diff --git a/.bumpversion.cfg b/.bumpversion.cfg index a3a4c1790f..f9c0a609b9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.9.4-dev +current_version = 0.10.0-dev commit = False tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-(?P[a-z]+))? @@ -8,8 +8,8 @@ serialize = {major}.{minor}.{patch} [bumpversion:file:aviary/__init__.py] -search = __version__ = "{current_version}" -replace = __version__ = "{new_version}" +search = __version__ = '{current_version}' +replace = __version__ = '{new_version}' [bumpversion:file:.github/ISSUE_TEMPLATE/bug_report.yml] search = placeholder: "{current_version}" diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index cd237761ce..f85184911b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,5 +1,5 @@ name: Bug Report -description: Submit a report if you believe you've found a bug in Aviary. +description: Submit a report only if you believe you've found a bug in Aviary. If you're not sure if your problem is a bug, especially for installation issues, try reaching out on the discussions page first. labels: ["bug"] body: - type: textarea @@ -13,7 +13,7 @@ body: id: example attributes: label: Example - description: Please provide an example of the code that triggers the unexpected behavior. If possible, we would appreciate a minimal test case that reproduces the issue. Alternatively, link to a file in another repository where the issue is demonstrated. + description: Please provide an example of the code that triggers the unexpected behavior. If possible, create a complete, minimal test case that reproduces the issue. Alternatively, link to a file in another repository where the issue is demonstrated. validations: required: true - type: input @@ -21,7 +21,7 @@ body: attributes: label: Aviary Version description: What version of Aviary is being used. - placeholder: "0.9.4-dev" + placeholder: "0.10.0-dev" validations: required: true - type: textarea diff --git a/.github/actions/prepare_environment/action.yml b/.github/actions/prepare_environment/action.yml index d071583892..dc449fe5c3 100644 --- a/.github/actions/prepare_environment/action.yml +++ b/.github/actions/prepare_environment/action.yml @@ -58,7 +58,7 @@ runs: echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts - name: Setup miniconda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true python-version: ${{ inputs.PY }} @@ -110,6 +110,9 @@ runs: pip install git+https://github.com/OpenMDAO/build_pyoptsparse build_pyoptsparse -v $BRANCH $SNOPT + echo "The build script has been grabbing an older version of IPOPT with some problems." + conda install ipopt=3.14 + - name: Install OpenMDAO if: inputs.OPENMDAO shell: bash -l {0} @@ -156,10 +159,11 @@ runs: run: | conda info conda list - conda env export --file ${{ inputs.NAME }}_environment.yml + conda env export --file environment.yml + mv environment.yml ${{ inputs.NAME }}_environment.yml - name: 'Upload environment artifact' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ inputs.NAME }}_environment path: ${{ inputs.NAME }}_environment.yml diff --git a/.github/install_env_from_github.sh b/.github/install_env_from_github.sh index a87cd103f3..e116432972 100755 --- a/.github/install_env_from_github.sh +++ b/.github/install_env_from_github.sh @@ -49,7 +49,7 @@ fi # pyoptsparse_line=$(grep ' pyoptsparse' $input_yaml | sed 's/^ //') # Remove specified packages and write to an intermediate file -grep -v -e 'aviary' -e 'om-aviary' -e 'build-pyoptsparse' -e 'pyoptsparse' -e 'networkx' -e ' - pip:' $input_yaml > $intermediate_yaml +grep -v -e 'aviary' -e 'build-pyoptsparse' -e 'pyoptsparse' -e 'networkx' -e ' - pip:' $input_yaml > $intermediate_yaml # Check for 'dev' versions of OpenMDAO and Dymos if grep -q -e 'openmdao.*dev' $intermediate_yaml; then @@ -119,4 +119,4 @@ rm -f $requirements_txt echo "---------------" echo "Reminder: You need to install Aviary manually using the relevant versions based on what you are trying to debug." echo "Please also install pyOptSparse with SNOPT manually if you need them to debug your problem." -echo "Activate the new environment using: conda activate $env_name" \ No newline at end of file +echo "Activate the new environment using: conda activate $env_name" diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml new file mode 100644 index 0000000000..8a7fb18bf0 --- /dev/null +++ b/.github/workflows/publish-image.yml @@ -0,0 +1,77 @@ +name: Publish Images + +on: + release: + types: [published] + + # Run the workflow manually from the Actions tab + workflow_dispatch: + +jobs: + + build_image: + + strategy: + + fail-fast: false + + matrix: + include: + - NAME: ubuntu + OS: ubuntu-24.04 + FILE: Dockerfile + IMAGE_NAME: ${{ github.repository }} + REGISTRY: ghcr.io + + - NAME: ubuntu-arm + OS: ubuntu-24.04-arm + FILE: Dockerfile.arm + IMAGE_NAME: ${{ github.repository }}-arm + REGISTRY: ghcr.io + + runs-on: ${{ matrix.OS }} + + permissions: + contents: read + packages: write + + defaults: + run: + shell: bash -l {0} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get tags + run: | + git fetch --unshallow --tags + git describe --tags + git describe --tags > tag.txt + echo "TAG=$(cat tag.txt)" >> $GITHUB_ENV + + # Login to container registry + - name: Log into registry ${{ matrix.REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ matrix.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ matrix.REGISTRY }}/${{ matrix.IMAGE_NAME }} + tags: | + type=raw,value=${{ env.TAG }} + + # Build and push image with Buildx + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + push: true + file: ${{ matrix.FILE }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/release_workflow.yml b/.github/workflows/release_workflow.yml new file mode 100644 index 0000000000..626460b6a9 --- /dev/null +++ b/.github/workflows/release_workflow.yml @@ -0,0 +1,56 @@ +# Publish release to PyPi + +name: Aviary Release + +on: + # Trigger on release, to publish release packages to PyPI + release: + types: [published] + + # Run the workflow manually + # This might be useful if the automated publish fails for some reason (use with CARE!!) + workflow_dispatch: + +jobs: + pypi-publish: + name: Upload release to PyPI + runs-on: ubuntu-latest + + environment: release + + permissions: + id-token: write + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + with: + python-version: "3.x" + + - name: deps + run: python -m pip install -U hatch + + - name: build + run: hatch build + + - name: Publish package distributions to PyPI (v1.12.4) + uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc + + test-pypi-release: + name: Test Aviary PyPI Release + needs: [pypi-publish] + runs-on: ubuntu-latest + + steps: + - uses: benc-uk/workflow-dispatch@v1 + with: + workflow: Test "no dev" install + repo: ${{ github.repository_owner }}/Aviary + inputs: > + { + "run_name": "Test PyPI install", + "use_pypi": true + } + token: ${{ secrets.ACCESS_TOKEN }} + if: github.event_name == 'release' diff --git a/.github/workflows/test_benchmarks.yml b/.github/workflows/test_benchmarks.yml index ef06bf6a61..5b18b2c2c4 100644 --- a/.github/workflows/test_benchmarks.yml +++ b/.github/workflows/test_benchmarks.yml @@ -18,7 +18,7 @@ on: jobs: latest_benchmarks: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 90 steps: @@ -38,8 +38,7 @@ jobs: SCIPY: 1 PYOPTSPARSE: 'v2.9.1' SNOPT: '7.7' - #OPENMDAO: 'latest' - OPENMDAO: '3.34.2' + OPENMDAO: 'latest' DYMOS: 'latest' SSH_PRIVATE_KEY: ${{secrets.SSH_PRIVATE_KEY}} SSH_KNOWN_HOSTS: ${{secrets.SSH_KNOWN_HOSTS}} diff --git a/.github/workflows/test_docs.yml b/.github/workflows/test_docs.yml index adb4cd351d..1915e397e3 100644 --- a/.github/workflows/test_docs.yml +++ b/.github/workflows/test_docs.yml @@ -18,7 +18,7 @@ on: jobs: latest_docs: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 90 steps: @@ -38,8 +38,7 @@ jobs: SCIPY: 1 PYOPTSPARSE: 'v2.9.1' SNOPT: '7.7' - #OPENMDAO: 'latest' - OPENMDAO: '3.34.2' + OPENMDAO: 'latest' DYMOS: 'latest' SSH_PRIVATE_KEY: ${{secrets.SSH_PRIVATE_KEY}} SSH_KNOWN_HOSTS: ${{secrets.SSH_KNOWN_HOSTS}} @@ -57,7 +56,7 @@ jobs: id: build_docs shell: bash -l {0} run: | - pip install -U jupyter-book + pip install -U "jupyter-book<2" cd aviary/docs echo "=============================================================" echo "Build the docs" diff --git a/.github/workflows/test_workflow.yml b/.github/workflows/test_workflow.yml index 36242e6364..40af27b036 100644 --- a/.github/workflows/test_workflow.yml +++ b/.github/workflows/test_workflow.yml @@ -18,7 +18,7 @@ jobs: pre_commit: # run pre-commit checks - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -28,30 +28,30 @@ jobs: - uses: pre-commit/action@v3.0.1 test_ubuntu: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - # oldest versions of openmdao/dymos + # oldest supported versions of openmdao/dymos + # Note: bugfixes sometimes require incrementing the minimal version of openmdao or dymos. - NAME: oldest PY: '3.9' NUMPY: '1.20' SCIPY: '1.6' PYOPTSPARSE: 'v2.9.1' SNOPT: '7.7' - OPENMDAO: '3.33.0' - DYMOS: '1.8.0' + OPENMDAO: '3.37.0' + DYMOS: '1.13.1' # latest versions of openmdao/dymos - NAME: latest - PY: '3.10' + PY: '3.12' NUMPY: 1 SCIPY: 1 - PYOPTSPARSE: 'v2.9.1' + PYOPTSPARSE: 'v2.12.0' SNOPT: '7.7' - #OPENMDAO: 'latest' - OPENMDAO: '3.34.2' + OPENMDAO: 'latest' DYMOS: 'latest' steps: diff --git a/.github/workflows/test_workflow_dev_deps.yml b/.github/workflows/test_workflow_dev_deps.yml index a3fd589448..fed5ad9127 100644 --- a/.github/workflows/test_workflow_dev_deps.yml +++ b/.github/workflows/test_workflow_dev_deps.yml @@ -14,7 +14,7 @@ on: jobs: test_ubuntu: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: @@ -27,8 +27,7 @@ jobs: SCIPY: 1 PYOPTSPARSE: 'latest' SNOPT: '7.7' - #OPENMDAO: 'dev' - OPENMDAO: '3.34.2' + OPENMDAO: 'dev' DYMOS: 'dev' steps: diff --git a/.github/workflows/test_workflow_no_dev_install.yml b/.github/workflows/test_workflow_no_dev_install.yml index b4c9d1672f..cbd08a87cf 100644 --- a/.github/workflows/test_workflow_no_dev_install.yml +++ b/.github/workflows/test_workflow_no_dev_install.yml @@ -14,10 +14,25 @@ on: # Allow running the workflow manually from the Actions tab workflow_dispatch: + inputs: + run_name: + type: string + description: 'Name of workflow run as it will appear under Actions tab:' + required: false + default: "" + + use_pypi: + type: boolean + description: 'Run tests against the published PyPI version of Aviary' + required: false + default: false + +run-name: ${{ inputs.run_name }} + jobs: test_ubuntu_no_dev_install: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 90 @@ -26,8 +41,9 @@ jobs: matrix: include: # latest versions of openmdao/dymos + # DYMOS is currently broken with py 3.14.1 - NAME: latest - PY: 3 + PY: '3.14.0' steps: - name: Display run details @@ -52,7 +68,7 @@ jobs: echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts - name: Setup miniconda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true python-version: ${{ matrix.PY }} @@ -70,19 +86,26 @@ jobs: echo "" echo "Temporarily install specific versions for now." pip install "numpy<2" - pip install "openmdao==3.34.2" pip install packaging - pip install .[all] + if [[ "${{ inputs.use_pypi }}" == "true" ]]; then + echo "-----------------------------------------------------------" + echo "Installing from PyPI" + echo "-----------------------------------------------------------" + python -m pip install aviary[all] + else + pip install .[all] + fi - name: Display conda environment info shell: bash -l {0} run: | conda info conda list - conda env export --file ${{ matrix.NAME }}_environment.yml + conda env export --file environment.yml + mv environment.yml ${{ inputs.NAME }}_environment.yml - name: 'Upload environment artifact' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.NAME }}_environment path: ${{ matrix.NAME }}_environment.yml diff --git a/.gitignore b/.gitignore index 8243711447..cdba40a216 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ target/ # Jupyter Notebook .ipynb_checkpoints +.db-journal # IPython profile_default/ @@ -131,6 +132,8 @@ dmypy.json # Test and spec generated reports/ +aviary/reports/ +*.openmdao_out *.out *.png *.sql @@ -152,5 +155,9 @@ coloring_files/ # OpenMDAO N2 diagrams n2.html +# Input and output lists +input_list.txt +output_list.txt + # Windows downloads *:Zone.Identifier diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f905f3e77..94441427a6 100755 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,10 @@ repos: -- repo: https://github.com/hhatto/autopep8 - rev: 'v2.0.4' - hooks: - - id: autopep8 \ No newline at end of file + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.11.6 + hooks: + # run the linter + # - id: ruff + # args: [ --fix ] + # run the formatter + - id: ruff-format \ No newline at end of file diff --git a/CITATION.cff b/CITATION.cff index c44eee143e..a7f0448453 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -27,4 +27,4 @@ identifiers: repository-code: 'https://github.com/OpenMDAO/Aviary' repository: 'https://github.com/OpenMDAO/Aviary_Community' license: Apache-2.0 -version: 0.9.3 +version: 0.9.10 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..f88e6b4365 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,123 @@ +# Define image with OpenMDAO/Dymos/Aviary and OpenVSP support + +FROM ubuntu:24.04 + +SHELL ["/bin/bash", "-c"] + +ARG DEBIAN_FRONTEND=noninteractive + +# Install updates +RUN apt-get update -y && apt-get install \ + python3-dev python3-sphinx vim nano bash-completion unzip wget file desktop-file-utils git sudo make cmake=3.28.3-1build7 swig g++ gfortran doxygen graphviz texlive-latex-base \ + libblas-dev liblapack-dev libxml2-dev libfltk1.3-dev libcpptest-dev libjpeg-dev libglm-dev libeigen3-dev libcminpack-dev libglew-dev -y + +RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb ;\ + apt-get install -y ./google-chrome-stable_current_amd64.deb + +# Create user +ENV USER=omdao +RUN adduser --shell /bin/bash --disabled-password ${USER} +RUN adduser ${USER} sudo +RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +USER ${USER} +WORKDIR /home/${USER} + +# Install Miniforge +RUN wget -q -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" ;\ + bash Miniforge3.sh -b ;\ + rm Miniforge3.sh ;\ + export PATH=$HOME/miniforge3/bin:$PATH ;\ + conda init bash + +# Create conda environment +RUN source $HOME/miniforge3/etc/profile.d/conda.sh ;\ + conda create -n mdaowork python=3.11 numpy scipy cython swig -y + +# Modify .bashrc +RUN echo "## Always activate mdaowork environment on startup ##" >> ~/.bashrc ;\ + echo "conda activate mdaowork" >> ~/.bashrc ;\ + echo "" >> ~/.bashrc ;\ + echo "## OpenMPI settings" >> ~/.bashrc ;\ + echo "export PRTE_MCA_rmaps_default_mapping_policy=:oversubscribe" >> ~/.bashrc ;\ + echo "export OMPI_MCA_rmaps_base_oversubscribe=1" >> ~/.bashrc ;\ + echo "export OMPI_MCA_btl=^openib" >> ~/.bashrc ;\ + echo "" >> ~/.bashrc ;\ + echo "## Required for some newer MPI / libfabric instances" >> ~/.bashrc ;\ + echo "export RDMAV_FORK_SAFE=true" >> ~/.bashrc ;\ + echo "" >> ~/.bashrc + +# Build and Install OpenVSP (based on script from Irian Ordaz @ LARC) +RUN source $HOME/miniforge3/etc/profile.d/conda.sh ;\ + conda activate mdaowork ;\ + mkdir OpenVSP && cd OpenVSP ;\ + git clone https://github.com/OpenVSP/OpenVSP.git repo ;\ + cd repo ;\ + git checkout tags/OpenVSP_3.41.1 -b OpenVSP_3.41.1 ;\ + cd .. ;\ + mkdir -p build/Libraries build/vsp ;\ + cd build/Libraries ;\ + cmake -DCMAKE_BUILD_TYPE=Release -DVSP_NO_GRAPHICS=true ../../repo/Libraries ;\ + make ;\ + cd ../vsp ;\ + cmake -DCMAKE_BUILD_TYPE=Release -DVSP_NO_GRAPHICS=true \ + -DPYTHON_LIBRARY=$HOME/miniforge3/envs/mdaowork/lib/libpython3.so \ + -DPYTHON_INCLUDE_DIR=$HOME/miniforge3/envs/mdaowork/include/python3.11 \ + -DVSP_LIBRARY_PATH=$HOME/OpenVSP/build/Libraries \ + ../../repo/src ;\ + make ;\ + cd vsp ;\ + make;\ + sudo make install + +# Install OpenMDAO/Dymos/Aviary into conda environment +RUN source $HOME/miniforge3/etc/profile.d/conda.sh ;\ + conda activate mdaowork ;\ + # + # Install OpenMDAO/Dymos/Aviary dependencies and OpenVSP Python API + # + conda install matplotlib graphviz -q -y ;\ + conda install mpi4py openmpi petsc4py=3.20 pyoptsparse -q -y ;\ + python -m pip install pyparsing psutil objgraph plotly pyxdsm pydot ;\ + # + # Install build_pyoptsparse + # (this will allow the user additional options for installing pyoptsparse, beyond the conda install above) + # + python -m pip install git+https://github.com/openmdao/build_pyoptsparse ;\ + # build_pyoptsparse -v ;\ + # + # Install OpenMDAO + # + git clone https://github.com/OpenMDAO/OpenMDAO.git ;\ + python -m pip install -e 'OpenMDAO[all]' ;\ + # + # Install Dymos + # + git clone https://github.com/OpenMDAO/dymos.git ;\ + python -m pip install -e 'dymos[all]' ;\ + # + # Install Aviary + # + git clone https://github.com/OpenMDAO/Aviary.git ;\ + python -m pip install -e 'Aviary[all]' ;\ + # + # Install MPhys + # + git clone https://github.com/OpenMDAO/MPhys.git ;\ + python -m pip install -e 'MPhys[all]' ;\ + # + # Install OpenAeroStruct + # + git clone https://github.com/mdolab/OpenAeroStruct.git ;\ + python -m pip install -e 'OpenAeroStruct' ;\ + # + # Install OpenVSP Python support + # + conda install wxPython ;\ + cd $HOME/OpenVSP/build/vsp/python_pseudo ;\ + pip install -r requirements-dev.txt + +# Set up a work directory that can be shared with the host operating system +WORKDIR /home/${USER}/work + +ENTRYPOINT ["tail", "-f", "/dev/null"] diff --git a/Dockerfile.arm b/Dockerfile.arm new file mode 100644 index 0000000000..0d6a7a0799 --- /dev/null +++ b/Dockerfile.arm @@ -0,0 +1,164 @@ +# This Docker File is for use by developers of OpenMDAO, Dymos, and Aviary + +FROM arm64v8/ubuntu:noble + +SHELL ["/bin/bash", "-c"] + +ARG DEBIAN_FRONTEND=noninteractive + +# Install updates +RUN apt-get update -y && apt-get install sudo wget git g++ gfortran make cmake=3.28.3-1build7 libblas-dev liblapack-dev libxml2-dev \ + python3-dev python3-sphinx vim nano bash-completion unzip file desktop-file-utils swig doxygen graphviz \ + # texlive-latex-base \ + libfltk1.3-dev libcpptest-dev libjpeg-dev libglm-dev libeigen3-dev libcminpack-dev libglew-dev libgtk-3-dev -y + +# install a browser +RUN apt-get update -y && apt-get install firefox --fix-missing -y + +# Create user +ENV USER=omdao +RUN adduser --shell /bin/bash --disabled-password ${USER} +RUN adduser ${USER} sudo +RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers +RUN chmod u+s /usr/bin/sudo + +USER ${USER} +WORKDIR /home/${USER} + +# Install Miniforge +RUN wget -q -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" ;\ + bash Miniforge3.sh -b ;\ + rm Miniforge3.sh ;\ + export PATH=$HOME/miniforge3/bin:$PATH ;\ + conda init bash + +# Create conda environment +RUN source $HOME/miniforge3/etc/profile.d/conda.sh ;\ + conda create -n mdaowork python=3.11 numpy scipy cython swig -y + +# Modify .bashrc +RUN echo "## Always activate mdaowork environment on startup ##" >> ~/.bashrc ;\ + echo "conda activate mdaowork" >> ~/.bashrc ;\ + echo "export PYTHONPATH=${PYTHONPATH}:$HOME/vtk/build/lib/python3.11/site-packages:$HOME/OpenVSP/build/vsp/python_pseudo/PyVSP" >> ~/.bashrc ;\ + echo "" >> ~/.bashrc ;\ + echo "## OpenMPI settings" >> ~/.bashrc ;\ + echo "export PRTE_MCA_rmaps_default_mapping_policy=:oversubscribe" >> ~/.bashrc ;\ + echo "export OMPI_MCA_rmaps_base_oversubscribe=1" >> ~/.bashrc ;\ + echo "export OMPI_MCA_btl=^openib" >> ~/.bashrc ;\ + echo "" >> ~/.bashrc ;\ + echo "## Required for some newer MPI / libfabric instances" >> ~/.bashrc ;\ + echo "export RDMAV_FORK_SAFE=true" >> ~/.bashrc ;\ + echo "" >> ~/.bashrc + +# Build and Install VTK, which is needed by OpenVSP +RUN source $HOME/miniforge3/etc/profile.d/conda.sh ;\ + conda activate mdaowork ;\ + wget -q https://www.vtk.org/files/release/9.4/VTK-9.4.1.tar.gz ;\ + tar -xzpf VTK-9.4.1.tar.gz ;\ + rm VTK-9.4.1.tar.gz ;\ + mkdir vtk ;\ + mv VTK-9.4.1 vtk/source ;\ + cd vtk ;\ + mkdir build ;\ + cd build ;\ + ls -l ../source ;\ + cmake ../source -DVTK_WRAP_PYTHON=ON;\ + make ;\ + sudo make install + +# Build and Install OpenVSP (based on script from Irian Ordaz @ LARC) +RUN source $HOME/miniforge3/etc/profile.d/conda.sh ;\ + conda activate mdaowork ;\ + mkdir OpenVSP && cd OpenVSP ;\ + git clone https://github.com/OpenVSP/OpenVSP.git repo ;\ + cd repo ;\ + git checkout tags/OpenVSP_3.41.1 -b OpenVSP_3.41.1 ;\ + cd .. ;\ + mkdir -p build/Libraries build/vsp ;\ + cd build/Libraries ;\ + cmake -DCMAKE_BUILD_TYPE=Release -DVSP_NO_GRAPHICS=true \ + -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -fPIC" \ + -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} -fPIC" \ + ../../repo/Libraries ;\ + make ;\ + cd ../vsp ;\ + cmake -DCMAKE_BUILD_TYPE=Release -DVSP_NO_GRAPHICS=true \ + -DPYTHON_LIBRARY=$HOME/miniforge3/envs/mdaowork/lib/libpython3.so \ + -DPYTHON_INCLUDE_DIR=$HOME/miniforge3/envs/mdaowork/include/python3.11 \ + -DVSP_LIBRARY_PATH=$HOME/OpenVSP/build/Libraries \ + -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -fPIC" \ + -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} -fPIC" \ + ../../repo/src ;\ + make ;\ + cd vsp ;\ + make ;\ + sudo make install + +# Install OpenMDAO/Dymos/Aviary into conda environment +RUN source $HOME/miniforge3/etc/profile.d/conda.sh ;\ + conda activate mdaowork ;\ + # + # Install OpenMDAO/Dymos/Aviary dependencies and OpenVSP Python API + # + conda install matplotlib graphviz -q -y ;\ + conda install mpi4py openmpi petsc4py=3.20 pyoptsparse -q -y ;\ + python -m pip install pyparsing psutil objgraph plotly pyxdsm pydot ;\ + # + # Install build_pyoptsparse + # (this will allow the user additional options for installing pyoptsparse, beyond the conda install above) + # + python -m pip install git+https://github.com/openmdao/build_pyoptsparse ;\ + # build_pyoptsparse -v ;\ + # + # Install OpenMDAO + # + git clone https://github.com/OpenMDAO/OpenMDAO.git ;\ + python -m pip install -e 'OpenMDAO[all]' ;\ + # + # Install Dymos + # + git clone https://github.com/OpenMDAO/dymos.git ;\ + python -m pip install -e 'dymos[all]' ;\ + # + # Install Aviary + # + git clone https://github.com/OpenMDAO/Aviary.git ;\ + python -m pip install -e 'Aviary[all]' ;\ + # + # Install MPhys + # + git clone https://github.com/OpenMDAO/MPhys.git ;\ + python -m pip install -e 'MPhys[all]' ;\ + # + # Install OpenAeroStruct + # + git clone https://github.com/mdolab/OpenAeroStruct.git ;\ + python -m pip install -e 'OpenAeroStruct' ;\ + # + # Install OpenVSP Python support + # + pip install wxPython ;\ + cd $HOME/OpenVSP/build/vsp/python_pseudo ;\ + pip install utilities/. ;\ + pip install degen_geom/. ;\ + pip install openvsp_config/. ;\ + pip install openvsp/. ;\ + pip install CHARM/. ;\ + pip install AvlPy/. ;\ + pip install pyPMARC/. ;\ + # pip doesn't recognize vtk in PYTHONPATH as satisfying the vtk dependency for PyVSP, + # so we'll just hack this into PYTHONPATH as well. + # pip install PyVSP/. + # + # fix for this warning: + # WARNING 7: VSPAERO Viewer Not Found. + # Expected here: /home/omdao/miniforge3/envs/mdaowork/lib/python3.11/site-packages/openvsp/vspviewer + VSPVIEWER_DIR=$CONDA_PREFIX/lib/python3.11/site-packages/openvsp/vspviewer ;\ + mkdir $VSPVIEWER_DIR ;\ + cp $CONDA_PREFIX/lib/python3.11/site-packages/openvsp/vspaero $VSPVIEWER_DIR ;\ + cp $CONDA_PREFIX/lib/python3.11/site-packages/openvsp/vsploads $VSPVIEWER_DIR + +# Set up a work directory that can be shared with the host operating system +WORKDIR /home/${USER}/work + +ENTRYPOINT ["tail", "-f", "/dev/null"] diff --git a/README.md b/README.md index f654a6157a..789186ae6d 100644 --- a/README.md +++ b/README.md @@ -3,24 +3,25 @@ [![All Contributors](https://img.shields.io/badge/all_contributors-17-orange.svg?style=flat-square)](#contributors-) -**Check out the Aviary [documentation](https://openmdao.github.io/Aviary/intro.html).** +**Check out the Aviary [documentation](https://openmdao.github.io/Aviary/intro.html)** **[NASA's Aviary Takes Flight](https://ntrs.nasa.gov/citations/20240009217) (Presented at EAA AirVenture 2024)** -**Get in touch with the Aviary team at agency-aviary@mail.nasa.gov** +**Get in touch with the Aviary team at agency-aviary@mail.nasa.gov or the GitHub [discussions page](https://github.com/OpenMDAO/Aviary/discussions)** ## Description -This repository is an [OpenMDAO](https://openmdao.org/)-based aircraft modeling tool that incorporates aircraft sizing and weight equations from its predecessors [GASP (General Aviation Synthesis Program)](https://ntrs.nasa.gov/api/citations/19810010563/downloads/19810010563.pdf) and [FLOPS (Flight Optimization System)](https://software.nasa.gov/software/LAR-18934-1). -It also incorporates aerodynamic calculations from GASP and FLOPS and has the capability to use an aerodynamics deck as well as an aircraft engine deck. +This repository is an [OpenMDAO](https://openmdao.org/)-based aircraft modeling tool that incorporates aircraft sizing equations from its predecessors [GASP (General Aviation Synthesis Program)](https://ntrs.nasa.gov/api/citations/19810010563/downloads/19810010563.pdf) and [FLOPS (Flight Optimization System)](https://software.nasa.gov/software/LAR-18934-1). There are two options for the mission analysis portion of this code, a 2 degrees-of-freedom (2DOF) approach, and a energy-height approach. The user can select which type of mission analysis to use, as well as whether to use the FLOPS-based code or the GASP-based code for the weight, sizing, and aerodynamic relations. +Aviary is currently in a beta state. The code is under active development, and frequent changes should be expected. + ## Installation The simplest installation method for users is to install via pip: - pip install om-aviary + pip install aviary Please see the [installation doc page](https://openmdao.github.io/Aviary/getting_started/installation.html) for more detailed instructions. The minimum supported Python version for Aviary is 3.9. diff --git a/aviary/__init__.py b/aviary/__init__.py index 7f33873b34..003f960d36 100644 --- a/aviary/__init__.py +++ b/aviary/__init__.py @@ -1 +1 @@ -__version__ = "0.9.4-dev" +__version__ = '0.10.0-dev' diff --git a/aviary/api.py b/aviary/api.py index c0b6b026a1..e7daa10032 100644 --- a/aviary/api.py +++ b/aviary/api.py @@ -1,12 +1,12 @@ -''' -This module is the API for Aviary aircraft analysis code +""" +This module is the API for Aviary aircraft analysis code. For users: All built-in Aviary functions, code, and objects should be imported from this file. For developers: All Aviary code which is intended to be user-facing should be imported to this file. -''' +""" # TODO: don't rename things here, do it in the entire codebase # TODO: when documenting methods and classes, make sure to include documentation (printing of docstrings) for everything that's imported in this API @@ -23,28 +23,64 @@ from aviary.variable_info.options import get_option_defaults, is_option from aviary.utils.develop_metadata import add_meta_data, update_meta_data from aviary.variable_info.variable_meta_data import CoreMetaData -from aviary.variable_info.functions import add_aviary_input, add_aviary_output, get_units, override_aviary_vars, setup_trajectory_params +from aviary.variable_info.functions import ( + add_aviary_input, + add_aviary_output, + get_units, + override_aviary_vars, + setup_model_options, + setup_trajectory_params, +) from aviary.utils.merge_hierarchies import merge_hierarchies from aviary.utils.merge_variable_metadata import merge_meta_data from aviary.utils.named_values import NamedValues, get_keys, get_items, get_values from aviary.utils.aviary_values import AviaryValues from aviary.utils.csv_data_file import read_data_file, write_data_file from aviary.utils.data_interpolator_builder import build_data_interpolator -from aviary.variable_info.enums import AlphaModes, AnalysisScheme, ProblemType, SpeedType, GASPEngineType, FlapType, EquationsOfMotion, LegacyCode, Verbosity -from aviary.interface.default_phase_info.two_dof import phase_info as default_2DOF_phase_info -from aviary.interface.default_phase_info.two_dof_fiti import phase_info as default_2DOF_fiti_phase_info -from aviary.interface.default_phase_info.two_dof_fiti_deprecated import create_2dof_based_ascent_phases, create_2dof_based_descent_phases -from aviary.interface.default_phase_info.height_energy import phase_info as default_height_energy_phase_info +from aviary.variable_info.enums import ( + AlphaModes, + EquationsOfMotion, + FlapType, + GASPEngineType, + LegacyCode, + ProblemType, + SpeedType, + Verbosity, +) +from aviary.models.missions.two_dof_default import phase_info as default_2DOF_phase_info +from aviary.models.missions.height_energy_default import ( + phase_info as default_height_energy_phase_info, +) from aviary.interface.methods_for_level1 import run_level_1 from aviary.interface.methods_for_level1 import run_aviary -from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.interface.utils.check_phase_info import check_phase_info -from aviary.utils.engine_deck_conversion import EngineDeckConverter -from aviary.utils.fortran_to_aviary import create_aviary_deck -from aviary.utils.functions import set_aviary_input_defaults, set_aviary_initial_values, get_path +from aviary.interface.methods_for_level2 import AviaryProblem, reload_aviary_problem +from aviary.utils.engine_deck_conversion import convert_engine_deck +from aviary.utils.fortran_to_aviary import fortran_to_aviary +from aviary.utils.functions import ( + get_path, + set_aviary_initial_values, + set_aviary_input_defaults, + top_dir, +) from aviary.utils.options import list_options -from aviary.constants import GRAV_METRIC_GASP, GRAV_ENGLISH_GASP, GRAV_METRIC_FLOPS, GRAV_ENGLISH_FLOPS, GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH, RHO_SEA_LEVEL_METRIC, MU_TAKEOFF, MU_LANDING, PSLS_PSF, TSLS_DEGR, RADIUS_EARTH_METRIC -from aviary.subsystems.test.subsystem_tester import TestSubsystemBuilderBase, skipIfMissingDependencies +from aviary.constants import ( + GRAV_ENGLISH_FLOPS, + GRAV_ENGLISH_GASP, + GRAV_ENGLISH_LBM, + GRAV_METRIC_FLOPS, + GRAV_METRIC_GASP, + MU_LANDING, + MU_TAKEOFF, + PSLS_PSF, + RADIUS_EARTH_METRIC, + RHO_SEA_LEVEL_ENGLISH, + RHO_SEA_LEVEL_METRIC, + TSLS_DEGR, +) +from aviary.subsystems.test.subsystem_tester import ( + TestSubsystemBuilderBase, + skipIfMissingDependencies, +) from aviary.subsystems.propulsion.utils import build_engine_deck ################### @@ -52,20 +88,30 @@ ################### # Miscellaneous -from aviary.interface.methods_for_level2 import PreMissionGroup, PostMissionGroup from aviary.subsystems.premission import CorePreMission from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.utils.preprocessors import preprocess_options, preprocess_propulsion +from aviary.utils.preprocessors import ( + preprocess_crewpayload, + preprocess_options, + preprocess_propulsion, +) from aviary.utils.process_input_decks import create_vehicle from aviary.utils.functions import create_opts2vals, add_opts2vals, Null -from aviary.utils.preprocessors import preprocess_crewpayload # ODEs # TODO: check and see if this works with both sides, or just GASP -from aviary.mission.gasp_based.ode.base_ode import BaseODE +from aviary.mission.base_ode import BaseODE +from aviary.mission.flops_based.ode.energy_ODE import EnergyODE from aviary.mission.flops_based.ode.landing_ode import LandingODE as DetailedLandingODE from aviary.mission.flops_based.ode.landing_ode import FlareODE as DetailedFlareODE from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE as DetailedTakeoffODE +from aviary.mission.flops_based.phases.simplified_takeoff import ( + TakeoffGroup as HeightEnergySimplifiedTakeoff, +) +from aviary.mission.flops_based.phases.simplified_landing import ( + LandingGroup as HeightEnergySimplifiedLanding, +) +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.mission.gasp_based.ode.accel_ode import AccelODE as TwoDOFAccelerationODE from aviary.mission.gasp_based.ode.ascent_ode import AscentODE as TwoDOFAscentODE from aviary.mission.gasp_based.ode.breguet_cruise_ode import BreguetCruiseODESolution @@ -76,71 +122,89 @@ from aviary.mission.gasp_based.ode.rotation_ode import RotationODE as TwoDOFRotationODE from aviary.mission.gasp_based.ode.landing_ode import LandingSegment as TwoDOFSimplifiedLanding from aviary.mission.gasp_based.ode.taxi_ode import TaxiSegment as AnalyticTaxi -from aviary.mission.flops_based.phases.simplified_takeoff import TakeoffGroup as HeightEnergySimplifiedTakeoff -from aviary.mission.flops_based.phases.simplified_landing import LandingGroup as HeightEnergySimplifiedLanding # Phase builders from aviary.mission.phase_builder_base import PhaseBuilderBase + # note that this is only for simplified right now -from aviary.mission.energy_phase import EnergyPhase as HeightEnergyPhaseBuilder -from aviary.mission.flops_based.phases.build_landing import Landing as HeightEnergyLandingPhaseBuilder +from aviary.mission.flops_based.phases.energy_phase import ( + EnergyPhase as HeightEnergyPhaseBuilder, +) +from aviary.mission.flops_based.phases.build_landing import ( + Landing as HeightEnergyLandingPhaseBuilder, +) + # note that this is only for simplified right now -from aviary.mission.flops_based.phases.build_takeoff import Takeoff as HeightEnergyTakeoffPhaseBuilder -from aviary.mission.flops_based.phases.detailed_landing_phases import LandingApproachToMicP3 as DetailedLandingApproachToMicP3PhaseBuilder -from aviary.mission.flops_based.phases.detailed_landing_phases import LandingMicP3ToObstacle as DetailedLandingMicP3ToObstaclePhaseBuilder -from aviary.mission.flops_based.phases.detailed_landing_phases import LandingObstacleToFlare as DetailedLandingObstacleToFlarePhaseBuilder -from aviary.mission.flops_based.phases.detailed_landing_phases import LandingFlareToTouchdown as DetailedLandingFlareToTouchdownPhaseBuilder -from aviary.mission.flops_based.phases.detailed_landing_phases import LandingTouchdownToNoseDown as DetailedLandingTouchdownToNoseDownPhaseBuilder -from aviary.mission.flops_based.phases.detailed_landing_phases import LandingNoseDownToStop as DetailedLandingNoseDownToStopPhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffBrakeReleaseToDecisionSpeed as DetailedTakeoffBrakeReleaseToDecisionSpeedPhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffDecisionSpeedToRotate as DetailedTakeoffDecisionSpeedToRotatePhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffDecisionSpeedBrakeDelay as DetailedTakeoffDecisionSpeedBrakeDelayPhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffRotateToLiftoff as DetailedTakeoffRotateToLiftoffPhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffLiftoffToObstacle as DetailedTakeoffLiftoffToObstaclePhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffObstacleToMicP2 as DetailedTakeoffObstacleToMicP2PhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffMicP2ToEngineCutback as DetailedTakeoffMicP2ToEngineCutbackPhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffEngineCutback as DetailedTakeoffEngineCutbackPhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffEngineCutbackToMicP1 as DetailedTakeoffEngineCutbackToMicP1PhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffMicP1ToClimb as DetailedTakeoffMicP1ToClimbPhaseBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffBrakeToAbort as DetailedTakeoffBrakeToAbortPhaseBuilder +from aviary.mission.flops_based.phases.build_takeoff import ( + Takeoff as HeightEnergyTakeoffPhaseBuilder, +) +from aviary.mission.flops_based.phases.detailed_landing_phases import ( + LandingApproachToMicP3 as DetailedLandingApproachToMicP3PhaseBuilder, + LandingMicP3ToObstacle as DetailedLandingMicP3ToObstaclePhaseBuilder, + LandingObstacleToFlare as DetailedLandingObstacleToFlarePhaseBuilder, + LandingFlareToTouchdown as DetailedLandingFlareToTouchdownPhaseBuilder, + LandingTouchdownToNoseDown as DetailedLandingTouchdownToNoseDownPhaseBuilder, + LandingNoseDownToStop as DetailedLandingNoseDownToStopPhaseBuilder, +) +from aviary.mission.flops_based.phases.detailed_takeoff_phases import ( + TakeoffBrakeReleaseToDecisionSpeed as DetailedTakeoffBrakeReleaseToDecisionSpeedPhaseBuilder, + TakeoffDecisionSpeedToRotate as DetailedTakeoffDecisionSpeedToRotatePhaseBuilder, + TakeoffDecisionSpeedBrakeDelay as DetailedTakeoffDecisionSpeedBrakeDelayPhaseBuilder, + TakeoffRotateToLiftoff as DetailedTakeoffRotateToLiftoffPhaseBuilder, + TakeoffLiftoffToObstacle as DetailedTakeoffLiftoffToObstaclePhaseBuilder, + TakeoffObstacleToMicP2 as DetailedTakeoffObstacleToMicP2PhaseBuilder, + TakeoffMicP2ToEngineCutback as DetailedTakeoffMicP2ToEngineCutbackPhaseBuilder, + TakeoffEngineCutback as DetailedTakeoffEngineCutbackPhaseBuilder, + TakeoffEngineCutbackToMicP1 as DetailedTakeoffEngineCutbackToMicP1PhaseBuilder, + TakeoffMicP1ToClimb as DetailedTakeoffMicP1ToClimbPhaseBuilder, + TakeoffBrakeToAbort as DetailedTakeoffBrakeToAbortPhaseBuilder, +) # Phase builders from aviary.mission.gasp_based.phases.accel_phase import AccelPhase as TwoDOFAccelerationPhase from aviary.mission.gasp_based.phases.ascent_phase import AscentPhase as TwoDOFAscentPhase from aviary.mission.gasp_based.phases.climb_phase import ClimbPhase as TwoDOFClimbPhase from aviary.mission.gasp_based.phases.descent_phase import DescentPhase as TwoDOFDescentPhase -from aviary.mission.gasp_based.phases.groundroll_phase import GroundrollPhase as TwoDOFGroundrollPhase +from aviary.mission.gasp_based.phases.groundroll_phase import ( + GroundrollPhase as TwoDOFGroundrollPhase, +) from aviary.mission.gasp_based.phases.rotation_phase import RotationPhase as TwoDOFRotationPhase - # Trajectory builders -from aviary.mission.flops_based.phases.detailed_landing_phases import LandingTrajectory as DetailedLandingTrajectoryBuilder -from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffTrajectory as DetailedTakeoffTrajectoryBuilder +from aviary.mission.flops_based.phases.detailed_landing_phases import ( + LandingTrajectory as DetailedLandingTrajectoryBuilder, +) +from aviary.mission.flops_based.phases.detailed_takeoff_phases import ( + TakeoffTrajectory as DetailedTakeoffTrajectoryBuilder, +) -# SimuPy -from aviary.mission.gasp_based.ode.time_integration_base_classes import SimuPyProblem -from aviary.mission.gasp_based.phases.time_integration_phases import SGMGroundroll, SGMRotation, SGMAscent, SGMAscentCombined, SGMAccel, SGMClimb, SGMCruise, SGMDescent -from aviary.mission.gasp_based.phases.time_integration_traj import TimeIntegrationTrajBase, FlexibleTraj +############## +# Subsystems # +############## # Aerodynamics -from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase -from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.subsystems.aerodynamics.aerodynamics_builder import ( + AerodynamicsBuilderBase, + CoreAerodynamicsBuilder, +) from aviary.subsystems.aerodynamics.flops_based.tabular_aero_group import TabularAeroGroup # Atmosphere from aviary.subsystems.atmosphere.atmosphere import Atmosphere # Geometry -from aviary.subsystems.geometry.geometry_builder import GeometryBuilderBase -from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder +from aviary.subsystems.geometry.geometry_builder import GeometryBuilderBase, CoreGeometryBuilder # Mass -from aviary.subsystems.mass.mass_builder import MassBuilderBase -from aviary.subsystems.mass.mass_builder import CoreMassBuilder +from aviary.subsystems.mass.mass_builder import MassBuilderBase, CoreMassBuilder # Propulsion from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.subsystems.propulsion.engine_model import EngineModel -from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase -from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder +from aviary.subsystems.propulsion.motor.motor_builder import MotorBuilder +from aviary.subsystems.propulsion.propulsion_builder import ( + PropulsionBuilderBase, + CorePropulsionBuilder, +) +from aviary.subsystems.propulsion.turboprop_model import TurbopropModel diff --git a/aviary/examples/external_subsystems/OAS_weight/__init__.py b/aviary/core/__init__.py similarity index 100% rename from aviary/examples/external_subsystems/OAS_weight/__init__.py rename to aviary/core/__init__.py diff --git a/aviary/core/aviary_group.py b/aviary/core/aviary_group.py new file mode 100644 index 0000000000..ddee28eb1b --- /dev/null +++ b/aviary/core/aviary_group.py @@ -0,0 +1,1568 @@ +import inspect +import warnings +from importlib.util import spec_from_file_location, module_from_spec +from pathlib import Path +import sys + +import dymos as dm +import openmdao.api as om +from dymos.utils.misc import _unspecified +from openmdao.utils.mpi import MPI + +from aviary.core.post_mission_group import PostMissionGroup +from aviary.core.pre_mission_group import PreMissionGroup +from aviary.interface.utils import set_warning_format +from aviary.mission.height_energy_problem_configurator import HeightEnergyProblemConfigurator +from aviary.mission.solved_two_dof_problem_configurator import SolvedTwoDOFProblemConfigurator +from aviary.mission.two_dof_problem_configurator import TwoDOFProblemConfigurator +from aviary.mission.utils import get_phase_mission_bus_lengths, process_guess_var +from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder +from aviary.subsystems.mass.mass_builder import CoreMassBuilder +from aviary.subsystems.performance.performance_builder import CorePerformanceBuilder +from aviary.subsystems.premission import CorePreMission +from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder +from aviary.utils.functions import get_path +from aviary.utils.preprocessors import preprocess_options +from aviary.utils.process_input_decks import create_vehicle, update_GASP_options +from aviary.utils.utils import wrapped_convert_units +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode, ProblemType, Verbosity +from aviary.variable_info.functions import setup_trajectory_params +from aviary.variable_info.variables import Aircraft, Mission, Settings + +TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM +HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY +SOLVED_2DOF = EquationsOfMotion.SOLVED_2DOF +CUSTOM = EquationsOfMotion.CUSTOM + +FLOPS = LegacyCode.FLOPS +GASP = LegacyCode.GASP + + +class AviaryGroup(om.Group): + """ + A standard OpenMDAO group where all elements of a given aviary aircraft design and mission are + defined. + + This includes pre_mission, mission, and post_mission analysis. This group also contains methods + for loading data from .csv and phase_info files, setting initial values on the group, and + connecting all the phases inside the mission analysis to each other. + + Instantiating multiple AviaryGroups allows for analysis and optimization of multiple aircraft or + one aircraft in multiple missions simultaneously. + """ + + def __init__(self, verbosity=None, **kwargs): + super().__init__(**kwargs) + + self.pre_mission = PreMissionGroup() + self.post_mission = PostMissionGroup() + self.verbosity = verbosity + self.regular_phases = [] + self.reserve_phases = [] + + self.aviary_inputs = None + self.meta_data = None + self.mission_info = None + + def configure(self): + """Configure the Aviary group.""" + aviary_options = self.aviary_inputs + aviary_metadata = self.meta_data + + # Find promoted name of every input in the model. + all_prom_inputs = [] + + # We can call list_inputs on the subsystems. + for system in self.system_iter(recurse=False): + var_abs = system.list_inputs(out_stream=None, val=False) + var_prom = [v['prom_name'] for k, v in var_abs] + all_prom_inputs.extend(var_prom) + + # Calls to promotes aren't handled until this group resolves. + # Here, we address anything promoted with an alias in AviaryProblem. + input_meta = system._var_promotes['input'] + var_prom = [v[0][1] for v in input_meta if isinstance(v[0], tuple)] + all_prom_inputs.extend(var_prom) + var_prom = [v[0] for v in input_meta if not isinstance(v[0], tuple)] + all_prom_inputs.extend(var_prom) + + if MPI and self.comm.size > 1: + # Under MPI, promotion info only lives on rank 0, so broadcast. + all_prom_inputs = self.comm.bcast(all_prom_inputs, root=0) + + for key in aviary_metadata: + if ':' not in key or key.startswith('dynamic:'): + continue + + if aviary_metadata[key]['option']: + continue + + # Skip anything that is not presently an input. + if key not in all_prom_inputs: + continue + + if key in aviary_options: + val, units = aviary_options.get_item(key) + else: + val = aviary_metadata[key]['default_value'] + units = aviary_metadata[key]['units'] + + if val is None: + # optional, but no default value + continue + + self.set_input_defaults(key, val=val, units=units) + + # try to get all the possible EOMs from the Enums rather than specifically calling the names here + # This will require some modifications to the enums + mission_method = aviary_options.get_val(Settings.EQUATIONS_OF_MOTION) + + # Temporarily add extra stuff here, probably patched soon + if mission_method is HEIGHT_ENERGY: + # Set a more appropriate solver for dymos when the phases are linked. + if MPI and isinstance(self.traj.phases.linear_solver, om.PETScKrylov): + # When any phase is connected with input_initial = True, dymos puts + # a jacobi solver in the phases group. This is necessary in case + # the phases are cyclic. However, this causes some problems + # with the newton solvers in Aviary, exacerbating issues with + # solver tolerances at multiple levels. Since Aviary's phases + # are basically in series, the jacobi solver is a much better + # choice and should be able to handle it in a couple of + # iterations. + self.traj.phases.linear_solver = om.LinearBlockJac(maxiter=5) + + # Due to recent changes in dymos, there is now a solver in any phase + # that has connected initial states. It is not clear that this solver + # is necessary except in certain corner cases that do not apply to the + # Aviary trajectory. In our case, this solver merely addresses a lag + # in the state input component. Since this solver can cause some + # numerical problems, and can slow things down, we need to move it down + # into the state interp component. + # TODO: Future updates to dymos may make this unnecessary. + for phase in self.traj.phases.system_iter(recurse=False): + # Don't move the solvers if we are using solve segments. + if self.mission_info[phase.name]['user_options'].get('distance_solve_segments'): + continue + + phase.nonlinear_solver = om.NonlinearRunOnce() + phase.linear_solver = om.LinearRunOnce() + if isinstance(phase.indep_states, om.ImplicitComponent): + phase.indep_states.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) + phase.indep_states.linear_solver = om.DirectSolver(rhs_checking=True) + + def load_inputs( + self, + aircraft_data, + phase_info=None, + engine_builders=None, + problem_configurator=None, + verbosity=None, + ): + """ + This method loads the aviary_values inputs and options that the + user specifies. They could specify files to load and values to + replace here as well. + Phase info is also loaded if provided by the user. If phase_info is None, + the appropriate default phase_info based on mission analysis method is used. + + This method is not strictly necessary; a user could also supply + an AviaryValues object and/or phase_info dict of their own. + """ + ## LOAD INPUT FILE ### + # Create AviaryValues object from file (or process existing AviaryValues object + # with default values from metadata) and generate initial guesses + aviary_inputs, self.initialization_guesses = create_vehicle( + aircraft_data, meta_data=self.meta_data, verbosity=verbosity + ) + + # Update default verbosity now that we have read the input data, if a global verbosity + # override was not requested + if self.verbosity is None: + self.verbosity = aviary_inputs.get_val(Settings.VERBOSITY) + # set default warning format for the rest of the problem + set_warning_format(self.verbosity) + + # If user did not ask for verbosity override for this method either, use the problem's + # default verbosity for the rest of the method + if verbosity is None: + verbosity = self.verbosity + # Now that the input file has been read, we have the desired verbosity for this + # run stored in aviary_inputs. Save this to self. + self.aviary_inputs = aviary_inputs + + # pull which methods will be used for subsystems and mission + self.mission_method = mission_method = aviary_inputs.get_val(Settings.EQUATIONS_OF_MOTION) + self.mass_method = mass_method = aviary_inputs.get_val(Settings.MASS_METHOD) + self.aero_method = aero_method = aviary_inputs.get_val(Settings.AERODYNAMICS_METHOD) + + # Create engine_builder + self.engine_builders = engine_builders + + # Determine which problem configurator to use based on mission_method + if mission_method is HEIGHT_ENERGY: + self.configurator = HeightEnergyProblemConfigurator() + elif mission_method is TWO_DEGREES_OF_FREEDOM: + self.configurator = TwoDOFProblemConfigurator() + elif mission_method is SOLVED_2DOF: + self.configurator = SolvedTwoDOFProblemConfigurator() + elif mission_method is CUSTOM: + if problem_configurator: + self.configurator = problem_configurator() + # TODO: make draft / example custom builder + else: + raise ValueError( + 'When using "settings:equations_of_motion,custom", a ' + 'problem_configurator must be specified in load_inputs().' + ) + else: + raise ValueError( + 'settings:equations_of_motion must be one of: height_energy, 2DOF, ' + 'solved_2DOF, or custom' + ) + + # TODO this should be a preprocessor step if it is required here + if mass_method is GASP or aero_method is GASP: + aviary_inputs = update_GASP_options(aviary_inputs) + + ## LOAD PHASE_INFO ### + # if phase info is a file, load it + if isinstance(phase_info, str) or isinstance(phase_info, Path): + phase_info_path = get_path(phase_info) + spec = spec_from_file_location('phase_info_file', str(phase_info_path)) + phase_info_file = module_from_spec(spec) + sys.modules['phase_info_file'] = phase_info_file + spec.loader.exec_module(phase_info_file) + + phase_info = getattr(phase_info_file, 'phase_info') + + if phase_info is None: + phase_info = self.configurator.get_default_phase_info(self) + if verbosity is not None and verbosity >= Verbosity.BRIEF: + print( + f'Loaded default phase_info for {self.mission_method.value.lower()} equations ' + 'of motion.' + ) + + # create a new dictionary that only contains the phases from phase_info + self.mission_info = {} + + for phase_name in phase_info: + if 'external_subsystems' not in phase_info[phase_name]: + phase_info[phase_name]['external_subsystems'] = [] + + if phase_name not in ['pre_mission', 'post_mission']: + self.mission_info[phase_name] = phase_info[phase_name] + + # pre_mission and post_mission are stored in their own dictionaries. + if 'pre_mission' in phase_info: + self.pre_mission_info = phase_info['pre_mission'] + else: + self.pre_mission_info = {} + + if 'post_mission' in phase_info: + self.post_mission_info = phase_info['post_mission'] + else: + self.post_mission_info = {} + + self.configurator.initial_guesses(self) + # This function sets all the following defaults if they were not already set + # self.engine_builders, self.pre_mission_info, self_post_mission_info + # self.require_range_residual, self.target_range + # Other specific self.*** are defined in here as well that are specific to + # each builder + + return self.aviary_inputs, self.verbosity + + def check_and_preprocess_inputs(self, verbosity=None): + """ + This method checks the user-supplied input values for any potential problems + and preprocesses the inputs to prepare them for use in the Aviary problem. + """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + aviary_inputs = self.aviary_inputs + # Target_distance verification for all phases + # Checks to make sure target_distance is positive, + for phase_name, phase in self.mission_info.items(): + if 'user_options' in phase: + target_distance = phase['user_options'].get('target_distance', (None, 'm')) + if target_distance[0] is not None and target_distance[0] <= 0: + raise ValueError( + f'Invalid target_distance in [{phase_name}].[user_options]. ' + f'Current (value: {target_distance[0]}), ' + f'(units: {target_distance[1]}) <= 0' + ) + + # Checks to make sure time_duration is positive, + # Sets duration_bounds, initial_guesses, and fixed_duration + for phase_name, phase in self.mission_info.items(): + if 'user_options' in phase: + analytic = False + if self.mission_method is EquationsOfMotion.TWO_DEGREES_OF_FREEDOM: + try: + # if the user provided an option, use it + analytic = phase['user_options']['analytic'] + except KeyError: + # if it isn't specified, only the default 2DOF cruise for + # collocation is analytic + if 'cruise' in phase_name: + analytic = phase['user_options']['analytic'] = True + else: + analytic = phase['user_options']['analytic'] = False + + if 'time_duration' in phase['user_options']: + time_duration, units = phase['user_options']['time_duration'] + + if time_duration is None: + continue + + if time_duration <= 0: + raise ValueError( + f'Invalid time_duration in phase_info[{phase_name}]' + f'[user_options]. Current (value: {time_duration[0]}), ' + f'(units: {time_duration[1]}) <= 0")' + ) + + if 'initial_guesses' not in phase: + phase['initial_guesses'] = {} + + guesses = phase['initial_guesses'] + if 'time' in guesses: + time_guess, units_guess = guesses['time'] + + if time_guess[1] is not None: + msg = f'Duration initial guess of {time_guess[1]} {units_guess} ' + msg += f'specified on fixed duration phase for phase {phase_name}. ' + msg += f'Using fixed value of {time_duration} {units} instead.' + print(msg) + + time_duration_conv = wrapped_convert_units( + (time_duration, units), units_guess + ) + guesses['time'] = ((time_guess[0], time_duration_conv), units_guess) + + else: + guesses['time'] = ((None, time_duration), units) + + for phase_name in self.mission_info: + for external_subsystem in self.mission_info[phase_name]['external_subsystems']: + aviary_inputs = external_subsystem.preprocess_inputs(aviary_inputs) + + # PREPROCESSORS # + # BUG we can't provide updated metadata to preprocessors, because we need the + # processed options to build our subsystems to begin with + preprocess_options( + aviary_inputs, + engine_models=self.engine_builders, + verbosity=verbosity, + # metadata=self.meta_data + ) + + # TODO this seems like the wrong place to define the core subsystems. Maybe move to + # load_inputs? + ## Set Up Core Subsystems ## + perf = CorePerformanceBuilder('core_performance') + prop = CorePropulsionBuilder('core_propulsion', engine_models=self.engine_builders) + mass = CoreMassBuilder('core_mass', code_origin=self.mass_method) + + # If all phases ask for tabular aero, we can skip pre-mission. Check phase_info + tabular = False + for phase in self.mission_info: + if phase not in ('pre_mission', 'post_mission'): + try: + if ( + 'tabular' + in self.mission_info[phase]['subsystem_options']['core_aerodynamics'][ + 'method' + ] + ): + tabular = True + except KeyError: + tabular = False + + aero = CoreAerodynamicsBuilder( + 'core_aerodynamics', code_origin=self.aero_method, tabular=tabular + ) + + # which geometry methods should be used? + geom_code_origin = None + + if (self.aero_method is FLOPS) and (self.mass_method is FLOPS): + geom_code_origin = FLOPS + elif (self.aero_method is GASP) and (self.mass_method is GASP): + geom_code_origin = GASP + else: + geom_code_origin = (FLOPS, GASP) + + # which geometry method gets prioritized in case of conflicting outputs + code_origin_to_prioritize = self.configurator.get_code_origin(self) + + geom = CoreGeometryBuilder( + 'core_geometry', + code_origin=geom_code_origin, + code_origin_to_prioritize=code_origin_to_prioritize, + ) + + subsystems = self.core_subsystems = { + 'propulsion': prop, + 'geometry': geom, + 'mass': mass, + 'aerodynamics': aero, + 'performance': perf, + } + + # TODO optionally accept which subsystems to load from phase_info + default_mission_subsystems = [ + subsystems['aerodynamics'], + subsystems['propulsion'], + ] + self.ode_args = { + 'aviary_options': aviary_inputs, + 'core_subsystems': default_mission_subsystems, + } + + # self._update_metadata_from_subsystems() + self._check_reserve_phase_separation() + + def _check_reserve_phase_separation(self): + """ + This method checks for reserve=True & False + Returns an error if a non-reserve phase is specified after a reserve phase. + return two dictionaries of phases: regular_phases and reserve_phases + For shooting trajectories, this will also check if a phase is part of the descent. + """ + # Check to ensure no non-reserve phases are specified after reserve phases + start_reserve = False + raise_error = False + self.regular_phases = [] + for idx, phase_name in enumerate(self.mission_info): + if 'user_options' in self.mission_info[phase_name]: + if 'reserve' in self.mission_info[phase_name]['user_options']: + if self.mission_info[phase_name]['user_options']['reserve'] is False: + # This is a regular phase + self.regular_phases.append(phase_name) + if start_reserve is True: + raise_error = True + else: + # This is a reserve phase + self.reserve_phases.append(phase_name) + start_reserve = True + else: + # This is a regular phase by default + self.regular_phases.append(phase_name) + if start_reserve is True: + raise_error = True + + if raise_error is True: + raise ValueError( + 'In phase_info, reserve=False cannot be specified after a phase where ' + 'reserve=True. All reserve phases must happen after non-reserve phases. ' + # TODO: will need to pre-pend current group level to all error messages!! + f'Regular Phases : {self.regular_phases} | ' + f'Reserve Phases : {self.reserve_phases} ' + ) + + def add_pre_mission_systems(self, verbosity=None): + """ + Add pre-mission systems to the Aviary group. These systems are executed before + the mission. + + Depending on the mission model specified (`FLOPS` or `GASP`), this method adds + various subsystems to the aircraft model. For the `FLOPS` mission model, a + takeoff phase is added using the Takeoff class with the number of engines and + airport altitude specified. For the `GASP` mission model, three subsystems are + added: a TaxiSegment subsystem, an ExecComp to calculate the time to initiate + gear and flaps, and an ExecComp to calculate the speed at which to initiate + rotation. All subsystems are promoted with aircraft and mission inputs and + outputs as appropriate. + + A user can override this method with their own pre-mission systems as desired. + """ + + pre_mission = self.pre_mission + self.add_subsystem( + 'pre_mission', + pre_mission, + promotes_inputs=['aircraft:*', 'mission:*'], + promotes_outputs=['aircraft:*', 'mission:*'], + ) + + if 'linear_solver' in self.pre_mission_info: + pre_mission.linear_solver = self.pre_mission_info['linear_solver'] + + if 'nonlinear_solver' in self.pre_mission_info: + pre_mission.nonlinear_solver = self.pre_mission_info['nonlinear_solver'] + + self._add_premission_external_subsystems() + + subsystems = self.core_subsystems + + # Propulsion isn't included in core pre-mission group to avoid override step in + # configure() - instead add it now + pre_mission.add_subsystem( + 'core_propulsion', + subsystems['propulsion'].build_pre_mission(self.aviary_inputs), + ) + + default_subsystems = [ + subsystems['geometry'], + subsystems['aerodynamics'], + subsystems['mass'], + subsystems['performance'], + ] + + pre_mission.add_subsystem( + 'core_subsystems', + CorePreMission( + aviary_options=self.aviary_inputs, + subsystems=default_subsystems, + process_overrides=False, + ), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + if self.pre_mission_info['include_takeoff']: + self.configurator.add_takeoff_systems(self) + + def _add_premission_external_subsystems(self): + """ + This private method adds each external subsystem to the pre-mission subsystem and + a mass component that captures external subsystem masses for use in mass buildups. + + Firstly, the method iterates through all external subsystems in the pre-mission + information. For each subsystem, it builds the pre-mission instance of the + subsystem. + + Secondly, the method collects the mass names of the added subsystems. This + expression is then used to define an ExecComp (a component that evaluates a + simple equation given input values). + + The method promotes the input and output of this ExecComp to the top level of the + pre-mission object, allowing this calculated subsystem mass to be accessed + directly from the pre-mission object. + """ + mass_names = [] + # Loop through all the phases in this subsystem. + for external_subsystem in self.pre_mission_info['external_subsystems']: + # Get all the subsystem builders for this phase. + subsystem_premission = external_subsystem.build_pre_mission(self.aviary_inputs) + + if subsystem_premission is not None: + self.pre_mission.add_subsystem(external_subsystem.name, subsystem_premission) + + mass_names.extend(external_subsystem.get_mass_names()) + + if mass_names: + formatted_names = [] + for name in mass_names: + formatted_name = name.replace(':', '_') + formatted_names.append(formatted_name) + + # Define the expression for computing the sum of masses + expr = 'subsystem_mass = ' + ' + '.join(formatted_names) + + promotes_inputs_list = [ + (formatted_name, original_name) + for formatted_name, original_name in zip(formatted_names, mass_names) + ] + + # Create the ExecComp + self.pre_mission.add_subsystem( + 'external_comp_sum', + om.ExecComp(expr, units='kg'), + promotes_inputs=promotes_inputs_list, + promotes_outputs=[('subsystem_mass', Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS)], + ) + + def _get_phase(self, phase_name, phase_idx, comm): + phase_options = self.mission_info[phase_name] + + # TODO optionally accept which subsystems to load from phase_info + subsystems = self.core_subsystems + default_mission_subsystems = [ + subsystems['aerodynamics'], + subsystems['propulsion'], + ] + + phase_builder = self.configurator.get_phase_builder(self, phase_name, phase_options) + + phase_object = phase_builder.from_phase_info( + phase_name, + phase_options, + default_mission_subsystems, + meta_data=self.meta_data, + ) + + phase = phase_object.build_phase(aviary_options=self.aviary_inputs) + + self.phase_objects.append(phase_object) + + # TODO: add logic to filter which phases get which controls. + # right now all phases get all controls added from every subsystem. + # for example, we might only want ELECTRIC_SHAFT_POWER applied during the + # climb phase. + all_subsystems = self.get_all_subsystems(phase_options['external_subsystems']) + + # loop through all_subsystems and call `get_controls` on each subsystem + for subsystem in all_subsystems: + # add the controls from the subsystems to each phase + arg_spec = inspect.getfullargspec(subsystem.get_controls) + if 'phase_name' in arg_spec.args: + control_dicts = subsystem.get_controls(phase_name=phase_name) + else: + control_dicts = subsystem.get_controls(phase_name=phase_name) + for control_name, control_dict in control_dicts.items(): + phase.add_control(control_name, **control_dict) + + # This fills in all defaults from the phase_builders user_options. + full_options = phase_object.user_options.to_phase_info() + self.mission_info[phase_name]['user_options'] = full_options + + # TODO: Should some of this stuff be moved into the phase builder? + self.configurator.set_phase_options(self, phase_name, phase_idx, phase, full_options, comm) + + return phase + + def add_phases( + self, phase_info_parameterization=None, parallel_phases=True, verbosity=None, comm=None + ): + """ + Add the mission phases to the problem trajectory based on the user-specified + phase_info dictionary. + + Parameters + ---------- + phase_info_parameterization (function, optional): A function that takes in the + phase_info dictionary and aviary_inputs and returns modified phase_info. + Defaults to None. + + parallel_phases (bool, optional): If True, the top-level container of all phases + will be a ParallelGroup, otherwise it will be a standard OpenMDAO Group. + Defaults to True. + + Returns + ------- + traj: The Dymos Trajectory object containing the added mission phases. + """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + if phase_info_parameterization is not None: + self.mission_info, self.post_mission_info = phase_info_parameterization( + self.mission_info, self.post_mission_info, self.aviary_inputs + ) + + phase_info = self.mission_info + + phases = list(phase_info.keys()) + traj = self.add_subsystem('traj', dm.Trajectory(parallel_phases=parallel_phases)) + + def add_subsystem_timeseries_outputs(phase, phase_name): + phase_options = self.mission_info[phase_name] + all_subsystems = self.get_all_subsystems(phase_options['external_subsystems']) + for subsystem in all_subsystems: + timeseries_to_add = subsystem.get_outputs() + for timeseries in timeseries_to_add: + phase.add_timeseries_output(timeseries) + mbvars = subsystem.get_post_mission_bus_variables( + self.aviary_inputs, self.mission_info + ) + if mbvars: + mbvars_this_phase = mbvars.get(phase_name, None) + if mbvars_this_phase: + timeseries_to_add = mbvars_this_phase.keys() + for timeseries in timeseries_to_add: + phase.add_timeseries_output( + timeseries, timeseries='mission_bus_variables' + ) + + self.phase_objects = [] + for phase_idx, phase_name in enumerate(phases): + phase = traj.add_phase(phase_name, self._get_phase(phase_name, phase_idx, comm)) + add_subsystem_timeseries_outputs(phase, phase_name) + + # loop through phase_info and external subsystems + external_parameters = {} + for phase_name in self.mission_info: + external_parameters[phase_name] = {} + all_subsystems = self.get_all_subsystems( + self.mission_info[phase_name]['external_subsystems'] + ) + + subsystem_options = phase_info[phase_name].get('subsystem_options', {}) + + for subsystem in all_subsystems: + if subsystem.name in subsystem_options: + kwargs = subsystem_options[subsystem.name] + else: + kwargs = {} + parameter_dict = subsystem.get_parameters( + phase_info=self.mission_info[phase_name], + aviary_inputs=self.aviary_inputs, + **kwargs, + ) + for parameter in parameter_dict: + external_parameters[phase_name][parameter] = parameter_dict[parameter] + + traj = setup_trajectory_params( + self, + traj, + self.aviary_inputs, + phases, + meta_data=self.meta_data, + external_parameters=external_parameters, + ) + + self.traj = traj + + return traj + + def add_post_mission_systems(self, verbosity=None): + """ + Add post-mission systems to the aircraft model. This is akin to the pre-mission + group or the "premission_systems", but occurs after the mission in the execution + order. + + Depending on the mission model specified (`FLOPS` or `GASP`), this method adds + various subsystems to the aircraft model. For the `FLOPS` mission model, a + landing phase is added using the Landing class with the wing area and lift + coefficient specified, and a takeoff constraints ExecComp is added to enforce + mass, range, velocity, and altitude continuity between the takeoff and climb + phases. The landing subsystem is promoted with aircraft and mission inputs and + outputs as appropriate, while the takeoff constraints ExecComp is only promoted + with mission inputs and outputs. + + For the `GASP` mission model, four subsystems are added: a LandingSegment + subsystem, an ExecComp to calculate the reserve fuel required, an ExecComp to + calculate the overall fuel burn, and three ExecComps to calculate various + mission objectives and constraints. All subsystems are promoted with aircraft + and mission inputs and outputs as appropriate. + + A user can override this with their own postmission systems. + """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + post_mission = self.post_mission + self.add_subsystem( + 'post_mission', + post_mission, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + # Make dymos state outputs easy to access later + self.add_subsystem( + 'state_output', + om.ExecComp( + ['mass_final = mass_in', 'time_final = time_in', 'range_final = range_in'], + mass_in={'units': 'lbm'}, + mass_final={'units': 'lbm'}, + time_in={'units': 'min'}, + time_final={'units': 'min'}, + range_in={'units': 'nmi'}, + range_final={'units': 'nmi'}, + ), + promotes_outputs={ + ('mass_final', Mission.Summary.FINAL_MASS), + ('time_final', Mission.Summary.FINAL_TIME), + ('range_final', Mission.Summary.RANGE), + }, + ) + + self.configurator.add_post_mission_systems(self) + + # Add all post-mission external subsystems. + phase_mission_bus_lengths = get_phase_mission_bus_lengths(self.traj) + for external_subsystem in self.post_mission_info['external_subsystems']: + subsystem_postmission = external_subsystem.build_post_mission( + aviary_inputs=self.aviary_inputs, + phase_info=self.mission_info, + phase_mission_bus_lengths=phase_mission_bus_lengths, + ) + + if subsystem_postmission is not None: + post_mission.add_subsystem(external_subsystem.name, subsystem_postmission) + + # Check if regular_phases[] is accessible + try: + self.regular_phases[0] + except BaseException: + raise ValueError( + 'regular_phases[] dictionary is not accessible. For HEIGHT_ENERGY and ' + 'SOLVED_2DOF missions, check_and_preprocess_inputs() must be called ' + 'before add_post_mission_systems().' + ) + + # Fuel burn in regular phases + ecomp = om.ExecComp( + 'fuel_burned = initial_mass - mass_final', # TODO: Fix to be difference in cumulative fuel burn + initial_mass={'units': 'lbm'}, + mass_final={'units': 'lbm'}, + fuel_burned={'units': 'lbm'}, + ) + + post_mission.add_subsystem( + 'fuel_burned', + ecomp, + promotes=[('fuel_burned', Mission.Summary.FUEL_BURNED)], + ) + + if self.pre_mission_info['include_takeoff']: + post_mission.promotes( + 'fuel_burned', + [('initial_mass', Mission.Summary.GROSS_MASS)], + ) + else: + # timeseries has to be used because Breguet cruise phases don't have + # states + self.connect( + f'traj.{self.regular_phases[0]}.timeseries.mass', + 'fuel_burned.initial_mass', + src_indices=[0], + ) + + self.connect( + f'traj.{self.regular_phases[-1]}.timeseries.mass', + 'fuel_burned.mass_final', + src_indices=[-1], + ) + + # Fuel burn in reserve phases + if self.reserve_phases: + ecomp = om.ExecComp( + 'reserve_fuel_burned = initial_mass - mass_final', # TODO: Fix to be different in cumulative fuel burn + initial_mass={'units': 'lbm'}, + mass_final={'units': 'lbm'}, + reserve_fuel_burned={'units': 'lbm'}, + ) + + post_mission.add_subsystem( + 'reserve_fuel_burned', + ecomp, + promotes=[('reserve_fuel_burned', Mission.Summary.RESERVE_FUEL_BURNED)], + ) + + # timeseries has to be used because Breguet cruise phases don't have + # states + self.connect( + f'traj.{self.reserve_phases[0]}.timeseries.mass', + 'reserve_fuel_burned.initial_mass', + src_indices=[0], + ) + self.connect( + f'traj.{self.reserve_phases[-1]}.timeseries.mass', + 'reserve_fuel_burned.mass_final', + src_indices=[-1], + ) + + self.add_fuel_reserve_component() + + # TODO: need to add some sort of check that this value is less than the fuel capacity + # TODO: the overall_fuel variable is the burned fuel plus the reserve, but should + # also include the unused fuel, and the hierarchy variable name should be + # more clear + ecomp = om.ExecComp( + 'overall_fuel = (1 + fuel_margin/100)*fuel_burned + reserve_fuel', + overall_fuel={'units': 'lbm', 'shape': 1}, + fuel_margin={'units': 'unitless', 'val': 0}, + fuel_burned={'units': 'lbm'}, # from regular_phases only + reserve_fuel={'units': 'lbm', 'shape': 1}, + ) + post_mission.add_subsystem( + 'fuel_calc', + ecomp, + promotes_inputs=[ + ('fuel_margin', Aircraft.Fuel.FUEL_MARGIN), + ('fuel_burned', Mission.Summary.FUEL_BURNED), + ('reserve_fuel', Mission.Design.RESERVE_FUEL), + ], + promotes_outputs=[('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS)], + ) + + # If a target distance (or time) has been specified for this phase + # distance (or time) is measured from the start of this phase to the end + # of this phase + for phase_name in self.mission_info: + user_options = self.mission_info[phase_name]['user_options'] + + target_distance = user_options.get('target_distance', (None, 'nmi')) + target_distance = wrapped_convert_units(target_distance, 'nmi') + if target_distance is not None: + post_mission.add_subsystem( + f'{phase_name}_distance_constraint', + om.ExecComp( + 'distance_resid = target_distance - (final_distance - initial_distance)', + distance_resid={'units': 'nmi'}, + target_distance={'val': target_distance, 'units': 'nmi'}, + final_distance={'units': 'nmi'}, + initial_distance={'units': 'nmi'}, + ), + ) + self.connect( + f'traj.{phase_name}.timeseries.distance', + f'{phase_name}_distance_constraint.final_distance', + src_indices=[-1], + ) + self.connect( + f'traj.{phase_name}.timeseries.distance', + f'{phase_name}_distance_constraint.initial_distance', + src_indices=[0], + ) + self.add_constraint( + f'{phase_name}_distance_constraint.distance_resid', + equals=0.0, + ref=1e2, + ) + + # this is only used for analytic phases with a target duration + time_duration = user_options.get('time_duration', (None, 'min')) + time_duration = wrapped_convert_units(time_duration, 'min') + analytic = user_options.get('analytic', False) + + if analytic and time_duration is not None: + post_mission.add_subsystem( + f'{phase_name}_duration_constraint', + om.ExecComp( + 'duration_resid = time_duration - (final_time - initial_time)', + duration_resid={'units': 'min'}, + time_duration={'val': time_duration, 'units': 'min'}, + final_time={'units': 'min'}, + initial_time={'units': 'min'}, + ), + ) + self.connect( + f'traj.{phase_name}.timeseries.time', + f'{phase_name}_duration_constraint.final_time', + src_indices=[-1], + ) + self.connect( + f'traj.{phase_name}.timeseries.time', + f'{phase_name}_duration_constraint.initial_time', + src_indices=[0], + ) + self.add_constraint( + f'{phase_name}_duration_constraint.duration_resid', + equals=0.0, + ref=1e2, + ) + + ecomp = om.ExecComp( + 'mass_resid = operating_empty_mass + overall_fuel + payload_mass - initial_mass', + operating_empty_mass={'units': 'lbm'}, + overall_fuel={'units': 'lbm'}, + payload_mass={'units': 'lbm'}, + initial_mass={'units': 'lbm'}, + mass_resid={'units': 'lbm'}, + ) + + post_mission.add_subsystem( + 'mass_constraint', + ecomp, + promotes_inputs=[ + ('operating_empty_mass', Mission.Summary.OPERATING_MASS), + ('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS), + ('payload_mass', Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS), + ('initial_mass', Mission.Summary.GROSS_MASS), + ], + promotes_outputs=[('mass_resid', Mission.Constraints.MASS_RESIDUAL)], + ) + + ecomp = om.ExecComp( + 'excess_fuel_capacity = total_fuel_capacity - unusable_fuel - overall_fuel', + total_fuel_capacity={'units': 'lbm'}, + unusable_fuel={'units': 'lbm'}, + overall_fuel={'units': 'lbm'}, + excess_fuel_capacity={'units': 'lbm'}, + ) + + post_mission.add_subsystem( + 'excess_fuel_constraint', + ecomp, + promotes_inputs=[ + ('total_fuel_capacity', Aircraft.Fuel.TOTAL_CAPACITY), + ('unusable_fuel', Aircraft.Fuel.UNUSABLE_FUEL_MASS), + ('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS), + ], + promotes_outputs=[('excess_fuel_capacity', Mission.Constraints.EXCESS_FUEL_CAPACITY)], + ) + + # determine if the user wants the excess_fuel_capacity constraint active and if so add it to the problem + if Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT in self.aviary_inputs: + ignore_capacity_constraint = self.aviary_inputs.get_val( + Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT, units='unitless' + ) + else: + ignore_capacity_constraint = self.meta_data[ + Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT + ]['default_value'] + self.aviary_inputs.set_val( + Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT, + val=ignore_capacity_constraint, + units='unitless', + ) + + if not ignore_capacity_constraint: + self.add_constraint( + Mission.Constraints.EXCESS_FUEL_CAPACITY, lower=0, ref=1.0e5, units='lbm' + ) + else: + if verbosity >= Verbosity.BRIEF: + warnings.warn( + 'Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT = True, therefore ' + 'EXCESS_FUEL_CAPACITY constraint was not added to the Aviary problem. The ' + 'aircraft may not have enough space for fuel, so check the value of ' + 'Mission.Constraints.EXCESS_FUEL_CAPACITY for details.' + ) + + def link_phases(self, verbosity=None, comm=None): + """ + Link phases together after they've been added. + + Based on which phases the user has selected, we might need + special logic to do the Dymos linkages correctly. Some of those + connections for the simple GASP and FLOPS mission are shown here. + """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + self._add_bus_variables_and_connect() + self._connect_mission_bus_variables() + + final_phase = self.regular_phases[-1] + + # We connect the last points in the trajectory to the state_output component to make it + # easier for users to access Mission.Summary.FINAL_MASS, Mission.Summary.FINAL_TIME, + # and Mission.Summary.RANGE. + self.connect( + f'traj.{final_phase}.states:mass', + 'state_output.mass_in', + src_indices=[-1], + ) + self.connect( + f'traj.{final_phase}.timeseries.distance', + 'state_output.range_in', + src_indices=[-1], + ) + self.connect( + f'traj.{final_phase}.timeseries.time', 'state_output.time_in', src_indices=[-1] + ) + + phases = list(self.mission_info.keys()) + + if len(phases) <= 1: + return + + # In summary, the following code loops over all phases in self.mission_info, gets + # the linked variables from each external subsystem in each phase, and stores + # the lists of linked variables in lists_to_link. It then gets a list of + # unique variable names from lists_to_link and loops over them, creating + # a list of phase names for each variable and linking the phases + # using self.traj.link_phases(). + + lists_to_link = [] + for idx, phase_name in enumerate(self.mission_info): + lists_to_link.append([]) + for external_subsystem in self.mission_info[phase_name]['external_subsystems']: + lists_to_link[idx].extend(external_subsystem.get_linked_variables()) + + # get unique variable names from lists_to_link + unique_vars = list(set([var for sublist in lists_to_link for var in sublist])) + + # Phase linking. + # If we are under mpi, and traj.phases is running in parallel, then let the + # optimizer handle the linkage constraints. Note that we can technically + # parallelize connected phases, but it requires a solver that we would like + # to avoid. + true_unless_mpi = True + if comm.size > 1 and self.traj.options['parallel_phases']: + true_unless_mpi = False + + # loop over unique variable names + for var in unique_vars: + phases_to_link = [] + for idx, phase_name in enumerate(self.mission_info): + if var in lists_to_link[idx]: + phases_to_link.append(phase_name) + + if len(phases_to_link) > 1: # TODO: hack + self.traj.link_phases(phases=phases_to_link, vars=[var], connected=True) + + self.configurator.link_phases(self, phases, connect_directly=true_unless_mpi) + + self.configurator.check_trajectory(self) + + def _add_bus_variables_and_connect(self): + all_subsystems = self.get_all_subsystems(group='pre_mission') + + base_phases = list(self.mission_info.keys()) + + for external_subsystem in all_subsystems: + bus_variables = external_subsystem.get_pre_mission_bus_variables(self.aviary_inputs) + if bus_variables is not None: + for bus_variable, variable_data in bus_variables.items(): + mission_variable_name = variable_data['mission_name'] + src_indices = variable_data.get('src_indices', None) + + # check if mission_variable_name is a list + if not isinstance(mission_variable_name, list): + mission_variable_name = [mission_variable_name] + + # loop over the mission_variable_name list and add each variable to + # the trajectory + for mission_var_name in mission_variable_name: + if mission_var_name not in self.meta_data: + # base_units = self.get_io_metadata(includes=f'pre_mission.{external_subsystem.name}.{bus_variable}')[f'pre_mission.{external_subsystem.name}.{bus_variable}']['units'] + base_units = variable_data['units'] + + shape = variable_data.get('shape', _unspecified) + + targets = mission_var_name + if '.' in mission_var_name: + # Support for non-hierarchy variables as parameters. + mission_var_name = mission_var_name.split('.')[-1] + + if 'phases' in variable_data: + # Support for connecting bus variables into a subset of + # phases. + for phase_name in variable_data['phases']: + phase = getattr(self.traj.phases, phase_name) + + phase.add_parameter( + mission_var_name, + opt=False, + static_target=True, + units=base_units, + shape=shape, + targets=targets, + ) + + self.connect( + f'pre_mission.{bus_variable}', + f'traj.{phase_name}.parameters:{mission_var_name}', + src_indices=src_indices, + ) + + else: + self.traj.add_parameter( + mission_var_name, + opt=False, + static_target=True, + units=base_units, + shape=shape, + targets={phase_name: [targets] for phase_name in base_phases}, + ) + + self.connect( + f'pre_mission.{bus_variable}', + 'traj.parameters:' + mission_var_name, + src_indices=src_indices, + ) + + if 'post_mission_name' in variable_data: + # check if post_mission_variable_name is a list + post_mission_variable_name = variable_data['post_mission_name'] + if not isinstance(post_mission_variable_name, list): + post_mission_variable_name = [post_mission_variable_name] + + for post_mission_var_name in post_mission_variable_name: + self.connect( + f'pre_mission.{bus_variable}', + post_mission_var_name, + src_indices=src_indices, + ) + + def _connect_mission_bus_variables(self): + all_subsystems = self.get_all_subsystems(group='post_mission') + + # Loop through all external subsystems. + for external_subsystem in all_subsystems: + for phase_name, var_mapping in external_subsystem.get_post_mission_bus_variables( + aviary_inputs=self.aviary_inputs, phase_info=self.mission_info + ).items(): + for mission_variable_name, variable_data in var_mapping.items(): + post_mission_variable_names = variable_data['post_mission_name'] + src_indices = variable_data.get('src_indices', None) + if not isinstance(post_mission_variable_names, list): + post_mission_variable_names = [post_mission_variable_names] + + for post_mission_var_name in post_mission_variable_names: + # Remove possible prefix before a `.`, like ." + mvn_basename = mission_variable_name.rpartition('.')[-1] + src_name = f'traj.{phase_name}.mission_bus_variables.{mvn_basename}' + self.connect(src_name, post_mission_var_name, src_indices=src_indices) + + def add_design_variables(self, problem_type: ProblemType = None, verbosity=None): + """ + Adds design variables to the Aviary problem. + + Depending on the mission model and problem type, different design variables and + constraints are added. + + If using the FLOPS model, a design variable is added for the gross mass of the + aircraft, with a lower bound of 10 lbm and an upper bound of 900,000 lbm. + + If using the GASP model, the following design variables are added depending on + the mission type: + - the initial thrust-to-weight ratio of the aircraft during ascent + - the duration of the ascent phase + - the time constant for the landing gear actuation + - the time constant for the flaps actuation + + In addition, two constraints are added for the GASP model: + - the initial altitude of the aircraft with gear extended is constrained to be 50 ft + - the initial altitude of the aircraft with flaps extended is constrained to be 400 ft + + If solving a sizing problem, a design variable is added for the gross mass of + the aircraft, and another for the gross mass of the aircraft computed during the + mission. A constraint is also added to ensure that the residual range is zero. + + If solving an alternate problem, only a design variable for the gross mass of + the aircraft computed during the mission is added. A constraint is also added to + ensure that the residual range is zero. + + In all cases, a design variable is added for the final cruise mass of the + aircraft, with no upper bound, and a residual mass constraint is added to ensure + that the mass balances. + + """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + # add the engine builder `get_design_vars` dict to a collected dict from + # the external subsystems + + # TODO : maybe in the most general case we need to handle DVs in the mission and + # post-mission as well. For right now we just handle pre_mission + all_subsystems = self.get_all_subsystems() + + # loop through all_subsystems and call `get_design_vars` on each subsystem + for subsystem in all_subsystems: + dv_dict = subsystem.get_design_vars() + for dv_name, dv_dict in dv_dict.items(): + self.add_design_var(dv_name, **dv_dict) + + if self.mission_method is SOLVED_2DOF: # TODO: to be removed soon + optimize_mass = self.pre_mission_info.get('optimize_mass') + if optimize_mass: + self.add_design_var( + Mission.Design.GROSS_MASS, + units='lbm', + lower=10, + upper=900.0e3, + ref=175.0e3, + ) + + elif self.mission_method in ( + HEIGHT_ENERGY, + TWO_DEGREES_OF_FREEDOM, + ): # TODO: This becomes generic as soon as SOLVED_2DOF is removed + # vehicle sizing problem + # size the vehicle (via design GTOW) to meet a target range using all fuel + # capacity + if problem_type is ProblemType.SIZING: + self.add_design_var( + Mission.Design.GROSS_MASS, + lower=10.0, + upper=None, + units='lbm', + ref=175e3, + ) + self.add_design_var( + Mission.Summary.GROSS_MASS, + lower=10.0, + upper=None, + units='lbm', + ref=175e3, + ) + + self.add_subsystem( + 'gtow_constraint', + om.EQConstraintComp( + 'GTOW', + eq_units='lbm', + normalize=True, + add_constraint=True, + ), + promotes_inputs=[ + ('lhs:GTOW', Mission.Design.GROSS_MASS), + ('rhs:GTOW', Mission.Summary.GROSS_MASS), + ], + ) + + if self.require_range_residual: + self.add_constraint(Mission.Constraints.RANGE_RESIDUAL, equals=0, ref=1000) + + elif problem_type is ProblemType.ALTERNATE: + # target range problem + # fixed vehicle (design GTOW) but variable actual GTOW for off-design + # get the design gross mass and set as the upper bound for the gross mass design variable + MTOW = self.aviary_inputs.get_val(Mission.Design.GROSS_MASS, 'lbm') + self.add_design_var( + Mission.Summary.GROSS_MASS, + lower=10.0, + upper=MTOW, + units='lbm', + ref=MTOW, + ) + + self.add_constraint(Mission.Constraints.RANGE_RESIDUAL, equals=0, ref=1000) + + elif problem_type is ProblemType.FALLOUT: + # fixed vehicle gross mass aviary finds optimal trajectory and maximum range + if verbosity >= Verbosity.VERBOSE: + print('No additional aircraft design variables added for Fallout missions') + + elif problem_type is ProblemType.MULTI_MISSION: + self.add_design_var( + Mission.Summary.GROSS_MASS, + lower=10.0, + upper=900e3, + units='lbm', + ref=175e3, + ) + + # TODO: RANGE_RESIDUAL constraint should be added based on what the + # user sets as the objective. if Objective is not range or Mission.Summary.Range, + # the range constriant should be added to make target rage = summary range + self.add_constraint(Mission.Constraints.RANGE_RESIDUAL, equals=0, ref=1000) + + # We must ensure that design.gross_mass is greater than + # mission.summary.gross_mass and this must hold true for each of the + # different missions that is flown the result will be the + # design.gross_mass should be equal to the mission.summary.gross_mass + # of the heaviest mission + self.add_subsystem( + 'GROSS_MASS_constraint', + om.ExecComp( + 'gross_mass_resid = design_mass - actual_mass', + design_mass={'val': 1, 'units': 'kg'}, + actual_mass={'val': 0, 'units': 'kg'}, + gross_mass_resid={'val': 30, 'units': 'kg'}, + ), + promotes_inputs=[ + ('design_mass', Mission.Design.GROSS_MASS), + ('actual_mass', Mission.Summary.GROSS_MASS), + ], + promotes_outputs=['gross_mass_resid'], + ) + + self.add_constraint('gross_mass_resid', lower=0) + + if self.mission_method is TWO_DEGREES_OF_FREEDOM: + # TODO: This should be moved into the problem configurator b/c it's 2DOF specific + # problem formulation to make the trajectory work + self.add_design_var(Mission.Takeoff.ASCENT_T_INITIAL, lower=0, upper=100, ref=30.0) + self.add_design_var(Mission.Takeoff.ASCENT_DURATION, lower=1, upper=1000, ref=10.0) + self.add_design_var('tau_gear', lower=0.01, upper=1.0, units='unitless', ref=1) + self.add_design_var('tau_flaps', lower=0.01, upper=1.0, units='unitless', ref=1) + self.add_constraint('h_fit.h_init_gear', equals=50.0, units='ft', ref=50.0) + self.add_constraint('h_fit.h_init_flaps', equals=400.0, units='ft', ref=400.0) + + def set_initial_guesses(self, parent_prob=None, parent_prefix='', verbosity=None): + """ + Call `set_val` on the trajectory for states and controls to seed the problem with + reasonable initial guesses. This is especially important for collocation methods. + + This method first identifies all phases in the trajectory then loops over each phase. + Specific initial guesses are added depending on the phase and mission method. Cruise is + treated as a special phase for GASP-based missions because it is an AnalyticPhase in + Dymos. For this phase, we handle the initial guesses first separately and continue to the + next phase after that. For other phases, we set the initial guesses for states and + controls according to the information available in the 'initial_guesses' attribute of the + phase. + """ + # any mission that does not have any dymos phases, there is nothing to set. + if not hasattr(self, 'traj'): + return + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + target_prob = self + if parent_prob is not None and parent_prefix != '': + target_prob = parent_prob + + traj = self.traj + + # Determine which phases to loop over, fetching them from the trajectory + phase_items = traj._phases.items() + + # Loop over each phase and set initial guesses for the state and control + # variables + for idx, (phase_name, phase) in enumerate(phase_items): + # TODO: This will be uncommented when an openmdao bug is fixed. + # We are using a workaround for now. + # if not phase._is_local: + # # Don't set anything if phase is not on this proc. + # continue + + if self.mission_method is SOLVED_2DOF: + self.phase_objects[idx].apply_initial_guesses(self, 'traj', phase) + + if self.mission_info[phase_name]['user_options'].get('ground_roll') and idx == 0: + continue + + # If not, fetch the initial guesses specific to the phase + # check if guesses exist for this phase + if 'initial_guesses' in self.mission_info[phase_name]: + guesses = self.mission_info[phase_name]['initial_guesses'].copy() + else: + guesses = {} + + # Add subsystem guesses + self._add_subsystem_guesses(phase_name, phase, target_prob, parent_prefix) + + # Set initial guesses for states, controls and time for each phase. + self.configurator.set_phase_initial_guesses( + self, phase_name, phase, guesses, target_prob, parent_prefix + ) + + def get_all_subsystems(self, external_subsystems=None, group='pre_mission'): + all_subsystems = [] + if external_subsystems is None: + if group == 'pre_mission': + all_subsystems.extend(self.pre_mission_info['external_subsystems']) + elif group == 'post_mission': + all_subsystems.extend(self.post_mission_info['external_subsystems']) + else: + all_subsystems.extend(external_subsystems) + + all_subsystems.append(self.core_subsystems['aerodynamics']) + all_subsystems.append(self.core_subsystems['propulsion']) + + return all_subsystems + + def _add_subsystem_guesses(self, phase_name, phase, target_prob, parent_prefix): + """ + Adds the initial guesses for each subsystem of a given phase to the problem. + This method first fetches all subsystems associated with the given phase. + It then loops over each subsystem and fetches its initial guesses. For each + guess, it identifies whether the guess corresponds to a state or a control + variable and then processes the guess variable. After this, the initial + guess is set in the problem using the `set_val` method. + + Parameters + ---------- + phase_name : str + The name of the phase for which the subsystem guesses are being added. + phase : Phase + The phase object for which the subsystem guesses are being added. + """ + # Get all subsystems associated with the phase + all_subsystems = self.get_all_subsystems( + self.mission_info[phase_name]['external_subsystems'] + ) + + # Loop over each subsystem + for subsystem in all_subsystems: + # Fetch the initial guesses for the subsystem + initial_guesses = subsystem.get_initial_guesses() + + # Loop over each guess + for key, val_dict in initial_guesses.items(): + # Identify the type of the guess (state or control) + var_type = val_dict['type'] + if 'state' in var_type: + path_string = 'states' + elif 'control' in var_type: + path_string = 'controls' + + # Process the guess variable (handles array interpolation) + # val['val'] = self.process_guess_var(val['val'], key, phase) + val = process_guess_var(val_dict['val'], key, phase) + + # Set the initial guess in the problem + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.{path_string}:{key}', + val, + units=val_dict.get('units', None), + ) + + def add_fuel_reserve_component( + self, post_mission=True, reserves_name=Mission.Design.RESERVE_FUEL + ): + if post_mission: + reserve_calc_location = self.post_mission + else: + reserve_calc_location = self.model + + RESERVE_FUEL_FRACTION = self.aviary_inputs.get_val( + Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless' + ) + if RESERVE_FUEL_FRACTION != 0: + reserve_fuel_frac = om.ExecComp( + 'reserve_fuel_frac_mass = reserve_fuel_fraction * (takeoff_mass - final_mass)', + reserve_fuel_frac_mass={'units': 'lbm'}, + reserve_fuel_fraction={ + 'units': 'unitless', + 'val': RESERVE_FUEL_FRACTION, + }, + final_mass={'units': 'lbm'}, + takeoff_mass={'units': 'lbm'}, + ) + + reserve_calc_location.add_subsystem( + 'reserve_fuel_frac', + reserve_fuel_frac, + promotes_inputs=[ + ('takeoff_mass', Mission.Summary.GROSS_MASS), + ('final_mass', Mission.Landing.TOUCHDOWN_MASS), + ('reserve_fuel_fraction', Aircraft.Design.RESERVE_FUEL_FRACTION), + ], + promotes_outputs=['reserve_fuel_frac_mass'], + ) + + RESERVE_FUEL_ADDITIONAL = self.aviary_inputs.get_val( + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm' + ) + reserve_fuel = om.ExecComp( + 'reserve_fuel = reserve_fuel_frac_mass + reserve_fuel_additional + reserve_fuel_burned', + reserve_fuel={'units': 'lbm', 'shape': 1}, + reserve_fuel_frac_mass={'units': 'lbm', 'val': 0}, + reserve_fuel_additional={'units': 'lbm', 'val': RESERVE_FUEL_ADDITIONAL}, + reserve_fuel_burned={'units': 'lbm', 'val': 0}, + ) + + reserve_calc_location.add_subsystem( + 'reserve_fuel', + reserve_fuel, + promotes_inputs=[ + 'reserve_fuel_frac_mass', + ('reserve_fuel_additional', Aircraft.Design.RESERVE_FUEL_ADDITIONAL), + ('reserve_fuel_burned', Mission.Summary.RESERVE_FUEL_BURNED), + ], + promotes_outputs=[('reserve_fuel', reserves_name)], + ) diff --git a/aviary/core/post_mission_group.py b/aviary/core/post_mission_group.py new file mode 100644 index 0000000000..48d5895f42 --- /dev/null +++ b/aviary/core/post_mission_group.py @@ -0,0 +1,23 @@ +import openmdao +import openmdao.api as om +from packaging import version + +from aviary.utils.functions import promote_aircraft_and_mission_vars + +use_new_openmdao_syntax = version.parse(openmdao.__version__) >= version.parse('3.28') + + +class PostMissionGroup(om.Group): + """OpenMDAO group that holds all post-mission systems.""" + + def setup(self, **kwargs): + if use_new_openmdao_syntax: + # rely on openMDAO's auto-ordering for this group + self.options['auto_order'] = True + + def configure(self): + """ + Configure this group for post-mission. + Promote aircraft and mission variables. + """ + promote_aircraft_and_mission_vars(self) diff --git a/aviary/core/pre_mission_group.py b/aviary/core/pre_mission_group.py new file mode 100644 index 0000000000..0122d37b95 --- /dev/null +++ b/aviary/core/pre_mission_group.py @@ -0,0 +1,24 @@ +import openmdao.api as om + +from aviary.utils.functions import promote_aircraft_and_mission_vars +from aviary.variable_info.functions import override_aviary_vars + + +class PreMissionGroup(om.Group): + """OpenMDAO group that holds all pre-mission systems.""" + + def configure(self): + """ + Configure this group for pre-mission. + Promote aircraft and mission variables. + Override output aviary variables. + """ + external_outputs = promote_aircraft_and_mission_vars(self) + + pre_mission = self.core_subsystems + override_aviary_vars( + pre_mission, + pre_mission.options['aviary_options'], + external_overrides=external_outputs, + code_origin_overrides=pre_mission.code_origin_overrides, + ) diff --git a/aviary/docs/_toc.yml b/aviary/docs/_toc.yml index bc76d351ba..401523e959 100644 --- a/aviary/docs/_toc.yml +++ b/aviary/docs/_toc.yml @@ -27,6 +27,9 @@ parts: - file: user_guide/examples_of_the_same_mission_at_different_UI_levels - file: user_guide/aviary_commands - file: user_guide/input_files + - file: user_guide/phase_info + - file: user_guide/phase_info_detailed + - file: user_guide/phase_info_conversion - file: user_guide/drawing_and_running_simple_missions - file: user_guide/pre_mission_and_mission - file: user_guide/postprocessing_and_visualizing_results @@ -36,6 +39,8 @@ parts: - file: user_guide/aerodynamics - file: user_guide/external_aero - file: user_guide/propulsion + sections: + - file: user_guide/creating_a_turboprop_engine.ipynb - file: user_guide/hamilton_standard - file: user_guide/mass - file: user_guide/subsystems @@ -47,7 +52,8 @@ parts: - file: user_guide/reserve_missions - file: user_guide/multi_mission - file: user_guide/off_design_missions - - file: user_guide/SGM_capabilities + - file: user_guide/payload_range_functionality + - file: user_guide/features/blended_wing_body - file: user_guide/troubleshooting - caption: Examples @@ -74,13 +80,17 @@ parts: - file: theory_guide/mass - file: theory_guide/mission - file: theory_guide/propulsion + sections: + - file: theory_guide/turboprop - file: theory_guide/optimization_algorithms - file: theory_guide/validation + - file: theory_guide/gasp_based_bwb - caption: Developer Guide chapters: - file: developer_guide/codebase_overview - file: developer_guide/coding_standards + - file: developer_guide/ai_policy.md - file: developer_guide/unit_tests - file: developer_guide/contributing_guidelines - file: developer_guide/how_to_contribute_docs diff --git a/aviary/docs/build_source_docs.py b/aviary/docs/build_source_docs.py index 43bd363b3a..0d623e786a 100644 --- a/aviary/docs/build_source_docs.py +++ b/aviary/docs/build_source_docs.py @@ -15,7 +15,6 @@ def header(filename, path): - header = """--- orphan: true --- @@ -35,54 +34,54 @@ def header(filename, path): def build_src_docs(top, src_dir, project_name='aviary'): - doc_dir = os.path.join(top, "_srcdocs") + doc_dir = os.path.join(top, '_srcdocs') if not os.path.isdir(doc_dir): os.mkdir(doc_dir) - packages_dir = os.path.join(doc_dir, "packages") + packages_dir = os.path.join(doc_dir, 'packages') if not os.path.isdir(packages_dir): os.mkdir(packages_dir) - index_filename = os.path.join(doc_dir, "index.md") - index = open(index_filename, "w") + index_filename = os.path.join(doc_dir, 'index.md') + index = open(index_filename, 'w') index_data = index_top for package in packages: sub_packages = [] - package_filename = os.path.join(packages_dir, package + ".md") - package_name = project_name + "." + package + package_filename = os.path.join(packages_dir, package + '.md') + package_name = project_name + '.' + package package_dir = os.path.join(src_dir, package.replace('.', '/')) for sub_listing in sorted(os.listdir(package_dir)): - if (os.path.isdir(sub_listing) and sub_listing != "tests") or \ - (sub_listing.endswith(".py") and not sub_listing.startswith('_')): + if (os.path.isdir(sub_listing) and sub_listing != 'tests') or ( + sub_listing.endswith('.py') and not sub_listing.startswith('_') + ): sub_packages.append(sub_listing.rsplit('.')[0]) if len(sub_packages) > 0: - title = f"[{package}]" - link = f"(packages/{package}.md)\n" - index_data += f"- {title}{link}" + title = f'[{package}]' + link = f'(packages/{package}.md)\n' + index_data += f'- {title}{link}' package_dir = os.path.join(packages_dir, package) os.mkdir(package_dir) - package_file = open(package_filename, "w") - package_data = f"---\norphan: true\n---\n\n# {package_name}\n\n" + package_file = open(package_filename, 'w') + package_data = f'---\norphan: true\n---\n\n# {package_name}\n\n' for sub_package in sub_packages: SKIP_SUBPACKAGES = ['__pycache__'] if sub_package not in SKIP_SUBPACKAGES: - title = f"[{sub_package}]" - link = f"({package}/{sub_package}.md)\n" - package_data += f"- {title}{link}" + title = f'[{sub_package}]' + link = f'({package}/{sub_package}.md)\n' + package_data += f'- {title}{link}' - ref_sheet_filename = os.path.join( - package_dir, sub_package + ".md") - ref_sheet = open(ref_sheet_filename, "w") + ref_sheet_filename = os.path.join(package_dir, sub_package + '.md') + ref_sheet = open(ref_sheet_filename, 'w') - filename = sub_package + ".py" - ref_sheet.write(header(filename, package_name + "." + sub_package)) + filename = sub_package + '.py' + ref_sheet.write(header(filename, package_name + '.' + sub_package)) ref_sheet.close() package_file.write(package_data) @@ -93,4 +92,4 @@ def build_src_docs(top, src_dir, project_name='aviary'): if __name__ == '__main__': - build_src_docs(".", "..") + build_src_docs('.', '..') diff --git a/aviary/docs/developer_guide/ai_policy.md b/aviary/docs/developer_guide/ai_policy.md new file mode 100644 index 0000000000..e44e42dac9 --- /dev/null +++ b/aviary/docs/developer_guide/ai_policy.md @@ -0,0 +1,27 @@ +# Aviary's AI Policy +Use of generative artificial intelligence (LLMs) to produce code for Aviary is allowed, but contributions must follow the following guidelines. If you wish to use AI to assist in contributing code to Aviary, we recommend sticking to limited, targeted uses to speed up development time for small-scale tasks, or to limit AI use to a purely advisory role and not for writing code. Extensive use of AI-generated code leads to large, fragmented, and difficult to maintain codebases. + +However, this advice is based on experience using current-generation AI models, and as these tool's capabilities improve we may revise our recommendations. + +## 1. Disclose any use of AI + +Any use of AI tools should be clearly disclosed. It is helpful to separate AI-generated code into their own commits whenever possible. Mention that AI was used in the commit messages. Give additional details in your pull request descriptions about how AI was used. Include a brief explanation of what you used the AI for (debugging, generating new code, etc.), which model you used, and which files were affected. + +## 2. Thoroughly test all AI-generated code + +Like all code contributions, it is important to run all unittests and benchmark tests on as many different OS and environment configurations as you reasonably can - this goes double for any changes that used AI assistance. If any code generated by AI is not explicitly tested by a unittest, you should write a new test to cover the AI generated code. If AI modifies existing code, especially if new functionality is added, existing unittests should be extended to test that new functionality. + +## 3. AI should never be used as a source for data +Generative AI, as the name implies, is not a tool that is good at "fetching" information - it generates a best guess for what you asked for. Therefore, it is extremely unreliable as a source of "truth" data. AI should not be used as the source of numerical data, such as default values, constants/conversion factors, aircraft performance data, or similar. + +AI should also not be used to write unittests. While writing unittests can be a tedious step that may be tempting to automate, they are extremely critical to get right. The test setup and which values are compared against must be carefully chosen to ensure the code is properly being verified (and potentially validated) including potential edge cases. + +## 4. Do not use AI for documentation + +AI tools should not be used for documentation. Current AI tools struggle with holding large codebases like Aviary in context, and hallucinations or general mistakes are harder to catch in text then they are in code - even with Aviary's documentation checking utilities (DocTAPE). Any AI written documentation pages will be rejected. + +## 5. Use common sense when using AI tools + +In general, you should never just accept and copy/paste code an AI tool gives you. All AI-generated code should be reviewed and understood before you commit it. + +The key takeaway is that you should always fully understand your code before submitting it to Aviary, no matter how it was created. \ No newline at end of file diff --git a/aviary/docs/developer_guide/codebase_overview.ipynb b/aviary/docs/developer_guide/codebase_overview.ipynb index cc4769beaa..d82eb0b906 100644 --- a/aviary/docs/developer_guide/codebase_overview.ipynb +++ b/aviary/docs/developer_guide/codebase_overview.ipynb @@ -13,17 +13,17 @@ "from aviary.utils.doctape import glue_variable\n", "\n", "structure = {\n", - " 'docs':'contains the doc files for Aviary',\n", - " 'examples':'contains example code for using Aviary, including external subsystem examples',\n", - " 'interface':'is where most code that users interact with is located',\n", - " 'mission':'contains OpenMDAO components and groups for modeling the aircraft mission',\n", - " 'models':'contains aircraft and propulsion models for use in Aviary examples and tests',\n", - " 'subsystems':'is where the aerodynamic, propulsion, mass, and geometry core subsystems are located',\n", - " 'utils':'contains utility functions for use in Aviary code, examples, and tests',\n", - " 'validation_cases':'contains validation cases for testing and benchmarking Aviary',\n", - " 'variable_info':'contains the variable meta data as well as several variable classes that are used in Aviary',\n", - " 'visualization':'is where the Aviary dashboard is located',\n", - " }\n", + " 'docs': 'contains the doc files for Aviary',\n", + " 'examples': 'contains example code for using Aviary, including external subsystem examples',\n", + " 'interface': 'is where most code that users interact with is located',\n", + " 'mission': 'contains OpenMDAO components and groups for modeling the aircraft mission',\n", + " 'models': 'contains aircraft and propulsion models for use in Aviary examples and tests',\n", + " 'subsystems': 'is where the aerodynamic, atmosphere, energy, propulsion, mass, and geometry core subsystems are located',\n", + " 'utils': 'contains utility functions for use in Aviary code, examples, and tests',\n", + " 'validation_cases': 'contains validation cases for testing and benchmarking Aviary',\n", + " 'variable_info': 'contains the variable meta data as well as several variable classes that are used in Aviary',\n", + " 'visualization': 'is where the Aviary dashboard is located',\n", + "}\n", "\n", "bulleted_list = ''\n", "for key, val in structure.items():\n", @@ -31,7 +31,7 @@ "\n", "# change display to False to prevent displaying the results when running cells directly\n", "# (Does not change the generated book)\n", - "glue_variable('folder_structure', bulleted_list, display=True)\n" + "glue_variable('folder_structure', bulleted_list, display=True)" ] }, { @@ -61,11 +61,13 @@ "source": [ "# Testing Cell\n", "import os\n", - "from aviary.utils.functions import get_path\n", + "\n", "from aviary.utils.doctape import check_contains\n", + "from aviary.utils.functions import get_path\n", "\n", - "folder = get_path('docs').parent\n", - "subfolders = [ f.name for f in os.scandir(folder) ]\n", + "folder = get_path('docs').parent\n", + "subfolders = [f.name for f in os.scandir(folder)]\n", + "# if a key in structure dictionary is not an actual folder name, this run fails.\n", "check_contains(structure, subfolders)" ] } diff --git a/aviary/docs/developer_guide/coding_standards.ipynb b/aviary/docs/developer_guide/coding_standards.ipynb index e77c5fb60d..d63c06accf 100644 --- a/aviary/docs/developer_guide/coding_standards.ipynb +++ b/aviary/docs/developer_guide/coding_standards.ipynb @@ -13,16 +13,16 @@ "# Testing Cell\n", "import aviary.api as av\n", "from aviary.utils.doctape import get_attribute_name, get_variable_name, glue_variable\n", - "Verbosity = av.Verbosity;\n", "\n", - "verbosity = get_attribute_name(av.Settings,av.Settings.VERBOSITY)\n", - "glue_variable('VERBOSITY',verbosity, md_code=True)\n", + "Verbosity = av.Verbosity\n", + "verbosity = get_attribute_name(av.Settings, av.Settings.VERBOSITY)\n", + "glue_variable('VERBOSITY', verbosity, md_code=True)\n", "glue_variable(get_variable_name(Verbosity), md_code=True)\n", - "glue_variable('QUIET',av.Verbosity.QUIET.name, md_code=True)\n", - "glue_variable('BRIEF',av.Verbosity.BRIEF.name, md_code=True)\n", + "glue_variable('QUIET', av.Verbosity.QUIET.name, md_code=True)\n", + "glue_variable('BRIEF', av.Verbosity.BRIEF.name, md_code=True)\n", "glue_variable(get_variable_name(Verbosity.BRIEF), md_code=True)\n", - "glue_variable('VERBOSE',av.Verbosity.VERBOSE.name, md_code=True)\n", - "glue_variable('DEBUG',av.Verbosity.DEBUG.name, md_code=True)" + "glue_variable('VERBOSE', av.Verbosity.VERBOSE.name, md_code=True)\n", + "glue_variable('DEBUG', av.Verbosity.DEBUG.name, md_code=True)" ] }, { @@ -36,19 +36,15 @@ "In general, always follow the excellent advice given in the [PEP 8 Python style guide](https://peps.python.org/pep-0008/). Consistency is also key - pick a convention and stick with it for an entire file.\n", "\n", "## Style and Formatting\n", - "The Aviary development team uses the [autopep8 formatter](https://pypi.org/project/autopep8/) to handle formatting in a consistent way across the codebase. Autopep8 is a tool that formats Python code (through alteration of whitespace and line breaks) to follow a consistent style and attempt to keep lines within the character limit whenever possible. Aviary uses autopep8 as part of its [pre-commit](https://pre-commit.com/) scripts. The only required setting (which Aviary automatically enforces) is `max_line_length = 89`. Use of the `aggressive` or `experimental` flag is optional and up to the user, but take care that these settings do not alter code function or significantly hamper readability. The utility [isort](https://pycqa.github.io/isort/) is also recommended for formatting of import statements (something not specifically handled by autopep8), but it is currently not required.\n", + "The Aviary development team uses the [ruff formatter](https://docs.astral.sh/ruff/formatter/) to handle formatting in a consistent way across the codebase. Ruff is a tool that formats Python code (through alteration of whitespace and line breaks) to follow a consistent style and attempt to keep lines within the character limit whenever possible. Aviary uses ruff as part of its [pre-commit](https://pre-commit.com/) scripts. Aviary includes a configuration script for ruff, so devs can directly run ruff within the repository and it will use the correct rules. Aviary uses a maximum line length of 100 as a compromise between short, readable lines, and preventing excessive line breaks. The linting capability of ruff is also recommended to be run on all code you plan to contribute to Aviary, but it is currently not required.\n", "\n", - "### Pre-Commit Setup\n", - "To set up pre-commit in your development python environment, there are a few one-time steps that must be done. The following commands need to be run to install pre-commit.\n", + "Ruff is not a dependency for Aviary, and is optional to install - if you are using pre-commit, that package will download and install a special version of ruff that is used only for pre-commit hooks. Installing ruff directly in your python environment is only needed if you wish to manually run the formatter or linter on your code before committing.\n", "\n", - "`pip install pre-commit`\n", "\n", - "`pre-commit install`\n", - "\n", - "The Aviary repository contains a configuration file that defines what is run when commits are made and with what options enabled. Currently this is limited to autopep8 with a max line length restriction.\n", + "The Aviary repository contains a configuration file that defines what is run when commits are made and with what options enabled. Currently this is limited to formatting with ruff.\n", "\n", "### Controlling Display Levels\n", - "To make debugging issues easier, it is strongly recommended to make use of the {glue:md}`Verbosity` setting. This allows control over how much information is displayed to a user; too much information makes finding relevant information difficult and not enough information can make tracking difficult. Aviary uses a sliding scale of possible verbosity settings:\n", + "To make debugging issues easier, it is strongly recommended to make use of the {glue:md}`Verbosity` enum (_located in aviary/variable_info/enums.py_). This allows control over how much information is displayed to a user; too much information makes finding relevant information difficult and not enough information can make tracking difficult. Aviary uses a sliding scale of possible verbosity settings, loosly based off of [Ubuntu's format](https://discourse.ubuntu.com/t/cli-verbosity-levels/26973):\n", "| Verbosity Level | Numerical Value | Description |\n", "| :--- | :--- | :--- |\n", "| `QUIET` | 0 | All output except errors are suppressed |\n", @@ -56,10 +52,10 @@ "| `VERBOSE` | 2 | All user-relevant information is output, in human-readable format |\n", "| `DEBUG` | 3 | Any information can be outputted, including warnings, intermediate calculations, etc., with no formatting requirement |\n", "\n", - "Verbosity levels are defined in Aviary using the `Verbosity` Enum. Each verbosity level is paired with an integer value. In source code, verbosity level can be checked either through comparison with the Enum, or through equality or inequality comparisons with the matching integer value. This allows for code to be triggered not just at a specific level, but for any level above or below the desired setting. Numerical comparisons are recommended for several reasons: they don't require importing the {glue:md}`Verbosity` Enum, and activation is more flexible through the use of inequality comparators, preventing issues like a message only being outputted during {glue:md}`BRIEF` but not {glue:md}`VERBOSE` or {glue:md}`DEBUG`, which a user would expect to also see in higher verbosity settings.\n", - "{glue:md}`BRIEF` is default setting and is used in most cases; however, {glue:md}`QUIET` should be used for tests.\n", + "Verbosity levels are defined in Aviary using the {glue:md}`Verbosity` Enum. Each verbosity level is paired with an integer value. In source code, verbosity level can be checked either through comparison with the Enum, or through equality or inequality comparisons with the matching integer value. This allows for code to be triggered not just at a specific level, but for any level above or below the desired setting. Numerical comparisons are recommended for several reasons: they don't require importing the {glue:md}`Verbosity` Enum, and activation is more flexible through the use of inequality comparators, preventing issues like a message only being outputted during {glue:md}`BRIEF` but not {glue:md}`VERBOSE` or {glue:md}`DEBUG`, which a user would expect to also see in higher verbosity settings.\n", + "{glue:md}`BRIEF` is the default setting and is used in most cases; however, {glue:md}`QUIET` should be used for tests.\n", "\n", - "It is preferred that within source code, the full Enums are used for better readability (e.g. `Verbosity.BRIEF`). For tests, scripts, examples, and other places where Aviary is called (rather than defined), it is ok to use the integer representations of verbosity to shorten lines and remove the need to import the {glue:md}`Verbosity` Enum (e.g. passing `0` as the verbosity argument to a function when {glue:md}`QUIET` is desired). Of course, it is always acceptable to use the full Enum in these cases for the same readability reasons." + "It is preferred that within source code, the full Enums are used for better readability (e.g. {glue:md}`Verbosity.BRIEF`). For tests, scripts, examples, and other places where Aviary is called (rather than defined), it is ok to use the integer representations of verbosity to shorten lines and remove the need to import the {glue:md}`Verbosity` Enum (e.g. passing `0` as the verbosity argument to a function when {glue:md}`QUIET` is desired). An example of this is: *options.set_val(Settings.VERBOSITY, 0)* instead of *options.set_val(Settings.VERBOSITY, Verbosity.QUIET)*. Of course, it is always acceptable to use the full Enum in these cases for the same readability reasons." ] }, { @@ -74,8 +70,9 @@ "source": [ "# Testing Cell\n", "import aviary.api as av\n", - "av.Verbosity.BRIEF;\n", - "av.Verbosity.QUIET;" + "\n", + "av.Verbosity.BRIEF\n", + "av.Verbosity.QUIET" ] }, { @@ -86,31 +83,31 @@ "## Naming Conventions\n", "### Variables\n", "When it comes to variable naming, always be verbose! The Aviary team considers long but clear and descriptive names superior to shortened or vague names. Typing out a long name is only difficult once, as most IDEs will help you auto-complete long variable names, but the readability they add lasts a lifetime!\n", - "The Aviary variable hierarchy is an excellent example of good variable naming. When adding variables to the hierarchy, adhering to the following naming conventions is requested. Inside the codebase itself, such as inside openMDAO components, it is not required but still highly recommended to follow these guidelines.\n", + "The Aviary variable hierarchy is an excellent example of variable naming in Aviary. When adding variables to the hierarchy, adhering to the following naming conventions is requested. Inside the codebase itself, such as inside openMDAO components, it is not required but still highly recommended to follow these guidelines.\n", "\n", "**A good variable name should:**\n", "1. Not be ambiguous (avoid names that cannot be understood without context, like *x* or *calc*)\n", - "2. Avoid abbreviation (*thrust_to_weight_ratio* preferred to *T_W_ratio*). Note that Aviary will sometimes still shorten extremely long words such as \"miscellaneous\" to \"misc\" - use your best judgement!\n", + "2. Avoid abbreviation (*thrust_to_weight_ratio* preferred to *TW_ratio*). Note that Aviary will sometimes still shorten extremely long words such as \"miscellaneous\" to \"misc\" - use your best judgement!\n", "3. Use physical descriptions rather than jargon or mathematical symbols (*density* preferred to *rho* - even better, include what flight condition this density is at, such as *current*, *sea_level*, etc.)\n", - "4. Place adjectives or modifiers after the \"main\" variable name rather than before (such as *thrust_max*, *thrust_sea_level_static*). This makes it is easier to autocomplete using an IDE - simply typing \"thrust\" will provide you with a handy list of all of the different kinds of thrust you can use.\n", + "4. Place adjectives or modifiers after the \"main\" variable name rather than before (such as *thrust_max*, *thrust_sea_level_static*). This makes it is easier to find in a alphabetical list or when using autocomplete in an IDE - simply typing \"thrust\" will provide you with a handy list of all of the different kinds of thrust you can use.\n", "5. Be formatted in \"[snake case](https://en.wikipedia.org/wiki/Snake_case)\", or all lowercase with underscore-delineated words (such as *example_variable*)\n", "\n", "### Classes\n", - "Class names should be written in \"[CamelCase](https://en.wikipedia.org/wiki/Camel_case_)\", or naming with no delimiters such as dashes or underscores between words and each word beginning with a capital letter.\n", + "Class names should be written in \"[camel case](https://en.wikipedia.org/wiki/Camel_case)\", or naming with no delimiters such as dashes or underscores between words and each word beginning with a capital letter (such as *def ExampleClass()*).\n", "\n", "### Functions and Methods\n", - "Function and method names, similar to variables, should be formatted in \"snake case\". Class methods that are not intended to be accessed outside of the class definition can append an underscore at the beginning of the method name to mark it as \"private\", to help other users avoid using those methods incorrectly. An example of this is:\n", + "Function and method names, similar to variables, should be formatted in \"snake case\". Class methods that are not intended to be accessed outside of the class definition can append an underscore at the beginning of the method name to mark it as \"private\", to help other developers avoid using those methods incorrectly. An example of this is:\n", "*def _private_method(self):*\n", "\n", - "### Import statements\n", + "## Import statements\n", "\n", - "Autopep8 allows both absolute and relative paths in `import` statements. Aviary will use absolute path option only. Following autopep8, imports should be grouped in the following order:\n", + "Ruff's linting rules allow both absolute and relative paths in `import` statements. Aviary uses absolute paths only. Following PEP8, imports should be grouped in the following order:\n", "\n", - " 1. Standard library imports.\n", - " 2. Related third party imports.\n", - " 3. Local application/library specific imports.\n", + "1. Standard library imports (e.g. warnings, numpy).\n", + "2. Related third party imports (e.g. openmdao.api).\n", + "3. Local application/library specific imports (e.g. aviary.api).\n", "\n", - "There should be a blank line between each group of imports.\n", + "The library names should be in alphabetic order in each group and there should be a blank line between each group of imports.\n", "\n", "## Code Re-Use and Utility Functions\n", "If an identical block of code appears multiple times inside a file, consider moving it to a function to make your code cleaner. Repeated code bloats files and makes them less readable. If that function ends up being useful outside that individual file, move it to a \"utils.py\" file in the lowest-level directory shared by all files that need that function. If the utility function is useful across all of Aviary and is integral to the tool's operation, the aviary/utils folder is the appropriate place for it.\n" @@ -119,7 +116,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -133,7 +130,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/developer_guide/doctape.ipynb b/aviary/docs/developer_guide/doctape.ipynb index b4db14ae84..36e95ea552 100644 --- a/aviary/docs/developer_guide/doctape.ipynb +++ b/aviary/docs/developer_guide/doctape.ipynb @@ -9,7 +9,7 @@ "DocTAPE (Documentation Testing and Automated Placement of Expressions) is a collection of utility functions (and wrappers for [Glue](https://myst-nb.readthedocs.io/en/latest/render/glue.html)) that are useful\n", "for automating the process of building and testing documentation to ensure that documentation doesn't get stale.\n", "\n", - "Our standard practice it to include a comment (`# Testing Cell`) at the begining of code cells as well as make use of the `remove-cell` tag.\n", + "Our standard practice is to include a comment (`# Testing Cell`) at the beginning of code cells as well as make use of the `remove-cell` tag.\n", "\n", "> \"metadata\": { \"tags\": [ \"remove-cell\" ] },\n", "\n", @@ -33,6 +33,15 @@ "# Testing Cell\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This section is for writing Jupyter notebook in Aviary documentation only. You can skip it for now if you are focusing on the Aviary development.\n", + "\n", + "The Aviary documentation is composed of markdown files and jupyter notebook files. Generally speaking, if a document page contains data, it should be a jupyter notbook file. All glues live in jupyter notbook files." + ] + }, { "cell_type": "code", "execution_count": null, @@ -45,83 +54,81 @@ "source": [ "# Testing Cell\n", "\n", - "from aviary.utils import doctape\n", "import inspect\n", "\n", - "imported_functions = {k:v for k,v in inspect.getmembers(doctape, inspect.isfunction) if v.__module__ == doctape.__name__}\n", - "imported_classes = {k:v for k,v in inspect.getmembers(doctape, inspect.isclass) if v.__module__ == doctape.__name__}\n", + "from aviary.utils import doctape\n", + "\n", + "imported_functions = {\n", + " k: v\n", + " for k, v in inspect.getmembers(doctape, inspect.isfunction)\n", + " if v.__module__ == doctape.__name__\n", + "}\n", + "imported_classes = {\n", + " k: v\n", + " for k, v in inspect.getmembers(doctape, inspect.isclass)\n", + " if v.__module__ == doctape.__name__\n", + "}\n", "\n", "custom_classes = {\n", - " \"expected_error\": \"is an execption that can be used in try/except blocks to allow desired errors to pass while still raising unexpected errors.\",\n", + " 'expected_error': 'is an execption that can be used in try/except blocks to allow desired errors to pass while still raising unexpected errors.',\n", "}\n", "testing_functions = {\n", - " \"check_value\": \"is a simple function for comparing two values\",\n", - " \"check_contains\": \"confirms that all the elements of one iterable are contained in the other\",\n", - " \"check_args\": \"gets the signature of a function and compares it to the arguments you are expecting\",\n", - " \"run_command_no_file_error\": \"executes a CLI command but won't fail if a FileNotFoundError is raised\",\n", + " 'check_value': 'is a simple function for comparing two values',\n", + " 'check_contains': 'confirms that all the elements of one iterable are contained in the other',\n", + " 'check_args': 'gets the signature of a function and compares it to the arguments you are expecting',\n", + " 'run_command_no_file_error': \"executes a CLI command but won't fail if a FileNotFoundError is raised\",\n", "}\n", "glue_functions = {\n", - " \"glue_variable\": \"Glue a variable for later use in markdown cells of notebooks (can auto format for code)\",\n", - " \"glue_keys\": \"recursively glue all of the keys from a dict of dicts\",\n", + " 'glue_variable': 'glue a variable for later use in markdown cells of notebooks (can auto format for code)',\n", + " 'glue_keys': 'recursively glue all of the keys from a dict of dicts',\n", + " 'glue_actions': 'glue all Aviary CLI options for a given command',\n", + " 'glue_class_functions': 'glue all class functions for a gen class',\n", + " 'glue_function_arguments': 'glue all function arguments and default for a given function',\n", + " 'glue_class_options': 'glue all class options for a given class',\n", "}\n", "utility_functions = {\n", - " \"gramatical_list\": \"combines the elements of a list into a string with proper punctuation\",\n", - " \"get_variable_name\": \"returns the name of the variable passed to the function as a string\",\n", - " \"get_previous_line\": \"returns the previous line of code as a string\",\n", - " \"get_attribute_name\": \"gets the name of an object's attribute based on it's value\",\n", - " \"get_all_keys\": \"recursively get all of the keys from a dict of dicts\",\n", - " \"get_value\": \"recursively get a value from a dict of dicts\",\n", + " 'gramatical_list': 'combines the elements of a list into a string with proper punctuation',\n", + " 'get_variable_name': 'returns the name of the variable passed to the function as a string',\n", + " 'get_previous_line': 'returns the previous line of code as a string',\n", + " 'get_attribute_name': \"gets the name of an object's attribute based on it's value\",\n", + " 'get_all_keys': 'recursively get all of the keys from a dict of dicts',\n", + " 'get_value': 'recursively get a value from a dict of dicts',\n", + " 'get_class_names': 'gets all class names from a given file and return as a set',\n", + " 'get_function_names': 'gets all function names in a given file and return as a set',\n", + " 'get_all_non_aviary_names': 'gets names of all the non-Aviary variables of a component as a list',\n", "}\n", "\n", - "doctape.check_value(imported_classes.keys(),custom_classes.keys())\n", - "doctape.check_value(imported_functions.keys(), {\n", - " **testing_functions, **glue_functions, **utility_functions}.keys())\n", + "# make sure all classes and functions are listed here with descriptions.\n", + "doctape.check_value(imported_classes.keys(), custom_classes.keys())\n", + "doctape.check_value(\n", + " imported_functions.keys(), {**testing_functions, **glue_functions, **utility_functions}.keys()\n", + ")\n", "\n", "class_list = ''\n", - "for key,val in custom_classes.items():\n", + "for key, val in custom_classes.items():\n", " doctape.glue_variable(key, md_code=True)\n", " class_list += f'- `{key}` {val}\\n'\n", "\n", - "# testing_list = ''\n", - "# for key,val in testing_functions.items():\n", - "# testing_list += f'- `{key}` {val}\\n'\n", - "\n", "utility_list = '```{eval-rst}\\n'\n", "for key in utility_functions:\n", " doctape.glue_variable(key, md_code=True)\n", - " utility_list += ' '*4+f'.. autofunction:: aviary.utils.doctape.{key}\\n{\" \"*8}:noindex:\\n\\n'\n", + " utility_list += (\n", + " ' ' * 4 + f'.. autofunction:: aviary.utils.doctape.{key}\\n{\" \" * 8}:noindex:\\n\\n'\n", + " )\n", "utility_list += '```'\n", "\n", - "# testing_list = '```{eval-rst}\\n'\n", - "# for key in testing_functions:\n", - "# utils.glue_variable(key, md_code=True)\n", - "# testing_list += ' '*4+f'.. autofunction:: aviary.utils.doctape.{key}\\n{\" \"*8}:noindex:\\n\\n'\n", - "# testing_list += '```'\n", - "\n", - "# testing_list = '
\\n\\nFunction Docs\\n\\n'\n", "testing_list = '```{eval-rst}\\n'\n", "for key in testing_functions:\n", " doctape.glue_variable(key, md_code=True)\n", - " testing_list += ' '*4+f'.. autofunction:: aviary.utils.doctape.{key}\\n{\" \"*8}:noindex:\\n\\n'\n", + " testing_list += (\n", + " ' ' * 4 + f'.. autofunction:: aviary.utils.doctape.{key}\\n{\" \" * 8}:noindex:\\n\\n'\n", + " )\n", "testing_list += '```'\n", - "# testing_list += '\\n\\n
'\n", - "\n", - "# glue_list = ''\n", - "# for key,val in glue_functions.items():\n", - "# glue_list += f'- `{key}` {key}\\n'\n", - "\n", - "# glue_list = ''\n", - "# for key in glue_functions:\n", - "# # doc_str = inspect.getdoc(imported_functions[key])\n", - "# doc_str = imported_functions[key].__doc__.split('\\n')[1]\n", - "# # doc_str = '\\n'.join([s+' ' for s in imported_functions[key].__doc__.split('\\n')])\n", - "# print(doc_str)\n", - "# glue_list += f'- `{key}`: {doc_str}\\n'\n", "\n", "glue_list = '```{eval-rst}\\n'\n", "for key in glue_functions:\n", " doctape.glue_variable(key, md_code=True)\n", - " glue_list += ' '*4+f'.. autofunction:: aviary.utils.doctape.{key}\\n{\" \"*8}:noindex:\\n\\n'\n", + " glue_list += ' ' * 4 + f'.. autofunction:: aviary.utils.doctape.{key}\\n{\" \" * 8}:noindex:\\n\\n'\n", "glue_list += '```'\n", "\n", "doctape.glue_variable('class_list', class_list)\n", @@ -160,6 +167,7 @@ "source": [ "# Testing Cell\n", "import myst_nb\n", + "\n", "from aviary.utils.doctape import glue_variable\n", "\n", "glue_variable(myst_nb.__name__)\n", @@ -190,7 +198,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "base", "language": "python", "name": "python3" }, @@ -204,7 +212,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/developer_guide/doctape_examples.ipynb b/aviary/docs/developer_guide/doctape_examples.ipynb index 378bfe52eb..b9083e761c 100644 --- a/aviary/docs/developer_guide/doctape_examples.ipynb +++ b/aviary/docs/developer_guide/doctape_examples.ipynb @@ -21,10 +21,16 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils import doctape\n", "import inspect\n", "\n", - "imported_functions = {k for k,v in inspect.getmembers(doctape, inspect.isfunction) if v.__module__ == doctape.__name__}\n", + "from aviary.utils import doctape\n", + "\n", + "imported_functions = {\n", + " k\n", + " for k, v in inspect.getmembers(doctape, inspect.isfunction)\n", + " if v.__module__ == doctape.__name__\n", + "}\n", + "# We prepare all function names for using in the current page (before or later)\n", "for func in imported_functions:\n", " doctape.glue_variable(func, md_code=True)\n", "doctape.glue_variable(doctape.expected_error.__name__, md_code=True)" @@ -46,7 +52,8 @@ "metadata": {}, "outputs": [], "source": [ - "from aviary.utils.doctape import expected_error, check_value\n", + "from aviary.utils.doctape import check_value, expected_error\n", + "\n", "try:\n", " check_value(int('1'), 2, error_type=expected_error)\n", "except expected_error:\n", @@ -71,7 +78,7 @@ }, "outputs": [], "source": [ - "from aviary.utils.doctape import expected_error, check_value\n", + "from aviary.utils.doctape import check_value, expected_error\n", "\n", "try:\n", " check_value(int('1)'), 2)\n", @@ -109,12 +116,12 @@ "metadata": {}, "outputs": [], "source": [ + "from aviary.models.missions.height_energy_default import phase_info\n", "from aviary.utils.doctape import check_value\n", - "from aviary.examples.reserve_missions.run_reserve_mission_fixedrange import phase_info\n", "\n", - "user_opts = phase_info['reserve_cruise']['user_options']\n", - "check_value(user_opts['target_distance'],(200, 'km'))\n", - "check_value(user_opts['reserve'],True)" + "user_opts = phase_info['climb']['user_options']\n", + "check_value(user_opts['altitude_final'], (32000.0, 'ft'))\n", + "check_value(user_opts['mach_optimize'], False)" ] }, { @@ -135,22 +142,25 @@ }, "outputs": [], "source": [ - "from aviary.utils.doctape import check_contains\n", - "import aviary.api as av\n", "import os\n", "\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import check_contains\n", + "\n", "off_design_examples = av.get_path(os.path.join('examples'))\n", "check_contains(\n", " ('run_off_design_example.py'),\n", " os.listdir(off_design_examples),\n", - " error_string=\"{var} not in \"+str(off_design_examples),\n", - " error_type=FileNotFoundError)\n", + " error_string='{var} not in ' + str(off_design_examples),\n", + " error_type=FileNotFoundError,\n", + ")\n", "print('This file exists and does not raise any errors')\n", "check_contains(\n", " ('made_up_file.py'),\n", " os.listdir(off_design_examples),\n", - " error_string=\"{var} not in \"+str(off_design_examples),\n", - " error_type=FileNotFoundError)\n", + " error_string='{var} not in ' + str(off_design_examples),\n", + " error_type=FileNotFoundError,\n", + ")\n", "print('This file does not exist, so we will not reach this point')" ] }, @@ -178,12 +188,12 @@ "from aviary.utils.doctape import check_args, check_contains, glue_variable\n", "\n", "default_error = RuntimeError\n", - "check_args(check_contains, {'error_type':default_error}, exact=False)\n", + "check_args(check_contains, {'error_type': default_error}, exact=False)\n", "glue_variable('default_error', default_error.__name__)\n", "\n", "exact_arg = 'exact'\n", "check_args(check_args, exact_arg)\n", - "glue_variable(exact_arg, md_code=True)\n" + "glue_variable(exact_arg, md_code=True)" ] }, { @@ -208,6 +218,7 @@ "source": [ "# Testing Cell\n", "from aviary.utils.doctape import run_command_no_file_error\n", + "\n", "command = \"\"\"\n", " aviary run_mission --optimizer IPOPT --phase_info outputted_phase_info.py \n", " validation_cases/benchmark_tests/test_aircraft/aircraft_for_bench_FwFm.csv\n", @@ -235,6 +246,7 @@ "source": [ "# Testing Cell\n", "import myst_nb\n", + "\n", "from aviary.utils.doctape import glue_variable\n", "\n", "glue_variable(myst_nb.__name__)\n", @@ -259,7 +271,7 @@ "### {glue:md}`glue_variable`\n", "allows users to specify a value that is {glue:}`something different than` what is displayed, but defaults to using the name of the variable if nothing is specified. This makes adapting old documentation easier, because users can just wrap {glue:}`the entire phrase they want to replace`.\n", "\n", - "Glued text can either be {glue:md}`plain text` or can be formatted as {glue:md}`inline code`\n" + "Glued text can either be {glue:md}`plain text` or can be formatted as {glue:md}`inline code`. Note that the variables in this context do not have the same naming restrictions as Python variables, they can contain spaces or start with a number.\n" ] }, { @@ -277,7 +289,7 @@ "\n", "glue_variable('plain text')\n", "glue_variable('inline code', md_code=True)\n", - "glue_variable('something different than','not the same as')\n", + "glue_variable('something different than', 'not the same as')\n", "glue_variable('the entire phrase they want to replace')" ] }, @@ -303,10 +315,10 @@ "from aviary.utils.doctape import glue_keys\n", "\n", "simplified_dict = {\n", - " 'phase1':{'altitude':{'val':30,'units':'kft'},'mach':.4},\n", - " 'phase2':{'altitude':{'val':10,'units':'km'},'mach':.5}\n", - " }\n", - "glue_keys(simplified_dict)\n" + " 'phase1': {'altitude': {'val': 30, 'units': 'kft'}, 'mach': 0.4},\n", + " 'phase2': {'altitude': {'val': 10, 'units': 'km'}, 'mach': 0.5},\n", + "}\n", + "glue_keys(simplified_dict)" ] }, { @@ -337,12 +349,12 @@ "from aviary.utils.doctape import gramatical_list\n", "\n", "single_element = gramatical_list([1])\n", - "two_elements = gramatical_list(['apples','bananas'])\n", - "three_elements_with_or = gramatical_list(['apples','bananas', 'strawberries'],'or')\n", + "two_elements = gramatical_list(['apples', 'bananas'])\n", + "three_elements_with_or = gramatical_list(['apples', 'bananas', 'strawberries'], 'or')\n", "\n", - "print(f\"I would like to order {single_element} smoothie.\")\n", - "print(f\"Do you want {three_elements_with_or} in your smoothie?\")\n", - "print(f\"I only want {two_elements}.\")" + "print(f'I would like to order {single_element} smoothie.')\n", + "print(f'Do you want {three_elements_with_or} in your smoothie?')\n", + "print(f'I only want {two_elements}.')" ] }, { @@ -367,8 +379,8 @@ }, "outputs": [], "source": [ - "from aviary.utils.doctape import get_variable_name, glue_variable\n", "from aviary.api import AviaryProblem\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", "\n", "glue_variable('function_name', get_variable_name(get_variable_name))\n", "glue_variable(get_variable_name(print))\n", @@ -407,26 +419,26 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.api import Mission\n", - "from aviary.utils.doctape import glue_variable, get_previous_line, get_variable_name\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_previous_line, get_variable_name, glue_variable\n", "\n", - "glue_variable('value', Mission.Design.MACH, md_code=True)\n", + "glue_variable('value', Aircraft.Design.EMPTY_MASS, md_code=True)\n", "glue_variable('var_value_code', get_previous_line(), md_code=True)\n", - "glue_variable(get_variable_name(Mission.Design.MACH), md_code=True)\n", - "glue_variable('var_name_code', get_previous_line(), md_code=True)\n" + "glue_variable(get_variable_name(Aircraft.Design.EMPTY_MASS), md_code=True)\n", + "glue_variable('var_name_code', get_previous_line(), md_code=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "If you want to glue the name of a variable, instead of the value that variable holds, you can use the {glue:md}`get_variable_name` to extract it.\n", + "If you want to glue the name of a variable, instead of the value that variable holds, you can use the {glue:md}`get_variable_name` function to extract it.\n", "\n", "For example:\n", - "Using {glue:md}`var_value_code` will result in {glue:md}`value`, whereas using {glue:md}`var_name_code` will result in {glue:md}`Mission.Design.MACH`\n", + "Using {glue:md}`var_value_code` will result in {glue:md}`value`, whereas using {glue:md}`var_name_code` will result in {glue:md}`Aircraft.Design.EMPTY_MASS`\n", "\n", "### {glue:md}`get_attribute_name`\n", - "allows users to get the name of object attributes in order to glue them into documentation. This works well for Enums or Class Variables that have unique values." + "allows users to get the name of object attributes in order to glue them into documentation. This works well for Enums or Class variables that have unique values." ] }, { @@ -439,9 +451,9 @@ }, "outputs": [], "source": [ + "import aviary.api as av\n", "from aviary.api import LegacyCode\n", "from aviary.utils.doctape import get_attribute_name, glue_variable\n", - "import aviary.api as av\n", "\n", "some_custom_alias = av.LegacyCode\n", "\n", @@ -471,9 +483,9 @@ "from aviary.utils.doctape import get_all_keys, get_value\n", "\n", "simplified_dict = {\n", - " 'phase1':{'altitude':{'val':30,'units':'kft'},'mach':.4},\n", - " 'phase2':{'altitude':{'val':10,'units':'km'},'mach':.5}\n", - " }\n", + " 'phase1': {'altitude': {'val': 30, 'units': 'kft'}, 'mach': 0.4},\n", + " 'phase2': {'altitude': {'val': 10, 'units': 'km'}, 'mach': 0.5},\n", + "}\n", "unique_keys_only = get_all_keys(simplified_dict)\n", "all_keys = get_all_keys(simplified_dict, track_layers=True)\n", "print(unique_keys_only)\n", @@ -482,11 +494,76 @@ "p1_alt = get_value(simplified_dict, 'phase1.altitude.val')\n", "print(p1_alt)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.api import Aircraft, Mission\n", + "from aviary.utils.doctape import check_args, get_all_keys, get_previous_line, glue_variable\n", + "\n", + "glue_variable(Aircraft.__name__)\n", + "glue_variable(Mission.__name__)\n", + "\n", + "track_layers = 'track_layers'\n", + "check_args(get_all_keys, track_layers)\n", + "glue_variable(track_layers)\n", + "\n", + "get_all_keys(Mission, track_layers='Mission')\n", + "track_layers_with_name = get_previous_line().split(', ')[1].split(')')[0]\n", + "glue_variable('track_layers_with_Mission', track_layers_with_name, display=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These can also be used to recursively get all of the attributes from a complex object, like the {glue:md}`Aircraft` or {glue:md}`Mission` hierarchies.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from aviary.api import Mission\n", + "from aviary.utils.doctape import get_all_keys, get_value, glue_keys\n", + "\n", + "k1 = get_all_keys(Mission)\n", + "print(k1[:5]) # Display the first 5 keys in Mission\n", + "k2 = get_all_keys(Mission, track_layers=True)\n", + "print(k2[:5]) # Display the first 5 keys in Mission\n", + "k3 = get_all_keys(Mission, track_layers='Mission')\n", + "print(k3[:5]) # Display the first 5 keys in Mission\n", + "\n", + "glue_keys(Mission, False)\n", + "\n", + "print(get_value(Mission, 'Constraints.GEARBOX_SHAFT_POWER_RESIDUAL'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If {glue:md}`get_all_keys` is used on an object like {glue:md}`Mission` without specifying a value for {glue:md}`track_layers` will return all of the uniquely named attributes of the object (such as `GEARBOX_SHAFT_POWER_RESIDUAL`). Setting {glue:md}`track_layers` to `True` will get all of the attributes in dot notation, but will not include the name of the original object (`Constraints.GEARBOX_SHAFT_POWER_RESIDUAL`). If you want the full name of the attribute, including the name of the original object, you can use that name as the value of {glue:md}`track_layers` (using {glue:md}`track_layers_with_Mission` gives us access to {glue:md}`Mission.Constraints.GEARBOX_SHAFT_POWER_RESIDUAL`)\n", + "\n", + "Using {glue:md}`glue_keys` handles this for us automatically by using the `__name__` attribute of the object passed to it as the value of {glue:md}`track_layers`.\n", + "\n", + "As with the dict_of_dicts, we can recusively get the value of an attribute using the full path along with {glue:md}`get_value`." + ] } ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -500,9 +577,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/developer_guide/how_to_contribute_docs.md b/aviary/docs/developer_guide/how_to_contribute_docs.md index b2517a24ca..feb947dc29 100644 --- a/aviary/docs/developer_guide/how_to_contribute_docs.md +++ b/aviary/docs/developer_guide/how_to_contribute_docs.md @@ -3,7 +3,9 @@ Doc pages can be added as `.ipynb` or `.md` files within the `aviary/docs` folder. We're using [jupyter-book](https://jupyterbook.org/) for the docs, which is a well-documented and full-featured platform. To build the docs, you'll need to install jupyter-book following [these instructions](https://jupyterbook.org/en/stable/start/overview.html). -Jupyter-book allows for arbitrary Jupyter notebook usage to intersperse code and documentation and it uses [MyST markdown](https://jupyterbook.org/en/stable/content/myst.html). +Jupyter-book allows for arbitrary Jupyter notebook usage to intersperse code and documentation and it uses [MyST markdown](https://jupyterbook.org/en/stable/content/myst.html). + +Whenever a page contains code, it should be a Jupyter notebook. Otherwise, you can write it as markdown page. Note that if you run an optimiser in a Jupyter notebook, don't use `SNOPT` because it is not available in test run on Github. Also, if you plan to push a Jupyter notebook to the Aviary repository, make sure you run `reset_notebook` on that page. To modify the docs, simply add a file to the repo within the docs folder. You can then add it to the `docs/_toc.yml` file following the structure for the skeletal outline. diff --git a/aviary/docs/developer_guide/unit_tests.md b/aviary/docs/developer_guide/unit_tests.md index ae3e42989c..2db94834b4 100644 --- a/aviary/docs/developer_guide/unit_tests.md +++ b/aviary/docs/developer_guide/unit_tests.md @@ -27,7 +27,8 @@ Ran 888 tests using 16 processes Wall clock time: 00:00:54.15 ``` -## Current Unit Tests +## Writing Unit Tests +To write your own unittests, you should use the following utilities. ### assert_near_equal @@ -61,7 +62,7 @@ assert_check_partials(data, atol=1e-06, rtol=1e-06) This assert makes sure that the computed derivatives in the code match those computed numerically within the given absolute and relative tolerances. In Aviary, there are two ways to compute a component's derivatives: analytically or numerically. When the derivatives are analytic, it is best practice to use `check_partials` to compare them against the complex step (`cs`) or finite difference (`fd`) estimates. -Complex step is much more acurate, but all code in your component's `compute` method must be complex-safe to use this -- in other words, no calculation that squelches the imaginary part of the calculation (like `abs`.) +Complex step is much more accurate, but all code in your component's `compute` method must be complex-safe to use this -- in other words, no calculation that squelches the imaginary part of the calculation (like `abs`.) Note that there are some complex-safe alternatives to commonly-used calculations in the openmdao library. If your code is not complex-safe, or it wraps an external component that doesn't support complex numbers, then finite difference should be used. If your component computes its derivatives numerically, there is less reason to test it because you are testing one numerical method against another. If you choose to do this, you will need to use a different method, form, or step. @@ -72,7 +73,7 @@ data = prob.check_partials(out_stream=None, method="cs", step=1.01e-40) assert_check_partials(data, atol=1e-06, rtol=1e-06) ``` -Although the default method of `check_partials` is `fd` (finite difference), we prefer `cs` ([complex step](https://openmdao.org/newdocs/versions/latest/advanced_user_guide/complex_step.html) because it usally gives more accurate results. +Although the default method of `check_partials` is `fd` (finite difference), we prefer `cs` ([complex step](https://openmdao.org/newdocs/versions/latest/advanced_user_guide/complex_step.html) because it usually gives more accurate results. ````{margin} ```{note} @@ -122,4 +123,4 @@ Add a new file to this directory with the name `test_.py` where `< Within this file, add a class called `Test` that inherits from `unittest.TestCase`. Within this class, add a method called `test_` where `` is the name of the test you're adding. -Do not write docstrings to unit test methods as we explain in [Guidelines for Contributing Code](contributing_guidelines.md). +Do not write docstrings for unittest methods, as they interfere with printouts while running testflo. diff --git a/aviary/docs/examples/OAS_subsystem.ipynb b/aviary/docs/examples/OAS_subsystem.ipynb index 712eb63d1f..555fd608d4 100644 --- a/aviary/docs/examples/OAS_subsystem.ipynb +++ b/aviary/docs/examples/OAS_subsystem.ipynb @@ -12,12 +12,13 @@ "source": [ "# Testing Cell\n", "import openmdao.api as om\n", + "\n", "from aviary.utils.doctape import check_args, glue_variable\n", + "\n", "group = om.Group()\n", - "promotes_inputs='promotes_inputs'\n", - "check_args(group.add_subsystem,promotes_inputs)\n", - "glue_variable(promotes_inputs, md_code=True)\n", - "\n" + "promotes_inputs = 'promotes_inputs'\n", + "check_args(group.add_subsystem, promotes_inputs)\n", + "glue_variable(promotes_inputs, md_code=True)" ] }, { @@ -29,14 +30,14 @@ "This is an example of an external subsystem using the [OpenAeroStruct (OAS)](https://github.com/mdolab/OpenAeroStruct) structural analysis system to perform aerostructural optimization of a typical large single aisle transport aircraft wing.\n", "The subsystem is based on the [OpenAeroStruct aerostructural optimization with wingbox](https://mdolab-openaerostruct.readthedocs-hosted.com/en/latest/aerostructural_wingbox_walkthrough.html) example problem.\n", "\n", - "This example performs a sub-optimization for minimum wing weight that is then used by Aviary.\n", + "This example performs a sub-optimization for minimum wing mass that is then used by Aviary.\n", "Another use case would be to perform a structural analysis only.\n", - "Structural design variables would be passed to the subsystem from Aviary and wing weight and a constraint or constraints representing the structural analysis would be passed back to Aviary for use by the top level optimization.\n", + "Structural design variables would be passed to the subsystem from Aviary and wing mass and a constraint or constraints representing the structural analysis would be passed back to Aviary for use by the top level optimization.\n", "\n", "## Motivation\n", "\n", - "There may be a need for a higher fidelity tool to compute wing weight instead of relying on the empirical methods in core Aviary.\n", - "A structural analysis external tool is usually used because of an unusual aircraft configuration that may not be predicted my Aviary empirical weight estimation methods, but in this example case it is simply a demonstration of an external capability to compute wing weight.\n", + "There may be a need for a higher fidelity tool to compute wing mass instead of relying on the empirical methods in core Aviary.\n", + "A structural analysis external tool is usually used because of an unusual aircraft configuration that may not be predicted my Aviary empirical mass estimation methods, but in this example case it is simply a demonstration of an external capability to compute wing mass.\n", "\n", "## External Dependencies\n", "\n", @@ -49,15 +50,15 @@ "The analysis tool takes inputs and parameters from Aviary and return outputs that Aviary can use to override existing variables.\n", "The subsystem builder uses the Aviary external subsystem builder template to connect the analysis tool to Aviary as either a pre-mission, mission or post-mission subsystem.\n", "\n", - "For this case, the analysis tool will compute a wing weight in the pre-mission portion of the Aviary analysis and return its value to Aviary to override the empirical wing weight value.\n", - "Fuel weight is passed in from Aviary as the only input currently, but other inputs may also be passed in through the subsystem builder, [OAS_wing_weight_builder](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_builder.py), by the {glue:md}`promotes_inputs` parameter.\n", + "For this case, the analysis tool will compute a wing mass in the pre-mission portion of the Aviary analysis and return its value to Aviary to override the empirical wing mass value.\n", + "Fuel mass is passed in from Aviary as the only input currently, but other inputs may also be passed in through the subsystem builder, [OAS_wing_mass_builder](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_builder.py), by the {glue:md}`promotes_inputs` parameter.\n", "Other Aviary variables can also be added as additional inputs based on user needs.\n", "\n", "```{note}\n", - "Some modifications of the [OAS_wing_weight_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py) code will be necessary to add new inputs not already defined.\n", + "Some modifications of the [OAS_wing_mass_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py) code will be necessary to add new inputs not already defined.\n", "```\n", "\n", - "Here is the builder object for the OAS wing weight analysis example:" + "Here is the builder object for the OAS wing mass analysis example:" ] }, { @@ -66,22 +67,23 @@ "metadata": {}, "outputs": [], "source": [ - "# %load ../../examples/external_subsystems/OAS_weight/OAS_wing_weight_builder.py\n", + "# %load ../../examples/external_subsystems/OAS_mass/OAS_wing_mass_builder.py\n", "\"\"\"\n", "Builder for an OpenAeroStruct component that computes a new wing mass.\n", "\n", "\"\"\"\n", "import openmdao.api as om\n", + "\n", "import aviary.api as av\n", - "from aviary.examples.external_subsystems.OAS_weight.OAS_wing_weight_analysis import OAStructures\n", + "from aviary.examples.external_subsystems.OAS_mass.OAS_wing_mass_analysis import OAStructures\n", "\n", "\n", - "class OASWingWeightBuilder(av.SubsystemBuilderBase):\n", - " def __init__(self, name='wing_weight'):\n", + "class OASWingmassBuilder(av.SubsystemBuilderBase):\n", + " def __init__(self, name='wing_mass'):\n", " super().__init__(name)\n", "\n", " def build_pre_mission(self, aviary_inputs):\n", - " '''\n", + " \"\"\"\n", " Build an OpenMDAO system for the pre-mission computations of the subsystem.\n", "\n", " Returns\n", @@ -90,23 +92,25 @@ " An OpenMDAO system containing all computations that need to happen in\n", " the pre-mission part of the Aviary problem. This\n", " includes sizing, design, and other non-mission parameters.\n", - " '''\n", - "\n", + " \"\"\"\n", " wing_group = om.Group()\n", - " wing_group.add_subsystem(\"aerostructures\",\n", - " OAStructures(\n", - " symmetry=True,\n", - " wing_weight_ratio=1.0,\n", - " S_ref_type='projected',\n", - " n_point_masses=1,\n", - " num_twist_cp=4,\n", - " num_box_cp=51),\n", - " promotes_inputs=[\n", - " ('fuel', av.Mission.Design.FUEL_MASS),\n", - " ],\n", - " promotes_outputs=[('wing_weight', av.Aircraft.Wing.MASS)])\n", - "\n", - " return wing_group\n" + " wing_group.add_subsystem(\n", + " 'aerostructures',\n", + " OAStructures(\n", + " symmetry=True,\n", + " wing_weight_ratio=1.0,\n", + " S_ref_type='projected',\n", + " n_point_masses=1,\n", + " num_twist_cp=4,\n", + " num_box_cp=51,\n", + " ),\n", + " promotes_inputs=[\n", + " ('fuel', av.Mission.Summary.FUEL_MASS),\n", + " ],\n", + " promotes_outputs=[('wing_mass', av.Aircraft.Wing.MASS)],\n", + " )\n", + "\n", + " return wing_group" ] }, { @@ -121,9 +125,7 @@ "source": [ "# Testing Cell\n", "from aviary.api import Aircraft\n", - "from aviary.examples.external_subsystems.OAS_weight.run_simple_OAS_mission import use_OAS\n", - "from aviary.examples.external_subsystems.OAS_weight.OAS_wing_weight_analysis import OAStructures\n", - "from aviary.utils.doctape import glue_variable, glue_keys, get_variable_name\n", + "from aviary.utils.doctape import get_variable_name, glue_keys, glue_variable\n", "\n", "glue_variable(OAStructures.__qualname__, md_code=True)\n", "o = OAStructures()\n", @@ -135,6 +137,7 @@ "for key in o.options._dict:\n", " options_list += f'- {key}\\n'\n", "glue_variable('options_list', options_list, display=False)\n", + "# make all option keys available for later use (e.g. wing_weight_ratio below)\n", "glue_keys(o.options._dict, display=False)\n", "\n", "inputs_list = ''\n", @@ -147,11 +150,7 @@ " outputs_list += f'- {key}\\n'\n", "glue_variable('outputs_list', outputs_list, display=False)\n", "\n", - "glue_variable(get_variable_name(Aircraft.Wing.MASS), md_code=True)\n", - "oas = f'{use_OAS=}'.split('=')[0]\n", - "glue_variable(oas, md_code=True)\n", - "glue_variable(oas+'=False', md_code=True)\n", - "glue_variable(oas+'=True', md_code=True)" + "glue_variable(get_variable_name(Aircraft.Wing.MASS), md_code=True)" ] }, { @@ -160,8 +159,8 @@ "source": [ "## Analysis Model Details\n", "\n", - "This analysis is based on the Aviary benchmark [aircraft_for_bench_FwFm](https://github.com/OpenMDAO/Aviary/blob/main/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv) input data representing a typical large single aisle class transport aircraft.\n", - "The analysis code [OAS_wing_weight_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py) contains the {glue:md}`OAStructures` class which performs a structural analysis of the wing. The image below shows a simplified XDSM diagram of the pre-mission data flow in this example.\n", + "This analysis is based on the Aviary benchmark [aircraft_for_bench_FwFm](https://github.com/OpenMDAO/Aviary/blob/main/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv) input data representing a typical large single aisle class transport aircraft.\n", + "The analysis code [OAS_wing_mass_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py) contains the {glue:md}`OAStructures` class which performs a structural analysis of the wing. The image below shows a simplified XDSM diagram of the pre-mission data flow in this example.\n", "\n", "![OAS XDSM](images/OAS_xdsm.PNG)\n", "\n", @@ -175,10 +174,10 @@ "We then set initial values for the wing skin thickness and spar thickness are set, along with material properties and stress allowables for a metal material, typically aluminum.\n", "OpenAeroStruct will then calculate aeroelastic loads for a 2.5g maneuver condition and apply those loads to the finite element model of the wing structure.\n", "\n", - "Results of the structural optimization determine the optimum wing skin thickness, spar cap thickness, wing twist, wing t/c and maneuver angle of attack that satisfies strength constraints while minimizing wing weight.\n", + "Results of the structural optimization determine the optimum wing skin thickness, spar cap thickness, wing twist, wing t/c and maneuver angle of attack that satisfies strength constraints while minimizing wing mass.\n", "The 'OAStructures' class returns the optimized wing mass and the fuel mass burned but currently only the wing mass is used to override the Aviary variable 'Aircraft.Wing.MASS'.\n", "\n", - "The [OAS_wing_weight_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py) code may be executed in Python to test the OpenAeroStruct analysis outside of the Aviary subsystem interface.\n", + "The [OAS_wing_mass_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py) code may be executed in Python to test the OpenAeroStruct analysis outside of the Aviary subsystem interface.\n", "Default values for each of the inputs and options are included at the bottom of the analysis code file.\n", "This can be a useful test to demonstrate that the OpenAeroStruct analysis model has been properly defined and the model returns reasonable results.\n", "\n", @@ -208,7 +207,7 @@ ":format: myst\n", "```\n", "\n", - "See [OAS_wing_weight_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py) and the [OpenAeroStruct aerostructural optimization with wingbox](https://mdolab-openaerostruct.readthedocs-hosted.com/en/latest/aerostructural_wingbox_walkthrough.html) documentation for descriptions of these variables." + "See [OAS_wing_mass_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py) and the [OpenAeroStruct aerostructural optimization with wingbox](https://mdolab-openaerostruct.readthedocs-hosted.com/en/latest/aerostructural_wingbox_walkthrough.html) documentation for descriptions of these variables." ] }, { @@ -217,228 +216,28 @@ "source": [ "## Test Case\n", "\n", - "A simple Aviary mission is defined to test the inclusion of the OpenAeroStruct wing weight subsystem during the pre-mission phase.\n", - "The test mission is defined in [run_simple_OAS_mission](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS/run_simple_OAS_mission.py) and is a mission based on input data read from the benchmark data file [aircraft_for_bench_FwFm](https://github.com/OpenMDAO/Aviary/blob/main/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv).\n", + "A simple Aviary mission is defined to test the inclusion of the OpenAeroStruct wing mass subsystem during the pre-mission phase.\n", + "The test mission is defined in [run_simple_OAS_mission](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_mass/run_simple_OAS_mission.py) and is a mission based on input data read from the benchmark data file [aircraft_for_bench_FwFm](https://github.com/OpenMDAO/Aviary/blob/main/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv).\n", "\n", "The OpenAeroStruct subsystem is used to compute an optimum wing mass which will override the Aviary computed wing mass value.\n", - "The value of the Aviary variable {glue:md}`Aircraft.Wing.MASS` is printed at the conclusion of the mission to verify that the wing weight from the subsystem is overriding the Aviary computed wing weight.\n", - "\n", - "A variable in the [run_simple_OAS_mission](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS/run_simple_OAS_mission.py) file named {glue:md}`use_OAS` may be set by the user to `True` or `False` to run the simple mission with or without the OpenAeroStruct subsystem included.\n", - "This will allow the mission to be flown either using the Aviary empirical wing weight estimation ({glue:md}`use_OAS=False`) or with the OpenAeroStruct subsystem ({glue:md}`use_OAS=True`)." + "The value of the Aviary variable {glue:md}`Aircraft.Wing.MASS` is printed at the conclusion of the mission to verify that the wing mass from the subsystem is overriding the Aviary computed wing mass." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Wing weight optimization of this type usually does not have knowledge of non-optimum wing mass values such as leading and training edge structure, actuators, stiffeners, etc.\n", - "The optimum wing mass computed by the {glue:md}`OAStructures` class can be scaled using the option {glue:md}`wing_weight_ratio` to better match either the Aviary empirical wing weight value or a known fly-away weight estimate for your wing model.\n", - "One method to determine the wing_weight_ratio would be to run the mission to calculate the Aviary empirical wing weight and then run [OAS_wing_weight_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py) by itself using its default input values and compare wing weights. The {glue:md}`wing_weight_ratio` value may then be set to calibrate the OpenAeroStruct wing weight to the expected fly-away weight.\n", - "\n", - "This calibration step has already been performed for this model, so the user may run the simple mission with or without the OpenAeroStruct subsystem active and compare the results.\n", - "\n", - "## Example Run Script\n", - "\n", - "Here is the full run script used to run the simple mission with the OpenAeroStruct subsystem active.\n", - "This run script is also available in the [run_simple_OAS_mission file.](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py)\n", - "\n", + "Wing mass optimization of this type usually does not have knowledge of non-optimum wing mass values such as leading and training edge structure, actuators, stiffeners, etc.\n", + "The optimum wing mass computed by the {glue:md}`OAStructures` class can be scaled using the option {glue:md}`wing_weight_ratio` to better match either the Aviary empirical wing mass value or a known fly-away mass estimate for your wing model.\n", + "One method to determine the wing_weight_ratio would be to run the mission to calculate the Aviary empirical wing mass and then run [OAS_wing_mass_analysis](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py) by itself using its default input values and compare wing masss. The {glue:md}`wing_weight_ratio` value may then be set to calibrate the OpenAeroStruct wing mass to the expected fly-away mass.\n", "\n", - "```{note}\n", - "We do not actually perform the optimization below.\n", - "Instead, we define and set up the model and the call to run the optimization is commented you.\n", - "You can uncomment this and run the code block to perform a full optimization.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# %load ../../examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py\n", - "'''\n", - "This is a simple test mission to demonstrate the inclusion of a\n", - "pre-mission user defined external subsystem. The simple mission\n", - "is based on input data read from the benchmark data file bench_4.csv,\n", - "which represents a single-aisle commercial transport aircraft. The\n", - "OpenAeroStruct (OAS) subsystem is used to compute an optimum wing\n", - "mass which will override the Aviary computed wing mass value.\n", - "\n", - "The flag 'use_OAS' is set to 'True' to include the OAS subsystem in\n", - "the mission, or set to 'False' to run the mission without the\n", - "subsystem so that wing mass values between the 2 methods may be\n", - "compared.\n", - "\n", - "'''\n", - "\n", - "import numpy as np\n", - "import openmdao.api as om\n", - "import aviary.api as av\n", - "from aviary.examples.external_subsystems.OAS_weight.OAS_wing_weight_builder import OASWingWeightBuilder\n", - "\n", - "# flag to turn on/off OpenAeroStruct subsystem for comparison testing\n", - "use_OAS = True\n", - "\n", - "wing_weight_builder = OASWingWeightBuilder()\n", - "\n", - "# Load the phase_info and other common setup tasks\n", - "phase_info = {\n", - " 'climb_1': {\n", - " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", - " 'user_options': {\n", - " 'optimize_mach': False,\n", - " 'optimize_altitude': False,\n", - " 'polynomial_control_order': 1,\n", - " 'num_segments': 5,\n", - " 'order': 3,\n", - " 'solve_for_distance': False,\n", - " 'initial_mach': (0.2, 'unitless'),\n", - " 'final_mach': (0.72, 'unitless'),\n", - " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", - " 'initial_altitude': (0.0, 'ft'),\n", - " 'final_altitude': (32000.0, 'ft'),\n", - " 'altitude_bounds': ((0.0, 34000.0), 'ft'),\n", - " 'throttle_enforcement': 'path_constraint',\n", - " 'fix_initial': True,\n", - " 'constrain_final': False,\n", - " 'fix_duration': False,\n", - " 'initial_bounds': ((0.0, 0.0), 'min'),\n", - " 'duration_bounds': ((64.0, 192.0), 'min'),\n", - " },\n", - " 'initial_guesses': {'time': ([0, 128], 'min')},\n", - " },\n", - " 'climb_2': {\n", - " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", - " 'user_options': {\n", - " 'optimize_mach': False,\n", - " 'optimize_altitude': False,\n", - " 'polynomial_control_order': 1,\n", - " 'num_segments': 5,\n", - " 'order': 3,\n", - " 'solve_for_distance': False,\n", - " 'initial_mach': (0.72, 'unitless'),\n", - " 'final_mach': (0.72, 'unitless'),\n", - " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", - " 'initial_altitude': (32000.0, 'ft'),\n", - " 'final_altitude': (34000.0, 'ft'),\n", - " 'altitude_bounds': ((23000.0, 38000.0), 'ft'),\n", - " 'throttle_enforcement': 'boundary_constraint',\n", - " 'fix_initial': False,\n", - " 'constrain_final': False,\n", - " 'fix_duration': False,\n", - " 'initial_bounds': ((64.0, 192.0), 'min'),\n", - " 'duration_bounds': ((56.5, 169.5), 'min'),\n", - " },\n", - " 'initial_guesses': {'time': ([128, 113], 'min')},\n", - " },\n", - " 'descent_1': {\n", - " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", - " 'user_options': {\n", - " 'optimize_mach': False,\n", - " 'optimize_altitude': False,\n", - " 'polynomial_control_order': 1,\n", - " 'num_segments': 5,\n", - " 'order': 3,\n", - " 'solve_for_distance': False,\n", - " 'initial_mach': (0.72, 'unitless'),\n", - " 'final_mach': (0.36, 'unitless'),\n", - " 'mach_bounds': ((0.34, 0.74), 'unitless'),\n", - " 'initial_altitude': (34000.0, 'ft'),\n", - " 'final_altitude': (500.0, 'ft'),\n", - " 'altitude_bounds': ((0.0, 38000.0), 'ft'),\n", - " 'throttle_enforcement': 'path_constraint',\n", - " 'fix_initial': False,\n", - " 'constrain_final': True,\n", - " 'fix_duration': False,\n", - " 'initial_bounds': ((120.5, 361.5), 'min'),\n", - " 'duration_bounds': ((29.0, 87.0), 'min'),\n", - " },\n", - " 'initial_guesses': {'time': ([241, 58], 'min')},\n", - " },\n", - " 'post_mission': {\n", - " 'include_landing': False,\n", - " 'constrain_range': True,\n", - " 'target_range': (1800., 'nmi'),\n", - " },\n", - "}\n", - "\n", - "phase_info['pre_mission'] = {'include_takeoff': False, 'optimize_mass': True}\n", - "if use_OAS:\n", - " phase_info['pre_mission']['external_subsystems'] = [wing_weight_builder]\n", - "\n", - "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", - "mission_method = 'simple'\n", - "mass_method = 'FLOPS'\n", - "make_plots = False\n", - "max_iter = 100\n", - "optimizer = 'IPOPT'\n", - "\n", - "prob = av.AviaryProblem()\n", - "\n", - "prob.load_inputs(aircraft_definition_file, phase_info)\n", - "prob.check_and_preprocess_inputs()\n", - "prob.add_pre_mission_systems()\n", - "prob.add_phases()\n", - "prob.add_post_mission_systems()\n", - "prob.link_phases()\n", - "prob.add_driver(optimizer=optimizer, max_iter=max_iter)\n", - "prob.add_design_variables()\n", - "prob.add_objective()\n", - "prob.setup()\n", - "\n", - "if use_OAS:\n", - " OAS_sys = 'pre_mission.wing_weight.aerostructures.'\n", - " prob.set_val(OAS_sys + 'box_upper_x', np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32,\n", - " 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]), units='unitless')\n", - " prob.set_val(OAS_sys + 'box_lower_x', np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32,\n", - " 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]), units='unitless')\n", - " prob.set_val(OAS_sys + 'box_upper_y', np.array([0.0447, 0.046, 0.0472, 0.0484, 0.0495, 0.0505, 0.0514, 0.0523, 0.0531, 0.0538, 0.0545, 0.0551, 0.0557, 0.0563, 0.0568, 0.0573, 0.0577, 0.0581, 0.0585, 0.0588, 0.0591, 0.0593, 0.0595, 0.0597,\n", - " 0.0599, 0.06, 0.0601, 0.0602, 0.0602, 0.0602, 0.0602, 0.0602, 0.0601, 0.06, 0.0599, 0.0598, 0.0596, 0.0594, 0.0592, 0.0589, 0.0586, 0.0583, 0.058, 0.0576, 0.0572, 0.0568, 0.0563, 0.0558, 0.0553, 0.0547, 0.0541]), units='unitless')\n", - " prob.set_val(OAS_sys + 'box_lower_y', np.array([-0.0447, -0.046, -0.0473, -0.0485, -0.0496, -0.0506, -0.0515, -0.0524, -0.0532, -0.054, -0.0547, -0.0554, -0.056, -0.0565, -0.057, -0.0575, -0.0579, -0.0583, -0.0586, -0.0589, -0.0592, -0.0594, -0.0595, -0.0596, -\n", - " 0.0597, -0.0598, -0.0598, -0.0598, -0.0598, -0.0597, -0.0596, -0.0594, -0.0592, -0.0589, -0.0586, -0.0582, -0.0578, -0.0573, -0.0567, -0.0561, -0.0554, -0.0546, -0.0538, -0.0529, -0.0519, -0.0509, -0.0497, -0.0485, -0.0472, -0.0458, -0.0444]), units='unitless')\n", - " prob.set_val(OAS_sys + 'twist_cp', np.array([-6., -6., -4., 0.]), units='deg')\n", - " prob.set_val(OAS_sys + 'spar_thickness_cp',\n", - " np.array([0.004, 0.005, 0.008, 0.01]), units='m')\n", - " prob.set_val(OAS_sys + 'skin_thickness_cp',\n", - " np.array([0.005, 0.01, 0.015, 0.025]), units='m')\n", - " prob.set_val(OAS_sys + 't_over_c_cp',\n", - " np.array([0.08, 0.08, 0.10, 0.08]), units='unitless')\n", - " prob.set_val(OAS_sys + 'airfoil_t_over_c', 0.12, units='unitless')\n", - " prob.set_val(OAS_sys + 'fuel', 40044.0, units='lbm')\n", - " prob.set_val(OAS_sys + 'fuel_reserve', 3000.0, units='lbm')\n", - " prob.set_val(OAS_sys + 'CD0', 0.0078, units='unitless')\n", - " prob.set_val(OAS_sys + 'cruise_Mach', 0.785, units='unitless')\n", - " prob.set_val(OAS_sys + 'cruise_altitude', 11303.682962301647, units='m')\n", - " prob.set_val(OAS_sys + 'cruise_range', 3500, units='nmi')\n", - " prob.set_val(OAS_sys + 'cruise_SFC', 0.53 / 3600, units='1/s')\n", - " prob.set_val(OAS_sys + 'engine_mass', 7400, units='lbm')\n", - " prob.set_val(OAS_sys + 'engine_location', np.array([25, -10.0, 0.0]), units='m')\n", - "\n", - "prob.set_initial_guesses()\n", - "# prob.run_aviary_problem('dymos_solution.db', make_plots=False)\n", - "# print('wing mass = ', prob.model.get_val(av.Aircraft.Wing.MASS, units='lbm'))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "from aviary.interface.utils.check_phase_info import check_phase_info, HEIGHT_ENERGY\n", - "check_phase_info(phase_info, HEIGHT_ENERGY);" + "This calibration step has already been performed for this model, so the user may run the simple mission with or without the OpenAeroStruct subsystem active and compare the results." ] } ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -452,9 +251,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.9" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/examples/additional_flight_phases.ipynb b/aviary/docs/examples/additional_flight_phases.ipynb index 2c026f3d02..9f42c35911 100644 --- a/aviary/docs/examples/additional_flight_phases.ipynb +++ b/aviary/docs/examples/additional_flight_phases.ipynb @@ -11,12 +11,12 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.doctape import glue_variable\n", "from aviary.interface.cmd_entry_points import _command_map\n", + "from aviary.utils.doctape import glue_variable\n", "\n", "draw_mission = 'draw_mission'\n", - "_command_map[draw_mission];\n", - "glue_variable(draw_mission, 'aviary '+draw_mission, md_code=True)" + "_command_map[draw_mission]\n", + "glue_variable(draw_mission, 'aviary ' + draw_mission, md_code=True)" ] }, { @@ -48,179 +48,158 @@ "outputs": [], "source": [ "phase_info = {\n", - " \"pre_mission\": {\"include_takeoff\": False, \"optimize_mass\": True},\n", - " \"climb_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.2, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (0.0, \"ft\"),\n", - " \"final_altitude\": (31000.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 31500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": True,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((0.0, 0.0), \"min\"),\n", - " \"duration_bounds\": ((25.5, 76.5), \"min\"),\n", + " 'pre_mission': {'include_takeoff': False, 'optimize_mass': True},\n", + " 'climb_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.2, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (0.0, 'ft'),\n", + " 'altitude_final': (31000.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 31500.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'time_duration_bounds': ((25.5, 76.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([0, 51], \"min\")},\n", + " 'initial_guesses': {'time': ([0, 51], 'min')},\n", " },\n", - " \"cruise_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.7, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (31000.0, \"ft\"),\n", - " \"final_altitude\": (31000.0, \"ft\"),\n", - " \"altitude_bounds\": ((30500.0, 31500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((25.5, 76.5), \"min\"),\n", - " \"duration_bounds\": ((23.5, 70.5), \"min\"),\n", + " 'cruise_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (31000.0, 'ft'),\n", + " 'altitude_final': (31000.0, 'ft'),\n", + " 'altitude_bounds': ((30500.0, 31500.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((25.5, 76.5), 'min'),\n", + " 'time_duration_bounds': ((23.5, 70.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([51, 47], \"min\")},\n", + " 'initial_guesses': {'time': ([51, 47], 'min')},\n", " },\n", - " \"climb_2\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.74, \"unitless\"),\n", - " \"mach_bounds\": ((0.7, 0.76), \"unitless\"),\n", - " \"initial_altitude\": (31000.0, \"ft\"),\n", - " \"final_altitude\": (33000.0, \"ft\"),\n", - " \"altitude_bounds\": ((30500.0, 33500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((49.0, 147.0), \"min\"),\n", - " \"duration_bounds\": ((5.0, 15.0), \"min\"),\n", + " 'climb_2': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.74, 'unitless'),\n", + " 'mach_bounds': ((0.7, 0.76), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (31000.0, 'ft'),\n", + " 'altitude_final': (33000.0, 'ft'),\n", + " 'altitude_bounds': ((30500.0, 33500.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((49.0, 147.0), 'min'),\n", + " 'time_duration_bounds': ((5.0, 15.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([98, 10], \"min\")},\n", + " 'initial_guesses': {'time': ([98, 10], 'min')},\n", " },\n", - " \"cruise_2\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.74, \"unitless\"),\n", - " \"final_mach\": (0.74, \"unitless\"),\n", - " \"mach_bounds\": ((0.72, 0.76), \"unitless\"),\n", - " \"initial_altitude\": (33000.0, \"ft\"),\n", - " \"final_altitude\": (33000.0, \"ft\"),\n", - " \"altitude_bounds\": ((32500.0, 33500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((54.0, 162.0), \"min\"),\n", - " \"duration_bounds\": ((24.0, 72.0), \"min\"),\n", + " 'cruise_2': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.74, 'unitless'),\n", + " 'mach_final': (0.74, 'unitless'),\n", + " 'mach_bounds': ((0.72, 0.76), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (33000.0, 'ft'),\n", + " 'altitude_final': (33000.0, 'ft'),\n", + " 'altitude_bounds': ((32500.0, 33500.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((54.0, 162.0), 'min'),\n", + " 'time_duration_bounds': ((24.0, 72.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([108, 48], \"min\")},\n", + " 'initial_guesses': {'time': ([108, 48], 'min')},\n", " },\n", - " \"climb_3\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.74, \"unitless\"),\n", - " \"final_mach\": (0.76, \"unitless\"),\n", - " \"mach_bounds\": ((0.72, 0.78), \"unitless\"),\n", - " \"initial_altitude\": (33000.0, \"ft\"),\n", - " \"final_altitude\": (34500.0, \"ft\"),\n", - " \"altitude_bounds\": ((32500.0, 35000.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((78.0, 234.0), \"min\"),\n", - " \"duration_bounds\": ((7.0, 21.0), \"min\"),\n", + " 'climb_3': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.74, 'unitless'),\n", + " 'mach_final': (0.76, 'unitless'),\n", + " 'mach_bounds': ((0.72, 0.78), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (33000.0, 'ft'),\n", + " 'altitude_final': (34500.0, 'ft'),\n", + " 'altitude_bounds': ((32500.0, 35000.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((78.0, 234.0), 'min'),\n", + " 'time_duration_bounds': ((7.0, 21.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([156, 14], \"min\")},\n", + " 'initial_guesses': {'time': ([156, 14], 'min')},\n", " },\n", - " \"climb_4\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.76, \"unitless\"),\n", - " \"final_mach\": (0.76, \"unitless\"),\n", - " \"mach_bounds\": ((0.74, 0.78), \"unitless\"),\n", - " \"initial_altitude\": (34500.0, \"ft\"),\n", - " \"final_altitude\": (36000.0, \"ft\"),\n", - " \"altitude_bounds\": ((34000.0, 36500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((85.0, 255.0), \"min\"),\n", - " \"duration_bounds\": ((43.0, 129.0), \"min\"),\n", + " 'climb_4': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.76, 'unitless'),\n", + " 'mach_final': (0.76, 'unitless'),\n", + " 'mach_bounds': ((0.74, 0.78), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (34500.0, 'ft'),\n", + " 'altitude_final': (36000.0, 'ft'),\n", + " 'altitude_bounds': ((34000.0, 36500.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((85.0, 255.0), 'min'),\n", + " 'time_duration_bounds': ((43.0, 129.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([170, 86], \"min\")},\n", + " 'initial_guesses': {'time': ([170, 86], 'min')},\n", " },\n", - " \"descent_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.76, \"unitless\"),\n", - " \"final_mach\": (0.2, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.78), \"unitless\"),\n", - " \"initial_altitude\": (36000.0, \"ft\"),\n", - " \"final_altitude\": (500.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 36500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": True,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((128.0, 384.0), \"min\"),\n", - " \"duration_bounds\": ((41.0, 123.0), \"min\"),\n", + " 'descent_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.76, 'unitless'),\n", + " 'mach_final': (0.2, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.78), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (36000.0, 'ft'),\n", + " 'altitude_final': (500.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 36500.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((128.0, 384.0), 'min'),\n", + " 'time_duration_bounds': ((41.0, 123.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([256, 82], \"min\")},\n", + " 'initial_guesses': {'time': ([256, 82], 'min')},\n", " },\n", - " \"post_mission\": {\n", - " \"include_landing\": False,\n", - " \"constrain_range\": True,\n", - " \"target_range\": (2393, \"nmi\"),\n", + " 'post_mission': {\n", + " 'include_landing': False,\n", + " 'constrain_range': True,\n", + " 'target_range': (2393, 'nmi'),\n", " },\n", "}" ] @@ -237,7 +216,9 @@ "source": [ "# Testing Cell\n", "from aviary.utils.doctape import glue_keys\n", - "glue_keys(phase_info, display=False)\n" + "\n", + "# make all phase_info keys available for later use (e.g. mach_optimize and target_range below)\n", + "glue_keys(phase_info, display=False)" ] }, { @@ -257,8 +238,12 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " phase_info, optimizer=\"SLSQP\", make_plots=True)" + "prob = av.run_aviary(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " phase_info,\n", + " optimizer='SLSQP',\n", + " make_plots=True,\n", + ")" ] }, { @@ -285,8 +270,8 @@ "There are a lot of options for how you could modify this example.\n", "You could:\n", "\n", - "- enable the {glue:md}`optimize_mach` or {glue:md}`optimize_altitude` flags\n", - "- increase the {glue:md}`polynomial_control_order` so there's more flexibility in the optimized mission\n", + "- enable the {glue:md}`mach_optimize` or {glue:md}`altitude_optimize` flags\n", + "- increase the {glue:md}`mach_polynomial_order` and {glue:md}`altitude_polynomial_order` so there's more flexibility in the optimized mission\n", "- try different {glue:md}`target_range` values for the full mission range\n", "- add an external subsystem to the phases\n", "\n", @@ -296,7 +281,7 @@ ], "metadata": { "kernelspec": { - "display_name": "base", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -310,9 +295,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb index 899e3de38e..fbf4ed142c 100644 --- a/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb +++ b/aviary/docs/examples/coupled_aircraft_mission_optimization.ipynb @@ -45,83 +45,74 @@ "outputs": [], "source": [ "phase_info = {\n", - " \"pre_mission\": {\"include_takeoff\": False, \"optimize_mass\": True},\n", - " \"climb_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 5,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.2, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.84), \"unitless\"),\n", - " \"initial_altitude\": (0.0, \"ft\"),\n", - " \"final_altitude\": (32500.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 33000.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": True,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((0.0, 0.0), \"min\"),\n", - " \"duration_bounds\": ((35.0, 105.0), \"min\"),\n", + " 'pre_mission': {'include_takeoff': False, 'optimize_mass': True},\n", + " 'climb_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 5,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.2, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.84), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (0.0, 'ft'),\n", + " 'altitude_final': (32500.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 33000.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'time_duration_bounds': ((35.0, 105.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([0, 70], \"min\")},\n", + " 'initial_guesses': {'time': ([0, 70], 'min')},\n", " },\n", - " \"cruise\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 5,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.80, \"unitless\"),\n", - " \"mach_bounds\": ((0.7, 0.84), \"unitless\"),\n", - " \"initial_altitude\": (32500.0, \"ft\"),\n", - " \"final_altitude\": (36000.0, \"ft\"),\n", - " \"altitude_bounds\": ((32000.0, 36500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((35.0, 105.0), \"min\"),\n", - " \"duration_bounds\": ((91.5, 274.5), \"min\"),\n", + " 'cruise': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 5,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.80, 'unitless'),\n", + " 'mach_bounds': ((0.7, 0.84), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (32500.0, 'ft'),\n", + " 'altitude_final': (36000.0, 'ft'),\n", + " 'altitude_bounds': ((32000.0, 36500.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((35.0, 105.0), 'min'),\n", + " 'time_duration_bounds': ((91.5, 274.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([70, 183], \"min\")},\n", + " 'initial_guesses': {'time': ([70, 183], 'min')},\n", " },\n", - " \"descent_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 5,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.21, \"unitless\"),\n", - " \"mach_bounds\": ((0.19, 0.84), \"unitless\"),\n", - " \"initial_altitude\": (36000.0, \"ft\"),\n", - " \"final_altitude\": (0.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 36500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": True,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((126.5, 379.5), \"min\"),\n", - " \"duration_bounds\": ((25.0, 75.0), \"min\"),\n", + " 'descent_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 5,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.21, 'unitless'),\n", + " 'mach_bounds': ((0.19, 0.84), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (36000.0, 'ft'),\n", + " 'altitude_final': (0.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 36500.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((126.5, 379.5), 'min'),\n", + " 'time_duration_bounds': ((25.0, 75.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([253, 50], \"min\")},\n", + " 'initial_guesses': {'time': ([253, 50], 'min')},\n", " },\n", - " \"post_mission\": {\n", - " \"include_landing\": False,\n", - " \"constrain_range\": True,\n", - " \"target_range\": (2080, \"nmi\"),\n", + " 'post_mission': {\n", + " 'include_landing': False,\n", + " 'constrain_range': True,\n", + " 'target_range': (2080, 'nmi'),\n", " },\n", "}" ] @@ -137,23 +128,25 @@ "outputs": [], "source": [ "# Testing Cell\n", + "from aviary.mission.flight_phase_builder import FlightPhaseOptions\n", "from aviary.utils.doctape import check_value, glue_variable\n", - "from aviary.interface.utils.check_phase_info import check_phase_info, HEIGHT_ENERGY\n", "\n", "# checking that the phase info example is valid\n", - "check_phase_info(phase_info, HEIGHT_ENERGY);\n", + "FlightPhaseOptions(phase_info['climb_1']['user_options'])\n", + "FlightPhaseOptions(phase_info['cruise']['user_options'])\n", + "FlightPhaseOptions(phase_info['descent_1']['user_options'])\n", "\n", "# checking that optimize mach and altitude are False in the example\n", "for phase, info in phase_info.items():\n", - " if phase not in ('pre_mission','post_mission'):\n", - " opt_mach = info['user_options']['optimize_mach']\n", - " check_value(opt_mach,False)\n", - " opt_alt = info['user_options']['optimize_altitude']\n", - " check_value(opt_alt,False)\n", - "\n", - "# gluing optimize_altitude and optimize_mach\n", - "glue_variable('optimize_altitude','optimize_altitude = False', md_code=True)\n", - "glue_variable('optimize_mach','optimize_mach = False', md_code=True)\n" + " if phase not in ('pre_mission', 'post_mission'):\n", + " opt_mach = info['user_options']['mach_optimize']\n", + " check_value(opt_mach, False)\n", + " opt_alt = info['user_options']['altitude_optimize']\n", + " check_value(opt_alt, False)\n", + "\n", + "# gluing altitude_optimize and mach_optimize\n", + "glue_variable('altitude_optimize', 'altitude_optimize = False', md_code=True)\n", + "glue_variable('mach_optimize', 'mach_optimize = False', md_code=True)" ] }, { @@ -167,7 +160,7 @@ "\n", "First, let us run Aviary with a simple setup: fly a prescribed mission profile with an unchanged wing design.\n", "Here we are varying the durations of each of the phases (climb, cruise, and descent) to minimize fuel burn across the mission.\n", - "The altitude and Mach profiles of the mission are fixed because {glue:md}`optimize_altitude` and {glue:md}`optimize_mach` for each of the phases in the `phase_info` object." + "The altitude and Mach profiles of the mission are fixed because {glue:md}`altitude_optimize` and {glue:md}`mach_optimize` for each of the phases in the `phase_info` object." ] }, { @@ -181,8 +174,10 @@ "outputs": [], "source": [ "from openmdao.core.problem import _clear_problem_names\n", + "\n", "_clear_problem_names() # need to reset these to simulate separate runs\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "clear_reports()" ] }, @@ -194,13 +189,14 @@ "source": [ "import aviary.api as av\n", "\n", - "aircraft_filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", - "optimizer = \"IPOPT\"\n", + "aircraft_filename = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "optimizer = 'IPOPT'\n", "make_plots = True\n", - "max_iter = 200\n", + "max_iter = 100\n", "\n", - "prob = av.run_aviary(aircraft_filename, phase_info, optimizer=optimizer,\n", - " make_plots=make_plots, max_iter=max_iter)" + "prob = av.run_aviary(\n", + " aircraft_filename, phase_info, optimizer=optimizer, make_plots=make_plots, max_iter=max_iter\n", + ")" ] }, { @@ -236,7 +232,7 @@ "from aviary.interface.methods_for_level1 import run_aviary\n", "from aviary.utils.doctape import glue_variable\n", "\n", - "glue_variable(run_aviary.__name__,md_code=True)\n" + "glue_variable(run_aviary.__name__, md_code=True)" ] }, { @@ -270,8 +266,10 @@ "outputs": [], "source": [ "from openmdao.core.problem import _clear_problem_names\n", + "\n", "_clear_problem_names() # need to reset these to simulate separate runs\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "clear_reports()" ] }, @@ -281,7 +279,7 @@ "metadata": {}, "outputs": [], "source": [ - "prob = av.AviaryProblem(av.AnalysisScheme.COLLOCATION)\n", + "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", @@ -289,21 +287,14 @@ "\n", "prob.check_and_preprocess_inputs()\n", "\n", - "prob.add_pre_mission_systems()\n", - "\n", - "prob.add_phases()\n", - "\n", - "prob.add_post_mission_systems()\n", - "\n", - "# Link phases and variables\n", - "prob.link_phases()\n", + "prob.build_model()\n", "\n", "prob.add_driver(optimizer, max_iter=max_iter)\n", "\n", "prob.add_design_variables()\n", "\n", "# The following line is an example of how to add a design variable for the aspect ratio of the wing\n", - "prob.model.add_design_var(av.Aircraft.Wing.ASPECT_RATIO, lower=10., upper=14., ref=12.)\n", + "prob.model.add_design_var(av.Aircraft.Wing.ASPECT_RATIO, lower=10.0, upper=14.0, ref=12.0)\n", "\n", "# Load optimization problem formulation\n", "# Detail which variables the optimizer can control\n", @@ -311,8 +302,6 @@ "\n", "prob.setup()\n", "\n", - "prob.set_initial_guesses()\n", - "\n", "prob.run_aviary_problem(make_plots=make_plots)" ] }, @@ -354,8 +343,10 @@ "outputs": [], "source": [ "from openmdao.core.problem import _clear_problem_names\n", + "\n", "_clear_problem_names() # need to reset these to simulate separate runs\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "clear_reports()" ] }, @@ -365,15 +356,16 @@ "metadata": {}, "outputs": [], "source": [ - "phase_info['climb_1']['user_options']['optimize_mach'] = True\n", - "phase_info['climb_1']['user_options']['optimize_altitude'] = True\n", - "phase_info['cruise']['user_options']['optimize_mach'] = True\n", - "phase_info['cruise']['user_options']['optimize_altitude'] = True\n", - "phase_info['descent_1']['user_options']['optimize_mach'] = True\n", - "phase_info['descent_1']['user_options']['optimize_altitude'] = True\n", - "\n", - "prob = av.run_aviary(aircraft_filename, phase_info, optimizer=optimizer,\n", - " make_plots=make_plots, max_iter=max_iter)" + "phase_info['climb_1']['user_options']['mach_optimize'] = True\n", + "phase_info['climb_1']['user_options']['altitude_optimize'] = True\n", + "phase_info['cruise']['user_options']['mach_optimize'] = True\n", + "phase_info['cruise']['user_options']['altitude_optimize'] = True\n", + "phase_info['descent_1']['user_options']['mach_optimize'] = True\n", + "phase_info['descent_1']['user_options']['altitude_optimize'] = True\n", + "\n", + "prob = av.run_aviary(\n", + " aircraft_filename, phase_info, optimizer=optimizer, make_plots=make_plots, max_iter=max_iter\n", + ")" ] }, { @@ -420,8 +412,10 @@ "outputs": [], "source": [ "from openmdao.core.problem import _clear_problem_names\n", + "\n", "_clear_problem_names() # need to reset these to simulate separate runs\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "clear_reports()" ] }, @@ -431,29 +425,22 @@ "metadata": {}, "outputs": [], "source": [ - "prob = av.AviaryProblem(av.AnalysisScheme.COLLOCATION)\n", + "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", "prob.load_inputs(aircraft_filename, phase_info)\n", "\n", "prob.check_and_preprocess_inputs()\n", - "# Preprocess inputs\n", - "prob.add_pre_mission_systems()\n", "\n", - "prob.add_phases()\n", - "\n", - "prob.add_post_mission_systems()\n", - "\n", - "# Link phases and variables\n", - "prob.link_phases()\n", + "prob.build_model()\n", "\n", "prob.add_driver(optimizer, max_iter=max_iter)\n", "\n", "prob.add_design_variables()\n", "\n", "# prob.model.add_design_var(av.Aircraft.Engine.SCALED_SLS_THRUST, lower=25.e3, upper=30.e3, units='lbf', ref=28.e3)\n", - "prob.model.add_design_var(av.Aircraft.Wing.ASPECT_RATIO, lower=10., upper=14., ref=12.)\n", + "prob.model.add_design_var(av.Aircraft.Wing.ASPECT_RATIO, lower=10.0, upper=14.0, ref=12.0)\n", "\n", "# Load optimization problem formulation\n", "# Detail which variables the optimizer can control\n", @@ -461,8 +448,6 @@ "\n", "prob.setup()\n", "\n", - "prob.set_initial_guesses()\n", - "\n", "prob.run_aviary_problem(make_plots=make_plots)" ] }, @@ -479,7 +464,9 @@ "metadata": {}, "outputs": [], "source": [ - "optimized_mission_optimized_wing_fuel_burn = prob.get_val(av.Mission.Summary.FUEL_BURNED, units='kg')[0]\n", + "optimized_mission_optimized_wing_fuel_burn = prob.get_val(\n", + " av.Mission.Summary.FUEL_BURNED, units='kg'\n", + ")[0]\n", "optimized_mission_optimized_wing_aspect_ratio = prob.get_val(av.Aircraft.Wing.ASPECT_RATIO)[0]\n", "print('Mission fuel burn, kg:', optimized_mission_optimized_wing_fuel_burn)\n", "print('Aspect ratio:', optimized_mission_optimized_wing_aspect_ratio)" @@ -514,18 +501,33 @@ "\n", "# Create a dictionary with the data\n", "data = {\n", - " 'Case': ['Fixed Mission, Fixed Wing', 'Fixed Mission, Optimized Wing', 'Optimized Mission, Fixed Wing', 'Optimized Mission, Optimized Wing'],\n", + " 'Case': [\n", + " 'Fixed Mission, Fixed Wing',\n", + " 'Fixed Mission, Optimized Wing',\n", + " 'Optimized Mission, Fixed Wing',\n", + " 'Optimized Mission, Optimized Wing',\n", + " ],\n", " 'Optimize Mission': ['-', '-', '✓', '✓'],\n", " 'Optimize Wing': ['-', '✓', '-', '✓'],\n", - " 'Aspect Ratio': [fixed_mission_fixed_wing_aspect_ratio, fixed_mission_optimized_wing_aspect_ratio, optimized_mission_fixed_wing_aspect_ratio, optimized_mission_optimized_wing_aspect_ratio],\n", - " 'Fuel Burn Value': [fixed_mission_fixed_wing_fuel_burn, fixed_mission_optimized_wing_fuel_burn, optimized_mission_fixed_wing_fuel_burn, optimized_mission_optimized_wing_fuel_burn]\n", + " 'Aspect Ratio': [\n", + " fixed_mission_fixed_wing_aspect_ratio,\n", + " fixed_mission_optimized_wing_aspect_ratio,\n", + " optimized_mission_fixed_wing_aspect_ratio,\n", + " optimized_mission_optimized_wing_aspect_ratio,\n", + " ],\n", + " 'Fuel Burn Value': [\n", + " fixed_mission_fixed_wing_fuel_burn,\n", + " fixed_mission_optimized_wing_fuel_burn,\n", + " optimized_mission_fixed_wing_fuel_burn,\n", + " optimized_mission_optimized_wing_fuel_burn,\n", + " ],\n", "}\n", "\n", "# Create a DataFrame from the dictionary\n", "df = pd.DataFrame(data).round(2)\n", "\n", "# Display the DataFrame\n", - "df\n" + "df" ] }, { diff --git a/aviary/docs/examples/images/fixed_range_cruise_distance.png b/aviary/docs/examples/images/fixed_range_cruise_distance.png deleted file mode 100644 index 22c92b68ae..0000000000 Binary files a/aviary/docs/examples/images/fixed_range_cruise_distance.png and /dev/null differ diff --git a/aviary/docs/examples/images/fixed_range_cruise_mass.png b/aviary/docs/examples/images/fixed_range_cruise_mass.png deleted file mode 100644 index 47b5acb804..0000000000 Binary files a/aviary/docs/examples/images/fixed_range_cruise_mass.png and /dev/null differ diff --git a/aviary/docs/examples/images/fixed_range_cruise_altitude.png b/aviary/docs/examples/images/fixed_range_reserve_altitude.png similarity index 100% rename from aviary/docs/examples/images/fixed_range_cruise_altitude.png rename to aviary/docs/examples/images/fixed_range_reserve_altitude.png diff --git a/aviary/docs/examples/images/multi_mission.png b/aviary/docs/examples/images/multi_mission.png index ef605db51f..7fa053e396 100644 Binary files a/aviary/docs/examples/images/multi_mission.png and b/aviary/docs/examples/images/multi_mission.png differ diff --git a/aviary/docs/examples/images/multiphase_reserve.png b/aviary/docs/examples/images/multiphase_reserve.png deleted file mode 100644 index 40b776d4f9..0000000000 Binary files a/aviary/docs/examples/images/multiphase_reserve.png and /dev/null differ diff --git a/aviary/docs/examples/images/multiphase_reserve_altitude.png b/aviary/docs/examples/images/multiphase_reserve_altitude.png new file mode 100644 index 0000000000..8ecf484e93 Binary files /dev/null and b/aviary/docs/examples/images/multiphase_reserve_altitude.png differ diff --git a/aviary/docs/examples/images/multiphase_reserve_distance.png b/aviary/docs/examples/images/multiphase_reserve_distance.png new file mode 100644 index 0000000000..a2ca12c48a Binary files /dev/null and b/aviary/docs/examples/images/multiphase_reserve_distance.png differ diff --git a/aviary/docs/examples/images/multiphase_reserve_mass.png b/aviary/docs/examples/images/multiphase_reserve_mass.png new file mode 100644 index 0000000000..bba265115f Binary files /dev/null and b/aviary/docs/examples/images/multiphase_reserve_mass.png differ diff --git a/aviary/docs/examples/intro.ipynb b/aviary/docs/examples/intro.ipynb index 4c24a1ad77..3e8a772b8b 100644 --- a/aviary/docs/examples/intro.ipynb +++ b/aviary/docs/examples/intro.ipynb @@ -11,14 +11,12 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.functions import get_path\n", - "from pathlib import Path\n", - "import pkg_resources\n", + "import aviary.api as av\n", "from aviary.utils.doctape import glue_variable\n", + "from aviary.utils.functions import get_path\n", "\n", - "aviary_base_path = Path(pkg_resources.resource_filename('aviary', '.')).parent\n", - "path=get_path('examples/external_subsystems').relative_to(aviary_base_path)\n", - "glue_variable(str(path),md_code=True)" + "path = get_path('examples/external_subsystems').relative_to(av.top_dir)\n", + "glue_variable(path, md_code=True)" ] }, { @@ -34,7 +32,7 @@ "You can find these examples [here](https://github.com/OpenMDAO/Aviary/tree/main/aviary/examples).\n", "\n", "In addition to the examples for core Aviary, we also provide some examples for using external subsystems.\n", - "These are contained in the {glue:md}`aviary/examples/external_subsystems` folder.\n", + "These are contained in the {glue:md}`examples/external_subsystems` folder.\n", "Currently, the folder contains a few different examples, including a battery external subsystem and an example integration with [OpenAeroStruct](https://github.com/mdolab/OpenAerostruct/).\n", "These examples provide a valuable starting point, especially for users interested in integrating their own subsystems into an Aviary model.\n" ] @@ -53,7 +51,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "av1", "language": "python", "name": "python3" }, @@ -67,7 +65,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/aviary/docs/examples/level_2_detailed_takeoff_and_landing.ipynb b/aviary/docs/examples/level_2_detailed_takeoff_and_landing.ipynb index 1107acb8f2..6d7caa60cf 100644 --- a/aviary/docs/examples/level_2_detailed_takeoff_and_landing.ipynb +++ b/aviary/docs/examples/level_2_detailed_takeoff_and_landing.ipynb @@ -12,23 +12,34 @@ "source": [ "# Testing Cell\n", "import aviary.api as av\n", + "\n", + "# TODO this runs the entire example - the phase_info should be separated from the run script?\n", + "from aviary.examples.run_level2_with_detailed_landing import phase_info as landing_phase_info\n", + "from aviary.examples.run_level2_with_detailed_takeoff import phase_info as takeoff_phase_info\n", "from aviary.interface.graphical_input import create_phase_info\n", "from aviary.utils.doctape import check_value, glue_keys\n", - "from aviary.examples.run_detailed_takeoff_in_level2 import phase_info as takeoff_phase_info\n", - "from aviary.examples.run_detailed_landing_in_level2 import phase_info as landing_phase_info\n", "\n", "check_value(av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value, '2DOF')\n", "check_value(av.EquationsOfMotion.SOLVED_2DOF.value, 'solved_2DOF')\n", "\n", - "class true():\n", - " def get(self): return True\n", - "user_choices = {\"constrain_range\": True, \"solve_for_distance\": True,\n", - " \"include_takeoff\": True, \"include_landing\": True}\n", - "dummy_phase_info = create_phase_info([1,2],[1,2],[1,2],[None,None,None],\n", - " [1,2],[1],[true()],[true()],user_choices,[1])\n", + "\n", + "class true:\n", + " def get(self):\n", + " return True\n", + "\n", + "\n", + "user_choices = {\n", + " 'constrain_range': True,\n", + " 'solve_for_distance': True,\n", + " 'include_takeoff': True,\n", + " 'include_landing': True,\n", + "}\n", + "dummy_phase_info = create_phase_info(\n", + " [1, 2], [1, 2], [1, 2], [None, None, None], [1, 2], [1], [true()], [true()], user_choices, [1]\n", + ")\n", "dummy_phase_info.update(takeoff_phase_info)\n", "dummy_phase_info.update(landing_phase_info)\n", - "glue_keys(dummy_phase_info, display=False)\n" + "glue_keys(dummy_phase_info, display=False)" ] }, { @@ -57,13 +68,13 @@ "We use the `phase_info` object to define the trajectories.\n", "We generally use polynomial controls of order 1 to simplify the optimization problem.\n", "What this means is that the control variables (Mach and altitude) are linear within one phase.\n", - "You can increase the order of the polynomial control or set {glue:md}`use_polynomial_control` to `False` to have the optimizer control the values at every node.\n", + "You can increase the order of the polynomial controls by setting {glue:md}`altitude_polynomial_order` or {glue:md}`mach_polynomial_order` to a higher value. You can also set them to `None` to have the optimizer control the values at every node.\n", "\n", "We add any constraints needed for the trajectory in the {glue:md}`constraints` argument passed inside of {glue:md}`user_options`.\n", "Any arbitrary variable present in the phase ODE can be constrained.\n", "You can use boundary or path constraints by setting the {glue:md}`type` argument in the constraint dict.\n", "\n", - "We optimize mach and altitude using the {glue:md}`optimize_mach` and {glue:md}`optimize_altitude` flags.\n", + "We optimize mach and altitude using the {glue:md}`mach_optimize` and {glue:md}`altitude_optimize` flags.\n", "You can choose to disable optimization of these variables by setting them to `False` for any phase.\n", "Aviary internally handles the connections for Mach and altitude between the phases to ensure continuity in the trajectory.\n", "You can choose how to enforce that the throttle value is between 0 and 1; solver bounded, with boundary constraints, or path constraints.\n", @@ -113,7 +124,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -127,9 +138,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/examples/modified_aircraft.csv b/aviary/docs/examples/modified_aircraft.csv index b2ab642a3b..48560f57e1 100644 --- a/aviary/docs/examples/modified_aircraft.csv +++ b/aviary/docs/examples/modified_aircraft.csv @@ -7,17 +7,17 @@ aircraft:canard:aspect_ratio,0.0,unitless aircraft:canard:thickness_to_chord,0.0,unitless aircraft:crew_and_payload:baggage_mass_per_passenger,45.0,lbm aircraft:crew_and_payload:cargo_container_mass_scaler,1.0,unitless +aircraft:crew_and_payload:design:num_business_class,0,unitless +aircraft:crew_and_payload:design:num_first_class,11,unitless +aircraft:crew_and_payload:design:num_passengers,169,unitless +aircraft:crew_and_payload:design:num_tourist_class,158,unitless aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless aircraft:crew_and_payload:mass_per_passenger,180.0,lbm aircraft:crew_and_payload:misc_cargo,0.0,lbm aircraft:crew_and_payload:non_flight_crew_mass_scaler,1.0,unitless -aircraft:crew_and_payload:num_business_class,0,unitless -aircraft:crew_and_payload:num_first_class,11,unitless aircraft:crew_and_payload:num_flight_attendants,3,unitless aircraft:crew_and_payload:num_flight_crew,2,unitless aircraft:crew_and_payload:num_galley_crew,0,unitless -aircraft:crew_and_payload:num_passengers,169,unitless -aircraft:crew_and_payload:num_tourist_class,158,unitless aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless aircraft:crew_and_payload:wing_cargo,0.0,lbm aircraft:design:base_area,0.0,ft**2 @@ -25,6 +25,7 @@ aircraft:design:empty_mass_margin_scaler,0.0,unitless aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:reserve_fuel_additional,3000.,lbm +aircraft:design:reserve_fuel_fraction,0,unitless aircraft:design:subsonic_drag_coeff_factor,1.0,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:use_alt_mass,False,unitless @@ -32,7 +33,7 @@ aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless aircraft:electrical:mass_scaler,1.25,unitless aircraft:engine:additional_mass_fraction,0.,unitless aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_28k.csv,unitless aircraft:engine:flight_idle_thrust_fraction,0.0,unitless aircraft:engine:flight_idle_max_fraction,1.0,unitless aircraft:engine:flight_idle_min_fraction,0.08,unitless @@ -49,6 +50,7 @@ aircraft:engine:num_fuselage_engines,0,unitless aircraft:engine:num_wing_engines,2,unitless aircraft:engine:reference_mass,7400,lbm aircraft:engine:reference_sls_thrust,28928.1,lbf +aircraft:engine:scale_factor,1.0,unitless aircraft:engine:scale_mass,True,unitless aircraft:engine:scale_performance,True,unitless aircraft:engine:scaled_sls_thrust,28928.1,lbf @@ -62,7 +64,6 @@ aircraft:fins:mass,0.0,lbm aircraft:fins:num_fins,0,unitless aircraft:fins:taper_ratio,10.0,unitless aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless aircraft:fuel:fuel_system_mass_scaler,1.0,unitless aircraft:fuel:fuselage_fuel_capacity,0.0,lbm aircraft:fuel:num_tanks,7,unitless @@ -90,7 +91,6 @@ aircraft:horizontal_tail:wetted_area,592.65,ft**2 aircraft:hydraulics:mass_scaler,1.0,unitless aircraft:hydraulics:system_pressure,3000,psi aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless aircraft:landing_gear:main_gear_oleo_length,102.0,inch aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless @@ -114,11 +114,12 @@ aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless aircraft:wing:airfoil_technology,1.92669766647637,unitless aircraft:wing:area,1370.0,ft**2 aircraft:wing:aspect_ratio,11.02091,unitless -aircraft:wing:bending_mass_scaler,1.0,unitless +aircraft:wing:bending_material_mass_scaler,1.0,unitless aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless aircraft:wing:composite_fraction,0.2,unitless aircraft:wing:control_surface_area,137,ft**2 aircraft:wing:control_surface_area_ratio,0.1,unitless +aircraft:wing:detailed_wing,True,unitless aircraft:wing:glove_and_bat,134.0,ft**2 aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless aircraft:wing:load_distribution_control,2.0,unitless @@ -132,7 +133,7 @@ aircraft:wing:shear_control_mass_scaler,1.0,unitless aircraft:wing:span_efficiency_reduction,False,unitless aircraft:wing:span,117.83,ft aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless +aircraft:wing:surface_control_mass_scaler,1.0,unitless aircraft:wing:sweep,25.0,deg aircraft:wing:taper_ratio,0.278,unitless aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless @@ -153,4 +154,6 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless settings:equations_of_motion,height_energy +settings:aerodynamics_method,FLOPS settings:mass_method,FLOPS +settings:payload_range,false diff --git a/aviary/docs/examples/more_advanced_example.ipynb b/aviary/docs/examples/more_advanced_example.ipynb index e1bb5f3825..4f6eec29e2 100644 --- a/aviary/docs/examples/more_advanced_example.ipynb +++ b/aviary/docs/examples/more_advanced_example.ipynb @@ -11,8 +11,9 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.doctape import glue_variable\n", "import aviary.api as av\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", "glue_variable('fuel_burned', av.Mission.Summary.FUEL_BURNED, True)" ] }, @@ -27,11 +28,11 @@ "\n", "## Increasing Complexity in Phase Information\n", "\n", - "We will now modify the `phase_info` object from our prior example by increasing {glue:md}`num_segments` to 3 and setting {glue:md}`optimize_mach` to `True` in each of the three phases.\n", + "We will now modify the `phase_info` object from our prior example by increasing {glue:md}`num_segments` to 3 and setting {glue:md}`mach_optimize` to `True` in each of the three phases.\n", "This means that we'll query the aircraft performance at more points along the mission and also give the optimizer the freedom to choose an optimal Mach profile.\n", "\n", "```{note}\n", - "We are still using a {glue:md}`polynomial_control_order` of 1, which means that the optimal Mach profiles for each phase will be linear (straight lines).\n", + "We are still using a {glue:md}`mach_polynomial_order` and {glue:md}`altitude_polynomial_order` of 1, which means that the optimal Mach profiles for each phase will be linear (straight lines).\n", "Later in this example, we increase this order which will allow the optimizer to choose a more complex Mach profile.\n", "```" ] @@ -43,83 +44,73 @@ "outputs": [], "source": [ "phase_info = {\n", - " \"pre_mission\": {\"include_takeoff\": False, \"optimize_mass\": True},\n", - " \"climb_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": True,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.2, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (0.0, \"ft\"),\n", - " \"final_altitude\": (30500.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 31000.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": True,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((0.0, 0.0), \"min\"),\n", - " \"duration_bounds\": ((27.0, 81.0), \"min\"),\n", + " 'pre_mission': {'include_takeoff': False, 'optimize_mass': True},\n", + " 'climb_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'distance_solve_segments': False,\n", + " 'mach_optimize': True,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.2, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (0.0, 'ft'),\n", + " 'altitude_final': (30500.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 31000.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'time_duration_bounds': ((27.0, 81.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([0, 54], \"min\")},\n", + " 'initial_guesses': {'time': ([0, 54], 'min')},\n", " },\n", - " \"cruise\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": True,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.7, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (30500.0, \"ft\"),\n", - " \"final_altitude\": (31000.0, \"ft\"),\n", - " \"altitude_bounds\": ((30000.0, 31500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((27.0, 81.0), \"min\"),\n", - " \"duration_bounds\": ((85.5, 256.5), \"min\"),\n", + " 'cruise': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': True,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_initial': (30500.0, 'ft'),\n", + " 'altitude_final': (31000.0, 'ft'),\n", + " 'altitude_bounds': ((30000.0, 31500.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((27.0, 81.0), 'min'),\n", + " 'time_duration_bounds': ((85.5, 256.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([54, 171], \"min\")},\n", + " 'initial_guesses': {'time': ([54, 171], 'min')},\n", " },\n", - " \"descent_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": True,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 3,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.2, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (31000.0, \"ft\"),\n", - " \"final_altitude\": (500.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 31500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": True,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((112.5, 337.5), \"min\"),\n", - " \"duration_bounds\": ((26.5, 79.5), \"min\"),\n", + " 'descent_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 3,\n", + " 'order': 3,\n", + " 'mach_optimize': True,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.2, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_initial': (31000.0, 'ft'),\n", + " 'altitude_final': (500.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 31500.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((112.5, 337.5), 'min'),\n", + " 'time_duration_bounds': ((26.5, 79.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([225, 53], \"min\")},\n", + " 'initial_guesses': {'time': ([225, 53], 'min')},\n", " },\n", - " \"post_mission\": {\n", - " \"include_landing\": False,\n", - " \"constrain_range\": True,\n", - " \"target_range\": (1915, \"nmi\"),\n", + " 'post_mission': {\n", + " 'include_landing': False,\n", + " 'constrain_range': True,\n", + " 'target_range': (1915, 'nmi'),\n", " },\n", "}" ] @@ -135,12 +126,9 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.default_phase_info.height_energy import phase_info as HE_phase_info\n", - "from aviary.interface.utils.check_phase_info import check_phase_info, HEIGHT_ENERGY\n", + "from aviary.models.missions.height_energy_default import phase_info as HE_phase_info\n", "from aviary.utils.doctape import glue_keys\n", "\n", - "check_phase_info(phase_info, HEIGHT_ENERGY);\n", - "\n", "HE_phase_info.update(phase_info)\n", "glue_keys(HE_phase_info)" ] @@ -165,8 +153,10 @@ "outputs": [], "source": [ "from openmdao.core.problem import _clear_problem_names\n", + "\n", "_clear_problem_names() # need to reset these to simulate separate runs\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "clear_reports()" ] }, @@ -178,8 +168,12 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " phase_info, optimizer=\"SLSQP\", make_plots=True)" + "prob = av.run_aviary(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " phase_info,\n", + " optimizer='SLSQP',\n", + " make_plots=True,\n", + ")" ] }, { @@ -199,7 +193,7 @@ "This means that we have more points shown on the resulting plots.\n", "\n", "The second is that the optimizer chose the optimal Mach profile.\n", - "Again, each phase's Mach profile is constrained to be linear because we set {glue:md}`polynomial_control_order` to 1.\n", + "Again, each phase's Mach profile is constrained to be linear because we set {glue:md}`mach_polynomial_order` and {glue:md}`altitude_polynomial_order` to 1.\n", "However, we see that the optimizer chose to decrease the Mach number during the cruise-climb segment to minimize fuel burn.\n", "\n", "```{note}\n", @@ -246,6 +240,7 @@ "source": [ "# Testing Cell\n", "from aviary.utils.doctape import glue_variable\n", + "\n", "new_filename = 'modified_aircraft.csv'\n", "glue_variable(new_filename, md_code=True)" ] @@ -273,7 +268,7 @@ "source": [ "import csv\n", "\n", - "filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "filename = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "filename = av.get_path(filename)\n", "\n", "# Read the file\n", @@ -296,7 +291,7 @@ "# Write the modified content to a new CSV file\n", "with open(new_filename, 'w', newline='') as file:\n", " writer = csv.writer(file)\n", - " writer.writerows(lines)\n" + " writer.writerows(lines)" ] }, { @@ -320,8 +315,10 @@ "outputs": [], "source": [ "from openmdao.core.problem import _clear_problem_names\n", + "\n", "_clear_problem_names() # need to reset these to simulate separate runs\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "clear_reports()" ] }, @@ -331,8 +328,7 @@ "metadata": {}, "outputs": [], "source": [ - "prob = av.run_aviary('modified_aircraft.csv', phase_info,\n", - " optimizer=\"SLSQP\", make_plots=True)" + "prob = av.run_aviary('modified_aircraft.csv', phase_info, optimizer='SLSQP', make_plots=True)" ] }, { @@ -360,8 +356,8 @@ "\n", "## Increasing the Polynomial Control Order\n", "\n", - "Next, we'll increase the {glue:md}`polynomial_control_order` to 3 for the climb and descent phases.\n", - "This means that the optimizer will be able to choose a cubic Mach profile per phase instead of a line.\n", + "Next, we'll increase the {glue:md}`mach_polynomial_order` and {glue:md}`altitude_polynomial_order` to 3 for the climb and descent phases.\n", + "This means that the optimizer will be able to choose a cubic Mach and altitude profile per phase instead of a straight line.\n", "We'll use the original aircraft configuration for this run.\n", "\n", "```{note}\n", @@ -380,8 +376,10 @@ "outputs": [], "source": [ "from openmdao.core.problem import _clear_problem_names\n", + "\n", "_clear_problem_names() # need to reset these to simulate separate runs\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "clear_reports()" ] }, @@ -391,12 +389,19 @@ "metadata": {}, "outputs": [], "source": [ - "phase_info['climb_1']['user_options']['polynomial_control_order'] = 3\n", - "phase_info['cruise']['user_options']['polynomial_control_order'] = 1\n", - "phase_info['descent_1']['user_options']['polynomial_control_order'] = 3\n", + "phase_info['climb_1']['user_options']['mach_polynomial_order'] = 3\n", + "phase_info['climb_1']['user_options']['altitude_polynomial_order'] = 3\n", + "phase_info['cruise']['user_options']['mach_polynomial_order'] = 1\n", + "phase_info['cruise']['user_options']['altitude_polynomial_order'] = 1\n", + "phase_info['descent_1']['user_options']['mach_polynomial_order'] = 3\n", + "phase_info['descent_1']['user_options']['altitude_polynomial_order'] = 3\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " phase_info, optimizer=\"IPOPT\", make_plots=True)" + "prob = av.run_aviary(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " phase_info,\n", + " optimizer='IPOPT',\n", + " make_plots=True,\n", + ")" ] }, { @@ -454,7 +459,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/examples/multi_mission.ipynb b/aviary/docs/examples/multi_mission.ipynb index 6372aa40e1..b06dc4efe5 100644 --- a/aviary/docs/examples/multi_mission.ipynb +++ b/aviary/docs/examples/multi_mission.ipynb @@ -11,43 +11,44 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.doctape import glue_variable, get_variable_name\n", - "from aviary.api import Aircraft, Mission, AviaryProblem\n", - "from aviary.examples.multi_mission import run_multimission_example_large_single_aisle\n", + "from aviary.api import Aircraft, AviaryProblem, Mission\n", + "from aviary.examples.multi_mission import run_multimission_example\n", + "from aviary.utils.doctape import (\n", + " get_variable_name,\n", + " glue_variable,\n", + " glue_class_functions,\n", + ")\n", "\n", - "glue_variable('capi',AviaryProblem.check_and_preprocess_inputs.__name__,md_code=True)\n", + "current_glued_vars = []\n", "\n", - "glue_variable(get_variable_name(Mission.Design.RANGE), md_code=True)\n", + "# Get all methods of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars, prefix='prob')\n", "\n", + "glue_variable(get_variable_name(Aircraft.Avionics.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.CARGO_MASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_PASSENGERS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_BUSINESS_CLASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_FIRST_CLASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_TOURIST_CLASS), md_code=True)\n", - "\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.PASSENGER_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_PASSENGERS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS), md_code=True)\n", - "\n", + "glue_variable(get_variable_name(Aircraft.Design.EMPTY_MASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO), md_code=True)\n", - "glue_variable(get_variable_name(Mission.Summary.CRUISE_MACH), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Furnishings.MASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.LandingGear.MAIN_GEAR_MASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.LandingGear.NOSE_GEAR_MASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.Wing.SWEEP), md_code=True)\n", "glue_variable(get_variable_name(Mission.Design.GROSS_MASS), md_code=True)\n", - "glue_variable(get_variable_name(Mission.Summary.GROSS_MASS), md_code=True)\n", - "glue_variable(get_variable_name(Aircraft.Design.EMPTY_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Design.RANGE), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Summary.CRUISE_MACH), md_code=True)\n", "glue_variable(get_variable_name(Mission.Summary.FUEL_BURNED), md_code=True)\n", - "\n", - "glue_variable(get_variable_name(Aircraft.Furnishings.MASS), md_code=True)\n", - "glue_variable(get_variable_name(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS), md_code=True)\n", - "\n", - "glue_variable(get_variable_name(Aircraft.CrewPayload.CARGO_MASS), md_code=True)\n", - "glue_variable(get_variable_name(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS), md_code=True)\n", - "glue_variable(get_variable_name(Aircraft.CrewPayload.PASSENGER_MASS), md_code=True)\n", - "glue_variable(get_variable_name(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS), md_code=True)\n", - "\n", - "\n" + "glue_variable(get_variable_name(Mission.Summary.GROSS_MASS), md_code=True)" ] }, { @@ -57,92 +58,269 @@ "# Multi-Mission Example\n", "\n", "The [Multi-mission Example](\n", - "https://github.com/OpenMDAO/Aviary/tree/main/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py) demonstrates the capability to optimize an aircraft design considering two missions that the aircraft will perform. For a background on this example see [Multi-Mission Overview](../user_guide/multi_mission).\n", + "https://github.com/OpenMDAO/Aviary/tree/main/aviary/examples/multi_mission/run_multimission_example.py) demonstrates the capability to optimize a single aircraft design considering two missions that the aircraft will perform. For a background on this example see [Multi-Mission Overview](../user_guide/multi_mission). It is expected that the users is familiar with methods from level 1 and level 2 before exploring this content.\n", "\n", - "## Implementation\n", - "At a minimum, the user must supply the following inputs for a multi-mission:\n", - "* 2 aircraft configuration examples (i.e. .csv files)\n", - "* 2 `phase_info` describing the different aircraft missions\n", - "* a weighting of the relative importance of each mission\n", - "* {glue:md}Mission.Design.RANGE\n", - "* {glue:md}Aircraft.CrewPayload.Design.NUM_PASSENGERS\n", - "* {glue:md}Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO\n", + "## Theory\n", + "Each of the two missions in the example are instantiated as a single aviary problems with two AviaryGroups inside of it. Each AviaryGroup has it's own pre-missions, mission, and post-mission elements. Two get the pre-missions to have the same aircraft design, {glue:md}`Mission.Design.GROSS_MASS`, {glue:md}`Mission.Design.RANGE`, {glue:md}`Aircraft.Wing.SWEEP`, are promoted out of the pre-missions to a single values. This ensures that the aircrafts in both pre-missions have the same design even though their passenger count and fuel mass are different. There is no post-mission for the example, but if one was required for calculating cost or acoustic constraints, there would need to be two post-mission systems as well.\n", "\n", - "### Aircraft Configuration\n", - "In the example, we import a single aircraft configuration (LargeSingleAisle2FLOPS) and then modify it to create a primary mission which carries 162 passengers and a deadhead mission. The deadhead mission is a mission with a single passengers, but it still has the same number of seats in the aircraft, even though those seats are mostly empty. The number of seats for passenters in the aircraft, as well as some other systems like passenger airconditioning mass, is set by values of {glue:md}Aircraft.CrewPayload.Design.NUM_PASSENGERS, {glue:md}Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, {glue:md}Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, and {glue:md}Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS. Whereas the actual number of passengers on the flight is specified by variables of {glue:md}Aircraft.CrewPayload.NUM_PASSENGERS, {glue:md}Aircraft.CrewPayload.NUM_TOURIST_CLASS, {glue:md}Aircraft.CrewPayload.NUM_BUSINESS_CLASS, and {glue:md}Aircraft.CrewPayload.NUM_BUSINESS_CLASS.\n", + "Graphs for each mission are created and stored in the run_multimission_example folder. A custom print functions were added to display some important information. The user can see detailed info of each mission result using the `prob.model.mission1.list_vars()` commands listed in the comments at the bottom of the example. \n", "\n", - "### Phase Info\n", - "The same mission distance and profile (takeoff, climb, cruise, descent, landing) is being flown for both missions. To enable this, a single phase_info is imported and then deepcopied. The user could modify the deadhead mission to be different from the primary mission by changing the target_range of the deadhead mission to a different value, for example by changing `phase_info_deadhead['post_mission']['target_range'] = [1500, \"nmi\"]` \n", + "A number of checks exist in {glue:md}`add_aviary_group` which under the hood calls {glue:md}`check_and_preprocess_inputs` to help the user in the case that incomplete as-flow or design passenger information is provided. This was done to provide backward compatability for older aircraft models which only specify design passenger information. \n", "\n", - "### Weighting\n", - "The `weights` input value describes the relative importance or frequence of one mission over the other. In the example, the the weigting is [9,1] indicating that for every nine times the aircraft flies a full passenger load, it flies a single deadhead leg. These weightings are based on user input and are converted into fractions. This weighting can be estimated from examining historical passenger loads on a typical aircraf route of interest. The objective function is based on combining the fuel-burn values from both missions and multiplying that by the weights. Other objectives, like max range, have not been tested yet.\n", + "In this example we wanted to compare the same aircraft flying a mission with full passengers vs. a mission with no passengers. However, there are limitations in Aviary's ability to detect user input vs. default values. So we set the passenger count to one instead. Right now, the only way to set an aircraft to exactly zero passengers is by setting {glue:md}`Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS` to zero plus any {glue:md}`Aircraft.CrewPayload.CARGO_MASS` being carried. This zeros out passenger and baggage mass regardless of what value is input to {glue:md}`Aircraft.CrewPayload.NUM_PASSENGERS`, {glue:md}`Aircraft.CrewPayload.NUM_TOURIST_CLASS`, {glue:md}`Aircraft.CrewPayload.NUM_BUSINESS_CLASS`, and {glue:md}`Aircraft.CrewPayload.NUM_FIRST_CLASS`. Once issue #610 is resolved the user should be able to set passenger and bags mass to exactly zero by setting {glue:md}`Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS` to zero.\n", "\n", - "### Setting Values\n", - "The {glue:md}Mission.Design.RANGE value must be set to size some of Aviary's subsystems. These subsystems, such as avionics, have increasing mass as {glue:md}Mission.Design.RANGE increases. These are first order approximations that come with aviary. But because of these, we must ensure that both pre-missions have the same {glue:md}Mission.Design.RANGE, even if the actual range flown buy each mission (target_rage) is different. Without this, the avoinics mass calculated in pre-mission would be different for the two missions, resulting in a different aircraft design, which is counter to what is intended with the multi-mission feature. \n", + "## Best Pratices\n", + "The user should be cognizant of the implications of having two pre-mission systems, one for each mission. When trying to mirror these to create a single aircraft that flies different missions, both of the pre-mission systems should be nearly identical in setup, except for fuel-mass, passenger, and payload calculations. There are numerous opportunities for the user to get this wrong, and accidentally create two different aircraft as a result. For example, in a previous iteration of this example, {glue:md}`Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO` was not specified, which resulted in two different landing gears being designed, one for mission1, one for mission2.\n", "\n", - "The total number of passengers ({glue:md}Aircraft.CrewPayload.Design.NUM_PASSENGERS) and the design number of passengers of each type (business, tourist, first class), help to define the passenger air conditioning subsystems and the passenger support mass (seats) respectively. Thus when these values are set equal in the primary and deadhead missions, we ensure the aircraft will be designed similarly. \n", "\n", - "It is good practice, but not required, to set {glue:md}Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO in Aviary Values to ensure consistent design of the landing gear for both missions. This combined with Design.GROSS_MASS helps to ensure that {glue:md}Aircraft.LandingGear.MAIN_GEAR_MASS and {glue:md}Aircraft.LandingGear.NOSE_GEAR_MASS are the same for both missions. If {glue:md}Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO is not set, Landing Gear Masses will be caluclated based on {glue:md}Mission.Summary.CRUISE_MACH and {glue:md}Mission.Design.RANGE. This is potentially problematic because {glue:md}Mission.Summary.CRUISE_MACH may not be set, and instead cruse mach may be optimized. In that case, {glue:md}Mission.Summary.CRUISE_MACH could vary between the Primary and Deadhead missions, which would then cascade into differeing {glue:md}Aircraft.LandingGear.MAIN_GEAR_MASS which causes the aircraft designs to diverge.\n", + "```\n", + "Note: If you are having trouble getting your {glue:md}`Aircraft.Design.EMPTY_MASS` (the final drymass mass summation from pre-mission) to be equal for both pre-missions, use the following OpenMDAO commends at the end of the example to list out and compare the mass from each subsystem.\n", + "prob.model.mission1.list_vars(val=True, units=True, print_arrays=False)\n", + "prob.model.mission2.list_vars(val=True, units=True, print_arrays=False)\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Phase Info\n", + "The same mission distance and profile (takeoff, climb, cruise, descent, landing) is being flown for both missions. To enable this, a single phase_info is imported and then deepcopied. The user could modify the mission2 to be different from mission1 by changing the target_range to a different value (i.e `phase_info_mission2['post_mission']['target_range'] = [1500, \"nmi\"]` )." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy as copy\n", "\n", - "## Theory\n", - "Each of the two missions in the example are instantiated as separate aviary problems before copying those two groups over to a single `super_prob`. This means there are two pre-missions, two missions run in parallel. Two get the pre-missions to have the same aircraft design, {glue:md}Mission.Design.GROSS_MASS, {glue:md}Mission.Design.RANGE, {glue:md}Aircraft.Wing.SWEEP, are promoted out of the pre-missions to a single values. This ensures that the aircrafts in both pre-missions have the same design even though their passenger count and fuel mass are different. There is no post-mission for the example, but if one was required for calculating cost or acoustic constraints, there would need to be two post-mission systems as well.\n", + "import aviary.api as av\n", + "from aviary.models.missions.height_energy_default import phase_info\n", + "from aviary.validation_cases.validation_tests import get_flops_inputs\n", + "from aviary.variable_info.enums import ProblemType\n", + "from aviary.variable_info.variables import Aircraft, Mission, Settings\n", + "\n", + "phase_info_mission1 = copy.deepcopy(phase_info)\n", + "phase_info_mission2 = copy.deepcopy(phase_info)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Aircraft Configuration\n", + "In the example, we import a single aircraft configuration (LargeSingleAisle2FLOPS) and then modify it to create a mission1 which carries 162 passengers and mission2, a mission which carries only a single passengers on the same aircraft. The number of seats for passengers in the aircraft, as well as some other systems like passenger airconditioning mass, is set by values of {glue:md}`Aircraft.CrewPayload.Design.NUM_PASSENGERS`, {glue:md}`Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS`, {glue:md}`Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS`, and {glue:md}`Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS`. Whereas the actual number of passengers on the flight is specified by variables of {glue:md}`Aircraft.CrewPayload.NUM_PASSENGERS`, {glue:md}`Aircraft.CrewPayload.NUM_TOURIST_CLASS`, {glue:md}`Aircraft.CrewPayload.NUM_BUSINESS_CLASS`, and {glue:md}`Aircraft.CrewPayload.NUM_BUSINESS_CLASS`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "aviary_inputs_mission1 = get_flops_inputs('LargeSingleAisle2FLOPS')\n", "\n", - "To impact the structure of aviary problems as little as possible, after instantiation of the pre-mission, mission, and post-mission systems, the connections between those systems are created. Then those groups are then copied over into a regular openmdao problem called `super_prob`. This enables the use all the basic aviary connection and checking functions with minimal modification. There originally was a desire to use openmdao subproblems for this implementation but derivatives through subproblems were not available at that time.\n", + "aviary_inputs_mission2 = copy.deepcopy(aviary_inputs_mission1)\n", + "aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, 1, 'unitless')\n", + "aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, 1, 'unitless')\n", + "aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS, 0, 'unitless')\n", + "aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_FIRST_CLASS, 0, 'unitless')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Adding Aviary Groups\n", + "Now we must set the problem type to multimission, this will allow us to use our other commandes like {glue:md}`add_aviary_group` to combine the aviary_values and phase_info to create two Aviary Groups which are added to the problem. {glue:md}`add_aviary_group` can accept engine_builders as well if you wanted to specify a custom engine builder for the models. We give each of the groups a name: mission1 and mission 2 which we will use to reference them later. Lastly we build the model, which adds pre-mission, phases, post-mission, and links phases sequentially. These elements could be called individually if the user desired more control over each one." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "prob = av.AviaryProblem(problem_type=ProblemType.MULTI_MISSION)\n", "\n", - "Initialization of states and variables is conducted last through `prob.set_initial_guesses()`. This has to be completed after the aviary groups are added to `super_prob`. Setting initial guesses and then copying over a group into `super_prob` will not work in this case because initial guesses is set on the problem, not the group. \n", + "prob.add_aviary_group('mission1', aircraft=aviary_inputs_mission1, mission=phase_info_mission1)\n", "\n", - "Some custom graphing and print functions were added to this example because the basic aviary graphing programs have not yet been modified to handle two database file from two separate missions. The user can see detailed info of each mission result using the `super_prob.model.group_1.list_vars()` commands listed in the comments at the bottom of the example.\n", + "prob.add_aviary_group('mission2', aircraft=aviary_inputs_mission2, mission=phase_info_mission2)\n", "\n", - "A number of checks exist in {glue:md}`capi` to help the user in the case that incomplete as-flow or design passenger information is provided. This was done to provide backward compatability for older aircraft models which only specify design passenger information. However, due to current limitations in Aviary's ability to detect user input vs. default values, the only way to set an aircraft to exactly zero passengers is by setting {glue:md}Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS to zero plus any {glue:md}Aircraft.CrewPayload.CARGO_MASS being carried. This zeros out passenger and baggage mass regardless of what value is input to {glue:md}Aircraft.CrewPayload.NUM_PASSENGERS, {glue:md}Aircraft.CrewPayload.NUM_TOURIST_CLASS, {glue:md}Aircraft.CrewPayload.NUM_BUSINESS_CLASS, and {glue:md}Aircraft.CrewPayload.NUM_FIRST_CLASS. Once issue #610 is resolved the user should be able to set passenger and bags mass to exactly zero by setting {glue:md}Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS to zero.\n", + "prob.build_model()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### User Input\n", + "Now we have the opportunity for the user to tell us how these aircraft are the same. Up to this point, each call to {glue:md}`add_aviary_group` has setup two completely separate aircraft but in the example we are trying to design a single aircraft. To do this we must explicitly tell Aviary which key parameters are mirrored on both aircraft. These key parameters are used to size different subsystems.\n", "\n", - "## Best Pratices\n", - "The user should be cognizant of the implications of having two pre-mission systems, one for each mission. Both of the pre-mission systems should be nearly identical in setup, except for fuel-mass, passenger, and payload calculations. There are numerous opportunities for the user to get this wrong, and accidentally create two different aircraft as a result. For example, in a previous iteration of this example, {glue:md}Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO was not specified, which resulted in two different landing gears being designed, one for the Primary mission, one for the Deadhead mission.\n", + "{glue:md}`promote_inputs` tells aviary that between mission1 and mission2, the following 3 values are the same and should be promoted to the top level of the problem: {glue:md}`Mission.Design.GROSS_MASS`, {glue:md}`Mission.Design.RANGE`, and {glue:md}`Aircraft.Wing.SWEEP`. If we did not promote these values, they would still only be accesible inside of their individual groups (i.e. mission1.mission:design:gross_mass). \n", "\n", - "If you are having trouble getting your {glue:md}Aircraft.Design.EMPTY_MASS (the final drymass mass summation from pre-mission) to be equal for both pre-missions, use the following OpenMDAO commends at the end of the example to list out and compare the mass from each subsystem.\n", + "{glue:md}`add_design_var_default` is used to tell Aviary that we are setting `Aircraft1:GROSS_MASS` as a design variable controlled by the optimizer, and to set it's initial value and upper and lower constraints. Normally this is done as part of a two-step process using `prob.model.add_design_var` to set the range, and then after setup calling {glue:md}`prob.set_val` to set the initial value. However, it is more convenient to set them both in one place. The value can still be over-written later using {glue:md}`prob.set_val` after setup.\n", "\n", - "```\n", - "super_prob.model.group_1.list_vars(val=True, units=True, print_arrays=False)\n", - "super_prob.model.group_2.list_vars(val=True, units=True, print_arrays=False)\n", - "```\n" + "{glue:md}`add_composite_objective` specifies that the output of {glue:md}`Mission.Summary.FUEL_BURNED` from `mission1` and `mission2` should be summed together based on a 2:1 weighting. Alternatively, the user could have specified the same thing using {glue:md}`add_composite_objective_adv` which provides a slightly more streamlined interface if users know their mission frequency and ouput weights separetly. This typically happens if you know how often you will fly a particular mission from historical data, and then you would like to weight the fuel-burn on each mission vs. another metric, such as maintinance costs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "prob.promote_inputs(\n", + " ['mission1', 'mission2'],\n", + " [\n", + " (Mission.Design.GROSS_MASS, 'Aircraft1:GROSS_MASS'),\n", + " (Mission.Design.RANGE, 'Aircraft1:RANGE'),\n", + " (Aircraft.Wing.SWEEP, 'Aircraft1:SWEEP'),\n", + " ],\n", + ")\n", + "\n", + "prob.add_design_var_default(\n", + " 'Aircraft1:GROSS_MASS',\n", + " lower=10.0,\n", + " upper=900e3,\n", + " units='lbm',\n", + " default_val=100000,\n", + ")\n", + "prob.add_design_var_default(\n", + " 'Aircraft1:SWEEP',\n", + " lower=23.0,\n", + " upper=27.0,\n", + " units='deg',\n", + " default_val=25,\n", + ")\n", + "\n", + "prob.add_composite_objective(\n", + " ('mission1', Mission.Summary.FUEL_BURNED, 2),\n", + " ('mission2', Mission.Summary.FUEL_BURNED, 1),\n", + " ref=1,\n", + ")\n", + "# prob.add_composite_objective_adv(missions=['mission1', 'mission2'], mission_weights=[2,1], outputs=[Mission.Summary.FUEL_BURNED], outputoutput_weights=[1] ref=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Results\n", - "The results of the [Multi-mission Example](\n", - "https://github.com/OpenMDAO/Aviary/tree/main/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py) are included in the data table and plots below.\n", - "\n", - "From the table results we can see that the Primary mission have the same {glue:md}Mission.Design.GROSS_MASS. However, the {glue:md}Mission.Summary.GROSS_MASS varies as expected because these represent \"as-flown\" values. The Primary mission has the higher {glue:md}Mission.Summary.GROSS_MASS which corresponds to the full passenger load and bags. Consequently, the {glue:md}Mission.Summary.FUEL_BURNED for each mission is different, higher for the Primary mission, as expected because this mission is carrying more mass for the same mission. {glue:md}Aircraft.Wing.SWEEP is the same for both missions, indicating that the aircraft has been designed similarly in both cases. We do not want to see different values for the wing design because it would mean that the two pre-mission systems are not mirroring eachother. If they were not the same it would mean we are designing two different aircraft. \n", + "### Setting up the model\n", + "Now with the basics complete we can add a driver, set the basic design variables, and setup the aviary model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "prob.add_driver('IPOPT', max_iter=50)\n", + "prob.add_design_variables()\n", "\n", - "The {glue:md}Aircraft.LandingGear.MAIN_GEAR_MASS and {glue:md}Aircraft.LandingGear.NOSE_GEAR_MASS masses were also displayed because they are sensitive to {glue:md}Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO. We expect these landing gear masses to be the same and they are which is good news for us and indicates that both pre-mission designs are mirroring eachother.\n", + "prob.setup()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Setting Values\n", + "The {glue:md}`Mission.Design.RANGE` value must be set to size some of Aviary's subsystems. These subsystems, such as avionics, have increasing mass as {glue:md}`Mission.Design.RANGE` increases. These are first order approximations that come with aviary. But because of these, we must ensure that both pre-missions have the same {glue:md}`Mission.Design.RANGE`, even if the actual range flown buy each mission (target_rage) is different. Without this, the avoinics mass calculated in pre-mission would be different for the two missions, resulting in a different aircraft design, which is counter to what is intended with the multi-mission feature. \n", "\n", - "The {glue:md}Aircraft.Furnishings.MASS and {glue:md}Aircraft.CrewPayload.PASSENGER_SERVICE_MASS are displayed. These values represent the weight of the seats and the air conditioning system for the passengers. They are both the same which is what we expect to see.\n", + "{glue:md}`set_design_range` method will access the phase_info for any missions supplied, find the largest `target_rage`, and set `Aircraft1:Range` to that value. This will ensure the avionics are designed similarly for both aircraft.\n", "\n", - "A summary colum called 'Expectations' is included as a summary of what we want to see when evaluating this data. \n", + "The total number of passengers ({glue:md}`Aircraft.CrewPayload.Design.NUM_PASSENGERS`) and the design number of passengers of each type (business, tourist, first class), help to define the passenger air conditioning subsystems and the passenger support mass (seats) respectively. Thus when these values are set equal in mission1 and mission2, we ensure the aircraft will be designed similarly. These settings were already set in the `LargeSingleAisle2FLOPS` model which we are using.\n", "\n", - "| Variable | Primary | Deadhead | Expectations |\n", - "|:-------------------------------------------------|:-----------------------------:|:--------------------:|---:|\n", - "{glue:md}Mission.Design.GROSS_MASS | 157432.51366187233 (lbm) | 157432.51366187233 (lbm) | Equal |\n", - "{glue:md}Aircraft.Design.EMPTY_MASS | 87415.21921741116 (lbm) | 87415.21921741116 (lbm) | Equal |\n", - "{glue:md}Aircraft.Wing.SWEEP | 22.99999998488638 (deg) | 22.99999998488638 (deg) | Equal |\n", - "{glue:md}Aircraft.LandingGear.MAIN_GEAR_MASS | 5766.748146883955 (lbm) | 5766.748146883955 (lbm) | Equal |\n", - "{glue:md}Aircraft.LandingGear.NOSE_GEAR_MASS | 747.1260464958017 (lbm) | 747.1260464958017 (lbm) | Equal |\n", - "{glue:md}Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO | 0.84 (unitless) | 0.84 (unitless) | Equal |\n", - "{glue:md}Aircraft.Furnishings.MASS | 14690.33988 (lbm) | 14690.33988 (lbm) | Equal |\n", - "{glue:md}Aircraft.CrewPayload.PASSENGER_SERVICE_MASS | 2524.475592961527 (lbm) | 2524.475592961527 (lbm) | Equal |\n", - "{glue:md}Mission.Summary.GROSS_MASS | 157432.51316817472 (lbm) | 120023.28881408491 (lbm) | Different |\n", - "{glue:md}Mission.Summary.FUEL_BURNED | 27042.6844662215 (lbm) | 22883.460112131652 (lbm) | Different |\n", - "{glue:md}Aircraft.CrewPayload.PASSENGER_MASS | 26730.0 (lbm) | 165.0 (lbm) | Different |\n", - "{glue:md}Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS | 32400.0 (lbm) | 200.0 (lbm) | Different |\n", - "{glue:md}Aircraft.CrewPayload.CARGO_MASS | 4077.0 (lbm) | 4077.0 (lbm) | Different |\n", - "{glue:md}Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS | 36477.0 (lbm) | 4277.0 (lbm) | Different |\n", + "```\n", + "Note: It is good practice, but not required, to set `Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO` in Aviary Values to ensure consistent design of the landing gear for both missions. This combined with `Design.GROSS_MASS` helps to ensure that `Aircraft.LandingGear.MAIN_GEAR_MASS` and `Aircraft.LandingGear.NOSE_GEAR_MASS` are the same for both missions. If `Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO` is not set, Landing Gear Masses will be caluclated based on`Mission.Summary.CRUISE_MACH` and Mission.Design.RANGE`. This is potentially problematic because `Mission.Summary.CRUISE_MACH` may not be set, and instead cruse mach may be optimized. In that case, `Mission.Summary.CRUISE_MACH` could vary between mission1 and mission2, which would then cascade into differeing `Aircraft.LandingGear.MAIN_GEAR_MASS` which causes the aircraft designs to diverge.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "prob.set_design_range(('mission1', 'mission2'), range='Aircraft1:RANGE')\n", "\n", + "prob.run_aviary_problem()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Results\n", + "The results of the [Multi-mission Example](\n", + "https://github.com/OpenMDAO/Aviary/tree/main/aviary/examples/multi_mission/run_multimission_example.py) are included in the data table and plots below.\n", + "\n", + "From the table results we can see that the mission1 and mission2 have the same {glue:md}`Mission.Design.GROSS_MASS`, which has been promoted to `Aircraft1:GROSS_MASS`. However, the {glue:md}`Mission.Summary.GROSS_MASS` varies as expected because these represent \"as-flown\" values. The full passengers mission (mission1) has the higher {glue:md}`Mission.Summary.GROSS_MASS`. Consequently, the {glue:md}`Mission.Summary.FUEL_BURNED` for each mission is different, higher for mission1, as expected because this mission is carrying more mass for the same mission. {glue:md}`Aircraft.Wing.SWEEP` is the same for both missions, indicating that the aircraft wings have been designed similarly in both cases. We do not want to see different values for the wing design because it would mean that the two pre-mission systems are not mirroring eachother. If they were not the same it would mean we are designing two different aircraft. \n", + "\n", + "The {glue:md}`Aircraft.LandingGear.MAIN_GEAR_MASS` and {glue:md}`Aircraft.LandingGear.NOSE_GEAR_MASS` masses were also displayed because they are sensitive to {glue:md}`Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO`. We expect these landing gear masses to be the same and they are which is good news for us and indicates that both pre-mission designs are mirroring eachother.\n", + "\n", + "The {glue:md}`Aircraft.Furnishings.MASS` and {glue:md}`Aircraft.CrewPayload.PASSENGER_SERVICE_MASS` are displayed. These values represent the weight of the seats and the air conditioning system for the passengers. They are both the same which is what we expect to see.\n", + "\n", + "The {glue:md}`Aircraft.Avionics.MASS` also match, indicating that the {glue:md}`Mission.Design.RANGE` for both aircraft has been properly set to the same value.\n", + "\n", + "\n", + "mission:design:gross_mass was unavailable. Perhapse it has been promoted to the problem level?\n", + "mission:design:gross_mass was unavailable. Perhapse it has been promoted to the problem level?\n", + " \n", + "mission1.aircraft:design:empty_mass (lbm), [87415.60555673]\n", + "mission2.aircraft:design:empty_mass (lbm), [87415.60555673]\n", + " \n", + "mission1.aircraft:landing_gear:main_gear_mass (lbm), [5767.0394946]\n", + "mission2.aircraft:landing_gear:main_gear_mass (lbm), [5767.0394946]\n", + " \n", + "mission1.aircraft:landing_gear:nose_gear_mass (lbm), [747.15266738]\n", + "mission2.aircraft:landing_gear:nose_gear_mass (lbm), [747.15266738]\n", + " \n", + "mission1.aircraft:design:landing_to_takeoff_mass_ratio (unitless), [0.84]\n", + "mission2.aircraft:design:landing_to_takeoff_mass_ratio (unitless), [0.84]\n", + "\n", + "mission1.aircraft:avionics:mass (lbm), [1281.74589387]\n", + "mission2.aircraft:avionics:mass (lbm), [1281.74589387]\n", + " \n", + "mission1.aircraft:furnishings:mass (lbm), [14690.33988]\n", + "mission2.aircraft:furnishings:mass (lbm), [14690.33988]\n", + " \n", + "mission1.aircraft:crew_and_payload:passenger_service_mass (lbm), [2524.47559296]\n", + "mission2.aircraft:crew_and_payload:passenger_service_mass (lbm), [2524.47559296]\n", + " \n", + "mission1.mission:summary:gross_mass (lbm), [157440.88610181]\n", + "mission2.mission:summary:gross_mass (lbm), [120056.71107322]\n", + " \n", + "mission1.mission:summary:fuel_burned (lbm), [27050.67106054]\n", + "mission2.mission:summary:fuel_burned (lbm), [22916.49603196]\n", + " \n", + "mission1.aircraft:crew_and_payload:passenger_mass (lbm), [26730.]\n", + "mission2.aircraft:crew_and_payload:passenger_mass (lbm), [165.]\n", + " \n", + "mission1.aircraft:crew_and_payload:passenger_payload_mass (lbm), [32400.]\n", + "mission2.aircraft:crew_and_payload:passenger_payload_mass (lbm), [200.]\n", + " \n", + "mission1.aircraft:crew_and_payload:cargo_mass (lbm), [4077.]\n", + "mission2.aircraft:crew_and_payload:cargo_mass (lbm), [4077.]\n", + " \n", + "mission1.aircraft:crew_and_payload:total_payload_mass (lbm), [36477.]\n", + "mission2.aircraft:crew_and_payload:total_payload_mass (lbm), [4277.]\n", + " \n", + "Objective Value (unitless): [25672.61271768]\n", + "Aircraft1:GROSS_MASS (lbm) [157440.88610181]\n", + "Aircraft1:SWEEP (deg) [23.]\n", + "\n", + "In the graph below The Altitude, Drag force, Throttle command, and Mass of the mission1 (full passenger load) and mission2 (one passenger) are displayed. The mission2 shows a characteristic smaller mass throughout the flight as expected since we have just one passenger, and a slightly lower throttle profile to match, indicating the engine is not being pushed as hard to meet the demands of a lighter plane. Otherwise the missions themselves match, showing Mach, Distance, and Altitude all identical for every part of the mission. We did not allow the mach or altitude to be optimized for this mission so these results are not surprising.\n", "\n", - "In the graph below The Altitude, Drag force, Throttle command, Mass, Distance, and Mach number of the Primary and Deadhead missions are displayed. The Deadhead mission shows a characteristic smaller mass throughout the flight as expected since we have fewer passengers, and a slightly lower throttle profile to match, indicating the engine is not being pushed as hard to meet the demands of a lighter plane. Otherwise the missions themselves match, showing Mach, Distance, and Altitude all identical for every part of the mission. We did not allow the mach or altitude to be optimized for this mission so these results are not surprising. \n", + "```\n", + "Note: When comparing the graphs of the two missions, not all the graphs have the same scale.\n", + "```\n", "\n", - "![Results](images/multi_mission.png \"Primary vs. Deadhead mission results\")" + "![Results](images/multi_mission.png \"mission1 vs. mission2 results\")" ] }, { @@ -153,7 +331,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -167,9 +345,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/examples/off_design_example.ipynb b/aviary/docs/examples/off_design_example.ipynb index 9b53836b06..416b5aa196 100644 --- a/aviary/docs/examples/off_design_example.ipynb +++ b/aviary/docs/examples/off_design_example.ipynb @@ -12,50 +12,25 @@ "An overview of off-design missions is presented in [Off-Design Mission User Guide](../user_guide/off_design_missions).\n", "\n", "The example is available in `aviary/examples/run_off_design_example.py`\n", - "The examples start with `run_aviary_example.py` and adds off-design missions.\n", + "It uses the `run_level2_example.py` script and additionally runs two off-design missions.\n", "\n", "The results of the sizing problem are saved using `prob.save_sizing_to_json()`.\n", "By default, this method saves the results to `sizing_problem.json` but the name of the file may be changed using the `json_filename` argument.\n", "The saved problem may then be used to run off-design missions using `prob.fallout_mission()` and `prob.alternate_mission()`.\n", "\n", - "This example can be modified to use the 2DOF formulation by using `aircraft_for_bench_GwGm` instead of `aircraft_for_bench_FwFm` and import the default 2DOF phase_info (aviary/interface/default_phase_info/two_dof.py) instead of the `phase_info` declared in the problem.\n" + "This example can be modified to use the 2DOF formulation by using `aircraft_for_bench_GwGm` instead of `aircraft_for_bench_FwFm` and import the default 2DOF phase_info (aviary/models/missions/two_dof_default.py) instead of the `phase_info` declared in the problem.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The methods used to run the off-design missions accept the mission parameters `payload_mass`, `mission_range`, `mission_mass`, and `phase_info` as inputs depending on the type of mission being run.\n", + "The methods used to run the off-design missions accept a variety of arguments including `phase_info`, some mission configuration variables such as `equations_of_motion`, and inputs that depend on the type of mission being run such as payload, passenger count, and range.\n", "If these values are not specified, the same values as the design mission are used by default.\n", - "For this example, we simply run a fallout and alternate mission with those default values.\n", - "The expected result is that the range for the fallout mission and the mission mass for the alternate will be the same as the values computed by the sizing mission.\n", - "\n", - "The results of this study are output after interrogating the problem objects." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "## Sizing Results\n", - "Design Range = 3375.\n", - "Design Gross mass = 175871.01115631\n", - "Summary Gross mass = 175871.01115631\n", - "\n", - "## Fallout Results\n", - "Summary Range = 3375.00699084\n", - "Design Gross mass = 175871.01115631\n", - "Summary Gross mass = 175871.01115631\n", - "\n", - "## Alternate Results\n", - "Summary Range = 3375.\n", - "Design Gross mass = 175871.01115631\n", - "Summary Gross mass = 175869.64047452\n", "\n", + "The expected result is that specified variables, such a new payload, passenger count, or range, are reflected in the results of the off-design mission. Variables that should not change, such as takeoff gross mass, or other `Design` values, are also printed to demonstrate that they remain unchanged. This proves that the aircraft was not resized and instead was only flown on a new mission.\n", "\n", - "In these results, `design` values represent the values used to size the aircraft, while the `summary` values represent the values used in the specific mission that is run.\n", - "We can see that the results are almost identical as expected." + "When looking at the specific variables that were selected for printing in this example, `design` values represent the values used to size the aircraft, while the `summary` values represent the values used in the specific mission that was run." ] } ], diff --git a/aviary/docs/examples/outputted_phase_info.py b/aviary/docs/examples/outputted_phase_info.py deleted file mode 100644 index daf97400c1..0000000000 --- a/aviary/docs/examples/outputted_phase_info.py +++ /dev/null @@ -1,2 +0,0 @@ -phase_info = {'pre_mission': {'include_takeoff': True, 'optimize_mass': True}, 'climb_1': {'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, 'user_options': {'optimize_mach': True, 'optimize_altitude': True, 'polynomial_control_order': [1, 2], 'use_polynomial_control': True, 'num_segments': [1], 'order': 1, 'solve_for_distance': True, 'initial_mach': (1, None), 'final_mach': (2, None), 'mach_bounds': ( - (0.98, 2.02), None), 'initial_altitude': (1, None), 'final_altitude': (2, None), 'altitude_bounds': ((0.0, 502), None), 'throttle_enforcement': 'path_constraint', 'fix_initial': True, 'constrain_final': True, 'fix_duration': False, 'initial_bounds': ((0.0, 0.0), None), 'duration_bounds': ((0.5, 1.5), None)}, 'initial_guesses': {'time': ([1, 1], None)}}, 'post_mission': {'include_landing': True, 'constrain_range': True, 'target_range': (514.5, None)}} diff --git a/aviary/docs/examples/reserve_missions.ipynb b/aviary/docs/examples/reserve_missions.ipynb index 15b3b0e7c9..8deb3c4eaa 100644 --- a/aviary/docs/examples/reserve_missions.ipynb +++ b/aviary/docs/examples/reserve_missions.ipynb @@ -11,182 +11,72 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.functions import get_path, get_model\n", + "import aviary.api as av\n", "from aviary.utils.doctape import glue_variable\n", + "from aviary.utils.functions import get_model, get_path\n", "\n", "folder = get_path('examples/reserve_missions')\n", - "aviary_top_dir = get_path('docs').parent.parent\n", - "reserve_missions_dir = folder.relative_to(aviary_top_dir)\n", - "glue_variable(str(reserve_missions_dir), md_code=True)\n", + "reserve_missions_dir = folder.relative_to(av.top_dir.parent)\n", + "glue_variable(reserve_missions_dir, md_code=True)\n", "\n", - "run_basic_aviary_example = 'run_basic_aviary_example.py'\n", - "get_path(folder.parent.joinpath(run_basic_aviary_example))\n", - "glue_variable(str(run_basic_aviary_example), md_code=True)\n", + "level1_example = 'run_level1_example.py'\n", + "get_path(folder.parent.joinpath(level1_example))\n", + "glue_variable(level1_example, md_code=True)\n", "\n", - "aircraft_for_bench_GwGm = get_model('aircraft_for_bench_GwGm.csv')\n", - "glue_variable(aircraft_for_bench_GwGm.stem, md_code=True)\n", - "\n", - "aircraft_for_bench_FwFm = get_model('aircraft_for_bench_FwFm.csv')\n", - "glue_variable(aircraft_for_bench_FwFm.stem, md_code=True)\n", - "\n", - "example_phase_info = 'example_phase_info'\n", - "get_path(folder.parent.joinpath(example_phase_info+'.py'))\n", - "glue_variable(str(example_phase_info), md_code=True)\n", - "\n", - "run_reserve_mission_fixedrange = 'run_reserve_mission_fixedrange.py'\n", - "get_path(folder.joinpath(run_reserve_mission_fixedrange))\n", - "glue_variable(str(run_reserve_mission_fixedrange), md_code=True)\n", - "\n", - "run_2dof_reserve_mission_fixedrange = 'run_2dof_reserve_mission_fixedrange.py'\n", - "get_path(folder.joinpath(run_2dof_reserve_mission_fixedrange))\n", - "glue_variable(str(run_2dof_reserve_mission_fixedrange), md_code=True)\n", + "run_reserve_mission_multiphase = 'run_reserve_mission_multiphase.py'\n", + "get_path(folder.joinpath(run_reserve_mission_multiphase))\n", + "glue_variable(run_reserve_mission_multiphase, md_code=True)\n", "\n", "expected_values = {\n", - " \"reserve\": True,\n", - " \"target_distance\": (200, 'km'),\n", - " \"target_duration\": (30, 'min'),\n", - " }\n", + " 'reserve': True,\n", + " 'target_distance': (300, 'km'),\n", + " 'time_duration': (30, 'min'),\n", + "}\n", "for key, val in expected_values.items():\n", " glue_variable(key, md_code=True)\n", " var_with_val = f'\"{key}\": {val},'\n", - " glue_variable(key+'_with_val', var_with_val, md_code=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Reserve Mission Examples\n", - "\n", - "The reserve mission examples are broken up into two sections: height-energy missions, and 2DOF missions.\n", - "By default Aviary uses a height-energy formulation unless you have specified otherwise.\n", - "Single phase reserves for fixed-time and fixed-range will be presented as well as an example of a multiphase reserve mission.\n", - "An overview of how to formulate a reserve mission is presented in [Reserve Mission User Guide](../user_guide/reserve_missions).\n", - "\n", - "All of the reserve mission examples are available in {glue:md}`aviary/examples/reserve_missions`\n", - "The examples start with {glue:md}`run_basic_aviary_example.py` and add reserve phases.\n", - "The 2DOF examples use {glue:md}`aircraft_for_bench_GwGm` instead of {glue:md}`aircraft_for_bench_FwFm` and import the default two_dof phase_info instead of the {glue:md}`example_phase_info`.\n", - "\n", - "## Fixed Range Reserve\n", - "\n", - "The simplest example of a reserve mission implementation can be seen in fixed-range examples, which add a fixed-range cruise to the end of the basic mission.\n", - "\n", - "* Height Energy: {glue:md}`run_reserve_mission_fixedrange.py`\n", - "* Two Degree of Freedom: {glue:md}`run_2dof_reserve_mission_fixedrange.py`\n", - "\n", - "This is performed by making a copy the cruise `phase_info` object and adding {glue:md}`reserve_with_val` and {glue:md}`target_distance_with_val`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "from aviary.interface.utils.check_phase_info import check_phase_info, HEIGHT_ENERGY\n", - "from aviary.utils.functions import get_path\n", - "from aviary.utils.doctape import glue_variable, check_value, get_all_keys\n", - "# from aviary.utils.doctape import check_contains, expected_error\n", - "\n", - "folder = get_path('examples/reserve_missions')\n", - "\n", - "from aviary.examples.reserve_missions.run_reserve_mission_fixedrange import phase_info\n", - "check_phase_info(phase_info, HEIGHT_ENERGY);\n", - "user_opts = phase_info['reserve_cruise']['user_options']\n", - "check_value(user_opts['target_distance'],(200, 'km'))\n", - "check_value(user_opts['reserve'],True)\n", - "\n", - "run_reserve_mission_fixedtime = 'run_reserve_mission_fixedtime.py'\n", - "get_path(folder.joinpath(run_reserve_mission_fixedtime))\n", - "glue_variable(str(run_reserve_mission_fixedtime), md_code=True)\n", - "\n", - "from aviary.examples.reserve_missions.run_reserve_mission_fixedtime import phase_info\n", - "check_phase_info(phase_info, HEIGHT_ENERGY);\n", - "user_opts = phase_info['reserve_cruise']['user_options']\n", - "check_value(user_opts['target_duration'],(30, 'min'))\n", - "check_value(user_opts['reserve'],True)\n", - "all_keys = get_all_keys(phase_info['reserve_cruise'], track_layers=True)\n", - "for key in all_keys:\n", - " glue_variable(key.replace('.','-'), md_code=True)\n", - "print(all_keys)\n", - "\n", - "# ******NOTE****** These were not removed, as the docs seem to indicate\n", - "# time = 'initial_guesses:time'\n", - "# duration_bounds = 'user_options:duration_bounds'\n", - "# fixed_duration = 'user_options:fixed_duration'\n", - "# for key in (time,duration_bounds,fixed_duration):\n", - "# try:\n", - "# check_contains(key, all_keys, error_type=expected_error)\n", - "# raise RuntimeError(f'phase_info should not contain `{key}`, but does')\n", - "# except expected_error:\n", - "# pass\n", - "\n", - "run_2dof_reserve_mission_fixedtime = 'run_2dof_reserve_mission_fixedtime.py'\n", - "get_path(folder.joinpath(run_2dof_reserve_mission_fixedtime))\n", - "glue_variable(str(run_2dof_reserve_mission_fixedtime), md_code=True)\n", - "\n", - "run_reserve_mission_multiphase = 'run_reserve_mission_multiphase.py'\n", - "get_path(folder.joinpath(run_reserve_mission_multiphase))\n", - "glue_variable(str(run_reserve_mission_multiphase), md_code=True)\n", - "\n", - "run_2dof_reserve_mission_multiphase = 'run_2dof_reserve_mission_multiphase.py'\n", - "get_path(folder.joinpath(run_2dof_reserve_mission_multiphase))\n", - "glue_variable(str(run_2dof_reserve_mission_multiphase), md_code=True)" + " glue_variable(key + '_with_val', var_with_val, md_code=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The results of this study are shown in the `traj_results_report.html`.\n", - "The first thing we review is the altitude plot.\n", - "This plot clearly shows that a reserve cruise phase was created at the end of the regular mission.\n", - "There is no climb phase in that reserve; we jump to cruising altitude and cruise for 200 km.\n", + "# Reserve Mission Example\n", + "The following is an example implementation of a reserve mission as outlined in the [Reserve Mission User Guide](../user_guide/reserve_missions). The full script that runs this example is avaliable in {glue:md}`aviary/examples/reserve_missions`\n", "\n", - "![Altitude](images/fixed_range_cruise_altitude.png \"Altitude vs. Time for Fixed Range Cruise Reserve Example\")\n", + "The example is based off of the {glue:md}`run_level1_example.py` and adds a reserve mission with multiple phases. The reserve mission consists of a climb phase, a fixed-range cruise phase, a fixed-duration cruise phase, and then finally a descent phase.\n", "\n", - "Additionally when looking at the mass and distance plots from the same study, we can see that the regular and reserve phases are connected properly.\n", - "There is no discontinuity between regular and reserve phases for either distance or mass.\n", + "This multiphase reserve mission example demonstrates how to create an arbitrarily ordered set of phases for a reserve mission, including climb and descent phases. The same phase info used in the Level 1 example is imported, then reserve mission segments are manually defined and added to it. These new phases are specifically treated as reserve mission segments by Aviary because they contain the option `\"reserve\": True`.\n", "\n", - "![Distance](images/fixed_range_cruise_distance.png \"Distance vs. Time for Fixed Range Cruise Reserve Example\")\n", - "![Mass](images/fixed_range_cruise_mass.png \"Mass vs. Time for Fixed Range Cruise Reserve Example\")\n", + "For the first cruise phase, the range is fixed to 300 km. This is done by adding `\"target_distance\": (300, 'km')` to that phase's options.\n", "\n", - "## Fixed Time Reserve\n", + "The second cruise phase is set to a 30 min duration, essentially a loiter segment. This is done by setting the option `\"time_duration\": (30, 'min')`.\n", "\n", - "Similar to the fixed-range example, a simple fixed-time reserve mission is also provided.\n", + "These two options are mutually exclusive - you can't fix both distance and duration in your mission, or the problem becomes infeasible and can't be solved.\n", "\n", - "* Height Energy: {glue:md}`run_reserve_mission_fixedtime.py`\n", - "* Two Degree of Freedom: {glue:md}`run_2dof_reserve_mission_fixedtime.py`\n", + "Results from this mission can be seen in the figure below.\n", "\n", - "Again, we make a copy of the cruise phase from `phase_info` and then modify it by adding {glue:md}`reserve_with_val` and {glue:md}`target_duration_with_val`.\n", - "We have also removed other references to time in the reserve phase definition.\n", - "We do not list {glue:md}`initial_guesses-time`, {glue:md}`user_options-duration_bounds`, or {glue:md}`user_options-fix_duration`.\n", - "All of these are set automatically when we set {glue:md}`target_duration`.\n", + "![MultiphaseTrajectory](images/multiphase_reserve_altitude.png)\n", "\n", - "## Multiphase Reserve Mission\n", + "The reserve mission can be clearly seen following the regular mission.\n", + "There are two distinct cruise segments visible within the reserve mission, which are our fixed-distance and fixed-duration cruises.\n", "\n", - "The last example reserve mission includes five phases: climb, cruise for distance, cruise for time, cruise for distance, descend.\n", + "We can also take a look at the plots of distance and mass vs. time to verify that the reserve mission directly connects to the main mission without any discontinuities.\n", "\n", - "* Height Energy: {glue:md}`run_reserve_mission_multiphase.py`\n", - "* Two Degree of Freedom: {glue:md}`run_2dof_reserve_mission_multiphase.py`\n", + "![MultiphaseDistance](images/multiphase_reserve_distance.png)\n", + "![MultiphaseMass](images/multiphase_reserve_mass.png)\n", "\n", - "This demonstrates how to create an arbitrarily ordered set of phases for reserve, including climb and descent phases.\n", - "All of these reserve phases are tagged with {glue:md}`reserve_with_val`.\n", + "## Discontinuous Reserve Missions\n", + "It is possible to define a reserve mission that does not directly connect to the main mission. This may be desired for a variety of reasons, and is easily accomplished. For example, if you removed the climb, fixed-duration cruise, and descent segments from the multiphase reserve mission (leaving only the fixed-range cruise), you can generate a discontinuous mission trajectory that looks like the following:\n", "\n", - "Results from this mission can be seen in the figure below.\n", - "![Multiphase](images/multiphase_reserve.png \"Distance vs. Time for Multiphase Reserve Example\")\n", - "There are three distinct cruise segments and the added reserve climb and reserve descent show a more realistic flight profile for a diverted aircraft." + "![SinglePhaseTrajectory](images/fixed_range_reserve_altitude.png)" ] } ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -200,9 +90,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.9" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/examples/simple_mission_example.ipynb b/aviary/docs/examples/simple_mission_example.ipynb index e712dd1edd..255b920c82 100644 --- a/aviary/docs/examples/simple_mission_example.ipynb +++ b/aviary/docs/examples/simple_mission_example.ipynb @@ -40,7 +40,7 @@ "source": [ "import aviary.api as av\n", "\n", - "filename = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "filename = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "filename = av.get_path(filename)\n", "\n", "with open(filename, 'r') as file:\n", @@ -79,14 +79,14 @@ "source": [ "# Testing Cell\n", "import aviary.api as av\n", - "from aviary.utils.doctape import check_value, glue_variable\n", "from aviary.interface.cmd_entry_points import _command_map\n", + "from aviary.utils.doctape import check_value, glue_variable\n", "\n", "check_value(av.LegacyCode.FLOPS.value, 'FLOPS')\n", "check_value(av.EquationsOfMotion.HEIGHT_ENERGY.value, 'height_energy')\n", "\n", "draw_mission = 'draw_mission'\n", - "_command_map[draw_mission];\n", + "_command_map[draw_mission]\n", "glue_variable(draw_mission, md_code=True)" ] }, @@ -167,83 +167,72 @@ "outputs": [], "source": [ "phase_info = {\n", - " \"pre_mission\": {\"include_takeoff\": False, \"optimize_mass\": True},\n", - " \"climb_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 2,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.2, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (0.0, \"ft\"),\n", - " \"final_altitude\": (30500.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 31000.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": True,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((0.0, 0.0), \"min\"),\n", - " \"duration_bounds\": ((27.0, 81.0), \"min\"),\n", + " 'pre_mission': {'include_takeoff': False, 'optimize_mass': True},\n", + " 'climb_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 2,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.2, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (0.0, 'ft'),\n", + " 'altitude_final': (30500.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 31000.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'time_duration_bounds': ((27.0, 81.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([0, 54], \"min\")},\n", + " 'initial_guesses': {'time': ([0, 54], 'min')},\n", " },\n", - " \"cruise\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 2,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.7, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (30500.0, \"ft\"),\n", - " \"final_altitude\": (31000.0, \"ft\"),\n", - " \"altitude_bounds\": ((30000.0, 31500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((27.0, 81.0), \"min\"),\n", - " \"duration_bounds\": ((85.5, 256.5), \"min\"),\n", + " 'cruise': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 2,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (30500.0, 'ft'),\n", + " 'altitude_final': (31000.0, 'ft'),\n", + " 'altitude_bounds': ((30000.0, 31500.0), 'ft'),\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((27.0, 81.0), 'min'),\n", + " 'time_duration_bounds': ((85.5, 256.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([54, 171], \"min\")},\n", + " 'initial_guesses': {'time': ([54, 171], 'min')},\n", " },\n", - " \"descent_1\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 2,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.2, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (31000.0, \"ft\"),\n", - " \"final_altitude\": (500.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 31500.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": True,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((112.5, 337.5), \"min\"),\n", - " \"duration_bounds\": ((26.5, 79.5), \"min\"),\n", + " 'descent_1': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 2,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.2, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_initial': (31000.0, 'ft'),\n", + " 'altitude_final': (500.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 31500.0), 'ft'),\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((112.5, 337.5), 'min'),\n", + " 'time_duration_bounds': ((26.5, 79.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([225, 53], \"min\")},\n", + " 'initial_guesses': {'time': ([225, 53], 'min')},\n", " },\n", - " \"post_mission\": {\n", - " \"include_landing\": False,\n", - " \"constrain_range\": True,\n", - " \"target_range\": (1915, \"nmi\"),\n", + " 'post_mission': {\n", + " 'include_landing': False,\n", + " 'constrain_range': True,\n", + " 'target_range': (1915, 'nmi'),\n", " },\n", "}" ] @@ -281,8 +270,8 @@ "from aviary.utils.doctape import glue_variable\n", "\n", "run_mission = 'run_mission'\n", - "_command_map[run_mission];\n", - "glue_variable('aviary '+run_mission, md_code=True)" + "_command_map[run_mission]\n", + "glue_variable('aviary ' + run_mission, md_code=True)" ] }, { @@ -315,7 +304,7 @@ "This means that the optimizer will determine the throttle value that allows the aircraft to fly the prescribed mission while minimizing fuel burn across the mission.\n", "\n", "We could allow the optimizer to control the Mach and altitude values as well.\n", - "By checking the appropriate boxes in the GUI or by setting the `optimize_mach` or `optimize_altitude` flags to `True` in the `phase_info` dict, Aviary will find the best Mach and altitude values for each phase.\n", + "By checking the appropriate boxes in the GUI or by setting the `mach_optimize` or `altutude_optimize` flags to `True` in the `phase_info` dict, Aviary will find the best Mach and altitude values for each phase.\n", "There are many more options available to expose to the optimizer here that allow us to control the mission definition.\n", "We will discuss more of these options in other examples.\n", "\n", @@ -336,8 +325,12 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " phase_info, optimizer=\"SLSQP\", make_plots=True)" + "prob = av.run_aviary(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " phase_info,\n", + " optimizer='SLSQP',\n", + " make_plots=True,\n", + ")" ] }, { @@ -414,9 +407,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/getting_started/expected_user_knowledge.md b/aviary/docs/getting_started/expected_user_knowledge.md index 279692a4bd..414b849614 100644 --- a/aviary/docs/getting_started/expected_user_knowledge.md +++ b/aviary/docs/getting_started/expected_user_knowledge.md @@ -66,7 +66,7 @@ Users have complete control over the Aviary model and how the methods are called ## Familiarity with dependencies As users dig deeper into the Aviary code, they will encounter the various dependencies that Aviary relies on. -The most important of these is OpenMDAO, which is the optimization framework that Aviary is built on top of. In addition to its [basic user guide](https://openmdao.org/newdocs/versions/latest/basic_user_guide/basic_user_guide.htmlAviary), users are encouraged to learn more about the following topics in the [OpenMDAO Advanced User Guide](https://openmdao.org/newdocs/versions/latest/advanced_user_guide/advanced_user_guide.html): +The most important of these is OpenMDAO, which is the optimization framework that Aviary is built on top of. In addition to its [basic user guide](https://openmdao.org/newdocs/versions/latest/basic_user_guide/basic_user_guide.html), users are encouraged to learn more about the following topics in the [OpenMDAO Advanced User Guide](https://openmdao.org/newdocs/versions/latest/advanced_user_guide/advanced_user_guide.html): - [Implicit Components](https://openmdao.org/newdocs/versions/latest/features/core_features/working_with_components/implicit_component.html) - [N2 Diagram](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_details/n2_details.html) - [Nonlinear and Linear Solvers](https://openmdao.org/newdocs/versions/latest/features/core_features/controlling_solver_behavior/set_solvers.html) diff --git a/aviary/docs/getting_started/images/N2_phases_links.PNG b/aviary/docs/getting_started/images/N2_phases_links.PNG index e7ead84f3c..0bbbc5d353 100644 Binary files a/aviary/docs/getting_started/images/N2_phases_links.PNG and b/aviary/docs/getting_started/images/N2_phases_links.PNG differ diff --git a/aviary/docs/getting_started/images/N2_start.PNG b/aviary/docs/getting_started/images/N2_start.PNG index 757ecd2d5a..e8560c9e89 100644 Binary files a/aviary/docs/getting_started/images/N2_start.PNG and b/aviary/docs/getting_started/images/N2_start.PNG differ diff --git a/aviary/docs/getting_started/images/opt_report_top.PNG b/aviary/docs/getting_started/images/opt_report_top.PNG index 56118d7fd6..5efbb1753c 100644 Binary files a/aviary/docs/getting_started/images/opt_report_top.PNG and b/aviary/docs/getting_started/images/opt_report_top.PNG differ diff --git a/aviary/docs/getting_started/images/traj_results_report_altitude.PNG b/aviary/docs/getting_started/images/traj_results_report_altitude.PNG index 8e2185eb76..87acb30f26 100644 Binary files a/aviary/docs/getting_started/images/traj_results_report_altitude.PNG and b/aviary/docs/getting_started/images/traj_results_report_altitude.PNG differ diff --git a/aviary/docs/getting_started/images/traj_results_report_top_ascent.PNG b/aviary/docs/getting_started/images/traj_results_report_top_ascent.PNG index 519434c8d7..7fe4775075 100644 Binary files a/aviary/docs/getting_started/images/traj_results_report_top_ascent.PNG and b/aviary/docs/getting_started/images/traj_results_report_top_ascent.PNG differ diff --git a/aviary/docs/getting_started/input_csv_phase_info.ipynb b/aviary/docs/getting_started/input_csv_phase_info.ipynb index 1195b3b9f1..4ef92808c4 100644 --- a/aviary/docs/getting_started/input_csv_phase_info.ipynb +++ b/aviary/docs/getting_started/input_csv_phase_info.ipynb @@ -11,21 +11,22 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.functions import get_model\n", "from aviary.utils.doctape import glue_variable\n", + "from aviary.utils.functions import get_model\n", "\n", "csv_snippet = '```\\n'\n", - "filename = 'aircraft_for_bench_FwFm.csv'\n", + "filename = 'aircraft_for_bench_FwGm.csv'\n", "with open(get_model(filename)) as f_in:\n", " lines = f_in.readlines()\n", " l, s = [], 1\n", + " # pick up a few rows from the top and the bottom\n", " for ii in range(7):\n", - " l.append(lines[ii*2*s])\n", - " s*=-1\n", + " l.append(lines[ii * 2 * s])\n", + " s *= -1\n", " l.sort()\n", - " csv_snippet+=''.join(l)\n", + " csv_snippet += ''.join(l)\n", "\n", - "csv_snippet+='...\\n```'\n", + "csv_snippet += '...\\n```'\n", "glue_variable('csv_snippet', csv_snippet)" ] }, @@ -66,20 +67,19 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.process_input_decks import create_vehicle\n", - "from aviary.utils.aviary_values import AviaryValues\n", - "from aviary.utils.process_input_decks import initialization_guessing\n", "from aviary.api import Aircraft, LegacyCode\n", "from aviary.interface.cmd_entry_points import _command_map\n", - "from aviary.utils.doctape import glue_variable, get_variable_name\n", + "from aviary.utils.aviary_values import AviaryValues\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.utils.process_input_decks import create_vehicle, initialization_guessing\n", "\n", "default_guesses = '```\\n'\n", "vehicle_deck = AviaryValues()\n", - "_ , initialization_guesses = create_vehicle(vehicle_deck=vehicle_deck)\n", + "_, initialization_guesses = create_vehicle(vehicle_deck=vehicle_deck)\n", "for key, val in initialization_guesses.items():\n", - " default_guesses+=f\"{key},{val}\\n\"\n", + " default_guesses += f'{key},{val}\\n'\n", " glue_variable(key, md_code=True)\n", - "default_guesses+='```'\n", + "default_guesses += '```'\n", "glue_variable('default_guesses', default_guesses)\n", "\n", "\n", @@ -87,7 +87,7 @@ "glue_variable(get_variable_name(Aircraft.Design.RESERVE_FUEL_FRACTION), md_code=True)\n", "\n", "f2a = 'fortran_to_aviary'\n", - "_command_map[f2a];\n", + "_command_map[f2a]\n", "glue_variable(f2a)\n", "glue_variable(LegacyCode.GASP.name)" ] @@ -129,47 +129,55 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.default_phase_info.height_energy import phase_info as HE_phase_info\n", - "from aviary.interface.default_phase_info.two_dof import phase_info as TwoDOF_phase_info\n", - "from aviary.interface.utils.check_phase_info import check_phase_info, HEIGHT_ENERGY, TWO_DEGREES_OF_FREEDOM\n", - "from aviary.utils.doctape import glue_keys\n", - "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "# All valid options are contained in the options dictionary definitions.\n", "from copy import deepcopy\n", - "import openmdao.api as om\n", "\n", - "check_phase_info(HE_phase_info, HEIGHT_ENERGY);\n", - "check_phase_info(TwoDOF_phase_info, TWO_DEGREES_OF_FREEDOM);\n", + "import openmdao.api as om\n", "\n", - "def get_completed_phase_info(filename, phase_info=None):\n", - " prob = AviaryProblem()\n", - " prob.load_inputs(filename, phase_info=phase_info)\n", - " prob.check_and_preprocess_inputs()\n", - " prob.add_phases()\n", - " complete_phase_info = {}\n", - " for phase in prob.phase_objects:\n", - " phase_name, info = phase.to_phase_info()\n", - " complete_phase_info[phase_name] = info\n", - " return complete_phase_info\n", + "from aviary.models.missions.height_energy_default import phase_info as HE_phase_info\n", + "from aviary.models.missions.two_dof_default import phase_info as TwoDOF_phase_info\n", + "from aviary.mission.flight_phase_builder import FlightPhaseOptions\n", + "from aviary.mission.flops_based.phases.groundroll_phase import GroundrollPhaseOptions as FGopt\n", + "from aviary.mission.gasp_based.phases.accel_phase import AccelPhaseOptions\n", + "from aviary.mission.gasp_based.phases.ascent_phase import AscentPhaseOptions\n", + "from aviary.mission.gasp_based.phases.climb_phase import ClimbPhaseOptions\n", + "from aviary.mission.gasp_based.phases.cruise_phase import CruisePhaseOptions\n", + "from aviary.mission.gasp_based.phases.descent_phase import DescentPhaseOptions\n", + "from aviary.mission.gasp_based.phases.groundroll_phase import GroundrollPhaseOptions as GGopt\n", + "from aviary.mission.gasp_based.phases.rotation_phase import RotationPhaseOptions\n", + "from aviary.mission.gasp_based.phases.twodof_phase import TwoDOFPhaseOptions\n", + "from aviary.utils.doctape import glue_keys\n", "\n", "solved_alpha = deepcopy(HE_phase_info['cruise'])\n", "solved_alpha['subsystem_options']['core_aerodynamics']['method'] = 'solved_alpha'\n", - "solved_alpha['subsystem_options']['core_aerodynamics']['aero_data'] = \\\n", - " \"subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt\"\n", + "solved_alpha['subsystem_options']['core_aerodynamics']['aero_data'] = (\n", + " 'subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt'\n", + ")\n", "\n", "pre_mission = deepcopy(HE_phase_info['pre_mission'])\n", "pre_mission['linear_solver'] = om.DirectSolver()\n", "pre_mission['nonlinear_solver'] = om.NewtonSolver()\n", + "pre_mission['external_subsystems'] = []\n", "\n", - "custom_phase_info = {'pre_mission':pre_mission, 'solved_alpha':solved_alpha}\n", + "custom_phase_info = {'pre_mission': pre_mission, 'solved_alpha': solved_alpha}\n", "\n", "dummy_phase_info = {}\n", - "dummy_phase_info.update(HE_phase_info)\n", - "dummy_phase_info.update(get_completed_phase_info('aircraft_for_bench_FwFm.csv'))\n", "dummy_phase_info.update(custom_phase_info)\n", - "dummy_phase_info.update(get_completed_phase_info('aircraft_for_bench_FwFm.csv', custom_phase_info))\n", + "dummy_phase_info.update(pre_mission)\n", + "dummy_phase_info.update(HE_phase_info)\n", "dummy_phase_info.update(TwoDOF_phase_info)\n", - "dummy_phase_info.update(get_completed_phase_info('aircraft_for_bench_GwGm.csv'))\n", - "glue_keys(dummy_phase_info)\n" + "\n", + "dummy_phase_info.update(AccelPhaseOptions().items())\n", + "dummy_phase_info.update(AscentPhaseOptions().items())\n", + "dummy_phase_info.update(ClimbPhaseOptions().items())\n", + "dummy_phase_info.update(CruisePhaseOptions().items())\n", + "dummy_phase_info.update(DescentPhaseOptions().items())\n", + "dummy_phase_info.update(FGopt().items())\n", + "dummy_phase_info.update(FlightPhaseOptions().items())\n", + "dummy_phase_info.update(GGopt().items())\n", + "dummy_phase_info.update(RotationPhaseOptions().items())\n", + "dummy_phase_info.update(TwoDOFPhaseOptions().items())\n", + "glue_keys(dummy_phase_info)" ] }, { @@ -186,56 +194,47 @@ " - {glue:md}`required_available_climb_rate`: the minimum rate of climb required from the aircraft at the top of climb (beginning of cruise) point in the mission. You don't want your available rate-of-climb to be 0 in case you need to gain altitude during cruise.\n", " - {glue:md}`EAS_limit`: the maximum descending EAS in knots.\n", " - {glue:md}`throttle`: the prescribed throttle setting. This is only used for `GASP` and `solved` missions.\n", - "- If a key ends with `_ref` or `_ref0` (except {glue:md}`duration_ref` and {glue:md}`initial_ref`), it is the unit-reference and zero-reference values of the control variable at the nodes. This option is invalid if opt=False. Note that it is a simple usage of ref and ref0. We refer to [Dymos](https://openmdao.github.io/dymos/api/phase_api.html?highlight=ref0#add-state) for details.\n", + "- If a key ends with `_ref` or `_ref0` (except {glue:md}`time_duration_ref` and {glue:md}`time_initial_ref`), it is the unit-reference and zero-reference values of the control variable at the nodes. This option is invalid if opt=False. Note that it is a simple usage of ref and ref0. We refer to [Dymos](https://openmdao.github.io/dymos/api/phase_api.html?highlight=ref0#add-state) for details.\n", "- Some keys are for phase time only.\n", - " - {glue:md}`duration_ref` is the unit-reference for phase time duration.\n", - " - {glue:md}`duration_bounds` are the bounds (lower, upper) for the time duration of the phase.\n", - " - {glue:md}`initial_ref` is the unit-reference for the initial value of time.\n", - " - {glue:md}`initial_bounds`: the lower and upper bounds of initial time.\n", - "- If a key starts with `final_`, it is the final value of a state variable.\n", + " - {glue:md}`time_duration_ref` is the unit-reference for phase time duration.\n", + " - {glue:md}`time_duration_bounds` are the bounds (lower, upper) for the time duration of the phase.\n", + " - {glue:md}`time_initial_ref` is the unit-reference for the initial value of time.\n", + " - {glue:md}`time_initial_bounds`: the lower and upper bounds of initial time.\n", + "- If a key ends with `_final`, it is the final value of a state variable.\n", "- If a key ends with `_constraint_eq`, it is an equality constraint.\n", "\n", "- Keys related to altitude:\n", - " - We use {glue:md}`final_altitude` to indicate the final altitude of the phase.\n", + " - We use {glue:md}`altitude_final` to indicate the final altitude of the phase.\n", " - Meanwhile, {glue:md}`alt` is a key in acceleration phase parameter for altitude in `GASP` missions and {glue:md}`altitude` is a key in all other phases of all missions.\n", "\n", "- Some keys are a boolean flag of True or False:\n", - " - {glue:md}`input_initial`: the flag to indicate whether initial values of of a state (such as: altitude, velocity, mass, etc.) is taken.\n", - " - {glue:md}`add_initial_mass_constraint`: the flag to indicate whether to add initial mass constraint\n", " - {glue:md}`clean`: the flag to indicate no flaps or gear are included.\n", - " - {glue:md}`connect_initial_mass`: the flag to indicate whether the initial mass is the same as the final mass of previous phase.\n", - " - {glue:md}`fix_initial`: the flag to indicate whether the initial state variables is fixed.\n", " - {glue:md}`no_climb`: if True for the descent phase, the aircraft is not allowed to climb during the descent phase.\n", " - {glue:md}`no_descent`: if True for the climb phase, the aircraft is not allowed to descend during the climb phase.\n", " - {glue:md}`include_landing`: the flag to indicate whether there is a landing phase.\n", " - {glue:md}`include_takeoff`: the flag to indicate whether there is a takeoff phase.\n", " - {glue:md}`optimize_mass`: if True, the gross takeoff mass of the aircraft is a design variable.\n", - " - {glue:md}`target_mach`: the flag to indicate whether to target mach number.\n", + " - {glue:md}`target_mach`: the flag to indicate whether to target Mach number.\n", "- {glue:md}`initial_guesses`: initial guesses of state variables.\n", "- `COLLOCATION` related keys:\n", - " - {glue:md}`num_segments`: the number of segments in transcription creation in Dymos. The minimum value is 1. This is needed if 'AnalysisScheme' is `COLLOCATION`.\n", - " - {glue:md}`order`: the order of polynomials for interpolation in transcription creation in Dymos. The minimum value is 3. This is needed if 'AnalysisScheme' is `COLLOCATION`.\n", + " - {glue:md}`num_segments`: the number of segments in transcription creation in Dymos. The minimum value is 1.\n", + " - {glue:md}`order`: the order of polynomials for interpolation in transcription creation in Dymos. The minimum value is 3.\n", "- Other Aviary keys:\n", " - {glue:md}`subsystem_options`: The {glue:md}`core_aerodynamics` key allows two methods: `computed` and `solved_alpha`. In case of `solved_alpha`, it requires an additional key {glue:md}`aero_data`.\n", " - {glue:md}`external_subsystems`: a list of external subsystems.\n", "- other keys that are self-explanatory:\n", " - {glue:md}`clean`: a flag for low speed aero (which includes high-lift devices) or cruise aero (clean, because it does not include high-lift devices).\n", " - {glue:md}`EAS_target`: the target equivalent airspeed.\n", - " - {glue:md}`initial_mach`: initial Mach number.\n", + " - {glue:md}`mach_initial`: initial Mach number.\n", " - {glue:md}`linear_solver`: provide an instance of a [LinearSolver](https://openmdao.org/newdocs/versions/latest/features/core_features/controlling_solver_behavior/set_solvers.html) to the phase. \n", - " - {glue:md}`mach_cruise`: the cruise mach number.\n", + " - {glue:md}`mach_cruise`: the cruise Mach number.\n", " - {glue:md}`nonlinear_solver`: provide an instance of a [NonlinearSolver](https://openmdao.org/newdocs/versions/latest/features/core_features/controlling_solver_behavior/set_solvers.html) to the phase. \n", - " - {glue:md}`polynomial_control_order`: default to `None`.\n", - " - {glue:md}`fix_duration`: default to `False`.\n", - " - {glue:md}`solve_for_distance`: if True, use a nonlinear solver to converge the `distance` state variable to the desired value. Otherwise use the optimizer to converge the `distance` state.\n", - " - {glue:md}`optimize_mach`: if True, the Mach number is a design variable.\n", - " - {glue:md}`optimize_altitude`: if True, the altitude is a design variable.\n", + " - {glue:md}`mach_polynomial_order`: default to `None`.\n", + " - {glue:md}`distance_solve_segments`: if True, use a nonlinear solver to converge the `distance` state variable to the desired value. Otherwise use the optimizer to converge the `distance` state.\n", + " - {glue:md}`mach_optimize`: if True, the Mach number is a design variable.\n", + " - {glue:md}`altitude_optimize`: if True, the altitude is a design variable.\n", " - {glue:md}`constraints`: a dictionary of user-defined constraints. The keys are the names of the constraints and the values are the keyword arguments expected by Dymos.\n", "\n", - "```{note}\n", - "Not all the keys apply to all phases. The users should select the right keys for each phase of interest. The required keys for each phase are defined in [check_phase_info](https://github.com/OpenMDAO/Aviary/blob/main/aviary/interface/utils.py) function. Currently, this function does the check only for `FLOPS` and `GASP` missions.\n", - "```\n", - "\n", "## Using custom phase builders\n", "\n", "For the `height_energy`, you can use a user-defined phase builder.\n", @@ -243,7 +242,7 @@ "The `from_phase_info` method is used to convert the `phase_info` dictionary into the inputs needed for the phase builder object.\n", "The `build_phase` method is used to actually build and output the `Phase` object.\n", "\n", - "For examples of how to create a custom phase builder, see the `energy_phase.py` file.\n", + "For examples of how to create a custom phase builder, see the [energy_phase.py](../../mission/flops_based/phases/energy_phase.py) file.\n", "\n", "```{note}\n", "Using custom phase builders is a particularly advanced feature and is not recommended for most users.\n", @@ -262,14 +261,15 @@ "source": [ "# Testing Cell\n", "from aviary.mission.phase_builder_base import PhaseBuilderBase\n", - "PhaseBuilderBase.from_phase_info;\n", - "PhaseBuilderBase.build_phase;" + "\n", + "PhaseBuilderBase.from_phase_info\n", + "PhaseBuilderBase.build_phase" ] } ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -283,9 +283,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/getting_started/installation.md b/aviary/docs/getting_started/installation.md index 98b95a6353..1b77f297ad 100644 --- a/aviary/docs/getting_started/installation.md +++ b/aviary/docs/getting_started/installation.md @@ -1,317 +1,292 @@ # Installation -## Quick start installation +Aviary can be installed on any OS, including Windows, Linux, and macOS (as well as integrated shells like unix on macOS or Linux through WSL on Windows). + +Aviary requires a working Python environment. This installation guide assumes that you already have Python installed on your system. We recommend using conda for environment management as it makes it easier to install Aviary with its full feature set, which is explained in the next section. Our recommended package manager is [miniforge](https://github.com/conda-forge/miniforge). Miniforge is an open-source alternative to miniconda, and functions identically. ```{note} -If you do not already have Python installed, we recommend installing [condaforge](https://github.com/conda-forge/miniforge?tab=readme-ov-file#download). -The minimum supported version of Python is 3.9; we recommend using the latest release of Python. +The minimum supported Python version is 3.9; we recommend using the latest release of Python. ``` -The simplest way to install Aviary to use pip in a terminal: - -```python -pip install om-aviary -``` +The Detailed and Developer's installation guides assume you have [git](https://git-scm.com) installed. The Developer's Guide also assumes that if you are using your own fork of Aviary, that you have your system correctly configured with the proper permissions to pull from and push to your fork. -This will install the latest release of Aviary and all of its dependencies. +## Which Installation Guide Should I Use? +The following guides are available: -That's it! -If you've done that successfully, you can now use Aviary in your Python environment. +- [Quick Start Guide](#quick-start-guide) +- [Detailed Installation Guide](#detailed-guide) +- [Developer's Guide](#developers-guide) +- Docker Installation Guide (coming soon) -## More in-depth installation instructions +The different installation guides are intended to get users of various levels of Python experience and analysis needs started. Here is a brief explanation of what can differ between Aviary installs. -If you want to instead clone the Aviary repository and install from source (this is useful if you modify any of Aviary's internal code), follow the instructions below. -Once you have cloned the Aviary repo, change directories into the top-level Aviary folder (not within the `aviary` folder) and run the following command: +### Optimizers +Aviary uses the `pyOptSparse` package to get access to a variety of different optimizers. Many of the more powerful and robust optimizers do not come with pyOptSparse by default, and may require additional steps to install. The Quick Start guide does not include pyOptSparse, however you can always "upgrade" your install with pyOptSparse later to get access to more optimizers. Using a conda environment can simplify that installation process. -```python -pip install . -``` +### Editable Source Code +If you do not follow the Developer's Guide, then you will not have an editable version of Aviary source code. Following that guide installs a copy of Aviary that you can freely modify. -If you also want to install all packages used for the Aviary tests _and_ external subsystem examples, you can instead run: +### Access to Development Versions +The Quick Start Guide only grabs the most recent versioned release of Aviary, so if you need a new feature or bugfix you will have to wait until the next version release to get it. However, the other guides show how to directly get the latest Aviary code from GitHub. These development versions are generally stable and give you access to new features immediately. However, we recommend using tagged releases for studies, which makes documenting and replicating your work much easier. -```python -pip install .[all] +(quick-start-guide)= +# Quick Start Guide ``` - -If you are a developer and plan to modify parts of the Aviary code, install in an "editable mode" with ``pip``: - -```python -pip install -e . +Prerequisites: Python environment +Features: Minimal Aviary install, basic optimizers only ``` -This installs the package in the current environment such that changes to the Python code don't require re-installation. -This command should be performed while in the folder containing ``setup.py``. +Aviary can be very quickly installed via the terminal. This version of Aviary only includes basic optimizers. -```{note} -You can do this editable installation with any of the `[test]` or `[all]` options as well. ``` - -```{note} -You can install the _optional_ package [pyOptSparse by following the instructions here](https://mdolab-pyoptsparse.readthedocs-hosted.com/en/latest/install.html). If you do not need the SNOPT optimizer, installing pyOptSparse is as simple as running `conda install -c conda-forge pyoptsparse`. This will install pyOptSparse as well as the IPOPT optimizer. -``` - -## Installation Troubleshooting - -```{note} -If you encounter issues during pip installation, you may need run `pip install packaging` before you can pip install Aviary. +pip install aviary ``` -## Installation on Linux for Developers +This will install the latest release of Aviary and all of its dependencies. This may take serval minutes. Verify your installation following [these steps](#verify-installation), and you're done! Keep in mind that some examples and most tests require optimizers that aren't included in this installation. To run those on your own machine, you will need to follow [this step](#install-pyoptsparse) from the Detailed Installation Guide. -As an example, let us do a step-by-step installation from scratch on your Linux operating system. We assume that you have [Anaconda](https://www.anaconda.com/distribution) and your new environment will be built on top of it. In this section, we assume you are a developer and hence you will need developer's versions of OpenMDAO and Dymos. As a result, you will need [Git](https://git-scm.com/). We also assume that you have a bash shell. +## Updating Aviary +When a new version of Aviary is released, you can update your local copy by running the following command: -We will be installing some Python packages from source in this part of the docs. -Depending on the system you're installing on, the OpenMDAO repositories might require a password-protected SSH key. -This means that users need to [generate a new SSH key and add it to the ssh-agent](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent?platform=linux) and then [add the new SSH key to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account?platform=linux). -We assume you already have access to the OpenMDAO repos as shown below or that you've already added an SSH key. - -### Preparing your Anaconda Environment - -On the Linux system, log in to your account and create your working directory. -For this doc we will use `workspace`: - -```bash -$ mkdir ~/workspace +``` +pip install --upgrade aviary ``` -Then `cd` to this newly created directory. Please note that `~/workspace` is just an example. In fact, you can install Aviary wherever you want on your system. Save the following as a file named `aviary-linux-dev-modified.yml` to this directory: - +(detailed-guide)= +# Detailed Installation Guide ``` -name: av1 -channels: - - defaults -dependencies: - - python=3 - - numpy=1 - - scipy=1 - - matplotlib - - pandas - - jupyter - - pip - - pip: - - parameterized - - testflo - - jupyter-book - - mdolab-baseclasses - - sqlitedict - - f90nml - - bokeh +Prerequisites: Python environment (conda recommended), git (optional) +Features: Latest development version of Aviary with additional optimizers ``` -In this file, the `name` can be anything you like. The version of python is not limited to 3.9, but we recommend that you stay with this version because it is the version that we use to fully test Aviary and that it is required for some packages later on. For example, if you are going to add `OpenVSP` to your environment, you will find that you need this version. - -In the list, we see the popular Python packages for scientific computations: `numpy`, `scipy`, `matplotlib` and `pandas`. Aviary follows a standard source code formatting convention. `autopep8` provides an easy way to check your source code for this purpose. `jupyter` and `jupyter-book` are used to create Aviary manual. `parameterized` and `testflo` are for Aviary testing. Aviary uses a lot of packages developed by [MDOLab](https://mdolab.engin.umich.edu/). So, we want to include its base classes. OpenMDAO records data in SQLite database and that is what `sqlitedict` comes for. `f90nml` is A Python module and command line tool for parsing Fortran namelist files. `bokeh` is an interactive visualization library for modern web browsers. It is needed to generate Aviary output (traj_results_report.html). +This installation guide will show you how to install Aviary with the ability to grab latest development versions, as well as a guide on how to install `pyoptsparse` with additional optimizers. -Since we are going to depend on `OpenMDAO` and `dymos`, we could have included them in the `pip` list. We leave them out because we will install the developer version later. In this way, we will get the latest working copies that Aviary depends on. But we do not intend to make changes to them. +If you installed Aviary following the Quick Start Guide, you can "upgrade" your installation to use more optimizers by skipping ahead to [Step 2](#install-pyoptsparse). Once you have pyoptsparse installed, proceed to [verifying your installation](#verify-installation). -[pre-commit](https://pre-commit.com/) and [autopep8 formatter](https://pypi.org/project/autopep8/) are additionally required for developers who wish to contribute to the Aviary repository. Read our [coding standards](../developer_guide/coding_standards) for more information. - -Now, run create your new conda environment using this `.yml` file: +## Step 1: Install Aviary +You can install the development version of Aviary directly from the github repository, rather than the latest tagged version from PyPi. If you don't have git, you can download the files from github, and install it using pip from inside the top-level Aviary directory (`pip install .`). If you don't want or need the latest, cutting-edge version of Aviary, installing it using the method shown in the Quick Start Guide is fine. ``` -$ conda env create -n av1 --file aviary-linux-dev-modified.yml +pip install git+https://github.com/OpenMDAO/Aviary@main ``` -Suppose everything runs smoothly. You have a new conda environment `av1`. You can start your conda environment: +### Updating Aviary +To update your copy of Aviary to the latest development version, run this command: ``` -$ conda activate av1 +pip install --upgrade git+https://github.com/OpenMDAO/Aviary@main ``` -### Installing Additional Dependencies +(install-pyoptsparse)= +## Step 2: Install pyOptSparse +There are two sets of instructions included for pyOptSparse - read through both and determine which fits your needs and Python environment setup. -Aviary can run in MPI. -You do not need the `mpi4py` or `petsc4py` packages to use Aviary. -They are useful when running large OpenMDAO models in parallel. -If needed, you can install them with the following command: +### Installing with conda +If you have a conda environment, then you can easily install pyOptSparse with access to the "IPOPT" optimizer. This is the most commonly used optimizer in Aviary, as it is generally more performant than "SLSQP" (the default option) and is available for free. First, install the `pyoptsparse` package using conda: ``` -$ conda install -c conda-forge mpi4py petsc4py +conda install pyoptsparse ``` -Download developer version of `OpenMDAO`: +Next, add the IPOPT optimizer using the following command: ``` -$ cd ~/workspace -$ git clone git@github.com:OpenMDAO/OpenMDAO.git +conda install cyipopt ``` -You have a new subdirectory `workspace/OpenMDAO`. You are not expected to modify source code of OpenMDAO, but you want to keep up with the latests version of it. The best way to do is to install OpenMDAO in developer mode. This removes the need to reinstall OpenMDAO after changes are made. Go to this directory where you see a file `setup.py`. Run +### Installing with pip, or if you have SNOPT +To install pyOptSparse without conda, you will need the [build_pyoptsparse](https://github.com/OpenMDAO/build_pyoptsparse) package to help build pyOptSparse correctly. It is possible to install pyOptSparse without this utility package, but that is outside the scope of this guide. + +First install `build_pyoptsparse`, then run it as a command: ``` -$ cd OpenMDAO -$ pip install -e . +pip install git+https://github.com/OpenMDAO/build_pyoptsparse +build_pyoptsparse ``` -You should see something like the following: +#### Adding SNOPT +[SNOPT](http://ccom.ucsd.edu/~optimizers/solvers/snopt/) is a proprietary, high-performance optimizer that is very good at solving large nonlinear problems and is used by many OpenMDAO users. SNOPT is only supported on Linux. + +If you have a copy of SNOPT, instead run the following command to install `pyoptsparse` with both IPOPT and SNOPT available: ``` -Successfully installed networkx-3.1 openmdao-3.29.1.dev0 +build_pyoptsparse -s /path_to_SNOPT_dir ``` -Now, let us install `dymos` in a similar way: +#### Troubleshooting +Here are steps to resolve some common errors seen when installing pyOptSparse. First, try running `build_pyoptsparse -v` to get a more verbose output. +*If you see an error for a missing command:* ``` -$ cd ~/workspace/ -$ git clone git@github.com:OpenMDAO/dymos.git -$ cd dymos -$ pip install -e . +ERROR: Required command swig not found. ``` +Install the missing package (in this case `swig`) using pip or conda. Swig is a commonly missing dependency. -You should see something like the following: - +*If you see an error where a conda or mamba command failed:* ``` -Successfully installed dymos-1.9.2.dev0 +subprocess.CalledProcessError: Command '['mamba', 'info', '--unsafe-channels']' returned non-zero exit status 109. ``` +Run `build_pyoptsparse -m` to disable use of mamba commands during installation. Adding `-e` will do the same for conda if your error specifically mentions `'conda'`. -### Installing pyOptSparse - -Next, we will install `pyoptsparse`. -If you want to easily install and use pyOptSparse, follow the [installation instructions on the pyOptSparse docs](https://mdolab-pyoptsparse.readthedocs-hosted.com/en/latest/install.html). -Specifically, if you do not need the SNOPT optimizer and want to run Aviary with IPOPT, you can install pyOptSparse using the following command: - +(developers-guide)= +# Developer's Guide ``` -conda install -c conda-forge pyoptsparse +Prerequisites: Python environment (conda recommended), git +Features: Editable install of latest version Aviary with additional optimizers, additional packages for development and testing ``` +The Developer's Guide installs an editable version of Aviary source code, cloned from github, as well as additional Python packages needed for Aviary development and contributing code to the project. -The OpenMDAO team provides a [`build_pyoptsparse`](https://github.com/OpenMDAO/build_pyoptsparse) package to help users install MDO Lab's pyOptSparse, optionally including the `SNOPT` and `IPOPT` optimizers. +## Step 1: Install Aviary + It is recommended for developers to create their own fork of Aviary and clone that. In these instructions we will use the main [github repository](https://github.com/OpenMDAO/Aviary), if you are using a fork simply substitute the url with your own. Navigate to the folder where you'd like Aviary to be downloaded to, then run: -This process depends on certain libraries. -One of them is the [Lapack](https://www.netlib.org/lapack/) Fortran library. -If you don't have `Lapack`, you can either [build it from source](https://github.com/Reference-LAPACK/lapack) or try one of the [prebuilt binaries](https://www.netlib.org/lapack/archives/). -We are assuming you have Lapack installed correctly. + ``` +git clone https://github.com/OpenMDAO/Aviary + ``` -Now do the following: +Next, we will install Aviary in "editable" mode, which means that you can make changes to the code inside this Aviary directory. The `[all]` tag will also install all optional dependencies - Aviary has several installation configurations you can use by adding the correct tag inside brackets after the period. The available tags are detailed [here](#optional-dependencies). From inside the top-level Aviary directory (it should contain a file called `pyproject.toml`), run: ``` -$ cd ~/workspace/ -$ git clone git@github.com:OpenMDAO/build_pyoptsparse.git -$ python -m pip install ./build_pyoptsparse +pip install -e .[all] ``` -```{note} -`SNOPT` is a commercial optimizer that is free for academic use and available for purchase for commercial use. Users must obtain it themselves. -``` - -Assuming you have the `SNOPT` source code already, copy it to the `workspace` directory. -Run: +### Updating Aviary +To update your copy of Aviary to the latest development version, run this command from anywhere inside the Aviary repository folder: ``` -$ build_pyoptsparse -d -s ~/workspace/SNOPT_Source/ +git pull ``` -Note that you should provide the absolute -- not relative -- path to your SNOPT source files. -If successful, you should get the following: +## Step 2: Install pyOptSparse +The instructions for installing pyOptSparse are the same as the Detailed Installation Guide [here](#install-pyoptsparse). + +(optional-dependencies)= +# Optional Dependencies +There are many additional packages that are useful for developers and advanced users, but not required for users. Select the ones that make sense for your use case. Once you have installed the packages you need, [verify your installation](#verify-installation). +You can automatically install these optional packages by specifying a tag inside brackets after "aviary" when pip installing, like so: +``` +pip install aviary[] ``` ----------------------- The pyOptSparse build is complete ---------------------- -NOTE: Set the following environment variable before using this installation: -export LD_LIBRARY_PATH=$CONDA_PREFIX/lib +The following tags are available: +- `docs`: installs [packages for building docs](#docs-packages) +- `dev`: installs the [packages for running tests](#tests-packages) and [contributing code](#contribution-packages) +- `all`: installs all optional packages listed in this section -Otherwise, you may encounter errors such as: - "pyOptSparse Error: There was an error importing the compiled IPOPT module" +(tests-packages)= +## Packages For Running Tests +In order to run Aviary's test suite, you will need the following packages: +- *testflo* +- *ambiance* +- *openaerostruct* ------------------------------------ SUCCESS! ---------------------------------- -``` +`testflo` is the core package that automates testing. The other two packages, `ambiance` and `openaerostruct`, are needed to run example cases that incorporate them as external subsystems. It is useful to be able to run these cases even if you have no interest in those specific tools to ensure that the interface for external subsystems is working correctly. + +(contribution-packages)= +## Packages For Contributing Code +To contribute code, you will need to follow Aviary's [contribution guidelines](../developer_guide/contributing_guidelines.md). This involves the use of additional packages: +- *pre-commit* -So, let us add this environment variable to your bash shell: +The `pre-commit` package has an additional install step after you get the package through `pip` or `conda` commands. ``` -$ export LD_LIBRARY_PATH=$CONDA_PREFIX/lib +pip install pre-commit +pre-commit install ``` -If you don't have the Lapack package and you don't plan to build it by yourself, you can build `pyOptSparse` with `SNOPT` by adding an option `--no-ipopt` to your `build_pyoptsparse` command. +(docs-packages)= +## Packages For Building Docs +Several additional packages are needed to build a copy of the Aviary documentation locally: +- *jupyter-book* +- *itables* -Alternatively, if `build_pyoptsparse` fails again and you have `SNOPT` source code, you still can build `pyOptSparse` with `SNOPT` by directly building pyOptSparse. -First, clone the `pyOptSparse` repository: + +(verify-installation)= +# Verify Your Installation +First, check that Aviary commands can be successfully executed: ``` -$ cd ~/workspace/ -$ git clone https://github.com/mdolab/pyoptsparse +aviary ``` -You will see a `pySNOPT` subdirectory in it. Go to your `SNOPT` source folder and copy all Fortran source code files into this directory: +You should get a printout similar to below: ``` -$ cp -a * ~/workspace/pyoptsparse/pyoptsparse/pySNOPT/source/ -``` +usage: aviary [-h] [--version] ... -You are ready to install `pyoptsparse` (with `SNOPT`): +aviary Command Line Tools -``` -$ cd ~/workspace/pyoptsparse/ -$ pip install -e . +options: + -h, --help show this help message and exit + --version show version and exit + +Tools: + check Verifies Aviary installation + convert_aero_table Converts FLOPS- or GASP-formatted aero data files into Aviary csv format. + convert_engine Converts FLOPS- or GASP-formatted engine decks into Aviary csv format FLOPS + decks are changed from column-delimited to csv format with added headers. + GASP decks are reorganized into column based csv. T4 is recovered through + calculation. Data points whose T4 exceeds T4max are removed. + convert_prop_table Converts GASP-formatted propeller map file into Aviary csv format. + dashboard Run the Dashboard tool + draw_mission Allows users to draw a mission profile for use in Aviary. + fortran_to_aviary Converts legacy Fortran input decks to Aviary csv based decks + hangar Allows users that pip installed Aviary to download models from the Aviary + hangar + plot_drag_polar Plot a Drag Polar Graph using a provided polar data csv input + rtplot Run a script and automatically show a real-time plot of the optimization + progress + run_mission Runs Aviary using a provided input deck ``` -You should see something like the following: +Next try running the check command: ``` -Successfully built pyoptsparse -Installing collected packages: pyoptsparse -Successfully installed pyoptsparse-2.10.1 +aviary check ``` -### Installing Aviary and Running Tests +The command should finish without raising any errors - warnings and other printouts are ok. If you don't get any errors, you are ready to use Aviary! -Now, we are ready to install Aviary. Assuming that you will become a contributor sooner or later, we want to install a copy from the main source. (You will need a GitHub account for this) Let us open `https://github.com/openMDAO/om-aviary/` in a web browser and click [fork](https://github.com/OpenMDAO/Aviary/fork) on the top-right corner. You then have created your own copy of Aviary on GitHub website. Now we create a copy on your local drive (supposing `USER_ID` is your GitHub account ID): +## Developer Verification +If you followed the Developer's Guide, then you may also have access to testflo. If not, you can always install the package individually. To run Aviary's test suite, run the following command from inside the top level of the Aviary repository. Be advised, running the full test suite may take a significant amount of time, on the order of thirty minutes on weaker machines such as laptops. ``` -$ cd ~/workspace -$ git clone git@github.com:USER_ID/Aviary.git -$ cd Aviary -$ pip install -e . +testflo ``` -When it is done, let us run test: +The tests should begin running. You will see a series of characters printed to the screen, along with normal printouts from running Aviary cases. Periods indicate successful tests, "E" for failed tests, and "S" represents a skipped test. Skipped tests are not a concern. Tests are flagged to be skipped for a variety of reasons, and do not mean there is a problem with your installation. -``` -$ testflo . -``` +If you are missing optional packages, tests that require them will simply be skipped, so you should never be seeing failures because of which installation guide you used. If you receive an MPI error, you can add the `--nompi` option to the testflo command run. -If you run into an MPI error, you can add `--nompi` option to `testflo` command run. If everything runs, you will get something like the following: +A successful test run should look like the following once complete. The exact number of tests ran will vary as Aviary development continues, but there should be not be any failed tests. ``` -Passed: 1065 -Failed: 0 -Skipped: 3 - +OK -Ran 1065 tests using 1 processes -Wall clock time: 00:02:47.31 -``` +Passed: 1392 +Failed: 0 +Skipped: 10 -To find which tests are skipped, we can add `--show_skipped` option: +Ran 1402 tests using 208 processes +Wall clock time: 00:06:6.20 ``` -The following tests were skipped: -test_conventional_problem.py:TestConventionalProblem.test_conventional_problem_ipopt -test_conventional_problem.py:TestConventionalProblem.test_conventional_problem_snopt -test_cruise.py:TestCruise.test_cruise_result -``` - -Actually, those three tests were skipped on purpose. Depending on what optimizers are installed, the number of skipped tests may be different. Your installation is successful. -To see the test name before each unit test and push all outputs to standard outputs: +You can also run the benchmark tests, which are a suite of full aircraft optimization problems. These are separate from the test suite called with testflo to allow developers to only run the subset of tests they need to save runtime. To run the benchmark tests, execute the `run_all_benchmarks.py` script located in the `aviary` directory in the repository. ``` -$ testflo -s --pre_announce . +python aviary/run_all_benchmarks.py ``` -Run `testflo --help` to see other options. For example, we have a set of longer tests (called bench tests) that perform full trajectory optimizations. To run all the bench tests, you can run this: +The final printout should look like this: ``` -$ cd ~/Aviary/aviary -$ python run_all_benchmarks.py -``` +OK -If you want to test a particular case (e.g. `test_simplified_takeoff.py`): +Passed: 13 +Failed: 0 +Skipped: 1 -``` -$ testflo test_simplified_takeoff.py -``` -```{note} -Installing Aviary via pip here does not install all packages needed for external subsystems. -For example, if you're using [OpenVSP](https://openvsp.org/), [pyCycle](https://github.com/OpenMDAO/pyCycle), or other tools outside of "core Aviary", you would need to install those separately. -``` +Ran 14 tests using 208 processes +Wall clock time: 00:02:45.00 +``` \ No newline at end of file diff --git a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb index 9d9a491fc0..ce8f69e78c 100644 --- a/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb +++ b/aviary/docs/getting_started/onboarding_ext_subsystem.ipynb @@ -1,5 +1,25 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "16100856", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.interface.methods_for_level2 import AviaryGroup\n", + "from aviary.utils.doctape import glue_class_options\n", + "\n", + "current_glued_vars = []\n", + "\n", + "glue_class_options(AviaryGroup, current_glued_vars, md_code=True)" + ] + }, { "cell_type": "markdown", "id": "ac9434a4", @@ -7,7 +27,7 @@ "source": [ "# Models with External Subsystems\n", "\n", - "In level 2, we have given simple examples of defining external subsystems in `phase_info`. The subsystems that we gave were all dummy subsystems and are not really used in simulation. Assume you have an external subsystem and you want to use it. Let us show you how to achieve this goal." + "In level 2, we have given simple examples of defining external subsystems in {glue:md}`mission_info`. The subsystems that we gave were all dummy subsystems and are not really used in simulation. Assume you have an external subsystem and you want to use it. Let us show you how to achieve this goal." ] }, { @@ -18,7 +38,7 @@ "## Installation of Aviary examples\n", "\n", "The Aviary team has provided a few external subsystems for you to use.\n", - "These are included in the `aviary/examples/external_subsystems` directory.\n", + "These are included in the {glue:md}`aviary/examples/external_subsystems` directory.\n", "We'll now discuss them here and show you how to use them." ] }, @@ -34,8 +54,24 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.functions import get_path\n", - "get_path('examples/external_subsystems')" + "import aviary.api as av\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.utils.functions import get_model, get_path\n", + "\n", + "path = get_path('examples/external_subsystems').relative_to(av.top_dir.parent)\n", + "glue_variable(path, md_code=True)\n", + "path = get_path('examples/external_subsystems/battery')\n", + "glue_variable(path.stem, md_code=True)\n", + "path = get_path('examples/external_subsystems/custom_mass')\n", + "glue_variable(path.stem, md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.HorizontalTail.MASS), md_code=True)\n", + "\n", + "aircraft_csv_file = 'aircraft_for_bench_FwFm.csv'\n", + "get_model(aircraft_csv_file)\n", + "glue_variable(aircraft_csv_file, md_code=True)" ] }, { @@ -43,11 +79,11 @@ "id": "2f17ec04", "metadata": {}, "source": [ - "## Adding simple_weight subsystems\n", + "## Adding Subsystems\n", "\n", - "Currently, there are a couple of examples: `battery` and `simple_weight`. Let us take a look at `simple_weight` first. As shown in this example, this is a simplified example of a component that computes a weight for the wing and horizontal tail. It does not provide realistic computations but rough estimates to `Aircraft.Wing.MASS` and `Aircraft.HorizontalTail.MASS`. When this external subsystem is added to your pre-mission phase, Aviary will compute these weights in its core subsystem as usual, but then the wing mass and tail mass values will be overridden by this external subsytem.\n", + "Currently, there are a couple of examples: {glue:md}`battery` and {glue:md}`custom_mass`. Let us take a look at {glue:md}`custom_mass` first. As shown in this example, this is a simplified example of a component that computes a weight for the wing and horizontal tail. It does not provide realistic computations but rough estimates to {glue:md}`Aircraft.Wing.MASS` and {glue:md}`Aircraft.HorizontalTail.MASS`. When this external subsystem is added to your pre-mission phase, Aviary will compute these weights in its core subsystem as usual, but then the wing mass and tail mass values will be overridden by this external subsytem.\n", "\n", - "In [level 2](onboarding_level2), we have briefly covered how to add external subsystems in `phase_info`. Alternatively, external subsystems (and any other new keys) can be added after a `phase_info` is loaded. Let us see how it works using the aircraft_for_bench_FwFm.csv model. First, we import this particular external subsystem.\n", + "In [level 2](onboarding_level2), we have briefly covered how to add external subsystems in {glue:md}`mission_info`. Alternatively, external subsystems (and any other new keys) can be added after a {glue:md}`mission_info` is loaded. Let us see how it works using the {glue:md}`aircraft_for_bench_FwFm.csv` model. First, we import this particular external subsystem.\n", "\n", "Then add this external subsystem to `pre_mission`.\n", "That is all you need to do in addition to our traditional level 2 examples. Here is the complete run script," @@ -65,9 +101,14 @@ "outputs": [], "source": [ "# Testing Cell\n", + "import aviary.api as av\n", "from aviary.api import Aircraft\n", - "Aircraft.Wing.MASS;\n", - "Aircraft.HorizontalTail.MASS;" + "from aviary.utils.doctape import check_value, glue_variable\n", + "\n", + "Aircraft.Wing.MASS\n", + "Aircraft.HorizontalTail.MASS\n", + "check_value(av.EquationsOfMotion.HEIGHT_ENERGY.value, 'height_energy')\n", + "glue_variable(av.EquationsOfMotion.HEIGHT_ENERGY.value, md_code=False)" ] }, { @@ -78,37 +119,33 @@ "outputs": [], "source": [ "from copy import deepcopy\n", - "from aviary.api import Aircraft\n", - "import aviary.api as av\n", "\n", - "from aviary.examples.external_subsystems.simple_weight.simple_weight_builder import WingWeightBuilder\n", + "import aviary.api as av\n", + "from aviary.api import Aircraft\n", + "from aviary.examples.external_subsystems.custom_mass.custom_mass_builder import (\n", + " WingMassBuilder,\n", + ")\n", "\n", "# Max iterations set to 1 to reduce runtime of example\n", "max_iter = 1\n", "phase_info = deepcopy(av.default_height_energy_phase_info)\n", "# Here we just add the simple weight system to only the pre-mission\n", - "phase_info['pre_mission']['external_subsystems'] = [WingWeightBuilder(name=\"wing_external\")]\n", + "phase_info['pre_mission']['external_subsystems'] = [WingMassBuilder(name='wing_external')]\n", "\n", "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info)\n", + "prob.load_inputs(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " phase_info,\n", + ")\n", "\n", - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on how clashing the issues are\n", "prob.check_and_preprocess_inputs()\n", "\n", - "prob.add_pre_mission_systems()\n", + "prob.build_model()\n", "\n", - "prob.add_phases()\n", - "\n", - "prob.add_post_mission_systems()\n", - "\n", - "# Link phases and variables\n", - "prob.link_phases()\n", - "\n", - "prob.add_driver(\"SLSQP\", max_iter)\n", + "prob.add_driver('SLSQP', max_iter)\n", "\n", "prob.add_design_variables()\n", "\n", @@ -116,8 +153,6 @@ "\n", "prob.setup()\n", "\n", - "prob.set_initial_guesses()\n", - "\n", "prob.run_aviary_problem(suppress_solver_print=True)\n", "\n", "print('Engine Mass', prob.get_val(av.Aircraft.Engine.MASS))\n", @@ -131,7 +166,7 @@ "metadata": {}, "source": [ "Ignore the intermediate warning messages and you see the outputs at the end.\n", - "Since this is a `FLOPS` mission and no objective is provided, we know that the objective is `fuel_burned`.\n", + "Since this is a {glue:md}`height_energy` mission and no objective is provided, we know that the objective is `fuel_burned`.\n", "\n", "To see the outputs without external subsystem add-on, let us comment out the lines that add the wing weight builder and run the modified script:" ] @@ -144,7 +179,7 @@ "outputs": [], "source": [ "# # Here we just add the simple weight system to only the pre-mission\n", - "# phase_info['pre_mission']['external_subsystems'] = [WingWeightBuilder(name=\"wing_external\")]\n", + "# phase_info['pre_mission']['external_subsystems'] = [WingWeightBuilder(name='wing_external')]\n", "\n", "# Max iterations set to 1 to reduce runtime of example\n", "max_iter = 1\n", @@ -152,22 +187,16 @@ "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', av.default_height_energy_phase_info)\n", + "prob.load_inputs(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " av.default_height_energy_phase_info,\n", + ")\n", "\n", - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on how clashing the issues are\n", "prob.check_and_preprocess_inputs()\n", "\n", - "prob.add_pre_mission_systems()\n", - "\n", - "prob.add_phases()\n", + "prob.build_model()\n", "\n", - "prob.add_post_mission_systems()\n", - "\n", - "# Link phases and variables\n", - "prob.link_phases()\n", - "\n", - "prob.add_driver(\"SLSQP\", max_iter)\n", + "prob.add_driver('SLSQP', max_iter)\n", "\n", "prob.add_design_variables()\n", "\n", @@ -175,8 +204,6 @@ "\n", "prob.setup()\n", "\n", - "prob.set_initial_guesses()\n", - "\n", "prob.run_aviary_problem(suppress_solver_print=True)\n", "\n", "print('Engine Mass', prob.get_val(Aircraft.Engine.MASS))\n", @@ -189,7 +216,69 @@ "id": "7df25fe0", "metadata": {}, "source": [ - "As we see, the engine mass is not altered but wing mass and tail mass are changed dramatically. This is not surprising because our `simple_weight` subsystem is quite simple. Later on, we will show you a more realistic wing weight external subsystem." + "As we see, the engine mass is not altered but wing mass and tail mass are changed dramatically. This is not surprising because our {glue:md}`custom_mass` subsystem is quite simple. Later on, we will show you a more realistic wing weight external subsystem." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8ec009f", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import check_contains, glue_function_arguments\n", + "\n", + "imported_functions = {k for k, v in inspect.getmembers(AviaryProblem, inspect.isfunction)}\n", + "check_contains(\n", + " [\n", + " '__init__',\n", + " 'load_inputs',\n", + " 'build_model',\n", + " 'add_driver',\n", + " 'add_design_variables',\n", + " 'add_objective',\n", + " 'setup',\n", + " 'set_initial_guesses',\n", + " 'run_aviary_problem',\n", + " ],\n", + " imported_functions,\n", + ")\n", + "\n", + "# Retrieve all arguments from add_driver()\n", + "glue_function_arguments(AviaryProblem.add_driver, current_glued_vars, md_code=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5dcecf3", + "metadata": { + "tags": [ + "remove-output" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.models.missions.height_energy_default import phase_info\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import glue_class_functions, glue_variable\n", + "\n", + "# Get all functions of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, [], md_code=False)\n", + "\n", + "# Retrieve all top-level keys of phase_info\n", + "top_level_keys_list = [k for k in phase_info.keys() if k not in ('pre_mission', 'post_mission')]\n", + "for key in top_level_keys_list:\n", + " glue_variable(key, md_code=False)" ] }, { @@ -201,23 +290,19 @@ "\n", "In the above example, there is no new Aviary variable added to Aviary and the external subsystem is added to pre-mission only. So, the subsystem is not very involved. We will see a more complicated example now. Before we move on, let us recall the steps in Aviary model building:\n", "\n", - "- **init**\n", - "- **load_inputs**\n", - "- **check_and_preprocess_inputs**\n", - "- **add_pre_mission_systems**\n", - "- **add_phases**\n", - "- **add_post_mission_systems**\n", - "- **link_phases**\n", - "- add_driver\n", - "- **add_design_variables**\n", - "- **add_objective**\n", - "- setup\n", - "- **set_initial_guesses**\n", - "- run_aviary_problem\n", + "- **{glue:md}`__init__()`**\n", + "- **{glue:md}`load_inputs()`**\n", + "- **{glue:md}`build_model()`**\n", + "- **{glue:md}`check_and_preprocess_inputs()`**\n", + "- {glue:md}`add_driver()`\n", + "- **{glue:md}`add_design_variables()`**\n", + "- **{glue:md}`add_objective()`**\n", + "- {glue:md}`setup()`\n", + "- {glue:md}`run_aviary_problem()`\n", "\n", "The steps in bold are related specifically to subsystems. So, almost all of the steps involve subsystems. As long as your external subsystem is built based on the guidelines, Aviary will take care of your subsystem.\n", "\n", - "The next example is the [battery subsystem](https://github.com/OpenMDAO/Aviary/blob/main/aviary/docs/user_guide/battery_subsystem_example). The battery subsystem provides methods to define the battery subsystem's states, design variables, fixed values, initial guesses, and mass names. It also provides methods to build OpenMDAO systems for the pre-mission and mission computations of the subsystem, to get the constraints for the subsystem, and to preprocess the inputs for the subsystem. This subsystem has its own set of variables. We will build an Aviary model with full phases (namely, `climb`, `cruise` and `descent`) and maximize the final total mass: `Dynamic.Mission.MASS`." + "The next example is the [battery subsystem](https://github.com/OpenMDAO/Aviary/blob/main/aviary/docs/user_guide/battery_subsystem_example). The battery subsystem provides methods to define the battery subsystem's states, design variables, fixed values, initial guesses, and mass names. It also provides methods to build OpenMDAO systems for the pre-mission and mission computations of the subsystem, to get the constraints for the subsystem, and to preprocess the inputs for the subsystem. This subsystem has its own set of variables. We will build an Aviary model with full phases (namely, {glue:md}`climb`, {glue:md}`cruise` and {glue:md}`descent`) and maximize the final total mass: {glue:md}`Dynamic.Vehicle.MASS`." ] }, { @@ -233,7 +318,10 @@ "source": [ "# Testing Cell\n", "from aviary.api import Dynamic\n", - "Dynamic.Mission.MASS;" + "from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "glue_variable(BatteryBuilder.__name__, md_code=True)" ] }, { @@ -241,8 +329,8 @@ "id": "689d7dcb", "metadata": {}, "source": [ - "We also need `BatteryBuilder` along with battery related aircraft variables and build a new battery object.\n", - "Now, add our new battery subsystem into each phase including pre-mission:\n" + "We also need {glue:md}`BatteryBuilder` along with battery related aircraft variables and build a new battery object.\n", + "Now, add our new battery subsystem into each phase including pre-mission:" ] }, { @@ -253,8 +341,8 @@ "outputs": [], "source": [ "from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder\n", - "from aviary.examples.external_subsystems.battery.battery_variables import Aircraft\n", "from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData\n", + "from aviary.examples.external_subsystems.battery.battery_variables import Aircraft\n", "\n", "battery_builder = BatteryBuilder(include_constraints=False)\n", "\n", @@ -281,8 +369,13 @@ "source": [ "prob = av.AviaryProblem()\n", "\n", - "prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " phase_info, meta_data=ExtendedMetaData)" + "prob.load_inputs(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " phase_info,\n", + " meta_data=ExtendedMetaData,\n", + ")\n", + "\n", + "prob.check_and_preprocess_inputs()" ] }, { @@ -292,27 +385,7 @@ "source": [ "Since this example contains new variables in the aircraft hierarchy, the metadata for those variables was added to an extended metadata dictionary. We need to pass that into load_inputs so that it can load susbsystem-specific inputs from the csv file.\n", "\n", - "In the battery subsystem, the type of battery cell we use is `18650`. The option is not set in `input_file`, instead it is controlled by importing the correct battery map [here](https://github.com/OpenMDAO/Aviary/blob/1fca1c03cb2e1d6387442162e8d7dabf83eee197/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py#L5)." - ] - }, - { - "cell_type": "markdown", - "id": "e92d14c1", - "metadata": {}, - "source": [ - "We can then check our inputs:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7cf0222f", - "metadata": {}, - "outputs": [], - "source": [ - "# Have checks for clashing user inputs\n", - "# Raise warnings or errors depending on severity of the issues\n", - "prob.check_and_preprocess_inputs()" + "The inputs are then checked by calling check_and_preprocess_inputs." ] }, { @@ -320,19 +393,21 @@ "id": "e8e14515", "metadata": {}, "source": [ + "In the battery subsystem, the type of battery cell we use is `18650`. This type of battery information is set in `preprocess_inputs()` within `examples/external_subsystems/batterybattery_builder.py`.\n", + "\n", "### Checking in the setup function call\n", "\n", - "Function `setup` can have an argument `check` with default value `False`. If we set it to `True`, it will cause a default set of checks to be run. So, instead of a simple `prob.setup()` call, let us do the following:\n", + "The OpenMDAO Function {glue:md}`setup()` can have an argument `check` with default value `None` (see [here](https://openmdao.org/newdocs/versions/latest/features/core_features/running_your_models/setup.html)). If we set it to `True`, it will cause a default set of checks to be run. So, instead of a simple {glue:md}`setup()` call, let us call it with `check=True`.\n", "\n", "The following are a few check points printed on the command line:\n", "\n", "```\n", + "INFO: checking out_of_order\n", "INFO: checking system\n", "INFO: checking solvers\n", "INFO: checking dup_inputs\n", "INFO: checking missing_recorders\n", - "```\n", - "\n" + "```\n" ] }, { @@ -342,17 +417,10 @@ "metadata": {}, "outputs": [], "source": [ - "prob.add_pre_mission_systems()\n", - "\n", - "traj = prob.add_phases()\n", - "\n", - "prob.add_post_mission_systems()\n", - "\n", - "# Link phases and variables\n", - "prob.link_phases()\n", + "prob.build_model()\n", "\n", "max_iter = 1\n", - "prob.add_driver(\"SLSQP\", max_iter)\n", + "prob.add_driver('SLSQP', max_iter)\n", "\n", "prob.add_design_variables()\n", "\n", @@ -368,7 +436,7 @@ "print('Battery MASS', prob.get_val(Aircraft.Battery.MASS))\n", "print('Cell Max', prob.get_val(Aircraft.Battery.Cell.MASS))\n", "masses_descent = prob.get_val('traj.descent.timeseries.mass', units='kg')\n", - "print(f\"Final Descent Mass: {masses_descent[-1]}\")\n", + "print(f'Final Descent Mass: {masses_descent[-1]}')\n", "\n", "print('done')" ] @@ -390,16 +458,33 @@ "metadata": {}, "outputs": [], "source": [ - "print('Battery MASS', prob.get_val(Aircraft.Battery.MASS))\n", + "print('Battery MASS', prob.get_val(Aircraft.Battery.MASS, units='lbm'))\n", "print('Cell Max', prob.get_val(Aircraft.Battery.Cell.MASS))" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "45764df7", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "glue_variable(get_variable_name(Dynamic.Vehicle.MASS), md_code=True)" + ] + }, { "cell_type": "markdown", "id": "ed8c764a", "metadata": {}, "source": [ - "Since our objective is `mass`, we want to print the value of `Dynamic.Mission.Mass`. Remember, we have imported Dynamic from aviary.variable_info.variables for this purpose.\n", + "Since our objective is `mass`, we want to print the value of {glue:md}`Dynamic.Vehicle.MASS`. Remember, we have imported Dynamic from aviary.variable_info.variables for this purpose.\n", "\n", "So, we have to print the final mass in a different way. Keep in mind that we have three phases in the mission and that final mass is our objective. So, we can get the final mass of the descent phase instead. Let us try this approach. Let us comment out the print statement of final mass (and the import of Dynamic), then add the following lines:" ] @@ -412,7 +497,82 @@ "outputs": [], "source": [ "masses_descent = prob.get_val('traj.descent.timeseries.mass', units='kg')\n", - "print(f\"Final Descent Mass: {masses_descent[-1]}\")" + "print(f'Final Descent Mass: {masses_descent[-1]}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "046ffc08", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from openmdao.utils.assert_utils import assert_near_equal\n", + "\n", + "from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder\n", + "from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData\n", + "from aviary.examples.external_subsystems.battery.battery_variables import Dynamic\n", + "\n", + "battery_builder = BatteryBuilder(include_constraints=False)\n", + "\n", + "phase_info['pre_mission']['external_subsystems'] = [battery_builder]\n", + "phase_info['climb']['external_subsystems'] = [battery_builder]\n", + "phase_info['cruise']['external_subsystems'] = [battery_builder]\n", + "phase_info['descent']['external_subsystems'] = [battery_builder]\n", + "\n", + "prob = av.AviaryProblem()\n", + "\n", + "prob.load_inputs(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " phase_info,\n", + " meta_data=ExtendedMetaData,\n", + ")\n", + "\n", + "prob.check_and_preprocess_inputs()\n", + "\n", + "prob.build_model()\n", + "\n", + "max_iter = 1\n", + "prob.add_driver('SLSQP', max_iter)\n", + "\n", + "prob.add_design_variables()\n", + "\n", + "# prob.add_objective('mass')\n", + "prob.model.add_objective(f'traj.climb.states:{Dynamic.Battery.STATE_OF_CHARGE}', index=-1, ref=-1)\n", + "\n", + "prob.setup(check=True)\n", + "\n", + "prob.set_initial_guesses()\n", + "\n", + "prob.run_aviary_problem()\n", + "\n", + "\n", + "soc_cruise = prob.get_val('traj.climb.timeseries.dynamic:battery:state_of_charge')\n", + "state_of_charge = soc_cruise[-1]\n", + "expected_soc = 0.91333333\n", + "assert_near_equal(state_of_charge[0], expected_soc, 1e-5)\n", + "glue_variable('expected_soc', '[' + str(expected_soc) + ']', md_code=False)" + ] + }, + { + "cell_type": "markdown", + "id": "69ffb9a2", + "metadata": {}, + "source": [ + "# Level 3\n", + "\n", + "Level 3 represents the highest level of user control and customization in Aviary's user interface.\n", + "At this level, users have full access to Python and OpenMDAO methods that Aviary calls.\n", + "They can use the complete set of Aviary's methods, functionalities, and classes to construct and fine-tune their aircraft models.\n", + "Level 3 enables users to have supreme control over every aspect of the model, including subsystems, connections, and advanced optimization techniques.\n", + "\n", + "Level 3 is the most complex but specific methods defined at this level are used in levels 1 and 2, hopefully reducing user activation energy when learning more about Aviary.\n", + "This progressive approach helps users gradually enhance their analysis capabilities and adapt to more complex modeling requirements as they gain proficiency and experience." ] }, { @@ -426,21 +586,20 @@ "\n", "```\n", "prob.model.add_objective(\n", - " f'traj.climb.states:{Mission.Battery.STATE_OF_CHARGE}', index=-1, ref=-1)\n", + " f'traj.climb.states:{Dynamic.Battery.STATE_OF_CHARGE}', index=-1, ref=-1)\n", "```\n", "\n", "In the above, `index=-1` means the end of climb phase and `ref=-1` means that we want to maximize the state of charge at the end of climb phase. Once again, we are unable to print battery state of charge as we did with battery mass and battery cell mass. We will use the same approach to get mass. In fact, we have prepared for this purpose by setting up time series of climb and cruise phases as well. All we need to do is to add the following lines:\n", "\n", "```\n", "soc_cruise = prob.get_val(\n", - " 'traj.climb.timeseries.mission:battery:state_of_charge')\n", - "print(f\"State of Charge: {soc_cruise[-1]}\")\n", + " 'traj.climb.timeseries.dynamic:battery:state_of_charge')\n", + "print(f'State of Charge: {soc_cruise[-1]}')\n", "```\n", "\n", "Now you get a new output:\n", "\n", - "```\n", - "State of Charge: [0.97458496]" + "State of Charge: {glue:md}`expected_soc`\n" ] }, { @@ -525,6 +684,26 @@ "The OpenAeroStruct example is explained in detail in [Using Aviary and OpenAeroStruct Together](../examples/OAS_subsystem)." ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9ce7c16", + "metadata": { + "tags": [ + "remove-output" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.examples.external_subsystems.OAS_mass.OAS_wing_mass_builder import (\n", + " OASWingMassBuilder,\n", + ")\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "glue_variable(OASWingMassBuilder.__name__, md_code=True)" + ] + }, { "cell_type": "markdown", "id": "a9d285b7", @@ -532,7 +711,7 @@ "source": [ "### Running the OpenAeroStruct Example\n", "\n", - "We are ready to run this example. First, we create an `OASWingWeightBuilder` instance." + "We are ready to run this example. First, we create an {glue:md}`OASWingMassBuilder` instance." ] }, { @@ -544,10 +723,13 @@ "source": [ "import numpy as np\n", "import openmdao.api as om\n", + "\n", "import aviary.api as av\n", - "from aviary.examples.external_subsystems.OAS_weight.OAS_wing_weight_builder import OASWingWeightBuilder\n", + "from aviary.examples.external_subsystems.OAS_mass.OAS_wing_mass_builder import (\n", + " OASWingMassBuilder,\n", + ")\n", "\n", - "wing_weight_builder = OASWingWeightBuilder()" + "wing_weight_builder = OASWingMassBuilder()" ] }, { @@ -571,79 +753,71 @@ " 'climb_1': {\n", " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", " 'user_options': {\n", - " 'optimize_mach': False,\n", - " 'optimize_altitude': False,\n", - " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_distance': False,\n", - " 'initial_mach': (0.2, 'unitless'),\n", - " 'final_mach': (0.72, 'unitless'),\n", + " 'distance_solve_segments': False,\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.2, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", - " 'initial_altitude': (0.0, 'ft'),\n", - " 'final_altitude': (32000.0, 'ft'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (0.0, 'ft'),\n", + " 'altitude_final': (32000.0, 'ft'),\n", " 'altitude_bounds': ((0.0, 34000.0), 'ft'),\n", " 'throttle_enforcement': 'path_constraint',\n", - " 'fix_initial': True,\n", - " 'constrain_final': False,\n", - " 'fix_duration': False,\n", - " 'initial_bounds': ((0.0, 0.0), 'min'),\n", - " 'duration_bounds': ((64.0, 192.0), 'min'),\n", + " 'time_initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'time_duration_bounds': ((64.0, 192.0), 'min'),\n", " },\n", " 'initial_guesses': {'time': ([0, 128], 'min')},\n", " },\n", " 'climb_2': {\n", " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", " 'user_options': {\n", - " 'optimize_mach': False,\n", - " 'optimize_altitude': False,\n", - " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_distance': False,\n", - " 'initial_mach': (0.72, 'unitless'),\n", - " 'final_mach': (0.72, 'unitless'),\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", - " 'initial_altitude': (32000.0, 'ft'),\n", - " 'final_altitude': (34000.0, 'ft'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (32000.0, 'ft'),\n", + " 'altitude_final': (34000.0, 'ft'),\n", " 'altitude_bounds': ((23000.0, 38000.0), 'ft'),\n", " 'throttle_enforcement': 'boundary_constraint',\n", - " 'fix_initial': False,\n", - " 'constrain_final': False,\n", - " 'fix_duration': False,\n", - " 'initial_bounds': ((64.0, 192.0), 'min'),\n", - " 'duration_bounds': ((56.5, 169.5), 'min'),\n", + " 'time_initial_bounds': ((64.0, 192.0), 'min'),\n", + " 'time_duration_bounds': ((56.5, 169.5), 'min'),\n", " },\n", " 'initial_guesses': {'time': ([128, 113], 'min')},\n", " },\n", " 'descent_1': {\n", " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", " 'user_options': {\n", - " 'optimize_mach': False,\n", - " 'optimize_altitude': False,\n", - " 'polynomial_control_order': 1,\n", " 'num_segments': 5,\n", " 'order': 3,\n", - " 'solve_for_distance': False,\n", - " 'initial_mach': (0.72, 'unitless'),\n", - " 'final_mach': (0.36, 'unitless'),\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.36, 'unitless'),\n", " 'mach_bounds': ((0.34, 0.74), 'unitless'),\n", - " 'initial_altitude': (34000.0, 'ft'),\n", - " 'final_altitude': (500.0, 'ft'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (34000.0, 'ft'),\n", + " 'altitude_final': (500.0, 'ft'),\n", " 'altitude_bounds': ((0.0, 38000.0), 'ft'),\n", " 'throttle_enforcement': 'path_constraint',\n", - " 'fix_initial': False,\n", - " 'constrain_final': True,\n", - " 'fix_duration': False,\n", - " 'initial_bounds': ((120.5, 361.5), 'min'),\n", - " 'duration_bounds': ((29.0, 87.0), 'min'),\n", + " 'time_initial_bounds': ((120.5, 361.5), 'min'),\n", + " 'time_duration_bounds': ((29.0, 87.0), 'min'),\n", " },\n", " 'initial_guesses': {'time': ([241, 58], 'min')},\n", " },\n", " 'post_mission': {\n", " 'include_landing': False,\n", " 'constrain_range': True,\n", - " 'target_range': (1800., 'nmi'),\n", + " 'target_range': (1800.0, 'nmi'),\n", " },\n", "}\n", "\n", @@ -666,7 +840,7 @@ "metadata": {}, "outputs": [], "source": [ - "aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "aircraft_definition_file = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "make_plots = False\n", "max_iter = 0\n", "optimizer = 'SNOPT'\n", @@ -675,10 +849,7 @@ "\n", "prob.load_inputs(aircraft_definition_file, phase_info)\n", "prob.check_and_preprocess_inputs()\n", - "prob.add_pre_mission_systems()\n", - "prob.add_phases()\n", - "prob.add_post_mission_systems()\n", - "prob.link_phases()" + "prob.build_model()" ] }, { @@ -697,17 +868,16 @@ "outputs": [], "source": [ "driver = prob.driver = om.pyOptSparseDriver()\n", - "driver.options[\"optimizer\"] = optimizer\n", + "driver.options['optimizer'] = optimizer\n", "driver.declare_coloring()\n", - "driver.opt_settings[\"Major iterations limit\"] = max_iter\n", - "driver.opt_settings[\"Major optimality tolerance\"] = 1e-4\n", - "driver.opt_settings[\"Major feasibility tolerance\"] = 1e-5\n", - "driver.opt_settings[\"iSumm\"] = 6\n", + "driver.opt_settings['Major iterations limit'] = max_iter\n", + "driver.opt_settings['Major optimality tolerance'] = 1e-4\n", + "driver.opt_settings['Major feasibility tolerance'] = 1e-5\n", + "driver.opt_settings['iSumm'] = 6\n", "\n", "prob.add_design_variables()\n", "prob.add_objective()\n", - "prob.setup()\n", - "prob.set_initial_guesses()" + "prob.setup()" ] }, { @@ -725,12 +895,65 @@ "metadata": {}, "outputs": [], "source": [ - "OAS_sys = 'pre_mission.wing_weight.aerostructures.'\n", - "prob.set_val(OAS_sys + 'box_upper_x', np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]), units='unitless')\n", - "prob.set_val(OAS_sys + 'box_lower_x', np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]), units='unitless')\n", - "prob.set_val(OAS_sys + 'box_upper_y', np.array([ 0.0447, 0.046, 0.0472, 0.0484, 0.0495, 0.0505, 0.0514, 0.0523, 0.0531, 0.0538, 0.0545, 0.0551, 0.0557, 0.0563, 0.0568, 0.0573, 0.0577, 0.0581, 0.0585, 0.0588, 0.0591, 0.0593, 0.0595, 0.0597, 0.0599, 0.06, 0.0601, 0.0602, 0.0602, 0.0602, 0.0602, 0.0602, 0.0601, 0.06, 0.0599, 0.0598, 0.0596, 0.0594, 0.0592, 0.0589, 0.0586, 0.0583, 0.058, 0.0576, 0.0572, 0.0568, 0.0563, 0.0558, 0.0553, 0.0547, 0.0541]), units='unitless')\n", - "prob.set_val(OAS_sys + 'box_lower_y', np.array([-0.0447, -0.046, -0.0473, -0.0485, -0.0496, -0.0506, -0.0515, -0.0524, -0.0532, -0.054, -0.0547, -0.0554, -0.056, -0.0565, -0.057, -0.0575, -0.0579, -0.0583, -0.0586, -0.0589, -0.0592, -0.0594, -0.0595, -0.0596, -0.0597, -0.0598, -0.0598, -0.0598, -0.0598, -0.0597, -0.0596, -0.0594, -0.0592, -0.0589, -0.0586, -0.0582, -0.0578, -0.0573, -0.0567, -0.0561, -0.0554, -0.0546, -0.0538, -0.0529, -0.0519, -0.0509, -0.0497, -0.0485, -0.0472, -0.0458, -0.0444]), units='unitless')\n", - "prob.set_val(OAS_sys + 'twist_cp', np.array([-6., -6., -4., 0.]), units='deg')\n", + "OAS_sys = 'pre_mission.wing_mass.aerostructures.'\n", + "# fmt: off\n", + "prob.set_val(\n", + " OAS_sys + 'box_upper_x',\n", + " np.array(\n", + " [\n", + " 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24,\n", + " 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39,\n", + " 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54,\n", + " 0.55, 0.56, 0.57, 0.58, 0.59, 0.6,\n", + " ]\n", + " ),\n", + " units='unitless',\n", + ")\n", + "\n", + "prob.set_val(\n", + " OAS_sys + 'box_lower_x',\n", + " np.array(\n", + " [\n", + " 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24,\n", + " 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39,\n", + " 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54,\n", + " 0.55, 0.56, 0.57, 0.58, 0.59, 0.6,\n", + " ]\n", + " ),\n", + " units='unitless',\n", + ")\n", + "\n", + "prob.set_val(\n", + " OAS_sys + 'box_upper_y',\n", + " np.array(\n", + " [\n", + " 0.0447, 0.046, 0.0472, 0.0484, 0.0495, 0.0505, 0.0514, 0.0523, 0.0531, 0.0538, 0.0545,\n", + " 0.0551, 0.0557, 0.0563, 0.0568, 0.0573, 0.0577, 0.0581, 0.0585, 0.0588, 0.0591, 0.0593,\n", + " 0.0595, 0.0597, 0.0599, 0.06, 0.0601, 0.0602, 0.0602, 0.0602, 0.0602, 0.0602, 0.0601,\n", + " 0.06, 0.0599, 0.0598, 0.0596, 0.0594, 0.0592, 0.0589, 0.0586, 0.0583, 0.058, 0.0576,\n", + " 0.0572, 0.0568, 0.0563, 0.0558, 0.0553, 0.0547, 0.0541,\n", + " ]\n", + " ),\n", + " units='unitless',\n", + ")\n", + "\n", + "prob.set_val(\n", + " OAS_sys + 'box_lower_y',\n", + " np.array(\n", + " [\n", + " -0.0447, -0.046, -0.0473, -0.0485, -0.0496, -0.0506, -0.0515, -0.0524, -0.0532, -0.054,\n", + " -0.0547, -0.0554, -0.056, -0.0565, -0.057, -0.0575, -0.0579, -0.0583, -0.0586, -0.0589,\n", + " -0.0592, -0.0594, -0.0595, -0.0596, -0.0597, -0.0598, -0.0598, -0.0598, -0.0598,\n", + " -0.0597, -0.0596, -0.0594, -0.0592, -0.0589, -0.0586, -0.0582, -0.0578, -0.0573,\n", + " -0.0567, -0.0561, -0.0554, -0.0546, -0.0538, -0.0529, -0.0519, -0.0509, -0.0497, \n", + " -0.0485, -0.0472, -0.0458, -0.0444,\n", + " ]\n", + " ),\n", + " units='unitless',\n", + ")\n", + "# fmt: on\n", + "\n", + "prob.set_val(OAS_sys + 'twist_cp', np.array([-6.0, -6.0, -4.0, 0.0]), units='deg')\n", "prob.set_val(OAS_sys + 'spar_thickness_cp', np.array([0.004, 0.005, 0.008, 0.01]), units='m')\n", "prob.set_val(OAS_sys + 'skin_thickness_cp', np.array([0.005, 0.01, 0.015, 0.025]), units='m')\n", "prob.set_val(OAS_sys + 't_over_c_cp', np.array([0.08, 0.08, 0.10, 0.08]), units='unitless')\n", @@ -746,13 +969,30 @@ "prob.set_val(OAS_sys + 'engine_location', np.array([25, -10.0, 0.0]), units='m')" ] }, + { + "cell_type": "markdown", + "id": "e61579fc", + "metadata": {}, + "source": [ + "We are now ready to run Aviary on this model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9eca5661", + "metadata": {}, + "outputs": [], + "source": [ + "prob.run_aviary_problem('oas_solution.db', run_driver=False, make_plots=False)" + ] + }, { "cell_type": "markdown", "id": "d345e83d", "metadata": {}, "source": [ - "We are now ready to run Aviary on this model.\n", - "Note that there are multiple numbers of optimization loops that are output from this run even though we have set `max_iter` to 0.\n", + "Note that there are multiple numbers of optimization loops that are output from this run even though we have set {glue:md}`max_iter` to 0.\n", "This is because OpenAeroStruct has an optimization process internally. In order to shorten the runtime, we have set `run_driver = False`. This means that we will not run optimization but [run model](https://openmdao.org/newdocs/versions/latest/features/core_features/running_your_models/run_model.html). " ] }, @@ -771,7 +1011,7 @@ "metadata": {}, "outputs": [], "source": [ - "print('wing mass = ',prob.model.get_val(av.Aircraft.Wing.MASS, units='lbm'))" + "print('wing mass = ', prob.model.get_val(av.Aircraft.Wing.MASS, units='lbm'))" ] }, { @@ -799,7 +1039,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level1.ipynb b/aviary/docs/getting_started/onboarding_level1.ipynb index c6afb14566..17571e14fe 100644 --- a/aviary/docs/getting_started/onboarding_level1.ipynb +++ b/aviary/docs/getting_started/onboarding_level1.ipynb @@ -1,5 +1,25 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "3b749fb0", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.interface.methods_for_level2 import AviaryGroup\n", + "from aviary.utils.doctape import glue_class_options\n", + "\n", + "current_glued_vars = []\n", + "\n", + "glue_class_options(AviaryGroup, current_glued_vars, md_code=True)" + ] + }, { "cell_type": "markdown", "id": "e78c2158", @@ -26,6 +46,54 @@ "!aviary" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "51f42a8c", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "import aviary.api as av\n", + "from aviary.interface.methods_for_level1 import run_level_1\n", + "from aviary.utils.doctape import check_value, glue_variable\n", + "from aviary.utils.functions import get_model, get_path\n", + "\n", + "# obtain the default value of maximum number of iterations from function run_level_1().\n", + "num_max_iter = inspect.signature(run_level_1).parameters['max_iter'].default\n", + "glue_variable('num_max_iter', str(num_max_iter), md_code=False)\n", + "\n", + "# check if aircraft_for_bench_GwGm.csv exists in models/aircraft/test_aircraft/.\n", + "csv_file_path = get_model('aircraft_for_bench_GwGm.csv')\n", + "\n", + "glue_variable(csv_file_path.stem, md_code=True)\n", + "glue_variable(csv_file_path.name, md_code=True)\n", + "glue_variable(csv_file_path.relative_to(av.top_dir), md_code=True)\n", + "\n", + "glue_dos2unix = 'dos2unix ' + str(csv_file_path.name)\n", + "glue_variable('dos2unix aircraft_for_bench_GwGm.csv', glue_dos2unix, md_code=False)\n", + "\n", + "path = get_path('models').relative_to(av.top_dir.parent)\n", + "glue_variable(path, md_code=True)\n", + "path = get_path('models/aircraft/test_aircraft').relative_to(av.top_dir.parent)\n", + "glue_variable(path, md_code=True)\n", + "\n", + "check_value(av.EquationsOfMotion.HEIGHT_ENERGY.value, 'height_energy')\n", + "check_value(av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value, '2DOF')\n", + "check_value(av.EquationsOfMotion.SOLVED_2DOF.value, 'solved_2DOF')\n", + "\n", + "HEIGHT_ENERGY = av.EquationsOfMotion.HEIGHT_ENERGY\n", + "glue_variable('height_energy', HEIGHT_ENERGY.name, md_code=True)\n", + "TWO_DEGREES_OF_FREEDOM = av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM\n", + "glue_variable(TWO_DEGREES_OF_FREEDOM.name, md_code=True)" + ] + }, { "cell_type": "markdown", "id": "eebbbea4", @@ -35,17 +103,25 @@ "\n", "## First level 1 run\n", "\n", - "We are ready to run some models. By default, Aviary runs the optimizer for up to 50 iterations. In order to reduce the run time, we will limit the maximum number of iterations to 1. It will be faster for these examples, but you will not get optimal solutions. Issue the following command:" + "We are ready to run some models. By default, Aviary runs the optimizer for up to {glue:md}`num_max_iter` iterations. In order to reduce the run time, we will limit the maximum number of iterations to 1. It will be faster for these examples, but you will not get optimal solutions. \n", + "\n", + "Note: The following examples use the IPOPT optimizer, which is accessible by installing pyoptsparse. An example of a level 1 problem using the SLSQP optimizer is available in 'run_level1_example.py' in the aviary/examples directory. \n", + "\n", + "Issue the following command:" ] }, { "cell_type": "code", "execution_count": null, "id": "844ca5ad", - "metadata": {}, + "metadata": { + "tags": [ + "hide-output" + ] + }, "outputs": [], "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1" + "!aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1" ] }, { @@ -53,11 +129,12 @@ "id": "386ca993", "metadata": {}, "source": [ - "The argument `models/test_aircraft/aircraft_for_bench_GwGm.csv` shows where the aircraft csv file lives. This argument must be one of the following three options:\n", + "The argument {glue:md}`models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv` shows where the aircraft csv file lives. This argument must be one of the following three options:\n", "\n", "- an absolute path,\n", "- a relative path relative to the current working directory,\n", - "- a relative path relative to the Aviary package.\n", + "- a relative path relative to the Aviary package,\n", + "- a relative path relative to the Aviary models folder.\n", "\n", "Aviary searches for the given dataset in this order. If a dataset file exists in multiple directories, the first one Aviary finds will be used.\n", "\n", @@ -77,14 +154,13 @@ "- **UserWarning:** Issued for warnings about potential OpenMDAO, Dymos, and/or Aviary problems.\n", "- **DerivativesWarning:** Issued when the approximated partials or coloring cannot be evaluated as expected (an [OpenMDAO warning](https://openmdao.org/newdocs/versions/latest/features/warning_control/warnings.html)).\n", "\n", - "Some of these warnings are expected and can be ignored. For example, the following warnings are expected when running the `aircraft_for_bench_GwGm.csv` model:\n", + "Some of these warnings are expected and can be ignored. For example, the following warnings are expected when running the {glue:md}`aircraft_for_bench_GwGm.csv` model:\n", "\n", "```\n", - "~/workspace/OpenMDAO/openmdao/core/group.py:326: PromotionWarning:: Setting input defaults for input 'mission:takeoff:ascent_duration' which override previously set defaults for ['auto', 'prom', 'src_shape', 'val'].\n", - "~/workspace/dymos/dymos/phase/phase.py:2007: RuntimeWarning: Invalid options for non-optimal control 'throttle' in phase 'groundroll': lower, upper\n", - " warnings.warn(f\"Invalid options for non-optimal control '{name}' in phase \"\n", - "~/workspace/dymos/dymos/phase/phase.py:1967: UserWarning: Phase time options have no effect because fix_initial=True or input_initial=True for phase 'traj.phases.rotation': initial_ref\n", - " warnings.warn(f'Phase time options have no effect because fix_initial=True '\n", + "'rhs_checking' is disabled for 'DirectSolver in 'traj.phases.desc1' ' but that solver has redundant adjoint solves. If it is expensive to compute derivatives for this solver, turning on 'rhs_checking' may improve performance.\n", + "\n", + "~/OpenMDAO/OpenMDAO/openmdao/core/total_jac.py:1670: DerivativesWarning:The following constraints or objectives cannot be impacted by the design variables of the problem at the current design point:\n", + " traj.climb2.mach[final], inds=[(11, 0)]\n", "```\n", "\n", "For now, we can ignore the warning messages and continue.\n", @@ -101,44 +177,48 @@ "metadata": {}, "outputs": [], "source": [ - "!aviary run_mission" + "!aviary run_mission -h" ] }, { - "cell_type": "markdown", - "id": "01f6c52c", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "id": "b7878ec1", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], "source": [ - "Let us discuss these in more detail:\n", - "\n", - "- `-o ––outdir`: Use specified directory to write output. The default is the current directory.\n", - "\n", - "- `--optimizer`: Name of optimizer. Choices are: `SNOPT`, `IPOPT`, `SLSQP`, and `None`. The default is `SNOPT`. If optimizer is `None`, it will be set to `IPOPT` or `SNOPT` depending on the analysis scheme. The optimization objective is fuel burn for level 1 runs. The objective is\n", - " - `mission:objectives:fuel` if `mission_method` is `GASP` \n", - " - `fuel_burned` if `mission_method` is `FLOPS`.\n", - "\n", - "- `--phase_info`: Path to phase info file. If not provided, it is `default_phase_info/gasp.py` if Mission origin is `2DOF` and `default_phase_info/flops.py` for `simple`.\n", - "\n", - "- `--max_iter`: Maximum number of iterations. Default is 50.\n", + "# Testing Cell\n", + "from aviary.utils.doctape import glue_actions, glue_variable\n", + "from aviary.variable_info.variables import Aircraft, Mission\n", "\n", - "- `shooting`: Use shooting instead of collocation.\n", + "glue_actions('run_mission', current_glued_vars, glue_default=True, glue_choices=True)\n", "\n", - "For the `aircraft_for_bench_GwGm` example so far, we have used the `IPOPT` optimizer because it is publicly available through [pyOptSparse](https://mdolab-pyoptsparse.readthedocs-hosted.com/en/latest/)." + "glue_variable(Aircraft.__name__, md_code=True)\n", + "glue_variable(Mission.__name__, md_code=True)\n", + "glue_variable(Aircraft.__name__.lower(), md_code=True)\n", + "glue_variable(Mission.__name__.lower(), md_code=True)" ] }, { "cell_type": "markdown", - "id": "3283590e", + "id": "01f6c52c", "metadata": {}, "source": [ - "## Aviary run_mission command\n", + "Let us discuss these in more detail:\n", "\n", - "The Level 1 CLI (i.e. `run_mission` option) is designed to offer the lowest barrier to entry for new users.\n", - "Analysts who have experience with legacy tools, such as `FLOPS` and `GASP`, should find the switch from FORTRAN namelists to csv-based input decks to be straightforward. Aviary input decks allow the user the ability to set aircraft characteristics and basic mission parameters,\n", - "such as cruise Mach number and altitude, in a simple text-based format that does not require any familiarity with Python or OpenMDAO.\n", + "- {glue:md}`--optimizer`: Name of optimizer. Choices are: {glue:md}`SNOPT`, {glue:md}`IPOPT`, {glue:md}`SLSQP`, and `None`. The default is {glue:md}`IPOPT`. If optimizer is `None`, it will be set to {glue:md}`IPOPT`. The optimization objective is fuel burn for level 1 runs. The objective is\n", + " - `mission:objectives:fuel` if `mission_method` is `GASP` \n", + " - `fuel_burned` if `mission_method` is `FLOPS`.\n", "\n", - "Aviary can then be executed by calling [`aviary run_mission`](../user_guide/aviary_commands) with the csv input deck.\n", - "Although the order of the variables in the input deck is not important, you might find it helpful to separate the variables based on if they're used as initial guesses or in the metadata." + "- {glue:md}`--phase_info`: Path to phase info file. If not provided, it is {glue:md}`models/missions/two_dof_default.py` if mission origin is {glue:md}`TWO_DEGREES_OF_FREEDOM` and {glue:md}`models/missions/height_energy_default.py` for {glue:md}`HEIGHT_ENERGY`.\n", + "\n", + "- {glue:md}`--max_iter`: Maximum number of iterations. Default is {glue:md}`num_max_iter`.\n", + "\n", + "For the {glue:md}`aircraft_for_bench_GwGm.csv` example so far, we have used the {glue:md}`IPOPT` optimizer because it is publicly available through [pyOptSparse](https://mdolab-pyoptsparse.readthedocs-hosted.com/en/latest/)." ] }, { @@ -154,7 +234,30 @@ "source": [ "# Testing Cell\n", "from aviary.interface.cmd_entry_points import _command_map\n", - "_command_map['run_mission'];" + "\n", + "run_mission = 'run_mission'\n", + "_command_map[run_mission]\n", + "command = 'aviary ' + run_mission\n", + "glue_variable(run_mission, md_code=True)\n", + "glue_variable(command, md_code=True)\n", + "f_to_a = 'fortran_to_aviary'\n", + "_command_map[f_to_a]\n", + "glue_variable(f_to_a, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "92de3e87", + "metadata": {}, + "source": [ + "## Aviary run_mission command\n", + "\n", + "The Level 1 CLI (i.e. {glue:md}`run_mission` option) is designed to offer the lowest barrier to entry for new users.\n", + "Analysts who have experience with legacy tools, such as `FLOPS` and `GASP`, should find the switch from FORTRAN namelists to csv-based input decks to be straightforward. Aviary input decks allow the user the ability to set aircraft characteristics and basic mission parameters,\n", + "such as cruise Mach number and altitude, in a simple text-based format that does not require any familiarity with Python or OpenMDAO.\n", + "\n", + "Aviary can then be executed by calling {glue:md}`aviary run_mission` with the csv input deck.\n", + "Although the order of the variables in the input deck is not important, you might find it helpful to separate the variables based on if they're used as initial guesses or in the metadata." ] }, { @@ -164,7 +267,7 @@ "source": [ "## First aircraft model\n", "\n", - "We have a few sample aircraft csv files in `aviary/models`. They are all `.csv` files. For example, `aircraft_for_bench_GwGm.csv` (in test_models) is a large single aisle aircraft mission model." + "We have a few sample aircraft csv files in {glue:md}`aviary/models`. They are all `.csv` files. For example, {glue:md}`aircraft_for_bench_GwGm.csv` (in {glue:md}`aviary/models/aircraft/test_aircraft`) is a large single aisle aircraft mission model." ] }, { @@ -179,8 +282,62 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.functions import get_path\n", - "get_path('models/test_aircraft/aircraft_for_bench_GwGm.csv');" + "from aviary.utils.functions import get_model, get_path\n", + "\n", + "get_path('models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv')\n", + "\n", + "csv_snippet = '```\\n'\n", + "filename = 'aircraft_for_bench_GwGm.csv'\n", + "with open(get_model(filename)) as f_in:\n", + " lines = f_in.readlines()\n", + " n = len(lines)\n", + " l_aircraft = []\n", + " l_mission = []\n", + " l_settings = []\n", + " l_init = []\n", + " l_GASP = []\n", + " cnt_aircraft = 0\n", + " cnt_mission = 0\n", + " cnt_settings = 0\n", + " cnt_initial = 0\n", + " cnt_gasp = 0\n", + " for idx in range(n):\n", + " s = lines[idx]\n", + " if 'aircraft:wing:aspect_ratio' in s:\n", + " glue_variable('aircraft:wing:aspect_ratio', md_code=True)\n", + " glue_variable('Aircraft.Wing.ASPECT_RATIO', md_code=True)\n", + " pass\n", + " elif 'climb_range' in s:\n", + " glue_variable('climb_range', md_code=True)\n", + " if s.startswith('aircraft') and cnt_aircraft < 3:\n", + " l_aircraft.append(s)\n", + " cnt_aircraft += 1\n", + " elif s.startswith('mission') and cnt_mission < 3:\n", + " l_mission.append(s)\n", + " cnt_mission += 1\n", + " elif s.startswith('settings') and cnt_settings < 3:\n", + " l_settings.append(s)\n", + " cnt_settings += 1\n", + " elif s.count(',') == 1 and cnt_initial < 3:\n", + " l_init.append(s)\n", + " cnt_initial += 1\n", + " elif s.startswith('INGASP') and cnt_gasp < 3:\n", + " l_GASP.append(s)\n", + " cnt_gasp = cnt_gasp + 1\n", + " l = l_aircraft\n", + " l.extend(['......\\n'])\n", + " l.extend(l_mission)\n", + " l.extend(['......\\n'])\n", + " l.extend(l_settings)\n", + " l.extend(['......\\n'])\n", + " l.extend(l_init)\n", + " l.extend(['......\\n'])\n", + " l.extend(l_GASP)\n", + " l.extend(['......\\n'])\n", + " csv_snippet += ''.join(l)\n", + "\n", + "csv_snippet += '...\\n```'\n", + "glue_variable('csv_snippet', csv_snippet, md_code=False)" ] }, { @@ -188,55 +345,46 @@ "id": "d0094350", "metadata": {}, "source": [ - "Open `aircraft_for_bench_GwGm.csv` using your favorite editor (e.g., MS Excel or VS Code). If you choose to use MS Excel, you need to take extra steps to make sure that it is in the original format. We recommend running dos2unix first (e.g. `dos2unix aircraft_for_bench_GwGm.csv`).\n", + "Open {glue:md}`aircraft_for_bench_GwGm.csv` using your favorite editor (e.g., MS Excel or VS Code). If you choose to use MS Excel, you need to take extra steps to make sure that it is in the original format. We recommend running dos2unix first (e.g. {glue:md}`dos2unix aircraft_for_bench_GwGm.csv`).\n", "\n", - "The file `aircraft_for_bench_GwGm.csv` is a data input file modeling large single aisle aircraft which was converted from a `GASP` input deck.\n", + "The file {glue:md}`aircraft_for_bench_GwGm.csv` is a data input file modeling large single aisle aircraft which was converted from a `GASP` input deck.\n", "Here is a snippet of the file:\n", "\n", - "```\n", - "aircraft:air_conditioning:mass_coefficient,1.65,unitless\n", - "aircraft:anti_icing:mass,551,lbm\n", - "aircraft:apu:mass,928,lbm\n", - "......\n", - "mission:design:cruise_altitude,37500,ft\n", - "mission:design:gross_mass,175400,lbm\n", - "......\n", - "reserves,0\n", - "rotation_mass,0.99\n", - "time_to_climb,0\n", - "......\n", - "INGASP.ALR,1.11,\n", - "INGASP.BENGOB,0.05,\n", - "INGASP.CINP,0.11,\n", - "......\n", + "```{glue:md} csv_snippet\n", + ":format: myst\n", "```\n", "\n", "The input `.csv` file defines the aircraft and mission. In an Aviary input file you see a list of Aviary variables, their values, and units. Aviary variables are colon delimited strings (e.g. `aircraft:wing:aspect_ratio`). An Aviary variable name usually has three words. The first word is `aircraft` or `mission`, the second word is a subsystem name and the third is the variable name. Each variable has a value and units. Aviary requires units for every variable because it reduces errors and is a good engineering practice.\n", "\n", "```{note}\n", - "If you have used the `fortran_to_aviary` tool to create a `.csv` file you must check the outputted variable values and units to ensure the file is valid and what you expect.\n", + "If you have used the {glue:md}`fortran_to_aviary` tool to create a `.csv` file you must check the outputted variable values and units to ensure the file is valid and what you expect.\n", "```\n", "\n", - "Be aware that some variables do not follow the standard naming format (e.g. `reserves`). These are used for the initial guessing of the trajectory. They are intentionally separate to prevent conflicts with some similarly named variables. They are only used once to set up the problem and then are discarded.\n", + "Be aware that some variables do not follow the standard naming format (e.g. {glue:md}`climb_range`). These are used for the initial guessing of the trajectory. They are intentionally separate to prevent conflicts with some similarly named variables. They are only used once to set up the problem and then are discarded.\n", "\n", "Finally we see a list of `GASP` variables that are not converted. Not all variables are converted to Aviary right now. They may represent some features in `FLOPS` and `GASP` that we haven't implemented in Aviary yet.\n", "\n", "To find information about a variable (e.g. description, data type, etc.), users should read the [Variable Metadata Doc](../user_guide/variable_metadata).\n", "\n", - "There are special rules for the mapping from the input file variable names to the metadata. For example, variable `aircraft:wing:aspect_ratio` in `aircraft_for_bench_GwGm.csv` is mapped to `Aircraft.Wing.ASPECT_RATIO` in `aviary/variable_info/variable_meta_data.py`. So, the first part (e.g., `aircraft` or `mission`) is mapped to the same word but with the first letter capitalized (e.g., `Aircraft` or `Mission`). The third word is all caps (e.g., `ASPECT_RATIO`). The middle part (e.g., `wing`) is a little more complicated. In most cases, this part capitalizes the first letter (e.g., `Wing`). The following words have special mappings:\n", - "\n", - "- `air_conditioning -> AirConditioning`\n", - "- `anti_icing -> AntiIcing`\n", - "- `blended_wing_body -> BWB`\n", - "- `crew_and_payload -> CrewPayload`\n", - "- `horizontal_tail -> HorizontalTail`\n", - "- `landing_gear -> LandingGear`\n", - "- `tail_boom -> TailBoom`\n", - "- `vertical_tail -> VerticalTail`\n", - "\n", - "This can be summarized as to capitalize the leading letter and to capitalize the first letter after special character “`_`”.\n", + "Variable names may appear differently within the code from how they are formatted inside OpenMDAO components and in input files and outputs. This is because OpenMDAO requires variable names to be strings, but for developer convenience those strings are mapped to Python classes and attributes. The top-level and sub-categories have capitalized first letters, and the final variable name is always in all-caps. For more information on Aviary's variable hierarchy, see the [Variable Hierarchy doc](../user_guide/variable_hierarchy.ipynb).\n", "\n", - "File `aviary/variable_info/variables.py` is a variable hierarchy that is for a single mission. Each mission gets a copy of this hierarchy. Below is a snippet of this file:" + "File {glue:md}`aviary/variable_info/variables.py` is a variable hierarchy that is for a single mission. Each mission gets a copy of this hierarchy. Below is a snippet of this file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3c818d7", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "file_path = av.get_path('variable_info/variables.py')\n", + "glue_variable(file_path.relative_to(av.top_dir.parent), md_code=True)" ] }, { @@ -255,9 +403,9 @@ "# Get the path of variables.py within the aviary package\n", "file_path = av.get_path('variable_info/variables.py')\n", "\n", - "# Read and print the first 15 lines of the file\n", + "# Read and print the first 17 lines of the file\n", "with open(file_path, 'r') as file:\n", - " for i in range(18):\n", + " for i in range(17):\n", " print(file.readline().strip('\\n'))" ] }, @@ -269,6 +417,40 @@ "Aviary variables are always set to default values before the input file is read in. Then Aviary will update the values based on the user-provided `.csv` input file. If you want to set different values, you can set them in the `.csv` input file." ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b10a4df", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "# check if the following model files exist.\n", + "\n", + "other_models = '```\\n'\n", + "filename = 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv'\n", + "filepath = av.get_path(filename)\n", + "other_models += 'aviary/' + filename + '\\n'\n", + "\n", + "filename = 'models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv'\n", + "filepath = av.get_path(filename)\n", + "other_models += 'aviary/' + filename + '\\n'\n", + "glue_variable('large_single_aisle_1', md_code=True)\n", + "\n", + "filename = 'models/aircraft/small_single_aisle/small_single_aisle_GASP.csv'\n", + "filepath = av.get_path(filename)\n", + "other_models += 'aviary/' + filename + '\\n'\n", + "\n", + "glue_variable('other_models', other_models, md_code=False)" + ] + }, { "cell_type": "markdown", "id": "74c88a21", @@ -278,24 +460,25 @@ "\n", "Other input files reside in aviary/models. They include:\n", "\n", - "```\n", - "aviary/models/validation_data/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv\n", - "aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv\n", - "aviary/models/small_single_aisle/small_single_aisle_GwGm.csv\n", - "aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv\n", + "```{glue:md} other_models\n", + ":format: myst\n", "```\n", "\n", - "For example, to run `large_single_aisle_1` model, you execute the following command:" + "For example, to run {glue:md}`large_single_aisle_1` model, you execute the following command:" ] }, { "cell_type": "code", "execution_count": null, "id": "1f10bc75", - "metadata": {}, + "metadata": { + "tags": [ + "hide-output" + ] + }, "outputs": [], "source": [ - "!aviary run_mission models/large_single_aisle_1/large_single_aisle_1_GwGm.csv --max_iter 1 --optimizer IPOPT" + "!aviary run_mission models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv --max_iter 1 --optimizer IPOPT" ] }, { @@ -310,10 +493,14 @@ "cell_type": "code", "execution_count": null, "id": "5217ccc8", - "metadata": {}, + "metadata": { + "tags": [ + "hide-output" + ] + }, "outputs": [], "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --max_iter 1 --optimizer IPOPT" + "!aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv --max_iter 1 --optimizer IPOPT" ] }, { @@ -324,19 +511,19 @@ "## Aviary fortran_to_aviary command\n", "\n", "```{note}\n", - "You only need to use the `fortran_to_aviary` command if you are converting a FLOPS or GASP deck to Aviary's csv format.\n", + "You only need to use the {glue:md}`fortran_to_aviary` command if you are converting a FLOPS or GASP deck to Aviary's csv format.\n", "```\n", "\n", - "This [`fortran_to_aviary`](../user_guide/aviary_commands) tool converts FORTRAN namelists into Aviary's csv based format using the mappings found in the `historical_name` section of the [variable_meta_data](../user_guide/variable_metadata). The resulting csv is automatically sorted into three sections:\n", + "This {glue:md}`fortran_to_aviary` tool (see [Aviary Commands](../user_guide/aviary_commands) for details) converts FORTRAN namelists into Aviary's csv based format using the mappings found in the `historical_name` section of the [variable_meta_data](../user_guide/variable_metadata). The resulting csv is automatically sorted into three sections:\n", "1. **Input Values:**\n", - " Any FORTRAN variables that were mapped to input variables in Aviary components\n", + " Any FORTRAN variables that were mapped to input variables in the variable metadata, converted to their equivalent Aviary names\n", "2. **Initial Guesses:**\n", " Some variables are only used as initial guesses for the trajectory.\n", " These are displayed separately from the Input Values because they will not be passed directly to components\n", "3. **Unconverted Values:**\n", - " If the fortran_to_aviary converter can't find an Aviary variable that matches the FORTRAN variable, it is added to the end of the csv file.\n", + " If the {glue:md}`fortran_to_aviary` converter can't find an Aviary variable that matches the FORTRAN variable, it is added to the end of the csv file.\n", " We recommend that you check this section after converting a namelist to ensure that there aren't any variables you expected to be converted here.\n", - " Many of these unconverted variables represent features or options that are not used in Aviary and can be safely ignored. Variables related to mission definition are important, but Aviary defines mission profiles in a significantly different way. Currently, the user must build a new [mission definition file](../examples/simple_mission_example) that recreates the mission.\n", + " Many of these unconverted variables represent features or options that are not used in Aviary and can be ignored. Variables related to mission definition are important, but Aviary defines mission profiles in a significantly different way. Currently, the user must build a new [mission definition file](../examples/simple_mission_example) that recreates the mission.\n", " Aviary will ignore unconverted variables when loading the csv, so you can safely leave them.\n" ] }, @@ -344,12 +531,17 @@ "cell_type": "code", "execution_count": null, "id": "117aea9a", - "metadata": {}, + "metadata": { + "tags": [ + "remove-cell" + ] + }, "outputs": [], "source": [ "# Testing Cell\n", "from aviary.interface.cmd_entry_points import _command_map\n", - "_command_map['fortran_to_aviary'];" + "\n", + "_command_map['fortran_to_aviary']" ] }, { @@ -359,13 +551,13 @@ "source": [ "## Phase info\n", "\n", - "Aviary runs depend not only on input `*.csv` files, but also on `phase_info` dictionaries. A `phase_info` dictionary defines the mission and any analysis settings used within Aviary. It is used by Aviary to build a mission trajectory (e.g., from take-off to landing).\n", + "Aviary runs depend not only on input `*.csv` files, but also on {glue:md}`phase_info` dictionaries. A {glue:md}`phase_info` dictionary defines the mission and any analysis settings used within Aviary. It is used by Aviary to build a mission trajectory (e.g., from take-off to landing).\n", "\n", - "A [Python dictionary](https://www.w3schools.com/python/python_dictionaries.asp) is a set of key-value pairs. Most keys in `phase_info` are self-explained. Users should read Dymos' [Phase Options](https://openmdao.github.io/dymos/api/phase_api.html). For more details about phase_info keys, especially their example usages, please read [onboarding phase information](input_csv_phase_info).\n", + "A [Python dictionary](https://www.w3schools.com/python/python_dictionaries.asp) is a set of key-value pairs. Most keys in {glue:md}`phase_info` are self-explained. Users should read Dymos' [Phase Options](https://openmdao.github.io/dymos/api/phase_api.html). For more details about phase_info keys, especially their example usages, please read [onboarding phase information](input_csv_phase_info).\n", "\n", - "### Default GASP phases\n", + "### Default TWO_DEGREES_OF_FREEDOM phases\n", "\n", - "The `default_phase_info/two_dof.py` file is shown below:" + "The {glue:md}`aviary/models/missions/two_dof_default.py` file is shown below:" ] }, { @@ -382,7 +574,7 @@ "import aviary.api as av\n", "\n", "# Get the path of variables.py within the aviary package\n", - "file_path = av.get_path('interface/default_phase_info/two_dof.py')\n", + "file_path = av.get_path('models/missions/two_dof_default.py')\n", "\n", "# Read the file contents\n", "with open(file_path, 'r') as file:\n", @@ -391,10 +583,10 @@ " if line.startswith('phase_info ='):\n", " print(line.strip('\\n'))\n", " break\n", - " \n", + "\n", " # Print the remaining lines\n", " for line in file:\n", - " print(line.strip('\\n'))\n" + " print(line.strip('\\n'))" ] }, { @@ -409,10 +601,98 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.default_phase_info.two_dof import phase_info\n", - "from aviary.interface.utils.check_phase_info import check_phase_info, TWO_DEGREES_OF_FREEDOM\n", - "\n", - "check_phase_info(phase_info, TWO_DEGREES_OF_FREEDOM);\n" + "from aviary.models.missions.two_dof_default import phase_info\n", + "from aviary.utils.doctape import check_value, glue_keys, glue_variable\n", + "from aviary.variable_info.enums import EquationsOfMotion, SpeedType\n", + "\n", + "TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM\n", + "# make sure that the default values in two_dof.py are not changed.\n", + "\n", + "duration_bounds = phase_info['groundroll']['user_options']['time_duration_bounds']\n", + "duration_bounds_lower = float(duration_bounds[0][0])\n", + "duration_bounds_upper = float(duration_bounds[0][1])\n", + "# check_value(duration_bounds, ((1., 100.), 's'))\n", + "glue_variable('default_duration_bounds', duration_bounds, md_code=True)\n", + "\n", + "duration_ref = phase_info['groundroll']['user_options']['time_duration_ref']\n", + "duration_ref_val = float(duration_ref[0])\n", + "# check_value(duration_ref, (50.0, 's'))\n", + "glue_variable('default_duration_ref', duration_ref, md_code=True)\n", + "\n", + "duration_lower_relative = duration_bounds_lower / duration_ref_val\n", + "duration_upper_relative = duration_bounds_upper / duration_ref_val\n", + "glue_variable('duration_lower_relative', duration_lower_relative, md_code=True)\n", + "glue_variable('duration_upper_relative', duration_upper_relative, md_code=True)\n", + "glue_variable(\n", + " 'time_duration_bounds_relative',\n", + " f'({duration_lower_relative}, {duration_upper_relative})',\n", + " md_code=True,\n", + ")\n", + "\n", + "velocity_bounds = phase_info['groundroll']['user_options']['velocity_bounds']\n", + "velocity_lower_val = float(velocity_bounds[0][0])\n", + "velocity_upper_val = float(velocity_bounds[0][1])\n", + "glue_variable('default_velocity_bounds', velocity_bounds, md_code=True)\n", + "\n", + "velocity_ref = phase_info['groundroll']['user_options']['velocity_ref']\n", + "velocity_ref_val = float(velocity_ref[0])\n", + "glue_variable('default_velocity_ref', velocity_ref, md_code=True)\n", + "\n", + "velocity_lower_relative = velocity_lower_val / velocity_ref_val\n", + "velocity_upper_relative = velocity_upper_val / velocity_ref_val\n", + "glue_variable('velocity_lower_relative', velocity_lower_relative, md_code=True)\n", + "glue_variable('velocity_upper_relative', velocity_upper_relative, md_code=True)\n", + "glue_variable(\n", + " 'velocity_bounds_relative',\n", + " f'({velocity_lower_relative}, {velocity_upper_relative})',\n", + " md_code=True,\n", + ")\n", + "\n", + "distance_ref = phase_info['groundroll']['user_options']['distance_ref']\n", + "distance_ref_val = float(distance_ref[0])\n", + "distance_ref_unit = distance_ref[1]\n", + "# check_value(distance_ref, (3000, 'ft'))\n", + "glue_variable('default_distance_ref', distance_ref, md_code=True)\n", + "glue_variable('default_distance_unit', distance_ref_unit, md_code=False)\n", + "\n", + "distance_bounds = phase_info['groundroll']['user_options']['distance_bounds']\n", + "distance_lower_val = float(distance_bounds[0][0])\n", + "distance_upper_val = float(distance_bounds[0][1])\n", + "\n", + "distance_lower_relative = distance_lower_val / distance_ref_val\n", + "distance_upper_relative = distance_upper_val / distance_ref_val\n", + "glue_variable('distance_lower_relative', distance_lower_relative, md_code=True)\n", + "glue_variable('distance_upper_relative', distance_upper_relative, md_code=True)\n", + "\n", + "mass_ref = phase_info['groundroll']['user_options']['mass_ref']\n", + "mass_ref_val = float(mass_ref[0])\n", + "# check_value(mass_ref, (150_000, 'lbm'))\n", + "glue_variable('default_mass_ref', mass_ref, md_code=True)\n", + "\n", + "mass_bounds = phase_info['groundroll']['user_options']['mass_bounds']\n", + "mass_lower_val = float(mass_bounds[0][0])\n", + "mass_upper = mass_bounds[0][1]\n", + "glue_variable('default_mass_bounds', mass_bounds, md_code=True)\n", + "glue_variable('mass_upper', mass_upper, md_code=True)\n", + "\n", + "mass_lower_relative = mass_lower_val / mass_ref_val\n", + "glue_variable('mass_lower_relative', mass_lower_relative, md_code=True)\n", + "\n", + "throttle = phase_info['groundroll']['initial_guesses']['throttle']\n", + "# check_value(throttle, ([0.956, 0.956], 'unitless'))\n", + "\n", + "num_segments = phase_info['groundroll']['user_options']['num_segments']\n", + "# check_value(num_segments, 1)\n", + "glue_variable('default_num_segments', num_segments, md_code=True)\n", + "\n", + "order = phase_info['groundroll']['user_options']['order']\n", + "# check_value(order, 3)\n", + "glue_variable('default_order', order, md_code=True)\n", + "\n", + "mass_defect_ref = phase_info['groundroll']['user_options']['mass_defect_ref']\n", + "glue_variable('default_mass_defect_ref', mass_defect_ref, md_code=True)\n", + "\n", + "glue_keys(phase_info)" ] }, { @@ -420,11 +700,9 @@ "id": "73ee7276", "metadata": {}, "source": [ - "The file `default_phase_info/two_dof.py` contains the following phases:\n", + "The file {glue:md}`two_dof_default.py` contains the following phases:\n", "\n", - "```\n", - "groundroll, rotation, ascent, accel, climb1, climb2, cruise, desc1, desc2.\n", - "```\n", + "{glue:md}`groundroll`, {glue:md}`rotation`, {glue:md}`ascent`, {glue:md}`accel`, {glue:md}`climb1`, {glue:md}`climb2`, {glue:md}`cruise`, {glue:md}`desc1`, {glue:md}`desc2`.\n", "\n", "All of the above phases belong to mission. No pre-mission phase is provided. If `pre_mission` is missing, a default `pre_mission` is provided:\n", "```\n", @@ -454,39 +732,70 @@ "\n", "Let us discuss the groundroll phase in detail as an example.\n", "\n", - "In `groundroll` phase, we are given `duration_bounds` of `((1., 100.), 's')` and a reference value `duration_ref` of `(50., 's')`. Here, `duration_bounds` is a tuple of (lower, upper) bounds for the duration of the integration variable across the phase and `duration_ref` is the unit-reference value for the duration of the integration variable across the phase (see [Dymos Variables](https://openmdao.github.io/dymos/features/phases/variables.html)). This implies a time range of `(0.2, 2)` in ground roll phase, or:\n", - "```\n", - "0.02 ≤ traj.groundroll.t_duration ≤ 2.\n", - "```\n", - "We see `velocity_lower: (0, 'kn')`, `velocity_upper: (1000, 'kn')`, and `velocity_ref: (100, 'kn')`. They result in `TAS` as a design variable with a range: `(0, 10)`, or\n", - "```\n", - "0 ≤ traj.groundroll.states:TAS ≤ 10.\n", - "```\n", + "In {glue:md}`groundroll` phase, we are given {glue:md}`time_duration_bounds` of range {glue:md}`default_duration_bounds` and a reference value {glue:md}`time_duration_ref` of value {glue:md}`default_duration_ref`. Here, {glue:md}`time_duration_bounds` is a tuple of (lower, upper) bounds for the duration of the integration variable across the phase and {glue:md}`time_duration_ref` is the unit-reference value for the duration of the integration variable across the phase (see [Dymos Variables](https://openmdao.github.io/dymos/features/phases/variables.html)). This implies a time range of {glue:md}`time_duration_bounds_relative` in {glue:md}`groundroll` phase, or:\n", + "\n", + "{glue:md}`duration_lower_relative` ≤ traj.groundroll.t_duration ≤ {glue:md}`duration_upper_relative`.\n", + "\n", + "We see {glue:md}`velocity_bounds` with lower and upper bound values of {glue:md}`default_velocity_bounds`, and {glue:md}`velocity_ref` of value {glue:md}`default_velocity_ref`. They result in `velocity` as a design variable with a range: {glue:md}`velocity_bounds_relative`, or\n", + "\n", + "{glue:md}`velocity_lower_relative` ≤ traj.groundroll.states:velocity ≤ {glue:md}`velocity_upper_relative`.\n", + "\n", "Similarly, we get:\n", - "```\n", - "0 ≤ traj.groundroll.states:distance ≤ 3.3333\n", - "```\n", - "The mass parameter is a little bit different because we have `mass_upper: (None, 'lbm')` (and `mass_lower: (0, 'lbm')`). In this situation, OpenMDAO provides replaces the `None` with an actual upper bound that is very large. We get:\n", - "```\n", - "0 ≤ traj.groundroll.states:mass ≤ 5.7e+15.\n", - "```\n", - "Comparing to `TAS` and `distance`, `mass` is not scaled to the same range. This is okay because aircraft mass is actually a constant in this phase. A huge upper bound will not have an impact.\n", "\n", - "In ground roll phase, throttle setting is set to maximum (1.0). Aviary sets a phase parameter:\n", - "```\n", - "Dynamic.Mission.THROTTLE = 1.0\n", - "```\n", - "For the [`COLLOCATION`](https://openmdao.github.io/dymos/getting_started/collocation.html) setting, there is one [segment](https://openmdao.github.io/dymos/getting_started/intro_to_dymos/intro_segments.html) (`'num_segments': 1`) and polynomial interpolation degree is 3 (`'order': 3`). Increasing the number of segments and/or increasing the degree of polynomial will improve accuracy but will also increase the complexity of computation. For groundroll, it is unnecessary.\n", + "{glue:md}`distance_lower_relative` ≤ traj.groundroll.states:distance ≤ {glue:md}`distance_upper_relative`\n", + "\n", + "The mass parameter is a little bit different because we have {glue:md}`mass_bounds`: {glue:md}`default_mass_bounds`. In this situation, OpenMDAO replaces {glue:md}`mass_upper` with an actual upper bound that is very large. We get:\n", + "\n", + "{glue:md}`mass_lower_relative` ≤ traj.groundroll.states:mass ≤ 6.66667e+15.\n", + "\n", + "Comparing to `velocity` and `distance`, `mass` is not scaled to the same range. This is okay because aircraft mass is actually a constant in this phase. A huge upper bound will not have an impact.\n", "\n", - "Since groundroll is the first phase, `connect_initial_mass` is set to `False`. `fix_initial` is set to `True`, but `fix_initial_mass` to `False` because aircraft total mass is a design parameter.\n", + "For the [`COLLOCATION`](https://openmdao.github.io/dymos/getting_started/collocation.html) setting, there is one [segment](https://openmdao.github.io/dymos/getting_started/intro_to_dymos/intro_segments.html) (`'num_segments'`: {glue:md}`default_num_segments`) and polynomial interpolation degree is {glue:md}`default_order` (`'order'`: {glue:md}`default_order`). Increasing the number of segments and/or increasing the degree of polynomial will improve accuracy but will also increase the complexity of computation. For groundroll, it is unnecessary.\n", "\n", - "Parameter `mass_defect_ref: (10.e3, 'lbm')` (or `mass_defect_ref: (1.e4, 'lbm')`) lbm. Defect is a residual that measures how accurately the proposed state and control history obeyed the ODE governing the system dynamics. For distance, the defect reference is `100` ft. For `TAS`, `defect_ref` is not provided. The default behavior is to make make the `defect_ref` equal to the `ref` value. Please see [here](https://stackoverflow.com/questions/65243017/openmdao-dymos-defect-refs-how-should-i-set-these) for more info.\n", + "For parameter {glue:md}`mass_defect_ref`, we set values to {glue:md}`default_mass_defect_ref`. Defect is a residual that measures how accurately the proposed state and control history obeyed the ODE governing the system dynamics. For distance, the defect reference {glue:md}`distance_ref` is {glue:md}`default_distance_ref` {glue:md}`default_distance_unit`.\n", "\n", "#### Other phases\n", "\n", "We will not discuss the other phases in detail.\n", "\n", - "Phase `climb1` is for climb up to 10,000 ft and phase `climb2` is for climb to cruise phase. Phase `desc1` is for descent down to 10,000 ft and phase `desc2` is for descent from 10,000 ft down to 1,000 ft." + "Roughly speaking, phase {glue:md}`climb1` is for climb up to 10,000 ft and phase {glue:md}`climb2` is for climb to cruise phase. Phase {glue:md}`desc1` is for descent down to `10,000` ft and phase {glue:md}`desc2` is for descent from `10,000` ft down to `1,000` ft." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4362df8", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "\n", + "from aviary.variable_info.enums import EquationsOfMotion\n", + "from aviary.utils.doctape import check_value, get_all_keys, get_variable_name\n", + "\n", + "\n", + "TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM\n", + "HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY\n", + "\n", + "phase_info_files = ['height_energy_default.py', 'two_dof_default.py']\n", + "for str_phase_info in phase_info_files:\n", + " file_path = av.get_path('models/missions/' + str_phase_info)\n", + " glue_variable('models/missions/' + str_phase_info)\n", + " # Glue the filename and filepath\n", + " glue_variable((str_phase_info), md_code=True)\n", + " file_path = file_path.relative_to(av.top_dir.parent)\n", + " glue_variable(file_path, md_code=True)\n", + "\n", + "glue_variable(HEIGHT_ENERGY.name, md_code=True)\n", + "\n", + "# glue new phase name (skip 'cruise', 'pre_mission', 'post_mission' to avoid duplicate key)\n", + "for key in ['climb', 'descent']:\n", + " glue_variable(key, md_code=True)" ] }, { @@ -494,18 +803,16 @@ "id": "086a4719", "metadata": {}, "source": [ - "### Default FLOPS phases\n", + "### Default HEIGHT_ENERGY phases\n", "\n", - "The file `default_phase_info/flops.py` contains the following phases:\n", + "The file {glue:md}`aviary/models/missions/height_energy_default.py` contains the following phases:\n", "\n", - "```\n", - "pre_mission, climb, cruise, descent, post_mission\n", - "```\n", + "{glue:md}`pre_mission`, {glue:md}`climb`, {glue:md}`cruise`, {glue:md}`descent`, {glue:md}`post_mission`\n", "\n", - "The differences between `GASP` and `FLOPS` phases are due to how `GASP` and `FLOPS` implement trajectory analysis.\n", + "The differences between {glue:md}`HEIGHT_ENERGY` and {glue:md}`TWO_DEGREES_OF_FREEDOM` phases are due to how `FLOPS` and `GASP` implement trajectory analysis.\n", "\n", "```{note}\n", - "File `default_phase_info/flops.py` has a `pre_mission` phase and a `post_mission` phase. In `pre_mission`, `takeoff` is the simplified takeoff and in `post_mission`, `landing` is the simplified landing. For `FLOPS` missions, there are [detailed takeoff and landing](../user_guide/FLOPS_based_detailed_takeoff_and_landing) available. But they are not used in `default_phase_info/flops.py`. The other phases are mission phases.\n", + "File {glue:md}`aviary/models/missions/height_energy_default.py` has a {glue:md}`pre_mission` phase and a {glue:md}`post_mission` phase. In {glue:md}`pre_mission`, `takeoff` is the simplified takeoff and in `post_mission`, `landing` is the simplified landing. For {glue:md}`HEIGHT_ENERGY` missions, there are [detailed takeoff and landing](../user_guide/FLOPS_based_detailed_takeoff_and_landing) available. But they are not used in `height_energy_default.py`. The other phases are mission phases.\n", "```" ] }, @@ -521,9 +828,9 @@ "We usually expect that users access these reports through the dashboard, though you can also access the html files directly.\n", "```\n", "\n", - "Each standard run generates several output files. Which output files are generated depend on the run options. In this section, we assume that we've set `max_iter = 50` to ensure convergence. The following screenshots used in this article are all from a run using `aircraft_for_bench_GwGm.csv`.\n", + "Each standard run generates several output files. Which output files are generated depend on the run options. In this section, we assume that we've set `max_iter` = {glue:md}`num_max_iter` to ensure convergence. The following screenshots used in this article are all from a run using {glue:md}`aircraft_for_bench_GwGm.csv`.\n", "\n", - "First, there is always a sub-folder `reports/aviary` that contains a few HTML files.\n", + "First, there is always a sub-folder `reports/case_name` where `case_name` is the csv file name. In our case, it is `reports/aircraft_for_bench_GwGm`. It contains a few HTML files:\n", "\n", "- `driver_scaling_report.html`\n", "- `inputs.html`\n", @@ -559,7 +866,26 @@ "\n", "> ![Sample inputs.html (top lines)](images/inputs_html_top.PNG)\n", "\n", - "New users can choose to use `input_list.txt` instead (see below)." + "New users can choose to use `input_list.txt` instead (see below) if `settings:verbosity` is set to 2 or higher. Note that this file lives in the current folder." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d43c3358", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing cell\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import glue_class_functions\n", + "\n", + "# Get all functions of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars)" ] }, { @@ -575,7 +901,7 @@ "We *strongly* recommend that you understand N2 diagrams well, especially if you are debugging a model or adding external subsystems. Here is a [doc page](https://openmdao.github.io/PracticalMDO/Notebooks/ModelConstruction/using_n2.html) featuring an informative video on how to use N2 diagrams effectively. MDO lab has another resource for learning about N2 and [XDSM](https://mdolab-pyxdsm.readthedocs-hosted.com/).\n", "```\n", "\n", - " Here is a screenshot of an N2 diagram after we run `aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv`.\n", + " Here is a screenshot of an N2 diagram after we run `aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv`.\n", "\n", "> ![Sample n2.html (on start)](images/N2_start.PNG)\n", "\n", @@ -587,9 +913,7 @@ "\n", "> ![Sample n2.html (on phases)](images/N2_phases_links.PNG)\n", "\n", - "Note that `desc2` phase is linked back up to `static_analysis`. This means that at least one variable must be matched in the two places. There must be a nonlinear solver for this step. \n", - "\n", - "For `GASP` missions, there is a takeoff subsystem (including `taxi` phase) within `pre_mission`. For `FLOPS` missions, there is a takeoff subsystem within `pre_mission` in which a `takeoff` phase is added. It is added after `static_analysis` in `add_pre_mission_systems` method.\n", + "For {glue:md}`TWO_DEGREES_OF_FREEDOM` missions, there is a takeoff subsystem (including `taxi` phase) within `pre_mission`. For {glue:md}`HEIGHT_ENERGY` missions, there is a takeoff subsystem within `pre_mission` in which a `takeoff` phase is added. It is added after `static_analysis` in {glue:md}`add_pre_mission_systems()` method.\n", "\n", "Similarly, there is a `landing` phase within `post_mission`." ] @@ -643,11 +967,11 @@ "This is one of the most important files produced by Aviary. It will help you visualize and understand the optimal trajectory produced by Aviary.\n", "```\n", "\n", - "This file contains timeseries and phase parameters in different tabs. For our `aircraft_for_bench_GwGm` run, they are: groundroll, rotation, ascent, accel, climb1, climb2, cruise, desc1, and desc2 parameters. On the timeseries tab, users can select which phases to view. The following are the top of timeseries tab and ascent parameters tab:\n", + "This file contains timeseries and phase parameters in different tabs. For our {glue:md}`aircraft_for_bench_GwGm` run, they are: {glue:md}`groundroll`, {glue:md}`rotation`, {glue:md}`ascent`, {glue:md}`accel`, {glue:md}`climb1`, {glue:md}`climb2`, {glue:md}`cruise`, {glue:md}`desc1`, and {glue:md}`desc2` parameters. On the timeseries tab, users can select which phases to view. The following are the top of timeseries tab and ascent parameters tab:\n", "\n", "> ![Sample traj_results_report.html (top part of timeseries)](images/traj_results_report_top.PNG)\n", "\n", - "Let's find the altitude chart. Move the cursor to the top of climb2. We see that the aircraft climbs to 37910 feet at 2814 second. Then it enters to cruise phase. At 28290 second, it starts descent from 37660 feet.\n", + "Let's find the altitude chart. Move the cursor to the top of climb2. We see that the aircraft climbs to 37500 feet at 1200 second. Then it enters to cruise phase. At 28090 second, it starts descent from 40000 feet.\n", "\n", "> ![Sample traj_results_report.html (altitude)](images/traj_results_report_altitude.PNG)\n", "\n", @@ -665,7 +989,28 @@ "source": [ "### Optimizer output\n", "\n", - "If `IPOPT` is the optimizer, `IPOPT.out` is generated. If `SLSQP` is the optimizer and `pyOptSparseDriver` is the driver, `SLSQP.out` is generated. Generally speaking, `IPOPT` and `SNOPT` converge Aviary optimization problems better than `SLSQP`, but `SLSQP` is bundled with Scipy by default, making it more widely available." + "If {glue:md}`IPOPT` is the optimizer, `IPOPT.out` is generated. If {glue:md}`SLSQP` is the optimizer and `pyOptSparseDriver` is the driver, `SLSQP.out` is generated. Generally speaking, {glue:md}`IPOPT` and {glue:md}`SNOPT` converge Aviary optimization problems better than {glue:md}`SLSQP`, but {glue:md}`SLSQP` is bundled with Scipy by default, making it more widely available." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2d62b620", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import glue_function_arguments\n", + "\n", + "# retrieve all argument of build_pre_mission(self, aviary_inputs, **kwargs)\n", + "glue_function_arguments(\n", + " AviaryProblem.run_aviary_problem, current_glued_vars, glue_default=True, md_code=True\n", + ")" ] }, { @@ -675,7 +1020,30 @@ "source": [ "### SQLite database file\n", "\n", - "There is a `.db` file after run. By default, it is `aviary_history.db`. This is an SQLite database file. In level 2 and level 3, we will be able to choose a different name. Our run is recorded into this file. You generally shouldn't need to parse through this file on your own, but it is available if you're seeking additional problem information." + "There is a `.db` file created after run called {glue:md}'problem_history.db' in the report directory. This is an SQLite database file. Our run is recorded into this file. You generally shouldn't need to parse through this file on your own, but it is available if you're seeking additional problem information." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b671348f", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import get_attribute_name, glue_variable\n", + "\n", + "Verbosity = av.Verbosity\n", + "verbosity = get_attribute_name(av.Settings, av.Settings.VERBOSITY)\n", + "glue_variable('VERBOSITY', verbosity, md_code=True)\n", + "glue_variable('BRIEF', av.Verbosity.BRIEF.name, md_code=True)\n", + "glue_variable('VERBOSE', av.Verbosity.VERBOSE.name, md_code=True)\n", + "# glue_variable(av.Settings.VERBOSITY)" ] }, { @@ -685,7 +1053,7 @@ "source": [ "### Plain text inputs and outputs\n", "\n", - "If `Settings.VERBOSITY` is set to `2` (Verbosity.VERBOSE) or higher, `input_list.txt` and `output_list.txt` are generated. We recommend this parameter be set to `1` (Verbosity.BRIEF) for beginners. See [Coding Standards](../developer_guide/coding_standards.ipynb) for more details.\n", + "If {glue:md}`VERBOSITY` is set to `2` ({glue:md}`VERBOSE`) or higher, `input_list.txt` and `output_list.txt` are generated. We recommend this parameter be set to `1` ({glue:md}`BRIEF`) for beginners. See [Coding Standards](../developer_guide/coding_standards.ipynb) for more details.\n", "\n", "Let us look at `input_list.txt`:\n", "\n", @@ -738,6 +1106,27 @@ "```" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "18e1c3c6", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.api import Mission\n", + "from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "glue_variable(get_variable_name(Mission.Objectives.FUEL), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Objectives.RANGE), md_code=True)\n", + "glue_variable(BatteryBuilder.__name__, md_code=True)" + ] + }, { "cell_type": "markdown", "id": "15e1f0b4", @@ -747,16 +1136,15 @@ "\n", "Aviary Level 1 is quite capable yet limited in how much is exposed to the user. If you need additional flexibility or want to add your own subsystems, you will need to move to Levels 2 or 3. Let us briefly discuss some of the possible reasons for you to move to Levels 2 or 3.\n", "\n", - "If you examine the Aviary metadata, you find that Aviary has two choices of objectives: `Mission.Objectives.FUEL` and `Mission.Objectives.RANGE`. But in level 1, you are limited to minimizing fuel. Users will be able to make other choices in level 2 and level 3.\n", + "If you examine the Aviary metadata, you find that Aviary has two choices of objectives: {glue:md}`Mission.Objectives.FUEL` and {glue:md}`Mission.Objectives.RANGE`. But in level 1, you are limited to minimizing fuel. Users will be able to make other choices in level 2 and level 3.\n", "\n", - "Level 1 uses the default `phase_info` dictionaries, though there is an option to use a customized `phase_info`.\n", + "Level 1 uses the default {glue:md}`phase_info` dictionaries, though there is an option to use a customized {glue:md}`phase_info`.\n", "For more details, please read [drawing and running simple missions](../user_guide/drawing_and_running_simple_missions).\n", "\n", - "There may be more or fewer key-value pairs in each of the phases. For example, if you have an external subsystem, say, a battery with `BatteryBuilder()`, you can add a key `external_subsystems` with value `BatteryBuilder()`. We will go into details later.\n", + "There may be more or fewer key-value pairs in each of the phases. For example, if you have an external subsystem, say, a battery with {glue:md}`BatteryBuilder`, you can add a key `external_subsystems` with value {glue:md}`BatteryBuilder`. We will go into details later (see [here](onboarding_ext_subsystem)).\n", "\n", "No matter what mission method users choose, they can create their own phase sequences and run Aviary using either level 2 or 3 interface.\n", "\n", - "In the `aviary/interface/default_phase_info` subdirectory, you see another `phase_info` file `solved.py`. It defines the `phase_info` object for the \"solved\" mission method which is not explained in level 1. The “solved” mission method is a more simplified and robust method than the other methods. In just a few words, it's a way of implementing a trajectory where the aircraft only flies in straight lines in the altitude-range space and usually at constant velocity. The idea is to simplify the design space by reducing the flexibility the optimizer has to choose a trajectory profile. It still uses a collocation method to solve the mission dynamics, but the complexity of the design problem is lessened.\n", "\n", "We are ready to move on to [Level 2](onboarding_level2)." ] @@ -778,7 +1166,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level2.ipynb b/aviary/docs/getting_started/onboarding_level2.ipynb index 1ab60df9b4..172d2c6bd5 100644 --- a/aviary/docs/getting_started/onboarding_level2.ipynb +++ b/aviary/docs/getting_started/onboarding_level2.ipynb @@ -2,33 +2,135 @@ "cells": [ { "cell_type": "markdown", - "id": "04133934", + "id": "cd250ed3", "metadata": {}, "source": [ "# Level 2\n", "\n", "We have discussed [Level 1](onboarding_level1) in great detail. As we have seen, Level 1 is relatively simple.\n", "\n", - "In Level 2, we see more flexibility and additional choices. You will be exposed to some simple Python code and see how Aviary establishes a problem from beginning to end. Each step is built upon the capabilities of [Level 3](onboarding_level3). Users will be led to Level 3 in a natural way.\n", + "In Level 2, we see more flexibility and additional choices. You will be exposed to some simple Python code and see how Aviary establishes a problem from beginning to end. Each step is built upon the capabilities of [Level 3](onboarding_level3). Users will be led to Level 3 in a natural way." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e1804c6", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.api import Dynamic, Mission\n", + "from aviary.interface.methods_for_level1 import run_aviary\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.core.aviary_group import AviaryGroup\n", + "from aviary.utils.doctape import (\n", + " get_variable_name,\n", + " glue_function_arguments,\n", + " glue_keys,\n", + " glue_variable,\n", + " glue_class_functions,\n", + ")\n", + "\n", + "current_glued_vars = []\n", + "\n", + "file_path = av.get_path('interface/methods_for_level1.py').relative_to(av.top_dir)\n", + "glue_variable(file_path, md_code=True)\n", + "glue_variable(file_path.name, md_code=True)\n", + "\n", + "glue_variable(run_aviary.__name__ + '()', md_code=True)\n", + "AviaryValues = av.AviaryValues\n", + "glue_variable(AviaryValues.__name__, md_code=True)\n", + "\n", + "# glue all argument of function run_aviary()\n", + "glue_function_arguments(run_aviary, current_glued_vars, glue_default=True, md_code=True)\n", + "\n", + "# Get all methods of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars, prefix='prob', md_code=True)\n", + "\n", + "glue_keys(dict(av.ProblemType.__members__))\n", + "ProblemType = av.ProblemType\n", + "glue_variable(ProblemType.__name__, md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Mission.Objectives.FUEL), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Objectives.RANGE), md_code=True)\n", + "glue_variable(get_variable_name(Dynamic.Vehicle.MASS), md_code=True)\n", + "\n", + "glue_variable('HEIGHT_ENERGY', av.EquationsOfMotion.HEIGHT_ENERGY.name, md_code=True)\n", + "glue_variable(\n", + " 'TWO_DEGREES_OF_FREEDOM', av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.name, md_code=False\n", + ")\n", + "glue_variable('SOLVED_2DOF', av.EquationsOfMotion.SOLVED_2DOF.name, md_code=True)\n", + "\n", + "glue_variable('height_energy', av.EquationsOfMotion.HEIGHT_ENERGY.value, md_code=True)\n", + "glue_variable('2DOF', av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value, md_code=True)\n", + "glue_variable('solved_2DOF', av.EquationsOfMotion.SOLVED_2DOF.value, md_code=True)\n", + "\n", + "glue_variable('problem_type', av.Settings.PROBLEM_TYPE.split(':')[1], md_code=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5614146d", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import glue_variable, run_command_no_file_error\n", + "from aviary.utils.functions import get_path\n", "\n", - "Level 2 is defined in the [aviary/interface/methods_for_level1.py file](https://github.com/OpenMDAO/Aviary/blob/main/aviary/interface/methods_for_level1.py) and it has a single method `run_aviary()` with a few arguments. If you examine `interface/level1.py` you see that Level 1 prepares those arguments and then call `run_aviary()`. For `aviary run_mission aircraft_for_bench_GwGm` examples, those arguments are:\n", + "file_path = 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv'\n", "\n", - "- `aircraft_filename`: `aircraft_for_bench_GwGm`\n", - "- `phase_info`: `phase_info` (loaded from `aviary/interface/default_phase_info/gasp.py`)\n", - "- `optimizer`: `IPOPT` (the default is `None`)\n", - "- `analysis_scheme`: `AnalysisScheme.COLLOCATION` (the default)\n", - "- `objective_type`: `None` (default)\n", - "- `record_filename`: `problem_history.db` (the default)\n", - "- `restart_filename`: `None` (the default)\n", - "- `max_iter`: 50 (the default)\n", + "command = 'aviary run_mission ' + file_path\n", + "glue_variable(command, md_code=True)\n", + "command += ' --max_iter 0 --optimizer IPOPT'\n", + "run_command_no_file_error(command)\n", "\n", - "All the above arguments are straightforward except `objective_type`. Even though `objective_type` is `None`, it is not treated as `None`. In this scenario, the objective is set based on `problem_type` when using the GASP-based mission method, but not the FLOPS-based mission. There are three options for `problem_type`. Aviary has the following mapping when `objective_type` is not set by user and `mission_method` is `EquationsOfMotion.TWO_DEGREES_OF_FREEDOM`:\n", + "file_path = get_path(file_path)\n", + "glue_variable(file_path.name, md_code=True)\n", + "glue_variable(file_path.stem, md_code=True)\n", "\n", - "| problem_type | objective |\n", + "phase_info_path = av.get_path('models/missions/two_dof_default.py').relative_to(av.top_dir.parent)\n", + "glue_variable('phase_info_path', phase_info_path, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "04133934", + "metadata": {}, + "source": [ + "Level 2 is defined in the [aviary/interface/methods_for_level1.py file](https://github.com/OpenMDAO/Aviary/blob/main/aviary/interface/methods_for_level1.py) and it has a method {glue:md}`run_aviary()` with a few arguments. If you examine {glue:md}`interface/methods_for_level1.py` you see that Level 1 prepares those arguments and then call {glue:md}`run_aviary()`. For {glue:md}`aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv` examples, those arguments and their values are:\n", + "\n", + "- {glue:md}`aircraft_data`: {glue:md}`aircraft_for_bench_GwGm.csv`\n", + "- {glue:md}`phase_info`: not provided (and will be loaded from {glue:md}`phase_info_path`)\n", + "- {glue:md}`optimizer`: {glue:md}`optimizer_default`\n", + "- {glue:md}`objective_type`: {glue:md}`objective_type_default`\n", + "- {glue:md}`restart_filename`: {glue:md}`restart_filename_default`\n", + "- {glue:md}`max_iter`: {glue:md}`max_iter_default`\n", + "- {glue:md}`run_driver`: {glue:md}`run_driver_default`\n", + "- {glue:md}`make_plots`: {glue:md}`make_plots_default`\n", + "- {glue:md}`phase_info_parameterization`: {glue:md}`phase_info_parameterization_default`\n", + "- {glue:md}`verbosity`: {glue:md}`verbosity_default`\n", + "\n", + "All the above arguments are straightforward except {glue:md}`objective_type`. Even though {glue:md}`objective_type` is `None`, it is not treated as `None`. In this scenario, the objective is set based on {glue:md}`problem_type` when using the {glue:md}`2DOF` mission method. There are three options for {glue:md}`problem_type` which is set to {glue:md}`SIZING` as default when aircraft is created. Aviary has the following mapping when user does not set {glue:md}`objective_type` but set `mission_method` to {glue:md}`2DOF` (in .csv file):\n", + "\n", + "| {glue:md}`problem_type` | `objective` |\n", "| ------------ | --------- |\n", - "| `SIZING` | Mission.Objectives.FUEL |\n", - "| `ALTERNATE` | Mission.Objectives.FUEL |\n", - "| `FALLOUT` | Mission.Objectives.RANGE |" + "| {glue:md}`SIZING` | {glue:md}`Mission.Objectives.FUEL` |\n", + "| {glue:md}`ALTERNATE` | {glue:md}`Mission.Objectives.FUEL`|\n", + "| {glue:md}`FALLOUT` | {glue:md}`Mission.Objectives.RANGE` |\n", + "| {glue:md}`MULTI_MISSION` | No Default, user specified |" ] }, { @@ -44,22 +146,22 @@ "source": [ "# Testing Cell\n", "import openmdao.api as om\n", + "\n", "from aviary.api import Mission\n", - "from aviary.variable_info.enums import ProblemType as PT, EquationsOfMotion as EOM\n", "from aviary.interface.methods_for_level2 import AviaryProblem\n", - "from aviary.utils.doctape import check_contains\n", + "from aviary.mission.two_dof_problem_configurator import TwoDOFProblemConfigurator\n", + "from aviary.utils.doctape import check_contains, glue_class_functions, glue_variable\n", + "from aviary.variable_info.enums import EquationsOfMotion as EOM\n", + "from aviary.variable_info.enums import ProblemType as PT\n", + "\n", + "file_path = av.get_path('interface/methods_for_level2.py')\n", + "glue_variable(file_path.name, md_code=True)\n", "\n", - "EOM.HEIGHT_ENERGY;\n", - "mo = Mission.Objectives\n", - "expected_objective = {PT.SIZING:mo.FUEL, PT.ALTERNATE:mo.FUEL, PT.FALLOUT:mo.RANGE}\n", - "for ptype, obj in expected_objective.items():\n", - " dummy_prob = om.Problem()\n", - " dummy_prob.mission_method = EOM.TWO_DEGREES_OF_FREEDOM\n", - " dummy_prob.problem_type = ptype\n", - " AviaryProblem.add_objective(dummy_prob)\n", - " dummy_prob.setup()\n", - " objectives = dummy_prob.model._responses.keys()\n", - " check_contains(obj, objectives)\n" + "# Get all functions of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars, prefix='prob', md_code=True)\n", + "\n", + "# Get all functions of class TwoDOFProblemConfigurator\n", + "glue_class_functions(TwoDOFProblemConfigurator, current_glued_vars, prefix='prob', md_code=True)" ] }, { @@ -67,35 +169,36 @@ "id": "9ffcd43c", "metadata": {}, "source": [ - "In Aviary, `problem_type` is set to `SIZING` when it creates a vehicle (see [create_vehicle](https://github.com/OpenMDAO/Aviary/blob/main/aviary/utils/UI.py)). As you can see, since `problem_type` is `SIZING` by default in our case and we don't manually alter this setting, Aviary set objective to `Mission.Objectives.FUEL`. We will discuss more options of `objective_type` later on.\n", + "In Aviary, {glue:md}`problem_type` is set to {glue:md}`SIZING` when it creates a vehicle (see [create_vehicle](https://github.com/OpenMDAO/Aviary/blob/main/aviary/utils/UI.py)). As you can see, since {glue:md}`problem_type` is {glue:md}`SIZING` by default in our case and we don't manually alter this setting, Aviary set objective to {glue:md}`Mission.Objectives.FUEL`. We will discuss more options of {glue:md}`objective_type` later on.\n", "\n", "```{note}\n", - "If you want to use a custom objective function, you can set any arbitrary variable to be the objective by directly calling the OpenMDAO [`add_objective` method](https://openmdao.org/newdocs/versions/latest/features/core_features/adding_desvars_cons_objs/adding_objective.html#adding-an-objective) instead of using Aviary's built-in `add_objective()` method.\n", + "If you want to use a custom objective function, you can set any arbitrary variable to be the objective by directly calling the OpenMDAO [`add_objective` method](https://openmdao.org/newdocs/versions/latest/features/core_features/adding_desvars_cons_objs/adding_objective.html#adding-an-objective) instead of using Aviary's built-in {glue:md}`add_objective()` method.\n", "```\n", "\n", "In our onboarding runs, we want to limit the number of iterations to 1 so that they all run faster. As a result, we will not consider whether the optimization converges. So, we will have\n", "\n", - "```\n", - "`max_iter`: 1\n", - "```\n", + "{glue:md}`max_iter`: 1\n", "\n", "Level 2 cannot be run via `aviary` command on the command line. Users must develop level 2 Python code. The good news is that the Python code is pretty small. You can follow the following steps in order (we do not include function arguments for simplicity):\n", "\n", "- `prob = AviaryProblem()`\n", - "- `prob.load_inputs()`\n", - "- `prob.check_and_preprocess_inputs()`\n", - "- `prob.add_pre_mission_systems()`\n", - "- `prob.add_phases()`\n", - "- `prob.add_post_mission_systems()`\n", - "- `prob.link_phases()`\n", - "- `prob.add_driver()`\n", - "- `prob.add_design_variables()`\n", - "- `prob.add_objective()`\n", - "- `prob.setup()`\n", - "- `prob.set_initial_guesses()`\n", - "- `prob.run_aviary_problem()`\n", - "\n", - "In the rest of this page, we will show a few examples to demonstrate how level 2 runs these steps. We start from rebuilding `aircraft_for_bench_GwGm` model in great details." + "- {glue:md}`load_inputs()` \n", + "- modify the aviary values dictionary if needed\n", + "- {glue:md}`check_and_preprocess_inputs()`\n", + "- {glue:md}`build_model()`\n", + "- {glue:md}`add_pre_mission_systems()`\n", + "- {glue:md}`add_phases()`\n", + "- {glue:md}`add_post_mission_systems()`\n", + "- {glue:md}`link_phases()`\n", + "- Add custom promotions, connections if needed\n", + "- {glue:md}`add_driver()`\n", + "- {glue:md}`add_design_variables()`\n", + "- {glue:md}`add_objective()`\n", + "- {glue:md}`setup()`\n", + "- Set custom starting values using set_val if needed\n", + "- {glue:md}`run_aviary_problem()`\n", + "\n", + "In the rest of this page, we will show a few examples to demonstrate how level 2 runs these steps. We start from rebuilding {glue:md}`aircraft_for_bench_GwGm` model in great details." ] }, { @@ -103,9 +206,9 @@ "id": "a1b573a9", "metadata": {}, "source": [ - "## Build level 2 for the same `aircraft_for_bench_GwGm` Model\n", + "## Build level 2 for the same {glue:md}`aircraft_for_bench_GwGm` Model\n", "\n", - "We create a level 2 Python script to reproduce the `aircraft_for_bench_GwGm` model run that was used as an example in the level 1 document (this time we won’t use the level 1 functionality). The methods listed above are defined in level 3 (namely, [interface/methods_for_level2.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/interface/methods_for_level2.py)). You can run the code as follows:" + "We create a level 2 Python script to reproduce the {glue:md}`aircraft_for_bench_GwGm` model run that was used as an example in the level 1 document (this time we won’t use the level 1 functionality). The methods listed above are defined in level 3 (namely, [interface/methods_for_level2.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/interface/methods_for_level2.py)). You can run the code as follows:" ] }, { @@ -115,42 +218,33 @@ "metadata": {}, "outputs": [], "source": [ - "from aviary.api import Aircraft, Mission\n", - "import aviary.api as av\n", "from copy import deepcopy\n", "\n", + "import aviary.api as av\n", "\n", "# inputs that run_aviary() requires\n", - "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_GwGm.csv\"\n", - "optimizer = \"IPOPT\"\n", - "analysis_scheme = av.AnalysisScheme.COLLOCATION\n", + "aircraft_data = 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv'\n", + "optimizer = 'IPOPT'\n", "objective_type = None\n", - "record_filename = 'aviary_history.db'\n", "restart_filename = None\n", "max_iter = 0\n", "phase_info = deepcopy(av.default_2DOF_phase_info)\n", "\n", "# Build problem\n", - "prob = av.AviaryProblem(analysis_scheme)\n", + "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(aircraft_filename, phase_info)\n", + "prob.load_inputs(aircraft_data, phase_info)\n", "\n", - "# Preprocess inputs\n", "prob.check_and_preprocess_inputs()\n", + "# check the aircraft_data and phase_info for errors\n", "\n", "# adds a pre-mission group (propulsion, geometry, aerodynamics, and mass)\n", - "prob.add_pre_mission_systems()\n", - "\n", "# adds a sequence of core mission phases.\n", - "prob.add_phases()\n", - "\n", "# adds a landing phase\n", - "prob.add_post_mission_systems()\n", - "\n", "# Link phases and variables\n", - "prob.link_phases()\n", + "prob.build_model()\n", "\n", "# adds an optimizer to the driver\n", "prob.add_driver(optimizer, max_iter=max_iter)\n", @@ -162,14 +256,34 @@ "# Detail which variables the optimizer can control\n", "prob.add_objective(objective_type=objective_type)\n", "\n", - "# setup the problem\n", + "# setup the problem and set initial guesses of states and controls variables\n", "prob.setup()\n", "\n", - "# set initial guesses of states and controls variables\n", - "prob.set_initial_guesses()\n", - "\n", "# run the problem we just set up\n", - "prob.run_aviary_problem(record_filename, restart_filename=restart_filename)" + "prob.run_aviary_problem(restart_filename=restart_filename)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbe17794", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from openmdao.utils.assert_utils import assert_near_equal\n", + "\n", + "from aviary.utils.doctape import glue_variable\n", + "from aviary.variable_info.variable_meta_data import Mission\n", + "\n", + "obj_fuel = prob.get_val(Mission.Objectives.FUEL)\n", + "exp_fuel = 5.27313333\n", + "assert_near_equal(obj_fuel[0], exp_fuel, 1e-5)\n", + "glue_variable('str_obj_fuel', str(obj_fuel), md_code=True)" ] }, { @@ -177,13 +291,13 @@ "id": "96066213", "metadata": {}, "source": [ - "In this code, you do the same import as `methods_for_level1.py` does and set the values of all the arguments in `run_aviary()`. Now we will go through each line in detail to explain each step:\n", + "In this code, you do the same import as {glue:md}`methods_for_level1.py` does and set the values of all the arguments in {glue:md}`run_aviary()`. Now we will go through each line in detail to explain each step:\n", "\n", "## Dissection of level 2 for the same `aircraft_for_bench_GwGm` model\n", "\n", - "All the methods of `prob` object (including its creation) are defined in level 3 (`methods_for_level2.py`). We now look at each of them.\n", + "All the methods of `prob` object (including its creation) are defined in level 2 ({glue:md}`methods_for_level2.py`). We now look at each of them.\n", "\n", - "We add other inputs that `run_aviary()` requires:" + "We add other inputs that {glue:md}`run_aviary()` requires:" ] }, { @@ -193,15 +307,50 @@ "metadata": {}, "outputs": [], "source": [ - "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_GwGm.csv\"\n", - "optimizer = \"IPOPT\"\n", - "analysis_scheme = av.AnalysisScheme.COLLOCATION\n", + "aircraft_data = 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv'\n", + "optimizer = 'IPOPT'\n", "objective_type = None\n", - "record_filename = 'aviary_history.db'\n", "restart_filename = None\n", "max_iter = 1\n", "\n", - "prob = av.AviaryProblem(analysis_scheme)" + "prob = av.AviaryProblem()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93651343", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "import aviary.api as av\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import get_attribute_name, glue_variable\n", + "\n", + "# read source code of __init__() starting from line 'self.model = AviaryGroup()'\n", + "source_code = inspect.getsource(AviaryProblem.__init__)\n", + "src_init = '```\\n'\n", + "new_line = ''\n", + "start_reading = False\n", + "for ch in source_code:\n", + " if ch == '\\n':\n", + " new_line = new_line.strip()\n", + " if 'AviaryGroup()' in new_line:\n", + " start_reading = True\n", + " if start_reading:\n", + " src_init += new_line + '\\n'\n", + " new_line = ''\n", + " else:\n", + " new_line += ch\n", + "\n", + "glue_variable('src_init', src_init, md_code=False)" ] }, { @@ -211,25 +360,11 @@ "source": [ "Several objects are initialized in this step:\n", "\n", + "```{glue:md} src_init\n", + ":format: myst\n", "```\n", - "self.model = om.Group()\n", - "self.pre_mission = PreMissionGroup()\n", - "self.post_mission = PostMissionGroup()\n", - "self.aviary_inputs = None\n", - "self.phase_info = phase_info\n", - "self.traj = None\n", - "self.analysis_scheme = analysis_scheme\n", - "self.pre_mission_info = self.phase_info.pop('pre_mission')\n", - "self.post_mission_info = self.phase_info.pop('post_mission')\n", - "```\n", - "\n", - "`phase_info` is a user defined dictionary (in a Python file) that controls the profile of the mission to be simulated (e.g. climb, cruise, descent segments etc).\n", - "\n", - "For `analysis_scheme`, the two options are: `AnalysisScheme.COLLOCATION` (default) and `AnalysisScheme.SHOOTING` which are defined and described in [variables_info/enums.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/variable_info/enums.py):\n", - "- COLLOCATION uses the collocation method to optimize all points simultaneously.\n", - "- SHOOTING is a forward in time integration method that simulates the trajectory.\n", "\n", - "In this onboarding document, only the `COLLOCATION` scheme will be discussed. The line" + "{glue:md}`phase_info` is a user defined dictionary (in a Python file) that controls the profile of the mission to be simulated (e.g. climb, cruise, descent segments etc). The line" ] }, { @@ -244,9 +379,26 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.api import AnalysisScheme\n", - "AnalysisScheme.COLLOCATION;\n", - "AnalysisScheme.SHOOTING;" + "from aviary.utils.doctape import check_value, glue_variable\n", + "\n", + "from aviary.utils.functions import get_model\n", + "\n", + "filename = 'aircraft_for_bench_GwGm.csv'\n", + "turbofan_file = 'models/engines/turbofan_23k_1.csv'\n", + "data_var_name = 'aircraft:engine:data_file' # read its value from .csv file\n", + "# glue_variable(data_var_name, md_code=True)\n", + "with open(get_model(filename)) as f_in:\n", + " lines = f_in.readlines()\n", + " for sLine in lines:\n", + " if data_var_name in sLine:\n", + " check_value(sLine.strip(), 'aircraft:engine:data_file,' + turbofan_file + ',unitless')\n", + " s = '```\\n'\n", + " s += sLine.strip()\n", + " glue_variable(turbofan_file, md_code=True)\n", + " glue_variable('engine_data_file_line', s, md_code=False)\n", + " val_and_units = s.split(',', 1)[-1]\n", + " glue_variable('models/engines/turbofan_28k.csv,unitless', val_and_units, md_code=False)\n", + " break" ] }, { @@ -257,7 +409,8 @@ "outputs": [], "source": [ "phase_info = deepcopy(av.default_2DOF_phase_info)\n", - "prob.load_inputs(aircraft_filename, phase_info)" + "prob.load_inputs(aircraft_data, phase_info)\n", + "prob.check_and_preprocess_inputs()" ] }, { @@ -267,17 +420,18 @@ "source": [ "is a function that has a few tasks:\n", "\n", - "- Read aircraft deck file `aircraft_filename`\n", - "- Read phase info file `phase_info`\n", + "- Read aircraft deck file `aircraft_data`\n", + "- Read phase info file {glue:md}`phase_info`\n", "- Build core subsystems\n", + "- Check and preprocess all inputs\n", "\n", - "We have seen `aircraft_filename` file (a `.csv` file) in our level 1 examples. In [level 1](onboarding_level1), we simply called it input file. An aircraft model can also be directly defined in Python, by setting up an `AviaryValues` object with the desired inputs and options normally found in an input file. That object can be provided in the place of `aircraft_filename`.\n", + "We have seen {glue:md}`aircraft_data` file (a `.csv` file) in our level 1 examples. In [level 1](onboarding_level1), we simply called it input file. An aircraft model can also be directly defined in Python, by setting up an {glue:md}`AviaryValues` object with the desired inputs and options normally found in an input file. That object can be provided in the place of {glue:md}`aircraft_data`.\n", "\n", "\n", - "Engines are built by using `aircraft:engine:data_file` in the .csv file. For example in `aircraft_for_bench_GwGm.csv` file, we see:\n", + "Engines are built by using the input data {glue:md}`engine_data_file` in the .csv file. For example in {glue:md}`aircraft_for_bench_GwGm.csv` file, we see:\n", "\n", - "```\n", - "aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless\n", + "```{glue:md} engine_data_file_line\n", + ":format: myst\n", "```" ] }, @@ -293,8 +447,20 @@ "outputs": [], "source": [ "# Testing Cell\n", + "import pandas as pd\n", + "from myst_nb import glue\n", + "\n", "from aviary.api import Aircraft\n", - "Aircraft.Engine.DATA_FILE;" + "from aviary.subsystems.propulsion.engine_model import EngineModel\n", + "from aviary.utils.functions import get_path\n", + "\n", + "glue_variable('engine_data_file', Aircraft.Engine.DATA_FILE)\n", + "glue_variable(EngineModel.__name__, md_code=True)\n", + "\n", + "# build the top rows of turbofan_28k.csv from that file\n", + "file_path = get_path('models/engines/turbofan_28k.csv')\n", + "df = pd.read_csv(file_path, nrows=5, skiprows=2, header=0)\n", + "glue('top_rows_of_engine_deck', df)" ] }, { @@ -302,21 +468,17 @@ "id": "5f349611", "metadata": {}, "source": [ - "So, `aircraft:engine:data_file` has value `models/engines/turbofan_28k.deck,unitless`. The top rows of engine deck file are:\n", + "So, {glue:md}`engine_data_file` has value {glue:md}`models/engines/turbofan_28k.csv,unitless`. We follow this path and open that file. The top rows of engine deck file are:\n", "\n", - "| **Mach_Number (unitless)** | **Altitude (ft)** | **Throttle (unitless)** | **Gross_Thrust (lbf)** | **Ram_Drag (lbf)** | **Fuel_Flow (lb/h)** | **NOx_Rate (lb/h)** |\n", - "| ---------------------- | -------------- | -------------------- | ------------------- | --------------- | --- | --- |\n", - "| 0.0, | 0.0, | 50.0, | 28928.1, | 0.0, | 8662.3, | 61.9894 |\n", - "| 0.0, | 0.0, | 48.0, | 26999.7, | 0.0, | 7932.6, | 49.2185 |\n", - "| 0.0, | 0.0, | 46.0, | 25071.1, | 0.0, | 7258.1, | 33.3976 |\n", - "| 0.0, | 0.0, | 42.0, | 21214.0, | 0.0, | 5979.1, | 19.8547 |\n", - "| 0.0, | 0.0, | 38.0, | 17356.9, | 0.0, | 4795.2, | 17.5877 |\n", + "```{glue:figure} top_rows_of_engine_deck\n", + ":name: 'tbl:df'\n", + "```\n", "\n", - "Users can provide an `EngineModel` instance of their own to use in Aviary's propulsion systems by adding it to `engine_models`.\n", + "Users can provide an {glue:md}`EngineModel` instance of their own to use in Aviary's propulsion systems.\n", "\n", "Other subsystems, including mass, geometry, and aerodynamics, are set up according to which legacy code options the user has specified in their input file, using `settings:equations_of_motion` and `settings:mass_method`. Aerodynamics is set up to match the selected equations of motion, while geometry will use either GASP, FLOPS, or both methods as required to calculate all values needed by other subsystems.\n", "\n", - "Next we check the user-provided inputs:" + "Next we check the user-provided inputs. The {glue:md}`prob.check_and_preprocess_inputs` method checks the user-supplied input values for any potential problems. These problems include variable names that are not recognized in Aviary, conflicting options or values, or units mismatching. You only want to check and pre-process your inputs once so after loading your inputs, make sure to update anything you need to before you check the values. " ] }, { @@ -332,18 +494,9 @@ "source": [ "# Testing Cell\n", "from aviary.api import Settings\n", - "Settings.EQUATIONS_OF_MOTION;\n", - "Settings.MASS_METHOD;" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e3d91612", - "metadata": {}, - "outputs": [], - "source": [ - "prob.check_and_preprocess_inputs()" + "\n", + "Settings.EQUATIONS_OF_MOTION\n", + "Settings.MASS_METHOD" ] }, { @@ -351,37 +504,27 @@ "id": "7f312145", "metadata": {}, "source": [ - "This method checks the user-supplied input values for any potential problems. These problems include variable names that are not recognized in Aviary, conflicting options or values, or units mismatching.\n", + "Next, we use {glue:md}`build_model` to build the model which includes: adding pre-mission systems including propulsion, geometry, aerodynamics, and mass subsystems. Then a sequence of core mission phases is added. In addition, if `mission_method` is {glue:md}`2DOF` and `ascent` is a phase, it adds an equality constraint to the problem to ensure that the velocity at the end of the groundroll phase is equal to the rotation velocity at the start of the rotation phase ({glue:md}`_add_groundroll_eq_constraint()`). If `mission_method` is {glue:md}`height_energy`, it sets up trajectory parameters by calling `setup_trajectory_params()`. If `mission_method` is {glue:md}`solved_2DOF`, it has a block of code to make sure that the trajectory is smooth by applying boundary constraints between phases (e.g. fuselage pitch angle or true airspeed).\n", "\n", - "Next, we add pre-mission systems:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "00de09c8", - "metadata": {}, - "outputs": [], - "source": [ - "prob.add_pre_mission_systems()" - ] - }, - { - "cell_type": "markdown", - "id": "12d71c79", - "metadata": {}, - "source": [ - "This call adds a pre-mission group which includes propulsion, geometry, aerodynamics, and mass subsystems. \n", + "For {glue:md}`height_energy` missions, aviary currently models FLOPS' \"simplified\" takeoff as defined in [mission/flops_based/phases/simplified_takeoff.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_takeoff.py).\n", + "\n", + "It follows by adding post-mission subsystems which includes landing phase if `include_landing` key of `post_mission` has value of `True`. If the user chooses to define a `post_mission`, it will override the default. For {glue:md}`2DOF` missions, landing is defined in [mission/gasp_based/ode/landing_ode.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/gasp_based/ode/landing_ode.py).\n", "\n", - "For `height_energy` missions, aviary currently models FLOPS' \"simplified\" takeoff as defined in [mission/flops_based/phases/simplified_takeoff.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_takeoff.py).\n", + "Following this, the phases are linked together. This is important for allowing each phase of flight to pass to the next without discontinuities in the parameters. Consider Dymos' [Aircraft Balanced Field Length Calculation](https://openmdao.github.io/dymos/examples/balanced_field/balanced_field.html) example. In that example, we see separate nonlinear boundary constraints, nonlinear path constraints, and phase continuity constraints between phases. We don't want to go deeper in this function call, but just point out that each individual link can be set via dymos function {glue:md}`link_phases()`. See [dymos API](https://openmdao.github.io/dymos/api/trajectory_api.html) for more details. The links are set up based on physical principals (e.g. you can’t have instantaneous changes in mass, velocity, position etc.). Special care is required if the user selects a different or unusual set of phases. \n", "\n", - "Next is the line" + "```{note}\n", + "{glue:md}`prob.build_model` can be broken out into four separate commands if finer control to each step is desired. These commands should be executed in order and are:\n", + "{glue:md}`prob.add_pre_mission_systems`\n", + "{glue:md}`prob.add_phases`\n", + "{glue:md}`prob.add_post_mission_systems`\n", + "{glue:md}`prob.link_phases`\n", + "```" ] }, { "cell_type": "code", "execution_count": null, - "id": "b17b6637", + "id": "00de09c8", "metadata": { "tags": [ "hide-output" @@ -389,71 +532,48 @@ }, "outputs": [], "source": [ - "prob.add_phases()" + "prob.build_model()" ] }, { "cell_type": "markdown", - "id": "f9f50477", + "id": "0f5006a5", "metadata": {}, "source": [ - "which adds a sequence of core mission phases. In addition, if `mission_method` is `2dof` and `ascent` is a phase, it adds an equality constraint to the problem to ensure that the TAS at the end of the groundroll phase is equal to the rotation velocity at the start of the rotation phase (`_add_groundroll_eq_constraint(phase)`). If `mission_method` is `height_energy`, it sets up trajectory parameters by calling `setup_trajectory_params()`. If `mission_method` is `solved`, it has a block of code to make sure that the trajectory is smooth by applying boundary constraints between phases (e.g. fuselage pitch angle or true airspeed).\n", + "Now, our aircraft and the mission are fully defined. We are ready to define an optimization problem. This is achieved by adding an optimization driver, adding design variables, and an objective. \n", "\n", - "It follows by adding post-mission subsystems:" + "For {glue:md}`add_driver()` function, we accept its argument `use_coloring=None`. Coloring is a technique that OpenMDAO uses to compute partial derivatives efficiently. This will become important later." ] }, { "cell_type": "code", "execution_count": null, - "id": "af5ba774", - "metadata": {}, + "id": "87e863bc", + "metadata": { + "tags": [ + "hide-output" + ] + }, "outputs": [], "source": [ - "prob.add_post_mission_systems()" - ] - }, - { - "cell_type": "markdown", - "id": "0c8038df", - "metadata": {}, - "source": [ - "Similar to pre-mission, it adds a landing phase if `include_landing` key of `post_mission` has value of `True`. If user chooses to define a `post_mission`, it will override the default. For `2dof` missions, landing is defined in [mission/gasp_based/ode/landing_ode.py](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/gasp_based/ode/landing_ode.py). For `simple` mission, landing means a [simplified landing](https://github.com/OpenMDAO/Aviary/blob/main/aviary/mission/flops_based/phases/simplified_landing.py). Note that the `solved` method currently doesn't have any post mission systems.\n", - "\n", - "The next line is" + "prob.add_driver(optimizer, max_iter=max_iter)" ] }, { "cell_type": "code", "execution_count": null, - "id": "f765815b", - "metadata": {}, + "id": "b16a1c86", + "metadata": { + "tags": [ + "remove-cell" + ] + }, "outputs": [], "source": [ - "prob.link_phases()" - ] - }, - { - "cell_type": "markdown", - "id": "0f5006a5", - "metadata": {}, - "source": [ - "This is important for allowing each phase of flight to pass to the next without discontinuities in the parameters. Consider Dymos' [Aircraft Balanced Field Length Calculation](https://openmdao.github.io/dymos/examples/balanced_field/balanced_field.html) example. In that example, we see separate nonlinear boundary constraints, nonlinear path constraints, and phase continuity constraints between phases. We don't want to go deeper in this function call, but just point out that each individual link can be set via dymos function `link_phases`. See [dymos API](https://openmdao.github.io/dymos/api/trajectory_api.html) for more details.\n", - "\n", - "The code blocks in this function (namely, `link_phases()`) are for `2DOF`, `simple`, and `solved` missions. The links are set up based on physical principals (e.g. you can’t have instantaneous changes in mass, velocity, position etc.). Special care is required if the user selects a different or unusual set of phases. \n", - "\n", - "Now, our aircraft and the mission are fully defined. We are ready to define an optimization problem. This is achieved by adding an optimization driver, adding design variables, and an objective. \n", + "# Testing Cell\n", + "from aviary.utils.doctape import glue_actions\n", "\n", - "For `add_driver` function, we accept `use_coloring=None`. Coloring is a technique that OpenMDAO uses to compute partial derivatives efficiently. This will become important later." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "87e863bc", - "metadata": {}, - "outputs": [], - "source": [ - "prob.add_driver(optimizer, max_iter=max_iter)" + "glue_actions('run_mission', current_glued_vars, glue_default=True, glue_choices=True)" ] }, { @@ -461,24 +581,28 @@ "id": "1cd6d86a", "metadata": {}, "source": [ - "Drivers available for use in Aviary are `SLSQP`, `SNOPT`, and `IPOPT`. The table below summarizes the basic setting along with sample values (the settings are options required by each optimizer):\n", + "Available drivers for use in Aviary are {glue:md}`SLSQP`, {glue:md}`SNOPT`, and {glue:md}`IPOPT`. The table below summarizes the basic setting along with sample values (the settings are options required by each optimizer):\n", "\n", "| **Optimizers** | **Drivers** | **Settings** |\n", "| ---------- | ------- | -------- |\n", - "| `SNOPT` | om.pyOptSparseDriver() | `Major iterations limit`: 50
`Major optimality tolerance`: 1e-4
`Major feasibility tolerance`: 1e-6
`iSumm`: 6 |\n", - "| `IPOPT` | om.pyOptSparseDriver() | `tol`: 1e-9
`mu_init`: 1e-5
`max_iter`: 50
`print_level`: 5 |\n", - "| `SLSQP` | om.ScipyOptimizeDriver() | `tol`: 1.0E-9
`maxiter`: 50
`disp`: True |\n", + "| {glue:md}`SNOPT` | om.pyOptSparseDriver() | `Major iterations limit`: 50
`Major optimality tolerance`: 1e-4
`Major feasibility tolerance`: 1e-6
`iSumm`: 6 |\n", + "| {glue:md}`IPOPT` | om.pyOptSparseDriver() | `tol`: 1e-9
`mu_init`: 1e-5
`max_iter`: 50
`print_level`: 5 |\n", + "| {glue:md}`SLSQP` | om.ScipyOptimizeDriver() | `tol`: 1.0E-9
`maxiter`: 50
`disp`: True |\n", "\n", - "Note that `SLSQP` is freely available, but its performance is not as good as `SNOPT` and `IPOPT` sometimes. `SNOPT` is a commercial optimizer, but it is free for academic use. `IPOPT` is an open-source optimizer and it is free for all users.\n", + "Note that {glue:md}`SLSQP` is freely available, but its performance is not as good as {glue:md}`SNOPT` and {glue:md}`IPOPT` sometimes. {glue:md}`SNOPT` is a commercial optimizer, and it is free for academic use. {glue:md}`IPOPT` is an open-source optimizer and it is free for all users.\n", "\n", - "Design variables (and constraints) are set in the line `prob.add_design_variables()`:" + "Design variables (and constraints) are set in the line {glue:md}`prob.add_design_variables()`:" ] }, { "cell_type": "code", "execution_count": null, "id": "0a408e2e", - "metadata": {}, + "metadata": { + "tags": [ + "hide-output" + ] + }, "outputs": [], "source": [ "prob.add_design_variables()" @@ -496,13 +620,14 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.variable_info.enums import ProblemType as PT, EquationsOfMotion as EOM\n", - "\n", - "EOM.HEIGHT_ENERGY;\n", - "EOM.TWO_DEGREES_OF_FREEDOM;\n", - "PT.SIZING;\n", - "PT.ALTERNATE;\n", - "PT.FALLOUT;" + "from aviary.variable_info.enums import EquationsOfMotion as EOM\n", + "from aviary.variable_info.enums import ProblemType as PT\n", + "\n", + "EOM.HEIGHT_ENERGY\n", + "EOM.TWO_DEGREES_OF_FREEDOM\n", + "PT.SIZING\n", + "PT.ALTERNATE\n", + "PT.FALLOUT" ] }, { @@ -510,22 +635,24 @@ "id": "5dfe75ac", "metadata": {}, "source": [ - "For default `HEIGHT_ENERGY` mission model, it is relatively simple:\n", + "The details of the design variables and constraints are in the source code of {glue:md}`add_design_variables()`. Let us summarize the data below:\n", + "\n", + "For default {glue:md}`height_energy` mission model, it is relatively simple:\n", "\n", "| **Design Variables** | **Lower Bound** | **Upper Bound** | **Reference Value** | **Units** |\n", "| ----------- | ----------- | ----------- | --------------- | ----- |\n", - "| Mission.Design.GROSS_MASS | 100.e3 | 200.e3 | 135.e3 | lbm |\n", + "| Mission.Design.GROSS_MASS | 10 | 900.e3| 175.e3 | lbm |\n", "\n", - "For default `TWO_DEGREES_OF_FREEDOM` mission model, the design variables and constraints depend on the type of problems (`SIZING`, `ALTERNATE`, or `FALLOUT`, see `ProblemType` class in `aviary/variable_info/enums.py` for details). First, there are four common design variables and two common constraints. There are two more design variables and two constraints for sizing problem.\n", + "For default {glue:md}`2DOF` mission model, the design variables and constraints depend on the type of problems ({glue:md}`SIZING`, {glue:md}`ALTERNATE`, or {glue:md}`FALLOUT`, see {glue:md}`ProblemType` class in `aviary/variable_info/enums.py` for details). First, there are four common design variables and two common constraints. There are two more design variables and two constraints for sizing problems.\n", "\n", - "| **Problem Type** | **Design Variables** | **Lower Bound** | **Upper Bound** | **Reference** Value | Units |\n", + "| **Problem Type** | **Design Variables** | **Lower Bound** | **Upper Bound** | **Reference Value** | **Units** |\n", "| ----------- | ----------- | ----------- | ----------- | --------------- | ----- |\n", "| Any | Mission.Takeoff.ASCENT_T_INITIAL | 0 | 100 | 30.0 | s |\n", "| Any | Mission.Takeoff.ASCENT_DURATION | 1 | 1000 | 10.0 | s |\n", "| Any | tau_gear | 0.01 | 1.0 | 1 | s |\n", "| Any | tau_flaps | 0.01 | 1.0 | 1 | s |\n", - "| SIZING | Mission.Design.GROSS_MASS | 10. | 400.e3 | 175_000 | lbm |\n", - "| SIZING | Mission.Summary.GROSS_MASS | 10. | 400.e3 | 175_000 | lbm |\n", + "| SIZING | Mission.Design.GROSS_MASS | 10. | None | 175_000 | lbm |\n", + "| SIZING | Mission.Summary.GROSS_MASS | 10. | None | 175_000 | lbm |\n", "| ALTERNATE | Mission.Summary.GROSS_MASS | 0 | infinite | 175_000 | lbm |\n", "| **Problem Type** | **Constraint** | **Relation** | **Value** | **Reference Value** | **Units** |\n", "| Any | h_fit.h_init_gear | = | 50.0 | 50.0 | ft |\n", @@ -533,7 +660,7 @@ "| SIZING | Mission.Constraints.RANGE_RESIDUAL | = | 0 | 10 | unitless |\n", "| ALTERNATE | Mission.Constraints.RANGE_RESIDUAL | = | 0 | 10 | lbm |\n", "\n", - "In the above table, there are two hard-coded design variables: `tau_gear` and `tau_flaps`. They represent fractions of ascent time to start gear retraction and flaps retraction. There are two hard-coded constraints: `h_fit.h_init_gear` and `h_fit.h_init_flaps`. They are the altitudes of initial gear retraction and initial flaps retraction. The underscore in number \"175_000\" is for readability only. \n", + "In the above table, there are two hard-coded design variables: `tau_gear` and `tau_flaps`. They represent fractions of ascent time to start gear retraction and flaps retraction. There are two hard-coded constraints: `h_fit.h_init_gear` and `h_fit.h_init_flaps`. They are the altitudes of initial gear retraction and initial flaps retraction. The underscore in number '175_000' is for readability only. \n", "\n", "There are other constraints using OpenMDAO's `EQConstraintComp` component. We will not go into the details as this part is complicated and needs special attention. Note that each subsystem (for example engine model) might have their own design variables (think, for example, sizing the engine). Aviary goes through all subsystems and adds appropriate design variables.\n", "\n", @@ -554,63 +681,32 @@ "outputs": [], "source": [ "# Testing Cell\n", - "import openmdao.api as om\n", - "import aviary.api as av\n", - "from aviary.validation_cases.validation_tests import get_flops_inputs\n", - "from aviary.models.large_single_aisle_1.V3_bug_fixed_IO import V3_bug_fixed_options\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.models.missions.two_dof_default import phase_info\n", + "\n", + "prob = AviaryProblem()\n", + "from aviary.models.aircraft.large_single_aisle_1.V3_bug_fixed_IO import V3_bug_fixed_options\n", "from aviary.utils.doctape import check_contains\n", + "from aviary.validation_cases.validation_tests import get_flops_inputs\n", "\n", - "av.EquationsOfMotion.HEIGHT_ENERGY; #check that HEIGHT_ENERGY exists\n", + "prob.load_inputs('models/test_aircraft/aircraft_for_bench_GwGm.csv', phase_info, verbosity=1)\n", "\n", - "# Setting up expected design variables and constraints based on problem type\n", - "common_des_vars = ['tau_gear', 'tau_flaps']\n", - "common_constraints = ['h_fit.h_init_gear', 'h_fit.h_init_flaps']\n", - "expected_vars = {\n", - " av.ProblemType.SIZING: {'des': common_des_vars, 'cons': common_constraints},\n", - " av.ProblemType.ALTERNATE: {'des': common_des_vars, 'cons': common_constraints},\n", - " av.ProblemType.FALLOUT: {'des': common_des_vars, 'cons': common_constraints}\n", - "}\n", + "prob.check_and_preprocess_inputs()\n", + "\n", + "prob.build_model()\n", "\n", - "# Combine FLOPS and GASP inputs, prioritizing the GASP values\n", - "input_options = get_flops_inputs('LargeSingleAisle1FLOPS')\n", - "input_options.update(V3_bug_fixed_options)\n", - "\n", - "# Creating the core subsystems - required for AviaryProblem._get_all_subsystems()\n", - "aero = av.CoreAerodynamicsBuilder('core_aerodynamics', code_origin=av.LegacyCode.GASP)\n", - "prop = av.CorePropulsionBuilder('core_propulsion',engine_models=av.build_engine_deck(input_options))\n", - "\n", - "# Creating a dummy problem that contains the minimal set of information that is required to call add_design_variables() and setup()\n", - "class dprob(om.Problem):\n", - " def __init__(self, problem_type):\n", - " super().__init__()\n", - " self.problem_type = problem_type\n", - " self.pre_mission_info = {'external_subsystems': []}\n", - " self.core_subsystems = {'propulsion': prop, 'aerodynamics': aero}\n", - " self.mission_method = av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM\n", - " self.analysis_scheme = av.AnalysisScheme.COLLOCATION\n", - " self.require_range_residual = True\n", - " self.model = om.Group()\n", - "\n", - " # self._get_all_subsystems() is called as part of AviaryProblem.add_design_variables()\n", - " _get_all_subsystems = av.AviaryProblem._get_all_subsystems\n", - "\n", - "# for each problem type\n", - "for ptype, vars in expected_vars.items():\n", - " dummy_prob = dprob(ptype)\n", - " # we create the problem and let aviary add the design variables\n", - " av.AviaryProblem.add_design_variables(dummy_prob)\n", - " dummy_prob.setup()\n", - " # then we check that all of the expected design variables are in the model\n", - " check_contains(vars['des'], dummy_prob.model._design_vars.keys())\n", - " # and we check that all of the expected constraints are in the model\n", - " check_contains(vars['cons'], dummy_prob.model._responses.keys())" + "prob.add_design_variables()" ] }, { "cell_type": "code", "execution_count": null, "id": "46eee283", - "metadata": {}, + "metadata": { + "tags": [ + "hide-output" + ] + }, "outputs": [], "source": [ "prob.add_objective(objective_type=objective_type)" @@ -623,71 +719,20 @@ "source": [ "The selection of objective is a little complicated. \n", "\n", - "Earlier in this page, we have discussed the objective when `objective_type=None` and `mission_method` is `2DOF`. Let us discuss the other situations.\n", + "Earlier in this page, we have discussed the objective when `objective_type=None` and `mission_method` is {glue:md}`2DOF`. Let us discuss the other situations.\n", "\n", "There are several objective types that users can choose: `mass`, `hybrid_objective`, `fuel_burned`, and `fuel`. \n", "\n", "| objective_type | objective |\n", "| -------------- | --------- |\n", - "| mass | `Dynamic.Mission.MASS` |\n", + "| mass | {glue:md}`Dynamic.Vehicle.MASS` |\n", "| hybrid_objective | `-final_mass / {takeoff_mass} + final_time / 5.` |\n", - "| fuel_burned | `initial_mass - mass_final` (for `FLOPS` mission only)|\n", - "| fuel | `Mission.Objectives.FUEL` |\n", - "\n", - "As listed in the above, if `objective_type=\"mass\"`, the objective is the final value of `Dynamic.Mission.MASS` at the end of the mission.\n", - "If `objective_type=\"fuel\"`, the objective is the `Mission.Objectives.FUEL`.\n", - "There is a special objective type: `hybrid_objective`. When `objective_type=\"hybrid_objective\"`, the objective is a mix of minimizing fuel burn and minimizing the mission duration:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b4df9df0", - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "import openmdao.api as om\n", - "from aviary.api import Mission, Dynamic\n", - "from aviary.variable_info.enums import EquationsOfMotion as EOM, AnalysisScheme as AS\n", - "from aviary.interface.methods_for_level2 import AviaryProblem\n", - "from aviary.utils.aviary_values import AviaryValues\n", - "from aviary.utils.doctape import check_contains\n", + "| fuel_burned | `initial_mass - mass_final` (for `height_energy` mission only)|\n", + "| fuel | {glue:md}`Mission.Objectives.FUEL` |\n", "\n", - "mo = Mission.Objectives\n", - "dm = Dynamic.Mission\n", - "expected_objective = {'mass':dm.MASS, 'hybrid_objective':'obj_comp.obj',\n", - " 'fuel_burned':Mission.Summary.FUEL_BURNED, 'fuel':mo.FUEL}\n", - "\n", - "class dprob(om.Problem):\n", - " def __init__(self):\n", - " super().__init__()\n", - " self.phase_info = {'final_phase':1}\n", - " self.regular_phases = ['final_phase']\n", - " self.mission_method = EOM.TWO_DEGREES_OF_FREEDOM\n", - " self.analysis_scheme = AS.COLLOCATION\n", - " self.aviary_inputs = AviaryValues({Mission.Design.GROSS_MASS:(1, 'lbm')})\n", - " self.model = om.Group()\n", - " # add variables used in hybrid objective connections\n", - " group = self.model\n", - " for name in ('traj','final_phase','timeseries'):\n", - " group = group.add_subsystem(name, om.Group())\n", - " var_names = [('mass',0,{'units':'lbm'}), ('time',0,{'units':'h'})]\n", - " group.add_subsystem('ivc',om.IndepVarComp(var_names),promotes=['*'])\n", - "\n", - " _add_hybrid_objective = AviaryProblem._add_hybrid_objective\n", - "\n", - "for otype, obj in expected_objective.items():\n", - " dummy_prob = dprob()\n", - " AviaryProblem.add_objective(dummy_prob, otype)\n", - " dummy_prob.setup()\n", - " # traj timeseries values are promoted to the top in the real problem\n", - " objectives = [key.split('.')[-1] if 'timeseries' in key else key for key in dummy_prob.model._responses]\n", - " check_contains(obj,objectives,\"{var} not in {actual_values}\"+f' for {otype}')\n" + "As listed in the above, if `objective_type=\"mass\"`, the objective is the final value of {glue:md}`Dynamic.Vehicle.MASS` at the end of the mission.\n", + "If `objective_type=\"fuel\"`, the objective is the {glue:md}`Mission.Objectives.FUEL`.\n", + "There is a special objective type: `hybrid_objective`. When `objective_type='hybrid_objective'`, the objective is a mix of minimizing fuel burn and minimizing the mission duration:" ] }, { @@ -698,18 +743,16 @@ "```\n", " obj = -final_mass / {takeoff_mass} + final_time / 5.\n", "```\n", - "This is because if we just minimized fuel burn then the optimizer would probably fly the plane slowly to save fuel, but we actually care about some mix of minimizing fuel burn while providing a reasonable travel time for the passengers. This leads to the `hybrid_objective` which seeks to minimize a combination of those two objectives. `final_time` is the duration of the full mission and is usually in the range of hours. So, the denominator `5.` means `5 hours`. That's just a value to scale the final_time variable. Since it's a composite objective we didn't want to have OpenMDAO do the scaling because the two variables in the objective are of a different order of magnitude. We will show an example of this objective type in level 2 discussion.\n", + "This is because if we just minimized fuel burn then the optimizer would probably fly the plane slowly to save fuel, but we actually care about some mix of minimizing fuel burn while providing a reasonable travel time for the passengers. This leads to the `hybrid_objective` which seeks to minimize a combination of those two objectives. `final_time` is the duration of the full mission and is usually in the range of hours. So, the denominator `5.` means `5 hours`. That's just a value to scale the final_time variable. Since it's a composite objective we didn't want to have OpenMDAO do the scaling because the two variables in the objective are of a different order of magnitude.\n", "\n", - "If `objective_type=None` for a `2DOF` mission, Aviary will choose the objective based on `mission_method` and `problem_type`. We have discussed this case earlier in this page.\n", + "If `objective_type=None` for a {glue:md}`2DOF` mission, Aviary will choose the objective based on `mission_method` and {glue:md}`problem_type`. We have discussed this case earlier in this page.\n", "\n", - "If `objective_type=None` for a `FLOPS` mission method, Aviary adds a `fuel_burned` objective. In fact, this objective is available for `FLOPS` mission only. That number you get is for the actual fuel burned in lbm. You may get something like `fuel_burned` with the scaled value `[3.91228276]`, reference value `1e+04`. It translates to the dimensional physical quantity of `39,122.8276` lbm. To see this in action, check the resulting `reports/opt_report.html` file to see the optimal results.\n", - "\n", - "**Note:** Aviary variable `Mission.Objectives.FUEL` when using the GASP-based mission is actually a hybrid objective defined as\n", + "**Note:** Aviary variable `Mission.Objectives.FUEL` when using the {glue:md}`2DOF` mission is actually a hybrid objective defined as\n", "\n", "```\n", " reg_objective = overall_fuel/10000 + ascent_duration/30.\n", "```\n", - "where `overall_fuel` has the unit of `lbm` and `ascent_duration` has the unit of seconds. In our case, `settings:equations_of_motion = 2DOF`, the final value of objective is `[5.5910123]`, with `ref: 1.0` and `units: blank`. The units should be interpreted as `unitless`.\n", + "where `overall_fuel` has the unit of `lbm` and `ascent_duration` has the unit of seconds. In our case, `settings:equations_of_motion = 2DOF`, the final value of objective is {glue:md}`str_obj_fuel`, with `ref: 1.0` and `units: blank`. The units should be interpreted as `unitless`.\n", "\n", "Here, `ref` is the reference value. For different objectives, the range may vary significantly different. We want to normalize the value. Ideally, users should choose `ref` such that the objective is in the range of `(0,1)`. This is required by optimizer.\n", "\n", @@ -722,7 +765,11 @@ "cell_type": "code", "execution_count": null, "id": "dbfca715", - "metadata": {}, + "metadata": { + "tags": [ + "hide-output" + ] + }, "outputs": [], "source": [ "prob.setup()" @@ -733,23 +780,13 @@ "id": "40b9cfea", "metadata": {}, "source": [ - "This is a lightly wrapped OpenMDAO `setup()` method for the problem. It allows us to do `pre-` and `post-setup` changes, like adding calls to `set_input_defaults` and do some simple `set_vals` if needed. \n", + "This is a lightly wrapped OpenMDAO {glue:md}`setup()` and {glue:md}`prob.set_initial_guesses` method for the problem. It allows us to do `pre-` and `post-setup` changes, like adding calls to `set_input_defaults` and do some simple `set_vals` if needed as well as setting initial guesses. \n", "\n", - "If we look at the signature of `setup()` in OpenMDAO's [Problem](https://openmdao.org/newdocs/versions/latest/_srcdocs/packages/core/problem.html) class, we find that the available kwargs are: `check`, `logger`, `mode`, `force_alloc_complex`, `distributed_vector_class`, `local_vector_class`, and `derivatives`. The ones that Aviary uses are `check` and `force_alloc_complex`. Argument `check` is a flag to determine default checks are performed. [Default checks](https://openmdao.org/newdocs/versions/latest/theory_manual/setup_stack.html) are: 'auto_ivc_warnings', comp_has_no_outputs', 'dup_inputs', 'missing_recorders', 'out_of_order', 'solvers', 'system', 'unserializable_options'.\n", + "If we look at the signature of {glue:md}`setup()` in OpenMDAO's [Problem](https://openmdao.org/newdocs/versions/latest/_srcdocs/packages/core/problem.html) class, we find that the available kwargs are: `check`, `logger`, `mode`, `force_alloc_complex`, `distributed_vector_class`, `local_vector_class`, and `derivatives`. The ones that Aviary uses are `check` and `force_alloc_complex`. Argument `check` is a flag to determine default checks are performed. [Default checks](https://openmdao.org/newdocs/versions/latest/theory_manual/setup_stack.html) are: 'auto_ivc_warnings', comp_has_no_outputs', 'dup_inputs', 'missing_recorders', 'out_of_order', 'solvers', 'system', 'unserializable_options'.\n", "\n", "If [force_alloc_complex](https://openmdao.org/newdocs/versions/latest/advanced_user_guide/complex_step.html) is true, sufficient memory will be allocated to allow nonlinear vectors to store complex values while operating under complex step. For our example, we don't use any of them.\n", "\n", - "For optimization problems, initial guesses are important." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "afdf6203", - "metadata": {}, - "outputs": [], - "source": [ - "prob.set_initial_guesses()" + "For optimization problems, initial guesses are important. {glue:md}`prob.setup` does setup initial guesses as well." ] }, { @@ -757,7 +794,7 @@ "id": "57986647", "metadata": {}, "source": [ - "For `solved_2DOF` and `2DOF` missions, this method performs several calls to `set_val` on the trajectory for states and controls to seed the problem with reasonable initial guesses using `initial_guesses` within corresponding phases (e.g. `default_flops_phases.py` and `default_gasp_phases.py`). For `solved_2DOF` missions, it performs similar tasks but for hard-coded state parameters. This is reasonable because a `solved_2DOF` mission is actually a level 3 Aviary approach. We will cover it in [level 3 onboarding doc](onboarding_level3) in the next page. Note that initial guesses for all phases are especially important for collocation methods.\n", + "For {glue:md}`solved_2DOF` and {glue:md}`2DOF` missions, the {glue:md}`prob.set_initial_guesses` method performs several calls to `set_val` on the trajectory for states and controls to seed the problem with reasonable initial guesses using `initial_guesses` within corresponding phases (e.g. `height_energy.py` and `two_dof.py`). For `solved_2DOF` missions, it performs similar tasks but for hard-coded state parameters. This is reasonable because a `solved_2DOF` mission is actually a level 3 Aviary approach. We will cover it in [level 3 onboarding doc](onboarding_level3) in the next page. Note that initial guesses for all phases are especially important for collocation methods.\n", "\n", "The last line is to run the problem we just set up:" ] @@ -765,26 +802,13 @@ { "cell_type": "code", "execution_count": null, - "id": "1fed2339", + "id": "2f1a2b82", "metadata": { "tags": [ - "remove-cell" + "hide-output" ] }, "outputs": [], - "source": [ - "# Testing Cell\n", - "import aviary.api as av\n", - "av.EquationsOfMotion.SOLVED_2DOF;\n", - "av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM;" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2f1a2b82", - "metadata": {}, - "outputs": [], "source": [ "prob.run_aviary_problem()" ] @@ -794,7 +818,7 @@ "id": "107f7407", "metadata": {}, "source": [ - "This is a simple wrapper of Dymos' [run_problem()](https://openmdao.github.io/dymos/api/run_problem_function.html) function. It allows the users to provide `record_filename`, `restart_filename`, `suppress_solver_print`, and `run_driver`. In our case, `record_filename` is changed to `aviary_history.db` and `restart_filename` is set to `None`. The rest of the arguments take default values. If a restart file name is provided, aviary (or dymos) will load the states, controls, and parameters as given in the provided case as the initial guess for the next run. We have discussed the `.db` file in [level 1 onboarding doc](onboarding_level1) and will discuss how to use it to generate useful output in [level 3 onboarding doc](onboarding_level3).\n", + "This is a simple wrapper of Dymos' [run_problem()](https://openmdao.github.io/dymos/api/run_problem_function.html) function. It allows the users to provide, `restart_filename`, `suppress_solver_print`, and `run_driver`. In our case, `restart_filename` is set to `None`. The rest of the arguments take default values. If a restart file name is provided, aviary (or dymos) will load the states, controls, and parameters as given in the provided case as the initial guess for the next run. We have discussed the `.db` file in [level 1 onboarding doc](onboarding_level1) and will discuss how to use it to generate useful output in [level 3 onboarding doc](onboarding_level3).\n", "\n", "Finally, we can add a few print statements for the variables that we are interested:\n" ] @@ -806,38 +830,38 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"Mission.Objectives.FUEL\",\n", - " prob.get_val(Mission.Objectives.FUEL, units='unitless'))\n", - "print(\"Mission.Design.FUEL_MASS\",\n", - " prob.get_val(Mission.Design.FUEL_MASS, units='lbm'))\n", - "print(\"Mission.Design.FUEL_MASS_REQUIRED\",\n", - " prob.get_val(Mission.Design.FUEL_MASS_REQUIRED, units='lbm'))\n", - "print(\"Mission.Summary.TOTAL_FUEL_MASS\",\n", - " prob.get_val(Mission.Summary.TOTAL_FUEL_MASS, units='lbm'))\n", - "print(\"Mission.Summary.GROSS_MASS (takeoff_mass)\",\n", - " prob.get_val(Mission.Summary.GROSS_MASS, units='lbm'))\n", - "print(\"Mission.Landing.TOUCHDOWN_MASS (final_mass)\",\n", - " prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'))\n", + "print('Mission.Objectives.FUEL', prob.get_val(Mission.Objectives.FUEL, units='unitless'))\n", + "print('Mission.Summary.FUEL_MASS', prob.get_val(Mission.Summary.FUEL_MASS, units='lbm'))\n", + "print(\n", + " 'Mission.Summary.FUEL_MASS_REQUIRED',\n", + " prob.get_val(Mission.Summary.FUEL_MASS_REQUIRED, units='lbm'),\n", + ")\n", + "print('Mission.Summary.TOTAL_FUEL_MASS', prob.get_val(Mission.Summary.TOTAL_FUEL_MASS, units='lbm'))\n", + "print(\n", + " 'Mission.Summary.GROSS_MASS (takeoff_mass)',\n", + " prob.get_val(Mission.Summary.GROSS_MASS, units='lbm'),\n", + ")\n", + "print(\n", + " 'Mission.Landing.TOUCHDOWN_MASS (final_mass)',\n", + " prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'),\n", + ")\n", "print()\n", "\n", - "print(\"Groundroll Final Mass (lbm)\",\n", - " prob.get_val('traj.phases.groundroll.states:mass', units='lbm')[-1])\n", - "print(\"Rotation Final Mass (lbm)\",\n", - " prob.get_val('traj.rotation.states:mass', units='lbm')[-1])\n", - "print(\"Ascent Final Mass (lbm)\",\n", - " prob.get_val('traj.ascent.states:mass', units='lbm')[-1])\n", - "print(\"Accel Final Mass (lbm)\",\n", - " prob.get_val('traj.accel.states:mass', units='lbm')[-1])\n", - "print(\"Climb1 Final Mass (lbm)\",\n", - " prob.get_val('traj.climb1.states:mass', units='lbm')[-1])\n", - "print(\"Climb2 Final Mass (lbm)\",\n", - " prob.get_val('traj.climb2.states:mass', units='lbm')[-1])\n", - "print(\"Cruise Final Mass (lbm)\",\n", - " prob.get_val('traj.phases.cruise.rhs.calc_weight.mass', units='lbm')[-1])\n", - "print(\"Desc1 Final Mass (lbm)\",\n", - " prob.get_val('traj.desc1.states:mass', units='lbm')[-1])\n", - "print(\"Desc2 Final Mass (lbm)\",\n", - " prob.get_val('traj.desc2.states:mass', units='lbm')[-1])\n", + "print(\n", + " 'Groundroll Final Mass (lbm)',\n", + " prob.get_val('traj.groundroll.states:mass', units='lbm')[-1],\n", + ")\n", + "print('Rotation Final Mass (lbm)', prob.get_val('traj.rotation.states:mass', units='lbm')[-1])\n", + "print('Ascent Final Mass (lbm)', prob.get_val('traj.ascent.states:mass', units='lbm')[-1])\n", + "print('Accel Final Mass (lbm)', prob.get_val('traj.accel.states:mass', units='lbm')[-1])\n", + "print('Climb1 Final Mass (lbm)', prob.get_val('traj.climb1.states:mass', units='lbm')[-1])\n", + "print('Climb2 Final Mass (lbm)', prob.get_val('traj.climb2.states:mass', units='lbm')[-1])\n", + "print(\n", + " 'Cruise Final Mass (lbm)',\n", + " prob.get_val('traj.phases.cruise.rhs.calc_weight.mass', units='lbm')[-1],\n", + ")\n", + "print('Desc1 Final Mass (lbm)', prob.get_val('traj.desc1.states:mass', units='lbm')[-1])\n", + "print('Desc2 Final Mass (lbm)', prob.get_val('traj.desc2.states:mass', units='lbm')[-1])\n", "print('done')" ] }, @@ -866,7 +890,7 @@ "metadata": {}, "outputs": [], "source": [ - "!aviary run_mission models/test_aircraft/aircraft_for_bench_FwFm.csv --max_iter 0 --optimizer IPOPT" + "!aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv --max_iter 0 --optimizer IPOPT" ] }, { @@ -876,7 +900,7 @@ "source": [ "Once again, to convert it to a level 2 model, we need to set all the arguments in level 1 manually.\n", "\n", - "By running a model in level 2 directly, we have the flexibility to modify the input parameters (e.g. `phase_info`). Let us continue to make modifications and obtain a different run script shown below:" + "By running a model in level 2 directly, we have the flexibility to modify the input parameters (e.g. {glue:md}`phase_info`). Let us continue to make modifications and obtain a different run script shown below:" ] }, { @@ -892,28 +916,23 @@ " 'optimize_mass': False,\n", " },\n", " 'cruise': {\n", - " 'subsystem_options': {\n", - " 'core_aerodynamics': {'method': 'computed'}\n", - " },\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", " 'user_options': {\n", - " 'optimize_mach': False,\n", - " 'optimize_altitude': False,\n", - " 'polynomial_control_order': 1,\n", " 'num_segments': 2,\n", " 'order': 3,\n", - " 'solve_for_distance': False,\n", - " 'initial_mach': (0.72, 'unitless'),\n", - " 'final_mach': (0.72, 'unitless'),\n", + " 'mach_optimize': False,\n", + " 'mach_polynomial_order': 1,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", - " 'initial_altitude': (35000.0, 'ft'),\n", - " 'final_altitude': (35000.0, 'ft'),\n", + " 'altitude_optimize': False,\n", + " 'altitude_polynomial_order': 1,\n", + " 'altitude_initial': (35000.0, 'ft'),\n", + " 'altitude_final': (35000.0, 'ft'),\n", " 'altitude_bounds': ((23000.0, 38000.0), 'ft'),\n", " 'throttle_enforcement': 'boundary_constraint',\n", - " 'fix_initial': True,\n", - " 'constrain_final': False,\n", - " 'fix_duration': False,\n", - " 'initial_bounds': ((0.0, 0.0), 'min'),\n", - " 'duration_bounds': ((10., 30.), 'min'),\n", + " 'time_initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'time_duration_bounds': ((10.0, 30.0), 'min'),\n", " },\n", " 'initial_guesses': {'time': ([0, 30], 'min')},\n", " },\n", @@ -923,33 +942,23 @@ "}\n", "\n", "# inputs that run_aviary() requires\n", - "aircraft_filename = \"models/test_aircraft/aircraft_for_bench_FwFm.csv\"\n", - "mission_method = \"height_energy_energy\"\n", - "mass_method = \"FLOPS\"\n", - "optimizer = \"SLSQP\"\n", - "analysis_scheme = av.AnalysisScheme.COLLOCATION\n", + "aircraft_data = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "mission_method = 'height_energy'\n", + "mass_method = 'FLOPS'\n", + "optimizer = 'SLSQP'\n", "objective_type = None\n", - "record_filename = 'history.db'\n", "restart_filename = None\n", "\n", "# Build problem\n", - "prob = av.AviaryProblem(analysis_scheme)\n", + "prob = av.AviaryProblem()\n", "\n", "# Load aircraft and options data from user\n", "# Allow for user overrides here\n", - "prob.load_inputs(aircraft_filename, phase_info)\n", + "prob.load_inputs(aircraft_data, phase_info)\n", "\n", - "# Preprocess inputs\n", "prob.check_and_preprocess_inputs()\n", "\n", - "prob.add_pre_mission_systems()\n", - "\n", - "prob.add_phases()\n", - "\n", - "prob.add_post_mission_systems()\n", - "\n", - "# Link phases and variables\n", - "prob.link_phases()\n", + "prob.build_model()\n", "\n", "prob.add_driver(optimizer, max_iter=0)\n", "\n", @@ -961,11 +970,9 @@ "\n", "prob.setup()\n", "\n", - "prob.set_initial_guesses()\n", - "\n", - "prob.run_aviary_problem(record_filename)\n", + "prob.run_aviary_problem()\n", "\n", - "print(\"done\")\n" + "print('done')" ] }, { @@ -978,7 +985,7 @@ "We will see more details for what users can do in [level 3](onboarding_level3).\n", "\n", "Level 2 is where you can integrate user-defined [external subsystems](../user_guide/subsystems), which is one of the main features of the Aviary tool. [Examples](../user_guide/using_external_subsystems) of external subsystems are: acoustics, battery modeling, etc.\n", - "Assume that you already have an external subsystem that you want to incorporate it into your model. We show how to add external subsystems via `external_subsystems` key in `phase_info`.\n", + "Assume that you already have an external subsystem that you want to incorporate it into your model. We show how to add external subsystems via `external_subsystems` key in {glue:md}`phase_info`.\n", "\n", "We will cover external subsystems in details in [Models with External Subsystems](onboarding_ext_subsystem) page.\n" ] @@ -991,11 +998,11 @@ "## Summary\n", "\n", "As you see, level 2 is more flexible than level 1. In level 2, you can:\n", - "- add/remove pre-defined mission phases (via `phase_info`, see example above);\n", - "- scale design variables (via reference value in `phase_info`)\n", - "- import additional files (e.g. `aero_data`);\n", - "- set pre-defined objective (e.g. `hybrid_objective`);\n", - "- add external subsystems (via `phase_info`);\n", + "- add/remove pre-defined mission phases (via {glue:md}`phase_info`, see example above);\n", + "- scale design variables (via reference value in {glue:md}`phase_info`)\n", + "- import additional files (e.g. `aero_data`)\n", + "- set pre-defined objective (e.g. `hybrid_objective`)\n", + "- add external subsystems (via {glue:md}`phase_info`)\n", "- set `use_coloring` (see example above).\n", "\n", "Most Aviary users should be well-served by Level 2; we have purposefully constructed it to be capable of most all use cases, even those on the forefront of research in aircraft design.\n", @@ -1006,7 +1013,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1020,7 +1027,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/onboarding_level3.ipynb b/aviary/docs/getting_started/onboarding_level3.ipynb index f235936b52..5513fd4825 100644 --- a/aviary/docs/getting_started/onboarding_level3.ipynb +++ b/aviary/docs/getting_started/onboarding_level3.ipynb @@ -13,9 +13,42 @@ "Level 3 enables users to have supreme control over every aspect of the model, including subsystems, connections, and advanced optimization techniques.\n", "\n", "Level 3 is the most complex but specific methods defined at this level are used in levels 1 and 2, hopefully reducing user activation energy when learning more about Aviary.\n", - "This progressive approach helps users gradually enhance their analysis capabilities and adapt to more complex modeling requirements as they gain proficiency and experience.\n", + "This progressive approach helps users gradually enhance their analysis capabilities and adapt to more complex modeling requirements as they gain proficiency and experience." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d94bb575", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import glue_class_functions, glue_variable\n", "\n", - "We will show two approaches of level 3 development using two examples: The first one will implement all methods differently from what are available in `aviary/interface/methods_for_level2.py` but will follow the same steps. It will show that you don't have to have a `.csv` input file and you don't have to have a `phase_info` dictionary. The second is a `solved` mission approach that is embedded into all the methods of `aviary/interface/methods_for_level2.py`.\n", + "current_glued_vars = []\n", + "\n", + "file_path = 'interface/methods_for_level2.py'\n", + "file_path = av.get_path(file_path).relative_to(av.top_dir.parent)\n", + "glue_variable(str(file_path), md_code=True)\n", + "glue_variable('solved_2DOF', av.EquationsOfMotion.SOLVED_2DOF.value, md_code=True)\n", + "\n", + "# Get all functions of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars)" + ] + }, + { + "cell_type": "markdown", + "id": "9a52d5e2", + "metadata": {}, + "source": [ + "We will show two approaches of level 3 development using two examples: The first one will implement all methods differently from what are available in {glue:md}`aviary/interface/methods_for_level2.py` but will follow the same steps. It will show that you don't have to have a `.csv` input file and you don't have to have a `phase_info` dictionary. The second is a {glue:md}`solved_2DOF` mission approach that is embedded into all the methods of {glue:md}`aviary/interface/methods_for_level2.py`.\n", "\n", "```{note}\n", "For each of these examples we have set `max_iter = 0`, which means that the optimization will not run. This is done to reduce the computational time for the examples. If you want to run the optimization, you can set `max_iter = 100` or some similar value.\n", @@ -32,19 +65,19 @@ "In [level 2](onboarding_level2), we have shown how to follow the standard steps to build an Aviary model, but sometimes you may find that the model you have in mind does not match that predefined structure. If you start a new model that cannot been embedded in those methods, we can write special methods ourselves. This example will show you how to do that.\n", "\n", "In `aviary/validation_cases/benchmark_tests` folder, there is an N3CC aircraft full mission benchmark test `test_FLOPS_based_sizing_N3CC.py`. Now, we will show how to create an N3CC example in level3. The key is that we follow the same steps:\n", - "- init\n", - "- load_inputs\n", - "- check_and_preprocess_inputs (optional)\n", - "- add_pre_mission_systems\n", - "- add_phases\n", - "- add_post_mission_systems\n", - "- link_phases\n", - "- add_driver\n", - "- add_design_variables (optional)\n", - "- add_objective\n", - "- setup\n", - "- set_initial_guesses\n", - "- run_aviary_problem" + "- {glue:md}`__init__()`\n", + "- {glue:md}`load_inputs()`\n", + "- {glue:md}`check_and_preprocess_inputs()`\n", + "- {glue:md}`build_model()`\n", + "- {glue:md}`add_pre_mission_systems()`\n", + "- {glue:md}`add_phases()`\n", + "- {glue:md}`add_post_mission_systems()`\n", + "- {glue:md}`link_phases()`\n", + "- {glue:md}`add_driver()`\n", + "- {glue:md}`add_design_variables()` (optional)\n", + "- {glue:md}`add_objective()`\n", + "- {glue:md}`setup()`\n", + "- {glue:md}`run_aviary_problem()`" ] }, { @@ -60,10 +93,12 @@ "source": [ "# Testing Cell\n", "import os\n", + "\n", "from aviary.utils.functions import get_path\n", + "\n", "folder = 'validation_cases/benchmark_tests'\n", "file = 'test_FLOPS_based_sizing_N3CC.py'\n", - "get_path(os.path.join(folder,file));\n" + "get_path(os.path.join(folder, file))" ] }, { @@ -81,13 +116,13 @@ "metadata": {}, "outputs": [], "source": [ - "'''\n", + "\"\"\"\n", "NOTES:\n", "Includes:\n", "Takeoff, Climb, Cruise, Descent, Landing\n", "Computed Aero\n", - "N3CC data\n", - "'''\n", + "advanced_single_aisle data\n", + "\"\"\"\n", "\n", "import dymos as dm\n", "import openmdao.api as om\n", @@ -95,92 +130,85 @@ "\n", "import aviary.api as av\n", "from aviary.validation_cases.validation_tests import get_flops_inputs\n", - "\n", + "from aviary.variable_info.functions import setup_model_options\n", "\n", "prob = om.Problem(model=om.Group())\n", "driver = prob.driver = om.pyOptSparseDriver()\n", - "driver.options[\"optimizer\"] = \"IPOPT\"\n", - "driver.opt_settings[\"max_iter\"] = 100\n", - "driver.opt_settings[\"tol\"] = 1e-3\n", + "driver.options['optimizer'] = 'IPOPT'\n", + "driver.opt_settings['max_iter'] = 100\n", + "driver.opt_settings['tol'] = 1e-3\n", "driver.opt_settings['print_level'] = 4\n", "\n", "########################################\n", "# Aircraft Input Variables and Options #\n", "########################################\n", "\n", - "aviary_inputs = get_flops_inputs('N3CC')\n", + "aviary_inputs = get_flops_inputs('AdvancedSingleAisle')\n", "\n", - "aviary_inputs.set_val(av.Mission.Landing.LIFT_COEFFICIENT_MAX,\n", - " 2.4, units=\"unitless\")\n", - "aviary_inputs.set_val(av.Mission.Takeoff.LIFT_COEFFICIENT_MAX,\n", - " 2.0, units=\"unitless\")\n", - "aviary_inputs.set_val(\n", - " av.Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT,\n", - " val=.0175, units=\"unitless\")\n", + "aviary_inputs.set_val(av.Mission.Landing.LIFT_COEFFICIENT_MAX, 2.4, units='unitless')\n", + "aviary_inputs.set_val(av.Mission.Takeoff.LIFT_COEFFICIENT_MAX, 2.0, units='unitless')\n", + "aviary_inputs.set_val(av.Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, val=0.0175, units='unitless')\n", "\n", "takeoff_fuel_burned = 577 # lbm\n", "takeoff_thrust_per_eng = 24555.5 # lbf\n", "takeoff_L_over_D = 17.35\n", "\n", - "aviary_inputs.set_val(av.Mission.Takeoff.FUEL_SIMPLE,\n", - " takeoff_fuel_burned, units='lbm')\n", - "aviary_inputs.set_val(av.Mission.Takeoff.LIFT_OVER_DRAG,\n", - " takeoff_L_over_D, units=\"unitless\")\n", - "aviary_inputs.set_val(av.Mission.Design.THRUST_TAKEOFF_PER_ENG,\n", - " takeoff_thrust_per_eng, units='lbf')\n", + "aviary_inputs.set_val(av.Mission.Takeoff.FUEL_SIMPLE, takeoff_fuel_burned, units='lbm')\n", + "aviary_inputs.set_val(av.Mission.Takeoff.LIFT_OVER_DRAG, takeoff_L_over_D, units='unitless')\n", + "aviary_inputs.set_val(av.Mission.Design.THRUST_TAKEOFF_PER_ENG, takeoff_thrust_per_eng, units='lbf')\n", "\n", "alt_airport = 0 # ft\n", "cruise_mach = 0.79\n", "\n", - "alt_i_climb = 0*_units.foot # m\n", - "alt_f_climb = 35000.0*_units.foot # m\n", - "mass_i_climb = 131000*_units.lb # kg\n", - "mass_f_climb = 126000*_units.lb # kg\n", + "alt_i_climb = 0 * _units.foot # m\n", + "alt_f_climb = 35000.0 * _units.foot # m\n", + "mass_i_climb = 131000 * _units.lb # kg\n", + "mass_f_climb = 126000 * _units.lb # kg\n", "# initial mach set to lower value so it can intersect with takeoff end mach\n", "# mach_i_climb = 0.3\n", "mach_i_climb = 0.2\n", "mach_f_climb = cruise_mach\n", - "range_i_climb = 0*_units.nautical_mile # m\n", - "range_f_climb = 160.3*_units.nautical_mile # m\n", + "range_i_climb = 0 * _units.nautical_mile # m\n", + "range_f_climb = 160.3 * _units.nautical_mile # m\n", "t_i_climb = 2 * _units.minute # sec\n", - "t_f_climb = 26.20*_units.minute # sec\n", + "t_f_climb = 26.20 * _units.minute # sec\n", "t_duration_climb = t_f_climb - t_i_climb\n", "\n", - "alt_i_cruise = 35000*_units.foot # m\n", - "alt_f_cruise = 35000*_units.foot # m\n", - "alt_min_cruise = 35000*_units.foot # m\n", - "alt_max_cruise = 35000*_units.foot # m\n", - "mass_i_cruise = 126000*_units.lb # kg\n", - "mass_f_cruise = 102000*_units.lb # kg\n", + "alt_i_cruise = 35000 * _units.foot # m\n", + "alt_f_cruise = 35000 * _units.foot # m\n", + "alt_min_cruise = 35000 * _units.foot # m\n", + "alt_max_cruise = 35000 * _units.foot # m\n", + "mass_i_cruise = 126000 * _units.lb # kg\n", + "mass_f_cruise = 102000 * _units.lb # kg\n", "cruise_mach = cruise_mach\n", - "range_i_cruise = 160.3*_units.nautical_mile # m\n", - "range_f_cruise = 3243.9*_units.nautical_mile # m\n", - "t_i_cruise = 26.20*_units.minute # sec\n", - "t_f_cruise = 432.38*_units.minute # sec\n", + "range_i_cruise = 160.3 * _units.nautical_mile # m\n", + "range_f_cruise = 3243.9 * _units.nautical_mile # m\n", + "t_i_cruise = 26.20 * _units.minute # sec\n", + "t_f_cruise = 432.38 * _units.minute # sec\n", "t_duration_cruise = t_f_cruise - t_i_cruise\n", "\n", - "alt_i_descent = 35000*_units.foot\n", + "alt_i_descent = 35000 * _units.foot\n", "# final altitude set to 35 to ensure landing is feasible point\n", "# alt_f_descent = 0*_units.foot\n", - "alt_f_descent = 35*_units.foot\n", + "alt_f_descent = 35 * _units.foot\n", "mach_i_descent = 0.79\n", "mach_f_descent = 0.3\n", - "mass_i_descent = 102000*_units.pound\n", - "mass_f_descent = 101000*_units.pound\n", - "distance_i_descent = 3243.9*_units.nautical_mile\n", - "distance_f_descent = 3378.7*_units.nautical_mile\n", - "t_i_descent = 432.38*_units.minute\n", - "t_f_descent = 461.62*_units.minute\n", + "mass_i_descent = 102000 * _units.pound\n", + "mass_f_descent = 101000 * _units.pound\n", + "distance_i_descent = 3243.9 * _units.nautical_mile\n", + "distance_f_descent = 3378.7 * _units.nautical_mile\n", + "t_i_descent = 432.38 * _units.minute\n", + "t_f_descent = 461.62 * _units.minute\n", "t_duration_descent = t_f_descent - t_i_descent\n", "\n", - "engine = av.build_engine_deck(aviary_inputs)\n", - "av.preprocess_options(aviary_inputs, engine_models=engine)\n", + "engines = [av.build_engine_deck(aviary_inputs)]\n", + "av.preprocess_options(aviary_inputs, engine_models=engines)\n", "\n", "# define subsystems\n", "aero = av.CoreAerodynamicsBuilder(code_origin=av.LegacyCode('FLOPS'))\n", "geom = av.CoreGeometryBuilder(code_origin=av.LegacyCode('FLOPS'))\n", "mass = av.CoreMassBuilder(code_origin=av.LegacyCode('FLOPS'))\n", - "prop = av.CorePropulsionBuilder(engine_models=engine)\n", + "prop = av.CorePropulsionBuilder(engine_models=engines)\n", "\n", "premission_subsystems = [prop, geom, aero, mass]\n", "mission_subsystems = [aero, prop]\n", @@ -193,15 +221,17 @@ "aviary_inputs.set_val(av.Mission.Design.GROSS_MASS, 135000.0, units='lbm')\n", "aviary_inputs.set_val(av.Mission.Summary.GROSS_MASS, 135000.0, units='lbm')\n", "\n", - "prob.model.add_design_var(av.Mission.Design.GROSS_MASS, units='lbm',\n", - " lower=100000.0, upper=200000.0, ref=135000)\n", - "prob.model.add_design_var(av.Mission.Summary.GROSS_MASS, units='lbm',\n", - " lower=100000.0, upper=200000.0, ref=135000)\n", + "prob.model.add_design_var(\n", + " av.Mission.Design.GROSS_MASS, units='lbm', lower=100000.0, upper=200000.0, ref=135000\n", + ")\n", + "prob.model.add_design_var(\n", + " av.Mission.Summary.GROSS_MASS, units='lbm', lower=100000.0, upper=200000.0, ref=135000\n", + ")\n", "\n", "takeoff_options = av.HeightEnergyTakeoffPhaseBuilder(\n", " airport_altitude=alt_airport, # ft\n", " # no units\n", - " num_engines=aviary_inputs.get_val(av.Aircraft.Engine.NUM_ENGINES)\n", + " num_engines=aviary_inputs.get_val(av.Aircraft.Engine.NUM_ENGINES),\n", ")\n", "\n", "#################\n", @@ -215,25 +245,23 @@ "descent_seg_ends, _ = dm.utils.lgl.lgl(num_segments_descent + 1)\n", "\n", "transcription_climb = dm.Radau(\n", - " num_segments=num_segments_climb, order=3, compressed=True,\n", - " segment_ends=climb_seg_ends)\n", - "transcription_cruise = dm.Radau(\n", - " num_segments=num_segments_cruise, order=3, compressed=True)\n", + " num_segments=num_segments_climb, order=3, compressed=True, segment_ends=climb_seg_ends\n", + ")\n", + "transcription_cruise = dm.Radau(num_segments=num_segments_cruise, order=3, compressed=True)\n", "transcription_descent = dm.Radau(\n", - " num_segments=num_segments_descent, order=3, compressed=True,\n", - " segment_ends=descent_seg_ends)\n", + " num_segments=num_segments_descent, order=3, compressed=True, segment_ends=descent_seg_ends\n", + ")\n", "\n", "climb_options = av.HeightEnergyPhaseBuilder(\n", " 'test_climb',\n", - " user_options=av.AviaryValues({\n", - " 'initial_altitude': (alt_i_climb, 'm'),\n", - " 'final_altitude': (alt_f_climb, 'm'),\n", - " 'initial_mach': (mach_i_climb, 'unitless'),\n", - " 'final_mach': (mach_f_climb, 'unitless'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " 'input_initial': (True, 'unitless'),\n", - " 'use_polynomial_control': (False, 'unitless'),\n", - " }),\n", + " user_options={\n", + " 'altitude_optimize': (False, 'unitless'),\n", + " 'altitude_initial': (alt_i_climb, 'm'),\n", + " 'altitude_final': (alt_f_climb, 'm'),\n", + " 'mach_optimize': (False, 'unitless'),\n", + " 'mach_initial': (mach_i_climb, 'unitless'),\n", + " 'mach_final': (mach_f_climb, 'unitless'),\n", + " },\n", " core_subsystems=mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_climb,\n", @@ -241,14 +269,17 @@ "\n", "cruise_options = av.HeightEnergyPhaseBuilder(\n", " 'test_cruise',\n", - " user_options=av.AviaryValues({\n", - " 'initial_altitude': (alt_min_cruise, 'm'),\n", - " 'final_altitude': (alt_max_cruise, 'm'),\n", - " 'initial_mach': (cruise_mach, 'unitless'),\n", - " 'final_mach': (cruise_mach, 'unitless'),\n", + " user_options={\n", + " 'altitude_optimize': (False, 'unitless'),\n", + " 'altitude_polynomial_order': 3,\n", + " 'altitude_initial': (alt_min_cruise, 'm'),\n", + " 'altitude_final': (alt_max_cruise, 'm'),\n", + " 'mach_optimize': (False, 'unitless'),\n", + " 'mach_polynomial_order': 3,\n", + " 'mach_initial': (cruise_mach, 'unitless'),\n", + " 'mach_final': (cruise_mach, 'unitless'),\n", " 'required_available_climb_rate': (300, 'ft/min'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " }),\n", + " },\n", " core_subsystems=mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_cruise,\n", @@ -256,14 +287,14 @@ "\n", "descent_options = av.HeightEnergyPhaseBuilder(\n", " 'test_descent',\n", - " user_options=av.AviaryValues({\n", - " 'final_altitude': (alt_f_descent, 'm'),\n", - " 'initial_altitude': (alt_i_descent, 'm'),\n", - " 'initial_mach': (mach_i_descent, 'unitless'),\n", - " 'final_mach': (mach_f_descent, 'unitless'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " 'use_polynomial_control': (False, 'unitless'),\n", - " }),\n", + " user_options={\n", + " 'altitude_optimize': (False, 'unitless'),\n", + " 'altitude_final': (alt_f_descent, 'm'),\n", + " 'altitude_initial': (alt_i_descent, 'm'),\n", + " 'mach_optimize': (False, 'unitless'),\n", + " 'mach_initial': (mach_i_descent, 'unitless'),\n", + " 'mach_final': (mach_f_descent, 'unitless'),\n", + " },\n", " core_subsystems=mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_descent,\n", @@ -271,17 +302,16 @@ "\n", "landing_options = av.HeightEnergyLandingPhaseBuilder(\n", " ref_wing_area=aviary_inputs.get_val(av.Aircraft.Wing.AREA, units='ft**2'),\n", - " Cl_max_ldg=aviary_inputs.get_val(\n", - " av.Mission.Landing.LIFT_COEFFICIENT_MAX) # no units\n", + " Cl_max_ldg=aviary_inputs.get_val(av.Mission.Landing.LIFT_COEFFICIENT_MAX), # no units\n", ")\n", "\n", "# Upstream pre-mission analysis for aero\n", "prob.model.add_subsystem(\n", " 'pre_mission',\n", - " av.CorePreMission(aviary_options=aviary_inputs,\n", - " subsystems=premission_subsystems),\n", + " av.CorePreMission(aviary_options=aviary_inputs, subsystems=premission_subsystems),\n", " promotes_inputs=['aircraft:*', 'mission:*'],\n", - " promotes_outputs=['aircraft:*', 'mission:*'])\n", + " promotes_outputs=['aircraft:*', 'mission:*'],\n", + ")\n", "\n", "# directly connect phases (strong_couple = True), or use linkage constraints (weak\n", "# coupling / strong_couple=False)\n", @@ -290,35 +320,57 @@ "takeoff = takeoff_options.build_phase(False)\n", "\n", "climb = climb_options.build_phase(aviary_options=aviary_inputs)\n", + "climb.set_state_options('mass', fix_initial=False, input_initial=True)\n", + "climb.set_state_options('distance', fix_initial=False, input_initial=True)\n", + "climb.set_control_options('altitude', fix_initial=False)\n", + "climb.set_control_options('mach', fix_initial=False)\n", "\n", "cruise = cruise_options.build_phase(aviary_options=aviary_inputs)\n", + "cruise.set_state_options('mass', fix_initial=False, input_initial=False)\n", + "cruise.set_state_options('distance', fix_initial=False, input_initial=False)\n", + "cruise.set_control_options('mach', fix_initial=False)\n", "\n", "descent = descent_options.build_phase(aviary_options=aviary_inputs)\n", + "descent.set_state_options('mass', fix_initial=False, input_initial=False)\n", + "descent.set_state_options('distance', fix_initial=False, input_initial=False)\n", + "descent.set_control_options('mach', fix_initial=False)\n", "\n", "landing = landing_options.build_phase(False)\n", "\n", "prob.model.add_subsystem(\n", - " 'takeoff', takeoff, promotes_inputs=['aircraft:*', 'mission:*'],\n", - " promotes_outputs=['mission:*'])\n", + " 'takeoff', takeoff, promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=['mission:*']\n", + ")\n", "\n", "traj = prob.model.add_subsystem('traj', dm.Trajectory())\n", "\n", "# if fix_initial is false, can we always set input_initial to be true for\n", "# necessary states, and then ignore if we use a linkage?\n", - "climb.set_time_options(fix_initial=True, fix_duration=False, units='s',\n", - " duration_bounds=(t_duration_climb*0.5, t_duration_climb*2),\n", - " duration_ref=t_duration_climb)\n", - "cruise.set_time_options(fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(t_duration_cruise*0.5, t_duration_cruise*2),\n", - " duration_ref=t_duration_cruise,\n", - " initial_bounds=(t_duration_climb*0.5, t_duration_climb*2))\n", + "climb.set_time_options(\n", + " fix_initial=True,\n", + " fix_duration=False,\n", + " units='s',\n", + " duration_bounds=(t_duration_climb * 0.5, t_duration_climb * 2),\n", + " duration_ref=t_duration_climb,\n", + ")\n", + "cruise.set_time_options(\n", + " fix_initial=False,\n", + " fix_duration=False,\n", + " units='s',\n", + " duration_bounds=(t_duration_cruise * 0.5, t_duration_cruise * 2),\n", + " duration_ref=t_duration_cruise,\n", + " initial_bounds=(t_duration_climb * 0.5, t_duration_climb * 2),\n", + ")\n", "descent.set_time_options(\n", - " fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(t_duration_descent*0.5, t_duration_descent*2),\n", + " fix_initial=False,\n", + " fix_duration=False,\n", + " units='s',\n", + " duration_bounds=(t_duration_descent * 0.5, t_duration_descent * 2),\n", " duration_ref=t_duration_descent,\n", " initial_bounds=(\n", - " (t_duration_cruise + t_duration_climb)*0.5,\n", - " (t_duration_cruise + t_duration_climb)*2))\n", + " (t_duration_cruise + t_duration_climb) * 0.5,\n", + " (t_duration_cruise + t_duration_climb) * 2,\n", + " ),\n", + ")\n", "\n", "traj.add_phase('climb', climb)\n", "\n", @@ -327,88 +379,91 @@ "traj.add_phase('descent', descent)\n", "\n", "prob.model.add_subsystem(\n", - " 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'],\n", - " promotes_outputs=['mission:*'])\n", + " 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=['mission:*']\n", + ")\n", "\n", "###############\n", "# link phases #\n", "###############\n", + "phases = ['climb', 'cruise', 'descent']\n", + "traj.link_phases(\n", + " phases, ['time', av.Dynamic.Vehicle.MASS, av.Dynamic.Mission.DISTANCE], connected=strong_couple\n", + ")\n", "\n", - "traj.link_phases([\"climb\", \"cruise\", \"descent\"], [\"time\", av.Dynamic.Mission.MASS, av.Dynamic.Mission.DISTANCE], connected=strong_couple)\n", - "\n", - "param_vars = [av.Aircraft.Nacelle.CHARACTERISTIC_LENGTH,\n", - " av.Aircraft.Nacelle.FINENESS,\n", - " av.Aircraft.Nacelle.LAMINAR_FLOW_LOWER,\n", - " av.Aircraft.Nacelle.LAMINAR_FLOW_UPPER,\n", - " av.Aircraft.Nacelle.WETTED_AREA]\n", - "\n", - "params = {}\n", - "for var in param_vars:\n", - " params[var] = {'shape': (1, ), 'static_target': True}\n", - "\n", + "# loop through phases and get all subsystem parameters\n", "external_parameters = {}\n", - "external_parameters['climb'] = params\n", - "external_parameters['cruise'] = params\n", - "external_parameters['descent'] = params\n", - "\n", - "traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs,\n", - " external_parameters=external_parameters)\n", + "for phase_name in phases:\n", + " external_parameters[phase_name] = {}\n", + " for subsystem in mission_subsystems:\n", + " parameter_dict = subsystem.get_parameters(phase_info={}, aviary_inputs=aviary_inputs)\n", + " for parameter in parameter_dict:\n", + " external_parameters[phase_name][parameter] = parameter_dict[parameter]\n", + "\n", + "traj = av.setup_trajectory_params(\n", + " prob.model, traj, aviary_inputs, phases, external_parameters=external_parameters\n", + ")\n", "\n", "##################################\n", "# Connect in Takeoff and Landing #\n", "##################################\n", - "prob.model.connect(av.Mission.Takeoff.FINAL_MASS,\n", - " 'traj.climb.initial_states:mass')\n", - "prob.model.connect(av.Mission.Takeoff.GROUND_DISTANCE,\n", - " 'traj.climb.initial_states:distance')\n", + "prob.model.connect(av.Mission.Takeoff.FINAL_MASS, 'traj.climb.initial_states:mass')\n", + "prob.model.connect(av.Mission.Takeoff.GROUND_DISTANCE, 'traj.climb.initial_states:distance')\n", "\n", - "prob.model.connect('traj.descent.states:mass',\n", - " av.Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1])\n", - "prob.model.connect('traj.descent.control_values:altitude', av.Mission.Landing.INITIAL_ALTITUDE,\n", - " src_indices=[-1])\n", + "prob.model.connect('traj.descent.states:mass', av.Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1])\n", + "prob.model.connect(\n", + " 'traj.descent.control_values:altitude', av.Mission.Landing.INITIAL_ALTITUDE, src_indices=[-1]\n", + ")\n", "\n", "###############\n", "# Constraints #\n", "###############\n", "\n", - "ecomp = om.ExecComp('fuel_burned = initial_mass - descent_mass_final',\n", - " initial_mass={'units': 'lbm', 'shape': 1},\n", - " descent_mass_final={'units': 'lbm', 'shape': 1},\n", - " fuel_burned={'units': 'lbm', 'shape': 1})\n", + "ecomp = om.ExecComp(\n", + " 'fuel_burned = initial_mass - descent_mass_final',\n", + " initial_mass={'units': 'lbm', 'shape': 1},\n", + " descent_mass_final={'units': 'lbm', 'shape': 1},\n", + " fuel_burned={'units': 'lbm', 'shape': 1},\n", + ")\n", "\n", - "prob.model.add_subsystem('fuel_burn', ecomp,\n", - " promotes_inputs=[\n", - " ('initial_mass', av.Mission.Design.GROSS_MASS)],\n", - " promotes_outputs=['fuel_burned'])\n", + "prob.model.add_subsystem(\n", + " 'fuel_burn',\n", + " ecomp,\n", + " promotes_inputs=[('initial_mass', av.Mission.Design.GROSS_MASS)],\n", + " promotes_outputs=['fuel_burned'],\n", + ")\n", "\n", - "prob.model.connect(\"traj.descent.states:mass\",\n", - " \"fuel_burn.descent_mass_final\", src_indices=[-1])\n", + "prob.model.connect('traj.descent.states:mass', 'fuel_burn.descent_mass_final', src_indices=[-1])\n", "\n", - "ecomp = om.ExecComp('overall_fuel = fuel_burned + fuel_reserve',\n", - " fuel_burned={'units': 'lbm', 'shape': 1},\n", - " fuel_reserve={'units': 'lbm', 'val': 2173.},\n", - " overall_fuel={'units': 'lbm'})\n", - "prob.model.add_subsystem('fuel_calc', ecomp,\n", - " promotes_inputs=['fuel_burned'],\n", - " promotes_outputs=['overall_fuel'])\n", + "ecomp = om.ExecComp(\n", + " 'overall_fuel = fuel_burned + fuel_reserve',\n", + " fuel_burned={'units': 'lbm', 'shape': 1},\n", + " fuel_reserve={'units': 'lbm', 'val': 2173.0},\n", + " overall_fuel={'units': 'lbm'},\n", + ")\n", + "prob.model.add_subsystem(\n", + " 'fuel_calc', ecomp, promotes_inputs=['fuel_burned'], promotes_outputs=['overall_fuel']\n", + ")\n", "\n", "ecomp = om.ExecComp(\n", - " 'mass_resid = operating_empty_mass + overall_fuel + payload_mass '\n", - " '- initial_mass',\n", + " 'mass_resid = operating_empty_mass + overall_fuel + payload_mass - initial_mass',\n", " operating_empty_mass={'units': 'lbm'},\n", " overall_fuel={'units': 'lbm'},\n", " payload_mass={'units': 'lbm'},\n", " initial_mass={'units': 'lbm'},\n", - " mass_resid={'units': 'lbm'})\n", + " mass_resid={'units': 'lbm'},\n", + ")\n", "\n", "prob.model.add_subsystem(\n", - " 'mass_constraint', ecomp,\n", + " 'mass_constraint',\n", + " ecomp,\n", " promotes_inputs=[\n", - " ('operating_empty_mass', av.Aircraft.Design.OPERATING_MASS),\n", + " ('operating_empty_mass', av.Mission.Summary.OPERATING_MASS),\n", " 'overall_fuel',\n", " ('payload_mass', av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS),\n", - " ('initial_mass', av.Mission.Design.GROSS_MASS)],\n", - " promotes_outputs=['mass_resid'])\n", + " ('initial_mass', av.Mission.Design.GROSS_MASS),\n", + " ],\n", + " promotes_outputs=['mass_resid'],\n", + ")\n", "\n", "prob.model.add_constraint('mass_resid', equals=0.0, ref=1.0)\n", "\n", @@ -435,21 +490,22 @@ "# we are maxing final mass b/c we don't have an independent value for fuel_mass yet\n", "# we are going to normalize these (making each of the sub-objectives approx = 1 )\n", "prob.model.add_subsystem(\n", - " \"regularization\",\n", + " 'regularization',\n", " om.ExecComp(\n", - " \"reg_objective = fuel_mass/1500\",\n", + " 'reg_objective = fuel_mass/1500',\n", " reg_objective=0.0,\n", - " fuel_mass={\"units\": \"lbm\", \"shape\": 1},\n", + " fuel_mass={'units': 'lbm', 'shape': 1},\n", " ),\n", - " promotes_outputs=['reg_objective']\n", + " promotes_outputs=['reg_objective'],\n", ")\n", "# connect the final mass from cruise into the objective\n", - "prob.model.connect(av.Mission.Design.FUEL_MASS, \"regularization.fuel_mass\")\n", + "prob.model.connect(av.Mission.Summary.FUEL_MASS, 'regularization.fuel_mass')\n", "\n", "prob.model.add_objective('reg_objective', ref=1)\n", "\n", "# Set initial default values for all LEAPS aircraft variables.\n", "varnames = [\n", + " av.Aircraft.Engine.SCALE_FACTOR,\n", " av.Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN,\n", " av.Aircraft.Wing.SWEEP,\n", " av.Aircraft.Wing.TAPER_RATIO,\n", @@ -459,7 +515,23 @@ "]\n", "av.set_aviary_input_defaults(prob.model, varnames, aviary_inputs)\n", "\n", - "prob.setup(force_alloc_complex=True)\n", + "av.setup_model_options(prob, aviary_inputs)\n", + "\n", + "prob.setup()\n", + "\n", + "phase = prob.model.traj.phases.cruise\n", + "phase.nonlinear_solver = om.NonlinearRunOnce()\n", + "phase.linear_solver = om.LinearRunOnce()\n", + "if isinstance(phase.indep_states, om.ImplicitComponent):\n", + " phase.indep_states.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)\n", + " phase.indep_states.linear_solver = om.DirectSolver(rhs_checking=True)\n", + "\n", + "phase = prob.model.traj.phases.descent\n", + "phase.nonlinear_solver = om.NonlinearRunOnce()\n", + "phase.linear_solver = om.LinearRunOnce()\n", + "if isinstance(phase.indep_states, om.ImplicitComponent):\n", + " phase.indep_states.nonlinear_solver = om.NewtonSolver(solve_subsystems=True)\n", + " phase.indep_states.linear_solver = om.DirectSolver(rhs_checking=True)\n", "\n", "av.set_aviary_initial_values(prob, aviary_inputs)\n", "\n", @@ -470,99 +542,148 @@ "prob.set_val('traj.climb.t_initial', t_i_climb, units='s')\n", "prob.set_val('traj.climb.t_duration', t_duration_climb, units='s')\n", "\n", - "prob.set_val('traj.climb.controls:altitude', climb.interp(\n", - " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m')\n", "prob.set_val(\n", - " 'traj.climb.controls:mach', climb.interp(\n", - " av.Dynamic.Mission.MACH, ys=[mach_i_climb, mach_f_climb]), units='unitless')\n", - "prob.set_val('traj.climb.states:mass', climb.interp(\n", - " av.Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", - "prob.set_val('traj.climb.states:distance', climb.interp(\n", - " av.Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]), units='m')\n", + " 'traj.climb.controls:altitude',\n", + " climb.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]),\n", + " units='m',\n", + ")\n", + "prob.set_val(\n", + " 'traj.climb.controls:mach',\n", + " climb.interp(av.Dynamic.Atmosphere.MACH, ys=[mach_i_climb, mach_f_climb]),\n", + " units='unitless',\n", + ")\n", + "prob.set_val(\n", + " 'traj.climb.states:mass',\n", + " climb.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_climb, mass_f_climb]),\n", + " units='kg',\n", + ")\n", + "prob.set_val(\n", + " 'traj.climb.states:distance',\n", + " climb.interp(av.Dynamic.Mission.DISTANCE, ys=[range_i_climb, range_f_climb]),\n", + " units='m',\n", + ")\n", "\n", "prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s')\n", "prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s')\n", "\n", - "prob.set_val('traj.cruise.controls:altitude', cruise.interp(\n", - " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m')\n", "prob.set_val(\n", - " 'traj.cruise.controls:mach', cruise.interp(\n", - " av.Dynamic.Mission.MACH, ys=[cruise_mach, cruise_mach]), units='unitless')\n", - "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", - " av.Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", - "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", - " av.Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]), units='m')\n", + " 'traj.cruise.controls:altitude',\n", + " cruise.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]),\n", + " units='m',\n", + ")\n", + "prob.set_val(\n", + " 'traj.cruise.controls:mach',\n", + " cruise.interp(av.Dynamic.Atmosphere.MACH, ys=[cruise_mach, cruise_mach]),\n", + " units='unitless',\n", + ")\n", + "prob.set_val(\n", + " 'traj.cruise.states:mass',\n", + " cruise.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_cruise, mass_f_cruise]),\n", + " units='kg',\n", + ")\n", + "prob.set_val(\n", + " 'traj.cruise.states:distance',\n", + " cruise.interp(av.Dynamic.Mission.DISTANCE, ys=[range_i_cruise, range_f_cruise]),\n", + " units='m',\n", + ")\n", "\n", "prob.set_val('traj.descent.t_initial', t_i_descent, units='s')\n", "prob.set_val('traj.descent.t_duration', t_duration_descent, units='s')\n", "\n", - "prob.set_val('traj.descent.controls:altitude', descent.interp(\n", - " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m')\n", "prob.set_val(\n", - " 'traj.descent.controls:mach', descent.interp(\n", - " av.Dynamic.Mission.MACH, ys=[mach_i_descent, mach_f_descent]), units='unitless')\n", - "prob.set_val('traj.descent.states:mass', descent.interp(\n", - " av.Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", - "prob.set_val('traj.descent.states:distance', descent.interp(\n", - " av.Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", - "\n", - "# Turn off solver printing so that the SNOPT output is readable.\n", + " 'traj.descent.controls:altitude',\n", + " descent.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]),\n", + " units='m',\n", + ")\n", + "prob.set_val(\n", + " 'traj.descent.controls:mach',\n", + " descent.interp(av.Dynamic.Atmosphere.MACH, ys=[mach_i_descent, mach_f_descent]),\n", + " units='unitless',\n", + ")\n", + "prob.set_val(\n", + " 'traj.descent.states:mass',\n", + " descent.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_descent, mass_f_descent]),\n", + " units='kg',\n", + ")\n", + "prob.set_val(\n", + " 'traj.descent.states:distance',\n", + " descent.interp(av.Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]),\n", + " units='m',\n", + ")\n", + "\n", + "# Turn off solver printing so that the optimizer output is readable.\n", "prob.set_solver_print(level=0)\n", "\n", - "dm.run_problem(prob, simulate=False, make_plots=False, simulate_kwargs={\n", - " 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9},\n", - " solution_record_file='N3CC_sizing.db')\n", - "prob.record(\"final\")\n", + "dm.run_problem(\n", + " prob,\n", + " simulate=False,\n", + " make_plots=False,\n", + " solution_record_file='N3CC_sizing.db',\n", + ")\n", + "prob.record('final')\n", "prob.cleanup()\n", "\n", "times_climb = prob.get_val('traj.climb.timeseries.time', units='s')\n", - "altitudes_climb = prob.get_val(\n", - " 'traj.climb.timeseries.altitude', units='m')\n", + "altitudes_climb = prob.get_val('traj.climb.timeseries.altitude', units='m')\n", "masses_climb = prob.get_val('traj.climb.timeseries.mass', units='kg')\n", "ranges_climb = prob.get_val('traj.climb.timeseries.distance', units='m')\n", - "velocities_climb = prob.get_val(\n", - " 'traj.climb.timeseries.velocity', units='m/s')\n", + "velocities_climb = prob.get_val('traj.climb.timeseries.velocity', units='m/s')\n", "thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N')\n", "times_cruise = prob.get_val('traj.cruise.timeseries.time', units='s')\n", - "altitudes_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.altitude', units='m')\n", + "altitudes_cruise = prob.get_val('traj.cruise.timeseries.altitude', units='m')\n", "masses_cruise = prob.get_val('traj.cruise.timeseries.mass', units='kg')\n", "ranges_cruise = prob.get_val('traj.cruise.timeseries.distance', units='m')\n", - "velocities_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.velocity', units='m/s')\n", - "thrusts_cruise = prob.get_val(\n", - " 'traj.cruise.timeseries.thrust_net_total', units='N')\n", + "velocities_cruise = prob.get_val('traj.cruise.timeseries.velocity', units='m/s')\n", + "thrusts_cruise = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N')\n", "times_descent = prob.get_val('traj.descent.timeseries.time', units='s')\n", - "altitudes_descent = prob.get_val(\n", - " 'traj.descent.timeseries.altitude', units='m')\n", + "altitudes_descent = prob.get_val('traj.descent.timeseries.altitude', units='m')\n", "masses_descent = prob.get_val('traj.descent.timeseries.mass', units='kg')\n", "ranges_descent = prob.get_val('traj.descent.timeseries.distance', units='m')\n", - "velocities_descent = prob.get_val(\n", - " 'traj.descent.timeseries.velocity', units='m/s')\n", - "thrusts_descent = prob.get_val(\n", - " 'traj.descent.timeseries.thrust_net_total', units='N')\n", - "\n", - "\n", - "print(\"-------------------------------\")\n", - "print(f\"times_climb: {times_climb[-1]} (s)\")\n", - "print(f\"altitudes_climb: {altitudes_climb[-1]} (m)\")\n", - "print(f\"masses_climb: {masses_climb[-1]} (kg)\")\n", - "print(f\"ranges_climb: {ranges_climb[-1]} (m)\")\n", - "print(f\"velocities_climb: {velocities_climb[-1]} (m/s)\")\n", - "print(f\"thrusts_climb: {thrusts_climb[-1]} (N)\")\n", - "print(f\"times_cruise: {times_cruise[-1]} (s)\")\n", - "print(f\"altitudes_cruise: {altitudes_cruise[-1]} (m)\")\n", - "print(f\"masses_cruise: {masses_cruise[-1]} (kg)\")\n", - "print(f\"ranges_cruise: {ranges_cruise[-1]} (m)\")\n", - "print(f\"velocities_cruise: {velocities_cruise[-1]} (m/s)\")\n", - "print(f\"thrusts_cruise: {thrusts_cruise[-1]} (N)\")\n", - "print(f\"times_descent: {times_descent[-1]} (s)\")\n", - "print(f\"altitudes_descent: {altitudes_descent[-1]} (m)\")\n", - "print(f\"masses_descent: {masses_descent[-1]} (kg)\")\n", - "print(f\"ranges_descent: {ranges_descent[-1]} (m)\")\n", - "print(f\"velocities_descent: {velocities_descent[-1]} (m/s)\")\n", - "print(f\"thrusts_descent: {thrusts_descent[-1]} (N)\")\n", - "print(\"-------------------------------\")\n" + "velocities_descent = prob.get_val('traj.descent.timeseries.velocity', units='m/s')\n", + "thrusts_descent = prob.get_val('traj.descent.timeseries.thrust_net_total', units='N')\n", + "\n", + "\n", + "print('-------------------------------')\n", + "print(f'times_climb: {times_climb[-1]} (s)')\n", + "print(f'altitudes_climb: {altitudes_climb[-1]} (m)')\n", + "print(f'masses_climb: {masses_climb[-1]} (kg)')\n", + "print(f'ranges_climb: {ranges_climb[-1]} (m)')\n", + "print(f'velocities_climb: {velocities_climb[-1]} (m/s)')\n", + "print(f'thrusts_climb: {thrusts_climb[-1]} (N)')\n", + "print(f'times_cruise: {times_cruise[-1]} (s)')\n", + "print(f'altitudes_cruise: {altitudes_cruise[-1]} (m)')\n", + "print(f'masses_cruise: {masses_cruise[-1]} (kg)')\n", + "print(f'ranges_cruise: {ranges_cruise[-1]} (m)')\n", + "print(f'velocities_cruise: {velocities_cruise[-1]} (m/s)')\n", + "print(f'thrusts_cruise: {thrusts_cruise[-1]} (N)')\n", + "print(f'times_descent: {times_descent[-1]} (s)')\n", + "print(f'altitudes_descent: {altitudes_descent[-1]} (m)')\n", + "print(f'masses_descent: {masses_descent[-1]} (kg)')\n", + "print(f'ranges_descent: {ranges_descent[-1]} (m)')\n", + "print(f'velocities_descent: {velocities_descent[-1]} (m/s)')\n", + "print(f'thrusts_descent: {thrusts_descent[-1]} (N)')\n", + "print('-------------------------------')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "171b77ba", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.utils.functions import get_path\n", + "from aviary.validation_cases.validation_tests import get_flops_inputs\n", + "\n", + "glue_variable(get_flops_inputs.__name__ + '()')\n", + "glue_variable(get_path('advanced_single_aisle_data.py').relative_to(av.top_dir), md_code=True)" ] }, { @@ -570,9 +691,9 @@ "id": "2b43d293", "metadata": {}, "source": [ - "This model demonstrates the flexibility of level 3. For example, we do not load the aircraft model from a `.csv` file but from a Python file using the `get_flops_inputs()` method.\n", + "This model demonstrates the flexibility of level 3. For example, we do not load the aircraft model from a `.csv` file but from a Python file using the {glue:md}`get_flops_inputs()` method.\n", "\n", - "This function not only reads Aviary and mission variables but also builds the engine. More information can be found in `aviary/models/N3CC/N3CC_data.py`.\n", + "This function not only reads Aviary and mission variables but also builds the engine. More information can be found in {glue:md}`models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py`.\n", "\n", "Note that we can read large single aisle aircraft inputs this way as well:" ] @@ -590,7 +711,8 @@ "source": [ "# Testing Cell\n", "from aviary.interface.download_models import get_model\n", - "get_model('N3CC/N3CC_data.py');" + "\n", + "get_model('advanced_single_aisle/advanced_single_aisle_data.py')" ] }, { @@ -613,10 +735,10 @@ "source": [ "The data files are at:\n", "```\n", - "aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py\n", - "aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py\n", - "aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py\n", - "aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py\n", + "aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py\n", + "aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py\n", + "aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py\n", + "aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py\n", "```\n", "\n", "respectively." @@ -634,15 +756,17 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.download_models import get_model\n", "import os\n", + "\n", + "from aviary.interface.download_models import get_model\n", + "\n", "all_files = {\n", - " 'large_single_aisle_1':[''],\n", - " 'large_single_aisle_2':['','_detailwing','_altwt'],\n", - " }\n", + " 'large_single_aisle_1': [''],\n", + " 'large_single_aisle_2': ['', '_detailwing', '_altwt'],\n", + "}\n", "for folder, files in all_files.items():\n", " for file in files:\n", - " get_model(os.path.join(folder,folder+file+'_FLOPS_data.py'));" + " get_model(os.path.join(folder, folder + file + '_FLOPS_data.py'))" ] }, { @@ -652,7 +776,7 @@ "source": [ "### Discussing this example in more detail\n", "\n", - "We move all the code blocks on taxi to `add_pre_mission_system` function because it is how it is done in `methods_for_level2.py`. Similarly, all the code blocks on landing are moved to `add_post_mission_systems` function. Be careful! Generally speaking, not all components can be moved around due to the expected order of execution." + "We move all the code blocks on taxi to {glue:md}`add_pre_mission_systems()` function because it is how it is done in {glue:md}`aviary/interface/methods_for_level2.py`. Similarly, all the code blocks on landing are moved to {glue:md}`add_post_mission_systems()` function. Be careful! Generally speaking, not all components can be moved around due to the expected order of execution." ] }, { @@ -660,7 +784,7 @@ "id": "c2452c52", "metadata": {}, "source": [ - "In `aviary/validation_cases/benchmark_tests` folder, there is another N3CC model `test_FLOPS_based_sizing_N3CC.py`. If we had started from that model, you would need to have an `add_design_variables` function." + "In `aviary/validation_cases/benchmark_tests` folder, there is another N3CC model `test_FLOPS_based_sizing_N3CC.py`. If we had started from that model, you would need to have an {glue:md}`add_design_variables()` function." ] }, { @@ -675,11 +799,13 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.functions import get_path\n", "import os\n", + "\n", + "from aviary.utils.functions import get_path\n", + "\n", "folder = 'validation_cases/benchmark_tests'\n", "file = 'test_FLOPS_based_sizing_N3CC.py'\n", - "get_path(os.path.join(folder,file));" + "get_path(os.path.join(folder, file))" ] }, { @@ -695,7 +821,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -709,7 +835,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/getting_started/tools_that_aviary_uses.md b/aviary/docs/getting_started/tools_that_aviary_uses.md index ce1b71f9f1..f47e779ea8 100644 --- a/aviary/docs/getting_started/tools_that_aviary_uses.md +++ b/aviary/docs/getting_started/tools_that_aviary_uses.md @@ -79,14 +79,6 @@ NASA has used Dymos in various projects, from optimizing the trajectory of space efficient electric aircraft flight profiles subject to thermal constraints. These projects have benefited from Dymos's capabilities and Dymos has in turn grown as a more than capable tool, hence its usage in Aviary. -## Simupy - -[**Simupy**](https://simupy.readthedocs.io/en/latest/) is a Python package for the simulation of dynamic systems. -It provides a framework for defining and solving differential equations, including the ability to handle -discontinuities and events. -As Aviary is further developed, Simupy will be available to handle the time integration of the system dynamics. -This capability is not currently fully integrated into Aviary. - ## FLOPS The following description has been adapted from the FLOPS User's Guide[^FLOPSMAN]. For diff --git a/aviary/docs/getting_started/what_aviary_does.md b/aviary/docs/getting_started/what_aviary_does.md index acf630706f..c024208920 100644 --- a/aviary/docs/getting_started/what_aviary_does.md +++ b/aviary/docs/getting_started/what_aviary_does.md @@ -61,7 +61,7 @@ Please see the [external subsystems doc pages](../user_guide/subsystems) for mor Aviary is designed to be flexible enough to design a variety of aircraft. Although many of the core subsystems were written with transport aircraft in mind, these subsystems can be replaced or augmented to support other types of aircraft. -We have used Aviary to design single- and double-aisle commercial aircraft, regional jets, advanced concepts like truss-braced wings with hybrid-electric propulsion, and more. +We have used Aviary to design single- and double-aisle commercial aircraft, regional jets, advanced concepts like truss-braced wings with hybrid-electric propulsion and blended wing body aircraft, and more. Aviary is also able to optimize a variety of mission types and definitions. Users are able to freely define the mission definition, including the number of phases, which quantities are controlled by the optimizer, and more. diff --git a/aviary/docs/misc_resources/comparison_to_flops.md b/aviary/docs/misc_resources/comparison_to_flops.md index f4068ea1cb..e50963283e 100644 --- a/aviary/docs/misc_resources/comparison_to_flops.md +++ b/aviary/docs/misc_resources/comparison_to_flops.md @@ -93,7 +93,7 @@ complex than for a traditional tube-and-wing configuration. FLOPS allows for the input of a maximum of two engine types, each with its own engine deck, whereas in Aviary an unlimited number of engine types may be -defined. This means that Aviary supports arbitrary numbers of heterogenous +defined. This means that Aviary supports arbitrary numbers of heterogeneous engines, each of which has unique characteristics and can use different methodologies for sizing and performance estimation. Aviary retains many of the relations used by FLOPS to scale engine mass and performance as a function of change in target thrust. Aviary introduces the capability to define these scaling relations on a per-engine-type basis, instead diff --git a/aviary/docs/misc_resources/externally_supported_subsystems.ipynb b/aviary/docs/misc_resources/externally_supported_subsystems.ipynb index 76cb510d25..dcb06fb345 100644 --- a/aviary/docs/misc_resources/externally_supported_subsystems.ipynb +++ b/aviary/docs/misc_resources/externally_supported_subsystems.ipynb @@ -7,7 +7,7 @@ "# Externally Supported Subsystems\n", "\n", "Aviary supports any generic subsystem that a user adds.\n", - "We include some examples within the Aviary repo within the `aviary/examples/external_subsystems` folder." + "We include some examples within the Aviary repo within the {glue:md}`aviary/examples/external_subsystems` folder." ] }, { @@ -22,13 +22,18 @@ "source": [ "# Testing Cell\n", "import aviary.api as av\n", - "av.get_path('examples/external_subsystems')" + "from aviary.utils.doctape import glue_variable\n", + "\n", + "folder = av.get_path('examples/external_subsystems')\n", + "ext_examples_dir = folder.relative_to(av.top_dir.parent)\n", + "\n", + "glue_variable(str(ext_examples_dir), md_code=True)" ] } ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "av1", "language": "python", "name": "python3" }, @@ -42,7 +47,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/aviary/docs/misc_resources/glossary.md b/aviary/docs/misc_resources/glossary.md index 41ec2a4c57..947df7053f 100644 --- a/aviary/docs/misc_resources/glossary.md +++ b/aviary/docs/misc_resources/glossary.md @@ -42,11 +42,11 @@ flight envelope homogeneous engines An individual engine or set of engines that all have identical performance characteristics. E.g. you might have four engines on an aircraft, but they are all assumed to have the same thrust, fuel consumption, etc. - All engines in a homogenous set use the same `EngineModel` object in Aviary. + All engines in a homogeneous set use the same `EngineModel` object in Aviary. See also; heterogeneous engines. heterogeneous engines - Multiple sets of homogenous engines, with each set having unique performance characteristics. + Multiple sets of homogeneous engines, with each set having unique performance characteristics. This is useful if you are modeling an aircraft with engines of different sizes or types. Each set of unique engines uses a different `EngineModel` object in Aviary. See also; homogeneous engines. diff --git a/aviary/docs/misc_resources/modeling_exercise.ipynb b/aviary/docs/misc_resources/modeling_exercise.ipynb index 5266902151..b39ae4f01b 100644 --- a/aviary/docs/misc_resources/modeling_exercise.ipynb +++ b/aviary/docs/misc_resources/modeling_exercise.ipynb @@ -20,8 +20,8 @@ "\n", "## Task 1: Run a basic Aviary script\n", "\n", - "Aviary ships with multiple examples in the `aviary/examples` directory.\n", - "The most basic, `run_basic_aviary_example.py`, [(available here)](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/run_basic_aviary_example.py) is our first starting point.\n", + "Aviary ships with multiple examples in the {glue:md}`aviary/examples` directory.\n", + "The most basic, {glue:md}`run_level1_example.py`, [(available here)](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/level1_example.py) is our first starting point.\n", "Run this script in your terminal." ] }, @@ -37,7 +37,15 @@ "source": [ "# Testing Cell\n", "import aviary.api as av\n", - "av.get_path('examples/run_basic_aviary_example.py')" + "from aviary.utils.doctape import glue_variable\n", + "\n", + "examples_dir = av.get_path('examples')\n", + "examples_dir = examples_dir.relative_to(av.top_dir.parent)\n", + "glue_variable(examples_dir, md_code=True)\n", + "\n", + "folder = av.get_path('examples/run_level1_example.py')\n", + "basic_example_filepath = av.get_path('examples/run_level1_example.py')\n", + "glue_variable(basic_example_filepath.name, md_code=True)" ] }, { @@ -58,7 +66,7 @@ "Once you have successfully run this script, please open the Aviary dashboard by running the following command in your terminal:\n", "\n", "```bash\n", - "aviary dashboard run_basic_aviary_example\n", + "aviary dashboard run_level1_example\n", "```" ] }, @@ -73,7 +81,26 @@ "outputs": [], "source": [ "from aviary.interface.cmd_entry_points import _command_map\n", - "_command_map['dashboard'];" + "\n", + "_command_map['dashboard']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.interface.methods_for_level2 import AviaryGroup\n", + "from aviary.utils.doctape import glue_variable, glue_class_options\n", + "\n", + "current_glued_vars = []\n", + "glue_class_options(AviaryGroup, current_glued_vars, md_code=True)" ] }, { @@ -88,10 +115,10 @@ "The next step is to run an Aviary case with a mission profile that you define.\n", "Please follow the [instructions in this example doc](../examples/simple_mission_example) to create a custom mission profile.\n", "Once you have created your custom mission profile, run the Aviary case following the instructions in the example doc.\n", - "If you are not able to successfully create a custom `phase_info` object to define the mission, please use the default one defined in the example.\n", + "If you are not able to successfully create a custom {glue:md}`mission_info` object to define the mission, please use the default one defined in the example.\n", "\n", "```{note}\n", - "The survey will ask you to provide a copy of the `phase_info` object you create, so please save this information for later.\n", + "The survey will ask you to provide a copy of the {glue:md}`mission_info` object you create, so please save this information for later.\n", "```\n", "\n", "Again open the Aviary dashboard and visually examine the results by running the following command in your terminal:\n", @@ -103,7 +130,7 @@ "## Task 3: Run a mission with a reserve phase\n", "\n", "Aviary has the capability to run a mission with a reserve phase as [detailed in the docs here](https://openmdao.github.io/Aviary/examples/reserve_missions.html).\n", - "The included example, `run_reserve_mission_fixedrange.py`, [(available here)](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/reserve_missions/run_reserve_mission_fixedrange.py) demonstrates how to run a mission with a reserve phase.\n", + "The included example, {glue:md}`run_reserve_mission_multiphase.py`, [(available here)](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/reserve_missions/run_reserve_mission_multiphase.py) demonstrates how to run a mission with a reserve phase.\n", "Please copy the contents of this file into a new Python script." ] }, @@ -119,7 +146,11 @@ "source": [ "# Testing Cell\n", "import aviary.api as av\n", - "av.get_path('examples/reserve_missions/run_reserve_mission_fixedrange.py');" + "from aviary.utils.doctape import glue_variable\n", + "\n", + "file_name = 'run_reserve_mission_multiphase.py'\n", + "file_path = av.get_path('examples/reserve_missions/' + file_name)\n", + "glue_variable(file_name, md_code=True)" ] }, { @@ -130,7 +161,7 @@ "Then open the Aviary dashboard to visually examine the results:\n", "\n", "```bash\n", - "aviary dashboard run_reserve_mission_fixedrange\n", + "aviary dashboard run_reserve_mission_multiphase\n", "```\n", "\n", "```{note}\n", @@ -141,7 +172,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -155,9 +186,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/misc_resources/planned_future_features.md b/aviary/docs/misc_resources/planned_future_features.md index e2660c7767..5b4c42ffbb 100644 --- a/aviary/docs/misc_resources/planned_future_features.md +++ b/aviary/docs/misc_resources/planned_future_features.md @@ -3,17 +3,12 @@ Aviary is under active development and new features are being added regularly. The following is a non-exhaustive list of planned features that are not yet implemented. (The Aviary team reserves the right to remove features from this list if the need arises. This list is provided for informational purposes only and is not a commitment to perform work.) -- The ability to run off-design missions to develop payload-range diagrams - The full capabilities of FLOPS and GASP to model medium and large sized commercial aircraft, with a few exceptions that have been determined unnecessary -- The tested ability to have different types of engines on the same aircraft -- The ability to accept propeller maps for modeling propeller-driven aircraft - A converter to convert a table of mach/altitude combinations into a phase_info file. This capability exists in the simple mission GUI, but it will be tweaked to allow for the direct input of tabular data as an alternative to the GUI - Natively supported builders for certain high-interest external subsystem tools. Some potential tools to support are: NPSS, pyCycle, OpenVSP, VSPaero, OpenAeroStruct, etc. The Aviary team develops these builders as the need arises, and the development or lack of it for a certain tool does not indicate endorsement of the tool. - Improved cleanliness of the code - Improved ease-of-use for the user interface - Improved Fortran-to-Aviary converter which requires no human intervention or checking - Support for relevant FAA regulations governing aircraft design and operation -- Capability to fly reserve missions using the same mission analysis techniques as the main mission (right now reserve estimates are fixed values or fixed percentages of mission fuel) -- Improved model re-run capability - Full test suite that tests the code format, including testing for docstrings on all functions and classes - Fully tested code blocks in the documentation \ No newline at end of file diff --git a/aviary/docs/tests/check_jupyter_output_linting.py b/aviary/docs/tests/check_jupyter_output_linting.py index 02c6a8ea95..e6fb199eed 100644 --- a/aviary/docs/tests/check_jupyter_output_linting.py +++ b/aviary/docs/tests/check_jupyter_output_linting.py @@ -1,16 +1,9 @@ -import unittest -import os.path import json +import os.path import sys +import unittest -exclude = { - 'tests', - 'test', - '_build', - '.ipynb_checkpoints', - '_srcdocs', - '__pycache__' -} +exclude = {'tests', 'test', '_build', '.ipynb_checkpoints', '_srcdocs', '__pycache__'} directories = None @@ -42,23 +35,19 @@ def _get_files(): # Loop over files for file_name in os.listdir(dirpath): if not file_name.startswith('_') and file_name.endswith('.ipynb'): - FILES.append(dirpath + "/" + file_name) + FILES.append(dirpath + '/' + file_name) if len(FILES) < 1: - raise RuntimeError(f"No notebooks found. Top directory is {top}.") + raise RuntimeError(f'No notebooks found. Top directory is {top}.') return FILES @unittest.skipIf(sys.platform == 'win32', "Tests don't work in Windows") class LintJupyterOutputsTestCase(unittest.TestCase): - """ - Check Jupyter Notebooks for outputs through execution count and recommend to remove output. - """ + """Check Jupyter Notebooks for outputs through execution count and recommend to remove output.""" def test_output(self): - """ - Check that output has been cleaned out of all cells. - """ + """Check that output has been cleaned out of all cells.""" for file in _get_files(): with self.subTest(file): with open(file) as f: @@ -66,30 +55,28 @@ def test_output(self): for cell in json_data['cells']: if 'execution_count' in cell and cell['execution_count'] is not None: msg = "Clear output with 'reset_notebook path_to_notebook.ipynb'" - self.fail(f"Output found in {file}.\n{msg}") + self.fail(f'Output found in {file}.\n{msg}') def test_assert(self): - """ - Make sure any code cells with asserts are hidden. - """ + """Make sure any code cells with asserts are hidden.""" for file in _get_files(): with open(file) as f: json_data = json.load(f) for block in json_data['cells'][1:]: - # Don't check markup cells if block['cell_type'] != 'code': continue tags = block['metadata'].get('tags') if tags: - # Don't check hidden cells - if ('remove-input' in tags and 'remove-output' in tags) or 'remove-cell' in tags: + if ( + 'remove-input' in tags and 'remove-output' in tags + ) or 'remove-cell' in tags: continue # We allow an assert in a cell if you tag it. - if "allow-assert" in tags: + if 'allow-assert' in tags: continue for line in block['source']: @@ -97,14 +84,14 @@ def test_assert(self): sblock = ''.join(block['source']) stags = tags if tags else '' delim = '-' * 50 - self.fail(f"Assert found in a code block in {file}:\n" - f"Tags: {stags}\n" - f"Block source:\n{delim}\n{sblock}\n{delim}") + self.fail( + f'Assert found in a code block in {file}:\n' + f'Tags: {stags}\n' + f'Block source:\n{delim}\n{sblock}\n{delim}' + ) def test_eval_rst(self): - """ - Make sure any automethod calls are bracketed with {eval-rst}. - """ + """Make sure any automethod calls are bracketed with {eval-rst}.""" files = set() for file in _get_files(): @@ -112,7 +99,6 @@ def test_eval_rst(self): json_data = json.load(f) blocks = json_data['cells'] for block in blocks[1:]: - # check only markdown cells if block['cell_type'] != 'markdown': continue @@ -122,8 +108,10 @@ def test_eval_rst(self): files.add(file) if files: - self.fail("'automethod' directive found in the following {} files without" - "'eval-rst':\n{}".format(len(files), '\n'.join(files))) + self.fail( + "'automethod' directive found in the following {} files without" + "'eval-rst':\n{}".format(len(files), '\n'.join(files)) + ) if __name__ == '__main__': diff --git a/aviary/docs/theory_guide/building_metadata_syntax.ipynb b/aviary/docs/theory_guide/building_metadata_syntax.ipynb index 5176bdfd05..deb9d5c4bb 100644 --- a/aviary/docs/theory_guide/building_metadata_syntax.ipynb +++ b/aviary/docs/theory_guide/building_metadata_syntax.ipynb @@ -20,6 +20,24 @@ " !python -m pip install openmdao[notebooks]" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.utils.develop_metadata import add_meta_data, update_meta_data\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "glue_variable(add_meta_data.__name__, md_code=True)\n", + "glue_variable(update_meta_data.__name__, md_code=True)" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -27,7 +45,7 @@ "source": [ "# Building Metadata\n", "\n", - "When working with Aviary models, sometimes it is necessary to extend the Aviary-core variable hierarchy or update existing metadata. The syntax for `add_meta_data` and `update_meta_data` can be found below. For a more detailed explanation of metadata please visit [this link](../user_guide/variable_metadata).\n", + "When working with Aviary models, sometimes it is necessary to extend the Aviary-core variable hierarchy or update existing metadata. The syntax for {glue:md}`add_meta_data` and {glue:md}`update_meta_data` can be found below. For a more detailed explanation of metadata please visit [this link](../user_guide/variable_metadata).\n", "\n", "```{eval-rst}\n", ".. autofunction:: aviary.utils.develop_metadata.add_meta_data\n", @@ -49,17 +67,14 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.develop_metadata import add_meta_data, update_meta_data;" + "from aviary.utils.develop_metadata import add_meta_data, update_meta_data" ] } ], "metadata": { "celltoolbar": "Tags", - "interpreter": { - "hash": "e6c7471802ed76737b16357fb02af5587f3a4cbee5ea7658f3f9a6981469039b" - }, "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "av1", "language": "python", "name": "python3" }, @@ -73,7 +88,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.0" + "version": "3.9.18" }, "orphan": true }, diff --git a/aviary/docs/theory_guide/gasp_based_bwb.ipynb b/aviary/docs/theory_guide/gasp_based_bwb.ipynb new file mode 100644 index 0000000000..25b9a51ba7 --- /dev/null +++ b/aviary/docs/theory_guide/gasp_based_bwb.ipynb @@ -0,0 +1,478 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "71b05853", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.geometry.gasp_based.fuselage import (\n", + " BWBFuselageParameters1,\n", + " BWBCabinLayout,\n", + " BWBFuselageParameters2,\n", + " BWBFuselageSize,\n", + " BWBFuselageGroup,\n", + " BWBFuselageSize,\n", + ")\n", + "from aviary.subsystems.geometry.gasp_based.engine import (\n", + " EngineSize,\n", + " BWBEngineSizeGroup,\n", + " PercentNotInFuselage,\n", + ")\n", + "\n", + "glue_variable(get_variable_name(BWBFuselageParameters1), md_code=True)\n", + "glue_variable(get_variable_name(BWBCabinLayout), md_code=True)\n", + "glue_variable(get_variable_name(BWBFuselageParameters2), md_code=True)\n", + "glue_variable(get_variable_name(BWBFuselageSize), md_code=True)\n", + "glue_variable(get_variable_name(BWBFuselageGroup), md_code=True)\n", + "glue_variable(get_variable_name(EngineSize), md_code=True)\n", + "glue_variable(get_variable_name(BWBEngineSizeGroup), md_code=True)\n", + "glue_variable(get_variable_name(PercentNotInFuselage), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.VERTICAL_MOUNT_LOCATION), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "bb9395be", + "metadata": {}, + "source": [ + "# GASP based BWB model implementation\n", + "\n", + "Modeling of GASP based blended wing body (BWB) aircraft is similar to that of the conventional aircraft but with several key differences. This page is a record of the development. For users, please read [Blended Wing Body Modeling](../user_guide/features/blended_wing_body) in the user guide.\n", + "\n", + "## BWB geometry subsystem\n", + "\n", + "For BWB geomtric subsystem, we add the following components:\n", + "- {glue:md}`BWBFuselageParameters1`: This component computes several fuselage geometric parameters based on user inputs\n", + "- {glue:md}`BWBCabinLayout`: This component computes the layout of passenger cabin for BWB. Several parameters are hard coded in this component.\n", + "- {glue:md}`BWBFuselageParameters2`: This component computes several fuselage geometric parameters based on both the user inputs and cabin layout.\n", + "- {glue:md}`BWBFuselageSize`: It carries out the computation of fuselage length and wetted area of BWB model.\n", + "- {glue:md}`BWBFuselageGroup`: {glue:md}`BWBFuselageParameters1` + {glue:md}`BWBCabinLayout` + {glue:md}`BWBFuselageParameters2` + {glue:md}`BWBFuselageSize`\n", + "- {glue:md}`PercentNotInFuselage`: For BWB, engines may be partially buried into fuselage. This component computes the percentage of corresponding surface area of nacelles not buried in fuselage. This parameter is passed to {glue:md}`EngineSize` component which computes the wetted area of nacelle. This function has infinity derivatives at the two ends. We use two cubic polynomials to smooth it.\n", + "- {glue:md}`BWBEngineSizeGroup`: {glue:md}`PercentNotInFuselage` + {glue:md}`EngineSize`. For Tube+Wing aircraft, we assume that engines are not buried into fuselage and hence {glue:md}`EngineSize` is good enough. But this feature can be extended to conventional aircraft.\n", + "- {glue:md}`ExposedWing`: Computation of exposed wing area. This is useful for BWB, but is available to tube+wing model too. For {glue:md}`Aircraft.Wing.VERTICAL_MOUNT_LOCATION` in the range (0, 1), the function has infinity derivatives at the two ends. We use two cubic polynomials to smooth it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c6fc56a", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft, Mission\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.mass.gasp_based.design_load import (\n", + " BWBLoadSpeeds,\n", + " BWBLoadFactors,\n", + " LoadSpeeds,\n", + " LoadFactors,\n", + " BWBDesignLoadGroup,\n", + ")\n", + "from aviary.subsystems.geometry.gasp_based.wing import ExposedWing\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Design.WING_LOADING), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Design.GROSS_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.EXPOSED_AREA), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(BWBLoadSpeeds), md_code=True)\n", + "glue_variable(get_variable_name(BWBLoadFactors), md_code=True)\n", + "glue_variable(get_variable_name(LoadSpeeds), md_code=True)\n", + "glue_variable(get_variable_name(LoadFactors), md_code=True)\n", + "glue_variable(get_variable_name(BWBDesignLoadGroup), md_code=True)\n", + "glue_variable(get_variable_name(ExposedWing), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "4e5d3844", + "metadata": {}, + "source": [ + "## BWB mass subsystem\n", + "\n", + "- For design load of a BWB airctaft, variable {glue:md}`Aircraft.Design.WING_LOADING` is replaced by {glue:md}`Mission.Design.GROSS_MASS` over {glue:md}`Aircraft.Wing.EXPOSED_AREA`. As a result, {glue:md}`BWBLoadSpeeds` and {glue:md}`BWBLoadFactors` components replace {glue:md}`LoadSpeeds` and {glue:md}`LoadFactors`. A new group {glue:md}`BWBDesignLoadGroup` is created to include these two new components.\n", + "- Aviary engine geometry uses different empirical equation. In GASP, the sizing relation is based on aircraft gross weight and the number of engines. For BWB, we adopt GASP implementation. We also allow the engines that are partially buried into the fuselage. This implementation can be easily modified to apply to conventional aircraft." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d9bb373", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import (\n", + " EquipAndUsefulLoadMassGroup,\n", + " EquipMassPartialSum,\n", + " UsefulLoadMass,\n", + " BWBACMass,\n", + " BWBFurnishingMass,\n", + ")\n", + "\n", + "glue_variable(get_variable_name(EquipAndUsefulLoadMassGroup), md_code=True)\n", + "glue_variable(get_variable_name(EquipMassPartialSum), md_code=True)\n", + "glue_variable(get_variable_name(UsefulLoadMass), md_code=True)\n", + "glue_variable(get_variable_name(BWBACMass), md_code=True)\n", + "glue_variable(get_variable_name(BWBFurnishingMass), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.APU.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Avionics.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.AntiIcing.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Furnishings.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.EMERGENCY_EQUIPMENT_MASS), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "8d5ec109", + "metadata": {}, + "source": [ + "### Equip And Useful Load\n", + "\n", + " - {glue:md}`EquipAndUsefulLoadMassGroup` includes the computations of 19 items. Ideally, each of them should be done in its own component and one group has them all. This is a long time goal. For now, it is separated to two components {glue:md}`EquipMassPartialSum` and {glue:md}`UsefulLoadMass`. The air conditioning and furnishing masses are already singled out because they need to be modified for BWB.\n", + " - A new variable {glue:md}`Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER` is added which corresponds to `CW(15)` in GASP. Its value is different for conventional aircraft and BWB.\n", + " - Two new components {glue:md}`BWBACMass` and {glue:md}`BWBFurnishingMass` are added to `equipment_and_useful_load.py`.\n", + " - **Note:** GASP Fortran code has new updates that are not included in Aviary. We've updated Aviary for furnishing mass but other masses need to be checked.\n", + " - **Note:** {glue:md}`EquipMassPartialSum` has implementation errors for the computations of {glue:md}`Aircraft.APU.MASS`, {glue:md}`Aircraft.Avionics.MASS`, {glue:md}`Aircraft.AntiIcing.MASS`, {glue:md}`Aircraft.Furnishings.MASS`, and {glue:md}`Aircraft.Design.EMERGENCY_EQUIPMENT_MASS`. As a result, Aviary always uses user provided masses (not empirical formulas). We should use Aviary's feature of `overriding` to override those variables." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f78bf945", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.mass.gasp_based.wing import (\n", + " WingMassSolve,\n", + " BWBWingMassSolve,\n", + " BWBWingMassGroup,\n", + " WingMassTotal,\n", + ")\n", + "from aviary.subsystems.geometry.gasp_based.wing import (\n", + " WingFoldArea,\n", + " WingFoldVolume,\n", + " BWBWingFoldVolume,\n", + " BWBWingGroup,\n", + " BWBWingVolume,\n", + " WingParameters,\n", + " WingVolume,\n", + ")\n", + "\n", + "glue_variable(get_variable_name(WingMassSolve), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingMassSolve), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingMassGroup), md_code=True)\n", + "glue_variable(get_variable_name(WingMassTotal), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingVolume), md_code=True)\n", + "glue_variable(get_variable_name(WingFoldArea), md_code=True)\n", + "glue_variable(get_variable_name(WingFoldVolume), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingFoldVolume), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingGroup), md_code=True)\n", + "glue_variable(get_variable_name(WingParameters), md_code=True)\n", + "glue_variable(get_variable_name(WingVolume), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.SPAN), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.AVG_DIAMETER), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.FOLDING_AREA), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "f2d65f4d", + "metadata": {}, + "source": [ + "### Wing Mass Model\n", + "\n", + " - For wing mass of BWB aircraft, variable {glue:md}`Aircraft.Wing.SPAN` has to deduct cabin width (i.e. {glue:md}`Aircraft.Fuselage.AVG_DIAMETER`). As a result, {glue:md}`WingMassSolve` component is replaced by {glue:md}`BWBWingMassSolve` component. {glue:md}`BWBWingMassGroup` is created to pair {glue:md}`BWBWingMassSolve` and {glue:md}`WingMassTotal`.\n", + " - In `geometry/gasp_based/wing.py`, {glue:md}`Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX` is moved out of {glue:md}`WingParameters` class. In stead, a class {glue:md}`WingVolume` is created to compute {glue:md}`Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX`. For BWB, another component {glue:md}`BWBWingVolume` is created for the same purpose. The algorithm is quite different for BWB.\n", + " - In `geometry/gasp_based/wing.py`, there are two components related to wing fold: {glue:md}`WingFoldArea` and {glue:md}`WingFoldVolume`. The first computes {glue:md}`Aircraft.Wing.FOLDING_AREA` and the second computes {glue:md}`Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX`. For BWB, another class {glue:md}`BWBWingFoldVolume` is created to do the same job. Note that for BWB, {glue:md}`BWBWingFoldVolume` uses the result in {glue:md}`BWBWingVolume`.\n", + " - A {glue:md}`BWBWingGroup` is created to put all these pieces together. \n", + " - Unit tests are added to make sure that the Aviary result is the same as GASP model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8cc16a1f", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft, Mission\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.mass.gasp_based.fuel import (\n", + " BWBFuselageMass,\n", + " FuselageMass,\n", + " StructMass,\n", + " BodyTankCalculations,\n", + " FuelMassGroup,\n", + ")\n", + "\n", + "glue_variable(get_variable_name(BWBFuselageMass), md_code=True)\n", + "glue_variable(get_variable_name(FuselageMass), md_code=True)\n", + "glue_variable(get_variable_name(StructMass), md_code=True)\n", + "glue_variable(get_variable_name(BodyTankCalculations), md_code=True)\n", + "glue_variable(get_variable_name(FuelMassGroup), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Mission.Summary.FUEL_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Summary.TOTAL_FUEL_MASS), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Design.FIXED_USEFUL_LOAD), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.HIGH_LIFT_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuel.FUEL_SYSTEM_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.STRUCTURE_MASS), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Summary.FUEL_MASS_REQUIRED), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Propulsion.MASS), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuel.TOTAL_CAPACITY), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "59e51bab", + "metadata": {}, + "source": [ + "### Fuel Model\n", + "\n", + " - {glue:md}`FuelMassGroup` groups all fuel related components. In case of BWB, {glue:md}`BWBFuselageMass` is in place of {glue:md}`FuselageMass`. This group has a nonlinear solver. In order for it to converge, one must provide good initial guesses for the inputs. Otherwise, it may claim that convergence is reached but gives rise to a strange solution.\n", + " - The computation in {glue:md}`BodyTankCalculations` component can not be matched in GASP Fortran code exactly. It is possible that `extra_fuel_volume` becomes negative. We added code to make sure that it is always positive.\n", + " - For fuselage mass of BWB aircraft, the empirical weight equation is quite different from conventional aircraft. It was computed in `FuselageAndStructMass` component. This component had two parts: fuselage mass and structural mass. In order to reuse the code for structural mass, this component is split into two components: {glue:md}`FuselageMass` and {glue:md}`StructMass`. For BWB, {glue:md}`FuselageMass` is replaced by {glue:md}`BWBFuselageMass`.\n", + " - **Note:** The historic name of {glue:md}`Mission.Summary.FUEL_MASS_REQUIRED` is `INGASP.WFAREQ`, but `WFAREQ` includes fuel margin in GASP while {glue:md}`Mission.Summary.FUEL_MASS_REQUIRED` doesn't. The historic name of {glue:md}`Mission.Summary.TOTAL_FUEL_MASS` is `INGASP.WFA`, but does not include fuel margin in GASP while {glue:md}`Mission.Summary.FUEL_MASS_REQUIRED` does.\n", + " - **Note:** GASP Fortran code has features that are not implemented in Aviary (e.g. tail boom support, tip tank weight, fuselage acoustic treatment, pylon, acoustic treatment).\n", + "\n", + "- Comparison to GASP model\n", + "\n", + "| Aviary |     | GASP |     | Observation |\n", + "| ------- | ------- | ------- | -------- | ------------- |\n", + "| {glue:md}`Aircraft.Design.FIXED_USEFUL_LOAD` | 5972 | WFUL | 5775 | different unit weight of pilots and attendents |\n", + "| {glue:md}`Aircraft.Wing.HIGH_LIFT_MASS` | 972 | WHLDEV | 974 | In GASP, wing loading is a variable, but in Aviary, it is a constant |\n", + "| {glue:md}`Aircraft.Fuel.FUEL_SYSTEM_MASS` | 1316 | WFSS | 1281 | the mass in GASP is computed after engine sizing. |\n", + "| {glue:md}`Aircraft.Design.STRUCTURE_MASS` | 44471 | WST | 45623 | the mass in GASP is computed after engine sizing. |\n", + "| {glue:md}`Mission.Summary.FUEL_MASS` | 34188 | WFADES | 33268 | The mass in GASP is computed after engine sizing. |\n", + "| {glue:md}`Aircraft.Propulsion.MASS` | 8628 | WP | 8592 | the mass in GASP is computed after engine sizing. |\n", + "| {glue:md}`Aircraft.Fuel.TOTAL_CAPACITY` | 38068 | WFAMAX | 33268 | The mass in GASP is computed after engine sizing. |\n", + "| {glue:md}`Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS` | 1687 | WPES | the mass in GASP is computed after engine sizing. |\n", + "| {glue:md}`Mission.Summary.FUEL_MASS_REQUIRED` | 34188 | WFAREQ | 36595 | Aviary does not include margin. |\n", + "| | | | |\n", + "\n", + "Because most of the variables match pretty well. We show those with significant differences. As we see, most differences are due to the fact that GASP computes the fuel masses after engine sizing.\n", + "\n", + "The fuel computation is a nonlinear system of equations. A simplied XDSM diagram is shown below:\n", + "\n", + "![GASP based fuel mass computation](images/gasp_bwb_fuel_mass.png)\n", + "\n", + "A Newton solver is applied until {glue:md}`Mission.Summary.FUEL_MASS`, `wingfuel_mass_min` and {glue:md}`Aircraft.Fuel.TOTAL_CAPACITY` are converged.\n", + "\n", + "For conventional aircraft, {glue:md}`BWBFuselageMass` is replaced by {glue:md}`FuselageMass`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f53d372", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.utils.doctape import get_all_non_aviary_names, get_variable_name, glue_variable\n", + "from aviary.subsystems.aerodynamics.gasp_based.gaspaero import (\n", + " BWBBodyLiftCurveSlope,\n", + " BWBFormFactorAndSIWB,\n", + " BWBAeroSetup,\n", + " BWBLiftCoeff,\n", + " BWBLiftCoeffClean,\n", + " AeroGeom,\n", + " Xlifts,\n", + ")\n", + "from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces\n", + "from aviary.subsystems.aerodynamics.gasp_based.gaspaero import CruiseAero, LowSpeedAero\n", + "from aviary.subsystems.aerodynamics.gasp_based.table_based import TabularCruiseAero\n", + "\n", + "glue_variable(get_variable_name(BWBBodyLiftCurveSlope), md_code=True)\n", + "glue_variable(get_variable_name(BWBFormFactorAndSIWB), md_code=True)\n", + "glue_variable(get_variable_name(BWBAeroSetup), md_code=True)\n", + "glue_variable(get_variable_name(BWBLiftCoeff), md_code=True)\n", + "glue_variable(get_variable_name(BWBLiftCoeffClean), md_code=True)\n", + "glue_variable(get_variable_name(CruiseAero), md_code=True)\n", + "glue_variable(get_variable_name(LowSpeedAero), md_code=True)\n", + "glue_variable(get_variable_name(AeroGeom), md_code=True)\n", + "glue_variable(get_variable_name(TabularCruiseAero), md_code=True)\n", + "\n", + "lift_curve_slope, lift_ratio = get_all_non_aviary_names(Xlifts, include_in_out='out')\n", + "glue_variable('lift_curve_slope', lift_curve_slope, md_code=False)\n", + "glue_variable('lift_ratio', lift_ratio, md_code=False)\n", + "sa1, sa2, sa3, sa4, sa5, sa6, sa7, cf = get_all_non_aviary_names(AeroGeom, include_in_out='out')\n", + "glue_variable('SA1', sa1, md_code=False)\n", + "glue_variable('SA2', sa2, md_code=False)\n", + "glue_variable('SA3', sa3, md_code=False)\n", + "glue_variable('SA4', sa4, md_code=False)\n", + "glue_variable('SA5', sa5, md_code=False)\n", + "glue_variable('SA6', sa6, md_code=False)\n", + "glue_variable('SA7', sa7, md_code=False)\n", + "glue_variable('cf', cf, md_code=False)\n", + "[cl, cd] = get_all_non_aviary_names(AeroForces, include_in_out='in')\n", + "glue_variable('CL', cl, md_code=False)\n", + "glue_variable('CD', cd, md_code=False)" + ] + }, + { + "cell_type": "markdown", + "id": "55356baa", + "metadata": {}, + "source": [ + "## BWB aerodynamics\n", + "\n", + "This feature implements GASP aerodynamics subsystems for BWB aircraft. Five new components are added:\n", + "\n", + "- {glue:md}`BWBBodyLiftCurveSlope`\n", + "- {glue:md}`BWBFormFactorAndSIWB`\n", + "- {glue:md}`BWBAeroSetup`\n", + "- {glue:md}`BWBLiftCoeff`\n", + "- {glue:md}`BWBLiftCoeffClean`\n", + "\n", + "Two group components {glue:md}`CruiseAero` and {glue:md}`LowSpeedAero` are configured for BWB as an option (default to conventional aircraft).\n", + "\n", + "In GASP, friction due to nacelle is removed from the computation of `SA5`. Instead, it is computed separately and is added in the drag computation. The Aviary implementation is not the same.\n", + "\n", + "`alpha_stall` and `CL_max` are computed based on wing only for now. We expect that they will be updated in the future.\n", + "\n", + "Table based aerodynamics is still available to BWB as long as users provide aerodynamics tables. A sample cruise aero table for BWB is available and an example using {glue:md}`TabularCruiseAero` is provided.\n", + "\n", + "### Comparison of `BWBAeroSetup` with GASP\n", + "\n", + "| Variables | GASP | Variables | Aviary |\n", + "| ---------- | ------ | ------- | ------- |\n", + "| CLAW | 4.63868 | {glue:md}`lift_curve_slope` | 4.63868 |\n", + "| BARL | -0.14081 | {glue:md}`lift_ratio` | -0.14081 |\n", + "| CFIN | 0.002836 | {glue:md}`cf` | 0.002836 |\n", + "| SA1 | 0.81401 | {glue:md}`SA1` | 0.80832 |\n", + "| SA2 | -0.15743 | {glue:md}`SA2` | -0.13651 |\n", + "| SA3 | 0.033989 | {glue:md}`SA3` | 0.033989 |\n", + "| SA4 | 0.10197 | {glue:md}`SA4` | 0.10197 |\n", + "| SA5 | 0.004464 | {glue:md}`SA5` | 0.009628 |\n", + "| SA6 | 2.23877 | {glue:md}`SA6` | 2.09277 |\n", + "| SA7 | 0.034136 | {glue:md}`SA7` | 0.040498 |\n", + "\n", + "The differences are due to several reasons:\n", + "\n", + "- GASP has different coefficients of friction for different part of an aircraft. For this purpose, several new parameters (aero calibration factors) are added. Aviary has one single coefficient {glue:md}`cf` (an output from {glue:md}`AeroGeom` component)\n", + "- GASP has several factors that are included in the computation of friction (e.g. winglet, tip tank, excrescence) but not in Aviary.\n", + "- GASP excludes frictions from nacelle in {glue:md}`SA5`. Nacelle friction is done in engine computation and is added in drag computation. But in Aviary, nacelle friction is included in {glue:md}`SA5` and not in drag computation.\n", + "\n", + "### Comparison of `CruiseAero` with GASP\n", + "\n", + "| Variables | GASP | Variables | Aviary |\n", + "| ---------- | ------ | ------- | ------- |\n", + "| CLTOT | 0.41069 | {glue:md}`CL` | 0.41067 |\n", + "| CD | 0.014738 | {glue:md}`CD` | 0.022509 |\n", + "| CL/CD | 27.86518 | L/D | 18.24451 |\n", + "\n", + "As we see, `CL` matches closely but `CD` doesn't. This is because the differences in {glue:md}`BWBAeroSetup` as we discussed above.\n", + "\n", + "### Comparison of `LowSpeedAero` with GASP\n", + "\n", + "| Variables (Takeoff) | CL (GASP/Aviary) | CD (GASP/Aviary)| CL/CD (GASP/Aviary) |\n", + "| --------------- | ----------------- | ------------------- | ----------------------- |\n", + "| α = -2.0 | 0.07507 / 0.05787 | 0.01853 / 0.02565 | 4.05136 / 3.307513 |\n", + "| α = 0.0 | 0.23964 / 0.21906 | 0.01866 / 0.02592 | 12.84433 / 9,49165 |\n", + "| α = 2.0 | 0.40422 / 0.407231 | 0.02070 / 0.02844 | 20.74018 / 16.22583 |\n", + "\n", + "| Variables (Landing) | CL (GASP/Aviary) | CD (GASP/Aviary)| CL/CD (GASP/Aviary) |\n", + "| --------------- | ----------------- | ------------------- | ----------------------- |\n", + "| α = -2.0 | 0.18551 / 0.19824 | 0.02299 / 0.02962 | 8.06918 / 6.69194 |\n", + "| α = 0.0 | 0.35009 / 0.35944 | 0.02292 / 0.02970 | 15.27225 / 12.10145 |\n", + "| α = 2.0 | 0.51467 / 0.52062 | 0.02482 / 0.03209 | 20.74018 / 16.22583 |\n", + "\n", + "As we see, `CL` matches closely but `CD` doesn't. This is because the differences in {glue:md}`BWBAeroSetup`.\n", + "\n", + "## Missing features in Aviary\n", + "\n", + "In addition to the missing fetures, there are other features in GASP that are not implemented in Aviary.\n", + "\n", + "- GASP computes maximum CL for cruise, take-off, and landing phases but not in Aviary.\n", + "- GASP computes lift curve slope (i.e. the derivative of the Lift Coeff w.r.t. Alpha), named `CLATOT`. \n", + "- GASP computes stall alpha from the wings. For BWB, this is not sufficient. Both GASP and Aviary should enhance their models.\n", + "- GASP computes excrescence drag.\n", + "- Drag coefficients SA3 and SA4 are computed in Aviary but are not used.\n", + "- Aviary does not have tail boom support.\n", + "- Aviary does not have winglet geometry.\n", + "- In GASP, a pilot weight is 170 lb and in Aviary it is 198 lb. In GASP, each attendant weights 130 lb and in Aviary it is 177 lb.\n", + "- GASP has fuselage acoustic treatment.\n", + "- GASP conputes tip tank weight.\n", + "- GASP allows canard configurations.\n" + ] + }, + { + "cell_type": "markdown", + "id": "ca8ccfe7", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/aviary/docs/theory_guide/images/gasp_bwb_fuel_mass.png b/aviary/docs/theory_guide/images/gasp_bwb_fuel_mass.png new file mode 100644 index 0000000000..325e51f06e Binary files /dev/null and b/aviary/docs/theory_guide/images/gasp_bwb_fuel_mass.png differ diff --git a/aviary/docs/theory_guide/images/turboprop_connections.png b/aviary/docs/theory_guide/images/turboprop_connections.png new file mode 100644 index 0000000000..8028833a0a Binary files /dev/null and b/aviary/docs/theory_guide/images/turboprop_connections.png differ diff --git a/aviary/docs/theory_guide/images/turboprop_promotions.png b/aviary/docs/theory_guide/images/turboprop_promotions.png new file mode 100644 index 0000000000..6eae79712b Binary files /dev/null and b/aviary/docs/theory_guide/images/turboprop_promotions.png differ diff --git a/aviary/docs/theory_guide/images/wing_fuel_capacity_derivation.png b/aviary/docs/theory_guide/images/wing_fuel_capacity_derivation.png new file mode 100644 index 0000000000..37fdea60f5 Binary files /dev/null and b/aviary/docs/theory_guide/images/wing_fuel_capacity_derivation.png differ diff --git a/aviary/docs/theory_guide/intro.ipynb b/aviary/docs/theory_guide/intro.ipynb index 396011377d..c5212733b1 100644 --- a/aviary/docs/theory_guide/intro.ipynb +++ b/aviary/docs/theory_guide/intro.ipynb @@ -1,8 +1,27 @@ { "cells": [ { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "glue_variable('height_energy', av.EquationsOfMotion.HEIGHT_ENERGY.value, md_code=False)\n", + "glue_variable('2DOF', av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value, md_code=False)\n", + "glue_variable('solved_2DOF', av.EquationsOfMotion.SOLVED_2DOF.value, md_code=False)" + ] + }, + { "metadata": {}, + "cell_type": "markdown", "source": [ "# Overview of Aviary Functionality\n", "\n", @@ -23,7 +42,7 @@ "The [mass](./mass) calculations that Aviary provides are similar to the geometry calculations. They use empirical equations based on the traditional tube-and-wing aircraft design, and work well for this case but break down in the case of unconventional configurations. For more novel aircraft configurations the Aviary team recommends implementing an external subsystem.\n", "\n", "## Mission Analysis\n", - "The [mission analysis](./mission) calculations that Aviary provides are broader in scope than the other disciplines. Aviary provides two different types of equations of motion (2DOF and height energy), and also provides two different ways to integrate these EOMs (collocation and analytic shooting). The intended capability is that either EOM can be used with either integration technique.\n", + "The [mission analysis](./mission) calculations that Aviary provides are broader in scope than the other disciplines. Aviary provides two different types of equations of motion ({glue:md}`2DOF` and {glue:md}`height_energy`) and uses collocation to integrate them.\n", "\n", "\n", "The second aspect of Aviary, instead of being computational like the first, is about subsystem integration. In addition to the capability to build purely Aviary-based aircraft models, Aviary provides the ability to build mixed-origin aircraft models, which are aircraft models consisting partially or entirely of external user-provided subsystems. In the case of a mixed-origin model, instead of just selecting existing Aviary subsystems and combining them into an aircraft model, the user also provides the Aviary code with their own subsystems (these could be pre-existing codes such as [pyCycle](https://github.com/OpenMDAO/pyCycle), or they could be new subsystems the user has built themselves). An example of a mixed-origin model is the [OpenAeroStruct example case](../examples/OAS_subsystem). In this example, the built-in Aviary subsystem for mass is partially replaced by external subsystems.\n", @@ -47,8 +66,22 @@ } ], "metadata": { + "kernelspec": { + "display_name": "av1", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" } }, "nbformat": 4, diff --git a/aviary/docs/theory_guide/mass.md b/aviary/docs/theory_guide/mass.md index 91f1211165..15e234b1c8 100644 --- a/aviary/docs/theory_guide/mass.md +++ b/aviary/docs/theory_guide/mass.md @@ -6,3 +6,45 @@ This includes the empty weight, fuel weight, payload weight, and other mass prop ```{note} This section is under further development. ``` + +## FLOPS Based Mass Subsystem + +### Fuel_Capacity + +The Fuel Capacity Group contains 4 subsystems: + +1. Wing Fuel Capacity + + There are 2 different relationships that can be used, and Aviary will switch between them based on the value of the Aircraft.Fuel.WING_REF_CAPACITY_TERM_A parameter. + + If Aircraft.Fuel.WING_REF_CAPACITY_TERM_A > 0: + + Aviary allows the user to specify their own relationship for fuel capacity as a polynomial function of the difference in wing area to some reference area. This is for compatability to legacy FLOPS, but in reality an aviary user will probably write their own OpenMDAO component for calculating wing fuel capacity rather than fitting their own coefficients to an equation of the form: + + Wing Fuel Capacity = Wing_Reference_Capacity * (coeff_a * Area Delta^1.5 + coeff_b * Area_Delta) + + Where coeff_a and coeff_b are user specified (Aircraft.Fuel.WING_REF_CAPACITY_TERM_A, Aircraft.Fuel.WING_REF_CAPACITY_TERM_B) + + Where Area_Delta = Aircraft.Wing.AREA - Aircraft.Fuel.WING_REF_CAPACITY_AREA (user specified) + + Else (default): + + Aviary assumes that the wing volume can be approximated as a rectangular based pyramid, and that the available volume for fuel is a user specified fraction of this theoretcial volume (Aircraft.Fuel.WING_FUEL_FRACTION). The derivation of Aviary's theoretical volume calculation is included below: + + ![wing_fuel_capacity_derivation](images/wing_fuel_capacity_derivation.png) + + Aviary then converts the volume to a capacity (lbm) using the user specified fuel density (Aircraft.Fuel.DENSITY). + +2. Fuselage Fuel Capacity + + Fusleage Fuel Capacity = Total Fuel Capacity - Wing Fuel Capacity + +3. Auxiliary Fuel capacity + + Auxiliary Fuel Capacity = Total Fuel Capacity - Wing Fuel Capacity - Fuselage Fuel Capacity + +4. Total Fuel Capacity + + Total Fuel Capacity = Wing Fuel Capacity + Fuselage Fuel Capacity + Auxiliary Fuel Capacity + +It is possible for Aviary to calculate negative fuel capacities depending on user overrides and the input wing geometry. These situations are not currently flagged to the user. diff --git a/aviary/docs/theory_guide/merging_syntax.ipynb b/aviary/docs/theory_guide/merging_syntax.ipynb index 13a98ed3e9..ac7647fcf2 100644 --- a/aviary/docs/theory_guide/merging_syntax.ipynb +++ b/aviary/docs/theory_guide/merging_syntax.ipynb @@ -48,8 +48,8 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.merge_hierarchies import merge_hierarchies;\n", - "from aviary.utils.merge_variable_metadata import merge_meta_data;" + "from aviary.utils.merge_hierarchies import merge_hierarchies\n", + "from aviary.utils.merge_variable_metadata import merge_meta_data" ] } ], diff --git a/aviary/docs/theory_guide/propulsion.ipynb b/aviary/docs/theory_guide/propulsion.ipynb index a6afb686a8..bf2b8425ae 100644 --- a/aviary/docs/theory_guide/propulsion.ipynb +++ b/aviary/docs/theory_guide/propulsion.ipynb @@ -1,5 +1,28 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.subsystems.propulsion.engine_deck import EngineDeck, EngineScaling\n", + "from aviary.subsystems.propulsion.engine_model import EngineModel\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "glue_variable(EngineModel.__name__ + 's', md_code=True, display=True)\n", + "glue_variable(EngineDeck.__name__ + 's', md_code=True, display=True)\n", + "\n", + "glue_variable(EngineModel.__name__, md_code=True)\n", + "glue_variable(EngineDeck.__name__, md_code=True)\n", + "glue_variable(EngineScaling.__name__, md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -8,9 +31,9 @@ "\n", "Propulsion is unique among the core Aviary subsystems for its level of flexibility and compatibility with custom and external code. Aviary supports an arbitrary number of engines on a vehicle which can be modeled using the built-in method (engine decks) alongside any user-provided models.\n", "\n", - "Aviary propulsion can be thought of as having two levels: system-level propulsion and individual engines. The top-level propulsion subsystem is model-agnostic and exists to organize engines and sum relevant outputs into system-level totals that other subsystems can use. Modeling of each type of engine on the aircraft is handled with `EngineModels`.\n", + "Aviary propulsion can be thought of as having two levels: system-level propulsion and individual engines. The top-level propulsion subsystem is model-agnostic and exists to organize engines so that the appropriate analyses are called during pre-, during, and post-mission analysis, and to sum relevant outputs into system-level totals that other subsystems can use. Modeling of each type of engine on the aircraft is handled with a class called `EngineModels`. This class inherits from the `SubsystemBuilderBase`, with a few minor additions to make defining engines easier.\n", "\n", - "This page details how the core propulsion subsystem works when using `EngineDecks`. External propulsion subsystems (when wrapped by an `EngineModel`) are treated the same way by Aviary, but the details of what is computed and where will differ by model." + "This page details how the core propulsion subsystem works, focusing on using `EngineDecks`. External propulsion subsystems (when wrapped into an `EngineModel`) are treated the same way by Aviary, but the details of what is computed and where will differ by model." ] }, { @@ -20,18 +43,18 @@ "## Preprocessing\n", "\n", "Before analysis is performed, Aviary's propulsion preprocessor function is used to ensure input consistency. These consistency checks serve two functions.\n", - "First, the inputs and options used to initialize individual `EngineModels` and the vehicle-level variable hierarchy need to match. The vehicle-level hierarchy's engine-related inputs must be vectorized to include information for all individual engines being modeled.\n", + "First, the inputs and options used to initialize individual {glue:md}`EngineModels` and the vehicle-level variable hierarchy need to match. The vehicle-level hierarchy's engine-related inputs must be vectorized to include information for all individual engines being modeled.\n", "Second, a select number of inputs are checked for physical consistency with each other. For example, the sum of wing- and fuselage-mounted engines must match the total number of engines on the vehicle.\n", "\n", - "Because engine-related variables are expected to be vectorized with a value for each unique `EngineModel`, if a variable is defined for one engine, it must also be defined for all others so a vector of consistent size can be created. The propulsion preprocessor handles this automatically. Values of variables defined in an `EngineModel` are given highest priority and always used if available. Otherwise, if a value for that variable is present in the vehicle-level variable hierarchy, it is treated as a 'user-provided default' value to assign to any engine that doesn't explicitly define it. Finally, if neither of these values can be found, the default value pulled from Aviary variable metadata is used.\n", + "Because engine-related variables are expected to be vectorized with a value for each unique {glue:md}`EngineModel`, if a variable is defined for one engine, it must also be defined for all others so a vector of consistent size can be created. The propulsion preprocessor handles this automatically. Values of variables defined in an {glue:md}`EngineModel` are given highest priority and always used if available. Otherwise, if a value for that variable is present in the vehicle-level variable hierarchy, it is treated as a 'user-provided default' value to assign to any engine that doesn't explicitly define it. Finally, if neither of these values can be found, the default value pulled from Aviary variable metadata is used.\n", "\n", - "`EngineModels` objects have input preprocessing steps performed during initialization to handle internal consistency of inputs and options within that individual engine.\n", + "{glue:md}`EngineModels` objects have input preprocessing steps performed during initialization to handle internal consistency of inputs and options within that individual engine.\n", "\n", "## Pre-Mission Analysis\n", "\n", - "Aviary propulsion organizes all pre-mission analysis into a propulsion group that is added to the 'pre_mission_analysis' group. Pre-mission propulsion calls the pre-mission builders for each provided `EngineModel`, adding each created subsystem to the propulsion group. Aviary also includes a component which calculates system-level SLS (sea-level static) thrust and another component which calculates distributed propulsion factors based on total thrust and total number of engines. These distributed factors are used by some Aviary core mass estimation components.\n", + "Aviary propulsion organizes all pre-mission analysis into a propulsion group that is added to the 'pre_mission_analysis' group. Pre-mission propulsion calls the pre-mission builders for each provided {glue:md}`EngineModel`, adding each created subsystem to the propulsion group. Aviary also includes a component which calculates system-level SLS (sea-level static) thrust and another component which calculates distributed propulsion factors based on total thrust and total number of engines. These distributed factors are used by some Aviary core mass estimation components.\n", "\n", - "The `EngineDeck` pre-mission builder includes a `EngineScaling` component that calculates a performance scaling factor based on the percent difference in desired target thrust versus the unscaled SLS thrust present in the data file." + "The {glue:md}`EngineDeck` pre-mission builder includes a {glue:md}`EngineScaling` component that calculates a performance scaling factor based on the percent difference in desired target thrust versus the unscaled SLS thrust present in the data file." ] }, { @@ -45,16 +68,17 @@ "outputs": [], "source": [ "# Testing Cell\n", + "import aviary.api as av\n", "from aviary.subsystems.propulsion.engine_deck import EngineDeck, EngineScaling\n", "from aviary.utils.aviary_values import AviaryValues\n", - "import aviary.api as av\n", - "filename = 'models/engines/turbofan_28k.deck'\n", + "\n", + "filename = 'models/engines/turbofan_28k.csv'\n", "\n", "options = AviaryValues()\n", "options.set_val(av.Aircraft.Engine.DATA_FILE, av.get_path(filename))\n", "options.set_val(av.Aircraft.Engine.INTERPOLATION_METHOD, 'slinear')\n", "\n", - "engine_group = EngineDeck(options=options).build_mission(1,options)\n", + "engine_group = EngineDeck(options=options).build_mission(1, options)\n", "scaling_subsys = engine_group._get_subsystem('engine_scaling')\n", "if not isinstance(scaling_subsys, EngineScaling):\n", " raise TypeError(f'scaling_subsys is {type(scaling_subsys)}, but should be {EngineScaling}')" @@ -66,22 +90,22 @@ "source": [ "## Mission Analysis\n", "\n", - "Similar to pre-mission, during mission analysis Aviary propulsion creates a group that calls the mission builder for each `EngineModel`. Engine performance data is [muxed](https://openmdao.org/newdocs/versions/latest/features/building_blocks/components/mux_comp.html) together and then summed into vehicle-level totals using an additional component. Both single engine and vehicle-level propulsion performance is promoted within the propulsion group although only vehicle-level totals are used by other Aviary core subsystems.\n", + "Similar to pre-mission, during mission analysis Aviary propulsion creates a group that calls the mission builder for each {glue:md}`EngineModel`. Engine performance data is [muxed](https://openmdao.org/newdocs/versions/latest/features/building_blocks/components/mux_comp.html) together and then summed into vehicle-level totals using an additional component. Both single engine and vehicle-level propulsion performance is promoted within the propulsion group although only vehicle-level totals are used by other Aviary core subsystems.\n", "\n", - "`EngineDeck` mission builders produce a more complicated group that interpolates and scales performance values based on flight condition. To provide maximum thrust conditions (as needed by the [energy-state approximation](energy-method)), a duplicate set of interpolation components are created and run at max throttle setting to always produce max thrust for a given flight condition. This performance data is then scaled with an additional component. Only the scaled data is exposed to the greater propulsion group. Unscaled engine data is not promoted outside that `EngineDeck's` mission group, and is therefore generally unavailable to other Aviary components.\n", + "{glue:md}`EngineDeck` mission builders produce a more complicated group that interpolates and scales performance values based on flight condition. To provide maximum thrust conditions (as needed by the [energy-state approximation](energy-method)), a duplicate set of interpolation components are created and run at max throttle setting to always produce max thrust for a given flight condition. This performance data is then scaled with an additional component. Only the scaled data is exposed to the greater propulsion group. Unscaled engine data is not promoted outside that {glue:md}`EngineDeck`'s mission group, and is therefore generally unavailable to other Aviary components.\n", "\n", "## Post-Mission Analysis\n", "\n", - "Aviary currently does not support post-mission propulsion analysis. A future update will include a propulsion-level group that iteratively calls `EngineModel` post-mission builders similar to how pre-mission is performed.\n", + "Post-mission is handled in the same way as pre-mission - the top-level propulsion group iteratively calls `EngineModel` post-mission builders and adds them to the `AviaryProblem's` 'post_mission_analysis' group\n", "\n", "## External Subsystems\n", - "Because the actual computation of propulsion-related variables is done within `EngineModels`, in most cases the propulsion subsystem builder does not need to be replaced when adding new propulsion analysis to Aviary." + "Because the actual computation of propulsion-related variables is done within {glue:md}`EngineModels`, in most cases the propulsion subsystem builder does not need to be replaced when adding new propulsion analysis to Aviary." ] } ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "av1", "language": "python", "name": "python3" }, @@ -95,7 +119,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/aviary/docs/theory_guide/turboprop.ipynb b/aviary/docs/theory_guide/turboprop.ipynb new file mode 100644 index 0000000000..d7daad6703 --- /dev/null +++ b/aviary/docs/theory_guide/turboprop.ipynb @@ -0,0 +1,61 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The Turboprop Model\n", + "The `TurbopropModel` is an advanced `EngineModel` included with Aviary to assist in modeling propeller-driven propulsion systems. The `TurbopropModel` functions like a container that houses and links together the individual components needed to model a propeller based engine.\n", + "\n", + "## Shaft Power Model\n", + "This section is a WIP\n", + "\n", + "## Gearbox Model\n", + "This section is a WIP\n", + "\n", + "## Propeller Model\n", + "If no custom propeller model is specified, the `TurbopropModel` uses the [Hamilton Standard](Hamilton Standard.md) methodology, or a propeller map if one is provided in `Aircraft.Engine.Propeller.DATA_FILE`. To pass a propeller map in-memory, you can use a `PropellerBuilder` to provide your propeller data.\n", + "\n", + "## Variable Aliasing\n", + "The `TurbopropModel` will automatically alias some variables to ensure proper connections between components and avoid conflicts. The first example of this is thrust. It is common for turboshaft engine models to include the (typically small) amount of thrust produced as a byproduct of shaft power production, sometimes referred to as \"tailpipe thrust\". Aviary engine models expect this value to be reported under `Dynamic.Vehicle.Propulsion.THRUST`, the same name expected for thrust produced by propellers. The `TurbopropModel` will alias thrust produced by the turboshaft engine to \"turboshaft_thrust\" and propeller-produced thrust to \"propeller_thrust\". These two variables are sent to a component that adds them together and outputs the total thrust as `Dynamic.Vehicle.Propulsion.THRUST`. The individual thrust components are not promoted outside the turboprop model group.\n", + "\n", + "Other aliasing descriptions WIP.\n", + "\n", + "## Model Connections\n", + "Each of the three models that are housed in a `TurbopropModel` are treated in a very generic way, with as few assumptions about their inputs, outputs, and analysis made as possible. This means that the user has great flexibility in replacing these models with a custom one, which is detailed later. Because it is possible (and ordinarily expected) that several of these models might have have identical variables, connections and promotions are handled very carefully. This is usually only a problem during mission analysis - for example, RPM is both an input *and* output of a gearbox model, and RPM might also be an output from a turboshaft as well as an input to a propeller. It is clear this is a messy situation, and must be handled in the order that power flows through the overall turboprop system.\n", + "\n", + "The most important thing to keep in mind is the `TurbopropModel` is just a special `EngineModel`, and during mission analysis only needs to communicate the very top-level information required to solve the vehicle equations of motions. Basically, the only things the vehicle physics cares about is energy consumption and thrust production. Therefore, we don't need to worry too much about promotions, just connections.\n", + "\n", + "There are several \"categories\" of variables that the `TurbopropModel` automatically handles when setting up the three models.\n", + "1. Inputs of a component that don't correspond with outputs of any other component. These are promoted to the top level of the turboprop, with one special type of exception that is connected instead.\n", + "2. Outputs of a component that don't correspond with inputs of any other component. These are also promoted to the top level of the turboprop\n", + "3. Variables that are outputs of one model, and inputs of another. These are directly connected, with one special type of exception that is promoted instead.\n", + "4. Variables that are duplicated in some way, such as RPM as an output for both a shaft power model *and* a gearbox model, and as an input for the gearbox model *and* the propeller model. These are connected using aliasing, with one special type of exception for outputs that are promoted instead.\n", + "\n", + "Variable categories 1 and 3 have special cases, which is if that variable appears in the list of variables vectorized by the `vectorize_propulsion` component of the [`PropulsionMission` group](https://github.com/OpenMDAO/Aviary/blob/main/aviary/subsystems/propulsion/propulsion_mision.py). These are the variables the propulsion subsystem is required to collect and summate for the vehicle flight physics. Some special handling is needed to prevent a \"circular\" connection loop. For example, \"shaft_horsepower\" might be an output of the shaft horsepower model, and an input to the propeller model. We can't just directly connect the two models because we need the higher-level propulsion system to access the \"shaft_horsepower\" value. We can accomplish this by promoting the output instead. But we can't similarly promote the input, because OpenMDAO will attempt to connect the vectorized \"shaft_horsepower\" output from `vectorize_propulsion` right back into the propeller model, which is a nonsensical loop that breaks the model. So in this case, we must connect the input instead.\n", + "This process is automated, so the end user will never even be aware of this happening, nor does a model maker need to worry about it when creating their models - it's completely fine to use these \"special\" variables as input or outputs of your own models.\n", + "\n", + "This all sounds quite complicated, but the core concept is straightforward and can be more easily explained as a diagram. We can visualize the turboprop, with the different variable connection types below:\n", + "\n", + "![](images/turboprop_promotions.png)\n", + "\n", + "In this diagram, the blue arrows represent connections while the orange arrows represent promotions (categories 1 and 2). We can see that each component has inputs and outputs that don't interact with the other models and are directly promoted (categories 1 and 2), while any variables that are shared between the models are connected (categories 3 and 4). When viewed in this way, it is clear that some categories are just special cases of others, or handle different edge cases for the same concept.\n", + "\n", + "Categories 1, 2, and 3 are easy to automate, and do not take any special consideration from the developer or user. Variables that are \"duplicates\", however, are impossible to resolve without setting some naming standards. This issue only appears with variables surrounding the gearbox, the only place where the same variable name could appear twice in the turboprop. Let's break down this scenario into a simplified, single variable example:\n", + "\n", + "![](images/turboprop_connections.png)\n", + "\n", + "Here we are looking at a generic variable \"_A_\" that appears in multiple components in a conflicting way - in a real turboprop, this might be something like RPM or shaft horsepower. It makes sense for the shaft horsepower model and the propeller model to directly use the name \"_A_\" for their output and input respectively. They weren't designed with the turboprop model in mind, and they shouldn't have to be. The gearbox, however, uses \"_A_\" as both and input and an output, but they can't use the same name in OpenMDAO! So Aviary expects the following convention in cases like this: the input side should use the variable name plus \"_\\_in_\" at the end, while the output side should use the variable name plus \"_\\_out_\" at the end. This avoids messy scenarios like trying to give unique names to each side of the component - we can't automate the connections if developers are using their own choice of name each time.\n", + "\n", + "Using this naming convention, the connections become much simpler - the `TurbopropModel` simply searches for the \"_\\_in_\" and \"_\\_out_\" flags at the end of variable names, and if it finds a valid match with the base variable name, it makes a connection using aliasing. The `TurbopropModel` checks the inputs and outputs of all models before making any connections or promotions, so we avoid directly connecting \"_A_\" between the shaft horsepower and propeller models, and accidentally skip the gearbox entirely." + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb index 80456bf57d..fd4cb32793 100644 --- a/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb +++ b/aviary/docs/user_guide/FLOPS_based_detailed_takeoff_and_landing.ipynb @@ -1,5 +1,37 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "262c6ac0", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "from aviary.mission.phase_builder_base import PhaseBuilderBase\n", + "from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder\n", + "from aviary.utils.aviary_values import AviaryValues\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "glue_variable(get_variable_name(AviaryValues), md_code=True)\n", + "glue_variable(get_variable_name(CoreAerodynamicsBuilder), md_code=True)\n", + "\n", + "# glue all arguments of function PhaseBuilderBase.__init__(self, name=None, meta_data=None, code_origin=None)\n", + "sigs = inspect.signature(PhaseBuilderBase)\n", + "parameters = sigs.parameters\n", + "for name, param in parameters.items():\n", + " glue_variable(name, md_code=True)\n", + " # print(f'Name: {name}, Default: {param.default}, Kind: {param.kind}')" + ] + }, { "cell_type": "markdown", "id": "01c83833", @@ -12,12 +44,12 @@ "```\n", "\n", "Aviary support of FLOPS based detailed takeoff and landing is implemented in terms of\n", - "user options, initial guesses, and different types of builders. User options and initial guesses are often collected in `AviaryValues` objects, which are then used to setup different builders. Builders are used to create analysis components. The builders for takeoff and landing can be separated into three general categories: aerodynamics, phases, and trajectories. The following sections describe which builders are associated with takeoff and landing and how to generally use them.\n", + "user options, initial guesses, and different types of builders. User options and initial guesses are often collected in {glue:md}`AviaryValues` objects, which are then used to setup different builders. Builders are used to create analysis components. The builders for takeoff and landing can be separated into three general categories: aerodynamics, phases, and trajectories. The following sections describe which builders are associated with takeoff and landing and how to generally use them.\n", "\n", "The following code excerpts were copied from Aviary validation data and benchmarks. For a\n", "more complete working example, with appropriate support for drivers, see the following\n", "files:\n", - "- [N3CC data set](https://github.com/OpenMDAO/Aviary/tree/main/aviary/models/N3CC/N3CC_data.py)\n", + "- [N3CC data set](https://github.com/OpenMDAO/Aviary/tree/main/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py)\n", "- [Balanced Field Length benchmark](https://github.com/OpenMDAO/Aviary/tree/main/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py)\n", "- [Detailed Landing benchmark](https://github.com/OpenMDAO/Aviary/tree/main/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py)\n", "- [Detailed Takeoff benchmark](https://github.com/OpenMDAO/Aviary/tree/main/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py)\n", @@ -25,11 +57,11 @@ "## Takeoff\n", "\n", "### Aerodynamics Builder\n", - "Both takeoff and landing are designed to use the FLOPS-derived `low_speed` aerodynamics method defined in the `CoreAerodynamicsBuilder`. The builder supports several options specified in a `subsystem_options` dictionary provided to the phase builder. The most important subsystem options are the three required sequences: `angles_of_attack`, `lift_coefficients`, and `drag_coefficients`. At least two values must be specified in `angles_of_attack`. For each value in `angles_of_attack`, there must be one dependent value at the corresponding index in each of `lift_coefficients` and `drag_coefficients`.\n", + "Both takeoff and landing are designed to use the FLOPS-derived `low_speed` aerodynamics method defined in the {glue:md}`CoreAerodynamicsBuilder`. The builder supports several options specified in a {glue:md}`subsystem_options` dictionary provided to the phase builder. The most important subsystem options are the three required sequences: `angles_of_attack`, `lift_coefficients`, and `drag_coefficients`. At least two values must be specified in `angles_of_attack`. For each value in `angles_of_attack`, there must be one dependent value at the corresponding index in each of `lift_coefficients` and `drag_coefficients`.\n", "\n", - "Once a `CoreAerodynamicsBuilder` object is created, it can be used to create a phase builder.\n", + "Once a {glue:md}`CoreAerodynamicsBuilder` object is created, it can be used to create a phase builder.\n", "The phase builder will pass the aerodynamics builder down to where it is needed to\n", - "create appropriate aerodynamics analysis components. A single `CoreAerodynamicsBuilder` object\n", + "create appropriate aerodynamics analysis components. A single {glue:md}`CoreAerodynamicsBuilder` object\n", "can be shared with different phase builders. Subsystem options can also often be shared by different phase builders. In most cases, values like `angles_of_attack`, `lift_coefficients`, `drag_coefficients`, and a few others are identical across all phases of takeoff/landing trajectory, even if other option values vary by phase." ] }, @@ -40,51 +72,80 @@ "metadata": {}, "outputs": [], "source": [ - "from aviary.api import Dynamic, Mission\n", - "\n", "import aviary.api as av\n", - "\n", - "from aviary.models.N3CC.N3CC_data import inputs\n", + "from aviary.api import Dynamic, Mission\n", + "from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import inputs\n", "from aviary.utils.preprocessors import preprocess_options\n", "\n", "aviary_options = inputs.deepcopy()\n", "\n", "# This builder can be used for both takeoff and landing phases\n", - "aero_builder = av.CoreAerodynamicsBuilder(\n", - " name='low_speed_aero',\n", - " code_origin=av.LegacyCode.FLOPS\n", - ")\n", - "\n", - "takeoff_subsystem_options = {'low_speed_aero': {\n", - " 'method': 'low_speed',\n", - " 'ground_altitude': 0., # units='m'\n", - " 'angles_of_attack': [\n", - " 0.0, 1.0, 2.0, 3.0, 4.0, 5.0,\n", - " 6.0, 7.0, 8.0, 9.0, 10.0, 11.0,\n", - " 12.0, 13.0, 14.0, 15.0], # units='deg'\n", - " 'lift_coefficients': [\n", - " 0.5178, 0.6, 0.75, 0.85, 0.95, 1.05,\n", - " 1.15, 1.25, 1.35, 1.5, 1.6, 1.7,\n", - " 1.8, 1.85, 1.9, 1.95],\n", - " 'drag_coefficients': [\n", - " 0.0674, 0.065, 0.065, 0.07, 0.072, 0.076,\n", - " 0.084, 0.09, 0.10, 0.11, 0.12, 0.13,\n", - " 0.15, 0.16, 0.18, 0.20],\n", - " 'lift_coefficient_factor': 1.,\n", - " 'drag_coefficient_factor': 1.}}\n", + "aero_builder = av.CoreAerodynamicsBuilder(name='low_speed_aero', code_origin=av.LegacyCode.FLOPS)\n", + "\n", + "# fmt: off\n", + "takeoff_subsystem_options = {\n", + " 'low_speed_aero': {\n", + " 'method': 'low_speed',\n", + " 'ground_altitude': 0.0, # units='m'\n", + " 'angles_of_attack': [\n", + " 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0,\n", + " ], # units='deg'\n", + " 'lift_coefficients': [\n", + " 0.5178, 0.6, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25,\n", + " 1.35, 1.5, 1.6, 1.7, 1.8, 1.85, 1.9, 1.95,\n", + " ],\n", + " 'drag_coefficients': [\n", + " 0.0674, 0.065, 0.065, 0.07, 0.072, 0.076, 0.084, 0.09,\n", + " 0.10, 0.11, 0.12, 0.13, 0.15, 0.16, 0.18, 0.20,\n", + " ],\n", + " 'lift_coefficient_factor': 1.0,\n", + " 'drag_coefficient_factor': 1.0,\n", + " }\n", + "}\n", + "# fmt: off\n", "\n", "# when using spoilers, add a few more options\n", - "takeoff_spoiler_subsystem_options = {'low_speed_aero': {\n", - " **takeoff_subsystem_options['low_speed_aero'],\n", - " 'use_spoilers': True,\n", - " 'spoiler_drag_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_DRAG_COEFFICIENT),\n", - " 'spoiler_lift_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_LIFT_COEFFICIENT)}}\n", + "takeoff_spoiler_subsystem_options = {\n", + " 'low_speed_aero': {\n", + " **takeoff_subsystem_options['low_speed_aero'],\n", + " 'use_spoilers': True,\n", + " 'spoiler_drag_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_DRAG_COEFFICIENT),\n", + " 'spoiler_lift_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_LIFT_COEFFICIENT),\n", + " }\n", + "}\n", "\n", "# We also need propulsion analysis for takeoff and landing. No additional configuration\n", "# is needed for this builder\n", - "engine = av.build_engine_deck(aviary_options)\n", - "preprocess_options(aviary_options, engine_models=engine)\n", - "prop_builder = av.CorePropulsionBuilder(engine_models=engine)" + "engines = [av.build_engine_deck(aviary_options)]\n", + "preprocess_options(aviary_options, engine_models=engines)\n", + "prop_builder = av.CorePropulsionBuilder(engine_models=engines)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2597f97e", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "import aviary.api as av\n", + "from aviary.mission.flops_based.phases.detailed_takeoff_phases import TakeoffTrajectory\n", + "from aviary.utils.doctape import get_class_names, glue_class_functions\n", + "\n", + "file_path = av.get_path('mission/flops_based/phases/detailed_takeoff_phases.py')\n", + "takeoff_class_names = get_class_names(file_path)\n", + "for class_name in takeoff_class_names:\n", + " glue_variable(class_name, md_code=True)\n", + "\n", + "# Get all functions of class TakeoffTrajectory\n", + "glue_class_functions(TakeoffTrajectory, current_glued_vars)" ] }, { @@ -95,40 +156,40 @@ "### Phase Builders\n", "There are eleven types of phase builders for takeoff. In general, the following phase\n", "builders are always required:\n", - "- `TakeoffBrakeReleaseToDecisionSpeed` : a phase builder for the first phase of takeoff,\n", + "- {glue:md}`TakeoffBrakeReleaseToDecisionSpeed` : a phase builder for the first phase of takeoff,\n", " from brake release to decision speed, the maximum speed at which takeoff can be safely\n", - " brought to full stop using zero thrust while braking;\n", - "- `TakeoffDecisionSpeedToRotate` : a phase builder for the second phase of takeoff, from\n", - " decision speed to rotation;\n", - "- `TakeoffRotateToLiftoff` : a phase builder for the third phase of takeoff, from\n", - " rotation to liftoff;\n", - "- `TakeoffLiftoffToObstacle` : a phase builder for the fourth phase of takeoff, from\n", + " brought to full stop using zero thrust while braking\n", + "- {glue:md}`TakeoffDecisionSpeedToRotate` : a phase builder for the second phase of takeoff, from\n", + " decision speed to rotation\n", + "- {glue:md}`TakeoffRotateToLiftoff` : a phase builder for the third phase of takeoff, from\n", + " rotation to liftoff\n", + "- {glue:md}`TakeoffLiftoffToObstacle` : a phase builder for the fourth phase of takeoff, from\n", " liftoff to clearing the required obstacle.\n", "\n", "The following phase builders are only required if acoustic calculations are required:\n", - "- `TakeoffObstacleToMicP2` : a phase builder for the fifth phase of takeoff, from\n", - " clearing the required obstacle to the P2 mic location;\n", - "- `TakeoffMicP2ToEngineCutback` : a phase builder for the sixth phase of takeoff, from\n", - " the P2 mic location to engine cutback;\n", - "- `TakeoffEngineCutback` : a phase builder for the seventh phase of takeoff, from start\n", - " to finish of engine cutback;\n", - "- `TakeoffEngineCutbackToMicP1` : a phase builder for the eighth phase of takeoff, from\n", - " engine cutback to the P1 mic location;\n", - "- `TakeoffMicP1ToClimb` : a phase builder for the ninth phase of takeoff, from P1 mic\n", + "- {glue:md}`TakeoffObstacleToMicP2` : a phase builder for the fifth phase of takeoff, from\n", + " clearing the required obstacle to the P2 mic location\n", + "- {glue:md}`TakeoffMicP2ToEngineCutback` : a phase builder for the sixth phase of takeoff, from\n", + " the P2 mic location to engine cutback\n", + "- {glue:md}`TakeoffEngineCutback` : a phase builder for the seventh phase of takeoff, from start\n", + " to finish of engine cutback\n", + "- {glue:md}`TakeoffEngineCutbackToMicP1` : a phase builder for the eighth phase of takeoff, from\n", + " engine cutback to the P1 mic location\n", + "- {glue:md}`TakeoffMicP1ToClimb` : a phase builder for the ninth phase of takeoff, from P1 mic\n", " location to climb.\n", "\n", "The following phase builders are only required if balanced field length calculations are\n", "required:\n", - "- `TakeoffDecisionSpeedBrakeDelay` : a phase builder for the second phase of aborted\n", - " takeoff, from decision speed to brake application;\n", - "- `TakeoffBrakeToAbort` : a phase builder for the last phase of aborted takeoff, from\n", + "- {glue:md}`TakeoffDecisionSpeedBrakeDelay` : a phase builder for the second phase of aborted\n", + " takeoff, from decision speed to brake application\n", + "- {glue:md}`TakeoffBrakeToAbort` : a phase builder for the last phase of aborted takeoff, from\n", " brake application to full stop.\n", "\n", "When creating any of these phase builders, the following data should first be collected\n", "and passed to the builder during creation: subsystem builders, subsystem options, user options, and initial guesses. The subsystem builders and options are created as described in the previous\n", - "section. User options are collected in an `AviaryValues` object. Each type of phase\n", + "section. User options are collected in an {glue:md}`AviaryValues` object. Each type of phase\n", "builder supports its own set of user options, with associated default values. Initial\n", - "guesses are collected in an `AviaryValues` object separate from the user options. Each\n", + "guesses are collected in an {glue:md}`AviaryValues` object separate from the user options. Each\n", "type of phase builder supports its own set of initial guesses; initial guesses have no\n", "default values and are required.\n", "\n", @@ -150,17 +211,18 @@ "source": [ "# Testing Cell\n", "import aviary.mission.flops_based.phases.detailed_takeoff_phases as DTP\n", - "DTP.TakeoffBrakeReleaseToDecisionSpeed;\n", - "DTP.TakeoffDecisionSpeedToRotate;\n", - "DTP.TakeoffRotateToLiftoff;\n", - "DTP.TakeoffLiftoffToObstacle;\n", - "DTP.TakeoffObstacleToMicP2;\n", - "DTP.TakeoffMicP2ToEngineCutback;\n", - "DTP.TakeoffEngineCutback;\n", - "DTP.TakeoffEngineCutbackToMicP1;\n", - "DTP.TakeoffMicP1ToClimb;\n", - "DTP.TakeoffDecisionSpeedBrakeDelay;\n", - "DTP.TakeoffBrakeToAbort;" + "\n", + "DTP.TakeoffBrakeReleaseToDecisionSpeed\n", + "DTP.TakeoffDecisionSpeedToRotate\n", + "DTP.TakeoffRotateToLiftoff\n", + "DTP.TakeoffLiftoffToObstacle\n", + "DTP.TakeoffObstacleToMicP2\n", + "DTP.TakeoffMicP2ToEngineCutback\n", + "DTP.TakeoffEngineCutback\n", + "DTP.TakeoffEngineCutbackToMicP1\n", + "DTP.TakeoffMicP1ToClimb\n", + "DTP.TakeoffDecisionSpeedBrakeDelay\n", + "DTP.TakeoffBrakeToAbort" ] }, { @@ -173,29 +235,30 @@ "takeoff_brake_release_user_options = av.AviaryValues()\n", "\n", "takeoff_brake_release_user_options.set_val('max_duration', val=60.0, units='s')\n", - "takeoff_brake_release_user_options.set_val('duration_ref', val=60.0, units='s')\n", + "takeoff_brake_release_user_options.set_val('time_duration_ref', val=60.0, units='s')\n", "takeoff_brake_release_user_options.set_val('distance_max', val=7500.0, units='ft')\n", "takeoff_brake_release_user_options.set_val('max_velocity', val=167.85, units='kn')\n", "\n", "takeoff_brake_release_initial_guesses = av.AviaryValues()\n", "\n", - "takeoff_brake_release_initial_guesses.set_val('time', [0., 30.], 's')\n", - "takeoff_brake_release_initial_guesses.set_val('distance', [0., 4100.], 'ft')\n", - "takeoff_brake_release_initial_guesses.set_val('velocity', [0.01, 150.], 'kn')\n", + "takeoff_brake_release_initial_guesses.set_val('time', [0.0, 30.0], 's')\n", + "takeoff_brake_release_initial_guesses.set_val('distance', [0.0, 4100.0], 'ft')\n", + "takeoff_brake_release_initial_guesses.set_val('velocity', [0.01, 150.0], 'kn')\n", "\n", "gross_mass_units = 'lbm'\n", "gross_mass = inputs.get_val(Mission.Design.GROSS_MASS, gross_mass_units)\n", "takeoff_brake_release_initial_guesses.set_val('mass', gross_mass, gross_mass_units)\n", "\n", - "takeoff_brake_release_initial_guesses.set_val('throttle', 1.)\n", - "takeoff_brake_release_initial_guesses.set_val('angle_of_attack', 0., 'deg')\n", + "takeoff_brake_release_initial_guesses.set_val('throttle', 1.0)\n", + "takeoff_brake_release_initial_guesses.set_val('angle_of_attack', 0.0, 'deg')\n", "\n", "takeoff_brake_release_builder = av.DetailedTakeoffBrakeReleaseToDecisionSpeedPhaseBuilder(\n", " 'takeoff_brake_release',\n", " core_subsystems=[aero_builder, prop_builder],\n", " subsystem_options=takeoff_subsystem_options,\n", " user_options=takeoff_brake_release_user_options,\n", - " initial_guesses=takeoff_brake_release_initial_guesses)" + " initial_guesses=takeoff_brake_release_initial_guesses,\n", + ")" ] }, { @@ -204,64 +267,64 @@ "metadata": {}, "source": [ "### Trajectory Builder\n", - "Objects of the trajectory builder type `TakeoffTrajectory` can be used to collect the\n", + "Objects of the trajectory builder type {glue:md}`TakeoffTrajectory` can be used to collect the\n", "required phases for either general takeoff analysis or balanced field length analysis.\n", "The builder has setters for each of the following generally required phase builders:\n", - "- `set_brake_release_to_decision_speed()` : assign a phase builder, typically of type\n", - " `TakeoffBrakeReleaseToDecisionSpeed`, for the beginning of takeoff to the time when the\n", - " pilot must choose either to liftoff or halt the aircraft;\n", - "- `set_decision_speed_to_rotate()` : assign a phase builder, typically of type\n", - " `TakeoffDecisionSpeedToRotate`, for the short distance between achieving decision speed\n", - " and beginning the rotation phase;\n", - "- `set_rotate_to_liftoff()` : assign a phase builder, typically of type\n", - " `TakeoffRotateToLiftoff`, for the short distance required to rotate the aircraft to\n", - " achieve liftoff;\n", - "- `set_liftoff_to_obstacle()` : assign a phase builder, typically of type\n", - " `TakeoffLiftoffToObstacle`, for the short period between liftoff and clearing the\n", + "- {glue:md}`set_brake_release_to_decision_speed()` : assign a phase builder, typically of type\n", + " {glue:md}`TakeoffBrakeReleaseToDecisionSpeed`, for the beginning of takeoff to the time when the\n", + " pilot must choose either to liftoff or halt the aircraft\n", + "- {glue:md}`set_decision_speed_to_rotate()` : assign a phase builder, typically of type\n", + " {glue:md}`TakeoffDecisionSpeedToRotate`, for the short distance between achieving decision speed\n", + " and beginning the rotation phase\n", + "- {glue:md}`set_rotate_to_liftoff()` : assign a phase builder, typically of type\n", + " {glue:md}`TakeoffRotateToLiftoff`, for the short distance required to rotate the aircraft to\n", + " achieve liftoff\n", + "- {glue:md}`set_liftoff_to_obstacle()` : assign a phase builder, typically of type\n", + " {glue:md}`TakeoffLiftoffToObstacle`, for the short period between liftoff and clearing the\n", " required obstacle.\n", "\n", "The builder has setters for the following phase builders, which are only required if\n", "acoustic calculations are required:\n", - "- `set_obstacle_to_mic_p2()` : assign a phase builder, typically of type\n", - " `TakeoffObstacleToMicP2`, for the fifth phase of takeoff, from clearing the required\n", - " obstacle to the p2 mic loation;\n", - "- `set_mic_p2_to_engine_cutback()` : a phase builder, typically of type\n", - " `TakeoffMicP2ToEngineCutback`, for the sixth phase of takeoff, from the p2 mic location\n", - " to engine cutback;\n", - "- `set_engine_cutback()` : a phase builder, typically of type `TakeoffEngineCutback`, for\n", - " the seventh phase of takeoff, from start to finish of engine cutback;\n", - "- `set_engine_cutback_to_mic_p1()` : a phase builder, typically of type\n", - " `TakeoffEngineCutbackToMicP1`, for the eighth phase of takeoff, engine cutback to the\n", - " P1 mic location;\n", - "- `set_mic_p1_to_climb()` : a phase builder, typically of type `TakeoffMicP1ToClimb`, for\n", + "- {glue:md}`set_obstacle_to_mic_p2()` : assign a phase builder, typically of type\n", + " {glue:md}`TakeoffObstacleToMicP2`, for the fifth phase of takeoff, from clearing the required\n", + " obstacle to the p2 mic loation\n", + "- {glue:md}`set_mic_p2_to_engine_cutback()` : a phase builder, typically of type\n", + " {glue:md}`TakeoffMicP2ToEngineCutback`, for the sixth phase of takeoff, from the p2 mic location\n", + " to engine cutback\n", + "- {glue:md}`set_engine_cutback()` : a phase builder, typically of type {glue:md}`TakeoffEngineCutback`, for\n", + " the seventh phase of takeoff, from start to finish of engine cutback\n", + "- {glue:md}`set_engine_cutback_to_mic_p1()` : a phase builder, typically of type\n", + " {glue:md}`TakeoffEngineCutbackToMicP1`, for the eighth phase of takeoff, engine cutback to the\n", + " P1 mic location\n", + "- `{glue:md}`set_mic_p1_to_climb`()` : a phase builder, typically of type {glue:md}`TakeoffMicP1ToClimb`, for\n", " the ninth phase of takeoff, from P1 mic location to climb.\n", "\n", "The builder also has setters for the following phase builders, which are only required if\n", "balanced field length calculations are required:\n", - "- `set_decision_speed_to_brake()` : assign a phase builder, typically of type\n", - " `TakeoffDecisionSpeedBrakeDelay`, for delayed braking when the engine fails;\n", - "- `set_brake_to_abort()` : assign a phase builder, typically of type\n", - " `TakeoffBrakeToAbort`, for braking to fullstop after engine failure.\n", + "- {glue:md}`set_decision_speed_to_brake()` : assign a phase builder, typically of type\n", + " {glue:md}`TakeoffDecisionSpeedBrakeDelay`, for delayed braking when the engine fails\n", + "- {glue:md}`set_brake_to_abort()` : assign a phase builder, typically of type\n", + " {glue:md}`TakeoffBrakeToAbort`, for braking to fullstop after engine failure.\n", "\n", - "After all required phase builders have been assigned, the `build_trajectory()` method can\n", - "be called on the builder, which requires an `AviaryValues` object for Aviary level\n", + "After all required phase builders have been assigned, the {glue:md}`build_trajectory()` method can\n", + "be called on the builder, which requires an {glue:md}`AviaryValues` object for Aviary level\n", "analysis options, and which optionally accepts a model (an OpenMDAO `Group`) and a\n", "trajectory. If specified, the model is used in handling trajectory parameter setup;\n", "otherwise, trajectory parameter setup must be handled by client code. If specified, the\n", "trajectory is updated with phase analysis components created from the phase builders;\n", "otherwise, a new trajectory is created, updated with these components, and returned.\n", - "Calling `build_trajectory()` adds phase analysis components to the trajectory, and then\n", + "Calling {glue:md}`build_trajectory()` adds phase analysis components to the trajectory, and then\n", "links those phases appropriately. Note, externally created trajectories can be added to\n", - "the problem model either before or after the call to `build_trajectory()`.\n", + "the problem model either before or after the call to {glue:md}`build_trajectory()`.\n", "\n", - "Once `build_trajectory()` is called on the builder, client code can optionally retrieve\n", - "named phase analysis components from the builder with the `get_phase()` method. Client\n", + "Once {glue:md}`build_trajectory()` is called on the builder, client code can optionally retrieve\n", + "named phase analysis components from the builder with the {glue:md}`get_phase()` method. Client\n", "code can then add objectives and constraints to these components to satisfy application\n", "specific requirements.\n", "\n", - "Before running the problem, the `apply_initial_guesses()` method should be called on the\n", + "Before running the problem, the {glue:md}`apply_initial_guesses()` method should be called on the\n", "trajectory builder with the problem and the name of the trajectory. For each created\n", - "phase, this method calls the `apply_initial_guesses()` method on the associated phase\n", + "phase, this method calls the {glue:md}`apply_initial_guesses()` method on the associated phase\n", "builder. Any initial guesses not applied are returned in a dictionary, where the name of\n", "the phase maps to the list of initial guesses not applied. Once the problem is built up\n", "and set up, the problem can be run for trajectory analysis." @@ -277,21 +340,25 @@ "import warnings\n", "\n", "import dymos as dm\n", - "\n", "import openmdao.api as om\n", "\n", - "from aviary.models.N3CC.N3CC_data import (\n", - " takeoff_decision_speed_builder, takeoff_rotate_builder, takeoff_liftoff_builder,\n", - " takeoff_mic_p2_builder, takeoff_mic_p2_to_engine_cutback_builder,\n", - " takeoff_engine_cutback_builder, takeoff_engine_cutback_to_mic_p1_builder,\n", - " takeoff_mic_p1_to_climb_builder, takeoff_liftoff_user_options)\n", + "from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import (\n", + " takeoff_decision_speed_builder,\n", + " takeoff_engine_cutback_builder,\n", + " takeoff_engine_cutback_to_mic_p1_builder,\n", + " takeoff_liftoff_builder,\n", + " takeoff_liftoff_user_options,\n", + " takeoff_mic_p1_to_climb_builder,\n", + " takeoff_mic_p2_builder,\n", + " takeoff_mic_p2_to_engine_cutback_builder,\n", + " takeoff_rotate_builder,\n", + ")\n", "from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems\n", - "\n", + "from aviary.variable_info.functions import setup_model_options\n", "\n", "takeoff_trajectory_builder = av.DetailedTakeoffTrajectoryBuilder('detailed_takeoff')\n", "\n", - "takeoff_trajectory_builder.set_brake_release_to_decision_speed(\n", - " takeoff_brake_release_builder)\n", + "takeoff_trajectory_builder.set_brake_release_to_decision_speed(takeoff_brake_release_builder)\n", "\n", "takeoff_trajectory_builder.set_decision_speed_to_rotate(takeoff_decision_speed_builder)\n", "\n", @@ -301,21 +368,19 @@ "\n", "takeoff_trajectory_builder.set_obstacle_to_mic_p2(takeoff_mic_p2_builder)\n", "\n", - "takeoff_trajectory_builder.set_mic_p2_to_engine_cutback(\n", - " takeoff_mic_p2_to_engine_cutback_builder)\n", + "takeoff_trajectory_builder.set_mic_p2_to_engine_cutback(takeoff_mic_p2_to_engine_cutback_builder)\n", "\n", "takeoff_trajectory_builder.set_engine_cutback(takeoff_engine_cutback_builder)\n", "\n", - "takeoff_trajectory_builder.set_engine_cutback_to_mic_p1(\n", - " takeoff_engine_cutback_to_mic_p1_builder)\n", + "takeoff_trajectory_builder.set_engine_cutback_to_mic_p1(takeoff_engine_cutback_to_mic_p1_builder)\n", "\n", "takeoff_trajectory_builder.set_mic_p1_to_climb(takeoff_mic_p1_to_climb_builder)\n", "\n", "takeoff = om.Problem()\n", "\n", "# default subsystems\n", - "default_premission_subsystems = get_default_premission_subsystems('FLOPS', engine)\n", - " \n", + "default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines)\n", + "\n", "# Upstream pre-mission analysis for aero\n", "takeoff.model.add_subsystem(\n", " 'core_subsystems',\n", @@ -324,29 +389,34 @@ " subsystems=default_premission_subsystems,\n", " ),\n", " promotes_inputs=['*'],\n", - " promotes_outputs=['*'])\n", + " promotes_outputs=['*'],\n", + ")\n", "\n", "# Instantiate the trajectory and add the phases\n", "traj = dm.Trajectory()\n", "takeoff.model.add_subsystem('traj', traj)\n", "\n", "takeoff_trajectory_builder.build_trajectory(\n", - " aviary_options=aviary_options, model=takeoff.model, traj=traj)\n", + " aviary_options=aviary_options, model=takeoff.model, traj=traj\n", + ")\n", "\n", "distance_max, units = takeoff_liftoff_user_options.get_item('distance_max')\n", "liftoff = takeoff_trajectory_builder.get_phase('takeoff_liftoff')\n", "\n", - "liftoff.add_objective(\n", - " Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units)\n", + "liftoff.add_objective(Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units)\n", "\n", "# Insert a constraint for a fake decision speed, until abort is added.\n", "takeoff.model.add_constraint(\n", - " 'traj.takeoff_brake_release.states:velocity',\n", - " equals=149.47, units='kn', ref=150.0, indices=[-1])\n", + " 'traj.takeoff_brake_release.states:velocity', equals=149.47, units='kn', ref=150.0, indices=[-1]\n", + ")\n", "\n", "takeoff.model.add_constraint(\n", " 'traj.takeoff_decision_speed.states:velocity',\n", - " equals=155.36, units='kn', ref=159.0, indices=[-1])\n", + " equals=155.36,\n", + " units='kn',\n", + " ref=159.0,\n", + " indices=[-1],\n", + ")\n", "\n", "varnames = [\n", " av.Aircraft.Wing.AREA,\n", @@ -354,18 +424,18 @@ " av.Aircraft.Wing.SPAN,\n", "]\n", "av.set_aviary_input_defaults(takeoff.model, varnames, aviary_options)\n", - " \n", + "\n", + "setup_model_options(takeoff, aviary_options)\n", + "\n", "# suppress warnings:\n", "# \"input variable '...' promoted using '*' was already promoted using 'aircraft:*'\n", "with warnings.catch_warnings():\n", - "\n", - " warnings.simplefilter(\"ignore\", om.PromotionWarning)\n", + " warnings.simplefilter('ignore', om.PromotionWarning)\n", " takeoff.setup(check=True)\n", "\n", "av.set_aviary_initial_values(takeoff, aviary_options)\n", "\n", - "takeoff_trajectory_builder.apply_initial_guesses(takeoff, 'traj')\n", - "\n" + "takeoff_trajectory_builder.apply_initial_guesses(takeoff, 'traj')" ] }, { @@ -387,30 +457,102 @@ "metadata": {}, "outputs": [], "source": [ - "landing_subsystem_options = {'low_speed_aero': {\n", - " 'method': 'low_speed',\n", - " 'ground_altitude': 0., # units='m'\n", - " 'angles_of_attack': [\n", - " 0.0, 1.0, 2.0, 3.0, 4.0, 5.0,\n", - " 6.0, 7.0, 8.0, 9.0, 10.0, 11.0,\n", - " 12.0, 13.0, 14.0, 15.0], # units='deg'\n", - " 'lift_coefficients': [\n", - " 0.7, 0.9, 1.05, 1.15, 1.25, 1.4,\n", - " 1.5, 1.60, 1.7, 1.8, 1.9, 2.0,\n", - " 2.1, 2.2, 2.3, 2.40],\n", - " 'drag_coefficients': [\n", - " 0.1, 0.1, 0.12, 0.13, 0.14, 0.15,\n", - " 0.16, 0.17, 0.18, 0.20, 0.22, 0.24,\n", - " 0.26, 0.3, 0.32, 0.34],\n", - " 'lift_coefficient_factor': 1.,\n", - " 'drag_coefficient_factor': 1.}}\n", + "landing_subsystem_options = {\n", + " 'low_speed_aero': {\n", + " 'method': 'low_speed',\n", + " 'ground_altitude': 0.0, # units='m'\n", + " 'angles_of_attack': [\n", + " 0.0,\n", + " 1.0,\n", + " 2.0,\n", + " 3.0,\n", + " 4.0,\n", + " 5.0,\n", + " 6.0,\n", + " 7.0,\n", + " 8.0,\n", + " 9.0,\n", + " 10.0,\n", + " 11.0,\n", + " 12.0,\n", + " 13.0,\n", + " 14.0,\n", + " 15.0,\n", + " ], # units='deg'\n", + " 'lift_coefficients': [\n", + " 0.7,\n", + " 0.9,\n", + " 1.05,\n", + " 1.15,\n", + " 1.25,\n", + " 1.4,\n", + " 1.5,\n", + " 1.60,\n", + " 1.7,\n", + " 1.8,\n", + " 1.9,\n", + " 2.0,\n", + " 2.1,\n", + " 2.2,\n", + " 2.3,\n", + " 2.40,\n", + " ],\n", + " 'drag_coefficients': [\n", + " 0.1,\n", + " 0.1,\n", + " 0.12,\n", + " 0.13,\n", + " 0.14,\n", + " 0.15,\n", + " 0.16,\n", + " 0.17,\n", + " 0.18,\n", + " 0.20,\n", + " 0.22,\n", + " 0.24,\n", + " 0.26,\n", + " 0.3,\n", + " 0.32,\n", + " 0.34,\n", + " ],\n", + " 'lift_coefficient_factor': 1.0,\n", + " 'drag_coefficient_factor': 1.0,\n", + " }\n", + "}\n", "\n", "# when using spoilers, add a few more options\n", - "landing_spoiler_subsystem_options = {'low_speed_aero': {\n", - " **landing_subsystem_options['low_speed_aero'],\n", - " 'use_spoilers': True,\n", - " 'spoiler_lift_coefficient': -0.81,\n", - " 'spoiler_drag_coefficient': 0.085}}" + "landing_spoiler_subsystem_options = {\n", + " 'low_speed_aero': {\n", + " **landing_subsystem_options['low_speed_aero'],\n", + " 'use_spoilers': True,\n", + " 'spoiler_lift_coefficient': -0.81,\n", + " 'spoiler_drag_coefficient': 0.085,\n", + " }\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "084a0348", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.mission.flops_based.phases.detailed_landing_phases import LandingTrajectory\n", + "\n", + "file_path = av.get_path('mission/flops_based/phases/detailed_landing_phases.py')\n", + "landing_class_names = get_class_names(file_path)\n", + "for class_name in landing_class_names:\n", + " glue_variable(class_name, md_code=True)\n", + "\n", + "# Get all functions of class LandingTrajectory\n", + "glue_class_functions(LandingTrajectory, current_glued_vars)" ] }, { @@ -421,20 +563,20 @@ "### Phase Builders\n", "There are six types of phase builders for landing. In general, the following phase\n", "builders are always required:\n", - "- `LandingObstacleToFlare` : a phase builder for moving from the start of the runway,\n", + "- {glue:md}`LandingObstacleToFlare` : a phase builder for moving from the start of the runway,\n", " just above the required clearance height, to the start of a maneuver to help soften the\n", - " impact of touchdown;\n", - "- `LandingFlareToTouchdown` : a phase builder for moving through a maneuver to help\n", - " soften the impact of touchdown;\n", - "- `LandingTouchdownToNoseDown` : a phase builder for rotating the nose down after\n", - " touchdown;\n", - "- `LandingNoseDownToStop` : a phase builder for the final phase of landing, from nose\n", + " impact of touchdown\n", + "- {glue:md}`LandingFlareToTouchdown` : a phase builder for moving through a maneuver to help\n", + " soften the impact of touchdown\n", + "- {glue:md}`LandingTouchdownToNoseDown` : a phase builder for rotating the nose down after\n", + " touchdown\n", + "- {glue:md}`LandingNoseDownToStop` : a phase builder for the final phase of landing, from nose\n", " down to full stop.\n", "\n", "The following phase builders are only required if acoustic calculations are required:\n", - "- `LandingApproachToMicP3` : a phase builder for moving from descent to the mic location\n", - " P3;\n", - "- `LandingMicP3ToObstacle` : a phase builder for moving from the mic location P3 to the\n", + "- {glue:md}`LandingApproachToMicP3` : a phase builder for moving from descent to the mic location\n", + " P3\n", + "- {glue:md}`LandingMicP3ToObstacle` : a phase builder for moving from the mic location P3 to the\n", " start of the runway, just above the required clearance height.\n", "\n", "The general procedure for creating and using phase builders for landing is the same as\n", @@ -455,11 +597,12 @@ "source": [ "# Testing Cell\n", "import aviary.mission.flops_based.phases.detailed_landing_phases as DLP\n", - "DLP.LandingObstacleToFlare;\n", - "DLP.LandingFlareToTouchdown;\n", - "DLP.LandingTouchdownToNoseDown;\n", - "DLP.LandingNoseDownToStop;\n", - "DLP.LandingApproachToMicP3;\n", + "\n", + "DLP.LandingObstacleToFlare\n", + "DLP.LandingFlareToTouchdown\n", + "DLP.LandingTouchdownToNoseDown\n", + "DLP.LandingNoseDownToStop\n", + "DLP.LandingApproachToMicP3\n", "DLP.LandingMicP3ToObstacle;" ] }, @@ -472,10 +615,9 @@ "source": [ "from aviary.api import DetailedLandingApproachToMicP3PhaseBuilder as LandingApproachToMicP3\n", "\n", - "\n", "# NOTE FLOPS output is based on \"constant\" landing mass - assume reserves weight\n", "# - currently neglecting taxi\n", - "detailed_landing_mass = 106292. # units='lbm'\n", + "detailed_landing_mass = 106292.0 # units='lbm'\n", "\n", "# Flops variable APRANG\n", "apr_angle = -3.0 # deg\n", @@ -487,35 +629,33 @@ "\n", "landing_approach_to_mic_p3_user_options = av.AviaryValues()\n", "\n", - "landing_approach_to_mic_p3_user_options.set_val('max_duration', val=50., units='s')\n", - "landing_approach_to_mic_p3_user_options.set_val('duration_ref', val=50., units='s')\n", - "landing_approach_to_mic_p3_user_options.set_val('initial_ref', val=50.0, units='s')\n", - "landing_approach_to_mic_p3_user_options.set_val('distance_max', val=10000., units='ft')\n", - "landing_approach_to_mic_p3_user_options.set_val('max_velocity', val=140., units='kn')\n", - "landing_approach_to_mic_p3_user_options.set_val('altitude_ref', val=800., units='ft')\n", + "landing_approach_to_mic_p3_user_options.set_val('max_duration', val=50.0, units='s')\n", + "landing_approach_to_mic_p3_user_options.set_val('time_duration_ref', val=50.0, units='s')\n", + "landing_approach_to_mic_p3_user_options.set_val('time_initial_ref', val=50.0, units='s')\n", + "landing_approach_to_mic_p3_user_options.set_val('distance_max', val=10000.0, units='ft')\n", + "landing_approach_to_mic_p3_user_options.set_val('max_velocity', val=140.0, units='kn')\n", + "landing_approach_to_mic_p3_user_options.set_val('altitude_ref', val=800.0, units='ft')\n", "\n", - "landing_approach_to_mic_p3_user_options.set_val(\n", - " 'lower_angle_of_attack', val=0., units='deg')\n", + "landing_approach_to_mic_p3_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg')\n", "\n", - "landing_approach_to_mic_p3_user_options.set_val(\n", - " 'upper_angle_of_attack', val=12., units='deg')\n", + "landing_approach_to_mic_p3_user_options.set_val('upper_angle_of_attack', val=12.0, units='deg')\n", "\n", - "landing_approach_to_mic_p3_user_options.set_val(\n", - " 'angle_of_attack_ref', val=12., units='deg')\n", + "landing_approach_to_mic_p3_user_options.set_val('angle_of_attack_ref', val=12.0, units='deg')\n", "\n", - "landing_approach_to_mic_p3_user_options.set_val('initial_height', val=600., units='ft')\n", + "landing_approach_to_mic_p3_user_options.set_val('initial_height', val=600.0, units='ft')\n", "\n", "landing_approach_to_mic_p3_initial_guesses = av.AviaryValues()\n", "\n", - "landing_approach_to_mic_p3_initial_guesses.set_val('time', [-42., 15.], 's')\n", - "landing_approach_to_mic_p3_initial_guesses.set_val('distance', [-4000., -2000.], 'ft')\n", - "landing_approach_to_mic_p3_initial_guesses.set_val('velocity', 140., 'kn')\n", + "landing_approach_to_mic_p3_initial_guesses.set_val('time', [-42.0, 15.0], 's')\n", + "landing_approach_to_mic_p3_initial_guesses.set_val('distance', [-4000.0, -2000.0], 'ft')\n", + "landing_approach_to_mic_p3_initial_guesses.set_val('velocity', 140.0, 'kn')\n", "landing_approach_to_mic_p3_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm')\n", "landing_approach_to_mic_p3_initial_guesses.set_val('throttle', throttle)\n", - "landing_approach_to_mic_p3_initial_guesses.set_val('altitude', [600., 394.], 'ft')\n", + "landing_approach_to_mic_p3_initial_guesses.set_val('altitude', [600.0, 394.0], 'ft')\n", "\n", "landing_approach_to_mic_p3_initial_guesses.set_val(\n", - " Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg')\n", + " Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg'\n", + ")\n", "\n", "landing_approach_to_mic_p3_initial_guesses.set_val('angle_of_attack', 5.25, 'deg')\n", "\n", @@ -524,7 +664,8 @@ " core_subsystems=[aero_builder, prop_builder],\n", " subsystem_options=landing_subsystem_options,\n", " user_options=landing_approach_to_mic_p3_user_options,\n", - " initial_guesses=landing_approach_to_mic_p3_initial_guesses)" + " initial_guesses=landing_approach_to_mic_p3_initial_guesses,\n", + ")" ] }, { @@ -533,31 +674,30 @@ "metadata": {}, "source": [ "### Trajectory Builder\n", - "Objects of the trajectory builder type `LandingTrajectory` can be used to collect the\n", + "Objects of the trajectory builder type {glue:md}`LandingTrajectory` can be used to collect the\n", "required phases for general landing analysis. The builder has setters for each of the\n", "following generally required phase builders:\n", - "- `set_obstacle_to_flare()` : assign a phase builder, typically of type\n", - " `LandingObstacleToFlare`, for moving from the start of the runway, just above the\n", + "- {glue:md}`set_obstacle_to_flare()` : assign a phase builder, typically of type\n", + " {glue:md}`LandingObstacleToFlare`, for moving from the start of the runway, just above the\n", " required clearance height, to the start of a maneuver to help soften the impact of\n", - " touchdown;\n", - "- `set_flare_to_touchdown()` : assign a phase builder, typically of type\n", - " `LandingFlareToTouchdown`, for moving through a maneuver to help soften the impact of\n", - " touchdown;\n", - "- `set_touchdown_to_nose_down()` : assign a phase builder, typically of type\n", - " `LandingTouchdownToNoseDown`, for rotating the nose down after touchdown;\n", - "- `set_nose_down_to_stop()` : assign a phase builder, typically of type\n", - " `LandingNoseDownToStop`, for the final phase of landing, from nose down to full stop.\n", + " touchdown\n", + "- {glue:md}`set_flare_to_touchdown()` : assign a phase builder, typically of type\n", + " {glue:md}`LandingFlareToTouchdown`, for moving through a maneuver to help soften the impact of touchdown\n", + "- {glue:md}`set_touchdown_to_nose_down()` : assign a phase builder, typically of type\n", + " {glue:md}`LandingTouchdownToNoseDown`, for rotating the nose down after touchdown\n", + "- {glue:md}`set_nose_down_to_stop()` : assign a phase builder, typically of type\n", + " {glue:md}`LandingNoseDownToStop`, for the final phase of landing, from nose down to full stop.\n", "\n", "The builder also has setters for each of the following phase builders, which are only\n", "required if acoustic calculations are required:\n", - "- `set_approach_to_mic_p3()` : assign a phase builder, typically of type\n", - " `LandingApproachToMicP3`, for moving from the end of descent to the mic location P3;\n", - "- `set_mic_p3_to_obstacle()` : assign a phase builder, typically of type\n", - " `LandingMicP3ToObstacle`, for moving from the mic location P3 to the start of the\n", + "- {glue:md}`set_approach_to_mic_p3()` : assign a phase builder, typically of type\n", + " {glue:md}`LandingApproachToMicP3`, for moving from the end of descent to the mic location P3\n", + "- {glue:md}`set_mic_p3_to_obstacle()` : assign a phase builder, typically of type\n", + " {glue:md}`LandingMicP3ToObstacle`, for moving from the mic location P3 to the start of the\n", " runway, just above the required clearance height.\n", "\n", "After all required phase builders have been assigned, the general procedure for using the\n", - "`build_trajectory()`, `get_phase()`, and `apply_initial_guesses()` methods of the\n", + "{glue:md}`build_trajectory()`, {glue:md}`get_phase()`, and {glue:md}`apply_initial_guesses()` methods of the\n", "trajectory builder is the same for landing as that for takeoff. See the \"Trajectory\n", "Builder\" subsection in the \"Takeoff\" section above for a description." ] @@ -569,10 +709,14 @@ "metadata": {}, "outputs": [], "source": [ - "from aviary.models.N3CC.N3CC_data import (\n", - " landing_mic_p3_to_obstacle_builder, landing_obstacle_builder, landing_flare_builder,\n", - " landing_touchdown_builder, landing_fullstop_builder, landing_fullstop_user_options)\n", - "\n", + "from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import (\n", + " landing_flare_builder,\n", + " landing_fullstop_builder,\n", + " landing_fullstop_user_options,\n", + " landing_mic_p3_to_obstacle_builder,\n", + " landing_obstacle_builder,\n", + " landing_touchdown_builder,\n", + ")\n", "\n", "landing_trajectory_builder = av.DetailedLandingTrajectoryBuilder('detailed_landing')\n", "\n", @@ -598,14 +742,16 @@ " subsystems=default_premission_subsystems,\n", " ),\n", " promotes_inputs=['*'],\n", - " promotes_outputs=['*'])\n", + " promotes_outputs=['*'],\n", + ")\n", "\n", "# Instantiate the trajectory and add the phases\n", "traj = dm.Trajectory()\n", "landing.model.add_subsystem('traj', traj)\n", "\n", "landing_trajectory_builder.build_trajectory(\n", - " aviary_options=aviary_options, model=landing.model, traj=traj)\n", + " aviary_options=aviary_options, model=landing.model, traj=traj\n", + ")\n", "\n", "distance_max, units = landing_fullstop_user_options.get_item('distance_max')\n", "fullstop = landing_trajectory_builder.get_phase('landing_fullstop')\n", @@ -618,24 +764,24 @@ " av.Aircraft.Wing.SPAN,\n", "]\n", "av.set_aviary_input_defaults(landing.model, varnames, aviary_options)\n", - " \n", + "\n", + "setup_model_options(landing, aviary_options)\n", + "\n", "# suppress warnings:\n", "# \"input variable '...' promoted using '*' was already promoted using 'aircraft:*'\n", "with warnings.catch_warnings():\n", - "\n", - " warnings.simplefilter(\"ignore\", om.PromotionWarning)\n", + " warnings.simplefilter('ignore', om.PromotionWarning)\n", " landing.setup(check=True)\n", "\n", "av.set_aviary_initial_values(landing, aviary_options)\n", "\n", - "landing_trajectory_builder.apply_initial_guesses(landing, 'traj')\n", - "\n" + "landing_trajectory_builder.apply_initial_guesses(landing, 'traj')" ] } ], "metadata": { "kernelspec": { - "display_name": "base", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -649,7 +795,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.5" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/SGM_capabilities.ipynb b/aviary/docs/user_guide/SGM_capabilities.ipynb deleted file mode 100644 index b8e0082156..0000000000 --- a/aviary/docs/user_guide/SGM_capabilities.ipynb +++ /dev/null @@ -1,306 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Key SGM Capabilities\n", - "\n", - "Shooting (or Forward in Time Integration) methods offer several benefits over collocation methods that some users might find useful:\n", - "* Trajectories are physical for every iteration of the optimization (including failed optimizations)\n", - "* Little to no initial guessing required for the trajectory\n", - "* Dynamically ordered events and phases\n", - "\n", - "## Setting up ODEs\n", - "\n", - "SGM expects all of the states (including time) as inputs to the ODE and the state rates as outputs.\n", - "If a particular state does not directly influence the EOM (such as distance in the GASP based climb_eom), it can be added using the built in helper functions:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "from aviary.mission.gasp_based.ode.base_ode import BaseODE\n", - "from aviary.variable_info.variables import Dynamic, Mission, Aircraft\n", - "from aviary.variable_info.enums import AnalysisScheme, LegacyCode\n", - "from aviary.mission.gasp_based.ode.time_integration_base_classes import SimuPyProblem\n", - "from aviary.mission.gasp_based.ode.rotation_ode import RotationODE\n", - "\n", - "from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder\n", - "from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder\n", - "from aviary.subsystems.propulsion.utils import build_engine_deck\n", - "from aviary.utils.process_input_decks import create_vehicle, update_GASP_options\n", - "from aviary.interface.download_models import get_model\n", - "\n", - "aviary_inputs, initialization_guesses = create_vehicle(get_model('aircraft_for_bench_GwGm.csv'))\n", - "aviary_inputs = update_GASP_options(aviary_inputs)\n", - "aviary_inputs.set_val(Mission.Summary.CRUISE_MASS_FINAL,\n", - " val=initialization_guesses['cruise_mass_final'], units='lbm')\n", - "aviary_inputs.set_val(Mission.Summary.GROSS_MASS,\n", - " val=initialization_guesses['actual_takeoff_mass'], units='lbm')\n", - "aviary_inputs.set_val(Aircraft.Engine.NUM_ENGINES, val=[1], units='unitless')\n", - "default_mission_subsystems = [\n", - " CoreAerodynamicsBuilder('core_aerodynamics', code_origin=LegacyCode.GASP),\n", - " CorePropulsionBuilder('core_propulsion',engine_models=build_engine_deck(aviary_inputs))\n", - " ]\n", - "ode_args = {'aviary_options':aviary_inputs,\n", - " 'core_subsystems': default_mission_subsystems}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs, add_SGM_required_outputs\n", - "\n", - "class ClimbODE(BaseODE):\n", - " # ## ... ## #\n", - " def setup(self):\n", - " # ## ... ## #\n", - " analysis_scheme = self.options[\"analysis_scheme\"]\n", - " # ## ... ## #\n", - " if analysis_scheme is AnalysisScheme.SHOOTING:\n", - " add_SGM_required_inputs(self, {\n", - " 't_curr': {'units': 's'},\n", - " Dynamic.Mission.DISTANCE: {'units': 'ft'},\n", - " 'alt_trigger': {'units': self.options['alt_trigger_units'], 'val': 10e3},\n", - " 'speed_trigger': {'units': self.options['speed_trigger_units'], 'val': 100},\n", - " })\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "these functions allow the user to leave the EOMs unmodified for collocation vs shooting, and provide an easy way to set the units, default values, and any other keyword args for the OpenMDAO functions [add_input and add_output](https://openmdao.org/newdocs/versions/latest/features/core_features/working_with_components/continuous_variables.html) for any variables that only used by SGM.\n", - "\n", - "## Setting up Phases\n", - "\n", - "Each SGM phase should inherit from SimuPyProblem and requires an instantiated ODE. If no states are provided Aviary will attempt to determine the states in the current phase by finding the state rates (any output that ends in `'_rate'`). States and their rates are expected to have the same name (other than the addition of the `'_rate'` suffix for the state rate), if the state rate associated with a state doesn't follow this pattern, it can be specified through `alternate_state_rate_names`, a dictionary with state names as the keys and the desired state rate as the value." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "from aviary.mission.gasp_based.ode.time_integration_base_classes import SimuPyProblem\n", - "from aviary.utils.doctape import check_args, check_value\n", - "import inspect\n", - "\n", - "rate_suffix = inspect.signature(SimuPyProblem).parameters['rate_suffix'].default\n", - "check_value(rate_suffix, '_rate')\n", - "check_args(SimuPyProblem,'alternate_state_rate_names')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class SGMRotation(SimuPyProblem):\n", - " '''\n", - " This creates a subproblem for the rotation phase of the trajectory that will\n", - " be solved using SGM.\n", - " Rotation ends when the normal force on the runway reaches 0.\n", - " '''\n", - "\n", - " def __init__(\n", - " self,\n", - " phase_name='rotation',\n", - " ode_args={},\n", - " simupy_args={},\n", - " ):\n", - " super().__init__(\n", - " RotationODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args),\n", - " problem_name=phase_name,\n", - " outputs=[\"normal_force\", \"alpha\"],\n", - " states=[\n", - " Dynamic.Mission.MASS,\n", - " Dynamic.Mission.DISTANCE,\n", - " Dynamic.Mission.ALTITUDE,\n", - " Dynamic.Mission.VELOCITY,\n", - " ],\n", - " # state_units=['lbm','nmi','ft'],\n", - " alternate_state_rate_names={\n", - " Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL},\n", - " **simupy_args,\n", - " )\n", - "\n", - " self.phase_name = phase_name\n", - " self.add_trigger(\"normal_force\", 0, units='lbf')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One of the main benefits of SGM is the ability to add arbitrarily ordered phases using triggers. Aviary uses an `event_trigger` class to store the information necessary for SGM phases. Instantiated event_triggers can be passed directly to the problem, or the helper function self.add_trigger can be used to generate the triggers. Triggers are generally used to check when the value of a state reaches a certain value, but can be used with any output from the ODE, such as `normal_force` in SGMRotation. Multiple triggers can be added to one phase, but the event will be triggered by whichever condition is met first." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "from aviary.mission.gasp_based.ode.time_integration_base_classes import event_trigger\n", - "from aviary.mission.gasp_based.phases.time_integration_phases import SGMRotation\n", - "from aviary.utils.doctape import check_value\n", - "\n", - "rotation_trigger: event_trigger = SGMRotation(ode_args=ode_args).triggers[0]\n", - "check_value(rotation_trigger.state,'normal_force')\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setting up Trajectories\n", - "\n", - "Aviary problems using the shooting method use `FlexibleTraj` to define their trajectories, instead of `dm.Trajectory()`. Similar to collocation problems, SGM will loop through the phases specified in the `phase_info` to build up the trajectory. When creating an SGM trajectory, the variables that will be used as inputs and outputs for states, triggers, and variables, including phase specific ones, are specified." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from aviary.mission.gasp_based.phases.time_integration_traj import FlexibleTraj\n", - "from aviary.interface.default_phase_info.two_dof_fiti import phase_info, add_default_sgm_args\n", - "\n", - "add_default_sgm_args(phase_info, ode_args)\n", - "\n", - "full_traj = FlexibleTraj(\n", - " Phases=phase_info,\n", - " traj_final_state_output=[\n", - " Dynamic.Mission.MASS,\n", - " Dynamic.Mission.DISTANCE,\n", - " ],\n", - " traj_initial_state_input=[\n", - " Dynamic.Mission.MASS,\n", - " Dynamic.Mission.DISTANCE,\n", - " Dynamic.Mission.ALTITUDE,\n", - " ],\n", - " traj_event_trigger_input=[\n", - " # specify ODE, output_name, with units that SimuPyProblem expects\n", - " # assume event function is of form ODE.output_name - value\n", - " # third key is event_idx associated with input\n", - " ('groundroll', Dynamic.Mission.VELOCITY, 0,),\n", - " ('climb3', Dynamic.Mission.ALTITUDE, 0,),\n", - " ('cruise', Dynamic.Mission.MASS, 0,),\n", - " ],\n", - " traj_intermediate_state_output=[\n", - " ('cruise', Dynamic.Mission.DISTANCE),\n", - " ('cruise', Dynamic.Mission.MASS),\n", - " ]\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Because all phases require `ode_args` and `simupy_args` which are usually the same for all phases, `add_default_sgm_args` has been provided to add these to the phase info automatically.\n", - "\n", - "### Setting up Phase Info\n", - "\n", - "By default, SGM uses the `two_dof_fiti` (two degree of freedom, forward in time integration) phase_info, which contains the information required to build the default trajectory used by GASP. This phase info can be imported all at once or in a few pre-defined groups:\n", - "phase_info contains all the phases from ascent_phases (which is composed of takeoff_phases and climb_phases), cruise_phases, and descent_phases." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from aviary.interface.default_phase_info.two_dof_fiti import phase_info\n", - "from aviary.interface.default_phase_info.two_dof_fiti import takeoff_phases, climb_phases, descent_phases" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`phase_info_parameterization` can be used to update the values of certain variables, like speed_trigger or cruise_alt using values from the input deck.\n", - "\n", - "## Descent Fuel Estimation\n", - "\n", - "In the current formulation of the trajectory, the fuel and/or distance required for the descent are required a priori for the cruise trigger. This can be achieved by adding a submodel that contains just the descent trajectory before the main trajectory is created. The value that results from the aircraft flying this descent can then be connected to trigger values in the main trajectory.\n", - "\n", - "The default descent that is flown using the `two_dof_fiti` phase_info is an idle descent." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from aviary.mission.gasp_based.idle_descent_estimation import add_descent_estimation_as_submodel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "from aviary.interface.default_phase_info.two_dof_fiti import descent_phases\n", - "from aviary.utils.doctape import check_value\n", - "\n", - "for phase_name, phase in descent_phases.items():\n", - " check_value(phase['user_options'][Dynamic.Mission.THROTTLE],(0, 'unitless'))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "latest_env", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.13" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/aviary/docs/user_guide/UI_Levels.md b/aviary/docs/user_guide/UI_Levels.md index c73ba9268e..342ee2d4b6 100644 --- a/aviary/docs/user_guide/UI_Levels.md +++ b/aviary/docs/user_guide/UI_Levels.md @@ -69,8 +69,7 @@ Levels 2 and 3 will require code to control the more detailed aspects of the ana | **Level 1** | **Level 2** | **Level 3** | |:--------------------------------------------:|:---------------------------------:|:----------------------:| | Mission Type (Sizing, Fallout) | All Level 1 Controls | All Level 2 Controls | -| Integration Method (Collocation, Shooting) | Specify phase order and options | Custom ODEs and EOMs | -| Optimizer (IPOPT, SNOPT) | | | +| Optimizer (IPOPT, SNOPT) | Specify phase order and options | Custom ODEs and EOMs | | Mission Description (Altitude, Mach, etc) | | | ## User Interaction with Code diff --git a/aviary/docs/user_guide/aerodynamics.ipynb b/aviary/docs/user_guide/aerodynamics.ipynb index 023e8883a5..70b123fdd9 100644 --- a/aviary/docs/user_guide/aerodynamics.ipynb +++ b/aviary/docs/user_guide/aerodynamics.ipynb @@ -1,5 +1,41 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "import aviary.api as av\n", + "from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "CoreAerodynamicsBuilder\n", + "glue_variable(get_variable_name(CoreAerodynamicsBuilder), md_code=True)\n", + "\n", + "HEIGHT_ENERGY = av.EquationsOfMotion.HEIGHT_ENERGY\n", + "glue_variable('height_energy', HEIGHT_ENERGY.value, md_code=False)\n", + "\n", + "TWO_DEGREES_OF_FREEDOM = av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM\n", + "glue_variable(TWO_DEGREES_OF_FREEDOM.value, md_code=False)\n", + "\n", + "# glue all arguments of function CoreAerodynamicsBuilder.__init__()\n", + "sigs = inspect.signature(CoreAerodynamicsBuilder)\n", + "parameters = sigs.parameters\n", + "for name, param in parameters.items():\n", + " glue_variable(name, md_code=True)\n", + " # print(f'Name: {name}, Default: {param.default}, Kind: {param.kind}')" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -7,7 +43,7 @@ "\n", "# Aerodynamics Subsystem\n", "\n", - "The built-in aerodynamics subsystem in Aviary offers multiple options for computing drag. Users can select from methods based on the FLOPS or GASP legacy codes. Choice of which legacy code's routines to use is determined by the `code_origin` option provided when initializing a `CoreAerodynamicsBuilder`. When using Aviary's [Level 1 interface](../getting_started/onboarding_level1), the code origin for aerodynamics is automatically set to match with the mission method (height-energy is paired with FLOPS, and 2-degree-of-freedom is paired with GASP). Future updates to Aviary will allow for the user to specify aerodynamics code origin directly in the input file." + "The built-in aerodynamics subsystem in Aviary offers multiple options for computing drag. Users can select from methods based on the FLOPS or GASP legacy codes. Choice of which legacy code's routines to use is determined by the {glue:md}`code_origin` option provided when initializing a {glue:md}`CoreAerodynamicsBuilder`. When using Aviary's [Level 1 interface](../getting_started/onboarding_level1), the code origin for aerodynamics is automatically set to match with the mission method ({glue:md}`height_energy` is paired with FLOPS, and {glue:md}`2DOF` is paired with GASP). Future updates to Aviary will allow for the user to specify aerodynamics code origin directly in the input file." ] }, { @@ -21,13 +57,39 @@ "aero_builder = CoreAerodynamicsBuilder(name='aero_example', code_origin=LegacyCode.FLOPS)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.interface.methods_for_level1 import run_aviary\n", + "from aviary.utils.doctape import glue_class_functions\n", + "\n", + "# Get all functions of class CoreAerodynamicsBuilder\n", + "glue_class_functions(\n", + " CoreAerodynamicsBuilder, current_glued_vars, prefix=CoreAerodynamicsBuilder.__name__\n", + ")\n", + "\n", + "# glue all argument of function run_aviary()\n", + "sigs = inspect.signature(run_aviary)\n", + "parameters = sigs.parameters\n", + "for name, param in parameters.items():\n", + " glue_variable(name, md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Both FLOPS and GASP methods have only a single option for pre-mission components, so there are no user-configurable options when calling `CoreAerodynamicsBuilder.build_pre_mission()`.\n", + "Both FLOPS and GASP methods have only a single option for pre-mission components, so there are no user-configurable options when calling {glue:md}`CoreAerodynamicsBuilder.build_pre_mission()`.\n", "\n", - "For mission analysis, a variety of methods are available to both legacy codes, each with unique options. This can be configured per-mission segment in a `phase_info` file, with relevant aerodynamics configurations placed inside `['core_subsystems']`. The following example would instruct Aviary to send the defined options to a subsystem named 'aero_example' when building the mission, if the dictionary is properly added to `phase_info`" + "For mission analysis, a variety of methods are available to both legacy codes, each with unique options. This can be configured per-mission segment in a {glue:md}`phase_info` file, with relevant aerodynamics configurations placed inside `['core_subsystems']`. The following example would instruct Aviary to send the defined options to a subsystem named 'aero_example' when building the mission, if the dictionary is properly added to {glue:md}`phase_info`" ] }, { @@ -43,7 +105,8 @@ "# Testing Cell\n", "from aviary.api import CoreAerodynamicsBuilder\n", "from aviary.utils.doctape import check_args\n", - "check_args(CoreAerodynamicsBuilder.build_pre_mission,['aviary_inputs'])" + "\n", + "check_args(CoreAerodynamicsBuilder.build_pre_mission, ['aviary_inputs', 'kwargs'])" ] }, { @@ -63,10 +126,10 @@ "\n", "# If you are manually building your subsystems, you can instead directly pass the\n", "# arguments to the builder\n", - "input_variables = AviaryValues() # include your aircraft inputs here\n", - "mission_comp = aero_builder.build_mission(num_nodes=1,\n", - " aviary_inputs=input_variables,\n", - " kwargs=aerodynamic_args['aero_example'])" + "input_variables = AviaryValues() # include your aircraft inputs here\n", + "mission_comp = aero_builder.build_mission(\n", + " num_nodes=1, aviary_inputs=input_variables, kwargs=aerodynamic_args['aero_example']\n", + ")" ] }, { @@ -81,9 +144,9 @@ "\n", "\n", "The following input variables are required for the pre-mission calculations:\n", - "- `Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN` : Maximum camber at 70 percent semi-span, percent of local chord\n", - "- `Aircraft.Design.BASE_AREA` : Aircraft base area (total exit cross-section area minus inlet capture areas for internally mounted engines)\n", - "- `Aircraft.Wing.AIRFOIL_TECHNOLOGY` : Airfoil technology parameter. Limiting values are: 1.0 represents conventional technology wing (Default); 2.0 represents advanced technology wing\n", + "- {glue:md}`Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN` : Maximum camber at 70 percent semi-span, percent of local chord\n", + "- {glue:md}`Aircraft.Design.BASE_AREA` : Aircraft base area (total exit cross-section area minus inlet capture areas for internally mounted engines)\n", + "- {glue:md}`Aircraft.Wing.AIRFOIL_TECHNOLOGY` : Airfoil technology parameter. Limiting values are: 1.0 represents conventional technology wing (Default); 2.0 represents advanced technology wing\n", "" ] }, @@ -99,32 +162,37 @@ "source": [ "# Testing Cell\n", "from aviary.api import Aircraft\n", - "Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN;\n", - "Aircraft.Wing.AIRFOIL_TECHNOLOGY;\n", - "Aircraft.Design.BASE_AREA;" + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.AIRFOIL_TECHNOLOGY), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.BASE_AREA), md_code=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "For mission analysis, FLOPS-based aerodynamics has several choices of method to determine the total lift and drag on the vehicle, listed below. The default is `computed`. If another method is desired, it should be specified in `phase_info` for each individual mission segment.\n", + "For mission analysis, FLOPS-based aerodynamics has several choices of method to determine the total lift and drag on the vehicle, listed below. The default is `computed`. If another method is desired, it should be specified in {glue:md}`phase_info` for each individual mission segment.\n", "- `computed`: uses regression-based techniques to estimate lift and drag\n", "- `low_speed`: for use in detailed takeoff analysis, and includes high-lift devices and considers angle-of-attack\n", "- `tabular`: allows the user to substitute the lift and drag coefficient calculations in `computed` with data tables\n", + "- `external`: disables Aviary's core aerodynamics computation, intended for use with external subsystems to replace all aerodynamic calculations.\n", "\n", "### Computed Aerodynamics\n", "The FLOPS based aerodynamics subsystem uses a modified version of algorithms from the EDET (Empirical Drag Estimation Technique) program [^edet] to internally compute drag polars. FLOPS improvements to EDET as implemented in Aviary include smoothing of drag polars, more accurate Reynolds number calculations, and use of the Sommer and Short T' method [^tprime] for skin friction calculations.\n", "\n", "### Low Speed Aerodynamics\n", - "This aerodynamics routine is designed for use with the height-energy detailed takeoff phase, which includes use of high-lift devices. This aerodynamics method uses angle of attack, which is a special case not present in other height-energy phases.\n", + "This aerodynamics routine is designed for use with the {glue:md}`height_energy` detailed takeoff phase, which includes use of high-lift devices. This aerodynamics method uses angle of attack, which is a special case not present in other {glue:md}`height_energy` phases.\n", "\n", "### User Specified Tabular Drag Polars\n", "Third party drag polars can be specified by the user, either via a data file in [Aviary data format](./input_files) or a NamedValues object. Two tables are required, one for lift-dependent drag, and another for zero-lift drag.\n", "- The lift-dependent drag coefficient table must include Mach number and lift coefficient as independent variables.\n", "- The zero-lift drag coefficient table must include altitude and Mach number as independent variables.\n", "\n", - "Tabular aerodynamics uses Aviary's [data_interpolator_builder](../_srcdocs/packages/utils/data_interpolator_builder) interface. This component is unique as it requires two data tables to be provided. All configuration options, such as the choice to use a structured metamodel or training data, are applied to both tables." + "Tabular aerodynamics uses Aviary's [data_interpolator_builder](../_srcdocs/packages/utils/data_interpolator_builder) interface. This component is unique as it requires two data tables to be provided. All configuration options, such as the choice to use a structured metamodel or training data, are applied to both tables.\n", + "\n", + "### External Aerodynamics\n", + "Selecting the `external` aerodynamics method disables Aviary's core aerodynamics group. This allows for external subsystems to completely replace these calculations." ] }, { @@ -138,17 +206,22 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.api import LegacyCode, CoreAerodynamicsBuilder, AviaryValues\n", + "from aviary.api import AviaryValues, CoreAerodynamicsBuilder, LegacyCode\n", + "\n", "cab = CoreAerodynamicsBuilder(code_origin=LegacyCode.FLOPS)\n", "# here we are only checking that the CoreAerodynamicsBuilder has a build_mission for a given method\n", "# we know this will fail when it attempts to build the aero groups\n", - "for method in (None,'computed','low_speed','tabular','solved_alpha'):\n", + "for method in (None, 'computed', 'low_speed', 'tabular', 'external'):\n", " try:\n", - " cab.build_mission(1,AviaryValues(),method=method)\n", + " cab.build_mission(1, AviaryValues(), method=method)\n", " except ValueError as e:\n", " raise e\n", " except:\n", - " pass" + " pass\n", + "try:\n", + " cab.build_mission(1, AviaryValues(), method='computed', solve_alpha=True)\n", + "except KeyError:\n", + " pass" ] }, { @@ -158,14 +231,18 @@ "## GASP Based\n", "### Using GASP Aerodynamics with the Height-Energy Equations of Motion (FLOPS Mission)\n", "\n", - "You can also use GASP-based aero with the height-energy mission by using the `solved_alpha` method.\n", + "You can also use GASP-based aero with the {glue:md}`height_energy` mission by using the `solve_alpha` flag.\n", "\n", - "Gasp-based drag polars have 3 inputs: altitude, mach number, and angle of attack. Since the height-energy equations of motion do not incorporate angle of attack, `solved_alpha` creates an computational group with a solver that varies the angle of attack until the interpolated lift matches the weight force on the aircraft. The format for the table in the file is the same as for GASP-based aerodynamics used with the 2-DOF mission.\n", + "GASP-based drag polars have 3 inputs: altitude, Mach number, and angle of attack. Since the {glue:md}`height_energy` equations of motion do not incorporate angle of attack, `solve_alpha` adds a computational group with a solver that varies the angle of attack until the lift from the FLOPS aero module matches the weight force on the aircraft. When using tabular aerodynamics, the format for the drag table file is the same as for GASP-based aerodynamics used with the {glue:md}`2DOF` mission.\n", "\n", "## Externally Computed Polars\n", "\n", "Both FLOPS and GASP methods that use data tables support the use of training data, where the values for interpolation are provided by another openMDAO component via connections. An example problem using this method can be found [here](./external_aero).\n", "\n", + "## References\n", + "\n", + "These papers provide a thorough overview of the specific methodologies used for emperical drag prediction in Aviary.\n", + "\n", "[^edet]: Feagin, Richard C. and Morrison, William D., Jr. \"Delta Method, An Empirical\n", "Drag Buildup Technique.\" NASA CR-151971, December 1978.\n", "\n", @@ -191,7 +268,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.1.-1" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/aviary_commands.ipynb b/aviary/docs/user_guide/aviary_commands.ipynb index 853d6ec5eb..62d56db6cc 100644 --- a/aviary/docs/user_guide/aviary_commands.ipynb +++ b/aviary/docs/user_guide/aviary_commands.ipynb @@ -1,5 +1,27 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.interface.cmd_entry_points import _command_map\n", + "from aviary.utils.doctape import glue_keys, glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "# glue all the options of 'aviary'\n", + "glue_keys(_command_map)\n", + "for key in _command_map:\n", + " glue_variable('aviary ' + key, md_code=True)" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -22,7 +44,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -41,11 +62,10 @@ }, "outputs": [], "source": [ - "!aviary -h" + "!aviary -h 2>/dev/null" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -53,7 +73,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -72,11 +91,10 @@ }, "outputs": [], "source": [ - "!aviary run_mission -h" + "!aviary run_mission -h 2>/dev/null" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -86,11 +104,16 @@ "(aviary-run_mission-command)=\n", "### aviary run_mission\n", "\n", - "`run_mission` is a command line interface that will run an analysis on a given csv input file.\n", - "\n", - "To use small_single_aisle_GwGm.csv run the command `aviary run_mission models/small_single_aisle/small_single_aisle_GwGm.csv`
\n", - "\n", - "SNOPT is the default optimizer, but IPOPT is available as well." + "{glue:md}`run_mission` is a command line interface that will run an analysis on a given csv input file." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "aviary run_mission -h\n", + "```" ] }, { @@ -103,21 +126,18 @@ }, "outputs": [], "source": [ - "# Testing Cell\n", - "import subprocess\n", - "command = 'aviary run_mission models/small_single_aisle/small_single_aisle_GwGm.csv'\n", - "command += ' --max_iter 0 --optimizer IPOPT' # max_iter to limit build time, IPOPT to run on CI\n", - "subprocess.run(command.split()).check_returncode();\n" + "!aviary run_mission -h 2>/dev/null" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ - "```\n", - "aviary run_mission -h\n", - "```" + "To use {glue:md}`small_single_aisle_GASP.csv`, run the command\n", + "{glue:md}`aviary run_mission models/aircraft/small_single_aisle/small_single_aisle_GASP.csv` in\n", + "{glue:md}`aviary/models/aircraft/small_single_aisle`\n", + "\n", + "SNOPT is the default optimizer, but IPOPT is available as well." ] }, { @@ -125,26 +145,94 @@ "execution_count": null, "metadata": { "tags": [ - "remove-input" + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import os\n", + "import subprocess\n", + "\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "str_folder = 'models/aircraft/small_single_aisle'\n", + "folder = av.get_path(str_folder)\n", + "model_dir = folder.relative_to(av.top_dir.parent)\n", + "glue_variable(model_dir, md_code=True)\n", + "\n", + "str_model = 'small_single_aisle_GASP.csv'\n", + "folder = av.get_path(str_folder) / (str_model)\n", + "file_name = os.path.basename(folder)\n", + "glue_variable(file_name, md_code=False)\n", + "\n", + "command = 'aviary run_mission ' + str_folder + '/' + str_model\n", + "glue_variable(command, md_code=True)\n", + "command += ' --max_iter 0 --optimizer IPOPT' # max_iter to limit build time, IPOPT to run on CI\n", + "subprocess.run(command.split()).check_returncode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" ] }, "outputs": [], "source": [ - "!aviary run_mission -h" + "# Testing Cell\n", + "import inspect\n", + "\n", + "import aviary.api as av\n", + "from aviary.interface.methods_for_level1 import run_level_1\n", + "from aviary.utils.doctape import glue_actions, glue_variable\n", + "from aviary.variable_info.variables import Settings\n", + "\n", + "# glue all the options of 'aviary run_mission'\n", + "glue_actions('run_mission', current_glued_vars, md_code=True)\n", + "\n", + "glue_variable(av.EquationsOfMotion.HEIGHT_ENERGY.value, md_code=False, display=True)\n", + "glue_variable(av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value, md_code=False, display=True)\n", + "glue_variable(av.EquationsOfMotion.SOLVED_2DOF.value, md_code=False, display=True)\n", + "glue_variable('equations_of_motion', Settings.EQUATIONS_OF_MOTION, display=True)\n", + "\n", + "# obtain the default value of maximum number of iterations from function run_level_1().\n", + "max_iter = inspect.signature(run_level_1).parameters['max_iter'].default\n", + "if 'max_iter' not in current_glued_vars:\n", + " glue_variable('max_iter', str(max_iter), md_code=False)\n", + " current_glued_vars.append('max_iter')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`input_deck` is the path to vehicle input deck .csv file.\n", - "`-o` or `--outdir` is the directory to write outputs. The default is current directory.\n", - "`--optimizer` is the name of the optimizer. The default is `SNOPT`.\n", - "`--shooting` indicates that the integration method is shooting method instead of collocation scheme. The default is collocation.\n", - "`--phase_info` is the path to phase info file. If it is missing, it depends on the integration method (collocation or shooting) and on the mission method (settings:equations+of_motion with value of `2DOF` or `height_energy`) which is defined in the .csv input file.\n", - "`--max_iter` is the maximum number of iterations. The default is 50.\n", + "{glue:md}`input_deck` is the path to vehicle input deck .csv file.\n", + "{glue:md}`--optimizer` is the name of the optimizer. The default is `IPOPT`.\n", + "{glue:md}`--phase_info` is the path to phase info file. If it is missing, it depends on the mission method (`equations_of_motion` with value of {glue:md}`2DOF` or {glue:md}`height_energy`) which is defined in the .csv input file.\n", + "{glue:md}`--max_iter` is the maximum number of iterations. The default is {glue:md}`max_iter`.\n", + "\n", + "More detailed information and examples can be found in the [Level 1 interface](../getting_started/onboarding_level1.ipynb)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.utils.doctape import glue_actions\n", "\n", - "More detailed discussions can be found in [onboarding_level1](../getting_started/onboarding_level1.ipynb)." + "# glue all the options of 'aviary fortran_to_aviary'\n", + "glue_actions('fortran_to_aviary', current_glued_vars, md_code=True)" ] }, { @@ -155,48 +243,99 @@ "(aviary-fortran_to_aviary-command)=\n", "### aviary fortran_to_aviary\n", "\n", - "The `aviary fortran_to_aviary` command will convert a Fortran input deck to an Aviary csv.\n", - "\n", - "The only two required inputs are `-l` (for `--legacy_code` with options `FLOPS` and `GASP`) and the filepath to the input deck. \n", - "Optionally, a deck of default values can be specified via the option `-d` (for `--defaults_deck`) and a default deck file, this is useful if an input deck assumes certain values for any unspecified variables.\n", + "The {glue:md}`aviary fortran_to_aviary` command will convert a Fortran input deck to an Aviary csv.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "aviary fortran_to_aviary -h\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-input" + ] + }, + "outputs": [], + "source": [ + "!aviary fortran_to_aviary -h 2>/dev/null" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The only two required inputs are the filepath to the input deck and {glue:md}`-l` (for {glue:md}`--legacy_code` with options `FLOPS` and `GASP`).\n", "When this command is run, a brief message is printed. To print more messages, one can set verbosity level higher. For example, `-v 3` will result in debug messages being printed. See [Controlling Display Levels](../developer_guide/coding_standards.ipynb) for more details.\n", "If an invalid filepath is given, pre-packaged resources will be checked for input decks with a matching name.\n", "If the output file name is not specified, a detault name is assumed to be the trunk of the input file name with `csv` as file extension. For example, an input file `sample.dat` will result in `sample_converted.csv`.\n", - "If the output file exists, the command will not run unless the user specifies `--force` to force the overwritten action.\n", + "If the output file exists, the command will not run unless the user specifies {glue:md}`--force` to force the overwritten action.\n", "\n", - "Here, pre-packaged resources are absolute path, relative path, and Aviary based path.\n", + "Here, pre-packaged resources are absolute path, relative path, Aviary based path, and relative path relative to the Aviary models folder.\n", "\n", "Notes for input decks:\n", - "- FLOPS, GASP, or Aviary names can be used for variables (Ex WG or Mission:Design:GROSS_MASS)\n", - "- When specifying variables from FORTRAN, they should be in the appropriate NAMELIST.\n", - "- Aviary variable names should be specified outside any NAMELISTS.\n", - "- Names are not case-sensitive.\n", - "- Units can be specified using any of the openMDAO valid units.\n", - "- Comments can be added using !\n", - "- Lists can be entered by separating values with commas.\n", - "- Individual list elements can be specified by adding an index after the variable name.\n", - "- (NOTE: 1 indexing is used inside NAMELISTS, while 0 indexing is used outside NAMELISTS)\n", - "\n", - "Example inputs:\n", + "- When specifying variables from FORTRAN, they should be in the appropriate NAMELIST\n", + "- Names are not case-sensitive\n", + "- Comments can be added using \"!\"\n", + "- Lists can be entered by separating values with commas on the same line\n", + "- For GASP variables where required, individual list elements can be specified by adding an index after the variable name\n", + " - (NOTE: 1 indexing is used inside NAMELISTS, while 0 indexing is used outside NAMELISTS)\n", + "\n", + "Example inputs (GASP-style file):\n", "```\n", - "aircraft:fuselage:pressure_differential = .5, atm !DELP in GASP, but using atmospheres instead of psi\n", - "ARNGE(1) = 3600 !target range in nautical miles\n", - "pyc_phases = taxi, groundroll, rotation, landing\n", + "$INGASP\n", + "DELP = 7.34797 ! typical GASP input\n", + "ARNGE(1) = 3600 ! variable with specified index\n", + "ACLS = 0.0,0.40,0.60,0.80,1.00,1.20, 1.40,1.60,1.80, ! values given as array\n", "```\n", "\n", "Example usage:\n", - "```\n", - "`aviary fortran_to_aviary --legacy_code GASP --force GASP_test.dat` Convert the GASP input deck to Aviary (even if an output exists).\n", - "```\n" + "`aviary fortran_to_aviary --legacy_code GASP --force GASP_test.dat` Converts the GASP input deck to Aviary (even if a file with the name GASP_test.dat already exists)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "# glue all the options of 'aviary convert_engine'\n", + "glue_actions('convert_engine', current_glued_vars, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(aviary-hangar-command)=\n", + "### aviary hangar\n", + "\n", + "The {glue:md}`aviary hangar` command will copy files and folders from the Aviary hangar to an accessible directory.\n", + "This is useful for users that have pip installed Aviary, but want to experiment with the included examples.\n", + "\n", + "\n" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "```\n", - "aviary fortran_to_aviary -h\n", + "aviary hangar -h\n", "```" ] }, @@ -210,19 +349,13 @@ }, "outputs": [], "source": [ - "!aviary fortran_to_aviary -h" + "!aviary hangar -h 2>/dev/null" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "(aviary-hangar-command)=\n", - "### aviary hangar\n", - "\n", - "The `aviary hangar` command will copy files and folders from the Aviary hangar to an accessible directory.\n", - "This is useful for users that have pip installed Aviary, but want to experiment with the included examples.\n", - "\n", "The only required input is the name of an input deck.\n", "This can be specified as the name of the file, the path from [aviary/models](https://github.com/OpenMDAO/Aviary/tree/main/aviary/models), the name of a folder in aviary/models. Multiple files and folders can be copied at once.\n", "Optionally, the output directory can be specified; if it is not, the files will be copied into the current working directory in a folder called `aviary_models`.\n", @@ -230,12 +363,17 @@ "\n", "Example usage:\n", "```\n", - "`aviary hangar engines` Copy all files in the engines folder\n", - "`aviary hangar turbofan_22k.txt` Copy the 22k turbofan deck\n", - "`aviary hangar N3CC/N3CC_data.py` Copy the N3CC data\n", - "`aviary hangar small_single_aisle_GwGm.dat small_single_aisle_GwGm.csv` Copy the Fortran and Aviary input decks for the small single aisle\n", - "`aviary hangar turbofan_22k.txt -o ~/example_files` Copy the engine model into ~/example_files\n", - "```\n" + "# Copy all files in the engines folder\n", + "aviary hangar engines\n", + "# Copy the 22k turbofan deck\n", + "aviary hangar turbofan_22k.txt\n", + "# Copy the N3CC data\n", + "aviary hangar advanced_single_aisle/advanced_single_aisle_data.py\n", + "# Copy the Fortran and Aviary input decks for the small single aisle\n", + "aviary hangar small_single_aisle_GwGm.dat small_single_aisle_GwGm.csv\n", + "# Copy the engine model into ~/example_files\n", + "aviary hangar turbofan_22k.txt -o ~/example_files\n", + "```" ] }, { @@ -249,18 +387,39 @@ "outputs": [], "source": [ "# Testing Cell\n", + "import os\n", "import subprocess\n", "import tempfile\n", - "import os\n", + "\n", "commands = [\n", - " 'engines','turbofan_22k.txt','N3CC/N3CC_data.py',\n", - " 'small_single_aisle_GwGm.dat small_single_aisle_GwGm.csv',\n", - " 'turbofan_22k.txt -o ~/example_files']\n", - "with tempfile.TemporaryDirectory() as tempdir:\n", - " os.chdir(tempdir)\n", - " for command in commands:\n", - " command = 'aviary hangar ' + command\n", - " subprocess.run(command.split()).check_returncode();" + " 'engines',\n", + " 'turbofan_22k.csv',\n", + " 'advanced_single_aisle/advanced_single_aisle_data.py',\n", + " 'small_single_aisle_GASP.dat small_single_aisle_GASP.csv',\n", + " 'turbofan_22k.csv -o ~/example_files',\n", + "]\n", + "# Save the current directory\n", + "original_cwd = os.getcwd()\n", + "\n", + "try:\n", + " with tempfile.TemporaryDirectory() as tempdir:\n", + " os.chdir(tempdir)\n", + " for command in commands:\n", + " command = 'aviary hangar ' + command\n", + " subprocess.run(command.split()).check_returncode()\n", + "finally:\n", + " # Always restore the original directory\n", + " os.chdir(original_cwd)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(aviary-EDC-command)=\n", + "### aviary convert_engine\n", + "\n", + "The {glue:md}`aviary convert_engine` command will convert a legacy formatted (FLOPS or GASP) engine deck into an Aviary formatted engine deck." ] }, { @@ -268,7 +427,7 @@ "metadata": {}, "source": [ "```\n", - "aviary hangar -h\n", + "aviary convert_engine -h\n", "```" ] }, @@ -282,27 +441,22 @@ }, "outputs": [], "source": [ - "!aviary hangar -h" + "!aviary convert_engine -h 2>/dev/null" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "(aviary-EDC-command)=\n", - "### aviary convert_engine\n", - "\n", - "The `aviary convert_engine` command will convert a legacy formatted (FLOPS or GASP) engine deck into an Aviary formatted engine deck.\n", - "\n", "Users must provide the path or name of an input deck, and the engine format being converted.\n", "If an invalid filepath is given for the input file, pre-packaged resources will be checked for input decks with a matching name.\n", "\n", "The path to the output file name is optional. If it is missing, the output file name takes the \n", - "trunk of the input file name with `deck` as default file extension. For example, an input file `sample.eng` will result in `sample.deck` unless the user specifies the output file name.\n", + "trunk of the input file name with `deck` as default file extension. For example, an input file `sample.eng` will result in `sample.csv` unless the user specifies the output file name.\n", "\n", "If the output file exists, it will be overwritten.\n", "\n", - "The engine format is specified by `-f` or `--data_format` with one of `FLOPS`, `GASP`, and `GASP_TS` string. If multiple are specified, the last one will be used.\n", + "The engine format is specified by {glue:md}`-f` or {glue:md}`--data_format` with one of `FLOPS`, `GASP`, and `GASP_TS` string (`TS` stands for turboshaft). If multiple are specified, the last one will be used.\n", "\n", "Notes for input decks:\n", "- Turbofan decks for both FLOPS and GASP can be converted\n", @@ -311,11 +465,15 @@ "\n", "\n", "Example usage:\n", + "\n", "```\n", - "`aviary convert_engine turbofan_23k_1.eng turbofan_23k_1_lbm_s.deck -f GASP` Convert a GASP based turbofan\n", - "`aviary convert_engine -f FLOPS turbofan_22k.eng turbofan_22k.txt` Convert a FLOPS based turbofan\n", - "`aviary convert_engine turboshaft_4465hp.eng turboshaft_4465hp.deck --data_format GASP_TS` Convert a GASP based turboshaft\n", - "```\n" + "# Convert a GASP based turbofan\n", + "aviary convert_engine turbofan_23k_1.eng turbofan_23k_1.csv -f GASP \n", + "# Convert a FLOPS based turbofan\n", + "aviary convert_engine turbofan_22k.eng turbofan_22k.csv -f FLOPS \n", + "# Convert a GASP based turboshaft\n", + "aviary convert_engine turboshaft_4465hp.eng turboshaft_4465hp.csv --data_format GASP_TS\n", + "```" ] }, { @@ -330,21 +488,48 @@ "source": [ "# Testing Cell\n", "from aviary.utils.doctape import run_command_no_file_error\n", + "\n", "commands = [\n", - " 'utils/test/data/GASP_turbofan_23k_1.eng turbofan_23k_1_lbm_s.deck -f GASP',\n", - " 'utils/test/data/FLOPS_turbofan_22k.txt turbofan_22k.txt -f FLOPS',\n", - " 'turboshaft_4465hp.eng turboshaft_4465hp.deck -f GASP_TS',\n", - " ]\n", + " 'utils/test/data/turbofan_23k_1.eng turbofan_23k_1.csv -f GASP',\n", + " 'utils/test/data/turbofan_22k.txt turbofan_22k.csv -f FLOPS',\n", + " 'utils/test/data/turboshaft_4465hp.eng turboshaft_4465hp.csv -f GASP_TS',\n", + "]\n", "for command in commands:\n", " run_command_no_file_error('aviary convert_engine ' + command)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "# glue all the options of 'aviary convert_aero_table'\n", + "glue_actions('convert_aero_table', current_glued_vars, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(aviary-ATC-command)=\n", + "### aviary convert_aero_table\n", + "\n", + "The {glue:md}`aviary convert_aero_table` command will convert a legacy formatted (FLOPS or GASP) aero table into an Aviary formatted aero table.\n" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", - "aviary convert_engine -h\n", + "aviary convert_aero_table -h\n", "```" ] }, @@ -358,42 +543,36 @@ }, "outputs": [], "source": [ - "!aviary convert_engine -h" + "!aviary convert_aero_table -h 2>/dev/null" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "(aviary-ATC-command)=\n", - "### aviary convert_aero_table\n", - "\n", - "The `aviary convert_aero_table` command will convert a legacy formatted (FLOPS or GASP) aero table into an Aviary formatted aero table.\n", - "\n", "Users must provide the path or name of an input deck and the data format being converted.\n", "Optionally, the path to the output file can also be specified, otherwise the default output file will be in the same location and have the same name as input file, but with '_aviary' appended to the end of filename trunk while the file extension is preserved. For example, an input file `sample.txt` will result in `sample_aviary.txt` unless the user specifies the output file name.\n", - "If both `-f` and `--data_format` are specified, the later one is taken.\n", + "If both {glue:md}`-f` and {glue:md}`--data_format` are specified, the later one is taken.\n", "If an existing file has the same name as output file name, the existing file will be overwritten.\n", "If an invalid filepath is given for the input file, pre-packaged resources will be checked for input decks with a matching name.\n", "\n", "Notes for input decks:\n", "- Aero tables for both FLOPS and GASP can be converted\n", "- GASP tables will create a single file containing all the lift and drag information\n", + "- There are two types of GASP tables. The first one combines CL and CD into one single table. The second one has them separated with a possible CD0 table. We name the first one as `GASP_ALT` and the second one as `GASP`. The second one is usually obtained by high fidelity CFD tools.\n", "- FLOPS tables will create two files, one containing the lift-dependent drag and the other containing the lift-independent drag.\n", "- Comments can be added using #\n", "\n", "\n", "Example usage:\n", "```\n", - "`aviary convert_aero_table -f GASP subsystems/aerodynamics/gasp_based/data/GASP_aero_free.txt large_single_aisle_1_aero_flaps.txt` Convert a GASP based aero table\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "`aviary convert_aero_table -f FLOPS utils/test/flops_test_polar.txt aviary_flops_polar.txt` Convert a FLOPS based aero table\n", - "```\n" + "# Converts a GASP based aero table \n", + "aviary convert_aero_table -f GASP_ALT utils/test/data/aero_free_GASP.txt large_single_aisle_1_aero_flaps.csv\n", + "# Converts a GASP based alternative aero table \n", + "aviary convert_aero_table -f GASP utils/test/data/aero_BWB_modified_GASP.txt generic_BWB_GASP_aero.csv\n", + "# Converts a FLOPS based aero table\n", + "aviary convert_aero_table -f FLOPS utils/test/data/flops_test_polar.txt aviary_flops_polar.txt\n", + "```" ] }, { @@ -408,12 +587,24 @@ "source": [ "# Testing Cell\n", "from aviary.utils.doctape import run_command_no_file_error\n", + "\n", "commands = [\n", - " '-f GASP subsystems/aerodynamics/gasp_based/data/GASP_aero_free.txt large_single_aisle_1_aero_flaps.txt',\n", - " '-f FLOPS utils/test/flops_test_polar.txt aviary_flops_polar.txt',\n", + " '-f GASP_ALT utils/test/data/aero_free_GASP.txt large_single_aisle_1_aero_flaps.csv',\n", + " '-f GASP utils/test/data/aero_BWB_modified_GASP.txt',\n", + " '-f FLOPS utils/test/data/flops_test_polar.txt aviary_flops_polar.txt',\n", "]\n", "for command in commands:\n", - " run_command_no_file_error('aviary convert_aero_table ' + command)\n" + " run_command_no_file_error('aviary convert_aero_table ' + command)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(aviary-PMC-command)=\n", + "### aviary convert_prop_table\n", + "\n", + "The {glue:md}`aviary convert_prop_table` command converts a legacy formatted (GASP) propeller map into an Aviary formatted propeller map. Currently, GASP is the only format supported." ] }, { @@ -421,7 +612,7 @@ "metadata": {}, "source": [ "```\n", - "aviary convert_aero_table -h\n", + "aviary convert_prop_table -h\n", "```" ] }, @@ -435,20 +626,15 @@ }, "outputs": [], "source": [ - "!aviary convert_aero_table -h" + "!aviary convert_prop_table -h 2>/dev/null" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "(aviary-PMC-command)=\n", - "### aviary convert_prop_table\n", - "\n", - "The `aviary convert_prop_table` command will convert a legacy formatted (GASP) propeller map into an Aviary formatted propeller map. Currently, it is the only format allowed and so it is the default format.\n", - "\n", - "Users must provide the path or name of an input deck, the path to the output file, and the engine format being converted.\n", - "If an invalid filepath is given for the input file, pre-packaged resources will be checked for input decks with a matching name.\n", + "Users must provide the path or name of an input deck, and optionally the path to the desired output file. If not provided, the output file will have the same filename as the input file but with the exension `.prop`. This is arbitrary, and `.prop` is not a required file extension for propeller data files, but it is designed to help users recognize the purpose of the data table without needing to open it.\n", + "If an invalid filepath is given for the input file, Aviary's files will be checked for input decks with a matching name.\n", "\n", "Notes for input decks:\n", "- There are two options for Mach number: Mach number and helical Mach number at 75% radius. We provide one example for each. This is the first integer on the first line of the input file. (1 = Mach, 2 = helical Mach)\n", @@ -456,23 +642,39 @@ "\n", "\n", "Example usage:\n", + "\n", "```\n", - "`aviary convert_prop_table -f GASP PropFan.map PropFan.prop` Convert a GASP based propeller map\n", - "`aviary convert_prop_table -f GASP general_aviation.map general_aviation.prop` Convert a GASP based propeller map\n", - "`aviary convert_prop_table general_aviation.map` Convert a GASP based propeller map\n", + "# Convert GASP based propeller map PropFan.map to Aviary data table PropFan.csv\n", + "aviary convert_prop_table PropFan.map PropFan.csv\n", + "# Convert GASP based propeller map general_aviation.map to Aviary data table general_aviation.csv\n", + "aviary convert_prop_table general_aviation.map general_aviation.csv\n", + "# Convert GASP based propeller map general_aviation.map to Aviary data table general_aviation.csv\n", + "aviary convert_prop_table general_aviation.map\n", "```\n", - "\n", "The first example uses Mach number and the second example uses helical Mach number. \n", - "Note that the output file name can be skipped as demonstrated in the third example. Since there is only one input data format that is supported at this time, it defaults to GASP if not provided. This is shown in the third example as well." + "Note that the output file name was not specified in the third example." ] }, { - "cell_type": "markdown", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], "source": [ - "```\n", - "aviary convert_prop_table -h\n", - "```" + "# Testing Cell\n", + "from aviary.utils.doctape import run_command_no_file_error\n", + "\n", + "commands = [\n", + " 'models/engines/propellers/PropFan.map PropFan.csv',\n", + " 'models/engines/propellers/general_aviation.map general_aviation.csv',\n", + " 'models/engines/propellers/general_aviation.map',\n", + "]\n", + "for command in commands:\n", + " run_command_no_file_error('aviary convert_prop_table ' + command)" ] }, { @@ -480,12 +682,13 @@ "execution_count": null, "metadata": { "tags": [ - "remove-input" + "remove-cell" ] }, "outputs": [], "source": [ - "!aviary convert_prop_table -h" + "# glue all the options of 'aviary convert_prop_table'\n", + "glue_actions('convert_prop_table', current_glued_vars, md_code=True)" ] }, { @@ -495,7 +698,7 @@ "(aviary-draw-command)=\n", "### aviary draw_mission\n", "\n", - "The `aviary draw_mission` command will bring up a new graphical interface for users to create a mission. This command does not have an input. More details can be found at [Drawing and running simple missions](drawing_and_running_simple_missions.ipynb)." + "The {glue:md}`aviary draw_mission` command will bring up a new graphical interface for users to create a mission. This command does not have an input. More details can be found at [Drawing and running simple missions](drawing_and_running_simple_missions.ipynb)." ] }, { @@ -505,16 +708,45 @@ "(aviary-plot-command)=\n", "### aviary plot_drag_polar\n", "\n", - "The `aviary plot_drag_polar` command will bring up a new graphical interface for users to draw drag polar. No options are needed on the command line but a file explorer window will pop-up to allow the user to select a drag polar file (a `.csv` file). It is not working at this time." + "The {glue:md}`aviary plot_drag_polar` command will bring up a new graphical interface for users to draw drag polar. No options are needed on the command line but a file explorer window will pop-up to allow the user to select a drag polar file (a `.csv` file). It is not working at this time." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "aviary plot_drag_polar -h\n", + "```" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [ + "remove-input" + ] + }, + "outputs": [], + "source": [ + "!aviary plot_drag_polar -h 2>/dev/null" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, "outputs": [], "source": [ - "!aviary plot_drag_polar -h" + "# Testing Cell\n", + "\n", + "# glue all the options of 'aviary dashboard'\n", + "glue_actions('dashboard', current_glued_vars, glue_default=True, md_code=True)" ] }, { @@ -524,16 +756,29 @@ "(aviary-dashboard-command)=\n", "### aviary dashboard\n", "\n", - "The `aviary dashboard` command will bring up a dashboard that lets the user easily browse between the reports and files that are generated during an Aviary run." + "The {glue:md}`aviary dashboard` command will bring up a dashboard that lets the user easily browse between the reports and files that are generated during an Aviary run." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "aviary dashboard -h\n", + "```" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [ + "remove-input" + ] + }, "outputs": [], "source": [ - "!aviary dashboard -h" + "!aviary dashboard -h 2>/dev/null" ] }, { @@ -542,23 +787,63 @@ "source": [ "To use this utility, either a problem has been run or a run script is provided.\n", "\n", - "`--problem_recorder` is an input. Default is `problem_history.db`.\n", - "`--driver_recorder` is an optional input.\n", - "`--port` is the dashboard server port ID. The default is `0` meaning any free port.\n", - "`-b` or `--background` indicates to run in background. Default is `False`.\n", - "`-d` or `--debug` indicates to show debugging output. Default is `False`.\n", - "`--save` is the name of zip file in which dashboard files are saved. If no argument given, use the script name to name the zip file.\n", - "`--force` indicates to overwrite the saved zip file. The default is `False`.\n", - "`script_name` is the name of aviary script that was run (not including .py), or the csv input filename if the user runs a Level 1 script.\n", + "{glue:md}`--port` is the dashboard server port ID. The default is {glue:md}`port_default` meaning any free port.\n", + "{glue:md}`-b` or {glue:md}`--background` indicates to run in background. Default is `False`.\n", + "{glue:md}`-d` or {glue:md}`--debug` indicates to show debugging output. Default is `False`.\n", + "{glue:md}`--save` is the name of zip file in which dashboard files are saved. If no argument given, use the script name to name the zip file.\n", + "{glue:md}`--force` indicates to overwrite the saved zip file. The default is `False`.\n", + "{glue:md}`script_name` is the name of aviary script that was run (not including .py), or the csv input filename if the user runs a Level 1 script.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "More discussion on {glue:md}`aviary dashboard` command can be found in [Postprocessing and Visualizing Results from Aviary](postprocessing_and_visualizing_results.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "(aviary-rtplot-command)=\n", + "### aviary rtplot\n", "\n", - "More discussion on `aviary dashboard` command can be found in [Postprocessing and Visualizing Results from Aviary](postprocessing_and_visualizing_results.ipynb)." + "The {glue:md}`aviary rtplot` command runs an Aviary script and also displays a real-time plot of the variables as an optimization progresses. It makes use of the data being written to a case recorder file, the script must add a recorder to the `Driver`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "aviary rtplot -h\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!aviary rtplot -h 2>/dev/null" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An example of using this command would be\n", + "```\n", + "aviary rtplot aviary_script.py\n", + "```" ] } ], "metadata": { - "celltoolbar": "Tags", "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -572,7 +857,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/battery_subsystem_example.ipynb b/aviary/docs/user_guide/battery_subsystem_example.ipynb index f0491516b7..3e7bed5f62 100644 --- a/aviary/docs/user_guide/battery_subsystem_example.ipynb +++ b/aviary/docs/user_guide/battery_subsystem_example.ipynb @@ -1,5 +1,26 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "folder = av.get_path('examples/external_subsystems/battery')\n", + "examples_dir = folder.relative_to(av.top_dir.parent)\n", + "glue_variable(examples_dir, md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -9,7 +30,7 @@ "## Examining the battery as an example case\n", "\n", "Let's take a look at how to integrate an external subsystem into Aviary using the example of a battery model.\n", - "This battery model and builder are provided in the `aviary/examples/external_subsystems/battery` folder.\n", + "This battery model and builder are provided in the {glue:md}`aviary/examples/external_subsystems/battery` folder.\n", "\n", "We'll show you how to define the builder object, how to specify the pre-mission and mission models, and how to implement the interface methods.\n", "In each of these methods, we've removed the initial docstring to increase readability on this page.\n", @@ -34,8 +55,13 @@ "outputs": [], "source": [ "# Testing Cell\n", + "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase\n", + "from aviary.utils.doctape import glue_variable\n", "from aviary.utils.functions import get_path\n", - "get_path('examples/external_subsystems/battery/battery_builder.py');\n" + "\n", + "# make sure that the path exists.\n", + "get_path('examples/external_subsystems/battery/battery_builder.py')\n", + "glue_variable(SubsystemBuilderBase.__name__, md_code=True)" ] }, { @@ -45,7 +71,7 @@ "## Defining the builder object\n", "\n", "The first step is to define a builder object for your external subsystem.\n", - "This class extends the `SubsystemBuilderBase` class and provides implementations for all of the interface methods that Aviary requires.\n", + "This class extends the {glue:md}`SubsystemBuilderBase` class and provides implementations for all of the interface methods that Aviary requires.\n", "\n", "```{note}\n", "Throughout this doc page we add methods to the builder class in different sections.\n", @@ -60,10 +86,10 @@ "outputs": [], "source": [ "import aviary.api as av\n", - "from aviary.examples.external_subsystems.battery.model.battery_premission import BatteryPreMission\n", - "from aviary.examples.external_subsystems.battery.model.battery_mission import BatteryMission\n", - "from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Mission\n", "from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData\n", + "from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Dynamic\n", + "from aviary.examples.external_subsystems.battery.model.battery_mission import BatteryMission\n", + "from aviary.examples.external_subsystems.battery.model.battery_premission import BatteryPreMission\n", "\n", "\n", "class BatteryBuilder(av.SubsystemBuilderBase):\n", @@ -84,7 +110,51 @@ "You can use any arguments that the `add_state` command accepts here, including `ref`s, `bound`s, `solve_segments`, and more.\n", "Please see the [Dymos docs for states](https://openmdao.github.io/dymos/features/phases/variables.html#states) for a table of all the available input args.\n", "\n", - "Within the subsystem builder, we will now define the states of the battery model using the `get_states` method." + "Within the subsystem builder, we will now define the states of the battery model using the {glue:md}`get_states()` method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "import aviary.api as av\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase\n", + "from aviary.utils.doctape import (\n", + " get_variable_name,\n", + " glue_class_functions,\n", + " glue_function_arguments,\n", + " glue_variable,\n", + ")\n", + "\n", + "# Get all functions of class SubsystemBuilderBase\n", + "glue_class_functions(SubsystemBuilderBase, current_glued_vars)\n", + "\n", + "AviaryValues = av.AviaryValues\n", + "glue_variable(get_variable_name(AviaryValues), md_code=True)\n", + "\n", + "# retrieve all argument of build_pre_mission(self, aviary_inputs, **kwargs)\n", + "glue_function_arguments(SubsystemBuilderBase.build_pre_mission, current_glued_vars, md_code=True)\n", + "\n", + "\n", + "# retrieve all argument of build_mission(self, num_nodes, aviary_inputs, **kwargs)\n", + "glue_function_arguments(SubsystemBuilderBase.build_mission, current_glued_vars, md_code=True)\n", + "\n", + "\n", + "# Get all functions of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars)\n", + "\n", + "TestSubsystemBuilderBase = av.TestSubsystemBuilderBase\n", + "glue_variable(get_variable_name(TestSubsystemBuilderBase), md_code=True)" ] }, { @@ -96,15 +166,15 @@ "class BatteryBuilder(BatteryBuilder):\n", " def get_states(self):\n", " states_dict = {\n", - " Mission.Battery.STATE_OF_CHARGE: {\n", - " 'rate_source': Mission.Battery.STATE_OF_CHARGE_RATE,\n", + " Dynamic.Battery.STATE_OF_CHARGE: {\n", + " 'rate_source': Dynamic.Battery.STATE_OF_CHARGE_RATE,\n", " 'fix_initial': True,\n", " },\n", - " Mission.Battery.VOLTAGE_THEVENIN: {\n", + " Dynamic.Battery.VOLTAGE_THEVENIN: {\n", " 'units': 'V',\n", - " 'rate_source': Mission.Battery.VOLTAGE_THEVENIN_RATE,\n", - " 'defect_ref': 1.e5,\n", - " 'ref': 1.e5,\n", + " 'rate_source': Dynamic.Battery.VOLTAGE_THEVENIN_RATE,\n", + " 'defect_ref': 1.0e5,\n", + " 'ref': 1.0e5,\n", " },\n", " }\n", "\n", @@ -136,12 +206,12 @@ " def get_constraints(self):\n", " if self.include_constraints:\n", " constraints = {\n", - " Mission.Battery.STATE_OF_CHARGE: {\n", + " Dynamic.Battery.STATE_OF_CHARGE: {\n", " 'lower': 0.2,\n", " 'type': 'boundary',\n", " 'loc': 'final',\n", " },\n", - " Mission.Battery.VOLTAGE_THEVENIN: {\n", + " Dynamic.Battery.VOLTAGE_THEVENIN: {\n", " 'lower': 0,\n", " 'type': 'path',\n", " },\n", @@ -171,8 +241,8 @@ "class BatteryBuilder(BatteryBuilder):\n", " def get_parameters(self):\n", " parameters_dict = {\n", - " Mission.Battery.TEMPERATURE: {'val': 25.0, 'units': 'degC'},\n", - " Mission.Battery.CURRENT: {'val': 3.25, 'units': 'A'}\n", + " Dynamic.Battery.TEMPERATURE: {'val': 25.0, 'units': 'degC'},\n", + " Dynamic.Battery.CURRENT: {'val': 3.25, 'units': 'A'},\n", " }\n", "\n", " return parameters_dict" @@ -183,7 +253,7 @@ "metadata": {}, "source": [ "If you want to add high-level design variables to your external subsystem that are not exposed at the phase level, you can do so by creating a method that describes your desired design variables.\n", - "This method is called `get_design_vars`.\n", + "This method is called {glue:md}`get_design_vars()`.\n", "There might be calculations at the pre-mission level that necessitate using this method to allow the optimizer to control high-level sizing variables.\n", "In the simple battery case, we allow the optimizer to control the energy capacity of the battery, effectively sizing it." ] @@ -213,7 +283,7 @@ "source": [ "## Defining the OpenMDAO systems needed\n", "\n", - "Next up, we have the two methods for getting the mission and pre-mission models, `get_mission` and `get_pre_mission`, respectively.\n", + "Next up, we have the two methods for getting the mission and pre-mission models, {glue:md}`build_mission()` and {glue:md}`build_pre_mission()`, respectively.\n", "When you define these methods they should return OpenMDAO Systems ([groups](https://openmdao.org/newdocs/versions/latest/_srcdocs/packages/core/group.html) or [components](https://openmdao.org/newdocs/versions/latest/_srcdocs/packages/core/component.html)) that represent the mission and pre-mission subsystems of the external model.\n", "Please see the [OpenMDAO docs on creating a simple component](https://openmdao.org/newdocs/versions/latest/basic_user_guide/single_disciplinary_optimization/first_analysis.html) for more information on how to create OpenMDAO systems.\n", "In short, an OpenMDAO System takes in input variables, does some calculations, and returns output variables.\n", @@ -239,11 +309,11 @@ "metadata": {}, "source": [ "That's pretty straightforward.\n", - "The `build_pre_mission` method requires the `aviary_inputs` object (an instantiation of an `AviaryValues` object).\n", - "This battery example does not use any information from `aviary_inputs`.\n", - "The pre-mission builder can then use the data and options within the `aviary_inputs` object to construct the OpenMDAO System using user-specified logic.\n", + "The {glue:md}`build_pre_mission()` method requires the {glue:md}`aviary_inputs` object (an instantiation of an {glue:md}`AviaryValues` object).\n", + "This battery example does not use any information from {glue:md}`aviary_inputs`.\n", + "The pre-mission builder can then use the data and options within the {glue:md}`aviary_inputs` object to construct the OpenMDAO System using user-specified logic.\n", "\n", - "Now we'll discuss arguably the most important method needed when making external subsystems (though they're all important): `build_mission`.\n", + "Now we'll discuss arguably the most important method needed when making external subsystems (though they're all important): {glue:md}`build_mission()`.\n", "This method returns an OpenMDAO System that provides all computations needed during the mission.\n", "This includes computing state rates so that the mission integration code can compute the state values and obtain the corresponding performance of the aircraft.\n", "\n", @@ -265,8 +335,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Note that `build_mission` requires both `num_nodes` and `aviary_inputs` as arguments.\n", - "`num_nodes` is needed to correctly set up all the vectors within your mission subsystem, whereas `aviary_inputs` helps provide necessary options for the subsystem." + "Note that {glue:md}`build_mission()` requires both {glue:md}`num_nodes` and {glue:md}`aviary_inputs` as arguments.\n", + "{glue:md}`num_nodes` is needed to correctly set up all the vectors within your mission subsystem, whereas {glue:md}`aviary_inputs` helps provide necessary options for the subsystem." ] }, { @@ -279,12 +349,12 @@ "\n", "Let's talk about preprocessing your inputs.\n", "You might want to have some logic that sets different values in your problem based on user-provided options.\n", - "`preprocess_inputs` allows you to do this.\n", - "It occurs between `load_inputs` and `build_pre_mission` in the Aviary stack, so after the initial data inputs are loaded but before they're used to instantiate any OpenMDAO models.\n", + "{glue:md}`preprocess_inputs()` allows you to do this.\n", + "It occurs between {glue:md}`load_inputs()` and {glue:md}`add_pre_mission_systems()` in the Aviary stack, so after the initial data inputs are loaded but before they're used to instantiate any OpenMDAO models.\n", "This is a great place to set any values you need for variables within your subsystem.\n", "\n", "```{note}\n", - "For both users and developers: `preprocess_inputs` happens **once** per analysis or optimization run, just like loading the inputs. It does not occur as part of an OpenMDAO system, so it does not get iterated over during the optimization process.\n", + "For both users and developers: {glue:md}`preprocess_inputs()` happens **once** per analysis or optimization run, just like loading the inputs. It does not occur as part of an OpenMDAO system, so it does not get iterated over during the optimization process.\n", "```\n", "\n", "You can have calculations or checks you need in this method based on user inputs.\n", @@ -292,7 +362,7 @@ "Now you may want to link some variables between phases.\n", "States, for example, are usually great candidates for linking.\n", "In the case of the battery example, if we have a climb and then a cruise phase, we'd want to connect the state-of-charge and voltage states so the end of climb is equal to the beginning of cruise.\n", - "Thus, our `get_linked_variables` method looks like this:" + "Thus, our {glue:md}`get_linked_variables()` method looks like this:" ] }, { @@ -303,18 +373,18 @@ "source": [ "class BatteryBuilder(BatteryBuilder):\n", " def get_linked_variables(self):\n", - " '''\n", + " \"\"\"\n", " Return the list of linked variables for the battery subsystem; in this case\n", " it's our two state variables.\n", - " '''\n", - " return [Mission.Battery.VOLTAGE_THEVENIN, Mission.Battery.STATE_OF_CHARGE]" + " \"\"\"\n", + " return [Dynamic.Battery.VOLTAGE_THEVENIN, Dynamic.Battery.STATE_OF_CHARGE]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The last method we'll discuss here is `get_initial_guesses`.\n", + "The last method we'll discuss here is {glue:md}`get_initial_guesses()`.\n", "This method allows you to return info for any variable you want to provide an initial guess for.\n", "Depending on the integration method you're using, initial guesses may greatly help convergence of your optimization problem.\n", "Collocation methods especially benefit from good initial guesses.\n", @@ -333,11 +403,11 @@ "class BatteryBuilder(BatteryBuilder):\n", " def get_initial_guesses(self):\n", " initial_guess_dict = {\n", - " Mission.Battery.STATE_OF_CHARGE: {\n", + " Dynamic.Battery.STATE_OF_CHARGE: {\n", " 'val': 1.0,\n", " 'type': 'state',\n", " },\n", - " Mission.Battery.VOLTAGE_THEVENIN: {\n", + " Dynamic.Battery.VOLTAGE_THEVENIN: {\n", " 'val': 5.0,\n", " 'units': 'V',\n", " 'type': 'state',\n", @@ -374,10 +444,10 @@ "Specifically, the tests can help users check that their subsystem's inputs and outputs are correct and consistent with the expected format, even before running an Aviary mission.\n", "\n", "This test works by inheriting from a base class that loops through each of the methods and tests the outputs.\n", - "All you'd have to do is provide your builder object as well as the `aviary_inputs` object needed to for the methods in the builder object.\n", + "All you'd have to do is provide your builder object as well as the {glue:md}`aviary_inputs` object needed to for the methods in the builder object.\n", "\n", "Here's an example of the full code that you would write to test the battery builder.\n", - "Although there are no unit tests explicitly shown in this file, they are contained in the `TestSubsystemBuilderBase` class, so you only need these few lines to test your subsystem." + "Although there are no unit tests explicitly shown in this file, they are contained in the {glue:md}`TestSubsystemBuilderBase` class, so you only need these few lines to test your subsystem." ] }, { @@ -390,7 +460,6 @@ "\n", "\n", "class TestBattery(av.TestSubsystemBuilderBase):\n", - "\n", " def setUp(self):\n", " self.subsystem_builder = BatteryBuilder()\n", " self.aviary_values = av.AviaryValues()" @@ -427,7 +496,7 @@ "metadata": {}, "outputs": [], "source": [ - "unittest.main(argv=[''], verbosity=2, exit=False)\n" + "unittest.main(argv=[''], verbosity=2, exit=False)" ] }, { @@ -448,11 +517,11 @@ " def get_constraints(self):\n", " if self.include_constraints:\n", " constraints = {\n", - " Mission.Battery.STATE_OF_CHARGE: {\n", + " Dynamic.Battery.STATE_OF_CHARGE: {\n", " 'lower': 0.2,\n", " 'loc': 'final',\n", " },\n", - " Mission.Battery.VOLTAGE_THEVENIN: {\n", + " Dynamic.Battery.VOLTAGE_THEVENIN: {\n", " 'lower': 0,\n", " 'type': 'path',\n", " },\n", @@ -461,26 +530,28 @@ " constraints = {}\n", "\n", " return constraints\n", - " \n", + "\n", + "\n", "class BatteryBuilder(BatteryBuilder):\n", " def get_states(self):\n", " states_dict = {\n", - " Mission.Battery.STATE_OF_CHARGE: {\n", - " 'rate_source': Mission.Battery.STATE_OF_CHARGE_RATE,\n", + " Dynamic.Battery.STATE_OF_CHARGE: {\n", + " 'rate_source': Dynamic.Battery.STATE_OF_CHARGE_RATE,\n", " 'fix_initial': True,\n", " },\n", - " 'amps' : 6,\n", + " 'amps': 6,\n", " }\n", "\n", " return states_dict\n", - " \n", - "class TestBattery(av.TestSubsystemBuilderBase):\n", "\n", + "\n", + "class TestBattery(av.TestSubsystemBuilderBase):\n", " def setUp(self):\n", " self.subsystem_builder = BatteryBuilder()\n", " self.aviary_values = av.AviaryValues()\n", "\n", - "unittest.main(argv=[''], exit=False)\n" + "\n", + "unittest.main(argv=[''], exit=False)" ] }, { @@ -488,8 +559,8 @@ "metadata": {}, "source": [ "The output is a bit verbose, but tells you which methods are incorrect and why.\n", - "For example, here the `get_states` method returned a dict that included a key (`'amps'`) with a value of 6 instead of being a dictionary as expected.\n", - "In the `get_constraints` method, a constraint was added to the dictionary but did not include a `type` key, which is required as stated by the error message.\n", + "For example, here the {glue:md}`get_states()` method returned a dict that included a key (`'amps'`) with a value of 6 instead of being a dictionary as expected.\n", + "In the {glue:md}`get_constraints()` method, a constraint was added to the dictionary but did not include a `type` key, which is required as stated by the error message.\n", "\n", "If you encounter an error when using your subsystem, but the test here did not find it, please let the Aviary dev team know!\n", "We'd love to hear from you on the [GitHub issues page](https://github.com/OpenMDAO/Aviary/issues) so we can help everyone write great external subsystems." @@ -498,7 +569,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "av1", "language": "python", "name": "python3" }, @@ -512,7 +583,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/creating_a_turboprop_engine.ipynb b/aviary/docs/user_guide/creating_a_turboprop_engine.ipynb new file mode 100644 index 0000000000..57a2a1fd35 --- /dev/null +++ b/aviary/docs/user_guide/creating_a_turboprop_engine.ipynb @@ -0,0 +1,101 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Creating a Turboprop Powered Aircraft Example\n", + "\n", + "Here we will create an aircraft using a more advanced `EngineModel`, the `TurbopropModel`. This is a more complicated type of engine that combines several different models into a single unit. The `TurbopropModel` has three individual pieces needed to create it - a \"shaft power model\" that describes how the turboprop turns energy into shaft power, such as a turboshaft or motor, a \"gearbox model\" for adjusting the shaft RPM, and a \"propeller model\" to convert shaft power into thrust. Let's walk through two examples: first building a turboprop-powered aircraft with a minimum amount of information, and then a second example where we electrify the aircraft by replacing the default models in the `TurbopropModel` with custom ones.\n", + "\n", + "## Basic Turboprop Aircraft Example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import aviary.api as av\n", + "from aviary.models.aircraft.large_turboprop_freighter.phase_info import two_dof_phase_info\n", + "\n", + "Aircraft = av.Aircraft\n", + "Mission = av.Mission\n", + "Dynamic = av.Dynamic\n", + "\n", + "# define the minimum option set for a turboprop\n", + "options = av.AviaryValues()\n", + "\n", + "# top-level turboprop settings\n", + "options.set_val(av.Settings.VERBOSITY, 0) # quiet unneeded printouts\n", + "options.set_val(Aircraft.Engine.FIXED_RPM, 13820, units='rpm')\n", + "\n", + "# EngineDeck minimum option set\n", + "options.set_val(Aircraft.Engine.DATA_FILE, av.get_path('models/engines/turboshaft_4465hp.csv'))\n", + "\n", + "# Gearbox model minimum option set\n", + "options.set_val(Aircraft.Engine.Gearbox.GEAR_RATIO, 13.55, 'unitless')\n", + "options.set_val(Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN, 4465, 'hp')\n", + "\n", + "# Hamilton Standard propeller minimum option set\n", + "options.set_val(Aircraft.Engine.Propeller.TIP_MACH_MAX, 1.0)\n", + "options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=4, units='unitless')\n", + "options.set_val(Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, True)\n", + "\n", + "# Initialize turboprop model. Model uses an EngineDeck built from `options`, basic\n", + "# gearbox model with default efficiency of 1, and the Hamilton Standard propeller model\n", + "# \"turboprop\" is ready to be included in an AviaryProblem\n", + "turboprop = av.TurbopropModel(name='turboprop_example', options=options)\n", + "\n", + "# Build and run AviaryProblem using the Level2 interface\n", + "prob = av.AviaryProblem()\n", + "\n", + "prob.load_inputs(\n", + " 'models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv',\n", + " two_dof_phase_info,\n", + " engine_builders=[turboprop],\n", + ")\n", + "\n", + "prob.check_and_preprocess_inputs()\n", + "\n", + "prob.build_model()\n", + "prob.add_driver('IPOPT', max_iter=0, verbosity=0)\n", + "prob.add_design_variables()\n", + "prob.add_objective()\n", + "prob.setup()\n", + "prob.run_aviary_problem(suppress_solver_print=True, make_plots=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Electrified Propeller Aircraft Example\n", + "\n", + "This model is a WIP and will be coming soon" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/aviary/docs/user_guide/drawing_and_running_simple_missions.ipynb b/aviary/docs/user_guide/drawing_and_running_simple_missions.ipynb index 42dd8bad58..8e1fb5d3d5 100644 --- a/aviary/docs/user_guide/drawing_and_running_simple_missions.ipynb +++ b/aviary/docs/user_guide/drawing_and_running_simple_missions.ipynb @@ -1,5 +1,29 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "from aviary.interface.methods_for_level1 import run_aviary\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "# glue all argument of function run_aviary()\n", + "sigs = inspect.signature(run_aviary)\n", + "parameters = sigs.parameters\n", + "for name, param in parameters.items():\n", + " glue_variable(name, md_code=True)\n", + " glue_variable('--' + name, md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -11,8 +35,8 @@ "Aviary comes with a simple built-in graphical interface for defining missions.\n", "This tool can be accessed via the command line and provides an interactive way to define flight phases, including altitude, Mach number, and optimization parameters.\n", "\n", - "It is specifically made to only be used with the `\"height_energy\"` mission method.\n", - "You could use the results from the GUI to run a mission with a different method, but it would require manually changing the generated `phase_info` python dictionary.\n", + "It is specifically made to only be used with the {glue:md}`height_energy` mission method.\n", + "You could use the results from the GUI to run a mission with a different method, but it would require manually changing the generated {glue:md}`phase_info` python dictionary.\n", "\n", "![Graphical user interface for drawing missions](images/gui_main.png)" ] @@ -28,8 +52,13 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.utils.check_phase_info import check_phase_info, HEIGHT_ENERGY\n", - "check_phase_info({}, HEIGHT_ENERGY)" + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.variable_info.enums import EquationsOfMotion\n", + "\n", + "\n", + "glue_variable(\n", + " 'height_energy', get_variable_name(EquationsOfMotion.HEIGHT_ENERGY).lower(), md_code=False\n", + ")" ] }, { @@ -59,7 +88,11 @@ "source": [ "# Test Cell\n", "from aviary.interface.cmd_entry_points import _command_map\n", - "_command_map['draw_mission'];" + "\n", + "_command_map['draw_mission']\n", + "str_run_mission = 'run_mission'\n", + "_command_map[str_run_mission]\n", + "glue_variable(str_run_mission, md_code=True)" ] }, { @@ -88,7 +121,7 @@ "\n", "- **Removing Points**: Press the `X` button next to the point on the tabular section to remove that point.\n", "\n", - "- **Output Phase Info**: Press this button to create an output python file named `outputted_phase_info.py` which contains the mission information in a python dictionary called `phase_info`. This button serves the same function as using the menu `File`->`Save` command. \n", + "- **Output Phase Info**: Press this button to create an output python file named `outputted_phase_info.py` which contains the mission information in a python dictionary called {glue:md}`phase_info`. This button serves the same function as using the menu `File`->`Save` command. \n", "\n", "- **Light/Dark Mode**: Press the button on the bottom left to toggle the theme between light and dark mode. The default is light mode. If the user chooses to save settings (read `Edit Tab` below), the last used theme will be loaded the next time the program is run.\n", "\n", @@ -124,7 +157,7 @@ "3.2. `Solve for Distance`: If checked, calculates the total flight range based on the profile.
\n", "3.3. `Include Takeoff`: If checked, includes takeoff in the mission analysis.
\n", "3.4. `Include Landing`: If checked, includes landing in the mission analysis.
\n", - "3.5. `Polynomial Control Order`: Sets the polynomial order for control optimization, default being 1. This is for all phases. You can modify behavior on a per-phase basis by editing the outputted `phase_info` dict.
\n", + "3.5. `Polynomial Control Order`: Sets the polynomial order for control optimization, default being 1. This is for both altitude and mach in all phases. You can modify behavior on a per-phase basis by editing the outputted `phase_info` dict.
\n", "3.6. `Phase Transcription Order`: This setting will only show once at least 2 points are added to the plots/table. This number controls the number of points that are used to evaluate each mission phase. The minimum value is 3, and increasing this value will increase the number of points Aviary uses to analyze that phase.\n", "\n", "#### Help Tab\n", @@ -145,9 +178,9 @@ "\n", "## Running a Mission Simulation\n", "\n", - "After generating the flight profile, use the `run_mission` command to simulate the mission.\n", - "This command utilizes the `phase_info` from `outputted_phase_info.py` and simulates the mission based on the defined parameters. In the commands below, replace `outputted_phase_info.py` with your filename if you choose to save the output file with a different filename.\n", - "You can use the `--phase_info` flag to specify the path to the `outputted_phase_info.py` file.\n", + "After generating the flight profile, use the {glue:md}`run_mission` command to simulate the mission.\n", + "This command utilizes the {glue:md}`phase_info` from `outputted_phase_info.py` and simulates the mission based on the defined parameters. In the commands below, replace `outputted_phase_info.py` with your filename if you choose to save the output file with a different filename.\n", + "You can use the {glue:md}`--phase_info` flag to specify the path to the `outputted_phase_info.py` file.\n", "Here we use a benchmark case as the inputted .csv file, though you can use any Aviary .csv here that defines an aircraft.\n", "\n", "```bash\n", @@ -181,8 +214,11 @@ "source": [ "# Testing Cell\n", "from aviary.utils.doctape import run_command_no_file_error\n", - "command = 'aviary run_mission --optimizer IPOPT --phase_info outputted_phase_info.py '\\\n", + "\n", + "command = (\n", + " 'aviary run_mission --optimizer IPOPT --phase_info outputted_phase_info.py '\n", " 'validation_cases/benchmark_tests/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + ")\n", "command += ' --max_iter 0'\n", "run_command_no_file_error(command)" ] @@ -190,7 +226,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -204,9 +240,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.19" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/example.csv b/aviary/docs/user_guide/example.csv deleted file mode 100644 index 4a4e26b9c4..0000000000 --- a/aviary/docs/user_guide/example.csv +++ /dev/null @@ -1,7 +0,0 @@ -# This is test data generated using write_data_file -# Aviary data tables can support multiple comments - -aircraft:wing:span (ft), Scale Factor - 79, 0.5 - 118, 0.75 - 171, 0.8 diff --git a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb index 84634708f1..fdec20b2b7 100644 --- a/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb +++ b/aviary/docs/user_guide/examples_of_the_same_mission_at_different_UI_levels.ipynb @@ -1,5 +1,30 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import inspect\n", + "\n", + "from aviary.interface.methods_for_level1 import run_aviary\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "# glue all argument of function run_aviary()\n", + "sigs = inspect.signature(run_aviary)\n", + "parameters = sigs.parameters\n", + "for name, param in parameters.items():\n", + " glue_variable(name, md_code=True)\n", + "glue_variable(AviaryProblem.__name__, md_code=False)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -20,7 +45,7 @@ "\n", "This is the most basic level of the UI.\n", "There's a command-line interface (CLI) for Level 1, or you can use the Python API shown below.\n", - "If you want to make minor modifications to `phase_info`, you can do so here, but Level 1 largely assumes you're using the default setup." + "If you want to make minor modifications to {glue:md}`phase_info`, you can do so here, but Level 1 largely assumes you're using the default setup." ] }, { @@ -31,9 +56,13 @@ "source": [ "import aviary.api as av\n", "\n", - "prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " av.default_height_energy_phase_info,\n", - " max_iter=0, optimizer=\"SLSQP\", make_plots=False)" + "prob = av.run_aviary(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " av.default_height_energy_phase_info,\n", + " max_iter=0,\n", + " optimizer='SLSQP',\n", + " make_plots=False,\n", + ")" ] }, { @@ -42,7 +71,7 @@ "source": [ "## Level 2\n", "\n", - "This level grants more flexibility both in defining the `phase_info` object but also in calling the individual methods of `AviaryProblem` when setting up and running your model.\n", + "This level grants more flexibility both in defining the {glue:md}`phase_info` object but also in calling the individual methods of {glue:md}`AviaryProblem` when setting up and running your model.\n", "You can modify the methods you call, what they do, and what info they're given here.\n", "This is much more verbose than Level 1.\n", "In the absence of additional arguments to the methods, much of the default behavior here is the same as Level 1." @@ -57,88 +86,75 @@ "import aviary.api as av\n", "\n", "phase_info = {\n", - " \"pre_mission\": {\"include_takeoff\": False, \"optimize_mass\": True},\n", - " \"climb\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 5,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.2, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.18, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (0.0, \"ft\"),\n", - " \"final_altitude\": (32000.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 34000.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": True,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((0.0, 0.0), \"min\"),\n", - " \"duration_bounds\": ((64.0, 192.0), \"min\"),\n", - " \"add_initial_mass_constraint\": False,\n", + " 'pre_mission': {'include_takeoff': False, 'optimize_mass': True},\n", + " 'climb': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 5,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_initial': (0.2, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.18, 0.74), 'unitless'),\n", + " 'mach_polynomial_order': 3,\n", + " 'altitude_optimize': False,\n", + " 'altitude_initial': (0.0, 'ft'),\n", + " 'altitude_final': (32000.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 34000.0), 'ft'),\n", + " 'altitude_polynomial_order': 3,\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((0.0, 0.0), 'min'),\n", + " 'time_duration_bounds': ((64.0, 192.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([0, 128], \"min\")},\n", " },\n", - " \"cruise\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 5,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.72, \"unitless\"),\n", - " \"mach_bounds\": ((0.7, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (32000.0, \"ft\"),\n", - " \"final_altitude\": (34000.0, \"ft\"),\n", - " \"altitude_bounds\": ((23000.0, 38000.0), \"ft\"),\n", - " \"throttle_enforcement\": \"boundary_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": False,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((64.0, 192.0), \"min\"),\n", - " \"duration_bounds\": ((56.5, 169.5), \"min\"),\n", + " 'cruise': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 5,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.72, 'unitless'),\n", + " 'mach_bounds': ((0.7, 0.74), 'unitless'),\n", + " 'mach_polynomial_order': 3,\n", + " 'altitude_optimize': False,\n", + " 'altitude_initial': (32000.0, 'ft'),\n", + " 'altitude_final': (34000.0, 'ft'),\n", + " 'altitude_bounds': ((23000.0, 38000.0), 'ft'),\n", + " 'altitude_polynomial_order': 3,\n", + " 'throttle_enforcement': 'boundary_constraint',\n", + " 'time_initial_bounds': ((64.0, 192.0), 'min'),\n", + " 'time_duration_bounds': ((56.5, 169.5), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([128, 113], \"min\")},\n", " },\n", - " \"descent\": {\n", - " \"subsystem_options\": {\"core_aerodynamics\": {\"method\": \"computed\"}},\n", - " \"user_options\": {\n", - " \"optimize_mach\": False,\n", - " \"optimize_altitude\": False,\n", - " \"polynomial_control_order\": 1,\n", - " \"num_segments\": 5,\n", - " \"order\": 3,\n", - " \"solve_for_distance\": False,\n", - " \"initial_mach\": (0.72, \"unitless\"),\n", - " \"final_mach\": (0.36, \"unitless\"),\n", - " \"mach_bounds\": ((0.34, 0.74), \"unitless\"),\n", - " \"initial_altitude\": (34000.0, \"ft\"),\n", - " \"final_altitude\": (500.0, \"ft\"),\n", - " \"altitude_bounds\": ((0.0, 38000.0), \"ft\"),\n", - " \"throttle_enforcement\": \"path_constraint\",\n", - " \"fix_initial\": False,\n", - " \"constrain_final\": True,\n", - " \"fix_duration\": False,\n", - " \"initial_bounds\": ((120.5, 361.5), \"min\"),\n", - " \"duration_bounds\": ((29.0, 87.0), \"min\"),\n", + " 'descent': {\n", + " 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}},\n", + " 'user_options': {\n", + " 'num_segments': 5,\n", + " 'order': 3,\n", + " 'mach_optimize': False,\n", + " 'mach_initial': (0.72, 'unitless'),\n", + " 'mach_final': (0.36, 'unitless'),\n", + " 'mach_bounds': ((0.34, 0.74), 'unitless'),\n", + " 'mach_polynomial_order': 3,\n", + " 'altitude_optimize': False,\n", + " 'altitude_initial': (34000.0, 'ft'),\n", + " 'altitude_final': (500.0, 'ft'),\n", + " 'altitude_bounds': ((0.0, 38000.0), 'ft'),\n", + " 'altitude_polynomial_order': 3,\n", + " 'throttle_enforcement': 'path_constraint',\n", + " 'time_initial_bounds': ((120.5, 361.5), 'min'),\n", + " 'time_duration_bounds': ((29.0, 87.0), 'min'),\n", " },\n", - " \"initial_guesses\": {\"time\": ([241, 58], \"min\")},\n", " },\n", - " \"post_mission\": {\n", - " \"include_landing\": False,\n", - " \"constrain_range\": True,\n", - " \"target_range\": (1906, \"nmi\"),\n", + " 'post_mission': {\n", + " 'include_landing': False,\n", + " 'constrain_range': True,\n", + " 'target_range': (1906.0, 'nmi'),\n", " },\n", "}\n", "\n", - "csv_path = \"models/test_aircraft/aircraft_for_bench_FwFm.csv\"\n", + "csv_path = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "\n", "prob = av.AviaryProblem()\n", "\n", @@ -148,26 +164,17 @@ "\n", "prob.check_and_preprocess_inputs()\n", "\n", - "prob.add_pre_mission_systems()\n", - "\n", - "prob.add_phases()\n", - "\n", - "prob.add_post_mission_systems()\n", - "\n", - "# Link phases and variables\n", - "prob.link_phases()\n", + "prob.build_model()\n", "\n", - "prob.add_driver(\"SLSQP\", max_iter=0)\n", + "prob.add_driver('SLSQP', max_iter=0)\n", "\n", "prob.add_design_variables()\n", "\n", - "prob.add_objective(objective_type=\"mass\", ref=-1e5)\n", + "prob.add_objective(objective_type='mass', ref=-1e5)\n", "\n", "prob.setup()\n", "\n", - "prob.set_initial_guesses()\n", - "\n", - "prob.run_aviary_problem(record_filename='level2_example.db', suppress_solver_print=True, make_plots=False)" + "prob.run_aviary_problem(suppress_solver_print=True, make_plots=False)" ] }, { @@ -187,68 +194,66 @@ "metadata": {}, "outputs": [], "source": [ - "import scipy.constants as _units\n", - "\n", - "import openmdao.api as om\n", "import dymos as dm\n", + "import openmdao.api as om\n", + "import scipy.constants as _units\n", "\n", "import aviary.api as av\n", "from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems\n", "\n", - "\n", "prob = om.Problem(model=om.Group())\n", "driver = prob.driver = om.ScipyOptimizeDriver()\n", - "driver.options[\"optimizer\"] = \"SLSQP\"\n", - "driver.options[\"maxiter\"] = 1\n", + "driver.options['optimizer'] = 'SLSQP'\n", + "driver.options['maxiter'] = 1\n", "\n", "########################################\n", "# Aircraft Input Variables and Options #\n", "########################################\n", "\n", - "csv_path = \"models/test_aircraft/aircraft_for_bench_FwFm.csv\"\n", + "csv_path = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", "\n", - "aviary_inputs, _ = av.create_vehicle('models/test_aircraft/aircraft_for_bench_FwFm.csv')\n", + "aviary_inputs, _ = av.create_vehicle('models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv')\n", "\n", - "engine = av.build_engine_deck(aviary_inputs)\n", - "av.preprocess_options(aviary_inputs, engine_models=engine)\n", + "engines = [av.build_engine_deck(aviary_inputs)]\n", + "av.preprocess_options(aviary_inputs, engine_models=engines)\n", "\n", "alt_airport = 0 # ft\n", "\n", - "alt_i_climb = 0*_units.foot # m\n", - "alt_f_climb = 32000.0*_units.foot # m\n", - "mass_i_climb = 131000*_units.lb # kg\n", - "mass_f_climb = 126000*_units.lb # kg\n", + "alt_i_climb = 0 * _units.foot # m\n", + "alt_f_climb = 32000.0 * _units.foot # m\n", + "mass_i_climb = 131000 * _units.lb # kg\n", + "mass_f_climb = 126000 * _units.lb # kg\n", "mach_i_climb = 0.2\n", "mach_f_climb = 0.72\n", - "distance_i_climb = 0*_units.nautical_mile # m\n", - "distance_f_climb = 160.3*_units.nautical_mile # m\n", - "t_i_climb = 0. * _units.minute # sec\n", + "distance_i_climb = 0 * _units.nautical_mile # m\n", + "distance_f_climb = 160.3 * _units.nautical_mile # m\n", + "t_i_climb = 0.0 * _units.minute # sec\n", "t_f_climb = 128 * _units.minute # sec\n", "t_duration_climb = t_f_climb - t_i_climb\n", "\n", - "alt_i_cruise = 32000*_units.foot # m\n", - "alt_f_cruise = 34000*_units.foot # m\n", - "alt_min_cruise = 32000*_units.foot # m\n", - "alt_max_cruise = 34000*_units.foot # m\n", - "mass_i_cruise = 126000*_units.lb # kg\n", - "mass_f_cruise = 102000*_units.lb # kg\n", + "alt_i_cruise = 32000 * _units.foot # m\n", + "alt_f_cruise = 34000 * _units.foot # m\n", + "alt_min_cruise = 32000 * _units.foot # m\n", + "alt_max_cruise = 34000 * _units.foot # m\n", + "mass_i_cruise = 126000 * _units.lb # kg\n", + "mass_f_cruise = 102000 * _units.lb # kg\n", "cruise_mach = 0.79\n", - "distance_i_cruise = 160.3*_units.nautical_mile # m\n", - "distance_f_cruise = 3243.9*_units.nautical_mile # m\n", - "t_i_cruise = 128. * _units.minute # sec\n", - "t_f_cruise = 241. * _units.minute # sec\n", + "distance_i_cruise = 160.3 * _units.nautical_mile # m\n", + "distance_f_cruise = 3243.9 * _units.nautical_mile # m\n", + "t_i_cruise = 128.0 * _units.minute # sec\n", + "t_f_cruise = 241.0 * _units.minute # sec\n", "t_duration_cruise = t_f_cruise - t_i_cruise\n", "\n", - "alt_i_descent = 34000*_units.foot\n", - "alt_f_descent = 500*_units.foot\n", + "alt_i_descent = 34000 * _units.foot\n", + "alt_f_descent = 500 * _units.foot\n", "mach_i_descent = 0.72\n", "mach_f_descent = 0.3\n", - "mass_i_descent = 102000*_units.pound\n", - "mass_f_descent = 101000*_units.pound\n", - "distance_i_descent = 3243.9*_units.nautical_mile\n", - "distance_f_descent = 3378.7*_units.nautical_mile\n", - "t_i_descent = 241. * _units.minute\n", - "t_f_descent = 299. * _units.minute\n", + "mass_i_descent = 102000 * _units.pound\n", + "mass_f_descent = 101000 * _units.pound\n", + "distance_i_descent = 3243.9 * _units.nautical_mile\n", + "distance_f_descent = 3378.7 * _units.nautical_mile\n", + "t_i_descent = 241.0 * _units.minute\n", + "t_f_descent = 299.0 * _units.minute\n", "t_duration_descent = t_f_descent - t_i_descent\n", "\n", "####################\n", @@ -257,7 +262,7 @@ "aero = av.CoreAerodynamicsBuilder(code_origin=av.LegacyCode('FLOPS'))\n", "geom = av.CoreGeometryBuilder(code_origin=av.LegacyCode('FLOPS'))\n", "mass = av.CoreMassBuilder(code_origin=av.LegacyCode('FLOPS'))\n", - "prop = av.CorePropulsionBuilder(engine_models=engine)\n", + "prop = av.CorePropulsionBuilder(engine_models=engines)\n", "\n", "premission_subsystems = [prop, geom, aero, mass]\n", "mission_subsystems = [aero, prop]\n", @@ -269,11 +274,12 @@ "# Nudge it a bit off the correct answer to verify that the optimize takes us there.\n", "aviary_inputs.set_val(av.Mission.Design.GROSS_MASS, 135000.0, units='lbm')\n", "\n", - "prob.model.add_design_var(av.Mission.Design.GROSS_MASS, units='lbm',\n", - " lower=100000.0, upper=200000.0, ref=135000)\n", + "prob.model.add_design_var(\n", + " av.Mission.Design.GROSS_MASS, units='lbm', lower=100000.0, upper=200000.0, ref=135000\n", + ")\n", "\n", "# default subsystems\n", - "default_mission_subsystems = get_default_mission_subsystems('FLOPS', engine)\n", + "default_mission_subsystems = get_default_mission_subsystems('FLOPS', engines)\n", "\n", "#################\n", "# Define Phases #\n", @@ -286,24 +292,21 @@ "descent_seg_ends, _ = dm.utils.lgl.lgl(num_segments_descent + 1)\n", "\n", "transcription_climb = dm.Radau(\n", - " num_segments=num_segments_climb, order=3, compressed=True,\n", - " segment_ends=climb_seg_ends)\n", - "transcription_cruise = dm.Radau(\n", - " num_segments=num_segments_cruise, order=3, compressed=True)\n", + " num_segments=num_segments_climb, order=3, compressed=True, segment_ends=climb_seg_ends\n", + ")\n", + "transcription_cruise = dm.Radau(num_segments=num_segments_cruise, order=3, compressed=True)\n", "transcription_descent = dm.Radau(\n", - " num_segments=num_segments_descent, order=3, compressed=True,\n", - " segment_ends=descent_seg_ends)\n", + " num_segments=num_segments_descent, order=3, compressed=True, segment_ends=descent_seg_ends\n", + ")\n", "\n", "climb_options = av.HeightEnergyPhaseBuilder(\n", " 'test_climb',\n", - " user_options=av.AviaryValues({\n", - " 'initial_altitude': (alt_i_climb, 'm'),\n", - " 'final_altitude': (alt_f_climb, 'm'),\n", - " 'initial_mach': (mach_i_climb, 'unitless'),\n", - " 'final_mach': (mach_f_climb, 'unitless'),\n", - " 'fix_initial': (True, 'unitless'),\n", - " 'use_polynomial_control': (False, 'unitless'),\n", - " }),\n", + " user_options={\n", + " 'altitude_initial': (alt_i_climb, 'm'),\n", + " 'altitude_final': (alt_f_climb, 'm'),\n", + " 'mach_initial': (mach_i_climb, 'unitless'),\n", + " 'mach_final': (mach_f_climb, 'unitless'),\n", + " },\n", " core_subsystems=default_mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_climb,\n", @@ -311,14 +314,15 @@ "\n", "cruise_options = av.HeightEnergyPhaseBuilder(\n", " 'test_cruise',\n", - " user_options=av.AviaryValues({\n", - " 'initial_altitude': (alt_min_cruise, 'm'),\n", - " 'final_altitude': (alt_max_cruise, 'm'),\n", - " 'initial_mach': (cruise_mach, 'unitless'),\n", - " 'final_mach': (cruise_mach, 'unitless'),\n", + " user_options={\n", + " 'altitude_polynomial_order': 3,\n", + " 'altitude_initial': (alt_min_cruise, 'm'),\n", + " 'altitude_final': (alt_max_cruise, 'm'),\n", + " 'mach_polynomial_order': 3,\n", + " 'mach_initial': (cruise_mach, 'unitless'),\n", + " 'mach_final': (cruise_mach, 'unitless'),\n", " 'required_available_climb_rate': (300, 'ft/min'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " }),\n", + " },\n", " core_subsystems=default_mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_cruise,\n", @@ -326,14 +330,12 @@ "\n", "descent_options = av.HeightEnergyPhaseBuilder(\n", " 'test_descent',\n", - " user_options=av.AviaryValues({\n", - " 'final_altitude': (alt_f_descent, 'm'),\n", - " 'initial_altitude': (alt_i_descent, 'm'),\n", - " 'initial_mach': (mach_i_descent, 'unitless'),\n", - " 'final_mach': (mach_f_descent, 'unitless'),\n", - " 'fix_initial': (False, 'unitless'),\n", - " 'use_polynomial_control': (False, 'unitless'),\n", - " }),\n", + " user_options={\n", + " 'altitude_final': (alt_f_descent, 'm'),\n", + " 'altitude_initial': (alt_i_descent, 'm'),\n", + " 'mach_initial': (mach_i_descent, 'unitless'),\n", + " 'mach_final': (mach_f_descent, 'unitless'),\n", + " },\n", " core_subsystems=default_mission_subsystems,\n", " subsystem_options={'core_aerodynamics': {'method': 'computed'}},\n", " transcription=transcription_descent,\n", @@ -344,10 +346,10 @@ "# Upstream pre-mission analysis for aero\n", "prob.model.add_subsystem(\n", " 'pre_mission',\n", - " av.CorePreMission(aviary_options=aviary_inputs,\n", - " subsystems=premission_subsystems),\n", + " av.CorePreMission(aviary_options=aviary_inputs, subsystems=premission_subsystems),\n", " promotes_inputs=['aircraft:*', 'mission:*'],\n", - " promotes_outputs=['aircraft:*', 'mission:*'])\n", + " promotes_outputs=['aircraft:*', 'mission:*'],\n", + ")\n", "\n", "# directly connect phases (strong_couple = True), or use linkage constraints (weak\n", "# coupling / strong_couple=False)\n", @@ -363,20 +365,32 @@ "\n", "# if fix_initial is false, can we always set input_initial to be true for\n", "# necessary states, and then ignore if we use a linkage?\n", - "climb.set_time_options(fix_initial=True, fix_duration=False, units='s',\n", - " duration_bounds=(t_duration_climb*0.5, t_duration_climb*2),\n", - " duration_ref=t_duration_climb)\n", - "cruise.set_time_options(fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(t_duration_cruise*0.5, t_duration_cruise*2),\n", - " duration_ref=t_duration_cruise,\n", - " initial_bounds=(t_duration_climb*0.5, t_duration_climb*2))\n", + "climb.set_time_options(\n", + " fix_initial=True,\n", + " fix_duration=False,\n", + " units='s',\n", + " duration_bounds=(t_duration_climb * 0.5, t_duration_climb * 2),\n", + " duration_ref=t_duration_climb,\n", + ")\n", + "cruise.set_time_options(\n", + " fix_initial=False,\n", + " fix_duration=False,\n", + " units='s',\n", + " duration_bounds=(t_duration_cruise * 0.5, t_duration_cruise * 2),\n", + " duration_ref=t_duration_cruise,\n", + " initial_bounds=(t_duration_climb * 0.5, t_duration_climb * 2),\n", + ")\n", "descent.set_time_options(\n", - " fix_initial=False, fix_duration=False, units='s',\n", - " duration_bounds=(t_duration_descent*0.5, t_duration_descent*2),\n", + " fix_initial=False,\n", + " fix_duration=False,\n", + " units='s',\n", + " duration_bounds=(t_duration_descent * 0.5, t_duration_descent * 2),\n", " duration_ref=t_duration_descent,\n", " initial_bounds=(\n", - " (t_duration_cruise + t_duration_climb)*0.5,\n", - " (t_duration_cruise + t_duration_climb)*2))\n", + " (t_duration_cruise + t_duration_climb) * 0.5,\n", + " (t_duration_cruise + t_duration_climb) * 2,\n", + " ),\n", + ")\n", "\n", "traj.add_phase('climb', climb)\n", "\n", @@ -384,47 +398,52 @@ "\n", "traj.add_phase('descent', descent)\n", "\n", - "traj.link_phases([\"climb\", \"cruise\", \"descent\"], [\n", - " \"time\", \"mass\", \"distance\"], connected=strong_couple)\n", + "traj.link_phases(\n", + " ['climb', 'cruise', 'descent'], ['time', 'mass', 'distance'], connected=strong_couple\n", + ")\n", "\n", "# Need to declare dymos parameters for every input that is promoted out of the missions.\n", "external_parameters = {'climb': {}, 'cruise': {}, 'descent': {}}\n", "for default_subsys in default_mission_subsystems:\n", - " params = default_subsys.get_parameters(aviary_inputs=aviary_inputs,\n", - " phase_info={})\n", + " params = default_subsys.get_parameters(aviary_inputs=aviary_inputs, phase_info={})\n", " for key, val in params.items():\n", " for phname in external_parameters:\n", " external_parameters[phname][key] = val\n", - " \n", - "traj = av.setup_trajectory_params(prob.model, traj, aviary_inputs, \n", - " external_parameters=external_parameters)\n", + "\n", + "traj = av.setup_trajectory_params(\n", + " prob.model, traj, aviary_inputs, external_parameters=external_parameters\n", + ")\n", "\n", "###############\n", "# Constraints #\n", "###############\n", "\n", - "ecomp = om.ExecComp('fuel_burned = initial_mass - descent_mass_final',\n", - " initial_mass={'units': 'lbm', 'shape': 1},\n", - " descent_mass_final={'units': 'lbm', 'shape': 1},\n", - " fuel_burned={'units': 'lbm', 'shape': 1})\n", + "ecomp = om.ExecComp(\n", + " 'fuel_burned = initial_mass - descent_mass_final',\n", + " initial_mass={'units': 'lbm', 'shape': 1},\n", + " descent_mass_final={'units': 'lbm', 'shape': 1},\n", + " fuel_burned={'units': 'lbm', 'shape': 1},\n", + ")\n", "\n", - "prob.model.add_subsystem('fuel_burn', ecomp,\n", - " promotes_inputs=[\n", - " ('initial_mass', av.Mission.Design.GROSS_MASS)],\n", - " promotes_outputs=['fuel_burned'])\n", + "prob.model.add_subsystem(\n", + " 'fuel_burn',\n", + " ecomp,\n", + " promotes_inputs=[('initial_mass', av.Mission.Design.GROSS_MASS)],\n", + " promotes_outputs=['fuel_burned'],\n", + ")\n", "\n", - "prob.model.connect(\"traj.descent.states:mass\",\n", - " \"fuel_burn.descent_mass_final\", src_indices=[-1])\n", + "prob.model.connect('traj.descent.states:mass', 'fuel_burn.descent_mass_final', src_indices=[-1])\n", "\n", "##########################\n", "# Add Objective Function #\n", "##########################\n", "\n", - "prob.model.add_objective(\"fuel_burned\", ref=1e4)\n", + "prob.model.add_objective('fuel_burned', ref=1e4)\n", "\n", "# Set initial default values for any variables that have\n", "# different defaults in premission and mission.\n", "varnames = [\n", + " av.Aircraft.Engine.SCALE_FACTOR,\n", " av.Aircraft.Wing.AREA,\n", " av.Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN,\n", " av.Aircraft.Wing.SWEEP,\n", @@ -434,6 +453,8 @@ "]\n", "av.set_aviary_input_defaults(prob.model, varnames, aviary_inputs)\n", "\n", + "av.setup_model_options(prob, aviary_inputs)\n", + "\n", "prob.setup(force_alloc_complex=True)\n", "\n", "av.set_aviary_initial_values(prob, aviary_inputs)\n", @@ -445,47 +466,84 @@ "prob.set_val('traj.climb.t_initial', t_i_climb, units='s')\n", "prob.set_val('traj.climb.t_duration', t_duration_climb, units='s')\n", "\n", - "prob.set_val('traj.climb.controls:altitude', climb.interp(\n", - " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m')\n", "prob.set_val(\n", - " 'traj.climb.controls:mach', climb.interp(\n", - " av.Dynamic.Mission.MACH, ys=[mach_i_climb, mach_f_climb]), units='unitless')\n", - "prob.set_val('traj.climb.states:mass', climb.interp(\n", - " av.Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg')\n", - "prob.set_val('traj.climb.states:distance', climb.interp(\n", - " av.Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m')\n", + " 'traj.climb.controls:altitude',\n", + " climb.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]),\n", + " units='m',\n", + ")\n", + "prob.set_val(\n", + " 'traj.climb.controls:mach',\n", + " climb.interp(av.Dynamic.Atmosphere.MACH, ys=[mach_i_climb, mach_f_climb]),\n", + " units='unitless',\n", + ")\n", + "prob.set_val(\n", + " 'traj.climb.states:mass',\n", + " climb.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_climb, mass_f_climb]),\n", + " units='kg',\n", + ")\n", + "prob.set_val(\n", + " 'traj.climb.states:distance',\n", + " climb.interp(av.Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]),\n", + " units='m',\n", + ")\n", "\n", "prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s')\n", "prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s')\n", "\n", - "prob.set_val('traj.cruise.controls:altitude', cruise.interp(\n", - " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m')\n", "prob.set_val(\n", - " 'traj.cruise.controls:mach', cruise.interp(\n", - " av.Dynamic.Mission.MACH, ys=[cruise_mach, cruise_mach]), units='unitless')\n", - "prob.set_val('traj.cruise.states:mass', cruise.interp(\n", - " av.Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg')\n", - "prob.set_val('traj.cruise.states:distance', cruise.interp(\n", - " av.Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m')\n", + " 'traj.cruise.controls:altitude',\n", + " cruise.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]),\n", + " units='m',\n", + ")\n", + "prob.set_val(\n", + " 'traj.cruise.controls:mach',\n", + " cruise.interp(av.Dynamic.Atmosphere.MACH, ys=[cruise_mach, cruise_mach]),\n", + " units='unitless',\n", + ")\n", + "prob.set_val(\n", + " 'traj.cruise.states:mass',\n", + " cruise.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_cruise, mass_f_cruise]),\n", + " units='kg',\n", + ")\n", + "prob.set_val(\n", + " 'traj.cruise.states:distance',\n", + " cruise.interp(av.Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]),\n", + " units='m',\n", + ")\n", "\n", "prob.set_val('traj.descent.t_initial', t_i_descent, units='s')\n", "prob.set_val('traj.descent.t_duration', t_duration_descent, units='s')\n", "\n", - "prob.set_val('traj.descent.controls:altitude', descent.interp(\n", - " av.Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m')\n", "prob.set_val(\n", - " 'traj.descent.controls:mach', descent.interp(\n", - " av.Dynamic.Mission.MACH, ys=[mach_i_descent, mach_f_descent]), units='unitless')\n", - "prob.set_val('traj.descent.states:mass', descent.interp(\n", - " av.Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg')\n", - "prob.set_val('traj.descent.states:distance', descent.interp(\n", - " av.Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m')\n", + " 'traj.descent.controls:altitude',\n", + " descent.interp(av.Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]),\n", + " units='m',\n", + ")\n", + "prob.set_val(\n", + " 'traj.descent.controls:mach',\n", + " descent.interp(av.Dynamic.Atmosphere.MACH, ys=[mach_i_descent, mach_f_descent]),\n", + " units='unitless',\n", + ")\n", + "prob.set_val(\n", + " 'traj.descent.states:mass',\n", + " descent.interp(av.Dynamic.Vehicle.MASS, ys=[mass_i_descent, mass_f_descent]),\n", + " units='kg',\n", + ")\n", + "prob.set_val(\n", + " 'traj.descent.states:distance',\n", + " descent.interp(av.Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]),\n", + " units='m',\n", + ")\n", "\n", "# Turn off solver printing so that the SNOPT output is readable.\n", "prob.set_solver_print(level=0)\n", "\n", - "dm.run_problem(prob, simulate=False, make_plots=False, simulate_kwargs={\n", - " 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9})" + "dm.run_problem(\n", + " prob,\n", + " simulate=False,\n", + " make_plots=False,\n", + " simulate_kwargs={'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9},\n", + ")" ] } ], @@ -505,7 +563,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/external_aero.ipynb b/aviary/docs/user_guide/external_aero.ipynb index 40936bd6e0..3cbf0dec9f 100644 --- a/aviary/docs/user_guide/external_aero.ipynb +++ b/aviary/docs/user_guide/external_aero.ipynb @@ -9,7 +9,7 @@ "\n", "This example shows how to build, using the level-2 interface, an aviary model that includes an external susbsystem that computes a lift and drag polar and passes them into the mission aerodynamics for a 3-phase mission (climb, cruise, descent). During the mission, Aviary will interpolate on the computed polars to compute actual lift and drag for a given flight condition.\n", "\n", - "We start with the assumption that we have an external component called `ExternalAero` that can compute the lift and drag at any given altitude, mach number, and angle of attack. The details of such a component may be highly complicated and not important for the purposes of this example. We will be using a structured grid, which assumes the data table is regularly spaced in all dimensions. We want to compute lift and drag over a grid of altitudes (in 'ft'), mach numbers, and angles of attack given by:" + "We start with the assumption that we have an external component called {glue:md}`ExternalAero` that can compute the lift and drag at any given altitude, Mach number, and angle of attack. The details of such a component may be highly complicated and not important for the purposes of this example. We will be using a structured grid, which assumes the data table is regularly spaced in all dimensions. We want to compute lift and drag over a grid of altitudes (in 'ft'), Mach numbers, and angles of attack given by:" ] }, { @@ -23,22 +23,27 @@ }, "outputs": [], "source": [ - "# This hidden cell just creates a component that produces the lift and drag polar. \n", + "# This hidden cell just creates a component that produces the lift and drag polar.\n", "# The implementation details are unimportant to the example.\n", - "import openmdao.api as om\n", "import numpy as np\n", + "import openmdao.api as om\n", "\n", - "from aviary.api import Aircraft\n", "import aviary.api as av\n", + "from aviary.api import Aircraft\n", "\n", "# The drag-polar-generating component reads this in, instead of computing the polars.\n", - "polar_file = \"subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free_reduced_alpha.txt\"\n", - "\n", - "aero_data = av.read_data_file(polar_file, aliases = {'altitude': 'altitude',\n", - " 'mach': 'mach',\n", - " 'angle_of_attack': 'angle_of_attack',\n", - " 'lift_coefficient': 'cl',\n", - " 'drag_coefficient': 'cd'})\n", + "polar_file = 'models/large_single_aisle_1/large_single_aisle_1_aero_free_reduced_alpha.csv'\n", + "\n", + "aero_data, _, _ = av.read_data_file(\n", + " polar_file,\n", + " aliases={\n", + " 'altitude': 'altitude',\n", + " 'mach': 'mach',\n", + " 'angle_of_attack': 'angle_of_attack',\n", + " 'lift_coefficient': 'cl',\n", + " 'drag_coefficient': 'cd',\n", + " },\n", + ")\n", "\n", "altitude = np.unique(aero_data.get_val('altitude', 'ft'))\n", "mach = np.unique(aero_data.get_val('mach', 'unitless'))\n", @@ -55,16 +60,21 @@ " calculation. It does nothing but read in the pre-computed table. A real\n", " component would actually computed the values at all requested points.\n", " \"\"\"\n", + "\n", " def initialize(self):\n", - " \"\"\"\n", - " Declare options.\n", - " \"\"\"\n", - " self.options.declare(\"altitude\", default=None, allow_none=True,\n", - " desc=\"List of altitudes in ascending order.\")\n", - " self.options.declare(\"mach\", default=None, allow_none=True,\n", - " desc=\"List of mach numbers in ascending order.\")\n", - " self.options.declare(\"angle_of_attack\", default=None, allow_none=True,\n", - " desc=\"List of angles of attack in ascending order.\")\n", + " \"\"\"Declare options.\"\"\"\n", + " self.options.declare(\n", + " 'altitude', default=None, allow_none=True, desc='List of altitudes in ascending order.'\n", + " )\n", + " self.options.declare(\n", + " 'mach', default=None, allow_none=True, desc='List of Mach numbers in ascending order.'\n", + " )\n", + " self.options.declare(\n", + " 'angle_of_attack',\n", + " default=None,\n", + " allow_none=True,\n", + " desc='List of angles of attack in ascending order.',\n", + " )\n", "\n", " def setup(self):\n", " altitude = self.options['altitude']\n", @@ -84,33 +94,51 @@ " This component doesn't do anything, except set the drag and lift\n", " polars from the file we read in.\n", " \"\"\"\n", - "\n", " # Your component will compute CD and CL for a grid of altitudes, machs, and\n", - " # angles of attack, and return them in a multidimensional array as described \n", + " # angles of attack, and return them in a multidimensional array as described\n", " # in the example text.\n", "\n", " # Because it would be prohibitive to embed something like a vortex lattice\n", " # code in this example, we are \"cheating\" here by sending a pre-computed\n", " # drag polar.\n", - " \n", + "\n", " outputs['drag_table'] = CD\n", " outputs['lift_table'] = CL\n", - " \n", + "\n", + "\n", "print('Altitude (ft)', altitude)\n", "print('Mach', mach)\n", "print('Angle of Attack (deg)', angle_of_attack)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "c21e45ca", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "# class ExternalAero is defined within this file\n", + "glue_variable(ExternalAero.__name__, md_code=True)" + ] + }, { "cell_type": "markdown", "id": "elder-kinase", "metadata": {}, "source": [ - "In a structured grid, interpolation data must be present for every combination of inputs. In other words, our `ExternalAero` component must run a full factorial of points spanning those 3 variables. The Aviary variable hierarchy includes two variables for the polars: `Aircraft.Design.LIFT_POLAR`, and `Aircraft.Design.DRAG_POLAR`. The data in each of these polars should be a `n` x `m` x `k` numpy array, where `n` is the number of altitudes, `m` is the number of mach numbers, and `k` is the number of angles of attack. The `ExternalAero` will need to compute these values and place them into an array of this shape.\n", + "In a structured grid, interpolation data must be present for every combination of inputs. In other words, our {glue:md}`ExternalAero` component must run a full factorial of points spanning those 3 variables. The Aviary variable hierarchy includes two variables for the polars: {glue:md}`Aircraft.Design.LIFT_POLAR`, and {glue:md}`Aircraft.Design.DRAG_POLAR`. The data in each of these polars should be a `n` x `m` x `k` numpy array, where `n` is the number of altitudes, `m` is the number of mach numbers, and `k` is the number of angles of attack. The `ExternalAero` will need to compute these values and place them into an array of this shape.\n", "\n", "If use of a structured grid is not desirable, then the data does not need to meet these formatting requirements. In that case, the data table does not have to be regularly spaced, and each variable (`Altitude`, `Mach`, `angle_of_attack`, `LIFT_POLAR`, and `DRAG_POLAR`) must be 1-dimensional numpy arrays of equal length.\n", "\n", - "Using the level-2 interface, we create a builder for our external `ExternalAero` subsystem. In this example, the component produces outputs `drag_table` and `lift_table`, but we can specify an alias to `Aircraft.Design.DRAG_POLAR` and `Aircraft.Design.LIFT_POLAR` respectively. It is important that we inherit from the `AerodynamicsBuilderBase` to let Aviary know this is builder produces aerodynamics components. Some mission analysis methods require special handling of aerodynamics components that will not occur if we skip this step." + "Using the level-2 interface, we create a builder for our external `ExternalAero` subsystem. In this example, the component produces outputs `drag_table` and `lift_table`, but we can specify an alias to {glue:md}`Aircraft.Design.DRAG_POLAR` and {glue:md}`Aircraft.Design.LIFT_POLAR` respectively. It is important that we inherit from the {glue:md}`AerodynamicsBuilderBase` to let Aviary know this is builder produces aerodynamics components. Some mission analysis methods require special handling of aerodynamics components that will not occur if we skip this step." ] }, { @@ -125,9 +153,14 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.api import Aircraft\n", - "Aircraft.Design.LIFT_POLAR;\n", - "Aircraft.Design.DRAG_POLAR;" + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "glue_variable(AerodynamicsBuilderBase.__name__, md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.LIFT_POLAR), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.DRAG_POLAR), md_code=True)\n", + "glue_variable(AviaryProblem.__name__, md_code=False)" ] }, { @@ -139,7 +172,7 @@ "source": [ "class ExternalAeroBuilder(av.AerodynamicsBuilderBase):\n", " \"\"\"\n", - " An example subsystem builder that adds an external aerodynamics component\n", + " An example subsystem builder that adds an external aerodynamics component.\n", "\n", " Parameters\n", " ----------\n", @@ -147,13 +180,12 @@ " Altitude, Mach number, and angle of attack data, all in ascending order.\n", " \"\"\"\n", "\n", - " def __init__(self, name='aero', altitude=None, mach=None,\n", - " angle_of_attack=None):\n", + " def __init__(self, name='aero', altitude=None, mach=None, angle_of_attack=None):\n", " super().__init__(name)\n", " self.altitude = altitude\n", " self.mach = mach\n", " self.angle_of_attack = angle_of_attack\n", - " \n", + "\n", " def build_pre_mission(self, aviary_inputs):\n", " \"\"\"\n", " Build an OpenMDAO system for the pre-mission computations of the subsystem.\n", @@ -166,15 +198,17 @@ " and other non-mission parameters.\n", " \"\"\"\n", " aero_group = om.Group()\n", - " aero = ExternalAero(altitude=self.altitude, mach=self.mach, angle_of_attack=self.angle_of_attack)\n", + " aero = ExternalAero(\n", + " altitude=self.altitude, mach=self.mach, angle_of_attack=self.angle_of_attack\n", + " )\n", " aero_group.add_subsystem(\n", - " 'premission_aero', \n", + " 'premission_aero',\n", " aero,\n", " promotes_inputs=['*'],\n", " promotes_outputs=[\n", " ('drag_table', Aircraft.Design.DRAG_POLAR),\n", - " ('lift_table', Aircraft.Design.LIFT_POLAR)\n", - " ]\n", + " ('lift_table', Aircraft.Design.LIFT_POLAR),\n", + " ],\n", " )\n", " return aero_group" ] @@ -198,8 +232,9 @@ "source": [ "phase_info = av.default_height_energy_phase_info.copy()\n", "\n", - "external_aero = ExternalAeroBuilder(name='external_aero',\n", - " altitude=altitude, mach=mach, angle_of_attack=angle_of_attack)\n", + "external_aero = ExternalAeroBuilder(\n", + " name='external_aero', altitude=altitude, mach=mach, angle_of_attack=angle_of_attack\n", + ")\n", "\n", "phase_info['pre_mission']['external_subsystems'] = [external_aero]" ] @@ -209,7 +244,7 @@ "id": "technological-compatibility", "metadata": {}, "source": [ - "Next, the existing mission phases need to be given the information they need to set up our aerodynamics analysis using `phase_info`. We use the `solved_alpha` method of Aviary's included aerodynamics for this, which can accept the input passed from our external subsystem. Since we are using Aviary's built-in aerodynamics methods, we use the default name \"core_aerodynamics\". Don't forget to update the `subsystem_options` for each phase. We must specify the `method`, the `aero_data` that contains our altitude, Mach, and angle of attack data, as well as the `connect_training_data` flag to denote we are passing our drag polars via openMDAO connections." + "Next, the existing mission phases need to be given the information they need to set up our aerodynamics analysis using _glue:md}`phase_info`. We use the `tabular_cruise` method with the `solve_alpha` flag of Aviary's included aerodynamics for this, which can accept the input passed from our external subsystem. Since we are using Aviary's built-in aerodynamics methods, we use the default name \"core_aerodynamics\". Don't forget to update the `subsystem_options` for each phase. We must specify the `method`, the `aero_data` that contains our altitude, Mach, and angle of attack data, as well as the `connect_training_data` flag to denote we are passing our drag polars via openMDAO connections." ] }, { @@ -219,13 +254,16 @@ "metadata": {}, "outputs": [], "source": [ - "subsystem_options = {'method': 'solved_alpha',\n", - " 'aero_data': aero_data,\n", - " 'connect_training_data': True}\n", + "subsystem_options = {\n", + " 'method': 'tabular_cruise',\n", + " 'solve_alpha': True,\n", + " 'aero_data': aero_data,\n", + " 'connect_training_data': True,\n", + "}\n", "\n", "phase_info['climb']['subsystem_options'] = {'core_aerodynamics': subsystem_options}\n", "phase_info['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options}\n", - "phase_info['descent']['subsystem_options'] = {'core_aerodynamics': subsystem_options}\n" + "phase_info['descent']['subsystem_options'] = {'core_aerodynamics': subsystem_options}" ] }, { @@ -233,7 +271,7 @@ "id": "equivalent-lawsuit", "metadata": {}, "source": [ - "Finally, we can instantiate the AviaryProblem like normal. However, we need to tell Aviary the size of our lift and drag polars so that it can allocate the right shape for the connection." + "Finally, we can instantiate the {glue:md}`AviaryProblem` like normal. However, we need to tell Aviary the size of our lift and drag polars so that it can allocate the right shape for the connection." ] }, { @@ -245,19 +283,16 @@ "source": [ "from aviary.utils.functions import get_aviary_resource_path\n", "\n", - "input_file = get_aviary_resource_path(\"models/test_aircraft/aircraft_for_bench_GwFm.csv\")\n", + "input_file = get_aviary_resource_path('models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv')\n", "\n", "prob = av.AviaryProblem()\n", "prob.load_inputs(input_file, phase_info)\n", "\n", - "# Preprocess inputs\n", - "prob.check_and_preprocess_inputs()\n", - "\n", "# Add correctly-sized polar to aviary_inputs so that input components are sized correctly.\n", "shape = (altitude.size, mach.size, angle_of_attack.size)\n", "\n", "prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, np.zeros(shape), units='unitless')\n", - "prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, np.zeros(shape), units='unitless')\n" + "prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, np.zeros(shape), units='unitless')" ] }, { @@ -272,17 +307,14 @@ "outputs": [], "source": [ "# get through setup for the problem\n", - "prob.add_pre_mission_systems()\n", - "prob.add_phases()\n", - "prob.add_post_mission_systems()\n", - "prob.link_phases()\n", - "prob.add_driver(\"SLSQP\")\n", + "prob.check_and_preprocess_inputs()\n", + "prob.build_model()\n", + "prob.add_driver('SLSQP')\n", "prob.add_design_variables()\n", - "prob.add_objective(objective_type=\"mass\", ref=-1e5)\n", + "prob.add_objective(objective_type='mass', ref=-1e5)\n", "prob.setup()\n", - "prob.set_initial_guesses()\n", "\n", - "prob.run_model()\n" + "prob.run_model()" ] }, { @@ -296,9 +328,10 @@ }, "outputs": [], "source": [ - "\n", + "# Testing Cell\n", "# Make sure we succesfully passed the polar\n", "from openmdao.utils.assert_utils import assert_near_equal\n", + "\n", "om_CD = prob.get_val(Aircraft.Design.DRAG_POLAR)[0, 0, 0]\n", "assert_near_equal(om_CD, CD[0, 0, 0], 1e-6)" ] @@ -307,7 +340,7 @@ "metadata": { "celltoolbar": "Tags", "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -321,7 +354,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.12.9" }, "orphan": true }, diff --git a/aviary/docs/user_guide/features/blended_wing_body.ipynb b/aviary/docs/user_guide/features/blended_wing_body.ipynb new file mode 100644 index 0000000000..7402d24b0b --- /dev/null +++ b/aviary/docs/user_guide/features/blended_wing_body.ipynb @@ -0,0 +1,386 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "7e0c045e", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n" + ] + }, + { + "cell_type": "markdown", + "id": "267d6a8d", + "metadata": {}, + "source": [ + "# Blended Wing Body Modeling\n", + "\n", + "The blended wing body aircraft is modeled following GASP implementation. It is important to point out the the Aviary implementation is limited to certain assumptions. To model a special model, the user must read this document carefully to see it is within the scope of the Aviary implementation.\n", + "\n", + "## GASP Based Geometry\n", + "\n", + "Comparing to traditional tube and wing model, Blended wing body (BWB) modeling has four major new changes in geometry subsystems:\n", + "\n", + "- partially buried engine in fuselage,\n", + "- Fuselage layout and size parameters,\n", + "- Computation of wing tank fuel volume (either with wing fold or not),\n", + "- Exposed wing area computation.\n", + "\n", + "We will explain some details of each feature in this document." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ad70480", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.SEAT_WIDTH), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.NUM_AISLES), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.AISLE_WIDTH), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_PASSENGERS), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.AVG_DIAMETER), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "359567b5", + "metadata": {}, + "source": [ + "### Partially Buried Engine in Fuselage\n", + "\n", + "In a BWB, an engine can be partially buried in fuselage. Supposed that the nacelle has the diameter $D$ and the buried diameter is $d$. In Aviary, Let's denote the ratio $x = d/D$. So, $0 \\le x \\le 1$. This variable is called {glue:md}`Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE`. Then the percentage of perimeter not buried in fuselage is $f(x) = 1 - \\arccos(2*(0.5 -x))/\\pi$. As we see, if the nacelle is not buried in fuselage at all, then $x = 0$ and $f(x) = 1$. Note that function $f(x)$ has infinity derivatives at $x = 0$ and $x = 1$. We have to use two cubic functions instead near the two ends. This is shown in the following image:\n", + "\n", + "![Partially buried engine in fuselage](../images/BWB_engine.png)\n", + "\n", + "The wetted area of nacelle can be computed as usual but scaled down by a factor $f(x)$.\n", + "\n", + "### Fuselage Layout\n", + "\n", + "In the current implementation, a few parameters are fixed for the first class cabin:\n", + "\n", + "| Parameters | Values | Units |\n", + "| ---------- | ------ | ----- |\n", + "| length of first class lav, galley & closet | 8.0 | ft |\n", + "| first class seat width | 28.0 | inch |\n", + "| first class seat pitch | 36.0 | inch |\n", + "| Number of aisles in first class | 2 | unitless |\n", + "| First class aisle width | 24.0 | inch |\n", + "| Length of first class/tourist class aisle | 5.0 | ft |\n", + "| Tourist class passengers per lav | 78 | unitless |\n", + "| Lav width | 42.0 | inch |\n", + "| Tourist class galley area per passenger | 0.15 | ft**2 |\n", + "| | | |\n", + "\n", + "Aviary will try to fit the seats in both first class and tourist class based on the above and following parameters:\n", + "\n", + "| Parameters | Units |\n", + "| ---------- | ----- |\n", + "| {glue:md}`Aircraft.Fuselage.SEAT_WIDTH` | inch |\n", + "| {glue:md}`Aircraft.Fuselage.NUM_AISLES` | unitless |\n", + "| {glue:md}`Aircraft.Fuselage.AISLE_WIDTH` | inch |\n", + "| {glue:md}`Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST` | inch |\n", + "| {glue:md}`Aircraft.CrewPayload.Design.NUM_PASSENGERS` | unitless |\n", + "| {glue:md}`Aircraft.CrewPayload.Design.NUM_FIRST_CLASS` | unitless |\n", + "| {glue:md}`Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP` | deg |\n", + "| {glue:md}`Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH` | ft |\n", + "| {glue:md}`Aircraft.Fuselage.AVG_DIAMETER` | ft |\n", + "| {glue:md}`Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL` | ft |\n", + "| nose_length | ft |\n", + "| | |\n", + "\n", + "The output is the fuselage station of aft pressure bulkhead. If there is no first class cabin, please set {glue:md}`Aircraft.CrewPayload.Design.NUM_FIRST_CLASS` to 0.0.\n", + "\n", + "The fuselage size group is shown as follows:\n", + "\n", + "![Fuselage size](../images/BWB_GASP_Fuselage_Geometry.png)\n", + "\n", + "### Wing Fuel Volume Computation\n", + "\n", + "For the wing fuel volume, we first compute its value assuming no wing fold structure. In\n", + "the case of wing fold, a simple adjustment model from the first computation for the wing fuel volume is implemented using linear interpolation plus factors for wing thickness.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19502cf3", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "from aviary.subsystems.geometry.gasp_based.wing import WingFoldArea, BWBWingFoldVolume\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.VERTICAL_MOUNT_LOCATION), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Wing.SPAN), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Wing.TAPER_RATIO), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Wing.AREA), md_code=False)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.ASPECT_RATIO), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Wing.SWEEP), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Wing.THICKNESS_TO_CHORD_TIP), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.LandingGear.MAIN_GEAR_LOCATION), md_code=False)\n", + "glue_variable(get_variable_name(Aircraft.Fuel.WING_FUEL_FRACTION), md_code=False)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.FOLDED_SPAN), md_code=False)\n", + "\n", + "glue_variable(get_variable_name(WingFoldArea), md_code=True)\n", + "glue_variable(get_variable_name(BWBWingFoldVolume), md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "723142b3", + "metadata": {}, + "source": [ + "### Exposed Wing Area Computation\n", + "\n", + "For blended wing body aircraft, the exposed wing area refers to the wing section that is not fully integrated or blended into the fuselage, but rather extends outwards, potentially with a distinct edge or separation from the body. It must be computed separately and it will be used in the angle of attack computation.\n", + "\n", + "One of the dependent parameters is {glue:md}`Aircraft.Wing.VERTICAL_MOUNT_LOCATION` (denoted by $x$ in this section, where $0 \\le x \\le 1$, unitless). Giving $x$, the body half span at the wing location depends on function $f(x) = \\sqrt{(0.25 - (0.5 - x)^2)}$. Since $f(x)$ has infinite derivatives at the two ends, we must create two cubic polynomials instead near the ends. The implementation is similar to that of partially buried engine in fuselage and we skip the details here.\n", + "\n", + "Other design parameters are:\n", + "\n", + "| Parameters | Units |\n", + "| ---------- | ----- |\n", + "| {glue:md}`Aircraft.Fuselage.AVG_DIAMETER` | ft |\n", + "| {glue:md}`Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO` | unitless |\n", + "| {glue:md}`Aircraft.Wing.SPAN` | ft |\n", + "| {glue:md}`Aircraft.Wing.TAPER_RATIO` | unitless |\n", + "| {glue:md}`Aircraft.Wing.AREA` | ft**2 |\n", + "| | |\n", + "\n", + "### Outputs from Wing Group\n", + "\n", + "Several geometric parameters are used:\n", + "\n", + "| Parameters | Units |\n", + "| ---------- | ----- |\n", + "| {glue:md}`Aircraft.Wing.ASPECT_RATIO` | unitless |\n", + "| {glue:md}`Aircraft.Wing.TAPER_RATIO` | unitless |\n", + "| {glue:md}`Aircraft.Wing.SWEEP` | deg |\n", + "| {glue:md}`Aircraft.Wing.THICKNESS_TO_CHORD_ROOT` | unitless |\n", + "| {glue:md}`Aircraft.Fuselage.AVG_DIAMETER` | ft |\n", + "| {glue:md}`Aircraft.Wing.THICKNESS_TO_CHORD_TIP` | unitless |\n", + "| {glue:md}`Aircraft.LandingGear.MAIN_GEAR_LOCATION` | ft |\n", + "| {glue:md}`Aircraft.Fuel.WING_FUEL_FRACTION` | unitless |\n", + "| | |\n", + "\n", + "In BWB model, we assume that the wing has no strut. \n", + "\n", + "If the wing has fold, an additional geometric parameter is needed:\n", + "\n", + "| Parameters | Units |\n", + "| ---------- | ----- |\n", + "| {glue:md}`Aircraft.Wing.FOLDED_SPAN` | ft |\n", + "| | |\n", + "\n", + "The wing group is shown as follows (assuming no fold):\n", + "\n", + "![Wing computation](../images/BWB_GASP_wing_Geom_no_fold.png)\n", + "\n", + "If we add fold structure, the diagram has two more components {glue:md}`WingFoldArea` and \n", + "{glue:md}`BWBWingFoldVolume`. Let us de-emphasize other components by compressing all their inputs\n", + "and outputs that are not related to fold structure. We also do not show dimensional and non-dimensional conversion of fold calculation.\n", + "\n", + "![Wing computation](../images/BWB_GASP_wing_Geom_w_fold.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "75b0faa1", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_all_non_aviary_names, get_variable_name, glue_variable\n", + "from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces\n", + "from aviary.subsystems.aerodynamics.gasp_based.table_based import TabularCruiseAero\n", + "from aviary.subsystems.aerodynamics.gasp_based.gaspaero import (\n", + " BWBBodyLiftCurveSlope,\n", + " AeroGeom,\n", + " AeroSetup,\n", + " FormFactorAndSIWB,\n", + " UFac,\n", + " BWBBodyLiftCurveSlope,\n", + ")\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.HYDRAULIC_DIAMETER), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.FORM_FACTOR), md_code=True)\n", + "\n", + "glue_variable(get_variable_name(BWBBodyLiftCurveSlope), md_code=True)\n", + "glue_variable(get_variable_name(TabularCruiseAero), md_code=True)\n", + "glue_variable(get_variable_name(AeroGeom), md_code=True)\n", + "glue_variable(get_variable_name(AeroSetup), md_code=True)\n", + "\n", + "[cl, cd] = get_all_non_aviary_names(AeroForces, include_in_out='in')\n", + "glue_variable('CL', cl, md_code=True)\n", + "glue_variable('CD', cd, md_code=True)\n", + "siwb = get_all_non_aviary_names(FormFactorAndSIWB)[0]\n", + "glue_variable('siwb', siwb, md_code=True)\n", + "ufac = get_all_non_aviary_names(UFac, include_in_out='out')[0]\n", + "glue_variable('ufac', ufac, md_code=True)\n", + "body_lift_curve_slope = get_all_non_aviary_names(BWBBodyLiftCurveSlope)[0]\n", + "glue_variable('body_lift_curve_slope', body_lift_curve_slope, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "id": "ba35cb8b", + "metadata": {}, + "source": [ + "## GASP Base Mass\n", + "\n", + "After the changes in geometry, several mass computation must be updated. Comparing to traditional tube and wing model, BWB modeling has four major new changes in mass subsystems:\n", + "\n", + "- Computation of various design load speeds,\n", + "- Computation of air conditioning mass and furnishing mass,\n", + "- Computation of BWB fuselage,\n", + "- Computation of wing mass for BWB\n", + "\n", + "### Design Load\n", + "\n", + "In the case of tube + wing design, we assume a given\n", + " wing loading. In the case of BWB, wing loading is replaced by gross mass over exposed wing area:\n", + "\n", + "

wing loading = gross mass / exposed wing area

\n", + "\n", + "A diagram is shown below. We simplied the inputs and outputs but high light gross mass and exposed wing area.\n", + "\n", + "![BWB design load](../images/BWB_GASP_design_load.png)\n", + "\n", + "### Equipments Masses and Useful Load\n", + "\n", + "Air conditioning mass and furnishing mass are part of equipments and useful load masses. In the case of tube + wing design, Aviary uses {glue:md}`Aircraft.Fuselage.AVG_DIAMETER` as cabin width. In the case of BWB, this parameter must be replaced by hydraulic diameter ({glue:md}`Aircraft.Fuselage.HYDRAULIC_DIAMETER`). To compute hydraulic diameter, we use cabin width and cabin height to obtain the cabin cross area and then:\n", + "\n", + "

hydraulic diameter = (4 * (fuselage cross area) / π)1/2

\n", + "\n", + "### Fuselage Mass\n", + "\n", + "Because of the shape of BWB aircraft, the computation of fuselage mass is quite different from conventional aircraft. It is basically an empirical equation based on collected data.\n", + "\n", + "### Wing Mass\n", + "\n", + "In the wing mass computation of conventional aircraft, we assume the cabin width (or fuselage width) is small. But that is not the case for BWB. So, for BWB aircraft, wing span is replaced by:\n", + "\n", + "

wing span - cabin width

\n", + "\n", + "All other steps are the same.\n", + "\n", + "## GASP Based Aerodynamics\n", + "\n", + "All the BWB related modifications in aerodynamics reside in `subsystems/aerodynamics/gasp_based/gaspaero.py`. The primary goal is to compute the lift coefficient {glue:md}`CL` and the drag coefficient {glue:md}`CD`. Because of the shape of fuselage, the lift effect from the body can not be ignored. The main features are:\n", + "\n", + "**1. Computation of body form factor**\n", + "\n", + "In the computation of body form drag factor {glue:md}`Aircraft.Fuselage.FORM_FACTOR`, the fuselage fineness ratio is based on hydraulic diameter instead of fuselage average diameter. Let us denote the body form drag factor as `body_form_factor`. Then, it holds ${\\rm body\\_form\\_factor}(x) = 1 + 1.5x^{1.5} + 7x^3$, where $x = ({\\rm hydraulic diameter}) / ({\\rm fuselage length})$.\n", + "\n", + "**2. Computation of curve fitting correction factor for Oswald efficiency**\n", + "\n", + "In GASP and Aviary, there is a parameter named {glue:md}`siwb`. It is basically the curve fitting correction factor for Oswald efficiency and it holds ${\\rm siwb}(x) = 1 - 0.0088x - 1.7364x^2 - 2.303x^3 + 6.0606x^4$.\n", + "\n", + "For conventional aircraft, $x = ({\\rm cabin width}) / ({\\rm wing span})$. For BWB, $x$ is replaced by hydraulic diameter over wing span.\n", + "\n", + "**3. Computation of unified induced drag correction factor**\n", + "\n", + "In GASP and Aviary, there is a parameter named {glue:md}`ufac`. It is basically the unified induced drag correction factor. For conventional aircraft, this factor is usually around 1. For BWB aircraft, we need to set an upper limit 0.975.\n", + "\n", + "All three parameters above are fed into the main component {glue:md}`AeroGeom` of aero dynamics system {glue:md}`AeroSetup` for BWB aircraft. This system computes the drag parameters from cruise conditions and geometric parameters. The basic diagram is shown below:\n", + "\n", + "![BWB aero setup](../images/BWB_GASP_Aero_setup.png)\n", + "\n", + "**4. Computation of body lift curve slope of fuselage**\n", + "\n", + "For BWB aircraft, lift coefficient depends on both the wing and the body. A new component {glue:md}`BWBBodyLiftCurveSlope` is added to compute the body lift curve slope ({glue:md}`body_lift_curve_slope`) of fuselage for a given Mach number. Suppose that we are given the lift curve slope (`CLALPH_B0` or {glue:md}`Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0`) of fuselage at Mach 0, then for any given Mach, we define\n", + "\n", + "

body_lift_curve_slope = CLALPH_B0 / (1.0 - mach2)1/2

\n", + "\n", + "Note: This formula is valid only for Mach number less than 1. We advise that a BWB model should limit the Mach number to within 0.8 for accuracy. For Mach number greater than 0.8, please consider using table based aero model.\n", + "\n", + "**5. Computation of lift coeficient from the wing**\n", + "\n", + "Depending on whether it is during a cruise flight or low speed flight, the computations of lift coefficient are different. For cruise, the computation is relative clean while for low speed, we must take ground effect into considerations. The two situations are shown in the following two diagrams.\n", + "\n", + "For cruise:\n", + "\n", + "![BWB cruise aero](../images/BWB_GASP_Aero_cruise.png)\n", + "\n", + "For low speed:\n", + "\n", + "![BWB low speed aero](../images/BWB_GASP_Aero_lowspeed.png)\n", + "\n", + "This model has its limitations. Generally speaking, it is good for number of passengers fewer than 250. There are other limitations. For detailed discussions, we refer readers to [theory guide](../../theory_guide/gasp_based_bwb).\n", + "\n", + "**6. Computation of total lift coefficient**\n", + "\n", + "The total lift coefficient is a scaled sum of lift coeficient of the wings and the lift coefficient of the body. For the wing, the ratio of the exposed wing area vs the wing area scales the the lift coefficient of the wings. For the body, the ratio of planform area over the the wing area.\n", + "\n", + "## GASP Based Aerodynamics using an aerodynamics table\n", + "\n", + "As we point out earlier, the designed maximum cruise Mach number should be less than or equal to 0.8. If the Mach number is greater than 0.8, the lift and drag coefficients can be computed using table based modeling {glue:md}`TabularCruiseAero`. Aero tables are usually the results of high fidelity CFD tools. Aviary provide a tool to convert GASP aero tables to Aviary format. In terms of the modeling, there is no special treatment for BWB aircraft than traditional aircraft." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/aviary/docs/user_guide/features/overriding.ipynb b/aviary/docs/user_guide/features/overriding.ipynb index 2948c2b1e8..c6aceeff6e 100644 --- a/aviary/docs/user_guide/features/overriding.ipynb +++ b/aviary/docs/user_guide/features/overriding.ipynb @@ -27,7 +27,7 @@ "\n", "Aviary allows you to replace certain internally computed quantities with a custom value, which can either be a constant or a value computed by some custom component through a capability called `Overriding`. The motivation for this capability comes from FLOPS, which allowed the user to override certain variables with pre-computed values from other more accurate sources. Aviary expands this feature to allow direct override of any intermediate calculation except for dynamic mission variables that are controlled by Dymos.\n", "\n", - "Throughout an Aviary model, all inputs and outputs that begin with \"aircraft:\" or \"mission:\" are promoted to the top level. When an output and an input have the same name, they are implicitly connected through this process. When we override an Aviary output, it is no longer promoted as the original variable name, but is instead promoted with the string \"AUTO_OVERRIDE:\" prepended to the variable name. This eliminates the connection from the output to the input and a visible dead-end promoted name that will be seen in the `list_outputs`. \n", + "Throughout an Aviary model, all inputs and outputs that begin with \"aircraft:\" or \"mission:\" are promoted to the top level. When an output and an input have the same name, they are implicitly connected through this process. When we override an Aviary output, it is no longer promoted as the original variable name, but is instead promoted with the string \"AIRCRAFT_DATA_OVERRIDE:\" prepended to the variable name. This eliminates the connection from the output to the input and a visible dead-end promoted name that will be seen in the `list_outputs`. \n", "\n", "Once an output has been overridden, the inputs are free to take on any value specified in the `aviary_inputs`. If you add an external component to your aviary model that provides this same output, then those inputs will be implicitly connected to that component. If you add multiple components that provide the output, then you will have to override all but one of them.\n", "\n", @@ -44,15 +44,33 @@ "metadata": {}, "outputs": [], "source": [ - "from aviary.api import Aircraft\n", "import aviary.api as av\n", - "from aviary.validation_cases.validation_data.flops_data.FLOPS_Test_Data import FLOPS_Test_Data\n", + "from aviary.api import Aircraft\n", + "from aviary.validation_cases.validation_tests import get_flops_inputs\n", "\n", - "aviary_inputs = av.AviaryValues(FLOPS_Test_Data['LargeSingleAisle1FLOPS']['inputs'])\n", + "aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS')\n", "\n", "aviary_inputs.set_val(Aircraft.HorizontalTail.MASS, 2200.0, units='lbm')" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c32c524", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "glue_variable(get_variable_name(Aircraft.HorizontalTail.MASS), md_code=False)" + ] + }, { "cell_type": "markdown", "id": "encouraging-picnic", @@ -60,7 +78,7 @@ "source": [ "## Replacing Computed Value with the Output of Another Component\n", "\n", - "Consider a case where we have added one component that computes the mass of the horizontal tail. We want to override the internally computed value of the mass with a new value that comes from an external component. We can do this in the level 2 interface when we define our builder, by simply providing an output that uses Aviary's name in the variable hierarchy. (i.e., Aircraft.HorizontalTail.MASS for this case) When we do this, aviary will automatically detect that an external subsystem is providing this variable, and will override the internal calculation." + "Consider a case where we have added one component that computes the mass of the horizontal tail. We want to override the internally computed value of the mass with a new value that comes from an external component. We can do this in the level 2 interface when we define our builder, by simply providing an output that uses Aviary's name in the variable hierarchy. (i.e., {glue:md}`Aircraft.HorizontalTail.MASS` for this case) When we do this, aviary will automatically detect that an external subsystem is providing this variable, and will override the internal calculation." ] }, { @@ -72,35 +90,30 @@ "source": [ "import openmdao.api as om\n", "\n", - "from aviary.api import SubsystemBuilderBase, Aircraft\n", + "from aviary.api import Aircraft, SubsystemBuilderBase\n", "\n", "\n", "class HTailMass(om.ExplicitComponent):\n", - " \"\"\"\n", - " User-provided subsystem to compute the tail weight with a simple formula.\n", - " \"\"\"\n", + " \"\"\"User-provided subsystem to compute the tail weight with a simple formula.\"\"\"\n", "\n", " def setup(self):\n", - "\n", " self.add_input('Area', 1.0, units='ft**2')\n", " self.add_output('Mass', 1.0, units='lbm')\n", - " \n", + "\n", " self.declare_partials('Mass', 'Area', val=20.0)\n", "\n", " def compute(self, inputs, outputs):\n", " outputs['Mass'] = 20.0 * inputs['Area']\n", - " \n", - " \n", + "\n", + "\n", "class HTailWeightBuilder(SubsystemBuilderBase):\n", - " \"\"\"\n", - " Prototype of a subsystem that overrides an aviary internally computed var.\n", - " \"\"\"\n", + " \"\"\"Prototype of a subsystem that overrides an aviary internally computed var.\"\"\"\n", "\n", " def __init__(self, name='wing_weight'):\n", " super().__init__(name)\n", "\n", " def build_pre_mission(self, aviary_inputs):\n", - " '''\n", + " \"\"\"\n", " Build an OpenMDAO system for the pre-mission computations of the subsystem.\n", "\n", " Returns\n", @@ -109,17 +122,20 @@ " An OpenMDAO system containing all computations that need to happen in\n", " the pre-mission part of the Aviary problem. This\n", " includes sizing, design, and other non-mission parameters.\n", - " '''\n", + " \"\"\"\n", " wing_group = om.Group()\n", - " wing_group.add_subsystem(\"tail_weight\", HTailMass(),\n", - " promotes_inputs=[('Area', Aircraft.HorizontalTail.AREA)],\n", - " promotes_outputs=[('Mass', Aircraft.HorizontalTail.MASS)]\n", - " )\n", + " wing_group.add_subsystem(\n", + " 'tail_weight',\n", + " HTailMass(),\n", + " promotes_inputs=[('Area', Aircraft.HorizontalTail.AREA)],\n", + " promotes_outputs=[('Mass', Aircraft.HorizontalTail.MASS)],\n", + " )\n", " return wing_group\n", "\n", "\n", - "from aviary.api import default_height_energy_phase_info as phase_info \n", - "phase_info['pre_mission']['external_subsystems'] = [HTailWeightBuilder(name=\"tail_external\")]\n" + "from aviary.api import default_height_energy_phase_info as phase_info\n", + "\n", + "phase_info['pre_mission']['external_subsystems'] = [HTailWeightBuilder(name='tail_external')]" ] }, { @@ -152,7 +168,7 @@ "metadata": { "celltoolbar": "Tags", "kernelspec": { - "display_name": "Python 3", + "display_name": "av1", "language": "python", "name": "python3" }, @@ -166,7 +182,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.17" + "version": "3.9.18" }, "orphan": true }, diff --git a/aviary/docs/user_guide/features_and_functionalities.ipynb b/aviary/docs/user_guide/features_and_functionalities.ipynb index 27a2ef86e2..e86bef5863 100644 --- a/aviary/docs/user_guide/features_and_functionalities.ipynb +++ b/aviary/docs/user_guide/features_and_functionalities.ipynb @@ -1,5 +1,27 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.api import LegacyCode\n", + "from aviary.interface.methods_for_level2 import AviaryGroup\n", + "from aviary.utils.doctape import glue_variable, glue_class_options\n", + "\n", + "current_glued_vars = []\n", + "glue_class_options(AviaryGroup, current_glued_vars, md_code=True)\n", + "\n", + "glue_variable(LegacyCode.FLOPS.name, md_code=False)\n", + "glue_variable(LegacyCode.GASP.name, md_code=False)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -45,11 +67,11 @@ "\n", "Throughout Aviary we use a series of terms when discussing mission optimization.\n", "\n", - "A \"trajectory\" is the full mission that the aircraft flies.\n", + "A [\"trajectory\"](https://openmdao.github.io/dymos/features/phases/phases.html) is the full mission that the aircraft flies.\n", "Usually this is from takeoff to landing, inclusive.\n", "Sometimes you might want to model just a portion of the full aircraft trajectory; for example only the cruise portion.\n", "\n", - "A \"phase\" is a part of the trajectory that is defined by a single set of differential equations.\n", + "A [\"phase\"](https://openmdao.github.io/dymos/features/phases/phases.html) is a part of the trajectory that is defined by a single set of differential equations.\n", "For example, a simple way of defining a full trajectory is to have climb, cruise, and descent phases.\n", "Each of these phases can have different physics, subsystems, controls, and constraints.\n", "For example, the climb phase for a hybrid-electric aircraft might be have electric motor assistance whereas that might not be needed for the cruise phase.\n", @@ -59,19 +81,18 @@ "\n", "### Defining a mission\n", "\n", - "A mission is defined by a series of phases that the user chooses by specifying options in the `phase_info` dictionary.\n", - "The `phase_info` dictionary is a dictionary of dictionaries, where each key is the name of a phase and the value is a dictionary of options for that phase.\n", + "A mission is defined by a series of phases that the user chooses by specifying options in the {glue:md}`mission_info` dictionary.\n", + "The {glue:md}`mission_info` dictionary is a dictionary of dictionaries, where each key is the name of a phase and the value is a dictionary of options for that phase.\n", "\n", "How you choose to define your phases is dependent on the aircraft you're modeling, the mission you're trying to evaluate, and the flexibility you want to give the optimizer.\n", "For example, if you have a relatively conventional aircraft that is flying a straightforward mission, you might just need three phases: climb, cruise, and descent.\n", "However, if you have a more complex aircraft or mission, you might need to define more phases.\n", "For instance, if you're modeling a hybrid-electric aircraft with non-conventional propulsion systems that are controlled in different ways, you might want to define additional phases and prescribe different options based on which physics you want included at different stages in the flight.\n", "\n", - "In general, if you're familiar with the legacy tools FLOPS or GASP, you can use the corresponding default `phase_info` objects to start defining your mission.\n", + "In general, if you're familiar with the legacy tools {glue:md}`FLOPS` or {glue:md}`GASP`, you can use the corresponding default {glue:md}`mission_info` objects to start defining your mission.\n", "FLOPS-based missions have three integrated phases: climb, cruise, and descent, as well as analytic takeoff and landing systems.\n", - "GASP-based missions have at least nine integrated phases: groundroll, rotation, ascent, accel, climb1, climb2, cruise, desc1, and desc2, as well landing systems.\n", - "GASP-based missions that are solved using SGM have additional phases.\n", - "The difference in the number of phases is due to the fact that GASP had more detailed requirements on the flight profile, especially in the early phases of a mission." + "GASP-based missions have at least nine integrated phases: {glue:md}`groundroll`, {glue:md}`rotation`, {glue:md}`ascent`, {glue:md}`accel`, {glue:md}`climb1`, {glue:md}`climb2`, {glue:md}`cruise`, {glue:md}`desc1`, and {glue:md}`desc2`, as well landing systems.\n", + "The difference in the number of phases is due to the fact that {glue:md}`GASP` had more detailed requirements on the flight profile, especially in the early phases of a mission." ] }, { @@ -85,17 +106,28 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.utils.check_phase_info import phase_keys_gasp\n", - "from aviary.utils.doctape import check_value\n", - "expected_keys = ['groundroll', 'rotation', 'ascent', 'accel', 'climb1', 'climb2', 'cruise', 'desc1', 'desc2']\n", - "check_value(list(phase_keys_gasp.keys()), expected_keys)" + "from aviary.utils.doctape import check_value, get_variable_name, glue_variable\n", + "\n", + "expected_keys = [\n", + " 'groundroll',\n", + " 'rotation',\n", + " 'ascent',\n", + " 'accel',\n", + " 'climb1',\n", + " 'climb2',\n", + " 'cruise',\n", + " 'desc1',\n", + " 'desc2',\n", + "]\n", + "for key in expected_keys:\n", + " glue_variable(key, md_code=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "You can import a copy of the default `phase_info` dicts and then modify them as you need to for your own mission definition.\n", + "You can import a copy of the default {glue:md}`mission_info` dicts and then modify them as you need to for your own mission definition.\n", "\n", "### Defining mission controls and constraints\n", "\n", @@ -106,55 +138,13 @@ "However, if you're modeling an urban air mobility aircraft that will fly a more complex mission, you might want to give the optimizer more flexibility in how it flies the mission.\n", "Purposefully giving the optimizer the freedom to explore the trajectory design space at the same time it's designing the aircraft is a perfect example use case for Aviary.\n", "This will result in a more complex optimization problem that might not converge well without some expert knowledge of the problem, but it will allow you to explore the design space more fully.\n", - "\n", - "## Collocation and Shooting\n", - "\n", - "Both [collocation](https://openmdao.org/dymos/docs/latest/getting_started/collocation.html) and shooting methods are included in Aviary for mission analysis as they each have something to offer.\n", - "Collocation methods are easily parallelizable and call the model ODE relatively few times.\n", - "This leads to significantly faster optimization times for large problems.\n", - "\n", - "```{note}\n", - "Please see [this Dymos doc page](https://openmdao.org/dymos/docs/latest/getting_started/transcriptions.html#differences-between-collocation-and-explicit-shooting) for a better understanding of the similarities and differences between shooting and collocation methods.\n", - "```\n", - "\n", - "Shooting (or Forward in Time Integration) methods provide physically valid trajectories at all iterations of the optimization. This means that even if an optimization fails to converge, the results are still physical and can be useful for debugging.\n", - "[This journal paper](https://link.springer.com/article/10.1007/s10957-023-02303-3) contains more information about the shooting method used in Aviary.\n", - "\n", - "While collocation methods require a reasonably accurate estimation of the trajectory to be able to converge, shooting methods only require the initial state. This makes analyzing a new aircraft or mission easier for analysts as they do not need to produce accurate initial guesses.\n", - "One of the main advantages of shooting methods is the ability to dynamically order phases based on events. This means that different constraints, controls, or ODEs can be used depending on conditions during the trajectory. For example, the drag calculations change depending on aircraft configuration during takeoff; if the flaps are retracted when the aircraft reaches a certain speed, but the gear is retracted based on altitude, the two events could occur in either order.\n", - "\n", - "Collocation results are presented as part of a fixed step-size timeseries. To improve performance, the shooting method uses an adaptive step size; this means that the resulting trajectories will not always have a consistent number of points. There are plans to add a post processing interpolation to the trajectory results to produce a consistent timeseries, but that has not been implemented yet.\n", - "\n", - "```{note}\n", - "When using Aviary, the `AnalysisScheme` option is used to select the integration method. The default is `COLLOCATION`, but this can be changed to `SHOOTING` to use the shooting method.\n", - "```\n", - "\n", - "```{note}\n", - "Due to limitations in the availability of developer time, there will be limited feature development for the shooting method for the near future from the core team; however, we welcome contributions from users.\n", - "For a non-exhaustive list of the currently available key features and how to use them, please see [SGM Capabilities](SGM_capabilities.ipynb)\n", - "```\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "from aviary.variable_info.enums import AnalysisScheme\n", - "AnalysisScheme.COLLOCATION;\n", - "AnalysisScheme.SHOOTING;" + "\n" ] } ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -168,9 +158,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/hamilton_standard.ipynb b/aviary/docs/user_guide/hamilton_standard.ipynb index b6fa18475a..ddc378fccf 100644 --- a/aviary/docs/user_guide/hamilton_standard.ipynb +++ b/aviary/docs/user_guide/hamilton_standard.ipynb @@ -1,5 +1,38 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.api import Aircraft\n", + "from aviary.subsystems.atmosphere.atmosphere import Atmosphere\n", + "from aviary.subsystems.propulsion.propeller.hamilton_standard import (\n", + " HamiltonStandard,\n", + " PostHamiltonStandard,\n", + " PreHamiltonStandard,\n", + ")\n", + "from aviary.subsystems.propulsion.propeller.propeller_performance import InstallLoss\n", + "from aviary.utils.doctape import check_value, get_variable_name, glue_variable\n", + "\n", + "check_value(\n", + " Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS,\n", + " 'aircraft:engine:propeller:compute_installation_loss',\n", + ")\n", + "glue_variable(get_variable_name(Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS), md_code=True)\n", + "glue_variable(Atmosphere.__name__, md_code=True)\n", + "glue_variable(InstallLoss.__name__, md_code=True)\n", + "glue_variable(PreHamiltonStandard.__name__, md_code=True)\n", + "glue_variable(HamiltonStandard.__name__, md_code=True)\n", + "glue_variable(PostHamiltonStandard.__name__, md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -12,7 +45,7 @@ "You can find the definitions, methodology, and Fortran code in the document.\n", "In Aviary, we implement only one of the computation options: the code computes the corresponding thrust for a given horsepower.\n", "\n", - "Below is an XDSM diagram of Hamilton Standard model (assuming `Dynamic.Mission.INSTALLATION_LOSS_FACTOR` is computed):\n", + "Below is an XDSM diagram of Hamilton Standard model (assuming {glue:md}`Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS` is `True`):\n", "\n", "![Hamilton Standard Diagram](images/hamilton_standard.png)\n", "\n", @@ -63,13 +96,13 @@ "\n", "When shaft power is zero, propeller efficiencies are undefined. We set them as 0.0.\n", "\n", - "As shown in the above XDSM diagram, the model is an OpenMDAO group that is composed of four components and one subgroup:\n", + "As shown in the above XDSM diagram, the model is an OpenMDAO group that is composed of three components and two groups:\n", "\n", - "- `USatmos`\n", - "- `PreHamiltonStandard`\n", - "- `HamiltonStandard`\n", - "- `InstallLoss`\n", - "- `PostHamiltonStandard`" + "- {glue:md}`Atmosphere` (group)\n", + "- {glue:md}`PreHamiltonStandard`\n", + "- {glue:md}`HamiltonStandard`\n", + "- {glue:md}`InstallLoss` (group)\n", + "- {glue:md}`PostHamiltonStandard`" ] }, { @@ -84,55 +117,54 @@ "source": [ "# Testing Cell\n", "import openmdao.api as om\n", - "from aviary.subsystems.atmosphere.atmosphere import Atmosphere\n", - "from aviary.subsystems.propulsion.propeller.propeller_performance import PropellerPerformance, InstallLoss\n", + "\n", + "import aviary.api as av\n", "import aviary.subsystems.propulsion.propeller.hamilton_standard as hs\n", + "from aviary.subsystems.atmosphere.atmosphere import Atmosphere\n", + "from aviary.subsystems.propulsion.propeller.propeller_performance import (\n", + " InstallLoss,\n", + " PropellerPerformance,\n", + ")\n", "from aviary.variable_info.options import get_option_defaults\n", - "import aviary.api as av\n", "\n", "options = get_option_defaults()\n", - "options.set_val(av.Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, val=True, units='unitless')\n", - "options.set_val(av.Aircraft.Engine.NUM_PROPELLER_BLADES, val=4, units='unitless')\n", + "options.set_val(av.Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=True, units='unitless')\n", + "options.set_val(av.Aircraft.Engine.Propeller.NUM_BLADES, val=4, units='unitless')\n", "options.set_val(av.Aircraft.Engine.GENERATE_FLIGHT_IDLE, False)\n", - "options.set_val(av.Aircraft.Engine.DATA_FILE, 'models/engines/turboshaft_4465hp.deck')\n", - "options.set_val(av.Aircraft.Engine.USE_PROPELLER_MAP, val=False)\n", + "options.set_val(av.Aircraft.Engine.DATA_FILE, 'models/engines/turboshaft_4465hp.csv')\n", "\n", "prob = om.Problem()\n", "group = prob.model\n", - "for name in ('traj','cruise','rhs_all'):\n", + "for name in ('traj', 'cruise', 'rhs_all'):\n", " group = group.add_subsystem(name, om.Group())\n", "var_names = [\n", - " (av.Aircraft.Engine.PROPELLER_TIP_SPEED_MAX,0,{'units':'ft/s'}),\n", + " (av.Aircraft.Engine.Propeller.TIP_SPEED_MAX, 0, {'units': 'ft/s'}),\n", " # (av.Dynamic.Mission.PERCENT_ROTOR_RPM_CORRECTED,0,{'units':'unitless'}),\n", - " (av.Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR,0,{'units':'unitless'}),\n", - " (av.Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT,0,{'units':'unitless'}),\n", - " ]\n", - "group.add_subsystem('ivc',om.IndepVarComp(var_names),promotes=['*'])\n", - "\n", - "prob.model.add_subsystem(\n", - " name='atmosphere',\n", - " subsys=Atmosphere(num_nodes=1),\n", - " promotes=['*']\n", - ")\n", + " (av.Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 0, {'units': 'unitless'}),\n", + " (av.Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0, {'units': 'unitless'}),\n", + "]\n", + "group.add_subsystem('ivc', om.IndepVarComp(var_names), promotes=['*'])\n", + "\n", + "prob.model.add_subsystem(name='atmosphere', subsys=Atmosphere(num_nodes=1), promotes=['*'])\n", "\n", "pp = prob.model.add_subsystem(\n", " 'pp',\n", " PropellerPerformance(aviary_options=options),\n", " promotes_inputs=['*'],\n", - " promotes_outputs=[\"*\"],\n", + " promotes_outputs=['*'],\n", ")\n", - "pp.set_input_defaults(av.Aircraft.Engine.PROPELLER_DIAMETER, 10, units=\"ft\")\n", - "pp.set_input_defaults(av.Dynamic.Mission.MACH, .7, units=\"unitless\")\n", - "# pp.set_input_defaults(av.Dynamic.Mission.TEMPERATURE, 650, units=\"degR\")\n", - "pp.set_input_defaults(av.Dynamic.Mission.PROPELLER_TIP_SPEED, 800, units=\"ft/s\")\n", - "pp.set_input_defaults(av.Dynamic.Mission.VELOCITY, 100, units=\"knot\")\n", + "pp.set_input_defaults(av.Aircraft.Engine.Propeller.DIAMETER, 10, units='ft')\n", + "pp.set_input_defaults(av.Dynamic.Atmosphere.MACH, 0.7, units='unitless')\n", + "# pp.set_input_defaults(av.Dynamic.Atmosphere.TEMPERATURE, 650, units=\"degR\")\n", + "pp.set_input_defaults(av.Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, 800, units='ft/s')\n", + "pp.set_input_defaults(av.Dynamic.Mission.VELOCITY, 100, units='knot')\n", "prob.setup()\n", "\n", "subsyses = {\n", - " 'install_loss':InstallLoss,\n", - " 'pre_hamilton_standard':hs.PreHamiltonStandard,\n", - " 'hamilton_standard':hs.HamiltonStandard,\n", - " 'post_hamilton_standard':hs.PostHamiltonStandard,\n", + " 'install_loss': InstallLoss,\n", + " 'pre_hamilton_standard': hs.PreHamiltonStandard,\n", + " 'hamilton_standard': hs.HamiltonStandard,\n", + " 'post_hamilton_standard': hs.PostHamiltonStandard,\n", "}\n", "\n", "for name, component in subsyses.items():\n", @@ -140,18 +172,20 @@ " if subsys is None:\n", " raise ValueError(f\"couldn't find {name} in PropellerPerformance\")\n", " if not isinstance(subsys, component):\n", - " raise TypeError(f'PropellerPerformance component {name} is {type(subsys)}, but should be {component}')" + " raise TypeError(\n", + " f'PropellerPerformance component {name} is {type(subsys)}, but should be {component}'\n", + " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The `atmosphere` component provides the flight conditions.\n", - "The flight conditions are passed to the `PreHamiltonStandard` component which computes the propeller tip Mach number, advance ratio, and power coefficient.\n", - "These values are then fed into the `HamiltonStandard` component.\n", + "The {glue:md}`Atmosphere` component provides the flight conditions.\n", + "The flight conditions are passed to the {glue:md}`PreHamiltonStandard` component which computes the propeller tip Mach number, advance ratio, and power coefficient.\n", + "These values are then fed into the {glue:md}`HamiltonStandard` component.\n", "\n", - "`HamiltonStandard` is the core of the model.\n", + "{glue:md}`HamiltonStandard` is the core of the model.\n", "Given the power coefficient (CP) and advance ratio (J), it finds the blade angle (BL) by a CP-BL chart by tracing the advance ratio.\n", "Then with the blade angle, it finds the thrust coefficient (CT) using its CT-BL chart by tracing advance ratio again.\n", "This algorithm is shown in the below pair of charts.\n", @@ -162,7 +196,7 @@ "\n", "![CP and CT matching](images/CPE_CTE_matching.png)\n", "\n", - "Finally, the thrust is computed in the `PostHamiltonStandard` component based on thrust coefficient and tip compressibility loss factor.\n", + "Finally, the thrust is computed in the {glue:md}`PostHamiltonStandard` component based on thrust coefficient and tip compressibility loss factor.\n", "\n", "The Hamilton Standard model uses wind tunnel test data from uninstalled propellers.\n", "When a nacelle is mounted behind the propeller, an installation loss factor is introduced.\n", @@ -171,7 +205,7 @@ "\n", "![Installation Loss Factor](images/installation_loss_factor.png)\n", "\n", - "This diagram is represented by `InstallLoss` group in the first diagram.\n", + "This diagram is represented by {glue:md}`InstallLoss` group in the first diagram.\n", "Nacelle diameter is needed when installation loss factor is computed.\n", "We use the average nacelle diameter.\n", "\n", @@ -189,8 +223,20 @@ "outputs": [], "source": [ "# Testing Cell\n", + "import inspect\n", + "\n", "from aviary.api import Aircraft, Dynamic\n", - "from aviary.subsystems.propulsion.turboprop_model import TurbopropModel" + "from aviary.subsystems.propulsion.turboprop_model import TurbopropModel\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "glue_variable(get_variable_name(TurbopropModel), md_code=True)\n", + "\n", + "# glue all arguments of function TurbopropModel.__init__()\n", + "sigs = inspect.signature(TurbopropModel)\n", + "parameters = sigs.parameters\n", + "for name, param in parameters.items():\n", + " glue_variable(name, md_code=True)\n", + " # print(f'Name: {name}, Default: {param.default}, Kind: {param.kind}')" ] }, { @@ -203,20 +249,20 @@ }, "outputs": [], "source": [ - "Aircraft.Engine.PROPELLER_DIAMETER\n", - "Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT\n", - "Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR\n", - "Aircraft.Engine.NUM_PROPELLER_BLADES\n", - "Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS\n", - "Dynamic.Mission.PROPELLER_TIP_SPEED\n", - "Dynamic.Mission.SHAFT_POWER" + "Aircraft.Engine.Propeller.DIAMETER\n", + "Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT\n", + "Aircraft.Engine.Propeller.ACTIVITY_FACTOR\n", + "Aircraft.Engine.Propeller.NUM_BLADES\n", + "Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS\n", + "Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED\n", + "Dynamic.Vehicle.Propulsion.SHAFT_POWER" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "To build a turboprop engine that uses the Hamilton Standard propeller model we use a `TurboPropModel` object with `propeller_model` set to `True` and `shaft_power_model` set to `False` (the default):" + "To build a turboprop engine that uses the Hamilton Standard propeller model we use a {glue:md}`TurbopropModel` object without providing a custom {glue:md}`propeller_model`, here it is set to `None` (the default). In this example, we also set {glue:md}`shaft_power_model` to `None`, another default that assumes we are using a turboshaft engine deck:" ] }, { @@ -229,7 +275,7 @@ }, "outputs": [], "source": [ - "engine = TurbopropModel(options=options, shaft_power_model=None, propeller_model=True)" + "engine = TurbopropModel(options=options, shaft_power_model=None, propeller_model=None)" ] }, { @@ -249,9 +295,9 @@ }, "outputs": [], "source": [ - "options.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10, units='ft')\n", - "options.set_val(Aircraft.Engine.NUM_PROPELLER_BLADES, val=4, units='unitless')\n", - "options.set_val(Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, val=True, units='unitless')" + "options.set_val(Aircraft.Engine.Propeller.DIAMETER, 10, units='ft')\n", + "options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=4, units='unitless')\n", + "options.set_val(Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=True, units='unitless')" ] }, { @@ -271,9 +317,52 @@ }, "outputs": [], "source": [ - "prob.set_val(f'traj.cruise.rhs_all.{Aircraft.Engine.PROPELLER_TIP_SPEED_MAX}', 710., units='ft/s')\n", - "prob.set_val(f'traj.cruise.rhs_all.{Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR}', 150., units='unitless')\n", - "prob.set_val(f'traj.cruise.rhs_all.{Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT}', 0.5, units='unitless')" + "prob.set_val(f'traj.cruise.rhs_all.{Aircraft.Engine.Propeller.TIP_SPEED_MAX}', 710.0, units='ft/s')\n", + "prob.set_val(\n", + " f'traj.cruise.rhs_all.{Aircraft.Engine.Propeller.ACTIVITY_FACTOR}', 150.0, units='unitless'\n", + ")\n", + "prob.set_val(\n", + " f'traj.cruise.rhs_all.{Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT}',\n", + " 0.5,\n", + " units='unitless',\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "\n", + "folder_path = av.get_path('models/engines/propellers')\n", + "propellers_dir = folder_path.relative_to(av.top_dir)\n", + "glue_variable(propellers_dir, md_code=True)\n", + "\n", + "file_path = av.get_path(folder_path / 'general_aviation.csv')\n", + "glue_variable(file_path.name, md_code=True)\n", + "\n", + "map_file_name = file_path.stem + '.map'\n", + "file_path = av.get_path(folder_path / map_file_name)\n", + "glue_variable(file_path.name, md_code=True)\n", + "\n", + "file_path = av.get_path(folder_path / 'PropFan.csv')\n", + "glue_variable(file_path.name, md_code=True)\n", + "\n", + "map_file_name = file_path.stem + '.map'\n", + "file_path = av.get_path(folder_path / map_file_name)\n", + "glue_variable(file_path.name, md_code=True)\n", + "\n", + "check_value(Aircraft.Engine.Propeller.DATA_FILE, 'aircraft:engine:propeller:data_file')\n", + "glue_variable(get_variable_name(Aircraft.Engine.Propeller.DATA_FILE), md_code=True)\n", + "check_value(Dynamic.Atmosphere.MACH, 'mach')\n", + "glue_variable(get_variable_name(Dynamic.Atmosphere.MACH), md_code=True)" ] }, { @@ -282,9 +371,9 @@ "source": [ "# Propeller Map Alternative\n", "\n", - "The Hamilton Standard model has limitations where it can be applied; for model aircraft design, it is possible that users may want to provide their own data tables. Two sample data sets are provided in `models/propellers` folder: `general_aviation.prop` and `PropFan.prop`. In both cases, they are in `.csv` format and are converted from `GASP` maps: `general_aviation.map` and `PropFan.map` (see [Command Line Tools](aviary_commands.ipynb) for details). The difference between these two samples is that the generatl aviation sample uses helical Mach numbers as input while the propfan sample uses the free stream Mach numbers. Helical Mach numbers appear higher, due to the inclusion of the rotational component of the tip velocity. In our example, they range from 0.7 to 0.95. To determine which mach type in a GASP map is used, please look at the first integer of the first line. If it is 1, it uses helical mach; if it is 2, it uses free stream mach. To determin which mach type is an Aviary propeller file is used, please look at the second item in the header. It is either `Helical_Mach` or `Mach`.\n", + "The Hamilton Standard model has limitations where it can be applied; for model aircraft design, it is possible that users may want to provide their own data tables. Two sample data sets are provided in {glue:md}`models/engines/propellers` folder: {glue:md}`general_aviation.csv` and {glue:md}`PropFan.csv`. In both cases, they are in `.csv` format and are converted from `GASP` maps: {glue:md}`general_aviation.csv` and {glue:md}`PropFan.csv` (see [Command Line Tools](aviary_commands.ipynb) for details). The difference between these two samples is that the general aviation sample uses helical Mach numbers as input while the propfan sample uses the free stream Mach numbers. Helical Mach numbers appear higher, due to the inclusion of the rotational component of the tip velocity. In our example, they range from 0.7 to 0.95. To determine which mach type in a GASP map is used, look at the first integer of the first line. If it is 1, it uses helical mach; if it is 2, it uses free stream mach. To determine which mach type is an Aviary propeller file is used, look at which variables are present in the header. It is typically either `helical_mach` or `mach`. If both are present in the header, Aviary will directly use the data in the Mach number column.\n", "\n", - "To use a propeller map, users can set `Aircraft.Engine.USE_PROPELLER_MAP` to `True` and provide the propeller map file path to `Aircraft.Engine.PROPELLER_DATA_FILE`. If helical Mach numbers are in the propeller map file, then an `OutMachs` component is added to convert helical Mach numbers to flight Mach numbers (`Dynamic.Mission.MACH`).\n", + "To use a propeller map, users can provide the propeller map file path to {glue:md}`Aircraft.Engine.Propeller.DATA_FILE`.\n", "\n", "In the Hamilton Standard models, the thrust coefficients do not take compressibility into account. Therefore, propeller tip compressibility loss factor has to be computed and will be used to compute thrust. If a propeller map is used, the compressibility effects should be included in the data provided. Therefore, this factor is assumed to be 1.0 and is supplied to post Hamilton Standard component. Other outputs are computed using the same formulas." ] @@ -292,7 +381,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -306,7 +395,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/images/BWB_GASP_Aero_cruise.png b/aviary/docs/user_guide/images/BWB_GASP_Aero_cruise.png new file mode 100644 index 0000000000..09332ce676 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_GASP_Aero_cruise.png differ diff --git a/aviary/docs/user_guide/images/BWB_GASP_Aero_lowspeed.png b/aviary/docs/user_guide/images/BWB_GASP_Aero_lowspeed.png new file mode 100644 index 0000000000..7304acd447 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_GASP_Aero_lowspeed.png differ diff --git a/aviary/docs/user_guide/images/BWB_GASP_Aero_setup.png b/aviary/docs/user_guide/images/BWB_GASP_Aero_setup.png new file mode 100644 index 0000000000..39e9cc1e3e Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_GASP_Aero_setup.png differ diff --git a/aviary/docs/user_guide/images/BWB_GASP_Fuselage_Geometry.png b/aviary/docs/user_guide/images/BWB_GASP_Fuselage_Geometry.png new file mode 100644 index 0000000000..717e7a7b63 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_GASP_Fuselage_Geometry.png differ diff --git a/aviary/docs/user_guide/images/BWB_GASP_design_load.png b/aviary/docs/user_guide/images/BWB_GASP_design_load.png new file mode 100644 index 0000000000..ce1dd0defd Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_GASP_design_load.png differ diff --git a/aviary/docs/user_guide/images/BWB_GASP_wing_Geom_no_fold.png b/aviary/docs/user_guide/images/BWB_GASP_wing_Geom_no_fold.png new file mode 100644 index 0000000000..be44cce8b6 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_GASP_wing_Geom_no_fold.png differ diff --git a/aviary/docs/user_guide/images/BWB_GASP_wing_Geom_w_fold.png b/aviary/docs/user_guide/images/BWB_GASP_wing_Geom_w_fold.png new file mode 100644 index 0000000000..69202c40d8 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_GASP_wing_Geom_w_fold.png differ diff --git a/aviary/docs/user_guide/images/BWB_engine.png b/aviary/docs/user_guide/images/BWB_engine.png new file mode 100644 index 0000000000..c1805ef2f5 Binary files /dev/null and b/aviary/docs/user_guide/images/BWB_engine.png differ diff --git a/aviary/docs/user_guide/images/payload-range-envelope.png b/aviary/docs/user_guide/images/payload-range-envelope.png new file mode 100644 index 0000000000..100b13c062 Binary files /dev/null and b/aviary/docs/user_guide/images/payload-range-envelope.png differ diff --git a/aviary/docs/user_guide/input_files.ipynb b/aviary/docs/user_guide/input_files.ipynb index 40465df57e..3bc4aa8c0e 100644 --- a/aviary/docs/user_guide/input_files.ipynb +++ b/aviary/docs/user_guide/input_files.ipynb @@ -35,17 +35,17 @@ }, "outputs": [], "source": [ - "from aviary.api import Aircraft\n", "import aviary.api as av\n", + "from aviary.api import Aircraft\n", "\n", - "file_path = av.get_path('models/test_aircraft/aircraft_for_bench_FwFm.csv')\n", + "file_path = av.get_path('models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv')\n", "\n", "with open(file_path, 'r') as file:\n", " for i, line in enumerate(file):\n", " if i < 20:\n", " print(line.strip('\\n'))\n", " else:\n", - " break\n" + " break" ] }, { @@ -65,12 +65,33 @@ "The data in an external data file must be in column format, delimited by commas. Only numerical data that can be cast to type `float` is compatible with Aviary data tables at this time. An error will be raised if non-numerical data is present in the data file that is not a comment or a correctly formatted header." ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.utils.csv_data_file import read_data_file, write_data_file\n", + "from aviary.utils.doctape import check_value, get_function_names, get_variable_name, glue_variable\n", + "\n", + "file_path = av.get_path('utils/csv_data_file.py')\n", + "takeoff_function_names = get_function_names(file_path)\n", + "\n", + "for function_name in takeoff_function_names:\n", + " glue_variable(function_name + '()', md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Reading and writing Aviary data files\n", - "Aviary includes a pair of utility functions, `read_data_file` and `write_data_file`, to assist reading and writing files in Aviary data format. Here we will demonstrate writing data to a csv file, then reading it back to retrieve the data." + "Aviary includes a pair of utility functions, {glue:md}`read_data_file()` and {glue:md}`write_data_file()`, to assist reading and writing files in Aviary data format. Here we will demonstrate writing data to a csv file, then reading it back to retrieve the data." ] }, { @@ -85,12 +106,14 @@ "data.set_val('Scale Factor', [0.5, 0.75, 0.8], 'unitless')\n", "# add these comments to the file, added to the top. Demonstrate how comments do not\n", "# require inclusion of a '#' symbol, and will work either way\n", - "comments = ['This is test data generated using write_data_file',\n", - " '# Aviary data tables can support multiple comments']\n", + "comments = [\n", + " 'This is test data generated using write_data_file',\n", + " '# Aviary data tables can support multiple comments',\n", + "]\n", "# the name of the file we will write to\n", "filename = 'example.csv'\n", "\n", - "av.write_data_file(filename, data, comments)" + "av.write_data_file(filename, data, comments=comments)" ] }, { @@ -129,25 +152,25 @@ "outputs": [], "source": [ "# read the csv file that was just created\n", - "read_data, read_comments = av.read_data_file(filename, save_comments=True)\n", + "read_data, _, _, read_comments = av.read_data_file(filename, save_comments=True)\n", "# print out comments\n", "print(read_comments)\n", "# print out variable name, units, and values\n", "items = av.get_items(read_data)\n", "for item in items:\n", " print(f'{item[0]}, units: {item[1][1]}')\n", - " print(item[1][0])\n" + " print(item[1][0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Running this code shows our comments were correctly retrieved (stripped of leading `#`). We also have both our variables with their correct units and values. The `write_data_file` function has added back in units of 'unitless' for Mach Number. `Scale Factor` was also modified to `Scale_Factor`. This is because it is assumed these names will feed into openMDAO variables, and spaces are not allowed.\n", + "Running this code shows our comments were correctly retrieved (stripped of leading `#`). We also have both our variables with their correct units and values. The {glue:md}`write_data_file()` function has added back in units of 'unitless' for Mach Number. `Scale Factor` was also modified to `Scale_Factor`. This is because it is assumed these names will feed into openMDAO variables, and spaces are not allowed.\n", "\n", - "Now let's explore some optional arguments for `csv_reader`.\n", + "Now let's explore some optional arguments for {glue:md}`read_data_file()`.\n", "\n", - "The first optional argument for `csv_reader` is variable metadata. When provided, `read_data_file` checks variable names in the header against the metadata and skips reading any variables not found. In addition, units specified in the data file are checked for compatibility with the default units for that variable. If units are not provided for a variable, default units are applied instead of always applying 'unitless'. Let's re-run the same code as before, but this time provide Aviary's core metadata to the reader. The expected behavior is for `Scale Factor` to be skipped, since it isn't in the variable hierarchy." + "The first optional argument for {glue:md}`read_data_file()` is variable metadata. When provided, {glue:md}`read_data_file()` checks variable names in the header against the metadata and skips reading any variables not found. In addition, units specified in the data file are checked for compatibility with the default units for that variable. If units are not provided for a variable, default units are applied instead of always applying 'unitless'. Let's re-run the same code as before, but this time provide Aviary's core metadata to the reader. The expected behavior is for `Scale Factor` to be skipped, since it isn't in the variable hierarchy." ] }, { @@ -157,7 +180,7 @@ "outputs": [], "source": [ "# call read_data_file again, but this time provide variable metadata\n", - "read_data, read_comments = av.read_data_file(filename, av.CoreMetaData, save_comments=True)\n", + "read_data, _, _, read_comments = av.read_data_file(filename, av.CoreMetaData, save_comments=True)\n", "# print out comments\n", "print(read_comments)\n", "# print out variable name, units, and values\n", @@ -173,7 +196,7 @@ "source": [ "We can see that only `aircraft:wing:span` was read from file this time, and is the only variable present in the data loaded to memory. Additionally, a warning was created informing us that `Scale Factor` was skipped.\n", "\n", - "A second optional argument is `aliases`. This argument is used to map multiple possible header names to the same openMDAO variable. This is useful if your data files do not use Aviary variable names, or could contain multiple variants of names that all mean the same thing (such as 'height', 'alt', and 'altitude'). In this example, our data file has a header labeled `Scale Factor`, but we would like to map it to the more precise `aircraft:wing:mass_scaler`. The allowable header name matching is not case-sensitive and Aviary will treat spaces and underscores as identical, so `scale_factor` will match with `Scale Factor`. This improves ease-of-use. However, the variable name you want headers mapped to are case-sensitive, in case you are connecting to an external component that doesn't follow Aviary's [variable naming standards](../developer_guide/coding_standards). So if your alias dict contains `Final_Name: example_var`, any case combination of `example_var` will always return `Final_Name` capitalized as specified." + "A second optional argument is `aliases`. This argument is used to map multiple possible header names to the same openMDAO variable. This is useful if your data files do not use Aviary variable names, or could contain multiple variants of names that all mean the same thing (such as 'height', 'alt', and 'altitude'). In this example, our data file has a header labeled `Scale Factor`, but we would like to map it to the more precise `aircraft:wing:mass_scaler`. The allowable header name matching is not case-sensitive and Aviary will treat spaces and underscores as identical, so `scale_factor` will match with `Scale Factor`. This improves ease-of-use. However, the variable name you want headers mapped to are case-sensitive, in case you are connecting to an external component that doesn't follow Aviary's [variable naming standards](../developer_guide/coding_standards). So if your alias dict contains `Final_Name:example_var`, any case combination of `example_var` will always return `Final_Name` capitalized as specified." ] }, { @@ -188,9 +211,11 @@ "source": [ "# Testing Cell\n", "from aviary.api import Aircraft\n", - "from aviary.utils.doctape import check_value\n", - "check_value(Aircraft.Wing.SPAN,'aircraft:wing:span')\n", - "check_value(Aircraft.Wing.MASS_SCALER,'aircraft:wing:mass_scaler')" + "\n", + "check_value(Aircraft.Wing.SPAN, 'aircraft:wing:span')\n", + "glue_variable(get_variable_name(Aircraft.Wing.SPAN), md_code=True)\n", + "check_value(Aircraft.Wing.MASS_SCALER, 'aircraft:wing:mass_scaler')\n", + "glue_variable(get_variable_name(Aircraft.Wing.MASS_SCALER), md_code=True)" ] }, { @@ -204,7 +229,7 @@ "alias_dict = {Aircraft.Wing.MASS_SCALER: 'Scale Factor'}\n", "\n", "# call read_data_file again, but this time provide variable alias dictionary\n", - "read_data, read_comments = av.read_data_file(filename, aliases=alias_dict, save_comments=True)\n", + "read_data, _, _, read_comments = av.read_data_file(filename, aliases=alias_dict, save_comments=True)\n", "# print out comments\n", "print(read_comments)\n", "# print out variable name, units, and values\n", @@ -238,7 +263,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/mass.ipynb b/aviary/docs/user_guide/mass.ipynb index 912484e2ee..47f310ab4e 100644 --- a/aviary/docs/user_guide/mass.ipynb +++ b/aviary/docs/user_guide/mass.ipynb @@ -1,5 +1,96 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import re\n", + "\n", + "from aviary.subsystems.mass.flops_based.mass_summation import (\n", + " AltSystemsEquipMass,\n", + " EmptyMass,\n", + " FuelMass,\n", + " MassSummation,\n", + " OperatingMass,\n", + " PropulsionMass,\n", + " StructureMass,\n", + " SystemsEquipMass,\n", + " ZeroFuelMass,\n", + ")\n", + "from aviary.subsystems.mass.gasp_based.design_load import DesignLoadGroup\n", + "from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import EquipAndUsefulLoadMassGroup\n", + "from aviary.subsystems.mass.gasp_based.fixed import FixedMassGroup\n", + "from aviary.subsystems.mass.gasp_based.wing import WingMassGroup\n", + "from aviary.subsystems.mass.gasp_based.fuel import FuelMassGroup\n", + "from aviary.subsystems.mass.gasp_based.wing import WingMassGroup\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "\n", + "def split_by_capitals_and_underscores(text):\n", + " # Use a regex to split the string at capital letters and underscores\n", + " # Make sure it handles consecutive capital letters\n", + " phrases = re.findall(r'[A-Z]+(?:[a-z]*)', text)\n", + " phrases = [phrase for phrase in phrases if phrase != '_'] # Remove standalone underscores\n", + " str_phrase = ''\n", + " for item in phrases:\n", + " str_phrase += item + ' '\n", + " str_phrase = str_phrase[:-1]\n", + " return str_phrase\n", + "\n", + "\n", + "AltSystemsEquipMass\n", + "glue_variable(get_variable_name(AltSystemsEquipMass), md_code=True)\n", + "\n", + "st = split_by_capitals_and_underscores(get_variable_name(MassSummation))\n", + "glue_variable('Total ' + st, md_code=False)\n", + "glue_variable(get_variable_name(MassSummation), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(StructureMass))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(StructureMass), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(PropulsionMass))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(PropulsionMass), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(SystemsEquipMass))\n", + "st = st.replace('Equip', 'and Equipment')\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(SystemsEquipMass), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(EmptyMass))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(EmptyMass), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(OperatingMass))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(OperatingMass), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(ZeroFuelMass))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(ZeroFuelMass), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(FuelMass))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(FuelMass), md_code=False)\n", + "\n", + "st = split_by_capitals_and_underscores(get_variable_name(DesignLoadGroup))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(DesignLoadGroup), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(FixedMassGroup))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(FixedMassGroup), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(EquipAndUsefulLoadMassGroup))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(EquipAndUsefulLoadMassGroup), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(WingMassGroup))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(WingMassGroup), md_code=False)\n", + "st = split_by_capitals_and_underscores(get_variable_name(FuelMassGroup))\n", + "glue_variable(st, md_code=False)\n", + "glue_variable(get_variable_name(FuelMassGroup), md_code=False)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -20,31 +111,34 @@ "\n", "### FLOPS-Based Components\n", "\n", - "- **Total Mass Summation:** Orchestrates the calculation of the total mass by summing up contributions from structural, propulsion, systems and equipment, and fuel masses.\n", - "- **Structure Mass:** Calculates the mass contributions from the aircraft's structural components like wings, fuselage, landing gear, etc.\n", - "- **Propulsion Mass:** Computes the mass related to the aircraft's propulsion system, including engines and associated components.\n", - "- **Systems and Equipment Mass:** Determines the mass of systems and equipment on the aircraft, with an alternative calculation option (`AltSystemsEquipMass`) available.\n", - "- **Empty Mass:** Represents the total mass of the aircraft without fuel, calculated using either standard or alternative methods.\n", - "- **Operating Mass:** Accounts for the mass of the crew, passengers, and service items in addition to the empty mass.\n", - "- **Zero Fuel Mass:** The total mass of the aircraft without considering the fuel.\n", - "- **Fuel Mass:** Calculates the mass of the fuel required for the mission.\n", + "- **{glue:md}`Total Mass Summation` ({glue:md}`MassSummation`):** Orchestrates the calculation of the total mass by summing up contributions from structural, propulsion, systems and equipment, and fuel masses.\n", + "- **{glue:md}`Structure Mass` ({glue:md}`StructureMass`):** Calculates the mass contributions from the aircraft's structural components like wings, fuselage, landing gear, etc.\n", + "- **{glue:md}`Propulsion Mass` ({glue:md}`PropulsionMass`):** Computes the mass related to the aircraft's propulsion system, including engines and associated components.\n", + "- **{glue:md}`Systems and Equipment Mass` ({glue:md}`SystemsEquipMass`):** Determines the mass of systems and equipment on the aircraft, with an alternative calculation option ({glue:md}`AltSystemsEquipMass`) available.\n", + "- **{glue:md}`Empty Mass` ({glue:md}`EmptyMass`):** Represents the total mass of the aircraft without fuel, calculated using either standard or alternative methods.\n", + "- **{glue:md}`Operating Mass` ({glue:md}`OperatingMass`):** Accounts for the mass of the crew, passengers, and service items in addition to the empty mass.\n", + "- **{glue:md}`Zero Fuel Mass` ({glue:md}`ZeroFuelMass`):** The total mass of the aircraft without considering the fuel.\n", + "- **{glue:md}`Fuel Mass` ({glue:md}`FuelMass`):** Calculates the mass of the fuel required for the mission.\n", "\n", "### GASP-Based Components\n", "\n", - "- **Design Load Group:** Establishes design load parameters that influence other mass calculations.\n", - "- **Fixed Mass Group:** Deals with fixed masses, like payload and engine mass, that are essential in determining the wing and fuel mass.\n", - "- **Equip and Useful Load Mass:** Calculates the equipment and useful load mass, vital for determining the aircraft's operability.\n", - "- **Wing Mass Group:** Computes the mass of the wing, influenced by fixed mass group outputs.\n", - "- **Fuel Mass Group:** Determines the fuel mass, taking into account design load and fixed mass group parameters.\n", + "- **{glue:md}`Design Load Group` ({glue:md}`DesignLoadGroup`):** Establishes design load parameters that influence other mass calculations.\n", + "- **{glue:md}`Fixed Mass Group` ({glue:md}`FixedMassGroup`):** Deals with fixed masses, like payload and engine mass, that are essential in determining the wing and fuel mass.\n", + "- **{glue:md}`Equip And Useful Load Mass Group` ({glue:md}`EquipAndUsefulLoadMassGroup`):** Calculates the equipment and useful load mass, vital for determining the aircraft's operability.\n", + "- **{glue:md}`Wing Mass Group` ({glue:md}`WingMassGroup`):** Computes the mass of the wing, influenced by fixed mass group outputs.\n", + "- **{glue:md}`Fuel Mass Group` ({glue:md}`FuelMassGroup`):** Determines the fuel mass, taking into account design load and fixed mass group parameters.\n", "\n", "## Using the Mass Subsystem\n", "\n", - "The choice of which code's methods for mass estimate to use is set using the variable `settings:mass_method`. This variable can be specified in the Aviary input file or can be manually set when using the Level 2 or 3 interface.\n", + "The choice of which code's methods for mass estimate to use is set using the variable {glue:md}`setting_MASS_METHOD`. This variable can be specified in the Aviary input file or can be manually set when using the Level 2 or 3 interface.\n", "To effectively use the mass subsystem in Aviary, users need to provide reasonable estimates for mass-related variables in their aircraft .csv file.\n", "Which variables are used depends on which mass estimation subsystem you're using, such as `aircraft:crew_and_payload:mass_per_passenger`, `aircraft:engine:additional_mass_fraction`, etc.\n", "\n", "Aviary allows for extensive customization and extensions within the mass subsystem.\n", - "Users can develop alternative components and integrate them as subsystems with the existing platform." + "Users can develop alternative components and integrate them as subsystems with the existing platform.\n", + "\n", + "## External Mass\n", + "Specifying the `external` mass method disables Aviary's core mass group. This allows for external subsystems to completely replace these calculations." ] }, { @@ -59,16 +153,34 @@ "source": [ "# Testing Cell\n", "from aviary.api import Aircraft, Settings\n", - "from aviary.utils.doctape import check_value\n", - "check_value(Settings.MASS_METHOD,'settings:mass_method')\n", - "check_value(Aircraft.CrewPayload.MASS_PER_PASSENGER,'aircraft:crew_and_payload:mass_per_passenger')\n", - "check_value(Aircraft.Engine.ADDITIONAL_MASS_FRACTION,'aircraft:engine:additional_mass_fraction')" + "from aviary.utils.doctape import check_value, glue_variable\n", + "\n", + "check_value(Settings.MASS_METHOD, 'settings:mass_method')\n", + "check_value(Aircraft.CrewPayload.MASS_PER_PASSENGER, 'aircraft:crew_and_payload:mass_per_passenger')\n", + "check_value(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 'aircraft:engine:additional_mass_fraction')\n", + "\n", + "setting_MASS_METHOD = Settings.MASS_METHOD\n", + "glue_variable('setting_MASS_METHOD', setting_MASS_METHOD, md_code=False)" ] } ], "metadata": { + "kernelspec": { + "display_name": "av1", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/multi_mission.ipynb b/aviary/docs/user_guide/multi_mission.ipynb index 6c18ad0e8e..9daaa3bdf6 100644 --- a/aviary/docs/user_guide/multi_mission.ipynb +++ b/aviary/docs/user_guide/multi_mission.ipynb @@ -12,15 +12,17 @@ "source": [ "# Testing Cell\n", "\n", - "from aviary.utils.doctape import glue_variable, get_variable_name\n", "from aviary.api import Aircraft, AviaryProblem\n", - "glue_variable('capi',AviaryProblem.check_and_preprocess_inputs.__name__,md_code=True)\n", + "from aviary.utils.doctape import get_variable_name, glue_variable, glue_class_functions\n", "\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.Design.NUM_PASSENGERS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_PASSENGERS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_BUSINESS_CLASS), md_code=True)\n", "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_FIRST_CLASS), md_code=True)\n", - "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_TOURIST_CLASS), md_code=True)\n" + "glue_variable(get_variable_name(Aircraft.CrewPayload.NUM_TOURIST_CLASS), md_code=True)\n", + "\n", + "current_glued_vars = []\n", + "glue_class_functions(AviaryProblem, current_glued_vars, prefix='prob', md_code=True)" ] }, { @@ -29,18 +31,44 @@ "source": [ "# Multi-Mission Optimization\n", "\n", + "It is expected that the users is familiar with methods from level 1 and level 2 before exploring this content.\n", + "\n", "## Overview\n", "\n", - "Multi-missions adds the capability to optimize an aircraft design considering two or more missions that the aircraft will perform. This is in contrast to designing an aircraft for a single mission, and hopefully helps to represent the conditions the aircraft will be flying in better. In the example provided, a large single aisle passenger aircraft is designed based on a mission with every seat filled, and a second 'deadhead' mission where there are no passengers. A weighting is provided by the user to determine how often the missions are full of passengers vs. how often the flights are empty. A cargo example could be constructed where one mission is designed for maximum range and a second mission designed for maximum payload. \n", + "Some of the more advanced capabilities that aviary can perform include a multi-mission optimization. The simplest capability could be described as optimize a single aircraft design considering two or more missions that the aircraft will perform. This is in contrast to the traditional \"Design\" an aircraft for a single mission, and and then fly the aircraft model in \"Off Design\" to see how it performs in all other mission scenarios. Multi-mission blurs these lines, allowing the aircraft to be designed by asessing the impact over many different missions simultaneously. As such, an economic mission flown for 70% of missions, a max payload mission flown for 20% of missions, and a max range mission flown for 10% of missions could all simultaneously contribute to the aircraft design. The weightings are specified by the user and ideally would reflect the frequency at which each of the individual missions were flown. At it's most complex, multi-mission could allow the user to optimize multiple different aircraft which have a collection of common parts that are being sized (i.e. engines), and each of those aircraft are also flying multiple different missions. \n", + "\n", + "The MDAO architecture of multi-mission is uses a single monolithic optimization problem. There is no sub-optimizers in the current implementation. This limits the capabilities for including subsystems, such as uncertainty quantification, that are known to fail with mololithic architectures. Future releases may incorporate sub-optimization as a feature.\n", + "\n", + "In the example provided, a large single aisle passenger aircraft is designed based on a mission with every seat filled, and a second mission where there are no passengers. A weighting is provided by the user to determine how often the missions are full of passengers vs. how often the flights are empty. The objective function is based on combining the fuel-burn values from both missions and the optimizers objective is to minimize the weighted fuel-burn. Other objectives, are possible to sepcify, but a maximum range objective is currently not supported but should be added in the future. Behind the scenes of Aviary, both aircraft are setup completely separately, with their own pre-mission, mission, and post-mission. We will need to link some design values together to ensure the aircraft \"mirror\" eachother for our example case.\n", + "\n", + "## Workflow\n", + "\n", + "The multi-mission interface is slightly modified from the standard aviary methods to provide a more streamlined method of handling inputs. A number of new methods have been added to `methods_for_level2` to support this. The standard workflow for a multi-mission problem is as follows:\n", "\n", - "To impact the structure of aviaryproblems as little as possible, after instantiation of the pre-mission, mission, and post-mission systems, the connections between those systems are created. Then those groups are then copied over into a regular openmdao problem. This enables the use all the basic aviary connection and checking functions with minimal modification. \n", + "- load aviary_values from a .csv (Future Capability)\n", + "- aviary_valuse.set_val\n", + "- merge_hirarchies\n", + "- add AviaryProblem\n", + "- {glue:md}`add_aviary_group`\n", + "- {glue:md}`build_model`\n", + "- add initial guesses for external subsystems (see test_subsystems_within_a_mission.py for example)\n", + "- {glue:md}`promote_inputs`\n", + "- {glue:md}`add_design_var_default`\n", + "- {glue:md}`add_composite_objective`\n", + "- {glue:md}`add_composite_objective_adv`\n", + "- {glue:md}`add_driver`\n", + "- {glue:md}`add_design_variables`\n", + "- {glue:md}`setup`\n", + "- {glue:md}`set_val`\n", + "- {glue:md}`set_design_range`\n", + "- {glue:md}`run_aviary_problem`\n", "\n", - "The objective function is based on combining the fuel-burn values from both missions and the optimizers objective is to minimize the weighted fuel-burn. Other objectives, like max range, have not been tested yet.\n", + "The ProblemType must be set to MULTI_MISSION otherwise many of the supporting methods will not be enabled. Currently, the {glue:md}`add_aviary_group` method only supports ingesting an aviary_values object. In the future, the capability to sparately load a .csv file and return an aviary_values object will be provided. All modifications to aviary_values must be made before calling {glue:md}`add_aviary_group` because it calls {glue:md}`load_inputs` and then {glue:md}`check_and_preprocess_inputs`, giving the user no opportunity to modify aviary values after loading. This decision was made because {glue:md}`load_inputs` actually sets some unchangable defaults in the background and the user should have the capability to change those settings before they are fixed. {glue:md}`build_model` is called next. This function could be broken out into it's four constituent methods if finer control is desired (see methods for level 2 for details). After calling {glue:md}`build_model`, initial guesses for external subsystems can then be provided since those subsystems are now loaded. Then {glue:md}`promote_inputs` is used to link key design variables between the different aircraft, ensuring that a single optimizer control is mirrored on both aircraft. {glue:md}`add_design_var_default` is a quick way to sepcify both what the optimizer is allowed to control as well as setting a default value for that control. The initial control value can still be modeifed after setup using {glue:md}`set_val` if desired. {glue:md}`add_composite_objective` and {glue:md}`add_composite_objective_adv` are two new ways that the user can specify a composite or combined objective from multiple aircraft and/or missions. For example, you could set the objective to be a combination of fuel-burn from mission1 and maintaince costs from mission2. Each of the different composite objective functions provides a slightly different way of specifying the objective. Users that know the frequency of each of their missions, which can typically be obtained by looking at the flight history of similarly sized aircraft, will find it easy to use {glue:md}`add_composite_objective_adv` to load in their mission frequencies. We then progress to standard {glue:md}`add_driver` and {glue:md}`add_design_variables` calls, followed by {glue:md}`setup` which now also automatically sets input defaults. At this point we can now use {glue:md}`set_val` to create or change any initial guesses if necessary. {glue:md}`set_design_range` is then used to set the design range for each aircraft to a similar value, ensuring subsystems like avionics are mirrored between the two aircraft. It does this by looking through the phase_info of each model and taking the largest one. Lastly, the problem is run using {glue:md}`run_aviary_problem`. A report folder holding each model individually is created and available for users to inspect.\n", "\n", "## Design vs. As-Flown\n", - "To support the need to design an aircraft with a certain number of seats, but then possibly fly missions with less passengers, a distinction in the metadata was introduced between {glue:md}Aircraft.CrewPayload.Design.NUM_PASSENGERS and {glue:md}Aircraft.CrewPayload.NUM_PASSENGERS. The individual passenger classes ({glue:md}Aircraft.CrewPayload.NUM_FIRST_CLASS, {glue:md}Aircraft.CrewPayload.NUM_BUSINESS_CLASS, {glue:md}Aircraft.CrewPayload.NUM_TOURIST_CLASS) also have these distinctions. The Design values represent how many seats are available in the aircraft. Whereas the non-design values represent an as-flow value of how many passengers are on a particular flight. \n", + "To support the need to design an aircraft with a certain number of seats, but then possibly fly missions with less passengers, a distinction in the metadata was introduced between {glue:md}`Aircraft.CrewPayload.Design.NUM_PASSENGERS` and {glue:md}`Aircraft.CrewPayload.NUM_PASSENGERS`. The individual passenger classes ({glue:md}`Aircraft.CrewPayload.NUM_FIRST_CLASS`, {glue:md}`Aircraft.CrewPayload.NUM_BUSINESS_CLASS`, {glue:md}`Aircraft.CrewPayload.NUM_TOURIST_CLASS`) also have these distinctions. The Design values represent how many seats are available in the aircraft. Whereas the non-design values represent an as-flow value of how many passengers are on a particular flight. \n", "\n", - "A number of checks exist in {glue:md}`capi` to help the user in the case that incomplete as-flow or design passenger information is provided. Please review the [Multi-Mission Theory](../examples/multi_mission) for further details.\n", + "A number of checks exist in {glue:md}`check_and_preprocess_inputs` to help the user in the case that incomplete as-flow or design passenger information is provided.\n", "\n", "## Example\n", "An example of a multi-mission as well as Setup, Theory, and Results, is presented in [Multi-Mission Examples](../examples/multi_mission)." @@ -49,7 +77,7 @@ ], "metadata": { "kernelspec": { - "display_name": "base", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -63,9 +91,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.5" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/off_design_missions.ipynb b/aviary/docs/user_guide/off_design_missions.ipynb index 3798fe65d4..2b4075e92c 100644 --- a/aviary/docs/user_guide/off_design_missions.ipynb +++ b/aviary/docs/user_guide/off_design_missions.ipynb @@ -1,5 +1,67 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.api import Settings\n", + "from aviary.utils.doctape import glue_variable, check_value\n", + "\n", + "str_problem_type = Settings.PROBLEM_TYPE\n", + "str_sizing = av.ProblemType.SIZING.value\n", + "str_alternate = av.ProblemType.ALTERNATE.value\n", + "str_fallout = av.ProblemType.FALLOUT.value\n", + "\n", + "\n", + "str_alternate_snippet = f'```\\n{str_problem_type}, {str_alternate}\\n```'\n", + "glue_variable('alternate_snippet', str_alternate_snippet, md_code=False)\n", + "\n", + "fallout_snippet = f'```\\n{str_problem_type}, {str_fallout}\\n```'\n", + "glue_variable('fallout_snippet', fallout_snippet, md_code=False)\n", + "\n", + "check_value(av.EquationsOfMotion.HEIGHT_ENERGY.value, 'height_energy')\n", + "check_value(av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value, '2DOF')\n", + "\n", + "\n", + "HEIGHT_ENERGY = av.EquationsOfMotion.HEIGHT_ENERGY\n", + "glue_variable('height_energy', HEIGHT_ENERGY.name, md_code=True)\n", + "TWO_DEGREES_OF_FREEDOM = av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM\n", + "glue_variable('2DOF', TWO_DEGREES_OF_FREEDOM.name, md_code=True)\n", + "\n", + "file_path = av.get_path('examples/run_off_design_example.py').relative_to(av.top_dir.parent)\n", + "glue_variable('run_off_design_example.py', file_path, md_code=True)\n", + "\n", + "file_path2 = av.get_path('examples/run_level2_example.py').relative_to(av.top_dir.parent)\n", + "glue_variable('run_level2_example.py', file_path2, md_code=True)\n", + "\n", + "glue_variable('num_first', av.Aircraft.CrewPayload.NUM_FIRST_CLASS, md_code=False)\n", + "glue_variable('num_business', av.Aircraft.CrewPayload.NUM_BUSINESS_CLASS, md_code=False)\n", + "glue_variable('num_tourist', av.Aircraft.CrewPayload.NUM_TOURIST_CLASS, md_code=False)\n", + "glue_variable('num_pax', av.Aircraft.CrewPayload.NUM_PASSENGERS, md_code=False)\n", + "glue_variable('wing_cargo', av.Aircraft.CrewPayload.WING_CARGO, md_code=False)\n", + "glue_variable('misc_cargo', av.Aircraft.CrewPayload.MISC_CARGO, md_code=False)\n", + "glue_variable('cargo_mass', av.Aircraft.CrewPayload.CARGO_MASS, md_code=False)\n", + "\n", + "glue_variable('operating_mass', av.Mission.Summary.OPERATING_MASS, md_code=True)\n", + "glue_variable('empty_mass', av.Aircraft.Design.EMPTY_MASS, md_code=True)\n", + "glue_variable('cargo_container_mass', av.Aircraft.CrewPayload.CARGO_CONTAINER_MASS, md_code=True)\n", + "glue_variable('design_gross_mass', av.Mission.Design.GROSS_MASS, md_code=True)\n", + "\n", + "file_path3 = av.get_path('models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv')\n", + "\n", + "glue_variable('objectives_fuel', av.Mission.Objectives.FUEL, md_code=True)\n", + "glue_variable('objectives_range', av.Mission.Objectives.RANGE, md_code=True)\n", + "glue_variable('summary_gross_mass', av.Mission.Summary.GROSS_MASS, md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -8,33 +70,282 @@ "\n", "## Overview\n", "\n", + "Off-design missions are missions that take an already designed and sized aircraft and attempt to run different mission trajectories, different payload quantities, or both.\n", + "\n", "Off-design missions are enabled for the following mission types:\n", "\n", - "* height_energy (collocation) (completed)\n", - "* 2DOF (collocation) (complete)\n", - "* 2DOF (shooting) (future work)\n", - "* height_energy (shooting) (future work)\n", + "* {glue:md}`height_energy`\n", + "* {glue:md}`2DOF`\n", + "\n", + "There are currently two types of off-design missions supported in Aviary:\n", + "\n", + "- Alternate Missions: the mission's target range and aircraft payload mass are inputs and the fuel mass required is solved for. \n", + "- Fallout Missions: the aircraft payload and gross mass as inputs and the range of the aircraft is solved for. \n", + "\n", + "The off-design missions correspond to the different problem types that can have differing objectives which are discussed in detail in [Level 2](../getting_started/onboarding_level2).\n", + "The problem type determines what the optimizer can control to find a valid solution. \n", + "- Sizing Missions allow the optimizer to control both the {glue:md}`summary_gross_mass` and {glue:md}`design_gross_mass` for the given mission and objective. \n", + "- Alternate Missions allow the optimizer to only control the {glue:md}`summary_gross_mass` for the mission.\n", + "- Fallout Missions don't allow the optimizer to control either {glue:md}`summary_gross_mass` or {glue:md}`design_gross_mass` but allows the optimizer to extend the range until the summary matches the design.\n", + "\n", + "There are currently 3 different methods for running an off-design mission within Aviary. \n", "\n", - "An off-design mission can be created either by directly entering the parameters of the sized aircraft or by using the built-in functionality to run an off-design in the same script as the sizing mission.\n", - "There are currently two types of off-design missions supported in Aviary; alternate and fallout.\n", - "For an alternate mission, the target range of the mission and the payload mass are specified and the fuel mass required is solved for.\n", - "Fallout missions meanwhile take the payload and fuel masses as inputs and determine the range of the aircraft.\n", - "To create a simple off-design mission, take your input deck and add the line `settings:problem_type, fallout` or `settings:problem_type, alternate`.\n", + "The first method is to take the input deck of an already sized aircraft and change its problem type to either `fallout` or `alternate`. \n", "\n", "```{note}\n", - "You may need to revise some of the values in your input deck for the off-design mission.\n", + "The user may need to revise some of the values in their input deck for the off-design mission.\n", "Since the aircraft is not re-designed, it is assumed that provided inputs constitute a valid aircraft.\n", "```\n", + "The second method is to run off-design missions in the same script used to solve the design mission.\n", + "An example of this is shown in {glue:md}`run_off_design_example.py`.\n", + "\n", + "The third method is to run a sizing mission to design the aircraft, save the sizing information to a JSON file, then load the off-design mission in another script. \n", + "\n", + "```{note}\n", + "If the sizing mission did not converge to a valid aircraft design, any off-design analysis will be invalid even if the off-design missions themselves converged.\n", + "Therefore the validity of off-design analysis depends entirely on the validity of its source sizing mission.\n", + "```\n", + "\n", + "## Off-Design from an already sized aircraft. \n", + "\n", + "The first method of running an off-design mission requires that the user has an input deck of a fully sized and valid aircraft.\n", + "ex: `aircraft_for_bench_FwFm.csv`.\n", + "This is done by adding one of the following lines to its csv file:\n", + "\n", + "{glue:md}`fallout_snippet`\n", + "\n", + "or\n", + "\n", + "{glue:md}`alternate_snippet`\n", + "\n", + "Once the problem type is specified, run Aviary as you would any other mission. \n", + "\n", + "```{note}\n", + "Off-design missions are run with the assumption that the sizing mission's {glue:md}`design_gross_mass` is the maximum structural mass the aircraft can support. \n", + "However, Aviary is capable of running a converging off-design missions with {glue:md}`summary_gross_mass` that exceed that structural constraint. \n", + "Therefore the user should check the {glue:md}`summary_gross_mass` of the off-design to ensure the optimization is valid. \n", + "```\n", + "## Sizing & off-design in the same script.\n", + "\n", + "Firstly, we highly recommend users first read through and understand the [Level 2](../getting_started/onboarding_level2) onboarding guide before attempting an off-design mission. \n", + "\n", + "This is the Aviary Team's preferred method for running off-design missions as it allows the user to interrogate both the sizing and off-design missions together in the same script.\n", + "Off-design functionality within the script involves first running a sizing mission then transferring the sizing parameters via JSON file into a new `AviaryProblem()` object.\n", + "User input payload, `phase_info`, and `mission_mass` or `mission_range` is parsed to the new problem object and the problem is executed within the level 2 method. \n", + "\n", + "Running an off-design mission first requires a sizing mission setup similar to {glue:md}`run_level2_example.py` then the addition of `save_sizing_to_json()` to the `AviaryProblem`.\n", + "- `prob.save_sizing_to_json(json_filename = 'sizing_problem.json')` \n", + "\n", + "The `save_sizing_to_json()` argument saves the sizing mission's parameters to a JSON filename of the user's choosing where `sizing_problem.json` is the default filename.\n", + "\n", + "To run a fallout or alternate mission these level 2 functions can be added to the end of the script.\n", + "\n", + "- `prob.fallout_mission(json_filename = 'sizing_problem.json')` \n", + "\n", + "- `prob.alternate_mission(json_filename = 'sizing_problem.json')`\n", + "\n", + "If an argument is left empty Aviary will assume it is the same as that of the sizing mission. \n", + "Both off-design mission types take payload as an input parameter. \n", + "The mission's payload is split up into the 3 passenger classes and the 2 cargo loadings. \n", + "The respective Aviary variables are then updated with the user's off-design passenger and cargo quantities.\n", + "\n", + "```{note} \n", + "As of v0.9.10 Aviary's off-design capabilities do not allow missions to be run with 0 passengers, so a minimum of 1 passenger must be specified. \n", + "This is a known bug and is currently being investigated. \n", + "```\n", + "\n", + "| `Inputs` | `Aviary Variable Name` | `Description`\n", + "| ----------------- | ----------------------------- | ----------------------------------------- |\n", + "| `num_first` | {glue:md}`num_first` | The number of first class passengers |\n", + "| `num_business` | {glue:md}`num_business` | The number of business class passengers |\n", + "| `num_tourist` | {glue:md}`num_tourist` | The number of tourist class passengers |\n", + "| `num_pax` | {glue:md}`num_pax` | Total number of passengers |\n", + "| `wing_cargo` | {glue:md}`wing_cargo` | Cargo carried in wing |\n", + "| `misc_cargo` | {glue:md}`misc_cargo` | Additional cargo carried in fuselage |\n", + "| `cargo_mass` | {glue:md}`cargo_mass` | Total mass of as-flown cargo |\n", + "| `phase_info` | phase_info | The mission trajectory for the aircraft |\n", + "| `mission_range` | `target_range` | The target range for alternate missions |\n", + "| `mission_mass` | {glue:md}`summary_gross_mass` | The mission mass for fallout missions |\n", + "\n", + "\n", + "```{note} \n", + "Off-design missions **cannot** be run with more passengers than the original sizing mission. \n", + "For example, if {glue:md}`num_first` within the Aviary inputs csv was set to 3, an off-design mission cannot be run where `num_first = 8` as the cabin for first class was sized for precisely 3 passengers.\n", + "```\n", + "\n", + "The `phase_info` argument allows the user to specify a different phase information for an off-design mission trajectory, more information can be found in [The `phase_info` Format](phase_info).\n", + "This can be due to the off-design mission requiring a different trajectory shape or phase durations than the sizing mission. \n", + "For example, an aircraft sized for long-range cruise might need its climb and descent profiles modified to operate on shorter routes. \n", + "\n", + "```{note}\n", + "In cases where passengers or cargo are changed and the user has not specified a {glue:md}`cargo_container_mass` in the Aviary input deck, off-design missions recalculates it in the off-design mission.\n", + "It is the only parameter within the operating mass that gets recalculated between off-design and sizing.\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "\n", + "\"\"\"\n", + "This is an example of a sizing mission and alternate mission being run in the same script. \n", + "This is done with \n", + "\"\"\"\n", + "import aviary.api as av\n", + "\n", + "# inputs that run_aviary() requires\n", + "aircraft_data = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv'\n", + "optimizer = 'SLSQP'\n", + "phase_info = av.default_height_energy_phase_info\n", + "max_iter = 15\n", + "\n", + "# Set up and run avairy problem.\n", + "prob = av.AviaryProblem(verbosity=0)\n", + "\n", + "# This is the default FwFm (Flops weights Flops mission) aircraft.\n", + "prob.load_inputs(aircraft_data, phase_info)\n", + "\n", + "prob.check_and_preprocess_inputs()\n", + "\n", + "prob.add_pre_mission_systems()\n", + "\n", + "prob.add_phases()\n", + "\n", + "prob.add_post_mission_systems()\n", + "\n", + "prob.link_phases()\n", + "\n", + "prob.add_driver(optimizer, max_iter=max_iter)\n", + "\n", + "prob.add_design_variables()\n", + "\n", + "prob.add_objective()\n", + "\n", + "prob.setup()\n", + "\n", + "prob.set_initial_guesses()\n", + "\n", + "prob.run_aviary_problem()\n", + "\n", + "# save the sizing mission to a JSON file\n", + "prob.save_sizing_to_json(json_filename='off_design_documentation_example.json')\n", + "\n", + "# initialize alternate mission flying a much shorter distance.\n", + "# if payload values are unspecified, off-design will uses the values from the sizing mission.\n", + "# the mission_range argument is much shorter than the sizing mission's 1906 NM range.\n", + "prob.alternate_mission(\n", + " json_filename='off_design_documentation_example.json',\n", + " num_first=0,\n", + " num_business=0,\n", + " num_tourist=50,\n", + " num_pax=50,\n", + " wing_cargo=0,\n", + " misc_cargo=0,\n", + " cargo_mass=0,\n", + " mission_range=1000,\n", + " phase_info=phase_info,\n", + " verbosity=0,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Off-design missions separately\n", + "\n", + "The third method in running an off-design mission requires saving the sizing information as a JSON file using `save_sizing_to_json()` then calls the JSON file into an off-design mission in another script.\n", + "This method allows for off-design missions to be run without re-executing the sizing mission every time. \n", + "Once saved, the third method works identically to the second method except that the user must manually run the `_load_off_design()` function to create a new Aviary problem. \n", + "\n", "\n", - "From there, the mission may be run as before." + "The `_load_off_design()` function then requires the `json_filename` input along with 3 additional problem definition parameters `problem_type`, `equations_of_motion`, and `mass_method`. \n", + "Once defined, the `_load_off_design()` function essentially replaces the `load_inputs()` step of a standard level 2 problem. \n", + "The user can then adjust payload quantities and `mission_range`/`mission_gross_mass` then complete the level 2 script as shown below. \n", + "\n", + "- `problem_type`: Determines which type of off-design analysis the user would like to run. (alternate or fallout)\n", + "- `equations_of_motion`: Determines the type of trajectory calculations the user is running. ({glue:md}`height_energy` or {glue:md}`2DOF`)\n", + "- `mass_method`: Specifies how mass calculations are handled (FLOPS or GASP)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "\n", + "\"\"\"\n", + "This is an example of running off-design mission directly form a saved sized aircraft JSON file\n", + "Note: If there were external subsystems in the original sized aircraft model \n", + "these will NOT be transferred (since these are not saved in the JSON file).\n", + "\"\"\"\n", + "\n", + "from aviary.interface.methods_for_level2 import _load_off_design\n", + "from aviary.variable_info.enums import LegacyCode\n", + "import aviary.api as av\n", + "\n", + "optimizer = 'SLSQP'\n", + "phase_info = av.default_height_energy_phase_info\n", + "max_iter = 15\n", + "# Load aircraft and options data from provided sources\n", + "\n", + "# To run an alternate mission, we need the sized aircraft JSON file from the sizing mission.\n", + "# Set ProblemType to ALTERNATE, and specify the mission range and payload mass.\n", + "# mission_gross_mass does nothing).\n", + "\n", + "# Use specific _load_off_design function to define the off-design mission.\n", + "prob_alternate = _load_off_design(\n", + " json_filename='off_design_documentation_example.json',\n", + " problem_type=av.ProblemType.ALTERNATE,\n", + " equations_of_motion=av.EquationsOfMotion.HEIGHT_ENERGY,\n", + " mass_method=LegacyCode.FLOPS,\n", + " phase_info=phase_info,\n", + " num_first=0,\n", + " num_business=0,\n", + " num_tourist=50,\n", + " num_pax=50,\n", + " wing_cargo=0,\n", + " misc_cargo=0,\n", + " cargo_mass=0,\n", + " mission_range=1000,\n", + " verbosity=0,\n", + ")\n", + "\n", + "# Run off-design mission the same way as any Level 2 aviary problem.\n", + "prob_alternate.check_and_preprocess_inputs()\n", + "\n", + "prob_alternate.add_pre_mission_systems()\n", + "\n", + "prob_alternate.add_phases()\n", + "\n", + "prob_alternate.add_post_mission_systems()\n", + "\n", + "prob_alternate.link_phases()\n", + "\n", + "prob_alternate.add_driver(optimizer=optimizer, max_iter=max_iter)\n", + "\n", + "prob_alternate.add_design_variables()\n", + "\n", + "prob_alternate.add_objective()\n", + "\n", + "prob_alternate.setup()\n", + "\n", + "prob_alternate.set_initial_guesses()\n", + "\n", + "prob_alternate.run_aviary_problem()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "You may also run multiple off-design missions in the same script used to solve the design mission.\n", - "An examples of this is shown in `run_off_design_example.py`." + "##" ] }, { @@ -48,16 +359,27 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.doctape import check_contains\n", - "import aviary.api as av\n", "import os\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import check_contains\n", "\n", + "# make sure off_design_example.py exists in aviary/examples folder\n", "off_design_examples = av.get_path(os.path.join('examples'))\n", "check_contains(\n", " ('run_off_design_example.py'),\n", " os.listdir(off_design_examples),\n", - " error_string=\"{var} not in \"+str(off_design_examples),\n", - " error_type=FileNotFoundError)" + " error_string='{var} not in ' + str(off_design_examples),\n", + " error_type=FileNotFoundError,\n", + ")\n", + "\n", + "# make sure run_level2_example.py exists in aviary/examples folder\n", + "run_level2_examples = av.get_path(os.path.join('examples'))\n", + "check_contains(\n", + " ('run_level2_example.py'),\n", + " os.listdir(run_level2_examples),\n", + " error_string='{var} not in ' + str(run_level2_examples),\n", + " error_type=FileNotFoundError,\n", + ")" ] } ], @@ -77,9 +399,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.0" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/payload_range_functionality.ipynb b/aviary/docs/user_guide/payload_range_functionality.ipynb new file mode 100644 index 0000000000..112e1fdb44 --- /dev/null +++ b/aviary/docs/user_guide/payload_range_functionality.ipynb @@ -0,0 +1,130 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.api import Settings\n", + "from aviary.utils.doctape import glue_variable, check_value\n", + "\n", + "HEIGHT_ENERGY = av.EquationsOfMotion.HEIGHT_ENERGY\n", + "glue_variable('height_energy', HEIGHT_ENERGY.name, md_code=True)\n", + "glue_variable('2DOF', av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.name, md_code=True)\n", + "\n", + "PAYLOAD_RANGE = av.Settings.PAYLOAD_RANGE\n", + "\n", + "str_alternate_snippet = f'```\\n{PAYLOAD_RANGE}, {True}\\n```'\n", + "glue_variable('payload_range_toggle', str_alternate_snippet, md_code=True)\n", + "glue_variable('payload_range', av.Settings.PAYLOAD_RANGE, md_code=True)\n", + "\n", + "\n", + "glue_variable('operating_mass', av.Mission.Summary.OPERATING_MASS, md_code=True)\n", + "glue_variable('total_payload_mass', av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, md_code=True)\n", + "glue_variable('design_gross_mass', av.Mission.Design.GROSS_MASS, md_code=True)\n", + "glue_variable('total_fuel_capacity', av.Aircraft.Fuel.TOTAL_CAPACITY, md_code=True)\n", + "\n", + "file_path3 = av.get_path('models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv')\n", + "\n", + "glue_variable('objectives_fuel', av.Mission.Objectives.FUEL, md_code=True)\n", + "glue_variable('objectives_range', av.Mission.Objectives.RANGE, md_code=True)\n", + "glue_variable('summary_gross_mass', av.Mission.Summary.GROSS_MASS, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Payload Range Functionality. \n", + "\n", + "## Overview\n", + "\n", + "Aviary has the capability to generate payload range diagrams for models utilizing the {glue:md}`height_energy` equations of motion. Support for the {glue:md}`2DOF` equations of motion is planned in a future release.\n", + "\n", + "A payload-range diagram is an aircraft performance visualization that illustrates the trade-off between how much mass the aircraft can carry in terms of passengers and cargo (payload) vs how far it can fly (range).\n", + "The payload-range shows 3 different points:\n", + "- **Maximum Payload Point (\"Design Range\")**: The range the aircraft can fly with maximum payload mass and fuel mass up to the maximum gross mass. This range is typically the design point of the aircraft (the \"sizing\" mission).\n", + "- **Maximum Fuel Point (\"Max Economic Range\")**: The range the aircraft can fly at maximum fuel capacity and payload mass up to maximum gross mass. This is the furthest range the aircraft can fly at its maximum gross mass.\n", + "- **Maximum Range Point (\"Ferry Range\")**: The range the aircraft can fly at maximum fuel capacity and zero payload. This is the furthest the aircraft can fly. \n", + "\n", + "![Payload Range Envelope Example](images/payload-range-envelope.png)\n", + "\n", + "After a successful sizing mission (**Maximum Payload Point**) the payload-range function calculates the required aircraft loading conditions and runs an off-design fallout mission for the \"Max Economic\" \"Ferry\" range points.\n", + "\n", + "When a user requests for a payload-range diagram to be generated, the additional points are run using the design mission's phase info. It is assumed that this `phase_info` contains a cruise phase named `cruise`, and Aviary will automatically adjust the `time_duration_bound` of the cruise phase to account for the longer off-design missions.\n", + "\n", + "```{note}\n", + "We highly recommend that users first read through [Off Design Missions](off_design_missions) to understand the underlying mechanics of how Aviary runs off-design missions.\n", + "```\n", + "\n", + "Each point is configured using the following methods:\n", + "- **Maximum Payload Point**: The results of the sizing mission are used to plot this point.\n", + "\n", + "- **Maximum Fuel Point**: The aircraft's mission fuel is assumed to match {glue:md}`total_fuel_capacity`. The available payload is computed as {glue:md}`design_gross_mass` minus {glue:md}`operating_mass` minus {glue:md}`total_fuel_capacity`. Therefore the aircraft's mission mass is equal to its design gross mass.\n", + "\n", + "- **Maximum Range Point**: The aircraft is flown at a gross mass equal to {glue:md}`design_gross_mass` plus {glue:md}`total_fuel_capacity`.\n", + "\n", + "```{note}\n", + "There is an edge case where an aircraft's fuel capacity could exceed its design gross mass if fully fueled to that capacity. In this case, at the maximum fuel point the aircraft is filled with fuel up to its design gross mass. Because there is no room for additional payload, this point is also equivalent to the maximum range point. Aviary will not run that last point as it is redundant, and instead re-use the results of the maximum fuel point for building the payload-range data table.\n", + "```\n", + "\n", + "## Outputs\n", + "After running all of the points of the payload-range diagram, a table of gross mass vs. range for each point is saved in a filed called `payload_range_data.csv`. This file is placed in the reports folder for that run." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Running a payload/range analysis \n", + "There are currently two methods to run a payload-range analysis. \n", + "The first method is to set {glue:md}`payload_range` to True in your csv input file or AviaryValues input (if using the Level 2 interface).\n", + "\n", + "```{note}\n", + "Setting this flag will result in Aviary running a payload-range analysis every time that specific aircraft model is sized. \n", + "```\n", + "\n", + "### Method Call\n", + "The second way to generate the payload-range diagram is to manually call the `run_payload_range()` method after running a sizing mission. If the payload range points run successfully, then the method returns a tuple containing the AviaryProblems used to create the maximum economic range and ferry range points.\n", + "\n", + "`(max_econ_range_prob, ferry_range_prob) = prob.run_payload_range()`\n", + "\n", + "## Output and visualization. \n", + "The data for the payload-range points can be found in `payload_range_data.csv`, located within the main problem's reports folder. \n", + "The information is also visualized within the `Payload/Range Diagram` tab in the Aviary dashboard for the sizing mission. \n", + "\n", + "```{note}\n", + "Aviary will only save the results payload/range analysis (and therefore only plot the diagram in the dashboard) if the sizing and two off-design points converged to a valid solution.\n", + "```" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/aviary/docs/user_guide/phase_info.ipynb b/aviary/docs/user_guide/phase_info.ipynb new file mode 100644 index 0000000000..769f8ba9bc --- /dev/null +++ b/aviary/docs/user_guide/phase_info.ipynb @@ -0,0 +1,201 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.mission.flight_phase_builder import FlightPhaseOptions\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "opts = FlightPhaseOptions()\n", + "for key in opts:\n", + " glue_variable(key, md_code=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The `phase_info` Format\n", + "\n", + "## Overview\n", + "\n", + "Aviary uses a nested python dictionary to define and control all aspects of the mission and its phases. Understanding this format is necessary if you want to modify existing missions or design your own.\n", + "\n", + "The top level of the phase_info contains a name string and a sub-dictionary for each phase in the mission. Users are free to choose any valid python name for their phases (valid characters are upper/lower case letters, numbers, and underscores.) In addition, there are two default phases \"pre_mission\" and \"post_mission\". These contain any settings that pertain to the pre_mission, which is any calculation that occurs before the mission runs, and the post_mission, which is any calculation that occurs after the mission runs.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "phase_info = {\n", + " 'pre_mission': {},\n", + " 'climb1': {},\n", + " 'climb2': {},\n", + " 'cruise': {},\n", + " 'descent': {},\n", + " 'post_mission': {},\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the order is important, so 'pre_mission' should be first, followed by phases in chronological order, terminated by 'post_mission'.\n", + "\n", + "## Phase Options\n", + "\n", + "Each phase has its own options that are organized like this:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "phase_info['climb1'] = {\n", + " 'subsystem_options': {},\n", + " 'user_options': {},\n", + " 'initial_conditions': {},\n", + " 'external_subsystems': [],\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The 'subsystem_options' dictionary contains settings for core subsystems, primarily the core aerodynamics calculations.\n", + "The 'user_options' dictionary includes all settings that define the phase and its boundary conditions.\n", + "The 'initial_conditions' dictionary allows you to set initial values for any variables thate are under control of the optimizer, including states, optimized controls, and time.\n", + "Finally, 'external_subsystems' is a list that contains all of the external builder objects.\n", + "\n", + "## Subsystem Options\n", + "\n", + "The subsystem options for core aerodynamics are outlined in [Externally Computed Polars](external_aero.ipynb).\n", + "\n", + "## User Options\n", + "\n", + "An overview of user options for a Height Energy phase is given in the [Level 1 Introduction](../getting_started/onboarding_level1.ipynb), and an example for a cruise phase is shown in the [Level 2 Introduction](../getting_started/onboarding_level2.ipynb). These are a good starting points for understanding how these options are specified. The Aviary trajectory is constructed using phase builders. In general, each option is a name, value pair where the names are intended to follow a specific pattern. In particular, when the option name includes a variable name, that name goes first. For example, the initial and final values for constraints on altitude would be \"altitude_initial\" and \"altitude_final\". Each value could be a number, tuple/list, array, or a boolean as needed. The user options format supports (and enforces) the inclusion of an OpenMDAO unit string when specifying any quantity that has a unit. These take the format \"(500, 's')\". If an option requires units and takes multiple value, the format \"((300.0, 900.0), 's')\" is used. Some variables (such as Mach) require an explicit \"unitless\" as the unit.\n", + "\n", + "Each builder has its own options that are tied to the equations of motion that it models. Thus, since the two-degree-of-freedom (2DOF) equations have different states and controls than the height energy equations, the phase_infos have some user options that are different. The following section describes the general patterns that apply to the phases that are included in Aviary. Note that, at present, the height energy phases fully adhere to this standard, while the '2DOF' phases are still being converted.\n", + "\n", + "### General phase settings\n", + "\n", + "- **{glue:md}`num_segments`**: The number of segments in the dymos transcription.\n", + "\n", + "- **{glue:md}`order`**: The order of polynomials for the dymos transcription.\n", + "\n", + "- **{glue:md}`throttle_enforcement`**: Enforce throttle as a path_constraint (default), boundary_constraint, a control (which can be optimized or set to a fixed value), or a solver bound (not recommended).\n", + "\n", + "- **{glue:md}`throttle_allocation`**: How to allocate throttles for multi-engine, can be [‘fixed’, ‘static’, ‘dynamic’].\n", + "\n", + "- **{glue:md}`no_climb`**: Set to True to prevent the aircraft from climbing during the phase. This option can be used to prevent unexpected climb during a descent phase.\n", + "\n", + "- **{glue:md}`no_descent`**: Set to True to prevent the aircraft from descending during the phase. This can be used to prevent unexpected descent during a climb phase.\n", + "\n", + "### Specialized phase settings\n", + "\n", + "- **{glue:md}`reserve`**: When True, this is a reserve phase. These phases should be after your flight phases.\n", + "\n", + "- **{glue:md}`ground_roll`**: When True, restrict the problem to the ground plane. This will remove certain states/controls, and is only used in takeoff and landing phases.\n", + "\n", + "- **{glue:md}`required_available_climb_rate`**: Adds a lower bound path constraint on altitude_rate_max, which is the maximum rate that the aircraft could climb at any point in the phase.\n", + "\n", + "- **{glue:md}`target_distance`**: Total mission distance constraint. This should be set in the final flight phase only.\n", + "\n", + "### State variables\n", + "\n", + "In a height energy phase, the states are mass and distance. In a two degree of freedom phase, the states also include altitude and velocity.\n", + "\n", + "- **{glue:md}`mass_initial`**: Mass at the start of the phase. When unspecified, the optimizer controls the value. When specified, a constraint is created on the initial mass.\n", + "\n", + "- **{glue:md}`mass_final`**: Mass at the end of the phase. When unspecified, the optimizer controls the value. When specified, a constraint is created on the final mass.\n", + "\n", + "- **{glue:md}`mass_bounds`**: Tuple of upper and lower bounds for all values of mass in the phase. The default of None for either means that bound will not be declared.\n", + "\n", + "- **{glue:md}`mass_ref`**: Multiplicative scale factor \"ref\" for mass. Default is 1.0\n", + "\n", + "- **{glue:md}`mass_ref0`**: Additive scale factor \"ref0\" for mass. Default is None.\n", + "\n", + "- **{glue:md}`mass_defect_ref`**: Multiplicative scale factor \"ref\" for defect constraint. Deafult is None, which means the ref and defect_ref are the same.\n", + "\n", + "- **{glue:md}`mass_solve_segments`**: When True, a solver will be used to converge the mass collocation defects within a segment. Note that the state continuity defects between segements will still be handled by the optimizer.\n", + "\n", + "### Controls\n", + "\n", + "In a height energy phase, the controls are mach and altitude. In a two degree of freedom phase, the controls are throttle or angle of attack depending on the phase.\n", + "\n", + "- **{glue:md}`altitude_optimize`**: When True, the optimizer will set this value. When False, the initial value for all nodes can be set in the initial_conditions section of the phase.\n", + "\n", + "- **{glue:md}`altitude_initial`**: Altitude at the start of the phase. If altitude_optimize is True, specifying this will create a constraint. Otherwise, it serves as an initial value for the first point. When unspecified, the linkage constraint with the upstream phase will drive this value if altitude_optimize is True.\n", + "\n", + "- **{glue:md}`altitude_final`**: Altitude at the end of the phase. If altitude_optimize is True, specifying this will create a constraint. Otherwise, it serves as an initial value for the first point. When unspecified, the linkage constraint with the downstream phase will drive this value if altitude_optimize is True.\n", + "\n", + "- **{glue:md}`altitude_bounds`**: Tuple of upper and lower bounds for all values of altitude in the phase. The default of None for either means that bound will not be declared.\n", + "\n", + "- **{glue:md}`altitude_ref`**: Multiplicative scale factor \"ref\" for altitude. Default is 1.0\n", + "\n", + "- **{glue:md}`altitude_ref0`**: Additive scale factor \"ref0\" for altitude. Default is None.\n", + "\n", + "- **{glue:md}`altitude_polynomial_order`**: The order of polynomials for interpolation in the transcription. Default is None, which does not use a polynomial.\n", + "\n", + "### Time\n", + "- **{glue:md}`time_initial`**: Value of \"time\" at the start of the phase. When unspecified, the value is determined by the optimizer.\n", + "\n", + "- **{glue:md}`time_duration`**: Duration of the phase. When unspecified, the value is determined by the optimizer.\n", + "\n", + "- **{glue:md}`time_initial_bounds`**: Upper and lower bounds for time_initial. Ignored if \"time_initial\" is specified. \n", + "\n", + "- **{glue:md}`time_duration_bounds`**: Upper and lower bounds for time_duration. \n", + "\n", + "- **{glue:md}`time_initial_ref`**: Multiplicative scale factor \"ref\" for time_initial. Default is 1.0\n", + "\n", + "- **{glue:md}`time_duration_ref`**: Additive scale factor \"ref\" for time_duration. Default is None.\n", + "\n", + "A full description of every user option in the phase_info for each of Aviary's phase builders is given in the [Complete phase_info Reference.](phase_info_detailed.ipynb)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pre and Post mission Options\n", + "TODO: Coming Soon." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/aviary/docs/user_guide/phase_info_conversion.ipynb b/aviary/docs/user_guide/phase_info_conversion.ipynb new file mode 100644 index 0000000000..2d81ee35a2 --- /dev/null +++ b/aviary/docs/user_guide/phase_info_conversion.ipynb @@ -0,0 +1,47 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Converting from legacy `phase_info` user options\n", + "\n", + "To be completed.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/aviary/docs/user_guide/phase_info_detailed.ipynb b/aviary/docs/user_guide/phase_info_detailed.ipynb new file mode 100644 index 0000000000..b8b06363e2 --- /dev/null +++ b/aviary/docs/user_guide/phase_info_detailed.ipynb @@ -0,0 +1,193 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import openmdao.api as om" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Complete `phase_info` user options reference for all Aviary EquationsOfMotion\n", + "\n", + "## HEIGHT_ENERGY\n", + "\n", + "The height energy phase_info has been converted to the new system." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.flight_phase_builder.FlightPhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## SOLVED_2DOF\n", + "\n", + "The solved 2dof phase_info has not been converted completely to the new system." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.twodof_phase.TwoDOFPhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## TWO_DEGREES_OF_FREEDOM\n", + "\n", + "The two degree of freedom phase_info has not been converted completely to the new system.\n", + "\n", + "### AccelPhase\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.accel_phase.AccelPhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### AscentPhase\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.ascent_phase.AscentPhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ClimbPhase\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.climb_phase.ClimbPhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### CruisePhase\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.cruise_phase.CruisePhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### DescentPhase\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.descent_phase.DescentPhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### GroundrollPhase\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.groundroll_phase.GroundrollPhaseOptions')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### RotationPhase\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "om.show_options_table('aviary.mission.gasp_based.phases.rotation_phase.RotationPhaseOptions')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/aviary/docs/user_guide/postprocessing_and_visualizing_results.ipynb b/aviary/docs/user_guide/postprocessing_and_visualizing_results.ipynb index a24c03ef19..5bd5c18fc6 100644 --- a/aviary/docs/user_guide/postprocessing_and_visualizing_results.ipynb +++ b/aviary/docs/user_guide/postprocessing_and_visualizing_results.ipynb @@ -1,5 +1,40 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", + "from aviary.utils.doctape import glue_class_functions, glue_function_arguments, glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "# make sure that the path exists.\n", + "folder = av.get_path('examples')\n", + "examples_dir = folder.relative_to(av.top_dir.parent)\n", + "glue_variable(examples_dir, md_code=True)\n", + "\n", + "str_level2_example = 'run_level2_example.py'\n", + "level2_example = av.get_path(folder / str_level2_example)\n", + "examples_dir = level2_example.relative_to(av.top_dir.parent)\n", + "glue_variable(examples_dir.name, md_code=True)\n", + "glue_variable(examples_dir.stem + '.zip', md_code=True)\n", + "\n", + "# Get all functions of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars)\n", + "\n", + "# Retrieve all arguments from a function\n", + "glue_function_arguments(AviaryProblem.run_aviary_problem, current_glued_vars, md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -16,31 +51,31 @@ "\n", "| **Section** | **File** | **Location** |\n", "|--------------|-----------------------------------------------|--------------------------------------------------------------------------------|\n", - "| Model | Inputs | ./reports/*name_of_run_script*/inputs.html |\n", - "| Model | Debug Input List | ./input_list.txt |\n", - "| Model | Debug Input List | ./output_list.txt |\n", - "| Model | N2 | ./reports/*name_of_run_script*/n2.html |\n", - "| Model | Trajectory Linkage Report | ./reports/*name_of_run_script*/traj_linkage_report.html |\n", - "| Optimization | Driver Scaling Report | ./reports/*name_of_run_script*/driver_scaling_report.html |\n", - "| Optimization | Total Coloring Report | ./reports/*name_of_run_script*/total_coloring.html |\n", - "| Optimization | Optimization Report | ./reports/*name_of_run_script*/opt_report.html |\n", - "| Optimization | SNOPT Output (similarly for other optimizers) | ./reports/*name_of_run_script*/SNOPT_print.out |\n", - "| Optimization | Driver recording | Case Recorder file specified by `driver_recorder` command option |\n", - "| Results | Trajectory Results Report | ./reports/*name_of_run_script*/traj_results_report.html |\n", - "| Results | Subsystem Results | ./reports/subsystems/*name_of_subsystem.md (or .html)* |\n", - "| Results | Mission Results | ./reports/subsystems/mission_summary.md |\n", - "| Results | Problem final case recording | Case Recorder file specified by `problem_recorder` command option, default is `problem_history.db` |\n", - "\n", - "As an example of the workflow for the dashboard, assume that the user has run an Aviary script, `run_aviary_example`, which records both the `Problem` final case and also all the cases of the optimization done by the `Driver`. (To record both the Problem final case and also the Driver optimization iterations, the user must make use of the `optimization_history_filename` option in the call to `run_aviary_problem`.)\n", + "| Model | Input Checks | ./*name_of_run_script*_out/reports/input_checks.md |\n", + "| Model | Inputs | ./*name_of_run_script*_out/reports/inputs.html |\n", + "| Model | Debug Input List | ./*name_of_run_script*_out/reports/input_list.txt |\n", + "| Model | Debug Input List | ./*name_of_run_script*_out/reports/output_list.txt |\n", + "| Model | N2 | ./*name_of_run_script*_out/reports/n2.html |\n", + "| Model | Trajectory Linkage Report | ./*name_of_run_script*_out/reports/traj_linkage_report.html |\n", + "| Optimization | Driver Scaling Report | ./*name_of_run_script*_out/reports/driver_scaling_report.html |\n", + "| Optimization | Total Coloring Report | ./*name_of_run_script*_out/reports/total_coloring.html |\n", + "| Optimization | Optimization Report | ./*name_of_run_script*_out/reports/opt_report.html |\n", + "| Optimization | SNOPT Output (similarly for other optimizers) | ./*name_of_run_script*_out/reports/SNOPT_print.out |\n", + "| Results | Trajectory Results Report | ./*name_of_run_script*/reports/traj_results_report.html |\n", + "| Results | Subsystem Results | ./*name_of_run_script*_out/reports/subsystems/*name_of_subsystem.md (or .html)*|\n", + "| Results | Mission Results | ./*name_of_run_script*_out/reports/subsystems/mission_summary.md |\n", + "| Results | Problem final case recording | ./*name_of_run_script*_out/problem_history.db |\n", + "\n", + "As an example of the workflow for the dashboard, assume that the user has run an Aviary script, {glue:md}`run_level2_example.py`, which records both the `Problem` final case and also all the cases of the optimization done by the [`Driver`](https://openmdao.org/newdocs/versions/latest/features/building_blocks/drivers/). The sample code can be found in {glue:md}`aviary/examples` folder. (To record both the Problem final case and also the Driver optimization iterations, the user must make use of the `verbosity` flag in the call to {glue:md}`run_aviary_problem()`.)\n", "\n", "```bash\n", - "python run_aviary_example.py\n", + "python level2_example.py\n", "```\n", "\n", - "In this example, the case recorder files are named `problem_final_case.db` and `driver_cases.db`, respectively. So after the run is completed, the user could run the dashboard using:\n", + "After the run is completed, the user can run the dashboard using:\n", "\n", "```bash\n", - "aviary dashboard run_aviary_example --problem_recorder=problem_final_case.db --driver_recorder=driver_cases.db\n", + "aviary dashboard level2_example\n", "```\n", "\n", "```{note}\n", @@ -60,26 +95,44 @@ "outputs": [], "source": [ "# Testing Cell\n", - "import tempfile\n", + "from aviary.utils.doctape import glue_actions\n", + "\n", + "glue_actions('dashboard', current_glued_vars, glue_default=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", "import os\n", + "import shutil\n", "import subprocess\n", + "import tempfile\n", + "\n", "from aviary.utils.functions import get_path\n", - "import shutil\n", - "file_name = 'run_aviary_example'\n", + "\n", + "file_name = 'run_level2_example'\n", "commands = [\n", - " 'python '+file_name+'.py',\n", - " 'aviary dashboard '+file_name+' --problem_recorder=problem_final_case.db --driver_recorder=driver_cases.db --background'\n", - " ]\n", + " 'python ' + file_name + '.py',\n", + " 'aviary dashboard ' + file_name + '--background',\n", + "]\n", "with tempfile.TemporaryDirectory() as tempdir:\n", " os.chdir(tempdir)\n", - " shutil.copy2(get_path('examples/'+file_name+'.py'), '.')\n", - " shutil.copy2(get_path('examples/example_phase_info.py'), '.')\n", + " shutil.copy2(get_path('examples/' + file_name + '.py'), '.')\n", + " shutil.copy2(get_path('models/missions/height_energy_default.py'), '.')\n", " for command in commands:\n", " try:\n", " subprocess.run(command.split(), timeout=5)\n", " except subprocess.TimeoutExpired:\n", - " # timeout used to stop dashboard server from running indefinitely \n", - " pass\n" + " # timeout used to stop dashboard server from running indefinitely\n", + " pass" ] }, { @@ -94,22 +147,20 @@ "The Problem recorder file is required for the Aircraft 3d model tab to be displayed in the dashboard.\n", "```\n", "\n", - "The `problem_recorder` and `driver_recorder` options to the dashboard command are used to indicate the file names for those recorder files, if they are not the standard values of `problem_history.db` and `driver_history.db`, respectively. If `driver_recorder` is set to the string `\"None\"`, then the driver case recorder file is ignored. This is useful if the user is not interested in seeing dashboard tabs related to driver history. If that file is large, it could unnecessarily be read and slow down the generation of the dashboard significantly.\n", - "\n", "### Saving and Sharing Dashboards\n", "\n", - "The user can also save a dashboard and share it with other users to view. The dashboard is saved as a zip file. To save a dashboard to a file, use the `--save` option. For example, \n", + "The user can also save a dashboard and share it with other users to view. The dashboard is saved as a zip file. To save a dashboard to a file, use the {glue:md}`--save` option. For example, \n", "\n", "```bash\n", - "aviary dashboard --save run_aviary_example --problem_recorder=problem_final_case.db --driver_recorder=driver_cases.db\n", + "aviary dashboard --save\n", "```\n", "\n", - "By default, the zip file is named based on the name of the problem. So in this example, the saved zip file will be named `run_aviary_example.zip`. \n", + "By default, the zip file is named based on the name of the problem. So in this example, the saved zip file will be named {glue:md}`run_level2_example.zip`.\n", "\n", - "If the user wants to save to a different file, they can provide that file name as an argument to the `save` option as in this example:\n", + "If the user wants to save to a different file, they can provide that file name as an argument to the {glue:md}`--save` option as in this example:\n", "\n", "```bash\n", - "aviary dashboard --save saved_dashboard.zip run_aviary_example --problem_recorder=problem_final_case.db --driver_recorder=driver_cases.db\n", + "aviary dashboard --save saved_dashboard.zip level2_example\n", "```\n", "\n", "In this case, the zip file will be named `saved_dashboard.zip`. \n", @@ -121,7 +172,7 @@ "```\n", "\n", "Running this form of the dashboard command will result in a new directory being created in the `reports` directory. For the example, this\n", - "directory is named `reports/saved_dashboard`. If that directory existed previously, the command will fail to prevent the existing directory from being overwritten. The user can force that overwriting to happen by using the `--force` option, as shown in this example:\n", + "directory is named `reports/saved_dashboard`. If that directory existed previously, the command will fail to prevent the existing directory from being overwritten. The user can force that overwriting to happen by using the {glue:md}`--force` option, as shown in this example:\n", "\n", "```bash\n", "aviary dashboard --force saved_dashboard.zip\n", @@ -142,12 +193,16 @@ " - This is an OpenMDAO output. After all design variables, objectives, and constraints are declared and the problem has been set up, this report presents all the design variables and constraints in all phases as well as the objectives. \n", " - It lists design variables and constraints and objectives in three different tables. It contains the following columns: name, size, indices, driver value and units, model value and units, ref, ref0, scaler, adder, etc. It contains a Jacobian Info matrix too.\n", " - More details can be found at [openmdao scaling](https://openmdao.org/newdocs/versions/latest/other_useful_docs/om_command.html#om-command-scaling).\n", + "- `input_checks.md`\n", + " - This report gives a list of all unconnected inputs in the model that have not been specificed in the prob.aviary_inputs, which includes inputs in the csv file along with any that were added to it prior to setup.\n", + " - It is split into two section: the first contains variables in the aircraft:* and mission:* hierarchy, while the second contains all of the other variables.\n", + " - The purpose of this report is to help identify variables that may have been accidentally omitted in the aircraft definition.\n", "- `inputs.html`\n", " - This is a sortable and filterable inputs report of input variables in different phases.\n", " - It contains the following columns: absolute name, source name, source is IVC, source is DV, units, shape, tags, val, min val, and max val. Here, `IVC` is the abbreviation of `IndepVarComp` and `DV` is the abbreviation of \"design variable\".\n", "- `n2.html`\n", " - This is an OpenMDAO model hierarchy and an N-squared diagram in the shape of a matrix, representing functional or physical interfaces between system elements. It can be used to systematically identify, define, tabulate, design, and analyze functional and physical interfaces.\n", - " - More information can be found at OpenMDAO's [N2 Basics](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_basics/n2_basics.html) and [N2 Details](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_details/n2_details.html). There is a tutorial on [YouTub e](https://www.youtube.com/watch?v=42VtbX6CX3A).\n", + " - More information can be found at OpenMDAO's [N2 Basics](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_basics/n2_basics.html) and [N2 Details](https://openmdao.org/newdocs/versions/latest/features/model_visualization/n2_details/n2_details.html). There is a tutorial on [YouTube](https://www.youtube.com/watch?v=42VtbX6CX3A).\n", "- `opt_report.html`\n", " - This is the OpenMDAO Optimization Report. It writes a summary of results of an optimization run.\n", " - OpenMDAO reference is at [Optimization Report](https://openmdao.org/newdocs/versions/latest/features/reports/optimization_report.html).\n", @@ -165,23 +220,7 @@ "\n", "### Database Output Files\n", "\n", - "There is an SQLite database output. By default, it is `problem_history.db`. It can be used to rerun your case though we do not detail that here. Users can write separate Python script to create user customized outputs and graphs. We will show how to use the this database to create user's customized graph in [the onboarding docs](../getting_started/onboarding)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "remove-cell" - ] - }, - "outputs": [], - "source": [ - "# Testing Cell\n", - "from aviary.utils.doctape import check_args\n", - "from aviary.interface.methods_for_level2 import AviaryProblem\n", - "check_args(AviaryProblem.run_aviary_problem,{'record_filename':\"problem_history.db\"},exact=False)" + "Aviary creates an SQLite database output called `problem_history.db`. It can be used to rerun your case, though we do not detail that here. Users can write a separate Python script to create user customized outputs and graphs. We will show how to use the this database to create a customized graph in [the onboarding docs](../getting_started/onboarding)." ] }, { @@ -208,23 +247,26 @@ "outputs": [], "source": [ "# Testing Cell\n", - "import tempfile\n", "import os\n", "import sys\n", + "import tempfile\n", + "\n", "from openmdao.core.problem import _clear_problem_names\n", "from openmdao.utils.reports_system import clear_reports\n", + "\n", "import aviary.api as av\n", - "from aviary.utils.doctape import check_contains, expected_error, gramatical_list, glue_variable\n", + "from aviary.utils.doctape import check_contains, expected_error, glue_variable, gramatical_list\n", "\n", "list_files = ['input_list.txt', 'output_list.txt']\n", "optimizer_files = {\n", - " 'SNOPT':'SNOPT_print.out',\n", - " 'IPOPT':'IPOPT.out',\n", - " 'SLSQP':'',\n", - " }\n", - "vtsplf = (av.Verbosity.VERBOSE, av.Verbosity.DEBUG) # verbosities that should produce _list files\n", + " 'SNOPT': 'SNOPT_print.out',\n", + " 'IPOPT': 'IPOPT.out',\n", + " 'SLSQP': '',\n", + "}\n", + "vtsplf = (av.Verbosity.VERBOSE, av.Verbosity.DEBUG) # verbosities that should produce _list files\n", "\n", - "def run_and_check(verbosity:av.Verbosity, optimizer='IPOPT'):\n", + "\n", + "def run_and_check(verbosity: av.Verbosity, optimizer='IPOPT'):\n", " list_files_expected = True if verbosity in vtsplf else False\n", " optimizer_file = optimizer_files[optimizer]\n", "\n", @@ -233,45 +275,60 @@ " clear_reports()\n", " os.chdir(tempdir)\n", " old_stdout = sys.stdout\n", - " sys.stdout = open(os.devnull, \"w\")\n", - " av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv',\n", - " None, optimizer=optimizer, max_iter=0, verbosity=verbosity);\n", + " sys.stdout = open(os.devnull, 'w')\n", + " av.run_aviary(\n", + " 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv',\n", + " None,\n", + " optimizer=optimizer,\n", + " max_iter=0,\n", + " verbosity=verbosity,\n", + " )\n", " sys.stdout = old_stdout\n", - " folder_contents = [ f.name for f in os.scandir(tempdir) ]\n", + " folder_contents = [\n", + " f.name for f in os.scandir(tempdir + '/aircraft_for_bench_FwFm_out/reports/')\n", + " ]\n", " all_files = []\n", - " for p,d,f in os.walk(tempdir):\n", - " all_files+=f\n", + " for p, d, f in os.walk(tempdir):\n", + " all_files += f\n", "\n", - " if optimizer_file: check_contains(optimizer_file,all_files)\n", + " if optimizer_file:\n", + " check_contains(optimizer_file, all_files)\n", " if list_files_expected:\n", - " check_contains(list_files,folder_contents)\n", + " check_contains(list_files, folder_contents)\n", " else:\n", " try:\n", - " check_contains(list_files,folder_contents,error_type=expected_error)\n", - " raise RuntimeError(gramatical_list(list_files)+' were found')\n", + " check_contains(list_files, folder_contents, error_type=expected_error)\n", + " raise RuntimeError(gramatical_list(list_files) + ' were found')\n", " except expected_error:\n", " pass\n", " print('\\n')\n", " print(f'{verbosity.name} passed')\n", "\n", - "for filename in list_files :\n", - " glue_variable(filename,md_code=True)\n", + "\n", + "for filename in list_files:\n", + " glue_variable(filename, md_code=True)\n", "for optimizer, optimizer_file in optimizer_files.items():\n", - " glue_variable(optimizer,md_code=True)\n", - " glue_variable(optimizer_file,md_code=True)\n", - "glue_variable('SLSQP.out',md_code=True) # only possible at level3\n", - "string = f\"If `{av.Verbosity.__qualname__}` is set to {gramatical_list(['`'+v.name+'`' for v in vtsplf],'or')}, {gramatical_list(list_files,add_accents=True)} are generated.\"\n", - "glue_variable('verbosity_files',string)\n", + " glue_variable(optimizer, md_code=True)\n", + " glue_variable(optimizer_file, md_code=True)\n", + "glue_variable('SLSQP.out', md_code=True) # only possible at level3\n", + "string = f'If `{av.Verbosity.__qualname__}` is set to {gramatical_list([\"`\" + v.name + \"`\" for v in vtsplf], \"or\")}, {gramatical_list(list_files, add_accents=True)} are generated.'\n", + "glue_variable('verbosity_files', string)\n", "\n", "run_and_check(av.Verbosity.QUIET)\n", "run_and_check(av.Verbosity.BRIEF)\n", - "run_and_check(av.Verbosity.VERBOSE)\n", "try:\n", - " run_and_check(av.Verbosity.DEBUG,optimizer='SNOPT')\n", + " run_and_check(av.Verbosity.VERBOSE, optimizer='SNOPT')\n", "except ImportError:\n", - " pass # SNOPT might not be available\n", - "run_and_check(av.Verbosity.DEBUG,optimizer='IPOPT')\n", - "run_and_check(av.Verbosity.DEBUG,optimizer='SLSQP')\n" + " pass # SNOPT might not be available\n", + "try:\n", + " run_and_check(av.Verbosity.VERBOSE, optimizer='IPOPT')\n", + "except ImportError:\n", + " pass # SNOPT might not be available\n", + "\n", + "run_and_check(av.Verbosity.VERBOSE, optimizer='SLSQP')\n", + "\n", + "# NOTE: We can't test with verbosity=DEBUG here because `show_sparsity=True` in the driver coloring generates a Bokeh report,\n", + "# and there seem to be some unexpected interactions inside of a notebook cell. This might be fixable on the OpenMDAO side." ] }, { @@ -282,7 +339,7 @@ "\n", "There is an optimizer output. If {glue:md}`SNOPT` is the optimizer, {glue:md}`SNOPT_print.out` is generated. The SNOPT output is a detailed output of the optimizer performance. New users likely will want to exercise caution when viewing this output, as it includes some advanced information.\n", "\n", - "If {glue:md}`IPOPT` is the optimizer, {glue:md}`IPOPT.out` is generated. If {glue:md}`SLSQP` is the optimizer and `pyOptSparseDriver` is the driver, {glue:md}`SLSQP.out` is generated.\n", + "If {glue:md}`IPOPT` is the optimizer, {glue:md}`IPOPT.out` is generated. If {glue:md}`SLSQP` is the optimizer and [`pyOptSparseDriver`](https://openmdao.org/newdocs/versions/latest/features/building_blocks/drivers/pyoptsparse_driver.html) is the driver, {glue:md}`SLSQP.out` is generated.\n", "\n", "{glue:md}`verbosity_files`\n", "\n", @@ -297,7 +354,7 @@ "\n", "When a problem is setup, we can add an argument `check=True`. This is an OpenMDAO feature (see [Setup Your Model](https://openmdao.org/newdocs/versions/latest/features/core_features/running_your_models/setup.html) for more information). If we do, a bunch of checks will be performed. You will see those checks on the command line.\n", "\n", - "After a model is run, a `check_partials()` method can be applied and results are printed to the command line. This helps us make sure all of our partial derivatives are correct. We refer users to OpenMDAO's document [Working with Derivatives\n", + "After a model is run, a {glue:md}`check_partials()` method can be applied and results are printed to the command line. This helps us make sure all of our partial derivatives are correct. We refer users to OpenMDAO's document [Working with Derivatives\n", "Using Finite Difference or Complex Step](https://openmdao.org/newdocs/versions/latest/features/core_features/working_with_derivatives/main.html).\n", "\n", "When Aviary is run, some messages are printed on the command line and they are important. More details are in [the onboarding docs](../getting_started/onboarding).\n", @@ -314,7 +371,7 @@ "These files are useful for post-processing and inputting the mission outputs into other tools, especially those used for acoustic analysis.\n", "\n", "```{note}\n", - "This feature is under further development. Please let us know if you have any suggestions for functionality or improvements. This feature is not currently supported when using the shooting integration method.\n", + "This feature is under further development. Please let us know if you have any suggestions for functionality or improvements.\n", "```\n", "\n", "Here is an example of the first few lines of a `mission_timeseries_data.csv` file:\n", @@ -332,7 +389,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -346,9 +403,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.9" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/pre_mission_and_mission.ipynb b/aviary/docs/user_guide/pre_mission_and_mission.ipynb index e82566fc6c..32a4348264 100644 --- a/aviary/docs/user_guide/pre_mission_and_mission.ipynb +++ b/aviary/docs/user_guide/pre_mission_and_mission.ipynb @@ -36,7 +36,7 @@ "\n", "Systems within the mission group are often vectorized.\n", "This is possible because the systems are evaluated at each analysis point independently of the other analysis points when using {term}`collocation integration methods`.\n", - "Within Aviary, the number of mission analysis points is called `num_nodes`." + "Within Aviary, the number of mission analysis points is called {glue:md}`num_nodes`." ] }, { @@ -50,9 +50,20 @@ "outputs": [], "source": [ "# Testing Cell\n", + "import inspect\n", + "\n", "from aviary.mission.phase_builder_base import PhaseBuilderBase\n", - "from aviary.utils.doctape import check_args\n", - "check_args(PhaseBuilderBase.__init__,'num_nodes')" + "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase\n", + "from aviary.utils.doctape import check_args, get_variable_name, glue_class_functions, glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "check_args(PhaseBuilderBase.__init__, 'num_nodes')\n", + "glue_variable('num_nodes', md_code=True)\n", + "glue_variable(get_variable_name(SubsystemBuilderBase), md_code=True)\n", + "\n", + "# Get all functions of class SubsystemBuilderBase\n", + "glue_class_functions(SubsystemBuilderBase, current_glued_vars)" ] }, { @@ -69,7 +80,7 @@ "## The Bus System in Aviary\n", "\n", "Within Aviary, you might want to connect a pre-mission system to a mission system.\n", - "Variables that include a `':'` (which includes all variables that start with `aircraft:` and `mission:`) are connected when you use the `get_parameters()` method within `SubsystemBuilderBase`.\n", + "Variables that include a `':'` (which includes all variables that start with `aircraft:` and `mission:`) are connected when you use the {glue:md}`get_parameters()` method within {glue:md}`SubsystemBuilderBase`.\n", "However, you might want to connect a variable from a pre-mission system to a mission system that does not begin with `'aircraft:'`.\n", "For example, you might have a subsystem that has some computations in the pre-mission system that you want to connect to the mission system, but you don't necessarily want to expose those variables to the rest of Aviary.\n", "The bus system is also useful if you have variables that begin with `'aircraft:'` but you don't want them exposed to the rest of Aviary.\n", @@ -77,7 +88,7 @@ "To do this, you can use the \"bus\" system.\n", "The bus system allows you to connect variables from the pre-mission system to the mission system based on what you specify.\n", "This is especially relevant when you're using external subsystems as core Aviary does not use the bus system internally.\n", - "The notion of the bus system is detailed more within the `SubsystemBuilderBase` docstrings.\n" + "The notion of the bus system is detailed more within the {glue:md}`SubsystemBuilderBase` docstrings.\n" ] }, { @@ -92,8 +103,9 @@ "source": [ "# Testing Cell\n", "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase\n", - "SubsystemBuilderBase.get_parameters;\n", - "SubsystemBuilderBase.get_bus_variables;" + "\n", + "SubsystemBuilderBase.get_parameters\n", + "SubsystemBuilderBase.get_pre_mission_bus_variables" ] }, { @@ -110,7 +122,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -124,7 +136,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.8" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/propulsion.ipynb b/aviary/docs/user_guide/propulsion.ipynb index 83489c5628..fc16e39444 100644 --- a/aviary/docs/user_guide/propulsion.ipynb +++ b/aviary/docs/user_guide/propulsion.ipynb @@ -9,15 +9,30 @@ "\n", "The propulsion subsystem in Aviary organizes and executes models for engine sizing and performance.\n", "\n", - "Aviary does not natively model gas-turbine or electric motor performance, and instead relies on user-provided data and/or custom performance models to perform propulsion analysis.\n", + "Aviary does not natively model gas-turbine performance, and instead relies on user-provided data and/or custom performance models to perform propulsion analysis.\n", "\n", "Aviary supports an arbitrary number of propulsor models on a vehicle, each with their own unique properties such as performance characteristics, scaling behaviors, and number of propulsors for that given type. \n", - "\n", - "Each unique type of engine is referred to as an engine model. In Aviary, an engine model contains information on how to size and estimate performance for a single instance of an engine of that type. During analysis, Aviary handles summing performance data to a system level. This way, information is available on the performance of both a single instance of an engine, as well as aircraft-level totals, for other Aviary subsystems to utilize.\n", "\n", "```{note}\n", "In Aviary, when we refer to multiple engines of the same type, we say they are homogenous. When you are dealing with multiple engines of different types, we say they are heterogeneous.\n", - "``` " + "``` \n", + "\n", + "\n", + "Each unique type of engine is defined by a *engine model*. In Aviary, an *engine model* contains information on how to size and estimate performance for a single instance of an engine of that type. During analysis, Aviary handles summing performance data to a system level. This way, information is available on the performance of both a single instance of an engine, as well as aircraft-level totals, for other Aviary subsystems to utilize.\n", + "\n", + "Aviary's variable hierarchy makes a distinction between variables that apply to a single instance of an engine, under the `Aircraft.Engine` sub-category, and variables that apply to the propulsion system as a whole under `Aircraft.Propulsion`. As an example, imagine an aircraft with a heterogeneous set of engines (those with unique properties). Maximum sea-level-static thrust would be defined differently per engine vs propulsion system like so:\n", + "\n", + ">*aircraft:engine:scaled_sls_thrust = [1500, 2200], lbf*\n", + ">\n", + ">*aircraft:engine:num_engines = [3, 2], unitless*\n", + ">\n", + ">*aircraft:propulsion:total_scaled_sls_thrust = 8900, lbf*\n", + "\n", + "As you can see, variables under *engine* are vectors that store a value for a single each instance of a single type of engine, while variables under *propulsion* only store a single value that is relevant to the entire aircraft rather than any one specific engine or set of engines. Put another way, this aircraft has two hereogenous types of engines, the first that produces 1,500 lbf of thrust *per engine*, with three of those engines on the aircraft, and the second engine that produces 2,200 lbf of thrust *per engine* with only two copies of that engine on the aircraft. The propulsion-level total is 8,900 lbf of thrust, which is every engine physically present on the aircraft combined together (1500\\*3 + 2200\\*2).\n", + "\n", + "In general, the user does not need to define *propulsion* variables, as Aviary can calculate them given values in *engine*, but they are important to understand when reading results.\n", + "\n", + "In this section, we will explain how to set up the propulsion systems of an Aviary model, focusing on relatively straightforward aircraft configurations." ] }, { @@ -27,7 +42,11 @@ "source": [ "## Engine Decks\n", "\n", - "The built-in way Aviary handles engine performance is by interpolating tabular data from a user-defined file that describes performance characteristics for a given engine. Engines modeled in this manner are called engine decks. Engine decks are a type of engine model - they use the same basic interface, but have additional functionality to handle reading and processing data files." + "The primary way Aviary handles engine performance is by interpolating tabular data from a user-defined file that describes performance characteristics for a given engine. Engines modeled in this manner are called *engine decks*. Engine decks are a type of engine model - they use the same basic interface, but have additional functionality to handle reading and processing data files.\n", + "\n", + "Engine decks can contain a variety of different data to represent any number of propulsion systems, typically ones that utilize combustion such as turbofan or turboshaft engines, including hybridized ones. The most common application of an *engine deck* is to represent a turbofan engine, essentially as black box model that describes the relationship between energy consuption (in the form of fuel) into useful work (the production of thrust).\n", + "\n", + "More advanced applications of *engine decks* are as parts of larger, more detailed *engine models*, such as a turboprop. A turboprop model, as described later, connects a turboshaft engine deck with a gearbox and propeller model to bridge the gap between energy consumption and thrust production, packaged together into a single model that treated as a singular unit by the greater propulsion system." ] }, { @@ -36,7 +55,7 @@ "metadata": {}, "source": [ "### Formatting\n", - "An engine deck data file requires specific formatting for Aviary to correctly interpret. These files must follow the [Aviary data file format](input_files). An example of a properly-formatted engine deck can be found [here](https://github.com/OpenMDAO/Aviary/blob/main/aviary/models/engines/turbofan_22k.deck)." + "An *engine deck* data file requires specific formatting for Aviary to correctly interpret. These files must follow the [Aviary data file format](input_files.ipynb). An example of a properly-formatted *engine deck* can be found [here](https://github.com/OpenMDAO/Aviary/blob/main/aviary/models/engines/turbofan_22k.csv)." ] }, { @@ -46,28 +65,30 @@ "source": [ "### Variables\n", "\n", - "The following engine performance parameters are supported natively by Aviary for use in engine decks. If units are not specified, the default units are assumed. A variety of alternate names for these variables are understood by Aviary, but it is recommended to use the official names given here. A column with a header not recognized by Aviary will be ignored, with a warning raised at runtime. This allows for variables not used by Aviary to still be included in a data file, either for reference or compatibility with another analysis tool.\n", + "The following engine performance parameters are supported natively by Aviary for use in *engine decks*. If units are not specified, the default units are assumed. A variety of alternate names for these variables are understood by Aviary, but it is recommended to use the official names given here. A column with a header not recognized by Aviary will be ignored, with a warning raised at runtime. This allows for variables not used by Aviary to still be included in a data file, either for reference or compatibility with another analysis tool.\n", "\n", "\n", "| Variable | Default Units | Required? |\n", "| :--- | :--- | :---: |\n", - "| `Mach Number` | unitless | ✔ |\n", - "| `Altitude` | ft | ✔ |\n", - "| `Throttle` | unitless | ✔ |\n", - "| `Hybrid Throttle` | unitless | ✘ |\n", - "| `Net Thrust` | lbf | ✔* |\n", - "| `Gross Thrust` | lbf | ✘ |\n", - "| `Ram Drag` | lbf | ✘ |\n", - "| `Fuel Flow Rate` | lbm/h | ✘ |\n", - "| `Electric Power` | kW | ✘ |\n", - "| `NOx Rate` | lbm/h | ✘ |\n", - "| `T4 Temperature` | degR | ✘ |\n", - "\n", - "**`Net Thrust` (defined as `Gross Thrust` - `Ram Drag`) is not required if both of those variables are provided for calculation*\n", - "\n", - "`Mach Number`, `Altitude`, and the two throttle parameters are independent variables required to describe the operating conditions of the engine. `Hybrid Throttle` is optional, and is intended for use as a second degree of control for engines using independently controllable fuel- and electric-based power. The remaining variables are dependent on the operating conditions and are therefore typically optional.\n", - "\n", - "Engine decks without headers are assumed to contain only the required variable set, in the order specified by the table (`Mach`, `Altitude`, `Throttle`, and `Net Thrust`), and with default units.\n", + "| {glue:md}`Mach Number` | unitless | ✔ |\n", + "| {glue:md}`Altitude` | ft | ✔ |\n", + "| {glue:md}`Throttle` | unitless | ✔ |\n", + "| {glue:md}`Hybrid Throttle` | unitless | ✘ |\n", + "| {glue:md}`Net Thrust` | lbf | ✔* |\n", + "| {glue:md}`Gross Thrust` | lbf | ✘* |\n", + "| {glue:md}`Ram Drag` | lbf | ✘* |\n", + "| {glue:md}`Shaft Power` | hp | ✘ |\n", + "| {glue:md}`RPM` | rpm | ✘ |\n", + "| {glue:md}`Fuel Flow Rate` | lbm/h | ✘ |\n", + "| {glue:md}`Electric Power` | kW | ✘ |\n", + "| {glue:md}`NOx Rate` | lbm/h | ✘ |\n", + "| {glue:md}`T4 Temperature` | degR | ✘ |\n", + "\n", + "**{glue:md}`Net Thrust` (defined as {glue:md}`Gross Thrust` - {glue:md}`Ram Drag`) is not required if both of those variables are provided for calculation*\n", + "\n", + "{glue:md}`Mach Number`, {glue:md}`Altitude`, and the two throttle parameters are independent variables required to describe the operating conditions of the engine. {glue:md}`Hybrid Throttle` is optional, and is intended for use as a second degree of control for engines using independently controllable fuel- and electric-based power. The remaining variables are dependent on the operating conditions and are therefore typically optional.\n", + "\n", + "*Engine decks* without headers are assumed to contain only the required variable set, in the order specified by the table ({glue:md}`Mach`, {glue:md}`Altitude`, {glue:md}`Throttle`, and {glue:md}`Net Thrust`), and with default units.\n", "\n", "Comments may be added to an engine deck data file by using a '`#`' symbol preceding the comment. Anything after this symbol on that line is ignored by Aviary, allowing the user to temporarily remove data points or add in-line comments with context for the data. It is good practice to include comments at the start of the file to explain what kind of engine the data represents, and where it came from." ] @@ -85,54 +106,84 @@ "source": [ "# Testing Cell\n", "from aviary.api import Aircraft\n", - "from aviary.subsystems.propulsion.engine_deck import aliases, default_required_variables, required_options, dependent_options\n", + "from aviary.subsystems.propulsion.engine_deck import (\n", + " aliases,\n", + " default_required_variables,\n", + " dependent_options,\n", + " required_options,\n", + ")\n", "from aviary.subsystems.propulsion.utils import EngineModelVariables\n", - "from aviary.utils.doctape import check_value, check_contains, glue_variable\n", + "from aviary.utils.doctape import check_contains, check_value, get_variable_name, glue_variable\n", "from aviary.variable_info.variable_meta_data import CoreMetaData\n", "\n", - "vars = ['Mach Number', 'Altitude', 'Throttle', 'Hybrid Throttle', 'Net Thrust',\n", - " 'Gross Thrust', 'Ram Drag', 'Fuel Flow Rate', 'Electric Power', 'NOx Rate',\n", - " 'T4 Temperature']\n", + "vars = [\n", + " 'Mach Number',\n", + " 'Altitude',\n", + " 'Throttle',\n", + " 'Hybrid Throttle',\n", + " 'Net Thrust',\n", + " 'Gross Thrust',\n", + " 'Ram Drag',\n", + " 'Fuel Flow Rate',\n", + " 'Electric Power',\n", + " 'NOx Rate',\n", + " 'T4 Temperature',\n", + " 'Shaft Power',\n", + " 'RPM',\n", + "]\n", "required = ['Mach', 'Altitude', 'Throttle', 'Net Thrust']\n", "\n", + "for var in vars:\n", + " glue_variable(var, md_code=True)\n", + "for var in required:\n", + " if var not in vars:\n", + " glue_variable(var, md_code=True)\n", + "\n", + "\n", "def str_to_enum(list_of_vars):\n", " for ii, var in enumerate(list_of_vars):\n", " for enum, alias in aliases.items():\n", - " if var.lower().replace(' ','_') in alias:\n", + " if var.lower().replace(' ', '_') in alias:\n", " list_of_vars[ii] = enum\n", " break\n", " if not isinstance(list_of_vars[ii], EngineModelVariables):\n", " raise TypeError(f'\"{var}\" could not be mapped to EngineModelVariables')\n", - " \n", + "\n", + "\n", "# Check that all of variables in the table have an associated EngineModelVariable\n", "str_to_enum(vars)\n", "str_to_enum(required)\n", "check_value(set(required), default_required_variables)\n", "\n", - "\n", "Aircraft.Engine = Aircraft.Engine\n", "check_contains(required_options, CoreMetaData)\n", - "required = (#f'{Aircraft.Engine.DATA_FILE=}'.split('=')[0],\n", - " f'{Aircraft.Engine.SCALE_PERFORMANCE=}'.split('=')[0],\n", - " f'{Aircraft.Engine.IGNORE_NEGATIVE_THRUST=}'.split('=')[0],\n", - " f'{Aircraft.Engine.GEOPOTENTIAL_ALT=}'.split('=')[0],\n", - " f'{Aircraft.Engine.GENERATE_FLIGHT_IDLE=}'.split('=')[0])\n", + "required = ( # f'{Aircraft.Engine.DATA_FILE=}'.split('=')[0],\n", + " get_variable_name(Aircraft.Engine.SCALE_PERFORMANCE),\n", + " get_variable_name(Aircraft.Engine.IGNORE_NEGATIVE_THRUST),\n", + " get_variable_name(Aircraft.Engine.GEOPOTENTIAL_ALT),\n", + " get_variable_name(Aircraft.Engine.GENERATE_FLIGHT_IDLE),\n", + ")\n", "required_options_list = ''\n", "for var in required:\n", " required_options_list += f'* `{var}`\\n'\n", - "required_options_list += f'* `{f\"{Aircraft.Engine.NUM_WING_ENGINES=}\".split(\"=\")[0]}` and/or '+\\\n", - " f'`{f\"{Aircraft.Engine.NUM_FUSELAGE_ENGINES=}\".split(\"=\")[0]}`\\n'\n", + "required_options_list += (\n", + " f'* `{get_variable_name(Aircraft.Engine.NUM_WING_ENGINES)}` and/or '\n", + " + f'`{get_variable_name(Aircraft.Engine.NUM_FUSELAGE_ENGINES)}`\\n'\n", + ")\n", "glue_variable('required_options', required_options_list, display=True)\n", "\n", - "GENERATE_FLIGHT_IDLE = (Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION,\n", - " Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION,\n", - " Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION,)\n", + "GENERATE_FLIGHT_IDLE = (\n", + " Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION,\n", + " Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION,\n", + " Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION,\n", + ")\n", "check_value(dependent_options[Aircraft.Engine.GENERATE_FLIGHT_IDLE], GENERATE_FLIGHT_IDLE)\n", - "flight_idle_options = f'* `{f\"{Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION=}\".split(\"=\")[0]}`\\n' +\\\n", - " f'* `{f\"{Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION=}\".split(\"=\")[0]}`\\n' +\\\n", - " f'* `{f\"{Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION=}\".split(\"=\")[0]}`\\n'\n", - "glue_variable('flight_idle_options', flight_idle_options, display=True)\n", - "\n" + "flight_idle_options = (\n", + " f'* `{get_variable_name(Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION)}`\\n'\n", + " + f'* `{get_variable_name(Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION)}`\\n'\n", + " + f'* `{get_variable_name(Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION)}`\\n'\n", + ")\n", + "glue_variable('flight_idle_options', flight_idle_options, display=True)" ] }, { @@ -159,9 +210,9 @@ ":format: myst\n", "```\n", "\n", - "If you are missing any required variables, you will see a warning at runtime. Aviary will try using the default value for the missing variable, which may affect analysis results.\n", + "If you are missing any required variables, you may see a warning at runtime, depending on verbosity level. Aviary will try using the default value for the missing variable, which may affect analysis results.\n", "\n", - "```bash\n", + "```\n", "UserWarning: is a required option for EngineDecks, but has not been specified for EngineDeck . The default value will be used.\n", "```\n", "\n", @@ -185,10 +236,15 @@ "from aviary.api import Aircraft\n", "from aviary.subsystems.propulsion.engine_deck import dependent_options\n", "from aviary.utils.doctape import check_value\n", + "\n", "ae = Aircraft.Engine\n", "\n", - "required = (ae.FLIGHT_IDLE_THRUST_FRACTION, ae.FLIGHT_IDLE_MIN_FRACTION, ae.FLIGHT_IDLE_MAX_FRACTION)\n", - "check_value(required,dependent_options[ae.GENERATE_FLIGHT_IDLE])" + "required = (\n", + " ae.FLIGHT_IDLE_THRUST_FRACTION,\n", + " ae.FLIGHT_IDLE_MIN_FRACTION,\n", + " ae.FLIGHT_IDLE_MAX_FRACTION,\n", + ")\n", + "check_value(required, dependent_options[ae.GENERATE_FLIGHT_IDLE])" ] }, { @@ -198,9 +254,9 @@ "source": [ "### Intermediate Guide\n", "\n", - "Engine models are defined in Aviary using an `EngineModel` object. An `EngineModel` is responsible for handling many tasks required to prepare an engine for use in Aviary, such as reading engine data from a file in the case of an `EngineDeck` (which is a child class of `EngineModel`). \n", + "Engine models are defined in Aviary using an {glue:md}`EngineModel` object. An {glue:md}`EngineModel` is responsible for handling many tasks required to prepare an engine for use in Aviary, such as reading engine data from a file in the case of an {glue:md}`EngineDeck` (which is a child class of {glue:md}`EngineModel`). \n", "\n", - "An `EngineModel` (and classes inheriting it) can be manually created and added to the Aviary problem. This is extremely useful when setting up an aircraft with multiple heterogenous types, each with unique properties, or using a custom engine model. An `EngineModel` requires an `AviaryValues` object containing the variables required for that engine (such as those outlined in the Beginner Guide example for `EngineDecks`)." + "An {glue:md}`EngineModel` (and classes inheriting it) can be manually created and added to the Aviary problem, instead of being created from the values provided via an Aviary input file. This is extremely useful when setting up an aircraft with multiple heterogenous types of engines, each with unique properties, or using a custom engine model. An {glue:md}`EngineModel` requires an {glue:md}`AviaryValues` object containing the variables required for that engine (such as those outlined in the Beginner Guide example for {glue:md}`EngineDeck`)." ] }, { @@ -215,15 +271,21 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.subsystems.propulsion.engine_model import EngineModel\n", + "import inspect\n", + "\n", "from aviary.subsystems.propulsion.engine_deck import EngineDeck\n", - "from aviary.utils.doctape import check_value\n", + "from aviary.subsystems.propulsion.engine_model import EngineModel\n", "from aviary.utils.aviary_values import AviaryValues\n", - "import inspect\n", + "from aviary.utils.doctape import check_value, get_variable_name, glue_variable\n", "\n", "check_value(EngineDeck.__base__, EngineModel)\n", "type_hint = inspect.signature(EngineModel).parameters['options'].annotation\n", - "check_value(type_hint, AviaryValues)" + "check_value(type_hint, AviaryValues)\n", + "\n", + "glue_variable(EngineModel.__name__, md_code=True)\n", + "glue_variable(EngineDeck.__name__, md_code=True)\n", + "glue_variable(AviaryValues.__name__, md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.DRAG_POLAR), md_code=True)" ] }, { @@ -233,23 +295,23 @@ "metadata": {}, "outputs": [], "source": [ - "# enforce uniform code style across documentation\n", "import aviary.api as av\n", - "from aviary.utils.functions import get_path\n", - "from aviary.variable_info.variables import Aircraft\n", + "from aviary.api import Aircraft\n", "\n", "aviary_options = av.AviaryValues()\n", "\n", "# Add relevant inputs and options to engine_options\n", "# using engine_options.set_val(...)\n", - "filename = get_path('models/engines/turbofan_28k.deck')\n", + "filename = av.get_path('models/engines/turbofan_28k.csv')\n", "aviary_options.set_val(Aircraft.Engine.DATA_FILE, filename)\n", - "aviary_options.set_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, 0.9)\n", + "# example of setting an engine variable to a specific value\n", + "aviary_options.set_val(Aircraft.Engine.SCALE_FACTOR, 0.9)\n", "\n", "# It is assumed here that aviary_options is configured to have\n", - "# all inputs needed for analysis, except engine-level values\n", - "engine_model = av.EngineModel(name='example',\n", - " options=aviary_options)" + "# all inputs needed for analysis, except engine-level values.\n", + "# Because not all required options were defined in this example, we\n", + "# see a number of warnings about the missing variables.\n", + "engine_deck = av.EngineDeck(name='example', options=aviary_options)" ] }, { @@ -257,7 +319,9 @@ "id": "19e31c3b", "metadata": {}, "source": [ - "Once an `EngineModel` has been created, it must be added to the Aviary analysis you want to perform. The simplest way to do this is to take advantage of the propulsion preprocessor utility. This preprocessor handles all of the details of getting data related to `EngineModels`, which may change during initialization, correctly set up in the `AviaryValues` object which is used to define the vehicle at the Aviary problem level." + "In this example code snippet, we didn't set a value for every required variable and option previously listed - because of this, we get a number of warnings letting us know which ones we forgot to set, and that the default values specified will be used.\n", + "\n", + "Once an {glue:md}`EngineDeck` has been successfully created, it must be attached to the vehicle model you want to analyze. The simplest way to do this is to take advantage of the propulsion preprocessor utility. This preprocessor handles all of the details of getting data related to `EngineModels`, which may change during initialization, correctly set up in the `AviaryValues` object which is used to define the vehicle at the Aviary problem level. This is a critical step, because once Aviary begins analysis it assumes that all of the relevant data present in individual `EngineModels` have made their way into the vehicle-level data." ] }, { @@ -267,8 +331,7 @@ "metadata": {}, "outputs": [], "source": [ - "av.preprocess_propulsion(aviary_options=aviary_options,\n", - " engine_models=[engine_model])" + "av.preprocess_propulsion(aviary_options=aviary_options, engine_models=[engine_deck])" ] }, { @@ -276,7 +339,8 @@ "id": "bbabdf30", "metadata": {}, "source": [ - "In this example, *aviary_options* is modified in-place with updated values from *engine_model*, as well as properly configuring engine-related variables into vectors. When working with multiple heterogenous engines, simply provide `preprocess_propulsion()` with a list of all `EngineModels`, like so:" + "#### Heterogenous Engine Sets\n", + "In this example, our aircraft model has two distinct types of engines, which are assumed to have different properties. To keep this example simple, we will build an aircraft with two sets of engines based on the `EngineDeck` we just set up, but one set of engines is scaled to half size using `Aircraft.Engine.SCALE_FACTOR`." ] }, { @@ -290,17 +354,39 @@ }, "outputs": [], "source": [ - "# Testing Cell\n", "import aviary.api as av\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", "\n", - "filename = 'models/engines/turbofan_28k.deck'\n", + "filename = 'models/engines/turbofan_28k.csv'\n", "options = av.AviaryValues()\n", "options.set_val(av.Aircraft.Engine.DATA_FILE, av.get_path(filename))\n", - "options.set_val(av.Aircraft.Engine.INTERPOLATION_METHOD, 'slinear')\n", "\n", - "engine_model_1 = av.EngineDeck(options=options)\n", - "engine_model_2 = av.EngineModel(options=options)\n", - "aviary_options = options" + "engine_deck_1 = av.EngineModel(options=options)\n", + "\n", + "# now let's change the second engine to be scaled smaller by changing options\n", + "options.set_val(Aircraft.Engine.SCALE_FACTOR, 0.5)\n", + "engine_deck_2 = av.EngineModel(options=options)" + ] + }, + { + "cell_type": "markdown", + "id": "961a361d", + "metadata": {}, + "source": [ + "*aviary_options* is modified in-place with updated values to represent our new *engine_deck*. When working with multiple heterogenous engines, simply provide `preprocess_propulsion()` with a list of all `EngineModels`, like so:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9335d5ca", + "metadata": {}, + "outputs": [], + "source": [ + "# Test Cell\n", + "aviary_options = av.AviaryValues()\n", + "# set this to avoid warning in later cell\n", + "aviary_options.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2)" ] }, { @@ -314,9 +400,28 @@ }, "outputs": [], "source": [ - "av.preprocess_propulsion(aviary_options=aviary_options,\n", - " engine_models=[engine_model_1,\n", - " engine_model_2])\n" + "av.preprocess_propulsion(\n", + " aviary_options=aviary_options, engine_models=[engine_deck_1, engine_deck_2]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c566473f", + "metadata": {}, + "outputs": [], + "source": [ + "# Testing Cell\n", + "print(f'Interpolation Method: {aviary_options.get_val(Aircraft.Engine.SCALE_FACTOR)}')" + ] + }, + { + "cell_type": "markdown", + "id": "612e0ff5", + "metadata": {}, + "source": [ + "Note how calling `preprocess_propulsion()` changes `Aircraft.Engine.SCALE_FACTOR`, which was individually defined for each `EngineDeck`, into a list containing both values. This way Aviary can access information on every `EngineModel` present on the aircraft without needing access to each individual `EngineModel` object. This is important to be aware of if you are manually setting any variables related to engines or propulsion rather than using the built-in methods and functions presented in the Intermediate guide, which will do this work for you." ] }, { @@ -332,7 +437,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -346,7 +451,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.8" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/reserve_missions.ipynb b/aviary/docs/user_guide/reserve_missions.ipynb index 42a13eb580..cf1fe1bdbb 100644 --- a/aviary/docs/user_guide/reserve_missions.ipynb +++ b/aviary/docs/user_guide/reserve_missions.ipynb @@ -1,5 +1,37 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.interface.methods_for_level2 import AviaryGroup, AviaryProblem\n", + "from aviary.utils.doctape import glue_class_functions, glue_variable, glue_class_options\n", + "\n", + "current_glued_vars = []\n", + "\n", + "glue_variable(av.EquationsOfMotion.HEIGHT_ENERGY.value, md_code=False)\n", + "glue_variable(av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value, md_code=False)\n", + "\n", + "glue_class_options(AviaryGroup, current_glued_vars, md_code=True)\n", + "\n", + "folder = 'examples/reserve_missions/'\n", + "\n", + "str_level2_example = 'run_reserve_mission_multiphase.py'\n", + "file_path = av.get_path(folder + str_level2_example)\n", + "glue_variable(file_path.name, md_code=True)\n", + "\n", + "# Get all functions of class AviaryProblem\n", + "glue_class_functions(AviaryProblem, current_glued_vars, prefix='prob')" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -10,19 +42,17 @@ "\n", "Reserve missions are enabled for the following mission types:\n", "\n", - "* height_energy (completed)\n", - "* 2DOF (collocation) (complete)\n", - "* 2DOF (shooting) (in-progress)\n", - "* height_energy (shooting) (future work)\n", + "* {glue:md}`height_energy`\n", + "* {glue:md}`2DOF`\n", "\n", - "A reserve mission can be created by appending one or more reserve phases to `phase_info` after the last phase of the regular mission.\n", - "To create a simple reserve mission, copy your current cruise phase which is located in `phase_info`.\n", + "A reserve mission can be created by appending one or more reserve phases to {glue:md}`mission_info` after the last phase of the regular mission.\n", + "To create a simple reserve mission, copy your current cruise phase which is located in {glue:md}`mission_info`.\n", "\n", "```{note}\n", "You may need to revise some of your assumptions for the copied phase if you are making a reserve phase that is radically different than the original (i.e. original phase was to travel 3000km but reserve phase is 100km).\n", "```\n", "\n", - "Append that phase to the end of `phase_info`, name it `reserve_cruise` and add `\"reserve\": True,` to `user_options` for this phase.\n", + "Append that phase to the end of {glue:md}`mission_info`, name it `reserve_cruise` and add `\"reserve\": True,` to `user_options` for this phase.\n", "There are two optional flags that can now be added to `user_options`.\n", "The `\"target_duration\"` option creates a phase requiring the aircraft to fly for a specific amount of time.\n", "The `\"target_distance\"` option creates a phase requiring the aircraft to fly for a specific distance.\n", @@ -41,30 +71,31 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.mission.flight_phase_builder import FlightPhaseBase\n", "import os\n", - "import aviary.api as av\n", "from importlib.machinery import SourceFileLoader\n", + "\n", + "import aviary.api as av\n", + "from aviary.mission.flight_phase_builder import FlightPhaseBase\n", "from aviary.utils.doctape import check_contains\n", "\n", - "gasp_phase_path = av.get_path(os.path.join('mission','gasp_based','phases'))\n", + "gasp_phase_path = av.get_path(os.path.join('mission', 'gasp_based', 'phases'))\n", "files = os.listdir(gasp_phase_path)\n", "phases = [FlightPhaseBase]\n", "for file in files:\n", - " if '_phase.py' in file:\n", - " file_path = os.path.join(str(gasp_phase_path),file)\n", + " if '_phase.py' in file and 'twodof' not in file:\n", + " file_path = os.path.join(str(gasp_phase_path), file)\n", " phase_name = file.split('_phase.py')[0].capitalize()\n", " module = SourceFileLoader(phase_name, file_path).load_module()\n", - " phases.append(getattr(module, phase_name+'Phase'))\n", + " phases.append(getattr(module, phase_name + 'Phase'))\n", "\n", "for phase in phases:\n", " phase_name = phase().__class__.__name__\n", " if 'Groundroll' in phase_name:\n", - " continue # no reserve groundroll\n", + " continue # no reserve groundroll\n", " check_contains(\n", - " ['reserve','target_duration','target_distance'],\n", - " phase._meta_data_,\n", - " error_string=\"{var} is not a valid key for \"+str(phase_name)\n", + " ['reserve', 'time_duration', 'target_distance'],\n", + " phase.default_options_class(),\n", + " error_string='{var} is not a valid key for ' + str(phase_name),\n", " )" ] }, @@ -73,7 +104,7 @@ "metadata": {}, "source": [ "You can chain together multiple reserve phases to make a complete reserve mission (i.e. climb to altitude, cruise for range, cruise for time, then descend).\n", - "Examples of this are shown in `run_reserve_mission_multiphase.py` and `run_2dof_reserve_mission_multiphase.py`." + "An example of this is shown in {glue:md}`run_reserve_mission_multiphase.py`." ] }, { @@ -87,16 +118,41 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.doctape import check_contains\n", - "import aviary.api as av\n", "import os\n", "\n", - "reserve_examples = av.get_path(os.path.join('examples','reserve_missions'))\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import check_contains\n", + "\n", + "reserve_examples = av.get_path(os.path.join('examples', 'reserve_missions'))\n", "check_contains(\n", - " ('run_reserve_mission_multiphase.py','run_2dof_reserve_mission_multiphase.py'),\n", + " ('run_reserve_mission_multiphase.py'),\n", " os.listdir(reserve_examples),\n", - " error_string=\"{var} not in \"+str(reserve_examples),\n", - " error_type=FileNotFoundError)" + " error_string='{var} not in ' + str(reserve_examples),\n", + " error_type=FileNotFoundError,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "methods_for_level2 = av.get_path('interface/methods_for_level2.py').name\n", + "glue_variable(methods_for_level2, md_code=True)\n", + "\n", + "setting_2DOF = (\n", + " av.Settings.EQUATIONS_OF_MOTION + ',' + av.EquationsOfMotion.TWO_DEGREES_OF_FREEDOM.value\n", + ")\n", + "glue_variable('setting_2DOF', setting_2DOF, md_code=True)" ] }, { @@ -114,10 +170,10 @@ "\n", "### Caveats when using 2DOF\n", "\n", - "If you are using 2DOF equations of motion (EOM) in your problem (i.e. `settings:equations_of_motion,2DOF`) there are some additional things you need to be aware of.\n", - "The name of the reserve phase should include one of the keywords to indicate which EOM from 2DOF will be selected and the prefix `reserve_`.\n", - "Valid keywords include: `rotation`, `accel`, `ascent`, `climb1`, `climb2`, `cruise`, `desc1`, `desc2`.\n", - "This is because 2DOF uses different EOMs for different phases and we need to let `methods_for_level2.py` know which method to select.\n", + "If you are using {glue:md}`2DOF` equations of motion (EOM) in your problem (i.e. {glue:md}`setting_2DOF`) there are some additional things you need to be aware of.\n", + "The name of the reserve phase should include one of the keywords to indicate which EOM from {glue:md}`2DOF` will be selected and the prefix `reserve_`.\n", + "Valid keywords include: {glue:md}`rotation`, {glue:md}`accel`, {glue:md}`ascent`, {glue:md}`climb1`, {glue:md}`climb2`, {glue:md}`cruise`, {glue:md}`desc1`, {glue:md}`desc2`.\n", + "This is because {glue:md}`2DOF` uses different EOMs for different phases and we need to let {glue:md}`methods_for_level2.py` know which method to select.\n", "This is why in the example in the first paragraph above, the phase was named `reserve_cruise`.\n", "Cruise phases can have additional information in suffixes, but this isn't necessary.\n", "Do not worry about phase naming if you are using Height-Energy EOM as all those EOMs are the same for every phase." @@ -134,15 +190,11 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.utils.check_phase_info import phase_keys_gasp\n", - "from aviary.utils.doctape import check_contains\n", + "from aviary.utils.doctape import check_contains, glue_variable\n", "\n", - "expected_phases = [phase for phase in phase_keys_gasp if phase!='groundroll'] # no reserve groundroll\n", - "check_contains(\n", - " ['rotation','accel','ascent','climb1','climb2','cruise','desc1','desc2'],\n", - " expected_phases,\n", - " error_string=\"{var} is not a valid name for a 2DOF reserve phase, choose from \"+f\"{expected_phases}\"\n", - " )\n" + "two_DOF_phases = ['rotation', 'accel', 'ascent', 'climb1', 'climb2', 'cruise', 'desc1', 'desc2']\n", + "for ph in two_DOF_phases:\n", + " glue_variable(ph, md_code=True)" ] }, { @@ -151,21 +203,20 @@ "source": [ "## Theory\n", "\n", - "When adding a reserve phase, `check_and_preprocess_inputs()` divides all the phases into two dictionaries: `regular_phases` which contain your nominal phases and `reserve_phases` which contains any phases with the `reserve` flag set to `True`.\n", - "Additionally, `check_and_preprocess_inputs()` will add the `\"analytic\"` flag to each phase.\n", + "When adding a reserve phase, {glue:md}`check_and_preprocess_inputs()` divides all the phases into two dictionaries: `regular_phases` which contain your nominal phases and `reserve_phases` which contains any phases with the `reserve` flag set to `True`.\n", + "Additionally, {glue:md}`check_and_preprocess_inputs()` will add the `\"analytic\"` flag to each phase.\n", "This is used to indicate if a phase is an analytic phase (i.e. Breguet range) or a ordinary differential equation (ODE).\n", "\n", "Only the final mission mass and range from `regular_phases` are automatically connected to the first point of the `reserve_phases`.\n", "All other state variables (i.e. altitude, mach) are not automatically connected, allowing you to start the reserve mission at whatever altitude you want.\n", "\n", - "The `\"analytic\"` flag helps to properly connect phases for 2DOF missions.\n", - "2DOF `cruise` missions are analytic because they use a Breguet range calculation instead of integrating an EOM. \n", + "The `\"analytic\"` flag helps to properly connect phases for {glue:md}`2DOF` missions.\n", + "{glue:md}`2DOF` `cruise` missions are analytic because they use a Breguet range calculation instead of integrating an EOM. \n", "Analytic phases have a slightly different naming convention in order to access state/timeseries variables like distance, mass, and range compared with their non-analytic counterparts.\n", "\n", "You cannot create a reserve mission that enforces time or range constraints over multiple phases (i.e specify the total range covered by a climb + cruise + descent).\n", "This is because each constraint `\"target_distance\"` or `\"target_time\"` is only enforced on a single phase.\n", - "\n", - "It is essential that you run `prob.check_and_preprocess_inputs()` after `prob.load_inputs()` to make sure that regular and reserve phases are separated via `phase_separator()`." + "It is essential that you run {glue:md}`prob.check_and_preprocess_inputs()` after {glue:md}`prob.load_inputs()` to make sure that regular and reserve phases are separated via `phase_separator()`." ] }, { @@ -179,28 +230,29 @@ "outputs": [], "source": [ "# Testing Cell\n", + "import os\n", "from importlib.machinery import SourceFileLoader\n", - "from aviary.interface.methods_for_level2 import AviaryProblem\n", - "from aviary.interface.default_phase_info.two_dof import phase_info\n", + "\n", + "import aviary.api as av\n", + "from aviary.models.missions.two_dof_default import phase_info\n", "from aviary.interface.download_models import get_model\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", "from aviary.utils.doctape import check_contains\n", - "import aviary.api as av\n", - "import os\n", "\n", "prob = AviaryProblem()\n", "prob.load_inputs(get_model('aircraft_for_bench_GwGm.csv'), phase_info)\n", "prob.check_and_preprocess_inputs()\n", "\n", - "gasp_phase_path = av.get_path(os.path.join('mission','gasp_based','phases'))\n", + "gasp_phase_path = av.get_path(os.path.join('mission', 'gasp_based', 'phases'))\n", "for file in os.listdir(gasp_phase_path):\n", - " if '_phase.py' in file:\n", + " if '_phase.py' in file and 'twodof' not in file:\n", " phase_name = file.split('_phase.py')[0].capitalize()\n", - " file_path = os.path.join(str(gasp_phase_path),file)\n", + " file_path = os.path.join(str(gasp_phase_path), file)\n", " module = SourceFileLoader(phase_name, file_path).load_module()\n", " check_contains(\n", " 'analytic',\n", - " getattr(module, phase_name+'Phase')._meta_data_,\n", - " error_string=f\"analytic is not a valid key for {phase_name}\",\n", + " getattr(module, phase_name + 'PhaseOptions')(),\n", + " error_string=f'analytic is not a valid key for {phase_name}',\n", " error_type=NameError,\n", " )" ] @@ -212,7 +264,7 @@ "### Advanced Users and Target Duration Phases\n", "\n", "For advanced users, instead of just copying a phase you used before, you might completely specify a new phase from scratch. \n", - "When creating a `\"target_duration\"` reserve phase there are a number of values inside of `phase_info['user_options']` that are overwritten in `check_and_preprocess_inputs()`. \n", + "When creating a `\"target_duration\"` reserve phase there are a number of values inside of `phase_info['user_options']` that are overwritten in {glue:md}`prob.check_and_preprocess_inputs()`. \n", "Specifically, `duration_bounds`, `fixed_duration`, and `\"initial_guesses\": {\"time\"}` will be over-written. \n", "That is because if `\"target_duration\"` is specified, Aviary already knows what these other three values need to be: `target_duration = duration_bounds = \"initial_guesses\": {\"time\"}`, and `fix_duration = True`." ] @@ -228,35 +280,36 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.methods_for_level2 import AviaryProblem\n", - "from aviary.interface.default_phase_info.two_dof import phase_info\n", - "from aviary.interface.download_models import get_model\n", "from copy import deepcopy\n", + "\n", + "from aviary.models.missions.two_dof_default import phase_info\n", + "from aviary.interface.download_models import get_model\n", + "from aviary.interface.methods_for_level2 import AviaryProblem\n", "from aviary.utils.doctape import check_value\n", "\n", "climb1_info = deepcopy(phase_info['climb1'])\n", "phase_info_for_test = {'climb1': climb1_info}\n", "user_options = climb1_info['user_options']\n", "user_options['reserve'] = True\n", - "user_options['target_duration'] = (10, 'min')\n", - "user_options['duration_bounds'] = ((30, 300), 's')\n", - "climb1_info['initial_guesses']['time'] = ([1., 2.], 'min')\n", + "user_options['time_duration'] = (10, 'min')\n", + "user_options['time_duration_bounds'] = ((30, 300), 's')\n", + "climb1_info['initial_guesses']['time'] = ((1.0, 2.0), 'min')\n", "\n", "prob = AviaryProblem()\n", "prob.load_inputs(get_model('aircraft_for_bench_GwGm.csv'), phase_info_for_test)\n", + "\n", "prob.check_and_preprocess_inputs()\n", "\n", "values_of_interest = {\n", - " 'target_duration': user_options['target_duration'],\n", - " 'duration_bounds': user_options['duration_bounds'],\n", - " 'fix_duration': user_options['fix_duration'],\n", - " 'time': climb1_info['initial_guesses']['time']\n", - " }\n", + " 'time_duration': user_options['time_duration'],\n", + " 'time_duration_bounds': user_options['time_duration_bounds'],\n", + " 'time': climb1_info['initial_guesses']['time'],\n", + "}\n", "expected_values = {\n", - " 'target_duration': (10, 'min'),\n", - " 'duration_bounds': ((10, 10), 'min'),\n", - " 'fix_duration': True,\n", - " 'time': ((10, 10), 'min')}\n", + " 'time_duration': (10, 'min'),\n", + " 'time_duration_bounds': ((30, 300), 's'),\n", + " 'time': ((1.0, 10.0), 'min'),\n", + "}\n", "check_value(values_of_interest, expected_values)" ] }, @@ -266,13 +319,13 @@ "source": [ "### Fuel Burn Calculations\n", "\n", - "Fuel burn during the regular mission (`Mission.Summary.FUEL_BURNED`) is calculated only based on `regular_phases`.\n", + "Fuel burn during the regular mission ({glue:md}`Mission.Summary.FUEL_BURNED`) is calculated only based on `regular_phases`.\n", "\n", - "Reserve fuel (`Mission.Design.RESERVE_FUEL`) is the sum of `Aircraft.Design.RESERVE_FUEL_ADDITIONAL`, `Aircraft.Design.RESERVE_FUEL_FRACTION`, and `Mission.Summary.RESERVE_FUEL_BURNED`.\n", + "Reserve fuel ({glue:md}`Mission.Design.RESERVE_FUEL`) is the sum of {glue:md}`Aircraft.Design.RESERVE_FUEL_ADDITIONAL`, {glue:md}`Aircraft.Design.RESERVE_FUEL_FRACTION`, and {glue:md}`Mission.Summary.RESERVE_FUEL_BURNED`.\n", "\n", - "* `RESERVE_FUEL_ADDITIONAL` is a fixed value (i.e. 300kg)\n", - "* `RESERVE_FUEL_FRACTION` is based on a fraction of `Mission.Summary.FUEL_BURNED`\n", - "* `RESERVE_FUEL_BURNED` is sum of fuel burn in all `reserve_phases`\n" + "* {glue:md}`RESERVE_FUEL_ADDITIONAL` is a fixed value (i.e. 300kg)\n", + "* {glue:md}`RESERVE_FUEL_FRACTION` is based on a fraction of {glue:md}`Mission.Summary.FUEL_BURNED`\n", + "* {glue:md}`RESERVE_FUEL_BURNED` is sum of fuel burn in all `reserve_phases`\n" ] }, { @@ -287,11 +340,22 @@ "source": [ "# Testing Cell\n", "from aviary.api import Aircraft, Mission\n", - "Mission.Summary.FUEL_BURNED;\n", - "Mission.Design.RESERVE_FUEL;\n", - "Aircraft.Design.RESERVE_FUEL_ADDITIONAL;\n", - "Aircraft.Design.RESERVE_FUEL_FRACTION;\n", - "Mission.Summary.RESERVE_FUEL_BURNED;" + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "Mission.Summary.FUEL_BURNED\n", + "Mission.Design.RESERVE_FUEL\n", + "Aircraft.Design.RESERVE_FUEL_ADDITIONAL\n", + "Aircraft.Design.RESERVE_FUEL_FRACTION\n", + "glue_variable(get_variable_name(Mission.Summary.FUEL_BURNED), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Design.RESERVE_FUEL), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.RESERVE_FUEL_ADDITIONAL), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Design.RESERVE_FUEL_FRACTION), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Summary.RESERVE_FUEL_BURNED), md_code=True)\n", + "glue_variable(\n", + " get_variable_name(Aircraft.Design.RESERVE_FUEL_ADDITIONAL).split('.')[2], md_code=True\n", + ")\n", + "glue_variable(get_variable_name(Aircraft.Design.RESERVE_FUEL_FRACTION).split('.')[2], md_code=True)\n", + "glue_variable(get_variable_name(Mission.Summary.RESERVE_FUEL_BURNED).split('.')[2], md_code=True)" ] } ], @@ -311,9 +375,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.0" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/step_by_step_external_guide.ipynb b/aviary/docs/user_guide/step_by_step_external_guide.ipynb index b1c70a1289..e6389dc74b 100644 --- a/aviary/docs/user_guide/step_by_step_external_guide.ipynb +++ b/aviary/docs/user_guide/step_by_step_external_guide.ipynb @@ -55,7 +55,7 @@ "\n", "Now we'll create your subsystem builder. This is arguably the most important step since it exposes your model to Aviary using a consistent interface. The main idea surrounding the subsystem builder is that subject matter experts (you!) will create a specialized Python class that defines specific methods needed by Aviary to integrate your subsystem. I'll walk you through this process now, but don't worry -- we also have some tests to help ensure your subsystem builder is set up correctly.\n", "\n", - "1. First, let's work out some ground rules of the subsystem builder. You'll inherit from `SubsystemBuilderBase` when you create your builder. This base class features *all* methods used by Aviary, even if your specific subsystem doesn't need them (this varies on a subsystem to subsystem basis).\n", + "1. First, let's work out some ground rules of the subsystem builder. You'll inherit from {glue:md}`SubsystemBuilderBase` when you create your builder. This base class features *all* methods used by Aviary, even if your specific subsystem doesn't need them (this varies on a subsystem to subsystem basis).\n", "2. Most all of these methods are documented in-line, as well as on the doc page. I hope that you can follow those and understand what to do with your model, but if you can't, please let us know your questions and we'll rework these docs.\n", "3. These methods can be roughly divided into three broad categories (shown in the graphic below):\n", "\n", @@ -67,7 +67,7 @@ "\n", "![subsystem methods](images/external_subsystem_methods.png)\n", "\n", - "To integrate external subsystems into Aviary, you need to use the [`SubsystemBuilderBase` class](../user_guide/subsystems) as a template for creating your builder object.\n", + "To integrate external subsystems into Aviary, you need to use the [{glue:md}`SubsystemBuilderBase` class](../user_guide/subsystems) as a template for creating your builder object.\n", "This class provides you with skeletal methods that you replace to specify the behavior of your subsystem.\n", "The methods you should implement depend on what type of subsystem you're building." ] @@ -83,7 +83,14 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase" + "from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder\n", + "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase\n", + "from aviary.utils.doctape import glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "glue_variable(SubsystemBuilderBase.__name__, md_code=True)\n", + "glue_variable(BatteryBuilder.__name__ + '()', md_code=True)" ] }, { @@ -100,7 +107,7 @@ "\n", "## Using your builder within Aviary\n", "\n", - "Awesome. Let's keep going and start to discuss using these subsystems within Aviary. The overarching idea is that now that you have a subsystem builder, you can pass an instantiation of this builder object to Aviary via the `phase_info` dictionary. Take a look at [`run_cruise.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/battery/run_cruise.py) and [`run_multiphase_mission.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/battery/run_multiphase_mission.py) to see how we do this for the battery model. Specifically, here are the relevant lines of code from the `run_cruise.py` file:" + "Awesome. Let's keep going and start to discuss using these subsystems within Aviary. The overarching idea is that now that you have a subsystem builder, you can pass an instantiation of this builder object to Aviary via the {glue:md}`phase_info` dictionary. Take a look at [`run_cruise.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/battery/run_cruise.py) and [`run_multiphase_mission.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/battery/run_multiphase_mission.py) to see how we do this for the battery model. Specifically, here are the relevant lines of code from the `run_cruise.py` file:" ] }, { @@ -113,7 +120,24 @@ }, "outputs": [], "source": [ - "from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder" + "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase\n", + "from aviary.utils.doctape import check_contains, glue_class_functions\n", + "\n", + "# Get all functions of class SubsystemBuilderBase\n", + "glue_class_functions(SubsystemBuilderBase, current_glued_vars)\n", + "\n", + "# make sure all the functions in images/external_subsystem_methods.png exist\n", + "expected_function_names = [\n", + " 'get_states()',\n", + " 'get_constraints()',\n", + " 'get_design_vars()',\n", + " 'get_parameters()',\n", + " 'preprocess_inputs()',\n", + " 'get_initial_guesses()',\n", + " 'get_mass_names()',\n", + " 'get_outputs()',\n", + "]\n", + "check_contains(expected_function_names, current_glued_vars)" ] }, { @@ -128,19 +152,37 @@ "source": [ "battery_builder = BatteryBuilder()\n", "\n", - "phase_info = {\n", - " 'pre_mission': {\n", - " 'include_takeoff': False,\n", - " 'external_subsystems': [battery_builder],\n", - " 'optimize_mass': False,\n", - " },\n", - " 'cruise': {\n", - " # ... #\n", - " 'external_subsystems': [battery_builder],\n", - " # ... #\n", - " }\n", + "phase_info = (\n", + " {\n", + " 'pre_mission': {\n", + " 'include_takeoff': False,\n", + " 'external_subsystems': [battery_builder],\n", + " 'optimize_mass': False,\n", + " },\n", + " 'cruise': {\n", + " # ... #\n", + " 'external_subsystems': [battery_builder],\n", + " # ... #\n", + " },\n", " },\n", - " # ... #" + ")\n", + "# ... #" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.utils.doctape import get_variable_name, glue_variable\n", + "\n", + "glue_variable(get_variable_name(phase_info), md_code=True)" ] }, { @@ -153,7 +195,7 @@ "\n", "2. **Add any `external_subsystems` to your pre- and post-mission phases too.** If you have pre- or post-mission analyses in your subsystem, make sure to add the `external_subsystems` list to the `pre_mission` and `post_mission` sub-dicts within the `phase_info` dict. This means that Aviary will build and use those systems before or after the mission; otherwise Aviary won't know to put the systems there.\n", "\n", - "3. **Start with a simple mission in Aviary.** To begin, try adapting the [`run_cruise.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/battery/run_cruise.py) script to use your subsystem. Replace the `BatteryBuilder()` instance with your subsystem, for example. You might need other setup or inputs based on the complexity of your model. But in general, it helps to start with the simplest mission you can. In this case, that's probably a steady level cruise flight.\n", + "3. **Start with a simple mission in Aviary.** To begin, try adapting the [`run_cruise.py`](https://github.com/OpenMDAO/Aviary/blob/main/aviary/examples/external_subsystems/battery/run_cruise.py) script to use your subsystem. Replace the {glue:md}`BatteryBuilder()` instance with your subsystem, for example. You might need other setup or inputs based on the complexity of your model. But in general, it helps to start with the simplest mission you can. In this case, that's probably a steady level cruise flight.\n", "\n", " Even though this is a \"simple\" mission, there's still a lot that can go wrong. It turns out that designing an aircraft is challenging sometimes. I don't expect your mission optimization to converge well your first try; it often takes some debugging and digging to get your subsystem integrated well. It's really challenging to write docs to help you do this without knowing more about your system, what it's trying to do while the aircraft is flying, and what you've already checked. That being said, make sure to reach out if you're encountering problems here.\n", "\n", @@ -162,10 +204,24 @@ } ], "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/subsystems.ipynb b/aviary/docs/user_guide/subsystems.ipynb index 2683ed2e16..6c077a4098 100644 --- a/aviary/docs/user_guide/subsystems.ipynb +++ b/aviary/docs/user_guide/subsystems.ipynb @@ -12,63 +12,82 @@ "source": [ "# Testing Cell\n", "import aviary.interface.methods_for_level2 as methods_for_level2\n", - "from aviary.utils.doctape import glue_variable\n", "from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase\n", + "from aviary.utils.doctape import glue_variable\n", "from aviary.utils.functions import get_path\n", "\n", + "# the descriptions in AviaryProblem class are too much in details for listing. We provide a shortlists.\n", "expected_flow = {\n", - " 'load_inputs':'loads the aviary_values inputs and options that the user specifies.',\n", - " 'check_and_preprocess_inputs':{'desc':'checks the user-supplied input values for any potential problems.',\n", - " 'preprocess_inputs':''},\n", - " 'add_pre_mission_systems':{'desc':'adds pre-mission Systems to the Aviary problem',\n", - " 'get_mass_names':'',\n", - " 'build_pre_mission':''},\n", - " 'add_phases':{'desc':'adds mission phases to the Aviary problem',\n", - " 'get_states':'',\n", - " 'get_constraints':'',\n", - " 'get_controls':'',\n", - " 'get_parameters':'',\n", - " 'build_mission':''},\n", - " 'add_post_mission_systems':{'desc':'adds the post-mission Systems to the Aviary problem',\n", - " 'build_post_mission':''},\n", - " 'link_phases':{'desc':'links variables between phases',\n", - " 'get_linked_variables':'',\n", - " 'get_bus_variables':''},\n", - " 'add_driver':'adds the driver (usually an optimizer)',\n", - " 'add_design_variables':{'desc':'adds the optimization design variables',\n", - " 'get_design_vars':''},\n", - " 'add_objective':'adds the user-selected objective',\n", - " 'setup':{'desc':'sets up the Aviary problem',\n", - " 'get_outputs':'',\n", - " 'define_order':''},\n", - " 'set_initial_guesses':{'desc':'sets the initial guesses for the Aviary problem',\n", - " 'get_initial_guesses':''},\n", - " 'run_aviary_problem':'actually runs the Aviary problem',\n", + " 'load_inputs': 'loads the aviary_values inputs and options that the user specifies and checks them',\n", + " 'add_pre_mission_systems': {\n", + " 'desc': 'adds pre-mission Systems to the Aviary problem',\n", + " 'get_mass_names': '',\n", + " 'build_pre_mission': '',\n", + " },\n", + " 'add_phases': {\n", + " 'desc': 'adds mission phases to the Aviary problem',\n", + " 'get_states': '',\n", + " 'get_constraints': '',\n", + " 'get_controls': '',\n", + " 'get_parameters': '',\n", + " 'needs_mission_solver': '',\n", + " 'build_mission': '',\n", + " },\n", + " 'add_post_mission_systems': {\n", + " 'desc': 'adds the post-mission Systems to the Aviary problem',\n", + " 'build_post_mission': '',\n", + " },\n", + " 'link_phases': {\n", + " 'desc': 'links variables between phases',\n", + " 'get_linked_variables': '',\n", + " 'get_pre_mission_bus_variables': '',\n", + " },\n", + " 'add_driver': 'adds the driver (usually an optimizer)',\n", + " 'add_design_variables': {\n", + " 'desc': 'adds the optimization design variables',\n", + " 'get_design_vars': '',\n", + " },\n", + " 'add_objective': 'adds the user-selected objective',\n", + " 'setup': {'desc': 'sets up the Aviary problem', 'get_outputs': '', 'define_order': ''},\n", + " 'set_initial_guesses': {\n", + " 'desc': 'sets the initial guesses for the Aviary problem',\n", + " 'get_initial_guesses': '',\n", + " },\n", + " 'run_aviary_problem': 'actually runs the Aviary problem',\n", "}\n", "\n", "bulleted_list = ''\n", - "def build_list(dict_of_dicts:dict, layer=0, bulleted_list=''):\n", + "\n", + "\n", + "def build_list(dict_of_dicts: dict, layer=0, bulleted_list=''):\n", " for key, val in dict_of_dicts.items():\n", " # check that the function exists where we expect it\n", - " if layer == 0: getattr(methods_for_level2.AviaryProblem, key)\n", - " else: getattr(SubsystemBuilderBase, key)\n", + " if layer == 0:\n", + " getattr(methods_for_level2.AviaryProblem, key)\n", + " else:\n", + " getattr(SubsystemBuilderBase, key)\n", "\n", - " if isinstance(val,str): desc = val\n", - " elif isinstance(val,dict): desc = val.pop('desc')\n", - " else: desc = str(val)\n", + " if isinstance(val, str):\n", + " desc = val\n", + " elif isinstance(val, dict):\n", + " desc = val.pop('desc')\n", + " else:\n", + " desc = str(val)\n", " # add indents as necessary only add the \"-\" if there is a description\n", - " line = (' '*layer) + '- ' + f'`{key}`' + (f' - {desc}')*(len(desc)>0) + '\\n'\n", + " line = (' ' * layer) + '- ' + f'`{key}`' + (f' - {desc}') * (len(desc) > 0) + '\\n'\n", " bulleted_list += line\n", - " if isinstance(val,dict):\n", - " bulleted_list = build_list(val, layer+1, bulleted_list)\n", + " if isinstance(val, dict):\n", + " bulleted_list = build_list(val, layer + 1, bulleted_list)\n", " return bulleted_list\n", "\n", + "\n", "bulleted_list = build_list(expected_flow)\n", "\n", "glue_variable('expected_flow', bulleted_list, display=True)\n", "glue_variable(SubsystemBuilderBase.__name__, md_code=True)\n", - "glue_variable('methods_for_level2.py',\n", - " str(get_path(methods_for_level2.__file__).name), md_code=True)\n" + "glue_variable(\n", + " 'methods_for_level2.py', str(get_path(methods_for_level2.__file__).name), md_code=True\n", + ")" ] }, { @@ -100,7 +119,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -114,9 +133,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/aviary/docs/user_guide/troubleshooting.ipynb b/aviary/docs/user_guide/troubleshooting.ipynb index 1f1ddea42a..c0128247a6 100644 --- a/aviary/docs/user_guide/troubleshooting.ipynb +++ b/aviary/docs/user_guide/troubleshooting.ipynb @@ -44,7 +44,7 @@ "\n", "```{note}\n", "A \"Verbosity\" control has been added to minimize the amount of unnecessary information that will be displayed. Verbosity settings are discussed in more detail in the developer guide. Mode 0 (QUIET) will suppress practically everything other than warnings and errors. Mode 2 (VERBOSE) will include information such as the progress of the optimization, instead of just a final summary. And mode 3 (DEBUG) will contain detailed information about many of the steps as they happen.\n", - "Some of Aviary's CLI functions, such as \"fortran_to_aviary\", allow the verbosity to be set directly with a command line argument. \"run_mission\" uses the variable \"settings:verbosity\" to control the print levels.\n", + "Some of Aviary's CLI functions, such as \"fortran_to_aviary\", allow the verbosity to be set directly with a command line argument. \"run_mission\" uses the variable \"{glue:md}`setting_VERBOSITY`\" to control the print levels.\n", "```" ] }, @@ -59,24 +59,28 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.interface.cmd_entry_points import _command_map\n", "import argparse\n", + "\n", "from aviary.api import Settings\n", - "from aviary.utils.doctape import check_value, check_contains\n", + "from aviary.interface.cmd_entry_points import _command_map\n", + "from aviary.utils.doctape import check_contains, check_value, glue_variable\n", "\n", - "_command_map['run_mission'];\n", - "check_value(Settings.VERBOSITY,'settings:verbosity')\n", + "_command_map['run_mission']\n", + "check_value(Settings.VERBOSITY, 'settings:verbosity')\n", "\n", "for command in ['fortran_to_aviary']:\n", " parser = argparse.ArgumentParser()\n", " _command_map[command][0](parser)\n", - " actions = [*parser._get_optional_actions(),*parser._get_positional_actions()]\n", + " actions = [*parser._get_optional_actions(), *parser._get_positional_actions()]\n", " check_contains(\n", " 'verbosity',\n", " [action.dest for action in actions],\n", - " f\"{command} does not accept `verbosity` as an argument\",\n", + " f'{command} does not accept `verbosity` as an argument',\n", " AttributeError,\n", - " )" + " )\n", + "\n", + "setting_VERBOSITY = Settings.VERBOSITY\n", + "glue_variable('setting_VERBOSITY', setting_VERBOSITY, md_code=False)" ] }, { @@ -113,7 +117,7 @@ ], "metadata": { "kernelspec": { - "display_name": "latest_env", + "display_name": "av1", "language": "python", "name": "python3" }, @@ -127,7 +131,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/aviary/docs/user_guide/variable_hierarchy.ipynb b/aviary/docs/user_guide/variable_hierarchy.ipynb index 8f213a1341..2b65e370fd 100644 --- a/aviary/docs/user_guide/variable_hierarchy.ipynb +++ b/aviary/docs/user_guide/variable_hierarchy.ipynb @@ -1,5 +1,48 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "import ast\n", + "\n", + "import aviary.api as av\n", + "from aviary.api import Aircraft, Mission\n", + "from aviary.utils.doctape import get_function_names, get_variable_name, glue_variable\n", + "from aviary.variable_info.variables import Aircraft\n", + "\n", + "# glue_variable(\"aircraft:wing:span\", md_code=True) -- This would fail.\n", + "glue_variable('wingspan', Aircraft.Wing.SPAN, md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.ASPECT_RATIO), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.SPAN), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Fuselage.LENGTH), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.HorizontalTail.ROOT_CHORD), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.VerticalTail.ROOT_CHORD), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.VerticalTail.SPAN), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Design.CRUISE_ALTITUDE), md_code=True)\n", + "glue_variable(get_variable_name(Mission.Design.RANGE), md_code=True)\n", + "glue_variable(Aircraft.__name__, md_code=True)\n", + "glue_variable(Mission.__name__, md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing).split('.')[1], md_code=True)\n", + "\n", + "file_path = av.get_path('variable_info/functions.py')\n", + "var_function_names = get_function_names(file_path)\n", + "for function_name in var_function_names:\n", + " glue_variable(function_name + '()', md_code=True)\n", + "\n", + "file_path = av.get_path('utils/functions.py')\n", + "util_function_names = get_function_names(file_path)\n", + "for function_name in util_function_names:\n", + " if function_name not in var_function_names:\n", + " glue_variable(function_name + '()', md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -10,7 +53,7 @@ "\n", "The variable hierarchy itself is rather simple. The variables are broken up into separate high level categories and each category becomes its own top-level class. Within that class we create \"inner classes\" (classes which are an attribute of a higher level class) that encompass a more specific category. If needed, secondary inner classes within an inner class may be created, and so on until the desired detail depth is achieved. However, too many layers down and the tedium will outweigh any value gained through specificity. \n", "\n", - "These classes and inner classes are not used for any sort of complex coding functionality. Instead they simply serve to house model variables themselves. Each class and inner class can have variables assigned to it (in object-oriented speak, the variables become an attribute of the class or inner class), and each variable assigned to a class or inner class corresponds 1-to-1 with a variable needed for the model. The variables in each class are really just identifiers that point to the actual variable name in the model. The value assigned to each variable in the classes is a string that is the name of that variable in the actual model. That string is the variable name that OpenMDAO will see, despite the fact that the user will rarely call the variable by that name. Instead the user will refer to a variable name by its hierarchy variable (eg. referring to `'aircraft:wing:span'` as `Aircraft.Wing.SPAN`) to make it easier to autofill the variable and also to allow more uniform and controlled access to the variable names themselves.\n", + "These classes and inner classes are not used for any sort of complex coding functionality. Instead they simply serve to house model variables themselves. Each class and inner class can have variables assigned to it (in object-oriented speak, the variables become an attribute of the class or inner class), and each variable assigned to a class or inner class corresponds 1-to-1 with a variable needed for the model. The variables in each class are really just identifiers that point to the actual variable name in the model. The value assigned to each variable in the classes is a string that is the name of that variable in the actual model. That string is the variable name that OpenMDAO will see, despite the fact that the user will rarely call the variable by that name. Instead the user will refer to a variable name by its hierarchy variable (eg. referring to `wingspan` as {glue:md}`Aircraft.Wing.SPAN`) to make it easier to autofill the variable and also to allow more uniform and controlled access to the variable names themselves.\n", "\n", "Below is an example of a simple variable hierarchy that includes basic information for an aircraft:" ] @@ -29,7 +72,7 @@ "from aviary.api import Aircraft\n", "from aviary.utils.doctape import check_value\n", "\n", - "check_value(Aircraft.Wing.SPAN,'aircraft:wing:span')" + "check_value(Aircraft.Wing.SPAN, 'aircraft:wing:span')" ] }, { @@ -61,15 +104,29 @@ "\n", " class Wing:\n", " ROOT_CHORD = 'aircraft:wing:root_chord'\n", - " SPAN = 'aircraft:wing:span'\n", - " " + " SPAN = 'aircraft:wing:span'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This code snippet is a notional example of how an overly simple hierarchy looks. In this example the variables all have a depth of three, meaning that all the variables are referred to in three tiers: `Aircraft.Fuselage.LENGTH`, `Aircraft.HorizontalTail.ROOT_CHORD`, `Aircraft.Wing.SPAN`, etc. The variable names in this hierarchy can actually be used to access the values of those variables in an Aviary model, assuming that the hierarchy has been properly provided to the Aviary model. Below is an example of using a variable hierarchy variable in the `add_aviary_input()` and `add_aviary_output()` functions to add inputs and outputs to an OpenMDAO component for use in Aviary." + "This code snippet is a notional example of how an overly simple hierarchy looks. In this example the variables all have a depth of three, meaning that all the variables are referred to in three tiers: {glue:md}`Aircraft.Fuselage.LENGTH`, {glue:md}`Aircraft.HorizontalTail.ROOT_CHORD`, {glue:md}`Aircraft.Wing.SPAN`, etc. The variable names in this hierarchy can actually be used to access the values of those variables in an Aviary model, assuming that the hierarchy has been properly provided to the Aviary model. \n", + "\n", + "There are special rules for the mapping from the input file variable names to the metadata. For example, variable aircraft:wing:aspect_ratio in `aircraft_for_bench_GwGm.csv` is mapped to {glue:md}`Aircraft.Wing.ASPECT_RATIO` in aviary/variable_info/variable_meta_data.py. So, the first part (e.g., `aircraft` or `mission`) is mapped to the same word but with the first letter capitalized (e.g., {glue:md}`Aircraft` or {glue:md}`Mission`). The third word is all caps (e.g., ASPECT_RATIO). The middle part (e.g., wing) is a little more complicated. In most cases, this part capitalizes the first letter (e.g., Wing). The following words have special mappings:\n", + "\n", + "- air_conditioning -> AirConditioning\n", + "- anti_icing -> AntiIcing\n", + "- blended_wing_body -> BWB\n", + "- crew_and_payload -> CrewPayload\n", + "- horizontal_tail -> HorizontalTail\n", + "- landing_gear -> LandingGear\n", + "- tail_boom -> TailBoom\n", + "- vertical_tail -> VerticalTail\n", + "\n", + "This can be summarized as to capitalize the leading letter and to capitalize the first letter after special character “_”.\n", + "\n", + "Below is an example of using a variable hierarchy variable in the {glue:md}`add_aviary_input()` and {glue:md}`add_aviary_output()` functions to add inputs and outputs to an OpenMDAO component for use in Aviary." ] }, { @@ -83,13 +140,29 @@ "outputs": [], "source": [ "import openmdao.api as om\n", + "\n", "import aviary.api as av\n", "\n", + "\n", "class AviaryExampleComponent(om.ExplicitComponent):\n", " def setup(self):\n", - " \n", - " av.add_aviary_input(self, Aircraft.VerticalTail.ROOT_CHORD, val=4, units='ft', desc='chord of the vertical tail')\n", - " av.add_aviary_output(self, Aircraft.VerticalTail.SPAN, val=0, units='ft', desc='span of the vertical tail')" + " av.add_aviary_input(\n", + " self,\n", + " Aircraft.VerticalTail.ROOT_CHORD,\n", + " val=4,\n", + " units='ft',\n", + " desc='chord of the vertical tail',\n", + " )\n", + " av.add_aviary_output(\n", + " self, Aircraft.VerticalTail.SPAN, val=0, units='ft', desc='span of the vertical tail'\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If `units` is not provided, it assumes the `units` in the metadata." ] }, { @@ -105,21 +178,21 @@ "# Testing Cell\n", "from aviary.utils.doctape import check_value\n", "\n", - "Aircraft.Fuselage.LENGTH;\n", - "Aircraft.HorizontalTail.ROOT_CHORD;\n", - "check_value(Aircraft.VerticalTail.ROOT_CHORD,'aircraft:vertical_tail:root_chord')\n", - "check_value(Aircraft.Wing.ROOT_CHORD,'aircraft:wing:root_chord')\n", - "check_value(Aircraft.VerticalTail.SPAN,'aircraft:vertical_tail:span')" + "Aircraft.Fuselage.LENGTH\n", + "Aircraft.HorizontalTail.ROOT_CHORD\n", + "check_value(Aircraft.VerticalTail.ROOT_CHORD, 'aircraft:vertical_tail:root_chord')\n", + "check_value(Aircraft.Wing.ROOT_CHORD, 'aircraft:wing:root_chord')\n", + "check_value(Aircraft.VerticalTail.SPAN, 'aircraft:vertical_tail:span')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In this code snippet the variables `Aircraft.VerticalTail.ROOT_CHORD` and `Aircraft.VerticalTail.SPAN` from the variable hierarchy are used in the `add_aviary_input` and `add_aviary_output` functions to represent the actual variable names, which are `aircraft:vertical_tail:root_chord` and `aircraft:vertical_tail:span` respectively. The point being illustrated here is that you can use the variables from these variable hierarchies just as you would use their string-valued variable names, and in fact you *must* use the variable hierarchy variable and *not* the string-valued variable name. This way, if a change is made to the string-valued variable name in the hierarchy, that change is automatically reflected throughout all your code.\n", + "In this code snippet the variables {glue:md}`Aircraft.VerticalTail.ROOT_CHORD` and {glue:md}`Aircraft.VerticalTail.SPAN` from the variable hierarchy are used in the {glue:md}`add_aviary_input()` and {glue:md}`add_aviary_output()` functions to represent the actual variable names, which are `aircraft:vertical_tail:root_chord` and `aircraft:vertical_tail:span` respectively. The point being illustrated here is that you can use the variables from these variable hierarchies just as you would use their string-valued variable names, and in fact you *must* use the variable hierarchy variable and *not* the string-valued variable name. This way, if a change is made to the string-valued variable name in the hierarchy, that change is automatically reflected throughout all your code.\n", "\n", "## The Aviary-core Variable Hierarchies\n", - "While the idea of a variable hierarchy can be created and used on its own, Aviary-core provides two specific variable hierarchies that are necessary for Aviary-core systems and which follow both the rules of convention and the rules of programmatic necessity laid out above. The two hierarchies provided by Aviary-core are `Aircraft` and `Mission`. `Aircraft` houses all variables that have to do with physical aspects of the aircraft, as well as all variables that do not affect the mission or change in time. This includes several variables that are options in the model instead of inputs or outputs. `Mission` on the other hand houses all variables that reference the mission or change in time. This includes things such as `Mission.Design.CRUISE_ALTITUDE` and `Mission.Design.RANGE` as well as things such as objectives for the optimization, parameters at various phases of flight, etc. The `Aircraft` and `Mission` hierarchies are the only hierarchies provided by Aviary-core, and they are both necessary for the successful running of various Aviary subsystems. Whatever additional or extended variable hierarchies have been created by the user, the end hierarchy *must* include the variables from the `Aircraft` and `Mission` hierarchies in the Aviary core, and these variables must not be altered. We offer more information below on extending and merging together variable hierarchies.\n", + "While the idea of a variable hierarchy can be created and used on its own, Aviary-core provides two specific variable hierarchies that are necessary for Aviary-core systems and which follow both the rules of convention and the rules of programmatic necessity laid out above. The two hierarchies provided by Aviary-core are {glue:md}`Aircraft` and {glue:md}`Mission`. {glue:md}`Aircraft` houses all variables that have to do with physical aspects of the aircraft, as well as all variables that do not affect the mission or change in time. This includes several variables that are options in the model instead of inputs or outputs. {glue:md}`Mission` on the other hand houses all variables that reference the mission or change in time. This includes things such as {glue:md}`Mission.Design.CRUISE_ALTITUDE` and {glue:md}`Mission.Design.RANGE` as well as things such as objectives for the optimization, parameters at various phases of flight, etc. The {glue:md}`Aircraft` and {glue:md}`Mission` hierarchies are the only hierarchies provided by Aviary-core, and they are both necessary for the successful running of various Aviary subsystems. Whatever additional or extended variable hierarchies have been created by the user, the end hierarchy *must* include the variables from the {glue:md}`Aircraft` and {glue:md}`Mission` hierarchies in the Aviary core, and these variables must not be altered. We offer more information below on extending and merging together variable hierarchies.\n", "\n", "For a complete list of the variables included in the Aviary-core hierarchy visit the [Variable Metadata doc page](../user_guide/variable_metadata). The hierarchies themselves are located [here](https://github.com/OpenMDAO/Aviary/blob/main/aviary/variable_info/variables.py) in the repository and can be accessed in this way:" ] @@ -137,8 +210,8 @@ "# Testing Cell\n", "from aviary.api import Aircraft, Mission\n", "\n", - "Mission.Design.CRUISE_ALTITUDE;\n", - "Mission.Design.RANGE;" + "Mission.Design.CRUISE_ALTITUDE\n", + "Mission.Design.RANGE" ] }, { @@ -171,14 +244,14 @@ "- All variables in the hierarchy have a depth of 3. This is optional, but again we follow this convention within the Aviary-core variable hierarchy to preserve cleanliness and uniformity of code.\n", "- Including colons after all words in the string-valued variable name is optional. As stated above, it is a must after the first word for use in promotion statements, but after that it is purely a choice of convention to preserve clarity.\n", "\n", - "It is prudent at this point to pause and explain what is meant by *hierarchy type*. This is not a technical coding in term, instead *type* is an explanatory term that we use to describe the classification of a hierarchy. A hierarchy's type is its high level category. For example, a hierarchy of the `Aircraft` type would be a hierarchy that houses the variables that have to do with the physical aspects of an aircraft, and a hierarchy of the `Mission` type would be a hierarchy that houses the variables which reference the mission or change in time. These are the only two types of hierarchies that are provided in Aviary-core, however, other types are possible, such as a `Fleet` type hierarchy describing the variables that affect an entire fleet of aircraft, an `AirTrafficControl` type hierarchy describing all the variables having to do with air traffic control, etc. The concept of the `Aircraft` and `Mission` type hierarchies will be used throughout the rest of this article.\n", + "It is prudent at this point to pause and explain what is meant by *hierarchy type*. This is not a technical coding in term, instead *type* is an explanatory term that we use to describe the classification of a hierarchy. A hierarchy's type is its high level category. For example, a hierarchy of the {glue:md}`Aircraft` type would be a hierarchy that houses the variables that have to do with the physical aspects of an aircraft, and a hierarchy of the {glue:md}`Mission` type would be a hierarchy that houses the variables which reference the mission or change in time. These are the only two types of hierarchies that are provided in Aviary-core, however, other types are possible, such as a `Fleet` type hierarchy describing the variables that affect an entire fleet of aircraft, an `AirTrafficControl` type hierarchy describing all the variables having to do with air traffic control, etc. The concept of the {glue:md}`Aircraft` and {glue:md}`Mission` type hierarchies will be used throughout the rest of this article.\n", "\n", "\n", "## Building Your Own Hierarchy\n", - "The Aviary-core provides the pre-built variable hierarchies listed above. However, for the user that would like to add external subsystems to Aviary, the variables in the Aviary-core hierarchies may not be sufficient. In this case, there are three options: 1) extend the existing variable hierarchies from Aviary-core, 2) create your own variable hierarchies and merge them with the existing hierarchies from Aviary-core, 3) do a combination of #1 and #2. Extending a creating your own variable hierarchies are addressed below.\n", + "The Aviary-core provides the pre-built variable hierarchies listed above. However, for the user that would like to add external subsystems to Aviary, the variables in the Aviary-core hierarchies may not be sufficient. In this case, there are three options: 1) extend the existing variable hierarchies from Aviary-core, 2) create your own variable hierarchies and merge them with the existing hierarchies from Aviary-core, 3) do a combination of #1 and #2. Extending and creating your own variable hierarchies are addressed below.\n", "\n", "### Extend the Existing Aviary-core Hierarchies\n", - "If you are just adding one external subsystem to an Aviary-core model, or if you are adding multiple subsystems all being developed in the same location by the same person, our suggested path is to create one extension of the Aviary-core hierarchies. The method to extend the Aviary-core variable hierarchies is to subclass those hierarchies (which preserves all the data from the original hierarchies) and add your own additional variables as necessary. To take a simple example, let's say we wanted to add a little bit of detail to the existing `Aircraft` variable hierarchy for our external subsystem. The detail we would like to add is some information about the flaps on the wing as well as a jury strut and a center of gravity location. We would extend the existing variable hierarchy using the following code:" + "If you are just adding one external subsystem to an Aviary-core model, or if you are adding multiple subsystems all being developed in the same location by the same person, our suggested path is to create one extension of the Aviary-core hierarchies. The method to extend the Aviary-core variable hierarchies is to subclass those hierarchies (which preserves all the data from the original hierarchies) and add your own additional variables as necessary. To take a simple example, let's say we wanted to add a little bit of detail to the existing {glue:md}`Aircraft` variable hierarchy for our external subsystem. The detail we would like to add is some information about the flaps on the wing as well as a jury strut and a center of gravity location. We would extend the existing variable hierarchy using the following code:" ] }, { @@ -191,8 +264,8 @@ "\n", "AviaryAircraft = av.Aircraft\n", "\n", - "class Aircraft(AviaryAircraft):\n", "\n", + "class Aircraft(AviaryAircraft):\n", " CG = 'aircraft:center_of_gravity'\n", "\n", " class Wing(AviaryAircraft.Wing):\n", @@ -209,12 +282,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "There are a few things to notice about this code. The first is that, unlike the Aviary-core `Aircraft` variable hierarchy, this hierarchy has variables with a depth of two and a depth of four. When we extend the Aviary-core variable hierarchies we are not restricted to the depth of three that the core hierarchies have. The second thing to notice is that when we extend an inner class that already exists in the Aviary-core hierarchy (`Wing`) we subclass the inner class from the Aviary-core so that we can preserve all the information from that Aviary-core inner class. However, in the case of the inner class `Jury` which does not already exist in the Aviary-core hierarchy, there is nothing to subclass, and thus that inner class stands on its own.\n", + "There are a few things to notice about this code. The first is that, unlike the Aviary-core {glue:md}`Aircraft` variable hierarchy, this hierarchy has variables with a depth of two and a depth of four. When we extend the Aviary-core variable hierarchies we are not restricted to the depth of three that the core hierarchies have. The second thing to notice is that when we extend an inner class that already exists in the Aviary-core hierarchy ({glue:md}`Wing`) we subclass the inner class from the Aviary-core so that we can preserve all the information from that Aviary-core inner class. However, in the case of the inner class `Jury` which does not already exist in the Aviary-core hierarchy, there is nothing to subclass, and thus that inner class stands on its own.\n", "\n", "When extending the Aviary-core variable hierarchies, you can create one extension of each type of hierarchy, or you can create multiple extensions of each type which will eventually be merged together. If you are developing only one external subsystem or all your subsystems are being developed in the same place by the same person, one extension of each Aviary-core hierarchy should suffice. However, if you have multiple developers working on different subsystems in different locations, each developer may want to create their own extension. To aid in this case, Aviary provides the capability to merge together multiple hierarchies of the same type into one hierarchy of that type. More information on this capability is shown at the bottom of this page.\n", "\n", "### Creating Your Own Variable Hierarchy\n", - "It is possible to create your own variable hierarchy that is not an extension of the Aviary-core variable hierarchies, but there are specific things to know. The use case for this is mostly when you would like to create a third hierarchy that does not fall under either the `Aircraft` or the `Mission` categories. An example of this might be if you are doing fleet-level analyses and would like a `Fleet` variable hierarchy.\n", + "It is possible to create your own variable hierarchy that is not an extension of the Aviary-core variable hierarchies, but there are specific things to know. The use case for this is mostly when you would like to create a third hierarchy that does not fall under either the {glue:md}`Aircraft` or the {glue:md}`Mission` categories. An example of this might be if you are doing fleet-level analyses and would like a `Fleet` variable hierarchy.\n", "\n", "A new variable hierarchy can be created in exactly the same manner that Aviary-core creates its own variable hierarchies, illustrated above. For the case of creating a new `Fleet` variable hierarchy, it might look something like this:" ] @@ -245,17 +318,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Usually if you are creating your own variable hierarchy that is not an extension of the Aviary-core hierarchies it will be because you want a hierarchy that is not of the type `Aircraft` or `Mission`. In this case, your new hierarchy is relatively straightforward, you can create it and simply provide it to Aviary along with the core hierarchies or extensions thereof. However, if you are creating your own variable hierarchy that is of the type `Aircraft` or `Mission` but is not an extension of the Aviary-core hierarchies (which we do not recommend doing), there are a few things to keep in mind:\n", + "Usually if you are creating your own variable hierarchy that is not an extension of the Aviary-core hierarchies it will be because you want a hierarchy that is not of the type {glue:md}`Aircraft` or {glue:md}`Mission`. In this case, your new hierarchy is relatively straightforward, you can create it and simply provide it to Aviary along with the core hierarchies or extensions thereof. However, if you are creating your own variable hierarchy that is of the type {glue:md}`Aircraft` or {glue:md}`Mission` but is not an extension of the Aviary-core hierarchies (which we do not recommend doing), there are a few things to keep in mind:\n", "- The newly created variable hierarchy does not have any of the information from the Aviary-core hierarchy. You *must* still provide Aviary with the input values and information from the Aviary-core hierarchy, or all the inputs will be set to their default values which are unlikely to suit your needs.\n", " + You can merge together all variable hierarchies that are of the same type (see below).\n", "- You should avoid adding variables to your created hierarchy that already exist in the Aviary-core hierarchy, as this may cause conflicts when merging hierarchies together.\n", "\n", - "In general, we recommend extending the Aviary-core variable hierarchies whenever possible, and only creating a new hierarchy from scratch when the categories of `Aircraft` and `Mission` do not fit your needs.\n", + "In general, we recommend extending the Aviary-core variable hierarchies whenever possible, and only creating a new hierarchy from scratch when the categories of {glue:md}`Aircraft` and {glue:md}`Mission` do not fit your needs.\n", "\n", "## Merging Extended Hierarchies\n", "As briefly mentioned above, when there are multiple variable hierarchies of the same type we need the ability to merge them together into one hierarchy of that type which includes all the information from the different hierarchies. Aviary provides this capability through the `merge_hierarchies()` method. The goal of this method is to clean up all the user hierarchies so that Aviary can be provided with only one hierarchy of each type, and also to resolve any discrepancies between different hierarchies of the same type.\n", "\n", - "Using the [`merge_hierarchies()` function](../theory_guide/merging_syntax) is quite simple. It takes a list of all the hierarchies you would like to merge together and returns one hierarchy that has the merged information from all the input hierarchies, as in this snippet of code where we are merging together three notional `Aircraft` type hierarchies:" + "Using the [`merge_hierarchies()` function](../theory_guide/merging_syntax) is quite simple. It takes a list of all the hierarchies you would like to merge together and returns one hierarchy that has the merged information from all the input hierarchies, as in this snippet of code where we are merging together three notional {glue:md}`Aircraft` type hierarchies:" ] }, { @@ -287,6 +360,7 @@ "outputs": [], "source": [ "import aviary.api as av\n", + "\n", "FullAircraft = av.merge_hierarchies([Aircraft1, Aircraft2, Aircraft3])" ] }, @@ -309,11 +383,8 @@ ], "metadata": { "celltoolbar": "Tags", - "interpreter": { - "hash": "e6c7471802ed76737b16357fb02af5587f3a4cbee5ea7658f3f9a6981469039b" - }, "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -327,7 +398,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.3" }, "orphan": true }, diff --git a/aviary/docs/user_guide/variable_metadata.ipynb b/aviary/docs/user_guide/variable_metadata.ipynb index 15fea1c3b4..db0c8f231a 100644 --- a/aviary/docs/user_guide/variable_metadata.ipynb +++ b/aviary/docs/user_guide/variable_metadata.ipynb @@ -1,5 +1,32 @@ { "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "from aviary.api import Aircraft\n", + "from aviary.utils.develop_metadata import add_meta_data\n", + "from aviary.utils.doctape import get_variable_name, glue_function_arguments, glue_variable\n", + "\n", + "current_glued_vars = []\n", + "\n", + "# Retrieve all arguments from a function\n", + "glue_function_arguments(add_meta_data, current_glued_vars)\n", + "\n", + "glue_variable(get_variable_name(Aircraft.Wing.MASS_SCALER), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft), md_code=True)\n", + "glue_variable(get_variable_name(Aircraft.Wing.SPAN), md_code=False)\n", + "glue_variable('utils/develop_metadata.py', md_code=False)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -9,16 +36,36 @@ "\n", "Every variable in an Aviary variable hierarchy must have metadata associated with it. This metadata is used for setting initial values, setting Aviary inputs and outputs, and various other functionalities throughout the code. It is also helpful information for the user to have regarding each variable and the metadata dictionary allows all that information to live in one organized location. Unlike variable hierarchies, which are broken up into different categories based on the type of information they contain, the variable metadata all lives in the same dictionary, regardless of which variable hierarchy its variables come from.\n", "\n", - "The variable metadata dictionary is exactly what it sounds like: a Python dictionary, or more explicitly a Python dictionary of dictionaries. The entire metadata is one dictionary, and within that metadata dictionary each variable has its own sub-dictionary including all the information relevant to that variable. The information included in each sub-dictionary is:\n", + "The variable metadata dictionary is exactly what it sounds like: a Python dictionary, or more explicitly a Python dictionary of dictionaries. The entire metadata is one dictionary, and within that metadata dictionary each variable (the {glue:md}`key`) has its own sub-dictionary including all the information relevant to that variable. The information included in each sub-dictionary is:\n", + "\n", + "| Key Name in Metadata | Default Value | Information |\n", + "| -------------------------- | ------------- | --------------------------- |\n", + "| {glue:md}`key` | `None` | Name |\n", + "| {glue:md}`units` | `unitless` | Units |\n", + "| {glue:md}`default_value` | `0.0` | Default Value |\n", + "| {glue:md}`types` | `None` | Type Restrictions |\n", + "| {glue:md}`multivalue` | `False` | Can variable be vectorized? |\n", + "| {glue:md}`option` | `False` | Is Option? |\n", + "| {glue:md}`desc` | `None` | Description |\n", + "| {glue:md}`historical_name` | `None` | Historical Variable Name(s) |\n", + "\n", + "Many of these variables are self-explanatory, but many require additional discussion.\n", + "\n", + "`key` is the variable name, which must be a string compatible with OpenMDAO's variable name rules. Units must be a string, also compatible with OpenMDAO's list of supported units.\n", + "\n", + "`default_value` is what Aviary will use if the variable is not provided by the user as an input or does not come from another part of the problem (computed by another component, provided by Dymos as a state/control/timeseries , etc.)\n", + "\n", + "`types` is a Python type or tuple of types that this variable is allowed to be. If not provided, `types` defaults to the type of `default_value` (which in turn is defaulted to a float).\n", + "\n", + "`multivalue` is a boolean flag that tells Aviary if this variable can be a iterable (typically a list, numpy array, or tuple). If this flag is True, those iterable types are also allowable types in addition to whatever is listed in `types`. When doing type checks, Aviary will check the value of each index in a provided iterable against `types`. So if your variable is expected to be a list of floats, then `types` should be set to float, and `multivalue` should be True. If you provide an iterable type in `types` while multivalue is True, then you are telling Aviary that you can have a multidimensional array (e.g. a list that contains lists). Expected array size is not set in metadata, but instead in OpenMDAO system definition, when inputs/outputs/options are added to the system.\n", + "\n", + "If `multivalue` is False and an iterable type is given in `types`, then Aviary will not know how to enforce type checks for values inside the iterable! Any iterable that matches `types` will pass, regardless of what it contains - this is technically fine, but opens you up to an accidental TypeError later down the line. We don't reccomend setting up variables like this. In general, only add iterable types to `types` if you are working with multidimensional arrays.\n", + "\n", + "`option` is a boolean flag if your variable is used as an OpenMDAO option, rather than a component input or output. Set this flag to True to ensure your variable correctly gets connected to any components that ask for it through options.\n", + "\n", + "`desc` is a string that should describe what the variable represents, how it is used, and any other information that would be helpful for an aircraft designer setting a value for that variable in their input file.\n", "\n", - "| Information | Default Value | Key Name in Metadata |\n", - "| --------------------------- | ------------- | -------------------- |\n", - "| Units | `unitless` | units |\n", - "| Description | `None` | desc |\n", - "| Default Value | `0.0` | default_value |\n", - "| Is Option? | `False` | option |\n", - "| Type Restrictions | `None` | types |\n", - "| Historical Variable Name(s) | `None` | historical_name |" + "`historical_name` is a dictionary that connects this variable with any potential matching variables in legacy codes Aviary inherrited from. Variable names under the keys FLOPS or GASP will be used by the `fortran_to_aviary` input file conversion utility to attempt to match legacy input files with Aviary variables." ] }, { @@ -40,21 +87,21 @@ " 'desc': None,\n", " 'default_value': 0.0,\n", " 'option': False,\n", - " 'types': None,\n", + " 'types': float,\n", " 'historical_name': None,\n", - " }\n", + " 'multivalue': False,\n", + "}\n", "\n", "meta_data = {}\n", - "add_meta_data('testing',meta_data)\n", - "check_value(meta_data['testing'], expected_meta_data)\n", - "\n" + "add_meta_data('testing', meta_data)\n", + "check_value(meta_data['testing'], expected_meta_data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The information in the metadata dictionary is accessed just like information in any other Python dictionary. For example, if you wanted to know the units of the `Aircraft.Wing.SPAN` variable from the Aviary-core `Aircraft` variable hierarchy along with whether or not the variable was an option, you would access those units using the following code:" + "The information in the metadata dictionary is accessed just like information in any other Python dictionary. For example, if you wanted to know the units of the {glue:md}`Aircraft.Wing.SPAN` variable from the Aviary-core {glue:md}`Aircraft` variable hierarchy along with whether or not the variable was an option, you would access those units using the following code:" ] }, { @@ -75,14 +122,14 @@ "wingspan_is_option = av.CoreMetaData[AviaryAircraft.Wing.SPAN]['option']\n", "\n", "print(wingspan_units)\n", - "print(wingspan_is_option)\n" + "print(wingspan_is_option)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In this example we use the variable hierarchy to provide the name of the variable we are seeking to Aviary's `CoreMetaData`, and we use the keys from the metadata dictionary to provide the specific information that we would like to know. This would return" + "In this example we use the variable hierarchy to provide the name of the variable we are seeking to Aviary's {glue:md}`CoreMetaData`, and we use the keys from the metadata dictionary to provide the specific information that we would like to know. This would return" ] }, { @@ -95,8 +142,10 @@ }, "outputs": [], "source": [ - "import aviary.api as av\n", "import warnings\n", + "\n", + "import aviary.api as av\n", + "\n", "warnings.filterwarnings('ignore')\n", "\n", "AviaryAircraft = av.Aircraft\n", @@ -105,19 +154,19 @@ "wingspan_is_option = av.CoreMetaData[AviaryAircraft.Wing.SPAN]['option']\n", "\n", "print(wingspan_units)\n", - "print(wingspan_is_option)\n" + "print(wingspan_is_option)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "which tells you that the units of the variable Aircraft.Wing.SPAN from the Aviary-core `Aircraft` variable hierarchy are feet, and that Aircraft.Wing.SPAN is not an option.\n", + "which tells you that the units of the variable {glue:md}`Aircraft.Wing.SPAN` from the Aviary-core {glue:md}`Aircraft` variable hierarchy are feet, and that {glue:md}`Aircraft.Wing.SPAN` is not an option.\n", "\n", "```{note}\n", "Many of the weight and aerodynamic estimating relationships in Aviary originated from historical codes called GASP and FLOPS. For engineers who are familiar with GASP and FLOPS it is helpful to know what an Aviary variable was called in those historical codes.\n", "\n", - "The historical variable name portion of the metadata allows us to associate any names that an Aviary variable may have had in a previous code. This piece of the metadata is actually a dictionary within each subdictionary belonging to each variable. This dictionary is used by adding an entry for each historical code, where the key is the name of the historical code, and the value for that key is a string or list of strings illustrating the name(s) that variable held in the historic code. This is an optional feature, but can be helpful for users who are porting old codes into new formats. If a tilde (~) is attached to a historical variable, it is a local variable or parameter in GASP or FLOPS. More details about the naming convention is described in `utils/develop_metadata.py`.\n", + "The historical variable name portion of the metadata allows us to associate any names that an Aviary variable may have had in a previous code. This piece of the metadata is actually a dictionary within each subdictionary belonging to each variable. This dictionary is used by adding an entry for each historical code, where the key is the name of the historical code, and the value for that key is a string or list of strings illustrating the name(s) that variable held in the historic code. This is an optional feature, but can be helpful for users who are porting old codes into new formats. If a tilde (~) is attached to a historical variable, it is a local variable or parameter in GASP or FLOPS. More details about the naming convention is described in {glue:md}`utils/develop_metadata.py`.\n", "```\n", "\n", "## The Aviary-core Metadata\n", @@ -149,11 +198,11 @@ "## Building Your Own Metadata\n", "Unlike the variable hierarchies, which are separated out into different hierarchies for different types of data, there is only one metadata dictionary for all variables in every variable hierarchy. Technically the user may build a metadata dictionary from scratch instead of extending the Aviary-core metadata, however, there is no real value to this as you will eventually have to merge back in the Aviary-core metadata anyway, so there are no normal circumstances under which this is the recommended practice. However, just like with variable hierarchies, you can have several different metadata dictionaries which will eventually be merged together. This may be necessary when there are multiple people developing different external subsystems in different locations.\n", "\n", - "There are two different ways to change the metadata in a metadata dictionary. The first is to add a new variable to the dictionary, and add that variable's metadata along with it. This makes use of the `add_meta_data()` function. This function takes in the variable name of the variable to be added to the metadata dictionary be provided, as well as the dictionary itself that the variable should be added to. It also optionally takes in all of the metadata information listed at the beginning of this page. The function returns nothing, but it internally updates the provided metadata dictionary so that dictionary will contain the new variable and its metadata.\n", + "There are two different ways to change the metadata in a metadata dictionary. The first is to add a new variable to the dictionary, and add that variable's metadata along with it. This makes use of the {glue:md}`add_meta_data()` function. This function takes in the variable name of the variable to be added to the metadata dictionary be provided, as well as the dictionary itself that the variable should be added to. It also optionally takes in all of the metadata information listed at the beginning of this page. The function returns nothing, but it internally updates the provided metadata dictionary so that dictionary will contain the new variable and its metadata.\n", "\n", - "The second way to change the metadata in a metadata dictionary is by updating the metadata associated with a variable that is already in the dictionary. This is accomplished using the `update_meta_data()` function. This function behaves almost identically to the `add_meta_data()` function, the only difference being that instead of adding a new variable to the dictionary, it will take the input of metadata information that you provide and overwrite the old metadata of the given variable with the new metadata.\n", + "The second way to change the metadata in a metadata dictionary is by updating the metadata associated with a variable that is already in the dictionary. This is accomplished using the {glue:md}`update_meta_data()` function. This function behaves almost identically to the {glue:md}`add_meta_data()` function, the only difference being that instead of adding a new variable to the dictionary, it will take the input of metadata information that you provide and overwrite the old metadata of the given variable with the new metadata.\n", "\n", - "There are two pitfalls that may occur when using these functions. The first pitfall is attempting to call the `add_meta_data()` function for a variable that already exists in the metadata. This will throw an error, because the `add_meta_data()` function is only for new variables to the metadata. Conversely, attempting to update the metadata of a variable that is not in the metadata dictionary via `update_meta_data()` will throw an error because that function is only for variables that already exist in the metadata.\n", + "There are two pitfalls that may occur when using these functions. The first pitfall is attempting to call the {glue:md}`add_meta_data()` function for a variable that already exists in the metadata. This will throw an error, because the {glue:md}`add_meta_data()` function is only for new variables to the metadata. Conversely, attempting to update the metadata of a variable that is not in the metadata dictionary via {glue:md}`update_meta_data()` will throw an error because that function is only for variables that already exist in the metadata.\n", "\n", "The methods outlined above for updating and adding to the variable metadata are the crux of how the variable metadata can be extended for new variables. The user will simply import the existing Aviary-core metadata and add to it as they see fit.\n", "\n", @@ -161,7 +210,7 @@ "The variable metadata dictionary that is imported from the Aviary API is actually a copy of the original Aviary metadata dictionary to avoid mutating the original dictionary. That being said, it functions just as a metadata dictionary that you would input to an Aviary model and you can extend it or input it to a model as-is depending on your needs.\n", "```\n", "\n", - "Lets examine how we would extend the variable metadata dictionary in practice. Say we have just extended the Aviary-core `Aircraft` variable hierarchy to add some center of gravity, flap, and jury strut information using the extension below:" + "Lets examine how we would extend the variable metadata dictionary in practice. Say we have just extended the Aviary-core {glue:md}`Aircraft` variable hierarchy to add some center of gravity, flap, and jury strut information using the extension below:" ] }, { @@ -175,7 +224,10 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.develop_metadata import add_meta_data, update_meta_data" + "from aviary.utils.develop_metadata import add_meta_data, update_meta_data\n", + "\n", + "glue_variable(get_variable_name(add_meta_data) + '()', md_code=True)\n", + "glue_variable(get_variable_name(update_meta_data) + '()', md_code=True)" ] }, { @@ -192,8 +244,8 @@ "\n", "AviaryAircraft = av.Aircraft\n", "\n", - "class ExtendedAircraft(AviaryAircraft):\n", "\n", + "class ExtendedAircraft(AviaryAircraft):\n", " CG = 'aircraft:center_of_gravity'\n", "\n", " class Wing(AviaryAircraft.Wing):\n", @@ -240,7 +292,7 @@ " units='ft**2',\n", " desc='planform area of flap',\n", " default_value=10,\n", - " option=False\n", + " option=False,\n", ")\n", "\n", "av.add_meta_data(\n", @@ -249,7 +301,7 @@ " units='ft',\n", " desc='chord of flap at root of wing',\n", " default_value=1,\n", - " option=False\n", + " option=False,\n", ")\n", "\n", "av.add_meta_data(\n", @@ -258,7 +310,7 @@ " units='ft',\n", " desc='span of flap',\n", " default_value=60,\n", - " option=False\n", + " option=False,\n", ")\n", "\n", "av.add_meta_data(\n", @@ -267,20 +319,76 @@ " units='kg',\n", " desc='mass of jury strut',\n", " default_value=50,\n", - " option=False\n", + " option=False,\n", ")" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "from aviary.variable_info.variable_meta_data import CoreMetaData\n", + "\n", + "glue_variable(get_variable_name(CoreMetaData), md_code=True)\n", + "glue_variable(get_variable_name(ExtendedAircraft), md_code=True)\n", + "glue_variable(get_variable_name(ExtendedMetaData), md_code=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "\n", + "import os\n", + "\n", + "import aviary.api as av\n", + "from aviary.utils.doctape import get_function_names, glue_variable\n", + "\n", + "folder = av.get_path('utils')\n", + "\n", + "utils_dir = folder.relative_to(av.top_dir)\n", + "\n", + "file_path = os.path.join(utils_dir, 'merge_hierarchies.py')\n", + "glue_variable(file_path, md_code=False)\n", + "file_path = av.get_path(file_path)\n", + "function_names_hierarchies = get_function_names(file_path)\n", + "for function_name in function_names_hierarchies:\n", + " glue_variable(function_name + '()', md_code=True)\n", + "\n", + "file_path = os.path.join(utils_dir, 'merge_variable_metadata.py')\n", + "glue_variable(file_path, md_code=False)\n", + "file_path = av.get_path(file_path)\n", + "\n", + "file_path = av.get_path(file_path)\n", + "function_names_metadata = get_function_names(file_path)\n", + "for function_name in function_names_metadata:\n", + " glue_variable(function_name + '()', md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "`ExtendedMetaData` now contains the metadata of all the Aviary-core variables along with the metadata information that we just added.\n", + "{glue:md}`ExtendedMetaData` now contains the metadata of all the Aviary-core variables along with the metadata information that we just added.\n", "\n", "## Merging Independent Metadata\n", - "Extending the metadata is great, but sometimes users will end up with multiple metadata dictionaries because different subsystem developers extended the metadata (and created associated variable hierarchies) to suit their own needs. Aviary needs to be given one single metadata dictionary which contains metadata of all the variables it has been given, so we need to be able to merge together multiple metadata dictionaries into one. The `merge_meta_data()` function has been provided to combine all the different metadata into one. The `merge_meta_data()` function behaves quite similarly to the `merge_hierarchies()` function. It takes in a string of metadata dictionaries that need to be merged together, and it returns a single metadata dictionary containing the metadata from all the individual dictionaries.\n", + "Extending the metadata is great, but sometimes users will end up with multiple metadata dictionaries because different subsystem developers extended the metadata (and created associated variable hierarchies) to suit their own needs. Aviary needs to be given one single metadata dictionary which contains metadata of all the variables it has been given, so we need to be able to merge together multiple metadata dictionaries into one. The {glue:md}`merge_meta_data()` function has been provided to combine all the different metadata into one. The {glue:md}`merge_meta_data()` function behaves quite similarly to the {glue:md}`merge_hierarchies()` function. It takes in a string of metadata dictionaries that need to be merged together, and it returns a single metadata dictionary containing the metadata from all the individual dictionaries.\n", "\n", - "Let's say that we have created our `ExtendedAircraft` and `ExtendedMetaData` from above, and that elsewhere we have a subsystem that requires information about engine cooling system mass as well as whether the aircraft has winglets. Below is the buildup of the `Aircraft` type hierarchy and the metadata for our new subsystem:" + "Let's say that we have created our {glue:md}`ExtendedAircraft` and {glue:md}`ExtendedMetaData` from above, and that elsewhere we have a subsystem that requires information about engine cooling system mass as well as whether the aircraft has winglets. Below is the buildup of the {glue:md}`Aircraft` type hierarchy and the metadata for our new subsystem:" ] }, { @@ -294,8 +402,8 @@ "outputs": [], "source": [ "# Testing Cell\n", - "from aviary.utils.merge_variable_metadata import merge_meta_data\n", - "from aviary.utils.merge_hierarchies import merge_hierarchies" + "from aviary.utils.merge_hierarchies import merge_hierarchies\n", + "from aviary.utils.merge_variable_metadata import merge_meta_data" ] }, { @@ -310,16 +418,16 @@ "source": [ "import aviary.api as av\n", "\n", - "class ExtendedAircraft2(av.Aircraft):\n", "\n", + "class ExtendedAircraft2(av.Aircraft):\n", " class Engine(av.Aircraft.Engine):\n", - "\n", " class Cooling:\n", " MASS = 'aircraft:engine:cooling:mass'\n", "\n", " class Wing(av.Aircraft.Wing):\n", " WINGLETS = 'aircraft:wing:winglets'\n", "\n", + "\n", "ExtendedMetaData2 = av.CoreMetaData\n", "\n", "av.add_meta_data(\n", @@ -343,11 +451,26 @@ ")" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-output" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "glue_variable(get_variable_name(ExtendedAircraft2), md_code=True)\n", + "glue_variable(get_variable_name(ExtendedMetaData2), md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We can see from the above code that we have an `Aircraft` type variable hierarchy named `ExtendedAircraft2` and that we have created our own metadata dictionary `ExtendedMetaData2` which is an extension of the `CoreMetaData` dictionary in Aviary-core. Now we have two different `Aircraft` type variable hierarchy extensions, `ExtendedAircraft` and `ExtendedAircraft2`. We also have two different metadata extensions, `ExtendedMetaData` and `ExtendedMetaData2`. We need a single `Aircraft` type variable hierarchy, and single metadata dictionary. Thus, we will use the merging functions built into Aviary:" + "We can see from the above code that we have an {glue:md}`Aircraft` type variable hierarchy named {glue:md}`ExtendedAircraft2` and that we have created our own metadata dictionary {glue:md}`ExtendedMetaData2` which is an extension of the {glue:md}`CoreMetaData` dictionary in Aviary-core. Now we have two different {glue:md}`Aircraft` type variable hierarchy extensions, {glue:md}`ExtendedAircraft` and {glue:md}`ExtendedAircraft2`. We also have two different metadata extensions, {glue:md}`ExtendedMetaData` and {glue:md}`ExtendedMetaData2`. We need a single {glue:md}`Aircraft` type variable hierarchy, and single metadata dictionary. Thus, we will use the merging functions built into Aviary:" ] }, { @@ -364,11 +487,26 @@ "FinalMetaData = av.merge_meta_data([ExtendedMetaData, ExtendedMetaData2])" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Testing Cell\n", + "glue_variable(get_variable_name(FinalAircraft), md_code=True)\n", + "glue_variable(get_variable_name(FinalMetaData), md_code=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Above we merged together our hierarchy and metadata extensions, and now we have one single `Aircraft` type hierarchy `FinalAircraft` and one single metadata dictionary `FinalMetaData` which we can provide to the Aviary model.\n", + "Above we merged together our hierarchy and metadata extensions, and now we have one single {glue:md}`Aircraft` type hierarchy {glue:md}`FinalAircraft` and one single metadata dictionary {glue:md}`FinalMetaData` which we can provide to the Aviary model.\n", "\n", "There is one situation when an attempt to merge together multiple metadata dictionaries will cause errors, and that situation is if more than one metadata dictionary contains the same variable with different metadata. If multiple dictionaries contain the same variable with identical metadata the merge will proceed, but if the metadata differs at all the merge will halt and force the user to rectify the discrepancy.\n", "\n", @@ -402,17 +540,17 @@ "outputs": [], "source": [ "try:\n", - " from itables import init_notebook_mode\n", - " from itables import show\n", + " from itables import init_notebook_mode, show\n", "except:\n", - " print(\"Warning: itables is not installed.\")\n", - " print(\"To install itables, run the following command:\")\n", - " print(\"pip install itables\")\n", + " print('Warning: itables is not installed.')\n", + " print('To install itables, run the following command:')\n", + " print('pip install itables')\n", "\n", "else:\n", - " import pandas as pd\n", " from copy import deepcopy\n", "\n", + " import pandas as pd\n", + "\n", " init_notebook_mode(all_interactive=True)\n", "\n", " # Your complex dictionary\n", @@ -424,7 +562,7 @@ " row = {'variable name': key}\n", " for k, v in value.items():\n", " if k == 'historical_name' and v is not None:\n", - " value[k] = '
'.join([f\"{k2}: {v2}\" for k2, v2 in v.items()])\n", + " value[k] = '
'.join([f'{k2}: {v2}' for k2, v2 in v.items()])\n", " row.update(value)\n", " transformed_data.append(row)\n", "\n", @@ -437,17 +575,22 @@ " columns.append('historical_name')\n", " df = df.reindex(columns=columns)\n", "\n", - " show(df, scrollY=\"600px\", scrollCollapse=True, paging=False, classes=\"display compact\", columnDefs=[{\"width\": \"120px\", \"className\": \"dt-left\", \"targets\": \"_all\"}], scrollX=True)\n" + " show(\n", + " df,\n", + " scrollY='600px',\n", + " scrollCollapse=True,\n", + " paging=False,\n", + " classes='display compact',\n", + " columnDefs=[{'width': '120px', 'className': 'dt-left', 'targets': '_all'}],\n", + " scrollX=True,\n", + " )" ] } ], "metadata": { "celltoolbar": "Tags", - "interpreter": { - "hash": "e6c7471802ed76737b16357fb02af5587f3a4cbee5ea7658f3f9a6981469039b" - }, "kernelspec": { - "display_name": "Python 3", + "display_name": "aviary", "language": "python", "name": "python3" }, @@ -461,7 +604,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.12.8" }, "orphan": true }, diff --git a/aviary/examples/example_phase_info.py b/aviary/examples/example_phase_info.py deleted file mode 100644 index 53b5d04d84..0000000000 --- a/aviary/examples/example_phase_info.py +++ /dev/null @@ -1,79 +0,0 @@ -phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.2, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.18, 0.74), "unitless"), - "initial_altitude": (0.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((0.0, 34000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((64.0, 192.0), "min"), - }, - "initial_guesses": {"time": ([0, 128], "min")}, - }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (34000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((56.5, 169.5), "min"), - }, - "initial_guesses": {"time": ([128, 113], "min")}, - }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.36, "unitless"), - "mach_bounds": ((0.34, 0.74), "unitless"), - "initial_altitude": (34000.0, "ft"), - "final_altitude": (500.0, "ft"), - "altitude_bounds": ((0.0, 38000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((29.0, 87.0), "min"), - }, - "initial_guesses": {"time": ([241, 58], "min")}, - }, - "post_mission": { - "include_landing": False, - "target_range": (1906, "nmi"), - }, -} diff --git a/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py b/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py similarity index 61% rename from aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py rename to aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py index 3d38ed2655..d8a9f158aa 100644 --- a/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_analysis.py +++ b/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_analysis.py @@ -1,4 +1,4 @@ -''' +""" OpenMDAO component for aerostructural analysis using OpenAeroStruct. This analysis is based on the aircraft_for_bench_FwFm.csv input data representing a @@ -19,7 +19,7 @@ Currently, only the wing mass is used to override the Aviary variable Aircraft.Wing.MASS. -''' +""" import time import warnings @@ -31,23 +31,23 @@ import ambiance except ImportError: raise ImportError( - "ambiance package not found. You can install it by running 'pip install ambiance'.") + "ambiance package not found. You can install it by running 'pip install ambiance'." + ) try: import openaerostruct except ImportError: raise ImportError( - "openaerostruct package not found. You can install it by running 'pip install openaerostruct'.") + "openaerostruct package not found. You can install it by running 'pip install openaerostruct'." + ) from ambiance import Atmosphere - from openaerostruct.integration.aerostruct_groups import AerostructGeometry, AerostructPoint from openaerostruct.structures.wingbox_fuel_vol_delta import WingboxFuelVolDelta def user_mesh(): - """generate a user defined mesh which is model specific""" - + """Generate a user defined mesh which is model specific.""" # Planform specifications half_span = 17.9573 kink_location = 4.9544 @@ -84,26 +84,26 @@ def user_mesh(): # Outboard mesh[:, :ny_outboard, 1] = np.linspace(half_span, kink_location, ny_outboard) # Inboard - mesh[:, ny_outboard: ny_outboard + ny_inboard, - 1] = np.linspace(kink_location, 0, ny_inboard)[1:] + mesh[:, ny_outboard : ny_outboard + ny_inboard, 1] = np.linspace(kink_location, 0, ny_inboard)[ + 1: + ] ###### THE X-COORDINATES ###### # Start with the leading edge and create some intermediate arrays that we will use x_LE = np.zeros(ny_inboard + ny_outboard - 1) - array_for_inboard_leading_edge_x_coord = np.linspace( - 0, kink_location, ny_inboard) * np.tan( + array_for_inboard_leading_edge_x_coord = np.linspace(0, kink_location, ny_inboard) * np.tan( inboard_LE_sweep / 180.0 * np.pi ) array_for_outboard_leading_edge_x_coord = ( - np.linspace(0, half_span - kink_location, ny_outboard) * - np.tan(outboard_LE_sweep / 180.0 * np.pi) + np.linspace(0, half_span - kink_location, ny_outboard) + * np.tan(outboard_LE_sweep / 180.0 * np.pi) + np.ones(ny_outboard) * array_for_inboard_leading_edge_x_coord[-1] ) x_LE[:ny_inboard] = array_for_inboard_leading_edge_x_coord - x_LE[ny_inboard: ny_inboard + ny_outboard] = array_for_outboard_leading_edge_x_coord[1:] + x_LE[ny_inboard : ny_inboard + ny_outboard] = array_for_outboard_leading_edge_x_coord[1:] # Then the trailing edge x_TE = np.zeros(ny_inboard + ny_outboard - 1) @@ -121,7 +121,7 @@ def user_mesh(): ) x_TE[:ny_inboard] = array_for_inboard_trailing_edge_x_coord - x_TE[ny_inboard: ny_inboard + ny_outboard] = array_for_outboard_trailing_edge_x_coord[1:] + x_TE[ny_inboard : ny_inboard + ny_outboard] = array_for_outboard_trailing_edge_x_coord[1:] for i in range(0, ny_inboard + ny_outboard - 1): mesh[:, i, 0] = np.linspace(np.flip(x_LE)[i], np.flip(x_TE)[i], nx) @@ -130,65 +130,75 @@ def user_mesh(): class OAStructures(om.ExplicitComponent): - """OAS structure component""" + """OAS structure component.""" def initialize(self): - self.options.declare('symmetry', default=True, - desc='wing symmetry (True or False)') - self.options.declare('chord_cos_spacing', default=0, - desc='chordwise cosine spacing') - self.options.declare('span_cos_spacing', default=0, - desc='spanwise cosine spacing') - self.options.declare('num_box_cp', default=0, - desc='number of chordwise CPs on the structural box') + self.options.declare('symmetry', default=True, desc='wing symmetry (True or False)') + self.options.declare('chord_cos_spacing', default=0, desc='chordwise cosine spacing') + self.options.declare('span_cos_spacing', default=0, desc='spanwise cosine spacing') + self.options.declare( + 'num_box_cp', default=0, desc='number of chordwise CPs on the structural box' + ) self.options.declare('num_twist_cp', default=0, desc='number of twist CPs') - self.options.declare('S_ref_type', default='wetted', - desc='type of computed wing area (wetted or projected)') - self.options.declare('fem_model_type', default='wingbox', - desc='type of FEM model (wingbox or tube)') + self.options.declare( + 'S_ref_type', default='wetted', desc='type of computed wing area (wetted or projected)' + ) + self.options.declare( + 'fem_model_type', default='wingbox', desc='type of FEM model (wingbox or tube)' + ) self.options.declare('with_viscous', default=True, desc='viscous drag selection') self.options.declare('with_wave', default=True, desc='wave drag selection') - self.options.declare('k_lam', default=0.05, - desc='fraction of chord with laminar flow') - self.options.declare('c_max_t', default=0.38, - desc='chordwise location of maximum thickness') + self.options.declare('k_lam', default=0.05, desc='fraction of chord with laminar flow') + self.options.declare( + 'c_max_t', default=0.38, desc='chordwise location of maximum thickness' + ) self.options.declare('E', default=73.1e9, desc='Youngs Modulus for AL 7073 [Pa]') - self.options.declare('G', default=(73.1e9 / 2 / 1.33), - desc='Shear Modulus for AL 7073 [Pa]') - self.options.declare('yield', default=(420.0e6 / 1.5), - desc='Allowable yield stress for AL 7073 [Pa]') - self.options.declare('mrho', default=2.78e3, - desc='Material density for AL 7073 [kg/m^3]') - self.options.declare('strength_factor_for_upper_skin', default=1.0, - desc='the yield stress is multiplied by this factor for the upper skin') - self.options.declare('wing_weight_ratio', default=1.00, - desc='Ratio of the total wing weight (including non-structural components) to the wing structural weight.') - self.options.declare('exact_failure_constraint', - default=False, desc='if false, use KS function') - self.options.declare('struct_weight_relief', default=True, - desc='if true, use structural weight as intertia relief loads') - self.options.declare('distributed_fuel_weight', default=True, - desc='Set True to distribute the fuel weight across the entire wing.') + self.options.declare( + 'G', default=(73.1e9 / 2 / 1.33), desc='Shear Modulus for AL 7073 [Pa]' + ) + self.options.declare( + 'yield', default=(420.0e6 / 1.5), desc='Allowable yield stress for AL 7073 [Pa]' + ) + self.options.declare('mrho', default=2.78e3, desc='Material density for AL 7073 [kg/m^3]') + self.options.declare( + 'strength_factor_for_upper_skin', + default=1.0, + desc='the yield stress is multiplied by this factor for the upper skin', + ) + self.options.declare( + 'wing_weight_ratio', + default=1.00, + desc='Ratio of the total wing weight (including non-structural components) to the wing structural weight.', + ) + self.options.declare( + 'exact_failure_constraint', default=False, desc='if false, use KS function' + ) + self.options.declare( + 'struct_weight_relief', + default=True, + desc='if true, use structural weight as inertia relief loads', + ) + self.options.declare( + 'distributed_fuel_weight', + default=True, + desc='Set True to distribute the fuel weight across the entire wing.', + ) self.options.declare('n_point_masses', default=0, desc='number of point masses') - self.options.declare('fuel_density', default=803.0, - desc='fuel density (only needed if the fuel-in-wing volume constraint is used) [kg/m^3]') + self.options.declare( + 'fuel_density', + default=803.0, + desc='fuel density (only needed if the fuel-in-wing volume constraint is used) [kg/m^3]', + ) def setup(self): - self.add_input('box_upper_x', units='unitless', - shape=(self.options['num_box_cp'],)) - self.add_input('box_lower_x', units='unitless', - shape=(self.options['num_box_cp'],)) - self.add_input('box_upper_y', units='unitless', - shape=(self.options['num_box_cp'],)) - self.add_input('box_lower_y', units='unitless', - shape=(self.options['num_box_cp'],)) + self.add_input('box_upper_x', units='unitless', shape=(self.options['num_box_cp'],)) + self.add_input('box_lower_x', units='unitless', shape=(self.options['num_box_cp'],)) + self.add_input('box_upper_y', units='unitless', shape=(self.options['num_box_cp'],)) + self.add_input('box_lower_y', units='unitless', shape=(self.options['num_box_cp'],)) self.add_input('twist_cp', units='deg', shape=(self.options['num_twist_cp'],)) - self.add_input('spar_thickness_cp', units='m', - shape=(self.options['num_twist_cp'],)) - self.add_input('skin_thickness_cp', units='m', - shape=(self.options['num_twist_cp'],)) - self.add_input('t_over_c_cp', units='unitless', - shape=(self.options['num_twist_cp'],)) + self.add_input('spar_thickness_cp', units='m', shape=(self.options['num_twist_cp'],)) + self.add_input('skin_thickness_cp', units='m', shape=(self.options['num_twist_cp'],)) + self.add_input('t_over_c_cp', units='unitless', shape=(self.options['num_twist_cp'],)) self.add_input('airfoil_t_over_c', units='unitless') self.add_input('fuel', val=0.0, units='kg') self.add_input('fuel_reserve', val=0.0, units='kg') @@ -201,7 +211,7 @@ def setup(self): self.add_input('engine_mass', val=0.0, units='kg') self.add_input('engine_location', val=np.array([0.0, 0.0, 0.0]), units='m') - self.add_output('wing_weight', units='kg') + self.add_output('wing_mass', units='kg') self.add_output('fuel_burn', units='kg') self.declare_partials(of=['*'], wrt=['fuel'], method='fd') @@ -209,14 +219,14 @@ def setup(self): self.previous_DV_values = {} def compute(self, inputs, outputs): - start_time = time.time() - # perform the wing structural optimization and return the wing weight + # perform the wing structural optimization and return the wing mass mesh = user_mesh() # surface options dictionary + # fmt: off surf_dict = { # surface name 'name': 'meshwing', @@ -226,7 +236,7 @@ def compute(self, inputs, outputs): # wing mesh 'mesh': mesh, - + # wing definition 'S_ref_type': self.options['S_ref_type'], 'fem_model_type': self.options['fem_model_type'], @@ -260,7 +270,7 @@ def compute(self, inputs, outputs): # flow, used for viscous drag 'c_max_t': self.options['c_max_t'], - + # Structural values 'E': self.options['E'], 'G': self.options['G'], @@ -269,18 +279,19 @@ def compute(self, inputs, outputs): 'strength_factor_for_upper_skin': self.options['strength_factor_for_upper_skin'], 'wing_weight_ratio': self.options['wing_weight_ratio'], 'exact_failure_constraint': self.options['exact_failure_constraint'], - + # structural weight factors 'struct_weight_relief': self.options['struct_weight_relief'], 'distributed_fuel_weight': self.options['distributed_fuel_weight'], - + # point masses 'n_point_masses': self.options['n_point_masses'], - + # fuel factors 'fuel_density': self.options['fuel_density'], 'Wf_reserve': inputs['fuel_reserve'][0], } + # fmt: on # define the surfaces surfaces = [surf_dict] @@ -305,26 +316,42 @@ def compute(self, inputs, outputs): # set values on the subproblem based on what's passed in from Aviary # Add problem information as an independent variables component indep_var_comp = om.IndepVarComp() - indep_var_comp.add_output('Mach_number', val=mach, - desc='Mach number for cruise and for maneuver') - indep_var_comp.add_output('v', val=velocity, units='m/s', - desc='velocity for cruise and for maneuver') - indep_var_comp.add_output('re', - val=np.array([rho[0] * velocity[0] * 1.0 / (dynamic_viscosity[0]), - rho[1] * velocity[1] * 1.0 / (dynamic_viscosity[1])]), - desc='Reynolds number per unit length for cruise and for maneuver', units='1/m' - ) - indep_var_comp.add_output('rho', val=rho, units='kg/m**3', - desc='atmostheric density for cruise and for maneuver') - indep_var_comp.add_output('speed_of_sound', val=speed_of_sound, - units='m/s', desc='speed of sound for cruise and for maneuver') - indep_var_comp.add_output('CT', val=0.53 / 3600, units='1/s', - desc='cruise thrust specific fuel consumption') + indep_var_comp.add_output( + 'Mach_number', val=mach, desc='Mach number for cruise and for maneuver' + ) + indep_var_comp.add_output( + 'v', val=velocity, units='m/s', desc='velocity for cruise and for maneuver' + ) + indep_var_comp.add_output( + 're', + val=np.array( + [ + rho[0] * velocity[0] * 1.0 / (dynamic_viscosity[0]), + rho[1] * velocity[1] * 1.0 / (dynamic_viscosity[1]), + ] + ), + desc='Reynolds number per unit length for cruise and for maneuver', + units='1/m', + ) + indep_var_comp.add_output( + 'rho', val=rho, units='kg/m**3', desc='atmostheric density for cruise and for maneuver' + ) + indep_var_comp.add_output( + 'speed_of_sound', + val=speed_of_sound, + units='m/s', + desc='speed of sound for cruise and for maneuver', + ) + indep_var_comp.add_output( + 'CT', val=0.53 / 3600, units='1/s', desc='cruise thrust specific fuel consumption' + ) indep_var_comp.add_output('R', val=cruise_range, units='m', desc='cruise range') - indep_var_comp.add_output('W0_without_point_masses', - val=40.e3 + fuel + surf_dict['Wf_reserve'], units='kg') - indep_var_comp.add_output('load_factor', val=np.array( - [1.0, 2.5]), desc='load factor for cruise and for maneuver') + indep_var_comp.add_output( + 'W0_without_point_masses', val=40.0e3 + fuel + surf_dict['Wf_reserve'], units='kg' + ) + indep_var_comp.add_output( + 'load_factor', val=np.array([1.0, 2.5]), desc='load factor for cruise and for maneuver' + ) indep_var_comp.add_output('alpha', val=0.0, units='deg') indep_var_comp.add_output('alpha_maneuver', val=0.0, units='deg') indep_var_comp.add_output('empty_cg', val=np.zeros((3)), units='m') @@ -338,12 +365,13 @@ def compute(self, inputs, outputs): point_mass_locations = inputs['engine_location'] indep_var_comp.add_output('point_masses', val=point_masses, units='kg') - indep_var_comp.add_output('point_mass_locations', - val=point_mass_locations, units='m') + indep_var_comp.add_output('point_mass_locations', val=point_mass_locations, units='m') # add an ExecComp subsystem to compute the actual W0 to be used within OAS based on the sum of the point mass and other W0 weight prob.model.add_subsystem( - 'W0_comp', om.ExecComp('W0 = W0_without_point_masses + 2 * sum(point_masses)', units='kg'), promotes=['*'] + 'W0_comp', + om.ExecComp('W0 = W0_without_point_masses + 2 * sum(point_masses)', units='kg'), + promotes=['*'], ) # Loop over each surface in the surfaces list @@ -361,58 +389,56 @@ def compute(self, inputs, outputs): point_name = 'AS_point_{}'.format(i) # Create the aerostruct point group and add it to the model - AS_point = AerostructPoint( - surfaces=surfaces, internally_connect_fuelburn=False) + AS_point = AerostructPoint(surfaces=surfaces, internally_connect_fuelburn=False) prob.model.add_subsystem(point_name, AS_point) # Connect flow properties to the analysis point prob.model.connect('v', point_name + '.v', src_indices=[i]) - prob.model.connect('Mach_number', point_name + - '.Mach_number', src_indices=[i]) + prob.model.connect('Mach_number', point_name + '.Mach_number', src_indices=[i]) prob.model.connect('re', point_name + '.re', src_indices=[i]) prob.model.connect('rho', point_name + '.rho', src_indices=[i]) prob.model.connect('CT', point_name + '.CT') prob.model.connect('R', point_name + '.R') prob.model.connect('W0', point_name + '.W0') - prob.model.connect('speed_of_sound', point_name + - '.speed_of_sound', src_indices=[i]) + prob.model.connect('speed_of_sound', point_name + '.speed_of_sound', src_indices=[i]) prob.model.connect('empty_cg', point_name + '.empty_cg') - prob.model.connect('load_factor', point_name + - '.load_factor', src_indices=[i]) - prob.model.connect('fuel_mass', point_name + - '.total_perf.L_equals_W.fuelburn') + prob.model.connect('load_factor', point_name + '.load_factor', src_indices=[i]) + prob.model.connect('fuel_mass', point_name + '.total_perf.L_equals_W.fuelburn') prob.model.connect('fuel_mass', point_name + '.total_perf.CG.fuelburn') for surface in surfaces: name = surface['name'] if surf_dict['distributed_fuel_weight']: - prob.model.connect('load_factor', point_name + - '.coupled.load_factor', src_indices=[i]) + prob.model.connect( + 'load_factor', point_name + '.coupled.load_factor', src_indices=[i] + ) com_name = point_name + '.' + name + '_perf.' prob.model.connect( - name + '.local_stiff_transformed', point_name + - '.coupled.' + name + '.local_stiff_transformed' + name + '.local_stiff_transformed', + point_name + '.coupled.' + name + '.local_stiff_transformed', ) - prob.model.connect(name + '.nodes', point_name + - '.coupled.' + name + '.nodes') + prob.model.connect(name + '.nodes', point_name + '.coupled.' + name + '.nodes') # Connect aerodyamic mesh to coupled group mesh - prob.model.connect(name + '.mesh', point_name + - '.coupled.' + name + '.mesh') + prob.model.connect(name + '.mesh', point_name + '.coupled.' + name + '.mesh') if surf_dict['struct_weight_relief']: - prob.model.connect(name + '.element_mass', - point_name + '.coupled.' + name + '.element_mass') + prob.model.connect( + name + '.element_mass', point_name + '.coupled.' + name + '.element_mass' + ) # Connect performance calculation variables prob.model.connect(name + '.nodes', com_name + 'nodes') - prob.model.connect(name + '.cg_location', point_name + - '.' + 'total_perf.' + name + '_cg_location') - prob.model.connect(name + '.structural_mass', point_name + - '.' + 'total_perf.' + name + '_structural_mass') + prob.model.connect( + name + '.cg_location', point_name + '.' + 'total_perf.' + name + '_cg_location' + ) + prob.model.connect( + name + '.structural_mass', + point_name + '.' + 'total_perf.' + name + '_structural_mass', + ) # Connect wingbox properties to von Mises stress calcs prob.model.connect(name + '.Qz', com_name + 'Qz') @@ -428,8 +454,7 @@ def compute(self, inputs, outputs): coupled_name = point_name + '.coupled.' + name prob.model.connect('point_masses', coupled_name + '.point_masses') - prob.model.connect('point_mass_locations', - coupled_name + '.point_mass_locations') + prob.model.connect('point_mass_locations', coupled_name + '.point_mass_locations') # use only the first surface for constraints surface = surfaces[0] @@ -438,43 +463,47 @@ def compute(self, inputs, outputs): prob.model.connect('alpha', 'AS_point_0' + '.alpha') prob.model.connect('alpha_maneuver', 'AS_point_1' + '.alpha') - # Here we add the fuel volume constraint componenet to the model - prob.model.add_subsystem( - 'fuel_vol_delta', WingboxFuelVolDelta(surface=surfaces[0])) + # Here we add the fuel volume constraint component to the model + prob.model.add_subsystem('fuel_vol_delta', WingboxFuelVolDelta(surface=surfaces[0])) prob.model.connect(name + '.struct_setup.fuel_vols', 'fuel_vol_delta.fuel_vols') prob.model.connect('AS_point_0.fuelburn', 'fuel_vol_delta.fuelburn') if surf_dict['distributed_fuel_weight']: - prob.model.connect(name + '.struct_setup.fuel_vols', - 'AS_point_0.coupled.' + name + '.struct_states.fuel_vols') - prob.model.connect('fuel_mass', 'AS_point_0.coupled.' + - name + '.struct_states.fuel_mass') - - prob.model.connect(name + '.struct_setup.fuel_vols', - 'AS_point_1.coupled.' + name + '.struct_states.fuel_vols') - prob.model.connect('fuel_mass', 'AS_point_1.coupled.' + - name + '.struct_states.fuel_mass') + prob.model.connect( + name + '.struct_setup.fuel_vols', + 'AS_point_0.coupled.' + name + '.struct_states.fuel_vols', + ) + prob.model.connect( + 'fuel_mass', 'AS_point_0.coupled.' + name + '.struct_states.fuel_mass' + ) + + prob.model.connect( + name + '.struct_setup.fuel_vols', + 'AS_point_1.coupled.' + name + '.struct_states.fuel_vols', + ) + prob.model.connect( + 'fuel_mass', 'AS_point_1.coupled.' + name + '.struct_states.fuel_mass' + ) # add an ExecComp to compute the fuel difference comp = om.ExecComp('fuel_diff = (fuel_mass - fuelburn) / fuelburn', units='kg') # add a fuel difference subsystem - prob.model.add_subsystem('fuel_diff', comp, promotes_inputs=[ - 'fuel_mass'], promotes_outputs=['fuel_diff']) + prob.model.add_subsystem( + 'fuel_diff', comp, promotes_inputs=['fuel_mass'], promotes_outputs=['fuel_diff'] + ) prob.model.connect('AS_point_0.fuelburn', 'fuel_diff.fuelburn') - # add an objective funtion + # add an objective function prob.model.add_objective('AS_point_0.fuelburn', scaler=1e-5) # add design variables - prob.model.add_design_var(name + '.twist_cp', lower=- - 15.0, upper=15.0, scaler=0.1) - prob.model.add_design_var(name + '.spar_thickness_cp', - lower=0.003, upper=0.1, scaler=1e2) - prob.model.add_design_var(name + '.skin_thickness_cp', - lower=0.003, upper=0.1, scaler=1e2) - prob.model.add_design_var(name + '.geometry.t_over_c_cp', - lower=0.07, upper=0.2, scaler=10.0) + prob.model.add_design_var(name + '.twist_cp', lower=-15.0, upper=15.0, scaler=0.1) + prob.model.add_design_var(name + '.spar_thickness_cp', lower=0.003, upper=0.1, scaler=1e2) + prob.model.add_design_var(name + '.skin_thickness_cp', lower=0.003, upper=0.1, scaler=1e2) + prob.model.add_design_var( + name + '.geometry.t_over_c_cp', lower=0.07, upper=0.2, scaler=10.0 + ) prob.model.add_design_var('alpha_maneuver', lower=-15.0, upper=15) # add problem constraints @@ -491,17 +520,18 @@ def compute(self, inputs, outputs): prob.driver = om.ScipyOptimizeDriver() prob.driver.options['optimizer'] = 'SLSQP' prob.driver.options['tol'] = 1e-8 - # Set up the problem with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=om.PromotionWarning) + warnings.filterwarnings('ignore', category=om.PromotionWarning) prob.setup() # change linear solver for aerostructural coupled adjoint prob.model.AS_point_0.coupled.linear_solver = om.LinearBlockGS( - iprint=0, maxiter=30, use_aitken=True) + iprint=0, maxiter=30, use_aitken=True + ) prob.model.AS_point_1.coupled.linear_solver = om.LinearBlockGS( - iprint=0, maxiter=30, use_aitken=True) + iprint=0, maxiter=30, use_aitken=True + ) prob.model.AS_point_0.coupled.nonlinear_solver.options['iprint'] = 0 prob.model.AS_point_1.coupled.nonlinear_solver.options['iprint'] = 0 @@ -513,16 +543,15 @@ def compute(self, inputs, outputs): prob.run_driver() self.previous_DV_values[name + '.twist_cp'] = prob[name + '.twist_cp'] - self.previous_DV_values[name + - '.spar_thickness_cp'] = prob[name + '.spar_thickness_cp'] - self.previous_DV_values[name + - '.skin_thickness_cp'] = prob[name + '.skin_thickness_cp'] - self.previous_DV_values[name + - '.geometry.t_over_c_cp'] = prob[name + '.geometry.t_over_c_cp'] + self.previous_DV_values[name + '.spar_thickness_cp'] = prob[name + '.spar_thickness_cp'] + self.previous_DV_values[name + '.skin_thickness_cp'] = prob[name + '.skin_thickness_cp'] + self.previous_DV_values[name + '.geometry.t_over_c_cp'] = prob[ + name + '.geometry.t_over_c_cp' + ] self.previous_DV_values['alpha_maneuver'] = prob['alpha_maneuver'] # output wing weight and fuel burn - outputs['wing_weight'] = prob[name + '.structural_mass'][0] + outputs['wing_mass'] = prob[name + '.structural_mass'][0] outputs['fuel_burn'] = prob['AS_point_0.fuelburn'][0] # calculate execution time @@ -531,5 +560,8 @@ def compute(self, inputs, outputs): tm_min, remainder = divmod(remainder, 60) tm_sec = int(remainder) tm_msec = (remainder - tm_sec) * 1000 - print('Structures OAS Compute End --- execution time {:02}:{:02}:{:02}.{:03}' - .format(int(tm_hrs), int(tm_min), int(tm_sec), int(tm_msec))) + print( + 'Structures OAS Compute End --- execution time {:02}:{:02}:{:02}.{:03}'.format( + int(tm_hrs), int(tm_min), int(tm_sec), int(tm_msec) + ) + ) diff --git a/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_builder.py b/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_builder.py new file mode 100644 index 0000000000..f374a65ad3 --- /dev/null +++ b/aviary/examples/external_subsystems/OAS_mass/OAS_wing_mass_builder.py @@ -0,0 +1,57 @@ +import openmdao.api as om + +import aviary.api as av +from aviary.examples.external_subsystems.OAS_mass.OAS_wing_mass_analysis import OAStructures + + +class OASWingMassBuilder(av.SubsystemBuilderBase): + """ + Builder for an OpenAeroStruct component that computes a new wing mass. + + This also provides a method to build OpenMDAO systems for the pre-mission and mission computations of the subsystem. + + Attributes + ---------- + name : str ('wing_mass') + object label + + Methods + ------- + __init__(self, name='wing_mass'): + Initializes the OASWingmassBuilder object with a given name. + build_pre_mission(self) -> openmdao.core.System: + Build an OpenMDAO system for the pre-mission computations of the subsystem. + """ + + def __init__(self, name='wing_mass'): + super().__init__(name) + + def build_pre_mission(self, aviary_inputs): + """ + Build an OpenMDAO system for the pre-mission computations of the subsystem. + + Returns + ------- + pre_mission_sys : openmdao.core.System + An OpenMDAO system containing all computations that need to happen in + the pre-mission part of the Aviary problem. This + includes sizing, design, and other non-mission parameters. + """ + wing_group = om.Group() + wing_group.add_subsystem( + 'aerostructures', + OAStructures( + symmetry=True, + wing_weight_ratio=1.0, + S_ref_type='projected', + n_point_masses=1, + num_twist_cp=4, + num_box_cp=51, + ), + promotes_inputs=[ + ('fuel', av.Mission.Summary.FUEL_MASS), + ], + promotes_outputs=[('wing_mass', av.Aircraft.Wing.MASS)], + ) + + return wing_group diff --git a/aviary/examples/external_subsystems/simple_weight/__init__.py b/aviary/examples/external_subsystems/OAS_mass/__init__.py similarity index 100% rename from aviary/examples/external_subsystems/simple_weight/__init__.py rename to aviary/examples/external_subsystems/OAS_mass/__init__.py diff --git a/aviary/examples/external_subsystems/OAS_mass/run_OAS_wing_mass_example.py b/aviary/examples/external_subsystems/OAS_mass/run_OAS_wing_mass_example.py new file mode 100644 index 0000000000..11ec537668 --- /dev/null +++ b/aviary/examples/external_subsystems/OAS_mass/run_OAS_wing_mass_example.py @@ -0,0 +1,212 @@ +""" +This is a simple test mission to demonstrate the inclusion of a pre-mission user defined external +subsystem. The simple mission is based on input data read from the benchmark data file bench_4.csv, +which represents a single-aisle commercial transport aircraft. The OpenAeroStruct (OAS) subsystem is +used to compute an optimum wing mass which will override the Aviary computed wing mass value. + +The flag 'use_OAS' is set to 'True' to include the OAS subsystem in the mission, or set to 'False' +to run the mission without the subsystem so that wing mass values between the 2 methods may be +compared. +""" + +import numpy as np + +import aviary.api as av +from aviary.examples.external_subsystems.OAS_mass.OAS_wing_mass_builder import OASWingMassBuilder + +# This problem can take a while to run - use the most performant optimizer installed +optimizer = 'SLSQP' +try: + from pyoptsparse import OPT +except ImportError: + pass +else: + try: + OPT('IPOPT') + except Exception: + pass + else: + optimizer = 'IPOPT' + try: + OPT('SNOPT') + except Exception: + pass + else: + optimizer = 'SNOPT' + + +################# +# Problem Setup # +################# +wing_mass_builder = OASWingMassBuilder() + +# Load the phase_info and other common setup tasks +phase_info = { + 'climb_1': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'distance_solve_segments': False, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.2, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.18, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (0.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'altitude_bounds': ((0.0, 34000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((64.0, 192.0), 'min'), + }, + 'initial_guesses': {'time': ([0, 128], 'min')}, + }, + 'climb_2': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (34000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((64.0, 192.0), 'min'), + 'time_duration_bounds': ((56.5, 169.5), 'min'), + }, + 'initial_guesses': {'time': ([128, 113], 'min')}, + }, + 'descent_1': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.36, 'unitless'), + 'mach_bounds': ((0.34, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (34000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'altitude_bounds': ((0.0, 38000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((120.5, 361.5), 'min'), + 'time_duration_bounds': ((29.0, 87.0), 'min'), + }, + 'initial_guesses': {'time': ([241, 58], 'min')}, + }, + 'post_mission': { + 'include_landing': False, + 'constrain_range': True, + 'target_range': (1800.0, 'nmi'), + }, +} + +phase_info['pre_mission'] = {'include_takeoff': False, 'optimize_mass': True} +phase_info['pre_mission']['external_subsystems'] = [wing_mass_builder] + +aircraft_definition_file = 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv' +make_plots = False + +# create and begin setting up Aviary problem +prob = av.AviaryProblem() + +prob.load_inputs(aircraft_definition_file, phase_info) +prob.check_and_preprocess_inputs() +prob.build_model() +prob.add_driver(optimizer=optimizer) +prob.add_design_variables() +prob.add_objective() +prob.setup() + +# define OAS inputs +OAS_sys = 'pre_mission.wing_mass.aerostructures.' +# block auto-formatting of tables +# fmt: off +prob.set_val( + OAS_sys + 'box_upper_x', + np.array( + [ + 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, + 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, + 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, + 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, + ] + ), + units='unitless', +) + +prob.set_val( + OAS_sys + 'box_lower_x', + np.array( + [ + 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, + 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, + 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, + 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, + ] + ), + units='unitless', +) + +prob.set_val( + OAS_sys + 'box_upper_y', + np.array( + [ + 0.0447, 0.046, 0.0472, 0.0484, 0.0495, 0.0505, 0.0514, 0.0523, 0.0531, 0.0538, + 0.0545, 0.0551, 0.0557, 0.0563, 0.0568, 0.0573, 0.0577, 0.0581, 0.0585, 0.0588, + 0.0591, 0.0593, 0.0595, 0.0597, 0.0599, 0.06, 0.0601, 0.0602, 0.0602, 0.0602, + 0.0602, 0.0602, 0.0601, 0.06, 0.0599, 0.0598, 0.0596, 0.0594, 0.0592, 0.0589, + 0.0586, 0.0583, 0.058, 0.0576, 0.0572, 0.0568, 0.0563, 0.0558, 0.0553, 0.0547, + 0.0541, + ] + ), + units='unitless', +) + +prob.set_val( + OAS_sys + 'box_lower_y', + np.array( + [ + -0.0447, -0.046, -0.0473, -0.0485, -0.0496, -0.0506, -0.0515, -0.0524, -0.0532, + -0.054, -0.0547, -0.0554, -0.056, -0.0565, -0.057, -0.0575, -0.0579, -0.0583, + -0.0586, -0.0589, -0.0592, -0.0594, -0.0595, -0.0596, -0.0597, -0.0598, -0.0598, + -0.0598, -0.0598, -0.0597, -0.0596, -0.0594, -0.0592, -0.0589, -0.0586, -0.0582, + -0.0578, -0.0573, -0.0567, -0.0561, -0.0554, -0.0546, -0.0538, -0.0529, -0.0519, + -0.0509, -0.0497, -0.0485, -0.0472, -0.0458, -0.0444, + ] + ), + units='unitless', +) + +# fmt: on +prob.set_val(OAS_sys + 'twist_cp', np.array([-6.0, -6.0, -4.0, 0.0]), units='deg') +prob.set_val(OAS_sys + 'spar_thickness_cp', np.array([0.004, 0.005, 0.008, 0.01]), units='m') +prob.set_val(OAS_sys + 'skin_thickness_cp', np.array([0.005, 0.01, 0.015, 0.025]), units='m') +prob.set_val(OAS_sys + 't_over_c_cp', np.array([0.08, 0.08, 0.10, 0.08]), units='unitless') +prob.set_val(OAS_sys + 'airfoil_t_over_c', 0.12, units='unitless') +prob.set_val(OAS_sys + 'fuel', 40044.0, units='lbm') +prob.set_val(OAS_sys + 'fuel_reserve', 3000.0, units='lbm') +prob.set_val(OAS_sys + 'CD0', 0.0078, units='unitless') +prob.set_val(OAS_sys + 'cruise_Mach', 0.785, units='unitless') +prob.set_val(OAS_sys + 'cruise_altitude', 11303.682962301647, units='m') +prob.set_val(OAS_sys + 'cruise_range', 3500, units='nmi') +prob.set_val(OAS_sys + 'cruise_SFC', 0.53 / 3600, units='1/s') +prob.set_val(OAS_sys + 'engine_mass', 7400, units='lbm') +prob.set_val(OAS_sys + 'engine_location', np.array([25, -10.0, 0.0]), units='m') + +# finish setting up Aviary problem and run +prob.run_aviary_problem(make_plots=False) + +print('wing mass = ', prob.model.get_val(av.Aircraft.Wing.MASS, units='lbm')) diff --git a/aviary/examples/external_subsystems/OAS_mass/test/test_OAS_wing_mass_analysis.py b/aviary/examples/external_subsystems/OAS_mass/test/test_OAS_wing_mass_analysis.py new file mode 100644 index 0000000000..4cdc4fcd40 --- /dev/null +++ b/aviary/examples/external_subsystems/OAS_mass/test/test_OAS_wing_mass_analysis.py @@ -0,0 +1,97 @@ +import unittest + +import numpy as np +import openmdao.api as om +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.examples.external_subsystems.OAS_mass.OAS_wing_mass_analysis import OAStructures + + +class Test_OAStructures(unittest.TestCase): + """Test OAS wing mass component.""" + + @use_tempdirs + def test_OAS_wing_mass_analysis(self): + # run program + prob = om.Problem() + + # mesh example + prob.model.add_subsystem( + 'OAS', + OAStructures( + symmetry=True, + wing_weight_ratio=1.0, + S_ref_type='projected', + n_point_masses=1, + num_twist_cp=4, + num_box_cp=51, + ), + ) + + prob.setup() + + # test data taken from the OpenAeroStruct example aeroelastic wingbox example + # and the aircraft_for_bench_FwFm.csv benchmark data file. All length units are in meters + # and all mass units are in kilograms for this test data. + # fmt: off + prob['OAS.box_upper_x'] = np.array( + [ + 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, + 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, + 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, + 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, + ] + ) + prob['OAS.box_lower_x'] = np.array( + [ + 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, + 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, + 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, + 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, + ] + ) + prob['OAS.box_upper_y'] = np.array( + [ + 0.0447, 0.046, 0.0472, 0.0484, 0.0495, 0.0505, 0.0514, 0.0523, 0.0531, 0.0538, + 0.0545, 0.0551, 0.0557, 0.0563, 0.0568, 0.0573, 0.0577, 0.0581, 0.0585, 0.0588, + 0.0591, 0.0593, 0.0595, 0.0597, 0.0599, 0.06, 0.0601, 0.0602, 0.0602, 0.0602, + 0.0602, 0.0602, 0.0601, 0.06, 0.0599, 0.0598, 0.0596, 0.0594, 0.0592, 0.0589, + 0.0586, 0.0583, 0.058, 0.0576, 0.0572, 0.0568, 0.0563, 0.0558, 0.0553, 0.0547, + 0.0541, + ] + ) + prob['OAS.box_lower_y'] = np.array( + [ + -0.0447, -0.046, -0.0473, -0.0485, -0.0496, -0.0506, -0.0515, -0.0524, -0.0532, + -0.054, -0.0547, -0.0554, -0.056, -0.0565, -0.057, -0.0575, -0.0579, -0.0583, + -0.0586, -0.0589, -0.0592, -0.0594, -0.0595, -0.0596, -0.0597, -0.0598, -0.0598, + -0.0598, -0.0598, -0.0597, -0.0596, -0.0594, -0.0592, -0.0589, -0.0586, -0.0582, + -0.0578, -0.0573, -0.0567, -0.0561, -0.0554, -0.0546, -0.0538, -0.0529, -0.0519, + -0.0509, -0.0497, -0.0485, -0.0472, -0.0458, -0.0444, + ] + ) + # fmt: on + + prob['OAS.twist_cp'] = np.array([-6.0, -6.0, -4.0, 0.0]) + prob['OAS.spar_thickness_cp'] = np.array([0.004, 0.005, 0.008, 0.01]) + prob['OAS.skin_thickness_cp'] = np.array([0.005, 0.01, 0.015, 0.025]) + prob['OAS.t_over_c_cp'] = np.array([0.08, 0.08, 0.10, 0.08]) + prob['OAS.airfoil_t_over_c'] = 0.13 + prob['OAS.fuel'] = 18163.652864 + prob['OAS.fuel_reserve'] = 1360.77711 + prob['OAS.CD0'] = 0.0078 + prob['OAS.cruise_Mach'] = 0.785 + prob['OAS.cruise_altitude'] = 11303.682962301647 + prob['OAS.cruise_range'] = 6482000.0 + prob['OAS.cruise_SFC'] = 0.53 / 3600 + prob['OAS.engine_mass'] = 3356.583538 + prob['OAS.engine_location'] = np.array([4.825, -1.0, 0.0]) + + prob.run_model() + + print('wing mass = ', prob.model.get_val('OAS.wing_mass', units='lbm')) + print('fuel burn = ', prob.model.get_val('OAS.fuel_burn', units='lbm')) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_builder.py b/aviary/examples/external_subsystems/OAS_mass/test/test_OAS_wing_mass_builder.py similarity index 76% rename from aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_builder.py rename to aviary/examples/external_subsystems/OAS_mass/test/test_OAS_wing_mass_builder.py index 302e85775b..5d9e18aca4 100644 --- a/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_builder.py +++ b/aviary/examples/external_subsystems/OAS_mass/test/test_OAS_wing_mass_builder.py @@ -1,14 +1,16 @@ +import importlib.util import unittest -import aviary.api as av +import aviary.api as av path_to_builder = 'OAS_weight.OAS_wing_weight_builder.OASWingWeightBuilder' OASWingWeightBuilder = av.TestSubsystemBuilderBase.import_builder(path_to_builder) @av.skipIfMissingDependencies(OASWingWeightBuilder) +@unittest.skipUnless(importlib.util.find_spec('ambiance'), "'ambiance' is not installed") class TestStructures(av.TestSubsystemBuilderBase): - """Test OAS structure builder""" + """Test OAS structure builder.""" def setUp(self): self.subsystem_builder = OASWingWeightBuilder() diff --git a/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_builder.py b/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_builder.py deleted file mode 100644 index a7e6bc3ad9..0000000000 --- a/aviary/examples/external_subsystems/OAS_weight/OAS_wing_weight_builder.py +++ /dev/null @@ -1,54 +0,0 @@ -import openmdao.api as om -import aviary.api as av -from aviary.examples.external_subsystems.OAS_weight.OAS_wing_weight_analysis import OAStructures - - -class OASWingWeightBuilder(av.SubsystemBuilderBase): - """ - Builder for an OpenAeroStruct component that computes a new wing mass. - - This also provides a method to build OpenMDAO systems for the pre-mission and mission computations of the subsystem. - - Attributes - ---------- - name : str ('wing_weight') - object label - - Methods - ------- - __init__(self, name='wing_weight'): - Initializes the OASWingWeightBuilder object with a given name. - build_pre_mission(self) -> openmdao.core.System: - Build an OpenMDAO system for the pre-mission computations of the subsystem. - """ - - def __init__(self, name='wing_weight'): - super().__init__(name) - - def build_pre_mission(self, aviary_inputs): - ''' - Build an OpenMDAO system for the pre-mission computations of the subsystem. - - Returns - ------- - pre_mission_sys : openmdao.core.System - An OpenMDAO system containing all computations that need to happen in - the pre-mission part of the Aviary problem. This - includes sizing, design, and other non-mission parameters. - ''' - - wing_group = om.Group() - wing_group.add_subsystem("aerostructures", - OAStructures( - symmetry=True, - wing_weight_ratio=1.0, - S_ref_type='projected', - n_point_masses=1, - num_twist_cp=4, - num_box_cp=51), - promotes_inputs=[ - ('fuel', av.Mission.Design.FUEL_MASS), - ], - promotes_outputs=[('wing_weight', av.Aircraft.Wing.MASS)]) - - return wing_group diff --git a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py b/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py deleted file mode 100644 index 630e85913d..0000000000 --- a/aviary/examples/external_subsystems/OAS_weight/run_simple_OAS_mission.py +++ /dev/null @@ -1,162 +0,0 @@ -''' -This is a simple test mission to demonstrate the inclusion of a -pre-mission user defined external subsystem. The simple mission -is based on input data read from the benchmark data file bench_4.csv, -which represents a single-aisle commercial transport aircraft. The -OpenAeroStruct (OAS) subsystem is used to compute an optimum wing -mass which will override the Aviary computed wing mass value. - -The flag 'use_OAS' is set to 'True' to include the OAS subsystem in -the mission, or set to 'False' to run the mission without the -subsystem so that wing mass values between the 2 methods may be -compared. - -''' - -import numpy as np -import openmdao.api as om -import aviary.api as av -from aviary.examples.external_subsystems.OAS_weight.OAS_wing_weight_builder import OASWingWeightBuilder - -# flag to turn on/off OpenAeroStruct subsystem for comparison testing -use_OAS = True - -wing_weight_builder = OASWingWeightBuilder() - -# Load the phase_info and other common setup tasks -phase_info = { - 'climb_1': { - 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, - 'user_options': { - 'optimize_mach': False, - 'optimize_altitude': False, - 'polynomial_control_order': 1, - 'num_segments': 5, - 'order': 3, - 'solve_for_distance': False, - 'initial_mach': (0.2, 'unitless'), - 'final_mach': (0.72, 'unitless'), - 'mach_bounds': ((0.18, 0.74), 'unitless'), - 'initial_altitude': (0.0, 'ft'), - 'final_altitude': (32000.0, 'ft'), - 'altitude_bounds': ((0.0, 34000.0), 'ft'), - 'throttle_enforcement': 'path_constraint', - 'fix_initial': True, - 'constrain_final': False, - 'fix_duration': False, - 'initial_bounds': ((0.0, 0.0), 'min'), - 'duration_bounds': ((64.0, 192.0), 'min'), - }, - 'initial_guesses': {'time': ([0, 128], 'min')}, - }, - 'climb_2': { - 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, - 'user_options': { - 'optimize_mach': False, - 'optimize_altitude': False, - 'polynomial_control_order': 1, - 'num_segments': 5, - 'order': 3, - 'solve_for_distance': False, - 'initial_mach': (0.72, 'unitless'), - 'final_mach': (0.72, 'unitless'), - 'mach_bounds': ((0.7, 0.74), 'unitless'), - 'initial_altitude': (32000.0, 'ft'), - 'final_altitude': (34000.0, 'ft'), - 'altitude_bounds': ((23000.0, 38000.0), 'ft'), - 'throttle_enforcement': 'boundary_constraint', - 'fix_initial': False, - 'constrain_final': False, - 'fix_duration': False, - 'initial_bounds': ((64.0, 192.0), 'min'), - 'duration_bounds': ((56.5, 169.5), 'min'), - }, - 'initial_guesses': {'time': ([128, 113], 'min')}, - }, - 'descent_1': { - 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, - 'user_options': { - 'optimize_mach': False, - 'optimize_altitude': False, - 'polynomial_control_order': 1, - 'num_segments': 5, - 'order': 3, - 'solve_for_distance': False, - 'initial_mach': (0.72, 'unitless'), - 'final_mach': (0.36, 'unitless'), - 'mach_bounds': ((0.34, 0.74), 'unitless'), - 'initial_altitude': (34000.0, 'ft'), - 'final_altitude': (500.0, 'ft'), - 'altitude_bounds': ((0.0, 38000.0), 'ft'), - 'throttle_enforcement': 'path_constraint', - 'fix_initial': False, - 'constrain_final': True, - 'fix_duration': False, - 'initial_bounds': ((120.5, 361.5), 'min'), - 'duration_bounds': ((29.0, 87.0), 'min'), - }, - 'initial_guesses': {'time': ([241, 58], 'min')}, - }, - 'post_mission': { - 'include_landing': False, - 'constrain_range': True, - 'target_range': (1800., 'nmi'), - }, -} - -phase_info['pre_mission'] = {'include_takeoff': False, 'optimize_mass': True} -if use_OAS: - phase_info['pre_mission']['external_subsystems'] = [wing_weight_builder] - -aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' -make_plots = False -max_iter = 1 # set this to a higher number to fully run the optimization -optimizer = 'SLSQP' - - -if __name__ == '__main__': - prob = av.AviaryProblem() - - prob.load_inputs(aircraft_definition_file, phase_info) - prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() - prob.add_driver(optimizer=optimizer, max_iter=max_iter) - prob.add_design_variables() - prob.add_objective() - prob.setup() - - if use_OAS: - OAS_sys = 'pre_mission.wing_weight.aerostructures.' - prob.set_val(OAS_sys + 'box_upper_x', np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, - 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]), units='unitless') - prob.set_val(OAS_sys + 'box_lower_x', np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, - 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]), units='unitless') - prob.set_val(OAS_sys + 'box_upper_y', np.array([0.0447, 0.046, 0.0472, 0.0484, 0.0495, 0.0505, 0.0514, 0.0523, 0.0531, 0.0538, 0.0545, 0.0551, 0.0557, 0.0563, 0.0568, 0.0573, 0.0577, 0.0581, 0.0585, 0.0588, 0.0591, 0.0593, 0.0595, 0.0597, - 0.0599, 0.06, 0.0601, 0.0602, 0.0602, 0.0602, 0.0602, 0.0602, 0.0601, 0.06, 0.0599, 0.0598, 0.0596, 0.0594, 0.0592, 0.0589, 0.0586, 0.0583, 0.058, 0.0576, 0.0572, 0.0568, 0.0563, 0.0558, 0.0553, 0.0547, 0.0541]), units='unitless') - prob.set_val(OAS_sys + 'box_lower_y', np.array([-0.0447, -0.046, -0.0473, -0.0485, -0.0496, -0.0506, -0.0515, -0.0524, -0.0532, -0.054, -0.0547, -0.0554, -0.056, -0.0565, -0.057, -0.0575, -0.0579, -0.0583, -0.0586, -0.0589, -0.0592, -0.0594, -0.0595, -0.0596, - - 0.0597, -0.0598, -0.0598, -0.0598, -0.0598, -0.0597, -0.0596, -0.0594, -0.0592, -0.0589, -0.0586, -0.0582, -0.0578, -0.0573, -0.0567, -0.0561, -0.0554, -0.0546, -0.0538, -0.0529, -0.0519, -0.0509, -0.0497, -0.0485, -0.0472, -0.0458, -0.0444]), units='unitless') - prob.set_val(OAS_sys + 'twist_cp', np.array([-6., -6., -4., 0.]), units='deg') - prob.set_val(OAS_sys + 'spar_thickness_cp', - np.array([0.004, 0.005, 0.008, 0.01]), units='m') - prob.set_val(OAS_sys + 'skin_thickness_cp', - np.array([0.005, 0.01, 0.015, 0.025]), units='m') - prob.set_val(OAS_sys + 't_over_c_cp', - np.array([0.08, 0.08, 0.10, 0.08]), units='unitless') - prob.set_val(OAS_sys + 'airfoil_t_over_c', 0.12, units='unitless') - prob.set_val(OAS_sys + 'fuel', 40044.0, units='lbm') - prob.set_val(OAS_sys + 'fuel_reserve', 3000.0, units='lbm') - prob.set_val(OAS_sys + 'CD0', 0.0078, units='unitless') - prob.set_val(OAS_sys + 'cruise_Mach', 0.785, units='unitless') - prob.set_val(OAS_sys + 'cruise_altitude', 11303.682962301647, units='m') - prob.set_val(OAS_sys + 'cruise_range', 3500, units='nmi') - prob.set_val(OAS_sys + 'cruise_SFC', 0.53 / 3600, units='1/s') - prob.set_val(OAS_sys + 'engine_mass', 7400, units='lbm') - prob.set_val(OAS_sys + 'engine_location', np.array([25, -10.0, 0.0]), units='m') - - prob.set_initial_guesses() - prob.run_aviary_problem('dymos_solution.db', make_plots=False) - - print('wing mass = ', prob.model.get_val(av.Aircraft.Wing.MASS, units='lbm')) diff --git a/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_analysis.py b/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_analysis.py deleted file mode 100644 index 8f807277ad..0000000000 --- a/aviary/examples/external_subsystems/OAS_weight/test_OAS_wing_weight_analysis.py +++ /dev/null @@ -1,62 +0,0 @@ -import numpy as np -import unittest - -import openmdao.api as om -from openmdao.utils.testing_utils import use_tempdirs - -from aviary.examples.external_subsystems.OAS_weight.OAS_wing_weight_analysis import OAStructures - - -class Test_OAStructures(unittest.TestCase): - """Test OAS wing weight component""" - - @use_tempdirs - def test_OAS_wing_weight_analysis(self): - # run program - prob = om.Problem() - - # mesh example - prob.model.add_subsystem('OAS', OAStructures( - symmetry=True, - wing_weight_ratio=1.0, - S_ref_type='projected', - n_point_masses=1, - num_twist_cp=4, - num_box_cp=51)) - - prob.setup() - - # test data taken from the OpenAeroStruct example aeroelastic wingbox example - # and the aircraft_for_bench_FwFm.csv benchmark data file. All length units are in meters - # and all mass units are in kilograms for this test data. - prob['OAS.box_upper_x'] = np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, - 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]) - prob['OAS.box_lower_x'] = np.array([0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, - 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6]) - prob['OAS.box_upper_y'] = np.array([0.0447, 0.046, 0.0472, 0.0484, 0.0495, 0.0505, 0.0514, 0.0523, 0.0531, 0.0538, 0.0545, 0.0551, 0.0557, 0.0563, 0.0568, 0.0573, 0.0577, 0.0581, 0.0585, 0.0588, 0.0591, 0.0593, 0.0595, 0.0597, - 0.0599, 0.06, 0.0601, 0.0602, 0.0602, 0.0602, 0.0602, 0.0602, 0.0601, 0.06, 0.0599, 0.0598, 0.0596, 0.0594, 0.0592, 0.0589, 0.0586, 0.0583, 0.058, 0.0576, 0.0572, 0.0568, 0.0563, 0.0558, 0.0553, 0.0547, 0.0541]) - prob['OAS.box_lower_y'] = np.array([-0.0447, -0.046, -0.0473, -0.0485, -0.0496, -0.0506, -0.0515, -0.0524, -0.0532, -0.054, -0.0547, -0.0554, -0.056, -0.0565, -0.057, -0.0575, -0.0579, -0.0583, -0.0586, -0.0589, -0.0592, -0.0594, -0.0595, -0.0596, - - 0.0597, -0.0598, -0.0598, -0.0598, -0.0598, -0.0597, -0.0596, -0.0594, -0.0592, -0.0589, -0.0586, -0.0582, -0.0578, -0.0573, -0.0567, -0.0561, -0.0554, -0.0546, -0.0538, -0.0529, -0.0519, -0.0509, -0.0497, -0.0485, -0.0472, -0.0458, -0.0444]) - prob['OAS.twist_cp'] = np.array([-6., -6., -4., 0.]) - prob['OAS.spar_thickness_cp'] = np.array([0.004, 0.005, 0.008, 0.01]) - prob['OAS.skin_thickness_cp'] = np.array([0.005, 0.01, 0.015, 0.025]) - prob['OAS.t_over_c_cp'] = np.array([0.08, 0.08, 0.10, 0.08]) - prob['OAS.airfoil_t_over_c'] = 0.13 - prob['OAS.fuel'] = 18163.652864 - prob['OAS.fuel_reserve'] = 1360.77711 - prob['OAS.CD0'] = 0.0078 - prob['OAS.cruise_Mach'] = 0.785 - prob['OAS.cruise_altitude'] = 11303.682962301647 - prob['OAS.cruise_range'] = 6482000.0 - prob['OAS.cruise_SFC'] = 0.53 / 3600 - prob['OAS.engine_mass'] = 3356.583538 - prob['OAS.engine_location'] = np.array([4.825, -1.0, 0.0]) - - prob.run_model() - - print('wing weight = ', prob.model.get_val('OAS.wing_weight', units='lbm')) - print('fuel burn = ', prob.model.get_val('OAS.fuel_burn', units='lbm')) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/examples/external_subsystems/battery/battery_builder.py b/aviary/examples/external_subsystems/battery/battery_builder.py index 37816e8f2d..350a06ddb5 100644 --- a/aviary/examples/external_subsystems/battery/battery_builder.py +++ b/aviary/examples/external_subsystems/battery/battery_builder.py @@ -1,12 +1,14 @@ -from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Mission -from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData +from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ( + ExtendedMetaData, +) +from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Dynamic from aviary.examples.external_subsystems.battery.model.battery_mission import BatteryMission from aviary.examples.external_subsystems.battery.model.battery_premission import BatteryPreMission from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase class BatteryBuilder(SubsystemBuilderBase): - ''' + """ Define the builder for a battery subsystem that provides methods to define the battery subsystem's states, design variables, fixed values, initial guesses, and mass names. It also provides methods to build OpenMDAO systems for the pre-mission and mission computations of the subsystem, to get the constraints for the subsystem, and to preprocess the inputs for the subsystem. @@ -44,14 +46,14 @@ class BatteryBuilder(SubsystemBuilderBase): Returns a list of names for the battery subsystem mass. preprocess_inputs(self, aviary_inputs) -> aviary_inputs: preprocesses the inputs for the battery subsystem, setting the values for battery performance based on the battery cell type. - ''' + """ def __init__(self, name='battery', include_constraints=True): self.include_constraints = include_constraints super().__init__(name, meta_data=ExtendedMetaData) def get_states(self): - ''' + """ Return a dictionary of states for the battery subsystem. Returns @@ -64,31 +66,31 @@ def get_states(self): The units for the state variable. - any additional keyword arguments required by OpenMDAO for the state variable. - ''' + """ states_dict = { - Mission.Battery.STATE_OF_CHARGE: { - 'rate_source': Mission.Battery.STATE_OF_CHARGE_RATE, + Dynamic.Battery.STATE_OF_CHARGE: { + 'rate_source': Dynamic.Battery.STATE_OF_CHARGE_RATE, 'fix_initial': True, }, - Mission.Battery.VOLTAGE_THEVENIN: { + Dynamic.Battery.VOLTAGE_THEVENIN: { 'units': 'V', - 'rate_source': Mission.Battery.VOLTAGE_THEVENIN_RATE, - 'defect_ref': 1.e5, - 'ref': 1.e5, + 'rate_source': Dynamic.Battery.VOLTAGE_THEVENIN_RATE, + 'defect_ref': 1.0e5, + 'ref': 1.0e5, }, } return states_dict def get_linked_variables(self): - ''' + """ Return the list of linked variables for the battery subsystem; in this case it's our two state variables. - ''' - return [Mission.Battery.VOLTAGE_THEVENIN, Mission.Battery.STATE_OF_CHARGE] + """ + return [Dynamic.Battery.VOLTAGE_THEVENIN, Dynamic.Battery.STATE_OF_CHARGE] def build_pre_mission(self, aviary_inputs): - ''' + """ Build an OpenMDAO system for the pre-mission computations of the subsystem. Returns @@ -97,11 +99,11 @@ def build_pre_mission(self, aviary_inputs): An OpenMDAO system containing all computations that need to happen in the pre-mission part of the Aviary problem. This includes sizing, design, and other non-mission parameters. - ''' + """ return BatteryPreMission() def build_mission(self, num_nodes, aviary_inputs): - ''' + """ Build an OpenMDAO system for the mission computations of the subsystem. Returns @@ -111,11 +113,11 @@ def build_mission(self, num_nodes, aviary_inputs): during the mission. This includes time-dependent states that are being integrated as well as any other variables that vary during the mission. - ''' + """ return BatteryMission(num_nodes=num_nodes, aviary_inputs=aviary_inputs) def get_constraints(self): - ''' + """ Return a dictionary of constraints for the battery subsystem. Returns @@ -134,15 +136,15 @@ def get_constraints(self): below 0.2 at the final mission point. - thevenin voltage constraint: A path constraint that ensures the Thevenin voltage does not fall below 0. - ''' + """ if self.include_constraints: constraints = { - Mission.Battery.STATE_OF_CHARGE: { + Dynamic.Battery.STATE_OF_CHARGE: { 'lower': 0.2, 'type': 'boundary', 'loc': 'final', }, - Mission.Battery.VOLTAGE_THEVENIN: { + Dynamic.Battery.VOLTAGE_THEVENIN: { 'lower': 0, 'type': 'path', }, @@ -153,7 +155,7 @@ def get_constraints(self): return constraints def get_design_vars(self): - ''' + """ Return a dictionary of design variables for the battery subsystem. Returns @@ -170,8 +172,7 @@ def get_design_vars(self): The upper bound for the design variable - any additional keyword arguments required by OpenMDAO for the design variable - ''' - + """ DVs = { Aircraft.Battery.Cell.DISCHARGE_RATE: { 'units': 'A', @@ -183,7 +184,7 @@ def get_design_vars(self): return DVs def get_parameters(self, aviary_inputs=None, phase_info=None): - ''' + """ Return a dictionary of fixed values exposed to the phases for the battery subsystem. Returns @@ -197,17 +198,16 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): - 'units': str or None The units for the variable. - any additional keyword arguments required by OpenMDAO for the variable. - ''' - + """ parameters_dict = { - Mission.Battery.TEMPERATURE: {'val': 25.0, 'units': 'degC'}, - Mission.Battery.CURRENT: {'val': 3.25, 'units': 'A'} + Dynamic.Battery.TEMPERATURE: {'val': 25.0, 'units': 'degC'}, + Dynamic.Battery.CURRENT: {'val': 3.25, 'units': 'A'}, } return parameters_dict def get_initial_guesses(self): - ''' + """ Return a dictionary of initial guesses for the battery subsystem. Returns @@ -216,14 +216,13 @@ def get_initial_guesses(self): A dictionary where the keys are the names of the initial guesses and the values are dictionaries with any additional keyword arguments required by OpenMDAO for the variable. - ''' - + """ initial_guess_dict = { - Mission.Battery.STATE_OF_CHARGE: { + Dynamic.Battery.STATE_OF_CHARGE: { 'val': 1.0, 'type': 'state', }, - Mission.Battery.VOLTAGE_THEVENIN: { + Dynamic.Battery.VOLTAGE_THEVENIN: { 'val': 5.0, 'units': 'V', 'type': 'state', @@ -233,32 +232,32 @@ def get_initial_guesses(self): return initial_guess_dict def get_mass_names(self): - ''' + """ Return a list of names for the battery subsystem. Returns ------- mass_names : list A list of names for the battery subsystem. - ''' + """ return [Aircraft.Battery.MASS] def preprocess_inputs(self, aviary_inputs): - ''' + """ Preprocess the inputs for the battery subsystem. Description ----------- This method preprocesses the inputs for the battery subsystem. In this case, it sets the values battery performance based on the battery cell type. - ''' + """ battery_cell_info_18650 = { Aircraft.Battery.Cell.DISCHARGE_RATE: [2.0, 'A'], Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX: [3.5, 'A*h'], Aircraft.Battery.Cell.HEAT_CAPACITY: [1020.0, 'J/(kg*K)'], Aircraft.Battery.Cell.MASS: [0.045, 'kg'], Aircraft.Battery.Cell.VOLTAGE_LOW: [2.9, 'V'], - Aircraft.Battery.Cell.VOLUME: [1.125, 'inch**3'] + Aircraft.Battery.Cell.VOLUME: [1.125, 'inch**3'], } for key, val in battery_cell_info_18650.items(): @@ -267,13 +266,16 @@ def preprocess_inputs(self, aviary_inputs): return aviary_inputs def get_outputs(self): - ''' + """ Return a list of output names for the battery subsystem. Returns ------- outputs : list A list of variable names for the battery subsystem. - ''' - - return [Mission.Battery.VOLTAGE, Mission.Battery.HEAT_OUT, Aircraft.Battery.EFFICIENCY] + """ + return [ + Dynamic.Battery.VOLTAGE, + Dynamic.Battery.HEAT_OUT, + Dynamic.Battery.EFFICIENCY, + ] diff --git a/aviary/examples/external_subsystems/battery/battery_variable_meta_data.py b/aviary/examples/external_subsystems/battery/battery_variable_meta_data.py index 5fd87a3727..9cac36e7cb 100644 --- a/aviary/examples/external_subsystems/battery/battery_variable_meta_data.py +++ b/aviary/examples/external_subsystems/battery/battery_variable_meta_data.py @@ -1,7 +1,5 @@ -import numpy as np import aviary.api as av -from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Mission - +from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Dynamic ExtendedMetaData = av.CoreMetaData @@ -10,180 +8,197 @@ av.add_meta_data( Aircraft.Battery.CURRENT_MAX, - units="A", - desc="Max current through the pack", - default_value=10., - meta_data=ExtendedMetaData + units='A', + desc='Max current through the pack', + default_value=10.0, + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.ENERGY_REQUIRED, - units="kW*h", - desc="Required battery energy", + units='kW*h', + desc='Required battery energy', default_value=65.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.HEAT_CAPACITY, - units="J/(kg*K)", - desc="mass-averaged specific heat (cp)", + units='J/(kg*K)', + desc='mass-averaged specific heat (cp)', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.N_PARALLEL, units=None, - desc="Number of cells in parallel, based on power constraint", + desc='Number of cells in parallel, based on power constraint', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.N_SERIES, units=None, - desc="Number of cells in series", + desc='Number of cells in series', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.VOLTAGE, - units="V", - desc="Nominal bus voltage", + units='V', + desc='Nominal bus voltage', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) ##### CASE VALUES ##### av.add_meta_data( Aircraft.Battery.Case.HEAT_CAPACITY, - units="J/(kg*K)", - desc="Mass-averaged specific heat (cp)", + units='J/(kg*K)', + desc='Mass-averaged specific heat (cp)', default_value=921.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.Case.WEIGHT_FRAC, units=None, - desc="Case weight per unit of cell weight", + desc='Case weight per unit of cell weight', default_value=1.3, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) ##### CELL VALUES ##### av.add_meta_data( Aircraft.Battery.Cell.DISCHARGE_RATE, - units="A", - desc="Cell discharge rate", + units='A', + desc='Cell discharge rate', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, - units="A*h", - desc="Maximum energy capacity of a single cell (Q_max)", + units='A*h', + desc='Maximum energy capacity of a single cell (Q_max)', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.Cell.HEAT_CAPACITY, - units="J/(kg*K)", - desc="Specific heat of a battery cell", + units='J/(kg*K)', + desc='Specific heat of a battery cell', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.Cell.MASS, - units="kg", - desc="Mass of a single cell", + units='kg', + desc='Mass of a single cell', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.Cell.VOLTAGE_LOW, - units="V", - desc="Cell Voltage at low SOC, before drop-off", + units='V', + desc='Cell Voltage at low SOC, before drop-off', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Battery.Cell.VOLUME, - units="inch**3", - desc="Volume of a single cell", + units='inch**3', + desc='Volume of a single cell', default_value=1.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, +) + +av.add_meta_data( + Dynamic.Battery.CURRENT, + units='A', + desc='Current output from the battery', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.CURRENT, - units="A", - desc="Current output from the battery", - default_value=None, - meta_data=ExtendedMetaData + Dynamic.Battery.EFFICIENCY, + units='unitless', + desc='Current efficiency of the battery', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.HEAT_OUT, - units="W", - desc="Heat generated by the battery", - default_value=None, - meta_data=ExtendedMetaData + Dynamic.Battery.HEAT_OUT, + units='W', + desc='Heat generated by the battery', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.STATE_OF_CHARGE, + Dynamic.Battery.STATE_OF_CHARGE, units=None, - desc="State of charge of the battery (SOC)", - default_value=None, - meta_data=ExtendedMetaData + desc='State of charge of the battery (SOC)', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.STATE_OF_CHARGE_RATE, - units="1/s", - desc="Time rate of change of the battery state of charge", - default_value=None, - meta_data=ExtendedMetaData + Dynamic.Battery.STATE_OF_CHARGE_RATE, + units='1/s', + desc='Time rate of change of the battery state of charge', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.TEMPERATURE, - units="K", - desc="Battery pack bulk temperature", - default_value=None, - meta_data=ExtendedMetaData + Dynamic.Battery.TEMPERATURE, + units='K', + desc='Battery pack bulk temperature', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.VOLTAGE, - units="V", - desc="Total battery voltage", - default_value=None, - meta_data=ExtendedMetaData + Dynamic.Battery.VOLTAGE, + units='V', + desc='Total battery voltage', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.VOLTAGE_THEVENIN, - units="V", - desc="Thevenin (Polarization) voltage", - default_value=None, - meta_data=ExtendedMetaData + Dynamic.Battery.VOLTAGE_THEVENIN, + units='V', + desc='Thevenin (Polarization) voltage', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) av.add_meta_data( - Mission.Battery.VOLTAGE_THEVENIN_RATE, - units="V/s", - desc="Time rate of change of Thevenin voltage", - default_value=None, - meta_data=ExtendedMetaData + Dynamic.Battery.VOLTAGE_THEVENIN_RATE, + units='V/s', + desc='Time rate of change of Thevenin voltage', + default_value=0.0, + multivalue=True, + meta_data=ExtendedMetaData, ) diff --git a/aviary/examples/external_subsystems/battery/battery_variables.py b/aviary/examples/external_subsystems/battery/battery_variables.py index f6d8530e35..48f32d4c3a 100644 --- a/aviary/examples/external_subsystems/battery/battery_variables.py +++ b/aviary/examples/external_subsystems/battery/battery_variables.py @@ -1,50 +1,47 @@ from aviary.variable_info.variables import Aircraft as av_Aircraft -from aviary.variable_info.variables import Mission as av_Mission +from aviary.variable_info.variables import Dynamic as av_Dynamic AviaryAircraft = av_Aircraft -AviaryMission = av_Mission +AviaryDynamic = av_Dynamic class Aircraft(AviaryAircraft): - """ - Aircraft data hierarchy for battery subsystem. - """ + """Aircraft data hierarchy for battery subsystem.""" # cell = single cell, battery = one case plus multiple cells class Battery(AviaryAircraft.Battery): - CURRENT_MAX = "aircraft:battery:current_max" - ENERGY_REQUIRED = "aircraft:battery:energy_required" - HEAT_CAPACITY = "aircraft:battery:heat_capacity" - N_PARALLEL = "aircraft:battery:n_parallel" - N_SERIES = "aircraft:battery:n_series" - VOLTAGE = "aircraft:battery:voltage" + CURRENT_MAX = 'aircraft:battery:current_max' + ENERGY_REQUIRED = 'aircraft:battery:energy_required' + HEAT_CAPACITY = 'aircraft:battery:heat_capacity' + N_PARALLEL = 'aircraft:battery:n_parallel' + N_SERIES = 'aircraft:battery:n_series' + VOLTAGE = 'aircraft:battery:voltage' class Case: - HEAT_CAPACITY = "aircraft:battery:case:heat_capacity" - WEIGHT_FRAC = "aircraft:battery:case:weight_frac" + HEAT_CAPACITY = 'aircraft:battery:case:heat_capacity' + WEIGHT_FRAC = 'aircraft:battery:case:weight_frac' class Cell: - DISCHARGE_RATE = "aircraft:battery:cell:discharge_rate" - ENERGY_CAPACITY_MAX = "aircraft:battery:cell:energy_capacity_max" - HEAT_CAPACITY = "aircraft:battery:cell:heat_capacity" - MASS = "aircraft:battery:cell:mass" - VOLTAGE_LOW = "aircraft:battery:cell:voltage_low" - VOLUME = "aircraft:battery:cell:volume" - TYPE = "aircraft:battery:cell:type" + DISCHARGE_RATE = 'aircraft:battery:cell:discharge_rate' + ENERGY_CAPACITY_MAX = 'aircraft:battery:cell:energy_capacity_max' + HEAT_CAPACITY = 'aircraft:battery:cell:heat_capacity' + MASS = 'aircraft:battery:cell:mass' + VOLTAGE_LOW = 'aircraft:battery:cell:voltage_low' + VOLUME = 'aircraft:battery:cell:volume' + TYPE = 'aircraft:battery:cell:type' -class Mission(AviaryMission): - """ - Mission data hierarchy for battery subsystem. - """ +class Dynamic(AviaryDynamic): + """Dynamic data hierarchy for battery subsystem.""" class Battery: - CURRENT = "mission:battery:current" - HEAT_OUT = "mission:battery:heat_out" - STATE_OF_CHARGE = "mission:battery:state_of_charge" - STATE_OF_CHARGE_RATE = "mission:battery:state_of_charge_rate" - TEMPERATURE = "mission:battery:temperature" - VOLTAGE = "mission:battery:voltage" - VOLTAGE_THEVENIN = "mission:battery:voltage_thevenin" - VOLTAGE_THEVENIN_RATE = "mission:battery:voltage_thevenin_rate" + CURRENT = 'dynamic:battery:current' + EFFICIENCY = 'dynamic:battery:efficiency' + HEAT_OUT = 'dynamic:battery:heat_out' + STATE_OF_CHARGE = 'dynamic:battery:state_of_charge' + STATE_OF_CHARGE_RATE = 'dynamic:battery:state_of_charge_rate' + TEMPERATURE = 'dynamic:battery:temperature' + VOLTAGE = 'dynamic:battery:voltage' + VOLTAGE_THEVENIN = 'dynamic:battery:voltage_thevenin' + VOLTAGE_THEVENIN_RATE = 'dynamic:battery:voltage_thevenin_rate' diff --git a/aviary/examples/external_subsystems/battery/model/battery_mission.py b/aviary/examples/external_subsystems/battery/model/battery_mission.py index 50195cec7c..6ca1e19742 100644 --- a/aviary/examples/external_subsystems/battery/model/battery_mission.py +++ b/aviary/examples/external_subsystems/battery/model/battery_mission.py @@ -2,7 +2,7 @@ Battery Performance Modeling on Maxwell X-57 Jeffrey C. Chin, Sydney L. Schnulo, Thomas B. Miller, Kevin Prokopius, and Justin Gray -http://openmdao.org/pubs/chin_battery_performance_x57_2019.pdf +http://openmdao.org/pubs/chin_battery_performance_x57_2019.pdf. Thevenin voltage equation based on paper "Evaluation of Lithium Ion Battery Equivalent Circuit Models @@ -16,56 +16,59 @@ """ from openmdao.api import Group -from aviary.examples.external_subsystems.battery.model.cell_comp import CellComp -from aviary.examples.external_subsystems.battery.model.reg_thevenin_interp_group import RegTheveninInterpGroup +from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Dynamic +from aviary.examples.external_subsystems.battery.model.cell_comp import CellComp +from aviary.examples.external_subsystems.battery.model.reg_thevenin_interp_group import ( + RegTheveninInterpGroup, +) from aviary.utils.aviary_values import AviaryValues -from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Mission class BatteryMission(Group): """Assembly to connect subcomponents of the Thevenin Battery Equivalent - Circuit Model From Interpolated Performance Maps + Circuit Model From Interpolated Performance Maps. """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) self.options.declare( - 'aviary_inputs', types=AviaryValues, + 'aviary_inputs', + types=AviaryValues, desc='collection of Aircraft/Mission specific options', default=None, ) def setup(self): - n = self.options["num_nodes"] + n = self.options['num_nodes'] self.add_subsystem( - name="interp_group", + name='interp_group', subsys=RegTheveninInterpGroup(num_nodes=n), ) - self.add_subsystem(name="cell", subsys=CellComp(num_nodes=n)) + self.add_subsystem(name='cell', subsys=CellComp(num_nodes=n)) # Connect internal names - self.connect("interp_group.U_oc", "cell.U_oc") - self.connect("interp_group.C_Th", "cell.C_Th") - self.connect("interp_group.R_Th", "cell.R_Th") - self.connect("interp_group.R_0", "cell.R_0") + self.connect('interp_group.U_oc', 'cell.U_oc') + self.connect('interp_group.C_Th', 'cell.C_Th') + self.connect('interp_group.R_Th', 'cell.R_Th') + self.connect('interp_group.R_0', 'cell.R_0') # Promote interp group inputs to match Aviary variable names self.promotes( - "interp_group", + 'interp_group', inputs=[ - ("T_batt", "mission:battery:temperature"), - ("SOC", "mission:battery:state_of_charge"), + ('T_batt', 'dynamic:battery:temperature'), + ('SOC', 'dynamic:battery:state_of_charge'), ], ) self.promotes( - "cell", + 'cell', inputs=[ - Mission.Battery.VOLTAGE_THEVENIN, - Mission.Battery.CURRENT, + Dynamic.Battery.VOLTAGE_THEVENIN, + Dynamic.Battery.CURRENT, Aircraft.Battery.N_SERIES, Aircraft.Battery.N_PARALLEL, Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, @@ -73,12 +76,12 @@ def setup(self): ) self.promotes( - "cell", + 'cell', outputs=[ - Mission.Battery.VOLTAGE, - Mission.Battery.VOLTAGE_THEVENIN_RATE, - Mission.Battery.STATE_OF_CHARGE_RATE, - Mission.Battery.HEAT_OUT, - Aircraft.Battery.EFFICIENCY, + Dynamic.Battery.VOLTAGE, + Dynamic.Battery.VOLTAGE_THEVENIN_RATE, + Dynamic.Battery.STATE_OF_CHARGE_RATE, + Dynamic.Battery.HEAT_OUT, + Dynamic.Battery.EFFICIENCY, ], ) diff --git a/aviary/examples/external_subsystems/battery/model/battery_premission.py b/aviary/examples/external_subsystems/battery/model/battery_premission.py index 0d39fbb87e..81f054da39 100644 --- a/aviary/examples/external_subsystems/battery/model/battery_premission.py +++ b/aviary/examples/external_subsystems/battery/model/battery_premission.py @@ -1,60 +1,50 @@ import openmdao.api as om -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Mission from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData +from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Dynamic +from aviary.variable_info.functions import add_aviary_input, add_aviary_output class BatteryPreMission(om.ExplicitComponent): - """ - Calculates battery pack mass - """ + """Calculates battery pack mass.""" def setup(self): - # Inputs # control from optimizer - add_aviary_input(self, Aircraft.Battery.ENERGY_REQUIRED, - meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.EFFICIENCY, meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.ENERGY_REQUIRED, meta_data=ExtendedMetaData) + add_aviary_input(self, Dynamic.Battery.EFFICIENCY, meta_data=ExtendedMetaData) # output from zappy add_aviary_input(self, Aircraft.Battery.CURRENT_MAX, meta_data=ExtendedMetaData) # params (fixed) - add_aviary_input(self, Aircraft.Battery.Cell.HEAT_CAPACITY, - meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.Case.HEAT_CAPACITY, - meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.Cell.HEAT_CAPACITY, meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.Case.HEAT_CAPACITY, meta_data=ExtendedMetaData) add_aviary_input(self, Aircraft.Battery.Cell.MASS, meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.Cell.VOLTAGE_LOW, - meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.Cell.DISCHARGE_RATE, - meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, - meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.Case.WEIGHT_FRAC, - meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.Cell.VOLTAGE_LOW, meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.Cell.DISCHARGE_RATE, meta_data=ExtendedMetaData) + add_aviary_input( + self, Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, meta_data=ExtendedMetaData + ) + add_aviary_input(self, Aircraft.Battery.Case.WEIGHT_FRAC, meta_data=ExtendedMetaData) add_aviary_input(self, Aircraft.Battery.VOLTAGE, meta_data=ExtendedMetaData) add_aviary_input(self, Aircraft.Battery.Cell.VOLUME, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.N_SERIES, - val=0.0, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.N_PARALLEL, - val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.N_SERIES, val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.N_PARALLEL, val=0.0, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.MASS, - val=0.0, meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.HEAT_CAPACITY, - val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.MASS, val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.HEAT_CAPACITY, val=0.0, meta_data=ExtendedMetaData) # unconnected output used for test checking - add_aviary_output(self, Aircraft.Battery.VOLUME, - val=0.0, meta_data=ExtendedMetaData) + add_aviary_output(self, Aircraft.Battery.VOLUME, val=0.0, meta_data=ExtendedMetaData) - self.declare_partials(Aircraft.Battery.N_SERIES, [ - Aircraft.Battery.VOLTAGE, Aircraft.Battery.Cell.VOLTAGE_LOW]) - self.declare_partials(Aircraft.Battery.N_PARALLEL, [ - Aircraft.Battery.CURRENT_MAX, Aircraft.Battery.Cell.DISCHARGE_RATE]) + self.declare_partials( + Aircraft.Battery.N_SERIES, [Aircraft.Battery.VOLTAGE, Aircraft.Battery.Cell.VOLTAGE_LOW] + ) + self.declare_partials( + Aircraft.Battery.N_PARALLEL, + [Aircraft.Battery.CURRENT_MAX, Aircraft.Battery.Cell.DISCHARGE_RATE], + ) self.declare_partials( Aircraft.Battery.MASS, [ @@ -67,8 +57,14 @@ def setup(self): ], ) - self.declare_partials(Aircraft.Battery.HEAT_CAPACITY, [ - Aircraft.Battery.Case.HEAT_CAPACITY, Aircraft.Battery.Cell.HEAT_CAPACITY, Aircraft.Battery.Case.WEIGHT_FRAC]) + self.declare_partials( + Aircraft.Battery.HEAT_CAPACITY, + [ + Aircraft.Battery.Case.HEAT_CAPACITY, + Aircraft.Battery.Cell.HEAT_CAPACITY, + Aircraft.Battery.Case.WEIGHT_FRAC, + ], + ) self.declare_partials( Aircraft.Battery.VOLUME, [ @@ -81,14 +77,14 @@ def setup(self): ) def compute(self, inputs, outputs): - bus_v = inputs[Aircraft.Battery.VOLTAGE] c_l_v = inputs[Aircraft.Battery.Cell.VOLTAGE_LOW] max_amps = inputs[Aircraft.Battery.CURRENT_MAX] outputs[Aircraft.Battery.N_SERIES] = bus_v / c_l_v - outputs[Aircraft.Battery.N_PARALLEL] = max_amps / \ - inputs[Aircraft.Battery.Cell.DISCHARGE_RATE] + outputs[Aircraft.Battery.N_PARALLEL] = ( + max_amps / inputs[Aircraft.Battery.Cell.DISCHARGE_RATE] + ) outputs[Aircraft.Battery.MASS] = ( outputs[Aircraft.Battery.N_SERIES] * outputs[Aircraft.Battery.N_PARALLEL] @@ -96,16 +92,17 @@ def compute(self, inputs, outputs): * inputs[Aircraft.Battery.Case.WEIGHT_FRAC] ) outputs[Aircraft.Battery.HEAT_CAPACITY] = ( - inputs[Aircraft.Battery.Cell.HEAT_CAPACITY] + inputs[Aircraft.Battery.Case.HEAT_CAPACITY] * - (1.0 - inputs[Aircraft.Battery.Case.WEIGHT_FRAC]) + inputs[Aircraft.Battery.Cell.HEAT_CAPACITY] + + inputs[Aircraft.Battery.Case.HEAT_CAPACITY] + * (1.0 - inputs[Aircraft.Battery.Case.WEIGHT_FRAC]) ) / inputs[Aircraft.Battery.Case.WEIGHT_FRAC] outputs[Aircraft.Battery.VOLUME] = ( - outputs[Aircraft.Battery.N_SERIES] * - outputs[Aircraft.Battery.N_PARALLEL] * inputs[Aircraft.Battery.Cell.VOLUME] + outputs[Aircraft.Battery.N_SERIES] + * outputs[Aircraft.Battery.N_PARALLEL] + * inputs[Aircraft.Battery.Cell.VOLUME] ) def compute_partials(self, inputs, partials): - bus_v = inputs[Aircraft.Battery.VOLTAGE] c_l_v = inputs[Aircraft.Battery.Cell.VOLTAGE_LOW] max_amps = inputs[Aircraft.Battery.CURRENT_MAX] @@ -120,55 +117,57 @@ def compute_partials(self, inputs, partials): # n_{series} partials[Aircraft.Battery.N_SERIES, Aircraft.Battery.VOLTAGE] = 1.0 / c_l_v - partials[Aircraft.Battery.N_SERIES, - Aircraft.Battery.Cell.VOLTAGE_LOW] = -bus_v / (c_l_v ** 2) + partials[Aircraft.Battery.N_SERIES, Aircraft.Battery.Cell.VOLTAGE_LOW] = -bus_v / (c_l_v**2) # n_{parallel} - partials[Aircraft.Battery.N_PARALLEL, - Aircraft.Battery.CURRENT_MAX] = 1.0 / I_rate - partials[Aircraft.Battery.N_PARALLEL, - Aircraft.Battery.Cell.DISCHARGE_RATE] = -max_amps / (I_rate ** 2) + partials[Aircraft.Battery.N_PARALLEL, Aircraft.Battery.CURRENT_MAX] = 1.0 / I_rate + partials[Aircraft.Battery.N_PARALLEL, Aircraft.Battery.Cell.DISCHARGE_RATE] = -max_amps / ( + I_rate**2 + ) # mass_{battery} partials[Aircraft.Battery.MASS, Aircraft.Battery.VOLTAGE] = ( - partials[Aircraft.Battery.N_SERIES, - Aircraft.Battery.VOLTAGE] * n_p * m_cell * wf_case + partials[Aircraft.Battery.N_SERIES, Aircraft.Battery.VOLTAGE] * n_p * m_cell * wf_case ) partials[Aircraft.Battery.MASS, Aircraft.Battery.Cell.VOLTAGE_LOW] = ( - partials[Aircraft.Battery.N_SERIES, - Aircraft.Battery.Cell.VOLTAGE_LOW] * n_p * m_cell * wf_case + partials[Aircraft.Battery.N_SERIES, Aircraft.Battery.Cell.VOLTAGE_LOW] + * n_p + * m_cell + * wf_case ) partials[Aircraft.Battery.MASS, Aircraft.Battery.CURRENT_MAX] = ( - partials[Aircraft.Battery.N_PARALLEL, - Aircraft.Battery.CURRENT_MAX] * n_s * m_cell * wf_case + partials[Aircraft.Battery.N_PARALLEL, Aircraft.Battery.CURRENT_MAX] + * n_s + * m_cell + * wf_case ) partials[Aircraft.Battery.MASS, Aircraft.Battery.Cell.DISCHARGE_RATE] = ( - partials[Aircraft.Battery.N_PARALLEL, - Aircraft.Battery.Cell.DISCHARGE_RATE] * n_s * m_cell * wf_case + partials[Aircraft.Battery.N_PARALLEL, Aircraft.Battery.Cell.DISCHARGE_RATE] + * n_s + * m_cell + * wf_case ) partials[Aircraft.Battery.MASS, Aircraft.Battery.Cell.MASS] = n_s * n_p * wf_case - partials[Aircraft.Battery.MASS, - Aircraft.Battery.Case.WEIGHT_FRAC] = n_s * n_p * m_cell + partials[Aircraft.Battery.MASS, Aircraft.Battery.Case.WEIGHT_FRAC] = n_s * n_p * m_cell # C_{p,batt} - partials[Aircraft.Battery.HEAT_CAPACITY, - Aircraft.Battery.Cell.HEAT_CAPACITY] = 1.0 / wf_case - partials[Aircraft.Battery.HEAT_CAPACITY, - Aircraft.Battery.Case.HEAT_CAPACITY] = (1.0 - wf_case) / wf_case + partials[Aircraft.Battery.HEAT_CAPACITY, Aircraft.Battery.Cell.HEAT_CAPACITY] = ( + 1.0 / wf_case + ) + partials[Aircraft.Battery.HEAT_CAPACITY, Aircraft.Battery.Case.HEAT_CAPACITY] = ( + 1.0 - wf_case + ) / wf_case partials[Aircraft.Battery.HEAT_CAPACITY, Aircraft.Battery.Case.WEIGHT_FRAC] = ( - -(cp_cell + cp_case) / wf_case ** 2 + -(cp_cell + cp_case) / wf_case**2 ) # volume_{pack} partials[Aircraft.Battery.VOLUME, Aircraft.Battery.VOLTAGE] = ( partials[Aircraft.Battery.N_SERIES, Aircraft.Battery.VOLTAGE] * n_p * vc ) partials[Aircraft.Battery.VOLUME, Aircraft.Battery.Cell.VOLTAGE_LOW] = ( - partials[Aircraft.Battery.N_SERIES, - Aircraft.Battery.Cell.VOLTAGE_LOW] * n_p * vc + partials[Aircraft.Battery.N_SERIES, Aircraft.Battery.Cell.VOLTAGE_LOW] * n_p * vc ) partials[Aircraft.Battery.VOLUME, Aircraft.Battery.CURRENT_MAX] = ( - partials[Aircraft.Battery.N_PARALLEL, - Aircraft.Battery.CURRENT_MAX] * n_s * vc + partials[Aircraft.Battery.N_PARALLEL, Aircraft.Battery.CURRENT_MAX] * n_s * vc ) partials[Aircraft.Battery.VOLUME, Aircraft.Battery.Cell.DISCHARGE_RATE] = ( - partials[Aircraft.Battery.N_PARALLEL, - Aircraft.Battery.Cell.DISCHARGE_RATE] * n_s * vc + partials[Aircraft.Battery.N_PARALLEL, Aircraft.Battery.Cell.DISCHARGE_RATE] * n_s * vc ) partials[Aircraft.Battery.VOLUME, Aircraft.Battery.Cell.VOLUME] = n_s * n_p diff --git a/aviary/examples/external_subsystems/battery/model/cell_comp.py b/aviary/examples/external_subsystems/battery/model/cell_comp.py index d442f75cb8..c946d538df 100644 --- a/aviary/examples/external_subsystems/battery/model/cell_comp.py +++ b/aviary/examples/external_subsystems/battery/model/cell_comp.py @@ -1,16 +1,13 @@ import numpy as np - from openmdao.api import ExplicitComponent -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Mission from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData +from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Dynamic +from aviary.variable_info.functions import add_aviary_input, add_aviary_output class CellComp(ExplicitComponent): - """ - Compute behavior of a single battery cell then expand to the full pack. - """ + """Compute behavior of a single battery cell then expand to the full pack.""" def initialize(self): self.options.declare('num_nodes', types=int) @@ -19,217 +16,289 @@ def setup(self): n = self.options['num_nodes'] # Inputs - add_aviary_input(self, Mission.Battery.CURRENT, val=3.25 * - np.ones(n), meta_data=ExtendedMetaData) + add_aviary_input( + self, + Dynamic.Battery.CURRENT, + val=3.25 * np.ones(n), + meta_data=ExtendedMetaData, + ) # Static Constants - add_aviary_input(self, Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, - meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.N_PARALLEL, - val=40., meta_data=ExtendedMetaData) - add_aviary_input(self, Aircraft.Battery.N_SERIES, - val=128.0, meta_data=ExtendedMetaData) + add_aviary_input( + self, Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, meta_data=ExtendedMetaData + ) + add_aviary_input(self, Aircraft.Battery.N_PARALLEL, val=40.0, meta_data=ExtendedMetaData) + add_aviary_input(self, Aircraft.Battery.N_SERIES, val=128.0, meta_data=ExtendedMetaData) # Integrated State Variables - add_aviary_input(self, Mission.Battery.STATE_OF_CHARGE, - val=0.98*np.ones(n), meta_data=ExtendedMetaData) - add_aviary_input(self, Mission.Battery.VOLTAGE_THEVENIN, - val=np.ones(n), meta_data=ExtendedMetaData) + add_aviary_input( + self, + Dynamic.Battery.STATE_OF_CHARGE, + val=0.98 * np.ones(n), + meta_data=ExtendedMetaData, + ) + add_aviary_input( + self, + Dynamic.Battery.VOLTAGE_THEVENIN, + val=np.ones(n), + meta_data=ExtendedMetaData, + ) # Map Inputs From The Interpolation Component - self.add_input('U_oc', val=4.16*np.ones(n), - units='V', desc='Open-circuit voltage') - self.add_input('C_Th', val=2000.*np.ones(n), units='F', - desc='Thevenin RC parallel capacitance (polarization)') - self.add_input('R_Th', val=0.01*np.ones(n), units='ohm', - desc='Thevenin RC parallel resistance (polarization)') - self.add_input('R_0', val=0.01*np.ones(n), units='ohm', - desc='Internal resistance of the battery') + self.add_input('U_oc', val=4.16 * np.ones(n), units='V', desc='Open-circuit voltage') + self.add_input( + 'C_Th', + val=2000.0 * np.ones(n), + units='F', + desc='Thevenin RC parallel capacitance (polarization)', + ) + self.add_input( + 'R_Th', + val=0.01 * np.ones(n), + units='ohm', + desc='Thevenin RC parallel resistance (polarization)', + ) + self.add_input( + 'R_0', val=0.01 * np.ones(n), units='ohm', desc='Internal resistance of the battery' + ) # Outputs - add_aviary_output(self, Mission.Battery.STATE_OF_CHARGE_RATE, - val=np.ones(n), meta_data=ExtendedMetaData) - add_aviary_output(self, Mission.Battery.VOLTAGE_THEVENIN_RATE, - val=np.ones(n), meta_data=ExtendedMetaData) - add_aviary_output(self, Mission.Battery.VOLTAGE, val=416 * - np.ones(n), meta_data=ExtendedMetaData) - add_aviary_output(self, Mission.Battery.HEAT_OUT, - val=np.ones(n), meta_data=ExtendedMetaData) - add_aviary_output(self, Aircraft.Battery.EFFICIENCY, - val=np.ones(n), meta_data=ExtendedMetaData) + add_aviary_output( + self, + Dynamic.Battery.STATE_OF_CHARGE_RATE, + val=np.ones(n), + meta_data=ExtendedMetaData, + ) + add_aviary_output( + self, + Dynamic.Battery.VOLTAGE_THEVENIN_RATE, + val=np.ones(n), + meta_data=ExtendedMetaData, + ) + add_aviary_output( + self, + Dynamic.Battery.VOLTAGE, + val=416 * np.ones(n), + meta_data=ExtendedMetaData, + ) + add_aviary_output( + self, Dynamic.Battery.HEAT_OUT, val=np.ones(n), meta_data=ExtendedMetaData + ) + add_aviary_output( + self, Dynamic.Battery.EFFICIENCY, val=np.ones(n), meta_data=ExtendedMetaData + ) # Partials self.declare_partials(of='*', wrt='*', dependent=False) ar = np.arange(n) - self.declare_partials(of=Mission.Battery.STATE_OF_CHARGE_RATE, - wrt=Mission.Battery.CURRENT, rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.STATE_OF_CHARGE_RATE, - wrt=Aircraft.Battery.N_PARALLEL) - self.declare_partials(of=Mission.Battery.STATE_OF_CHARGE_RATE, - wrt=Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX) - - self.declare_partials(of=Mission.Battery.VOLTAGE_THEVENIN_RATE, - wrt=Mission.Battery.VOLTAGE_THEVENIN, rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE_THEVENIN_RATE, - wrt='R_Th', rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE_THEVENIN_RATE, - wrt='C_Th', rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE_THEVENIN_RATE, - wrt=Mission.Battery.CURRENT, rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE_THEVENIN_RATE, - wrt=Aircraft.Battery.N_PARALLEL) - - self.declare_partials(of=Mission.Battery.VOLTAGE, wrt='U_oc', rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE, - wrt=Mission.Battery.VOLTAGE_THEVENIN, rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE, - wrt=Mission.Battery.CURRENT, rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE, - wrt=Aircraft.Battery.N_PARALLEL) - self.declare_partials(of=Mission.Battery.VOLTAGE, wrt='R_0', rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.VOLTAGE, - wrt=Aircraft.Battery.N_SERIES) - - self.declare_partials(of=Mission.Battery.HEAT_OUT, - wrt=Mission.Battery.CURRENT, rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.HEAT_OUT, - wrt=Aircraft.Battery.N_PARALLEL) - self.declare_partials(of=Mission.Battery.HEAT_OUT, - wrt=Aircraft.Battery.N_SERIES) - self.declare_partials(of=Mission.Battery.HEAT_OUT, wrt='R_0', rows=ar, cols=ar) - self.declare_partials(of=Mission.Battery.HEAT_OUT, - wrt=Mission.Battery.VOLTAGE_THEVENIN, rows=ar, cols=ar) - - self.declare_partials(of=Aircraft.Battery.EFFICIENCY, - wrt=Mission.Battery.CURRENT, rows=ar, cols=ar) - self.declare_partials(of=Aircraft.Battery.EFFICIENCY, - wrt=Aircraft.Battery.N_PARALLEL) - # self.declare_partials(of=Aircraft.Battery.EFFICIENCY, wrt=Aircraft.Battery.N_SERIES, rows=ar, cols=ar) # known 0 - self.declare_partials(of=Aircraft.Battery.EFFICIENCY, - wrt='R_0', rows=ar, cols=ar) - self.declare_partials(of=Aircraft.Battery.EFFICIENCY, - wrt=Mission.Battery.VOLTAGE_THEVENIN, rows=ar, cols=ar) - self.declare_partials(of=Aircraft.Battery.EFFICIENCY, - wrt='U_oc', rows=ar, cols=ar) + self.declare_partials( + of=Dynamic.Battery.STATE_OF_CHARGE_RATE, + wrt=Dynamic.Battery.CURRENT, + rows=ar, + cols=ar, + ) + self.declare_partials( + of=Dynamic.Battery.STATE_OF_CHARGE_RATE, wrt=Aircraft.Battery.N_PARALLEL + ) + self.declare_partials( + of=Dynamic.Battery.STATE_OF_CHARGE_RATE, + wrt=Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, + ) + + self.declare_partials( + of=Dynamic.Battery.VOLTAGE_THEVENIN_RATE, + wrt=Dynamic.Battery.VOLTAGE_THEVENIN, + rows=ar, + cols=ar, + ) + self.declare_partials( + of=Dynamic.Battery.VOLTAGE_THEVENIN_RATE, wrt='R_Th', rows=ar, cols=ar + ) + self.declare_partials( + of=Dynamic.Battery.VOLTAGE_THEVENIN_RATE, wrt='C_Th', rows=ar, cols=ar + ) + self.declare_partials( + of=Dynamic.Battery.VOLTAGE_THEVENIN_RATE, + wrt=Dynamic.Battery.CURRENT, + rows=ar, + cols=ar, + ) + self.declare_partials( + of=Dynamic.Battery.VOLTAGE_THEVENIN_RATE, wrt=Aircraft.Battery.N_PARALLEL + ) + + self.declare_partials(of=Dynamic.Battery.VOLTAGE, wrt='U_oc', rows=ar, cols=ar) + self.declare_partials( + of=Dynamic.Battery.VOLTAGE, + wrt=Dynamic.Battery.VOLTAGE_THEVENIN, + rows=ar, + cols=ar, + ) + self.declare_partials( + of=Dynamic.Battery.VOLTAGE, wrt=Dynamic.Battery.CURRENT, rows=ar, cols=ar + ) + self.declare_partials(of=Dynamic.Battery.VOLTAGE, wrt=Aircraft.Battery.N_PARALLEL) + self.declare_partials(of=Dynamic.Battery.VOLTAGE, wrt='R_0', rows=ar, cols=ar) + self.declare_partials(of=Dynamic.Battery.VOLTAGE, wrt=Aircraft.Battery.N_SERIES) + + self.declare_partials( + of=Dynamic.Battery.HEAT_OUT, wrt=Dynamic.Battery.CURRENT, rows=ar, cols=ar + ) + self.declare_partials(of=Dynamic.Battery.HEAT_OUT, wrt=Aircraft.Battery.N_PARALLEL) + self.declare_partials(of=Dynamic.Battery.HEAT_OUT, wrt=Aircraft.Battery.N_SERIES) + self.declare_partials(of=Dynamic.Battery.HEAT_OUT, wrt='R_0', rows=ar, cols=ar) + self.declare_partials( + of=Dynamic.Battery.HEAT_OUT, + wrt=Dynamic.Battery.VOLTAGE_THEVENIN, + rows=ar, + cols=ar, + ) + + self.declare_partials( + of=Dynamic.Battery.EFFICIENCY, + wrt=Dynamic.Battery.CURRENT, + rows=ar, + cols=ar, + ) + self.declare_partials(of=Dynamic.Battery.EFFICIENCY, wrt=Aircraft.Battery.N_PARALLEL) + # self.declare_partials(of=Dynamic.Battery.EFFICIENCY, wrt=Aircraft.Battery.N_SERIES, rows=ar, cols=ar) # known 0 + self.declare_partials(of=Dynamic.Battery.EFFICIENCY, wrt='R_0', rows=ar, cols=ar) + self.declare_partials( + of=Dynamic.Battery.EFFICIENCY, + wrt=Dynamic.Battery.VOLTAGE_THEVENIN, + rows=ar, + cols=ar, + ) + self.declare_partials(of=Dynamic.Battery.EFFICIENCY, wrt='U_oc', rows=ar, cols=ar) def compute(self, inputs, outputs): C_Th = inputs['C_Th'] R_Th = inputs['R_Th'] - U_Th = inputs[Mission.Battery.VOLTAGE_THEVENIN] + U_Th = inputs[Dynamic.Battery.VOLTAGE_THEVENIN] R_0 = inputs['R_0'] Q_max = inputs[Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX] U_oc = inputs['U_oc'] n_p = inputs[Aircraft.Battery.N_PARALLEL] n_s = inputs[Aircraft.Battery.N_SERIES] - I_pack = inputs[Mission.Battery.CURRENT] + I_pack = inputs[Dynamic.Battery.CURRENT] # cell I_Li = I_pack / n_p - outputs[Mission.Battery.STATE_OF_CHARGE_RATE] = -I_Li / \ - (3600.0 * Q_max) # conversion from hours to seconds - outputs[Mission.Battery.VOLTAGE_THEVENIN_RATE] = - \ - U_Th / (R_Th * C_Th) + I_Li / C_Th + outputs[Dynamic.Battery.STATE_OF_CHARGE_RATE] = -I_Li / ( + 3600.0 * Q_max + ) # conversion from hours to seconds + outputs[Dynamic.Battery.VOLTAGE_THEVENIN_RATE] = -U_Th / (R_Th * C_Th) + I_Li / C_Th U_L = U_oc - U_Th - (I_Li * R_0) # thermal - Q_cell = I_Li**2 * (R_0 + U_Th/I_Li) + Q_cell = I_Li**2 * (R_0 + U_Th / I_Li) # pack - outputs[Mission.Battery.VOLTAGE] = U_L * n_s - outputs[Mission.Battery.HEAT_OUT] = Q_cell * n_s * n_p - P_tot = I_pack * outputs[Mission.Battery.VOLTAGE] - outputs[Aircraft.Battery.EFFICIENCY] = 1. - outputs[Mission.Battery.HEAT_OUT] / \ - ((P_tot + outputs[Mission.Battery.HEAT_OUT])) + outputs[Dynamic.Battery.VOLTAGE] = U_L * n_s + outputs[Dynamic.Battery.HEAT_OUT] = Q_cell * n_s * n_p + P_tot = I_pack * outputs[Dynamic.Battery.VOLTAGE] + outputs[Dynamic.Battery.EFFICIENCY] = 1.0 - outputs[Dynamic.Battery.HEAT_OUT] / ( + P_tot + outputs[Dynamic.Battery.HEAT_OUT] + ) def compute_partials(self, inputs, partials): - C_Th = inputs['C_Th'] R_Th = inputs['R_Th'] - U_Th = inputs[Mission.Battery.VOLTAGE_THEVENIN] + U_Th = inputs[Dynamic.Battery.VOLTAGE_THEVENIN] R_0 = inputs['R_0'] Q_max = inputs[Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX] U_oc = inputs['U_oc'] n_p = inputs[Aircraft.Battery.N_PARALLEL] n_s = inputs[Aircraft.Battery.N_SERIES] - I_pack = inputs[Mission.Battery.CURRENT] + I_pack = inputs[Dynamic.Battery.CURRENT] I_Li = I_pack / n_p U_L = U_oc - U_Th - (I_Li * R_0) - Q_cell = I_Li**2 * (R_0 + U_Th/I_Li) + Q_cell = I_Li**2 * (R_0 + U_Th / I_Li) U_pack = U_L * n_s Q_pack = Q_cell * n_s * n_p P_tot = I_pack * U_pack - pack_eta = 1. - Q_pack/((P_tot + Q_pack)) - dI_li__dnp = -I_pack/n_p**2 - dU_L__dnp = -R_0*dI_li__dnp + dI_li__dnp = -I_pack / n_p**2 + dU_L__dnp = -R_0 * dI_li__dnp dU_pack__dnp = dU_L__dnp * n_s - dQ_cell__dnp = 2*I_Li*dI_li__dnp*(R_0+U_Th/I_Li) - U_Th*dI_li__dnp - dQ_pack__dnp = n_s*(dQ_cell__dnp*n_p + Q_cell) + dQ_cell__dnp = 2 * I_Li * dI_li__dnp * (R_0 + U_Th / I_Li) - U_Th * dI_li__dnp + dQ_pack__dnp = n_s * (dQ_cell__dnp * n_p + Q_cell) dPtot__dnp = I_pack * dU_pack__dnp - dpack_eta__dnp = -dQ_pack__dnp / \ - (P_tot+Q_pack) + Q_pack/(P_tot + Q_pack)**2 * (dPtot__dnp+dQ_pack__dnp) + dpack_eta__dnp = -dQ_pack__dnp / (P_tot + Q_pack) + Q_pack / (P_tot + Q_pack) ** 2 * ( + dPtot__dnp + dQ_pack__dnp + ) - dI_li__dI_pack = 1/n_p - dQ_cell__dI_pack = 2*I_Li*dI_li__dI_pack*(R_0+U_Th/I_Li) - U_Th*dI_li__dI_pack + dI_li__dI_pack = 1 / n_p + dQ_cell__dI_pack = 2 * I_Li * dI_li__dI_pack * (R_0 + U_Th / I_Li) - U_Th * dI_li__dI_pack dQ_pack__dI_pack = dQ_cell__dI_pack * n_s * n_p - dU_pack__dI_pack = -R_0*n_s/n_p - dPtot__dI_pack = U_pack + dU_pack__dI_pack*I_pack - dpack_eta__dI_pack = -dQ_pack__dI_pack / \ - (P_tot+Q_pack) + Q_pack/(P_tot + Q_pack)**2 * (dPtot__dI_pack+dQ_pack__dI_pack) + dU_pack__dI_pack = -R_0 * n_s / n_p + dPtot__dI_pack = U_pack + dU_pack__dI_pack * I_pack + dpack_eta__dI_pack = -dQ_pack__dI_pack / (P_tot + Q_pack) + Q_pack / ( + P_tot + Q_pack + ) ** 2 * (dPtot__dI_pack + dQ_pack__dI_pack) - dPtot__dU_th = -I_pack*n_s + dPtot__dU_th = -I_pack * n_s dQ_pack_dU_th = I_pack * n_s - dpack_eta__dU_t = -dQ_pack_dU_th / \ - (P_tot+Q_pack) + Q_pack/(P_tot + Q_pack)**2 * (dPtot__dU_th+dQ_pack_dU_th) + dpack_eta__dU_t = -dQ_pack_dU_th / (P_tot + Q_pack) + Q_pack / (P_tot + Q_pack) ** 2 * ( + dPtot__dU_th + dQ_pack_dU_th + ) dU_pack__dR_0 = -I_pack * n_s / n_p dPtot__dR_0 = I_pack * dU_pack__dR_0 dQ_pack__dR_0 = (I_pack**2 * n_s) / n_p - dpack_eta__dR_0 = -dQ_pack__dR_0 / \ - (P_tot+Q_pack) + Q_pack/(P_tot + Q_pack)**2 * (dPtot__dR_0+dQ_pack__dR_0) - - dPtot__dU_oc = I_pack*n_s - dpack_eta__dU_oc = Q_pack/(P_tot + Q_pack)**2 * dPtot__dU_oc - - partials[Mission.Battery.STATE_OF_CHARGE_RATE, - Mission.Battery.CURRENT] = -1./(3600.0*Q_max*n_p) - partials[Mission.Battery.STATE_OF_CHARGE_RATE, - Aircraft.Battery.N_PARALLEL] = I_pack/(3600.0*Q_max*n_p**2) - partials[Mission.Battery.STATE_OF_CHARGE_RATE, - Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX] = I_pack/(3600.0*n_p*Q_max**2) - - partials[Mission.Battery.VOLTAGE_THEVENIN_RATE, - Mission.Battery.VOLTAGE_THEVENIN] = -1./(R_Th*C_Th) - partials[Mission.Battery.VOLTAGE_THEVENIN_RATE, 'R_Th'] = U_Th/(C_Th * R_Th**2) - partials[Mission.Battery.VOLTAGE_THEVENIN_RATE, 'C_Th'] = ( - n_p*U_Th - I_pack*R_Th) / (C_Th**2 * n_p * R_Th) - partials[Mission.Battery.VOLTAGE_THEVENIN_RATE, - Mission.Battery.CURRENT] = 1./(C_Th*n_p) - partials[Mission.Battery.VOLTAGE_THEVENIN_RATE, - Aircraft.Battery.N_PARALLEL] = -I_pack/(C_Th*n_p**2) - - partials[Mission.Battery.VOLTAGE, 'U_oc'] = n_s - partials[Mission.Battery.VOLTAGE, Mission.Battery.VOLTAGE_THEVENIN] = -n_s - partials[Mission.Battery.VOLTAGE, 'R_0'] = dU_pack__dR_0 - partials[Mission.Battery.VOLTAGE, Aircraft.Battery.N_PARALLEL] = dU_pack__dnp - partials[Mission.Battery.VOLTAGE, Mission.Battery.CURRENT] = dU_pack__dI_pack - partials[Mission.Battery.VOLTAGE, Aircraft.Battery.N_SERIES] = U_oc - \ - U_Th - (I_pack/n_p * R_0) - - partials[Mission.Battery.HEAT_OUT, Mission.Battery.CURRENT] = n_s * \ - ((2 * I_pack * R_0)/n_p + U_Th) - partials[Mission.Battery.HEAT_OUT, Aircraft.Battery.N_PARALLEL] = dQ_pack__dnp - partials[Mission.Battery.HEAT_OUT, 'R_0'] = (I_pack**2 * n_s) / n_p - partials[Mission.Battery.HEAT_OUT, - Mission.Battery.VOLTAGE_THEVENIN] = dQ_pack_dU_th - partials[Mission.Battery.HEAT_OUT, Aircraft.Battery.N_SERIES] = ( - I_pack**2 * ((n_p * U_Th)/I_pack + R_0)) / n_p - - partials[Aircraft.Battery.EFFICIENCY, 'U_oc'] = dpack_eta__dU_oc - partials[Aircraft.Battery.EFFICIENCY, - Aircraft.Battery.N_PARALLEL] = dpack_eta__dnp - partials[Aircraft.Battery.EFFICIENCY, - Mission.Battery.CURRENT] = dpack_eta__dI_pack - partials[Aircraft.Battery.EFFICIENCY, 'R_0'] = dpack_eta__dR_0 - partials[Aircraft.Battery.EFFICIENCY, - Mission.Battery.VOLTAGE_THEVENIN] = dpack_eta__dU_t - # partials[Aircraft.Battery.EFFICIENCY,Aircraft.Battery.N_SERIES] = 0. + dpack_eta__dR_0 = -dQ_pack__dR_0 / (P_tot + Q_pack) + Q_pack / (P_tot + Q_pack) ** 2 * ( + dPtot__dR_0 + dQ_pack__dR_0 + ) + + dPtot__dU_oc = I_pack * n_s + dpack_eta__dU_oc = Q_pack / (P_tot + Q_pack) ** 2 * dPtot__dU_oc + + partials[Dynamic.Battery.STATE_OF_CHARGE_RATE, Dynamic.Battery.CURRENT] = -1.0 / ( + 3600.0 * Q_max * n_p + ) + partials[Dynamic.Battery.STATE_OF_CHARGE_RATE, Aircraft.Battery.N_PARALLEL] = I_pack / ( + 3600.0 * Q_max * n_p**2 + ) + partials[ + Dynamic.Battery.STATE_OF_CHARGE_RATE, + Aircraft.Battery.Cell.ENERGY_CAPACITY_MAX, + ] = I_pack / (3600.0 * n_p * Q_max**2) + + partials[Dynamic.Battery.VOLTAGE_THEVENIN_RATE, Dynamic.Battery.VOLTAGE_THEVENIN] = -1.0 / ( + R_Th * C_Th + ) + partials[Dynamic.Battery.VOLTAGE_THEVENIN_RATE, 'R_Th'] = U_Th / (C_Th * R_Th**2) + partials[Dynamic.Battery.VOLTAGE_THEVENIN_RATE, 'C_Th'] = (n_p * U_Th - I_pack * R_Th) / ( + C_Th**2 * n_p * R_Th + ) + partials[Dynamic.Battery.VOLTAGE_THEVENIN_RATE, Dynamic.Battery.CURRENT] = 1.0 / ( + C_Th * n_p + ) + partials[Dynamic.Battery.VOLTAGE_THEVENIN_RATE, Aircraft.Battery.N_PARALLEL] = -I_pack / ( + C_Th * n_p**2 + ) + + partials[Dynamic.Battery.VOLTAGE, 'U_oc'] = n_s + partials[Dynamic.Battery.VOLTAGE, Dynamic.Battery.VOLTAGE_THEVENIN] = -n_s + partials[Dynamic.Battery.VOLTAGE, 'R_0'] = dU_pack__dR_0 + partials[Dynamic.Battery.VOLTAGE, Aircraft.Battery.N_PARALLEL] = dU_pack__dnp + partials[Dynamic.Battery.VOLTAGE, Dynamic.Battery.CURRENT] = dU_pack__dI_pack + partials[Dynamic.Battery.VOLTAGE, Aircraft.Battery.N_SERIES] = ( + U_oc - U_Th - (I_pack / n_p * R_0) + ) + + partials[Dynamic.Battery.HEAT_OUT, Dynamic.Battery.CURRENT] = n_s * ( + (2 * I_pack * R_0) / n_p + U_Th + ) + partials[Dynamic.Battery.HEAT_OUT, Aircraft.Battery.N_PARALLEL] = dQ_pack__dnp + partials[Dynamic.Battery.HEAT_OUT, 'R_0'] = (I_pack**2 * n_s) / n_p + partials[Dynamic.Battery.HEAT_OUT, Dynamic.Battery.VOLTAGE_THEVENIN] = dQ_pack_dU_th + partials[Dynamic.Battery.HEAT_OUT, Aircraft.Battery.N_SERIES] = ( + I_pack**2 * ((n_p * U_Th) / I_pack + R_0) + ) / n_p + + partials[Dynamic.Battery.EFFICIENCY, 'U_oc'] = dpack_eta__dU_oc + partials[Dynamic.Battery.EFFICIENCY, Aircraft.Battery.N_PARALLEL] = dpack_eta__dnp + partials[Dynamic.Battery.EFFICIENCY, Dynamic.Battery.CURRENT] = dpack_eta__dI_pack + partials[Dynamic.Battery.EFFICIENCY, 'R_0'] = dpack_eta__dR_0 + partials[Dynamic.Battery.EFFICIENCY, Dynamic.Battery.VOLTAGE_THEVENIN] = dpack_eta__dU_t + # partials[Dynamic.Battery.EFFICIENCY,Aircraft.Battery.N_SERIES] = 0. diff --git a/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py b/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py index 090c59f4b0..f3bb17ebe2 100644 --- a/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py +++ b/aviary/examples/external_subsystems/battery/model/reg_thevenin_interp_group.py @@ -1,12 +1,10 @@ import numpy as np - from openmdao.api import Group, MetaModelStructuredComp - # These battery values are entirely fabricated and not representative of any real battery. # This model is used as an example of how to integrate external subsystems in Aviary. -T_bp = np.array([0., 60.]) -SOC_bp = np.linspace(0., 1., 32) +T_bp = np.array([0.0, 60.0]) +SOC_bp = np.linspace(0.0, 1.0, 32) tU_oc = np.vstack((np.linspace(2.8, 4.2, 32), np.linspace(2.7, 4.1, 32))) tC_Th = np.ones((2, 32)) * 1000.0 @@ -26,8 +24,9 @@ def initialize(self): def setup(self): n = self.options['num_nodes'] - thevenin_interp_comp = MetaModelStructuredComp(method='slinear', vec_size=n, - training_data_gradients=False, extrapolate=True) + thevenin_interp_comp = MetaModelStructuredComp( + method='slinear', vec_size=n, training_data_gradients=False, extrapolate=True + ) thevenin_interp_comp.add_input('T_batt', 1.0, T_bp, units='degC') thevenin_interp_comp.add_input('SOC', 1.0, SOC_bp, units=None) @@ -37,6 +36,6 @@ def setup(self): thevenin_interp_comp.add_output('R_0', 1.0, tR_0, units='ohm') thevenin_interp_comp.add_output('U_oc', 1.0, tU_oc, units='V') - self.add_subsystem(name='interp_comp', - subsys=thevenin_interp_comp, - promotes=["*"]) # promots params and values + self.add_subsystem( + name='interp_comp', subsys=thevenin_interp_comp, promotes=['*'] + ) # promots params and values diff --git a/aviary/examples/external_subsystems/battery/model/test_cell_comp.py b/aviary/examples/external_subsystems/battery/model/test_cell_comp.py index a2b259478d..a82667052d 100644 --- a/aviary/examples/external_subsystems/battery/model/test_cell_comp.py +++ b/aviary/examples/external_subsystems/battery/model/test_cell_comp.py @@ -1,13 +1,13 @@ -from aviary.examples.external_subsystems.battery.model.cell_comp import CellComp -from openmdao.api import Problem, Group -from openmdao.utils.testing_utils import use_tempdirs import unittest +from openmdao.api import Group, Problem +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.examples.external_subsystems.battery.model.cell_comp import CellComp + class Test_cell_comp(unittest.TestCase): - """ - test partials in CellComp component - """ + """test partials in CellComp component.""" @use_tempdirs def test_cell_comp(self): @@ -19,5 +19,5 @@ def test_cell_comp(self): p.check_partials(compact_print=True, method='cs', step=1e-50) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/examples/external_subsystems/battery/run_cruise.py b/aviary/examples/external_subsystems/battery/run_cruise.py deleted file mode 100644 index 253f64dd12..0000000000 --- a/aviary/examples/external_subsystems/battery/run_cruise.py +++ /dev/null @@ -1,48 +0,0 @@ -from copy import deepcopy -import aviary.api as av - -from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder -from aviary.examples.external_subsystems.battery.battery_variables import Aircraft, Mission -from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData - - -battery_builder = BatteryBuilder() - -phase_info = deepcopy(av.default_height_energy_phase_info) -# Here we just add the simple weight system to only the pre-mission -phase_info['pre_mission']['external_subsystems'] = [battery_builder] -phase_info['climb']['external_subsystems'] = [battery_builder] - - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', - phase_info, meta_data=ExtendedMetaData) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP") - - prob.add_design_variables() - - prob.model.add_objective( - f'traj.climb.states:{Mission.Battery.STATE_OF_CHARGE}', index=-1, ref=-1) - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(suppress_solver_print=True) diff --git a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py b/aviary/examples/external_subsystems/battery/run_external_battery_mission_example.py similarity index 76% rename from aviary/examples/external_subsystems/battery/run_multiphase_mission.py rename to aviary/examples/external_subsystems/battery/run_external_battery_mission_example.py index 5b46452512..abaeaeace2 100644 --- a/aviary/examples/external_subsystems/battery/run_multiphase_mission.py +++ b/aviary/examples/external_subsystems/battery/run_external_battery_mission_example.py @@ -1,13 +1,14 @@ -from aviary.interface.methods_for_level2 import AviaryProblem +"""Example mission using the a detailed battery model.""" +from aviary.api import default_height_energy_phase_info as phase_info from aviary.examples.external_subsystems.battery.battery_builder import BatteryBuilder from aviary.examples.external_subsystems.battery.battery_variable_meta_data import ExtendedMetaData -from aviary.api import default_height_energy_phase_info as phase_info +from aviary.interface.methods_for_level2 import AviaryProblem from aviary.utils.functions import get_aviary_resource_path - battery_builder = BatteryBuilder(include_constraints=False) +# add the battery model to each mission phase, as well as pre-mission for sizing phase_info['pre_mission']['external_subsystems'] = [battery_builder] phase_info['climb']['external_subsystems'] = [battery_builder] phase_info['cruise']['external_subsystems'] = [battery_builder] @@ -19,31 +20,22 @@ # Load aircraft and options data from user # Allow for user overrides here input_file = get_aviary_resource_path( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv') + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv' + ) prob.load_inputs(input_file, phase_info, meta_data=ExtendedMetaData) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() + prob.build_model() - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP") + prob.add_driver('SLSQP') prob.add_design_variables() prob.add_objective('mass') # prob.model.add_objective( - # f'traj.climb.states:{Mission.Battery.STATE_OF_CHARGE}', index=-1, ref=-1) + # f'traj.climb.states:{Dynamic.Battery.STATE_OF_CHARGE}', index=-1, ref=-1) prob.setup() - prob.set_initial_guesses() - prob.run_aviary_problem() diff --git a/aviary/examples/external_subsystems/battery/test_battery_builder.py b/aviary/examples/external_subsystems/battery/test/test_battery_builder.py similarity index 80% rename from aviary/examples/external_subsystems/battery/test_battery_builder.py rename to aviary/examples/external_subsystems/battery/test/test_battery_builder.py index 885b6192ea..9254bb2713 100644 --- a/aviary/examples/external_subsystems/battery/test_battery_builder.py +++ b/aviary/examples/external_subsystems/battery/test/test_battery_builder.py @@ -1,16 +1,15 @@ import unittest -import aviary.api as av +import aviary.api as av BatteryBuilder = av.TestSubsystemBuilderBase.import_builder( - 'battery.battery_builder.BatteryBuilder') + 'battery.battery_builder.BatteryBuilder' +) @av.skipIfMissingDependencies(BatteryBuilder) class TestBattery(av.TestSubsystemBuilderBase): - """ - Test battery builder - """ + """Test battery builder.""" def setUp(self): self.subsystem_builder = BatteryBuilder() diff --git a/aviary/interface/default_phase_info/__init__.py b/aviary/examples/external_subsystems/custom_aero/__init__.py similarity index 100% rename from aviary/interface/default_phase_info/__init__.py rename to aviary/examples/external_subsystems/custom_aero/__init__.py diff --git a/aviary/examples/external_subsystems/custom_aero/custom_aero_builder.py b/aviary/examples/external_subsystems/custom_aero/custom_aero_builder.py new file mode 100644 index 0000000000..3c2783552d --- /dev/null +++ b/aviary/examples/external_subsystems/custom_aero/custom_aero_builder.py @@ -0,0 +1,102 @@ +"""Builder for a simple drag calculation that replaces Aviary's calculation.""" + +from aviary.examples.external_subsystems.custom_aero.simple_drag import SimpleAeroGroup +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase +from aviary.variable_info.variables import Aircraft, Dynamic + + +class CustomAeroBuilder(SubsystemBuilderBase): + """ + Prototype of a subsystem that overrides an aviary internally computed var. + + It also provides a method to build OpenMDAO systems for the pre-mission and mission computations of the subsystem. + + Attributes + ---------- + name : str ('simple_aero') + object label + """ + + def __init__(self, name='simple_aero'): + super().__init__(name) + + def build_mission(self, num_nodes, aviary_inputs, **kwargs): + """ + Build an OpenMDAO system for the mission computations of the subsystem. + + Returns + ------- + mission_sys : openmdao.core.System + An OpenMDAO system containing all computations that need to happen + during the mission. This includes time-dependent states that are + being integrated as well as any other variables that vary during + the mission. + """ + aero_group = SimpleAeroGroup( + num_nodes=num_nodes, + ) + return aero_group + + def mission_inputs(self, **kwargs): + promotes = [ + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.MASS, + 'aircraft:*', + ] + return promotes + + def mission_outputs(self, **kwargs): + promotes = [ + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.LIFT, + ] + return promotes + + def get_parameters(self, aviary_inputs=None, phase_info=None): + """ + Return a dictionary of fixed values for the subsystem. + + Optional, used if subsystems have fixed values. + + Used in the phase builders (e.g. cruise_phase.py) when other parameters are added to the phase. + + This is distinct from `get_design_vars` in a nuanced way. Design variables + are variables that are optimized by the problem that are not at the phase level. + An example would be something that occurs in the pre-mission level of the problem. + Parameters are fixed values that are held constant throughout a phase, but if + `opt=True`, they are able to change during the optimization. + + Parameters + ---------- + phase_info : dict + The phase_info subdict for this phase. + + Returns + ------- + fixed_values : dict + A dictionary where the keys are the names of the fixed variables + and the values are dictionaries with the following keys: + + - 'value': float or array + The fixed value for the variable. + - 'units': str + The units for the fixed value (optional). + - any additional keyword arguments required by OpenMDAO for the fixed + variable. + """ + params = {} + params[Aircraft.Wing.AREA] = { + 'shape': (1,), + 'static_target': True, + 'units': 'ft**2', + } + return params + + def needs_mission_solver(self, aviary_inputs): + """ + Return True if the mission subsystem needs to be in the solver loop in mission, otherwise + return False. Aviary will only place it in the solver loop when True. The default is + True. + """ + return False diff --git a/aviary/examples/external_subsystems/custom_aero/run_custom_aero_example.py b/aviary/examples/external_subsystems/custom_aero/run_custom_aero_example.py new file mode 100644 index 0000000000..d96ff46ad3 --- /dev/null +++ b/aviary/examples/external_subsystems/custom_aero/run_custom_aero_example.py @@ -0,0 +1,53 @@ +"""Run the a mission with a simple external component that computes aircraft lift and drag.""" + +from copy import deepcopy + +import aviary.api as av +from aviary.examples.external_subsystems.custom_aero.custom_aero_builder import CustomAeroBuilder + +phase_info = deepcopy(av.default_height_energy_phase_info) + +# Just do cruise in this example. +phase_info.pop('climb') +phase_info.pop('descent') + +# Add custom aero. +# TODO: This API for replacing aero will be changed an upcoming release. +phase_info['cruise']['external_subsystems'] = [CustomAeroBuilder()] + +# Disable internal aero +# TODO: This API for replacing aero will be changed an upcoming release. +phase_info['cruise']['subsystem_options']['core_aerodynamics'] = { + 'method': 'external', +} + +# Start cruise at t=0. +del phase_info['cruise']['user_options']['time_initial_bounds'] +phase_info['cruise']['user_options']['time_initial'] = (0.0, 'min') + + +if __name__ == '__main__': + prob = av.AviaryProblem() + + # Load aircraft and options data from user + # Allow for user overrides here + prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', phase_info + ) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + # Note, SLSQP has trouble here. + prob.add_driver('IPOPT') + + prob.add_design_variables() + + prob.add_objective() + + prob.setup() + + prob.run_aviary_problem(suppress_solver_print=True) + + print('done') diff --git a/aviary/examples/external_subsystems/custom_aero/simple_drag.py b/aviary/examples/external_subsystems/custom_aero/simple_drag.py new file mode 100644 index 0000000000..5d59739034 --- /dev/null +++ b/aviary/examples/external_subsystems/custom_aero/simple_drag.py @@ -0,0 +1,100 @@ +import numpy as np +import openmdao.api as om + +from aviary.subsystems.aerodynamics.aero_common import DynamicPressure +from aviary.subsystems.aerodynamics.flops_based.drag import SimpleDrag +from aviary.subsystems.aerodynamics.flops_based.lift import LiftEqualsWeight +from aviary.variable_info.variables import Aircraft, Dynamic + + +class SimplestDragCoeff(om.ExplicitComponent): + """ + Simple representation of aircraft drag as CD = CD_zero + k * CL**2. + + Values are fictional. Typically, some higher fidelity method will go here instead. + """ + + def initialize(self): + self.options.declare( + 'num_nodes', default=1, types=int, desc='Number of nodes along mission segment' + ) + + self.options.declare('CD_zero', default=0.01) + self.options.declare('k', default=0.04) + + def setup(self): + nn = self.options['num_nodes'] + + self.add_input('cl', val=np.zeros(nn), units='unitless') + + self.add_output('CD', val=np.zeros(nn), units='unitless') + + def setup_partials(self): + nn = self.options['num_nodes'] + arange = np.arange(nn) + + self.declare_partials('CD', 'cl', rows=arange, cols=arange) + + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + CD_zero = self.options['CD_zero'] + k = self.options['k'] + + cl = inputs['cl'] + + outputs['CD'] = CD_zero + k * cl**2 + + def compute_partials(self, inputs, partials, discrete_inputs=None): + k = self.options['k'] + + cl = inputs['cl'] + + partials['CD', 'cl'] = 2.0 * k * cl + + +class SimpleAeroGroup(om.Group): + def initialize(self): + self.options.declare( + 'num_nodes', default=1, types=int, desc='Number of nodes along mission segment' + ) + + def setup(self): + nn = self.options['num_nodes'] + + self.add_subsystem( + 'DynamicPressure', + DynamicPressure(num_nodes=nn), + promotes_inputs=[ + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.STATIC_PRESSURE, + ], + promotes_outputs=[Dynamic.Atmosphere.DYNAMIC_PRESSURE], + ) + + self.add_subsystem( + 'Lift', + LiftEqualsWeight(num_nodes=nn), + promotes_inputs=[ + Aircraft.Wing.AREA, + Dynamic.Vehicle.MASS, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + ], + promotes_outputs=['cl', Dynamic.Vehicle.LIFT], + ) + + self.add_subsystem( + 'SimpleDragCoeff', + SimplestDragCoeff(num_nodes=nn), + promotes_inputs=['cl'], + promotes_outputs=['CD'], + ) + + self.add_subsystem( + 'SimpleDrag', + SimpleDrag(num_nodes=nn), + promotes_inputs=[ + 'CD', + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + Aircraft.Wing.AREA, + ], + promotes_outputs=[Dynamic.Vehicle.DRAG], + ) diff --git a/aviary/examples/external_subsystems/simple_weight/simple_weight.py b/aviary/examples/external_subsystems/custom_mass/custom_mass.py similarity index 91% rename from aviary/examples/external_subsystems/simple_weight/simple_weight.py rename to aviary/examples/external_subsystems/custom_mass/custom_mass.py index 50875de750..3737a1b675 100644 --- a/aviary/examples/external_subsystems/simple_weight/simple_weight.py +++ b/aviary/examples/external_subsystems/custom_mass/custom_mass.py @@ -1,21 +1,22 @@ """ This is a simplified example of a component that computes a weight for the -wing and horiztonal tail. The calculation is nonsensical, but it shows how +wing and horizontal tail. The calculation is nonsensical, but it shows how a basic external subsystem an use hierarchy inputs and set new values for parts of the weight calculation. The wing and tail weights will replace Aviary's internally-computed values. -This examples shows that you can use the Aviary hierarchy in your component +This examples shows that you can use the Aviary hierarchy in your component (as we do for the wing and engine weight), but you can also use your own local names (as we do for 'Tail'), and promote them in your builder. """ + import openmdao.api as om from aviary.variable_info.variables import Aircraft -class SimpleWeight(om.ExplicitComponent): +class CustomMass(om.ExplicitComponent): """ A simple component that computes a wing mass as a function of the engine mass. These values are not representative of any existing aircraft, and the component @@ -23,7 +24,6 @@ class SimpleWeight(om.ExplicitComponent): """ def setup(self): - self.add_input(Aircraft.Engine.MASS, 1.0, units='lbm') self.add_output(Aircraft.Wing.MASS, 1.0, units='lbm') diff --git a/aviary/examples/external_subsystems/simple_weight/simple_weight_builder.py b/aviary/examples/external_subsystems/custom_mass/custom_mass_builder.py similarity index 64% rename from aviary/examples/external_subsystems/simple_weight/simple_weight_builder.py rename to aviary/examples/external_subsystems/custom_mass/custom_mass_builder.py index e4e3af23c5..35467358c5 100644 --- a/aviary/examples/external_subsystems/simple_weight/simple_weight_builder.py +++ b/aviary/examples/external_subsystems/custom_mass/custom_mass_builder.py @@ -2,17 +2,18 @@ Builder for a simple component that computes a new wing and horizontal tail mass. -The SimpleWeight component is placed inside of a group so that we can promote +The CustomMass component is placed inside of a group so that we can promote the variable "Tail" using the alias Aircraft.HorizontalTail.MASS """ + import openmdao.api as om -from aviary.examples.external_subsystems.simple_weight.simple_weight import SimpleWeight +from aviary.examples.external_subsystems.custom_mass.custom_mass import CustomMass from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.variable_info.variables import Aircraft -class WingWeightBuilder(SubsystemBuilderBase): +class WingMassBuilder(SubsystemBuilderBase): """ Prototype of a subsystem that overrides an aviary internally computed var. @@ -20,22 +21,22 @@ class WingWeightBuilder(SubsystemBuilderBase): Attributes ---------- - name : str ('wing_weight') + name : str ('wing_mass') object label Methods ------- - __init__(self, name='wing_weight'): - Initializes the WingWeightBuilder object with a given name. + __init__(self, name='wing_mass'): + Initializes the WingMassBuilder object with a given name. build_pre_mission(self, aviary_inputs) -> openmdao.core.System: Builds an OpenMDAO system for the pre-mission computations of the subsystem. """ - def __init__(self, name='wing_weight'): + def __init__(self, name='wing_mass'): super().__init__(name) def build_pre_mission(self, aviary_inputs): - ''' + """ Build an OpenMDAO system for the pre-mission computations of the subsystem. Returns @@ -44,10 +45,12 @@ def build_pre_mission(self, aviary_inputs): An OpenMDAO system containing all computations that need to happen in the pre-mission part of the Aviary problem. This includes sizing, design, and other non-mission parameters. - ''' + """ wing_group = om.Group() - wing_group.add_subsystem("aerostructures", SimpleWeight(), - promotes_inputs=["aircraft:*"], - promotes_outputs=[Aircraft.Wing.MASS, - ('Tail', Aircraft.HorizontalTail.MASS)]) + wing_group.add_subsystem( + 'aerostructures', + CustomMass(), + promotes_inputs=['aircraft:*'], + promotes_outputs=[Aircraft.Wing.MASS, ('Tail', Aircraft.HorizontalTail.MASS)], + ) return wing_group diff --git a/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py b/aviary/examples/external_subsystems/custom_mass/run_custom_mass_example.py similarity index 53% rename from aviary/examples/external_subsystems/simple_weight/run_simple_weight.py rename to aviary/examples/external_subsystems/custom_mass/run_custom_mass_example.py index e09e40dd28..69d5776dab 100644 --- a/aviary/examples/external_subsystems/simple_weight/run_simple_weight.py +++ b/aviary/examples/external_subsystems/custom_mass/run_custom_mass_example.py @@ -1,37 +1,28 @@ -""" -Run the a mission with a simple external component that computes the wing -and horizontal tail mass. -""" -from copy import deepcopy -import aviary.api as av +"""Run the a mission with a simple external component that computes the wing and horizontal tail mass.""" -from aviary.examples.external_subsystems.simple_weight.simple_weight_builder import WingWeightBuilder +from copy import deepcopy +import aviary.api as av +from aviary.examples.external_subsystems.custom_mass.custom_mass_builder import WingMassBuilder phase_info = deepcopy(av.default_height_energy_phase_info) # Here we just add the simple weight system to only the pre-mission -phase_info['pre_mission']['external_subsystems'] = [WingWeightBuilder()] +phase_info['pre_mission']['external_subsystems'] = [WingMassBuilder()] if __name__ == '__main__': prob = av.AviaryProblem() # Load aircraft and options data from user # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) + prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', phase_info + ) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - - prob.add_phases() + prob.build_model() - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP") + prob.add_driver('SLSQP') prob.add_design_variables() @@ -39,12 +30,8 @@ prob.setup() - prob.set_initial_guesses() - prob.run_aviary_problem(suppress_solver_print=True) print('Engine Mass', prob.get_val(av.Aircraft.Engine.MASS)) print('Wing Mass', prob.get_val(av.Aircraft.Wing.MASS)) print('Horizontal Tail Mass', prob.get_val(av.Aircraft.HorizontalTail.MASS)) - - print('done') diff --git a/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/DesignEngineGroup.py b/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/DesignEngineGroup.py index 1ab83fed8a..cd3c2eec77 100644 --- a/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/DesignEngineGroup.py +++ b/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/DesignEngineGroup.py @@ -1,21 +1,23 @@ -import numpy as np -import openmdao.api as om import subprocess as subprocess +import numpy as np +import openmdao.api as om from openmdao.utils.file_wrap import FileParser -from aviary.examples.external_subsystems.engine_NPSS.engine_variables import Aircraft +from aviary.examples.external_subsystems.engine_NPSS.NPSS_variables import Aircraft from aviary.utils.functions import get_path class NPSSExternalCodeComp(om.ExternalCodeComp): - """ - Component that wraps NPSS engine model - """ + """Component that wraps NPSS engine model.""" def initialize(self): - self.options.declare('vec_size', default=72, types=int, - desc='number of points in NPSS model deck. Will need to be updated if size of deck changes') + self.options.declare( + 'vec_size', + default=72, + types=int, + desc='number of points in NPSS model deck. Will need to be updated if size of deck changes', + ) def setup(self): vec_size = self.options['vec_size'] @@ -23,30 +25,39 @@ def setup(self): self.add_input('MN_DES', val=0.0, units=None, desc='design Mach number') self.add_input('W_DES', val=240.0, units='lbm/s', desc='design mass flow') - self.add_output('Fn_SLS', val=1.0, units='lbf', - desc='net thrust at sea-level-static conditions') - self.add_output('Wf_training_data', val=np.ones(vec_size), - units='lbm/s', desc='fuel flow training data') - self.add_output('thrust_training_data', val=np.ones( - vec_size), units='lbf', desc='thrust training data') - self.add_output('thrustmax_training_data', val=np.ones(vec_size), - units='lbf', desc='maximum thrust training data') + self.add_output( + 'Fn_SLS', val=1.0, units='lbf', desc='net thrust at sea-level-static conditions' + ) + self.add_output( + 'Wf_training_data', val=np.ones(vec_size), units='lbm/s', desc='fuel flow training data' + ) + self.add_output( + 'thrust_training_data', val=np.ones(vec_size), units='lbf', desc='thrust training data' + ) + self.add_output( + 'thrustmax_training_data', + val=np.ones(vec_size), + units='lbf', + desc='maximum thrust training data', + ) self.input_file = get_path( - './examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/input.int') + './examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/input.int' + ) self.output_file = get_path( - './examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/output.int') + './examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/output.int' + ) self.options['external_input_files'] = [self.input_file] self.options['external_output_files'] = [self.output_file] run_location = get_path( - './examples/external_subsystems/engine_NPSS/NPSS_Model/turbojet.run') - engine_location = get_path( - './examples/external_subsystems/engine_NPSS/NPSS_Model/') + './examples/external_subsystems/engine_NPSS/NPSS_Model/turbojet.run' + ) + engine_location = get_path('./examples/external_subsystems/engine_NPSS/NPSS_Model/') engine_location = str(engine_location) - run_command = ['runnpss', run_location, '-D ENG_PATH='+engine_location] + run_command = ['runnpss', run_location, '-D ENG_PATH=' + engine_location] self.options['command'] = run_command def setup_partials(self): @@ -62,8 +73,9 @@ def compute(self, inputs, outputs): # generate the input file for the external code with open(self.input_file, 'w') as input_file: - input_file.write('Alt_DES = %.16f ;\nMN_DES = %.16f ;\nW_DES = %.16f ;' - % (Alt_DES, MN_DES, W_DES)) + input_file.write( + 'Alt_DES = %.16f ;\nMN_DES = %.16f ;\nW_DES = %.16f ;' % (Alt_DES, MN_DES, W_DES) + ) # the parent compute function actually runs the external code super().compute(inputs, outputs) @@ -72,59 +84,73 @@ def compute(self, inputs, outputs): parser = FileParser() parser.set_file(self.output_file) - parser.mark_anchor("Fn_SLS") + parser.mark_anchor('Fn_SLS') Fn_SLS = float(parser.transfer_var(0, 3)) outputs['Fn_SLS'] = Fn_SLS - parser.mark_anchor("Wf_training_data") + parser.mark_anchor('Wf_training_data') parser.set_delimiters(', ') - Wf_training_data_raw = parser.transfer_array(0, 4, 0, vec_size*3) - Wf_training_data_snip = [ - a for a in Wf_training_data_raw if a.replace('.', '').isnumeric()] + Wf_training_data_raw = parser.transfer_array(0, 4, 0, vec_size * 3) + Wf_training_data_snip = [a for a in Wf_training_data_raw if a.replace('.', '').isnumeric()] Wf_training_data = np.array(Wf_training_data_snip, float) outputs['Wf_training_data'] = Wf_training_data - parser.mark_anchor("thrust_training_data") + parser.mark_anchor('thrust_training_data') parser.set_delimiters(', ') - thrust_training_data_raw = parser.transfer_array(0, 4, 0, vec_size*3) + thrust_training_data_raw = parser.transfer_array(0, 4, 0, vec_size * 3) thrust_training_data_snip = [ - a for a in thrust_training_data_raw if a.replace('.', '').isnumeric()] + a for a in thrust_training_data_raw if a.replace('.', '').isnumeric() + ] thrust_training_data = np.array(thrust_training_data_snip, float) outputs['thrust_training_data'] = thrust_training_data - parser.mark_anchor("thrustmax_training_data") + parser.mark_anchor('thrustmax_training_data') parser.set_delimiters(', ') - thrustmax_training_data_raw = parser.transfer_array(0, 4, 0, vec_size*3) + thrustmax_training_data_raw = parser.transfer_array(0, 4, 0, vec_size * 3) thrustmax_training_data_snip = [ - a for a in thrustmax_training_data_raw if a.replace('.', '').isnumeric()] + a for a in thrustmax_training_data_raw if a.replace('.', '').isnumeric() + ] thrustmax_training_data = np.array(thrustmax_training_data_snip, float) outputs['thrustmax_training_data'] = thrustmax_training_data # print(thrustmax_training_data) class DesignEngineGroup(om.Group): - """ - Group that contains NPSSExternalCodeComp and component to calculate negative fuel flow rate - """ + """Group that contains NPSSExternalCodeComp and component to calculate negative fuel flow rate.""" def initialize(self): - self.options.declare('vec_size', default=72, types=int, - desc='number of points in NPSS model deck. Will need to be updated if size of deck changes') + self.options.declare( + 'vec_size', + default=72, + types=int, + desc='number of points in NPSS model deck. Will need to be updated if size of deck changes', + ) def setup(self): vec_size = self.options['vec_size'] - self.add_subsystem('DESIGN', NPSSExternalCodeComp(vec_size=vec_size), - promotes_inputs=[('W_DES', Aircraft.Engine.DESIGN_MASS_FLOW)], - promotes_outputs=[('Fn_SLS', Aircraft.Engine.SCALED_SLS_THRUST), ('thrust_training_data', 'Fn_train'), - ('thrustmax_training_data', 'Fn_max_train'), ('Wf_training_data', 'Wf_td')]) - - self.add_subsystem('negative_fuel_rate', - om.ExecComp('y=-x', - x={'val': np.ones(vec_size), 'units': 'lbm/s'}, - y={'val': np.ones(vec_size), 'units': 'lbm/s'}, - has_diag_partials=True,), - promotes_inputs=[('x', 'Wf_td')], - promotes_outputs=[('y', 'Wf_inv_train')]) + self.add_subsystem( + 'DESIGN', + NPSSExternalCodeComp(vec_size=vec_size), + promotes_inputs=[('W_DES', Aircraft.Engine.DESIGN_MASS_FLOW)], + promotes_outputs=[ + ('Fn_SLS', Aircraft.Engine.SCALED_SLS_THRUST), + ('thrust_training_data', 'Fn_train'), + ('thrustmax_training_data', 'Fn_max_train'), + ('Wf_training_data', 'Wf_td'), + ], + ) + + self.add_subsystem( + 'negative_fuel_rate', + om.ExecComp( + 'y=-x', + x={'val': np.ones(vec_size), 'units': 'lbm/s'}, + y={'val': np.ones(vec_size), 'units': 'lbm/s'}, + has_diag_partials=True, + ), + promotes_inputs=[('x', 'Wf_td')], + promotes_outputs=[('y', 'Wf_inv_train')], + ) def configure(self): self.set_input_defaults(Aircraft.Engine.DESIGN_MASS_FLOW, 240.0, units='lbm/s') diff --git a/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/input.int b/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/input.int index 4240d9dcfe..25fdd53c13 100755 --- a/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/input.int +++ b/aviary/examples/external_subsystems/engine_NPSS/NPSS_Model/Design_files/input.int @@ -1,3 +1,3 @@ Alt_DES = 0.0000000000000000 ; MN_DES = 0.0000000000000000 ; -W_DES = 315.1649027273072079 ; \ No newline at end of file +W_DES = 240.0000000000000000 ; \ No newline at end of file diff --git a/aviary/examples/external_subsystems/engine_NPSS/table_engine_builder.py b/aviary/examples/external_subsystems/engine_NPSS/NPSS_engine_builder.py similarity index 54% rename from aviary/examples/external_subsystems/engine_NPSS/table_engine_builder.py rename to aviary/examples/external_subsystems/engine_NPSS/NPSS_engine_builder.py index bd2f9e53a7..7ca7373e25 100644 --- a/aviary/examples/external_subsystems/engine_NPSS/table_engine_builder.py +++ b/aviary/examples/external_subsystems/engine_NPSS/NPSS_engine_builder.py @@ -1,19 +1,22 @@ import os + import numpy as np import openmdao.api as om -from aviary.examples.external_subsystems.engine_NPSS.engine_variable_meta_data import ExtendedMetaData -from aviary.examples.external_subsystems.engine_NPSS.engine_variables import Aircraft, Dynamic -from aviary.examples.external_subsystems.engine_NPSS.NPSS_Model.DesignEngineGroup import DesignEngineGroup -from aviary.examples.external_subsystems.engine_NPSS.table_engine_connected_variables import vars_to_connect +from aviary.examples.external_subsystems.engine_NPSS.connected_variables import vars_to_connect +from aviary.examples.external_subsystems.engine_NPSS.NPSS_Model.DesignEngineGroup import ( + DesignEngineGroup, +) +from aviary.examples.external_subsystems.engine_NPSS.NPSS_variable_meta_data import ExtendedMetaData +from aviary.examples.external_subsystems.engine_NPSS.NPSS_variables import Aircraft, Dynamic from aviary.subsystems.propulsion.engine_model import EngineModel from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import get_aviary_resource_path -class TableEngineBuilder(EngineModel): +class NPSSTabularEngineBuilder(EngineModel): """ - NPSS engine builder from table + NPSS engine builder from table. Attributes ---------- @@ -25,12 +28,12 @@ class TableEngineBuilder(EngineModel): Methods ------- __init__(self, name='NPSS_prop_system', aviary_inputs=AviaryValues()): - Initializes the TableEngineBuilder object with a given name. + Initializes the NPSSTabularEngineBuilder object with a given name. build_pre_mission(self, aviary_inputs=AviaryValues()) -> openmdao.core.System: Builds an OpenMDAO system for the pre-mission computations of the subsystem. build_mission(self, num_nodes, aviary_inputs) -> openmdao.core.System: Builds an OpenMDAO system for the mission computations of the subsystem. - get_bus_variables(self) -> dict: + get_pre_mission_bus_variables(self) -> dict: Transfer training data from pre-mission to mission. get_controls(self, phase_name) -> dict: Builds dictionary of controls for engine off-design. @@ -39,11 +42,10 @@ class TableEngineBuilder(EngineModel): """ def __init__(self, name='NPSS_prop_system', aviary_inputs=AviaryValues()): - super().__init__(name, options=aviary_inputs, meta_data=ExtendedMetaData) def build_pre_mission(self, aviary_inputs=AviaryValues()): - ''' + """ Builds the design (pre-mission) engine model. Parameters @@ -55,12 +57,11 @@ def build_pre_mission(self, aviary_inputs=AviaryValues()): ------- prob : openmdao.core.Group engine model for design. - ''' - + """ return DesignEngineGroup() def build_mission(self, num_nodes, aviary_inputs): - ''' + """ Builds the off-design (mission) engine model. Parameters @@ -74,21 +75,32 @@ def build_mission(self, num_nodes, aviary_inputs): ------- prob : openmdao.core.Group engine model for off-design. - ''' + """ interp_method = aviary_inputs.get_val(Aircraft.Engine.INTERPOLATION_METHOD)[0] # interpolator object for engine data engine = om.MetaModelSemiStructuredComp( - method=interp_method, extrapolate=True, vec_size=num_nodes, training_data_gradients=True) - - ref = os.path.join("examples", "external_subsystems", "engine_NPSS", - "NPSS_Model", "Output", "RefEngine.outputAviary") + method=interp_method, + extrapolate=True, + vec_size=num_nodes, + training_data_gradients=True, + ) + + ref = os.path.join( + 'examples', + 'external_subsystems', + 'engine_NPSS', + 'NPSS_Model', + 'Output', + 'RefEngine.outputAviary', + ) csv_path = get_aviary_resource_path(ref) engine_data = np.genfromtxt(csv_path, skip_header=0) # Sort the data by Mach, then altitude, then throttle - engine_data = engine_data[np.lexsort( - (engine_data[:, 2], engine_data[:, 1], engine_data[:, 0]))] + engine_data = engine_data[ + np.lexsort((engine_data[:, 2], engine_data[:, 1], engine_data[:, 0])) + ] zeros_array = np.zeros((engine_data.shape[0], 1)) # create a new array for thrust_max. here we take the values where throttle=1.0 @@ -97,57 +109,78 @@ def build_mission(self, num_nodes, aviary_inputs): # for a given mach, altitude, and hybrid throttle setting, the thrust_max is the value where throttle=1.0 for i in range(engine_data.shape[0]): # find the index of the first instance where throttle=1.0 - index = np.where((engine_data[:, 0] == engine_data[i, 0]) & ( - engine_data[:, 1] == engine_data[i, 1]) & (engine_data[:, 2] == 1.0))[0][0] + index = np.where( + (engine_data[:, 0] == engine_data[i, 0]) + & (engine_data[:, 1] == engine_data[i, 1]) + & (engine_data[:, 2] == 1.0) + )[0][0] thrust_max[i] = engine_data[index, 3] - print(Dynamic.Mission.THRUST, '--------------------------------------') + print(Dynamic.Vehicle.Propulsion.THRUST, '--------------------------------------') # add inputs and outputs to interpolator - engine.add_input(Dynamic.Mission.MACH, - engine_data[:, 0], - units='unitless', - desc='Current flight Mach number') - engine.add_input(Dynamic.Mission.ALTITUDE, - engine_data[:, 1], - units='ft', - desc='Current flight altitude') - engine.add_input(Dynamic.Mission.THROTTLE, - engine_data[:, 2], - units='unitless', - desc='Current engine throttle') - engine.add_output(Dynamic.Mission.THRUST, - engine_data[:, 3], - units='lbf', - desc='Current net thrust produced') - engine.add_output(Dynamic.Mission.THRUST_MAX, - thrust_max, - units='lbf', - desc='Max net thrust produced') - engine.add_output(Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, - -engine_data[:, 4], - units='lbm/s', - desc='Current fuel flow rate ') - engine.add_output(Dynamic.Mission.ELECTRIC_POWER_IN, - zeros_array, - units='kW', - desc='Current electric energy rate') - engine.add_output(Dynamic.Mission.NOX_RATE, - zeros_array, - units='lb/h', - desc='Current NOx emission rate') - engine.add_output(Dynamic.Mission.TEMPERATURE_T4, - zeros_array, - units='degR', - desc='Current turbine exit temperature') + engine.add_input( + Dynamic.Atmosphere.MACH, + engine_data[:, 0], + units='unitless', + desc='Current flight Mach number', + ) + engine.add_input( + Dynamic.Mission.ALTITUDE, + engine_data[:, 1], + units='ft', + desc='Current flight altitude', + ) + engine.add_input( + Dynamic.Vehicle.Propulsion.THROTTLE, + engine_data[:, 2], + units='unitless', + desc='Current engine throttle', + ) + engine.add_output( + Dynamic.Vehicle.Propulsion.THRUST, + engine_data[:, 3], + units='lbf', + desc='Current net thrust produced', + ) + engine.add_output( + Dynamic.Vehicle.Propulsion.THRUST_MAX, + thrust_max, + units='lbf', + desc='Max net thrust produced', + ) + engine.add_output( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, + -engine_data[:, 4], + units='lbm/s', + desc='Current fuel flow rate ', + ) + engine.add_output( + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, + zeros_array, + units='kW', + desc='Current electric energy rate', + ) + engine.add_output( + Dynamic.Vehicle.Propulsion.NOX_RATE, + zeros_array, + units='lb/h', + desc='Current NOx emission rate', + ) + engine.add_output( + Dynamic.Vehicle.Propulsion.TEMPERATURE_T4, + zeros_array, + units='degR', + desc='Current turbine exit temperature', + ) return engine - def get_bus_variables(self): + def get_pre_mission_bus_variables(self, aviary_inputs=None): """Transfer training data from pre-mission to mission""" return vars_to_connect def get_controls(self, phase_name): - ''' + """ Builds dictionary of controls for engine off-design. Returns @@ -156,12 +189,11 @@ def get_controls(self, phase_name): Dictionary with keys that are names of variables to be controlled and the values are dictionaries with the keys `units`, `upper`, and `lower` which states the units of the variable to be controlled. - ''' - + """ return {} def get_design_vars(self): - ''' + """ Builds dictionary of design variables for Engine off-design. Returns @@ -169,9 +201,13 @@ def get_design_vars(self): design_vars : dict Dictionary with keys that are names of variables to be made design variables and the values are dictionaries with the keys `units`, `upper`, `lower`, and `ref`. - ''' - mass_flow_dict = {'units': 'lbm/s', 'upper': 450, 'lower': 100, - 'ref': 450} # upper and lower are just notional for now + """ + mass_flow_dict = { + 'units': 'lbm/s', + 'upper': 450, + 'lower': 100, + 'ref': 450, + } # upper and lower are just notional for now design_vars = { Aircraft.Engine.DESIGN_MASS_FLOW: mass_flow_dict, } @@ -179,9 +215,9 @@ def get_design_vars(self): return design_vars -''' +""" inputs: mach, altitude # rename variables # deal with multiple engines -''' +""" diff --git a/aviary/examples/external_subsystems/engine_NPSS/NPSS_variable_meta_data.py b/aviary/examples/external_subsystems/engine_NPSS/NPSS_variable_meta_data.py new file mode 100644 index 0000000000..7a22bc68b7 --- /dev/null +++ b/aviary/examples/external_subsystems/engine_NPSS/NPSS_variable_meta_data.py @@ -0,0 +1,52 @@ +import aviary.api as av +from aviary.examples.external_subsystems.engine_NPSS.NPSS_variables import Aircraft, Dynamic + +ExtendedMetaData = av.CoreMetaData + + +##### ENGINE VALUES ##### + +av.add_meta_data( + Aircraft.Engine.DESIGN_MACH, + units='unitless', + desc='Mach Number at Design Point (Cruise)', + default_value=0.8, + meta_data=ExtendedMetaData, + historical_name={'NPSS': 'ambient.MN_in'}, +) + +av.add_meta_data( + Aircraft.Engine.DESIGN_ALTITUDE, + units='ft', + desc='Altitude at Design Point (Cruise)', + default_value=35000.0, + meta_data=ExtendedMetaData, + historical_name={'NPSS': 'ambient.alt_in'}, +) + +av.add_meta_data( + Aircraft.Engine.DESIGN_MASS_FLOW, + units='lbm/s', + desc='Mass Flow at Design Point (Cruise) for a single engine', + default_value=350.0, + meta_data=ExtendedMetaData, + historical_name={'NPSS': 'start.W_in'}, +) + +av.add_meta_data( + Aircraft.Engine.DESIGN_NET_THRUST, + units='lbf', + desc='Net Thrust at Design Point (Cruise)', + default_value=3888.1, + meta_data=ExtendedMetaData, + historical_name={'NPSS': 'PERF.Fn'}, +) + +av.add_meta_data( + Dynamic.Engine.SHAFT_MECH_SPEED, + units='rpm', + desc='Mechanical Speed of Shaft for Mission From the Part Power Case', + default_value=5000, + meta_data=ExtendedMetaData, + historical_name={'NPSS': 'shaft.Nmech'}, +) diff --git a/aviary/examples/external_subsystems/engine_NPSS/NPSS_variables.py b/aviary/examples/external_subsystems/engine_NPSS/NPSS_variables.py new file mode 100644 index 0000000000..b497673a42 --- /dev/null +++ b/aviary/examples/external_subsystems/engine_NPSS/NPSS_variables.py @@ -0,0 +1,22 @@ +import aviary.api as av + +AviaryAircraft = av.Aircraft +AviaryDynamic = av.Dynamic + + +class Aircraft(AviaryAircraft): + """Aircraft data hierarchy for NPSS model.""" + + class Engine(AviaryAircraft.Engine): + DESIGN_MACH = 'aircraft:engine:design_mach' + DESIGN_ALTITUDE = 'aircraft:engine:design_alt' + DESIGN_MASS_FLOW = 'aircraft:engine:design_mass_flow' + # TODO: will need to use this to calculate the Aviary-core variable aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST using number of engines + DESIGN_NET_THRUST = 'aircraft:engine:design_net_thrust' + + +class Dynamic(AviaryDynamic): + """Dynamics data hierarchy for NPSS model.""" + + class Engine: + SHAFT_MECH_SPEED = 'dynamic:engine:shaft_mech_speed' # Part power variable names diff --git a/aviary/examples/external_subsystems/engine_NPSS/connected_variables.py b/aviary/examples/external_subsystems/engine_NPSS/connected_variables.py new file mode 100755 index 0000000000..ada6733410 --- /dev/null +++ b/aviary/examples/external_subsystems/engine_NPSS/connected_variables.py @@ -0,0 +1,22 @@ +from aviary.examples.external_subsystems.engine_NPSS.NPSS_variables import Dynamic + +vars_to_connect = { + 'Fn_train': { + 'mission_name': [ + Dynamic.Vehicle.Propulsion.THRUST + '_train', + ], + 'units': 'lbf', + }, + 'Fn_max_train': { + 'mission_name': [ + Dynamic.Vehicle.Propulsion.THRUST_MAX + '_train', + ], + 'units': 'lbf', + }, + 'Wf_inv_train': { + 'mission_name': [ + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE + '_train', + ], + 'units': 'lbm/s', + }, +} diff --git a/aviary/examples/external_subsystems/engine_NPSS/define_simple_engine_problem.py b/aviary/examples/external_subsystems/engine_NPSS/define_simple_engine_problem.py deleted file mode 100644 index 434db6156b..0000000000 --- a/aviary/examples/external_subsystems/engine_NPSS/define_simple_engine_problem.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Define an aviary mission with an NPSS defined engine. During pre-mission the engine is designed and an engine deck is made. -During the mission the deck is used for performance. Weight is estimated using the default Aviary method. -The engine model was developed using NPSS v3.2. -""" -from copy import deepcopy -import aviary.api as av - -from aviary.examples.external_subsystems.engine_NPSS.engine_variable_meta_data import ExtendedMetaData -from aviary.examples.external_subsystems.engine_NPSS.table_engine_builder import TableEngineBuilder as EngineBuilder - - -def define_aviary_NPSS_problem(): - """ - Build NPSS model in Aviary - """ - phase_info = deepcopy(av.default_height_energy_phase_info) - - prob = av.AviaryProblem() - - prob.options["group_by_pre_opt_post"] = True - - # Load aircraft and options data from user - # Allow for user overrides here - # add engine builder - prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', - phase_info, engine_builders=[EngineBuilder()], meta_data=ExtendedMetaData) - - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP") - - prob.add_design_variables() - - prob.add_objective() - - prob.setup() - - prob.set_initial_guesses() - return prob diff --git a/aviary/examples/external_subsystems/engine_NPSS/engine_variable_meta_data.py b/aviary/examples/external_subsystems/engine_NPSS/engine_variable_meta_data.py deleted file mode 100644 index 67580a95e1..0000000000 --- a/aviary/examples/external_subsystems/engine_NPSS/engine_variable_meta_data.py +++ /dev/null @@ -1,53 +0,0 @@ -import aviary.api as av -from aviary.examples.external_subsystems.engine_NPSS.engine_variables import Aircraft, Dynamic - - -ExtendedMetaData = av.CoreMetaData - - -##### ENGINE VALUES ##### - -av.add_meta_data( - Aircraft.Engine.DESIGN_MACH, - units='unitless', - desc="Mach Number at Design Point (Cruise)", - default_value=0.8, - meta_data=ExtendedMetaData, - historical_name={'NPSS': 'ambient.MN_in'} -) - -av.add_meta_data( - Aircraft.Engine.DESIGN_ALTITUDE, - units="ft", - desc="Altitude at Design Point (Cruise)", - default_value=35000., - meta_data=ExtendedMetaData, - historical_name={'NPSS': 'ambient.alt_in'} -) - -av.add_meta_data( - Aircraft.Engine.DESIGN_MASS_FLOW, - units="lbm/s", - desc="Mass Flow at Design Point (Cruise) for a single engine", - default_value=350., - meta_data=ExtendedMetaData, - historical_name={'NPSS': 'start.W_in'} -) - -av.add_meta_data( - Aircraft.Engine.DESIGN_NET_THRUST, - units="lbf", - desc="Net Thrust at Design Point (Cruise)", - default_value=3888.1, - meta_data=ExtendedMetaData, - historical_name={'NPSS': 'PERF.Fn'} -) - -av.add_meta_data( - Dynamic.Engine.SHAFT_MECH_SPEED, - units="rpm", - desc="Mechanical Speed of Shaft for Mission From the Part Power Case", - default_value=5000, - meta_data=ExtendedMetaData, - historical_name={'NPSS': 'shaft.Nmech'} -) diff --git a/aviary/examples/external_subsystems/engine_NPSS/engine_variables.py b/aviary/examples/external_subsystems/engine_NPSS/engine_variables.py deleted file mode 100644 index 3a1b6280a9..0000000000 --- a/aviary/examples/external_subsystems/engine_NPSS/engine_variables.py +++ /dev/null @@ -1,26 +0,0 @@ -import aviary.api as av - -AviaryAircraft = av.Aircraft -AviaryDynamic = av.Dynamic - - -class Aircraft(AviaryAircraft): - """ - Aircraft data hierarchy for NPSS model. - """ - - class Engine(AviaryAircraft.Engine): - DESIGN_MACH = "aircraft:engine:design_mach" - DESIGN_ALTITUDE = "aircraft:engine:design_alt" - DESIGN_MASS_FLOW = "aircraft:engine:design_mass_flow" - # TODO: will need to use this to calculate the Aviary-core variable aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST using number of engines - DESIGN_NET_THRUST = "aircraft:engine:design_net_thrust" - - -class Dynamic(AviaryDynamic): - """ - Dynamics data hierarchy for NPSS model. - """ - - class Engine: - SHAFT_MECH_SPEED = "dynamic:engine:shaft_mech_speed" # Part power variable names diff --git a/aviary/examples/external_subsystems/engine_NPSS/run_NPSS_example.py b/aviary/examples/external_subsystems/engine_NPSS/run_NPSS_example.py new file mode 100644 index 0000000000..7557c847cc --- /dev/null +++ b/aviary/examples/external_subsystems/engine_NPSS/run_NPSS_example.py @@ -0,0 +1,42 @@ +""" +Define an aviary mission with an NPSS defined engine. During pre-mission the engine is designed and +an engine deck is made. During the mission the deck is used for performance. Weight is estimated +using the default Aviary method. The engine model was developed using NPSS v3.2. +""" + +import aviary.api as av +from aviary.examples.external_subsystems.engine_NPSS.NPSS_engine_builder import ( + NPSSTabularEngineBuilder, +) +from aviary.examples.external_subsystems.engine_NPSS.NPSS_variable_meta_data import ExtendedMetaData + +"""Build NPSS model in Aviary.""" +phase_info = av.default_height_energy_phase_info + +prob = av.AviaryProblem() + +prob.options['group_by_pre_opt_post'] = True + +# Load aircraft and options data from user +# Allow for user overrides here +# add engine builder +prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', + phase_info, + engine_builders=[NPSSTabularEngineBuilder()], + meta_data=ExtendedMetaData, +) + +prob.check_and_preprocess_inputs() + +prob.build_model() + +prob.add_driver('SLSQP') + +prob.add_design_variables() + +prob.add_objective() + +prob.setup() + +prob.run_aviary_problem(suppress_solver_print=True) diff --git a/aviary/examples/external_subsystems/engine_NPSS/table_engine_connected_variables.py b/aviary/examples/external_subsystems/engine_NPSS/table_engine_connected_variables.py deleted file mode 100755 index 2450f0ae10..0000000000 --- a/aviary/examples/external_subsystems/engine_NPSS/table_engine_connected_variables.py +++ /dev/null @@ -1,22 +0,0 @@ -from aviary.examples.external_subsystems.engine_NPSS.engine_variables import Aircraft, Dynamic - -vars_to_connect = { - "Fn_train": { - "mission_name": [ - Dynamic.Mission.THRUST+"_train", - ], - "units": "lbf", - }, - "Fn_max_train": { - "mission_name": [ - Dynamic.Mission.THRUST_MAX+"_train", - ], - "units": "lbf", - }, - "Wf_inv_train": { - "mission_name": [ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE+"_train", - ], - "units": "lbm/s", - }, -} diff --git a/aviary/examples/external_subsystems/engine_NPSS/test/test_NPSS_builder.py b/aviary/examples/external_subsystems/engine_NPSS/test/test_NPSS_builder.py new file mode 100644 index 0000000000..6f2ca05c7d --- /dev/null +++ b/aviary/examples/external_subsystems/engine_NPSS/test/test_NPSS_builder.py @@ -0,0 +1,78 @@ +"""Benchmark test for aviary mission with an NPSS defined engine.""" + +import os as os +import unittest +from copy import deepcopy + +from openmdao.utils.assert_utils import assert_near_equal + +import aviary.api as av +from aviary.examples.external_subsystems.engine_NPSS.NPSS_engine_builder import ( + NPSSTabularEngineBuilder, +) + +from aviary.examples.external_subsystems.engine_NPSS.NPSS_variable_meta_data import ExtendedMetaData + + +class AviaryNPSSTestCase(unittest.TestCase): + """Test NPSS engine builder from table by building an Aviary model with NPSS engine and run.""" + + @unittest.skipUnless(os.environ.get('NPSS_TOP', False), 'environment does not contain NPSS') + def bench_test_aviary_NPSS(self): + """Build NPSS model in Aviary.""" + phase_info = deepcopy(av.default_height_energy_phase_info) + + prob = av.AviaryProblem() + + prob.options['group_by_pre_opt_post'] = True + + # Load aircraft and options data from user + # Allow for user overrides here + # add engine builder + prob.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', + phase_info, + engine_builders=[NPSSTabularEngineBuilder()], + meta_data=ExtendedMetaData, + ) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.add_driver('SLSQP') + + prob.add_design_variables() + + prob.add_objective() + + prob.setup() + + prob.run_aviary_problem(suppress_solver_print=True) + + rtol = 0.01 + + # There are no truth values for these. + assert_near_equal( + prob.get_val('aircraft:engine:design_mass_flow'), 315.1648646, tolerance=rtol + ) + + assert_near_equal( + prob.get_val('aircraft:engine:scaled_sls_thrust'), 35045.993119, tolerance=rtol + ) + + assert_near_equal( + prob.get_val('traj.cruise.rhs_all.NPSS_prop_system.fuel_flow_rate_negative')[0], + -1.13552634, + tolerance=rtol, + ) + assert_near_equal( + prob.get_val('traj.cruise.rhs_all.NPSS_prop_system.thrust_net')[0], + 4253.95759421, + tolerance=rtol, + ) + + +if __name__ == '__main__': + test = AviaryNPSSTestCase() + test.bench_test_aviary_NPSS() diff --git a/aviary/examples/external_subsystems/engine_NPSS/test_NPSS_builder.py b/aviary/examples/external_subsystems/engine_NPSS/test_NPSS_builder.py deleted file mode 100644 index 79ae3e8b7f..0000000000 --- a/aviary/examples/external_subsystems/engine_NPSS/test_NPSS_builder.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Benchmark test for aviary mission with an NPSS defined engine. -""" - -import unittest -import os as os - -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.examples.external_subsystems.engine_NPSS.define_simple_engine_problem import define_aviary_NPSS_problem - - -class AviaryNPSSTestCase(unittest.TestCase): - """ - Test NPSS engine builder from table by building an Aviary model with NPSS engine and run - """ - - @unittest.skipUnless(os.environ.get('NPSS_TOP', False), 'environment does not contain NPSS') - def bench_test_aviary_NPSS(self): - prob = define_aviary_NPSS_problem() - prob.run_aviary_problem(suppress_solver_print=True) - - rtol = 0.01 - - # There are no truth values for these. - assert_near_equal(prob.get_val('aircraft:engine:design_mass_flow'), - 315.1648646, tolerance=rtol) - - assert_near_equal(prob.get_val('aircraft:engine:scaled_sls_thrust'), - 35045.993119, tolerance=rtol) - - assert_near_equal(prob.get_val('traj.cruise.rhs_all.NPSS_prop_system.fuel_flow_rate_negative')[0], - -1.13552634, tolerance=rtol) - assert_near_equal(prob.get_val('traj.cruise.rhs_all.NPSS_prop_system.thrust_net')[0], - 4253.95759421, tolerance=rtol) - - -if __name__ == '__main__': - test = AviaryNPSSTestCase() - test.bench_test_aviary_NPSS() diff --git a/aviary/examples/level2_shooting_traj.py b/aviary/examples/level2_shooting_traj.py deleted file mode 100644 index e512617366..0000000000 --- a/aviary/examples/level2_shooting_traj.py +++ /dev/null @@ -1,132 +0,0 @@ -""" -Top level run script for an Aviary problem. - -This theoretically could be the Level 2 (intermediate) user's -entry point to Aviary. -""" - -from aviary.api import AviaryProblem -from aviary.api import AnalysisScheme, SpeedType, AlphaModes, Verbosity -from aviary.api import FlexibleTraj -from aviary.api import SGMCruise, SGMDescent -from aviary.api import Dynamic - - -def custom_run_aviary(aircraft_filename, optimizer=None, - analysis_scheme=AnalysisScheme.COLLOCATION, objective_type=None, - record_filename='dymos_solution.db', restart_filename=None, max_iter=50, - run_driver=True, make_plots=True, phase_info_parameterization=None, - optimization_history_filename=None, verbosity=Verbosity.BRIEF): - """ - This function runs the aviary optimization problem for the specified aircraft configuration and mission. - - It first creates an instance of the AviaryProblem class using the given mission_method and mass_method. - It then loads aircraft and options data from the user-provided aircraft_filename and checks for any clashing inputs. - Pre-mission systems are added, phases are added and linked, then post-mission systems are added. - A driver is added using the specified optimizer (The default optimizer depends on the analysis scheme). - Design variables and the optimization objective are added, and the problem is set up. - Initial guesses are set and the optimization problem is run. - The function returns the AviaryProblem instance. - - A user can modify these methods or add their own to modify the behavior - of the Aviary problem. - """ - # Build problem - prob = AviaryProblem(analysis_scheme) - - from aviary.interface.default_phase_info.two_dof_fiti import ascent_phases, \ - add_default_sgm_args, phase_info_parameterization - - phase_info = { - **ascent_phases, - 'cruise': { - 'kwargs': dict( - input_speed_type=SpeedType.MACH, - input_speed_units="unitless", - alpha_mode=AlphaModes.REQUIRED_LIFT, - ), - 'builder': SGMCruise, - 'user_options': { - 'mach': (0, 'unitless'), - 'attr:distance_trigger': (500, 'NM'), - }, - }, - 'desc1': { - 'kwargs': dict( - input_speed_type=SpeedType.MACH, - input_speed_units='unitless', - speed_trigger_units='kn', - ), - 'builder': SGMDescent, - 'user_options': { - 'alt_trigger': (10000, 'ft'), - 'mach': (0, 'unitless'), - 'speed_trigger': (350, 'kn'), - Dynamic.Mission.THROTTLE: (0, 'unitless'), - }, - 'descent_phase': True, - }, - } - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs(aircraft_filename, phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - # ######################################## # - # replace the default trajectory with a custom trajectory - # This trajectory uses the full GASP based ascent profile, - # a distance based cruise, and a simplified descent - phase_info, _ = phase_info_parameterization(phase_info, None, prob.aviary_inputs) - add_default_sgm_args(phase_info, prob.ode_args) - traj = FlexibleTraj( - Phases=phase_info, - traj_final_state_output=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - ], - traj_initial_state_input=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - traj_event_trigger_input=[ - ('groundroll', Dynamic.Mission.VELOCITY, 0,), - ('climb3', Dynamic.Mission.ALTITUDE, 0,), - ('cruise', Dynamic.Mission.DISTANCE, 0,), - ], - ) - prob.traj = prob.model.add_subsystem('traj', traj) - # ######################################## # - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver(optimizer, max_iter=max_iter) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective(objective_type=objective_type) - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem( - record_filename, restart_filename=restart_filename, run_driver=run_driver, make_plots=make_plots) - - return prob - - -if __name__ == "__main__": - input_deck = 'models/large_single_aisle_1/large_single_aisle_1_GwGm.csv' - custom_run_aviary( - input_deck, analysis_scheme=AnalysisScheme.SHOOTING, run_driver=False) diff --git a/aviary/examples/multi_mission/run_multimission_example.py b/aviary/examples/multi_mission/run_multimission_example.py new file mode 100644 index 0000000000..7a9db4aa65 --- /dev/null +++ b/aviary/examples/multi_mission/run_multimission_example.py @@ -0,0 +1,172 @@ +""" +Authors: Eliot Aretskin-Hariton, Kenneth Moore, Jatin Soni +Multi Mission Optimization Example using Aviary. + +In this example, a monolithic optimization is created by instantiating two aviary groups +using using multiple add_aviary_group() calls. Once those groups are setup and all of their +phases are linked together, we then promote GROSS_MASS, RANGE, and wing SWEEP from each of +those sub-groups (prob.model.mission1 and prob.model.mission2) up to prob.model so +the optimizer can control them both with a single value. The fuel_burn results from each +of the mission1 and mission2 are summed and weighted to create the objective function. +""" + +import copy as copy + +import aviary.api as av +from aviary.models.missions.height_energy_default import phase_info +from aviary.validation_cases.validation_tests import get_flops_inputs +from aviary.variable_info.enums import ProblemType +from aviary.variable_info.variables import Aircraft, Mission, Settings + + +def multi_mission_example(): + # fly the same mission twice with two different passenger loads + phase_info_mission1 = copy.deepcopy(phase_info) + phase_info_mission2 = copy.deepcopy(phase_info) + + # get large single aisle values + aviary_inputs_mission1 = get_flops_inputs('LargeSingleAisle2FLOPS') + # loading a CSV - a new ' create vehicle function' + + aviary_inputs_mission2 = copy.deepcopy(aviary_inputs_mission1) + + # Due to current limitations in Aviary's ability to detect user input vs. default values, + # the only way to set an aircraft to zero passengers is by setting + # TOTAL_PAYLOAD_MASS = X CARGO_MASS + 0 PASSENGER_PAYLOAD_MASS. + # This zeros out passenger and baggage mass. + # Due to issue #610, setting PASSENGER_PAYLOAD_MASS = 0 will not work yet. + # aviary_inputs_deadhead.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 4077, 'lbm') + + aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, 1, 'unitless') + aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, 1, 'unitless') + aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS, 0, 'unitless') + aviary_inputs_mission2.set_val(Aircraft.CrewPayload.NUM_FIRST_CLASS, 0, 'unitless') + + # merged_meta_data = av.merge_hierarchies(meta_data1, meta_data2) + # merge all metata data hierarchies here + + prob = av.AviaryProblem(problem_type=ProblemType.MULTI_MISSION) + # set constraints in the background. Currently works with every objective type except Range. + # can accept meta_data = merged_meta_data + + prob.add_aviary_group('mission1', aircraft=aviary_inputs_mission1, mission=phase_info_mission1) + # This method calls load_inputs(), check_and_preprocess_inputs(), and combines meta data. + # This can only accept an AviaryValues, .csv are not accepted. You can pass engine_builders + # and problem_configurator as inputs. + + prob.add_aviary_group('mission2', aircraft=aviary_inputs_mission2, mission=phase_info_mission2) + # Load aircraft in second configuration for same mission + + prob.build_model() + # combines four basic commands + # prob.add_pre_mission_systems() + # prob.add_phases() + # prob.add_post_mission_systems() + # prob.link_phases() + + prob.promote_inputs( + ['mission1', 'mission2'], + [ + (Mission.Design.GROSS_MASS, 'Aircraft1:GROSS_MASS'), + (Mission.Design.RANGE, 'Aircraft1:RANGE'), + (Aircraft.Wing.SWEEP, 'Aircraft1:SWEEP'), + ], + ) + # Links key design variables to ensure both aircraft are modelled the same: + # Design gross mass sizes things like the landing gear + # Design range sizing things like the avionics system + + prob.add_design_var_default( + 'Aircraft1:GROSS_MASS', + lower=10.0, + upper=900e3, + units='lbm', + default_val=100000, + ) + prob.add_design_var_default( + 'Aircraft1:SWEEP', + lower=23.0, + upper=27.0, + units='deg', + default_val=25, + ) + # This both adds the design variable AND sets the default value. This value can be over-written after-setup using set_val. + + prob.add_composite_objective( + ('mission1', Mission.Summary.FUEL_BURNED, 2), + ('mission2', Mission.Summary.FUEL_BURNED, 1), + ref=1, + ) + # Adds an objective where mission 1 is flown 2x more times than mission2 + # Alternative way that users could specify the same objective: + # prob.add_composite_objective_adv(missions=['mission1', 'mission2'], mission_weights=[2,1], outputs=[Mission.Summary.FUEL_BURNED], ref=1) + # TODO: MULTI_MISSION cannot handle RANGE objectives correctly at the moment. + + # optimizer and iteration limit are optional provided here + # Note: IPOPT needs more iters than SNOPT. + prob.add_driver('IPOPT', max_iter=70) + prob.add_design_variables() + + prob.setup() + # combines 2 basic commands: + # prob.setup() + # prob.set_initial_guesses() + + # set_val on OpenMDAO design variables can be placed here and will over-write all other defaults + + prob.set_design_range(('mission1', 'mission2'), range='Aircraft1:RANGE') + # Determines the maximum design_range from both missions and sets that as the design range for both missions + # to ensure that the avionics system is designed similarly for both aircraft + + # TODO: how to handle "aircraft that the user says are the same but are not the same i.e. wing design is different" + + prob.run_aviary_problem() + + return prob + + +def print_mission_outputs(prob, outputs, mission_names): + for var, units in outputs: + for mission in mission_names: + try: + value = prob.get_val(name=f'{mission}.{var}', units=units) + print(f'{mission}.{var} ({units}), {value}') + except: + print(f'{var} was unavailable. Perhapse it has been promoted to the problem level?') + print(' ') + + +if __name__ == '__main__': + prob = multi_mission_example() + objective = prob.get_val('composite_objective', units=None) + + printoutputs = [ + (Mission.Design.GROSS_MASS, 'lbm'), + (Aircraft.Design.EMPTY_MASS, 'lbm'), + (Aircraft.LandingGear.MAIN_GEAR_MASS, 'lbm'), + (Aircraft.LandingGear.NOSE_GEAR_MASS, 'lbm'), + (Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 'unitless'), + (Aircraft.Avionics.MASS, 'lbm'), + (Aircraft.Furnishings.MASS, 'lbm'), + (Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 'lbm'), + (Mission.Summary.GROSS_MASS, 'lbm'), + (Mission.Summary.FUEL_BURNED, 'lbm'), + (Aircraft.CrewPayload.PASSENGER_MASS, 'lbm'), + (Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), + (Aircraft.CrewPayload.CARGO_MASS, 'lbm'), + (Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm'), + ] + + print_mission_outputs(prob, printoutputs, ('mission1', 'mission2')) + + print('Objective Value (unitless): ', objective) + print('Aircraft1:GROSS_MASS (lbm)', prob.get_val('Aircraft1:GROSS_MASS', units='lbm')) + print('Aircraft1:SWEEP (deg)', prob.get_val('Aircraft1:SWEEP', units='deg')) + + # If you notice differences in Aircraft.Design.EMPTY_MASS, your aircraft are not + # mirroring eachother and there is some difference in configuration between the two aircraft. + # Aircraft.Design.EMPTY_MASS is the final dry mass summation from pre-mission. + # You can use the following OpenMDAO commends below to list out and compare + # the each individual mass from every subsystem on the aircraft + # prob.model.mission1.list_vars(val=True, units=True, print_arrays=False) + # prob.model.mission2.list_vars(val=True, units=True, print_arrays=False) diff --git a/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py b/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py deleted file mode 100644 index 2dab1dfb18..0000000000 --- a/aviary/examples/multi_mission/run_multimission_example_large_single_aisle.py +++ /dev/null @@ -1,306 +0,0 @@ -""" -authors: Jatin Soni, Eliot Aretskin -Multi Mission Optimization Example using Aviary - -In this example, a monolithic optimization is created by instantiating two aviary problems -using typical AviaryProblem calls like load_inputs(), check_and_preprocess_payload(), -etc. Once those problems are setup and all of their phases are linked together, we copy -those problems as group into a super_problem. We then promote GROSS_MASS, RANGE, and -wing SWEEP from each of those sub-groups (group1 and group2) up to the super_probem so -the optimizer can control them. The fuel_burn results from each of the group1 and group2 -dymos missions are summed and weighted to create the objective function the optimizer sees. - -""" -import copy as copy -from aviary.examples.example_phase_info import phase_info -from aviary.variable_info.variables import Mission, Aircraft, Settings -from aviary.variable_info.enums import ProblemType -import aviary.api as av -import openmdao.api as om -import matplotlib.pyplot as plt -from os.path import join -import numpy as np -import dymos as dm -import warnings -import sys -from aviary.subsystems.mass.flops_based.furnishings import TransportFurnishingsGroupMass -from aviary.api import SubsystemBuilderBase -from aviary.validation_cases.validation_tests import get_flops_inputs - -# fly the same mission twice with two different passenger loads -phase_info_primary = copy.deepcopy(phase_info) -phase_info_deadhead = copy.deepcopy(phase_info) -# get large single aisle values -aviary_inputs_primary = get_flops_inputs('LargeSingleAisle2FLOPS') -aviary_inputs_primary.set_val(Mission.Design.GROSS_MASS, val=100000, units='lbm') -aviary_inputs_primary.set_val(Settings.VERBOSITY, val=1) - -aviary_inputs_deadhead = copy.deepcopy(aviary_inputs_primary) - -# Due to current limitations in Aviary's ability to detect user input vs. default values, -# the only way to set an aircraft to zero passengers is by setting -# TOTAL_PAYLOAD_MASS = X CARGO_MASS + 0 PASSENGER_PAYLOAD_MASS. -# This zeros out passenger and baggage mass. -# Due to issue #610, setting PASSENGER_PAYLOAD_MASS = 0 will not work yet. -# aviary_inputs_deadhead.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 4077, 'lbm') - -aviary_inputs_deadhead.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, 1, 'unitless') -aviary_inputs_deadhead.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, 1, 'unitless') -aviary_inputs_deadhead.set_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS, 0, 'unitless') -aviary_inputs_deadhead.set_val(Aircraft.CrewPayload.NUM_FIRST_CLASS, 0, 'unitless') - -Optimizer = 'SLSQP' # SLSQP or SNOPT - - -class MultiMissionProblem(om.Problem): - def __init__(self, aviary_values, phase_infos, weights): - super().__init__() - self.num_missions = len(aviary_values) - # phase infos and aviary_values length must match - this maybe unnecessary if - # different aviary_values (payloads) fly same mission (say pax vs cargo) - # or if same payload flies 2 different missions (altitude/mach differences) - if self.num_missions != len(phase_infos): - raise Exception("Length of aviary_values and phase_infos must be the same!") - - # if fewer weights than aviary_values are provided, assign equal weights for all aviary_values - if len(weights) < self.num_missions: - weights = [1]*self.num_missions - # if more weights than aviary_values, raise exception - elif len(weights) > self.num_missions: - raise Exception("Length of weights cannot exceed length of aviary_values!") - self.weights = weights - self.phase_infos = phase_infos - - self.group_prefix = 'group' - self.probs = [] - self.fuel_vars = [] - self.phases = {} - # define individual aviary problems - for i, (aviary_values, phase_info) in enumerate(zip(aviary_values, phase_infos)): - prob = av.AviaryProblem() - prob.load_inputs(aviary_values, phase_info) - prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() - - # alternate prevents use of equality constraint b/w design and summary gross mass - prob.problem_type = ProblemType.MULTI_MISSION - prob.add_design_variables() - self.probs.append(prob) - # phase names for each traj (can be used later to make plots/print outputs) - self.phases[f"{self.group_prefix}_{i}"] = list(prob.traj._phases.keys()) - - # design range and gross mass are promoted, these are Max Range/Max Takeoff Mass - # and must be the same for each aviary problem. Subsystems within aviary are sized - # using these - empty mass is same across all aviary problems. - # the fuel objective is also promoted since that's used in the compound objective - promoted_name = f"{self.group_prefix}_{i}_fuelobj" - self.fuel_vars.append(promoted_name) - self.model.add_subsystem( - self.group_prefix + f'_{i}', prob.model, - promotes_inputs=[Mission.Design.GROSS_MASS, - Mission.Design.RANGE, - Aircraft.Wing.SWEEP], - promotes_outputs=[(Mission.Summary.FUEL_BURNED, promoted_name)]) - - def add_design_variables(self): - self.model.add_design_var(Mission.Design.GROSS_MASS, - lower=10., upper=900e3, units='lbm') - self.model.add_design_var(Aircraft.Wing.SWEEP, lower=23., upper=27., units='deg') - - def add_driver(self): - self.driver = om.pyOptSparseDriver() - if Optimizer == "SLSQP": - self.driver.options["optimizer"] = "SLSQP" - elif Optimizer == "SNOPT": - self.driver.options["optimizer"] = "SNOPT" - self.driver.opt_settings["Major optimality tolerance"] = 1e-7 - self.driver.opt_settings["Major feasibility tolerance"] = 1e-7 - # self.driver.opt_settings["Major iterations"] = 0 - self.driver.opt_settings["iSumm"] = 6 - self.driver.opt_settings["iPrint"] = 9 - self.driver.opt_settings['Verify level'] = -1 - self.driver.opt_settings["Nonderivative linesearch"] = None - self.driver.declare_coloring() - # linear solver causes nan entry error for landing to takeoff mass ratio param - # self.model.linear_solver = om.DirectSolver() - - def add_objective(self): - # weights are normalized - e.g. for given weights 3:1, the normalized - # weights are 0.75:0.25 - weights = [float(weight/sum(self.weights)) for weight in self.weights] - weighted_str = "+".join([f"{fuelobj}*{weight}" - for fuelobj, weight in zip(self.fuel_vars, weights)]) - # weighted_str looks like: fuel_0 * weight[0] + fuel_1 * weight[1] - # note that the fuel objective itself is the base aviary fuel objective - # which is also a function of climb time becuse climb is not very sensitive to fuel - - # adding compound execComp to super problem - self.model.add_subsystem('compound_fuel_burn_objective', om.ExecComp( - "compound = "+weighted_str, has_diag_partials=True), - promotes_inputs=self.fuel_vars, - promotes_outputs=["compound"]) - self.model.add_objective('compound') - - def setup_wrapper(self): - """Wrapper for om.Problem setup with warning ignoring and setting options""" - for prob in self.probs: - prob.model.options['aviary_options'] = prob.aviary_inputs - prob.model.options['aviary_metadata'] = prob.meta_data - prob.model.options['phase_info'] = prob.phase_info - - # Aviary's problem setup wrapper uses these ignored warnings to suppress - # some warnings related to variable promotion. Replicating that here with - # setup for the super problem - with warnings.catch_warnings(): - warnings.simplefilter("ignore", om.OpenMDAOWarning) - warnings.simplefilter("ignore", om.PromotionWarning) - self.setup(check='all') - - def run(self): - self.model.set_solver_print(0) - dm.run_problem(self, make_plots=False) - - def get_design_range(self): - """Finds the longest mission and sets its range as the design range for all - Aviary problems. Used within Aviary for sizing subsystems (avionics and AC).""" - design_range = [] - for phase_info in self.phase_infos: - design_range.append(phase_info['post_mission'] - ['target_range'][0]) # TBD add units - design_range_min = np.min(design_range) - design_range_max = np.max(design_range) - return design_range_max, design_range_min # design_range_min - - def create_timeseries_plots(self, plotvars=[], show=True): - """ - Temporary create plots manually because graphing won't work for dual-trajectories. - Creates timeseries plots for any variables within timeseries. Specify variables - and units by setting plotvars = [('altitude','ft')]. Any number of vars can be added. - """ - plt.figure() - for plotidx, (var, unit) in enumerate(plotvars): - plt.subplot(int(np.ceil(len(plotvars)/2)), 2, plotidx+1) - for i in range(self.num_missions): - time = np.array([]) - yvar = np.array([]) - # this loop concatenates data from all phases - for phase in self.phases[f"{self.group_prefix}_{i}"]: - rawt = self.get_val( - f"{self.group_prefix}_{i}.traj.{phase}.timeseries.time", - units='s') - rawy = self.get_val( - f"{self.group_prefix}_{i}.traj.{phase}.timeseries.{var}", - units=unit) - time = np.hstack([time, np.ndarray.flatten(rawt)]) - yvar = np.hstack([yvar, np.ndarray.flatten(rawy)]) - plt.plot(time, yvar, linewidth=self.num_missions-i) - plt.xlabel("Time (s)") - plt.ylabel(f"{var.title()} ({unit})") - plt.grid() - plt.figlegend([f"Mission {i}" for i in range(self.num_missions)]) - if show: - plt.show() - - def print_vars(self, vars=[]): - """Specify vars with name and unit in a tuple, e.g. vars = [ (Mission.Summary.FUEL_BURNED, 'lbm') ]""" - - print("\n\n=========================\n") - print(f"{'':40}", end=': ') - for i in range(self.num_missions): - name = f"Mission {i}" - print(f"{name:^30}", end='| ') - print() - for var, unit in vars: - varname = f"{var.replace(':', '.').upper()}" - print(f"{varname:40}", end=": ") - for i in range(self.num_missions): - try: - val = self.get_val(f'group_{i}.{var}', units=unit)[0] - printstatement = f"{val} ({unit})" - except: - printstatement = f"unable get get_val({var})" - print(f"{printstatement:^30}", end="| ") - print() - - -def large_single_aisle_example(makeN2=False): - aviary_values = [aviary_inputs_primary, - aviary_inputs_deadhead] - phase_infos = [phase_info_primary, - phase_info_deadhead] - optalt, optmach = False, False - for phaseinfo in phase_infos: - for key in phaseinfo.keys(): - if "user_options" in phaseinfo[key].keys(): - phaseinfo[key]["user_options"]["optimize_mach"] = optmach - phaseinfo[key]["user_options"]["optimize_altitude"] = optalt - - # how much each mission should be valued by the optimizer, larger numbers = more significance - weights = [9, 1] - - super_prob = MultiMissionProblem(aviary_values, phase_infos, weights) - super_prob.add_driver() - super_prob.add_design_variables() - super_prob.add_objective() - # set input default to prevent error, value doesn't matter since set val is used later - super_prob.model.set_input_defaults(Mission.Design.RANGE, val=1.) - super_prob.setup_wrapper() - super_prob.set_val(Mission.Design.RANGE, super_prob.get_design_range()[0]) - - for i, prob in enumerate(super_prob.probs): - prob.set_initial_guesses(super_prob, super_prob.group_prefix+f"_{i}.") - - if makeN2: - # TODO: Not sure we need this at all. - from openmdao.api import n2 - from os.path import basename, dirname, join, abspath - - def createN2(fileref, prob): - n2folder = join(dirname(abspath(__file__)), "N2s") - n2(prob, outfile=join(n2folder, - f"n2_{basename(fileref).split('.')[0]}.html")) - - createN2(__file__, super_prob) - - super_prob.run() - printoutputs = [ - (Mission.Design.GROSS_MASS, 'lbm'), - (Aircraft.Design.EMPTY_MASS, 'lbm'), - (Aircraft.Wing.SWEEP, 'deg'), - (Aircraft.LandingGear.MAIN_GEAR_MASS, 'lbm'), - (Aircraft.LandingGear.NOSE_GEAR_MASS, 'lbm'), - (Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 'unitless'), - (Aircraft.Furnishings.MASS, 'lbm'), - (Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 'lbm'), - (Mission.Summary.GROSS_MASS, 'lbm'), - (Mission.Summary.FUEL_BURNED, 'lbm'), - (Aircraft.CrewPayload.PASSENGER_MASS, 'lbm'), - (Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), - (Aircraft.CrewPayload.CARGO_MASS, 'lbm'), - (Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm')] - super_prob.print_vars(vars=printoutputs) - - plotvars = [('altitude', 'ft'), - ('mass', 'lbm'), - ('drag', 'lbf'), - ('distance', 'nmi'), - ('throttle', 'unitless'), - ('mach', 'unitless')] - super_prob.create_timeseries_plots(plotvars=plotvars, show=False) - - plt.show() - - return super_prob - - -if __name__ == '__main__': - makeN2 = True if (len(sys.argv) > 1 and "n2" in sys.argv[1]) else False - - super_prob = large_single_aisle_example(makeN2=makeN2) - - # Uncomment the following lines to see mass breakdown details for each mission. - # super_prob.model.group_1.list_vars(val=True, units=True, print_arrays=False) - # super_prob.model.group_2.list_vars(val=True, units=True, print_arrays=False) diff --git a/aviary/examples/reserve_missions/run_2dof_reserve_mission_fixedrange.py b/aviary/examples/reserve_missions/run_2dof_reserve_mission_fixedrange.py deleted file mode 100644 index aafdb4aa1f..0000000000 --- a/aviary/examples/reserve_missions/run_2dof_reserve_mission_fixedrange.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. -This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. - -We define a `phase_info` object, which tells Aviary how to model the mission. -Here we have climb, cruise, and descent phases. -We then call the correct methods in order to set up and run an Aviary optimization problem. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. -""" - -import aviary.api as av -from aviary.interface.default_phase_info.two_dof import phase_info -from copy import deepcopy - -phase_info = deepcopy(phase_info) - -# Add reserve phase(s) -reserve_cruise = deepcopy(phase_info['cruise']) -reserve_cruise['user_options']['reserve'] = True -reserve_cruise['user_options']['target_distance'] = (200, 'km') -reserve_cruise['initial_guesses']['initial_distance'] = (3700, 'nmi') - -phase_info.update({'reserve_cruise': reserve_cruise}) - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_GwGm.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SNOPT", max_iter=50, verbosity=2) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(record_filename='2dof_reserve_mission_fixedrange.db') diff --git a/aviary/examples/reserve_missions/run_2dof_reserve_mission_fixedtime.py b/aviary/examples/reserve_missions/run_2dof_reserve_mission_fixedtime.py deleted file mode 100644 index 9f3f82f3eb..0000000000 --- a/aviary/examples/reserve_missions/run_2dof_reserve_mission_fixedtime.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. -This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. - -We define a `phase_info` object, which tells Aviary how to model the mission. -Here we have climb, cruise, and descent phases. -We then call the correct methods in order to set up and run an Aviary optimization problem. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. -""" -import aviary.api as av -from aviary.interface.default_phase_info.two_dof import phase_info -from copy import deepcopy - -phase_info = deepcopy(phase_info) - -# Add reserve phase(s) -reserve_cruise = deepcopy(phase_info['cruise']) -reserve_cruise['user_options']['reserve'] = True -reserve_cruise['user_options']['target_duration'] = (30, 'min') -reserve_cruise['user_options']['initial_bounds'] = ((149.5, 448.5), "min") -reserve_cruise['initial_guesses']['initial_distance'] = (4000, 'nmi') - -phase_info.update({'reserve_cruise': reserve_cruise}) - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_GwGm.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SNOPT", max_iter=50) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(record_filename='2dof_reserve_mission_fixedtime.db') diff --git a/aviary/examples/reserve_missions/run_2dof_reserve_mission_multiphase.py b/aviary/examples/reserve_missions/run_2dof_reserve_mission_multiphase.py deleted file mode 100644 index 45aa0d0bf7..0000000000 --- a/aviary/examples/reserve_missions/run_2dof_reserve_mission_multiphase.py +++ /dev/null @@ -1,101 +0,0 @@ -""" -This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. -This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. - -We define a `phase_info` object, which tells Aviary how to model the mission. -Here we have climb, cruise, and descent phases. -We then call the correct methods in order to set up and run an Aviary optimization problem. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. -""" -import aviary.api as av -from aviary.interface.default_phase_info.two_dof import phase_info -from copy import deepcopy - -phase_info = deepcopy(phase_info) -# Add reserve phase(s) -reserve_climb1 = deepcopy(phase_info['climb1']) -reserve_climb1['user_options']['reserve'] = True -reserve_climb1['user_options']['distance_upper'] = (5000, 'NM') -reserve_climb1['initial_guesses']['distance'] = ([3675, 3700], 'nmi') - -reserve_climb2 = deepcopy(phase_info['climb2']) -reserve_climb2['user_options']['reserve'] = True -reserve_climb2['user_options']['final_altitude'] = (25e3, 'ft') -reserve_climb2['user_options']['distance_upper'] = (5000, 'NM') -reserve_climb2['initial_guesses']['altitude'] = ([10e3, 25e3], 'ft') -reserve_climb2['initial_guesses']['distance'] = ([3700, 3725], 'nmi') - -distance_cruise1 = deepcopy(phase_info['cruise']) -distance_cruise1['user_options']['reserve'] = True -distance_cruise1['user_options']['alt_cruise'] = (25e3, 'ft') -distance_cruise1['user_options']['target_distance'] = (100, 'nmi') -distance_cruise1['initial_guesses']['altitude'] = (25e3, 'ft') -distance_cruise1['initial_guesses']['initial_distance'] = (3725, 'nmi') - -duration_cruise1 = deepcopy(phase_info['cruise']) -duration_cruise1['user_options']['reserve'] = True -duration_cruise1['user_options']['alt_cruise'] = (25e3, 'ft') -duration_cruise1['user_options']['target_duration'] = (30, 'min') -duration_cruise1['user_options']['initial_bounds'] = ((149.5, 448.5), "min") -duration_cruise1['initial_guesses']['altitude'] = (25e3, 'ft') -duration_cruise1['initial_guesses']['initial_distance'] = (3825, 'nmi') - -distance_cruise2 = deepcopy(phase_info['cruise']) -distance_cruise2['user_options']['reserve'] = True -distance_cruise2['user_options']['alt_cruise'] = (25e3, 'ft') -distance_cruise2['user_options']['target_distance'] = (75, 'nmi') -distance_cruise2['initial_guesses']['altitude'] = (25e3, 'ft') -distance_cruise2['initial_guesses']['initial_distance'] = (3900, 'nmi') - -reserve_descent1 = deepcopy(phase_info['desc1']) -reserve_descent1['user_options']['reserve'] = True -reserve_descent1['initial_guesses']['altitude'] = ([25e3, 10e3], 'ft') -reserve_descent1['initial_guesses']['distance'] = ([3900, 3925], 'nmi') - -reserve_descent2 = deepcopy(phase_info['desc2']) -reserve_descent2['user_options']['reserve'] = True -reserve_descent2['initial_guesses']['distance'] = ([3925, 3950], 'nmi') - -phase_info.update({ - "reserve_climb1": reserve_climb1, - "reserve_climb2": reserve_climb2, - "reserve_cruise_fixed_range": distance_cruise1, - "reserve_cruise_fixed_time": duration_cruise1, - "reserve_cruise_fixed_range_2": distance_cruise2, - "reserve_desc1": reserve_descent1, - "reserve_desc2": reserve_descent2, -}) - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_GwGm.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SNOPT", max_iter=50) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(record_filename='2dof_reserve_mission_multiphase.db') diff --git a/aviary/examples/reserve_missions/run_reserve_mission_fixedrange.py b/aviary/examples/reserve_missions/run_reserve_mission_fixedrange.py deleted file mode 100644 index c138d59e5f..0000000000 --- a/aviary/examples/reserve_missions/run_reserve_mission_fixedrange.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. -This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. - -We define a `phase_info` object, which tells Aviary how to model the mission. -Here we have climb, cruise, and descent phases. -We then call the correct methods in order to set up and run an Aviary optimization problem. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. -""" -import aviary.api as av -from aviary.examples.example_phase_info import phase_info -from copy import deepcopy - -phase_info = deepcopy(phase_info) - -# Copy the current cruise phase, then make it a reserve phase -reserve_phase_0 = deepcopy(phase_info['cruise']) -reserve_phase_0['user_options']['reserve'] = True -reserve_phase_0['user_options']['target_distance'] = (200, 'km') -# remove the climb from the original cruise -reserve_phase_0['user_options']['final_altitude'] = (32000.0, "ft") -# This cruise is much shorter so we need to revise the duration_bounds for this phase -reserve_phase_0['user_options']['duration_bounds'] = ((0, 120.0), "min") - -# Add the reserve phase to phase_info -phase_info.update({'reserve_cruise': reserve_phase_0}) - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP", max_iter=100) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(record_filename='reserve_mission_fixedrange.db') diff --git a/aviary/examples/reserve_missions/run_reserve_mission_fixedtime.py b/aviary/examples/reserve_missions/run_reserve_mission_fixedtime.py deleted file mode 100644 index 12251aaf37..0000000000 --- a/aviary/examples/reserve_missions/run_reserve_mission_fixedtime.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. -This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. - -We define a `phase_info` object, which tells Aviary how to model the mission. -Here we have climb, cruise, and descent phases. -We then call the correct methods in order to set up and run an Aviary optimization problem. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. -""" -import aviary.api as av -from aviary.examples.example_phase_info import phase_info -from copy import deepcopy - -phase_info = deepcopy(phase_info) - -# Copy the current cruise phase, then make it a reserve phase -reserve_phase_0 = deepcopy(phase_info['cruise']) -reserve_phase_0['user_options']['reserve'] = True -reserve_phase_0['user_options']['target_duration'] = (30, 'min') - -# Add the reserve phase to phase_info -phase_info.update({'reserve_cruise': reserve_phase_0}) - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP", max_iter=100) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(record_filename='reserve_mission_fixedtime.db') diff --git a/aviary/examples/reserve_missions/run_reserve_mission_multiphase.py b/aviary/examples/reserve_missions/run_reserve_mission_multiphase.py index 06402a4e21..d221c28def 100644 --- a/aviary/examples/reserve_missions/run_reserve_mission_multiphase.py +++ b/aviary/examples/reserve_missions/run_reserve_mission_multiphase.py @@ -1,179 +1,139 @@ """ -This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. -This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. +This is a slightly more complex Aviary example of sizing an aircraft whose design mission includes +a reserve segment. It is the same basic problem as the `level2_example.py` script, but with the +addition of a reserve mission. -We define a `phase_info` object, which tells Aviary how to model the mission. -Here we have climb, cruise, and descent phases. -We then call the correct methods in order to set up and run an Aviary optimization problem. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. +The pre-existing phase_info data is imported, and a reserve mission with a climb, 2 cruise, and a +descent segment are added. The first cruise has a fixed range, while the second cruise has a fixed +time (i.e. a loiter) to demonstrate how different reserve missions can be created. + +We then call the correct methods in order to set up and run an Aviary problem using the level 2 +interface. """ + import aviary.api as av -from aviary.examples.example_phase_info import phase_info -from copy import deepcopy +from aviary.models.missions.height_energy_default import phase_info -phase_info = deepcopy(phase_info) -# Add reserve phase(s) -phase_info.update({ - "reserve_climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "reserve": True, - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.36, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.18, 0.74), "unitless"), - "initial_altitude": (0.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((0.0, 32000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((64.0, 192.0), "min"), - }, - "initial_guesses": {"time": ([0, 128], "min")}, - }, - "reserve_cruise_fixed_range": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "reserve": True, - # Distance traveled in this phase - "target_distance": (200, 'km'), - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((149.5, 448.5), "min"), - "duration_bounds": ((0, 300), "min"), +##################### +# Define Phase Info # +##################### + +# Add reserve phases to existing phase_info +phase_info.update( + { + 'reserve_climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'reserve': True, + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.36, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (500.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((30.0, 192.0), 'min'), + }, + 'initial_guesses': { + 'time': ([0, 128], 'min'), + }, }, - "initial_guesses": {"time": ([30, 120], "min")}, - }, - "reserve_cruise_fixed_time": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "reserve": True, - # Time length of this phase - "target_duration": (45, "min"), - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "initial_bounds": ((149.5, 448.5), "min"), + 'reserve_cruise_fixed_range': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'reserve': True, + # Distance traveled in this phase + 'target_distance': (300, 'km'), + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((149.5, 448.5), 'min'), + 'time_duration_bounds': ((0, 300), 'min'), + }, + 'initial_guesses': { + 'time': ([30, 120], 'min'), + }, }, - }, - "reserve_cruise_fixed_range_2": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "reserve": True, - # Distance traveled in this phase - "target_distance": (100, 'km'), - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((149.5, 448.5), "min"), - "duration_bounds": ((0, 300), "min"), + 'reserve_cruise_fixed_time': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'reserve': True, + # Time length of this phase + 'time_duration': (30, 'min'), + 'num_segments': 5, + 'order': 3, + 'distance_solve_segments': False, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((60, 448.5), 'min'), + }, }, - "initial_guesses": {"time": ([30, 120], "min")}, - }, - "reserve_descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "reserve": True, - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.36, "unitless"), - "mach_bounds": ((0.34, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (500.0, "ft"), - "altitude_bounds": ((0.0, 32000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((29.0, 87.0), "min"), + 'reserve_descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'reserve': True, + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.36, 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((120.5, 550.0), 'min'), + 'time_duration_bounds': ((29.0, 87.0), 'min'), + }, }, - "initial_guesses": {"time": ([241, 58], "min")}, } -}) - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() +) - prob.add_pre_mission_systems() +###################### +# Run Aircraft Model # +###################### - prob.add_phases() +prob = av.AviaryProblem() - prob.add_post_mission_systems() +# Load aircraft and options data from user +# Allow for user overrides here +prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', phase_info +) - # Link phases and variables - prob.link_phases() +prob.check_and_preprocess_inputs() - prob.add_driver("SLSQP", max_iter=100) +prob.build_model() - prob.add_design_variables() +prob.add_driver('SLSQP') - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective() +prob.add_design_variables() - prob.setup() +# Load optimization problem formulation +# Detail which variables the optimizer can control +prob.add_objective() - prob.set_initial_guesses() +prob.setup() - prob.run_aviary_problem(record_filename='reserve_mission_multiphase.db') +prob.run_aviary_problem() diff --git a/aviary/examples/run_aviary_example.py b/aviary/examples/run_aviary_example.py deleted file mode 100644 index 9e434b42d3..0000000000 --- a/aviary/examples/run_aviary_example.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. -This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. - -We define a `phase_info` object, which tells Aviary how to model the mission. -Here we have climb, cruise, and descent phases. -We then call the correct methods in order to set up and run an Aviary optimization problem. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. -""" -import aviary.api as av -from example_phase_info import phase_info - -prob = av.AviaryProblem() - -# Load aircraft and options data from user -# Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) - -# Preprocess inputs -prob.check_and_preprocess_inputs() - -prob.add_pre_mission_systems() - -prob.add_phases() - -prob.add_post_mission_systems() - -# Link phases and variables -prob.link_phases() - -prob.add_driver("SLSQP", max_iter=100) - -prob.add_design_variables() - -# Load optimization problem formulation -# Detail which variables the optimizer can control -prob.add_objective() - -prob.setup() - -prob.set_initial_guesses() - -prob.run_aviary_problem() diff --git a/aviary/examples/run_basic_aviary_example.py b/aviary/examples/run_basic_aviary_example.py deleted file mode 100644 index a1fe4abd71..0000000000 --- a/aviary/examples/run_basic_aviary_example.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -This is a straightforward and basic example of running a coupled aircraft design-mission optimization in Aviary. -This uses the "level 1" API within Aviary. - -We use the pre-defined single aisle commercial transport aircraft definition and use a pre-defined phase_info object -to describe the mission optimization problem to Aviary. -This mission consists of climb, cruise, and descent phases. -We then call the `run_aviary` function, which takes in the path to the aircraft model, the phase info, and some other options. -This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. -""" -import aviary.api as av - - -prob = av.run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', av.default_height_energy_phase_info, - optimizer="SLSQP", make_plots=True) diff --git a/aviary/examples/run_custom_optimization_example.py b/aviary/examples/run_custom_optimization_example.py new file mode 100644 index 0000000000..e640a08654 --- /dev/null +++ b/aviary/examples/run_custom_optimization_example.py @@ -0,0 +1,58 @@ +""" +This is an example of running constrained optimization in Aviary using the "level 2" API. It runs +the same aircraft and mission as the `level1_example.py` script, but it uses the AviaryProblem class +to set up the problem. + +The same ".csv" file is used to define the aircraft, but wing area and engine scale factor are added +as design variables. Then, wing loading and thrust-to-weight ratio are constrained to arbitrary +limits. If this example is run without these constraints, wing area is increased to its upper bound +and engine scale factor is reduced to its lower bound. +""" + +from aviary.models.missions.height_energy_default import phase_info + +import aviary.api as av + +# Suppress outputs +prob = av.AviaryProblem(verbosity=0) + +# Load aircraft and options data from provided sources +prob.load_inputs('models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) + +prob.check_and_preprocess_inputs() + +prob.add_pre_mission_systems() + +prob.add_phases() + +prob.add_post_mission_systems() + +prob.link_phases() + +# Optimizer and iteration limit are optional provided here +prob.add_driver('SLSQP', max_iter=20) + +# Add the default design variables needed to size the aircraft +prob.add_design_variables() + +# Add wing area and engine scaling as additional design variables +prob.model.add_design_var(av.Aircraft.Engine.SCALE_FACTOR, lower=0.8, upper=1.2, ref=1) +prob.model.add_design_var(av.Aircraft.Wing.AREA, lower=1200, upper=1800, units='ft**2', ref=1400) + +prob.add_objective() + +# Constrain wing loading and thrust-to-weight ratio +prob.model.add_constraint(av.Aircraft.Design.WING_LOADING, lower=120, units='lbf/ft**2') +prob.model.add_constraint(av.Aircraft.Design.THRUST_TO_WEIGHT_RATIO, lower=0.35) + +prob.setup() + +prob.run_aviary_problem() + +print(f'\nTakeoff Gross Weight = {prob.get_val(av.Mission.Summary.GROSS_MASS, units="lbm")} lbm') +print('\nDesign Variables\n---------------') +print(f'Engine Scale Factor (started at 1) = {prob.get_val(av.Aircraft.Engine.SCALE_FACTOR)}') +print(f'Wing Area (started at 1370) = {prob.get_val(av.Aircraft.Wing.AREA, units="ft**2")} ft^2') +print('\nConstraints\n-----------') +print(f'Wing Loading = {prob.get_val(av.Aircraft.Design.WING_LOADING, units="lbf/ft**2")} lbf/ft^2') +print(f'Thrust/Weight Ratio = {prob.get_val(av.Aircraft.Design.THRUST_TO_WEIGHT_RATIO)}') diff --git a/aviary/examples/run_detailed_landing_in_level2.py b/aviary/examples/run_detailed_landing_in_level2.py deleted file mode 100644 index 82c6fd2201..0000000000 --- a/aviary/examples/run_detailed_landing_in_level2.py +++ /dev/null @@ -1,204 +0,0 @@ -import openmdao.api as om -import aviary.api as av - - -subsystem_options = {'core_aerodynamics': - {'method': 'low_speed', - 'ground_altitude': 0., # units='ft' - 'angles_of_attack': [ - -5.0, -4.0, -3.0, -2.0, -1.0, - 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, - 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, - 12.0, 13.0, 14.0, 15.0], # units='deg' - 'lift_coefficients': [ - 0.01, 0.1, 0.2, 0.3, 0.4, - 0.5178, 0.6, 0.75, 0.85, 0.95, 1.05, - 1.15, 1.25, 1.35, 1.5, 1.6, 1.7, - 1.8, 1.85, 1.9, 1.95], - 'drag_coefficients': [ - 0.04, 0.02, 0.01, 0.02, 0.04, - 0.0674, 0.065, 0.065, 0.07, 0.072, 0.076, - 0.084, 0.09, 0.10, 0.11, 0.12, 0.13, - 0.15, 0.16, 0.18, 0.20], - 'lift_coefficient_factor': 2., - 'drag_coefficient_factor': 2.}} -subsystem_options_landing = subsystem_options.copy() -subsystem_options_landing['core_aerodynamics']['drag_coefficient_factor'] = 3. - -optimize_mach = False -optimize_altitude = False - -phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": False}, - 'GH': { - 'user_options': { - 'num_segments': 5, - 'order': 3, - 'fix_initial': True, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((0., 16.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((500., 5.e3), 'ft'), - 'mach_bounds': ((0.1, 0.5), 'unitless'), - 'initial_mach': (0.15, 'unitless'), - 'final_mach': (0.15, 'unitless'), - 'initial_altitude': (500., 'ft'), - 'final_altitude': (394., 'ft'), - 'altitude_bounds': ((0., 1000.), 'ft'), - 'polynomial_control_order': 1, - 'throttle_enforcement': 'bounded', - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'rotation': False, - 'constraints': { - 'flight_path_angle': { - 'equals': -3., - 'loc': 'initial', - 'units': 'deg', - 'type': 'boundary', - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(0.e3, 2.e3), 'ft'], - 'time': [(0., 12.), 's'], - 'mass': [(120.e3, 119.8e3), 'lbm'], - }, - }, - 'HI': { - 'user_options': { - 'num_segments': 5, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((0., 16.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((500., 15.e3), 'ft'), - 'mach_bounds': ((0.1, 0.5), 'unitless'), - 'altitude_bounds': ((0., 1000.), 'ft'), - 'initial_mach': (0.15, 'unitless'), - 'final_mach': (0.15, 'unitless'), - 'initial_altitude': (394., 'ft'), - 'final_altitude': (50., 'ft'), - 'polynomial_control_order': 1, - 'throttle_enforcement': 'bounded', - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'rotation': False, - 'constraints': { - 'flight_path_angle': { - 'equals': -3., - 'loc': 'final', - 'units': 'deg', - 'type': 'boundary', - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(2.e3, 6.5e3), 'ft'], - 'time': [(12., 50.), 's'], - 'mass': [(119.8e3, 119.7e3), 'lbm'], - }, - }, - 'IJ': { - 'user_options': { - 'num_segments': 5, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((0., 30.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((500., 15.e3), 'ft'), - 'mach_bounds': ((0.1, 0.5), 'unitless'), - 'altitude_bounds': ((0., 1000.), 'ft'), - 'initial_mach': (0.15, 'unitless'), - 'final_mach': (0.15, 'unitless'), - 'initial_altitude': (50., 'ft'), - 'final_altitude': (0., 'ft'), - 'polynomial_control_order': 2, - 'throttle_enforcement': 'path_constraint', - 'optimize_mach': False, - 'optimize_altitude': True, - 'rotation': False, - 'constraints': { - }, - }, - 'subsystem_options': subsystem_options_landing, - 'initial_guesses': { - 'distance': [(8.5e3, 2.e3), 'ft'], - 'time': [(50., 60.), 's'], - 'mass': [(119.7e3, 119.67e3), 'lbm'], - }, - }, - "post_mission": { - "include_landing": False, - "constrain_range": False, - }, -} - - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs( - 'models/test_aircraft/aircraft_for_bench_solved2dof.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP", max_iter=100) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective('mass') - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(record_filename='detailed_landing.db') - - cr = om.CaseReader('detailed_landing.db') - cases = cr.get_cases('problem') - case = cases[0] - - output_data = {} - - point_name = 'P3' - phase_name = 'GH' - output_data[point_name] = {} - output_data[point_name]['thrust_fraction'] = case.get_val(f'traj.{phase_name}.rhs_all.thrust_net', units='N')[ - -1][0] / case.get_val(f'traj.{phase_name}.rhs_all.thrust_net_max', units='N')[-1][0] - output_data[point_name]['true_airspeed'] = case.get_val( - f'traj.{phase_name}.timeseries.velocity', units='kn')[-1][0] - output_data[point_name]['angle_of_attack'] = case.get_val( - f'traj.{phase_name}.timeseries.alpha', units='deg')[-1][0] - output_data[point_name]['flight_path_angle'] = case.get_val( - f'traj.{phase_name}.timeseries.flight_path_angle', units='deg')[-1][0] - output_data[point_name]['altitude'] = case.get_val( - f'traj.{phase_name}.timeseries.altitude', units='ft')[-1][0] - output_data[point_name]['distance'] = case.get_val( - f'traj.{phase_name}.timeseries.distance', units='ft')[-1][0] - - print(output_data) diff --git a/aviary/examples/run_detailed_takeoff_in_level2.py b/aviary/examples/run_detailed_takeoff_in_level2.py deleted file mode 100644 index 9b1607ea94..0000000000 --- a/aviary/examples/run_detailed_takeoff_in_level2.py +++ /dev/null @@ -1,379 +0,0 @@ -import openmdao.api as om -import aviary.api as av - - -subsystem_options = {'core_aerodynamics': - {'method': 'low_speed', - 'ground_altitude': 0., # units='ft' - 'angles_of_attack': [ - -5.0, -4.0, -3.0, -2.0, -1.0, - 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, - 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, - 12.0, 13.0, 14.0, 15.0], # units='deg' - 'lift_coefficients': [ - 0.01, 0.1, 0.2, 0.3, 0.4, - 0.5178, 0.6, 0.75, 0.85, 0.95, 1.05, - 1.15, 1.25, 1.35, 1.5, 1.6, 1.7, - 1.8, 1.85, 1.9, 1.95], - 'drag_coefficients': [ - 0.04, 0.02, 0.01, 0.02, 0.04, - 0.0674, 0.065, 0.065, 0.07, 0.072, 0.076, - 0.084, 0.09, 0.10, 0.11, 0.12, 0.13, - 0.15, 0.16, 0.18, 0.20], - 'lift_coefficient_factor': 1., - 'drag_coefficient_factor': 1.}} - -optimize_mach = True -optimize_altitude = True -optimizer = "SLSQP" - -phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": False}, - 'AB': { - 'user_options': { - 'num_segments': 5, - 'order': 3, - 'fix_initial': True, - 'ground_roll': True, - 'duration_ref': (100., 'kn'), - 'duration_bounds': ((100., 500.), 'kn'), - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(0., 2.e3), 'ft'], - 'time': [(0., 20.), 's'], - 'velocity': [(1., 120.), 'kn'], - 'mass': [(175.e3, 174.85e3), 'lbm'], - }, - }, - 'rotate': { - 'user_options': { - 'num_segments': 5, - 'order': 3, - 'fix_initial': False, - 'ground_roll': True, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((1.e3, 3.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((200., 2.e3), 'ft'), - 'mach_bounds': ((0.18, 0.2), 'unitless'), - 'polynomial_control_order': 1, - 'throttle_enforcement': 'boundary_constraint', - 'optimize_mach': optimize_mach, - 'optimize_altitude': False, - 'rotation': True, - 'initial_mach': (0.18, 'unitless'), - 'final_mach': (0.2, 'unitless'), - 'initial_altitude': (0., 'ft'), - 'final_altitude': (0., 'ft'), - 'constraints': { - 'normal_force': { - 'equals': 0., - 'loc': 'final', - 'units': 'lbf', - 'type': 'boundary', - 'ref': 10.e5, - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(2.e3, 1.e3), 'ft'], - 'time': [(20., 25.), 's'], - 'mass': [(174.85e3, 174.84e3), 'lbm'], - 'alpha': [(0., 12.), 'deg'], - }, - }, - 'BC': { - 'user_options': { - 'num_segments': 5, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((1., 16.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((500., 1500.), 'ft'), - 'mach_bounds': ((0.2, 0.22), 'unitless'), - 'altitude_bounds': ((0., 250.), 'ft'), - 'initial_mach': (0.2, 'unitless'), - 'final_mach': (0.22, 'unitless'), - 'initial_altitude': (0., 'ft'), - 'final_altitude': (50., 'ft'), - 'polynomial_control_order': 1, - 'throttle_enforcement': 'boundary_constraint', - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'rotation': False, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(3.e3, 1.e3), 'ft'], - 'time': [(25., 35.), 's'], - 'mass': [(174.84e3, 174.82e3), 'lbm'], - }, - }, - 'CD_to_P2': { - 'user_options': { - 'num_segments': 4, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((1.e3, 20.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((3.e3, 20.e3), 'ft'), - 'mach_bounds': ((0.22, 0.3), 'unitless'), - 'altitude_bounds': ((0., 985.), 'ft'), - 'initial_mach': (0.22, 'unitless'), - 'final_mach': (0.3, 'unitless'), - 'initial_altitude': (50., 'ft'), - 'final_altitude': (985., 'ft'), - 'polynomial_control_order': 1, - 'throttle_enforcement': 'boundary_constraint', - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'constraints': { - 'altitude': { - 'equals': 985., - 'loc': 'final', - 'units': 'ft', - 'type': 'boundary', - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(4.e3, 10.e3), 'ft'], - 'time': [(35., 60.), 's'], - 'mass': [(174.82e3, 174.8e3), 'lbm'], - }, - }, - 'P2_to_DE': { - 'user_options': { - 'num_segments': 4, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((1.e3, 20.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((3.e3, 20.e3), 'ft'), - 'mach_bounds': ((0.22, 0.3), 'unitless'), - 'altitude_bounds': ((985., 1100.), 'ft'), - 'initial_mach': (0.22, 'unitless'), - 'final_mach': (0.3, 'unitless'), - 'initial_altitude': (985., 'ft'), - 'final_altitude': (1100., 'ft'), - 'polynomial_control_order': 1, - 'throttle_enforcement': 'path_constraint', - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'constraints': { - 'distance': { - 'upper': 19.e3, - 'ref': 20.e3, - 'loc': 'final', - 'units': 'ft', - 'type': 'boundary', - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(10.e3, 14.e3), 'ft'], - 'time': [(60., 80.), 's'], - 'mass': [(174.8e3, 174.5e3), 'lbm'], - }, - }, - 'DE': { - 'user_options': { - 'num_segments': 3, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((500., 30.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((50., 5000.), 'ft'), - 'mach_bounds': ((0.24, 0.32), 'unitless'), - 'altitude_bounds': ((985., 1.5e3), 'ft'), - 'initial_mach': (0.3, 'unitless'), - 'final_mach': (0.3, 'unitless'), - 'initial_altitude': (1100., 'ft'), - 'final_altitude': (1200., 'ft'), - 'polynomial_control_order': 2, - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'throttle_enforcement': 'path_constraint', - 'constraints': { - 'flight_path_angle': { - 'equals': 4., - 'loc': 'final', - 'units': 'deg', - 'type': 'boundary', - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(18.e3, 2.e3), 'ft'], - 'mass': [(174.5e3, 174.4e3), 'lbm'], - 'time': [(80., 85.), 's'], - }, - }, - 'EF_to_P1': { - 'user_options': { - 'num_segments': 3, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((500., 50.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((1.e3, 20.e3), 'ft'), - 'mach_bounds': ((0.24, 0.32), 'unitless'), - 'altitude_bounds': ((1.1e3, 1.2e3), 'ft'), - 'initial_mach': (0.3, 'unitless'), - 'final_mach': (0.3, 'unitless'), - 'initial_altitude': (1100., 'ft'), - 'final_altitude': (1200., 'ft'), - 'polynomial_control_order': 1, - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'throttle_enforcement': 'bounded', - 'constraints': { - 'distance': { - 'equals': 21325., - 'units': 'ft', - 'type': 'boundary', - 'loc': 'final', - 'ref': 30.e3, - }, - 'flight_path_angle': { - 'equals': 4., - 'loc': 'final', - 'units': 'deg', - 'type': 'boundary', - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(20.e3, 1325.), 'ft'], - 'mass': [(174.4e3, 174.3e3), 'lbm'], - 'time': [(85., 90.), 's'], - }, - }, - 'EF_past_P1': { - 'user_options': { - 'num_segments': 5, - 'order': 3, - 'fix_initial': False, - 'ground_roll': False, - 'clean': False, - 'initial_ref': (1.e3, 'ft'), - 'initial_bounds': ((20.e3, 50.e3), 'ft'), - 'duration_ref': (1.e3, 'ft'), - 'duration_bounds': ((100., 50.e3), 'ft'), - 'mach_bounds': ((0.24, 0.32), 'unitless'), - 'altitude_bounds': ((1.e3, 3.e3), 'ft'), - 'initial_mach': (0.3, 'unitless'), - 'final_mach': (0.3, 'unitless'), - 'initial_altitude': (1200., 'ft'), - 'final_altitude': (2000., 'ft'), - 'polynomial_control_order': 1, - 'optimize_mach': optimize_mach, - 'optimize_altitude': optimize_altitude, - 'throttle_enforcement': 'boundary_constraint', - 'constraints': { - 'flight_path_angle': { - 'equals': 4., - 'loc': 'final', - 'units': 'deg', - 'type': 'boundary', - }, - 'distance': { - 'equals': 30.e3, - 'units': 'ft', - 'type': 'boundary', - 'loc': 'final', - 'ref': 30.e3, - }, - }, - }, - 'subsystem_options': subsystem_options, - 'initial_guesses': { - 'distance': [(21325., 50.e3), 'ft'], - 'mass': [(174.3e3, 174.2e3), 'lbm'], - 'time': [(90., 180.), 's'], - }, - }, - "post_mission": { - "include_landing": False, - "constrain_range": False, - }, -} - -if __name__ == '__main__': - prob = av.AviaryProblem() - - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs( - 'models/test_aircraft/aircraft_for_bench_solved2dof.csv', phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver(optimizer, max_iter=25) - - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective('mass') - - prob.setup() - - prob.set_initial_guesses() - - prob.run_aviary_problem(record_filename='detailed_takeoff.db') - - cr = om.CaseReader('detailed_takeoff.db') - cases = cr.get_cases('problem') - case = cases[0] - - output_data = {} - - for (point_name, phase_name) in [['P1', 'EF_to_P1'], ['P2', 'CD_to_P2']]: - output_data[point_name] = {} - output_data[point_name]['thrust_fraction'] = case.get_val(f'traj.{phase_name}.rhs_all.thrust_net', units='N')[ - -1][0] / case.get_val(f'traj.{phase_name}.rhs_all.thrust_net_max', units='N')[-1][0] - output_data[point_name]['true_airspeed'] = case.get_val( - f'traj.{phase_name}.timeseries.velocity', units='kn')[-1][0] - output_data[point_name]['angle_of_attack'] = case.get_val( - f'traj.{phase_name}.timeseries.alpha', units='deg')[-1][0] - output_data[point_name]['flight_path_angle'] = case.get_val( - f'traj.{phase_name}.timeseries.flight_path_angle', units='deg')[-1][0] - output_data[point_name]['altitude'] = case.get_val( - f'traj.{phase_name}.timeseries.altitude', units='ft')[-1][0] - output_data[point_name]['distance'] = case.get_val( - f'traj.{phase_name}.timeseries.distance', units='ft')[-1][0] - - print(output_data) diff --git a/aviary/examples/run_level1_example.py b/aviary/examples/run_level1_example.py new file mode 100644 index 0000000000..ae1cd57aaf --- /dev/null +++ b/aviary/examples/run_level1_example.py @@ -0,0 +1,21 @@ +""" +This is a basic example of running a coupled aircraft design-mission optimization in Aviary using +the "level 1" API. + +The properties of the aircraft are defined in a pre-existing ".csv" file - in this case it describes +a conventional single-aisle commercial transport. The mission is defined using a "phase_info" file, +which consists of a climb, cruise, and descent phase. + +The aircraft sizing problem is ran by calling the `run_aviary` function, which takes in the path to +the aircraft model, the phase info, and some other optional settings. This performs a coupled +design-mission optimization. +""" + +import aviary.api as av + +prob = av.run_aviary( + aircraft_data='models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', + phase_info='models/missions/height_energy_default.py', + optimizer='SLSQP', + make_plots=True, +) diff --git a/aviary/examples/run_level2_example.py b/aviary/examples/run_level2_example.py new file mode 100644 index 0000000000..f6ea8d44b2 --- /dev/null +++ b/aviary/examples/run_level2_example.py @@ -0,0 +1,39 @@ +""" +This is an example of running a coupled aircraft design-mission optimization in Aviary using the +"level 2" API. It runs the same aircraft and mission as the `level1_example.py` script, but it uses +the AviaryProblem class to set up the problem. This exposes more options and flexibility to the user. + +The same ".csv" file is used to define the aircraft, but now the phase_info dictionary is directly +imported from the file and passed as an argument. It is common for level 2 scripts to modify +existing phase_info, but here it is used as-is here to match the level 1 example. + +We then call the correct methods in order to set up and run an Aviary optimization problem. Most +methods have optional arguments, but none are necessary here. The selection of the SLSQP optimizer +limited to 50 iterations are included to demonstrate of how those common settings are set. +""" + +from aviary.models.missions.height_energy_default import phase_info + +import aviary.api as av + +prob = av.AviaryProblem() + +# Load aircraft and options data from provided sources +prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', phase_info +) + +prob.check_and_preprocess_inputs() + +prob.build_model() + +# optimizer and iteration limit are optional provided here +prob.add_driver('SLSQP', max_iter=50) + +prob.add_design_variables() + +prob.add_objective() + +prob.setup() + +prob.run_aviary_problem() diff --git a/aviary/examples/run_level2_with_detailed_landing.py b/aviary/examples/run_level2_with_detailed_landing.py new file mode 100644 index 0000000000..2513114730 --- /dev/null +++ b/aviary/examples/run_level2_with_detailed_landing.py @@ -0,0 +1,206 @@ +import openmdao.api as om + +import aviary.api as av + +# fmt: off +subsystem_options = { + 'core_aerodynamics': { + 'method': 'low_speed', + 'ground_altitude': 0.0, # units='ft' + 'angles_of_attack': [ + -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, + ], # units='deg' + 'lift_coefficients': [ + 0.01, 0.1, 0.2, 0.3, 0.4, 0.5178, 0.6, 0.75, 0.85, 0.95, 1.05, + 1.15, 1.25, 1.35, 1.5, 1.6, 1.7, 1.8, 1.85, 1.9, 1.95, + ], + 'drag_coefficients': [ + 0.04, 0.02, 0.01, 0.02, 0.04, 0.0674, 0.065, 0.065, 0.07, 0.072, + 0.076, 0.084, 0.09, 0.10, 0.11, 0.12, 0.13, 0.15, 0.16, 0.18, 0.20, + ], + 'lift_coefficient_factor': 2.0, + 'drag_coefficient_factor': 2.0, + } +} +# fmt: on + +subsystem_options_landing = subsystem_options.copy() +subsystem_options_landing['core_aerodynamics']['drag_coefficient_factor'] = 3.0 + +mach_optimize = False +altitude_optimize = False + +phase_info = { + 'pre_mission': {'include_takeoff': False, 'optimize_mass': False}, + 'GH': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'ground_roll': False, + 'clean': False, + 'time_initial': (0.0, 'ft'), + 'time_duration_ref': (2750.0, 'ft'), + 'time_duration_bounds': ((500.0, 5.0e3), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_bounds': ((0.1, 0.5), 'unitless'), + 'mach_initial': (0.15, 'unitless'), + 'mach_final': (0.15, 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 1, + 'altitude_initial': (500.0, 'ft'), + 'altitude_final': (394.0, 'ft'), + 'altitude_bounds': ((0.0, 1000.0), 'ft'), + 'mass_initial': (120.0e3, 'lbm'), + 'throttle_enforcement': 'bounded', + 'rotation': False, + 'constraints': { + 'flight_path_angle': { + 'equals': -3.0, + 'loc': 'initial', + 'units': 'deg', + 'type': 'boundary', + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(0.0e3, 2.0e3), 'ft'], + 'time': [(0.0, 12.0), 's'], + 'mass': [(120.0e3, 119.8e3), 'lbm'], + }, + }, + 'HI': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'ground_roll': False, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((0.0, 16.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((500.0, 15.0e3), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_initial': (0.15, 'unitless'), + 'mach_final': (0.15, 'unitless'), + 'mach_bounds': ((0.1, 0.5), 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 1, + 'altitude_initial': (394.0, 'ft'), + 'altitude_final': (50.0, 'ft'), + 'altitude_bounds': ((0.0, 1000.0), 'ft'), + 'throttle_enforcement': 'bounded', + 'rotation': False, + 'constraints': { + 'flight_path_angle': { + 'equals': -3.0, + 'loc': 'final', + 'units': 'deg', + 'type': 'boundary', + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(2.0e3, 6.5e3), 'ft'], + 'time': [(12.0, 50.0), 's'], + 'mass': [(119.8e3, 119.7e3), 'lbm'], + }, + }, + 'IJ': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'ground_roll': False, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((0.0, 30.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((500.0, 15.0e3), 'ft'), + 'mach_optimize': False, + 'mach_polynomial_order': 2, + 'mach_bounds': ((0.1, 0.5), 'unitless'), + 'mach_initial': (0.15, 'unitless'), + 'mach_final': (0.15, 'unitless'), + 'altitude_optimize': True, + 'altitude_polynomial_order': 2, + #'altitude_initial': (50.0, 'ft'), + #'altitude_final': (0.0, 'ft'), + 'altitude_bounds': ((0.0, 1000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'rotation': False, + 'constraints': {}, + }, + 'subsystem_options': subsystem_options_landing, + 'initial_guesses': { + 'altitude': [(50.0, 0.0), 'ft'], + 'distance': [(8.5e3, 2.0e3), 'ft'], + 'time': [(50.0, 60.0), 's'], + 'mass': [(119.7e3, 119.67e3), 'lbm'], + }, + }, + 'post_mission': { + 'include_landing': False, + 'constrain_range': False, + }, +} + +prob = av.AviaryProblem() + +# Load aircraft and options data from user +# Allow for user overrides here +prob.load_inputs('models/aircraft/test_aircraft/aircraft_for_bench_solved2dof.csv', phase_info) + +prob.check_and_preprocess_inputs() + +prob.build_model() + +prob.add_driver('SLSQP', max_iter=100) + +prob.add_design_variables() + +# Load optimization problem formulation +# Detail which variables the optimizer can control +prob.add_objective('mass') + +prob.setup() + +prob.run_aviary_problem() + +try: + loc = prob.get_outputs_dir() + cr = om.CaseReader(f'{loc}/problem_history.db') +except: + cr = om.CaseReader('problem_history.db') + +cases = cr.get_cases('problem') +case = cases[0] + +output_data = {} + +point_name = 'P3' +phase_name = 'GH' +output_data[point_name] = {} +output_data[point_name]['thrust_fraction'] = ( + case.get_val(f'traj.{phase_name}.rhs_all.thrust_net', units='N')[-1][0] + / case.get_val(f'traj.{phase_name}.rhs_all.thrust_net_max', units='N')[-1][0] +) +output_data[point_name]['true_airspeed'] = case.get_val( + f'traj.{phase_name}.timeseries.velocity', units='kn' +)[-1][0] +output_data[point_name]['angle_of_attack'] = case.get_val( + f'traj.{phase_name}.timeseries.angle_of_attack', units='deg' +)[-1][0] +output_data[point_name]['flight_path_angle'] = case.get_val( + f'traj.{phase_name}.timeseries.flight_path_angle', units='deg' +)[-1][0] +output_data[point_name]['altitude'] = case.get_val( + f'traj.{phase_name}.timeseries.altitude', units='ft' +)[-1][0] +output_data[point_name]['distance'] = case.get_val( + f'traj.{phase_name}.timeseries.distance', units='ft' +)[-1][0] + +print(output_data) diff --git a/aviary/examples/run_level2_with_detailed_takeoff.py b/aviary/examples/run_level2_with_detailed_takeoff.py new file mode 100644 index 0000000000..679f6beb00 --- /dev/null +++ b/aviary/examples/run_level2_with_detailed_takeoff.py @@ -0,0 +1,365 @@ +import openmdao.api as om + +import aviary.api as av + +# fmt: off +subsystem_options = { + 'core_aerodynamics': { + 'method': 'low_speed', + 'ground_altitude': 0.0, # units='ft' + 'angles_of_attack': [ + -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, + 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, + ], # units='deg' + 'lift_coefficients': [ + 0.01, 0.1, 0.2, 0.3, 0.4, 0.5178, 0.6, 0.75, 0.85, 0.95, + 1.05, 1.15, 1.25, 1.35, 1.5, 1.6, 1.7, 1.8, 1.85, 1.9, 1.95, + ], + 'drag_coefficients': [ + 0.04, 0.02, 0.01, 0.02, 0.04, 0.0674, 0.065, 0.065, 0.07, 0.072, + 0.076, 0.084, 0.09, 0.10, 0.11, 0.12, 0.13, 0.15, 0.16, 0.18, 0.20, + ], + 'lift_coefficient_factor': 1.0, + 'drag_coefficient_factor': 1.0, + } +} +# fmt: on + +mach_optimize = True +altitude_optimize = True +optimizer = 'SLSQP' + +phase_info = { + 'pre_mission': {'include_takeoff': False, 'optimize_mass': False}, + 'AB': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'ground_roll': True, + 'time_duration_ref': (100.0, 'kn'), + 'time_duration_bounds': ((100.0, 500.0), 'kn'), + 'time_initial': (0.0, 'kn'), + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(0.0, 2.0e3), 'ft'], + 'time': [(0.0, 20.0), 's'], + 'velocity': [(1.0, 120.0), 'kn'], + 'mass': [(175.0e3, 174.85e3), 'lbm'], + }, + }, + 'rotate': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'ground_roll': True, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((1.0e3, 3.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((200.0, 2.0e3), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'rotation': True, + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_bounds': ((0.18, 0.2), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (0.0, 'ft'), + 'altitude_final': (0.0, 'ft'), + 'constraints': { + 'normal_force': { + 'equals': 0.0, + 'loc': 'final', + 'units': 'lbf', + 'type': 'boundary', + 'ref': 10.0e5, + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(2.0e3, 1.0e3), 'ft'], + 'time': [(20.0, 25.0), 's'], + 'mach': [(0.18, 0.2), 'unitless'], + 'mass': [(174.85e3, 174.84e3), 'lbm'], + 'angle_of_attack': [(0.0, 12.0), 'deg'], + }, + }, + 'BC': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((1.0, 16.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((500.0, 1500.0), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_bounds': ((0.2, 0.22), 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 1, + 'altitude_bounds': ((0.0, 250.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'rotation': False, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(3.0e3, 1.0e3), 'ft'], + 'time': [(25.0, 35.0), 's'], + 'mach': [(0.2, 0.22), 'unitless'], + 'altitude': [(0.0, 50.0), 'ft'], + 'mass': [(174.84e3, 174.82e3), 'lbm'], + }, + }, + 'CD_to_P2': { + 'user_options': { + 'num_segments': 4, + 'order': 3, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((1.0e3, 20.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((3.0e3, 20.0e3), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_bounds': ((0.22, 0.3), 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 1, + 'altitude_initial': (50.0, 'ft'), + 'altitude_final': (985.0, 'ft'), + 'altitude_bounds': ((0.0, 985.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'constraints': { + 'altitude': { + 'equals': 985.0, + 'loc': 'final', + 'units': 'ft', + 'type': 'boundary', + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(4.0e3, 10.0e3), 'ft'], + 'time': [(35.0, 60.0), 's'], + 'mach': [(0.22, 0.3), 'unitless'], + 'mass': [(174.82e3, 174.8e3), 'lbm'], + }, + }, + 'P2_to_DE': { + 'user_options': { + 'num_segments': 4, + 'order': 3, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((1.0e3, 20.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((3.0e3, 20.0e3), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_bounds': ((0.22, 0.3), 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 1, + 'altitude_bounds': ((985.0, 1100.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'constraints': { + 'distance': { + 'upper': 19.0e3, + 'ref': 20.0e3, + 'loc': 'final', + 'units': 'ft', + 'type': 'boundary', + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(10.0e3, 14.0e3), 'ft'], + 'time': [(60.0, 80.0), 's'], + 'mach': [(0.22, 0.3), 'unitless'], + 'altitude': [(985.0, 1100.0), 'ft'], + 'mass': [(174.8e3, 174.5e3), 'lbm'], + }, + }, + 'DE': { + 'user_options': { + 'num_segments': 3, + 'order': 3, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((500.0, 30.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((50.0, 5000.0), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 2, + 'mach_bounds': ((0.24, 0.32), 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 2, + 'altitude_bounds': ((985.0, 1.5e3), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'constraints': { + 'flight_path_angle': { + 'equals': 4.0, + 'loc': 'final', + 'units': 'deg', + 'type': 'boundary', + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(18.0e3, 2.0e3), 'ft'], + 'mass': [(174.5e3, 174.4e3), 'lbm'], + 'mach': [(0.3, 0.3), 'unitless'], + 'altitude': [(1100.0, 1200.0), 'ft'], + 'time': [(80.0, 85.0), 's'], + }, + }, + 'EF_to_P1': { + 'user_options': { + 'num_segments': 3, + 'order': 3, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((500.0, 50.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((1.0e3, 20.0e3), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_bounds': ((0.24, 0.32), 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 1, + 'altitude_bounds': ((1.1e3, 1.2e3), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'constraints': { + 'distance': { + 'equals': 21325.0, + 'units': 'ft', + 'type': 'boundary', + 'loc': 'final', + 'ref': 30.0e3, + }, + 'flight_path_angle': { + 'equals': 4.0, + 'loc': 'final', + 'units': 'deg', + 'type': 'boundary', + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(20.0e3, 1325.0), 'ft'], + 'mass': [(174.4e3, 174.3e3), 'lbm'], + 'mach': [(0.3, 0.3), 'unitless'], + 'altitude': [(1100.0, 1200.0), 'ft'], + 'time': [(85.0, 90.0), 's'], + }, + }, + 'EF_past_P1': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'clean': False, + 'time_initial_ref': (1.0e3, 'ft'), + 'time_initial_bounds': ((20.0e3, 50.0e3), 'ft'), + 'time_duration_ref': (1.0e3, 'ft'), + 'time_duration_bounds': ((100.0, 50.0e3), 'ft'), + 'mach_optimize': mach_optimize, + 'mach_polynomial_order': 1, + 'mach_bounds': ((0.24, 0.32), 'unitless'), + 'altitude_optimize': altitude_optimize, + 'altitude_polynomial_order': 1, + 'altitude_bounds': ((1.0e3, 3.0e3), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'constraints': { + 'flight_path_angle': { + 'equals': 4.0, + 'loc': 'final', + 'units': 'deg', + 'type': 'boundary', + }, + 'distance': { + 'equals': 30.0e3, + 'units': 'ft', + 'type': 'boundary', + 'loc': 'final', + 'ref': 30.0e3, + }, + }, + }, + 'subsystem_options': subsystem_options, + 'initial_guesses': { + 'distance': [(21325.0, 50.0e3), 'ft'], + 'mass': [(174.3e3, 174.2e3), 'lbm'], + 'mach': [(0.3, 0.3), 'unitless'], + 'altitude': [(1200.0, 2000.0), 'ft'], + 'time': [(90.0, 180.0), 's'], + }, + }, + 'post_mission': { + 'include_landing': False, + 'constrain_range': False, + }, +} + + +if __name__ == '__main__': + prob = av.AviaryProblem() + + # Load aircraft and options data from user + # Allow for user overrides here + prob.load_inputs('models/aircraft/test_aircraft/aircraft_for_bench_solved2dof.csv', phase_info) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.add_driver(optimizer, max_iter=25) + + prob.add_design_variables() + + # Load optimization problem formulation + # Detail which variables the optimizer can control + prob.add_objective('mass') + + prob.setup() + + prob.run_aviary_problem(suppress_solver_print=True) + + try: + loc = prob.get_outputs_dir() + cr = om.CaseReader(f'{loc}/problem_history.db') + except: + cr = om.CaseReader('problem_history.db') + + cases = cr.get_cases('problem') + case = cases[0] + + output_data = {} + + for point_name, phase_name in [['P1', 'EF_to_P1'], ['P2', 'CD_to_P2']]: + output_data[point_name] = {} + output_data[point_name]['thrust_fraction'] = ( + case.get_val(f'traj.{phase_name}.rhs_all.thrust_net', units='N')[-1][0] + / case.get_val(f'traj.{phase_name}.rhs_all.thrust_net_max', units='N')[-1][0] + ) + output_data[point_name]['true_airspeed'] = case.get_val( + f'traj.{phase_name}.timeseries.velocity', units='kn' + )[-1][0] + output_data[point_name]['angle_of_attack'] = case.get_val( + f'traj.{phase_name}.timeseries.angle_of_attack', units='deg' + )[-1][0] + output_data[point_name]['flight_path_angle'] = case.get_val( + f'traj.{phase_name}.timeseries.flight_path_angle', units='deg' + )[-1][0] + output_data[point_name]['altitude'] = case.get_val( + f'traj.{phase_name}.timeseries.altitude', units='ft' + )[-1][0] + output_data[point_name]['distance'] = case.get_val( + f'traj.{phase_name}.timeseries.distance', units='ft' + )[-1][0] + + print(output_data) diff --git a/aviary/examples/run_level3_example.py b/aviary/examples/run_level3_example.py new file mode 100644 index 0000000000..77f6c93e27 --- /dev/null +++ b/aviary/examples/run_level3_example.py @@ -0,0 +1,523 @@ +import warnings + +import dymos as dm +import openmdao.api as om + +import aviary.api as av +from aviary.core.pre_mission_group import PreMissionGroup +from aviary.mission.flops_based.phases.energy_phase import EnergyPhase +from aviary.models.missions.height_energy_default import phase_info +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import setup_model_options, setup_trajectory_params +from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Aircraft, Dynamic, Mission + + +class L3SubsystemsGroup(om.Group): + """Group that contains all pre-mission groups of core Aviary subsystems (geometry, mass, propulsion, aerodynamics).""" + + def initialize(self): + self.options.declare( + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) + self.code_origin_overrides = [] + + +prob = av.AviaryProblem() + +##### +# prob.load_inputs(csv_path, phase_info) +csv_path = 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv' + +aviary_inputs, _ = av.create_vehicle(csv_path) + +engine = av.build_engine_deck(aviary_inputs) + +prob.model.mission_info = {} +for phase_name in phase_info: + if phase_name not in ['pre_mission', 'post_mission']: + prob.model.mission_info[phase_name] = phase_info[phase_name] +aviary_inputs.set_val(Mission.Summary.RANGE, 1906.0, units='NM') +prob.require_range_residual = True +prob.target_range = 1906.0 + +##### +# prob.check_and_preprocess_inputs() +av.preprocess_options(aviary_inputs, engine_models=[engine]) + +##### +# prob.add_pre_mission_systems() +aerodynamics = av.CoreAerodynamicsBuilder(code_origin=av.LegacyCode('FLOPS')) +geometry = av.CoreGeometryBuilder(code_origin=av.LegacyCode('FLOPS')) +mass = av.CoreMassBuilder(code_origin=av.LegacyCode('FLOPS')) +propulsion = av.CorePropulsionBuilder(engine_models=engine) + +prob.model.core_subsystems = { + 'propulsion': propulsion, + 'geometry': geometry, + 'mass': mass, + 'aerodynamics': aerodynamics, +} +prob.meta_data = BaseMetaData.copy() + +##### +# prob.add_pre_mission_systems() +# overwrites calculated values in pre-mission with override values from .csv +prob.model.add_subsystem( + 'pre_mission', + PreMissionGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], + promotes_outputs=['aircraft:*', 'mission:*'], +) + +##### +# This is a combination of prob.add_pre_mission_systems and prob.setup() +# In the aviary code add_pre_mission_systems only instantiates the objects and methods, the build method is called in prob.setup() +prob.model.pre_mission.add_subsystem( + 'core_propulsion', + propulsion.build_pre_mission(aviary_inputs), +) + +# adding another group subsystem to match the L2 example +prob.model.pre_mission.add_subsystem( + 'core_subsystems', + L3SubsystemsGroup(aviary_options=aviary_inputs), + promotes_inputs=['*'], + promotes_outputs=['*'], +) +prob.model.pre_mission.core_subsystems.add_subsystem( + 'core_geometry', + geometry.build_pre_mission(aviary_inputs), + promotes_inputs=['*'], + promotes_outputs=['*'], +) +prob.model.pre_mission.core_subsystems.add_subsystem( + 'core_aerodynamics', + aerodynamics.build_pre_mission(aviary_inputs), + promotes_inputs=['*'], + promotes_outputs=['*'], +) +prob.model.pre_mission.core_subsystems.add_subsystem( + 'core_mass', + mass.build_pre_mission(aviary_inputs), + promotes_inputs=['*'], + promotes_outputs=['*'], +) + +##### +# prob.add_phases() +phases = ['climb', 'cruise', 'descent'] +prob.traj = prob.model.add_subsystem('traj', dm.Trajectory()) +default_mission_subsystems = [ + prob.model.core_subsystems['aerodynamics'], + prob.model.core_subsystems['propulsion'], +] +for phase_idx, phase_name in enumerate(phases): + base_phase_options = prob.model.mission_info[phase_name] + phase_options = {} + for key, val in base_phase_options.items(): + phase_options[key] = val + phase_options['user_options'] = {} + for key, val in base_phase_options['user_options'].items(): + phase_options['user_options'][key] = val + phase_builder = EnergyPhase + phase_object = phase_builder.from_phase_info( + phase_name, phase_options, default_mission_subsystems, meta_data=prob.meta_data + ) + phase = phase_object.build_phase(aviary_options=aviary_inputs) + prob.traj.add_phase(phase_name, phase) + +externs = {'climb': {}, 'cruise': {}, 'descent': {}} +for default_subsys in default_mission_subsystems: + params = default_subsys.get_parameters(aviary_inputs=aviary_inputs, phase_info={}) + for key, val in params.items(): + for phname in externs: + externs[phname][key] = val + +prob.traj = setup_trajectory_params( + prob.model, prob.traj, aviary_inputs, external_parameters=externs +) + +# need aviary inputs assigned to the problem object for other functions below +# this maybe needs a better location in this script. +prob.aviary_inputs = aviary_inputs + +##### +# prob.add_post_mission_systems() +prob.model.add_subsystem( + 'post_mission', + om.Group(), + promotes_inputs=['*'], + promotes_outputs=['*'], +) + +prob.traj._phases['climb'].set_state_options( + Dynamic.Vehicle.MASS, fix_initial=False, input_initial=False +) + +prob.traj._phases['climb'].set_state_options( + Dynamic.Mission.DISTANCE, fix_initial=True, input_initial=False +) + +prob.traj._phases['climb'].set_time_options( + fix_initial=False, + initial_bounds=(0, 0), + initial_ref=600, + duration_bounds=(3840, 11520), + duration_ref=7680.0, +) + +prob.traj._phases['cruise'].set_time_options( + duration_bounds=(3390, 10170), + duration_ref=6780.0, +) + +prob.traj._phases['descent'].set_time_options( + duration_bounds=(1740, 5220), + duration_ref=3480.0, +) + +eq = prob.model.add_subsystem( + f'link_climb_mass', + om.EQConstraintComp(), + promotes_inputs=[('rhs:mass', Mission.Summary.GROSS_MASS)], +) + +eq.add_eq_output('mass', eq_units='lbm', normalize=False, ref=100000.0, add_constraint=True) + +prob.model.connect( + f'traj.climb.states:mass', + f'link_climb_mass.lhs:mass', + src_indices=[0], + flat_src_indices=True, +) + +prob.model.add_subsystem( + 'range_constraint', + om.ExecComp( + 'range_resid = target_range - actual_range', + target_range={'val': prob.target_range, 'units': 'NM'}, + actual_range={'val': prob.target_range, 'units': 'NM'}, + range_resid={'val': 30, 'units': 'NM'}, + ), + promotes_inputs=[ + ('actual_range', Mission.Summary.RANGE), + 'target_range', + ], + promotes_outputs=[('range_resid', Mission.Constraints.RANGE_RESIDUAL)], +) + +prob.model.add_constraint(Mission.Constraints.MASS_RESIDUAL, equals=0.0, ref=1.0e5) +# for reference this is the end of builder.add_post_mission_systems() + +ecomp = om.ExecComp( + 'fuel_burned = initial_mass - mass_final', + initial_mass={'units': 'lbm'}, + mass_final={'units': 'lbm'}, + fuel_burned={'units': 'lbm'}, +) + +prob.model.post_mission.add_subsystem( + 'fuel_burned', + ecomp, + promotes=[('fuel_burned', Mission.Summary.FUEL_BURNED)], +) + +prob.model.connect( + f'traj.climb.timeseries.mass', + 'fuel_burned.initial_mass', + src_indices=[0], +) + +prob.model.connect( + f'traj.descent.timeseries.mass', + 'fuel_burned.mass_final', + src_indices=[-1], +) + +RESERVE_FUEL_ADDITIONAL = prob.aviary_inputs.get_val( + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm' +) + +reserve_fuel = om.ExecComp( + 'reserve_fuel = reserve_fuel_frac_mass + reserve_fuel_additional + reserve_fuel_burned', + reserve_fuel={'units': 'lbm', 'shape': 1}, + reserve_fuel_frac_mass={'units': 'lbm', 'val': 0}, + reserve_fuel_additional={'units': 'lbm', 'val': RESERVE_FUEL_ADDITIONAL}, + reserve_fuel_burned={'units': 'lbm', 'val': 0}, +) +prob.model.post_mission.add_subsystem( + 'reserve_fuel', + reserve_fuel, + promotes_inputs=[ + 'reserve_fuel_frac_mass', + ('reserve_fuel_additional', Aircraft.Design.RESERVE_FUEL_ADDITIONAL), + ('reserve_fuel_burned', Mission.Summary.RESERVE_FUEL_BURNED), + ], + promotes_outputs=[('reserve_fuel', Mission.Design.RESERVE_FUEL)], +) + +ecomp = om.ExecComp( + 'overall_fuel = (1 + fuel_margin/100)*fuel_burned + reserve_fuel', + overall_fuel={'units': 'lbm', 'shape': 1}, + fuel_margin={'units': 'unitless', 'val': 0}, + fuel_burned={'units': 'lbm'}, # from regular_phases only + reserve_fuel={'units': 'lbm', 'shape': 1}, +) +prob.model.post_mission.add_subsystem( + 'fuel_calc', + ecomp, + promotes_inputs=[ + ('fuel_margin', Aircraft.Fuel.FUEL_MARGIN), + ('fuel_burned', Mission.Summary.FUEL_BURNED), + ('reserve_fuel', Mission.Design.RESERVE_FUEL), + ], + promotes_outputs=[('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS)], +) + +# If target distances have been set per phase then there is a block of code to add here. +# In this case individual phases don't have target distances. + +ecomp = om.ExecComp( + 'mass_resid = operating_empty_mass + overall_fuel + payload_mass - initial_mass', + operating_empty_mass={'units': 'lbm'}, + overall_fuel={'units': 'lbm'}, + payload_mass={'units': 'lbm'}, + initial_mass={'units': 'lbm'}, + mass_resid={'units': 'lbm'}, +) + +# this seems clunky - we could just move this directly into the promotes inputs block? +payload_mass_src = Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS + +prob.model.post_mission.add_subsystem( + 'mass_constraint', + ecomp, + promotes_inputs=[ + ('operating_empty_mass', Mission.Summary.OPERATING_MASS), + ('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS), + ('payload_mass', payload_mass_src), + ('initial_mass', Mission.Summary.GROSS_MASS), + ], + promotes_outputs=[('mass_resid', Mission.Constraints.MASS_RESIDUAL)], +) + +ecomp = om.ExecComp( + 'excess_fuel_capacity = total_fuel_capacity - unusable_fuel - overall_fuel', + total_fuel_capacity={'units': 'lbm'}, + unusable_fuel={'units': 'lbm'}, + overall_fuel={'units': 'lbm'}, + excess_fuel_capacity={'units': 'lbm'}, +) + +prob.model.post_mission.add_subsystem( + 'excess_fuel_constraint', + ecomp, + promotes_inputs=[ + ('total_fuel_capacity', Aircraft.Fuel.TOTAL_CAPACITY), + ('unusable_fuel', Aircraft.Fuel.UNUSABLE_FUEL_MASS), + ('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS), + ], + promotes_outputs=[('excess_fuel_capacity', Mission.Constraints.EXCESS_FUEL_CAPACITY)], +) + +prob.model.add_constraint(Mission.Constraints.EXCESS_FUEL_CAPACITY, lower=0, units='lbm') + +##### +# prob.link_phases() + +all_subsystems = [] +all_subsystems.append(prob.model.core_subsystems['propulsion']) + +phases = list(prob.model.mission_info.keys()) +prob.traj.link_phases(phases, ['time'], ref=None, connected=True) +prob.traj.link_phases(phases, [Dynamic.Vehicle.MASS], ref=None, connected=True) +prob.traj.link_phases(phases, [Dynamic.Mission.DISTANCE], ref=None, connected=True) + +prob.model.connect( + f'traj.descent.timeseries.distance', + Mission.Summary.RANGE, + src_indices=[-1], + flat_src_indices=True, +) +#### End of link_phases + +##### +# prob.add_driver('SLSQP', max_iter=50) +# SLSQP Optimizer Settings +prob.driver = om.ScipyOptimizeDriver() +prob.driver.options['optimizer'] = 'SLSQP' +prob.driver.declare_coloring(show_summary=False) +prob.driver.options['disp'] = True +prob.driver.options['tol'] = 1e-9 +prob.driver.options['maxiter'] = 50 + +# IPOPT Optimizer Settings +# prob.driver.opt_settings['print_user_options'] = 'no' +# prob.driver.opt_settings['print_frequency_iter'] = 10 +# prob.driver.opt_settings['print_level'] = 3 +# prob.driver.opt_settings['tol'] = 1.0e-6 +# prob.driver.opt_settings['mu_init'] = 1e-5 +# prob.driver.opt_settings['max_iter'] = 50 +# prob.driver.opt_settings['nlp_scaling_method'] = 'gradient-based' +# prob.driver.opt_settings['alpha_for_y'] = 'safer-min-dual-infeas' +# prob.driver.opt_settings['mu_strategy'] = 'monotone' +# prob.driver.options['print_results'] = 'minimal' +# prob.driver.opt_settings['iSumm'] = 6 +# prob.driver.opt_settings['iPrint'] = 0 + +# SNOPT Optimizer Settings # +# prob.driver.opt_settings['Major iterations limit'] = 50 +# prob.driver.opt_settings['Major optimality tolerance'] = 1e-4 +# prob.driver.opt_settings['Major feasibility tolerance'] = 1e-7 +# prob.driver.opt_settings['iSumm'] = 6 +# prob.driver.opt_settings['iPrint'] = 0 + +##### +# prob.add_design_variables() +prob.model.add_design_var( + Mission.Design.GROSS_MASS, + lower=100000.0, + upper=None, + units='lbm', + ref=175e3, +) +prob.model.add_design_var( + Mission.Summary.GROSS_MASS, + lower=100000.0, + upper=None, + units='lbm', + ref=175e3, +) + +prob.model.add_subsystem( + 'gtow_constraint', + om.EQConstraintComp( + 'GTOW', + eq_units='lbm', + normalize=True, + add_constraint=True, + ), + promotes_inputs=[ + ('lhs:GTOW', Mission.Design.GROSS_MASS), + ('rhs:GTOW', Mission.Summary.GROSS_MASS), + ], +) +prob.model.add_constraint(Mission.Constraints.RANGE_RESIDUAL, equals=0, ref=10) + +##### +# prob.add_objective() +prob.model.add_subsystem( + 'fuel_obj', + om.ExecComp( + 'reg_objective = overall_fuel/10000 + ascent_duration/30.', + reg_objective={'val': 0.0, 'units': 'unitless'}, + ascent_duration={'units': 's', 'shape': 1}, + overall_fuel={'units': 'lbm'}, + ), + promotes_inputs=[ + ('ascent_duration', Mission.Takeoff.ASCENT_DURATION), + ('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS), + ], + promotes_outputs=[('reg_objective', Mission.Objectives.FUEL)], +) +prob.model.add_objective(Mission.Objectives.FUEL, ref=1) + +prob.model.add_subsystem( + 'range_obj', + om.ExecComp( + 'reg_objective = -actual_range/1000 + ascent_duration/30.', + reg_objective={'val': 0.0, 'units': 'unitless'}, + ascent_duration={'units': 's', 'shape': 1}, + actual_range={'val': prob.target_range, 'units': 'NM'}, + ), + promotes_inputs=[ + ('actual_range', Mission.Summary.RANGE), + ('ascent_duration', Mission.Takeoff.ASCENT_DURATION), + ], + promotes_outputs=[('reg_objective', Mission.Objectives.RANGE)], +) + +##### +# prob.setup() +setup_model_options(prob, prob.aviary_inputs, prob.meta_data) + +with warnings.catch_warnings(): + prob.model.aviary_inputs = prob.aviary_inputs + prob.model.meta_data = prob.meta_data + +with warnings.catch_warnings(): + warnings.simplefilter('ignore', om.OpenMDAOWarning) + warnings.simplefilter('ignore', om.PromotionWarning) + + om.Problem.setup(prob, check=False) + +# set initial guesses manually +control_keys = ['mach', 'altitude'] +state_keys = ['mass', Dynamic.Mission.DISTANCE] +guesses = {} +guesses['mach_climb'] = ([0.2, 0.72], 'unitless') +guesses['altitude_climb'] = ([0, 32000.0], 'ft') +guesses['time_climb'] = ([0, 3840.0], 's') +guesses['mach_cruise'] = ([0.72, 0.72], 'unitless') +guesses['altitude_cruise'] = ([32000.0, 34000.0], 'ft') +guesses['time_cruise'] = ([3840.0, 3390.0], 's') +guesses['mach_descent'] = ([0.72, 0.36], 'unitless') +guesses['altitude_descent'] = ([34000.0, 500.0], 'ft') +guesses['time_descent'] = ([7230.0, 1740.0], 's') + +prob.set_val('traj.climb.t_initial', guesses['time_climb'][0][0], units='s') +prob.set_val('traj.climb.t_duration', guesses['time_climb'][0][1], units='s') +prob.set_val( + 'traj.climb.controls:mach', + prob.model.traj.phases.climb.interp('mach', xs=[-1, 1], ys=guesses['mach_climb'][0]), + units='unitless', +) +prob.set_val( + 'traj.climb.controls:altitude', + prob.model.traj.phases.climb.interp('altitude', xs=[-1, 1], ys=guesses['altitude_climb'][0]), + units='ft', +) + +prob.set_val('traj.cruise.t_initial', guesses['time_cruise'][0][0], units='s') +prob.set_val('traj.cruise.t_duration', guesses['time_cruise'][0][1], units='s') +prob.set_val( + 'traj.cruise.controls:mach', + prob.model.traj.phases.cruise.interp('mach', xs=[-1, 1], ys=guesses['mach_cruise'][0]), + units='unitless', +) +prob.set_val( + 'traj.cruise.controls:altitude', + prob.model.traj.phases.cruise.interp('altitude', xs=[-1, 1], ys=guesses['altitude_cruise'][0]), + units='ft', +) + +prob.set_val('traj.descent.t_initial', guesses['time_descent'][0][0], units='s') +prob.set_val('traj.descent.t_duration', guesses['time_descent'][0][1], units='s') +prob.set_val( + 'traj.descent.controls:mach', + prob.model.traj.phases.climb.interp('mach', xs=[-1, 1], ys=guesses['mach_descent'][0]), + units='unitless', +) +prob.set_val( + 'traj.descent.controls:altitude', + prob.model.traj.phases.climb.interp('altitude', xs=[-1, 1], ys=guesses['altitude_descent'][0]), + units='ft', +) +prob.set_val('traj.climb.states:mass', 125000, units='lbm') +prob.set_val('traj.cruise.states:mass', 125000, units='lbm') +prob.set_val('traj.descent.states:mass', 125000, units='lbm') + +prob.set_val(Mission.Design.GROSS_MASS, 175400, units='lbm') +prob.set_val(Mission.Summary.GROSS_MASS, 175400, units='lbm') + +prob.verbosity = Verbosity.BRIEF + +prob.run_aviary_problem() + +# Uncomment these lines to get printouts of every variable in the openmdao model +# prob.model.list_vars(units=True, print_arrays=True) +# prob.list_driver_vars(print_arrays=True) diff --git a/aviary/examples/run_off_design_example.py b/aviary/examples/run_off_design_example.py index 7ff669934f..3ad07c2014 100644 --- a/aviary/examples/run_off_design_example.py +++ b/aviary/examples/run_off_design_example.py @@ -1,6 +1,6 @@ """ This is a slightly more complex Aviary example of running a coupled aircraft design-mission optimization. -It runs the same mission as the `run_basic_aviary_example.py` script, but it uses the AviaryProblem class to set up the problem. +It runs the same mission as the `level1_example.py` script, but it uses the AviaryProblem class to set up the problem. This exposes more options and flexibility to the user and uses the "Level 2" API within Aviary. We define a `phase_info` object, which tells Aviary how to model the mission. @@ -8,170 +8,77 @@ We then call the correct methods in order to set up and run an Aviary optimization problem. This performs a coupled design-mission optimization and outputs the results from Aviary into the `reports` folder. """ -from openmdao.utils.general_utils import env_truthy -import aviary.api as av -from aviary.interface.default_phase_info.height_energy import phase_info_parameterization -from aviary.variable_info.enums import ProblemType -from aviary.variable_info.variables import Mission +import aviary.api as av -phase_info = { - "pre_mission": {"include_takeoff": True, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - 'fix_initial': False, - 'input_initial': True, - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 6, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.3, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.1, 0.8), "unitless"), - "initial_altitude": (35., "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((0.0, 35000.0), "ft"), - "throttle_enforcement": "path_constraint", - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 2.0), "min"), - "duration_bounds": ((5.0, 50.0), "min"), - "no_descent": False, - "add_initial_mass_constraint": False, - }, - "initial_guesses": {"time": ([0, 40.0], "min")}, - }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "polynomial_control_order": 1, - "use_polynomial_control": True, - "num_segments": 1, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.79, 0.79), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((35000.0, 35000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((60.0, 720.0), "min"), - }, - "initial_guesses": {"time": ([128, 113], "min")}, - }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.3, "unitless"), - "mach_bounds": ((0.2, 0.8), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35.0, "ft"), - "altitude_bounds": ((0.0, 35000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120., 800.), "min"), - "duration_bounds": ((5.0, 35.0), "min"), - "no_climb": True, - }, - "initial_guesses": {"time": ([241, 30], "min")}, - }, - "post_mission": { - "include_landing": True, - "constrain_range": True, - "target_range": (3375.0, "nmi"), - }, -} +# We will size the aircraft in this example for a longer design range than specified in the default +# phase_info +phase_info = av.default_height_energy_phase_info +phase_info['post_mission']['target_range'] = (2500.0, 'nmi') ################## # Sizing Mission # ################## -prob = av.AviaryProblem() +prob = av.AviaryProblem(verbosity=0) # Load aircraft and options data from user # Allow for user overrides here -prob.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) +prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', phase_info +) # Preprocess inputs prob.check_and_preprocess_inputs() -prob.add_pre_mission_systems() -prob.add_phases(phase_info_parameterization=phase_info_parameterization) -prob.add_post_mission_systems() -# Link phases and variables -prob.link_phases() -if env_truthy("TESTFLO_RUNNING"): - prob.add_driver('SLSQP', max_iter=100) -else: - prob.add_driver('SNOPT', max_iter=100) +prob.build_model() + +prob.add_driver('SLSQP', max_iter=50) prob.add_design_variables() # Load optimization problem formulation # Detail which variables the optimizer can control prob.add_objective() prob.setup() -prob.set_initial_guesses() +print('Running Design Mission') prob.run_aviary_problem() -prob.save_sizing_to_json() # Fallout Mission -prob_fallout = prob.fallout_mission() +print('Running fixed-mass, varying range off-design problem') +prob_fallout = prob.run_off_design_mission(problem_type='fallout', mission_gross_mass=115000) # Alternate Mission -prob_alternate = prob.alternate_mission() +print('Running fixed-range, varying fuel off-design problem') +prob_alternate = prob.run_off_design_mission(problem_type='alternate', mission_range=1250) -print('--------------') +print('\n--------------') print('Sizing Results') print('--------------') -print(f'Design Range = {prob.get_val(av.Mission.Design.RANGE)}') -print(f'Summary Range = {prob.get_val(av.Mission.Summary.RANGE)}') -print(f'Fuel mass = {prob.get_val(av.Mission.Design.FUEL_MASS)}') -print(f'Total fuel mass = {prob.get_val(av.Mission.Summary.TOTAL_FUEL_MASS)}') -print(f'Empty mass = {prob.get_val(av.Aircraft.Design.OPERATING_MASS)}') -print(f'Payload mass = {prob.get_val(av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)}') -print(f'Design Gross mass = {prob.get_val(av.Mission.Design.GROSS_MASS)}') -print(f'Summary Gross mass = {prob.get_val(av.Mission.Summary.GROSS_MASS)}') +print(f'Design Range = {prob.get_val(av.Mission.Design.RANGE)[0]} nmi') +print(f'Mission Range = {prob.get_val(av.Mission.Summary.RANGE)[0]} nmi') +print(f'Fuel Mass = {prob.get_val(av.Mission.Summary.TOTAL_FUEL_MASS)[0]} lbm') +print(f'Operating Empty Mass = {prob.get_val(av.Mission.Summary.OPERATING_MASS)[0]} lbm') +print(f'Payload Mass = {prob.get_val(av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)[0]} lbm') +print(f'Design Gross Mass = {prob.get_val(av.Mission.Design.GROSS_MASS)[0]} lbm') +print(f'Mission Gross Mass = {prob.get_val(av.Mission.Summary.GROSS_MASS)[0]} lbm') -print('---------------') +print('\n---------------') print('Fallout Results') print('---------------') -print(f'Design Range = {prob_fallout.get_val(av.Mission.Design.RANGE)}') -print(f'Summary Range = {prob_fallout.get_val(av.Mission.Summary.RANGE)}') -print(f'Fuel mass = {prob_fallout.get_val(av.Mission.Design.FUEL_MASS)}') -print(f'Total fuel mass = {prob_fallout.get_val(av.Mission.Summary.TOTAL_FUEL_MASS)}') -print(f'Empty mass = {prob_fallout.get_val(av.Aircraft.Design.OPERATING_MASS)}') -print( - f'Payload mass = {prob_fallout.get_val(av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)}') -print(f'Design Gross mass = {prob_fallout.get_val(av.Mission.Design.GROSS_MASS)}') -print(f'Summary Gross mass = {prob_fallout.get_val(av.Mission.Summary.GROSS_MASS)}') +print(f'Design Range = {prob_fallout.get_val(av.Mission.Design.RANGE)[0]} nmi') +print(f'Mission Range = {prob_fallout.get_val(av.Mission.Summary.RANGE)[0]} nmi') +print(f'Fuel Mass = {prob_fallout.get_val(av.Mission.Summary.TOTAL_FUEL_MASS)[0]} lbm') +print(f'Operating Empty Mass = {prob_fallout.get_val(av.Mission.Summary.OPERATING_MASS)[0]} lbm') +print(f'Payload Mass = {prob_fallout.get_val(av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)[0]} lbm') +print(f'Design Gross Mass = {prob_fallout.get_val(av.Mission.Design.GROSS_MASS)[0]} lbm') +print(f'Mission Gross Mass = {prob_fallout.get_val(av.Mission.Summary.GROSS_MASS)[0]} lbm') -print('---------------') +print('\n-----------------') print('Alternate Results') -print('---------------') -print(f'Design Range = {prob_alternate.get_val(av.Mission.Design.RANGE)}') -print(f'Summary Range = {prob_alternate.get_val(av.Mission.Summary.RANGE)}') -print(f'Fuel mass = {prob_alternate.get_val(av.Mission.Design.FUEL_MASS)}') -print(f'Total fuel mass = {prob_alternate.get_val(av.Mission.Summary.TOTAL_FUEL_MASS)}') -print(f'Empty mass = {prob_alternate.get_val(av.Aircraft.Design.OPERATING_MASS)}') -print( - f'Payload mass = {prob_alternate.get_val(av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)}') -print(f'Design Gross mass = {prob_alternate.get_val(av.Mission.Design.GROSS_MASS)}') -print(f'Summary Gross mass = {prob_alternate.get_val(av.Mission.Summary.GROSS_MASS)}') +print('-----------------') +print(f'Design Range = {prob_alternate.get_val(av.Mission.Design.RANGE)[0]} nmi') +print(f'Mission Range = {prob_alternate.get_val(av.Mission.Summary.RANGE)[0]} nmi') +print(f'Fuel Mass = {prob_alternate.get_val(av.Mission.Summary.TOTAL_FUEL_MASS)[0]} lbm') +print(f'Operating Empty Mass = {prob_alternate.get_val(av.Mission.Summary.OPERATING_MASS)[0]} lbm') +print(f'Payload Mass = {prob_alternate.get_val(av.Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)[0]} lbm') +print(f'Design Gross Mass = {prob_alternate.get_val(av.Mission.Design.GROSS_MASS)[0]} lbm') +print(f'Mission Gross Mass = {prob_alternate.get_val(av.Mission.Summary.GROSS_MASS)[0]} lbm') diff --git a/aviary/examples/test/test_all_examples.py b/aviary/examples/test/test_all_examples.py index 4f65499b70..a592a4f2b6 100644 --- a/aviary/examples/test/test_all_examples.py +++ b/aviary/examples/test/test_all_examples.py @@ -9,13 +9,63 @@ import unittest from pathlib import Path +from openmdao.utils.testing_utils import use_tempdirs +from openmdao.utils.general_utils import set_pyoptsparse_opt +from parameterized import parameterized +# TODO: Address any issue that requires a skip. +SKIP_EXAMPLES = { + 'run_multimission_example.py': 'Broken due to OpenMDAO changes', + 'run_OAS_wing_mass_example.py': 'Timeout when running via this script', + 'run_NPSS_example.py': 'Cannot be run without NPSS install', +} + +# TODO: temporary fix, waiting on https://github.com/OpenMDAO/OpenMDAO/issues/3510 +OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT') + + +def find_examples(): + """ + Find and return a list of run scripts in the specified directory. + + Returns + ------- + list + A list of pathlib.Path objects pointing to the run scripts. + """ + base_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), '.') + + run_files = [] + for root, _, files in os.walk(base_dir): + for file in files: + if file.startswith('run_') and file.endswith('.py'): + run_files.append(Path(root) / file) + return run_files + + +def example_name(testcase_func, param_num, param): + """ + Returns a formatted case name for unit testing with decorator @parameterized.expand(). + It is intended to be used when expand() is called with a list of strings + representing test case names. + + Parameters + ---------- + testcase_func : Any + This parameter is ignored. + param_num : Any + This parameter is ignored. + param : param + The param object containing the case name to be formatted. + """ + return 'test_example_' + param.args[0].name.replace('.py', '') + + +@use_tempdirs class RunScriptTest(unittest.TestCase): """ A test case class that uses unittest to run and test scripts with a timeout. - ... - Attributes ---------- base_directory : str @@ -35,40 +85,6 @@ class RunScriptTest(unittest.TestCase): Generates a test for each run script with a timeout. """ - @classmethod - def setUpClass(cls): - """ - Class method to set up the test case class by finding all run scripts. - - This method is called once before starting the tests and is used to - populate the 'run_files' attribute with a list of run scripts. - """ - base_directory = os.path.join(os.path.dirname( - os.path.dirname(os.path.abspath(__file__))), ".") - cls.run_files = cls.find_run_files(base_directory) - - @staticmethod - def find_run_files(base_dir): - """ - Find and return a list of run scripts in the specified directory. - - Parameters - ---------- - base_dir : str - The directory to search for run scripts. - - Returns - ------- - list - A list of pathlib.Path objects pointing to the run scripts. - """ - run_files = [] - for root, _, files in os.walk(base_dir): - for file in files: - if file.startswith('run_') and file.endswith('.py'): - run_files.append(Path(root) / file) - return run_files - def run_script(self, script_path, max_allowable_time=500): """ Attempt to run a script with a 500-second timeout and handle errors. @@ -84,29 +100,25 @@ def run_script(self, script_path, max_allowable_time=500): Any exception other than ImportError or TimeoutExpired that occurs while running the script. """ with open(os.devnull, 'w') as devnull: - proc = subprocess.Popen(['python', script_path], - stdout=devnull, stderr=subprocess.PIPE) + proc = subprocess.Popen(['python', script_path], stdout=devnull, stderr=subprocess.PIPE) proc.wait(timeout=max_allowable_time) (stdout, stderr) = proc.communicate() if proc.returncode != 0: if 'ImportError' in str(stderr): - self.skipTest(f"Skipped {script_path.name} due to ImportError") + self.skipTest(f'Skipped {script_path.name} due to ImportError') else: - raise Exception( - f"Error running {script_path.name}:\n{stderr.decode('utf-8')}") + raise Exception(f'Error running {script_path.name}:\n{stderr.decode("utf-8")}') - def test_run_scripts(self): - """ - Test each run script to ensure it executes without error. + @parameterized.expand(find_examples(), name_func=example_name) + def test_run_scripts(self, example_path): + """Test each run script to ensure it executes without error.""" + if example_path.name in SKIP_EXAMPLES: + reason = SKIP_EXAMPLES[example_path.name] + self.skipTest(f'Skipped {example_path.name}: {reason}.') - This method generates a subtest for each script in 'run_files'. - Each script is tested to ensure it runs without errors. - """ - for script_path in self.run_files: - with self.subTest(script=script_path.name): - self.run_script(script_path) + self.run_script(example_path) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/examples/test/test_level2_shooting_traj.py b/aviary/examples/test/test_level2_shooting_traj.py deleted file mode 100644 index 9fb3a51551..0000000000 --- a/aviary/examples/test/test_level2_shooting_traj.py +++ /dev/null @@ -1,21 +0,0 @@ -import unittest - -from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs - -from aviary.api import AnalysisScheme -from aviary.examples.level2_shooting_traj import custom_run_aviary - - -@use_tempdirs -class CustomTrajTestCase(unittest.TestCase): - # A test class for shooting scheme - - @require_pyoptsparse(optimizer='IPOPT') - def test_run_aviary(self): - input_deck = 'models/large_single_aisle_1/large_single_aisle_1_GwGm.csv' - custom_run_aviary( - input_deck, analysis_scheme=AnalysisScheme.SHOOTING, run_driver=False) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/examples/variable_meta_data_extension.py b/aviary/examples/variable_meta_data_extension.py index e42b178728..ddd293575d 100644 --- a/aviary/examples/variable_meta_data_extension.py +++ b/aviary/examples/variable_meta_data_extension.py @@ -1,7 +1,7 @@ -''' -Define meta data associated with variables in the disciplinary data hierarchy. -''' +"""Define meta data associated with variables in the disciplinary data hierarchy.""" + from copy import deepcopy + import numpy as np import aviary.api as av @@ -38,6 +38,8 @@ Aircraft.CG, units='ft', desc='Center of gravity', + types=float, + multivalue=True, default_value=np.zeros(3), meta_data=ExtendedMetaData, # note that VSP_example is not a real code and center_of_gravity is not a real variable name. These are here to show how the historical_name argument can be used. @@ -48,8 +50,8 @@ Aircraft.MASS, units='lbm', desc='Total aircraft mass.', - default_value=1., - meta_data=ExtendedMetaData + default_value=1.0, + meta_data=ExtendedMetaData, ) # _ _ _ _ _ _______ _ _ @@ -65,7 +67,7 @@ units='ft', desc='Mean aerodynamic chord.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -73,7 +75,7 @@ units='ft**2', desc='Area of each elevator element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -81,7 +83,7 @@ units='ft', desc='Root chord of each elevator element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -89,7 +91,7 @@ units='ft', desc='Span of each elevator element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) # _ @@ -107,7 +109,7 @@ units='kg', desc='mass of the aircraft`s jury', default_value=0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) # _ _ _ _____ @@ -125,7 +127,7 @@ units='ft', desc='Main gear oleo diameter', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) # __ __ _ _ _ _______ _ _ @@ -141,7 +143,7 @@ units='ft', desc='Mean aerodynamic chord.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -149,7 +151,7 @@ units='ft**2', desc='Area of each rudder element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -157,7 +159,7 @@ units='ft', desc='Root chord of each rudder element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -165,7 +167,7 @@ units='ft', desc='Span of each rudder element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) # __ __ _ @@ -182,8 +184,10 @@ Aircraft.Wing.AERO_CENTER, units='ft', desc='aerodynamic center.', + types=float, + multivalue=True, default_value=np.zeros(3), - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -191,7 +195,7 @@ units='ft', desc='Reference chord.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -199,7 +203,7 @@ units='ft**2', desc='Area of each flap element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -207,7 +211,7 @@ units='ft', desc='Root chord of each flap element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -215,7 +219,7 @@ units='ft', desc='Span of each flap element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -223,7 +227,7 @@ units='ft**2', desc='Area of each Krueger element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -231,7 +235,7 @@ units='ft', desc='Root chord of each krueger element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -239,7 +243,7 @@ units='ft', desc='Span of each krueger element.', default_value=0.0, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) # ============================================================================================================================================ @@ -269,7 +273,7 @@ units='lbm', desc='Fuel mass states along cruise phase', default_value=None, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -277,7 +281,7 @@ units='unitless', desc='Mach number states along cruise phase', default_value=None, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( @@ -285,7 +289,7 @@ units='lbm', desc='Gross mass states along cruise phase', default_value=None, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) # _______ _ @@ -301,7 +305,7 @@ units='h', desc='I am changing the description of this variable to demonstrate the update_meta_data function', default_value=0.167, - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, # We use the ExtendedMetaData because this is the metadata we want to edit. # Despite the fact that we never added Mission.Taxi.DURATION to the ExtendedMetaData, # the variable is already there because it exists in the av.CoreMetaData diff --git a/aviary/examples/variables_extension.py b/aviary/examples/variables_extension.py index 85e69d55ad..e796dde351 100644 --- a/aviary/examples/variables_extension.py +++ b/aviary/examples/variables_extension.py @@ -5,56 +5,55 @@ class Aircraft(AviaryAircraft): - """Extended Aircraft data hierarchy""" + """Extended Aircraft data hierarchy.""" - CG = "aircraft:center_of_gravity" - MASS = "aircraft:mass" + CG = 'aircraft:center_of_gravity' + MASS = 'aircraft:mass' class HorizontalTail(AviaryAircraft.HorizontalTail): - MEAN_AERO_CHORD = "aircraft:horizontal_tail:mean_aerodynamic_chord" + MEAN_AERO_CHORD = 'aircraft:horizontal_tail:mean_aerodynamic_chord' class Elevator: - AREA = "aircraft:horizontal_tail:elevator:area_dist" - ROOT_CHORD = "aircraft:horizontal_tail:elevator:root_chord_dist" - SPAN = "aircraft:horizontal_tail:elevator:span_dist" + AREA = 'aircraft:horizontal_tail:elevator:area_dist' + ROOT_CHORD = 'aircraft:horizontal_tail:elevator:root_chord_dist' + SPAN = 'aircraft:horizontal_tail:elevator:span_dist' class Jury: - MASS = "aircraft:jury:mass" + MASS = 'aircraft:jury:mass' class LandingGear(AviaryAircraft.LandingGear): - MAIN_GEAR_OLEO_DIAMETER = "aircraft:landing_gear:main_gear_oleo_diameter" + MAIN_GEAR_OLEO_DIAMETER = 'aircraft:landing_gear:main_gear_oleo_diameter' class VerticalTail(AviaryAircraft.VerticalTail): - MEAN_AERO_CHORD = "aircraft:vertical_tail:mean_aerodynamic_chord" + MEAN_AERO_CHORD = 'aircraft:vertical_tail:mean_aerodynamic_chord' class Rudder: - AREA = "aircraft:vertical_tail:rudder:area_dist" - ROOT_CHORD = "aircraft:vertical_tail:rudder:root_chord_dist" - SPAN = "aircraft:vertical_tail:rudder:span_dist" + AREA = 'aircraft:vertical_tail:rudder:area_dist' + ROOT_CHORD = 'aircraft:vertical_tail:rudder:root_chord_dist' + SPAN = 'aircraft:vertical_tail:rudder:span_dist' class Wing(AviaryAircraft.Wing): - - AERO_CENTER = "aircraft:wing:aerodynamic_center" - CHORD = "aircraft:wing:chord" + AERO_CENTER = 'aircraft:wing:aerodynamic_center' + CHORD = 'aircraft:wing:chord' class Flap: - AREA = "aircraft:wing:flap:area_dist" - ROOT_CHORD = "aircraft:wing:flap:root_chord_dist" - SPAN = "aircraft:wing:flap:span_dist" + AREA = 'aircraft:wing:flap:area_dist' + ROOT_CHORD = 'aircraft:wing:flap:root_chord_dist' + SPAN = 'aircraft:wing:flap:span_dist' class Krueger: - AREA = "aircraft:wing:krueger:area_dist" - ROOT_CHORD = "aircraft:wing:krueger:root_chord_dist" - SPAN = "aircraft:wing:krueger:span_dist" + AREA = 'aircraft:wing:krueger:area_dist' + ROOT_CHORD = 'aircraft:wing:krueger:root_chord_dist' + SPAN = 'aircraft:wing:krueger:span_dist' class Mission(AviaryMission): - """Extended Mission data hierarchy""" + """Extended Mission data hierarchy.""" class Cruise: - FUEL_MASS = "mission:cruise:fuel_mass" - MACH = "mission:cruise:mach" - MASS = "mission:cruise:mass" + FUEL_MASS = 'mission:cruise:fuel_mass' + MACH = 'mission:cruise:mach' + MASS = 'mission:cruise:mass' # note that we do not include a Mission.Taxi object, despite the fact that we will edit # the Mission.Taxi.DURATION variable in the meta_data_extension example. We do not need diff --git a/aviary/interface/cmd_entry_points.py b/aviary/interface/cmd_entry_points.py index 5b32168cdf..6372b20d9a 100644 --- a/aviary/interface/cmd_entry_points.py +++ b/aviary/interface/cmd_entry_points.py @@ -2,16 +2,17 @@ import os import sys -import aviary +from aviary.interface.download_models import _exec_hangar, _setup_hangar_parser +from aviary.interface.graphical_input import _exec_flight_profile, _setup_flight_profile_parser from aviary.interface.methods_for_level1 import _exec_level1, _setup_level1_parser -from aviary.utils.fortran_to_aviary import _exec_F2A, _setup_F2A_parser -from aviary.utils.engine_deck_conversion import _exec_EDC, _setup_EDC_parser, EDC_description +from aviary.interface.plot_drag_polar import _exec_plot_drag_polar, _setup_plot_drag_polar_parser +from aviary.interface.test_installation import _exec_installation_test, _setup_installation_test from aviary.utils.aero_table_conversion import _exec_ATC, _setup_ATC_parser +from aviary.utils.engine_deck_conversion import _exec_EDC, _setup_EDC_parser +from aviary.utils.fortran_to_aviary import _exec_F2A, _setup_F2A_parser from aviary.utils.propeller_map_conversion import _exec_PMC, _setup_PMC_parser -from aviary.visualization.dashboard import _dashboard_setup_parser, _dashboard_cmd -from aviary.interface.graphical_input import _exec_flight_profile, _setup_flight_profile_parser -from aviary.interface.download_models import _exec_hangar, _setup_hangar_parser -from aviary.interface.plot_drag_polar import _exec_plot_drag_polar, _setup_plot_drag_polar_parser +from aviary.visualization.dashboard import _dashboard_cmd, _dashboard_setup_parser +from aviary.visualization.realtime_plot import _rtplot_cmd, _rtplot_setup_parser def _load_and_exec(script_name, user_args): @@ -25,7 +26,6 @@ def _load_and_exec(script_name, user_args): user_args : list of str Args to be passed to the user script. """ - sys.path.insert(0, os.path.dirname(script_name)) sys.argv[:] = [script_name] + user_args @@ -44,51 +44,86 @@ def _load_and_exec(script_name, user_args): _command_map = { - 'fortran_to_aviary': (_setup_F2A_parser, _exec_F2A, - "Converts legacy Fortran input decks to Aviary csv based decks"), - 'run_mission': (_setup_level1_parser, _exec_level1, - "Runs Aviary using a provided input deck"), - 'draw_mission': (_setup_flight_profile_parser, _exec_flight_profile, - "Allows users to draw a mission profile for use in Aviary."), - 'dashboard': (_dashboard_setup_parser, _dashboard_cmd, - "Run the Dashboard tool"), - 'hangar': (_setup_hangar_parser, _exec_hangar, - "Allows users that pip installed Aviary to download models from the Aviary hangar"), - 'convert_engine': (_setup_EDC_parser, _exec_EDC, EDC_description), - 'convert_aero_table': (_setup_ATC_parser, _exec_ATC, - 'Converts FLOPS- or GASP-formatted aero data files into Aviary csv format.'), - 'convert_prop_table': (_setup_PMC_parser, _exec_PMC, - 'Converts GASP-formatted propeller map file into Aviary csv format.'), - 'plot_drag_polar': (_setup_plot_drag_polar_parser, _exec_plot_drag_polar, 'Plot a Drag Polar Graph using a provided polar data csv input'), + 'check': ( + _setup_installation_test, + _exec_installation_test, + 'Verify Aviary installation', + ), + 'fortran_to_aviary': ( + _setup_F2A_parser, + _exec_F2A, + 'Convert legacy Fortran (FLOPS OR GASP) input file to Aviary input file.', + ), + 'run_mission': (_setup_level1_parser, _exec_level1, 'Run Aviary using a provided input deck.'), + 'draw_mission': ( + _setup_flight_profile_parser, + _exec_flight_profile, + 'Open the mission profile drawing GUI.', + ), + 'dashboard': ( + _dashboard_setup_parser, + _dashboard_cmd, + 'Open the results dashboard for a provided Aviary run.', + ), + 'hangar': ( + _setup_hangar_parser, + _exec_hangar, + 'Copy aircraft and engine models included with Aviary to specified folder. Allows users' + 'who did not install Aviary locally to still access model files.', + ), + 'convert_engine': ( + _setup_EDC_parser, + _exec_EDC, + 'Convert FLOPS- or GASP-formatted engine decks into Aviary csv format.', + ), + 'convert_aero_table': ( + _setup_ATC_parser, + _exec_ATC, + 'Convert FLOPS- or GASP-formatted aero data files into Aviary csv format.', + ), + 'convert_prop_table': ( + _setup_PMC_parser, + _exec_PMC, + 'Convert GASP-formatted propeller map file into Aviary csv format.', + ), + 'plot_drag_polar': ( + _setup_plot_drag_polar_parser, + _exec_plot_drag_polar, + 'Plot a Drag Polar Graph using a provided polar data csv input.', + ), + 'rtplot': ( + _rtplot_setup_parser, + _rtplot_cmd, + 'Run a script and show a real-time plot of the optimization progress.', + ), } def aviary_cmd(): - """ - Run an 'aviary' sub-command or list help info for 'aviary' command or sub-commands. - """ + """Run an 'aviary' sub-command or list help info for 'aviary' command or sub-commands.""" # pre-parse sys.argv to split between before and after '--' if '--' in sys.argv: idx = sys.argv.index('--') sys_args = sys.argv[:idx] - user_args = sys.argv[idx + 1:] + user_args = sys.argv[idx + 1 :] sys.argv[:] = sys_args else: user_args = [] - parser = argparse.ArgumentParser(description='aviary Command Line Tools', - # epilog='Use -h after any sub-command for sub-command help, ' - # 'for example, "openmdao tree -h" for help on the "tree" ' - # 'command. If using a tool on a script that takes its own ' - # 'command line arguments, place those arguments after a "--". ' - # 'For example: ' - # '"openmdao n2 -o foo.html myscript.py -- -x --myarg=bar"' - ) + parser = argparse.ArgumentParser( + description='aviary Command Line Tools', + # epilog='Use -h after any sub-command for sub-command help, ' + # 'for example, "openmdao tree -h" for help on the "tree" ' + # 'command. If using a tool on a script that takes its own ' + # 'command line arguments, place those arguments after a "--". ' + # 'For example: ' + # '"openmdao n2 -o foo.html myscript.py -- -x --myarg=bar"' + ) # Adding the --version argument parser.add_argument('--version', action='store_true', help='show version and exit') - subs = parser.add_subparsers(title='Tools', metavar='', dest="subparser_name") + subs = parser.add_subparsers(title='Tools', metavar='', dest='subparser_name') for p, (parser_setup_func, executor, help_str) in sorted(_command_map.items()): subp = subs.add_parser(p, help=help_str) parser_setup_func(subp) @@ -98,8 +133,12 @@ def aviary_cmd(): # '--version', '--dependency_versions')] cmdargs = [a for a in sys.argv[1:] if a not in ('-h',)] + if len(args) == 0 and len(cmdargs) == 0: + args = ['-h'] + if len(args) == 1 and len(user_args) == 0: - if args[0] not in ('draw_mission', 'run_mission', 'plot_drag_polar'): + # if command requires arguments but is run without any, return help for that command + if args[0] not in ('check', 'draw_mission', 'run_mission', 'plot_drag_polar'): parser.parse_args([args[0], '-h']) if not set(args).intersection(subs.choices) and len(args) == 1 and os.path.isfile(cmdargs[0]): @@ -109,7 +148,7 @@ def aviary_cmd(): # Check if --version was passed if options.version: - print(f"Aviary version: {aviary.__version__}") + print(f'Aviary version: {aviary.__version__}') return if unknown: @@ -125,8 +164,6 @@ def aviary_cmd(): if hasattr(options, 'executor'): options.executor(options, user_args) - else: - os.system('aviary -h') if __name__ == '__main__': diff --git a/aviary/interface/default_phase_info/height_energy.py b/aviary/interface/default_phase_info/height_energy.py deleted file mode 100644 index 3df09fffa5..0000000000 --- a/aviary/interface/default_phase_info/height_energy.py +++ /dev/null @@ -1,130 +0,0 @@ -from aviary.variable_info.variables import Mission - -# defaults for height energy based phases - -phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.2, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.18, 0.74), "unitless"), - "initial_altitude": (0.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((0.0, 34000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((64.0, 192.0), "min"), - "add_initial_mass_constraint": False, - }, - }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (34000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((56.5, 169.5), "min"), - }, - }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.36, "unitless"), - "mach_bounds": ((0.34, 0.74), "unitless"), - "initial_altitude": (34000.0, "ft"), - "final_altitude": (500.0, "ft"), - "altitude_bounds": ((0.0, 38000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((29.0, 87.0), "min"), - }, - }, - "post_mission": { - "include_landing": False, - "constrain_range": True, - "target_range": (1906., "nmi"), - }, -} - - -def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs): - """ - Modify the values in the phase_info dictionary to accommodate different values - for the following mission design inputs: cruise altitude, cruise Mach number, - cruise range, design gross mass. - - Parameters - ---------- - phase_info : dict - Dictionary of phase settings for a mission profile - post_mission_info : dict - Dictionary of phase settings for a post mission profile - aviary_inputs : - Object containing values and units for all aviary inputs and options - - Returns - ------- - dict - Modified phase_info and post_mission_info that have been changed to match - the new mission parameters - """ - - alt_cruise = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') - mach_cruise = aviary_inputs.get_val(Mission.Summary.CRUISE_MACH) - - # Range - old_range_cruise, range_units = post_mission_info['target_range'] - range_cruise = aviary_inputs.get_val(Mission.Design.RANGE, units=range_units) - if range_cruise != old_range_cruise: - new_val = post_mission_info['target_range'][0] * range_cruise / old_range_cruise - post_mission_info['target_range'] = (new_val, range_units) - - # Altitude - old_alt_cruise = 32000. - if alt_cruise != old_alt_cruise: - phase_info['climb']['user_options']['final_altitude'] = (alt_cruise, 'ft') - phase_info['cruise']['user_options']['initial_altitude'] = (alt_cruise, 'ft') - phase_info['cruise']['user_options']['final_altitude'] = (alt_cruise, 'ft') - phase_info['descent']['user_options']['initial_altitude'] = (alt_cruise, 'ft') - - # Mach - old_mach_cruise = 0.72 - if mach_cruise != old_mach_cruise: - phase_info['climb']['user_options']['final_mach'] = (mach_cruise, "unitless") - phase_info['cruise']['user_options']['initial_mach'] = (mach_cruise, "unitless") - phase_info['cruise']['user_options']['final_mach'] = (mach_cruise, "unitless") - phase_info['descent']['user_options']['initial_mach'] = (mach_cruise, "unitless") - - return phase_info, post_mission_info diff --git a/aviary/interface/default_phase_info/height_energy_fiti.py b/aviary/interface/default_phase_info/height_energy_fiti.py deleted file mode 100644 index d96443ef6d..0000000000 --- a/aviary/interface/default_phase_info/height_energy_fiti.py +++ /dev/null @@ -1,82 +0,0 @@ -from aviary.mission.flops_based.phases.time_integration_phases import SGMHeightEnergy -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Dynamic, Mission -from aviary.variable_info.enums import SpeedType, AlphaModes - -from aviary.interface.default_phase_info.two_dof_fiti import add_default_sgm_args - -# defaults for height energy based forward in time integeration phases -cruise_mach = .8, -cruise_alt = 35e3, - -phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": True}, - "climb": { - 'builder': SGMHeightEnergy, - "user_options": { - 'mach': (cruise_mach, 'unitless'), - 'alt_trigger': (cruise_alt, 'ft'), - }, - }, - "cruise": { - 'kwargs': dict( - input_speed_type=SpeedType.MACH, - input_speed_units="unitless", - alpha_mode=AlphaModes.REQUIRED_LIFT, - ), - 'builder': SGMHeightEnergy, - "user_options": { - 'mach': (cruise_mach, 'unitless'), - }, - }, - "descent": { - 'builder': SGMHeightEnergy, - "user_options": { - 'mach': (cruise_mach, 'unitless'), - 'alt_trigger': (1000, 'ft'), - Dynamic.Mission.THROTTLE: (0, 'unitless'), - }, - }, - "post_mission": { - "include_landing": False, - "constrain_range": True, - "target_range": (1906., "nmi"), - }, -} - - -def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs: AviaryValues): - """ - Modify the values in the phase_info dictionary to accomodate different values - for the following mission design inputs: cruise altitude, cruise mach number, - cruise range, design gross mass. - - Parameters - ---------- - phase_info : dict - Dictionary of phase settings for a mission profile - post_mission_info : dict - Dictionary of phase settings for a post mission profile - aviary_inputs : - Object containing values and units for all aviary inputs and options - - Returns - ------- - dict - Modified phase_info and post_mission_info that have been changed to match - the new mission parameters - """ - - range_cruise = aviary_inputs.get_item(Mission.Design.RANGE) - alt_cruise = aviary_inputs.get_item(Mission.Design.CRUISE_ALTITUDE) - gross_mass = aviary_inputs.get_item(Mission.Design.GROSS_MASS) - mach_cruise = aviary_inputs.get_item(Mission.Design.MACH) - - phase_info['climb']['user_options']['alt_trigger'] = alt_cruise - phase_info['climb']['user_options']['mach'] = mach_cruise - - phase_info['cruise']['user_options']['mach'] = mach_cruise - - phase_info['descent']['user_options']['mach'] = mach_cruise - - return phase_info, post_mission_info diff --git a/aviary/interface/default_phase_info/two_dof.py b/aviary/interface/default_phase_info/two_dof.py deleted file mode 100644 index e5dd9e40c2..0000000000 --- a/aviary/interface/default_phase_info/two_dof.py +++ /dev/null @@ -1,370 +0,0 @@ -from aviary.variable_info.enums import SpeedType -from aviary.variable_info.variables import Mission - -# defaults for 2DOF based phases -mission_distance = 3675 - -phase_info = { - 'groundroll': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'connect_initial_mass': False, - 'fix_initial': True, - 'fix_initial_mass': False, - 'duration_ref': (50., 's'), - 'duration_bounds': ((1., 100.), 's'), - 'velocity_lower': (0, 'kn'), - 'velocity_upper': (1000, 'kn'), - 'velocity_ref': (150, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'ft'), - 'distance_upper': (10.e3, 'ft'), - 'distance_ref': (3000, 'ft'), - 'distance_defect_ref': (3000, 'ft'), - }, - 'initial_guesses': { - 'time': ([0.0, 40.0], 's'), - 'velocity': ([0.066, 143.1], 'kn'), - 'distance': ([0.0, 1000.], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - } - }, - 'rotation': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'fix_initial': False, - 'duration_bounds': ((1, 100), 's'), - 'duration_ref': (50.0, 's'), - 'velocity_lower': (0, 'kn'), - 'velocity_upper': (1000, 'kn'), - 'velocity_ref': (100, 'kn'), - 'velocity_ref0': (0, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'ft'), - 'distance_upper': (10_000, 'ft'), - 'distance_ref': (5000, 'ft'), - 'distance_defect_ref': (5000, 'ft'), - 'angle_lower': (0., 'rad'), - 'angle_upper': (5., 'rad'), - 'angle_ref': (5., 'rad'), - 'angle_defect_ref': (5., 'rad'), - 'normal_ref': (10000, 'lbf'), - }, - 'initial_guesses': { - 'time': ([40.0, 5.0], 's'), - 'alpha': ([0.0, 2.5], 'deg'), - 'velocity': ([143, 150.], 'kn'), - 'distance': ([3680.37217765, 4000], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - } - }, - 'ascent': { - 'user_options': { - 'num_segments': 4, - 'order': 3, - 'fix_initial': False, - 'velocity_lower': (0, 'kn'), - 'velocity_upper': (700, 'kn'), - 'velocity_ref': (200, 'kn'), - 'velocity_ref0': (0, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'ft'), - 'distance_upper': (15_000, 'ft'), - 'distance_ref': (1e4, 'ft'), - 'distance_defect_ref': (1e4, 'ft'), - 'alt_lower': (0, 'ft'), - 'alt_upper': (700, 'ft'), - 'alt_ref': (1000, 'ft'), - 'alt_defect_ref': (1000, 'ft'), - 'final_altitude': (500, 'ft'), - 'alt_constraint_ref': (500, 'ft'), - 'angle_lower': (-10, 'rad'), - 'angle_upper': (20, 'rad'), - 'angle_ref': (57.2958, 'deg'), - 'angle_defect_ref': (57.2958, 'deg'), - 'pitch_constraint_lower': (0., 'deg'), - 'pitch_constraint_upper': (15., 'deg'), - 'pitch_constraint_ref': (1., 'deg'), - }, - 'initial_guesses': { - 'time': ([45., 25.], 's'), - 'flight_path_angle': ([0.0, 8.], 'deg'), - 'alpha': ([2.5, 1.5], 'deg'), - 'velocity': ([150., 185.], 'kn'), - 'distance': ([4.e3, 10.e3], 'ft'), - 'altitude': ([0.0, 500.], 'ft'), - 'tau_gear': (0.2, 'unitless'), - 'tau_flaps': (0.9, 'unitless'), - 'throttle': ([0.956, 0.956], 'unitless'), - } - }, - 'accel': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'fix_initial': False, - 'alt': (500, 'ft'), - 'EAS_constraint_eq': (250, 'kn'), - 'duration_bounds': ((1, 200), 's'), - 'duration_ref': (1000, 's'), - 'velocity_lower': (150, 'kn'), - 'velocity_upper': (270, 'kn'), - 'velocity_ref': (250, 'kn'), - 'velocity_ref0': (150, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'NM'), - 'distance_upper': (150, 'NM'), - 'distance_ref': (5, 'NM'), - 'distance_defect_ref': (5, 'NM'), - }, - 'initial_guesses': { - 'time': ([70., 13.], 's'), - 'velocity': ([185., 250.], 'kn'), - 'distance': ([10.e3, 20.e3], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - } - }, - 'climb1': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'fix_initial': False, - 'EAS_target': (250, 'kn'), - 'mach_cruise': 0.8, - 'target_mach': False, - 'final_altitude': (10.e3, 'ft'), - 'duration_bounds': ((30, 300), 's'), - 'duration_ref': (1000, 's'), - 'alt_lower': (400, 'ft'), - 'alt_upper': (11_000, 'ft'), - 'alt_ref': (10.e3, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'NM'), - 'distance_upper': (500, 'NM'), - 'distance_ref': (10, 'NM'), - 'distance_ref0': (0, 'NM'), - }, - 'initial_guesses': { - 'time': ([1., 2.], 'min'), - 'distance': ([20.e3, 100.e3], 'ft'), - 'altitude': ([500., 10.e3], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - } - }, - 'climb2': { - 'user_options': { - 'num_segments': 3, - 'order': 3, - 'fix_initial': False, - 'EAS_target': (270, 'kn'), - 'mach_cruise': 0.8, - 'target_mach': True, - 'final_altitude': (37.5e3, 'ft'), - 'required_available_climb_rate': (0.1, 'ft/min'), - 'duration_bounds': ((200, 17_000), 's'), - 'duration_ref': (5000, 's'), - 'alt_lower': (9000, 'ft'), - 'alt_upper': (40000, 'ft'), - 'alt_ref': (30000, 'ft'), - 'alt_ref0': (0, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (10, 'NM'), - 'distance_upper': (1000, 'NM'), - 'distance_ref': (500, 'NM'), - 'distance_ref0': (0, 'NM'), - 'distance_defect_ref': (500, 'NM'), - }, - 'initial_guesses': { - 'time': ([216., 1300.], 's'), - 'distance': ([100.e3, 200.e3], 'ft'), - 'altitude': ([10.e3, 37.5e3], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - } - }, - 'cruise': { - 'user_options': { - 'alt_cruise': (37.5e3, 'ft'), - 'mach_cruise': 0.8, - }, - 'initial_guesses': { - # [Initial mass, delta mass] for special cruise phase. - 'mass': ([171481., -35000], 'lbm'), - 'initial_distance': (200.e3, 'ft'), - 'initial_time': (1516., 's'), - 'altitude': (37.5e3, 'ft'), - 'mach': (0.8, 'unitless'), - } - }, - 'desc1': { - 'user_options': { - 'num_segments': 3, - 'order': 3, - 'fix_initial': False, - 'input_initial': False, - 'EAS_limit': (350, 'kn'), - 'mach_cruise': 0.8, - 'input_speed_type': SpeedType.MACH, - 'final_altitude': (10.e3, 'ft'), - 'duration_bounds': ((300., 900.), 's'), - 'duration_ref': (1000, 's'), - 'alt_lower': (1000, 'ft'), - 'alt_upper': (40_000, 'ft'), - 'alt_ref': (30_000, 'ft'), - 'alt_ref0': (0, 'ft'), - 'alt_constraint_ref': (10000, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (140_000, 'lbm'), - 'mass_ref0': (0, 'lbm'), - 'mass_defect_ref': (140_000, 'lbm'), - 'distance_lower': (3000., 'NM'), - 'distance_upper': (5000., 'NM'), - 'distance_ref': (mission_distance, 'NM'), - 'distance_ref0': (0, 'NM'), - 'distance_defect_ref': (100, 'NM'), - }, - 'initial_guesses': { - 'mass': (136000., 'lbm'), - 'altitude': ([37.5e3, 10.e3], 'ft'), - 'throttle': ([0.0, 0.0], 'unitless'), - 'distance': ([.92*mission_distance, .96*mission_distance], 'NM'), - 'time': ([28000., 500.], 's'), - } - }, - 'desc2': { - 'user_options': { - 'num_segments': 1, - 'order': 7, - 'fix_initial': False, - 'input_initial': False, - 'EAS_limit': (250, 'kn'), - 'mach_cruise': 0.80, - 'input_speed_type': SpeedType.EAS, - 'final_altitude': (1000, 'ft'), - 'duration_bounds': ((100., 5000), 's'), - 'duration_ref': (500, 's'), - 'alt_lower': (500, 'ft'), - 'alt_upper': (11_000, 'ft'), - 'alt_ref': (10.e3, 'ft'), - 'alt_ref0': (1000, 'ft'), - 'alt_constraint_ref': (1000, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'NM'), - 'distance_upper': (5000, 'NM'), - 'distance_ref': (3500, 'NM'), - 'distance_defect_ref': (100, 'NM'), - }, - 'initial_guesses': { - 'mass': (136000., 'lbm'), - 'altitude': ([10.e3, 1.e3], 'ft'), - 'throttle': ([0., 0.], 'unitless'), - 'distance': ([.96*mission_distance, mission_distance], 'NM'), - 'time': ([28500., 500.], 's'), - } - }, -} - - -def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs): - """ - Modify the values in the phase_info dictionary to accomodate different values - for the following mission design inputs: cruise altitude, cruise mach number, - cruise range, design gross mass. - - Parameters - ---------- - phase_info : dict - Dictionary of phase settings for a mission profile - post_mission_info : dict - Dictionary of phase settings for a post mission profile - aviary_inputs : - Object containing values and units for all aviary inputs and options - - Returns - ------- - dict - Modified phase_info that has been changed to match the new mission - parameters - """ - - range_cruise = aviary_inputs.get_val(Mission.Design.RANGE, units='NM') - alt_cruise = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') - gross_mass = aviary_inputs.get_val(Mission.Design.GROSS_MASS, units='lbm') - mach_cruise = aviary_inputs.get_val(Mission.Design.MACH) - - # Range - old_range_cruise = phase_info['desc2']['initial_guesses']['distance'][0][1] - range_scale = 1.0 - if range_cruise != old_range_cruise: - - phase_info['desc1']['initial_guesses']['distance'] = \ - ([.92*range_cruise, .96*range_cruise], 'NM') - phase_info['desc2']['initial_guesses']['distance'] = \ - ([.96*range_cruise, range_cruise], 'NM') - range_scale = range_cruise / old_range_cruise - - # Altitude - old_alt_cruise = phase_info['climb2']['user_options']['final_altitude'][0] - if alt_cruise != old_alt_cruise: - - phase_info['climb2']['user_options']['final_altitude'] = (alt_cruise, 'ft') - phase_info['climb2']['initial_guesses']['altitude'] = ([10.e3, alt_cruise], 'ft') - phase_info['cruise']['initial_guesses']['altitude'] = (alt_cruise, 'ft') - phase_info['desc1']['initial_guesses']['altitude'] = ([alt_cruise, 10.e3], 'ft') - - # TODO - Could adjust time guesses/bounds in climb2 and desc2. - - # Mass - old_gross_mass = 175400.0 - if gross_mass != old_gross_mass: - - # Note, this requires that the guess for gross mass is pretty close to the - # compute mass. - - fuel_used = 35000 * range_scale - phase_info['groundroll']['initial_guesses']['mass'] = \ - ([gross_mass, gross_mass], 'lbm') - phase_info['rotation']['initial_guesses']['mass'] = \ - ([gross_mass, gross_mass], 'lbm') - phase_info['accel']['initial_guesses']['mass'] = \ - ([gross_mass, gross_mass], 'lbm') - phase_info['ascent']['initial_guesses']['mass'] = \ - ([gross_mass, gross_mass], 'lbm') - - phase_info['cruise']['initial_guesses']['mass'] = \ - ([gross_mass, -fuel_used], 'lbm') - - end_mass = gross_mass - fuel_used - phase_info['desc1']['initial_guesses']['mass'] = (end_mass, 'lbm') - phase_info['desc2']['initial_guesses']['mass'] = (end_mass, 'lbm') - - # Mach - old_mach_cruise = phase_info['cruise']['initial_guesses']['mach'][0] - if mach_cruise != old_mach_cruise: - - phase_info['cruise']['initial_guesses']['mach'] = (mach_cruise, 'unitless') - - return phase_info, post_mission_info diff --git a/aviary/interface/default_phase_info/two_dof_fiti.py b/aviary/interface/default_phase_info/two_dof_fiti.py deleted file mode 100644 index 0c4318f044..0000000000 --- a/aviary/interface/default_phase_info/two_dof_fiti.py +++ /dev/null @@ -1,208 +0,0 @@ -from aviary.mission.gasp_based.phases.time_integration_phases import SGMGroundroll, \ - SGMRotation, SGMAscentCombined, SGMAccel, SGMClimb, SGMCruise, SGMDescent -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import AlphaModes, SpeedType, Verbosity -from aviary.variable_info.variables import Aircraft, Mission, Dynamic, Settings - -# defaults for 2DOF based forward in time integeration phases -cruise_alt = 35e3, -cruise_mach = .8, - -takeoff_phases = { - 'groundroll': { - 'builder': SGMGroundroll, - 'user_options': { - # special case - 'attr:VR_value': ('SGMGroundroll_velocity_trigger', 'kn'), - }, - }, - 'rotation': { - 'builder': SGMRotation, - 'user_options': { - }, - }, - 'ascent': { - 'builder': SGMAscentCombined, - 'user_options': { - 't_init_gear': (10000, 's'), - 't_init_flaps': (10000, 's'), - # special case - 'rotation.start_rotation': (10000, 's'), - # special case - 'attr:fuselage_angle_max': (Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE, 'deg'), - }, - }, - 'accel': { - 'builder': SGMAccel, - 'user_options': { - }, - }, -} -climb_phases = { - 'climb1': { - 'kwargs': dict( - input_speed_type=SpeedType.EAS, - input_speed_units='kn', - speed_trigger_units='unitless', - ), - 'builder': SGMClimb, - 'user_options': { - 'alt_trigger': (10000, 'ft'), - 'EAS': (250, 'kn'), - 'speed_trigger': (cruise_mach, 'unitless'), - }, - }, - 'climb2': { - 'kwargs': dict( - input_speed_type=SpeedType.EAS, - input_speed_units='kn', - speed_trigger_units='unitless', - ), - 'builder': SGMClimb, - 'user_options': { - 'alt_trigger': (cruise_alt, 'ft'), - 'EAS': (270, 'kn'), - 'speed_trigger': (cruise_mach, 'unitless'), - }, - }, - 'climb3': { - 'kwargs': dict( - input_speed_type=SpeedType.MACH, - input_speed_units='unitless', - speed_trigger_units='kn', - ), - 'builder': SGMClimb, - 'user_options': { - 'alt_trigger': (cruise_alt, 'ft'), - 'mach': (cruise_mach, 'unitless'), - 'speed_trigger': (0, 'kn'), - }, - }, -} -ascent_phases = { - **takeoff_phases, - **climb_phases -} -cruise_phase = { - 'cruise': { - 'kwargs': dict( - input_speed_type=SpeedType.MACH, - input_speed_units="unitless", - alpha_mode=AlphaModes.REQUIRED_LIFT, - ), - 'builder': SGMCruise, - 'user_options': { - 'mach': (cruise_mach, 'unitless'), - 'attr:mass_trigger': ('SGMCruise_mass_trigger', 'lbm') - }, - }, -} -descent_phases = { - 'desc1': { - 'kwargs': dict( - input_speed_type=SpeedType.MACH, - input_speed_units='unitless', - speed_trigger_units='kn', - ), - 'builder': SGMDescent, - 'user_options': { - 'alt_trigger': (10000, 'ft'), - 'mach': (cruise_mach, 'unitless'), - 'speed_trigger': (350, 'kn'), - Dynamic.Mission.THROTTLE: (0, 'unitless'), - }, - 'descent_phase': True, - }, - 'desc2': { - 'kwargs': dict( - input_speed_type=SpeedType.EAS, - input_speed_units='kn', - speed_trigger_units='kn', - ), - 'builder': SGMDescent, - 'user_options': { - 'alt_trigger': (10000, 'ft'), - 'EAS': (350, 'kn'), - 'speed_trigger': (0, 'kn'), - Dynamic.Mission.THROTTLE: (0, 'unitless'), - }, - 'descent_phase': True, - }, - 'desc3': { - 'kwargs': dict( - input_speed_type=SpeedType.EAS, - input_speed_units='kn', - speed_trigger_units='kn', - ), - 'builder': SGMDescent, - 'user_options': { - 'alt_trigger': (1000, 'ft'), - 'EAS': (250, 'kn'), - 'speed_trigger': (0, 'kn'), - Dynamic.Mission.THROTTLE: (0, 'unitless'), - }, - 'descent_phase': True, - }, -} - -phase_info = { - **ascent_phases, - **cruise_phase, - **descent_phases, -} - - -def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs: AviaryValues): - """ - Modify the values in the phase_info dictionary to accomodate different values - for the following mission design inputs: cruise altitude, cruise mach number, - cruise range, design gross mass. - - Parameters - ---------- - phase_info : dict - Dictionary of phase settings for a mission profile - aviary_inputs : - Object containing values and units for all aviary inputs and options - - Returns - ------- - dict - Modified phase_info that has been changed to match the new mission - parameters - """ - - range_cruise = aviary_inputs.get_item(Mission.Design.RANGE) - alt_cruise = aviary_inputs.get_item(Mission.Design.CRUISE_ALTITUDE) - gross_mass = aviary_inputs.get_item(Mission.Design.GROSS_MASS) - mach_cruise = aviary_inputs.get_item(Mission.Design.MACH) - - phase_info['climb1']['user_options']['speed_trigger'] = mach_cruise - - phase_info['climb2']['user_options']['alt_trigger'] = alt_cruise - phase_info['climb2']['user_options']['speed_trigger'] = mach_cruise - - phase_info['climb3']['user_options']['alt_trigger'] = alt_cruise - phase_info['climb3']['user_options']['mach'] = mach_cruise - - phase_info['cruise']['user_options']['mach'] = mach_cruise - - phase_info['desc1']['user_options']['mach'] = mach_cruise - - return phase_info, post_mission_info - - -def add_default_sgm_args(phase_info: dict, ode_args: dict, verbosity=None): - """ - Add default SGM arguments to phase_info - """ - for phase_name, info in phase_info.items(): - kwargs = info.get('kwargs', {}) - if 'ode_args' not in kwargs: - kwargs['ode_args'] = ode_args - if 'simupy_args' not in kwargs: - if verbosity is None: - verbosity, _ = ode_args['aviary_options'].get_item( - Settings.VERBOSITY, default=(Verbosity.QUIET, 'unitless')) - kwargs['simupy_args'] = {'verbosity': verbosity} - info['kwargs'] = kwargs diff --git a/aviary/interface/default_phase_info/two_dof_fiti_deprecated.py b/aviary/interface/default_phase_info/two_dof_fiti_deprecated.py deleted file mode 100644 index 573e4412da..0000000000 --- a/aviary/interface/default_phase_info/two_dof_fiti_deprecated.py +++ /dev/null @@ -1,196 +0,0 @@ -import warnings - -from aviary.variable_info.enums import SpeedType, Verbosity -from aviary.mission.gasp_based.phases.time_integration_phases import SGMGroundroll, \ - SGMRotation, SGMAscentCombined, SGMAccel, SGMClimb, SGMCruise, SGMDescent -from aviary.variable_info.variables import Aircraft, Mission, Dynamic - -# defaults for 2DOF based forward in time integeration phases - - -def create_2dof_based_ascent_phases( - ode_args, - cruise_alt=35e3, - cruise_mach=.8, - simupy_args=dict( - verbosity=Verbosity.QUIET, - ), -): - - warnings.warn("`descent_range_and_fuel` has been replaced with `add_descent_estimation_as_submodel`" - "\nThe new methodology uses a phase_info that more closely matches that of collocation", - DeprecationWarning) - - groundroll_kwargs = dict( - ode_args=ode_args, - simupy_args=simupy_args, - ) - groundroll_vals = { - # special case - 'attr:VR_value': {'val': 'SGMGroundroll_velocity_trigger', 'units': 'kn'}, - } - - rotation_kwargs = dict( - ode_args=ode_args, - simupy_args=simupy_args, - ) - rotation_vals = {} - - ascent_kwargs = dict( - ode_args=ode_args, - simupy_args=simupy_args, - ) - ascent_vals = { - 't_init_gear': {'val': 10000, 'units': 's'}, - 't_init_flaps': {'val': 10000, 'units': 's'}, - 'rotation.start_rotation': {'val': 10000, 'units': 's'}, # special case - # special case - 'attr:fuselage_angle_max': {'val': Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE, 'units': 'deg'}, - } - - accel_kwargs = dict( - ode_args=ode_args, - simupy_args=simupy_args, - ) - accel_vals = {} - - # need to set trigger units - climb1_kwargs = dict( - input_speed_type=SpeedType.EAS, - input_speed_units='kn', - ode_args=ode_args, - simupy_args=simupy_args, - ) - climb1_vals = { - 'alt_trigger': {'val': 10000, 'units': 'ft'}, - 'EAS': {'val': 250, 'units': climb1_kwargs['input_speed_units']}, - 'speed_trigger': {'val': cruise_mach, 'units': None}, - } - - climb2_kwargs = dict( - input_speed_type=SpeedType.EAS, - input_speed_units='kn', - ode_args=ode_args, - simupy_args=simupy_args, - ) - climb2_vals = { - 'alt_trigger': {'val': cruise_alt, 'units': 'ft'}, - 'EAS': {'val': 270, 'units': climb2_kwargs['input_speed_units']}, - 'speed_trigger': {'val': cruise_mach, 'units': None}, - } - - climb3_kwargs = dict( - input_speed_type=SpeedType.MACH, - input_speed_units='unitless', - ode_args=ode_args, - simupy_args=simupy_args, - ) - climb3_vals = { - 'alt_trigger': {'val': cruise_alt, 'units': 'ft'}, - 'mach': {'val': cruise_mach, 'units': climb3_kwargs['input_speed_units']}, - 'speed_trigger': {'val': 0, 'units': None}, - } - - phases = { - 'groundroll': { - 'ode': SGMGroundroll(**groundroll_kwargs), - 'vals_to_set': groundroll_vals, - }, - 'rotation': { - 'ode': SGMRotation(**rotation_kwargs), - 'vals_to_set': rotation_vals, - }, - 'ascent': { - 'ode': SGMAscentCombined(**ascent_kwargs), - 'vals_to_set': ascent_vals, - }, - 'accel': { - 'ode': SGMAccel(**accel_kwargs), - 'vals_to_set': accel_vals, - }, - 'climb1': { - 'ode': SGMClimb(**climb1_kwargs), - 'vals_to_set': climb1_vals, - }, - 'climb2': { - 'ode': SGMClimb(**climb2_kwargs), - 'vals_to_set': climb2_vals, - }, - 'climb3': { - 'ode': SGMClimb(**climb3_kwargs), - 'vals_to_set': climb3_vals, - }, - - } - - return phases - - -def create_2dof_based_descent_phases( - ode_args, - cruise_mach=.8, - simupy_args=dict( - verbosity=Verbosity.QUIET, - ), -): - - warnings.warn("`descent_range_and_fuel` has been replaced with `add_descent_estimation_as_submodel`" - "\nThe new methodology uses a phase_info that more closely matches that of collocation", - DeprecationWarning) - - descent1_kwargs = dict( - input_speed_type=SpeedType.MACH, - input_speed_units="unitless", - speed_trigger_units='kn', - ode_args=ode_args, - simupy_args=simupy_args, - ) - descent1_vals = { - 'alt_trigger': {'val': 10000, 'units': 'ft'}, - 'mach': {'val': cruise_mach, 'units': descent1_kwargs['input_speed_units']}, - 'speed_trigger': {'val': 350, 'units': descent1_kwargs['speed_trigger_units']}, - } - - descent2_kwargs = dict( - input_speed_type=SpeedType.EAS, - input_speed_units="kn", - speed_trigger_units='kn', - ode_args=ode_args, - simupy_args=simupy_args, - ) - descent2_vals = { - 'alt_trigger': {'val': 10000, 'units': 'ft'}, - 'EAS': {'val': 350, 'units': descent2_kwargs['input_speed_units']}, - 'speed_trigger': {'val': 0, 'units': descent2_kwargs['speed_trigger_units']}, - } - - descent3_kwargs = dict( - input_speed_type=SpeedType.EAS, - input_speed_units="kn", - speed_trigger_units='kn', - ode_args=ode_args, - simupy_args=simupy_args, - ) - descent3_vals = { - 'alt_trigger': {'val': 1000, 'units': 'ft'}, - 'EAS': {'val': 250, 'units': descent3_kwargs['input_speed_units']}, - 'speed_trigger': {'val': 0, 'units': descent3_kwargs['speed_trigger_units']}, - } - - phases = { - 'descent1': { - 'ode': SGMDescent(**descent1_kwargs), - 'vals_to_set': descent1_vals, - }, - 'descent2': { - 'ode': SGMDescent(**descent2_kwargs), - 'vals_to_set': descent2_vals, - }, - 'descent3': { - 'ode': SGMDescent(**descent3_kwargs), - 'vals_to_set': descent3_vals, - }, - - } - - return phases diff --git a/aviary/interface/download_models.py b/aviary/interface/download_models.py index e35df71b23..882a2d8474 100644 --- a/aviary/interface/download_models.py +++ b/aviary/interface/download_models.py @@ -1,14 +1,13 @@ -import os -from pathlib import Path import argparse +import os import shutil +from pathlib import Path + from aviary.utils.functions import get_model def save_file(aviary_path: Path, outdir: Path, verbose=False) -> Path: - ''' - Saves the file or folder specified into the output directory, creating directories as needed. - ''' + """Saves the file or folder specified into the output directory, creating directories as needed.""" outdir.mkdir(parents=True, exist_ok=True) if aviary_path.is_dir(): if verbose: @@ -27,24 +26,32 @@ def save_file(aviary_path: Path, outdir: Path, verbose=False) -> Path: def _setup_hangar_parser(parser: argparse.ArgumentParser): - def_outdir = os.path.join(os.getcwd(), "aviary_models") + def_outdir = os.path.join(os.getcwd(), 'aviary_models') parser.add_argument( - 'input_decks', metavar='indecks', type=str, nargs='+', help='Name of file or folder to download from Aviary/models' + 'input_decks', + metavar='indecks', + type=str, + nargs='+', + help='Name of file or folder to download from Aviary/models', ) parser.add_argument( - "-o", "--outdir", default=def_outdir, help="Directory to write outputs. Defaults to aviary_models in the current directory." + '-o', + '--outdir', + default=def_outdir, + help='Directory to write outputs. Defaults to aviary_models in the current directory.', ) parser.add_argument( - "-v", "--verbose", - action="store_true", - help="Enable verbose outputs", + '-v', + '--verbose', + action='store_true', + help='Enable verbose outputs', ) def _exec_hangar(args, user_args): input_decks = [] for input_deck in args.input_decks: - input_decks.append(get_model(input_deck, args.verbose)) + input_decks.append(get_model(input_deck)) for input_deck in input_decks: save_file(input_deck, Path(args.outdir), args.verbose) diff --git a/aviary/interface/graphical_input.py b/aviary/interface/graphical_input.py index b9fda18bfb..0d0bdfc152 100644 --- a/aviary/interface/graphical_input.py +++ b/aviary/interface/graphical_input.py @@ -1,18 +1,18 @@ +import importlib.util # used for opening existing phase info file +import json import os +import platform +import pprint import shutil import subprocess -import json -import platform -import importlib.util # used for opening existing phase info file -import numpy as np - import tkinter as tk # base tkinter import tkinter.ttk as ttk # used for combobox -from tkinter import filedialog, messagebox, font +from tkinter import filedialog, font, messagebox -from matplotlib.figure import Figure -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +import numpy as np from matplotlib.backend_bases import MouseButton +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.figure import Figure # used for unit conversion of numerical data from openmdao.utils.units import convert_units @@ -53,8 +53,7 @@ def __init__(self, parent, *args, **kw): self.freezeframe_bottom = tk.Frame(self) self.freezeframe_bottom.pack(side='bottom', fill='x') - canvas = tk.Canvas(self, bd=0, highlightthickness=0, - yscrollcommand=vscrollbar.set) + canvas = tk.Canvas(self, bd=0, highlightthickness=0, yscrollcommand=vscrollbar.set) canvas.pack(side='left', fill='y', expand=True) self.vscroll_canvas = canvas vscrollbar.config(command=canvas.yview) @@ -65,75 +64,82 @@ def __init__(self, parent, *args, **kw): # Create a frame inside the canvas which will be scrolled with it. self.interior = interior = tk.Frame(canvas) - interior_id = canvas.create_window(0, 0, window=interior, - anchor='nw') + interior_id = canvas.create_window(0, 0, window=interior, anchor='nw') # Track changes to the canvas and frame width and sync them, # also updating the scrollbar. def _configure_interior(event): # Update the scrollbars to match the size of the inner frame. size = (interior.winfo_reqwidth(), interior.winfo_reqheight()) - canvas.config(scrollregion="0 0 %s %s" % size) + canvas.config(scrollregion='0 0 %s %s' % size) if interior.winfo_reqwidth() != canvas.winfo_width(): # Update the canvas's width to fit the inner frame. canvas.config(width=interior.winfo_reqwidth()) + interior.bind('', _configure_interior) def _configure_canvas(event): if interior.winfo_reqwidth() != canvas.winfo_width(): # Update the inner frame's width to fill the canvas. canvas.itemconfigure(interior_id, width=canvas.winfo_width()) + canvas.bind('', _configure_canvas) class AviaryMissionEditor(tk.Tk): - """ - Aviary mission editor class - """ + """Aviary mission editor class.""" def __init__(self): - screen_width, screen_height = \ - [int(x) for x in get_screen_geometry().split("+")[0].split("x")] + screen_width, screen_height = [ + int(x) for x in get_screen_geometry().split('+')[0].split('x') + ] super().__init__() self.title('Mission Design Utility') - self.protocol("WM_DELETE_WINDOW", self.close_window) - self.macOS = platform.system() == "Darwin" - self.default_font = font.nametofont("TkDefaultFont") + self.protocol('WM_DELETE_WINDOW', self.close_window) + self.macOS = platform.system() == 'Darwin' + self.default_font = font.nametofont('TkDefaultFont') # used by labels, buttons self.default_font.configure(size=12 if self.macOS else 10) - font.nametofont("TkTextFont").configure( - size=12 if self.macOS else 10) # used by entries + font.nametofont('TkTextFont').configure(size=12 if self.macOS else 10) # used by entries # ------ # theme related initializations - self.theme = "light" - self.pallete = {"light": {'background_primary': '#ffffff', - 'foreground_primary': '#000000', - 'foreground_secondary': '#999999', - 'crosshair': '#EE0000', - 'lines': ['#0209c6', '#aa00aa'], - 'image': 'dark_mode.png', - 'hover': '#63ebeb'}, - "dark": {'background_primary': '#1e1e1e', - 'foreground_primary': '#FEFEFE', - 'foreground_secondary': '#CCCCCC', - 'crosshair': '#EE0000', - 'lines': ['#00b6f2', '#ffff00'], - 'image': 'light_mode.png', - 'hover': '#007acc'}} + self.theme = 'light' + self.pallete = { + 'light': { + 'background_primary': '#ffffff', + 'foreground_primary': '#000000', + 'foreground_secondary': '#999999', + 'crosshair': '#EE0000', + 'lines': ['#0209c6', '#aa00aa'], + 'image': 'dark_mode.png', + 'hover': '#63ebeb', + }, + 'dark': { + 'background_primary': '#1e1e1e', + 'foreground_primary': '#FEFEFE', + 'foreground_secondary': '#CCCCCC', + 'crosshair': '#EE0000', + 'lines': ['#00b6f2', '#ffff00'], + 'image': 'light_mode.png', + 'hover': '#007acc', + }, + } self.style_combobox = ttk.Style() - self.style_combobox.theme_use("alt") + self.style_combobox.theme_use('alt') # updates image object inside pallete with PhotoImage object using absolute filepath self.source_directory = os.path.abspath(os.path.dirname(__file__)) for theme_info in self.pallete.values(): - theme_info["image"] = tk.PhotoImage( + theme_info['image'] = tk.PhotoImage( file=os.path.join( - self.source_directory, "mac_theme.png" - if self.macOS else theme_info["image"])) + self.source_directory, + 'static', + 'mac_theme.png' if self.macOS else theme_info['image'], + ) + ) # stores/retrieves persistent settings in source directory - self.persist_filename = os.path.join( - self.source_directory, "persist_settings.json") + self.persist_filename = os.path.join(self.source_directory, 'persist_settings.json') # ------ # window geometry definition @@ -149,24 +155,28 @@ def __init__(self): if os.path.exists(self.persist_filename): # a file will only exist if at a previous point user wanted to store settings self.store_settings.set(True) - with open(self.persist_filename, "r") as fp: + with open(self.persist_filename, 'r') as fp: persist_settings = json.load(fp) window_geometry = persist_settings['window_geometry'] self.theme = persist_settings['theme'] else: - default_win_size = (max(min_win_size[0], int(screen_width/2)), - max(min_win_size[1], int(screen_height/2))) - default_location = (int((screen_width-default_win_size[0])/2), 0) - window_geometry = f"{default_win_size[0]}x{default_win_size[1]}+" +\ - f"{default_location[0]}+{default_location[1]}" + default_win_size = ( + max(min_win_size[0], int(screen_width / 2)), + max(min_win_size[1], int(screen_height / 2)), + ) + default_location = (int((screen_width - default_win_size[0]) / 2), 0) + window_geometry = ( + f'{default_win_size[0]}x{default_win_size[1]}+' + + f'{default_location[0]}+{default_location[1]}' + ) self.geometry(window_geometry) # Set the window icon, provides 2 sizes of logos to prevent blurry icons self.iconphoto( - False, tk.PhotoImage( - file=os.path.join(self.source_directory, "aviary_logo_16.png")), - tk.PhotoImage( - file=os.path.join(self.source_directory, "aviary_logo_32.png"))) + False, + tk.PhotoImage(file=os.path.join(self.source_directory, 'static', 'aviary_logo_16.png')), + tk.PhotoImage(file=os.path.join(self.source_directory, 'static', 'aviary_logo_32.png')), + ) # ------ # create window layout with frames for containing graph, table, and scrollbar @@ -185,24 +195,26 @@ def __init__(self): # Main definition of data which can be plotted/tabulated. Assumes single # independent variable followed by any number of dependent variables. # Plot titles inform the program of number of dependent variables. - self.data_info = {"plot_titles": ["Altitude Profile", "Mach Profile"], - "labels": ["Time", "Altitude", "Mach"], - "units": ["min", "ft", "unitless"], - "limits": [400, 50e3, 1.0], - "rounding": [0, 0, 2]} + self.data_info = { + 'plot_titles': ['Altitude Profile', 'Mach Profile'], + 'labels': ['Time', 'Altitude', 'Mach'], + 'units': ['min', 'ft', 'unitless'], + 'limits': [400, 50e3, 1.0], + 'rounding': [0, 0, 2], + } self.advanced_options = { - "constrain_range": tk.BooleanVar(value=True), - "solve_for_distance": tk.BooleanVar(), - "include_takeoff": tk.BooleanVar(), - "include_landing": tk.BooleanVar(), - "polynomial_control_order": tk.IntVar(value=1)} + 'constrain_range': tk.BooleanVar(value=True), + 'distance_solve_segments': tk.BooleanVar(), + 'include_takeoff': tk.BooleanVar(), + 'include_landing': tk.BooleanVar(), + 'polynomial_order': tk.IntVar(value=1), + } self.check_data_info() # sanity checking of data_info dict # replace constants with stringvars which can be updated within the GUI by the user - for key in ["units", "limits", "rounding"]: - self.data_info[key] = [tk.StringVar(value=item) - for item in self.data_info[key]] + for key in ['units', 'limits', 'rounding']: + self.data_info[key] = [tk.StringVar(value=item) for item in self.data_info[key]] # starting mach is hardcoded as 0.3 b/c Aviary models are not suitable for very low mach self.data = [[0], [0], [0.3]] @@ -211,27 +223,30 @@ def __init__(self): # internal variables to remember mouse state self.mouse_drag, self.mouse_press = False, False - self.ptcontainer = 0.04 # percent of plot size, boundary around point where it can be dragged + self.ptcontainer = ( + 0.04 # percent of plot size, boundary around point where it can be dragged + ) self.popup = None self.show_optimize = tk.BooleanVar() # controls display of optimize phase checkboxes # controls display of phase info (climb/descent rates) self.show_phase_slope = tk.BooleanVar() - self.theme_button = tk.Button(self, - image=self.pallete[self.theme]["image"], font=( - 'Arial', 8), - command=lambda: self.update_theme(toggle=True)) + self.theme_button = tk.Button( + self, + image=self.pallete[self.theme]['image'], + font=('Arial', 8), + command=lambda: self.update_theme(toggle=True), + ) # to prevent lose of image reference from garbage collector - self.theme_button.image = self.pallete[self.theme]["image"] - self.theme_button.bind("", func=self.on_enter) - self.theme_button.bind("", func=self.on_leave) + self.theme_button.image = self.pallete[self.theme]['image'] + self.theme_button.bind('', func=self.on_enter) + self.theme_button.bind('', func=self.on_leave) self.theme_button.place(anchor='sw', relx=0, rely=1.0) - self.output_phase_info_button = tk.Button( - self, text="Output Phase Info", command=self.save) - self.output_phase_info_button.bind("", func=self.on_enter) - self.output_phase_info_button.bind("", func=self.on_leave) + self.output_phase_info_button = tk.Button(self, text='Output Phase Info', command=self.save) + self.output_phase_info_button.bind('', func=self.on_enter) + self.output_phase_info_button.bind('', func=self.on_leave) self.output_phase_info_button.place(relx=0, rely=0, anchor='nw') self.save_option_defaults() @@ -244,36 +259,38 @@ def __init__(self): def save_option_defaults(self): """Saves default values for advanced options and axes limits, these will be referenced - if user chooses to reset advanced options or axes limits""" - + if user chooses to reset advanced options or axes limits. + """ self.advanced_options_defaults = {} for key, item in self.advanced_options.items(): self.advanced_options_defaults[key] = item.get() self.data_info_defaults = {} for key, item in self.data_info.items(): - if key == "units" or key == "limits" or key == "rounding": + if key == 'units' or key == 'limits' or key == 'rounding': self.data_info_defaults[key] = [element for element in item] def check_data_info(self): - """Verifies data_info dict has consistent number of dependent variables """ - self.num_dep_vars = len(self.data_info["plot_titles"]) + """Verifies data_info dict has consistent number of dependent variables.""" + self.num_dep_vars = len(self.data_info['plot_titles']) for key, item in self.data_info.items(): - if key != "plot_titles": + if key != 'plot_titles': if len(item) != self.num_dep_vars + 1: raise Exception( - f"Check data_info dictionary, expected {self.num_dep_vars+1} elements inside {key}.") + f'Check data_info dictionary, expected {self.num_dep_vars + 1} elements inside {key}.' + ) def update_list(self, value, index, axis): - """Updates internal data lists based on row,col values. col corresponds - to dependent/independent variable. row corresponds to point number.""" + """Updates internal data lists based on row,col values. col corresponds + to dependent/independent variable. row corresponds to point number. + """ try: value = float(value) except (ValueError, TypeError): - self.point_warning_strvar.set("Invalid table entry!") + self.point_warning_strvar.set('Invalid table entry!') return # skip updating if value is not convertible to a float if value < 0: - self.point_warning_strvar.set("Table entries must be positive values!") + self.point_warning_strvar.set('Table entries must be positive values!') return # skip updating negative values if index == len(self.data[0]): self.data[axis].append(value) @@ -282,104 +299,118 @@ def update_list(self, value, index, axis): self.phase_order_list.append(self.phase_order_default) else: self.data[axis][index] = value - self.point_warning_strvar.set("") + self.point_warning_strvar.set('') def update_theme(self, toggle=False): - """Called by theme toggle button and start of app, changes color settings for widgets - based on current theme.""" + """Called by theme toggle button and start of app, changes color settings for widgets + based on current theme. + """ if toggle: - self.theme = "light" if self.theme == "dark" else "dark" + self.theme = 'light' if self.theme == 'dark' else 'dark' # this command sets options for all the widgets self.tk_setPalette( - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"], - insertBackground=self.pallete[self.theme]["foreground_primary"], - highlightBackground=self.pallete[self.theme]["background_primary"], - highlightColor=self.pallete[self.theme]["background_primary"], - activeForeground=self.pallete[self.theme]["foreground_primary"], - activeBackground=self.pallete[self.theme]["background_primary"], - selectColor=self.pallete[self.theme]["background_primary"]) + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + insertBackground=self.pallete[self.theme]['foreground_primary'], + highlightBackground=self.pallete[self.theme]['background_primary'], + highlightColor=self.pallete[self.theme]['background_primary'], + activeForeground=self.pallete[self.theme]['foreground_primary'], + activeBackground=self.pallete[self.theme]['background_primary'], + selectColor=self.pallete[self.theme]['background_primary'], + ) if not self.macOS: self.create_menu() # recreating menu b/c tkinter menus cannot be reconfigured with new colors # update table header color, different from background - self.frame_tableheaders.configure(background=self.pallete[self.theme]["hover"]) + self.frame_tableheaders.configure(background=self.pallete[self.theme]['hover']) self.frame_plot_table_border.configure( - highlightbackground=self.pallete[self.theme]["foreground_primary"]) + highlightbackground=self.pallete[self.theme]['foreground_primary'] + ) for widget in self.table_header_widgets: - widget.configure(background=self.pallete[self.theme]["hover"]) - widget.configure(foreground=self.pallete[self.theme]["foreground_primary"]) + widget.configure(background=self.pallete[self.theme]['hover']) + widget.configure(foreground=self.pallete[self.theme]['foreground_primary']) if isinstance(widget, tk.Entry): - widget.configure(readonlybackground=self.pallete[self.theme]["hover"]) + widget.configure(readonlybackground=self.pallete[self.theme]['hover']) - self.fig.set_facecolor(self.pallete[self.theme]["background_primary"]) + self.fig.set_facecolor(self.pallete[self.theme]['background_primary']) for plot in self.plots: - plot.set_facecolor(self.pallete[self.theme]["background_primary"]) - plot.yaxis.label.set_color(self.pallete[self.theme]["foreground_primary"]) - plot.xaxis.label.set_color(self.pallete[self.theme]["foreground_primary"]) - plot.title.set_color(self.pallete[self.theme]["foreground_primary"]) + plot.set_facecolor(self.pallete[self.theme]['background_primary']) + plot.yaxis.label.set_color(self.pallete[self.theme]['foreground_primary']) + plot.xaxis.label.set_color(self.pallete[self.theme]['foreground_primary']) + plot.title.set_color(self.pallete[self.theme]['foreground_primary']) plot.grid(True, color=self.pallete[self.theme]['foreground_secondary']) for axis in ['x', 'y']: - plot.tick_params( - axis=axis, colors=self.pallete[self.theme]["foreground_primary"]) + plot.tick_params(axis=axis, colors=self.pallete[self.theme]['foreground_primary']) for spine in ['left', 'top', 'right', 'bottom']: - plot.spines[spine].set_color( - self.pallete[self.theme]['foreground_secondary']) + plot.spines[spine].set_color(self.pallete[self.theme]['foreground_secondary']) for text_list in self.plot_texts: for text in text_list: - text.set(color=self.pallete[self.theme]["foreground_primary"]) + text.set(color=self.pallete[self.theme]['foreground_primary']) self.redraw_plot() # updating combobox colors - self.option_add("*TCombobox*Listbox*Background", - self.pallete[self.theme]["background_primary"]) - self.option_add("*TCombobox*Listbox*Foreground", - self.pallete[self.theme]["foreground_primary"]) - self.option_add('*TCombobox*Listbox*selectBackground', - self.pallete[self.theme]["hover"]) - self.option_add('*TCombobox*Listbox*selectForeground', - self.pallete[self.theme]["foreground_primary"]) - self.style_combobox.map('TCombobox', fieldbackground=[( - 'readonly', self.pallete[self.theme]["background_primary"])]) - self.style_combobox.map('TCombobox', selectbackground=[( - 'readonly', self.pallete[self.theme]["background_primary"])]) - self.style_combobox.map('TCombobox', selectforeground=[( - 'readonly', self.pallete[self.theme]["foreground_primary"])]) - self.style_combobox.map('TCombobox', background=[( - 'readonly', self.pallete[self.theme]["hover"])]) - self.style_combobox.map('TCombobox', foreground=[( - 'readonly', self.pallete[self.theme]["foreground_primary"])]) - - self.theme_button.configure(image=self.pallete[self.theme]["image"], - bg=self.pallete[self.theme]["background_primary"]) - self.theme_button.image = self.pallete[self.theme]["image"] + self.option_add( + '*TCombobox*Listbox*Background', self.pallete[self.theme]['background_primary'] + ) + self.option_add( + '*TCombobox*Listbox*Foreground', self.pallete[self.theme]['foreground_primary'] + ) + self.option_add('*TCombobox*Listbox*selectBackground', self.pallete[self.theme]['hover']) + self.option_add( + '*TCombobox*Listbox*selectForeground', self.pallete[self.theme]['foreground_primary'] + ) + self.style_combobox.map( + 'TCombobox', + fieldbackground=[('readonly', self.pallete[self.theme]['background_primary'])], + ) + self.style_combobox.map( + 'TCombobox', + selectbackground=[('readonly', self.pallete[self.theme]['background_primary'])], + ) + self.style_combobox.map( + 'TCombobox', + selectforeground=[('readonly', self.pallete[self.theme]['foreground_primary'])], + ) + self.style_combobox.map( + 'TCombobox', background=[('readonly', self.pallete[self.theme]['hover'])] + ) + self.style_combobox.map( + 'TCombobox', foreground=[('readonly', self.pallete[self.theme]['foreground_primary'])] + ) + + self.theme_button.configure( + image=self.pallete[self.theme]['image'], + bg=self.pallete[self.theme]['background_primary'], + ) + self.theme_button.image = self.pallete[self.theme]['image'] self.output_phase_info_button.configure( - bg=self.pallete[self.theme]["background_primary"], - fg=self.pallete["light" if self.macOS else self.theme] - ["foreground_primary"]) + bg=self.pallete[self.theme]['background_primary'], + fg=self.pallete['light' if self.macOS else self.theme]['foreground_primary'], + ) if self.macOS: # macOS does not support button background color change with Tkinter, so maintain foreground color - self.table_add_button.configure( - foreground=self.pallete["light"]["foreground_primary"]) + self.table_add_button.configure(foreground=self.pallete['light']['foreground_primary']) for widget in self.table_widgets: if isinstance(widget, tk.Button): - widget.configure( - foreground=self.pallete["light"]["foreground_primary"]) + widget.configure(foreground=self.pallete['light']['foreground_primary']) -# ---------------------- -# Plot related functions + # ---------------------- + # Plot related functions def create_plots(self): - """Creates subplots according to data_info dict. Sets labels and limits. - Ties mouse events to appropriate internal functions.""" + """Creates subplots according to data_info dict. Sets labels and limits. + Ties mouse events to appropriate internal functions. + """ self.fig = Figure() self.plots = [] self.plot_texts = [[] for _ in range(self.num_dep_vars)] for i in range(self.num_dep_vars): - self.plots.append(self.fig.add_subplot( - self.num_dep_vars, 1, i+1, - title=self.data_info["plot_titles"][i])) + self.plots.append( + self.fig.add_subplot( + self.num_dep_vars, 1, i + 1, title=self.data_info['plot_titles'][i] + ) + ) for plot in self.plots: self.crossX = plot.axhline(y=0) self.crossY = plot.axvline(x=0) @@ -393,9 +424,8 @@ def create_plots(self): self.figure_canvas = FigureCanvasTkAgg(self.fig, master=self.frame_plots) self.figure_canvas.draw() - self.mouse_coords_str = tk.StringVar(value="Mouse Coordinates") - self.mouse_coords = tk.Label( - self.frame_plotReadouts, textvariable=self.mouse_coords_str) + self.mouse_coords_str = tk.StringVar(value='Mouse Coordinates') + self.mouse_coords = tk.Label(self.frame_plotReadouts, textvariable=self.mouse_coords_str) self.mouse_coords.pack() self.crosshair = False self.figure_canvas.get_tk_widget().pack(expand=True, fill='both') @@ -403,48 +433,55 @@ def create_plots(self): def update_axes(self, units=False, limits=False, refresh=False): for i, plot in enumerate(self.plots): if units: - xlabel = f"{self.data_info['labels'][0]} ({self.data_info['units'][0].get()})" - ylabel = f"{self.data_info['labels'][i+1]} ({self.data_info['units'][i+1].get()})" + xlabel = f'{self.data_info["labels"][0]} ({self.data_info["units"][0].get()})' + ylabel = ( + f'{self.data_info["labels"][i + 1]} ({self.data_info["units"][i + 1].get()})' + ) plot.set(xlabel=xlabel, ylabel=ylabel) if limits: - xlim = (0, float(self.data_info["limits"][0].get())) - ylim = (0, float(self.data_info["limits"][i+1].get())) + xlim = (0, float(self.data_info['limits'][0].get())) + ylim = (0, float(self.data_info['limits'][i + 1].get())) plot.set(xlim=xlim, ylim=ylim) if refresh: self.figure_canvas.draw() def redraw_plot(self): - """Redraws plot, using the new values inside data lists""" + """Redraws plot, using the new values inside data lists.""" self.clear_plot() for i, plot in enumerate(self.plots): - plot.plot(self.data[0], self.data[i+1], - color=self.pallete[self.theme]['lines'][i], - marker='o', markersize=5) + plot.plot( + self.data[0], + self.data[i + 1], + color=self.pallete[self.theme]['lines'][i], + marker='o', + markersize=5, + ) if self.show_phase_slope.get(): self.toggle_phase_slope(redraw=False) self.figure_canvas.draw() if len(self.data[0]) > 1: - units = [ - self.data_info["units"][i].get() - for i in range(len(self.data_info["units"]))] + units = [self.data_info['units'][i].get() for i in range(len(self.data_info['units']))] est_range, range_unit = estimate_total_range_trapezoidal( - times=self.data[0], mach_numbers=self.data[2], units=units) - self.mouse_coords_str.set(self.mouse_coords_str.get().split(" | Est")[0] + - f" | Estimated Range: {est_range} {range_unit}") + times=self.data[0], mach_numbers=self.data[2], units=units + ) + self.mouse_coords_str.set( + self.mouse_coords_str.get().split(' | Est')[0] + + f' | Estimated Range: {est_range} {range_unit}' + ) def clear_plot(self): - """Clears all lines from plots except for crosshairs""" + """Clears all lines from plots except for crosshairs.""" for plot in self.plots: for line in plot.lines: if line == self.crossX or line == self.crossY: continue line.remove() -# ---------------------- -# Mouse related functions + # ---------------------- + # Mouse related functions def on_mouse_press(self, event): - """Handles mouse press event, sets internal mouse state""" + """Handles mouse press event, sets internal mouse state.""" self.mouse_press = True def on_mouse_release(self, event): @@ -456,9 +493,9 @@ def on_mouse_release(self, event): self.mouse_press, self.mouse_drag = False, False def on_mouse_click(self, event): - """Called when mouse click is determined, adds new point if it is valid""" + """Called when mouse click is determined, adds new point if it is valid.""" # this list creates default values for subplots not clicked on, half of ylim - default_y_vals = [float(lim.get())/2 for lim in self.data_info["limits"][1:]] + default_y_vals = [float(lim.get()) / 2 for lim in self.data_info['limits'][1:]] valid_click = False # if mouse click points are not None if event.xdata and event.ydata and event.button == MouseButton.LEFT: @@ -466,7 +503,8 @@ def on_mouse_click(self, event): for plot_idx, plot in enumerate(self.plots): # checks if mouse is inside subplot and it is the first point or next in time if event.inaxes == plot and ( - len(self.data[0]) < 1 or event.xdata > max(self.data[0])): + len(self.data[0]) < 1 or event.xdata > max(self.data[0]) + ): valid_click = True break # once we know a subplot was clicked inside at a valid location @@ -475,8 +513,9 @@ def on_mouse_click(self, event): for y_idx, default_val in enumerate(default_y_vals): self.update_list( index=len(self.data[0]), - axis=y_idx + 1, value=event.ydata - if plot_idx == y_idx else default_val) + axis=y_idx + 1, + value=event.ydata if plot_idx == y_idx else default_val, + ) valid_click = False # update plots and tables after having changed the lists self.redraw_plot() @@ -484,8 +523,9 @@ def on_mouse_click(self, event): def on_mouse_move(self, event): """Handles functionality related to mouse movement. Creates crosshair if mouse is inside - a subplot and updates cursor if near a point that can be dragged. Also handles moving - point on graph if it is being dragged.""" + a subplot and updates cursor if near a point that can be dragged. Also handles moving + point on graph if it is being dragged. + """ if event.xdata and event.ydata: for plot_idx, plot in enumerate(self.plots): if event.inaxes == plot: @@ -494,27 +534,31 @@ def on_mouse_move(self, event): self.crossX.remove() self.crossY.remove() self.crossX = plot.axhline( - y=event.ydata, color=self.pallete[self.theme]['crosshair']) + y=event.ydata, color=self.pallete[self.theme]['crosshair'] + ) self.crossY = plot.axvline( - x=event.xdata, color=self.pallete[self.theme]['crosshair']) + x=event.xdata, color=self.pallete[self.theme]['crosshair'] + ) self.figure_canvas.draw() self.crosshair = True # update mouse coordinates on screen, rounding is handled based on # rounding defined in data_info xvalue = self.display_rounding(event.xdata, 0) - yvalue = self.display_rounding(event.ydata, plot_idx+1) + yvalue = self.display_rounding(event.ydata, plot_idx + 1) self.mouse_coords_str.set( - f"{self.data_info['labels'][0]}: {xvalue} {self.data_info['units'][0].get()} | " + - f"{self.data_info['labels'][plot_idx+1]}: {yvalue} {self.data_info['units'][plot_idx+1].get()}") + f'{self.data_info["labels"][0]}: {xvalue} {self.data_info["units"][0].get()} | ' + + f'{self.data_info["labels"][plot_idx + 1]}: {yvalue} {self.data_info["units"][plot_idx + 1].get()}' + ) # check if mouse is near an existing point, use closest point for dragging near = False dists = [] if len(self.data[0]) > 0: - for existing_pt in zip(self.data[0], self.data[plot_idx+1]): - dists.append(self.get_distance( - (event.xdata, event.ydata), existing_pt, plot_idx)) + for existing_pt in zip(self.data[0], self.data[plot_idx + 1]): + dists.append( + self.get_distance((event.xdata, event.ydata), existing_pt, plot_idx) + ) min_dist = min(dists) if min_dist < self.ptcontainer: self.figure_canvas.set_cursor(4) @@ -528,8 +572,7 @@ def on_mouse_move(self, event): if self.mouse_press and (near or self.mouse_drag): self.mouse_drag = True self.update_list(index=self.near_idx, axis=0, value=event.xdata) - self.update_list(index=self.near_idx, - axis=plot_idx+1, value=event.ydata) + self.update_list(index=self.near_idx, axis=plot_idx + 1, value=event.ydata) # redraw plot after looping through subplots self.redraw_plot() @@ -537,14 +580,15 @@ def on_mouse_move(self, event): def get_distance(self, pt1: tuple, pt2: tuple, plot_idx: int): """Returns a normalized distance value between 2 points. Normalization is based on the subplot's - x and y limits, subplot specified as plot_idx""" + x and y limits, subplot specified as plot_idx. + """ lims = (self.plots[plot_idx].get_xlim()[1], self.plots[plot_idx].get_ylim()[1]) - return np.sqrt(sum([((pt1[i] - pt2[i])/lims[i])**2 for i in range(2)])) + return np.sqrt(sum([((pt1[i] - pt2[i]) / lims[i]) ** 2 for i in range(2)])) -# ---------------------- -# Table related functions + # ---------------------- + # Table related functions def update_str_vars(self): - """Updates StringVar values for the table. Used when points are dragged on plot""" + """Updates StringVar values for the table. Used when points are dragged on plot.""" for i, vallist in enumerate(self.data): for j, val in enumerate(vallist): val = self.display_rounding(val, i) @@ -552,13 +596,14 @@ def update_str_vars(self): def delete_point(self, row: int): """When X button next to tabular point is pressed, lists are popped and plot and tables - are updated to show the removed point.""" + are updated to show the removed point. + """ if row < len(self.data[0]) and row > 0: - self.phase_order_list.pop(row-1) + self.phase_order_list.pop(row - 1) if len(self.plot_texts[0]) > 0: for i in range(self.num_dep_vars): - self.plot_texts[i][row-1].remove() - self.plot_texts[i].pop(row-1) + self.plot_texts[i][row - 1].remove() + self.plot_texts[i].pop(row - 1) self.figure_canvas.draw() for i in range(len(self.data)): @@ -570,36 +615,46 @@ def delete_point(self, row: int): def update_table(self, overwrite=False, bool_list=None): """This function handles both adding a new entry to table and overwriting the whole table. Overwriting causes all table widgets to be destroyed and a new set of widgets to be created. - This also resets the StringVars.""" - row = len( - self.data[0])-1 # last row (assumes data lists have been updated with new point) + This also resets the StringVars. + """ + row = ( + len( + # last row (assumes data lists have been updated with new point) + self.data[0] + ) + - 1 + ) if overwrite and len(self.table_widgets) > 0: for item in self.table_widgets: item.destroy() self.table_widgets = [] - self.table_strvars = [[] for i in range(self.num_dep_vars+1)] + self.table_strvars = [[] for i in range(self.num_dep_vars + 1)] self.table_boolvars = [[] for i in range(self.num_dep_vars)] if len(self.data[0]) > 0: row = 0 # set row to 0 if overwriting entire table while row < len(self.data[0]) and row >= 0: # numerical label for each point - rowtxt = str(row+1) - if row+1 < 10: - rowtxt = " "+rowtxt + rowtxt = str(row + 1) + if row + 1 < 10: + rowtxt = ' ' + rowtxt rownum_label = tk.Label( - self.frame_table.interior, text=rowtxt, - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) - rownum_label.grid(row=row*2+2, column=0) + self.frame_table.interior, + text=rowtxt, + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) + rownum_label.grid(row=row * 2 + 2, column=0) self.table_widgets.append(rownum_label) if row > 0 and self.show_optimize.get(): # have at least 2 points optimize_label = tk.Label( - self.frame_table.interior, text="Optimize:", - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) - optimize_label.grid(row=row*2+1, column=1) + self.frame_table.interior, + text='Optimize:', + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) + optimize_label.grid(row=row * 2 + 1, column=1) self.table_widgets.append(optimize_label) # entries and stringvars for each x,y value @@ -608,67 +663,80 @@ def update_table(self, overwrite=False, bool_list=None): entry_text = tk.StringVar(value=val) self.table_strvars[col].append(entry_text) - entry = tk.Entry(self.frame_table.interior, - width=self.table_column_widths[col], - textvariable=entry_text, justify='center', - background=self.pallete[self.theme] - ["background_primary"], - foreground=self.pallete[self.theme] - ["foreground_primary"]) - entry.grid(row=row*2+2, column=col+1) + entry = tk.Entry( + self.frame_table.interior, + width=self.table_column_widths[col], + textvariable=entry_text, + justify='center', + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) + entry.grid(row=row * 2 + 2, column=col + 1) # binds key release to update list function - entry.bind("", lambda e, row=row, col=col, entry_text=entry_text: [ - self.update_list(index=row, axis=col, value=entry_text.get()), self.redraw_plot()]) + entry.bind( + '', + lambda e, row=row, col=col, entry_text=entry_text: [ + self.update_list(index=row, axis=col, value=entry_text.get()), + self.redraw_plot(), + ], + ) self.table_widgets.append(entry) - if col > 0 and row > 0 and self.show_optimize.get(): # have at least 2 points and for dependent var cols only + if ( + col > 0 and row > 0 and self.show_optimize.get() + ): # have at least 2 points and for dependent var cols only checkbox_label = tk.Label( - self.frame_table.interior, text=self.data_info["labels"][col], - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) - checkbox_label.grid(row=row*2+1, column=col+1, sticky='w') + self.frame_table.interior, + text=self.data_info['labels'][col], + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) + checkbox_label.grid(row=row * 2 + 1, column=col + 1, sticky='w') self.table_widgets.append(checkbox_label) optimize_variable = tk.BooleanVar() - self.table_boolvars[col-1].append(optimize_variable) + self.table_boolvars[col - 1].append(optimize_variable) # if bool list has already been populated (e.g. opening an existing phase info) if bool_list: - optimize_variable.set(value=bool_list[col-1][row-1]) + optimize_variable.set(value=bool_list[col - 1][row - 1]) optimize_checkbox = tk.Checkbutton( - self.frame_table.interior, variable=optimize_variable, - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"], - activebackground=self.pallete[self.theme] - ["background_primary"], - activeforeground=self.pallete[self.theme] - ["foreground_primary"], - selectcolor=self.pallete[self.theme]["background_primary"], - highlightbackground=self.pallete[self.theme] - ["background_primary"], - highlightcolor=self.pallete[self.theme]["background_primary"]) - optimize_checkbox.grid(row=row*2+1, column=col+1, sticky='e') + self.frame_table.interior, + variable=optimize_variable, + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + activebackground=self.pallete[self.theme]['background_primary'], + activeforeground=self.pallete[self.theme]['foreground_primary'], + selectcolor=self.pallete[self.theme]['background_primary'], + highlightbackground=self.pallete[self.theme]['background_primary'], + highlightcolor=self.pallete[self.theme]['background_primary'], + ) + optimize_checkbox.grid(row=row * 2 + 1, column=col + 1, sticky='e') self.table_widgets.append(optimize_checkbox) # delete button for each point delete_button = tk.Button( - self.frame_table.interior, text="X", width=self.delete_button_width, - font=('Arial', self.default_font.actual()["size"] - 2), - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete["light" if self.macOS else self.theme] - ["foreground_primary"]) - delete_button.bind("", lambda e, row=row: self.delete_point(row)) - delete_button.bind("", func=self.on_enter) - delete_button.bind("", func=self.on_leave) - delete_button.grid(row=row*2+2, column=col+2) + self.frame_table.interior, + text='X', + width=self.delete_button_width, + font=('Arial', self.default_font.actual()['size'] - 2), + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete['light' if self.macOS else self.theme][ + 'foreground_primary' + ], + ) + delete_button.bind('', lambda e, row=row: self.delete_point(row)) + delete_button.bind('', func=self.on_enter) + delete_button.bind('', func=self.on_leave) + delete_button.grid(row=row * 2 + 2, column=col + 2) self.table_widgets.append(delete_button) row += 1 # reposition add new point button based on updated table if len(self.data[0]) > 0: - self.table_add_button.grid(row=row*2+3, column=0, columnspan=col+2) + self.table_add_button.grid(row=row * 2 + 3, column=0, columnspan=col + 2) def update_header(self, new_headers): - """Update header""" + """Update header.""" i = 0 for widget in self.table_header_widgets: if isinstance(widget, tk.Entry): @@ -677,12 +745,14 @@ def update_header(self, new_headers): def add_new_row(self): """Updates data lists with a generic new point and runs redraw plot and update table. - New point is added at x = halfway between last point and x limit, y = half of y limit""" - default_y_vals = [float(lim.get())/2 for lim in self.data_info["limits"][1:]] + New point is added at x = halfway between last point and x limit, y = half of y limit. + """ + default_y_vals = [float(lim.get()) / 2 for lim in self.data_info['limits'][1:]] newx = 0 if len(self.data[0]) > 0: - newx = (float(self.data_info["limits"][0].get()) - - self.data[0][-1]) / 2 + self.data[0][-1] + newx = (float(self.data_info['limits'][0].get()) - self.data[0][-1]) / 2 + self.data[0][ + -1 + ] for col, item in enumerate([newx, *default_y_vals]): self.update_list(index=len(self.data[0]), axis=col, value=item) @@ -696,19 +766,22 @@ def create_table(self): self.table_boolvars = [] self.table_widgets = [] # list used to hold graphical table elements, can be used to modify them self.table_header_widgets = [] # list used to hold header widgets, referenced for theme changes - header = tk.Label(self.frame_tableheaders, text="Pt") + header = tk.Label(self.frame_tableheaders, text='Pt') header.grid(row=0, column=0) self.table_header_widgets.append(header) - for col, (label, unit) in enumerate( - zip(self.data_info["labels"], - self.data_info["units"])): - header_str = f"{label} ({unit.get()})" + for col, (label, unit) in enumerate(zip(self.data_info['labels'], self.data_info['units'])): + header_str = f'{label} ({unit.get()})' header_text = tk.StringVar(value=header_str) header_width = int(len(header_str) * (0.75 if self.macOS else 1)) header = tk.Entry( - self.frame_tableheaders, textvariable=header_text, state='readonly', - width=header_width, justify='center', relief='groove') - header.grid(row=0, column=col+1) + self.frame_tableheaders, + textvariable=header_text, + state='readonly', + width=header_width, + justify='center', + relief='groove', + ) + header.grid(row=0, column=col + 1) self.table_column_widths.append(header_width) self.table_strvars.append([]) if col > 0: @@ -717,77 +790,83 @@ def create_table(self): # this spacer prevents invisbility of delete buttons after all of them have been deleted and a new point is added self.delete_button_width = 1 if self.macOS else 4 - delete_button_spacer = tk.Label( - self.frame_tableheaders, width=self.delete_button_width) - delete_button_spacer.grid(row=0, column=col+2) + delete_button_spacer = tk.Label(self.frame_tableheaders, width=self.delete_button_width) + delete_button_spacer.grid(row=0, column=col + 2) self.table_header_widgets.append(delete_button_spacer) # button for adding new rows to table self.table_add_button = tk.Button( - self.frame_table.interior, text="Add New Point", command=self.add_new_row) - self.table_add_button.bind("", func=self.on_enter) - self.table_add_button.bind("", func=self.on_leave) + self.frame_table.interior, text='Add New Point', command=self.add_new_row + ) + self.table_add_button.bind('', func=self.on_enter) + self.table_add_button.bind('', func=self.on_leave) self.point_warning_strvar = tk.StringVar() - self.point_warning = tk.Label(self.frame_table.freezeframe_bottom, - textvariable=self.point_warning_strvar) + self.point_warning = tk.Label( + self.frame_table.freezeframe_bottom, textvariable=self.point_warning_strvar + ) self.point_warning.pack() self.update_table() def display_rounding(self, value, col: int, extra=0): """Returns a rounded value based on which variable the value belongs to. - Uses rounding amount specified in data_info""" - return format( - value, "." + str(int(self.data_info["rounding"][col].get()) + extra) + "f") + Uses rounding amount specified in data_info. + """ + return format(value, '.' + str(int(self.data_info['rounding'][col].get()) + extra) + 'f') -# ---------------------- -# Popup related functions + # ---------------------- + # Popup related functions def close_popup(self): - """Function to close existing popup and refocus main window""" + """Function to close existing popup and refocus main window.""" self.focus_set() self.popup.destroy() self.popup = None - def generic_popup(self, pop_title="Popup", buttons_text=[]): + def generic_popup(self, pop_title='Popup', buttons_text=[]): """Function to create a base window for a popup. Returns popup object to be used for adding widget - and configuring settings. Buttons_text can be used to specify any number of buttons. These button - objects are returned for configuring commands and location.""" + and configuring settings. Buttons_text can be used to specify any number of buttons. These button + objects are returned for configuring commands and location. + """ popup = tk.Toplevel(self) # Set the window icon, provides 2 sizes of logos to prevent blurry icons popup.iconphoto( - False, tk.PhotoImage( - file=os.path.join(self.source_directory, "aviary_logo_16.png")), - tk.PhotoImage( - file=os.path.join(self.source_directory, "aviary_logo_32.png"))) + False, + tk.PhotoImage(file=os.path.join(self.source_directory, 'static', 'aviary_logo_16.png')), + tk.PhotoImage(file=os.path.join(self.source_directory, 'static', 'aviary_logo_32.png')), + ) popup.resizable(False, False) popup.title(pop_title) popup.focus_set() - popup.configure(background=self.pallete[self.theme]["background_primary"]) + popup.configure(background=self.pallete[self.theme]['background_primary']) self.popup = popup - popup.protocol("WM_DELETE_WINDOW", func=self.close_popup) + popup.protocol('WM_DELETE_WINDOW', func=self.close_popup) popup_content_frame = tk.Frame( - popup, background=self.pallete[self.theme]["background_primary"]) + popup, background=self.pallete[self.theme]['background_primary'] + ) popup_content_frame.pack(side='top', fill='x') - button_frame = tk.Frame(popup, bg=self.pallete[self.theme]["background_primary"]) + button_frame = tk.Frame(popup, bg=self.pallete[self.theme]['background_primary']) button_frame.pack(side='bottom', pady=5) buttons = {} # button width based on longest button string - button_width = len(max(buttons_text, key=len))+5 + button_width = len(max(buttons_text, key=len)) + 5 for button_txt in buttons_text: button = tk.Button( - button_frame, text=button_txt.title(), - width=button_width, background=self.pallete[self.theme] - ["background_primary"], - foreground=self.pallete["light" if self.macOS else self.theme] - ["foreground_primary"]) - button.bind("", func=self.on_enter) - button.bind("", func=self.on_leave) + button_frame, + text=button_txt.title(), + width=button_width, + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete['light' if self.macOS else self.theme][ + 'foreground_primary' + ], + ) + button.bind('', func=self.on_enter) + button.bind('', func=self.on_leave) button.pack(side='left', padx=5) buttons[button_txt] = button @@ -795,83 +874,105 @@ def generic_popup(self, pop_title="Popup", buttons_text=[]): def place_popup(self): """Generic popup lets Tkinter automatically size the popup to fit all contents. - This function uses that size and main GUI window size/location to compute a - location for the popup that is central to the GUI.""" + This function uses that size and main GUI window size/location to compute a + location for the popup that is central to the GUI. + """ self.popup.update_idletasks() - pop_wid, pop_hei = [int(x) - for x in self.popup.winfo_geometry().split("+")[0].split("x")] - win_size, win_left, win_top = self.winfo_geometry().split("+") - win_wid, win_hei = win_size.split("x") - win_left, win_top, win_wid, win_hei = int( - win_left), int(win_top), int(win_wid), int(win_hei) - pop_left, pop_top = int(win_left + win_wid/2 - pop_wid / - 2), int(win_top + win_hei/2 - pop_hei/2) - self.popup.geometry(f"+{pop_left}+{pop_top}") + pop_wid, pop_hei = [int(x) for x in self.popup.winfo_geometry().split('+')[0].split('x')] + win_size, win_left, win_top = self.winfo_geometry().split('+') + win_wid, win_hei = win_size.split('x') + win_left, win_top, win_wid, win_hei = ( + int(win_left), + int(win_top), + int(win_wid), + int(win_hei), + ) + pop_left, pop_top = ( + int(win_left + win_wid / 2 - pop_wid / 2), + int(win_top + win_hei / 2 - pop_hei / 2), + ) + self.popup.geometry(f'+{pop_left}+{pop_top}') def change_axes_popup(self): """Creates a popup window that allows user to edit axes limits. This function is triggered - by the menu buttons""" + by the menu buttons. + """ + def reset_options(old_list=None): if not old_list: if len(self.data[0]) > 0: # if resetting to bring data into view old_list = [] for val_list in self.data: - old_list.append(max(val_list)*1.2) + old_list.append(max(val_list) * 1.2) else: - old_list = [float(item.get()) - for item in self.data_info_defaults["limits"]] - for i, (value, lim_str) in enumerate( - zip(old_list, self.data_info["limits"])): + old_list = [float(item.get()) for item in self.data_info_defaults['limits']] + for i, (value, lim_str) in enumerate(zip(old_list, self.data_info['limits'])): lim_str.set(value=self.display_rounding(value, col=i)) - current_lims = [float(lim.get()) for lim in self.data_info["limits"]] + current_lims = [float(lim.get()) for lim in self.data_info['limits']] popup, content_frame, buttons = self.generic_popup( - pop_title="Axes Limits", buttons_text=["apply", "reset", "cancel"]) - popup.protocol("WM_DELETE_WINDOW", func=lambda: [ - self.close_popup(), reset_options(current_lims)]) + pop_title='Axes Limits', buttons_text=['apply', 'reset', 'cancel'] + ) + popup.protocol( + 'WM_DELETE_WINDOW', func=lambda: [self.close_popup(), reset_options(current_lims)] + ) for i in range(2): # allow columns to expand in frame content_frame.columnconfigure(i, weight=1) for row, (label, unit, lim_str) in enumerate( - zip( - self.data_info["labels"], - self.data_info["units"], - self.data_info["limits"])): + zip(self.data_info['labels'], self.data_info['units'], self.data_info['limits']) + ): lim_str.set(value=self.display_rounding(float(lim_str.get()), col=row)) lim_label = tk.Label( - content_frame, text=f"{label} ({unit.get()})", justify='right', - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) + content_frame, + text=f'{label} ({unit.get()})', + justify='right', + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) lim_label.grid(row=row, column=0, sticky='e') - lim_entry = tk.Entry(content_frame, textvariable=lim_str, - width=max(6, len(lim_str.get())), - background=self.pallete[self.theme] - ["background_primary"], - foreground=self.pallete[self.theme] - ["foreground_primary"]) + lim_entry = tk.Entry( + content_frame, + textvariable=lim_str, + width=max(6, len(lim_str.get())), + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) lim_entry.grid(row=row, column=1, sticky='w') # apply uses values in entry boxes, reset defaults to original limits, cancel uses previously set limits - buttons["apply"].configure( - command=lambda: [self.close_popup(), self.update_axes(limits=True, refresh=True)]) - buttons["reset"].configure(command=lambda: [self.close_popup( - ), reset_options(), self.update_axes(limits=True, refresh=True)]) - buttons["cancel"].configure(command=lambda: [self.close_popup(), reset_options( - current_lims), self.update_axes(limits=True, refresh=True)]) + buttons['apply'].configure( + command=lambda: [self.close_popup(), self.update_axes(limits=True, refresh=True)] + ) + buttons['reset'].configure( + command=lambda: [ + self.close_popup(), + reset_options(), + self.update_axes(limits=True, refresh=True), + ] + ) + buttons['cancel'].configure( + command=lambda: [ + self.close_popup(), + reset_options(current_lims), + self.update_axes(limits=True, refresh=True), + ] + ) self.place_popup() def get_phase_names(self): """Returns a list of phase names, these are decided based on final and starting altitudes. These names are only used for the dropdown menu in advanced options, and are not connected to - phase info phase names.""" - names = ["Climb ", "Cruise ", "Descent "] + phase info phase names. + """ + names = ['Climb ', 'Cruise ', 'Descent '] counters = [1, 1, 1] phase_name_list = [] - for i in range(len(self.data[0])-1): - nextpt = round(self.data[1][i+1], int(self.data_info["rounding"][1].get())) - nowpt = round(self.data[1][i], int(self.data_info["rounding"][1].get())) + for i in range(len(self.data[0]) - 1): + nextpt = round(self.data[1][i + 1], int(self.data_info['rounding'][1].get())) + nowpt = round(self.data[1][i], int(self.data_info['rounding'][1].get())) if nextpt > nowpt: j = 0 elif nextpt < nowpt: @@ -879,55 +980,65 @@ def get_phase_names(self): else: j = 1 - phase_name_list.append(names[j]+str(counters[j])) + phase_name_list.append(names[j] + str(counters[j])) counters[j] += 1 return phase_name_list def advanced_options_popup(self): - """Creates a popup window that allows user to edit advanced options for phase info. + """Creates a popup window that allows user to edit advanced options for phase info. Options included are specified as a dict in __init__ and include solve/constrain for range, - include landing/takeoff, polynomial order, and phase order. This function is triggered by the menu buttons""" + include landing/takeoff, polynomial order, and phase order. This function is triggered by the menu buttons. + """ def reset_options(self, old_dict=self.advanced_options_defaults): for key, value in old_dict.items(): self.advanced_options[key].set(value=value) - self.phase_order_list = [self.phase_order_default]*(len(self.data[0])-1) + self.phase_order_list = [self.phase_order_default] * (len(self.data[0]) - 1) current_info = {} # this stores option values as they are before user edits inside popup for key, var in self.advanced_options.items(): current_info[key] = var.get() popup, content_frame, buttons = self.generic_popup( - pop_title="Advanced Options", buttons_text=["apply", "reset", "cancel"]) - popup.protocol("WM_DELETE_WINDOW", func=lambda: [ - self.close_popup(), reset_options(self, current_info)]) + pop_title='Advanced Options', buttons_text=['apply', 'reset', 'cancel'] + ) + popup.protocol( + 'WM_DELETE_WINDOW', func=lambda: [self.close_popup(), reset_options(self, current_info)] + ) for i in range(3): content_frame.columnconfigure(i, weight=1) for row, (option_label_txt, option_var) in enumerate(self.advanced_options.items()): option_label = tk.Label( - content_frame, text=option_label_txt.replace("_", " ").title(), - justify='right', background=self.pallete[self.theme] - ["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) + content_frame, + text=option_label_txt.replace('_', ' ').title(), + justify='right', + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) option_label.grid(row=row, column=0, sticky='e') if type(tk.BooleanVar()) == type(option_var): option_checkbox = tk.Checkbutton( - content_frame, variable=option_var, - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"], - activebackground=self.pallete[self.theme]["background_primary"], - activeforeground=self.pallete[self.theme]["foreground_primary"], - selectcolor=self.pallete[self.theme]["background_primary"], - highlightbackground=self.pallete[self.theme]["background_primary"], - highlightcolor=self.pallete[self.theme]["background_primary"]) + content_frame, + variable=option_var, + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + activebackground=self.pallete[self.theme]['background_primary'], + activeforeground=self.pallete[self.theme]['foreground_primary'], + selectcolor=self.pallete[self.theme]['background_primary'], + highlightbackground=self.pallete[self.theme]['background_primary'], + highlightcolor=self.pallete[self.theme]['background_primary'], + ) option_checkbox.grid(row=row, column=1, sticky='w') elif type(tk.IntVar()) == type(option_var): option_entry = tk.Entry( - content_frame, textvariable=option_var, width=3, - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) + content_frame, + textvariable=option_var, + width=3, + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) option_entry.grid(row=row, column=1, sticky='w') def set_var(_): @@ -942,141 +1053,173 @@ def change_var(_): return if newval < self.phase_order_default: messagebox.showwarning( - title="Error", message=f"Phase transcription order must be " + - "at least {self.phase_order_default}!") + title='Error', + message='Phase transcription order must be ' + + 'at least {self.phase_order_default}!', + ) newval = self.phase_order_default self.phase_order_list[phase_idx] = newval if len(self.data[0]) > 1: order_label = tk.Label( - content_frame, text="Phase Transcription Order: ", - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) - order_label.grid(row=row+1, column=0, sticky='e') + content_frame, + text='Phase Transcription Order: ', + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) + order_label.grid(row=row + 1, column=0, sticky='e') order_combo = ttk.Combobox( - content_frame, state='readonly', values=self.get_phase_names(), width=9) - order_combo.bind("<>", set_var) + content_frame, state='readonly', values=self.get_phase_names(), width=9 + ) + order_combo.bind('<>', set_var) order_combo.current(0) - order_combo.grid(row=row+1, column=1, sticky='w') + order_combo.grid(row=row + 1, column=1, sticky='w') order_var = tk.StringVar(value=self.phase_order_default) order_entry = tk.Entry( - content_frame, width=3, textvariable=order_var, - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) - order_entry.bind("", func=change_var) - order_entry.grid(row=row+1, column=2, sticky='w') + content_frame, + width=3, + textvariable=order_var, + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) + order_entry.bind('', func=change_var) + order_entry.grid(row=row + 1, column=2, sticky='w') # apply maintains user options as set by user in popup, reset reverts them to default values, cancel reverts to # values as they were at the start of the popup - buttons["apply"].configure(command=lambda: self.close_popup()) - buttons["reset"].configure( - command=lambda: [self.close_popup(), reset_options(self)]) - buttons["cancel"].configure( - command=lambda: [self.close_popup(), reset_options(self, current_info)]) + buttons['apply'].configure(command=lambda: self.close_popup()) + buttons['reset'].configure(command=lambda: [self.close_popup(), reset_options(self)]) + buttons['cancel'].configure( + command=lambda: [self.close_popup(), reset_options(self, current_info)] + ) self.place_popup() -# ---------------------- -# Menu related functions + # ---------------------- + # Menu related functions def create_menu(self): - """Creates menu. Structure is specified as a dictionary, can add commands, - separators, and checkbuttons.""" - structure = {"File": [["command", "Open Phase Info..", self.open_phase_info], - ["command", "Save Phase Info", self.save], - ["command", "Save Phase Info as..", self.save_as], - ["separator"], - ["command", "Exit", self.close_window]], - "Edit": [["command", "Axes Limits", self.change_axes_popup], - ["command", "Units", self.change_units], - ["command", "Rounding", self.change_rounding], - ["checkbutton", "Store Settings?", self.remind_store_settings, self.store_settings]], - "View": [["checkbutton", "Optimize Phase", self.toggle_optimize_view, self.show_optimize], - ["checkbutton", "Phase Slopes", - self.toggle_phase_slope, self.show_phase_slope], - ["command", "Advanced Options", self.advanced_options_popup]], - "Help": [["command", "Instructions", self.show_instructions]]} + """Creates menu. Structure is specified as a dictionary, can add commands, + separators, and checkbuttons. + """ + structure = { + 'File': [ + ['command', 'Open Phase Info..', self.open_phase_info], + ['command', 'Save Phase Info', self.save], + ['command', 'Save Phase Info as..', self.save_as], + ['separator'], + ['command', 'Exit', self.close_window], + ], + 'Edit': [ + ['command', 'Axes Limits', self.change_axes_popup], + ['command', 'Units', self.change_units], + ['command', 'Rounding', self.change_rounding], + ['checkbutton', 'Store Settings?', self.remind_store_settings, self.store_settings], + ], + 'View': [ + ['checkbutton', 'Optimize Phase', self.toggle_optimize_view, self.show_optimize], + ['checkbutton', 'Phase Slopes', self.toggle_phase_slope, self.show_phase_slope], + ['command', 'Advanced Options', self.advanced_options_popup], + ], + 'Help': [['command', 'Instructions', self.show_instructions]], + } menu_bar = tk.Menu(self) for tab_label, tab_list in structure.items(): tab = tk.Menu( - menu_bar, tearoff=False, background=self.pallete[self.theme] - ['background_primary'], + menu_bar, + tearoff=False, + background=self.pallete[self.theme]['background_primary'], foreground=self.pallete[self.theme]['foreground_primary'], - activebackground=self.pallete[self.theme]['hover']) + activebackground=self.pallete[self.theme]['hover'], + ) menu_bar.add_cascade(label=tab_label, menu=tab) for item in tab_list: - if item[0] == "separator": + if item[0] == 'separator': tab.add_separator() - elif item[0] == "command": + elif item[0] == 'command': tab.add_command(label=item[1], command=item[2]) - elif item[0] == "checkbutton": + elif item[0] == 'checkbutton': tab.add_checkbutton( label=item[1], command=item[2], variable=item[3], - selectcolor=self.pallete[self.theme]['foreground_primary']) + selectcolor=self.pallete[self.theme]['foreground_primary'], + ) self.config(menu=menu_bar) def temporary_notice(self): - messagebox.showinfo(title="Under Development", - message="This section is currently under development!") + messagebox.showinfo( + title='Under Development', message='This section is currently under development!' + ) def close_window(self): """Closes main window and saves persistent settings into a binary pickle file.""" if self.store_settings.get(): # if user wants to store settings - with open(self.persist_filename, "w") as fp: - json.dump({'window_geometry': self.winfo_geometry(), - 'theme': self.theme}, fp) + with open(self.persist_filename, 'w') as fp: + json.dump({'window_geometry': self.winfo_geometry(), 'theme': self.theme}, fp) # if user doesn't want to store settings and file exists elif os.path.exists(self.persist_filename): os.remove(self.persist_filename) # remove file self.destroy() def toggle_optimize_view(self): - """Runs update table with overwrite on to toggle display of optimize checkboxes""" + """Runs update table with overwrite on to toggle display of optimize checkboxes.""" self.update_table(overwrite=True) def toggle_phase_slope(self, redraw=True): if len(self.data[0]) > 1 and self.show_phase_slope.get(): - y_lims = [float(item.get()) for item in self.data_info["limits"][1:]] - for i in range(len(self.data[0])-1): + y_lims = [float(item.get()) for item in self.data_info['limits'][1:]] + for i in range(len(self.data[0]) - 1): for j in range(self.num_dep_vars): - xs = self.data[0][i:i+2] - ys = self.data[j+1][i:i+2] + xs = self.data[0][i : i + 2] + ys = self.data[j + 1][i : i + 2] # offset from line by 8% of y limit - text_position = (np.mean(xs), np.mean(ys)+y_lims[j]*0.1) + text_position = (np.mean(xs), np.mean(ys) + y_lims[j] * 0.1) # find slope and attach units if either unit is not unitless try: slope = self.display_rounding( - (ys[1]-ys[0])/(xs[1]-xs[0]), j+1, extra=1) + (ys[1] - ys[0]) / (xs[1] - xs[0]), j + 1, extra=1 + ) except ZeroDivisionError: - slope = "undefined" - xunit, yunit = self.data_info["units"][0].get( - ), self.data_info["units"][j+1].get() - if yunit != "unitless" and xunit != "unitless": - slope = f"{slope} {yunit}/{xunit}" + slope = 'undefined' + xunit, yunit = ( + self.data_info['units'][0].get(), + self.data_info['units'][j + 1].get(), + ) + if yunit != 'unitless' and xunit != 'unitless': + slope = f'{slope} {yunit}/{xunit}' # matplotlib text angle is in display units, so use transform to find angle scaled_pt1, scaled_pt2 = [ - self.plots[j].transData.transform_point(pt) for pt in zip( - xs, ys)] - line_angle = np.rad2deg(np.arctan2( - scaled_pt2[1]-scaled_pt1[1], scaled_pt2[0]-scaled_pt1[0])) + self.plots[j].transData.transform_point(pt) for pt in zip(xs, ys) + ] + line_angle = np.rad2deg( + np.arctan2(scaled_pt2[1] - scaled_pt1[1], scaled_pt2[0] - scaled_pt1[0]) + ) if i < len(self.plot_texts[j]): self.plot_texts[j][i].set( - text=slope, position=text_position, rotation=line_angle) + text=slope, position=text_position, rotation=line_angle + ) else: self.plot_texts[j].append( self.plots[j].annotate( - slope, xy=text_position, rotation=line_angle, - verticalalignment='center', horizontalalignment='center', + slope, + xy=text_position, + rotation=line_angle, + verticalalignment='center', + horizontalalignment='center', rotation_mode='anchor', - color=self.pallete[self.theme]["foreground_primary"])) + color=self.pallete[self.theme]['foreground_primary'], + ) + ) self.plot_texts[j][i].set_bbox( dict( - facecolor=self.pallete[self.theme]["background_primary"], - alpha=0.5, linewidth=0)) + facecolor=self.pallete[self.theme]['background_primary'], + alpha=0.5, + linewidth=0, + ) + ) if not self.show_phase_slope.get() and len(self.plot_texts) > 0: for text_list in self.plot_texts: @@ -1089,78 +1232,90 @@ def toggle_phase_slope(self, redraw=True): def show_instructions(self): """Shows a messagebox with instructions to use this utility.""" - message = "This tool can be used to design a mission which can be used by Aviary for modelling and optimization.\n\n" +\ - "To begin, start by adding points to the Altitude Plot, Mach Plot, or the table on the right.\n\n" +\ - "Points can be edited by dragging points on the plot or editing the table values. Points can be deleted " +\ - "with the 'X' button adjacent to each point on the table.\n\n" +\ - "Use 'Edit'->'Axes Limits' to change the axes limits.\n\n" +\ - "Use 'View'->'Optimize Phase' to add the option to optimize any mission phase.\n\n" +\ - "Use 'View'->'Phase Slopes' to toggle climb/descent rate information on the plots.\n\n" +\ - "Use 'View'->'Advanced Options' to edit additional options related to the mission and optimization.\n\n" +\ - "If you would like to save window size, location, and theme information for subsequent runs, toggle 'Edit'->'Store Settings?'" - messagebox.showinfo(title="Mission Design Instructions", message=message) + message = ( + 'This tool can be used to design a mission which can be used by Aviary for modelling and optimization.\n\n' + + 'To begin, start by adding points to the Altitude Plot, Mach Plot, or the table on the right.\n\n' + + 'Points can be edited by dragging points on the plot or editing the table values. Points can be deleted ' + + "with the 'X' button adjacent to each point on the table.\n\n" + + "Use 'Edit'->'Axes Limits' to change the axes limits.\n\n" + + "Use 'View'->'Optimize Phase' to add the option to optimize any mission phase.\n\n" + + "Use 'View'->'Phase Slopes' to toggle climb/descent rate information on the plots.\n\n" + + "Use 'View'->'Advanced Options' to edit additional options related to the mission and optimization.\n\n" + + "If you would like to save window size, location, and theme information for subsequent runs, toggle 'Edit'->'Store Settings?'" + ) + messagebox.showinfo(title='Mission Design Instructions', message=message) def remind_store_settings(self): - status = "be" if self.store_settings.get() else "not be" + status = 'be' if self.store_settings.get() else 'not be' messagebox.showinfo( - title="Store Settings", - message=f"Settings related to window location, size, and theme will {status} stored!") + title='Store Settings', + message=f'Settings related to window location, size, and theme will {status} stored!', + ) def change_units(self): popup, content_frame, buttons = self.generic_popup( - pop_title="Change Units", buttons_text=["apply", "cancel"]) - popup.protocol("WM_DELETE_WINDOW", func=lambda: [self.close_popup()]) + pop_title='Change Units', buttons_text=['apply', 'cancel'] + ) + popup.protocol('WM_DELETE_WINDOW', func=lambda: [self.close_popup()]) for i in range(2): content_frame.columnconfigure(i, weight=1) def set_var(row): - self.data_info["units"][row].set(unit_combos[row].get()) + self.data_info['units'][row].set(unit_combos[row].get()) def reset_units_strvar(): for i, unit in enumerate(old_units): - self.data_info["units"][i].set(unit) + self.data_info['units'][i].set(unit) # this creates a copy instead of a reference - old_units = [item.get() for item in self.data_info["units"]] - unit_combos = [None]*(self.num_dep_vars+1) - avail_units = [["s", "min", "h"], ["m", "km", "ft", "mi", "nmi"]] + old_units = [item.get() for item in self.data_info['units']] + unit_combos = [None] * (self.num_dep_vars + 1) + avail_units = [['s', 'min', 'h'], ['m', 'km', 'ft', 'mi', 'nmi']] for row, (var_label, var_unit) in enumerate( - zip(self.data_info["labels"], - self.data_info["units"])): - if var_unit.get() != "unitless": + zip(self.data_info['labels'], self.data_info['units']) + ): + if var_unit.get() != 'unitless': for unit_type in avail_units: if var_unit.get() in unit_type: unit_list = unit_type - tk.Label(content_frame, text=var_label, justify='right', - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]).grid( - row=row, column=0, sticky='e') + tk.Label( + content_frame, + text=var_label, + justify='right', + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ).grid(row=row, column=0, sticky='e') unit_combos[row] = ttk.Combobox( - content_frame, values=unit_list, state='readonly', width=10) + content_frame, values=unit_list, state='readonly', width=10 + ) unit_combos[row].current(unit_list.index(var_unit.get())) - unit_combos[row].bind("<>", - lambda e, row=row: set_var(row)) + unit_combos[row].bind('<>', lambda e, row=row: set_var(row)) unit_combos[row].grid(row=row, column=1, sticky='w') def apply_units(): - new_headers = [f"{label} ({unit.get()})" for label, unit in zip( - self.data_info["labels"], self.data_info["units"])] + new_headers = [ + f'{label} ({unit.get()})' + for label, unit in zip(self.data_info['labels'], self.data_info['units']) + ] self.update_header(new_headers) for col, (old_unit, new_unit, limit, rounding) in enumerate( zip( - old_units, self.data_info["units"], - self.data_info["limits"], - self.data_info["rounding"])): - new_lim = convert_units(val=float(limit.get()), - old_units=old_unit, new_units=new_unit.get()) + old_units, + self.data_info['units'], + self.data_info['limits'], + self.data_info['rounding'], + ) + ): + new_lim = convert_units( + val=float(limit.get()), old_units=old_unit, new_units=new_unit.get() + ) limit.set(value=new_lim) for row, val in enumerate(self.data[col]): - new_val = convert_units( - val=val, old_units=old_unit, new_units=new_unit.get()) + new_val = convert_units(val=val, old_units=old_unit, new_units=new_unit.get()) self.update_list(index=row, axis=col, value=new_val) - num_digs = np.floor(np.log10(new_lim))+1 + num_digs = np.floor(np.log10(new_lim)) + 1 rounding.set(value=0 if num_digs >= 3 else 2) self.update_axes(limits=True, units=True) @@ -1171,15 +1326,15 @@ def apply_units(): self.show_phase_slope.set(not self.show_phase_slope.get()) self.toggle_phase_slope(redraw=i == 1) - buttons["apply"].configure(command=lambda: [self.close_popup(), apply_units()]) - buttons["cancel"].configure( - command=lambda: [self.close_popup(), reset_units_strvar()]) + buttons['apply'].configure(command=lambda: [self.close_popup(), apply_units()]) + buttons['cancel'].configure(command=lambda: [self.close_popup(), reset_units_strvar()]) self.place_popup() def change_rounding(self): popup, content_frame, buttons = self.generic_popup( - pop_title="Rounding Options", buttons_text=["apply", "cancel"]) - popup.protocol("WM_DELETE_WINDOW", func=lambda: [self.close_popup()]) + pop_title='Rounding Options', buttons_text=['apply', 'cancel'] + ) + popup.protocol('WM_DELETE_WINDOW', func=lambda: [self.close_popup()]) for i in range(2): # allow columns to expand in frame content_frame.columnconfigure(i, weight=1) @@ -1188,42 +1343,44 @@ def apply_rounding(): self.update_table(overwrite=True) def cancel_rounding(): - for changed, old in zip(self.data_info["rounding"], current_rounding): + for changed, old in zip(self.data_info['rounding'], current_rounding): changed.set(old.get()) - current_rounding = [item for item in self.data_info["rounding"]] + current_rounding = [item for item in self.data_info['rounding']] for row, (label, unit, round_str) in enumerate( - zip( - self.data_info["labels"], - self.data_info["units"], - self.data_info["rounding"])): + zip(self.data_info['labels'], self.data_info['units'], self.data_info['rounding']) + ): round_label = tk.Label( - content_frame, text=f"{label} ({unit.get()})", justify='right', - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) + content_frame, + text=f'{label} ({unit.get()})', + justify='right', + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) round_label.grid(row=row, column=0, sticky='e') round_entry = tk.Entry( - content_frame, textvariable=round_str, width=max( - 4, len(round_str.get())), - background=self.pallete[self.theme]["background_primary"], - foreground=self.pallete[self.theme]["foreground_primary"]) + content_frame, + textvariable=round_str, + width=max(4, len(round_str.get())), + background=self.pallete[self.theme]['background_primary'], + foreground=self.pallete[self.theme]['foreground_primary'], + ) round_entry.grid(row=row, column=1, sticky='w') - buttons["apply"].configure( - command=lambda: [self.close_popup(), apply_rounding()]) - buttons["cancel"].configure( - command=lambda: [self.close_popup(), cancel_rounding()]) + buttons['apply'].configure(command=lambda: [self.close_popup(), apply_rounding()]) + buttons['cancel'].configure(command=lambda: [self.close_popup(), cancel_rounding()]) self.place_popup() def open_phase_info(self): - """Opens a dialog box to select a .py file with a phase info dict. File must contain a dict called phase_info. - File can be placed in any directory.""" - file_dialog = filedialog.Open(self, filetypes=[("Python files", "*.py")]) + """Opens a dialog box to select a .py file with a phase info dict. File must contain a dict called phase_info. + File can be placed in any directory. + """ + file_dialog = filedialog.Open(self, filetypes=[('Python files', '*.py')]) filename = file_dialog.show() - if filename != "": + if filename != '': # imports file similar to how a module is imported, allowing direct access to variables - spec = importlib.util.spec_from_file_location("module_name", filename) + spec = importlib.util.spec_from_file_location('module_name', filename) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) phase_info = None @@ -1231,48 +1388,62 @@ def open_phase_info(self): phase_info = module.phase_info except AttributeError: raise Exception( - "Python File does not contain a global dictionary called phase_info!") + 'Python File does not contain a global dictionary called phase_info!' + ) if phase_info: - init = False + first_phase = True idx = 0 - ylabs = ["altitude", "mach"] + ylabs = ['altitude', 'mach'] self.phase_order_list = [] - units = [None]*3 - for phase_dict in (phase_info.values()): - if "initial_guesses" in phase_dict: # not a pre/post mission dict - self.advanced_options["solve_for_distance"].set( - value=phase_dict["user_options"]["solve_for_distance"]) - self.advanced_options["polynomial_control_order"].set( - value=phase_dict["user_options"]["polynomial_control_order"]) - self.phase_order_list.append(phase_dict["user_options"]["order"]) - - timevals, units[0] = phase_dict["initial_guesses"]["time"] - if not init: # for first run initialize internal lists with correct num of elements - numpts = phase_dict["user_options"]["num_segments"]+1 - self.data = [[0]*numpts for _ in range(self.num_dep_vars+1)] - bool_list = [[0]*(numpts-1) - for _ in range(self.num_dep_vars)] - self.data[0][0] = timevals[0] - for i in range(self.num_dep_vars): - self.data[i+1][0], units[i + - 1] = phase_dict["user_options"]["initial_"+ylabs[i]] - init = True - - self.data[0][idx+1] = timevals[1] + timevals[0] + units = [None] * 3 + for name, phase_dict in phase_info.items(): + if name in ['pre_mission', 'post_mission']: + # Skip pre/post + continue + + usr_opts = phase_dict['user_options'] + + value = usr_opts.get('distance_solve_segments', None) + if value is not None: + self.advanced_options['distance_solve_segments'].set(value=value) + + mach_poly = usr_opts.get('mach_polynomial_order', None) + alt_poly = usr_opts.get('altitude_polynomial_order', None) + + if mach_poly is not None: + self.advanced_options['polynomial_order'].set(value=mach_poly) + elif alt_poly is not None: + self.advanced_options['polynomial_order'].set(value=alt_poly) + + self.phase_order_list.append(usr_opts['order']) + + timevals, units[0] = phase_dict['initial_guesses']['time'] + if first_phase: + # For first phase, initialize internal lists with correct num of elements + numpts = usr_opts['num_segments'] + 1 + self.data = [[0] * numpts for _ in range(self.num_dep_vars + 1)] + bool_list = [[0] * (numpts - 1) for _ in range(self.num_dep_vars)] + self.data[0][0] = timevals[0] for i in range(self.num_dep_vars): - self.data[i+1][idx + - 1] = phase_dict["user_options"]["final_"+ylabs[i]][0] - bool_list[i][idx] = phase_dict["user_options"][ - "optimize_" + ylabs[i]] - - idx += 1 - - self.advanced_options["constrain_range"].set( - value=phase_info["post_mission"]["constrain_range"]) - self.advanced_options["include_landing"].set( - value=phase_info["post_mission"]["include_landing"]) - self.advanced_options["include_takeoff"].set( - value=phase_info["pre_mission"]["include_takeoff"]) + self.data[i + 1][0], units[i + 1] = usr_opts[f'{ylabs[i]}_initial'] + first_phase = False + + self.data[0][idx + 1] = timevals[1] + timevals[0] + for i in range(self.num_dep_vars): + self.data[i + 1][idx + 1] = usr_opts[f'{ylabs[i]}_final'][0] + bool_list[i][idx] = usr_opts[f'{ylabs[i]}_optimize'] + + idx += 1 + + self.advanced_options['constrain_range'].set( + value=phase_info['post_mission']['constrain_range'] + ) + self.advanced_options['include_landing'].set( + value=phase_info['post_mission']['include_landing'] + ) + self.advanced_options['include_takeoff'].set( + value=phase_info['pre_mission']['include_takeoff'] + ) # checks if any optimize values are true, in which case checkboxes are shown for axis_list in bool_list: @@ -1281,53 +1452,62 @@ def open_phase_info(self): self.show_optimize.set(True) break lim_margin = 1.2 - limits = [max(axis)*lim_margin for axis in self.data] - for var, lim in zip(self.data_info["limits"], limits): + limits = [max(axis) * lim_margin for axis in self.data] + for var, lim in zip(self.data_info['limits'], limits): var.set(value=lim) - for str_var, unit in zip(self.data_info["units"], units): + for str_var, unit in zip(self.data_info['units'], units): str_var.set(unit) self.update_axes(limits=True, units=True) self.redraw_plot() - new_headers = [f"{label} ({unit.get()})" for label, unit in zip( - self.data_info["labels"], self.data_info["units"])] + new_headers = [ + f'{label} ({unit.get()})' + for label, unit in zip(self.data_info['labels'], self.data_info['units']) + ] self.update_header(new_headers) self.update_table(overwrite=True, bool_list=bool_list) def save_as(self): """Creates a file dialog that saves as a phase info. User can specify filename and location.""" filename = filedialog.asksaveasfilename( - defaultextension='.py', confirmoverwrite=True, - filetypes=[("Python files", "*.py")], - initialfile='outputted_phase_info') + defaultextension='.py', + confirmoverwrite=True, + filetypes=[('Python files', '*.py')], + initialfile='outputted_phase_info', + ) if not filename: return self.save(filename=filename) def save(self, filename=None): """Saves mission into a file as a phase info dictionary which can be used by Aviary. - This function is also called by the save as function with a non-default filename. """ - for i in range(len(self.data[0])-1): - if self.data[0][i] > self.data[0][i+1]: # going backwards in time + This function is also called by the save as function with a non-default filename. + """ + for i in range(len(self.data[0]) - 1): + if self.data[0][i] > self.data[0][i + 1]: # going backwards in time messagebox.showerror( - title="Time Travel Error", - message="All mission points must go forwards in time! Edit points and try again.") + title='Time Travel Error', + message='All mission points must go forwards in time! Edit points and try again.', + ) return low_mach = 0.25 if min(self.data[2]) < low_mach: # low mach value in mission - message = f"Low mach values (below {low_mach}) can cause issues with FLOPS based models.\n" +\ - "Would you like to continue saving this mission?" - continue_saving = messagebox.askyesno(title="Low Mach Values", - message=message) + message = ( + f'Low mach values (below {low_mach}) can cause issues with FLOPS based models.\n' + + 'Would you like to continue saving this mission?' + ) + continue_saving = messagebox.askyesno(title='Low Mach Values', message=message) if not continue_saving: return - users = {'solve_for_distance': self.advanced_options["solve_for_distance"].get(), - 'constrain_range': self.advanced_options["constrain_range"].get(), - 'include_takeoff': self.advanced_options["include_takeoff"].get(), - 'include_landing': self.advanced_options["include_landing"].get()} - polyord = self.advanced_options["polynomial_control_order"].get() - if len(self.table_boolvars[0]) != len(self.data[0])-1: + users = { + 'distance_solve_segments': self.advanced_options['distance_solve_segments'].get(), + 'constrain_range': self.advanced_options['constrain_range'].get(), + 'include_takeoff': self.advanced_options['include_takeoff'].get(), + 'include_landing': self.advanced_options['include_landing'].get(), + } + polyord = self.advanced_options['polynomial_order'].get() + if len(self.table_boolvars[0]) != len(self.data[0]) - 1: for i in range(self.num_dep_vars): - self.table_boolvars[i] = [tk.BooleanVar()]*(len(self.data[0])-1) + self.table_boolvars[i] = [tk.BooleanVar()] * (len(self.data[0]) - 1) if not filename: filename = os.path.join(os.getcwd(), 'outputted_phase_info.py') @@ -1339,25 +1519,38 @@ def save(self, filename=None): times=self.data[0], altitudes=self.data[1], mach_values=self.data[2], - units=[item.get() for item in self.data_info["units"]], - polynomial_order=polyord, num_segments=len(self.data[0]) - 1, - optimize_altitude_phase_vars=self.table_boolvars[0], - optimize_mach_phase_vars=self.table_boolvars[1], - user_choices=users, orders=self.phase_order_list, filename=filename) + units=[item.get() for item in self.data_info['units']], + polynomial_order=polyord, + num_segments=len(self.data[0]) - 1, + altitude_optimize_phase_vars=self.table_boolvars[0], + mach_optimize_phase_vars=self.table_boolvars[1], + user_choices=users, + orders=self.phase_order_list, + filename=filename, + ) self.close_window() # button hover color functions - def on_enter( - self, event): event.widget["background"] = self.pallete[self.theme]["hover"] - - def on_leave(self, event): event.widget["background"] = self.pallete[self.theme][ - "background_primary"] - - -def create_phase_info(times, altitudes, mach_values, units, - polynomial_order, num_segments, optimize_mach_phase_vars, - optimize_altitude_phase_vars, user_choices, - orders, filename='outputted_phase_info.py'): + def on_enter(self, event): + event.widget['background'] = self.pallete[self.theme]['hover'] + + def on_leave(self, event): + event.widget['background'] = self.pallete[self.theme]['background_primary'] + + +def create_phase_info( + times, + altitudes, + mach_values, + units, + polynomial_order, + num_segments, + mach_optimize_phase_vars, + altitude_optimize_phase_vars, + user_choices, + orders, + filename='outputted_phase_info.py', +): """ Creates a dictionary containing the information about different flight phases based on input times, altitudes, and Mach values. @@ -1385,8 +1578,7 @@ def create_phase_info(times, altitudes, mach_values, units, # times = np.round(np.array(times)).astype(int) # altitudes = np.round(np.array(altitudes) / 500) * 500 # mach_values = np.round(np.array(mach_values), 2) - times, altitudes, mach_values = np.array( - times), np.array(altitudes), np.array(mach_values) + times, altitudes, mach_values = np.array(times), np.array(altitudes), np.array(mach_values) # Utility function to create bounds def create_bounds(center): @@ -1395,15 +1587,14 @@ def create_bounds(center): return (lower_bound, upper_bound) # Calculate duration bounds for each phase - duration_bounds = [create_bounds(times[i+1] - times[i]) - for i in range(num_phases)] + duration_bounds = [create_bounds(times[i + 1] - times[i]) for i in range(num_phases)] # Initialize the cumulative initial bounds - cumulative_initial_bounds = [(0., 0.)] # Initial bounds for the first phase + cumulative_initial_bounds = [(0.0, 0.0)] # Initial bounds for the first phase # Calculate the cumulative initial bounds for subsequent phases for i in range(1, num_phases): - previous_duration_bounds = duration_bounds[i-1] + previous_duration_bounds = duration_bounds[i - 1] previous_initial_bounds = cumulative_initial_bounds[-1] new_initial_bound_min = previous_initial_bounds[0] + previous_duration_bounds[0] new_initial_bound_max = previous_initial_bounds[1] + previous_duration_bounds[1] @@ -1411,17 +1602,17 @@ def create_bounds(center): # Add pre_mission and post_mission phases phase_info['pre_mission'] = { - 'include_takeoff': user_choices["include_takeoff"], + 'include_takeoff': user_choices['include_takeoff'], 'optimize_mass': True, } climb_count = 1 cruise_count = 1 descent_count = 1 - alt_margin = convert_units(500, "ft", units[1]) + alt_margin = convert_units(500, 'ft', units[1]) for i in range(num_phases): initial_altitude = altitudes[i] - final_altitude = altitudes[i+1] + final_altitude = altitudes[i + 1] # Determine phase type: climb, cruise, or descent if final_altitude > initial_altitude: @@ -1440,75 +1631,85 @@ def create_bounds(center): phase_name = f'{phase_type}_{phase_count}' phase_info[phase_name] = { - 'subsystem_options': { - 'core_aerodynamics': {'method': 'computed'} - }, + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, 'user_options': { - 'optimize_mach': optimize_mach_phase_vars[i].get(), - 'optimize_altitude': optimize_altitude_phase_vars[i].get(), - 'polynomial_control_order': polynomial_order, - 'use_polynomial_control': True, 'num_segments': num_segments, 'order': orders[i], - 'solve_for_distance': False, - 'initial_mach': (mach_values[i], units[2]), - 'final_mach': (mach_values[i+1], units[2]), - 'mach_bounds': ((np.min(mach_values[i:i+2]) - 0.02, np.max(mach_values[i:i+2]) + 0.02), units[2]), - 'initial_altitude': (altitudes[i], units[1]), - 'final_altitude': (altitudes[i+1], units[1]), - 'altitude_bounds': ((max(np.min(altitudes[i:i+2]) - alt_margin, 0.), np.max(altitudes[i:i+2]) + alt_margin), units[1]), - 'throttle_enforcement': 'path_constraint' if (i == (num_phases - 1) or i == 0) else 'boundary_constraint', - 'fix_initial': True if i == 0 else False, - 'constrain_final': True if i == (num_phases - 1) else False, - 'fix_duration': False, - 'initial_bounds': (cumulative_initial_bounds[i], units[0]), - 'duration_bounds': (duration_bounds[i], units[0]), + 'mach_optimize': mach_optimize_phase_vars[i].get(), + 'mach_polynomial_order': polynomial_order, + 'mach_initial': (mach_values[i], units[2]), + 'mach_final': (mach_values[i + 1], units[2]), + 'mach_bounds': ( + (np.min(mach_values[i : i + 2]) - 0.02, np.max(mach_values[i : i + 2]) + 0.02), + units[2], + ), + 'altitude_optimize': altitude_optimize_phase_vars[i].get(), + 'altitude_polynomial_order': polynomial_order, + 'altitude_initial': (altitudes[i], units[1]), + 'altitude_final': (altitudes[i + 1], units[1]), + 'altitude_bounds': ( + ( + max(np.min(altitudes[i : i + 2]) - alt_margin, 0.0), + np.max(altitudes[i : i + 2]) + alt_margin, + ), + units[1], + ), + 'throttle_enforcement': 'path_constraint' + if (i == (num_phases - 1) or i == 0) + else 'boundary_constraint', + 'time_initial_bounds': (cumulative_initial_bounds[i], units[0]), + 'time_duration_bounds': (duration_bounds[i], units[0]), }, 'initial_guesses': { - 'time': ([times[i], times[i+1]-times[i]], units[0]), - } + 'time': ([times[i], times[i + 1] - times[i]], units[0]), + }, } phase_info['post_mission'] = { - 'include_landing': user_choices["include_landing"], + 'include_landing': user_choices['include_landing'], 'constrain_range': True, - 'target_range': (0., 'nmi'), + 'target_range': (0.0, 'nmi'), } # Apply user choices to each phase for phase_name, _ in phase_info.items(): if 'pre_mission' in phase_name or 'post_mission' in phase_name: continue - phase_info[phase_name]['user_options'].update({ - 'solve_for_distance': user_choices.get('solve_for_distance', False), - }) + phase_info[phase_name]['user_options'].update( + { + 'distance_solve_segments': user_choices.get('distance_solve_segments', False), + } + ) # Apply global settings if required - phase_info['post_mission']['constrain_range'] = user_choices.get( - 'constrain_range', True) + phase_info['post_mission']['constrain_range'] = user_choices.get('constrain_range', True) # Calculate the total range total_range, range_unit = estimate_total_range_trapezoidal(times, mach_values, units) - print( - f"Total range is estimated to be {total_range} {range_unit}") + print(f'Total range is estimated to be {total_range} {range_unit}') phase_info['post_mission']['target_range'] = (total_range, range_unit) # write a python file with the phase information with open(filename, 'w') as f: - f.write(f'phase_info = {phase_info}') + f.write('phase_info = ') + pp = pprint.PrettyPrinter(indent=4, stream=f, sort_dicts=False) + pp.pprint(phase_info) - # Check for 'black' and format the file - if shutil.which('black'): - subprocess.run(['black', filename]) + # Check for 'ruff' and format the file + if shutil.which('ruff'): + subprocess.run(['ruff', filename]) else: if shutil.which('autopep8'): subprocess.run(['autopep8', '--in-place', '--aggressive', filename]) print("File formatted using 'autopep8'") else: - print("'black' and 'autopep8' are not installed. Please consider installing one of them for better formatting.") + print( + "'ruff' or 'autopep8' are not installed. Please consider installing one of them " + 'for better formatting.' + ) - print(f"Phase info has been saved and formatted in {filename}") + print(f'Phase info has been saved and formatted in {filename}') return phase_info @@ -1518,7 +1719,7 @@ def estimate_total_range_trapezoidal(times, mach_numbers, units): speed_of_sound = 343 # Speed of sound in meters per second # convert time list into np array with units of seconds - times_sec = np.array([convert_units(time, units[0], "s") for time in times]) + times_sec = np.array([convert_units(time, units[0], 's') for time in times]) # Calculate the speeds at each Mach number speeds = np.array(mach_numbers) * speed_of_sound @@ -1527,13 +1728,13 @@ def estimate_total_range_trapezoidal(times, mach_numbers, units): total_range = np.trapz(speeds, times_sec) # in meters range_unit = units[1] # m and ft are small units for range, change to larger ones - if range_unit == "m": - range_unit = "km" - if range_unit == "ft": - range_unit = "nmi" + if range_unit == 'm': + range_unit = 'km' + if range_unit == 'ft': + range_unit = 'nmi' # return range in the same units as altitude units - return round(convert_units(total_range, "m", range_unit), 2), range_unit + return round(convert_units(total_range, 'm', range_unit), 2), range_unit def _setup_flight_profile_parser(parser): @@ -1563,6 +1764,6 @@ def _exec_flight_profile(options, user_args): app.mainloop() -if __name__ == "__main__": +if __name__ == '__main__': app = AviaryMissionEditor() app.mainloop() diff --git a/aviary/interface/methods_for_level1.py b/aviary/interface/methods_for_level1.py index b93d39c47e..6ffc729036 100644 --- a/aviary/interface/methods_for_level1.py +++ b/aviary/interface/methods_for_level1.py @@ -1,21 +1,26 @@ -""" -This file contains functions needed to run Aviary using the Level 1 interface. -""" -import os -from importlib.machinery import SourceFileLoader +"""This file contains functions needed to run Aviary using the Level 1 interface.""" + +from importlib.util import spec_from_file_location, module_from_spec from pathlib import Path +import sys -import openmdao.api as om -from aviary.variable_info.enums import AnalysisScheme, Verbosity from aviary.interface.methods_for_level2 import AviaryProblem from aviary.utils.functions import get_path +from aviary.variable_info.enums import Verbosity -def run_aviary(aircraft_filename, phase_info, optimizer=None, - analysis_scheme=AnalysisScheme.COLLOCATION, objective_type=None, - record_filename='problem_history.db', restart_filename=None, max_iter=50, - run_driver=True, make_plots=True, phase_info_parameterization=None, - optimization_history_filename=None, verbosity=Verbosity.BRIEF): +def run_aviary( + aircraft_data, + phase_info, + optimizer=None, + objective_type=None, + restart_filename=None, + max_iter=50, + run_driver=True, + make_plots=True, + phase_info_parameterization=None, + verbosity=None, +): """ Run the Aviary optimization problem for a specified aircraft configuration and mission. @@ -26,18 +31,15 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, Parameters ---------- - aircraft_filename : str - Filename from which to load the aircraft and options data. + aircraft_data: str, Path, AviaryValues + Filename from which to load the aircraft and options data, either as a string or + Path object, or an AviaryValues object containing that information. phase_info : dict Information about the phases of the mission. optimizer : str The optimizer to use. - analysis_scheme : AnalysisScheme, optional - The analysis scheme to use, defaults to AnalysisScheme.COLLOCATION. objective_type : str, optional Type of the optimization objective. - record_filename : str, optional - Filename for recording the solution, defaults to 'dymos_solution.db'. restart_filename : str, optional Filename to use for restarting the optimization, if applicable. max_iter : int, optional @@ -47,13 +49,11 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, make_plots : bool, optional If True, generate plots during the optimization, defaults to True. phase_info_parameterization : function, optional - Additional information to parameterize the phase_info object based on - desired cruise altitude and Mach. - optimization_history_filename : str or Path - The name of the database file where the driver iterations are to be recorded. The - default is None. - verbosity : Verbosity or int + Additional information to parameterize the phase_info object based on desired cruise + altitude and Mach. + verbosity : Verbosity or int, optional Sets level of information outputted to the terminal during model execution. + If provided, overrides verbosity specified in aircraft_data. Returns ------- @@ -66,133 +66,104 @@ def run_aviary(aircraft_filename, phase_info, optimizer=None, It raises warnings or errors if there are clashing user inputs. Users can modify or add methods to alter the Aviary problem's behavior. """ - # compatibility with being passed int for verbosity - verbosity = Verbosity(verbosity) + # If loading from a file, use filename as problem name. Else, use OpenMDAO default + if isinstance(aircraft_data, (str, Path)): + name = Path(aircraft_data).stem + else: + name = None # Build problem - prob = AviaryProblem(analysis_scheme, name=Path(aircraft_filename).stem) + prob = AviaryProblem(name=name, verbosity=verbosity) # Load aircraft and options data from user # Allow for user overrides here - prob.load_inputs(aircraft_filename, phase_info, verbosity=verbosity) + prob.load_inputs(aircraft_data, phase_info, verbosity=verbosity) - # Preprocess inputs - prob.check_and_preprocess_inputs() + prob.check_and_preprocess_inputs(verbosity=verbosity) - prob.add_pre_mission_systems() + # Add Systems + prob.add_pre_mission_systems(verbosity=verbosity) - prob.add_phases(phase_info_parameterization=phase_info_parameterization) + prob.add_phases(phase_info_parameterization=phase_info_parameterization, verbosity=verbosity) - prob.add_post_mission_systems() + prob.add_post_mission_systems(verbosity=verbosity) # Link phases and variables - prob.link_phases() + prob.link_phases(verbosity=verbosity) prob.add_driver(optimizer, max_iter=max_iter, verbosity=verbosity) - prob.add_design_variables() + prob.add_design_variables(verbosity=verbosity) # Load optimization problem formulation # Detail which variables the optimizer can control - prob.add_objective(objective_type=objective_type) - - prob.setup() + prob.add_objective(objective_type=objective_type, verbosity=verbosity) - prob.set_initial_guesses() + prob.setup(verbosity=verbosity) prob.run_aviary_problem( - record_filename, restart_filename=restart_filename, run_driver=run_driver, + restart_filename=restart_filename, + run_driver=run_driver, make_plots=make_plots, - optimization_history_filename=optimization_history_filename) + verbosity=verbosity, + ) return prob def run_level_1( - input_deck, - outdir='output', - optimizer='SNOPT', - phase_info=None, - max_iter=50, - analysis_scheme=AnalysisScheme.COLLOCATION, + input_deck, optimizer='IPOPT', phase_info=None, max_iter=50, verbosity=Verbosity.BRIEF ): - ''' + """ This file enables running aviary from the command line with a user specified input deck. - usage: aviary run_mission [input_deck] [opt_args] - ''' - - kwargs = { - 'max_iter': max_iter, - } - - if analysis_scheme is AnalysisScheme.SHOOTING: - kwargs['analysis_scheme'] = AnalysisScheme.SHOOTING - kwargs['run_driver'] = False - # kwargs['optimizer'] = 'IPOPT' - # else: - kwargs['optimizer'] = optimizer + usage: aviary run_mission [input_deck] [opt_args]. + """ + kwargs = {'max_iter': max_iter, 'optimizer': optimizer, 'verbosity': Verbosity(verbosity)} if isinstance(phase_info, str): phase_info_path = get_path(phase_info) - phase_info_file = SourceFileLoader( - "phase_info_file", str(phase_info_path)).load_module() + spec = spec_from_file_location('phase_info_file', str(phase_info_path)) + phase_info_file = module_from_spec(spec) + sys.modules['phase_info_file'] = phase_info_file + spec.loader.exec_module(phase_info_file) + phase_info = getattr(phase_info_file, 'phase_info') kwargs['phase_info_parameterization'] = getattr( - phase_info_file, 'phase_info_parameterization', None) + phase_info_file, 'phase_info_parameterization', None + ) prob = run_aviary(input_deck, phase_info, **kwargs) - # update n2 diagram after run. - outfile = os.path.join(outdir, "n2.html") - if outdir != '': - os.makedirs(outdir, exist_ok=True) - om.n2( - prob, - outfile=outfile, - show_browser=False, - ) - return prob def _setup_level1_parser(parser): - def_outdir = os.path.join(os.getcwd(), "output") - parser.add_argument('input_deck', metavar='indeck', type=str, - nargs=1, help='Name of vehicle input deck file') - parser.add_argument( - "-o", "--outdir", default=def_outdir, help="Directory to write outputs" - ) parser.add_argument( - "--optimizer", + 'input_deck', + metavar='indeck', type=str, - default='SNOPT', - help="Name of optimizer", - choices=("SNOPT", "IPOPT", "SLSQP", "None") + nargs=1, + help='Name of vehicle input deck file', ) parser.add_argument( - "--phase_info", + '--optimizer', type=str, - default=None, - help="Path to phase info file" + default='IPOPT', + help='Name of optimizer', + choices=('SNOPT', 'IPOPT', 'SLSQP', 'None'), ) + parser.add_argument('--phase_info', type=str, default=None, help='Path to phase info file') + parser.add_argument('--max_iter', type=int, default=50, help='maximum number of iterations') parser.add_argument( - "--max_iter", + '--verbosity', type=int, - default=50, - help="maximum number of iterations") - parser.add_argument( - "--shooting", - action="store_true", - help="Use shooting instead of collocation", + default=1, + help='verbosity settings: 0=quiet, 1=brief, 2=verbose, 3=debug', + choices=(0, 1, 2, 3), ) def _exec_level1(args, user_args): - if args.shooting: - analysis_scheme = AnalysisScheme.SHOOTING - else: - analysis_scheme = AnalysisScheme.COLLOCATION - if args.optimizer == 'None': args.optimizer = None @@ -200,16 +171,10 @@ def _exec_level1(args, user_args): if isinstance(args.input_deck, list): args.input_deck = args.input_deck[0] - if args.outdir == os.path.join(os.getcwd(), "output"): - # if default outdir, add the input deck name - file_name_stem = Path(args.input_deck).stem - args.outdir = args.outdir + os.sep + file_name_stem - - prob = run_level_1( + run_level_1( input_deck=args.input_deck, - outdir=args.outdir, optimizer=args.optimizer, phase_info=args.phase_info, max_iter=args.max_iter, - analysis_scheme=analysis_scheme, + verbosity=args.verbosity, ) diff --git a/aviary/interface/methods_for_level2.py b/aviary/interface/methods_for_level2.py index 01d141f075..b599c1a26a 100644 --- a/aviary/interface/methods_for_level2.py +++ b/aviary/interface/methods_for_level2.py @@ -1,223 +1,36 @@ -from dymos.transcriptions.transcription_base import TranscriptionBase import csv +import json +import math +import os import warnings -import inspect -from pathlib import Path +from copy import deepcopy from datetime import datetime -import importlib.util -import sys -import json -import enum - -import numpy as np +from enum import Enum +from pathlib import Path import dymos as dm -from dymos.utils.misc import _unspecified - +import numpy as np +import openmdao import openmdao.api as om -from openmdao.core.component import Component -from openmdao.utils.mpi import MPI from openmdao.utils.reports_system import _default_reports +from openmdao.utils.units import convert_units +from packaging import version -from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH -from aviary.interface.default_phase_info.two_dof_fiti import add_default_sgm_args -from aviary.interface.utils.check_phase_info import check_phase_info -from aviary.mission.energy_phase import EnergyPhase -from aviary.mission.flops_based.phases.build_landing import Landing -from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.mission.twodof_phase import TwoDOFPhase -from aviary.mission.gasp_based.idle_descent_estimation import add_descent_estimation_as_submodel -from aviary.mission.gasp_based.ode.params import ParamPort -from aviary.mission.gasp_based.phases.time_integration_traj import FlexibleTraj -from aviary.mission.gasp_based.phases.groundroll_phase import GroundrollPhase -from aviary.mission.flops_based.phases.groundroll_phase import GroundrollPhase as GroundrollPhaseVelocityIntegrated -from aviary.mission.gasp_based.phases.rotation_phase import RotationPhase -from aviary.mission.gasp_based.phases.climb_phase import ClimbPhase -from aviary.mission.gasp_based.phases.cruise_phase import CruisePhase -from aviary.mission.gasp_based.phases.accel_phase import AccelPhase -from aviary.mission.gasp_based.phases.ascent_phase import AscentPhase -from aviary.mission.gasp_based.phases.descent_phase import DescentPhase -from aviary.mission.gasp_based.ode.landing_ode import LandingSegment -from aviary.mission.gasp_based.ode.taxi_ode import TaxiSegment -from aviary.mission.gasp_based.phases.v_rotate_comp import VRotateComp -from aviary.mission.gasp_based.polynomial_fit import PolynomialFit -from aviary.mission.phase_builder_base import PhaseBuilderBase - -from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder -from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder -from aviary.subsystems.mass.mass_builder import CoreMassBuilder -from aviary.subsystems.premission import CorePreMission -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder - +from aviary.core.aviary_group import AviaryGroup +from aviary.interface.utils import set_warning_format from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import create_opts2vals, add_opts2vals, promote_aircraft_and_mission_vars, wrapped_convert_units -from aviary.utils.functions import convert_strings_to_data, set_value +from aviary.utils.csv_data_file import write_data_file +from aviary.utils.functions import convert_strings_to_data, get_path from aviary.utils.merge_variable_metadata import merge_meta_data -from aviary.utils.preprocessors import preprocess_options -from aviary.utils.process_input_decks import create_vehicle, update_GASP_options, initialization_guessing - -from aviary.variable_info.enums import AnalysisScheme, ProblemType, EquationsOfMotion, LegacyCode, Verbosity -from aviary.variable_info.functions import setup_trajectory_params, override_aviary_vars -from aviary.variable_info.variables import Aircraft, Mission, Dynamic, Settings +from aviary.utils.named_values import NamedValues +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode, ProblemType, Verbosity +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings FLOPS = LegacyCode.FLOPS GASP = LegacyCode.GASP -TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM -HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY -SOLVED_2DOF = EquationsOfMotion.SOLVED_2DOF - -if hasattr(TranscriptionBase, 'setup_polynomial_controls'): - use_new_dymos_syntax = False -else: - use_new_dymos_syntax = True - - -class PreMissionGroup(om.Group): - """OpenMDAO group that holds all pre-mission systems""" - - def configure(self): - """ - Configure this group for pre-mission. - Promote aircraft and mission variables. - Override output aviary variables. - """ - external_outputs = promote_aircraft_and_mission_vars(self) - - pre_mission = self.core_subsystems - override_aviary_vars( - pre_mission, - pre_mission.options["aviary_options"], - external_overrides=external_outputs, - manual_overrides=pre_mission.manual_overrides, - ) - - -class PostMissionGroup(om.Group): - """OpenMDAO group that holds all post-mission systems""" - - def configure(self): - """ - Congigure this group for post-mission. - Promote aircraft and mission variables. - """ - promote_aircraft_and_mission_vars(self) - - -class AviaryGroup(om.Group): - """ - A standard OpenMDAO group that handles Aviary's promotions in the configure - method. This assures that we only call set_input_defaults on variables - that are present in the model. - """ - - def initialize(self): - """declare options""" - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - self.options.declare( - 'aviary_metadata', types=dict, - desc='metadata dictionary of the full aviary problem.') - self.options.declare( - 'phase_info', types=dict, - desc='phase-specific settings.') - - def configure(self): - """ - Configure the Aviary group - """ - aviary_options = self.options['aviary_options'] - aviary_metadata = self.options['aviary_metadata'] - - # Find promoted name of every input in the model. - all_prom_inputs = [] - - # We can call list_inputs on the subsystems. - for system in self.system_iter(recurse=False): - var_abs = system.list_inputs(out_stream=None, val=False) - var_prom = [v['prom_name'] for k, v in var_abs] - all_prom_inputs.extend(var_prom) - - # Calls to promotes aren't handled until this group resolves. - # Here, we address anything promoted with an alias in AviaryProblem. - input_meta = system._var_promotes['input'] - var_prom = [v[0][1] for v in input_meta if isinstance(v[0], tuple)] - all_prom_inputs.extend(var_prom) - var_prom = [v[0] for v in input_meta if not isinstance(v[0], tuple)] - all_prom_inputs.extend(var_prom) - - if MPI and self.comm.size > 1: - # Under MPI, promotion info only lives on rank 0, so broadcast. - all_prom_inputs = self.comm.bcast(all_prom_inputs, root=0) - - for key in aviary_metadata: - - if ':' not in key or key.startswith('dynamic:'): - continue - - if aviary_metadata[key]['option']: - continue - - # Skip anything that is not presently an input. - if key not in all_prom_inputs: - continue - - if key in aviary_options: - val, units = aviary_options.get_item(key) - else: - val = aviary_metadata[key]['default_value'] - units = aviary_metadata[key]['units'] - - if val is None: - # optional, but no default value - continue - - self.set_input_defaults(key, val=val, units=units) - - # The section below this contains some manipulations of the dymos solver - # structure for height energy. - if aviary_options.get_val(Settings.EQUATIONS_OF_MOTION) is not HEIGHT_ENERGY: - return - - phase_info = self.options['phase_info'] - - # Set a more appropriate solver for dymos when the phases are linked. - if MPI and isinstance(self.traj.phases.linear_solver, om.PETScKrylov): - - # When any phase is connected with input_initial = True, dymos puts - # a jacobi solver in the phases group. This is necessary in case - # the phases are cyclic. However, this causes some problems - # with the newton solvers in Aviary, exacerbating issues with - # solver tolerances at multiple levels. Since Aviary's phases - # are basically in series, the jacobi solver is a much better - # choice and should be able to handle it in a couple of - # iterations. - self.traj.phases.linear_solver = om.LinearBlockJac(maxiter=5) - - # Due to recent changes in dymos, there is now a solver in any phase - # that has connected initial states. It is not clear that this solver - # is necessary except in certain corner cases that do not apply to the - # Aviary trajectory. In our case, this solver merely addresses a lag - # in the state input component. Since this solver can cause some - # numerical problems, and can slow things down, we need to move it down - # into the state interp component. - # TODO: Future updates to dymos may make this unneccesary. - for phase in self.traj.phases.system_iter(recurse=False): - - # Don't move the solvers if we are using solve segements. - if phase_info[phase.name]['user_options'].get('solve_for_distance'): - continue - - phase.nonlinear_solver = om.NonlinearRunOnce() - phase.linear_solver = om.LinearRunOnce() - if isinstance(phase.indep_states, om.ImplicitComponent): - phase.indep_states.nonlinear_solver = \ - om.NewtonSolver(solve_subsystems=True) - phase.indep_states.linear_solver = om.DirectSolver(rhs_checking=True) - class AviaryProblem(om.Problem): """ @@ -235,9 +48,22 @@ class AviaryProblem(om.Problem): additional methods to help users create and solve Aviary problems. """ - def __init__(self, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): + def __init__( + self, + problem_type: ProblemType = None, + verbosity=None, + meta_data=BaseMetaData.copy(), + **kwargs, + ): # Modify OpenMDAO's default_reports for this session. - new_reports = ['subsystems', 'mission', 'timeseries_csv', 'run_status'] + new_reports = [ + 'subsystems', + 'mission', + 'timeseries_csv', + 'run_status', + 'sizing_results', + 'input_checks', + ] for report in new_reports: if report not in _default_reports: _default_reports.append(report) @@ -246,1183 +72,301 @@ def __init__(self, analysis_scheme=AnalysisScheme.COLLOCATION, **kwargs): self.timestamp = datetime.now() - self.model = AviaryGroup() - self.pre_mission = PreMissionGroup() - self.post_mission = PostMissionGroup() + # If verbosity is set to anything but None, this defines how warnings are formatted for the + # whole problem - warning format won't be updated if user requests a different verbosity + # level for a specific method + self.verbosity = verbosity + set_warning_format(verbosity) - self.aviary_inputs = None + self.problem_type = problem_type + if problem_type == ProblemType.MULTI_MISSION: + self.model = om.Group() + else: + self.model = AviaryGroup() + self.aviary_inputs = None - self.traj = None + self.aviary_groups_dict = {} - self.analysis_scheme = analysis_scheme + self.meta_data = meta_data - self.regular_phases = [] - self.reserve_phases = [] + # TODO try and find a better solution than a new custom flag - the issue is multimission + # problems don't have a consistent variable path to check the inputs later on + self.generate_payload_range = False def load_inputs( - self, aviary_inputs, phase_info=None, engine_builders=None, - meta_data=BaseMetaData, verbosity=Verbosity.BRIEF): - """ - This method loads the aviary_values inputs and options that the - user specifies. They could specify files to load and values to - replace here as well. - Phase info is also loaded if provided by the user. If phase_info is None, - the appropriate default phase_info based on mission analysis method is used. - - This method is not strictly necessary; a user could also supply - an AviaryValues object and/or phase_info dict of their own. + self, + aircraft_data, + phase_info=None, + engine_builders=None, + problem_configurator=None, + meta_data=None, + verbosity=None, + ): """ - # compatibility with being passed int for verbosity - verbosity = Verbosity(verbosity) - ## LOAD INPUT FILE ### - # Create AviaryValues object from file (or process existing AviaryValues object - # with default values from metadata) and generate initial guesses - aviary_inputs, initialization_guesses = create_vehicle( - aviary_inputs, meta_data=meta_data, verbosity=verbosity) - - # pull which methods will be used for subsystems and mission - self.mission_method = mission_method = aviary_inputs.get_val( - Settings.EQUATIONS_OF_MOTION) - self.mass_method = mass_method = aviary_inputs.get_val(Settings.MASS_METHOD) - - if mission_method is TWO_DEGREES_OF_FREEDOM or mass_method is GASP: - aviary_inputs = update_GASP_options(aviary_inputs) - initialization_guesses = initialization_guessing(aviary_inputs, initialization_guesses, - engine_builders) - self.aviary_inputs = aviary_inputs - self.initialization_guesses = initialization_guesses - - ## LOAD PHASE_INFO ### - if phase_info is None: - # check if the user generated a phase_info from gui - # Load the phase info dynamically from the current working directory - phase_info_module_path = Path.cwd() / 'outputted_phase_info.py' - - if phase_info_module_path.exists(): - spec = importlib.util.spec_from_file_location( - 'outputted_phase_info', phase_info_module_path) - outputted_phase_info = importlib.util.module_from_spec(spec) - sys.modules['outputted_phase_info'] = outputted_phase_info - spec.loader.exec_module(outputted_phase_info) + This method loads the aviary_values inputs and options that the user specifies. They could + specify files to load and values to replace here as well. - # Access the phase_info variable from the loaded module - phase_info = outputted_phase_info.phase_info - - # if verbosity level is BRIEF or higher, print that we're using the outputted phase info - if verbosity is not None and verbosity >= Verbosity.BRIEF: - print('Using outputted phase_info from current working directory') - - else: - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - from aviary.interface.default_phase_info.two_dof import phase_info - elif self.analysis_scheme is AnalysisScheme.SHOOTING: - from aviary.interface.default_phase_info.two_dof_fiti import phase_info, \ - phase_info_parameterization - phase_info, _ = phase_info_parameterization( - phase_info, None, self.aviary_inputs) - - elif self.mission_method is HEIGHT_ENERGY: - from aviary.interface.default_phase_info.height_energy import phase_info - - if verbosity is not None and verbosity >= Verbosity.BRIEF: - print('Loaded default phase_info for ' - f'{self.mission_method.value.lower()} equations of motion') - - # create a new dictionary that only contains the phases from phase_info - self.phase_info = {} - - for phase_name in phase_info: - if 'external_subsystems' not in phase_info[phase_name]: - phase_info[phase_name]['external_subsystems'] = [] - - if phase_name not in ['pre_mission', 'post_mission']: - self.phase_info[phase_name] = phase_info[phase_name] - - # pre_mission and post_mission are stored in their own dictionaries. - if 'pre_mission' in phase_info: - self.pre_mission_info = phase_info['pre_mission'] - else: - self.pre_mission_info = {'include_takeoff': True, - 'external_subsystems': []} + Phase info is also loaded if provided by the user. If phase_info is None, the appropriate + default phase_info based on mission analysis method is used. - if 'post_mission' in phase_info: - self.post_mission_info = phase_info['post_mission'] + This method is not strictly necessary; a user could also supply an AviaryValues object + and/or phase_info dict of their own. + """ + # We haven't read the input data yet, we don't know what desired run verbosity is + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) else: - self.post_mission_info = {'include_landing': True, - 'external_subsystems': []} - - if engine_builders is None: - engine_builders = build_engine_deck(aviary_inputs) - self.engine_builders = engine_builders + verbosity = self.verbosity # usually None + + if meta_data is not None: + # Support for custom meta_data set. + self.meta_data = meta_data + + # TODO: We cannot pass self.verbosity back up from load inputs for multi-mission because there could be multiple .csv files + self.model.meta_data = self.meta_data + aviary_inputs, verbosity = self.model.load_inputs( + aircraft_data=aircraft_data, + phase_info=phase_info, + engine_builders=engine_builders, + problem_configurator=problem_configurator, + verbosity=verbosity, + ) self.aviary_inputs = aviary_inputs - - if mission_method is TWO_DEGREES_OF_FREEDOM: - aviary_inputs.set_val(Mission.Summary.CRUISE_MASS_FINAL, - val=self.initialization_guesses['cruise_mass_final'], units='lbm') - aviary_inputs.set_val(Mission.Summary.GROSS_MASS, - val=self.initialization_guesses['actual_takeoff_mass'], units='lbm') - - # Commonly referenced values - self.cruise_alt = aviary_inputs.get_val( - Mission.Design.CRUISE_ALTITUDE, units='ft') - self.problem_type = aviary_inputs.get_val(Settings.PROBLEM_TYPE) - self.mass_defect = aviary_inputs.get_val('mass_defect', units='lbm') - - self.cruise_mass_final = aviary_inputs.get_val( - Mission.Summary.CRUISE_MASS_FINAL, units='lbm') - - if self.post_mission_info is True and 'target_range' in self.post_mission_info: - self.target_range = wrapped_convert_units( - phase_info['post_mission']['target_range'], 'NM') - aviary_inputs.set_val(Mission.Summary.RANGE, - self.target_range, units='NM') - else: - self.target_range = aviary_inputs.get_val( - Mission.Design.RANGE, units='NM') - aviary_inputs.set_val(Mission.Summary.RANGE, aviary_inputs.get_val( - Mission.Design.RANGE, units='NM'), units='NM') - self.cruise_mach = aviary_inputs.get_val(Mission.Design.MACH) - self.require_range_residual = True - - elif mission_method is HEIGHT_ENERGY: + self.verbosity = verbosity + if self.problem_type is None: + # if there are multiple load_inputs() calls, only the problem type from the first aviary_values is used self.problem_type = aviary_inputs.get_val(Settings.PROBLEM_TYPE) - aviary_inputs.set_val(Mission.Summary.GROSS_MASS, - val=self.initialization_guesses['actual_takeoff_mass'], units='lbm') - if 'target_range' in self.post_mission_info: - aviary_inputs.set_val(Mission.Summary.RANGE, wrapped_convert_units( - phase_info['post_mission']['target_range'], 'NM'), units='NM') - self.require_range_residual = True - self.target_range = wrapped_convert_units( - phase_info['post_mission']['target_range'], 'NM') - else: - self.require_range_residual = False - # still instantiate target_range because it is used for default guesses for phase comps - self.target_range = aviary_inputs.get_val( - Mission.Design.RANGE, units='NM') - return aviary_inputs + # TODO try and find a better solution than a new custom flag - the issue is multimission + # problems don't have a consistent variable path to check the inputs later on + # BUG you can't specify generating payload-range diagram via aviary_inputs after load_inputs + if Settings.PAYLOAD_RANGE in aviary_inputs: + self.generate_payload_range = aviary_inputs.get_val(Settings.PAYLOAD_RANGE) - def _update_metadata_from_subsystems(self): - self.meta_data = BaseMetaData.copy() - - # loop through phase_info and external subsystems - for phase_name in self.phase_info: - external_subsystems = self._get_all_subsystems( - self.phase_info[phase_name]['external_subsystems']) - for subsystem in external_subsystems: - meta_data = subsystem.meta_data.copy() - self.meta_data = merge_meta_data([self.meta_data, meta_data]) + return self.aviary_inputs - def phase_separator(self): - """ - This method checks for reserve=True & False - Returns an error if a non-reserve phase is specified after a reserve phase. - return two dictionaries of phases: regular_phases and reserve_phases - For shooting trajectories, this will also check if a phase is part of the descent - """ - - # Check to ensure no non-reserve phases are specified after reserve phases - start_reserve = False - raise_error = False - for idx, phase_name in enumerate(self.phase_info): - if 'user_options' in self.phase_info[phase_name]: - if 'reserve' in self.phase_info[phase_name]["user_options"]: - if self.phase_info[phase_name]["user_options"]["reserve"] is False: - # This is a regular phase - self.regular_phases.append(phase_name) - if start_reserve is True: - raise_error = True - else: - # This is a reserve phase - self.reserve_phases.append(phase_name) - start_reserve = True - else: - # This is a regular phase by default - self.regular_phases.append(phase_name) - if start_reserve is True: - raise_error = True - - if raise_error is True: - raise ValueError( - f'In phase_info, reserve=False cannot be specified after a phase where reserve=True. ' - f'All reserve phases must happen after non-reserve phases. ' - f'Regular Phases : {self.regular_phases} | ' - f'Reserve Phases : {self.reserve_phases} ') - - if self.analysis_scheme is AnalysisScheme.SHOOTING: - self.descent_phases = {} - for name, info in self.phase_info.items(): - descent = info.get('descent_phase', False) - if descent: - self.descent_phases[name] = info - - def check_and_preprocess_inputs(self): + def check_and_preprocess_inputs(self, verbosity=None): """ This method checks the user-supplied input values for any potential problems and preprocesses the inputs to prepare them for use in the Aviary problem. """ - aviary_inputs = self.aviary_inputs - # Target_distance verification for all phases - # Checks to make sure target_distance is positive, - for idx, phase_name in enumerate(self.phase_info): - if 'user_options' in self.phase_info[phase_name]: - if 'target_distance' in self.phase_info[phase_name]["user_options"]: - target_distance = self.phase_info[phase_name]["user_options"][ - "target_distance"] - if target_distance[0] <= 0: - raise ValueError( - f"Invalid target_distance in [{phase_name}].[user_options]. " - f"Current (value: {target_distance[0]}), " - f"(units: {target_distance[1]}) <= 0" - ) - - # Checks to make sure target_duration is positive, - # Sets duration_bounds, initial_guesses, and fixed_duration - for idx, phase_name in enumerate(self.phase_info): - if 'user_options' in self.phase_info[phase_name]: - analytic = False - if (self.analysis_scheme is AnalysisScheme.COLLOCATION) and (self.mission_method is EquationsOfMotion.TWO_DEGREES_OF_FREEDOM): - try: - # if the user provided an option, use it - analytic = self.phase_info[phase_name]["user_options"][ - 'analytic'] - except KeyError: - # if it isn't specified, only the default 2DOF cruise for collocation is analytic - if 'cruise' in phase_name: - analytic = self.phase_info[phase_name]["user_options"][ - 'analytic'] = True - else: - analytic = self.phase_info[phase_name]["user_options"][ - 'analytic'] = False - - if 'target_duration' in self.phase_info[phase_name]["user_options"]: - target_duration = self.phase_info[phase_name]["user_options"][ - "target_duration"] - if target_duration[0] <= 0: - raise ValueError( - f'Invalid target_duration in phase_info[{phase_name}]' - f'[user_options]. Current (value: {target_duration[0]}), ' - f'(units: {target_duration[1]}) <= 0")' - ) - - # Only applies to non-analytic phases (all HE and most 2DOF) - if not analytic: - # Set duration_bounds and initial_guesses for time: - self.phase_info[phase_name]["user_options"].update({ - "duration_bounds": ((target_duration[0], target_duration[0]), target_duration[1])}) - self.phase_info[phase_name].update({"initial_guesses": {"time": ( - (target_duration[0], target_duration[0]), target_duration[1])}}) - # Set Fixed_duration to true: - self.phase_info[phase_name]["user_options"].update({ - "fix_duration": True}) - - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - check_phase_info(self.phase_info, self.mission_method) - - for phase_name in self.phase_info: - for external_subsystem in self.phase_info[phase_name]['external_subsystems']: - aviary_inputs = external_subsystem.preprocess_inputs( - aviary_inputs) - - # PREPROCESSORS # - # Fill in anything missing in the options with computed defaults. - preprocess_options(aviary_inputs, engine_models=self.engine_builders) - - mission_method = aviary_inputs.get_val(Settings.EQUATIONS_OF_MOTION) - mass_method = aviary_inputs.get_val(Settings.MASS_METHOD) - - ## Set Up Core Subsystems ## - if mission_method in (HEIGHT_ENERGY, SOLVED_2DOF): - everything_else_origin = FLOPS - elif mission_method is TWO_DEGREES_OF_FREEDOM: - everything_else_origin = GASP - else: - raise ValueError(f'Unknown mission method {self.mission_method}') - - prop = CorePropulsionBuilder( - 'core_propulsion', engine_models=self.engine_builders) - mass = CoreMassBuilder('core_mass', code_origin=self.mass_method) - aero = CoreAerodynamicsBuilder( - 'core_aerodynamics', code_origin=everything_else_origin) - - # TODO These values are currently hardcoded, in future should come from user - both_geom = False - code_origin_to_prioritize = None - - # which geometry methods should be used, or both? - geom_code_origin = None - if (everything_else_origin is FLOPS) and (mass_method is FLOPS): - geom_code_origin = FLOPS - elif (everything_else_origin is GASP) and (mass_method is GASP): - geom_code_origin = GASP + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) else: - both_geom = True - - # which geometry method gets prioritized in case of conflicting outputs - if not code_origin_to_prioritize: - if everything_else_origin is GASP: - code_origin_to_prioritize = GASP - elif everything_else_origin is FLOPS: - code_origin_to_prioritize = FLOPS - - geom = CoreGeometryBuilder('core_geometry', - code_origin=geom_code_origin, - use_both_geometries=both_geom, - code_origin_to_prioritize=code_origin_to_prioritize) + verbosity = self.verbosity # defaults to BRIEF - subsystems = self.core_subsystems = {'propulsion': prop, - 'geometry': geom, - 'mass': mass, - 'aerodynamics': aero} + self.model.check_and_preprocess_inputs(verbosity=verbosity) - # TODO optionally accept which subsystems to load from phase_info - default_mission_subsystems = [ - subsystems['aerodynamics'], subsystems['propulsion']] - self.ode_args = {'aviary_options': aviary_inputs, - 'core_subsystems': default_mission_subsystems} - - self._update_metadata_from_subsystems() - - if self.mission_method in (HEIGHT_ENERGY, SOLVED_2DOF, TWO_DEGREES_OF_FREEDOM): - self.phase_separator() - - def add_pre_mission_systems(self): - """ - Add pre-mission systems to the Aviary problem. These systems are executed before the mission. - - Depending on the mission model specified (`FLOPS` or `GASP`), this method adds various subsystems - to the aircraft model. For the `FLOPS` mission model, a takeoff phase is added using the Takeoff class - with the number of engines and airport altitude specified. For the `GASP` mission model, three subsystems - are added: a TaxiSegment subsystem, an ExecComp to calculate the time to initiate gear and flaps, - and an ExecComp to calculate the speed at which to initiate rotation. All subsystems are promoted with - aircraft and mission inputs and outputs as appropriate. - - A user can override this method with their own pre-mission systems as desired. - """ - pre_mission = self.pre_mission - self.model.add_subsystem('pre_mission', pre_mission, - promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['aircraft:*', 'mission:*'],) - - if 'linear_solver' in self.pre_mission_info: - pre_mission.linear_solver = self.pre_mission_info['linear_solver'] - - if 'nonlinear_solver' in self.pre_mission_info: - pre_mission.nonlinear_solver = self.pre_mission_info['nonlinear_solver'] - - self._add_premission_external_subsystems() - - subsystems = self.core_subsystems - - # Propulsion isn't included in core pre-mission group to avoid override step in - # configure() - instead add it now - pre_mission.add_subsystem( - 'core_propulsion', subsystems['propulsion'].build_pre_mission( - self.aviary_inputs),) - - default_subsystems = [subsystems['geometry'], - subsystems['aerodynamics'], - subsystems['mass'],] - - pre_mission.add_subsystem( - 'core_subsystems', - CorePreMission( - aviary_options=self.aviary_inputs, - subsystems=default_subsystems, - process_overrides=False, - ), - promotes_inputs=['*'], - promotes_outputs=['*']) - - if not self.pre_mission_info['include_takeoff']: - return - - # Check for 2DOF mission method - # NOTE should solved trigger this as well? - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - self._add_two_dof_takeoff_systems() - - # Check for HE mission method - elif self.mission_method is HEIGHT_ENERGY: - self._add_height_energy_takeoff_systems() - - def _add_height_energy_takeoff_systems(self): - # Initialize takeoff options - takeoff_options = Takeoff( - airport_altitude=0., # ft - num_engines=self.aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES) - ) - - # Build and add takeoff subsystem - takeoff = takeoff_options.build_phase(False) - self.model.add_subsystem( - 'takeoff', takeoff, promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['mission:*']) - - def _add_two_dof_takeoff_systems(self): - # Create options to values - OptionsToValues = create_opts2vals( - [Aircraft.CrewPayload.NUM_PASSENGERS, - Mission.Design.CRUISE_ALTITUDE, ]) - add_opts2vals(self.model, OptionsToValues, self.aviary_inputs) - - if self.analysis_scheme is AnalysisScheme.SHOOTING: - self._add_fuel_reserve_component( - post_mission=False, reserves_name='reserve_fuel_estimate') - add_default_sgm_args(self.descent_phases, self.ode_args) - add_descent_estimation_as_submodel( - self, - phases=self.descent_phases, - cruise_mach=self.cruise_mach, - cruise_alt=self.cruise_alt, - reserve_fuel='reserve_fuel_estimate', - all_subsystems=self._get_all_subsystems(), - ) + # we have to update meta data after check_and_preprocess because metadata update + # requires get_all_subsystems, which requires core_subsystems, which doesn't exist until + # after check_and_preprocess is assembled + self._update_metadata_from_subsystems(self.model) # update meta data with new entries - # Add thrust-to-weight ratio subsystem - self.model.add_subsystem( - 'tw_ratio', - om.ExecComp( - f'TW_ratio = Fn_SLS / (takeoff_mass * {GRAV_ENGLISH_LBM})', - TW_ratio={'units': "unitless"}, - Fn_SLS={'units': 'lbf'}, - takeoff_mass={'units': 'lbm'}, - ), - promotes_inputs=[('Fn_SLS', Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST), - ('takeoff_mass', Mission.Summary.GROSS_MASS)], - promotes_outputs=[('TW_ratio', Aircraft.Design.THRUST_TO_WEIGHT_RATIO)], - ) - - self.cruise_alt = self.aviary_inputs.get_val( - Mission.Design.CRUISE_ALTITUDE, units='ft') - - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - # Add event transformation subsystem - self.model.add_subsystem( - "event_xform", - om.ExecComp( - ["t_init_gear=m*tau_gear+b", "t_init_flaps=m*tau_flaps+b"], - t_init_gear={"units": "s"}, # initial time that gear comes up - t_init_flaps={"units": "s"}, # initial time that flaps retract - tau_gear={"units": "unitless"}, - tau_flaps={"units": "unitless"}, - m={"units": "s"}, - b={"units": "s"}, - ), - promotes_inputs=[ - "tau_gear", # design var - "tau_flaps", # design var - ("m", Mission.Takeoff.ASCENT_DURATION), - ("b", Mission.Takeoff.ASCENT_T_INTIIAL), - ], - promotes_outputs=["t_init_gear", "t_init_flaps"], # link to h_fit + def _update_metadata_from_subsystems(self, group): + """Merge metadata from user-defined subsystems into problem metadata.""" + # loop through phase_info and external subsystems + for phase_name in group.mission_info: + external_subsystems = group.get_all_subsystems( + group.mission_info[phase_name]['external_subsystems'] ) - # Add taxi subsystem - self.model.add_subsystem( - "taxi", TaxiSegment(**(self.ode_args)), - promotes_inputs=['aircraft:*', 'mission:*'], - ) - - # Calculate speed at which to initiate rotation - self.model.add_subsystem( - "vrot", - om.ExecComp( - "Vrot = ((2 * mass * g) / (rho * wing_area * CLmax))**0.5 + dV1 + dVR", - Vrot={"units": "ft/s"}, - mass={"units": "lbm"}, - CLmax={"units": "unitless"}, - g={"units": "lbf/lbm", "val": GRAV_ENGLISH_LBM}, - rho={"units": "slug/ft**3", "val": RHO_SEA_LEVEL_ENGLISH}, - wing_area={"units": "ft**2"}, - dV1={ - "units": "ft/s", - "desc": "Increment of engine failure decision speed above stall", - }, - dVR={ - "units": "ft/s", - "desc": "Increment of takeoff rotation speed above engine failure " - "decision speed", - }, - ), - promotes_inputs=[ - ("wing_area", Aircraft.Wing.AREA), - ("dV1", Mission.Takeoff.DECISION_SPEED_INCREMENT), - ("dVR", Mission.Takeoff.ROTATION_SPEED_INCREMENT), - ("CLmax", Mission.Takeoff.LIFT_COEFFICIENT_MAX), - ], - promotes_outputs=[('Vrot', Mission.Takeoff.ROTATION_VELOCITY)] - ) + for subsystem in external_subsystems: + meta_data = subsystem.meta_data.copy() + self.meta_data = merge_meta_data([self.meta_data, meta_data]) - def _add_premission_external_subsystems(self): + # Update the reference to the newly merged meta_data. + group.meta_data = self.meta_data + + def add_aviary_group( + self, + name: str, + aircraft: AviaryValues, + mission: dict, + engine_builders=None, + problem_configurator=None, + verbosity: Verbosity = Verbosity.BRIEF, + ): """ - This private method adds each external subsystem to the pre-mission subsystem and - a mass component that captures external subsystem masses for use in mass buildups. + Used for creating a multi-mission problem. This method creates an AviaryGroup() for each + airraft and mission combination. It can also accept a specific engine_builder for each + group. The method loads and checks_and_preprocesses inputs, and then combines metadata. - Firstly, the method iterates through all external subsystems in the pre-mission - information. For each subsystem, it builds the pre-mission instance of the - subsystem. + Parameters + ---------- + name : string + A unique name that identifies this group which can be referenced later. + aircraft : AviaryValues object + Defines the aircraft configuration + mission : phase_info, dict + Defines the mission the aircraft will fly + engine_builders : EngineBuilder object, optional + Defines a custom engine model + problem_configurator ; ProblemConfigurator, optional + Required when setting custom equations of motion. See two_dof_problem_configurator.py for an example. + verbosity : Verbosity or int, optional + Controls the level of printouts for this method. - Secondly, the method collects the mass names of the added subsystems. This - expression is then used to define an ExecComp (a component that evaluates a - simple equation given input values). + Returns + ------- + subsystem + The AviaryGroup object containing the specified aircraft, mission, and engine model. - The method promotes the input and output of this ExecComp to the top level of the - pre-mission object, allowing this calculated subsystem mass to be accessed - directly from the pre-mission object. """ + if self.problem_type is not ProblemType.MULTI_MISSION: + ValueError( + 'add_aviary_group() should only be called when ProblemType is MULTI_MISSION.' + ) - mass_names = [] - # Loop through all the phases in this subsystem. - for external_subsystem in self.pre_mission_info['external_subsystems']: - # Get all the subsystem builders for this phase. - subsystem_premission = external_subsystem.build_pre_mission( - self.aviary_inputs) + sub = self.model.add_subsystem(name, AviaryGroup()) + sub.meta_data = self.meta_data + sub.load_inputs( + aircraft_data=aircraft, + phase_info=mission, + engine_builders=engine_builders, + problem_configurator=problem_configurator, + verbosity=verbosity, + ) - if subsystem_premission is not None: - self.pre_mission.add_subsystem(external_subsystem.name, - subsystem_premission) + sub.check_and_preprocess_inputs() - mass_names.extend(external_subsystem.get_mass_names()) + self.aviary_groups_dict[name] = sub - if mass_names: - formatted_names = [] - for name in mass_names: - formatted_name = name.replace(':', '_') - formatted_names.append(formatted_name) + if self.verbosity is None: + # If problem-level verbosity was not defined, use the verbosity specified in the first + # added AviaryGroup + self.verbosity = sub.verbosity - # Define the expression for computing the sum of masses - expr = 'subsystem_mass = ' + ' + '.join(formatted_names) + # TODO try and find a better solution than a new custom flag - the issue is multimission + # problems don't have a consistent variable path to check the inputs later on + if Settings.PAYLOAD_RANGE in sub.aviary_inputs: + self.generate_payload_range = sub.aviary_inputs.get_val(Settings.PAYLOAD_RANGE) - promotes_inputs_list = [ - (formatted_name, original_name) for formatted_name, - original_name in zip(formatted_names, mass_names)] + self._update_metadata_from_subsystems(sub) # update meta data with new entries - # Create the ExecComp - self.pre_mission.add_subsystem( - 'external_comp_sum', om.ExecComp(expr, units='kg'), - promotes_inputs=promotes_inputs_list, - promotes_outputs=[('subsystem_mass', Aircraft.Design. - EXTERNAL_SUBSYSTEMS_MASS)]) + return sub - def _add_groundroll_eq_constraint(self): + def add_pre_mission_systems(self, verbosity=None): """ - Add an equality constraint to the problem to ensure that the TAS at the end of the - groundroll phase is equal to the rotation velocity at the start of the rotation phase. + Add pre-mission systems to the Aviary problem. These systems are executed before + the mission. + + Depending on the mission model specified (`FLOPS` or `GASP`), this method adds + various subsystems to the aircraft model. For the `FLOPS` mission model, a + takeoff phase is added using the Takeoff class with the number of engines and + airport altitude specified. For the `GASP` mission model, three subsystems are + added: a TaxiSegment subsystem, an ExecComp to calculate the time to initiate + gear and flaps, and an ExecComp to calculate the speed at which to initiate + rotation. All subsystems are promoted with aircraft and mission inputs and + outputs as appropriate. """ - self.model.add_subsystem( - "groundroll_boundary", - om.EQConstraintComp( - "velocity", - eq_units="ft/s", - normalize=True, - add_constraint=True, - ), - ) - self.model.connect(Mission.Takeoff.ROTATION_VELOCITY, - "groundroll_boundary.rhs:velocity") - self.model.connect( - "traj.groundroll.states:velocity", - "groundroll_boundary.lhs:velocity", - src_indices=[-1], - flat_src_indices=True, - ) - - def _get_phase(self, phase_name, phase_idx): - base_phase_options = self.phase_info[phase_name] - - # We need to exclude some things from the phase_options that we pass down - # to the phases. Intead of "popping" keys, we just create new outer dictionaries. - - phase_options = {} - for key, val in base_phase_options.items(): - phase_options[key] = val - - phase_options['user_options'] = {} - for key, val in base_phase_options['user_options'].items(): - phase_options['user_options'][key] = val - - # TODO optionally accept which subsystems to load from phase_info - subsystems = self.core_subsystems - default_mission_subsystems = [ - subsystems['aerodynamics'], subsystems['propulsion']] - - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - if 'groundroll' in phase_name: - phase_builder = GroundrollPhase - elif 'rotation' in phase_name: - phase_builder = RotationPhase - elif 'accel' in phase_name: - phase_builder = AccelPhase - elif 'ascent' in phase_name: - phase_builder = AscentPhase - elif 'climb' in phase_name: - phase_builder = ClimbPhase - elif 'cruise' in phase_name: - phase_builder = CruisePhase - elif 'desc' in phase_name: - phase_builder = DescentPhase - else: - raise ValueError( - f'{phase_name} does not have an associated phase_builder \n phase_name must ' - 'include one of: groundroll, rotation, accel, ascent, climb, cruise, or desc') - - if self.mission_method is HEIGHT_ENERGY: - if 'phase_builder' in phase_options: - phase_builder = phase_options['phase_builder'] - if not issubclass(phase_builder, PhaseBuilderBase): - raise TypeError( - f"phase_builder for the phase called {phase_name} must be a PhaseBuilderBase object.") - else: - phase_builder = EnergyPhase - - if self.mission_method is SOLVED_2DOF: - if phase_options['user_options']['ground_roll'] and phase_options['user_options']['fix_initial']: - phase_builder = GroundrollPhaseVelocityIntegrated - else: - phase_builder = TwoDOFPhase - - phase_object = phase_builder.from_phase_info( - phase_name, phase_options, default_mission_subsystems, - meta_data=self.meta_data) - - phase = phase_object.build_phase(aviary_options=self.aviary_inputs) - - self.phase_objects.append(phase_object) - - # TODO: add logic to filter which phases get which controls. - # right now all phases get all controls added from every subsystem. - # for example, we might only want ELECTRIC_SHAFT_POWER applied during the climb phase. - all_subsystems = self._get_all_subsystems( - phase_options['external_subsystems']) - - # loop through all_subsystems and call `get_controls` on each subsystem - for subsystem in all_subsystems: - # add the controls from the subsystems to each phase - arg_spec = inspect.getfullargspec(subsystem.get_controls) - if 'phase_name' in arg_spec.args: - control_dicts = subsystem.get_controls( - phase_name=phase_name) - else: - control_dicts = subsystem.get_controls( - phase_name=phase_name) - for control_name, control_dict in control_dicts.items(): - phase.add_control(control_name, **control_dict) - - user_options = AviaryValues(phase_options.get('user_options', ())) - - try: - fix_initial = user_options.get_val('fix_initial') - except KeyError: - fix_initial = False - - try: - fix_duration = user_options.get_val('fix_duration') - except KeyError: - fix_duration = False - - if 'ascent' in phase_name and self.mission_method is TWO_DEGREES_OF_FREEDOM: - phase.set_time_options( - units="s", - targets="t_curr", - input_initial=True, - input_duration=True, - ) - elif 'cruise' in phase_name and self.mission_method is TWO_DEGREES_OF_FREEDOM: - # Time here is really the independent variable through which we are integrating. - # In the case of the Breguet Range ODE, it's mass. - # We rely on mass being monotonically non-increasing across the phase. - phase.set_time_options( - name='mass', - fix_initial=False, - fix_duration=False, - units="lbm", - targets="mass", - initial_bounds=(0., 1.e7), - initial_ref=100.e3, - duration_bounds=(-1.e7, -1), - duration_ref=50000, - ) - elif 'descent' in phase_name and self.mission_method is TWO_DEGREES_OF_FREEDOM: - duration_ref = user_options.get_val("duration_ref", 's') - phase.set_time_options( - duration_bounds=duration_bounds, - fix_initial=fix_initial, - input_initial=input_initial, - units="s", - duration_ref=duration_ref, - ) + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) else: - # The rest of the phases includes all Height Energy method phases - # and any 2DOF phases that don't fall into the naming patterns - # above. - input_initial = False - time_units = phase.time_options['units'] - - # Make a good guess for a reasonable intitial time scaler. - try: - initial_bounds = user_options.get_val('initial_bounds', units=time_units) - except KeyError: - initial_bounds = (None, None) + verbosity = self.verbosity # defaults to BRIEF - if initial_bounds[0] is not None and initial_bounds[1] != 0.0: - # Upper bound is good for a ref. - user_options.set_val('initial_ref', initial_bounds[1], - units=time_units) - else: - user_options.set_val('initial_ref', 600., time_units) - - duration_bounds = user_options.get_val("duration_bounds", time_units) - user_options.set_val( - 'duration_ref', (duration_bounds[0] + duration_bounds[1]) / 2., - time_units - ) - if phase_idx > 0: - input_initial = True - - if fix_initial or input_initial: - - if self.comm.size > 1: - # Phases are disconnected to run in parallel, so initial ref is valid. - initial_ref = user_options.get_val("initial_ref", time_units) - else: - # Redundant on a fixed input; raises a warning if specified. - initial_ref = None - - phase.set_time_options( - fix_initial=fix_initial, fix_duration=fix_duration, units=time_units, - duration_bounds=user_options.get_val("duration_bounds", time_units), - duration_ref=user_options.get_val("duration_ref", time_units), - initial_ref=initial_ref, - ) - elif phase_name == 'descent' and self.mission_method is HEIGHT_ENERGY: # TODO: generalize this logic for all phases - phase.set_time_options( - fix_initial=False, fix_duration=False, units=time_units, - duration_bounds=user_options.get_val("duration_bounds", time_units), - duration_ref=user_options.get_val("duration_ref", time_units), - initial_bounds=initial_bounds, - initial_ref=user_options.get_val("initial_ref", time_units), - ) - else: # TODO: figure out how to handle this now that fix_initial is dict - phase.set_time_options( - fix_initial=fix_initial, fix_duration=fix_duration, units=time_units, - duration_bounds=user_options.get_val("duration_bounds", time_units), - duration_ref=user_options.get_val("duration_ref", time_units), - initial_bounds=initial_bounds, - initial_ref=user_options.get_val("initial_ref", time_units), - ) - - if 'cruise' not in phase_name and self.mission_method is TWO_DEGREES_OF_FREEDOM: - phase.add_control( - Dynamic.Mission.THROTTLE, targets=Dynamic.Mission.THROTTLE, - units='unitless', opt=False,) - - return phase - - def add_phases(self, phase_info_parameterization=None): + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + group.add_pre_mission_systems(verbosity=verbosity) + else: + self.model.add_pre_mission_systems(verbosity=verbosity) + + def add_phases( + self, + phase_info_parameterization=None, + parallel_phases=True, + verbosity=None, + ): """ Add the mission phases to the problem trajectory based on the user-specified phase_info dictionary. Parameters ---------- - phase_info_parameterization (function, optional): A function that takes in the phase_info dictionary - and aviary_inputs and returns modified phase_info. Defaults to None. + phase_info_parameterization (function, optional): A function that takes in the + phase_info dictionary and aviary_inputs and returns modified phase_info. + Defaults to None. + + parallel_phases (bool, optional): If True, the top-level container of all phases + will be a ParallelGroup, otherwise it will be a standard OpenMDAO Group. + Defaults to True. Returns ------- - traj: The Dymos Trajectory object containing the added mission phases. + + The Dymos Trajectory object containing the added mission phases. """ - if phase_info_parameterization is not None: - self.phase_info, self.post_mission_info = phase_info_parameterization( - self.phase_info, self.post_mission_info, self.aviary_inputs) - - phase_info = self.phase_info - - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - phases = list(phase_info.keys()) - traj = self.model.add_subsystem('traj', dm.Trajectory()) - - elif self.analysis_scheme is AnalysisScheme.SHOOTING: - vb = self.aviary_inputs.get_val(Settings.VERBOSITY) - add_default_sgm_args(self.phase_info, self.ode_args, vb) - - full_traj = FlexibleTraj( - Phases=self.phase_info, - traj_final_state_output=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - ], - traj_initial_state_input=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - traj_event_trigger_input=[ - # specify ODE, output_name, with units that SimuPyProblem expects - # assume event function is of form ODE.output_name - value - # third key is event_idx associated with input - ('groundroll', Dynamic.Mission.VELOCITY, 0,), - ('climb3', Dynamic.Mission.ALTITUDE, 0,), - ('cruise', Dynamic.Mission.MASS, 0,), - ], - traj_intermediate_state_output=[ - ('cruise', Dynamic.Mission.DISTANCE), - ('cruise', Dynamic.Mission.MASS), - ] - ) - traj = self.model.add_subsystem('traj', full_traj, promotes_inputs=[ - ('altitude_initial', Mission.Design.CRUISE_ALTITUDE)]) - - self.model.add_subsystem( - 'actual_descent_fuel', om.ExecComp( - 'actual_descent_fuel = traj_cruise_mass_final - traj_mass_final', - actual_descent_fuel={'units': 'lbm'}, - traj_cruise_mass_final={'units': 'lbm'}, - traj_mass_final={'units': 'lbm'},)) - - self.model.connect('start_of_descent_mass', 'traj.SGMCruise_mass_trigger') - self.model.connect( - 'traj.mass_final', - 'actual_descent_fuel.traj_mass_final', - src_indices=[-1], - flat_src_indices=True, - ) - self.model.connect( - 'traj.cruise_mass_final', - 'actual_descent_fuel.traj_cruise_mass_final', - src_indices=[-1], - flat_src_indices=True, + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + Traj = group.add_phases( + phase_info_parameterization=phase_info_parameterization, + parallel_phases=parallel_phases, + verbosity=verbosity, + comm=self.comm, + ) + else: + Traj = self.model.add_phases( + phase_info_parameterization=phase_info_parameterization, + parallel_phases=parallel_phases, + verbosity=verbosity, + comm=self.comm, ) - self.traj = full_traj - return traj - - def add_subsystem_timeseries_outputs(phase, phase_name): - phase_options = self.phase_info[phase_name] - all_subsystems = self._get_all_subsystems( - phase_options['external_subsystems']) - for subsystem in all_subsystems: - timeseries_to_add = subsystem.get_outputs() - for timeseries in timeseries_to_add: - phase.add_timeseries_output(timeseries) - - if self.mission_method in (TWO_DEGREES_OF_FREEDOM, HEIGHT_ENERGY, SOLVED_2DOF): - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - self.phase_objects = [] - for phase_idx, phase_name in enumerate(phases): - phase = traj.add_phase( - phase_name, self._get_phase(phase_name, phase_idx)) - add_subsystem_timeseries_outputs(phase, phase_name) - - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - - # In GASP, we still use the phase name to infer the phase type. - # We need this information to be available in the builders. - # TODO - Ultimately we should overhaul all of this. - self.phase_info[phase_name]['phase_type'] = phase_name - - if phase_name == 'ascent': - self._add_groundroll_eq_constraint() - - # loop through phase_info and external subsystems - external_parameters = {} - for phase_name in self.phase_info: - external_parameters[phase_name] = {} - all_subsystems = self._get_all_subsystems( - self.phase_info[phase_name]['external_subsystems']) - for subsystem in all_subsystems: - parameter_dict = subsystem.get_parameters( - phase_info=self.phase_info[phase_name], - aviary_inputs=self.aviary_inputs - ) - for parameter in parameter_dict: - external_parameters[phase_name][parameter] = parameter_dict[parameter] - - traj = setup_trajectory_params( - self.model, traj, self.aviary_inputs, phases, meta_data=self.meta_data, - external_parameters=external_parameters) - if self.mission_method is HEIGHT_ENERGY: - if not self.pre_mission_info['include_takeoff']: - first_flight_phase_name = list(phase_info.keys())[0] - first_flight_phase = traj._phases[first_flight_phase_name] - first_flight_phase.set_state_options(Dynamic.Mission.MASS, - fix_initial=False) + return Traj - self.traj = traj - - return traj - - def add_post_mission_systems(self, include_landing=True): + def add_post_mission_systems(self, verbosity=None): """ - Add post-mission systems to the aircraft model. This is akin to the pre-mission group - or the "premission_systems", but occurs after the mission in the execution order. - - Depending on the mission model specified (`FLOPS` or `GASP`), this method adds various subsystems - to the aircraft model. For the `FLOPS` mission model, a landing phase is added using the Landing class - with the wing area and lift coefficient specified, and a takeoff constraints ExecComp is added to enforce - mass, range, velocity, and altitude continuity between the takeoff and climb phases. The landing subsystem - is promoted with aircraft and mission inputs and outputs as appropriate, while the takeoff constraints ExecComp - is only promoted with mission inputs and outputs. - - For the `GASP` mission model, four subsystems are added: a LandingSegment subsystem, an ExecComp to calculate - the reserve fuel required, an ExecComp to calculate the overall fuel burn, and three ExecComps to calculate - various mission objectives and constraints. All subsystems are promoted with aircraft and mission inputs and - outputs as appropriate. - - A user can override this with their own postmission systems. + Add post-mission systems to the aircraft model. This is akin to the pre-mission + group or the "premission_systems", but occurs after the mission in the execution + order. + + Depending on the mission model specified (`FLOPS` or `GASP`), this method adds + various subsystems to the aircraft model. For the `FLOPS` mission model, a + landing phase is added using the Landing class with the wing area and lift + coefficient specified, and a takeoff constraints ExecComp is added to enforce + mass, range, velocity, and altitude continuity between the takeoff and climb + phases. The landing subsystem is promoted with aircraft and mission inputs and + outputs as appropriate, while the takeoff constraints ExecComp is only promoted + with mission inputs and outputs. + + For the `GASP` mission model, four subsystems are added: a LandingSegment + subsystem, an ExecComp to calculate the reserve fuel required, an ExecComp to + calculate the overall fuel burn, and three ExecComps to calculate various + mission objectives and constraints. All subsystems are promoted with aircraft + and mission inputs and outputs as appropriate. """ - - if self.pre_mission_info['include_takeoff'] and self.mission_method is HEIGHT_ENERGY: - self._add_post_mission_takeoff_systems() - - if include_landing and self.post_mission_info['include_landing']: - if self.mission_method is HEIGHT_ENERGY: - self._add_height_energy_landing_systems() - elif self.mission_method is TWO_DEGREES_OF_FREEDOM: - self._add_two_dof_landing_systems() - - self.model.add_subsystem('post_mission', self.post_mission, - promotes_inputs=['*'], - promotes_outputs=['*']) - - # Loop through all the phases in this subsystem. - for external_subsystem in self.post_mission_info['external_subsystems']: - # Get all the subsystem builders for this phase. - subsystem_postmission = external_subsystem.build_post_mission( - self.aviary_inputs) - - if subsystem_postmission is not None: - self.post_mission.add_subsystem(external_subsystem.name, - subsystem_postmission) - - if self.mission_method in (HEIGHT_ENERGY, SOLVED_2DOF, TWO_DEGREES_OF_FREEDOM): - # Check if regular_phases[] is accessible - try: - self.regular_phases[0] - except: - raise ValueError( - f"regular_phases[] dictionary is not accessible." - f" For HEIGHT_ENERGY and SOLVED_2DOF missions, check_and_preprocess_inputs()" - f" must be called before add_post_mission_systems().") - - # Fuel burn in regular phases - ecomp = om.ExecComp('fuel_burned = initial_mass - mass_final', - initial_mass={'units': 'lbm'}, - mass_final={'units': 'lbm'}, - fuel_burned={'units': 'lbm'}) - - self.post_mission.add_subsystem( - 'fuel_burned', ecomp, - promotes=[('fuel_burned', Mission.Summary.FUEL_BURNED)]) - - if self.analysis_scheme is AnalysisScheme.SHOOTING: - # shooting method currently doesn't have timeseries - self.post_mission.promotes('fuel_burned', [ - ('initial_mass', Mission.Summary.GROSS_MASS), - ('mass_final', Mission.Landing.TOUCHDOWN_MASS), - ]) - else: - if self.pre_mission_info['include_takeoff']: - self.post_mission.promotes('fuel_burned', [ - ('initial_mass', Mission.Summary.GROSS_MASS), - ]) - else: - # timeseries has to be used because Breguet cruise phases don't have states - self.model.connect(f"traj.{self.regular_phases[0]}.timeseries.mass", - "fuel_burned.initial_mass", src_indices=[0]) - - self.model.connect(f"traj.{self.regular_phases[-1]}.timeseries.mass", - "fuel_burned.mass_final", src_indices=[-1]) - - # Fuel burn in reserve phases - if self.reserve_phases: - ecomp = om.ExecComp('reserve_fuel_burned = initial_mass - mass_final', - initial_mass={'units': 'lbm'}, - mass_final={'units': 'lbm'}, - reserve_fuel_burned={'units': 'lbm'}) - - self.post_mission.add_subsystem('reserve_fuel_burned', ecomp, promotes=[ - ('reserve_fuel_burned', Mission.Summary.RESERVE_FUEL_BURNED)]) - - if self.analysis_scheme is AnalysisScheme.SHOOTING: - # shooting method currently doesn't have timeseries - self.post_mission.promotes('reserve_fuel_burned', [ - ('initial_mass', Mission.Landing.TOUCHDOWN_MASS), - ]) - self.model.connect( - f"traj.{self.reserve_phases[-1]}.states:mass", - "reserve_fuel_burned.mass_final", src_indices=[-1]) - else: - # timeseries has to be used because Breguet cruise phases don't have states - self.model.connect( - f"traj.{self.reserve_phases[0]}.timeseries.mass", - "reserve_fuel_burned.initial_mass", src_indices=[0]) - self.model.connect( - f"traj.{self.reserve_phases[-1]}.timeseries.mass", - "reserve_fuel_burned.mass_final", src_indices=[-1]) - - self._add_fuel_reserve_component() - - # TODO: need to add some sort of check that this value is less than the fuel capacity - # TODO: the overall_fuel variable is the burned fuel plus the reserve, but should - # also include the unused fuel, and the hierarchy variable name should be more clear - ecomp = om.ExecComp('overall_fuel = (1 + fuel_margin/100)*fuel_burned + reserve_fuel', - overall_fuel={'units': 'lbm', 'shape': 1}, - fuel_margin={"units": "unitless", 'val': 0}, - fuel_burned={'units': 'lbm'}, # from regular_phases only - reserve_fuel={'units': 'lbm', 'shape': 1}, - ) - self.post_mission.add_subsystem( - 'fuel_calc', ecomp, - promotes_inputs=[ - ("fuel_margin", Aircraft.Fuel.FUEL_MARGIN), - ('fuel_burned', Mission.Summary.FUEL_BURNED), - ("reserve_fuel", Mission.Design.RESERVE_FUEL), - ], - promotes_outputs=[('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS)]) - - # If a target distance (or time) has been specified for this phase - # distance (or time) is measured from the start of this phase to the end of this phase - for phase_name in self.phase_info: - if 'target_distance' in self.phase_info[phase_name]["user_options"]: - target_distance = wrapped_convert_units( - self.phase_info[phase_name]["user_options"] - ["target_distance"], - 'nmi') - self.post_mission.add_subsystem( - f"{phase_name}_distance_constraint", om.ExecComp( - "distance_resid = target_distance - (final_distance - initial_distance)", - distance_resid={'units': 'nmi'}, - target_distance={'val': target_distance, 'units': 'nmi'}, - final_distance={'units': 'nmi'}, - initial_distance={'units': 'nmi'},)) - self.model.connect( - f"traj.{phase_name}.timeseries.distance", - f"{phase_name}_distance_constraint.final_distance", - src_indices=[-1]) - self.model.connect( - f"traj.{phase_name}.timeseries.distance", - f"{phase_name}_distance_constraint.initial_distance", - src_indices=[0]) - self.model.add_constraint( - f"{phase_name}_distance_constraint.distance_resid", equals=0.0, ref=1e2) - - # this is only used for analytic phases with a target duration - if 'target_duration' in self.phase_info[phase_name]["user_options"] and \ - self.phase_info[phase_name]["user_options"].get("analytic", False): - target_duration = wrapped_convert_units( - self.phase_info[phase_name]["user_options"] - ["target_duration"], - 'min') - self.post_mission.add_subsystem( - f"{phase_name}_duration_constraint", om.ExecComp( - "duration_resid = target_duration - (final_time - initial_time)", - duration_resid={'units': 'min'}, - target_duration={'val': target_duration, 'units': 'min'}, - final_time={'units': 'min'}, - initial_time={'units': 'min'},)) - self.model.connect( - f"traj.{phase_name}.timeseries.time", - f"{phase_name}_duration_constraint.final_time", src_indices=[-1]) - self.model.connect( - f"traj.{phase_name}.timeseries.time", - f"{phase_name}_duration_constraint.initial_time", - src_indices=[0]) - self.model.add_constraint( - f"{phase_name}_duration_constraint.duration_resid", equals=0.0, ref=1e2) - - if self.mission_method in (TWO_DEGREES_OF_FREEDOM, HEIGHT_ENERGY): - self._add_objectives() - - ecomp = om.ExecComp( - 'mass_resid = operating_empty_mass + overall_fuel + payload_mass -' - ' initial_mass', - operating_empty_mass={'units': 'lbm'}, - overall_fuel={'units': 'lbm'}, - payload_mass={'units': 'lbm'}, - initial_mass={'units': 'lbm'}, - mass_resid={'units': 'lbm'}) - - if self.mass_method is GASP: - payload_mass_src = Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) else: - payload_mass_src = Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS - - self.post_mission.add_subsystem( - 'mass_constraint', ecomp, - promotes_inputs=[ - ('operating_empty_mass', Aircraft.Design.OPERATING_MASS), - ('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS), - ('payload_mass', payload_mass_src), - ('initial_mass', Mission.Summary.GROSS_MASS)], - promotes_outputs=[("mass_resid", Mission.Constraints.MASS_RESIDUAL)]) - - if self.mission_method in (HEIGHT_ENERGY, TWO_DEGREES_OF_FREEDOM): - self.post_mission.add_constraint( - Mission.Constraints.MASS_RESIDUAL, equals=0.0, ref=1.e5) - - if self.mission_method is HEIGHT_ENERGY: - # connect summary mass to the initial guess of mass in the first phase - if not self.pre_mission_info['include_takeoff']: - first_flight_phase_name = list(self.phase_info.keys())[0] - eq = self.model.add_subsystem(f'link_{first_flight_phase_name}_mass', - om.EQConstraintComp(), - promotes_inputs=[('rhs:mass', - Mission.Summary.GROSS_MASS)]) - eq.add_eq_output('mass', eq_units='lbm', normalize=False, - ref=100000., add_constraint=True) - self.model.connect( - f'traj.{first_flight_phase_name}.states:mass', - f'link_{first_flight_phase_name}_mass.lhs:mass', - src_indices=[0], - flat_src_indices=True, - ) - - def _link_phases_helper_with_options(self, phases, option_name, var, **kwargs): - # Initialize a list to keep track of indices where option_name is True - true_option_indices = [] + verbosity = self.verbosity # defaults to BRIEF - # Loop through phases to find where option_name is True - for idx, phase_name in enumerate(phases): - if self.phase_info[phase_name]['user_options'].get(option_name, False): - true_option_indices.append(idx) - - # Determine the groups of phases to link based on consecutive indices - groups_to_link = [] - current_group = [] + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + group.add_post_mission_systems(verbosity=verbosity) + else: + self.model.add_post_mission_systems(verbosity=verbosity) - for idx in true_option_indices: - if not current_group or idx == current_group[-1] + 1: - # If the current index is consecutive, add it to the current group - current_group.append(idx) - else: - # Otherwise, start a new group and save the previous one - groups_to_link.append(current_group) - current_group = [idx] - - # Add the last group if it exists - if current_group: - groups_to_link.append(current_group) - - # Loop through each group and determine the phases to link - for group in groups_to_link: - # Extend the group to include the phase before the first True option and after the last True option, if applicable - if group[0] > 0: - group.insert(0, group[0] - 1) - if group[-1] < len(phases) - 1: - group.append(group[-1] + 1) - - # Extract the phase names for the current group - phases_to_link = [phases[idx] for idx in group] - - # Link the phases for the current group - if len(phases_to_link) > 1: - self.traj.link_phases(phases=phases_to_link, vars=[var], **kwargs) - - def link_phases(self): + def link_phases(self, verbosity=None): """ Link phases together after they've been added. @@ -1430,484 +374,198 @@ def link_phases(self): special logic to do the Dymos linkages correctly. Some of those connections for the simple GASP and FLOPS mission are shown here. """ - self._add_bus_variables_and_connect() - - phases = list(self.phase_info.keys()) - - if len(phases) <= 1: - return - - # In summary, the following code loops over all phases in self.phase_info, gets - # the linked variables from each external subsystem in each phase, and stores - # the lists of linked variables in lists_to_link. It then gets a list of - # unique variable names from lists_to_link and loops over them, creating - # a list of phase names for each variable and linking the phases - # using self.traj.link_phases(). - - lists_to_link = [] - for idx, phase_name in enumerate(self.phase_info): - lists_to_link.append([]) - for external_subsystem in self.phase_info[phase_name]['external_subsystems']: - lists_to_link[idx].extend(external_subsystem.get_linked_variables()) - - # get unique variable names from lists_to_link - unique_vars = list(set([var for sublist in lists_to_link for var in sublist])) - - # Phase linking. - # If we are under mpi, and traj.phases is running in parallel, then let the - # optimizer handle the linkage constraints. Note that we can technically - # paralellize connected phases, but it requires a solver that we would like - # to avoid. - true_unless_mpi = True - if self.comm.size > 1 and self.traj.options['parallel_phases']: - true_unless_mpi = False - - # loop over unique variable names - for var in unique_vars: - phases_to_link = [] - for idx, phase_name in enumerate(self.phase_info): - if var in lists_to_link[idx]: - phases_to_link.append(phase_name) - - if len(phases_to_link) > 1: # TODO: hack - self.traj.link_phases(phases=phases_to_link, vars=[var], connected=True) - - if self.mission_method in (HEIGHT_ENERGY, SOLVED_2DOF): - # connect regular_phases with each other if you are optimizing alt or mach - self._link_phases_helper_with_options( - self.regular_phases, 'optimize_altitude', Dynamic.Mission.ALTITUDE, ref=1.e4) - self._link_phases_helper_with_options( - self.regular_phases, 'optimize_mach', Dynamic.Mission.MACH) - - # connect reserve phases with each other if you are optimizing alt or mach - self._link_phases_helper_with_options( - self.reserve_phases, 'optimize_altitude', Dynamic.Mission.ALTITUDE, ref=1.e4) - self._link_phases_helper_with_options( - self.reserve_phases, 'optimize_mach', Dynamic.Mission.MACH) - - if self.mission_method is HEIGHT_ENERGY: - # connect mass and distance between all phases regardless of reserve / non-reserve status - self.traj.link_phases(phases, ["time"], - ref=None if true_unless_mpi else 1e3, - connected=true_unless_mpi) - self.traj.link_phases(phases, [Dynamic.Mission.MASS], - ref=None if true_unless_mpi else 1e6, - connected=true_unless_mpi) - self.traj.link_phases(phases, [Dynamic.Mission.DISTANCE], - ref=None if true_unless_mpi else 1e3, - connected=true_unless_mpi) - - self.model.connect(f'traj.{self.regular_phases[-1]}.timeseries.distance', - 'actual_range', - src_indices=[-1], flat_src_indices=True) - - elif self.mission_method is SOLVED_2DOF: - self.traj.link_phases(phases, [Dynamic.Mission.MASS], connected=True) - self.traj.link_phases( - phases, [Dynamic.Mission.DISTANCE], - units='ft', ref=1.e3, connected=False) - self.traj.link_phases(phases, ["time"], connected=False) - - if len(phases) > 2: - self.traj.link_phases( - phases[1:], ["alpha"], units='rad', connected=False) - - elif self.mission_method is TWO_DEGREES_OF_FREEDOM: - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - for ii in range(len(phases)-1): - phase1, phase2 = phases[ii:ii+2] - analytic1 = self.phase_info[phase1]['user_options']['analytic'] - analytic2 = self.phase_info[phase2]['user_options']['analytic'] - - if not (analytic1 or analytic2): - # we always want time, distance, and mass to be continuous - states_to_link = { - 'time': true_unless_mpi, - Dynamic.Mission.DISTANCE: true_unless_mpi, - Dynamic.Mission.MASS: False, - } - - # if both phases are reserve phases or neither is a reserve phase - # (we are not on the boundary between the regular and reserve missions) - # and neither phase is ground roll or rotation (altitude isn't a state): - # we want altitude to be continous as well - if ((phase1 in self.reserve_phases) == (phase2 in self.reserve_phases)) and \ - not ({"groundroll", "rotation"} & {phase1, phase2}) and \ - not ('accel', 'climb1') == (phase1, phase2): # required for convergence of FwGm - states_to_link[Dynamic.Mission.ALTITUDE] = true_unless_mpi - - # if either phase is rotation, we need to connect velocity - # ascent to accel also requires velocity - if 'rotation' in ( - phase1, phase2) or ( - 'ascent', 'accel') == ( - phase1, phase2): - states_to_link[Dynamic.Mission.VELOCITY] = true_unless_mpi - # if the first phase is rotation, we also need alpha - if phase1 == 'rotation': - states_to_link['alpha'] = False - - for state, connected in states_to_link.items(): - # in initial guesses, all of the states, other than time use the same name - initial_guesses1 = self.phase_info[phase1]['initial_guesses'] - initial_guesses2 = self.phase_info[phase2]['initial_guesses'] - - # if a state is in the initial guesses, get the units of the initial guess - kwargs = {} - if not connected: - if state in initial_guesses1: - kwargs = {'units': initial_guesses1[state][-1]} - elif state in initial_guesses2: - kwargs = {'units': initial_guesses2[state][-1]} - - self.traj.link_phases( - [phase1, phase2], [state], connected=connected, **kwargs) - - # if either phase is analytic we have to use a linkage_constraint - else: - # analytic phases use the prefix "initial" for time and distance, but not mass - if analytic2: - prefix = 'initial_' - else: - prefix = '' - - self.traj.add_linkage_constraint( - phase1, phase2, 'time', prefix+'time', connected=True) - self.traj.add_linkage_constraint( - phase1, phase2, 'distance', prefix + 'distance', - connected=True) - self.traj.add_linkage_constraint( - phase1, phase2, 'mass', 'mass', connected=False, ref=1.0e5) - - # add all params and promote them to self.model level - ParamPort.promote_params( - self.model, - trajs=["traj"], - phases=[ - [*self.regular_phases, - *self.reserve_phases] - ], - ) - - self.model.promotes( - "traj", - inputs=[ - ("ascent.parameters:t_init_gear", "t_init_gear"), - ("ascent.parameters:t_init_flaps", "t_init_flaps"), - ("ascent.t_initial", Mission.Takeoff.ASCENT_T_INTIIAL), - ("ascent.t_duration", Mission.Takeoff.ASCENT_DURATION), - ], - ) - - # imitate input_initial for taxi -> groundroll - eq = self.model.add_subsystem( - "taxi_groundroll_mass_constraint", om.EQConstraintComp()) - eq.add_eq_output("mass", eq_units="lbm", normalize=False, - ref=10000., add_constraint=True) - self.model.connect( - "taxi.mass", "taxi_groundroll_mass_constraint.rhs:mass") - self.model.connect( - "traj.groundroll.states:mass", - "taxi_groundroll_mass_constraint.lhs:mass", - src_indices=[0], - flat_src_indices=True, - ) - - self.model.connect("traj.ascent.timeseries.time", "h_fit.time_cp") - self.model.connect( - "traj.ascent.timeseries.altitude", "h_fit.h_cp") - - self.model.connect(f'traj.{self.regular_phases[-1]}.states:mass', - Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) - - connect_map = { - f"traj.{self.regular_phases[-1]}.timeseries.distance": 'actual_range', - } - - else: - connect_map = { - "taxi.mass": "traj.mass_initial", - Mission.Takeoff.ROTATION_VELOCITY: "traj.SGMGroundroll_velocity_trigger", - "traj.distance_final": 'actual_range', - "traj.mass_final": Mission.Landing.TOUCHDOWN_MASS, - } - - # promote all ParamPort inputs for analytic segments as well - param_list = list(ParamPort.param_data) - self.model.promotes("taxi", inputs=param_list) - self.model.promotes("landing", inputs=param_list) - if self.analysis_scheme is AnalysisScheme.SHOOTING: - param_list.append(Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE) - self.model.promotes("traj", inputs=param_list) - # self.model.list_inputs() - # self.model.promotes("traj", inputs=['ascent.ODE_group.eoms.'+Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE]) - - self.model.connect("taxi.mass", "vrot.mass") - - def connect_with_common_params(self, source, target): - self.model.connect( - source, - target, - src_indices=[-1], - flat_src_indices=True, - ) + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF - for source, target in connect_map.items(): - connect_with_common_params(self, source, target) + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + group.link_phases(verbosity=verbosity, comm=self.comm) + else: + self.model.link_phases(verbosity=verbosity, comm=self.comm) - def add_driver( - self, optimizer=None, use_coloring=None, max_iter=50, - verbosity=Verbosity.BRIEF): + def add_driver(self, optimizer=None, use_coloring=None, max_iter=50, verbosity=None): """ Add an optimization driver to the Aviary problem. - Depending on the provided optimizer, the method instantiates the relevant driver (ScipyOptimizeDriver or - pyOptSparseDriver) and sets the optimizer options. Options for 'SNOPT', 'IPOPT', and 'SLSQP' are - specified. The method also allows for the declaration of coloring and setting debug print options. + Depending on the provided optimizer, the method instantiates the relevant + driver (ScipyOptimizeDriver or pyOptSparseDriver) and sets the optimizer + options. Options for 'SNOPT', 'IPOPT', and 'SLSQP' are specified. The method + also allows for the declaration of coloring and setting debug print options. Parameters ---------- optimizer : str - The name of the optimizer to use. It can be "SLSQP", "SNOPT", "IPOPT" or others supported by OpenMDAO. - If "SLSQP", it will instantiate a ScipyOptimizeDriver, else it will instantiate a pyOptSparseDriver. + The name of the optimizer to use. It can be "SLSQP", "SNOPT", "IPOPT" or + others supported by OpenMDAO. If "SLSQP", it will instantiate a + ScipyOptimizeDriver, else it will instantiate a pyOptSparseDriver. use_coloring : bool, optional - If True (default), the driver will declare coloring, which can speed up derivative computations. + If True (default), the driver will declare coloring, which can speed up + derivative computations. max_iter : int, optional - The maximum number of iterations allowed for the optimization process. Default is 50. This option is - applicable to "SNOPT", "IPOPT", and "SLSQP" optimizers. + The maximum number of iterations allowed for the optimization process. + Default is 50. This option is applicable to "SNOPT", "IPOPT", and "SLSQP" + optimizers. - verbosity : Verbosity, int or list, optional - If Verbosity.DEBUG, debug print options ['desvars','ln_cons','nl_cons','objs'] will be set. If a list is - provided, it will be used as the debug print options. + verbosity : Verbosity or int, optional + Controls the level of printouts for this method. If None, uses the value of + Settings.VERBOSITY in provided aircraft data. Returns ------- None """ - # compatibility with being passed int for verbosity - verbosity = Verbosity(verbosity) + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF - # Set defaults for optimizer and use_coloring based on analysis scheme + # Set defaults for optimizer and use_coloring if optimizer is None: - optimizer = 'IPOPT' if self.analysis_scheme is AnalysisScheme.SHOOTING else 'SNOPT' + optimizer = 'IPOPT' if use_coloring is None: - use_coloring = False if self.analysis_scheme is AnalysisScheme.SHOOTING else True + use_coloring = True # check if optimizer is SLSQP - if optimizer == "SLSQP": + if optimizer == 'SLSQP': driver = self.driver = om.ScipyOptimizeDriver() else: driver = self.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = optimizer + driver.options['optimizer'] = optimizer if use_coloring: - driver.declare_coloring() + # define coloring options by verbosity + if verbosity < Verbosity.VERBOSE: # QUIET, BRIEF + driver.declare_coloring(show_summary=False) + elif verbosity == Verbosity.VERBOSE: + driver.declare_coloring(show_summary=True) + else: # DEBUG + driver.declare_coloring(show_summary=True, show_sparsity=True) - if driver.options["optimizer"] == "SNOPT": + if driver.options['optimizer'] == 'SNOPT': + # Print Options # if verbosity == Verbosity.QUIET: isumm, iprint = 0, 0 elif verbosity == Verbosity.BRIEF: isumm, iprint = 6, 0 - elif verbosity > Verbosity.BRIEF: + elif verbosity > Verbosity.BRIEF: # VERBOSE, DEBUG isumm, iprint = 6, 9 - driver.opt_settings["Major iterations limit"] = max_iter - driver.opt_settings["Major optimality tolerance"] = 1e-4 - driver.opt_settings["Major feasibility tolerance"] = 1e-7 - driver.opt_settings["iSumm"] = isumm - driver.opt_settings["iPrint"] = iprint - elif driver.options["optimizer"] == "IPOPT": + driver.opt_settings['iSumm'] = isumm + driver.opt_settings['iPrint'] = iprint + # Optimizer Settings # + driver.opt_settings['Major iterations limit'] = max_iter + driver.opt_settings['Major optimality tolerance'] = 1e-4 + driver.opt_settings['Major feasibility tolerance'] = 1e-6 + + elif driver.options['optimizer'] == 'IPOPT': + # Print Options # if verbosity == Verbosity.QUIET: - print_level = 3 # minimum to get exit status + print_level = 0 driver.opt_settings['print_user_options'] = 'no' elif verbosity == Verbosity.BRIEF: - print_level = 5 + print_level = 3 # minimum to get exit status driver.opt_settings['print_user_options'] = 'no' driver.opt_settings['print_frequency_iter'] = 10 elif verbosity == Verbosity.VERBOSE: print_level = 5 else: # DEBUG print_level = 7 - driver.opt_settings['tol'] = 1.0E-6 + driver.opt_settings['print_level'] = print_level + # Optimizer Settings # + driver.opt_settings['tol'] = 1.0e-6 driver.opt_settings['mu_init'] = 1e-5 driver.opt_settings['max_iter'] = max_iter - driver.opt_settings['print_level'] = print_level # for faster convergence driver.opt_settings['nlp_scaling_method'] = 'gradient-based' driver.opt_settings['alpha_for_y'] = 'safer-min-dual-infeas' driver.opt_settings['mu_strategy'] = 'monotone' - elif driver.options["optimizer"] == "SLSQP": + + elif driver.options['optimizer'] == 'SLSQP': + # Print Options # if verbosity == Verbosity.QUIET: disp = False else: disp = True - driver.options["tol"] = 1e-9 - driver.options["maxiter"] = max_iter - driver.options["disp"] = disp - - if verbosity > Verbosity.QUIET: - if isinstance(verbosity, list): - driver.options['debug_print'] = verbosity - elif verbosity == Verbosity.DEBUG: - driver.options['debug_print'] = ['desvars', 'ln_cons', 'nl_cons', 'objs'] - if optimizer in ("SNOPT", "IPOPT"): + driver.options['disp'] = disp + # Optimizer Settings # + driver.options['tol'] = 1e-9 + driver.options['maxiter'] = max_iter + + # pyoptsparse print settings for both SNOPT, IPOPT + if optimizer in ('SNOPT', 'IPOPT'): if verbosity == Verbosity.QUIET: driver.options['print_results'] = False - elif verbosity < Verbosity.DEBUG: + elif verbosity < Verbosity.DEBUG: # QUIET, BRIEF, VERBOSE driver.options['print_results'] = 'minimal' - - def add_design_variables(self): + elif verbosity >= Verbosity.DEBUG: + driver.options['print_opt_prob'] = True + + # optimizer agnostic settings + if verbosity == Verbosity.DEBUG: + driver.options['debug_print'] = [ + 'desvars', + 'ln_cons', + 'nl_cons', + 'objs', + ] + + def add_design_variables(self, verbosity=None): """ Adds design variables to the Aviary problem. - Depending on the mission model and problem type, different design variables and constraints are added. + Depending on the mission model and problem type, different design variables and + constraints are added. - If using the FLOPS model, a design variable is added for the gross mass of the aircraft, with a lower bound of 10 lbm and an upper bound of 900,000 lbm. + If using the FLOPS model, a design variable is added for the gross mass of the + aircraft, with a lower bound of 10 lbm and an upper bound of 900,000 lbm. - If using the GASP model, the following design variables are added depending on the mission type: - - the initial thrust-to-weight ratio of the aircraft during ascent - - the duration of the ascent phase - - the time constant for the landing gear actuation - - the time constant for the flaps actuation + If using the GASP model, the following design variables are added depending on + the mission type: + - the initial thrust-to-weight ratio of the aircraft during ascent + - the duration of the ascent phase + - the time constant for the landing gear actuation + - the time constant for the flaps actuation In addition, two constraints are added for the GASP model: - - the initial altitude of the aircraft with gear extended is constrained to be 50 ft - - the initial altitude of the aircraft with flaps extended is constrained to be 400 ft - - If solving a sizing problem, a design variable is added for the gross mass of the aircraft, and another for the gross mass of the aircraft computed during the mission. A constraint is also added to ensure that the residual range is zero. + - the initial altitude of the aircraft with gear extended is constrained to be 50 ft + - the initial altitude of the aircraft with flaps extended is constrained to be 400 ft - If solving an alternate problem, only a design variable for the gross mass of the aircraft computed during the mission is added. A constraint is also added to ensure that the residual range is zero. + If solving a sizing problem, a design variable is added for the gross mass of + the aircraft, and another for the gross mass of the aircraft computed during the + mission. A constraint is also added to ensure that the residual range is zero. - In all cases, a design variable is added for the final cruise mass of the aircraft, with no upper bound, and a residual mass constraint is added to ensure that the mass balances. + If solving an alternate problem, only a design variable for the gross mass of + the aircraft computed during the mission is added. A constraint is also added to + ensure that the residual range is zero. + In all cases, a design variable is added for the final cruise mass of the + aircraft, with no upper bound, and a residual mass constraint is added to ensure + that the mass balances. """ - # add the engine builder `get_design_vars` dict to a collected dict from the external subsystems - - # TODO : maybe in the most general case we need to handle DVs in the mission and post-mission as well. - # for right now we just handle pre_mission - all_subsystems = self._get_all_subsystems() - - # loop through all_subsystems and call `get_design_vars` on each subsystem - for subsystem in all_subsystems: - dv_dict = subsystem.get_design_vars() - for dv_name, dv_dict in dv_dict.items(): - self.model.add_design_var(dv_name, **dv_dict) - - if self.mission_method is SOLVED_2DOF: - optimize_mass = self.pre_mission_info.get('optimize_mass') - if optimize_mass: - self.model.add_design_var(Mission.Design.GROSS_MASS, units='lbm', - lower=10, upper=900.e3, ref=175.e3) - - elif self.mission_method in (HEIGHT_ENERGY, TWO_DEGREES_OF_FREEDOM): - # vehicle sizing problem - # size the vehicle (via design GTOW) to meet a target range using all fuel capacity - if self.problem_type is ProblemType.SIZING: - self.model.add_design_var( - Mission.Design.GROSS_MASS, - lower=10.0, - upper=None, - units='lbm', - ref=175e3, - ) - self.model.add_design_var( - Mission.Summary.GROSS_MASS, - lower=10.0, - upper=None, - units='lbm', - ref=175e3, - ) - - self.model.add_subsystem( - 'gtow_constraint', - om.EQConstraintComp( - 'GTOW', - eq_units='lbm', - normalize=True, - add_constraint=True, - ), - promotes_inputs=[ - ('lhs:GTOW', Mission.Design.GROSS_MASS), - ('rhs:GTOW', Mission.Summary.GROSS_MASS), - ], - ) - - if self.require_range_residual: - self.model.add_constraint( - Mission.Constraints.RANGE_RESIDUAL, equals=0, ref=10 - ) - - # target range problem - # fixed vehicle (design GTOW) but variable actual GTOW for off-design mission range - elif self.problem_type is ProblemType.ALTERNATE: - self.model.add_design_var( - Mission.Summary.GROSS_MASS, - lower=10., - upper=900e3, - units='lbm', - ref=175e3, - ) - - self.model.add_constraint( - Mission.Constraints.RANGE_RESIDUAL, equals=0, ref=10 - ) - - elif self.problem_type is ProblemType.FALLOUT: - print('No design variables for Fallout missions') - - elif self.problem_type is ProblemType.MULTI_MISSION: - self.model.add_design_var( - Mission.Summary.GROSS_MASS, - lower=10., - upper=900e3, - units='lbm', - ref=175e3, - ) - - self.model.add_constraint( - Mission.Constraints.RANGE_RESIDUAL, equals=0, ref=10 - ) - - # We must ensure that design.gross_mass is greater than mission.summary.gross_mass - # and this must hold true for each of the different missions that is flown - # the result will be the design.gross_mass should be equal to the mission.summary.gross_mass - # of the heaviest mission - self.model.add_subsystem( - "GROSS_MASS_constraint", - om.ExecComp( - "gross_mass_resid = design_mass - actual_mass", - design_mass={"val": 1, "units": "kg"}, - actual_mass={"val": 0, "units": "kg"}, - gross_mass_resid={"val": 30, "units": "kg"}, - ), - promotes_inputs=[ - ("design_mass", Mission.Design.GROSS_MASS), - ("actual_mass", Mission.Summary.GROSS_MASS), - ], - promotes_outputs=["gross_mass_resid"], - ) + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF - self.model.add_constraint( - "gross_mass_resid", lower=0 - ) + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + group.add_design_variables(problem_type=self.problem_type, verbosity=verbosity) + else: + self.model.add_design_variables(problem_type=self.problem_type, verbosity=verbosity) - if self.mission_method is TWO_DEGREES_OF_FREEDOM and self.analysis_scheme is AnalysisScheme.COLLOCATION: - # problem formulation to make the trajectory work - self.model.add_design_var(Mission.Takeoff.ASCENT_T_INTIIAL, - lower=0, upper=100, ref=30.0) - self.model.add_design_var(Mission.Takeoff.ASCENT_DURATION, - lower=1, upper=1000, ref=10.) - self.model.add_design_var("tau_gear", lower=0.01, - upper=1.0, units="unitless", ref=1) - self.model.add_design_var("tau_flaps", lower=0.01, - upper=1.0, units="unitless", ref=1) - self.model.add_constraint( - "h_fit.h_init_gear", equals=50.0, units="ft", ref=50.0) - self.model.add_constraint("h_fit.h_init_flaps", - equals=400.0, units="ft", ref=400.0) - - def add_objective(self, objective_type=None, ref=None): + def add_objective(self, objective_type=None, ref=None, verbosity=None): """ Add the objective function based on the given objective_type and ref. @@ -1919,52 +577,101 @@ def add_objective(self, objective_type=None, ref=None): Parameters ---------- objective_type : str - The type of objective to add. Options are 'mass', 'hybrid_objective', 'fuel_burned', and 'fuel'. + The type of objective to add. Options are 'mass', 'hybrid_objective', + 'fuel_burned', and 'fuel'. ref : float - The reference value for the objective. If None, a default value will be used based on the objective type. Please see the - `default_ref_values` dict for these default values. + The reference value for the objective. If None, a default value will be used + based on the objective type. Please see the `default_ref_values` dict for + these default values. + verbosity : Verbosity or int, optional + Controls the level of printouts for this method. If None, uses the value of + Settings.VERBOSITY in provided aircraft data. Raises ------ ValueError: If an invalid problem type is provided. """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + self.model.add_subsystem( + 'fuel_obj', + om.ExecComp( + 'reg_objective = overall_fuel/10000 + ascent_duration/30.', + reg_objective={'val': 0.0, 'units': 'unitless'}, + ascent_duration={'units': 's', 'shape': 1}, + overall_fuel={'units': 'lbm'}, + ), + promotes_inputs=[ + ('ascent_duration', Mission.Takeoff.ASCENT_DURATION), + ('overall_fuel', Mission.Summary.TOTAL_FUEL_MASS), + ], + promotes_outputs=[('reg_objective', Mission.Objectives.FUEL)], + ) + + # TODO: All references to self.model. will need to be updated + self.model.add_subsystem( + 'range_obj', + om.ExecComp( + 'reg_objective = -actual_range/1000 + ascent_duration/30.', + reg_objective={'val': 0.0, 'units': 'unitless'}, + ascent_duration={'units': 's', 'shape': 1}, + actual_range={'val': self.model.target_range, 'units': 'NM'}, + ), + promotes_inputs=[ + ('actual_range', Mission.Summary.RANGE), + ('ascent_duration', Mission.Takeoff.ASCENT_DURATION), + ], + promotes_outputs=[('reg_objective', Mission.Objectives.RANGE)], + ) + # Dictionary for default reference values default_ref_values = { 'mass': -5e4, 'hybrid_objective': -5e4, 'fuel_burned': 1e4, - 'fuel': 1e4 + 'fuel': 1e4, } # Check if an objective type is specified if objective_type is not None: ref = ref if ref is not None else default_ref_values.get(objective_type, 1) - final_phase_name = self.regular_phases[-1] + final_phase_name = self.model.regular_phases[-1] + if objective_type == 'mass': - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - self.model.add_objective( - f"traj.{final_phase_name}.timeseries.{Dynamic.Mission.MASS}", - index=-1, ref=ref) - else: - last_phase = self.traj._phases.items()[final_phase_name] - last_phase.add_objective( - Dynamic.Mission.MASS, loc='final', ref=ref) + self.model.add_objective( + f'traj.{final_phase_name}.timeseries.{Dynamic.Vehicle.MASS}', + index=-1, + ref=ref, + ) elif objective_type == 'time': self.model.add_objective( - f"traj.{final_phase_name}.timeseries.time", index=-1, ref=ref) - elif objective_type == "hybrid_objective": - self._add_hybrid_objective(self.phase_info) - self.model.add_objective("obj_comp.obj") - elif objective_type == "fuel_burned": + f'traj.{final_phase_name}.timeseries.time', index=-1, ref=ref + ) + + elif objective_type == 'hybrid_objective': + self._add_hybrid_objective(self.model.mission_info) + self.model.add_objective('obj_comp.obj') + + elif objective_type == 'fuel_burned': self.model.add_objective(Mission.Summary.FUEL_BURNED, ref=ref) - elif objective_type == "fuel": + + elif objective_type == 'fuel': self.model.add_objective(Mission.Objectives.FUEL, ref=ref) + else: raise ValueError( - f"{objective_type} is not a valid objective.\nobjective_type must" - " be one of mass, time, hybrid_objective, fuel_burned, or fuel") + f"{objective_type} is not a valid objective. 'objective_type' must " + 'be one of the following: mass, time, hybrid_objective, ' + 'fuel_burned, or fuel' + ) else: # If no 'objective_type' is specified, we handle based on 'problem_type' # If 'ref' is not specified, assign a default value @@ -1972,609 +679,1106 @@ def add_objective(self, objective_type=None, ref=None): if self.problem_type is ProblemType.SIZING: self.model.add_objective(Mission.Objectives.FUEL, ref=ref) + elif self.problem_type is ProblemType.ALTERNATE: self.model.add_objective(Mission.Objectives.FUEL, ref=ref) + elif self.problem_type is ProblemType.FALLOUT: + # if ref > 0: + # # Maximize range. + # ref = -ref self.model.add_objective(Mission.Objectives.RANGE, ref=ref) + else: raise ValueError(f'{self.problem_type} is not a valid problem type.') - def _add_bus_variables_and_connect(self): - all_subsystems = self._get_all_subsystems() - - base_phases = list(self.phase_info.keys()) - - for external_subsystem in all_subsystems: - bus_variables = external_subsystem.get_bus_variables() - if bus_variables is not None: - for bus_variable, variable_data in bus_variables.items(): - mission_variable_name = variable_data['mission_name'] - - # check if mission_variable_name is a list - if not isinstance(mission_variable_name, list): - mission_variable_name = [mission_variable_name] - - # loop over the mission_variable_name list and add each variable to the trajectory - for mission_var_name in mission_variable_name: - if mission_var_name not in self.meta_data: - # base_units = self.model.get_io_metadata(includes=f'pre_mission.{external_subsystem.name}.{bus_variable}')[f'pre_mission.{external_subsystem.name}.{bus_variable}']['units'] - base_units = variable_data['units'] - - shape = variable_data.get('shape', _unspecified) - - targets = mission_var_name - if '.' in mission_var_name: - # Support for non-hierarchy variables as parameters. - mission_var_name = mission_var_name.split('.')[-1] - - if 'phases' in variable_data: - # Support for connecting bus variables into a subset of - # phases. - for phase_name in variable_data['phases']: - phase = getattr(self.traj.phases, phase_name) - - phase.add_parameter(mission_var_name, opt=False, static_target=True, - units=base_units, shape=shape, targets=targets) - - self.model.connect(f'pre_mission.{bus_variable}', - f'traj.{phase_name}.parameters:{mission_var_name}') - - else: - self.traj.add_parameter(mission_var_name, opt=False, static_target=True, - units=base_units, shape=shape, targets={ - phase_name: [mission_var_name] for phase_name in base_phases}) + def add_design_var_default( + self, + name: str, + lower: float = None, + upper: float = None, + units: str = None, + src_shape=None, + default_val: float = None, + ref: float = None, + ): + """ + Add a design variable to the problem as well as initialized a default value for that design variable. - self.model.connect( - f'pre_mission.{bus_variable}', f'traj.parameters:'+mission_var_name) + The default value can be over-written after setup with prob.set_val() - if 'post_mission_name' in variable_data: - self.model.connect(f'pre_mission.{external_subsystem.name}.{bus_variable}', - f'post_mission.{external_subsystem.name}.{variable_data["post_mission_name"]}') + Parameters + ---------- + name : string + A unique name that identifies this design variable. + lower : float, optional + The lowest value that the optimizer can choose for this design variable. + upper : float, optional + The largest value that the optimizer can choose for this design variable. + src_shape : int or tuple, optional + Assumed shape of any connected source or higher level promoted input. + default_val : float or ndarray, optional + The default value to be assigned to this design variable. + ref : float or ndarray, optional + Value of design var that scales to 1.0 in the driver. - def setup(self, **kwargs): """ - Lightly wrapped setup() method for the problem. - """ - # suppress warnings: - # "input variable '...' promoted using '*' was already promoted using 'aircraft:*' - with warnings.catch_warnings(): + self.model.add_design_var(name=name, lower=lower, upper=upper, units=units, ref=ref) + if default_val is not None: + self.model.set_input_defaults( + name=name, val=default_val, units=units, src_shape=src_shape + ) - self.model.options['aviary_options'] = self.aviary_inputs - self.model.options['aviary_metadata'] = self.meta_data - self.model.options['phase_info'] = self.phase_info + def set_design_range(self, missions: list[str], range: str): + # TODO: What happens if design range is specified in CSV??? should be able to access from group.aviary_values + """ + Used for multi-mission problems. This method finds the longest mission and sets its range + as the design range for all AviaryGroups. design_range is used within Aviary for sizing + subsystems (avionics and AC). This could be simpllified in the future if there was a + single pre-mission for similar aircraft. - warnings.simplefilter("ignore", om.OpenMDAOWarning) - warnings.simplefilter("ignore", om.PromotionWarning) - super().setup(**kwargs) + Parameters + ---------- + missions : list[str] + The names of all the missions instantiated via add_aviary_group() + range : str + The promoted name of the range variable. i.e. "Aircraft1.Range" - def set_initial_guesses(self, parent_prob=None, parent_prefix=""): """ - Call `set_val` on the trajectory for states and controls to seed - the problem with reasonable initial guesses. This is especially - important for collocation methods. - This method first identifies all phases in the trajectory then - loops over each phase. Specific initial guesses - are added depending on the phase and mission method. Cruise is treated - as a special phase for GASP-based missions because it is an AnalyticPhase - in Dymos. For this phase, we handle the initial guesses first separately - and continue to the next phase after that. For other phases, we set the initial - guesses for states and controls according to the information available - in the 'initial_guesses' attribute of the phase. + matching_names = [ + (name, group) for name, group in self.aviary_groups_dict.items() if name in missions + ] + design_range = [] + # loop through all the phase_info and extract target ranges + for name, group in matching_names: + target_range, units = group.post_mission_info['target_range'] + design_range.append(convert_units(target_range, units, 'nmi')) + # TODO: loop through all the .csv files and extract Mission.Design.RANGE + design_range_max = np.max(design_range) + self.set_val(range, val=design_range_max, units='nmi') + + def add_composite_objective(self, *args, ref: float = None): """ - setvalprob = self - if parent_prob is not None and parent_prefix != "": - setvalprob = parent_prob - # Grab the trajectory object from the model - if self.analysis_scheme is AnalysisScheme.SHOOTING: - if self.problem_type is ProblemType.SIZING: - setvalprob.set_val(parent_prefix+Mission.Summary.GROSS_MASS, - self.get_val(Mission.Design.GROSS_MASS)) - - setvalprob.set_val(parent_prefix+"traj.SGMClimb_"+Dynamic.Mission.ALTITUDE + - "_trigger", val=self.cruise_alt, units="ft") - - return + Creates composite_objective output by assemblin an ExecComp based on a variety of AviaryGroup + outputs selected by the user. A number of different outputs from the same or different + aricraft can be combined in this way such as creating an objective function based on fuel + plus noise emissions. Each objective output should include a weight otherwise the weight will be + assumed to be equal (i.e. fuel is equally important as reducing noise emissions). - traj = self.model.traj - - # Determine which phases to loop over, fetching them from the trajectory - phase_items = traj._phases.items() - - # Loop over each phase and set initial guesses for the state and control variables - for idx, (phase_name, phase) in enumerate(phase_items): - if self.mission_method is SOLVED_2DOF: - self.phase_objects[idx].apply_initial_guesses(self, 'traj', phase) - if self.phase_info[phase_name]['user_options']['ground_roll'] and self.phase_info[phase_name]['user_options']['fix_initial']: - continue + Parameters + ---------- + *args : a list of 3-tuple, 2-tuple, str. Or it can be left empty + If 3-tuple: (model, output, weight) + If 2-tuple: (model, output) or (output, weight) + If 1-tuple: (output) or 'fuel', 'fuel_burned', 'mass', 'range', 'time' + If empty, information will be populated based on problem_type: + - If ProblemType = FALLOUT, objective = Mission.Objectives.RANGE + - If ProblemType = Sizing or Alternate, objective = Mission.Objectives.FUEL + + Example inputs can be any of the following: + ('fuel') + (Mission.Summary.FUEL_BURNED) + (Mission.Summary.FUEL_BURNED, Mission.Summary.CO2) + ('model1', Mission.Summary.FUEL_BURNED) + (Mission.Summary.FUEL_BURNED, 1.0) + (Mission.Summary.FUEL_BURNED, 1.0), (Mission.Summary.CO2, 2.0) + ('model1', Mission.Summary.FUEL_BURNED), ('model2', Mission.Summary.CO2) + ('model1', Mission.Summary.FUEL_BURNED, 1.0), ('model2', Mission.Summary.CO2, 2.0) + + ref : float, optional + Reference value for the final objective for scaling. + + Behavior + -------- + - Connects each specified mission output into a newly created `ExecComp` block. + - Computes a weighted sum: each output is weighted by both the total weights + - Adds the result as the final objective named `'composite_objective'`, accessible at the top level model. + """ - # If not, fetch the initial guesses specific to the phase - # check if guesses exist for this phase - if "initial_guesses" in self.phase_info[phase_name]: - guesses = self.phase_info[phase_name]['initial_guesses'] + # There are LOTS of different ways for the users to input str, 2-tuple, or 3-tuple into *args + # Correct combinations are (output), (output, weight), (model, output), or (model, output, weight). + # We have to catch every case and advise the user on how to corect their errors and add defaults as needed. + default_model = 'model' + default_weight = 1.0 + objectives = [] + for arg in args: + if isinstance(arg, tuple) and len(arg) == 3: + model, output, weight = arg + if model not in self.aviary_groups_dict: + raise ValueError( + f'The first element specified in {arg} must be the model name.' + ) + elif isinstance(arg, tuple) and len(arg) == 2: + first, second = arg + if isinstance(first, str) and isinstance(second, str): + if first in self.aviary_groups_dict: + # we have the model and output but no weight + model, output, weight = first, second, default_weight + else: + raise ValueError( + f'The first element specified in {arg} must be the model name.' + ) + elif isinstance(first, str) and isinstance(second, (float, int)): + if first in self.aviary_groups_dict: + raise ValueError( + f'When specifying {arg}, the user specified a model name and a weight ' + f'but did not specify what output from that model the weight should be applied to.' + ) + else: + # we have the output and the weight but not model + model, output, weight = default_model, first, second + else: + raise ValueError( + f'The user specified {arg} which is not a 2-tuple of (model, output) or (output, weight).' + ) + elif isinstance(arg, str): + if arg in self.aviary_groups_dict: + raise ValueError( + f"When specifying '{arg}', the user provided only a model name " + f'but did not specify what output from that model should be used as the objective.' + ) + else: + # we have an output and we use the default model and weights + model, output, weight = default_model, arg, default_weight + + # in some cases the users provides no input and we can derive the objectie from the problem type: + elif self.model.problem_type is ProblemType.SIZING: + model, output, weight = default_model, Mission.Objectives.FUEL, default_weight + elif self.model.problem_type is ProblemType.ALTERNATE: + model, output, weight = default_model, Mission.Objectives.FUEL, default_weight + elif self.model.problem_type is ProblemType.FALLOUT: + model, output, weight = default_model, Mission.Objectives.RANGE, default_weight else: - guesses = {} - - if self.mission_method is TWO_DEGREES_OF_FREEDOM and \ - self.phase_info[phase_name]["user_options"].get("analytic", False): - for guess_key, guess_data in guesses.items(): - val, units = guess_data + raise ValueError( + f'Unrecognized objective format: {arg}. ' + f'Each argument must be one of the following: ' + f'(output), (output, weight), (model, output), or (model, output, weight).' + f'Outputs can be from the variable meta data, or can be: fuel_burned, fuel' + f'Or problem type must be set to SIZING, ALTERNATE, or FALLOUT' + ) + objectives.append((model, output, weight)) + # objectives = [ + # ('model1', Mission.Summary.FUEL_BURNED, 1), + # ('model2', Mission.Summary.CO2, 1), + # ... + # ] - if 'mass' == guess_key: - # Set initial and duration mass for the analytic cruise phase. - # Note we are integrating over mass, not time for this phase. - setvalprob.set_val(parent_prefix+f'traj.{phase_name}.t_initial', - val[0], units=units) - setvalprob.set_val(parent_prefix+f'traj.{phase_name}.t_duration', - val[1], units=units) + # Dictionary for default reference values + default_ref_values = { + 'mass': -5e4, + 'hybrid_objective': -5e4, + 'fuel_burned': 1e4, + 'fuel': 1e4, + } - else: - # Otherwise, set the value of the parameter in the trajectory phase - setvalprob.set_val( - parent_prefix + f'traj.{phase_name}.parameters:{guess_key}', - val, units=units) + # Now checkout the output and see if we have recognizable strings and replace them with the variable meta data name + objectives_cleaned = [] + for model, output, weight in objectives: + if output == 'fuel_burned': + output = Mission.Summary.FUEL_BURNED + # default scaling is valid only if this is the only argument and the ref has not yet been set + if len(args) == 1 and ref == None: + # set a default ref + ref = default_ref_values['fuel_burned'] + elif output == 'fuel': + output = Mission.Objectives.FUEL + if len(args) == 1 and ref == None: + ref = default_ref_values['fuel'] + elif output == 'mass': + output = Mission.Summary.FINAL_MASS + if len(args) == 1 and ref == None: + ref = default_ref_values['mass'] + elif output == 'time': + output = Mission.Summary.FINAL_TIME + elif output == 'range': + output = Mission.Summary.RANGE # Unsure if this will work + objectives_cleaned.append((model, output, weight)) + + # Create the calculation string for the ExecComp() and the promotion reference values + weighted_exprs = [] + connection_names = [] + obj_inputs = [] + total_weight = sum(weight for _, _, weight in objectives_cleaned) + for model, output, weight in objectives_cleaned: + output_safe = output.replace(':', '_') + + # we use "_" here because ExecComp() cannot intake "." + obj_input = f'{model}_{output_safe}' + obj_inputs.append(obj_input) + weighted_exprs.append(f'{obj_input}*{weight}/{total_weight}') + connection_names.append( + [f'{model}.{output}', f'composite_function.{model}_{output_safe}'] + ) + final_expr = ' + '.join(weighted_exprs) - continue + # weighted_str looks like: 'model1_fuelburn*0.67*0.5 + model1_gross_mass*0.33*0.5 + model2_fuelburn*0.67*0.5 + model2_gross_mass*0.33*0.5' - # If not cruise and GASP, add subsystem guesses - self._add_subsystem_guesses(phase_name, phase, setvalprob, parent_prefix) + kwargs = {} + if version.parse(openmdao.__version__) >= version.parse('3.40'): + # We can get the correct unit from the source. This prevents a warning. + kwargs = {k: {'units_by_conn': True} for k in obj_inputs} - # Set initial guesses for states and controls for each phase - self._add_guesses(phase_name, phase, guesses, setvalprob, parent_prefix) + # adding composite execComp to super problem + self.model.add_subsystem( + 'composite_function', + om.ExecComp('composite_objective = ' + final_expr, **kwargs), + promotes_outputs=['composite_objective'], + ) - def _process_guess_var(self, val, key, phase): + # connect from inside of the models to the composite objective + for source, target in connection_names: + self.model.connect(source, target) + # finally add the objective + self.model.add_objective('composite_objective', ref=ref) + + def add_composite_objective_adv( + self, + missions: list[str], + outputs: list[str], + mission_weights: list[float] = None, + output_weights: list[float] = None, + ref: float = 1.0, + ): """ - Process the guess variable, which can either be a float or an array of floats. - This method is responsible for interpolating initial guesses when the user - provides a list or array of values rather than a single float. It interpolates - the guess values across the phase's domain for a given variable, be it a control - or a state variable. The interpolation is performed between -1 and 1 (representing - the normalized phase time domain), using the numpy linspace function. - The result of this method is a single value or an array of interpolated values - that can be used to seed the optimization problem with initial guesses. + Adds a composite objective function to the OpenMDAO problem by aggregating output values across + multiple mission models, with independent weighting for both missions and outputs. This is most + useful when you have historical information on how often a given mission was flown (mission_weights) + and then you have a duel set of objectives you wish to include i.e. for each flight minimize + both fuel_burned and gross_mass. How important fuel_burned is vs. gross_mass is determined via + specifying output_weights. + Parameters ---------- - val : float or list/array of floats - The initial guess value(s) for a particular variable. - key : str - The key identifying the variable for which the initial guess is provided. - phase : Phase - The phase for which the variable is being set. - Returns - ------- - val : float or array of floats - The processed guess value(s) to be used in the optimization problem. + missions : list of str + List of subsystem names (e.g., 'model1', 'model2') corresponding to different missions. + + outputs : list of str + List of output variable names (e.g., Mission.Summary.FUEL_BURNED, Mission.Summary.GROSS_MASS) to be included + in the objective from each mission. + + mission_weights : list of float, optional + Weights assigned to each mission. If None, equal weighting is assumed. + These weights will be normalized internally to sum to 1.0. + + output_weights : list of float, optional + Weights assigned to each output variable. If None, equal weighting is assumed. + These weights will also be normalized internally to sum to 1.0. + + ref : float, optional + Reference value for the final objective. Passed to `add_objective()` for scaling. + + Behavior + -------- + - Connects each specified mission output into a newly created `ExecComp` block. + - Computes a weighted sum: each output is weighted by both its output weight + and the weight of the mission it came from. + - Adds the result as the final objective named `'composite_objective'`, accessible at the top level model. """ - # Check if val is not a single float - if not isinstance(val, float): - # If val is an array of values - if len(val) > 1: - # Get the shape of the val array - shape = np.shape(val) - - # Generate an array of evenly spaced values between -1 and 1, - # reshaping to match the shape of the val array - xs = np.linspace(-1, 1, num=np.prod(shape)).reshape(shape) - - # Check if the key indicates a control or state variable - if "controls:" in key or "states:" in key: - # If so, strip the first part of the key to match the variable name in phase - stripped_key = ":".join(key.split(":")[1:]) - - # Interpolate the initial guess values across the phase's domain - val = phase.interp(stripped_key, xs=xs, ys=val) - else: - # If not a control or state variable, interpolate the initial guess values directly - val = phase.interp(key, xs=xs, ys=val) - # Return the processed guess value(s) - return val + # Setup mission and output lengths if they are not already given + if mission_weights is None: + mission_weights = np.ones(len(missions)) + + if output_weights is None: + output_weights = np.ones(len(outputs)) + + # # Make an ExecComp + # for mission in missions: + # for output in outputs: + + # weights are normalized - e.g. for given weights 3:1, the normalized + # weights are 0.75:0.25 + # TODO: Remove before push + # output_weights = [2,1] + # mission_weights = [1,1] + # missions = ['model1','model2'] + # outputs = ['fuelburn','gross_mass'] + weighted_exprs = [] + connection_names = [] + output_weights = [float(weight / sum(output_weights)) for weight in output_weights] + mission_weights = [float(weight / sum(mission_weights)) for weight in mission_weights] + for mission, mission_weight in zip(missions, mission_weights): + for output, output_weight in zip(outputs, output_weights): + connection_names.append( + [f'composite_function.{mission}_{output}', f'{mission}.{output}'] + ) + weighted_exprs.append(f'{mission}_{output}*{output_weight}*{mission_weight}') + final_expr = ' + '.join(weighted_exprs) + # weighted_str looks like: 'model1.fuelburn*0.67*0.5 + model1.gross_mass*0.33*0.5 + model2.fuelburn*0.67*0.5 + model2.gross_mass*0.33*0.5' + + # adding composite execComp to super problem + self.model.add_subsystem( + 'composite_function', + om.ExecComp('composite_objective = ' + final_expr, has_diag_partials=True), + promotes_outputs=['composite_objective'], + ) + # connect from inside of the models to the composite objective + for target, source in connection_names: + self.model.connect(target, source) + # finally add the objective + self.model.add_objective('composite_objective', ref=ref) - def _add_subsystem_guesses(self, phase_name, phase, setvalprob, parent_prefix): + def build_model(self, verbosity=None): """ - Adds the initial guesses for each subsystem of a given phase to the problem. - This method first fetches all subsystems associated with the given phase. - It then loops over each subsystem and fetches its initial guesses. For each - guess, it identifies whether the guess corresponds to a state or a control - variable and then processes the guess variable. After this, the initial - guess is set in the problem using the `set_val` method. + A lightly wrapped add_pre_mission_systems(), add_phases(), add_post_mission_systems(), and link_phases() + method to decrease code length for the avarage user. If the user needs finer control, they should + not use build_model but instead call the four individual methods separately. + Parameters ---------- - phase_name : str - The name of the phase for which the subsystem guesses are being added. - phase : Phase - The phase object for which the subsystem guesses are being added. + verbosity : Verbosity or int, optional + Controls the level of printouts for this method. """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + group.add_pre_mission_systems(verbosity=verbosity) + group.add_phases(verbosity=verbosity, comm=self.comm) + group.add_post_mission_systems(verbosity=verbosity) + group.link_phases(verbosity=verbosity, comm=self.comm) + else: + self.model.add_pre_mission_systems(verbosity=verbosity) + self.model.add_phases(verbosity=verbosity, comm=self.comm) + self.model.add_post_mission_systems(verbosity=verbosity) + self.model.link_phases(verbosity=verbosity, comm=self.comm) - # Get all subsystems associated with the phase - all_subsystems = self._get_all_subsystems( - self.phase_info[phase_name]['external_subsystems']) + def promote_inputs(self, mission_names: list[str], var_pairs: list[tuple[str, str]]): + """ + Link a promoted input to multiple groups' unpromoted inputs using an internal IVC. - # Loop over each subsystem - for subsystem in all_subsystems: - # Fetch the initial guesses for the subsystem - initial_guesses = subsystem.get_initial_guesses() + Parameters + ---------- + self : om.Problem + The Problem instance this is being called from. - # Loop over each guess - for key, val in initial_guesses.items(): - # Identify the type of the guess (state or control) - type = val.pop('type') - if 'state' in type: - path_string = 'states' - elif 'control' in type: - path_string = 'controls' + missions : list of str + The subsystem names receiving the connection. - # Process the guess variable (handles array interpolation) - val['val'] = self._process_guess_var(val['val'], key, phase) + var_pairs : list of (str, str) + Each pair is (input_name_in_group, top_level_name_to_use) + """ - # Set the initial guess in the problem - setvalprob.set_val( - parent_prefix+f'traj.{phase_name}.{path_string}:{key}', **val) + # + for name, group in self.aviary_groups_dict.items(): + for mission_name in mission_names: + if name == mission_name: + # the group name matches the mission name, + # group.promotes(var_pairs) + # print("var_pairs",var_pairs) + self.model.promotes(mission_name, inputs=var_pairs) - def _add_guesses(self, phase_name, phase, guesses, setvalprob, parent_prefix): + def setup(self, **kwargs): """ - Adds the initial guesses for each variable of a given phase to the problem. - This method sets the initial guesses for time, control, state, and problem-specific - variables for a given phase. If using the GASP model, it also handles some special - cases that are not covered in the `phase_info` object. These include initial guesses - for mass, time, and distance, which are determined based on the phase name and other - mission-related variables. + A lightly wrapped setup() and set_initial_defaults() method for the problem. + Parameters ---------- - phase_name : str - The name of the phase for which the guesses are being added. - phase : Phase - The phase object for which the guesses are being added. - guesses : dict - A dictionary containing the initial guesses for the phase. + verbosity : Verbosity or int, optional + Controls the level of printouts for this method. + **kwargs : optional + All arguments to be passed to the OpenMDAO prob.setup() method. """ - # If using the GASP model, set initial guesses for the rotation mass and flight duration - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - rotation_mass = self.initialization_guesses['rotation_mass'] - flight_duration = self.initialization_guesses['flight_duration'] - - if self.mission_method in (HEIGHT_ENERGY, SOLVED_2DOF): - control_keys = ["mach", "altitude"] - state_keys = ["mass", Dynamic.Mission.DISTANCE] + # verbosity is not used in this method, but it is understandable that a user + # might try and include it (only method that doesn't accept it). Capture it + if 'verbosity' in kwargs: + kwargs.pop('verbosity') + # Use OpenMDAO's model options to pass all options through the system hierarchy. + + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + setup_model_options( + self, group.aviary_inputs, group.meta_data, prefix=name, group=group + ) + with warnings.catch_warnings(): + # group.aviary_inputs is already set + group.meta_data = self.meta_data # <- meta_data is the same for all groups + # group.phase_info is already set else: - control_keys = ["velocity_rate", "throttle"] - state_keys = ["altitude", "mass", Dynamic.Mission.DISTANCE, - Dynamic.Mission.VELOCITY, "flight_path_angle", "alpha"] - if self.mission_method is TWO_DEGREES_OF_FREEDOM and phase_name == 'ascent': - # Alpha is a control for ascent. - control_keys.append('alpha') - - prob_keys = ["tau_gear", "tau_flaps"] - - # for the simple mission method, use the provided initial and final mach and altitude values from phase_info - if self.mission_method in (HEIGHT_ENERGY, SOLVED_2DOF): - initial_altitude = wrapped_convert_units( - self.phase_info[phase_name]['user_options']['initial_altitude'], 'ft') - final_altitude = wrapped_convert_units( - self.phase_info[phase_name]['user_options']['final_altitude'], 'ft') - initial_mach = self.phase_info[phase_name]['user_options']['initial_mach'] - final_mach = self.phase_info[phase_name]['user_options']['final_mach'] - - guesses["mach"] = ([initial_mach[0], final_mach[0]], "unitless") - guesses["altitude"] = ([initial_altitude, final_altitude], 'ft') - - if self.mission_method is HEIGHT_ENERGY: - # if time not in initial guesses, set it to the average of the initial_bounds and the duration_bounds - if 'time' not in guesses: - initial_bounds = wrapped_convert_units( - self.phase_info[phase_name]['user_options']['initial_bounds'], 's') - duration_bounds = wrapped_convert_units( - self.phase_info[phase_name]['user_options']['duration_bounds'], 's') - guesses["time"] = ([np.mean(initial_bounds[0]), np.mean( - duration_bounds[0])], 's') - - # if time not in initial guesses, set it to the average of the initial_bounds and the duration_bounds - if 'time' not in guesses: - initial_bounds = self.phase_info[phase_name]['user_options'][ - 'initial_bounds'] - duration_bounds = self.phase_info[phase_name]['user_options'][ - 'duration_bounds'] - # Add a check for the initial and duration bounds, raise an error if they are not consistent - if initial_bounds[1] != duration_bounds[1]: - raise ValueError( - f"Initial and duration bounds for {phase_name} are not consistent.") - guesses["time"] = ([np.mean(initial_bounds[0]), np.mean( - duration_bounds[0])], initial_bounds[1]) + setup_model_options(self, self.aviary_inputs, self.meta_data) + # suppress warnings: + # "input variable '...' promoted using '*' was already promoted using 'aircraft:*' + with warnings.catch_warnings(): + self.model.aviary_inputs = ( + self.aviary_inputs + ) # <- there is only one aviary_inputs in this case + self.model.meta_data = self.meta_data + # self.model.phase_info is already set - for guess_key, guess_data in guesses.items(): - val, units = guess_data + with warnings.catch_warnings(): + warnings.simplefilter('ignore', om.OpenMDAOWarning) + warnings.simplefilter('ignore', om.PromotionWarning) - # Set initial guess for time variables - if 'time' == guess_key and self.mission_method is not SOLVED_2DOF: - setvalprob.set_val(parent_prefix+f'traj.{phase_name}.t_initial', - val[0], units=units) - setvalprob.set_val(parent_prefix+f'traj.{phase_name}.t_duration', - val[1], units=units) + super().setup(**kwargs) - else: - # Set initial guess for control variables - if guess_key in control_keys: - try: - setvalprob.set_val( - parent_prefix + f'traj.{phase_name}.controls:{guess_key}', - self._process_guess_var(val, guess_key, phase), - units=units) - except KeyError: - try: - setvalprob.set_val( - parent_prefix + - f'traj.{phase_name}.polynomial_controls:{guess_key}', - self._process_guess_var(val, guess_key, phase), - units=units) - except KeyError: - setvalprob.set_val(parent_prefix + - f'traj.{phase_name}.bspline_controls:', - {guess_key}, - self._process_guess_var( - val, guess_key, phase), - units=units) - - if self.mission_method is SOLVED_2DOF: - continue - - if guess_key in control_keys: - pass - # Set initial guess for state variables - elif guess_key in state_keys: - setvalprob.set_val(parent_prefix + - f'traj.{phase_name}.states:{guess_key}', self. - _process_guess_var(val, guess_key, phase), - units=units) - elif guess_key in prob_keys: - setvalprob.set_val(parent_prefix+guess_key, val, units=units) - elif ":" in guess_key: - setvalprob.set_val(parent_prefix + - f'traj.{phase_name}.{guess_key}', self._process_guess_var( - val, guess_key, phase), - units=units) - else: - # raise error if the guess key is not recognized - raise ValueError( - f"Initial guess key {guess_key} in {phase_name} is not recognized.") + self.set_initial_guesses(verbosity=None) - if self.mission_method is SOLVED_2DOF: - return + def set_initial_guesses(self, parent_prob=None, parent_prefix='', verbosity=None): + """ + Call `set_val` on the trajectory for states and controls to seed the problem with + reasonable initial guesses. This is especially important for collocation methods. + + This method first identifies all phases in the trajectory then loops over each phase. + Specific initial guesses are added depending on the phase and mission method. Cruise is + treated as a special phase for GASP-based missions because it is an AnalyticPhase in + Dymos. For this phase, we handle the initial guesses first separately and continue to the + next phase after that. For other phases, we set the initial guesses for states and + controls according to the information available in the 'initial_guesses' attribute of the + phase. + """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + if self.problem_type == ProblemType.MULTI_MISSION: + for name, group in self.aviary_groups_dict.items(): + group.set_initial_guesses( + parent_prob=parent_prob, + parent_prefix=parent_prefix, + verbosity=verbosity, + ) - # We need some special logic for these following variables because GASP computes - # initial guesses using some knowledge of the mission duration and other variables - # that are only available after calling `create_vehicle`. Thus these initial guess - # values are not included in the `phase_info` object. - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - base_phase = phase_name.removeprefix('reserve_') else: - base_phase = phase_name - if 'mass' not in guesses: - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - # Determine a mass guess depending on the phase name - if base_phase in ["groundroll", "rotation", "ascent", "accel", "climb1"]: - mass_guess = rotation_mass - elif base_phase == "climb2": - mass_guess = 0.99 * rotation_mass - elif "desc" in base_phase: - mass_guess = 0.9 * self.cruise_mass_final - else: - mass_guess = self.aviary_inputs.get_val( - Mission.Design.GROSS_MASS, units='lbm') - # Set the mass guess as the initial value for the mass state variable - setvalprob.set_val(parent_prefix+f'traj.{phase_name}.states:mass', - mass_guess, units='lbm') - - if 'time' not in guesses: - # Determine initial time and duration guesses depending on the phase name - if 'desc1' == base_phase: - t_initial = flight_duration*.9 - t_duration = flight_duration*.04 - elif 'desc2' in base_phase: - t_initial = flight_duration*.94 - t_duration = 5000 - # Set the time guesses as the initial values for the time-related trajectory variables - setvalprob.set_val(parent_prefix+f"traj.{phase_name}.t_initial", - t_initial, units='s') - setvalprob.set_val(parent_prefix+f"traj.{phase_name}.t_duration", - t_duration, units='s') - - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - if 'distance' not in guesses: - # Determine initial distance guesses depending on the phase name - if 'desc1' == base_phase: - ys = [self.target_range*.97, self.target_range*.99] - elif 'desc2' in base_phase: - ys = [self.target_range*.99, self.target_range] - # Set the distance guesses as the initial values for the distance state variable - setvalprob.set_val(parent_prefix + - f"traj.{phase_name}.states:distance", phase.interp( - Dynamic.Mission.DISTANCE, ys=ys) - ) - - def run_aviary_problem(self, record_filename="problem_history.db", - optimization_history_filename=None, restart_filename=None, - suppress_solver_print=True, run_driver=True, simulate=False, - make_plots=True): + self.model.set_initial_guesses( + parent_prob=parent_prob, + parent_prefix=parent_prefix, + verbosity=verbosity, + ) + + def run_aviary_problem( + self, + restart_filename=None, + suppress_solver_print=True, + run_driver=True, + simulate=False, + make_plots=True, + verbosity=None, + ): """ - This function actually runs the Aviary problem, which could be a simulation, optimization, or a driver execution, depending on the arguments provided. + This function actually runs the Aviary problem, which could be a simulation, + optimization, or a driver execution, depending on the arguments provided. Parameters ---------- - record_filename : str, optional - The name of the database file where the solutions are to be recorded. The default is "problem_history.db". - optimization_history_filename : str, None - The name of the database file where the driver iterations are to be recorded. The default is None. restart_filename : str, optional - The name of the file that contains previously computed solutions which are to be used as starting points for this run. If it is None (default), no restart file will be used. + The name of the file that contains previously computed solutions which are + to be used as starting points for this run. If it is None (default), no + restart file will be used. suppress_solver_print : bool, optional - If True (default), all solvers' print statements will be suppressed. Useful for deeply nested models with multiple solvers so the print statements don't overwhelm the output. + If True (default), all solvers' print statements will be suppressed. Useful + for deeply nested models with multiple solvers so the print statements don't + overwhelm the output. run_driver : bool, optional - If True (default), the driver (aka optimizer) will be executed. If False, the problem will be run through one pass -- equivalent to OpenMDAO's `run_model` behavior. + If True (default), the driver (aka optimizer) will be executed. If False, + the problem will be run through one pass -- equivalent to OpenMDAO's + `run_model` behavior. simulate : bool, optional - If True, an explicit Dymos simulation will be performed. The default is False. + If True, an explicit Dymos simulation will be performed. The default is + False. make_plots : bool, optional If True (default), Dymos html plots will be generated as part of the output. + verbosity : Verbosity or int, optional + Controls the level of printouts for this method. """ + # `self.verbosity` is "true" verbosity for entire run. `verbosity` is verbosity + # override for just this method + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF - if self.aviary_inputs.get_val(Settings.VERBOSITY).value >= 2: + if verbosity >= Verbosity.VERBOSE: # VERBOSE, DEBUG self.final_setup() - with open('input_list.txt', 'w') as outfile: + with open(self.get_reports_dir() / 'input_list.txt', 'w') as outfile: self.model.list_inputs(out_stream=outfile) + recorder = om.SqliteRecorder('optimization_history.db') + self.driver.add_recorder(recorder) + if suppress_solver_print: self.set_solver_print(level=0) - if optimization_history_filename: - recorder = om.SqliteRecorder(optimization_history_filename) - self.driver.add_recorder(recorder) - # and run mission, and dynamics if run_driver: - failed = dm.run_problem( - self, run_driver=run_driver, simulate=simulate, make_plots=make_plots, - solution_record_file=record_filename, restart=restart_filename) + self.result = dm.run_problem( + self, + run_driver=run_driver, + simulate=simulate, + make_plots=make_plots, + solution_record_file='problem_history.db', + restart=restart_filename, + ) + + # Manually print out a failure message for low verbosity modes that suppress + # optimizer printouts, which may include the results message. Assumes success, + # alerts user on a failure + if ( + not self.result.success and verbosity <= Verbosity.BRIEF # QUIET, BRIEF + ): + warnings.warn('\nAviary run failed. See the dashboard for more details.\n') else: - # prevent UserWarning that is displayed when an event is triggered - warnings.filterwarnings('ignore', category=UserWarning) - failed = self.run_model() - warnings.filterwarnings('default', category=UserWarning) + self.run_model() + self.result = self.driver.result + + # update n2 diagram after run. + outdir = Path(self.get_reports_dir(force=True)) + outfile = os.path.join(outdir, 'n2.html') + om.n2( + self, + outfile=outfile, + show_browser=False, + ) - if self.aviary_inputs.get_val(Settings.VERBOSITY).value >= 2: - with open('output_list.txt', 'w') as outfile: + if verbosity >= Verbosity.VERBOSE: # VERBOSE, DEBUG + with open(Path(self.get_reports_dir()) / 'output_list.txt', 'w') as outfile: self.model.list_outputs(out_stream=outfile) - self.problem_ran_successfully = not failed - - def alternate_mission(self, run_mission=True, - json_filename='sizing_problem.json', - payload_mass=None, mission_range=None, - phase_info=None, verbosity=Verbosity.BRIEF): + if self.generate_payload_range: + self.run_payload_range() + + def run_off_design_mission( + self, + problem_type: ProblemType, + phase_info=None, + equations_of_motion: EquationsOfMotion = None, + problem_configurator=None, + num_first_class=None, + num_business=None, + num_tourist=None, + num_pax=None, + wing_cargo=None, + misc_cargo=None, + cargo_mass=None, + mission_gross_mass=None, + mission_range=None, + optimizer=None, + name=None, + fill_cargo=False, + fill_fuel=False, + verbosity=None, + payload_range_controls=None, + ): """ - This function runs an alternate mission based on a sizing mission output. + Runs the aircraft model in a off-design mission of the specified type. It is assumed that + the AviaryProblem is loaded with an already sized aircraft. Parameters ---------- - run_mission : bool - Flag to determine whether to run the mission before returning the problem object. - json_filename : str - Name of the file that the sizing mission has been saved to. - mission_range : float, optional - Target range for the fallout mission. - payload_mass : float, optional - Mass of the payload for the mission. + problem_type : str, ProblemType + The type of off-design mission to be flown. SIZING missions are not allowed. phase_info : dict, optional - Dictionary containing the phases and their required parameters. - verbosity : Verbosity or list, optional - If Verbosity.DEBUG, debug print options ['desvars','ln_cons','nl_cons','objs'] will be set. - If a list is provided, it will be used as the debug print options. + The phase_info to use for the off-design mission. If not provided, the phase info used + for the previous Aviary run (typically the design mission) is used. + equation_of_motion : (str, EquationsOfMotion), optional + Which equations of motion to use for the off-design mission. If not provided, the + equations of motion used for the previous Aviary run (typically the design mission) is + used. + problem_configurator : ProblemConfigurator, optional + Problem configurator to use for the off-design mission. If not provided, the problem + configurator used for the previous Aviary run (typically the design mission) is used. + num_first_class : int, optional + [FLOPS mass only] Number of first-class passengers flying on the off-design mission. + num_business : int, optional + [FLOPS mass only] Number of business-class passengers flying on the off-design mission. + num_tourist : int, optional + [FLOPS mass only] Number of tourist-class passengers flying on the off-design mission. + num_pax : int, optional + Total number of passengers flying on the off-design mission. Optional if using + FLOPS-based mass and passengers per class are defined instead. + wing_cargo : float, optional + [FLOPS mass only] Mass of wing cargo flying on off-design mission, in pounds-mass. + misc_cargo : float, optional + [FLOPS mass only] Mass of miscellaneous cargo flying on off-design mission, in + pounds-mass. + cargo_mass : float, optional + Total cargo mass flying on off-design mission, in pounds-mass. Optional if using FLOPS- + based mass, individual wing and/or misc cargo is defined, and no additional cargo is + being carried elsewhere. Note: if using FLOPS-based mass, this variable is an override + for total cargo mass. + mission_gross_mass : float, optional + Gross mass of aircraft flying off-design mission, in pounds-mass. Defaults to design + gross mass. For missions where mass is solved for (such as ALTERNATE missions), this is + the initial guess. + mission_range : float, optional + [ALTERNATE missions only] + Sets fixed range of flown off-design mission, in nautical miles. Unused for other + mission types. + optimizer : string, optional + Set which optimizer to use for the off-design mission. If not provided, the optimizer + used for the previously ran sizing mission is used. If that cannot be found, such as + when a problem is loaded from a json output file, then the default optimizer (SLSQP) + is chosen. + name : str, optional + Name of the off-design problem. Defaults to "{original problem name}_off_design". + fill_cargo : bool, optional + Adds a design variable to vary cargo mass to exactly fill the aircraft to design + takeoff gross weight. Useful for cases where precise cargo mass required is not known, + or when operating mass can change between missions. Defaults to False. Cannot be used at + the same time as fill_fuel. + fill_fuel : bool, optional + Adds takeoff gross mass as a design variable. Useful for cases when operating mass can + change between missions. Defaults to False. Cannot be used at the same time as + fill_cargo. + verbosity : (int, Verbosity), optional + Sets the printout level for the entire off-design problem that is ran. + payload_range_controls : bool, optional + Flag used by run_payload_range method call. Adds a cargo variable as a design variable + (chosen based on the specific problem), which is allowed to float a small amount to + account for issues when hardcoding payload & fuel mass for certain points on the + payload-range diagram. This argument is generally not needed for users manually running + off-design missions. """ + # For off-design missions, provided verbosity will be used for all L2 method calls + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + # accept str for problem type + problem_type = ProblemType(problem_type) + if problem_type is ProblemType.SIZING: + raise UserWarning('Off-design missions cannot be SIZING missions.') + + if fill_cargo and fill_fuel: + raise UserWarning( + 'Cannot run an off-design mission with both "fill_cargo" and "fill_fuel" flags ' + 'active.' + ) + + if name is None: + name = name = self._name + '_off_design' + off_design_prob = AviaryProblem(name=name) + + # Set up problem for mission, such as equations of motion, configurators, etc. + inputs = deepcopy(self.aviary_inputs) + + design_gross_mass = self.get_val(Mission.Design.GROSS_MASS, units='lbm')[0] + inputs.set_val(Mission.Design.GROSS_MASS, design_gross_mass, units='lbm') + + if problem_type is not None: + inputs.set_val(Settings.PROBLEM_TYPE, problem_type) + if equations_of_motion is not None: + inputs.set_val(Settings.EQUATIONS_OF_MOTION, equations_of_motion) + + if problem_configurator is not None: + off_design_prob.model.configurator = problem_configurator + if phase_info is None: - phase_info = self.phase_info - if mission_range is None: - design_range = self.get_val(Mission.Design.RANGE) - if payload_mass is None: - if self.mission_method is HEIGHT_ENERGY: - payload_mass = self.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS) - elif self.mission_method is TWO_DEGREES_OF_FREEDOM: - payload_mass = self.get_val(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS) - - mission_mass = self.get_val(Mission.Design.GROSS_MASS) - optimizer = self.driver.options["optimizer"] - - prob_alternate = _load_off_design(json_filename, ProblemType.ALTERNATE, - phase_info, payload_mass, design_range, mission_mass) - - prob_alternate.check_and_preprocess_inputs() - prob_alternate.add_pre_mission_systems() - prob_alternate.add_phases() - prob_alternate.add_post_mission_systems() - prob_alternate.link_phases() - prob_alternate.add_driver(optimizer, verbosity=verbosity) - prob_alternate.add_design_variables() - prob_alternate.add_objective() - prob_alternate.setup() - prob_alternate.set_initial_guesses() - if run_mission: - prob_alternate.run_aviary_problem( - record_filename='alternate_problem_history.db') - return prob_alternate - - def fallout_mission(self, run_mission=True, - json_filename='sizing_problem.json', - mission_mass=None, payload_mass=None, - phase_info=None, verbosity=Verbosity.BRIEF): + # model phase_info only contains mission information, recreate the whole thing here + phase_info = self.model.mission_info.copy() + phase_info['pre_mission'] = self.model.pre_mission_info.copy() + phase_info['post_mission'] = self.model.post_mission_info.copy() + + # update passenger count and cargo masses + mass_method = inputs.get_val(Settings.MASS_METHOD) + + # Sanity check passenger counts - cover specific edge case that preprocessors won't catch + # Since we inherit mission pax count from sizing mission, we need to overwrite it + if ( + mass_method is FLOPS + and num_pax is None + and not any((num_tourist, num_business, num_first_class)) + ): + num_pax = sum(filter(None, [num_tourist, num_business, num_first_class])) + + # only FLOPS cares about seat class or specific cargo categories + if mass_method == LegacyCode.FLOPS: + if num_first_class is not None: + inputs.set_val(Aircraft.CrewPayload.NUM_FIRST_CLASS, num_first_class) + if num_business is not None: + inputs.set_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS, num_business) + if num_tourist is not None: + inputs.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, num_tourist) + + if wing_cargo is not None: + inputs.set_val(Aircraft.CrewPayload.WING_CARGO, wing_cargo, 'lbm') + if misc_cargo is not None: + inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, misc_cargo, 'lbm') + else: + warnings.warn( + 'Off-design functionality is in beta for GASP-mass based aircraft. Please manually ' + 'verify your results.' + ) + + if num_pax is not None: + inputs.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, num_pax) + if cargo_mass is not None: + inputs.set_val(Aircraft.CrewPayload.CARGO_MASS, cargo_mass, 'lbm') + + # NOTE once load_inputs is run, phase info details are stored in prob.model.configurator, + # meaning any phase_info changes that happen after load inputs is ignored + + if problem_type is ProblemType.ALTERNATE: + # Set mission range, aviary will calculate required fuel + if mission_range is None: + if verbosity >= Verbosity.VERBOSE: + warnings.warn( + 'Alternate problem type requested with no specified range. Using design ' + 'mission range for the off-design mission.' + ) + mission_range = self.get_val(Mission.Summary.RANGE, units='NM')[0] + + phase_info['post_mission']['target_range'] = ( + mission_range, + 'nmi', + ) + + # reset the AviaryProblem to run the new mission + off_design_prob.load_inputs(inputs, phase_info, verbosity=verbosity) + + # Update inputs that are specific to problem type + # Some Alternate problem changes had to happen before load_inputs, all fallout problem + # changes must come after load_inputs + if problem_type is ProblemType.ALTERNATE: + off_design_prob.aviary_inputs.set_val(Mission.Summary.RANGE, mission_range, units='NM') + # set initial guess for Mission.Summary.GROSS_MASS to help optimizer with new design + # variable bounds. + if mission_gross_mass is None: + mission_gross_mass = off_design_prob.aviary_inputs.get_val( + Mission.Design.GROSS_MASS, 'lbm' + ) + off_design_prob.aviary_inputs.set_val( + Mission.Summary.GROSS_MASS, mission_gross_mass * 0.9, units='lbm' + ) + + elif problem_type is ProblemType.FALLOUT: + # Set mission fuel and calculate gross weight, aviary will calculate range + if mission_gross_mass is None: + if verbosity >= Verbosity.VERBOSE: + warnings.warn( + 'Fallout problem type requested with no specified gross mass. Using design ' + 'takeoff gross mass for the off-design mission.' + ) + mission_gross_mass = self.get_val(Mission.Design.GROSS_MASS, units='lbm')[0] + + off_design_prob.aviary_inputs.set_val( + Mission.Summary.GROSS_MASS, mission_gross_mass, units='lbm' + ) + + off_design_prob.check_and_preprocess_inputs(verbosity=verbosity) + # off_design_prob.add_pre_mission_systems(verbosity=verbosity) + # off_design_prob.add_phases(verbosity=verbosity) + # off_design_prob.add_post_mission_systems(verbosity=verbosity) + # off_design_prob.link_phases(verbosity=verbosity) + off_design_prob.build_model(verbosity=verbosity) + + if optimizer is None: + try: + optimizer = self.driver.options['optimizer'] + except KeyError: + optimizer = None + off_design_prob.add_driver(optimizer, verbosity=verbosity) + off_design_prob.add_design_variables(verbosity=verbosity) + + # Handle edge case for payload-range diagrams + # Select which cargo variable makes the most sense to float, and then set a tolerance + # based on rough guesses on what is sufficient to get the problem to converge without + # setting design variable bounds too large + if fill_cargo: + # GASP cargo mass is an input, can directly use as control variable + if mass_method is GASP: + control_var = Aircraft.CrewPayload.CARGO_MASS + val = cargo_mass + tol = 1.05 + # FLOPS cargo mass is an output, not valid for control variable. Pick control var. + else: + # See if misc_cargo is being used, float that as a backup + if misc_cargo is None or misc_cargo == 0: + # We aren't using cargo_mass OR misc_mass - try wing cargo as last resort + if wing_cargo is None or wing_cargo == 0: + # We don't know enough about the aircraft to make any informed guesses. Use + # arbitrary values + control_var = Aircraft.CrewPayload.MISC_CARGO + val = self.get_val(Mission.Design.GROSS_MASS) + tol = 0.05 + inputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 0, 'lbm') + else: + control_var = Aircraft.CrewPayload.WING_CARGO + val = wing_cargo + tol = 1.1 + else: + control_var = Aircraft.CrewPayload.MISC_CARGO + val = misc_cargo + tol = 1.1 + + off_design_prob.model.add_design_var( + control_var, + lower=0, + upper=val * tol, + ref=val, + ) + + if fill_fuel: + off_design_prob.model.add_design_var( + Mission.Summary.GROSS_MASS, + lower=0, + upper=off_design_prob.aviary_inputs.get_val(Mission.Design.GROSS_MASS, units='lbm'), + ref=off_design_prob.aviary_inputs.get_val(Mission.Design.GROSS_MASS, units='lbm'), + ) + + off_design_prob.add_objective(verbosity=verbosity) + off_design_prob.setup(verbosity=verbosity) + off_design_prob.set_initial_guesses(verbosity=verbosity) + + off_design_prob.run_aviary_problem(verbosity=verbosity) + + return off_design_prob + + def run_payload_range(self, verbosity=None): """ - This function runs a fallout mission based on a sizing mission output. + This function runs Payload/Range analysis for the aircraft model. + + For an aircraft model that has been sized with a mission has has successfully converged, + this function will adjust the given phase information, assuming that there is a phase named + 'cruise' and elongates the duration bounds to allow the optimizer + to converge for the max economic and ferry missions. Parameters ---------- - run_mission : bool - Flag to determine whether to run the mission before returning the problem object. - json_filename : str - Name of the file that the sizing mission has been saved to. - mission_mass : float, optional - Takeoff mass for the fallout mission. - payload_mass : float, optional - Mass of the payload for the mission. - phase_info : dict, optional - Dictionary containing the phases and their required parameters. - verbosity : Verbosity or list, optional - If Verbosity.DEBUG, debug print options ['desvars','ln_cons','nl_cons','objs'] will be set. - If a list is provided, it will be used as the debug print options. + verbosity : Verbosity or int (optional) + Sets overriding verbosity to be used while running all payload-range points + + Returns + ------- + payload_range_problems : tuple + Tuple containing the off-design AviaryProblems for the max economic and ferry ranges + + TODO currently does not account for reserve fuel """ - if phase_info is None: - phase_info = self.phase_info - if mission_mass is None: - mission_mass = self.get_val(Mission.Design.GROSS_MASS) - if payload_mass is None: - if self.mission_method is HEIGHT_ENERGY: - payload_mass = self.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS) - elif self.mission_method is TWO_DEGREES_OF_FREEDOM: - payload_mass = self.get_val(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS) - - design_range = self.get_val(Mission.Design.RANGE) - optimizer = self.driver.options["optimizer"] - - prob_fallout = _load_off_design(json_filename, ProblemType.FALLOUT, phase_info, - payload_mass, design_range, mission_mass) - - prob_fallout.check_and_preprocess_inputs() - prob_fallout.add_pre_mission_systems() - prob_fallout.add_phases() - prob_fallout.add_post_mission_systems() - prob_fallout.link_phases() - prob_fallout.add_driver(optimizer, verbosity=verbosity) - prob_fallout.add_design_variables() - prob_fallout.add_objective() - prob_fallout.setup() - prob_fallout.set_initial_guesses() - if run_mission: - prob_fallout.run_aviary_problem(record_filename='fallout_problem_history.db') - return prob_fallout - - def save_sizing_to_json(self, json_filename='sizing_problem.json'): + # For off-design missions, provided verbosity will be used for all L2 method calls + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = self.verbosity # defaults to BRIEF + + if not self.result.success and verbosity > Verbosity.QUIET: + warnings.warn( + 'Payload Range Diagrams cannot be generated for unconverged Aviary problems.' + ) + return () + elif self.problem_type is ProblemType.MULTI_MISSION and verbosity > Verbosity.QUIET: + warnings.warn( + 'Payload Range Diagrams currently cannot be generated for aircraft designed ' + 'using multimission capability.' + ) + return () + + # Off-design missions are not tested with 2DOF missions. + mass_method = self.model.aviary_inputs.get_val(Settings.MASS_METHOD) + equations_of_motion = self.model.aviary_inputs.get_val(Settings.EQUATIONS_OF_MOTION) + if equations_of_motion is EquationsOfMotion.HEIGHT_ENERGY: + # make a copy of the phase_info to avoid modifying the original. + phase_info = self.model.mission_info.copy() + phase_info['pre_mission'] = self.model.pre_mission_info.copy() + phase_info['post_mission'] = self.model.post_mission_info.copy() + # This checks if the 'cruise' phase exists, then automatically extends duration bounds + # of the cruise stage to allow for the longer economic and ferry missions. + if phase_info['cruise']: + min_duration = phase_info['cruise']['user_options']['time_duration_bounds'][0][0] + max_duration = phase_info['cruise']['user_options']['time_duration_bounds'][0][1] + cruise_units = phase_info['cruise']['user_options']['time_duration_bounds'][1] + + phase_info['cruise']['user_options'].update( + {'time_duration_bounds': ((min_duration, 2 * max_duration), cruise_units)} + ) + + # TODO Verify that previously run point is actually max payload/fuel point, and if not + # run off-design mission for that point + # Point 1 is along the y axis (range=0) + payload_1 = float(self.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)[0]) + range_1 = 0 + fuel_1 = 0 + + # Point 2 (Design Range): sizing mission which is assumed to be the point of max + # payload + fuel on the payload and range diagram + payload_2 = payload_1 + + range_2 = float(self.get_val(Mission.Summary.RANGE)[0]) + gross_mass = float(self.get_val(Mission.Summary.GROSS_MASS)[0]) + # NOTE this operating mass is based on the previously run mission - assumed this is the + # design mission!! Includes cargo containers needed for design (max payload) + operating_mass = float(self.get_val(Mission.Summary.OPERATING_MASS)[0]) + fuel_capacity = float(self.get_val(Aircraft.Fuel.TOTAL_CAPACITY)[0]) + unusable_fuel = float(self.get_val(Aircraft.Fuel.UNUSABLE_FUEL_MASS)[0]) + max_payload = float(self.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)[0]) + + fuel_2 = self.get_val(Mission.Summary.FUEL_BURNED)[0] + + # Operating mass includes unusable fuel, don't double count + max_usable_fuel = fuel_capacity - unusable_fuel + + # An aircraft may be designed with fuel tank capacity that, if fully filled, would + # exceed MTOW. In that scenario, Max Economic Range and Ferry Range are the same, and + # the point only needs to be run once. + if operating_mass + max_usable_fuel < gross_mass: + # Point 3 (Max Economic Range): max fuel and remaining payload capacity + # Assume proportional decrease in all cargo types (including number of passengers) + # to make room for maximum fuel. Round pax count down to avoid loading over TOGW + + economic_mission_total_payload = gross_mass - operating_mass - max_usable_fuel + payload_frac = economic_mission_total_payload / max_payload + + # Calculates Different payload quantities + economic_mission_wing_cargo = ( + self.model.aviary_inputs.get_val(Aircraft.CrewPayload.WING_CARGO, 'lbm') + * payload_frac + ) + economic_mission_misc_cargo = ( + self.model.aviary_inputs.get_val(Aircraft.CrewPayload.MISC_CARGO, 'lbm') + * payload_frac + ) + economic_mission_num_first = int( + self.model.aviary_inputs.get_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) + * payload_frac + ) + economic_mission_num_bus = int( + self.model.aviary_inputs.get_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) + * payload_frac + ) + economic_mission_num_tourist = int( + self.model.aviary_inputs.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + * payload_frac + ) + + # Passenger number rounding and potentially cargo container mass changing means + # we don't know if we actually filled the aircraft to exactly TOGW yet. Need to use + # "fill_cargo" flag in off-design call + economic_range_prob = self.run_off_design_mission( + problem_type=ProblemType.FALLOUT, + phase_info=phase_info, + num_first_class=economic_mission_num_first, + num_business=economic_mission_num_bus, + num_tourist=economic_mission_num_tourist, + wing_cargo=economic_mission_wing_cargo, + misc_cargo=economic_mission_misc_cargo, + name=self._name + '_max_economic_range', + fill_cargo=True, + verbosity=verbosity, + ) + + # Pull the payload and range values from the fallout mission + payload_3 = float( + economic_range_prob.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS) + ) + + range_3 = float(economic_range_prob.get_val(Mission.Summary.RANGE)) + fuel_3 = economic_range_prob.get_val(Mission.Summary.FUEL_BURNED)[0] + + prob_3_skip = False + else: + prob_3_skip = True + # only fill fuel until hit TOGW + max_usable_fuel = gross_mass - operating_mass + + # Point 4 (Ferry Range): maximum fuel and 0 payload + # Total cargo mass is an input in GASP, but an output in FLOPS. Avoid overriding cargo + # mass to 0 if not using GASP + if mass_method is GASP: + ferry_cargo_mass = 0 + else: + ferry_cargo_mass = None + ferry_range_gross_mass = operating_mass + max_usable_fuel + ferry_range_prob = self.run_off_design_mission( + problem_type=ProblemType.FALLOUT, + phase_info=phase_info, + num_first_class=0, + num_business=0, + num_tourist=0, + wing_cargo=0, + misc_cargo=0, + cargo_mass=ferry_cargo_mass, + mission_gross_mass=ferry_range_gross_mass, + name=self._name + '_ferry_range', + fill_fuel=True, + verbosity=verbosity, + ) + + payload_4 = float(ferry_range_prob.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS)) + range_4 = float(ferry_range_prob.get_val(Mission.Summary.RANGE)) + fuel_4 = ferry_range_prob.get_val(Mission.Summary.FUEL_BURNED)[0] + + # if economic mission was skipped, economic_range_prob is the same as ferry_range_prob + if prob_3_skip: + economic_range_prob = ferry_range_prob + payload_3 = payload_4 + range_3 = range_4 + + # Check if fallout missions ran successfully before writing to csv file + # If both missions ran successfully, writes the payload/range data to a csv file + self.payload_range_data = payload_range_data = NamedValues() + if ferry_range_prob.result.success and economic_range_prob.result.success: + payload_range_data.set_val( + 'Mission Name', + ['Zero Fuel', 'Design Mission', 'Max Economic Mission', 'Ferry Mission'], + ) + payload_range_data.set_val( + 'Payload', [payload_1, payload_2, payload_3, payload_4], 'lbm' + ) + payload_range_data.set_val('Fuel', [fuel_1, fuel_2, fuel_3, fuel_4], 'lbm') + payload_range_data.set_val('Range', [range_1, range_2, range_3, range_4], 'NM') + + write_data_file( + Path(self.get_reports_dir(force=True)) / 'payload_range_data.csv', + payload_range_data, + ) + + # Prints the payload/range data to the console if verbosity is set to VERBOSE or DEBUG + if verbosity >= Verbosity.VERBOSE: + for item in payload_range_data: + print(f'{item[0]} ({item[1][1]}): {item[1][0]}') + + return (economic_range_prob, ferry_range_prob) + else: + warnings.warn( + 'One or both of the fallout missions did not run successfully; payload/range ' + 'diagram was not generated.' + ) + else: + warnings.warn( + 'Payload/range analysis is currently only supported for the energy equations of ' + 'motion.' + ) + + def save_results(self, json_filename='sizing_results.json'): """ This function saves an aviary problem object into a json file. Parameters ---------- - aviary_problem: OpenMDAO Aviary Problem + aviary_problem : AviaryProblem Aviary problem object optimized for the aircraft design/sizing mission. Assumed to contain aviary_inputs and Mission.Summary.GROSS_MASS - json_filename: string + json_filename : string User specified name and relative path of json file to save the data into. + save_to_reports : bool + Flag that sets where the results are saved - if True, the file is saved in the OpenMDAO + reports directory. If False, the file is saved to the current working directory. """ - aviary_input_list = [] with open(json_filename, 'w') as jsonfile: # Loop through aviary input datastructure and create a list - for data in self.aviary_inputs: + for data in self.model.aviary_inputs: (name, (value, units)) = data type_value = type(value) # Get the gross mass value from the sizing problem and add it to input list if name == Mission.Summary.GROSS_MASS or name == Mission.Design.GROSS_MASS: Mission_Summary_GROSS_MASS_val = self.get_val( - Mission.Summary.GROSS_MASS, units=units) + Mission.Summary.GROSS_MASS, units=units + ) Mission_Summary_GROSS_MASS_val_list = Mission_Summary_GROSS_MASS_val.tolist() value = Mission_Summary_GROSS_MASS_val_list[0] @@ -2583,413 +1787,226 @@ def save_sizing_to_json(self, json_filename='sizing_problem.json'): # int, bool, float doesn't need anything special # Convert numpy arrays to lists - if type_value == np.ndarray: + if type_value is np.ndarray: value = value.tolist() - # Lists are fine except if they contain enums - if type_value == list: - if isinstance(value[0], enum.Enum): + # Lists are fine except if they contain enums or Paths + if type_value is list: + if isinstance(value[0], Enum): for i in range(len(value)): - value[i] = str([value[i]]) + value[i] = value[i].name + elif isinstance(value[0], Path): + for i in range(len(value)): + value[i] = str(value[i]) - # Enums need converting to a string - if isinstance(value, enum.Enum): - value = str([value]) + # Enums and Paths need converting to a string + if isinstance(value, Enum): + value = value.name + elif isinstance(value, Path): + value = str(value) # Append the data to the list aviary_input_list.append([name, value, units, str(type_value)]) + if Mission.Design.GROSS_MASS not in self.model.aviary_inputs: + aviary_input_list.append( + [ + Mission.Design.GROSS_MASS, + self.get_val(Mission.Design.GROSS_MASS, 'lbm')[0], + 'lbm', + str(float), + ] + ) + # Write the list to a json file - json.dump(aviary_input_list, jsonfile, sort_keys=True, - indent=4, ensure_ascii=False) + json.dump( + aviary_input_list, + jsonfile, + sort_keys=True, + indent=4, + ensure_ascii=False, + ) jsonfile.close() def _add_hybrid_objective(self, phase_info): phases = list(phase_info.keys()) - takeoff_mass = self.aviary_inputs.get_val( - Mission.Design.GROSS_MASS, units='lbm') + takeoff_mass = self.model.aviary_inputs.get_val(Mission.Design.GROSS_MASS, units='lbm') - obj_comp = om.ExecComp(f"obj = -final_mass / {takeoff_mass} + final_time / 5.", - final_mass={"units": "lbm"}, - final_time={"units": "h"}) - self.model.add_subsystem("obj_comp", obj_comp) + obj_comp = om.ExecComp( + f'obj = -final_mass / {takeoff_mass} + final_time / 5.', + final_mass={'units': 'lbm'}, + final_time={'units': 'h'}, + ) + self.model.add_subsystem('obj_comp', obj_comp) final_phase_name = phases[-1] - self.model.connect(f"traj.{final_phase_name}.timeseries.mass", - "obj_comp.final_mass", src_indices=[-1]) - self.model.connect(f"traj.{final_phase_name}.timeseries.time", - "obj_comp.final_time", src_indices=[-1]) - - def _add_vrotate_comp(self): - self.model.add_subsystem("vrot_comp", VRotateComp()) - self.model.connect('traj.groundroll.states:mass', - 'vrot_comp.mass', src_indices=om.slicer[0, ...]) - - vrot_eq_comp = self.model.add_subsystem("vrot_eq_comp", om.EQConstraintComp()) - vrot_eq_comp.add_eq_output( - "v_rotate_error", eq_units="kn", lhs_name="v_rot_computed", - rhs_name="groundroll_v_final", add_constraint=True) - - self.model.connect('vrot_comp.Vrot', 'vrot_eq_comp.v_rot_computed') self.model.connect( - 'traj.groundroll.timeseries.velocity', 'vrot_eq_comp.groundroll_v_final', - src_indices=om.slicer[-1, ...]) + f'traj.{final_phase_name}.timeseries.mass', + 'obj_comp.final_mass', + src_indices=[-1], + ) + self.model.connect( + f'traj.{final_phase_name}.timeseries.time', + 'obj_comp.final_time', + src_indices=[-1], + ) def _save_to_csv_file(self, filename): with open(filename, 'w', newline='') as csvfile: fieldnames = ['name', 'value', 'units'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) - for name, value_units in sorted(self.aviary_inputs): + for name, value_units in sorted(self.model.aviary_inputs): value, units = value_units writer.writerow({'name': name, 'value': value, 'units': units}) - def _get_all_subsystems(self, external_subsystems=None): - all_subsystems = [] - if external_subsystems is None: - all_subsystems.extend(self.pre_mission_info['external_subsystems']) - else: - all_subsystems.extend(external_subsystems) - - all_subsystems.append(self.core_subsystems['aerodynamics']) - all_subsystems.append(self.core_subsystems['propulsion']) - - return all_subsystems - - def _add_height_energy_landing_systems(self): - landing_options = Landing( - ref_wing_area=self.aviary_inputs.get_val( - Aircraft.Wing.AREA, units='ft**2'), - Cl_max_ldg=self.aviary_inputs.get_val( - Mission.Landing.LIFT_COEFFICIENT_MAX) # no units - ) - - landing = landing_options.build_phase(False) - self.model.add_subsystem( - 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['mission:*']) - - last_flight_phase_name = list(self.phase_info.keys())[-1] - control_type_string = 'control_values' - if self.phase_info[last_flight_phase_name]['user_options'].get( - 'use_polynomial_control', True): - if not use_new_dymos_syntax: - control_type_string = 'polynomial_control_values' - - last_regular_phase = self.regular_phases[-1] - self.model.connect(f'traj.{last_regular_phase}.states:mass', - Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) - self.model.connect(f'traj.{last_regular_phase}.{control_type_string}:altitude', - Mission.Landing.INITIAL_ALTITUDE, - src_indices=[0]) - - def _add_post_mission_takeoff_systems(self): - first_flight_phase_name = list(self.phase_info.keys())[0] - connect_takeoff_to_climb = not self.phase_info[first_flight_phase_name][ - 'user_options'].get('add_initial_mass_constraint', True) - - if connect_takeoff_to_climb: - self.model.connect(Mission.Takeoff.FINAL_MASS, - f'traj.{first_flight_phase_name}.initial_states:mass') - self.model.connect(Mission.Takeoff.GROUND_DISTANCE, - f'traj.{first_flight_phase_name}.initial_states:distance') - - control_type_string = 'control_values' - if self.phase_info[first_flight_phase_name]['user_options'].get( - 'use_polynomial_control', True): - if not use_new_dymos_syntax: - control_type_string = 'polynomial_control_values' - - if self.phase_info[first_flight_phase_name]['user_options'].get( - 'optimize_mach', False): - # Create an ExecComp to compute the difference in mach - mach_diff_comp = om.ExecComp( - 'mach_resid_for_connecting_takeoff = final_mach - initial_mach') - self.model.add_subsystem('mach_diff_comp', mach_diff_comp) - - # Connect the inputs to the mach difference component - self.model.connect(Mission.Takeoff.FINAL_MACH, - 'mach_diff_comp.final_mach') - self.model.connect( - f'traj.{first_flight_phase_name}.{control_type_string}:mach', - 'mach_diff_comp.initial_mach', src_indices=[0]) - - # Add constraint for mach difference - self.model.add_constraint( - 'mach_diff_comp.mach_resid_for_connecting_takeoff', equals=0.0) - - if self.phase_info[first_flight_phase_name]['user_options'].get( - 'optimize_altitude', False): - # Similar steps for altitude difference - alt_diff_comp = om.ExecComp( - 'altitude_resid_for_connecting_takeoff = final_altitude - initial_altitude', - units='ft') - self.model.add_subsystem('alt_diff_comp', alt_diff_comp) - - self.model.connect(Mission.Takeoff.FINAL_ALTITUDE, - 'alt_diff_comp.final_altitude') - self.model.connect( - f'traj.{first_flight_phase_name}.{control_type_string}:altitude', - 'alt_diff_comp.initial_altitude', src_indices=[0]) - - self.model.add_constraint( - 'alt_diff_comp.altitude_resid_for_connecting_takeoff', equals=0.0) - - def _add_two_dof_landing_systems(self): - self.model.add_subsystem( - "landing", - LandingSegment( - **(self.ode_args)), - promotes_inputs=['aircraft:*', 'mission:*', - (Dynamic.Mission.MASS, Mission.Landing.TOUCHDOWN_MASS)], - promotes_outputs=['mission:*'], - ) - self.model.connect( - 'pre_mission.interference_independent_of_shielded_area', - 'landing.interference_independent_of_shielded_area') - self.model.connect( - 'pre_mission.drag_loss_due_to_shielded_wing_area', - 'landing.drag_loss_due_to_shielded_wing_area') - - def _add_objectives(self): - "add objectives and some constraints" - self.model.add_subsystem( - "fuel_obj", - om.ExecComp( - "reg_objective = overall_fuel/10000 + ascent_duration/30.", - reg_objective={"val": 0.0, "units": "unitless"}, - ascent_duration={"units": "s", "shape": 1}, - overall_fuel={"units": "lbm"}, - ), - promotes_inputs=[ - ("ascent_duration", Mission.Takeoff.ASCENT_DURATION), - ("overall_fuel", Mission.Summary.TOTAL_FUEL_MASS), - ], - promotes_outputs=[("reg_objective", Mission.Objectives.FUEL)], - ) - - self.model.add_subsystem( - "range_obj", - om.ExecComp( - "reg_objective = -actual_range/1000 + ascent_duration/30.", - reg_objective={"val": 0.0, "units": "unitless"}, - ascent_duration={"units": "s", "shape": 1}, - actual_range={ - "val": self.target_range, "units": "NM"}, - ), - promotes_inputs=[ - "actual_range", - ("ascent_duration", Mission.Takeoff.ASCENT_DURATION), - ], - promotes_outputs=[("reg_objective", Mission.Objectives.RANGE)], - ) - - if self.analysis_scheme is AnalysisScheme.COLLOCATION: - if self.mission_method is TWO_DEGREES_OF_FREEDOM: - ascent_phase = getattr(self.traj.phases, 'ascent') - ascent_tx = ascent_phase.options["transcription"] - ascent_num_nodes = ascent_tx.grid_data.num_nodes - self.model.add_subsystem( - "h_fit", - PolynomialFit(N_cp=ascent_num_nodes), - promotes_inputs=["t_init_gear", "t_init_flaps"], - ) - - self.model.add_subsystem( - "range_constraint", - om.ExecComp( - "range_resid = target_range - actual_range", - target_range={"val": self.target_range, "units": "NM"}, - actual_range={"val": self.target_range, "units": "NM"}, - range_resid={"val": 30, "units": "NM"}, - ), - promotes_inputs=[ - "actual_range", - ("target_range", Mission.Summary.RANGE), - ], - promotes_outputs=[ - ("range_resid", Mission.Constraints.RANGE_RESIDUAL)], - ) - def _add_fuel_reserve_component(self, post_mission=True, - reserves_name=Mission.Design.RESERVE_FUEL): - if post_mission: - reserve_calc_location = self.post_mission - else: - reserve_calc_location = self.model - - RESERVE_FUEL_FRACTION = self.aviary_inputs.get_val( - Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless') - if RESERVE_FUEL_FRACTION != 0: - reserve_fuel_frac = om.ExecComp( - 'reserve_fuel_frac_mass = reserve_fuel_fraction * (takeoff_mass - final_mass)', - reserve_fuel_frac_mass={"units": "lbm"}, - reserve_fuel_fraction={"units": "unitless", - "val": RESERVE_FUEL_FRACTION}, - final_mass={"units": "lbm"}, - takeoff_mass={"units": "lbm"}) - - reserve_calc_location.add_subsystem( - "reserve_fuel_frac", reserve_fuel_frac, - promotes_inputs=[("takeoff_mass", Mission.Summary.GROSS_MASS), - ("final_mass", Mission.Landing.TOUCHDOWN_MASS), - ("reserve_fuel_fraction", Aircraft.Design. - RESERVE_FUEL_FRACTION)], - promotes_outputs=["reserve_fuel_frac_mass"]) - - RESERVE_FUEL_ADDITIONAL = self.aviary_inputs.get_val( - Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm') - reserve_fuel = om.ExecComp('reserve_fuel = reserve_fuel_frac_mass + reserve_fuel_additional + reserve_fuel_burned', - reserve_fuel={"units": "lbm", 'shape': 1}, - reserve_fuel_frac_mass={"units": "lbm", "val": 0}, - reserve_fuel_additional={ - "units": "lbm", "val": RESERVE_FUEL_ADDITIONAL}, - reserve_fuel_burned={"units": "lbm", "val": 0}) - - reserve_calc_location.add_subsystem("reserve_fuel", reserve_fuel, - promotes_inputs=["reserve_fuel_frac_mass", - ("reserve_fuel_additional", - Aircraft.Design.RESERVE_FUEL_ADDITIONAL), - ("reserve_fuel_burned", - Mission.Summary.RESERVE_FUEL_BURNED)], - promotes_outputs=[ - ("reserve_fuel", reserves_name)] - ) - - -def _read_sizing_json(aviary_problem, json_filename): +def _read_sizing_json(json_filename, meta_data, verbosity=Verbosity.BRIEF): """ - This function reads in an aviary problem object from a json file. + This function reads in saved results from a json file. Parameters ---------- - aviary_problem: OpenMDAO Aviary Problem - Aviary problem object optimized for the aircraft design/sizing mission. - Assumed to contain aviary_inputs and Mission.Summary.GROSS_MASS - json_filename: string - User specified name and relative path of json file to save the data into + json_filename: str, Path + json file to load the data from + meta_data: dict + Variable metadata that will be used to load file data Returns - ---------- - Aviary Problem object with updated input values from json file - + ------- + AviaryValues object with updated input values from json file """ + aviary_inputs = AviaryValues() + # load saved input list from json file with open(json_filename) as json_data_file: loaded_aviary_input_list = json.load(json_data_file) json_data_file.close() # Loop over input list and assign aviary problem input values - counter = 0 # list index tracker for inputs in loaded_aviary_input_list: [var_name, var_values, var_units, var_type] = inputs - # Initialize some flags to idetify arrays and enums - is_array = False + # Initialize some flags to identify enums is_enum = False - if var_type == "": - is_array = True - - elif var_type == "": + if var_type == "": # check if the list contains enums for i in range(len(var_values)): if isinstance(var_values[i], str): - if var_values[i].find("<") != -1: + if var_values[i].find('<') != -1: # Found a list of enums: set the flag is_enum = True # Manipulate the string to find the value tmp_var_values = var_values[i].split(':')[-1] - var_values[i] = tmp_var_values.replace(">", "").replace( - "]", "").replace("'", "").replace(" ", "") + var_values[i] = ( + tmp_var_values.replace('>', '') + .replace('<', '') + .replace(']', '') + .replace("'", '') + .replace(' ', '') + ) if is_enum: var_values = convert_strings_to_data(var_values) - else: - var_values = [var_values] - - elif var_type.find("", "").replace( - "]", "").replace("'", "").replace(" ", "") + var_values = ( + tmp_var_values.replace('>', '') + .replace('<', '') + .replace(']', '') + .replace("'", '') + .replace(' ', '') + ) var_values = convert_strings_to_data([var_values]) - else: - # values are expected to be parsed as a list to set_value function - var_values = [var_values] - # Check if the variable is in meta data - if var_name in BaseMetaData.keys(): + if var_name in meta_data.keys(): try: - aviary_problem.aviary_inputs = set_value( - var_name, var_values, aviary_problem.aviary_inputs, units=var_units, - is_array=is_array, meta_data=BaseMetaData) - except: - # Print helpful error - print("FAILURE: list_num = ", counter, "Input String = ", inputs, - "Attempted to set_value(", var_name, ",", var_values, ",", var_units, ")") + aviary_inputs.set_val(var_name, var_values, units=var_units, meta_data=meta_data) + + except BaseException: + if verbosity >= Verbosity.VERBOSE: + warnings.warn( + f'Could not add item in json output to AviaryValues: input string = ' + f'{inputs}, attempted to set_value({var_name}, {var_values}, {var_units}). ' + 'This variable was skipped.' + ) else: # Not in the MetaData - print("Name not found in MetaData: list_num =", counter, "Input String =", - inputs, "Attempted set_value(", var_name, ",", var_values, ",", var_units, ")") + if verbosity >= Verbosity.VERBOSE: + warnings.warn( + f'While reading json output, item was not found in MetaData: {inputs}. This ' + 'variable was skipped.' + ) - counter = counter + 1 # increment index tracker - return aviary_problem + return aviary_inputs -def _load_off_design(json_filename, ProblemType, phase_info, - payload, mission_range, mission_gross_mass): +def reload_aviary_problem( + filename, phase_info=None, metadata=BaseMetaData.copy(), verbosity=Verbosity.QUIET +): """ - This function loads a sized aircraft, and sets up an aviary problem - for a specified off design mission. + Loads a previously sized Aviary model and returns an AviaryProblem for that model. Parameters ---------- - json_filename: string + filename : str, Path User specified name and relative path of json file containing the sized aircraft data - ProblemType: enum - Alternate or Fallout. Alternate requires mission_range input and - Fallout requires mission_fuel input - phase_info: phase_info dictionary for off design mission - payload: float - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS - mission_range float - Mission.Summary.RANGE 'NM' - mission_gross_mass float - Mission.Summary.GROSS_MASS 'lbm' + + metadata : dict (optional) + Custom metadata if needed to read all variables present in the json output file + + verbosity : Verbosity, int (optional) + Controls level of terminal output for function call Returns - ---------- - Aviary Problem object with completed load_inputs() for specified off design mission + ------- + Aviary Problem object with filled aviary_inputs. To use this problem for anything other than + running off-design missions, then the full level 2 interface should be used. "load_inputs()" + can be skipped as the "aviary_inputs" attribute is prefilled here. """ - + # warning if default is used # Initialize a new aviary problem and aviary_input data structure prob = AviaryProblem() - prob.aviary_inputs = AviaryValues() - prob = _read_sizing_json(prob, json_filename) + filename = get_path(filename) + + aviary_inputs = _read_sizing_json(filename, metadata, verbosity) + + prob.load_inputs(aviary_inputs, phase_info, verbosity=verbosity) + + prob.check_and_preprocess_inputs(verbosity=verbosity) + + # Add Systems + prob.add_pre_mission_systems(verbosity=verbosity) + + prob.add_phases(verbosity=verbosity) + + prob.add_post_mission_systems(verbosity=verbosity) + + # Link phases and variables + prob.link_phases(verbosity=verbosity) + + prob.add_driver(verbosity=verbosity) + + prob.add_design_variables(verbosity=verbosity) - # Update problem type - prob.problem_type = ProblemType - prob.aviary_inputs.set_val('settings:problem_type', ProblemType, units='unitless') + # Load optimization problem formulation + # Detail which variables the optimizer can control + prob.add_objective(verbosity=verbosity) - # Set Payload - prob.aviary_inputs.set_val( - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, payload, units='lbm') + prob.setup(verbosity=verbosity) - if ProblemType == ProblemType.ALTERNATE: - # Set mission range, aviary will calculate required fuel - prob.aviary_inputs.set_val(Mission.Design.RANGE, mission_range, units='NM') + prob.final_setup() - elif ProblemType == ProblemType.FALLOUT: - # Set mission fuel and calculate gross weight, aviary will calculate range - prob.aviary_inputs.set_val(Mission.Summary.GROSS_MASS, - mission_gross_mass, units='lbm') + # some variables are normally in the problem instead, so add them there too + prob.set_val( + Mission.Summary.GROSS_MASS, aviary_inputs.get_val(Mission.Summary.GROSS_MASS, 'lbm'), 'lbm' + ) - # Load inputs - prob.load_inputs(prob.aviary_inputs, phase_info) return prob diff --git a/aviary/interface/plot_drag_polar.py b/aviary/interface/plot_drag_polar.py index dccb3af432..1bf438ef9d 100644 --- a/aviary/interface/plot_drag_polar.py +++ b/aviary/interface/plot_drag_polar.py @@ -1,37 +1,39 @@ -import numpy as np -import matplotlib.cm as cm -import matplotlib.pyplot as plt -from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk) import tkinter as tk -from tkinter import Label, Button, StringVar, filedialog, messagebox +from tkinter import Button, Label, StringVar, filedialog, messagebox from tkinter.ttk import Combobox + +import matplotlib.cm as cm +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk + import aviary.api as av from aviary.utils.functions import get_path def plot_drag_polar(input_file=None): - """ - Plot drag polar - """ + """Plot drag polar.""" if input_file is None: - input_file = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")]) + input_file = filedialog.askopenfilename(filetypes=[('CSV files', '*.csv')]) if not input_file: - messagebox.showerror( - "Error", "No file selected") + messagebox.showerror('Error', 'No file selected') exit() return try: input_path = get_path(input_file) - polar_data = av.read_data_file(input_path, aliases={ - 'altitude': 'altitude', - 'mach_number': 'mach_number', - 'alpha': 'angle_of_attack', - 'CL': 'lift_coefficient', - 'CD': 'total_drag_coefficient' - }) + polar_data, _, _ = av.read_data_file( + input_path, + aliases={ + 'altitude': 'altitude', + 'mach_number': 'mach_number', + 'alpha': 'angle_of_attack', + 'CL': 'lift_coefficient', + 'CD': 'total_drag_coefficient', + }, + ) except Exception as e: - messagebox.showerror("Error", f"Failed to read the file: {str(e)}") + messagebox.showerror('Error', f'Failed to read the file: {str(e)}') return mach = polar_data.get_val('mach_number') @@ -70,13 +72,11 @@ def update_plot(): ax.clear() if fix_variable == 'Mach': - indices = mach == fix_value fixed_values = altitude_values fixed_label = 'Altitude' else: - index = altitude == fix_value fixed_values = mach_values fixed_label = 'Mach' @@ -111,7 +111,7 @@ def update_plot(): x_val = alpha elif x_var == 'CL/CD': - x_val = np.array(CL)/np.array(CD) + x_val = np.array(CL) / np.array(CD) if y_var == 'CD': y_val = CD @@ -123,7 +123,7 @@ def update_plot(): y_val = alpha elif y_var == 'CL/CD': - y_val = np.array(CL)/np.array(CD) + y_val = np.array(CL) / np.array(CD) plot_polar(ax, x_val, y_val, color=colors[i], label=f'{fixed_label} {val}') @@ -146,36 +146,39 @@ def update_fix_value_combobox(*args): set_x_var = StringVar(value='CD') - set_x_label = Label(master=window, text="x-axis") + set_x_label = Label(master=window, text='x-axis') set_x_label.pack(side='left', padx=5, pady=5) - set_x_combobox = Combobox(master=window, textvariable=set_x_var, values=[ - 'CD', 'CL', 'Alpha', 'CL/CD']) + set_x_combobox = Combobox( + master=window, textvariable=set_x_var, values=['CD', 'CL', 'Alpha', 'CL/CD'] + ) set_x_combobox.pack(side='left', padx=5, pady=5) set_y_var = StringVar(value='CL') - set_y_label = Label(master=window, text="y-axis") + set_y_label = Label(master=window, text='y-axis') set_y_label.pack(side='left', padx=5, pady=5) - set_y_combobox = Combobox(master=window, textvariable=set_y_var, values=[ - 'CL', 'CD', 'Alpha', 'CL/CD']) + set_y_combobox = Combobox( + master=window, textvariable=set_y_var, values=['CL', 'CD', 'Alpha', 'CL/CD'] + ) set_y_combobox.pack(side='left', padx=5, pady=5) fix_variable_var = StringVar(value='Mach') fix_value_var = StringVar(value=float(mach_values[0])) - fix_variable_label = Label(master=window, text="Fix Variable:") + fix_variable_label = Label(master=window, text='Fix Variable:') fix_variable_label.pack(side='left', padx=5, pady=5) fix_variable_combobox = Combobox( - master=window, textvariable=fix_variable_var, values=['Mach', 'Altitude']) + master=window, textvariable=fix_variable_var, values=['Mach', 'Altitude'] + ) fix_variable_combobox.pack(side='left', padx=5, pady=5) - fix_variable_combobox.bind("<>", update_fix_value_combobox) + fix_variable_combobox.bind('<>', update_fix_value_combobox) fix_variable_combobox.current(0) - fix_value_label = Label(master=window, text="Fix Value:") + fix_value_label = Label(master=window, text='Fix Value:') fix_value_label.pack(side='left', padx=5, pady=5) fix_value_combobox = Combobox(master=window, textvariable=fix_value_var) fix_value_combobox.pack(side='left', padx=5, pady=5) update_fix_value_combobox() - plot_button = Button(master=window, text="Plot", command=update_plot) + plot_button = Button(master=window, text='Plot', command=update_plot) plot_button.pack(side='right', padx=5, pady=5) window.mainloop() @@ -183,6 +186,7 @@ def update_fix_value_combobox(*args): def _setup_plot_drag_polar_parser(parser): """ Set up the command line options for the Model Building tool. + Parameters ---------- parser : argparse.ArgumentParser @@ -190,13 +194,13 @@ def _setup_plot_drag_polar_parser(parser): parser : argparse subparser The parser we're adding options to. """ - pass def _exec_plot_drag_polar(options, user_args): """ Run the Model Building tool. + Parameters ---------- options : argparse.Namespace @@ -207,5 +211,5 @@ def _exec_plot_drag_polar(options, user_args): plot_drag_polar() -if __name__ == "__main__": +if __name__ == '__main__': plot_drag_polar() diff --git a/aviary/interface/reports.py b/aviary/interface/reports.py index 9ae88f1797..479eaf8166 100644 --- a/aviary/interface/reports.py +++ b/aviary/interface/reports.py @@ -1,72 +1,96 @@ import datetime import json -from pathlib import Path import sys import time -import pandas as pd -import numpy as np +from pathlib import Path +import numpy as np +import pandas as pd from openmdao.utils.mpi import MPI from openmdao.utils.reports_system import register_report -from openmdao.visualization.tables.table_builder import generate_table -from aviary.interface.utils.markdown_utils import write_markdown_variable_table +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.interface.utils import write_markdown_variable_table from aviary.utils.named_values import NamedValues -from aviary.utils.functions import wrapped_convert_units +from aviary.utils.utils import wrapped_convert_units +from aviary.variable_info.enums import ProblemType def register_custom_reports(): """ Registers Aviary reports with OpenMDAO, so they are automatically generated and - added to the same reports folder as other default reports + added to the same reports folder as other default reports. """ # TODO top-level aircraft report? # TODO add flag to skip registering reports? # register per-subsystem report generation - register_report(name='subsystems', - func=subsystem_report, - desc='Generates reports for each subsystem builder in the ' - 'Aviary Problem', - class_name='AviaryProblem', - method='run_driver', - pre_or_post='post', - # **kwargs - ) - - register_report(name='mission', - func=mission_report, - desc='Generates report for mission results from Aviary problem', - class_name='AviaryProblem', - method='run_driver', - pre_or_post='post') - - register_report(name='timeseries_csv', - func=timeseries_csv, - desc='Generates an output .csv file for variables in the timeseries of the trajectory', - class_name='AviaryProblem', - method='run_driver', - pre_or_post='post') - - register_report(name='run_status', - func=run_status, - desc='Generates a report on the status of the run', - class_name='AviaryProblem', - method='run_driver', - pre_or_post='post', - ) - - -def run_status(prob): + register_report( + name='subsystems', + func=subsystem_report, + desc='Generates reports for each subsystem builder in the Aviary Problem', + class_name='AviaryProblem', + method='run_driver', + pre_or_post='post', + # **kwargs + ) + + register_report( + name='mission', + func=mission_report, + desc='Generates report for mission results from Aviary problem', + class_name='AviaryProblem', + method='run_driver', + pre_or_post='post', + ) + + register_report( + name='timeseries_csv', + func=timeseries_csv, + desc='Generates an output .csv file for variables in the timeseries of the trajectory', + class_name='AviaryProblem', + method='run_driver', + pre_or_post='post', + ) + + register_report( + name='run_status', + func=run_status, + desc='Generates a report on the status of the run', + class_name='AviaryProblem', + method='run_driver', + pre_or_post='post', + ) + + register_report( + name='sizing_results', + func=sizing_results, + desc='Generates an output file containing all variables in a completed sizing problem', + class_name='AviaryProblem', + method='run_driver', + pre_or_post='post', + ) + + register_report( + name='input_checks', + func=input_check_report, + desc='Generates a report on the aviary inputs', + class_name='AviaryProblem', + method='final_setup', + pre_or_post='post', + ) + + +def run_status(prob: AviaryProblem): """ - Creates a JSON file that containts high level overview of the run + Creates a JSON file that contains high level overview of the run. Parameters ---------- prob : AviaryProblem The AviaryProblem used to generate this report """ - if MPI and MPI.COMM_WORLD.rank != 0: + if MPI and prob.comm.rank != 0: return reports_folder = Path(prob.get_reports_dir()) @@ -74,12 +98,13 @@ def run_status(prob): runtime = prob.driver.result.runtime runtime_ms = (runtime * 1000.0) % 1000.0 - runtime_formatted = \ - f"{time.strftime('%H hours %M minutes %S seconds', time.gmtime(runtime))} " \ - f"{runtime_ms:.1f} milliseconds" + runtime_formatted = ( + f'{time.strftime("%H hours %M minutes %S seconds", time.gmtime(runtime))} ' + f'{runtime_ms:.1f} milliseconds' + ) t = datetime.datetime.now() - time_stamp = t.strftime("%Y-%m-%d %H:%M:%S %Z") + time_stamp = t.strftime('%Y-%m-%d %H:%M:%S %Z') status = {} status['Problem'] = prob._name @@ -97,10 +122,27 @@ def run_status(prob): print(file=f) # avoid 'no newline at end of file' message -def subsystem_report(prob, **kwargs): +def sizing_results(prob: AviaryProblem): + """ + Creates a JSON file that contains the variable set from a sizing problem. If the ProblemType run + was not sizing, no file is generated. + + Parameters + ---------- + prob : AviaryProblem + The AviaryProblem used to generate this report + """ + reports_folder = Path(prob.get_reports_dir()) + report_file = reports_folder / 'sizing_results.json' + + if prob.problem_type is ProblemType.SIZING: + prob.save_results(report_file) + + +def subsystem_report(prob: AviaryProblem, **kwargs): """ Loops through all subsystem builders in the AviaryProblem calls their write_report - method. All generated report files are placed in the "reports/subsystem_reports" folder + method. All generated report files are placed in the "reports/subsystem_reports" folder. Parameters ---------- @@ -110,50 +152,67 @@ def subsystem_report(prob, **kwargs): reports_folder = Path(prob.get_reports_dir() / 'subsystems') reports_folder.mkdir(exist_ok=True) + multi_mission = prob.problem_type == ProblemType.MULTI_MISSION + if multi_mission: + for _, model in prob.aviary_groups_dict.items(): + # TODO: We need to rewrite the reports to support multimission. + # For now, we are just running the reports on the first mission. + break + prob = model + else: + model = prob.model + # TODO external subsystems?? - core_subsystems = prob.core_subsystems + core_subsystems = model.core_subsystems # TODO: redo for multimissions for subsystem in core_subsystems.values(): subsystem.report(prob, reports_folder, **kwargs) -def mission_report(prob, **kwargs): +def mission_report(prob: AviaryProblem, **kwargs): """ - Creates a basic mission summary report that is placed in the "reports" folder + Creates a basic mission summary report that is placed in the "reports" folder. Parameters ---------- prob : AviaryProblem The AviaryProblem used to generate this report """ - def _get_phase_value(traj, phase, var_name, units, indices=None): + + def _get_phase_value(model, traj, phase, var_name, units, indices=None): try: - vals = prob.get_val(f"{traj}.{phase}.timeseries.{var_name}", - units=units, - indices=indices, - get_remote=True) + vals = model.get_val( + f'{traj}.{phase}.timeseries.{var_name}', + units=units, + indices=indices, + get_remote=True, + ) except KeyError: try: - vals = prob.get_val(f"{traj}.{phase}.{var_name}", - units=units, - indices=indices, - get_remote=True) + vals = model.get_val( + f'{traj}.{phase}.{var_name}', + units=units, + indices=indices, + get_remote=True, + ) # 2DOF breguet range cruise uses time integration to track mass except TypeError: - vals = prob.get_val(f"{traj}.{phase}.timeseries.time", - units=units, - indices=indices, - get_remote=True) + vals = model.get_val( + f'{traj}.{phase}.timeseries.time', + units=units, + indices=indices, + get_remote=True, + ) except KeyError: vals = None return vals - def _get_phase_diff(traj, phase, var_name, units, indices=[0, -1]): - vals = _get_phase_value(traj, phase, var_name, units, indices) + def _get_phase_diff(model, traj, phase, var_name, units, indices=[0, -1]): + vals = _get_phase_value(model, traj, phase, var_name, units, indices) if vals is not None: - diff = vals[-1]-vals[0] + diff = vals[-1] - vals[0] if isinstance(diff, np.ndarray): diff = diff[0] return diff @@ -163,61 +222,240 @@ def _get_phase_diff(traj, phase, var_name, units, indices=[0, -1]): reports_folder = Path(prob.get_reports_dir()) report_file = reports_folder / 'mission_summary.md' - # read per-phase data from trajectory - data = {} - for idx, phase in enumerate(prob.phase_info): - # TODO for traj in trajectories, currently assuming single one named "traj" - # TODO delta mass and fuel consumption need to be tracked separately - fuel_burn = _get_phase_diff('traj', phase, 'mass', 'lbm', [-1, 0]) - time = _get_phase_diff('traj', phase, 't', 'min') - range = _get_phase_diff('traj', phase, 'distance', 'nmi') - - # get initial values, first in traj - if idx == 0: - initial_mass = _get_phase_value('traj', phase, 'mass', 'lbm', 0)[0] - initial_time = _get_phase_value('traj', phase, 't', 'min', 0) - initial_range = _get_phase_value('traj', phase, 'distance', 'nmi', 0)[0] - - outputs = NamedValues() - # Fuel burn is negative of delta mass - outputs.set_val('Fuel Burn', fuel_burn, 'lbm') - outputs.set_val('Elapsed Time', time, 'min') - outputs.set_val('Ground Distance', range, 'nmi') - data[phase] = outputs - - # get final values, last in traj - final_mass = _get_phase_value('traj', phase, 'mass', 'lbm', -1)[0] - final_time = _get_phase_value('traj', phase, 't', 'min', -1) - final_range = _get_phase_value('traj', phase, 'distance', 'nmi', -1)[0] - - totals = NamedValues() - totals.set_val('Total Fuel Burn', initial_mass - final_mass, 'lbm') - totals.set_val('Total Time', final_time - initial_time, 'min') - totals.set_val('Total Ground Distance', final_range - initial_range, 'nmi') - - if MPI and MPI.COMM_WORLD.rank != 0: + multi_mission = prob.problem_type == ProblemType.MULTI_MISSION + if multi_mission: + models = prob.aviary_groups_dict + else: + models = {prob._name: prob.model} + + all_data = {} + all_totals = {} + for name, model in models.items(): + # read per-phase data from trajectory + data = {} + for idx, phase in enumerate(model.mission_info): # TODO: redo for multimissions + # TODO for traj in trajectories, currently assuming single one named "traj" + # TODO delta mass and fuel consumption need to be tracked separately + fuel_burn = _get_phase_diff(model, 'traj', phase, 'mass', 'lbm', [-1, 0]) + time = _get_phase_diff(model, 'traj', phase, 't', 'min') + range = _get_phase_diff(model, 'traj', phase, 'distance', 'nmi') + + # get initial values, first in traj + if idx == 0: + initial_mass = _get_phase_value(model, 'traj', phase, 'mass', 'lbm', 0)[0] + initial_time = _get_phase_value(model, 'traj', phase, 't', 'min', 0) + initial_range = _get_phase_value(model, 'traj', phase, 'distance', 'nmi', 0)[0] + + outputs = NamedValues() + # Fuel burn is negative of delta mass + outputs.set_val('Fuel Burn', fuel_burn, 'lbm') + outputs.set_val('Elapsed Time', time, 'min') + outputs.set_val('Ground Distance', range, 'nmi') + data[phase] = outputs + + # get final values, last in traj + final_mass = _get_phase_value(model, 'traj', phase, 'mass', 'lbm', -1)[0] + final_time = _get_phase_value(model, 'traj', phase, 't', 'min', -1) + final_range = _get_phase_value(model, 'traj', phase, 'distance', 'nmi', -1)[0] + + totals = NamedValues() + totals.set_val('Total Fuel Burn', initial_mass - final_mass, 'lbm') + + if multi_mission: + var_name = f'{name}.' + else: + var_name = '' + + totals.set_val( + 'Total Fuel Capacity', + prob.get_val(f'{var_name}aircraft:fuel:total_capacity', units='lbm')[0], + units='lbm', + ) + totals.set_val( + 'Excess Fuel Capacity', + prob.get_val(f'{var_name}mission:constraints:excess_fuel_capacity', units='lbm')[0], + units='lbm', + ) + totals.set_val('Total Time', final_time - initial_time, 'min') + totals.set_val('Total Ground Distance', final_range - initial_range, 'nmi') + + all_data[name] = data + all_totals[name] = totals + + if MPI and prob.comm.rank != 0: + # All collective calls are completed. We only output on rank 0. return with open(report_file, mode='w') as f: - f.write('# MISSION SUMMARY') - write_markdown_variable_table(f, totals, - ['Total Fuel Burn', - 'Total Time', - 'Total Ground Distance'], - {'Total Fuel Burn': {'units': 'lbm'}, - 'Total Time': {'units': 'min'}, - 'Total Ground Distance': {'units': 'nmi'}}) - - f.write('\n# MISSION SEGMENTS') - for phase in data: - f.write(f'\n## {phase}') - write_markdown_variable_table(f, data[phase], ['Fuel Burn', 'Elapsed Time', 'Ground Distance'], - {'Fuel Burn': {'units': 'lbm'}, - 'Elapsed Time': {'units': 'min'}, - 'Ground Distance': {'units': 'nmi'}}) - - -def timeseries_csv(prob, **kwargs): + for name, model in models.items(): + data = all_data[name] + totals = all_totals[name] + + if multi_mission: + f.write(f'\n\n\n# MULTIMISSION: {name}\n\n') + + f.write('# MISSION SUMMARY') + write_markdown_variable_table( + f, + totals, + [ + 'Total Fuel Burn', + 'Total Fuel Capacity', + 'Excess Fuel Capacity', + 'Total Time', + 'Total Ground Distance', + ], + { + 'Total Fuel Burn': {'units': 'lbm'}, + 'Total Fuel Capacity': {'units': 'lbm'}, + 'Excess Fuel Capacity': {'units': 'lbm'}, + 'Total Time': {'units': 'min'}, + 'Total Ground Distance': {'units': 'nmi'}, + }, + ) + + f.write('\n# MISSION SEGMENTS') + for phase in data: + f.write(f'\n## {phase}') + write_markdown_variable_table( + f, + data[phase], + ['Fuel Burn', 'Elapsed Time', 'Ground Distance'], + { + 'Fuel Burn': {'units': 'lbm'}, + 'Elapsed Time': {'units': 'min'}, + 'Ground Distance': {'units': 'nmi'}, + }, + ) + + +def input_check_report(prob: AviaryProblem, **kwargs): + """ + Creates a basic input checking report. + + This report informs the user which aviary inputs were not specified by the user. + + Parameters + ---------- + prob : AviaryProblem + The AviaryProblem used to generate this report + """ + reports_folder = Path(prob.get_reports_dir()) + report_file = reports_folder / 'input_checks.md' + + multi_mission = prob.problem_type == ProblemType.MULTI_MISSION + if multi_mission: + models = prob.aviary_groups_dict + else: + models = {prob._name: prob.model} + + # a change in OpenMDAO 3.38.1-dev adds a resolver in place of the prom2abs/abs2prom attributes + try: + resolver = prob.model._resolver + + def prom2abs(prom_name): + return resolver.absnames(prom_name, 'input') + + def abs2prom(abs_name): + return resolver.abs2prom(abs_name, 'input') + + except AttributeError: + + def prom2abs(prom_name): + return prob.model._var_allprocs_prom2abs_list['input'][prom_name] + + def abs2prom(abs_name): + return prob.model._var_allprocs_abs2prom['input'][abs_name] + + # Find all unconnected inputs. + all_ivc_abs = [k for k, v in prob.model._conn_abs_in2out.items() if 'ivc' in v] + all_ivc_prom = [abs2prom(v) for v in all_ivc_abs] + aviary_metadata = prob.meta_data + + bare_inputs = all_ivc_prom + for name, model in models.items(): + if multi_mission: + aviary_inputs = model.aviary_inputs + else: + aviary_inputs = prob.aviary_inputs + + bare_inputs = {v for v in bare_inputs if v not in aviary_inputs} + if multi_mission: + bare_inputs = {v for v in bare_inputs if v.lstrip(f'{name}.') not in aviary_inputs} + + bare_hierarchy_inputs = { + v + for v in bare_inputs + if v.startswith('mission:') + or v.startswith('aircraft:') + or '.mission:' in v + or '.aircraft:' in v + } + bare_local_inputs = bare_inputs - bare_hierarchy_inputs + + # There are no more collective calls, so we can exit. + if MPI and prob.comm.rank != 0: + return + + with open(report_file, mode='w') as f: + f.write('# Unspecified Hierarchy Variables\n') + f.write( + 'These aviary inputs are unspecified in aviary_inputs, and may be using default values ' + 'defined in the Aviary metadata.\n\n' + ) + + if bare_hierarchy_inputs: + f.write('| Name | Value | Units | Description | Absolute Paths\n') + f.write('| :- | :- | :- | :- | :- |\n') + + for var in sorted(bare_hierarchy_inputs): + metadata = aviary_metadata.get(var) + try: + units = metadata['units'] + except: + metadata = aviary_metadata.get(var.split('.')[-1]) + units = metadata['units'] + + val = prob.model.get_val(var, units=units) + desc = metadata['desc'] + abs_paths = prom2abs(var) + + f.write(f'| **{var}** | {val} | {units} | {desc} | {abs_paths}|\n') + + f.write('\n') + + else: + f.write('None\n') + + f.write('# Unspecified Local Variables\n') + f.write( + 'These local subsystem inputs are unconnected, and may be using default ' + 'values specified in the component.\n\n' + ) + + if bare_local_inputs: + f.write('| Name | Value | Units | Absolute Paths\n') + f.write('| :- | :- | :- | :- |\n') + + for var in sorted(bare_local_inputs): + # Filter out dymos internals. + if var.startswith('traj') and '.rhs_all.' not in var: + continue + + abs_paths = prom2abs(var) + val = prob.model.get_val(var) + meta = prob.model._var_allprocs_abs2meta['input'][abs_paths[0]] + units = meta['units'] + + f.write(f'| **{var}** | {val} | {units} | {abs_paths}|\n') + + f.write('\n\n') + + else: + f.write('None') + + +def timeseries_csv(prob: AviaryProblem, **kwargs): """ Generates a CSV file containing timeseries data for variables from an Aviary mission. @@ -237,22 +475,33 @@ def timeseries_csv(prob, **kwargs): The first row of the CSV file contains headers with variable names and units. Each subsequent row represents the mission outputs at a different time step. """ - timeseries_outputs = prob.model.list_outputs( - includes='*timeseries*', out_stream=None, return_format='dict', units=True) - phase_names = prob.model.traj._phases.keys() + multi_mission = prob.problem_type == ProblemType.MULTI_MISSION + if multi_mission: + for _, model in prob.aviary_groups_dict.items(): + # TODO: We need to rewrite this report to support multimission + # For now, just write the first mission's csv file. + break + else: + model = prob.model + + timeseries_outputs = model.list_outputs( + includes='*timeseries*', out_stream=None, return_format='dict', units=True + ) + phase_names = model.traj._phases.keys() # There are no more collective calls, so we can exit. - if MPI and MPI.COMM_WORLD.rank != 0: + if MPI and prob.comm.rank != 0: return - timeseries_outputs = {value['prom_name']: value for key, - value in timeseries_outputs.items()} + timeseries_outputs = {value['prom_name']: value for key, value in timeseries_outputs.items()} - timeseries_outputs = {key: value for key, - value in timeseries_outputs.items() if not key.endswith('_phase')} + timeseries_outputs = { + key: value for key, value in timeseries_outputs.items() if not key.endswith('_phase') + } - unique_variable_names = set([timeseries_output.split('.')[-1] - for timeseries_output in timeseries_outputs]) + unique_variable_names = set( + [timeseries_output.split('.')[-1] for timeseries_output in timeseries_outputs] + ) timeseries_data = {} for variable_name in unique_variable_names: @@ -265,7 +514,9 @@ def timeseries_csv(prob, **kwargs): if variable_str not in timeseries_outputs: Warning( - f'Variable {variable_str} not found in timeseries_outputs for phase {phase_name}.') + f'Variable {variable_str} not found in timeseries_outputs for phase ' + f'{phase_name}.' + ) val = np.zeros_like(timeseries_outputs[time_str]['val']) val[:] = np.nan if first: @@ -302,8 +553,10 @@ def timeseries_csv(prob, **kwargs): timeseries_data[variable_name]['shape'] = val_full_traj.shape # Create a DataFrame from timeseries_data - df_data = {variable_name: pd.Series(timeseries_data[variable_name]['val'].flatten()) - for variable_name in timeseries_data} + df_data = { + variable_name: pd.Series(timeseries_data[variable_name]['val'].flatten()) + for variable_name in timeseries_data + } df = pd.DataFrame(df_data) time_column = ['time'] # Isolate the 'time' column diff --git a/aviary/interface/aviary_logo_16.png b/aviary/interface/static/aviary_logo_16.png similarity index 100% rename from aviary/interface/aviary_logo_16.png rename to aviary/interface/static/aviary_logo_16.png diff --git a/aviary/interface/aviary_logo_32.png b/aviary/interface/static/aviary_logo_32.png similarity index 100% rename from aviary/interface/aviary_logo_32.png rename to aviary/interface/static/aviary_logo_32.png diff --git a/aviary/interface/dark_mode.png b/aviary/interface/static/dark_mode.png similarity index 100% rename from aviary/interface/dark_mode.png rename to aviary/interface/static/dark_mode.png diff --git a/aviary/interface/light_mode.png b/aviary/interface/static/light_mode.png similarity index 100% rename from aviary/interface/light_mode.png rename to aviary/interface/static/light_mode.png diff --git a/aviary/interface/mac_theme.png b/aviary/interface/static/mac_theme.png similarity index 100% rename from aviary/interface/mac_theme.png rename to aviary/interface/static/mac_theme.png diff --git a/aviary/interface/test/sizing_problem_for_test.json b/aviary/interface/test/sizing_results_for_test.json similarity index 75% rename from aviary/interface/test/sizing_problem_for_test.json rename to aviary/interface/test/sizing_results_for_test.json index 57eb1845ba..7d44bed7fb 100644 --- a/aviary/interface/test/sizing_problem_for_test.json +++ b/aviary/interface/test/sizing_results_for_test.json @@ -1,494 +1,4 @@ [ - [ - "aircraft:blended_wing_body_design:num_bays", - 0, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:mass_per_passenger", - 180, - "lbm", - "" - ], - [ - "aircraft:crew_and_payload:num_business_class", - 0, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_first_class", - 11, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_passengers", - 169, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_tourist_class", - 158, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:passenger_mass_with_bags", - 200, - "lbm", - "" - ], - [ - "aircraft:design:compute_htail_volume_coeff", - false, - "unitless", - "" - ], - [ - "aircraft:design:compute_vtail_volume_coeff", - false, - "unitless", - "" - ], - [ - "aircraft:design:part25_structural_category", - 3, - "unitless", - "" - ], - [ - "aircraft:design:reserve_fuel_additional", - 3000, - "lbm", - "" - ], - [ - "aircraft:design:reserve_fuel_fraction", - 0, - "unitless", - "" - ], - [ - "aircraft:design:smooth_mass_discontinuities", - false, - "unitless", - "" - ], - [ - "aircraft:design:ulf_calculated_from_maneuver", - false, - "unitless", - "" - ], - [ - "aircraft:design:use_alt_mass", - false, - "unitless", - "" - ], - [ - "aircraft:electrical:has_hybrid_system", - false, - "unitless", - "" - ], - [ - "aircraft:engine:compute_propeller_installation_loss", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:constant_fuel_consumption", - [ - 0.0 - ], - "lbm/h", - "" - ], - [ - "aircraft:engine:flight_idle_max_fraction", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:flight_idle_min_fraction", - [ - 0.08 - ], - "unitless", - "" - ], - [ - "aircraft:engine:flight_idle_thrust_fraction", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:fuel_flow_scaler_constant_term", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:fuel_flow_scaler_linear_term", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:generate_flight_idle", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:geopotential_alt", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:has_propellers", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:ignore_negative_thrust", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:interpolation_method", - [ - "slinear" - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_engines", - [ - 2 - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_fuselage_engines", - [ - 0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_propeller_blades", - [ - 0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_wing_engines", - [ - 2 - ], - "unitless", - "" - ], - [ - "aircraft:engine:scale_mass", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:scale_performance", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:subsonic_fuel_flow_scaler", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:supersonic_fuel_flow_scaler", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:type", - [ - "[]" - ], - "unitless", - "" - ], - [ - "aircraft:engine:use_propeller_map", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:shaft_power_design", - [ - 1.0 - ], - "kW", - "" - ], - [ - "aircraft:fins:num_fins", - 0, - "unitless", - "" - ], - [ - "aircraft:fuel:num_tanks", - 7, - "unitless", - "" - ], - [ - "aircraft:fuselage:aisle_width", - 24, - "inch", - "" - ], - [ - "aircraft:fuselage:military_cargo_floor", - false, - "unitless", - "" - ], - [ - "aircraft:fuselage:num_aisles", - 1, - "unitless", - "" - ], - [ - "aircraft:fuselage:num_fuselages", - 1, - "unitless", - "" - ], - [ - "aircraft:fuselage:num_seats_abreast", - 6, - "unitless", - "" - ], - [ - "aircraft:fuselage:seat_pitch", - 29, - "inch", - "" - ], - [ - "aircraft:fuselage:seat_width", - 20, - "inch", - "" - ], - [ - "aircraft:landing_gear:carrier_based", - false, - "unitless", - "" - ], - [ - "aircraft:landing_gear:drag_coefficient", - 0.0, - "unitless", - "" - ], - [ - "aircraft:landing_gear:fixed_gear", - true, - "unitless", - "" - ], - [ - "aircraft:strut:dimensional_location_specified", - true, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:num_tails", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:airfoil_technology", - 1.92669766647637, - "unitless", - "" - ], - [ - "aircraft:wing:choose_fold_location", - true, - "unitless", - "" - ], - [ - "aircraft:wing:detailed_wing", - false, - "unitless", - "" - ], - [ - "aircraft:wing:flap_type", - "[]", - "unitless", - "" - ], - [ - "aircraft:wing:fold_dimensional_location_specified", - false, - "unitless", - "" - ], - [ - "aircraft:wing:has_fold", - false, - "unitless", - "" - ], - [ - "aircraft:wing:has_strut", - false, - "unitless", - "" - ], - [ - "aircraft:wing:load_distribution_control", - 2, - "unitless", - "" - ], - [ - "aircraft:wing:loading_above_20", - true, - "unitless", - "" - ], - [ - "aircraft:wing:num_flap_segments", - 2, - "unitless", - "" - ], - [ - "aircraft:wing:num_integration_stations", - 50, - "unitless", - "" - ], - [ - "aircraft:wing:span_efficiency_reduction", - false, - "unitless", - "" - ], - [ - "mission:design:cruise_altitude", - 35000, - "ft", - "" - ], - [ - "mission:design:rate_of_climb_at_top_of_climb", - 0.0, - "ft/min", - "" - ], - [ - "mission:summary:fuel_flow_scaler", - 1, - "unitless", - "" - ], - [ - "mission:takeoff:angle_of_attack_runway", - 0.0, - "deg", - "" - ], - [ - "mission:takeoff:obstacle_height", - 35.0, - "ft", - "" - ], - [ - "mission:takeoff:thrust_incidence", - 0.0, - "deg", - "" - ], - [ - "mission:taxi:duration", - 0.167, - "h", - "" - ], - [ - "mission:taxi:mach", - 0.0001, - "unitless", - "" - ], - [ - "settings:verbosity", - "[]", - "unitless", - "" - ], [ "INGASP.JENGSZ", 4, @@ -515,21 +25,51 @@ ], [ "settings:problem_type", - "[]", + "SIZING", "unitless", "" ], [ - "aircraft:air_conditioning:mass_scaler", - 1, + "aircraft:crew_and_payload:design:num_passengers", + 169, "unitless", "" ], + [ + "aircraft:design:reserve_fuel_additional", + 3000.0, + "lbm", + "" + ], + [ + "aircraft:design:reserve_fuel_fraction", + 0.0, + "unitless", + "" + ], + [ + "mission:design:cruise_altitude", + 35000.0, + "ft", + "" + ], + [ + "aircraft:crew_and_payload:passenger_mass_with_bags", + 0.0, + "lbm", + "" + ], + [ + "aircraft:air_conditioning:mass_scaler", + 1.0, + "unitless", + "" + ], [ "aircraft:anti_icing:mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:apu:mass_scaler", @@ -545,51 +85,75 @@ ], [ "aircraft:canard:area", - 0, + 0.0, "ft**2", - "" + "" ], [ "aircraft:canard:aspect_ratio", - 0, + 0.0, "unitless", - "" + "" ], [ "aircraft:canard:thickness_to_chord", - 0, + 0.0, "unitless", - "" + "" ], [ "aircraft:crew_and_payload:baggage_mass_per_passenger", - 45, + 45.0, "lbm", - "" + "" ], [ "aircraft:crew_and_payload:cargo_container_mass_scaler", - 1, + 1.0, + "unitless", + "" + ], + [ + "aircraft:crew_and_payload:design:num_business_class", + 0, "unitless", "" ], [ - "aircraft:crew_and_payload:flight_crew_mass_scaler", - 1, + "aircraft:crew_and_payload:design:num_first_class", + 11, + "unitless", + "" + ], + [ + "aircraft:crew_and_payload:design:num_tourist_class", + 158, "unitless", "" ], + [ + "aircraft:crew_and_payload:flight_crew_mass_scaler", + 1.0, + "unitless", + "" + ], + [ + "aircraft:crew_and_payload:mass_per_passenger", + 180.0, + "lbm", + "" + ], [ "aircraft:crew_and_payload:misc_cargo", - 0, + 0.0, "lbm", - "" + "" ], [ "aircraft:crew_and_payload:non_flight_crew_mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:crew_and_payload:num_flight_attendants", @@ -611,27 +175,27 @@ ], [ "aircraft:crew_and_payload:passenger_service_mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:crew_and_payload:wing_cargo", - 0, + 0.0, "lbm", - "" + "" ], [ "aircraft:design:base_area", - 0, + 0.0, "ft**2", - "" + "" ], [ "aircraft:design:empty_mass_margin_scaler", - 0, + 0.0, "unitless", - "" + "" ], [ "aircraft:design:lift_dependent_drag_coeff_factor", @@ -641,21 +205,27 @@ ], [ "aircraft:design:touchdown_mass", - 152800, + 152800.0, "lbm", - "" + "" ], [ "aircraft:design:subsonic_drag_coeff_factor", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:design:supersonic_drag_coeff_factor", - 1, + 1.0, "unitless", - "" + "" + ], + [ + "aircraft:design:use_alt_mass", + false, + "unitless", + "" ], [ "aircraft:design:zero_lift_drag_coeff_factor", @@ -677,10 +247,90 @@ "unitless", "" ], + [ + "aircraft:engine:constant_fuel_consumption", + [ + 0.0 + ], + "lbm/h", + "" + ], [ "aircraft:engine:data_file", [ - "models/engines/turbofan_28k.deck" + "models/engines/turbofan_28k.csv" + ], + "unitless", + "" + ], + [ + "aircraft:engine:flight_idle_thrust_fraction", + [ + 0.0 + ], + "unitless", + "" + ], + [ + "aircraft:engine:flight_idle_max_fraction", + [ + 1.0 + ], + "unitless", + "" + ], + [ + "aircraft:engine:flight_idle_min_fraction", + [ + 0.08 + ], + "unitless", + "" + ], + [ + "aircraft:engine:fuel_flow_scaler_constant_term", + [ + 0.0 + ], + "unitless", + "" + ], + [ + "aircraft:engine:fuel_flow_scaler_linear_term", + [ + 0.0 + ], + "unitless", + "" + ], + [ + "aircraft:engine:generate_flight_idle", + [ + true + ], + "unitless", + "" + ], + [ + "aircraft:engine:geopotential_alt", + [ + false + ], + "unitless", + "" + ], + [ + "aircraft:engine:ignore_negative_thrust", + [ + false + ], + "unitless", + "" + ], + [ + "aircraft:engine:interpolation_method", + [ + "slinear" ], "unitless", "" @@ -701,10 +351,34 @@ "lbm", "" ], + [ + "aircraft:engine:num_engines", + [ + 2 + ], + "unitless", + "" + ], + [ + "aircraft:engine:num_fuselage_engines", + [ + 0 + ], + "unitless", + "" + ], + [ + "aircraft:engine:num_wing_engines", + [ + 2 + ], + "unitless", + "" + ], [ "aircraft:engine:reference_mass", [ - 7400 + 7400.0 ], "lbm", "" @@ -717,12 +391,52 @@ "lbf", "" ], + [ + "aircraft:engine:scale_factor", + [ + 1.0 + ], + "unitless", + "" + ], + [ + "aircraft:engine:scale_mass", + [ + true + ], + "unitless", + "" + ], + [ + "aircraft:engine:scale_performance", + [ + true + ], + "unitless", + "" + ], [ "aircraft:engine:scaled_sls_thrust", [ - 28928.1 + 28928.1 + ], + "lbf", + "" + ], + [ + "aircraft:engine:subsonic_fuel_flow_scaler", + [ + 1.0 + ], + "unitless", + "" + ], + [ + "aircraft:engine:supersonic_fuel_flow_scaler", + [ + 1.0 ], - "lbf", + "unitless", "" ], [ @@ -743,63 +457,69 @@ ], [ "aircraft:fins:area", - 0, + 0.0, "ft**2", - "" + "" ], [ "aircraft:fins:mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:fins:mass", - 0, + 0.0, "lbm", + "" + ], + [ + "aircraft:fins:num_fins", + 0, + "unitless", "" ], [ "aircraft:fins:taper_ratio", - 10, + 10.0, "unitless", - "" + "" ], [ "aircraft:fuel:auxiliary_fuel_capacity", - 0, + 0.0, "lbm", - "" - ], - [ - "aircraft:fuel:density_ratio", - 1, - "unitless", - "" + "" ], [ "aircraft:fuel:fuel_system_mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:fuel:fuselage_fuel_capacity", - 0, + 0.0, "lbm", + "" + ], + [ + "aircraft:fuel:num_tanks", + 7, + "unitless", "" ], [ "aircraft:fuel:total_capacity", - 45694, + 45694.0, "lbm", - "" + "" ], [ "aircraft:fuel:unusable_fuel_mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:furnishings:mass_scaler", @@ -809,9 +529,9 @@ ], [ "aircraft:fuselage:length", - 128, + 128.0, "ft", - "" + "" ], [ "aircraft:fuselage:mass_scaler", @@ -831,6 +551,18 @@ "ft", "" ], + [ + "aircraft:fuselage:military_cargo_floor", + false, + "unitless", + "" + ], + [ + "aircraft:fuselage:num_fuselages", + 1, + "unitless", + "" + ], [ "aircraft:fuselage:passenger_compartment_length", 85.5, @@ -845,9 +577,9 @@ ], [ "aircraft:fuselage:wetted_area_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:fuselage:wetted_area", @@ -857,15 +589,15 @@ ], [ "aircraft:horizontal_tail:area", - 355, + 355.0, "ft**2", - "" + "" ], [ "aircraft:horizontal_tail:aspect_ratio", - 6, + 6.0, "unitless", - "" + "" ], [ "aircraft:horizontal_tail:mass_scaler", @@ -887,15 +619,15 @@ ], [ "aircraft:horizontal_tail:vertical_tail_fraction", - 0, + 0.0, "unitless", - "" + "" ], [ "aircraft:horizontal_tail:wetted_area_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:horizontal_tail:wetted_area", @@ -905,15 +637,15 @@ ], [ "aircraft:hydraulics:mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:hydraulics:system_pressure", - 3000, + 3000.0, "psi", - "" + "" ], [ "aircraft:instruments:mass_scaler", @@ -929,21 +661,21 @@ ], [ "aircraft:landing_gear:main_gear_oleo_length", - 102, + 102.0, "inch", - "" + "" ], [ "aircraft:landing_gear:nose_gear_mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:landing_gear:nose_gear_oleo_length", - 67, + 67.0, "inch", - "" + "" ], [ "aircraft:nacelle:avg_diameter", @@ -985,21 +717,21 @@ ], [ "aircraft:propulsion:engine_oil_mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:propulsion:misc_mass_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:vertical_tail:area", - 284, + 284.0, "ft**2", - "" + "" ], [ "aircraft:vertical_tail:aspect_ratio", @@ -1009,6 +741,12 @@ ], [ "aircraft:vertical_tail:mass_scaler", + 1.0, + "unitless", + "" + ], + [ + "aircraft:vertical_tail:num_tails", 1, "unitless", "" @@ -1027,9 +765,9 @@ ], [ "aircraft:vertical_tail:wetted_area_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:vertical_tail:wetted_area", @@ -1039,15 +777,21 @@ ], [ "aircraft:wing:aeroelastic_tailoring_factor", - 0, + 0.0, "unitless", - "" + "" + ], + [ + "aircraft:wing:airfoil_technology", + 1.92669766647637, + "unitless", + "" ], [ "aircraft:wing:area", - 1370, + 1370.0, "ft**2", - "" + "" ], [ "aircraft:wing:aspect_ratio", @@ -1056,10 +800,10 @@ "" ], [ - "aircraft:wing:bending_mass_scaler", - 1, + "aircraft:wing:bending_material_mass_scaler", + 1.0, "unitless", - "" + "" ], [ "aircraft:wing:chord_per_semispan", @@ -1079,9 +823,9 @@ ], [ "aircraft:wing:control_surface_area", - 137, + 137.0, "ft**2", - "" + "" ], [ "aircraft:wing:control_surface_area_ratio", @@ -1089,33 +833,45 @@ "unitless", "" ], + [ + "aircraft:wing:detailed_wing", + true, + "unitless", + "" + ], [ "aircraft:wing:glove_and_bat", - 134, + 134.0, "ft**2", - "" + "" ], [ "aircraft:wing:input_station_dist", [ - 0, + 0.0, 0.2759, 0.9367 ], "unitless", "" ], + [ + "aircraft:wing:load_distribution_control", + 2.0, + "unitless", + "" + ], [ "aircraft:wing:load_fraction", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:wing:load_path_sweep_dist", [ - 0, - 22 + 0.0, + 22.0 ], "deg", "" @@ -1128,21 +884,33 @@ ], [ "aircraft:wing:max_camber_at_70_semispan", - 0, + 0.0, "unitless", - "" + "" ], [ "aircraft:wing:misc_mass_scaler", - 1, + 1.0, + "unitless", + "" + ], + [ + "aircraft:wing:num_integration_stations", + 50, "unitless", "" ], [ "aircraft:wing:shear_control_mass_scaler", - 1, + 1.0, "unitless", - "" + "" + ], + [ + "aircraft:wing:span_efficiency_reduction", + false, + "unitless", + "" ], [ "aircraft:wing:span", @@ -1152,21 +920,21 @@ ], [ "aircraft:wing:strut_bracing_factor", - 0, + 0.0, "unitless", - "" + "" ], [ - "aircraft:wing:surface_ctrl_mass_scaler", - 1, + "aircraft:wing:surface_control_mass_scaler", + 1.0, "unitless", - "" + "" ], [ "aircraft:wing:sweep", - 25, + 25.0, "deg", - "" + "" ], [ "aircraft:wing:taper_ratio", @@ -1198,15 +966,15 @@ ], [ "aircraft:wing:var_sweep_mass_penalty", - 0, + 0.0, "unitless", - "" + "" ], [ "aircraft:wing:wetted_area_scaler", - 1, + 1.0, "unitless", - "" + "" ], [ "aircraft:wing:wetted_area", @@ -1224,11 +992,11 @@ "mission:design:gross_mass", 175400.0, "lbm", - "" + "" ], [ "mission:design:range", - 1906.0, + 3500.0, "NM", "" ], @@ -1240,9 +1008,9 @@ ], [ "mission:landing:lift_coefficient_max", - 2, + 2.0, "unitless", - "" + "" ], [ "mission:summary:cruise_mach", @@ -1250,17 +1018,23 @@ "unitless", "" ], + [ + "mission:summary:fuel_flow_scaler", + 1.0, + "unitless", + "" + ], [ "mission:takeoff:fuel_simple", - 577, + 577.0, "lbm", - "" + "" ], [ "mission:takeoff:lift_coefficient_max", - 3, + 3.0, "unitless", - "" + "" ], [ "mission:takeoff:lift_over_drag", @@ -1270,22 +1044,94 @@ ], [ "settings:equations_of_motion", - "[]", + "HEIGHT_ENERGY", "unitless", "" ], + [ + "settings:aerodynamics_method", + "FLOPS", + "unitless", + "" + ], [ "settings:mass_method", - "[]", + "FLOPS", "unitless", "" ], + [ + "settings:payload_range", + false, + "unitless", + "" + ], + [ + "settings:verbosity", + "BRIEF", + "unitless", + "" + ], [ "mission:summary:gross_mass", 175400.0, "lbm", + "" + ], + [ + "mission:summary:range", + 1906.0, + "NM", + "" + ], + [ + "aircraft:crew_and_payload:num_passengers", + 169, + "unitless", + "" + ], + [ + "aircraft:crew_and_payload:num_first_class", + 11, + "unitless", + "" + ], + [ + "aircraft:crew_and_payload:num_business_class", + 0, + "unitless", + "" + ], + [ + "aircraft:crew_and_payload:num_tourist_class", + 158, + "unitless", "" ], + [ + "aircraft:engine:global_hybrid_throttle", + [ + false + ], + "unitless", + "" + ], + [ + "aircraft:engine:global_throttle", + [ + false + ], + "unitless", + "" + ], + [ + "aircraft:engine:interpolation_sort", + [ + "mach" + ], + "unitless", + "" + ], [ "aircraft:propulsion:total_num_engines", 2, @@ -1303,5 +1149,11 @@ 2, "unitless", "" + ], + [ + "aircraft:fuel:ignore_fuel_capacity_constraint", + false, + "unitless", + "" ] ] \ No newline at end of file diff --git a/aviary/interface/test/specially_named_for_tests.deck b/aviary/interface/test/specially_named_for_tests.deck deleted file mode 100644 index c70bb2431e..0000000000 --- a/aviary/interface/test/specially_named_for_tests.deck +++ /dev/null @@ -1,280 +0,0 @@ -# GASP-derived engine deck converted from GASP_turbofan_24k_1.eng -# t4max: 3100.0 -# t4cruise: 2770.0 -# t4climb: 3030.0 -# sls_airflow: 794.67 -# sfn_idle: -10.0 - -Mach_Number (unitless),Altitude (ft),Throttle (unitless),Thrust (lbf),Fuel_Flow (lb/h),T4 (degR) -0.0,0.0,0.16353735150633147,119.332,721.4768,1556.0099999999998 -0.2,0.0,0.17028114775207215,14.3682,743.0868,1568.4580799999999 -0.35,0.0,0.18419022750891215,-95.7382,813.6561,1594.1322449999998 -0.0,0.0,0.4445288617455241,5986.5659,2297.7,2074.68 -0.2,0.0,0.4535205900731783,4426.9868,2382.6592,2091.27744 -0.35,0.0,0.47206602974896494,4101.6514,2636.7056,2125.5096599999997 -0.0,0.0,0.7255203719847167,14508.1279,5221.8164,2593.35 -0.2,0.0,0.7367600323942844,11986.2969,5504.7871,2614.0968 -0.35,0.0,0.7599418319890177,11371.3486,6035.5361,2656.8870749999996 -0.0,0.0,0.8660161271043131,20704.6621,7578.1924,2852.685 -0.2,0.0,0.8783797535548376,17494.3438,7922.1538,2875.50648 -0.35,0.0,0.9038797331090441,16450.9082,8616.7412,2922.5757824999996 -0.0,5000.0,0.13455730859421963,-283.8691,483.9326,1502.517 -0.2,5000.0,0.14106926449666327,-337.63,486.0058,1514.537136 -0.35,5000.0,0.15450017354545342,-460.2864,533.3245,1539.3286664999998 -0.4,5000.0,0.1606051322039946,-633.109,492.154,1550.5975440000002 -0.0,5000.0,0.40588880452937487,4645.6011,1810.4146,2003.356 -0.2,5000.0,0.41457141239929984,3457.7671,1896.6125,2019.382848 -0.35,5000.0,0.43247929113101996,3183.5225,2084.186,2052.4382219999998 -0.4,5000.0,0.4406192360090748,3191.0259,2195.3877,2067.463392 -0.0,5000.0,0.6772203004645302,11501.6416,4088.8958,2504.195 -0.2,5000.0,0.6880735603019363,9535.8857,4341.2363,2524.22856 -0.35,5000.0,0.7104584087165866,9117.8936,4799.5552,2565.5477775 -0.4,5000.0,0.720633339814155,9141.541,5010.4902,2584.32924 -0.0,5000.0,0.8128860484321079,16675.2012,6008.3486,2754.6145 -0.2,5000.0,0.8248246342532547,14081.458,6303.144,2776.651416 -0.35,5000.0,0.8494479675093697,13356.3652,6889.1826,2822.1025552499996 -0.4,5000.0,0.8606403917166953,13355.5928,7170.4268,2842.762164 -0.0,5000.0,0.9485517963996855,22470.0859,8456.2871,3005.034 -0.2,5000.0,0.9615757082045728,19249.4688,8807.3457,3029.074272 -0.35,5000.0,0.9884375263021531,18039.3008,9468.2324,3078.6573329999997 -0.2,10000.0,0.1118573812412544,-822.5745,215.0546,1460.616192 -0.35,10000.0,0.1248101195819947,-901.472,242.3344,1484.5250879999999 -0.4,10000.0,0.13069772791869488,-905.2738,264.2812,1495.392768 -0.5,10000.0,0.14482798792677534,-999.016,295.9601,1521.4752 -0.2,10000.0,0.3756222347254212,2609.6204,1489.958,1947.4882559999999 -0.35,10000.0,0.392892552513075,2421.3765,1644.6975,1979.3667839999998 -0.4,10000.0,0.4007426969620086,2389.4829,1714.1914,1993.857024 -0.5,10000.0,0.4195830436394492,2366.1904,1880.4651,2028.6336000000001 -0.2,10000.0,0.6393870882095881,7380.8604,3369.4685,2434.36032 -0.35,10000.0,0.6609749854441553,7050.9414,3714.5696,2474.20848 -0.4,10000.0,0.6707876660053224,7070.9849,3873.8013,2492.32128 -0.5,10000.0,0.6943380993521232,7255.2305,4292.9683,2535.7920000000004 -0.2,10000.0,0.7712695149516715,10938.293,4854.7241,2677.796352 -0.35,10000.0,0.7950162019096956,10456.3809,5342.2646,2721.629328 -0.4,10000.0,0.8058101505269791,10500.5176,5588.375,2741.5534079999998 -0.5,10000.0,0.8317156272084599,10706.1602,6161.3193,2789.3712 -0.2,10000.0,0.903151941693755,15233.1191,6841.9819,2921.232384 -0.35,10000.0,0.9290574183752356,14328.6211,7440.0151,2969.0501759999997 -0.4,10000.0,0.940832635048636,14275.5801,7734.5859,2990.785536 -0.5,10000.0,0.9690931550647969,14450.1992,8450.3193,3042.9504 -0.35,15000.0,0.09512173069923609,-1098.6724,78.2106,1429.724583 -0.4,15000.0,0.10079200090355886,-1100.22,89.7779,1440.191088 -0.5,15000.0,0.11440064939393334,-1181.3855,101.7453,1465.3107 -0.6,15000.0,0.13103344199327993,-1205.2955,142.0774,1496.012448 -0.7,15000.0,0.15069037870159863,-1225.8739,196.2914,1532.296332 -0.35,15000.0,0.35330803400273025,1717.6884,1241.4174,1906.299444 -0.4,15000.0,0.3608683942751605,1702.991,1297.3217,1920.254784 -0.5,15000.0,0.3790132589289933,1693.1018,1430.4333,1953.7476000000001 -0.6,15000.0,0.401190315728122,1755.8381,1608.9412,1994.683264 -0.7,15000.0,0.42739956467254686,1869.8241,1831.4385,2043.0617759999998 -0.35,15000.0,0.6114943373062243,5423.8013,2846.3318,2382.874305 -0.4,15000.0,0.6209447876467622,5452.8086,2978.8232,2400.31848 -0.5,15000.0,0.6436258684640532,5590.9741,3300.1682,2442.1845000000003 -0.6,15000.0,0.6713471894629641,5780.7983,3683.4683,2493.35408 -0.7,15000.0,0.7041087506434951,6126.1079,4189.8335,2553.8272199999997 -0.35,15000.0,0.7405874889579713,8155.5605,4126.1772,2621.1617355 -0.4,15000.0,0.750982984332563,8198.8164,4310.9678,2640.350328 -0.5,15000.0,0.775932173231583,8349.123,4735.9551,2686.40295 -0.6,15000.0,0.8064256263303851,8647.9658,5296.4033,2742.689488 -0.7,15000.0,0.8424633436289692,9090.6523,5980.9526,2809.2099419999995 -0.35,15000.0,0.8696806406097184,11302.9482,5732.9326,2859.449166 -0.4,15000.0,0.8810211810183639,11277.7783,5955.8916,2880.382176 -0.5,15000.0,0.908238477999113,11415.6416,6538.3872,2930.6214 -0.6,15000.0,0.9415040631978061,11752.5889,7287.6011,2992.024896 -0.7,15000.0,0.9808179366144435,12278.0391,8162.4443,3064.592664 -0.35,15000.0,0.9987737922614655,14194.7988,7561.2437,3097.7365965 -0.4,20000.0,0.07088459661825924,-1282.7881,-58.1917,1384.986312 -0.5,20000.0,0.08397160433621581,-1291.4023,-35.9897,1409.1430500000001 -0.6,20000.0,0.0999668359914959,-1314.7943,-13.7096,1438.667952 -0.7,20000.0,0.11887029158409965,-1317.3593,30.5004,1473.5610179999999 -0.75,20000.0,0.129412603356898,-1303.0309,62.9165,1493.0206125 -0.8,20000.0,0.14068197111402717,-1300.4995,95.539,1513.822248 -0.85,20000.0,0.1526783948554872,-1314.8655,130.4481,1535.9659244999998 -0.4,20000.0,0.3209918552280944,-1314.8655,130.4481,1846.648416 -0.5,20000.0,0.33844119885203644,1127.8431,1057.4075,1878.8574 -0.6,20000.0,0.35976817439241,1177.5199,1194.4406,1918.223936 -0.7,20000.0,0.3849727818492149,1283.9022,1371.9934,1964.7480239999998 -0.75,20000.0,0.3990291975462794,1351.9348,1479.6199,1990.69415 -0.8,20000.0,0.4140550212224517,1422.9874,1597.0325,2018.429664 -0.85,20000.0,0.43005025287773163,1497.1804,1726.3944,2047.9545659999997 -0.4,20000.0,0.5710991138379296,1497.1804,1726.3944,2308.31052 -0.5,20000.0,0.5929107933678571,4188.0752,2486.6428,2348.57175 -0.6,20000.0,0.619569512793324,4391.1245,2806.6602,2397.77992 -0.7,20000.0,0.6510752721143301,4681.4683,3193.5149,2455.9350299999996 -0.75,20000.0,0.6686457917356609,4836.7534,3409.625,2488.3676875 -0.8,20000.0,0.6874280713308761,5033.2417,3666.7864,2523.03708 -0.85,20000.0,0.7074221108999761,5249.0439,3954.8074,2559.9432074999995 -0.4,20000.0,0.6961527431428471,5249.0439,3954.8074,2539.141572 -0.5,20000.0,0.7201455906257674,6433.3589,3625.6497,2583.428925 -0.6,20000.0,0.7494701819937811,6678.2866,4049.002,2637.557912 -0.7,20000.0,0.7841265172468879,7040.1738,4558.1138,2701.5285329999997 -0.75,20000.0,0.8034540888303515,7289.0552,4889.8906,2737.20445625 -0.8,20000.0,0.8241145963850883,7562.4126,5254.9111,2775.340788 -0.85,20000.0,0.8461080399110984,7834.7402,5635.7271,2815.9375282499996 -0.4,20000.0,0.8212063724477647,7834.7402,5635.7271,2769.972624 -0.5,20000.0,0.8473803878836779,8923.8301,5014.8716,2818.2861000000003 -0.6,20000.0,0.8793708511942381,9235.125,5567.9268,2877.335904 -0.7,20000.0,0.9171777623794455,9644.4395,6284.7583,2947.1220359999998 -0.75,20000.0,0.9382623859250422,9927.1709,6715.8271,2986.041225 -0.8,20000.0,0.9608011214393005,10270.2266,7187.0791,3027.644496 -0.85,20000.0,0.9847939689222206,10602.9805,7673.8276,3071.9318489999996 -0.4,20000.0,0.9462600017526823,10602.9805,7673.8276,3000.803676 -0.5,20000.0,0.9746151851415882,11176.3115,6563.2012,3053.1432750000004 -0.5,25000.0,0.053542559278498165,-1465.4062,-188.1391,1352.9754 -0.6,25000.0,0.06890022998971188,-1426.801,-149.6866,1381.323456 -0.7,25000.0,0.08705020446660067,-1363.875,-100.6971,1414.8257039999999 -0.75,25000.0,0.09717230561717351,-1356.431,-78.4116,1433.5096500000002 -0.8,25000.0,0.10799248270916502,-1372.119,-60.3519,1453.4821440000003 -0.85,25000.0,0.11951073574257509,-1366.2582,-27.7235,1474.743186 -0.5,25000.0,0.29786913877507964,623.2464,740.7552,1803.9672 -0.6,25000.0,0.31834603305669795,694.4828,854.7831,1841.7646080000002 -0.7,25000.0,0.34254599902588306,796.8191,995.9554,1886.434272 -0.75,25000.0,0.3560421338933134,854.2121,1078.9293,1911.3462000000002 -0.8,25000.0,0.3704690366826354,912.9566,1170.1919,1937.9761920000003 -0.85,25000.0,0.3858267073938489,987.3726,1275.196,1966.324248 -0.5,25000.0,0.542195718271661,3099.1606,1863.2922,2254.959 -0.6,25000.0,0.567791836123684,3197.1284,2070.8472,2302.2057600000003 -0.7,25000.0,0.5980417935851654,3467.0327,2388.3503,2358.04284 -0.75,25000.0,0.6149119621694533,3629.5518,2572.8838,2389.1827500000004 -0.8,25000.0,0.6329455906561059,3795.5439,2768.6123,2422.4702400000006 -0.85,25000.0,0.6521426790451228,3972.0083,2983.749,2457.90531 -0.5,25000.0,0.6643590080199518,4847.6045,2713.7314,2480.4549 -0.6,25000.0,0.6925147376571771,5057.584,3047.0024,2532.4263360000004 -0.7,25000.0,0.7257896908648065,5390.5591,3467.1848,2593.847124 -0.75,25000.0,0.7443468763075233,5582.8701,3706.4697,2628.1010250000004 -0.8,25000.0,0.764183867642841,5794.8218,3969.082,2664.7172640000003 -0.85,25000.0,0.7853006648707594,6021.8667,4255.4692,2703.6958409999997 -0.5,25000.0,0.7865222977682426,6847.7173,3776.6926,2705.9508 -0.6,25000.0,0.8172376391906699,7105.2158,4227.3726,2762.646912 -0.7,25000.0,0.8535375881444476,7488.4961,4771.2456,2829.6514079999997 -0.75,25000.0,0.8737817904455932,7730.9092,5085.4976,2867.0193000000004 -0.8,25000.0,0.8954221446295763,7994.9702,5443.1182,2906.9642880000006 -0.85,25000.0,0.9184586506963964,8268.126,5859.8896,2949.486372 -0.5,25000.0,0.9086855875165333,8774.7217,5016.1353,2931.4467 -0.6,25000.0,0.9419605407241631,8996.7305,5546.0391,2992.8674880000003 -0.7,25000.0,0.9812854854240889,9364.9141,6212.1289,3065.455692 -0.6,30000.0,0.03783362398792773,-1641.9077,-317.4978,1323.97896 -0.7,30000.0,0.05523011734910169,-1494.1465,-242.8544,1356.0903899999998 -0.75,30000.0,0.06493200787744878,-1459.6558,-214.7922,1373.9986875 -0.8,30000.0,0.07530299430430264,-1417.6088,-182.9302,1393.1420400000002 -0.85,30000.0,0.08634307662966285,-1385.2917,-151.6695,1413.5204474999998 -0.6,30000.0,0.2769238917209858,227.7136,550.9996,1765.30528 -0.7,30000.0,0.30011921620255094,366.4952,678.6176,1808.1205199999997 -0.75,30000.0,0.3130550702403472,426.1066,746.9874,1831.99825 -0.8,30000.0,0.3268830521428189,492.9079,822.7838,1857.5227200000002 -0.85,30000.0,0.34160316190996587,558.5389,904.9783,1884.6939299999997 -0.6,30000.0,0.5160141594540438,2331.6267,1545.6548,2206.6316 -0.7,30000.0,0.5450083150560002,2501.7324,1756.8065,2260.1506499999996 -0.75,30000.0,0.5611781326032457,2588.3354,1872.9819,2289.9978125000002 -0.8,30000.0,0.5784631099813351,2727.0273,2023.1437,2321.9034 -0.85,30000.0,0.596863247190269,2904.0581,2206.6726,2355.8674125 -0.6,30000.0,0.6355592933205729,3759.6587,2264.3767,2427.29476 -0.7,30000.0,0.6674528644827249,4001.1108,2563.0559,2486.1657149999996 -0.75,30000.0,0.6852396637846948,4169.2144,2752.1565,2518.9975937500003 -0.8,30000.0,0.7042531389005933,4352.5088,2964.0923,2554.0937400000003 -0.85,30000.0,0.7244932898304203,4551.0488,3195.9551,2591.4541537499995 -0.6,30000.0,0.7551044271871017,5374.0977,3151.9736,2647.95792 -0.7,30000.0,0.7898974139094496,5683.3257,3554.6294,2712.1807799999997 -0.75,30000.0,0.8093011949661438,5885.228,3809.8965,2747.997375 -0.8,30000.0,0.8300431678198514,6105.729,4092.3638,2786.2840800000004 -0.85,30000.0,0.8521233324705719,6346.2397,4394.3291,2827.0408949999996 -0.6,30000.0,0.8746495610536307,6929.9941,4177.7715,2868.62108 -0.7,30000.0,0.9123419633361742,7279.8677,4698.106,2938.1958449999997 -0.75,30000.0,0.933362726147593,7486.4111,5003.8521,2976.99715625 -0.8,30000.0,0.9558331967391097,7707.4565,5339.5127,3018.4744200000005 -0.85,30000.0,0.9797533751107234,7972.8979,5724.6699,3062.6276362499993 -0.6,30000.0,0.9941946949201598,8212.2148,5181.8916,3089.28424 -0.6,35000.0,0.006767017986143824,-2123.249,-584.9083,1266.6344640000002 -0.7,35000.0,0.0234100302316027,-1820.1091,-457.5376,1297.3550759999998 -0.75,35000.0,0.032691710137724185,-1716.4246,-406.0729,1314.487725 -0.8,35000.0,0.04261350589944024,-1619.9938,-355.8443,1332.801936 -0.85,35000.0,0.05317541751675062,-1548.7271,-319.6995,1352.2977089999997 -0.6,35000.0,0.23550175038527377,-356.928,224.8273,1688.8459520000001 -0.7,35000.0,0.257692433379219,-140.5189,361.974,1729.8067679999997 -0.75,35000.0,0.270068006587381,-51.8074,430.4904,1752.6503 -0.8,35000.0,0.28329706760300233,37.8187,502.8929,1777.069248 -0.85,35000.0,0.29737961642608296,113.3275,573.9567,1803.0636119999997 -0.6,35000.0,0.4642364827844037,1454.7124,1061.7505,2111.05744 -0.7,35000.0,0.4919748365268352,1646.2544,1245.0011,2162.2584599999996 -0.75,35000.0,0.5074443030370379,1745.0444,1347.3065,2190.812875 -0.8,35000.0,0.5239806293065646,1852.8096,1456.8871,2221.33656 -0.85,35000.0,0.5415838153354151,1957.7714,1573.3245,2253.8295149999994 -0.6,35000.0,0.5786038489839687,2586.5618,1613.2426,2322.163184 -0.7,35000.0,0.6091160381006433,2820.207,1856.6794,2378.4843059999994 -0.75,35000.0,0.6261324512618663,2947.7493,1991.9904,2409.8941625 -0.8,35000.0,0.6443224101583457,3081.2561,2140.0664,2443.470216 -0.85,35000.0,0.6636859147900814,3229.0686,2303.3765,2479.2124664999997 -0.6,35000.0,0.6929712151835339,3896.791,2298.6492,2533.2689280000004 -0.7,35000.0,0.7262572396744517,4133.7578,2598.9985,2594.7101519999997 -0.75,35000.0,0.7448205994866945,4280.896,2775.2344,2628.97545 -0.8,35000.0,0.7646641910101267,4453.6055,2973.5544,2665.603872 -0.85,35000.0,0.7857880142447474,4645.3311,3191.2744,2704.5954179999994 -0.6,35000.0,0.8073385813830989,5179.4541,3073.7734,2744.3746720000004 -0.7,35000.0,0.8433984412482597,5378.2861,3439.0317,2810.9359979999995 -0.75,35000.0,0.8635087477115231,5558.4214,3673.3267,2848.0567375 -0.8,35000.0,0.8850059718619078,5782.9717,3937.8389,2887.737528 -0.85,35000.0,0.9078901136994137,6003.707,4228.5078,2929.9783694999996 -0.6,35000.0,0.9217059475826638,6185.6665,3843.9114,2955.4804160000003 -0.7,35000.0,0.9605396428220678,6448.7495,4289.6572,3027.1618439999993 -0.75,35000.0,0.9821968959363515,6643.8325,4566.875,3067.138025 -0.6,39000.0,0.0,-2891.208,-973.3418,1254.14352 -0.7,39000.0,0.0164788868092279,-2274.4888,-723.6464,1284.56118 -0.75,39000.0,0.025669035222066663,-2074.3691,-635.4612,1301.524875 -0.8,39000.0,0.03549298697372193,-1901.4742,-554.7587,1319.6584800000003 -0.85,39000.0,0.04595074206419332,-1727.4702,-492.0538,1338.961995 -0.6,39000.0,0.22647905973708216,-1016.0961,-113.6783,1672.1913600000003 -0.7,39000.0,0.2484509088160526,-619.0324,85.2694,1712.74824 -0.75,39000.0,0.26070444003317095,-475.6894,169.3863,1735.3665 -0.8,39000.0,0.2738030423687113,-345.4908,251.9748,1759.5446400000003 -0.85,39000.0,0.28774671582267314,-224.3491,330.3477,1785.2826599999999 -0.6,39000.0,0.4529581194741643,858.6461,745.9283,2090.2392000000004 -0.7,39000.0,0.48042293082287746,1057.115,908.0612,2140.9353 -0.75,39000.0,0.49573984484427525,1160.6975,999.6034,2169.208125 -0.8,39000.0,0.5121130977637007,1260.0049,1095.5002,2199.4308000000005 -0.85,39000.0,0.5295426895811531,1360.948,1198.1838,2231.603325 -0.6,39000.0,0.5661976493427054,1822.3699,1207.3475,2299.2631200000005 -0.7,39000.0,0.5964089418262896,2034.8923,1413.623,2355.0288299999997 -0.75,39000.0,0.6132575472498274,2152.665,1530.2035,2386.1289375 -0.8,39000.0,0.6312681254611954,2276.0742,1655.8514,2419.3738800000006 -0.85,39000.0,0.6504406764603928,2411.04,1792.4537,2454.7636574999997 -0.6,39000.0,0.6794371792112462,2928.707,1774.6229,2508.28704 -0.7,39000.0,0.712394952829702,3140.615,2027.7026,2569.12236 -0.75,39000.0,0.7307752496553795,3269.2891,2173.5259,2603.04975 -0.8,39000.0,0.7504231531586901,3409.4595,2331.6143,2639.3169600000006 -0.85,39000.0,0.7713386633396329,3569.9548,2506.552,2677.92399 -0.6,39000.0,0.7926767090797873,4031.9429,2418.1599,2717.3109600000003 -0.7,39000.0,0.8283809638331144,4201.459,2716.3413,2783.21589 -0.75,39000.0,0.8482929520609317,4342.3438,2902.6355,2819.9705625 -0.8,39000.0,0.8695781808561848,4520.5684,3115.1143,2859.2600400000006 -0.85,39000.0,0.8922366502188729,4733.9717,3355.8064,2901.0843225 -0.6,39000.0,0.9059162389483284,4911.5527,3072.9634,2926.3348800000003 -0.7,39000.0,0.9443669748365267,5093.3384,3415.3503,2997.3094199999996 -0.75,39000.0,0.9658106544664838,5267.2007,3645.8479,3036.891375 -0.8,39000.0,0.9887332085536794,5457.7554,3898.7056,3079.2031200000006 -0.7,43000.0,0.0164788868092279,-3281.6809,-1263.1353,1284.56118 -0.75,43000.0,0.025669035222066663,-2792.3232,-1044.274,1301.524875 -0.8,43000.0,0.03549298697372193,-2422.3247,-874.4929,1319.6584800000003 -0.85,43000.0,0.04595074206419332,-2115.3579,-755.3212,1338.961995 -0.7,43000.0,0.2484509088160526,-1400.321,-335.28,1712.74824 -0.75,43000.0,0.26070444003317095,-1085.2146,-177.6793,1735.3665 -0.8,43000.0,0.2738030423687113,-839.2385,-47.0228,1759.5446400000003 -0.85,43000.0,0.28774671582267314,-638.0304,58.5412,1785.2826599999999 -0.7,43000.0,0.48042293082287746,473.8456,589.921,2140.9353 -0.75,43000.0,0.49573984484427525,620.6105,690.3464,2169.208125 -0.8,43000.0,0.5121130977637007,749.7365,788.1461,2199.4308000000005 -0.85,43000.0,0.5295426895811531,863.3511,885.1731,2231.603325 -0.7,43000.0,0.5964089418262896,1387.9363,1053.5619,2355.0288299999997 -0.75,43000.0,0.6132575472498274,1505.2258,1156.5454,2386.1289375 -0.8,43000.0,0.6312681254611954,1626.7366,1265.7191,2419.3738800000006 -0.85,43000.0,0.6504406764603928,1753.5994,1381.5503,2454.7636574999997 -0.7,43000.0,0.712394952829702,2339.4993,1573.6965,2569.12236 -0.75,43000.0,0.7307752496553795,2457.5403,1694.1971,2603.04975 -0.8,43000.0,0.7504231531586901,2579.1248,1823.5708,2639.3169600000006 -0.85,43000.0,0.7713386633396329,2720.0356,1971.6774,2677.92399 -0.7,43000.0,0.8283809638331144,3260.1284,2150.562,2783.21589 -0.75,43000.0,0.8482929520609317,3384.1062,2302.1875,2819.9705625 -0.8,43000.0,0.8695781808561848,3539.3022,2476.9392,2859.2600400000006 -0.85,43000.0,0.8922366502188729,3710.6001,2667.4424,2901.0843225 -0.7,43000.0,0.9443669748365267,4031.8059,2740.031,2997.3094199999996 -0.75,43000.0,0.9658106544664838,4170.4385,2924.7302,3036.891375 -0.8,43000.0,0.9887332085536794,4324.1924,3131.4419,3079.2031200000006 diff --git a/aviary/interface/test/test_check_phase_info.py b/aviary/interface/test/test_check_phase_info.py deleted file mode 100644 index 9e18ca5219..0000000000 --- a/aviary/interface/test/test_check_phase_info.py +++ /dev/null @@ -1,49 +0,0 @@ -import unittest -import copy - -from aviary.interface.utils.check_phase_info import check_phase_info -from aviary.interface.default_phase_info.height_energy import phase_info as phase_info_height_energy -from aviary.interface.default_phase_info.two_dof import phase_info as phase_info_two_dof -from aviary.variable_info.enums import EquationsOfMotion - -HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY -TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM - - -class TestCheckInputs(unittest.TestCase): - def test_correct_input_height_energy(self): - # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info( - phase_info_height_energy, mission_method=HEIGHT_ENERGY)) - - def test_incorrect_tuple(self): - # Let's replace a tuple with a float in the 'climb' phase - incorrect_tuple_phase_info = copy.deepcopy(phase_info_height_energy) - incorrect_tuple_phase_info['climb']['user_options']['initial_altitude'] = 10.668e3 - with self.assertRaises(ValueError): - check_phase_info(incorrect_tuple_phase_info, mission_method=HEIGHT_ENERGY) - - def test_incorrect_unit(self): - # Let's replace a valid unit with an invalid one in the 'climb' phase - incorrect_unit_phase_info = copy.deepcopy(phase_info_height_energy) - incorrect_unit_phase_info['climb']['user_options']['initial_altitude'] = ( - 10.668e3, 'invalid_unit') - with self.assertRaisesRegex(ValueError, - "Key initial_altitude in phase climb has an invalid unit invalid_unit."): - check_phase_info(incorrect_unit_phase_info, mission_method=HEIGHT_ENERGY) - - def test_correct_input_two_dof(self): - # This should pass without any issue as it's the same valid dict as before - self.assertTrue(check_phase_info(phase_info_two_dof, - mission_method=TWO_DEGREES_OF_FREEDOM)) - - def test_incorrect_mission_method(self): - # Let's pass an incorrect mission_method name - incorrect_mission_method = 'INVALID_METHOD' - with self.assertRaises(ValueError): - check_phase_info(phase_info_height_energy, - mission_method=incorrect_mission_method) - - -if __name__ == '__main__': - unittest.main() diff --git a/aviary/interface/test/test_cmd_entry_points.py b/aviary/interface/test/test_cmd_entry_points.py index c255fe9a25..7454bdf20e 100644 --- a/aviary/interface/test/test_cmd_entry_points.py +++ b/aviary/interface/test/test_cmd_entry_points.py @@ -2,18 +2,19 @@ import unittest from pathlib import Path -from aviary.utils.functions import get_aviary_resource_path from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs +from aviary.utils.functions import get_aviary_resource_path + @use_tempdirs class CommandEntryPointsTestCases(unittest.TestCase): def run_and_test_cmd(self, cmd): # this only tests that a given command line tool returns a 0 return code. It doesn't - # check the expected output at all. The underlying functions that implement the - # commands should be tested seperately. + # check the expected output at all. The underlying functions that implement the + # commands should be tested separately. try: - output = subprocess.check_output(cmd.split()) + subprocess.check_output(cmd.split()) except subprocess.CalledProcessError as err: self.fail(f"Command '{cmd}' failed. Return code: {err.returncode}") @@ -24,97 +25,102 @@ def get_file(self, filename): return filepath -class run_missionTestCases(CommandEntryPointsTestCases): - @require_pyoptsparse(optimizer="SNOPT") - def bench_test_SNOPT_cmd(self): - cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer SNOPT --max_iter 1' +class InstallationTest(CommandEntryPointsTestCases): + def run_installation_test(self): + cmd = 'aviary check' self.run_and_test_cmd(cmd) - @require_pyoptsparse(optimizer="IPOPT") - def bench_test_IPOPT_cmd(self): - cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1' + +class run_missionTestCases(CommandEntryPointsTestCases): + @require_pyoptsparse(optimizer='SNOPT') + def bench_test_SNOPT_cmd(self): + cmd = 'aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer SNOPT --max_iter 1' self.run_and_test_cmd(cmd) - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def bench_test_IPOPT_cmd(self): - cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv' \ - ' --optimizer IPOPT --max_iter 1 --shooting' + cmd = 'aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1' self.run_and_test_cmd(cmd) - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def bench_test_phase_info_cmd(self): - cmd = 'aviary run_mission models/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1' \ - ' --phase_info interface/default_phase_info/two_dof.py' + cmd = ( + 'aviary run_mission models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv --optimizer IPOPT --max_iter 1' + ' --phase_info models/missions/two_dof_default.py' + ) self.run_and_test_cmd(cmd) class fortran_to_aviaryTestCases(CommandEntryPointsTestCases): def test_diff_configuration_conversion(self): - filepath = get_aviary_resource_path( - 'models/test_aircraft/converter_configuration_test_data_GwGm.dat') - outfile = Path.cwd() / 'test_aircraft/converter_configuration_test_data_GwGm' / 'output.dat' + filepath = get_aviary_resource_path('utils/test/data/configuration_test_data_GASP.dat') + outfile = Path.cwd() / 'utils/test/data/configuration_test_data_GASP' / 'output.dat' cmd = f'aviary fortran_to_aviary {filepath} -o {outfile} -l GASP' self.run_and_test_cmd(cmd) def test_small_single_aisle_conversion(self): filepath = get_aviary_resource_path( - 'models/small_single_aisle/small_single_aisle_GwGm.dat') + 'models/aircraft/small_single_aisle/small_single_aisle_GASP.dat' + ) outfile = Path.cwd() / 'small_single_aisle' / 'output.dat' cmd = f'aviary fortran_to_aviary {filepath} -o {outfile} -l GASP' self.run_and_test_cmd(cmd) def test_FLOPS_conversion(self): filepath = get_aviary_resource_path( - 'models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.txt') - outfile = Path.cwd() / 'N3CC' / 'output.dat' + 'models/aircraft/advanced_single_aisle/N3CC_generic_low_speed_polars_FLOPS.txt' + ) + outfile = Path.cwd() / 'advanced_single_aisle' / 'output.dat' cmd = f'aviary fortran_to_aviary {filepath} -o {outfile} -l FLOPS' self.run_and_test_cmd(cmd) def test_force_conversion(self): filepath = get_aviary_resource_path( - 'models/test_aircraft/converter_configuration_test_data_GwGm.dat') + 'models/aircraft/small_single_aisle/small_single_aisle_GASP.dat' + ) outfile = Path.cwd() / 'output.dat' cmd1 = f'aviary fortran_to_aviary {filepath} -o {outfile} -l GASP' self.run_and_test_cmd(cmd1) filepath = get_aviary_resource_path( - 'models/test_aircraft/converter_configuration_test_data_GwGm.dat') + 'models/aircraft/small_single_aisle/small_single_aisle_GASP.dat' + ) cmd2 = f'aviary fortran_to_aviary {filepath} -o {outfile} --force -l GASP' self.run_and_test_cmd(cmd2) class hangarTestCases(CommandEntryPointsTestCases): def test_copy_folder(self): - cmd = f'aviary hangar engines' + cmd = 'aviary hangar engines' self.run_and_test_cmd(cmd) def test_copy_deck(self): - cmd = f'aviary hangar turbofan_22k.txt' + cmd = 'aviary hangar turbofan_22k.csv' self.run_and_test_cmd(cmd) def test_copy_n3cc_data(self): - cmd = f'aviary hangar N3CC/N3CC_data.py' + cmd = 'aviary hangar advanced_single_aisle/advanced_single_aisle_data.py' self.run_and_test_cmd(cmd) def test_copy_multiple(self): - cmd = f'aviary hangar small_single_aisle_GwGm.dat small_single_aisle_GwGm.csv' + cmd = 'aviary hangar small_single_aisle_GASP.dat small_single_aisle_GASP.csv' self.run_and_test_cmd(cmd) def test_copy_to(self): outfile = Path.cwd() / 'example_files' - cmd = f'aviary hangar small_single_aisle_GwGm.dat -o {outfile}' + cmd = f'aviary hangar small_single_aisle_GASP.dat -o {outfile}' self.run_and_test_cmd(cmd) class convert_engineTestCases(CommandEntryPointsTestCases): def test_GASP_conversion(self): filepath = self.get_file('utils/test/data/GASP_turbofan_23k_1.eng') - outfile = Path.cwd() / 'turbofan_23k_1_lbm_s.deck' + outfile = Path.cwd() / 'turbofan_23k_1.csv' cmd = f'aviary convert_engine {filepath} {outfile} -f GASP' self.run_and_test_cmd(cmd) def test_FLOPS_conversion(self): filepath = self.get_file('utils/test/data/FLOPS_turbofan_22k.txt') - outfile = Path.cwd() / 'turbofan_22k.txt' + outfile = Path.cwd() / 'turbofan_22k.csv' cmd = f'aviary convert_engine {filepath} {outfile} -f FLOPS' self.run_and_test_cmd(cmd) @@ -127,32 +133,29 @@ def test_GASP_TS_conversion(self): class convert_aero_tableTestCases(CommandEntryPointsTestCases): def test_GASP_conversion(self): - filepath = self.get_file( - 'subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt') + filepath = self.get_file('subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt') outfile = Path.cwd() / 'output.dat' cmd = f'aviary fortran_to_aviary {filepath} -o {outfile} -l GASP' self.run_and_test_cmd(cmd) def test_FLOPS_conversion(self): filepath = self.get_file( - 'models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.txt') - outfile = Path.cwd() / 'N3CC' / 'output.dat' + 'models/aircraft/advanced_single_aisle/N3CC_generic_low_speed_polars_FLOPSinp.txt' + ) + outfile = Path.cwd() / 'advanced_single_aisle' / 'output.dat' cmd = f'aviary fortran_to_aviary {filepath} -o {outfile} -l FLOPS' self.run_and_test_cmd(cmd) class convert_propeller_tableTestCases(CommandEntryPointsTestCases): - """ - aviary convert_prop_table test. The only option is from GASP propeller map to Aviary table. - """ + """aviary convert_prop_table test. The only option is from GASP propeller map to Aviary table.""" def test_GASP_conversion(self): - filepath = self.get_file( - 'models/propellers/PropFan.map') + filepath = self.get_file('models/propellers/PropFan.csv') outfile = Path.cwd() / 'output.dat' cmd = f'aviary convert_prop_table {filepath} {outfile} -f GASP' self.run_and_test_cmd(cmd) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/interface/test/test_download_models.py b/aviary/interface/test/test_download_models.py index 26b629ca16..e4151872dc 100644 --- a/aviary/interface/test/test_download_models.py +++ b/aviary/interface/test/test_download_models.py @@ -1,65 +1,55 @@ -import subprocess +import shutil import unittest from pathlib import Path -import shutil -from aviary.utils.functions import get_aviary_resource_path from openmdao.utils.testing_utils import use_tempdirs + from aviary.interface.download_models import get_model, save_file +from aviary.utils.functions import get_aviary_resource_path @use_tempdirs -class CommandEntryPointsTestCases(unittest.TestCase): - - def run_and_test_hangar(self, filenames, out_dir=''): - # tests that the commands return an exit code of 0 and that the files are generated - if isinstance(filenames, str): - filenames = [filenames] - cmd = ['aviary', 'hangar'] + filenames - +class TestDownloadModels(unittest.TestCase): + def run_and_test_hangar(self, filename, out_dir=''): + # tests that the function runs successfully and that the files are generated if out_dir: - cmd += ['-o', out_dir] out_dir = Path(out_dir) else: out_dir = Path.cwd() / 'aviary_models' - try: - output = subprocess.check_output(cmd) - for filename in filenames: - path = out_dir / filename.split('/')[-1] - self.assertTrue(path.exists()) - except subprocess.CalledProcessError as err: - self.fail(f"Command '{cmd}' failed. Return code: {err.returncode}") + path = get_model(filename) + save_file(path, outdir=out_dir) + path = out_dir / filename.split('/')[-1] + self.assertTrue(path.exists()) def test_single_file_without_path(self): - filename = 'turbofan_22k.deck' + filename = 'turbofan_22k.csv' self.run_and_test_hangar(filename) def test_single_file_with_path(self): - filename = 'engines/turbofan_22k.deck' + filename = 'engines/turbofan_22k.csv' self.run_and_test_hangar(filename) - def test_multiple_files(self): - filenames = ['small_single_aisle_GwGm.dat', 'small_single_aisle_GwGm.csv'] - self.run_and_test_hangar(filenames) - def test_folder(self): filename = 'engines' self.run_and_test_hangar(filename) def test_single_file_custom_outdir(self): - filename = 'small_single_aisle_GwGm.csv' - out_dir = '~/test_hangar' + filename = 'small_single_aisle_GASP.csv' + out_dir = 'test_hangar' self.run_and_test_hangar(filename, out_dir) shutil.rmtree(out_dir) def test_expected_path(self): - aviary_path = get_model('converter_configuration_test_data_GwGm.dat') + aviary_path = get_model('large_single_aisle_1_GASP.dat') expected_path = get_aviary_resource_path( - 'models/test_aircraft/converter_configuration_test_data_GwGm.dat') + 'models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.dat' + ) self.assertTrue(str(aviary_path) == str(expected_path)) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = CommandEntryPointsTestCases() + # test.test_single_file_with_path() diff --git a/aviary/interface/test/test_height_energy_mission.py b/aviary/interface/test/test_height_energy_mission.py index 1c257c23c9..d8a254e2b7 100644 --- a/aviary/interface/test/test_height_energy_mission.py +++ b/aviary/interface/test/test_height_energy_mission.py @@ -1,107 +1,105 @@ -from copy import deepcopy import os -import unittest import subprocess +import sys +import unittest +from copy import deepcopy -from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs +from io import StringIO +import dymos from openmdao.core.problem import _clear_problem_names from openmdao.utils.reports_system import clear_reports +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from aviary.interface.methods_for_level1 import run_aviary from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.mission.flops_based.phases.energy_phase import EnergyPhase from aviary.subsystems.test.test_dummy_subsystem import ArrayGuessSubsystemBuilder -from aviary.mission.energy_phase import EnergyPhase from aviary.variable_info.variables import Dynamic @use_tempdirs class AircraftMissionTestSuite(unittest.TestCase): - def setUp(self): - # Load the phase_info and other common setup tasks self.phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.2, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.18, 0.74), "unitless"), - "initial_altitude": (0.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((0.0, 34000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((64.0, 192.0), "min"), + 'pre_mission': {'include_takeoff': False, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.2, 'unitless'), + 'mach_bounds': ((0.18, 0.74), 'unitless'), + 'mach_polynomial_order': 1, + 'altitude_optimize': False, + 'altitude_initial': (0.0, 'ft'), + 'altitude_bounds': ((0.0, 34000.0), 'ft'), + 'altitude_polynomial_order': 1, + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((64.0, 192.0), 'min'), + }, + 'initial_guesses': { + 'time': ([0, 128], 'min'), + 'mach': ([0.2, 0.72], 'unitless'), + 'altitude': ([0, 32000.0], 'ft'), }, - "initial_guesses": {"time": ([0, 128], "min")}, }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (34000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((56.5, 169.5), "min"), + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'mach_polynomial_order': 1, + 'altitude_optimize': False, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'altitude_polynomial_order': 1, + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((64.0, 192.0), 'min'), + 'time_duration_bounds': ((56.5, 169.5), 'min'), + }, + 'initial_guesses': { + 'time': ([128, 113], 'min'), + 'mach': ([0.72, 0.72], 'unitless'), + 'altitude': ([32000, 34000.0], 'ft'), }, - "initial_guesses": {"time": ([128, 113], "min")}, }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.36, "unitless"), - "mach_bounds": ((0.34, 0.74), "unitless"), - "initial_altitude": (34000.0, "ft"), - "final_altitude": (500.0, "ft"), - "altitude_bounds": ((0.0, 38000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((29.0, 87.0), "min"), + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.36, 'unitless'), + 'mach_bounds': ((0.34, 0.74), 'unitless'), + 'mach_polynomial_order': 1, + 'altitude_optimize': False, + 'altitude_initial': (34000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'altitude_bounds': ((0.0, 38000.0), 'ft'), + 'altitude_polynomial_order': 1, + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((120.5, 361.5), 'min'), + 'time_duration_bounds': ((29.0, 87.0), 'min'), + }, + 'initial_guesses': { + 'time': ([241, 58], 'min'), }, - "initial_guesses": {"time": ([241, 58], "min")}, }, - "post_mission": { - "include_landing": False, - "constrain_range": True, - "target_range": (1906, "nmi"), + 'post_mission': { + 'include_landing': False, + 'constrain_range': True, + 'target_range': (1906, 'nmi'), }, } - self.aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' + self.aircraft_definition_file = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' self.make_plots = False self.max_iter = 100 @@ -110,9 +108,7 @@ def setUp(self): clear_reports() def add_external_subsystem(self, phase_info, subsystem_builder): - """ - Add an external subsystem to all phases in the mission. - """ + """Add an external subsystem to all phases in the mission.""" for phase in phase_info: if 'user_options' in phase_info[phase]: if 'external_subsystems' not in phase_info[phase]: @@ -126,7 +122,6 @@ def run_mission(self, phase_info, optimizer): make_plots=self.make_plots, max_iter=self.max_iter, optimizer=optimizer, - optimization_history_filename="driver_test.db", verbosity=0, ) @@ -136,98 +131,106 @@ def test_mission_basic_and_dashboard(self): # But we need to remember whether it was set so we can restore it testflo_running = os.environ.pop('TESTFLO_RUNNING', None) - prob = self.run_mission(self.phase_info, "SLSQP") + prob = self.run_mission(self.phase_info, 'SLSQP') # restore what was there before running the test if testflo_running is not None: os.environ['TESTFLO_RUNNING'] = testflo_running self.assertIsNotNone(prob) - self.assertTrue(prob.problem_ran_successfully) + self.assertTrue(prob.result.success) - cmd = ( - 'aviary dashboard --problem_recorder dymos_solution.db --driver_recorder ' - f'driver_test.db {prob.driver._problem()._name}' - ) + cmd = f'aviary dashboard {prob.driver._problem()._name}' # this only tests that a given command line tool returns a 0 return code. It doesn't # check the expected output at all. The underlying functions that implement the - # commands should be tested seperately. + # commands should be tested separately. try: subprocess.check_output(cmd.split()) except subprocess.CalledProcessError as err: self.fail("Command '{}' failed. Return code: {}".format(cmd, err.returncode)) - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_mission_basic_pyopt(self): - prob = self.run_mission(self.phase_info, "IPOPT") + prob = self.run_mission(self.phase_info, 'IPOPT') self.assertIsNotNone(prob) - self.assertTrue(prob.problem_ran_successfully) + self.assertTrue(prob.result.success) - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_mission_optimize_mach_only(self): - # Test with optimize_mach flag set to True + # Test with mach_optimize flag set to True modified_phase_info = self.phase_info.copy() - for phase in ["climb", "cruise", "descent"]: - modified_phase_info[phase]["user_options"]["optimize_mach"] = True - prob = self.run_mission(modified_phase_info, "IPOPT") - self.assertTrue(prob.problem_ran_successfully) + for phase in ['climb', 'cruise', 'descent']: + modified_phase_info[phase]['user_options']['mach_optimize'] = True + prob = self.run_mission(modified_phase_info, 'IPOPT') + self.assertTrue(prob.result.success) - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_mission_optimize_altitude_and_mach(self): - # Test with optimize_altitude flag set to True + # Test with altitude_optimize flag set to True modified_phase_info = self.phase_info.copy() - for phase in ["climb", "cruise", "descent"]: - modified_phase_info[phase]["user_options"]["optimize_altitude"] = True - modified_phase_info[phase]["user_options"]["optimize_mach"] = True + for phase in ['climb', 'cruise', 'descent']: + modified_phase_info[phase]['user_options']['altitude_optimize'] = True + modified_phase_info[phase]['user_options']['mach_optimize'] = True modified_phase_info['climb']['user_options']['constraints'] = { - Dynamic.Mission.THROTTLE: { + Dynamic.Vehicle.Propulsion.THROTTLE: { 'lower': 0.2, 'upper': 0.9, 'type': 'path', }, } - prob = self.run_mission(modified_phase_info, "IPOPT") - self.assertTrue(prob.problem_ran_successfully) + prob = self.run_mission(modified_phase_info, 'IPOPT') + self.assertTrue(prob.result.success) + + try: + numeric, rel = dymos.__version__.split('-') + except ValueError: + numeric = dymos.__version__ + dm_version = tuple([int(s) for s in numeric.split('.')]) + + if dm_version <= (1, 12, 0): + con_name = 'traj.climb.throttle[path]' + else: + con_name = 'traj.phases.climb->path_constraint->throttle' constraints = prob.driver._cons for name, meta in constraints.items(): - if 'traj.phases.climb->path_constraint->throttle' in name: + if con_name in name: self.assertEqual(meta['upper'], 0.9) self.assertEqual(meta['lower'], 0.2) - @require_pyoptsparse(optimizer="IPOPT") - def test_mission_optimize_altitude_only(self): - # Test with optimize_altitude flag set to True + @require_pyoptsparse(optimizer='IPOPT') + def test_mission_altitude_optimize_only(self): + # Test with altitude_optimize flag set to True modified_phase_info = self.phase_info.copy() - for phase in ["climb", "cruise", "descent"]: - modified_phase_info[phase]["user_options"]["optimize_altitude"] = True - prob = self.run_mission(modified_phase_info, "IPOPT") - self.assertTrue(prob.problem_ran_successfully) + for phase in ['climb', 'cruise', 'descent']: + modified_phase_info[phase]['user_options']['altitude_optimize'] = True + prob = self.run_mission(modified_phase_info, 'IPOPT') + self.assertTrue(prob.result.success) - @require_pyoptsparse(optimizer="IPOPT") - def test_mission_solve_for_distance_IPOPT(self): + @require_pyoptsparse(optimizer='IPOPT') + def test_mission_distance_solve_segments_IPOPT(self): modified_phase_info = self.phase_info.copy() - for phase in ["climb", "cruise", "descent"]: - modified_phase_info[phase]["user_options"]["solve_for_distance"] = True - prob = self.run_mission(modified_phase_info, "IPOPT") - self.assertTrue(prob.problem_ran_successfully) + for phase in ['climb', 'cruise', 'descent']: + modified_phase_info[phase]['user_options']['distance_solve_segments'] = True + prob = self.run_mission(modified_phase_info, 'IPOPT') + self.assertTrue(prob.result.success) - def test_mission_solve_for_distance_SLSQP(self): + def test_mission_distance_solve_segments_SLSQP(self): modified_phase_info = self.phase_info.copy() - for phase in ["climb", "cruise", "descent"]: - modified_phase_info[phase]["user_options"]["solve_for_distance"] = True - prob = self.run_mission(modified_phase_info, "SLSQP") - self.assertTrue(prob.problem_ran_successfully) + for phase in ['climb', 'cruise', 'descent']: + modified_phase_info[phase]['user_options']['distance_solve_segments'] = True + prob = self.run_mission(modified_phase_info, 'SLSQP') + self.assertTrue(prob.result.success) - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_mission_with_external_subsystem(self): # Test mission with an external subsystem added to each phase modified_phase_info = self.phase_info.copy() dummy_subsystem_builder = ArrayGuessSubsystemBuilder() self.add_external_subsystem(modified_phase_info, dummy_subsystem_builder) - prob = self.run_mission(modified_phase_info, "IPOPT") - self.assertTrue(prob.problem_ran_successfully) + prob = self.run_mission(modified_phase_info, 'IPOPT') + self.assertTrue(prob.result.success) def test_custom_phase_builder(self): local_phase_info = self.phase_info.copy() @@ -243,7 +246,7 @@ def test_custom_phase_builder(self): def test_custom_phase_builder_error(self): local_phase_info = self.phase_info.copy() - local_phase_info['climb']['phase_builder'] = "fake phase object" + local_phase_info['climb']['phase_builder'] = 'fake phase object' with self.assertRaises(TypeError): run_aviary( @@ -259,13 +262,13 @@ def test_support_constraint_aliases(self): modified_phase_info = deepcopy(self.phase_info) modified_phase_info['climb']['user_options']['constraints'] = { 'throttle_1': { - 'target': Dynamic.Mission.THROTTLE, + 'target': Dynamic.Vehicle.Propulsion.THROTTLE, 'equals': 0.2, 'loc': 'initial', 'type': 'boundary', }, 'throttle_2': { - 'target': Dynamic.Mission.THROTTLE, + 'target': Dynamic.Vehicle.Propulsion.THROTTLE, 'equals': 0.8, 'loc': 'final', 'type': 'boundary', @@ -274,28 +277,70 @@ def test_support_constraint_aliases(self): prob = AviaryProblem() - csv_path = "models/test_aircraft/aircraft_for_bench_FwFm.csv" + csv_path = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' prob.load_inputs(csv_path, modified_phase_info) prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() + prob.build_model() prob.setup() - prob.set_initial_guesses() prob.run_model() prob_vars = prob.list_problem_vars() cons = {key: val for (key, val) in prob_vars['constraints']} - con1 = cons['traj.phases.climb->initial_boundary_constraint->throttle_1'] - con2 = cons['traj.phases.climb->final_boundary_constraint->throttle_2'] + + try: + numeric, rel = dymos.__version__.split('-') + except ValueError: + numeric = dymos.__version__ + dm_version = tuple([int(s) for s in numeric.split('.')]) + + if dm_version <= (1, 12, 0): + con1 = cons['traj.phases.climb->initial_boundary_constraint->throttle_1'] + con2 = cons['traj.phases.climb->final_boundary_constraint->throttle_2'] + else: + con1 = cons['traj.climb.throttle_1[initial]'] + con2 = cons['traj.climb.throttle_2[final]'] self.assertEqual(con1['name'], 'timeseries.throttle_1') self.assertEqual(con2['name'], 'timeseries.throttle_2') + def test_trajectory_warning(self): + modified_phase_info = deepcopy(self.phase_info) + modified_phase_info['climb']['user_options']['altitude_final'] = (1000.0, 'ft') + modified_phase_info['cruise']['user_options']['mach_final'] = (0.5, 'unitless') + prob = AviaryProblem(verbosity=1) + + csv_path = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' + + prob.load_inputs(csv_path, modified_phase_info) + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() + prob.add_phases() + prob.add_post_mission_systems() + + stdout = sys.stdout + strout = StringIO() + sys.stdout = strout + try: + prob.link_phases() + finally: + sys.stdout = stdout + output = strout.getvalue().split('\n') + + print('z') + + self.assertEqual( + output[1], 'The following issues were detected in your phase_info options.' + ) + self.assertEqual(output[2], ' Constraint mismatch across phase boundary:') + self.assertEqual(output[3], " climb altitude_final: (1000.0, 'ft')") + self.assertEqual(output[4], " cruise altitude_initial: (32000.0, 'ft')") + self.assertEqual(output[5], ' Constraint mismatch across phase boundary:') + self.assertEqual(output[6], " cruise mach_final: (0.5, 'unitless')") + self.assertEqual(output[7], " descent mach_initial: (0.72, 'unitless')") + if __name__ == '__main__': unittest.main() diff --git a/aviary/interface/test/test_installation_test.py b/aviary/interface/test/test_installation_test.py new file mode 100644 index 0000000000..2f57c77177 --- /dev/null +++ b/aviary/interface/test/test_installation_test.py @@ -0,0 +1,13 @@ +import unittest + +from aviary.interface.test_installation import _exec_installation_test + + +class test_installation(unittest.TestCase): + def test_installation(self): + success = _exec_installation_test(None, None) + assert success + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/interface/test/test_interface_bugs.py b/aviary/interface/test/test_interface_bugs.py index dbab7e2473..14ba6b566f 100644 --- a/aviary/interface/test/test_interface_bugs.py +++ b/aviary/interface/test/test_interface_bugs.py @@ -1,27 +1,23 @@ -from copy import deepcopy import unittest +from copy import deepcopy import openmdao.api as om +from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.models.aircraft.test_aircraft.GwFm_phase_info import phase_info as ph_in from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.interface.default_phase_info.height_energy import phase_info as ph_in -from aviary.variable_info.variables import Aircraft from aviary.utils.functions import get_aviary_resource_path -from openmdao.utils.testing_utils import use_tempdirs +from aviary.variable_info.variables import Aircraft class WingWeightSubsys(om.ExplicitComponent): - def setup(self): - self.add_input(Aircraft.Engine.MASS, 1.0, units='lbm') self.add_output(Aircraft.Canard.ASPECT_RATIO, 1.0, units='unitless') self.add_output('Tail', 1.0, units='unitless') - self.declare_partials( - Aircraft.Canard.ASPECT_RATIO, Aircraft.Engine.MASS, val=2.0 - ) + self.declare_partials(Aircraft.Canard.ASPECT_RATIO, Aircraft.Engine.MASS, val=2.0) self.declare_partials('Tail', Aircraft.Engine.MASS, val=0.7) def compute(self, inputs, outputs): @@ -30,15 +26,13 @@ def compute(self, inputs, outputs): class WingWeightBuilder(SubsystemBuilderBase): - """ - Prototype of a subsystem that overrides an aviary internally computed var. - """ + """Prototype of a subsystem that overrides an aviary internally computed var.""" def __init__(self, name='wing_weight'): super().__init__(name) - def build_post_mission(self, aviary_inputs): - ''' + def build_post_mission(self, aviary_inputs, phase_info, phase_mission_bus_lengths): + """ Build an OpenMDAO system for the pre-mission computations of the subsystem. Returns @@ -47,12 +41,12 @@ def build_post_mission(self, aviary_inputs): An OpenMDAO system containing all computations that need to happen in the pre-mission part of the Aviary problem. This includes sizing, design, and other non-mission parameters. - ''' + """ wing_group = om.Group() wing_group.add_subsystem( - "aerostructures", + 'aerostructures', WingWeightSubsys(), - promotes_inputs=["aircraft:*"], + promotes_inputs=['aircraft:*'], promotes_outputs=[ Aircraft.Canard.ASPECT_RATIO, ('Tail', Aircraft.Canard.WETTED_AREA_SCALER), @@ -63,42 +57,67 @@ def build_post_mission(self, aviary_inputs): @use_tempdirs class PreMissionGroupTest(unittest.TestCase): - def test_post_mission_promotion(self): phase_info = deepcopy(ph_in) phase_info['post_mission'] = {} phase_info['post_mission']['include_landing'] = False phase_info['post_mission']['external_subsystems'] = [ - WingWeightBuilder(name="wing_external") + WingWeightBuilder(name='wing_external') ] prob = AviaryProblem() csv_path = get_aviary_resource_path( - 'models/test_aircraft/aircraft_for_bench_GwFm.csv' + 'models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv' ) prob.load_inputs(csv_path, phase_info) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() + prob.build_model() - prob.add_phases() + prob.add_driver('SLSQP', verbosity=0) - prob.add_post_mission_systems() + prob.add_design_variables() - # Link phases and variables + prob.add_objective(objective_type='mass', ref=-1e5) + + prob.setup() + + def test_serial_phase_group(self): + phase_info = deepcopy(ph_in) + phase_info['post_mission'] = {} + phase_info['post_mission']['include_landing'] = False + phase_info['post_mission']['external_subsystems'] = [ + WingWeightBuilder(name='wing_external') + ] + + prob = AviaryProblem() + + csv_path = get_aviary_resource_path( + 'models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv' + ) + prob.load_inputs(csv_path, phase_info) + + prob.check_and_preprocess_inputs() + + prob.add_pre_mission_systems() + prob.add_phases(parallel_phases=False) + prob.add_post_mission_systems() prob.link_phases() - prob.add_driver("SLSQP", verbosity=0) + prob.add_driver('SLSQP', verbosity=0) prob.add_design_variables() - prob.add_objective(objective_type="mass", ref=-1e5) + prob.add_objective(objective_type='mass', ref=-1e5) prob.setup() + assert not isinstance( + prob.model.traj.phases, om.ParallelGroup + ) # TODO: redo for multimissions + if __name__ == '__main__': unittest.main() diff --git a/aviary/interface/test/test_json.py b/aviary/interface/test/test_json.py deleted file mode 100644 index 7b6ac524f4..0000000000 --- a/aviary/interface/test/test_json.py +++ /dev/null @@ -1,69 +0,0 @@ -import unittest -from pathlib import Path -from copy import deepcopy - -from aviary.utils.functions import get_aviary_resource_path -from openmdao.utils.testing_utils import use_tempdirs -import aviary.api as av -from aviary.interface.default_phase_info.height_energy import phase_info, phase_info_parameterization - - -local_phase_info = deepcopy(phase_info) - - -@use_tempdirs -class TestJson(unittest.TestCase): - """ - These tests just check that the json files can be saved or loaded - They don't check that the files were properly created or that the - off-design mission ran correctly. - run_off_design_example.py in aviary/examples tests the full functionality - """ - - def get_file(self, filename): - filepath = get_aviary_resource_path(filename) - if not Path(filepath).exists(): - self.skipTest(f"couldn't find {filepath}") - return filepath - - def setUp(self): - self.prob = prob = av.AviaryProblem() - # Load aircraft and options data from user - # Allow for user overrides here - prob.load_inputs( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', local_phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases(phase_info_parameterization=phase_info_parameterization) - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - prob.add_driver('SLSQP', max_iter=0) - prob.add_design_variables() - - # Load optimization problem formulation - # Detail which variables the optimizer can control - prob.add_objective() - prob.setup() - prob.set_initial_guesses() - - def test_save_json(self): - self.prob.run_aviary_problem() - self.prob.save_sizing_to_json() - - def test_alternate(self): - filepath = self.get_file('interface/test/sizing_problem_for_test.json') - prob_alternate = self.prob.alternate_mission( - run_mission=False, json_filename=filepath, phase_info=local_phase_info) - - def test_fallout(self): - filepath = self.get_file('interface/test/sizing_problem_for_test.json') - prob_fallout = self.prob.fallout_mission( - run_mission=False, json_filename=filepath, phase_info=local_phase_info) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/interface/test/test_linkage_logic.py b/aviary/interface/test/test_linkage_logic.py index 781ef562c6..1ddec8e4af 100644 --- a/aviary/interface/test/test_linkage_logic.py +++ b/aviary/interface/test/test_linkage_logic.py @@ -1,113 +1,105 @@ -import unittest import copy +import unittest -from openmdao.utils.testing_utils import use_tempdirs from openmdao.core.problem import _clear_problem_names +from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem @use_tempdirs class AircraftMissionTestSuite(unittest.TestCase): - def setUp(self): cruise_dict = { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (32000.0, "ft"), - "final_altitude": (34000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((56.5, 169.5), "min"), + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (34000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((64.0, 192.0), 'min'), + 'time_duration_bounds': ((56.5, 169.5), 'min'), }, } cruise_dicts = [copy.deepcopy(cruise_dict) for _ in range(5)] for i, cruise_dict in enumerate(cruise_dicts): - cruise_dict["user_options"]["initial_bounds"] = ( - (64.0 + i*10, 192.0 + i*10), "min") - cruise_dict["user_options"]["duration_bounds"] = ( - (56.5 + i*10, 169.5 + i*10), "min") - cruise_dicts[0]["user_options"]["optimize_mach"] = True - cruise_dicts[1]["user_options"]["optimize_mach"] = True - cruise_dicts[4]["user_options"]["optimize_mach"] = True - cruise_dicts[2]["user_options"]["optimize_altitude"] = True - cruise_dicts[3]["user_options"]["optimize_altitude"] = True + cruise_dict['user_options']['time_initial_bounds'] = ( + (64.0 + i * 10, 192.0 + i * 10), + 'min', + ) + cruise_dict['user_options']['time_duration_bounds'] = ( + (56.5 + i * 10, 169.5 + i * 10), + 'min', + ) + cruise_dicts[0]['user_options']['mach_optimize'] = True + cruise_dicts[1]['user_options']['mach_optimize'] = True + cruise_dicts[4]['user_options']['mach_optimize'] = True + cruise_dicts[2]['user_options']['altitude_optimize'] = True + cruise_dicts[3]['user_options']['altitude_optimize'] = True # Create the phase_info self.phase_info = { - "pre_mission": {"include_takeoff": False, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.2, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.18, 0.74), "unitless"), - "initial_altitude": (0.0, "ft"), - "final_altitude": (32000.0, "ft"), - "altitude_bounds": ((0.0, 34000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((64.0, 192.0), "min"), + 'pre_mission': {'include_takeoff': False, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.2, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.18, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (0.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'altitude_bounds': ((0.0, 34000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((64.0, 192.0), 'min'), }, }, - "cruise0": cruise_dicts[0], - "cruise1": cruise_dicts[1], - "cruise2": cruise_dicts[2], - "cruise3": cruise_dicts[3], - "cruise4": cruise_dicts[4], - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.36, "unitless"), - "mach_bounds": ((0.34, 0.74), "unitless"), - "initial_altitude": (34000.0, "ft"), - "final_altitude": (500.0, "ft"), - "altitude_bounds": ((0.0, 38000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((29.0, 87.0), "min"), + 'cruise0': cruise_dicts[0], + 'cruise1': cruise_dicts[1], + 'cruise2': cruise_dicts[2], + 'cruise3': cruise_dicts[3], + 'cruise4': cruise_dicts[4], + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.36, 'unitless'), + 'mach_bounds': ((0.34, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (34000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'altitude_bounds': ((0.0, 38000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((120.5, 361.5), 'min'), + 'time_duration_bounds': ((29.0, 87.0), 'min'), }, }, - "post_mission": { - "include_landing": False, - "constrain_range": True, - "target_range": (1906, "nmi"), + 'post_mission': { + 'include_landing': False, + 'constrain_range': True, + 'target_range': (1906, 'nmi'), }, } - self.aircraft_definition_file = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' + self.aircraft_definition_file = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' self.make_plots = False self.max_iter = 0 @@ -120,17 +112,9 @@ def test_linkages(self): # Allow for user overrides here prob.load_inputs(self.aircraft_definition_file, self.phase_info) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() + prob.build_model() prob.add_driver('SLSQP', verbosity=0) @@ -142,8 +126,6 @@ def test_linkages(self): prob.setup() - prob.set_initial_guesses() - prob.run_aviary_problem(run_driver=False, make_plots=False) constraints = prob.model.get_constraints() @@ -171,14 +153,15 @@ def get_linkage_string(phase_1, var, phase_2): for phase_1, var, phase_2 in linkage_data: linkage_string = get_linkage_string(phase_1, var, phase_2) - self.assertIn(linkage_string, constraints, - f"Linkage {linkage_string} is missing") + self.assertIn(linkage_string, constraints, f'Linkage {linkage_string} is missing') for phase_1, var, phase_2 in not_linkage_data: linkage_string = get_linkage_string(phase_1, var, phase_2) - self.assertNotIn(linkage_string, constraints, - f"Linkage {linkage_string} is present") + self.assertNotIn(linkage_string, constraints, f'Linkage {linkage_string} is present') if __name__ == '__main__': unittest.main() + # test = AircraftMissionTestSuite() + # test.setUp() + # test.test_linkages() diff --git a/aviary/interface/test/test_phase_info.py b/aviary/interface/test/test_phase_info.py index 9d4c0aca91..d1fe74f89e 100644 --- a/aviary/interface/test/test_phase_info.py +++ b/aviary/interface/test/test_phase_info.py @@ -2,95 +2,39 @@ Test the conversion between phase info and phase builder to ensure consistency and correctness. """ + import unittest from copy import deepcopy from openmdao.utils.assert_utils import assert_near_equal - -from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_two_dof -from aviary.interface.default_phase_info.two_dof import phase_info_parameterization as phase_info_parameterization_two_dof -from aviary.interface.default_phase_info.height_energy import phase_info as ph_in_height_energy -from aviary.interface.default_phase_info.height_energy import phase_info_parameterization as phase_info_parameterization_height_energy +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.models.missions.height_energy_default import ( + phase_info as ph_in_height_energy, +) +from aviary.models.missions.height_energy_default import ( + phase_info_parameterization as phase_info_parameterization_height_energy, +) +from aviary.models.missions.two_dof_default import phase_info as ph_in_two_dof +from aviary.models.missions.two_dof_default import ( + phase_info_parameterization as phase_info_parameterization_two_dof, +) from aviary.interface.methods_for_level2 import AviaryProblem - -from aviary.mission.phase_builder_base import \ - PhaseBuilderBase as PhaseBuilder, phase_info_to_builder -from aviary.variable_info.variables import Aircraft, Mission - - -class TestPhaseInfo(unittest.TestCase): - - def _test_phase_info_dict(self, phase_info_dict, name): - """Helper method to test a given phase_info dict""" - - _climb_info = (name, phase_info_dict[name]) - - # Removing the 'fix_duration' key from user_options for test comparison - _climb_info[1]['user_options'].pop('fix_duration') - - # Convert phase info to a phase builder - _phase_builder: PhaseBuilder = phase_info_to_builder(*_climb_info) - - # Convert back the phase builder to phase info - _phase_builder_info = _phase_builder.to_phase_info() - - if _climb_info != _phase_builder_info: - lhs_name, lhs_info = _climb_info - rhs_name, rhs_info = _phase_builder_info - - if lhs_name != rhs_name: - raise RuntimeError(f'name mismatch: {lhs_name} != {rhs_name}') - - lhs_keys = set(sorted(set(lhs_info.keys()))) - rhs_keys = set(sorted(set(rhs_info.keys()))) - - common = lhs_keys & rhs_keys - lhs_unique = lhs_keys - common - - if lhs_keys != rhs_keys: - if not common: - raise RuntimeError( - f'key mismatch: no keys in common: {lhs_keys} != {rhs_keys}') - if lhs_unique: - raise RuntimeError( - 'key mismatch: the new builder is missing the following keys:' f' {lhs_unique}') - - # Loop through each key to compare values - for key in lhs_keys: - lhs_value = lhs_info[key] - rhs_value = rhs_info[key] - - if lhs_value != rhs_value: - if key in ['user_options', 'initial_guesses']: - for name in lhs_value: - lhs_option = lhs_value[name] - rhs_option = rhs_value[name] - - if lhs_option != rhs_option: - raise RuntimeError( - f'value mismatch ({key}[{name}]):' f' {lhs_option} != {rhs_option}') - else: - raise RuntimeError( - f'value mismatch ({key}): {lhs_value} != {rhs_value}') - - def test_default_phase_height_energy(self): - """Tests the roundtrip conversion for default_phase_info.height_energy""" - from aviary.interface.default_phase_info.height_energy import phase_info - local_phase_info = deepcopy(phase_info) - self._test_phase_info_dict(local_phase_info, 'cruise') +from aviary.mission.phase_builder_base import PhaseBuilderBase as PhaseBuilder +from aviary.mission.phase_builder_base import phase_info_to_builder +from aviary.variable_info.variables import Mission +@use_tempdirs class TestParameterizePhaseInfo(unittest.TestCase): - def test_phase_info_parameterization_two_dof(self): phase_info = deepcopy(ph_in_two_dof) prob = AviaryProblem() - csv_path = "models/small_single_aisle/small_single_aisle_GwGm.csv" + csv_path = 'models/aircraft/small_single_aisle/small_single_aisle_GASP.csv' prob.load_inputs(csv_path, phase_info) - prob.check_and_preprocess_inputs() # We can set some crazy vals, since we aren't going to optimize. prob.aviary_inputs.set_val(Mission.Design.RANGE, 5000, 'km') @@ -98,6 +42,8 @@ def test_phase_info_parameterization_two_dof(self): prob.aviary_inputs.set_val(Mission.Design.GROSS_MASS, 120000, 'lbm') prob.aviary_inputs.set_val(Mission.Design.MACH, 0.6, 'unitless') + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() prob.add_phases(phase_info_parameterization=phase_info_parameterization_two_dof) prob.add_post_mission_systems() @@ -105,53 +51,86 @@ def test_phase_info_parameterization_two_dof(self): prob.link_phases() prob.setup() - prob.set_initial_guesses() prob.run_model() - assert_near_equal(prob.get_val("traj.desc2.timeseries.input_values:distance", units='km')[-1], - 5000.0) - assert_near_equal(prob.get_val("traj.climb2.timeseries.input_values:altitude", units='ft')[-1], - 31000.0) - assert_near_equal(prob.get_val("traj.groundroll.timeseries.input_values:mass", units='lbm')[0], - 120000.0) - assert_near_equal(prob.get_val("traj.cruise.rhs.mach")[0], - 0.6) + assert_near_equal( + prob.get_val('traj.desc2.timeseries.input_values:distance', units='km')[-1], 5000.0 + ) + assert_near_equal( + prob.get_val('traj.climb2.timeseries.input_values:altitude', units='ft')[-1], 31000.0 + ) + assert_near_equal( + prob.get_val('traj.groundroll.timeseries.input_values:mass', units='lbm')[0], 120000.0 + ) + assert_near_equal(prob.get_val('traj.cruise.rhs.mach')[0], 0.6) def test_phase_info_parameterization_height_energy(self): phase_info = deepcopy(ph_in_height_energy) prob = AviaryProblem() - csv_path = "models/test_aircraft/aircraft_for_bench_FwFm.csv" + csv_path = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' prob.load_inputs(csv_path, phase_info) - prob.check_and_preprocess_inputs() # We can set some crazy vals, since we aren't going to optimize. - prob.aviary_inputs.set_val(Mission.Design.RANGE, 5000., 'km') - prob.aviary_inputs.set_val(Mission.Design.CRUISE_ALTITUDE, 31000., units='ft') - prob.aviary_inputs.set_val(Mission.Design.GROSS_MASS, 195000., 'lbm') + prob.aviary_inputs.set_val(Mission.Design.RANGE, 5000.0, 'km') + prob.aviary_inputs.set_val(Mission.Design.CRUISE_ALTITUDE, 31000.0, units='ft') + prob.aviary_inputs.set_val(Mission.Design.GROSS_MASS, 195000.0, 'lbm') prob.aviary_inputs.set_val(Mission.Summary.CRUISE_MACH, 0.6, 'unitless') + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() - prob.add_phases( - phase_info_parameterization=phase_info_parameterization_height_energy) + prob.add_phases(phase_info_parameterization=phase_info_parameterization_height_energy) prob.add_post_mission_systems() prob.link_phases() prob.setup() - prob.set_initial_guesses() prob.run_model() range_resid = prob.get_val(Mission.Constraints.RANGE_RESIDUAL, units='nmi')[-1] assert_near_equal(range_resid, 1906, tolerance=1e-3) - assert_near_equal(prob.get_val("traj.cruise.timeseries.altitude", units='ft')[0], - 31000.0) - assert_near_equal(prob.get_val("traj.cruise.timeseries.mach")[0], - 0.6) + assert_near_equal(prob.get_val('traj.cruise.timeseries.altitude', units='ft')[0], 31000.0) + assert_near_equal(prob.get_val('traj.cruise.timeseries.mach')[0], 0.6) + + +@use_tempdirs +class TestPhaseInfoAPI(unittest.TestCase): + def test_time_duration(self): + phase_info = { + 'pre_mission': {'include_takeoff': False, 'optimize_mass': False}, + 'only_cruise': { + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'time_duration': (77, 's'), + }, + }, + } + prob = AviaryProblem() + + csv_path = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' + + prob.load_inputs(csv_path, phase_info) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_aviary_problem() + + time = prob.get_val('traj.only_cruise.timeseries.time', units='s')[-1] + assert_near_equal(time, 77.0, 1e-5) # To run the tests diff --git a/aviary/interface/test/test_preprocess.py b/aviary/interface/test/test_preprocess.py new file mode 100644 index 0000000000..f5e20ae5ec --- /dev/null +++ b/aviary/interface/test/test_preprocess.py @@ -0,0 +1,41 @@ +""" +Test preprocessing as part of the level 2 interface. +""" + +from copy import deepcopy +import unittest + +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.models.aircraft.advanced_single_aisle.phase_info import phase_info +from aviary.variable_info.variables import Aircraft + + +@use_tempdirs +class TestLevel2Preprocessing(unittest.TestCase): + def test_crew_preprocessing(self): + # Test that flight-crew preprocesses correctly. + prob = AviaryProblem() + local_phase_info = deepcopy(phase_info) + + prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', + local_phase_info, + ) + + prob.check_and_preprocess_inputs() + aviary_inputs = prob.aviary_inputs + + num_flight_crew = aviary_inputs.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) + self.assertEqual(num_flight_crew, 3) + + num_flight_attendants = aviary_inputs.get_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS) + self.assertEqual(num_flight_attendants, 4) + + num_galley_crew = aviary_inputs.get_val(Aircraft.CrewPayload.NUM_GALLEY_CREW) + self.assertEqual(num_galley_crew, 1) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/interface/test/test_reports.py b/aviary/interface/test/test_reports.py new file mode 100644 index 0000000000..c21bc18329 --- /dev/null +++ b/aviary/interface/test/test_reports.py @@ -0,0 +1,135 @@ +import csv +import unittest +from copy import deepcopy +from pathlib import Path + +import openmdao.api as om +from openmdao.core.problem import _clear_problem_names +from openmdao.utils.testing_utils import set_env_vars, use_tempdirs + +from aviary.models.missions.height_energy_default import phase_info +from aviary.interface.methods_for_level1 import run_aviary +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase +from aviary.utils.develop_metadata import add_meta_data +from aviary.variable_info.variable_meta_data import CoreMetaData + + +@use_tempdirs +class TestReports(unittest.TestCase): + def setUp(self): + om.clear_reports() + _clear_problem_names() + + @set_env_vars(TESTFLO_RUNNING='0', OPENMDAO_REPORTS='timeseries_csv') + def test_timeseries_report(self): + local_phase_info = deepcopy(phase_info) + self.prob = run_aviary( + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', + local_phase_info, + optimizer='SLSQP', + max_iter=0, + ) + + expected_header = [ + 'time (s)', + 'altitude (ft)', + 'altitude_rate (ft/s)', + 'distance (m)', + 'drag (lbf)', + 'electric_power_in_total (kW)', + 'fuel_flow_rate_negative_total (lbm/h)', + 'mach (unitless)', + 'mach_rate (1/s)', + 'mass (kg)', + 'specific_energy_rate_excess (m/s)', + 'throttle (unitless)', + 'thrust_net_total (lbf)', + 'velocity (m/s)', + ] + + expected_rows = [ + [ + '0.0', + '0.0', + '8.333333333333337', + '1.0', + '21108.418300418845', + '0.0', + '-10492.593707324704', + '0.2', + '0.0001354166666666668', + '79560.101698', + '12.350271989430475', + '0.565484286063171', + '28478.788920867584', + '68.05737270077049', + ] + ] + + report_file_path = ( + Path(self.prob.get_reports_dir()).joinpath('mission_timeseries_data.csv').absolute() + ) + with open(report_file_path, mode='r') as csvfile: + csvreader = csv.reader(csvfile) + header = next(csvreader) # Read the header row + + # Validate the header + self.assertEqual(expected_header, header, 'CSV header does not match expected values') + + for expected_row, output_row in zip(expected_rows, csvreader): + for expected_val, output_val in zip(expected_row, output_row): + self.assertAlmostEqual( + float(expected_val), + float(output_val), + places=7, + msg='CSV row value does not match expected value within tolerance', + ) + + @set_env_vars(TESTFLO_RUNNING='0', OPENMDAO_REPORTS='check_input_report') + def test_check_input_report(self): + # Make sure the input check works with custom metadata. + + class ExtraBuilder(SubsystemBuilderBase): + def build_pre_mission(self, aviary_inputs): + comp = om.ExecComp('z = 2*x') + wing_group = om.Group() + wing_group.add_subsystem( + 'aerostructures', + comp, + promotes_inputs=[('x', 'aircraft:custom_var')], + ) + return wing_group + + metadata = deepcopy(CoreMetaData) + local_phase_info = deepcopy(phase_info) + + local_phase_info['pre_mission']['external_subsystems'] = [ExtraBuilder()] + + add_meta_data( + 'aircraft:custom_var', + metadata, + units=None, + desc='testing', + ) + + prob = AviaryProblem() + prob.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', + local_phase_info, + ) + + prob.check_and_preprocess_inputs() + + prob.meta_data = metadata + + prob.build_model() + + prob.setup() + + # no need to run this model, just generate the report. + prob.final_setup() + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/interface/test/test_reserve_support.py b/aviary/interface/test/test_reserve_support.py index 8219c7a6af..0cea403eb7 100644 --- a/aviary/interface/test/test_reserve_support.py +++ b/aviary/interface/test/test_reserve_support.py @@ -1,42 +1,41 @@ -from copy import deepcopy import unittest +from copy import deepcopy from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs +from aviary.models.missions.two_dof_default import phase_info as ph_in_gasp from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.interface.default_phase_info.height_energy import phase_info as ph_in_flops -from aviary.interface.default_phase_info.two_dof import phase_info as ph_in_gasp +from aviary.models.aircraft.test_aircraft.GwFm_phase_info import phase_info as ph_in_flops from aviary.variable_info.variables import Aircraft, Mission +# NOTE this test is probably in the wrong place, it isn't really testing a part of the +# interface. Also test name is `PreMissionGroupTest` which is completely inaccurate. +# This test is for checking if reserve missions are being properly applied, which +# it only partially does (should be checking that the reserve mission properly +# exists in traj as well) @use_tempdirs -class PreMissionGroupTest(unittest.TestCase): - +class ReserveTest(unittest.TestCase): def test_post_mission_promotion(self): phase_info = deepcopy(ph_in_flops) prob = AviaryProblem() - csv_path = "models/test_aircraft/aircraft_for_bench_GwFm.csv" + csv_path = 'models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv' prob.load_inputs(csv_path, phase_info) - prob.check_and_preprocess_inputs() - prob.aviary_inputs.set_val( - Aircraft.Design.RESERVE_FUEL_ADDITIONAL, 10000.0, units='lbm') + prob.aviary_inputs.set_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, 10000.0, units='lbm') - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() + prob.check_and_preprocess_inputs() - prob.link_phases() + prob.build_model() prob.add_design_variables() - prob.add_objective(objective_type="mass", ref=-1e5) + prob.add_objective(objective_type='mass', ref=-1e5) prob.setup() - prob.set_initial_guesses() prob.run_model() @@ -50,29 +49,26 @@ def test_gasp_relative_reserve(self): prob = AviaryProblem() - csv_path = "models/small_single_aisle/small_single_aisle_GwGm.csv" + csv_path = 'models/aircraft/small_single_aisle/small_single_aisle_GASP.csv' prob.load_inputs(csv_path, phase_info) - prob.check_and_preprocess_inputs() prob.aviary_inputs.set_val(Mission.Summary.GROSS_MASS, 140000.0, units='lbm') - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() + prob.check_and_preprocess_inputs() - prob.link_phases() + prob.build_model() prob.add_design_variables() - prob.add_objective(objective_type="mass", ref=-1e5) + prob.add_objective(objective_type='mass', ref=-1e5) prob.setup() - prob.set_initial_guesses() prob.run_model() res_frac = prob.aviary_inputs.get_val( - Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless') + Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless' + ) td_mass = prob.model.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm') reserve = prob.model.get_val(Mission.Design.RESERVE_FUEL, units='lbm') assert_near_equal(reserve, res_frac * (140000.0 - td_mass), 1e-3) diff --git a/aviary/interface/test/test_save_results.py b/aviary/interface/test/test_save_results.py new file mode 100644 index 0000000000..d15e24d863 --- /dev/null +++ b/aviary/interface/test/test_save_results.py @@ -0,0 +1,101 @@ +import unittest +from copy import deepcopy + +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs + +import aviary.api as av +from aviary.interface.methods_for_level2 import reload_aviary_problem +from aviary.models.missions.height_energy_default import phase_info, phase_info_parameterization +from aviary.utils.functions import get_path + + +@use_tempdirs +class TestSizingResults(unittest.TestCase): + """ + These tests just check that the json files for the sizing mission results can be saved or loaded + and used to run an off-design problem without error. These tests don't check that the off-design + mission ran correctly. + """ + + @require_pyoptsparse(optimizer='SLSQP') + def test_save_json(self): + local_phase_info = deepcopy(phase_info) + + prob = av.AviaryProblem() + # Load aircraft and options data from user + # Allow for user overrides here + prob.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', local_phase_info + ) + + # Preprocess inputs + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() + prob.add_phases(phase_info_parameterization=phase_info_parameterization) + prob.add_post_mission_systems() + + # Link phases and variables + prob.link_phases() + prob.add_driver('SLSQP', max_iter=0) + prob.add_design_variables() + + # Load optimization problem formulation + # Detail which variables the optimizer can control + prob.add_objective() + prob.setup() + prob.set_initial_guesses() + prob.run_aviary_problem() + prob.save_results() + + self.compare_files( + 'sizing_results.json', + 'interface/test/sizing_results_for_test.json', + ) + + @require_pyoptsparse(optimizer='IPOPT') + def test_alternate(self): + local_phase_info = deepcopy(phase_info) + + prob = reload_aviary_problem('interface/test/sizing_results_for_test.json') + prob.run_off_design_mission(problem_type='alternate', phase_info=local_phase_info) + + @require_pyoptsparse(optimizer='IPOPT') + def test_fallout(self): + local_phase_info = deepcopy(phase_info) + + prob = reload_aviary_problem('interface/test/sizing_results_for_test.json') + prob.run_off_design_mission(problem_type='fallout', phase_info=local_phase_info) + + def compare_files(self, test_file, validation_file): + """ + Compares the specified file with a validation file. + + Use the `skip_list` input to specify strings that are in lines you want to skip. This is + useful for skipping lines that are expected to differ (such as timestamps) + """ + test_file = get_path(test_file) + + validation_file = get_path(validation_file) + + # Open the converted and validation files + with open(test_file, 'r') as f_in, open(validation_file, 'r') as expected: + for line in f_in: + # Remove whitespace and compare + expected_line = ''.join(expected.readline().split()) + line_no_whitespace = ''.join(line.split()) + + # Assert that the lines are equal + try: + self.assertEqual(line_no_whitespace.count(expected_line), 1) + + except Exception: + exc_string = f'Error: {test_file}\nFound: {line_no_whitespace}\nExpected: {expected_line}' + raise Exception(exc_string) + + +if __name__ == '__main__': + unittest.main() + + # test = TestSizingResults() + # test.test_save_json() + # test.test_fallout() diff --git a/aviary/interface/test/test_timeseries_report.py b/aviary/interface/test/test_timeseries_report.py deleted file mode 100644 index 7b6eb0b606..0000000000 --- a/aviary/interface/test/test_timeseries_report.py +++ /dev/null @@ -1,61 +0,0 @@ -from copy import deepcopy -from pathlib import Path -import unittest -import csv - -import openmdao.api as om -from openmdao.core.problem import _clear_problem_names -from openmdao.utils.testing_utils import use_tempdirs, set_env_vars - -from aviary.interface.default_phase_info.height_energy import phase_info -from aviary.interface.methods_for_level1 import run_aviary - - -@use_tempdirs -class AviaryMissionTimeseries(unittest.TestCase): - def setUp(self): - om.clear_reports() - _clear_problem_names() - - @set_env_vars(TESTFLO_RUNNING='0', OPENMDAO_REPORTS='timeseries_csv') - def test_timeseries_report(self): - local_phase_info = deepcopy(phase_info) - self.prob = run_aviary('models/test_aircraft/aircraft_for_bench_FwFm.csv', - local_phase_info, - optimizer='SLSQP', - max_iter=0) - - expected_header = [ - "time (s)", "altitude (ft)", "altitude_rate (ft/s)", "distance (m)", "drag (lbf)", "electric_power_in_total (kW)", - "fuel_flow_rate_negative_total (lbm/h)", "mach (unitless)", "mach_rate (unitless/s)", - "mass (kg)", "specific_energy_rate_excess (m/s)", "throttle (unitless)", - "thrust_net_total (lbf)", "velocity (m/s)" - ] - - expected_rows = [ - [ - "0.0", "0.0", "8.333333333333337", "1.0", "21108.418300418845", "0.0", - "-10492.593707324704", "0.2", "0.0001354166666666668", "79560.101698", - "12.350271989430475", "0.565484286063171", "28478.788920867584", - "68.05737270077049" - ] - ] - - report_file_path = Path(self.prob.get_reports_dir()).joinpath( - 'mission_timeseries_data.csv').absolute() - with open(report_file_path, mode='r') as csvfile: - csvreader = csv.reader(csvfile) - header = next(csvreader) # Read the header row - - # Validate the header - self.assertEqual(expected_header, header, - "CSV header does not match expected values") - - for expected_row, output_row in zip(expected_rows, csvreader): - for expected_val, output_val in zip(expected_row, output_row): - self.assertAlmostEqual(float(expected_val), float( - output_val), places=7, msg="CSV row value does not match expected value within tolerance") - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/interface/test_installation.py b/aviary/interface/test_installation.py new file mode 100644 index 0000000000..415ae2c161 --- /dev/null +++ b/aviary/interface/test_installation.py @@ -0,0 +1,118 @@ +""" +NOTE this file cannot be a unittest, as testflo is an optional dependency. Instead, a separate + unittest that imports and runs this function exists under interface/tests/test_installation.py. +""" + + +def _setup_installation_test(parser): + """There are no arguments for `aviary check`.""" + pass + + +def _exec_installation_test(args, user_args): + """ + Tests your Aviary installation by importing the API, and then running an example case. + Printouts are provided to explain what was run in the case that there are multiple options, and + a confirmation that the entire run was error free. + + Returns + ------- + success : bool + State of installation tests: True = successful, False = problems with installation + """ + success = True + print('Testing imports:') + # Test that openmdao can be imported + print('Importing OpenMDAO') + try: + from openmdao.utils.testing_utils import use_tempdirs + except ImportError: + print('ERROR: OpenMDAO is not installed') + return False + else: + print('success') + + # Check for pyoptsparse, let user know if it is found or not + print('Importing pyOptSparse') + try: + from pyoptsparse import OPT + except ImportError: + print('pyOptSparse is not installed') + use_pyoptsparse = False + else: + print('success') + use_pyoptsparse = True + + # Check for which optimizers are available + # SLSQP is default + optimizers = ['SLSQP'] + if use_pyoptsparse: + # First test the IPOPT can be found + try: + OPT('IPOPT') + except Exception: + # IPOPT is optional, so it isn't an issue if we don't find it + pass + else: + optimizers.append('IPOPT') + # Next test if SNOPT is available. Use it if so. + try: + OPT('SNOPT') + except Exception: + # SNOPT is optional, so it isn't an issue if we don't find it + pass + else: + optimizers.append('SNOPT') + + # Tell user which optimizers are available + print(f'The following optimizers are available for use: {optimizers}') + optimizer = optimizers[-1] + + # Try importing the Aviary api - there are many files imported here so a large number of errors + # are possible. Catch any exception and show to user. + print('Importing Aviary api') + try: + import aviary.api as av + except Exception as import_error: + print(f'An error occurred while importing Aviary API: {import_error}\n') + return False + else: + print('success') + + @use_tempdirs + def _test_install(optimizer): + """Runs an example Aviary problem using the requested optimizer in a temporary directory.""" + return av.run_aviary( + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', + av.default_height_energy_phase_info, + optimizer=optimizer, + make_plots=False, + verbosity=0, + ) + + print(f'\nRunning a basic Aviary model using the {optimizer} optimizer:') + try: + prob = _test_install(optimizer) + except Exception as error: + print(f'The following error occurred while running the Aviary problem: {error}') + success = False + else: + if prob.result.success: + print('Aviary run successful') + print( + '\nYour Aviary installation is working. Please review the printouts to make sure ' + 'all expected features are present.' + ) + else: + print('Aviary run failed') + print( + '\nYour Aviary installation is not working properly. Please review the printouts ' + 'to determine which step failed.' + ) + success = False + + return success + + +if __name__ == '__main__': + _exec_installation_test(None, None) diff --git a/aviary/interface/utils/markdown_utils.py b/aviary/interface/utils.py similarity index 65% rename from aviary/interface/utils/markdown_utils.py rename to aviary/interface/utils.py index 4f71780547..35b69968ed 100644 --- a/aviary/interface/utils/markdown_utils.py +++ b/aviary/interface/utils.py @@ -1,6 +1,10 @@ -import numpy as np from math import floor, log10 +import numpy as np +import warnings + +from aviary.variable_info.enums import Verbosity + # TODO openMDAO has generate_table() that might be able to replace this # TODO rounding might have other use cases, move to utils if so @@ -11,6 +15,7 @@ def round_it(x, sig=None): """ Round a float to a specified significance. If the number is equal to zero, "0" will be returned, regardless of the number of significant digits specified + If the number is NaN, directly returns it (stays NaN). Parameters ---------- @@ -21,7 +26,8 @@ def round_it(x, sig=None): Returns ------- - The rounded number + The rounded number, or provided string if not convertible to float, or original + number if it is NaN """ # default sig figs to 2 decimal places out if isinstance(x, str): @@ -29,10 +35,16 @@ def round_it(x, sig=None): x = float(x) except ValueError: return x + + if np.isnan(x): + # return NaNs directly back to markdown report + return x + if not sig: - sig = len(str(round(x)))+2 + sig = len(str(round(x))) + 2 + if x != 0: - return round(x, sig-int(floor(log10(abs(x))))-1) + return round(x, sig - int(floor(log10(abs(x)))) - 1) else: return 0 @@ -40,7 +52,7 @@ def round_it(x, sig=None): def write_markdown_variable_table(open_file, problem, outputs, metadata): """ Writes a table of the provided variable names in outputs. Converts units to defaults - from metadata if avaliable. + from metadata if available. Parameters ---------- @@ -84,7 +96,7 @@ def write_markdown_variable_table(open_file, problem, outputs, metadata): # handle rounding + formatting if isinstance(val, (np.ndarray, list, tuple)): val = [round_it(item) for item in val] - # if an interable with a length of 1, remove bracket/paretheses, etc. + # if an interable with a length of 1, remove bracket/parentheses, etc. if len(val) == 1: val = val[0] else: @@ -95,3 +107,38 @@ def write_markdown_variable_table(open_file, problem, outputs, metadata): units = '-' summary_line = f'| {var_name} | {val} | {units} |\n' open_file.write(summary_line) + + +def set_warning_format(verbosity): + # if verbosity not set / not known yet, default to most simple warning format rather than no + # warnings at all + if verbosity is None: + verbosity = Verbosity.BRIEF + + # Reset all warning filters + warnings.resetwarnings() + + # NOTE identity comparison is preferred for Enum but here verbosity is often an int, so we need + # an equality comparison + if verbosity == Verbosity.QUIET: + # Suppress all warnings + warnings.filterwarnings('ignore') + + elif verbosity == Verbosity.BRIEF: + + def simplified_warning(message, category, filename, lineno, line=None): + return f'Warning: {message}\n\n' + + warnings.formatwarning = simplified_warning + warnings.simplefilter('ignore', DeprecationWarning) + + elif verbosity == Verbosity.VERBOSE: + + def simplified_warning(message, category, filename, lineno, line=None): + return f'{category.__name__}: {message}\n\n' + + warnings.formatwarning = simplified_warning + + else: # DEBUG + # use the default warning formatting + warnings.filterwarnings('default') diff --git a/aviary/interface/utils/check_phase_info.py b/aviary/interface/utils/check_phase_info.py deleted file mode 100644 index 6440ce24d0..0000000000 --- a/aviary/interface/utils/check_phase_info.py +++ /dev/null @@ -1,253 +0,0 @@ -from openmdao.utils.units import valid_units -from aviary.variable_info.enums import SpeedType, EquationsOfMotion - -TWO_DEGREES_OF_FREEDOM = EquationsOfMotion.TWO_DEGREES_OF_FREEDOM -HEIGHT_ENERGY = EquationsOfMotion.HEIGHT_ENERGY -SOLVED_2DOF = EquationsOfMotion.SOLVED_2DOF - - -# Define common keys for all phases -common_keys = { - 'num_segments': int, - 'order': int, - 'fix_initial': (bool, dict), -} - -# Common key-values for climb, cruise, and descent -common_entries = { - 'optimize_mach': bool, - 'optimize_altitude': bool, - 'solve_for_distance': bool, - 'initial_mach': tuple, - 'final_mach': tuple, - 'mach_bounds': tuple, - 'initial_altitude': tuple, - 'final_altitude': tuple, - 'altitude_bounds': tuple, - 'throttle_enforcement': str, - 'constrain_final': bool, - 'fix_duration': bool, - 'initial_bounds': tuple, - 'duration_bounds': tuple, -} - -# Combine common and phase-specific entries -phase_keys_height_energy = { - 'pre_mission': {'include_takeoff': bool, 'optimize_mass': bool}, - 'post_mission': {'include_landing': bool} -} - -common_TAS = { - 'velocity_lower': tuple, - 'velocity_upper': tuple, - 'velocity_ref': tuple, -} -common_mass = { - 'mass_lower': tuple, - 'mass_upper': tuple, - 'mass_ref': tuple, - 'mass_defect_ref': tuple, -} -common_distance = { - 'distance_lower': tuple, - 'distance_upper': tuple, - 'distance_ref': tuple, -} -common_angle = { - 'angle_lower': tuple, - 'angle_upper': tuple, - 'angle_ref': tuple, - 'angle_defect_ref': tuple, -} -common_duration = { - 'duration_bounds': tuple, - 'duration_ref': tuple, -} -common_alt = { - 'alt_lower': tuple, - 'alt_upper': tuple, - 'alt_ref': tuple, -} -common_descent = { - 'input_initial': (bool, dict), - 'EAS_limit': tuple, - 'mach_cruise': float, - 'input_speed_type': SpeedType, - 'final_altitude': tuple, - 'alt_constraint_ref': tuple, -} - -phase_keys_gasp = { - 'groundroll': { - 'connect_initial_mass': bool, - 'fix_initial_mass': bool, - **common_duration, - **common_TAS, - **common_mass, - **common_distance, - 'distance_defect_ref': tuple, - }, - 'rotation': { - **common_duration, - **common_TAS, - **common_mass, - **common_distance, - **common_angle, - 'normal_ref': tuple, - 'velocity_ref0': tuple, - 'distance_defect_ref': tuple, - }, - 'ascent': { - **common_TAS, - **common_mass, - **common_distance, - **common_alt, - 'final_altitude': tuple, - 'alt_constraint_ref': tuple, - 'alt_defect_ref': tuple, - **common_angle, - 'pitch_constraint_lower': tuple, - 'pitch_constraint_upper': tuple, - 'pitch_constraint_ref': tuple, - 'velocity_ref0': tuple, - 'distance_defect_ref': tuple, - }, - 'accel': { - 'alt': tuple, - 'EAS_constraint_eq': tuple, - **common_duration, - 'duration_ref': tuple, - **common_TAS, - **common_mass, - **common_distance, - 'velocity_ref0': tuple, - 'distance_defect_ref': tuple, - }, - 'climb1': { - 'EAS_target': tuple, - 'mach_cruise': float, - 'target_mach': bool, - 'final_altitude': tuple, - **common_duration, - **common_alt, - **common_mass, - **common_distance, - 'distance_ref0': tuple, - }, - 'climb2': { - 'EAS_target': tuple, - 'mach_cruise': float, - 'target_mach': bool, - 'final_altitude': tuple, - 'required_available_climb_rate': tuple, - **common_duration, - **common_alt, - **common_mass, - **common_distance, - 'alt_ref0': tuple, - 'distance_ref0': tuple, - 'distance_defect_ref': tuple, - }, - 'cruise': { - 'mach_cruise': float, - 'alt_cruise': tuple, - }, - 'desc1': { - **common_descent, - **common_duration, - **common_alt, - **common_mass, - **common_distance, - 'alt_ref0': tuple, - 'mass_ref0': tuple, - 'distance_ref0': tuple, - }, - 'desc2': { - **common_descent, - **common_duration, - **common_alt, - **common_mass, - **common_distance, - 'alt_ref0': tuple, - 'distance_defect_ref': tuple, - }, -} - - -def check_phase_info(phase_info, mission_method): - """ - Check if all phases exist in phase_info for the given mission_method. - - Parameters - ---------- - phase_info : dict - Dictionary of phase settings for a mission profile - mission_method : str - The mission method - - Returns - ------- - True if all phases exist in phase_info - Otherwise, raise key not found in phase exception - """ - phase_keys = {} - if mission_method is TWO_DEGREES_OF_FREEDOM: - for phase in phase_info: - base_phase = phase.removeprefix('reserve_') - if base_phase != 'pre_mission' and base_phase != 'post_mission': - if 'cruise' in base_phase: - phase_keys[phase] = {**phase_keys_gasp['cruise']} - else: - phase_keys[phase] = {**common_keys, **phase_keys_gasp[base_phase]} - elif mission_method is SOLVED_2DOF: - return - elif mission_method is HEIGHT_ENERGY: - for phase in phase_info: - if phase != 'pre_mission' and phase != 'post_mission': - phase_keys[phase] = {**common_keys, **common_entries} - else: - phase_keys[phase] = phase_keys_height_energy[phase] - else: - possible_values = ["'"+e.value+"'" for e in EquationsOfMotion] - possible_values[-1] = "or " + possible_values[-1] - raise ValueError("Invalid mission_method. Please choose from " + - ", ".join(possible_values) + ".") - - # Check if all phases exist in phase_info - for phase in phase_info: - if mission_method is TWO_DEGREES_OF_FREEDOM: - base_phase = phase.removeprefix('reserve_') - if 'cruise' in base_phase: - base_phase = 'cruise' - else: - base_phase = phase - if 'user_options' in phase_info[base_phase]: - phase_options = phase_info[base_phase]['user_options'] - else: - phase_options = phase_info[base_phase] - - if phase_options.get('target_range', False) and phase_options.get('target_duration', False): - raise ValueError( - f"target_range and target_duration have both been set to True for {phase}, please pick one.") - - # Check if all required keys exist, if there are no extra keys, and if they are of the correct type - for key, expected_type in phase_keys[phase].items(): - # Check tuples for (val, units) structure - if expected_type is tuple: - if key not in phase_options: - raise ValueError( - f"Key {key} not found in phase {phase} of the provided dictionary.") - value = phase_options[key] - if not isinstance(value, tuple) or len(value) != 2: - raise ValueError(f"Key {key} in phase {phase} should be a tuple of size 2 (value, unit), " - f"but got {value}.") - unit = value[1] - if not valid_units(unit): - raise ValueError( - f"Key {key} in phase {phase} has an invalid unit {unit}.") - - if not isinstance(phase_options[key], expected_type): - raise TypeError(f"Key {key} in phase {phase} should be of type {expected_type.__name__}, " - f"but got type {type(phase_options[key]).__name__}") - - return True diff --git a/aviary/mission/base_ode.py b/aviary/mission/base_ode.py new file mode 100644 index 0000000000..b44bb9719d --- /dev/null +++ b/aviary/mission/base_ode.py @@ -0,0 +1,170 @@ +import openmdao.api as om + +from aviary.subsystems.atmosphere.atmosphere import Atmosphere +from aviary.utils.aviary_values import AviaryValues +from aviary.utils.functions import promote_aircraft_and_mission_vars +from aviary.variable_info.variable_meta_data import _MetaData + + +# +class ExternalSubsystemGroup(om.Group): + """ + Create a lightly modified version of an OM group to add external subsystems to the + ODE with a special configure() method that promotes all 'aircraft:*' and 'mission:*' + variables to the ODE. + """ + + def configure(self): + promote_aircraft_and_mission_vars(self) + + +class BaseODE(om.Group): + """The base class for all ODE components.""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + self.options.declare( + 'subsystem_options', + types=dict, + default={}, + desc='dictionary of parameters to be passed to the subsystem builders', + ) + self.options.declare( + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) + self.options.declare( + 'core_subsystems', + desc='list of core subsystem builder instances to be added to the ODE', + ) + self.options.declare( + 'external_subsystems', + default=[], + desc='list of external subsystem builder instances to be added to the ODE', + ) + self.options.declare( + 'meta_data', + default=_MetaData, + desc='metadata associated with the variables to be passed into the ODE', + ) + + def add_atmosphere(self, **kwargs): + """Adds Atmosphere component to ODE.""" + nn = self.options['num_nodes'] + self.add_subsystem( + name='atmosphere', + subsys=Atmosphere(num_nodes=nn, **kwargs), # Atmosphere defaults to TAS + promotes=['*'], + ) + + def add_core_subsystems(self, solver_group=None): + """ + Adds all specified external subsystems to ODE in their own group. + + Parameters + ---------- + solver_group : om.Group + If not None, core subsystems that require a solver + (subsystem.needs_mission_solver() == True) are placed inside solver_group. + If None, all core subsystems are added to BaseODE regardless of if they + request a solver. TODO add solver compatibility to all ODEs + """ + nn = self.options['num_nodes'] + aviary_options = self.options['aviary_options'] + core_subsystems = self.options['core_subsystems'] + subsystem_options = self.options['subsystem_options'] + + for subsystem in core_subsystems: + # check if subsystem_options has entry for a subsystem of this name + if subsystem.name in subsystem_options: + kwargs = subsystem_options[subsystem.name] + else: + kwargs = {} + + subsystem_mission = subsystem.build_mission( + num_nodes=nn, aviary_inputs=aviary_options, **kwargs + ) + + if subsystem_mission is not None: + if solver_group is not None: + target = solver_group + else: + target = self + + target.add_subsystem( + subsystem.name, + subsystem_mission, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) + + def add_external_subsystems(self, solver_group=None): + """ + Adds all specified external subsystems to ODE in their own group. + + Parameters + ---------- + solver_group : om.Group + If not None, external subsystems that require a solver + (subsystem.needs_mission_solver() == True) are placed inside solver_group. + If None, all external subsystems are added to BaseODE regardless of if they + request a solver. TODO add solver compatibility to all ODEs + + Returns + bool + True if any subsystem needs a solver. + """ + nn = self.options['num_nodes'] + aviary_options = self.options['aviary_options'] + external_subsystems = self.options['external_subsystems'] + subsystem_options = self.options['subsystem_options'] + + external_subsystem_group = ExternalSubsystemGroup() + external_subsystem_group_solver = ExternalSubsystemGroup() + add_subsystem_group = False + add_subsystem_group_solver = False + + for subsystem in external_subsystems: + if subsystem.name in subsystem_options: + kwargs = subsystem_options[subsystem.name] + else: + kwargs = {} + + subsystem_mission = subsystem.build_mission( + num_nodes=nn, aviary_inputs=aviary_options, **kwargs + ) + + if subsystem_mission is not None: + target = external_subsystem_group + if subsystem.needs_mission_solver(aviary_options) and solver_group is not None: + add_subsystem_group_solver = True + target = external_subsystem_group_solver + else: + add_subsystem_group = True + + target.add_subsystem( + subsystem.name, + subsystem_mission, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) + + # Only add the external subsystem group if it has at least one subsystem. + # Without this logic there'd be an empty OM group added to the ODE. + if add_subsystem_group: + self.add_subsystem( + name='external_subsystems', + subsys=external_subsystem_group, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + if add_subsystem_group_solver: + solver_group.add_subsystem( + name='external_subsystems', + subsys=external_subsystem_group_solver, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + return add_subsystem_group_solver diff --git a/aviary/mission/flight_phase_builder.py b/aviary/mission/flight_phase_builder.py index 874da3dd04..0f0254c96d 100644 --- a/aviary/mission/flight_phase_builder.py +++ b/aviary/mission/flight_phase_builder.py @@ -1,64 +1,186 @@ -import numpy as np - import dymos as dm +import numpy as np -from aviary.mission.initial_guess_builders import InitialGuessState -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.phases.phase_utils import add_subsystem_variables_to_phase, get_initial +from aviary.mission.flops_based.ode.energy_ODE import EnergyODE +from aviary.mission.flops_based.phases.phase_utils import ( + add_subsystem_variables_to_phase, + get_initial, +) +from aviary.mission.initial_guess_builders import ( + InitialGuessState, + InitialGuessControl, +) from aviary.mission.phase_builder_base import PhaseBuilderBase, register - +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import EquationsOfMotion, ThrottleAllocation from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Dynamic +# Height Energy and Solved2DOF use this builder # TODO: support/handle the following in the base class # - phase.set_time_options() # - currently handled in level 3 interface implementation # - self.external_subsystems # - self.meta_data, with cls.default_meta_data customization point + + +class FlightPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=1, + desc='The number of segments in transcription creation in Dymos. ' + 'The default value is 1.', + ) + + self.declare( + name='order', + types=int, + default=3, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos. The default value is 3.', + ) + + # TODO: These defaults aren't great, but need to keep things the same for now. + defaults = { + 'mass_ref': 1e4, + 'mass_bounds': (0.0, None), + } + self.add_state_options('mass', units='kg', defaults=defaults) + + # TODO: These defaults aren't great, but need to keep things the same for now. + defaults = { + 'distance_ref': 1e6, + 'distance_bounds': (0.0, None), + } + self.add_state_options('distance', units='m', defaults=defaults) + + self.add_control_options('altitude', units='ft') + + # TODO: These defaults aren't great, but need to keep things the same for now. + defaults = { + 'mach_ref': 0.5, + } + self.add_control_options('mach', units='unitless', defaults=defaults) + + self.add_time_options(units='s') + + self.declare( + name='throttle_enforcement', + default='path_constraint', + values=['path_constraint', 'boundary_constraint', 'bounded', 'control', None], + desc='Flag to enforce engine throttle bounds as path constraints, boundary ' + 'constraints, solver bounds. You can also select "control" to turn throttle into a ' + 'control, which allows you to assign a value or let the optimizer choose it.', + ) + + # Throttle is a solver variable, unless you set throttle_enforcement to control. + defaults = { + 'throttle_bounds': (0.0, 1.0), + } + self.add_control_options('throttle', units='unitless', defaults=defaults) + + self.declare( + name='throttle_allocation', + default=ThrottleAllocation.FIXED, + values=[ + ThrottleAllocation.FIXED, + ThrottleAllocation.STATIC, + ThrottleAllocation.DYNAMIC, + ], + desc='Specifies how to handle the throttles for multiple engines. FIXED is a ' + 'user-specified value. STATIC is specified by the optimizer as one value for the ' + 'whole phase. DYNAMIC is specified by the optimizer at each point in the phase.', + ) + + self.declare( + name='required_available_climb_rate', + default=None, + units='ft/s', + desc='Adds a constraint requiring Dynamic.Mission.ALTITUDE_RATE_MAX to be no ' + 'smaller than required_available_climb_rate. This helps to ensure that the ' + 'propulsion system is large enough to handle emergency maneuvers at all points ' + 'throughout the flight envelope. Default value is None for no constraint.', + ) + + self.declare( + name='ground_roll', + types=bool, + default=False, + desc='Set to True only for phases where the aircraft is rolling on the ground. ' + 'All other phases of flight (climb, cruise, descent) this must be set to False.', + ) + + self.declare( + name='constraints', + types=dict, + default={}, + desc="Add in custom constraints i.e. 'flight_path_angle': {'equals': -3., " + "'loc': 'initial', 'units': 'deg', 'type': 'boundary',}. For more details see " + '_add_user_defined_constraints().', + ) + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + self.declare( + name='no_climb', + types=bool, + default=False, + desc='Set to True to prevent the aircraft from climbing during the phase. This option ' + 'can be used to prevent unexpected climb during a descent phase.', + ) + + self.declare( + name='no_descent', + types=bool, + default=False, + desc='Set to True to prevent the aircraft from descending during the phase. This ' + 'can be used to prevent unexpected descent during a climb phase.', + ) + + @register class FlightPhaseBase(PhaseBuilderBase): """ - The base class for flight phase + The base class for flight phase. + + This houses parts of the build_phase process that are commmon to EnergyPhase and TwoDOFPhase. """ __slots__ = ('external_subsystems', 'meta_data') - # region : derived type customization points - _meta_data_ = {} - _initial_guesses_meta_data_ = {} - default_name = 'cruise' - - default_ode_class = MissionODE + default_ode_class = EnergyODE + default_options_class = FlightPhaseOptions default_meta_data = _MetaData - # endregion : derived type customization points - def __init__( - self, name=None, subsystem_options=None, user_options=None, initial_guesses=None, - ode_class=None, transcription=None, core_subsystems=None, - external_subsystems=None, meta_data=None + def build_phase( + self, + aviary_options: AviaryValues = None, + phase_type=EquationsOfMotion.HEIGHT_ENERGY, ): - super().__init__( - name=name, core_subsystems=core_subsystems, subsystem_options=subsystem_options, user_options=user_options, initial_guesses=initial_guesses, ode_class=ode_class, transcription=transcription) - - # TODO: support external_subsystems and meta_data in the base class - if external_subsystems is None: - external_subsystems = [] - - self.external_subsystems = external_subsystems - - if meta_data is None: - meta_data = self.default_meta_data - - self.meta_data = meta_data - - def build_phase(self, aviary_options: AviaryValues = None, phase_type=EquationsOfMotion.HEIGHT_ENERGY): - ''' + """ Return a new energy phase for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -74,113 +196,76 @@ def build_phase(self, aviary_options: AviaryValues = None, phase_type=EquationsO Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) + self.phase = phase num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - user_options: AviaryValues = self.user_options - - fix_initial = user_options.get_val('fix_initial') - constrain_final = user_options.get_val('constrain_final') - optimize_mach = user_options.get_val('optimize_mach') - optimize_altitude = user_options.get_val('optimize_altitude') - input_initial = user_options.get_val('input_initial') - polynomial_control_order = user_options.get_item('polynomial_control_order')[0] - use_polynomial_control = user_options.get_val('use_polynomial_control') - throttle_enforcement = user_options.get_val('throttle_enforcement') - mach_bounds = user_options.get_item('mach_bounds') - altitude_bounds = user_options.get_item('altitude_bounds') - initial_mach = user_options.get_item('initial_mach')[0] - final_mach = user_options.get_item('final_mach')[0] - initial_altitude = user_options.get_item('initial_altitude')[0] - final_altitude = user_options.get_item('final_altitude')[0] - solve_for_distance = user_options.get_val('solve_for_distance') - no_descent = user_options.get_val('no_descent') - no_climb = user_options.get_val('no_climb') - constraints = user_options.get_val('constraints') + user_options = self.user_options + + throttle_enforcement = user_options['throttle_enforcement'] + no_descent = user_options['no_descent'] + no_climb = user_options['no_climb'] + constraints = user_options['constraints'] + ground_roll = user_options['ground_roll'] ############## # Add States # ############## - # TODO: critically think about how we should handle fix_initial and input_initial defaults. - # In keeping with Dymos standards, the default should be False instead of True. - input_initial_mass = get_initial(input_initial, Dynamic.Mission.MASS) - fix_initial_mass = get_initial(fix_initial, Dynamic.Mission.MASS, True) - - # Experiment: use a constraint for mass instead of connected initial. - # This is due to some problems in mpi. - # This is needed for the cutting edge full subsystem integration. - # TODO: when a Dymos fix is in and we've verified that full case works with the fix, - # remove this argument. - if user_options.get_val('add_initial_mass_constraint'): - phase.add_constraint('rhs_all.initial_mass_residual', equals=0.0, ref=1e4) - input_initial_mass = False - if phase_type is EquationsOfMotion.HEIGHT_ENERGY: - rate_source = Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL + rate_source = Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL else: - rate_source = "dmass_dr" - - phase.add_state( - Dynamic.Mission.MASS, fix_initial=fix_initial_mass, fix_final=False, - lower=0.0, ref=1e4, defect_ref=1e6, units='kg', - rate_source=rate_source, - targets=Dynamic.Mission.MASS, - input_initial=input_initial_mass, - ) + rate_source = 'dmass_dr' + + self.add_state('mass', Dynamic.Vehicle.MASS, rate_source) if phase_type is EquationsOfMotion.HEIGHT_ENERGY: - input_initial_distance = get_initial(input_initial, Dynamic.Mission.DISTANCE) - fix_initial_distance = get_initial( - fix_initial, Dynamic.Mission.DISTANCE, True) - phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=fix_initial_distance, fix_final=False, - lower=0.0, ref=1e6, defect_ref=1e8, units='m', - rate_source=Dynamic.Mission.DISTANCE_RATE, - input_initial=input_initial_distance, - solve_segments='forward' if solve_for_distance else None, - ) + self.add_state('distance', Dynamic.Mission.DISTANCE, Dynamic.Mission.DISTANCE_RATE) - phase = add_subsystem_variables_to_phase( - phase, self.name, self.external_subsystems) + phase = add_subsystem_variables_to_phase(phase, self.name, self.external_subsystems) ################ # Add Controls # ################ if phase_type is EquationsOfMotion.HEIGHT_ENERGY: - rate_targets = [Dynamic.Mission.MACH_RATE] + rate_targets = [Dynamic.Atmosphere.MACH_RATE] else: rate_targets = ['dmach_dr'] - if use_polynomial_control: - phase.add_polynomial_control( - Dynamic.Mission.MACH, - targets=Dynamic.Mission.MACH, units=mach_bounds[1], - opt=optimize_mach, lower=mach_bounds[0][0], upper=mach_bounds[0][1], - rate_targets=rate_targets, - order=polynomial_control_order, ref=0.5, - ) - else: - phase.add_control( - Dynamic.Mission.MACH, - targets=Dynamic.Mission.MACH, units=mach_bounds[1], - opt=optimize_mach, lower=mach_bounds[0][0], upper=mach_bounds[0][1], - rate_targets=rate_targets, - ref=0.5, - ) + self.add_control( + 'mach', + Dynamic.Atmosphere.MACH, + rate_targets, + add_constraints=Dynamic.Atmosphere.MACH not in constraints, + ) - # Add altitude rate as a control - if phase_type is EquationsOfMotion.HEIGHT_ENERGY: + if phase_type is EquationsOfMotion.HEIGHT_ENERGY and not ground_roll: rate_targets = [Dynamic.Mission.ALTITUDE_RATE] - rate2_targets = [] + rate2_targets = None else: rate_targets = ['dh_dr'] rate2_targets = ['d2h_dr2'] + self.add_control( + 'altitude', + Dynamic.Mission.ALTITUDE, + rate_targets, + rate2_targets=rate2_targets, + add_constraints=Dynamic.Mission.ALTITUDE not in constraints, + ) + + if throttle_enforcement == 'control': + self.add_control( + 'throttle', + Dynamic.Vehicle.Propulsion.THROTTLE, + rate_targets=None, + add_constraints=True, + ) + # For heterogeneous-engine cases, we may have throttle allocation control. if phase_type is EquationsOfMotion.HEIGHT_ENERGY and num_engine_type > 1: - allocation = user_options.get_val('throttle_allocation') + allocation = user_options['throttle_allocation'] # Allocation should default to an even split so that we don't start # with an allocation that might not produce enough thrust. @@ -188,157 +273,130 @@ def build_phase(self, aviary_options: AviaryValues = None, phase_type=EquationsO if allocation == ThrottleAllocation.DYNAMIC: phase.add_control( - "throttle_allocations", - shape=(num_engine_type - 1, ), + 'throttle_allocations', + shape=(num_engine_type - 1,), val=val, - targets="throttle_allocations", units="unitless", - opt=True, lower=0.0, upper=1.0, + targets='throttle_allocations', + units='unitless', + opt=True, + lower=0.0, + upper=1.0, ) else: - if allocation == ThrottleAllocation.STATIC: - opt = True - else: - opt = False - phase.add_parameter( - "throttle_allocations", - units="unitless", + 'throttle_allocations', + units='unitless', val=val, - shape=(num_engine_type - 1, ), - opt=opt, lower=0.0, upper=1.0, - ) - - ground_roll = user_options.get_val('ground_roll') - if ground_roll: - phase.add_polynomial_control(Dynamic.Mission.ALTITUDE, - order=1, val=0, opt=False, - fix_initial=fix_initial, - rate_targets=['dh_dr'], rate2_targets=['d2h_dr2']) - else: - if use_polynomial_control: - phase.add_polynomial_control( - Dynamic.Mission.ALTITUDE, - targets=Dynamic.Mission.ALTITUDE, units=altitude_bounds[1], - opt=optimize_altitude, lower=altitude_bounds[0][0], upper=altitude_bounds[0][1], - rate_targets=rate_targets, rate2_targets=rate2_targets, - order=polynomial_control_order, ref=altitude_bounds[0][1], - ) - else: - phase.add_control( - Dynamic.Mission.ALTITUDE, - targets=Dynamic.Mission.ALTITUDE, units=altitude_bounds[1], - opt=optimize_altitude, lower=altitude_bounds[0][0], upper=altitude_bounds[0][1], - rate_targets=rate_targets, rate2_targets=rate2_targets, - ref=altitude_bounds[0][1], + shape=(num_engine_type - 1,), + opt=allocation == ThrottleAllocation.STATIC, + lower=0.0, + upper=1.0, ) ################## # Add Timeseries # ################## phase.add_timeseries_output( - Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units='unitless' - ) - - phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) - phase.add_timeseries_output( - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, - output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, units='m/s' - ) + if phase_type is EquationsOfMotion.HEIGHT_ENERGY: + phase.add_timeseries_output( + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + output_name=Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + units='m/s', + ) phase.add_timeseries_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - output_name=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + units='lbm/h', ) phase.add_timeseries_output( - Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL, - output_name=Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL, units='kW' + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + units='kW', ) phase.add_timeseries_output( Dynamic.Mission.ALTITUDE_RATE, - output_name=Dynamic.Mission.ALTITUDE_RATE, units='ft/s' + output_name=Dynamic.Mission.ALTITUDE_RATE, + units='ft/s', ) - phase.add_timeseries_output( - Dynamic.Mission.THROTTLE, - output_name=Dynamic.Mission.THROTTLE, units='unitless' - ) + if throttle_enforcement != 'control': + phase.add_timeseries_output( + Dynamic.Vehicle.Propulsion.THROTTLE, + output_name=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + ) phase.add_timeseries_output( Dynamic.Mission.VELOCITY, - output_name=Dynamic.Mission.VELOCITY, units='m/s' + output_name=Dynamic.Mission.VELOCITY, + units='m/s', ) - phase.add_timeseries_output(Dynamic.Mission.ALTITUDE) - if phase_type is EquationsOfMotion.SOLVED_2DOF: phase.add_timeseries_output(Dynamic.Mission.FLIGHT_PATH_ANGLE) - phase.add_timeseries_output("alpha") - phase.add_timeseries_output( - "fuselage_pitch", output_name="theta", units="deg") - phase.add_timeseries_output("thrust_req", units="lbf") - phase.add_timeseries_output("normal_force") - phase.add_timeseries_output("time") + phase.add_timeseries_output(Dynamic.Vehicle.ANGLE_OF_ATTACK) + phase.add_timeseries_output('fuselage_pitch', output_name='theta', units='deg') + phase.add_timeseries_output('thrust_req', units='lbf') + phase.add_timeseries_output('normal_force') + phase.add_timeseries_output('time') ################### # Add Constraints # ################### - if optimize_mach and fix_initial and not Dynamic.Mission.MACH in constraints: - phase.add_boundary_constraint( - Dynamic.Mission.MACH, loc='initial', equals=initial_mach, - ) - - if optimize_mach and constrain_final and not Dynamic.Mission.MACH in constraints: - phase.add_boundary_constraint( - Dynamic.Mission.MACH, loc='final', equals=final_mach, - ) - - if optimize_altitude and fix_initial and not Dynamic.Mission.ALTITUDE in constraints: - phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='initial', equals=initial_altitude, units=altitude_bounds[1], ref=1.e4, - ) - - if optimize_altitude and constrain_final and not Dynamic.Mission.ALTITUDE in constraints: - phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='final', equals=final_altitude, units=altitude_bounds[1], ref=1.e4, - ) - if no_descent and not Dynamic.Mission.ALTITUDE_RATE in constraints: - phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, lower=0.0) + if no_descent and Dynamic.Mission.ALTITUDE_RATE not in constraints: + phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, lower=0.0, ref=20.0) - if no_climb and not Dynamic.Mission.ALTITUDE_RATE in constraints: - phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, upper=0.0) + if no_climb and Dynamic.Mission.ALTITUDE_RATE not in constraints: + phase.add_path_constraint(Dynamic.Mission.ALTITUDE_RATE, upper=0.0, ref=20.0) - required_available_climb_rate, units = user_options.get_item( - 'required_available_climb_rate') + required_available_climb_rate, units = user_options['required_available_climb_rate'] - if required_available_climb_rate is not None and not Dynamic.Mission.ALTITUDE_RATE_MAX in constraints: + if ( + required_available_climb_rate is not None + and Dynamic.Mission.ALTITUDE_RATE_MAX not in constraints + ): phase.add_path_constraint( Dynamic.Mission.ALTITUDE_RATE_MAX, - lower=required_available_climb_rate, units=units + lower=required_available_climb_rate, + units=units, ) - if not Dynamic.Mission.THROTTLE in constraints: + if Dynamic.Vehicle.Propulsion.THROTTLE not in constraints: if throttle_enforcement == 'boundary_constraint': phase.add_boundary_constraint( - Dynamic.Mission.THROTTLE, loc='initial', lower=0.0, upper=1.0, units='unitless', + Dynamic.Vehicle.Propulsion.THROTTLE, + loc='initial', + lower=0.0, + upper=1.0, + units='unitless', ) phase.add_boundary_constraint( - Dynamic.Mission.THROTTLE, loc='final', lower=0.0, upper=1.0, units='unitless', + Dynamic.Vehicle.Propulsion.THROTTLE, + loc='final', + lower=0.0, + upper=1.0, + units='unitless', ) elif throttle_enforcement == 'path_constraint': phase.add_path_constraint( - Dynamic.Mission.THROTTLE, lower=0.0, upper=1.0, units='unitless', + Dynamic.Vehicle.Propulsion.THROTTLE, + lower=0.0, + upper=1.0, + units='unitless', ) self._add_user_defined_constraints(phase, constraints) @@ -346,115 +404,50 @@ def build_phase(self, aviary_options: AviaryValues = None, phase_type=EquationsO return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" user_options = self.user_options - num_segments, _ = user_options.get_item('num_segments') - order, _ = user_options.get_item('order') + num_segments = user_options['num_segments'] + order = user_options['order'] seg_ends, _ = dm.utils.lgl.lgl(num_segments + 1) transcription = dm.Radau( - num_segments=num_segments, order=order, compressed=True, - segment_ends=seg_ends) + num_segments=num_segments, + order=order, + compressed=True, + segment_ends=seg_ends, + ) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ + """Return extra kwargs required for initializing the ODE.""" # TODO: support external_subsystems and meta_data in the base class return { 'external_subsystems': self.external_subsystems, 'meta_data': self.meta_data, 'subsystem_options': self.subsystem_options, - 'throttle_enforcement': self.user_options.get_val('throttle_enforcement'), - 'throttle_allocation': self.user_options.get_val('throttle_allocation') + 'throttle_enforcement': self.user_options['throttle_enforcement'], + 'throttle_allocation': self.user_options['throttle_allocation'], } -FlightPhaseBase._add_meta_data( - 'reserve', val=False, desc='this phase is part of the reserve mission.') - -FlightPhaseBase._add_meta_data( - 'target_distance', val={}, desc='the amount of distance traveled in this phase added as a constraint') - -FlightPhaseBase._add_meta_data( - 'target_duration', val={}, desc='the amount of time taken by this phase added as a constraint') - -FlightPhaseBase._add_meta_data( - 'num_segments', val=5, desc='transcription: number of segments') - -FlightPhaseBase._add_meta_data( - 'order', val=3, - desc='transcription: order of the state transcription; the order of the control' - ' transcription is `order - 1`') - -FlightPhaseBase._add_meta_data('polynomial_control_order', val=3) - -FlightPhaseBase._add_meta_data('use_polynomial_control', val=True) - -FlightPhaseBase._add_meta_data('ground_roll', val=False) - -FlightPhaseBase._add_meta_data('add_initial_mass_constraint', val=False) - -FlightPhaseBase._add_meta_data('fix_initial', val=True) - -FlightPhaseBase._add_meta_data('fix_duration', val=False) - -FlightPhaseBase._add_meta_data('optimize_mach', val=False) - -FlightPhaseBase._add_meta_data('optimize_altitude', val=False) - -FlightPhaseBase._add_meta_data('initial_bounds', val=(0., 100.), units='s') +# Previous implementation: -FlightPhaseBase._add_meta_data('duration_bounds', val=(0., 100.), units='s') -FlightPhaseBase._add_meta_data( - 'required_available_climb_rate', val=None, units='m/s', - desc='minimum avaliable climb rate') - -FlightPhaseBase._add_meta_data( - 'no_climb', val=False, desc='aircraft is not allowed to climb during phase') - -FlightPhaseBase._add_meta_data( - 'no_descent', val=False, desc='aircraft is not allowed to descend during phase') - -FlightPhaseBase._add_meta_data('constrain_final', val=False) - -FlightPhaseBase._add_meta_data('input_initial', val=False) - -FlightPhaseBase._add_meta_data('initial_mach', val=None, units='unitless') - -FlightPhaseBase._add_meta_data('final_mach', val=None, units='unitless') - -FlightPhaseBase._add_meta_data('initial_altitude', val=None, units='ft') - -FlightPhaseBase._add_meta_data('final_altitude', val=None, units='ft') - -FlightPhaseBase._add_meta_data('throttle_enforcement', val=None) - -FlightPhaseBase._add_meta_data('throttle_allocation', val=ThrottleAllocation.FIXED) - -FlightPhaseBase._add_meta_data('mach_bounds', val=(0., 2.), units='unitless') - -FlightPhaseBase._add_meta_data('altitude_bounds', val=(0., 60.e3), units='ft') - -FlightPhaseBase._add_meta_data('solve_for_distance', val=False) - -FlightPhaseBase._add_meta_data('constraints', val={}) +FlightPhaseBase._add_initial_guess_meta_data( + InitialGuessControl('altitude'), desc='initial guess for vertical distances' +) FlightPhaseBase._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for vertical distances') + InitialGuessControl('mach'), desc='initial guess for speed' +) FlightPhaseBase._add_initial_guess_meta_data( - InitialGuessState('mach'), - desc='initial guess for speed') + InitialGuessControl('throttle'), desc='initial guess for throttle' +) FlightPhaseBase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') + InitialGuessState('mass'), desc='initial guess for mass' +) diff --git a/aviary/mission/flops_based/ode/energy_ODE.py b/aviary/mission/flops_based/ode/energy_ODE.py new file mode 100644 index 0000000000..33a4cc1b6e --- /dev/null +++ b/aviary/mission/flops_based/ode/energy_ODE.py @@ -0,0 +1,189 @@ +import numpy as np +import openmdao.api as om + +from aviary.mission.base_ode import BaseODE as _BaseODE +from aviary.mission.flops_based.ode.mission_EOM import MissionEOM + +from aviary.subsystems.propulsion.throttle_allocation import ThrottleAllocator +from aviary.variable_info.enums import SpeedType, ThrottleAllocation +from aviary.variable_info.variables import Aircraft, Dynamic, Mission + + +class EnergyODE(_BaseODE): + """The base class for all energy method ODE components.""" + + def initialize(self): + super().initialize() + + # TODO throttle enforcement & allocation should be moved to BaseODE for + # use in 2DOF + self.options.declare( + 'throttle_enforcement', + default='path_constraint', + values=['path_constraint', 'boundary_constraint', 'bounded', 'control', None], + desc='Flag to enforce engine throttle bounds as path constraints, boundary ' + 'constraints, solver bounds. You can also select "control" to turn throttle into a ' + 'control, which allows you to assign a value or let the optimizer choose it.', + ) + self.options.declare( + 'throttle_allocation', + default=ThrottleAllocation.FIXED, + types=ThrottleAllocation, + desc='Flag that determines how to handle throttles for multiple engines.', + ) + + def setup(self): + options = self.options + nn = options['num_nodes'] + aviary_options = options['aviary_options'] + num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) + + self.add_atmosphere(input_speed_type=SpeedType.MACH) + + # add execcomp to compute velocity_rate based off mach_rate and sos + self.add_subsystem( + name='velocity_rate_comp', + subsys=om.ExecComp( + 'velocity_rate = mach_rate * sos', + mach_rate={'units': '1/s', 'shape': (nn,)}, + sos={'units': 'm/s', 'shape': (nn,)}, + velocity_rate={'units': 'm/s**2', 'shape': (nn,)}, + has_diag_partials=True, + ), + promotes_inputs=[ + ('mach_rate', Dynamic.Atmosphere.MACH_RATE), + ('sos', Dynamic.Atmosphere.SPEED_OF_SOUND), + ], + promotes_outputs=[('velocity_rate', Dynamic.Mission.VELOCITY_RATE)], + ) + + throttle_enforcement = options['throttle_enforcement'] + + sub1 = self.add_subsystem('solver_sub', om.Group(), promotes=['*']) + + if throttle_enforcement == 'control': + solver_group = None + core_needs_solver = False + else: + solver_group = sub1 + core_needs_solver = True + + self.add_core_subsystems(solver_group=solver_group) + + ext_needs_solver = self.add_external_subsystems(solver_group=sub1) + + sub1.add_subsystem( + name='mission_EOM', + subsys=MissionEOM(num_nodes=nn), + promotes_inputs=[ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.VELOCITY_RATE, + ], + promotes_outputs=[ + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + Dynamic.Mission.ALTITUDE_RATE_MAX, + Dynamic.Mission.DISTANCE_RATE, + 'thrust_required', + ], + ) + + # THROTTLE Section + # TODO: Split this out into a function that can be used by the other ODEs. + # TODO: Need a thrust residual ref in the phase_info. + thrust_res_ref = 1.0e6 + if num_engine_type > 1: + # Multi Engine + + sub1.add_subsystem( + name='throttle_balance', + subsys=om.BalanceComp( + name='aggregate_throttle', + units='unitless', + val=np.ones((nn,)), + lhs_name='thrust_required', + rhs_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + eq_units='lbf', + normalize=False, + res_ref=thrust_res_ref, + ), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + sub1.add_subsystem( + 'throttle_allocator', + ThrottleAllocator( + num_nodes=nn, throttle_allocation=self.options['throttle_allocation'] + ), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + else: + # Single Engine + + if throttle_enforcement == 'control': + self.add_subsystem( + 'throttle_balance', + om.ExecComp( + 'thrust_residual=thrust_required-thrust', + thrust={'val': np.ones((nn,)), 'units': 'lbf'}, + thrust_required={'val': np.ones((nn,)), 'units': 'lbf'}, + thrust_residual={'val': np.ones((nn,)), 'units': 'lbf'}, + has_diag_partials=True, + ), + promotes_inputs=[ + ('thrust', Dynamic.Vehicle.Propulsion.THRUST_TOTAL), + 'thrust_required', + ], + promotes_outputs=['*'], + ) + self.add_constraint('thrust_residual', ref=thrust_res_ref, equals=0.0) + else: + # Add a balance comp to compute throttle based on the required thrust. + sub1.add_subsystem( + name='throttle_balance', + subsys=om.BalanceComp( + name=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + val=np.ones((nn,)), + lhs_name='thrust_required', + rhs_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + eq_units='lbf', + normalize=False, + lower=0.0 if throttle_enforcement == 'bounded' else None, + upper=1.0 if throttle_enforcement == 'bounded' else None, + res_ref=thrust_res_ref, + ), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.set_input_defaults( + Dynamic.Vehicle.Propulsion.THROTTLE, val=np.ones(nn), units='unitless' + ) + + self.set_input_defaults(Dynamic.Atmosphere.MACH, val=np.ones(nn), units='unitless') + self.set_input_defaults(Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') + self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.ones(nn), units='m/s') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.ones(nn), units='m') + self.set_input_defaults(Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), units='m/s') + + if core_needs_solver or ext_needs_solver: + sub1.nonlinear_solver = om.NewtonSolver( + solve_subsystems=True, + atol=1.0e-10, + rtol=1.0e-10, + ) + print_level = 2 + + sub1.nonlinear_solver.linesearch = om.BoundsEnforceLS() + sub1.linear_solver = om.DirectSolver(assemble_jac=True) + sub1.nonlinear_solver.options['err_on_non_converge'] = True + sub1.nonlinear_solver.options['iprint'] = print_level + + self.options['auto_order'] = True diff --git a/aviary/mission/flops_based/ode/landing_eom.py b/aviary/mission/flops_based/ode/landing_eom.py index 10c2304aac..a1c6e2cedd 100644 --- a/aviary/mission/flops_based/ode/landing_eom.py +++ b/aviary/mission/flops_based/ode/landing_eom.py @@ -1,24 +1,22 @@ -''' -Define utilities for calculating landing EOMs. -''' +"""Define utilities for calculating landing EOMs.""" + import numpy as np import openmdao.api as om from aviary.constants import GRAV_METRIC_FLOPS as grav_metric -from aviary.mission.flops_based.ode.takeoff_eom import (Accelerations, - DistanceRates, - FlightPathAngleRate, - StallSpeed, - VelocityRate) +from aviary.mission.flops_based.ode.takeoff_eom import ( + Accelerations, + DistanceRates, + FlightPathAngleRate, + VelocityRate, +) from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input -from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.variable_info.variables import Dynamic, Mission class FlareEOM(om.Group): - ''' - Define a group for calculating equations of motion from start of flare to touchdown. - ''' + """Define a group for calculating equations of motion from start of flare to touchdown.""" def initialize(self): options = self.options @@ -26,8 +24,10 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): options = self.options @@ -35,9 +35,7 @@ def setup(self): nn = options['num_nodes'] aviary_options = options['aviary_options'] - kwargs = { - 'num_nodes': nn, - 'climbing': True} + kwargs = {'num_nodes': nn, 'climbing': True} inputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY] outputs = [Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] @@ -46,59 +44,77 @@ def setup(self): 'distance_rates', DistanceRates(**kwargs), promotes_inputs=inputs, - promotes_outputs=outputs) + promotes_outputs=outputs, + ) - kwargs = { - 'num_nodes': nn, - 'aviary_options': aviary_options} + kwargs = {'num_nodes': nn, 'aviary_options': aviary_options} inputs = [ - Dynamic.Mission.MASS, Dynamic.Mission.LIFT, Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, - 'angle_of_attack', Dynamic.Mission.FLIGHT_PATH_ANGLE] + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ] outputs = ['forces_horizontal', 'forces_vertical'] self.add_subsystem( - 'sum_forces', - FlareSumForces(**kwargs), - promotes_inputs=inputs, - promotes_outputs=outputs) + 'sum_forces', FlareSumForces(**kwargs), promotes_inputs=inputs, promotes_outputs=outputs + ) - inputs = ['forces_horizontal', 'forces_vertical', Dynamic.Mission.MASS] + inputs = ['forces_horizontal', 'forces_vertical', Dynamic.Vehicle.MASS] outputs = ['acceleration_horizontal', 'acceleration_vertical'] self.add_subsystem( 'accelerations', Accelerations(num_nodes=nn), promotes_inputs=inputs, - promotes_outputs=outputs) + promotes_outputs=outputs, + ) inputs = [ - 'acceleration_horizontal', 'acceleration_vertical', - Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] + 'acceleration_horizontal', + 'acceleration_vertical', + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE, + ] - outputs = [Dynamic.Mission.VELOCITY_RATE,] + outputs = [ + Dynamic.Mission.VELOCITY_RATE, + ] self.add_subsystem( 'velocity_rate', VelocityRate(num_nodes=nn), promotes_inputs=inputs, - promotes_outputs=outputs) + promotes_outputs=outputs, + ) inputs = [ - Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, - 'acceleration_horizontal', 'acceleration_vertical'] + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.ALTITUDE_RATE, + 'acceleration_horizontal', + 'acceleration_vertical', + ] outputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE] self.add_subsystem( - 'flight_path_angle_rate', FlightPathAngleRate(num_nodes=nn), + 'flight_path_angle_rate', + FlightPathAngleRate(num_nodes=nn), promotes_inputs=inputs, - promotes_outputs=outputs) + promotes_outputs=outputs, + ) inputs = [ - Dynamic.Mission.MASS, Dynamic.Mission.LIFT, Dynamic.Mission.DRAG, - 'angle_of_attack', Dynamic.Mission.FLIGHT_PATH_ANGLE] + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ] outputs = ['forces_perpendicular', 'required_thrust'] @@ -106,7 +122,8 @@ def setup(self): 'glide_slope_forces', GlideSlopeForces(**kwargs), promotes_inputs=inputs, - promotes_outputs=outputs) + promotes_outputs=outputs, + ) expr = 'net_alpha_rate = flare_rate - angle_of_attack_rate' flare_comp = om.ExecComp( @@ -117,18 +134,15 @@ def setup(self): has_diag_partials=True, ) self.add_subsystem( - "flare_rate", + 'flare_rate', flare_comp, - promotes_inputs=[('flare_rate', Mission.Landing.FLARE_RATE), - 'angle_of_attack_rate'], - promotes_outputs=['net_alpha_rate'] + promotes_inputs=[('flare_rate', Mission.Landing.FLARE_RATE), 'angle_of_attack_rate'], + promotes_outputs=['net_alpha_rate'], ) class GlideSlopeForces(om.ExplicitComponent): - ''' - Define a component for calculating forces for evaluation of glide slope criteria. - ''' + """Define a component for calculating forces for evaluation of glide slope criteria.""" def initialize(self): options = self.options @@ -136,31 +150,38 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): options = self.options nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') - self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') + self.add_input(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') self.add_output( - 'forces_perpendicular', val=np.zeros(nn), units='N', + 'forces_perpendicular', + val=np.zeros(nn), + units='N', desc='current forces perpendicular to the thrust vector; checking for zero' - ' perpendicular force') + ' perpendicular force', + ) self.add_output( - 'required_thrust', val=np.zeros(nn), units='N', - desc='current estimate of thrust required to maintain glide slope') + 'required_thrust', + val=np.zeros(nn), + units='N', + desc='current estimate of thrust required to maintain glide slope', + ) def setup_partials(self): options = self.options @@ -178,15 +199,14 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - total_num_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - drag = inputs[Dynamic.Mission.DRAG] + mass = inputs[Dynamic.Vehicle.MASS] + lift = inputs[Dynamic.Vehicle.LIFT] + drag = inputs[Dynamic.Vehicle.DRAG] weight = mass * grav_metric - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal @@ -207,7 +227,7 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): f_v = (weight * c_gamma - lift) / s_angle outputs['forces_perpendicular'] = f_h - f_v - outputs['required_thrust'] = (f_h + f_v) / (2.) + outputs['required_thrust'] = (f_h + f_v) / (2.0) def compute_partials(self, inputs, J, discrete_inputs=None): options = self.options @@ -216,15 +236,14 @@ def compute_partials(self, inputs, J, discrete_inputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - total_num_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - drag = inputs[Dynamic.Mission.DRAG] + mass = inputs[Dynamic.Vehicle.MASS] + lift = inputs[Dynamic.Vehicle.LIFT] + drag = inputs[Dynamic.Vehicle.DRAG] weight = mass * grav_metric - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal @@ -244,20 +263,20 @@ def compute_partials(self, inputs, J, discrete_inputs=None): f_h = -grav_metric * s_gamma / c_angle f_v = grav_metric * c_gamma / s_angle - J[forces_key, Dynamic.Mission.MASS] = f_h - f_v - J[thrust_key, Dynamic.Mission.MASS] = (f_h + f_v) / (2.) + J[forces_key, Dynamic.Vehicle.MASS] = f_h - f_v + J[thrust_key, Dynamic.Vehicle.MASS] = (f_h + f_v) / (2.0) - f_h = 0. - f_v = -1. / s_angle + f_h = 0.0 + f_v = -1.0 / s_angle - J[forces_key, Dynamic.Mission.LIFT] = -f_v - J[thrust_key, Dynamic.Mission.LIFT] = f_v / (2.) + J[forces_key, Dynamic.Vehicle.LIFT] = -f_v + J[thrust_key, Dynamic.Vehicle.LIFT] = f_v / (2.0) - f_h = 1. / c_angle - f_v = 0. + f_h = 1.0 / c_angle + f_v = 0.0 - J[forces_key, Dynamic.Mission.DRAG] = f_h - J[thrust_key, Dynamic.Mission.DRAG] = f_h / (2.) + J[forces_key, Dynamic.Vehicle.DRAG] = f_h + J[thrust_key, Dynamic.Vehicle.DRAG] = f_h / (2.0) # ddx(1 / cos(x)) = sec(x) * tan(x) = tan(x) / cos(x) # ddx(1 / sin(x)) = -csc(x) * cot(x) = -1 / (sin(x) * tan(x)) @@ -266,21 +285,21 @@ def compute_partials(self, inputs, J, discrete_inputs=None): f_h = t_angle * (drag - weight * s_gamma) / c_angle f_v = -(weight * c_gamma - lift) / (s_angle * t_angle) - J[forces_key, 'angle_of_attack'] = f_h - f_v - J[thrust_key, 'angle_of_attack'] = (f_h + f_v) / (2.) + J[forces_key, Dynamic.Vehicle.ANGLE_OF_ATTACK] = f_h - f_v + J[thrust_key, Dynamic.Vehicle.ANGLE_OF_ATTACK] = (f_h + f_v) / (2.0) f_h = -weight * c_gamma / c_angle f_v = -weight * s_gamma / s_angle - J[forces_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = - f_h + f_v - J[thrust_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -(f_h + f_v) / (2.) + J[forces_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -f_h + f_v + J[thrust_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -(f_h + f_v) / (2.0) class FlareSumForces(om.ExplicitComponent): - ''' + """ Define a component for calculating the separate sums for both the horizontal and vertical forces from start of flare to landing. - ''' + """ def initialize(self): options = self.options @@ -288,31 +307,38 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): options = self.options nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') - self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') + self.add_input(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') self.add_output( - 'forces_horizontal', val=np.zeros(nn), units='N', - desc='current sum of forces in the horizontal direction') + 'forces_horizontal', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the horizontal direction', + ) self.add_output( - 'forces_vertical', val=np.zeros(nn), units='N', - desc='current sum of forces in the vertical direction') + 'forces_vertical', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the vertical direction', + ) def setup_partials(self): options = self.options @@ -321,15 +347,23 @@ def setup_partials(self): rows_cols = np.arange(nn) - self.declare_partials('forces_horizontal', Dynamic.Mission.MASS, dependent=False) + self.declare_partials('forces_horizontal', Dynamic.Vehicle.MASS, dependent=False) self.declare_partials( - 'forces_vertical', Dynamic.Mission.MASS, val=-grav_metric, rows=rows_cols, - cols=rows_cols) + 'forces_vertical', + Dynamic.Vehicle.MASS, + val=-grav_metric, + rows=rows_cols, + cols=rows_cols, + ) wrt = [ - Dynamic.Mission.LIFT, Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, 'angle_of_attack', - Dynamic.Mission.FLIGHT_PATH_ANGLE] + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ] self.declare_partials('*', wrt, rows=rows_cols, cols=rows_cols) @@ -341,12 +375,12 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] + mass = inputs[Dynamic.Vehicle.MASS] + lift = inputs[Dynamic.Vehicle.LIFT] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal @@ -379,12 +413,11 @@ def compute_partials(self, inputs, J, discrete_inputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] + lift = inputs[Dynamic.Vehicle.LIFT] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] # FLOPS measures glideslope below horizontal @@ -399,19 +432,19 @@ def compute_partials(self, inputs, J, discrete_inputs=None): s_gamma = np.sin(gamma) f_h_key = 'forces_horizontal' - J[f_h_key, Dynamic.Mission.LIFT] = -s_gamma + J[f_h_key, Dynamic.Vehicle.LIFT] = -s_gamma f_v_key = 'forces_vertical' - J[f_v_key, Dynamic.Mission.LIFT] = c_gamma + J[f_v_key, Dynamic.Vehicle.LIFT] = c_gamma - J[f_h_key, Dynamic.Mission.THRUST_TOTAL] = -c_angle - J[f_v_key, Dynamic.Mission.THRUST_TOTAL] = s_angle + J[f_h_key, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = -c_angle + J[f_v_key, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = s_angle - J[f_h_key, Dynamic.Mission.DRAG] = c_gamma - J[f_v_key, Dynamic.Mission.DRAG] = s_gamma + J[f_h_key, Dynamic.Vehicle.DRAG] = c_gamma + J[f_v_key, Dynamic.Vehicle.DRAG] = s_gamma - J[f_h_key, 'angle_of_attack'] = thrust * s_angle - J[f_v_key, 'angle_of_attack'] = thrust * c_angle + J[f_h_key, Dynamic.Vehicle.ANGLE_OF_ATTACK] = thrust * s_angle + J[f_v_key, Dynamic.Vehicle.ANGLE_OF_ATTACK] = thrust * c_angle f_h = -drag * s_gamma - lift * c_gamma - thrust * s_angle J[f_h_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -f_h @@ -421,10 +454,10 @@ def compute_partials(self, inputs, J, discrete_inputs=None): class GroundSumForces(om.ExplicitComponent): - ''' + """ Define a component for calculating the separate sums for both the horizontal and vertical forces from start of touchdown through full stop. - ''' + """ def initialize(self): options = self.options @@ -432,27 +465,34 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'friction_coefficient', default=0.025, - desc='current friction coefficient, either rolling friction or breaking' - ' friction') + 'friction_coefficient', + default=0.025, + desc='current friction coefficient, either rolling friction or breaking friction', + ) def setup(self): options = self.options nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') self.add_output( - 'forces_horizontal', val=np.zeros(nn), units='N', - desc='current sum of forces in the horizontal direction') + 'forces_horizontal', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the horizontal direction', + ) self.add_output( - 'forces_vertical', val=np.zeros(nn), units='N', - desc='current sum of forces in the vertical direction') + 'forces_vertical', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the vertical direction', + ) def setup_partials(self): options = self.options @@ -462,25 +502,41 @@ def setup_partials(self): rows_cols = np.arange(nn) self.declare_partials( - 'forces_vertical', Dynamic.Mission.MASS, val=-grav_metric, rows=rows_cols, - cols=rows_cols) + 'forces_vertical', + Dynamic.Vehicle.MASS, + val=-grav_metric, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'forces_vertical', Dynamic.Mission.LIFT, val=1., rows=rows_cols, cols=rows_cols) + 'forces_vertical', Dynamic.Vehicle.LIFT, val=1.0, rows=rows_cols, cols=rows_cols + ) self.declare_partials( - 'forces_vertical', [Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG], dependent=False) + 'forces_vertical', + [Dynamic.Vehicle.Propulsion.THRUST_TOTAL, Dynamic.Vehicle.DRAG], + dependent=False, + ) self.declare_partials( - 'forces_horizontal', [Dynamic.Mission.MASS, Dynamic.Mission.LIFT], rows=rows_cols, - cols=rows_cols) + 'forces_horizontal', + [Dynamic.Vehicle.MASS, Dynamic.Vehicle.LIFT], + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'forces_horizontal', Dynamic.Mission.THRUST_TOTAL, val=-1., rows=rows_cols, - cols=rows_cols) + 'forces_horizontal', + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + val=-1.0, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'forces_horizontal', Dynamic.Mission.DRAG, val=1., rows=rows_cols, cols=rows_cols) + 'forces_horizontal', Dynamic.Vehicle.DRAG, val=1.0, rows=rows_cols, cols=rows_cols + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): options = self.options @@ -488,17 +544,17 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): nn = options['num_nodes'] friction_coefficient = options['friction_coefficient'] - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] + mass = inputs[Dynamic.Vehicle.MASS] + lift = inputs[Dynamic.Vehicle.LIFT] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] weight = mass * grav_metric f_v = lift - weight outputs['forces_vertical'] = f_v - idx_sup = np.where(f_v < 0.) + idx_sup = np.where(f_v < 0.0) friction = np.zeros(nn) friction[idx_sup] = -friction_coefficient * f_v[idx_sup] @@ -511,19 +567,19 @@ def compute_partials(self, inputs, J, discrete_inputs=None): nn = options['num_nodes'] friction_coefficient = options['friction_coefficient'] - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] + mass = inputs[Dynamic.Vehicle.MASS] + lift = inputs[Dynamic.Vehicle.LIFT] weight = mass * grav_metric f_v = lift - weight - idx_sup = np.where(f_v < 0.) + idx_sup = np.where(f_v < 0.0) friction = np.zeros(nn) friction[idx_sup] = friction_coefficient * grav_metric - J['forces_horizontal', Dynamic.Mission.MASS] = friction + J['forces_horizontal', Dynamic.Vehicle.MASS] = friction friction = np.zeros(nn) friction[idx_sup] = -friction_coefficient - J['forces_horizontal', Dynamic.Mission.LIFT] = friction + J['forces_horizontal', Dynamic.Vehicle.LIFT] = friction diff --git a/aviary/mission/flops_based/ode/landing_ode.py b/aviary/mission/flops_based/ode/landing_ode.py index cad16438a3..cdf20065f4 100644 --- a/aviary/mission/flops_based/ode/landing_ode.py +++ b/aviary/mission/flops_based/ode/landing_ode.py @@ -1,103 +1,40 @@ -''' +""" Define the ODEs for landing. Classes ------- FlareODE : the ODE for the flare phase of landing -''' +""" import numpy as np - import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.mission.flops_based.ode.landing_eom import FlareEOM, StallSpeed +from aviary.mission.base_ode import BaseODE as _BaseODE +from aviary.mission.flops_based.ode.landing_eom import FlareEOM +from aviary.mission.flops_based.ode.takeoff_ode import StallSpeed from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE as _TakeoffODE -from aviary.mission.gasp_based.ode.time_integration_base_classes import ( - add_SGM_required_inputs, -) -from aviary.mission.utils import ExternalSubsystemGroup -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import AnalysisScheme +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.variable_info.variables import Aircraft, Dynamic, Mission class LandingODE(_TakeoffODE): - ''' - Define the ODE for most phases of landing. - ''' + """Define the ODE for most phases of landing.""" # region : derived type customization points stall_speed_lift_coefficient_name = Mission.Landing.LIFT_COEFFICIENT_MAX # endregion : derived type customization points -class FlareODE(om.Group): - ''' - Define the ODE for the flare phase of landing. - ''' - - def initialize(self): - options = self.options - - options.declare( - 'num_nodes', - default=1, - types=int, - desc='Number of nodes to be evaluated in the RHS', - ) - - options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - ) - - self.options.declare( - 'subsystem_options', - types=dict, - default={}, - desc='dictionary of parameters to be passed to the subsystem builders', - ) - - self.options.declare( - 'core_subsystems', - desc='list of core subsystem builder instances to be added to the ODE', - ) - self.options.declare( - 'external_subsystems', - default=[], - desc='list of external subsystem builder instances to be added to the ODE', - ) - - self.options.declare( - "analysis_scheme", - default=AnalysisScheme.COLLOCATION, - types=AnalysisScheme, - desc="The analysis method that will be used to close the trajectory; for example collocation or time integration", - ) +class FlareODE(_BaseODE): + """Define the ODE for the flare phase of landing.""" def setup(self): options = self.options - nn = options["num_nodes"] - analysis_scheme = options['analysis_scheme'] - aviary_options = options['aviary_options'] - subsystem_options = options['subsystem_options'] - core_subsystems = options['core_subsystems'] - - if analysis_scheme is AnalysisScheme.SHOOTING: - SGM_required_inputs = { - 't_curr': {'units': 's'}, - Dynamic.Mission.DISTANCE: {'units': 'm'}, - } - add_SGM_required_inputs(self, SGM_required_inputs) - - self.add_subsystem( - name='atmosphere', subsys=Atmosphere(num_nodes=nn), promotes=['*'] - ) + nn = options['num_nodes'] + self.add_subsystem(name='atmosphere', subsys=Atmosphere(num_nodes=nn), promotes=['*']) - # NOTE: the following are potentially signficant differences in implementation + # NOTE: the following are potentially significant differences in implementation # between FLOPS and Aviary: # - FLOPS detailed takeoff/landing assumes constant mass for the duration of # that specific analysis. @@ -105,62 +42,19 @@ def setup(self): # mass to vary as needed as a function of time and variation in related # optimization control variables. self.add_subsystem( - "stall_speed", + 'stall_speed', StallSpeed(num_nodes=nn), promotes_inputs=[ - "mass", - Dynamic.Mission.DENSITY, + 'mass', + Dynamic.Atmosphere.DENSITY, ('area', Aircraft.Wing.AREA), - ("lift_coefficient_max", Mission.Landing.LIFT_COEFFICIENT_MAX), + ('lift_coefficient_max', Mission.Landing.LIFT_COEFFICIENT_MAX), ], - promotes_outputs=[("stall_speed", "v_stall")], + promotes_outputs=[('stall_speed', 'v_stall')], ) - base_options = {'num_nodes': nn, 'aviary_inputs': aviary_options} - - for subsystem in core_subsystems: - # check if subsystem_options has entry for a subsystem of this name - if subsystem.name in subsystem_options: - kwargs = subsystem_options[subsystem.name] - else: - kwargs = {} - - kwargs.update(base_options) - system = subsystem.build_mission(**kwargs) - - if system is not None: - self.add_subsystem( - subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs), - ) - - # Create a lightly modified version of an OM group to add external subsystems - # to the ODE with a special configure() method that promotes - # all aircraft:* and mission:* variables to the ODE. - external_subsystem_group = ExternalSubsystemGroup() - add_subsystem_group = False - - for subsystem in self.options['external_subsystems']: - subsystem_mission = subsystem.build_mission( - num_nodes=nn, aviary_inputs=aviary_options - ) - if subsystem_mission is not None: - add_subsystem_group = True - external_subsystem_group.add_subsystem( - subsystem.name, subsystem_mission - ) - - # Only add the external subsystem group if it has at least one subsystem. - # Without this logic there'd be an empty OM group added to the ODE. - if add_subsystem_group: - self.add_subsystem( - name='external_subsystems', - subsys=external_subsystem_group, - promotes_inputs=['*'], - promotes_outputs=['*'], - ) + self.add_core_subsystems() + self.add_external_subsystems() kwargs = {'num_nodes': nn, 'aviary_options': options['aviary_options']} @@ -170,11 +64,11 @@ def setup(self): promotes_inputs=[ Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, - 'angle_of_attack', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, 'angle_of_attack_rate', Mission.Landing.FLARE_RATE, ], diff --git a/aviary/mission/flops_based/ode/mission_EOM.py b/aviary/mission/flops_based/ode/mission_EOM.py index 1bb2bf10b5..1b54f43244 100644 --- a/aviary/mission/flops_based/ode/mission_EOM.py +++ b/aviary/mission/flops_based/ode/mission_EOM.py @@ -8,11 +8,12 @@ class MissionEOM(om.Group): - """Define the mission equation of motion for the energy method""" + """Define the mission equation of motion for the energy method.""" def initialize(self): - self.options.declare('num_nodes', types=int, - desc='Number of nodes to be evaluated in the RHS') + self.options.declare( + 'num_nodes', types=int, desc='Number of nodes to be evaluated in the RHS' + ) def setup(self): nn = self.options['num_nodes'] @@ -20,37 +21,55 @@ def setup(self): self.add_subsystem( name='required_thrust', subsys=RequiredThrust(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.DRAG, - Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY, - Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.MASS], - promotes_outputs=['thrust_required']) + promotes_inputs=[ + Dynamic.Vehicle.DRAG, + Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.VELOCITY_RATE, + Dynamic.Vehicle.MASS, + ], + promotes_outputs=['thrust_required'], + ) self.add_subsystem( name='groundspeed', subsys=RangeRate(num_nodes=nn), promotes_inputs=[ Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY], - promotes_outputs=[Dynamic.Mission.DISTANCE_RATE]) + Dynamic.Mission.VELOCITY, + ], + promotes_outputs=[Dynamic.Mission.DISTANCE_RATE], + ) self.add_subsystem( name='excess_specific_power', subsys=SpecificEnergyRate(num_nodes=nn), promotes_inputs=[ - (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), + ( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + ), Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, Dynamic.Mission.DRAG], - promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)]) + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.DRAG, + ], + promotes_outputs=[ + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ) + ], + ) self.add_subsystem( name=Dynamic.Mission.ALTITUDE_RATE_MAX, - subsys=AltitudeRate( - num_nodes=nn), + subsys=AltitudeRate(num_nodes=nn), promotes_inputs=[ - (Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ), Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.VELOCITY], - promotes_outputs=[ - (Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX)]) + Dynamic.Mission.VELOCITY, + ], + promotes_outputs=[(Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX)], + ) diff --git a/aviary/mission/flops_based/ode/mission_ODE.py b/aviary/mission/flops_based/ode/mission_ODE.py deleted file mode 100644 index 95d95c81f9..0000000000 --- a/aviary/mission/flops_based/ode/mission_ODE.py +++ /dev/null @@ -1,295 +0,0 @@ -import numpy as np - -import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere - -from aviary.mission.flops_based.ode.mission_EOM import MissionEOM -from aviary.mission.gasp_based.ode.time_integration_base_classes import ( - add_SGM_required_inputs, - add_SGM_required_outputs, -) -from aviary.subsystems.propulsion.throttle_allocation import ThrottleAllocator -from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import promote_aircraft_and_mission_vars -from aviary.variable_info.enums import AnalysisScheme, ThrottleAllocation, SpeedType -from aviary.variable_info.variable_meta_data import _MetaData -from aviary.variable_info.variables import Aircraft, Dynamic, Mission - - -class ExternalSubsystemGroup(om.Group): - """ - For external subsystem group, promote relevant aircraft and mission variables. - """ - - def configure(self): - promote_aircraft_and_mission_vars(self) - - -class MissionODE(om.Group): - """Define the ODE of motion""" - - def initialize(self): - self.options.declare( - 'num_nodes', types=int, desc='Number of nodes to be evaluated in the RHS' - ) - self.options.declare( - 'subsystem_options', - types=dict, - default={}, - desc='dictionary of parameters to be passed to the subsystem builders', - ) - self.options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - ) - self.options.declare( - 'core_subsystems', - desc='list of core subsystem builder instances to be added to the ODE', - ) - self.options.declare( - 'external_subsystems', - default=[], - desc='list of external subsystem builder instances to be added to the ODE', - ) - self.options.declare( - 'meta_data', - default=_MetaData, - desc='metadata associated with the variables to be passed into the ODE', - ) - self.options.declare( - 'use_actual_takeoff_mass', - default=False, - desc='flag to use actual takeoff mass in the climb phase, otherwise assume 100 kg fuel burn', - ) - self.options.declare( - 'throttle_enforcement', - default='path_constraint', - values=['path_constraint', 'boundary_constraint', 'bounded', None], - desc='flag to enforce throttle constraints on the path or at the segment boundaries or using solver bounds', - ) - self.options.declare( - 'throttle_allocation', - default=ThrottleAllocation.FIXED, - types=ThrottleAllocation, - desc='Flag that determines how to handle throttles for multiple engines.', - ) - self.options.declare( - "analysis_scheme", - default=AnalysisScheme.COLLOCATION, - types=AnalysisScheme, - desc="The analysis method that will be used to close the trajectory; for example collocation or time integration", - ) - - def setup(self): - options = self.options - nn = options['num_nodes'] - analysis_scheme = options['analysis_scheme'] - aviary_options = options['aviary_options'] - core_subsystems = options['core_subsystems'] - subsystem_options = options['subsystem_options'] - num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - - if analysis_scheme is AnalysisScheme.SHOOTING: - SGM_required_inputs = { - 't_curr': {'units': 's'}, - Dynamic.Mission.DISTANCE: {'units': 'm'}, - } - add_SGM_required_inputs(self, SGM_required_inputs) - - self.add_subsystem( - name='atmosphere', - subsys=Atmosphere(num_nodes=nn, input_speed_type=SpeedType.MACH), - promotes=['*'], - ) - - # add execcomp to compute velocity_rate based off mach_rate and sos - self.add_subsystem( - name='velocity_rate_comp', - subsys=om.ExecComp( - 'velocity_rate = mach_rate * sos', - mach_rate={'units': 'unitless/s', 'shape': (nn,)}, - sos={'units': 'm/s', 'shape': (nn,)}, - velocity_rate={'units': 'm/s**2', 'shape': (nn,)}, - has_diag_partials=True, - ), - promotes_inputs=[ - ('mach_rate', Dynamic.Mission.MACH_RATE), - ('sos', Dynamic.Mission.SPEED_OF_SOUND), - ], - promotes_outputs=[('velocity_rate', Dynamic.Mission.VELOCITY_RATE)], - ) - - base_options = {'num_nodes': nn, 'aviary_inputs': aviary_options} - - for subsystem in core_subsystems: - # check if subsystem_options has entry for a subsystem of this name - if subsystem.name in subsystem_options: - kwargs = subsystem_options[subsystem.name] - else: - kwargs = {} - - kwargs.update(base_options) - system = subsystem.build_mission(**kwargs) - - if system is not None: - self.add_subsystem( - subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs), - ) - - # Create a lightly modified version of an OM group to add external subsystems - # to the ODE with a special configure() method that promotes - # all aircraft:* and mission:* variables to the ODE. - external_subsystem_group = ExternalSubsystemGroup() - add_subsystem_group = False - - for subsystem in self.options['external_subsystems']: - subsystem_mission = subsystem.build_mission( - num_nodes=nn, aviary_inputs=aviary_options - ) - if subsystem_mission is not None: - add_subsystem_group = True - external_subsystem_group.add_subsystem( - subsystem.name, subsystem_mission - ) - - # Only add the external subsystem group if it has at least one subsystem. - # Without this logic there'd be an empty OM group added to the ODE. - if add_subsystem_group: - self.add_subsystem( - name='external_subsystems', - subsys=external_subsystem_group, - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - self.add_subsystem( - name='mission_EOM', - subsys=MissionEOM(num_nodes=nn), - promotes_inputs=[ - Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_MAX_TOTAL, - Dynamic.Mission.DRAG, - Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY_RATE, - ], - promotes_outputs=[ - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, - Dynamic.Mission.ALTITUDE_RATE_MAX, - Dynamic.Mission.DISTANCE_RATE, - 'thrust_required', - ], - ) - - # THROTTLE Section - # TODO: Split this out into a function that can be used by the other ODEs. - if num_engine_type > 1: - - # Multi Engine - - self.add_subsystem( - name='throttle_balance', - subsys=om.BalanceComp( - name="aggregate_throttle", - units="unitless", - val=np.ones((nn,)), - lhs_name='thrust_required', - rhs_name=Dynamic.Mission.THRUST_TOTAL, - eq_units="lbf", - normalize=False, - res_ref=1.0e6, - ), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - self.add_subsystem( - "throttle_allocator", - ThrottleAllocator( - num_nodes=nn, - aviary_options=aviary_options, - throttle_allocation=self.options['throttle_allocation'], - ), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - else: - - # Single Engine - - # Add a balance comp to compute throttle based on the required thrust. - self.add_subsystem( - name='throttle_balance', - subsys=om.BalanceComp( - name=Dynamic.Mission.THROTTLE, - units="unitless", - val=np.ones((nn,)), - lhs_name='thrust_required', - rhs_name=Dynamic.Mission.THRUST_TOTAL, - eq_units="lbf", - normalize=False, - lower=0.0 if options['throttle_enforcement'] == 'bounded' else None, - upper=1.0 if options['throttle_enforcement'] == 'bounded' else None, - res_ref=1.0e6, - ), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) - - self.set_input_defaults(Dynamic.Mission.THROTTLE, val=1.0, units='unitless') - - self.set_input_defaults(Dynamic.Mission.MACH, val=np.ones(nn), units='unitless') - self.set_input_defaults(Dynamic.Mission.MASS, val=np.ones(nn), units='kg') - self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.ones(nn), units='m/s') - self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.ones(nn), units='m') - self.set_input_defaults( - Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), units='m/s' - ) - - if options['use_actual_takeoff_mass']: - exec_comp_string = 'initial_mass_residual = initial_mass - mass[0]' - initial_mass_string = Mission.Takeoff.FINAL_MASS - else: - exec_comp_string = 'initial_mass_residual = initial_mass - mass[0] - 100.' - initial_mass_string = Mission.Summary.GROSS_MASS - - # Experimental: Add a component to constrain the initial mass to be equal to design gross weight. - initial_mass_residual_constraint = om.ExecComp( - exec_comp_string, - initial_mass={'units': 'kg'}, - mass={'units': 'kg', 'shape': (nn,)}, - initial_mass_residual={'units': 'kg', 'res_ref': 1.0e5}, - ) - - self.add_subsystem( - 'initial_mass_residual_constraint', - initial_mass_residual_constraint, - promotes_inputs=[ - ('initial_mass', initial_mass_string), - ('mass', Dynamic.Mission.MASS), - ], - promotes_outputs=['initial_mass_residual'], - ) - - if analysis_scheme is AnalysisScheme.SHOOTING: - SGM_required_outputs = { - Dynamic.Mission.ALTITUDE_RATE: {'units': 'm/s'}, - } - add_SGM_required_outputs(self, SGM_required_outputs) - - print_level = 0 if analysis_scheme is AnalysisScheme.SHOOTING else 2 - - self.nonlinear_solver = om.NewtonSolver( - solve_subsystems=True, - atol=1.0e-10, - rtol=1.0e-10, - ) - self.nonlinear_solver.linesearch = om.BoundsEnforceLS() - self.linear_solver = om.DirectSolver(assemble_jac=True) - self.nonlinear_solver.options['err_on_non_converge'] = True - self.nonlinear_solver.options['iprint'] = print_level diff --git a/aviary/mission/flops_based/ode/range_rate.py b/aviary/mission/flops_based/ode/range_rate.py index 12f4fcc0f5..c3e64ced30 100644 --- a/aviary/mission/flops_based/ode/range_rate.py +++ b/aviary/mission/flops_based/ode/range_rate.py @@ -7,7 +7,7 @@ class RangeRate(om.ExplicitComponent): """ Compute the range rate using equation: - distance_rate = (velocity**2 - climb_rate**2)**0.5 + distance_rate = (velocity**2 - climb_rate**2)**0.5. """ def initialize(self): @@ -20,17 +20,20 @@ def setup(self): Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), desc='climb rate', - units='m/s') + units='m/s', + ) self.add_input( Dynamic.Mission.VELOCITY, val=np.ones(nn), desc='current velocity', - units='m/s') + units='m/s', + ) self.add_output( Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc='current horizontal velocity (assumed no wind)', - units='m/s') + units='m/s', + ) def compute(self, inputs, outputs): climb_rate = inputs[Dynamic.Mission.ALTITUDE_RATE] @@ -38,21 +41,25 @@ def compute(self, inputs, outputs): climb_rate_2 = climb_rate**2 velocity_2 = velocity**2 if (climb_rate_2 >= velocity_2).any(): - raise om.AnalysisError( - "WARNING: climb rate exceeds velocity (range_rate.py)") - outputs[Dynamic.Mission.DISTANCE_RATE] = (velocity_2 - climb_rate_2)**0.5 + raise om.AnalysisError('WARNING: climb rate exceeds velocity (range_rate.py)') + outputs[Dynamic.Mission.DISTANCE_RATE] = (velocity_2 - climb_rate_2) ** 0.5 def setup_partials(self): arange = np.arange(self.options['num_nodes']) self.declare_partials( - Dynamic.Mission.DISTANCE_RATE, [ - Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], rows=arange, cols=arange) + Dynamic.Mission.DISTANCE_RATE, + [Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], + rows=arange, + cols=arange, + ) def compute_partials(self, inputs, J): climb_rate = inputs[Dynamic.Mission.ALTITUDE_RATE] velocity = inputs[Dynamic.Mission.VELOCITY] - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] = -climb_rate / \ - (velocity**2 - climb_rate**2)**0.5 - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = velocity / \ - (velocity**2 - climb_rate**2)**0.5 + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] = ( + -climb_rate / (velocity**2 - climb_rate**2) ** 0.5 + ) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = ( + velocity / (velocity**2 - climb_rate**2) ** 0.5 + ) diff --git a/aviary/mission/flops_based/ode/required_thrust.py b/aviary/mission/flops_based/ode/required_thrust.py index af3c5ed621..82b6b39a43 100644 --- a/aviary/mission/flops_based/ode/required_thrust.py +++ b/aviary/mission/flops_based/ode/required_thrust.py @@ -1,5 +1,6 @@ -import openmdao.api as om import numpy as np +import openmdao.api as om + from aviary.constants import GRAV_METRIC_FLOPS as gravity from aviary.variable_info.variables import Dynamic @@ -7,7 +8,7 @@ class RequiredThrust(om.ExplicitComponent): """ Computes the required thrust using the equation: - thrust_required = drag + (altitude_rate*gravity/velocity + velocity_rate) * mass + thrust_required = drag + (altitude_rate*gravity/velocity + velocity_rate) * mass. """ def initialize(self): @@ -16,37 +17,45 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - self.add_input(Dynamic.Mission.DRAG, val=np.zeros(nn), - units='N', desc='drag force') - self.add_input(Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), - units='m/s', desc='rate of change of altitude') - self.add_input(Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units='m/s', desc=Dynamic.Mission.VELOCITY) - self.add_input(Dynamic.Mission.VELOCITY_RATE, val=np.zeros( - nn), units='m/s**2', desc='rate of change of velocity') - self.add_input(Dynamic.Mission.MASS, val=np.zeros( - nn), units='kg', desc='mass of the aircraft') - self.add_output('thrust_required', val=np.zeros( - nn), units='N', desc='required thrust') + self.add_input(Dynamic.Vehicle.DRAG, val=np.zeros(nn), units='N', desc='drag force') + self.add_input( + Dynamic.Mission.ALTITUDE_RATE, + val=np.zeros(nn), + units='m/s', + desc='rate of change of altitude', + ) + self.add_input( + Dynamic.Mission.VELOCITY, + val=np.zeros(nn), + units='m/s', + desc=Dynamic.Mission.VELOCITY, + ) + self.add_input( + Dynamic.Mission.VELOCITY_RATE, + val=np.zeros(nn), + units='m/s**2', + desc='rate of change of velocity', + ) + self.add_input( + Dynamic.Vehicle.MASS, val=np.zeros(nn), units='kg', desc='mass of the aircraft' + ) + self.add_output('thrust_required', val=np.zeros(nn), units='N', desc='required thrust') ar = np.arange(nn) - self.declare_partials('thrust_required', Dynamic.Mission.DRAG, rows=ar, cols=ar) - self.declare_partials( - 'thrust_required', Dynamic.Mission.ALTITUDE_RATE, rows=ar, cols=ar) - self.declare_partials( - 'thrust_required', Dynamic.Mission.VELOCITY, rows=ar, cols=ar) - self.declare_partials( - 'thrust_required', Dynamic.Mission.VELOCITY_RATE, rows=ar, cols=ar) - self.declare_partials('thrust_required', Dynamic.Mission.MASS, rows=ar, cols=ar) + self.declare_partials('thrust_required', Dynamic.Vehicle.DRAG, rows=ar, cols=ar) + self.declare_partials('thrust_required', Dynamic.Mission.ALTITUDE_RATE, rows=ar, cols=ar) + self.declare_partials('thrust_required', Dynamic.Mission.VELOCITY, rows=ar, cols=ar) + self.declare_partials('thrust_required', Dynamic.Mission.VELOCITY_RATE, rows=ar, cols=ar) + self.declare_partials('thrust_required', Dynamic.Vehicle.MASS, rows=ar, cols=ar) def compute(self, inputs, outputs): - drag = inputs[Dynamic.Mission.DRAG] + drag = inputs[Dynamic.Vehicle.DRAG] altitude_rate = inputs[Dynamic.Mission.ALTITUDE_RATE] velocity = inputs[Dynamic.Mission.VELOCITY] velocity_rate = inputs[Dynamic.Mission.VELOCITY_RATE] - mass = inputs[Dynamic.Mission.MASS] + mass = inputs[Dynamic.Vehicle.MASS] - thrust_required = drag + (altitude_rate*gravity/velocity + velocity_rate) * mass + thrust_required = drag + (altitude_rate * gravity / velocity + velocity_rate) * mass outputs['thrust_required'] = thrust_required @@ -54,12 +63,14 @@ def compute_partials(self, inputs, partials): altitude_rate = inputs[Dynamic.Mission.ALTITUDE_RATE] velocity = inputs[Dynamic.Mission.VELOCITY] velocity_rate = inputs[Dynamic.Mission.VELOCITY_RATE] - mass = inputs[Dynamic.Mission.MASS] + mass = inputs[Dynamic.Vehicle.MASS] - partials['thrust_required', Dynamic.Mission.DRAG] = 1.0 - partials['thrust_required', Dynamic.Mission.ALTITUDE_RATE] = gravity/velocity * mass - partials['thrust_required', Dynamic.Mission.VELOCITY] = - \ - altitude_rate*gravity/velocity**2 * mass + partials['thrust_required', Dynamic.Vehicle.DRAG] = 1.0 + partials['thrust_required', Dynamic.Mission.ALTITUDE_RATE] = gravity / velocity * mass + partials['thrust_required', Dynamic.Mission.VELOCITY] = ( + -altitude_rate * gravity / velocity**2 * mass + ) partials['thrust_required', Dynamic.Mission.VELOCITY_RATE] = mass - partials['thrust_required', Dynamic.Mission.MASS] = altitude_rate * \ - gravity/velocity + velocity_rate + partials['thrust_required', Dynamic.Vehicle.MASS] = ( + altitude_rate * gravity / velocity + velocity_rate + ) diff --git a/aviary/mission/flops_based/ode/takeoff_eom.py b/aviary/mission/flops_based/ode/takeoff_eom.py index d0d1ab4d04..6a466cc8b7 100644 --- a/aviary/mission/flops_based/ode/takeoff_eom.py +++ b/aviary/mission/flops_based/ode/takeoff_eom.py @@ -1,21 +1,19 @@ -''' -Define utilities for calculating takeoff EOMs. -''' +"""Define utilities for calculating takeoff EOMs.""" + import numpy as np import openmdao.api as om from aviary.constants import GRAV_METRIC_FLOPS as grav_metric - from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Dynamic, Mission class StallSpeed(om.ExplicitComponent): - ''' + """ Define a component for calculating the minimum speed of an aircraft required to produce lift. - ''' + """ def initialize(self): options = self.options @@ -27,27 +25,28 @@ def setup(self): nn = options['num_nodes'] - self.add_input( - 'mass', val=np.ones(nn), units='kg', desc='current mass of the aircraft') + self.add_input('mass', val=np.ones(nn), units='kg', desc='current mass of the aircraft') add_aviary_input( self, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=np.ones(nn), units='kg/m**3', desc='current atmospheric density', ) - self.add_input( - 'area', val=1., units='m**2', desc='surface area contributing to lift') + self.add_input('area', val=1.0, units='m**2', desc='surface area contributing to lift') self.add_input( - 'lift_coefficient_max', val=1., units='unitless', - desc='maximum lift coefficient') + 'lift_coefficient_max', val=1.0, units='unitless', desc='maximum lift coefficient' + ) self.add_output( - 'stall_speed', val=np.zeros(nn), units='m/s', - desc='minimum speed of an aircraft required to produce lift') + 'stall_speed', + val=np.zeros(nn), + units='m/s', + desc='minimum speed of an aircraft required to produce lift', + ) def setup_partials(self): options = self.options @@ -57,7 +56,7 @@ def setup_partials(self): self.declare_partials( 'stall_speed', - ['mass', Dynamic.Mission.DENSITY], + ['mass', Dynamic.Atmosphere.DENSITY], rows=rows_cols, cols=rows_cols, ) @@ -66,43 +65,44 @@ def setup_partials(self): def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): mass = inputs['mass'] - density = inputs[Dynamic.Mission.DENSITY] + density = inputs[Dynamic.Atmosphere.DENSITY] area = inputs['area'] lift_coefficient_max = inputs['lift_coefficient_max'] weight = mass * grav_metric - stall_speed = (2. * weight / (density * area * lift_coefficient_max))**0.5 + stall_speed = (2.0 * weight / (density * area * lift_coefficient_max)) ** 0.5 outputs['stall_speed'] = stall_speed def compute_partials(self, inputs, J, discrete_inputs=None): mass = inputs['mass'] - density = inputs[Dynamic.Mission.DENSITY] + density = inputs[Dynamic.Atmosphere.DENSITY] area = inputs['area'] lift_coefficient_max = inputs['lift_coefficient_max'] weight = mass * grav_metric - stall_speed = (2. * weight / (density * area * lift_coefficient_max))**0.5 + stall_speed = (2.0 * weight / (density * area * lift_coefficient_max)) ** 0.5 - J['stall_speed', 'mass'] = \ - grav_metric / (stall_speed * density * area * lift_coefficient_max) + J['stall_speed', 'mass'] = grav_metric / ( + stall_speed * density * area * lift_coefficient_max + ) - J['stall_speed', Dynamic.Mission.DENSITY] = -weight / ( + J['stall_speed', Dynamic.Atmosphere.DENSITY] = -weight / ( stall_speed * density**2 * area * lift_coefficient_max ) - J['stall_speed', 'area'] = \ - -weight / (stall_speed * density * area**2 * lift_coefficient_max) + J['stall_speed', 'area'] = -weight / ( + stall_speed * density * area**2 * lift_coefficient_max + ) - J['stall_speed', 'lift_coefficient_max'] = \ - -weight / (stall_speed * density * area * lift_coefficient_max**2) + J['stall_speed', 'lift_coefficient_max'] = -weight / ( + stall_speed * density * area * lift_coefficient_max**2 + ) class TakeoffEOM(om.Group): - ''' - Define a group for calculating takeoff equations of motion. - ''' + """Define a group for calculating takeoff equations of motion.""" def initialize(self): options = self.options @@ -110,18 +110,19 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'climbing', default=False, types=bool, - desc='mode of operation (ground roll or flight)' + 'climbing', default=False, types=bool, desc='mode of operation (ground roll or flight)' ) options.declare( 'friction_key', - desc='current friction coefficient key, ' - 'either rolling friction or braking friction') + desc='current friction coefficient key, either rolling friction or braking friction', + ) options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): options = self.options @@ -132,61 +133,65 @@ def setup(self): aviary_options = options['aviary_options'] mu = aviary_options.get_val(friction_key) - kwargs = { - 'num_nodes': nn, - 'climbing': climbing - } + kwargs = {'num_nodes': nn, 'climbing': climbing} inputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY] outputs = [Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE] self.add_subsystem( - 'distance_rates', DistanceRates(**kwargs), - promotes_inputs=inputs, promotes_outputs=outputs + 'distance_rates', + DistanceRates(**kwargs), + promotes_inputs=inputs, + promotes_outputs=outputs, ) kwargs = { 'num_nodes': nn, 'climbing': climbing, 'friction_coefficient': mu, - 'aviary_options': aviary_options + 'aviary_options': aviary_options, } self.add_subsystem( 'sum_forces', SumForces(**kwargs), promotes_inputs=['*'], - promotes_outputs=['forces_horizontal', 'forces_vertical']) + promotes_outputs=['forces_horizontal', 'forces_vertical'], + ) self.add_subsystem( - 'accelerations', Accelerations(num_nodes=nn), + 'accelerations', + Accelerations(num_nodes=nn), promotes_inputs=['*'], - promotes_outputs=['*'] + promotes_outputs=['*'], ) self.add_subsystem( - 'velocity_rate', VelocityRate(num_nodes=nn), + 'velocity_rate', + VelocityRate(num_nodes=nn), promotes_inputs=['*'], - promotes_outputs=['*'] + promotes_outputs=['*'], ) self.add_subsystem( - 'flight_path_angle_rate', FlightPathAngleRate(num_nodes=nn), + 'flight_path_angle_rate', + FlightPathAngleRate(num_nodes=nn), promotes_inputs=['*'], - promotes_outputs=['*'] + promotes_outputs=['*'], ) self.add_subsystem( 'climb_gradient_forces', ClimbGradientForces(num_nodes=nn, aviary_options=aviary_options), - promotes=['*']) + promotes=['*'], + ) class DistanceRates(om.ExplicitComponent): - ''' + """ Define a component for calculating takeoff horizontal and vertical velocity components. - ''' + """ def initialize(self): options = self.options @@ -194,8 +199,7 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'climbing', default=False, types=bool, - desc='mode of operation (ground roll or flight)' + 'climbing', default=False, types=bool, desc='mode of operation (ground roll or flight)' ) def setup(self): @@ -203,14 +207,11 @@ def setup(self): nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') add_aviary_input(self, Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='m/s') - add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, - val=np.zeros(nn), units='m/s') - add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, - val=np.zeros(nn), units='m/s') + add_aviary_output(self, Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_output(self, Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') def setup_partials(self): options = self.options @@ -224,10 +225,16 @@ def setup_partials(self): else: self.declare_partials( - Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE, dependent=False) + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + dependent=False, + ) self.declare_partials( - Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY, val=np.identity(nn)) + Dynamic.Mission.DISTANCE_RATE, + Dynamic.Mission.VELOCITY, + val=np.identity(nn), + ) self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, '*', dependent=False) @@ -266,9 +273,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): class Accelerations(om.ExplicitComponent): - ''' - Define a component for calculating horizontal and vertical accelerations from forces. - ''' + """Define a component for calculating horizontal and vertical accelerations from forces.""" def initialize(self): options = self.options @@ -278,23 +283,35 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') self.add_input( - 'forces_horizontal', val=np.zeros(nn), units='N', - desc='current sum of forces in the horizontal direction') + 'forces_horizontal', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the horizontal direction', + ) self.add_input( - 'forces_vertical', val=np.zeros(nn), units='N', - desc='current sum of forces in the vertical direction') + 'forces_vertical', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the vertical direction', + ) self.add_output( - 'acceleration_horizontal', val=np.zeros(nn), - desc='current horizontal acceleration', units='m/s**2') + 'acceleration_horizontal', + val=np.zeros(nn), + desc='current horizontal acceleration', + units='m/s**2', + ) self.add_output( - 'acceleration_vertical', val=np.zeros(nn), - desc='current vertical acceleration', units='m/s**2') + 'acceleration_vertical', + val=np.zeros(nn), + desc='current vertical acceleration', + units='m/s**2', + ) def setup_partials(self): nn = self.options['num_nodes'] @@ -302,26 +319,33 @@ def setup_partials(self): rows_cols = np.arange(nn) self.declare_partials( - 'acceleration_horizontal', Dynamic.Mission.MASS, rows=rows_cols, cols=rows_cols) + 'acceleration_horizontal', + Dynamic.Vehicle.MASS, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'acceleration_vertical', Dynamic.Mission.MASS, rows=rows_cols, cols=rows_cols) + 'acceleration_vertical', + Dynamic.Vehicle.MASS, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'acceleration_horizontal', 'forces_horizontal', rows=rows_cols, - cols=rows_cols) + 'acceleration_horizontal', 'forces_horizontal', rows=rows_cols, cols=rows_cols + ) - self.declare_partials( - 'acceleration_vertical', 'forces_horizontal', dependent=False) + self.declare_partials('acceleration_vertical', 'forces_horizontal', dependent=False) - self.declare_partials( - 'acceleration_horizontal', 'forces_vertical', dependent=False) + self.declare_partials('acceleration_horizontal', 'forces_vertical', dependent=False) self.declare_partials( - 'acceleration_vertical', 'forces_vertical', rows=rows_cols, cols=rows_cols) + 'acceleration_vertical', 'forces_vertical', rows=rows_cols, cols=rows_cols + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - mass = inputs[Dynamic.Mission.MASS] + mass = inputs[Dynamic.Vehicle.MASS] f_h = inputs['forces_horizontal'] f_v = inputs['forces_vertical'] @@ -332,24 +356,22 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): outputs['acceleration_vertical'] = a_v def compute_partials(self, inputs, J, discrete_inputs=None): - mass = inputs[Dynamic.Mission.MASS] + mass = inputs[Dynamic.Vehicle.MASS] f_h = inputs['forces_horizontal'] f_v = inputs['forces_vertical'] m2 = mass * mass - J['acceleration_horizontal', Dynamic.Mission.MASS] = -f_h / m2 - J['acceleration_vertical', Dynamic.Mission.MASS] = -f_v / m2 + J['acceleration_horizontal', Dynamic.Vehicle.MASS] = -f_h / m2 + J['acceleration_vertical', Dynamic.Vehicle.MASS] = -f_v / m2 - J['acceleration_horizontal', 'forces_horizontal'] = 1. / mass + J['acceleration_horizontal', 'forces_horizontal'] = 1.0 / mass - J['acceleration_vertical', 'forces_vertical'] = 1. / mass + J['acceleration_vertical', 'forces_vertical'] = 1.0 / mass class VelocityRate(om.ExplicitComponent): - ''' - Define a component for calculating total acceleration. - ''' + """Define a component for calculating total acceleration.""" def initialize(self): options = self.options @@ -360,20 +382,23 @@ def setup(self): nn = self.options['num_nodes'] self.add_input( - 'acceleration_horizontal', val=np.zeros(nn), - desc='current horizontal acceleration', units='m/s**2') + 'acceleration_horizontal', + val=np.zeros(nn), + desc='current horizontal acceleration', + units='m/s**2', + ) self.add_input( - 'acceleration_vertical', val=np.zeros(nn), - desc='current vertical acceleration', units='m/s**2') + 'acceleration_vertical', + val=np.zeros(nn), + desc='current vertical acceleration', + units='m/s**2', + ) - add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, - val=np.zeros(nn), units='m/s') - add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, - val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') - add_aviary_output(self, Dynamic.Mission.VELOCITY_RATE, - val=np.ones(nn), units='m/s**2') + add_aviary_output(self, Dynamic.Mission.VELOCITY_RATE, val=np.ones(nn), units='m/s**2') rows_cols = np.arange(nn) @@ -394,24 +419,24 @@ def compute_partials(self, inputs, J, discrete_inputs=None): v_h = inputs[Dynamic.Mission.DISTANCE_RATE] v_v = inputs[Dynamic.Mission.ALTITUDE_RATE] - num = (a_h * v_h + a_v * v_v) + num = a_h * v_h + a_v * v_v fact = v_h**2 + v_v**2 den = np.sqrt(fact) J[Dynamic.Mission.VELOCITY_RATE, 'acceleration_horizontal'] = v_h / den J[Dynamic.Mission.VELOCITY_RATE, 'acceleration_vertical'] = v_v / den - J[Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.DISTANCE_RATE] = a_h / den - 0.5 * num / fact**(3/2) * 2.0 * v_h + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.DISTANCE_RATE] = ( + a_h / den - 0.5 * num / fact ** (3 / 2) * 2.0 * v_h + ) - J[Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.ALTITUDE_RATE] = a_v / den - 0.5 * num / fact**(3/2) * 2.0 * v_v + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.ALTITUDE_RATE] = ( + a_v / den - 0.5 * num / fact ** (3 / 2) * 2.0 * v_v + ) class FlightPathAngleRate(om.ExplicitComponent): - ''' - Define a component for calculating flight path angle change rate. - ''' + """Define a component for calculating flight path angle change rate.""" def initialize(self): options = self.options @@ -421,25 +446,29 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, - val=np.zeros(nn), units='m/s') - add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, - val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), units='m/s') + add_aviary_input(self, Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), units='m/s') self.add_input( - 'acceleration_horizontal', val=np.zeros(nn), + 'acceleration_horizontal', + val=np.zeros(nn), desc='current horizontal acceleration', - units='m/s**2' + units='m/s**2', ) self.add_input( - 'acceleration_vertical', val=np.zeros(nn), + 'acceleration_vertical', + val=np.zeros(nn), desc='current vertical acceleration', - units='m/s**2' + units='m/s**2', ) add_aviary_output( - self, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, val=np.zeros(nn), units='rad/s') + self, + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + val=np.zeros(nn), + units='rad/s', + ) rows_cols = np.arange(nn) @@ -461,8 +490,8 @@ def compute_partials(self, inputs, J, discrete_inputs=None): a_h = inputs['acceleration_horizontal'] a_v = inputs['acceleration_vertical'] - num = (a_v * v_h - a_h * v_v) - den = (v_h**2 + v_v**2) + num = a_v * v_h - a_h * v_v + den = v_h**2 + v_v**2 df_dvh = a_v / den - num / den**2 * 2.0 * v_h @@ -479,10 +508,10 @@ def compute_partials(self, inputs, J, discrete_inputs=None): class SumForces(om.ExplicitComponent): - ''' + """ Define a component for calculating the separate sums for both the horizontal and vertical forces. - ''' + """ def initialize(self): options = self.options @@ -490,41 +519,48 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'climbing', default=False, types=bool, - desc='mode of operation (ground roll or flight)' + 'climbing', default=False, types=bool, desc='mode of operation (ground roll or flight)' ) options.declare( - 'friction_coefficient', default=0.025, - desc='current friction coefficient, either rolling friction or braking' - ' friction') + 'friction_coefficient', + default=0.025, + desc='current friction coefficient, either rolling friction or braking friction', + ) options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): options = self.options nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') - self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') + self.add_input(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') self.add_output( - 'forces_horizontal', val=np.zeros(nn), units='N', - desc='current sum of forces in the horizontal direction') + 'forces_horizontal', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the horizontal direction', + ) self.add_output( - 'forces_vertical', val=np.zeros(nn), units='N', - desc='current sum of forces in the vertical direction') + 'forces_vertical', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the vertical direction', + ) def setup_partials(self): options = self.options @@ -535,16 +571,23 @@ def setup_partials(self): rows_cols = np.arange(nn) if climbing: - self.declare_partials('forces_horizontal', - Dynamic.Mission.MASS, dependent=False) + self.declare_partials('forces_horizontal', Dynamic.Vehicle.MASS, dependent=False) self.declare_partials( - 'forces_vertical', Dynamic.Mission.MASS, val=-grav_metric, rows=rows_cols, - cols=rows_cols) + 'forces_vertical', + Dynamic.Vehicle.MASS, + val=-grav_metric, + rows=rows_cols, + cols=rows_cols, + ) wrt = [ - Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.LIFT, Dynamic.Mission.DRAG, 'angle_of_attack', - Dynamic.Mission.FLIGHT_PATH_ANGLE] + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ] self.declare_partials('*', wrt, rows=rows_cols, cols=rows_cols) @@ -555,28 +598,45 @@ def setup_partials(self): val = -grav_metric * mu self.declare_partials( - 'forces_horizontal', Dynamic.Mission.MASS, val=val, rows=rows_cols, - cols=rows_cols) + 'forces_horizontal', + Dynamic.Vehicle.MASS, + val=val, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'forces_horizontal', Dynamic.Mission.LIFT, val=mu, rows=rows_cols, - cols=rows_cols) + 'forces_horizontal', + Dynamic.Vehicle.LIFT, + val=mu, + rows=rows_cols, + cols=rows_cols, + ) t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') val = np.cos(t_inc) + np.sin(t_inc) * mu self.declare_partials( - 'forces_horizontal', Dynamic.Mission.THRUST_TOTAL, val=val, rows=rows_cols, - cols=rows_cols) + 'forces_horizontal', + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + val=val, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'forces_horizontal', Dynamic.Mission.DRAG, val=-1., rows=rows_cols, - cols=rows_cols) + 'forces_horizontal', + Dynamic.Vehicle.DRAG, + val=-1.0, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'forces_horizontal', ['angle_of_attack', - Dynamic.Mission.FLIGHT_PATH_ANGLE], - dependent=False) + 'forces_horizontal', + [Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Mission.FLIGHT_PATH_ANGLE], + dependent=False, + ) self.declare_partials('forces_vertical', ['*'], dependent=False) @@ -588,10 +648,10 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] + mass = inputs[Dynamic.Vehicle.MASS] + lift = inputs[Dynamic.Vehicle.LIFT] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] weight = mass * grav_metric @@ -600,10 +660,9 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): # - section: "COMPUTE TRAJECTORY FROM LIFTOFF UNTIL OBSTACLE HEIGHT IS # REACHED" # - variables: FORCH, FORCV - alpha0 = \ - aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') + alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc + gamma @@ -648,11 +707,11 @@ def compute_partials(self, inputs, J, discrete_inputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - lift = inputs[Dynamic.Mission.LIFT] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] + lift = inputs[Dynamic.Vehicle.LIFT] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc + gamma @@ -663,30 +722,32 @@ def compute_partials(self, inputs, J, discrete_inputs=None): c_gamma = np.cos(gamma) s_gamma = np.sin(gamma) - J['forces_horizontal', Dynamic.Mission.THRUST_TOTAL] = c_angle - J['forces_vertical', Dynamic.Mission.THRUST_TOTAL] = s_angle + J['forces_horizontal', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = c_angle + J['forces_vertical', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = s_angle - J['forces_horizontal', Dynamic.Mission.LIFT] = -s_gamma - J['forces_vertical', Dynamic.Mission.LIFT] = c_gamma + J['forces_horizontal', Dynamic.Vehicle.LIFT] = -s_gamma + J['forces_vertical', Dynamic.Vehicle.LIFT] = c_gamma - J['forces_horizontal', Dynamic.Mission.DRAG] = -c_gamma - J['forces_vertical', Dynamic.Mission.DRAG] = -s_gamma + J['forces_horizontal', Dynamic.Vehicle.DRAG] = -c_gamma + J['forces_vertical', Dynamic.Vehicle.DRAG] = -s_gamma - J['forces_horizontal', 'angle_of_attack'] = -thrust * s_angle - J['forces_vertical', 'angle_of_attack'] = thrust * c_angle + J['forces_horizontal', Dynamic.Vehicle.ANGLE_OF_ATTACK] = -thrust * s_angle + J['forces_vertical', Dynamic.Vehicle.ANGLE_OF_ATTACK] = thrust * c_angle - J['forces_horizontal', Dynamic.Mission.FLIGHT_PATH_ANGLE] = \ + J['forces_horizontal', Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( -thrust * s_angle + drag * s_gamma - lift * c_gamma + ) - J['forces_vertical', Dynamic.Mission.FLIGHT_PATH_ANGLE] = \ + J['forces_vertical', Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( thrust * c_angle - drag * c_gamma - lift * s_gamma + ) class ClimbGradientForces(om.ExplicitComponent): - ''' + """ Define a component for calculating residual forces for evaluation of climb gradient criteria. - ''' + """ def initialize(self): options = self.options @@ -694,33 +755,39 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): options = self.options nn = options['num_nodes'] - add_aviary_input(self, Dynamic.Mission.MASS, val=np.ones(nn), units='kg') - add_aviary_input(self, Dynamic.Mission.LIFT, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), units='N') - add_aviary_input(self, Dynamic.Mission.DRAG, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg') + add_aviary_input(self, Dynamic.Vehicle.LIFT, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), units='N') + add_aviary_input(self, Dynamic.Vehicle.DRAG, val=np.ones(nn), units='N') - self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') + self.add_input(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='rad') self.add_output( - 'climb_gradient_forces_horizontal', val=np.zeros(nn), units='N', - desc='current sum of forces in the horizontal direction; checking for excess' - ' thrust') + 'climb_gradient_forces_horizontal', + val=np.zeros(nn), + units='N', + desc='current sum of forces in the horizontal direction; checking for excess thrust', + ) self.add_output( - 'climb_gradient_forces_vertical', val=np.zeros(nn), units='N', + 'climb_gradient_forces_vertical', + val=np.zeros(nn), + units='N', desc='current sum of forces in the vertical direction; checking for net zero' - ' vertical force') + ' vertical force', + ) def setup_partials(self): options = self.options @@ -732,23 +799,38 @@ def setup_partials(self): self.declare_partials( '*', [ - Dynamic.Mission.MASS, Dynamic.Mission.THRUST_TOTAL, 'angle_of_attack', - Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=rows_cols, cols=rows_cols) + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ], + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'climb_gradient_forces_horizontal', Dynamic.Mission.DRAG, val=-1., - rows=rows_cols, cols=rows_cols) + 'climb_gradient_forces_horizontal', + Dynamic.Vehicle.DRAG, + val=-1.0, + rows=rows_cols, + cols=rows_cols, + ) self.declare_partials( - 'climb_gradient_forces_vertical', Dynamic.Mission.DRAG, dependent=False) + 'climb_gradient_forces_vertical', Dynamic.Vehicle.DRAG, dependent=False + ) self.declare_partials( - 'climb_gradient_forces_horizontal', Dynamic.Mission.LIFT, dependent=False) + 'climb_gradient_forces_horizontal', Dynamic.Vehicle.LIFT, dependent=False + ) self.declare_partials( - 'climb_gradient_forces_vertical', Dynamic.Mission.LIFT, val=1., - rows=rows_cols, cols=rows_cols) + 'climb_gradient_forces_vertical', + Dynamic.Vehicle.LIFT, + val=1.0, + rows=rows_cols, + cols=rows_cols, + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): options = self.options @@ -758,14 +840,14 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] + mass = inputs[Dynamic.Vehicle.MASS] + lift = inputs[Dynamic.Vehicle.LIFT] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] weight = mass * grav_metric - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc @@ -792,14 +874,12 @@ def compute_partials(self, inputs, J, discrete_inputs=None): alpha0 = aviary_options.get_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 'rad') t_inc = aviary_options.get_val(Mission.Takeoff.THRUST_INCIDENCE, 'rad') - mass = inputs[Dynamic.Mission.MASS] - lift = inputs[Dynamic.Mission.LIFT] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] + mass = inputs[Dynamic.Vehicle.MASS] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] weight = mass * grav_metric - alpha = inputs['angle_of_attack'] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] angle = alpha - alpha0 + t_inc @@ -813,14 +893,14 @@ def compute_partials(self, inputs, J, discrete_inputs=None): f_h_key = 'climb_gradient_forces_horizontal' f_v_key = 'climb_gradient_forces_vertical' - J[f_h_key, Dynamic.Mission.MASS] = -grav_metric * s_gamma - J[f_v_key, Dynamic.Mission.MASS] = -grav_metric * c_gamma + J[f_h_key, Dynamic.Vehicle.MASS] = -grav_metric * s_gamma + J[f_v_key, Dynamic.Vehicle.MASS] = -grav_metric * c_gamma - J[f_h_key, Dynamic.Mission.THRUST_TOTAL] = c_angle - J[f_v_key, Dynamic.Mission.THRUST_TOTAL] = s_angle + J[f_h_key, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = c_angle + J[f_v_key, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = s_angle - J[f_h_key, 'angle_of_attack'] = -thrust * s_angle - J[f_v_key, 'angle_of_attack'] = thrust * c_angle + J[f_h_key, Dynamic.Vehicle.ANGLE_OF_ATTACK] = -thrust * s_angle + J[f_v_key, Dynamic.Vehicle.ANGLE_OF_ATTACK] = thrust * c_angle J[f_h_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -weight * c_gamma J[f_v_key, Dynamic.Mission.FLIGHT_PATH_ANGLE] = weight * s_gamma diff --git a/aviary/mission/flops_based/ode/takeoff_ode.py b/aviary/mission/flops_based/ode/takeoff_ode.py index 57278f53f8..7fbbb2479d 100644 --- a/aviary/mission/flops_based/ode/takeoff_ode.py +++ b/aviary/mission/flops_based/ode/takeoff_ode.py @@ -1,104 +1,42 @@ -''' -Define the ODE for takeoff. -''' +"""Define the ODE for takeoff.""" import numpy as np import openmdao.api as om +from aviary.mission.base_ode import BaseODE as _BaseODE from aviary.mission.flops_based.ode.takeoff_eom import StallSpeed, TakeoffEOM -from aviary.mission.gasp_based.ode.time_integration_base_classes import ( - add_SGM_required_inputs, -) -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.utils.aviary_values import AviaryValues -from aviary.mission.utils import ExternalSubsystemGroup -from aviary.variable_info.enums import AnalysisScheme from aviary.variable_info.variables import Aircraft, Dynamic, Mission -class TakeoffODE(om.Group): - ''' - Define the ODE for takeoff. - ''' +class TakeoffODE(_BaseODE): + """Define the ODE for takeoff.""" # region : derived type customization points stall_speed_lift_coefficient_name = Mission.Takeoff.LIFT_COEFFICIENT_MAX # endregion : derived type customization points def initialize(self): - options = self.options - - options.declare( - 'num_nodes', - default=1, - types=int, - desc='Number of nodes to be evaluated in the RHS', - ) - - options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - ) - - self.options.declare( - 'subsystem_options', - types=dict, - default={}, - desc='dictionary of parameters to be passed to the subsystem builders', - ) - - self.options.declare( - 'core_subsystems', - desc='list of core subsystem builder instances to be added to the ODE', - ) + super().initialize() self.options.declare( - 'external_subsystems', - default=[], - desc='list of external subsystem builder instances to be added to the ODE', - ) - - options.declare( 'friction_key', - desc='current friction coefficient key, ' - 'either rolling friction or braking friction', + desc='current friction coefficient key, either rolling friction or braking friction', ) - options.declare( + self.options.declare( 'climbing', default=False, types=bool, desc='mode of operation (ground roll or flight)', ) - self.options.declare( - "analysis_scheme", - default=AnalysisScheme.COLLOCATION, - types=AnalysisScheme, - desc="The analysis method that will be used to close the trajectory; for example collocation or time integration", - ) - def setup(self): options = self.options - nn = options["num_nodes"] - analysis_scheme = options['analysis_scheme'] - aviary_options = options['aviary_options'] - subsystem_options = options['subsystem_options'] - core_subsystems = options['core_subsystems'] + nn = options['num_nodes'] - if analysis_scheme is AnalysisScheme.SHOOTING: - SGM_required_inputs = { - 't_curr': {'units': 's'}, - Dynamic.Mission.DISTANCE: {'units': 'm'}, - } - add_SGM_required_inputs(self, SGM_required_inputs) + self.add_atmosphere() - self.add_subsystem( - name='atmosphere', subsys=Atmosphere(num_nodes=nn), promotes=['*'] - ) - - # NOTE: the following are potentially signficant differences in implementation + # NOTE: the following are potentially significant differences in implementation # between FLOPS and Aviary: # - FLOPS detailed takeoff/landing assumes constant mass for the duration of # that specific analysis. @@ -106,62 +44,20 @@ def setup(self): # mass to vary as needed as a function of time and variation in related # optimization control variables. self.add_subsystem( - "stall_speed", + 'stall_speed', StallSpeed(num_nodes=nn), promotes_inputs=[ - "mass", - Dynamic.Mission.DENSITY, + 'mass', + Dynamic.Atmosphere.DENSITY, ('area', Aircraft.Wing.AREA), - ("lift_coefficient_max", self.stall_speed_lift_coefficient_name), + ('lift_coefficient_max', self.stall_speed_lift_coefficient_name), ], - promotes_outputs=[("stall_speed", "v_stall")], + promotes_outputs=[('stall_speed', 'v_stall')], ) - base_options = {'num_nodes': nn, 'aviary_inputs': aviary_options} - - for subsystem in core_subsystems: - # check if subsystem_options has entry for a subsystem of this name - if subsystem.name in subsystem_options: - kwargs = subsystem_options[subsystem.name] - else: - kwargs = {} - - kwargs.update(base_options) - system = subsystem.build_mission(**kwargs) - - if system is not None: - self.add_subsystem( - subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs), - ) - - # Create a lightly modified version of an OM group to add external subsystems - # to the ODE with a special configure() method that promotes - # all aircraft:* and mission:* variables to the ODE. - external_subsystem_group = ExternalSubsystemGroup() - add_subsystem_group = False - - for subsystem in self.options['external_subsystems']: - subsystem_mission = subsystem.build_mission( - num_nodes=nn, aviary_inputs=aviary_options - ) - if subsystem_mission is not None: - add_subsystem_group = True - external_subsystem_group.add_subsystem( - subsystem.name, subsystem_mission - ) - - # Only add the external subsystem group if it has at least one subsystem. - # Without this logic there'd be an empty OM group added to the ODE. - if add_subsystem_group: - self.add_subsystem( - name='external_subsystems', - subsys=external_subsystem_group, - promotes_inputs=['*'], - promotes_outputs=['*'], - ) + self.add_core_subsystems() + + self.add_external_subsystems() kwargs = { 'num_nodes': nn, @@ -176,11 +72,11 @@ def setup(self): promotes_inputs=[ Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, - 'angle_of_attack', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, ], promotes_outputs=[ Dynamic.Mission.DISTANCE_RATE, diff --git a/aviary/mission/flops_based/ode/test/test_landing_eom.py b/aviary/mission/flops_based/ode/test/test_landing_eom.py index 220effc629..52bcf0db9f 100644 --- a/aviary/mission/flops_based/ode/test/test_landing_eom.py +++ b/aviary/mission/flops_based/ode/test/test_landing_eom.py @@ -2,24 +2,27 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.flops_based.ode.landing_eom import ( - FlareEOM, GlideSlopeForces, FlareSumForces, GroundSumForces) -from aviary.models.N3CC.N3CC_data import ( - detailed_landing_flare, inputs) + FlareEOM, + FlareSumForces, + GlideSlopeForces, + GroundSumForces, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + detailed_landing_flare, + inputs, +) +from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.preprocessors import preprocess_options from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_tests import do_validation_test from aviary.variable_info.variables import Dynamic -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.preprocessors import preprocess_options class FlareEOMTest(unittest.TestCase): - """ - Test against data of detailed_landing_flare from models/N3CC/N3CC_data.py - """ + """Test against data of detailed_landing_flare from models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py.""" def setUp(self): prob = self.prob = om.Problem() @@ -27,56 +30,69 @@ def setUp(self): time, _ = detailed_landing_flare.get_item('time') nn = len(time) aviary_options = inputs - engine = build_engine_deck(aviary_options) - preprocess_options(aviary_options, engine_models=engine) + engines = [build_engine_deck(aviary_options)] + preprocess_options(aviary_options, engine_models=engines) prob.model.add_subsystem( - "landing_flare_eom", + 'landing_flare_eom', FlareEOM(num_nodes=nn, aviary_options=aviary_options), promotes_inputs=['*'], - promotes_outputs=['*']) + promotes_outputs=['*'], + ) prob.setup(check=False, force_alloc_complex=True) def test_case(self): - do_validation_test( self.prob, 'landing_flare_eom', input_validation_data=detailed_landing_flare, output_validation_data=detailed_landing_flare, input_keys=[ - 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], output_keys=[ Dynamic.Mission.DISTANCE_RATE, - Dynamic.Mission.ALTITUDE_RATE], - tol=1e-2, atol=1e-8, rtol=5e-10) + Dynamic.Mission.ALTITUDE_RATE, + ], + tol=1e-2, + atol=1e-8, + rtol=5e-10, + ) def test_IO(self): exclude_inputs = { - 'angle_of_attack', 'acceleration_vertical', - 'forces_vertical', 'angle_of_attack_rate', - 'acceleration_horizontal', 'forces_horizontal'} + 'angle_of_attack', + 'acceleration_vertical', + 'forces_vertical', + 'angle_of_attack_rate', + 'acceleration_horizontal', + 'forces_horizontal', + } exclude_outputs = { - 'forces_vertical', 'acceleration_horizontal', - 'forces_perpendicular', 'acceleration_vertical', - 'net_alpha_rate', 'forces_horizontal', 'required_thrust' + 'forces_vertical', + 'acceleration_horizontal', + 'forces_perpendicular', + 'acceleration_vertical', + 'net_alpha_rate', + 'forces_horizontal', + 'required_thrust', } - assert_match_varnames(self.prob.model, - exclude_inputs=exclude_inputs, - exclude_outputs=exclude_outputs) + assert_match_varnames( + self.prob.model, exclude_inputs=exclude_inputs, exclude_outputs=exclude_outputs + ) class OtherTest(unittest.TestCase): """ - Test against data of detailed landing glide slope forces, flare sum forces, - and ground sum forces from models/N3CC/N3CC_data.py + Test against data of detailed landing glide slope forces, flare sum forces, + and ground sum forces from models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py. """ def test_GlideSlopeForces(self): @@ -86,38 +102,32 @@ def test_GlideSlopeForces(self): aviary_options = inputs prob = om.Problem() - # use data from detailed_landing_flare in models/N3CC/N3CC_data.py + # use data from detailed_landing_flare in models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py prob.model.add_subsystem( - "glide", GlideSlopeForces(num_nodes=2, aviary_options=aviary_options), promotes=["*"] + 'glide', GlideSlopeForces(num_nodes=2, aviary_options=aviary_options), promotes=['*'] ) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([106292, 106292]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([106292, 106292]), units="lbm" + Dynamic.Vehicle.DRAG, np.array([47447.13138523, 44343.01567596]), units='N' ) prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([47447.13138523, 44343.01567596]), units="N" + Dynamic.Vehicle.LIFT, + np.array([482117.47027692, 568511.57097785]), + units='N', ) prob.model.set_input_defaults( - Dynamic.Mission.LIFT, np.array([482117.47027692, 568511.57097785]), units="N" + Dynamic.Vehicle.ANGLE_OF_ATTACK, np.array([5.086, 6.834]), units='deg' ) prob.model.set_input_defaults( - "angle_of_attack", np.array([5.086, 6.834]), units="deg" - ) - prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([-3.0, -2.47]), units="deg" + Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([-3.0, -2.47]), units='deg' ) prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob["forces_perpendicular"], np.array( - [135087.0, 832087.6]), tol - ) - assert_near_equal( - prob["required_thrust"], np.array( - [-44751.64, -391905.6]), tol - ) + assert_near_equal(prob['forces_perpendicular'], np.array([135087.0, 832087.6]), tol) + assert_near_equal(prob['required_thrust'], np.array([-44751.64, -391905.6]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-12) def test_FlareSumForces(self): @@ -127,41 +137,35 @@ def test_FlareSumForces(self): aviary_options = inputs prob = om.Problem() prob.model.add_subsystem( - "flare", FlareSumForces(num_nodes=2, aviary_options=aviary_options), promotes=["*"] + 'flare', FlareSumForces(num_nodes=2, aviary_options=aviary_options), promotes=['*'] ) - # use data from detailed_landing_flare in models/N3CC/N3CC_data.py - prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([106292, 106292]), units="lbm" - ) + # use data from detailed_landing_flare in models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([106292, 106292]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([47447.13138523, 44343.01567596]), units="N" + Dynamic.Vehicle.DRAG, np.array([47447.13138523, 44343.01567596]), units='N' ) prob.model.set_input_defaults( - Dynamic.Mission.LIFT, np.array([482117.47027692, 568511.57097785]), units="N" + Dynamic.Vehicle.LIFT, + np.array([482117.47027692, 568511.57097785]), + units='N', ) prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([4980.3, 4102]), units="N" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, np.array([4980.3, 4102]), units='N' ) prob.model.set_input_defaults( - "angle_of_attack", np.array([5.086, 6.834]), units="deg" + Dynamic.Vehicle.ANGLE_OF_ATTACK, np.array([5.086, 6.834]), units='deg' ) prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([-3., -2.47]), units="deg" + Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([-3.0, -2.47]), units='deg' ) prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob["forces_horizontal"], np.array( - [17173.03, 15710.98]), tol - ) - assert_near_equal( - prob["forces_vertical"], np.array( - [11310.84, 97396.16]), tol - ) + assert_near_equal(prob['forces_horizontal'], np.array([17173.03, 15710.98]), tol) + assert_near_equal(prob['forces_vertical'], np.array([11310.84, 97396.16]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-9, rtol=1e-12) def test_GroundSumForces(self): @@ -170,37 +174,34 @@ def test_GroundSumForces(self): tol = 1e-6 prob = om.Problem() prob.model.add_subsystem( - "ground", GroundSumForces(num_nodes=2, friction_coefficient=0.025), promotes=["*"] + 'ground', GroundSumForces(num_nodes=2, friction_coefficient=0.025), promotes=['*'] ) - # use data from detailed_landing_flare in models/N3CC/N3CC_data.py - prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([106292, 106292]), units="lbm" - ) + # use data from detailed_landing_flare in models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([106292, 106292]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([47447.13138523, 44343.01567596]), units="N" + Dynamic.Vehicle.DRAG, np.array([47447.13138523, 44343.01567596]), units='N' ) prob.model.set_input_defaults( - Dynamic.Mission.LIFT, np.array([482117.47027692, 568511.57097785]), units="N" + Dynamic.Vehicle.LIFT, + np.array([482117.47027692, 568511.57097785]), + units='N', ) prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([4980.3, 4102]), units="N" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, np.array([4980.3, 4102]), units='N' ) prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob["forces_horizontal"], np.array( - [42466.83, 40241.02]), tol - ) - assert_near_equal( - prob["forces_vertical"], np.array( - [9307.098, 95701.199]), tol - ) + assert_near_equal(prob['forces_horizontal'], np.array([42466.83, 40241.02]), tol) + assert_near_equal(prob['forces_vertical'], np.array([9307.098, 95701.199]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": - unittest.main() +if __name__ == '__main__': + # unittest.main() + test = FlareEOMTest() + test.setUp() + test.test_case() diff --git a/aviary/mission/flops_based/ode/test/test_landing_ode.py b/aviary/mission/flops_based/ode/test/test_landing_ode.py index 00310a904b..5870139256 100644 --- a/aviary/mission/flops_based/ode/test/test_landing_ode.py +++ b/aviary/mission/flops_based/ode/test/test_landing_ode.py @@ -2,22 +2,24 @@ import openmdao.api as om +from aviary.mission.flops_based.ode.landing_ode import FlareODE +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + detailed_landing_flare, + inputs, + landing_subsystem_options, +) from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.aviary_values import get_items +from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import set_aviary_initial_values +from aviary.utils.preprocessors import preprocess_options from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems -from aviary.mission.flops_based.ode.landing_ode import FlareODE -from aviary.models.N3CC.N3CC_data import ( - detailed_landing_flare, inputs, landing_subsystem_options) from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic, Aircraft -from aviary.utils.preprocessors import preprocess_options +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Dynamic class FlareODETest(unittest.TestCase): - """ - Test against data of detailed_landing_flare from models/N3CC/N3CC_data.py - """ + """Test against data of detailed_landing_flare from models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py.""" def test_case(self): prob = om.Problem() @@ -25,25 +27,28 @@ def test_case(self): nn = len(time) aviary_options = inputs - engine = build_engine_deck(aviary_options) + engines = [build_engine_deck(aviary_options)] - preprocess_options(aviary_options, engine_models=engine) + preprocess_options(aviary_options, engine_models=engines) - default_mission_subsystems = get_default_mission_subsystems( - 'FLOPS', engine) + default_mission_subsystems = get_default_mission_subsystems('FLOPS', engines) prob.model.add_subsystem( - "landing_flare_ode", + 'landing_flare_ode', FlareODE( num_nodes=nn, subsystem_options=landing_subsystem_options, core_subsystems=default_mission_subsystems, - aviary_options=aviary_options), + aviary_options=aviary_options, + ), promotes_inputs=['*'], - promotes_outputs=['*']) + promotes_outputs=['*'], + ) prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units='ft**2') + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) set_aviary_initial_values(prob, aviary_options) @@ -54,19 +59,25 @@ def test_case(self): input_validation_data=detailed_landing_flare, output_validation_data=detailed_landing_flare, input_keys=[ - 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], output_keys=[ Dynamic.Mission.DISTANCE_RATE, - Dynamic.Mission.ALTITUDE_RATE], - tol=1e-2, atol=5e-9, rtol=5e-9, - check_values=False, check_partials=True) + Dynamic.Mission.ALTITUDE_RATE, + ], + tol=1e-2, + atol=5e-9, + rtol=5e-9, + check_values=False, + check_partials=True, + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/ode/test/test_mission_eom.py b/aviary/mission/flops_based/ode/test/test_mission_eom.py index 648c3a111f..0e30403ab8 100644 --- a/aviary/mission/flops_based/ode/test/test_mission_eom.py +++ b/aviary/mission/flops_based/ode/test/test_mission_eom.py @@ -2,8 +2,7 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.flops_based.ode.mission_EOM import MissionEOM from aviary.utils.test_utils.variable_test import assert_match_varnames @@ -11,52 +10,60 @@ class MissionEOMTest(unittest.TestCase): - """ - Test energy-method equations of motion - """ + """Test energy-method equations of motion.""" def setUp(self): self.prob = prob = om.Problem() - prob.model.add_subsystem( - "mission", MissionEOM(num_nodes=3), promotes=["*"] - ) + prob.model.add_subsystem('mission', MissionEOM(num_nodes=3), promotes=['*']) prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([81796.1389890711, 74616.9849763798, 65193.7423491884]), units="kg" + Dynamic.Vehicle.MASS, + np.array([81796.1389890711, 74616.9849763798, 65193.7423491884]), + units='kg', ) prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([9978.32211087097, 8769.90342254821, 7235.03338269778]), units="lbf" + Dynamic.Vehicle.DRAG, + np.array([9978.32211087097, 8769.90342254821, 7235.03338269778]), + units='lbf', ) prob.model.set_input_defaults( - Dynamic.Mission.ALTITUDE_RATE, np.array([29.8463233754212, -5.69941245767868E-09, -4.32644785970493]), units="ft/s" + Dynamic.Mission.ALTITUDE_RATE, + np.array([29.8463233754212, -5.69941245767868e-09, -4.32644785970493]), + units='ft/s', ) prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY_RATE, np.array([0.558739800813549, 3.33665416459715E-17, -0.38372209277242]), units="m/s**2" + Dynamic.Mission.VELOCITY_RATE, + np.array([0.558739800813549, 3.33665416459715e-17, -0.38372209277242]), + units='m/s**2', ) prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([164.029012458452, 232.775306059091, 117.638805929526]), units="m/s" + Dynamic.Mission.VELOCITY, + np.array([164.029012458452, 232.775306059091, 117.638805929526]), + units='m/s', ) prob.model.set_input_defaults( - Dynamic.Mission.THRUST_MAX_TOTAL, np.array([40799.6009633346, 11500.32, 42308.2709683461]), units="lbf" + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + np.array([40799.6009633346, 11500.32, 42308.2709683461]), + units='lbf', ) prob.setup(check=False, force_alloc_complex=True) def test_case(self): - """ - test on mission EOM using data from validation_cases/validation_data/flops_data/full_mission_test_data.py - """ - + """Test on mission EOM using data from validation_cases/validation_data/flops_data/full_mission_test_data.py.""" tol = 1e-6 self.prob.run_model() - assert_near_equal(self.prob.get_val(Dynamic.Mission.ALTITUDE_RATE_MAX, units='ft/min'), - np.array([3679.0525544843, 760.55416759, 6557.07891846677]), tol) + assert_near_equal( + self.prob.get_val(Dynamic.Mission.ALTITUDE_RATE_MAX, units='ft/min'), + np.array([3679.0525544843, 760.55416759, 6557.07891846677]), + tol, + ) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-12) def test_IO(self): assert_match_varnames(self.prob.model, exclude_outputs={'thrust_required'}) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/ode/test/test_range_rate.py b/aviary/mission/flops_based/ode/test/test_range_rate.py index 3d6d3ab2a5..60af51f5a0 100644 --- a/aviary/mission/flops_based/ode/test/test_range_rate.py +++ b/aviary/mission/flops_based/ode/test/test_range_rate.py @@ -4,18 +4,14 @@ from aviary.mission.flops_based.ode.range_rate import RangeRate from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import \ - data +from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import data from aviary.validation_cases.validation_tests import do_validation_test from aviary.variable_info.variables import Dynamic class RangeRateTest(unittest.TestCase): def setUp(self): - """ - test using data from validation_cases/validation_data/flops_data/full_mission_test_data.py - """ - + """Test using data from validation_cases/validation_data/flops_data/full_mission_test_data.py.""" prob = self.prob = om.Problem() time, _ = data.get_item('time') @@ -30,19 +26,19 @@ def setUp(self): prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - - do_validation_test(self.prob, - 'full_mission_test_data', - input_validation_data=data, - output_validation_data=data, - input_keys=[Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY], - output_keys=Dynamic.Mission.DISTANCE_RATE, - tol=1e-12) + do_validation_test( + self.prob, + 'full_mission_test_data', + input_validation_data=data, + output_validation_data=data, + input_keys=[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY], + output_keys=Dynamic.Mission.DISTANCE_RATE, + tol=1e-12, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/ode/test/test_required_thrust.py b/aviary/mission/flops_based/ode/test/test_required_thrust.py index 4e55b5b7a6..50aea187ed 100644 --- a/aviary/mission/flops_based/ode/test/test_required_thrust.py +++ b/aviary/mission/flops_based/ode/test/test_required_thrust.py @@ -2,8 +2,7 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.flops_based.ode.required_thrust import RequiredThrust from aviary.utils.test_utils.variable_test import assert_match_varnames @@ -11,49 +10,39 @@ class RequiredThrustTest(unittest.TestCase): - """ - Test required thrust - """ + """Test required thrust.""" def setUp(self): prob = self.prob = om.Problem() - prob.model.add_subsystem( - "req_thrust", RequiredThrust(num_nodes=2), promotes=["*"] - ) - prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([47447.13138523, 44343.01567596]), units="N" - ) + prob.model.add_subsystem('req_thrust', RequiredThrust(num_nodes=2), promotes=['*']) prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([106292, 106292]), units="lbm" + Dynamic.Vehicle.DRAG, np.array([47447.13138523, 44343.01567596]), units='N' ) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([106292, 106292]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.ALTITUDE_RATE, np.array([1.72, 11.91]), units="m/s" + Dynamic.Mission.ALTITUDE_RATE, np.array([1.72, 11.91]), units='m/s' ) prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY_RATE, np.array([5.23, 2.7]), units="m/s**2" + Dynamic.Mission.VELOCITY_RATE, np.array([5.23, 2.7]), units='m/s**2' ) prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([160.99, 166.68]), units="m/s" + Dynamic.Mission.VELOCITY, np.array([160.99, 166.68]), units='m/s' ) prob.setup(check=False, force_alloc_complex=True) def test_case(self): - tol = 1e-6 self.prob.run_model() - assert_near_equal( - self.prob["thrust_required"], - np.array([304653.8, 208303.1]), tol - ) + assert_near_equal(self.prob['thrust_required'], np.array([304653.8, 208303.1]), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_IO(self): assert_match_varnames(self.prob.model, exclude_outputs={'thrust_required'}) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/ode/test/test_takeoff_eom.py b/aviary/mission/flops_based/ode/test/test_takeoff_eom.py index e3e35fc219..6a323a85af 100644 --- a/aviary/mission/flops_based/ode/test/test_takeoff_eom.py +++ b/aviary/mission/flops_based/ode/test/test_takeoff_eom.py @@ -2,23 +2,33 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.flops_based.ode.takeoff_eom import ( - TakeoffEOM, StallSpeed, DistanceRates, Accelerations, VelocityRate, - FlightPathAngleRate, SumForces, ClimbGradientForces) -from aviary.models.N3CC.N3CC_data import ( - detailed_takeoff_climbing, detailed_takeoff_ground, inputs) + Accelerations, + ClimbGradientForces, + DistanceRates, + FlightPathAngleRate, + StallSpeed, + SumForces, + TakeoffEOM, + VelocityRate, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + detailed_takeoff_climbing, + detailed_takeoff_ground, + inputs, +) from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic, Mission +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Dynamic, Mission + +inputs.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) class TakeoffEOMTest(unittest.TestCase): - """ - Test detailed takeoff equation of motion - """ + """Test detailed takeoff equation of motion.""" def test_case_ground(self): prob = self._make_prob(climbing=False) @@ -29,18 +39,21 @@ def test_case_ground(self): input_validation_data=detailed_takeoff_ground, output_validation_data=detailed_takeoff_ground, input_keys=[ - 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], output_keys=[ Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY_RATE], - tol=1e-2) + Dynamic.Mission.VELOCITY_RATE, + ], + tol=1e-2, + ) def test_case_climbing(self): prob = self._make_prob(climbing=True) @@ -51,18 +64,23 @@ def test_case_climbing(self): input_validation_data=detailed_takeoff_climbing, output_validation_data=detailed_takeoff_climbing, input_keys=[ - 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], output_keys=[ Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY_RATE], - tol=1e-2, atol=1e-9, rtol=1e-11) + Dynamic.Mission.VELOCITY_RATE, + ], + tol=1e-2, + atol=1e-9, + rtol=1e-11, + ) @staticmethod def _make_prob(climbing): @@ -71,16 +89,19 @@ def _make_prob(climbing): time, _ = detailed_takeoff_climbing.get_item('time') nn = len(time) aviary_options = inputs + inputs.set_val(Aircraft.Engine.NUM_ENGINES, [2]) prob.model.add_subsystem( - "takeoff_eom", - TakeoffEOM(num_nodes=nn, - aviary_options=aviary_options, - climbing=climbing, - friction_key=Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT - ), + 'takeoff_eom', + TakeoffEOM( + num_nodes=nn, + aviary_options=aviary_options, + climbing=climbing, + friction_key=Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, + ), promotes_inputs=['*'], - promotes_outputs=['*']) + promotes_outputs=['*'], + ) prob.setup(check=False, force_alloc_complex=True) @@ -89,313 +110,254 @@ def _make_prob(climbing): def test_IO(self): prob = self._make_prob(climbing=False) exclude_inputs = { - 'angle_of_attack', 'acceleration_horizontal', - 'acceleration_vertical', 'forces_vertical', 'forces_horizontal'} + 'angle_of_attack', + 'acceleration_horizontal', + 'acceleration_vertical', + 'forces_vertical', + 'forces_horizontal', + } exclude_outputs = { - 'acceleration_horizontal', 'acceleration_vertical', - 'climb_gradient_forces_vertical', 'forces_horizontal', - 'forces_vertical', 'climb_gradient_forces_horizontal'} - assert_match_varnames(prob.model, - exclude_inputs=exclude_inputs, - exclude_outputs=exclude_outputs) + 'acceleration_horizontal', + 'acceleration_vertical', + 'climb_gradient_forces_vertical', + 'forces_horizontal', + 'forces_vertical', + 'climb_gradient_forces_horizontal', + } + assert_match_varnames( + prob.model, exclude_inputs=exclude_inputs, exclude_outputs=exclude_outputs + ) def test_StallSpeed(self): tol = 1e-6 prob = om.Problem() - prob.model.add_subsystem( - "stall_speed", StallSpeed(num_nodes=2), promotes=["*"] - ) - prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, np.array([1, 2]), units="kg/m**3" - ) - prob.model.set_input_defaults( - "area", 10, units="m**2" - ) - prob.model.set_input_defaults( - "lift_coefficient_max", 5000, units="unitless" - ) + prob.model.add_subsystem('stall_speed', StallSpeed(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults(Dynamic.Atmosphere.DENSITY, np.array([1, 2]), units='kg/m**3') + prob.model.set_input_defaults('area', 10, units='m**2') + prob.model.set_input_defaults('lift_coefficient_max', 5000, units='unitless') prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob["stall_speed"], np.array( - [0.01980571, 0.01400475]), tol - ) + assert_near_equal(prob['stall_speed'], np.array([0.01980571, 0.01400475]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_DistanceRates_1(self): - """ - climbing = True - """ - + """Climbing = True.""" tol = 1e-6 prob = om.Problem() prob.model.add_subsystem( - "dist_rates", DistanceRates(num_nodes=2, climbing=True), promotes=["*"] - ) - prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([0.612, 4.096]), units="rad" + 'dist_rates', DistanceRates(num_nodes=2, climbing=True), promotes=['*'] ) prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([5.23, 2.7]), units="m/s" + Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([0.612, 4.096]), units='rad' ) + prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, np.array([5.23, 2.7]), units='m/s') prob.setup(check=False, force_alloc_complex=True) prob.run_model() + assert_near_equal(prob[Dynamic.Mission.DISTANCE_RATE], np.array([4.280758, -1.56085]), tol) assert_near_equal( - prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [4.280758, -1.56085]), tol - ) - assert_near_equal( - prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [3.004664, -2.203122]), tol + prob[Dynamic.Mission.ALTITUDE_RATE], + np.array([3.004664, -2.203122]), + tol, ) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_DistanceRates_2(self): - """ - climbing = False - """ - + """Climbing = False.""" tol = 1e-6 prob = om.Problem() prob.model.add_subsystem( - "dist_rates", DistanceRates(num_nodes=2, climbing=False), promotes=["*"] + 'dist_rates', DistanceRates(num_nodes=2, climbing=False), promotes=['*'] ) prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([0.0, 0.0]), units="rad" - ) - prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([1.0, 2.0]), units="m/s" + Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([0.0, 0.0]), units='rad' ) + prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, np.array([1.0, 2.0]), units='m/s') prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob[Dynamic.Mission.DISTANCE_RATE], np.array([1.0, 2.0]), tol) - assert_near_equal( - prob[Dynamic.Mission.ALTITUDE_RATE], np.array([0.0, 0.0]), tol - ) + assert_near_equal(prob[Dynamic.Mission.DISTANCE_RATE], np.array([1.0, 2.0]), tol) + assert_near_equal(prob[Dynamic.Mission.ALTITUDE_RATE], np.array([0.0, 0.0]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_Accelerations(self): tol = 1e-6 prob = om.Problem() - prob.model.add_subsystem( - "acceleration", Accelerations(num_nodes=2), promotes=["*"] - ) - prob.model.set_input_defaults( - "forces_horizontal", [100.0, 200.0], units="N" - ) - prob.model.set_input_defaults( - "forces_vertical", [50.0, 100.0], units="N" - ) + prob.model.add_subsystem('acceleration', Accelerations(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults('forces_horizontal', [100.0, 200.0], units='N') + prob.model.set_input_defaults('forces_vertical', [50.0, 100.0], units='N') prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob["acceleration_horizontal"], np.array( - [100.0, 200.0]), tol - ) - assert_near_equal( - prob["acceleration_vertical"], np.array( - [50.0, 100.0]), tol - ) + assert_near_equal(prob['acceleration_horizontal'], np.array([100.0, 200.0]), tol) + assert_near_equal(prob['acceleration_vertical'], np.array([50.0, 100.0]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_VelocityRate(self): tol = 1e-6 prob = om.Problem() - prob.model.add_subsystem( - "vel_rate", VelocityRate(num_nodes=2), promotes=["*"] - ) - prob.model.set_input_defaults( - "acceleration_horizontal", [100.0, 200.0], units="m/s**2" - ) - prob.model.set_input_defaults( - "acceleration_vertical", [50.0, 100.0], units="m/s**2" - ) - prob.model.set_input_defaults( - Dynamic.Mission.DISTANCE_RATE, [160.98, 166.25], units="m/s" - ) - prob.model.set_input_defaults( - Dynamic.Mission.ALTITUDE_RATE, [1.72, 11.91], units="m/s" - ) + prob.model.add_subsystem('vel_rate', VelocityRate(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults('acceleration_horizontal', [100.0, 200.0], units='m/s**2') + prob.model.set_input_defaults('acceleration_vertical', [50.0, 100.0], units='m/s**2') + prob.model.set_input_defaults(Dynamic.Mission.DISTANCE_RATE, [160.98, 166.25], units='m/s') + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE_RATE, [1.72, 11.91], units='m/s') prob.setup(check=False, force_alloc_complex=True) prob.run_model() assert_near_equal( - prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [100.5284, 206.6343]), tol + prob[Dynamic.Mission.VELOCITY_RATE], + np.array([100.5284, 206.6343]), + tol, ) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_FlightPathAngleRate(self): tol = 1e-6 prob = om.Problem() - prob.model.add_subsystem( - "gamma_rate", FlightPathAngleRate(num_nodes=2), promotes=["*"] - ) - prob.model.set_input_defaults( - "acceleration_horizontal", [100.0, 200.0], units="m/s**2" - ) - prob.model.set_input_defaults( - "acceleration_vertical", [50.0, 100.0], units="m/s**2" - ) - prob.model.set_input_defaults( - Dynamic.Mission.DISTANCE_RATE, [160.98, 166.25], units="m/s" - ) - prob.model.set_input_defaults( - Dynamic.Mission.ALTITUDE_RATE, [1.72, 11.91], units="m/s" - ) + prob.model.add_subsystem('gamma_rate', FlightPathAngleRate(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults('acceleration_horizontal', [100.0, 200.0], units='m/s**2') + prob.model.set_input_defaults('acceleration_vertical', [50.0, 100.0], units='m/s**2') + prob.model.set_input_defaults(Dynamic.Mission.DISTANCE_RATE, [160.98, 166.25], units='m/s') + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE_RATE, [1.72, 11.91], units='m/s') prob.setup(check=False, force_alloc_complex=True) prob.run_model() assert_near_equal( - prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array( - [0.3039257, 0.51269018]), tol + prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], + np.array([0.3039257, 0.51269018]), + tol, ) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_SumForcese_1(self): - """ - climbing = True - """ - + """Climbing = True.""" tol = 1e-6 prob = om.Problem() aviary_options = inputs prob.model.add_subsystem( - "sum1", SumForces(num_nodes=2, climbing=True, aviary_options=aviary_options), promotes=["*"] - ) - prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([106292, 106292]), units="lbm" + 'sum1', + SumForces(num_nodes=2, climbing=True, aviary_options=aviary_options), + promotes=['*'], ) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([106292, 106292]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([47447.13138523, 44343.01567596]), units="N" + Dynamic.Vehicle.DRAG, np.array([47447.13138523, 44343.01567596]), units='N' ) prob.model.set_input_defaults( - Dynamic.Mission.LIFT, np.array([482117.47027692, 568511.57097785]), units="N" + Dynamic.Vehicle.LIFT, + np.array([482117.47027692, 568511.57097785]), + units='N', ) prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([4980.3, 4102]), units="N" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, np.array([4980.3, 4102]), units='N' ) prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob["forces_horizontal"], np.array( - [-42466.83, -40241.02]), tol - ) - assert_near_equal( - prob["forces_vertical"], np.array( - [9307.0983, 95701.1990]), tol - ) + assert_near_equal(prob['forces_horizontal'], np.array([-42466.83, -40241.02]), tol) + assert_near_equal(prob['forces_vertical'], np.array([9307.0983, 95701.1990]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_SumForcese_2(self): - """ - climbing = False - """ - + """Climbing = False.""" tol = 1e-6 prob = om.Problem() aviary_options = inputs prob.model.add_subsystem( - "sum2", SumForces(num_nodes=2, climbing=False, aviary_options=aviary_options), promotes=["*"] - ) - prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([106292, 106292]), units="lbm" + 'sum2', + SumForces(num_nodes=2, climbing=False, aviary_options=aviary_options), + promotes=['*'], ) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([106292, 106292]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([47447.13138523, 44343.01567596]), units="N" + Dynamic.Vehicle.DRAG, np.array([47447.13138523, 44343.01567596]), units='N' ) prob.model.set_input_defaults( - Dynamic.Mission.LIFT, np.array([482117.47027692, 568511.57097785]), units="N" + Dynamic.Vehicle.LIFT, + np.array([482117.47027692, 568511.57097785]), + units='N', ) prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([4980.3, 4102]), units="N" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, np.array([4980.3, 4102]), units='N' ) prob.setup(check=False, force_alloc_complex=True) prob.run_model() - assert_near_equal( - prob["forces_horizontal"], np.array([-42234.154, -37848.486]), tol - ) - assert_near_equal( - prob["forces_vertical"], np.array([0.0, 0.0]), tol - ) + assert_near_equal(prob['forces_horizontal'], np.array([-42234.154, -37848.486]), tol) + assert_near_equal(prob['forces_vertical'], np.array([0.0, 0.0]), tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_ClimbGradientForces(self): - """ - climbing = False - """ - + """Climbing = False.""" tol = 1e-6 prob = om.Problem() aviary_options = inputs prob.model.add_subsystem( - "climb_grad", ClimbGradientForces(num_nodes=2, aviary_options=aviary_options), promotes=["*"] - ) - prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([106292, 106292]), units="lbm" + 'climb_grad', + ClimbGradientForces(num_nodes=2, aviary_options=aviary_options), + promotes=['*'], ) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([106292, 106292]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([47447.13138523, 44343.01567596]), units="N" + Dynamic.Vehicle.DRAG, np.array([47447.13138523, 44343.01567596]), units='N' ) prob.model.set_input_defaults( - Dynamic.Mission.LIFT, np.array([482117.47027692, 568511.57097785]), units="N" + Dynamic.Vehicle.LIFT, + np.array([482117.47027692, 568511.57097785]), + units='N', ) prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([4980.3, 4102]), units="N" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, np.array([4980.3, 4102]), units='N' ) prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([0.612, 4.096]), units="rad" + Dynamic.Mission.FLIGHT_PATH_ANGLE, np.array([0.612, 4.096]), units='rad' ) prob.model.set_input_defaults( - "angle_of_attack", np.array([5.086, 6.834]), units="rad" + Dynamic.Vehicle.ANGLE_OF_ATTACK, np.array([5.086, 6.834]), units='rad' ) + setup_model_options(prob, inputs) + prob.setup(check=False, force_alloc_complex=True) prob.run_model() assert_near_equal( - prob["climb_gradient_forces_horizontal"], - np.array([-317261.63, 344951.97]), tol + prob['climb_gradient_forces_horizontal'], np.array([-317261.63, 344951.97]), tol ) assert_near_equal( - prob["climb_gradient_forces_vertical"], - np.array([90485.14, 843986.59]), tol + prob['climb_gradient_forces_vertical'], np.array([90485.14, 843986.59]), tol ) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = TakeoffEOMTest() + # test.test_case_ground() diff --git a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py index 4606806146..49feba8683 100644 --- a/aviary/mission/flops_based/ode/test/test_takeoff_ode.py +++ b/aviary/mission/flops_based/ode/test/test_takeoff_ode.py @@ -3,23 +3,27 @@ import openmdao.api as om +from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + detailed_takeoff_climbing, + detailed_takeoff_ground, + inputs, + takeoff_subsystem_options, +) from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import set_aviary_initial_values +from aviary.utils.preprocessors import preprocess_options from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems -from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE -from aviary.models.N3CC.N3CC_data import ( - detailed_takeoff_climbing, detailed_takeoff_ground, takeoff_subsystem_options, inputs) from aviary.validation_cases.validation_tests import do_validation_test -from aviary.variable_info.variables import Dynamic, Mission, Aircraft -from aviary.utils.preprocessors import preprocess_options +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Dynamic, Mission takeoff_subsystem_options = deepcopy(takeoff_subsystem_options) class TakeoffODETest(unittest.TestCase): - """ - Test detailed takeoff ODE - """ + """Test detailed takeoff ODE.""" def test_case_ground(self): prob = self._make_prob(climbing=False) @@ -30,20 +34,26 @@ def test_case_ground(self): input_validation_data=detailed_takeoff_ground, output_validation_data=detailed_takeoff_ground, input_keys=[ - 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.ALTITUDE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], output_keys=[ Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY_RATE], - tol=1e-2, atol=1e-9, rtol=1e-11, - check_values=False, check_partials=True) + Dynamic.Mission.VELOCITY_RATE, + ], + tol=1e-2, + atol=1e-9, + rtol=1e-11, + check_values=False, + check_partials=True, + ) def test_case_climbing(self): prob = self._make_prob(climbing=True) @@ -54,20 +64,26 @@ def test_case_climbing(self): input_validation_data=detailed_takeoff_climbing, output_validation_data=detailed_takeoff_climbing, input_keys=[ - 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.ALTITUDE, Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], output_keys=[ Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.VELOCITY_RATE], - tol=1e-2, atol=1e-9, rtol=1e-11, - check_values=False, check_partials=True) + Dynamic.Mission.VELOCITY_RATE, + ], + tol=1e-2, + atol=1e-9, + rtol=1e-11, + check_values=False, + check_partials=True, + ) @staticmethod def _make_prob(climbing): @@ -76,27 +92,30 @@ def _make_prob(climbing): time, _ = detailed_takeoff_climbing.get_item('time') nn = len(time) aviary_options = inputs - engine = build_engine_deck(aviary_options) + engines = [build_engine_deck(aviary_options)] - preprocess_options(aviary_options, engine_models=engine) + preprocess_options(aviary_options, engine_models=engines) - default_mission_subsystems = get_default_mission_subsystems( - 'FLOPS', engine) + default_mission_subsystems = get_default_mission_subsystems('FLOPS', engines) prob.model.add_subsystem( - "takeoff_ode", + 'takeoff_ode', TakeoffODE( num_nodes=nn, aviary_options=aviary_options, subsystem_options=takeoff_subsystem_options, core_subsystems=default_mission_subsystems, climbing=climbing, - friction_key=Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT), + friction_key=Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, + ), promotes_inputs=['*'], - promotes_outputs=['*']) + promotes_outputs=['*'], + ) prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units='ft**2') + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) set_aviary_initial_values(prob, aviary_options) @@ -104,5 +123,5 @@ def _make_prob(climbing): return prob -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/phases/build_landing.py b/aviary/mission/flops_based/phases/build_landing.py index 2b7cebd7ee..b266d3cdf7 100644 --- a/aviary/mission/flops_based/phases/build_landing.py +++ b/aviary/mission/flops_based/phases/build_landing.py @@ -32,28 +32,29 @@ def __init__( # connections. __slots__ = ( - "ref_wing_area", - "Cl_max_ldg", + 'ref_wing_area', + 'Cl_max_ldg', ) def build_phase(self, use_detailed=False): """ Construct and return a new phase for landing analysis. + Parameters ---------- use_detailed : bool (False) tells whether to use simplified or detailed landing. Currently detailed is disabled. + Returns ------- Group a group in OpenMDAO """ - if use_detailed: raise om.AnalysisError( - "Must set landing method to `use_detailed=False`, detailed landing is" - " not currently enabled." + 'Must set landing method to `use_detailed=False`, detailed landing is' + ' not currently enabled.' ) ############## @@ -61,10 +62,9 @@ def build_phase(self, use_detailed=False): ############## landing = LandingGroup() + landing.set_input_defaults(Aircraft.Wing.AREA, val=self.ref_wing_area, units='ft**2') landing.set_input_defaults( - Aircraft.Wing.AREA, val=self.ref_wing_area, units="ft**2" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=self.Cl_max_ldg, units='unitless' ) - landing.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=self.Cl_max_ldg, units='unitless') return landing diff --git a/aviary/mission/flops_based/phases/build_takeoff.py b/aviary/mission/flops_based/phases/build_takeoff.py index ff99291bd2..abd319fc05 100644 --- a/aviary/mission/flops_based/phases/build_takeoff.py +++ b/aviary/mission/flops_based/phases/build_takeoff.py @@ -34,28 +34,29 @@ def __init__( # connections. The only variables that should stay are: airport_altitude __slots__ = ( - "airport_altitude", - "num_engines", + 'airport_altitude', + 'num_engines', ) def build_phase(self, use_detailed=False): """ Construct and return a new phase for takeoff analysis. + Parameters ---------- use_detailed : bool(False) tells whether to use simplified or detailed takeoff. Currently detailed is disabled. + Returns ------- Group a group in OpenMDAO """ - if use_detailed: # TODO raise om.AnalysisError( - "Must set takeoff method to `use_detailed=False`, detailed takeoff is" - " not currently enabled." + 'Must set takeoff method to `use_detailed=False`, detailed takeoff is' + ' not currently enabled.' ) ############## @@ -63,9 +64,6 @@ def build_phase(self, use_detailed=False): ############## takeoff = TakeoffGroup(num_engines=self.num_engines) - takeoff.set_input_defaults( - Dynamic.Mission.ALTITUDE, - val=self.airport_altitude, - units="ft") + takeoff.set_input_defaults(Dynamic.Mission.ALTITUDE, val=self.airport_altitude, units='ft') return takeoff diff --git a/aviary/mission/flops_based/phases/detailed_landing_phases.py b/aviary/mission/flops_based/phases/detailed_landing_phases.py index 4dffa24e78..fde894ec4f 100644 --- a/aviary/mission/flops_based/phases/detailed_landing_phases.py +++ b/aviary/mission/flops_based/phases/detailed_landing_phases.py @@ -1,4 +1,4 @@ -''' +""" Define utilities for building detailed landing phases and the typical landing trajectory. Classes @@ -23,28 +23,94 @@ full stop LandingTrajectory : a trajectory builder for detailed landing -''' +""" + import dymos as dm import openmdao.api as om from aviary.mission.flops_based.ode.landing_ode import FlareODE, LandingODE -from aviary.mission.flops_based.phases.detailed_takeoff_phases import \ - TakeoffTrajectory as _TakeoffTrajectory -from aviary.mission.flops_based.phases.detailed_takeoff_phases import \ - _init_initial_guess_meta_data +from aviary.mission.flops_based.phases.detailed_takeoff_phases import ( + TakeoffTrajectory as _TakeoffTrajectory, +) +from aviary.mission.flops_based.phases.detailed_takeoff_phases import _init_initial_guess_meta_data +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessParameter, + InitialGuessPolynomialControl, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase -from aviary.mission.initial_guess_builders import InitialGuessControl, InitialGuessParameter, InitialGuessPolynomialControl, InitialGuessState, InitialGuessIntegrationVariable from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import LegacyCode from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic, Mission from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Dynamic, Mission + + +class LandingApproachToMicP3Options(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) + + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) + + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) + + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) + + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) + + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) + + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) + + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) + + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) + + self.declare( + name='initial_height', default=1.0, units='ft', desc='Starting altitude for thie phase.' + ) @_init_initial_guess_meta_data class LandingApproachToMicP3(PhaseBuilderBase): - ''' + """ Define a phase builder for moving from descent to the mic location P3. This phase is required for acoustic calculations. @@ -58,8 +124,8 @@ class LandingApproachToMicP3(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -100,21 +166,16 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'landing_approach' - default_ode_class = LandingODE - # endregion : derived type customization points + default_options_class = LandingApproachToMicP3Options def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -130,57 +191,79 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( duration_bounds=(1, max_duration), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, fix_final=False, - upper=0, ref=distance_max, - defect_ref=distance_max, units=units, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + fix_final=False, + upper=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, fix_final=False, + Dynamic.Mission.ALTITUDE, + fix_initial=False, + fix_final=False, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, fix_final=False, - lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + fix_final=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, opt=False, fix_initial=True) phase.add_state( - Dynamic.Mission.MASS, fix_initial=True, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=True, + fix_final=False, + lower=0.0, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) units = 'deg' @@ -189,81 +272,66 @@ def build_phase(self, aviary_options: AviaryValues = None): angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) phase.add_control( - 'angle_of_attack', opt=True, units=units, - upper=upper_angle_of_attack, lower=lower_angle_of_attack, - ref=angle_of_attack_ref + Dynamic.Vehicle.ANGLE_OF_ATTACK, + opt=True, + units=units, + upper=upper_angle_of_attack, + lower=lower_angle_of_attack, + ref=angle_of_attack_ref, ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - initial_height, units = user_options.get_item('initial_height') + initial_height, units = user_options['initial_height'] - airport_altitude = aviary_options.get_val( - Mission.Landing.AIRPORT_ALTITUDE, units) + airport_altitude = aviary_options.get_val(Mission.Landing.AIRPORT_ALTITUDE, units) h = initial_height + airport_altitude phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='initial', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, + loc='initial', + equals=h, + ref=h, + units=units, + linear=True, + ) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=5, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} - - -LandingApproachToMicP3._add_meta_data('max_duration', val=100., units='s') - -LandingApproachToMicP3._add_meta_data('duration_ref', val=1., units='s') - -LandingApproachToMicP3._add_meta_data('initial_ref', val=10.0, units='s') - -LandingApproachToMicP3._add_meta_data('distance_max', val=1000., units='ft') - -LandingApproachToMicP3._add_meta_data('max_velocity', val=100., units='ft/s') - -LandingApproachToMicP3._add_meta_data('altitude_ref', val=1., units='ft') - -LandingApproachToMicP3._add_meta_data('lower_angle_of_attack', val=-10., units='deg') + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -LandingApproachToMicP3._add_meta_data('upper_angle_of_attack', val=15., units='deg') - -LandingApproachToMicP3._add_meta_data('angle_of_attack_ref', val=10., units='deg') - -LandingApproachToMicP3._add_meta_data('initial_height', val=1., units='ft') LandingApproachToMicP3._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) LandingApproachToMicP3._add_initial_guess_meta_data(InitialGuessState('altitude')) LandingApproachToMicP3._add_initial_guess_meta_data( - InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) # @_init_initial_guess_meta_data # <--- inherited from base class class LandingMicP3ToObstacle(LandingApproachToMicP3): - ''' + """ Define a phase builder for moving from the mic location P3 to the start of the runway, just above the required clearance height. This phase is required for acoustic calculations. @@ -278,8 +346,8 @@ class LandingMicP3ToObstacle(LandingApproachToMicP3): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -320,19 +388,14 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - # _meta_data_ = {} # <--- inherited from base class + __slots__ = () default_name = 'landing_mic_p3' - # endregion : derived type customization points def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -348,21 +411,43 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) # at the moment, these state options are the only differences between phases of # this class and phases of its base class phase.set_state_options(Dynamic.Mission.DISTANCE, fix_final=True) phase.set_state_options(Dynamic.Mission.VELOCITY, fix_final=True) - phase.set_state_options(Dynamic.Mission.MASS, fix_initial=False) + phase.set_state_options(Dynamic.Vehicle.MASS, fix_initial=False) return phase +class LandingObstacleToFlareOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) + + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) + + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) + + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) + + @_init_initial_guess_meta_data class LandingObstacleToFlare(PhaseBuilderBase): - ''' + """ Define a phase builder for moving from the start of the runway, just above the required clearance height, to the start of a maneuver to help soften the impact of touchdown. @@ -413,21 +498,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'landing_obstacle' default_ode_class = LandingODE - # endregion : derived type customization points + default_options_class = LandingObstacleToFlareOptions def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -443,119 +524,184 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') + max_duration, units = user_options['max_duration'] - phase.set_time_options( - fix_initial=True, duration_bounds=(1, max_duration), - units=units) + phase.set_time_options(fix_initial=True, duration_bounds=(1, max_duration), units=units) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=True, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=False, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=True, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=True, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, - opt=False, fix_initial=False) + phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, opt=False, fix_initial=False) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - phase.add_control('angle_of_attack', opt=False, units='deg') + phase.add_control(Dynamic.Vehicle.ANGLE_OF_ATTACK, opt=False, units='deg') phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - obstacle_height, units = aviary_options.get_item( - Mission.Landing.OBSTACLE_HEIGHT) + obstacle_height, units = aviary_options.get_item(Mission.Landing.OBSTACLE_HEIGHT) if obstacle_height is None: - raise TypeError( - f'missing required aviary_option: {Mission.Landing.OBSTACLE_HEIGHT}') + raise TypeError(f'missing required aviary_option: {Mission.Landing.OBSTACLE_HEIGHT}') - airport_altitude = aviary_options.get_val( - Mission.Landing.AIRPORT_ALTITUDE, units) + airport_altitude = aviary_options.get_val(Mission.Landing.AIRPORT_ALTITUDE, units) h = obstacle_height + airport_altitude phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='initial', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, + loc='initial', + equals=h, + ref=h, + units=units, + linear=True, + ) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=5, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -LandingObstacleToFlare._add_meta_data('max_duration', val=100., units='s') +LandingObstacleToFlare._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -LandingObstacleToFlare._add_meta_data('distance_max', val=1000., units='ft') +LandingObstacleToFlare._add_initial_guess_meta_data(InitialGuessState('altitude')) -LandingObstacleToFlare._add_meta_data('max_velocity', val=100., units='ft/s') +LandingObstacleToFlare._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -LandingObstacleToFlare._add_meta_data('altitude_ref', val=1., units='ft') -LandingObstacleToFlare._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) +class LandingFlareToTouchdownOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -LandingObstacleToFlare._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -LandingObstacleToFlare._add_initial_guess_meta_data( - InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) + + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) + + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) + + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) + + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) + + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) + + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) @_init_initial_guess_meta_data class LandingFlareToTouchdown(PhaseBuilderBase): - ''' + """ Define a phase builder for moving through a maneuver to help soften the impact of touchdown. @@ -569,8 +715,8 @@ class LandingFlareToTouchdown(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -610,21 +756,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'landing_flare' default_ode_class = FlareODE - # endregion : derived type customization points + default_options_class = LandingFlareToTouchdownOptions def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -640,59 +782,83 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + fix_initial=False, + duration_bounds=(1, max_duration), + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, fix_final=True, - lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=False, + fix_final=True, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, - fix_initial=False, opt=False) + phase.add_control(Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, opt=False) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) # TODO: Upper limit is a bit of a hack. It hopefully won't be needed if we # can get some other constraints working. phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - lower=0.0, upper=0.2, - opt=True + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + lower=0.0, + upper=0.2, + opt=True, ) units = 'deg' @@ -700,84 +866,102 @@ def build_phase(self, aviary_options: AviaryValues = None): upper_angle_of_attack = user_options.get_val('upper_angle_of_attack', units) angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) - phase.add_polynomial_control( - 'angle_of_attack', opt=True, units=units, order=1, - lower=lower_angle_of_attack, upper=upper_angle_of_attack, + phase.add_control( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + control_type='polynomial', + opt=True, + units=units, + order=1, + lower=lower_angle_of_attack, + upper=upper_angle_of_attack, ref=angle_of_attack_ref, - rate_targets="angle_of_attack_rate" + rate_targets='angle_of_attack_rate', ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - phase.add_timeseries_output( - 'required_thrust', units='lbf' - ) + phase.add_timeseries_output('required_thrust', units='lbf') - phase.add_timeseries_output( - 'forces_perpendicular', units='lbf' - ) + phase.add_timeseries_output('forces_perpendicular', units='lbf') # Since the control is linear, only need to constrain one point. - phase.add_boundary_constraint( - 'net_alpha_rate', - equals=0.0, loc='final', - units='deg/s' - ) + phase.add_boundary_constraint('net_alpha_rate', equals=0.0, loc='final', units='deg/s') return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=5, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ + """Return extra kwargs required for initializing the ODE.""" return {} -LandingFlareToTouchdown._add_meta_data('max_duration', val=100., units='s') - -LandingFlareToTouchdown._add_meta_data('duration_ref', val=1., units='s') +LandingFlareToTouchdown._add_initial_guess_meta_data( + InitialGuessPolynomialControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -LandingFlareToTouchdown._add_meta_data('initial_ref', val=10.0, units='s') +LandingFlareToTouchdown._add_initial_guess_meta_data(InitialGuessState('altitude')) -LandingFlareToTouchdown._add_meta_data('distance_max', val=1000., units='ft') +LandingFlareToTouchdown._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -LandingFlareToTouchdown._add_meta_data('max_velocity', val=100., units='ft/s') -LandingFlareToTouchdown._add_meta_data('altitude_ref', val=1., units='ft') +class LandingTouchdownToNoseDownOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=5.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -LandingFlareToTouchdown._add_meta_data('lower_angle_of_attack', val=-10., units='deg') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -LandingFlareToTouchdown._add_meta_data('upper_angle_of_attack', val=15., units='deg') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -LandingFlareToTouchdown._add_meta_data('angle_of_attack_ref', val=10., units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -LandingFlareToTouchdown._add_initial_guess_meta_data( - InitialGuessPolynomialControl('angle_of_attack')) + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) -LandingFlareToTouchdown._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) -LandingFlareToTouchdown._add_initial_guess_meta_data( - InitialGuessControl(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='max_angle_of_attack', + default=10.0, + units='deg', + desc='Maximum angle of attack in this phase.', + ) @_init_initial_guess_meta_data class LandingTouchdownToNoseDown(PhaseBuilderBase): - ''' + """ Define a phase builder for rotating the nose down after touchdown. Attributes @@ -790,8 +974,8 @@ class LandingTouchdownToNoseDown(PhaseBuilderBase): supported options: - max_duration (5.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - max_angle_of_attack (10.0, 'deg') @@ -826,21 +1010,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'landing_touchdown' default_ode_class = LandingODE - # endregion : derived type customization points + default_options_class = LandingTouchdownToNoseDownOptions def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -856,102 +1036,142 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + fix_initial=False, + duration_bounds=(1, max_duration), + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) units = 'deg' max_angle_of_attack = user_options.get_val('max_angle_of_attack', units) - phase.add_polynomial_control( - 'angle_of_attack', opt=True, units=units, order=1, - lower=0, upper=max_angle_of_attack, fix_final=True, - fix_initial=False, ref=max_angle_of_attack) + phase.add_control( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + control_type='polynomial', + opt=True, + units=units, + order=1, + lower=0, + upper=max_angle_of_attack, + fix_final=True, + fix_initial=False, + ref=max_angle_of_attack, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=3, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': False, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': False, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -LandingTouchdownToNoseDown._add_meta_data('max_duration', val=5.0, units='s') +LandingTouchdownToNoseDown._add_initial_guess_meta_data( + InitialGuessPolynomialControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -LandingTouchdownToNoseDown._add_meta_data('duration_ref', val=1.0, units='s') -LandingTouchdownToNoseDown._add_meta_data('initial_ref', val=10.0, units='s') +class LandingNoseDownToStopOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=1000.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -LandingTouchdownToNoseDown._add_meta_data('distance_max', val=1000.0, units='ft') + self.declare( + name='time_duration_ref', default=10.0, units='s', desc='Scale factor ref for duration.' + ) -LandingTouchdownToNoseDown._add_meta_data('max_velocity', val=100.0, units='ft/s') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -LandingTouchdownToNoseDown._add_meta_data('max_angle_of_attack', val=10.0, units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -LandingTouchdownToNoseDown._add_initial_guess_meta_data( - InitialGuessPolynomialControl('angle_of_attack')) + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) @_init_initial_guess_meta_data class LandingNoseDownToStop(PhaseBuilderBase): - ''' + """ Define a phase builder for the final phase of landing, from nose down to full stop. Attributes @@ -964,7 +1184,7 @@ class LandingNoseDownToStop(PhaseBuilderBase): supported options: - max_duration - - duration_ref + - time_duration_ref - distance_max - max_velocity @@ -998,21 +1218,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'landing_stop' default_ode_class = LandingODE - # endregion : derived type customization points + default_options_class = LandingNoseDownToStopOptions def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -1028,101 +1244,107 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + fix_initial=False, + duration_bounds=(1, max_duration), + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, fix_final=False, - lower=0, ref=distance_max, - defect_ref=distance_max, units=units, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + fix_final=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, fix_final=True, - lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + fix_final=True, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) # TODO: Energy phase places this under an if num_engines > 0. phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - phase.add_parameter('angle_of_attack', val=0.0, opt=False, units='deg') + phase.add_parameter(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=0.0, opt=False, units='deg') phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=3, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': False, - 'friction_key': Mission.Takeoff.BRAKING_FRICTION_COEFFICIENT} - + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': False, 'friction_key': Mission.Takeoff.BRAKING_FRICTION_COEFFICIENT} -LandingNoseDownToStop._add_meta_data('max_duration', val=1000.0, units='s') - -LandingNoseDownToStop._add_meta_data('duration_ref', val=10.0, units='s') - -LandingNoseDownToStop._add_meta_data('initial_ref', val=10.0, units='s') - -LandingNoseDownToStop._add_meta_data('distance_max', val=1000.0, units='ft') - -LandingNoseDownToStop._add_meta_data('max_velocity', val=100.0, units='ft/s') LandingNoseDownToStop._add_initial_guess_meta_data( - InitialGuessParameter('angle_of_attack')) + InitialGuessParameter(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) class LandingTrajectory: - ''' + """ Define a trajectory builder for detailed landing. Identify, collect, and call the necessary phase builders to create a typical landing trajectory. - ''' + """ + MappedPhase = _TakeoffTrajectory.MappedPhase default_name = 'detailed_landing' @@ -1144,74 +1366,69 @@ def __init__(self, name=None): self._traj = None def get_phase_names(self): - ''' - Return a list of base names for available phases. - ''' + """Return a list of base names for available phases.""" keys = list(self._phases) return keys def get_phase(self, key) -> dm.Phase: - ''' + """ Return the phase associated with the specified base name. Raises ------ KeyError if the specified base name is not found - ''' - mapped_phase: self.MappedPhase = self._phases[key] + """ + mapped_phase = self._phases[key] return mapped_phase.phase def set_approach_to_mic_p3(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for moving from descent to the mic location P3. This phase - is required for acoustic calculations - ''' + is required for acoustic calculations. + """ self._approach_to_mic_p3 = phase_builder def set_mic_p3_to_obstacle(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for moving from the mic location P3 to the start of the runway, just above the required clearance height. This phase is required for - acoustic calculations - ''' + acoustic calculations. + """ self._mic_p3_to_obstacle = phase_builder def set_obstacle_to_flare(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for moving from the start of the runway, just above the required clearance height, to the start of a maneuver to help soften the impact of touchdown. - ''' + """ self._obstacle_to_flare = phase_builder def set_flare_to_touchdown(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for moving through a maneuver to help soften the impact of touchdown. - ''' + """ self._flare_to_touchdown = phase_builder def set_touchdown_to_nose_down(self, phase_builder: PhaseBuilderBase): - ''' - Assign a phase builder for rotating the nose down after touchdown. - ''' + """Assign a phase builder for rotating the nose down after touchdown.""" self._touchdown_to_nose_down = phase_builder def set_nose_down_to_stop(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the final phase of landing, from nose down to full stop. - ''' + """ self._nose_down_to_stop = phase_builder def build_trajectory( - self, *, aviary_options: AviaryValues, model: om.Group = None, - traj: dm.Trajectory = None + self, *, aviary_options: AviaryValues, model: om.Group = None, traj: dm.Trajectory = None ) -> dm.Trajectory: - ''' + """ Return a new trajectory for detailed landing analysis. Call only after assigning phase builders for required phases. @@ -1239,7 +1456,7 @@ def build_trajectory( Do not modify this object or any of its referenced data between the call to `build_trajectory()` and the call to `apply_initial_guesses()`, or the behavior is undefined, no diagnostic required. - ''' + """ if traj is None: traj = dm.Trajectory() @@ -1255,19 +1472,15 @@ def build_trajectory( # We need to create parameters for just the inputs we have. # They mostly come from the low-speed aero subsystem. - aero = CoreAerodynamicsBuilder('core_aerodynamics', - BaseMetaData, - LegacyCode('FLOPS')) + aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, LegacyCode('FLOPS')) - phase_info = {'subsystem_options': { - 'core_aerodynamics': {'method': 'low_speed'}} - } + args = {'method': 'low_speed'} - params = aero.get_parameters(aviary_options, phase_info) + params = aero.get_parameters(aviary_options, **args) # takeoff introduces this one. params[Mission.Landing.LIFT_COEFFICIENT_MAX] = { - 'shape': (1, ), + 'shape': (1,), 'static_target': True, } @@ -1275,13 +1488,14 @@ def build_trajectory( for phase in self._phases.keys(): ext_params[phase] = params - setup_trajectory_params(model, traj, aviary_options, - phase_names, external_parameters=ext_params) + setup_trajectory_params( + model, traj, aviary_options, phase_names, external_parameters=ext_params + ) return traj def apply_initial_guesses(self, prob: om.Problem, traj_name): - ''' + """ Call `prob.set_val()` for states/parameters/etc. for each phase in this trajectory. @@ -1293,11 +1507,11 @@ def apply_initial_guesses(self, prob: om.Problem, traj_name): for any phase with missing initial guesses that cannot be applied, a list of those missing initial guesses; if a given phase has no missing initial guesses, the returned mapping will not contain the name of that phase - ''' + """ not_applied = {} phase_builder: PhaseBuilderBase = None # type hint - for (phase, phase_builder) in self._phases.values(): + for phase, phase_builder in self._phases.values(): tmp = phase_builder.apply_initial_guesses(prob, traj_name, phase) if tmp: diff --git a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py index 5c5d716c9e..f91ba7fcf6 100644 --- a/aviary/mission/flops_based/phases/detailed_takeoff_phases.py +++ b/aviary/mission/flops_based/phases/detailed_takeoff_phases.py @@ -1,4 +1,4 @@ -''' +""" Define utilities for building detailed takeoff phases and the typical takeoff trajectory. Classes @@ -39,55 +39,80 @@ application to full stop TakeoffTrajectory : a trajectory builder for detailed takeoff -''' +""" + from collections import namedtuple import dymos as dm import openmdao.api as om from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessIntegrationVariable, + InitialGuessParameter, + InitialGuessPolynomialControl, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase -from aviary.mission.initial_guess_builders import InitialGuessControl, InitialGuessParameter, InitialGuessPolynomialControl, InitialGuessState, InitialGuessIntegrationVariable from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import LegacyCode from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Dynamic, Mission from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Dynamic, Mission def _init_initial_guess_meta_data(cls: PhaseBuilderBase): - ''' - Create default initial guess meta data preset with common items. - ''' + """Create default initial guess meta data preset with common items.""" cls._initial_guesses_meta_data_ = {} cls._add_initial_guess_meta_data( InitialGuessIntegrationVariable(), - desc='initial guess for initial time and duration specified as a tuple') + desc='initial guess for initial time and duration specified as a tuple', + ) cls._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for horizontal distance traveled') + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled' + ) - cls._add_initial_guess_meta_data( - InitialGuessState('velocity'), - desc='initial guess for speed') + cls._add_initial_guess_meta_data(InitialGuessState('velocity'), desc='initial guess for speed') - cls._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') + cls._add_initial_guess_meta_data(InitialGuessState('mass'), desc='initial guess for mass') cls._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') + InitialGuessControl('throttle'), desc='initial guess for throttle' + ) return cls +class TakeoffBrakeReleaseToDecisionSpeedOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=1000.0, + units='s', + desc='Upper bound on duration for this phase.', + ) + + self.declare( + name='time_duration_ref', default=10.0, units='s', desc='Scale factor ref for duration.' + ) + + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) + + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) + + @_init_initial_guess_meta_data class TakeoffBrakeReleaseToDecisionSpeed(PhaseBuilderBase): - ''' + """ Define a phase builder for the first phase of takeoff, from brake release to decision speed, the maximum speed at which takeoff can be safely brought to full stop using zero thrust while braking. @@ -102,7 +127,7 @@ class TakeoffBrakeReleaseToDecisionSpeed(PhaseBuilderBase): supported options: - max_duration (1000.0, 's') - - duration_ref (10.0, 's') + - time_duration_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') @@ -136,21 +161,16 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_brake_release' - default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffBrakeReleaseToDecisionSpeedOptions def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -166,92 +186,129 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) phase.set_time_options( - fix_initial=True, duration_bounds=(1, max_duration), - duration_ref=duration_ref, units=units) + fix_initial=True, + duration_bounds=(1, max_duration), + duration_ref=duration_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=True, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=True, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=True, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=True, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=True, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=True, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) # TODO: Energy phase places this under an if num_engines > 0. phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - phase.add_parameter('angle_of_attack', val=0.0, opt=False, units='deg') + phase.add_parameter(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=0.0, opt=False, units='deg') phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=3, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': False, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': False, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffBrakeReleaseToDecisionSpeed._add_meta_data('max_duration', val=1000.0, units='s') +TakeoffBrakeReleaseToDecisionSpeed._add_initial_guess_meta_data( + InitialGuessParameter(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -TakeoffBrakeReleaseToDecisionSpeed._add_meta_data('duration_ref', val=10.0, units='s') -TakeoffBrakeReleaseToDecisionSpeed._add_meta_data('distance_max', val=1000.0, units='ft') +class TakeoffDecisionSpeedToRotateOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=1000.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffBrakeReleaseToDecisionSpeed._add_meta_data( - 'max_velocity', val=100.0, units='ft/s') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffBrakeReleaseToDecisionSpeed._add_initial_guess_meta_data( - InitialGuessParameter('angle_of_attack')) + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) + + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) + + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) @_init_initial_guess_meta_data class TakeoffDecisionSpeedToRotate(PhaseBuilderBase): - ''' + """ Define a phase builder for the second phase of takeoff, from decision speed to rotation. @@ -265,8 +322,8 @@ class TakeoffDecisionSpeedToRotate(PhaseBuilderBase): supported options: - max_duration (1000.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') @@ -300,21 +357,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_decision_speed' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffDecisionSpeedToRotateOptions def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -330,60 +383,83 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) # TODO: Energy phase places this under an if num_engines > 0. phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) phase.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.2, ref=1.2) - phase.add_parameter('angle_of_attack', val=0.0, opt=False, units='deg') + phase.add_parameter(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=0.0, opt=False, units='deg') phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( @@ -393,39 +469,53 @@ def build_phase(self, aviary_options=None): return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=3, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': False, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': False, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffDecisionSpeedToRotate._add_meta_data('max_duration', val=1000.0, units='s') +TakeoffDecisionSpeedToRotate._add_initial_guess_meta_data( + InitialGuessParameter(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -TakeoffDecisionSpeedToRotate._add_meta_data('duration_ref', val=1.0, units='s') -TakeoffDecisionSpeedToRotate._add_meta_data('initial_ref', val=10.0, units='s') +class TakeoffDecisionSpeedBrakeDelayOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=1000.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffDecisionSpeedToRotate._add_meta_data('distance_max', val=1000.0, units='ft') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffDecisionSpeedToRotate._add_meta_data('max_velocity', val=100.0, units='ft/s') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffDecisionSpeedToRotate._add_initial_guess_meta_data( - InitialGuessParameter('angle_of_attack')) + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) + + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) @_init_initial_guess_meta_data class TakeoffDecisionSpeedBrakeDelay(TakeoffDecisionSpeedToRotate): - ''' + """ Define a phase builder for the second phase of aborted takeoff, from decision speed to brake application. @@ -439,8 +529,8 @@ class TakeoffDecisionSpeedBrakeDelay(TakeoffDecisionSpeedToRotate): supported options: - max_duration (1000.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') @@ -474,21 +564,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_brake_delay' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_classs = TakeoffDecisionSpeedBrakeDelayOptions def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -504,29 +590,56 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) phase.set_time_options(fix_duration=True) return phase -TakeoffDecisionSpeedBrakeDelay._add_meta_data('max_duration', val=1000.0, units='s') +TakeoffDecisionSpeedBrakeDelay._add_initial_guess_meta_data( + InitialGuessParameter(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) + + +class TakeoffRotateToLiftoffOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=5.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffDecisionSpeedBrakeDelay._add_meta_data('duration_ref', val=1.0, units='s') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffDecisionSpeedBrakeDelay._add_meta_data('initial_ref', val=10.0, units='s') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffDecisionSpeedBrakeDelay._add_meta_data('distance_max', val=1000.0, units='ft') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffDecisionSpeedBrakeDelay._add_meta_data('max_velocity', val=100.0, units='ft/s') + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) -TakeoffDecisionSpeedBrakeDelay._add_initial_guess_meta_data( - InitialGuessParameter('angle_of_attack')) + self.declare( + name='max_angle_of_attack', + default=10.0, + units='deg', + desc='Maximum angle of attack in this phase.', + ) @_init_initial_guess_meta_data class TakeoffRotateToLiftoff(PhaseBuilderBase): - ''' + """ Define a phase builder for the third phase of takeoff, from rotation to liftoff. Attributes @@ -539,8 +652,8 @@ class TakeoffRotateToLiftoff(PhaseBuilderBase): supported options: - max_duration (5.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - max_angle_of_attack (10.0, 'deg') @@ -575,21 +688,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_rotate' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffRotateToLiftoffOptions def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -605,62 +714,91 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - max_angle_of_attack, units = user_options.get_item('max_angle_of_attack') + max_angle_of_attack, units = user_options['max_angle_of_attack'] phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - phase.add_polynomial_control( - 'angle_of_attack', opt=True, units=units, order=1, - lower=0, upper=max_angle_of_attack, - ref=max_angle_of_attack) + phase.add_control( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + control_type='polynomial', + opt=True, + units=units, + order=1, + lower=0, + upper=max_angle_of_attack, + ref=max_angle_of_attack, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) phase.add_timeseries_output( @@ -670,41 +808,86 @@ def build_phase(self, aviary_options=None): return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=3, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': False, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': False, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffRotateToLiftoff._add_meta_data('max_duration', val=5.0, units='s') +TakeoffRotateToLiftoff._add_initial_guess_meta_data( + InitialGuessPolynomialControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -TakeoffRotateToLiftoff._add_meta_data('duration_ref', val=1.0, units='s') -TakeoffRotateToLiftoff._add_meta_data('initial_ref', val=10.0, units='s') +class TakeoffLiftoffToObstacleOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffRotateToLiftoff._add_meta_data('distance_max', val=1000.0, units='ft') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffRotateToLiftoff._add_meta_data('max_velocity', val=100.0, units='ft/s') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffRotateToLiftoff._add_meta_data('max_angle_of_attack', val=10.0, units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffRotateToLiftoff._add_initial_guess_meta_data( - InitialGuessPolynomialControl('angle_of_attack')) + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) + + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) + + self.declare( + name='flight_path_angle_ref', + default=5.0, + units='deg', + desc='Scale factor ref for flight path angle.', + ) + + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) + + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) + + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) @_init_initial_guess_meta_data class TakeoffLiftoffToObstacle(PhaseBuilderBase): - ''' + """ Define a phase builder for the fourth phase of takeoff, from liftoff to clearing the required obstacle. @@ -718,8 +901,8 @@ class TakeoffLiftoffToObstacle(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -760,21 +943,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_liftoff' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffLiftoffToObstacleOptions def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -790,153 +969,236 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=True, lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, upper=altitude_ref, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=True, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + upper=altitude_ref, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') + flight_path_angle_ref, units = user_options['flight_path_angle_ref'] phase.add_state( - Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=True, lower=0, - ref=flight_path_angle_ref, upper=flight_path_angle_ref, - defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) + Dynamic.Mission.FLIGHT_PATH_ANGLE, + fix_initial=True, + lower=0, + ref=flight_path_angle_ref, + upper=flight_path_angle_ref, + defect_ref=flight_path_angle_ref, + units=units, + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - lower_angle_of_attack, units = user_options.get_item('lower_angle_of_attack') + lower_angle_of_attack, units = user_options['lower_angle_of_attack'] upper_angle_of_attack = user_options.get_val('upper_angle_of_attack', units) angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) phase.add_control( - 'angle_of_attack', opt=True, units=units, - lower=lower_angle_of_attack, upper=upper_angle_of_attack, - ref=angle_of_attack_ref) + Dynamic.Vehicle.ANGLE_OF_ATTACK, + opt=True, + units=units, + lower=lower_angle_of_attack, + upper=upper_angle_of_attack, + ref=angle_of_attack_ref, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - obstacle_height, units = aviary_options.get_item( - Mission.Takeoff.OBSTACLE_HEIGHT) + obstacle_height, units = aviary_options.get_item(Mission.Takeoff.OBSTACLE_HEIGHT) if obstacle_height is None: - raise TypeError( - f'missing required aviary_option: {Mission.Takeoff.OBSTACLE_HEIGHT}') + raise TypeError(f'missing required aviary_option: {Mission.Takeoff.OBSTACLE_HEIGHT}') - airport_altitude = aviary_options.get_val( - Mission.Takeoff.AIRPORT_ALTITUDE, units) + airport_altitude = aviary_options.get_val(Mission.Takeoff.AIRPORT_ALTITUDE, units) h = obstacle_height + airport_altitude phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='final', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, + loc='final', + equals=h, + ref=h, + units=units, + linear=True, + ) - phase.add_path_constraint( - 'v_over_v_stall', lower=1.25, ref=2.0) + phase.add_path_constraint('v_over_v_stall', lower=1.25, ref=2.0) - phase.add_boundary_constraint('takeoff_eom.forces_vertical', loc='initial', equals=0, - ref=100000) + phase.add_boundary_constraint( + 'takeoff_eom.forces_vertical', loc='initial', equals=0, ref=100000 + ) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=5, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffLiftoffToObstacle._add_meta_data('max_duration', val=100., units='s') +TakeoffLiftoffToObstacle._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -TakeoffLiftoffToObstacle._add_meta_data('duration_ref', val=1., units='s') +TakeoffLiftoffToObstacle._add_initial_guess_meta_data(InitialGuessState('altitude')) -TakeoffLiftoffToObstacle._add_meta_data('initial_ref', val=10.0, units='s') +TakeoffLiftoffToObstacle._add_initial_guess_meta_data( + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -TakeoffLiftoffToObstacle._add_meta_data('distance_max', val=1000., units='ft') -TakeoffLiftoffToObstacle._add_meta_data('max_velocity', val=100., units='ft/s') +class TakeoffObstacleToMicP2Options(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffLiftoffToObstacle._add_meta_data('altitude_ref', val=1., units='ft') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffLiftoffToObstacle._add_meta_data('flight_path_angle_ref', val=5., units='deg') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffLiftoffToObstacle._add_meta_data('lower_angle_of_attack', val=-10., units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffLiftoffToObstacle._add_meta_data('upper_angle_of_attack', val=15., units='deg') + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) -TakeoffLiftoffToObstacle._add_meta_data('angle_of_attack_ref', val=10., units='deg') + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) -TakeoffLiftoffToObstacle._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) + self.declare( + name='flight_path_angle_ref', + default=5.0, + units='deg', + desc='Scale factor ref for flight path angle.', + ) -TakeoffLiftoffToObstacle._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) -TakeoffLiftoffToObstacle._add_initial_guess_meta_data( - InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) + + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) + + self.declare( + name='mic_altitude', default=1.0, units='ft', desc='Altitude for the P2 microphone.' + ) @_init_initial_guess_meta_data class TakeoffObstacleToMicP2(PhaseBuilderBase): - ''' + """ Define a phase builder for the fifth phase of takeoff, from clearing the required obstacle to the P2 mic location. This phase is required for acoustic calculations. @@ -950,8 +1212,8 @@ class TakeoffObstacleToMicP2(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -993,21 +1255,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_climb' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffObstacleToMicP2Options def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -1023,149 +1281,228 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=False, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') + flight_path_angle_ref, units = user_options['flight_path_angle_ref'] phase.add_state( - Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + fix_initial=False, + lower=0, ref=flight_path_angle_ref, - defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) + defect_ref=flight_path_angle_ref, + units=units, + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - lower_angle_of_attack, units = user_options.get_item('lower_angle_of_attack') + lower_angle_of_attack, units = user_options['lower_angle_of_attack'] upper_angle_of_attack = user_options.get_val('upper_angle_of_attack', units) angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) phase.add_control( - 'angle_of_attack', opt=True, units=units, - lower=lower_angle_of_attack, upper=upper_angle_of_attack, - ref=angle_of_attack_ref) + Dynamic.Vehicle.ANGLE_OF_ATTACK, + opt=True, + units=units, + lower=lower_angle_of_attack, + upper=upper_angle_of_attack, + ref=angle_of_attack_ref, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - final_altitude, units = user_options.get_item('mic_altitude') + final_altitude, units = user_options['mic_altitude'] - airport_altitude = aviary_options.get_val( - Mission.Takeoff.AIRPORT_ALTITUDE, units) + airport_altitude = aviary_options.get_val(Mission.Takeoff.AIRPORT_ALTITUDE, units) h = final_altitude + airport_altitude phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, loc='final', equals=h, ref=h, units=units, linear=True) + Dynamic.Mission.ALTITUDE, + loc='final', + equals=h, + ref=h, + units=units, + linear=True, + ) - phase.add_boundary_constraint( - 'v_over_v_stall', loc='final', lower=1.25, ref=1.25) + phase.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" num_segments_climb = 7 - transcription = dm.Radau(num_segments=num_segments_climb, order=3, - compressed=True) + transcription = dm.Radau(num_segments=num_segments_climb, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffObstacleToMicP2._add_meta_data('max_duration', val=100., units='s') +TakeoffObstacleToMicP2._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) + +TakeoffObstacleToMicP2._add_initial_guess_meta_data(InitialGuessState('altitude')) -TakeoffObstacleToMicP2._add_meta_data('duration_ref', val=1., units='s') +TakeoffObstacleToMicP2._add_initial_guess_meta_data( + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -TakeoffObstacleToMicP2._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffObstacleToMicP2._add_meta_data('distance_max', val=1000., units='ft') +class TakeoffMicP2ToEngineCutbackOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffObstacleToMicP2._add_meta_data('max_velocity', val=100., units='ft/s') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffObstacleToMicP2._add_meta_data('altitude_ref', val=1., units='ft') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffObstacleToMicP2._add_meta_data('flight_path_angle_ref', val=5., units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffObstacleToMicP2._add_meta_data('lower_angle_of_attack', val=-10., units='deg') + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) -TakeoffObstacleToMicP2._add_meta_data('upper_angle_of_attack', val=15., units='deg') + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) -TakeoffObstacleToMicP2._add_meta_data('angle_of_attack_ref', val=10., units='deg') + self.declare( + name='flight_path_angle_ref', + default=5.0, + units='deg', + desc='Scale factor ref for flight path angle.', + ) -TakeoffObstacleToMicP2._add_meta_data('mic_altitude', val=1.0, units='ft') + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) -TakeoffObstacleToMicP2._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) -TakeoffObstacleToMicP2._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) -TakeoffObstacleToMicP2._add_initial_guess_meta_data( - InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='final_range', default=1000.0, units='ft', desc='Final range at end of phase.' + ) @_init_initial_guess_meta_data class TakeoffMicP2ToEngineCutback(PhaseBuilderBase): - ''' + """ Define a phase builder for the sixth phase of takeoff, from the P2 mic location to engine cutback. This phase is required for acoustic calculations. @@ -1179,8 +1516,8 @@ class TakeoffMicP2ToEngineCutback(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -1222,21 +1559,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_climb' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffMicP2ToEngineCutbackOptions def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -1252,150 +1585,213 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=False, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') + flight_path_angle_ref, units = user_options['flight_path_angle_ref'] phase.add_state( - Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + fix_initial=False, + lower=0, ref=flight_path_angle_ref, - defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) + defect_ref=flight_path_angle_ref, + units=units, + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - lower_angle_of_attack, units = user_options.get_item('lower_angle_of_attack') + lower_angle_of_attack, units = user_options['lower_angle_of_attack'] upper_angle_of_attack = user_options.get_val('upper_angle_of_attack', units) angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) phase.add_control( - 'angle_of_attack', opt=True, units=units, - lower=lower_angle_of_attack, upper=upper_angle_of_attack, - ref=angle_of_attack_ref) + Dynamic.Vehicle.ANGLE_OF_ATTACK, + opt=True, + units=units, + lower=lower_angle_of_attack, + upper=upper_angle_of_attack, + ref=angle_of_attack_ref, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) # start engine cutback phase at this range, where this phase ends # TODO: what is the difference between distance_max and final_range? # - should final_range replace distance_max? # - is there any reason to support both in this phase? - final_range, units = user_options.get_item('final_range') + final_range, units = user_options['final_range'] phase.add_boundary_constraint( - Dynamic.Mission.DISTANCE, loc='final', equals=final_range, ref=final_range, - units=units, linear=True) + Dynamic.Mission.DISTANCE, + loc='final', + equals=final_range, + ref=final_range, + units=units, + linear=True, + ) - phase.add_boundary_constraint( - 'v_over_v_stall', loc='final', lower=1.25, ref=1.25) + phase.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" num_segments_climb = 7 - transcription = dm.Radau(num_segments=num_segments_climb, order=3, - compressed=True) + transcription = dm.Radau(num_segments=num_segments_climb, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} - - -TakeoffMicP2ToEngineCutback._add_meta_data('max_duration', val=100., units='s') + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffMicP2ToEngineCutback._add_meta_data('duration_ref', val=1., units='s') -TakeoffMicP2ToEngineCutback._add_meta_data('initial_ref', val=10.0, units='s') +TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -TakeoffMicP2ToEngineCutback._add_meta_data('distance_max', val=1000., units='ft') +TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data(InitialGuessState('altitude')) -TakeoffMicP2ToEngineCutback._add_meta_data('max_velocity', val=100., units='ft/s') +TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data( + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -TakeoffMicP2ToEngineCutback._add_meta_data('altitude_ref', val=1., units='ft') -TakeoffMicP2ToEngineCutback._add_meta_data('flight_path_angle_ref', val=5., units='deg') +class TakeoffEngineCutbackOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffMicP2ToEngineCutback._add_meta_data( - 'lower_angle_of_attack', val=-10., units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffMicP2ToEngineCutback._add_meta_data('upper_angle_of_attack', val=15., units='deg') + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) -TakeoffMicP2ToEngineCutback._add_meta_data('angle_of_attack_ref', val=10., units='deg') + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) -TakeoffMicP2ToEngineCutback._add_meta_data('final_range', val=1000., units='ft') + self.declare( + name='flight_path_angle_ref', + default=5.0, + units='deg', + desc='Scale factor ref for flight path angle.', + ) -TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) -TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) -TakeoffMicP2ToEngineCutback._add_initial_guess_meta_data( - InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) @_init_initial_guess_meta_data class TakeoffEngineCutback(PhaseBuilderBase): - ''' + """ Define a phase builder for the seventh phase of takeoff, from start to finish of engine cutback. This phase is required for acoustic calculations. @@ -1408,7 +1804,7 @@ class TakeoffEngineCutback(PhaseBuilderBase): state/path constraint values and flags supported options: - - initial_ref (10.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -1449,21 +1845,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_climb' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffEngineCutbackOptions def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -1479,131 +1871,210 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - initial_ref, units = user_options.get_item('initial_ref') + initial_ref, units = user_options['time_initial_ref'] phase.set_time_options( - fix_initial=False, fix_duration=True, + fix_initial=False, + fix_duration=True, initial_bounds=(1, initial_ref), initial_ref=initial_ref, - units=units) + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=False, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') + flight_path_angle_ref, units = user_options['flight_path_angle_ref'] phase.add_state( - Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + fix_initial=False, + lower=0, ref=flight_path_angle_ref, - defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) + defect_ref=flight_path_angle_ref, + units=units, + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - lower_angle_of_attack, units = user_options.get_item('lower_angle_of_attack') + lower_angle_of_attack, units = user_options['lower_angle_of_attack'] upper_angle_of_attack = user_options.get_val('upper_angle_of_attack', units) angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) phase.add_control( - 'angle_of_attack', opt=True, units=units, - lower=lower_angle_of_attack, upper=upper_angle_of_attack, - ref=angle_of_attack_ref) + Dynamic.Vehicle.ANGLE_OF_ATTACK, + opt=True, + units=units, + lower=lower_angle_of_attack, + upper=upper_angle_of_attack, + ref=angle_of_attack_ref, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - phase.add_boundary_constraint( - 'v_over_v_stall', loc='final', lower=1.25, ref=1.25) + phase.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" num_segments_climb = 7 - transcription = dm.Radau(num_segments=num_segments_climb, order=3, - compressed=True) + transcription = dm.Radau(num_segments=num_segments_climb, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + + +TakeoffEngineCutback._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) + +TakeoffEngineCutback._add_initial_guess_meta_data(InitialGuessState('altitude')) +TakeoffEngineCutback._add_initial_guess_meta_data( + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -TakeoffEngineCutback._add_meta_data('initial_ref', val=10.0, units='s') -TakeoffEngineCutback._add_meta_data('distance_max', val=1000., units='ft') +class TakeoffEngineCutbackToMicP1Options(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffEngineCutback._add_meta_data('max_velocity', val=100., units='ft/s') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffEngineCutback._add_meta_data('altitude_ref', val=1., units='ft') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffEngineCutback._add_meta_data('flight_path_angle_ref', val=5., units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffEngineCutback._add_meta_data('lower_angle_of_attack', val=-10., units='deg') + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) -TakeoffEngineCutback._add_meta_data('upper_angle_of_attack', val=15., units='deg') + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) -TakeoffEngineCutback._add_meta_data('angle_of_attack_ref', val=10., units='deg') + self.declare( + name='flight_path_angle_ref', + default=5.0, + units='deg', + desc='Scale factor ref for flight path angle.', + ) -TakeoffEngineCutback._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) -TakeoffEngineCutback._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) -TakeoffEngineCutback._add_initial_guess_meta_data( - InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) + + self.declare( + name='mic_range', default=1000.0, units='ft', desc='Downfield location of microphone.' + ) @_init_initial_guess_meta_data class TakeoffEngineCutbackToMicP1(PhaseBuilderBase): - ''' + """ Define a phase builder for the eighth phase of takeoff, from engine cutback to the P1 mic location. This phase is required for acoustic calculations. @@ -1617,8 +2088,8 @@ class TakeoffEngineCutbackToMicP1(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -1660,21 +2131,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_climb' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffEngineCutbackToMicP1Options def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -1690,146 +2157,224 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=False, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') + flight_path_angle_ref, units = user_options['flight_path_angle_ref'] phase.add_state( - Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + fix_initial=False, + lower=0, ref=flight_path_angle_ref, - defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) + defect_ref=flight_path_angle_ref, + units=units, + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - lower_angle_of_attack, units = user_options.get_item('lower_angle_of_attack') + lower_angle_of_attack, units = user_options['lower_angle_of_attack'] upper_angle_of_attack = user_options.get_val('upper_angle_of_attack', units) angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) phase.add_control( - 'angle_of_attack', opt=True, units=units, - lower=lower_angle_of_attack, upper=upper_angle_of_attack, - ref=angle_of_attack_ref) + Dynamic.Vehicle.ANGLE_OF_ATTACK, + opt=True, + units=units, + lower=lower_angle_of_attack, + upper=upper_angle_of_attack, + ref=angle_of_attack_ref, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - mic_range, units = user_options.get_item('mic_range') + mic_range, units = user_options['mic_range'] phase.add_boundary_constraint( - Dynamic.Mission.DISTANCE, loc='final', equals=mic_range, ref=mic_range, - units=units, linear=True) + Dynamic.Mission.DISTANCE, + loc='final', + equals=mic_range, + ref=mic_range, + units=units, + linear=True, + ) - phase.add_boundary_constraint( - 'v_over_v_stall', loc='final', lower=1.25, ref=1.25) + phase.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" num_segments_climb = 7 - transcription = dm.Radau(num_segments=num_segments_climb, order=3, - compressed=True) + transcription = dm.Radau(num_segments=num_segments_climb, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffEngineCutbackToMicP1._add_meta_data('max_duration', val=100., units='s') +TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -TakeoffEngineCutbackToMicP1._add_meta_data('duration_ref', val=1., units='s') +TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data(InitialGuessState('altitude')) -TakeoffEngineCutbackToMicP1._add_meta_data('initial_ref', val=10.0, units='s') +TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data( + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -TakeoffEngineCutbackToMicP1._add_meta_data('distance_max', val=1000., units='ft') -TakeoffEngineCutbackToMicP1._add_meta_data('max_velocity', val=100., units='ft/s') +class TakeoffMicP1ToClimbOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) + + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffEngineCutbackToMicP1._add_meta_data('altitude_ref', val=1., units='ft') + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffEngineCutbackToMicP1._add_meta_data('flight_path_angle_ref', val=5., units='deg') + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffEngineCutbackToMicP1._add_meta_data( - 'lower_angle_of_attack', val=-10., units='deg') + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) -TakeoffEngineCutbackToMicP1._add_meta_data('upper_angle_of_attack', val=15., units='deg') + self.declare( + name='altitude_ref', default=1.0, units='ft', desc='Scale factor ref for altitude.' + ) -TakeoffEngineCutbackToMicP1._add_meta_data('angle_of_attack_ref', val=10., units='deg') + self.declare( + name='flight_path_angle_ref', + default=5.0, + units='deg', + desc='Scale factor ref for flight path angle.', + ) -TakeoffEngineCutbackToMicP1._add_meta_data('mic_range', val=1000.0, units='ft') + self.declare( + name='lower_angle_of_attack', + types=tuple, + default=-10.0, + units='deg', + desc='Lower bound for angle of attack.', + ) -TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) + self.declare( + name='upper_angle_of_attack', + default=15.0, + units='deg', + desc='Upper bound for angle of attack.', + ) -TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='angle_of_attack_ref', + default=10.0, + units='deg', + desc='Scale factor ref for angle of attack.', + ) -TakeoffEngineCutbackToMicP1._add_initial_guess_meta_data( - InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='mic_range', default=1000.0, units='ft', desc='Downfield location of microphone.' + ) @_init_initial_guess_meta_data class TakeoffMicP1ToClimb(PhaseBuilderBase): - ''' + """ Define a phase builder for the ninth phase of takeoff, from P1 mic location to climb. This phase is required for acoustic calculations. @@ -1843,8 +2388,8 @@ class TakeoffMicP1ToClimb(PhaseBuilderBase): supported options: - max_duration (100.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') - altitude_ref (1.0, 'ft') @@ -1886,21 +2431,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_climb' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffMicP1ToClimbOptions def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -1916,145 +2457,187 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - altitude_ref, units = user_options.get_item('altitude_ref') + altitude_ref, units = user_options['altitude_ref'] phase.add_state( - Dynamic.Mission.ALTITUDE, fix_initial=False, lower=0, ref=altitude_ref, - defect_ref=altitude_ref, units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE) + Dynamic.Mission.ALTITUDE, + fix_initial=False, + lower=0, + ref=altitude_ref, + defect_ref=altitude_ref, + units=units, + rate_source=Dynamic.Mission.ALTITUDE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, lower=0, ref=max_velocity, - defect_ref=max_velocity, units=units, upper=max_velocity, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + lower=0, + ref=max_velocity, + defect_ref=max_velocity, + units=units, + upper=max_velocity, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) - flight_path_angle_ref, units = user_options.get_item('flight_path_angle_ref') + flight_path_angle_ref, units = user_options['flight_path_angle_ref'] phase.add_state( - Dynamic.Mission.FLIGHT_PATH_ANGLE, fix_initial=False, lower=0, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + fix_initial=False, + lower=0, ref=flight_path_angle_ref, - defect_ref=flight_path_angle_ref, units=units, - rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE) + defect_ref=flight_path_angle_ref, + units=units, + rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - lower_angle_of_attack, units = user_options.get_item('lower_angle_of_attack') + lower_angle_of_attack, units = user_options['lower_angle_of_attack'] upper_angle_of_attack = user_options.get_val('upper_angle_of_attack', units) angle_of_attack_ref = user_options.get_val('angle_of_attack_ref', units) phase.add_control( - 'angle_of_attack', opt=True, units=units, - lower=lower_angle_of_attack, upper=upper_angle_of_attack, - ref=angle_of_attack_ref) + Dynamic.Vehicle.ANGLE_OF_ATTACK, + opt=True, + units=units, + lower=lower_angle_of_attack, + upper=upper_angle_of_attack, + ref=angle_of_attack_ref, + ) phase.add_timeseries_output( - Dynamic.Mission.DRAG, output_name=Dynamic.Mission.DRAG, units='lbf' + Dynamic.Vehicle.DRAG, output_name=Dynamic.Vehicle.DRAG, units='lbf' ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, - output_name=Dynamic.Mission.THRUST_TOTAL, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', ) - mic_range, units = user_options.get_item('mic_range') + mic_range, units = user_options['mic_range'] phase.add_boundary_constraint( - Dynamic.Mission.DISTANCE, loc='final', equals=mic_range, ref=mic_range, - units=units, linear=True) + Dynamic.Mission.DISTANCE, + loc='final', + equals=mic_range, + ref=mic_range, + units=units, + linear=True, + ) - phase.add_boundary_constraint( - 'v_over_v_stall', loc='final', lower=1.25, ref=1.25) + phase.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" num_segments_climb = 7 - transcription = dm.Radau(num_segments=num_segments_climb, order=3, - compressed=True) + transcription = dm.Radau(num_segments=num_segments_climb, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': True, - 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} - - -TakeoffMicP1ToClimb._add_meta_data('max_duration', val=100., units='s') - -TakeoffMicP1ToClimb._add_meta_data('duration_ref', val=1., units='s') - -TakeoffMicP1ToClimb._add_meta_data('initial_ref', val=10.0, units='s') + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': True, 'friction_key': Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT} -TakeoffMicP1ToClimb._add_meta_data('distance_max', val=1000., units='ft') -TakeoffMicP1ToClimb._add_meta_data('max_velocity', val=100., units='ft/s') - -TakeoffMicP1ToClimb._add_meta_data('altitude_ref', val=1., units='ft') +TakeoffMicP1ToClimb._add_initial_guess_meta_data( + InitialGuessControl(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) -TakeoffMicP1ToClimb._add_meta_data('flight_path_angle_ref', val=5., units='deg') +TakeoffMicP1ToClimb._add_initial_guess_meta_data(InitialGuessState('altitude')) -TakeoffMicP1ToClimb._add_meta_data('lower_angle_of_attack', val=-10., units='deg') +TakeoffMicP1ToClimb._add_initial_guess_meta_data( + InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE) +) -TakeoffMicP1ToClimb._add_meta_data('upper_angle_of_attack', val=15., units='deg') -TakeoffMicP1ToClimb._add_meta_data('angle_of_attack_ref', val=10., units='deg') +class TakeoffBrakeToAbortOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='max_duration', + default=100.0, + units='s', + desc='Upper bound on duration for this phase.', + ) -TakeoffMicP1ToClimb._add_meta_data('mic_range', val=1000., units='ft') + self.declare( + name='time_duration_ref', default=1.0, units='s', desc='Scale factor ref for duration.' + ) -TakeoffMicP1ToClimb._add_initial_guess_meta_data( - InitialGuessControl('angle_of_attack')) + self.declare( + name='time_initial_ref', + default=10.0, + units='s', + desc='Scale factor ref for the phase starting time.', + ) -TakeoffMicP1ToClimb._add_initial_guess_meta_data(InitialGuessState('altitude')) + self.declare( + name='distance_max', default=1000.0, units='ft', desc='Upper bound for distance.' + ) -TakeoffMicP1ToClimb._add_initial_guess_meta_data( - InitialGuessState(Dynamic.Mission.FLIGHT_PATH_ANGLE)) + self.declare( + name='max_velocity', default=100.0, units='ft/s', desc='Upper bound for velocity.' + ) @_init_initial_guess_meta_data class TakeoffBrakeToAbort(PhaseBuilderBase): - ''' + """ Define a phase builder for the last phase of aborted takeoff, from brake application to full stop. @@ -2068,8 +2651,8 @@ class TakeoffBrakeToAbort(PhaseBuilderBase): supported options: - max_duration (1000.0, 's') - - duration_ref (1.0, 's') - - initial_ref (10.0, 's') + - time_duration_ref (1.0, 's') + - time_initial_ref (10.0, 's') - distance_max (1000.0, 'ft') - max_velocity (100.0, 'ft/s') @@ -2103,21 +2686,17 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' - __slots__ = () + """ - # region : derived type customization points - _meta_data_ = {} + __slots__ = () default_name = 'takeoff_abort' default_ode_class = TakeoffODE - # endregion : derived type customization points + default_options_class = TakeoffBrakeToAbortOptions def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -2133,91 +2712,99 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - max_duration, units = user_options.get_item('max_duration') - duration_ref = user_options.get_val('duration_ref', units) - initial_ref = user_options.get_val('initial_ref', units) + max_duration, units = user_options['max_duration'] + duration_ref = user_options.get_val('time_duration_ref', units) + initial_ref = user_options.get_val('time_initial_ref', units) phase.set_time_options( - fix_initial=False, duration_bounds=(1, max_duration), + fix_initial=False, + duration_bounds=(1, max_duration), initial_bounds=(1, initial_ref), - duration_ref=duration_ref, initial_ref=initial_ref, - units=units) + duration_ref=duration_ref, + initial_ref=initial_ref, + units=units, + ) - distance_max, units = user_options.get_item('distance_max') + distance_max, units = user_options['distance_max'] phase.add_state( - Dynamic.Mission.DISTANCE, fix_initial=False, lower=0, ref=distance_max, - defect_ref=distance_max, units=units, upper=distance_max, - rate_source=Dynamic.Mission.DISTANCE_RATE) + Dynamic.Mission.DISTANCE, + fix_initial=False, + lower=0, + ref=distance_max, + defect_ref=distance_max, + units=units, + upper=distance_max, + rate_source=Dynamic.Mission.DISTANCE_RATE, + ) - max_velocity, units = user_options.get_item('max_velocity') + max_velocity, units = user_options['max_velocity'] phase.add_state( - Dynamic.Mission.VELOCITY, fix_initial=False, fix_final=True, - lower=0, ref=max_velocity, upper=max_velocity, - defect_ref=max_velocity, units=units, - rate_source=Dynamic.Mission.VELOCITY_RATE) + Dynamic.Mission.VELOCITY, + fix_initial=False, + fix_final=True, + lower=0, + ref=max_velocity, + upper=max_velocity, + defect_ref=max_velocity, + units=units, + rate_source=Dynamic.Mission.VELOCITY_RATE, + ) phase.add_state( - Dynamic.Mission.MASS, fix_initial=False, fix_final=False, - lower=0.0, upper=1e9, ref=5e4, defect_ref=5e4, units='kg', - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, + fix_initial=False, + fix_final=False, + lower=0.0, + upper=1e9, + ref=5e4, + defect_ref=5e4, + units='kg', + rate_source=Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + targets=Dynamic.Vehicle.MASS, ) phase.add_control( - Dynamic.Mission.THROTTLE, - targets=Dynamic.Mission.THROTTLE, units='unitless', - opt=False + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, ) - phase.add_parameter('angle_of_attack', val=0.0, opt=False, units='deg') + phase.add_parameter(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=0.0, opt=False, units='deg') return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" transcription = dm.Radau(num_segments=3, order=3, compressed=True) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - return { - 'climbing': False, - 'friction_key': Mission.Takeoff.BRAKING_FRICTION_COEFFICIENT} - - -TakeoffBrakeToAbort._add_meta_data('max_duration', val=1000.0, units='s') - -TakeoffBrakeToAbort._add_meta_data('duration_ref', val=1.0, units='s') - -TakeoffBrakeToAbort._add_meta_data('initial_ref', val=10.0, units='s') + """Return extra kwargs required for initializing the ODE.""" + return {'climbing': False, 'friction_key': Mission.Takeoff.BRAKING_FRICTION_COEFFICIENT} -TakeoffBrakeToAbort._add_meta_data('distance_max', val=1000.0, units='ft') - -TakeoffBrakeToAbort._add_meta_data('max_velocity', val=100.0, units='ft/s') TakeoffBrakeToAbort._add_initial_guess_meta_data( - InitialGuessParameter('angle_of_attack')) + InitialGuessParameter(Dynamic.Vehicle.ANGLE_OF_ATTACK) +) class TakeoffTrajectory: - ''' + """ Define a trajectory builder for detailed takeoff. Identify, collect, and call the necessary phase builders to create a typical takeoff trajectory. - ''' + """ + MappedPhase = namedtuple('MappedPhase', ('phase', 'phase_builder')) default_name = 'detailed_takeoff' @@ -2244,102 +2831,98 @@ def __init__(self, name=None): self._traj = None def get_phase_names(self): - ''' - Return a list of base names for available phases. - ''' + """Return a list of base names for available phases.""" keys = list(self._phases) return keys def get_phase(self, key) -> dm.Phase: - ''' + """ Return the phase associated with the specified base name. Raises ------ KeyError if the specified base name is not found - ''' - mapped_phase: self.MappedPhase = self._phases[key] + """ + mapped_phase = self._phases[key] return mapped_phase.phase def set_brake_release_to_decision_speed(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the beginning of takeoff to the time when the pilot must choose either to liftoff or halt the aircraft. - ''' + """ self._brake_release_to_decision_speed = phase_builder def set_decision_speed_to_rotate(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the short distance between achieving decision speed and beginning the rotation phase. - ''' + """ self._decision_speed_to_rotate = phase_builder def set_rotate_to_liftoff(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the short distance required to rotate the aircraft to achieve liftoff. - ''' + """ self._rotate_to_liftoff = phase_builder def set_liftoff_to_obstacle(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the short period between liftoff and clearing the required obstacle. - ''' + """ self._liftoff_to_obstacle = phase_builder def set_obstacle_to_mic_p2(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the fifth phase of takeoff, from clearing the required obstacle to the p2 mic loation. This phase is required for acoustic calculations. - ''' + """ self._obstacle_to_mic_p2 = phase_builder def set_mic_p2_to_engine_cutback(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the sixth phase of takeoff, from the p2 mic location to engine cutback. This phase is required for acoustic calculations. - ''' + """ self._mic_p2_to_engine_cutback = phase_builder def set_engine_cutback(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the seventh phase of takeoff, from start to finish of engine cutback. This phase is required for acoustic calculations. - ''' + """ self._engine_cutback = phase_builder def set_engine_cutback_to_mic_p1(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the eighth phase of takeoff, engine cutback to the P1 mic location. This phase is required for acoustic calculations. - ''' + """ self._engine_cutback_to_mic_p1 = phase_builder def set_mic_p1_to_climb(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for the ninth phase of takeoff, from P1 mic location to climb. This phase is required for acoustic calculations. - ''' + """ self._mic_p1_to_climb = phase_builder def set_decision_speed_to_brake(self, phase_builder: PhaseBuilderBase): - ''' + """ Assign a phase builder for delayed braking when the engine fails. Note, this phase is optional. It is only required if balanced field length calculations are required. - ''' + """ self._decision_speed_to_brake = phase_builder - def set_brake_to_abort( - self, phase_builder: PhaseBuilderBase, balanced_field_ref=8_000. - ): - ''' + def set_brake_to_abort(self, phase_builder: PhaseBuilderBase, balanced_field_ref=8_000.0): + """ Assign a phase builder for braking to fullstop after engine failure. Note, this phase is optional. It is only required if balanced field length @@ -2360,15 +2943,14 @@ def set_brake_to_abort( continental United States. International travel of similar aircraft may require a larger value, while a smaller aircraft with a shorter range may require a smaller value. - ''' + """ self._brake_to_abort = phase_builder self._balanced_field_ref = balanced_field_ref def build_trajectory( - self, *, aviary_options: AviaryValues, model: om.Group = None, - traj: dm.Trajectory = None + self, *, aviary_options: AviaryValues, model: om.Group = None, traj: dm.Trajectory = None ) -> dm.Trajectory: - ''' + """ Return a new trajectory for detailed takeoff analysis. Call only after assigning phase builders for required phases. @@ -2396,7 +2978,7 @@ def build_trajectory( Do not modify this object or any of its referenced data between the call to `build_trajectory()` and the call to `apply_initial_guesses()`, or the behavior is undefined, no diagnostic required. - ''' + """ if traj is None: traj = dm.Trajectory() @@ -2412,20 +2994,15 @@ def build_trajectory( # We need to create parameters for just the inputs we have. # They mostly come from the low-speed aero subsystem. - aero = CoreAerodynamicsBuilder('core_aerodynamics', - BaseMetaData, - LegacyCode('FLOPS')) + aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, LegacyCode('FLOPS')) - phase_info = {} - phase_info['subsystem_options'] = {} - phase_info['subsystem_options']['core_aerodynamics'] = {} - phase_info['subsystem_options']['core_aerodynamics']['method'] = 'low_speed' + kwargs = {'method': 'low_speed'} - params = aero.get_parameters(aviary_options, phase_info) + params = aero.get_parameters(aviary_options, **kwargs) # takeoff introduces this one. params[Mission.Takeoff.LIFT_COEFFICIENT_MAX] = { - 'shape': (1, ), + 'shape': (1,), 'static_target': True, } @@ -2433,13 +3010,14 @@ def build_trajectory( for phase in self._phases.keys(): ext_params[phase] = params - setup_trajectory_params(model, traj, aviary_options, - phase_names, external_parameters=ext_params) + setup_trajectory_params( + model, traj, aviary_options, phase_names, external_parameters=ext_params + ) return traj def apply_initial_guesses(self, prob: om.Problem, traj_name): - ''' + """ Call `prob.set_val()` for states/parameters/etc. for each phase in this trajectory. @@ -2451,11 +3029,11 @@ def apply_initial_guesses(self, prob: om.Problem, traj_name): for any phase with missing initial guesses that cannot be applied, a list of those missing initial guesses; if a given phase has no missing initial guesses, the returned mapping will not contain the name of that phase - ''' + """ not_applied = {} phase_builder: PhaseBuilderBase = None # type hint - for (phase, phase_builder) in self._phases.values(): + for phase, phase_builder in self._phases.values(): tmp = phase_builder.apply_initial_guesses(prob, traj_name, phase) if tmp: @@ -2466,44 +3044,33 @@ def apply_initial_guesses(self, prob: om.Problem, traj_name): def _add_phases(self, aviary_options: AviaryValues): self._phases = {} - self._add_phase( - self._brake_release_to_decision_speed, aviary_options) + self._add_phase(self._brake_release_to_decision_speed, aviary_options) - self._add_phase( - self._decision_speed_to_rotate, aviary_options) + self._add_phase(self._decision_speed_to_rotate, aviary_options) - self._add_phase( - self._rotate_to_liftoff, aviary_options) + self._add_phase(self._rotate_to_liftoff, aviary_options) - self._add_phase( - self._liftoff_to_obstacle, aviary_options) + self._add_phase(self._liftoff_to_obstacle, aviary_options) obstacle_to_mic_p2 = self._obstacle_to_mic_p2 if obstacle_to_mic_p2 is not None: - self._add_phase( - obstacle_to_mic_p2, aviary_options) + self._add_phase(obstacle_to_mic_p2, aviary_options) - self._add_phase( - self._mic_p2_to_engine_cutback, aviary_options) + self._add_phase(self._mic_p2_to_engine_cutback, aviary_options) - self._add_phase( - self._engine_cutback, aviary_options) + self._add_phase(self._engine_cutback, aviary_options) - self._add_phase( - self._engine_cutback_to_mic_p1, aviary_options) + self._add_phase(self._engine_cutback_to_mic_p1, aviary_options) - self._add_phase( - self._mic_p1_to_climb, aviary_options) + self._add_phase(self._mic_p1_to_climb, aviary_options) decision_speed_to_brake = self._decision_speed_to_brake if decision_speed_to_brake is not None: - self._add_phase( - decision_speed_to_brake, aviary_options) + self._add_phase(decision_speed_to_brake, aviary_options) - self._add_phase( - self._brake_to_abort, aviary_options) + self._add_phase(self._brake_to_abort, aviary_options) def _link_phases(self): traj: dm.Trajectory = self._traj @@ -2536,25 +3103,23 @@ def _link_phases(self): acoustics_vars = ext_vars + [Dynamic.Mission.FLIGHT_PATH_ANGLE, 'altitude'] - traj.link_phases( - [liftoff_name, obstacle_to_mic_p2_name], - vars=acoustics_vars) + traj.link_phases([liftoff_name, obstacle_to_mic_p2_name], vars=acoustics_vars) traj.link_phases( - [obstacle_to_mic_p2_name, mic_p2_to_engine_cutback_name], - vars=acoustics_vars) + [obstacle_to_mic_p2_name, mic_p2_to_engine_cutback_name], vars=acoustics_vars + ) traj.link_phases( - [mic_p2_to_engine_cutback_name, engine_cutback_name], - vars=acoustics_vars) + [mic_p2_to_engine_cutback_name, engine_cutback_name], vars=acoustics_vars + ) traj.link_phases( - [engine_cutback_name, engine_cutback_to_mic_p1_name], - vars=acoustics_vars) + [engine_cutback_name, engine_cutback_to_mic_p1_name], vars=acoustics_vars + ) traj.link_phases( - [engine_cutback_to_mic_p1_name, mic_p1_to_climb_name], - vars=acoustics_vars) + [engine_cutback_to_mic_p1_name, mic_p1_to_climb_name], vars=acoustics_vars + ) decision_speed_to_brake = self._decision_speed_to_brake @@ -2566,9 +3131,14 @@ def _link_phases(self): traj.link_phases([brake_name, abort_name], vars=basic_vars) traj.add_linkage_constraint( - phase_a=abort_name, var_a='distance', loc_a='final', - phase_b=liftoff_name, var_b='distance', loc_b='final', - ref=self._balanced_field_ref) + phase_a=abort_name, + var_a='distance', + loc_a='final', + phase_b=liftoff_name, + var_b='distance', + loc_b='final', + ref=self._balanced_field_ref, + ) def _add_phase(self, phase_builder: PhaseBuilderBase, aviary_options: AviaryValues): name = phase_builder.name diff --git a/aviary/mission/energy_phase.py b/aviary/mission/flops_based/phases/energy_phase.py similarity index 69% rename from aviary/mission/energy_phase.py rename to aviary/mission/flops_based/phases/energy_phase.py index 35a28c1288..ebd9708b92 100644 --- a/aviary/mission/energy_phase.py +++ b/aviary/mission/flops_based/phases/energy_phase.py @@ -1,11 +1,7 @@ -import dymos as dm - from aviary.mission.flight_phase_builder import FlightPhaseBase, register +from aviary.mission.flops_based.ode.energy_ODE import EnergyODE from aviary.mission.initial_guess_builders import InitialGuessIntegrationVariable, InitialGuessState -from aviary.utils.aviary_values import AviaryValues -from aviary.mission.flops_based.ode.mission_ODE import MissionODE - # TODO: support/handle the following in the base class # - phase.set_time_options() @@ -14,14 +10,14 @@ # - self.meta_data, with cls.default_meta_data customization point @register class EnergyPhase(FlightPhaseBase): - - default_ode_class = MissionODE + default_ode_class = EnergyODE EnergyPhase._add_initial_guess_meta_data( InitialGuessIntegrationVariable(), - desc='initial guess for initial time and duration specified as a tuple') + desc='initial guess for initial time and duration specified as a tuple', +) EnergyPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for horizontal distance traveled') + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled' +) diff --git a/aviary/mission/flops_based/phases/groundroll_phase.py b/aviary/mission/flops_based/phases/groundroll_phase.py index f779ab9a5d..2a4304d50e 100644 --- a/aviary/mission/flops_based/phases/groundroll_phase.py +++ b/aviary/mission/flops_based/phases/groundroll_phase.py @@ -1,59 +1,86 @@ import dymos as dm +from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE +from aviary.mission.initial_guess_builders import ( + InitialGuessIntegrationVariable, + InitialGuessPolynomialControl, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase, register -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessPolynomialControl - +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Dynamic -from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE - +# Solved 2DOF uses this builder. +# # TODO: support/handle the following in the base class # - phase.set_time_options() # - currently handled in level 3 interface implementation -# - self.external_subsystems # - self.meta_data, with cls.default_meta_data customization point -@register -class GroundrollPhase(PhaseBuilderBase): - ''' - A phase builder for a two degree of freedom (2DOF) phase. - ''' - __slots__ = ('external_subsystems', 'meta_data') - # region : derived type customization points - _meta_data_ = {} - _initial_guesses_meta_data_ = {} +class GroundrollPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=5, + desc='The number of segments in transcription creation in Dymos. ' + 'The default value is 5.', + ) + + self.declare( + name='order', + types=int, + default=3, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos. The default value is 3.', + ) + + defaults = { + 'time_initial_bounds': (0.0, 100.0), + 'time_duration_bounds': (0.0, 3600.0), + 'time_initial_ref': 100.0, + 'time_duration_ref': 100.0, + } + self.add_time_options(units='kn', defaults=defaults) - default_name = 'groundroll' + # The options below have not yet been revamped. - default_ode_class = GroundrollODE + self.declare( + name='constraints', + types=dict, + default={}, + desc="Add in custom constraints i.e. 'flight_path_angle': {'equals': -3., " + "'loc': 'initial', 'units': 'deg', 'type': 'boundary',}. For more details see " + '_add_user_defined_constraints().', + ) - default_meta_data = _MetaData - # endregion : derived type customization points + self.declare( + name='ground_roll', + types=bool, + default=False, + desc='Set to True only for phases where the aircraft is rolling on the ground. ' + 'All other phases of flight (climb, cruise, descent) this must be set to False.', + ) - def __init__( - self, name=None, subsystem_options=None, user_options=None, initial_guesses=None, - ode_class=None, transcription=None, core_subsystems=None, - external_subsystems=None, meta_data=None - ): - super().__init__( - name=name, core_subsystems=core_subsystems, subsystem_options=subsystem_options, user_options=user_options, initial_guesses=initial_guesses, ode_class=ode_class, transcription=transcription) - # TODO: support external_subsystems and meta_data in the base class - if external_subsystems is None: - external_subsystems = [] +@register +class GroundrollPhase(PhaseBuilderBase): + """A phase builder for a two degree of freedom (2DOF) phase.""" - self.external_subsystems = external_subsystems + __slots__ = ('external_subsystems', 'meta_data') - if meta_data is None: - meta_data = self.default_meta_data + _initial_guesses_meta_data_ = {} - self.meta_data = meta_data + default_name = 'groundroll' + default_ode_class = GroundrollODE + default_options_class = GroundrollPhaseOptions + default_meta_data = _MetaData def build_phase(self, aviary_options: AviaryValues = None): - ''' + """ Return a new 2dof phase for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -69,75 +96,95 @@ def build_phase(self, aviary_options: AviaryValues = None): Returns ------- dymos.Phase - ''' + """ phase: dm.Phase = super().build_phase(aviary_options) user_options: AviaryValues = self.user_options - duration_bounds = user_options.get_val('duration_bounds', units='kn') - duration_ref = user_options.get_val('duration_ref', units='kn') + duration_bounds = user_options.get_val('time_duration_bounds', units='kn') + duration_ref = user_options.get_val('time_duration_ref', units='kn') constraints = user_options.get_val('constraints') - phase.set_time_options(fix_initial=True, fix_duration=False, - units="kn", name=Dynamic.Mission.VELOCITY, - duration_bounds=duration_bounds, duration_ref=duration_ref) - - phase.set_state_options("time", rate_source="dt_dv", units="s", - fix_initial=True, fix_final=False, ref=1., defect_ref=1., solve_segments='forward') - - phase.set_state_options("mass", rate_source="dmass_dv", - fix_initial=True, fix_final=False, lower=1, upper=500.e3, ref=100.e3, defect_ref=100.e3, units='lbm') - - phase.set_state_options(Dynamic.Mission.DISTANCE, rate_source="over_a", - fix_initial=True, fix_final=False, lower=0, upper=8000., ref=1.e2, defect_ref=1.e2, units='ft') - - phase.add_parameter("t_init_gear", units="s", - static_target=True, opt=False, val=32.3) - phase.add_parameter("t_init_flaps", units="s", - static_target=True, opt=False, val=44.0) - phase.add_parameter("wing_area", units="ft**2", - static_target=True, opt=False, val=1370) + phase.set_time_options( + fix_initial=True, + fix_duration=False, + units='kn', + name=Dynamic.Mission.VELOCITY, + duration_bounds=duration_bounds, + duration_ref=duration_ref, + ) + + phase.set_state_options( + 'time', + rate_source='dt_dv', + units='s', + fix_initial=True, + fix_final=False, + ref=1.0, + defect_ref=1.0, + solve_segments='forward', + ) + + phase.set_state_options( + 'mass', + rate_source='dmass_dv', + fix_initial=True, + fix_final=False, + lower=1, + upper=500.0e3, + ref=100.0e3, + defect_ref=100.0e3, + units='lbm', + ) + + phase.set_state_options( + Dynamic.Mission.DISTANCE, + rate_source='over_a', + fix_initial=True, + fix_final=False, + lower=0, + upper=8000.0, + ref=1.0e2, + defect_ref=1.0e2, + units='ft', + ) + + phase.add_parameter('t_init_gear', units='s', static_target=True, opt=False, val=32.3) + phase.add_parameter('t_init_flaps', units='s', static_target=True, opt=False, val=44.0) + phase.add_parameter('wing_area', units='ft**2', static_target=True, opt=False, val=1370) self._add_user_defined_constraints(phase, constraints) - phase.add_timeseries_output(Dynamic.Mission.THRUST_TOTAL, units="lbf") - phase.add_timeseries_output("thrust_req", units="lbf") - phase.add_timeseries_output("normal_force") - phase.add_timeseries_output(Dynamic.Mission.MACH) - phase.add_timeseries_output("EAS", units="kn") - phase.add_timeseries_output(Dynamic.Mission.VELOCITY, units="kn") - phase.add_timeseries_output(Dynamic.Mission.LIFT) - phase.add_timeseries_output(Dynamic.Mission.DRAG) - phase.add_timeseries_output("time") - phase.add_timeseries_output("mass") - phase.add_timeseries_output(Dynamic.Mission.ALTITUDE) - phase.add_timeseries_output("alpha") - phase.add_timeseries_output(Dynamic.Mission.FLIGHT_PATH_ANGLE) - phase.add_timeseries_output(Dynamic.Mission.THROTTLE) + phase.add_timeseries_output(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, units='lbf') + phase.add_timeseries_output('normal_force') + phase.add_timeseries_output(Dynamic.Atmosphere.MACH) + phase.add_timeseries_output('EAS', units='kn') + phase.add_timeseries_output(Dynamic.Mission.VELOCITY, units='kn') + phase.add_timeseries_output(Dynamic.Vehicle.LIFT) + phase.add_timeseries_output(Dynamic.Vehicle.DRAG) + phase.add_timeseries_output('time') + phase.add_timeseries_output('mass') + phase.add_timeseries_output(Dynamic.Vehicle.ANGLE_OF_ATTACK) return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" user_options = self.user_options - num_segments, _ = user_options.get_item('num_segments') - order, _ = user_options.get_item('order') + num_segments = user_options['num_segments'] + order = user_options['order'] seg_ends, _ = dm.utils.lgl.lgl(num_segments + 1) transcription = dm.Radau( - num_segments=num_segments, order=order, compressed=True, - segment_ends=seg_ends) + num_segments=num_segments, order=order, compressed=True, segment_ends=seg_ends + ) return transcription def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ + """Return extra kwargs required for initializing the ODE.""" # TODO: support external_subsystems and meta_data in the base class return { 'external_subsystems': self.external_subsystems, @@ -147,54 +194,23 @@ def _extra_ode_init_kwargs(self): } -GroundrollPhase._add_meta_data( - 'num_segments', val=5, desc='transcription: number of segments') - -GroundrollPhase._add_meta_data( - 'order', val=3, - desc='transcription: order of the state transcription; the order of the control' - ' transcription is `order - 1`') - -GroundrollPhase._add_meta_data('fix_initial', val=False) - -GroundrollPhase._add_meta_data('fix_duration', val=False) - -GroundrollPhase._add_meta_data('optimize_mach', val=False) - -GroundrollPhase._add_meta_data('optimize_altitude', val=False) - -GroundrollPhase._add_meta_data('initial_bounds', val=(0., 100.), - units='s', desc='initial bounds') -GroundrollPhase._add_meta_data('duration_bounds', val=( - 0., 3600.), units='s', desc='duration bounds') -GroundrollPhase._add_meta_data('initial_ref', val=100., - units='s', desc='initial reference') -GroundrollPhase._add_meta_data('duration_ref', val=1000., - units='s', desc='duration reference') -GroundrollPhase._add_meta_data('control_order', val=1, desc='control order') -GroundrollPhase._add_meta_data('opt', val=True, desc='opt') -GroundrollPhase._add_meta_data('input_speed_type', val='TAS', desc='input speed type') -GroundrollPhase._add_meta_data('ground_roll', val=True) -GroundrollPhase._add_meta_data('rotation', val=False) -GroundrollPhase._add_meta_data('clean', val=False) -GroundrollPhase._add_meta_data('constraints', val={}) - GroundrollPhase._add_initial_guess_meta_data( InitialGuessIntegrationVariable(key='velocity'), - desc='initial guess for initial velocity and final specified as a tuple') + desc='initial guess for initial velocity and final specified as a tuple', +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessPolynomialControl('altitude'), - desc='initial guess for vertical distances') + InitialGuessPolynomialControl('altitude'), desc='initial guess for vertical distances' +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') + InitialGuessState('mass'), desc='initial guess for mass' +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for distance') + InitialGuessState('distance'), desc='initial guess for distance' +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessState('time'), - desc='initial guess for time') + InitialGuessState('time'), desc='initial guess for time' +) diff --git a/aviary/mission/flops_based/phases/phase_utils.py b/aviary/mission/flops_based/phases/phase_utils.py index 1dd4b27fc0..104bed0280 100644 --- a/aviary/mission/flops_based/phases/phase_utils.py +++ b/aviary/mission/flops_based/phases/phase_utils.py @@ -21,10 +21,8 @@ def add_subsystem_variables_to_phase(phase, phase_name, external_subsystems): The modified phase object with added variables. """ - # Loop through each subsystem in the list of external_subsystems for subsystem in external_subsystems: - # Fetch the states from the current subsystem subsystem_states = subsystem.get_states() @@ -48,14 +46,14 @@ def add_subsystem_variables_to_phase(phase, phase_name, external_subsystems): # Add each constraint and its corresponding arguments to the phase for constraint_name in constraints: - kwargs = constraints[constraint_name] - if kwargs['type'] == 'boundary': - kwargs.pop('type') - phase.add_boundary_constraint(constraint_name, **kwargs) - elif kwargs['type'] == 'path': - kwargs.pop('type') - phase.add_path_constraint(constraint_name, **kwargs) - + con_args = constraints[constraint_name].copy() + con_type = con_args.pop('type') + if con_type == 'boundary': + phase.add_boundary_constraint(constraint_name, **con_args) + elif con_type == 'path': + phase.add_path_constraint(constraint_name, **con_args) + else: + raise ValueError(f'Invalid type "{con_type}" in builder for {subsystem.pathname}.') return phase diff --git a/aviary/mission/flops_based/phases/simplified_landing.py b/aviary/mission/flops_based/phases/simplified_landing.py index 2fc6dddcb6..6397e53694 100644 --- a/aviary/mission/flops_based/phases/simplified_landing.py +++ b/aviary/mission/flops_based/phases/simplified_landing.py @@ -1,26 +1,23 @@ import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_METRIC +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission, Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic, Mission class LandingCalc(om.ExplicitComponent): - """ - Calculate the distance covered over the ground and approach velocity during landing - """ + """Calculate the distance covered over the ground and approach velocity during landing.""" def setup(self): - add_aviary_input(self, Mission.Landing.TOUCHDOWN_MASS, val=150_000) add_aviary_input( self, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=1.225, - units="kg/m**3", - desc="atmospheric density", + units='kg/m**3', + desc='atmospheric density', ) add_aviary_input(self, Aircraft.Wing.AREA, val=700) @@ -31,16 +28,20 @@ def setup(self): add_aviary_output(self, Mission.Landing.INITIAL_VELOCITY, val=0) - self.declare_partials(Mission.Landing.INITIAL_VELOCITY, [ - Mission.Landing.LIFT_COEFFICIENT_MAX, Aircraft.Wing.AREA, Mission.Landing.TOUCHDOWN_MASS]) - self.declare_partials(Mission.Landing.GROUND_DISTANCE, "*") + self.declare_partials( + Mission.Landing.INITIAL_VELOCITY, + [ + Mission.Landing.LIFT_COEFFICIENT_MAX, + Aircraft.Wing.AREA, + Mission.Landing.TOUCHDOWN_MASS, + ], + ) + self.declare_partials(Mission.Landing.GROUND_DISTANCE, '*') def compute(self, inputs, outputs): - rho_SL = RHO_SEA_LEVEL_METRIC - landing_weight = inputs[Mission.Landing.TOUCHDOWN_MASS] * \ - GRAV_ENGLISH_LBM - rho = inputs[Dynamic.Mission.DENSITY] + landing_weight = inputs[Mission.Landing.TOUCHDOWN_MASS] * GRAV_ENGLISH_LBM + rho = inputs[Dynamic.Atmosphere.DENSITY] planform_area = inputs[Aircraft.Wing.AREA] Cl_ldg_max = inputs[Mission.Landing.LIFT_COEFFICIENT_MAX] @@ -49,68 +50,58 @@ def compute(self, inputs, outputs): # TODO: This equation from FLOPS estimates the landing field length, not the actual ground # distance covered during landing, which should be less. - Cl_app = Cl_ldg_max / 1.3 ** 2 + Cl_app = Cl_ldg_max / 1.3**2 V_app = 17.18644 * (landing_weight / (planform_area * Cl_app)) ** 0.5 - landing_distance = 2500 + 105 * landing_weight / ( - planform_area * rho_ratio * Cl_app * 1.69 - ) + landing_distance = 2500 + 105 * landing_weight / (planform_area * rho_ratio * Cl_app * 1.69) outputs[Mission.Landing.GROUND_DISTANCE] = landing_distance outputs[Mission.Landing.INITIAL_VELOCITY] = V_app def compute_partials(self, inputs, J): - rho_SL = RHO_SEA_LEVEL_METRIC - landing_weight = inputs[Mission.Landing.TOUCHDOWN_MASS] * \ - GRAV_ENGLISH_LBM - rho = inputs[Dynamic.Mission.DENSITY] + landing_weight = inputs[Mission.Landing.TOUCHDOWN_MASS] * GRAV_ENGLISH_LBM + rho = inputs[Dynamic.Atmosphere.DENSITY] planform_area = inputs[Aircraft.Wing.AREA] Cl_ldg_max = inputs[Mission.Landing.LIFT_COEFFICIENT_MAX] rho_ratio = rho / rho_SL - Cl_app = Cl_ldg_max / 1.3 ** 2 + Cl_app = Cl_ldg_max / 1.3**2 J[Mission.Landing.INITIAL_VELOCITY, Mission.Landing.LIFT_COEFFICIENT_MAX] = ( 17.18644 * 0.5 * (landing_weight / (planform_area * Cl_app)) ** (-0.5) * (-landing_weight) - / (planform_area * Cl_app ** 2) - / 1.3 ** 2 + / (planform_area * Cl_app**2) + / 1.3**2 ) J[Mission.Landing.INITIAL_VELOCITY, Aircraft.Wing.AREA] = ( 17.18644 * 0.5 * (landing_weight / (planform_area * Cl_app)) ** (-0.5) * (-landing_weight) - / (planform_area ** 2 * Cl_app) + / (planform_area**2 * Cl_app) ) J[Mission.Landing.INITIAL_VELOCITY, Mission.Landing.TOUCHDOWN_MASS] = ( 17.18644 * 0.5 * (landing_weight / (planform_area * Cl_app)) ** (-0.5) - * GRAV_ENGLISH_LBM / (planform_area * Cl_app) + * GRAV_ENGLISH_LBM + / (planform_area * Cl_app) ) - J[Mission.Landing.GROUND_DISTANCE, Mission.Landing.TOUCHDOWN_MASS] = \ - 105 * GRAV_ENGLISH_LBM / ( - planform_area * rho_ratio * Cl_app * 1.69 + J[Mission.Landing.GROUND_DISTANCE, Mission.Landing.TOUCHDOWN_MASS] = ( + 105 * GRAV_ENGLISH_LBM / (planform_area * rho_ratio * Cl_app * 1.69) ) J[Mission.Landing.GROUND_DISTANCE, Aircraft.Wing.AREA] = ( - -105 * landing_weight / (planform_area ** 2 * rho_ratio * Cl_app * 1.69) + -105 * landing_weight / (planform_area**2 * rho_ratio * Cl_app * 1.69) ) J[Mission.Landing.GROUND_DISTANCE, Mission.Landing.LIFT_COEFFICIENT_MAX] = ( - -105 - * landing_weight - / (planform_area * rho_ratio * Cl_app ** 2 * 1.69) - / 1.3 ** 2 + -105 * landing_weight / (planform_area * rho_ratio * Cl_app**2 * 1.69) / 1.3**2 ) - J[Mission.Landing.GROUND_DISTANCE, Dynamic.Mission.DENSITY] = ( - -105 - * landing_weight - / (planform_area * rho_ratio**2 * Cl_app * 1.69) - / rho_SL + J[Mission.Landing.GROUND_DISTANCE, Dynamic.Atmosphere.DENSITY] = ( + -105 * landing_weight / (planform_area * rho_ratio**2 * Cl_app * 1.69) / rho_SL ) @@ -121,7 +112,6 @@ class LandingGroup(om.Group): """ def setup(self): - self.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=1), @@ -132,11 +122,11 @@ def setup(self): ) self.add_subsystem( - "calcs", + 'calcs', LandingCalc(), promotes_inputs=[ Mission.Landing.TOUCHDOWN_MASS, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, Aircraft.Wing.AREA, Mission.Landing.LIFT_COEFFICIENT_MAX, ], diff --git a/aviary/mission/flops_based/phases/simplified_takeoff.py b/aviary/mission/flops_based/phases/simplified_takeoff.py index 3f7ef9d31f..a91edecd73 100644 --- a/aviary/mission/flops_based/phases/simplified_takeoff.py +++ b/aviary/mission/flops_based/phases/simplified_takeoff.py @@ -1,7 +1,7 @@ import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_METRIC +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -9,80 +9,76 @@ class StallSpeed(om.ExplicitComponent): """ Calculates the stall speed of the aircraft using - v_stall = (2 * weight / (density * planform_area * Cl_max)) ** 0.5 + v_stall = (2 * weight / (density * planform_area * Cl_max)) ** 0.5. """ def setup(self): - """ - Setup the inputs and output to calculate the stall speed of the aircraft. - """ - + """Setup the inputs and output to calculate the stall speed of the aircraft.""" self.add_input( - "mass", + 'mass', val=150_000, - units="lbm", - desc="mass of the aircraft", + units='lbm', + desc='mass of the aircraft', ) self.add_input( - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=1.225, - units="kg/m**3", - desc="atmospheric density", + units='kg/m**3', + desc='atmospheric density', ) - self.add_input("planform_area", val=7, units="m**2", desc="area of the wings") + self.add_input('planform_area', val=7, units='m**2', desc='area of the wings') self.add_input( - "Cl_max", + 'Cl_max', val=2, units='unitless', - desc="maximum lift coefficient", + desc='maximum lift coefficient', ) self.add_output( - "v_stall", + 'v_stall', val=0.1, - units="m/s", - desc="stall velocity", + units='m/s', + desc='stall velocity', ) - self.declare_partials("v_stall", "*") + self.declare_partials('v_stall', '*') def compute(self, inputs, outputs): - - weight = inputs["mass"] * GRAV_ENGLISH_LBM + weight = inputs['mass'] * GRAV_ENGLISH_LBM # # convert from pounds to newtons. # This is only necessary because the equation expects newtons, # but the mission expects pounds mass instead of pounds force. - weight = weight*4.44822 - rho = inputs[Dynamic.Mission.DENSITY] - S = inputs["planform_area"] - Cl_max = inputs["Cl_max"] + weight = weight * 4.44822 + rho = inputs[Dynamic.Atmosphere.DENSITY] + S = inputs['planform_area'] + Cl_max = inputs['Cl_max'] v_stall = (2 * weight / (rho * S * Cl_max)) ** 0.5 - outputs["v_stall"] = v_stall + outputs['v_stall'] = v_stall def compute_partials(self, inputs, J): - - weight = inputs["mass"] * GRAV_ENGLISH_LBM - rho = inputs[Dynamic.Mission.DENSITY] - S = inputs["planform_area"] - Cl_max = inputs["Cl_max"] + weight = inputs['mass'] * GRAV_ENGLISH_LBM + rho = inputs[Dynamic.Atmosphere.DENSITY] + S = inputs['planform_area'] + Cl_max = inputs['Cl_max'] rad = 2 * weight / (rho * S * Cl_max) - J["v_stall", "mass"] = 0.5 * 4.44822**.5 * \ - rad ** (-0.5) * 2 * GRAV_ENGLISH_LBM / (rho * S * Cl_max) - J["v_stall", Dynamic.Mission.DENSITY] = ( + J['v_stall', 'mass'] = ( + 0.5 * 4.44822**0.5 * rad ** (-0.5) * 2 * GRAV_ENGLISH_LBM / (rho * S * Cl_max) + ) + J['v_stall', Dynamic.Atmosphere.DENSITY] = ( 0.5 * 4.44822**0.5 * rad ** (-0.5) * (-2 * weight) / (rho**2 * S * Cl_max) ) - J["v_stall", "planform_area"] = ( - 0.5 * 4.44822**.5 * rad ** (-0.5) * (-2 * weight) / (rho * S ** 2 * Cl_max) + J['v_stall', 'planform_area'] = ( + 0.5 * 4.44822**0.5 * rad ** (-0.5) * (-2 * weight) / (rho * S**2 * Cl_max) ) - J["v_stall", "Cl_max"] = ( - 0.5 * 4.44822**.5 * rad ** (-0.5) * (-2 * weight) / (rho * S * Cl_max ** 2) + J['v_stall', 'Cl_max'] = ( + 0.5 * 4.44822**0.5 * rad ** (-0.5) * (-2 * weight) / (rho * S * Cl_max**2) ) @@ -93,26 +89,25 @@ class FinalTakeoffConditions(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_engines", desc="number of engines on aircraft") + self.options.declare('num_engines', desc='number of engines on aircraft') def setup(self): - self.add_input( - "v_stall", + 'v_stall', val=0.1, - units="m/s", - desc="stall speed of the aircraft", + units='m/s', + desc='stall speed of the aircraft', ) add_aviary_input(self, Mission.Summary.GROSS_MASS, val=150_000) - add_aviary_input(self, Mission.Takeoff.FUEL_SIMPLE, val=10.e3) + add_aviary_input(self, Mission.Takeoff.FUEL_SIMPLE, val=10.0e3) self.add_input( - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=1.225, - units="kg/m**3", - desc="atmospheric density", + units='kg/m**3', + desc='atmospheric density', ) add_aviary_input(self, Aircraft.Wing.AREA, val=7) @@ -125,25 +120,23 @@ def setup(self): add_aviary_output(self, Mission.Takeoff.GROUND_DISTANCE, val=0) - add_aviary_output(self, Mission.Takeoff.FINAL_VELOCITY, - val=0, units="m/s") + add_aviary_output(self, Mission.Takeoff.FINAL_VELOCITY, val=0, units='m/s') add_aviary_output(self, Mission.Takeoff.FINAL_MASS, val=0) add_aviary_output(self, Mission.Takeoff.FINAL_ALTITUDE, val=0) def setup_partials(self): - self.declare_partials( Mission.Takeoff.FINAL_VELOCITY, - "v_stall", + 'v_stall', val=1.2309, ) self.declare_partials( Mission.Takeoff.GROUND_DISTANCE, [ Mission.Summary.GROSS_MASS, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, Aircraft.Wing.AREA, Mission.Takeoff.LIFT_COEFFICIENT_MAX, Mission.Design.THRUST_TAKEOFF_PER_ENG, @@ -162,13 +155,12 @@ def setup_partials(self): ) def compute(self, inputs, outputs): - rho_SL = RHO_SEA_LEVEL_METRIC - v_stall = inputs["v_stall"] + v_stall = inputs['v_stall'] gross_mass = inputs[Mission.Summary.GROSS_MASS] ramp_weight = gross_mass * GRAV_ENGLISH_LBM - rho = inputs[Dynamic.Mission.DENSITY] + rho = inputs[Dynamic.Atmosphere.DENSITY] S = inputs[Aircraft.Wing.AREA] Cl_max = inputs[Mission.Takeoff.LIFT_COEFFICIENT_MAX] thrust = inputs[Mission.Design.THRUST_TAKEOFF_PER_ENG] @@ -198,29 +190,25 @@ def compute(self, inputs, outputs): climbout_distance = ( 140.0 * (ramp_weight / S) ** 0.5 - / ( - 1.0 - + thrust * num_engines / ramp_weight - - 0.90 / L_over_D - ) + / (1.0 + thrust * num_engines / ramp_weight - 0.90 / L_over_D) ) # The FLOPS methodology does not calculate V2. However, it assumes CL @ V2 = 0.66 * CL_max. # Therefore, V2 = V_stall / sqrt(0.66). V2 = v_stall * 1.2309 - outputs[Mission.Takeoff.GROUND_DISTANCE] = rolling_distance + \ - rotation_distance + climbout_distance + outputs[Mission.Takeoff.GROUND_DISTANCE] = ( + rolling_distance + rotation_distance + climbout_distance + ) outputs[Mission.Takeoff.FINAL_VELOCITY] = V2 - outputs[Mission.Takeoff.FINAL_MASS] = \ - gross_mass - inputs[Mission.Takeoff.FUEL_SIMPLE] + outputs[Mission.Takeoff.FINAL_MASS] = gross_mass - inputs[Mission.Takeoff.FUEL_SIMPLE] outputs[Mission.Takeoff.FINAL_ALTITUDE] = 35 def compute_partials(self, inputs, J): rho_SL = RHO_SEA_LEVEL_METRIC ramp_weight = inputs[Mission.Summary.GROSS_MASS] * GRAV_ENGLISH_LBM - rho = inputs[Dynamic.Mission.DENSITY] + rho = inputs[Dynamic.Atmosphere.DENSITY] S = inputs[Aircraft.Wing.AREA] Cl_max = inputs[Mission.Takeoff.LIFT_COEFFICIENT_MAX] thrust = inputs[Mission.Design.THRUST_TAKEOFF_PER_ENG] @@ -231,47 +219,40 @@ def compute_partials(self, inputs, J): den_RD = ( S * Cl_max - * ( - thrust * num_engines / ramp_weight - - (0.20 + 0.00550 * ramp_weight / S) / L_over_D - ) + * (thrust * num_engines / ramp_weight - (0.20 + 0.00550 * ramp_weight / S) / L_over_D) ) rad_Rot = ramp_weight / (S * Cl_max * rho_ratio) - den_Cout = ( - 1.0 + thrust * num_engines / ramp_weight - 0.90 / L_over_D - ) + den_Cout = 1.0 + thrust * num_engines / ramp_weight - 0.90 / L_over_D S * Cl_max * ( - thrust * num_engines / ramp_weight - - (0.20 + 0.00550 * ramp_weight / S) / L_over_D - ) - S * Cl_max * ( - -thrust * num_engines / ramp_weight ** 2 - - (0.00550 / S) / L_over_D + thrust * num_engines / ramp_weight - (0.20 + 0.00550 * ramp_weight / S) / L_over_D ) + S * Cl_max * (-thrust * num_engines / ramp_weight**2 - (0.00550 / S) / L_over_D) # dRD_dWt = (den_RD*17 - 17*ramp_weight*S*Cl_max*(-thrust*num_engines/ramp_weight**2 - (.00550/S)/L_over_D))/den_RD**2 - dRD_dM = (17 / den_RD - 17 * ramp_weight / den_RD ** 2 * S * Cl_max * ( - -thrust * num_engines / ramp_weight ** 2 - - (0.00550 / S) / L_over_D - )) * GRAV_ENGLISH_LBM + dRD_dM = ( + 17 / den_RD + - 17 + * ramp_weight + / den_RD**2 + * S + * Cl_max + * (-thrust * num_engines / ramp_weight**2 - (0.00550 / S) / L_over_D) + ) * GRAV_ENGLISH_LBM dRD_dS = ( den_RD * 0 - 17 * ramp_weight * ( Cl_max - * ( - thrust * num_engines / ramp_weight - - (0.2 + 0.0055 * ramp_weight / S) / L_over_D - ) - + S * Cl_max * (0.0055 * ramp_weight / S ** 2 / L_over_D) + * (thrust * num_engines / ramp_weight - (0.2 + 0.0055 * ramp_weight / S) / L_over_D) + + S * Cl_max * (0.0055 * ramp_weight / S**2 / L_over_D) ) - ) / den_RD ** 2 + ) / den_RD**2 dRD_dClMax = ( -17 * ramp_weight - / den_RD ** 2 + / den_RD**2 * ( S * ( @@ -286,10 +267,7 @@ def compute_partials(self, inputs, J): / ( S * Cl_max - * ( - thrust * num_engines / ramp_weight - - (0.2 + 0.0055 * ramp_weight / S) / L_over_D - ) + * (thrust * num_engines / ramp_weight - (0.2 + 0.0055 * ramp_weight / S) / L_over_D) ) ** 2 * S @@ -303,118 +281,85 @@ def compute_partials(self, inputs, J): / ( S * Cl_max - * ( - thrust * num_engines / ramp_weight - - (0.2 + 0.0055 * ramp_weight / S) / L_over_D - ) + * (thrust * num_engines / ramp_weight - (0.2 + 0.0055 * ramp_weight / S) / L_over_D) ) ** 2 * S * Cl_max * (0.2 + 0.0055 * ramp_weight / S) - / L_over_D ** 2 + / L_over_D**2 ) dRD_dRho = 0 - dRot_dM = 140 * 0.5 * \ - rad_Rot ** (-0.5) / (S * Cl_max * rho_ratio) * GRAV_ENGLISH_LBM - dRot_dS = ( - 140 - * 0.5 - * rad_Rot ** (-0.5) - * (-ramp_weight / (S ** 2 * Cl_max * rho_ratio)) - ) - dRot_dClMax = ( - 140 - * 0.5 - * rad_Rot ** (-0.5) - * (-ramp_weight / (S * Cl_max ** 2 * rho_ratio)) - ) + dRot_dM = 140 * 0.5 * rad_Rot ** (-0.5) / (S * Cl_max * rho_ratio) * GRAV_ENGLISH_LBM + dRot_dS = 140 * 0.5 * rad_Rot ** (-0.5) * (-ramp_weight / (S**2 * Cl_max * rho_ratio)) + dRot_dClMax = 140 * 0.5 * rad_Rot ** (-0.5) * (-ramp_weight / (S * Cl_max**2 * rho_ratio)) dRot_dThrust = 0 dRot_dLoD = 0 - dRot_dRho = ( - 140 - * 0.5 - * rad_Rot ** (-0.5) - * (-ramp_weight / (S * Cl_max * rho ** 2 / rho_SL)) - ) + dRot_dRho = 140 * 0.5 * rad_Rot ** (-0.5) * (-ramp_weight / (S * Cl_max * rho**2 / rho_SL)) - dCout_dM = (140 * 0.5 * (ramp_weight / S) ** (-0.5) / S / den_Cout - 140 * ( - ramp_weight / S - ) ** 0.5 / (den_Cout) ** 2 * ( - -thrust * num_engines / ramp_weight ** 2 - )) * GRAV_ENGLISH_LBM - dCout_dS = ( - 140 * 0.5 * (ramp_weight / S) ** (-0.5) * (-ramp_weight) / S ** 2 / den_Cout - ) - dCout_dClMax = 0 - dCout_dThrust = ( - -140 + dCout_dM = ( + 140 * 0.5 * (ramp_weight / S) ** (-0.5) / S / den_Cout + - 140 * (ramp_weight / S) ** 0.5 - / den_Cout ** 2 - * num_engines - / ramp_weight - ) - dCout_dLoD = ( - -140 * (ramp_weight / S) ** 0.5 / den_Cout ** 2 * 0.9 / L_over_D ** 2 - ) + / (den_Cout) ** 2 + * (-thrust * num_engines / ramp_weight**2) + ) * GRAV_ENGLISH_LBM + dCout_dS = 140 * 0.5 * (ramp_weight / S) ** (-0.5) * (-ramp_weight) / S**2 / den_Cout + dCout_dClMax = 0 + dCout_dThrust = -140 * (ramp_weight / S) ** 0.5 / den_Cout**2 * num_engines / ramp_weight + dCout_dLoD = -140 * (ramp_weight / S) ** 0.5 / den_Cout**2 * 0.9 / L_over_D**2 dCout_dRho = 0 - J[Mission.Takeoff.GROUND_DISTANCE, - Mission.Summary.GROSS_MASS] = dRD_dM + dRot_dM + dCout_dM - J[Mission.Takeoff.GROUND_DISTANCE, Dynamic.Mission.DENSITY] = ( + J[Mission.Takeoff.GROUND_DISTANCE, Mission.Summary.GROSS_MASS] = dRD_dM + dRot_dM + dCout_dM + J[Mission.Takeoff.GROUND_DISTANCE, Dynamic.Atmosphere.DENSITY] = ( dRD_dRho + dRot_dRho + dCout_dRho ) - J[Mission.Takeoff.GROUND_DISTANCE, - Aircraft.Wing.AREA] = dRD_dS + dRot_dS + dCout_dS - J[ - Mission.Takeoff.GROUND_DISTANCE, - Mission.Takeoff.LIFT_COEFFICIENT_MAX - ] = dRD_dClMax + dRot_dClMax + dCout_dClMax - J[ - Mission.Takeoff.GROUND_DISTANCE, - Mission.Design.THRUST_TAKEOFF_PER_ENG - ] = dRD_dThrust + dRot_dThrust + dCout_dThrust - J[Mission.Takeoff.GROUND_DISTANCE, - Mission.Takeoff.LIFT_OVER_DRAG] = dRD_dLoD + dRot_dLoD + dCout_dLoD + J[Mission.Takeoff.GROUND_DISTANCE, Aircraft.Wing.AREA] = dRD_dS + dRot_dS + dCout_dS + J[Mission.Takeoff.GROUND_DISTANCE, Mission.Takeoff.LIFT_COEFFICIENT_MAX] = ( + dRD_dClMax + dRot_dClMax + dCout_dClMax + ) + J[Mission.Takeoff.GROUND_DISTANCE, Mission.Design.THRUST_TAKEOFF_PER_ENG] = ( + dRD_dThrust + dRot_dThrust + dCout_dThrust + ) + J[Mission.Takeoff.GROUND_DISTANCE, Mission.Takeoff.LIFT_OVER_DRAG] = ( + dRD_dLoD + dRot_dLoD + dCout_dLoD + ) class TakeoffGroup(om.Group): """ Calculate the final takeoff condition including ground distance, final velocity, - final mass, and final altitude with atmosphere is included. + final mass, and final altitude with atmosphere is included. """ def initialize(self): - self.options.declare("num_engines", desc="number of engines on aircraft") + self.options.declare('num_engines', desc='number of engines on aircraft') def setup(self): + self.add_subsystem(name='atmosphere', subsys=Atmosphere(num_nodes=1), promotes=['*']) self.add_subsystem( - name='atmosphere', subsys=Atmosphere(num_nodes=1), promotes=['*'] - ) - - self.add_subsystem( - "stall_speed", + 'stall_speed', StallSpeed(), promotes_outputs=[ - "v_stall", + 'v_stall', ], promotes_inputs=[ - ("mass", Mission.Summary.GROSS_MASS), - Dynamic.Mission.DENSITY, + ('mass', Mission.Summary.GROSS_MASS), + Dynamic.Atmosphere.DENSITY, ('planform_area', Aircraft.Wing.AREA), - ("Cl_max", Mission.Takeoff.LIFT_COEFFICIENT_MAX), + ('Cl_max', Mission.Takeoff.LIFT_COEFFICIENT_MAX), ], ) self.add_subsystem( - "final_conditions", - FinalTakeoffConditions(num_engines=self.options["num_engines"]), + 'final_conditions', + FinalTakeoffConditions(num_engines=self.options['num_engines']), promotes_inputs=[ - "v_stall", + 'v_stall', Mission.Summary.GROSS_MASS, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, Aircraft.Wing.AREA, Mission.Takeoff.FUEL_SIMPLE, Mission.Takeoff.LIFT_COEFFICIENT_MAX, @@ -429,10 +374,17 @@ def setup(self): ], ) - self.add_subsystem('compute_mach', om.ExecComp('final_mach = final_velocity / speed_of_sound', - final_mach={'units': 'unitless'}, - final_velocity={'units': 'm/s'}, - speed_of_sound={'units': 'm/s'}), - promotes_inputs=[('speed_of_sound', 'speed_of_sound'), - ('final_velocity', Mission.Takeoff.FINAL_VELOCITY)], - promotes_outputs=[('final_mach', Mission.Takeoff.FINAL_MACH)]) + self.add_subsystem( + 'compute_mach', + om.ExecComp( + 'final_mach = final_velocity / speed_of_sound', + final_mach={'units': 'unitless'}, + final_velocity={'units': 'm/s'}, + speed_of_sound={'units': 'm/s'}, + ), + promotes_inputs=[ + ('speed_of_sound', 'speed_of_sound'), + ('final_velocity', Mission.Takeoff.FINAL_VELOCITY), + ], + promotes_outputs=[('final_mach', Mission.Takeoff.FINAL_MACH)], + ) diff --git a/aviary/mission/flops_based/phases/test/test_building_landing.py b/aviary/mission/flops_based/phases/test/test_building_landing.py index 79ab9ef192..9455f4efce 100644 --- a/aviary/mission/flops_based/phases/test/test_building_landing.py +++ b/aviary/mission/flops_based/phases/test/test_building_landing.py @@ -8,9 +8,7 @@ class LandingPhaseTest(unittest.TestCase): - """ - Test landing phase builder - """ + """Test landing phase builder.""" def test_case1(self): landing_options = Landing( @@ -26,16 +24,14 @@ def test_case1(self): prob.setup(force_alloc_complex=True) prob.run_model() partial_data = prob.check_partials( - out_stream=None, method="cs", compact_print=False, excludes=["*atmosphere*"]) + out_stream=None, method='cs', compact_print=False, excludes=['*atmosphere*'] + ) assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) tol = 1e-6 - assert_near_equal( - prob[Mission.Landing.GROUND_DISTANCE], 6331.781, tol - ) - assert_near_equal( - prob[Mission.Landing.INITIAL_VELOCITY], 134.9752, tol) + assert_near_equal(prob[Mission.Landing.GROUND_DISTANCE], 6331.781, tol) + assert_near_equal(prob[Mission.Landing.INITIAL_VELOCITY], 134.9752, tol) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/phases/test/test_building_takeoff.py b/aviary/mission/flops_based/phases/test/test_building_takeoff.py index 5f36d51770..6e0d6a1de5 100644 --- a/aviary/mission/flops_based/phases/test/test_building_takeoff.py +++ b/aviary/mission/flops_based/phases/test/test_building_takeoff.py @@ -8,9 +8,7 @@ class TakeoffPhaseTest(unittest.TestCase): - """ - Test takeoff phase builder - """ + """Test takeoff phase builder.""" def test_case1(self): takeoff_options = Takeoff( @@ -24,20 +22,17 @@ def test_case1(self): prob = om.Problem() prob.model = takeoff - prob.model.set_input_defaults( - Aircraft.Wing.AREA, 1370.3, units="ft**2" - ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units='ft**2') prob.setup(force_alloc_complex=True) prob.run_model() partial_data = prob.check_partials( - out_stream=None, method="cs", compact_print=False, excludes=["*atmosphere*"]) + out_stream=None, method='cs', compact_print=False, excludes=['*atmosphere*'] + ) assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) tol = 1e-6 - assert_near_equal( - prob[Mission.Takeoff.GROUND_DISTANCE], 2811.442, tol - ) + assert_near_equal(prob[Mission.Takeoff.GROUND_DISTANCE], 2811.442, tol) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/phases/test/test_simplified_landing.py b/aviary/mission/flops_based/phases/test/test_simplified_landing.py index 1d011a8f74..4d9e03928a 100644 --- a/aviary/mission/flops_based/phases/test/test_simplified_landing.py +++ b/aviary/mission/flops_based/phases/test/test_simplified_landing.py @@ -1,40 +1,38 @@ import unittest import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary import constants -from aviary.mission.flops_based.phases.simplified_landing import (LandingCalc, - LandingGroup) -from aviary.variable_info.variables import Aircraft, Mission, Dynamic +from aviary.mission.flops_based.phases.simplified_landing import LandingCalc, LandingGroup +from aviary.variable_info.variables import Aircraft, Dynamic, Mission class LandingCalcTest(unittest.TestCase): - """ - Test computation in LandingCalc class (the simplified landing) - """ + """Test computation in LandingCalc class (the simplified landing).""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "land", + 'land', LandingCalc(), - promotes=["*"], + promotes=['*'], ) self.prob.model.set_input_defaults( - Mission.Landing.TOUCHDOWN_MASS, val=152800.0, units="lbm" + Mission.Landing.TOUCHDOWN_MASS, val=152800.0, units='lbm' ) # check (this is the design landing mass) self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, val=constants.RHO_SEA_LEVEL_METRIC, units="kg/m**3" + Dynamic.Atmosphere.DENSITY, + val=constants.RHO_SEA_LEVEL_METRIC, + units='kg/m**3', ) # not exact value but should be close enough self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.0, units="ft**2" + Aircraft.Wing.AREA, val=1370.0, units='ft**2' ) # check (this is the reference wing area) self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=3, units='unitless') # check + Mission.Landing.LIFT_COEFFICIENT_MAX, val=3, units='unitless' + ) # check self.prob.setup(check=False, force_alloc_complex=True) @@ -47,64 +45,61 @@ def test_case1(self): self.prob[Mission.Landing.GROUND_DISTANCE], 6403.64963504, tol ) # not actual value # not actual value - assert_near_equal( - self.prob[Mission.Landing.INITIAL_VELOCITY], 136.22914933, tol) + assert_near_equal(self.prob[Mission.Landing.INITIAL_VELOCITY], 136.22914933, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class LandingCalcTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.flops_based.phases.simplified_landing as landing + landing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.flops_based.phases.simplified_landing as landing + landing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() prob.model.add_subsystem( - "land", + 'land', LandingCalc(), - promotes=["*"], + promotes=['*'], ) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class LandingGroupTest(unittest.TestCase): - """ - Test the computation of LandingGroup - """ + """Test the computation of LandingGroup.""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "land", + 'land', LandingGroup(), - promotes=["*"], + promotes=['*'], ) self.prob.model.set_input_defaults( - Mission.Landing.TOUCHDOWN_MASS, val=152800.0, units="lbm" + Mission.Landing.TOUCHDOWN_MASS, val=152800.0, units='lbm' ) # check (this is the design landing mass) self.prob.model.set_input_defaults( - Mission.Landing.INITIAL_ALTITUDE, val=35, units="ft" + Mission.Landing.INITIAL_ALTITUDE, val=35, units='ft' ) # confirm initial altitude should be 35 ft. self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.0, units="ft**2" + Aircraft.Wing.AREA, val=1370.0, units='ft**2' ) # check (this is the reference wing area) self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=3, units='unitless') # check + Mission.Landing.LIFT_COEFFICIENT_MAX, val=3, units='unitless' + ) # check self.prob.setup(check=False, force_alloc_complex=True) @@ -117,14 +112,13 @@ def test_case1(self): self.prob[Mission.Landing.GROUND_DISTANCE], 6407.19354429, tol ) # not actual value # not actual value - assert_near_equal( - self.prob[Mission.Landing.INITIAL_VELOCITY], 136.22914933, tol) + assert_near_equal(self.prob[Mission.Landing.INITIAL_VELOCITY], 136.22914933, tol) partial_data = self.prob.check_partials( - out_stream=None, excludes=['*.standard_atmosphere'], method="cs" + out_stream=None, excludes=['*.standard_atmosphere'], method='cs' ) assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py b/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py index 588e5bc032..320a85cf55 100644 --- a/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py +++ b/aviary/mission/flops_based/phases/test/test_simplified_takeoff.py @@ -7,38 +7,36 @@ import unittest import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary import constants from aviary.mission.flops_based.phases.simplified_takeoff import ( - FinalTakeoffConditions, StallSpeed, TakeoffGroup) + FinalTakeoffConditions, + StallSpeed, + TakeoffGroup, +) from aviary.variable_info.variables import Aircraft, Dynamic, Mission class StallSpeedTest(unittest.TestCase): - """ - Test computation in StallSpeed class - """ + """Test computation in StallSpeed class.""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "comp", + 'comp', StallSpeed(), - promotes=["*"], + promotes=['*'], ) - self.prob.model.set_input_defaults("mass", val=181200.0, units="lbm") # check + self.prob.model.set_input_defaults('mass', val=181200.0, units='lbm') # check self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, val=constants.RHO_SEA_LEVEL_METRIC, units="kg/m**3" + Dynamic.Atmosphere.DENSITY, val=constants.RHO_SEA_LEVEL_METRIC, units='kg/m**3' ) # check self.prob.model.set_input_defaults( - "planform_area", val=1370.0, units="ft**2" + 'planform_area', val=1370.0, units='ft**2' ) # check (this is the reference wing area) - self.prob.model.set_input_defaults( - 'Cl_max', val=2.0000, units='unitless') # check + self.prob.model.set_input_defaults('Cl_max', val=2.0000, units='unitless') # check self.prob.setup(check=False, force_alloc_complex=True) @@ -47,76 +45,68 @@ def test_case1(self): tol = 1e-5 - assert_near_equal(self.prob["v_stall"], 71.90002053, tol) # not actual value + assert_near_equal(self.prob['v_stall'], 71.90002053, tol) # not actual value - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials( - partial_data, atol=1e-12, rtol=1e-12 - ) # check the partial derivatives + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) # check the partial derivatives class StallSpeedTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.flops_based.phases.simplified_takeoff as takeoff + takeoff.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.flops_based.phases.simplified_takeoff as takeoff + takeoff.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): self.prob = om.Problem() self.prob.model.add_subsystem( - "comp", + 'comp', StallSpeed(), - promotes=["*"], + promotes=['*'], ) self.prob.setup(check=False, force_alloc_complex=True) self.prob.run_model() - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class FinalConditionsTest(unittest.TestCase): - """ - Test final conditions computation in FinalTakeoffConditions class - """ + """Test final conditions computation in FinalTakeoffConditions class.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "comp", FinalTakeoffConditions(num_engines=2), promotes=["*"] - ) + self.prob.model.add_subsystem('comp', FinalTakeoffConditions(num_engines=2), promotes=['*']) + self.prob.model.set_input_defaults('v_stall', val=100, units='m/s') # not actual value self.prob.model.set_input_defaults( - "v_stall", val=100, units="m/s" - ) # not actual value - self.prob.model.set_input_defaults( - Mission.Summary.GROSS_MASS, val=181200.0, units="lbm" + Mission.Summary.GROSS_MASS, val=181200.0, units='lbm' ) # check self.prob.model.set_input_defaults( - Mission.Takeoff.FUEL_SIMPLE, val=577, units="lbm" + Mission.Takeoff.FUEL_SIMPLE, val=577, units='lbm' ) # check self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=constants.RHO_SEA_LEVEL_ENGLISH, - units="slug/ft**3", + units='slug/ft**3', ) # check + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.0, units='ft**2') # check self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.0, units="ft**2" + Mission.Takeoff.LIFT_COEFFICIENT_MAX, val=2.0000, units='unitless' ) # check self.prob.model.set_input_defaults( - Mission.Takeoff.LIFT_COEFFICIENT_MAX, val=2.0000, units='unitless') # check - self.prob.model.set_input_defaults( - Mission.Design.THRUST_TAKEOFF_PER_ENG, val=28928.0, units="lbf") # check + Mission.Design.THRUST_TAKEOFF_PER_ENG, val=28928.0, units='lbf' + ) # check self.prob.model.set_input_defaults( - Mission.Takeoff.LIFT_OVER_DRAG, val=17.354, units='unitless') # check + Mission.Takeoff.LIFT_OVER_DRAG, val=17.354, units='unitless' + ) # check self.prob.setup(check=False, force_alloc_complex=True) @@ -133,71 +123,62 @@ def test_case1(self): assert_near_equal( self.prob[Mission.Takeoff.FINAL_MASS], 180623.0, tol ) # lbm (not actual value) - assert_near_equal( - self.prob[Mission.Takeoff.FINAL_ALTITUDE], 35, tol) # ft + assert_near_equal(self.prob[Mission.Takeoff.FINAL_ALTITUDE], 35, tol) # ft - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class FinalConditionsTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.flops_based.phases.simplified_takeoff as takeoff + takeoff.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.flops_based.phases.simplified_takeoff as takeoff + takeoff.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem( - "comp", FinalTakeoffConditions(num_engines=2), promotes=["*"] - ) + prob.model.add_subsystem('comp', FinalTakeoffConditions(num_engines=2), promotes=['*']) # default value v_stall = 0.1 will worsen the output - prob.model.set_input_defaults("v_stall", val=100, units="m/s") + prob.model.set_input_defaults('v_stall', val=100, units='m/s') # default value GROSS_MASS = 150000 will worsen the output - prob.model.set_input_defaults( - Mission.Summary.GROSS_MASS, val=181200.0, units="lbm") + prob.model.set_input_defaults(Mission.Summary.GROSS_MASS, val=181200.0, units='lbm') prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class TakeoffGroupTest(unittest.TestCase): - """ - Test computation in TakeoffGroup - """ + """Test computation in TakeoffGroup.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group_example", TakeoffGroup(num_engines=2), promotes=["*"] - ) + self.prob.model.add_subsystem('group_example', TakeoffGroup(num_engines=2), promotes=['*']) self.prob.model.set_input_defaults( - Mission.Summary.GROSS_MASS, val=181200.0, units="lbm" + Mission.Summary.GROSS_MASS, val=181200.0, units='lbm' ) # check self.prob.model.set_input_defaults( - Mission.Takeoff.FUEL_SIMPLE, val=577, units="lbm" + Mission.Takeoff.FUEL_SIMPLE, val=577, units='lbm' ) # check + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.0, units='ft**2') # check self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.0, units="ft**2" + Mission.Takeoff.LIFT_COEFFICIENT_MAX, val=2.0000, units='unitless' ) # check self.prob.model.set_input_defaults( - Mission.Takeoff.LIFT_COEFFICIENT_MAX, val=2.0000, units='unitless') # check - self.prob.model.set_input_defaults( - Mission.Design.THRUST_TAKEOFF_PER_ENG, val=28928.0, units="lbf") # check - self.prob.model.set_input_defaults( - Mission.Takeoff.LIFT_OVER_DRAG, val=17.354, units='unitless') # check + Mission.Design.THRUST_TAKEOFF_PER_ENG, val=28928.0, units='lbf' + ) # check self.prob.model.set_input_defaults( - Dynamic.Mission.ALTITUDE, val=0, units="ft") # check + Mission.Takeoff.LIFT_OVER_DRAG, val=17.354, units='unitless' + ) # check + self.prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, val=0, units='ft') # check self.prob.setup(check=False, force_alloc_complex=True) @@ -215,13 +196,13 @@ def test_case1(self): assert_near_equal( self.prob[Mission.Takeoff.FINAL_MASS], 180623.0, tol ) # lbm (not actual value) - assert_near_equal( - self.prob[Mission.Takeoff.FINAL_ALTITUDE], 35, tol) # ft + assert_near_equal(self.prob[Mission.Takeoff.FINAL_ALTITUDE], 35, tol) # ft partial_data = self.prob.check_partials( - out_stream=None, excludes=['*.standard_atmosphere'], method="cs") + out_stream=None, excludes=['*.standard_atmosphere'], method='cs' + ) assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/flops_based/phases/test/test_time_integration_phases.py b/aviary/mission/flops_based/phases/test/test_time_integration_phases.py deleted file mode 100644 index 790969a395..0000000000 --- a/aviary/mission/flops_based/phases/test/test_time_integration_phases.py +++ /dev/null @@ -1,200 +0,0 @@ -import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.interface.default_phase_info.height_energy_fiti import add_default_sgm_args -from aviary.interface.methods_for_level2 import AviaryGroup -from aviary.mission.gasp_based.phases.time_integration_traj import FlexibleTraj -from aviary.mission.flops_based.phases.time_integration_phases import \ - SGMHeightEnergy -from aviary.subsystems.premission import CorePreMission -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.preprocessors import preprocess_propulsion -from aviary.utils.process_input_decks import create_vehicle -from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems -from aviary.variable_info.enums import EquationsOfMotion -from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings - -import warnings -import unittest -import importlib - - -@unittest.skipUnless(importlib.util.find_spec("pyoptsparse") is not None, "pyoptsparse is not installed") -class HE_SGMDescentTestCase(unittest.TestCase): - """ - This test builds height-energy based trajectories and then simulates them and checks that the final values are correct. - The trajectories used are intended to be single phases to simplify debugging and to allow for easier testing of trigger based values. - """ - - def setUp(self): - aviary_inputs, initialization_guesses = create_vehicle( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv') - aviary_inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, val=28690, units="lbf") - aviary_inputs.set_val(Dynamic.Mission.THROTTLE, val=0, units="unitless") - aviary_inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, - val=0.0175, units="unitless") - aviary_inputs.set_val(Mission.Takeoff.BRAKING_FRICTION_COEFFICIENT, - val=0.35, units="unitless") - aviary_inputs.set_val(Settings.EQUATIONS_OF_MOTION, - val=EquationsOfMotion.SOLVED_2DOF) - - engines = build_engine_deck(aviary_inputs) - # don't need mass - core_subsystems = get_default_premission_subsystems('FLOPS', engines)[:-1] - ode_args = dict(aviary_options=aviary_inputs, core_subsystems=core_subsystems) - preprocess_propulsion(aviary_inputs, engines) - - ode_args['num_nodes'] = 1 - ode_args['subsystem_options'] = {'core_aerodynamics': {'method': 'computed'}} - - self.ode_args = ode_args - self.aviary_inputs = aviary_inputs - self.tol = 1e-5 - - def setup_prob(self, phases) -> om.Problem: - prob = om.Problem() - prob.driver = om.pyOptSparseDriver() - prob.driver.options["optimizer"] = 'IPOPT' - prob.driver.opt_settings['tol'] = 1.0E-6 - prob.driver.opt_settings['mu_init'] = 1e-5 - prob.driver.opt_settings['max_iter'] = 50 - prob.driver.opt_settings['print_level'] = 5 - - aviary_options = self.ode_args['aviary_options'] - subsystems = self.ode_args['core_subsystems'] - - add_default_sgm_args(phases, self.ode_args) - - traj = FlexibleTraj( - Phases=phases, - promote_all_auto_ivc=True, - traj_final_state_output=[Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE], - traj_initial_state_input=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - ) - prob.model = AviaryGroup(aviary_options=aviary_options, - aviary_metadata=BaseMetaData) - prob.model.add_subsystem( - 'pre_mission', - CorePreMission(aviary_options=aviary_options, subsystems=subsystems), - promotes_inputs=['aircraft:*'], - promotes_outputs=['aircraft:*', 'mission:*'], - ) - prob.model.add_subsystem('traj', traj, - promotes=['aircraft:*', 'mission:*'] - ) - - prob.model.add_subsystem( - "fuel_obj", - om.ExecComp( - "reg_objective = overall_fuel/10000", - reg_objective={"val": 0.0, "units": "unitless"}, - overall_fuel={"units": "lbm"}, - ), - promotes_inputs=[ - ("overall_fuel", Mission.Summary.TOTAL_FUEL_MASS), - ], - promotes_outputs=[("reg_objective", Mission.Objectives.FUEL)], - ) - - prob.model.add_objective(Mission.Objectives.FUEL, ref=1e4) - - with warnings.catch_warnings(): - - warnings.simplefilter("ignore", om.PromotionWarning) - - prob.setup() - - return prob - - def run_simulation(self, phases, initial_values: dict): - prob = self.setup_prob(phases) - - for key, val in initial_values.items(): - prob.set_val(key, **val) - - prob.run_model() - - distance = prob.get_val('traj.distance_final', units='NM')[0] - mass = prob.get_val('traj.mass_final', units='lbm')[0] - alt = prob.get_val('traj.altitude_final', units='ft')[0] - - final_states = {'distance': distance, 'mass': mass, 'altitude': alt} - return final_states - - # def test_takeoff(self): - # initial_values_takeoff = { - # "traj.altitude_initial": {'val': 0, 'units': "ft"}, - # "traj.mass_initial": {'val': 171000, 'units': "lbm"}, - # "traj.distance_initial": {'val': 0, 'units': "NM"}, - # "traj.velocity": {'val': .1, 'units': "m/s"}, - # } - - # ode_args = self.ode_args - # ode_args['friction_key'] = Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT - # brake_release_to_decision = SGMDetailedTakeoff( - # ode_args, - # simupy_args=dict(verbosity=Verbosity.DEBUG,) - # ) - # brake_release_to_decision.clear_triggers() - # brake_release_to_decision.add_trigger(Dynamic.Mission.VELOCITY, value=167.85, units='kn') - - # phases = {'HE': { - # 'ode': brake_release_to_decision, - # 'vals_to_set': {} - # }} - - # final_states = self.run_simulation(phases, initial_values_takeoff) - # # assert_near_equal(final_states['altitude'], 500, self.tol) - # assert_near_equal(final_states['velocity'], 167.85, self.tol) - - def test_cruise(self): - initial_values_cruise = { - "traj.altitude_initial": {'val': 35000, 'units': "ft"}, - "traj.mass_initial": {'val': 171000, 'units': "lbm"}, - "traj.distance_initial": {'val': 0, 'units': "NM"}, - "traj.mach": {'val': .8, 'units': "unitless"}, - } - - phases = {'HE': { - 'kwargs': { - 'mass_trigger': (160000, 'lbm'), - }, - 'builder': SGMHeightEnergy, - "user_options": { - }, - }} - - final_states = self.run_simulation(phases, initial_values_cruise) - assert_near_equal(final_states['mass'], 160000, self.tol) - - # def test_landing(self): - # initial_values_landing = { - # "traj.altitude_initial": {'val': 35000, 'units': "ft"}, - # "traj.mass_initial": {'val': 171000, 'units': "lbm"}, - # "traj.distance_initial": {'val': 0, 'units': "NM"}, - # "traj.velocity": {'val': 300, 'units': "m/s"}, - # } - - # ode_args = self.ode_args - # ode_args['friction_key'] = Mission.Takeoff.BRAKING_FRICTION_COEFFICIENT - # phases = {'HE': { - # 'ode': SGMDetailedLanding( - # ode_args, - # simupy_args=dict(verbosity=Verbosity.QUIET,) - # ), - # 'vals_to_set': {} - # }} - - # final_states = self.run_simulation(phases, initial_values_landing) - # assert_near_equal(final_states['altitude'], 0, self.tol) - - -if __name__ == '__main__': - unittest.main() diff --git a/aviary/mission/flops_based/phases/time_integration_phases.py b/aviary/mission/flops_based/phases/time_integration_phases.py deleted file mode 100644 index 6f8f1c7525..0000000000 --- a/aviary/mission/flops_based/phases/time_integration_phases.py +++ /dev/null @@ -1,106 +0,0 @@ -from aviary.mission.flops_based.ode.mission_ODE import MissionODE -from aviary.mission.flops_based.ode.landing_ode import LandingODE -from aviary.mission.flops_based.ode.takeoff_ode import TakeoffODE -from aviary.mission.gasp_based.ode.time_integration_base_classes import SimuPyProblem -from aviary.variable_info.enums import AnalysisScheme -from aviary.variable_info.variables import Dynamic - - -class SGMHeightEnergy(SimuPyProblem): - """ - This creates a subproblem that will be used by most height energy phases during a trajectory that will - be solved using SGM. - A mass trigger is added as an example, but any other trigger can be added as necessary. - """ - - def __init__( - self, - ode_args, - phase_name='mission', - simupy_args={}, - mass_trigger=(150000, 'lbm') - ): - super().__init__(MissionODE( - analysis_scheme=AnalysisScheme.SHOOTING, - **ode_args), - problem_name=phase_name, - outputs=[], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - aviary_options=ode_args['aviary_options'], - **simupy_args) - - self.phase_name = phase_name - self.mass_trigger = mass_trigger - self.add_trigger(Dynamic.Mission.MASS, 'mass_trigger') - - -class SGMDetailedTakeoff(SimuPyProblem): - """ - This creates a subproblem that will be used by height energy phases during detailed takeoff that will - be solved using SGM. - An altitude trigger is added as an example, but any other trigger can be added as necessary in order to - string together the phases needed for a noise certification takeoff. - """ - - def __init__( - self, - ode_args, - phase_name='detailed_takeoff', - simupy_args={}, - ): - super().__init__(TakeoffODE( - analysis_scheme=AnalysisScheme.SHOOTING, - **ode_args), - problem_name=phase_name, - outputs=[], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - aviary_options=ode_args['aviary_options'], - **simupy_args) - - self.phase_name = phase_name - self.add_trigger(Dynamic.Mission.ALTITUDE, 50, units='ft') - - -class SGMDetailedLanding(SimuPyProblem): - """ - This creates a subproblem that will be used by height energy phases during detailed landing that will - be solved using SGM. - An altitude trigger is added as an example, but any other trigger can be added as necessary in order to - string together the phases needed for a noise certification landing. - """ - - def __init__( - self, - ode_args, - phase_name='detailed_landing', - simupy_args={}, - ): - super().__init__(LandingODE( - analysis_scheme=AnalysisScheme.SHOOTING, - **ode_args), - problem_name=phase_name, - outputs=[], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - aviary_options=ode_args['aviary_options'], - **simupy_args) - - self.phase_name = phase_name - self.add_trigger(Dynamic.Mission.ALTITUDE, 0, units='ft') diff --git a/aviary/mission/gasp_based/idle_descent_estimation.py b/aviary/mission/gasp_based/idle_descent_estimation.py deleted file mode 100644 index be3efca5b8..0000000000 --- a/aviary/mission/gasp_based/idle_descent_estimation.py +++ /dev/null @@ -1,187 +0,0 @@ -import openmdao.api as om - -from aviary.mission.gasp_based.phases.time_integration_traj import FlexibleTraj -from aviary.utils.functions import promote_aircraft_and_mission_vars -from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.variable_info.enums import Verbosity - - -def add_descent_estimation_as_submodel( - main_prob: om.Problem, - subsys_name='idle_descent_estimation', - phases=None, - ode_args=None, - initial_mass=None, - cruise_alt=None, - cruise_mach=None, - reserve_fuel=None, - all_subsystems=None, - verbosity=Verbosity.QUIET, -): - """ - This creates a sub model that contains a copy of the descent portion of the mission's trajectory. This is used to calculate an estimation of the fuel burn and distance required for the descent, so that they can be used as triggers for the cruise phase. The sub model is then added to the main problem. - The user can specify certain initial conditions or requirements such as cruise Mach number, reserve fuel required, etc. - """ - if phases is None: - from aviary.interface.default_phase_info.two_dof_fiti import \ - descent_phases as phases, add_default_sgm_args - add_default_sgm_args(phases, ode_args) - - if all_subsystems is None: - all_subsystems = [] - - traj = FlexibleTraj( - Phases=phases, - traj_initial_state_input=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - traj_final_state_output=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - promote_all_auto_ivc=True, - ) - - model = om.Group() - - if isinstance(initial_mass, str): - model.add_subsystem( - 'top_of_descent_mass', - om.ExecComp( - 'mass_initial = top_of_descent_mass', - mass_initial={'units': 'lbm'}, - top_of_descent_mass={'units': 'lbm'}, - ), - promotes_inputs=['top_of_descent_mass'], - promotes_outputs=['mass_initial']) - else: - model.add_subsystem( - 'top_of_descent_mass', - om.ExecComp( - 'mass_initial = operating_mass + payload_mass + reserve_fuel + descent_fuel_estimate', - mass_initial={'units': 'lbm'}, - operating_mass={'units': 'lbm'}, - payload_mass={'units': 'lbm'}, - reserve_fuel={'units': 'lbm', 'val': 0}, - descent_fuel_estimate={'units': 'lbm', 'val': 0}, - ), - promotes_inputs=[ - ('operating_mass', Aircraft.Design.OPERATING_MASS), - ('payload_mass', Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS), - 'reserve_fuel', - # ('reserve_fuel', Mission.Design.RESERVE_FUEL), - ('descent_fuel_estimate', 'descent_fuel'), - ], - promotes_outputs=['mass_initial'] - ) - - all_bus_vars = set() - for subsystem in all_subsystems: - bus_vars = subsystem.get_bus_variables() - for var, data in bus_vars.items(): - mission_variable_name = data['mission_name'] - if not isinstance(mission_variable_name, list): - mission_variable_name = [mission_variable_name] - for mission_var_name in mission_variable_name: - all_bus_vars.add(mission_var_name) - - model.add_subsystem( - 'descent_traj', traj, - promotes_inputs=['altitude_initial', 'mass_initial', 'aircraft:*'] + - [(var, 'parameters:'+var) for var in all_bus_vars], - promotes_outputs=['mass_final', 'distance_final'], - ) - - model.add_subsystem( - 'actual_fuel_burn', - om.ExecComp( - 'actual_fuel_burn = mass_initial - mass_final', - actual_fuel_burn={'units': 'lbm'}, - mass_initial={'units': 'lbm'}, - mass_final={'units': 'lbm'}, - ), - promotes_inputs=[ - 'mass_initial', - 'mass_final', - ], - promotes_outputs=[('actual_fuel_burn', 'descent_fuel')]) - - if verbosity >= Verbosity.BRIEF: - from aviary.utils.functions import create_printcomp - dummy_comp = create_printcomp( - all_inputs=[ - Aircraft.Design.OPERATING_MASS, - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, - 'descent_fuel', - 'reserve_fuel', - 'mass_initial', - 'distance_final', - ], - input_units={ - 'descent_fuel': 'lbm', - 'reserve_fuel': 'lbm', - 'mass_initial': 'lbm', - 'distance_final': 'nmi', - }) - model.add_subsystem( - "dummy_comp", - dummy_comp(), - promotes_inputs=["*"], - ) - model.set_input_defaults('reserve_fuel', 0, 'lbm') - model.set_input_defaults('mass_initial', 0, 'lbm') - - model.add_objective("descent_fuel", ref=1e4) - - model.linear_solver = om.DirectSolver(assemble_jac=True) - model.nonlinear_solver = om.NonlinearBlockGS(iprint=3, rtol=1e-2, maxiter=5) - - input_aliases = [] - if isinstance(initial_mass, str): - input_aliases.append(('top_of_descent_mass', initial_mass)) - elif isinstance(initial_mass, (int, float)): - model.set_input_defaults('mass_initial', initial_mass) - - if isinstance(cruise_alt, str): - input_aliases.append(('altitude_initial', cruise_alt)) - elif isinstance(cruise_alt, (int, float)): - model.set_input_defaults('altitude_initial', cruise_alt) - - if isinstance(reserve_fuel, str): - input_aliases.append(('reserve_fuel', reserve_fuel)) - elif isinstance(reserve_fuel, (int, float)): - model.set_input_defaults('reserve_fuel', reserve_fuel) - - model.set_input_defaults(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 0) - model.set_input_defaults( - Aircraft.Design.OPERATING_MASS, val=0, units='lbm') - model.set_input_defaults('descent_traj.'+Dynamic.Mission.THROTTLE, 0) - - promote_aircraft_and_mission_vars(model) - - subprob = om.Problem(model=model) - subcomp = om.SubmodelComp( - problem=subprob, - inputs=[ - 'aircraft:*', - ], - outputs=['distance_final', 'descent_fuel', 'mass_initial'], - do_coloring=False - ) - - main_prob.model.add_subsystem( - subsys_name, - subcomp, - promotes_inputs=[ - 'aircraft:*', - ] + input_aliases, - promotes_outputs=[ - ('distance_final', 'descent_range'), - 'descent_fuel', - ('mass_initial', 'start_of_descent_mass'), - ], - - ) diff --git a/aviary/mission/gasp_based/ode/accel_eom.py b/aviary/mission/gasp_based/ode/accel_eom.py index 04f0d3ac9d..5a42fe31d1 100644 --- a/aviary/mission/gasp_based/ode/accel_eom.py +++ b/aviary/mission/gasp_based/ode/accel_eom.py @@ -6,7 +6,6 @@ class AccelerationRates(om.ExplicitComponent): - """ Compute the TAS rate, distance rate, and mass flow rate for a level flight acceleration phase. @@ -14,73 +13,86 @@ class AccelerationRates(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) self.add_input( - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, val=np.ones(nn) * 1e6, - units="lbm", - desc="total mass of the aircraft", + units='lbm', + desc='total mass of the aircraft', ) self.add_input( - Dynamic.Mission.DRAG, + Dynamic.Vehicle.DRAG, val=np.zeros(nn), - units="lbf", - desc="drag on aircraft", + units='lbf', + desc='drag on aircraft', ) self.add_input( - Dynamic.Mission.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.zeros(nn), - units="lbf", - desc="total thrust", + units='lbf', + desc='total thrust', ) self.add_input( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="ft/s", - desc="true air speed", + units='ft/s', + desc='true air speed', ) self.add_output( Dynamic.Mission.VELOCITY_RATE, val=np.zeros(nn), - units="ft/s**2", - desc="rate of change of true air speed", + units='ft/s**2', + desc='rate of change of true air speed', ) self.add_output( Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), - units="ft/s", - desc="rate of change of horizontal distance covered", + units='ft/s', + desc='rate of change of horizontal distance covered', ) self.declare_partials( - Dynamic.Mission.VELOCITY_RATE, [ - Dynamic.Mission.MASS, Dynamic.Mission.DRAG, Dynamic.Mission.THRUST_TOTAL], rows=arange, cols=arange) - self.declare_partials(Dynamic.Mission.DISTANCE_RATE, [ - Dynamic.Mission.VELOCITY], rows=arange, cols=arange, val=1.) + Dynamic.Mission.VELOCITY_RATE, + [ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + Dynamic.Mission.DISTANCE_RATE, + [Dynamic.Mission.VELOCITY], + rows=arange, + cols=arange, + val=1.0, + ) def compute(self, inputs, outputs): - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - drag = inputs[Dynamic.Mission.DRAG] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + drag = inputs[Dynamic.Vehicle.DRAG] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] TAS = inputs[Dynamic.Mission.VELOCITY] - outputs[Dynamic.Mission.VELOCITY_RATE] = ( - GRAV_ENGLISH_GASP / weight) * (thrust - drag) + outputs[Dynamic.Mission.VELOCITY_RATE] = (GRAV_ENGLISH_GASP / weight) * (thrust - drag) outputs[Dynamic.Mission.DISTANCE_RATE] = TAS def compute_partials(self, inputs, J): - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - drag = inputs[Dynamic.Mission.DRAG] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + drag = inputs[Dynamic.Vehicle.DRAG] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.MASS] = \ + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( -(GRAV_ENGLISH_GASP / weight**2) * (thrust - drag) * GRAV_ENGLISH_LBM - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.DRAG] = - \ - (GRAV_ENGLISH_GASP / weight) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.THRUST_TOTAL] = GRAV_ENGLISH_GASP / weight + ) + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -(GRAV_ENGLISH_GASP / weight) + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + GRAV_ENGLISH_GASP / weight + ) diff --git a/aviary/mission/gasp_based/ode/accel_ode.py b/aviary/mission/gasp_based/ode/accel_ode.py index 1278e99c47..e204f7460f 100644 --- a/aviary/mission/gasp_based/ode/accel_ode.py +++ b/aviary/mission/gasp_based/ode/accel_ode.py @@ -1,15 +1,14 @@ import numpy as np from aviary.mission.gasp_based.ode.accel_eom import AccelerationRates -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.params import ParamPort + +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.subsystems.mass.mass_to_weight import MassToWeight -from aviary.variable_info.enums import AnalysisScheme, AnalysisScheme -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs, add_SGM_required_outputs +from aviary.variable_info.variables import Dynamic -class AccelODE(BaseODE): +class AccelODE(TwoDOFODE): """ODE for level acceleration. In level acceleration, there are only nonzero net forces in the direction of motion. @@ -18,61 +17,50 @@ class AccelODE(BaseODE): """ def setup(self): - nn = self.options["num_nodes"] - analysis_scheme = self.options["analysis_scheme"] - aviary_options = self.options['aviary_options'] - core_subsystems = self.options['core_subsystems'] - - if analysis_scheme is AnalysisScheme.SHOOTING: - add_SGM_required_inputs(self, { - 't_curr': {'units': 's'}, - Dynamic.Mission.DISTANCE: {'units': 'ft'}, - }) - add_SGM_required_outputs(self, { - Dynamic.Mission.ALTITUDE_RATE: {'units': 'ft/s'}, - }) + nn = self.options['num_nodes'] # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) - self.add_atmosphere(nn) + self.add_atmosphere() self.add_subsystem( - "calc_weight", + 'calc_weight', MassToWeight(num_nodes=nn), - promotes_inputs=[("mass", Dynamic.Mission.MASS)], - promotes_outputs=["weight"] + promotes_inputs=[('mass', Dynamic.Vehicle.MASS)], + promotes_outputs=['weight'], ) - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'cruise', 'output_alpha': True} - for subsystem in core_subsystems: - system = subsystem.build_mission(**kwargs) - if system is not None: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + kwargs = { + 'method': 'cruise', + 'output_alpha': True, + } + self.options['subsystem_options'].setdefault('core_aerodynamics', {}).update(kwargs) + + self.add_core_subsystems() + + self.add_external_subsystems() self.add_subsystem( - "accel_eom", + 'accel_eom', AccelerationRates(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Dynamic.Mission.VELOCITY, - Dynamic.Mission.DRAG, - Dynamic.Mission.THRUST_TOTAL, ], + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + ], promotes_outputs=[ Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.DISTANCE_RATE, ], + Dynamic.Mission.DISTANCE_RATE, + ], ) self.add_excess_rate_comps(nn) ParamPort.set_default_vals(self) - self.set_input_defaults(Dynamic.Mission.MASS, val=14e4 * - np.ones(nn), units="lbm") - self.set_input_defaults(Dynamic.Mission.ALTITUDE, - val=500 * np.ones(nn), units="ft") - self.set_input_defaults(Dynamic.Mission.VELOCITY, val=200*np.ones(nn), - units="m/s") # val here is nominal + self.set_input_defaults(Dynamic.Vehicle.MASS, val=14e4 * np.ones(nn), units='lbm') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=500 * np.ones(nn), units='ft') + self.set_input_defaults( + Dynamic.Mission.VELOCITY, val=200 * np.ones(nn), units='m/s' + ) # val here is nominal diff --git a/aviary/mission/gasp_based/ode/ascent_eom.py b/aviary/mission/gasp_based/ode/ascent_eom.py index 00d379462c..3be401f7cf 100644 --- a/aviary/mission/gasp_based/ode/ascent_eom.py +++ b/aviary/mission/gasp_based/ode/ascent_eom.py @@ -8,127 +8,178 @@ class AscentEOM(om.ExplicitComponent): """ - Ascent equation of motion: Compute the velocity rate, flight path angle rate, + Ascent equation of motion: Compute the velocity rate, flight path angle rate, altitude rate, distance rate, normal forces, fuselage pitch angle, load factor and angle of attack rate. """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] - self.add_input(Dynamic.Mission.MASS, val=np.ones(nn), - desc="aircraft mass", units="lbm") - self.add_input(Dynamic.Mission.THRUST_TOTAL, val=np.ones( - nn), desc=Dynamic.Mission.THRUST_TOTAL, units="lbf") + self.add_input(Dynamic.Vehicle.MASS, val=np.ones(nn), desc='aircraft mass', units='lbm') self.add_input( - Dynamic.Mission.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), - desc=Dynamic.Mission.LIFT, - units="lbf") + desc=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', + ) self.add_input( - Dynamic.Mission.DRAG, + Dynamic.Vehicle.LIFT, val=np.ones(nn), - desc=Dynamic.Mission.DRAG, - units="lbf") - self.add_input(Dynamic.Mission.VELOCITY, val=np.ones(nn), - desc="Velocity", units="ft/s") - self.add_input(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), - desc="flight path angle", units="rad") - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0, units="deg") - - self.add_input("alpha", val=np.ones(nn), desc="angle of attack", units="deg") - - self.add_output(Dynamic.Mission.VELOCITY_RATE, val=np.ones(nn), - desc="Velocity rate", units="ft/s**2") - self.add_output( - Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, val=np.ones(nn), desc="flight path angle rate", units="rad/s" + desc=Dynamic.Vehicle.LIFT, + units='lbf', ) - self.add_output( - Dynamic.Mission.ALTITUDE_RATE, + self.add_input( + Dynamic.Vehicle.DRAG, + val=np.ones(nn), + desc=Dynamic.Vehicle.DRAG, + units='lbf', + ) + self.add_input(Dynamic.Mission.VELOCITY, val=np.ones(nn), desc='Velocity', units='ft/s') + self.add_input( + Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.ones(nn), + desc='flight path angle', + units='rad', + ) + add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0, units='deg') + + self.add_input( + Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.ones(nn), - desc="altitude rate", - units="ft/s") + desc='angle of attack', + units='deg', + ) + self.add_output( - Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc="distance rate", units="ft/s" + Dynamic.Mission.VELOCITY_RATE, + val=np.ones(nn), + desc='Velocity rate', + units='ft/s**2', ) self.add_output( - "normal_force", val=np.ones(nn), desc="normal forces", units="lbf" + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + val=np.ones(nn), + desc='flight path angle rate', + units='rad/s', ) self.add_output( - "fuselage_pitch", val=np.ones(nn), desc="fuselage pitch angle", units="deg" + Dynamic.Mission.ALTITUDE_RATE, + val=np.ones(nn), + desc='altitude rate', + units='ft/s', ) self.add_output( - "load_factor", val=np.ones(nn), desc="load factor", units="unitless") + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc='distance rate', units='ft/s' + ) + self.add_output('normal_force', val=np.ones(nn), desc='normal forces', units='lbf') + self.add_output('fuselage_pitch', val=np.ones(nn), desc='fuselage pitch angle', units='deg') + self.add_output('load_factor', val=np.ones(nn), desc='load factor', units='unitless') self.add_output( - "alpha_rate", val=np.ones(nn), desc="angle of attack rate", units="deg/s" + 'angle_of_attack_rate', val=np.ones(nn), desc='angle of attack rate', units='deg/s' ) def setup_partials(self): - arange = np.arange(self.options["num_nodes"]) + arange = np.arange(self.options['num_nodes']) self.declare_partials( Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - [Dynamic.Mission.THRUST_TOTAL, "alpha", - Dynamic.Mission.LIFT, Dynamic.Mission.MASS, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY], + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.VELOCITY, + ], rows=arange, cols=arange, ) - self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, [ - Aircraft.Wing.INCIDENCE]) + self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, [Aircraft.Wing.INCIDENCE]) self.declare_partials( - "load_factor", - [Dynamic.Mission.LIFT, Dynamic.Mission.MASS, - Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.THRUST_TOTAL, "alpha"], + 'load_factor', + [ + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], rows=arange, cols=arange, ) - self.declare_partials("load_factor", [Aircraft.Wing.INCIDENCE]) + self.declare_partials('load_factor', [Aircraft.Wing.INCIDENCE]) self.declare_partials( Dynamic.Mission.VELOCITY_RATE, - [Dynamic.Mission.THRUST_TOTAL, "alpha", Dynamic.Mission.DRAG, - Dynamic.Mission.MASS, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.LIFT], + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Vehicle.LIFT, + ], rows=arange, cols=arange, ) self.declare_partials(Dynamic.Mission.VELOCITY_RATE, [Aircraft.Wing.INCIDENCE]) self.declare_partials( - Dynamic.Mission.ALTITUDE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange) + Dynamic.Mission.ALTITUDE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=arange, + cols=arange, + ) self.declare_partials( - Dynamic.Mission.DISTANCE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.DISTANCE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=arange, + cols=arange, ) self.declare_partials( - "normal_force", - [Dynamic.Mission.MASS, Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, "alpha"], + 'normal_force', + [ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], rows=arange, cols=arange, ) - self.declare_partials("normal_force", [Aircraft.Wing.INCIDENCE]) + self.declare_partials('normal_force', [Aircraft.Wing.INCIDENCE]) self.declare_partials( - "fuselage_pitch", Dynamic.Mission.FLIGHT_PATH_ANGLE, rows=arange, cols=arange, val=180 / np.pi, + 'fuselage_pitch', + Dynamic.Mission.FLIGHT_PATH_ANGLE, + rows=arange, + cols=arange, + val=180 / np.pi, + ) + self.declare_partials( + 'fuselage_pitch', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + rows=arange, + cols=arange, + val=1, ) - self.declare_partials("fuselage_pitch", "alpha", rows=arange, cols=arange, val=1) - self.declare_partials("fuselage_pitch", Aircraft.Wing.INCIDENCE, val=-1) + self.declare_partials('fuselage_pitch', Aircraft.Wing.INCIDENCE, val=-1) def compute(self, inputs, outputs): - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] mu = 0.0 - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] thrust_along_flightpath = thrust * np.cos((alpha - i_wing) * np.pi / 180) thrust_across_flightpath = thrust * np.sin((alpha - i_wing) * np.pi / 180) @@ -154,28 +205,26 @@ def compute(self, inputs, outputs): outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) - outputs["normal_force"] = normal_force - outputs["fuselage_pitch"] = gamma * 180 / np.pi - i_wing + alpha + outputs['normal_force'] = normal_force + outputs['fuselage_pitch'] = gamma * 180 / np.pi - i_wing + alpha - outputs["alpha_rate"] = np.zeros(nn) + outputs['angle_of_attack_rate'] = np.zeros(nn) - load_factor = (incremented_lift + thrust_across_flightpath) / ( - weight * np.cos(gamma) - ) + load_factor = (incremented_lift + thrust_across_flightpath) / (weight * np.cos(gamma)) - outputs["load_factor"] = load_factor + outputs['load_factor'] = load_factor def compute_partials(self, inputs, J): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] mu = MU_TAKEOFF mu = 0.0 @@ -191,17 +240,23 @@ def compute_partials(self, inputs, J): dTAcF_dAlpha = thrust * np.cos((alpha - i_wing) * np.pi / 180) * np.pi / 180 dTAcF_dIwing = -thrust * np.cos((alpha - i_wing) * np.pi / 180) * np.pi / 180 - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.THRUST_TOTAL] = dTAcF_dThrust * \ - GRAV_ENGLISH_GASP / (TAS * weight) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, "alpha"] = dTAcF_dAlpha * \ - GRAV_ENGLISH_GASP / (TAS * weight) + J[ + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + ] = dTAcF_dThrust * GRAV_ENGLISH_GASP / (TAS * weight) + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( + dTAcF_dAlpha * GRAV_ENGLISH_GASP / (TAS * weight) + ) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Aircraft.Wing.INCIDENCE] = ( dTAcF_dIwing * GRAV_ENGLISH_GASP / (TAS * weight) ) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - Dynamic.Mission.LIFT] = GRAV_ENGLISH_GASP / (TAS * weight) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.MASS] = (GRAV_ENGLISH_GASP / TAS) * GRAV_ENGLISH_LBM * ( - -thrust_across_flightpath / weight**2 - incremented_lift / weight**2 + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.LIFT] = GRAV_ENGLISH_GASP / ( + TAS * weight + ) + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.MASS] = ( + (GRAV_ENGLISH_GASP / TAS) + * GRAV_ENGLISH_LBM + * (-thrust_across_flightpath / weight**2 - incremented_lift / weight**2) ) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( weight * np.sin(gamma) * GRAV_ENGLISH_GASP / (TAS * weight) @@ -212,21 +267,22 @@ def compute_partials(self, inputs, J): / (TAS**2 * weight) ) - J["load_factor", Dynamic.Mission.LIFT] = 1 / (weight * np.cos(gamma)) - J["load_factor", Dynamic.Mission.MASS] = -(incremented_lift + thrust_across_flightpath) / ( - weight**2 * np.cos(gamma) - ) * GRAV_ENGLISH_LBM - J["load_factor", Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + J['load_factor', Dynamic.Vehicle.LIFT] = 1 / (weight * np.cos(gamma)) + J['load_factor', Dynamic.Vehicle.MASS] = ( + -(incremented_lift + thrust_across_flightpath) + / (weight**2 * np.cos(gamma)) + * GRAV_ENGLISH_LBM + ) + J['load_factor', Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( -(incremented_lift + thrust_across_flightpath) / (weight * (np.cos(gamma)) ** 2) * (-np.sin(gamma)) ) - J["load_factor", Dynamic.Mission.THRUST_TOTAL] = dTAcF_dThrust / \ - (weight * np.cos(gamma)) - J["load_factor", "alpha"] = dTAcF_dAlpha / (weight * np.cos(gamma)) - J["load_factor", Aircraft.Wing.INCIDENCE] = dTAcF_dIwing / ( + J['load_factor', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = dTAcF_dThrust / ( weight * np.cos(gamma) ) + J['load_factor', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dTAcF_dAlpha / (weight * np.cos(gamma)) + J['load_factor', Aircraft.Wing.INCIDENCE] = dTAcF_dIwing / (weight * np.cos(gamma)) normal_force1 = weight - incremented_lift - thrust_across_flightpath normal_force = np.where(normal_force1 < 0, np.zeros(nn), normal_force1) @@ -246,18 +302,19 @@ def compute_partials(self, inputs, J): dNF_dIwing = -np.ones(nn) * dTAcF_dIwing dNF_dIwing[normal_force1 < 0] = 0 - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.THRUST_TOTAL] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( (dTAlF_dThrust - mu * dNF_dThrust) * GRAV_ENGLISH_GASP / weight ) - J[Dynamic.Mission.VELOCITY_RATE, "alpha"] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( (dTAlF_dAlpha - mu * dNF_dAlpha) * GRAV_ENGLISH_GASP / weight ) J[Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE] = ( (dTAlF_dIwing - mu * dNF_dIwing) * GRAV_ENGLISH_GASP / weight ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.DRAG] = -GRAV_ENGLISH_GASP / weight - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.MASS] = ( - GRAV_ENGLISH_GASP * GRAV_ENGLISH_LBM + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -GRAV_ENGLISH_GASP / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( + GRAV_ENGLISH_GASP + * GRAV_ENGLISH_LBM * ( weight * (-np.sin(gamma) - mu * dNF_dWeight) - ( @@ -269,21 +326,21 @@ def compute_partials(self, inputs, J): ) / weight**2 ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = - \ - np.cos(gamma) * GRAV_ENGLISH_GASP - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.LIFT] = GRAV_ENGLISH_GASP * \ - (-mu * dNF_dLift) / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + -np.cos(gamma) * GRAV_ENGLISH_GASP + ) + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.LIFT] = ( + GRAV_ENGLISH_GASP * (-mu * dNF_dLift) / weight + ) J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = np.sin(gamma) - J[Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = np.cos(gamma) - J[Dynamic.Mission.DISTANCE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) - - J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM - J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift - J["normal_force", Dynamic.Mission.THRUST_TOTAL] = dNF_dThrust - J["normal_force", "alpha"] = dNF_dAlpha - J["normal_force", Aircraft.Wing.INCIDENCE] = dNF_dIwing + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + + J['normal_force', Dynamic.Vehicle.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM + J['normal_force', Dynamic.Vehicle.LIFT] = dNF_dLift + J['normal_force', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = dNF_dThrust + J['normal_force', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dNF_dAlpha + J['normal_force', Aircraft.Wing.INCIDENCE] = dNF_dIwing diff --git a/aviary/mission/gasp_based/ode/ascent_ode.py b/aviary/mission/gasp_based/ode/ascent_ode.py index 452ea4bcd6..5fba64153b 100644 --- a/aviary/mission/gasp_based/ode/ascent_ode.py +++ b/aviary/mission/gasp_based/ode/ascent_ode.py @@ -1,14 +1,13 @@ import numpy as np -from aviary.variable_info.enums import AlphaModes, AnalysisScheme -from aviary.variable_info.variables import Aircraft, Mission, Dynamic from aviary.mission.gasp_based.ode.ascent_eom import AscentEOM -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.params import ParamPort -from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE +from aviary.variable_info.enums import AlphaModes +from aviary.variable_info.variables import Aircraft, Dynamic -class AscentODE(BaseODE): +class AscentODE(TwoDOFODE): """ODE for initial ascent. This phase is intended to model the portion of aircraft flight starting when the @@ -18,84 +17,74 @@ class AscentODE(BaseODE): def initialize(self): super().initialize() - self.options.declare("alpha_mode", default=AlphaModes.DEFAULT, types=AlphaModes) + self.options.declare('alpha_mode', default=AlphaModes.DEFAULT, types=AlphaModes) def setup(self): - nn = self.options["num_nodes"] - alpha_mode = self.options["alpha_mode"] - analysis_scheme = self.options["analysis_scheme"] - aviary_options = self.options['aviary_options'] - core_subsystems = self.options['core_subsystems'] + nn = self.options['num_nodes'] + alpha_mode = self.options['alpha_mode'] # TODO: paramport ascent_params = ParamPort() - if analysis_scheme is AnalysisScheme.SHOOTING: - add_SGM_required_inputs(self, { - Dynamic.Mission.ALTITUDE: {'units': 'ft'}, - Dynamic.Mission.DISTANCE: {'units': 'ft'}, - }) + self.add_subsystem('params', ascent_params, promotes=['*']) - ascent_params.add_params({ - Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE: dict(units='deg', val=0), - }) - self.add_subsystem("params", ascent_params, promotes=["*"]) + self.add_atmosphere() - self.add_atmosphere(nn) + kwargs = { + 'method': 'low_speed', + 'retract_gear': True, + 'retract_flaps': True, + } + self.options['subsystem_options'].setdefault('core_aerodynamics', {}).update(kwargs) - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'low_speed', 'retract_gear': True, 'retract_flaps': True} - for subsystem in core_subsystems: - system = subsystem.build_mission(**kwargs) - if system is not None: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_core_subsystems() + + self.add_external_subsystems() if alpha_mode is AlphaModes.DEFAULT: # alpha as input pass else: - self.AddAlphaControl(alpha_mode=alpha_mode, num_nodes=nn) + self.add_alpha_control(alpha_mode=alpha_mode, num_nodes=nn) self.add_subsystem( - "ascent_eom", + 'ascent_eom', AscentEOM(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.LIFT, - Dynamic.Mission.DRAG, + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.DRAG, Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE, - "alpha", - ] + ["aircraft:*"], + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ] + + ['aircraft:*'], promotes_outputs=[ Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.DISTANCE_RATE, - "alpha_rate", - "normal_force", - "fuselage_pitch", - "load_factor", + 'angle_of_attack_rate', + 'normal_force', + 'fuselage_pitch', + 'load_factor', ], ) self.add_excess_rate_comps(nn) ParamPort.set_default_vals(self) - self.set_input_defaults("t_init_flaps", val=47.5) - self.set_input_defaults("t_init_gear", val=37.3) - self.set_input_defaults("alpha", val=np.zeros(nn), units="deg") - self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units="deg") - self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units="ft") - self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units="kn") - self.set_input_defaults("t_curr", val=np.zeros(nn), units="s") - self.set_input_defaults('aero_ramps.flap_factor:final_val', val=0.) - self.set_input_defaults('aero_ramps.gear_factor:final_val', val=0.) - self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=1.) - self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=1.) - self.set_input_defaults(Dynamic.Mission.MASS, val=np.ones( - nn), units='kg') # val here is nominal + self.set_input_defaults('t_init_flaps', val=47.5) + self.set_input_defaults('t_init_gear', val=37.3) + self.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='deg') + self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='deg') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units='ft') + self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='kn') + self.set_input_defaults('t_curr', val=np.zeros(nn), units='s') + self.set_input_defaults('aero_ramps.flap_factor:final_val', val=0.0) + self.set_input_defaults('aero_ramps.gear_factor:final_val', val=0.0) + self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=1.0) + self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=1.0) + self.set_input_defaults( + Dynamic.Vehicle.MASS, val=np.ones(nn), units='kg' + ) # val here is nominal diff --git a/aviary/mission/gasp_based/ode/base_ode.py b/aviary/mission/gasp_based/ode/base_ode.py deleted file mode 100644 index 9aad746bd7..0000000000 --- a/aviary/mission/gasp_based/ode/base_ode.py +++ /dev/null @@ -1,268 +0,0 @@ -import numpy as np - -import openmdao.api as om - -from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate -from aviary.mission.ode.altitude_rate import AltitudeRate -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import AnalysisScheme, AlphaModes, SpeedType -from aviary.variable_info.variables import Aircraft, Dynamic - - -class BaseODE(om.Group): - """ - The base class for all GASP based ODE components. - """ - - def initialize(self): - self.options.declare("num_nodes", default=1, types=int) - self.options.declare( - "analysis_scheme", - default=AnalysisScheme.COLLOCATION, - types=AnalysisScheme, - desc="The analysis method that will be used to close the trajectory; for example collocation or time integration", - ) - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - - self.options.declare( - 'core_subsystems', - desc='list of core subsystems' - ) - - self.options.declare( - 'subsystem_options', types=dict, default={}, - desc='dictionary of parameters to be passed to the subsystem builders' - ) - - def AddAlphaControl( - self, - alpha_group=None, - alpha_mode: AlphaModes = AlphaModes.DEFAULT, - num_nodes=1, - target_load_factor=1.1, - target_tas_rate=0, - # target_alt_rate=0, - # target_flight_path_angle=0, - atol=1e-7, - rtol=1e-7, - add_default_solver=True, - print_level=0, - ): - ''' - This is used when angle of attack in an ODE needs to be controlled directly. - ''' - - if not alpha_group: - alpha_group = self - nn = num_nodes - - if alpha_mode is AlphaModes.ROTATION: - alpha_comp = om.ExecComp( - 'alpha=rotation_rate*(t_curr-start_rotation)+alpha_init', - alpha=dict(val=0., units='deg'), - rotation_rate=dict(val=10.0/3.0, units='deg/s'), - t_curr=dict(val=0., units='s'), - start_rotation=dict(val=0., units='s'), - alpha_init=dict(val=0., units='deg'), - ) - alpha_comp_inputs = ["rotation_rate", "t_curr", "start_rotation", - ("alpha_init", Aircraft.Wing.INCIDENCE)] - - elif alpha_mode is AlphaModes.LOAD_FACTOR: - alpha_comp = om.BalanceComp( - name="alpha", - val=np.full(nn, 10), # initial guess - units="deg", - eq_units="unitless", - lhs_name="load_factor", - rhs_val=target_load_factor, - upper=25., - lower=-2., - ) - alpha_comp_inputs = ["load_factor"] - - elif alpha_mode is AlphaModes.FUSELAGE_PITCH: - alpha_comp = om.ExecComp( - 'alpha=max_fus_angle-gamma+i_wing', - alpha=dict(val=0., units='deg'), - max_fus_angle=dict(val=0., units='deg'), - gamma=dict(val=0., units='deg'), - i_wing=dict(val=0., units='deg'), - ) - alpha_comp_inputs = [("max_fus_angle", Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE), - ("gamma", Dynamic.Mission.FLIGHT_PATH_ANGLE), - ("i_wing", Aircraft.Wing.INCIDENCE)] - - elif alpha_mode is AlphaModes.DECELERATION: - alpha_comp = om.BalanceComp( - name="alpha", - val=np.full(nn, 10), # initial guess - units="deg", - lhs_name=Dynamic.Mission.VELOCITY_RATE, - rhs_name='target_tas_rate', - rhs_val=target_tas_rate, - eq_units="kn/s", - upper=25., - lower=-2., - ) - alpha_comp_inputs = [Dynamic.Mission.VELOCITY_RATE] - - elif alpha_mode is AlphaModes.REQUIRED_LIFT: - alpha_comp = om.BalanceComp( - name="alpha", - val=8.0 * np.ones(nn), - units="deg", - rhs_name="required_lift", - lhs_name=Dynamic.Mission.LIFT, - eq_units="lbf", - upper=12.0, - lower=-2, - ) - alpha_comp_inputs = ["required_lift", Dynamic.Mission.LIFT] - - # Future controller modes - # elif alpha_mode is AlphaModes.FLIGHT_PATH_ANGLE: - # alpha_comp = om.BalanceComp( - # name="alpha", - # val=np.full(nn, 1), - # units="deg", - # lhs_name=Dynamic.Mission.FLIGHT_PATH_ANGLE, - # rhs_name='target_flight_path_angle', - # rhs_val=target_flight_path_angle, - # eq_units="deg", - # upper=12.0, - # lower=-2, - # ) - # alpha_comp_inputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE] - - # elif alpha_mode is AlphaModes.ALTITUDE_RATE: - # alpha_comp = om.BalanceComp( - # name="alpha", - # val=np.full(nn, 1), - # units="deg", - # lhs_name=Dynamic.Mission.ALTITUDE_RATE, - # rhs_name='target_alt_rate', - # rhs_val=target_alt_rate, - # upper=12.0, - # lower=-2, - # ) - # alpha_comp_inputs = [Dynamic.Mission.ALTITUDE_RATE] - - # elif alpha_mode is AlphaModes.CONSTANT_ALTITUDE: - # alpha_comp = om.BalanceComp( - # name="alpha", - # val=np.full(nn, 1), - # units="deg", - # lhs_name=Dynamic.Mission.ALTITUDE, - # rhs_name='target_alt', - # rhs_val=37500, - # upper=12.0, - # lower=-2, - # ) - # alpha_comp_inputs = [Dynamic.Mission.ALTITUDE] - - if alpha_mode is not AlphaModes.DEFAULT: - alpha_group.add_subsystem("alpha_comp", - alpha_comp, - promotes_inputs=alpha_comp_inputs, - promotes_outputs=["alpha"], - ) - - if add_default_solver and alpha_mode not in (AlphaModes.ROTATION,): - alpha_group.nonlinear_solver = om.NewtonSolver() - alpha_group.nonlinear_solver.options["solve_subsystems"] = True - alpha_group.nonlinear_solver.options["iprint"] = print_level - alpha_group.nonlinear_solver.options["atol"] = atol - alpha_group.nonlinear_solver.options["rtol"] = rtol - alpha_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() - alpha_group.linear_solver = om.DirectSolver(assemble_jac=True) - - def AddThrottleControl( - self, - prop_group=om.Group(), - num_nodes=1, - atol=1e-12, - rtol=1e-12, - add_default_solver=True, - print_level=0, - ): - ''' - This is used when throttle in an ODE needs to be controlled directly. - ''' - - nn = num_nodes - - thrust_bal = om.BalanceComp( - name=Dynamic.Mission.THROTTLE, - val=np.ones(nn), - upper=1.0, - lower=0.0, - units='unitless', - lhs_name=Dynamic.Mission.THRUST_TOTAL, - rhs_name="required_thrust", - eq_units="lbf", - ) - prop_group.add_subsystem("thrust_balance", - thrust_bal, - promotes_inputs=[ - Dynamic.Mission.THRUST_TOTAL, 'required_thrust'], - promotes_outputs=[Dynamic.Mission.THROTTLE], - ) - - if add_default_solver: - prop_group.linear_solver = om.DirectSolver() - prop_group.linear_solver.options["iprint"] = print_level - - prop_group.nonlinear_solver = om.NewtonSolver() - prop_group.nonlinear_solver.options["err_on_non_converge"] = False - prop_group.nonlinear_solver.options["solve_subsystems"] = True - prop_group.nonlinear_solver.options["maxiter"] = 20 - prop_group.nonlinear_solver.options["iprint"] = print_level - prop_group.nonlinear_solver.options["atol"] = atol - prop_group.nonlinear_solver.options["rtol"] = rtol - prop_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() - prop_group.linear_solver = om.DirectSolver(assemble_jac=True) - - if prop_group is not self: - self.add_subsystem( - 'prop_group', - prop_group, - promotes=['*'] - ) - - def add_atmosphere(self, nn, input_speed_type=SpeedType.TAS): - """Add atmosphere component""" - self.add_subsystem( - name='atmosphere', - subsys=Atmosphere(num_nodes=nn, input_speed_type=input_speed_type), - promotes=['*'], - ) - - def add_excess_rate_comps(self, nn): - """Add SpecificEnergyRate and AltitudeRate components""" - self.add_subsystem( - name='SPECIFIC_ENERGY_RATE_EXCESS', - subsys=SpecificEnergyRate(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, - (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), - Dynamic.Mission.DRAG], - promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] - ) - - self.add_subsystem( - name='ALTITUDE_RATE_MAX', - subsys=AltitudeRate(num_nodes=nn), - promotes_inputs=[ - (Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), - Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.VELOCITY], - promotes_outputs=[ - (Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.ALTITUDE_RATE_MAX)]) diff --git a/aviary/mission/gasp_based/ode/breguet_cruise_eom.py b/aviary/mission/gasp_based/ode/breguet_cruise_eom.py index 1f77f98ed7..5d0d8fb1a0 100644 --- a/aviary/mission/gasp_based/ode/breguet_cruise_eom.py +++ b/aviary/mission/gasp_based/ode/breguet_cruise_eom.py @@ -6,37 +6,55 @@ class RangeComp(om.ExplicitComponent): - """ - Compute the cruise range and time for the breguet range component - """ + """Compute the cruise range and time for the breguet range component.""" def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - - nn = self.options["num_nodes"] - - self.add_input("cruise_time_initial", val=0.0, units="s", - desc="time at which cruise begins") - self.add_input("cruise_distance_initial", val=0.0, units="NM", - desc="range reference at which cruise begins") - - self.add_input("TAS_cruise", val=0.8 * np.ones(nn), - units="ft/s", desc="true airspeed") - self.add_input("mass", val=150000 * np.ones(nn), units="lbm", - desc="mass at each node, monotonically nonincreasing") - - self.add_input(Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - 0.74 * np.ones(nn), units="lbm/h") - - self.add_output("cruise_time", shape=(nn,), units="s", desc="time in cruise", - tags=['dymos.state_source:cruise_time']) - self.add_output("cruise_range", shape=(nn,), units="NM", desc="cruise range", - tags=["dymos.state_source:distance"]) + nn = self.options['num_nodes'] + + self.add_input( + 'cruise_time_initial', val=0.0, units='s', desc='time at which cruise begins' + ) + self.add_input( + 'cruise_distance_initial', + val=0.0, + units='NM', + desc='range reference at which cruise begins', + ) + + self.add_input('TAS_cruise', val=0.0001 * np.ones(nn), units='NM/s', desc='true airspeed') + self.add_input( + 'mass', + val=150000 * np.ones(nn), + units='lbm', + desc='mass at each node, monotonically nonincreasing', + ) + + self.add_input( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + 0.74 * np.ones(nn), + units='lbm/h', + ) + + self.add_output( + 'cruise_time', + shape=(nn,), + units='s', + desc='time in cruise', + tags=['dymos.state_source:cruise_time'], + ) + self.add_output( + 'cruise_range', + shape=(nn,), + units='NM', + desc='cruise range', + tags=['dymos.state_source:distance'], + ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # The nonzero partials of the change in range between each two nodes (dr) wrt fuel flow and mass are # along two diagonals. The lower diagonal contains the partials wrt the initial values of mass or fuel @@ -64,12 +82,28 @@ def setup_partials(self): self._tril_rs, self._tril_cs = rs, cs self.declare_partials( - "cruise_range", [Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "mass", "TAS_cruise"], rows=rs, cols=cs) + 'cruise_range', + [ + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + 'mass', + 'TAS_cruise', + ], + rows=rs, + cols=cs, + ) self.declare_partials( - "cruise_time", [Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, "mass", "TAS_cruise"], rows=rs, cols=cs) - - self.declare_partials("cruise_range", "cruise_distance_initial", val=1.0) - self.declare_partials("cruise_time", "cruise_time_initial", val=1.0) + 'cruise_time', + [ + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + 'mass', + 'TAS_cruise', + ], + rows=rs, + cols=cs, + ) + + self.declare_partials('cruise_range', 'cruise_distance_initial', val=1.0) + self.declare_partials('cruise_time', 'cruise_time_initial', val=1.0) # Allocated memory so we don't have to repeatedly do it in compute_partials # Note: since these are only used in compute_partials we don't have to worry about them supporting @@ -79,11 +113,11 @@ def setup_partials(self): self._scratch_nn_x_nn = np.zeros((nn, nn)) def compute(self, inputs, outputs): - v_x = inputs["TAS_cruise"] - m = inputs["mass"] - FF = -inputs[Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL] - r0 = inputs["cruise_distance_initial"] - t0 = inputs["cruise_time_initial"] + v_x = inputs['TAS_cruise'] + m = inputs['mass'] + FF = -inputs[Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL] + r0 = inputs['cruise_distance_initial'] + t0 = inputs['cruise_time_initial'] r0 = r0[0] t0 = t0[0] @@ -99,44 +133,44 @@ def compute(self, inputs, outputs): vx_2 = v_x[1:] # Final airspeed across each two-node pair vx_m = (vx_1 + vx_2) / 2 # Average airspeed across each two-node pair. - breg_1 = vx_1 * W1 * 3600 / (FF_1 * 6076.1) - breg_2 = vx_2 * W2 * 3600 / (FF_2 * 6076.1) + breg_1 = vx_1 * W1 * 3600 / FF_1 + breg_2 = vx_2 * W2 * 3600 / FF_2 bregA = (breg_1 + breg_2) / 2 - drange_cruise = bregA * np.log(1. / (1. - (W1 - W2) / W1)) + drange_cruise = bregA * np.log(1.0 / (1.0 - (W1 - W2) / W1)) - outputs["cruise_range"][0] = r0 - outputs["cruise_range"][1:] = r0 + np.cumsum(drange_cruise) - outputs["cruise_time"][0] = t0 - outputs["cruise_time"][1:] = t0 + np.cumsum(drange_cruise) / vx_m * 6076.1 + outputs['cruise_range'][0] = r0 + outputs['cruise_range'][1:] = r0 + np.cumsum(drange_cruise) + outputs['cruise_time'][0] = t0 + outputs['cruise_time'][1:] = t0 + np.cumsum(drange_cruise) / vx_m def compute_partials(self, inputs, J): - v_x = inputs["TAS_cruise"] + v_x = inputs['TAS_cruise'] vx_1 = v_x[:-1] # Initial airspeed across each two-node pair vx_2 = v_x[1:] # Final airspeed across each two-node pair vx_m = (vx_1 + vx_2) / 2 # Average airspeed across each two-node pair. - m = inputs["mass"] + m = inputs['mass'] # Initial mass across each two-node pair W1 = m[:-1] * GRAV_ENGLISH_LBM W2 = m[1:] * GRAV_ENGLISH_LBM # Final mass across each two-node pair - FF = -inputs[Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL] + FF = -inputs[Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL] FF_1 = FF[:-1] # Initial fuel flow across each two-node pair FF_2 = FF[1:] # Final fuel flow across each two_node pair - breg_1 = vx_1 * W1 * 3600 / (FF_1 * 6076.1) - breg_2 = vx_2 * W2 * 3600 / (FF_2 * 6076.1) + breg_1 = vx_1 * W1 * 3600 / FF_1 + breg_2 = vx_2 * W2 * 3600 / FF_2 bregA = (breg_1 + breg_2) / 2 star = np.log(1 / (1 - (W1 - W2) / W1)) - dBreg1_dVx1 = W1 * 3600 / (FF_1 * 6076.1) - dBreg1_dW1 = vx_1 * 3600 / (FF_1 * 6076.1) - dBreg1_dFF1 = vx_1 * W1 * 3600 / (FF_1**2 * 6076.1) + dBreg1_dVx1 = W1 * 3600 / FF_1 + dBreg1_dW1 = vx_1 * 3600 / FF_1 + dBreg1_dFF1 = vx_1 * W1 * 3600 / FF_1**2 - dBreg2_dVx2 = W2 * 3600 / (FF_2 * 6076.1) - dBreg2_dW2 = vx_2 * 3600 / (FF_2 * 6076.1) - dBreg2_dFF2 = vx_2 * W2 * 3600 / (FF_2**2 * 6076.1) + dBreg2_dVx2 = W2 * 3600 / FF_2 + dBreg2_dW2 = vx_2 * 3600 / FF_2 + dBreg2_dFF2 = vx_2 * W2 * 3600 / FF_2**2 dStar_dW1 = 1.0 / W1 dStar_dW2 = -1.0 / W2 @@ -161,24 +195,25 @@ def compute_partials(self, inputs, J): np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], dRange_dFF1) np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], dRange_dFF2) - J["cruise_range", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL][...] = \ - (self._d_cumsum_dx @ self._scratch_nn_x_nn)[self._tril_rs, self._tril_cs] + J['cruise_range', Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL][...] = ( + self._d_cumsum_dx @ self._scratch_nn_x_nn + )[self._tril_rs, self._tril_cs] # WRT Mass: dRange_dm = dRange_dW * dW_dm - np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], - dRange_dW1 * GRAV_ENGLISH_LBM) - np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], - dRange_dW2 * GRAV_ENGLISH_LBM) + np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], dRange_dW1 * GRAV_ENGLISH_LBM) + np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], dRange_dW2 * GRAV_ENGLISH_LBM) - J["cruise_range", "mass"][...] = \ - (self._d_cumsum_dx @ self._scratch_nn_x_nn)[self._tril_rs, self._tril_cs] + J['cruise_range', 'mass'][...] = (self._d_cumsum_dx @ self._scratch_nn_x_nn)[ + self._tril_rs, self._tril_cs + ] # WRT TAS_cruise np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], dRange_dVx1) np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], dRange_dVx2) - J["cruise_range", "TAS_cruise"][...] = \ - (self._d_cumsum_dx @ self._scratch_nn_x_nn)[self._tril_rs, self._tril_cs] + J['cruise_range', 'TAS_cruise'][...] = (self._d_cumsum_dx @ self._scratch_nn_x_nn)[ + self._tril_rs, self._tril_cs + ] # Partials of cruise_time @@ -186,11 +221,11 @@ def compute_partials(self, inputs, J): # But the jacobian is in a flat format in row-major order. The rows associated # with the nonzero elements are stored in self._tril_rs. - J["cruise_time", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL][1:] = \ - J["cruise_range", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL][1:] / \ - vx_m[self._tril_rs[1:] - 1] * 6076.1 - J["cruise_time", "mass"][1:] = \ - J["cruise_range", "mass"][1:] / vx_m[self._tril_rs[1:] - 1] * 6076.1 + J['cruise_time', Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL][1:] = ( + J['cruise_range', Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL][1:] + / vx_m[self._tril_rs[1:] - 1] + ) + J['cruise_time', 'mass'][1:] = J['cruise_range', 'mass'][1:] / vx_m[self._tril_rs[1:] - 1] drange_cruise = bregA * star @@ -203,7 +238,234 @@ def compute_partials(self, inputs, J): g = vx_m[:, np.newaxis] dg_du = self._scratch_nn_x_nn - dt_dvx = 6076.1 * ((df_du[1:, ...] * g) - (dg_du[1:, ...] * f)) / g**2 + dt_dvx = ((df_du[1:, ...] * g) - (dg_du[1:, ...] * f)) / g**2 + + J['cruise_time', 'TAS_cruise'][1:] = dt_dvx[self._tril_rs[1:] - 1, self._tril_cs[1:]] + + +class E_RangeComp(om.ExplicitComponent): + """ + Compute the cruise range and time for all-electrical aircraft. + Assume the battery mass does not change during the cruise. + """ + + def initialize(self): + self.options.declare('num_nodes', types=int) + + def setup(self): + nn = self.options['num_nodes'] + if nn < 2: + raise Exception('num_nodes should be at least 2.') + + self.add_input( + 'cruise_time_initial', val=0.0, units='s', desc='time at which cruise begins' + ) + self.add_input( + 'cruise_distance_initial', + val=0.0, + units='NM', + desc='range reference at which cruise begins', + ) + self.add_input('TAS_cruise', val=0.0001 * np.ones(nn), units='NM/s', desc='true airspeed') + self.add_input( + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, + 10.0 * np.ones(nn), + units='kW*h', + desc='total energy consumption, comes from propulsion', + ) + self.add_input( + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + 0.74 * np.ones(nn), + units='kW', + desc='total energy consumption, comes from propulsion', + ) + + self.add_output( + 'cruise_time', + shape=(nn,), + units='s', + desc='time in cruise', + tags=['dymos.state_source:cruise_time'], + ) + self.add_output( + 'cruise_range', + shape=(nn,), + units='NM', + desc='cruise range', + tags=['dymos.state_source:distance'], + ) + + def setup_partials(self): + nn = self.options['num_nodes'] + + # The nonzero partials of the change in range between each two nodes (dr) wrt fuel flow and mass are + # along two diagonals. The lower diagonal contains the partials wrt the initial values of mass or fuel + # flow across each two-node section. The upper diagonal contains the partials wrt the final values of mass + # or fuel flow across each two-node section. For instance, for five nodes we have: + # + # 0 0 0 0 0 + # i f 0 0 0 + # ddR/dW = 0 i f 0 0 + # 0 0 i f 0 + # 0 0 0 i f + # + # The change of range and time at the first node is zero, and it has no dependence on the mass + # history or fuel flow setting. + # Since dR is the difference in range between two nodes, we need to accumulate it across all provided masses + # using np.cumsum. + # The partial derivative of np.cumsum is just a lower triangular matrix of ones. + # Thus, the derivative of the accumulated range (and time) will be the matrix product: + # 1 0 0 0 0 0 0 0 0 0 + # 1 1 0 0 0 i f 0 0 0 + # ddR/dW = 1 1 1 0 0 @ 0 i f 0 0 + # 1 1 1 1 0 0 0 i f 0 + # 1 1 1 1 1 0 0 0 i f + rs, cs = np.tril_indices(nn) + self._tril_rs, self._tril_cs = rs, cs + + self.declare_partials( + 'cruise_range', + [ + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + 'TAS_cruise', + ], + rows=rs, + cols=cs, + ) + self.declare_partials( + 'cruise_time', + [ + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + 'TAS_cruise', + ], + rows=rs, + cols=cs, + ) + + self.declare_partials('cruise_range', 'cruise_distance_initial', val=1.0) + self.declare_partials('cruise_time', 'cruise_time_initial', val=1.0) + + # Allocated memory so we don't have to repeatedly do it in compute_partials + # Note: since these are only used in compute_partials we don't have to worry about them supporting + # complex values under complex step. + self._d_cumsum_dx = np.tri(nn) + # Note: We could make this sparse, probably doesn't matter. + self._scratch_nn_x_nn = np.zeros((nn, nn)) + + def compute(self, inputs, outputs): + v_x = inputs['TAS_cruise'] + EE = inputs[Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED] + EP = inputs[Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL] + r0 = inputs['cruise_distance_initial'] + t0 = inputs['cruise_time_initial'] + r0 = r0[0] + t0 = t0[0] + + # All-electric version + E_1 = EE[:-1] # Initial energy across each two-node pair, kW*h + E_2 = EE[1:] # Final power energy each two-node pair + P_1 = EP[:-1] # Initial power across each two-node pair, kW + P_2 = EP[1:] # Final power across each two-node pair + + vx_1 = v_x[:-1] # Initial airspeed across each two-node pair, NM/s + vx_2 = v_x[1:] # Final airspeed across each two-node pair + vx_m = (vx_1 + vx_2) / 2 # Average airspeed across each two-node pair. + + e_breg_1 = vx_1 * E_1 * 3600 / P_1 # NM + e_breg_2 = vx_2 * E_2 * 3600 / P_2 + e_drange_cruise = e_breg_2 - e_breg_1 + + outputs['cruise_range'][0] = r0 + outputs['cruise_range'][1:] = r0 + np.cumsum(e_drange_cruise) + outputs['cruise_time'][0] = t0 + outputs['cruise_time'][1:] = t0 + np.cumsum(e_drange_cruise) / vx_m + + def compute_partials(self, inputs, J): + v_x = inputs['TAS_cruise'] + vx_1 = v_x[:-1] # Initial airspeed across each two-node pair + vx_2 = v_x[1:] # Final airspeed across each two-node pair + vx_m = (vx_1 + vx_2) / 2 # Average airspeed across each two-node pair. + + e = inputs[Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED] + # Initial energy across each two-node pair + E_1 = e[:-1] + E_2 = e[1:] # Final energy across each two-node pair + + EP = inputs[Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL] + EP_1 = EP[:-1] # Initial power across each two-node pair + EP_2 = EP[1:] # Final power across each two-node pair + + e_breg_1 = vx_1 * E_1 * 3600 / EP_1 + e_breg_2 = vx_2 * E_2 * 3600 / EP_2 + e_drange_cruise = e_breg_2 - e_breg_1 + + dBreg1_dVx1 = E_1 * 3600 / EP_1 + dBreg1_dE1 = vx_1 * 3600 / EP_1 + dBreg1_dP1 = -vx_1 * E_1 * 3600 / EP_1**2 + + dBreg2_dVx2 = E_2 * 3600 / EP_2 + dBreg2_dE2 = vx_2 * 3600 / EP_2 + dBreg2_dP2 = -vx_2 * E_2 * 3600 / EP_2**2 + + dRange_dVx1 = -dBreg1_dVx1 + dRange_dVx2 = dBreg2_dVx2 + dRange_dE1 = -dBreg1_dE1 + dRange_dE2 = dBreg2_dE2 + dRange_dP1 = -dBreg1_dP1 + dRange_dP2 = dBreg2_dP2 + + # Partials of cruise_range + + # WRT electric power + np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], dRange_dP1) + np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], dRange_dP2) + + J['cruise_range', Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL][...] = ( + self._d_cumsum_dx @ self._scratch_nn_x_nn + )[self._tril_rs, self._tril_cs] + + # WRT CUMULATIVE_ELECTRIC_ENERGY_USED: + np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], dRange_dE1) + np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], dRange_dE2) + + J['cruise_range', Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED][...] = ( + self._d_cumsum_dx @ self._scratch_nn_x_nn + )[self._tril_rs, self._tril_cs] + + # WRT TAS_cruise + np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], dRange_dVx1) + np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], dRange_dVx2) + + J['cruise_range', 'TAS_cruise'][...] = (self._d_cumsum_dx @ self._scratch_nn_x_nn)[ + self._tril_rs, self._tril_cs + ] + + # Partials of cruise_time + + # Here we need to multiply rows [1:] of the jacobian by (6076.1 / vx_m) + # But the jacobian is in a flat format in row-major order. The rows associated + # with the nonzero elements are stored in self._tril_rs. + + J['cruise_time', Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL][1:] = ( + J['cruise_range', Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL][1:] + / vx_m[self._tril_rs[1:] - 1] + ) + J['cruise_time', Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED][1:] = ( + J['cruise_range', Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED][1:] + / vx_m[self._tril_rs[1:] - 1] + ) + + f = np.cumsum(e_drange_cruise)[:, np.newaxis] + df_du = self._d_cumsum_dx @ self._scratch_nn_x_nn + + np.fill_diagonal(self._scratch_nn_x_nn[1:, :-1], 0.5) + np.fill_diagonal(self._scratch_nn_x_nn[1:, 1:], 0.5) + + g = vx_m[:, np.newaxis] + dg_du = self._scratch_nn_x_nn + + dt_dvx = ((df_du[1:, ...] * g) - (dg_du[1:, ...] * f)) / g**2 - J["cruise_time", "TAS_cruise"][1:] = \ - dt_dvx[self._tril_rs[1:] - 1, self._tril_cs[1:]] + J['cruise_time', 'TAS_cruise'][1:] = dt_dvx[self._tril_rs[1:] - 1, self._tril_cs[1:]] diff --git a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py index 6af356f29a..ee7c2cf555 100644 --- a/aviary/mission/gasp_based/ode/breguet_cruise_ode.py +++ b/aviary/mission/gasp_based/ode/breguet_cruise_ode.py @@ -1,11 +1,11 @@ import numpy as np import openmdao.api as om -from aviary.mission.gasp_based.ode.base_ode import BaseODE +from aviary.mission.gasp_based.ode.breguet_cruise_eom import E_RangeComp, RangeComp from aviary.mission.gasp_based.ode.params import ParamPort -from aviary.mission.gasp_based.ode.breguet_cruise_eom import RangeComp -from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.mission.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.subsystems.mass.mass_to_weight import MassToWeight from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase @@ -13,16 +13,159 @@ from aviary.variable_info.variables import Dynamic -class BreguetCruiseODESolution(BaseODE): - """The GASP based cruise ODE""" +class BreguetCruiseODESolution(TwoDOFODE): + """The GASP based cruise ODE.""" + + def setup(self): + nn = self.options['num_nodes'] + aviary_options = self.options['aviary_options'] + core_subsystems = self.options['core_subsystems'] + subsystem_options = self.options['subsystem_options'] + + # TODO: paramport + self.add_subsystem('params', ParamPort(), promotes=['*']) + + self.add_atmosphere(input_speed_type=SpeedType.MACH) + + self.add_subsystem( + 'calc_weight', + MassToWeight(num_nodes=nn), + promotes_inputs=['mass'], + promotes_outputs=['weight'], + ) + + prop_group = om.Group() + + kwargs = { + 'num_nodes': nn, + 'aviary_inputs': aviary_options, + 'method': 'cruise', + 'output_alpha': True, + } + for subsystem in core_subsystems: + # check if subsystem_options has entry for a subsystem of this name + if subsystem.name in subsystem_options: + kwargs.update(subsystem_options[subsystem.name]) + system = subsystem.build_mission(**kwargs) + if system is not None: + if isinstance(subsystem, PropulsionBuilderBase): + prop_group.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) + else: + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) + + self.add_external_subsystems() + + bal = om.BalanceComp( + name=Dynamic.Vehicle.Propulsion.THROTTLE, + val=np.ones(nn), + upper=1.0, + lower=0.0, + units='unitless', + lhs_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + rhs_name=Dynamic.Vehicle.DRAG, + eq_units='lbf', + ) + + prop_group.add_subsystem( + 'thrust_balance', subsys=bal, promotes_inputs=['*'], promotes_outputs=['*'] + ) + + prop_group.linear_solver = om.DirectSolver() + + prop_group.nonlinear_solver = om.NewtonSolver( + solve_subsystems=True, + maxiter=20, + rtol=1e-12, + atol=1e-12, + err_on_non_converge=False, + ) + prop_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() + + prop_group.nonlinear_solver.options['iprint'] = 2 + prop_group.linear_solver.options['iprint'] = 2 + + self.add_subsystem( + 'prop_group', subsys=prop_group, promotes_inputs=['*'], promotes_outputs=['*'] + ) + + # + # collect initial/final outputs + # + self.add_subsystem( + 'breguet_eom', + RangeComp(num_nodes=nn), + promotes_inputs=[ + ('cruise_distance_initial', 'initial_distance'), + ('cruise_time_initial', 'initial_time'), + 'mass', + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + ('TAS_cruise', Dynamic.Mission.VELOCITY), + ], + promotes_outputs=[ + ('cruise_range', Dynamic.Mission.DISTANCE), + ('cruise_time', 'time'), + ], + ) + + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.MASS, + ( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + ), + Dynamic.Vehicle.DRAG, + ], + promotes_outputs=[ + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ) + ], + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ), + Dynamic.Mission.VELOCITY_RATE, + Dynamic.Mission.VELOCITY, + ], + promotes_outputs=[(Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX)], + ) + + ParamPort.set_default_vals(self) + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=37500 * np.ones(nn), units='ft') + self.set_input_defaults('mass', val=np.linspace(171481, 171581 - 10000, nn), units='lbm') + + +class E_BreguetCruiseODESolution(TwoDOFODE): + """The GASP based cruise ODE by electrical aircraft.""" def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] aviary_options = self.options['aviary_options'] core_subsystems = self.options['core_subsystems'] # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) self.add_subsystem( name='atmosphere', @@ -31,48 +174,52 @@ def setup(self): ) self.add_subsystem( - "calc_weight", + 'calc_weight', MassToWeight(num_nodes=nn), - promotes_inputs=["mass"], - promotes_outputs=["weight"] + promotes_inputs=['mass'], + promotes_outputs=['weight'], ) prop_group = om.Group() - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'cruise', 'output_alpha': True} + kwargs = { + 'num_nodes': nn, + 'aviary_inputs': aviary_options, + 'method': 'cruise', + 'output_alpha': True, + } for subsystem in core_subsystems: system = subsystem.build_mission(**kwargs) if system is not None: if isinstance(subsystem, PropulsionBuilderBase): - prop_group.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + prop_group.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) else: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) bal = om.BalanceComp( - name=Dynamic.Mission.THROTTLE, + name=Dynamic.Vehicle.Propulsion.THROTTLE, val=np.ones(nn), upper=1.0, lower=0.0, - units="unitless", - lhs_name=Dynamic.Mission.THRUST_TOTAL, - rhs_name=Dynamic.Mission.DRAG, - eq_units="lbf", + units='unitless', + lhs_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + rhs_name=Dynamic.Vehicle.DRAG, + eq_units='lbf', ) prop_group.add_subsystem( - "thrust_balance", - subsys=bal, - promotes_inputs=['*'], - promotes_outputs=['*']) + 'thrust_balance', subsys=bal, promotes_inputs=['*'], promotes_outputs=['*'] + ) prop_group.linear_solver = om.DirectSolver() @@ -85,58 +232,66 @@ def setup(self): ) prop_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() - prop_group.nonlinear_solver.options["iprint"] = 2 - prop_group.linear_solver.options["iprint"] = 2 + prop_group.nonlinear_solver.options['iprint'] = 2 + prop_group.linear_solver.options['iprint'] = 2 self.add_subsystem( - 'prop_group', - subsys=prop_group, - promotes_inputs=['*'], - promotes_outputs=['*']) + 'prop_group', subsys=prop_group, promotes_inputs=['*'], promotes_outputs=['*'] + ) # # collect initial/final outputs # self.add_subsystem( - "breguet_eom", - RangeComp(num_nodes=nn), + 'e_breguet_eom', + E_RangeComp(num_nodes=nn), promotes_inputs=[ - ("cruise_distance_initial", "initial_distance"), - ("cruise_time_initial", "initial_time"), - "mass", - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - ("TAS_cruise", Dynamic.Mission.VELOCITY), + ('cruise_distance_initial', 'initial_distance'), + ('cruise_time_initial', 'initial_time'), + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + ('TAS_cruise', Dynamic.Mission.VELOCITY), + ], + promotes_outputs=[ + ('cruise_range', Dynamic.Mission.DISTANCE), + ('cruise_time', 'time'), ], - promotes_outputs=[("cruise_range", Dynamic.Mission.DISTANCE), - ("cruise_time", "time")], ) self.add_subsystem( name='SPECIFIC_ENERGY_RATE_EXCESS', subsys=SpecificEnergyRate(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.VELOCITY, Dynamic.Mission.MASS, - (Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.THRUST_MAX_TOTAL), - Dynamic.Mission.DRAG], - promotes_outputs=[(Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS)] + promotes_inputs=[ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.MASS, + ( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + ), + Dynamic.Vehicle.DRAG, + ], + promotes_outputs=[ + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ) + ], ) self.add_subsystem( name='ALTITUDE_RATE_MAX', subsys=AltitudeRate(num_nodes=nn), promotes_inputs=[ - (Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS), + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ), Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.VELOCITY], - promotes_outputs=[ - (Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.ALTITUDE_RATE_MAX)]) + Dynamic.Mission.VELOCITY, + ], + promotes_outputs=[(Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX)], + ) ParamPort.set_default_vals(self) - self.set_input_defaults( - Dynamic.Mission.ALTITUDE, - val=37500 * np.ones(nn), - units="ft") - self.set_input_defaults("mass", val=np.linspace( - 171481, 171581 - 10000, nn), units="lbm") + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=37500 * np.ones(nn), units='ft') + self.set_input_defaults('mass', val=np.linspace(171481, 171581 - 10000, nn), units='lbm') diff --git a/aviary/mission/gasp_based/ode/climb_eom.py b/aviary/mission/gasp_based/ode/climb_eom.py index 63120bce74..d1c2922e0f 100644 --- a/aviary/mission/gasp_based/ode/climb_eom.py +++ b/aviary/mission/gasp_based/ode/climb_eom.py @@ -14,140 +14,160 @@ class ClimbRates(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) self.add_input( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="ft/s", - desc="true air speed", + units='ft/s', + desc='true air speed', ) - self.add_input(Dynamic.Mission.THRUST_TOTAL, val=np.zeros(nn), - units="lbf", desc="net thrust") self.add_input( - Dynamic.Mission.DRAG, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.zeros(nn), - units="lbf", - desc="net drag on aircraft") + units='lbf', + desc='net thrust', + ) + self.add_input( + Dynamic.Vehicle.DRAG, val=np.zeros(nn), units='lbf', desc='net drag on aircraft' + ) self.add_input( - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, val=np.zeros(nn), - units="lbm", - desc="mass of aircraft", + units='lbm', + desc='mass of aircraft', ) self.add_output( Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), - units="ft/s", - desc="rate of change of altitude", + units='ft/s', + desc='rate of change of altitude', ) self.add_output( Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), - units="ft/s", - desc="rate of change of horizontal distance covered", + units='ft/s', + desc='rate of change of horizontal distance covered', ) self.add_output( - "required_lift", + 'required_lift', val=np.zeros(nn), - units="lbf", - desc="lift required in order to maintain calculated flight path angle", + units='lbf', + desc='lift required in order to maintain calculated flight path angle', ) self.add_output( Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), - units="rad", - desc="flight path angle", + units='rad', + desc='flight path angle', ) - self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, - [Dynamic.Mission.VELOCITY, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, - Dynamic.Mission.MASS], - rows=arange, - cols=arange) + self.declare_partials( + Dynamic.Mission.ALTITUDE_RATE, + [ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + ], + rows=arange, + cols=arange, + ) self.declare_partials( Dynamic.Mission.DISTANCE_RATE, - [Dynamic.Mission.VELOCITY, Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, Dynamic.Mission.MASS], + [ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + 'required_lift', + [ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + Dynamic.Mission.FLIGHT_PATH_ANGLE, + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + ], rows=arange, cols=arange, ) - self.declare_partials("required_lift", - [Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], - rows=arange, - cols=arange) - self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE, - [Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, - Dynamic.Mission.MASS], - rows=arange, - cols=arange) def compute(self, inputs, outputs): - TAS = inputs[Dynamic.Mission.VELOCITY] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM gamma = np.arcsin((thrust - drag) / weight) outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) - outputs["required_lift"] = weight * np.cos(gamma) + outputs['required_lift'] = weight * np.cos(gamma) outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] = gamma def compute_partials(self, inputs, J): - TAS = inputs[Dynamic.Mission.VELOCITY] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM gamma = np.arcsin((thrust - drag) / weight) dGamma_dThrust = (1 - ((thrust - drag) / weight) ** 2) ** (-0.5) / weight dGamma_dDrag = (1 - ((thrust - drag) / weight) ** 2) ** (-0.5) / (-weight) dGamma_dWeight = ( - (1 - ((thrust - drag) / weight) ** 2) ** (-0.5) - * (drag - thrust) - / weight**2 + (1 - ((thrust - drag) / weight) ** 2) ** (-0.5) * (drag - thrust) / weight**2 ) J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = np.sin(gamma) - J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.THRUST_TOTAL] = TAS * \ - np.cos(gamma) * dGamma_dThrust - J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.DRAG] = TAS * \ - np.cos(gamma) * dGamma_dDrag - J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.MASS] = \ + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + TAS * np.cos(gamma) * dGamma_dThrust + ) + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Vehicle.DRAG] = TAS * np.cos(gamma) * dGamma_dDrag + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Vehicle.MASS] = ( TAS * np.cos(gamma) * dGamma_dWeight * GRAV_ENGLISH_LBM + ) J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = np.cos(gamma) - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.THRUST_TOTAL] = - \ - TAS * np.sin(gamma) * dGamma_dThrust - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.DRAG] = - \ - TAS * np.sin(gamma) * dGamma_dDrag - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.MASS] = \ + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + -TAS * np.sin(gamma) * dGamma_dThrust + ) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Vehicle.DRAG] = -TAS * np.sin(gamma) * dGamma_dDrag + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Vehicle.MASS] = ( -TAS * np.sin(gamma) * dGamma_dWeight * GRAV_ENGLISH_LBM + ) - J["required_lift", Dynamic.Mission.MASS] = ( + J['required_lift', Dynamic.Vehicle.MASS] = ( np.cos(gamma) - weight * np.sin(gamma) * dGamma_dWeight ) * GRAV_ENGLISH_LBM - J["required_lift", Dynamic.Mission.THRUST_TOTAL] = - \ - weight * np.sin(gamma) * dGamma_dThrust - J["required_lift", Dynamic.Mission.DRAG] = -weight * np.sin(gamma) * dGamma_dDrag - - J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.THRUST_TOTAL] = dGamma_dThrust - J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.DRAG] = dGamma_dDrag - J[Dynamic.Mission.FLIGHT_PATH_ANGLE, - Dynamic.Mission.MASS] = dGamma_dWeight * GRAV_ENGLISH_LBM + J['required_lift', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + -weight * np.sin(gamma) * dGamma_dThrust + ) + J['required_lift', Dynamic.Vehicle.DRAG] = -weight * np.sin(gamma) * dGamma_dDrag + + J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + dGamma_dThrust + ) + J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Vehicle.DRAG] = dGamma_dDrag + J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Vehicle.MASS] = ( + dGamma_dWeight * GRAV_ENGLISH_LBM + ) diff --git a/aviary/mission/gasp_based/ode/climb_ode.py b/aviary/mission/gasp_based/ode/climb_ode.py index 42c233736d..fb63453776 100644 --- a/aviary/mission/gasp_based/ode/climb_ode.py +++ b/aviary/mission/gasp_based/ode/climb_ode.py @@ -1,20 +1,19 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.subsystems.atmosphere.flight_conditions import FlightConditions -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.climb_eom import ClimbRates from aviary.mission.gasp_based.ode.constraints.flight_constraints import FlightConstraints from aviary.mission.gasp_based.ode.constraints.speed_constraints import SpeedConstraints from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase -from aviary.variable_info.enums import AnalysisScheme, AlphaModes, SpeedType -from aviary.variable_info.variables import Dynamic -from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs +from aviary.subsystems.atmosphere.atmosphere import Atmosphere +from aviary.subsystems.atmosphere.flight_conditions import FlightConditions +from aviary.variable_info.enums import AlphaModes, SpeedType +from aviary.variable_info.variables import Aircraft, Dynamic -class ClimbODE(BaseODE): +class ClimbODE(TwoDOFODE): """ODE for quasi-steady climb. This ODE has a ``KSComp`` which allows for the switching of obeying an EAS @@ -23,198 +22,201 @@ class ClimbODE(BaseODE): def initialize(self): super().initialize() - self.options.declare("input_speed_type", default=SpeedType.EAS, types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number") - self.options.declare("alt_trigger_units", default='ft', - desc='The units that the altitude trigger is provided in') - self.options.declare("speed_trigger_units", default='kn', - desc='The units that the speed trigger is provided in.') - self.options.declare("input_speed_type", default=SpeedType.EAS, types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number") - self.options.declare("EAS_target", desc="target climbing EAS in knots") self.options.declare( - "mach_cruise", default=0, desc="targeted cruise mach number" + 'input_speed_type', + default=SpeedType.EAS, + types=SpeedType, + desc='Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number', ) + self.options.declare( + 'alt_trigger_units', + default='ft', + desc='The units that the altitude trigger is provided in', + ) + self.options.declare( + 'speed_trigger_units', + default='kn', + desc='The units that the speed trigger is provided in.', + ) + self.options.declare( + 'input_speed_type', + default=SpeedType.EAS, + types=SpeedType, + desc='Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number', + ) + self.options.declare('EAS_target', desc='target climbing EAS in knots') + self.options.declare('mach_cruise', default=0, desc='targeted cruise Mach number') def setup(self): self.options['auto_order'] = True - nn = self.options["num_nodes"] - analysis_scheme = self.options["analysis_scheme"] + nn = self.options['num_nodes'] aviary_options = self.options['aviary_options'] core_subsystems = self.options['core_subsystems'] - input_speed_type = self.options["input_speed_type"] + subsystem_options = self.options['subsystem_options'] + input_speed_type = self.options['input_speed_type'] if input_speed_type is SpeedType.EAS: - speed_inputs = ["EAS"] - speed_outputs = ["mach", Dynamic.Mission.VELOCITY] + speed_inputs = ['EAS'] + speed_outputs = ['mach', Dynamic.Mission.VELOCITY] elif input_speed_type is SpeedType.MACH: - speed_inputs = ["mach"] - speed_outputs = ["EAS", Dynamic.Mission.VELOCITY] - - if analysis_scheme is AnalysisScheme.SHOOTING: - add_SGM_required_inputs(self, { - 't_curr': {'units': 's'}, - Dynamic.Mission.DISTANCE: {'units': 'ft'}, - 'alt_trigger': {'units': self.options['alt_trigger_units'], 'val': 10e3}, - 'speed_trigger': {'units': self.options['speed_trigger_units'], 'val': 100}, - }) + speed_inputs = ['mach'] + speed_outputs = ['EAS', Dynamic.Mission.VELOCITY] # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) self.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=nn), promotes_inputs=[Dynamic.Mission.ALTITUDE], promotes_outputs=[ - Dynamic.Mission.DENSITY, - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, - "viscosity", + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + 'viscosity', ], ) - if analysis_scheme is AnalysisScheme.COLLOCATION: - EAS_target = self.options["EAS_target"] - mach_cruise = self.options["mach_cruise"] - - mach_balance_group = self.add_subsystem( - "mach_balance_group", subsys=om.Group(), promotes=["*"] - ) - - mach_balance_group.nonlinear_solver = om.NewtonSolver() - mach_balance_group.nonlinear_solver.options["solve_subsystems"] = True - mach_balance_group.nonlinear_solver.options["iprint"] = 0 - mach_balance_group.nonlinear_solver.options["atol"] = 1e-7 - mach_balance_group.nonlinear_solver.options["rtol"] = 1e-7 - mach_balance_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() - mach_balance_group.linear_solver = om.DirectSolver(assemble_jac=True) - mach_balance_group.add_subsystem( - "speeds", - SpeedConstraints( - num_nodes=nn, EAS_target=EAS_target, mach_cruise=mach_cruise - ), - promotes_inputs=["EAS", Dynamic.Mission.MACH], - promotes_outputs=["speed_constraint"], - ) - mach_balance_group.add_subsystem( - "ks", - om.KSComp(width=2, vec_size=nn, units="unitless"), - promotes_inputs=[("g", "speed_constraint")], - promotes_outputs=["KS"], - ) - speed_bal = om.BalanceComp( - name="EAS", - val=EAS_target * np.ones(nn), - units="kn", - lhs_name="KS", - rhs_val=0.0, - eq_units='unitless', - upper=350, - lower=0, - ) - mach_balance_group.add_subsystem( - "speed_bal", - speed_bal, - promotes_inputs=["KS"], - promotes_outputs=["EAS"], - ) - - lift_balance_group = self.add_subsystem( - "lift_balance_group", subsys=om.Group(), promotes=["*"] - ) - flight_condition_group = mach_balance_group - - elif analysis_scheme is AnalysisScheme.SHOOTING: - lift_balance_group = self - flight_condition_group = self + EAS_target = self.options['EAS_target'] + mach_cruise = self.options['mach_cruise'] + + mach_balance_group = self.add_subsystem( + 'mach_balance_group', subsys=om.Group(), promotes=['*'] + ) + + mach_balance_group.nonlinear_solver = om.NewtonSolver() + mach_balance_group.nonlinear_solver.options['solve_subsystems'] = True + mach_balance_group.nonlinear_solver.options['iprint'] = 0 + mach_balance_group.nonlinear_solver.options['atol'] = 1e-7 + mach_balance_group.nonlinear_solver.options['rtol'] = 1e-7 + mach_balance_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() + mach_balance_group.linear_solver = om.DirectSolver(assemble_jac=True) + mach_balance_group.add_subsystem( + 'speeds', + SpeedConstraints(num_nodes=nn, EAS_target=EAS_target, mach_cruise=mach_cruise), + promotes_inputs=['EAS', Dynamic.Atmosphere.MACH], + promotes_outputs=['speed_constraint'], + ) + mach_balance_group.add_subsystem( + 'ks', + om.KSComp(width=2, vec_size=nn, units='unitless'), + promotes_inputs=[('g', 'speed_constraint')], + promotes_outputs=['KS'], + ) + speed_bal = om.BalanceComp( + name='EAS', + val=EAS_target * np.ones(nn), + units='kn', + lhs_name='KS', + rhs_val=0.0, + eq_units='unitless', + upper=350, + lower=0, + ) + mach_balance_group.add_subsystem( + 'speed_bal', + speed_bal, + promotes_inputs=['KS'], + promotes_outputs=['EAS'], + ) + + lift_balance_group = self.add_subsystem( + 'lift_balance_group', subsys=om.Group(), promotes=['*'] + ) + flight_condition_group = mach_balance_group flight_condition_group.add_subsystem( name='flight_conditions', subsys=FlightConditions(num_nodes=nn, input_speed_type=input_speed_type), - promotes_inputs=[Dynamic.Mission.DENSITY, Dynamic.Mission.SPEED_OF_SOUND] + promotes_inputs=[ + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + ] + speed_inputs, - promotes_outputs=[Dynamic.Mission.DYNAMIC_PRESSURE] + speed_outputs, + promotes_outputs=[Dynamic.Atmosphere.DYNAMIC_PRESSURE] + speed_outputs, ) - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'cruise'} + kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, 'method': 'cruise'} # collect the propulsion group names for later use with for subsystem in core_subsystems: + # check if subsystem_options has entry for a subsystem of this name + if subsystem.name in subsystem_options: + kwargs.update(subsystem_options[subsystem.name]) system = subsystem.build_mission(**kwargs) if system is not None: if isinstance(subsystem, AerodynamicsBuilderBase): - lift_balance_group.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + lift_balance_group.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) else: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) - # maybe replace this with the solver in AddAlphaControl? + self.add_external_subsystems() + + # maybe replace this with the solver in add_alpha_control? lift_balance_group.nonlinear_solver = om.NewtonSolver() - lift_balance_group.nonlinear_solver.options["solve_subsystems"] = True - lift_balance_group.nonlinear_solver.options["iprint"] = 0 - lift_balance_group.nonlinear_solver.options["atol"] = 1e-7 - lift_balance_group.nonlinear_solver.options["rtol"] = 1e-7 + lift_balance_group.nonlinear_solver.options['solve_subsystems'] = True + lift_balance_group.nonlinear_solver.options['iprint'] = 0 + lift_balance_group.nonlinear_solver.options['atol'] = 1e-7 + lift_balance_group.nonlinear_solver.options['rtol'] = 1e-7 lift_balance_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() lift_balance_group.linear_solver = om.DirectSolver(assemble_jac=True) lift_balance_group.add_subsystem( - "climb_eom", + 'climb_eom', ClimbRates(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Dynamic.Mission.VELOCITY, - Dynamic.Mission.DRAG, - Dynamic.Mission.THRUST_TOTAL + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, ], promotes_outputs=[ Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.DISTANCE_RATE, - "required_lift", + 'required_lift', Dynamic.Mission.FLIGHT_PATH_ANGLE, ], ) - self.AddAlphaControl( + self.add_alpha_control( alpha_group=lift_balance_group, alpha_mode=AlphaModes.REQUIRED_LIFT, add_default_solver=False, - num_nodes=nn) + num_nodes=nn, + ) self.add_subsystem( - "constraints", + 'constraints', FlightConstraints(num_nodes=nn), promotes_inputs=[ - "alpha", - Dynamic.Mission.DENSITY, - "CL_max", + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Atmosphere.DENSITY, + 'CL_max', Dynamic.Mission.FLIGHT_PATH_ANGLE, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Dynamic.Mission.VELOCITY, ] - + ["aircraft:*"], - promotes_outputs=["theta", "TAS_violation"], + + ['aircraft:*'], + promotes_outputs=['theta', 'TAS_violation'], ) # the last two subsystems will also be used for constraints self.add_excess_rate_comps(nn) ParamPort.set_default_vals(self) - self.set_input_defaults("CL_max", val=5 * np.ones(nn), units="unitless") - self.set_input_defaults(Dynamic.Mission.ALTITUDE, - val=500 * np.ones(nn), units='ft') - self.set_input_defaults(Dynamic.Mission.MASS, - val=174000 * np.ones(nn), units='lbm') - self.set_input_defaults(Dynamic.Mission.MACH, - val=0 * np.ones(nn), units="unitless") - - from aviary.variable_info.variables import Aircraft - self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units="ft**2") + self.set_input_defaults('CL_max', val=5 * np.ones(nn), units='unitless') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=500 * np.ones(nn), units='ft') + self.set_input_defaults(Dynamic.Vehicle.MASS, val=174000 * np.ones(nn), units='lbm') + self.set_input_defaults(Dynamic.Atmosphere.MACH, val=0 * np.ones(nn), units='unitless') + + self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units='ft**2') diff --git a/aviary/mission/gasp_based/ode/constraints/flight_constraints.py b/aviary/mission/gasp_based/ode/constraints/flight_constraints.py index 7cc0039e1a..076ebab6a8 100644 --- a/aviary/mission/gasp_based/ode/constraints/flight_constraints.py +++ b/aviary/mission/gasp_based/ode/constraints/flight_constraints.py @@ -7,7 +7,6 @@ class FlightConstraints(om.ExplicitComponent): - """ Compute the minimum TAS (defined as the stall speed multiplied by a safety factor of 1.1). @@ -18,196 +17,191 @@ class FlightConstraints(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) self.add_input( - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, val=np.ones(nn), - units="lbm", - desc="mass of aircraft", + units='lbm', + desc='mass of aircraft', ) add_aviary_input(self, Aircraft.Wing.AREA, val=2) add_aviary_input( self, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=np.ones(nn), - units="slug/ft**3", - desc="density of air", + units='slug/ft**3', + desc='density of air', ) self.add_input( - "CL_max", + 'CL_max', val=np.ones(nn), - units="unitless", - desc="maximum lift coefficient", + units='unitless', + desc='maximum lift coefficient', ) self.add_input( Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), - units="rad", - desc="flight path angle", + units='rad', + desc='flight path angle', ) - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=1.0, units="rad") + add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=1.0, units='rad') self.add_input( - "alpha", + Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.ones(nn), - units="rad", - desc="angle of attack", + units='rad', + desc='angle of attack', ) add_aviary_input( self, Dynamic.Mission.VELOCITY, val=np.ones(nn), - units="ft/s", - desc="true airspeed", + units='ft/s', + desc='true airspeed', ) self.add_output( - "theta", + 'theta', val=np.ones(nn), - units="rad", - desc="pitch angle of fuselage", + units='rad', + desc='pitch angle of fuselage', ) self.add_output( - "TAS_violation", + 'TAS_violation', val=np.ones(nn), - units="ft/s", - desc="value to show if minimum TAS constraint is being violated. Negative or" - " zero if constraint is satisfied.", + units='ft/s', + desc='value to show if minimum TAS constraint is being violated. Negative or' + ' zero if constraint is satisfied.', ) - self.add_output("TAS_min", val=np.zeros(nn), units="ft/s") + self.add_output('TAS_min', val=np.zeros(nn), units='ft/s') self.declare_partials( - "theta", [Dynamic.Mission.FLIGHT_PATH_ANGLE, "alpha"], rows=arange, cols=arange) + 'theta', + [Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Vehicle.ANGLE_OF_ATTACK], + rows=arange, + cols=arange, + ) self.declare_partials( - "theta", + 'theta', [ Aircraft.Wing.INCIDENCE, ], ) self.declare_partials( - "TAS_violation", + 'TAS_violation', [ - Dynamic.Mission.MASS, - Dynamic.Mission.DENSITY, - "CL_max", + Dynamic.Vehicle.MASS, + Dynamic.Atmosphere.DENSITY, + 'CL_max', Dynamic.Mission.VELOCITY, ], rows=arange, cols=arange, ) self.declare_partials( - "TAS_violation", + 'TAS_violation', [ Aircraft.Wing.AREA, ], ) self.declare_partials( - "TAS_min", - [Dynamic.Mission.MASS, Dynamic.Mission.DENSITY, "CL_max"], + 'TAS_min', + [Dynamic.Vehicle.MASS, Dynamic.Atmosphere.DENSITY, 'CL_max'], rows=arange, cols=arange, ) self.declare_partials( - "TAS_min", + 'TAS_min', [ Aircraft.Wing.AREA, ], ) def compute(self, inputs, outputs): - - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM wing_area = inputs[Aircraft.Wing.AREA] - rho = inputs[Dynamic.Mission.DENSITY] - CL_max = inputs["CL_max"] + rho = inputs[Dynamic.Atmosphere.DENSITY] + CL_max = inputs['CL_max'] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] TAS = inputs[Dynamic.Mission.VELOCITY] V_stall = (2 * weight / (wing_area * rho * CL_max)) ** 0.5 # stall speed TAS_min = ( 1.1 * V_stall - ) # minimum true airspeed accross each node, based on stall speed and safety margin - outputs["TAS_min"] = TAS_min + ) # minimum true airspeed across each node, based on stall speed and safety margin + outputs['TAS_min'] = TAS_min - outputs["theta"] = gamma - i_wing + alpha - outputs["TAS_violation"] = TAS_min - TAS + outputs['theta'] = gamma - i_wing + alpha + outputs['TAS_violation'] = TAS_min - TAS def compute_partials(self, inputs, J): - - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM wing_area = inputs[Aircraft.Wing.AREA] - rho = inputs[Dynamic.Mission.DENSITY] - CL_max = inputs["CL_max"] - gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] - i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] - TAS = inputs[Dynamic.Mission.VELOCITY] + rho = inputs[Dynamic.Atmosphere.DENSITY] + CL_max = inputs['CL_max'] - J["theta", Dynamic.Mission.FLIGHT_PATH_ANGLE] = 1 - J["theta", "alpha"] = 1 - J["theta", Aircraft.Wing.INCIDENCE] = -1 + J['theta', Dynamic.Mission.FLIGHT_PATH_ANGLE] = 1 + J['theta', Dynamic.Vehicle.ANGLE_OF_ATTACK] = 1 + J['theta', Aircraft.Wing.INCIDENCE] = -1 - J["TAS_violation", Dynamic.Mission.MASS] = ( - 1.1 * 0.5 * (2 / (wing_area * rho * CL_max)) ** 0.5 * - weight ** (-0.5) * GRAV_ENGLISH_LBM + J['TAS_violation', Dynamic.Vehicle.MASS] = ( + 1.1 + * 0.5 + * (2 / (wing_area * rho * CL_max)) ** 0.5 + * weight ** (-0.5) + * GRAV_ENGLISH_LBM ) - J["TAS_violation", Dynamic.Mission.DENSITY] = ( + J['TAS_violation', Dynamic.Atmosphere.DENSITY] = ( 1.1 * (2 * weight / (wing_area * CL_max)) ** 0.5 * (-0.5) * rho ** (-1.5) ) - J["TAS_violation", "CL_max"] = ( + J['TAS_violation', 'CL_max'] = ( 1.1 * (2 * weight / (wing_area * rho)) ** 0.5 * (-0.5) * CL_max ** (-1.5) ) - J["TAS_violation", Dynamic.Mission.VELOCITY] = -1 - J["TAS_violation", Aircraft.Wing.AREA] = ( + J['TAS_violation', Dynamic.Mission.VELOCITY] = -1 + J['TAS_violation', Aircraft.Wing.AREA] = ( 1.1 * (2 * weight / (rho * CL_max)) ** 0.5 * (-0.5) * wing_area ** (-1.5) ) - J["TAS_min", Dynamic.Mission.MASS] = 1.1 * ( - 0.5 * (2 / (wing_area * rho * CL_max)) ** 0.5 * - weight ** (-0.5) * GRAV_ENGLISH_LBM + J['TAS_min', Dynamic.Vehicle.MASS] = 1.1 * ( + 0.5 * (2 / (wing_area * rho * CL_max)) ** 0.5 * weight ** (-0.5) * GRAV_ENGLISH_LBM ) - J["TAS_min", Dynamic.Mission.DENSITY] = 1.1 * ( + J['TAS_min', Dynamic.Atmosphere.DENSITY] = 1.1 * ( (2 * weight / (wing_area * CL_max)) ** 0.5 * (-0.5) * rho ** (-1.5) ) - J["TAS_min", "CL_max"] = 1.1 * ( + J['TAS_min', 'CL_max'] = 1.1 * ( (2 * weight / (wing_area * rho)) ** 0.5 * (-0.5) * CL_max ** (-1.5) ) - J["TAS_min", Aircraft.Wing.AREA] = 1.1 * ( + J['TAS_min', Aircraft.Wing.AREA] = 1.1 * ( (2 * weight / (rho * CL_max)) ** 0.5 * (-0.5) * wing_area ** (-1.5) ) class ClimbAtTopOfClimb(om.ExplicitComponent): - """ - This class is not used nor tested. - """ + """This class is not used nor tested.""" def setup(self): - self.add_input(Dynamic.Mission.VELOCITY, units="ft/s", val=-200) - self.add_input( - Dynamic.Mission.FLIGHT_PATH_ANGLE, units="rad", val=0.) - self.add_output("ROC", units="ft/s") - self.declare_partials("*", "*") + self.add_input(Dynamic.Mission.VELOCITY, units='ft/s', val=-200) + self.add_input(Dynamic.Mission.FLIGHT_PATH_ANGLE, units='rad', val=0.0) + self.add_output('ROC', units='ft/s') + self.declare_partials('*', '*') def compute(self, inputs, outputs): - outputs["ROC"] = inputs[Dynamic.Mission.VELOCITY] * np.sin( + outputs['ROC'] = inputs[Dynamic.Mission.VELOCITY] * np.sin( inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] ) def compute_partials(self, inputs, J): - J["ROC", Dynamic.Mission.VELOCITY] = np.sin( + J['ROC', Dynamic.Mission.VELOCITY] = np.sin(inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE]) + J['ROC', Dynamic.Mission.FLIGHT_PATH_ANGLE] = inputs[Dynamic.Mission.VELOCITY] * np.cos( inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] ) - J["ROC", Dynamic.Mission.FLIGHT_PATH_ANGLE] = inputs[ - Dynamic.Mission.VELOCITY - ] * np.cos(inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE]) diff --git a/aviary/mission/gasp_based/ode/constraints/speed_constraints.py b/aviary/mission/gasp_based/ode/constraints/speed_constraints.py index d3540a45ce..7c8d1826ff 100644 --- a/aviary/mission/gasp_based/ode/constraints/speed_constraints.py +++ b/aviary/mission/gasp_based/ode/constraints/speed_constraints.py @@ -5,66 +5,58 @@ class SpeedConstraints(om.ExplicitComponent): - """ - Compute speed constraint to be driven to zero in order to control speed - """ + """Compute speed constraint to be driven to zero in order to control speed.""" def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) self.options.declare( - "EAS_target", + 'EAS_target', default=0, - desc="targeted equivalent airspeed in knots assuming mach constraint is" - " satisfied", - ) - self.options.declare( - "mach_cruise", default=0, desc="targeted cruise mach number" + desc='targeted equivalent airspeed in knots assuming mach constraint is satisfied', ) + self.options.declare('mach_cruise', default=0, desc='targeted cruise Mach number') def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) self.add_input( - "EAS", + 'EAS', val=np.ones(nn), - units="kn", - desc="equivalent airspeed", + units='kn', + desc='equivalent airspeed', ) self.add_input( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, val=np.ones(nn), - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) self.add_output( - "speed_constraint", + 'speed_constraint', val=np.ones((nn, 2)), - units="unitless", - desc="constraint to be driven to zero in order to control speed", + units='unitless', + desc='constraint to be driven to zero in order to control speed', ) + self.declare_partials('speed_constraint', 'EAS', rows=arange * 2, cols=arange, val=1.0) self.declare_partials( - "speed_constraint", "EAS", rows=arange * 2, cols=arange, val=1.0 - ) - self.declare_partials( - "speed_constraint", - Dynamic.Mission.MACH, + 'speed_constraint', + Dynamic.Atmosphere.MACH, rows=arange * 2 + 1, cols=arange, - val=self.options["EAS_target"], + val=self.options['EAS_target'], ) def compute(self, inputs, outputs): - - EAS = inputs["EAS"] - EAS_target = self.options["EAS_target"] - mach = inputs[Dynamic.Mission.MACH] - mach_cruise = self.options["mach_cruise"] + EAS = inputs['EAS'] + EAS_target = self.options['EAS_target'] + mach = inputs[Dynamic.Atmosphere.MACH] + mach_cruise = self.options['mach_cruise'] EAS_constraint = EAS - EAS_target EAS_constraint = EAS_constraint[:, np.newaxis] mach_constraint = EAS_target * (mach - mach_cruise) mach_constraint = mach_constraint[:, np.newaxis] - outputs["speed_constraint"] = np.hstack((EAS_constraint, mach_constraint)) + outputs['speed_constraint'] = np.hstack((EAS_constraint, mach_constraint)) diff --git a/aviary/mission/gasp_based/ode/constraints/test/test_climb_constraints.py b/aviary/mission/gasp_based/ode/constraints/test/test_climb_constraints.py index d2ff00e0bc..c6376f64d7 100644 --- a/aviary/mission/gasp_based/ode/constraints/test/test_climb_constraints.py +++ b/aviary/mission/gasp_based/ode/constraints/test/test_climb_constraints.py @@ -2,85 +2,75 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.mission.gasp_based.ode.constraints.speed_constraints import \ - SpeedConstraints +from aviary.mission.gasp_based.ode.constraints.speed_constraints import SpeedConstraints from aviary.variable_info.variables import Dynamic class SpeedConstraintTestCase1(unittest.TestCase): - """ - Test speed constraint at MACH = 0.6 with targeted MACH at 0.8 - """ + """Test speed constraint at MACH = 0.6 with targeted MACH at 0.8.""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "group", + 'group', SpeedConstraints(num_nodes=3, EAS_target=229, mach_cruise=0.8), - promotes=["*"], + promotes=['*'], ) - self.prob.model.set_input_defaults("EAS", np.array([229, 229, 229]), units="kn") + self.prob.model.set_input_defaults('EAS', np.array([229, 229, 229]), units='kn') self.prob.model.set_input_defaults( - Dynamic.Mission.MACH, np.array([0.6, 0.6, 0.6]), units="unitless" + Dynamic.Atmosphere.MACH, np.array([0.6, 0.6, 0.6]), units='unitless' ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob["speed_constraint"], + self.prob['speed_constraint'], np.array([[0, -45.8], [0, -45.8], [0, -45.8]]), tol, ) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class SpeedConstraintTestCase2(unittest.TestCase): - """ - Test speed constraint at MACH = 0.9 with targeted Mach at 0.8 - """ + """Test speed constraint at MACH = 0.9 with targeted Mach at 0.8.""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "group", + 'group', SpeedConstraints(num_nodes=3, EAS_target=229, mach_cruise=0.8), - promotes=["*"], + promotes=['*'], ) - self.prob.model.set_input_defaults("EAS", np.array([229, 229, 229]), units="kn") + self.prob.model.set_input_defaults('EAS', np.array([229, 229, 229]), units='kn') self.prob.model.set_input_defaults( - Dynamic.Mission.MACH, np.array([0.9, 0.9, 0.9]), units="unitless" + Dynamic.Atmosphere.MACH, np.array([0.9, 0.9, 0.9]), units='unitless' ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob["speed_constraint"], + self.prob['speed_constraint'], np.array([[0, 22.9], [0, 22.9], [0, 22.9]]), tol, ) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/constraints/test/test_flight_constraints.py b/aviary/mission/gasp_based/ode/constraints/test/test_flight_constraints.py index 1992c3407b..7ccd81bf95 100644 --- a/aviary/mission/gasp_based/ode/constraints/test/test_flight_constraints.py +++ b/aviary/mission/gasp_based/ode/constraints/test/test_flight_constraints.py @@ -2,41 +2,35 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.mission.gasp_based.ode.constraints.flight_constraints import \ - FlightConstraints +from aviary.mission.gasp_based.ode.constraints.flight_constraints import FlightConstraints from aviary.variable_info.variables import Aircraft, Dynamic class FlightConstraintTestCase(unittest.TestCase): - """ - Test minimum TAS computation - """ + """Test minimum TAS computation.""" def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", FlightConstraints(num_nodes=2), promotes=["*"] - ) + self.prob.model.add_subsystem('group', FlightConstraints(num_nodes=2), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([174878.0, 174878.0]), units="lbm" + Dynamic.Vehicle.MASS, np.array([174878.0, 174878.0]), units='lbm' ) - self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units="ft**2") + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units='ft**2') self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, 0.0023081 * np.ones(2), units="slug/ft**3" + Dynamic.Atmosphere.DENSITY, 0.0023081 * np.ones(2), units='slug/ft**3' ) + self.prob.model.set_input_defaults('CL_max', 1.2596 * np.ones(2), units='unitless') self.prob.model.set_input_defaults( - "CL_max", 1.2596 * np.ones(2), units="unitless") - self.prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, 7.76 * np.ones(2), units="deg") - self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, 0.0, units="deg") - self.prob.model.set_input_defaults("alpha", 5.19 * np.ones(2), units="deg") + Dynamic.Mission.FLIGHT_PATH_ANGLE, 7.76 * np.ones(2), units='deg' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, 0.0, units='deg') self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, 252 * np.ones(2), units="kn" + Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.19 * np.ones(2), units='deg' ) + self.prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, 252 * np.ones(2), units='kn') self.prob.setup(check=False, force_alloc_complex=True) @@ -44,43 +38,37 @@ def test_case1(self): tol = 1e-6 self.prob.run_model() + assert_near_equal(self.prob['theta'], np.array([0.2260201, 0.2260201]), tol) # from GASP assert_near_equal( - self.prob["theta"], np.array([0.2260201, 0.2260201]), tol - ) # from GASP - assert_near_equal( - self.prob["TAS_violation"], np.array([-99.39848181, -99.39848181]), tol + self.prob['TAS_violation'], np.array([-99.39848181, -99.39848181]), tol ) # note: output value isn't in GASP - assert_near_equal( - self.prob["TAS_min"], np.array([325.9296, 325.9296]), tol - ) + assert_near_equal(self.prob['TAS_min'], np.array([325.9296, 325.9296]), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-11, rtol=1e-12) class FlightConstraintTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.constraints.flight_constraints as constraints + constraints.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.constraints.flight_constraints as constraints + constraints.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem( - "group", FlightConstraints(num_nodes=2), promotes=["*"] - ) + prob.model.add_subsystem('group', FlightConstraints(num_nodes=2), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/descent_eom.py b/aviary/mission/gasp_based/ode/descent_eom.py index 37cdc2287d..bb8f88e8e0 100644 --- a/aviary/mission/gasp_based/ode/descent_eom.py +++ b/aviary/mission/gasp_based/ode/descent_eom.py @@ -9,145 +9,165 @@ class DescentRates(om.ExplicitComponent): """Descent rate equations of motion.""" def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) self.add_input( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="ft/s", - desc="true air speed", + units='ft/s', + desc='true air speed', ) - self.add_input(Dynamic.Mission.THRUST_TOTAL, val=np.zeros(nn), - units="lbf", desc="net thrust") self.add_input( - Dynamic.Mission.DRAG, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.zeros(nn), - units="lbf", - desc="net drag on aircraft") + units='lbf', + desc='net thrust', + ) + self.add_input( + Dynamic.Vehicle.DRAG, val=np.zeros(nn), units='lbf', desc='net drag on aircraft' + ) self.add_input( - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, val=np.zeros(nn), - units="lbm", - desc="mass of aircraft", + units='lbm', + desc='mass of aircraft', ) self.add_input( - "alpha", + Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.ones(nn), - units="rad", - desc="angle of attack of aircraft", + units='rad', + desc='angle of attack of aircraft', ) self.add_output( Dynamic.Mission.ALTITUDE_RATE, val=np.zeros(nn), - units="ft/s", - desc="rate of change of altitude", + units='ft/s', + desc='rate of change of altitude', ) self.add_output( Dynamic.Mission.DISTANCE_RATE, val=np.zeros(nn), - units="ft/s", - desc="rate of change of horizontal distance covered", + units='ft/s', + desc='rate of change of horizontal distance covered', ) self.add_output( - "required_lift", + 'required_lift', val=np.zeros(nn), - units="lbf", - desc="lift required in order to maintain calculated flight path angle", + units='lbf', + desc='lift required in order to maintain calculated flight path angle', ) self.add_output( Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), - units="rad", - desc="flight path angle", + units='rad', + desc='flight path angle', ) - self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, - [Dynamic.Mission.VELOCITY, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, - Dynamic.Mission.MASS], - rows=arange, - cols=arange) + self.declare_partials( + Dynamic.Mission.ALTITUDE_RATE, + [ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + ], + rows=arange, + cols=arange, + ) self.declare_partials( Dynamic.Mission.DISTANCE_RATE, - [Dynamic.Mission.VELOCITY, Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, Dynamic.Mission.MASS], + [ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + 'required_lift', + [ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], rows=arange, cols=arange, ) self.declare_partials( - "required_lift", - [Dynamic.Mission.MASS, Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, "alpha"], + Dynamic.Mission.FLIGHT_PATH_ANGLE, + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + ], rows=arange, cols=arange, ) - self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE, - [Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, - Dynamic.Mission.MASS], - rows=arange, - cols=arange) def compute(self, inputs, outputs): - TAS = inputs[Dynamic.Mission.VELOCITY] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - alpha = inputs["alpha"] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = (thrust - drag) / weight - outputs[Dynamic.Mission.ALTITUDE_RATE] = alt_rate = TAS * np.sin(gamma) + outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) - outputs["required_lift"] = weight * np.cos(gamma) - thrust * np.sin(alpha) + outputs['required_lift'] = weight * np.cos(gamma) - thrust * np.sin(alpha) outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] = gamma def compute_partials(self, inputs, J): - TAS = inputs[Dynamic.Mission.VELOCITY] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - alpha = inputs["alpha"] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] gamma = (thrust - drag) / weight J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = np.sin(gamma) - J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.THRUST_TOTAL] = TAS * \ - np.cos(gamma) / weight - J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.DRAG] = TAS * \ - np.cos(gamma) * (-1 / weight) - J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.MASS] = TAS * \ - np.cos(gamma) * (-(thrust - drag) / weight**2) * GRAV_ENGLISH_LBM + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + TAS * np.cos(gamma) / weight + ) + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Vehicle.DRAG] = TAS * np.cos(gamma) * (-1 / weight) + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Vehicle.MASS] = ( + TAS * np.cos(gamma) * (-(thrust - drag) / weight**2) * GRAV_ENGLISH_LBM + ) J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = np.cos(gamma) - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.THRUST_TOTAL] = - \ - TAS * np.sin(gamma) / weight - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.DRAG] = - \ - TAS * np.sin(gamma) * (-1 / weight) - J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.MASS] = ( + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + -TAS * np.sin(gamma) / weight + ) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Vehicle.DRAG] = ( + -TAS * np.sin(gamma) * (-1 / weight) + ) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Vehicle.MASS] = ( -TAS * np.sin(gamma) * (-(thrust - drag) / weight**2) * GRAV_ENGLISH_LBM ) - J["required_lift", Dynamic.Mission.MASS] = ( - np.cos(gamma) - weight * np.sin( - (thrust - drag) / weight - ) * (-(thrust - drag) / weight**2) + J['required_lift', Dynamic.Vehicle.MASS] = ( + np.cos(gamma) + - weight * np.sin((thrust - drag) / weight) * (-(thrust - drag) / weight**2) ) * GRAV_ENGLISH_LBM - J["required_lift", Dynamic.Mission.THRUST_TOTAL] = - \ - weight * np.sin(gamma) / weight - np.sin(alpha) - J["required_lift", Dynamic.Mission.DRAG] = - \ - weight * np.sin(gamma) * (-1 / weight) - J["required_lift", "alpha"] = -thrust * np.cos(alpha) - - J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.THRUST_TOTAL] = 1 / weight - J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.DRAG] = -1 / weight - J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.MASS] = - \ - (thrust - drag) / weight**2 * GRAV_ENGLISH_LBM + J['required_lift', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = -weight * np.sin( + gamma + ) / weight - np.sin(alpha) + J['required_lift', Dynamic.Vehicle.DRAG] = -weight * np.sin(gamma) * (-1 / weight) + J['required_lift', Dynamic.Vehicle.ANGLE_OF_ATTACK] = -thrust * np.cos(alpha) + + J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = 1 / weight + J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Vehicle.DRAG] = -1 / weight + J[Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Vehicle.MASS] = ( + -(thrust - drag) / weight**2 * GRAV_ENGLISH_LBM + ) diff --git a/aviary/mission/gasp_based/ode/descent_ode.py b/aviary/mission/gasp_based/ode/descent_ode.py index 9f9b3ab1e1..484436072a 100644 --- a/aviary/mission/gasp_based/ode/descent_ode.py +++ b/aviary/mission/gasp_based/ode/descent_ode.py @@ -1,23 +1,19 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.mission.gasp_based.ode.base_ode import BaseODE -from aviary.mission.gasp_based.ode.params import ParamPort -from aviary.mission.gasp_based.ode.descent_eom import DescentRates -from aviary.subsystems.atmosphere.flight_conditions import FlightConditions -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.constraints.flight_constraints import FlightConstraints from aviary.mission.gasp_based.ode.constraints.speed_constraints import SpeedConstraints - -from aviary.variable_info.enums import AnalysisScheme, AlphaModes, SpeedType -from aviary.variable_info.variables import Aircraft, Mission, Dynamic +from aviary.mission.gasp_based.ode.descent_eom import DescentRates +from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase -from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase -from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs +from aviary.subsystems.atmosphere.atmosphere import Atmosphere +from aviary.subsystems.atmosphere.flight_conditions import FlightConditions +from aviary.variable_info.enums import AlphaModes, SpeedType +from aviary.variable_info.variables import Aircraft, Dynamic -class DescentODE(BaseODE): +class DescentODE(TwoDOFODE): """ODE for quasi-steady descent. This ODE has a ``KSComp`` which allows for the switching of obeying an EAS @@ -29,208 +25,198 @@ class DescentODE(BaseODE): def initialize(self): super().initialize() - self.options.declare("input_speed_type", types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number") - self.options.declare("alt_trigger_units", default='ft', - desc='The units that the altitude trigger is provided in') - self.options.declare("speed_trigger_units", default='kn', - desc='The units that the speed trigger is provided in.') self.options.declare( - "mach_cruise", default=0, desc="targeted cruise mach number" + 'input_speed_type', + types=SpeedType, + desc='Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number', + ) + self.options.declare( + 'alt_trigger_units', + default='ft', + desc='The units that the altitude trigger is provided in', ) self.options.declare( - "EAS_limit", default=0, desc="maximum descending EAS in knots" + 'speed_trigger_units', + default='kn', + desc='The units that the speed trigger is provided in.', ) + self.options.declare('mach_cruise', default=0, desc='targeted cruise Mach number') + self.options.declare('EAS_limit', default=0, desc='maximum descending EAS in knots') def setup(self): self.options['auto_order'] = True - nn = self.options["num_nodes"] - analysis_scheme = self.options["analysis_scheme"] + nn = self.options['num_nodes'] aviary_options = self.options['aviary_options'] core_subsystems = self.options['core_subsystems'] - input_speed_type = self.options["input_speed_type"] - - flight_condition_group = self - - if input_speed_type is SpeedType.EAS: - speed_inputs = ["EAS"] - speed_outputs = ["mach", Dynamic.Mission.VELOCITY] - elif input_speed_type is SpeedType.MACH: - speed_inputs = ["mach"] - speed_outputs = ["EAS", Dynamic.Mission.VELOCITY] - - if analysis_scheme is AnalysisScheme.SHOOTING: - add_SGM_required_inputs(self, { - 't_curr': {'units': 's'}, - Dynamic.Mission.DISTANCE: {'units': 'ft'}, - 'alt_trigger': {'units': self.options['alt_trigger_units'], 'val': 10e3}, - 'speed_trigger': {'units': self.options['speed_trigger_units'], 'val': 100}, - }) + subsystem_options = self.options['subsystem_options'] + input_speed_type = self.options['input_speed_type'] + # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) self.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=nn), promotes_inputs=[Dynamic.Mission.ALTITUDE], promotes_outputs=[ - Dynamic.Mission.DENSITY, - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, - "viscosity", + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + 'viscosity', ], ) - if analysis_scheme is AnalysisScheme.COLLOCATION: - EAS_limit = self.options["EAS_limit"] - mach_cruise = self.options["mach_cruise"] - - # Add a group to contain the balance - - if input_speed_type is SpeedType.MACH: - mach_balance_group = self.add_subsystem( - "mach_balance_group", subsys=om.Group(), promotes=["*"] - ) - - mach_balance_group.options['auto_order'] = True - mach_balance_group.nonlinear_solver = om.NewtonSolver() - mach_balance_group.nonlinear_solver.options["solve_subsystems"] = True - mach_balance_group.nonlinear_solver.options["iprint"] = 0 - mach_balance_group.nonlinear_solver.options["atol"] = 1e-7 - mach_balance_group.nonlinear_solver.options["rtol"] = 1e-7 - mach_balance_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() - mach_balance_group.linear_solver = om.DirectSolver(assemble_jac=True) - - speed_bal = om.BalanceComp( - name=Dynamic.Mission.MACH, - val=mach_cruise * np.ones(nn), - units="unitless", - lhs_name="KS", - rhs_val=0.0, - eq_units='unitless', - upper=1000, - lower=0, - ) - mach_balance_group.add_subsystem( - "speed_bal", - speed_bal, - promotes_inputs=["KS"], - promotes_outputs=[Dynamic.Mission.MACH], - ) - - mach_balance_group.add_subsystem( - "speeds", - SpeedConstraints( - num_nodes=nn, - mach_cruise=mach_cruise, - EAS_target=EAS_limit, - ), - promotes_inputs=["EAS", Dynamic.Mission.MACH], - promotes_outputs=["speed_constraint"], - ) - mach_balance_group.add_subsystem( - "ks", - om.KSComp(width=2, vec_size=nn, units="unitless"), - promotes_inputs=[("g", "speed_constraint")], - promotes_outputs=["KS"], - ) - flight_condition_group = mach_balance_group - - lift_balance_group = self.add_subsystem( - "lift_balance_group", subsys=om.Group(), promotes=["*"] + EAS_limit = self.options['EAS_limit'] + mach_cruise = self.options['mach_cruise'] + + # Add a group to contain the balance + + if input_speed_type is SpeedType.MACH: + mach_balance_group = self.add_subsystem( + 'mach_balance_group', subsys=om.Group(), promotes=['*'] ) - elif analysis_scheme is AnalysisScheme.SHOOTING: - lift_balance_group = self + mach_balance_group.options['auto_order'] = True + mach_balance_group.nonlinear_solver = om.NewtonSolver() + mach_balance_group.nonlinear_solver.options['solve_subsystems'] = True + mach_balance_group.nonlinear_solver.options['iprint'] = 0 + mach_balance_group.nonlinear_solver.options['atol'] = 1e-7 + mach_balance_group.nonlinear_solver.options['rtol'] = 1e-7 + mach_balance_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() + mach_balance_group.linear_solver = om.DirectSolver(assemble_jac=True) + + speed_bal = om.BalanceComp( + name=Dynamic.Atmosphere.MACH, + val=mach_cruise * np.ones(nn), + units='unitless', + lhs_name='KS', + rhs_val=0.0, + eq_units='unitless', + upper=1000, + lower=0, + ) + mach_balance_group.add_subsystem( + 'speed_bal', + speed_bal, + promotes_inputs=['KS'], + promotes_outputs=[Dynamic.Atmosphere.MACH], + ) + + mach_balance_group.add_subsystem( + 'speeds', + SpeedConstraints( + num_nodes=nn, + mach_cruise=mach_cruise, + EAS_target=EAS_limit, + ), + promotes_inputs=['EAS', Dynamic.Atmosphere.MACH], + promotes_outputs=['speed_constraint'], + ) + mach_balance_group.add_subsystem( + 'ks', + om.KSComp(width=2, vec_size=nn, units='unitless'), + promotes_inputs=[('g', 'speed_constraint')], + promotes_outputs=['KS'], + ) + flight_condition_group = mach_balance_group + else: + flight_condition_group = self + + lift_balance_group = self.add_subsystem( + 'lift_balance_group', subsys=om.Group(), promotes=['*'] + ) flight_condition_group.add_subsystem( name='flight_conditions', subsys=FlightConditions(num_nodes=nn, input_speed_type=input_speed_type), promotes_inputs=['*'], # + speed_inputs, - promotes_outputs=[ - '*' - ], # [Dynamic.Mission.DYNAMIC_PRESSURE] + speed_outputs, + promotes_outputs=['*'], # [Dynamic.Atmosphere.DYNAMIC_PRESSURE] + speed_outputs, ) - # maybe replace this with the solver in AddAlphaControl? + # maybe replace this with the solver in add_alpha_control? lift_balance_group.nonlinear_solver = om.NewtonSolver() - lift_balance_group.nonlinear_solver.options["solve_subsystems"] = True - lift_balance_group.nonlinear_solver.options["iprint"] = 0 - lift_balance_group.nonlinear_solver.options["atol"] = 1e-7 - lift_balance_group.nonlinear_solver.options["rtol"] = 1e-7 + lift_balance_group.nonlinear_solver.options['solve_subsystems'] = True + lift_balance_group.nonlinear_solver.options['iprint'] = 0 + lift_balance_group.nonlinear_solver.options['atol'] = 1e-7 + lift_balance_group.nonlinear_solver.options['rtol'] = 1e-7 lift_balance_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() lift_balance_group.linear_solver = om.DirectSolver(assemble_jac=True) lift_balance_group.add_subsystem( - "descent_eom", + 'descent_eom', DescentRates(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Dynamic.Mission.VELOCITY, - Dynamic.Mission.DRAG, - Dynamic.Mission.THRUST_TOTAL, - "alpha", + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, ], promotes_outputs=[ Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.DISTANCE_RATE, - "required_lift", + 'required_lift', Dynamic.Mission.FLIGHT_PATH_ANGLE, ], ) self.add_subsystem( - "constraints", + 'constraints', FlightConstraints(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.MASS, - "alpha", - Dynamic.Mission.DENSITY, - "CL_max", + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Atmosphere.DENSITY, + 'CL_max', Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY, ] - + ["aircraft:*"], - promotes_outputs=["theta", "TAS_violation"], + + ['aircraft:*'], + promotes_outputs=['theta', 'TAS_violation'], ) - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'cruise'} + kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, 'method': 'cruise'} # collect the propulsion group names for later use for subsystem in core_subsystems: + # check if subsystem_options has entry for a subsystem of this name + if subsystem.name in subsystem_options: + kwargs.update(subsystem_options[subsystem.name]) system = subsystem.build_mission(**kwargs) if system is not None: if isinstance(subsystem, AerodynamicsBuilderBase): - lift_balance_group.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + lift_balance_group.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) else: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) + + self.add_external_subsystems() - self.AddAlphaControl( + self.add_alpha_control( alpha_group=lift_balance_group, alpha_mode=AlphaModes.REQUIRED_LIFT, add_default_solver=False, - num_nodes=nn) + num_nodes=nn, + ) # the last two subsystems will also be used for constraints self.add_excess_rate_comps(nn) ParamPort.set_default_vals(self) - self.set_input_defaults(Dynamic.Mission.ALTITUDE, - val=37500 * np.ones(nn), units="ft") - self.set_input_defaults(Dynamic.Mission.MASS, - val=147000 * np.ones(nn), units="lbm") - self.set_input_defaults(Dynamic.Mission.MACH, - val=0 * np.ones(nn), units="unitless") - self.set_input_defaults(Dynamic.Mission.THROTTLE, - val=0 * np.ones(nn), units="unitless") - - self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units="ft**2") + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=37500 * np.ones(nn), units='ft') + self.set_input_defaults(Dynamic.Vehicle.MASS, val=147000 * np.ones(nn), units='lbm') + self.set_input_defaults(Dynamic.Atmosphere.MACH, val=0 * np.ones(nn), units='unitless') + self.set_input_defaults( + Dynamic.Vehicle.Propulsion.THROTTLE, val=0 * np.ones(nn), units='unitless' + ) + + self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units='ft**2') diff --git a/aviary/mission/gasp_based/ode/flight_path_eom.py b/aviary/mission/gasp_based/ode/flight_path_eom.py index 07399a23f3..543b702eb4 100644 --- a/aviary/mission/gasp_based/ode/flight_path_eom.py +++ b/aviary/mission/gasp_based/ode/flight_path_eom.py @@ -15,92 +15,125 @@ def __init__(self, **kwargs): self._mu = MU_TAKEOFF def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare("ground_roll", types=bool, default=False, - desc="True if the aircraft is confined to the ground. Removes altitude rate as an " - "output and adjust the TAS rate equation.") + self.options.declare('num_nodes', types=int) + self.options.declare( + 'ground_roll', + types=bool, + default=False, + desc='True if the aircraft is confined to the ground. Removes altitude rate as an ' + 'output and adjust the TAS rate equation.', + ) def setup(self): - nn = self.options["num_nodes"] - ground_roll = self.options["ground_roll"] + nn = self.options['num_nodes'] + ground_roll = self.options['ground_roll'] - self.add_input(Dynamic.Mission.MASS, val=np.ones(nn), - desc="aircraft mass", units="lbm") - self.add_input(Dynamic.Mission.THRUST_TOTAL, val=np.ones( - nn), desc=Dynamic.Mission.THRUST_TOTAL, units="lbf") + self.add_input(Dynamic.Vehicle.MASS, val=np.ones(nn), desc='aircraft mass', units='lbm') self.add_input( - Dynamic.Mission.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), - desc=Dynamic.Mission.LIFT, - units="lbf") + desc=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', + ) self.add_input( - Dynamic.Mission.DRAG, + Dynamic.Vehicle.LIFT, val=np.ones(nn), - desc=Dynamic.Mission.DRAG, - units="lbf") - self.add_input(Dynamic.Mission.VELOCITY, val=np.ones(nn), - desc="true air speed", units="ft/s") - self.add_input(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), - desc="flight path angle", units="rad") + desc=Dynamic.Vehicle.LIFT, + units='lbf', + ) + self.add_input( + Dynamic.Vehicle.DRAG, + val=np.ones(nn), + desc=Dynamic.Vehicle.DRAG, + units='lbf', + ) + self.add_input( + Dynamic.Mission.VELOCITY, + val=np.ones(nn), + desc='true air speed', + units='ft/s', + ) + self.add_input( + Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.ones(nn), + desc='flight path angle', + units='rad', + ) add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0) - self.add_output(Dynamic.Mission.VELOCITY_RATE, val=np.ones(nn), desc="TAS rate", units="ft/s**2", - tags=['dymos.state_rate_source:velocity', 'dymos.state_units:kn']) + self.add_output( + Dynamic.Mission.VELOCITY_RATE, + val=np.ones(nn), + desc='TAS rate', + units='ft/s**2', + tags=['dymos.state_rate_source:velocity', 'dymos.state_units:kn'], + ) if not ground_roll: self._mu = 0.0 self.add_output( Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), - desc="altitude rate", - units="ft/s", - tags=[ - 'dymos.state_rate_source:altitude', - 'dymos.state_units:ft']) + desc='altitude rate', + units='ft/s', + tags=['dymos.state_rate_source:altitude', 'dymos.state_units:ft'], + ) self.add_output( Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, val=np.ones(nn), - desc="flight path angle rate", - units="rad/s", + desc='flight path angle rate', + units='rad/s', tags=[ 'dymos.state_rate_source:flight_path_angle', - 'dymos.state_units:rad']) - self.add_input("alpha", val=np.ones(nn), desc="angle of attack", units="deg") + 'dymos.state_units:rad', + ], + ) + self.add_input( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=np.ones(nn), + desc='angle of attack', + units='deg', + ) self.add_output( Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), - desc="distance rate", - units="ft/s", - tags=[ - 'dymos.state_rate_source:distance', - 'dymos.state_units:ft']) - self.add_output("normal_force", val=np.ones( - nn), desc="normal forces", units="lbf") - self.add_output("fuselage_pitch", val=np.ones( - nn), desc="fuselage pitch angle", units="deg") - self.add_output("load_factor", val=np.ones( - nn), desc="load factor", units="unitless") + desc='distance rate', + units='ft/s', + tags=['dymos.state_rate_source:distance', 'dymos.state_units:ft'], + ) + self.add_output('normal_force', val=np.ones(nn), desc='normal forces', units='lbf') + self.add_output('fuselage_pitch', val=np.ones(nn), desc='fuselage pitch angle', units='deg') + self.add_output('load_factor', val=np.ones(nn), desc='load factor', units='unitless') # Possible nice-to-have TODO: alpha as an output for groundroll def setup_partials(self): - arange = np.arange(self.options["num_nodes"], dtype=int) - ground_roll = self.options["ground_roll"] + arange = np.arange(self.options['num_nodes'], dtype=int) + ground_roll = self.options['ground_roll'] self.declare_partials( - "load_factor", - [Dynamic.Mission.LIFT, Dynamic.Mission.MASS, - Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.THRUST_TOTAL], + 'load_factor', + [ + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + ], rows=arange, cols=arange, ) - self.declare_partials("load_factor", [Aircraft.Wing.INCIDENCE]) + self.declare_partials('load_factor', [Aircraft.Wing.INCIDENCE]) self.declare_partials( Dynamic.Mission.VELOCITY_RATE, - [Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, - Dynamic.Mission.MASS, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.LIFT], + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Vehicle.LIFT, + ], rows=arange, cols=arange, ) @@ -109,74 +142,94 @@ def setup_partials(self): if not ground_roll: self.declare_partials( - Dynamic.Mission.ALTITUDE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange) + Dynamic.Mission.ALTITUDE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=arange, + cols=arange, + ) self.declare_partials( Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - [Dynamic.Mission.THRUST_TOTAL, "alpha", - Dynamic.Mission.LIFT, Dynamic.Mission.MASS, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.VELOCITY], + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.VELOCITY, + ], rows=arange, cols=arange, ) - self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, [ - Aircraft.Wing.INCIDENCE]) + self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, [Aircraft.Wing.INCIDENCE]) self.declare_partials( - "normal_force", - "alpha", + 'normal_force', + Dynamic.Vehicle.ANGLE_OF_ATTACK, rows=arange, cols=arange, ) self.declare_partials( - "fuselage_pitch", "alpha", rows=arange, cols=arange + 'fuselage_pitch', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + rows=arange, + cols=arange, ) self.declare_partials( - "load_factor", - "alpha", + 'load_factor', + Dynamic.Vehicle.ANGLE_OF_ATTACK, rows=arange, cols=arange, ) - self.declare_partials("load_factor", [Aircraft.Wing.INCIDENCE]) + self.declare_partials('load_factor', [Aircraft.Wing.INCIDENCE]) self.declare_partials( Dynamic.Mission.VELOCITY_RATE, - "alpha", + Dynamic.Vehicle.ANGLE_OF_ATTACK, rows=arange, cols=arange, ) self.declare_partials( - Dynamic.Mission.DISTANCE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.DISTANCE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=arange, + cols=arange, ) - # self.declare_partials("alpha_rate", ["*"], val=0.0) + # self.declare_partials("angle_of_attack_rate", ["*"], val=0.0) self.declare_partials( - "normal_force", - [Dynamic.Mission.MASS, Dynamic.Mission.LIFT, Dynamic.Mission.THRUST_TOTAL], + 'normal_force', + [ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + ], rows=arange, cols=arange, ) - self.declare_partials("normal_force", [Aircraft.Wing.INCIDENCE]) + self.declare_partials('normal_force', [Aircraft.Wing.INCIDENCE]) self.declare_partials( - "fuselage_pitch", Dynamic.Mission.FLIGHT_PATH_ANGLE, rows=arange, cols=arange, val=180 / np.pi + 'fuselage_pitch', + Dynamic.Mission.FLIGHT_PATH_ANGLE, + rows=arange, + cols=arange, + val=180 / np.pi, ) - self.declare_partials("fuselage_pitch", [Aircraft.Wing.INCIDENCE]) + self.declare_partials('fuselage_pitch', [Aircraft.Wing.INCIDENCE]) def compute(self, inputs, outputs): - mu = MU_TAKEOFF if self.options['ground_roll'] else 0.0 - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - if self.options["ground_roll"]: + if self.options['ground_roll']: alpha = inputs[Aircraft.Wing.INCIDENCE] else: - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] thrust_along_flightpath = thrust * np.cos((alpha - i_wing) * np.pi / 180) thrust_across_flightpath = thrust * np.sin((alpha - i_wing) * np.pi / 180) @@ -203,32 +256,30 @@ def compute(self, inputs, outputs): outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) - outputs["normal_force"] = normal_force + outputs['normal_force'] = normal_force - outputs["fuselage_pitch"] = gamma * 180 / np.pi - i_wing + alpha + outputs['fuselage_pitch'] = gamma * 180 / np.pi - i_wing + alpha - load_factor = (incremented_lift + thrust_across_flightpath) / ( - weight * np.cos(gamma) - ) + load_factor = (incremented_lift + thrust_across_flightpath) / (weight * np.cos(gamma)) - outputs["load_factor"] = load_factor + outputs['load_factor'] = load_factor def compute_partials(self, inputs, J): mu = MU_TAKEOFF if self.options['ground_roll'] else 0.0 - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - if self.options["ground_roll"]: + if self.options['ground_roll']: alpha = i_wing else: - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] thrust_along_flightpath = thrust * np.cos((alpha - i_wing) * np.pi / 180) thrust_across_flightpath = thrust * np.sin((alpha - i_wing) * np.pi / 180) @@ -241,17 +292,20 @@ def compute_partials(self, inputs, J): dTAcF_dAlpha = thrust * np.cos((alpha - i_wing) * np.pi / 180) * np.pi / 180 dTAcF_dIwing = -thrust * np.cos((alpha - i_wing) * np.pi / 180) * np.pi / 180 - J["load_factor", Dynamic.Mission.LIFT] = 1 / (weight * np.cos(gamma)) - J["load_factor", Dynamic.Mission.MASS] = -(incremented_lift + thrust_across_flightpath) / ( - weight**2 * np.cos(gamma) - ) * GRAV_ENGLISH_LBM - J["load_factor", Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + J['load_factor', Dynamic.Vehicle.LIFT] = 1 / (weight * np.cos(gamma)) + J['load_factor', Dynamic.Vehicle.MASS] = ( + -(incremented_lift + thrust_across_flightpath) + / (weight**2 * np.cos(gamma)) + * GRAV_ENGLISH_LBM + ) + J['load_factor', Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( -(incremented_lift + thrust_across_flightpath) / (weight * (np.cos(gamma)) ** 2) * (-np.sin(gamma)) ) - J["load_factor", Dynamic.Mission.THRUST_TOTAL] = dTAcF_dThrust / \ - (weight * np.cos(gamma)) + J['load_factor', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = dTAcF_dThrust / ( + weight * np.cos(gamma) + ) normal_force = weight - incremented_lift - thrust_across_flightpath # normal_force = np.where(normal_force1 < 0, np.zeros(nn), normal_force1) @@ -268,13 +322,14 @@ def compute_partials(self, inputs, J): dNF_dIwing = -np.ones(nn) * dTAcF_dIwing # dNF_dIwing[normal_force1 < 0] = 0 - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.THRUST_TOTAL] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( (dTAlF_dThrust - mu * dNF_dThrust) * GRAV_ENGLISH_GASP / weight ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.DRAG] = -GRAV_ENGLISH_GASP / weight - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.MASS] = ( - GRAV_ENGLISH_GASP * GRAV_ENGLISH_LBM + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -GRAV_ENGLISH_GASP / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( + GRAV_ENGLISH_GASP + * GRAV_ENGLISH_LBM * ( weight * (-np.sin(gamma) - mu * dNF_dWeight) - ( @@ -286,31 +341,42 @@ def compute_partials(self, inputs, J): ) / weight**2 ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = - \ - np.cos(gamma) * GRAV_ENGLISH_GASP - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.LIFT] = GRAV_ENGLISH_GASP * \ - (-mu * dNF_dLift) / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + -np.cos(gamma) * GRAV_ENGLISH_GASP + ) + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.LIFT] = ( + GRAV_ENGLISH_GASP * (-mu * dNF_dLift) / weight + ) # TODO: check partials, esp. for alphas if not self.options['ground_roll']: J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = np.sin(gamma) - J[Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) - - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.THRUST_TOTAL] = dTAcF_dThrust * \ - GRAV_ENGLISH_GASP / (TAS * weight) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, "alpha"] = dTAcF_dAlpha * \ - GRAV_ENGLISH_GASP / (TAS * weight) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Aircraft.Wing.INCIDENCE] = dTAcF_dIwing * \ - GRAV_ENGLISH_GASP / (TAS * weight) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - Dynamic.Mission.LIFT] = GRAV_ENGLISH_GASP / (TAS * weight) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.MASS] = (GRAV_ENGLISH_GASP / TAS) * GRAV_ENGLISH_LBM * ( - -thrust_across_flightpath / weight**2 - incremented_lift / weight**2 + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos( + gamma + ) + + J[ + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + ] = dTAcF_dThrust * GRAV_ENGLISH_GASP / (TAS * weight) + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( + dTAcF_dAlpha * GRAV_ENGLISH_GASP / (TAS * weight) + ) + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Aircraft.Wing.INCIDENCE] = ( + dTAcF_dIwing * GRAV_ENGLISH_GASP / (TAS * weight) ) - J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( - weight * np.sin(gamma) * GRAV_ENGLISH_GASP / (TAS * weight) + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.LIFT] = GRAV_ENGLISH_GASP / ( + TAS * weight ) + J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Vehicle.MASS] = ( + (GRAV_ENGLISH_GASP / TAS) + * GRAV_ENGLISH_LBM + * (-thrust_across_flightpath / weight**2 - incremented_lift / weight**2) + ) + J[ + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ] = weight * np.sin(gamma) * GRAV_ENGLISH_GASP / (TAS * weight) J[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, Dynamic.Mission.VELOCITY] = -( (thrust_across_flightpath + incremented_lift - weight * np.cos(gamma)) * GRAV_ENGLISH_GASP @@ -319,24 +385,24 @@ def compute_partials(self, inputs, J): dNF_dAlpha = -np.ones(nn) * dTAcF_dAlpha # dNF_dAlpha[normal_force1 < 0] = 0 - J[Dynamic.Mission.VELOCITY_RATE, "alpha"] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( (dTAlF_dAlpha - mu * dNF_dAlpha) * GRAV_ENGLISH_GASP / weight ) - J["normal_force", "alpha"] = dNF_dAlpha - J["fuselage_pitch", "alpha"] = 1 - J["load_factor", "alpha"] = dTAcF_dAlpha / (weight * np.cos(gamma)) + J['normal_force', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dNF_dAlpha + J['fuselage_pitch', Dynamic.Vehicle.ANGLE_OF_ATTACK] = 1 + J['load_factor', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dTAcF_dAlpha / ( + weight * np.cos(gamma) + ) J[Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE] = ( (dTAlF_dIwing - mu * dNF_dIwing) * GRAV_ENGLISH_GASP / weight ) - J["normal_force", Aircraft.Wing.INCIDENCE] = dNF_dIwing - J["fuselage_pitch", Aircraft.Wing.INCIDENCE] = -1 - J["load_factor", Aircraft.Wing.INCIDENCE] = dTAcF_dIwing / \ - (weight * np.cos(gamma)) + J['normal_force', Aircraft.Wing.INCIDENCE] = dNF_dIwing + J['fuselage_pitch', Aircraft.Wing.INCIDENCE] = -1 + J['load_factor', Aircraft.Wing.INCIDENCE] = dTAcF_dIwing / (weight * np.cos(gamma)) J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = np.cos(gamma) - J[Dynamic.Mission.DISTANCE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) - J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM - J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift - J["normal_force", Dynamic.Mission.THRUST_TOTAL] = dNF_dThrust + J['normal_force', Dynamic.Vehicle.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM + J['normal_force', Dynamic.Vehicle.LIFT] = dNF_dLift + J['normal_force', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = dNF_dThrust diff --git a/aviary/mission/gasp_based/ode/flight_path_ode.py b/aviary/mission/gasp_based/ode/flight_path_ode.py index dd06176747..4ad36b1a22 100644 --- a/aviary/mission/gasp_based/ode/flight_path_ode.py +++ b/aviary/mission/gasp_based/ode/flight_path_ode.py @@ -1,98 +1,77 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.mass.mass_to_weight import MassToWeight -from aviary.variable_info.enums import AlphaModes, AnalysisScheme, SpeedType -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.flight_path_eom import FlightPathEOM from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE +from aviary.subsystems.mass.mass_to_weight import MassToWeight from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase +from aviary.variable_info.enums import AlphaModes, SpeedType from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs -class FlightPathODE(BaseODE): - """ ODE using 2D aircraft equations of motion with states distance, alt, TAS, and gamma. +class FlightPathODE(TwoDOFODE): + """ODE using 2D aircraft equations of motion with states distance, alt, TAS, and gamma. Control is managed via angle-of-attack (alpha). """ def initialize(self): super().initialize() - self.options.declare("alpha_mode", default=AlphaModes.DEFAULT, types=AlphaModes) - self.options.declare("input_speed_type", default=SpeedType.TAS, types=SpeedType, - desc="Whether the speed is given as a equivalent airspeed, true airspeed, or mach number") + self.options.declare('alpha_mode', default=AlphaModes.DEFAULT, types=AlphaModes) self.options.declare( - "ground_roll", + 'input_speed_type', + default=SpeedType.TAS, + types=SpeedType, + desc='Whether the speed is given as a equivalent airspeed, true airspeed, or Mach number', + ) + self.options.declare( + 'ground_roll', types=bool, default=False, - desc="True if the aircraft is confined to the ground. Removes altitude rate as an " - "output and adjusts the TAS rate equation.") + desc='True if the aircraft is confined to the ground. Removes altitude rate as an ' + 'output and adjusts the TAS rate equation.', + ) self.options.declare( - "clean", + 'clean', types=bool, default=False, - desc="If true then no flaps or gear are included. Useful for high-speed flight phases.") + desc='If true then no flaps or gear are included. Useful for high-speed flight phases.', + ) def setup(self): self.options['auto_order'] = True - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] aviary_options = self.options['aviary_options'] alpha_mode = self.options['alpha_mode'] - analysis_scheme = self.options['analysis_scheme'] input_speed_type = self.options['input_speed_type'] print_level = 0 - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'low_speed'} + kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, 'method': 'low_speed'} if self.options['clean']: kwargs['method'] = 'cruise' kwargs['output_alpha'] = False EOM_inputs = [ - Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.LIFT, - Dynamic.Mission.DRAG, + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.DRAG, Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE, ] + ['aircraft:*'] if not self.options['ground_roll']: - EOM_inputs.append('alpha') - - if analysis_scheme is AnalysisScheme.SHOOTING: - SGM_required_inputs = { - 't_curr': {'units': 's'}, - 'distance_trigger': {'units': 'ft'}, - Dynamic.Mission.ALTITUDE: {'units': 'ft'}, - Dynamic.Mission.DISTANCE: {'units': 'ft'}, - } - if kwargs['method'] == 'cruise': - SGM_required_inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] = { - 'val': 0, 'units': 'deg'} - add_SGM_required_inputs(self, SGM_required_inputs) - prop_group = om.Group() - else: - prop_group = self + EOM_inputs.append(Dynamic.Vehicle.ANGLE_OF_ATTACK) + core_subsystems = self.options['core_subsystems'] # TODO: paramport flight_path_params = ParamPort() - if analysis_scheme is AnalysisScheme.SHOOTING and kwargs['method'] == 'cruise': - flight_path_params.add_params({ - Aircraft.Design.OPERATING_MASS: dict(units='lbm', val=0), - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS: dict(units='lbm', val=0), - Mission.Design.RESERVE_FUEL: dict(units='lbm', val=0), - }) - self.add_subsystem("params", flight_path_params, promotes=["*"]) - self.add_subsystem( - name='atmosphere', - subsys=Atmosphere(num_nodes=nn, input_speed_type=input_speed_type), - promotes=['*'], - ) + self.add_subsystem('params', flight_path_params, promotes=['*']) + + self.add_atmosphere(input_speed_type=input_speed_type) if alpha_mode is AlphaModes.DEFAULT: # alpha as input @@ -100,10 +79,10 @@ def setup(self): else: if alpha_mode is AlphaModes.REQUIRED_LIFT: self.add_subsystem( - "calc_weight", + 'calc_weight', MassToWeight(num_nodes=nn), - promotes_inputs=[("mass", Dynamic.Mission.MASS)], - promotes_outputs=["weight"] + promotes_inputs=[('mass', Dynamic.Vehicle.MASS)], + promotes_outputs=['weight'], ) self.add_subsystem( 'calc_lift', @@ -118,63 +97,44 @@ def setup(self): ), promotes_inputs=[ 'weight', - ('thrust', Dynamic.Mission.THRUST_TOTAL), - 'alpha', + ('thrust', Dynamic.Vehicle.Propulsion.THRUST_TOTAL), + ('alpha', Dynamic.Vehicle.ANGLE_OF_ATTACK), ('gamma', Dynamic.Mission.FLIGHT_PATH_ANGLE), - ('i_wing', Aircraft.Wing.INCIDENCE) + ('i_wing', Aircraft.Wing.INCIDENCE), ], - promotes_outputs=['required_lift'] + promotes_outputs=['required_lift'], ) - self.AddAlphaControl( + self.add_alpha_control( alpha_mode=alpha_mode, target_load_factor=1, - atol=1e-6, rtol=1e-12, num_nodes=nn, print_level=print_level) + atol=1e-6, + rtol=1e-12, + num_nodes=nn, + print_level=print_level, + ) for subsystem in core_subsystems: system = subsystem.build_mission(**kwargs) if system is not None: if isinstance(subsystem, PropulsionBuilderBase): - prop_group.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) else: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) - - if analysis_scheme is AnalysisScheme.SHOOTING: - prop_group.add_subsystem( - 'calc_thrust', - om.ExecComp( - # TODO fix engines not providing thrust in the right direction - # + weight*sin(alpha + gamma) - 'required_thrust = ( drag ) / cos(i_wing)', - required_thrust={'val': 0, 'units': 'lbf'}, - drag={'val': 0, 'units': 'lbf'}, - # weight={'val': 0, 'units': 'lbf'}, - # alpha={'val': 0, 'units': 'rad'}, - # gamma={'val': 0, 'units': 'rad'}, - i_wing={'val': 0, 'units': 'rad'}, - ), - promotes_inputs=[ - ('drag', Dynamic.Mission.DRAG), - # 'weight', - # 'alpha', - # ('gamma', Dynamic.Mission.FLIGHT_PATH_ANGLE), - ('i_wing', Aircraft.Wing.INCIDENCE) - ], - promotes_outputs=['required_thrust'] - ) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) - self.AddThrottleControl(prop_group=prop_group, - atol=1e-8, print_level=print_level) + self.add_external_subsystems() self.add_subsystem( - "flight_path_eom", + 'flight_path_eom', FlightPathEOM( num_nodes=nn, ground_roll=self.options['ground_roll'], @@ -183,27 +143,31 @@ def setup(self): promotes_outputs=[ Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.DISTANCE_RATE, - "normal_force", - "fuselage_pitch", - "load_factor", + 'normal_force', + 'fuselage_pitch', + 'load_factor', ], ) if not self.options['ground_roll']: - self.promotes('flight_path_eom', outputs=[ - Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE]) + self.promotes( + 'flight_path_eom', + outputs=[ + Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ], + ) self.add_excess_rate_comps(nn) ParamPort.set_default_vals(self) - if not self.options["clean"]: - self.set_input_defaults("t_init_flaps", val=47.5) - self.set_input_defaults("t_init_gear", val=37.3) - self.set_input_defaults("t_curr", val=np.zeros(nn), units="s") - self.set_input_defaults("alpha", val=np.zeros(nn), units="rad") - self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units="deg") - self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units="ft") - self.set_input_defaults(Dynamic.Mission.MACH, val=np.zeros(nn), units="unitless") - self.set_input_defaults(Dynamic.Mission.MASS, val=np.zeros(nn), units="lbm") - self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units="kn") + if not self.options['clean']: + self.set_input_defaults('t_init_flaps', val=47.5) + self.set_input_defaults('t_init_gear', val=37.3) + self.set_input_defaults('t_curr', val=np.zeros(nn), units='s') + self.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') + self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='deg') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units='ft') + self.set_input_defaults(Dynamic.Atmosphere.MACH, val=np.zeros(nn), units='unitless') + self.set_input_defaults(Dynamic.Vehicle.MASS, val=np.zeros(nn), units='lbm') + self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='kn') diff --git a/aviary/mission/gasp_based/ode/groundroll_eom.py b/aviary/mission/gasp_based/ode/groundroll_eom.py index 83ca58973e..aa822316c1 100644 --- a/aviary/mission/gasp_based/ode/groundroll_eom.py +++ b/aviary/mission/gasp_based/ode/groundroll_eom.py @@ -2,107 +2,157 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM, MU_TAKEOFF -from aviary.variable_info.enums import AnalysisScheme from aviary.variable_info.functions import add_aviary_input from aviary.variable_info.variables import Aircraft, Dynamic class GroundrollEOM(om.ExplicitComponent): - """GASP based ground roll EOM""" + """GASP based ground roll EOM.""" def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare("analysis_scheme", types=AnalysisScheme, default=AnalysisScheme.COLLOCATION, - desc="The analysis method that will be used to close the trajectory; for example collocation or time integration") + self.options.declare('num_nodes', types=int) def setup(self): - analysis_scheme = self.options["analysis_scheme"] - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) - self.add_input(Dynamic.Mission.MASS, val=np.ones(nn), - desc="aircraft mass", units="lbm") - self.add_input(Dynamic.Mission.THRUST_TOTAL, val=np.ones( - nn), desc=Dynamic.Mission.THRUST_TOTAL, units="lbf") - self.add_input(Dynamic.Mission.LIFT, val=np.ones( - nn), desc=Dynamic.Mission.LIFT, units="lbf") - self.add_input(Dynamic.Mission.DRAG, val=np.ones( - nn), desc=Dynamic.Mission.DRAG, units="lbf") - self.add_input(Dynamic.Mission.VELOCITY, val=np.ones(nn), - desc="true air speed", units="ft/s") - self.add_input(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), - desc="flight path angle", units="rad") + self.add_input(Dynamic.Vehicle.MASS, val=np.ones(nn), desc='aircraft mass', units='lbm') + self.add_input( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + val=np.ones(nn), + desc=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', + ) + self.add_input( + Dynamic.Vehicle.LIFT, + val=np.ones(nn), + desc=Dynamic.Vehicle.LIFT, + units='lbf', + ) + self.add_input( + Dynamic.Vehicle.DRAG, + val=np.ones(nn), + desc=Dynamic.Vehicle.DRAG, + units='lbf', + ) + self.add_input( + Dynamic.Mission.VELOCITY, + val=np.ones(nn), + desc='true air speed', + units='ft/s', + ) + self.add_input( + Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.ones(nn), + desc='flight path angle', + units='rad', + ) add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0) - self.add_input("alpha", val=np.zeros(nn), desc="angle of attack", units="deg") + self.add_input( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=np.zeros(nn), + desc='angle of attack', + units='deg', + ) - self.add_output(Dynamic.Mission.VELOCITY_RATE, val=np.ones(nn), - desc="TAS rate", units="ft/s**2") self.add_output( - Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, val=np.ones(nn), desc="flight path angle rate", units="rad/s" + Dynamic.Mission.VELOCITY_RATE, + val=np.ones(nn), + desc='TAS rate', + units='ft/s**2', ) - self.add_output(Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), - desc="altitude rate", units="ft/s") self.add_output( - Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc="distance rate", units="ft/s" + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + val=np.ones(nn), + desc='flight path angle rate', + units='rad/s', ) self.add_output( - "normal_force", val=np.ones(nn), desc="normal forces", units="lbf" + Dynamic.Mission.ALTITUDE_RATE, + val=np.ones(nn), + desc='altitude rate', + units='ft/s', ) self.add_output( - "fuselage_pitch", val=np.ones(nn), desc="fuselage pitch angle", units="deg" + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc='distance rate', units='ft/s' ) + self.add_output('normal_force', val=np.ones(nn), desc='normal forces', units='lbf') + self.add_output('fuselage_pitch', val=np.ones(nn), desc='fuselage pitch angle', units='deg') - self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, "*") + self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, '*') self.declare_partials( Dynamic.Mission.VELOCITY_RATE, - [Dynamic.Mission.THRUST_TOTAL, "alpha", Dynamic.Mission.DRAG, - Dynamic.Mission.MASS, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.LIFT], + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Vehicle.LIFT, + ], rows=arange, cols=arange, ) self.declare_partials(Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE) - self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange) self.declare_partials( - Dynamic.Mission.DISTANCE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.ALTITUDE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=arange, + cols=arange, ) self.declare_partials( - "normal_force", - [Dynamic.Mission.MASS, Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, "alpha"], + Dynamic.Mission.DISTANCE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange, ) - self.declare_partials("normal_force", Aircraft.Wing.INCIDENCE) self.declare_partials( - "fuselage_pitch", Dynamic.Mission.FLIGHT_PATH_ANGLE, rows=arange, cols=arange, val=180 / np.pi, + 'normal_force', + [ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], + rows=arange, + cols=arange, ) - self.declare_partials("fuselage_pitch", "alpha", rows=arange, cols=arange, val=1) - self.declare_partials("fuselage_pitch", Aircraft.Wing.INCIDENCE, val=-1) + self.declare_partials('normal_force', Aircraft.Wing.INCIDENCE) + self.declare_partials( + 'fuselage_pitch', + Dynamic.Mission.FLIGHT_PATH_ANGLE, + rows=arange, + cols=arange, + val=180 / np.pi, + ) + self.declare_partials( + 'fuselage_pitch', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + rows=arange, + cols=arange, + val=1, + ) + self.declare_partials('fuselage_pitch', Aircraft.Wing.INCIDENCE, val=-1) - if analysis_scheme is AnalysisScheme.COLLOCATION: - self.add_output( - "alpha_rate", val=np.ones(nn), desc="angle of attack rate", units="deg/s" - ) + self.add_output( + 'angle_of_attack_rate', val=np.ones(nn), desc='angle of attack rate', units='deg/s' + ) - self.declare_partials("alpha_rate", ["*"]) + self.declare_partials('angle_of_attack_rate', ['*']) def compute(self, inputs, outputs): - analysis_scheme = self.options["analysis_scheme"] - mu = MU_TAKEOFF - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] thrust_along_flightpath = thrust * np.cos((alpha - i_wing) * np.pi / 180) thrust_across_flightpath = thrust * np.sin((alpha - i_wing) * np.pi / 180) @@ -123,26 +173,24 @@ def compute(self, inputs, outputs): outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) - outputs["normal_force"] = normal_force - - outputs["fuselage_pitch"] = gamma * 180 / np.pi - i_wing + alpha + outputs['normal_force'] = normal_force - if analysis_scheme is AnalysisScheme.COLLOCATION: - outputs["alpha_rate"] = np.zeros(nn) + outputs['fuselage_pitch'] = gamma * 180 / np.pi - i_wing + alpha + outputs['angle_of_attack_rate'] = np.zeros(nn) def compute_partials(self, inputs, J): mu = MU_TAKEOFF - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] thrust_along_flightpath = thrust * np.cos((alpha - i_wing) * np.pi / 180) thrust_across_flightpath = thrust * np.sin((alpha - i_wing) * np.pi / 180) @@ -173,18 +221,19 @@ def compute_partials(self, inputs, J): dNF_dIwing = -np.ones(nn) * dTAcF_dIwing dNF_dIwing[normal_force1 < 0] = 0 - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.THRUST_TOTAL] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( (dTAlF_dThrust - mu * dNF_dThrust) * GRAV_ENGLISH_GASP / weight ) - J[Dynamic.Mission.VELOCITY_RATE, "alpha"] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( (dTAlF_dAlpha - mu * dNF_dAlpha) * GRAV_ENGLISH_GASP / weight ) J[Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE] = ( (dTAlF_dIwing - mu * dNF_dIwing) * GRAV_ENGLISH_GASP / weight ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.DRAG] = -GRAV_ENGLISH_GASP / weight - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.MASS] = ( - GRAV_ENGLISH_GASP * GRAV_ENGLISH_LBM + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -GRAV_ENGLISH_GASP / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( + GRAV_ENGLISH_GASP + * GRAV_ENGLISH_LBM * ( weight * (-np.sin(gamma) - mu * dNF_dWeight) - ( @@ -196,21 +245,21 @@ def compute_partials(self, inputs, J): ) / weight**2 ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = - \ - np.cos(gamma) * GRAV_ENGLISH_GASP - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.LIFT] = GRAV_ENGLISH_GASP * \ - (-mu * dNF_dLift) / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + -np.cos(gamma) * GRAV_ENGLISH_GASP + ) + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.LIFT] = ( + GRAV_ENGLISH_GASP * (-mu * dNF_dLift) / weight + ) J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = np.sin(gamma) - J[Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = np.cos(gamma) - J[Dynamic.Mission.DISTANCE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) - - J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM - J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift - J["normal_force", Dynamic.Mission.THRUST_TOTAL] = dNF_dThrust - J["normal_force", "alpha"] = dNF_dAlpha - J["normal_force", Aircraft.Wing.INCIDENCE] = dNF_dIwing + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + + J['normal_force', Dynamic.Vehicle.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM + J['normal_force', Dynamic.Vehicle.LIFT] = dNF_dLift + J['normal_force', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = dNF_dThrust + J['normal_force', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dNF_dAlpha + J['normal_force', Aircraft.Wing.INCIDENCE] = dNF_dIwing diff --git a/aviary/mission/gasp_based/ode/groundroll_ode.py b/aviary/mission/gasp_based/ode/groundroll_ode.py index a4dcb145ba..b6687419ba 100644 --- a/aviary/mission/gasp_based/ode/groundroll_ode.py +++ b/aviary/mission/gasp_based/ode/groundroll_ode.py @@ -1,17 +1,14 @@ import numpy as np import openmdao.api as om -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.groundroll_eom import GroundrollEOM from aviary.mission.gasp_based.ode.params import ParamPort -from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.variable_info.enums import AnalysisScheme +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase -from aviary.variable_info.variable_meta_data import _MetaData -from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs +from aviary.variable_info.variables import Aircraft, Dynamic -class GroundrollODE(BaseODE): +class GroundrollODE(TwoDOFODE): """ODE for takeoff ground roll. This phase begins at the point when the aircraft begins accelerating down the runway @@ -22,119 +19,117 @@ class GroundrollODE(BaseODE): def initialize(self): super().initialize() self.options.declare( - 'external_subsystems', default=[], - desc='list of external subsystem builder instances to be added to the ODE') - self.options.declare( - 'meta_data', default=_MetaData, - desc='metadata associated with the variables to be passed into the ODE') - self.options.declare( - 'set_input_defaults', default=True, - desc='set input defaults for the ODE') + 'set_input_defaults', default=True, desc='set input defaults for the ODE' + ) def setup(self): - nn = self.options["num_nodes"] - analysis_scheme = self.options["analysis_scheme"] + nn = self.options['num_nodes'] aviary_options = self.options['aviary_options'] core_subsystems = self.options['core_subsystems'] subsystem_options = self.options['subsystem_options'] - if analysis_scheme is AnalysisScheme.SHOOTING: - add_SGM_required_inputs(self, { - Dynamic.Mission.DISTANCE: {'units': 'ft'}, - }) - # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) - self.add_atmosphere(nn) + self.add_atmosphere() # broadcast scalar i_wing to alpha for aero - self.add_subsystem("init_alpha", - om.ExecComp("alpha = i_wing", - i_wing={"units": "deg", "val": 1.1}, - alpha={"units": "deg", "val": 1.1*np.ones(nn)},), - promotes=[("i_wing", Aircraft.Wing.INCIDENCE), - "alpha"]) - - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'low_speed'} + self.add_subsystem( + 'init_alpha', + om.ExecComp( + 'alpha = i_wing', + i_wing={'units': 'deg', 'val': 1.1}, + alpha={'units': 'deg', 'val': 1.1 * np.ones(nn)}, + ), + promotes=[ + ('i_wing', Aircraft.Wing.INCIDENCE), + ('alpha', Dynamic.Vehicle.ANGLE_OF_ATTACK), + ], + ) + + kwargs = { + 'num_nodes': nn, + 'aviary_inputs': aviary_options, + 'method': 'low_speed', + } for subsystem in core_subsystems: # check if subsystem_options has entry for a subsystem of this name if subsystem.name in subsystem_options: kwargs.update(subsystem_options[subsystem.name]) system = subsystem.build_mission(**kwargs) if system is not None: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) if type(subsystem) is AerodynamicsBuilderBase: self.promotes( subsystem.name, - inputs=["alpha"], + inputs=[Dynamic.Vehicle.ANGLE_OF_ATTACK], src_indices=np.zeros(nn, dtype=int), ) - self.add_subsystem("groundroll_eom", GroundrollEOM(num_nodes=nn), promotes=["*"]) - - self.add_subsystem("exec", om.ExecComp(f"over_a = velocity / velocity_rate", - velocity_rate={"units": "kn/s", - "val": np.ones(nn)}, - velocity={"units": "kn", - "val": np.ones(nn)}, - over_a={"units": "s", "val": np.ones(nn)}, - has_diag_partials=True, - ), - promotes=["*"]) - - self.add_subsystem("exec2", om.ExecComp(f"dt_dv = 1 / velocity_rate", - velocity_rate={"units": "kn/s", - "val": np.ones(nn)}, - dt_dv={"units": "s/kn", - "val": np.ones(nn)}, - has_diag_partials=True, - ), - promotes=["*"]) + self.add_external_subsystems() + + self.add_subsystem('groundroll_eom', GroundrollEOM(num_nodes=nn), promotes=['*']) + + self.add_subsystem( + 'exec', + om.ExecComp( + 'over_a = velocity / velocity_rate', + velocity_rate={'units': 'kn/s', 'val': np.ones(nn)}, + velocity={'units': 'kn', 'val': np.ones(nn)}, + over_a={'units': 's', 'val': np.ones(nn)}, + has_diag_partials=True, + ), + promotes=['*'], + ) self.add_subsystem( - "exec3", + 'exec2', om.ExecComp( - "dmass_dv = mass_rate * dt_dv", - mass_rate={ - "units": "lbm/s", - "val": np.ones(nn)}, - dt_dv={ - "units": "s/kn", - "val": np.ones(nn)}, - dmass_dv={ - "units": "lbm/kn", - "val": np.ones(nn)}, + 'dt_dv = 1 / velocity_rate', + velocity_rate={'units': 'kn/s', 'val': np.ones(nn)}, + dt_dv={'units': 's/kn', 'val': np.ones(nn)}, + has_diag_partials=True, + ), + promotes=['*'], + ) + + self.add_subsystem( + 'exec3', + om.ExecComp( + 'dmass_dv = mass_rate * dt_dv', + mass_rate={'units': 'lbm/s', 'val': np.ones(nn)}, + dt_dv={'units': 's/kn', 'val': np.ones(nn)}, + dmass_dv={'units': 'lbm/kn', 'val': np.ones(nn)}, has_diag_partials=True, ), promotes_outputs=[ - "dmass_dv", + 'dmass_dv', ], promotes_inputs=[ - ("mass_rate", - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL), - "dt_dv"]) + ('mass_rate', Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL), + 'dt_dv', + ], + ) ParamPort.set_default_vals(self) if self.options['set_input_defaults']: - self.set_input_defaults("t_init_flaps", val=100.) - self.set_input_defaults("t_init_gear", val=100.) - self.set_input_defaults('aero_ramps.flap_factor:final_val', val=1.) - self.set_input_defaults('aero_ramps.gear_factor:final_val', val=1.) - self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=1.) - self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=1.) - self.set_input_defaults("t_curr", val=np.zeros(nn), units="s") - - self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units="deg") - self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units="ft") - self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units="kn") - self.set_input_defaults(Dynamic.Mission.VELOCITY_RATE, - val=np.zeros(nn), units="kn/s") - - self.set_input_defaults(Aircraft.Wing.INCIDENCE, val=1.0, units="deg") + self.set_input_defaults('t_init_flaps', val=100.0) + self.set_input_defaults('t_init_gear', val=100.0) + self.set_input_defaults('aero_ramps.flap_factor:final_val', val=1.0) + self.set_input_defaults('aero_ramps.gear_factor:final_val', val=1.0) + self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=1.0) + self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=1.0) + self.set_input_defaults('t_curr', val=np.zeros(nn), units='s') + + self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='deg') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units='ft') + self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='kn') + self.set_input_defaults(Dynamic.Mission.VELOCITY_RATE, val=np.zeros(nn), units='kn/s') + + self.set_input_defaults(Aircraft.Wing.INCIDENCE, val=1.0, units='deg') diff --git a/aviary/mission/gasp_based/ode/landing_eom.py b/aviary/mission/gasp_based/ode/landing_eom.py index faf6c17940..f5d4af13f6 100644 --- a/aviary/mission/gasp_based/ode/landing_eom.py +++ b/aviary/mission/gasp_based/ode/landing_eom.py @@ -7,9 +7,7 @@ class LandingAltitudeComponent(om.ExplicitComponent): - """ - Compute the landing altitude. - """ + """Compute the landing altitude.""" def setup(self): add_aviary_input(self, Mission.Landing.OBSTACLE_HEIGHT, val=50.0) @@ -17,7 +15,7 @@ def setup(self): add_aviary_output(self, Mission.Landing.INITIAL_ALTITUDE, val=0.0) - self.declare_partials(Mission.Landing.INITIAL_ALTITUDE, "*", val=1) + self.declare_partials(Mission.Landing.INITIAL_ALTITUDE, '*', val=1) def compute(self, inputs, outputs): ( @@ -31,158 +29,156 @@ def compute_partials(self, inputs, J): class GlideConditionComponent(om.ExplicitComponent): - """ - Compute the initial conditions of the 2DOF glide phase. - """ + """Compute the initial conditions of the 2DOF glide phase.""" def setup(self): + self.add_input(Dynamic.Atmosphere.DENSITY, val=0.0, units='slug/ft**3', desc='air density') + add_aviary_input(self, Mission.Landing.MAXIMUM_SINK_RATE, val=900.0) self.add_input( - Dynamic.Mission.DENSITY, val=0.0, units="slug/ft**3", desc="air density" + Dynamic.Vehicle.MASS, + val=0.0, + units='lbm', + desc='aircraft mass at start of landing', ) - add_aviary_input(self, Mission.Landing.MAXIMUM_SINK_RATE, val=900.0) - self.add_input(Dynamic.Mission.MASS, val=0.0, units="lbm", - desc="aircraft mass at start of landing") add_aviary_input(self, Aircraft.Wing.AREA, val=1.0) add_aviary_input(self, Mission.Landing.GLIDE_TO_STALL_RATIO, val=1.3) - self.add_input("CL_max", val=0.0, units='unitless', - desc="CLMX: max CL at approach altitude") + self.add_input( + 'CL_max', val=0.0, units='unitless', desc='CLMX: max CL at approach altitude' + ) add_aviary_input(self, Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, val=1.15) add_aviary_input(self, Mission.Landing.TOUCHDOWN_SINK_RATE, val=5.0) add_aviary_input(self, Mission.Landing.INITIAL_ALTITUDE, val=0.0) add_aviary_input(self, Mission.Landing.BRAKING_DELAY, val=1.0) - add_aviary_output(self, Mission.Landing.INITIAL_VELOCITY, val=0.0, - desc="glide speed calculated using TAS_stall") + add_aviary_output( + self, + Mission.Landing.INITIAL_VELOCITY, + val=0.0, + desc='glide speed calculated using TAS_stall', + ) add_aviary_output(self, Mission.Landing.STALL_VELOCITY, val=0.0) + self.add_output('TAS_touchdown', val=0.0, units='ft/s', desc='VTD: touchdown speed') self.add_output( - "TAS_touchdown", val=0.0, units="ft/s", desc="VTD: touchdown speed" - ) - self.add_output( - "density_ratio", val=0.0, units="unitless", desc="DRAT: density ratio for DLAND" + 'density_ratio', val=0.0, units='unitless', desc='DRAT: density ratio for DLAND' ) self.add_output( - "wing_loading_land", + 'wing_loading_land', val=0.0, - units="lbf/ft**2", - desc="WOS: wing loading at landing", + units='lbf/ft**2', + desc='WOS: wing loading at landing', ) self.add_output( - "theta", + 'theta', val=0.0, - units="rad", - desc="THETA: theta angle for approach to transition", + units='rad', + desc='THETA: theta angle for approach to transition', ) + self.add_output('glide_distance', val=0.0, units='ft', desc='DLGL: glide distance') self.add_output( - "glide_distance", val=0.0, units="ft", desc="DLGL: glide distance" - ) - self.add_output( - "tr_distance", + 'tr_distance', val=0.0, - units="ft", - desc="DLTR: distance covered by the flare maneuver", + units='ft', + desc='DLTR: distance covered by the flare maneuver', ) self.add_output( - "delay_distance", + 'delay_distance', val=0.0, - units="ft", - desc="DDELAY: delay distance - touchdown to brake application", - ) - self.add_output( - "flare_alt", val=0.0, units="ft", desc="HFLAR: altitude of flare maneuver" + units='ft', + desc='DDELAY: delay distance - touchdown to brake application', ) + self.add_output('flare_alt', val=0.0, units='ft', desc='HFLAR: altitude of flare maneuver') self.declare_partials( Mission.Landing.INITIAL_VELOCITY, [ - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, Mission.Landing.GLIDE_TO_STALL_RATIO, ], ) self.declare_partials( Mission.Landing.STALL_VELOCITY, [ - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, ], ) self.declare_partials( - "TAS_touchdown", + 'TAS_touchdown', [ Mission.Landing.GLIDE_TO_STALL_RATIO, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, ], ) - self.declare_partials("density_ratio", [Dynamic.Mission.DENSITY]) - self.declare_partials("wing_loading_land", [ - Dynamic.Mission.MASS, Aircraft.Wing.AREA]) + self.declare_partials('density_ratio', [Dynamic.Atmosphere.DENSITY]) + self.declare_partials('wing_loading_land', [Dynamic.Vehicle.MASS, Aircraft.Wing.AREA]) self.declare_partials( - "theta", + 'theta', [ Mission.Landing.MAXIMUM_SINK_RATE, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, Mission.Landing.GLIDE_TO_STALL_RATIO, ], ) self.declare_partials( - "glide_distance", + 'glide_distance', [ Mission.Landing.INITIAL_ALTITUDE, Mission.Landing.MAXIMUM_SINK_RATE, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, Mission.Landing.GLIDE_TO_STALL_RATIO, ], ) self.declare_partials( - "tr_distance", + 'tr_distance', [ Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, Mission.Landing.TOUCHDOWN_SINK_RATE, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, Mission.Landing.GLIDE_TO_STALL_RATIO, Mission.Landing.MAXIMUM_SINK_RATE, ], ) self.declare_partials( - "delay_distance", + 'delay_distance', [ Mission.Landing.GLIDE_TO_STALL_RATIO, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, Mission.Landing.BRAKING_DELAY, ], ) self.declare_partials( - "flare_alt", + 'flare_alt', [ Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, Mission.Landing.TOUCHDOWN_SINK_RATE, Mission.Landing.MAXIMUM_SINK_RATE, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, - "CL_max", - Dynamic.Mission.DENSITY, + 'CL_max', + Dynamic.Atmosphere.DENSITY, Mission.Landing.GLIDE_TO_STALL_RATIO, ], ) @@ -224,16 +220,16 @@ def compute(self, inputs, outputs): tr_distance = ((RZ * theta) / 2.0) * ((1.0 - gamma_touchdown / theta) ** 2) delay_distance = TAS_touchdown * time_delay - outputs["flare_alt"] = flare_alt + outputs['flare_alt'] = flare_alt outputs[Mission.Landing.INITIAL_VELOCITY] = TAS_glide outputs[Mission.Landing.STALL_VELOCITY] = TAS_stall - outputs["TAS_touchdown"] = TAS_touchdown - outputs["density_ratio"] = rho_app / RHO_SEA_LEVEL_ENGLISH - outputs["wing_loading_land"] = wing_loading_land - outputs["glide_distance"] = glide_distance - outputs["tr_distance"] = tr_distance - outputs["delay_distance"] = delay_distance - outputs["theta"] = theta + outputs['TAS_touchdown'] = TAS_touchdown + outputs['density_ratio'] = rho_app / RHO_SEA_LEVEL_ENGLISH + outputs['wing_loading_land'] = wing_loading_land + outputs['glide_distance'] = glide_distance + outputs['tr_distance'] = tr_distance + outputs['delay_distance'] = delay_distance + outputs['theta'] = theta def compute_partials(self, inputs, J): ( @@ -265,87 +261,76 @@ def compute_partials(self, inputs, J): dTasStall_dWingArea = ( (2 * weight / (CL_max * rho_app)) ** 0.5 * (-0.5) * wing_area ** (-1.5) ) - dTasStall_dClMax = ( - (2 * wing_loading_land / (rho_app)) ** 0.5 * (-0.5) * CL_max ** (-1.5) - ) - dTasStall_dRhoApp = ( - (2 * wing_loading_land / (CL_max)) ** 0.5 * (-0.5) * rho_app ** (-1.5) - ) - dTasGlide_dWeight = ( - dTasStall_dWeight * glide_to_stall_ratio - ) - dTasTd_dWeight = ( - touchdown_velocity_ratio * dTasStall_dWeight - ) + dTasStall_dClMax = (2 * wing_loading_land / (rho_app)) ** 0.5 * (-0.5) * CL_max ** (-1.5) + dTasStall_dRhoApp = (2 * wing_loading_land / (CL_max)) ** 0.5 * (-0.5) * rho_app ** (-1.5) + dTasGlide_dWeight = dTasStall_dWeight * glide_to_stall_ratio + dTasTd_dWeight = touchdown_velocity_ratio * dTasStall_dWeight dTheta_dWeight = ( (1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5) * (-rate_of_sink_max / (60.0 * TAS_glide**2)) * dTasGlide_dWeight ) - J[Mission.Landing.INITIAL_VELOCITY, Dynamic.Mission.MASS] = \ + J[Mission.Landing.INITIAL_VELOCITY, Dynamic.Vehicle.MASS] = ( dTasGlide_dWeight * GRAV_ENGLISH_LBM + ) J[Mission.Landing.INITIAL_VELOCITY, Aircraft.Wing.AREA] = dTasGlide_dWingArea = ( dTasStall_dWingArea * glide_to_stall_ratio ) - J[Mission.Landing.INITIAL_VELOCITY, "CL_max"] = dTasGlide_dClMax = ( + J[Mission.Landing.INITIAL_VELOCITY, 'CL_max'] = dTasGlide_dClMax = ( dTasStall_dClMax * glide_to_stall_ratio ) - J[Mission.Landing.INITIAL_VELOCITY, Dynamic.Mission.DENSITY] = ( - dTasGlide_dRhoApp - ) = (dTasStall_dRhoApp * glide_to_stall_ratio) - J[Mission.Landing.INITIAL_VELOCITY, - Mission.Landing.GLIDE_TO_STALL_RATIO] = TAS_stall + J[Mission.Landing.INITIAL_VELOCITY, Dynamic.Atmosphere.DENSITY] = dTasGlide_dRhoApp = ( + dTasStall_dRhoApp * glide_to_stall_ratio + ) + J[Mission.Landing.INITIAL_VELOCITY, Mission.Landing.GLIDE_TO_STALL_RATIO] = TAS_stall - J[Mission.Landing.STALL_VELOCITY, Dynamic.Mission.MASS] = \ + J[Mission.Landing.STALL_VELOCITY, Dynamic.Vehicle.MASS] = ( dTasStall_dWeight * GRAV_ENGLISH_LBM + ) J[Mission.Landing.STALL_VELOCITY, Aircraft.Wing.AREA] = dTasStall_dWingArea - J[Mission.Landing.STALL_VELOCITY, "CL_max"] = dTasStall_dClMax - J[Mission.Landing.STALL_VELOCITY, Dynamic.Mission.DENSITY] = dTasStall_dRhoApp + J[Mission.Landing.STALL_VELOCITY, 'CL_max'] = dTasStall_dClMax + J[Mission.Landing.STALL_VELOCITY, Dynamic.Atmosphere.DENSITY] = dTasStall_dRhoApp - J["TAS_touchdown", Mission.Landing.GLIDE_TO_STALL_RATIO] = dTasTd_dGlideToStallRatio = ( + J['TAS_touchdown', Mission.Landing.GLIDE_TO_STALL_RATIO] = dTasTd_dGlideToStallRatio = ( 0.5 * TAS_stall ) - J["TAS_touchdown", Dynamic.Mission.MASS] = dTasTd_dWeight * GRAV_ENGLISH_LBM - J["TAS_touchdown", Aircraft.Wing.AREA] = dTasTd_dWingArea = ( + J['TAS_touchdown', Dynamic.Vehicle.MASS] = dTasTd_dWeight * GRAV_ENGLISH_LBM + J['TAS_touchdown', Aircraft.Wing.AREA] = dTasTd_dWingArea = ( touchdown_velocity_ratio * dTasStall_dWingArea ) - J["TAS_touchdown", "CL_max"] = dTasTd_dClMax = ( - touchdown_velocity_ratio * dTasStall_dClMax - ) - J["TAS_touchdown", Dynamic.Mission.DENSITY] = dTasTd_dRhoApp = ( + J['TAS_touchdown', 'CL_max'] = dTasTd_dClMax = touchdown_velocity_ratio * dTasStall_dClMax + J['TAS_touchdown', Dynamic.Atmosphere.DENSITY] = dTasTd_dRhoApp = ( touchdown_velocity_ratio * dTasStall_dRhoApp ) - J["density_ratio", Dynamic.Mission.DENSITY] = 1 / RHO_SEA_LEVEL_ENGLISH + J['density_ratio', Dynamic.Atmosphere.DENSITY] = 1 / RHO_SEA_LEVEL_ENGLISH - J["wing_loading_land", Dynamic.Mission.MASS] = GRAV_ENGLISH_LBM / wing_area - J["wing_loading_land", Aircraft.Wing.AREA] = -weight / wing_area**2 + J['wing_loading_land', Dynamic.Vehicle.MASS] = GRAV_ENGLISH_LBM / wing_area + J['wing_loading_land', Aircraft.Wing.AREA] = -weight / wing_area**2 np.arcsin(rate_of_sink_max / (60.0 * TAS_glide)) - J["theta", Mission.Landing.MAXIMUM_SINK_RATE] = dTheta_dRateOfSinkMax = ( - (1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5) - * 1 - / (60.0 * TAS_glide) + J['theta', Mission.Landing.MAXIMUM_SINK_RATE] = dTheta_dRateOfSinkMax = ( + (1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5) * 1 / (60.0 * TAS_glide) ) - J["theta", Dynamic.Mission.MASS] = dTheta_dWeight * GRAV_ENGLISH_LBM - J["theta", Aircraft.Wing.AREA] = dTheta_dWingArea = ( + J['theta', Dynamic.Vehicle.MASS] = dTheta_dWeight * GRAV_ENGLISH_LBM + J['theta', Aircraft.Wing.AREA] = dTheta_dWingArea = ( (1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5) * (-rate_of_sink_max / (60.0 * TAS_glide**2)) * dTasGlide_dWingArea ) - J["theta", "CL_max"] = dTheta_dClMax = ( + J['theta', 'CL_max'] = dTheta_dClMax = ( (1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5) * (-rate_of_sink_max / (60.0 * TAS_glide**2)) * dTasGlide_dClMax ) - J["theta", Dynamic.Mission.DENSITY] = dTheta_dRhoApp = ( + J['theta', Dynamic.Atmosphere.DENSITY] = dTheta_dRhoApp = ( (1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5) * (-rate_of_sink_max / (60.0 * TAS_glide**2)) * dTasGlide_dRhoApp ) - J["theta", Mission.Landing.GLIDE_TO_STALL_RATIO] = dTheta_dGlideToStallRatio = ( + J['theta', Mission.Landing.GLIDE_TO_STALL_RATIO] = dTheta_dGlideToStallRatio = ( (1 - (rate_of_sink_max / (60.0 * TAS_glide)) ** 2) ** (-0.5) * (-rate_of_sink_max / (60.0 * TAS_glide**2)) * TAS_stall @@ -353,38 +338,27 @@ def compute_partials(self, inputs, J): approach_alt / np.tan(theta) - J["glide_distance", Mission.Landing.INITIAL_ALTITUDE] = 1 / np.tan(theta) - J["glide_distance", Mission.Landing.MAXIMUM_SINK_RATE] = ( - -approach_alt - / (np.tan(theta)) ** 2 - * (1 / np.cos(theta)) ** 2 - * dTheta_dRateOfSinkMax + J['glide_distance', Mission.Landing.INITIAL_ALTITUDE] = 1 / np.tan(theta) + J['glide_distance', Mission.Landing.MAXIMUM_SINK_RATE] = ( + -approach_alt / (np.tan(theta)) ** 2 * (1 / np.cos(theta)) ** 2 * dTheta_dRateOfSinkMax ) - J["glide_distance", Dynamic.Mission.MASS] = ( + J['glide_distance', Dynamic.Vehicle.MASS] = ( -approach_alt / (np.tan(theta)) ** 2 * (1 / np.cos(theta)) ** 2 - * dTheta_dWeight * GRAV_ENGLISH_LBM + * dTheta_dWeight + * GRAV_ENGLISH_LBM ) - J["glide_distance", Aircraft.Wing.AREA] = ( - -approach_alt - / (np.tan(theta)) ** 2 - * (1 / np.cos(theta)) ** 2 - * dTheta_dWingArea + J['glide_distance', Aircraft.Wing.AREA] = ( + -approach_alt / (np.tan(theta)) ** 2 * (1 / np.cos(theta)) ** 2 * dTheta_dWingArea ) - J["glide_distance", "CL_max"] = ( - -approach_alt - / (np.tan(theta)) ** 2 - * (1 / np.cos(theta)) ** 2 - * dTheta_dClMax + J['glide_distance', 'CL_max'] = ( + -approach_alt / (np.tan(theta)) ** 2 * (1 / np.cos(theta)) ** 2 * dTheta_dClMax ) - J["glide_distance", Dynamic.Mission.DENSITY] = ( - -approach_alt - / (np.tan(theta)) ** 2 - * (1 / np.cos(theta)) ** 2 - * dTheta_dRhoApp + J['glide_distance', Dynamic.Atmosphere.DENSITY] = ( + -approach_alt / (np.tan(theta)) ** 2 * (1 / np.cos(theta)) ** 2 * dTheta_dRhoApp ) - J["glide_distance", Mission.Landing.GLIDE_TO_STALL_RATIO] = ( + J['glide_distance', Mission.Landing.GLIDE_TO_STALL_RATIO] = ( -approach_alt / (np.tan(theta)) ** 2 * (1 / np.cos(theta)) ** 2 @@ -393,24 +367,12 @@ def compute_partials(self, inputs, J): RZ = TAS_glide**2 / G / (landing_flare_load_factor - 1.0) - dRZ_dWeight = ( - 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dWeight - ) - dRZ_dWingArea = ( - 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dWingArea - ) - dRZ_dClMax = ( - 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dClMax - ) - dRZ_dRhoApp = ( - 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dRhoApp - ) - dRZ_dGlideToStallRatio = ( - 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * TAS_stall - ) - dRZ_dLandingFlareLoadFactor = ( - -(TAS_glide**2) / G / (landing_flare_load_factor - 1.0) ** 2 - ) + dRZ_dWeight = 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dWeight + dRZ_dWingArea = 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dWingArea + dRZ_dClMax = 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dClMax + dRZ_dRhoApp = 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * dTasGlide_dRhoApp + dRZ_dGlideToStallRatio = 2 * TAS_glide / G / (landing_flare_load_factor - 1.0) * TAS_stall + dRZ_dLandingFlareLoadFactor = -(TAS_glide**2) / G / (landing_flare_load_factor - 1.0) ** 2 gamma_touchdown = rate_of_sink_td / TAS_glide @@ -434,11 +396,7 @@ def compute_partials(self, inputs, J): inter2 = (1.0 - gamma_touchdown / theta) ** 2 dInter2_dRateOfSinkMax = ( - 2 - * (1.0 - gamma_touchdown / theta) - * gamma_touchdown - / theta**2 - * dTheta_dRateOfSinkMax + 2 * (1.0 - gamma_touchdown / theta) * gamma_touchdown / theta**2 * dTheta_dRateOfSinkMax ) dInter2_dWeight = ( -2 @@ -467,110 +425,91 @@ def compute_partials(self, inputs, J): dInter2_dGlideToStallRatio = ( -2 * (1.0 - gamma_touchdown / theta) - * ( - theta * dGammaTd_dGlideToStallRatio - - gamma_touchdown * dTheta_dGlideToStallRatio - ) + * (theta * dGammaTd_dGlideToStallRatio - gamma_touchdown * dTheta_dGlideToStallRatio) / theta**2 ) dInter2_dRateOfSinkTd = ( -2 * (1.0 - gamma_touchdown / theta) * dGammaTd_dRateOfSinkTd / theta ) - tr_distance = inter1 * inter2 - - J["tr_distance", Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR] = ( + J['tr_distance', Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR] = ( dInter1_dLandingFlareLoadFactor * inter2 ) - J["tr_distance", Mission.Landing.MAXIMUM_SINK_RATE] = ( + J['tr_distance', Mission.Landing.MAXIMUM_SINK_RATE] = ( dInter1_dRateOfSinkMax * inter2 + inter1 * dInter2_dRateOfSinkMax ) - J["tr_distance", Dynamic.Mission.MASS] = ( + J['tr_distance', Dynamic.Vehicle.MASS] = ( dInter1_dWeight * inter2 + inter1 * dInter2_dWeight ) * GRAV_ENGLISH_LBM - J["tr_distance", Aircraft.Wing.AREA] = ( + J['tr_distance', Aircraft.Wing.AREA] = ( dInter1_dWingArea * inter2 + inter1 * dInter2_dWingArea ) - J["tr_distance", "CL_max"] = dInter1_dClMax * inter2 + inter1 * dInter2_dClMax - J["tr_distance", Dynamic.Mission.DENSITY] = ( + J['tr_distance', 'CL_max'] = dInter1_dClMax * inter2 + inter1 * dInter2_dClMax + J['tr_distance', Dynamic.Atmosphere.DENSITY] = ( dInter1_dRhoApp * inter2 + inter1 * dInter2_dRhoApp ) - J["tr_distance", Mission.Landing.GLIDE_TO_STALL_RATIO] = ( + J['tr_distance', Mission.Landing.GLIDE_TO_STALL_RATIO] = ( dInter1_dGlideToStallRatio * inter2 + inter1 * dInter2_dGlideToStallRatio ) - J["tr_distance", Mission.Landing.TOUCHDOWN_SINK_RATE] = inter1 * dInter2_dRateOfSinkTd + J['tr_distance', Mission.Landing.TOUCHDOWN_SINK_RATE] = inter1 * dInter2_dRateOfSinkTd - J["delay_distance", Mission.Landing.GLIDE_TO_STALL_RATIO] = ( + J['delay_distance', Mission.Landing.GLIDE_TO_STALL_RATIO] = ( time_delay * dTasTd_dGlideToStallRatio ) - J["delay_distance", Dynamic.Mission.MASS] = \ - time_delay * dTasTd_dWeight * GRAV_ENGLISH_LBM - J["delay_distance", Aircraft.Wing.AREA] = time_delay * dTasTd_dWingArea - J["delay_distance", "CL_max"] = time_delay * dTasTd_dClMax - J["delay_distance", Dynamic.Mission.DENSITY] = time_delay * dTasTd_dRhoApp - J["delay_distance", Mission.Landing.BRAKING_DELAY] = TAS_touchdown - - flare_alt = ( - TAS_glide**2 - * (theta**2 - gamma_touchdown**2) - / (2.0 * G * (landing_flare_load_factor - 1.0)) - ) - - J["flare_alt", Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR] = ( + J['delay_distance', Dynamic.Vehicle.MASS] = time_delay * dTasTd_dWeight * GRAV_ENGLISH_LBM + J['delay_distance', Aircraft.Wing.AREA] = time_delay * dTasTd_dWingArea + J['delay_distance', 'CL_max'] = time_delay * dTasTd_dClMax + J['delay_distance', Dynamic.Atmosphere.DENSITY] = time_delay * dTasTd_dRhoApp + J['delay_distance', Mission.Landing.BRAKING_DELAY] = TAS_touchdown + J['flare_alt', Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR] = ( -(TAS_glide**2) * (theta**2 - gamma_touchdown**2) / (2.0 * G * (landing_flare_load_factor - 1.0)) ** 2 * 2 * G ) - J["flare_alt", Mission.Landing.TOUCHDOWN_SINK_RATE] = ( + J['flare_alt', Mission.Landing.TOUCHDOWN_SINK_RATE] = ( -2 * TAS_glide**2 * gamma_touchdown / (2.0 * G * (landing_flare_load_factor - 1.0)) * dGammaTd_dRateOfSinkTd ) - J["flare_alt", Mission.Landing.MAXIMUM_SINK_RATE] = ( + J['flare_alt', Mission.Landing.MAXIMUM_SINK_RATE] = ( 2 * TAS_glide**2 * theta / (2.0 * G * (landing_flare_load_factor - 1.0)) * dTheta_dRateOfSinkMax ) - J["flare_alt", Dynamic.Mission.MASS] = ( + J['flare_alt', Dynamic.Vehicle.MASS] = ( 1 / (2.0 * G * (landing_flare_load_factor - 1.0)) * ( 2 * TAS_glide * dTasGlide_dWeight * (theta**2 - gamma_touchdown**2) + TAS_glide**2 * (2 * theta * dTheta_dWeight - 2 * gamma_touchdown * dGammaTd_dWeight) - ) * GRAV_ENGLISH_LBM + ) + * GRAV_ENGLISH_LBM ) - J["flare_alt", Aircraft.Wing.AREA] = ( + J['flare_alt', Aircraft.Wing.AREA] = ( 1 / (2.0 * G * (landing_flare_load_factor - 1.0)) * ( - 2 - * TAS_glide - * dTasGlide_dWingArea - * (theta**2 - gamma_touchdown**2) + 2 * TAS_glide * dTasGlide_dWingArea * (theta**2 - gamma_touchdown**2) + TAS_glide**2 - * ( - 2 * theta * dTheta_dWingArea - - 2 * gamma_touchdown * dGammaTd_dWingArea - ) + * (2 * theta * dTheta_dWingArea - 2 * gamma_touchdown * dGammaTd_dWingArea) ) ) - J["flare_alt", "CL_max"] = ( + J['flare_alt', 'CL_max'] = ( 1 / (2.0 * G * (landing_flare_load_factor - 1.0)) * ( 2 * TAS_glide * dTasGlide_dClMax * (theta**2 - gamma_touchdown**2) - + TAS_glide**2 - * (2 * theta * dTheta_dClMax - 2 * gamma_touchdown * dGammaTd_dClMax) + + TAS_glide**2 * (2 * theta * dTheta_dClMax - 2 * gamma_touchdown * dGammaTd_dClMax) ) ) - J["flare_alt", Dynamic.Mission.DENSITY] = ( + J['flare_alt', Dynamic.Atmosphere.DENSITY] = ( 1 / (2.0 * G * (landing_flare_load_factor - 1.0)) * ( @@ -579,7 +518,7 @@ def compute_partials(self, inputs, J): * (2 * theta * dTheta_dRhoApp - 2 * gamma_touchdown * dGammaTd_dRhoApp) ) ) - J["flare_alt", Mission.Landing.GLIDE_TO_STALL_RATIO] = ( + J['flare_alt', Mission.Landing.GLIDE_TO_STALL_RATIO] = ( 1 / (2.0 * G * (landing_flare_load_factor - 1.0)) * ( @@ -594,113 +533,108 @@ def compute_partials(self, inputs, J): class LandingGroundRollComponent(om.ExplicitComponent): - """ - Compute the groundroll distance and average acceleration/deceleration - """ + """Compute the groundroll distance and average acceleration/deceleration.""" def setup(self): - - self.add_input("touchdown_CD", val=0.0, units='unitless', - desc="CDRL: CD at touchdown") - self.add_input("touchdown_CL", val=0.0, units='unitless', - desc="CLRL: CL at touchdown") + self.add_input('touchdown_CD', val=0.0, units='unitless', desc='CDRL: CD at touchdown') + self.add_input('touchdown_CL', val=0.0, units='unitless', desc='CLRL: CL at touchdown') add_aviary_input(self, Mission.Landing.STALL_VELOCITY, val=0.0) + self.add_input('TAS_touchdown', val=0.0, units='ft/s', desc='VTD: velocity at touchdown') self.add_input( - "TAS_touchdown", val=0.0, units="ft/s", desc="VTD: velocity at touchdown" - ) - self.add_input( - "thrust_idle", + 'thrust_idle', val=0.0, - units="lbf", - desc="TIDLE: idle thrust at start of landing", + units='lbf', + desc='TIDLE: idle thrust at start of landing', ) self.add_input( - "density_ratio", val=0.0, units="unitless", desc="DRAT: density ratio for DLAND" + 'density_ratio', val=0.0, units='unitless', desc='DRAT: density ratio for DLAND' ) self.add_input( - "wing_loading_land", + 'wing_loading_land', val=0.0, - units="lbf/ft**2", - desc="WOS: wing loading at landing", + units='lbf/ft**2', + desc='WOS: wing loading at landing', ) + self.add_input('glide_distance', val=0.0, units='ft', desc='DLGL: glide distance') self.add_input( - "glide_distance", val=0.0, units="ft", desc="DLGL: glide distance" - ) - self.add_input( - "tr_distance", + 'tr_distance', val=0.0, - units="ft", - desc="DLTR: distance from glide to touchdown", + units='ft', + desc='DLTR: distance from glide to touchdown', ) self.add_input( - "delay_distance", + 'delay_distance', val=0.0, - units="ft", - desc="DDELAY: touchdown to brake application", + units='ft', + desc='DDELAY: touchdown to brake application', ) self.add_input( - "CL_max", val=0.0, units="unitless", desc="CLMX: max CL at approach altitude" + 'CL_max', val=0.0, units='unitless', desc='CLMX: max CL at approach altitude' ) self.add_input( - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, val=0.0, - units="lbm", - desc="WL: aircraft mass at start of landing", + units='lbm', + desc='WL: aircraft mass at start of landing', ) self.add_output( - "ground_roll_distance", + 'ground_roll_distance', val=0.0, - units="ft", - desc="DLG: distance during braked ground roll", + units='ft', + desc='DLG: distance during braked ground roll', ) add_aviary_output(self, Mission.Landing.GROUND_DISTANCE, val=0.0) - self.add_output("average_acceleration", val=0.0, units="unitless", # renamed from GASP var ABAR - desc="average acceleration/decelleration based on starting speed (TAS) and rollout distance") + self.add_output( + 'average_acceleration', + val=0.0, + units='unitless', # renamed from GASP var ABAR + desc='average acceleration/decelleration based on starting speed (TAS) and rollout distance', + ) self.declare_partials( - "ground_roll_distance", + 'ground_roll_distance', [ - "wing_loading_land", - "density_ratio", - "touchdown_CD", - "touchdown_CL", - "thrust_idle", - Dynamic.Mission.MASS, - "CL_max", + 'wing_loading_land', + 'density_ratio', + 'touchdown_CD', + 'touchdown_CL', + 'thrust_idle', + Dynamic.Vehicle.MASS, + 'CL_max', Mission.Landing.STALL_VELOCITY, - "TAS_touchdown", + 'TAS_touchdown', ], ) self.declare_partials( Mission.Landing.GROUND_DISTANCE, [ - "wing_loading_land", - "density_ratio", - "touchdown_CD", - "touchdown_CL", - "thrust_idle", - Dynamic.Mission.MASS, - "CL_max", + 'wing_loading_land', + 'density_ratio', + 'touchdown_CD', + 'touchdown_CL', + 'thrust_idle', + Dynamic.Vehicle.MASS, + 'CL_max', Mission.Landing.STALL_VELOCITY, - "TAS_touchdown", - "tr_distance", - "delay_distance", - "glide_distance", + 'TAS_touchdown', + 'tr_distance', + 'delay_distance', + 'glide_distance', ], ) self.declare_partials( - "average_acceleration", + 'average_acceleration', [ - "TAS_touchdown", - "wing_loading_land", - "density_ratio", - "touchdown_CD", - "touchdown_CL", - "thrust_idle", - Dynamic.Mission.MASS, - "CL_max", + 'TAS_touchdown', + 'wing_loading_land', + 'density_ratio', + 'touchdown_CD', + 'touchdown_CL', + 'thrust_idle', + Dynamic.Vehicle.MASS, + 'CL_max', Mission.Landing.STALL_VELOCITY, ], ) @@ -731,17 +665,13 @@ def compute(self, inputs, outputs): FRAT = MUB - thrust_to_landing_weight_ratio ALN = np.log(FRAT / (FRAT + ARAT)) - ground_roll_distance = ( - -13.0287 * wing_loading_land * ALN / (density_ratio * DLRL) - ) - total_distance = ( - ground_roll_distance + tr_distance + delay_distance + glide_distance - ) + ground_roll_distance = -13.0287 * wing_loading_land * ALN / (density_ratio * DLRL) + total_distance = ground_roll_distance + tr_distance + delay_distance + glide_distance average_acceleration = TAS_touchdown**2.0 / (ground_roll_distance * 2.0 * G) - outputs["ground_roll_distance"] = ground_roll_distance + outputs['ground_roll_distance'] = ground_roll_distance outputs[Mission.Landing.GROUND_DISTANCE] = total_distance - outputs["average_acceleration"] = average_acceleration + outputs['average_acceleration'] = average_acceleration def compute_partials(self, inputs, J): ( @@ -771,12 +701,8 @@ def compute_partials(self, inputs, J): dDLRL_dTouchdownCD = 1 dDLRL_dTouchdownCL = -MUB - dARAT_dTouchdownCD = dDLRL_dTouchdownCD / ( - CL_max * (TAS_stall / TAS_touchdown) ** 2 - ) - dARAT_dTouchdownCL = dDLRL_dTouchdownCL / ( - CL_max * (TAS_stall / TAS_touchdown) ** 2 - ) + dARAT_dTouchdownCD = dDLRL_dTouchdownCD / (CL_max * (TAS_stall / TAS_touchdown) ** 2) + dARAT_dTouchdownCL = dDLRL_dTouchdownCL / (CL_max * (TAS_stall / TAS_touchdown) ** 2) dARAT_dClMax = -DLRL / (CL_max**2 * (TAS_stall / TAS_touchdown) ** 2) dARAT_dTasStall = -2 * DLRL / (CL_max * (TAS_stall**3 / TAS_touchdown**2)) dARAT_dTasTouchdown = 2 * TAS_touchdown * DLRL / (CL_max * (TAS_stall) ** 2) @@ -785,16 +711,10 @@ def compute_partials(self, inputs, J): dFRAT_dWeight = thrust_idle / weight**2 dALN_dTouchdownCD = ( - 1 - / (FRAT / (FRAT + ARAT)) - * (-FRAT / (FRAT + ARAT) ** 2) - * dARAT_dTouchdownCD + 1 / (FRAT / (FRAT + ARAT)) * (-FRAT / (FRAT + ARAT) ** 2) * dARAT_dTouchdownCD ) dALN_dTouchdownCL = ( - 1 - / (FRAT / (FRAT + ARAT)) - * (-FRAT / (FRAT + ARAT) ** 2) - * dARAT_dTouchdownCL + 1 / (FRAT / (FRAT + ARAT)) * (-FRAT / (FRAT + ARAT) ** 2) * dARAT_dTouchdownCL ) dALN_dThrustIdle = ( 1 @@ -804,120 +724,90 @@ def compute_partials(self, inputs, J): * dFRAT_dThrustIdle ) dALN_dWeight = ( - 1 - / (FRAT / (FRAT + ARAT)) - * ((FRAT + ARAT) - FRAT) - / (FRAT + ARAT) ** 2 - * dFRAT_dWeight - ) - dALN_dClMax = ( - 1 / (FRAT / (FRAT + ARAT)) * (-FRAT / (FRAT + ARAT) ** 2 * dARAT_dClMax) - ) - dALN_dTasStall = ( - 1 / (FRAT / (FRAT + ARAT)) * (-FRAT / (FRAT + ARAT) ** 2 * dARAT_dTasStall) + 1 / (FRAT / (FRAT + ARAT)) * ((FRAT + ARAT) - FRAT) / (FRAT + ARAT) ** 2 * dFRAT_dWeight ) + dALN_dClMax = 1 / (FRAT / (FRAT + ARAT)) * (-FRAT / (FRAT + ARAT) ** 2 * dARAT_dClMax) + dALN_dTasStall = 1 / (FRAT / (FRAT + ARAT)) * (-FRAT / (FRAT + ARAT) ** 2 * dARAT_dTasStall) dALN_dTasTouchdown = ( - 1 - / (FRAT / (FRAT + ARAT)) - * (-FRAT / (FRAT + ARAT) ** 2 * dARAT_dTasTouchdown) + 1 / (FRAT / (FRAT + ARAT)) * (-FRAT / (FRAT + ARAT) ** 2 * dARAT_dTasTouchdown) ) - ground_roll_distance = ( - -13.0287 * wing_loading_land * ALN / (density_ratio * DLRL) - ) - dGRD_dWeight = ( - -13.0287 * wing_loading_land * dALN_dWeight / (density_ratio * DLRL) - ) + ground_roll_distance = -13.0287 * wing_loading_land * ALN / (density_ratio * DLRL) + dGRD_dWeight = -13.0287 * wing_loading_land * dALN_dWeight / (density_ratio * DLRL) - J["ground_roll_distance", "wing_loading_land"] = dGRD_dWingLoadingLand = ( + J['ground_roll_distance', 'wing_loading_land'] = dGRD_dWingLoadingLand = ( -13.0287 * ALN / (density_ratio * DLRL) ) - J["ground_roll_distance", "density_ratio"] = dGRD_dDensityRatio = ( + J['ground_roll_distance', 'density_ratio'] = dGRD_dDensityRatio = ( 13.0287 * wing_loading_land * ALN / (density_ratio**2 * DLRL) ) - J["ground_roll_distance", "touchdown_CD"] = dGRD_dTouchdownCD = ( + J['ground_roll_distance', 'touchdown_CD'] = dGRD_dTouchdownCD = ( -13.0287 * (wing_loading_land / density_ratio) * (DLRL * dALN_dTouchdownCD - ALN * dDLRL_dTouchdownCD) / DLRL**2 ) - J["ground_roll_distance", "touchdown_CL"] = dGRD_dTouchdownCL = ( + J['ground_roll_distance', 'touchdown_CL'] = dGRD_dTouchdownCL = ( -13.0287 * (wing_loading_land / density_ratio) * (DLRL * dALN_dTouchdownCL - ALN * dDLRL_dTouchdownCL) / DLRL**2 ) - J["ground_roll_distance", "thrust_idle"] = dGRD_dThrustIdle = ( + J['ground_roll_distance', 'thrust_idle'] = dGRD_dThrustIdle = ( -13.0287 * wing_loading_land * dALN_dThrustIdle / (density_ratio * DLRL) ) - J["ground_roll_distance", Dynamic.Mission.MASS] = dGRD_dWeight * GRAV_ENGLISH_LBM - J["ground_roll_distance", "CL_max"] = dGRD_dClMax = ( + J['ground_roll_distance', Dynamic.Vehicle.MASS] = dGRD_dWeight * GRAV_ENGLISH_LBM + J['ground_roll_distance', 'CL_max'] = dGRD_dClMax = ( -13.0287 * wing_loading_land * dALN_dClMax / (density_ratio * DLRL) ) - J["ground_roll_distance", Mission.Landing.STALL_VELOCITY] = dGRD_dTasStall = ( + J['ground_roll_distance', Mission.Landing.STALL_VELOCITY] = dGRD_dTasStall = ( -13.0287 * wing_loading_land * dALN_dTasStall / (density_ratio * DLRL) ) - J["ground_roll_distance", "TAS_touchdown"] = dGRD_dTasTouchdown = ( + J['ground_roll_distance', 'TAS_touchdown'] = dGRD_dTasTouchdown = ( -13.0287 * wing_loading_land * dALN_dTasTouchdown / (density_ratio * DLRL) ) - J[Mission.Landing.GROUND_DISTANCE, - "wing_loading_land"] = dGRD_dWingLoadingLand - J[Mission.Landing.GROUND_DISTANCE, "density_ratio"] = dGRD_dDensityRatio - J[Mission.Landing.GROUND_DISTANCE, "touchdown_CD"] = dGRD_dTouchdownCD - J[Mission.Landing.GROUND_DISTANCE, "touchdown_CL"] = dGRD_dTouchdownCL - J[Mission.Landing.GROUND_DISTANCE, "thrust_idle"] = dGRD_dThrustIdle - J[Mission.Landing.GROUND_DISTANCE, Dynamic.Mission.MASS] = \ - dGRD_dWeight * GRAV_ENGLISH_LBM - J[Mission.Landing.GROUND_DISTANCE, "CL_max"] = dGRD_dClMax - J[Mission.Landing.GROUND_DISTANCE, - Mission.Landing.STALL_VELOCITY] = dGRD_dTasStall - J[Mission.Landing.GROUND_DISTANCE, "TAS_touchdown"] = dGRD_dTasTouchdown - J[Mission.Landing.GROUND_DISTANCE, "tr_distance"] = 1 - J[Mission.Landing.GROUND_DISTANCE, "delay_distance"] = 1 - J[Mission.Landing.GROUND_DISTANCE, "glide_distance"] = 1 - - J["average_acceleration", "wing_loading_land"] = ( - -(TAS_touchdown**2.0) - / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dWingLoadingLand + J[Mission.Landing.GROUND_DISTANCE, 'wing_loading_land'] = dGRD_dWingLoadingLand + J[Mission.Landing.GROUND_DISTANCE, 'density_ratio'] = dGRD_dDensityRatio + J[Mission.Landing.GROUND_DISTANCE, 'touchdown_CD'] = dGRD_dTouchdownCD + J[Mission.Landing.GROUND_DISTANCE, 'touchdown_CL'] = dGRD_dTouchdownCL + J[Mission.Landing.GROUND_DISTANCE, 'thrust_idle'] = dGRD_dThrustIdle + J[Mission.Landing.GROUND_DISTANCE, Dynamic.Vehicle.MASS] = dGRD_dWeight * GRAV_ENGLISH_LBM + J[Mission.Landing.GROUND_DISTANCE, 'CL_max'] = dGRD_dClMax + J[Mission.Landing.GROUND_DISTANCE, Mission.Landing.STALL_VELOCITY] = dGRD_dTasStall + J[Mission.Landing.GROUND_DISTANCE, 'TAS_touchdown'] = dGRD_dTasTouchdown + J[Mission.Landing.GROUND_DISTANCE, 'tr_distance'] = 1 + J[Mission.Landing.GROUND_DISTANCE, 'delay_distance'] = 1 + J[Mission.Landing.GROUND_DISTANCE, 'glide_distance'] = 1 + + J['average_acceleration', 'wing_loading_land'] = ( + -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) * dGRD_dWingLoadingLand ) - J["average_acceleration", "density_ratio"] = ( - -(TAS_touchdown**2.0) - / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dDensityRatio + J['average_acceleration', 'density_ratio'] = ( + -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) * dGRD_dDensityRatio ) - J["average_acceleration", "touchdown_CD"] = ( - -(TAS_touchdown**2.0) - / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dTouchdownCD + J['average_acceleration', 'touchdown_CD'] = ( + -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) * dGRD_dTouchdownCD ) - J["average_acceleration", "touchdown_CL"] = ( - -(TAS_touchdown**2.0) - / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dTouchdownCL + J['average_acceleration', 'touchdown_CL'] = ( + -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) * dGRD_dTouchdownCL ) - J["average_acceleration", "thrust_idle"] = ( - -(TAS_touchdown**2.0) - / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dThrustIdle + J['average_acceleration', 'thrust_idle'] = ( + -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) * dGRD_dThrustIdle ) - J["average_acceleration", Dynamic.Mission.MASS] = ( + J['average_acceleration', Dynamic.Vehicle.MASS] = ( -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dWeight * GRAV_ENGLISH_LBM + * dGRD_dWeight + * GRAV_ENGLISH_LBM ) - J["average_acceleration", "CL_max"] = ( - -(TAS_touchdown**2.0) - / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dClMax + J['average_acceleration', 'CL_max'] = ( + -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) * dGRD_dClMax ) - J["average_acceleration", Mission.Landing.STALL_VELOCITY] = ( - -(TAS_touchdown**2.0) - / (ground_roll_distance**2 * 2.0 * G) - * dGRD_dTasStall + J['average_acceleration', Mission.Landing.STALL_VELOCITY] = ( + -(TAS_touchdown**2.0) / (ground_roll_distance**2 * 2.0 * G) * dGRD_dTasStall ) - J["average_acceleration", "TAS_touchdown"] = ( + J['average_acceleration', 'TAS_touchdown'] = ( ground_roll_distance * 2 * G * 2 * TAS_touchdown - TAS_touchdown**2 * 2 * G * dGRD_dTasTouchdown ) / (ground_roll_distance * 2.0 * G) ** 2 diff --git a/aviary/mission/gasp_based/ode/landing_ode.py b/aviary/mission/gasp_based/ode/landing_ode.py index acb3627fd5..2076e930b6 100644 --- a/aviary/mission/gasp_based/ode/landing_ode.py +++ b/aviary/mission/gasp_based/ode/landing_ode.py @@ -1,30 +1,31 @@ -from aviary.subsystems.atmosphere.atmosphere import Atmosphere +import numpy as np -from aviary.mission.gasp_based.ode.base_ode import BaseODE -from aviary.mission.gasp_based.ode.params import ParamPort from aviary.mission.gasp_based.ode.landing_eom import ( - GlideConditionComponent, LandingAltitudeComponent, - LandingGroundRollComponent) + GlideConditionComponent, + LandingAltitudeComponent, + LandingGroundRollComponent, +) +from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Aircraft, Dynamic, Mission -class LandingSegment(BaseODE): - """ - Group for a 2-degree of freedom landing ODE. - """ +class LandingSegment(TwoDOFODE): + """Group for a 2-degree of freedom landing ODE.""" def setup(self): aviary_options = self.options['aviary_options'] core_subsystems = self.options['core_subsystems'] # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) self.add_subsystem( - "approach_alt_comp", + 'approach_alt_comp', LandingAltitudeComponent(), promotes_inputs=[ Mission.Landing.OBSTACLE_HEIGHT, @@ -38,15 +39,15 @@ def setup(self): subsys=Atmosphere(num_nodes=1, input_speed_type=SpeedType.MACH), promotes_inputs=[ (Dynamic.Mission.ALTITUDE, Mission.Landing.INITIAL_ALTITUDE), - (Dynamic.Mission.MACH, Mission.Landing.INITIAL_MACH), + (Dynamic.Atmosphere.MACH, Mission.Landing.INITIAL_MACH), ], promotes_outputs=[ - Dynamic.Mission.DENSITY, - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, - "viscosity", - Dynamic.Mission.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + 'viscosity', + Dynamic.Atmosphere.DYNAMIC_PRESSURE, ], ) @@ -55,57 +56,67 @@ def setup(self): if isinstance(subsystem, AerodynamicsBuilderBase): kwargs = {'method': 'low_speed'} aero_builder = subsystem - aero_system = subsystem.build_mission(num_nodes=1, - aviary_inputs=aviary_options, - **kwargs) + aero_system = subsystem.build_mission( + num_nodes=1, aviary_inputs=aviary_options, **kwargs + ) self.add_subsystem( subsystem.name, aero_system, promotes_inputs=[ - "*", - (Dynamic.Mission.ALTITUDE, Mission.Landing.INITIAL_ALTITUDE), - Dynamic.Mission.DENSITY, - Dynamic.Mission.SPEED_OF_SOUND, - "viscosity", - ("airport_alt", Mission.Landing.AIRPORT_ALTITUDE), - (Dynamic.Mission.MACH, Mission.Landing.INITIAL_MACH), - Dynamic.Mission.DYNAMIC_PRESSURE, - ("flap_defl", Aircraft.Wing.FLAP_DEFLECTION_LANDING), - ("t_init_flaps", "t_init_flaps_app"), - ("t_init_gear", "t_init_gear_app"), - ("CL_max_flaps", Mission.Landing.LIFT_COEFFICIENT_MAX), + '*', + ( + Dynamic.Mission.ALTITUDE, + Mission.Landing.INITIAL_ALTITUDE, + ), + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + 'viscosity', + ('airport_alt', Mission.Landing.AIRPORT_ALTITUDE), + (Dynamic.Atmosphere.MACH, Mission.Landing.INITIAL_MACH), + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + ('flap_defl', Aircraft.Wing.FLAP_DEFLECTION_LANDING), + ('t_init_flaps', 't_init_flaps_app'), + ('t_init_gear', 't_init_gear_app'), + ('CL_max_flaps', Mission.Landing.LIFT_COEFFICIENT_MAX), ( - "dCL_flaps_model", + 'dCL_flaps_model', Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT, ), ( - "dCD_flaps_model", + 'dCD_flaps_model', Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT, ), ], - promotes_outputs=["CL_max"], + promotes_outputs=['CL_max'], ) if isinstance(subsystem, PropulsionBuilderBase): propulsion_system = subsystem.build_mission( - num_nodes=1, aviary_inputs=aviary_options) - propulsion_mission = self.add_subsystem(subsystem.name, - propulsion_system, - promotes_inputs=[ - "*", (Dynamic.Mission.ALTITUDE, Mission.Landing.INITIAL_ALTITUDE), (Dynamic.Mission.MACH, Mission.Landing.INITIAL_MACH)], - promotes_outputs=[(Dynamic.Mission.THRUST_TOTAL, "thrust_idle")]) - propulsion_mission.set_input_defaults(Dynamic.Mission.THROTTLE, 0.0) + num_nodes=1, aviary_inputs=aviary_options + ) + propulsion_mission = self.add_subsystem( + subsystem.name, + propulsion_system, + promotes_inputs=[ + '*', + (Dynamic.Atmosphere.MACH, Mission.Landing.INITIAL_MACH), + ], + promotes_outputs=[(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, 'thrust_idle')], + ) + propulsion_mission.set_input_defaults(Dynamic.Vehicle.Propulsion.THROTTLE, 0.0) + + self.add_external_subsystems() self.add_subsystem( - "glide", + 'glide', GlideConditionComponent(), promotes_inputs=[ - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, Mission.Landing.MAXIMUM_SINK_RATE, - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, Aircraft.Wing.AREA, Mission.Landing.GLIDE_TO_STALL_RATIO, - "CL_max", + 'CL_max', Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, Mission.Landing.TOUCHDOWN_SINK_RATE, Mission.Landing.INITIAL_ALTITUDE, @@ -114,14 +125,14 @@ def setup(self): promotes_outputs=[ Mission.Landing.INITIAL_VELOCITY, Mission.Landing.STALL_VELOCITY, - "TAS_touchdown", - "density_ratio", - "wing_loading_land", - "theta", - "glide_distance", - "tr_distance", - "delay_distance", - "flare_alt", + 'TAS_touchdown', + 'density_ratio', + 'wing_loading_land', + 'theta', + 'glide_distance', + 'tr_distance', + 'delay_distance', + 'flare_alt', ], ) @@ -129,76 +140,75 @@ def setup(self): name='atmosphere_td', subsys=Atmosphere(num_nodes=1), promotes_inputs=[ - (Dynamic.Mission.ALTITUDE, Mission.Landing.AIRPORT_ALTITUDE), - (Dynamic.Mission.VELOCITY, "TAS_touchdown"), + Dynamic.Mission.ALTITUDE, + (Dynamic.Mission.VELOCITY, 'TAS_touchdown'), ], promotes_outputs=[ - (Dynamic.Mission.DENSITY, "rho_td"), - (Dynamic.Mission.SPEED_OF_SOUND, "sos_td"), - (Dynamic.Mission.TEMPERATURE, "T_td"), - ("viscosity", "viscosity_td"), - (Dynamic.Mission.DYNAMIC_PRESSURE, "q_td"), - (Dynamic.Mission.MACH, "mach_td"), + (Dynamic.Atmosphere.DENSITY, 'rho_td'), + (Dynamic.Atmosphere.SPEED_OF_SOUND, 'sos_td'), + (Dynamic.Atmosphere.TEMPERATURE, 'T_td'), + ('viscosity', 'viscosity_td'), + (Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'q_td'), + (Dynamic.Atmosphere.MACH, 'mach_td'), ], ) - kwargs = {'method': 'low_speed', - 'retract_flaps': True, - 'retract_gear': False} + kwargs = {'method': 'low_speed', 'retract_flaps': True, 'retract_gear': False} self.add_subsystem( - "aero_td", - aero_builder.build_mission( - num_nodes=1, aviary_inputs=aviary_options, **kwargs - ), + 'aero_td', + aero_builder.build_mission(num_nodes=1, aviary_inputs=aviary_options, **kwargs), promotes_inputs=[ - "*", - (Dynamic.Mission.ALTITUDE, Mission.Landing.AIRPORT_ALTITUDE), - (Dynamic.Mission.DENSITY, "rho_td"), - (Dynamic.Mission.SPEED_OF_SOUND, "sos_td"), - ("viscosity", "viscosity_td"), - ("airport_alt", Mission.Landing.AIRPORT_ALTITUDE), - (Dynamic.Mission.MACH, "mach_td"), - (Dynamic.Mission.DYNAMIC_PRESSURE, "q_td"), - ("alpha", Aircraft.Wing.INCIDENCE), - ("flap_defl", Aircraft.Wing.FLAP_DEFLECTION_LANDING), - ("CL_max_flaps", Mission.Landing.LIFT_COEFFICIENT_MAX), + '*', + Dynamic.Mission.ALTITUDE, + (Dynamic.Atmosphere.DENSITY, 'rho_td'), + (Dynamic.Atmosphere.SPEED_OF_SOUND, 'sos_td'), + ('viscosity', 'viscosity_td'), + ('airport_alt', Mission.Landing.AIRPORT_ALTITUDE), + (Dynamic.Atmosphere.MACH, 'mach_td'), + (Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'q_td'), + (Dynamic.Vehicle.ANGLE_OF_ATTACK, Aircraft.Wing.INCIDENCE), + ('flap_defl', Aircraft.Wing.FLAP_DEFLECTION_LANDING), + ('CL_max_flaps', Mission.Landing.LIFT_COEFFICIENT_MAX), ( - "dCL_flaps_model", + 'dCL_flaps_model', Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT, ), ( - "dCD_flaps_model", + 'dCD_flaps_model', Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT, ), - ("t_init_flaps", "t_init_flaps_td"), - ("t_init_gear", "t_init_gear_td"), + ('t_init_flaps', 't_init_flaps_td'), + ('t_init_gear', 't_init_gear_td'), ], - promotes_outputs=[("CD", "touchdown_CD"), ("CL", "touchdown_CL")], + promotes_outputs=[('CD', 'touchdown_CD'), ('CL', 'touchdown_CL')], ) # GASP seems to run groundroll with flaps up and gear down (IWLD=2) - self.set_input_defaults("t_init_flaps_td", 1e10) # never deploy - self.set_input_defaults("t_init_gear_td", 1e10) # ensure gear down + self.set_input_defaults('t_init_flaps_td', 1e10) # never deploy + self.set_input_defaults('t_init_gear_td', 1e10) # ensure gear down self.add_subsystem( - "landinggroundroll", + 'landinggroundroll', LandingGroundRollComponent(), promotes_inputs=[ - "touchdown_CD", - "touchdown_CL", - "TAS_touchdown", - "thrust_idle", - "density_ratio", - "wing_loading_land", - "glide_distance", - "tr_distance", - "delay_distance", - "CL_max", - Dynamic.Mission.MASS, - 'mission:*' + 'touchdown_CD', + 'touchdown_CL', + 'TAS_touchdown', + 'thrust_idle', + 'density_ratio', + 'wing_loading_land', + 'glide_distance', + 'tr_distance', + 'delay_distance', + 'CL_max', + Dynamic.Vehicle.MASS, + 'mission:*', ], promotes_outputs=[ - "ground_roll_distance", "average_acceleration", 'mission:*'], + 'ground_roll_distance', + 'average_acceleration', + 'mission:*', + ], ) ParamPort.set_default_vals(self) @@ -206,13 +216,18 @@ def setup(self): self.set_input_defaults(Mission.Landing.INITIAL_MACH, val=0.1) # landing doesn't change flap or gear position - self.set_input_defaults("t_init_flaps_app", val=1e10) - self.set_input_defaults("t_init_gear_app", val=1e10) + self.set_input_defaults('t_init_flaps_app', val=1e10) + self.set_input_defaults('t_init_gear_app', val=1e10) + self.set_input_defaults(Mission.Landing.INITIAL_ALTITUDE, val=50, units='ft') + self.set_input_defaults('aero_ramps.flap_factor:final_val', val=1.0) + self.set_input_defaults('aero_ramps.gear_factor:final_val', val=1.0) + self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=0.0) + self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=0.0) + + self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units='ft**2') + + # Throttle Idle + num_engine_types = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) self.set_input_defaults( - Mission.Landing.INITIAL_ALTITUDE, val=50, units="ft") - self.set_input_defaults('aero_ramps.flap_factor:final_val', val=1.) - self.set_input_defaults('aero_ramps.gear_factor:final_val', val=1.) - self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=0.) - self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=0.) - - self.set_input_defaults(Aircraft.Wing.AREA, val=1.0, units="ft**2") + Dynamic.Vehicle.Propulsion.THROTTLE, np.zeros((1, num_engine_types)) + ) diff --git a/aviary/mission/gasp_based/ode/params.py b/aviary/mission/gasp_based/ode/params.py index cd7264eff7..e59a70258c 100644 --- a/aviary/mission/gasp_based/ode/params.py +++ b/aviary/mission/gasp_based/ode/params.py @@ -11,9 +11,9 @@ class ParamPort(om.ExplicitComponent): """ param_data = { - Aircraft.Wing.INCIDENCE: dict(units="deg", val=0), - Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF: dict(units="deg", val=10), - Aircraft.Wing.FLAP_DEFLECTION_LANDING: dict(units="deg", val=40), + Aircraft.Wing.INCIDENCE: dict(units='deg', val=0), + Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF: dict(units='deg', val=10), + Aircraft.Wing.FLAP_DEFLECTION_LANDING: dict(units='deg', val=40), } def setup(self): @@ -23,11 +23,9 @@ def setup(self): @staticmethod def set_default_vals(sys): - """Set input defaults on a group""" + """Set input defaults on a group.""" for name, data in ParamPort.param_data.items(): - sys.set_input_defaults( - name, val=data.get("val", 1), units=data.get("units", None) - ) + sys.set_input_defaults(name, val=data.get('val', 1), units=data.get('units', None)) @staticmethod def add_params(param_data): @@ -61,7 +59,7 @@ def promote_params(sys, trajs=None, phases=None): phases : iterable, optional Phases to which to add parameters. """ - proms = [(f"parameters:{param}", param) for param in ParamPort.param_data] + proms = [(f'parameters:{param}', param) for param in ParamPort.param_data] if trajs: for trajname, phasenames in zip(trajs, phases): @@ -69,8 +67,8 @@ def promote_params(sys, trajs=None, phases=None): for param, data in ParamPort.param_data.items(): traj.add_parameter( param, - units=data.get("units", None), - val=data.get("val", 1.0), + units=data.get('units', None), + val=data.get('val', 1.0), opt=False, static_target=True, targets={phasename: [param] for phasename in phasenames}, @@ -82,8 +80,8 @@ def promote_params(sys, trajs=None, phases=None): for param, data in ParamPort.param_data.items(): phase.add_parameter( param, - units=data.get("units", None), - val=data.get("val", 1.0), + units=data.get('units', None), + val=data.get('val', 1.0), opt=False, static_target=True, ) @@ -91,60 +89,60 @@ def promote_params(sys, trajs=None, phases=None): params_for_unit_tests = { - Aircraft.Wing.AREA: dict(units="ft**2", val=1370.3), - Aircraft.Wing.HEIGHT: dict(units="ft", val=8), - Aircraft.Wing.SPAN: dict(units="ft", val=117.8), - Mission.Design.GROSS_MASS: dict(units="lbm", val=175400), - Mission.Summary.GROSS_MASS: dict(units="lbm", val=175400), - Mission.Summary.FUEL_FLOW_SCALER: dict(units="unitless", val=1.0), - Mission.Takeoff.AIRPORT_ALTITUDE: dict(units="ft", val=0), - Mission.Landing.AIRPORT_ALTITUDE: dict(units="ft", val=0), - Aircraft.Wing.AVERAGE_CHORD: dict(units="ft", val=12.615), - Aircraft.Fuselage.AVG_DIAMETER: dict(units="inch", val=12 * 13.100), - Aircraft.HorizontalTail.AVERAGE_CHORD: dict(units="ft", val=9.577), - Aircraft.HorizontalTail.AREA: dict(units="ft**2", val=375.880), - Aircraft.HorizontalTail.SPAN: dict(units="ft", val=42.254), - Aircraft.VerticalTail.AVERAGE_CHORD: dict(units="ft", val=16.832), - Aircraft.VerticalTail.AREA: dict(units="ft**2", val=469.318), - Aircraft.VerticalTail.SPAN: dict(units="ft", val=27.996), - Aircraft.Fuselage.LENGTH: dict(units="ft", val=129.4), - Aircraft.Nacelle.AVG_LENGTH: dict(units="ft", val=14.5), - Aircraft.Fuselage.WETTED_AREA: dict(units="ft**2", val=4000), - Aircraft.Nacelle.SURFACE_AREA: dict(units="ft**2", val=659.23 / 2), - Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED: dict(units="unitless", val=0.1397), + Aircraft.Wing.AREA: dict(units='ft**2', val=1370.3), + Aircraft.Wing.HEIGHT: dict(units='ft', val=8), + Aircraft.Wing.SPAN: dict(units='ft', val=117.8), + Mission.Design.GROSS_MASS: dict(units='lbm', val=175400), + Mission.Summary.GROSS_MASS: dict(units='lbm', val=175400), + Mission.Summary.FUEL_FLOW_SCALER: dict(units='unitless', val=1.0), + Mission.Takeoff.AIRPORT_ALTITUDE: dict(units='ft', val=0), + Mission.Landing.AIRPORT_ALTITUDE: dict(units='ft', val=0), + Aircraft.Wing.AVERAGE_CHORD: dict(units='ft', val=12.615), + Aircraft.Fuselage.AVG_DIAMETER: dict(units='inch', val=12 * 13.100), + Aircraft.HorizontalTail.AVERAGE_CHORD: dict(units='ft', val=9.577), + Aircraft.HorizontalTail.AREA: dict(units='ft**2', val=375.880), + Aircraft.HorizontalTail.SPAN: dict(units='ft', val=42.254), + Aircraft.VerticalTail.AVERAGE_CHORD: dict(units='ft', val=16.832), + Aircraft.VerticalTail.AREA: dict(units='ft**2', val=469.318), + Aircraft.VerticalTail.SPAN: dict(units='ft', val=27.996), + Aircraft.Fuselage.LENGTH: dict(units='ft', val=129.4), + Aircraft.Nacelle.AVG_LENGTH: dict(units='ft', val=14.5), + Aircraft.Fuselage.WETTED_AREA: dict(units='ft**2', val=4000), + Aircraft.Nacelle.SURFACE_AREA: dict(units='ft**2', val=659.23 / 2), + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED: dict(units='unitless', val=0.1397), Aircraft.Strut.CHORD: dict( - units="ft", val=0 + units='ft', val=0 ), # only available if Aviary_option Aircraft.Wing.HAS_STRUT - Aircraft.Wing.ASPECT_RATIO: dict(units="unitless", val=10.13), - Aircraft.Wing.TAPER_RATIO: dict(units="unitless", val=0.33), - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT: dict(units="unitless", val=0.15), - Aircraft.Wing.THICKNESS_TO_CHORD_TIP: dict(units="unitless", val=0.12), - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION: dict(units="unitless", val=0), - Aircraft.Wing.SWEEP: dict(units="deg", val=25), - Aircraft.HorizontalTail.SWEEP: dict(units="deg", val=25), - Aircraft.HorizontalTail.MOMENT_RATIO: dict(units="unitless", val=0.2307), - Aircraft.Wing.MOUNTING_TYPE: dict(units="unitless", val=0), - Aircraft.Design.STATIC_MARGIN: dict(units="unitless", val=0.03), - Aircraft.Design.CG_DELTA: dict(units="unitless", val=0.25), - Aircraft.Fuselage.FORM_FACTOR: dict(units="unitless", val=1.25), - Aircraft.Nacelle.FORM_FACTOR: dict(units="unitless", val=1.5), - Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR: dict(units="unitless", val=1.1), - Aircraft.Design.DRAG_COEFFICIENT_INCREMENT: dict(units="unitless", val=0.00175), - Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT: dict(units="ft**2", val=0.25), - Aircraft.Wing.CENTER_DISTANCE: dict(units="unitless", val=0.463), - Aircraft.Wing.MIN_PRESSURE_LOCATION: dict(units="unitless", val=0.3), - Aircraft.Wing.MAX_THICKNESS_LOCATION: dict(units="unitless", val=0.4), - Aircraft.Strut.AREA_RATIO: dict(units="unitless", val=0), - Aircraft.Wing.ZERO_LIFT_ANGLE: dict(units="deg", val=-1.2), - Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT: dict(units="unitless", val=0.033), - Aircraft.Wing.FLAP_CHORD_RATIO: dict(units="unitless", val=0.3), - Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP: dict(units="unitless", val=1.2596), - Mission.Takeoff.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.1886), - Mission.Landing.LIFT_COEFFICIENT_MAX: dict(units="unitless", val=2.8155), - Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=0.4182), - Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=1.0293), - Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=0.0085), - Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(units="unitless", val=0.0406), + Aircraft.Wing.ASPECT_RATIO: dict(units='unitless', val=10.13), + Aircraft.Wing.TAPER_RATIO: dict(units='unitless', val=0.33), + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT: dict(units='unitless', val=0.15), + Aircraft.Wing.THICKNESS_TO_CHORD_TIP: dict(units='unitless', val=0.12), + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION: dict(units='unitless', val=0), + Aircraft.Wing.SWEEP: dict(units='deg', val=25), + Aircraft.HorizontalTail.SWEEP: dict(units='deg', val=25), + Aircraft.HorizontalTail.MOMENT_RATIO: dict(units='unitless', val=0.2307), + Aircraft.Wing.VERTICAL_MOUNT_LOCATION: dict(units='unitless', val=0), + Aircraft.Design.STATIC_MARGIN: dict(units='unitless', val=0.03), + Aircraft.Design.CG_DELTA: dict(units='unitless', val=0.25), + Aircraft.Fuselage.FORM_FACTOR: dict(units='unitless', val=1.25), + Aircraft.Nacelle.FORM_FACTOR: dict(units='unitless', val=1.5), + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR: dict(units='unitless', val=1.1), + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT: dict(units='unitless', val=0.00175), + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT: dict(units='ft**2', val=0.25), + Aircraft.Wing.CENTER_DISTANCE: dict(units='unitless', val=0.463), + Aircraft.Wing.MIN_PRESSURE_LOCATION: dict(units='unitless', val=0.3), + Aircraft.Wing.MAX_THICKNESS_LOCATION: dict(units='unitless', val=0.4), + Aircraft.Strut.AREA_RATIO: dict(units='unitless', val=0), + Aircraft.Wing.ZERO_LIFT_ANGLE: dict(units='deg', val=-1.2), + Aircraft.Design.DRAG_DIVERGENCE_SHIFT: dict(units='unitless', val=0.033), + Aircraft.Wing.FLAP_CHORD_RATIO: dict(units='unitless', val=0.3), + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP: dict(units='unitless', val=1.2596), + Mission.Takeoff.LIFT_COEFFICIENT_MAX: dict(units='unitless', val=2.1886), + Mission.Landing.LIFT_COEFFICIENT_MAX: dict(units='unitless', val=2.8155), + Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(units='unitless', val=0.4182), + Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT: dict(units='unitless', val=1.0293), + Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(units='unitless', val=0.0085), + Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT: dict(units='unitless', val=0.0406), } diff --git a/aviary/mission/gasp_based/ode/rotation_eom.py b/aviary/mission/gasp_based/ode/rotation_eom.py index 49c3b74000..863a827da1 100644 --- a/aviary/mission/gasp_based/ode/rotation_eom.py +++ b/aviary/mission/gasp_based/ode/rotation_eom.py @@ -2,116 +2,166 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_GASP, GRAV_ENGLISH_LBM, MU_TAKEOFF -from aviary.variable_info.enums import AnalysisScheme from aviary.variable_info.functions import add_aviary_input from aviary.variable_info.variables import Aircraft, Dynamic class RotationEOM(om.ExplicitComponent): - """2-degree of freedom rotation EOM""" + """2-degree of freedom rotation EOM.""" def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare("analysis_scheme", types=AnalysisScheme, default=AnalysisScheme.COLLOCATION, - desc="The analysis method that will be used to close the trajectory; for example collocation or time integration") + self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] - analysis_scheme = self.options["analysis_scheme"] - - self.add_input(Dynamic.Mission.MASS, val=np.ones(nn), - desc="aircraft mass", units="lbm") - self.add_input(Dynamic.Mission.THRUST_TOTAL, val=np.ones( - nn), desc=Dynamic.Mission.THRUST_TOTAL, units="lbf") - self.add_input(Dynamic.Mission.LIFT, val=np.ones( - nn), desc=Dynamic.Mission.LIFT, units="lbf") - self.add_input(Dynamic.Mission.DRAG, val=np.ones( - nn), desc=Dynamic.Mission.DRAG, units="lbf") - self.add_input(Dynamic.Mission.VELOCITY, val=np.ones(nn), - desc="true air speed", units="ft/s") - self.add_input(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.ones(nn), - desc="flight path angle", units="rad") - - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0.0, units="deg") - self.add_input("alpha", val=np.ones(nn), desc="angle of attack", units="deg") - - self.add_output(Dynamic.Mission.VELOCITY_RATE, val=np.ones(nn), - desc="TAS rate", units="ft/s**2") + nn = self.options['num_nodes'] + + self.add_input(Dynamic.Vehicle.MASS, val=np.ones(nn), desc='aircraft mass', units='lbm') + self.add_input( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + val=np.ones(nn), + desc=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', + ) + self.add_input( + Dynamic.Vehicle.LIFT, + val=np.ones(nn), + desc=Dynamic.Vehicle.LIFT, + units='lbf', + ) + self.add_input( + Dynamic.Vehicle.DRAG, + val=np.ones(nn), + desc=Dynamic.Vehicle.DRAG, + units='lbf', + ) + self.add_input( + Dynamic.Mission.VELOCITY, + val=np.ones(nn), + desc='true air speed', + units='ft/s', + ) + self.add_input( + Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.ones(nn), + desc='flight path angle', + units='rad', + ) + + add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0.0, units='deg') + self.add_input( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=np.ones(nn), + desc='angle of attack', + units='deg', + ) + self.add_output( - Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, val=np.ones(nn), desc="flight path angle rate", units="rad/s" + Dynamic.Mission.VELOCITY_RATE, + val=np.ones(nn), + desc='TAS rate', + units='ft/s**2', ) - self.add_output(Dynamic.Mission.ALTITUDE_RATE, val=np.ones(nn), - desc="altitude rate", units="ft/s") self.add_output( - Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc="distance rate", units="ft/s" + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + val=np.ones(nn), + desc='flight path angle rate', + units='rad/s', ) self.add_output( - "normal_force", val=np.ones(nn), desc="normal forces", units="lbf" + Dynamic.Mission.ALTITUDE_RATE, + val=np.ones(nn), + desc='altitude rate', + units='ft/s', ) self.add_output( - "fuselage_pitch", val=np.ones(nn), desc="fuselage pitch angle", units="deg" + Dynamic.Mission.DISTANCE_RATE, val=np.ones(nn), desc='distance rate', units='ft/s' + ) + self.add_output('normal_force', val=np.ones(nn), desc='normal forces', units='lbf') + self.add_output('fuselage_pitch', val=np.ones(nn), desc='fuselage pitch angle', units='deg') + self.add_output( + 'angle_of_attack_rate', val=np.ones(nn), desc='angle of attack rate', units='deg/s' ) - if analysis_scheme is AnalysisScheme.COLLOCATION: - self.add_output( - "alpha_rate", val=np.ones(nn), desc="angle of attack rate", units="deg/s" - ) - - self.declare_partials("alpha_rate", ["*"]) + self.declare_partials('angle_of_attack_rate', ['*']) def setup_partials(self): - arange = np.arange(self.options["num_nodes"]) + arange = np.arange(self.options['num_nodes']) - self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, "*") + self.declare_partials(Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, '*') self.declare_partials( Dynamic.Mission.VELOCITY_RATE, - [Dynamic.Mission.THRUST_TOTAL, "alpha", Dynamic.Mission.DRAG, - Dynamic.Mission.MASS, Dynamic.Mission.FLIGHT_PATH_ANGLE, Dynamic.Mission.LIFT], + [ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Vehicle.LIFT, + ], rows=arange, cols=arange, ) self.declare_partials(Dynamic.Mission.VELOCITY_RATE, [Aircraft.Wing.INCIDENCE]) - self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange) self.declare_partials( - Dynamic.Mission.DISTANCE_RATE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], rows=arange, cols=arange + Dynamic.Mission.ALTITUDE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=arange, + cols=arange, + ) + self.declare_partials( + Dynamic.Mission.DISTANCE_RATE, + [Dynamic.Mission.VELOCITY, Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=arange, + cols=arange, ) self.declare_partials( - "normal_force", - [Dynamic.Mission.MASS, Dynamic.Mission.LIFT, - Dynamic.Mission.THRUST_TOTAL, "alpha"], + 'normal_force', + [ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], rows=arange, cols=arange, ) - self.declare_partials("normal_force", [Aircraft.Wing.INCIDENCE]) + self.declare_partials('normal_force', [Aircraft.Wing.INCIDENCE]) self.declare_partials( - "fuselage_pitch", Dynamic.Mission.FLIGHT_PATH_ANGLE, rows=arange, cols=arange, val=180 / np.pi, + 'fuselage_pitch', + Dynamic.Mission.FLIGHT_PATH_ANGLE, + rows=arange, + cols=arange, + val=180 / np.pi, ) - self.declare_partials("fuselage_pitch", "alpha", rows=arange, cols=arange, val=1) - self.declare_partials("fuselage_pitch", Aircraft.Wing.INCIDENCE, val=-1) + self.declare_partials( + 'fuselage_pitch', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + rows=arange, + cols=arange, + val=1, + ) + self.declare_partials('fuselage_pitch', Aircraft.Wing.INCIDENCE, val=-1) def compute(self, inputs, outputs): - analysis_scheme = self.options["analysis_scheme"] - - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] mu = MU_TAKEOFF - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] thrust_along_flightpath = thrust * np.cos((alpha - i_wing) * np.pi / 180) thrust_across_flightpath = thrust * np.sin((alpha - i_wing) * np.pi / 180) - normal_force = np.clip(weight - incremented_lift - thrust_across_flightpath, - a_min=0., a_max=None) + normal_force = np.clip( + weight - incremented_lift - thrust_across_flightpath, a_min=0.0, a_max=None + ) outputs[Dynamic.Mission.VELOCITY_RATE] = ( ( @@ -127,27 +177,23 @@ def compute(self, inputs, outputs): outputs[Dynamic.Mission.ALTITUDE_RATE] = TAS * np.sin(gamma) outputs[Dynamic.Mission.DISTANCE_RATE] = TAS * np.cos(gamma) - outputs["normal_force"] = normal_force - - outputs["fuselage_pitch"] = gamma * 180 / np.pi - i_wing + alpha - - if analysis_scheme is AnalysisScheme.COLLOCATION: - outputs['alpha_rate'] = np.full(nn, 3.33) + outputs['normal_force'] = normal_force + outputs['fuselage_pitch'] = gamma * 180 / np.pi - i_wing + alpha + outputs['angle_of_attack_rate'] = np.full(nn, 3.33) def compute_partials(self, inputs, J): - mu = MU_TAKEOFF - weight = inputs[Dynamic.Mission.MASS] * GRAV_ENGLISH_LBM - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - incremented_lift = inputs[Dynamic.Mission.LIFT] - incremented_drag = inputs[Dynamic.Mission.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * GRAV_ENGLISH_LBM + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + incremented_lift = inputs[Dynamic.Vehicle.LIFT] + incremented_drag = inputs[Dynamic.Vehicle.DRAG] TAS = inputs[Dynamic.Mission.VELOCITY] gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] thrust_along_flightpath = thrust * np.cos((alpha - i_wing) * np.pi / 180) thrust_across_flightpath = thrust * np.sin((alpha - i_wing) * np.pi / 180) @@ -160,8 +206,9 @@ def compute_partials(self, inputs, J): dTAcF_dAlpha = thrust * np.cos((alpha - i_wing) * np.pi / 180) * np.pi / 180 dTAcF_dIwing = -thrust * np.cos((alpha - i_wing) * np.pi / 180) * np.pi / 180 - normal_force = np.clip(weight - incremented_lift - thrust_across_flightpath, - a_min=0., a_max=None) + normal_force = np.clip( + weight - incremented_lift - thrust_across_flightpath, a_min=0.0, a_max=None + ) dNF_dWeight = np.ones(nn) dNF_dWeight[normal_force < 0] = 0 @@ -178,18 +225,19 @@ def compute_partials(self, inputs, J): dNF_dIwing = -np.ones(nn) * dTAcF_dIwing dNF_dIwing[normal_force < 0] = 0 - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.THRUST_TOTAL] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( (dTAlF_dThrust - mu * dNF_dThrust) * GRAV_ENGLISH_GASP / weight ) - J[Dynamic.Mission.VELOCITY_RATE, "alpha"] = ( + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( (dTAlF_dAlpha - mu * dNF_dAlpha) * GRAV_ENGLISH_GASP / weight ) J[Dynamic.Mission.VELOCITY_RATE, Aircraft.Wing.INCIDENCE] = ( (dTAlF_dIwing - mu * dNF_dIwing) * GRAV_ENGLISH_GASP / weight ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.DRAG] = -GRAV_ENGLISH_GASP / weight - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.MASS] = ( - GRAV_ENGLISH_GASP * GRAV_ENGLISH_LBM + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.DRAG] = -GRAV_ENGLISH_GASP / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.MASS] = ( + GRAV_ENGLISH_GASP + * GRAV_ENGLISH_LBM * ( weight * (-np.sin(gamma) - mu * dNF_dWeight) - ( @@ -201,21 +249,21 @@ def compute_partials(self, inputs, J): ) / weight**2 ) - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = - \ - np.cos(gamma) * GRAV_ENGLISH_GASP - J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.LIFT] = GRAV_ENGLISH_GASP * \ - (-mu * dNF_dLift) / weight + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + -np.cos(gamma) * GRAV_ENGLISH_GASP + ) + J[Dynamic.Mission.VELOCITY_RATE, Dynamic.Vehicle.LIFT] = ( + GRAV_ENGLISH_GASP * (-mu * dNF_dLift) / weight + ) J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.VELOCITY] = np.sin(gamma) - J[Dynamic.Mission.ALTITUDE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) + J[Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = TAS * np.cos(gamma) J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.VELOCITY] = np.cos(gamma) - J[Dynamic.Mission.DISTANCE_RATE, - Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) - - J["normal_force", Dynamic.Mission.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM - J["normal_force", Dynamic.Mission.LIFT] = dNF_dLift - J["normal_force", Dynamic.Mission.THRUST_TOTAL] = dNF_dThrust - J["normal_force", "alpha"] = dNF_dAlpha - J["normal_force", Aircraft.Wing.INCIDENCE] = dNF_dIwing + J[Dynamic.Mission.DISTANCE_RATE, Dynamic.Mission.FLIGHT_PATH_ANGLE] = -TAS * np.sin(gamma) + + J['normal_force', Dynamic.Vehicle.MASS] = dNF_dWeight * GRAV_ENGLISH_LBM + J['normal_force', Dynamic.Vehicle.LIFT] = dNF_dLift + J['normal_force', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = dNF_dThrust + J['normal_force', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dNF_dAlpha + J['normal_force', Aircraft.Wing.INCIDENCE] = dNF_dIwing diff --git a/aviary/mission/gasp_based/ode/rotation_ode.py b/aviary/mission/gasp_based/ode/rotation_ode.py index 64f5eaa687..5c8a5b9d5b 100644 --- a/aviary/mission/gasp_based/ode/rotation_ode.py +++ b/aviary/mission/gasp_based/ode/rotation_ode.py @@ -1,15 +1,13 @@ import numpy as np import openmdao.api as om -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.params import ParamPort from aviary.mission.gasp_based.ode.rotation_eom import RotationEOM -from aviary.variable_info.enums import AnalysisScheme -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.mission.gasp_based.ode.time_integration_base_classes import add_SGM_required_inputs +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE +from aviary.variable_info.variables import Aircraft, Dynamic -class RotationODE(BaseODE): +class RotationODE(TwoDOFODE): """ODE for takeoff rotation. This phase spans the time from when the aircraft is touching the runway but has @@ -17,60 +15,31 @@ class RotationODE(BaseODE): """ def setup(self): - nn = self.options["num_nodes"] - analysis_scheme = self.options["analysis_scheme"] - aviary_options = self.options['aviary_options'] - core_subsystems = self.options['core_subsystems'] - - if analysis_scheme is AnalysisScheme.SHOOTING: - add_SGM_required_inputs(self, { - Dynamic.Mission.DISTANCE: {'units': 'ft'}, - }) + nn = self.options['num_nodes'] # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) + + self.add_atmosphere() - self.add_atmosphere(nn) + kwargs = {'method': 'low_speed'} + self.options['subsystem_options'].setdefault('core_aerodynamics', {}).update(kwargs) - kwargs = {'num_nodes': nn, 'aviary_inputs': aviary_options, - 'method': 'low_speed'} - for subsystem in core_subsystems: - system = subsystem.build_mission(**kwargs) - if system is not None: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_core_subsystems() - if analysis_scheme is AnalysisScheme.SHOOTING: - alpha_comp = om.ExecComp( - 'alpha=rotation_rate*(t_curr-start_rotation)+alpha_init', - alpha=dict(val=0., units='deg'), - rotation_rate=dict(val=10.0/3.0, units='deg/s'), - t_curr=dict(val=0., units='s'), - start_rotation=dict(val=0., units='s'), - alpha_init=dict(val=0., units='deg'), - ) - alpha_comp_inputs = ["rotation_rate", "t_curr", "start_rotation", - ("alpha_init", Aircraft.Wing.INCIDENCE)] - self.add_subsystem("alpha_comp", - alpha_comp, - promotes_inputs=alpha_comp_inputs, - promotes_outputs=["alpha"], - ) + self.add_external_subsystems() - self.add_subsystem("rotation_eom", RotationEOM(num_nodes=nn), promotes=["*"]) + self.add_subsystem('rotation_eom', RotationEOM(num_nodes=nn), promotes=['*']) ParamPort.set_default_vals(self) - self.set_input_defaults("t_init_flaps", val=47.5, units='s') - self.set_input_defaults("t_init_gear", val=37.3, units='s') - self.set_input_defaults("alpha", val=np.ones(nn), units="deg") - self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units="deg") - self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units="ft") - self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units="kn") - self.set_input_defaults("t_curr", val=np.zeros(nn), units="s") - self.set_input_defaults('aero_ramps.flap_factor:final_val', val=1.) - self.set_input_defaults('aero_ramps.gear_factor:final_val', val=1.) - self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=1.) - self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=1.) + self.set_input_defaults('t_init_flaps', val=47.5, units='s') + self.set_input_defaults('t_init_gear', val=37.3, units='s') + self.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.ones(nn), units='deg') + self.set_input_defaults(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(nn), units='deg') + self.set_input_defaults(Dynamic.Mission.ALTITUDE, val=np.zeros(nn), units='ft') + self.set_input_defaults(Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='kn') + self.set_input_defaults('t_curr', val=np.zeros(nn), units='s') + self.set_input_defaults('aero_ramps.flap_factor:final_val', val=1.0) + self.set_input_defaults('aero_ramps.gear_factor:final_val', val=1.0) + self.set_input_defaults('aero_ramps.flap_factor:initial_val', val=1.0) + self.set_input_defaults('aero_ramps.gear_factor:initial_val', val=1.0) diff --git a/aviary/mission/gasp_based/ode/taxi_eom.py b/aviary/mission/gasp_based/ode/taxi_eom.py index cd548d7bd3..1ae4309397 100644 --- a/aviary/mission/gasp_based/ode/taxi_eom.py +++ b/aviary/mission/gasp_based/ode/taxi_eom.py @@ -1,61 +1,63 @@ -import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Dynamic, Mission class TaxiFuelComponent(om.ExplicitComponent): - """ - Compute the fuel consumed during taxi and update the mass after taxi in a 2DOF mission. - """ + """Compute the fuel consumed during taxi and update the mass after taxi in a 2DOF mission.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Mission.Taxi.DURATION, units='s') def setup(self): self.add_input( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, val=1.0, - units="lbm/s", - desc="fuel flow rate", + units='lbm/s', + desc='fuel flow rate', ) add_aviary_input(self, Mission.Summary.GROSS_MASS, val=175400.0) self.add_output( - "taxi_fuel_consumed", + 'taxi_fuel_consumed', val=1.0, - units="lbm", - desc="taxi_fuel_consumed", + units='lbm', + desc='taxi_fuel_consumed', ) self.add_output( - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, val=175000.0, - units="lbm", - desc="mass after taxi", + units='lbm', + desc='mass after taxi', ) def setup_partials(self): self.declare_partials( - "taxi_fuel_consumed", [ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL]) - self.declare_partials( - Dynamic.Mission.MASS, Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL) + 'taxi_fuel_consumed', + [Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL], + ) self.declare_partials( - Dynamic.Mission.MASS, Mission.Summary.GROSS_MASS, val=1) + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + ) + self.declare_partials(Dynamic.Vehicle.MASS, Mission.Summary.GROSS_MASS, val=1) def compute(self, inputs, outputs): fuelflow, takeoff_mass = inputs.values() - dt_taxi = self.options['aviary_options'].get_val(Mission.Taxi.DURATION, 's') - outputs["taxi_fuel_consumed"] = -fuelflow * dt_taxi - outputs[Dynamic.Mission.MASS] = takeoff_mass - outputs["taxi_fuel_consumed"] + dt_taxi, _ = self.options[Mission.Taxi.DURATION] + outputs['taxi_fuel_consumed'] = -fuelflow * dt_taxi + outputs[Dynamic.Vehicle.MASS] = takeoff_mass - outputs['taxi_fuel_consumed'] def compute_partials(self, inputs, J): - dt_taxi = self.options['aviary_options'].get_val(Mission.Taxi.DURATION, 's') + dt_taxi, _ = self.options[Mission.Taxi.DURATION] - J["taxi_fuel_consumed", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL] = -dt_taxi + J[ + 'taxi_fuel_consumed', + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + ] = -dt_taxi - J[Dynamic.Mission.MASS, Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL] = dt_taxi + J[ + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + ] = dt_taxi diff --git a/aviary/mission/gasp_based/ode/taxi_ode.py b/aviary/mission/gasp_based/ode/taxi_ode.py index 0c69e60dbd..4aeede88e3 100644 --- a/aviary/mission/gasp_based/ode/taxi_ode.py +++ b/aviary/mission/gasp_based/ode/taxi_ode.py @@ -1,49 +1,82 @@ -from aviary.mission.gasp_based.ode.base_ode import BaseODE +import numpy as np +import openmdao.api as om + from aviary.mission.gasp_based.ode.params import ParamPort from aviary.mission.gasp_based.ode.taxi_eom import TaxiFuelComponent -from aviary.subsystems.atmosphere.atmosphere import Atmosphere +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase from aviary.utils.aviary_values import AviaryValues from aviary.utils.functions import add_opts2vals, create_opts2vals -from aviary.variable_info.variables import Dynamic, Mission +from aviary.variable_info.enums import SpeedType +from aviary.variable_info.variables import Aircraft, Dynamic, Mission -class TaxiSegment(BaseODE): - """ODE for taxi phase of a 2DOF mission""" +class TaxiSegment(TwoDOFODE): + """ODE for taxi phase of a 2DOF mission.""" def setup(self): options: AviaryValues = self.options['aviary_options'] core_subsystems = self.options['core_subsystems'] - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) + + add_opts2vals(self, create_opts2vals([Mission.Taxi.MACH]), options) + + alias_comp = om.ExecComp( + 'alt=airport_alt', + alt={ + 'val': np.zeros(1), + 'units': 'ft', + }, + airport_alt={'val': np.zeros(1), 'units': 'ft'}, + has_diag_partials=True, + ) + + alias_comp.add_expr( + 'mach=taxi_mach', + mach={'val': np.zeros(1), 'units': 'unitless'}, + taxi_mach={'val': np.zeros(1), 'units': 'unitless'}, + ) self.add_subsystem( - name='atmosphere', - subsys=Atmosphere(num_nodes=1), - promotes=[ - '*', - (Dynamic.Mission.ALTITUDE, Mission.Takeoff.AIRPORT_ALTITUDE), + 'alias_taxi_phase', + alias_comp, + promotes_inputs=[ + ('airport_alt', Mission.Takeoff.AIRPORT_ALTITUDE), + ('taxi_mach', Mission.Taxi.MACH), + ], + promotes_outputs=[ + ('alt', Dynamic.Mission.ALTITUDE), + ('mach', Dynamic.Atmosphere.MACH), ], ) - add_opts2vals(self, create_opts2vals( - [Mission.Taxi.MACH]), options) + self.add_atmosphere(input_speed_type=SpeedType.MACH) for subsystem in core_subsystems: if isinstance(subsystem, PropulsionBuilderBase): system = subsystem.build_mission(num_nodes=1, aviary_inputs=options) - self.add_subsystem(subsystem.name, - system, - promotes_inputs=['*', (Dynamic.Mission.ALTITUDE, Mission.Takeoff.AIRPORT_ALTITUDE), - (Dynamic.Mission.MACH, Mission.Taxi.MACH)], - promotes_outputs=['*']) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=[ + '*', + (Dynamic.Mission.ALTITUDE, Mission.Takeoff.AIRPORT_ALTITUDE), + (Dynamic.Atmosphere.MACH, Mission.Taxi.MACH), + ], + promotes_outputs=['*'], + ) - self.add_subsystem("taxifuel", TaxiFuelComponent( - aviary_options=options), promotes=["*"]) + self.add_external_subsystems() + + self.add_subsystem('taxifuel', TaxiFuelComponent(), promotes=['*']) ParamPort.set_default_vals(self) self.set_input_defaults(Mission.Taxi.MACH, 0) # Throttle Idle - self.set_input_defaults('throttle', 0.0) + num_engine_types = len(options.get_val(Aircraft.Engine.NUM_ENGINES)) + self.set_input_defaults( + Dynamic.Vehicle.Propulsion.THROTTLE, np.zeros((1, num_engine_types)) + ) diff --git a/aviary/mission/gasp_based/ode/test/test_accel_eom.py b/aviary/mission/gasp_based/ode/test/test_accel_eom.py index bb3d8c5f40..14408610cb 100644 --- a/aviary/mission/gasp_based/ode/test/test_accel_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_accel_eom.py @@ -2,8 +2,7 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.accel_eom import AccelerationRates from aviary.variable_info.variables import Dynamic @@ -17,69 +16,68 @@ class AccelerationTestCase(unittest.TestCase): """ def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", AccelerationRates(num_nodes=2), promotes=["*"] - ) + self.prob.model.add_subsystem('group', AccelerationRates(num_nodes=2), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([174878, 174878]), units="lbm" + Dynamic.Vehicle.MASS, np.array([174878, 174878]), units='lbm' ) self.prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([2635.225, 2635.225]), units="lbf" + Dynamic.Vehicle.DRAG, np.array([2635.225, 2635.225]), units='lbf' ) # note: this input value is not provided in the GASP data, so an estimation was made based on another similar data point self.prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([32589, 32589]), units="lbf" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + np.array([32589, 32589]), + units='lbf', ) self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([252, 252]), units="kn") + Dynamic.Mission.VELOCITY, np.array([252, 252]), units='kn' + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [5.51533958, 5.51533958]), tol + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([5.51533958, 5.51533958]), + tol, # note: this was finite differenced from GASP. The fd value is: np.array([5.2353365, 5.2353365]) ) assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [425.32808399, 425.32808399]), tol + self.prob[Dynamic.Mission.DISTANCE_RATE], + np.array([425.32808399, 425.32808399]), + tol, # note: this was finite differenced from GASP. The fd value is: np.array([441.6439, 441.6439]) ) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AccelerationTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.accel_eom as accel + accel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.accel_eom as accel + accel.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem( - "group", AccelerationRates(num_nodes=2), promotes=["*"] - ) + prob.model.add_subsystem('group', AccelerationRates(num_nodes=2), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_accel_ode.py b/aviary/mission/gasp_based/ode/test/test_accel_ode.py index 4552ad305c..2aada70431 100644 --- a/aviary/mission/gasp_based/ode/test/test_accel_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_accel_ode.py @@ -6,55 +6,65 @@ from aviary.mission.gasp_based.ode.accel_ode import AccelODE from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.aviary_values import AviaryValues from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic class AccelerationODETestCase(unittest.TestCase): - """ - Test 2-degree of freedom acceleration ODE. - """ + """Test 2-degree of freedom acceleration ODE.""" def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) - self.sys = self.prob.model = AccelODE(num_nodes=2, - aviary_options=aviary_options, - core_subsystems=default_mission_subsystems) + self.sys = self.prob.model = AccelODE( + num_nodes=2, aviary_options=aviary_options, core_subsystems=default_mission_subsystems + ) def test_accel(self): # Test both points in GASP Large Single Aisle 1 acceleration segment + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + self.prob.setup(check=False, force_alloc_complex=True) throttle_climb = 0.956 - self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units="ft") + self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units='ft') self.prob.set_val( - Dynamic.Mission.THROTTLE, [ - throttle_climb, throttle_climb], units='unitless') - self.prob.set_val(Dynamic.Mission.VELOCITY, [185, 252], units="kn") - self.prob.set_val(Dynamic.Mission.MASS, [174974, 174878], units="lbm") + Dynamic.Vehicle.Propulsion.THROTTLE, + [throttle_climb, throttle_climb], + units='unitless', + ) + self.prob.set_val(Dynamic.Mission.VELOCITY, [185, 252], units='kn') + self.prob.set_val(Dynamic.Vehicle.MASS, [174974, 174878], units='lbm') set_params_for_unit_tests(self.prob) self.prob.run_model() testvals = { - Dynamic.Mission.LIFT: [174974, 174878], - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: [ - -13262.73, -13567.53] # lbm/h + Dynamic.Vehicle.LIFT: [174974, 174878], + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL: [ + -13264.82336817, + -13567.23449581, + ], # lbm/h } check_prob_outputs(self.prob, testvals, rtol=1e-6) partial_data = self.prob.check_partials( - method="cs", out_stream=None, excludes=["*params*", "*aero*"] + method='cs', out_stream=None, excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, rtol=1e-10) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_ascent_eom.py b/aviary/mission/gasp_based/ode/test/test_ascent_eom.py index c675b000ed..69798d5fc7 100644 --- a/aviary/mission/gasp_based/ode/test/test_ascent_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_ascent_eom.py @@ -10,82 +10,82 @@ class AscentEOMTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("group", AscentEOM(num_nodes=2), promotes=["*"]) + self.prob.model.add_subsystem('group', AscentEOM(num_nodes=2), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.MASS, val=175400 * np.ones(2), units="lbm" + Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm' ) self.prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, val=22000 * np.ones(2), units="lbf" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' ) + self.prob.model.set_input_defaults(Dynamic.Vehicle.LIFT, val=200 * np.ones(2), units='lbf') self.prob.model.set_input_defaults( - Dynamic.Mission.LIFT, val=200 * np.ones(2), units="lbf") + Dynamic.Vehicle.DRAG, val=10000 * np.ones(2), units='lbf' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.DRAG, val=10000 * np.ones(2), units="lbf") + Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units='ft/s' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units="ft/s") + Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units='rad' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units='deg') self.prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units="rad") - self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units="deg") - self.prob.model.set_input_defaults("alpha", val=np.zeros(2), units="deg") + Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(2), units='deg' + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [2.202965, 2.202965]), tol + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([2.202965, 2.202965]), + tol, ) assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array( - [-3.216328, -3.216328]), tol + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], + np.array([-3.216328, -3.216328]), + tol, ) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AscentEOMTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.ascent_eom as ascent + ascent.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.ascent_eom as ascent + ascent.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem("group", AscentEOM(num_nodes=2), promotes=["*"]) + prob.model.add_subsystem('group', AscentEOM(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.MASS, val=175400 * np.ones(2), units="lbm" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' ) + prob.model.set_input_defaults(Dynamic.Vehicle.LIFT, val=200 * np.ones(2), units='lbf') + prob.model.set_input_defaults(Dynamic.Vehicle.DRAG, val=10000 * np.ones(2), units='lbf') + prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units='ft/s') prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, val=22000 * np.ones(2), units="lbf" + Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units='rad' ) - prob.model.set_input_defaults( - Dynamic.Mission.LIFT, val=200 * np.ones(2), units="lbf") - prob.model.set_input_defaults( - Dynamic.Mission.DRAG, val=10000 * np.ones(2), units="lbf") - prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units="ft/s") - prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units="rad") - prob.model.set_input_defaults("alpha", val=np.zeros(2), units="deg") + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(2), units='deg') prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_ascent_ode.py b/aviary/mission/gasp_based/ode/test/test_ascent_ode.py index d56246abaa..5a45c778f9 100644 --- a/aviary/mission/gasp_based/ode/test/test_ascent_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_ascent_ode.py @@ -7,9 +7,11 @@ from aviary.mission.gasp_based.ode.ascent_ode import AscentODE from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.aviary_values import AviaryValues from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic class AscentODETestCase(unittest.TestCase): @@ -17,21 +19,30 @@ def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) + + self.prob.model = AscentODE( + num_nodes=2, aviary_options=aviary_options, core_subsystems=default_mission_subsystems + ) - self.prob.model = AscentODE(num_nodes=2, - aviary_options=aviary_options, - core_subsystems=default_mission_subsystems) + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) def test_ascent_partials(self): # Test partial derivatives self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") - self.prob.set_val("t_curr", [1, 2], units="s") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units='kn') + self.prob.set_val('t_curr', [1, 2], units='s') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) @@ -39,35 +50,29 @@ def test_ascent_partials(self): tol = tol = 1e-6 assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [641174.75, 641174.75]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array( - [2260.644, 2260.644]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [168.781, 168.781]), tol) - assert_near_equal( - self.prob["alpha_rate"], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob["normal_force"], np.array( - [0.0, 0.0]), tol) + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([642141.32322003, 642141.32322003]), + tol, + ) assert_near_equal( - self.prob["fuselage_pitch"], np.array( - [0.0, 0.0]), tol) + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], + np.array([2260.644, 2260.644]), + tol, + ) + assert_near_equal(self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array([0.0, 0.0]), tol) assert_near_equal( - self.prob["load_factor"], np.array( - [11850.494, 11850.494]), tol) + self.prob[Dynamic.Mission.DISTANCE_RATE], np.array([168.781, 168.781]), tol + ) + assert_near_equal(self.prob['angle_of_attack_rate'], np.array([0.0, 0.0]), tol) + assert_near_equal(self.prob['normal_force'], np.array([0.0, 0.0]), tol) + assert_near_equal(self.prob['fuselage_pitch'], np.array([0.0, 0.0]), tol) + assert_near_equal(self.prob['load_factor'], np.array([11850.494, 11850.494]), tol) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_breguet_cruise_eom.py b/aviary/mission/gasp_based/ode/test/test_breguet_cruise_eom.py index b563c2efe8..fcf2087346 100644 --- a/aviary/mission/gasp_based/ode/test/test_breguet_cruise_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_breguet_cruise_eom.py @@ -2,40 +2,41 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.constants import GRAV_ENGLISH_LBM -from aviary.mission.gasp_based.ode.breguet_cruise_eom import RangeComp +from aviary.mission.gasp_based.ode.breguet_cruise_eom import E_RangeComp, RangeComp from aviary.variable_info.variables import Dynamic class TestBreguetResults(unittest.TestCase): - """ - Test cruise range and time in RangeComp component - """ + """Test cruise range and time in RangeComp component.""" def setUp(self): nn = 10 self.prob = om.Problem() - self.prob.model.add_subsystem( - "range_comp", RangeComp(num_nodes=nn), promotes=["*"]) + self.prob.model.add_subsystem('range_comp', RangeComp(num_nodes=nn), promotes=['*']) self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val("TAS_cruise", 458.8, units="kn") - self.prob.set_val("mass", np.linspace(171481, 171481 - 10000, nn), units="lbm") - self.prob.set_val(Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - - 5870 * np.ones(nn,), units="lbm/h") + self.prob.set_val('TAS_cruise', 458.8, units='kn') + self.prob.set_val('mass', np.linspace(171481, 171481 - 10000, nn), units='lbm') + self.prob.set_val( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + -5870 + * np.ones( + nn, + ), + units='lbm/h', + ) def test_case1(self): - tol = 1e-6 self.prob.run_model() - cruise_range = self.prob.get_val("cruise_range", units="NM") - cruise_time = self.prob.get_val("cruise_time", units="s") + cruise_range = self.prob.get_val('cruise_range', units='NM') + cruise_time = self.prob.get_val('cruise_time', units='s') t_expected = 6134.7240144 r_expected = 781.83848643 @@ -45,7 +46,7 @@ def test_case1(self): with np.printoptions(linewidth=1024): self.prob.model.list_outputs(prom_name=True, print_arrays=True) - partial_data = self.prob.check_partials(method="cs") # , out_stream=None) + partial_data = self.prob.check_partials(method='cs') # , out_stream=None) assert_check_partials(partial_data, atol=tol, rtol=tol) @@ -54,21 +55,33 @@ def setUp(self): nn = 10 self.prob = om.Problem() - self.prob.model.add_subsystem( - "range_comp", RangeComp(num_nodes=nn), promotes=["*"]) + self.prob.model.add_subsystem('range_comp', RangeComp(num_nodes=nn), promotes=['*']) self.prob.model.set_input_defaults( - "TAS_cruise", 458.8 + 50 * np.random.rand(nn,), units="kn") + 'TAS_cruise', + 458.8 + + 50 + * np.random.rand( + nn, + ), + units='kn', + ) self.prob.model.set_input_defaults( - "mass", np.linspace(171481, 171481 - 10000, nn), units="lbm") + 'mass', np.linspace(171481, 171481 - 10000, nn), units='lbm' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, -5870 * np.ones(nn,), units="lbm/h") + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + -5870 + * np.ones( + nn, + ), + units='lbm/h', + ) self.prob.setup(check=False, force_alloc_complex=True) def test_partials(self): - - tol = 1e-12 + tol = 1e-10 self.prob.run_model() # cruise_range = self.prob.get_val("cruise_range", units="NM") @@ -82,75 +95,141 @@ def test_partials(self): with np.printoptions(linewidth=1024): self.prob.model.list_outputs(prom_name=True, print_arrays=True) - partial_data = self.prob.check_partials(method="cs") # , out_stream=None) + partial_data = self.prob.check_partials(method='cs') # , out_stream=None) assert_check_partials(partial_data, atol=tol, rtol=tol) class TestBreguetPartials2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.breguet_cruise_eom as breguet + breguet.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.breguet_cruise_eom as breguet + breguet.GRAV_ENGLISH_LBM = 1.0 def test_partials(self): nn = 2 prob = om.Problem() - prob.model.add_subsystem( - "range_comp", RangeComp(num_nodes=nn), promotes=["*"]) + prob.model.add_subsystem('range_comp', RangeComp(num_nodes=nn), promotes=['*']) prob.model.set_input_defaults( - "TAS_cruise", 458.8 + 50 * np.random.rand(nn,), units="kn") + 'TAS_cruise', + 458.8 + + 50 + * np.random.rand( + nn, + ), + units='kn', + ) + prob.model.set_input_defaults('mass', np.linspace(171481, 171481 - 10000, nn), units='lbm') prob.model.set_input_defaults( - "mass", np.linspace(171481, 171481 - 10000, nn), units="lbm") - prob.model.set_input_defaults( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, -5870 * np.ones(nn,), units="lbm/h") + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + -5870 + * np.ones( + nn, + ), + units='lbm/h', + ) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-11, rtol=1e-11) -class TestBreguetResults(unittest.TestCase): +class TestBreguetResults2(unittest.TestCase): def setUp(self): self.nn = nn = 100 self.prob = om.Problem() - self.prob.model.add_subsystem("range_comp", - RangeComp(num_nodes=nn), promotes=["*"]) + self.prob.model.add_subsystem('range_comp', RangeComp(num_nodes=nn), promotes=['*']) self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val("TAS_cruise", 458.8, units="kn") - self.prob.set_val("mass", np.linspace(171481, 171481 - 10000, nn), units="lbm") - self.prob.set_val(Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - - 5870 * np.ones(nn,), units="lbm/h") + self.prob.set_val('TAS_cruise', 458.8, units='kn') + self.prob.set_val('mass', np.linspace(171481, 171481 - 10000, nn), units='lbm') + self.prob.set_val( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + -5870 + * np.ones( + nn, + ), + units='lbm/h', + ) def test_results(self): self.prob.run_model() - W = self.prob.get_val("mass", units="lbm") * GRAV_ENGLISH_LBM - V = self.prob.get_val("TAS_cruise", units="kn") - r = self.prob.get_val("cruise_range", units="NM") - t = self.prob.get_val("cruise_time", units="h") - fuel_flow = - \ - self.prob.get_val( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units="lbm/h") + W = self.prob.get_val('mass', units='lbm') * GRAV_ENGLISH_LBM + V = self.prob.get_val('TAS_cruise', units='kn') + r = self.prob.get_val('cruise_range', units='NM') + t = self.prob.get_val('cruise_time', units='h') + fuel_flow = -self.prob.get_val( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' + ) - v_avg = (V[:-1] + V[1:])/2 - fuel_flow_avg = (fuel_flow[:-1] + fuel_flow[1:])/2 + v_avg = (V[:-1] + V[1:]) / 2 + fuel_flow_avg = (fuel_flow[:-1] + fuel_flow[1:]) / 2 # Range should be equal to the product of initial speed in the segment and change in time - assert_near_equal(np.diff(r), v_avg * np.diff(t), tolerance=1.0E-5) + assert_near_equal(np.diff(r), v_avg * np.diff(t), tolerance=1.0e-5) # time should satisfy: dt = -dW / fuel_flow - assert_near_equal(np.diff(t), -np.diff(W) / fuel_flow_avg, tolerance=1.0E-6) + assert_near_equal(np.diff(t), -np.diff(W) / fuel_flow_avg, tolerance=1.0e-6) + + +class TestElectricBreguetResults(unittest.TestCase): + """Test cruise range and time in E_RangeComp component.""" + + def setUp(self): + nn = 10 + + self.prob = om.Problem() + self.prob.model.add_subsystem('e_range_comp', E_RangeComp(num_nodes=nn), promotes=['*']) + + self.prob.setup(check=False, force_alloc_complex=True) + + self.prob.set_val('TAS_cruise', 458.8, units='kn') + self.prob.set_val( + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, + np.linspace(5843, 19390, nn), + units='kW*h', + ) + self.prob.set_val( + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + 7531.64 + * np.ones( + nn, + ), + units='kW', + ) # 10100.1 hp in GASP + + def test_case1(self): + tol = 1e-6 + self.prob.run_model() + + cruise_range = self.prob.get_val('cruise_range', units='NM') + cruise_time = self.prob.get_val('cruise_time', units='s') + + t_expected = 6475.243 + r_expected = 825.2337 + + assert_near_equal(cruise_range[-1, ...], r_expected, tolerance=tol) + assert_near_equal(cruise_time[-1, ...], t_expected, tolerance=tol) + + def test_partials(self): + tol = 1e-10 + self.prob.run_model() + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=tol, rtol=tol) -if __name__ == "__main__": - unittest.main() +if __name__ == '__main__': + # unittest.main() + test = TestBreguetPartials2() + test.setUp() + test.test_partials() diff --git a/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py b/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py index c69f465d22..c724838aea 100644 --- a/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_breguet_cruise_ode.py @@ -4,12 +4,16 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.mission.gasp_based.ode.breguet_cruise_ode import BreguetCruiseODESolution +from aviary.mission.gasp_based.ode.breguet_cruise_ode import ( + BreguetCruiseODESolution, + E_BreguetCruiseODESolution, +) from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic class CruiseODETestCase(unittest.TestCase): @@ -17,52 +21,127 @@ def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) self.prob.model = BreguetCruiseODESolution( num_nodes=2, aviary_options=aviary_options, - core_subsystems=default_mission_subsystems) + core_subsystems=default_mission_subsystems, + ) self.prob.model.set_input_defaults( - Dynamic.Mission.MACH, np.array([0, 0]), units="unitless" + Dynamic.Atmosphere.MACH, np.array([0, 0]), units='unitless' ) + setup_model_options(self.prob, aviary_options) + def test_cruise(self): # test partial derivatives self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val(Dynamic.Mission.MACH, [0.7, 0.7], units="unitless") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Dynamic.Atmosphere.MACH, [0.7, 0.7], units='unitless') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) self.prob.run_model() tol = tol = 1e-6 + assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([1.0, 1.0]), tol) + assert_near_equal(self.prob[Dynamic.Mission.DISTANCE], np.array([0.0, 923.16791306]), tol) + assert_near_equal(self.prob['time'], np.array([0, 8277.67602647]), tol) assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [1.0, 1.0]), tol) + self.prob[Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS], + np.array([3.8817684, 4.899673]), + tol, + ) assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE], np.array( - [0.0, 881.8116]), tol) + self.prob[Dynamic.Mission.ALTITUDE_RATE_MAX], + np.array([-17.17989089, -16.16198629]), + tol, + ) + + partial_data = self.prob.check_partials( + out_stream=None, method='cs', excludes=['*USatm*', '*params*', '*aero*'] + ) + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + +class ElectricCruiseODETestCase(unittest.TestCase): + """This test uses a makeup electrical engine to test electrical Breguet cruise ODE.""" + + def setUp(self): + self.prob = om.Problem() + + aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) + aviary_options.set_val( + Aircraft.Engine.DATA_FILE, + 'mission/gasp_based/ode/test/test_data/turbofan_23k_electrified.csv', + ) + default_mission_subsystems = get_default_mission_subsystems( + 'GASP', build_engine_deck(aviary_options) + ) + + self.prob.model = E_BreguetCruiseODESolution( + num_nodes=2, + aviary_options=aviary_options, + core_subsystems=default_mission_subsystems, + ) + + self.prob.model.set_input_defaults( + Dynamic.Atmosphere.MACH, np.array([0, 0]), units='unitless' + ) + + setup_model_options(self.prob, aviary_options) + + def test_electric_cruise(self): + # test partial derivatives + self.prob.setup(check=False, force_alloc_complex=True) + + self.prob.set_val(Dynamic.Atmosphere.MACH, [0.7, 0.7], units='unitless') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) + + set_params_for_unit_tests(self.prob) + + self.prob.run_model() + + tol = tol = 1e-6 + assert_near_equal(self.prob[Dynamic.Mission.VELOCITY_RATE], np.array([1.0, 1.0]), tol) + assert_near_equal(self.prob[Dynamic.Mission.DISTANCE], np.array([0.0, 66.31948625]), tol) + assert_near_equal(self.prob['time'], np.array([0, 594.66020611]), tol) assert_near_equal( - self.prob["time"], np.array( - [0, 7906.83]), tol) + self.prob[Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS], + np.array([3.88939674, 4.90776872]), + tol, + ) assert_near_equal( - self.prob[Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS], np.array( - [3.429719, 4.433518]), tol) + self.prob[Dynamic.Mission.ALTITUDE_RATE_MAX], + np.array([-17.17226255, -16.15389057]), + tol, + ) assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE_MAX], np.array( - [-17.63194, -16.62814]), tol) + self.prob[Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL], + np.array([4.46078513, 4.15465068]), + tol, + ) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*USatm*", "*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*USatm*', '*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_climb_eom.py b/aviary/mission/gasp_based/ode/test/test_climb_eom.py index ec9f04da54..92af6d6301 100644 --- a/aviary/mission/gasp_based/ode/test/test_climb_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_climb_eom.py @@ -2,8 +2,7 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.climb_eom import ClimbRates from aviary.variable_info.variables import Dynamic @@ -16,84 +15,87 @@ class ClimbTestCase(unittest.TestCase): """ def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("group", ClimbRates(num_nodes=2), promotes=["*"]) + self.prob.model.add_subsystem('group', ClimbRates(num_nodes=2), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([459, 459]), units="kn") + Dynamic.Mission.VELOCITY, np.array([459, 459]), units='kn' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([10473, 10473]), units="lbf" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + np.array([10473, 10473]), + units='lbf', ) self.prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([9091.517, 9091.517]), units="lbf" + Dynamic.Vehicle.DRAG, np.array([9091.517, 9091.517]), units='lbf' ) self.prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([171481, 171481]), units="lbm" + Dynamic.Vehicle.MASS, np.array([171481, 171481]), units='lbm' ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [6.24116612, 6.24116612]), tol + self.prob[Dynamic.Mission.ALTITUDE_RATE], + np.array([6.24116612, 6.24116612]), + tol, ) # note: values from GASP are: np.array([5.9667, 5.9667]) assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [774.679584, 774.679584]), tol + self.prob[Dynamic.Mission.DISTANCE_RATE], + np.array([774.679584, 774.679584]), + tol, # note: these values are finite differenced and lose accuracy. Fd values are: np.array([799.489, 799.489]) ) assert_near_equal( - self.prob["required_lift"], + self.prob['required_lift'], np.array([171475.43516703, 171475.43516703]), tol, ) # note: values from GASP are: np.array([170316.2, 170316.2]) assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE], np.array( - [0.00805627, 0.00805627]), tol + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE], + np.array([0.00805627, 0.00805627]), + tol, ) # note: values from GASP are:np.array([.0076794487, .0076794487]) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class ClimbTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.climb_eom as climb + climb.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.climb_eom as climb + climb.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem("group", ClimbRates(num_nodes=2), promotes=["*"]) - prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([459, 459]), units="kn") - prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([10473, 10473]), units="lbf" - ) + prob.model.add_subsystem('group', ClimbRates(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, np.array([459, 459]), units='kn') prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([9091.517, 9091.517]), units="lbf" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + np.array([10473, 10473]), + units='lbf', ) prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([171481, 171481]), units="lbm" + Dynamic.Vehicle.DRAG, np.array([9091.517, 9091.517]), units='lbf' ) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([171481, 171481]), units='lbm') prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_climb_ode.py b/aviary/mission/gasp_based/ode/test/test_climb_ode.py index 8be1742a80..2b50708ef3 100644 --- a/aviary/mission/gasp_based/ode/test/test_climb_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_climb_ode.py @@ -9,105 +9,127 @@ from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic class ClimbODETestCase(unittest.TestCase): - """ - Test 2-degree of freedom climb ODE - """ + """Test 2-degree of freedom climb ODE.""" def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val('verbosity', Verbosity.QUIET) + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) + default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) self.sys = self.prob.model = ClimbODE( num_nodes=1, EAS_target=250, mach_cruise=0.8, - aviary_options=get_option_defaults(), - core_subsystems=default_mission_subsystems + aviary_options=aviary_options, + core_subsystems=default_mission_subsystems, ) + setup_model_options(self.prob, aviary_options) + def test_start_of_climb(self): # Test against GASP start of climb at 250 kts EAS, check partials - self.sys.options["EAS_target"] = 250 + self.sys.options['EAS_target'] = 250 self.prob.setup(check=False, force_alloc_complex=True) throttle_climb = 0.956 - self.prob.set_val( - Dynamic.Mission.THROTTLE, throttle_climb, units='unitless') - self.prob.set_val(Dynamic.Mission.ALTITUDE, 1000, units="ft") - self.prob.set_val(Dynamic.Mission.MASS, 174845, units="lbm") - self.prob.set_val("EAS", 250, units="kn") + self.prob.set_val(Dynamic.Vehicle.Propulsion.THROTTLE, throttle_climb, units='unitless') + self.prob.set_val(Dynamic.Mission.ALTITUDE, 1000, units='ft') + self.prob.set_val(Dynamic.Vehicle.MASS, 174845, units='lbm') + self.prob.set_val('EAS', 250, units='kn') # slightly greater than zero to help check partials - self.prob.set_val(Aircraft.Wing.INCIDENCE, 0.0000001, units="deg") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Aircraft.Wing.INCIDENCE, 0.0000001, units='deg') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) self.prob.run_model() testvals = { - "alpha": 5.16398, - "CL": 0.59766664, - "CD": 0.03070836, - Dynamic.Mission.ALTITUDE_RATE: 3414.63 / 60, # ft/s - # TAS (kts -> ft/s) * cos(gamma), 253.6827 * 1.68781 * cos(0.13331060446181708) - Dynamic.Mission.DISTANCE_RATE: 424.36918705874785, # ft/s - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: -13448.29, # lbm/h - "theta": 0.22343879616956605, # rad (12.8021 deg) - Dynamic.Mission.FLIGHT_PATH_ANGLE: 0.13331060446181708, # rad (7.638135 deg) + Dynamic.Vehicle.ANGLE_OF_ATTACK: 5.16173398, + 'CL': 0.59745598, + 'CD': 0.02914888, + Dynamic.Mission.ALTITUDE_RATE: 58.0148345, # ft/s + # TAS (kts -> ft/s) * cos(gamma), 253.6827 * 1.68781 * + # cos(0.13331060446181708) + Dynamic.Mission.DISTANCE_RATE: 424.21929709, # ft/s + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL: -13447.80297433, # lbm/h + 'theta': 0.22600284, # rad (12.8021 deg) + # rad (7.638135 deg) + Dynamic.Mission.FLIGHT_PATH_ANGLE: 0.13591359, } check_prob_outputs(self.prob, testvals, rtol=1e-6) - self.prob.setup(check=False, force_alloc_complex=True) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) def test_end_of_climb(self): # Test against GASP at 270 kts EAS and at cruise Mach. - self.sys.options["num_nodes"] = 2 - self.sys.options["EAS_target"] = 270 + self.sys.options['num_nodes'] = 2 + self.sys.options['EAS_target'] = 270 self.prob.setup(check=False, force_alloc_complex=True) throttle_climb = 0.956 self.prob.set_val( - Dynamic.Mission.THROTTLE, np.array([ - throttle_climb, throttle_climb]), units='unitless') - self.prob.set_val(Dynamic.Mission.ALTITUDE, np.array([11000, 37000]), units="ft") - self.prob.set_val(Dynamic.Mission.MASS, np.array([174149, 171592]), units="lbm") - self.prob.set_val("EAS", np.array([270, 270]), units="kn") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + Dynamic.Vehicle.Propulsion.THROTTLE, + np.array([throttle_climb, throttle_climb]), + units='unitless', + ) + self.prob.set_val(Dynamic.Mission.ALTITUDE, np.array([11000, 37000]), units='ft') + self.prob.set_val(Dynamic.Vehicle.MASS, np.array([174149, 171592]), units='lbm') + self.prob.set_val('EAS', np.array([270, 270]), units='kn') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) self.prob.run_model() testvals = { - "alpha": [4.05559, 4.08245], - "CL": [0.512629, 0.617725], - "CD": [0.02692764, 0.03311237], - Dynamic.Mission.ALTITUDE_RATE: [3053.754 / 60, 429.665 / 60], # ft/s + Dynamic.Vehicle.ANGLE_OF_ATTACK: [4.05423953, 4.06601219], + 'CL': [0.51248541, 0.61580247], + 'CD': [0.02543166, 0.03141751], + Dynamic.Mission.ALTITUDE_RATE: [52.44471763, 9.11523198], # ft/s # TAS (kts -> ft/s) * cos(gamma), [319, 459] kts - Dynamic.Mission.DISTANCE_RATE: [536.2835, 774.4118], # ft/s - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: [-11420.05, -6050.26], - "theta": [0.16540479, 0.08049912], # rad ([9.47699, 4.61226] deg), - Dynamic.Mission.FLIGHT_PATH_ANGLE: [0.09462135, 0.00924686], # rad, gamma - Dynamic.Mission.THRUST_TOTAL: [25560.51, 10784.25], + # ft/s + Dynamic.Mission.DISTANCE_RATE: [536.08501758, 774.38047573], + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL: [ + -11417.86519196, + -6042.88107957, + ], + 'theta': [0.16827862, 0.08273576], # rad ([9.47740, 4.59730] deg), + # rad, gamma + Dynamic.Mission.FLIGHT_PATH_ANGLE: [0.09751879, 0.01177046], + Dynamic.Vehicle.Propulsion.THRUST_TOTAL: [25556.83497662, 10773.48189764], } check_prob_outputs(self.prob, testvals, 1e-6) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = ClimbODETestCase() + # test.setUp() + # test.test_end_of_climb() diff --git a/aviary/mission/gasp_based/ode/test/test_data/turbofan_23k_electrified.csv b/aviary/mission/gasp_based/ode/test/test_data/turbofan_23k_electrified.csv new file mode 100644 index 0000000000..0793b7cf1b --- /dev/null +++ b/aviary/mission/gasp_based/ode/test/test_data/turbofan_23k_electrified.csv @@ -0,0 +1,2809 @@ +# GASP-derived engine deck converted from GASP_turbofan_23k_1.eng +# Modified to be all-electric for testing modified breguet range component, not real data +# t4max: 3342.0 +# t4cruise: 3108.0 +# t4climb: 3196.0 +# sls_airflow: 994.36 +# sfn_idle: 1.25 + +Mach_Number, Altitude (ft), Throttle, Thrust (lbf),Electric_Power (W), T4 (degR) +0,0,0, 621.4719458090369, 621.4719458090369,0 +0,0, 0.4655924596050269,-1979.1619,-105.2491, 1556.0099999999998 +0,0, 0.5431912028725313, 1065.323499999999, 539.5527999999999, 1815.3449999999998 +0,0, 0.6207899461400359, 4109.808599999997, 1184.3545999999994,2074.68 +0,0, 0.6983886894075404, 7327.181199999998, 1870.6585999999998,2334.015 +0,0, 0.7759874326750449, 11036.915999999994, 2800.214400000001,2593.35 +0,0, 0.8535861759425494, 15708.877899999996, 4095.815400000001,2852.685 +0,0, 0.9311849192100538, 21836.462899999977, 5870.266599999997, 3112.0199999999995 +0,3000,0, 562.8245919323617, 562.8245919323617,0 +0,3000, 0.45598922800718134,-2285.519,-183.5061,1523.916 +0,3000, 0.5319874326750449, 456.4108999999994, 412.26110000000006,1777.902 +0,3000, 0.6079856373429084, 3198.3412999999987,1008.0283,2031.888 +0,3000, 0.6839838420107719, 5972.483399999998,1620.9913,2285.874 +0,3000, 0.7599820466786354, 9207.826199999998, 2437.9938999999995, 2539.8599999999997 +0,3000, 0.8359802513464991, 13217.797900000009, 3553.4655999999995,2793.846 +0,3000, 0.9119784560143627, 18617.677700000004, 5114.419399999995,3047.832 +0,3000, 0.9879766606822261, 25284.21289999999, 7083.126999999999, 3301.8179999999998 +0,6000,0, 508.6372241992847, 508.6372241992847,0 +0,6000, 0.4463850987432675,-2935.8345,-280.32,1491.819 +0,6000, 0.5207826152004787,-197.4633, 275.13859999999977,1740.4555 +0,6000,0.595180132, 2540.907699999998, 830.5971999999995,1989.092 +0,6000, 0.6695776481149013, 5279.279300000001, 1386.0558000000003,2237.7285 +0,6000, 0.7439751645721125, 8213.525399999993,2090.8967, 2486.3650000000002 +0,6000, 0.8183726810293238, 11851.381800000008, 3062.070300000002, 2735.0015000000003 +0,6000,0.892770197, 16560.28909999998, 4378.632800000005,2983.638 +0,6000, 0.9671677139437462, 22654.554700000022,6120.2305,3232.2745 +0,9000,0, 458.6569006593942, 458.6569006593942,0 +0,9000, 0.4367818671454219, 820.9403000000008,-198.5158,1459.725 +0,9000, 0.5095788450029922, 2287.7753999999904, 273.47830000000204,1703.0125 +0,9000, 0.5823758228605626, 3754.6023999999666, 745.4744000000036,1946.3 +0,9000, 0.6551728007181329, 5221.432299999996, 1217.471099999993,2189.5875 +0,9000, 0.7279697785757032, 6857.633999999983, 1767.4456000000362,2432.875 +0,9000, 0.8007667564332734, 10501.953100000013, 2618.3858000000314,2676.1625 +0,9000, 0.8735637342908438,14702.6974,3781.4553,2919.45 +0,9000,0.946360712, 19922.60839999998, 5272.304499999956, 3162.7374999999997 +0,12000,0, 412.6354242729135, 412.6354242729135,0 +0,12000, 0.42717773788150804,-10008.41005,-627.1232216,1427.628 +0,12000,0.498374028,-5628.271186,-88.3645568, 1665.5659999999998 +0,12000, 0.5695703171753441,-1248.107982, 450.40240640002145,1903.504 +0,12000, 0.6407666068222622, 3132.0434624000236, 989.1721031999733,2141.442 +0,12000, 0.7119628964691802, 7439.101973600087, 1656.5764536000047,2379.38 +0,12000,0.783159186, 10835.884655199505, 2375.840575199889, 2617.3179999999998 +0,12000, 0.8543554757630161, 10534.273431199275, 2915.174178399845,2855.256 +0,12000, 0.9255517654099341, 17296.457434399927, 4499.2635783996575,3093.194 +0,12000,0.996748055, 22936.55361199949, 6163.146618399912, 3331.1319999999996 +0,15000,0, 370.3405482510708, 370.3405482510708,0 +0,15000, 0.4175745062836625,-4108.3274,-953.7424,1395.534 +0,15000, 0.48717025733093955,-2085.1374,-423.2656,1628.123 +0,15000, 0.5567660083782167,-61.8775, 107.2300999999502,1860.712 +0,15000, 0.6263617594254937, 1961.357899999819, 637.7068999999258,2093.301 +0,15000, 0.6959575104727708, 3868.836799999729, 805.1977999995336,2325.89 +0,15000, 0.7655532615200478, 9295.393299999978, 2069.673199999495,2558.479 +0,15000,0.835149013, 8117.555200000044, 2353.5224000002117,2791.068 +0,15000, 0.9047447636146021, 22532.67410000153, 5324.8861000002025,3023.657 +0,15000, 0.9743405146618791,-366.1336, 2489.8093999998064,3256.246 +0,18000,0, 331.5464430756027, 331.5464430756027,0 +0,18000, 0.40797037701974864,-18660.52886,-3371.539818,1363.437 +0,18000, 0.47596543985637346,-12470.87884,-2194.400063,1590.6765 +0,18000, 0.5439605026929982,-6281.173878,-1017.324201,1817.916 +0,18000, 0.6119555655296229,-91.4635384, 159.76448639951894, 2045.1554999999998 +0,18000, 0.6799506283662478, 1838.8419391999305, 794.5162264001054,2272.395 +0,18000, 0.7479456912028726, 3461.4070168009703, 958.9548840003713,2499.6345 +0,18000, 0.8159407540394973, 8465.954334398888, 1595.0021775992507,2726.874 +0,18000, 0.8839358168761221,4672.626438, 1685.1043480005942,2954.1135 +0,18000, 0.9519308797127469, 30679.135772005346,5644.575666,3181.353 +0,21000,0, 296.0341081608423, 296.0341081608423,0 +0,21000, 0.3983671454219031, 5188.336937600053, 3488.554260800007,1331.343 +0,21000, 0.46476166965888693, 4883.054692800119, 2747.0215935999963,1553.2335 +0,21000, 0.5311561938958708, 4577.828439199983, 2005.5017512000343,1775.124 +0,21000, 0.5975507181328545, 4272.564631200534, 1263.935070399853,1997.0145 +0,21000, 0.6639452423698384, 4056.199360800366,908.3934728,2218.905 +0,21000, 0.7303397666068223, 1.5720368018537556, 649.5522704002658,2440.7955 +0,21000, 0.7967342908438062, 5555.628807200999, 1337.8957319992742,2662.686 +0,21000,0.863128815, 10865.940131196825, 3806.6596968006347,2884.5765 +0,21000, 0.9295233393177739, 13527.602489597844, 5415.268763999967,3106.467 +0,21000, 0.9959178635547576, 24247.309808000195, 11037.817901601342,3328.3575 +0,24000,0, 263.5961389215397, 263.5961389215397,0 +0,24000, 0.38876301615798925,-2276.284299,-4246.114488,1299.246 +0,24000, 0.4535568521843208,-1397.985689,-3030.823914,1515.787 +0,24000, 0.5183506882106523,-519.6311048,-1815.548862,1732.328 +0,24000, 0.5831445242369838, 358.6362591998643,-600.2790032,1948.869 +0,24000, 0.6479383602633153, 3549.5378272005296, 1028.186566400504,2165.41 +0,24000, 0.7127321962896469, 7246.497172000982, 2298.2067224006373,2381.951 +0,24000, 0.7775260323159785, 8081.8817984045445, 2419.336496798534,2598.492 +0,24000,0.842319868, 10914.132656799951, 2151.440016000627,2815.033 +0,24000, 0.9071137043686416, 8142.089100804155, 2189.648812002002,3031.574 +0,24000,0.97190754, 9356.254232008245, 3346.386321604228,3248.115 +0,27000,0, 234.03155056971013, 234.03155056971013,0 +0,27000, 0.37915978456014365, 31666.47125680015, 15545.981836000006,1267.152 +0,27000, 0.44235308198683426, 22716.749602400203, 11633.723804800002,1478.344 +0,27000, 0.5055463794135249, 13766.905935999872, 7721.385391999946,1689.536 +0,27000, 0.5687396768402154, 4817.089456799192, 3809.046979199601,1900.728 +0,27000, 0.6319329742669061,-4080.899666,-421.772892,2111.92 +0,27000, 0.6951262716935966, 3533.178786400851, 157.00693919892183,2323.112 +0,27000, 0.7583195691202873, 2905.361299203511, 84.29607599992141,2534.304 +0,27000, 0.8215128665469779,-631.55984, 2054.877212800607,2745.496 +0,27000, 0.8847061639736685, 10808.442852806893, 2537.8370016038916,2956.688 +0,27000, 0.9478994614003591,-1558.28779, 3488.2616032036394,3167.88 +0,30000,0, 207.15053647796987, 207.15053647796987,0 +0,30000, 0.3695556552962298, 423.60839999973825, 2063.463199999922,1235.055 +0,30000, 0.4311482645122681, 2344.484399999737, 1915.561399999787,1440.8975 +0,30000, 0.4927408737283064, 4264.664800000413, 1767.8806999995636,1646.74 +0,30000, 0.5543334829443447, 6185.202800000603, 1620.0712000001233,1852.5825 +0,30000, 0.6159260921603831, 4867.513699999471, 174.7018999992215,2058.425 +0,30000, 0.6775187013764212,-1357.8646, 312.41500000152246,2264.2675 +0,30000, 0.7391113105924596, 916.2128999978495,-601.5901,2470.11 +0,30000, 0.8007039198084979, 2808.1613999994415,-2068.8761,2675.9525 +0,30000, 0.8622965290245362, 14043.931799998172, 6579.604899998823,2881.795 +0,30000, 0.9238891382405745, 29400.548600009355, 4365.934599993016,3087.6375 +0,30000, 0.9854817474566128, 60041.21150001316, 12221.730399983775,3293.48 +0,33000,0, 182.7682627822692, 182.7682627822692,0 +0,33000, 0.3599524236983842, 73148.21513039994, 8353.324134399922,1202.961 +0,33000, 0.4199444943147816, 57096.465740799256, 6361.086206400059,1403.4545 +0,33000,0.479936565, 41044.58415039877, 4368.839710400288,1603.948 +0,33000, 0.5399286355475763, 24992.66943039941, 2376.7084791998554, 1804.4415000000001 +0,33000, 0.5999207061639737, 8940.679883199635, 384.3552863992233, 2004.9350000000002 +0,33000, 0.6599127767803711,-2678.41669,-598.4544072,2205.4285 +0,33000, 0.7199048473967684, 11541.777525599551, 4514.568512799082,2405.922 +0,33000, 0.7798969180131657, 10052.411211202108, 3617.193000001155,2606.4155 +0,33000, 0.8398889886295632,-5615.760698,-4056.633314,2806.909 +0,33000, 0.8998810592459605, 3125.791250395734, 1784.9111847969689,3007.4025 +0,33000,0.95987313,-53986.2557,-34872.51459,3207.896 +0,36000,0, 160.71110145094153, 160.71110145094153,0 +0,36000, 0.3503482944344704, 69414.82060000008, 6249.212800000052,1170.864 +0,36000, 0.40873967684021545, 54979.246499999215, 5111.865600000102,1366.008 +0,36000, 0.4671310592459605, 40543.321499997386, 3974.518400000331,1561.152 +0,36000, 0.5255224416517056, 26107.675899999722, 2837.2075999997337,1756.296 +0,36000, 0.5839138240574506, 11671.904299999183, 1699.743499999383,1951.44 +0,36000, 0.6423052064631957, 1488.745499999287, 509.0396000006642,2146.584 +0,36000, 0.7006965888689408, 908.5232000010947, 93.53199999941216,2341.728 +0,36000, 0.7590879712746859,-22077.3786,-3060.6909, 2536.8720000000003 +0,36000, 0.8174793536804309, 47160.97369998603, 10763.036000004584,2732.016 +0,36000, 0.8758707360861759, 16056.511699998635, 5520.046099998181,2927.16 +0,36000,0.934262118,-24769.2238,-23716.8812,3122.304 +0,39000,0, 139.18795884474554, 139.18795884474554,0 +0,39000, 0.3500628366247756, 476.76869999981204, 100.47639999994212,1169.91 +0,39000, 0.40840664272890487,-266.4172,-23.404,1364.895 +0,39000, 0.4667504488330341,-1009.8918,-147.2753,1559.88 +0,39000, 0.5250942549371634,-1753.1675,-271.0661, 1754.8650000000002 +0,39000, 0.5834380610412927,-2496.6147,-394.901, 1949.8500000000001 +0,39000,0.641781867,-4195.4422,-718.9284,2144.835 +0,39000, 0.7001256732495512,-200.1008,-10.5781,2339.82 +0,39000, 0.7584694793536805,-4917.3097,-2004.8832, 2534.8050000000003 +0,39000, 0.8168132854578097, 6913.459500000736,-4331.2686,2729.79 +0,39000,0.875157092, 11889.88930000615, 4348.427600005591,2924.775 +0,39000, 0.9335008976660683, 120355.93110000575, 68678.60510001137,3119.76 +0,42000,0, 120.49820969410051, 120.49820969410051,0 +0,42000, 0.3500628366247756,-462426.4545,-178027.5354,1169.91 +0,42000, 0.40840664272890487,-362855.99,-139381.9193,1364.895 +0,42000, 0.4667504488330341,-263285.614,-100736.254,1559.88 +0,42000, 0.5250942549371634,-163715.3712,-62090.52693, 1754.8650000000002 +0,42000, 0.5834380610412927,-64145.00642,-23445.02316, 1949.8500000000001 +0,42000,0.641781867,-17490.57143,-5916.4266,2144.835 +0,42000, 0.7001256732495512, 9317.000762499272, 942.0129812504897,2339.82 +0,42000, 0.7584694793536805,-11674.66693,-219.0788, 2534.8050000000003 +0,42000, 0.8168132854578097, 25036.390487502504, 13878.411762500029,2729.79 +0,42000,0.875157092,-11573.78817,-5031.31815,2924.775 +0,42000, 0.9335008976660683, 18711.330206260376, 14545.346225007728,3119.76 +0.05,0,0, 622.4046199093938, 622.4046199093938,0 +0.05,0, 0.4658252558348294,-1937.3721,-104.1252, 1556.7880049999999 +0.05,0, 0.5434627984739676, 906.8547000000044, 545.1483999999999, 1816.2526724999998 +0.05,0, 0.6211003411131059, 3751.0815000000075, 1194.4219999999982, 2075.7173399999997 +0.05,0,0.698737884, 6786.725600000015, 1886.2708999999904, 2335.1820074999996 +0.05,0, 0.7763754263913822, 10343.10549999996,2825.1267, 2594.6466749999995 +0.05,0, 0.8540129690305205, 14849.091799999986, 4132.926300000012, 2854.1113424999994 +0.05,0, 0.9316505116696588, 20803.984399999925,5925.9199, 3113.5760099999998 +0.05,3000,0, 563.6692510090572, 563.6692510090572,0 +0.05,3000, 0.4562172226211849,-2248.270465,-179.918008,1524.677958 +0.05,3000, 0.5322534263913824, 396.6363202068742, 416.5179393489364,1778.790951 +0.05,3000, 0.6082896301615799, 3041.5431144829804, 1012.9540865957446,2032.903944 +0.05,3000, 0.6843258339317774, 5721.0667973379595, 1627.1265442896877,2287.016937 +0.05,3000, 0.7603620377019749, 8885.487061135052, 2447.127690868093,2541.12993 +0.05,3000, 0.8363982414721723, 12820.922420032442, 3565.7965681932938,2795.242923 +0.05,3000, 0.9124344452423698, 18151.574776620157, 5134.593962625701,3049.355916 +0.05,3000, 0.9884706490125672, 24712.702336123915, 7106.733353212599, 3303.4689089999997 +0.05,6000,0, 509.40056157708136, 509.40056157708136,0 +0.05,6000, 0.4466082912926391,-2750.051225,-271.65065, 1492.5649094999999 +0.05,6000,0.521043007,-204.449625, 283.84602499999943,1741.325728 +0.05,6000, 0.5954777217235189, 2341.1521999999923, 839.3429499999986,1990.086546 +0.05,6000, 0.6699124369389586, 4887.9331250000205, 1395.473525000012,2238.847364 +0.05,6000, 0.7443471521543986,7675.513675, 2103.741374999999,2487.608183 +0.05,6000, 0.8187818673698384, 11181.158450000074, 3080.5632249999994,2736.369001 +0.05,6000, 0.8932165825852783, 15767.370700000045,4411.23985, 2985.1298189999998 +0.05,6000, 0.9676512978007181, 21640.416925000085, 6158.170575000004,3233.890637 +0.05,9000,0, 459.3452300603909, 459.3452300603909,0 +0.05,9000, 0.43700025807899456,-1627.5458,-281.5152, 1460.4548624999998 +0.05,9000, 0.5098336344254937, 358.4681999999958, 213.74320000000057, 1703.8640062499999 +0.05,9000, 0.5826670107719928, 2344.4798999999875,709.0022, 1947.2731499999998 +0.05,9000, 0.6555003871184918, 4330.492300000013, 1204.261499999999, 2190.6822937499996 +0.05,9000, 0.7283337634649909, 6540.991300000003, 1796.9236000000142, 2434.0914374999998 +0.05,9000, 0.8011671398114901, 9705.082500000013, 2638.345000000017,2677.500581 +0.05,9000, 0.8740005161579891, 13670.451900000027, 3784.247499999996, 2920.9097249999995 +0.05,9000, 0.9468338925044882, 18768.78350000001, 5284.293699999993, 3164.3188687499996 +0.05,12000,0, 413.25468693747047, 413.25468693747047,0 +0.05,12000, 0.4273913267504488,-5981.428852,-454.1694736, 1428.3418139999999 +0.05,12000, 0.4986232145421903,-2971.169758, 31.739027200003143, 1666.3987829999999 +0.05,12000, 0.5698551023339318, 39.101646400030575, 517.6516944000109, 1904.4557519999998 +0.05,12000, 0.6410869901256733, 3049.3670704000197, 1003.5658071999916,2142.512721 +0.05,12000, 0.7123188779174147, 6215.422945600052, 1593.535885600008,2380.56969 +0.05,12000,0.783550766, 9242.336699199815, 2316.0362791999564, 2618.6266589999996 +0.05,12000, 0.8547826535008975, 10783.706455199672, 3081.601726399949, 2856.6836279999998 +0.05,12000, 0.9260145412926392, 16227.539562400005, 4497.384066399855,3094.740597 +0.05,12000, 0.9972464290843805, 21278.34475199975, 6067.844866399971, 3332.7975659999997 +0.05,15000,0, 370.89633687515106, 370.89633687515106,0 +0.05,15000, 0.4177832935368042,-3422.1305,-736.5147, 1396.2317669999998 +0.05,15000, 0.48741384245960495,-1572.3614,-249.6188, 1628.9370614999998 +0.05,15000, 0.5570443913824057, 277.45209999977146, 237.2890999999638, 1861.6423559999998 +0.05,15000, 0.6266749403052064, 2127.2500999998797, 724.1849999999652,2094.347651 +0.05,15000, 0.6963054892280072, 3919.874699999812, 993.1869999997302,2327.052945 +0.05,15000, 0.7659360381508079, 8107.049899999965, 2006.6136999996747,2559.75824 +0.05,15000, 0.8355665870736084, 8295.775200000013, 2489.490100000111, 2792.4635339999995 +0.05,15000, 0.9051971359964092, 18916.62290000105, 4803.553300000074, 3025.1688284999996 +0.05,15000, 0.9748276849192099,5936.3338, 3539.5044999998445, 3257.8741229999996 +0.05,18000,0, 332.04401144149176, 332.04401144149176,0 +0.05,18000, 0.4081743622082585,-13675.57478,-2474.182922, 1364.1187184999999 +0.05,18000, 0.4762034225763016,-8945.338914,-1537.782515,1591.471838 +0.05,18000, 0.5442324829443447,-4215.065122,-601.4260288,1818.824958 +0.05,18000, 0.6122615433123877, 515.2119175997411, 334.93951039966885, 2046.1780777499998 +0.05,18000, 0.6802906036804308, 2286.805031199906, 893.9298304000711,2273.531198 +0.05,18000, 0.7483196640484739, 3918.8857048007403,1174.021464,2500.884317 +0.05,18000,0.816348724, 7981.962458399246, 1803.377673599487, 2728.2374369999998 +0.05,18000, 0.8843777847845601, 6270.0137423994165, 2149.1522480003446,2955.590557 +0.05,18000, 0.9524068451526032,25369.33325,5247.756162,3182.943677 +0.05,21000,0, 296.47838138566897, 296.47838138566897,0 +0.05,21000,0.398566329, 2763.0429736000383, 2319.5498488000057,1332.008672 +0.05,21000, 0.46499405049371634, 2979.9080608000777, 1901.5675495999965,1554.010117 +0.05,21000, 0.5314217719928186, 3196.8131311999755, 1483.5943032000205,1776.011562 +0.05,21000,0.597849493, 3413.691863200385, 1065.5872743999143, 1998.0130072499999 +0.05,21000, 0.6642772149910233, 3661.6466888002374, 912.1589208000045,2220.014453 +0.05,21000, 0.7307049364901257, 1190.716444801279, 855.5184744001613,2442.015898 +0.05,21000,0.797132658, 5622.828899200619, 1504.0795919994812,2664.017343 +0.05,21000, 0.8635603794883303, 10217.832863197733, 3505.378684800498,2886.018788 +0.05,21000, 0.9299881009874327, 12690.255665598383,4869.682104,3108.020234 +0.05,21000, 0.9964158224865349, 20717.669268000252, 9070.129177600902,3330.021679 +0.05,24000,0, 263.9917308599757, 263.9917308599757,0 +0.05,24000, 0.3889573976660682,-2747.962127,-3334.670248,1299.895623 +0.05,24000, 0.4537836306104128,-1687.356541,-2335.157098, 1516.5448934999997 +0.05,24000, 0.5186098635547576,-626.7097768,-1335.655158, 1733.1941639999998 +0.05,24000, 0.5834360964991023, 433.87318719989594,-336.1574312, 1949.8434344999998 +0.05,24000,0.648262329, 3143.9980152003727, 952.8473424003423, 2166.4927049999997 +0.05,24000, 0.7130885623877916, 6284.657012000669, 2004.5825584004442, 2383.1419754999997 +0.05,24000, 0.7779147953321364, 7322.359334403292, 2223.9269887989576,2599.791246 +0.05,24000, 0.8427410282764811,9905.923789, 2188.0958360004597,2816.440517 +0.05,24000, 0.9075672612208256, 8487.754812803025, 2430.261232001468, 3033.0897869999994 +0.05,24000, 0.9723934941651704, 10105.103932006055, 3585.9838056030603, 3249.7390574999995 +0.05,27000,0, 234.38277344848157, 234.38277344848157,0 +0.05,27000, 0.3793493644524237, 22931.447128800115, 11532.861036000008,1267.785576 +0.05,27000, 0.44257425852782767, 16521.53009840016, 8669.762336800008,1479.083172 +0.05,27000, 0.5057991526032316, 10111.520655999933,5806.602272,1690.380768 +0.05,27000, 0.5690240466786355, 3701.5320287993823, 2943.4422071996933, 1901.6783639999999 +0.05,27000, 0.6322489407540395,-2626.56235,-141.315832, 2112.9759599999998 +0.05,27000, 0.6954738348294435, 3350.7104024006403, 356.18118719919494,2324.273556 +0.05,27000, 0.7586987289048474, 3285.400167202547, 427.32905599995183,2535.571152 +0.05,27000, 0.8219236229802513, 1028.7607800030892, 2045.9029448004476,2746.868748 +0.05,27000, 0.8851485170556553, 10204.392964805276, 2577.580525602925,2958.166344 +0.05,27000, 0.9483734111310592,1146.704654, 3424.544991202748,3169.46394 +0.05,30000,0, 207.46141767148293, 207.46141767148293,0 +0.05,30000, 0.3697404331238779,-109.3373,1478.2505,1235.672528 +0.05,30000, 0.4313638386445242, 1570.1974999998001, 1424.7061999998389, 1441.6179487499999 +0.05,30000, 0.49298724416517054,3249.1904, 1371.3333999996703, 1647.5633699999998 +0.05,30000, 0.5546106496858169, 4928.461400000473, 1317.8605000000866, 1853.5087912499998 +0.05,30000, 0.6162340552064631, 4116.789099999579, 266.26629999940724,2059.454213 +0.05,30000, 0.6778574607271095,-612.2555, 406.93060000118476,2265.399634 +0.05,30000, 0.7394808662477558, 1491.7724999983147,-206.1382,2471.345055 +0.05,30000,0.801104272, 3295.7065999993756,-1231.1935, 2677.2904762499998 +0.05,30000, 0.8627276772890484, 12370.150599998626, 5613.435199999098, 2883.2358974999997 +0.05,30000, 0.9243510828096947, 24896.868800007083, 4169.043399994513, 3089.1813187499997 +0.05,30000, 0.9859744883303411, 49261.19940000991, 10598.273799987335, 3295.1267399999997 +0.05,33000,0, 183.04255227548572, 183.04255227548572,0 +0.05,33000, 0.3601323999102334, 57217.343818399924, 6462.072042399937,1203.562481 +0.05,33000, 0.42015446656193894, 44718.897576799376, 4942.357114400042,1404.156227 +0.05,33000, 0.48017653321364456, 32220.345998398952, 3422.6348784002153,1604.749974 +0.05,33000, 0.5401985998653501, 19721.768598399525, 1903.0035631998846,1805.343721 +0.05,33000, 0.6002206665170557, 7223.1322471996955, 383.1977143994138, 2005.9374675000001 +0.05,33000, 0.6602427331687613,-1714.224942,-318.2439112,2206.531214 +0.05,33000, 0.7202647998204668,9696.970218, 3766.076648799335,2407.124961 +0.05,33000, 0.7802868664721724, 8800.633575201666, 3135.405660000881, 2607.7187077500002 +0.05,33000, 0.8403089331238779,-3143.182866,-2751.989866,2808.312455 +0.05,33000, 0.9003309997755836, 3650.193898396974, 1749.952720797708, 3008.9062012500003 +0.05,33000, 0.9603530664272891,-41981.76681,-27546.71862,3209.499948 +0.05,36000,0, 160.95228865653291, 160.95228865653291,0 +0.05,36000, 0.3505234685816876, 54083.27970000006, 4792.784600000039,1171.449432 +0.05,36000, 0.40894404667863554, 42879.20929999936, 3942.496200000078,1366.691004 +0.05,36000, 0.46736462477558344,31674.8618, 3092.207800000253,1561.932576 +0.05,36000, 0.5257852028725314, 20470.73539999975, 2241.9479999997834, 1757.1741479999998 +0.05,36000, 0.5842057809694794, 9266.508899999362, 1391.5672999995181,1952.41572 +0.05,36000, 0.6426263590664273, 1420.9881999994286, 498.8894000005236,2147.657292 +0.05,36000, 0.7010469371633752, 1098.6751000008371, 214.43559999949366,2342.898864 +0.05,36000, 0.7594675152603231,-16849.8408,-2203.4709, 2538.1404359999997 +0.05,36000, 0.8178880933572711, 38222.791599989054, 8790.296900003581,2733.382008 +0.05,36000,0.876308671, 13946.345999998986, 4859.685299998545,2928.62358 +0.05,36000, 0.9347292495511669,-18581.3635,-18345.4445,3123.865152 +0.05,39000,0, 139.3968451913803, 139.3968451913803,0 +0.05,39000,0.350237868,297.7573, 18.414899999952333, 1170.4949550000001 +0.05,39000, 0.4086108460502693,-246.1483,-51.464,1365.577448 +0.05,39000, 0.46698382405745065,-790.2804,-121.3351,1560.65994 +0.05,39000,0.525356802,-1334.2551,-191.1425,1755.742433 +0.05,39000, 0.5837297800718133,-1878.3663,-260.985,1950.824925 +0.05,39000, 0.6421027580789946,-3177.828,-503.2265,2145.907418 +0.05,39000,0.700475736, 147.0693999971736, 104.10470000056785, 2340.9899100000002 +0.05,39000, 0.7588487140933573,-3416.9648,-1402.6943,2536.072403 +0.05,39000, 0.8172216921005386, 6216.859300000682,-3200.3318,2731.154895 +0.05,39000, 0.8755946701077199, 10314.047300004764, 3770.8095000044123,2926.237388 +0.05,39000, 0.9339676481149013, 95822.42960000428, 54546.04500000883,3121.31988 +0.05,42000,0, 120.67904739736119, 120.67904739736119,0 +0.05,42000,0.350237868,-379307.7606,-145962.8777, 1170.4949550000001 +0.05,42000, 0.4086108460502693,-297621.6838,-114274.1156,1365.577448 +0.05,42000, 0.46698382405745065,-215935.6775,-82585.31414,1560.65994 +0.05,42000,0.525356802,-134249.7806,-50896.46209,1755.742433 +0.05,42000, 0.5837297800718133,-52563.78405,-19207.79139,1950.824925 +0.05,42000, 0.6421027580789946,-14077.32979,-4743.836325,2145.907418 +0.05,42000,0.700475736, 7763.2552124993745, 869.3884437504009, 2340.9899100000002 +0.05,42000, 0.7588487140933573,-9094.635569,-55.98125,2536.072403 +0.05,42000, 0.8172216921005386, 20796.75561250199, 11430.454387500024,2731.154895 +0.05,42000, 0.8755946701077199,-8526.098525,-3736.200025,2926.237388 +0.05,42000, 0.9339676481149013, 16729.975118757982, 12533.790800006158,3121.31988 +0.1,0,0, 625.2082401190163, 625.2082401190163,0 +0.1,0, 0.46652364452423695,-2011.8834,-99.3087, 1559.1220199999998 +0.1,0, 0.5442775852782764, 630.3653000000087,552.14, 1818.9756899999998 +0.1,0, 0.6220315260323159, 3272.6143000000093, 1203.5886999999977, 2078.8293599999997 +0.1,0, 0.6997854667863553,6125.4189, 1899.5097999999746, 2338.6830299999997 +0.1,0, 0.7775394075403949,9521.6475, 2845.689899999991, 2598.5366999999997 +0.1,0, 0.8552933482944344,13855.2959,4165.0054, 2858.3903699999996 +0.1,0, 0.9330472890484739, 19628.417999999874, 5975.702099999982, 3118.2440399999996 +0.1,3000,0, 566.2082978816558, 566.2082978816558,0 +0.1,3000, 0.45690120646319565,-2313.858908,-177.0174796,1526.963832 +0.1,3000, 0.5330514075403949, 193.16308879568584, 421.9886124946206,1781.457804 +0.1,3000, 0.6092016086175942, 2700.1851220770013, 1020.9947294587513, 2035.9517759999999 +0.1,3000, 0.6853518096947936, 5250.776911976781, 1639.6440126681327,2290.445748 +0.1,3000, 0.7615020107719928, 8308.462378657994, 2467.4811311975077,2544.93972 +0.1,3000,0.837652212, 12111.905933439019, 3595.1033628732494, 2799.4336919999996 +0.1,3000, 0.9138024129263913, 17311.674484508192, 5179.058747362689,3053.927664 +0.1,3000, 0.9899526140035907, 23690.67883839665, 7160.928613317563,3308.421636 +0.1,6000,0, 511.6951552602684, 511.6951552602684,0 +0.1,6000, 0.44727786894075405,-2534.2515,-256.5705, 1494.8026380000001 +0.1,6000, 0.5218241804308797,-211.1178, 297.40659999999843, 1743.9364110000001 +0.1,6000, 0.5963704919210054, 2112.016099999982, 851.3837999999968, 1993.0701840000002 +0.1,6000, 0.6709168034111311, 4435.149400000046, 1405.3610000000385,2242.203957 +0.1,6000, 0.7454631149012568, 7123.782200000019, 2122.0649000000017,2491.33773 +0.1,6000, 0.8200094263913825, 10496.662100000101, 3109.141799999993,2740.471503 +0.1,6000, 0.8945557378815081, 14965.501000000098, 4455.733900000038, 2989.6052760000002 +0.1,6000, 0.9691020493716338, 20653.14060000009, 6216.630900000005, 3238.7390490000003 +0.1,9000,0, 461.4143496154138, 461.4143496154138,0 +0.1,9000, 0.4376554308797127,-2541.0796,-310.5673, 1462.6444499999998 +0.1,9000, 0.5105980026929982,-442.1006, 195.12520000000004, 1706.4185249999998 +0.1,9000, 0.5835405745062836, 1656.8783999999987, 700.8176999999998, 1950.1925999999999 +0.1,9000,0.656483146, 3755.8574000000044, 1206.5102999999988, 2193.9666749999997 +0.1,9000, 0.7294257181328545, 6110.102999999994, 1819.8495000000003,2437.74075 +0.1,9000,0.80236829, 9037.512700000003, 2663.9382000000014, 2681.5148249999997 +0.1,9000, 0.8753108617594254, 12865.362299999997, 3816.2123999999976, 2925.2888999999996 +0.1,9000, 0.9482534335727109,17810.1504, 5327.397900000005,3169.062975 +0.1,12000,0, 415.11619174472565, 415.11619174472565,0 +0.1,12000, 0.4280320933572711,-3536.912952,-348.3532856,1430.483256 +0.1,12000, 0.4993707755834829,-1373.46869, 108.10603120000133, 1668.8971319999998 +0.1,12000, 0.5707094578096947, 789.9805144000145, 564.5670224000042,1907.311008 +0.1,12000, 0.6420481400359066, 2953.4273184000126, 1021.0286311999994, 2145.7248839999997 +0.1,12000, 0.7133868222621185, 5376.871477600019, 1566.419477600006,2384.13876 +0.1,12000, 0.7847255044883303, 8124.962063199958, 2295.050403199987,2622.552636 +0.1,12000, 0.8560641867145422, 10739.448999199909,3200.652214,2860.966512 +0.1,12000, 0.9274028689407541, 15355.029330400024, 4528.343394399963,3099.380388 +0.1,12000, 0.9987415511669658, 20015.49159199992, 6050.922054400002, 3337.7942639999997 +0.1,15000,0, 372.56703858988044, 372.56703858988044,0 +0.1,15000, 0.4184096552962298,-2899.1604,-571.0417,1398.325068 +0.1,15000, 0.48814459784560144,-1193.4852,-116.4393,1631.379246 +0.1,15000, 0.5578795403949731, 512.2158999998668, 338.17009999997555,1864.433424 +0.1,15000, 0.6276144829443447, 2217.9079999999267, 792.7724999999884,2097.487602 +0.1,15000, 0.6973494254937164, 3920.2631999998775, 1137.1745999998623,2330.54178 +0.1,15000, 0.7670843680430879, 7199.866299999964, 1975.6096999998085,2563.595958 +0.1,15000, 0.8368193105924596, 8379.474099999994, 2608.4565000000475,2796.650136 +0.1,15000, 0.9065542531418312, 16168.369900000678, 4441.337700000001,3029.704314 +0.1,15000, 0.9762891956912029, 10308.451100000098, 4306.532599999886,3262.758492 +0.1,18000,0, 333.53970294374477, 333.53970294374477,0 +0.1,18000, 0.4087863177737881,-9788.776233,-1769.354986, 1366.1638739999999 +0.1,18000, 0.47691737073608614,-6203.25903,-1020.903847,1593.857853 +0.1,18000, 0.5450484236983841,-2617.717026,-272.4812768, 1821.5518319999999 +0.1,18000, 0.6131794766606822, 967.8267135998315, 475.94739439978537,2049.245811 +0.1,18000, 0.6813105296229802, 2611.2808031999007, 978.0446944000453,2276.93979 +0.1,18000, 0.7494415825852783, 4255.159712800536, 1348.6968440001574,2504.633769 +0.1,18000, 0.8175726355475762, 7612.584242399513, 1985.0263095996686, 2732.3277479999997 +0.1,18000, 0.8857036885098742,7486.397506, 2532.255948000171,2960.021727 +0.1,18000, 0.9538347414721723, 21206.83883200227, 4972.578097599593,3187.715706 +0.1,21000,0, 297.8138675873782, 297.8138675873782,0 +0.1,21000, 0.39916387971274686, 927.9313496000241, 1411.7156568000032,1334.005686 +0.1,21000, 0.4656911929982047, 1530.8667488000458, 1246.3805455999952, 1556.3399670000001 +0.1,21000, 0.5322185062836625,2133.829503, 1081.0515352000098,1778.674248 +0.1,21000, 0.5987458195691203, 2736.7746752002636, 915.6991383999566,2001.008529 +0.1,21000, 0.6652731328545781, 3334.3694368001447, 922.0845887999857,2223.34281 +0.1,21000, 0.7318004461400359, 2118.5667728008425, 1028.2248384000904,2445.677091 +0.1,21000, 0.7983277594254937, 5682.667971200344, 1652.3594519996477,2668.011372 +0.1,21000, 0.8648550727109515, 9678.700175198457, 3284.279992800378,2890.345653 +0.1,21000, 0.9313823859964094, 12027.24358159884, 4472.147044000036, 3112.6799340000002 +0.1,21000, 0.9979096992818672, 17995.243828000264, 7578.1478936005715,3335.014215 +0.1,24000,0, 265.18088101750504, 265.18088101750504,0 +0.1,24000, 0.38954054219030526,-3017.821735,-2577.092508, 1301.8444920000002 +0.1,24000, 0.4544639658886894,-1841.305013,-1756.177722, 1518.8185740000001 +0.1,24000, 0.5193873895870736,-664.7590688,-935.2707144,1735.792656 +0.1,24000, 0.5843108132854579, 511.7418951999231,-114.3670392,1952.766738 +0.1,24000,0.649234237, 2811.075483200248, 898.2858784002192,2169.74082 +0.1,24000, 0.7141576606822263, 5487.854352000431, 1772.8944544002939,2386.714902 +0.1,24000, 0.7790810843806105, 6695.0670304022915, 2076.138700799292, 2603.6889840000003 +0.1,24000, 0.8440045080789946,9078.895441, 2232.9741560003217,2820.663066 +0.1,24000, 0.9089279317773789, 8740.784044802118, 2643.1322520010326, 3037.6371480000003 +0.1,24000,0.973851355, 10632.689832004275, 3783.039529602125,3254.61123 +0.1,27000,0, 235.43855012398765, 235.43855012398765,0 +0.1,27000, 0.3799181041292639, 15827.530820800092, 8247.896836000007,1269.686304 +0.1,27000, 0.4432377881508079, 11485.00185440013, 6244.882188800003,1481.300688 +0.1,27000, 0.5065574721723519, 7142.404875999978, 4241.821951999971,1692.915072 +0.1,27000, 0.5698771561938959, 2799.823420799544, 2238.761715199774,1904.529456 +0.1,27000, 0.6331968402154399,-1446.007174, 89.49722800007748,2116.14384 +0.1,27000, 0.6965165242369838, 3193.342578400463, 525.5966151994144,2327.758224 +0.1,27000, 0.7598362082585278, 3581.758115201774, 714.2247359999725,2539.372608 +0.1,27000, 0.8231558922800718, 2379.170800002188, 2047.1357968003167,2750.986992 +0.1,27000, 0.8864755763016158,9673.633797, 2621.606589602129,2962.601376 +0.1,27000, 0.9497952603231598, 3357.267337598957, 3398.0692592020064,3174.21576 +0.1,30000,0, 208.39592716047972, 208.39592716047972,0 +0.1,30000, 0.37029476660682226,-571.8782, 987.1350999999564,1237.52511 +0.1,30000, 0.43201056104129265, 906.9155999998543, 1013.5340999998823,1443.779295 +0.1,30000, 0.49372635547576305,2385.2968, 1040.0629999997593,1650.03348 +0.1,30000, 0.5554421499102334, 3863.889300000365, 1066.5159000000576,1856.287665 +0.1,30000, 0.6171579443447038, 3474.2748999996747, 344.3792999995592,2062.54185 +0.1,30000, 0.6788737387791742, 18.95260000160397,493.2913, 2268.7960350000003 +0.1,30000, 0.7405895332136445, 1969.5103999987045, 132.61349999998208,2475.05022 +0.1,30000, 0.8023053276481149, 3700.863899999357,-519.5609,2681.304405 +0.1,30000, 0.8640211220825853,10959.7523, 4812.414299999331,2887.55859 +0.1,30000, 0.9257369165170558, 21054.53140000521, 3993.446599995782, 3093.8127750000003 +0.1,30000, 0.9874527109515261, 40095.13330000725, 9195.802199990372,3300.06696 +0.1,33000,0, 183.86706704026236, 183.86706704026236,0 +0.1,33000, 0.36067232854578096, 43687.42464639996, 4856.1138903999545,1205.366922 +0.1,33000, 0.4207843833034111, 34207.31479279952, 3738.626262400031,1406.261409 +0.1,33000, 0.48089643806104126, 24727.12258639917, 2621.132486400157,1607.155896 +0.1,33000, 0.5410084928186715, 15246.910706399654,1503.708967,1808.050383 +0.1,33000, 0.6011205475763016, 5766.653331199744, 386.15108239957067,2008.94487 +0.1,33000, 0.6612326023339318,-903.5494536,-79.4511352,2209.839357 +0.1,33000, 0.7213446570915619, 8126.707469599733, 3135.3974647995365,2410.733844 +0.1,33000, 0.7814567118491921, 7733.798859201299, 2735.111420000656,2611.628331 +0.1,33000, 0.8415687666068222,-1066.133674,-1643.251278,2812.522818 +0.1,33000, 0.9016808213644524, 4131.562286397973, 1761.128736798335,3013.417305 +0.1,33000, 0.9617928761220825,-31625.24698,-21203.41129,3214.311792 +0.1,36000,0, 161.6772978785534, 161.6772978785534,0 +0.1,36000, 0.3510489910233393, 41090.522300000055, 3556.3316000000327,1173.205728 +0.1,36000, 0.4095571561938959, 32625.619599999514, 2950.6852000000613,1368.740016 +0.1,36000, 0.46806532136445245, 24160.50249999836, 2345.0388000001926,1564.274304 +0.1,36000,0.526573487, 15695.556899999803, 1739.4143999998284,1759.808592 +0.1,36000, 0.5850816517055656, 7230.533299999508, 1133.6965999996314, 1955.3428800000002 +0.1,36000,0.643589817, 1364.1155999995503,494.6161,2150.877168 +0.1,36000, 0.7020979820466786, 1268.3249000006144, 324.23969999956853,2346.411456 +0.1,36000, 0.7606061472172352,-12394.2989,-1466.3963,2541.945744 +0.1,36000, 0.8191143123877918, 30619.60469999179, 7126.412500002727,2737.480032 +0.1,36000, 0.8776224775583483, 12129.063899999252, 4292.991999998852,2933.01432 +0.1,36000, 0.9361306427289049,-13311.9698,-13772.9272,3128.548608 +0.1,39000,0, 140.0247579668238, 140.0247579668238,0 +0.1,39000, 0.3507629622980251, 92.95119999989765,-57.5174,1172.24982 +0.1,39000, 0.40922345601436266,-270.2002,-79.7978,1367.62479 +0.1,39000, 0.4676839497307002,-633.5255,-102.0716, 1562.9997600000002 +0.1,39000, 0.5261444434470378,-996.7287,-124.296, 1758.3747300000002 +0.1,39000, 0.5846049371633754,-1360.0385,-146.5478, 1953.7497000000003 +0.1,39000, 0.6430654308797128,-2307.8725,-315.0536,2149.12467 +0.1,39000, 0.7015259245960502, 446.4423999978226,207.3932,2344.49964 +0.1,39000, 0.7599864183123879,-2130.3116,-884.7198, 2539.8746100000003 +0.1,39000, 0.8184469120287253, 5624.611300000615,-2225.9598,2735.24958 +0.1,39000,0.876907406, 8977.310800003586, 3289.4589000034102, 2930.6245500000005 +0.1,39000, 0.9353678994614004,75013.8125, 42558.82880000677, 3125.9995200000003 +0.1,42000,0, 121.22264589476711, 121.22264589476711,0 +0.1,42000, 0.3507629622980251,-306857.2146,-118020.5097,1172.24982 +0.1,42000, 0.40922345601436266,-240760.6761,-92393.28338,1367.62479 +0.1,42000, 0.4676839497307002,-174664.1927,-66766.02593, 1562.9997600000002 +0.1,42000, 0.5261444434470378,-108567.7979,-41138.72771, 1758.3747300000002 +0.1,42000, 0.5846049371633754,-42471.32287,-15511.57448, 1953.7497000000003 +0.1,42000, 0.6430654308797128,-11125.21901,-3727.20745,2149.12467 +0.1,42000, 0.7015259245960502, 6419.422362499474, 806.7819562503171,2344.49964 +0.1,42000, 0.7599864183123879,-6860.386856, 91.40070000099331, 2539.8746100000003 +0.1,42000, 0.8184469120287253, 17132.477837501516, 9318.980712500015,2735.24958 +0.1,42000,0.876907406,-5909.965075,-2619.3185, 2930.6245500000005 +0.1,42000, 0.9353678994614004, 14914.661481256073, 10745.344975004875, 3125.9995200000003 + 0.15000000000000002,0,0, 629.8996281297979, 629.8996281297979,0 + 0.15000000000000002,0, 0.4676876256732495,-1595.5012,-74.0941,1563.012045 + 0.15000000000000002,0, 0.5456355632854578, 705.9526000000034, 574.9103999999979,1823.514053 + 0.15000000000000002,0,0.623583501, 3007.406500000004, 1223.9147999999923,2084.01606 + 0.15000000000000002,0, 0.7015314385098743, 5609.046899999981, 1922.9932999999915,2344.518068 + 0.15000000000000002,0, 0.7794793761220825, 8876.089799999943, 2883.797399999987,2605.020075 + 0.15000000000000002,0, 0.8574273137342907, 13067.203099999975,4221.3491, 2865.5220824999997 + 0.15000000000000002,0,0.935375251, 18695.761699999897, 6062.876999999946,3126.02409 + 0.15000000000000002,3000,0, 570.4569668047991, 570.4569668047991,0 + 0.15000000000000002,3000, 0.4580411795332136,-2181.347289,-165.7745183,1530.773622 + 0.15000000000000002,3000, 0.5343813761220826, 124.06477920695296, 435.77105681481623, 1785.9025589999999 + 0.15000000000000002,3000, 0.6107215727109515, 2429.4768844882688, 1037.3165467991184, 2041.0314959999998 + 0.15000000000000002,3000, 0.6870617692998204,4789.782167, 1661.2813600811971,2296.160433 + 0.15000000000000002,3000, 0.7634019658886894, 7712.867227276924, 2500.2356125440488,2551.28937 + 0.15000000000000002,3000, 0.8397421624775583, 11398.747732624584, 3645.975555671739,2806.418307 + 0.15000000000000002,3000, 0.9160823590664272, 16460.686836097182, 5252.5780265567855,3061.547244 + 0.15000000000000002,3000, 0.9924225556552961, 22616.30261168905, 7246.400828948473,3316.676181 + 0.15000000000000002,6000,0, 515.5347727869121, 515.5347727869121,0 + 0.15000000000000002,6000, 0.44839383168761227,-2318.2634,-239.7174, 1498.5321855000002 + 0.15000000000000002,6000,0.523126137,-200.2143, 314.3302000000002, 1748.2875497500002 + 0.15000000000000002,6000, 0.5978584422501496, 1917.8348000000158, 868.3776999999989,1998.042914 + 0.15000000000000002,6000, 0.6725907475314185, 4035.8837999999832, 1422.4252999999953, 2247.7982782500003 + 0.15000000000000002,6000, 0.7473230528126871, 6617.027800000002, 2149.8712999999966,2497.553643 + 0.15000000000000002,6000, 0.8220553580939558, 9875.911099999976, 3152.006099999995,2747.309007 + 0.15000000000000002,6000, 0.8967876633752245, 14248.810499999892, 4521.647499999981, 2997.0643710000004 + 0.15000000000000002,6000, 0.9715199686564931, 19754.517599999926, 6301.743199999965,3246.819735 + 0.15000000000000002,9000,0, 464.87667402012113, 464.87667402012113,0 + 0.15000000000000002,9000, 0.4387473855475763,-2540.3364,-308.1429,1466.293763 + 0.15000000000000002,9000, 0.5118719498055057,-555.764, 201.76619999999988, 1710.6760562499999 + 0.15000000000000002,9000,0.584996514, 1428.808600000002, 711.6751999999983, 1955.0583499999998 + 0.15000000000000002,9000, 0.6581210783213644, 3413.381299999983, 1221.5841999999934, 2199.4406437499997 + 0.15000000000000002,9000, 0.7312456425792937, 5666.968299999971, 1844.6710999999873, 2443.8229374999996 + 0.15000000000000002,9000,0.804370207, 8495.826200000007, 2700.310799999986, 2688.2052312499995 + 0.15000000000000002,9000, 0.8774947710951526, 12251.267599999976, 3875.458299999995,2932.587525 + 0.15000000000000002,9000,0.950619335, 17028.86519999999, 5402.095699999995,3176.969819 + 0.15000000000000002,12000,0, 418.23110770402536, 418.23110770402536,0 + 0.15000000000000002,12000, 0.42910003770197486,-2305.408852,-294.8645576,1434.052326 + 0.15000000000000002,12000,0.500616711,-587.8128816, 150.6742552000002,1673.061047 + 0.15000000000000002,12000, 0.5721333836026331, 1129.7842224000021, 596.2134904000005, 1912.0697679999998 + 0.15000000000000002,12000, 0.6436500565529623, 2847.380806400004, 1041.7528752000007,2151.078489 + 0.15000000000000002,12000, 0.7151667295032913, 4844.310969600002, 1569.321629600002, 2390.0872099999997 + 0.15000000000000002,12000, 0.7866834024536206, 7393.286047199999, 2307.7492471999963,2629.095931 + 0.15000000000000002,12000, 0.8582000754039497, 10501.281363200009, 3290.8157423999987,2868.104652 + 0.15000000000000002,12000, 0.9297167483542788, 14658.189338400009, 4591.318162400003, 3107.1133729999997 + 0.15000000000000002,15000,0, 375.36267758804877, 375.36267758804877,0 + 0.15000000000000002,15000, 0.41945359156193895,-2520.8392,-451.0395,1401.813903 + 0.15000000000000002,15000, 0.48936252348892884,-931.7766,-18.3715,1635.449554 + 0.15000000000000002,15000, 0.5592714554159186, 657.2992999999323, 414.30009999998543,1869.085204 + 0.15000000000000002,15000, 0.6291803873429084, 2246.3705999999597, 846.9680999999999,2102.720855 + 0.15000000000000002,15000, 0.6990893192698981, 3880.9720999999263, 1245.6378999999426, 2336.3565049999997 + 0.15000000000000002,15000, 0.7689982511968881, 6536.210299999967, 1973.7554999999015,2569.992156 + 0.15000000000000002,15000, 0.8389071831238779, 8392.314099999989, 2716.585600000013,2803.627806 + 0.15000000000000002,15000, 0.9088161150508677, 14170.508800000393, 4219.588499999971,3037.263457 + 0.15000000000000002,15000, 0.9787250469778577, 13079.827900000022, 4844.291799999926,3270.899107 + 0.15000000000000002,18000,0, 336.0424917157098, 336.0424917157098,0 + 0.15000000000000002,18000, 0.40980624371633745,-6865.768601,-1234.37221, 1369.5724664999998 + 0.15000000000000002,18000, 0.4781072843357271,-4148.296486,-627.0506592,1597.834544 + 0.15000000000000002,18000, 0.5464083249551166,-1430.80929,-19.7463448, 1826.0966219999998 + 0.15000000000000002,18000, 0.6147093655745062, 1286.6786495998972,587.5618384, 2054.3586997499997 + 0.15000000000000002,18000, 0.6830104061938959, 2829.580855199914, 1049.714018400027,2282.620778 + 0.15000000000000002,18000, 0.7513114468132854,4487.853441, 1490.0790240000913,2510.882855 + 0.15000000000000002,18000, 0.8196124874326749, 7344.145386399712, 2145.268385599801, 2739.1449329999996 + 0.15000000000000002,18000, 0.8879135280520646, 8374.398930399811, 2847.7599480000604, 2967.4070107499997 + 0.15000000000000002,18000, 0.9562145686714542, 18054.61251200129, 4806.923773599721,3195.669089 + 0.15000000000000002,21000,0, 300.04857966919246, 300.04857966919246,0 + 0.15000000000000002,21000, 0.4001597975763016,-395.5991344, 732.6920848000025,1337.334044 + 0.15000000000000002,21000, 0.46685309717235185, 476.13615680002414, 758.0538815999962, 1560.2230507499999 + 0.15000000000000002,21000, 0.5335463967684021, 1347.8891551999695, 783.4195472000034,1783.112058 + 0.15000000000000002,21000, 0.6002396963644524, 2219.6311672001702, 808.7698623999845,2006.001065 + 0.15000000000000002,21000, 0.6669329959605027, 3067.974004800082, 938.1528767999782,2228.890073 + 0.15000000000000002,21000, 0.7336262955565529, 2816.9554208005247, 1172.638062400046, 2451.7790797499997 + 0.15000000000000002,21000, 0.8003195951526032, 5736.527123200167, 1786.3473119997775,2674.668087 + 0.15000000000000002,21000, 0.8670128947486535, 9241.062667199014, 3136.890520800275,2897.557094 + 0.15000000000000002,21000, 0.9337061943447037, 11521.471537599215, 4207.990584000048, 3120.4461014999997 + 0.15000000000000002,24000,0, 267.17072428261804, 267.17072428261804,0 + 0.15000000000000002,24000, 0.3905124497307002,-3119.500023,-1959.313268,1305.092607 + 0.15000000000000002,24000, 0.4555978580191502,-1883.091705,-1283.052486,1522.608042 + 0.15000000000000002,24000, 0.5206832663076002,-646.6635808,-606.7968304,1740.123476 + 0.15000000000000002,24000, 0.5857686745960503, 589.7342831999448, 69.45627280013055,1957.638911 + 0.15000000000000002,24000, 0.6508540828845003, 2543.7516312001544, 862.8719744001287,2175.154345 + 0.15000000000000002,24000, 0.7159394911729503, 4841.347192000255, 1597.8297104001808,2392.66978 + 0.15000000000000002,24000, 0.7810248994614004, 6188.723186401513, 1972.5562327995472,2610.185214 + 0.15000000000000002,24000, 0.8461103077498504, 8417.353212799979, 2287.3539760002122,2827.700649 + 0.15000000000000002,24000, 0.9111957160383004, 8916.145896801427, 2834.144372000686,3045.216083 + 0.15000000000000002,24000, 0.9762811243267504, 10974.383932002864, 3947.958193601398,3262.731518 + 0.15000000000000002,27000,0, 237.20521524522326, 237.20521524522326,0 + 0.15000000000000002,27000, 0.3808660035906642, 10189.283932800066, 5619.152736000004, 1272.8541839999998 + 0.15000000000000002,27000, 0.4443436708557749, 7489.483670400098, 4305.916960800002, 1484.9965479999998 + 0.15000000000000002,27000, 0.5078213381208857, 4789.635096000009, 2992.6484319999795,1697.138912 + 0.15000000000000002,27000, 0.5712990053859964, 2089.7977327996723, 1679.379903199837,1909.281276 + 0.15000000000000002,27000, 0.6347766726511072,-510.8828376, 276.4482880000653,2121.42364 + 0.15000000000000002,27000, 0.6982543399162178,3060.008614,669.0206232,2333.566004 + 0.15000000000000002,27000, 0.7617320071813284, 3805.4205432011745,952.091116, 2545.7083679999996 + 0.15000000000000002,27000, 0.8252096744464392, 3453.048220001474, 2059.674868800212,2757.850732 + 0.15000000000000002,27000, 0.8886873417115498, 9214.581448802797, 2672.258393601492, 2969.9930959999997 + 0.15000000000000002,27000, 0.9521650089766607, 5125.501961599364, 3407.1268072014045,3182.13546 + 0.15000000000000002,30000,0, 209.95967199210608, 209.95967199210608,0 + 0.15000000000000002,30000, 0.3712186557450628,-967.3588, 582.3463999999688, 1240.6127474999998 + 0.15000000000000002,30000, 0.4330884317025733, 347.2769999998956, 675.5304999999167,1447.381539 + 0.15000000000000002,30000, 0.49495820766008375, 1661.6072000001973, 768.8101999998297,1654.15033 + 0.15000000000000002,30000, 0.5568279836175942, 2976.093500000273, 862.0338000000352,1860.919121 + 0.15000000000000002,30000, 0.6186977595751048, 2931.8843999997534, 410.82999999968274,2067.687913 + 0.15000000000000002,30000, 0.6805675355326152, 545.8852000011739, 572.7082000006617,2274.456704 + 0.15000000000000002,30000, 0.7424373114901256, 2359.7099999990287, 420.6579999999891, 2481.2254949999997 + 0.15000000000000002,30000,0.804307087, 4032.8177999993854, 78.49129999950446, 2687.9942862499997 + 0.15000000000000002,30000, 0.8661768634051465, 9792.300499999297, 4164.313899999511,2894.763078 + 0.15000000000000002,30000, 0.9280466393626571,17824.3484,3841.9453,3101.531869 + 0.15000000000000002,30000, 0.9899164153201675,32416.9565, 8003.051599992887,3308.30066 + 0.15000000000000002,33000,0, 185.24675415655173, 185.24675415655173,0 + 0.15000000000000002,33000, 0.36157220960502695, 32364.60071439996, 3512.6477783999653,1208.374325 + 0.15000000000000002,33000, 0.4218342445391981, 25411.04958879962,2732.77825,1409.770045 + 0.15000000000000002,33000, 0.48209627947336925, 18457.435514399338, 1952.9036344001117,1611.165766 + 0.15000000000000002,33000, 0.5423583144075405, 11503.806854399732, 1173.0819911999308,1812.561487 + 0.15000000000000002,33000, 0.6026203493417116, 4550.143935199789, 393.15949039969667,2013.957208 + 0.15000000000000002,33000, 0.6628823842758828,-232.5511256, 122.14862080008288, 2215.3529282500003 + 0.15000000000000002,33000, 0.7231444192100539, 6810.178681599793, 2613.892160799697,2416.748649 + 0.15000000000000002,33000, 0.7834064541442249, 6838.791363200984, 2410.756280000477,2618.14437 + 0.15000000000000002,33000, 0.8436684890783962, 651.0772775957994,-712.2164496,2819.540091 + 0.15000000000000002,33000, 0.9039305240125675, 4571.670514398742, 1813.7719327988307, 3020.9358112500004 + 0.15000000000000002,33000, 0.9641925589467385,-22795.10911,-15770.3252,3222.331532 + 0.15000000000000002,36000,0, 162.89047916474146, 162.89047916474146,0 + 0.15000000000000002,36000, 0.35192486175942544, 30245.169900000037, 2522.2821000000245, 1176.1328879999999 + 0.15000000000000002,36000, 0.4105790053859964, 24067.410899999617, 2122.294500000045, 1372.1550359999999 + 0.15000000000000002,36000, 0.4692331490125673, 17889.489999998736, 1722.3069000001415,1568.177184 + 0.15000000000000002,36000, 0.5278872926391383, 11711.698999999831, 1322.3357999998664,1764.199332 + 0.15000000000000002,36000, 0.5865414362657091, 5533.848599999634, 922.2942999997248,1960.22148 + 0.15000000000000002,36000, 0.6451955798922799, 1317.7994999996508, 496.14320000030364, 2156.2436279999997 + 0.15000000000000002,36000, 0.7038497235188509, 1419.4675000004427, 424.36749999963945, 2352.2657759999997 + 0.15000000000000002,36000, 0.7625038671454218,-8648.1409,-838.9325, 2548.2879239999997 + 0.15000000000000002,36000, 0.8211580107719928, 24245.382599993958,5747.2843, 2744.3100719999998 + 0.15000000000000002,36000, 0.8798121543985636, 10584.679499999496,3815.3163,2940.33222 + 0.15000000000000002,36000, 0.9384662980251346,-8883.05,-9931.0064,3136.354368 + 0.15000000000000002,39000,0, 141.07546464115214, 141.07546464115214,0 + 0.15000000000000002,39000, 0.35163811938958706,-131.4163,-127.506,1175.174595 + 0.15000000000000002,39000, 0.4102444726211849,-331.6345,-108.0463,1371.037028 + 0.15000000000000002,39000, 0.4688508258527828,-531.9828,-88.5811,1566.89946 + 0.15000000000000002,39000, 0.5274571790843806,-732.2386,-69.0785, 1762.7618925000002 + 0.15000000000000002,39000, 0.5860635323159785,-932.5758,-49.5968, 1958.6243250000002 + 0.15000000000000002,39000, 0.6446698855475764,-1573.4118,-151.9089, 2154.4867575000003 + 0.15000000000000002,39000, 0.7032762387791741,702.4008, 300.67320000031214,2350.34919 + 0.15000000000000002,39000,0.761882592,-1039.9346,-443.3423,2546.211623 + 0.15000000000000002,39000, 0.8204889452423698, 5129.540000000539,-1394.9272,2742.074055 + 0.15000000000000002,39000, 0.8790952984739677, 7861.528800002612, 2897.856600002564,2937.936488 + 0.15000000000000002,39000, 0.9377016517055656, 57627.93950000226, 32544.422700005016,3133.79892 + 0.15000000000000002,42000,0, 122.13226677160911, 122.13226677160911,0 + 0.15000000000000002,42000, 0.35163811938958706,-244342.1447,-93916.57838,1175.174595 + 0.15000000000000002,42000, 0.4102444726211849,-191697.7169,-73517.17733,1371.037028 + 0.15000000000000002,42000, 0.4688508258527828,-139053.3312,-53117.75227,1566.89946 + 0.15000000000000002,42000, 0.5274571790843806,-86409.01606,-32718.29487, 1762.7618925000002 + 0.15000000000000002,42000, 0.5860635323159785,-33764.6375,-12318.95132, 1958.6243250000002 + 0.15000000000000002,42000, 0.6446698855475764,-8600.263769,-2854.880975, 2154.4867575000003 + 0.15000000000000002,42000, 0.7032762387791741, 5271.145412499565, 754.2486187502542,2350.34919 + 0.15000000000000002,42000,0.761882592,-4946.085294, 224.80105000077128,2546.211623 + 0.15000000000000002,42000, 0.8204889452423698, 14003.032162501113, 7520.600137500009,2742.074055 + 0.15000000000000002,42000, 0.8790952984739677,-3691.529825,-1665.985375,2937.936488 + 0.15000000000000002,42000, 0.9377016517055656, 13262.191193754406, 9169.165350003794,3133.79892 +0.2,0,0, 636.5069133156856, 636.5069133156856,0 +0.2,0, 0.4693171992818671,-1542.0807,-64.2361, 1568.4580799999999 +0.2,0, 0.5475367324955116, 640.9626000000038, 593.1168999999926, 1829.8677599999999 +0.2,0, 0.6257562657091561, 2824.005899999999, 1250.4697999999769,2091.27744 +0.2,0, 0.7039757989228006, 5274.056199999932, 1959.8085999999817, 2352.6871199999996 +0.2,0, 0.7821953321364452, 8355.228499999828, 2938.650899999966,2614.0968 +0.2,0, 0.8604148653500898,12458.0088, 4302.437499999974,2875.50648 +0.2,0, 0.9386343985637342, 17981.37299999976, 6187.372099999855, 3136.9161599999998 +0.2,3000,0, 576.4407326265805, 576.4407326265805,0 +0.2,3000, 0.4596371418312387,-1929.121419,-149.3436167, 1536.1073279999998 +0.2,3000, 0.5362433321364453, 191.11317695078907, 456.80206959578834,1792.125216 +0.2,3000, 0.6128495224416516, 2311.3476922983014, 1062.947794255317, 2048.1431039999998 +0.2,3000,0.689455713, 4495.356589577711, 1695.1622411824285, 2304.1609919999996 +0.2,3000, 0.7660619030520645, 7260.212017364856, 2547.1789124652673, 2560.1788799999995 +0.2,3000,0.842668093, 10867.078763726378, 3720.4781029514843,2816.196768 +0.2,3000, 0.9192742836624774, 15824.345569312045, 5357.960955607783, 3072.2146559999996 +0.2,3000, 0.9958804739676839, 21722.538066858622, 7363.900334681744, 3328.2325439999995 +0.2,6000,0, 520.9424363493725, 520.9424363493725,0 +0.2,6000, 0.4499561795332137,-2131.915,-225.7292, 1503.7535520000001 +0.2,6000, 0.5249488761220826,-154.4856, 333.12669999999974,1754.379144 +0.2,6000, 0.5999415727109516, 1822.943700000052, 891.9825999999932,2005.004736 +0.2,6000, 0.6749342692998205, 3805.0919999999605, 1453.3734999999926,2255.630328 +0.2,6000, 0.7499269658886895, 6213.947300000026, 2191.1645999999864,2506.25592 +0.2,6000, 0.8249196624775583, 9396.923799999935, 3213.3561999999943,2756.881512 +0.2,6000, 0.8999123590664274, 13711.429699999668, 4618.513199999946, 3007.5071040000003 +0.2,6000, 0.9749050556552963, 19006.339799999892,6419.6392,3258.132696 +0.2,9000,0, 469.7529632324795, 469.7529632324795,0 +0.2,9000, 0.4402761220825853,-2245.9915,-296.7128,1471.4028 +0.2,9000, 0.5136554757630162,-424.355, 217.80809999999943,1716.6366 +0.2,9000, 0.5870348294434471, 1397.281199999999, 732.3289999999951,1961.8704 +0.2,9000,0.660414183, 3218.9176999999613, 1246.8498999999854,2207.1042 +0.2,9000, 0.7337935368043088, 5313.586399999949, 1879.8361999999693,2452.338 +0.2,9000, 0.8071728904847397, 8076.6055000000415, 2752.6081999999706,2697.5718 +0.2,9000, 0.8805522441651706, 11792.00679999996, 3960.0935000000063,2942.8056 +0.2,9000, 0.9539315978456014, 16407.08400000003, 5508.865699999968,3188.0394 +0.2,12000,0, 422.6181117262611, 422.6181117262611,0 +0.2,12000, 0.43059515978456014,-1917.463052,-278.8931896,1439.049024 +0.2,12000, 0.5023610197486534,-366.8472336, 169.3814992000001,1678.890528 +0.2,12000, 0.5741268797127468, 1183.7683704000008, 617.6561984000002,1918.732032 +0.2,12000, 0.6458927396768401, 2734.3841343999993, 1065.9308391999998,2158.573536 +0.2,12000, 0.7176585996409335, 4538.604821600007,1596.336742,2398.41504 +0.2,12000, 0.7894244596050269, 6956.8339511999875, 2348.9991112000002,2638.256544 +0.2,12000, 0.8611903195691203, 10168.983847199988, 3370.5824104000035,2878.098048 +0.2,12000, 0.9329561795332136, 14116.282186399978, 4685.484970399994,3117.939552 +0.2,15000,0, 379.30001640872143, 379.30001640872143,0 +0.2,15000, 0.4209151023339318,-2268.589,-370.2242,1406.698272 +0.2,15000, 0.49106761938958704,-770.5034, 49.94019999999748,1641.147984 +0.2,15000, 0.5612201364452424, 727.5876999999736, 470.1060999999929,1875.597696 +0.2,15000, 0.6313726535008977, 2225.6768999999827, 890.2705000000028,2110.047408 +0.2,15000,0.701525171, 3812.9711999999613, 1327.0541999999837,2344.49712 +0.2,15000, 0.7716776876122082, 6078.449699999975, 1998.1453999999608,2578.946832 +0.2,15000, 0.8418302046678636, 8357.957399999987, 2820.0413999999987,2813.396544 +0.2,15000, 0.9119827217235189, 12805.633300000201, 4119.654899999968, 3047.8462560000003 +0.2,15000, 0.9821352387791741, 14580.073799999982, 5206.180199999959,3282.295968 +0.2,18000,0, 339.5673843782666, 339.5673843782666,0 +0.2,18000, 0.41123414003590664,-4772.187289,-846.5507944,1374.344496 +0.2,18000, 0.47977316337522435,-2684.108582,-339.5095512, 1603.4019119999998 +0.2,18000, 0.5483121867145422,-596.0216144, 167.52236720000874,1832.459328 +0.2,18000,0.61685121, 1492.0655255999425, 674.5565423999328,2061.516744 +0.2,18000, 0.6853902333931777, 2959.0167871999374, 1111.7910024000155,2290.57416 +0.2,18000, 0.7539292567324954, 4634.591288800215, 1605.2660040000465, 2519.6315759999998 +0.2,18000, 0.8224682800718133, 7162.971590399846, 2289.424201599894,2748.688992 +0.2,18000, 0.8910073034111311, 8986.639214399886, 3109.008747999999,2977.746408 +0.2,18000, 0.9595463267504487, 15775.614292000631, 4738.675489599826, 3206.8038239999996 +0.2,21000,0, 303.1959168749328, 303.1959168749328,0 +0.2,21000, 0.4015540825852783,-1286.149678, 250.11953280000162,1341.993744 +0.2,21000,0.468479763,-244.0783152, 413.1808575999969,1565.659368 +0.2,21000, 0.5354054434470378,798.0036872, 576.2444391999999,1789.324992 +0.2,21000, 0.6023311238779174, 1840.0794392001014, 739.2986463999998,2012.990616 +0.2,21000, 0.6692568043087972, 2856.0667928000416,960.3461848, 2236.6562400000003 +0.2,21000, 0.7361824847396768, 3317.7147888003046, 1293.7248464000222,2460.321864 +0.2,21000, 0.8031081651705566, 5785.787455200061, 1909.6551719998736,2683.987488 +0.2,21000, 0.8700338456014363, 8897.440939199427, 3056.7371688001904,2907.653112 +0.2,21000,0.936959526, 11155.844833599513, 4062.5397240000484,3131.318736 +0.2,24000,0, 269.97319167555275, 269.97319167555275,0 +0.2,24000, 0.39187312028725313,-3086.633891,-1467.264528,1309.639968 +0.2,24000, 0.4571853070017953,-1835.977217,-904.9480896,1527.913296 +0.2,24000, 0.5224974937163375,-585.3079128,-342.6348064,1746.186624 +0.2,24000, 0.5878096804308797, 665.3422511999618, 219.67660480007714,1964.459952 +0.2,24000, 0.6531218671454219, 2335.0078592000855,844.9754304,2182.73328 +0.2,24000,0.718434054, 4330.393532000133, 1474.0756264001006, 2401.0066079999997 +0.2,24000, 0.7837462405745063, 5792.046102400926, 1909.764184799733,2619.279936 +0.2,24000, 0.8490584272890486, 7905.602704799972, 2352.5142960001285,2837.553264 +0.2,24000, 0.9143706140035907, 9028.809468800908, 3009.1800920004225,3055.826592 +0.2,24000, 0.9796828007181327, 11165.558232001782, 4091.1444976008543, 3274.0999199999997 +0.2,27000,0, 239.6933616652464, 239.6933616652464,0 +0.2,27000, 0.3821930628366248, 5851.268064800048, 3574.6922360000026, 1277.2892160000001 +0.2,27000, 0.44589190664272893, 4417.294346400074, 2799.7002528000016,1490.170752 +0.2,27000, 0.5095907504488331, 2983.287816000025, 2024.685711999986,1703.052288 +0.2,27000, 0.5732895942549372, 1549.2890647997772, 1249.6711711998873, 1915.9338240000002 +0.2,27000, 0.6369884380610413, 207.16195839984994, 425.31934800005274,2128.81536 +0.2,27000, 0.7006872818671454, 2949.6418104002087, 790.2206111997298,2341.696896 +0.2,27000, 0.7643861256732496, 3967.3728512007283, 1148.0361959999918, 2554.5784320000002 +0.2,27000, 0.8280849694793537, 4283.771040000926, 2084.619260800131,2767.459968 +0.2,27000, 0.8917838132854579, 8825.652020801903, 2731.879137600994,2980.341504 +0.2,27000,0.955482657, 6503.510225599652, 3450.010035200928, 3193.2230400000003 +0.2,30000,0, 212.1620283175196, 212.1620283175196,0 +0.2,30000, 0.3725121005385996,-1299.1236, 256.11379999997877,1244.93544 +0.2,30000, 0.43459745062836624,-116.08, 404.18079999994404,1452.42468 +0.2,30000, 0.49668280071813287, 1066.744800000144, 552.3156999998861,1659.91392 +0.2,30000, 0.5587681508078994, 2249.6810000001974, 700.4106000000195, 1867.4031599999998 +0.2,30000,0.620853501, 2481.530899999819, 467.40749999978067, 2074.8923999999997 +0.2,30000, 0.6829388509874327, 978.6678000008255, 646.3924000004699,2282.38164 +0.2,30000, 0.7450242010771992, 2672.6546999992934, 663.9882999999927,2489.87088 +0.2,30000, 0.8071095511669658, 4300.752799999445, 575.4326999996099,2697.36012 +0.2,30000, 0.8691949012567325, 8847.358799999522, 3656.905699999661,2904.84936 +0.2,30000, 0.9312802513464992, 15157.131800002508, 3717.340599997726,3112.3386 +0.2,30000, 0.9933656014362657, 26100.612300003435,7008.758,3319.82784 +0.2,33000,0, 187.1898861728484, 187.1898861728484,0 +0.2,33000, 0.3628320430879713, 23055.01512239997, 2408.871806399976, 1212.5846880000001 +0.2,33000, 0.42330405026929985, 18179.434164799713, 1907.697678400014, 1414.6821360000001 +0.2,33000, 0.4837760574506284, 13303.806382399483, 1406.5194224000763,1616.779584 +0.2,33000,0.544248065, 8428.168142399802, 905.3799351999479,1818.877032 +0.2,33000, 0.6047200718132855, 3552.504859199834, 404.16703839979493,2020.97448 +0.2,33000, 0.6651920789946141,312.6091424, 290.78005680006254, 2223.0719280000003 +0.2,33000, 0.7256640861759426, 5726.573253599845, 2192.9219367998166, 2425.1693760000003 +0.2,33000, 0.7861360933572712,6102.495387, 2156.7862400003332, 2627.2668240000003 +0.2,33000, 0.8466081005385997, 2044.1403895971544, 59.31571839928711, 2829.3642720000003 +0.2,33000, 0.9070801077199283, 4972.292682399329, 1903.2150087992359, 3031.4617200000002 +0.2,33000, 0.9675521149012568,-15369.76611,-11175.19295,3233.559168 +0.2,36000,0, 164.59910670132666, 164.59910670132666,0 +0.2,36000, 0.3531510807899461, 21355.844000000034, 1673.0644000000184,1180.230912 +0.2,36000, 0.41200959425493716, 17053.516699999716, 1443.186000000033,1376.936064 +0.2,36000, 0.4708681077199282, 12751.070699999062, 1213.307600000101,1573.641216 +0.2,36000, 0.5297266211849192, 8448.720299999866,983.4412,1770.346368 +0.2,36000, 0.5885851346499102, 4146.325899999729, 753.5232999998013,1967.05152 +0.2,36000, 0.6474436481149013, 1281.7116999997365, 503.39420000022164,2163.756672 +0.2,36000, 0.7063021615798922, 1554.097800000296, 516.2421999997059,2360.461824 +0.2,36000, 0.7651606750448833,-5548.7548,-310.5449,2557.166976 +0.2,36000, 0.8240191885098743, 18994.094899995718, 4628.813800001455,2753.872128 +0.2,36000, 0.8828777019748654, 9293.206899999655, 3422.0082999993347,2950.57728 +0.2,36000, 0.9417362154398564,-5216.6114,-6751.3592,3147.282432 +0.2,39000,0, 142.55526520935254, 142.55526520935254,0 +0.2,39000, 0.3528633393177738,-369.1119,-191.7364,1179.26928 +0.2,39000, 0.4116738958707361,-423.5128,-135.8504, 1375.8141600000001 +0.2,39000, 0.4704844524236984,-478.008,-79.9599,1572.35904 +0.2,39000, 0.5292950089766607,-532.4351,-24.0419,1768.90392 +0.2,39000,0.588105566,-586.9227, 31.860599999995912, 1965.4488000000001 +0.2,39000, 0.6469161220825853,-962.282,-11.2916,2161.99368 +0.2,39000, 0.7057266786355476, 919.3271999988092, 385.33050000021944,2358.53856 +0.2,39000, 0.7645372351885098,-128.4183,-70.9444,2555.08344 +0.2,39000, 0.8233477917414722, 4724.469900000452,-694.0086, 2751.6283200000003 +0.2,39000, 0.8821583482944345, 6948.5503000018325, 2589.483400001871,2948.1732 +0.2,39000, 0.9409689048473968, 43362.67030000154, 24330.292900003617,3144.71808 +0.2,42000,0, 123.41336407810354, 123.41336407810354,0 +0.2,42000, 0.3528633393177738,-191029.879,-73367.23043,1179.26928 +0.2,42000, 0.4116738958707361,-149857.5562,-57423.55228, 1375.8141600000001 +0.2,42000, 0.4704844524236984,-108685.2646,-41479.85606,1572.35904 +0.2,42000, 0.5292950089766607,-67513.02814,-25536.13468,1768.90392 +0.2,42000,0.588105566,-26340.74252,-9592.500806, 1965.4488000000001 +0.2,42000, 0.6469161220825853,-6468.488781,-2115.1979,2161.99368 +0.2,42000, 0.7057266786355476, 4304.067562499638,711.8435313,2358.53856 +0.2,42000, 0.7645372351885098,-3325.895381, 345.9538000005905,2555.08344 +0.2,42000, 0.8233477917414722, 11367.893587500846, 6011.922062500005, 2751.6283200000003 +0.2,42000, 0.8821583482944345,-1836.934775,-861.51245,2948.1732 +0.2,42000, 0.9409689048473968, 11769.366156253061, 7794.408525002873,3144.71808 +0.25,0,0,645.0696726,645.0696726,0 +0.25,0, 0.4714123653500898,-1742.0389,-58.8918,1575.460125 +0.25,0, 0.5499810929084381, 445.66239999999954, 611.5524999999957,1838.036813 +0.25,0, 0.6285498204667863, 2633.363799999994, 1281.9967999999851,2100.6135 +0.25,0, 0.7071185480251346, 5070.965799999945, 2010.3996999999918,2363.190188 +0.25,0, 0.7856872755834828, 8055.822799999946, 3018.434599999992,2625.766875 +0.25,0, 0.8642560031418312, 12000.668900000195, 4407.951699999887, 2888.3435624999997 +0.25,0, 0.9428247307001796, 17434.64259999971, 6346.668900000043,3150.92025 +0.25,3000,0, 584.1954374240745, 584.1954374240745,0 +0.25,3000, 0.4616890933572711,-1964.949747,-139.765293,1542.96495 +0.25,3000,0.538637276, 108.11919704801501, 476.8597159877361,1800.125775 +0.25,3000, 0.6155854578096948, 2181.1881420929094, 1093.4848311978913,2057.2866 +0.25,3000, 0.6925336400359066, 4326.535310526286, 1741.598934762304,2314.447425 +0.25,3000, 0.7694818222621185, 6980.937827104638, 2613.340844112933, 2571.6082499999998 +0.25,3000, 0.8464300044883303, 10488.830165588359, 3818.898385857153, 2828.7690749999997 +0.25,3000, 0.9233781867145422, 15330.186727978782,5492.86062,3085.9299 +0.25,6000,0, 527.9505372376796, 527.9505372376796,0 +0.25,6000, 0.4519649124775584,-2162.8518,-217.173, 1510.4667375000001 +0.25,6000, 0.5272923978904848,-225.7294, 351.15710000000183, 1762.2111937500001 +0.25,6000, 0.6026198833034112, 1711.3927999999876,919.4872,2013.95565 +0.25,6000, 0.6779473687163377, 3662.1987000000377, 1495.1986999999938, 2265.7001062500003 +0.25,6000,0.753274854, 6012.335000000035, 2253.9147999999814, 2517.4445625000003 +0.25,6000, 0.8286023395421904,9041.0713, 3293.782700000007, 2769.1890187500003 +0.25,6000, 0.9039298249551168, 13317.44529999992, 4744.825699999964, 3020.9334750000003 +0.25,6000, 0.9792573103680432, 18435.918000000012, 6573.845699999974, 3272.6779312500003 +0.25,9000,0, 476.0724256705646, 476.0724256705646,0 +0.25,9000, 0.44224164048473963,-2278.7202,-298.7478,1477.971563 +0.25,9000, 0.5159485805655296,-489.7066, 227.3927999999987, 1724.3001562499999 +0.25,9000, 0.5896555206463195, 1299.3068999999755, 753.5333999999959, 1970.6287499999999 +0.25,9000, 0.6633624607271095, 3088.3203000000094, 1279.6740999999804,2216.957344 +0.25,9000, 0.7370694008078994, 5151.956499999974,1933.7926,2463.285938 +0.25,9000, 0.8107763408886893, 7776.433100000033, 2825.9757999999924,2709.614531 +0.25,9000, 0.8844832809694793, 11451.41889999997, 4068.226299999982,2955.943125 +0.25,9000, 0.9581902210502692, 15926.962899999764, 5648.186499999971, 3202.2717187499998 +0.25,12000,0, 428.30348146683866, 428.30348146683866,0 +0.25,12000, 0.43251745960502685,-2003.622052,-285.6290816, 1445.4733499999998 +0.25,12000, 0.5046037028725313,-463.2166456, 174.16556320000086, 1686.3855749999998 +0.25,12000, 0.5766899461400359, 1077.188558400014, 633.9602464000027, 1927.2977999999998 +0.25,12000, 0.6487761894075403, 2617.5939023999977, 1093.7548231999997,2168.210025 +0.25,12000, 0.7208624326750449, 4380.616433600048, 1641.559213600004,2409.12225 +0.25,12000, 0.7929486759425494, 6725.131075199985, 2413.666295200011,2650.034475 +0.25,12000, 0.8650349192100537, 9842.336751199888, 3458.4423184000325, 2890.9466999999995 +0.25,12000, 0.9371211624775582, 13708.570474399963, 4810.020418399966, 3131.8589249999995 +0.25,15000,0, 384.4026392638619, 384.4026392638619,0 +0.25,15000, 0.42279418761220816,-2123.8319,-322.3119, 1412.9781749999997 +0.25,15000, 0.4932598855475762,-692.9334, 93.85139999999924, 1648.4745374999998 +0.25,15000, 0.5637255834829443, 737.9664999999944,510.0151, 1883.9708999999998 +0.25,15000, 0.6341912814183124, 2168.865899999995, 926.1784000000018,2119.467263 +0.25,15000, 0.7046569793536804, 3727.2302999999856, 1389.900799999998,2354.963625 +0.25,15000, 0.7751226772890485, 5788.952299999985, 2045.8736999999917,2590.459988 +0.25,15000, 0.8455883752244163, 8300.066199999992, 2924.9878999999987, 2825.9563499999995 +0.25,15000, 0.9160540731597844, 11956.337100000073, 4122.886099999982, 3061.4527124999995 +0.25,15000, 0.9865197710951524, 15138.798399999987, 5445.595899999984, 3296.9490749999995 +0.25,18000,0, 344.13549463777605, 344.13549463777605,0 +0.25,18000, 0.41307000673249544,-3373.667697,-583.2069384, 1380.4799624999998 +0.25,18000,0.481915008,-1714.352618,-141.5671232, 1610.5599562499997 +0.25,18000, 0.5507600089766607,-55.0336984, 300.06845920000217, 1840.6399499999998 +0.25,18000, 0.6196050100987432, 1604.2851415999726, 741.7052063999719,2070.719944 +0.25,18000, 0.6884500112208258, 3016.900199199963, 1167.1288464000077,2300.799938 +0.25,18000, 0.7572950123429083, 4712.997656800105,1701.355784, 2530.8799312499996 +0.25,18000, 0.8261400134649909, 7055.3885543999295, 2422.8140575999532, 2760.9599249999997 +0.25,18000, 0.8949850145870736, 9375.739558399926, 3329.346847999977, 2991.0399187499997 +0.25,18000,0.963830016, 14232.80417200023, 4755.715545599903, 3221.1199124999994 +0.25,21000,0, 307.2747313966918, 307.2747313966918,0 +0.25,21000, 0.40334673473967686,-1822.321482,-68.3615992,1347.984788 +0.25,21000, 0.47057119052962293,-689.5712672, 188.35477359999797,1572.648919 +0.25,21000, 0.5377956463195691, 443.18469919997705, 445.0723111999984,1797.31305 +0.25,21000, 0.6050201021095153, 1575.9375912000526, 701.7846904000062,2021.977181 +0.25,21000, 0.6722445578994614,2692.254201, 988.6469127999845,2246.641313 +0.25,21000, 0.7394690136894075, 3652.6772768001633, 1396.4518904000124,2471.305444 +0.25,21000, 0.8066934694793537, 5831.830067200013, 2025.8950319999406,2695.969575 +0.25,21000, 0.8739179252692999, 8640.355591199714, 3037.3468368001204,2920.633706 +0.25,21000, 0.9411423810592459, 10913.268769599736, 4021.121464000041,3145.297838 +0.25,24000,0, 273.60506965742564, 273.60506965742564,0 +0.25,24000, 0.3936225538599641,-2952.860239,-1086.878288,1315.486575 +0.25,24000, 0.4592263128366248,-1723.222149,-611.0312336,1534.734338 +0.25,24000, 0.5248300718132854,-493.5766648,-135.1859424,1753.9821 +0.25,24000,0.590433831, 736.0576991999754, 340.6580568000406, 1973.2298624999999 +0.25,24000, 0.6560375897666069, 2177.825567200038, 842.9660464000267,2192.477625 +0.25,24000, 0.7216413487432676, 3940.2513720000516, 1396.3195024000481,2411.725388 +0.25,24000, 0.7872451077199282, 5493.7540784005105, 1884.3471567998606,2630.97315 +0.25,24000, 0.8528488666965889, 7527.949516799967, 2429.7341160000665,2850.220913 +0.25,24000, 0.9184526256732496, 9093.743860800534, 3174.121912000228,3069.468675 +0.25,24000, 0.9840563846499102, 11241.584732000993, 4223.0031416004695, 3288.7164374999998 +0.25,27000,0,242.9178931,242.9178931,0 +0.25,27000, 0.3838992818671454, 2648.044816800032, 2042.5788360000024, 1282.9913999999999 +0.25,27000, 0.44788249551166964, 2150.7526824000515, 1673.0656648000024,1496.8233 +0.25,27000, 0.5118657091561939, 1653.4395360000315, 1303.5377919999926,1710.6552 +0.25,27000, 0.5758489228007181, 1156.1315167998582, 934.0099191999275, 1924.4870999999998 +0.25,27000, 0.6398321364452424, 736.4785143999034,541.892408,2138.319 +0.25,27000, 0.7038153500897666, 2861.175466400128, 892.9639791998325,2352.1509 +0.25,27000, 0.7677985637342908, 4078.6004392004093, 1309.1679759999934, 2565.9827999999998 +0.25,27000, 0.8317817773788151, 4904.717260000526, 2123.0680728000707,2779.8147 +0.25,27000, 0.8957649910233393,8505.261613, 2802.812021600619,2993.6466 +0.25,27000, 0.9597482046678635, 7543.393829599838, 3525.0113432005637, 3207.4784999999997 +0.25,30000,0, 215.0161880007593, 215.0161880007593,0 +0.25,30000, 0.3741751009874327,-1570.5171, 0.6666999999864061,1250.493188 +0.25,30000, 0.43653761781867145,-490.5171, 192.97039999996466,1458.908719 +0.25,30000, 0.4989001346499102, 589.3328000001002, 385.3201999999282,1667.32425 +0.25,30000,0.561262651, 1669.258800000136, 577.6427000000085, 1875.7397812499999 +0.25,30000, 0.6236251683123878, 2115.127699999875, 515.9008999998551,2084.155313 +0.25,30000, 0.6859876851436265, 1327.4259000005518, 715.5550000003176, 2292.5708437499998 +0.25,30000, 0.7483502019748653, 2918.627899999504, 868.5973999999931,2500.986375 +0.25,30000, 0.8107127188061041, 4513.853399999529, 983.7328999997039, 2709.4019062499997 +0.25,30000, 0.8730752356373429, 8104.490799999696, 3277.9613999997746,2917.817438 +0.25,30000, 0.9354377524685815, 13003.693600001605, 3622.433599998433, 3126.2329687499996 +0.25,30000, 0.9978002692998204, 21020.044000002174, 6201.657399996548,3334.6485 +0.25,33000,0, 189.70810222904672, 189.70810222904672,0 +0.25,33000, 0.36445182899461404, 15564.810970399976, 1521.9840743999832, 1217.9980125000002 +0.25,33000, 0.42519380049371636, 12361.800720799785, 1246.2691464000075, 1420.9976812500001 +0.25,33000, 0.4859357719928187,9158.75679, 970.5509504000481,1623.99735 +0.25,33000,0.546677743, 5955.705670399858, 694.8600991999621,1826.997019 +0.25,33000, 0.6074197149910233, 2752.6369031998756, 419.1178263998696,2029.996688 +0.25,33000, 0.6681616864901258, 745.7704504000822,430.6678728,2232.996356 +0.25,33000, 0.7289036579892281, 4855.080585599885, 1863.8479927999024, 2435.9960250000004 +0.25,33000, 0.7896456294883304, 5511.795231200532, 1967.6473000002243,2638.995694 +0.25,33000, 0.8503876009874327, 3148.7460615981845, 689.5463263996025, 2841.9953625000003 +0.25,33000,0.911129572, 5335.202890399731, 2024.7906647995278,3044.995031 +0.25,33000, 0.9718715439856374,-9227.630858,-7345.747134,3247.9947 +0.25,36000,0, 166.81341497302694, 166.81341497302694,0 +0.25,36000, 0.35472764811490126, 14231.166100000022, 991.1068000000133,1185.4998 +0.25,36000, 0.41384892280071817, 11432.870499999794, 899.2216000000234,1383.0831 +0.25,36000,0.472970197, 8634.490999999323, 807.3364000000697,1580.6664 +0.25,36000, 0.5320914721723519, 5836.179399999893, 715.4595999999253,1778.2497 +0.25,36000, 0.5912127468581688, 3037.8362999998103, 623.5464999998621,1975.833 +0.25,36000, 0.6503340215439856, 1255.5239999998107,516.2926,2173.4163 +0.25,36000, 0.7094552962298025, 1674.2107000001897, 601.2869999997665,2370.9996 +0.25,36000, 0.7685765709156195,-3033.5286, 129.3010999999442, 2568.5829000000003 +0.25,36000, 0.8276978456014363, 14759.711199997131, 3746.902500000996,2766.1662 +0.25,36000, 0.8868191202872531, 8234.660199999773, 3108.4180999995124,2963.7495 +0.25,36000,0.945940395,-2234.6613,-4165.6627,3161.3328 +0.25,39000,0, 144.47302350861406, 144.47302350861406,0 +0.25,39000, 0.3544386220825853,-613.9023,-250.3941,1184.533875 +0.25,39000, 0.41351172576301615,-538.8967,-162.851,1381.956188 +0.25,39000, 0.47258482944344704,-463.9568,-75.3043,1579.3785 +0.25,39000,0.531657933,-388.9685, 12.261899999951396, 1776.8008125000001 +0.25,39000, 0.5907310368043088,-314.0237, 99.81699999999553,1974.223125 +0.25,39000, 0.6498041404847397,-462.3192, 109.2991000001223,2171.645438 +0.25,39000, 0.7088772441651706, 1101.6041999991653, 462.7509000001477,2369.06775 +0.25,39000, 0.7679503478456015, 621.6528000006874, 240.0913000001408,2566.490063 +0.25,39000, 0.8270234515260323, 4402.225500000371,-109.9786,2763.912375 +0.25,39000, 0.8860965552064632, 6220.224300001228, 2357.8201000013105,2961.334688 +0.25,39000, 0.9451696588868941, 31915.864600000932, 17743.905600002487,3158.757 +0.25,42000,0, 125.07361144148916, 125.07361144148916,0 +0.25,42000, 0.3544386220825853,-146187.7459,-56088.61268,1184.533875 +0.25,42000, 0.41351172576301615,-114664.944,-43890.16303,1381.956188 +0.25,42000, 0.47258482944344704,-83142.16449,-31691.70019,1579.3785 +0.25,42000,0.531657933,-51619.42711,-19493.21824, 1776.8008125000001 +0.25,42000, 0.5907310368043088,-20096.65255,-7294.801844,1974.223125 +0.25,42000, 0.6498041404847397,-4695.918744,-1496.499225,2171.645438 +0.25,42000, 0.7088772441651706, 3503.8320124997153, 679.6217937501436,2369.06775 +0.25,42000, 0.7679503478456015,-1973.981619, 456.5929500004386,2566.490063 +0.25,42000, 0.8270234515260323, 9186.537112500584, 4769.555887500006,2763.912375 +0.25,42000, 0.8860965552064632,-312.321925,-191.211525,2961.334688 +0.25,42000, 0.9451696588868941,10432.98827, 6610.231100002129,3158.757 + 0.30000000000000004,0,0, 655.6391260384394, 655.6391260384394,0 + 0.30000000000000004,0, 0.47397312387791735,-1722.0547,-36.4513, 1584.0181799999998 + 0.30000000000000004,0,0.552968645, 377.01429999999834, 641.9552999999967, 1848.0212099999999 + 0.30000000000000004,0, 0.6319641651705564, 2476.0832999999984, 1320.3618999999903, 2112.0242399999997 + 0.30000000000000004,0,0.710959686, 4891.319299999995, 2070.0437000000306, 2376.0272699999996 + 0.30000000000000004,0, 0.7899552064631955, 7905.778300000102, 3118.1068999999975, 2640.0302999999994 + 0.30000000000000004,0, 0.8689507271095152, 11771.340800000096, 4553.486800000054, 2904.0333299999998 + 0.30000000000000004,0, 0.9479462477558347, 17009.03710000029, 6539.682600000079, 3168.0363599999996 + 0.30000000000000004,3000,0, 593.7674677930876, 593.7674677930876,0 + 0.30000000000000004,3000, 0.46419703411131064,-1974.312731,-123.0554838, 1551.3464880000001 + 0.30000000000000004,3000, 0.5415632064631957, 44.41065904002425, 503.5027981613902,1809.904236 + 0.30000000000000004,3000, 0.6189293788150808, 2063.1340961042174, 1130.0611899839755,2068.461984 + 0.30000000000000004,3000,0.696295551, 4178.625497813836, 1795.7270179819875,2327.019732 + 0.30000000000000004,3000,0.773661724, 6845.890952974329, 2698.6560064776054,2585.57748 + 0.30000000000000004,3000, 0.8510278958707361, 10288.908661126477, 3946.674394161047,2844.135228 + 0.30000000000000004,3000, 0.9283940682226213, 14955.41640422129, 5662.275117429667, 3102.6929760000003 + 0.30000000000000004,6000,0, 536.6009960602593, 536.6009960602593,0 + 0.30000000000000004,6000, 0.45442003052064633,-2198.439,-203.6151,1518.671742 + 0.30000000000000004,6000, 0.5301567022740874,-298.3211, 374.1918000000013,1771.783699 + 0.30000000000000004,6000, 0.6058933740275285, 1601.796599999996, 951.9988000000036, 2024.8956560000001 + 0.30000000000000004,6000, 0.6816300457809695, 3532.944300000014, 1543.8254000000013,2278.007613 + 0.30000000000000004,6000, 0.7573667175344106, 5889.292000000001, 2330.751200000017, 2531.1195700000003 + 0.30000000000000004,6000, 0.8331033892878517, 8909.537099999992, 3405.4990000000075, 2784.2315270000004 + 0.30000000000000004,6000, 0.9088400610412927, 13001.74120000004, 4896.623500000034,3037.343484 + 0.30000000000000004,6000, 0.9845767327947337, 18010.134800000007, 6764.826699999997,3290.455441 + 0.30000000000000004,9000,0, 483.87286268948714, 483.87286268948714,0 + 0.30000000000000004,9000, 0.4446439407540395,-2330.1484,-290.1643,1486.00005 + 0.30000000000000004,9000, 0.5187512642130461,-563.7825, 245.97229999999956,1733.666725 + 0.30000000000000004,9000, 0.5928585876720527, 1202.583399999992, 782.1088999999985,1981.3334 + 0.30000000000000004,9000, 0.6669659111310592, 2968.9492000000055, 1318.245500000004,2229.000075 + 0.30000000000000004,9000, 0.7410732345900658, 5040.569799999995, 1997.8845000000047,2476.66675 + 0.30000000000000004,9000, 0.8151805580490723, 7692.805200000018, 2929.594499999995,2724.333425 + 0.30000000000000004,9000,0.889287882, 11181.069299999976,4198.1226,2972.0001 + 0.30000000000000004,9000, 0.9633952049670856, 15576.658200000007, 5822.217300000024,3219.666775 + 0.30000000000000004,12000,0, 435.32122530583854, 435.32122530583854,0 + 0.30000000000000004,12000, 0.4348669371633752,-2163.181591,-299.0330624,1453.325304 + 0.30000000000000004,12000, 0.5073447600239377,-609.0475616, 175.74389039999997, 1695.5461879999998 + 0.30000000000000004,12000, 0.5798225828845003, 945.0864592000006, 650.5209159999996, 1937.7670719999999 + 0.30000000000000004,12000, 0.6523004057450629, 2499.220427999975, 1125.2978248000068,2179.987956 + 0.30000000000000004,12000, 0.7247782286056254, 4287.446582399997, 1698.784959999999,2422.20884 + 0.30000000000000004,12000, 0.7972560514661878,6603.436107,2496.387107, 2664.4297239999996 + 0.30000000000000004,12000, 0.8697338743267504, 9629.066372000018, 3574.470187199962,2906.650608 + 0.30000000000000004,12000, 0.9422116971873129, 13412.543775199965, 4963.872883999996, 3148.8714919999998 + 0.30000000000000004,15000,0, 390.70106869560607, 390.70106869560607,0 + 0.30000000000000004,15000, 0.42509084739676845,-2067.99,-301.0187,1420.653612 + 0.30000000000000004,15000, 0.4959393219628965,-682.3344, 118.71769999999994,1657.429214 + 0.30000000000000004,15000, 0.5667877965290246, 703.3210999999991, 538.4540999999999,1894.204816 + 0.30000000000000004,15000, 0.6376362710951526, 2088.976599999998, 958.1905000000003,2130.980418 + 0.30000000000000004,15000, 0.7084847456612806, 3634.7191999999995, 1442.6549999999988,2367.75602 + 0.30000000000000004,15000, 0.7793332202274087, 5630.085899999996, 2114.0347000000015,2604.531622 + 0.30000000000000004,15000, 0.8501816947935369, 8242.302700000006,3037.5891,2841.307224 + 0.30000000000000004,15000, 0.9210301693596649, 11505.213899999999, 4210.631299999998,3078.082826 + 0.30000000000000004,15000,0.991878644, 15085.611299999993, 5615.936999999995,3314.858428 + 0.30000000000000004,18000,0, 349.77414772321083, 349.77414772321083,0 + 0.30000000000000004,18000, 0.4153138438061041,-2535.845225,-421.6568424,1387.978866 + 0.30000000000000004,18000, 0.48453281777378815,-1142.685894,-16.5099752,1619.308677 + 0.30000000000000004,18000, 0.5537517917414722, 250.47475760000808, 388.63553120000006,1850.638488 + 0.30000000000000004,18000, 0.6229707657091562, 1643.6352975999891, 793.7815303999928,2081.968299 + 0.30000000000000004,18000, 0.6921897396768403, 3020.542691199985, 1218.5807504000034,2313.29811 + 0.30000000000000004,18000, 0.7614087136445243, 4740.696944800034, 1785.446364000006, 2544.6279210000002 + 0.30000000000000004,18000, 0.8306276876122082, 7007.7219783999735, 2550.7582535999854,2775.957732 + 0.30000000000000004,18000, 0.8998466615798922,9594.321162, 3522.1187479999785,3007.287543 + 0.30000000000000004,18000, 0.9690656355475763, 13289.14215200003,4845.926242,3238.617354 + 0.30000000000000004,21000,0, 312.3094216255789, 312.3094216255789,0 + 0.30000000000000004,21000, 0.4055377540394973,-2082.715746,-255.1109112,1355.307174 + 0.30000000000000004,21000, 0.47312737971274693,-920.1372992, 60.16892959999867, 1581.1917030000002 + 0.30000000000000004,21000, 0.5407170053859964, 242.44379119998368, 375.4492631999985, 1807.0762320000001 + 0.30000000000000004,21000,0.608306631, 1405.0237232000215, 690.7271944000063,2032.960761 + 0.30000000000000004,21000, 0.6758962567324955, 2570.1426288000093, 1023.0374607999923,2258.84529 + 0.30000000000000004,21000, 0.7434858824057451, 3853.675284800081, 1485.7858944000095,2484.729819 + 0.30000000000000004,21000, 0.8110755080789946,5876.036059, 2138.678891999982,2710.614348 + 0.30000000000000004,21000, 0.8786651337522442, 8462.327223199887, 3072.246424800067,2936.498877 + 0.30000000000000004,21000, 0.9462547594254939, 10776.648645599891, 4069.0628040000292, 3162.3834060000004 + 0.30000000000000004,24000,0, 278.08808316301673, 278.08808316301673,0 + 0.30000000000000004,24000,0.39576075,-2751.815967,-804.086548,1322.632428 + 0.30000000000000004,24000, 0.46172087552363855,-1568.087101,-390.4686176,1543.071166 + 0.30000000000000004,24000,0.527681001,-384.3544368, 23.14846159999894,1763.509904 + 0.30000000000000004,24000, 0.5936411256732496, 799.3725271999853, 436.76472880001756,1983.948642 + 0.30000000000000004,24000, 0.6596012507480551,2065.186155, 855.2136224000054,2204.38738 + 0.30000000000000004,24000, 0.7255613758228605, 3656.178712000009, 1359.2486384000163,2424.826118 + 0.30000000000000004,24000,0.791521501, 5282.565414400236, 1892.8897487999411,2645.264856 + 0.30000000000000004,24000, 0.8574816259724716,7268.699249, 2520.292436000026,2865.703594 + 0.30000000000000004,24000, 0.9234417510472771, 9125.918172800291, 3334.852332000099,3086.142332 + 0.30000000000000004,24000, 0.9894018761220826, 11237.83543200046, 4353.938825600216,3306.58107 + 0.30000000000000004,27000,0, 246.8980978396312, 246.8980978396312,0 + 0.30000000000000004,27000, 0.3859846606822262, 414.1757888000175, 950.8760360000006,1289.960736 + 0.30000000000000004,27000, 0.4503154374625973, 572.1774784000326, 872.8467968000009, 1504.9541920000001 + 0.30000000000000004,27000, 0.5146462142429683, 730.1667560000297, 794.8086719999955,1719.947648 + 0.30000000000000004,27000, 0.5789769910233393, 888.1591887999183, 716.7705471999561,1934.941104 + 0.30000000000000004,27000, 0.6433077678037104, 1105.4181303999449, 631.9494680000264,2149.93456 + 0.30000000000000004,27000, 0.7076385445840815, 2793.542882400072, 981.0181271999061, 2364.9280160000003 + 0.30000000000000004,27000, 0.7719693213644524, 4150.088707200199, 1442.5944559999928,2579.921472 + 0.30000000000000004,27000, 0.8363000981448235, 5349.264880000251, 2176.1204048000295,2794.914928 + 0.30000000000000004,27000, 0.9006308749251946, 8251.826324800684,2887.400246, 3009.9083840000003 + 0.30000000000000004,27000, 0.9649616517055656, 8297.254473599945, 3630.423131200299,3224.90184 + 0.30000000000000004,30000,0, 218.53922387116555, 218.53922387116555,0 + 0.30000000000000004,30000, 0.3762076570915619,-1784.8838,-191.7655, 1257.2859899999999 + 0.30000000000000004,30000, 0.4389089332734889,-783.396, 35.38469999997946,1466.833655 + 0.30000000000000004,30000, 0.5016102094554159, 217.9944000000644, 262.5643999999586,1676.38132 + 0.30000000000000004,30000, 0.5643114856373429, 1219.433900000088, 489.7265000000019,1885.928985 + 0.30000000000000004,30000, 0.6270127618192699, 1824.5880999999167, 558.0992999999105,2095.47665 + 0.30000000000000004,30000, 0.6897140380011969, 1602.2850000003464, 781.4071000002007,2305.024315 + 0.30000000000000004,30000, 0.7524153141831238, 3107.9129999996703, 1040.4782999999925, 2514.5719799999997 + 0.30000000000000004,30000, 0.8151165903650508, 4681.3040999996265, 1315.8614999997862, 2724.1196449999998 + 0.30000000000000004,30000, 0.8778178665469778, 7543.260099999814, 3015.252699999859,2933.66731 + 0.30000000000000004,30000, 0.9405191427289048, 11314.845800000947, 3560.025399998981,3143.214975 + 0.30000000000000004,33000,0, 192.8164656284447, 192.8164656284447,0 + 0.30000000000000004,33000, 0.36643156732495513, 9700.131358399978,829.1826824,1224.614298 + 0.30000000000000004,33000, 0.4275034952124477, 7807.481456799842, 731.3772544000034,1428.716681 + 0.30000000000000004,33000, 0.4885754230999402, 5914.8083383997155, 633.5693184000281,1632.819064 + 0.30000000000000004,33000, 0.5496473509874327, 4022.1305383999047, 535.7797831999727,1836.921447 + 0.30000000000000004,33000, 0.6107192788749253, 2129.4408671999095, 437.9559543999235,2041.02383 + 0.30000000000000004,33000, 0.6717912067624178, 1080.7718984000546, 546.0367688000329,2245.126213 + 0.30000000000000004,33000, 0.7328631346499103, 4174.890077599918, 1618.031528799959,2449.228596 + 0.30000000000000004,33000, 0.7939350625374028, 5053.575195200373, 1837.7854600001444,2653.330979 + 0.30000000000000004,33000, 0.8550069904248954, 4000.5846935989316, 1196.6764743998133,2857.433362 + 0.30000000000000004,33000, 0.9160789183123879, 5662.175238399976, 2173.8316007997437,3061.535745 + 0.30000000000000004,33000, 0.9771508461998804,-4247.11627,-4209.720362,3265.638128 + 0.30000000000000004,36000,0, 169.54664938704636, 169.54664938704636,0 + 0.30000000000000004,36000, 0.3566545637342909, 8679.757700000011, 458.83760000000876,1191.939552 + 0.30000000000000004,36000, 0.41609699102333936, 7054.405799999855, 476.26320000001556,1390.596144 + 0.30000000000000004,36000, 0.47553941831238783, 5428.997299999534,493.6888, 1589.2527360000001 + 0.30000000000000004,36000, 0.5349818456014364, 3803.6348999999177, 511.1199999999469, 1787.9093280000002 + 0.30000000000000004,36000, 0.5944242728904848, 2178.250899999871, 528.5267999999088, 1986.5659200000002 + 0.30000000000000004,36000, 0.6538667001795333, 1238.9081999998675, 534.7619000001046, 2185.2225120000003 + 0.30000000000000004,36000, 0.7133091274685818, 1781.8011000001097, 680.9250999998211,2383.879104 + 0.30000000000000004,36000, 0.7727515547576302,-1039.8503,491.1401, 2582.5356960000004 + 0.30000000000000004,36000, 0.8321939820466787, 11436.201099998172, 3077.4519000006494,2781.192288 + 0.30000000000000004,36000, 0.8916364093357273, 7389.053499999863, 2869.8957999996564, 2979.8488800000005 + 0.30000000000000004,36000, 0.9510788366247757, 140.7929999991975,-2105.594, 3178.5054720000003 + 0.30000000000000004,39000,0, 146.8402110625349, 146.8402110625349,0 + 0.30000000000000004,39000, 0.35636396768402157,-859.5542,-303.6646,1190.96838 + 0.30000000000000004,39000, 0.4157579622980252,-670.8478,-188.689, 1389.4631100000001 + 0.30000000000000004,39000, 0.4751519569120287,-482.1849,-73.7106,1587.95784 + 0.30000000000000004,39000, 0.5345459515260323,-293.4891, 41.28099999996853,1786.45257 + 0.30000000000000004,39000, 0.5939399461400359,-104.8233, 156.26499999999578,1984.9473 + 0.30000000000000004,39000, 0.6533339407540395,-61.3595, 212.36400000007677,2183.44203 + 0.30000000000000004,39000, 0.7127279353680431, 1253.6143999994406, 534.3202000000931,2381.93676 + 0.30000000000000004,39000, 0.7721219299820467, 1227.694200000447, 497.3822000001031,2580.43149 + 0.30000000000000004,39000, 0.8315159245960504, 4155.631300000281, 370.38820000059354, 2778.9262200000003 + 0.30000000000000004,39000, 0.8909099192100539, 5658.399800000765, 2196.3475000008725,2977.42095 + 0.30000000000000004,39000, 0.9503039138240574, 22985.382100000505, 12612.727000001616,3175.91568 + 0.30000000000000004,42000,0, 127.12294002296355, 127.12294002296355,0 + 0.30000000000000004,42000, 0.35636396768402157,-109083.0735,-41796.87193,1190.96838 + 0.30000000000000004,42000, 0.4157579622980252,-85544.63034,-32694.76438, 1389.4631100000001 + 0.30000000000000004,42000, 0.4751519569120287,-62006.20249,-23592.64758,1587.95784 + 0.30000000000000004,42000, 0.5345459515260323,-38467.80599,-14490.51666,1786.45257 + 0.30000000000000004,42000, 0.5939399461400359,-14929.38217,-5388.433331,1984.9473 + 0.30000000000000004,42000, 0.6533339407540395,-3248.578356,-987.12595,2183.44203 + 0.30000000000000004,42000, 0.7127279353680431, 2856.0819624997694, 657.6385062501067,2381.93676 + 0.30000000000000004,42000, 0.7721219299820467,-864.5085062, 558.4525000003114,2580.43149 + 0.30000000000000004,42000, 0.8315159245960504, 7418.437737500386, 3770.111012500003, 2778.9262200000003 + 0.30000000000000004,42000, 0.8909099192100539, 916.1667250000646, 359.6056000004701,2977.42095 + 0.30000000000000004,42000, 0.9503039138240574, 9249.859431251229, 5605.789675001492,3175.91568 + 0.35000000000000003,0,0, 668.2783888765358, 668.2783888765358,0 + 0.35000000000000003,0, 0.47699947486535005,-1643.586825,-6.4903, 1594.1322449999998 + 0.35000000000000003,0, 0.5564993873429084, 344.1157499999982, 679.1378999999911, 1859.8209524999997 + 0.35000000000000003,0, 0.6359992998204667, 2331.8182250000036, 1364.7660999999753, 2125.5096599999997 + 0.35000000000000003,0,0.715499212, 4733.674174999985, 2140.1169000000614, 2391.1983674999997 + 0.35000000000000003,0, 0.7949991247755833, 7815.084525000263, 3234.264324999983, 2656.8870749999996 + 0.35000000000000003,0, 0.8744990372531417, 11600.211700000209, 4726.712575000102, 2922.5757824999996 + 0.35000000000000003,0, 0.9539989497307001, 16641.543900000517, 6761.731950000154, 3188.2644899999996 + 0.35000000000000003,3000,0, 605.2139827921145, 605.2139827921145,0 + 0.35000000000000003,3000, 0.4671609640933572,-1893.548064,-96.68371348, 1561.2519419999999 + 0.35000000000000003,3000, 0.5450211247755834, 35.55024366739556, 538.0440708611612, 1821.4605989999998 + 0.35000000000000003,3000, 0.6228812854578096, 1964.6485508357673, 1172.7718859203503, 2081.6692559999997 + 0.35000000000000003,3000, 0.7007414461400359, 4025.642942430229, 1856.2850790931543,2341.877913 + 0.35000000000000003,3000,0.778601607,6721.039341, 2796.180356596486, 2602.0865699999995 + 0.35000000000000003,3000, 0.8564617675044882, 10200.373970351768, 4099.958938889455, 2862.2952269999996 + 0.35000000000000003,3000, 0.9343219281867144, 14801.456835400393, 5884.001489814689, 3122.5038839999997 + 0.35000000000000003,6000,0, 546.9454687420075, 546.9454687420075,0 + 0.35000000000000003,6000, 0.4573215336624775,-2126.1724,-180.3598,1528.368566 + 0.35000000000000003,6000, 0.5335417892728905,-299.722, 405.4138000000008,1783.09666 + 0.35000000000000003,6000, 0.6097620448833034, 1526.7283999999997, 991.1875000000025,2037.824754 + 0.35000000000000003,6000, 0.6859823004937163, 3404.544699999999, 1598.9492000000062,2292.552848 + 0.35000000000000003,6000, 0.7622025561041292, 5790.660600000009, 2418.8593999999916,2547.280943 + 0.35000000000000003,6000, 0.8384228117145422, 8793.249999999989, 3531.679400000014,2802.009037 + 0.35000000000000003,6000,0.914643067, 12872.850599999958, 5085.368700000043,3056.737131 + 0.35000000000000003,6000,0.990863323, 17629.503899999945, 6974.8364000000065,3311.465225 + 0.35000000000000003,9000,0, 493.2008543374353, 493.2008543374353,0 + 0.35000000000000003,9000, 0.44748302289048475,-2261.0547,-272.2221,1495.488263 + 0.35000000000000003,9000, 0.5220635267055654,-556.4717, 272.5457999999998, 1744.7363062499999 + 0.35000000000000003,9000, 0.5966440305206463, 1148.111700000002, 817.3137999999987,1993.98435 + 0.35000000000000003,9000, 0.6712245343357272, 2852.695099999994, 1362.0818000000008,2243.232394 + 0.35000000000000003,9000, 0.7458050381508079, 4941.802700000021, 2070.978500000004,2492.480438 + 0.35000000000000003,9000, 0.8203855419658886, 7597.169399999982, 3042.699000000014, 2741.7284812499997 + 0.35000000000000003,9000, 0.8949660457809695, 11125.042000000005, 4371.106400000022,2990.976525 + 0.35000000000000003,9000, 0.9695465495960502, 15347.561500000023, 6032.982399999997,3240.224569 + 0.35000000000000003,12000,0, 443.71324946536083, 443.71324946536083,0 + 0.35000000000000003,12000,0.437643592,-2276.28064,-315.6978864, 1462.6048859999999 + 0.35000000000000003,12000, 0.5105841912028725,-720.8462688, 176.73515359999897,1706.372367 + 0.35000000000000003,12000,0.58352479, 834.5878952000091, 669.1681479999974, 1950.1398479999998 + 0.35000000000000003,12000, 0.6564653886894074, 2390.0219471999867, 1161.6011711999965, 2193.9073289999997 + 0.35000000000000003,12000, 0.7294059874326749, 4204.665229599948, 1764.086832799984, 2437.6748099999995 + 0.35000000000000003,12000, 0.8023465861759425, 6529.955508800013, 2593.206882400016,2681.442291 + 0.35000000000000003,12000,0.875287185, 9575.901431999913,3725.990086, 2925.2097719999997 + 0.35000000000000003,12000, 0.9482277836624774, 13217.24354319993, 5147.080213599976, 3168.9772529999996 + 0.35000000000000003,15000,0, 398.23291556418263, 398.23291556418263,0 + 0.35000000000000003,15000, 0.42780508168761217,-2082.4854,-300.0607,1429.724583 + 0.35000000000000003,15000, 0.4991059286355476,-721.9742, 129.89469999999943,1668.012014 + 0.35000000000000003,15000,0.570406776, 638.5368999999927,559.8501,1906.299444 + 0.35000000000000003,15000, 0.6417076225314182, 1999.0479999999943, 989.8055000000024,2144.586875 + 0.35000000000000003,15000, 0.7130084694793536, 3546.407700000006, 1493.7940999999996,2382.874305 + 0.35000000000000003,15000,0.784309316, 5564.218300000008, 2199.7226999999943,2621.161736 + 0.35000000000000003,15000, 0.8556101633752243, 8208.329100000015, 3164.0089999999987,2859.449166 + 0.35000000000000003,15000, 0.9269110103231597, 11334.85739999997, 4364.239700000006,3097.736597 + 0.35000000000000003,15000, 0.9982118572710952, 14750.12209999999, 5770.601599999988,3336.024027 + 0.35000000000000003,18000,0, 356.51701466246317, 356.51701466246317,0 + 0.35000000000000003,18000, 0.4179656512567324,-2124.355273,-339.2167064, 1396.8412064999998 + 0.35000000000000003,18000, 0.4876265931328545,-872.7657096, 52.37529280000007, 1629.6480742499998 + 0.35000000000000003,18000, 0.5572875350089767, 378.8240536000003,443.9671832, 1862.4549419999998 + 0.35000000000000003,18000, 0.6269484768850987, 1630.4137935999977, 835.5592143999997,2095.26181 + 0.35000000000000003,18000, 0.6966094187612208, 2987.2558631999964, 1268.9999144000012,2328.068678 + 0.35000000000000003,18000, 0.7662703606373429, 4735.313552800001, 1864.6357440000006,2560.875545 + 0.35000000000000003,18000, 0.8359313025134648, 7006.297562399993, 2678.577089600001, 2793.6824129999995 + 0.35000000000000003,18000,0.905592244, 9695.005226399984, 3700.6689479999927, 3026.4892807499996 + 0.35000000000000003,18000,0.975253186, 12807.588231999995, 4997.189877599993, 3259.2961484999996 + 0.35000000000000003,21000,0, 318.3300520455337, 318.3300520455337,0 + 0.35000000000000003,21000, 0.4081271404847397,-2145.93367,-342.4880032,1363.960904 + 0.35000000000000003,21000, 0.47614833056552963,-995.5710112, 5.216625599999403,1591.287721 + 0.35000000000000003,21000, 0.5441695206463196, 154.79256319999118, 352.9213951999991,1818.614538 + 0.35000000000000003,21000, 0.6121907107271095, 1305.1559352000045, 700.6253584000035,2045.941355 + 0.35000000000000003,21000, 0.6802119008078995, 2483.338476800004, 1063.5002287999985,2273.268173 + 0.35000000000000003,21000, 0.7482330908886894, 3952.541212800035, 1566.6935584000087,2500.59499 + 0.35000000000000003,21000, 0.8162542809694794, 5919.786531200003, 2251.6187520000017,2727.921807 + 0.35000000000000003,21000, 0.8842754710502693, 8355.876435199978, 3154.9628328000267,2955.248624 + 0.35000000000000003,21000, 0.9522966611310593, 10728.889761599974, 4191.690744000012,3182.575442 + 0.35000000000000003,24000,0, 283.44900235720434, 283.44900235720434,0 + 0.35000000000000003,24000, 0.39828771005385993,-2517.137975,-604.821308,1331.077527 + 0.35000000000000003,24000, 0.4646689950628366,-1393.832673,-232.4269416,1552.923782 + 0.35000000000000003,24000, 0.5310502800718132,-270.5258288, 139.96710559999946,1774.770036 + 0.35000000000000003,24000, 0.5974315650807899, 852.7786351999922, 512.3607208000052, 1996.6162904999999 + 0.35000000000000003,24000, 0.6638128500897665, 1990.071023199997, 880.0879583999972,2218.462545 + 0.35000000000000003,24000, 0.7301941350987432, 3463.433551999991, 1357.5503344000012, 2440.3087994999996 + 0.35000000000000003,24000, 0.7965754201077199, 5147.198410400079, 1931.9765607999832,2662.155054 + 0.35000000000000003,24000, 0.8629567051166966, 7112.157500799964, 2625.468256000004,2884.001309 + 0.35000000000000003,24000, 0.9293379901256732,9140.301505, 3497.253852000024,3105.847563 + 0.35000000000000003,24000, 0.9957192751346498, 11189.682332000142,4494.35625, 3327.6938174999996 + 0.35000000000000003,27000,0, 251.65774354850882, 251.65774354850882,0 + 0.35000000000000003,27000, 0.38844919928186716,-1015.777419, 227.64733600000045,1298.197224 + 0.35000000000000003,27000, 0.45319073249551173,-436.1124656, 345.87724880000087, 1514.5634280000002 + 0.35000000000000003,27000, 0.5179322657091562, 143.54597600002435, 464.1023519999982,1730.929632 + 0.35000000000000003,27000, 0.5826737989228007, 723.2061807999596, 582.3274551999768,1947.295836 + 0.35000000000000003,27000, 0.6474153321364453, 1342.3321063999733, 701.2725280000153,2163.66204 + 0.35000000000000003,27000, 0.7121568653500898, 2745.6773584000366, 1058.1504551999537,2380.028244 + 0.35000000000000003,27000, 0.7768983985637343, 4192.823055200075, 1555.4236359999916,2596.394448 + 0.35000000000000003,27000, 0.8416399317773788, 5650.791900000082, 2244.8753568000043,2812.760652 + 0.35000000000000003,27000, 0.9063814649910235, 8063.762256800326,2987.98701, 3029.1268560000003 + 0.35000000000000003,27000,0.971122998, 8817.193857599992, 3764.537799200125, 3245.4930600000002 + 0.35000000000000003,30000,0, 222.75217361934654, 222.75217361934654,0 + 0.35000000000000003,30000, 0.37860976885098746,-1945.5682,-328.9534,1265.313848 + 0.35000000000000003,30000, 0.4417113969928187,-1002.0784,-75.0909,1476.199489 + 0.35000000000000003,30000, 0.5048130251346499,-58.6472, 178.7889999999794,1687.08513 + 0.35000000000000003,30000, 0.5679146532764812, 884.8133000000524, 432.6583999999985, 1897.9707712499999 + 0.35000000000000003,30000, 0.6310162814183123, 1601.8253999999492, 595.7917999999488,2108.856413 + 0.35000000000000003,30000, 0.6941179095601435, 1813.370600000197, 845.1598000001154, 2319.7420537499997 + 0.35000000000000003,30000, 0.7572195377019749, 3250.793399999793, 1185.623999999991,2530.627695 + 0.35000000000000003,30000, 0.8203211658438061, 4812.289399999729, 1584.2880999998556,2741.513336 + 0.35000000000000003,30000, 0.8834227939856374, 7143.230299999894, 2856.5512999999182,2952.398978 + 0.35000000000000003,30000, 0.9465244221274686, 10041.400400000499, 3532.9170999993935,3163.284619 + 0.35000000000000003,33000,0, 196.53353785888967, 196.53353785888967,0 + 0.35000000000000003,33000, 0.36877125807899463, 5267.119386399985, 307.6657303999933, 1232.4335445000002 + 0.35000000000000003,33000, 0.4302331344254937, 4365.808572799895, 345.9066024000011,1437.839135 + 0.35000000000000003,33000, 0.49169501077199285, 3464.482626399804, 384.1456264000144, 1643.2447260000001 + 0.35000000000000003,33000,0.553156887, 2563.1538463999377, 422.3962871999813, 1848.6503167500002 + 0.35000000000000003,33000,0.614618763, 1661.8175511999393, 460.6255223999601,2054.055908 + 0.35000000000000003,33000, 0.6760806398114901, 1331.4525864000343, 641.1114448000225,2259.461498 + 0.35000000000000003,33000, 0.7375425161579893, 3665.191129599942, 1446.833744799994, 2464.8670890000003 + 0.35000000000000003,33000, 0.7990043925044884, 4714.719579200251, 1761.6467200000882, 2670.2726797500004 + 0.35000000000000003,33000, 0.8604662688509874, 4635.346685599444, 1598.9072623999446,2875.678271 + 0.35000000000000003,33000, 0.9219281451974866, 5954.983826400115, 2345.6705167998875,3081.083861 + 0.35000000000000003,33000, 0.9833900215439857,-306.6352416,-1694.84523, 3286.4894520000003 + 0.35000000000000003,36000,0, 172.8151313610703, 172.8151313610703,0 + 0.35000000000000003,36000, 0.3589318276481149, 4510.2403000000095, 58.68510000000589,1199.550168 + 0.35000000000000003,36000, 0.4187537989228007, 3767.0560999999075, 160.1727000000104, 1399.4751959999999 + 0.35000000000000003,36000, 0.47857577019748654, 3023.8359999997037, 261.6603000000293,1599.400224 + 0.35000000000000003,36000, 0.5383977414721723, 2280.645399999944, 363.15139999996495,1799.325252 + 0.35000000000000003,36000, 0.5982197127468581, 1537.4407999999187, 464.62709999994354,1999.25028 + 0.35000000000000003,36000,0.658041684, 1231.5360999999134, 558.7256000000657,2199.175308 + 0.35000000000000003,36000, 0.7178636552962298, 1878.8639000000571, 756.5796999998695,2399.100336 + 0.35000000000000003,36000, 0.7776856265709157, 494.8921000002565, 785.5066999999945,2599.025364 + 0.35000000000000003,36000, 0.8375075978456014, 8917.534199998934, 2596.3635000003906, 2798.9503919999997 + 0.35000000000000003,36000, 0.8973295691202872, 6736.400899999915, 2701.7914999997724,2998.87542 + 0.35000000000000003,36000, 0.9571515403949731, 1987.7441999995171,-502.8302,3198.800448 + 0.35000000000000003,39000,0, 149.67096345224525, 149.67096345224525,0 + 0.35000000000000003,39000, 0.3586393761220826,-1099.8343,-351.7334,1198.572795 + 0.35000000000000003,39000, 0.41841260547576303,-812.4277,-213.0053,1398.334928 + 0.35000000000000003,39000, 0.4781858348294435,-525.048,-74.2751,1598.09706 + 0.35000000000000003,39000, 0.5379590641831239,-237.6472, 64.46349999998127,1797.859193 + 0.35000000000000003,39000, 0.5977322935368043, 49.734000000072186, 203.1971999999966,1997.621325 + 0.35000000000000003,39000, 0.6575055228904848, 252.7609999998765, 300.4039000000438,2197.383458 + 0.35000000000000003,39000, 0.7172787522441652, 1379.740399999649,601.4242,2397.14559 + 0.35000000000000003,39000, 0.7770519815978456, 1707.121400000267,708.5457,2596.907723 + 0.35000000000000003,39000, 0.8368252109515261, 3977.511800000203,760.3172,2796.669855 + 0.35000000000000003,39000, 0.8965984403052065, 5244.925800000429, 2098.5464000005422,2996.431988 + 0.35000000000000003,39000,0.95637167, 16269.082500000211, 8764.223300000975,3196.19412 + 0.35000000000000003,42000,0, 129.57358731945757, 129.57358731945757,0 + 0.35000000000000003,42000, 0.3586393761220826,-78983.18996,-30208.15498,1198.572795 + 0.35000000000000003,42000, 0.41841260547576303,-61921.36514,-23615.11113,1398.334928 + 0.35000000000000003,42000, 0.4781858348294435,-44859.55019,-17022.06112,1598.09706 + 0.35000000000000003,42000, 0.5379590641831239,-27797.75776,-10429.00102,1797.859193 + 0.35000000000000003,42000, 0.5977322935368043,-10735.946,-3835.974169,1997.621325 + 0.35000000000000003,42000, 0.6575055228904848,-2092.492319,-575.419075,2197.383458 + 0.35000000000000003,42000, 0.7172787522441652, 2346.460612499827,645.9487688,2397.14559 + 0.35000000000000003,42000, 0.7770519815978456, 28.359456250032963, 653.2664500002124,2596.907723 + 0.35000000000000003,42000, 0.8368252109515261, 6023.070462500245, 2990.1968375000033,2796.669855 + 0.35000000000000003,42000, 0.8965984403052065, 1882.3891749999802, 805.6271250002965,2996.431988 + 0.35000000000000003,42000,0.95637167, 8216.781543750672, 4770.240850001006,3196.19412 +0.4,0,0, 683.0627788169501, 683.0627788169501,0 +0.4,0, 0.48049141831238773,-1668.094, 21.415500000000065, 1605.8023199999998 +0.4,0, 0.5605733213644524, 256.0641999999999, 717.9128999999815, 1873.4360399999998 +0.4,0,0.640655224, 2180.222400000022, 1414.4103999999504,2141.06976 +0.4,0, 0.7207371274685815,4596.5879, 2221.995600000102, 2408.7034799999997 +0.4,0, 0.8008190305206463, 7693.731000000509, 3363.503399999954,2676.3372 +0.4,0, 0.8809009335727109, 11317.468800000395, 4915.298800000162, 2943.9709199999998 +0.4,0, 0.9609828366247755, 16269.150400000764, 7008.135700000263, 3211.6046399999996 +0.4,3000,0, 618.6031925405131, 618.6031925405131,0 +0.4,3000,0.470580883,-1854.571478,-68.0780469, 1572.6813119999997 +0.4,3000, 0.5490110305206463,9.847154042, 576.1846389829623, 1834.7948639999997 +0.4,3000, 0.6274411777378814, 1874.265552771971, 1220.4472001755557, 2096.9084159999998 +0.4,3000, 0.7058713249551166, 3895.9089664878247, 1925.0278098149508, 2359.0219679999996 +0.4,3000, 0.7843014721723518, 6609.737412566807, 2909.9493632845124,2621.13552 +0.4,3000,0.862731619, 10118.806898024477, 4268.758614599299, 2883.2490719999996 +0.4,3000,0.941161767, 14841.293317746662, 6153.5577474078045, 3145.3626239999994 +0.4,6000,0, 559.0455982997187, 559.0455982997187,0 +0.4,6000, 0.4606694219030521,-2030.2659,-153.789, 1539.5572080000002 +0.4,6000, 0.5374476588868942,-276.7292, 441.2673000000023, 1796.1500760000001 +0.4,6000, 0.6142258958707361, 1476.8073999999945, 1036.3237000000072,2052.742944 +0.4,6000, 0.6910041328545782, 3306.417999999998, 1662.677200000013, 2309.3358120000003 +0.4,6000, 0.7677823698384201,5690.1733, 2514.907199999978,2565.92868 +0.4,6000, 0.8445606068222622, 8775.895499999911, 3689.9866000000475,2822.521548 +0.4,6000, 0.9213388438061042, 12875.938499999873, 5312.222200000114, 3079.1144160000003 +0.4,6000, 0.9981170807899462, 17540.921899999903, 7250.2881000000125,3335.707284 +0.4,9000,0, 504.1119863908427, 504.1119863908427,0 +0.4,9000, 0.45075888689407545,-2206.7393,-252.414,1506.4362 +0.4,9000, 0.5258853680430879,-551.2397, 302.5590999999988,1757.5089 +0.4,9000, 0.6010118491921005, 1104.2596000000121, 857.5321999999938,2008.5816 +0.4,9000, 0.6761383303411131, 2770.1293999999843, 1417.1211000000014,2259.6543 +0.4,9000, 0.7512648114901256,4862.4082, 2156.256800000008,2510.727 +0.4,9000, 0.8263912926391382, 7573.585399999938, 3174.4724000000497,2761.7997 +0.4,9000, 0.9015177737881509, 11153.245099999987, 4573.711400000064,3012.8724 +0.4,9000, 0.9766442549371633, 15268.127000000233, 6285.814899999968,3263.9451 +0.4,12000,0, 453.5295622640622, 453.5295622640622,0 +0.4,12000, 0.4408474254937163,-2305.549204,-320.3496, 1473.3120959999999 +0.4,12000, 0.5143219964093356,-768.8100288, 188.17093920000084, 1718.8641119999997 +0.4,12000, 0.5877965673249551, 767.9290016000155, 696.6913720000006, 1964.4161279999998 +0.4,12000, 0.6612711382405745, 2304.667965599983, 1205.211939999997,2209.968144 +0.4,12000, 0.7347457091561939,4138.79025, 1838.253679200001,2455.52016 +0.4,12000, 0.8082202800718132, 6506.763993599975, 2707.2267823999746, 2701.0721759999997 +0.4,12000, 0.8816948509874326, 9608.208797599986,3901.031196, 2946.6241919999998 +0.4,12000,0.955169422, 13166.092933599939, 5370.391927999954,3192.176208 +0.4,15000,0, 407.0430623664859, 407.0430623664859,0 +0.4,15000, 0.4309368904847397,-2148.7402,-313.154,1440.191088 +0.4,15000, 0.5027597055655296,-795.1206, 132.7379999999977,1680.222936 +0.4,15000, 0.5745825206463195, 558.4992999999782, 578.6300999999945,1920.254784 +0.4,15000, 0.6464053357271095, 1912.1190999999872, 1024.5221000000122,2160.286632 +0.4,15000, 0.7182281508078995, 3473.2656000000047, 1551.7954000000118,2400.31848 +0.4,15000, 0.7900509658886894, 5553.717300000019, 2300.0319999999783,2640.350328 +0.4,15000, 0.8618737809694794,8221.8076, 3310.4115999999863,2880.382176 +0.4,15000, 0.9336965960502693, 11327.861299999973, 4565.060499999995,3120.414024 +0.4,18000,0, 364.40427639783564, 364.40427639783564,0 +0.4,18000, 0.4210254290843806,-2004.833241,-313.2027304,1407.066984 +0.4,18000, 0.4911963339317774,-808.2493656, 81.80208079999984,1641.578148 +0.4,18000, 0.5613672387791742, 388.33448959999333, 476.80701519999946,1876.089312 +0.4,18000, 0.6315381436265709, 1584.918429600003, 871.8119583999967,2110.600476 +0.4,18000, 0.7017090484739678, 2934.3513151999905, 1321.2395383999988,2345.11164 +0.4,18000, 0.7718799533213645, 4714.4718808000125, 1946.0219240000013,2579.622804 +0.4,18000, 0.8420508581687612, 7037.441006399993, 2811.5908656000042,2814.133968 +0.4,18000,0.912221763, 9730.412950400061, 3878.3419480000066,3048.645132 +0.4,18000, 0.9823926678635548, 12651.102412000062, 5197.388753600004,3283.156296 +0.4,21000,0, 325.3724997702096, 325.3724997702096,0 +0.4,21000, 0.41111489407540397,-2090.576454,-362.8524752,1373.945976 +0.4,21000, 0.47963404308797125,-975.6670032,0.0911616,1602.936972 +0.4,21000, 0.5481531921005386, 139.24261519999845, 363.0348071999997,1831.927968 +0.4,21000, 0.6166723411131059, 1254.152327199999, 725.9783824000007,2060.918964 +0.4,21000, 0.6851914901256733, 2425.448144799999, 1110.0176167999998,2289.90996 +0.4,21000, 0.7537106391382405, 3981.1074608000063, 1644.1415824000026,2518.900956 +0.4,21000, 0.8222297881508079, 5964.462583200006, 2368.326612000003,2747.891952 +0.4,21000, 0.8907489371633752, 8313.523827199995, 3279.022960800002,2976.882948 +0.4,21000, 0.9592680861759425,10752.89742,4374.332284,3205.873944 +0.4,24000,0, 289.71977311505464, 289.71977311505464,0 +0.4,24000, 0.4012034326750449,-2282.463163,-475.014568,1340.821872 +0.4,24000, 0.46807067145421904,-1223.719465,-126.0729056, 1564.2921840000001 +0.4,24000, 0.5349379102333932,-164.9754408, 222.86868959999956,1787.762496 +0.4,24000, 0.6018051490125673, 893.7679231999969, 571.8101328000002,2011.232808 +0.4,24000, 0.6686723877917415, 1945.4615711999954, 915.9588543999971,2234.70312 +0.4,24000, 0.7355396265709157, 3347.2738919999906, 1385.9118903999984,2458.173432 +0.4,24000, 0.8024068653500898, 5076.371366400005, 1998.1921927999983,2681.643744 +0.4,24000, 0.8692741041292639, 7042.629872799978, 2746.5405759999967,2905.114056 +0.4,24000, 0.9361413429084381, 9151.862956800043, 3667.2089719999926, 3128.5843680000003 +0.4,27000,0, 257.22519309360155, 257.22519309360155,0 +0.4,27000, 0.3912928976660683,-1807.253207,-199.043764, 1307.7008640000001 +0.4,27000,0.456508381,-991.7983496, 38.99062080000045, 1525.6510080000003 +0.4,27000, 0.5217238635547576,-176.346304, 277.0228319999996, 1743.6011520000002 +0.4,27000, 0.5869393464991024, 639.1065927999852, 515.0550431999899,1961.551296 +0.4,27000,0.652154829, 1475.5717423999913, 755.6435880000065,2179.50144 +0.4,27000, 0.7173703123877918, 2716.5121944000152, 1128.1283631999827, 2397.4515840000004 +0.4,27000, 0.7825857953321366, 4217.788883200014, 1654.7635159999916, 2615.4017280000003 +0.4,27000, 0.8478012782764812, 5842.676319999998, 2330.4320287999926,2833.351872 +0.4,27000,0.913016761, 7939.485508800103, 3106.915513600064, 3051.3020160000005 +0.4,27000, 0.9782322441651707, 9155.313681600006, 3925.6477472000247, 3269.2521600000005 +0.4,30000,0, 227.6801423366946, 227.6801423366946,0 +0.4,30000, 0.38138143626570914,-2055.9148,-418.6676,1274.57676 +0.4,30000, 0.44494500897666067,-1153.926,-144.971,1487.00622 +0.4,30000, 0.5085085816876123,-251.9688, 128.73469999999205,1699.43568 +0.4,30000, 0.5720721543985637,650.004, 402.4347999999976,1911.86514 +0.4,30000, 0.6356357271095153, 1438.752899999973,630.7675,2124.2946 +0.4,30000, 0.6991992998204668, 1970.8082000000961, 908.0242000000571,2336.72406 +0.4,30000, 0.7627628725314183, 3357.552499999883, 1310.0274999999901,2549.15352 +0.4,30000, 0.8263264452423699, 4915.993799999826, 1801.4822999999126,2761.58298 +0.4,30000, 0.8898900179533213, 6883.9649999999465, 2789.628899999958,2974.01244 +0.4,30000, 0.9534535906642729, 9134.169400000219, 3543.909799999683, 3186.4419000000003 +0.4,33000,0,200.8814691,200.8814691,0 +0.4,33000, 0.37147090125673254, 2071.918154399991,-65.3686816,1241.455752 +0.4,33000, 0.4333827181328546, 1886.1142687999345, 72.74179039999981, 1448.3650440000001 +0.4,33000, 0.4952945350089767, 1700.3012543998755, 210.85097440000592, 1655.2743360000002 +0.4,33000, 0.5572063518850988, 1514.4866943999625, 348.96691119998786, 1862.1836280000002 +0.4,33000, 0.6191181687612208, 1328.6677551999628, 487.07063039998286,2069.09292 +0.4,33000,0.681029986, 1511.6516144000207, 720.1166008000149, 2276.0022120000003 +0.4,33000, 0.7429418025134651, 3305.1731415999616, 1341.6158408000108,2482.911504 +0.4,33000, 0.8048536193895872,4482.112683, 1733.6770800000518, 2689.8207960000004 +0.4,33000, 0.8667654362657092, 5088.722437599762, 1914.439790400013, 2896.7300880000003 +0.4,33000, 0.9286772531418314, 6215.402754400155, 2535.6401127999734, 3103.6393800000005 +0.4,33000, 0.9905890700179534, 2715.3993264003475, 271.1456615997158, 3310.5486720000004 +0.4,36000,0, 176.63833787526158, 176.63833787526158,0 +0.4,36000, 0.36155943985637345, 1531.2354000000068,-226.9224,1208.331648 +0.4,36000, 0.42181934649910235, 1419.7548999999472,-63.188,1409.720256 +0.4,36000, 0.48207925314183125, 1308.2534999998284, 100.54640000001775,1611.108864 +0.4,36000, 0.5423391597845602, 1196.7694999999637, 264.2827999999786,1812.497472 +0.4,36000,0.602599066, 1085.277099999953, 428.01029999996814,2013.88608 +0.4,36000,0.662858973, 1233.0794999999466, 588.1072000000377,2215.274688 +0.4,36000, 0.7231188797127469, 1967.3940000000218, 829.6739999999113,2416.663296 +0.4,36000, 0.7833787863554758, 1633.3106000001612, 1022.9355000000044,2618.051904 +0.4,36000, 0.8436386929982047, 7097.680099999437, 2279.5388000002094,2819.440512 +0.4,36000, 0.9038985996409336, 6256.716499999935, 2599.4552999998587,3020.82912 +0.4,36000, 0.9641585062836625, 3384.1849999997285, 710.9515999996339,3222.217728 +0.4,39000,0, 152.9821492144476, 152.9821492144476,0 +0.4,39000, 0.36126484739676845,-1328.5093,-394.786, 1207.3471200000001 +0.4,39000, 0.4214756552962298,-956.698,-235.4408, 1408.5716400000001 +0.4,39000, 0.48168646319569125,-584.9018,-76.0941,1609.79616 +0.4,39000, 0.5418972710951526,-213.0931, 83.25749999999019,1811.02068 +0.4,39000,0.602108079, 158.70370000004257, 242.60619999999753,2012.2452 +0.4,39000, 0.6623188868940754, 492.2061999999267, 375.91960000002126,2213.46972 +0.4,39000, 0.7225296947935369, 1484.3647999997984, 665.4487000000278, 2414.6942400000003 +0.4,39000, 0.7827405026929982, 2077.3499000001393, 881.1992000000447,2615.91876 +0.4,39000, 0.8429513105924596, 3860.6915000001327, 1073.0338000002043, 2817.1432800000002 +0.4,39000,0.903162118,4961.6513, 2057.897600000303,3018.3678 +0.4,39000, 0.9633729263913825, 11464.825500000024, 6025.860700000524,3219.59232 +0.4,42000,0, 132.44015681024968, 132.44015681024968,0 +0.4,42000, 0.36126484739676845,-55155.42354,-21038.60863, 1207.3471200000001 +0.4,42000, 0.4214756552962298,-43219.89844,-16428.95808, 1408.5716400000001 +0.4,42000, 0.48168646319569125,-31284.37919,-11819.30371,1609.79616 +0.4,42000, 0.5418972710951526,-19348.87544,-7209.642431,1811.02068 +0.4,42000,0.602108079,-7413.358625,-2600.003256,2012.2452 +0.4,42000, 0.6623188868940754,-1193.685331,-249.7196,2213.46972 +0.4,42000, 0.7225296947935369, 1960.611162499872, 644.6076812500502, 2414.6942400000003 +0.4,42000, 0.7827405026929982, 730.4577687500287, 742.7688000001347,2615.91876 +0.4,42000, 0.8429513105924596, 4959.910287500137, 2406.4227625000008, 2817.1432800000002 +0.4,42000,0.903162118, 2620.2034249999306, 1161.5412500001694,3018.3678 +0.4,42000, 0.9633729263913825, 7330.556506250279, 4092.741225000631,3219.59232 +0.45,0,0, 700.0801797612189, 700.0801797612189,0 +0.45,0, 0.48444895421903045,-1957.03495, 37.69040000000001, 1619.0284049999998 +0.45,0, 0.5651904465888689, 21.957100000003265,753.0929, 1888.8664724999999 +0.45,0, 0.6459319389587073, 2000.9496500000573, 1468.495799999914, 2158.7045399999997 +0.45,0, 0.7266734313285457,4478.61795, 2317.0561000001526, 2428.5426074999996 +0.45,0, 0.8074149236983841, 7451.707250000847, 3502.420649999905, 2698.3806749999994 +0.45,0, 0.8881564160682225, 10753.29930000068, 5106.915250000233, 2968.2187424999997 +0.45,0, 0.9688979084380609, 15828.844000001009, 7274.212600000403, 3238.0568099999996 +0.45,3000,0, 634.0146874708897, 634.0146874708897,0 +0.45,3000, 0.47445679174147215,-1796.128351,-34.76444813, 1585.6345979999999 +0.45,3000, 0.5535329236983841,-4.540111183, 619.5601725047652, 1849.9070309999997 +0.45,3000, 0.6326090556552961, 1787.0484633081803, 1273.8849800307673,2114.179464 +0.45,3000, 0.7116851876122082, 3770.802263345414, 2002.1491059367556,2378.451897 +0.45,3000, 0.7907613195691203, 6548.778538851607, 3041.3102339725506,2642.72433 +0.45,3000, 0.8698374515260322, 10052.928444097217, 4456.011219709164, 2906.9967629999996 +0.45,3000, 0.9489135834829443, 14817.911338693037,6437.991585, 3171.2691959999997 +0.45,6000,0, 572.9733123948596, 572.9733123948596,0 +0.45,6000, 0.4644636952423699,-2049.6963,-125.0056, 1552.2376695000003 +0.45,6000, 0.5418743111160982,-324.2031, 480.8055000000044, 1810.9439477500002 +0.45,6000, 0.6192849269898265, 1401.2902999999785, 1086.6167000000137,2069.650226 +0.45,6000, 0.6966955428635548, 3221.1557999999964, 1734.3525000000222, 2328.3565042500004 +0.45,6000, 0.7741061587372831, 5625.920900000156, 2623.0971999999456,2587.062783 +0.45,6000, 0.8515167746110115, 8795.058599999751, 3866.755400000111, 2845.7690607500003 +0.45,6000, 0.9289273904847398, 12959.425799999723, 5575.212400000224, 3104.4753390000005 +0.45,9000,0, 516.6711186686733, 516.6711186686733,0 +0.45,9000, 0.45447153276481145,-2181.1902,-228.1027,1518.843863 +0.45,9000, 0.5302167882256134,-563.1777, 337.4621000000017, 1771.9845062499999 +0.45,9000, 0.6059620436864153, 1054.834699999966, 903.0270000000058, 2025.1251499999998 +0.45,9000, 0.6817072991472172, 2703.822300000023, 1482.3687999999972,2278.265794 +0.45,9000, 0.7574525546080191, 4820.762700000048, 2256.1581999999953,2531.406438 +0.45,9000,0.83319781, 7577.894000000029, 3320.918000000023,2784.547081 +0.45,9000, 0.9089430655296229, 11215.82320000009, 4795.226099999938,3037.687725 +0.45,9000, 0.9846883209904248, 15292.752900000112, 6569.528800000084, 3290.8283687499998 +0.45,12000,0, 464.82851550887733, 464.82851550887733,0 +0.45,12000, 0.4444784362657091,-2217.08773,-298.7033952, 1485.4469339999998 +0.45,12000, 0.5185581756433273,-730.553152, 219.82969840000158, 1733.0214229999997 +0.45,12000, 0.5926379150209454, 755.9814679999953, 738.3626920000032, 1980.5959119999998 +0.45,12000, 0.6667176543985637, 2241.808226400012, 1256.5811488000033,2228.170401 +0.45,12000, 0.7407973937761819, 4085.417782399986, 1920.3996080000038,2475.74489 +0.45,12000,0.814877133, 6517.659347200003, 2839.2711984000275, 2723.3193789999996 +0.45,12000, 0.8889568725314182, 9678.488119199943, 4098.610881600032, 2970.8938679999997 +0.45,12000, 0.9630366119090364, 13226.14387360014, 5635.884553599994, 3218.4683569999997 +0.45,15000,0, 417.18387988529514, 417.18387988529514,0 +0.45,15000, 0.4344862737881508,-2248.1765,-334.0147,1452.053127 +0.45,15000, 0.5069006527528426,-885.0414, 132.60320000000033,1694.061982 +0.45,15000, 0.5793150317175344, 478.0936999999731, 599.2211000000017, 1936.0708359999999 +0.45,15000, 0.6517294106822261, 1841.228900000012, 1065.8390000000138, 2178.0796904999997 +0.45,15000,0.72414379, 3426.262700000081, 1625.1362000000022, 2420.0885449999996 +0.45,15000, 0.7965581686116098, 5560.950700000007, 2412.0569000000614,2662.0974 +0.45,15000, 0.8689725475763016, 8306.400400000102, 3482.9608999999764,2904.106254 +0.45,15000, 0.9413869265409933, 11366.819300000034, 4794.442900000058, 3146.1151084999997 +0.45,18000,0, 373.4828177407096, 373.4828177407096,0 +0.45,18000, 0.42449317728904845,-2042.914529,-320.9311144, 1418.6561984999998 +0.45,18000, 0.4952420401705565,-852.7941616, 88.48378879999879, 1655.0988982499998 +0.45,18000, 0.5659909030520646, 337.32636559999014, 497.8986271999961, 1891.5415979999998 +0.45,18000, 0.6367397659335726, 1527.447005600008, 907.3134623999873, 2127.9842977499998 +0.45,18000, 0.7074886288150807, 2879.140647199961, 1378.1528223999953, 2364.4269974999997 +0.45,18000, 0.7782374916965887, 4695.796328800072, 2036.702904000002, 2600.8696972499997 +0.45,18000, 0.8489863545780969, 7087.478010399991, 2955.119881600004, 2837.3123969999997 +0.45,18000,0.919735217, 9753.165534400208, 4068.4822480000066, 3073.7550967499997 +0.45,18000,0.99048408, 12682.644692000187, 5434.405169599993, 3310.1977964999996 +0.45,21000,0, 333.4786277229266, 333.4786277229266,0 +0.45,21000, 0.4145010148114901,-1995.245298,-348.5639272,1385.262392 +0.45,21000, 0.4835845172800718,-920.2198752, 21.385837599999846,1616.139457 +0.45,21000, 0.5526680197486534, 154.8055472000045, 391.33559919999914,1847.016522 +0.45,21000, 0.6217515222172351, 1229.830999200002,761.2854664, 2077.8935872499997 +0.45,21000, 0.6908350246858168, 2390.0780327999887, 1162.5720247999934,2308.770653 +0.45,21000, 0.7599185271543986, 3971.2064287999724, 1723.096666399986,2539.647718 +0.45,21000, 0.8290020296229802, 6011.445315199985, 2492.4144719999917,2770.524783 +0.45,21000, 0.8980855320915618, 8327.789999199958, 3437.953708799992, 3001.4018482499996 +0.45,21000, 0.9671690345601436, 10831.576913599956, 4602.314423999992,3232.278914 +0.45,24000,0,296.9376712,296.9376712,0 +0.45,24000, 0.4045079183123878,-2081.428431,-400.598328,1351.865463 +0.45,24000, 0.4719259046977857,-1081.008077,-60.5732096,1577.176374 +0.45,24000, 0.5393438910831837,-80.5878728, 279.4519135999998,1802.487284 +0.45,24000, 0.6067618774685817, 919.8322911999998, 619.4770647999999, 2027.7981945000001 +0.45,24000, 0.6741798638539797, 1924.3391992000036, 961.1961104000004,2253.109105 +0.45,24000, 0.7415978502393776, 3292.9577319999994, 1439.0206064000013,2478.420016 +0.45,24000, 0.8090158366247756,5058.802582, 2088.121244799998,2703.730926 +0.45,24000, 0.8764338230101736, 7044.421964800007, 2884.7883960000054,2929.041837 +0.45,24000, 0.9438518093955715, 9175.571628799988, 3850.600191999998,3154.352747 +0.45,27000,0, 263.6335414615541, 263.6335414615541,0 +0.45,27000, 0.39451575583482945,-2125.689975,-401.133764,1318.471656 +0.45,27000, 0.46026838180730095,-1212.561374,-100.9794872, 1538.2169319999998 +0.45,27000, 0.5260210077797726,-299.433584, 199.1741120000002,1757.962208 +0.45,27000, 0.5917736337522441,613.6945248, 499.3277111999971,1977.707484 +0.45,27000, 0.6575262597247158, 1533.4883383999988, 800.8446480000013,2197.45276 +0.45,27000, 0.7232788856971872, 2704.9806904000047, 1194.7192511999965,2417.198036 +0.45,27000, 0.7890315116696589, 4235.971591199998, 1747.7220959999943,2636.943312 +0.45,27000, 0.8547841376421305, 5958.2961399999795, 2433.889520799993,2856.688588 +0.45,27000, 0.9205367636146019, 7877.412180800003, 3246.5289576000127, 3076.4338639999996 +0.45,27000, 0.9862893895870736, 9363.715645600007, 4112.045375199989, 3296.1791399999997 +0.45,30000,0, 233.3524236984492, 233.3524236984492,0 +0.45,30000, 0.38452265933572716,-2119.2681,-468.6787,1285.074728 +0.45,30000,0.448609769,-1246.3005,-180.7702,1499.253849 +0.45,30000, 0.5126968791143028,-373.3472, 107.14219999999837,1713.43297 +0.45,30000, 0.5767839890035906, 499.6130000000109, 395.0520999999982,1927.612091 +0.45,30000, 0.6408710988928786, 1327.2838999999876, 664.8154999999888, 2141.7912125000003 +0.45,30000, 0.7049582087821664, 2084.7233000000356, 971.2114000000213,2355.970334 +0.45,30000, 0.7690453186714543, 3438.4736999999427, 1419.6817999999903,2570.149455 +0.45,30000, 0.8331324285607421, 5001.601799999912, 1979.9136999999562,2784.328576 +0.45,30000,0.897219538, 6745.027799999972, 2802.2571999999814,2998.507698 +0.45,30000, 0.9613066483393178, 8543.964800000062, 3595.8045999998685,3212.686819 +0.45,33000,0, 205.88610495794342, 205.88610495794342,0 +0.45,33000, 0.3745304968581688,-79.3292376,-312.7224536, 1251.6809205000002 +0.45,33000, 0.4369522463345303, 217.7307447999642,-105.2325816, 1460.2944072500002 +0.45,33000, 0.49937399581089176, 514.7858223999299, 102.25646240000151, 1668.9078940000002 +0.45,33000, 0.5617957452872532,811.8401824, 309.74895519999257, 1877.5213807500002 +0.45,33000, 0.6242174947636148, 1108.8922791999812, 517.2353783999948, 2086.1348675000004 +0.45,33000, 0.6866392442399761, 1635.2080824000109, 787.2769368000093, 2294.7483542500004 +0.45,33000, 0.7490609937163376, 3074.0255135999737, 1293.7390168000143, 2503.3618410000004 +0.45,33000, 0.8114827431926991, 4342.638807200094, 1748.3225400000283, 2711.9753277500004 +0.45,33000, 0.8739044926690606, 5396.402349599932, 2161.4751584000355, 2920.5888145000004 +0.45,33000,0.936326242, 6445.206122400138, 2739.0730888000144, 3129.2023012500003 +0.45,33000, 0.9987479916217835,4940.574534, 1760.5197135999297, 3337.8157880000003 +0.45,36000,0, 181.03899548825387, 181.03899548825387,0 +0.45,36000, 0.36453740035906645,-448.6355,-415.5566, 1218.2839920000001 +0.45,36000, 0.42529363375224416,-138.5643,-207.957,1421.331324 +0.45,36000, 0.4860498671454219, 171.49619999991523,-0.3574,1624.378656 +0.45,36000, 0.5468061005385997, 481.56579999997996, 207.2431999999886, 1827.4259880000002 +0.45,36000, 0.6075623339317774, 791.6308999999759, 414.8392999999842,2030.47332 +0.45,36000, 0.6683185673249552, 1243.2101999999709, 622.8302000000187,2233.520652 +0.45,36000, 0.7290748007181329, 2049.386300000002, 901.6311999999454, 2436.5679840000003 +0.45,36000, 0.7898310341113107, 2438.017200000094, 1213.961100000009, 2639.6153160000003 +0.45,36000, 0.8505872675044883, 5870.608399999759, 2102.879300000094,2842.662648 +0.45,36000, 0.9113435008976661, 5930.014399999951,2558.2373,3045.70998 +0.45,36000, 0.9720997342908438, 4408.108099999841, 1604.074299999797,3248.757312 +0.45,39000,0, 156.79345126637196, 156.79345126637196,0 +0.45,39000,0.364240382,-1539.3459,-433.0079,1217.291355 +0.45,39000, 0.4249471117594255,-1096.7203,-255.6364, 1420.1732475000001 +0.45,39000, 0.48565384201077205,-654.102,-78.2639, 1623.0551400000002 +0.45,39000, 0.5463605722621185,-211.4771, 99.11109999999593, 1825.9370325000002 +0.45,39000, 0.6070673025134651, 231.1413000000233, 276.48459999999864, 2028.8189250000003 +0.45,39000, 0.6677740327648115, 669.1399999999619, 441.4119000000078,2231.700818 +0.45,39000,0.728480763, 1571.8701999998975, 727.7795000000114,2434.58271 +0.45,39000, 0.7891874932675046, 2355.795200000056, 1022.9601000000242,2637.464603 +0.45,39000,0.849894224, 3797.994900000074, 1321.7634000000967, 2840.3464950000002 +0.45,39000, 0.9106009537701976, 4790.425300000062, 2067.881900000144, 3043.2283875000003 +0.45,39000, 0.9713076840215441, 8270.470799999934, 4225.105400000233, 3246.1102800000003 +0.45,42000,0, 135.7396884484182, 135.7396884484182,0 +0.45,42000,0.364240382,-36867.10241,-14004.37968,1217.291355 +0.45,42000, 0.4249471117594255,-28864.98024,-10914.06003, 1420.1732475000001 +0.45,42000, 0.48565384201077205,-20862.86109,-7823.738244, 1623.0551400000002 +0.45,42000, 0.5463605722621185,-12860.75201,-4733.411994, 1825.9370325000002 +0.45,42000, 0.6070673025134651,-4858.63465,-1643.099494, 2028.8189250000003 +0.45,42000, 0.6677740327648115,-518.1820938, 1.6314749999515925,2231.700818 +0.45,42000,0.728480763, 1684.176812499912, 653.6703437500308,2434.58271 +0.45,42000, 0.7891874932675046, 1267.6219312500225, 828.6935500000769,2637.464603 +0.45,42000,0.849894224, 4188.432212500062, 1995.3981874999993, 2840.3464950000002 +0.45,42000, 0.9106009537701976, 3163.467474999914, 1442.0361750000816, 3043.2283875000003 +0.45,42000, 0.9713076840215441, 6587.986218750055, 3562.4474000003593, 3246.1102800000003 +0.5,0,0, 719.4314612671865, 719.4314612671865,0 +0.5,0, 0.4888720825852782,-2671.8684, 32.758699999999806, 1633.8104999999998 +0.5,0,0.570350763,-449.1081, 779.4904999999499, 1906.1122499999997 +0.5,0, 0.6518294434470376, 1773.6538000001156, 1526.2232999998648, 2178.4139999999998 +0.5,0, 0.7333081238779173, 4378.321799999829, 2426.6747000002115,2450.71575 +0.5,0, 0.8147868043087971, 6999.002800001287, 3647.612599999831,2723.0175 +0.5,0, 0.8962654847396767, 9737.890400001086, 5289.231700000313, 2995.3192499999996 +0.5,0, 0.9777441651705564, 15257.612100001203,7555.2814, 3267.6209999999996 +0.5,3000,0, 651.5398182357003, 651.5398182357003,0 +0.5,3000, 0.4787886894075404,-1671.107484,5.00538285,1600.1118 +0.5,3000,0.558586804, 13.275047991812663, 669.3687714265706, 1866.7970999999998 +0.5,3000, 0.6383849192100538, 1697.6601824443974, 1333.7336254859874,2133.4824 +0.5,3000, 0.7181830341113106, 3635.0820330029937, 2087.9470674585764,2400.1677 +0.5,3000, 0.7979811490125673, 6571.444319536395, 3191.7589686606066,2666.853 +0.5,3000,0.877779264, 10002.666208570048, 4663.660854219054, 2933.5382999999997 +0.5,3000, 0.9575773788150808, 14493.51879823957, 6706.772401393939,3200.2236 +0.5,6000,0, 588.8111666636969, 588.8111666636969,0 +0.5,6000, 0.46870435368043095,-2323.4404,-95.1125, 1566.4099500000002 +0.5,6000, 0.5468217459605027,-537.0041, 523.0816000000067, 1827.4782750000002 +0.5,6000, 0.6249391382405746, 1249.4337999999539, 1141.2758000000201,2088.5466 +0.5,6000, 0.7030565305206464, 3131.3496999999998, 1813.3182000000352, 2349.6149250000003 +0.5,6000, 0.7811739228007182, 5635.994200000299, 2747.6319999998914,2610.68325 +0.5,6000,0.859291315, 8788.324299999487, 4048.3206000002106, 2871.7515750000002 +0.5,6000, 0.9374087073608619, 13071.733399999477, 5872.367700000376, 3132.8199000000004 +0.5,9000,0, 530.9526946258313, 530.9526946258313,0 +0.5,9000,0.458620961,-2094.958,-195.2897,1532.71125 +0.5,9000, 0.5350577872531418,-526.4189, 380.4171000000015,1788.163125 +0.5,9000, 0.6114946140035906, 1042.120000000015,956.124,2043.615 +0.5,9000, 0.6879314407540394, 2662.1138000000014, 1556.1228000000012,2299.066875 +0.5,9000, 0.7643682675044884, 4775.583500000009, 2364.992699999983,2554.51875 +0.5,9000, 0.8408050942549371, 7591.811000000019, 3485.4104000000293,2809.970625 +0.5,9000,0.917241921, 11306.148399999965, 5046.372599999943,3065.4225 +0.5,9000, 0.9936787477558348, 15293.14839999986, 6872.208499999927,3320.874375 +0.5,12000,0, 477.6770830239316, 477.6770830239316,0 +0.5,12000, 0.4485366247755835,-2187.265426,-271.2716776,1499.0094 +0.5,12000, 0.5232927289048473,-726.79402, 257.4959855999987,1748.8443 +0.5,12000, 0.5980488330341113, 733.6773127999961, 786.2635487999963,1998.6792 +0.5,12000, 0.6728049371633752, 2198.0139392000056, 1316.603116000014,2248.5141 +0.5,12000, 0.7475610412926392, 4042.146279200021, 2012.5947200000026,2498.349 +0.5,12000,0.822317145, 6520.894839200028, 2982.3744815999744,2748.1839 +0.5,12000,0.89707325, 9754.751044000044, 4315.032924000043,2998.0188 +0.5,12000, 0.9718293536804309, 13291.537559200007, 5923.305263999999,3247.8537 +0.5,15000,0, 428.71547716914586, 428.71547716914586,0 +0.5,15000, 0.4384532315978456,-2261.0837,-339.0793,1465.3107 +0.5,15000, 0.5115287701974865,-906.3853, 146.08440000000186,1709.52915 +0.5,15000, 0.5846043087971275, 448.31319999998357, 631.2480000000036, 1953.7476000000001 +0.5,15000, 0.6576798473967684, 1803.0116999999882, 1116.4117000000044,2197.96605 +0.5,15000, 0.7307553859964094, 3403.829100000003, 1708.3110000000179, 2442.1845000000003 +0.5,15000, 0.8038309245960503, 5551.820799999937, 2532.8901000000446,2686.40295 +0.5,15000, 0.8769064631956912, 8343.470700000102, 3663.9961000000026,2930.6214 +0.5,15000, 0.9499820017953322, 11431.692400000118, 5044.930700000068, 3174.8398500000003 +0.5,18000,0, 383.8064511653947, 383.8064511653947,0 +0.5,18000, 0.4283688958707361,-2094.154206,-339.0485784,1431.60885 +0.5,18000, 0.4997637118491921,-902.8737944,89.6265032,1670.210325 +0.5,18000, 0.5711585278276481, 288.4068280000008, 518.3015552000043,1908.8118 +0.5,18000, 0.6425533438061041, 1479.6873872000026, 946.9766072000012,2147.413275 +0.5,18000,0.71394816, 2838.9128223999755, 1442.4125631999755,2386.01475 +0.5,18000,0.785342976, 4697.477005600005, 2144.3397479999567, 2624.6162249999998 +0.5,18000, 0.8567377917414722, 7142.300167199911, 3115.1651495999827,2863.2177 +0.5,18000, 0.9281326077199282, 9817.644064799792, 4284.701770399893,3101.819175 +0.5,18000, 0.9995274236983842, 12759.608622399688, 5696.337651200022,3340.42065 +0.5,21000,0, 342.6964844596952, 342.6964844596952,0 +0.5,21000, 0.41828550269299825,-1938.541402,-331.9819592, 1397.9101500000002 +0.5,21000, 0.48799975314183125,-889.0242272, 45.69395359999921,1630.895175 +0.5,21000, 0.5577140035906643, 160.49295920000904, 423.3698711999971,1863.8802 +0.5,21000, 0.6274282540394973, 1210.0100512000092, 801.0458104000076,2096.865225 +0.5,21000, 0.6971425044883304, 2370.8345407999664, 1221.1458527999764,2329.85025 +0.5,21000, 0.7668567549371633, 3954.6705167999135, 1808.525510399951,2562.835275 +0.5,21000, 0.8365710053859965, 6062.115827199925,2627.494332, 2795.8203000000003 +0.5,21000, 0.9062852558348296, 8391.195551199897, 3625.281976799994, 3028.8053250000003 +0.5,21000, 0.9759995062836625, 10947.833549599862, 4860.964163999991,3261.79035 +0.5,24000,0, 305.14548031904746, 305.14548031904746,0 +0.5,24000, 0.4082011669658887,-1947.670679,-367.504588,1364.2083 +0.5,24000, 0.4762346947935368,-988.9591088,-25.0945536,1591.57635 +0.5,24000, 0.5442682226211849,-30.2477248, 317.31547760000126,1818.9444 +0.5,24000, 0.6123017504488331, 928.4636392000017, 659.7256168000013, 2046.3124500000001 +0.5,24000, 0.6803352782764811, 1919.6853072000154, 1014.1695264000023,2273.6805 +0.5,24000, 0.7483688061041293, 3285.743072000008, 1511.5637824000041,2501.04855 +0.5,24000, 0.8164023339317774, 5083.210358400028, 2198.3483167999907,2728.4166 +0.5,24000, 0.8844358617594255,7101.839377, 3041.490716000025,2955.78465 +0.5,24000, 0.9524693895870736, 9226.396620799947, 4053.310012000032,3183.1527 +0.5,27000,0, 270.9207737282607, 270.9207737282607,0 +0.5,27000, 0.39811777378815083,-2136.526123,-450.559164,1330.5096 +0.5,27000,0.464470736,-1216.082738,-127.1994752, 1552.2612000000001 +0.5,27000, 0.5308236983842012,-295.639364, 196.16019199999985, 1774.0128000000002 +0.5,27000, 0.5971766606822263, 624.8040767999979,519.5198592, 1995.7644000000003 +0.5,27000, 0.6635296229802514, 1544.4331943999975, 842.6577080000003,2217.516 +0.5,27000, 0.7298825852782765, 2710.016146400001,1261.690519,2439.2676 +0.5,27000, 0.7962355475763017, 4258.356579200003, 1841.4073760000022,2661.0192 +0.5,27000, 0.8625885098743268,6031.02936, 2556.346932800003, 2882.7708000000002 +0.5,27000,0.928941472, 7875.958372800001, 3409.170541600001, 3104.5224000000003 +0.5,27000, 0.9952944344703771, 9494.501449600015, 4322.023083200004, 3326.2740000000003 +0.5,30000,0, 239.8026397903099, 239.8026397903099,0 +0.5,30000, 0.3880334380610413,-2138.9726,-486.7573,1296.80775 +0.5,30000, 0.4527056777378815,-1286.5636,-189.0031,1512.942375 +0.5,30000, 0.5173779174147217,-434.1592, 108.7522000000004,1729.077 +0.5,30000, 0.5820501570915619, 418.2473000000023, 406.50669999999934,1945.211625 +0.5,30000, 0.6467223967684022, 1259.3316999999965, 699.7248999999965,2161.34625 +0.5,30000, 0.7113946364452425, 2165.2414000000063, 1035.9325000000042,2377.480875 +0.5,30000, 0.7760668761220826, 3503.840399999981, 1520.5798999999922,2593.6155 +0.5,30000, 0.8407391157989228, 5078.297899999971, 2132.051899999985,2809.750125 +0.5,30000,0.905411355,6705.9823, 2882.2078999999935,3025.88475 +0.5,30000, 0.9700835951526032, 8221.598600000001, 3691.4025999999676,3242.019375 +0.5,33000,0, 211.57711020332442, 211.57711020332442,0 +0.5,33000, 0.3779500448833034,-1380.47969,-457.1974856,1263.10905 +0.5,33000, 0.4409417190305207,-790.0097992,-205.1319136, 1473.6272250000002 +0.5,33000, 0.5039333931777379,-199.5420696, 46.93319039999984,1684.1454 +0.5,33000, 0.5669250673249552, 390.9254103999895, 298.99971919999604,1894.663575 +0.5,33000, 0.6299167414721724,981.3919232, 551.0638663999994,2105.18175 +0.5,33000, 0.6929084156193897, 1715.9610904000047, 846.8171528000048, 2315.6999250000003 +0.5,33000, 0.7559000897666068, 2950.937645599985, 1294.5644728000098,2526.2181 +0.5,33000, 0.8188917639138241, 4283.182251200047, 1800.029100000015,2736.736275 +0.5,33000, 0.8818834380610414, 5594.076821599999, 2358.2144664000275, 2947.2544500000004 +0.5,33000, 0.9448751122082586, 6646.168030400089, 2951.302144800023,3157.772625 +0.5,36000,0, 186.04318881714622, 186.04318881714622,0 +0.5,36000, 0.36786570915619393,-1620.7509,-524.7892,1229.4072 +0.5,36000, 0.42917666068222626,-1058.968,-288.2724, 1434.3084000000001 +0.5,36000, 0.4904876122082586,-497.1895,-51.7556, 1639.2096000000001 +0.5,36000, 0.5517985637342909, 64.59289999999119, 184.76159999999524, 1844.1108000000002 +0.5,36000, 0.6131095152603232, 626.3732999999901, 421.27699999999356,2049.012 +0.5,36000, 0.6744204667863555, 1261.599999999987, 662.8181000000078,2253.9132 +0.5,36000, 0.7357314183123879, 2126.835699999995,973.8745,2458.8144 +0.5,36000, 0.7970423698384203, 2971.6239000000483, 1369.118100000008, 2663.7156000000004 +0.5,36000, 0.8583533213644525, 5130.288699999933, 2042.286500000029, 2868.6168000000002 +0.5,36000, 0.9196642728904848, 5736.3086999999605, 2573.4875999999626,3073.518 +0.5,36000, 0.9809752244165172, 5137.506199999903, 2244.860799999908, 3278.4192000000003 +0.5,39000,0, 161.12746085764857, 161.12746085764857,0 +0.5,39000, 0.36756597845601446,-1726.1108,-466.5846, 1228.4055000000003 +0.5,39000, 0.42882697486535015,-1225.5562,-273.233, 1433.1397500000003 +0.5,39000, 0.4900879712746859,-725.0043,-79.8808, 1637.8740000000003 +0.5,39000, 0.5513489676840216,-224.4495,113.4724, 1842.6082500000002 +0.5,39000, 0.6126099640933573, 276.1023000000118, 306.8249999999995, 2047.3425000000002 +0.5,39000,0.673870961, 795.7262999999846,499.3816,2252.07675 +0.5,39000, 0.7351319569120289, 1646.6391999999578, 789.8024000000033, 2456.8110000000006 +0.5,39000, 0.7963929533213646,2559.8728,1141.4458, 2661.5452500000006 +0.5,39000, 0.8576539497307003, 3782.2465000000298, 1519.7314000000338, 2866.2795000000006 +0.5,39000, 0.9189149461400361, 4713.096799999996, 2121.9801000000493, 3071.0137500000005 +0.5,39000, 0.9801759425493718, 6383.878099999913, 3189.4236000000706, 3275.7480000000005 +0.5,42000,0, 139.49173999713312, 139.49173999713312,0 +0.5,42000, 0.36756597845601446,-23385.55479,-8821.614925, 1228.4055000000003 +0.5,42000, 0.42882697486535015,-18281.36054,-6848.171775, 1433.1397500000003 +0.5,42000, 0.4900879712746859,-13177.16749,-4874.727631, 1637.8740000000003 +0.5,42000, 0.5513489676840216,-8072.980487,-2901.280806, 1842.6082500000002 +0.5,42000, 0.6126099640933573,-2968.788675,-927.8417813, 2047.3425000000002 +0.5,42000,0.673870961,-32.00730625, 190.2931499999671,2252.07675 +0.5,42000, 0.7351319569120289, 1502.8007624999439, 673.1918562500176, 2456.8110000000006 +0.5,42000, 0.7963929533213646, 1665.6874437500146,912.7747, 2661.5452500000006 +0.5,42000, 0.8576539497307003, 3668.1112375000225, 1733.7325124999986, 2866.2795000000006 +0.5,42000, 0.9189149461400361, 3546.0393249999197, 1661.8001000000272, 3071.0137500000005 +0.5,42000, 0.9801759425493718, 5985.872581249946, 3168.515975000172, 3275.7480000000005 +0.55,0,0, 741.2309539750436, 741.2309539750436,0 +0.55,0, 0.49376080341113104,-3974.053075,-2.9553, 1650.1486049999999 +0.55,0, 0.5760542706463195,-1248.03395, 791.9182999999266,1925.173373 +0.55,0,0.658347738, 1477.9886750002056, 1586.7938999998005,2200.19814 +0.55,0, 0.7406412051166966,4294.256925,2552.2277,2475.222908 +0.55,0, 0.8229346723518851, 6245.607175001839, 3795.675774999729,2750.247675 +0.55,0, 0.9052281395870736, 8101.429300001626, 5449.917925000403,3025.272443 +0.55,0, 0.9875216068222621, 14492.442100001324,7846.66085, 3300.2972099999997 +0.55,3000,0, 671.2821262680602, 671.2821262680602,0 +0.55,3000, 0.48357657630161577,-1432.397676, 52.97974602761698, 1616.1129179999998 +0.55,3000, 0.5641726723518851,84.17923157, 726.8085357483799, 1885.4650709999999 +0.55,3000, 0.6447687684021544, 1600.763610180626, 1400.6415365412192,2154.817224 +0.55,3000, 0.7253648644524237, 3473.5074754605685,2182.719794, 2424.1693769999997 +0.55,3000,0.805960961, 6711.016354621169, 3362.7915673486837,2693.52153 +0.55,3000, 0.8865570565529622, 9967.947791443024, 4893.651618128972,2962.873683 +0.55,3000, 0.9671531526032315, 13630.323596386326, 6929.369597786992, 3232.2258359999996 +0.55,6000,0, 606.6527338247736, 606.6527338247736,0 +0.55,6000, 0.4733913972172353,-2990.475,-65.2126, 1582.0740495000002 +0.55,6000, 0.5522899634201077,-1009.9926, 567.1488000000096, 1845.7530577500002 +0.55,6000, 0.6311885296229803,970.4946, 1199.5103000000274, 2109.4320660000003 +0.55,6000, 0.7100870958258529, 3019.591300000012, 1898.9174000000519, 2373.1110742500005 +0.55,6000, 0.7889856620287254, 5758.484000000499, 2892.714199999804, 2636.7900825000006 +0.55,6000, 0.8678842282315979, 8693.277599999106, 4221.0170000003645, 2900.4690907500003 +0.55,6000, 0.9467827944344706, 13161.28219999912, 6201.716500000577, 3164.1480990000005 +0.55,9000,0, 547.0410922256885, 547.0410922256885,0 +0.55,9000, 0.4632071701077199,-1970.876741,-155.6626929,1548.038363 +0.55,9000, 0.5404083651256733,-459.3171268, 430.15506607143146, 1806.0447562499999 +0.55,9000, 0.6176095601436266, 1052.2420142857447, 1015.9728607142878,2064.05115 +0.55,9000, 0.6948107551615798, 2637.095010714283, 1638.6212839285743, 2322.0575437499997 +0.55,9000, 0.7720119501795331, 4737.155516071457, 2485.621998214252, 2580.0639374999996 +0.55,9000, 0.8492131451974864, 7626.859844642899, 3671.9032053572005, 2838.0703312499995 +0.55,9000, 0.9264143402154398, 11417.029544642775, 5327.190191071331,3096.076725 +0.55,12000,0, 492.15117631663975, 492.15117631663975,0 +0.55,12000, 0.4530219910233393,-2116.796359,-238.5194035,1513.999494 +0.55,12000, 0.5285256561938958,-692.9638734, 300.76422051767537,1766.332743 +0.55,12000, 0.6040293213644524, 730.8686215593578, 840.0477441287824,2018.665992 +0.55,12000, 0.6795329865350089, 2174.6392446969744, 1388.8844814078263,2270.999241 +0.55,12000, 0.7550366517055654, 4040.3970987689113, 2121.569023042914,2523.33249 +0.55,12000, 0.8305403168761221, 6529.060111805493, 3137.3830963067867,2775.665739 +0.55,12000, 0.9060439820466786, 9822.104707260094, 4549.432408270185,3027.998988 +0.55,12000, 0.9815476472172352, 13402.779552051634, 6231.9989891413825,3280.332237 +0.55,15000,0, 441.7059848428481, 441.7059848428481,0 +0.55,15000,0.442837764,-2244.3843,-311.1171, 1479.9638069999999 +0.55,15000, 0.5166440578994613,-904.5432, 184.2204000000013, 1726.6244414999999 +0.55,15000, 0.5904503518850988, 435.2979999999981, 679.5579000000037,1973.285076 +0.55,15000,0.664256646, 1775.1393000000053, 1174.895500000011, 2219.9457104999997 +0.55,15000, 0.7380629398563734, 3403.266100000056, 1800.471300000021, 2466.6063449999997 +0.55,15000, 0.8118692338420107, 5568.138700000022, 2669.2791000000393, 2713.2669794999997 +0.55,15000,0.885675528, 8425.525400000059, 3873.221400000082, 2959.9276139999997 +0.55,15000, 0.9594818218132853, 11567.98339999998, 5329.789100000073, 3206.5882484999997 +0.55,18000,0, 395.4361704421573, 395.4361704421573,0 +0.55,18000, 0.4326525848294434,-2211.981542,-357.7548824, 1445.9249384999998 +0.55,18000,0.504761349,-995.9855, 92.51225280000001,1686.912428 +0.55,18000, 0.5768701131059245, 220.01065520000793, 542.7794776000015, 1927.8999179999998 +0.55,18000, 0.6489788772441651, 1436.0066944000073,993.0467024,2168.887408 +0.55,18000, 0.7210876413824057, 2833.160671200017, 1520.3672440000319,2409.874898 +0.55,18000, 0.7931964055206463, 4728.219522400015, 2266.3068320000116, 2650.8623872499998 +0.55,18000, 0.8653051696588868, 7192.648788000011,3283.882787, 2891.8498769999997 +0.55,18000, 0.9374139337971273,9949.77938, 4537.130186400038, 3132.8373667499995 +0.55,21000,0, 353.08053063530826, 353.08053063530826,0 +0.55,21000, 0.4224683577199282,-2009.05732,-348.7651056,1411.889252 +0.55,21000, 0.4928797506732495,-949.5835648, 47.17231039999943,1647.204127 +0.55,21000,0.563291144, 109.8899311999936, 443.10964480000007,1882.519002 +0.55,21000, 0.6337025365798923, 1169.3634872000032, 839.0469760000057,2117.833877 +0.55,21000, 0.7041139295332137, 2361.7107808000314, 1285.765008000014, 2353.1487525000002 +0.55,21000, 0.7745253224865349, 3964.1757631999753, 1905.2080752000113,2588.463628 +0.55,21000, 0.8449367154398564, 6116.397459200073, 2777.1616560000057,2823.778503 +0.55,21000, 0.9153481083931778, 8496.229542400033, 3834.083450400037,3059.093378 +0.55,21000,0.985759501, 11078.59967360022,5133.617099,3294.408254 +0.55,24000,0, 314.39169351819487, 314.39169351819487,0 +0.55,24000, 0.4122831786355476,-1920.540449,-361.1584616,1377.850383 +0.55,24000, 0.4809970417414722,-975.1257144,-8.4452792,1607.492114 +0.55,24000, 0.5497109048473967,-29.7110752, 344.26792480000046,1837.133844 +0.55,24000, 0.6184247679533214, 915.7034959999933, 696.9812136000028,2066.775575 +0.55,24000,0.687138631, 1924.1688184000097, 1073.163849600008,2296.417305 +0.55,24000, 0.7558524941651705, 3310.932916799993, 1598.1045296000134,2526.059036 +0.55,24000, 0.8245663572710952,5137.796047, 2325.293103200006,2755.700766 +0.55,24000, 0.8932802203770197, 7198.693903999972, 3217.927966400006,2985.342497 +0.55,24000, 0.9619940834829444, 9318.197458400025, 4280.6321256000265,3214.984227 +0.55,27000,0, 279.1299440930007, 279.1299440930007,0 +0.55,27000, 0.40209895152603237,-2005.200051,-419.256464, 1343.8146960000001 +0.55,27000, 0.46911544344703776,-1120.043642,-92.8357432, 1567.7838120000001 +0.55,27000, 0.5361319353680432,-234.887144, 233.58507199999892,1791.752928 +0.55,27000, 0.6031484272890485,650.2693488, 560.0058871999997,2015.722044 +0.55,27000, 0.6701649192100539, 1536.7576103999888, 886.8647680000053, 2239.6911600000003 +0.55,27000, 0.7371814111310593, 2730.5518623999983, 1332.8095671999984,2463.660276 +0.55,27000, 0.8041979030520647, 4295.929247200005, 1942.9273560000163, 2687.6293920000003 +0.55,27000, 0.8712143949730701, 6094.253980000046, 2698.9033648000195,2911.598508 +0.55,27000, 0.9382308868940755, 7933.540184800076, 3597.1834656000115, 3135.5676240000003 +0.55,30000,0, 247.06889957859602, 247.06889957859602,0 +0.55,30000, 0.39191377244165176,-2118.3728,-480.674,1309.775828 +0.55,30000, 0.4572327345152603,-1282.077,-176.1843,1528.071799 +0.55,30000, 0.5225516965888689,-445.7816, 128.30539999999974,1746.36777 +0.55,30000, 0.5878706586624776, 390.5138999999999, 432.7950000000001, 1964.6637412500002 +0.55,30000, 0.6531896207360862, 1226.8095999999996, 737.2847999999999,2182.959713 +0.55,30000, 0.7185085828096949, 2222.487999999998, 1103.398600000001,2401.255684 +0.55,30000, 0.7838275448833035, 3563.936000000004, 1618.714799999998,2619.551655 +0.55,30000, 0.8491465069569121, 5155.266599999999, 2270.3665000000005, 2837.8476262500003 +0.55,30000, 0.9144654690305206, 6746.392100000003,3017.2527,3056.143598 +0.55,30000, 0.9797844311041293, 8117.882799999992, 3833.504899999997,3274.439569 +0.55,33000,0, 217.98810821959532, 217.98810821959532,0 +0.55,33000, 0.3817295453321365,-2025.390102,-521.5956776,1275.740141 +0.55,33000, 0.44535113622082584,-1287.775163,-244.0716056,1488.363497 +0.55,33000, 0.5089727271095152,-550.1608216, 33.452258399999884,1700.986854 +0.55,33000, 0.5725943179982047, 187.4534783999959, 310.9765031999984,1913.610211 +0.55,33000,0.636215909, 925.0674871999988, 588.5001944000004,2126.233568 +0.55,33000, 0.6998374997755834, 1767.7497384000012, 902.9619488000017,2338.856924 +0.55,33000,0.763459091, 2915.098937599995, 1335.4534088000032,2551.480281 +0.55,33000, 0.8270806815529623, 4290.627315200017, 1883.2427600000058,2764.103638 +0.55,33000, 0.8907022724416517, 5717.436253600007, 2522.8588144000096,2976.726995 +0.55,33000, 0.9543238633303411, 6820.062578400031, 3167.6599808000124,3189.350351 +0.55,36000,0, 191.68048348149455, 191.68048348149455,0 +0.55,36000, 0.37154436624775583,-2176.4893,-572.1919,1241.701272 +0.55,36000, 0.43346842728904844,-1492.5227,-318.2723,1448.651484 +0.55,36000, 0.4953924883303411,-808.5572,-64.3527,1655.601696 +0.55,36000, 0.5573165493716338,-124.5906, 189.56699999999898,1862.551908 +0.55,36000, 0.6192406104129264, 559.3753999999972, 443.48629999999815,2069.50212 +0.55,36000,0.681164671, 1287.9206999999963, 707.9944000000021,2276.452332 +0.55,36000, 0.7430887324955117, 2201.7370999999966, 1047.8270999999902,2483.402544 +0.55,36000, 0.8050127935368042, 3296.7427000000207, 1498.9411000000052, 2690.3527559999998 +0.55,36000, 0.8669368545780969, 4770.690599999995, 2073.6619000000005,2897.302968 +0.55,36000, 0.9288609156193895, 5655.613499999973, 2640.556299999988, 3104.2531799999997 +0.55,36000, 0.9907849766606822, 5650.371999999944, 2701.633999999972,3311.203392 +0.55,39000,0, 166.0097840490962, 166.0097840490962,0 +0.55,39000, 0.37124163824057455,-1882.5707,-495.7016, 1240.6895550000002 +0.55,39000, 0.43311524461400364,-1336.2673,-287.8715, 1447.4711475000001 +0.55,39000, 0.4949888509874327,-789.9644,-80.0411, 1654.2527400000001 +0.55,39000, 0.5568624573608618,-243.6606, 127.78950000000023, 1861.0343325000001 +0.55,39000, 0.6187360637342909, 302.64220000000506, 335.62000000000006, 2067.8159250000003 +0.55,39000,0.68060967, 884.1289999999966, 552.3294999999989, 2274.5975175000003 +0.55,39000, 0.7424832764811491, 1713.054399999989, 852.9032000000002, 2481.3791100000003 +0.55,39000, 0.8043568828545782, 2706.998199999994, 1244.2737000000025, 2688.1607025000003 +0.55,39000, 0.8662304892280073, 3806.2708000000052, 1680.163200000005, 2894.9422950000003 +0.55,39000, 0.9281040956014364, 4711.514799999981, 2213.673000000006, 3101.7238875000003 +0.55,39000, 0.9899777019748655, 5502.907099999938, 2746.281500000002, 3308.5054800000003 +0.55,42000,0, 143.71847921078623, 143.71847921078623,0 +0.55,42000, 0.37124163824057455,-13978.10886,-5206.461175, 1240.6895550000002 +0.55,42000, 0.43311524461400364,-10893.78934,-4009.048125, 1447.4711475000001 +0.55,42000, 0.4949888509874327,-7809.469987,-2811.634769, 1654.2527400000001 +0.55,42000, 0.5568624573608618,-4725.153862,-1614.219969, 1861.0343325000001 +0.55,42000, 0.6187360637342909,-1640.8353,-416.8090188, 2067.8159250000003 +0.55,42000,0.68060967, 298.81433124999626, 327.9244249999797, 2274.5975175000003 +0.55,42000, 0.7424832764811491, 1402.1262124999685, 703.2273187500086, 2481.3791100000003 +0.55,42000, 0.8043568828545782, 1950.4898062500074, 996.7462500000124, 2688.1607025000003 +0.55,42000, 0.8662304892280073, 3358.4223624999986, 1598.0351374999987, 2894.9422950000003 +0.55,42000, 0.9281040956014364, 3801.7769749999406, 1835.5212249999995, 3101.7238875000003 +0.55,42000, 0.9899777019748655,5521.017494, 2900.1035500000585, 3308.5054800000003 + 0.6000000000000001,0,0, 765.6069809658406, 765.6069809658406,0 + 0.6000000000000001,0, 0.49911511669658887,-6025.0477,-79.0273,1668.04272 + 0.6000000000000001,0, 0.5823009694793536,-2465.723, 785.1888999998976,1946.04984 + 0.6000000000000001,0, 0.6654868222621184, 1093.608100000325, 1649.4085999997192,2224.05696 + 0.6000000000000001,0, 0.7486726750448833, 4224.980799999542, 2695.0914000003568,2502.06408 + 0.6000000000000001,0,0.831858528, 5101.5099000025075, 3943.206699999594,2780.0712 + 0.6000000000000001,0, 0.9150443806104128,5674.1032, 5576.643700000501, 3058.0783199999996 + 0.6000000000000001,0, 0.9982302333931777, 13470.32140000134, 8143.669700001068,3336.08544 + 0.6000000000000001,3000,0, 693.3578249967735, 693.3578249967735,0 + 0.6000000000000001,3000, 0.48882045242369837,-1032.887727, 110.90694140501671,1633.637952 + 0.6000000000000001,3000, 0.5702905278276481, 229.05903954145114, 793.0775654701936,1905.910944 + 0.6000000000000001,3000, 0.6517606032315978,1491.021647, 1475.2571131964648,2178.183936 + 0.6000000000000001,3000, 0.7332306786355476, 3270.8377907181393, 2286.7653867022946,2450.456928 + 0.6000000000000001,3000, 0.8147007540394973, 7000.776244105932, 3555.9040300367856, 2722.7299199999998 + 0.6000000000000001,3000, 0.8961708294434471, 9948.700792716194,5147.927611,2995.002912 + 0.6000000000000001,3000, 0.9776409048473967, 11990.533633133324, 7075.252573780068,3267.275904 + 0.6000000000000001,6000,0, 626.6030385637355, 626.6030385637355,0 + 0.6000000000000001,6000, 0.4785248258527828,-4189.7769,-36.4088,1599.229968 + 0.6000000000000001,6000, 0.5582789634949132,-1838.029, 612.0603000000128, 1865.7682960000002 + 0.6000000000000001,6000, 0.6380331011370438,513.7294, 1260.529500000035, 2132.3066240000003 + 0.6000000000000001,6000, 0.7177872387791743, 2868.472200000034, 1990.4932000000745, 2398.8449520000004 + 0.6000000000000001,6000, 0.7975413764213047, 6031.481100000747, 3062.5463999996746, 2665.3832800000005 + 0.6000000000000001,6000, 0.8772955140634352, 8447.503499998587, 4371.179400000585, 2931.9216080000006 + 0.6000000000000001,6000, 0.9570496517055656, 13176.49309999862, 6561.287200000834,3198.459936 + 0.6000000000000001,9000,0, 565.0310160917361, 565.0310160917361,0 + 0.6000000000000001,9000, 0.46823016157989233,-1831.780464,-110.9093714, 1564.8252000000002 + 0.6000000000000001,9000, 0.5462685218432077,-380.2262071,485.4069643, 1825.6294000000003 + 0.6000000000000001,9000, 0.6243068821065231, 1071.3272571429072, 1081.7232428571447, 2086.4336000000003 + 0.6000000000000001,9000, 0.7023452423698385, 2620.857042857131, 1730.1024357142883, 2347.2378000000003 + 0.6000000000000001,9000, 0.7803836026331539, 4715.763664285782, 2620.907792857088, 2608.0420000000004 + 0.6000000000000001,9000, 0.8584219628964693, 7694.563978571501,3884.350021, 2868.8462000000004 + 0.6000000000000001,9000, 0.9364603231597847, 11541.275478571273,5637.718164, 3129.6504000000004 + 0.6000000000000001,12000,0, 508.33599738099446, 508.33599738099446,0 + 0.6000000000000001,12000, 0.4579345350089767,-2192.806423,-209.9565859,1530.417216 + 0.6000000000000001,12000, 0.5342569575104728,-752.0044664, 343.5381979292898,1785.486752 + 0.6000000000000001,12000, 0.6105793800119689, 688.7974737626541, 897.0328834848356,2040.556288 + 0.6000000000000001,12000,0.686901803, 2170.0898012121265, 1473.026894368681,2295.625824 + 0.6000000000000001,12000, 0.7632242250149611, 4070.513064924184, 2246.4019278282426,2550.69536 + 0.6000000000000001,12000, 0.8395466475164572, 6569.497112777638, 3309.109334772652,2805.764896 + 0.6000000000000001,12000, 0.9158690700179534, 9949.594150959572, 4819.664426919146,3060.834432 + 0.6000000000000001,12000, 0.9921914925194495, 13584.53113179258, 6570.464643434266,3315.903968 + 0.6000000000000001,15000,0, 456.23187174865643, 456.23187174865643,0 + 0.6000000000000001,15000, 0.4476398707360862,-2117.7908,-273.6782,1496.012448 + 0.6000000000000001,15000, 0.5222465158587672,-822.6001, 231.11120000000003,1745.347856 + 0.6000000000000001,15000, 0.5968531609814482, 472.5903999999954, 735.9005999999983,1994.683264 + 0.6000000000000001,15000, 0.6714598061041294, 1767.780999999998, 1240.6901000000028,2244.018672 + 0.6000000000000001,15000, 0.7460664512268104, 3415.828399999991, 1902.1244999999974,2493.35408 + 0.6000000000000001,15000, 0.8206730963494914, 5627.755399999985, 2827.2825000000053,2742.689488 + 0.6000000000000001,15000, 0.8952797414721724,8524.8691,4096.8911,2992.024896 + 0.6000000000000001,15000, 0.9698863865948534, 11754.323199999999, 5646.494599999994,3241.360304 + 0.6000000000000001,18000,0, 408.4404341094299, 408.4404341094299,0 + 0.6000000000000001,18000, 0.43734424416517054,-2177.575997,-339.751208,1461.604464 + 0.6000000000000001,18000, 0.5102349515260324,-974.971884, 123.70919039999988,1705.205208 + 0.6000000000000001,18000, 0.5831256588868942, 227.6324120000049, 587.1696104000007, 1948.8059520000002 + 0.6000000000000001,18000, 0.6560163662477558, 1430.2367760000086, 1050.6300303999874,2192.406696 + 0.6000000000000001,18000, 0.7289070736086177, 2848.3074672000175, 1611.5032296000218, 2436.0074400000003 + 0.6000000000000001,18000, 0.8017977809694794, 4781.003586400024,2399.854493,2679.608184 + 0.6000000000000001,18000, 0.8746884883303411, 7288.045300000037, 3480.612922400052,2923.208928 + 0.6000000000000001,18000,0.947579196, 10104.970703200119, 4808.753145599993, 3166.8096720000003 + 0.6000000000000001,21000,0, 364.6918921125046, 364.6918921125046,0 + 0.6000000000000001,21000, 0.4270495798922801,-2118.026526,-375.9020336, 1427.1996960000001 + 0.6000000000000001,21000, 0.4982245098743268,-1031.512446, 43.441929599999085, 1665.0663120000002 + 0.6000000000000001,21000, 0.5693994398563735, 55.00156879997306, 462.78577999999777, 1902.9329280000002 + 0.6000000000000001,21000, 0.6405743698384202, 1141.5156999999906,882.1296352, 2140.7995440000004 + 0.6000000000000001,21000, 0.7117492998204669, 2346.906501600018, 1355.1385416000142,2378.66616 + 0.6000000000000001,21000, 0.7829242298025134, 4019.284399999974, 2022.0448288000173,2616.532776 + 0.6000000000000001,21000, 0.8540991597845602, 6202.803570400104, 2945.7587832000013, 2854.3993920000003 + 0.6000000000000001,21000,0.92527409, 8634.536793600086, 4064.8407240000224, 3092.2660080000005 + 0.6000000000000001,21000, 0.9964490197486536, 11324.821619200115, 5443.804922399995, 3330.1326240000003 + 0.6000000000000001,24000,0, 324.73073881276036, 324.73073881276036,0 + 0.6000000000000001,24000, 0.4167539533213645,-1994.748622,-371.5027344, 1392.7917120000002 + 0.6000000000000001,24000, 0.4862129455415919,-1033.281939,-2.6093448, 1624.9236640000001 + 0.6000000000000001,24000, 0.5556719377618193,-71.81536, 366.28413119999993,1857.055616 + 0.6000000000000001,24000, 0.6251309299820468, 889.6513319999993, 735.1775775999968, 2089.1875680000003 + 0.6000000000000001,24000, 0.6945899222022741, 1932.7154008000007, 1137.0621960000046,2321.31952 + 0.6000000000000001,24000, 0.7640489144225016, 3352.6347416000162, 1693.830697600002,2553.451472 + 0.6000000000000001,24000,0.833507907, 5214.156200000017, 2466.3221327999972, 2785.5834240000004 + 0.6000000000000001,24000, 0.9029668988629563,7321.433097, 3415.3068103999935,3017.715376 + 0.6000000000000001,24000, 0.9724258910831838, 9475.582279999917, 4543.178333599979, 3249.8473280000003 + 0.6000000000000001,27000,0, 288.3093759754148, 288.3093759754148,0 + 0.6000000000000001,27000,0.406459289,-1906.461986,-382.468772,1358.386944 + 0.6000000000000001,27000, 0.4742025038898863,-1048.818354,-53.52256,1584.784768 + 0.6000000000000001,27000, 0.5419457187312987,-191.1747056, 275.42362559999987,1811.182592 + 0.6000000000000001,27000,0.609688934, 666.4689432000011, 604.3698080000012, 2037.5804160000002 + 0.6000000000000001,27000, 0.6774321484141234, 1540.7525855999975, 939.6804871999987, 2263.9782400000004 + 0.6000000000000001,27000, 0.7451753632555356, 2765.4334776000023, 1411.9077695999974,2490.376064 + 0.6000000000000001,27000,0.812918578, 4360.493993599985, 2059.8433800000043,2716.773888 + 0.6000000000000001,27000, 0.8806617929383603, 6182.694176000022, 2862.712054399992, 2943.1717120000003 + 0.6000000000000001,27000, 0.9484050077797725, 8049.501908799987, 3813.161476799994,3169.569536 + 0.6000000000000001,30000,0, 255.19397602395614, 255.19397602395614,0 + 0.6000000000000001,30000, 0.3961636624775583,-2060.8132,-458.1994,1323.97896 + 0.6000000000000001,30000, 0.4621909395571514,-1240.2024,-148.8284,1544.64212 + 0.6000000000000001,30000, 0.5282182166367445,-419.5912, 160.54249999999828,1765.30528 + 0.6000000000000001,30000, 0.5942454937163375, 401.01980000000225, 469.9133999999995,1985.96844 + 0.6000000000000001,30000, 0.6602727707959306, 1221.630899999998, 779.2843000000023,2206.6316 + 0.6000000000000001,30000, 0.7263000478755237, 2266.588600000004, 1174.8208000000072,2427.29476 + 0.6000000000000001,30000, 0.7923273249551166, 3629.043900000017, 1720.0795000000076,2647.95792 + 0.6000000000000001,30000, 0.8583546020347097, 5241.692399999984, 2407.327100000001,2868.62108 + 0.6000000000000001,30000, 0.9243818791143028,6845.8208, 3195.163300000004,3089.28424 + 0.6000000000000001,30000, 0.9904091561938959, 8183.629399999993, 4024.9125999999733,3309.9474 + 0.6000000000000001,33000,0, 225.15683745457622, 225.15683745457622,0 + 0.6000000000000001,33000, 0.38586899820466797,-2207.917374,-528.7189296, 1289.5741920000003 + 0.6000000000000001,33000, 0.4501804979054459,-1426.233147,-239.1670576, 1504.5032240000003 + 0.6000000000000001,33000, 0.5144919976062239,-644.5488336, 50.38476640000041, 1719.4322560000003 + 0.6000000000000001,33000, 0.5788034973070019, 137.13548640000013, 339.93660720000025, 1934.3612880000003 + 0.6000000000000001,33000,0.643114997, 918.8197711999989, 629.4884624000003, 2149.2903200000005 + 0.6000000000000001,33000,0.707426497, 1804.4131263999977, 959.9360247999986, 2364.2193520000005 + 0.6000000000000001,33000, 0.7717379964093359, 2945.698789600005, 1407.7670247999984, 2579.1483840000005 + 0.6000000000000001,33000, 0.8360494961101139, 4351.858299199991, 1992.4095199999974, 2794.0774160000005 + 0.6000000000000001,33000, 0.9003609958108918, 5802.171045599996, 2673.6093023999947, 3009.0064480000005 + 0.6000000000000001,33000, 0.9646724955116698, 6968.663866399994, 3383.479296799996, 3223.9354800000006 + 0.6000000000000001,36000,0, 197.98406351130433, 197.98406351130433,0 + 0.6000000000000001,36000, 0.37557337163375226,-2307.2292,-575.3364,1255.166208 + 0.6000000000000001,36000, 0.43816893357271103,-1590.2949,-312.0948, 1464.3605760000003 + 0.6000000000000001,36000, 0.5007644955116697,-873.3605,-48.8532, 1673.5549440000002 + 0.6000000000000001,36000, 0.5633600574506284,-156.4261, 214.3884000000002, 1882.7493120000001 + 0.6000000000000001,36000, 0.6259556193895872,560.5083, 477.6300999999998, 2091.9436800000003 + 0.6000000000000001,36000, 0.6885511813285459, 1321.8441000000003, 758.2826000000002, 2301.1380480000003 + 0.6000000000000001,36000, 0.7511467432675045, 2276.085399999999,1124.9122,2510.332416 + 0.6000000000000001,36000, 0.8137423052064633, 3475.9856000000013, 1613.9647000000016,2719.526784 + 0.6000000000000001,36000, 0.8763378671454221, 4685.783700000002, 2172.9069999999974, 2928.7211520000005 + 0.6000000000000001,36000, 0.9389334290843807, 5667.942900000003, 2754.7935000000016, 3137.9155200000005 + 0.6000000000000001,39000,0, 171.46916071842696, 171.46916071842696,0 + 0.6000000000000001,39000, 0.37526736086175944,-2002.4923,-520.5444,1254.14352 + 0.6000000000000001,39000, 0.4378119210053861,-1421.9152,-299.1928, 1463.1674400000002 + 0.6000000000000001,39000, 0.5003564811490127,-841.338,-77.8411, 1672.1913600000003 + 0.6000000000000001,39000, 0.5629010412926393,-260.7607, 143.51049999999998, 1881.2152800000003 + 0.6000000000000001,39000, 0.6254456014362658, 319.8165000000001, 364.86220000000003, 2090.2392000000004 + 0.6000000000000001,39000, 0.6879901615798925, 946.5119999999996, 602.7563999999996, 2299.2631200000005 + 0.6000000000000001,39000, 0.7505347217235189, 1775.498400000001, 918.4677000000001,2508.28704 + 0.6000000000000001,39000, 0.8130792818671455, 2814.586899999998,1339.0612, 2717.3109600000003 + 0.6000000000000001,39000, 0.8756238420107721, 3862.892300000001, 1816.284200000001, 2926.3348800000003 + 0.6000000000000001,39000, 0.9381684021543987, 4767.528299999998,2336.4414, 3135.3588000000004 + 0.6000000000000001,42000,0, 148.4447868609608, 148.4447868609608,0 + 0.6000000000000001,42000, 0.37526736086175944,-7912.092838,-2875.065225,1254.14352 + 0.6000000000000001,42000, 0.4378119210053861,-6127.016637,-2174.443875, 1463.1674400000002 + 0.6000000000000001,42000, 0.5003564811490127,-4341.940187,-1473.822556, 1672.1913600000003 + 0.6000000000000001,42000, 0.5629010412926393,-2556.865137,-773.2005813, 1881.2152800000003 + 0.6000000000000001,42000, 0.6254456014362658,-771.789125,-72.58010625, 2090.2392000000004 + 0.6000000000000001,42000, 0.6879901615798925, 508.2581187499988, 426.18429999999046, 2299.2631200000005 + 0.6000000000000001,42000, 0.7505347217235189, 1367.7963624999861, 743.8318312500035,2508.28704 + 0.6000000000000001,42000, 0.8130792818671455, 2147.8645187500006, 1082.3422000000003, 2717.3109600000003 + 0.6000000000000001,42000, 0.8756238420107721, 3218.840587499993, 1564.915462499999, 2926.3348800000003 + 0.6000000000000001,42000, 0.9381684021543987, 3964.538424999968, 1977.8877499999903, 3135.3588000000004 +0.65,0,0, 792.7024450524767, 792.7024450524767,0 +0.65,0, 0.5049350224416517,-8986.311,-205.033,1687.492845 +0.65,0, 0.5890908595152603,-4193.0778, 754.1148999998619, 1968.7416524999999 +0.65,0, 0.6732466965888689, 600.1659000004893, 1713.2683999996198,2249.99046 +0.65,0, 0.7574025336624776, 4169.050899999325,2856.6421,2531.239268 +0.65,0, 0.8415583707360862, 3476.700500003306, 4086.801899999419,2812.488075 +0.65,0, 0.9257142078096947, 2286.0993000032213, 5657.078800000607,3093.736883 +0.65,3000,0, 717.8963317155706, 717.8963317155706,0 +0.65,3000, 0.49452031777378813,-425.4664374, 180.53526898241603,1652.686902 +0.65,3000, 0.5769403707360862, 468.8010719162818,869.3739606,1928.134719 +0.65,3000, 0.6593604236983842, 1363.0971914531324, 1558.2287554517266,2203.582536 +0.65,3000, 0.7417804766606823, 3011.832178775709, 2400.3819444242067,2479.030353 +0.65,3000, 0.8242005296229802, 7474.005587990672, 3772.592356724915,2754.47817 +0.65,3000, 0.9066205825852781, 9944.852812389632, 5428.432934148905, 3029.9259869999996 +0.65,3000, 0.9890406355475763,9336.356808, 7113.890729373179,3305.373804 +0.65,6000,0, 648.7790381955078, 648.7790381955078,0 +0.65,6000, 0.4841046395870736,-6060.3229,-9.804,1617.877706 +0.65,6000, 0.5647887461849193,-3115.9737,656.8693,1887.52399 +0.65,6000, 0.6454728527827648,-171.6051, 1323.5427000000427,2157.170274 +0.65,6000, 0.7261569593806104, 2660.584000000071, 2087.388700000104,2426.816558 +0.65,6000, 0.8068410659784561, 6493.076300001056, 3261.3311999994967,2696.462843 +0.65,6000, 0.8875251725763016, 7988.586999997913,4485.1426,2966.109127 +0.65,6000, 0.9682092791741472, 13065.786999997952, 6949.1082000011465,3235.755411 +0.65,9000,0, 585.0279309383524, 585.0279309383524,0 +0.65,9000,0.473689935,-1700.503211,-62.71742857,1583.071763 +0.65,9000,0.552638257,-307.4999679,544.9037607, 1846.9170562499999 +0.65,9000, 0.6315865798922801, 1085.5022428572167, 1152.5248071428578,2110.76235 +0.65,9000, 0.7105349023788151, 2605.4910071428308, 1830.804439285713,2374.607644 +0.65,9000, 0.7894832248653502, 4721.692860714421, 2773.7117821427755,2638.452938 +0.65,9000, 0.8684315473518851, 7806.446846428692, 4126.704453571549,2902.298231 +0.65,9000,0.94737987,11671.69505, 5977.995810714067,3166.143525 +0.65,12000,0, 526.3264286380411, 526.3264286380411,0 +0.65,12000, 0.46327425673249556,-2317.344608,-180.2026798,1548.262566 +0.65,12000, 0.5404866328545782,-839.7218247, 389.27596239898526, 1806.3063270000002 +0.65,12000, 0.6176990089766607, 637.9008869823653, 958.7545196211898,2064.350088 +0.65,12000, 0.6949113850987433, 2175.165540303032, 1566.5214721338264,2322.393849 +0.65,12000, 0.7721237612208258,4118.990162, 2385.5284565403285,2580.43761 +0.65,12000, 0.8493361373429086, 6640.0689186108675, 3503.6583655680424, 2838.4813710000003 +0.65,12000, 0.9265485134649911, 10127.735213156528, 5124.887838813041,3096.525132 +0.65,15000,0, 472.37829491808674, 472.37829491808674,0 +0.65,15000, 0.45285955206463196,-2025.0591,-233.9827,1513.456623 +0.65,15000,0.528336144,-767.4877,281.0219,1765.699394 +0.65,15000, 0.6038127360861759, 490.08349999998507, 796.0265999999918,2017.942164 +0.65,15000,0.679289328, 1767.7185999999904, 1320.2819000000059,2270.184935 +0.65,15000, 0.7547659201077199,3444.229, 2021.0459999999955,2522.427705 +0.65,15000,0.830242512, 5711.7250999999715, 2999.7244000000214,2774.670476 +0.65,15000, 0.9057191041292639, 8684.402299999936, 4357.783199999955,3026.913246 +0.65,15000, 0.9811956961400359, 11932.069300000001, 5975.329599999968,3279.156017 +0.65,18000,0, 422.89547878519926, 422.89547878519926,0 +0.65,18000, 0.4424438738779174,-2094.231596,-304.123788,1478.647427 +0.65,18000, 0.5161845195242369,-920.8062992, 168.95020639999888,1725.088664 +0.65,18000, 0.5899251651705566, 252.61912400000503, 642.0242023999981,1971.529902 +0.65,18000, 0.6636658108168761, 1425.9856712000028, 1115.0722592000102,2217.97114 +0.65,18000, 0.7374064564631957,2877.673352, 1712.4198959999967,2464.412378 +0.65,18000, 0.8111471021095152, 4856.519299199997, 2548.907502400006,2710.853615 +0.65,18000, 0.8848877477558348, 7428.133271200024, 3703.352770400024,2957.294853 +0.65,18000, 0.9586283934021544, 10309.897340000027, 5113.859144800022,3203.736091 +0.65,21000,0, 377.5986397141995, 377.5986397141995,0 +0.65,21000, 0.4320291692100539,-2065.294921,-357.489156,1443.841484 +0.65,21000, 0.5040340307450629,-999.6529008, 73.78299760000081, 1684.4817307500002 +0.65,21000, 0.5760388922800719, 65.98912399999438, 505.05521920000234, 1925.1219780000001 +0.65,21000, 0.6480437538150808, 1131.6310856000116, 936.3273495999962,2165.762225 +0.65,21000, 0.7200486153500898, 2362.0323344000203, 1437.808717600006,2406.402473 +0.65,21000, 0.7920534768850989, 4097.359209600052,2154.983353, 2647.0427197500003 +0.65,21000, 0.8640583384201078, 6311.4237696000455, 3128.3837111999783,2887.682967 +0.65,21000, 0.9360631999551168, 8825.819702399976, 4334.821096799998,3128.323214 +0.65,24000,0, 336.22322815791756, 336.22322815791756,0 +0.65,24000, 0.42161349102333934,-2059.024546,-394.4845912,1409.032287 +0.65,24000, 0.4918824061938959,-1079.36919,-3.9418064, 1643.8710015000001 +0.65,24000, 0.5621513213644524,-99.7139104, 386.6009735999998,1878.709716 +0.65,24000,0.632420237, 879.9414511999969, 777.1436888000015,2113.548431 +0.65,24000, 0.7026891517055656, 1947.2460103999983, 1206.7936095999987,2348.387145 +0.65,24000, 0.7729580668761221, 3399.061526400003, 1798.5545215999973, 2583.2258595000003 +0.65,24000, 0.8432269820466787, 5318.818936000035, 2624.811353600009,2818.064574 +0.65,24000, 0.9134958972172352, 7475.729080000036, 3634.958116800016,3052.903289 +0.65,24000, 0.9837648123877918, 9731.872028000087, 4859.2952552000115, 3287.7420030000003 +0.65,27000,0, 298.5128831753196, 298.5128831753196,0 +0.65,27000, 0.4111987863554758,-1946.70211,-392.9390352, 1374.2263440000002 +0.65,27000, 0.47973191741472176,-1077.663289,-48.0893824, 1603.2640680000002 +0.65,27000, 0.5482650484739677,-208.6243848, 296.76018399999987, 1832.3017920000002 +0.65,27000, 0.6167981795332137, 660.4145191999962, 641.6097719999997,2061.339516 +0.65,27000, 0.6853313105924597, 1572.2684152000002, 1004.1083232000009, 2290.3772400000003 +0.65,27000, 0.7538644416517057, 2814.3681048000094, 1502.5744048000015, 2519.4149640000005 +0.65,27000, 0.8223975727109516, 4457.272203199989, 2196.2597152000176, 2748.4526880000003 +0.65,27000, 0.8909307037701976, 6322.386402400014, 3048.4214056000087,2977.490412 +0.65,27000, 0.9594638348294435,8214.633226, 4057.2307831999897, 3206.5281360000004 +0.65,30000,0, 264.22550183862404, 264.22550183862404,0 +0.65,30000, 0.4007831081687612,-1969.6383,-427.1041,1339.417148 +0.65,30000, 0.4675802928635548,-1168.3015,-113.45,1562.653339 +0.65,30000, 0.5343774775583483,-366.9648, 200.2041999999978, 1785.8895300000001 +0.65,30000, 0.6011746622531419, 434.3720000000084, 513.8582999999969, 2009.1257212500002 +0.65,30000, 0.6679718469479353, 1235.7088999999933, 827.5125000000068,2232.361913 +0.65,30000, 0.7347690316427289, 2307.668700000013, 1251.410200000019,2455.598104 +0.65,30000, 0.8015662163375225, 3709.447500000026, 1830.667000000022,2678.834295 +0.65,30000,0.868363401, 5346.759799999919, 2555.403299999985,2902.070486 +0.65,30000, 0.9351605857271096, 6983.832000000056,3403.7114,3125.306678 +0.65,33000,0, 233.12532409953172, 233.12532409953172,0 +0.65,33000, 0.3903684035008977,-2121.918406,-501.3691416,1304.611205 +0.65,33000, 0.45542980408438066,-1356.051551,-207.5336696, 1522.0464052500001 +0.65,33000, 0.5204912046678636,-590.1845056, 86.30181440000011,1739.481606 +0.65,33000, 0.5855526052513464, 175.68253440000333, 380.1373312000019,1956.916807 +0.65,33000, 0.6506140058348295, 941.5495751999918, 673.9727704000029,2174.352008 +0.65,33000, 0.7156754064183125, 1839.7903543999932, 1021.9640807999955, 2391.7872082500003 +0.65,33000, 0.7807368070017954, 3021.9266016000174, 1502.8665208000011,2609.222409 +0.65,33000, 0.8457982075852783, 4453.759503199965, 2121.975379999983,2826.65761 +0.65,33000, 0.9108596081687613, 5883.971597600017, 2828.667030400002, 3044.0928105000003 +0.65,33000, 0.9759210087522442, 7093.745994400008, 3594.092792799984,3261.528011 +0.65,36000,0, 204.9908832190209, 204.9908832190209,0 +0.65,36000, 0.37995272531418317,-2204.3491,-551.7944, 1269.8020080000001 +0.65,36000, 0.44327817953321363,-1503.3511,-283.878,1481.435676 +0.65,36000, 0.5066036337522442,-802.353,-15.9616,1693.069344 +0.65,36000, 0.5699290879712746,-101.355, 251.95479999999918,1904.703012 +0.65,36000, 0.6332545421903052, 599.6431000000001, 519.8713000000002,2116.33668 +0.65,36000, 0.6965799964093357,1363.042, 813.6062000000007,2327.970348 +0.65,36000, 0.7599054506283663, 2351.8755000000024, 1206.553000000001, 2539.6040160000002 +0.65,36000, 0.8232309048473968, 3571.964599999986, 1724.7234999999996,2751.237684 +0.65,36000, 0.8865563590664273, 4769.537599999995, 2315.9233000000045,2962.871352 +0.65,36000, 0.9498818132854578, 5753.311000000053, 2911.5493000000074,3174.50502 +0.65,39000,0, 177.53759609286755, 177.53759609286755,0 +0.65,39000, 0.37964314631956914,-2079.6423,-541.2985,1268.767395 +0.65,39000, 0.44291700403949735,-1475.5615,-306.8378, 1480.2286275000001 +0.65,39000, 0.5061908617594255,-871.4808,-72.3771, 1691.6898600000002 +0.65,39000, 0.5694647194793537,-267.4001, 162.0834999999989, 1903.1510925000002 +0.65,39000, 0.6327385771992818, 336.68069999999454, 396.5441999999992,2114.612325 +0.65,39000, 0.6960124349192102, 995.0391999999958, 653.1631000000007, 2326.0735575000003 +0.65,39000, 0.7592862926391383, 1838.353800000003, 987.8817000000003,2537.53479 +0.65,39000, 0.8225601503590666, 2900.0544000000154, 1433.4257000000036, 2748.9960225000004 +0.65,39000, 0.8858340080789947, 3944.9355000000214, 1941.3198000000118, 2960.4572550000003 +0.65,39000, 0.9491078657989229, 4862.986300000031, 2483.766100000017, 3171.9184875000005 +0.65,42000,0, 153.69837060723933, 153.69837060723933,0 +0.65,42000, 0.37964314631956914,-4454.834913,-1543.573875,1268.767395 +0.65,42000, 0.44291700403949735,-3405.792437,-1122.113825, 1480.2286275000001 +0.65,42000, 0.5061908617594255,-2356.749687,-700.6538938, 1691.6898600000002 +0.65,42000, 0.5694647194793537,-1307.707313,-279.1937437, 1903.1510925000002 +0.65,42000, 0.6327385771992818,-258.66475, 142.26605624999942,2114.612325 +0.65,42000, 0.6960124349192102, 630.2993562499995, 496.7317749999977, 2326.0735575000003 +0.65,42000, 0.7592862926391383, 1385.454412499997, 795.0604937500008,2537.53479 +0.65,42000, 0.8225601503590666, 2283.647081249999, 1171.2965499999975, 2748.9960225000004 +0.65,42000, 0.8858340080789947, 3208.840912499997,1610.982888, 2960.4572550000003 +0.65,42000, 0.9491078657989229, 4068.1816749999925, 2103.5878749999924, 3171.9184875000005 + 0.7000000000000001,0,0,822.675472,822.675472,0 + 0.7000000000000001,0, 0.5112205206463195,-13019.3017,-390.5481, 1708.4989799999998 + 0.7000000000000001,0, 0.5964239407540395,-6521.0009, 693.5088999998198, 1993.2488099999998 + 0.7000000000000001,0, 0.6816273608617593,-22.6841,1777.5743,2277.99864 + 0.7000000000000001,0, 0.7668307809694792, 4125.024699999041, 3038.2561000005308, 2562.7484699999995 + 0.7000000000000001,0, 0.8520342010771992, 1281.1685000042562, 4223.057899999199, 2847.4982999999997 + 0.7000000000000001,0, 0.9372376211849192,-2232.3952, 5678.893000000723,3132.24813 + 0.7000000000000001,3000,0, 745.0408501065614, 745.0408501065614,0 + 0.7000000000000001,3000, 0.5006761723518852, 436.9773930719457, 263.6130287598152, 1673.2597680000003 + 0.7000000000000001,3000, 0.5841222010771994, 824.2919286911242, 956.8958211138371, 1952.1363960000003 + 0.7000000000000001,3000, 0.6675682298025135, 1211.6531449894173, 1650.2048633070076, 2231.0130240000003 + 0.7000000000000001,3000, 0.7510142585278278, 2681.2498396332776, 2523.8675675461645, 2509.8896520000003 + 0.7000000000000001,3000, 0.8344602872531419, 8163.985986275406, 4014.352547413081, 2788.7662800000003 + 0.7000000000000001,3000, 0.9179063159784561, 9956.331450463373, 5737.1116862589215, 3067.6429080000003 + 0.7000000000000001,6000,0,673.3101491,673.3101491,0 + 0.7000000000000001,6000, 0.49013083842010774,-8741.0898, 13.498899999999836,1638.017262 + 0.7000000000000001,6000, 0.5718193114901258,-4938.6871, 700.6290000000191, 1911.0201390000002 + 0.7000000000000001,6000, 0.6535077845601437,-1136.2522, 1387.7592000000504,2184.023016 + 0.7000000000000001,6000, 0.7351962576301616, 2378.5183000001252, 2188.9470000001415,2457.025893 + 0.7000000000000001,6000, 0.8168847307001795, 7181.3604000014275, 3493.2711999992603,2730.02877 + 0.7000000000000001,6000, 0.8985732037701976, 7254.113099997037, 4549.241400001265, 3003.0316470000002 + 0.7000000000000001,6000, 0.9802616768402155, 12777.58479999708, 7363.207900001526,3276.034524 + 0.7000000000000001,9000,0, 607.1485362807002, 607.1485362807002,0 + 0.7000000000000001,9000, 0.4795864901256733,-1599.879021,-12.77455714, 1602.7780500000001 + 0.7000000000000001,9000, 0.5595175718132854,-259.4922357, 607.3764214285794,1869.907725 + 0.7000000000000001,9000, 0.6394486535008977, 1080.8934857143863, 1227.5272142857118,2137.0374 + 0.7000000000000001,9000,0.719379735, 2583.088014285665, 1940.965478571419, 2404.1670750000003 + 0.7000000000000001,9000, 0.7993108168761223, 4765.228021428801, 2946.8956642856006, 2671.2967500000004 + 0.7000000000000001,9000, 0.8792418985637344, 7974.031892857328, 4402.920107143004,2938.426425 + 0.7000000000000001,9000, 0.9591729802513466, 11801.097092856715, 6348.0624214282825, 3205.5561000000002 + 0.7000000000000001,12000,0, 546.2274600135438, 546.2274600135438,0 + 0.7000000000000001,12000, 0.4690411561938958,-2415.962284,-145.1551222, 1567.5355439999998 + 0.7000000000000001,12000, 0.5472146822262118,-907.3567092, 440.61407611110434,1828.791468 + 0.7000000000000001,12000, 0.6253882082585278, 601.2487619445025, 1026.3832216666335,2090.047392 + 0.7000000000000001,12000, 0.7035617342908438, 2181.3708066666563, 1667.0794752777572,2351.303316 + 0.7000000000000001,12000, 0.7817352603231598, 4172.977625833213, 2537.499840555433,2612.55924 + 0.7000000000000001,12000, 0.8599087863554757, 6741.132032777397, 3726.981897499777,2873.815164 + 0.7000000000000001,12000, 0.9380823123877916, 10353.412192777745, 5465.789210555413, 3135.0710879999997 + 0.7000000000000001,15000,0, 490.2394828743851, 490.2394828743851,0 + 0.7000000000000001,15000, 0.45849680789946146,-1946.59508,-191.27324, 1532.2963320000001 + 0.7000000000000001,15000, 0.5349129425493717,-723.95252, 334.60414999999705, 1787.6790540000002 + 0.7000000000000001,15000,0.611329077, 498.68997999996895,860.48174, 2043.0617760000002 + 0.7000000000000001,15000, 0.6877452118491922, 1775.4181499999763, 1410.187560000008, 2298.4444980000003 + 0.7000000000000001,15000, 0.7641613464991024, 3490.8625899999643, 2154.941179999995,2553.82722 + 0.7000000000000001,15000, 0.8405774811490127, 5818.840939999965, 3191.662840000045, 2809.2099420000004 + 0.7000000000000001,15000, 0.9169936157989229, 8894.500169999897, 4655.315229999899, 3064.5926640000002 + 0.7000000000000001,15000, 0.9934097504488332, 12116.06083000001, 6324.152319999926, 3319.9753860000005 + 0.7000000000000001,18000,0, 438.88566231757557, 438.88566231757557,0 + 0.7000000000000001,18000, 0.44795147396768403,-2026.140203,-266.429788,1497.053826 + 0.7000000000000001,18000,0.522610053,-873.2838232, 217.8617768000008,1746.562797 + 0.7000000000000001,18000,0.597268632, 279.57257679999043, 702.1532600000029,1996.071768 + 0.7000000000000001,18000, 0.6719272109515261, 1431.7158903999962, 1186.1548136000079,2245.580739 + 0.7000000000000001,18000, 0.7465857899461401, 2919.1741656000113, 1822.108252800007,2495.08971 + 0.7000000000000001,18000,0.821244369, 4970.509167200026, 2721.648908799995,2744.598681 + 0.7000000000000001,18000, 0.8959029479353681, 7601.833837599994, 3947.158848000014,2994.107652 + 0.7000000000000001,18000,0.970561527, 10552.041460799983, 5448.533919199945,3243.616623 + 0.7000000000000001,21000,0, 391.8760956187884, 391.8760956187884,0 + 0.7000000000000001,21000, 0.4374071256732496,-2058.549906,-335.007488, 1461.8146140000001 + 0.7000000000000001,21000, 0.5103083132854579,-994.0279152, 109.71660320000024,1705.450383 + 0.7000000000000001,21000, 0.5832095008976661, 70.49416239997012, 554.4407240000005,1949.086152 + 0.7000000000000001,21000, 0.6561106885098744, 1135.0161287999797, 999.1649048000115, 2192.7219210000003 + 0.7000000000000001,21000, 0.7290118761220826, 2418.2501247999735, 1537.6253976000207, 2436.3576900000003 + 0.7000000000000001,21000, 0.8019130637342909,4185.785828, 2297.9855528000157, 2679.9934590000003 + 0.7000000000000001,21000, 0.8748142513464991, 6471.901385600066, 3341.8394368000595, 2923.6292280000002 + 0.7000000000000001,21000, 0.9477154389587075, 9049.596870400062, 4628.783739999933,3167.264997 + 0.7000000000000001,24000,0, 348.9362302962637, 348.9362302962637,0 + 0.7000000000000001,24000, 0.4268617917414722,-2117.80628,-396.03726,1426.572108 + 0.7000000000000001,24000, 0.49800542369838424,-1121.716286, 11.971268799999827, 1664.3341260000002 + 0.7000000000000001,24000, 0.5691490556552963,-125.6263264, 419.9797943999992,1902.096144 + 0.7000000000000001,24000, 0.6402926876122083, 870.4636280000061, 827.9884175999965,2139.858162 + 0.7000000000000001,24000, 0.7114363195691202, 1967.7611927999963, 1282.7801839999945,2377.62018 + 0.7000000000000001,24000, 0.7825799515260324, 3469.5872823999894, 1919.6414463999868, 2615.3821980000002 + 0.7000000000000001,24000, 0.8537235834829444, 5457.3734527999895, 2804.8510808000015,2853.144216 + 0.7000000000000001,24000, 0.9248672154398564, 7676.847810399934, 3882.259772799949,3090.906234 + 0.7000000000000001,24000, 0.9960108473967685, 10022.141392000012,5202.332943, 3328.6682520000004 + 0.7000000000000001,27000,0, 309.80001209536334, 309.80001209536334,0 + 0.7000000000000001,27000, 0.41631744344703775,-2030.502564,-415.9767512, 1391.3328960000001 + 0.7000000000000001,27000,0.485703684,-1136.722539,-50.144916,1623.221712 + 0.7000000000000001,27000, 0.5550899245960503,-242.9424976, 315.6869239999984, 1855.1105280000002 + 0.7000000000000001,27000, 0.6244761651705566, 650.8375472000016, 681.5188536000011, 2086.9993440000003 + 0.7000000000000001,27000,0.693862406, 1604.3760575999977, 1073.508332000001, 2318.8881600000004 + 0.7000000000000001,27000, 0.7632486463195691,2876.443616, 1604.9369904000048,2550.776976 + 0.7000000000000001,27000, 0.8326348868940755, 4577.720181600009, 2346.9107568000077, 2782.6657920000002 + 0.7000000000000001,27000, 0.9020211274685818, 6499.507540000001, 3256.3135439999824, 3014.5546080000004 + 0.7000000000000001,27000,0.971407368, 8408.642636000033, 4327.124971999997,3246.443424 + 0.7000000000000001,30000,0, 274.21618388722516, 274.21618388722516,0 + 0.7000000000000001,30000, 0.4057721095152603,-1848.1926,-395.1587,1356.09039 + 0.7000000000000001,30000, 0.4734007944344704,-1073.736,-76.5637, 1582.1054550000001 + 0.7000000000000001,30000, 0.5410294793536805,-299.2792, 242.0312000000011, 1808.1205200000002 + 0.7000000000000001,30000, 0.6086581642728905, 475.1775000000036, 560.6260999999989, 2034.1355850000002 + 0.7000000000000001,30000, 0.6762868491921006, 1260.9569000000017, 883.7584999999957,2260.15065 + 0.7000000000000001,30000, 0.7439155341113106, 2355.853799999982, 1334.3778999999956,2486.165715 + 0.7000000000000001,30000, 0.8115442190305207, 3815.430199999983, 1956.4703000000018,2712.18078 + 0.7000000000000001,30000, 0.8791729039497308, 5479.653299999997, 2727.064699999983,2938.195845 + 0.7000000000000001,30000, 0.9468015888689408, 7139.989300000011, 3630.668700000011, 3164.2109100000002 + 0.7000000000000001,33000,0, 241.94007125432375, 241.94007125432375,0 + 0.7000000000000001,33000, 0.39522776122082587,-1961.491211,-461.1621056, 1320.8511780000001 + 0.7000000000000001,33000, 0.4610990547576302,-1228.507937,-165.4048584, 1540.9930410000002 + 0.7000000000000001,33000, 0.5269703482944346,-495.5246472, 130.35234959999892, 1761.1349040000002 + 0.7000000000000001,33000, 0.5928416418312389, 237.45868159999532, 426.1096640000017, 1981.2767670000003 + 0.7000000000000001,33000, 0.6587129353680431, 970.4420496000007, 721.8667992000085,2201.41863 + 0.7000000000000001,33000, 0.7245842289048475, 1889.0833775999988, 1093.7703032000031, 2421.5604930000004 + 0.7000000000000001,33000, 0.7904555224416517, 3121.5364655999983, 1611.628215200007, 2641.7023560000002 + 0.7000000000000001,33000, 0.8563268159784562, 4583.718986400011, 2265.904840799988, 2861.8442190000005 + 0.7000000000000001,33000, 0.9221981095152604, 6002.152556800032, 3007.508638400013, 3081.9860820000004 + 0.7000000000000001,33000, 0.9880694030520648, 7187.438087200046, 3789.1980624000244, 3302.1279450000006 + 0.7000000000000001,36000,0, 212.74183353551976, 212.74183353551976,0 + 0.7000000000000001,36000, 0.38468242728904856,-2059.2275,-519.1376, 1285.6086720000003 + 0.7000000000000001,36000, 0.44879616517055665,-1382.7578,-247.76, 1499.8767840000003 + 0.7000000000000001,36000, 0.5129099030520647,-706.2883, 23.617600000001527, 1714.1448960000002 + 0.7000000000000001,36000, 0.5770236409335727,-29.8187, 294.9951999999993, 1928.4130080000002 + 0.7000000000000001,36000, 0.6411373788150808, 646.6509000000017, 566.3728000000002,2142.68112 + 0.7000000000000001,36000,0.705251117, 1411.1861999999949, 873.8886999999995, 2356.9492320000004 + 0.7000000000000001,36000, 0.7693648545780971, 2431.1022999999936,1294.1727, 2571.2173440000006 + 0.7000000000000001,36000, 0.8334785924596051,3647.2917, 1841.7520999999933, 2785.4854560000003 + 0.7000000000000001,36000, 0.8975923303411133, 4915.921900000033, 2478.612299999982, 2999.7535680000005 + 0.7000000000000001,36000, 0.9617060682226213, 5891.731899999996, 3106.173800000009, 3214.0216800000003 + 0.7000000000000001,39000,0, 184.25050480869658, 184.25050480869658,0 + 0.7000000000000001,39000, 0.38436899461400365,-2107.7874,-558.1494, 1284.5611800000001 + 0.7000000000000001,39000, 0.4484304937163376,-1490.2678,-310.4474, 1498.6547100000003 + 0.7000000000000001,39000, 0.5124919928186715,-872.7485,-62.7454, 1712.7482400000004 + 0.7000000000000001,39000, 0.5765534919210055,-255.2291, 184.95659999999972, 1926.8417700000005 + 0.7000000000000001,39000, 0.6406149910233395, 362.29030000000097, 432.65859999999856, 2140.9353000000006 + 0.7000000000000001,39000, 0.7046764901256735, 1041.8744999999979,706.0504, 2355.0288300000007 + 0.7000000000000001,39000, 0.7687379892280073, 1906.0031999999928, 1062.530999999998, 2569.1223600000003 + 0.7000000000000001,39000, 0.8327994883303412, 2980.816200000006, 1534.984599999994, 2783.2158900000004 + 0.7000000000000001,39000, 0.8968609874326752, 4045.224899999976, 2068.4953999999934, 2997.3094200000005 + 0.7000000000000001,39000, 0.9609224865350091, 4979.737799999997, 2649.1279000000054, 3211.4029500000006 + 0.7000000000000001,42000,0, 159.50988971285093, 159.50988971285093,0 + 0.7000000000000001,42000, 0.38436899461400365,-2873.663287,-928.133925, 1284.5611800000001 + 0.7000000000000001,42000, 0.4484304937163376,-2154.866738,-629.812775, 1498.6547100000003 + 0.7000000000000001,42000, 0.5124919928186715,-1436.070088,-331.4916813, 1712.7482400000004 + 0.7000000000000001,42000, 0.5765534919210055,-717.2733875,-33.17055625, 1926.8417700000005 + 0.7000000000000001,42000, 0.6406149910233395, 1.5232250000012106, 265.15056875000033, 2140.9353000000006 + 0.7000000000000001,42000, 0.7046764901256735, 698.9133437499992, 551.2258500000008, 2355.0288300000007 + 0.7000000000000001,42000, 0.7687379892280073, 1440.7435625000016, 856.9684062500002, 2569.1223600000003 + 0.7000000000000001,42000, 0.8327994883303412, 2383.6729937500036, 1265.3433000000025, 2783.2158900000004 + 0.7000000000000001,42000, 0.8968609874326752, 3287.898337500004, 1712.8468125000027, 2997.3094200000005 + 0.7000000000000001,42000, 0.9609224865350091, 4146.564725000006, 2227.3098000000005, 3211.4029500000006 +0.75,0,0, 855.7001096973654, 855.7001096973654,0 +0.75,0, 0.5179716113105923,-18285.47853,-645.1483, 1731.0611249999997 +0.75,0, 0.6043002131956912,-9540.39485, 598.1834999997695, 2019.5713124999997 +0.75,0, 0.6906288150807899,-795.288075, 1841.5272999993576,2308.0815 +0.75,0, 0.7769574169658886, 4091.459674998692, 3241.3097000006283,2596.591688 +0.75,0, 0.8632860188509874,-1575.096575, 4348.571224998934,2885.101875 +0.75,0, 0.9496146207360862,-8051.1931, 5629.756075000845,3173.612063 +0.75,3000,0, 774.9490034179007, 774.9490034179007,0 +0.75,3000, 0.5072880161579892, 1601.5549643855284,361.8885207,1695.35655 +0.75,3000, 0.5918360188509874, 1316.418209865977, 1056.841247035669,1977.915975 +0.75,3000, 0.6763840215439856, 1031.352407125728, 1751.8338367623105,2260.4754 +0.75,3000, 0.7609320242369838, 2263.8499732908494, 2657.520356068175, 2543.0348249999997 +0.75,3000, 0.8454800269299819, 9103.999038960108, 4282.6806021012835, 2825.5942499999996 +0.75,3000, 0.9300280296229801, 9983.064306937486, 6075.907967768982, 3108.1536749999996 +0.75,6000,0,700.338819,700.338819,0 +0.75,6000, 0.4966034223518852,-12371.0544, 32.396999999999764, 1659.6486375000004 +0.75,6000, 0.5793706594105328,-7401.0296, 742.3926000000225, 1936.2567437500004 +0.75,6000, 0.6621378964691802,-2430.9552, 1452.3883000000574, 2212.8648500000004 +0.75,6000, 0.7449051335278278, 2004.8667000001983, 2294.5112000001873, 2489.4729562500006 +0.75,6000, 0.8276723705864752, 8134.424200001864, 3762.568999998957, 2766.0810625000004 +0.75,6000, 0.9104396076451229, 6181.666799995997, 4549.810600001754, 3042.6891687500006 +0.75,6000, 0.9932068447037704, 12260.307399996025, 7801.6147000019755, 3319.297275000001 +0.75,9000,0, 631.5212824237357, 631.5212824237357,0 +0.75,9000, 0.48591982719928184,-1552.741938, 37.23154999999814,1623.944063 +0.75,9000, 0.5669064650658288,-254.5568375, 671.5559125000093, 1894.6014062499999 +0.75,9000, 0.6478931029323758,1043.6275, 1305.880124999991,2165.25875 +0.75,9000, 0.7288797407989228, 2545.7391749999206, 2060.823737499976,2435.916094 +0.75,9000, 0.8098663786654698, 4856.654062500365, 3143.3211374998496,2706.573438 +0.75,9000, 0.8908530165320168, 8208.842562500264, 4716.950587500167,2977.230781 +0.75,9000, 0.9718396543985637, 11922.290462499355, 6747.957287499631,3247.888125 +0.75,12000,0, 568.1546531528352, 568.1546531528352,0 +0.75,12000, 0.4752352333931778,-2414.210824,-100.71135, 1588.2361500000002 +0.75,12000, 0.5544411056253741,-906.1498806, 500.18910124999115, 1852.9421750000001 +0.75,12000, 0.6336469778575703,601.9109994, 1101.089558749955,2117.6482 +0.75,12000, 0.7128528500897666, 2180.2099449999732, 1772.4121643749666,2382.354225 +0.75,12000,0.792058722, 4219.624693124859, 2700.8673112498186,2647.06025 +0.75,12000, 0.8712645945541592, 6873.0429587494455, 3985.0316393746716,2911.766275 +0.75,12000, 0.9504704667863556, 10623.509388750004, 5843.055108749798, 3176.4723000000004 +0.75,15000,0, 509.9191522656429, 509.9191522656429,0 +0.75,15000, 0.4645516382405745,-1862.80462,-144.79246,1552.531575 +0.75,15000, 0.5419769112806703,-676.74108,392.5096,1811.286838 +0.75,15000,0.619402184, 509.32251999994423, 929.8118599999656,2070.0421 +0.75,15000, 0.6968274573608617, 1791.3456999999582,1506.92374,2328.797363 +0.75,15000, 0.7742527304009575, 3558.123859999942, 2301.515419999996, 2587.5526250000003 +0.75,15000, 0.8516780034410533, 5947.896059999968, 3408.1558600000812,2846.307888 +0.75,15000,0.929103276, 9145.537879999885, 4988.904719999826,3105.06315 +0.75,18000,0, 456.5038367745404, 456.5038367745404,0 +0.75,18000, 0.45386704443447035,-1895.056081,-217.8517586,1516.823663 +0.75,18000, 0.5295115518402155,-787.5809771, 273.87789857142786,1769.627606 +0.75,18000, 0.6051560592459605,319.8940414, 765.6074528571417,2022.43155 +0.75,18000, 0.6808005666517055, 1455.5080100000002, 1269.3942185714275,2275.235494 +0.75,18000, 0.7564450740574507, 2998.6396071428335, 1952.1675628571531,2528.039438 +0.75,18000, 0.8320895814631958, 5096.756127142885, 2906.1171314285775,2780.843381 +0.75,18000, 0.9077340888689407, 7828.234138571509, 4228.108160000011,3033.647325 +0.75,18000, 0.9833785962746858, 10768.633251428544,5803.710746,3286.451269 +0.75,21000,0, 407.6071663985174, 407.6071663985174,0 +0.75,21000, 0.44318344928186715,-1994.685804,-302.5400768,1481.119088 +0.75,21000, 0.5170473574955117,-942.6488512,155.040208,1727.972269 +0.75,21000, 0.5909112657091562, 109.3881231999998, 612.6203983999997,1974.82545 +0.75,21000, 0.6647751739228007, 1161.0153512000147, 1070.0083592000099,2221.678631 +0.75,21000, 0.7386390821364452, 2485.164615200006, 1647.0263584000202,2468.531813 +0.75,21000, 0.8125029903500898, 4301.394192799989, 2459.976487999987,2715.384994 +0.75,21000, 0.8863668985637343, 6674.529284799966, 3580.0849944000006,2962.238175 +0.75,21000, 0.9602308067773788, 9300.840274399947, 4949.787423199967,3209.091356 +0.75,24000,0, 362.9435673034746, 362.9435673034746,0 +0.75,24000,0.432498855,-2007.58331,-361.6053784,1445.411175 +0.75,24000, 0.5045819980550569,-1039.136757, 55.65934800000037,1686.313038 +0.75,24000, 0.5766651406343507,-70.6903952, 472.9240992000011,1927.2149 +0.75,24000, 0.6487482832136444,897.7559632, 890.1888023999949,2168.116763 +0.75,24000, 0.7208314257929382, 2011.3042271999866, 1370.678020800001, 2409.0186249999997 +0.75,24000, 0.7929145683722322, 3583.6642232000054, 2062.3739848000064,2649.920488 +0.75,24000,0.864997711, 5630.150037599998, 3003.0377831999936,2890.82235 +0.75,24000, 0.9370808535308198, 7910.878530399985, 4166.8922007999845,3131.724213 +0.75,27000,0, 322.2363050265196, 322.2363050265196,0 +0.75,27000, 0.42181526032315986,-2119.09668,-419.2096, 1409.7066000000002 +0.75,27000, 0.49211780371035313,-1195.703041,-35.728532, 1644.6577000000002 +0.75,27000, 0.5624203470975464,-272.309312, 347.75253280000027, 1879.6088000000002 +0.75,27000, 0.6327228904847397, 651.0843952000021, 731.2335711999981,2114.5599 +0.75,27000, 0.7030254338719331, 1645.588803999999, 1148.9930671999957, 2349.5110000000004 +0.75,27000, 0.7733279772591263, 2951.861701599997, 1717.383557599986,2584.4621 +0.75,27000, 0.8436305206463197, 4733.9284415999655, 2516.5905071999987, 2819.4132000000004 +0.75,27000, 0.9139330640335129, 6696.334550399998, 3488.7168504000247,3054.3643 +0.75,27000, 0.9842356074207063,8694.841082, 4653.553852799981, 3289.3154000000004 +0.75,30000,0, 285.2240362311289, 285.2240362311289,0 +0.75,30000, 0.41113066651705565,-2108.3203,-445.4413,1373.998688 +0.75,30000, 0.4796524442698983,-1261.5813,-99.4672,1602.998469 +0.75,30000, 0.5481742220227409,-414.8423, 246.50700000000393,1831.99825 +0.75,30000, 0.6166959997755835, 431.89660000002067, 592.4810999999994,2060.998031 +0.75,30000, 0.6852177775284262, 1309.3966000000087, 953.0467999999876, 2289.9978125000002 +0.75,30000, 0.7537395552812688, 2431.7521999999644, 1431.941199999993, 2518.9975937500003 +0.75,30000, 0.8222613330341113, 3950.678999999937, 2101.5139000000145,2747.997375 +0.75,30000, 0.8907831107869539, 5654.978000000027, 2922.052699999952,2976.997156 +0.75,30000, 0.9593048885397966, 7341.8223000000335, 3889.1440000000557,3205.996938 +0.75,33000,0, 251.6522645417062, 251.6522645417062,0 +0.75,33000, 0.4004470713644525,-1946.435609,-443.2462712, 1338.2941125000002 +0.75,33000, 0.46718824992519453,-1210.797384,-139.1566712, 1561.3431312500002 +0.75,33000, 0.5339294284859366,-475.1592888, 164.93281119999878, 1784.3921500000001 +0.75,33000, 0.6006706070466786, 260.4789239999961, 469.02240479999654,2007.441169 +0.75,33000, 0.6674117856074208, 994.9745520000021, 772.5832200000028,2230.490188 +0.75,33000, 0.7341529641681628, 1955.3644784000073, 1175.602210400012,2453.539206 +0.75,33000,0.800894143, 3233.559563200008, 1728.0857511999939, 2676.5882250000004 +0.75,33000,0.867635321, 4721.139566399974, 2421.335973600044, 2899.6372437500004 +0.75,33000, 0.9343764998503891, 6164.250866400064,3219.196424, 3122.6862625000003 +0.75,36000,0, 221.28192281009532, 221.28192281009532,0 +0.75,36000, 0.3897624775583483,-2063.2429,-494.9377,1302.5862 +0.75,36000, 0.4547228904847397,-1379.5815,-217.8789,1519.6839 +0.75,36000, 0.5196833034111311,-695.92, 59.17990000000403,1736.7816 +0.75,36000, 0.5846437163375224,-12.2586, 336.2385999999983,1953.8793 +0.75,36000, 0.6496041292639138, 671.4028000000025, 613.2975000000015,2170.977 +0.75,36000, 0.7145645421903053, 1465.9484999999856, 939.0536000000008,2388.0747 +0.75,36000, 0.7795249551166966, 2515.7606999999834, 1389.1945000000037,2605.1724 +0.75,36000,0.844485368, 3764.5788999999695, 1975.5850999999932,2822.2701 +0.75,36000, 0.9094457809694794, 5018.906200000103, 2636.8754999999487,3039.3678 +0.75,36000, 0.9744061938958708, 6063.219699999988, 3334.0171000000305, 3256.4655000000002 +0.75,39000,0, 191.64686749769822, 191.64686749769822,0 +0.75,39000, 0.38944490574506285,-2080.6943,-571.2826,1301.524875 +0.75,39000, 0.45435239003590666,-1459.0957,-309.6625,1518.445688 +0.75,39000, 0.5192598743267505,-837.4968,-48.0423,1735.3665 +0.75,39000, 0.5841673586175943,-215.898, 213.5778999999992,1952.287313 +0.75,39000, 0.6490748429084381, 405.70080000000223, 475.1979999999941,2169.208125 +0.75,39000, 0.7139823271992819, 1099.181799999985, 763.9191000000053,2386.128938 +0.75,39000, 0.7788898114901257, 1982.8291999999897, 1143.8013999999948,2603.04975 +0.75,39000, 0.8437972957809695, 3074.287800000015, 1651.355299999991,2819.970563 +0.75,39000, 0.9087047800718133, 4156.584999999953, 2211.0363999999727,3036.891375 +0.75,39000, 0.9736122643626571, 5099.631799999978, 2826.007600000027,3253.812188 +0.75,42000,0, 165.91309060515698, 165.91309060515698,0 +0.75,42000, 0.38944490574506285,-2435.906163,-744.892175,1301.524875 +0.75,42000, 0.45435239003590666,-1798.989538,-475.295525,1518.445688 +0.75,42000, 0.5192598743267505,-1162.072988,-205.6988188,1735.3665 +0.75,42000, 0.5841673586175943,-525.1563625, 63.89788125000091,1952.287313 +0.75,42000, 0.6490748429084381, 111.76020000000042, 333.4945312500009,2169.208125 +0.75,42000, 0.7139823271992819, 748.0753812500001, 601.3255249999985,2386.128938 +0.75,42000, 0.7788898114901257, 1519.3070124999995, 929.6106687500013,2603.04975 +0.75,42000, 0.8437972957809695, 2473.777756250016, 1366.2164500000126,2819.970563 +0.75,42000, 0.9087047800718133, 3415.487862500008, 1847.1166375000055,3036.891375 +0.75,42000, 0.9736122643626571,4233.545575, 2363.7417250000076,3253.812188 +0.8,0,0, 891.9670832142106, 891.9670832142106,0 +0.8,0, 0.5251882944344703,-24946.3002,-978.4093, 1755.1792799999998 +0.8,0, 0.6127196768402154,-13342.1622, 462.9512999997122, 2047.7091599999999 +0.8,0, 0.7002510592459604,-1737.9922, 1904.3283999991927,2340.23904 +0.8,0, 0.7877824416517055, 4066.913299998261, 3467.1792000007335,2632.76892 +0.8,0, 0.8753138240574506,-5182.1052, 4459.938399998611,2925.2988 +0.8,0, 0.9628452064631957,-15340.1072, 5497.337800000968,3217.82868 +0.8,3000,0, 807.7935182956683, 807.7935182956683,0 +0.8,3000, 0.5143558491921005, 3115.3774764991103, 477.1100449146126, 1718.9772480000001 +0.8,3000, 0.6000818240574507, 1966.0665154408453, 1170.4083383575091, 2005.4734560000002 +0.8,3000, 0.6858077989228007, 816.8578778620677, 1863.7640758176378,2291.969664 +0.8,3000, 0.7715337737881509, 1744.3917797484191, 2801.638409990247,2578.465872 +0.8,3000,0.857259749, 10327.326346044792, 4579.072520789531, 2864.9620800000002 +0.8,3000,0.942985724, 10024.978981812033, 6446.765878679083, 3151.4582880000003 +0.8,6000,0, 730.0211447076573, 730.0211447076573,0 +0.8,6000, 0.5035223913824058,-17089.1935, 45.787399999999735, 1682.7718320000004 +0.8,6000, 0.5874427899461402,-10597.8616,781.2133, 1963.2338040000004 +0.8,6000, 0.6713631885098744,-4106.4574, 1516.639300000064, 2243.6957760000005 +0.8,6000, 0.7552835870736088, 1522.2208000002993, 2403.424400000244, 2524.1577480000005 +0.8,6000, 0.8392039856373431,9390.3585, 4073.4271999985795, 2804.6197200000006 +0.8,6000, 0.9231243842010773, 4708.833099994736, 4473.1850000023505, 3085.0816920000007 +0.8,9000,0, 658.2869277303441, 658.2869277303441,0 +0.8,9000,0.492689946,-1581.926, 85.61319999999782, 1646.5698000000002 +0.8,9000, 0.5748049371633753,-311.0476, 736.1732000000105, 1920.9981000000002 +0.8,9000, 0.6569199281867146, 959.8308000001607, 1386.733199999981, 2195.4264000000003 +0.8,9000, 0.7390349192100539, 2485.5355999998797, 2190.617399999954, 2469.8547000000003 +0.8,9000, 0.8211499102333932, 5006.255900000543, 3365.8498999998087, 2744.2830000000004 +0.8,9000, 0.9032649012567326, 8522.402300000365, 5072.7495000001745, 3018.7113000000004 +0.8,9000,0.985379892, 12028.083999999071, 7177.7196999995485, 3293.1396000000004 +0.8,12000,0, 592.2346427728596, 592.2346427728596,0 +0.8,12000, 0.4818564883303411,-2237.6416,-42.7688,1610.364384 +0.8,12000, 0.5621659030520646,-787.3421, 570.6375999999894,1878.758448 +0.8,12000, 0.6424753177737882, 662.9575000000891, 1184.044099999943,2147.152512 +0.8,12000, 0.7227847324955117, 2163.187299999944, 1880.2307999999502,2415.546576 +0.8,12000, 0.8030941472172353,4246.0806, 2874.182099999748, 2683.9406400000003 +0.8,12000, 0.8834035619389589,7036.1582, 4283.759299999549, 2952.3347040000003 +0.8,12000, 0.9637129766606822, 10934.911100000085, 6257.372099999738,3220.728768 +0.8,15000,0, 531.5309578285645, 531.5309578285645,0 +0.8,15000, 0.47102404308797136,-1754.0936,-93.783, 1574.1623520000003 +0.8,15000,0.54952805,-610.5999, 455.3898999999899, 1836.5227440000003 +0.8,15000, 0.6280320574506285, 532.8937999999116, 1004.5627999999449, 2098.8831360000004 +0.8,15000, 0.7065360646319571, 1815.9672999999357, 1607.0071000000114, 2361.2435280000004 +0.8,15000, 0.7850400718132856,3648.4075, 2458.4741000000004, 2623.6039200000005 +0.8,15000, 0.8635440789946142, 6097.683599999989, 3654.2615000001324, 2885.9643120000005 +0.8,15000, 0.9420480861759427, 9427.890599999919, 5357.9691999997385, 3148.3247040000006 +0.8,18000,0, 475.8517512728752, 475.8517512728752,0 +0.8,18000, 0.4601905852782765,-1752.1545,-164.554,1537.956936 +0.8,18000, 0.5368890161579892,-697.4081,333.9358, 1794.2830920000001 +0.8,18000, 0.6135874470377021, 357.3381999999945, 832.4254999999966,2050.609248 +0.8,18000, 0.6902858779174148, 1487.065700000014, 1362.2966000000101, 2306.9354040000003 +0.8,18000, 0.7669843087971275, 3076.798799999934, 2090.8596000000243, 2563.2615600000004 +0.8,18000, 0.8436827396768404, 5257.201700000051, 3116.5737000000263, 2819.5877160000005 +0.8,18000,0.920381171, 8079.039100000138,4535.6128,3075.913872 +0.8,18000, 0.9970796014362657, 11682.747099999984, 6187.112300000163,3332.240028 +0.8,21000,0, 424.8827027009254, 424.8827027009254,0 +0.8,21000, 0.4493581400359067,-1936.362344,-261.0069448, 1501.7549040000001 +0.8,21000, 0.5242511633752245,-895.9699432, 206.99386800000124, 1752.0473880000002 +0.8,21000, 0.5991441867145423, 144.42243520000366, 674.9947024000022, 2002.3398720000002 +0.8,21000,0.67403721, 1190.5510232000318, 1145.6883312000218,2252.632356 +0.8,21000, 0.7489302333931778, 2572.7608472000024, 1768.718302400065,2502.92484 +0.8,21000, 0.8238232567324956, 4454.742440800006, 2643.417227999981,2753.217324 +0.8,21000, 0.8987162800718134, 6906.615712799916, 3843.6439783999976, 3003.5098080000002 +0.8,21000, 0.9736093034111312, 9576.006558399831, 5301.669015199899, 3253.8022920000003 +0.8,24000,0, 378.32613485761414, 378.32613485761414,0 +0.8,24000, 0.4385246822262119,-1867.215134,-320.3754344,1465.549488 +0.8,24000, 0.5116121292639139,-932.3074488, 106.1674480000007,1709.807736 +0.8,24000, 0.5846995763016158, 2.6001568000203186, 532.7104272000039,1954.065984 +0.8,24000, 0.6577870233393177, 937.5077712000124, 959.2531983999899,2198.324232 +0.8,24000, 0.7308744703770198, 2096.598395199967, 1479.2069728000095,2442.58248 +0.8,24000, 0.8039619174147218, 3710.5476312000374, 2214.739116800036,2686.840728 +0.8,24000, 0.8770493644524238, 5841.670121600021, 3229.441011200005,2931.098976 +0.8,24000, 0.9501368114901257, 8176.213386400026, 4481.946372799968, 3175.3572240000003 +0.8,27000,0, 335.8935844964216, 335.8935844964216,0 +0.8,27000, 0.42769223698384207,-1977.18804,-375.29336, 1429.3474560000002 +0.8,27000, 0.4989742764811491,-1083.480113, 14.609547999999618, 1667.5720320000003 +0.8,27000, 0.5702563159784562,-189.772212, 404.5124648000015, 1905.7966080000003 +0.8,27000, 0.6415383554757631, 703.9355832000083, 794.4152791999975,2144.021184 +0.8,27000,0.712820395, 1692.4839440000023, 1230.7780751999899, 2382.2457600000002 +0.8,27000, 0.7841024344703771, 3068.2069456000063, 1849.3239215999743, 2620.4703360000003 +0.8,27000, 0.8553844739676841, 4908.5317655999415, 2704.7064952000183, 2858.6949120000004 +0.8,27000, 0.9266665134649912, 6922.4723264000595, 3748.6854464001153, 3096.9194880000005 +0.8,27000, 0.9979485529622982,9102.290086, 5050.496244799962, 3335.1440640000005 +0.8,30000,0, 297.3126318163514, 297.3126318163514,0 +0.8,30000, 0.41685877917414726,-2064.0918,-438.634, 1393.1420400000002 +0.8,30000, 0.48633524236983844,-1218.4246,-77.9119,1625.33238 +0.8,30000, 0.5558117055655297,-372.7574, 282.81030000000845, 1857.5227200000002 +0.8,30000, 0.6252881687612208, 472.90990000005195, 643.5324000000016,2089.71306 +0.8,30000, 0.6947646319569121, 1370.5848000000206, 1028.2997999999736,2321.9034 +0.8,30000, 0.7642410951526033, 2530.4713999999485, 1542.4593999999915, 2554.0937400000003 +0.8,30000, 0.8337175583482945, 4107.3310999998575, 2260.4058000000323, 2786.2840800000004 +0.8,30000, 0.9031940215439858, 5852.453600000058, 3140.5597999999054, 3018.4744200000005 +0.8,30000, 0.9726704847396769, 7598.472200000073,4178.7285,3250.66476 +0.8,33000,0, 262.31799417076513, 262.31799417076513,0 +0.8,33000, 0.4060263339317774,-2072.612345,-464.6530352,1356.940008 +0.8,33000, 0.47369738958707364,-1296.432944,-141.0548352, 1583.0966760000001 +0.8,33000, 0.5413684452423699,-520.2535648, 182.54331519999724, 1809.2533440000002 +0.8,33000, 0.6090395008976661, 255.9258639999875, 506.1415207999882, 2035.4100120000003 +0.8,33000, 0.6767105565529624, 1036.6761520000123, 831.8546400000043, 2261.5666800000004 +0.8,33000, 0.7443816122082587, 2035.1663264000142, 1265.5596984000265, 2487.7233480000004 +0.8,33000, 0.8120526678635548, 3365.893767200005, 1857.8651751999726,2713.880016 +0.8,33000, 0.8797237235188511, 4871.020294399914, 2596.612225600116,2940.036684 +0.8,33000, 0.9473947791741473, 6356.582314400168, 3459.1663840000238, 3166.1933520000002 +0.8,36000,0, 230.66047207444984, 230.66047207444984,0 +0.8,36000, 0.39519287612208265,-2093.6506,-502.8068, 1320.7345920000002 +0.8,36000, 0.46105835547576307,-1394.4094,-211.8819, 1540.8570240000001 +0.8,36000, 0.5269238348294435,-695.1683,79.0429, 1760.9794560000003 +0.8,36000,0.592789314, 4.073000000006379, 369.9678000000034, 1981.1018880000004 +0.8,36000, 0.6586547935368043, 703.3140999999993, 660.8927000000034, 2201.2243200000003 +0.8,36000, 0.7245202728904848, 1537.8642999999938, 1014.5940999999863, 2421.3467520000004 +0.8,36000, 0.7903857522441653, 2605.121800000032, 1502.2316999999891, 2641.4691840000005 +0.8,36000, 0.8562512315978458, 3906.2864000000573, 2121.9667999999783, 2861.5916160000006 +0.8,36000, 0.9221167109515261, 5160.527799999968, 2819.0461000000205, 3081.7140480000003 +0.8,36000, 0.9879821903052066, 6214.967299999988, 3542.957500000002, 3301.8364800000004 +0.8,39000,0, 199.76939990053197, 199.76939990053197,0 +0.8,39000, 0.3948708797127469,-2166.2283,-575.2119, 1319.6584800000003 +0.8,39000, 0.46068269299820475,-1512.1345,-300.6274, 1539.6015600000003 +0.8,39000, 0.5264945062836626,-858.0406,-26.0431, 1759.5446400000003 +0.8,39000, 0.5923063195691204,-203.9467, 248.5413000000005, 1979.4877200000003 +0.8,39000, 0.6581181328545782, 450.14720000000364,523.1257, 2199.4308000000005 +0.8,39000,0.723929946, 1165.0148999999974, 829.2135999999978, 2419.3738800000006 +0.8,39000, 0.7897417594254938, 2072.4602000000255, 1242.0977000000141, 2639.3169600000006 +0.8,39000, 0.8555535727109517, 3202.9565000000207, 1778.1105000000325, 2859.2600400000006 +0.8,39000, 0.9213653859964095,4305.4131, 2377.555700000009, 3079.2031200000006 +0.8,39000, 0.9871771992818673, 5206.169899999987, 2987.7084999999847, 3299.1462000000006 +0.8,42000,0,172.9449533,172.9449533,0 +0.8,42000, 0.3948708797127469,-2368.1668,-692.7329875, 1319.6584800000003 +0.8,42000, 0.46068269299820475,-1730.60195,-422.721675, 1539.6015600000003 +0.8,42000, 0.5264945062836626,-1093.0371,-152.7102438, 1759.5446400000003 +0.8,42000, 0.5923063195691204,-455.4723625, 117.30118124999811, 1979.4877200000003 +0.8,42000, 0.6581181328545782, 182.0924374999938, 387.3125562500025, 2199.4308000000005 +0.8,42000,0.723929946,816.2892187, 659.9683937500035, 2419.3738800000006 +0.8,42000, 0.7897417594254938, 1604.931393750002, 1013.4273500000048, 2639.3169600000006 +0.8,42000, 0.8555535727109517, 2582.4594437500164, 1475.4576624999977, 2859.2600400000006 +0.8,42000, 0.9213653859964095, 3546.2131375000176, 1986.8950687500085, 3079.2031200000006 +0.8,42000, 0.9871771992818673, 4367.351431250019, 2529.5573250000166, 3299.1462000000006 + 0.8500000000000001,0,0, 931.6846058533836, 931.6846058533836,0 + 0.8500000000000001,0, 0.5328705700179532,-33163.22545,-1399.9068, 1780.8534449999997 + 0.8500000000000001,0, 0.6216823316876122,-18017.2055, 282.62489999964583,2077.662353 + 0.8500000000000001,0,0.710494093,-2871.14265, 1965.1785999990016,2374.47126 + 0.8500000000000001,0, 0.7993058550269299, 4049.943049997757, 3717.240900000844, 2671.2801674999996 + 0.8500000000000001,0, 0.8881176166965888,-9629.86785, 4553.7559499982335,2968.089075 + 0.8500000000000001,0, 0.9769293783662476,-24268.9503, 5269.307950001098, 3264.8979824999997 + 0.8500000000000001,3000,0, 843.7629592699609, 843.7629592699609,0 + 0.8500000000000001,3000,0.521879671, 5025.556129412688,611.0259013,1744.121862 + 0.8500000000000001,3000, 0.6088596166965888, 2794.123445415729, 1298.7951950793586,2034.808839 + 0.8500000000000001,3000, 0.6958395619389587, 562.8324571984385, 1986.6439804729926,2325.495816 + 0.8500000000000001,3000, 0.7828195071813285, 1107.6344590059998, 2956.5198293123876,2616.182793 + 0.8500000000000001,3000, 0.8697994524236985, 11867.249507529436, 4905.024303477822, 2906.8697700000002 + 0.8500000000000001,3000, 0.9567793976660682, 10082.003075087057, 6851.6295189892335,3197.556747 + 0.8500000000000001,6000,0, 762.5275363533208, 762.5275363533208,0 + 0.8500000000000001,6000, 0.5108877455116697,-23034.4839,52.5672, 1707.3868455000002 + 0.8500000000000001,6000,0.596035703,-14624.0435, 816.1443000000294, 1991.9513197500003 + 0.8500000000000001,6000, 0.6811836606822264,-6213.5021,1579.7215, 2276.5157940000004 + 0.8500000000000001,6000, 0.7663316182675045, 913.1722000004283, 2515.0297000003125, 2561.0802682500002 + 0.8500000000000001,6000, 0.8514795758527829, 10987.254100002923,4430.0484, 2845.6447425000006 + 0.8500000000000001,6000, 0.9366275334380612, 2773.1969999932335, 4305.699400003077, 3130.2092167500005 + 0.8500000000000001,9000,0, 687.5991371685959, 687.5991371685959,0 + 0.8500000000000001,9000, 0.4998968469479354,-1710.26525, 130.68269999999754, 1670.6552625000002 + 0.8500000000000001,9000, 0.5832129881059247,-447.31835, 799.9592500000107, 1949.0978062500003 + 0.8500000000000001,9000, 0.6665291292639139, 815.6299000001924, 1469.236099999967,2227.54035 + 0.8500000000000001,9000, 0.7498452704219031, 2394.568399999829, 2330.5846499999247,2505.982894 + 0.8500000000000001,9000, 0.8331614115798923, 5224.318450000771, 3617.3436499997624,2784.425438 + 0.8500000000000001,9000, 0.9164775527378817, 8926.234550000489, 5474.270450000165, 3062.8679812500004 + 0.8500000000000001,9000, 0.9997936938958708, 12111.286549998713, 7637.388949999461, 3341.3105250000003 + 0.8500000000000001,12000,0, 618.6056751513992, 618.6056751513992,0 + 0.8500000000000001,12000,0.488904921,-1811.805983,32.77509091, 1633.9202460000001 + 0.8500000000000001,12000, 0.5703890745062837,-502.1741282,654.5961345,1906.240287 + 0.8500000000000001,12000, 0.6518732280071813, 807.4581645455567, 1276.4174145453858,2178.560328 + 0.8500000000000001,12000, 0.7333573815080789, 2121.807216363542, 1988.2466427272022,2450.880369 + 0.8500000000000001,12000, 0.8148415350089766, 4239.494582727135, 3055.995438181486,2723.20041 + 0.8500000000000001,12000, 0.8963256885098743, 7230.834259998971, 4629.116588181222,2995.520451 + 0.8500000000000001,12000,0.977809842, 11284.50162545477, 6709.4267509087695, 3267.8404920000003 + 0.8500000000000001,15000,0, 555.1989756828818, 555.1989756828818,0 + 0.8500000000000001,15000, 0.4779140224416518,-1600.8679,-37.4875, 1597.1886630000004 + 0.8500000000000001,15000, 0.5575663595152605,-510.2755, 523.8966999999848, 1863.3867735000003 + 0.8500000000000001,15000, 0.6372186965888691,580.3165, 1085.2803999999194, 2129.5848840000003 + 0.8500000000000001,15000, 0.7168710336624776, 1849.748999999912, 1706.954300000012, 2395.7829945000003 + 0.8500000000000001,15000, 0.7965233707360863, 3764.1081999998705, 2623.5226000000093, 2661.9811050000003 + 0.8500000000000001,15000, 0.8761757078096949, 6266.996700000038,3935.0378, 2928.1792155000003 + 0.8500000000000001,15000, 0.9558280448833036, 9731.933500000026, 5761.926199999636, 3194.3773260000007 + 0.8500000000000001,18000,0,497.0404846,497.0404846,0 + 0.8500000000000001,18000, 0.4669220964991024,-1687.664315,-117.824395,1560.453647 + 0.8500000000000001,18000, 0.5447424459156194,-658.79398, 392.73890499999624, 1820.5292542500001 + 0.8500000000000001,18000, 0.6225627953321364, 370.07645499999757, 903.3020149999953,2080.604862 + 0.8500000000000001,18000, 0.7003831447486536, 1514.0949650000405, 1460.1270850000383,2340.68047 + 0.8500000000000001,18000, 0.7782034941651707, 3095.6987249998615,2219.59968,2600.756078 + 0.8500000000000001,18000, 0.8560238435816877, 5489.965405000091, 3375.713290000069,2860.831685 + 0.8500000000000001,18000, 0.9338441929982048, 8311.905815000237, 4850.812890000003,3120.907293 + 0.8500000000000001,21000,0, 443.80188557335464, 443.80188557335464,0 + 0.8500000000000001,21000, 0.45593119793536807,-2030.569984,-220.8750328,1523.722064 + 0.8500000000000001,21000, 0.5319197309245961,-963.9674152, 255.8271280000035, 1777.6757407500002 + 0.8500000000000001,21000, 0.6079082639138241, 102.63542720000945, 732.5299664000062, 2031.6294180000002 + 0.8500000000000001,21000,0.683896797, 1196.4849752000518, 1222.023383200036,2285.583095 + 0.8500000000000001,21000, 0.7598853298922801,2703.483559, 1908.7494064001414,2539.536773 + 0.8500000000000001,21000, 0.8358738628815081, 4652.772908800035, 2847.8459679999723,2793.49045 + 0.8500000000000001,21000, 0.9118623958707361, 7160.375460799806, 4137.662922399976,3047.444127 + 0.8500000000000001,21000, 0.9878509288599642, 9868.793802399614, 5685.472187199768, 3301.3978042500003 + 0.8500000000000001,24000,0, 395.17224623209586, 395.17224623209586,0 + 0.8500000000000001,24000, 0.4449392719928187,-2172.624298,-307.1800504,1486.987047 + 0.8500000000000001,24000, 0.5190958173249551,-1129.085861, 139.10084800000098,1734.818222 + 0.8500000000000001,24000, 0.5932523626570916,-85.5475712,585.3815352,1982.649396 + 0.8500000000000001,24000, 0.6674089079892279, 957.9908592000262, 1031.6623543999842,2230.480571 + 0.8500000000000001,24000, 0.7415654533213645, 2199.4739431999415, 1595.9512448000323,2478.311745 + 0.8500000000000001,24000, 0.8157219986535009, 3874.790819200108,2387.007069,2726.14292 + 0.8500000000000001,24000, 0.8898785439856374, 6064.753545600091, 3480.3374192000456,2973.974094 + 0.8500000000000001,24000, 0.9640350893177738, 8458.319502400163, 4809.629764799953, 3221.8052685000002 + 0.8500000000000001,27000,0, 350.8502586805358, 350.8502586805358,0 + 0.8500000000000001,27000, 0.4339483734290844,-1979.7891,-346.64932,1450.255464 + 0.8500000000000001,27000, 0.5062731023339317,-1075.611905, 55.24152799999922,1691.964708 + 0.8500000000000001,27000, 0.5785978312387792,-171.434812, 457.1325168000036,1933.673952 + 0.8500000000000001,27000, 0.6509225601436266, 732.7423512000179, 859.0235672000003,2175.383196 + 0.8500000000000001,27000,0.723247289, 1756.2202840000068, 1325.537763199979, 2417.0924400000004 + 0.8500000000000001,27000, 0.7955720179533213, 3233.389629600036, 2003.429225599963,2658.801684 + 0.8500000000000001,27000, 0.8678967468581688, 5107.153129599948, 2912.376763200078,2900.510928 + 0.8500000000000001,27000, 0.9402214757630163, 7204.675762400198, 4059.925602400287, 3142.2201720000003 + 0.8500000000000001,30000,0, 310.55137280500526, 310.55137280500526,0 + 0.8500000000000001,30000, 0.42295644748653505,-1029.5775,-235.4189,1413.520448 + 0.8500000000000001,30000, 0.4934491887342909,-430.8531, 92.35080000000485, 1649.1071887500002 + 0.8500000000000001,30000, 0.5639419299820467, 167.87220000001005, 420.11980000001483, 1884.6939300000001 + 0.8500000000000001,30000, 0.6344346712298026, 766.5980000001027, 747.8891000000071,2120.280671 + 0.8500000000000001,30000, 0.7049274124775584, 1434.0783000000406, 1102.439899999954, 2355.8674125000002 + 0.8500000000000001,30000, 0.7754201537253143, 2647.118899999943, 1664.2917999999909, 2591.4541537500004 + 0.8500000000000001,30000, 0.8459128949730701, 4277.523699999738, 2427.7540000000527,2827.040895 + 0.8500000000000001,30000, 0.9164056362208259, 6051.799800000066, 3382.778499999846, 3062.6276362500003 + 0.8500000000000001,30000, 0.9868983774685818, 7919.080200000133, 4499.013400000312, 3298.2143775000004 + 0.8500000000000001,33000,0, 273.9984934495011, 273.9984934495011,0 + 0.8500000000000001,33000, 0.4119655489228008,-2004.589161,-492.5327192, 1376.7888645000003 + 0.8500000000000001,33000, 0.48062647374326756,-1230.077204,-145.3159192, 1606.2536752500002 + 0.8500000000000001,33000, 0.5492873985637343,-455.5648208, 201.90113919999445, 1835.7184860000002 + 0.8500000000000001,33000, 0.6179483233842012, 318.9473039999698, 549.1179167999743, 2065.1832967500004 + 0.8500000000000001,33000,0.686609248, 1132.3110520000323, 914.3112600000022,2294.648108 + 0.8500000000000001,33000, 0.7552701730251348, 2141.3011144000175, 1368.0828264000447, 2524.1129182500003 + 0.8500000000000001,33000, 0.8239310978456016, 3527.2610911999896, 2014.699119199929, 2753.5777290000005 + 0.8500000000000001,33000, 0.8925920226660683, 5086.397962399796, 2807.667837600225, 2983.0425397500003 + 0.8500000000000001,33000, 0.9612529474865351,6603.009402, 3726.8325440000453, 3212.5073505000005 + 0.8500000000000001,36000,0, 240.9313247706801, 240.9313247706801,0 + 0.8500000000000001,36000, 0.4009736229802514,-1990.3196,-480.3564, 1340.0538480000002 + 0.8500000000000001,36000, 0.46780256014362664,-1303.5686,-180.9795, 1563.3961560000002 + 0.8500000000000001,36000, 0.5346314973070019,-616.8176, 118.39739999998554, 1786.7384640000002 + 0.8500000000000001,36000, 0.6014604344703771,69.9334, 417.7744000000083, 2010.0807720000003 + 0.8500000000000001,36000, 0.6682893716337523, 756.6846000000004,717.1512, 2233.4230800000005 + 0.8500000000000001,36000, 0.7351183087971276, 1609.4240999999963, 1100.4500999999834, 2456.7653880000003 + 0.8500000000000001,36000, 0.8019472459605028, 2729.0259000000847, 1623.1648999999843, 2680.1076960000005 + 0.8500000000000001,36000, 0.8687761831238779, 4062.8066000001627, 2281.646999999975, 2903.4500040000003 + 0.8500000000000001,36000, 0.9356051202872533, 5356.056599999936, 3038.809800000109, 3126.7923120000005 + 0.8500000000000001,39000,0, 208.66473450701983, 208.66473450701983,0 + 0.8500000000000001,39000, 0.4006469165170557,-2125.7161,-543.8445, 1338.9619950000001 + 0.8500000000000001,39000, 0.4674214026032317,-1468.4615,-264.1049, 1562.1223275000002 + 0.8500000000000001,39000, 0.5341958886894076,-811.207, 15.634600000020747, 1785.2826600000003 + 0.8500000000000001,39000, 0.6009703747755836,-153.9524, 295.3741000000012, 2008.4429925000004 + 0.8500000000000001,39000, 0.6677448608617595, 503.3022000000066,575.1136, 2231.6033250000005 + 0.8500000000000001,39000, 0.7345193469479355, 1234.885399999997, 903.3082999999999, 2454.7636575000006 + 0.8500000000000001,39000, 0.8012938330341114, 2177.3831000000637, 1347.0217000000405, 2677.9239900000002 + 0.8500000000000001,39000, 0.8680683191202874, 3346.727800000066, 1917.0786000000792, 2901.0843225000003 + 0.8500000000000001,39000, 0.9348428052064633, 4473.484400000025, 2564.7319000000352, 3124.2446550000004 + 0.8500000000000001,42000,0, 180.64584855674735, 180.64584855674735,0 + 0.8500000000000001,42000, 0.4006469165170557,-2263.5729,-625.9026625, 1338.9619950000001 + 0.8500000000000001,42000, 0.4674214026032317,-1632.925075,-358.607625, 1562.1223275000002 + 0.8500000000000001,42000, 0.5341958886894076,-1002.277125,-91.31255625, 1785.2826600000003 + 0.8500000000000001,42000, 0.6009703747755836,-371.6293875, 175.9825437499955, 2008.4429925000004 + 0.8500000000000001,42000, 0.6677448608617595, 259.01843749998704, 443.27764375000606, 2231.6033250000005 + 0.8500000000000001,42000, 0.7345193469479355, 901.3025562499994, 728.5847062500076, 2454.7636575000006 + 0.8500000000000001,42000, 0.8012938330341114, 1698.1124562500038, 1105.3938000000114, 2677.9239900000002 + 0.8500000000000001,42000, 0.8680683191202874, 2714.2529562500267, 1596.3396374999934, 2901.0843225000003 + 0.8500000000000001,42000, 0.9348428052064633, 3678.5199625000514, 2136.845056250046, 3124.2446550000004 +0.9,0,0, 975.0792460884875, 975.0792460884875,0 +0.9,0, 0.5410184380610412,-43097.713,-1919.2165, 1808.0836199999999 +0.9,0, 0.6311881777378814,-23656.4273, 52.01689999957068, 2109.4308899999996 +0.9,0, 0.7213579174147217,-4215.0856, 2023.2788999987815,2410.77816 +0.9,0, 0.8115276570915619, 4039.106399997152, 3992.8711000009575,2712.12543 +0.9,0, 0.9016973967684021,-15008.395, 4626.620399997793,3013.4727 +0.9,0, 0.9918671364452423,-35007.5352, 4933.336300001234, 3314.8199699999996 +0.9,3000,0, 883.0625138951971, 883.0625138951971,0 +0.9,3000, 0.5298594829443446, 7379.202123126254, 765.3843898694084, 1770.7903919999997 +0.9,3000, 0.6181693967684021, 3821.475599790627, 1443.199917201217, 2065.9221239999997 +0.9,3000, 0.7064793105924595, 263.93904513484995, 2121.1219507283768, 2361.0538559999995 +0.9,3000, 0.7947892244165169, 338.33721106358644, 3122.462714034603, 2656.1855879999994 +0.9,3000, 0.8830991382405743, 13757.050123414076, 5262.031950166164, 2951.317319999999 +0.9,3000, 0.9714090520646318, 10154.064186762618, 7292.442988699428, 3246.4490519999995 +0.9,6000,0, 798.0434264963205, 798.0434264963205,0 +0.9,6000, 0.5186994847396769,-30345.9024, 51.63349999999974,1733.493678 +0.9,6000, 0.6051493988629563,-19574.4357, 846.2388000000326,2022.409291 +0.9,6000, 0.6915993129862358,-8802.8326, 1640.8442000000748,2311.324904 +0.9,6000, 0.7780492271095153, 160.31250000057844, 2628.670200000392,2600.240517 +0.9,6000, 0.8644991412327948, 12963.201800003575, 4836.635199997567, 2889.1561300000003 +0.9,6000, 0.9509490553560742, 312.3434999914898, 4033.688600003943,3178.071743 +0.9,9000,0, 719.6251221381219, 719.6251221381219,0 +0.9,9000, 0.5075405296229802,-1960.593729, 170.7523571428543, 1696.2004499999998 +0.9,9000, 0.5921306178934769,-681.7229143, 861.6450285714388, 1978.9005249999998 +0.9,9000, 0.6767207061639736, 597.1513142859377, 1552.5384857142335, 2261.6005999999998 +0.9,9000, 0.7613107944344703, 2264.9286857140532, 2480.963671428456, 2544.3006749999995 +0.9,9000,0.845900883, 5521.126628572485, 3900.6640857139973, 2827.0007499999997 +0.9,9000, 0.9304909709754637, 9431.862757143494, 5925.467042857279,3109.700825 +0.9,12000,0, 647.4181837534927, 647.4181837534927,0 +0.9,12000, 0.4963805314183123,-1062.255344, 130.02288585858622, 1658.9037359999998 +0.9,12000,0.57911062,-1.886726061, 754.7012670706948, 1935.3876919999998 +0.9,12000, 0.6618407085577498, 1058.4828937374864, 1379.380071515072,2211.871648 +0.9,12000, 0.7445707971274685, 2047.5740387877322, 2094.170953131217,2488.355604 +0.9,12000, 0.8273008856971873, 4187.015877575652, 3244.858557171291,2764.83956 +0.9,12000,0.910030974, 7457.427642220891, 5027.055212726513,3041.323516 +0.9,12000, 0.9927610628366246, 11669.165264040837, 7199.905628080427, 3317.8074719999995 +0.9,15000,0, 581.0582199564191, 581.0582199564191,0 +0.9,15000, 0.4852215763016158,-1383.5334, 24.851399999998264,1621.610508 +0.9,15000, 0.5660918390185518,-360.5144, 598.6816499999785, 1891.8789259999999 +0.9,15000, 0.6469621017354877, 662.5032999998161, 1172.510499999888,2162.147344 +0.9,15000, 0.7278323644524237, 1893.1568499998843, 1803.2820000000097,2432.415762 +0.9,15000, 0.8087026271693597, 3907.6206499998166, 2794.3663000000224,2702.68418 +0.9,15000, 0.8895728898862956, 6454.628500000117, 4255.542800000285,2972.952598 +0.9,15000, 0.9704431526032316, 10048.04175000023, 6200.193249999521,3243.221016 +0.9,18000,0,520.190908,520.190908,0 +0.9,18000, 0.4740615780969478,-1786.47608,-88.27847333, 1584.3137939999997 +0.9,18000, 0.5530718411131058,-724.6719267, 445.2796599999942, 1848.3660929999996 +0.9,18000, 0.6320821041292638, 337.13286000000505, 978.8373133333287, 2112.4183919999996 +0.9,18000, 0.7110923671454218, 1524.7078466667488, 1558.4659533334238, 2376.4706909999995 +0.9,18000, 0.7901026301615798, 3000.020899999749, 2320.7601600000553, 2640.5229899999995 +0.9,18000, 0.8691128931777377, 5830.9932600001675, 3705.0837466668113, 2904.5752889999994 +0.9,18000, 0.9481231561938956, 8486.446980000375, 5155.982346666653, 3168.6275879999994 +0.9,21000,0, 464.47263943053196, 464.47263943053196,0 +0.9,21000, 0.46290262298025125,-2413.970724,-191.5807408, 1547.0205659999997 +0.9,21000, 0.5400530601436265,-1249.260867,292.563488, 1804.8573269999997 +0.9,21000, 0.6172034973070017,-84.5498008, 776.7098904000111, 2062.6940879999997 +0.9,21000,0.694353934, 1152.8188072000742, 1294.964615200052, 2320.5308489999998 +0.9,21000, 0.7715043716337522, 2898.081851199932, 2072.7193704002534,2578.36761 +0.9,21000, 0.8486548087971274, 4902.840496800075, 3073.1607079999576,2836.204371 +0.9,21000, 0.9258052459605025, 7427.583428799606, 4466.756526399922, 3094.0411319999994 +0.9,24000,0, 413.57800001229543, 413.57800001229543,0 +0.9,24000, 0.4517426247755834,-3380.377002,-356.4080264, 1509.7238519999999 +0.9,24000, 0.5270330622381807,-1944.231593, 130.35004800000118,1761.344494 +0.9,24000, 0.6023234997007779,-508.0869792, 617.1068232000135, 2012.9651359999998 +0.9,24000, 0.6776139371633751, 928.0581272000454, 1103.8650703999788, 2264.5857779999997 +0.9,24000, 0.7529043746259724,2298.104271, 1709.643436800076, 2516.2064199999995 +0.9,24000, 0.8281948120885697, 4098.066687200226, 2588.2789408002095,2767.827062 +0.9,24000, 0.9034852495511668,6273.94601, 3752.7204072001286, 3019.4477039999997 +0.9,24000,0.978775687,8743.340178, 5132.795476799943, 3271.0683459999996 +0.9,27000,0, 367.19164787617416, 367.19164787617416,0 +0.9,27000, 0.4405836696588869,-2469.04386,-390.76398,1472.430624 +0.9,27000, 0.5140142812687014,-1423.591517, 44.119907999998674,1717.835728 +0.9,27000, 0.5874448928785159,-378.139112, 479.00428880000646,1963.240832 +0.9,27000, 0.6608755044883303, 667.3140992000291, 913.8893352000094,2208.645936 +0.9,27000, 0.7343061160981448, 1847.1878240000085, 1439.5940311999611,2454.05104 +0.9,27000, 0.8077367277079592, 3456.315953600096, 2182.7071695999566, 2699.4561439999998 +0.9,27000, 0.8811673393177738, 5334.240733600002, 3140.6402112001924,2944.861248 +0.9,27000, 0.9545979509275883, 7568.678658400436, 4445.009118400557,3190.266352 +0.9,30000,0, 325.0157795502978, 325.0157795502978,0 +0.9,30000, 0.42942367145421895, 1681.152200000004, 303.5219000000011, 1435.1339099999998 +0.9,30000, 0.5009942833632555, 1614.546000000012, 515.5695000000067, 1674.3228949999998 +0.9,30000, 0.5725648952722919, 1547.9432000000197, 727.6142000000225, 1913.5118799999998 +0.9,30000, 0.6441355071813285, 1481.341500000173, 939.6603000000168,2152.700865 +0.9,30000,0.715706119, 1489.4339000000646, 1168.3894999999263, 2391.8898499999996 +0.9,30000, 0.7872767309994015, 2776.802199999951, 1795.7976999999923,2631.078835 +0.9,30000, 0.8588473429084379, 4453.393999999567, 2598.1665000000708, 2870.2678199999996 +0.9,30000, 0.9304179548174745, 6232.736300000024, 3648.901299999773,3109.456805 +0.9,33000,0, 286.7603937465558, 286.7603937465558,0 +0.9,33000, 0.41826471633752244,-1438.511757,-498.6571232,1397.840682 +0.9,33000, 0.48797550239377613,-780.159164,-129.6842232, 1630.8141289999999 +0.9,33000, 0.5576862884500299,-121.8052568, 239.28958319998964,1863.787576 +0.9,33000, 0.6273970745062837, 536.5477439999379,608.2622928,2096.761023 +0.9,33000, 0.6971078605625374, 1317.005752000066, 1033.7325799999935,2329.73447 +0.9,33000, 0.7668186466187911, 2285.1789424000153, 1487.0621944000677, 2562.7079169999997 +0.9,33000, 0.8365294326750449, 3726.1488351999583, 2211.4953831998587,2795.681364 +0.9,33000, 0.9062402187312986,5415.78917, 3069.661709600374,3028.654811 +0.9,33000, 0.9759510047875523, 6924.213230400632, 4021.3689040000822, 3261.6282579999997 +0.9,36000,0, 252.15307094326414, 252.15307094326414,0 +0.9,36000, 0.40710471813285454,-1593.1189,-365.198,1360.543968 +0.9,36000, 0.47495550448833035,-983.3862,-76.3822,1587.301296 +0.9,36000, 0.5428062908438062,-373.6523, 212.43419999997226,1814.058624 +0.9,36000, 0.6106570771992819, 236.07989999997807, 501.25000000001575,2040.815952 +0.9,36000, 0.6785078635547577, 845.8141000000041, 790.0658000000207,2267.57328 +0.9,36000, 0.7463586499102335, 1663.118400000005, 1196.5614999999877,2494.330608 +0.9,36000, 0.8142094362657091, 2917.3133000001694, 1741.874699999983,2721.087936 +0.9,36000, 0.8820602226211849, 4224.531900000347, 2455.3754999999805,2947.845264 +0.9,36000, 0.9499110089766607, 5620.762499999893, 3309.852300000278,3174.602592 +0.9,39000,0, 218.38361472334765, 218.38361472334765,0 +0.9,39000, 0.4067730161579892,-1720.4844,-451.0876,1359.43542 +0.9,39000, 0.47456851885098744,-1147.154,-180.8578,1586.00799 +0.9,39000, 0.5423640215439857,-573.8231, 89.37320000003467,1812.58056 +0.9,39000, 0.6101595242369839,-0.4923, 359.60360000000304, 2039.1531300000001 +0.9,39000,0.677955027, 572.8385000000095, 629.8336000000298,2265.7257 +0.9,39000, 0.7457505296229803, 1304.3049000000003, 987.5776000000088, 2492.2982700000002 +0.9,39000, 0.8135460323159784,2300.0848, 1448.1752000000852,2718.87084 +0.9,39000, 0.8813415350089767, 3485.5072000001546, 2070.0880000001534, 2945.4434100000003 +0.9,39000, 0.9491370377019749, 4642.574100000079, 2769.2436000000844,3172.01598 +0.9,42000,0, 189.05970616353355, 189.05970616353355,0 +0.9,42000, 0.4067730161579892,-2081.7766,-554.0094375,1359.43542 +0.9,42000, 0.47456851885098744,-1479.96,-291.826575,1586.00799 +0.9,42000, 0.5423640215439857,-878.14375,-29.64401875,1812.58056 +0.9,42000, 0.6101595242369839,-276.3273125, 232.53875624999074, 2039.1531300000001 +0.9,42000,0.677955027, 325.48893749997995, 494.72118125001214,2265.7257 +0.9,42000, 0.7457505296229803, 960.1070437500007, 797.0973687500137, 2492.2982700000002 +0.9,42000, 0.8135460323159784, 1816.0550687500097,1199.02065,2718.87084 +0.9,42000, 0.8813415350089767, 2849.730018750023, 1733.8661124999928, 2945.4434100000003 +0.9,42000, 0.9491370377019749, 3854.696287500119, 2333.1897937501267,3172.01598 diff --git a/aviary/mission/gasp_based/ode/test/test_descent_eom.py b/aviary/mission/gasp_based/ode/test/test_descent_eom.py index 414a6ebc46..979a9f40e5 100644 --- a/aviary/mission/gasp_based/ode/test/test_descent_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_descent_eom.py @@ -2,8 +2,7 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.descent_eom import DescentRates from aviary.variable_info.variables import Dynamic @@ -16,88 +15,90 @@ class DescentTestCase(unittest.TestCase): """ def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", DescentRates(num_nodes=2), promotes=["*"] - ) + self.prob.model.add_subsystem('group', DescentRates(num_nodes=2), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([459, 459]), units="kn") + Dynamic.Mission.VELOCITY, np.array([459, 459]), units='kn' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([452, 452]), units="lbf") + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, np.array([452, 452]), units='lbf' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([7966.927, 7966.927]), units="lbf" + Dynamic.Vehicle.DRAG, np.array([7966.927, 7966.927]), units='lbf' ) # estimated from GASP values self.prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([147661, 147661]), units="lbm" + Dynamic.Vehicle.MASS, np.array([147661, 147661]), units='lbm' + ) + self.prob.model.set_input_defaults( + Dynamic.Vehicle.ANGLE_OF_ATTACK, np.array([3.2, 3.2]), units='deg' ) - self.prob.model.set_input_defaults("alpha", np.array([3.2, 3.2]), units="deg") self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [-39.41011217, -39.41011217]), tol + self.prob[Dynamic.Mission.ALTITUDE_RATE], + np.array([-39.41011217, -39.41011217]), + tol, ) # note: values from GASP are: np.array([-39.75, -39.75]) assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [773.70165638, 773.70165638]), tol + self.prob[Dynamic.Mission.DISTANCE_RATE], + np.array([773.70165638, 773.70165638]), + tol, # note: these values are finite differenced and lose accuracy. Fd values are:np.array([964.4634921, 964.4634921]) ) assert_near_equal( - self.prob["required_lift"], + self.prob['required_lift'], np.array([147444.58096139, 147444.58096139]), tol, - ) # note: values from GASP are: np.array([146288.8, 146288.8]) (estimated based on GASP values) + # note: values from GASP are: np.array([146288.8, 146288.8]) (estimated based on GASP values) + ) assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE], np.array( - [-0.05089311, -0.05089311]), tol + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE], + np.array([-0.05089311, -0.05089311]), + tol, ) # note: values from GASP are: np.array([-.0513127, -.0513127]) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class DescentTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.descent_eom as descent + descent.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.descent_eom as descent + descent.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem( - "group", DescentRates(num_nodes=2), promotes=["*"] - ) + prob.model.add_subsystem('group', DescentRates(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, np.array([459, 459]), units='kn') prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, np.array([459, 459]), units="kn") - prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, np.array([452, 452]), units="lbf") + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, np.array([452, 452]), units='lbf' + ) prob.model.set_input_defaults( - Dynamic.Mission.DRAG, np.array([7966.927, 7966.927]), units="lbf" + Dynamic.Vehicle.DRAG, np.array([7966.927, 7966.927]), units='lbf' ) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, np.array([147661, 147661]), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.MASS, np.array([147661, 147661]), units="lbm" + Dynamic.Vehicle.ANGLE_OF_ATTACK, np.array([3.2, 3.2]), units='deg' ) - prob.model.set_input_defaults("alpha", np.array([3.2, 3.2]), units="deg") prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_descent_ode.py b/aviary/mission/gasp_based/ode/test/test_descent_ode.py index 1fa46aea7c..cce9be1831 100644 --- a/aviary/mission/gasp_based/ode/test/test_descent_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_descent_ode.py @@ -12,105 +12,122 @@ from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs from aviary.variable_info.enums import SpeedType +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic class DescentODETestCase(unittest.TestCase): - """ - Test 2-degree of freedom descent ODE - """ + """Test 2-degree of freedom descent ODE.""" def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) + + self.sys = self.prob.model = DescentODE( + num_nodes=1, + mach_cruise=0.8, + aviary_options=get_option_defaults(), + core_subsystems=default_mission_subsystems, + ) - self.sys = self.prob.model = DescentODE(num_nodes=1, - mach_cruise=0.8, - aviary_options=get_option_defaults(), - core_subsystems=default_mission_subsystems) + setup_model_options(self.prob, aviary_options) - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), "Skipping due to OpenMDAO version being too low (<3.26)") + @unittest.skipIf( + version.parse(openmdao.__version__) < version.parse('3.26'), + 'Skipping due to OpenMDAO version being too low (<3.26)', + ) def test_high_alt(self): # Test descent above 10k ft with Mach under and over the EAS limit - self.sys.options["num_nodes"] = 2 - self.sys.options["input_speed_type"] = SpeedType.MACH - self.sys.options["EAS_limit"] = 350 + self.sys.options['num_nodes'] = 2 + self.sys.options['input_speed_type'] = SpeedType.MACH + self.sys.options['EAS_limit'] = 350 self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val( - Dynamic.Mission.THROTTLE, np.array([ - 0, 0]), units='unitless') - self.prob.set_val(Dynamic.Mission.ALTITUDE, np.array([36500, 14500]), units="ft") - self.prob.set_val(Dynamic.Mission.MASS, np.array([147661, 147572]), units="lbm") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Dynamic.Vehicle.Propulsion.THROTTLE, np.array([0, 0]), units='unitless') + self.prob.set_val(Dynamic.Mission.ALTITUDE, np.array([36500, 14500]), units='ft') + self.prob.set_val(Dynamic.Vehicle.MASS, np.array([147661, 147572]), units='lbm') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) self.prob.run_model() testvals = { - "alpha": np.array([3.23388, 1.203234]), - "CL": np.array([0.51849367, 0.25908653]), - "CD": np.array([0.02794324, 0.01862946]), + Dynamic.Vehicle.ANGLE_OF_ATTACK: np.array([3.22110553, 1.20422538]), + 'CL': np.array([0.51699989, 0.25916886]), + 'CD': np.array([0.02635475, 0.01730991]), # ft/s - Dynamic.Mission.ALTITUDE_RATE: np.array([-2356.7705, -2877.9606]) / 60, + Dynamic.Mission.ALTITUDE_RATE: np.array([-37.02561983, -44.211356]), # TAS (ft/s) * cos(gamma), [458.67774, 437.62297] kts - Dynamic.Mission.DISTANCE_RATE: [773.1637, 737.0653], # ft/s + Dynamic.Mission.DISTANCE_RATE: [773.25678423, 737.1789493], # ft/s # lbm/h - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: np.array([-451.0239, -997.1514]), - "EAS": [417.87419406, 590.73344937], # ft/s ([247.58367, 349.99997] kts) - Dynamic.Mission.MACH: [0.8, 0.697266], + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL: np.array( + [-452.29466667, -997.41373745] + ), + 'EAS': [418.50757579, 590.73344999], # ft/s ([247.95894, 349.99997] kts) + Dynamic.Atmosphere.MACH: [0.8, 0.697125], # gamma, rad ([-2.908332, -3.723388] deg) - Dynamic.Mission.FLIGHT_PATH_ANGLE: [-0.05075997, -0.06498538], + Dynamic.Mission.FLIGHT_PATH_ANGLE: [-0.04784615, -0.05990196], } check_prob_outputs(self.prob, testvals, rtol=1e-6) partial_data = self.prob.check_partials( - method="cs", out_stream=None, excludes=["*params*", "*aero*"] + method='cs', out_stream=None, excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) def test_low_alt(self): # Test descent below 10k ft - self.sys.options["input_speed_type"] = SpeedType.EAS - self.sys.options["EAS_limit"] = 350 + self.sys.options['input_speed_type'] = SpeedType.EAS + self.sys.options['EAS_limit'] = 350 self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val(Dynamic.Mission.THROTTLE, 0, units='unitless') - self.prob.set_val(Dynamic.Mission.ALTITUDE, 1500, units="ft") - self.prob.set_val(Dynamic.Mission.MASS, 147410, units="lbm") - self.prob.set_val("EAS", 250, units="kn") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Dynamic.Vehicle.Propulsion.THROTTLE, 0, units='unitless') + self.prob.set_val(Dynamic.Mission.ALTITUDE, 1500, units='ft') + self.prob.set_val(Dynamic.Vehicle.MASS, 147410, units='lbm') + self.prob.set_val('EAS', 250, units='kn') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) self.prob.run_model() testvals = { - "alpha": 4.19956, - "CL": 0.507578, - "CD": 0.0268404, - Dynamic.Mission.ALTITUDE_RATE: -1138.583 / 60, + Dynamic.Vehicle.ANGLE_OF_ATTACK: 4.20023671, + 'CL': 0.50764164, + 'CD': 0.02534414, + Dynamic.Mission.ALTITUDE_RATE: -17.70801923, # TAS (ft/s) * cos(gamma) = 255.5613 * 1.68781 * cos(-0.0440083) - Dynamic.Mission.DISTANCE_RATE: 430.9213, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL: -1295.11, - Dynamic.Mission.FLIGHT_PATH_ANGLE: -0.0440083, # rad (-2.52149 deg) + Dynamic.Mission.DISTANCE_RATE: 430.97461539, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL: -1295.11818529, + # rad (-2.52149 deg) + Dynamic.Mission.FLIGHT_PATH_ANGLE: -0.04106521, } check_prob_outputs(self.prob, testvals, rtol=1e-6) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = DescentODETestCase() + # test.setUp() + # test.test_high_alt() diff --git a/aviary/mission/gasp_based/ode/test/test_flight_path_eom.py b/aviary/mission/gasp_based/ode/test/test_flight_path_eom.py index 289e353e16..4d593d6d48 100644 --- a/aviary/mission/gasp_based/ode/test/test_flight_path_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_flight_path_eom.py @@ -13,7 +13,7 @@ def setUp(self): self.ground_roll = False self.prob = om.Problem() self.fp = self.prob.model.add_subsystem( - "group", FlightPathEOM(num_nodes=2, ground_roll=self.ground_roll), promotes=["*"] + 'group', FlightPathEOM(num_nodes=2, ground_roll=self.ground_roll), promotes=['*'] ) self.prob.setup(check=False, force_alloc_complex=True) @@ -24,100 +24,90 @@ def test_case1(self): self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [-27.10027, -27.10027]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [0.5403023, 0.5403023]), tol) - assert_near_equal( - self.prob["normal_force"], np.array( - [-0.0174524, -0.0174524]), tol) - assert_near_equal( - self.prob["fuselage_pitch"], np.array( - [58.2958, 58.2958]), tol) + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([-27.10027, -27.10027]), + tol, + ) assert_near_equal( - self.prob["load_factor"], np.array( - [1.883117, 1.883117]), tol) + self.prob[Dynamic.Mission.DISTANCE_RATE], np.array([0.5403023, 0.5403023]), tol + ) + assert_near_equal(self.prob['normal_force'], np.array([-0.0174524, -0.0174524]), tol) + assert_near_equal(self.prob['fuselage_pitch'], np.array([58.2958, 58.2958]), tol) + assert_near_equal(self.prob['load_factor'], np.array([1.883117, 1.883117]), tol) assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [0.841471, 0.841471]), tol) + self.prob[Dynamic.Mission.ALTITUDE_RATE], + np.array([0.841471, 0.841471]), + tol, + ) assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array( - [15.36423, 15.36423]), tol) + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], + np.array([15.36423, 15.36423]), + tol, + ) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_case2(self): - """ - ground_roll = True (the aircraft is confined to the ground) - """ - self.fp.options["ground_roll"] = True + """ground_roll = True (the aircraft is confined to the ground).""" + self.fp.options['ground_roll'] = True self.prob.setup(force_alloc_complex=True) tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [-27.09537, -27.09537]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [0.5403023, 0.5403023]), tol) - assert_near_equal( - self.prob["normal_force"], np.array( - [-0.0, -0.0]), tol) - assert_near_equal( - self.prob["fuselage_pitch"], np.array( - [57.29578, 57.29578]), tol) + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([-27.09537, -27.09537]), + tol, + ) assert_near_equal( - self.prob["load_factor"], np.array( - [1.850816, 1.850816]), tol) + self.prob[Dynamic.Mission.DISTANCE_RATE], np.array([0.5403023, 0.5403023]), tol + ) + assert_near_equal(self.prob['normal_force'], np.array([-0.0, -0.0]), tol) + assert_near_equal(self.prob['fuselage_pitch'], np.array([57.29578, 57.29578]), tol) + assert_near_equal(self.prob['load_factor'], np.array([1.850816, 1.850816]), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class FlightPathEOMTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.flight_path_eom as fp + fp.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.flight_path_eom as fp + fp.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): - """ - ground_roll = False (the aircraft is not confined to the ground) - """ + """ground_roll = False (the aircraft is not confined to the ground).""" prob = om.Problem() prob.model.add_subsystem( - "group", FlightPathEOM(num_nodes=2, ground_roll=False), promotes=["*"] + 'group', FlightPathEOM(num_nodes=2, ground_roll=False), promotes=['*'] ) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_case2(self): - """ - ground_roll = True (the aircraft is confined to the ground) - """ + """ground_roll = True (the aircraft is confined to the ground).""" prob = om.Problem() prob.model.add_subsystem( - "group", FlightPathEOM(num_nodes=2, ground_roll=True), promotes=["*"] + 'group', FlightPathEOM(num_nodes=2, ground_roll=True), promotes=['*'] ) prob.setup(check=False, force_alloc_complex=True) prob.setup(force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py b/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py index e3fb4bec94..d035c3ce8e 100644 --- a/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_flight_path_ode.py @@ -9,25 +9,30 @@ from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic class FlightPathODETestCase(unittest.TestCase): - """ - Test 2-degree of freedom flight path ODE - """ + """Test 2-degree of freedom flight path ODE.""" def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) + + self.fp = self.prob.model = FlightPathODE( + num_nodes=2, + aviary_options=get_option_defaults(), + core_subsystems=default_mission_subsystems, + ) - self.fp = self.prob.model = FlightPathODE(num_nodes=2, - aviary_options=get_option_defaults(), - core_subsystems=default_mission_subsystems) + setup_model_options(self.prob, aviary_options) def test_case1(self): # ground_roll = False (the aircraft is not confined to the ground) @@ -36,67 +41,70 @@ def test_case1(self): set_params_for_unit_tests(self.prob) - self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") - self.prob.set_val(Dynamic.Mission.MASS, [100000, 100000], units="lbm") - self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units="ft") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units='kn') + self.prob.set_val(Dynamic.Vehicle.MASS, [100000, 100000], units='lbm') + self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units='ft') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) self.prob.run_model() testvals = { - Dynamic.Mission.VELOCITY_RATE: [14.0673, 14.0673], + Dynamic.Mission.VELOCITY_RATE: [14.08998135, 14.08998135], Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE: [-0.1429133, -0.1429133], Dynamic.Mission.ALTITUDE_RATE: [0.0, 0.0], Dynamic.Mission.DISTANCE_RATE: [168.781, 168.781], - "normal_force": [74910.12, 74910.12], - "fuselage_pitch": [0.0, 0.0], - "load_factor": [0.2508988, 0.2508988], + 'normal_force': [74910.12, 74910.12], + 'fuselage_pitch': [0.0, 0.0], + 'load_factor': [0.2508988, 0.2508988], Dynamic.Mission.ALTITUDE_RATE: [0.0, 0.0], - Dynamic.Mission.ALTITUDE_RATE_MAX: [-0.01812796, -0.01812796], + Dynamic.Mission.ALTITUDE_RATE_MAX: [-0.01815717, -0.01815717], } check_prob_outputs(self.prob, testvals, rtol=1e-6) tol = 1e-6 - assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [0, 0]), tol - ) + assert_near_equal(self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array([0, 0]), tol) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*USatm*", "*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*USatm*', '*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) def test_case2(self): # ground_roll = True (the aircraft is confined to the ground) - self.fp.options["ground_roll"] = True + self.fp.options['ground_roll'] = True self.prob.setup(check=False, force_alloc_complex=True) set_params_for_unit_tests(self.prob) - self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") - self.prob.set_val(Dynamic.Mission.MASS, [100000, 100000], units="lbm") - self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units="ft") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units='kn') + self.prob.set_val(Dynamic.Vehicle.MASS, [100000, 100000], units='lbm') + self.prob.set_val(Dynamic.Mission.ALTITUDE, [500, 500], units='ft') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) self.prob.run_model() testvals = { - Dynamic.Mission.VELOCITY_RATE: [13.58489, 13.58489], + Dynamic.Mission.VELOCITY_RATE: [13.60756024, 13.60756024], Dynamic.Mission.DISTANCE_RATE: [168.781, 168.781], - "normal_force": [74910.12, 74910.12], - "fuselage_pitch": [0.0, 0.0], - "load_factor": [0.2508988, 0.2508988], - Dynamic.Mission.ALTITUDE_RATE_MAX: [0.7532356, 0.7532356], + 'normal_force': [74910.12, 74910.12], + 'fuselage_pitch': [0.0, 0.0], + 'load_factor': [0.2508988, 0.2508988], + Dynamic.Mission.ALTITUDE_RATE_MAX: [0.75320631, 0.75320631], } check_prob_outputs(self.prob, testvals, rtol=1e-6) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*USatm*", "*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*USatm*', '*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_groundroll_eom.py b/aviary/mission/gasp_based/ode/test/test_groundroll_eom.py index a1eaf3a25c..6517099084 100644 --- a/aviary/mission/gasp_based/ode/test/test_groundroll_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_groundroll_eom.py @@ -10,96 +10,84 @@ class GroundrollEOMTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", GroundrollEOM(num_nodes=2), promotes=["*"] - ) + self.prob.model.add_subsystem('group', GroundrollEOM(num_nodes=2), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.MASS, val=175400 * np.ones(2), units="lbm" + Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm' ) self.prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, val=22000 * np.ones(2), units="lbf" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' ) + self.prob.model.set_input_defaults(Dynamic.Vehicle.LIFT, val=200 * np.ones(2), units='lbf') self.prob.model.set_input_defaults( - Dynamic.Mission.LIFT, val=200 * np.ones(2), units="lbf") + Dynamic.Vehicle.DRAG, val=10000 * np.ones(2), units='lbf' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.DRAG, val=10000 * np.ones(2), units="lbf") + Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units='ft/s' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units="ft/s") + Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units='rad' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units='deg') self.prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units="rad") - self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units="deg") - self.prob.model.set_input_defaults("alpha", val=np.zeros(2), units="deg") + Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(2), units='deg' + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [1.5597, 1.5597]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [10.0, 10.0]), tol) - assert_near_equal( - self.prob["normal_force"], np.array( - [175200., 175200.]), tol) + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([1.5597, 1.5597]), + tol, + ) assert_near_equal( - self.prob["fuselage_pitch"], np.array( - [0.0, 0.0]), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array([0.0, 0.0]), tol + ) + assert_near_equal(self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array([0.0, 0.0]), tol) + assert_near_equal(self.prob[Dynamic.Mission.DISTANCE_RATE], np.array([10.0, 10.0]), tol) + assert_near_equal(self.prob['normal_force'], np.array([175200.0, 175200.0]), tol) + assert_near_equal(self.prob['fuselage_pitch'], np.array([0.0, 0.0]), tol) + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class GroundrollEOMTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.groundroll_eom as gr + gr.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.groundroll_eom as gr + gr.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem( - "group", GroundrollEOM(num_nodes=2), promotes=["*"] - ) + prob.model.add_subsystem('group', GroundrollEOM(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.MASS, val=175400 * np.ones(2), units="lbm" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' ) + prob.model.set_input_defaults(Dynamic.Vehicle.LIFT, val=200 * np.ones(2), units='lbf') + prob.model.set_input_defaults(Dynamic.Vehicle.DRAG, val=10000 * np.ones(2), units='lbf') + prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units='ft/s') prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, val=22000 * np.ones(2), units="lbf" + Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units='rad' ) - prob.model.set_input_defaults( - Dynamic.Mission.LIFT, val=200 * np.ones(2), units="lbf") - prob.model.set_input_defaults( - Dynamic.Mission.DRAG, val=10000 * np.ones(2), units="lbf") - prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units="ft/s") - prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units="rad") - prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units="deg") - prob.model.set_input_defaults("alpha", val=np.zeros(2), units="deg") + prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units='deg') + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(2), units='deg') prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py b/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py index d7ccbcef4a..f221d2084a 100644 --- a/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_groundroll_ode.py @@ -8,25 +8,30 @@ from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic class GroundrollODETestCase(unittest.TestCase): - """ - Test groundroll ODE - """ + """Test groundroll ODE.""" def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) + + self.prob.model = GroundrollODE( + num_nodes=2, + aviary_options=get_option_defaults(), + core_subsystems=default_mission_subsystems, + ) - self.prob.model = GroundrollODE(num_nodes=2, - aviary_options=get_option_defaults(), - core_subsystems=default_mission_subsystems) + setup_model_options(self.prob, aviary_options) def test_groundroll_partials(self): # Check partial derivatives @@ -34,30 +39,33 @@ def test_groundroll_partials(self): set_params_for_unit_tests(self.prob) - self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") - self.prob.set_val("t_curr", [1, 2], units="s") - self.prob.set_val("aircraft:wing:incidence", 0, units="deg") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units='kn') + self.prob.set_val('t_curr', [1, 2], units='s') + self.prob.set_val('aircraft:wing:incidence', 0, units='deg') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) self.prob.run_model() testvals = { - Dynamic.Mission.VELOCITY_RATE: [1413548.36, 1413548.36], + Dynamic.Mission.VELOCITY_RATE: [1415679.28759478, 1415679.28759478], Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE: [0.0, 0.0], Dynamic.Mission.ALTITUDE_RATE: [0.0, 0.0], Dynamic.Mission.DISTANCE_RATE: [168.781, 168.781], - "normal_force": [0.0, 0.0], - "fuselage_pitch": [0.0, 0.0], - "dmass_dv": [-5.03252493e-06, -5.03252493e-06], + 'normal_force': [0.0, 0.0], + 'fuselage_pitch': [0.0, 0.0], + 'dmass_dv': [-5.02403534e-06, -5.02403534e-06], } check_prob_outputs(self.prob, testvals, rtol=1e-6) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_landing_eom.py b/aviary/mission/gasp_based/ode/test/test_landing_eom.py index 15723113ff..f4a4242721 100644 --- a/aviary/mission/gasp_based/ode/test/test_landing_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_landing_eom.py @@ -1,32 +1,26 @@ import unittest import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.constants import RHO_SEA_LEVEL_ENGLISH from aviary.mission.gasp_based.ode.landing_eom import ( - GlideConditionComponent, LandingAltitudeComponent, - LandingGroundRollComponent) -from aviary.variable_info.variables import Aircraft, Mission, Dynamic + GlideConditionComponent, + LandingAltitudeComponent, + LandingGroundRollComponent, +) +from aviary.variable_info.variables import Aircraft, Dynamic, Mission class LandingAltTestCase(unittest.TestCase): - """ - Test computation of initial altitude in LandingAltitudeComponent component - """ + """Test computation of initial altitude in LandingAltitudeComponent component.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", LandingAltitudeComponent(), promotes=["*"] - ) + self.prob.model.add_subsystem('group', LandingAltitudeComponent(), promotes=['*']) - self.prob.model.set_input_defaults( - Mission.Landing.OBSTACLE_HEIGHT, 50, units="ft") - self.prob.model.set_input_defaults( - Mission.Landing.AIRPORT_ALTITUDE, 0, units="ft") + self.prob.model.set_input_defaults(Mission.Landing.OBSTACLE_HEIGHT, 50, units='ft') + self.prob.model.set_input_defaults(Mission.Landing.AIRPORT_ALTITUDE, 0, units='ft') self.prob.setup(check=False, force_alloc_complex=True) @@ -38,43 +32,35 @@ def test_case1(self): self.prob[Mission.Landing.OBSTACLE_HEIGHT], 50, tol ) # not actual GASP value, but intuitively correct - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class GlideTestCase(unittest.TestCase): - """ - Test computation of initial velocity and stall velocity in GlideConditionComponent component - """ + """Test computation of initial velocity and stall velocity in GlideConditionComponent component.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", GlideConditionComponent(), promotes=["*"] - ) + self.prob.model.add_subsystem('group', GlideConditionComponent(), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3" + Dynamic.Atmosphere.DENSITY, RHO_SEA_LEVEL_ENGLISH, units='slug/ft**3' ) # value from online calculator - self.prob.model.set_input_defaults( - Mission.Landing.MAXIMUM_SINK_RATE, 900, units="ft/min") + self.prob.model.set_input_defaults(Mission.Landing.MAXIMUM_SINK_RATE, 900, units='ft/min') - self.prob.model.set_input_defaults("mass", 165279, units="lbm") - self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units="ft**2") - self.prob.model.set_input_defaults( - Mission.Landing.GLIDE_TO_STALL_RATIO, 1.3, units="unitless") - self.prob.model.set_input_defaults("CL_max", 2.9533, units="unitless") + self.prob.model.set_input_defaults('mass', 165279, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units='ft**2') self.prob.model.set_input_defaults( - Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, 1.15, units="unitless" + Mission.Landing.GLIDE_TO_STALL_RATIO, 1.3, units='unitless' ) + self.prob.model.set_input_defaults('CL_max', 2.9533, units='unitless') self.prob.model.set_input_defaults( - Mission.Landing.TOUCHDOWN_SINK_RATE, 5, units="ft/s") - self.prob.model.set_input_defaults( - Mission.Landing.INITIAL_ALTITUDE, val=50.0, units="ft") - self.prob.model.set_input_defaults( - Mission.Landing.BRAKING_DELAY, val=1.0, units="s") + Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, 1.15, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Landing.TOUCHDOWN_SINK_RATE, 5, units='ft/s') + self.prob.model.set_input_defaults(Mission.Landing.INITIAL_ALTITUDE, val=50.0, units='ft') + self.prob.model.set_input_defaults(Mission.Landing.BRAKING_DELAY, val=1.0, units='s') self.prob.setup(check=False, force_alloc_complex=True) @@ -83,114 +69,102 @@ def test_case1(self): self.prob.run_model() assert_near_equal( - self.prob.get_val(Mission.Landing.INITIAL_VELOCITY, - units="kn"), 142.783, tol + self.prob.get_val(Mission.Landing.INITIAL_VELOCITY, units='kn'), 142.783, tol ) # note: actual GASP value is: 142.74 assert_near_equal( - self.prob.get_val(Mission.Landing.STALL_VELOCITY, - units="kn"), 109.8331, tol + self.prob.get_val(Mission.Landing.STALL_VELOCITY, units='kn'), 109.8331, tol ) # note: EAS in GASP, although at this altitude they are nearly identical. actual GASP value is 109.73 assert_near_equal( - self.prob.get_val("TAS_touchdown", units="kn"), 126.3081, tol + self.prob.get_val('TAS_touchdown', units='kn'), 126.3081, tol ) # note: actual GASP value is: 126.27 assert_near_equal( - self.prob.get_val("density_ratio", units="unitless"), 1.0, tol + self.prob.get_val('density_ratio', units='unitless'), 1.0, tol ) # note: calculated from GASP glide speed values as: .998739 assert_near_equal( - self.prob.get_val("wing_loading_land", units="lbf/ft**2"), 120.61519375, tol + self.prob.get_val('wing_loading_land', units='lbf/ft**2'), 120.61519375, tol ) # note: actual GASP value is: 120.61 assert_near_equal( - self.prob.get_val("theta", units="deg"), 3.56857, tol + self.prob.get_val('theta', units='deg'), 3.56857, tol ) # note: actual GASP value is: 3.57 assert_near_equal( - self.prob.get_val("glide_distance", units="ft"), 801.7444, tol + self.prob.get_val('glide_distance', units='ft'), 801.7444, tol ) # note: actual GASP value is: 802 assert_near_equal( - self.prob.get_val("tr_distance", units="ft"), 166.5303, tol + self.prob.get_val('tr_distance', units='ft'), 166.5303, tol ) # note: actual GASP value is: 167 assert_near_equal( - self.prob.get_val("delay_distance", units="ft"), 213.184, tol + self.prob.get_val('delay_distance', units='ft'), 213.184, tol ) # note: actual GASP value is: 213 assert_near_equal( - self.prob.get_val("flare_alt", units="ft"), 20.73407, tol + self.prob.get_val('flare_alt', units='ft'), 20.73407, tol ) # note: actual GASP value is: 20.8 - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-12) class GlideTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.landing_eom as landing + landing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.landing_eom as landing + landing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem( - "group", GlideConditionComponent(), promotes=["*"]) + prob.model.add_subsystem('group', GlideConditionComponent(), promotes=['*']) prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3" + Dynamic.Atmosphere.DENSITY, RHO_SEA_LEVEL_ENGLISH, units='slug/ft**3' ) + prob.model.set_input_defaults(Mission.Landing.MAXIMUM_SINK_RATE, 900, units='ft/min') + prob.model.set_input_defaults('mass', 165279, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units='ft**2') + prob.model.set_input_defaults(Mission.Landing.GLIDE_TO_STALL_RATIO, 1.3, units='unitless') + prob.model.set_input_defaults('CL_max', 2.9533, units='unitless') prob.model.set_input_defaults( - Mission.Landing.MAXIMUM_SINK_RATE, 900, units="ft/min") - prob.model.set_input_defaults("mass", 165279, units="lbm") - prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units="ft**2") - prob.model.set_input_defaults( - Mission.Landing.GLIDE_TO_STALL_RATIO, 1.3, units="unitless") - prob.model.set_input_defaults("CL_max", 2.9533, units="unitless") - prob.model.set_input_defaults( - Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, 1.15, units="unitless") - prob.model.set_input_defaults( - Mission.Landing.TOUCHDOWN_SINK_RATE, 5, units="ft/s") - prob.model.set_input_defaults( - Mission.Landing.INITIAL_ALTITUDE, val=50.0, units="ft") - prob.model.set_input_defaults( - Mission.Landing.BRAKING_DELAY, val=1.0, units="s") + Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, 1.15, units='unitless' + ) + prob.model.set_input_defaults(Mission.Landing.TOUCHDOWN_SINK_RATE, 5, units='ft/s') + prob.model.set_input_defaults(Mission.Landing.INITIAL_ALTITUDE, val=50.0, units='ft') + prob.model.set_input_defaults(Mission.Landing.BRAKING_DELAY, val=1.0, units='s') prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=2e-11, rtol=1e-12) + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-10, rtol=1e-12) class GroundRollTestCase(unittest.TestCase): """ - Test the computation of groundroll distance and average acceleration/deceleration in + Test the computation of groundroll distance and average acceleration/deceleration in LandingGroundRollComponent component. """ def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", LandingGroundRollComponent(), promotes=["*"] - ) + self.prob.model.add_subsystem('group', LandingGroundRollComponent(), promotes=['*']) - self.prob.model.set_input_defaults("touchdown_CD", val=0.07344) - self.prob.model.set_input_defaults("touchdown_CL", val=1.18694) + self.prob.model.set_input_defaults('touchdown_CD', val=0.07344) + self.prob.model.set_input_defaults('touchdown_CL', val=1.18694) self.prob.model.set_input_defaults( - Mission.Landing.STALL_VELOCITY, val=109.73, units="kn" + Mission.Landing.STALL_VELOCITY, val=109.73, units='kn' ) # note: EAS in GASP, although at this altitude they are nearly identical - self.prob.model.set_input_defaults("TAS_touchdown", val=126.27, units="kn") - self.prob.model.set_input_defaults("thrust_idle", val=1276, units="lbf") + self.prob.model.set_input_defaults('TAS_touchdown', val=126.27, units='kn') + self.prob.model.set_input_defaults('thrust_idle', val=1276, units='lbf') self.prob.model.set_input_defaults( - "density_ratio", val=0.998739, units="unitless" + 'density_ratio', val=0.998739, units='unitless' ) # note: calculated from GASP glide speed values - self.prob.model.set_input_defaults( - "wing_loading_land", val=120.61, units="lbf/ft**2" - ) - self.prob.model.set_input_defaults("glide_distance", val=802, units="ft") - self.prob.model.set_input_defaults("tr_distance", val=167, units="ft") - self.prob.model.set_input_defaults("delay_distance", val=213, units="ft") - self.prob.model.set_input_defaults("CL_max", 2.9533, units="unitless") - self.prob.model.set_input_defaults("mass", 165279, units="lbm") + self.prob.model.set_input_defaults('wing_loading_land', val=120.61, units='lbf/ft**2') + self.prob.model.set_input_defaults('glide_distance', val=802, units='ft') + self.prob.model.set_input_defaults('tr_distance', val=167, units='ft') + self.prob.model.set_input_defaults('delay_distance', val=213, units='ft') + self.prob.model.set_input_defaults('CL_max', 2.9533, units='unitless') + self.prob.model.set_input_defaults('mass', 165279, units='lbm') self.prob.setup(check=False, force_alloc_complex=True) @@ -199,64 +173,60 @@ def test_case1(self): self.prob.run_model() assert_near_equal( - self.prob["ground_roll_distance"], 2406.43116212, tol + self.prob['ground_roll_distance'], 2406.43116212, tol ) # actual GASP value is: 1798 assert_near_equal( self.prob[Mission.Landing.GROUND_DISTANCE], 3588.43116212, tol ) # actual GASP value is: 2980 assert_near_equal( - self.prob["average_acceleration"], 0.29308129, tol + self.prob['average_acceleration'], 0.29308129, tol ) # actual GASP value is: 0.3932 - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=5e-12, rtol=1e-12) class GroundRollTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.landing_eom as landing + landing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.landing_eom as landing + landing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", LandingGroundRollComponent(), promotes=["*"] - ) + self.prob.model.add_subsystem('group', LandingGroundRollComponent(), promotes=['*']) - self.prob.model.set_input_defaults("touchdown_CD", val=0.07344) - self.prob.model.set_input_defaults("touchdown_CL", val=1.18694) + self.prob.model.set_input_defaults('touchdown_CD', val=0.07344) + self.prob.model.set_input_defaults('touchdown_CL', val=1.18694) self.prob.model.set_input_defaults( - Mission.Landing.STALL_VELOCITY, val=109.73, units="kn" + Mission.Landing.STALL_VELOCITY, val=109.73, units='kn' ) # note: EAS in GASP, although at this altitude they are nearly identical - self.prob.model.set_input_defaults("TAS_touchdown", val=126.27, units="kn") - self.prob.model.set_input_defaults("thrust_idle", val=1276, units="lbf") + self.prob.model.set_input_defaults('TAS_touchdown', val=126.27, units='kn') + self.prob.model.set_input_defaults('thrust_idle', val=1276, units='lbf') self.prob.model.set_input_defaults( - "density_ratio", val=0.998739, units="unitless" + 'density_ratio', val=0.998739, units='unitless' ) # note: calculated from GASP glide speed values - self.prob.model.set_input_defaults( - "wing_loading_land", val=120.61, units="lbf/ft**2" - ) - self.prob.model.set_input_defaults("glide_distance", val=802, units="ft") - self.prob.model.set_input_defaults("tr_distance", val=167, units="ft") - self.prob.model.set_input_defaults("delay_distance", val=213, units="ft") - self.prob.model.set_input_defaults("CL_max", 2.9533, units="unitless") - self.prob.model.set_input_defaults("mass", 165279, units="lbm") + self.prob.model.set_input_defaults('wing_loading_land', val=120.61, units='lbf/ft**2') + self.prob.model.set_input_defaults('glide_distance', val=802, units='ft') + self.prob.model.set_input_defaults('tr_distance', val=167, units='ft') + self.prob.model.set_input_defaults('delay_distance', val=213, units='ft') + self.prob.model.set_input_defaults('CL_max', 2.9533, units='unitless') + self.prob.model.set_input_defaults('mass', 165279, units='lbm') self.prob.setup(check=False, force_alloc_complex=True) self.prob.run_model() - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=5e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_landing_ode.py b/aviary/mission/gasp_based/ode/test/test_landing_ode.py index 08dfe21542..be6c90e992 100644 --- a/aviary/mission/gasp_based/ode/test/test_landing_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_landing_ode.py @@ -1,75 +1,75 @@ -from packaging import version import unittest -import numpy as np - import openmdao import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials +from packaging import version -from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.mission.gasp_based.ode.landing_ode import LandingSegment +from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Dynamic, Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission class DLandTestCase(unittest.TestCase): - """ - Test 2DOF landing group - """ + """Test 2DOF landing group.""" def setUp(self): - self.prob = om.Problem() options = get_option_defaults() - engine = build_engine_deck(options) - core_subsystems = get_default_mission_subsystems('GASP', engine) + engines = [build_engine_deck(options)] + core_subsystems = get_default_mission_subsystems('GASP', engines) + + self.prob.model = LandingSegment(aviary_options=options, core_subsystems=core_subsystems) - self.prob.model = LandingSegment( - aviary_options=options, core_subsystems=core_subsystems) + setup_model_options(self.prob, options) - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), "Skipping due to OpenMDAO version being too low (<3.26)") + @unittest.skipIf( + version.parse(openmdao.__version__) < version.parse('3.26'), + 'Skipping due to OpenMDAO version being too low (<3.26)', + ) def test_dland(self): self.prob.setup(check=False, force_alloc_complex=True) set_params_for_unit_tests(self.prob) - self.prob.set_val(Mission.Landing.AIRPORT_ALTITUDE, 0, units="ft") - self.prob.set_val(Mission.Landing.INITIAL_MACH, 0.1, units="unitless") - self.prob.set_val("alpha", 0, units="deg") # doesn't matter - self.prob.set_val(Mission.Landing.MAXIMUM_SINK_RATE, 900, units="ft/min") - self.prob.set_val(Mission.Landing.GLIDE_TO_STALL_RATIO, 1.3, units="unitless") - self.prob.set_val(Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, - 1.15, units="unitless") - self.prob.set_val(Mission.Landing.TOUCHDOWN_SINK_RATE, 5, units="ft/s") - self.prob.set_val(Mission.Landing.BRAKING_DELAY, 1, units="s") - self.prob.set_val("mass", 165279, units="lbm") - self.prob.set_val(Dynamic.Mission.THROTTLE, 0.0, units='unitless') + self.prob.set_val(Mission.Landing.AIRPORT_ALTITUDE, 0, units='ft') + self.prob.set_val(Mission.Landing.INITIAL_MACH, 0.1, units='unitless') + self.prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0, units='deg') # doesn't matter + self.prob.set_val(Mission.Landing.MAXIMUM_SINK_RATE, 900, units='ft/min') + self.prob.set_val(Mission.Landing.GLIDE_TO_STALL_RATIO, 1.3, units='unitless') + self.prob.set_val(Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, 1.15, units='unitless') + self.prob.set_val(Mission.Landing.TOUCHDOWN_SINK_RATE, 5, units='ft/s') + self.prob.set_val(Mission.Landing.BRAKING_DELAY, 1, units='s') + self.prob.set_val('mass', 165279, units='lbm') + self.prob.set_val(Dynamic.Vehicle.Propulsion.THROTTLE, 0.0, units='unitless') + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25, units='unitless') self.prob.run_model() testvals = { Mission.Landing.INITIAL_VELOCITY: 240.9179994, # ft/s (142.74 knot) - "TAS_touchdown": 213.1197687, # ft/s (126.27 knot) - "theta": 0.06230825, # rad (3.57 deg) - "flare_alt": 20.8, - "ground_roll_distance": 1798, + 'TAS_touchdown': 213.1197687, # ft/s (126.27 knot) + 'theta': 0.06230825, # rad (3.57 deg) + 'flare_alt': 20.8, + 'ground_roll_distance': 1798, Mission.Landing.GROUND_DISTANCE: 2980, - "CL_max": 2.9533, + 'CL_max': 2.9533, } check_prob_outputs(self.prob, testvals, rtol=1e-2) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-6, rtol=1e-6) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = DLandTestCase() # test.setUp() diff --git a/aviary/mission/gasp_based/ode/test/test_rotation_eom.py b/aviary/mission/gasp_based/ode/test/test_rotation_eom.py index 13fdf4c288..d6b01fa40a 100644 --- a/aviary/mission/gasp_based/ode/test/test_rotation_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_rotation_eom.py @@ -10,91 +10,85 @@ class RotationEOMTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("group", RotationEOM(num_nodes=2), promotes=["*"]) + self.prob.model.add_subsystem('group', RotationEOM(num_nodes=2), promotes=['*']) self.prob.model.set_input_defaults( - Dynamic.Mission.MASS, val=175400 * np.ones(2), units="lbm" + Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm' ) self.prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, val=22000 * np.ones(2), units="lbf" + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' ) + self.prob.model.set_input_defaults(Dynamic.Vehicle.LIFT, val=200 * np.ones(2), units='lbf') self.prob.model.set_input_defaults( - Dynamic.Mission.LIFT, val=200 * np.ones(2), units="lbf") + Dynamic.Vehicle.DRAG, val=10000 * np.ones(2), units='lbf' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.DRAG, val=10000 * np.ones(2), units="lbf") + Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units='ft/s' + ) self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units="ft/s") + Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units='rad' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units='deg') self.prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units="rad") - self.prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units="deg") - self.prob.model.set_input_defaults("alpha", val=np.zeros(2), units="deg") + Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(2), units='deg' + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - tol = 1e-6 self.prob.run_model() assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [1.5597, 1.5597]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [10., 10.]), tol) - assert_near_equal( - self.prob["normal_force"], np.array( - [175200., 175200.]), tol) + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([1.5597, 1.5597]), + tol, + ) assert_near_equal( - self.prob["fuselage_pitch"], np.array( - [0.0, 0.0]), tol) + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array([0.0, 0.0]), tol + ) + assert_near_equal(self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array([0.0, 0.0]), tol) + assert_near_equal(self.prob[Dynamic.Mission.DISTANCE_RATE], np.array([10.0, 10.0]), tol) + assert_near_equal(self.prob['normal_force'], np.array([175200.0, 175200.0]), tol) + assert_near_equal(self.prob['fuselage_pitch'], np.array([0.0, 0.0]), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class RotationEOMTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.rotation_eom as rotation + rotation.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.rotation_eom as rotation + rotation.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem("group", RotationEOM(num_nodes=2), promotes=["*"]) - prob.model.set_input_defaults( - Dynamic.Mission.MASS, val=175400 * np.ones(2), units="lbm") + prob.model.add_subsystem('group', RotationEOM(num_nodes=2), promotes=['*']) + prob.model.set_input_defaults(Dynamic.Vehicle.MASS, val=175400 * np.ones(2), units='lbm') prob.model.set_input_defaults( - Dynamic.Mission.THRUST_TOTAL, val=22000 * np.ones(2), units="lbf") - prob.model.set_input_defaults( - Dynamic.Mission.LIFT, val=200 * np.ones(2), units="lbf") - prob.model.set_input_defaults( - Dynamic.Mission.DRAG, val=10000 * np.ones(2), units="lbf") - prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units="ft/s") + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=22000 * np.ones(2), units='lbf' + ) + prob.model.set_input_defaults(Dynamic.Vehicle.LIFT, val=200 * np.ones(2), units='lbf') + prob.model.set_input_defaults(Dynamic.Vehicle.DRAG, val=10000 * np.ones(2), units='lbf') + prob.model.set_input_defaults(Dynamic.Mission.VELOCITY, val=10 * np.ones(2), units='ft/s') prob.model.set_input_defaults( - Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units="rad") - prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units="deg") - prob.model.set_input_defaults("alpha", val=np.zeros(2), units="deg") + Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros(2), units='rad' + ) + prob.model.set_input_defaults(Aircraft.Wing.INCIDENCE, val=0, units='deg') + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(2), units='deg') prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_rotation_ode.py b/aviary/mission/gasp_based/ode/test/test_rotation_ode.py index 602e31945f..95b17aed8c 100644 --- a/aviary/mission/gasp_based/ode/test/test_rotation_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_rotation_ode.py @@ -4,41 +4,48 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.mission.gasp_based.ode.rotation_ode import RotationODE from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests +from aviary.mission.gasp_based.ode.rotation_ode import RotationODE from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic class RotationODETestCase(unittest.TestCase): - """ - Test 2-degree of freedom rotation ODE - """ + """Test 2-degree of freedom rotation ODE.""" def setUp(self): self.prob = om.Problem() aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) - self.prob.model = RotationODE(num_nodes=2, - aviary_options=get_option_defaults(), - core_subsystems=default_mission_subsystems) + self.prob.model = RotationODE( + num_nodes=2, + aviary_options=get_option_defaults(), + core_subsystems=default_mission_subsystems, + ) + setup_model_options(self.prob, aviary_options) def test_rotation_partials(self): # Check partial derivatives self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val(Aircraft.Wing.INCIDENCE, 1.5, units="deg") - self.prob.set_val(Dynamic.Mission.MASS, [100000, 100000], units="lbm") - self.prob.set_val("alpha", [1.5, 1.5], units="deg") - self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units="kn") - self.prob.set_val("t_curr", [1, 2], units="s") - self.prob.set_val("interference_independent_of_shielded_area", 1.89927266) - self.prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + self.prob.set_val(Aircraft.Wing.INCIDENCE, 1.5, units='deg') + self.prob.set_val(Dynamic.Vehicle.MASS, [100000, 100000], units='lbm') + self.prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [1.5, 1.5], units='deg') + self.prob.set_val(Dynamic.Mission.VELOCITY, [100, 100], units='kn') + self.prob.set_val('t_curr', [1, 2], units='s') + self.prob.set_val('interference_independent_of_shielded_area', 1.89927266) + self.prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) + self.prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, 1.25) + self.prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, 1.25) set_params_for_unit_tests(self.prob) @@ -46,29 +53,25 @@ def test_rotation_partials(self): tol = 1e-6 assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY_RATE], np.array( - [13.66655, 13.66655]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array( - [0.0, 0.0]), tol) - assert_near_equal( - self.prob[Dynamic.Mission.DISTANCE_RATE], np.array( - [168.781, 168.781]), tol) + self.prob[Dynamic.Mission.VELOCITY_RATE], + np.array([13.68842392, 13.68842392]), + tol, + ) assert_near_equal( - self.prob["normal_force"], np.array( - [66932.7, 66932.7]), tol) + self.prob[Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE], np.array([0.0, 0.0]), tol + ) + assert_near_equal(self.prob[Dynamic.Mission.ALTITUDE_RATE], np.array([0.0, 0.0]), tol) assert_near_equal( - self.prob["fuselage_pitch"], np.array( - [0.0, 0.0]), tol) + self.prob[Dynamic.Mission.DISTANCE_RATE], np.array([168.781, 168.781]), tol + ) + assert_near_equal(self.prob['normal_force'], np.array([66932.7, 66932.7]), tol) + assert_near_equal(self.prob['fuselage_pitch'], np.array([0.0, 0.0]), tol) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_taxi_eom.py b/aviary/mission/gasp_based/ode/test/test_taxi_eom.py index d4f1c968ff..4a9fcc790d 100644 --- a/aviary/mission/gasp_based/ode/test/test_taxi_eom.py +++ b/aviary/mission/gasp_based/ode/test/test_taxi_eom.py @@ -1,42 +1,43 @@ import unittest import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.utils.aviary_values import AviaryValues from aviary.mission.gasp_based.ode.taxi_eom import TaxiFuelComponent +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Dynamic, Mission class TaxiFuelComponentTestCase(unittest.TestCase): - """ - Test the computation of fuel consumed during taxi in TaxiFuelComponent component. - """ + """Test the computation of fuel consumed during taxi in TaxiFuelComponent component.""" def setUp(self): - self.prob = om.Problem(model=om.Group()) + self.prob = om.Problem() aviary_options = AviaryValues() - aviary_options.set_val(Mission.Taxi.DURATION, 0.1677, units="h") + aviary_options.set_val(Mission.Taxi.DURATION, 0.1677, units='h') + + self.prob.model.add_subsystem('taxi', TaxiFuelComponent(), promotes=['*']) - self.prob.model.add_subsystem('taxi', TaxiFuelComponent( - aviary_options=aviary_options), promotes=['*']) + setup_model_options(self.prob, aviary_options) def test_fuel_consumed(self): self.prob.setup(force_alloc_complex=True) - self.prob.set_val(Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - -1512, units="lbm/h") - self.prob.set_val(Mission.Summary.GROSS_MASS, 175400.0, units="lbm") + self.prob.set_val( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + -1512, + units='lbm/h', + ) + self.prob.set_val(Mission.Summary.GROSS_MASS, 175400.0, units='lbm') self.prob.run_model() - assert_near_equal(self.prob["taxi_fuel_consumed"], - 1512 * 0.1677, 1e-6) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + assert_near_equal(self.prob['taxi_fuel_consumed'], 1512 * 0.1677, 1e-6) + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_taxi_ode.py b/aviary/mission/gasp_based/ode/test/test_taxi_ode.py index 0c595da1a6..7058b26884 100644 --- a/aviary/mission/gasp_based/ode/test/test_taxi_ode.py +++ b/aviary/mission/gasp_based/ode/test/test_taxi_ode.py @@ -1,59 +1,72 @@ -from packaging import version import unittest import openmdao import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials +from packaging import version from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests from aviary.mission.gasp_based.ode.taxi_ode import TaxiSegment from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.utils.test_utils.IO_test_util import check_prob_outputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Dynamic, Mission class TaxiTestCase(unittest.TestCase): - """ - Test computation of taxi group. - """ + """Test computation of taxi group.""" def setUp(self): - self.prob = om.Problem() options = get_option_defaults() - options.set_val(Mission.Taxi.DURATION, 0.1677, units="h") + options.set_val(Mission.Taxi.DURATION, 0.1677, units='h') default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(options)) + 'GASP', [build_engine_deck(options)] + ) self.prob.model = TaxiSegment( - aviary_options=options, core_subsystems=default_mission_subsystems) + aviary_options=options, core_subsystems=default_mission_subsystems + ) - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), "Skipping due to OpenMDAO version being too low (<3.26)") + setup_model_options(self.prob, options) + + self.prob.model.set_input_defaults( + Mission.Takeoff.AIRPORT_ALTITUDE, + 0.0, + ) + + @unittest.skipIf( + version.parse(openmdao.__version__) < version.parse('3.26'), + 'Skipping due to OpenMDAO version being too low (<3.26)', + ) def test_taxi(self): self.prob.setup(check=False, force_alloc_complex=True) set_params_for_unit_tests(self.prob) - self.prob.set_val(Mission.Takeoff.AIRPORT_ALTITUDE, 0, units="ft") - self.prob.set_val(Mission.Taxi.MACH, 0.1, units="unitless") + self.prob.set_val(Mission.Takeoff.AIRPORT_ALTITUDE, 0, units='ft') + self.prob.set_val(Mission.Taxi.MACH, 0.1, units='unitless') self.prob.set_val( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, -1512, units="lbm/h") + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + -1512, + units='lbm/h', + ) self.prob.run_model() testvals = { - Dynamic.Mission.MASS: 175190.3, # lbm + Dynamic.Vehicle.MASS: 175190.3, # lbm } check_prob_outputs(self.prob, testvals, rtol=1e-6) partial_data = self.prob.check_partials( - out_stream=None, method="cs", excludes=["*atmos*", "*params*", "*aero*"] + out_stream=None, method='cs', excludes=['*atmos*', '*params*', '*aero*'] ) assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/test/test_v_rotate_comp.py b/aviary/mission/gasp_based/ode/test/test_v_rotate_comp.py new file mode 100644 index 0000000000..1c4df69f52 --- /dev/null +++ b/aviary/mission/gasp_based/ode/test/test_v_rotate_comp.py @@ -0,0 +1,64 @@ +import unittest + +import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials + +from aviary.constants import RHO_SEA_LEVEL_ENGLISH +from aviary.mission.gasp_based.ode.v_rotate_comp import VRotateComp +from aviary.variable_info.variables import Aircraft, Dynamic + + +class TestVRotateComp(unittest.TestCase): + """Test the computation of the speed at which takeoff rotation should be initiated.""" + + def test_partials(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'vrot_comp', VRotateComp(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + + prob.setup(force_alloc_complex=True) + + prob.set_val('dV1', val=10, units='kn') + prob.set_val('dVR', val=5, units='kn') + prob.set_val(Aircraft.Wing.AREA, val=1370, units='ft**2') + prob.set_val(Dynamic.Atmosphere.DENSITY, val=RHO_SEA_LEVEL_ENGLISH, units='slug/ft**3') + prob.set_val('CL_max', val=2.1886, units='unitless') + prob.set_val('mass', val=175_000, units='lbm') + + prob.run_model() + + # print(prob.get_val("Vrot", units="kn")) + + prob.check_partials(method='cs') + + +class TestVRotateComp2(unittest.TestCase): + """Test mass-weight conversion.""" + + def setUp(self): + import aviary.mission.gasp_based.ode.v_rotate_comp as vr + + vr.GRAV_ENGLISH_LBM = 1.1 + + def tearDown(self): + import aviary.mission.gasp_based.ode.v_rotate_comp as vr + + vr.GRAV_ENGLISH_LBM = 1.0 + + def test_partials(self): + prob = om.Problem() + prob.model.add_subsystem( + 'vrot_comp', VRotateComp(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + prob.setup(force_alloc_complex=True) + prob.set_val('dV1', val=10, units='kn') + prob.set_val('dVR', val=5, units='kn') + prob.set_val(Aircraft.Wing.AREA, val=1370, units='ft**2') + prob.set_val(Dynamic.Atmosphere.DENSITY, val=RHO_SEA_LEVEL_ENGLISH, units='slug/ft**3') + prob.set_val('CL_max', val=2.1886, units='unitless') + prob.set_val('mass', val=175_000, units='lbm') + + partial_data = prob.check_partials(method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/mission/gasp_based/ode/time_integration_base_classes.py b/aviary/mission/gasp_based/ode/time_integration_base_classes.py deleted file mode 100644 index b011808e08..0000000000 --- a/aviary/mission/gasp_based/ode/time_integration_base_classes.py +++ /dev/null @@ -1,1201 +0,0 @@ -import numpy as np -from scipy import interpolate - -import openmdao.api as om -from openmdao.utils import units - -from simupy.block_diagram import DEFAULT_INTEGRATOR_OPTIONS, SimulationMixin -from simupy.systems import DynamicalSystem - -from aviary.mission.gasp_based.ode.params import ParamPort -from aviary.variable_info.enums import Verbosity -from aviary.variable_info.variable_meta_data import _MetaData - - -def add_SGM_required_inputs(group: om.Group, inputs_to_add: dict): - """ - This is a simple utility that can be used to add inputs that are necessary for SGM but not collocation. - The SGM integrator expects that all states are inputs to the ODE. If any states aren't required by the EOM - they can be added to the ODE with this function, in order to minimize the differences between ODEs that are - used for both SGM and collocation. - """ - - blank_component = om.ExplicitComponent() - for input, details in inputs_to_add.items(): - blank_component.add_input(input, **details) - group.add_subsystem('SGM_required_inputs', - blank_component, - promotes_inputs=list(inputs_to_add.keys()), - ) - - -def add_SGM_required_outputs(group: om.Group, outputs_to_add: dict): - """ - This is a simple utility that can be used to add inputs that are necessary for SGM but not collocation. - The SGM integrator expects that all state rates are outputs from the ODE. If any state rates aren't - calculated by the EOM they can be added to the ODE with this function, in order to minimize the - differences between ODEs that are used for both SGM and collocation. - """ - - iv_comp = om.IndepVarComp() - for output, details in outputs_to_add.items(): - iv_comp.add_output(output, **details) - group.add_subsystem('SGM_required_outputs', - iv_comp, - promotes_outputs=list(outputs_to_add.keys()), - ) - - -class event_trigger(): - """ - event_trigger is used by SimuPyProblem to track the information that is required to trigger events during phases. - The state name, trigger value, and trigger units are required. Optionally a channel_name can be specified if it is - different from the state name. - Users are expect to interact with triggers primarily through SimuPyProblem.add_trigger() and - SimuPyProblem.clear_triggers(), but may want more detailed control over the triggers. - """ - - def __init__( - self, - state: str, - value: tuple[str, float, int], - units: str, - channel_name: str = None, - ): - self.state = state - self.value = value - self.units = units - if channel_name is None: - channel_name = state - self.channel_name = channel_name - - -class SimuPyProblem(SimulationMixin): - """ - Subproblem used as a basis for forward in time integration phases. - """ - - def __init__( - self, - ode, - aviary_options=None, - meta_data=_MetaData, - problem_name='', - time_independent=False, - t_name="t_curr", - states=None, - alternate_state_names=None, - blocked_state_names=None, - alternate_state_rate_names=None, - parameters=None, - outputs=None, - controls=None, - triggers=None, - include_state_outputs=False, - rate_suffix="_rate", - verbosity=Verbosity.QUIET, - max_allowable_time=1_000_000, - adjoint_int_opts=DEFAULT_INTEGRATOR_OPTIONS.copy(), - - ): - """ - states: a dictionary of the form {state_name:{'units':unit, 'rate':state_rate_name, 'rate_units':state_rate_units}} - alternate_state_names: a dictionary of the form {state_to_replace:new_state_name} - blocked_state_names: a list of the form [state_name_to_block] - alternate_state_rate_names: a dictionary of the form {state_to_modify:new_state_rate_name} - parameters: a dictionary of the form {parameter_name:unit} - outputs: a dictionary of the form {output_name:unit} - controls: a dictionary of the form {control_name:unit} - include_state_outputs : automatically add the state to the input - works well for auto-parsed naming, does not check for duplication before adding - states, parameters, outputs, and controls can also be input as a list of keys for the dictionary - """ - - default_om_list_args = dict(prom_name=True, val=False, - out_stream=None, units=True) - - self.verbosity = verbosity - self.max_allowable_time = max_allowable_time - self.adjoint_int_opts = adjoint_int_opts - self.adjoint_int_opts['nsteps'] = 5000 - self.adjoint_int_opts['name'] = "dop853" - - self.dt = 0.0 - prob = om.Problem() - if aviary_options: - from aviary.interface.methods_for_level2 import AviaryGroup - prob.model = AviaryGroup( - aviary_options=aviary_options, aviary_metadata=meta_data) - prob.model.add_subsystem( - "ODE_group", - ode, - promotes=["*"], - ) - self.ode = ode - - self.prob = prob - prob.setup(check=False, force_alloc_complex=True) - - # TODO - This is a hack to mimic the behavior of the old paramport, which - # contains some initial default values. It is unclear how actual "parameter" - # values are supposed to propagate from the pre-mission and top ivcs into - # the SGM phases. - from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests - set_params_for_unit_tests(prob) - - prob.final_setup() - - if triggers is None: - triggers = [] - elif not isinstance(triggers, list): - triggers = [triggers] - self.triggers = triggers - self.event_channel_names = [trigger.channel_name for trigger in triggers] - - self.time_independent = time_independent - if type(states) is list: - states = {state: {'units': None, 'rate': state+rate_suffix, 'rate_units': None} - for state in states} - if type(parameters) is list: - parameters = {parameter: None for parameter in parameters} - if type(outputs) is list: - outputs = {output: None for output in outputs} - if controls is None: - controls = {} - elif type(controls) is list: - controls = {control: None for control in controls} - if alternate_state_names is None: - alternate_state_names = {} - if alternate_state_rate_names is None: - alternate_state_rate_names = {} - - data = prob.model.list_inputs(includes=controls.keys(), **default_om_list_args) - control_data = {val.pop('prom_name'): val for key, val in data} - for control_name, control_units in controls.items(): - if control_units is None: - controls[control_name] = control_data[control_name]["units"] - self.controls = controls - - if ( - states is None - or parameters is None - or outputs is None # or - # event_names is None - ): - data = prob.model.list_outputs(**default_om_list_args) - model_outputs = [val['prom_name'] for key, val in data] - data = prob.model.list_inputs(**default_om_list_args) - model_inputs = [val['prom_name'] for key, val in data] - - if states is None: - states = { - output.replace(rate_suffix, ""): {'units': None, 'rate': output} - for output in model_outputs - if output.endswith(rate_suffix) - or output in alternate_state_names.keys() - } - - if blocked_state_names is not None: - for name in blocked_state_names: - if name in states.keys(): - states.pop(name) - if alternate_state_names: - for state_key, val in alternate_state_names.items(): - if state_key in states.keys(): # Used to rename an existing state - states[val] = states.pop(state_key) - else: # Used to add a new state - states[val] = {'units': None, 'rate': val+rate_suffix} - - if alternate_state_rate_names: - for state_name, val in alternate_state_rate_names.items(): - if state_name in states.keys(): - states[state_name]['rate'] = val - - state_rate_names = [val['rate'] for _, val in states.items()] - data = prob.model.list_outputs(includes=state_rate_names, **default_om_list_args) - rate_data = {val.pop('prom_name'): val for key, val in data} - for state_name, state_data in states.items(): - if state_data['rate_units'] is None: - state_data['rate_units'] = rate_data[state_data['rate']]["units"] - if state_data['units'] is None: - rate_unit = rate_data[state_data['rate']]["units"] - states[state_name]['units'] = units.simplify_unit("s*" + rate_unit) - - if parameters is None: - parameters = { - inp: None - for inp in set(model_inputs) - if inp not in list(states.keys()) + list(controls.keys()) + [t_name] - } - - data = prob.model.list_inputs(includes=parameters.keys(), **default_om_list_args) - parameter_data = {val.pop('prom_name'): val for key, val in data} - for parameter_name, parameter_units in parameters.items(): - if parameter_units is None: - parameters[parameter_name] = parameter_data[parameter_name]["units"] - - if outputs is None: - outputs = { - outp: None - for outp in model_outputs - if outp not in state_rate_names # + event_names - } - - for output_name, output_units in outputs.items(): - if output_units is None: - outputs[output_name] = next(iter(prob.model.get_io_metadata( - includes=[output_name], - metadata_keys=["units"] - ).values()))["units"] - - if include_state_outputs or outputs == {}: # prevent empty outputs - outputs.update({state: data['units'] for state, data in states.items()}) - - self.t_name = t_name - self.states = states - self.state_names = list(states.keys()) - - self.parameters = parameters - self.outputs = outputs - - self.dim_state = len(states) - self.dim_output = len(outputs) - self.dim_input = len(controls) - self.dim_parameters = len(parameters) - # TODO: add defensive checks to make sure dimensions match in both setup and - # calls - if verbosity >= Verbosity.VERBOSE: - if problem_name: - problem_name = '_'+problem_name - om.n2(prob, outfile="n2_simupy_problem" + - problem_name+".html", show_browser=False) - with open('input_list_simupy'+problem_name+'.txt', 'w') as outfile: - prob.model.list_inputs(out_stream=outfile,) - print(states) - - def add_parameter(self, name, units, **kwargs): - self.parameters[name] = units - self.dim_parameters = len(self.parameters) - - @property - def time(self): - return self.prob.get_val(self.t_name)[0] - - @time.setter - def time(self, value): - if self.time_independent or self.time == value: - return - self.prob.set_val(self.t_name, value) - - @property - def state(self): - return np.array( - [ - self.prob.get_val(state_name, units=state_data['units'])[0] - for state_name, state_data in self.states.items() - ] - ) - - @state.setter - def state(self, value): - if np.all(self.state == value): - return - for state_name, elem_val in zip( - self.states.keys(), value - ): - self.prob.set_val(state_name, elem_val, - units=self.states[state_name]['units']) - - def compute_along_traj(self, ts, xs): - self.prob.set_val(self.t_name, ts) - for state_name, elem_val in zip(self.states.keys(), xs.T): - self.prob.set_val(state_name, elem_val, - units=self.states[state_name]['units']) - - @property - def control(self): - return np.array( - [ - self.prob.get_val(control_name, units=unit)[0] - for control_name, unit in self.controls.items() - ] - ) - - @control.setter - def control(self, value): - if value is None: - value = np.array([]) - if (self.control.size == value.size) and np.all(self.control == value): - return - for control_name, elem_val in zip( - self.controls, value - ): - self.prob.set_val(control_name, elem_val, units=self.controls[control_name]) - - @property - def parameter(self): - return np.array( - [ - self.prob.get_val(parameter_name, units=unit)[0] - for parameter_name, unit in self.parameters.items() - ] - ) - - @parameter.setter - def parameter(self, value): - if np.all(self.parameter == value): - return - for parameter_name, elem_val in zip( - self.paramaters, value - ): - self.prob.set_val(parameter_name, elem_val) - - @property - def state_rate(self): - return np.array( - [ - self.prob.get_val(state_data['rate'], units=state_data['rate_units'])[0] - for _, state_data in self.states.items() - ] - ) - - @property - def output(self): - return np.array( - [ - self.prob.get_val(output_name, units=unit)[0] - for output_name, unit in self.outputs.items() - ] - ) - - @property - def events(self): - return np.array( - [ - self.prob.get_val(event_name, units=unit)[0] - for event_name, unit in zip(self.event_names, self.event_units) - ] - ) - - @property - def compute(self): - # TODO: create cache -- t, x (optionally u) as hash - # I guess just set_val for every input and output? - # for compute_totals, force run_model. anywhere else that needs forced - # run_model? - return self.prob.run_model - - @property - def compute_totals(self): - return self.prob.compute_totals - - def state_equation_function(self, t, x, u=None): - self.time = t - self.state = x - self.control = u - self.compute() - return self.state_rate - - def output_equation_function(self, t, x): - if self.output_nan: - return np.ones(self.dim_output) * np.nan - self.time = t - self.state = x - self.compute() - return self.output - - def prepare_to_integrate(self, t0, x0): - self.output_nan = False - # self.time = t0 - # self.state = x0 - # self.prob.run_model() - return self.output_equation_function(t0, x0) - - def update_equation_function(self, t, x, event_channels=None): - self.output_nan = True - return x - - def add_trigger(self, state, value, units=None, channel_name=None): - if isinstance(value, tuple): - units = value[1] - if units is None: - units = self.states[state]['units'] - elif hasattr(self, units): - units = getattr(self, units) - if channel_name is None: - channel_name = state - - self.triggers.append( - event_trigger(state, value, units, channel_name) - ) - self.event_channel_names.append(channel_name) - self.num_events = len(self.event_channel_names) - - def clear_triggers(self): - self.triggers = [] - self.event_channel_names = [] - self.num_events = 0 - - def event_equation_function(self, t, x): - self.output_equation_function(t, x) - self.compute() - event_values = [self.evaluate_trigger(trigger) for trigger in self.triggers] - # print(event_values) - return np.array(event_values) - - def evaluate_trigger(self, trigger: event_trigger): - trigger_value = trigger.value - if isinstance(trigger_value, str): - if hasattr(self, trigger_value): - trigger_value = getattr(self, trigger_value) - if isinstance(trigger_value, tuple): - trigger_value, trigger.units = trigger_value - else: - trigger_value = self.get_val( - trigger_value, units=trigger.units).squeeze() - current_value = self.get_val(trigger.state, units=trigger.units).squeeze() - return current_value - trigger_value - - @property - def get_val(self): - return self.prob.get_val - - @property - def set_val(self): - return self.prob.set_val - - -class SGMTrajBase(om.ExplicitComponent): - """ - SGMTrajBase is intended to mimic the dymos trajectory used in collocation problems as closely as possible. - Users are expected to mostly use FlexibleTraj which has some additions and helper functions that are more - specific to Aviary and aircraft simulation, whereas this base class is intended to be more generic and - provides a framework for any sort of SGM based trajectory. - """ - - def initialize(self, verbosity=Verbosity.QUIET): - # needs to get passed to each ODE - # TODO: param_dict - self.options.declare("param_dict", - default=ParamPort.param_data) - self.verbosity = verbosity - self.max_allowable_time = 1_000_000 - self.adjoint_int_opts = DEFAULT_INTEGRATOR_OPTIONS.copy() - self.adjoint_int_opts['nsteps'] = 5000 - self.adjoint_int_opts['name'] = "dop853" - self.additional_parameters = {} - - def add_parameter(self, name, units=None, **kwargs): - self.additional_parameters['parameters:'+name] = {'units': units} - - def setup_params( - self, - ODEs, - promote_all_auto_ivc=False, - traj_final_state_output=None, - traj_promote_final_output=None, - traj_promote_initial_input=None, - traj_initial_state_input=None, - traj_event_trigger_input=None, - traj_intermediate_state_output=None, - # traj_promote_intermediate_output=None, - ): - """ - API requirements: - pass ODE's, - next_problem = f(current_problem, current_result) - initial_state/time/etc - next_state from last state/output/event information - - pass in terminal and integrand output functions with derivatives (components) - -- anything special for final state, final time? - declare initial state(s) as parameters to take derivative wrt - assume all other inputs are parameters for deriv? - """ - if traj_promote_initial_input is None: - traj_promote_initial_input = {} - if traj_initial_state_input is None: - traj_initial_state_input = [] - # if traj_promote_intermediate_output is None: - # traj_promote_intermediate_output = [] - if traj_intermediate_state_output is None: - traj_intermediate_state_output = [] - if traj_final_state_output is None: - traj_final_state_output = [] - if traj_promote_final_output is None: - traj_promote_final_output = [] - if traj_event_trigger_input is None: - traj_event_trigger_input = [] - - self.phase_names = [ode.phase_name for ode in ODEs] - - if promote_all_auto_ivc: - for ode in ODEs: - ode: SimuPyProblem - ode.auto_ivc_vars = ode.prob.model.list_inputs( - is_indep_var=True, units=True, out_stream=None) - for abs_name, data in ode.auto_ivc_vars: - prom_name = data.pop('prom_name') - if '.' in prom_name: - continue - traj_promote_initial_input[prom_name] = data - - # TODO - This is a hack to mimic the behavior of the old paramport, which - # contains some initial default values. It is unclear how actual "parameter" - # values are supposed to propagate from the pre-mission and top ivcs into - # the SGM phases. - from aviary.mission.gasp_based.ode.params import params_for_unit_tests - traj_promote_initial_input = { - **params_for_unit_tests, - **traj_promote_initial_input - } - - self.traj_promote_initial_input = { - **self.options["param_dict"], **traj_promote_initial_input, **self.additional_parameters} - for name, kwargs in self.traj_promote_initial_input.items(): - self.add_input(name, **kwargs) - - final_suffix = "_final" - self.traj_final_state_output = { - final_state_output: { - **dict( - name=final_state_output+final_suffix, - state_name=final_state_output, - ), - **self.add_output( - final_state_output+final_suffix, - units=ODEs[-1].states[final_state_output]['units'], - ) - } - for final_state_output in traj_final_state_output - } - self.traj_intermediate_state_output = { - phase_name+'_'+intermediate_state_output+final_suffix: { - **dict( - phase_name=phase_name, - state_name=intermediate_state_output, - ), - **self.add_output( - phase_name+'_'+intermediate_state_output+final_suffix, - units=ODEs[self.phase_names.index( - phase_name)].states[intermediate_state_output]['units'], - ) - } - for phase_name, intermediate_state_output in traj_intermediate_state_output - } - self.traj_promote_final_output = { - promoted_final_output: { - **dict( - name=promoted_final_output+final_suffix, - output_name=promoted_final_output, - ), - **self.add_output( - promoted_final_output+final_suffix, - units=ODEs[-1].outputs[promoted_final_output], - ), - } - for promoted_final_output in traj_promote_final_output - } - # self.traj_promote_intermediate_output = { - # promoted_intermediate_output: { - # **dict( - # name=phase_name+'_'+promoted_intermediate_output+final_suffix, - # output_name=promoted_intermediate_output, - # ), - # **self.add_output( - # phase_name+'_'+promoted_intermediate_output, - # units=ODEs[-1].outputs[promoted_intermediate_output], - # ), - # } - # for phase_name,promoted_intermediate_output in traj_promote_intermediate_output - # } - self.all_traj_outputs = { - **self.traj_intermediate_state_output, - **self.traj_final_state_output, - # **self.traj_promote_intermediate_output, - **self.traj_promote_final_output, - } - initial_suffix = "_initial" - self.traj_initial_state_input = { - initial_state_input: { - **dict(name=initial_state_input+initial_suffix), - **self.add_input( - initial_state_input+initial_suffix, - units=ODEs[0].states[initial_state_input]['units'], - ) - } - for initial_state_input in traj_initial_state_input - } - - # TODO: assumes state, not output - trigger_suffix = "trigger" - self.traj_event_trigger_input = { - event_trigger_input: { - **dict(name="_".join([ - ODEs[self.phase_names.index( - event_trigger_input[0])].__class__.__name__, - event_trigger_input[1], - trigger_suffix - ])), - **self.add_input( - "_".join([ - ODEs[self.phase_names.index( - event_trigger_input[0])].__class__.__name__, - event_trigger_input[1], - trigger_suffix - ]), - units=ODEs[self.phase_names.index( - event_trigger_input[0])].states[event_trigger_input[1]]['units'], - ) - } - for event_trigger_input in traj_event_trigger_input - } - self.ODEs = ODEs - self.declare_partials(["*"], ["*"],) - - def compute_params(self, inputs): - for input in self.traj_promote_initial_input.keys(): - for ode in self.ODEs: - try: - ode.set_val(input.removeprefix('parameters:'), inputs[input]) - except KeyError: - if self.verbosity >= Verbosity.VERBOSE: - print( - "*** Input not found:", - ode, - input - ) - pass - - def compute_traj_loop(self, first_problem, inputs, outputs, t0=0., state0=None): - if self.verbosity >= Verbosity.VERBOSE: - print("initializing compute_traj_loop") - sim_results = [] - sim_problems = [first_problem] - t = t0 - if state0 is not None: - state = state0 - else: - state = np.array([ - inputs[state_name+"_initial"].squeeze() - if state_name in self.traj_initial_state_input - else 0. - for state_name in first_problem.state_names - ]).squeeze() - - while True: - current_problem = sim_problems[-1] - current_problem.initial_condition = state - - sim_result = current_problem.simulate( - (t, self.max_allowable_time), - ) - if sim_result.t.shape[0] == 2: - print("\n"*3, "IMMEDIATE PHASE TERMINATION", current_problem, "\n"*2) - sim_results.append(sim_result) - - t = sim_result.t[-1] - x = sim_result.x[-1, :] - - for output_name, output in self.traj_intermediate_state_output.items(): - if output['phase_name'] == current_problem.phase_name: - outputs[output_name] = sim_result.x[ - -1, - current_problem.state_names.index(output["state_name"]) - ] - - # TODO: is there a better way to do this? Perhaps don't use for loop -- use - # while True ?Ij - try: - try_next_problem = (yield current_problem, sim_result) - except GeneratorExit: - if self.verbosity >= 2: - print("stop iteration 1") - break - - if try_next_problem is not None: - next_problem = try_next_problem - else: - try: - next_problem = (yield current_problem, sim_result) - except GeneratorExit: - if self.verbosity >= Verbosity.VERBOSE: - print("stop iteration 2") - break - - if self.verbosity >= Verbosity.VERBOSE: - print(" was on problem:", current_problem, - "\n got back:", next_problem) - # compute the output at the final condition to make sure all outputs are current - current_problem.output_equation_function(t, x) - state = np.array( - [ - current_problem.prob.get_val(state_name, units=state_data['units']) - for state_name, state_data in next_problem.states.items() - ] - ).squeeze() - sim_problems.append(next_problem) - - if self.verbosity >= Verbosity.VERBOSE: - print("ended loop") - - # wrap main loop - self.sim_results = sim_results - self.sim_problems = sim_problems - - # trajectory-specific outputs - for output in self.traj_final_state_output: - output_name = self.traj_final_state_output[output]["name"] - state_name = self.traj_final_state_output[output]["state_name"] - - outputs[output_name] = sim_results[-1].x[ - -1, - sim_problems[-1].state_names.index(state_name) - ] - - for output in self.traj_promote_final_output: - promoted_name = self.traj_promote_final_output[output]["name"] - output_name = self.traj_promote_final_output[output]["output_name"] - - outputs[promoted_name] = sim_results[-1].y[ - -1, - list(sim_problems[-1].outputs.keys()).index(output_name) - ] - - self.last_inputs = np.array(list(inputs.values())) - - def compute_partials(self, inputs, J): - self.compute_params(inputs) - # defensive check -- should really make sure ALL inputs are the same, need a - # deep copy - # just calling compute_params doesn't fix it -- possibly different trajectory! - - if np.any(self.last_inputs != np.array(list(inputs.values()))): - raise ValueError( - "Attempting to run compute_partials when the last compute" - " inputs did not match", - ) - - param_dict = self.options["param_dict"] - - # assume the first problem has the most states? - costate_reses = {output: [] for output in self.all_traj_outputs} - tf_total = self.sim_results[-1].t[-1] - - next_res = self.sim_results[-1] - next_prob = self.sim_problems[-1] - - df_dxs = [] - df_dparams = [] - dg_dxs = [] - f_minuses = [] - f_pluses = [np.zeros(self.sim_problems[-1].dim_state)] - state_updates = [next_res.x[-1, :]] - dh_dxs = [np.eye(next_prob.dim_state)] - - dh_dparams = [np.zeros((next_prob.dim_state, len(param_dict)))] - - # keep directionality of forward for plant, backward for adjoint by caching - # everything in order to ensure fewest number of ODE calls with smallest - # step-size sum(abs(x[i]-x[i-1]), ) - costate_ics = [] - param_derivs = [] - - for output in self.all_traj_outputs: - output_name = self.all_traj_outputs[output]["name"] - costate = np.zeros(next_prob.dim_state) - param_deriv = np.zeros(len(param_dict)) - - if output in self.traj_final_state_output: - costate[next_prob.state_names.index(output)] = 1. - else: # in self.traj_promote_final_output - - next_prob.state_equation_function(next_res.t[-1], next_res.x[-1, :]) - costate[:] = next_prob.compute_totals( - output, - next_prob.state_names, - return_format='array' - ).squeeze() - - param_deriv[:] = next_prob.compute_totals( - output, - list(param_dict.keys()), - return_format='array' - ).squeeze() - - param_derivs.append(param_deriv) - costate_ics.append(costate) - - # pre-compute data for adjoint - for phase_idx, res, prob in zip( - range(len(self.sim_results), 0, -1), - self.sim_results[::-1], - self.sim_problems[::-1], - ): - # build time-varying co-state matrix - df_dx_data = np.empty(res.x.shape + (res.x.shape[-1],)) - - if param_dict: - df_dparam_data = np.empty(res.x.shape + (len(param_dict),)) - - last_res_idx = res.t.shape[0] - 1 - - num_active_event_channels = 0 - - state_rate = prob.state_equation_function(res.t[-1], res.x[-1, :]) - if (prob is not self.sim_problems[0]): - f_minuses.append(state_rate) - - for channel_idx, channel_name in enumerate(prob.event_channel_names): - - if np.argmin(np.abs(res.e[-1, :])) not in [channel_idx]: - continue - - num_active_event_channels += 1 - dg_dx = np.zeros((1, prob.dim_state)) - - if channel_name in prob.state_names: - dg_dx[0, prob.state_names.index(channel_name)] = 1. - else: - dg_dx[0, :] = prob.compute_totals( - [channel_name], - prob.state_names, - return_format='array' - ) - - # TODO: actually save dg_dts - if channel_name == prob.t_name: - dg_dt = 1. - else: - dg_dt = 0. - - dg_dxs.append(dg_dx) - - if num_active_event_channels != 1: - raise ValueError("Somehow ended a phase without an event? assume " - "time in the future?? but currently no time-based " - "events are used") - - for idx, (t, x) in enumerate(zip(res.t[::-1], res.x[::-1, :])): - state_rate = prob.state_equation_function(t, x) - - if (idx == last_res_idx) and (prob is not self.sim_problems[0]): - next_prob = self.sim_problems[self.sim_problems.index(prob)-1] - - f_plus = np.zeros(next_prob.dim_state) - plus_rate = state_rate - - # NOTE / TODO: should enforce that all states in all ODEs exist - # in eachother (even if only as output). Don't like assuming - # zero - # state_update = np.zeros(next_prob.dim_state) - state_update = np.ones(next_prob.dim_state)*np.inf - dh_dx = np.zeros((next_prob.dim_state,)*2) - dh_dparam = np.zeros((next_prob.dim_state, len(param_dict))) - - # here and co-state assume number of states is only decreasing - # forward in time - for state_name in next_prob.state_names: - state_idx = next_prob.state_names.index(state_name) - - if state_name in prob.state_names: - f_plus[ - state_idx - ] = plus_rate[prob.state_names.index(state_name)] - - # state_update[ - # next_prob.state_names.index(state_name) - # ] = x[prob.state_names.index(state_name)] - - # TODO: make sure index multiplying next_pronb costate - # lines up -- since costate is pre-filled to next_prob's - # order, the continuous terms should be right - # column should map to - dh_dx[state_idx, state_idx] = 1. - - elif state_name in prob.outputs.keys(): - state_update[ - state_idx - ] = res.y[-1, list(prob.outputs.keys()).index(state_name)] - - dh_j_dx = prob.compute_totals( - [state_name], - prob.state_names, - return_format='array').squeeze() - - dh_dparam[state_idx, :] = prob.compute_totals( - [state_name], - list(param_dict.keys()), - return_format='array' - ).squeeze() - - for state_name_2 in prob.state_names: - # I'm actually computing dh_dx.T - # dh_dx rows are new state, columns are old state - # now, dh_dx.T rows are old state, columns are new - # so I think this is right - dh_dx[ - next_prob.state_names.index(state_name_2), - state_idx, - ] = dh_j_dx[prob.state_names.index(state_name_2)] - - else: - state_update[ - state_idx - ] = 0. - - f_pluses.append(f_plus) - state_updates.append(state_update) - dh_dxs.append(dh_dx) - dh_dparams.append(dh_dparam) - - state_rate_names = [val['rate'] for _, val in prob.states.items()] - df_dx_data[idx, :, :] = prob.compute_totals(state_rate_names, - prob.state_names, - return_format='array').T - if param_dict: - df_dparam_data[idx, ...] = prob.compute_totals( - state_rate_names, - list(param_dict.keys()), - return_format='array' - ) - - k = min(3, res.t.shape[0]-1) - skip_interp = (k == 1) and np.isclose(res.t[0], res.t[1]) - - # TODO: why is this failing? - if skip_interp: - mean_df_dx = np.mean(df_dx_data, axis=0) - - df_dxs.append(lambda t: mean_df_dx) - else: - try: - df_dxs.append(interpolate.make_interp_spline( - tf_total - res.t[::-1], - df_dx_data, - k=k - )) - except Exception as e: - - print("EXCEPTION!", k, res.t, df_dx_data, sep='\n') - print("check: ", (k == 1) and (res.t[0] == res.t[1])) - breakpoint() - raise e - - if param_dict: - if skip_interp: - mean_df_dparam = np.mean(df_dparam_data, axis=0) - df_dparams.append(lambda t: mean_df_dparam) - else: - df_dparams.append(interpolate.make_interp_spline( - tf_total - res.t[::-1], - df_dparam_data, - k=k - )) - else: - df_dparams.append(None) - - if self.verbosity == Verbosity.DEBUG: - print("data....") - print("dgs", dg_dxs) - print("f-", f_minuses) - print("f+", f_pluses) - - print("size check:", len(self.sim_problems), len(dg_dxs), len(f_minuses), - len(f_pluses), ) - - # main loop - for output, costate_ic, param_deriv in zip(self.all_traj_outputs, costate_ics, - param_derivs): - - output_name = self.all_traj_outputs[output]["name"] - next_prob = self.sim_problems[-1] - costate = costate_ic - lamda_dot_plus = np.zeros_like(costate) - - # self.sim_results[-1].x[-1, next_prob.state_names.index(output)] - if self.verbosity >= Verbosity.VERBOSE: - print("\nstarting partial for %s" % output, costate) - - dg_dt = 0. - - for ( - phase_idx, - res, - prob, - df_dx, - df_dparam, - dg_dx, - f_minus, - f_plus, - state_update, - dh_dx, - dh_dparam, - ) in zip( - range(len(self.sim_results), 0, -1), - self.sim_results[::-1], - self.sim_problems[::-1], - df_dxs, - df_dparams, - dg_dxs, - f_minuses, - f_pluses, - state_updates, - dh_dxs, - dh_dparams, - ): - - t0, tf = tf_total - res.t[[-1, 0]] - - # assumes only 1 of time, state, or output dependence - # assume no discontinuous state update, would need an API for that in - # compute as well -- - # but assume some form of event has happened - - # already checked that event_channel_names was well-defined in the - # pre-compute, so will just assign the co-state just once - for channel_idx, channel_name in enumerate(prob.event_channel_names): - if np.argmin(np.abs(res.e[-1, :])) not in [channel_idx]: - continue - - state_disc = res.x[-1] - state_update - state_disc[np.where(np.isinf(state_update))] = 0. - - if channel_name != prob.t_name: - lamda_dot = df_dx(res.t[-1]) @ costate - # lamda_dot_plus = lamda_dot - if self.verbosity == Verbosity.DEBUG: - if np.any(state_disc): - print("update is non-zero!", prob, prob.state_names, - state_disc, costate, lamda_dot) - print( - "inner product becomes...", - state_disc[None, - :] @ dh_dx @ lamda_dot_plus[:, None], - state_disc[None, - :] @ dh_dx.T @ lamda_dot_plus[:, None] - ) - print("dh_dx for", prob, prob.state_names, "\n", dh_dx) - print("costate", costate) - costate_update_terms = [ - dh_dx.T @ costate[:, None], - # costate[:, None], - # TODO: should this be f_plus? probably not - (dg_dx.T @ (f_plus - f_minus) - [None, :] @ costate[:, None]) / (dg_dx@f_minus), - # don't believe in lamda_dot terms anymore - # -(dg_dx.T @ state_disc[None, :] @ dh_dx.T @ lamda_dot_plus[:, None]) / (dg_dx@f_minus), - - ] - - # TODO: is this wrong? - costate[:] = np.sum(costate_update_terms, axis=0).squeeze() - - if ( - (event_key := (prob, channel_name, channel_idx)) - in self.traj_event_trigger_input - ): - event_trigger_name = self.traj_event_trigger_input[event_key]["name"] - if self.verbosity >= Verbosity.VERBOSE: - print("setting event trigger data", event_trigger_name) - J[output_name, event_trigger_name] = ( - + costate[None, :] @ (f_minus - f_plus) / - (dg_dt + dg_dx@f_minus) - # +(lamda_dot_plus[None, :] @ dh_dx @ state_disc[None, :])/(dg_dt + dg_dx@f_minus) - ) - - # how to account for terminal event? through costate IC. - # TODO: Is this wrong? - param_deriv += (costate[None, :] @ dh_dparam).squeeze() - - # build co-state systems - - def co_state_rate(t, costate, *args): - return df_dx(t) @ costate - - if self.verbosity >= Verbosity.VERBOSE: - print('dim_state:', prob.dim_state, "ic:", costate) - - costate_sys = DynamicalSystem(state_equation_function=co_state_rate, - dim_state=prob.dim_state) - costate_sys.initial_condition = costate - - # simulate co-state system - co_res = costate_sys.simulate( - (t0, tf), integrator_options=self.adjoint_int_opts) - costate_reses[output].append(co_res) - - if param_dict: - df_dparam_val = df_dparam(co_res.t) - param_deriv_integrand_data = np.matmul( - co_res.x[:, None, :], - df_dparam_val - ).squeeze() - try: - param_deriv_integrand = interpolate.make_interp_spline( - co_res.t, - np.atleast_1d(param_deriv_integrand_data), - # k=df_dparam.k - k=min(3, co_res.t.shape[0]-1) - ) - except ValueError as e: - print( - "HIT VALUE ERROR!", - output, - prob, - co_res.t.shape, - co_res.x.shape, - df_dparam_val.shape, - df_dparam.k, - "final_results:\n\n", - t0, tf, - co_res.t, - co_res.x, - ) - raise e - param_deriv_integrand_antideriv = param_deriv_integrand.antiderivative() - - # TODO: is the sign wrong here? - param_deriv -= ( - param_deriv_integrand_antideriv(t0) - - param_deriv_integrand_antideriv(tf) - ) - - # consume initial condition - if prob is not self.sim_problems[0]: - next_prob = self.sim_problems[self.sim_problems.index(prob)-1] - else: - break - costate = np.zeros(next_prob.dim_state) - lamda_dot_plus = np.zeros_like(costate) - lamda_dot_plus_rate = co_state_rate(co_res.t[-1], co_res.x[-1]) - - # TODO: do co-states need unit changes? probably not... - for state_name in prob.state_names: - costate[next_prob.state_names.index( - state_name)] = co_res.x[-1, prob.state_names.index(state_name)] - lamda_dot_plus[ - next_prob.state_names.index(state_name) - ] = lamda_dot_plus_rate[prob.state_names.index(state_name)] - - for state_to_deriv, metadata in self.traj_initial_state_input.items(): - param_name = metadata["name"] - J[output_name, param_name] = costate_reses[output][-1].x[ - -1, - prob.state_names.index(state_to_deriv) - ] - for param_deriv_val, param_deriv_name in zip(param_deriv, param_dict): - J[output_name, param_deriv_name] = param_deriv_val - self.costate_reses = costate_reses - - -class _killer_comp(om.ExplicitComponent): - ''' - This component will stop the execution of the integration during compute, - this is useful for debugging trajectories by getting the initial value - of variables for a phase and then exiting. - ''' - - def compute(self, inputs, outputs): - print(f'exit in {self.name}') - exit() diff --git a/aviary/mission/gasp_based/ode/two_dof_ode.py b/aviary/mission/gasp_based/ode/two_dof_ode.py new file mode 100644 index 0000000000..b30dfe5dc1 --- /dev/null +++ b/aviary/mission/gasp_based/ode/two_dof_ode.py @@ -0,0 +1,252 @@ +import numpy as np +import openmdao.api as om + +from aviary.mission.base_ode import BaseODE as _BaseODE +from aviary.mission.ode.altitude_rate import AltitudeRate +from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate +from aviary.variable_info.enums import AlphaModes +from aviary.variable_info.variables import Aircraft, Dynamic + + +class TwoDOFODE(_BaseODE): + """The base class for all 2 Degree-of-Freedom ODE components.""" + + def initialize(self): + super().initialize() + + def add_alpha_control( + self, + alpha_group=None, + alpha_mode: AlphaModes = AlphaModes.DEFAULT, + num_nodes=1, + target_load_factor=1.1, + target_tas_rate=0, + # target_alt_rate=0, + # target_flight_path_angle=0, + atol=1e-7, + rtol=1e-7, + add_default_solver=True, + print_level=0, + ): + """This is used when angle of attack in an ODE needs to be controlled directly.""" + if not alpha_group: + alpha_group = self + nn = num_nodes + + if alpha_mode is AlphaModes.ROTATION: + alpha_comp = om.ExecComp( + 'alpha=rotation_rate*(t_curr-start_rotation)+alpha_init', + alpha=dict(val=0.0, units='deg'), + rotation_rate=dict(val=10.0 / 3.0, units='deg/s'), + t_curr=dict(val=0.0, units='s'), + start_rotation=dict(val=0.0, units='s'), + alpha_init=dict(val=0.0, units='deg'), + ) + alpha_comp_inputs = [ + 'rotation_rate', + 't_curr', + 'start_rotation', + ('alpha_init', Aircraft.Wing.INCIDENCE), + ] + alpha_comp_outputs = [('alpha', Dynamic.Vehicle.ANGLE_OF_ATTACK)] + + elif alpha_mode is AlphaModes.LOAD_FACTOR: + alpha_comp = om.BalanceComp( + name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=np.full(nn, 10), # initial guess + units='deg', + eq_units='unitless', + lhs_name='load_factor', + rhs_val=target_load_factor, + upper=25.0, + lower=-2.0, + ) + alpha_comp_inputs = ['load_factor'] + alpha_comp_outputs = [Dynamic.Vehicle.ANGLE_OF_ATTACK] + + elif alpha_mode is AlphaModes.FUSELAGE_PITCH: + alpha_comp = om.ExecComp( + 'alpha=max_fus_angle-gamma+i_wing', + alpha=dict(val=0.0, units='deg'), + max_fus_angle=dict(val=0.0, units='deg'), + gamma=dict(val=0.0, units='deg'), + i_wing=dict(val=0.0, units='deg'), + ) + alpha_comp_inputs = [ + ('max_fus_angle', Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE), + ('gamma', Dynamic.Mission.FLIGHT_PATH_ANGLE), + ('i_wing', Aircraft.Wing.INCIDENCE), + ] + alpha_comp_outputs = [('alpha', Dynamic.Vehicle.ANGLE_OF_ATTACK)] + + elif alpha_mode is AlphaModes.DECELERATION: + alpha_comp = om.BalanceComp( + name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=np.full(nn, 10), # initial guess + units='deg', + lhs_name=Dynamic.Mission.VELOCITY_RATE, + rhs_name='target_tas_rate', + rhs_val=target_tas_rate, + eq_units='kn/s', + upper=25.0, + lower=-2.0, + ) + alpha_comp_inputs = [Dynamic.Mission.VELOCITY_RATE] + alpha_comp_outputs = [Dynamic.Vehicle.ANGLE_OF_ATTACK] + + elif alpha_mode is AlphaModes.REQUIRED_LIFT: + alpha_comp = om.BalanceComp( + name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=8.0 * np.ones(nn), + units='deg', + rhs_name='required_lift', + lhs_name=Dynamic.Vehicle.LIFT, + eq_units='lbf', + upper=12.0, + lower=-2, + ) + alpha_comp_inputs = ['required_lift', Dynamic.Vehicle.LIFT] + alpha_comp_outputs = [Dynamic.Vehicle.ANGLE_OF_ATTACK] + + # Future controller modes + # elif alpha_mode is AlphaModes.FLIGHT_PATH_ANGLE: + # alpha_comp = om.BalanceComp( + # name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + # val=np.full(nn, 1), + # units="deg", + # lhs_name=Dynamic.Mission.FLIGHT_PATH_ANGLE, + # rhs_name='target_flight_path_angle', + # rhs_val=target_flight_path_angle, + # eq_units="deg", + # upper=12.0, + # lower=-2, + # ) + # alpha_comp_inputs = [Dynamic.Mission.FLIGHT_PATH_ANGLE] + + # elif alpha_mode is AlphaModes.ALTITUDE_RATE: + # alpha_comp = om.BalanceComp( + # name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + # val=np.full(nn, 1), + # units="deg", + # lhs_name=Dynamic.Mission.ALTITUDE_RATE, + # rhs_name='target_alt_rate', + # rhs_val=target_alt_rate, + # upper=12.0, + # lower=-2, + # ) + # alpha_comp_inputs = [Dynamic.Mission.ALTITUDE_RATE] + + # elif alpha_mode is AlphaModes.CONSTANT_ALTITUDE: + # alpha_comp = om.BalanceComp( + # name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + # val=np.full(nn, 1), + # units="deg", + # lhs_name=Dynamic.Mission.ALTITUDE, + # rhs_name='target_alt', + # rhs_val=37500, + # upper=12.0, + # lower=-2, + # ) + # alpha_comp_inputs = [Dynamic.Mission.ALTITUDE] + + if alpha_mode is not AlphaModes.DEFAULT: + alpha_group.add_subsystem( + 'alpha_comp', + alpha_comp, + promotes_inputs=alpha_comp_inputs, + promotes_outputs=alpha_comp_outputs, + ) + + if add_default_solver and alpha_mode not in (AlphaModes.ROTATION,): + alpha_group.nonlinear_solver = om.NewtonSolver() + alpha_group.nonlinear_solver.options['solve_subsystems'] = True + alpha_group.nonlinear_solver.options['iprint'] = print_level + alpha_group.nonlinear_solver.options['atol'] = atol + alpha_group.nonlinear_solver.options['rtol'] = rtol + alpha_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() + alpha_group.linear_solver = om.DirectSolver(assemble_jac=True) + + def add_throttle_control( + self, + prop_group=om.Group(), + num_nodes=1, + atol=1e-12, + rtol=1e-12, + add_default_solver=True, + print_level=0, + ): + """This is used when throttle in an ODE needs to be controlled directly.""" + nn = num_nodes + + thrust_bal = om.BalanceComp( + name=Dynamic.Vehicle.Propulsion.THROTTLE, + val=np.ones(nn), + upper=1.0, + lower=0.0, + units='unitless', + lhs_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + rhs_name='required_thrust', + eq_units='lbf', + ) + prop_group.add_subsystem( + 'thrust_balance', + thrust_bal, + promotes_inputs=[ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + 'required_thrust', + ], + promotes_outputs=[Dynamic.Vehicle.Propulsion.THROTTLE], + ) + + if add_default_solver: + prop_group.linear_solver = om.DirectSolver() + prop_group.linear_solver.options['iprint'] = print_level + + prop_group.nonlinear_solver = om.NewtonSolver() + prop_group.nonlinear_solver.options['err_on_non_converge'] = False + prop_group.nonlinear_solver.options['solve_subsystems'] = True + prop_group.nonlinear_solver.options['maxiter'] = 20 + prop_group.nonlinear_solver.options['iprint'] = print_level + prop_group.nonlinear_solver.options['atol'] = atol + prop_group.nonlinear_solver.options['rtol'] = rtol + prop_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() + prop_group.linear_solver = om.DirectSolver(assemble_jac=True) + + if prop_group is not self: + self.add_subsystem('prop_group', prop_group, promotes=['*']) + + def add_excess_rate_comps(self, nn): + """Add SpecificEnergyRate and AltitudeRate components.""" + self.add_subsystem( + name='SPECIFIC_ENERGY_RATE_EXCESS', + subsys=SpecificEnergyRate(num_nodes=nn), + promotes_inputs=[ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.MASS, + ( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + ), + Dynamic.Vehicle.DRAG, + ], + promotes_outputs=[ + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ) + ], + ) + + self.add_subsystem( + name='ALTITUDE_RATE_MAX', + subsys=AltitudeRate(num_nodes=nn), + promotes_inputs=[ + ( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + ), + Dynamic.Mission.VELOCITY_RATE, + Dynamic.Mission.VELOCITY, + ], + promotes_outputs=[(Dynamic.Mission.ALTITUDE_RATE, Dynamic.Mission.ALTITUDE_RATE_MAX)], + ) diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py b/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py index 84b35f5401..1d93ab8303 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/gamma_comp.py @@ -5,50 +5,60 @@ class GammaComp(om.ExplicitComponent): - """ - Computes flight path angle and its curvature. - """ + """Computes flight path angle and its curvature.""" def __init__(self, **kwargs): super().__init__(**kwargs) def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] - - self.add_input("dh_dr", shape=nn, units="m/distance_units", - desc="change in altitude wrt range") - - self.add_input("d2h_dr2", shape=nn, units="m/distance_units**2", - desc="second derivative of altitude wrt range") - - self.add_output(Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, units="rad", - desc="flight path angle") - - self.add_output("dgam_dr", shape=nn, units="rad/distance_units", - desc="change in flight path angle per unit range traversed") + nn = self.options['num_nodes'] + + self.add_input( + 'dh_dr', shape=nn, units='m/distance_units', desc='change in altitude wrt range' + ) + + self.add_input( + 'd2h_dr2', + shape=nn, + units='m/distance_units**2', + desc='second derivative of altitude wrt range', + ) + + self.add_output( + Dynamic.Mission.FLIGHT_PATH_ANGLE, + shape=nn, + units='rad', + desc='flight path angle', + ) + + self.add_output( + 'dgam_dr', + shape=nn, + units='rad/distance_units', + desc='change in flight path angle per unit range traversed', + ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] ar = np.arange(nn, dtype=int) - self.declare_partials(of=Dynamic.Mission.FLIGHT_PATH_ANGLE, - wrt="dh_dr", rows=ar, cols=ar) - self.declare_partials(of="dgam_dr", wrt=["dh_dr", "d2h_dr2"], rows=ar, cols=ar) + self.declare_partials(of=Dynamic.Mission.FLIGHT_PATH_ANGLE, wrt='dh_dr', rows=ar, cols=ar) + self.declare_partials(of='dgam_dr', wrt=['dh_dr', 'd2h_dr2'], rows=ar, cols=ar) def compute(self, inputs, outputs): - dh_dr = inputs["dh_dr"] - d2h_dr2 = inputs["d2h_dr2"] + dh_dr = inputs['dh_dr'] + d2h_dr2 = inputs['d2h_dr2'] outputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] = np.arctan(dh_dr) - outputs["dgam_dr"] = d2h_dr2 / (dh_dr**2 + 1) + outputs['dgam_dr'] = d2h_dr2 / (dh_dr**2 + 1) def compute_partials(self, inputs, partials): - dh_dr = inputs["dh_dr"] - d2h_dr2 = inputs["d2h_dr2"] + dh_dr = inputs['dh_dr'] + d2h_dr2 = inputs['d2h_dr2'] - partials[Dynamic.Mission.FLIGHT_PATH_ANGLE, "dh_dr"] = 1. / (dh_dr**2 + 1) - partials["dgam_dr", "dh_dr"] = -d2h_dr2 * dh_dr * 2 / (dh_dr**2 + 1)**2 - partials["dgam_dr", "d2h_dr2"] = 1. / (dh_dr**2 + 1) + partials[Dynamic.Mission.FLIGHT_PATH_ANGLE, 'dh_dr'] = 1.0 / (dh_dr**2 + 1) + partials['dgam_dr', 'dh_dr'] = -d2h_dr2 * dh_dr * 2 / (dh_dr**2 + 1) ** 2 + partials['dgam_dr', 'd2h_dr2'] = 1.0 / (dh_dr**2 + 1) diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_gamma_comp.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_gamma_comp.py index 6290cbc5e3..dc1d395362 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_gamma_comp.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_gamma_comp.py @@ -2,123 +2,121 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.mission.gasp_based.ode.unsteady_solved.gamma_comp import GammaComp -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom import \ - UnsteadySolvedEOM +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom import UnsteadySolvedEOM from aviary.variable_info.variables import Aircraft, Dynamic class TestUnsteadyFlightEOM(unittest.TestCase): - """ - Test 2-degree of freedom equations of motion for unsteady flight - """ + """Test 2-degree of freedom equations of motion for unsteady flight.""" def _test_unsteady_flight_eom(self, ground_roll=False): nn = 5 p = om.Problem() - p.model.add_subsystem("eom", - UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll), - promotes_inputs=["*"], - promotes_outputs=["*"]) + p.model.add_subsystem( + 'eom', + UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) p.setup(force_alloc_complex=True) - p.set_val(Dynamic.Mission.VELOCITY, 250, units="kn") - p.set_val(Dynamic.Mission.MASS, 175_000, units="lbm") - p.set_val(Dynamic.Mission.THRUST_TOTAL, 20_000, units="lbf") - p.set_val(Dynamic.Mission.LIFT, 175_000, units="lbf") - p.set_val(Dynamic.Mission.DRAG, 20_000, units="lbf") - p.set_val(Aircraft.Wing.INCIDENCE, 0.0, units="deg") + p.set_val(Dynamic.Mission.VELOCITY, 250, units='kn') + p.set_val(Dynamic.Vehicle.MASS, 175_000, units='lbm') + p.set_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, 20_000, units='lbf') + p.set_val(Dynamic.Vehicle.LIFT, 175_000, units='lbf') + p.set_val(Dynamic.Vehicle.DRAG, 20_000, units='lbf') + p.set_val(Aircraft.Wing.INCIDENCE, 0.0, units='deg') if not ground_roll: - p.set_val("alpha", 0.0, units="deg") - p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0, units="deg") - p.set_val("dh_dr", 0, units=None) - p.set_val("d2h_dr2", 0, units="1/m") + p.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, units='deg') + p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0, units='deg') + p.set_val('dh_dr', 0, units=None) + p.set_val('d2h_dr2', 0, units='1/m') p.run_model() # p.model.list_inputs() # p.model.list_outputs(print_arrays=True, units=True) - dt_dr = p.get_val("dt_dr", units="h/NM") - normal_force = p.get_val("normal_force", units="lbf") - load_factor = p.get_val("load_factor", units="unitless") - fuselage_pitch = p.get_val("fuselage_pitch", units="deg") + dt_dr = p.get_val('dt_dr', units='h/NM') + normal_force = p.get_val('normal_force', units='lbf') + load_factor = p.get_val('load_factor', units='unitless') + fuselage_pitch = p.get_val('fuselage_pitch', units='deg') # True airspeed in level flight is dr_dt - assert_near_equal(1/dt_dr, 250.0 * np.ones(nn), tolerance=1.0E-12) + assert_near_equal(1 / dt_dr, 250.0 * np.ones(nn), tolerance=1.0e-12) # Normal force in balanced level flight is 0.0 - assert_near_equal(normal_force, np.zeros(nn), tolerance=1.0E-12) + assert_near_equal(normal_force, np.zeros(nn), tolerance=1.0e-12) # Fuselage pitch balanced level flight with zero alpha and wing incidence is 0.0 - assert_near_equal(fuselage_pitch, np.zeros(nn), tolerance=1.0E-12) + assert_near_equal(fuselage_pitch, np.zeros(nn), tolerance=1.0e-12) # Load factor balanced level flight with zero alpha and wing incidence is 1.0 - assert_near_equal(load_factor, np.ones(nn), tolerance=1.0E-12) + assert_near_equal(load_factor, np.ones(nn), tolerance=1.0e-12) if not ground_roll: - dgam_dt = p.get_val("dgam_dt", units="deg/s") - dgam_dt_approx = p.get_val("dgam_dt_approx", units="deg/s") + dgam_dt = p.get_val('dgam_dt', units='deg/s') + dgam_dt_approx = p.get_val('dgam_dt_approx', units='deg/s') # Both approximate and computed dgam_dt should be zero. - assert_near_equal(dgam_dt, np.zeros(nn), tolerance=1.0E-12) - assert_near_equal(dgam_dt_approx, np.zeros(nn), tolerance=1.0E-12) - - p.set_val(Dynamic.Mission.VELOCITY, 250 + 10 * np.random.rand(nn), units="kn") - p.set_val(Dynamic.Mission.MASS, 175_000 + 1000 * np.random.rand(nn), units="lbm") - p.set_val(Dynamic.Mission.THRUST_TOTAL, 20_000 + - 100 * np.random.rand(nn), units="lbf") - p.set_val(Dynamic.Mission.LIFT, 175_000 + 1000 * np.random.rand(nn), units="lbf") - p.set_val(Dynamic.Mission.DRAG, 20_000 + 100 * np.random.rand(nn), units="lbf") - p.set_val(Aircraft.Wing.INCIDENCE, np.random.rand(1), units="deg") + assert_near_equal(dgam_dt, np.zeros(nn), tolerance=1.0e-12) + assert_near_equal(dgam_dt_approx, np.zeros(nn), tolerance=1.0e-12) + + p.set_val(Dynamic.Mission.VELOCITY, 250 + 10 * np.random.rand(nn), units='kn') + p.set_val(Dynamic.Vehicle.MASS, 175_000 + 1000 * np.random.rand(nn), units='lbm') + p.set_val( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + 20_000 + 100 * np.random.rand(nn), + units='lbf', + ) + p.set_val(Dynamic.Vehicle.LIFT, 175_000 + 1000 * np.random.rand(nn), units='lbf') + p.set_val(Dynamic.Vehicle.DRAG, 20_000 + 100 * np.random.rand(nn), units='lbf') + p.set_val(Aircraft.Wing.INCIDENCE, np.random.rand(1), units='deg') if not ground_roll: - p.set_val("alpha", 5 * np.random.rand(nn), units="deg") - p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, - 5 * np.random.rand(nn), units="deg") - p.set_val("dh_dr", 0.1 * np.random.rand(nn), units=None) - p.set_val("d2h_dr2", 0.01 * np.random.rand(nn), units="1/m") + p.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 5 * np.random.rand(nn), units='deg') + p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 5 * np.random.rand(nn), units='deg') + p.set_val('dh_dr', 0.1 * np.random.rand(nn), units=None) + p.set_val('d2h_dr2', 0.01 * np.random.rand(nn), units='1/m') p.run_model() with np.printoptions(linewidth=1024): - cpd = p.check_partials(method="cs") + cpd = p.check_partials(method='cs') assert_check_partials(cpd) def test_unsteady_flight_eom(self): for ground_roll in True, False: - with self.subTest(msg=f"ground_roll={ground_roll}"): + with self.subTest(msg=f'ground_roll={ground_roll}'): self._test_unsteady_flight_eom(ground_roll=ground_roll) def test_gamma_comp(self): nn = 2 p = om.Problem() - p.model.add_subsystem("gamma", - GammaComp(num_nodes=nn), - promotes_inputs=[ - "dh_dr", - "d2h_dr2"], - promotes_outputs=[ - Dynamic.Mission.FLIGHT_PATH_ANGLE, - "dgam_dr"]) + p.model.add_subsystem( + 'gamma', + GammaComp(num_nodes=nn), + promotes_inputs=['dh_dr', 'd2h_dr2'], + promotes_outputs=[Dynamic.Mission.FLIGHT_PATH_ANGLE, 'dgam_dr'], + ) p.setup(force_alloc_complex=True) p.run_model() assert_near_equal( - p[Dynamic.Mission.FLIGHT_PATH_ANGLE], [0.78539816, 0.78539816], - tolerance=1.0E-6) - assert_near_equal( - p["dgam_dr"], [0.5, 0.5], - tolerance=1.0E-6) + p[Dynamic.Mission.FLIGHT_PATH_ANGLE], + [0.78539816, 0.78539816], + tolerance=1.0e-6, + ) + assert_near_equal(p['dgam_dr'], [0.5, 0.5], tolerance=1.0e-6) - partial_data = p.check_partials(out_stream=None, method="cs") + partial_data = p.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py index 2c6653816f..81ef8d7a7d 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_alpha_thrust_iter_group.py @@ -1,26 +1,26 @@ import unittest import numpy as np - import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.constants import GRAV_ENGLISH_LBM from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_control_iter_group import \ - UnsteadyControlIterGroup -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_flight_conditions import \ - UnsteadySolvedFlightConditions +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_control_iter_group import ( + UnsteadyControlIterGroup, +) +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_flight_conditions import ( + UnsteadySolvedFlightConditions, +) from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import LegacyCode, SpeedType -from aviary.variable_info.options import get_option_defaults +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic class TestUnsteadyAlphaThrustIterGroup(unittest.TestCase): - """ - Test the UnsteadyControlIterGroup. - """ + """Test the UnsteadyControlIterGroup.""" def _test_unsteady_alpha_thrust_iter_group(self, ground_roll=False): nn = 5 @@ -30,27 +30,24 @@ def _test_unsteady_alpha_thrust_iter_group(self, ground_roll=False): p = om.Problem() - fc = UnsteadySolvedFlightConditions(num_nodes=nn, - input_speed_type=SpeedType.TAS, - ground_roll=ground_roll) + fc = UnsteadySolvedFlightConditions( + num_nodes=nn, input_speed_type=SpeedType.TAS, ground_roll=ground_roll + ) - p.model.add_subsystem("fc", subsys=fc, - promotes_inputs=["*"], - promotes_outputs=["*"]) + p.model.add_subsystem('fc', subsys=fc, promotes_inputs=['*'], promotes_outputs=['*']) - g = UnsteadyControlIterGroup(num_nodes=nn, - ground_roll=ground_roll, - clean=True, - aviary_options=get_option_defaults(), - core_subsystems=[aero]) + g = UnsteadyControlIterGroup( + num_nodes=nn, ground_roll=ground_roll, clean=True, core_subsystems=[aero] + ) - ig = p.model.add_subsystem("iter_group", - subsys=g, - promotes_inputs=["*"], - promotes_outputs=["*"]) + ig = p.model.add_subsystem( + 'iter_group', subsys=g, promotes_inputs=['*'], promotes_outputs=['*'] + ) if ground_roll: - ig.set_input_defaults("alpha", np.zeros(nn), units="deg") + ig.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, np.zeros(nn), units='deg') + + setup_model_options(p, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) p.setup(force_alloc_complex=True) @@ -58,32 +55,33 @@ def _test_unsteady_alpha_thrust_iter_group(self, ground_roll=False): p.final_setup() - p.set_val(Dynamic.Mission.SPEED_OF_SOUND, 968.076 * np.ones(nn), units="ft/s") - p.set_val( - Dynamic.Mission.DENSITY, 0.000659904 * np.ones(nn), units="slug/ft**3" - ) - p.set_val(Dynamic.Mission.VELOCITY, 487 * np.ones(nn), units="kn") - p.set_val("mass", 170_000 * np.ones(nn), units="lbm") - p.set_val("dTAS_dr", 0.0 * np.ones(nn), units="kn/NM") + p.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 968.076 * np.ones(nn), units='ft/s') + p.set_val(Dynamic.Atmosphere.DENSITY, 0.000659904 * np.ones(nn), units='slug/ft**3') + p.set_val(Dynamic.Mission.VELOCITY, 487 * np.ones(nn), units='kn') + p.set_val('mass', 170_000 * np.ones(nn), units='lbm') + p.set_val('dTAS_dr', 0.0 * np.ones(nn), units='kn/NM') if not ground_roll: - p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0.0 * np.ones(nn), units="rad") - p.set_val("alpha", 4 * np.ones(nn), units="deg") - p.set_val("dh_dr", 0.0 * np.ones(nn), units=None) - p.set_val("d2h_dr2", 0.0 * np.ones(nn), units="1/NM") + p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0.0 * np.ones(nn), units='rad') + p.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 4 * np.ones(nn), units='deg') + p.set_val('dh_dr', 0.0 * np.ones(nn), units=None) + p.set_val('d2h_dr2', 0.0 * np.ones(nn), units='1/NM') - p.set_val("thrust_req", 8000 * np.ones(nn), units="lbf") + p.set_val('thrust_req', 8000 * np.ones(nn), units='lbf') p.run_model() - drag = p.model.get_val(Dynamic.Mission.DRAG, units="lbf") - lift = p.model.get_val(Dynamic.Mission.LIFT, units="lbf") - thrust_req = p.model.get_val("thrust_req", units="lbf") - gamma = 0 if ground_roll else p.model.get_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, units="deg") - weight = p.model.get_val("mass", units="lbm") * GRAV_ENGLISH_LBM - iwing = p.model.get_val(Aircraft.Wing.INCIDENCE, units="deg") - alpha = iwing if ground_roll else p.model.get_val("alpha", units="deg") + drag = p.model.get_val(Dynamic.Vehicle.DRAG, units='lbf') + lift = p.model.get_val(Dynamic.Vehicle.LIFT, units='lbf') + thrust_req = p.model.get_val('thrust_req', units='lbf') + gamma = ( + 0 if ground_roll else p.model.get_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, units='deg') + ) + weight = p.model.get_val('mass', units='lbm') * GRAV_ENGLISH_LBM + iwing = p.model.get_val(Aircraft.Wing.INCIDENCE, units='deg') + alpha = ( + iwing if ground_roll else p.model.get_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, units='deg') + ) c_alphai = np.cos(np.radians(alpha - iwing)) s_alphai = np.sin(np.radians(alpha - iwing)) @@ -97,14 +95,15 @@ def _test_unsteady_alpha_thrust_iter_group(self, ground_roll=False): # 2. Test that forces balance normal to the velocity axis assert_near_equal(lift + thrust_req * s_alphai, weight * c_gamma) - cpd = p.check_partials(out_stream=None, method="cs", step=1.01e-40, - excludes=["*params*", "*aero*"]) + cpd = p.check_partials( + out_stream=None, method='cs', step=1.01e-40, excludes=['*params*', '*aero*'] + ) assert_check_partials(cpd, atol=1e-10, rtol=1e-10) def test_iter_group(self): # issue #494: why not ground_roll in [True] ? for ground_roll in [False]: - with self.subTest(msg=f"ground_roll={ground_roll}"): + with self.subTest(msg=f'ground_roll={ground_roll}'): self._test_unsteady_alpha_thrust_iter_group(ground_roll=ground_roll) diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_flight_conditions.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_flight_conditions.py index 3a2fb66c6b..24214c2df0 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_flight_conditions.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_flight_conditions.py @@ -2,21 +2,19 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.constants import RHO_SEA_LEVEL_METRIC -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_flight_conditions import \ - UnsteadySolvedFlightConditions +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_flight_conditions import ( + UnsteadySolvedFlightConditions, +) +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Dynamic class TestUnsteadyFlightConditions(unittest.TestCase): - """ - Unit test for UnsteadySolvedFlightConditions - """ + """Unit test for UnsteadySolvedFlightConditions.""" def _test_unsteady_flight_conditions(self, ground_roll=False, input_speed_type=SpeedType.TAS): nn = 5 @@ -28,65 +26,65 @@ def _test_unsteady_flight_conditions(self, ground_roll=False, input_speed_type=S subsys=Atmosphere(num_nodes=nn, output_dsos_dh=True), promotes_inputs=[Dynamic.Mission.ALTITUDE], promotes_outputs=[ - Dynamic.Mission.DENSITY, - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, - "viscosity", - "drhos_dh", - "dsos_dh", + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + 'viscosity', + 'drhos_dh', + 'dsos_dh', ], ) p.model.add_subsystem( - "flight_conditions", + 'flight_conditions', UnsteadySolvedFlightConditions( num_nodes=nn, ground_roll=ground_roll, input_speed_type=input_speed_type ), - promotes_inputs=["*"], - promotes_outputs=["*"], + promotes_inputs=['*'], + promotes_outputs=['*'], ) p.setup(force_alloc_complex=True) if input_speed_type is SpeedType.TAS: - p.set_val(Dynamic.Mission.ALTITUDE, 37500, units="ft") - p.set_val(Dynamic.Mission.VELOCITY, 250, units="kn") - p.set_val("dTAS_dr", np.zeros(nn), units="kn/km") + p.set_val(Dynamic.Mission.ALTITUDE, 37500, units='ft') + p.set_val(Dynamic.Mission.VELOCITY, 250, units='kn') + p.set_val('dTAS_dr', np.zeros(nn), units='kn/km') elif input_speed_type is SpeedType.EAS: - p.set_val(Dynamic.Mission.ALTITUDE, 37500, units="ft") - p.set_val("EAS", 250, units="kn") - p.set_val("dEAS_dr", np.zeros(nn), units="kn/km") + p.set_val(Dynamic.Mission.ALTITUDE, 37500, units='ft') + p.set_val('EAS', 250, units='kn') + p.set_val('dEAS_dr', np.zeros(nn), units='kn/km') else: - p.set_val(Dynamic.Mission.ALTITUDE, 37500, units="ft") - p.set_val(Dynamic.Mission.MACH, 0.78, units="unitless") - p.set_val("dmach_dr", np.zeros(nn), units="unitless/km") + p.set_val(Dynamic.Mission.ALTITUDE, 37500, units='ft') + p.set_val(Dynamic.Atmosphere.MACH, 0.78, units='unitless') + p.set_val('dmach_dr', np.zeros(nn), units='1/km') p.run_model() - mach = p.get_val(Dynamic.Mission.MACH) - eas = p.get_val("EAS") - tas = p.get_val(Dynamic.Mission.VELOCITY, units="m/s") - sos = p.get_val(Dynamic.Mission.SPEED_OF_SOUND, units="m/s") - rho = p.get_val(Dynamic.Mission.DENSITY, units="kg/m**3") + mach = p.get_val(Dynamic.Atmosphere.MACH) + eas = p.get_val('EAS') + tas = p.get_val(Dynamic.Mission.VELOCITY, units='m/s') + sos = p.get_val(Dynamic.Atmosphere.SPEED_OF_SOUND, units='m/s') + rho = p.get_val(Dynamic.Atmosphere.DENSITY, units='kg/m**3') rho_sl = RHO_SEA_LEVEL_METRIC - dTAS_dt_approx = p.get_val("dTAS_dt_approx") + dTAS_dt_approx = p.get_val('dTAS_dt_approx') - assert_near_equal(mach, tas/sos) + assert_near_equal(mach, tas / sos) assert_near_equal(eas, tas * np.sqrt(rho / rho_sl)) assert_near_equal(dTAS_dt_approx, np.zeros(nn)) with np.printoptions(linewidth=1024): - cpd = p.check_partials(method="cs") + cpd = p.check_partials(method='cs') assert_check_partials(cpd) def test_unsteady_flight_conditions(self): - for ground_roll in True, False: for in_type in [SpeedType.TAS, SpeedType.EAS, SpeedType.MACH]: - with self.subTest(msg=f"ground_roll={ground_roll} in_type={in_type}"): + with self.subTest(msg=f'ground_roll={ground_roll} in_type={in_type}'): self._test_unsteady_flight_conditions( - ground_roll=ground_roll, input_speed_type=in_type) + ground_roll=ground_roll, input_speed_type=in_type + ) if __name__ == '__main__': diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_eom.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_eom.py index 30bab82304..b965f88560 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_eom.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_eom.py @@ -2,144 +2,148 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom import \ - UnsteadySolvedEOM +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom import UnsteadySolvedEOM from aviary.variable_info.variables import Aircraft, Dynamic class TestUnsteadySolvedEOM(unittest.TestCase): - """ - unit test for UnsteadySolvedEOM - """ + """unit test for UnsteadySolvedEOM.""" def _test_unsteady_solved_eom(self, ground_roll=False): nn = 5 p = om.Problem() - p.model.add_subsystem("eom", - UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll), - promotes_inputs=["*"], - promotes_outputs=["*"]) + p.model.add_subsystem( + 'eom', + UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) p.setup(force_alloc_complex=True) - p.set_val(Dynamic.Mission.VELOCITY, 250, units="kn") - p.set_val("mass", 175_000, units="lbm") - p.set_val(Dynamic.Mission.THRUST_TOTAL, 20_000, units="lbf") - p.set_val(Dynamic.Mission.LIFT, 175_000, units="lbf") - p.set_val(Dynamic.Mission.DRAG, 20_000, units="lbf") - p.set_val(Aircraft.Wing.INCIDENCE, 0.0, units="deg") + p.set_val(Dynamic.Mission.VELOCITY, 250, units='kn') + p.set_val('mass', 175_000, units='lbm') + p.set_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, 20_000, units='lbf') + p.set_val(Dynamic.Vehicle.LIFT, 175_000, units='lbf') + p.set_val(Dynamic.Vehicle.DRAG, 20_000, units='lbf') + p.set_val(Aircraft.Wing.INCIDENCE, 0.0, units='deg') if not ground_roll: - p.set_val("alpha", 0.0, units="deg") - p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0, units="deg") - p.set_val("dh_dr", 0, units=None) - p.set_val("d2h_dr2", 0, units="1/m") + p.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, units='deg') + p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0, units='deg') + p.set_val('dh_dr', 0, units=None) + p.set_val('d2h_dr2', 0, units='1/m') p.run_model() # p.model.list_inputs() # p.model.list_outputs(print_arrays=True, units=True) - dt_dr = p.get_val("dt_dr", units="h/NM") - normal_force = p.get_val("normal_force", units="lbf") - load_factor = p.get_val("load_factor", units="unitless") - fuselage_pitch = p.get_val("fuselage_pitch", units="deg") + dt_dr = p.get_val('dt_dr', units='h/NM') + normal_force = p.get_val('normal_force', units='lbf') + load_factor = p.get_val('load_factor', units='unitless') + fuselage_pitch = p.get_val('fuselage_pitch', units='deg') # True airspeed in level flight is dr_dt - assert_near_equal(1/dt_dr, 250.0 * np.ones(nn), tolerance=1.0E-12) + assert_near_equal(1 / dt_dr, 250.0 * np.ones(nn), tolerance=1.0e-12) # Normal force in balanced level flight is 0.0 - assert_near_equal(normal_force, np.zeros(nn), tolerance=1.0E-12) + assert_near_equal(normal_force, np.zeros(nn), tolerance=1.0e-12) # Fuselage pitch balanced level flight with zero alpha and wing incidence is 0.0 - assert_near_equal(fuselage_pitch, np.zeros(nn), tolerance=1.0E-12) + assert_near_equal(fuselage_pitch, np.zeros(nn), tolerance=1.0e-12) # Load factor balanced level flight with zero alpha and wing incidence is 1.0 - assert_near_equal(load_factor, np.ones(nn), tolerance=1.0E-12) + assert_near_equal(load_factor, np.ones(nn), tolerance=1.0e-12) if not ground_roll: - dgam_dt = p.get_val("dgam_dt", units="deg/s") - dgam_dt_approx = p.get_val("dgam_dt_approx", units="deg/s") + dgam_dt = p.get_val('dgam_dt', units='deg/s') + dgam_dt_approx = p.get_val('dgam_dt_approx', units='deg/s') # Both approximate and computed dgam_dt should be zero. - assert_near_equal(dgam_dt, np.zeros(nn), tolerance=1.0E-12) - assert_near_equal(dgam_dt_approx, np.zeros(nn), tolerance=1.0E-12) - - p.set_val(Dynamic.Mission.VELOCITY, 250 + 10 * np.random.rand(nn), units="kn") - p.set_val("mass", 175_000 + 1000 * np.random.rand(nn), units="lbm") - p.set_val(Dynamic.Mission.THRUST_TOTAL, 20_000 + - 100 * np.random.rand(nn), units="lbf") - p.set_val(Dynamic.Mission.LIFT, 175_000 + 1000 * np.random.rand(nn), units="lbf") - p.set_val(Dynamic.Mission.DRAG, 20_000 + 100 * np.random.rand(nn), units="lbf") - p.set_val(Aircraft.Wing.INCIDENCE, np.random.rand(1), units="deg") + assert_near_equal(dgam_dt, np.zeros(nn), tolerance=1.0e-12) + assert_near_equal(dgam_dt_approx, np.zeros(nn), tolerance=1.0e-12) + + p.set_val(Dynamic.Mission.VELOCITY, 250 + 10 * np.random.rand(nn), units='kn') + p.set_val('mass', 175_000 + 1000 * np.random.rand(nn), units='lbm') + p.set_val( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + 20_000 + 100 * np.random.rand(nn), + units='lbf', + ) + p.set_val(Dynamic.Vehicle.LIFT, 175_000 + 1000 * np.random.rand(nn), units='lbf') + p.set_val(Dynamic.Vehicle.DRAG, 20_000 + 100 * np.random.rand(nn), units='lbf') + p.set_val(Aircraft.Wing.INCIDENCE, np.random.rand(1), units='deg') if not ground_roll: - p.set_val("alpha", 5 * np.random.rand(nn), units="deg") - p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, - 5 * np.random.rand(nn), units="deg") - p.set_val("dh_dr", 0.1 * np.random.rand(nn), units=None) - p.set_val("d2h_dr2", 0.01 * np.random.rand(nn), units="1/m") + p.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 5 * np.random.rand(nn), units='deg') + p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 5 * np.random.rand(nn), units='deg') + p.set_val('dh_dr', 0.1 * np.random.rand(nn), units=None) + p.set_val('d2h_dr2', 0.01 * np.random.rand(nn), units='1/m') p.run_model() with np.printoptions(linewidth=1024): - cpd = p.check_partials(method="cs") + cpd = p.check_partials(method='cs') assert_check_partials(cpd) def test_unsteady_solved_eom(self): for ground_roll in True, False: - with self.subTest(msg=f"ground_roll={ground_roll}"): + with self.subTest(msg=f'ground_roll={ground_roll}'): self._test_unsteady_solved_eom(ground_roll=ground_roll) class TestUnsteadySolvedEOM2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom as unsteady + unsteady.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom as unsteady + unsteady.GRAV_ENGLISH_LBM = 1.0 def _test_unsteady_solved_eom(self, ground_roll=False): nn = 2 p = om.Problem() - p.model.add_subsystem("eom", - UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll), - promotes_inputs=["*"], - promotes_outputs=["*"]) + p.model.add_subsystem( + 'eom', + UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) p.setup(force_alloc_complex=True) - p.set_val(Dynamic.Mission.VELOCITY, 250 + 10 * np.random.rand(nn), units="kn") - p.set_val("mass", 175_000 + 1000 * np.random.rand(nn), units="lbm") - p.set_val(Dynamic.Mission.THRUST_TOTAL, 20_000 + - 100 * np.random.rand(nn), units="lbf") - p.set_val(Dynamic.Mission.LIFT, 175_000 + 1000 * np.random.rand(nn), units="lbf") - p.set_val(Dynamic.Mission.DRAG, 20_000 + 100 * np.random.rand(nn), units="lbf") - p.set_val(Aircraft.Wing.INCIDENCE, np.random.rand(1), units="deg") + p.set_val(Dynamic.Mission.VELOCITY, 250 + 10 * np.random.rand(nn), units='kn') + p.set_val('mass', 175_000 + 1000 * np.random.rand(nn), units='lbm') + p.set_val( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + 20_000 + 100 * np.random.rand(nn), + units='lbf', + ) + p.set_val(Dynamic.Vehicle.LIFT, 175_000 + 1000 * np.random.rand(nn), units='lbf') + p.set_val(Dynamic.Vehicle.DRAG, 20_000 + 100 * np.random.rand(nn), units='lbf') + p.set_val(Aircraft.Wing.INCIDENCE, np.random.rand(1), units='deg') if not ground_roll: - p.set_val("alpha", nn * np.random.rand(nn), units="deg") - p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, - nn * np.random.rand(nn), units="deg") - p.set_val("dh_dr", 0.1 * np.random.rand(nn), units=None) - p.set_val("d2h_dr2", 0.01 * np.random.rand(nn), units="1/m") + p.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, nn * np.random.rand(nn), units='deg') + p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, nn * np.random.rand(nn), units='deg') + p.set_val('dh_dr', 0.1 * np.random.rand(nn), units=None) + p.set_val('d2h_dr2', 0.01 * np.random.rand(nn), units='1/m') - partial_data = p.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=5e-11, rtol=1e-12) + partial_data = p.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=5e-11, rtol=1e-11) def test_unsteady_solved_eom(self): for ground_roll in True, False: - with self.subTest(msg=f"ground_roll={ground_roll}"): + with self.subTest(msg=f'ground_roll={ground_roll}'): self._test_unsteady_solved_eom(ground_roll=ground_roll) diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py index a873b68c10..421eeeb985 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/test/test_unsteady_solved_ode.py @@ -1,46 +1,52 @@ import unittest import numpy as np - import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials +from openmdao.utils.assert_utils import assert_near_equal from aviary.constants import GRAV_ENGLISH_LBM from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_ode import \ - UnsteadySolvedODE +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_ode import UnsteadySolvedODE from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems from aviary.variable_info.enums import SpeedType +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic class TestUnsteadySolvedODE(unittest.TestCase): - """ Test the unsteady solved ODE in steady level flight. """ + """Test the unsteady solved ODE in steady level flight.""" - def _test_unsteady_solved_ode(self, ground_roll=False, input_speed_type=SpeedType.MACH, clean=True): + def _test_unsteady_solved_ode( + self, ground_roll=False, input_speed_type=SpeedType.MACH, clean=True + ): nn = 5 p = om.Problem() aviary_options = get_option_defaults() default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_options)) + 'GASP', [build_engine_deck(aviary_options)] + ) - ode = UnsteadySolvedODE(num_nodes=nn, - input_speed_type=input_speed_type, - clean=clean, - ground_roll=ground_roll, - aviary_options=aviary_options, - core_subsystems=default_mission_subsystems) + ode = UnsteadySolvedODE( + num_nodes=nn, + input_speed_type=input_speed_type, + clean=clean, + ground_roll=ground_roll, + aviary_options=aviary_options, + core_subsystems=default_mission_subsystems, + ) - p.model.add_subsystem("ode", ode, promotes=["*"]) + p.model.add_subsystem('ode', ode, promotes=['*']) - p.model.set_input_defaults(Dynamic.Mission.MACH, 0.8 * np.ones(nn)) + p.model.set_input_defaults(Dynamic.Atmosphere.MACH, 0.8 * np.ones(nn)) if ground_roll: - p.model.set_input_defaults(Dynamic.Mission.MACH, 0.1 * np.ones(nn)) - ode.set_input_defaults("alpha", np.zeros(nn), units="deg") + p.model.set_input_defaults(Dynamic.Atmosphere.MACH, 0.1 * np.ones(nn)) + ode.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, np.zeros(nn), units='deg') + + setup_model_options(p, aviary_options) p.setup(force_alloc_complex=True) @@ -48,36 +54,37 @@ def _test_unsteady_solved_ode(self, ground_roll=False, input_speed_type=SpeedTyp p.final_setup() - p.set_val(Dynamic.Mission.SPEED_OF_SOUND, 968.076 * np.ones(nn), units="ft/s") - p.set_val( - Dynamic.Mission.DENSITY, 0.000659904 * np.ones(nn), units="slug/ft**3" - ) - p.set_val("mach", 0.8 * np.ones(nn), units="unitless") - p.set_val("mass", 170_000 * np.ones(nn), units="lbm") + p.set_val(Aircraft.Wing.FORM_FACTOR, 1.25, units='unitless') + p.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 968.076 * np.ones(nn), units='ft/s') + p.set_val(Dynamic.Atmosphere.DENSITY, 0.000659904 * np.ones(nn), units='slug/ft**3') + p.set_val('mach', 0.8 * np.ones(nn), units='unitless') + p.set_val('mass', 170_000 * np.ones(nn), units='lbm') if not ground_roll: - p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0.0 * np.ones(nn), units="rad") - p.set_val("alpha", 4 * np.ones(nn), units="deg") - p.set_val("dh_dr", 0.0 * np.ones(nn), units="ft/NM") - p.set_val("d2h_dr2", 0.0 * np.ones(nn), units="1/NM") + p.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 0.0 * np.ones(nn), units='rad') + p.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 4 * np.ones(nn), units='deg') + p.set_val('dh_dr', 0.0 * np.ones(nn), units='ft/NM') + p.set_val('d2h_dr2', 0.0 * np.ones(nn), units='1/NM') - p.set_val("thrust_req", 8000 * np.ones(nn), units="lbf") + p.set_val('thrust_req', 8000 * np.ones(nn), units='lbf') p.run_model() - drag = p.model.get_val(Dynamic.Mission.DRAG, units="lbf") - lift = p.model.get_val(Dynamic.Mission.LIFT, units="lbf") - thrust_req = p.model.get_val("thrust_req", units="lbf") - gamma = 0 if ground_roll else p.model.get_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, units="deg") - weight = p.model.get_val("mass", units="lbm") * GRAV_ENGLISH_LBM + drag = p.model.get_val(Dynamic.Vehicle.DRAG, units='lbf') + lift = p.model.get_val(Dynamic.Vehicle.LIFT, units='lbf') + thrust_req = p.model.get_val('thrust_req', units='lbf') + gamma = ( + 0 if ground_roll else p.model.get_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, units='deg') + ) + weight = p.model.get_val('mass', units='lbm') * GRAV_ENGLISH_LBM fuelflow = p.model.get_val( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units="lbm/s") - dmass_dr = p.model.get_val("dmass_dr", units="lbm/ft") - dt_dr = p.model.get_val("dt_dr", units="s/ft") - tas = p.model.get_val(Dynamic.Mission.VELOCITY, units="ft/s") - iwing = p.model.get_val(Aircraft.Wing.INCIDENCE, units="deg") - alpha = p.model.get_val("alpha", units="deg") + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/s' + ) + dmass_dr = p.model.get_val('dmass_dr', units='lbm/ft') + dt_dr = p.model.get_val('dt_dr', units='s/ft') + tas = p.model.get_val(Dynamic.Mission.VELOCITY, units='ft/s') + iwing = p.model.get_val(Aircraft.Wing.INCIDENCE, units='deg') + alpha = p.model.get_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, units='deg') c_alphai = np.cos(np.radians(alpha - iwing)) s_alphai = np.sin(np.radians(alpha - iwing)) @@ -86,36 +93,32 @@ def _test_unsteady_solved_ode(self, ground_roll=False, input_speed_type=SpeedTyp s_gamma = np.sin(np.radians(gamma)) # 1. Test that forces balance along the velocity axis - assert_near_equal(drag + thrust_req * s_gamma, - thrust_req * c_alphai, tolerance=1.0E-12) + assert_near_equal(drag + thrust_req * s_gamma, thrust_req * c_alphai, tolerance=1.0e-12) # 2. Test that forces balance normal to the velocity axis - assert_near_equal(lift + thrust_req * s_alphai, - weight * c_gamma, tolerance=1.0E-12) + assert_near_equal(lift + thrust_req * s_alphai, weight * c_gamma, tolerance=1.0e-12) # 3. Test that dt_dr is the inverse of true airspeed - assert_near_equal(tas, 1/dt_dr, tolerance=1.0E-12) + assert_near_equal(tas, 1 / dt_dr, tolerance=1.0e-12) # 4. Test that the inverse of dt_dr is true airspeed - assert_near_equal(tas, 1/dt_dr, tolerance=1.0E-12) + assert_near_equal(tas, 1 / dt_dr, tolerance=1.0e-12) # 5. Test that fuelflow (lbf/s) * dt_dr (s/ft) is equal to dmass_dr - assert_near_equal(fuelflow * dt_dr, dmass_dr, tolerance=1.0E-12) + assert_near_equal(fuelflow * dt_dr, dmass_dr, tolerance=1.0e-12) - cpd = p.check_partials(out_stream=None, method="cs", - excludes=["*params*", "*aero*"]) + p.check_partials(out_stream=None, method='cs', excludes=['*params*', '*aero*']) # issue #495 # dTAS_dt_approx wrt flight_path_angle | abs | fwd-fd | 1.8689625335382314 # dTAS_dt_approx wrt flight_path_angle | rel | fwd-fd | 1.0 # assert_check_partials(cpd, atol=1e-6, rtol=1e-6) def test_steady_level_flight(self): - # issue #494: why not ground_roll in [True] ? for ground_roll in [False]: - with self.subTest(msg=f"ground_roll={ground_roll}"): + with self.subTest(msg=f'ground_roll={ground_roll}'): self._test_unsteady_solved_ode(ground_roll=ground_roll) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_control_iter_group.py b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_control_iter_group.py index 2df7762bde..26992e8174 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_control_iter_group.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_control_iter_group.py @@ -2,45 +2,51 @@ import openmdao.api as om from aviary.constants import RHO_SEA_LEVEL_ENGLISH - +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom import UnsteadySolvedEOM from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom import UnsteadySolvedEOM - class UnsteadyControlIterGroup(om.Group): - """ - This Group contains a nonlinear solver to determine alpha and thrust for a given flight condition. - """ + """This Group contains a nonlinear solver to determine alpha and thrust for a given flight condition.""" def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare("ground_roll", types=bool, default=False, - desc="True if the aircraft is confined to the ground. Removes altitude rate as an " - "output and adjusts the TAS rate equation.") - self.options.declare("clean", types=bool, default=False, - desc="If true then no flaps or gear are included. Useful for high-speed flight phases.") + self.options.declare('num_nodes', types=int) self.options.declare( - 'aviary_options', types=AviaryValues, default=None, - desc='collection of Aircraft/Mission specific options' + 'ground_roll', + types=bool, + default=False, + desc='True if the aircraft is confined to the ground. Removes altitude rate as an ' + 'output and adjusts the TAS rate equation.', + ) + self.options.declare( + 'clean', + types=bool, + default=False, + desc='If true then no flaps or gear are included. Useful for high-speed flight phases.', ) - # TODO finish description self.options.declare( - 'core_subsystems', - desc='list of core subsystems' + 'aviary_options', + types=AviaryValues, + default=None, + desc='collection of Aircraft/Mission specific options', ) + # TODO finish description + self.options.declare('core_subsystems', desc='list of core subsystems') + self.options.declare( - 'subsystem_options', types=dict, default={}, - desc='dictionary of parameters to be passed to the subsystem builders' + 'subsystem_options', + types=dict, + default={}, + desc='dictionary of parameters to be passed to the subsystem builders', ) def setup(self): - nn = self.options["num_nodes"] - ground_roll = self.options["ground_roll"] - clean = self.options["clean"] + nn = self.options['num_nodes'] + ground_roll = self.options['ground_roll'] + clean = self.options['clean'] aviary_options = self.options['aviary_options'] core_subsystems = self.options['core_subsystems'] @@ -54,60 +60,70 @@ def setup(self): for subsystem in core_subsystems: system = subsystem.build_mission(**kwargs) if system is not None: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs(**kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) eom_comp = UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll) - self.add_subsystem("eom", subsys=eom_comp, - promotes_inputs=["*", - (Dynamic.Mission.THRUST_TOTAL, "thrust_req")], - promotes_outputs=["*"]) + self.add_subsystem( + 'eom', + subsys=eom_comp, + promotes_inputs=[ + '*', + (Dynamic.Vehicle.Propulsion.THRUST_TOTAL, 'thrust_req'), + ], + promotes_outputs=['*'], + ) thrust_alpha_bal = om.BalanceComp() if not self.options['ground_roll']: - thrust_alpha_bal.add_balance("alpha", - units="rad", - val=np.zeros(nn), - lhs_name="dgam_dt_approx", - rhs_name="dgam_dt", - eq_units="rad/s", - normalize=False) - - thrust_alpha_bal.add_balance("thrust_req", - units="N", - val=100*np.ones(nn), - lhs_name="dTAS_dt_approx", - rhs_name="dTAS_dt", - eq_units="m/s**2", - normalize=False) - - self.add_subsystem("thrust_alpha_bal", subsys=thrust_alpha_bal, - promotes_inputs=["*"], - promotes_outputs=["*"]) - - self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True, - atol=1.0e-10, - rtol=1.0e-10) + thrust_alpha_bal.add_balance( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + units='rad', + val=np.zeros(nn), + lhs_name='dgam_dt_approx', + rhs_name='dgam_dt', + eq_units='rad/s', + normalize=False, + ) + + thrust_alpha_bal.add_balance( + 'thrust_req', + units='N', + val=100 * np.ones(nn), + lhs_name='dTAS_dt_approx', + rhs_name='dTAS_dt', + eq_units='m/s**2', + normalize=False, + ) + + self.add_subsystem( + 'thrust_alpha_bal', + subsys=thrust_alpha_bal, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True, atol=1.0e-10, rtol=1.0e-10) # self.nonlinear_solver.linesearch = om.ArmijoGoldsteinLS() self.linear_solver = om.DirectSolver(assemble_jac=True) # Set common default values for promoted inputs onn = np.ones(nn) self.set_input_defaults( - name=Dynamic.Mission.DENSITY, + name=Dynamic.Atmosphere.DENSITY, val=RHO_SEA_LEVEL_ENGLISH * onn, - units="slug/ft**3", + units='slug/ft**3', ) self.set_input_defaults( - name=Dynamic.Mission.SPEED_OF_SOUND, - val=1116.4 * onn, - units="ft/s") - if not self.options['ground_roll']: - self.set_input_defaults(name=Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=0.0 * onn, units="rad") - self.set_input_defaults( - name=Dynamic.Mission.VELOCITY, val=250.0 * onn, units="kn" + name=Dynamic.Atmosphere.SPEED_OF_SOUND, val=1116.4 * onn, units='ft/s' ) + if not self.options['ground_roll']: + self.set_input_defaults( + name=Dynamic.Mission.FLIGHT_PATH_ANGLE, val=0.0 * onn, units='rad' + ) + self.set_input_defaults(name=Dynamic.Mission.VELOCITY, val=250.0 * onn, units='kn') diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py index 257e12db51..466b014ac4 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_eom.py @@ -2,7 +2,7 @@ import openmdao.api as om from openmdao.utils.units import convert_units -from aviary.constants import GRAV_METRIC_GASP, GRAV_ENGLISH_LBM, MU_TAKEOFF +from aviary.constants import GRAV_ENGLISH_LBM, GRAV_METRIC_GASP, MU_TAKEOFF from aviary.variable_info.functions import add_aviary_input from aviary.variable_info.variables import Aircraft, Dynamic @@ -21,165 +21,230 @@ def __init__(self, **kwargs): super().__init__(**kwargs) def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare("ground_roll", types=bool, default=False, - desc="True if the aircraft is confined to the ground. " - "Removes altitude rate as an output and adjust " - "the TAS rate equation.") + self.options.declare('num_nodes', types=int) + self.options.declare( + 'ground_roll', + types=bool, + default=False, + desc='True if the aircraft is confined to the ground. ' + 'Removes altitude rate as an output and adjust ' + 'the TAS rate equation.', + ) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # Inputs - self.add_input( - Dynamic.Mission.VELOCITY, shape=nn, desc="true air speed", units="m/s" - ) + self.add_input(Dynamic.Mission.VELOCITY, shape=nn, desc='true air speed', units='m/s') # TODO: This should probably be declared in Newtons, but the weight variable # is really a mass. This should be resolved with an adapter component that # uses gravity. - self.add_input("mass", shape=nn, desc="aircraft mass", units="lbm") - self.add_input(Dynamic.Mission.THRUST_TOTAL, shape=nn, - desc=Dynamic.Mission.THRUST_TOTAL, units="N") - self.add_input(Dynamic.Mission.LIFT, shape=nn, - desc=Dynamic.Mission.LIFT, units="N") - self.add_input(Dynamic.Mission.DRAG, shape=nn, - desc=Dynamic.Mission.DRAG, units="N") - add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0, units="rad") - self.add_input("alpha", val=np.zeros( - nn), desc="angle of attack", units="rad") - - if not self.options["ground_roll"]: - self.add_input(Dynamic.Mission.FLIGHT_PATH_ANGLE, val=np.zeros( - nn), desc="flight path angle", units="rad") - self.add_input("dh_dr", val=np.zeros( - nn), desc="d(alt)/d(range)", units="m/distance_units") - self.add_input("d2h_dr2", val=np.zeros( - nn), desc="d(climb_rate)/d(range)", units="1/distance_units") + self.add_input('mass', shape=nn, desc='aircraft mass', units='lbm') + self.add_input( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + shape=nn, + desc=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='N', + ) + self.add_input(Dynamic.Vehicle.LIFT, shape=nn, desc=Dynamic.Vehicle.LIFT, units='N') + self.add_input(Dynamic.Vehicle.DRAG, shape=nn, desc=Dynamic.Vehicle.DRAG, units='N') + add_aviary_input(self, Aircraft.Wing.INCIDENCE, val=0, units='rad') + self.add_input( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=np.zeros(nn), + desc='angle of attack', + units='rad', + ) + + if not self.options['ground_roll']: + self.add_input( + Dynamic.Mission.FLIGHT_PATH_ANGLE, + val=np.zeros(nn), + desc='flight path angle', + units='rad', + ) + self.add_input( + 'dh_dr', val=np.zeros(nn), desc='d(alt)/d(range)', units='m/distance_units' + ) + self.add_input( + 'd2h_dr2', val=np.zeros(nn), desc='d(climb_rate)/d(range)', units='1/distance_units' + ) # Outputs - self.add_output("dt_dr", shape=nn, units="s/distance_units", - desc="Seconds passed per each meter of range covered.", - tags=['dymos.state_rate_source:time', 'dymos.state_units:s']) - self.add_output("normal_force", val=np.ones(nn), units="N", - desc="normal forces") - self.add_output("fuselage_pitch", val=np.ones(nn), units="rad", - desc="fuselage pitch angle") - self.add_output("load_factor", val=np.ones(nn), units="unitless", - desc="load factor") - self.add_output("dTAS_dt", shape=nn, units="m/s**2", - desc="rate of change of true airspeed") - - if not self.options["ground_roll"]: - self.add_output("dgam_dt", shape=nn, units="rad/s", - desc="rate of change of flight path angle", ) - self.add_output("dgam_dt_approx", shape=nn, units="rad/s", - desc="approximate rate of change of flight path angle " - "based on dh_dr and d2h_dr2") + self.add_output( + 'dt_dr', + shape=nn, + units='s/distance_units', + desc='Seconds passed per each meter of range covered.', + tags=['dymos.state_rate_source:time', 'dymos.state_units:s'], + ) + self.add_output('normal_force', val=np.ones(nn), units='N', desc='normal forces') + self.add_output('fuselage_pitch', val=np.ones(nn), units='rad', desc='fuselage pitch angle') + self.add_output('load_factor', val=np.ones(nn), units='unitless', desc='load factor') + self.add_output('dTAS_dt', shape=nn, units='m/s**2', desc='rate of change of true airspeed') + + if not self.options['ground_roll']: + self.add_output( + 'dgam_dt', + shape=nn, + units='rad/s', + desc='rate of change of flight path angle', + ) + self.add_output( + 'dgam_dt_approx', + shape=nn, + units='rad/s', + desc='approximate rate of change of flight path angle based on dh_dr and d2h_dr2', + ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] ar = np.arange(nn, dtype=int) - ground_roll = self.options["ground_roll"] + ground_roll = self.options['ground_roll'] + + self.declare_partials(of='dt_dr', wrt=Dynamic.Mission.VELOCITY, rows=ar, cols=ar) self.declare_partials( - of="dt_dr", wrt=Dynamic.Mission.VELOCITY, rows=ar, cols=ar + of=['normal_force', 'dTAS_dt'], + wrt=[ + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + 'mass', + Dynamic.Vehicle.LIFT, + ], + rows=ar, + cols=ar, ) - self.declare_partials(of=["normal_force", "dTAS_dt"], - wrt=[Dynamic.Mission.THRUST_TOTAL, Dynamic.Mission.DRAG, - "mass", Dynamic.Mission.LIFT], - rows=ar, cols=ar) - - self.declare_partials(of="normal_force", wrt="mass", - rows=ar, cols=ar, val=LBF_TO_N * GRAV_ENGLISH_LBM) + self.declare_partials( + of='normal_force', wrt='mass', rows=ar, cols=ar, val=LBF_TO_N * GRAV_ENGLISH_LBM + ) - self.declare_partials(of="normal_force", wrt=Dynamic.Mission.LIFT, - rows=ar, cols=ar, val=-1.0) + self.declare_partials( + of='normal_force', wrt=Dynamic.Vehicle.LIFT, rows=ar, cols=ar, val=-1.0 + ) - self.declare_partials(of="load_factor", wrt=[Dynamic.Mission.LIFT, "mass", Dynamic.Mission.THRUST_TOTAL], - rows=ar, cols=ar) + self.declare_partials( + of='load_factor', + wrt=[Dynamic.Vehicle.LIFT, 'mass', Dynamic.Vehicle.Propulsion.THRUST_TOTAL], + rows=ar, + cols=ar, + ) - self.declare_partials(of=["dTAS_dt", "normal_force", "load_factor"], - wrt=[Aircraft.Wing.INCIDENCE]) + self.declare_partials( + of=['dTAS_dt', 'normal_force', 'load_factor'], wrt=[Aircraft.Wing.INCIDENCE] + ) - self.declare_partials(of=["normal_force", "dTAS_dt"], - wrt=["alpha"], - rows=ar, cols=ar) + self.declare_partials( + of=['normal_force', 'dTAS_dt'], + wrt=[Dynamic.Vehicle.ANGLE_OF_ATTACK], + rows=ar, + cols=ar, + ) - self.declare_partials(of="fuselage_pitch", - wrt=["alpha"], - rows=ar, cols=ar, val=1.0) + self.declare_partials( + of='fuselage_pitch', + wrt=[Dynamic.Vehicle.ANGLE_OF_ATTACK], + rows=ar, + cols=ar, + val=1.0, + ) - self.declare_partials(of="fuselage_pitch", - wrt=Aircraft.Wing.INCIDENCE, - val=-1.0) + self.declare_partials(of='fuselage_pitch', wrt=Aircraft.Wing.INCIDENCE, val=-1.0) - self.declare_partials(of="load_factor", wrt=["alpha"], - rows=ar, cols=ar) + self.declare_partials( + of='load_factor', wrt=[Dynamic.Vehicle.ANGLE_OF_ATTACK], rows=ar, cols=ar + ) if not ground_roll: - self.declare_partials(of="dt_dr", wrt=Dynamic.Mission.FLIGHT_PATH_ANGLE, - rows=ar, cols=ar) - - self.declare_partials(of=["dgam_dt", "dgam_dt_approx"], - wrt=[Dynamic.Mission.LIFT, "mass", Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG, "alpha", Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=ar, cols=ar) + self.declare_partials( + of='dt_dr', wrt=Dynamic.Mission.FLIGHT_PATH_ANGLE, rows=ar, cols=ar + ) - self.declare_partials(of=["normal_force", "dTAS_dt"], - wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=ar, cols=ar) + self.declare_partials( + of=['dgam_dt', 'dgam_dt_approx'], + wrt=[ + Dynamic.Vehicle.LIFT, + 'mass', + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ], + rows=ar, + cols=ar, + ) self.declare_partials( - of=["dgam_dt"], wrt=[Dynamic.Mission.VELOCITY], rows=ar, cols=ar + of=['normal_force', 'dTAS_dt'], + wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=ar, + cols=ar, ) - self.declare_partials(of="load_factor", wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=ar, cols=ar) + self.declare_partials(of=['dgam_dt'], wrt=[Dynamic.Mission.VELOCITY], rows=ar, cols=ar) - self.declare_partials(of=["dgam_dt", "dgam_dt_approx"], - wrt=[Dynamic.Mission.LIFT, "mass", - Dynamic.Mission.THRUST_TOTAL, "alpha", Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=ar, cols=ar) + self.declare_partials( + of='load_factor', + wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=ar, + cols=ar, + ) + + self.declare_partials( + of=['dgam_dt', 'dgam_dt_approx'], + wrt=[ + Dynamic.Vehicle.LIFT, + 'mass', + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + ], + rows=ar, + cols=ar, + ) - self.declare_partials(of="fuselage_pitch", - wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=ar, cols=ar, val=1.0) + self.declare_partials( + of='fuselage_pitch', + wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=ar, + cols=ar, + val=1.0, + ) self.declare_partials( - of=["dgam_dt_approx"], - wrt=["dh_dr", "d2h_dr2", Dynamic.Mission.VELOCITY], + of=['dgam_dt_approx'], + wrt=['dh_dr', 'd2h_dr2', Dynamic.Mission.VELOCITY], rows=ar, cols=ar, ) - self.declare_partials(of=["dgam_dt_approx", "dgam_dt"], - wrt=[Aircraft.Wing.INCIDENCE]) + self.declare_partials(of=['dgam_dt_approx', 'dgam_dt'], wrt=[Aircraft.Wing.INCIDENCE]) def compute(self, inputs, outputs): tas = inputs[Dynamic.Mission.VELOCITY] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] # convert to newtons # TODO: change this to use the units conversion - weight = inputs["mass"] * GRAV_ENGLISH_LBM * LBF_TO_N - drag = inputs[Dynamic.Mission.DRAG] - lift = inputs[Dynamic.Mission.LIFT] - alpha = inputs["alpha"] + weight = inputs['mass'] * GRAV_ENGLISH_LBM * LBF_TO_N + drag = inputs[Dynamic.Vehicle.DRAG] + lift = inputs[Dynamic.Vehicle.LIFT] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] i_wing = inputs[Aircraft.Wing.INCIDENCE] g = GRAV_METRIC_GASP m = weight / g - if self.options["ground_roll"]: + if self.options['ground_roll']: mu = MU_TAKEOFF gamma = 0.0 else: mu = 0.0 gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] - dh_dr = inputs["dh_dr"] - d2h_dr2 = inputs["d2h_dr2"] + dh_dr = inputs['dh_dr'] + d2h_dr2 = inputs['d2h_dr2'] alpha_i = alpha - i_wing @@ -198,42 +263,41 @@ def compute(self, inputs, outputs): load_factor = (lift + tsai) / (weight * cgam) - outputs["dt_dr"] = 1.0 / dr_dt + outputs['dt_dr'] = 1.0 / dr_dt - outputs["normal_force"] = normal_force + outputs['normal_force'] = normal_force - outputs["dTAS_dt"] = (tcai - drag - weight * - sgam - mu * normal_force) / m + outputs['dTAS_dt'] = (tcai - drag - weight * sgam - mu * normal_force) / m - outputs["fuselage_pitch"] = gamma - i_wing + alpha + outputs['fuselage_pitch'] = gamma - i_wing + alpha - outputs["load_factor"] = load_factor + outputs['load_factor'] = load_factor - if not self.options["ground_roll"]: - outputs["dgam_dt"] = (tsai + lift - weight * cgam) / (m * tas) - dgam_dr = d2h_dr2 / (dh_dr ** 2 + 1) - outputs["dgam_dt_approx"] = dgam_dr * dr_dt + if not self.options['ground_roll']: + outputs['dgam_dt'] = (tsai + lift - weight * cgam) / (m * tas) + dgam_dr = d2h_dr2 / (dh_dr**2 + 1) + outputs['dgam_dt_approx'] = dgam_dr * dr_dt def compute_partials(self, inputs, partials): - ground_roll = self.options["ground_roll"] + ground_roll = self.options['ground_roll'] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] # convert to newtons # TODO: change this to use the units conversion - weight = inputs["mass"] * GRAV_ENGLISH_LBM * LBF_TO_N - drag = inputs[Dynamic.Mission.DRAG] - lift = inputs[Dynamic.Mission.LIFT] + weight = inputs['mass'] * GRAV_ENGLISH_LBM * LBF_TO_N + drag = inputs[Dynamic.Vehicle.DRAG] + lift = inputs[Dynamic.Vehicle.LIFT] tas = inputs[Dynamic.Mission.VELOCITY] i_wing = inputs[Aircraft.Wing.INCIDENCE] - alpha = inputs["alpha"] + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] - if self.options["ground_roll"]: + if self.options['ground_roll']: mu = MU_TAKEOFF gamma = 0.0 else: mu = 0.0 gamma = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] - dh_dr = inputs["dh_dr"] - d2h_dr2 = inputs["d2h_dr2"] + dh_dr = inputs['dh_dr'] + d2h_dr2 = inputs['d2h_dr2'] alpha_i = alpha - i_wing @@ -259,59 +323,63 @@ def compute_partials(self, inputs, partials): _f = tcai - drag - weight * sgam - mu * (weight - lift - tsai) - partials["dt_dr", Dynamic.Mission.VELOCITY] = -cgam / dr_dt**2 + partials['dt_dr', Dynamic.Mission.VELOCITY] = -cgam / dr_dt**2 - partials["dTAS_dt", Dynamic.Mission.THRUST_TOTAL] = calpha_i / \ - m + salpha_i / m * mu - partials["dTAS_dt", Dynamic.Mission.DRAG] = -1. / m + partials['dTAS_dt', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = ( + calpha_i / m + salpha_i / m * mu + ) + partials['dTAS_dt', Dynamic.Vehicle.DRAG] = -1.0 / m - partials["dTAS_dt", "mass"] = \ - GRAV_ENGLISH_LBM * (LBF_TO_N * (-sgam - mu) / m - _f / (weight/LBF_TO_N * m)) + partials['dTAS_dt', 'mass'] = GRAV_ENGLISH_LBM * ( + LBF_TO_N * (-sgam - mu) / m - _f / (weight / LBF_TO_N * m) + ) - partials["dTAS_dt", Dynamic.Mission.LIFT] = mu / m - partials["dTAS_dt", "alpha"] = -tsai / m + mu * tcai / m - partials["dTAS_dt", Aircraft.Wing.INCIDENCE] = tsai / m - mu * tcai / m + partials['dTAS_dt', Dynamic.Vehicle.LIFT] = mu / m + partials['dTAS_dt', Dynamic.Vehicle.ANGLE_OF_ATTACK] = -tsai / m + mu * tcai / m + partials['dTAS_dt', Aircraft.Wing.INCIDENCE] = tsai / m - mu * tcai / m - partials["normal_force", Dynamic.Mission.THRUST_TOTAL] = -salpha_i + partials['normal_force', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = -salpha_i - partials["load_factor", Dynamic.Mission.LIFT] = 1 / (weight * cgam) - partials["load_factor", Dynamic.Mission.THRUST_TOTAL] = salpha_i / \ - (weight * cgam) - partials["load_factor", "mass"] = \ - - (lift + tsai) / (weight**2/LBF_TO_N * cgam) * GRAV_ENGLISH_LBM + partials['load_factor', Dynamic.Vehicle.LIFT] = 1 / (weight * cgam) + partials['load_factor', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = salpha_i / ( + weight * cgam + ) + partials['load_factor', 'mass'] = ( + -(lift + tsai) / (weight**2 / LBF_TO_N * cgam) * GRAV_ENGLISH_LBM + ) - partials["normal_force", "alpha"] = -tcai - partials["normal_force", Aircraft.Wing.INCIDENCE] = tcai - partials["load_factor", Aircraft.Wing.INCIDENCE] = -tcai / (weight * cgam) + partials['normal_force', Dynamic.Vehicle.ANGLE_OF_ATTACK] = -tcai + partials['normal_force', Aircraft.Wing.INCIDENCE] = tcai + partials['load_factor', Aircraft.Wing.INCIDENCE] = -tcai / (weight * cgam) - partials["load_factor", "alpha"] = tcai / (weight * cgam) + partials['load_factor', Dynamic.Vehicle.ANGLE_OF_ATTACK] = tcai / (weight * cgam) if not ground_roll: - partials["dt_dr", Dynamic.Mission.FLIGHT_PATH_ANGLE] = -drdot_dgam / dr_dt**2 - - partials["dTAS_dt", Dynamic.Mission.FLIGHT_PATH_ANGLE] = -weight * cgam / m - - partials["dgam_dt", Dynamic.Mission.THRUST_TOTAL] = salpha_i / mtas - partials["dgam_dt", Dynamic.Mission.LIFT] = 1. / mtas - partials["dgam_dt", "mass"] = \ - GRAV_ENGLISH_LBM * (LBF_TO_N*cgam / (mtas) - (tsai + - lift + weight*cgam)/(weight**2 / LBF_TO_N/g * tas)) - partials["dgam_dt", Dynamic.Mission.FLIGHT_PATH_ANGLE] = m * \ - tas * weight * sgam / mtas2 - partials["dgam_dt", "alpha"] = m * tas * tcai / mtas2 - partials["dgam_dt", Dynamic.Mission.VELOCITY] = ( + partials['dt_dr', Dynamic.Mission.FLIGHT_PATH_ANGLE] = -drdot_dgam / dr_dt**2 + + partials['dTAS_dt', Dynamic.Mission.FLIGHT_PATH_ANGLE] = -weight * cgam / m + + partials['dgam_dt', Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = salpha_i / mtas + partials['dgam_dt', Dynamic.Vehicle.LIFT] = 1.0 / mtas + partials['dgam_dt', 'mass'] = GRAV_ENGLISH_LBM * ( + LBF_TO_N * cgam / (mtas) + - (tsai + lift + weight * cgam) / (weight**2 / LBF_TO_N / g * tas) + ) + partials['dgam_dt', Dynamic.Mission.FLIGHT_PATH_ANGLE] = m * tas * weight * sgam / mtas2 + partials['dgam_dt', Dynamic.Vehicle.ANGLE_OF_ATTACK] = m * tas * tcai / mtas2 + partials['dgam_dt', Dynamic.Mission.VELOCITY] = ( -m * (tsai + lift - weight * cgam) / mtas2 ) - partials["dgam_dt", Aircraft.Wing.INCIDENCE] = -m * tas * tcai / mtas2 - - dgam_dr = d2h_dr2 / (dh_dr ** 2 + 1) - ddgam_dr_ddh_dr = -2 * dh_dr * d2h_dr2 / (dh_dr**2 + 1)**2 - ddgam_dr_dd2h_dr2 = 1. / (dh_dr ** 2 + 1) - - partials["dgam_dt_approx", "dh_dr"] = dr_dt * ddgam_dr_ddh_dr - partials["dgam_dt_approx", "d2h_dr2"] = dr_dt * ddgam_dr_dd2h_dr2 - partials["dgam_dt_approx", Dynamic.Mission.VELOCITY] = dgam_dr * drdot_dtas - partials["dgam_dt_approx", - Dynamic.Mission.FLIGHT_PATH_ANGLE] = dgam_dr * drdot_dgam - partials["load_factor", Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( - lift + tsai) / (weight * cgam**2) * sgam + partials['dgam_dt', Aircraft.Wing.INCIDENCE] = -m * tas * tcai / mtas2 + + dgam_dr = d2h_dr2 / (dh_dr**2 + 1) + ddgam_dr_ddh_dr = -2 * dh_dr * d2h_dr2 / (dh_dr**2 + 1) ** 2 + ddgam_dr_dd2h_dr2 = 1.0 / (dh_dr**2 + 1) + + partials['dgam_dt_approx', 'dh_dr'] = dr_dt * ddgam_dr_ddh_dr + partials['dgam_dt_approx', 'd2h_dr2'] = dr_dt * ddgam_dr_dd2h_dr2 + partials['dgam_dt_approx', Dynamic.Mission.VELOCITY] = dgam_dr * drdot_dtas + partials['dgam_dt_approx', Dynamic.Mission.FLIGHT_PATH_ANGLE] = dgam_dr * drdot_dgam + partials['load_factor', Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + (lift + tsai) / (weight * cgam**2) * sgam + ) diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py index 08c1868baf..f091272236 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_flight_conditions.py @@ -11,7 +11,7 @@ class UnsteadySolvedFlightConditions(om.ExplicitComponent): Cross-compute TAS, EAS, and Mach regardless of the input speed type. Inputs: - Dynamic.Mission.DENSITY : local atmospheric density + Dynamic.Atmosphere.DENSITY : local atmospheric density Dynamic.Mission.SPEED_OF_SOUND : local speed of sound Additional inputs if ground_roll = False: @@ -26,236 +26,248 @@ class UnsteadySolvedFlightConditions(om.ExplicitComponent): dEAS_dr : approximate rate of change of equivalent airspeed per unit range Additional inputs when input_speed_type = SpeedType.MACH: - Dynamic.Mission.MACH : Mach number + Dynamic.Atmosphere.MACH : Mach number dmach_dr : approximate rate of change of Mach number per unit range Outputs always provided: - Dynamic.Mission.DYNAMIC_PRESSURE : dynamic pressure + Dynamic.Atmosphere.DYNAMIC_PRESSURE : dynamic pressure dTAS_dt_approx : approximate time derivative of TAS based on control rates. Additional outputs when input_speed_type = SpeedType.TAS EAS : equivalent airspeed - Dynamic.Mission.MACH : Mach number + Dynamic.Atmosphere.MACH : Mach number Outputs provided when input_speed_type = SpeedType.EAS: TAS : true airspeed - Dynamic.Mission.MACH : Mach number + Dynamic.Atmosphere.MACH : Mach number """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) self.options.declare( - "input_speed_type", + 'input_speed_type', default=SpeedType.TAS, types=SpeedType, - desc="tells whether the input airspeed is equivalent airspeed, true airspeed, or mach number", + desc='tells whether the input airspeed is equivalent airspeed, true airspeed, or Mach number', + ) + self.options.declare( + 'ground_roll', + types=bool, + default=False, + desc='True if the aircraft is confined to the ground. ' + 'Removes altitude rate as an output and adjust ' + 'the TAS rate equation.', ) - self.options.declare("ground_roll", types=bool, default=False, - desc="True if the aircraft is confined to the ground. " - "Removes altitude rate as an output and adjust " - "the TAS rate equation.") def setup(self): - nn = self.options["num_nodes"] - in_type = self.options["input_speed_type"] - ground_roll = self.options["ground_roll"] - ar = np.arange(self.options["num_nodes"]) + nn = self.options['num_nodes'] + in_type = self.options['input_speed_type'] + ground_roll = self.options['ground_roll'] + ar = np.arange(self.options['num_nodes']) self.add_input( - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=np.zeros(nn), - units="kg/m**3", - desc="density of air", + units='kg/m**3', + desc='density of air', ) self.add_input( - Dynamic.Mission.SPEED_OF_SOUND, + Dynamic.Atmosphere.SPEED_OF_SOUND, val=np.zeros(nn), - units="m/s", - desc="speed of sound", + units='m/s', + desc='speed of sound', ) self.add_output( - Dynamic.Mission.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, val=np.zeros(nn), - units="N/m**2", - desc="dynamic pressure", + units='N/m**2', + desc='dynamic pressure', ) self.add_output( - "dTAS_dt_approx", + 'dTAS_dt_approx', val=np.zeros(nn), - units="m/s**2", - desc="approximated rate of change of true airspeed", + units='m/s**2', + desc='approximated rate of change of true airspeed', ) if not ground_roll: self.add_input( Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=nn, - units="rad", - desc="flight path angle", + units='rad', + desc='flight path angle', ) if in_type is SpeedType.TAS: self.add_input( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="m/s", - desc="true air speed", + units='m/s', + desc='true air speed', ) self.add_input( - "dTAS_dr", + 'dTAS_dr', val=np.zeros(nn), - units="m/s/distance_units", - desc="change in true air speed per unit range", + units='m/s/distance_units', + desc='change in true air speed per unit range', ) self.add_output( - "EAS", + 'EAS', val=np.zeros(nn), - units="m/s", - desc="equivalent air speed", + units='m/s', + desc='equivalent air speed', ) self.add_output( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, val=np.zeros(nn), - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) self.declare_partials( - of=Dynamic.Mission.DYNAMIC_PRESSURE, - wrt=[Dynamic.Mission.DENSITY, Dynamic.Mission.VELOCITY], + of=Dynamic.Atmosphere.DYNAMIC_PRESSURE, + wrt=[Dynamic.Atmosphere.DENSITY, Dynamic.Mission.VELOCITY], rows=ar, cols=ar, ) self.declare_partials( - of=Dynamic.Mission.MACH, - wrt=[Dynamic.Mission.SPEED_OF_SOUND, Dynamic.Mission.VELOCITY], + of=Dynamic.Atmosphere.MACH, + wrt=[Dynamic.Atmosphere.SPEED_OF_SOUND, Dynamic.Mission.VELOCITY], rows=ar, cols=ar, ) self.declare_partials( - of="EAS", - wrt=[Dynamic.Mission.VELOCITY, Dynamic.Mission.DENSITY], + of='EAS', + wrt=[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.DENSITY], rows=ar, cols=ar, ) - self.declare_partials(of="dTAS_dt_approx", - wrt=["dTAS_dr"], - rows=ar, cols=ar) + self.declare_partials(of='dTAS_dt_approx', wrt=['dTAS_dr'], rows=ar, cols=ar) self.declare_partials( - of="dTAS_dt_approx", wrt=[Dynamic.Mission.VELOCITY], rows=ar, cols=ar + of='dTAS_dt_approx', wrt=[Dynamic.Mission.VELOCITY], rows=ar, cols=ar ) if not ground_roll: - self.declare_partials(of="dTAS_dt_approx", - wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=ar, cols=ar) + self.declare_partials( + of='dTAS_dt_approx', + wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=ar, + cols=ar, + ) elif in_type is SpeedType.EAS: self.add_input( - "EAS", + 'EAS', val=np.zeros(nn), - units="m/s", - desc="equivalent air speed", + units='m/s', + desc='equivalent air speed', ) self.add_input( - "dEAS_dr", + 'dEAS_dr', val=np.zeros(nn), - units="1/s", - desc="change in equivalent air speed per unit range", + units='1/s', + desc='change in equivalent air speed per unit range', ) self.add_input( - "drho_dh", + 'drho_dh', val=np.zeros(nn), - units="kg/m**4", - desc="change in air density per unit altitude", + units='kg/m**4', + desc='change in air density per unit altitude', ) self.add_output( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="m/s", - desc="true air speed", + units='m/s', + desc='true air speed', ) self.add_output( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, val=np.zeros(nn), - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) self.declare_partials( - of=Dynamic.Mission.DYNAMIC_PRESSURE, - wrt=[Dynamic.Mission.DENSITY, "EAS"], + of=Dynamic.Atmosphere.DYNAMIC_PRESSURE, + wrt=[Dynamic.Atmosphere.DENSITY, 'EAS'], rows=ar, cols=ar, ) self.declare_partials( - of=Dynamic.Mission.MACH, - wrt=[Dynamic.Mission.SPEED_OF_SOUND, "EAS", Dynamic.Mission.DENSITY], + of=Dynamic.Atmosphere.MACH, + wrt=[ + Dynamic.Atmosphere.SPEED_OF_SOUND, + 'EAS', + Dynamic.Atmosphere.DENSITY, + ], rows=ar, cols=ar, ) self.declare_partials( of=Dynamic.Mission.VELOCITY, - wrt=[Dynamic.Mission.DENSITY, "EAS"], + wrt=[Dynamic.Atmosphere.DENSITY, 'EAS'], rows=ar, cols=ar, ) self.declare_partials( - of="dTAS_dt_approx", - wrt=["drho_dh", Dynamic.Mission.DENSITY, "EAS", "dEAS_dr"], + of='dTAS_dt_approx', + wrt=['drho_dh', Dynamic.Atmosphere.DENSITY, 'EAS', 'dEAS_dr'], rows=ar, cols=ar, ) if not ground_roll: - self.declare_partials(of="dTAS_dt_approx", - wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], - rows=ar, cols=ar) + self.declare_partials( + of='dTAS_dt_approx', + wrt=[Dynamic.Mission.FLIGHT_PATH_ANGLE], + rows=ar, + cols=ar, + ) else: self.add_input( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, val=np.zeros(nn), - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) self.add_input( - "dmach_dr", + 'dmach_dr', val=np.zeros(nn), - units="unitless/distance_units", - desc="change in mach number per unit range", + units='1/distance_units', + desc='change in Mach number per unit range', ) self.add_input( - "dsos_dh", + 'dsos_dh', val=np.zeros(nn), - units="m/s/m", - desc="change in speed of sound per unit altitude", + units='m/s/m', + desc='change in speed of sound per unit altitude', ) self.add_output( - "EAS", + 'EAS', val=np.zeros(nn), - units="m/s", - desc="equivalent air speed", + units='m/s', + desc='equivalent air speed', ) self.add_output( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="m/s", - desc="true air speed", + units='m/s', + desc='true air speed', ) self.declare_partials( - of=Dynamic.Mission.DYNAMIC_PRESSURE, + of=Dynamic.Atmosphere.DYNAMIC_PRESSURE, wrt=[ - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.MACH, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.DENSITY, ], rows=ar, cols=ar, @@ -263,77 +275,78 @@ def setup(self): self.declare_partials( of=Dynamic.Mission.VELOCITY, - wrt=[Dynamic.Mission.SPEED_OF_SOUND, Dynamic.Mission.MACH], + wrt=[Dynamic.Atmosphere.SPEED_OF_SOUND, Dynamic.Atmosphere.MACH], rows=ar, cols=ar, ) self.declare_partials( - of="EAS", + of='EAS', wrt=[ - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.MACH, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.DENSITY, ], rows=ar, cols=ar, ) - self.declare_partials(of="dTAS_dt_approx", - wrt=["dmach_dr", "dsos_dh"], - rows=ar, cols=ar) + self.declare_partials( + of='dTAS_dt_approx', wrt=['dmach_dr', 'dsos_dh'], rows=ar, cols=ar + ) def compute(self, inputs, outputs): - in_type = self.options["input_speed_type"] - ground_roll = self.options["ground_roll"] + in_type = self.options['input_speed_type'] + ground_roll = self.options['ground_roll'] - rho = inputs[Dynamic.Mission.DENSITY] + rho = inputs[Dynamic.Atmosphere.DENSITY] rho_sl = constants.RHO_SEA_LEVEL_METRIC sqrt_rho_rho_sl = np.sqrt(rho / rho_sl) - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] cgam = 1.0 if ground_roll else np.cos(inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE]) sgam = 0.0 if ground_roll else np.sin(inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE]) if in_type is SpeedType.TAS: tas = inputs[Dynamic.Mission.VELOCITY] - dtas_dr = inputs["dTAS_dr"] - outputs[Dynamic.Mission.MACH] = tas / sos - outputs["EAS"] = tas * sqrt_rho_rho_sl - outputs["dTAS_dt_approx"] = dtas_dr * tas * cgam + dtas_dr = inputs['dTAS_dr'] + outputs[Dynamic.Atmosphere.MACH] = tas / sos + outputs['EAS'] = tas * sqrt_rho_rho_sl + outputs['dTAS_dt_approx'] = dtas_dr * tas * cgam elif in_type is SpeedType.EAS: - eas = inputs["EAS"] - drho_dh = inputs["drho_dh"] - deas_dr = inputs["dEAS_dr"] + eas = inputs['EAS'] + drho_dh = inputs['drho_dh'] + deas_dr = inputs['dEAS_dr'] outputs[Dynamic.Mission.VELOCITY] = tas = eas / sqrt_rho_rho_sl - outputs[Dynamic.Mission.MACH] = tas / sos + outputs[Dynamic.Atmosphere.MACH] = tas / sos drho_dt_approx = drho_dh * tas * sgam deas_dt_approx = deas_dr * tas * cgam - outputs["dTAS_dt_approx"] = deas_dt_approx * (rho_sl / rho)**1.5 \ + outputs['dTAS_dt_approx'] = ( + deas_dt_approx * (rho_sl / rho) ** 1.5 - 0.5 * eas * drho_dt_approx * rho_sl**1.5 / rho_sl**2.5 + ) else: - mach = inputs[Dynamic.Mission.MACH] - dmach_dr = inputs["dmach_dr"] + mach = inputs[Dynamic.Atmosphere.MACH] + dmach_dr = inputs['dmach_dr'] outputs[Dynamic.Mission.VELOCITY] = tas = sos * mach - outputs["EAS"] = tas * sqrt_rho_rho_sl + outputs['EAS'] = tas * sqrt_rho_rho_sl dmach_dt_approx = dmach_dr * tas * cgam - dsos_dt_approx = inputs["dsos_dh"] * tas * sgam - outputs["dTAS_dt_approx"] = dmach_dt_approx * sos \ - + dsos_dt_approx * tas / sos + dsos_dt_approx = inputs['dsos_dh'] * tas * sgam + outputs['dTAS_dt_approx'] = dmach_dt_approx * sos + dsos_dt_approx * tas / sos - outputs[Dynamic.Mission.DYNAMIC_PRESSURE] = 0.5 * rho * tas**2 + outputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] = 0.5 * rho * tas**2 def compute_partials(self, inputs, partials): - in_type = self.options["input_speed_type"] - ground_roll = self.options["ground_roll"] + in_type = self.options['input_speed_type'] + ground_roll = self.options['ground_roll'] - rho = inputs[Dynamic.Mission.DENSITY] + rho = inputs[Dynamic.Atmosphere.DENSITY] rho_sl = constants.RHO_SEA_LEVEL_METRIC sqrt_rho_rho_sl = np.sqrt(rho / rho_sl) dsqrt_rho_rho_sl_drho = 0.5 / sqrt_rho_rho_sl / rho_sl - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] cgam = 1.0 if ground_roll else np.cos(inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE]) sgam = 0.0 if ground_roll else np.sin(inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE]) @@ -342,63 +355,61 @@ def compute_partials(self, inputs, partials): TAS = inputs[Dynamic.Mission.VELOCITY] # Why is there tas and TAS? tas = inputs[Dynamic.Mission.VELOCITY] - dTAS_dr = inputs["dTAS_dr"] + dTAS_dr = inputs['dTAS_dr'] - partials[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.VELOCITY] = ( - rho * TAS - ) - partials[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.DENSITY] = ( - 0.5 * TAS**2 - ) + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Mission.VELOCITY] = rho * TAS + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.DENSITY] = 0.5 * TAS**2 - partials[Dynamic.Mission.MACH, Dynamic.Mission.VELOCITY] = 1 / sos - partials[Dynamic.Mission.MACH, - Dynamic.Mission.SPEED_OF_SOUND] = -TAS / sos ** 2 + partials[Dynamic.Atmosphere.MACH, Dynamic.Mission.VELOCITY] = 1 / sos + partials[Dynamic.Atmosphere.MACH, Dynamic.Atmosphere.SPEED_OF_SOUND] = -TAS / sos**2 - partials["EAS", Dynamic.Mission.VELOCITY] = sqrt_rho_rho_sl - partials["EAS", Dynamic.Mission.DENSITY] = tas * dsqrt_rho_rho_sl_drho + partials['EAS', Dynamic.Mission.VELOCITY] = sqrt_rho_rho_sl + partials['EAS', Dynamic.Atmosphere.DENSITY] = tas * dsqrt_rho_rho_sl_drho - partials["dTAS_dt_approx", "dTAS_dr"] = tas * cgam - partials["dTAS_dt_approx", Dynamic.Mission.VELOCITY] = dTAS_dr * cgam + partials['dTAS_dt_approx', 'dTAS_dr'] = tas * cgam + partials['dTAS_dt_approx', Dynamic.Mission.VELOCITY] = dTAS_dr * cgam if not ground_roll: - partials["dTAS_dt_approx", - Dynamic.Mission.FLIGHT_PATH_ANGLE] = -dTAS_dr * tas * sgam + partials['dTAS_dt_approx', Dynamic.Mission.FLIGHT_PATH_ANGLE] = ( + -dTAS_dr * tas * sgam + ) elif in_type is SpeedType.EAS: - EAS = inputs["EAS"] + EAS = inputs['EAS'] TAS = EAS / sqrt_rho_rho_sl dTAS_dRho = -0.5 * EAS * rho_sl**0.5 / rho**1.5 dTAS_dEAS = 1 / sqrt_rho_rho_sl - partials[Dynamic.Mission.DYNAMIC_PRESSURE, "EAS"] = EAS * rho_sl - partials[Dynamic.Mission.MACH, "EAS"] = dTAS_dEAS / sos - partials[Dynamic.Mission.MACH, Dynamic.Mission.DENSITY] = dTAS_dRho / sos - partials[Dynamic.Mission.MACH, - Dynamic.Mission.SPEED_OF_SOUND] = -TAS / sos ** 2 - partials[Dynamic.Mission.VELOCITY, Dynamic.Mission.DENSITY] = dTAS_dRho - partials[Dynamic.Mission.VELOCITY, "EAS"] = dTAS_dEAS - partials["dTAS_dt_approx", "dEAS_dr"] = TAS * cgam * (rho_sl / rho)**1.5 - partials['dTAS_dt_approx', 'drho_dh'] = -0.5 * \ - EAS * TAS * sgam * rho_sl**1.5 / rho_sl**2.5 + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'EAS'] = EAS * rho_sl + partials[Dynamic.Atmosphere.MACH, 'EAS'] = dTAS_dEAS / sos + partials[Dynamic.Atmosphere.MACH, Dynamic.Atmosphere.DENSITY] = dTAS_dRho / sos + partials[Dynamic.Atmosphere.MACH, Dynamic.Atmosphere.SPEED_OF_SOUND] = -TAS / sos**2 + partials[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.DENSITY] = dTAS_dRho + partials[Dynamic.Mission.VELOCITY, 'EAS'] = dTAS_dEAS + partials['dTAS_dt_approx', 'dEAS_dr'] = TAS * cgam * (rho_sl / rho) ** 1.5 + partials['dTAS_dt_approx', 'drho_dh'] = ( + -0.5 * EAS * TAS * sgam * rho_sl**1.5 / rho_sl**2.5 + ) else: - mach = inputs[Dynamic.Mission.MACH] + mach = inputs[Dynamic.Atmosphere.MACH] TAS = sos * mach - partials[Dynamic.Mission.DYNAMIC_PRESSURE, - Dynamic.Mission.SPEED_OF_SOUND] = rho * sos * mach ** 2 - partials[Dynamic.Mission.DYNAMIC_PRESSURE, - Dynamic.Mission.MACH] = rho * sos ** 2 * mach - partials[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.DENSITY] = ( + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.SPEED_OF_SOUND] = ( + rho * sos * mach**2 + ) + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.MACH] = ( + rho * sos**2 * mach + ) + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.DENSITY] = ( 0.5 * sos**2 * mach**2 ) - partials[Dynamic.Mission.VELOCITY, Dynamic.Mission.SPEED_OF_SOUND] = mach - partials[Dynamic.Mission.VELOCITY, Dynamic.Mission.MACH] = sos - partials["EAS", Dynamic.Mission.SPEED_OF_SOUND] = mach * sqrt_rho_rho_sl - partials["EAS", Dynamic.Mission.MACH] = sos * sqrt_rho_rho_sl - partials["EAS", Dynamic.Mission.DENSITY] = ( + partials[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.SPEED_OF_SOUND] = mach + partials[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.MACH] = sos + partials['EAS', Dynamic.Atmosphere.SPEED_OF_SOUND] = mach * sqrt_rho_rho_sl + partials['EAS', Dynamic.Atmosphere.MACH] = sos * sqrt_rho_rho_sl + partials['EAS', Dynamic.Atmosphere.DENSITY] = ( TAS * (1 / rho_sl) ** 0.5 * 0.5 * rho ** (-0.5) ) partials['dTAS_dt_approx', 'dmach_dr'] = TAS * cgam * sos diff --git a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py index fcc5c10ced..5f6e00da3a 100644 --- a/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py +++ b/aviary/mission/gasp_based/ode/unsteady_solved/unsteady_solved_ode.py @@ -1,22 +1,23 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.constants import RHO_SEA_LEVEL_ENGLISH as rho_sl -from aviary.mission.gasp_based.ode.base_ode import BaseODE from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.two_dof_ode import TwoDOFODE from aviary.mission.gasp_based.ode.unsteady_solved.gamma_comp import GammaComp -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_flight_conditions import \ - UnsteadySolvedFlightConditions from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_eom import UnsteadySolvedEOM -from aviary.variable_info.enums import SpeedType, LegacyCode -from aviary.variable_info.variables import Dynamic +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_flight_conditions import ( + UnsteadySolvedFlightConditions, +) from aviary.subsystems.aerodynamics.aerodynamics_builder import AerodynamicsBuilderBase +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.subsystems.propulsion.propulsion_builder import PropulsionBuilderBase +from aviary.variable_info.enums import LegacyCode, SpeedType from aviary.variable_info.variable_meta_data import _MetaData +from aviary.variable_info.variables import Dynamic -class UnsteadySolvedODE(BaseODE): +class UnsteadySolvedODE(TwoDOFODE): """ This 2D aircraft ODE provides the rate of change of time per unit range covered. @@ -38,31 +39,31 @@ class UnsteadySolvedODE(BaseODE): def initialize(self): super().initialize() self.options.declare( - "ground_roll", + 'ground_roll', types=bool, default=False, - desc="True if the aircraft is confined to the ground. Removes altitude rate " - "as an output and adjusts the TAS rate equation.", + desc='True if the aircraft is confined to the ground. Removes altitude rate ' + 'as an output and adjusts the TAS rate equation.', ) self.options.declare( - "clean", + 'clean', types=bool, default=False, - desc="If true then no flaps or gear are included. Useful for high-speed " - "flight phases.", + desc='If true then no flaps or gear are included. Useful for high-speed flight phases.', ) self.options.declare( - "include_param_comp", + 'include_param_comp', types=bool, default=True, - desc="If true then add a ParamComp to this ODE. Useful for smaller usages " - "of this ODE not within a full trajectory or a pre-mission group.", + desc='If true then add a ParamComp to this ODE. Useful for smaller usages ' + 'of this ODE not within a full trajectory or a pre-mission group.', ) self.options.declare( - "input_speed_type", + 'input_speed_type', default=SpeedType.TAS, types=SpeedType, - desc="Airspeed type specified as input.") + desc='Airspeed type specified as input.', + ) self.options.declare( 'throttle_enforcement', default='path_constraint', @@ -71,47 +72,53 @@ def initialize(self): 'boundaries or using solver bounds', ) self.options.declare( - 'external_subsystems', default=[], - desc='list of external subsystem builder instances to be added to the ODE') + 'external_subsystems', + default=[], + desc='list of external subsystem builder instances to be added to the ODE', + ) self.options.declare( - 'meta_data', default=_MetaData, - desc='metadata associated with the variables to be passed into the ODE') + 'meta_data', + default=_MetaData, + desc='metadata associated with the variables to be passed into the ODE', + ) def setup(self): - nn = self.options["num_nodes"] - ground_roll = self.options["ground_roll"] - input_speed_type = self.options["input_speed_type"] + nn = self.options['num_nodes'] + ground_roll = self.options['ground_roll'] + input_speed_type = self.options['input_speed_type'] aviary_options = self.options['aviary_options'] subsystem_options = self.options['subsystem_options'] core_subsystems = self.options['core_subsystems'] throttle_enforcement = self.options['throttle_enforcement'] - if self.options["include_param_comp"]: + if self.options['include_param_comp']: # TODO: paramport - self.add_subsystem("params", ParamPort(), promotes=["*"]) + self.add_subsystem('params', ParamPort(), promotes=['*']) self.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=nn, output_dsos_dh=True), promotes_inputs=[Dynamic.Mission.ALTITUDE], promotes_outputs=[ - Dynamic.Mission.DENSITY, - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, - "viscosity", - "drhos_dh", - "dsos_dh", + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + 'viscosity', + 'drhos_dh', + 'dsos_dh', ], ) - self.add_subsystem("flight_path_angle", - GammaComp(num_nodes=nn), - promotes_inputs=["*"], - promotes_outputs=["*"]) + self.add_subsystem( + 'flight_path_angle', + GammaComp(num_nodes=nn), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - "fc", + 'fc', UnsteadySolvedFlightConditions( num_nodes=nn, ground_roll=ground_roll, input_speed_type=input_speed_type ), @@ -119,39 +126,42 @@ def setup(self): promotes_outputs=['*'], ) - control_iter_group = self.add_subsystem("control_iter_group", - subsys=om.Group(), - promotes_inputs=["*"], - promotes_outputs=["*"]) + control_iter_group = self.add_subsystem( + 'control_iter_group', subsys=om.Group(), promotes_inputs=['*'], promotes_outputs=['*'] + ) # Also need to change the run script and the iter group solver when using this; # just testing for now - throttle_balance_group = self.add_subsystem("throttle_balance_group", - om.Group(), - promotes=["*"]) + throttle_balance_group = self.add_subsystem( + 'throttle_balance_group', om.Group(), promotes=['*'] + ) throttle_balance_comp = om.BalanceComp() throttle_balance_comp.add_balance( - Dynamic.Mission.THROTTLE, - units="unitless", + Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', val=np.ones(nn) * 0.5, - lhs_name=Dynamic.Mission.THRUST_TOTAL, - rhs_name="thrust_req", - eq_units="lbf", + lhs_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + rhs_name='thrust_req', + eq_units='lbf', normalize=False, lower=0.0 if throttle_enforcement == 'bounded' else None, upper=1.0 if throttle_enforcement == 'bounded' else None, res_ref=1.0e6, ) - throttle_balance_group.add_subsystem("throttle_balance_comp", subsys=throttle_balance_comp, - promotes_inputs=["*"], - promotes_outputs=["*"]) + throttle_balance_group.add_subsystem( + 'throttle_balance_comp', + subsys=throttle_balance_comp, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - throttle_balance_group.nonlinear_solver = om.NewtonSolver(solve_subsystems=True, - atol=1.0e-10, - rtol=1.0e-10, - ) + throttle_balance_group.nonlinear_solver = om.NewtonSolver( + solve_subsystems=True, + atol=1.0e-10, + rtol=1.0e-10, + ) throttle_balance_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() throttle_balance_group.linear_solver = om.DirectSolver(assemble_jac=True) throttle_balance_group.nonlinear_solver.options['err_on_non_converge'] = True @@ -171,99 +181,118 @@ def setup(self): if system is not None: if isinstance(subsystem, AerodynamicsBuilderBase): mission_inputs = subsystem.mission_inputs(**kwargs) - if subsystem.code_origin is LegacyCode.FLOPS and 'angle_of_attack' in mission_inputs: + if ( + subsystem.code_origin is LegacyCode.FLOPS + and 'angle_of_attack' in mission_inputs + ): mission_inputs.remove('angle_of_attack') - mission_inputs.append(('angle_of_attack', 'alpha')) - control_iter_group.add_subsystem(subsystem.name, - system, - promotes_inputs=mission_inputs, - promotes_outputs=subsystem.mission_outputs(**kwargs)) + mission_inputs.append(('angle_of_attack', Dynamic.Vehicle.ANGLE_OF_ATTACK)) + control_iter_group.add_subsystem( + subsystem.name, + system, + promotes_inputs=mission_inputs, + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) elif isinstance(subsystem, PropulsionBuilderBase): - throttle_balance_group.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + throttle_balance_group.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) else: - self.add_subsystem(subsystem.name, - system, - promotes_inputs=subsystem.mission_inputs( - **kwargs), - promotes_outputs=subsystem.mission_outputs(**kwargs)) + self.add_subsystem( + subsystem.name, + system, + promotes_inputs=subsystem.mission_inputs(**kwargs), + promotes_outputs=subsystem.mission_outputs(**kwargs), + ) + + self.add_external_subsystems() eom_comp = UnsteadySolvedEOM(num_nodes=nn, ground_roll=ground_roll) input_list = [ '*', - (Dynamic.Mission.THRUST_TOTAL, "thrust_req"), + (Dynamic.Vehicle.Propulsion.THRUST_TOTAL, 'thrust_req'), Dynamic.Mission.VELOCITY, ] - control_iter_group.add_subsystem("eom", subsys=eom_comp, - promotes_inputs=input_list, - promotes_outputs=["*"]) + control_iter_group.add_subsystem( + 'eom', subsys=eom_comp, promotes_inputs=input_list, promotes_outputs=['*'] + ) thrust_alpha_bal = om.BalanceComp() if not self.options['ground_roll']: - thrust_alpha_bal.add_balance("alpha", - units="rad", - val=np.zeros(nn), - lhs_name="dgam_dt_approx", - rhs_name="dgam_dt", - eq_units="rad/s", - lower=-np.pi/12, - upper=np.pi/12, - normalize=False) + thrust_alpha_bal.add_balance( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + units='rad', + val=np.zeros(nn), + lhs_name='dgam_dt_approx', + rhs_name='dgam_dt', + eq_units='rad/s', + lower=-np.pi / 12, + upper=np.pi / 12, + normalize=False, + ) - thrust_alpha_bal.add_balance("thrust_req", - units="N", - val=100*np.ones(nn), - lhs_name="dTAS_dt_approx", - rhs_name="dTAS_dt", - eq_units="m/s**2", - normalize=False) + thrust_alpha_bal.add_balance( + 'thrust_req', + units='N', + val=100 * np.ones(nn), + lhs_name='dTAS_dt_approx', + rhs_name='dTAS_dt', + eq_units='m/s**2', + normalize=False, + ) - control_iter_group.add_subsystem("thrust_alpha_bal", subsys=thrust_alpha_bal, - promotes_inputs=["*"], - promotes_outputs=["*"]) + control_iter_group.add_subsystem( + 'thrust_alpha_bal', + subsys=thrust_alpha_bal, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - control_iter_group.nonlinear_solver = om.NewtonSolver(solve_subsystems=True, - atol=1.0e-10, - rtol=1.0e-10) + control_iter_group.nonlinear_solver = om.NewtonSolver( + solve_subsystems=True, atol=1.0e-10, rtol=1.0e-10 + ) # control_iter_group.nonlinear_solver.linesearch = om.BoundsEnforceLS() control_iter_group.linear_solver = om.DirectSolver(assemble_jac=True) - self.add_subsystem("mass_rate", - om.ExecComp("dmass_dr = fuelflow * dt_dr", - fuelflow={"units": "lbm/s", "shape": nn}, - dt_dr={"units": "s/distance_units", "shape": nn}, - dmass_dr={"units": "lbm/distance_units", - "shape": nn, - "tags": ['dymos.state_rate_source:mass', - 'dymos.state_units:lbm']}, - has_diag_partials=True), - promotes_inputs=[ - ("fuelflow", Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL), "dt_dr"], - promotes_outputs=["dmass_dr"]) + self.add_subsystem( + 'mass_rate', + om.ExecComp( + 'dmass_dr = fuelflow * dt_dr', + fuelflow={'units': 'lbm/s', 'shape': nn}, + dt_dr={'units': 's/distance_units', 'shape': nn}, + dmass_dr={ + 'units': 'lbm/distance_units', + 'shape': nn, + 'tags': ['dymos.state_rate_source:mass', 'dymos.state_units:lbm'], + }, + has_diag_partials=True, + ), + promotes_inputs=[ + ('fuelflow', Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL), + 'dt_dr', + ], + promotes_outputs=['dmass_dr'], + ) - if self.options["include_param_comp"]: + if self.options['include_param_comp']: ParamPort.set_default_vals(self) onn = np.ones(nn) - self.set_input_defaults(name=Dynamic.Mission.DENSITY, - val=rho_sl * onn, units="slug/ft**3") self.set_input_defaults( - name=Dynamic.Mission.SPEED_OF_SOUND, - val=1116.4 * onn, - units="ft/s") + name=Dynamic.Atmosphere.DENSITY, val=rho_sl * onn, units='slug/ft**3' + ) + self.set_input_defaults( + name=Dynamic.Atmosphere.SPEED_OF_SOUND, val=1116.4 * onn, units='ft/s' + ) if not self.options['ground_roll']: self.set_input_defaults( - name=Dynamic.Mission.FLIGHT_PATH_ANGLE, val=0.0 * onn, units="rad") - self.set_input_defaults(name=Dynamic.Mission.VELOCITY, - val=250. * onn, units="kn") - self.set_input_defaults( - name=Dynamic.Mission.ALTITUDE, - val=10000. * onn, - units="ft") - self.set_input_defaults(name="dh_dr", val=0. * onn, units="ft/distance_units") - self.set_input_defaults(name="d2h_dr2", val=0. * onn, - units="ft/distance_units**2") + name=Dynamic.Mission.FLIGHT_PATH_ANGLE, val=0.0 * onn, units='rad' + ) + self.set_input_defaults(name=Dynamic.Mission.VELOCITY, val=250.0 * onn, units='kn') + self.set_input_defaults(name=Dynamic.Mission.ALTITUDE, val=10000.0 * onn, units='ft') + self.set_input_defaults(name='dh_dr', val=0.0 * onn, units='ft/distance_units') + self.set_input_defaults(name='d2h_dr2', val=0.0 * onn, units='ft/distance_units**2') diff --git a/aviary/mission/gasp_based/ode/v_rotate_comp.py b/aviary/mission/gasp_based/ode/v_rotate_comp.py new file mode 100644 index 0000000000..aef9fdbe67 --- /dev/null +++ b/aviary/mission/gasp_based/ode/v_rotate_comp.py @@ -0,0 +1,73 @@ +import openmdao.api as om + +from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH +from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.variables import Aircraft, Dynamic + + +class VRotateComp(om.ExplicitComponent): + """ + Component that computes V_rotate based on vehicle properties and speed buffers. + Note: This component is not used. + """ + + def setup(self): + # Temporarily set this to shape (1, 1) to avoid OpenMDAO bug + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=(1, 1), units='lbm') + add_aviary_input( + self, + Dynamic.Atmosphere.DENSITY, + shape=(1,), + units='slug/ft**3', + val=RHO_SEA_LEVEL_ENGLISH, + desc='sea-level atmospheric density', + ) + add_aviary_input(self, Aircraft.Wing.AREA, val=1.0) + self.add_input('CL_max', shape=(1,), units='unitless', desc='Maximum lift coefficient') + self.add_input( + 'dV1', + shape=(1,), + units='ft/s', + desc='Increment of engine failure decision speed above stall speed.', + ) + self.add_input( + 'dVR', + shape=(1,), + units='ft/s', + desc='Increment of takeoff rotation speed above engine failure decision speed.', + ) + + self.add_output( + 'Vrot', + shape=(1,), + units='ft/s', + desc='Speed at which takeoff rotation should be initiated.', + ) + + # Constant partials + self.declare_partials(of='Vrot', wrt=['dV1', 'dVR'], val=1.0) + # Partials of nonlinear terms + self.declare_partials( + of='Vrot', + wrt=[ + Dynamic.Vehicle.MASS, + Dynamic.Atmosphere.DENSITY, + Aircraft.Wing.AREA, + 'CL_max', + ], + ) + + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + mass, rho, wing_area, CL_max, dV1, dVR = inputs.values() + outputs['Vrot'] = ( + ((2 * mass * GRAV_ENGLISH_LBM) / (rho * wing_area * CL_max)) ** 0.5 + dV1 + dVR + ) + + def compute_partials(self, inputs, partials, discrete_inputs=None): + mass, rho, wing_area, CL_max, dV1, dVR = inputs.values() + K = 0.5 * ((2 * mass * GRAV_ENGLISH_LBM) / (rho * wing_area * CL_max)) ** 0.5 + + partials['Vrot', Dynamic.Vehicle.MASS] = K / mass + partials['Vrot', Dynamic.Atmosphere.DENSITY] = -K / rho + partials['Vrot', Aircraft.Wing.AREA] = -K / wing_area + partials['Vrot', 'CL_max'] = -K / CL_max diff --git a/aviary/mission/gasp_based/phases/accel_phase.py b/aviary/mission/gasp_based/phases/accel_phase.py index a1dcfa5d52..b3bc097e73 100644 --- a/aviary/mission/gasp_based/phases/accel_phase.py +++ b/aviary/mission/gasp_based/phases/accel_phase.py @@ -1,10 +1,90 @@ -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessControl from aviary.mission.gasp_based.ode.accel_ode import AccelODE -from aviary.mission.phase_builder_base import PhaseBuilderBase +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessIntegrationVariable, + InitialGuessState, +) +from aviary.mission.phase_builder_base import PhaseBuilderBase, register +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic +class AccelPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=1, + desc='The number of segments in transcription creation in Dymos. ' + 'The default value is 1.', + ) + + self.declare( + name='order', + types=int, + default=3, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos. The default value is 3.', + ) + + defaults = { + 'mass_bounds': (0.0, None), + } + self.add_state_options('mass', units='lbm', defaults=defaults) + + defaults = { + 'distance_bounds': (0.0, None), + } + self.add_state_options('distance', units='NM', defaults=defaults) + + defaults = { + 'velocity_bounds': (0.0, None), + } + self.add_state_options('velocity', units='kn', defaults=defaults) + + self.add_time_options(units='s') + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + self.declare( + name='EAS_constraint_eq', + default=250.0, + units='kn', + desc='Airspeed constraint applied at the end of the phase.', + ) + + # The options below have not yet been revamped. + + self.declare( + 'analytic', + types=bool, + default=False, + desc='When set to True, this is an analytic phase.', + ) + + self.declare( + name='alt', default=500.0, units='ft', desc='Constant altitude for this phase.' + ) + + +@register class AccelPhase(PhaseBuilderBase): """ A phase builder for an acceleration phase in a mission simulation. @@ -21,10 +101,11 @@ class AccelPhase(PhaseBuilderBase): Inherits all methods from PhaseBuilderBase. Additional method overrides and new methods specific to the acceleration phase are included. """ + default_name = 'accel_phase' default_ode_class = AccelODE + default_options_class = AccelPhaseOptions - _meta_data_ = {} _initial_guesses_meta_data_ = {} def build_phase(self, aviary_options: AviaryValues = None): @@ -44,84 +125,65 @@ def build_phase(self, aviary_options: AviaryValues = None): user_options = self.user_options # Extracting and setting options - EAS_constraint_eq = user_options.get_val('EAS_constraint_eq', units='kn') - alt = user_options.get_val('alt', units='ft') + EAS_constraint_eq = user_options.get_val('EAS_constraint_eq', 'kn') + alt = user_options.get_val('alt', 'ft') # States - self.add_velocity_state(user_options) - - self.add_mass_state(user_options) - - self.add_distance_state(user_options) + self.add_state('velocity', Dynamic.Mission.VELOCITY, Dynamic.Mission.VELOCITY_RATE) + self.add_state( + 'mass', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + ) + self.add_state('distance', Dynamic.Mission.DISTANCE, Dynamic.Mission.DISTANCE_RATE) # Boundary Constraints phase.add_boundary_constraint( - "EAS", loc="final", equals=EAS_constraint_eq, units="kn", ref=EAS_constraint_eq + 'EAS', loc='final', equals=EAS_constraint_eq, units='kn', ref=EAS_constraint_eq ) - phase.add_parameter(Dynamic.Mission.ALTITUDE, opt=False, units="ft", val=alt) + phase.add_parameter(Dynamic.Mission.ALTITUDE, opt=False, units='ft', val=alt) # Timeseries Outputs - phase.add_timeseries_output("EAS", output_name="EAS", units="kn") + phase.add_timeseries_output('EAS', output_name='EAS', units='kn') phase.add_timeseries_output( - Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units="unitless") - phase.add_timeseries_output("alpha", output_name="alpha", units="deg") - phase.add_timeseries_output("aero.CL", output_name="CL", units="unitless") + Dynamic.Atmosphere.MACH, + output_name=Dynamic.Atmosphere.MACH, + units='unitless', + ) phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, output_name=Dynamic.Mission.THRUST_TOTAL, units="lbf") - phase.add_timeseries_output("aero.CD", output_name="CD", units="unitless") + Dynamic.Vehicle.ANGLE_OF_ATTACK, + output_name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + units='deg', + ) + phase.add_timeseries_output( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', + ) - return phase + # TODO: These should be promoted in the 2dof mission outputs. + phase.add_timeseries_output('core_aerodynamics.CL', output_name='CL', units='unitless') + phase.add_timeseries_output('core_aerodynamics.CD', output_name='CD', units='unitless') + return phase -# Adding metadata for the AccelPhase -AccelPhase._add_meta_data( - 'analytic', val=False, desc='this is an analytic phase (no states).') -AccelPhase._add_meta_data( - 'reserve', val=False, desc='this phase is part of the reserve mission.') -AccelPhase._add_meta_data( - 'target_distance', val={}, desc='the amount of distance traveled in this phase added as a constraint') -AccelPhase._add_meta_data( - 'target_duration', val={}, desc='the amount of time taken by this phase added as a constraint') -AccelPhase._add_meta_data('fix_initial', val=False) -AccelPhase._add_meta_data('EAS_constraint_eq', val=250, units='kn') -AccelPhase._add_meta_data('duration_bounds', val=(0, 0), units='s') -AccelPhase._add_meta_data('duration_ref', val=1, units='s') -AccelPhase._add_meta_data('velocity_lower', val=0, units='kn') -AccelPhase._add_meta_data('velocity_upper', val=0, units='kn') -AccelPhase._add_meta_data('velocity_ref', val=1, units='kn') -AccelPhase._add_meta_data('velocity_ref0', val=0, units='kn') -AccelPhase._add_meta_data('velocity_defect_ref', val=None, units='kn') -AccelPhase._add_meta_data('mass_lower', val=0, units='lbm') -AccelPhase._add_meta_data('mass_upper', val=0, units='lbm') -AccelPhase._add_meta_data('mass_ref', val=1, units='lbm') -AccelPhase._add_meta_data('mass_ref0', val=0, units='lbm') -AccelPhase._add_meta_data('mass_defect_ref', val=None, units='lbm') -AccelPhase._add_meta_data('distance_lower', val=0, units='NM') -AccelPhase._add_meta_data('distance_upper', val=0, units='NM') -AccelPhase._add_meta_data('distance_ref', val=1, units='NM') -AccelPhase._add_meta_data('distance_ref0', val=0, units='NM') -AccelPhase._add_meta_data('distance_defect_ref', val=None, units='NM') -AccelPhase._add_meta_data('alt', val=500, units='ft') -AccelPhase._add_meta_data('num_segments', val=None, units='unitless') -AccelPhase._add_meta_data('order', val=None, units='unitless') AccelPhase._add_initial_guess_meta_data( InitialGuessIntegrationVariable(), - desc='initial guess for initial time and duration specified as a tuple') + desc='initial guess for initial time and duration specified as a tuple', +) AccelPhase._add_initial_guess_meta_data( - InitialGuessState('velocity'), - desc='initial guess for true airspeed') + InitialGuessState('velocity'), desc='initial guess for true airspeed' +) -AccelPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') +AccelPhase._add_initial_guess_meta_data(InitialGuessState('mass'), desc='initial guess for mass') AccelPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for horizontal distance traveled') + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled' +) AccelPhase._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') + InitialGuessControl('throttle'), desc='initial guess for throttle' +) diff --git a/aviary/mission/gasp_based/phases/ascent_phase.py b/aviary/mission/gasp_based/phases/ascent_phase.py index 6636554119..39b8694bc3 100644 --- a/aviary/mission/gasp_based/phases/ascent_phase.py +++ b/aviary/mission/gasp_based/phases/ascent_phase.py @@ -1,10 +1,120 @@ import numpy as np +from aviary.mission.gasp_based.ode.ascent_ode import AscentODE +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessIntegrationVariable, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessControl +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic -from aviary.mission.gasp_based.ode.ascent_ode import AscentODE + + +class AscentPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=1, + desc='The number of segments in transcription creation in Dymos. ' + 'The default value is 1.', + ) + + self.declare( + name='order', + types=int, + default=None, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos.', + ) + + defaults = { + 'mass_ref': 100_000.0, + 'mass_defect_ref': 1.0e2, + 'mass_bounds': (0.0, 190_000.0), + } + self.add_state_options('mass', units='lbm', defaults=defaults) + + # NOTE: All GASP phases before accel are in 'ft'. + defaults = { + 'distance_ref': 3000.0, + 'distance_bounds': (0.0, 10.0e3), + } + self.add_state_options('distance', units='ft', defaults=defaults) + + defaults = { + 'velocity_ref': 1.0e2, + 'velocity_bounds': (0.0, 1000.0), + } + self.add_state_options('velocity', units='kn', defaults=defaults) + + defaults = { + 'altitude_ref': 100.0, + 'altitude_bounds': (0.0, 700.0), + 'altitude_constraint_ref': 100.0, + } + self.add_state_options('altitude', units='ft', defaults=defaults) + + defaults = { + 'flight_path_angle_ref': np.deg2rad(1), + 'flight_path_angle_bounds': (-15 * np.pi / 180, 25.0 * np.pi / 180), + } + self.add_state_options('flight_path_angle', units='rad', defaults=defaults) + + defaults = { + 'angle_of_attack_ref': np.deg2rad(5), + 'angle_of_attack_bounds': (np.deg2rad(-30), np.deg2rad(30)), + 'angle_of_attack_optimize': True, + } + self.add_control_options('angle_of_attack', units='rad', defaults=defaults) + + self.add_time_options(units='s') + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + # The options below have not yet been revamped. + + self.declare( + 'analytic', + types=bool, + default=False, + desc='When set to True, this is an analytic phase.', + ) + + self.declare( + name='pitch_constraint_bounds', + default=(0.0, 15.0), + types=tuple, + units='deg', + allow_none=True, + desc='Tuple containing the lower and upper bounds of the pitch constraint, ' + 'with unit string.', + ) + + self.declare( + name='pitch_constraint_ref', + default=1.0, + units='deg', + desc='Scale factor ref for the pitch constraint.', + ) class AscentPhase(PhaseBuilderBase): @@ -26,8 +136,8 @@ class AscentPhase(PhaseBuilderBase): default_name = 'ascent_phase' default_ode_class = AscentODE + default_options_class = AscentPhaseOptions - _meta_data_ = {} _initial_guesses_meta_data_ = {} def build_phase(self, aviary_options: AviaryValues = None): @@ -36,151 +146,92 @@ def build_phase(self, aviary_options: AviaryValues = None): # Retrieve user options values user_options = self.user_options - pitch_constraint_lower = user_options.get_val( - 'pitch_constraint_lower', units='deg') - pitch_constraint_upper = user_options.get_val( - 'pitch_constraint_upper', units='deg') + pitch_constraint_bounds = user_options.get_val('pitch_constraint_bounds', units='deg') pitch_constraint_ref = user_options.get_val('pitch_constraint_ref', units='deg') - alpha_constraint_lower = user_options.get_val( - 'alpha_constraint_lower', units='rad') - alpha_constraint_upper = user_options.get_val( - 'alpha_constraint_upper', units='rad') - alpha_constraint_ref = user_options.get_val('alpha_constraint_ref', units='rad') - - self.add_flight_path_angle_state(user_options) - self.add_altitude_state(user_options) - self.add_velocity_state(user_options) - self.add_mass_state(user_options) - self.add_distance_state(user_options, units='ft') - self.add_altitude_constraint(user_options) + self.add_state( + 'flight_path_angle', + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, + ) + self.add_state('altitude', Dynamic.Mission.ALTITUDE, Dynamic.Mission.ALTITUDE_RATE) + self.add_state('velocity', Dynamic.Mission.VELOCITY, Dynamic.Mission.VELOCITY_RATE) + self.add_state( + 'mass', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + ) + self.add_state('distance', Dynamic.Mission.DISTANCE, Dynamic.Mission.DISTANCE_RATE) - phase.add_path_constraint( - "load_factor", - upper=1.10, - lower=0.0 + self.add_control( + 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, ) + phase.add_path_constraint('load_factor', upper=1.10, lower=0.0) + phase.add_path_constraint( - "fuselage_pitch", - "theta", - lower=pitch_constraint_lower, - upper=pitch_constraint_upper, - units="deg", + 'fuselage_pitch', + 'theta', + lower=pitch_constraint_bounds[0], + upper=pitch_constraint_bounds[1], + units='deg', ref=pitch_constraint_ref, ) - phase.add_control( - "alpha", - val=0, - lower=alpha_constraint_lower, - upper=alpha_constraint_upper, - units="rad", - ref=alpha_constraint_ref, - opt=True, - ) - - phase.add_parameter("t_init_gear", units="s", - static_target=True, opt=False, val=38.25) + phase.add_parameter('t_init_gear', units='s', static_target=True, opt=False, val=38.25) - phase.add_parameter("t_init_flaps", units="s", - static_target=True, opt=False, val=48.21) + phase.add_parameter('t_init_flaps', units='s', static_target=True, opt=False, val=48.21) - phase.add_timeseries_output(Dynamic.Mission.THRUST_TOTAL, units="lbf") - phase.add_timeseries_output("normal_force") - phase.add_timeseries_output(Dynamic.Mission.MACH) - phase.add_timeseries_output("EAS", units="kn") - phase.add_timeseries_output(Dynamic.Mission.LIFT) - phase.add_timeseries_output("CL") - phase.add_timeseries_output("CD") + phase.add_timeseries_output(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, units='lbf') + phase.add_timeseries_output('normal_force') + phase.add_timeseries_output(Dynamic.Atmosphere.MACH) + phase.add_timeseries_output('EAS', units='kn') + phase.add_timeseries_output(Dynamic.Vehicle.LIFT) + phase.add_timeseries_output('CL') + phase.add_timeseries_output('CD') return phase -# Adding metadata for the AscentPhase -AscentPhase._add_meta_data( - 'analytic', val=False, desc='this is an analytic phase (no states).') -AscentPhase._add_meta_data( - 'reserve', val=False, desc='this phase is part of the reserve mission.') -AscentPhase._add_meta_data( - 'target_distance', val={}, desc='the amount of distance traveled in this phase added as a constraint') -AscentPhase._add_meta_data( - 'target_duration', val={}, desc='the amount of time taken by this phase added as a constraint') -AscentPhase._add_meta_data('fix_initial', val=False) -AscentPhase._add_meta_data('angle_lower', val=-15 * np.pi / 180, units='rad') -AscentPhase._add_meta_data('angle_upper', val=25 * np.pi / 180, units='rad') -AscentPhase._add_meta_data('angle_ref', val=np.deg2rad(1), units='rad') -AscentPhase._add_meta_data('angle_ref0', val=0, units='rad') -AscentPhase._add_meta_data('angle_defect_ref', val=0.01, units='rad') -AscentPhase._add_meta_data('alt_lower', val=0, units='ft') -AscentPhase._add_meta_data('alt_upper', val=700, units='ft') -AscentPhase._add_meta_data('alt_ref', val=100, units='ft') -AscentPhase._add_meta_data('alt_ref0', val=0, units='ft') -AscentPhase._add_meta_data('alt_defect_ref', val=100, units='ft') -AscentPhase._add_meta_data('final_altitude', val=500, units='ft') -AscentPhase._add_meta_data('alt_constraint_ref', val=100, units='ft') -AscentPhase._add_meta_data('alt_constraint_ref0', val=0, units='ft') -AscentPhase._add_meta_data('velocity_lower', val=0, units='kn') -AscentPhase._add_meta_data('velocity_upper', val=1000, units='kn') -AscentPhase._add_meta_data('velocity_ref', val=1e2, units='kn') -AscentPhase._add_meta_data('velocity_ref0', val=0, units='kn') -AscentPhase._add_meta_data('velocity_defect_ref', val=None, units='kn') -AscentPhase._add_meta_data('mass_lower', val=0, units='lbm') -AscentPhase._add_meta_data('mass_upper', val=190_000, units='lbm') -AscentPhase._add_meta_data('mass_ref', val=100_000, units='lbm') -AscentPhase._add_meta_data('mass_ref0', val=0, units='lbm') -AscentPhase._add_meta_data('mass_defect_ref', val=1e2, units='lbm') -AscentPhase._add_meta_data('distance_lower', val=0, units='ft') -AscentPhase._add_meta_data('distance_upper', val=10.e3, units='ft') -AscentPhase._add_meta_data('distance_ref', val=3000, units='ft') -AscentPhase._add_meta_data('distance_ref0', val=0, units='ft') -AscentPhase._add_meta_data('distance_defect_ref', val=3000, units='ft') -AscentPhase._add_meta_data('pitch_constraint_lower', val=0, units='deg') -AscentPhase._add_meta_data('pitch_constraint_upper', val=15, units='deg') -AscentPhase._add_meta_data('pitch_constraint_ref', val=1, units='deg') -AscentPhase._add_meta_data('alpha_constraint_lower', val=np.deg2rad(-30), units='rad') -AscentPhase._add_meta_data('alpha_constraint_upper', val=np.deg2rad(30), units='rad') -AscentPhase._add_meta_data('alpha_constraint_ref', val=np.deg2rad(5), units='rad') -AscentPhase._add_meta_data('num_segments', val=None, units='unitless') -AscentPhase._add_meta_data('order', val=None, units='unitless') - # Adding initial guess metadata AscentPhase._add_initial_guess_meta_data( - InitialGuessIntegrationVariable(), - desc='initial guess for time options') + InitialGuessIntegrationVariable(), desc='initial guess for time options' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessState('flight_path_angle'), - desc='initial guess for flight path angle state') + InitialGuessState('flight_path_angle'), desc='initial guess for flight path angle state' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for altitude state') + InitialGuessState('altitude'), desc='initial guess for altitude state' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessState('velocity'), - desc='initial guess for true airspeed state') + InitialGuessState('velocity'), desc='initial guess for true airspeed state' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass state') + InitialGuessState('mass'), desc='initial guess for mass state' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for distance state') + InitialGuessState('distance'), desc='initial guess for distance state' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessControl('alpha'), - desc='initial guess for angle of attack control') + InitialGuessControl('angle_of_attack'), + desc='initial guess for angle of attack control', +) AscentPhase._add_initial_guess_meta_data( - InitialGuessControl('tau_gear'), - desc='when the gear is retracted') + InitialGuessControl('tau_gear'), desc='when the gear is retracted' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessControl('tau_flaps'), - desc='when the flaps are retracted') + InitialGuessControl('tau_flaps'), desc='when the flaps are retracted' +) AscentPhase._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') + InitialGuessControl('throttle'), desc='initial guess for throttle' +) diff --git a/aviary/mission/gasp_based/phases/climb_phase.py b/aviary/mission/gasp_based/phases/climb_phase.py index 0bb6bbed88..9404c68943 100644 --- a/aviary/mission/gasp_based/phases/climb_phase.py +++ b/aviary/mission/gasp_based/phases/climb_phase.py @@ -1,8 +1,107 @@ +from aviary.mission.gasp_based.ode.climb_ode import ClimbODE +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessIntegrationVariable, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessControl +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic -from aviary.mission.gasp_based.ode.climb_ode import ClimbODE + + +class ClimbPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=None, + desc='The number of segments in transcription creation in Dymos. ', + ) + + self.declare( + name='order', + types=int, + default=None, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos.', + ) + + defaults = { + 'mass_bounds': (0.0, None), + } + self.add_state_options('mass', units='lbm', defaults=defaults) + + defaults = { + 'distance_bounds': (0.0, None), + } + self.add_state_options('distance', units='NM', defaults=defaults) + + defaults = { + 'altitude_bounds': (0.0, None), + } + self.add_state_options('altitude', units='ft', defaults=defaults) + + self.add_time_options(units='s') + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + self.declare( + name='required_available_climb_rate', + default=None, + units='ft/min', + desc='Adds a constraint requiring Dynamic.Mission.ALTITUDE_RATE_MAX to be no ' + 'smaller than required_available_climb_rate. This helps to ensure that the ' + 'propulsion system is large enough to handle emergency maneuvers at all points ' + 'throughout the flight envelope. Default value is None for no constraint.', + ) + + # The options below have not yet been revamped. + + self.declare( + 'analytic', + types=bool, + default=False, + desc='When set to True, this is an analytic phase.', + ) + + self.declare( + name='EAS_target', + default=0.0, + units='kn', + desc='Target airspeed for the balance in this phase.', + ) + + self.declare( + name='mach_cruise', + default=0.0, + desc='Defines the mach constraint at the end of the phase. ' + 'Only valid when target_mach=True.', + ) + + self.declare( + 'target_mach', + types=bool, + default=False, + desc='Set to true to enforce a mach_constraint at the phase endpoint. ' + 'The mach value is set in "mach_cruise".', + ) class ClimbPhase(PhaseBuilderBase): @@ -21,10 +120,11 @@ class ClimbPhase(PhaseBuilderBase): Inherits all methods from PhaseBuilderBase. Additional method overrides and new methods specific to the climb phase are included. """ + default_name = 'climb_phase' default_ode_class = ClimbODE + default_options_class = ClimbPhaseOptions - _meta_data_ = {} _initial_guesses_meta_data_ = {} def build_phase(self, aviary_options: AviaryValues = None): @@ -49,67 +149,77 @@ def build_phase(self, aviary_options: AviaryValues = None): mach_cruise = user_options.get_val('mach_cruise') target_mach = user_options.get_val('target_mach') - final_altitude = user_options.get_val('final_altitude', units='ft') + altitude_final = user_options.get_val('altitude_final', units='ft') required_available_climb_rate = user_options.get_val( - 'required_available_climb_rate', units='ft/min') + 'required_available_climb_rate', units='ft/min' + ) # States - self.add_altitude_state(user_options) - - self.add_mass_state(user_options) - - self.add_distance_state(user_options) - - # Boundary Constraints - phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, - loc="final", - equals=final_altitude, - units="ft", - ref=final_altitude, + self.add_state('altitude', Dynamic.Mission.ALTITUDE, Dynamic.Mission.ALTITUDE_RATE) + self.add_state( + 'mass', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, ) + self.add_state('distance', Dynamic.Mission.DISTANCE, Dynamic.Mission.DISTANCE_RATE) if required_available_climb_rate is not None: # TODO: this should be altitude rate max phase.add_boundary_constraint( Dynamic.Mission.ALTITUDE_RATE, - loc="final", + loc='final', lower=required_available_climb_rate, - units="ft/min", + units='ft/min', ref=1, ) if target_mach: phase.add_boundary_constraint( - Dynamic.Mission.MACH, loc="final", equals=mach_cruise, + Dynamic.Atmosphere.MACH, + loc='final', + equals=mach_cruise, ) # Timeseries Outputs phase.add_timeseries_output( - Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units="unitless") - phase.add_timeseries_output("EAS", output_name="EAS", units="kn") + Dynamic.Atmosphere.MACH, + output_name=Dynamic.Atmosphere.MACH, + units='unitless', + ) + phase.add_timeseries_output('EAS', output_name='EAS', units='kn') + phase.add_timeseries_output( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/s' + ) + phase.add_timeseries_output('theta', output_name='theta', units='deg') phase.add_timeseries_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units="lbm/s") - phase.add_timeseries_output("theta", output_name="theta", units="deg") - phase.add_timeseries_output("alpha", output_name="alpha", units="deg") - phase.add_timeseries_output(Dynamic.Mission.FLIGHT_PATH_ANGLE, - output_name=Dynamic.Mission.FLIGHT_PATH_ANGLE, units="deg") + Dynamic.Vehicle.ANGLE_OF_ATTACK, + output_name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + units='deg', + ) phase.add_timeseries_output( - "TAS_violation", output_name="TAS_violation", units="kn") + Dynamic.Mission.FLIGHT_PATH_ANGLE, + output_name=Dynamic.Mission.FLIGHT_PATH_ANGLE, + units='deg', + ) + phase.add_timeseries_output('TAS_violation', output_name='TAS_violation', units='kn') phase.add_timeseries_output( - Dynamic.Mission.VELOCITY, output_name=Dynamic.Mission.VELOCITY, units="kn" + Dynamic.Mission.VELOCITY, + output_name=Dynamic.Mission.VELOCITY, + units='kn', ) - phase.add_timeseries_output("aero.CL", output_name="CL", units="unitless") phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, output_name=Dynamic.Mission.THRUST_TOTAL, units="lbf") - phase.add_timeseries_output("aero.CD", output_name="CD", units="unitless") + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', + ) + # TODO: These should be promoted in the 2dof mission outputs. + phase.add_timeseries_output('core_aerodynamics.CL', output_name='CL', units='unitless') + phase.add_timeseries_output('core_aerodynamics.CD', output_name='CD', units='unitless') return phase def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ + """Return extra kwargs required for initializing the ODE.""" # TODO: support external_subsystems and meta_data in the base class return { 'EAS_target': self.user_options.get_val('EAS_target', units='kn'), @@ -117,57 +227,21 @@ def _extra_ode_init_kwargs(self): } -# Adding metadata for the ClimbPhase -ClimbPhase._add_meta_data( - 'analytic', val=False, desc='this is an analytic phase (no states).') -ClimbPhase._add_meta_data( - 'reserve', val=False, desc='this phase is part of the reserve mission.') -ClimbPhase._add_meta_data( - 'target_distance', val={}, desc='the amount of distance traveled in this phase added as a constraint') -ClimbPhase._add_meta_data( - 'target_duration', val={}, desc='the amount of time taken by this phase added as a constraint') -ClimbPhase._add_meta_data('fix_initial', val=False) -ClimbPhase._add_meta_data('EAS_target', val=0) -ClimbPhase._add_meta_data('mach_cruise', val=0) -ClimbPhase._add_meta_data('target_mach', val=False) -ClimbPhase._add_meta_data('final_altitude', val=0) -ClimbPhase._add_meta_data('required_available_climb_rate', val=None, units='ft/min') -ClimbPhase._add_meta_data('duration_bounds', val=(0, 0), units='s') -ClimbPhase._add_meta_data('duration_ref', val=1, units='s') -ClimbPhase._add_meta_data('alt_lower', val=0, units='ft') -ClimbPhase._add_meta_data('alt_upper', val=0, units='ft') -ClimbPhase._add_meta_data('alt_ref', val=1, units='ft') -ClimbPhase._add_meta_data('alt_ref0', val=0, units='ft') -ClimbPhase._add_meta_data('alt_defect_ref', val=None, units='ft') -ClimbPhase._add_meta_data('mass_lower', val=0, units='lbm') -ClimbPhase._add_meta_data('mass_upper', val=0, units='lbm') -ClimbPhase._add_meta_data('mass_ref', val=1, units='lbm') -ClimbPhase._add_meta_data('mass_ref0', val=0, units='lbm') -ClimbPhase._add_meta_data('mass_defect_ref', val=None, units='lbm') -ClimbPhase._add_meta_data('distance_lower', val=0, units='NM') -ClimbPhase._add_meta_data('distance_upper', val=0, units='NM') -ClimbPhase._add_meta_data('distance_ref', val=1, units='NM') -ClimbPhase._add_meta_data('distance_ref0', val=0, units='NM') -ClimbPhase._add_meta_data('distance_defect_ref', val=None, units='NM') -ClimbPhase._add_meta_data('num_segments', val=None, units='unitless') -ClimbPhase._add_meta_data('order', val=None, units='unitless') - ClimbPhase._add_initial_guess_meta_data( InitialGuessIntegrationVariable(), - desc='initial guess for initial time and duration specified as a tuple') + desc='initial guess for initial time and duration specified as a tuple', +) ClimbPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for horizontal distance traveled') + InitialGuessState('distance'), desc='initial guess for horizontal distance traveled' +) ClimbPhase._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for vertical distances') + InitialGuessState('altitude'), desc='initial guess for vertical distances' +) -ClimbPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') +ClimbPhase._add_initial_guess_meta_data(InitialGuessState('mass'), desc='initial guess for mass') ClimbPhase._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') + InitialGuessControl('throttle'), desc='initial guess for throttle' +) diff --git a/aviary/mission/gasp_based/phases/cruise_phase.py b/aviary/mission/gasp_based/phases/cruise_phase.py index 44b7704f52..8595b321a5 100644 --- a/aviary/mission/gasp_based/phases/cruise_phase.py +++ b/aviary/mission/gasp_based/phases/cruise_phase.py @@ -1,8 +1,66 @@ +from aviary.mission.gasp_based.ode.breguet_cruise_ode import BreguetCruiseODESolution +from aviary.mission.initial_guess_builders import InitialGuessIntegrationVariable, InitialGuessState from aviary.mission.phase_builder_base import PhaseBuilderBase -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic -from aviary.mission.gasp_based.ode.breguet_cruise_ode import BreguetCruiseODESolution + + +class CruisePhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare(name='alt_cruise', default=0.0, units='ft', desc='Cruise altitude.') + + self.declare(name='mach_cruise', default=0.0, desc='Cruise Mach number.') + + self.declare( + 'analytic', + types=bool, + default=False, + desc='When set to True, this is an analytic phase.', + ) + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + self.declare( + 'time_duration', + default=None, + units='s', + desc='The amount of time taken by this phase added as a constraint.', + ) + + self.declare( + name='time_duration_bounds', + default=(0, 3600), + units='s', + desc='Lower and upper bounds on the phase duration, in the form of a nested tuple: ' + 'i.e. ((20, 36), "min") This constrains the duration to be between 20 and 36 min.', + ) + + self.declare( + 'time_initial_bounds', + types=tuple, + default=(0.0, 100.0), + units='s', + desc='Lower and upper bounds on the starting time for this phase relative to the ' + 'starting time of the mission, i.e., ((25, 45), "min") constrians this phase to ' + 'start between 25 and 45 minutes after the start of the mission.', + ) class CruisePhase(PhaseBuilderBase): @@ -21,21 +79,36 @@ class CruisePhase(PhaseBuilderBase): Inherits all methods from PhaseBuilderBase. Additional method overrides and new methods specific to the cruise phase are included. """ + default_name = 'cruise_phase' default_ode_class = BreguetCruiseODESolution + default_options_class = CruisePhaseOptions - _meta_data_ = {} _initial_guesses_meta_data_ = {} def __init__( - self, name=None, subsystem_options=None, user_options=None, initial_guesses=None, - ode_class=None, transcription=None, core_subsystems=None, - external_subsystems=None, meta_data=None + self, + name=None, + subsystem_options=None, + user_options=None, + initial_guesses=None, + ode_class=None, + transcription=None, + core_subsystems=None, + external_subsystems=None, + meta_data=None, ): super().__init__( - name=name, subsystem_options=subsystem_options, user_options=user_options, - initial_guesses=initial_guesses, ode_class=ode_class, transcription=transcription, - core_subsystems=core_subsystems, is_analytic_phase=True, + name=name, + subsystem_options=subsystem_options, + user_options=user_options, + initial_guesses=initial_guesses, + ode_class=ode_class, + transcription=transcription, + core_subsystems=core_subsystems, + external_subsystems=external_subsystems, + meta_data=meta_data, + is_analytic_phase=True, ) def build_phase(self, aviary_options: AviaryValues = None): @@ -59,60 +132,37 @@ def build_phase(self, aviary_options: AviaryValues = None): user_options = self.user_options mach_cruise = user_options.get_val('mach_cruise') - alt_cruise, alt_units = user_options.get_item('alt_cruise') + alt_cruise, alt_units = user_options['alt_cruise'] - phase.add_parameter(Dynamic.Mission.ALTITUDE, opt=False, - val=alt_cruise, units=alt_units) - phase.add_parameter(Dynamic.Mission.MACH, opt=False, - val=mach_cruise) - phase.add_parameter("initial_distance", opt=False, val=0.0, - units="NM", static_target=True) - phase.add_parameter("initial_time", opt=False, val=0.0, - units="s", static_target=True) + phase.add_parameter(Dynamic.Mission.ALTITUDE, opt=False, val=alt_cruise, units=alt_units) + phase.add_parameter(Dynamic.Atmosphere.MACH, opt=False, val=mach_cruise) + phase.add_parameter('initial_distance', opt=False, val=0.0, units='NM', static_target=True) + phase.add_parameter('initial_time', opt=False, val=0.0, units='s', static_target=True) - phase.add_timeseries_output("time", units="s", output_name="time") - phase.add_timeseries_output(Dynamic.Mission.MASS, units="lbm") - phase.add_timeseries_output(Dynamic.Mission.DISTANCE, units="nmi") + phase.add_timeseries_output('time', units='s', output_name='time') + phase.add_timeseries_output(Dynamic.Vehicle.MASS, units='lbm') + phase.add_timeseries_output(Dynamic.Mission.DISTANCE, units='nmi') return phase -# Adding metadata for the CruisePhase -CruisePhase._add_meta_data('alt_cruise', val=0) -CruisePhase._add_meta_data('mach_cruise', val=0) -CruisePhase._add_meta_data( - 'analytic', val=False, desc='this is an analytic phase (no states).') -CruisePhase._add_meta_data( - 'reserve', val=False, desc='this phase is part of the reserve mission.') -CruisePhase._add_meta_data( - 'target_distance', val={}, desc='the amount of distance traveled in this phase added as a constraint') -CruisePhase._add_meta_data( - 'target_duration', val={}, desc='the amount of time taken by this phase added as a constraint') -CruisePhase._add_meta_data('duration_bounds', val=( - 0., 3600.), units='s', desc='duration bounds') -CruisePhase._add_meta_data('fix_duration', val=False) -CruisePhase._add_meta_data('initial_bounds', val=(0., 100.), units='s') - CruisePhase._add_initial_guess_meta_data( InitialGuessIntegrationVariable(), - desc='initial guess for initial time and duration specified as a tuple') + desc='initial guess for initial time and duration specified as a tuple', +) -CruisePhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass') +CruisePhase._add_initial_guess_meta_data(InitialGuessState('mass'), desc='initial guess for mass') CruisePhase._add_initial_guess_meta_data( - InitialGuessState('initial_distance'), - desc='initial guess for initial_distance') + InitialGuessState('initial_distance'), desc='initial guess for initial_distance' +) CruisePhase._add_initial_guess_meta_data( - InitialGuessState('initial_time'), - desc='initial guess for initial_time') + InitialGuessState('initial_time'), desc='initial guess for initial_time' +) CruisePhase._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for altitude') + InitialGuessState('altitude'), desc='initial guess for altitude' +) -CruisePhase._add_initial_guess_meta_data( - InitialGuessState('mach'), - desc='initial guess for mach') +CruisePhase._add_initial_guess_meta_data(InitialGuessState('mach'), desc='initial guess for mach') diff --git a/aviary/mission/gasp_based/phases/descent_phase.py b/aviary/mission/gasp_based/phases/descent_phase.py index 713e2234f2..210f18e723 100644 --- a/aviary/mission/gasp_based/phases/descent_phase.py +++ b/aviary/mission/gasp_based/phases/descent_phase.py @@ -1,11 +1,98 @@ from aviary.mission.gasp_based.ode.descent_ode import DescentODE +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessIntegrationVariable, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessControl +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import SpeedType from aviary.variable_info.variables import Dynamic +class DescentPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=None, + desc='The number of segments in transcription creation in Dymos. ', + ) + + self.declare( + name='order', + types=int, + default=None, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos.', + ) + + defaults = { + 'mass_bounds': (0.0, None), + } + self.add_state_options('mass', units='lbm', defaults=defaults) + + defaults = { + 'distance_bounds': (0.0, None), + } + self.add_state_options('distance', units='NM', defaults=defaults) + + defaults = { + 'altitude_bounds': (0.0, None), + 'altitude_constraint_ref': 100.0, + } + self.add_state_options('altitude', units='ft', defaults=defaults) + + self.add_time_options(units='s') + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + # The options below have not yet been revamped. + + self.declare( + 'analytic', + types=bool, + default=False, + desc='When set to True, this is an analytic phase.', + ) + + self.declare( + name='EAS_limit', + default=0.0, + units='kn', + desc='Value for maximum speed constraint in this phase.', + ) + + self.declare( + name='mach_cruise', default=0.0, desc='Defines the mach constraint in this phase.' + ) + + self.declare( + name='input_speed_type', + default=SpeedType.MACH, + values=[SpeedType.MACH, SpeedType.EAS, SpeedType.TAS], + desc='Determines which speed variable is independent. The other two will be .' + 'computed from it.', + ) + + class DescentPhase(PhaseBuilderBase): """ A phase builder for an descent phase in a mission simulation. @@ -25,8 +112,8 @@ class DescentPhase(PhaseBuilderBase): default_name = 'descent_phase' default_ode_class = DescentODE + default_options_class = DescentPhaseOptions - _meta_data_ = {} _initial_guesses_meta_data_ = {} def build_phase(self, aviary_options: AviaryValues = None): @@ -38,41 +125,54 @@ def build_phase(self, aviary_options: AviaryValues = None): EAS_limit = user_options.get_val('EAS_limit', units='kn') # Add states - self.add_altitude_state(user_options) - - self.add_mass_state(user_options) - - self.add_distance_state(user_options) - - # Add boundary constraint - self.add_altitude_constraint(user_options) + self.add_state('altitude', Dynamic.Mission.ALTITUDE, Dynamic.Mission.ALTITUDE_RATE) + self.add_state( + 'mass', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + ) + self.add_state('distance', Dynamic.Mission.DISTANCE, Dynamic.Mission.DISTANCE_RATE) # Add parameter if necessary if input_speed_type == SpeedType.EAS: - phase.add_parameter("EAS", opt=False, units="kn", val=EAS_limit) + phase.add_parameter('EAS', opt=False, units='kn', val=EAS_limit) # Add timeseries outputs phase.add_timeseries_output( - Dynamic.Mission.MACH, output_name=Dynamic.Mission.MACH, units="unitless") - phase.add_timeseries_output("EAS", output_name="EAS", units="kn") + Dynamic.Atmosphere.MACH, + output_name=Dynamic.Atmosphere.MACH, + units='unitless', + ) + phase.add_timeseries_output('EAS', output_name='EAS', units='kn') + phase.add_timeseries_output( + Dynamic.Mission.VELOCITY, + output_name=Dynamic.Mission.VELOCITY, + units='kn', + ) phase.add_timeseries_output( - Dynamic.Mission.VELOCITY, output_name=Dynamic.Mission.VELOCITY, units="kn" + Dynamic.Mission.FLIGHT_PATH_ANGLE, + output_name=Dynamic.Mission.FLIGHT_PATH_ANGLE, + units='deg', ) - phase.add_timeseries_output(Dynamic.Mission.FLIGHT_PATH_ANGLE, - output_name=Dynamic.Mission.FLIGHT_PATH_ANGLE, units="deg") - phase.add_timeseries_output("alpha", output_name="alpha", units="deg") - phase.add_timeseries_output("theta", output_name="theta", units="deg") - phase.add_timeseries_output("aero.CL", output_name="CL", units="unitless") phase.add_timeseries_output( - Dynamic.Mission.THRUST_TOTAL, output_name=Dynamic.Mission.THRUST_TOTAL, units="lbf") - phase.add_timeseries_output("aero.CD", output_name="CD", units="unitless") + Dynamic.Vehicle.ANGLE_OF_ATTACK, + output_name=Dynamic.Vehicle.ANGLE_OF_ATTACK, + units='deg', + ) + phase.add_timeseries_output('theta', output_name='theta', units='deg') + phase.add_timeseries_output( + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + output_name=Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + units='lbf', + ) + # TODO: These should be promoted in the 2dof mission outputs. + phase.add_timeseries_output('core_aerodynamics.CL', output_name='CL', units='unitless') + phase.add_timeseries_output('core_aerodynamics.CD', output_name='CD', units='unitless') return phase def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ + """Return extra kwargs required for initializing the ODE.""" # TODO: support external_subsystems and meta_data in the base class return { 'input_speed_type': self.user_options.get_val('input_speed_type'), @@ -81,55 +181,19 @@ def _extra_ode_init_kwargs(self): } -# Adding metadata for the DescentPhase -DescentPhase._add_meta_data( - 'analytic', val=False, desc='this is an analytic phase (no states).') -DescentPhase._add_meta_data( - 'reserve', val=False, desc='this phase is part of the reserve mission.') -DescentPhase._add_meta_data( - 'target_distance', val={}, desc='the amount of distance traveled in this phase added as a constraint') -DescentPhase._add_meta_data( - 'target_duration', val={}, desc='the amount of time taken by this phase added as a constraint') -DescentPhase._add_meta_data('fix_initial', val=False) -DescentPhase._add_meta_data('input_initial', val=False) -DescentPhase._add_meta_data('EAS_limit', val=0, units='kn') -DescentPhase._add_meta_data('mach_cruise', val=0) -DescentPhase._add_meta_data('input_speed_type', val=SpeedType.MACH) -DescentPhase._add_meta_data('final_altitude', val=0, units='ft') -DescentPhase._add_meta_data('duration_bounds', val=(0, 0), units='s') -DescentPhase._add_meta_data('duration_ref', val=1, units='s') -DescentPhase._add_meta_data('alt_lower', val=0, units='ft') -DescentPhase._add_meta_data('alt_upper', val=0, units='ft') -DescentPhase._add_meta_data('alt_ref', val=1, units='ft') -DescentPhase._add_meta_data('alt_ref0', val=0, units='ft') -DescentPhase._add_meta_data('alt_defect_ref', val=None, units='ft') -DescentPhase._add_meta_data('alt_constraint_ref', val=None, units='ft') -DescentPhase._add_meta_data('mass_lower', val=0, units='lbm') -DescentPhase._add_meta_data('mass_upper', val=0, units='lbm') -DescentPhase._add_meta_data('mass_ref', val=1, units='lbm') -DescentPhase._add_meta_data('mass_ref0', val=0, units='lbm') -DescentPhase._add_meta_data('mass_defect_ref', val=None, units='lbm') -DescentPhase._add_meta_data('distance_lower', val=0, units='NM') -DescentPhase._add_meta_data('distance_upper', val=0, units='NM') -DescentPhase._add_meta_data('distance_ref', val=1, units='NM') -DescentPhase._add_meta_data('distance_ref0', val=0, units='NM') -DescentPhase._add_meta_data('distance_defect_ref', val=None, units='NM') -DescentPhase._add_meta_data('num_segments', val=None, units='unitless') -DescentPhase._add_meta_data('order', val=None, units='unitless') - # Adding initial guess metadata DescentPhase._add_initial_guess_meta_data( - InitialGuessIntegrationVariable(), - desc='initial guess for time options') + InitialGuessIntegrationVariable(), desc='initial guess for time options' +) DescentPhase._add_initial_guess_meta_data( - InitialGuessState('altitude'), - desc='initial guess for altitude state') + InitialGuessState('altitude'), desc='initial guess for altitude state' +) DescentPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass state') + InitialGuessState('mass'), desc='initial guess for mass state' +) DescentPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for distance state') + InitialGuessState('distance'), desc='initial guess for distance state' +) DescentPhase._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') + InitialGuessControl('throttle'), desc='initial guess for throttle' +) diff --git a/aviary/mission/gasp_based/phases/groundroll_phase.py b/aviary/mission/gasp_based/phases/groundroll_phase.py index d954b2c1bb..7e9e7ea471 100644 --- a/aviary/mission/gasp_based/phases/groundroll_phase.py +++ b/aviary/mission/gasp_based/phases/groundroll_phase.py @@ -1,10 +1,76 @@ from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessControl +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessIntegrationVariable, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic +class GroundrollPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=1, + desc='The number of segments in transcription creation in Dymos. ' + 'The default value is 1.', + ) + + self.declare( + name='order', + types=int, + default=3, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos. The default value is 3.', + ) + + defaults = { + 'mass_bounds': (0.0, 200_000.0), + 'mass_ref': 100_000.0, + 'mass_defect_ref': 100.0, + } + self.add_state_options('mass', units='lbm', defaults=defaults) + + defaults = { + 'time_duration_bounds': (1.0, 100.0), + } + self.add_time_options(units='s', defaults=defaults) + + # NOTE: All GASP phases before accel are in 'ft'. + defaults = { + 'distance_bounds': (0.0, 4000.0), + 'distance_ref': 3000.0, + } + self.add_state_options('distance', units='ft', defaults=defaults) + + defaults = { + 'velocity_bounds': (0.0, 1000.0), + 'velocity_ref': 100.0, + } + self.add_state_options('velocity', units='kn', defaults=defaults) + + # The options below have not yet been revamped. + + self.declare( + 'analytic', + types=bool, + default=False, + desc='When set to True, this is an analytic phase.', + ) + + self.declare( + name='t_init_gear', default=100.0, units='s', desc='Time where landing gear is lifted.' + ) + + self.declare( + name='t_init_flaps', default=100.0, units='s', desc='Time where flaps are retracted.' + ) + + class GroundrollPhase(PhaseBuilderBase): """ A phase builder for a groundroll phase in a mission simulation. @@ -24,125 +90,57 @@ class GroundrollPhase(PhaseBuilderBase): default_name = 'groundroll_phase' default_ode_class = GroundrollODE + default_options_class = GroundrollPhaseOptions - _meta_data_ = {} _initial_guesses_meta_data_ = {} def build_phase(self, aviary_options: AviaryValues = None): phase = self.phase = super().build_phase(aviary_options) - # Retrieve user options values - user_options = self.user_options - # Add the necessary get_val calls for each parameter, e.g., - fix_initial = user_options.get_val('fix_initial') - fix_initial_mass = user_options.get_val('fix_initial_mass') - connect_initial_mass = user_options.get_val('connect_initial_mass') - mass_lower = user_options.get_val('mass_lower', units='lbm') - mass_upper = user_options.get_val('mass_upper', units='lbm') - mass_ref = user_options.get_val('mass_ref', units='lbm') - mass_ref0 = user_options.get_val('mass_ref0', units='lbm') - mass_defect_ref = user_options.get_val('mass_defect_ref', units='lbm') - distance_lower = user_options.get_val('distance_lower', units='ft') - distance_upper = user_options.get_val('distance_upper', units='ft') - distance_ref = user_options.get_val('distance_ref', units='ft') - distance_ref0 = user_options.get_val('distance_ref0', units='ft') - distance_defect_ref = user_options.get_val('distance_defect_ref', units='ft') - # Add states - self.add_velocity_state(user_options) - - phase.add_state( - Dynamic.Mission.MASS, - fix_initial=fix_initial_mass, - input_initial=connect_initial_mass, - fix_final=False, - lower=mass_lower, - upper=mass_upper, - units="lbm", - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - ref=mass_ref, - defect_ref=mass_defect_ref, - ref0=mass_ref0, + self.add_state('velocity', Dynamic.Mission.VELOCITY, Dynamic.Mission.VELOCITY_RATE) + self.add_state( + 'mass', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, ) + self.add_state('distance', Dynamic.Mission.DISTANCE, Dynamic.Mission.DISTANCE_RATE) - phase.add_state( - Dynamic.Mission.DISTANCE, - fix_initial=fix_initial, - fix_final=False, - lower=distance_lower, - upper=distance_upper, - units="ft", - rate_source="distance_rate", - ref=distance_ref, - defect_ref=distance_defect_ref, - ref0=distance_ref0, - ) - - phase.add_parameter("t_init_gear", units="s", - static_target=True, opt=False, val=100) - phase.add_parameter("t_init_flaps", units="s", - static_target=True, opt=False, val=100) + phase.add_parameter('t_init_gear', units='s', static_target=True, opt=False, val=100) + phase.add_parameter('t_init_flaps', units='s', static_target=True, opt=False, val=100) # boundary/path constraints + controls # the final TAS is constrained externally to define the transition to the rotation # phase - phase.add_timeseries_output("time", units="s", output_name="time") - phase.add_timeseries_output(Dynamic.Mission.THRUST_TOTAL, units="lbf") + phase.add_timeseries_output('time', units='s', output_name='time') + phase.add_timeseries_output(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, units='lbf') - phase.add_timeseries_output("normal_force") - phase.add_timeseries_output(Dynamic.Mission.MACH) - phase.add_timeseries_output("EAS", units="kn") + phase.add_timeseries_output('normal_force') + phase.add_timeseries_output(Dynamic.Atmosphere.MACH) + phase.add_timeseries_output('EAS', units='kn') - phase.add_timeseries_output(Dynamic.Mission.LIFT) - phase.add_timeseries_output("CL") - phase.add_timeseries_output("CD") - phase.add_timeseries_output("fuselage_pitch", output_name="theta", units="deg") + phase.add_timeseries_output(Dynamic.Vehicle.LIFT) + phase.add_timeseries_output('CL') + phase.add_timeseries_output('CD') + phase.add_timeseries_output('fuselage_pitch', output_name='theta', units='deg') return phase -# Adding metadata for the GroundrollPhase -GroundrollPhase._add_meta_data( - 'analytic', val=False, desc='this is an analytic phase (no states).') -GroundrollPhase._add_meta_data('fix_initial', val=True) -GroundrollPhase._add_meta_data('fix_initial_mass', val=False) -GroundrollPhase._add_meta_data('connect_initial_mass', val=True) -GroundrollPhase._add_meta_data('duration_bounds', val=(1, 100), units='s') -GroundrollPhase._add_meta_data('duration_ref', val=1, units='s') -GroundrollPhase._add_meta_data('velocity_lower', val=0, units='kn') -GroundrollPhase._add_meta_data('velocity_upper', val=1000, units='kn') -GroundrollPhase._add_meta_data('velocity_ref', val=100, units='kn') -GroundrollPhase._add_meta_data('velocity_ref0', val=0, units='kn') -GroundrollPhase._add_meta_data('velocity_defect_ref', val=None, units='kn') -GroundrollPhase._add_meta_data('mass_lower', val=0, units='lbm') -GroundrollPhase._add_meta_data('mass_upper', val=200_000, units='lbm') -GroundrollPhase._add_meta_data('mass_ref', val=100_000, units='lbm') -GroundrollPhase._add_meta_data('mass_ref0', val=0, units='lbm') -GroundrollPhase._add_meta_data('mass_defect_ref', val=100, units='lbm') -GroundrollPhase._add_meta_data('distance_lower', val=0, units='ft') -GroundrollPhase._add_meta_data('distance_upper', val=4000, units='ft') -GroundrollPhase._add_meta_data('distance_ref', val=3000, units='ft') -GroundrollPhase._add_meta_data('distance_ref0', val=0, units='ft') -GroundrollPhase._add_meta_data('distance_defect_ref', val=3000, units='ft') -GroundrollPhase._add_meta_data('t_init_gear', val=100, units='s') -GroundrollPhase._add_meta_data('t_init_flaps', val=100, units='s') -GroundrollPhase._add_meta_data('num_segments', val=None, units='unitless') -GroundrollPhase._add_meta_data('order', val=None, units='unitless') - # Adding initial guess metadata GroundrollPhase._add_initial_guess_meta_data( - InitialGuessIntegrationVariable(), - desc='initial guess for time options') + InitialGuessIntegrationVariable(), desc='initial guess for time options' +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessState('velocity'), - desc='initial guess for true airspeed state') + InitialGuessState('velocity'), desc='initial guess for true airspeed state' +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass state') + InitialGuessState('mass'), desc='initial guess for mass state' +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for distance state') + InitialGuessState('distance'), desc='initial guess for distance state' +) GroundrollPhase._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') + InitialGuessControl('throttle'), desc='initial guess for throttle' +) diff --git a/aviary/mission/gasp_based/phases/rotation_phase.py b/aviary/mission/gasp_based/phases/rotation_phase.py index ebb04888ba..724c281a31 100644 --- a/aviary/mission/gasp_based/phases/rotation_phase.py +++ b/aviary/mission/gasp_based/phases/rotation_phase.py @@ -1,12 +1,114 @@ import numpy as np from aviary.mission.gasp_based.ode.rotation_ode import RotationODE -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessControl +from aviary.mission.initial_guess_builders import ( + InitialGuessControl, + InitialGuessIntegrationVariable, + InitialGuessState, +) from aviary.mission.phase_builder_base import PhaseBuilderBase +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Dynamic +class RotationPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=None, + desc='The number of segments in transcription creation in Dymos. ', + ) + + self.declare( + name='order', + types=int, + default=None, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos.', + ) + + defaults = { + 'mass_ref': 100_000.0, + 'mass_bounds': (0.0, 190_000.0), + } + self.add_state_options('mass', units='lbm', defaults=defaults) + + # NOTE: All GASP phases before accel are in 'ft'. + defaults = { + 'distance_ref': 3000.0, + 'distance_bounds': (0.0, 10.0e3), + } + self.add_state_options('distance', units='ft', defaults=defaults) + + defaults = { + 'velocity_ref': 100.0, + 'velocity_bounds': (0.0, 1000.0), + } + self.add_state_options('velocity', units='kn', defaults=defaults) + + defaults = { + 'angle_of_attack_defect_ref': 0.01, + 'angle_of_attack_bounds': (0.0, 25 * np.pi / 180), + } + self.add_state_options('angle_of_attack', units='rad', defaults=defaults) + + defaults = { + 'time_duration_bounds': (1.0, 100.0), + } + self.add_time_options(units='s', defaults=defaults) + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + # The options below have not yet been revamped. + + self.declare( + 'analytic', + types=bool, + default=False, + desc='When set to True, this is an analytic phase.', + ) + + self.declare( + name='normal_ref', + default=1.0, + units='lbf', + desc='Scale factor ref for the normal force constraint.', + ) + + self.declare( + name='normal_ref0', + default=0.0, + units='lbf', + desc='Scale factor ref0 for the normal force constraint.', + ) + + self.declare( + name='t_init_gear', default=100.0, units='s', desc='Time where landing gear is lifted.' + ) + + self.declare( + name='t_init_flaps', default=100.0, units='s', desc='Time where flaps are retracted.' + ) + + class RotationPhase(PhaseBuilderBase): """ A phase builder for a rotation phase in a 2-degree of freedom mission simulation. @@ -26,8 +128,8 @@ class RotationPhase(PhaseBuilderBase): default_name = 'rotation_phase' default_ode_class = RotationODE + default_options_class = RotationPhaseOptions - _meta_data_ = {} _initial_guesses_meta_data_ = {} def build_phase(self, aviary_options: AviaryValues = None): @@ -35,135 +137,62 @@ def build_phase(self, aviary_options: AviaryValues = None): # Retrieve user options values user_options = self.user_options - fix_initial = user_options.get_val('fix_initial') - angle_lower = user_options.get_val('angle_lower', units='rad') - angle_upper = user_options.get_val('angle_upper', units='rad') - angle_ref = user_options.get_val('angle_ref', units='rad') - angle_ref0 = user_options.get_val('angle_ref0', units='rad') - angle_defect_ref = user_options.get_val('angle_defect_ref', units='rad') - distance_lower = user_options.get_val('distance_lower', units='ft') - distance_upper = user_options.get_val('distance_upper', units='ft') - distance_ref = user_options.get_val('distance_ref', units='ft') - distance_ref0 = user_options.get_val('distance_ref0', units='ft') - distance_defect_ref = user_options.get_val('distance_defect_ref', units='ft') normal_ref = user_options.get_val('normal_ref', units='lbf') normal_ref0 = user_options.get_val('normal_ref0', units='lbf') # Add states - phase.add_state( - "alpha", - fix_initial=True, - fix_final=False, - lower=angle_lower, - upper=angle_upper, - units="rad", - rate_source="alpha_rate", - ref=angle_ref, - ref0=angle_ref0, - defect_ref=angle_defect_ref, - ) - - self.add_velocity_state(user_options) - - self.add_mass_state(user_options) - - phase.add_state( - Dynamic.Mission.DISTANCE, - fix_initial=fix_initial, - fix_final=False, - lower=distance_lower, - upper=distance_upper, - units="ft", - rate_source="distance_rate", - ref=distance_ref, - ref0=distance_ref0, - defect_ref=distance_defect_ref, + self.add_state('angle_of_attack', Dynamic.Vehicle.ANGLE_OF_ATTACK, 'angle_of_attack_rate') + self.add_state('velocity', Dynamic.Mission.VELOCITY, Dynamic.Mission.VELOCITY_RATE) + self.add_state( + 'mass', + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, ) + self.add_state('distance', Dynamic.Mission.DISTANCE, Dynamic.Mission.DISTANCE_RATE) # Add parameters - phase.add_parameter("t_init_gear", units="s", - static_target=True, opt=False, val=100) - phase.add_parameter("t_init_flaps", units="s", - static_target=True, opt=False, val=100) + phase.add_parameter('t_init_gear', units='s', static_target=True, opt=False, val=100) + phase.add_parameter('t_init_flaps', units='s', static_target=True, opt=False, val=100) # Add boundary constraints phase.add_boundary_constraint( - "normal_force", - loc="final", + 'normal_force', + loc='final', equals=0, - units="lbf", + units='lbf', ref=normal_ref, ref0=normal_ref0, ) # Add timeseries outputs - phase.add_timeseries_output(Dynamic.Mission.THRUST_TOTAL, units="lbf") - phase.add_timeseries_output("normal_force") - phase.add_timeseries_output(Dynamic.Mission.MACH) - phase.add_timeseries_output("EAS", units="kn") - phase.add_timeseries_output(Dynamic.Mission.LIFT) - phase.add_timeseries_output("CL") - phase.add_timeseries_output("CD") - phase.add_timeseries_output("fuselage_pitch", output_name="theta", units="deg") + phase.add_timeseries_output(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, units='lbf') + phase.add_timeseries_output('normal_force') + phase.add_timeseries_output(Dynamic.Atmosphere.MACH) + phase.add_timeseries_output('EAS', units='kn') + phase.add_timeseries_output(Dynamic.Vehicle.LIFT) + phase.add_timeseries_output('CL') + phase.add_timeseries_output('CD') + phase.add_timeseries_output('fuselage_pitch', output_name='theta', units='deg') return phase -# Adding metadata for the RotationPhase -RotationPhase._add_meta_data( - 'analytic', val=False, desc='this is an analytic phase (no states).') -RotationPhase._add_meta_data( - 'reserve', val=False, desc='this phase is part of the reserve mission.') -RotationPhase._add_meta_data( - 'target_distance', val={}, desc='the amount of distance traveled in this phase added as a constraint') -RotationPhase._add_meta_data( - 'target_duration', val={}, desc='the amount of time taken by this phase added as a constraint') -RotationPhase._add_meta_data('fix_initial', val=False) -RotationPhase._add_meta_data('duration_bounds', val=(1, 100), units='s') -RotationPhase._add_meta_data('duration_ref', val=1, units='s') -RotationPhase._add_meta_data('angle_lower', val=0.0, units='rad') # rad -RotationPhase._add_meta_data('angle_upper', val=25 * np.pi / 180, units='rad') # rad -RotationPhase._add_meta_data('angle_ref', val=1, units='rad') -RotationPhase._add_meta_data('angle_ref0', val=0, units='rad') -RotationPhase._add_meta_data('angle_defect_ref', val=0.01, units='rad') -RotationPhase._add_meta_data('velocity_lower', val=0, units='kn') -RotationPhase._add_meta_data('velocity_upper', val=1000, units='kn') -RotationPhase._add_meta_data('velocity_ref', val=100, units='kn') -RotationPhase._add_meta_data('velocity_ref0', val=0, units='kn') -RotationPhase._add_meta_data('velocity_defect_ref', val=None, units='kn') -RotationPhase._add_meta_data('mass_lower', val=0, units='lbm') -RotationPhase._add_meta_data('mass_upper', val=190_000, units='lbm') -RotationPhase._add_meta_data('mass_ref', val=100_000, units='lbm') -RotationPhase._add_meta_data('mass_ref0', val=0, units='lbm') -RotationPhase._add_meta_data('mass_defect_ref', val=None, units='lbm') -RotationPhase._add_meta_data('distance_lower', val=0, units='ft') -RotationPhase._add_meta_data('distance_upper', val=10.e3, units='ft') -RotationPhase._add_meta_data('distance_ref', val=3000, units='ft') -RotationPhase._add_meta_data('distance_ref0', val=0, units='ft') -RotationPhase._add_meta_data('distance_defect_ref', val=3000, units='ft') -RotationPhase._add_meta_data('normal_ref', val=1, units='lbf') -RotationPhase._add_meta_data('normal_ref0', val=0, units='lbf') -RotationPhase._add_meta_data('t_init_gear', val=100, units='s') -RotationPhase._add_meta_data('t_init_flaps', val=100, units='s') -RotationPhase._add_meta_data('num_segments', val=None, units='unitless') -RotationPhase._add_meta_data('order', val=None, units='unitless') - # Adding initial guess metadata RotationPhase._add_initial_guess_meta_data( - InitialGuessIntegrationVariable(), - desc='initial guess for time options') + InitialGuessIntegrationVariable(), desc='initial guess for time options' +) RotationPhase._add_initial_guess_meta_data( - InitialGuessState('alpha'), - desc='initial guess for angle of attack state') + InitialGuessState('angle_of_attack'), desc='initial guess for angle of attack state' +) RotationPhase._add_initial_guess_meta_data( - InitialGuessState('velocity'), - desc='initial guess for true airspeed state') + InitialGuessState('velocity'), desc='initial guess for true airspeed state' +) RotationPhase._add_initial_guess_meta_data( - InitialGuessState('mass'), - desc='initial guess for mass state') + InitialGuessState('mass'), desc='initial guess for mass state' +) RotationPhase._add_initial_guess_meta_data( - InitialGuessState('distance'), - desc='initial guess for distance state') + InitialGuessState('distance'), desc='initial guess for distance state' +) RotationPhase._add_initial_guess_meta_data( - InitialGuessControl('throttle'), - desc='initial guess for throttle') + InitialGuessControl('throttle'), desc='initial guess for throttle' +) diff --git a/aviary/mission/gasp_based/phases/test/test_v_rotate_comp.py b/aviary/mission/gasp_based/phases/test/test_v_rotate_comp.py deleted file mode 100644 index f166d8a7a2..0000000000 --- a/aviary/mission/gasp_based/phases/test/test_v_rotate_comp.py +++ /dev/null @@ -1,68 +0,0 @@ -import unittest - -import openmdao.api as om -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.constants import RHO_SEA_LEVEL_ENGLISH -from aviary.mission.gasp_based.phases.v_rotate_comp import VRotateComp -from aviary.variable_info.variables import Aircraft, Dynamic - - -class TestVRotateComp(unittest.TestCase): - """ - Test the computation of the speed at which takeoff rotation should be initiated - """ - - def test_partials(self): - prob = om.Problem() - - prob.model.add_subsystem("vrot_comp", VRotateComp(), promotes_inputs=[ - "*"], promotes_outputs=["*"]) - - prob.setup(force_alloc_complex=True) - - prob.set_val("dV1", val=10, units="kn") - prob.set_val("dVR", val=5, units="kn") - prob.set_val(Aircraft.Wing.AREA, val=1370, units="ft**2") - prob.set_val( - Dynamic.Mission.DENSITY, val=RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3" - ) - prob.set_val("CL_max", val=2.1886, units="unitless") - prob.set_val("mass", val=175_000, units="lbm") - - prob.run_model() - - # print(prob.get_val("Vrot", units="kn")) - - prob.check_partials(method='cs') - - -class TestVRotateComp2(unittest.TestCase): - """ - Test mass-weight conversion - """ - - def setUp(self): - import aviary.mission.gasp_based.phases.v_rotate_comp as vr - vr.GRAV_ENGLISH_LBM = 1.1 - - def tearDown(self): - import aviary.mission.gasp_based.phases.v_rotate_comp as vr - vr.GRAV_ENGLISH_LBM = 1.0 - - def test_partials(self): - prob = om.Problem() - prob.model.add_subsystem("vrot_comp", VRotateComp(), promotes_inputs=[ - "*"], promotes_outputs=["*"]) - prob.setup(force_alloc_complex=True) - prob.set_val("dV1", val=10, units="kn") - prob.set_val("dVR", val=5, units="kn") - prob.set_val(Aircraft.Wing.AREA, val=1370, units="ft**2") - prob.set_val( - Dynamic.Mission.DENSITY, val=RHO_SEA_LEVEL_ENGLISH, units="slug/ft**3" - ) - prob.set_val("CL_max", val=2.1886, units="unitless") - prob.set_val("mass", val=175_000, units="lbm") - - partial_data = prob.check_partials(method='cs') - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/mission/gasp_based/phases/time_integration_phases.py b/aviary/mission/gasp_based/phases/time_integration_phases.py deleted file mode 100644 index ca8a10f396..0000000000 --- a/aviary/mission/gasp_based/phases/time_integration_phases.py +++ /dev/null @@ -1,566 +0,0 @@ -import numpy as np - -from aviary.mission.gasp_based.ode.accel_ode import AccelODE -from aviary.mission.gasp_based.ode.ascent_ode import AscentODE -from aviary.mission.gasp_based.ode.climb_ode import ClimbODE -from aviary.mission.gasp_based.ode.descent_ode import DescentODE -from aviary.mission.gasp_based.ode.flight_path_ode import FlightPathODE -from aviary.mission.gasp_based.ode.groundroll_ode import GroundrollODE -from aviary.mission.gasp_based.ode.rotation_ode import RotationODE -from aviary.mission.gasp_based.ode.time_integration_base_classes import SimuPyProblem -from aviary.variable_info.enums import AlphaModes, AnalysisScheme, SpeedType, Verbosity -from aviary.variable_info.variables import Aircraft, Dynamic, Mission - - -class SGMGroundroll(SimuPyProblem): - ''' - This creates a subproblem for the groundroll phase of the trajectory that will - be solved using SGM. - Groundroll ends when TAS reaches rotation speed. - ''' - - def __init__( - self, - phase_name='groundroll', - VR_value=(143.1, 'kn'), - ode_args={}, - simupy_args={}, - ): - - super().__init__( - GroundrollODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args), - problem_name=phase_name, - outputs=["normal_force"], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, - ], - # state_units=['lbm','nmi','ft','ft/s'], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - **simupy_args, - ) - - self.phase_name = phase_name - self.VR_value = VR_value - self.add_trigger(Dynamic.Mission.VELOCITY, "VR_value") - - -class SGMRotation(SimuPyProblem): - ''' - This creates a subproblem for the rotation phase of the trajectory that will - be solved using SGM. - Rotation ends when the normal force on the runway reaches 0. - ''' - - def __init__( - self, - phase_name='rotation', - ode_args={}, - simupy_args={}, - ): - super().__init__( - RotationODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args), - problem_name=phase_name, - outputs=["normal_force", "alpha"], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, - ], - # state_units=['lbm','nmi','ft'], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - **simupy_args, - ) - - self.phase_name = phase_name - self.add_trigger("normal_force", 0, units='lbf') - - -# TODO : turn these into parameters? inputs? they need to match between -# ODE and SimuPy wrappers -load_factor_max = 1.10 -velocity_rate_safety = -np.inf # 100. -fuselage_pitch_max = 15.0 -gear_retraction_alt = 50.0 -flap_retraction_alt = 400.0 -ascent_termination_alt = 500.0 - - -class SGMAscent(SimuPyProblem): - ''' - This creates a subproblem for the ascent phase of the trajectory that will - be solved using SGM. - Ascent ends at ascent_termination_alt and retracts the gear and flaps at their - respective retraction altitudes. - ''' - - def __init__( - self, - phase_name='ascent', - alpha_mode=AlphaModes.DEFAULT, - ode_args={}, - simupy_args={}, - ): - controls = None - super().__init__( - AscentODE(analysis_scheme=AnalysisScheme.SHOOTING, - alpha_mode=alpha_mode, **ode_args), - problem_name=phase_name, - outputs=[ - "load_factor", - "fuselage_pitch", - "normal_force", - "alpha", - ], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, - Dynamic.Mission.FLIGHT_PATH_ANGLE, - "alpha", - ], - # state_units=['lbm','nmi','ft'], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - controls=controls, - **simupy_args, - ) - - self.phase_name = phase_name - self.event_channel_names = [ - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.ALTITUDE, - ] - self.num_events = len(self.event_channel_names) - - self.event_names = [ - "termination", - "flaps", - "gear", - ] - - def event_equation_function(self, t, x): - alpha = self.get_alpha(t, x) - self.ode0.set_val("alpha", alpha) - self.ode0.output_equation_function(t, x) - alt = self.ode0.get_val(Dynamic.Mission.ALTITUDE).squeeze() - return np.array( - [ - alt - ascent_termination_alt, - alt - flap_retraction_alt, - alt - gear_retraction_alt, - ] - ).squeeze() - - def update_equation_function(self, t, x, event_channels=None): - if 0 in event_channels: - self.output_nan = True - return x - elif 1 in event_channels: - if self.verbosity >= Verbosity.VERBOSE: - print("flaps!", t) - self.set_val("t_init_flaps", t) - elif 2 in event_channels: - if self.verbosity >= Verbosity.VERBOSE: - print("gear!", t) - self.set_val("t_init_gear", t) - else: - return np.nan * np.ones(self.dim_state) - return x - - -class SGMAscentCombined(SGMAscent): - ''' - This combines the different methods of limiting angle of attack to ensure that - none of the constraints are violated. - ''' - - def __init__( - self, - phase_name='ascent_combined', - fuselage_pitch_max=(0, 'deg'), - ode_args={}, - simupy_args={}, - ): - self.ode_args = ode_args - super().__init__(phase_name=phase_name, alpha_mode=AlphaModes.DEFAULT, - ode_args=ode_args, simupy_args=simupy_args) - - self.phase_name = phase_name - self.fuselage_pitch_max = fuselage_pitch_max - - ode0 = SGMAscent(alpha_mode=AlphaModes.DEFAULT, phase_name='ascent_ode0', - ode_args=ode_args, simupy_args=simupy_args) - rotation = SGMAscent(alpha_mode=AlphaModes.ROTATION, phase_name='ascent_rotation', - ode_args=ode_args, simupy_args=simupy_args) - load_factor = SGMAscent(alpha_mode=AlphaModes.LOAD_FACTOR, phase_name='ascent_load_factor', - ode_args=ode_args, simupy_args=simupy_args) - fuselage_pitch = SGMAscent(alpha_mode=AlphaModes.FUSELAGE_PITCH, phase_name='ascent_pitch', - ode_args=ode_args, simupy_args=simupy_args) - decel = SGMAscent(alpha_mode=AlphaModes.DECELERATION, phase_name='ascent_decel', - ode_args=ode_args, simupy_args=simupy_args) - - self.odes = (ode0, rotation, load_factor, fuselage_pitch, decel,) - ( - self.ode0, - self.rotation, - self.load_factor, - self.fuselage_pitch, - self.decel - ) = ( - ode0, rotation, load_factor, fuselage_pitch, decel, - ) - - self.set_val("t_init_flaps", 500.0, units='s') - self.set_val("t_init_gear", 500.0, units='s') - - self.ode_name = { - ode0: "ode0", - rotation: "rotation", - load_factor: "load_factor", - fuselage_pitch: "fuselage pitch", - decel: "decel" - } - - def prepare_to_integrate(self, t0, x0): - self.output_nan = False - self.alpha_cache = {} - self.prob_cache = {} - self.last_prob = self.rotation - for ode in self.odes[:]: - ode.prepare_to_integrate(t0, x0) - return self.output_equation_function(t0, x0) - # or can this just be done with prepare to integrate?? - - def set_val(self, *args, **kwargs): - for ode in self.odes: - ode.set_val(*args, **kwargs) - - def compute_alpha(self, ode, t, x): - return ode.output_equation_function(t, x)[list(ode.outputs.keys()).index("alpha")] - - def get_alpha(self, t, x): - a_key = (t,) + tuple(x) - # TODO: I think there's a pythonic way to do this - if a_key in self.alpha_cache: - alpha = self.alpha_cache[a_key] - else: - # in deriv.f, alpha from previous time-step is known and used as seed - # assume scheduled increment on alpha - # then check fuselage pitch, clip to max - # then check load factor, line search -alpha until satisfied - # then check end SPEED -- keep tas_rate = 0 if tas > vend - # (not implemented in gaspy) - # then check decel, line search -alpha until satisfied - (ode0, rotation, load_factor, fuselage_pitch, decel,) = self.odes - ode = self.last_prob - SATISFIED_CONSTRAINTS = False - for count in range(4): - alpha = self.compute_alpha(ode, t, x) - load_factor_val = ode.get_val("load_factor") - fuselage_pitch_val = ode.get_val("fuselage_pitch", units="deg") - velocity_rate_val = ode.get_val("velocity_rate") - if ( - (load_factor_val > load_factor_max) and not - np.isclose(load_factor_val, load_factor_max) - ): - print('*'*20, 'switching to load_factor', '*'*20) - ode = load_factor - continue - elif ( - (fuselage_pitch_val > fuselage_pitch_max) and not - np.isclose(fuselage_pitch_val, fuselage_pitch_max) - ): - print('*'*20, 'switching to fuselage_pitch', '*'*20) - ode = fuselage_pitch - continue - elif ( - (velocity_rate_val < velocity_rate_safety) and not - np.isclose(velocity_rate_val, velocity_rate_safety) - ): - print('*'*20, 'switching to decel', '*'*20) - ode = decel - continue - else: - if ( - np.isnan(load_factor_val) or - np.isnan(fuselage_pitch_val) or - np.isnan(velocity_rate_val) - ): - continue - SATISFIED_CONSTRAINTS = True - break - if SATISFIED_CONSTRAINTS: - self.alpha_cache[a_key] = alpha - self.prob_cache[a_key] = ode - self.last_prob = ode - else: - print("time :", t) - print("ode :", self.ode_name[ode]) - for key in ["load_factor", "fuselage_pitch", "velocity_rate"]: - print(key, ":", ode.get_val(key)) - raise ValueError("Ascent could not satisfy all constraints") - - return alpha - - def get_prob(self, t, x): - a_key = (t,) + tuple(x) - if a_key not in self.prob_cache: - self.get_alpha(t, x) - return self.prob_cache[a_key] - - def state_equation_function(self, t, x, u=None): - if np.any(np.isnan(x)): - return np.ones(self.dim_output) * np.nan - alpha = self.get_alpha(t, x) - prob = self.get_prob(t, x) - prob.set_val("alpha", alpha) - return prob.state_equation_function(t, x) - - @property - def compute_totals(self): - return self.get_prob(self.time, self.state).compute_totals - - def output_equation_function(self, t, x): - if np.any(np.isnan(x)) or self.output_nan: - return np.ones(self.dim_output) * np.nan - alpha = self.get_alpha(t, x) - prob = self.get_prob(t, x) - # I think always need to use ode0 and set alpha -- - # caching source problem doesn't necessarily save anything since you don't know - # it was the last compute. but maybe it's worth a shot? - # using solver may introduce slight variations depending on how it's walking or - # not? and need to have a real compute before compute totals - or does that mean - # use problem? - prob.set_val("alpha", alpha) - self.time = t - self.state = x - return prob.output_equation_function(t, x) - - -class SGMAccel(SimuPyProblem): - ''' - This creates a subproblem for the acceleration phase of the trajectory that will - be solved using SGM - ''' - - def __init__( - self, - phase_name='accel', - VC_value=250.0, - VC_units="kn", - ode_args={}, - simupy_args={}, - ): - ode = AccelODE(analysis_scheme=AnalysisScheme.SHOOTING, **ode_args) - super().__init__( - ode, - problem_name=phase_name, - outputs=["EAS", "mach", "alpha"], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, - ], - # state_units=['lbm','nmi','ft'], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - **simupy_args, - ) - - self.phase_name = phase_name - self.add_trigger("EAS", VC_value, units=VC_units) - - -class SGMClimb(SimuPyProblem): - ''' - This creates a subproblem for the climb phase of the trajectory that will - be solved using SGM - ''' - - def __init__( - self, - phase_name='climb', - input_speed_type=SpeedType.EAS, - input_speed_units="kn", - speed_trigger_units=None, - alt_trigger_units="ft", - ode_args={}, - simupy_args={}, - ): - ode = ClimbODE( - analysis_scheme=AnalysisScheme.SHOOTING, - input_speed_type=input_speed_type, - speed_trigger_units=speed_trigger_units, - alt_trigger_units=alt_trigger_units, - **ode_args, - ) - self.input_speed_type = input_speed_type - self.input_speed_units = input_speed_units - if input_speed_type is SpeedType.EAS: - self.speed_trigger_name = "mach" - elif input_speed_type is SpeedType.MACH: - self.speed_trigger_name = "TAS_violation" - else: - raise ValueError("bad speed type") - self.speed_trigger_units = speed_trigger_units - self.alt_trigger_units = alt_trigger_units - super().__init__( - ode, - problem_name=phase_name, - outputs=[ - "alpha", - Dynamic.Mission.FLIGHT_PATH_ANGLE, - "required_lift", - "lift", - "mach", - "EAS", - Dynamic.Mission.VELOCITY, - Dynamic.Mission.THRUST_TOTAL, - "drag", - Dynamic.Mission.ALTITUDE_RATE, - ], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - # state_units=['lbm','nmi','ft'], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - **simupy_args, - ) - - self.phase_name = phase_name - self.add_trigger(Dynamic.Mission.ALTITUDE, "alt_trigger", - units=self.alt_trigger_units) - self.add_trigger(self.speed_trigger_name, "speed_trigger", - units="speed_trigger_units") - - -class SGMCruise(SimuPyProblem): - ''' - This creates a subproblem for the cruise phase of the trajectory that will - be solved using SGM - ''' - - def __init__( - self, - phase_name='cruise', - alpha_mode=AlphaModes.DEFAULT, - input_speed_type=SpeedType.MACH, - input_speed_units="kn", - distance_trigger=(-1, 'ft'), - mass_trigger=(0, 'lbm'), - ode_args={}, - simupy_args={}, - ): - ode = FlightPathODE( - analysis_scheme=AnalysisScheme.SHOOTING, - alpha_mode=alpha_mode, - input_speed_type=input_speed_type, - clean=True, - **ode_args,) - - self.distance_trigger = distance_trigger - self.mass_trigger = mass_trigger - - super().__init__( - ode, - problem_name=phase_name, - outputs=[ - "alpha", # ? - "lift", - "EAS", - Dynamic.Mission.VELOCITY, - Dynamic.Mission.THRUST_TOTAL, - "drag", - Dynamic.Mission.ALTITUDE_RATE, - ], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.VELOCITY, - ], - # state_units=['lbm','nmi','ft'], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - **simupy_args, - ) - - self.phase_name = phase_name - self.add_trigger(Dynamic.Mission.DISTANCE, "distance_trigger") - self.add_trigger(Dynamic.Mission.MASS, 'mass_trigger') - - -class SGMDescent(SimuPyProblem): - ''' - This creates a subproblem for the descent phase of the trajectory that will - be solved using SGM - ''' - - def __init__( - self, - phase_name='descent', - input_speed_type=SpeedType.EAS, - input_speed_units="kn", - speed_trigger_units=None, - alt_trigger_units="ft", - ode_args={}, - simupy_args={}, - ): - ode = DescentODE( - analysis_scheme=AnalysisScheme.SHOOTING, - input_speed_type=input_speed_type, - speed_trigger_units=speed_trigger_units, - alt_trigger_units=alt_trigger_units, - **ode_args, - ) - self.input_speed_type = input_speed_type - self.input_speed_units = input_speed_units - if input_speed_type is SpeedType.MACH: - self.speed_trigger_name = "EAS" - elif input_speed_type is SpeedType.EAS: - self.speed_trigger_name = "TAS_violation" - else: - raise ValueError("bad speed type") - self.speed_trigger_units = speed_trigger_units - self.alt_trigger_units = alt_trigger_units - super().__init__( - ode, - problem_name=phase_name, - outputs=[ - "alpha", - "required_lift", - "lift", - "EAS", - Dynamic.Mission.VELOCITY, - Dynamic.Mission.THRUST_TOTAL, - "drag", - Dynamic.Mission.ALTITUDE_RATE, - ], - states=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DISTANCE, - Dynamic.Mission.ALTITUDE, - ], - # state_units=['lbm','nmi','ft'], - alternate_state_rate_names={ - Dynamic.Mission.MASS: Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL}, - **simupy_args, - ) - - self.phase_name = phase_name - self.add_trigger(Dynamic.Mission.ALTITUDE, "alt_trigger", - units=self.alt_trigger_units) - self.add_trigger(self.speed_trigger_name, "speed_trigger", - units=self.speed_trigger_units) diff --git a/aviary/mission/gasp_based/phases/time_integration_traj.py b/aviary/mission/gasp_based/phases/time_integration_traj.py deleted file mode 100644 index ff24eed025..0000000000 --- a/aviary/mission/gasp_based/phases/time_integration_traj.py +++ /dev/null @@ -1,114 +0,0 @@ -import numpy as np -from aviary.mission.gasp_based.ode.time_integration_base_classes import SGMTrajBase -from aviary.mission.gasp_based.phases.time_integration_phases import SGMGroundroll, SGMRotation -from aviary.variable_info.enums import Verbosity - - -class TimeIntegrationTrajBase(SGMTrajBase): - """Base class for time integration trajectory""" - - def initialize(self): - super().initialize() - self.options.declare("cruise_mach", default=0.8) - self.options.declare("ode_args", types=dict, default=dict()) - - -class FlexibleTraj(TimeIntegrationTrajBase): - ''' - A traj that can be given a list of phases to build flexible trajectories. - This is useful for simulating/testing phases one at a time as well as - allowing users to quickly redefine the phase order of the tracjectory. - ''' - - def initialize(self): - super().initialize() - self.options.declare('Phases', default=None) - self.options.declare('promote_all_auto_ivc', default=False) - self.options.declare('traj_intermediate_state_output', default=None) - self.options.declare('traj_final_state_output', default=None) - self.options.declare('traj_promote_final_output', default=None) - self.options.declare('traj_promote_initial_input', default=None) - self.options.declare('traj_initial_state_input', default=None) - self.options.declare('traj_event_trigger_input', default=None) - - def setup(self): - - ODEs = [] - for phase_name, phase_info in self.options['Phases'].items(): - kwargs = phase_info.get('kwargs', {}) - next_phase = phase_info['builder'](**kwargs) - next_phase.phase_name = phase_name - ODEs.append(next_phase) - - self.setup_params( - ODEs=ODEs, - promote_all_auto_ivc=self.options['promote_all_auto_ivc'], - traj_final_state_output=self.options['traj_final_state_output'], - traj_promote_final_output=self.options['traj_promote_final_output'], - - traj_promote_initial_input=self.options['traj_promote_initial_input'], - traj_initial_state_input=self.options['traj_initial_state_input'], - traj_event_trigger_input=self.options['traj_event_trigger_input'], - traj_intermediate_state_output=self.options['traj_intermediate_state_output'], - ) - self.declare_partials(["*"], ["*"],) - - def compute(self, inputs, outputs): - self.compute_params(inputs) - - for phase in self.ODEs: - phase_name = phase.phase_name - vals_to_set = self.options['Phases'][phase_name]['user_options'] - if vals_to_set: - for name, data in vals_to_set.items(): - var, units = data - if name.startswith('attr:'): - if isinstance(var, str): - val = np.squeeze(self.convert2units(var, inputs[var], units)) - data = (val, units) - setattr(phase, name.replace('attr:', ''), data) - elif name.startswith('rotation.'): - phase.rotation.set_val(name.replace( - 'rotation.', ''), var, units=units) - else: - phase.set_val(name, var, units=units) - - ode_index = 0 - sim_gen = self.compute_traj_loop(self.ODEs[0], inputs, outputs) - if self.verbosity >= Verbosity.BRIEF: - print('*'*40) - print('Starting: '+self.ODEs[ode_index].phase_name) - for current_problem, sim_result in sim_gen: - t_final = sim_result.t[-1] - x_final = sim_result.x[-1, :] - if type(current_problem) is SGMGroundroll: - t_start_rotation = t_final - - ode_index += 1 - try: - next_problem = self.ODEs[ode_index] - except IndexError: - next_problem = None - - if self.verbosity >= Verbosity.BRIEF: - print('Finished: '+current_problem.phase_name) - - if next_problem is not None: - if type(current_problem) is SGMGroundroll: - next_problem.prob.set_val("start_rotation", t_start_rotation) - elif type(current_problem) is SGMRotation: - next_problem.rotation.set_val("start_rotation", t_start_rotation) - - if self.verbosity >= Verbosity.BRIEF: - print('Starting: '+next_problem.phase_name) - sim_gen.send(next_problem) - else: - if self.verbosity >= Verbosity.BRIEF: - print('Reached the end of the Trajectory!') - sim_gen.close() - break - - if self.verbosity >= Verbosity.BRIEF: - print('t_final', t_final) - print('x_final', x_final) - print(self.ODEs[-1].states) diff --git a/aviary/mission/gasp_based/phases/twodof_phase.py b/aviary/mission/gasp_based/phases/twodof_phase.py new file mode 100644 index 0000000000..8159bc17da --- /dev/null +++ b/aviary/mission/gasp_based/phases/twodof_phase.py @@ -0,0 +1,302 @@ +import dymos as dm + +from aviary.mission.flight_phase_builder import FlightPhaseBase, register +from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_ode import UnsteadySolvedODE +from aviary.mission.initial_guess_builders import ( + InitialGuessIntegrationVariable, + InitialGuessPolynomialControl, + InitialGuessState, +) +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary +from aviary.utils.aviary_values import AviaryValues +from aviary.utils.utils import wrapped_convert_units +from aviary.variable_info.enums import EquationsOfMotion, SpeedType, ThrottleAllocation +from aviary.variable_info.variables import Dynamic + +# TODO: support/handle the following in the base class +# - phase.set_time_options() +# - currently handled in level 3 interface implementation +# - self.external_subsystems +# - self.meta_data, with cls.default_meta_data customization point + + +class TwoDOFPhaseOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + name='num_segments', + types=int, + default=1, + desc='The number of segments in transcription creation in Dymos. ' + 'The default value is 1.', + ) + + self.declare( + name='order', + types=int, + default=3, + desc='The order of polynomials for interpolation in the transcription ' + 'created in Dymos. The default value is 3.', + ) + + # TODO: These defaults aren't great, but need to keep things the same for now. + defaults = { + 'mass_ref': 1e4, + 'mass_defect_ref': 1e6, + 'mass_bounds': (0.0, None), + } + self.add_state_options('mass', units='kg', defaults=defaults) + + # TODO: These defaults aren't great, but need to keep things the same for now. + defaults = { + 'distance_ref': 1e6, + 'distance_defect_ref': 1e8, + 'distance_bounds': (0.0, None), + 'mass_bounds': (0.0, None), + } + self.add_state_options('distance', units='m', defaults=defaults) + + self.add_control_options('altitude', units='ft') + + # TODO: These defaults aren't great, but need to keep things the same for now. + defaults = { + 'mach_ref': 0.5, + } + self.add_control_options('mach', units='unitless', defaults=defaults) + + defaults = { + 'angle_of_attack_polynomial_order': 1, + 'angle_of_attack_optimize': True, + 'angle_of_attack_ref': 10.0, + 'angle_of_attack_bounds': (0.0, 15.0), + 'angle_of_attack_optimize': True, + 'angle_of_attack_initial': 0.0, + } + self.add_control_options('angle_of_attack', units='deg', defaults=defaults) + + self.add_time_options(units='ft') + + self.declare( + 'reserve', + types=bool, + default=False, + desc='Designate this phase as a reserve phase and contributes its fuel burn ' + 'towards the reserve mission fuel requirements. Reserve phases should be ' + 'be placed after all non-reserve phases in the phase_info.', + ) + + self.declare( + name='target_distance', + default=None, + units='m', + desc='The total distance traveled by the aircraft from takeoff to landing ' + 'for the primary mission, not including reserve missions. This value must ' + 'be positive.', + ) + + self.declare( + name='ground_roll', + types=bool, + default=False, + desc='Set to True only for phases where the aircraft is rolling on the ground. ' + 'All other phases of flight (climb, cruise, descent) this must be set to False.', + ) + + # The options below have not yet been revamped. + + self.declare( + name='required_available_climb_rate', + default=None, + units='ft/s', + desc='Adds a constraint requiring Dynamic.Mission.ALTITUDE_RATE_MAX to be no ' + 'smaller than required_available_climb_rate. This helps to ensure that the ' + 'propulsion system is large enough to handle emergency maneuvers at all points ' + 'throughout the flight envelope. Default value is None for no constraint.', + ) + + self.declare( + name='no_climb', + types=bool, + default=False, + desc='Set to True to prevent the aircraft from climbing during the phase. This option ' + 'can be used to prevent unexpected climb during a descent phase.', + ) + + self.declare( + name='no_descent', + types=bool, + default=False, + desc='Set to True to prevent the aircraft from descending during the phase. This ' + 'can be used to prevent unexpected descent during a climb phase.', + ) + + self.declare( + name='throttle_enforcement', + default='path_constraint', + values=['path_constraint', 'boundary_constraint', 'bounded', None], + desc='Flag to enforce engine throttle constraints on the path or at the segment ' + 'boundaries or using solver bounds.', + ) + + self.declare( + name='throttle_allocation', + default=ThrottleAllocation.FIXED, + values=[ + ThrottleAllocation.FIXED, + ThrottleAllocation.STATIC, + ThrottleAllocation.DYNAMIC, + ], + desc='Specifies how to handle the throttles for multiple engines. FIXED is a ' + 'user-specified value. STATIC is specified by the optimizer as one value for the ' + 'whole phase. DYNAMIC is specified by the optimizer at each point in the phase.', + ) + + self.declare( + name='constraints', + types=dict, + default={}, + desc="Add in custom constraints i.e. 'flight_path_angle': {'equals': -3., " + "'loc': 'initial', 'units': 'deg', 'type': 'boundary',}. For more details see " + '_add_user_defined_constraints().', + ) + + self.declare( + name='rotation', + types=bool, + default=False, + desc='Set to true if this is a rotation phase.', + ) + + self.declare( + name='clean', + types=bool, + default=False, + desc='Set to true to use clean aero with no ground effects.', + ) + + +@register +class TwoDOFPhase(FlightPhaseBase): + """A phase builder for a two degree of freedom (2DOF) phase.""" + + default_options_class = TwoDOFPhaseOptions + + def build_phase(self, aviary_options: AviaryValues = None): + """ + Return a new 2dof phase for analysis using these constraints. + + If ode_class is None, default_ode_class is used. + + If transcription is None, the return value from calling + make_default_transcription is used. + + Parameters + ---------- + aviary_options : AviaryValues () + collection of Aircraft/Mission specific options + + Returns + ------- + dymos.Phase + """ + self.ode_class = UnsteadySolvedODE + phase: dm.Phase = super().build_phase( + aviary_options, phase_type=EquationsOfMotion.SOLVED_2DOF + ) + + user_options = self.user_options + + time_units = 'ft' + initial = wrapped_convert_units(user_options['time_initial'], time_units) + duration = wrapped_convert_units(user_options['time_duration'], time_units) + initial_bounds = wrapped_convert_units(user_options['time_initial_bounds'], time_units) + duration_bounds = wrapped_convert_units(user_options['time_duration_bounds'], time_units) + initial_ref = wrapped_convert_units(user_options['time_initial_ref'], time_units) + duration_ref = wrapped_convert_units(user_options['time_duration_ref'], time_units) + rotation = user_options.get_val('rotation') + + fix_duration = duration is not None + fix_initial = initial is not None + + extra_options = {} + if not fix_initial: + extra_options = { + 'initial_bounds': initial_bounds, + 'initial_ref': initial_ref, + } + + if not fix_duration: + extra_options = { + 'duration_bounds': duration_bounds, + 'duration_ref': duration_ref, + } + + phase.set_time_options( + fix_initial=fix_initial, + fix_duration=fix_duration, + units=time_units, + name=Dynamic.Mission.DISTANCE, + **extra_options, + ) + + phase.set_state_options( + 'time', + rate_source='dt_dr', + fix_initial=fix_initial, + fix_final=False, + ref=100.0, + defect_ref=100.0, + ) + + if rotation: + self.add_control( + 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ) + + phase.add_timeseries_output('EAS', units='kn') + phase.add_timeseries_output(Dynamic.Mission.VELOCITY, units='kn') + phase.add_timeseries_output(Dynamic.Vehicle.LIFT) + phase.add_timeseries_output('thrust_req', units='lbf') + + return phase + + def make_default_transcription(self): + """Return a transcription object to be used by default in build_phase.""" + user_options = self.user_options + + num_segments = user_options['num_segments'] + order = user_options['order'] + + seg_ends, _ = dm.utils.lgl.lgl(num_segments + 1) + + transcription = dm.Radau( + num_segments=num_segments, order=order, compressed=True, segment_ends=seg_ends + ) + + return transcription + + def _extra_ode_init_kwargs(self): + """Return extra kwargs required for initializing the ODE.""" + # TODO: support external_subsystems and meta_data in the base class + return { + 'external_subsystems': self.external_subsystems, + 'meta_data': self.meta_data, + 'subsystem_options': self.subsystem_options, + 'input_speed_type': SpeedType.MACH, + 'clean': self.user_options.get_val('clean'), + 'ground_roll': self.user_options.get_val('ground_roll'), + 'throttle_enforcement': self.user_options.get_val('throttle_enforcement'), + } + + +TwoDOFPhase._add_initial_guess_meta_data( + InitialGuessIntegrationVariable(key='distance'), + desc='initial guess for initial distance and duration specified as a tuple', +) + +TwoDOFPhase._add_initial_guess_meta_data( + InitialGuessPolynomialControl('angle_of_attack'), + desc='initial guess for angle of attack', +) + +TwoDOFPhase._add_initial_guess_meta_data(InitialGuessState('time'), desc='initial guess for time') diff --git a/aviary/mission/gasp_based/phases/v_rotate_comp.py b/aviary/mission/gasp_based/phases/v_rotate_comp.py deleted file mode 100644 index 2c2b991be7..0000000000 --- a/aviary/mission/gasp_based/phases/v_rotate_comp.py +++ /dev/null @@ -1,62 +0,0 @@ -import openmdao.api as om - -from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH -from aviary.variable_info.functions import add_aviary_input -from aviary.variable_info.variables import Aircraft, Dynamic - - -class VRotateComp(om.ExplicitComponent): - """ - Component that computes V_rotate based on vehicle properties and speed buffers. - Note: This component is not used. - """ - - def setup(self): - # Temporarily set this to shape (1, 1) to avoid OpenMDAO bug - add_aviary_input(self, Dynamic.Mission.MASS, shape=(1, 1), units="lbm") - add_aviary_input( - self, - Dynamic.Mission.DENSITY, - shape=(1,), - units="slug/ft**3", - val=RHO_SEA_LEVEL_ENGLISH, - desc="sea-level atmospheric density", - ) - add_aviary_input(self, Aircraft.Wing.AREA, val=1.0) - self.add_input("CL_max", shape=(1,), units="unitless", - desc="Maximum lift coefficient") - self.add_input("dV1", shape=(1,), units="ft/s", - desc="Increment of engine failure decision speed above stall speed.") - self.add_input("dVR", shape=(1,), units="ft/s", - desc="Increment of takeoff rotation speed above engine failure decision speed.") - - self.add_output("Vrot", shape=(1,), units="ft/s", - desc="Speed at which takeoff rotation should be initiated.") - - # Constant partials - self.declare_partials(of="Vrot", wrt=["dV1", "dVR"], val=1.0) - # Partials of nonlinear terms - self.declare_partials( - of="Vrot", - wrt=[ - Dynamic.Mission.MASS, - Dynamic.Mission.DENSITY, - Aircraft.Wing.AREA, - "CL_max", - ], - ) - - def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - mass, rho, wing_area, CL_max, dV1, dVR = inputs.values() - outputs["Vrot"] = ((2 * mass * GRAV_ENGLISH_LBM) / - (rho * wing_area * CL_max))**0.5 + dV1 + dVR - - def compute_partials(self, inputs, partials, discrete_inputs=None): - mass, rho, wing_area, CL_max, dV1, dVR = inputs.values() - K = 0.5 * ((2 * mass * GRAV_ENGLISH_LBM) / - (rho * wing_area * CL_max)) ** 0.5 - - partials["Vrot", Dynamic.Mission.MASS] = K / mass - partials["Vrot", Dynamic.Mission.DENSITY] = -K / rho - partials["Vrot", Aircraft.Wing.AREA] = -K / wing_area - partials["Vrot", "CL_max"] = -K / CL_max diff --git a/aviary/mission/gasp_based/polynomial_fit.py b/aviary/mission/gasp_based/polynomial_fit.py index 747fc5ea52..2fabc71b72 100644 --- a/aviary/mission/gasp_based/polynomial_fit.py +++ b/aviary/mission/gasp_based/polynomial_fit.py @@ -1,6 +1,6 @@ import numpy as np -from numpy.polynomial import Polynomial import openmdao.api as om +from numpy.polynomial import Polynomial class PolynomialFit(om.ImplicitComponent): @@ -21,46 +21,41 @@ class PolynomialFit(om.ImplicitComponent): """ def initialize(self): - - self.options.declare("N_cp", types=int, desc="number of control point") + self.options.declare('N_cp', types=int, desc='number of control point') def setup(self): - # locations data up want to fit, which can # also be thought of as the "control points" # of the fit function - self.add_input("h_cp", shape=self.options["N_cp"], units="ft") - self.add_input("time_cp", shape=self.options["N_cp"], units="s") + self.add_input('h_cp', shape=self.options['N_cp'], units='ft') + self.add_input('time_cp', shape=self.options['N_cp'], units='s') - self.add_input("t_init_gear", 37.3, units="s") - self.add_output("h_init_gear", shape=1, units="ft") + self.add_input('t_init_gear', 37.3, units='s') + self.add_output('h_init_gear', shape=1, units='ft') - self.add_input("t_init_flaps", 47.5, units="s") - self.add_output("h_init_flaps", shape=1, units="ft") + self.add_input('t_init_flaps', 47.5, units='s') + self.add_output('h_init_flaps', shape=1, units='ft') # these are the coefficients of the polynomial function you are fitting - self.add_output("A", np.zeros(4)) # assuming a 5th order polynomial + self.add_output('A', np.zeros(4)) # assuming a 5th order polynomial # using CS here will give accurate partials, but will miss the sparsity pattern # issue #497 - self.declare_partials("*", "*", method="cs") + self.declare_partials('*', '*', method='cs') self.linear_solver = om.DirectSolver() def solve_nonlinear(self, inputs, outputs): - """ - Compute the outputs, given the inputs using the numpy fitting function. - """ - - X_cp = inputs["time_cp"] - Y_cp = inputs["h_cp"] + """Compute the outputs, given the inputs using the numpy fitting function.""" + X_cp = inputs['time_cp'] + Y_cp = inputs['h_cp'] # using the numpy fitting function because its faster and more stable polynomial = Polynomial.fit(X_cp, Y_cp, deg=3) coeffs = polynomial.convert().coef - outputs["A"][:] = coeffs + outputs['A'][:] = coeffs ( a0, @@ -69,28 +64,25 @@ def solve_nonlinear(self, inputs, outputs): a3, ) = coeffs - x_gear = inputs["t_init_gear"] - outputs["h_init_gear"] = a0 + a1 * x_gear + a2 * x_gear**2 + a3 * x_gear**3 + x_gear = inputs['t_init_gear'] + outputs['h_init_gear'] = a0 + a1 * x_gear + a2 * x_gear**2 + a3 * x_gear**3 - x_flaps = inputs["t_init_flaps"] - outputs["h_init_flaps"] = ( - a0 + a1 * x_flaps + a2 * x_flaps**2 + a3 * x_flaps**3 - ) + x_flaps = inputs['t_init_flaps'] + outputs['h_init_flaps'] = a0 + a1 * x_flaps + a2 * x_flaps**2 + a3 * x_flaps**3 def apply_nonlinear(self, inputs, outputs, residuals): - ( a0, a1, a2, a3, - ) = outputs["A"] + ) = outputs['A'] """ Compute the residuals """ - X_cp = inputs["time_cp"] - Y_cp = inputs["h_cp"] + X_cp = inputs['time_cp'] + Y_cp = inputs['h_cp'] Y_computed = a0 + a1 * X_cp + a2 * X_cp**2 + a3 * X_cp**3 @@ -100,20 +92,20 @@ def apply_nonlinear(self, inputs, outputs, residuals): # hence we differentiate the objective w.r.t A and set the resulting system of equations to 0 d_error__d_Y_computed = 2 * (Y_computed - Y_cp) - d_Y_computed__d_a0 = np.ones(self.options["N_cp"]) + d_Y_computed__d_a0 = np.ones(self.options['N_cp']) d_Y_computed__d_a1 = X_cp d_Y_computed__d_a2 = X_cp**2 d_Y_computed__d_a3 = X_cp**3 - residuals["A"][0] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a0) - residuals["A"][1] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a1) - residuals["A"][2] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a2) - residuals["A"][3] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a3) + residuals['A'][0] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a0) + residuals['A'][1] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a1) + residuals['A'][2] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a2) + residuals['A'][3] = np.sum(d_error__d_Y_computed * d_Y_computed__d_a3) - x_gear = inputs["t_init_gear"] + x_gear = inputs['t_init_gear'] h_gear = a0 + a1 * x_gear + a2 * x_gear**2 + a3 * x_gear**3 - residuals["h_init_gear"] = h_gear - outputs["h_init_gear"] + residuals['h_init_gear'] = h_gear - outputs['h_init_gear'] - x_flaps = inputs["t_init_flaps"] + x_flaps = inputs['t_init_flaps'] h_flaps = a0 + a1 * x_flaps + a2 * x_flaps**2 + a3 * x_flaps**3 - residuals["h_init_flaps"] = h_flaps - outputs["h_init_flaps"] + residuals['h_init_flaps'] = h_flaps - outputs['h_init_flaps'] diff --git a/aviary/mission/gasp_based/test/test_idle_descent_estimation.py b/aviary/mission/gasp_based/test/test_idle_descent_estimation.py deleted file mode 100644 index be6910d581..0000000000 --- a/aviary/mission/gasp_based/test/test_idle_descent_estimation.py +++ /dev/null @@ -1,88 +0,0 @@ -import unittest -import warnings -import importlib - -import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials - -from aviary.interface.default_phase_info.two_dof_fiti import descent_phases, add_default_sgm_args - -from aviary.mission.gasp_based.idle_descent_estimation import add_descent_estimation_as_submodel -from aviary.mission.gasp_based.ode.params import set_params_for_unit_tests -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.variable_info.variables import Aircraft, Dynamic, Settings -from aviary.utils.process_input_decks import create_vehicle -from aviary.utils.preprocessors import preprocess_propulsion -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems - - -@unittest.skipUnless(importlib.util.find_spec("pyoptsparse") is not None, "pyoptsparse is not installed") -class IdleDescentTestCase(unittest.TestCase): - """ - Test idle descent for 2DOF mission - """ - - def setUp(self): - input_deck = 'models/large_single_aisle_1/large_single_aisle_1_GwGm.csv' - aviary_inputs, _ = create_vehicle(input_deck) - aviary_inputs.set_val(Settings.VERBOSITY, 0) - aviary_inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, val=28690, units="lbf") - aviary_inputs.set_val(Dynamic.Mission.THROTTLE, val=0, units="unitless") - - engine = build_engine_deck(aviary_options=aviary_inputs) - preprocess_propulsion(aviary_inputs, engine) - - default_mission_subsystems = get_default_mission_subsystems( - 'GASP', build_engine_deck(aviary_inputs)) - - ode_args = dict(aviary_options=aviary_inputs, - core_subsystems=default_mission_subsystems) - - self.ode_args = ode_args - self.aviary_inputs = aviary_inputs - self.tol = 1e-5 - - add_default_sgm_args(descent_phases, self.ode_args) - self.phases = descent_phases - - def test_subproblem(self): - prob = om.Problem() - prob.model = om.Group() - - ivc = om.IndepVarComp() - ivc.add_output(Aircraft.Design.OPERATING_MASS, 97500, units='lbm') - ivc.add_output(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 36000, units='lbm') - ivc.add_output( - "parameters:interference_independent_of_shielded_area", 1.89927266) - ivc.add_output("parameters:drag_loss_due_to_shielded_wing_area", 68.02065834) - prob.model.add_subsystem('IVC', ivc, promotes=['*']) - - add_descent_estimation_as_submodel( - prob, - phases=self.phases, - ode_args=self.ode_args, - cruise_alt=35000, - reserve_fuel=4500, - all_subsystems=self.ode_args['core_subsystems'], - ) - prob.model.promotes('idle_descent_estimation', inputs=['parameters:*']) - - prob.setup() - - set_params_for_unit_tests(prob) - - warnings.filterwarnings('ignore', category=UserWarning) - prob.run_model() - warnings.filterwarnings('default', category=UserWarning) - - # Values obtained by running idle_descent_estimation - assert_near_equal(prob.get_val('descent_range', 'NM'), 98.38026813, self.tol) - assert_near_equal(prob.get_val('descent_fuel', 'lbm'), 250.84809336, self.tol) - - # TODO: check_partials() call results in runtime error: Jacobian in 'ODE_group' is not full rank. - # partial_data = prob.check_partials(out_stream=None, method="cs") - # assert_check_partials(partial_data, atol=0.0005, rtol=1e-9) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/mission/gasp_based/test/test_polynomial_fit.py b/aviary/mission/gasp_based/test/test_polynomial_fit.py index dc3893bd76..5ad0c2818a 100644 --- a/aviary/mission/gasp_based/test/test_polynomial_fit.py +++ b/aviary/mission/gasp_based/test/test_polynomial_fit.py @@ -5,40 +5,69 @@ from aviary.mission.gasp_based.polynomial_fit import PolynomialFit -X_cp = [45.0, 47.21906891, 50.28093109, 51.25, 51.25, 53.46906891, 56.53093109, 57.5, - 57.5, 59.71906891, 62.78093109, 63.75, 63.75, 65.96906891, 69.03093109, 70.0] -Y_cp = [0.0, 44.38137822, 105.61862178, 125.0, 125.0, 169.38137822, 230.61862178, 250.0, - 250.0, 294.38137822, 355.61862178, 375.0, 375.0, 419.38137822, 480.61862178, 500.0] +X_cp = [ + 45.0, + 47.21906891, + 50.28093109, + 51.25, + 51.25, + 53.46906891, + 56.53093109, + 57.5, + 57.5, + 59.71906891, + 62.78093109, + 63.75, + 63.75, + 65.96906891, + 69.03093109, + 70.0, +] +Y_cp = [ + 0.0, + 44.38137822, + 105.61862178, + 125.0, + 125.0, + 169.38137822, + 230.61862178, + 250.0, + 250.0, + 294.38137822, + 355.61862178, + 375.0, + 375.0, + 419.38137822, + 480.61862178, + 500.0, +] class PolynomialFitTest(unittest.TestCase): - """ - Test computation of initial gear time and initial flap time. - """ + """Test computation of initial gear time and initial flap time.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("polyfit", PolynomialFit(N_cp=16), promotes=["*"]) + self.prob.model.add_subsystem('polyfit', PolynomialFit(N_cp=16), promotes=['*']) - self.prob.model.set_input_defaults("time_cp", val=X_cp, units="s") - self.prob.model.set_input_defaults("h_cp", val=Y_cp, units="ft") - self.prob.model.set_input_defaults("t_init_gear", val=[15.0000001], units="s") - self.prob.model.set_input_defaults("t_init_flaps", val=[32.5000001], units="s") + self.prob.model.set_input_defaults('time_cp', val=X_cp, units='s') + self.prob.model.set_input_defaults('h_cp', val=Y_cp, units='ft') + self.prob.model.set_input_defaults('t_init_gear', val=[15.0000001], units='s') + self.prob.model.set_input_defaults('t_init_flaps', val=[32.5000001], units='s') newton = self.prob.model.nonlinear_solver = om.NewtonSolver() - newton.options["atol"] = 1e-6 - newton.options["rtol"] = 1e-6 - newton.options["iprint"] = 2 - newton.options["maxiter"] = 15 - newton.options["solve_subsystems"] = True - newton.options["max_sub_solves"] = 10 - newton.options["err_on_non_converge"] = True - newton.options["reraise_child_analysiserror"] = False + newton.options['atol'] = 1e-6 + newton.options['rtol'] = 1e-6 + newton.options['iprint'] = 2 + newton.options['maxiter'] = 15 + newton.options['solve_subsystems'] = True + newton.options['max_sub_solves'] = 10 + newton.options['err_on_non_converge'] = True + newton.options['reraise_child_analysiserror'] = False newton.linesearch = om.BoundsEnforceLS() - newton.linesearch.options["bound_enforcement"] = "scalar" - newton.linesearch.options["iprint"] = -1 - newton.options["err_on_non_converge"] = False + newton.linesearch.options['bound_enforcement'] = 'scalar' + newton.linesearch.options['iprint'] = -1 + newton.options['err_on_non_converge'] = False self.prob.model.linear_solver = om.DirectSolver(assemble_jac=True) @@ -51,9 +80,9 @@ def test_case1(self): self.prob.run_model() tol = 5e-4 - assert_near_equal(self.prob["h_init_gear"], -600, tol) - assert_near_equal(self.prob["h_init_flaps"], -250, tol) + assert_near_equal(self.prob['h_init_gear'], -600, tol) + assert_near_equal(self.prob['h_init_flaps'], -250, tol) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/height_energy_problem_configurator.py b/aviary/mission/height_energy_problem_configurator.py new file mode 100644 index 0000000000..5d8562b6e2 --- /dev/null +++ b/aviary/mission/height_energy_problem_configurator.py @@ -0,0 +1,658 @@ +from copy import deepcopy + +import numpy as np +import openmdao.api as om +from dymos.transcriptions.transcription_base import TranscriptionBase + +from aviary.mission.flight_phase_builder import FlightPhaseOptions +from aviary.mission.flops_based.phases.build_landing import Landing +from aviary.mission.flops_based.phases.build_takeoff import Takeoff +from aviary.mission.flops_based.phases.energy_phase import EnergyPhase +from aviary.mission.phase_builder_base import PhaseBuilderBase +from aviary.mission.problem_configurator import ProblemConfiguratorBase +from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.process_input_decks import initialization_guessing +from aviary.utils.utils import wrapped_convert_units +from aviary.variable_info.enums import LegacyCode, Verbosity +from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.mission.utils import process_guess_var + + +class HeightEnergyProblemConfigurator(ProblemConfiguratorBase): + """ + A Height-Energy specific builder that customizes AviaryProblem() for use with + height energy phases. + """ + + def initial_guesses(self, aviary_group): + """ + Set any initial guesses for variables in the aviary problem. + + This is called at the end of AivaryProblem.load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + # TODO: This should probably be moved to the set_initial_guesses() method in AviaryProblem class + # Defines how the problem should build it's initial guesses for load_inputs() + # this modifies mass_method, initialization_guesses, and aviary_values + + aviary_inputs = aviary_group.aviary_inputs + + if aviary_group.engine_builders is None: + aviary_group.engine_builders = [build_engine_deck(aviary_inputs)] + + aviary_group.initialization_guesses = initialization_guessing( + aviary_inputs, aviary_group.initialization_guesses, aviary_group.engine_builders + ) + + # Deal with missing defaults in phase info: + aviary_group.pre_mission_info.setdefault('include_takeoff', True) + aviary_group.pre_mission_info.setdefault('external_subsystems', []) + + aviary_group.post_mission_info.setdefault('include_landing', True) + aviary_group.post_mission_info.setdefault('external_subsystems', []) + + # Commonly referenced values + aviary_inputs.set_val( + Mission.Summary.GROSS_MASS, + val=aviary_group.initialization_guesses['actual_takeoff_mass'], + units='lbm', + ) + + if 'target_range' in aviary_group.post_mission_info: + aviary_inputs.set_val( + Mission.Summary.RANGE, + wrapped_convert_units(aviary_group.post_mission_info['target_range'], 'NM'), + units='NM', + ) + aviary_group.require_range_residual = True + aviary_group.target_range = wrapped_convert_units( + aviary_group.post_mission_info['target_range'], 'NM' + ) + else: + aviary_group.require_range_residual = False + # still instantiate target_range because it is used for default guesses + # for phase comps + aviary_group.target_range = aviary_inputs.get_val(Mission.Design.RANGE, units='NM') + + def get_default_phase_info(self, aviary_group): + """ + Return a default phase_info for this type or problem. + + The default phase_info is used in the level 1 and 2 interfaces when no + phase_info is specified. + + This is called during load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + + Returns + ------- + AviaryValues + General default phase_info. + """ + from aviary.models.missions.height_energy_default import phase_info + + return phase_info + + def get_code_origin(self, aviary_group): + """ + Return the legacy of this problem configurator. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + + Returns + ------- + LegacyCode + Code origin enum. + """ + return LegacyCode.FLOPS + + def add_takeoff_systems(self, aviary_group): + """ + Adds takeoff systems to the model in aviary_group. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + takeoff_options = Takeoff( + airport_altitude=0.0, # ft + num_engines=aviary_group.aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES), + ) + + # Build and add takeoff subsystem + takeoff = takeoff_options.build_phase(False) + aviary_group.add_subsystem( + 'takeoff', + takeoff, + promotes_inputs=['aircraft:*', 'mission:*'], + promotes_outputs=['mission:*'], + ) + + def get_phase_builder(self, aviary_group, phase_name, phase_options): + """ + Return a phase_builder for the requested phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + Name of the requested phase. + phase_options : dict + Phase options for the requested phase. + + Returns + ------- + PhaseBuilderBase + Phase builder for requested phase. + """ + if 'phase_builder' in phase_options: + phase_builder = phase_options['phase_builder'] + if not issubclass(phase_builder, PhaseBuilderBase): + raise TypeError( + 'phase_builder for the phase called ' + '{phase_name} must be a PhaseBuilderBase object.' + ) + else: + phase_builder = EnergyPhase + + return phase_builder + + def set_phase_options(self, aviary_group, phase_name, phase_idx, phase, user_options, comm): + """ + Set any necessary problem-related options on the phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + Name of the requested phase. + phase_idx : int + Phase position in aviary_group.phases. Can be used to identify first phase. + phase : Phase + Instantiated phase object. + user_options : dict + Subdictionary "user_options" from the phase_info. + comm : MPI.Comm or + MPI Communicator from OpenMDAO problem. + """ + time_units = 's' + initial = wrapped_convert_units(user_options['time_initial'], time_units) + duration = wrapped_convert_units(user_options['time_duration'], time_units) + initial_bounds = wrapped_convert_units(user_options['time_initial_bounds'], time_units) + duration_bounds = wrapped_convert_units(user_options['time_duration_bounds'], time_units) + initial_ref = wrapped_convert_units(user_options['time_initial_ref'], time_units) + duration_ref = wrapped_convert_units(user_options['time_duration_ref'], time_units) + + fix_initial = initial is not None + fix_duration = duration is not None + + # All follow-on phases. + input_initial = phase_idx > 0 + + # Figure out resonable refs if they aren't given. + if initial_ref == 1.0: + if initial_bounds[1]: + initial_ref = initial_bounds[1] + else: + # TODO: Why were we using this value? + initial_ref = 600.0 + + if duration_ref == 1.0: + # We have been using the average of the bounds if they exist. + lower, upper = duration_bounds + if lower is not None or upper is not None: + if lower is None: + lower = 0.0 + if upper is None: + upper = 0.0 + duration_ref = 0.5 * (lower + upper) + + if (fix_initial or input_initial) and comm.size == 1: + # Redundant on a fixed input (unless MPI); raises a warning if specified. + extra_options = {} + else: + extra_options = { + 'initial_ref': initial_ref, + 'initial_bounds': initial_bounds, + } + + if not fix_duration: + extra_options['duration_bounds'] = duration_bounds + extra_options['duration_ref'] = duration_ref + + phase.set_time_options( + fix_initial=fix_initial, + fix_duration=fix_duration, + units=time_units, + **extra_options, + ) + + def link_phases(self, aviary_group, phases, connect_directly=True): + """ + Apply any additional phase linking. + + Note that some phase variables are handled in the AviaryProblem. Only + problem-specific ones need to be linked here. + + This is called from AviaryProblem.link_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phases : Phase + Phases to be linked. + connect_directly : bool + When True, then connected=True. This allows the connections to be + handled by constraints if `phases` is a parallel group under MPI. + """ + # connect regular_phases with each other if you are optimizing alt or mach + self.link_phases_helper_with_options( + aviary_group, + aviary_group.regular_phases, + 'altitude_optimize', + Dynamic.Mission.ALTITUDE, + ref=1.0e4, + ) + self.link_phases_helper_with_options( + aviary_group, aviary_group.regular_phases, 'mach_optimize', Dynamic.Atmosphere.MACH + ) + + # connect reserve phases with each other if you are optimizing alt or mach + self.link_phases_helper_with_options( + aviary_group, + aviary_group.reserve_phases, + 'altitude_optimize', + Dynamic.Mission.ALTITUDE, + ref=1.0e4, + ) + self.link_phases_helper_with_options( + aviary_group, aviary_group.reserve_phases, 'mach_optimize', Dynamic.Atmosphere.MACH + ) + + # connect mass and distance between all phases regardless of reserve / + # non-reserve status + aviary_group.traj.link_phases( + phases, ['time'], ref=None if connect_directly else 1e3, connected=connect_directly + ) + aviary_group.traj.link_phases( + phases, + [Dynamic.Vehicle.MASS], + ref=None if connect_directly else 1e6, + connected=connect_directly, + ) + aviary_group.traj.link_phases( + phases, + [Dynamic.Mission.DISTANCE], + ref=None if connect_directly else 1e3, + connected=connect_directly, + ) + + # Under MPI, the states aren't directly connected. + if not connect_directly: + for phase_name in phases[1:]: + phase = aviary_group.traj._phases[phase_name] + phase.set_state_options(Dynamic.Vehicle.MASS, input_initial=False) + phase.set_state_options(Dynamic.Mission.DISTANCE, input_initial=False) + + phase = aviary_group.traj._phases[phases[0]] + + # Currently expects Distance to be an input. + phase.set_state_options(Dynamic.Mission.DISTANCE, input_initial=True) + + if aviary_group.pre_mission_info['include_takeoff']: + # Allow these to connect to outputs in the pre-mission takeoff system. + phase.set_state_options(Dynamic.Vehicle.MASS, input_initial=True) + + def check_trajectory(self, aviary_group): + """ + Checks the phase_info user options for any inconsistency. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + phase_info = aviary_group.mission_info + all_phases = [name for name in phase_info] + + stems = [ + Dynamic.Vehicle.MASS, + Dynamic.Mission.DISTANCE, + Dynamic.Atmosphere.MACH, + Dynamic.Mission.ALTITUDE, + ] + + msg = '' + for j in range(1, len(all_phases)): + left_name = all_phases[j - 1] + right_name = all_phases[j] + left = phase_info[left_name]['user_options'] + right = phase_info[right_name]['user_options'] + + for stem in stems: + final = left[f'{stem}_final'] + initial = right[f'{stem}_initial'] + + if initial[0] is None or final[0] is None: + continue + + if initial != final: + msg += ' Constraint mismatch across phase boundary:\n' + msg += f' {left_name} {stem}_final: {final}\n' + msg += f' {right_name} {stem}_initial: {initial}\n' + + if len(msg) > 0 and aviary_group.verbosity > Verbosity.QUIET: + print('\nThe following issues were detected in your phase_info options.') + print(msg, '\n') + + def add_post_mission_systems(self, aviary_group): + """ + Add any post mission systems. + + These may include any post-mission take off and landing systems. + + This is called from AviaryProblem.add_post_mission_systems + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + if aviary_group.pre_mission_info['include_takeoff']: + self._add_post_mission_takeoff_systems(aviary_group) + else: + first_flight_phase_name = list(aviary_group.mission_info.keys())[0] + + # Since we don't have the takeoff subsystem, we need to use the gross mass as the + # source for the mass at the beginning of the first flight phase. It turns out to be + # more robust to use a constraint rather than connecting it directly. + first_flight_phase = aviary_group.traj._phases[first_flight_phase_name] + first_flight_phase.set_state_options( + Dynamic.Vehicle.MASS, fix_initial=False, input_initial=False + ) + + # connect summary mass to the initial guess of mass in the first phase + eq = aviary_group.add_subsystem( + f'link_{first_flight_phase_name}_mass', + om.EQConstraintComp(), + promotes_inputs=[('rhs:mass', Mission.Summary.GROSS_MASS)], + ) + + # TODO: replace hard_coded ref for this constraint. + eq.add_eq_output( + 'mass', eq_units='lbm', normalize=False, ref=100000.0, add_constraint=True + ) + + aviary_group.connect( + f'traj.{first_flight_phase_name}.states:mass', + f'link_{first_flight_phase_name}_mass.lhs:mass', + src_indices=[0], + flat_src_indices=True, + ) + + if aviary_group.post_mission_info['include_landing']: + self._add_landing_systems(aviary_group) + + aviary_group.add_subsystem( + 'range_constraint', + om.ExecComp( + 'range_resid = target_range - actual_range', + target_range={'val': aviary_group.target_range, 'units': 'NM'}, + actual_range={'val': aviary_group.target_range, 'units': 'NM'}, + range_resid={'val': 30, 'units': 'NM'}, + ), + promotes_inputs=[ + ('actual_range', Mission.Summary.RANGE), + 'target_range', + ], + promotes_outputs=[('range_resid', Mission.Constraints.RANGE_RESIDUAL)], + ) + + # TODO: replace hard_coded ref for this constraint. + aviary_group.post_mission.add_constraint( + Mission.Constraints.MASS_RESIDUAL, equals=0.0, ref=1.0e5 + ) + + def _add_post_mission_takeoff_systems(self, aviary_group): + """ + Adds residual and constraint components for the mach and alpha connections from takeoff + to the first flight phase. + """ + first_flight_phase_name = list(aviary_group.mission_info.keys())[0] + phase_options = aviary_group.mission_info[first_flight_phase_name]['user_options'] + + aviary_group.connect( + Mission.Takeoff.FINAL_MASS, f'traj.{first_flight_phase_name}.initial_states:mass' + ) + aviary_group.connect( + Mission.Takeoff.GROUND_DISTANCE, + f'traj.{first_flight_phase_name}.initial_states:distance', + ) + + if phase_options.get('mach_optimize', False): + # Create an ExecComp to compute the difference in mach + mach_diff_comp = om.ExecComp( + 'mach_resid_for_connecting_takeoff = final_mach - initial_mach' + ) + aviary_group.add_subsystem('mach_diff_comp', mach_diff_comp) + + # Connect the inputs to the mach difference component + aviary_group.connect(Mission.Takeoff.FINAL_MACH, 'mach_diff_comp.final_mach') + aviary_group.connect( + f'traj.{first_flight_phase_name}.control_values:mach', + 'mach_diff_comp.initial_mach', + src_indices=[0], + ) + + # Add constraint for mach difference + aviary_group.add_constraint( + 'mach_diff_comp.mach_resid_for_connecting_takeoff', equals=0.0 + ) + + if phase_options.get('altitude_optimize', False): + # Similar steps for altitude difference + alt_diff_comp = om.ExecComp( + 'altitude_resid_for_connecting_takeoff = final_altitude - initial_altitude', + units='ft', + ) + aviary_group.add_subsystem('alt_diff_comp', alt_diff_comp) + + aviary_group.connect(Mission.Takeoff.FINAL_ALTITUDE, 'alt_diff_comp.final_altitude') + aviary_group.connect( + f'traj.{first_flight_phase_name}.control_values:altitude', + 'alt_diff_comp.initial_altitude', + src_indices=[0], + ) + + # Add constraint for altitude difference + aviary_group.add_constraint( + 'alt_diff_comp.altitude_resid_for_connecting_takeoff', equals=0.0 + ) + + def _add_landing_systems(self, aviary_group): + landing_options = Landing( + ref_wing_area=aviary_group.aviary_inputs.get_val(Aircraft.Wing.AREA, units='ft**2'), + Cl_max_ldg=aviary_group.aviary_inputs.get_val( + Mission.Landing.LIFT_COEFFICIENT_MAX + ), # no units + ) + + landing = landing_options.build_phase(False) + + aviary_group.add_subsystem( + 'landing', + landing, + promotes_inputs=['aircraft:*', 'mission:*'], + promotes_outputs=['mission:*'], + ) + + last_regular_phase = aviary_group.regular_phases[-1] + aviary_group.connect( + f'traj.{last_regular_phase}.states:mass', + Mission.Landing.TOUCHDOWN_MASS, + src_indices=[-1], + ) + aviary_group.connect( + f'traj.{last_regular_phase}.control_values:altitude', + Mission.Landing.INITIAL_ALTITUDE, + src_indices=[0], + ) + + def set_phase_initial_guesses( + self, aviary_group, phase_name, phase, guesses, target_prob, parent_prefix + ): + """ + Adds the initial guesses for each variable of a given phase to the problem. + + This method sets the initial guesses into the openmdao model for time, controls, states, + and problem-specific variables for a given phase. If using the GASP model, it also handles + some special cases that are not covered in the `phase_info` object. These include initial + guesses for mass, time, and distance, which are determined based on the phase name and + other mission-related variables. + + Parameters + ---------- + phase_name : str + The name of the phase for which the guesses are being added. + phase : Phase + The phase object for which the guesses are being added. + guesses : dict + A dictionary containing the initial guesses for the phase. + target_prob : Problem + Problem instance to apply the guesses. + parent_prefix : str + Location of this trajectory in the hierarchy. + """ + control_keys = ['mach', 'altitude'] + state_keys = ['mass', Dynamic.Mission.DISTANCE] + prob_keys = ['tau_gear', 'tau_flaps'] + + options = aviary_group.mission_info[phase_name]['user_options'] + + if options['throttle_enforcement'] == 'control': + control_keys.append('throttle') + + # Let's preserve the original user-specified initial conditions. + guess_dict = deepcopy(guesses) + + if 'mass' not in guess_dict: + mass_guess = aviary_group.aviary_inputs.get_val(Mission.Design.GROSS_MASS, units='lbm') + + guess_dict['mass'] = (mass_guess, 'lbm') + + if 'altitude' not in guess_dict: + # Use values from fixed endpoints. + altitude_initial = wrapped_convert_units(options['altitude_initial'], 'ft') + altitude_final = wrapped_convert_units(options['altitude_final'], 'ft') + + if altitude_initial is None: + # TODO: Pull from downstream phase. + altitude_initial = wrapped_convert_units(options['altitude_bounds'], 'ft')[0] + + if altitude_final is None: + # TODO: Pull from downstream phase. + altitude_final = altitude_initial + + guess_dict['altitude'] = ([altitude_initial, altitude_final], 'ft') + + if 'mach' not in guess_dict: + # Use values from fixed endpoints. + mach_initial = wrapped_convert_units(options['mach_initial'], 'unitless') + mach_final = wrapped_convert_units(options['mach_final'], 'unitless') + + if mach_initial is None: + # TODO: Pull from downstream phase. + mach_initial = wrapped_convert_units(options['mach_bounds'], 'unitless')[0] + + if mach_final is None: + # TODO: Pull from downstream phase. + mach_final = mach_initial + + guess_dict['mach'] = ([mach_initial, mach_final], 'unitless') + + if 'time' not in guess_dict: + # if time not in initial guesses, use the midpoints of any declared bounds. + initial = wrapped_convert_units(options['time_initial'], 's') + if initial is None: + initial_bounds = wrapped_convert_units(options['time_initial_bounds'], 's') + initial = np.mean(initial_bounds[0]) + duration = wrapped_convert_units(options['time_duration'], 's') + if duration is None: + duration_bounds = wrapped_convert_units(options['time_duration_bounds'], 's') + duration = np.mean(duration_bounds[0]) + + guess_dict['time'] = ([initial, duration], 's') + + for guess_key, guess_data in guess_dict.items(): + val, units = guess_data + + if 'time' == guess_key: + # Set initial guess for time variables + # Seems to be an openmdao bug. Switch to this when fixed. + # phase.set_time_val(initial=val[0], duration=val[1], units=units) + + if val[0] is not None: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.t_initial', val[0], units=units + ) + if val[1] is not None: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.t_duration', val[1], units=units + ) + + elif guess_key in control_keys: + # Set initial guess for control variables + # Seems to be an openmdao bug. Switch to this when fixed. + # phase.set_control_val(guess_key, val, units=units) + + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.controls:{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + + elif guess_key in state_keys: + # Set initial guess for state variables + # Seems to be an openmdao bug. Switch to this when fixed. + # phase.set_state_val(guess_key, val, units=units) + + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.states:{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + + elif guess_key in prob_keys: + target_prob.set_val(parent_prefix + guess_key, val, units=units) + + elif ':' in guess_key: + # These may come from external subsystems. + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + else: + # raise error if the guess key is not recognized + raise ValueError( + f'Initial guess key {guess_key} in {phase_name} is not recognized.' + ) diff --git a/aviary/mission/initial_guess_builders.py b/aviary/mission/initial_guess_builders.py index fba10b484d..402a879191 100644 --- a/aviary/mission/initial_guess_builders.py +++ b/aviary/mission/initial_guess_builders.py @@ -1,4 +1,4 @@ -''' +""" Define utilities for building phases. Classes @@ -17,30 +17,26 @@ InitialGuessIntegrationVariable : a utility for setting guesses for initial value and duration of an integration variable in a problem -''' +""" + from collections.abc import Sequence import dymos as dm import numpy as np import openmdao.api as om - - from dymos.transcriptions.transcription_base import TranscriptionBase -if hasattr(TranscriptionBase, 'setup_polynomial_controls'): - use_new_dymos_syntax = False -else: - use_new_dymos_syntax = True class InitialGuess: - ''' + """ Define a utility for setting an initial guess on a problem. Attributes ---------- key : str base name for the initial guess - ''' + """ + __slots__ = ('key',) def __init__(self, key): @@ -49,19 +45,14 @@ def __init__(self, key): def apply_initial_guess( self, prob: om.Problem, traj_name, phase: dm.Phase, phase_name, val, units ): - ''' - Set the initial guess on the problem. - ''' + """Set the initial guess on the problem.""" complete_key = self._get_complete_key(traj_name, phase_name) # TODO: this is a short term hack in need of an appropriate long term solution # - to interpolate, or not to interpolate: that is the question # - the solution should probably be a value decoration (a wrapper) that is # both lightweight and easy to check and unpack - if ( - isinstance(val, np.ndarray) - or (isinstance(val, Sequence) and not isinstance(val, str)) - ): + if isinstance(val, np.ndarray) or (isinstance(val, Sequence) and not isinstance(val, str)): val = phase.interp(self.key, val) try: @@ -71,9 +62,7 @@ def apply_initial_guess( prob.set_val(complete_key, val, units) def _get_complete_key(self, traj_name, phase_name): - ''' - Compose the complete key for setting the initial guess. - ''' + """Compose the complete key for setting the initial guess.""" _ = traj_name _ = phase_name @@ -81,89 +70,82 @@ def _get_complete_key(self, traj_name, phase_name): class InitialGuessControl(InitialGuess): - ''' + """ Define a utility for setting an initial guess for a control on a problem. Attributes ---------- key : str base name for the control - ''' + """ + __slots__ = () def _get_complete_key(self, traj_name, phase_name): - ''' - Compose the complete key for setting the control initial guess. - ''' + """Compose the complete key for setting the control initial guess.""" key = f'{traj_name}.{phase_name}.controls:{self.key}' return key class InitialGuessParameter(InitialGuess): - ''' + """ Define a utility for setting an initial guess for a parameter on a problem. Attributes ---------- key : str base name for the parameter - ''' + """ + __slots__ = () def _get_complete_key(self, traj_name, phase_name): - ''' - Compose the complete key for setting the parameter initial guess. - ''' + """Compose the complete key for setting the parameter initial guess.""" key = f'{traj_name}.{phase_name}.parameters:{self.key}' return key class InitialGuessPolynomialControl(InitialGuess): - ''' + """ Define a utility for setting an initial guess for a polynomial control on a problem. Attributes ---------- key : str base name for the polynomial control - ''' + """ + __slots__ = () def _get_complete_key(self, traj_name, phase_name): - ''' - Compose the complete key for setting the polynomial control initial guess. - ''' - if use_new_dymos_syntax: - key = f'{traj_name}.{phase_name}.controls:{self.key}' - else: - key = f'{traj_name}.{phase_name}.polynomial_controls:{self.key}' + """Compose the complete key for setting the polynomial control initial guess.""" + key = f'{traj_name}.{phase_name}.controls:{self.key}' return key class InitialGuessState(InitialGuess): - ''' + """ Define a utility for setting an initial guess for a state on a problem. Attributes ---------- key : str base name for the state - ''' + """ + __slots__ = () def _get_complete_key(self, traj_name, phase_name): - ''' - Compose the complete key for setting the state initial guess. - ''' + """Compose the complete key for setting the state initial guess.""" key = f'{traj_name}.{phase_name}.states:{self.key}' return key class InitialGuessIntegrationVariable(InitialGuess): - ''' + """ Define a utility for setting guesses for the initial and duration values for the integration variable, usually time. We might also use this for other integration variables, such as velocity or distance. @@ -174,7 +156,8 @@ class InitialGuessIntegrationVariable(InitialGuess): ---------- key : str ('time') the group identifier for guesses for initial integration variable value and duration - ''' + """ + __slots__ = () def __init__(self, key='time'): diff --git a/aviary/mission/ode/altitude_rate.py b/aviary/mission/ode/altitude_rate.py index 30c045c1d6..f5aee021b7 100644 --- a/aviary/mission/ode/altitude_rate.py +++ b/aviary/mission/ode/altitude_rate.py @@ -8,7 +8,7 @@ class AltitudeRate(om.ExplicitComponent): """ Rutowski "Energy Approach to the General Aircraft Performance Problem", doi 10.2514/8.2956 - Equation 6 + Equation 6. """ def initialize(self): @@ -16,17 +16,30 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - self.add_input(Dynamic.Mission.SPECIFIC_ENERGY_RATE, val=np.ones( - nn), desc='current specific power', units='m/s') - self.add_input(Dynamic.Mission.VELOCITY_RATE, val=np.ones( - nn), desc='current acceleration', units='m/s**2') + self.add_input( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + val=np.ones(nn), + desc='current specific power', + units='m/s', + ) + self.add_input( + Dynamic.Mission.VELOCITY_RATE, + val=np.ones(nn), + desc='current acceleration', + units='m/s**2', + ) self.add_input( Dynamic.Mission.VELOCITY, val=np.ones(nn), desc='current velocity', - units='m/s') - self.add_output(Dynamic.Mission.ALTITUDE_RATE, val=np.ones( - nn), desc='current climb rate', units='m/s') + units='m/s', + ) + self.add_output( + Dynamic.Mission.ALTITUDE_RATE, + val=np.ones(nn), + desc='current climb rate', + units='m/s', + ) def compute(self, inputs, outputs): gravity = constants.GRAV_METRIC_FLOPS @@ -34,18 +47,23 @@ def compute(self, inputs, outputs): acceleration = inputs[Dynamic.Mission.VELOCITY_RATE] velocity = inputs[Dynamic.Mission.VELOCITY] - outputs[Dynamic.Mission.ALTITUDE_RATE] = \ + outputs[Dynamic.Mission.ALTITUDE_RATE] = ( specific_power - (velocity * acceleration) / gravity + ) def setup_partials(self): arange = np.arange(self.options['num_nodes']) - self.declare_partials(Dynamic.Mission.ALTITUDE_RATE, - [Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.VELOCITY_RATE, - Dynamic.Mission.VELOCITY], - rows=arange, - cols=arange, - val=1) + self.declare_partials( + Dynamic.Mission.ALTITUDE_RATE, + [ + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.VELOCITY_RATE, + Dynamic.Mission.VELOCITY, + ], + rows=arange, + cols=arange, + val=1, + ) def compute_partials(self, inputs, J): gravity = constants.GRAV_METRIC_FLOPS diff --git a/aviary/mission/ode/specific_energy_rate.py b/aviary/mission/ode/specific_energy_rate.py index 41002d0df7..95d12ad54b 100644 --- a/aviary/mission/ode/specific_energy_rate.py +++ b/aviary/mission/ode/specific_energy_rate.py @@ -1,5 +1,6 @@ import numpy as np import openmdao.api as om + from aviary.constants import GRAV_METRIC_FLOPS as gravity from aviary.variable_info.variables import Dynamic @@ -7,7 +8,7 @@ class SpecificEnergyRate(om.ExplicitComponent): """ Rutowski "Energy Approach to the General Aircraft Performance Problem", doi 10.2514/8.2956 - Equation 5 + Equation 5. """ def initialize(self): @@ -20,50 +21,56 @@ def setup(self): Dynamic.Mission.VELOCITY, val=np.ones(nn), desc='current velocity', - units='m/s') + units='m/s', + ) + self.add_input(Dynamic.Vehicle.MASS, val=np.ones(nn), desc='current mass', units='kg') self.add_input( - Dynamic.Mission.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.ones(nn), - desc='current mass', - units='kg') - self.add_input(Dynamic.Mission.THRUST_TOTAL, val=np.ones(nn), - desc='current thrust', units='N') - self.add_input( - Dynamic.Mission.DRAG, + desc='current thrust', + units='N', + ) + self.add_input(Dynamic.Vehicle.DRAG, val=np.ones(nn), desc='current drag', units='N') + self.add_output( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, val=np.ones(nn), - desc='current drag', - units='N') - self.add_output(Dynamic.Mission.SPECIFIC_ENERGY_RATE, val=np.ones( - nn), desc='current specific power', units='m/s') + desc='current specific power', + units='m/s', + ) def compute(self, inputs, outputs): velocity = inputs[Dynamic.Mission.VELOCITY] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] - weight = inputs[Dynamic.Mission.MASS] * gravity - outputs[Dynamic.Mission.SPECIFIC_ENERGY_RATE] = velocity * \ - (thrust - drag) / weight + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * gravity + outputs[Dynamic.Mission.SPECIFIC_ENERGY_RATE] = velocity * (thrust - drag) / weight def setup_partials(self): arange = np.arange(self.options['num_nodes']) - self.declare_partials(Dynamic.Mission.SPECIFIC_ENERGY_RATE, - [Dynamic.Mission.VELOCITY, - Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.DRAG], - rows=arange, - cols=arange) + self.declare_partials( + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + [ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.DRAG, + ], + rows=arange, + cols=arange, + ) def compute_partials(self, inputs, J): velocity = inputs[Dynamic.Mission.VELOCITY] - thrust = inputs[Dynamic.Mission.THRUST_TOTAL] - drag = inputs[Dynamic.Mission.DRAG] - weight = inputs[Dynamic.Mission.MASS] * gravity + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] + drag = inputs[Dynamic.Vehicle.DRAG] + weight = inputs[Dynamic.Vehicle.MASS] * gravity - J[Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.VELOCITY] = (thrust - drag) / weight - J[Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.THRUST_TOTAL] = velocity / weight - J[Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.DRAG] = -velocity / weight - J[Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.MASS] = -gravity\ - * velocity * (thrust - drag) / (weight)**2 + J[Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Mission.VELOCITY] = (thrust - drag) / weight + J[ + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + ] = velocity / weight + J[Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Vehicle.DRAG] = -velocity / weight + J[Dynamic.Mission.SPECIFIC_ENERGY_RATE, Dynamic.Vehicle.MASS] = ( + -gravity * velocity * (thrust - drag) / (weight) ** 2 + ) diff --git a/aviary/mission/ode/test/test_altitude_rate.py b/aviary/mission/ode/test/test_altitude_rate.py index e6d33d5483..1caa25f001 100644 --- a/aviary/mission/ode/test/test_altitude_rate.py +++ b/aviary/mission/ode/test/test_altitude_rate.py @@ -4,8 +4,7 @@ from aviary.mission.ode.altitude_rate import AltitudeRate from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import \ - data +from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import data from aviary.validation_cases.validation_tests import do_validation_test from aviary.variable_info.variables import Dynamic @@ -26,20 +25,23 @@ def setUp(self): prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - - do_validation_test(self.prob, - 'full_mission_test_data', - input_validation_data=data, - output_validation_data=data, - input_keys=[Dynamic.Mission.SPECIFIC_ENERGY_RATE, - Dynamic.Mission.VELOCITY, - Dynamic.Mission.VELOCITY_RATE], - output_keys=Dynamic.Mission.ALTITUDE_RATE, - tol=1e-9) + do_validation_test( + self.prob, + 'full_mission_test_data', + input_validation_data=data, + output_validation_data=data, + input_keys=[ + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Mission.VELOCITY, + Dynamic.Mission.VELOCITY_RATE, + ], + output_keys=Dynamic.Mission.ALTITUDE_RATE, + tol=1e-9, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/ode/test/test_specific_energy_rate.py b/aviary/mission/ode/test/test_specific_energy_rate.py index 3618e4c298..f1b9c600a4 100644 --- a/aviary/mission/ode/test/test_specific_energy_rate.py +++ b/aviary/mission/ode/test/test_specific_energy_rate.py @@ -4,8 +4,7 @@ from aviary.mission.ode.specific_energy_rate import SpecificEnergyRate from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import \ - data +from aviary.validation_cases.validation_data.flops_data.full_mission_test_data import data from aviary.validation_cases.validation_tests import do_validation_test from aviary.variable_info.variables import Dynamic @@ -17,7 +16,7 @@ def setUp(self): time, _ = data.get_item('time') prob.model.add_subsystem( - "specific_energy_rate", + 'specific_energy_rate', SpecificEnergyRate(num_nodes=len(time)), promotes_inputs=['*'], promotes_outputs=['*'], @@ -26,21 +25,24 @@ def setUp(self): prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - - do_validation_test(self.prob, - 'full_mission_test_data', - input_validation_data=data, - output_validation_data=data, - input_keys=[Dynamic.Mission.DRAG, - Dynamic.Mission.MASS, - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.VELOCITY], - output_keys=Dynamic.Mission.SPECIFIC_ENERGY_RATE, - tol=1e-12) + do_validation_test( + self.prob, + 'full_mission_test_data', + input_validation_data=data, + output_validation_data=data, + input_keys=[ + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.MASS, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Mission.VELOCITY, + ], + output_keys=Dynamic.Mission.SPECIFIC_ENERGY_RATE, + tol=1e-12, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/mission/phase_builder_base.py b/aviary/mission/phase_builder_base.py index 11375cee4d..43b1d1aad0 100644 --- a/aviary/mission/phase_builder_base.py +++ b/aviary/mission/phase_builder_base.py @@ -1,44 +1,42 @@ -''' +""" Define utilities for building phases. Classes ------- PhaseBuilderBase : the interface for a phase builder -''' +""" + from abc import ABC from collections import namedtuple import dymos as dm import openmdao.api as om +import numpy as np -from aviary.mission.flops_based.ode.mission_ODE import MissionODE +from aviary.mission.flops_based.ode.energy_ODE import EnergyODE from aviary.mission.initial_guess_builders import InitialGuess from aviary.utils.aviary_values import AviaryValues, get_keys -from aviary.variable_info.variables import Dynamic from aviary.variable_info.variable_meta_data import _MetaData +from aviary.variable_info.variables import Dynamic - -_require_new_meta_data_class_attr_ = \ - namedtuple('_require_new_meta_data_class_attr_', ()) - - -_require_new_initial_guesses_meta_data_class_attr_ = \ - namedtuple('_require_new_initial_guesses_meta_data_class_attr_', ()) +_require_new_initial_guesses_meta_data_class_attr_ = namedtuple( + '_require_new_initial_guesses_meta_data_class_attr_', () +) class PhaseBuilderBase(ABC): - ''' + """ Define the interface for a phase builder. Attributes ---------- - name : str ('') + name : str ('_unknown phase_') object label core_subsystems : (None) list of SubsystemBuilderBase objects that will be added to the phase ODE - user_options : AviaryValues () + user_options : OptionsDictionary () state/path constraint values and flags initial_guesses : AviaryValues () @@ -62,6 +60,10 @@ class attribute: derived type customization point; the default value class attribute: derived type customization point; the default value for ode_class used by build_phase + default_options_class : type + class attribute: derived type customization point; the default class + containing the phase options options_dictionary + is_analytic_phase : bool (False) class attribute: derived type customization point; if True, build_phase will return an AnalyticPhase instead of a Phase @@ -74,30 +76,45 @@ class attribute: derived type customization point; the default value ------- build_phase make_default_transcription - validate_options - assign_default_options - ''' + """ + __slots__ = ( - 'name', 'core_subsystems', 'subsystem_options', 'user_options', - 'initial_guesses', 'ode_class', 'transcription', - 'is_analytic_phase', 'num_nodes', 'external_subsystems', 'meta_data', + 'name', + 'core_subsystems', + 'external_subsystems', + 'subsystem_options', + 'user_options', + 'initial_guesses', + 'ode_class', + 'transcription', + 'is_analytic_phase', + 'num_nodes', + 'meta_data', ) - # region : derived type customization points - _meta_data_ = _require_new_meta_data_class_attr_() - _initial_guesses_meta_data_ = _require_new_initial_guesses_meta_data_class_attr_() - default_name = '' + default_name = '_unknown phase_' - default_ode_class = MissionODE + default_ode_class = EnergyODE + default_options_class = om.OptionsDictionary default_meta_data = _MetaData # endregion : derived type customization points def __init__( - self, name=None, core_subsystems=None, user_options=None, initial_guesses=None, - ode_class=None, transcription=None, subsystem_options=None, is_analytic_phase=False, num_nodes=5, external_subsystems=None, meta_data=None, + self, + name=None, + core_subsystems=None, + external_subsystems=None, + user_options=None, + initial_guesses=None, + ode_class=None, + transcription=None, + subsystem_options=None, + is_analytic_phase=False, + num_nodes=5, + meta_data=None, ): if name is None: name = self.default_name @@ -106,17 +123,18 @@ def __init__( if core_subsystems is None: core_subsystems = [] + if external_subsystems is None: + external_subsystems = [] self.core_subsystems = core_subsystems + self.external_subsystems = external_subsystems if subsystem_options is None: subsystem_options = {} self.subsystem_options = subsystem_options - self.user_options = user_options - self.validate_options() - self.assign_default_options() + self.user_options = self.default_options_class(user_options) if initial_guesses is None: initial_guesses = AviaryValues() @@ -140,7 +158,7 @@ def __init__( self.meta_data = meta_data def build_phase(self, aviary_options=None): - ''' + """ Return a new phase object for analysis using these constraints. If ode_class is None, default_ode_class is used. @@ -156,7 +174,7 @@ def build_phase(self, aviary_options=None): Returns ------- dymos.Phase - ''' + """ ode_class = self.ode_class if ode_class is None: @@ -172,10 +190,7 @@ def build_phase(self, aviary_options=None): kwargs = self._extra_ode_init_kwargs() - kwargs = { - 'aviary_options': aviary_options, - **kwargs - } + kwargs = {'aviary_options': aviary_options, **kwargs} subsystem_options = self.subsystem_options @@ -183,6 +198,7 @@ def build_phase(self, aviary_options=None): kwargs['subsystem_options'] = subsystem_options kwargs['core_subsystems'] = self.core_subsystems + kwargs['external_subsystems'] = self.external_subsystems if self.is_analytic_phase: phase = dm.AnalyticPhase( @@ -192,78 +208,41 @@ def build_phase(self, aviary_options=None): ) else: phase = dm.Phase( - ode_class=ode_class, transcription=transcription, - ode_init_kwargs=kwargs + ode_class=ode_class, transcription=transcription, ode_init_kwargs=kwargs ) + # Add a timeseries for the "mission bus variables" that will be a uniform grid, using Falck Magik™. + # https://stackoverflow.com/questions/67771242/openmdao-dymos-interpolate-the-results-of-a-phase-onto-an-equispaced-grid + if self.is_analytic_phase: + tx_mission_bus = dm.GaussLobatto(num_segments=self.num_nodes, order=3, compressed=True) + else: + tx_mission_bus = dm.GaussLobatto( + num_segments=transcription.options['num_segments'], order=3, compressed=True + ) + phase.add_timeseries( + name='mission_bus_variables', transcription=tx_mission_bus, subset='all' + ) + # overrides should add state, controls, etc. return phase def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' + """Return a transcription object to be used by default in build_phase.""" user_options = self.user_options - num_segments, _ = user_options.get_item('num_segments') - order, _ = user_options.get_item('order') + num_segments = user_options['num_segments'] + order = user_options['order'] - transcription = dm.Radau( - num_segments=num_segments, order=order, compressed=True) + transcription = dm.Radau(num_segments=num_segments, order=order, compressed=True) return transcription - def validate_options(self): - ''' - Raise TypeError if an unsupported option is found. - - Users can call this method when updating options after initialization. - ''' - user_options = self.user_options - - if not user_options: - return # acceptable - - meta_data = self._meta_data_ - - for key in get_keys(user_options): - if key not in meta_data: - raise TypeError( - f'{self.__class__.__name__}: {self.name}:' - f' unsupported option: {key}' - ) - - def assign_default_options(self): - ''' - Update missing options with default values. - - If user_options is None, start with an empty AviaryValues. - - Users can call this method when replacing the user_options member after - initialization. - ''' - user_options = self.user_options - - if user_options is None: - user_options = self.user_options = AviaryValues() - - meta_data = self._meta_data_ - - for key in meta_data: - if key not in user_options: - item = meta_data[key] - - val = item['val'] - units = item['units'] - - user_options.set_val(key, val, units) - def validate_initial_guesses(self): - ''' + """ Raise TypeError if an unsupported initial guess is found. Users can call this method when updating initial guesses after initialization. - ''' + """ initial_guesses = self.initial_guesses if not initial_guesses: @@ -274,16 +253,11 @@ def validate_initial_guesses(self): for key in get_keys(initial_guesses): if key not in meta_data: raise TypeError( - f'{self.__class__.__name__}: {self.name}:' - f' unsupported initial guess: {key}' + f'{self.__class__.__name__}: {self.name}: unsupported initial guess: {key}' ) - def apply_initial_guesses( - self, prob: om.Problem, traj_name, phase: dm.Phase - ): - ''' - Apply any stored initial guesses; return a list of guesses not applied. - ''' + def apply_initial_guesses(self, prob: om.Problem, traj_name, phase: dm.Phase): + """Apply any stored initial guesses; return a list of guesses not applied.""" not_applied = [] phase_name = self.name @@ -303,13 +277,11 @@ def apply_initial_guesses( return not_applied def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ + """Return extra kwargs required for initializing the ODE.""" return {} def to_phase_info(self): - ''' + """ Return the stored settings as phase info. Returns @@ -319,9 +291,9 @@ def to_phase_info(self): object label phase_info : dict stored settings - ''' + """ subsystem_options = self.subsystem_options # TODO: aero info? - user_options = dict(self.user_options) + user_options = self.user_options.to_phase_info() initial_guesses = dict(self.initial_guesses) # TODO some of these may be purely programming API hooks, rather than for use @@ -332,14 +304,18 @@ def to_phase_info(self): # - meta_data phase_info = dict( - subsystem_options=subsystem_options, user_options=user_options, - initial_guesses=initial_guesses) + subsystem_options=subsystem_options, + user_options=user_options, + initial_guesses=initial_guesses, + ) return (self.name, phase_info) @classmethod - def from_phase_info(cls, name, phase_info: dict, core_subsystems=None, meta_data=None, transcription=None): - ''' + def from_phase_info( + cls, name, phase_info: dict, core_subsystems=None, meta_data=None, transcription=None + ): + """ Return a new phase builder based on the specified phase info. Note, calling code is responsible for matching phase info to the correct phase @@ -351,16 +327,15 @@ def from_phase_info(cls, name, phase_info: dict, core_subsystems=None, meta_data object label phase_info : dict stored settings - ''' + """ # loop over user_options dict entries # if the value is not a tuple, wrap it in a tuple with the second entry of 'unitless' for key, value in phase_info['user_options'].items(): if not isinstance(value, tuple): phase_info['user_options'][key] = (value, 'unitless') - subsystem_options = phase_info.get( - 'subsystem_options', {}) # TODO: aero info? - user_options = AviaryValues(phase_info.get('user_options', ())) + subsystem_options = phase_info.get('subsystem_options', {}) # TODO: aero info? + user_options = phase_info.get('user_options', ()) initial_guesses = AviaryValues(phase_info.get('initial_guesses', ())) external_subsystems = phase_info.get('external_subsystems', []) # TODO core subsystems in phase info? @@ -373,214 +348,202 @@ def from_phase_info(cls, name, phase_info: dict, core_subsystems=None, meta_data # - meta_data phase_builder = cls( - name, subsystem_options=subsystem_options, user_options=user_options, - initial_guesses=initial_guesses, meta_data=meta_data, - core_subsystems=core_subsystems, external_subsystems=external_subsystems, transcription=transcription) + name, + subsystem_options=subsystem_options, + user_options=user_options, + initial_guesses=initial_guesses, + meta_data=meta_data, + core_subsystems=core_subsystems, + external_subsystems=external_subsystems, + transcription=transcription, + ) return phase_builder - @classmethod - def _add_meta_data(cls, name, *, val, units='unitless', desc=None): - ''' - Update supported options with a new item. - - Raises - ------ - ValueError - if a repeat option is found - ''' - meta_data = cls._meta_data_ - - if name in meta_data: - raise ValueError( - f'{cls.__name__}": meta data: repeat option: {name}' - ) - - meta_data[name] = dict(val=val, units=units, desc=desc) - @classmethod def _add_initial_guess_meta_data(cls, initial_guess: InitialGuess, desc=None): - ''' + """ Update supported initial guesses with a new item. Raises ------ ValueError if a repeat initial guess is found - ''' + """ meta_data = cls._initial_guesses_meta_data_ name = initial_guess.key - meta_data[name] = dict( - apply_initial_guess=initial_guess.apply_initial_guess, desc=desc) + meta_data[name] = dict(apply_initial_guess=initial_guess.apply_initial_guess, desc=desc) def _add_user_defined_constraints(self, phase, constraints): - """ - Add each constraint and its corresponding arguments to the phase - """ - for constraint_name, kwargs in constraints.items(): - if kwargs['type'] == 'boundary': - kwargs.pop('type') - - if 'target' in kwargs: + """Add each constraint to this phase using the arguments given in the phase_info.""" + for constraint_name, constraint_dict in constraints.items(): + con_args = constraint_dict.copy() + con_type = con_args.pop('type') + if con_type == 'boundary': + if 'target' in con_args: # Support for constraint aliases. - target = kwargs.pop('target') - kwargs['constraint_name'] = constraint_name - phase.add_boundary_constraint(target, **kwargs) + target = con_args.pop('target') + con_args['constraint_name'] = constraint_name + phase.add_boundary_constraint(target, **con_args) else: - phase.add_boundary_constraint(constraint_name, **kwargs) + phase.add_boundary_constraint(constraint_name, **con_args) - elif kwargs['type'] == 'path': - kwargs.pop('type') - phase.add_path_constraint(constraint_name, **kwargs) + elif con_type == 'path': + phase.add_path_constraint(constraint_name, **con_args) - def set_time_options(self, user_options, targets=[]): - """ - Set time options: fix_initial flag, duration upper bounds, duration reference - """ - fix_initial = user_options.get_val('fix_initial') - duration_bounds = user_options.get_val('duration_bounds', units='s') - duration_ref = user_options.get_val('duration_ref', units='s') - - self.phase.set_time_options( - fix_initial=fix_initial, - duration_bounds=duration_bounds, - units="s", - targets=targets, - duration_ref=duration_ref, - ) + else: + raise ValueError( + f'Invalid type "{con_type}" for constraint {constraint_name} in {phase.name}.' + ) - def add_velocity_state(self, user_options): + def add_state(self, name, target, rate_source): """ - Add velocity state: lower and upper bounds, reference, zero-reference, and state defect reference. - """ - velocity_lower = user_options.get_val('velocity_lower', units='kn') - velocity_upper = user_options.get_val('velocity_upper', units='kn') - velocity_ref = user_options.get_val('velocity_ref', units='kn') - velocity_ref0 = user_options.get_val('velocity_ref0', units='kn') - velocity_defect_ref = user_options.get_val('velocity_defect_ref', units='kn') - self.phase.add_state( - Dynamic.Mission.VELOCITY, - fix_initial=user_options.get_val('fix_initial'), - fix_final=False, - lower=velocity_lower, - upper=velocity_upper, - units="kn", - rate_source=Dynamic.Mission.VELOCITY_RATE, - targets=Dynamic.Mission.VELOCITY, - ref=velocity_ref, - ref0=velocity_ref0, - defect_ref=velocity_defect_ref, - ) + Add a state to this phase using the options in the phase_info. - def add_mass_state(self, user_options): - """ - Add mass state: lower and upper bounds, reference, zero-reference, and state defect reference. + Parameters + ---------- + name : str + The name of this state in the phase_info options. + target : str + State promoted variable path to the ODE. + rate_source : str + Source of the state rate in the ODE. """ - mass_lower = user_options.get_val('mass_lower', units='lbm') - mass_upper = user_options.get_val('mass_upper', units='lbm') - mass_ref = user_options.get_val('mass_ref', units='lbm') - mass_ref0 = user_options.get_val('mass_ref0', units='lbm') - mass_defect_ref = user_options.get_val('mass_defect_ref', units='lbm') - self.phase.add_state( - Dynamic.Mission.MASS, - fix_initial=user_options.get_val('fix_initial'), - fix_final=False, - lower=mass_lower, - upper=mass_upper, - units="lbm", - rate_source=Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - targets=Dynamic.Mission.MASS, - ref=mass_ref, - ref0=mass_ref0, - defect_ref=mass_defect_ref, - ) + options = self.user_options + + initial, _ = options[f'{name}_initial'] + final, _ = options[f'{name}_final'] + bounds, units = options[f'{name}_bounds'] + ref, _ = options[f'{name}_ref'] + ref0, _ = options[f'{name}_ref0'] + defect_ref, _ = options[f'{name}_defect_ref'] + solve_segments = options[f'{name}_solve_segments'] + + # Try to only use arguments that aren't None because dymos' default is _undefined. + extra_options = {} + if ref0 is not None: + extra_options['ref0'] = ref0 + if defect_ref is not None: + extra_options['defect_ref'] = defect_ref + + # If a value is specified for the starting node, then fix_initial is True. + # Otherwise, input_initial is True. + # The problem configurator may change input_initial to False requested or necessary, (e.g., + # for parallel phases in MPI.) - def add_distance_state(self, user_options, units='NM'): - """ - Add distance state: lower and upper bounds, reference, zero-reference, and state defect reference. - """ - distance_lower = user_options.get_val('distance_lower', units=units) - distance_upper = user_options.get_val('distance_upper', units=units) - distance_ref = user_options.get_val('distance_ref', units=units) - distance_ref0 = user_options.get_val('distance_ref0', units=units) - distance_defect_ref = user_options.get_val('distance_defect_ref', units=units) self.phase.add_state( - Dynamic.Mission.DISTANCE, - fix_initial=user_options.get_val('fix_initial'), - fix_final=False, - lower=distance_lower, - upper=distance_upper, + target, + fix_initial=initial is not None, + input_initial=False, + lower=bounds[0], + upper=bounds[1], units=units, - rate_source=Dynamic.Mission.DISTANCE_RATE, - ref=distance_ref, - ref0=distance_ref0, - defect_ref=distance_defect_ref, + rate_source=rate_source, + ref=ref, + solve_segments='forward' if solve_segments else None, + **extra_options, ) - def add_flight_path_angle_state(self, user_options): - """ - Add flight path angle state: lower and upper bounds, reference, zero-reference, and state defect reference. - """ - angle_lower = user_options.get_val('angle_lower', units='rad') - angle_upper = user_options.get_val('angle_upper', units='rad') - angle_ref = user_options.get_val('angle_ref', units='rad') - angle_ref0 = user_options.get_val('angle_ref0', units='rad') - angle_defect_ref = user_options.get_val('angle_defect_ref', units='rad') - self.phase.add_state( - Dynamic.Mission.FLIGHT_PATH_ANGLE, - fix_initial=True, - fix_final=False, - lower=angle_lower, - upper=angle_upper, - units="rad", - rate_source=Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, - ref=angle_ref, - defect_ref=angle_defect_ref, - ref0=angle_ref0, - ) + if final is not None: + constraint_ref, _ = options[f'{name}_constraint_ref'] + if constraint_ref is None: + # If unspecified, final is a good value for it. + constraint_ref = final + self.phase.add_boundary_constraint( + target, + loc='final', + equals=final, + units=units, + ref=final, + ) - def add_altitude_state(self, user_options, units='ft'): - """ - Add altitude state: lower and upper bounds, reference, zero-reference, and state defect reference. + def add_control( + self, name, target, rate_targets=None, rate2_targets=None, add_constraints=True + ): """ - alt_lower = user_options.get_val('alt_lower', units=units) - alt_upper = user_options.get_val('alt_upper', units=units) - alt_ref = user_options.get_val('alt_ref', units=units) - alt_ref0 = user_options.get_val('alt_ref0', units=units) - alt_defect_ref = user_options.get_val('alt_defect_ref', units=units) - self.phase.add_state( - Dynamic.Mission.ALTITUDE, - fix_final=False, - lower=alt_lower, - upper=alt_upper, - units=units, - rate_source=Dynamic.Mission.ALTITUDE_RATE, - ref=alt_ref, - defect_ref=alt_defect_ref, - ref0=alt_ref0, - ) + Add a control to this phase using the options in the phase-info. - def add_altitude_constraint(self, user_options): - """ - Add altitude constraint: final altitude and altitude constraint reference. + Parameters + ---------- + name : str + The name of this control in the phase_info options. + target : str + Control promoted variable path to the ODE. + rate_source : list of str + List of rate targets for this control. + rate2_targets : Sequence of str or None + (Optional) The parameter in the ODE to which the control 2nd derivative is connected. + add_constraints : bool + When True, add constraints on any declared initial and final values if this control is + being optimized. Default is True. """ - final_altitude = user_options.get_val('final_altitude', units='ft') - alt_constraint_ref = user_options.get_val('alt_constraint_ref', units='ft') - self.phase.add_boundary_constraint( - Dynamic.Mission.ALTITUDE, - loc="final", - equals=final_altitude, - units="ft", - ref=alt_constraint_ref, - ) + options = self.user_options + phase = self.phase + + initial, _ = options[f'{name}_initial'] + final, _ = options[f'{name}_final'] + bounds, units = options[f'{name}_bounds'] + ref, _ = options[f'{name}_ref'] + ref0, _ = options[f'{name}_ref0'] + polynomial_order = options[f'{name}_polynomial_order'] + opt = options[f'{name}_optimize'] + + if ref == 1.0: + # This has not been moved from default, so find a good value. + candidates = [x for x in (bounds[0], bounds[1], initial, final) if x is not None] + if len(candidates) > 0: + ref = np.max(np.abs(np.array(candidates))) + + # Try to only use arguments that aren't None because dymos' default is _undefined. + extra_options = {} + if polynomial_order is not None: + extra_options['control_type'] = 'polynomial' + extra_options['order'] = polynomial_order + + if opt is True: + extra_options['lower'] = bounds[0] + extra_options['upper'] = bounds[1] + extra_options['ref'] = ref + extra_options['ref0'] = ref0 + extra_options['continuity_ref'] = ref + + # TODO: We may want to consider letting the user setting this. + # extra_options['rate_continuity_ref'] = ref + + if units not in ['unitless', None]: + extra_options['units'] = units + + if rate_targets is not None: + extra_options['rate_targets'] = rate_targets + + if rate2_targets is not None: + extra_options['rate2_targets'] = rate2_targets + + phase.add_control(target, targets=target, opt=opt, **extra_options) + + # Add timeseries for any control. + phase.add_timeseries_output(target) + + if not add_constraints: + return + + # Add an initial constraint. + if opt and initial is not None: + phase.add_boundary_constraint( + target, loc='initial', equals=initial, units=units, ref=ref + ) + + # Add a final constraint. + if opt and final is not None: + phase.add_boundary_constraint(target, loc='final', equals=final, units=units, ref=ref) _registered_phase_builder_types = [] def register(phase_builder_t=None, *, check_repeats=True): - ''' + """ Register a new phase builder type. Note, this function qualifies as a class decorator for ease of use. @@ -588,8 +551,9 @@ def register(phase_builder_t=None, *, check_repeats=True): Returns ------- phase builder type - ''' + """ if phase_builder_t is None: + def decorator(phase_builder_t): return register(phase_builder_t, check_repeats=check_repeats) @@ -604,7 +568,7 @@ def decorator(phase_builder_t): def phase_info_to_builder(name: str, phase_info: dict) -> PhaseBuilderBase: - ''' + """ Return a new phase builder based on the specified phase info. Note, the type of phase builder will be determined by calling @@ -616,7 +580,7 @@ def phase_info_to_builder(name: str, phase_info: dict) -> PhaseBuilderBase: ------ ValueError if a supported phase builder type cannot be determined - ''' + """ phase_builder_t: PhaseBuilderBase = None for phase_builder_t in _registered_phase_builder_types: @@ -630,9 +594,3 @@ def phase_info_to_builder(name: str, phase_info: dict) -> PhaseBuilderBase: if __name__ == '__main__': help(PhaseBuilderBase) - - try: - PhaseBuilderBase._add_meta_data('test', val=0, units=None, desc='test') - - except Exception as error: - print(error) diff --git a/aviary/mission/problem_configurator.py b/aviary/mission/problem_configurator.py new file mode 100644 index 0000000000..af2dd5ddfb --- /dev/null +++ b/aviary/mission/problem_configurator.py @@ -0,0 +1,240 @@ +# TODO: This is very much a conceptual prototype, and needs fine tuning. + + +class ProblemConfiguratorBase: + """Base class for a problem configurator in Aviary.""" + + def initial_guesses(self, aviary_group): + """ + Set any initial guesses for variables in the aviary problem. + + This is called at the end of AivaryProblem.load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + """ + pass + + def get_default_phase_info(self, aviary_group): + """ + Return a default phase_info for this type or problem. + + The default phase_info is used in the level 1 and 2 interfaces when no + phase_info is specified. + + This is called during load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + + Returns + ------- + AviaryValues + General default phase_info. + """ + msg = 'This pmethod must be defined in your problem configurator.' + raise NotImplementedError(msg) + + def get_code_origin(self, aviary_group): + """ + Return the legacy of this problem configurator. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + + Returns + ------- + LegacyCode + Code origin enum. + """ + pass + + def add_takeoff_systems(self, aviary_group): + """ + Adds takeoff systems to the model in aviary_group. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + """ + pass + + def get_phase_builder(self, aviary_group, phase_name, phase_options): + """ + Return a phase_builder for the requested phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + phase_name : str + Name of the requested phase. + phase_options : dict + Phase options for the requested phase. + + Returns + ------- + PhaseBuilderBase + Phase builder for requested phase. + """ + msg = 'This pmethod must be defined in your problem configurator.' + raise NotImplementedError(msg) + + def set_phase_options(self, aviary_group, phase_name, phase_idx, phase, user_options, comm): + """ + Set any necessary problem-related options on the phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + phase_name : str + Name of the requested phase. + phase_idx : int + Phase position in aviary_group.phases. Can be used to identify first phase. + phase : Phase + Instantiated phase object. + user_options : dict + Subdictionary "user_options" from the phase_info. + comm : MPI.Comm or + MPI Communicator from OpenMDAO problem. + """ + pass + + def link_phases(self, aviary_group, phases, connect_directly=True): + """ + Apply any additional phase linking. + + Note that some phase variables are handled in the AviaryProblem. Only + problem-specific ones need to be linked here. + + This is called from AviaryProblem.link_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + phases : Phase + Phases to be linked. + connect_directly : bool + When True, then connected=True. This allows the connections to be + handled by constraints if `phases` is a parallel group under MPI. + """ + pass + + def check_trajectory(self, aviary_group): + """ + Checks the phase_info user options for any inconsistency. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + """ + pass + + def link_phases_helper_with_options(self, aviary_group, phases, option_name, var, **kwargs): + # Initialize a list to keep track of indices where option_name is True + true_option_indices = [] + + # Loop through phases to find where option_name is True + for idx, phase_name in enumerate(phases): + if aviary_group.mission_info[phase_name]['user_options'].get(option_name, False): + true_option_indices.append(idx) + + # Determine the groups of phases to link based on consecutive indices + groups_to_link = [] + current_group = [] + + for idx in true_option_indices: + if not current_group or idx == current_group[-1] + 1: + # If the current index is consecutive, add it to the current group + current_group.append(idx) + else: + # Otherwise, start a new group and save the previous one + groups_to_link.append(current_group) + current_group = [idx] + + # Add the last group if it exists + if current_group: + groups_to_link.append(current_group) + + # Loop through each group and determine the phases to link + for group in groups_to_link: + # Extend the group to include the phase before the first True option and + # after the last True option, if applicable + if group[0] > 0: + group.insert(0, group[0] - 1) + if group[-1] < len(phases) - 1: + group.append(group[-1] + 1) + + # Extract the phase names for the current group + phases_to_link = [phases[idx] for idx in group] + + # Link the phases for the current group + if len(phases_to_link) > 1: + aviary_group.traj.link_phases(phases=phases_to_link, vars=[var], **kwargs) + + def add_post_mission_systems(self, aviary_group): + """ + Add any post mission systems. + + These may include any post-mission take off and landing systems. + + This is called from AviaryProblem.add_post_mission_systems + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + """ + pass + + def add_objective(self, aviary_group): + """ + Add any additional components related to objectives. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + """ + pass + + def set_phase_initial_guesses( + self, aviary_group, phase_name, phase, guesses, target_prob, parent_prefix + ): + """ + Adds the initial guesses for each variable of a given phase to the problem. + + This method sets the initial guesses into the openmdao model for time, controls, states, + and problem-specific variables for a given phase. If using the GASP model, it also handles + some special cases that are not covered in the `phase_info` object. These include initial + guesses for mass, time, and distance, which are determined based on the phase name and + other mission-related variables. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this builder. + phase : Phase + The phase object for which the guesses are being added. + guesses : dict + A dictionary containing the initial guesses for the phase. + target_prob : Problem + Problem instance to apply the guesses. + parent_prefix : str + Location of this trajectory in the hierarchy. + """ + pass diff --git a/aviary/mission/solved_two_dof_problem_configurator.py b/aviary/mission/solved_two_dof_problem_configurator.py new file mode 100644 index 0000000000..e52126b4bd --- /dev/null +++ b/aviary/mission/solved_two_dof_problem_configurator.py @@ -0,0 +1,336 @@ +from aviary.mission.flops_based.phases.groundroll_phase import ( + GroundrollPhase as GroundrollPhaseVelocityIntegrated, +) +from aviary.mission.gasp_based.phases.twodof_phase import TwoDOFPhase +from aviary.mission.problem_configurator import ProblemConfiguratorBase +from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.utils import wrapped_convert_units +from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.variables import Dynamic, Mission +from aviary.mission.utils import process_guess_var + + +class SolvedTwoDOFProblemConfigurator(ProblemConfiguratorBase): + """The Solved 2DOF builder is used for detailed take-off and landing.""" + + def initial_guesses(self, aviary_group): + """ + Set any initial guesses for variables in the aviary problem. + + This is called at the end of AivaryProblem.load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + if aviary_group.engine_builders is None: + aviary_group.engine_builders = [build_engine_deck(aviary_group.aviary_inputs)] + + # This doesn't really have much value, but is needed for initializing + # an objective-related component that still lives in level 2. + aviary_group.target_range = aviary_group.aviary_inputs.get_val( + Mission.Design.RANGE, units='NM' + ) + + def get_default_phase_info(self, aviary_group): + """ + Return a default phase_info for this type or problem. + + The default phase_info is used in the level 1 and 2 interfaces when no + phase_info is specified. + + This is called during load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + + Returns + ------- + AviaryValues + General default phase_info. + """ + raise RuntimeError('Solved 2DOF requires that a phase_info is specified.') + + def get_code_origin(self, aviary_group): + """ + Return the legacy of this problem configurator. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + + Returns + ------- + LegacyCode + Code origin enum. + """ + return LegacyCode.FLOPS + + def add_takeoff_systems(self, aviary_group): + """ + Adds takeoff systems to the model in aviary_group. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + pass + + def get_phase_builder(self, aviary_group, phase_name, phase_options): + """ + Return a phase_builder for the requested phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + Name of the requested phase. + phase_options : dict + Phase options for the requested phase. + + Returns + ------- + PhaseBuilderBase + Phase builder for requested phase. + """ + if phase_options['user_options'].get('ground_roll') and not phase_options[ + 'user_options' + ].get('rotation'): + phase_builder = GroundrollPhaseVelocityIntegrated + else: + phase_builder = TwoDOFPhase + + return phase_builder + + def set_phase_options(self, aviary_group, phase_name, phase_idx, phase, user_options, comm): + """ + Set any necessary problem-related options on the phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + Name of the requested phase. + phase_idx : int + Phase position in aviary_group.phases. Can be used to identify first phase. + phase : Phase + Instantiated phase object. + user_options : dict + Subdictionary "user_options" from the phase_info. + comm : MPI.Comm or + MPI Communicator from OpenMDAO problem. + """ + time_units = phase.time_options['units'] + initial = wrapped_convert_units(user_options['time_initial'], time_units) + duration = wrapped_convert_units(user_options['time_duration'], time_units) + initial_bounds = wrapped_convert_units(user_options['time_initial_bounds'], time_units) + duration_bounds = wrapped_convert_units(user_options['time_duration_bounds'], time_units) + initial_ref = wrapped_convert_units(user_options['time_initial_ref'], time_units) + duration_ref = wrapped_convert_units(user_options['time_duration_ref'], time_units) + + fix_duration = duration is not None + fix_initial = initial is not None + + if initial_ref is None: + # Make a good guess for a reasonable initial time scaler. + if initial_bounds[0] is not None and initial_bounds[1] != 0.0: + # Upper bound is good for a ref. + initial_ref = initial_bounds[1] + else: + initial_ref = 600.0 + + if duration_ref is None: + duration_ref = (duration_bounds[0] + duration_bounds[1]) / 2.0 + + extra_options = {} + if not fix_initial: + extra_options['initial_bounds'] = initial_bounds + + if comm.size == 1 or fix_initial: + # Redundant on a fixed input; raises a warning if specified. + extra_options['initial_ref'] = None + else: + extra_options['initial_ref'] = initial_ref + + phase.set_time_options( + fix_initial=fix_initial, + fix_duration=fix_duration, + units=time_units, + duration_bounds=duration_bounds, + duration_ref=duration_ref, + **extra_options, + ) + + def link_phases(self, aviary_group, phases, connect_directly=True): + """ + Apply any additional phase linking. + + Note that some phase variables are handled in the AviaryProblem. Only + problem-specific ones need to be linked here. + + This is called from AviaryProblem.link_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phases : Phase + Phases to be linked. + connect_directly : bool + When True, then connected=True. This allows the connections to be + handled by constraints if `phases` is a parallel group under MPI. + """ + # connect regular_phases with each other if you are optimizing alt or mach + self.link_phases_helper_with_options( + aviary_group, + aviary_group.regular_phases, + 'altitude_optimize', + Dynamic.Mission.ALTITUDE, + ref=1.0e4, + ) + self.link_phases_helper_with_options( + aviary_group, + aviary_group.regular_phases, + 'mach_optimize', + Dynamic.Atmosphere.MACH, + ) + + # connect reserve phases with each other if you are optimizing alt or mach + self.link_phases_helper_with_options( + aviary_group, + aviary_group.reserve_phases, + 'altitude_optimize', + Dynamic.Mission.ALTITUDE, + ref=1.0e4, + ) + self.link_phases_helper_with_options( + aviary_group, + aviary_group.reserve_phases, + 'mach_optimize', + Dynamic.Atmosphere.MACH, + ) + + aviary_group.traj.link_phases(phases, [Dynamic.Vehicle.MASS], connected=True) + aviary_group.traj.link_phases( + phases, [Dynamic.Mission.DISTANCE], units='ft', ref=1.0e3, connected=False + ) + aviary_group.traj.link_phases(phases, ['time'], connected=False) + + if len(phases) > 2: + aviary_group.traj.link_phases( + phases[1:], + [Dynamic.Vehicle.ANGLE_OF_ATTACK], + units='rad', + connected=False, + ) + + def check_trajectory(self, aviary_group): + """ + Checks the phase_info user options for any inconsistency. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + pass + + def add_post_mission_systems(self, model): + """ + Add any post mission systems. + + These may include any post-mission take off and landing systems. + + This is called from AviaryProblem.add_post_mission_systems + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + pass + + def set_phase_initial_guesses( + self, aviary_group, phase_name, phase, guesses, target_prob, parent_prefix + ): + """ + Adds the initial guesses for each variable of a given phase to the problem. + + This method sets the initial guesses into the openmdao model for time, controls, states, + and problem-specific variables for a given phase. If using the GASP model, it also handles + some special cases that are not covered in the `phase_info` object. These include initial + guesses for mass, time, and distance, which are determined based on the phase name and + other mission-related variables. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + The name of the phase for which the guesses are being added. + phase : Phase + The phase object for which the guesses are being added. + guesses : dict + A dictionary containing the initial guesses for the phase. + target_prob : Problem + Problem instance to apply the guesses. + parent_prefix : str + Location of this trajectory in the hierarchy. + """ + control_keys = ['mach', 'altitude'] + + # for the simple mission method, use the provided initial and final mach + # and altitude values from phase_info + initial_altitude = wrapped_convert_units( + aviary_group.mission_info[phase_name]['user_options']['altitude_initial'], 'ft' + ) + final_altitude = wrapped_convert_units( + aviary_group.mission_info[phase_name]['user_options']['altitude_final'], 'ft' + ) + initial_mach = aviary_group.mission_info[phase_name]['user_options']['mach_initial'] + final_mach = aviary_group.mission_info[phase_name]['user_options']['mach_final'] + + guesses['mach'] = ([initial_mach[0], final_mach[0]], 'unitless') + guesses['altitude'] = ([initial_altitude, final_altitude], 'ft') + + for guess_key, guess_data in guesses.items(): + val, units = guess_data + + if val[0] is None or val[1] is None: + continue + + # Set initial guess for control variables + if guess_key in control_keys: + try: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.controls:{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + + except KeyError: + try: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.polynomial_controls:{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + + except KeyError: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.bspline_controls:', + {guess_key}, + process_guess_var(val, guess_key, phase), + units=units, + ) diff --git a/aviary/interface/utils/__init__.py b/aviary/mission/test/__init__.py similarity index 100% rename from aviary/interface/utils/__init__.py rename to aviary/mission/test/__init__.py diff --git a/aviary/mission/test/test_external_subsystems_in_mission.py b/aviary/mission/test/test_external_subsystems_in_mission.py new file mode 100644 index 0000000000..6c2031609d --- /dev/null +++ b/aviary/mission/test/test_external_subsystems_in_mission.py @@ -0,0 +1,181 @@ +"""Test for some features when using an external subsystem in the mission.""" + +import unittest +from copy import deepcopy + +import openmdao.api as om +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.models.missions.height_energy_default import phase_info as energy_phase_info +from aviary.models.missions.two_dof_default import phase_info as two_dof_phase_info +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase +from aviary.variable_info.variables import Aircraft + +energy_phase_info = deepcopy(energy_phase_info) + +energy_phase_info['pre_mission']['include_takeoff'] = False +energy_phase_info['post_mission']['include_landing'] = False +energy_phase_info.pop('climb') +energy_phase_info.pop('descent') + +# TODO once 2DOF doesn't force exact mission phases + order remove everything but cruise +# for faster test evaluation +# two_dof_phase_info = deepcopy(two_dof_phase_info) +# two_dof_phase_info.pop('groundroll') +# two_dof_phase_info.pop('rotation') +# two_dof_phase_info.pop('ascent') +# two_dof_phase_info.pop('accel') +# two_dof_phase_info.pop('climb1') +# two_dof_phase_info.pop('climb2') +# two_dof_phase_info.pop('desc1') +# two_dof_phase_info.pop('desc2') + + +@use_tempdirs +class TestExternalSubsystems(unittest.TestCase): + def test_mission_solver_energy(self): + local_phase_info = deepcopy(energy_phase_info) + local_phase_info['cruise']['external_subsystems'] = [SolverBuilder(name='solve_me')] + + prob = AviaryProblem() + + prob.load_inputs( + 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv', + local_phase_info, + ) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + self.assertTrue( + hasattr( + prob.model.traj.phases.cruise.rhs_all.solver_sub.external_subsystems, + 'solve_me', + ) + ) + + def test_no_mission_solver_energy(self): + local_phase_info = deepcopy(energy_phase_info) + local_phase_info['cruise']['external_subsystems'] = [ + NoSolverBuilder(name='do_not_solve_me') + ] + + prob = AviaryProblem() + + prob.load_inputs( + 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv', + local_phase_info, + ) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + self.assertTrue( + hasattr( + prob.model.traj.phases.cruise.rhs_all.external_subsystems, + 'do_not_solve_me', + ) + ) + + def test_mission_solver_2DOF(self): + local_phase_info = deepcopy(two_dof_phase_info) + local_phase_info['cruise']['external_subsystems'] = [SolverBuilder(name='solve_me')] + + prob = AviaryProblem() + + prob.load_inputs( + 'models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv', + local_phase_info, + ) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + # NOTE currently 2DOF ODEs do not use the solver subsystem + self.assertTrue( + hasattr( + prob.model.traj.phases.cruise.rhs.external_subsystems, + 'solve_me', + ) + ) + + def test_no_mission_solver_2DOF(self): + local_phase_info = deepcopy(two_dof_phase_info) + local_phase_info['cruise']['external_subsystems'] = [ + NoSolverBuilder(name='do_not_solve_me') + ] + + prob = AviaryProblem() + + prob.load_inputs( + 'models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv', + local_phase_info, + ) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + self.assertTrue( + hasattr( + prob.model.traj.phases.cruise.rhs.external_subsystems, + 'do_not_solve_me', + ) + ) + + +class ExternNoSolve(om.ExplicitComponent): + """This component should not have a solver above it.""" + + def setup(self): + self.add_input(Aircraft.Wing.AREA, 1.0, units='ft**2') + self.add_output('stuff', 1.0, units='ft**2') + + def compute(self, inputs, outputs): + pass + + +class NoSolverBuilder(SubsystemBuilderBase): + """Mission only. No solver.""" + + def needs_mission_solver(self, aviary_options): + return False + + def build_mission(self, num_nodes, aviary_inputs): + return ExternNoSolve() + + +class SolverBuilder(SubsystemBuilderBase): + """Mission only. Solver.""" + + def needs_mission_solver(self, aviary_options): + return True + + def build_mission(self, num_nodes, aviary_inputs): + return ExternNoSolve() + + +if __name__ == '__main__': + unittest.main() + # test = TestExternalSubsystems() + # test.test_no_mission_solver_2DOF() diff --git a/aviary/mission/two_dof_problem_configurator.py b/aviary/mission/two_dof_problem_configurator.py new file mode 100644 index 0000000000..64d60075df --- /dev/null +++ b/aviary/mission/two_dof_problem_configurator.py @@ -0,0 +1,816 @@ +import openmdao.api as om + +from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH +from aviary.mission.gasp_based.ode.landing_ode import LandingSegment +from aviary.mission.gasp_based.ode.params import ParamPort +from aviary.mission.gasp_based.ode.taxi_ode import TaxiSegment +from aviary.mission.gasp_based.phases.accel_phase import AccelPhase +from aviary.mission.gasp_based.phases.ascent_phase import AscentPhase +from aviary.mission.gasp_based.phases.climb_phase import ClimbPhase +from aviary.mission.gasp_based.phases.cruise_phase import CruisePhase +from aviary.mission.gasp_based.phases.descent_phase import DescentPhase +from aviary.mission.gasp_based.phases.groundroll_phase import GroundrollPhase +from aviary.mission.gasp_based.phases.rotation_phase import RotationPhase +from aviary.mission.gasp_based.polynomial_fit import PolynomialFit +from aviary.mission.problem_configurator import ProblemConfiguratorBase +from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.functions import add_opts2vals, create_opts2vals +from aviary.utils.process_input_decks import initialization_guessing, update_GASP_options +from aviary.utils.utils import wrapped_convert_units +from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.mission.utils import process_guess_var + + +class TwoDOFProblemConfigurator(ProblemConfiguratorBase): + """ + A 2DOF specific builder that customizes AviaryProblem() for use with + two degree of freedom phases. + """ + + def initial_guesses(self, aviary_group): + """ + Set any initial guesses for variables in the aviary problem. + + This is called at the end of AivaryProblem.load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + # TODO: This should probably be moved to the set_initial_guesses() method in AviaryProblem class + # Defines how the problem should build it's initial guesses for load_inputs() + # this modifies mass_method, initialization_guesses, and aviary_values + + aviary_inputs = aviary_group.aviary_inputs + + aviary_inputs = update_GASP_options(aviary_inputs) + + if aviary_group.engine_builders is None: + aviary_group.engine_builders = [build_engine_deck(aviary_inputs)] + + aviary_group.initialization_guesses = initialization_guessing( + aviary_inputs, aviary_group.initialization_guesses, aviary_group.engine_builders + ) + + aviary_inputs.set_val( + Mission.Summary.CRUISE_MASS_FINAL, + val=aviary_group.initialization_guesses['cruise_mass_final'], + units='lbm', + ) + aviary_inputs.set_val( + Mission.Summary.GROSS_MASS, + val=aviary_group.initialization_guesses['actual_takeoff_mass'], + units='lbm', + ) + + # Deal with missing defaults in phase info: + aviary_group.pre_mission_info.setdefault('include_takeoff', True) + aviary_group.pre_mission_info.setdefault('external_subsystems', []) + + aviary_group.post_mission_info.setdefault('include_landing', True) + aviary_group.post_mission_info.setdefault('external_subsystems', []) + + # Commonly referenced values + aviary_group.cruise_alt = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') + aviary_group.mass_defect = aviary_inputs.get_val('mass_defect', units='lbm') + + aviary_group.cruise_mass_final = aviary_inputs.get_val( + Mission.Summary.CRUISE_MASS_FINAL, units='lbm' + ) + + if 'target_range' in aviary_group.post_mission_info: + aviary_group.target_range = wrapped_convert_units( + aviary_group.post_mission_info['target_range'], 'NM' + ) + aviary_inputs.set_val(Mission.Summary.RANGE, aviary_group.target_range, units='NM') + else: + aviary_group.target_range = aviary_inputs.get_val(Mission.Design.RANGE, units='NM') + aviary_inputs.set_val( + Mission.Summary.RANGE, + aviary_inputs.get_val(Mission.Design.RANGE, units='NM'), + units='NM', + ) + + aviary_group.cruise_mach = aviary_inputs.get_val(Mission.Design.MACH) + aviary_group.require_range_residual = True + + def get_default_phase_info(self, aviary_group): + """ + Return a default phase_info for this type or problem. + + The default phase_info is used in the level 1 and 2 interfaces when no + phase_info is specified. + + This is called during load_inputs. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + + Returns + ------- + AviaryValues + General default phase_info. + """ + from aviary.models.missions.two_dof_default import phase_info + + return phase_info + + def get_code_origin(self, aviary_group): + """ + Return the legacy of this problem configurator. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + + Returns + ------- + LegacyCode + Code origin enum. + """ + return LegacyCode.GASP + + def add_takeoff_systems(self, aviary_group): + """ + Adds takeoff systems to the model in aviary_group. + + Parameters + ---------- + aviary_group : AviaryProblem + Problem that owns this configurator. + """ + aviary_group.cruise_alt = aviary_group.aviary_inputs.get_val( + Mission.Design.CRUISE_ALTITUDE, units='ft' + ) + + # Add event transformation subsystem + aviary_group.add_subsystem( + 'event_xform', + om.ExecComp( + ['t_init_gear=m*tau_gear+b', 't_init_flaps=m*tau_flaps+b'], + t_init_gear={'units': 's'}, # initial time that gear comes up + t_init_flaps={'units': 's'}, # initial time that flaps retract + tau_gear={'units': 'unitless'}, + tau_flaps={'units': 'unitless'}, + m={'units': 's'}, + b={'units': 's'}, + ), + promotes_inputs=[ + 'tau_gear', # design var + 'tau_flaps', # design var + ('m', Mission.Takeoff.ASCENT_DURATION), + ('b', Mission.Takeoff.ASCENT_T_INITIAL), + ], + promotes_outputs=['t_init_gear', 't_init_flaps'], # link to h_fit + ) + + # Add taxi subsystem + aviary_group.add_subsystem( + 'taxi', + TaxiSegment(**(aviary_group.ode_args)), + promotes_inputs=['aircraft:*', 'mission:*'], + ) + + # Calculate speed at which to initiate rotation + aviary_group.add_subsystem( + 'vrot', + om.ExecComp( + 'Vrot = ((2 * mass * g) / (rho * wing_area * CLmax))**0.5 + dV1 + dVR', + Vrot={'units': 'ft/s'}, + mass={'units': 'lbm'}, + CLmax={'units': 'unitless'}, + g={'units': 'lbf/lbm', 'val': GRAV_ENGLISH_LBM}, + rho={'units': 'slug/ft**3', 'val': RHO_SEA_LEVEL_ENGLISH}, + wing_area={'units': 'ft**2'}, + dV1={ + 'units': 'ft/s', + 'desc': 'Increment of engine failure decision speed above stall', + }, + dVR={ + 'units': 'ft/s', + 'desc': 'Increment of takeoff rotation speed above engine failure ' + 'decision speed', + }, + ), + promotes_inputs=[ + ('wing_area', Aircraft.Wing.AREA), + ('dV1', Mission.Takeoff.DECISION_SPEED_INCREMENT), + ('dVR', Mission.Takeoff.ROTATION_SPEED_INCREMENT), + ('CLmax', Mission.Takeoff.LIFT_COEFFICIENT_MAX), + ], + promotes_outputs=[('Vrot', Mission.Takeoff.ROTATION_VELOCITY)], + ) + + def get_phase_builder(self, aviary_group, phase_name, phase_options): + """ + Return a phase_builder for the requested phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + Name of the requested phase. + phase_options : dict + Phase options for the requested phase. + + Returns + ------- + PhaseBuilderBase + Phase builder for requested phase. + """ + if 'groundroll' in phase_name: + phase_builder = GroundrollPhase + elif 'rotation' in phase_name: + phase_builder = RotationPhase + elif 'accel' in phase_name: + phase_builder = AccelPhase + elif 'ascent' in phase_name: + phase_builder = AscentPhase + elif 'climb' in phase_name: + phase_builder = ClimbPhase + elif 'cruise' in phase_name: + phase_builder = CruisePhase + elif 'desc' in phase_name: + phase_builder = DescentPhase + else: + raise ValueError( + f'{phase_name} does not have an associated phase_builder \n phase_name must ' + 'include one of: groundroll, rotation, accel, ascent, climb, cruise, or desc' + ) + + return phase_builder + + def set_phase_options(self, aviary_group, phase_name, phase_idx, phase, user_options, comm): + """ + Set any necessary problem-related options on the phase. + + This is called from _get_phase in AviaryProblem.add_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + Name of the requested phase. + phase_idx : int + Phase position in aviary_group.phases. Can be used to identify first phase. + phase : Phase + Instantiated phase object. + user_options : dict + Subdictionary "user_options" from the phase_info. + comm : MPI.Comm or + MPI Communicator from OpenMDAO problem. + """ + if 'cruise' in phase_name: + # Cruise phase integrates over mass instead of time. + # We rely on mass being monotonically non-increasing across the phase. + phase.set_time_options( + name='mass', + fix_initial=False, + fix_duration=False, + units='lbm', + targets='mass', + initial_bounds=(0.0, 1.0e7), + initial_ref=100.0e3, + duration_bounds=(-1.0e7, -1), + duration_ref=50000, + ) + return + + time_units = 's' + initial = wrapped_convert_units(user_options['time_initial'], time_units) + duration = wrapped_convert_units(user_options['time_duration'], time_units) + initial_bounds = wrapped_convert_units(user_options['time_initial_bounds'], time_units) + duration_bounds = wrapped_convert_units(user_options['time_duration_bounds'], time_units) + initial_ref = wrapped_convert_units(user_options['time_initial_ref'], time_units) + duration_ref = wrapped_convert_units(user_options['time_duration_ref'], time_units) + + fix_duration = duration is not None + fix_initial = initial is not None + + if 'ascent' in phase_name: + phase.set_time_options( + units='s', + targets='t_curr', + input_initial=True, + input_duration=True, + ) + + elif 'descent' in phase_name: + phase.set_time_options( + duration_bounds=duration_bounds, + fix_initial=fix_initial, + input_initial=input_initial, + units='s', + duration_ref=duration_ref, + ) + + else: + if initial_bounds[0] is not None and initial_bounds[1]: + # Upper bound is good for a ref. + time_initial_ref = initial_bounds[1] + else: + time_initial_ref = 600.0 + + if duration_ref is None: + # Why are we overriding this? + duration_ref = 0.5 * (duration_bounds[0] + duration_bounds[1]) + + input_initial = phase_idx > 0 + + if fix_initial or input_initial: + if comm.size > 1: + # Phases are disconnected to run in parallel, so initial ref is + # valid. + initial_ref = time_initial_ref + else: + # Redundant on a fixed input; raises a warning if specified. + initial_ref = None + + phase.set_time_options( + fix_initial=fix_initial, + fix_duration=fix_duration, + units=time_units, + duration_bounds=duration_bounds, + duration_ref=duration_ref, + initial_ref=initial_ref, + ) + + else: # TODO: figure out how to handle this now that fix_initial is dict + phase.set_time_options( + fix_initial=fix_initial, + fix_duration=fix_duration, + units=time_units, + duration_bounds=duration_bounds, + duration_ref=duration_ref, + initial_bounds=initial_bounds, + initial_ref=initial_ref, + ) + + phase.add_control( + Dynamic.Vehicle.Propulsion.THROTTLE, + targets=Dynamic.Vehicle.Propulsion.THROTTLE, + units='unitless', + opt=False, + ) + + # TODO: This seems like a hack. We might want to find a better way. + # The issue is that aero methods are hardcoded for GASP mission phases + # instead of being defaulted somewhere, so they don't use phase_info + # aviary_group.mission_info[phase_name]['phase_type'] = phase_name + if phase_name in ['ascent', 'groundroll', 'rotation']: + # safely add in default method in way that doesn't overwrite existing method + # and create nested structure if it doesn't already exist + aviary_group.mission_info[phase_name].setdefault('subsystem_options', {}).setdefault( + 'core_aerodynamics', {} + ).setdefault('method', 'low_speed') + + def link_phases(self, aviary_group, phases, connect_directly=True): + """ + Apply any additional phase linking. + + Note that some phase variables are handled in the AviaryProblem. Only + problem-specific ones need to be linked here. + + This is called from AviaryProblem.link_phases + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phases : Phase + Phases to be linked. + connect_directly : bool + When True, then connected=True. This allows the connections to be + handled by constraints if `phases` is a parallel group under MPI. + """ + for ii in range(len(phases) - 1): + phase1, phase2 = phases[ii : ii + 2] + analytic1 = aviary_group.mission_info[phase1]['user_options']['analytic'] + analytic2 = aviary_group.mission_info[phase2]['user_options']['analytic'] + + if not (analytic1 or analytic2): + # we always want time, distance, and mass to be continuous + states_to_link = { + 'time': connect_directly, + Dynamic.Mission.DISTANCE: connect_directly, + Dynamic.Vehicle.MASS: False, + } + + # if both phases are reserve phases or neither is a reserve phase + # (we are not on the boundary between the regular and reserve missions) + # and neither phase is ground roll or rotation (altitude isn't a state): + # we want altitude to be continuous as well + if ( + ( + (phase1 in aviary_group.reserve_phases) + == (phase2 in aviary_group.reserve_phases) + ) + and not ({'groundroll', 'rotation'} & {phase1, phase2}) + and not ('accel', 'climb1') == (phase1, phase2) + ): # required for convergence of FwGm + states_to_link[Dynamic.Mission.ALTITUDE] = connect_directly + + # if either phase is rotation, we need to connect velocity + # ascent to accel also requires velocity + if 'rotation' in (phase1, phase2) or ('ascent', 'accel') == (phase1, phase2): + states_to_link[Dynamic.Mission.VELOCITY] = connect_directly + # if the first phase is rotation, we also need alpha + if phase1 == 'rotation': + states_to_link[Dynamic.Vehicle.ANGLE_OF_ATTACK] = False + + for state, connected in states_to_link.items(): + # in initial guesses, all of the states, other than time use + # the same name + initial_guesses1 = aviary_group.mission_info[phase1]['initial_guesses'] + initial_guesses2 = aviary_group.mission_info[phase2]['initial_guesses'] + + # if a state is in the initial guesses, get the units of the + # initial guess + kwargs = {} + if not connected: + if state in initial_guesses1: + kwargs = {'units': initial_guesses1[state][-1]} + elif state in initial_guesses2: + kwargs = {'units': initial_guesses2[state][-1]} + + aviary_group.traj.link_phases( + [phase1, phase2], [state], connected=connected, **kwargs + ) + + # if either phase is analytic we have to use a linkage_constraint + else: + # analytic phases use the prefix "initial" for time and distance, + # but not mass + if analytic2: + prefix = 'initial_' + else: + prefix = '' + + aviary_group.traj.add_linkage_constraint( + phase1, phase2, 'time', prefix + 'time', connected=True + ) + aviary_group.traj.add_linkage_constraint( + phase1, phase2, 'distance', prefix + 'distance', connected=True + ) + aviary_group.traj.add_linkage_constraint( + phase1, phase2, 'mass', 'mass', connected=False, ref=1.0e5 + ) + + # This isn't computed, but is instead set in the cruise phase_info. + # We still need altitude continuity. + # Note: if both sides are Breguet Range, the user is doing something odd like a + # step cruise, so don't enforce a constraint. + if not (analytic1 and analytic2): + aviary_group.traj.add_linkage_constraint( + phase1, phase2, 'altitude', 'altitude', connected=False, ref=1.0e4 + ) + + # add all params and promote them to aviary_group level + ParamPort.promote_params( + aviary_group, + trajs=['traj'], + phases=[[*aviary_group.regular_phases, *aviary_group.reserve_phases]], + ) + + aviary_group.promotes( + 'traj', + inputs=[ + ('ascent.parameters:t_init_gear', 't_init_gear'), + ('ascent.parameters:t_init_flaps', 't_init_flaps'), + ('ascent.t_initial', Mission.Takeoff.ASCENT_T_INITIAL), + ('ascent.t_duration', Mission.Takeoff.ASCENT_DURATION), + ], + ) + + # imitate input_initial for taxi -> groundroll + eq = aviary_group.add_subsystem('taxi_groundroll_mass_constraint', om.EQConstraintComp()) + eq.add_eq_output('mass', eq_units='lbm', normalize=False, ref=10000.0, add_constraint=True) + aviary_group.connect('taxi.mass', 'taxi_groundroll_mass_constraint.rhs:mass') + aviary_group.connect( + 'traj.groundroll.states:mass', + 'taxi_groundroll_mass_constraint.lhs:mass', + src_indices=[0], + flat_src_indices=True, + ) + + aviary_group.connect('traj.ascent.timeseries.time', 'h_fit.time_cp') + aviary_group.connect('traj.ascent.timeseries.altitude', 'h_fit.h_cp') + + aviary_group.connect( + f'traj.{aviary_group.regular_phases[-1]}.states:mass', + Mission.Landing.TOUCHDOWN_MASS, + src_indices=[-1], + ) + + # promote all ParamPort inputs for analytic segments as well + param_list = list(ParamPort.param_data) + aviary_group.promotes('taxi', inputs=param_list) + aviary_group.promotes('landing', inputs=param_list) + aviary_group.connect('taxi.mass', 'vrot.mass') + + if 'ascent' in aviary_group.mission_info: + self._add_groundroll_eq_constraint(aviary_group) + + def check_trajectory(self, aviary_group): + """ + Checks the phase_info user options for any inconsistency. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + pass + + def _add_groundroll_eq_constraint(self, aviary_group): + """ + Add an equality constraint to the problem to ensure that the TAS at the end of the + groundroll phase is equal to the rotation velocity at the start of the rotation phase. + """ + aviary_group.add_subsystem( + 'groundroll_boundary', + om.EQConstraintComp( + 'velocity', + eq_units='ft/s', + normalize=True, + add_constraint=True, + ), + ) + aviary_group.connect(Mission.Takeoff.ROTATION_VELOCITY, 'groundroll_boundary.rhs:velocity') + aviary_group.connect( + 'traj.groundroll.states:velocity', + 'groundroll_boundary.lhs:velocity', + src_indices=[-1], + flat_src_indices=True, + ) + + def add_post_mission_systems(self, aviary_group): + """ + Add any post mission systems. + + These may include any post-mission take off and landing systems. + + This is called from AviaryProblem.add_post_mission_systems + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + """ + if aviary_group.post_mission_info['include_landing']: + self._add_landing_systems(aviary_group) + + ascent_phase = getattr(aviary_group.traj.phases, 'ascent') + ascent_tx = ascent_phase.options['transcription'] + ascent_num_nodes = ascent_tx.grid_data.num_nodes + aviary_group.add_subsystem( + 'h_fit', + PolynomialFit(N_cp=ascent_num_nodes), + promotes_inputs=['t_init_gear', 't_init_flaps'], + ) + + aviary_group.add_subsystem( + 'range_constraint', + om.ExecComp( + 'range_resid = target_range - actual_range', + target_range={'val': aviary_group.target_range, 'units': 'NM'}, + actual_range={'val': aviary_group.target_range, 'units': 'NM'}, + range_resid={'val': 30, 'units': 'NM'}, + ), + promotes_inputs=[ + ('actual_range', Mission.Summary.RANGE), + 'target_range', + ], + promotes_outputs=[('range_resid', Mission.Constraints.RANGE_RESIDUAL)], + ) + + aviary_group.post_mission.add_constraint( + Mission.Constraints.MASS_RESIDUAL, equals=0.0, ref=1.0e5 + ) + + def _add_landing_systems(self, aviary_group): + aviary_group.add_subsystem( + 'landing', + LandingSegment(**(aviary_group.ode_args)), + promotes_inputs=[ + 'aircraft:*', + 'mission:*', + (Dynamic.Vehicle.MASS, Mission.Landing.TOUCHDOWN_MASS), + ], + promotes_outputs=['mission:*'], + ) + + aviary_group.connect( + 'pre_mission.interference_independent_of_shielded_area', + 'landing.interference_independent_of_shielded_area', + ) + aviary_group.connect( + 'pre_mission.drag_loss_due_to_shielded_wing_area', + 'landing.drag_loss_due_to_shielded_wing_area', + ) + + def set_phase_initial_guesses( + self, aviary_group, phase_name, phase, guesses, target_prob, parent_prefix + ): + """ + Adds the initial guesses for each variable of a given phase to the problem. + + This method sets the initial guesses into the openmdao model for time, controls, states, + and problem-specific variables for a given phase. If using the GASP model, it also handles + some special cases that are not covered in the `phase_info` object. These include initial + guesses for mass, time, and distance, which are determined based on the phase name and + other mission-related variables. + + Parameters + ---------- + aviary_group : AviaryGroup + Aviary model that owns this configurator. + phase_name : str + The name of the phase for which the guesses are being added. + phase : Phase + The phase object for which the guesses are being added. + guesses : dict + A dictionary containing the initial guesses for the phase. + target_prob : Problem + Problem instance to apply the guesses. + parent_prefix : str + Location of this trajectory in the hierarchy. + """ + # Handle Analytic Phase + if aviary_group.mission_info[phase_name]['user_options'].get('analytic', False): + for guess_key, guess_data in guesses.items(): + val, units = guess_data + + if 'mass' == guess_key: + # Set initial and duration mass for the analytic cruise phase. + # Note we are integrating over mass, not time for this phase. + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.t_initial', val[0], units=units + ) + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.t_duration', val[1], units=units + ) + + elif guess_key == 'time': + # Time needs to be dealt with elsewhere. + continue + else: + # Otherwise, set the value of the parameter in the trajectory + # phase + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.parameters:{guess_key}', + val, + units=units, + ) + + # Analytic phase should have nothing else to set. + return + + # Set initial guesses for the rotation mass and flight duration + rotation_mass = aviary_group.initialization_guesses['rotation_mass'] + flight_duration = aviary_group.initialization_guesses['flight_duration'] + + control_keys = ['velocity_rate', 'throttle'] + state_keys = [ + 'altitude', + 'mass', + Dynamic.Mission.DISTANCE, + Dynamic.Mission.VELOCITY, + 'flight_path_angle', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ] + + if phase_name == 'ascent': + # Alpha is a control for ascent. + control_keys.append(Dynamic.Vehicle.ANGLE_OF_ATTACK) + + prob_keys = ['tau_gear', 'tau_flaps'] + + for guess_key, guess_data in guesses.items(): + val, units = guess_data + + # Set initial guess for time variables + if 'time' == guess_key: + if phase_name == 'ascent': + # These variables are promoted to the top. + init_path = Mission.Takeoff.ASCENT_T_INITIAL + dura_path = Mission.Takeoff.ASCENT_DURATION + else: + init_path = parent_prefix + f'traj.{phase_name}.t_initial' + dura_path = parent_prefix + f'traj.{phase_name}.t_duration' + + target_prob.set_val(init_path, val[0], units=units) + target_prob.set_val(dura_path, val[1], units=units) + + else: + # Set initial guess for control variables + if guess_key in control_keys: + try: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.controls:{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + + except KeyError: + try: + target_prob.set_val( + parent_prefix + + f'traj.{phase_name}.polynomial_controls:{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + + except KeyError: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.bspline_controls:', + {guess_key}, + process_guess_var(val, guess_key, phase), + units=units, + ) + + if guess_key in control_keys: + pass + + # Set initial guess for state variables + elif guess_key in state_keys: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.states:{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + + elif guess_key in prob_keys: + target_prob.set_val(parent_prefix + guess_key, val, units=units) + + elif ':' in guess_key: + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.{guess_key}', + process_guess_var(val, guess_key, phase), + units=units, + ) + else: + # raise error if the guess key is not recognized + raise ValueError( + f'Initial guess key {guess_key} in {phase_name} is not recognized.' + ) + + # We need some special logic for these following variables because GASP computes + # initial guesses using some knowledge of the mission duration and other variables + # that are only available after calling `create_vehicle`. Thus these initial guess + # values are not included in the `phase_info` object. + base_phase = phase_name.removeprefix('reserve_') + + if 'mass' not in guesses: + # Determine a mass guess depending on the phase name + if base_phase in ['groundroll', 'rotation', 'ascent', 'accel', 'climb1']: + mass_guess = rotation_mass + elif base_phase == 'climb2': + mass_guess = 0.99 * rotation_mass + elif 'desc' in base_phase: + mass_guess = 0.9 * aviary_group.cruise_mass_final + + # Set the mass guess as the initial value for the mass state variable + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.states:mass', mass_guess, units='lbm' + ) + + if 'time' not in guesses: + # Determine initial time and duration guesses depending on the phase name + if 'desc1' == base_phase: + t_initial = flight_duration * 0.9 + t_duration = flight_duration * 0.04 + elif 'desc2' in base_phase: + t_initial = flight_duration * 0.94 + t_duration = 5000 + + # Set the time guesses as the initial values for the time-related + # trajectory variables + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.t_initial', t_initial, units='s' + ) + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.t_duration', t_duration, units='s' + ) + + if 'distance' not in guesses: + # Determine initial distance guesses depending on the phase name + if 'desc1' == base_phase: + ys = [aviary_group.target_range * 0.97, aviary_group.target_range * 0.99] + elif 'desc2' in base_phase: + ys = [aviary_group.target_range * 0.99, aviary_group.target_range] + # Set the distance guesses as the initial values for the distance state + # variable + target_prob.set_val( + parent_prefix + f'traj.{phase_name}.states:distance', + phase.interp(Dynamic.Mission.DISTANCE, ys=ys), + ) diff --git a/aviary/mission/twodof_phase.py b/aviary/mission/twodof_phase.py deleted file mode 100644 index 21a96954d2..0000000000 --- a/aviary/mission/twodof_phase.py +++ /dev/null @@ -1,136 +0,0 @@ -import dymos as dm - -from aviary.mission.flight_phase_builder import FlightPhaseBase, register -from aviary.mission.initial_guess_builders import InitialGuessState, InitialGuessIntegrationVariable, InitialGuessControl, InitialGuessPolynomialControl - -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variable_meta_data import _MetaData -from aviary.variable_info.variables import Dynamic -from aviary.mission.gasp_based.ode.unsteady_solved.unsteady_solved_ode import UnsteadySolvedODE -from aviary.variable_info.enums import SpeedType, EquationsOfMotion - -# TODO: support/handle the following in the base class -# - phase.set_time_options() -# - currently handled in level 3 interface implementation -# - self.external_subsystems -# - self.meta_data, with cls.default_meta_data customization point - - -@register -class TwoDOFPhase(FlightPhaseBase): - ''' - A phase builder for a two degree of freedom (2DOF) phase. - ''' - - def build_phase(self, aviary_options: AviaryValues = None): - ''' - Return a new 2dof phase for analysis using these constraints. - - If ode_class is None, default_ode_class is used. - - If transcription is None, the return value from calling - make_default_transcription is used. - - Parameters - ---------- - aviary_options : AviaryValues () - collection of Aircraft/Mission specific options - - Returns - ------- - dymos.Phase - ''' - self.ode_class = UnsteadySolvedODE - phase: dm.Phase = super().build_phase( - aviary_options, phase_type=EquationsOfMotion.SOLVED_2DOF) - - user_options: AviaryValues = self.user_options - - control_order = user_options.get_val('control_order') - - fix_initial = user_options.get_val('fix_initial') - duration_bounds = user_options.get_val('duration_bounds', units='ft') - duration_ref = user_options.get_val('duration_ref', units='ft') - rotation = user_options.get_val('rotation') - - initial_kwargs = {} - if not fix_initial: - initial_kwargs = { - 'initial_bounds': user_options.get_val('initial_bounds', units='ft'), - 'initial_ref': user_options.get_val('initial_ref', units='ft'), - } - - phase.set_time_options(fix_initial=fix_initial, fix_duration=False, - units='ft', name=Dynamic.Mission.DISTANCE, - duration_bounds=duration_bounds, duration_ref=duration_ref, - **initial_kwargs) - - phase.set_state_options("time", rate_source="dt_dr", - fix_initial=fix_initial, fix_final=False, ref=100., defect_ref=100.) - - if rotation: - phase.add_polynomial_control("alpha", - order=control_order, - fix_initial=True, - lower=0, upper=15, - units='deg', ref=10., - val=0., - opt=True) - - phase.add_timeseries_output("EAS", units="kn") - phase.add_timeseries_output(Dynamic.Mission.VELOCITY, units="kn") - phase.add_timeseries_output(Dynamic.Mission.LIFT) - - return phase - - def make_default_transcription(self): - ''' - Return a transcription object to be used by default in build_phase. - ''' - user_options = self.user_options - - num_segments, _ = user_options.get_item('num_segments') - order, _ = user_options.get_item('order') - - seg_ends, _ = dm.utils.lgl.lgl(num_segments + 1) - - transcription = dm.Radau( - num_segments=num_segments, order=order, compressed=True, - segment_ends=seg_ends) - - return transcription - - def _extra_ode_init_kwargs(self): - """ - Return extra kwargs required for initializing the ODE. - """ - # TODO: support external_subsystems and meta_data in the base class - return { - 'external_subsystems': self.external_subsystems, - 'meta_data': self.meta_data, - 'subsystem_options': self.subsystem_options, - 'input_speed_type': SpeedType.MACH, - 'clean': self.user_options.get_val('clean'), - 'ground_roll': self.user_options.get_val('ground_roll'), - 'throttle_enforcement': self.user_options.get_val('throttle_enforcement'), - } - - -TwoDOFPhase._add_meta_data('initial_ref', val=100., units='s', desc='initial reference') -TwoDOFPhase._add_meta_data('duration_ref', val=1000., - units='s', desc='duration reference') -TwoDOFPhase._add_meta_data('control_order', val=1, desc='control order') -TwoDOFPhase._add_meta_data('rotation', val=False) -TwoDOFPhase._add_meta_data('clean', val=False) - -TwoDOFPhase._add_initial_guess_meta_data( - InitialGuessIntegrationVariable(key='distance'), - desc='initial guess for initial distance and duration specified as a tuple') - -TwoDOFPhase._add_initial_guess_meta_data( - InitialGuessPolynomialControl('alpha'), - desc='initial guess for alpha') - -TwoDOFPhase._add_initial_guess_meta_data( - InitialGuessState('time'), - desc='initial guess for time') diff --git a/aviary/mission/utils.py b/aviary/mission/utils.py index d0393f5c5a..f653ef7fb8 100644 --- a/aviary/mission/utils.py +++ b/aviary/mission/utils.py @@ -1,7 +1,71 @@ import openmdao.api as om +import numpy as np + from aviary.utils.functions import promote_aircraft_and_mission_vars class ExternalSubsystemGroup(om.Group): def configure(self): promote_aircraft_and_mission_vars(self) + + +def get_phase_mission_bus_lengths(traj): + phase_mission_bus_lengths = {} + for phase_name, phase in traj._phases.items(): + phase_mission_bus_lengths[phase_name] = phase._timeseries['mission_bus_variables'][ + 'transcription' + ].grid_data.subset_num_nodes['all'] + return phase_mission_bus_lengths + + +def process_guess_var(val, key, phase): + """ + Process the guess variable, which can either be a float or an array of floats. + This method is responsible for interpolating initial guesses when the user + provides a list or array of values rather than a single float. It interpolates + the guess values across the phase's domain for a given variable, be it a control + or a state variable. The interpolation is performed between -1 and 1 (representing + the normalized phase time domain), using the numpy linspace function. + The result of this method is a single value or an array of interpolated values + that can be used to seed the optimization problem with initial guesses. + + Parameters + ---------- + val : float or list/array of floats + The initial guess value(s) for a particular variable. + key : str + The key identifying the variable for which the initial guess is provided. + phase : Phase + The phase for which the variable is being set. + + Returns + ------- + val : float or array of floats + The processed guess value(s) to be used in the optimization problem. + """ + # Check if val is not a single float + if not isinstance(val, float): + # If val is an array of values + if len(val) > 1: + # Get the shape of the val array + shape = np.shape(val) + + # Generate an array of evenly spaced values between -1 and 1, + # reshaping to match the shape of the val array + xs = np.linspace(-1, 1, num=np.prod(shape)).reshape(shape) + + # Check if the key indicates a control or state variable + if 'controls:' in key or 'states:' in key: + # If so, strip the first part of the key to match the variable name + # in phase + stripped_key = ':'.join(key.split(':')[1:]) + + # Interpolate the initial guess values across the phase's domain + val = phase.interp(stripped_key, xs=xs, ys=val) + else: + # If not a control or state variable, interpolate the initial guess + # values directly + val = phase.interp(key, xs=xs, ys=val) + + # Return the processed guess value(s) + return val diff --git a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.txt b/aviary/models/aircraft/advanced_single_aisle/N3CC_generic_low_speed_polars_FLOPS.txt similarity index 100% rename from aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.txt rename to aviary/models/aircraft/advanced_single_aisle/N3CC_generic_low_speed_polars_FLOPS.txt diff --git a/aviary/models/N3CC/__init__.py b/aviary/models/aircraft/advanced_single_aisle/__init__.py similarity index 100% rename from aviary/models/N3CC/__init__.py rename to aviary/models/aircraft/advanced_single_aisle/__init__.py diff --git a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv b/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv similarity index 82% rename from aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv rename to aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv index 98cf16cf5f..6cd2b15fd1 100644 --- a/aviary/models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv +++ b/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv @@ -10,16 +10,19 @@ aircraft:canard:laminar_flow_lower,0,unitless aircraft:canard:laminar_flow_upper,0,unitless aircraft:canard:mass_scaler,1,unitless aircraft:crew_and_payload:baggage_mass_per_passenger,35,lbm +aircraft:crew_and_payload:cargo_container_mass_scaler,0,unitless aircraft:crew_and_payload:design:num_business_class,20,unitless aircraft:crew_and_payload:design:num_first_class,16,unitless +aircraft:crew_and_payload:design:num_passengers,154,unitless aircraft:crew_and_payload:design:num_tourist_class,118,unitless aircraft:crew_and_payload:flight_crew_mass_scaler,1,unitless aircraft:crew_and_payload:mass_per_passenger,165,lbm aircraft:crew_and_payload:misc_cargo,0,lbm aircraft:crew_and_payload:non_flight_crew_mass_scaler,1,unitless -aircraft:crew_and_payload:num_flight_attendants,-1,unitless -aircraft:crew_and_payload:num_flight_crew,-1,unitless -aircraft:crew_and_payload:num_galley_crew,-1,unitless +aircraft:crew_and_payload:num_business_class,20,unitless +aircraft:crew_and_payload:num_first_class,16,unitless +aircraft:crew_and_payload:num_passengers,154,unitless +aircraft:crew_and_payload:num_tourist_class,118,unitless aircraft:crew_and_payload:passenger_service_mass_scaler,1,unitless aircraft:crew_and_payload:wing_cargo,0,lbm aircraft:design:base_area,0,ft**2 @@ -28,25 +31,30 @@ aircraft:design:landing_to_takeoff_mass_ratio,0.84,unitless aircraft:design:lift_dependent_drag_coeff_factor,0.93,unitless aircraft:design:subsonic_drag_coeff_factor,0.95,unitless aircraft:design:supersonic_drag_coeff_factor,1,unitless -aircraft:design:touchdown_mass,0,lbm +aircraft:design:touchdown_mass,108976.4,lbm aircraft:design:use_alt_mass,False,unitless aircraft:design:zero_lift_drag_coeff_factor,0.96,unitless aircraft:electrical:mass_scaler,1.1976,unitless +aircraft:engine:data_file,models/engines/turbofan_22k.csv,unitless aircraft:engine:additional_mass_fraction,0,unitless aircraft:engine:constant_fuel_consumption,0,lbm/h aircraft:engine:flight_idle_max_fraction,1,unitless aircraft:engine:flight_idle_min_fraction,0.08,unitless +aircraft:engine:flight_idle_thrust_fraction,0,unitless aircraft:engine:fuel_flow_scaler_constant_term,0,unitless -aircraft:engine:fuel_flow_scaler_linear_term,0,unitless +aircraft:engine:fuel_flow_scaler_linear_term,1,unitless aircraft:engine:generate_flight_idle,True,unitless aircraft:engine:geopotential_alt,False,unitless aircraft:engine:ignore_negative_thrust,False,unitless aircraft:engine:mass_scaler,1.15,unitless +aircraft:engine:num_engines,2,unitless aircraft:engine:num_fuselage_engines,0,unitless aircraft:engine:num_wing_engines,2,unitless aircraft:engine:reference_mass,6293.8,lbm aircraft:engine:reference_sls_thrust,22200.5,lbf -aircraft:engine:scaled_sls_thrust,22200,0,0,0,0,0,lbf +aircraft:engine:scale_factor,0.99997747798473,unitless +aircraft:engine:scale_mass,True,unitless +aircraft:engine:scaled_sls_thrust,22200,lbf aircraft:engine:subsonic_fuel_flow_scaler,1,unitless aircraft:engine:supersonic_fuel_flow_scaler,1,unitless aircraft:engine:wing_locations,0.289682918,unitless @@ -55,13 +63,13 @@ aircraft:fins:mass_scaler,1,unitless aircraft:fins:num_fins,0,unitless aircraft:fins:taper_ratio,-10,unitless aircraft:fuel:auxiliary_fuel_capacity,0,lbm -aircraft:fuel:density_ratio,1,unitless +aircraft:fuel:wing_fuel_fraction,0.7752,unitless aircraft:fuel:fuel_system_mass_scaler,0.93202,unitless aircraft:fuel:fuselage_fuel_capacity,0,lbm aircraft:fuel:num_tanks,7,unitless -aircraft:fuel:total_capacity,0,lbm +aircraft:fuel:total_capacity,33136.4,lbm aircraft:fuel:unusable_fuel_mass_scaler,1,unitless -aircraft:fuel:wing_fuel_capacity,25.903,lbm +aircraft:fuel:wing_fuel_capacity,33136.4,lbm aircraft:furnishings:mass_scaler,0.81859,unitless aircraft:fuselage:laminar_flow_lower,0,unitless aircraft:fuselage:laminar_flow_upper,0,unitless @@ -83,23 +91,28 @@ aircraft:horizontal_tail:taper_ratio,0.2734375,unitless aircraft:horizontal_tail:thickness_to_chord,0.115,unitless aircraft:horizontal_tail:vertical_tail_fraction,0,unitless aircraft:horizontal_tail:wetted_area,576.571192,ft**2 +aircraft:horizontal_tail:wetted_area_scaler,1,unitless aircraft:hydraulics:mass_scaler,0.95543,unitless aircraft:hydraulics:system_pressure,5000,psi aircraft:instruments:mass_scaler,1.66955,unitless -aircraft:landing_gear:carrier_based,False,unitless aircraft:landing_gear:drag_coefficient,0.024,unitless aircraft:landing_gear:main_gear_mass_scaler,0.8846,unitless -aircraft:landing_gear:main_gear_oleo_length,0,inch +aircraft:landing_gear:main_gear_oleo_length,106.94,inch aircraft:landing_gear:nose_gear_mass_scaler,0.8846,unitless -aircraft:landing_gear:nose_gear_oleo_length,0,inch +aircraft:landing_gear:nose_gear_oleo_length,74.86,inch aircraft:nacelle:avg_diameter,7.2,ft aircraft:nacelle:avg_length,35,ft aircraft:nacelle:laminar_flow_lower,0,unitless aircraft:nacelle:laminar_flow_upper,0,unitless +aircraft:nacelle:mass_scaler,0,unitless +aircraft:nacelle:total_wetted_area,488.936564,ft**2 aircraft:nacelle:wetted_area,244.468282,ft**2 +aircraft:nacelle:wetted_area_scaler,1,unitless aircraft:paint:mass_per_unit_area,0,lbm/ft**2 aircraft:propulsion:engine_oil_mass_scaler,1,unitless -aircraft:propulsion:misc_mass_scaler,0,unitless +aircraft:propulsion:misc_mass_scaler,1,unitless +aircraft:propulsion:total_engine_controls_mass,0,lbm +aircraft:propulsion:total_starter_mass,0,lbm aircraft:vertical_tail:area,227.184358191707,ft**2 aircraft:vertical_tail:aspect_ratio,1.77777777777778,unitless aircraft:vertical_tail:laminar_flow_lower,29,unitless @@ -110,18 +123,21 @@ aircraft:vertical_tail:sweep,39.735053245438,deg aircraft:vertical_tail:taper_ratio,0.25,unitless aircraft:vertical_tail:thickness_to_chord,0.1,unitless aircraft:vertical_tail:wetted_area,445.645658,ft**2 +aircraft:vertical_tail:wetted_area_scaler,1,unitless aircraft:wing:aeroelastic_tailoring_factor,0.33333,unitless aircraft:wing:airfoil_technology,1.6,unitless -aircraft:wing:area,1220,1,0,0,0,0,ft**2 -aircraft:wing:aspect_ratio,11.5587605382765,1,0,0,0,0,unitless +aircraft:wing:area,1220,ft**2 +aircraft:wing:aspect_ratio,11.5587605382765,unitless aircraft:wing:aspect_ratio_reference,11.5587605382765,unitless -aircraft:wing:bending_mass_scaler,1,unitless +aircraft:wing:bending_material_mass_scaler,1,unitless aircraft:wing:bwb_aft_body_mass_scaler,1,unitless aircraft:wing:chord_per_semispan,0.273522534166506,0.204274849507037,0.0888152947868224,0.0725353313595661,unitless aircraft:wing:composite_fraction,0.33333,unitless aircraft:wing:control_surface_area_ratio,0.333,unitless aircraft:wing:dihedral,6,deg +aircraft:wing:detailed_wing,True,unitless aircraft:wing:glove_and_bat,0,ft**2 +aircraft:wing:height,8.6,ft aircraft:wing:input_station_dist,0,0.34453777998,0.919,1,unitless aircraft:wing:laminar_flow_lower,0,unitless aircraft:wing:laminar_flow_upper,58,unitless @@ -137,37 +153,48 @@ aircraft:wing:span,118.7505278165,ft aircraft:wing:span_efficiency_factor,0.95,unitless aircraft:wing:span_efficiency_reduction,False,unitless aircraft:wing:strut_bracing_factor,0,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.77696,unitless -aircraft:wing:sweep,23.6286942529271,0,0,0,0,0,deg -aircraft:wing:taper_ratio,0.265189599754917,0,0,0,0,0,unitless -aircraft:wing:thickness_to_chord,0.12233,0,0,0,0,0,unitless +aircraft:wing:surface_control_mass_scaler,1.77696,unitless +aircraft:wing:sweep,23.6286942529271,deg +aircraft:wing:taper_ratio,0.265189599754917,unitless +aircraft:wing:thickness_to_chord,0.12233,unitless aircraft:wing:thickness_to_chord_dist,0.14233,0.12233,0.1108,0.1058,unitless aircraft:wing:thickness_to_chord_reference,0.116565,unitless aircraft:wing:ultimate_load_factor,3.75,unitless aircraft:wing:var_sweep_mass_penalty,0,unitless aircraft:wing:wetted_area,2210.280228,ft**2 +aircraft:wing:wetted_area_scaler,1,unitless mission:constraints:max_mach,0.785,unitless -mission:design:gross_mass,1,lbm -mission:design:lift_coefficient,-1,unitless -mission:design:mach,-1,unitless +mission:design:gross_mass,130000,lbm mission:design:range,3500,NM mission:design:thrust_takeoff_per_eng,0,lbf +mission:landing:airport_altitude,0,ft +mission:landing:braking_friction_coefficient,0.35,unitless +mission:landing:drag_coefficient_min,0.045,unitless mission:landing:flare_rate,2.2,deg/s mission:landing:initial_velocity,145,ft/s mission:landing:lift_coefficient_max,2.5,unitless -mission:summary:cruise_mach,0.785,0,0,0,0,0,unitless +mission:landing:obstacle_height,50,ft +mission:landing:rolling_friction_coefficient,0.0175,unitless +mission:landing:spoiler_drag_coefficient,0.085,unitless +mission:landing:spoiler_lift_coefficient,-0.81,unitless +mission:summary:cruise_mach,0.785,unitless mission:summary:fuel_flow_scaler,1,unitless +mission:takeoff:airport_altitude,0,ft mission:takeoff:angle_of_attack_runway,0,deg mission:takeoff:braking_friction_coefficient,0.35,unitless +mission:takeoff:drag_coefficient_min,0.045,unitless mission:takeoff:final_altitude,35,ft -mission:takeoff:fuel_simple,0,lbm +mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,2,unitless +mission:takeoff:obstacle_height,35,ft mission:takeoff:rolling_friction_coefficient,0.0175,unitless mission:takeoff:spoiler_drag_coefficient,0.085,unitless mission:takeoff:spoiler_lift_coefficient,-0.81,unitless mission:takeoff:thrust_incidence,0,deg settings:equations_of_motion,height_energy +settings:aerodynamics_method,FLOPS settings:mass_method,FLOPS +settings:problem_type,sizing # Unconverted Values AERIN.clapp,2 @@ -392,7 +419,7 @@ TOLIN.rvfact,0 TOLIN.tdelg,3 TOLIN.tdsink,8 TOLIN.thfact,1 -TOLIN.thrld +TOLIN.thrld,0 TOLIN.tibra,0 TOLIN.tibrak,1.46 TOLIN.ticut,1.46 diff --git a/aviary/models/N3CC/N3CC_data.py b/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py similarity index 58% rename from aviary/models/N3CC/N3CC_data.py rename to aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py index ccea7fb00d..a568745921 100644 --- a/aviary/models/N3CC/N3CC_data.py +++ b/aviary/models/aircraft/advanced_single_aisle/advanced_single_aisle_data.py @@ -1,29 +1,45 @@ -''' +""" FLOPS derived input/output for use with Aviary unit tests and benchmarks - FLOPS title: "REF MDL N3CC (26616) AR11 1220t 1340p turbofan_22k M785 20210721" - FLOPS input file: "N3CC FLOPS In- generic low speed polars.txt" - FLOPS output file: "N3CC FLOPS Out -low speed polar input echo deleted.txt" -- FLOPS engine deck: "turbofan_22k.txt" -''' +- FLOPS engine deck: "turbofan_22k.csv". +""" + import numpy as np from aviary.mission.flops_based.phases.detailed_landing_phases import ( - LandingApproachToMicP3, LandingFlareToTouchdown, LandingMicP3ToObstacle, - LandingNoseDownToStop, LandingObstacleToFlare, LandingTouchdownToNoseDown, - LandingTrajectory) + LandingApproachToMicP3, + LandingFlareToTouchdown, + LandingMicP3ToObstacle, + LandingNoseDownToStop, + LandingObstacleToFlare, + LandingTouchdownToNoseDown, + LandingTrajectory, +) from aviary.mission.flops_based.phases.detailed_takeoff_phases import ( - TakeoffBrakeReleaseToDecisionSpeed, TakeoffBrakeToAbort, - TakeoffDecisionSpeedBrakeDelay, TakeoffDecisionSpeedToRotate, - TakeoffEngineCutback, TakeoffEngineCutbackToMicP1, - TakeoffLiftoffToObstacle, TakeoffMicP1ToClimb, TakeoffMicP2ToEngineCutback, - TakeoffObstacleToMicP2, TakeoffRotateToLiftoff, TakeoffTrajectory) + TakeoffBrakeReleaseToDecisionSpeed, + TakeoffBrakeToAbort, + TakeoffDecisionSpeedBrakeDelay, + TakeoffDecisionSpeedToRotate, + TakeoffEngineCutback, + TakeoffEngineCutbackToMicP1, + TakeoffLiftoffToObstacle, + TakeoffMicP1ToClimb, + TakeoffMicP2ToEngineCutback, + TakeoffObstacleToMicP2, + TakeoffRotateToLiftoff, + TakeoffTrajectory, +) from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.aviary_values import AviaryValues -from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems, get_default_mission_subsystems from aviary.utils.functions import get_path +from aviary.utils.test_utils.default_subsystems import ( + get_default_mission_subsystems, + get_default_premission_subsystems, +) +from aviary.variable_info.enums import EquationsOfMotion, LegacyCode, ProblemType from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings -from aviary.variable_info.enums import EquationsOfMotion, LegacyCode -# from aviary.utils.preprocessors import preprocess_options N3CC = {} inputs = N3CC['inputs'] = AviaryValues() @@ -31,10 +47,10 @@ # Overall Aircraft # --------------------------- -inputs.set_val(Aircraft.Design.BASE_AREA, 0., 'ft**2') +inputs.set_val(Aircraft.Design.BASE_AREA, 0.0, 'ft**2') inputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, 0.01498) inputs.set_val(Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 0.84) -inputs.set_val(Mission.Design.GROSS_MASS, 129734., 'lbm') +inputs.set_val(Mission.Design.GROSS_MASS, 129734.0, 'lbm') inputs.set_val(Aircraft.Design.USE_ALT_MASS, False) inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 0.93) inputs.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 0.95) @@ -75,10 +91,10 @@ inputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, 0.0) inputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, 1.0) -inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 0., 'lbm') -inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.) -inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165., 'lbm') -inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0., 'lbm') +inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 0.0, 'lbm') +inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165.0, 'lbm') +inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0.0, 'lbm') # Electrical # --------------------------- @@ -91,8 +107,8 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') -inputs.set_val(Aircraft.Fuel.CAPACITY_FACTOR, 25.903) -inputs.set_val(Aircraft.Fuel.DENSITY_RATIO, 1.0) +inputs.set_val(Aircraft.Fuel.WING_FUEL_FRACTION, 0.7752) +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') inputs.set_val(Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0, 'lbm') inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 0.93202) inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) @@ -112,14 +128,14 @@ inputs.set_val(Aircraft.Fuselage.MAX_HEIGHT, 13.0, 'ft') fuselage_max_width = 12.3 fuselage_max_width_units = 'ft' -inputs.set_val( - Aircraft.Fuselage.MAX_WIDTH, fuselage_max_width, fuselage_max_width_units -) +inputs.set_val(Aircraft.Fuselage.MAX_WIDTH, fuselage_max_width, fuselage_max_width_units) inputs.set_val(Aircraft.Fuselage.NUM_FUSELAGES, 1) inputs.set_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, 97.5, 'ft') inputs.set_val( Aircraft.Fuselage.PLANFORM_AREA, - fuselage_length * fuselage_max_width, f'{fuselage_length_units}**2') + fuselage_length * fuselage_max_width, + f'{fuselage_length_units}**2', +) inputs.set_val(Aircraft.Fuselage.MASS_SCALER, 0.69981) inputs.set_val(Aircraft.Fuselage.WETTED_AREA, 4235.082096, 'ft**2') # Override inputs.set_val(Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0) @@ -140,7 +156,7 @@ # Hydraulics # --------------------------- -inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 5000., 'psi') +inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 5000.0, 'psi') inputs.set_val(Aircraft.Hydraulics.MASS_SCALER, 0.95543) # Instruments @@ -149,7 +165,6 @@ # Landing Gear # --------------------------- -inputs.set_val(Aircraft.LandingGear.CARRIER_BASED, False) inputs.set_val(Aircraft.LandingGear.DRAG_COEFFICIENT, 0.024) inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, 0.8846) inputs.set_val(Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, 0.8846) @@ -164,12 +179,14 @@ nacelle_wetted_area = 244.468282 nacelle_wetted_area_units = 'ft**2' inputs.set_val( - Aircraft.Nacelle.WETTED_AREA, - nacelle_wetted_area, nacelle_wetted_area_units) # Override + Aircraft.Nacelle.WETTED_AREA, nacelle_wetted_area, nacelle_wetted_area_units +) # Override inputs.set_val(Aircraft.Nacelle.WETTED_AREA_SCALER, 1.0) inputs.set_val( Aircraft.Nacelle.TOTAL_WETTED_AREA, - nacelle_wetted_area * 2, nacelle_wetted_area_units) + nacelle_wetted_area * 2, + nacelle_wetted_area_units, +) # Paint # --------------------------- @@ -183,37 +200,23 @@ # Must set this to zero if misc_mass is zero. inputs.set_val(Aircraft.Propulsion.TOTAL_STARTER_MASS, 0.0, 'lbm') -filename = get_path('models/engines/turbofan_22k.deck') +filename = get_path('models/engines/turbofan_22k.csv') inputs.set_val(Aircraft.Engine.DATA_FILE, filename) -engine_mass = 6293.8 -engine_mass_units = 'lbm' -inputs.set_val(Aircraft.Engine.MASS, engine_mass, engine_mass_units) -inputs.set_val( - Aircraft.Engine.REFERENCE_MASS, - engine_mass, - engine_mass_units) -scaled_sls_thrust = 22200.5 -scaled_sls_thrust_units = 'lbf' -inputs.set_val( - Aircraft.Engine.SCALED_SLS_THRUST, scaled_sls_thrust, scaled_sls_thrust_units) -inputs.set_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, scaled_sls_thrust, scaled_sls_thrust_units) +inputs.set_val(Aircraft.Engine.MASS, 6293.8, 'lbm') +inputs.set_val(Aircraft.Engine.REFERENCE_MASS, 6293.8, 'lbm') +inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 0.99997747798473) inputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, 0.0) -num_engines = 2 -inputs.set_val(Aircraft.Engine.NUM_ENGINES, num_engines) -num_fuselage_engines = 0 -inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, num_fuselage_engines) -num_wing_engines = num_engines -inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, num_wing_engines) +inputs.set_val(Aircraft.Engine.NUM_ENGINES, 2) +inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 0) +inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2) inputs.set_val(Aircraft.Engine.WING_LOCATIONS, 0.289682918) inputs.set_val(Aircraft.Engine.SCALE_MASS, True) inputs.set_val(Aircraft.Engine.MASS_SCALER, 1.15) inputs.set_val(Aircraft.Engine.SCALE_PERFORMANCE, True) inputs.set_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, 1.0) inputs.set_val(Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER, 1.0) -inputs.set_val( - Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, 0.0) +inputs.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, 0.0) inputs.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM, 1.0) inputs.set_val(Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, 0.0, units='lb/h') inputs.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.0) @@ -246,25 +249,27 @@ inputs.set_val(Aircraft.Wing.AREA, 1220.0, 'ft**2') inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 11.5587605382765) inputs.set_val(Aircraft.Wing.ASPECT_RATIO_REF, 11.5587605382765) -inputs.set_val(Aircraft.Wing.BENDING_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, 1.0) inputs.set_val( Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, - np.array( - [0.273522534166506, 0.204274849507037, 0.0888152947868224, 0.0725353313595661])) + np.array([0.273522534166506, 0.204274849507037, 0.0888152947868224, 0.0725353313595661]), +) inputs.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.33333) inputs.set_val(Aircraft.Wing.DIHEDRAL, 6.0, 'deg') inputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, 0.333) +inputs.set_val(Aircraft.Wing.DETAILED_WING, True) inputs.set_val(Aircraft.Wing.GLOVE_AND_BAT, 0.0, 'ft**2') inputs.set_val(Aircraft.Wing.HEIGHT, 8.6, 'ft') -inputs.set_val( - Aircraft.Wing.INPUT_STATION_DIST, np.array([0.0, 0.34453777998, 0.919, 1.0])) +inputs.set_val(Aircraft.Wing.INPUT_STATION_DIST, np.array([0.0, 0.34453777998, 0.919, 1.0])) inputs.set_val(Aircraft.Wing.LAMINAR_FLOW_LOWER, 0.0) inputs.set_val(Aircraft.Wing.LAMINAR_FLOW_UPPER, 58.0) inputs.set_val(Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL, 2.0) inputs.set_val(Aircraft.Wing.LOAD_FRACTION, 1.0) inputs.set_val( Aircraft.Wing.LOAD_PATH_SWEEP_DIST, - np.array([0.0, 23.6286942529271, 23.6286942529271]), 'deg') + np.array([0.0, 23.6286942529271, 23.6286942529271]), + 'deg', +) inputs.set_val(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, 0.015) inputs.set_val(Aircraft.Wing.MISC_MASS_SCALER, 1.7) inputs.set_val(Aircraft.Wing.NUM_INTEGRATION_STATIONS, 100) @@ -277,9 +282,7 @@ inputs.set_val(Aircraft.Wing.SWEEP, 23.6286942529271, 'deg') inputs.set_val(Aircraft.Wing.TAPER_RATIO, 0.265189599754917) inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, 0.12233) -inputs.set_val( - Aircraft.Wing.THICKNESS_TO_CHORD_DIST, - np.array([0.14233, 0.12233, 0.1108, 0.1058])) +inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_DIST, np.array([0.14233, 0.12233, 0.1108, 0.1058])) inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_REF, 0.116565) inputs.set_val(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.75) inputs.set_val(Aircraft.Wing.MASS_SCALER, 0.7412) @@ -295,62 +298,64 @@ inputs.set_val(Mission.Constraints.MAX_MACH, 0.785) inputs.set_val(Mission.Landing.DRAG_COEFFICIENT_MIN, 0.045, 'unitless') inputs.set_val(Mission.Landing.LIFT_COEFFICIENT_MAX, 2.0, 'unitless') -inputs.set_val(Mission.Takeoff.AIRPORT_ALTITUDE, 0., 'ft') +inputs.set_val(Mission.Takeoff.AIRPORT_ALTITUDE, 0.0, 'ft') inputs.set_val(Mission.Takeoff.DRAG_COEFFICIENT_MIN, 0.05, 'unitless') inputs.set_val(Mission.Takeoff.LIFT_COEFFICIENT_MAX, 2.0, 'unitless') -inputs.set_val(Mission.Takeoff.OBSTACLE_HEIGHT, 35., 'ft') -inputs.set_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 0., 'deg') +inputs.set_val(Mission.Takeoff.OBSTACLE_HEIGHT, 35.0, 'ft') +inputs.set_val(Mission.Takeoff.ANGLE_OF_ATTACK_RUNWAY, 0.0, 'deg') inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.0175) inputs.set_val(Mission.Takeoff.BRAKING_FRICTION_COEFFICIENT, 0.35) inputs.set_val(Mission.Takeoff.SPOILER_DRAG_COEFFICIENT, 0.085000) inputs.set_val(Mission.Takeoff.SPOILER_LIFT_COEFFICIENT, -0.810000) -inputs.set_val(Mission.Landing.AIRPORT_ALTITUDE, 0., 'ft') +inputs.set_val(Mission.Landing.AIRPORT_ALTITUDE, 0.0, 'ft') inputs.set_val(Mission.Landing.ROLLING_FRICTION_COEFFICIENT, 0.0175) inputs.set_val(Mission.Landing.BRAKING_FRICTION_COEFFICIENT, 0.35) inputs.set_val(Mission.Landing.FLARE_RATE, 2.2, 'deg/s') -inputs.set_val(Mission.Landing.OBSTACLE_HEIGHT, 50., 'ft') +inputs.set_val(Mission.Landing.OBSTACLE_HEIGHT, 50.0, 'ft') inputs.set_val(Mission.Landing.SPOILER_DRAG_COEFFICIENT, 0.085000) inputs.set_val(Mission.Landing.SPOILER_LIFT_COEFFICIENT, -0.810000) -inputs.set_val(Mission.Takeoff.THRUST_INCIDENCE, 0., 'deg') -inputs.set_val(Mission.Takeoff.FUEL_SIMPLE, 577., 'lbm') +inputs.set_val(Mission.Takeoff.THRUST_INCIDENCE, 0.0, 'deg') +inputs.set_val(Mission.Takeoff.FUEL_SIMPLE, 577.0, 'lbm') # Settings # --------------------------- inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.AERODYNAMICS_METHOD, LegacyCode.FLOPS) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) inputs.set_val(Settings.VERBOSITY, 0) +inputs.set_val(Settings.PROBLEM_TYPE, ProblemType.SIZING) # --------------------------- # OUTPUTS # --------------------------- -outputs.set_val(Aircraft.Design.EMPTY_MASS, 67542., 'lbm') +outputs.set_val(Aircraft.Design.EMPTY_MASS, 67542.0, 'lbm') outputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN, 996, 'lbm') outputs.set_val(Aircraft.Design.TOUCHDOWN_MASS, 108976.4, 'lbm') -outputs.set_val(Aircraft.Design.OPERATING_MASS, 72642., 'lbm') -outputs.set_val(Aircraft.Propulsion.MASS, 13105., 'lbm') -outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 29336., 'lbm') -outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 24105., 'lbm') +outputs.set_val(Mission.Summary.OPERATING_MASS, 72642.0, 'lbm') +outputs.set_val(Aircraft.Propulsion.MASS, 13105.0, 'lbm') +outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 29336.0, 'lbm') +outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 24105.0, 'lbm') outputs.set_val(Aircraft.Design.TOTAL_WETTED_AREA, 7956.515738, 'ft**2') -outputs.set_val(Aircraft.Design.ZERO_FUEL_MASS, 103442., 'lbm') -outputs.set_val(Mission.Design.FUEL_MASS, 26292., 'lbm') +outputs.set_val(Mission.Summary.ZERO_FUEL_MASS, 103442.0, 'lbm') +outputs.set_val(Mission.Summary.FUEL_MASS, 26292.0, 'lbm') -outputs.set_val(Aircraft.AirConditioning.MASS, 1541., 'lbm') +outputs.set_val(Aircraft.AirConditioning.MASS, 1541.0, 'lbm') -outputs.set_val(Aircraft.AntiIcing.MASS, 108., 'lbm') +outputs.set_val(Aircraft.AntiIcing.MASS, 108.0, 'lbm') -outputs.set_val(Aircraft.APU.MASS, 1014., 'lbm') +outputs.set_val(Aircraft.APU.MASS, 1014.0, 'lbm') outputs.set_val(Aircraft.Avionics.MASS, 2032.0, 'lbm') -outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5390., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 0., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 0., 'lbm') +outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5390.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 0.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 0.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS, 675.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, 820.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 3033, 'lbm') -outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 25410., 'lbm') -outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 30800., 'lbm') +outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 25410.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 30800.0, 'lbm') outputs.set_val(Aircraft.Electrical.MASS, 2375.0, 'lbm') @@ -361,23 +366,22 @@ outputs.set_val(Aircraft.Fins.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.Furnishings.MASS, 12556., 'lbm') +outputs.set_val(Aircraft.Furnishings.MASS, 12556.0, 'lbm') outputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, 12.65, 'ft') outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 125.0, 'ft') # hand computed outputs.set_val(Aircraft.Fuselage.CROSS_SECTION, 125.68137760226817, 'ft**2') -outputs.set_val( - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 12.65 / (11.5587605382765 * 1220)**0.5) +outputs.set_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 12.65 / (11.5587605382765 * 1220) ** 0.5) outputs.set_val(Aircraft.Fuselage.FINENESS, 9.8814) outputs.set_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER, 125.0 / 12.65) -outputs.set_val(Aircraft.Fuselage.MASS, 11750., 'lbm') +outputs.set_val(Aircraft.Fuselage.MASS, 11750.0, 'lbm') outputs.set_val(Aircraft.Canard.MASS, 0.0, 'lbm') outputs.set_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 8.15, 'ft') outputs.set_val(Aircraft.HorizontalTail.FINENESS, 0.1150) -outputs.set_val(Aircraft.HorizontalTail.MASS, 2147., 'lbm') +outputs.set_val(Aircraft.HorizontalTail.MASS, 2147.0, 'lbm') outputs.set_val(Aircraft.Hydraulics.MASS, 832.0, 'lbm') @@ -396,43 +400,33 @@ outputs.set_val(Aircraft.Paint.MASS, 0.0, 'lbm') -outputs.set_val( - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, - scaled_sls_thrust * num_engines, scaled_sls_thrust_units) +inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 22200.5, 'lbf') +inputs.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 22200.5, 'lbf') +outputs.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 22200.5 * 2, 'lbf') outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, 110.0, 'lbm') -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, num_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, num_wing_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2) -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, num_fuselage_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 0) outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, 0.0, 'lbm') - -outputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) # Not printed in FLOPS, but total mass matches outputs.set_val(Aircraft.Engine.POD_MASS, 6619.27529209, 'lbm') -outputs.set_val(Aircraft.Engine.MASS, 12587./2.0, 'lbm') +outputs.set_val(Aircraft.Engine.MASS, 12587.0 / 2.0, 'lbm') outputs.set_val(Aircraft.Engine.ADDITIONAL_MASS, 0.0, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_MISC_MASS, 0.0, 'lbm') -thrust_reversers_mass = 0. -thrust_reversers_mass_units = 'lbm' -outputs.set_val( - Aircraft.Engine.THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) -outputs.set_val( - Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) -outputs.set_val( - Aircraft.Propulsion.TOTAL_ENGINE_MASS, - engine_mass * num_engines, engine_mass_units) +outputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS, 0, 'lbm') +outputs.set_val(Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, 0, 'lbm') +outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_MASS, 6293.8 * 2, 'lbm') outputs.set_val(Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, 11.25, 'ft') outputs.set_val(Aircraft.VerticalTail.FINENESS, 0.1000) outputs.set_val(Aircraft.VerticalTail.MASS, 1175.0, 'lbm') -outputs.set_val(Aircraft.Wing.BENDING_FACTOR, 11.9602) -outputs.set_val(Aircraft.Wing.BENDING_MASS, 5410.5, 'lbm') +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR, 11.9602) +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS, 5410.5, 'lbm') outputs.set_val(Aircraft.Wing.CHARACTERISTIC_LENGTH, 10.27, 'ft') outputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 0.333 * 1220, 'ft**2') outputs.set_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR, 0.960516) @@ -446,42 +440,50 @@ outputs.set_val(Mission.Design.LIFT_COEFFICIENT, 0.583) # Create engine model -engine = build_engine_deck(aviary_options=inputs) +engines = [build_engine_deck(options=inputs)] # Calls to preprocess_options() in this location should be avoided because they # # will trigger when get_flops_inputs() is imported # preprocess_options(inputs, engine_models=engine) # build subsystems -default_premission_subsystems = get_default_premission_subsystems('FLOPS', engine) -default_mission_subsystems = get_default_mission_subsystems('FLOPS', engine) +default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines) +default_mission_subsystems = get_default_mission_subsystems('FLOPS', engines) # region - detailed takeoff takeoff_trajectory_builder = TakeoffTrajectory('detailed_takeoff') # region - takeoff aero -takeoff_subsystem_options = {'core_aerodynamics': - {'method': 'low_speed', - 'ground_altitude': 0., # units='m' - 'angles_of_attack': [ - 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, - 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, - 12.0, 13.0, 14.0, 15.0], # units='deg' - 'lift_coefficients': [ - 0.5178, 0.6, 0.75, 0.85, 0.95, 1.05, - 1.15, 1.25, 1.35, 1.5, 1.6, 1.7, - 1.8, 1.85, 1.9, 1.95], - 'drag_coefficients': [ - 0.0674, 0.065, 0.065, 0.07, 0.072, 0.076, - 0.084, 0.09, 0.10, 0.11, 0.12, 0.13, - 0.15, 0.16, 0.18, 0.20], - 'lift_coefficient_factor': 1., - 'drag_coefficient_factor': 1.}} - -takeoff_subsystem_options_spoilers = {'core_aerodynamics': - {**takeoff_subsystem_options['core_aerodynamics'], - 'use_spoilers': True, - 'spoiler_drag_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_DRAG_COEFFICIENT), - 'spoiler_lift_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_LIFT_COEFFICIENT)}} +# block auto-formatting of tables +# fmt: off +takeoff_subsystem_options = { + 'core_aerodynamics': { + 'method': 'low_speed', + 'ground_altitude': 0.0, # units='m' + 'angles_of_attack': [ + 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, + ], # units='deg' + 'lift_coefficients': [ + 0.5178, 0.6, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25, + 1.35, 1.5, 1.6, 1.7, 1.8, 1.85, 1.9, 1.95, + ], + 'drag_coefficients': [ + 0.0674, 0.065, 0.065, 0.07, 0.072, 0.076, 0.084, 0.09, + 0.10, 0.11, 0.12, 0.13, 0.15, 0.16, 0.18, 0.20, + ], + 'lift_coefficient_factor': 1.0, + 'drag_coefficient_factor': 1.0, + } +} +# fmt: on + +takeoff_subsystem_options_spoilers = { + 'core_aerodynamics': { + **takeoff_subsystem_options['core_aerodynamics'], + 'use_spoilers': True, + 'spoiler_drag_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_DRAG_COEFFICIENT), + 'spoiler_lift_coefficient': inputs.get_val(Mission.Takeoff.SPOILER_LIFT_COEFFICIENT), + } +} # endregion - takeoff aero @@ -489,58 +491,59 @@ takeoff_brake_release_user_options = AviaryValues() takeoff_brake_release_user_options.set_val('max_duration', val=60.0, units='s') -takeoff_brake_release_user_options.set_val('duration_ref', val=60.0, units='s') +takeoff_brake_release_user_options.set_val('time_duration_ref', val=60.0, units='s') takeoff_brake_release_user_options.set_val('distance_max', val=7500.0, units='ft') takeoff_brake_release_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_brake_release_initial_guesses = AviaryValues() -takeoff_brake_release_initial_guesses.set_val('time', [0., 30.], 's') -takeoff_brake_release_initial_guesses.set_val('distance', [0., 4100.], 'ft') -takeoff_brake_release_initial_guesses.set_val('velocity', [0.01, 150.], 'kn') +takeoff_brake_release_initial_guesses.set_val('time', [0.0, 30.0], 's') +takeoff_brake_release_initial_guesses.set_val('distance', [0.0, 4100.0], 'ft') +takeoff_brake_release_initial_guesses.set_val('velocity', [0.01, 150.0], 'kn') gross_mass_units = 'lbm' gross_mass = inputs.get_val(Mission.Design.GROSS_MASS, gross_mass_units) takeoff_brake_release_initial_guesses.set_val('mass', gross_mass, gross_mass_units) -takeoff_brake_release_initial_guesses.set_val('throttle', 1.) -takeoff_brake_release_initial_guesses.set_val('angle_of_attack', 0., 'deg') +takeoff_brake_release_initial_guesses.set_val('throttle', 1.0) +takeoff_brake_release_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, 'deg') takeoff_brake_release_builder = TakeoffBrakeReleaseToDecisionSpeed( 'takeoff_brake_release', core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_brake_release_user_options, - initial_guesses=takeoff_brake_release_initial_guesses,) + initial_guesses=takeoff_brake_release_initial_guesses, +) -takeoff_trajectory_builder.set_brake_release_to_decision_speed( - takeoff_brake_release_builder) +takeoff_trajectory_builder.set_brake_release_to_decision_speed(takeoff_brake_release_builder) # endregion - takeoff brake release # region - takeoff decision speed takeoff_decision_speed_user_options = AviaryValues() takeoff_decision_speed_user_options.set_val('max_duration', val=60.0, units='s') -takeoff_decision_speed_user_options.set_val('duration_ref', val=60.0, units='s') -takeoff_decision_speed_user_options.set_val('initial_ref', val=35.0, units='s') +takeoff_decision_speed_user_options.set_val('time_duration_ref', val=60.0, units='s') +takeoff_decision_speed_user_options.set_val('time_initial_ref', val=35.0, units='s') takeoff_decision_speed_user_options.set_val('distance_max', val=7500.0, units='ft') takeoff_decision_speed_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_decision_speed_initial_guesses = AviaryValues() -takeoff_decision_speed_initial_guesses.set_val('time', [30., 2.], 's') -takeoff_decision_speed_initial_guesses.set_val('distance', [4100., 4500.], 'ft') -takeoff_decision_speed_initial_guesses.set_val('velocity', [150., 160.], 'kn') +takeoff_decision_speed_initial_guesses.set_val('time', [30.0, 2.0], 's') +takeoff_decision_speed_initial_guesses.set_val('distance', [4100.0, 4500.0], 'ft') +takeoff_decision_speed_initial_guesses.set_val('velocity', [150.0, 160.0], 'kn') takeoff_decision_speed_initial_guesses.set_val('mass', gross_mass, gross_mass_units) -takeoff_decision_speed_initial_guesses.set_val('throttle', 1.) -takeoff_decision_speed_initial_guesses.set_val('angle_of_attack', 0., 'deg') +takeoff_decision_speed_initial_guesses.set_val('throttle', 1.0) +takeoff_decision_speed_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, 'deg') takeoff_decision_speed_builder = TakeoffDecisionSpeedToRotate( 'takeoff_decision_speed', core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_decision_speed_user_options, - initial_guesses=takeoff_decision_speed_initial_guesses) + initial_guesses=takeoff_decision_speed_initial_guesses, +) takeoff_trajectory_builder.set_decision_speed_to_rotate(takeoff_decision_speed_builder) # endregion - takeoff decision speed @@ -549,19 +552,19 @@ takeoff_rotate_user_options = AviaryValues() takeoff_rotate_user_options.set_val('max_duration', val=60.0, units='s') -takeoff_rotate_user_options.set_val('duration_ref', val=60.0, units='s') -takeoff_rotate_user_options.set_val('initial_ref', val=38.0, units='s') +takeoff_rotate_user_options.set_val('time_duration_ref', val=60.0, units='s') +takeoff_rotate_user_options.set_val('time_initial_ref', val=38.0, units='s') takeoff_rotate_user_options.set_val('distance_max', val=7500.0, units='ft') takeoff_rotate_user_options.set_val('max_velocity', val=167.85, units='kn') takeoff_rotate_user_options.set_val('max_angle_of_attack', val=10.0, units='deg') takeoff_rotate_initial_guesses = AviaryValues() -takeoff_rotate_initial_guesses.set_val('time', [32., 1.], 's') -takeoff_rotate_initial_guesses.set_val('distance', [4500, 4800.0], 'ft') -takeoff_rotate_initial_guesses.set_val('velocity', [160., 160.0], 'kn') -takeoff_rotate_initial_guesses.set_val('throttle', 1.) -takeoff_rotate_initial_guesses.set_val('angle_of_attack', [0., 8.], 'deg') +takeoff_rotate_initial_guesses.set_val('time', [32.0, 1.0], 's') +takeoff_rotate_initial_guesses.set_val('distance', [4500.0, 4800.0], 'ft') +takeoff_rotate_initial_guesses.set_val('velocity', [160.0, 160.0], 'kn') +takeoff_rotate_initial_guesses.set_val('throttle', 1.0) +takeoff_rotate_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [0.0, 8.0], 'deg') takeoff_rotate_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_rotate_builder = TakeoffRotateToLiftoff( @@ -569,7 +572,8 @@ core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_rotate_user_options, - initial_guesses=takeoff_rotate_initial_guesses) + initial_guesses=takeoff_rotate_initial_guesses, +) takeoff_trajectory_builder.set_rotate_to_liftoff(takeoff_rotate_builder) # endregion - takeoff rotate @@ -577,27 +581,26 @@ # region - takeoff liftoff takeoff_liftoff_user_options = AviaryValues() -takeoff_liftoff_user_options.set_val('max_duration', val=12., units='s') -takeoff_liftoff_user_options.set_val('duration_ref', val=12., units='s') -takeoff_liftoff_user_options.set_val('initial_ref', val=39.0, units='s') -takeoff_liftoff_user_options.set_val('distance_max', val=7500., units='ft') +takeoff_liftoff_user_options.set_val('max_duration', val=12.0, units='s') +takeoff_liftoff_user_options.set_val('time_duration_ref', val=12.0, units='s') +takeoff_liftoff_user_options.set_val('time_initial_ref', val=39.0, units='s') +takeoff_liftoff_user_options.set_val('distance_max', val=7500.0, units='ft') takeoff_liftoff_user_options.set_val('max_velocity', val=167.85, units='kn') -takeoff_liftoff_user_options.set_val('altitude_ref', val=35., units='ft') -takeoff_liftoff_user_options.set_val('flight_path_angle_ref', val=10., units='deg') +takeoff_liftoff_user_options.set_val('altitude_ref', val=35.0, units='ft') +takeoff_liftoff_user_options.set_val('flight_path_angle_ref', val=10.0, units='deg') takeoff_liftoff_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') takeoff_liftoff_user_options.set_val('upper_angle_of_attack', val=8.117, units='deg') -takeoff_liftoff_user_options.set_val('angle_of_attack_ref', val=10., units='deg') +takeoff_liftoff_user_options.set_val('angle_of_attack_ref', val=10.0, units='deg') takeoff_liftoff_initial_guesses = AviaryValues() -takeoff_liftoff_initial_guesses.set_val('time', [33., 4.], 's') +takeoff_liftoff_initial_guesses.set_val('time', [33.0, 4.0], 's') takeoff_liftoff_initial_guesses.set_val('distance', [4800, 5700.0], 'ft') takeoff_liftoff_initial_guesses.set_val('velocity', [160, 167.0], 'kn') -takeoff_liftoff_initial_guesses.set_val('throttle', 1.) +takeoff_liftoff_initial_guesses.set_val('throttle', 1.0) takeoff_liftoff_initial_guesses.set_val('altitude', [0, 35.0], 'ft') -takeoff_liftoff_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [0, 6.0], 'deg') -takeoff_liftoff_initial_guesses.set_val('angle_of_attack', 8.117, 'deg') +takeoff_liftoff_initial_guesses.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [0, 6.0], 'deg') +takeoff_liftoff_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 8.117, 'deg') takeoff_liftoff_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_liftoff_builder = TakeoffLiftoffToObstacle( @@ -605,7 +608,8 @@ core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_liftoff_user_options, - initial_guesses=takeoff_liftoff_initial_guesses) + initial_guesses=takeoff_liftoff_initial_guesses, +) takeoff_trajectory_builder.set_liftoff_to_obstacle(takeoff_liftoff_builder) # endregion - takeoff liftoff @@ -613,34 +617,31 @@ # region - takeoff mic p2 takeoff_mic_p2_user_options = AviaryValues() -takeoff_mic_p2_user_options.set_val('max_duration', val=25., units='s') -takeoff_mic_p2_user_options.set_val('duration_ref', val=25., units='s') -takeoff_mic_p2_user_options.set_val('initial_ref', val=50.0, units='s') -takeoff_mic_p2_user_options.set_val('distance_max', val=12000., units='ft') +takeoff_mic_p2_user_options.set_val('max_duration', val=25.0, units='s') +takeoff_mic_p2_user_options.set_val('time_duration_ref', val=25.0, units='s') +takeoff_mic_p2_user_options.set_val('time_initial_ref', val=50.0, units='s') +takeoff_mic_p2_user_options.set_val('distance_max', val=12000.0, units='ft') takeoff_mic_p2_user_options.set_val('max_velocity', val=167.85, units='kn') -takeoff_mic_p2_user_options.set_val('altitude_ref', val=1500., units='ft') -takeoff_mic_p2_user_options.set_val('mic_altitude', val=985., units='ft') +takeoff_mic_p2_user_options.set_val('altitude_ref', val=1500.0, units='ft') +takeoff_mic_p2_user_options.set_val('mic_altitude', val=985.0, units='ft') -takeoff_mic_p2_user_options.set_val( - 'flight_path_angle_ref', val=12., units='deg') +takeoff_mic_p2_user_options.set_val('flight_path_angle_ref', val=12.0, units='deg') -takeoff_mic_p2_user_options.set_val( - 'lower_angle_of_attack', val=0.0, units='deg') +takeoff_mic_p2_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') takeoff_mic_p2_user_options.set_val('upper_angle_of_attack', val=12, units='deg') -takeoff_mic_p2_user_options.set_val('angle_of_attack_ref', val=10., units='deg') -takeoff_mic_p2_user_options.set_val('mic_altitude', val=985., units='ft') +takeoff_mic_p2_user_options.set_val('angle_of_attack_ref', val=10.0, units='deg') +takeoff_mic_p2_user_options.set_val('mic_altitude', val=985.0, units='ft') takeoff_mic_p2_initial_guesses = AviaryValues() -takeoff_mic_p2_initial_guesses.set_val('time', [36., 18], 's') +takeoff_mic_p2_initial_guesses.set_val('time', [36.0, 18], 's') takeoff_mic_p2_initial_guesses.set_val('distance', [5700, 10000.0], 'ft') takeoff_mic_p2_initial_guesses.set_val('velocity', [167, 167.0], 'kn') -takeoff_mic_p2_initial_guesses.set_val('throttle', 1.) +takeoff_mic_p2_initial_guesses.set_val('throttle', 1.0) takeoff_mic_p2_initial_guesses.set_val('altitude', [35, 985.0], 'ft') -takeoff_mic_p2_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [7.0, 10.0], 'deg') -takeoff_mic_p2_initial_guesses.set_val('angle_of_attack', 8.117, 'deg') +takeoff_mic_p2_initial_guesses.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [7.0, 10.0], 'deg') +takeoff_mic_p2_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 8.117, 'deg') takeoff_mic_p2_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_mic_p2_builder = TakeoffObstacleToMicP2( @@ -648,7 +649,8 @@ core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_mic_p2_user_options, - initial_guesses=takeoff_mic_p2_initial_guesses) + initial_guesses=takeoff_mic_p2_initial_guesses, +) takeoff_trajectory_builder.set_obstacle_to_mic_p2(takeoff_mic_p2_builder) # endregion - takeoff mic p2 @@ -656,60 +658,55 @@ # region - mic p2 to engine cutback takeoff_mic_p2_to_engine_cutback_user_options = AviaryValues() -takeoff_mic_p2_to_engine_cutback_user_options.set_val('max_duration', val=30., units='s') -takeoff_mic_p2_to_engine_cutback_user_options.set_val('duration_ref', val=40., units='s') -takeoff_mic_p2_to_engine_cutback_user_options.set_val('initial_ref', val=65.0, units='s') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('max_duration', val=30.0, units='s') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('time_duration_ref', val=40.0, units='s') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('time_initial_ref', val=65.0, units='s') -takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'distance_max', val=20000., units='ft') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('distance_max', val=20000.0, units='ft') -takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'max_velocity', val=167.85, units='kn') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('max_velocity', val=167.85, units='kn') -takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'altitude_ref', val=3000., units='ft') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('altitude_ref', val=3000.0, units='ft') takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'flight_path_angle_ref', val=12., units='deg') + 'flight_path_angle_ref', val=12.0, units='deg' +) -takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'lower_angle_of_attack', val=0.0, units='deg') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') -takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'upper_angle_of_attack', val=12, units='deg') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('upper_angle_of_attack', val=12, units='deg') -takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'angle_of_attack_ref', val=10., units='deg') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('angle_of_attack_ref', val=10.0, units='deg') -takeoff_mic_p2_to_engine_cutback_user_options.set_val( - 'final_range', val=19000., units='ft') +takeoff_mic_p2_to_engine_cutback_user_options.set_val('final_range', val=19000.0, units='ft') takeoff_mic_p2_to_engine_cutback_initial_guesses = AviaryValues() -takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('time', [53., 27], 's') -takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val( - 'distance', [10000, 19000.0], 'ft') +takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('time', [53.0, 27], 's') +takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('distance', [10000, 19000.0], 'ft') takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('throttle', 1.0) takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('altitude', [985, 2500.0], 'ft') takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [11.0, 10.0], 'deg') - -takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [11.0, 10.0], 'deg' +) takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val( - 'mass', gross_mass, gross_mass_units) + Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.0, 'deg' +) + +takeoff_mic_p2_to_engine_cutback_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_mic_p2_to_engine_cutback_builder = TakeoffMicP2ToEngineCutback( 'takeoff_mic_p2_to_engine_cutback', core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_mic_p2_to_engine_cutback_user_options, - initial_guesses=takeoff_mic_p2_to_engine_cutback_initial_guesses) + initial_guesses=takeoff_mic_p2_to_engine_cutback_initial_guesses, +) -takeoff_trajectory_builder.set_mic_p2_to_engine_cutback( - takeoff_mic_p2_to_engine_cutback_builder) +takeoff_trajectory_builder.set_mic_p2_to_engine_cutback(takeoff_mic_p2_to_engine_cutback_builder) # endregion - mic p2 to engine cutback # region - engine cutback phase @@ -726,32 +723,31 @@ cutback_rate = 0.1 # Throttle setting per second cutback_duration = (1.0 - cutback_throttle) / cutback_rate -takeoff_engine_cutback_user_options.set_val('initial_ref', val=95.0, units='s') -takeoff_engine_cutback_user_options.set_val('distance_max', val=21000., units='ft') +takeoff_engine_cutback_user_options.set_val('time_initial_ref', val=95.0, units='s') +takeoff_engine_cutback_user_options.set_val('distance_max', val=21000.0, units='ft') takeoff_engine_cutback_user_options.set_val('max_velocity', val=167.85, units='kn') -takeoff_engine_cutback_user_options.set_val('altitude_ref', val=4000., units='ft') +takeoff_engine_cutback_user_options.set_val('altitude_ref', val=4000.0, units='ft') -takeoff_engine_cutback_user_options.set_val( - 'flight_path_angle_ref', val=12., units='deg') +takeoff_engine_cutback_user_options.set_val('flight_path_angle_ref', val=12.0, units='deg') -takeoff_engine_cutback_user_options.set_val( - 'lower_angle_of_attack', val=0.0, units='deg') +takeoff_engine_cutback_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') takeoff_engine_cutback_user_options.set_val('upper_angle_of_attack', val=12, units='deg') -takeoff_engine_cutback_user_options.set_val('angle_of_attack_ref', val=10., units='deg') +takeoff_engine_cutback_user_options.set_val('angle_of_attack_ref', val=10.0, units='deg') takeoff_engine_cutback_initial_guesses = AviaryValues() -takeoff_engine_cutback_initial_guesses.set_val('time', [84., cutback_duration], 's') +takeoff_engine_cutback_initial_guesses.set_val('time', [84.0, cutback_duration], 's') takeoff_engine_cutback_initial_guesses.set_val('distance', [19000, 20000.0], 'ft') takeoff_engine_cutback_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_engine_cutback_initial_guesses.set_val('throttle', [1.0, cutback_throttle]) takeoff_engine_cutback_initial_guesses.set_val('altitude', [2500.0, 2600.0], 'ft') takeoff_engine_cutback_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [10.0, 10.0], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [10.0, 10.0], 'deg' +) -takeoff_engine_cutback_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') +takeoff_engine_cutback_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.0, 'deg') takeoff_engine_cutback_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_engine_cutback_builder = TakeoffEngineCutback( @@ -759,7 +755,8 @@ core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_engine_cutback_user_options, - initial_guesses=takeoff_engine_cutback_initial_guesses) + initial_guesses=takeoff_engine_cutback_initial_guesses, +) takeoff_trajectory_builder.set_engine_cutback(takeoff_engine_cutback_builder) # endregion - engine cutback phase @@ -767,98 +764,87 @@ # region - engine cutback to mic p1 takeoff_engine_cutback_to_mic_p1_user_options = AviaryValues() -takeoff_engine_cutback_to_mic_p1_user_options.set_val('max_duration', val=11., units='s') -takeoff_engine_cutback_to_mic_p1_user_options.set_val('duration_ref', val=11., units='s') -takeoff_engine_cutback_to_mic_p1_user_options.set_val('initial_ref', val=97.0, units='s') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('max_duration', val=11.0, units='s') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('time_duration_ref', val=11.0, units='s') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('time_initial_ref', val=97.0, units='s') -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'distance_max', val=22000., units='ft') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('distance_max', val=22000.0, units='ft') -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'max_velocity', val=167.85, units='kn') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('max_velocity', val=167.85, units='kn') -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'altitude_ref', val=3500., units='ft') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('altitude_ref', val=3500.0, units='ft') -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'mic_range', val=21325., units='ft') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('mic_range', val=21325.0, units='ft') takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'flight_path_angle_ref', val=12., units='deg') + 'flight_path_angle_ref', val=12.0, units='deg' +) -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'lower_angle_of_attack', val=0.0, units='deg') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'upper_angle_of_attack', val=15, units='deg') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('upper_angle_of_attack', val=15, units='deg') -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'angle_of_attack_ref', val=10., units='deg') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('angle_of_attack_ref', val=10.0, units='deg') -takeoff_engine_cutback_to_mic_p1_user_options.set_val( - 'mic_range', val=21325., units='ft') +takeoff_engine_cutback_to_mic_p1_user_options.set_val('mic_range', val=21325.0, units='ft') takeoff_engine_cutback_to_mic_p1_initial_guesses = AviaryValues() -takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('time', [87., 10], 's') -takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val( - 'distance', [20000, 21325.0], 'ft') +takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('time', [87.0, 10], 's') +takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('distance', [20000, 21325.0], 'ft') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('throttle', cutback_throttle) -takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val( - 'altitude', [2600, 2700.0], 'ft') +takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('altitude', [2600, 2700.0], 'ft') takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, 2.29, 'deg') -takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') - + Dynamic.Mission.FLIGHT_PATH_ANGLE, 2.29, 'deg' +) takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val( - 'mass', gross_mass, gross_mass_units) + Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.0, 'deg' +) + +takeoff_engine_cutback_to_mic_p1_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_engine_cutback_to_mic_p1_builder = TakeoffEngineCutbackToMicP1( 'takeoff_engine_cutback_to_mic_p1', core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_engine_cutback_to_mic_p1_user_options, - initial_guesses=takeoff_engine_cutback_to_mic_p1_initial_guesses) + initial_guesses=takeoff_engine_cutback_to_mic_p1_initial_guesses, +) -takeoff_trajectory_builder.set_engine_cutback_to_mic_p1( - takeoff_engine_cutback_to_mic_p1_builder) +takeoff_trajectory_builder.set_engine_cutback_to_mic_p1(takeoff_engine_cutback_to_mic_p1_builder) # endregion - engine cutback to mic p1 # region - mic p1 to climb takeoff_mic_p1_to_climb_user_options = AviaryValues() -takeoff_mic_p1_to_climb_user_options.set_val('max_duration', val=40., units='s') -takeoff_mic_p1_to_climb_user_options.set_val('duration_ref', val=40., units='s') -takeoff_mic_p1_to_climb_user_options.set_val('initial_ref', val=100.0, units='s') -takeoff_mic_p1_to_climb_user_options.set_val('distance_max', val=30000., units='ft') +takeoff_mic_p1_to_climb_user_options.set_val('max_duration', val=40.0, units='s') +takeoff_mic_p1_to_climb_user_options.set_val('time_duration_ref', val=40.0, units='s') +takeoff_mic_p1_to_climb_user_options.set_val('time_initial_ref', val=100.0, units='s') +takeoff_mic_p1_to_climb_user_options.set_val('distance_max', val=30000.0, units='ft') takeoff_mic_p1_to_climb_user_options.set_val('max_velocity', val=167.85, units='kn') -takeoff_mic_p1_to_climb_user_options.set_val('altitude_ref', val=4000., units='ft') +takeoff_mic_p1_to_climb_user_options.set_val('altitude_ref', val=4000.0, units='ft') -takeoff_mic_p1_to_climb_user_options.set_val( - 'flight_path_angle_ref', val=12., units='deg') +takeoff_mic_p1_to_climb_user_options.set_val('flight_path_angle_ref', val=12.0, units='deg') -takeoff_mic_p1_to_climb_user_options.set_val( - 'lower_angle_of_attack', val=0.0, units='deg') +takeoff_mic_p1_to_climb_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') -takeoff_mic_p1_to_climb_user_options.set_val( - 'upper_angle_of_attack', val=15, units='deg') +takeoff_mic_p1_to_climb_user_options.set_val('upper_angle_of_attack', val=15, units='deg') -takeoff_mic_p1_to_climb_user_options.set_val('angle_of_attack_ref', val=10., units='deg') -takeoff_mic_p1_to_climb_user_options.set_val('mic_range', val=30000., units='ft') +takeoff_mic_p1_to_climb_user_options.set_val('angle_of_attack_ref', val=10.0, units='deg') +takeoff_mic_p1_to_climb_user_options.set_val('mic_range', val=30000.0, units='ft') takeoff_mic_p1_to_climb_initial_guesses = AviaryValues() -takeoff_mic_p1_to_climb_initial_guesses.set_val('time', [95., 32], 's') +takeoff_mic_p1_to_climb_initial_guesses.set_val('time', [95.0, 32], 's') takeoff_mic_p1_to_climb_initial_guesses.set_val('distance', [21325, 30000.0], 'ft') takeoff_mic_p1_to_climb_initial_guesses.set_val('velocity', [167, 167.0], 'kn') takeoff_mic_p1_to_climb_initial_guesses.set_val('throttle', cutback_throttle) takeoff_mic_p1_to_climb_initial_guesses.set_val('altitude', [2700, 3200.0], 'ft') -takeoff_mic_p1_to_climb_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, 2.29, 'deg') -takeoff_mic_p1_to_climb_initial_guesses.set_val('angle_of_attack', 5.0, 'deg') +takeoff_mic_p1_to_climb_initial_guesses.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, 2.29, 'deg') +takeoff_mic_p1_to_climb_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.0, 'deg') takeoff_mic_p1_to_climb_initial_guesses.set_val('mass', gross_mass, gross_mass_units) takeoff_mic_p1_to_climb_builder = TakeoffMicP1ToClimb( @@ -866,7 +852,8 @@ core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=takeoff_mic_p1_to_climb_user_options, - initial_guesses=takeoff_mic_p1_to_climb_initial_guesses) + initial_guesses=takeoff_mic_p1_to_climb_initial_guesses, +) takeoff_trajectory_builder.set_mic_p1_to_climb(takeoff_mic_p1_to_climb_builder) # endregion - mic p1 to climb @@ -878,19 +865,18 @@ detailed_takeoff = AviaryValues() detailed_takeoff.set_val('time', [0.77, 32.01, 33.00, 35.40], 's') -detailed_takeoff.set_val(Dynamic.Mission.DISTANCE, [ - 3.08, 4626.88, 4893.40, 5557.61], 'ft') +detailed_takeoff.set_val(Dynamic.Mission.DISTANCE, [3.08, 4626.88, 4893.40, 5557.61], 'ft') detailed_takeoff.set_val(Dynamic.Mission.ALTITUDE, [0.00, 0.00, 0.64, 27.98], 'ft') velocity = np.array([4.74, 157.58, 160.99, 166.68]) detailed_takeoff.set_val(Dynamic.Mission.VELOCITY, velocity, 'kn') -detailed_takeoff.set_val(Dynamic.Mission.MACH, [0.007, 0.2342, 0.2393, 0.2477]) +detailed_takeoff.set_val(Dynamic.Atmosphere.MACH, [0.007, 0.2342, 0.2393, 0.2477]) detailed_takeoff.set_val( - Dynamic.Mission.THRUST_TOTAL, [44038.8, 34103.4, 33929.0, 33638.2], 'lbf') + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, [44038.8, 34103.4, 33929.0, 33638.2], 'lbf' +) -detailed_takeoff.set_val('angle_of_attack', [0.000, 3.600, 8.117, 8.117], 'deg') -detailed_takeoff.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [ - 0.000, 0.000, 0.612, 4.096], 'deg') +detailed_takeoff.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [0.000, 3.600, 8.117, 8.117], 'deg') +detailed_takeoff.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [0.000, 0.000, 0.612, 4.096], 'deg') # missing from the default FLOPS output generated by hand # RANGE_RATE = VELOCITY * cos(flight_path_angle) @@ -908,8 +894,7 @@ # NOTE FLOPS output is based on "constant" takeoff mass - assume gross weight # - currently neglecting taxi -detailed_takeoff.set_val(Dynamic.Mission.MASS, [ - 129734., 129734., 129734., 129734.], 'lbm') +detailed_takeoff.set_val(Dynamic.Vehicle.MASS, [129734.0, 129734.0, 129734.0, 129734.0], 'lbm') lift_coeff = np.array([0.5580, 0.9803, 1.4831, 1.3952]) drag_coeff = np.array([0.0801, 0.0859, 0.1074, 0.1190]) @@ -922,16 +907,16 @@ RHV2 = 0.5 * rho * v * v * S lift = RHV2 * lift_coeff # N -detailed_takeoff.set_val(Dynamic.Mission.LIFT, lift, 'N') +detailed_takeoff.set_val(Dynamic.Vehicle.LIFT, lift, 'N') drag = RHV2 * drag_coeff # N -detailed_takeoff.set_val(Dynamic.Mission.DRAG, drag, 'N') +detailed_takeoff.set_val(Dynamic.Vehicle.DRAG, drag, 'N') def _split_aviary_values(aviary_values, slicing): tmp = AviaryValues() - for (key, (val, units)) in aviary_values: + for key, (val, units) in aviary_values: tmpval = val[slicing] tmp.set_val(key, tmpval, units) @@ -948,34 +933,34 @@ def _split_aviary_values(aviary_values, slicing): balanced_brake_release_user_options = AviaryValues() balanced_brake_release_user_options.set_val('max_duration', val=60.0, units='s') -balanced_brake_release_user_options.set_val('duration_ref', val=60.0, units='s') +balanced_brake_release_user_options.set_val('time_duration_ref', val=60.0, units='s') balanced_brake_release_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_brake_release_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_brake_release_initial_guesses = AviaryValues() -balanced_brake_release_initial_guesses.set_val('time', [0., 30.], 's') -balanced_brake_release_initial_guesses.set_val('distance', [0., 4100.], 'ft') -balanced_brake_release_initial_guesses.set_val('velocity', [0.01, 150.], 'kn') +balanced_brake_release_initial_guesses.set_val('time', [0.0, 30.0], 's') +balanced_brake_release_initial_guesses.set_val('distance', [0.0, 4100.0], 'ft') +balanced_brake_release_initial_guesses.set_val('velocity', [0.01, 150.0], 'kn') balanced_brake_release_initial_guesses.set_val('mass', gross_mass, gross_mass_units) -balanced_brake_release_initial_guesses.set_val('throttle', 1.) -balanced_brake_release_initial_guesses.set_val('angle_of_attack', 0., 'deg') +balanced_brake_release_initial_guesses.set_val('throttle', 1.0) +balanced_brake_release_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, 'deg') balanced_brake_release_builder = TakeoffBrakeReleaseToDecisionSpeed( 'balanced_brake_release', core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=balanced_brake_release_user_options, - initial_guesses=balanced_brake_release_initial_guesses) + initial_guesses=balanced_brake_release_initial_guesses, +) -balanced_trajectory_builder.set_brake_release_to_decision_speed( - balanced_brake_release_builder) +balanced_trajectory_builder.set_brake_release_to_decision_speed(balanced_brake_release_builder) balanced_decision_speed_user_options = AviaryValues() balanced_decision_speed_user_options.set_val('max_duration', val=60.0, units='s') -balanced_decision_speed_user_options.set_val('duration_ref', val=5.0, units='s') -balanced_decision_speed_user_options.set_val('initial_ref', val=35.0, units='s') +balanced_decision_speed_user_options.set_val('time_duration_ref', val=5.0, units='s') +balanced_decision_speed_user_options.set_val('time_initial_ref', val=35.0, units='s') balanced_decision_speed_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_decision_speed_user_options.set_val('max_velocity', val=167.85, units='kn') @@ -984,39 +969,39 @@ def _split_aviary_values(aviary_values, slicing): num_engines = float(inputs.get_val(Aircraft.Engine.NUM_ENGINES)) engine_out_throttle = (num_engines - 1) / num_engines -balanced_decision_speed_initial_guesses.set_val('time', [30., 2.], 's') -balanced_decision_speed_initial_guesses.set_val('distance', [4100., 4500.], 'ft') -balanced_decision_speed_initial_guesses.set_val('velocity', [150., 160.], 'kn') +balanced_decision_speed_initial_guesses.set_val('time', [30.0, 2.0], 's') +balanced_decision_speed_initial_guesses.set_val('distance', [4100.0, 4500.0], 'ft') +balanced_decision_speed_initial_guesses.set_val('velocity', [150.0, 160.0], 'kn') balanced_decision_speed_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_decision_speed_initial_guesses.set_val('throttle', engine_out_throttle) -balanced_decision_speed_initial_guesses.set_val('angle_of_attack', 0., 'deg') +balanced_decision_speed_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, 'deg') balanced_decision_speed_builder = TakeoffDecisionSpeedToRotate( 'balanced_decision_speed', core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=balanced_decision_speed_user_options, - initial_guesses=balanced_decision_speed_initial_guesses) + initial_guesses=balanced_decision_speed_initial_guesses, +) -balanced_trajectory_builder.set_decision_speed_to_rotate( - balanced_decision_speed_builder) +balanced_trajectory_builder.set_decision_speed_to_rotate(balanced_decision_speed_builder) balanced_rotate_user_options = AviaryValues() balanced_rotate_user_options.set_val('max_duration', val=20.0, units='s') -balanced_rotate_user_options.set_val('duration_ref', val=5.0, units='s') -balanced_rotate_user_options.set_val('initial_ref', val=35.0, units='s') +balanced_rotate_user_options.set_val('time_duration_ref', val=5.0, units='s') +balanced_rotate_user_options.set_val('time_initial_ref', val=35.0, units='s') balanced_rotate_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_rotate_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_rotate_user_options.set_val('max_angle_of_attack', val=8.117, units='deg') balanced_rotate_initial_guesses = AviaryValues() -balanced_rotate_initial_guesses.set_val('time', [32., 1.], 's') -balanced_rotate_initial_guesses.set_val('distance', [4500., 4800.], 'ft') -balanced_rotate_initial_guesses.set_val('velocity', [160., 160.], 'kn') +balanced_rotate_initial_guesses.set_val('time', [32.0, 1.0], 's') +balanced_rotate_initial_guesses.set_val('distance', [4500.0, 4800.0], 'ft') +balanced_rotate_initial_guesses.set_val('velocity', [160.0, 160.0], 'kn') balanced_rotate_initial_guesses.set_val('throttle', engine_out_throttle) -balanced_rotate_initial_guesses.set_val('angle_of_attack', [0., 8.], 'deg') +balanced_rotate_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [0.0, 8.0], 'deg') balanced_rotate_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_rotate_builder = TakeoffRotateToLiftoff( @@ -1024,34 +1009,33 @@ def _split_aviary_values(aviary_values, slicing): core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=balanced_rotate_user_options, - initial_guesses=balanced_rotate_initial_guesses) + initial_guesses=balanced_rotate_initial_guesses, +) -balanced_trajectory_builder.set_rotate_to_liftoff( - balanced_rotate_builder) +balanced_trajectory_builder.set_rotate_to_liftoff(balanced_rotate_builder) balanced_liftoff_user_options = AviaryValues() -balanced_liftoff_user_options.set_val('max_duration', val=20., units='s') -balanced_liftoff_user_options.set_val('duration_ref', val=20., units='s') -balanced_liftoff_user_options.set_val('initial_ref', val=40.0, units='s') -balanced_liftoff_user_options.set_val('distance_max', val=7500., units='ft') +balanced_liftoff_user_options.set_val('max_duration', val=20.0, units='s') +balanced_liftoff_user_options.set_val('time_duration_ref', val=20.0, units='s') +balanced_liftoff_user_options.set_val('time_initial_ref', val=40.0, units='s') +balanced_liftoff_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_liftoff_user_options.set_val('max_velocity', val=167.85, units='kn') -balanced_liftoff_user_options.set_val('altitude_ref', val=35., units='ft') -balanced_liftoff_user_options.set_val('flight_path_angle_ref', val=5., units='deg') +balanced_liftoff_user_options.set_val('altitude_ref', val=35.0, units='ft') +balanced_liftoff_user_options.set_val('flight_path_angle_ref', val=5.0, units='deg') balanced_liftoff_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') balanced_liftoff_user_options.set_val('upper_angle_of_attack', val=8.117, units='deg') -balanced_liftoff_user_options.set_val('angle_of_attack_ref', val=10., units='deg') +balanced_liftoff_user_options.set_val('angle_of_attack_ref', val=10.0, units='deg') balanced_liftoff_initial_guesses = AviaryValues() -balanced_liftoff_initial_guesses.set_val('time', [33., 4.], 's') -balanced_liftoff_initial_guesses.set_val('distance', [4800., 7000.], 'ft') -balanced_liftoff_initial_guesses.set_val('velocity', [160., 167.], 'kn') +balanced_liftoff_initial_guesses.set_val('time', [33.0, 4.0], 's') +balanced_liftoff_initial_guesses.set_val('distance', [4800.0, 7000.0], 'ft') +balanced_liftoff_initial_guesses.set_val('velocity', [160.0, 167.0], 'kn') balanced_liftoff_initial_guesses.set_val('throttle', engine_out_throttle) -balanced_liftoff_initial_guesses.set_val('altitude', [0., 35.], 'ft') -balanced_liftoff_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [0., 5.], 'deg') -balanced_liftoff_initial_guesses.set_val('angle_of_attack', 8.117, 'deg') +balanced_liftoff_initial_guesses.set_val('altitude', [0.0, 35.0], 'ft') +balanced_liftoff_initial_guesses.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [0.0, 5.0], 'deg') +balanced_liftoff_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 8.117, 'deg') balanced_liftoff_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_liftoff_builder = TakeoffLiftoffToObstacle( @@ -1059,26 +1043,26 @@ def _split_aviary_values(aviary_values, slicing): core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=balanced_liftoff_user_options, - initial_guesses=balanced_liftoff_initial_guesses) + initial_guesses=balanced_liftoff_initial_guesses, +) -balanced_trajectory_builder.set_liftoff_to_obstacle( - balanced_liftoff_builder) +balanced_trajectory_builder.set_liftoff_to_obstacle(balanced_liftoff_builder) balanced_delayed_brake_user_options = AviaryValues() -balanced_delayed_brake_user_options.set_val('duration_ref', val=4.0, units='s') -balanced_delayed_brake_user_options.set_val('initial_ref', val=35.0, units='s') +balanced_delayed_brake_user_options.set_val('time_duration_ref', val=4.0, units='s') +balanced_delayed_brake_user_options.set_val('time_initial_ref', val=35.0, units='s') balanced_delayed_brake_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_delayed_brake_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_delayed_brake_initial_guesses = AviaryValues() -balanced_delayed_brake_initial_guesses.set_val('time', [30., 3.], 's') -balanced_delayed_brake_initial_guesses.set_val('distance', [4100., 4600.], 'ft') -balanced_delayed_brake_initial_guesses.set_val('velocity', [150., 150.], 'kn') +balanced_delayed_brake_initial_guesses.set_val('time', [30.0, 3.0], 's') +balanced_delayed_brake_initial_guesses.set_val('distance', [4100.0, 4600.0], 'ft') +balanced_delayed_brake_initial_guesses.set_val('velocity', [150.0, 150.0], 'kn') balanced_delayed_brake_initial_guesses.set_val('mass', gross_mass, gross_mass_units) balanced_delayed_brake_initial_guesses.set_val('throttle', engine_out_throttle) -balanced_delayed_brake_initial_guesses.set_val('angle_of_attack', 0., 'deg') +balanced_delayed_brake_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, 'deg') # NOTE: no special handling required; re-use existing phase builder type balanced_delayed_brake_builder = TakeoffDecisionSpeedBrakeDelay( @@ -1086,66 +1070,81 @@ def _split_aviary_values(aviary_values, slicing): core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options, user_options=balanced_delayed_brake_user_options, - initial_guesses=balanced_delayed_brake_initial_guesses) + initial_guesses=balanced_delayed_brake_initial_guesses, +) balanced_trajectory_builder.set_decision_speed_to_brake(balanced_delayed_brake_builder) balanced_abort_user_options = AviaryValues() balanced_abort_user_options.set_val('max_duration', val=60.0, units='s') -balanced_abort_user_options.set_val('initial_ref', val=35.0, units='s') -balanced_abort_user_options.set_val('duration_ref', val=60.0, units='s') +balanced_abort_user_options.set_val('time_initial_ref', val=35.0, units='s') +balanced_abort_user_options.set_val('time_duration_ref', val=60.0, units='s') balanced_abort_user_options.set_val('distance_max', val=7500.0, units='ft') balanced_abort_user_options.set_val('max_velocity', val=167.85, units='kn') balanced_abort_initial_guesses = AviaryValues() -balanced_abort_initial_guesses.set_val('time', [32., 22.], 's') -balanced_abort_initial_guesses.set_val('distance', [4600., 7000.], 'ft') -balanced_abort_initial_guesses.set_val('velocity', [150., 0.01], 'kn') +balanced_abort_initial_guesses.set_val('time', [32.0, 22.0], 's') +balanced_abort_initial_guesses.set_val('distance', [4600.0, 7000.0], 'ft') +balanced_abort_initial_guesses.set_val('velocity', [150.0, 0.01], 'kn') balanced_abort_initial_guesses.set_val('mass', gross_mass, gross_mass_units) -balanced_abort_initial_guesses.set_val('throttle', 0.) -balanced_abort_initial_guesses.set_val('angle_of_attack', 0., 'deg') +balanced_abort_initial_guesses.set_val('throttle', 0.0) +balanced_abort_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, 'deg') balanced_abort_builder = TakeoffBrakeToAbort( 'balanced_abort', core_subsystems=default_mission_subsystems, subsystem_options=takeoff_subsystem_options_spoilers, user_options=balanced_abort_user_options, - initial_guesses=balanced_abort_initial_guesses) + initial_guesses=balanced_abort_initial_guesses, +) distance_max = balanced_liftoff_user_options.get_val('distance_max', 'ft') balanced_trajectory_builder.set_brake_to_abort( - balanced_abort_builder, balanced_field_ref=distance_max) + balanced_abort_builder, balanced_field_ref=distance_max +) # endregion balanced field length # region - detailed landing landing_trajectory_builder = LandingTrajectory('detailed_landing') +# block auto-formatting of tables +# fmt: off + # region - landing aero -landing_subsystem_options = {'core_aerodynamics': {'method': 'low_speed', - 'ground_altitude': 0., # units='m' - 'angles_of_attack': [ - 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, - 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, - 12.0, 13.0, 14.0, 15.0], # units='deg' - 'lift_coefficients': [ - 0.7, 0.9, 1.05, 1.15, 1.25, 1.4, - 1.5, 1.60, 1.7, 1.8, 1.9, 2.0, - 2.1, 2.2, 2.3, 2.40], - 'drag_coefficients': [ - 0.1, 0.1, 0.12, 0.13, 0.14, 0.15, - 0.16, 0.17, 0.18, 0.20, 0.22, 0.24, - 0.26, 0.3, 0.32, 0.34], - 'lift_coefficient_factor': 1., - 'drag_coefficient_factor': 1., }} - -landing_subsystem_options_spoilers = {'core_aerodynamics': { - **landing_subsystem_options['core_aerodynamics'], - 'use_spoilers': True, - 'spoiler_lift_coefficient': -0.81, - 'spoiler_drag_coefficient': 0.085}} +landing_subsystem_options = { + 'core_aerodynamics': { + 'method': 'low_speed', + 'ground_altitude': 0.0, # units='m' + 'angles_of_attack': [ + 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, + 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, + ], # units='deg' + 'lift_coefficients': [ + 0.7, 0.9, 1.05, 1.15, 1.25, 1.4, 1.5, 1.60, + 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.40, + ], + 'drag_coefficients': [ + 0.1, 0.1, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, + 0.18, 0.20, 0.22, 0.24, 0.26, 0.3, 0.32, 0.34, + ], + 'lift_coefficient_factor': 1.0, + 'drag_coefficient_factor': 1.0, + } +} + +# fmt: on + +landing_subsystem_options_spoilers = { + 'core_aerodynamics': { + **landing_subsystem_options['core_aerodynamics'], + 'use_spoilers': True, + 'spoiler_lift_coefficient': -0.81, + 'spoiler_drag_coefficient': 0.085, + } +} # VELOCITY TIME DISTANCE ALPHA ALTITUDE # KNOTS SEC. FEET DEG. FEET @@ -1158,105 +1157,116 @@ def _split_aviary_values(aviary_values, slicing): detailed_landing = AviaryValues() -values = np.array([ - -4.08, -4.08, -3.92, -3.76, -3.59, -3.43, -3.27, -3.1, -2.94, -2.78, - -2.61, -2.45, -2.29, -2.12, -1.96, -1.8, -1.63, -1.47, -1.31, -1.14, - -0.98, -0.82, -0.65, -0.49, -0.33, -0.16, 0, 0.16, 0.33, 0.49, - 0.65, 0.82, 0.98, 1.14, 1.31, 1.47, 1.63, 1.8, 1.96, 2.12, - 2.29, 2.45, 2.61, 2.78, 2.94, 3.1, 3.13, 3.92, 4.97, 5.68, - 5.93, 6.97, 7.97, 8.97, 9.97, 10.97, 11.97, 12.97, 13.97, 14.97, - 15.97, 16.97, 17.97, 18.97, 19.97, 20.97, 21.97, 22.97, 23.97, 24.49]) +# block auto-formatting of tables +# fmt: off +values = np.array( + [ + -4.08, -4.08, -3.92, -3.76, -3.59, -3.43, -3.27, -3.1, -2.94, -2.78, -2.61, -2.45, -2.29, + -2.12, -1.96, -1.8, -1.63, -1.47, -1.31, -1.14, -0.98, -0.82, -0.65, -0.49, -0.33, -0.16, 0, + 0.16, 0.33, 0.49, 0.65, 0.82, 0.98, 1.14, 1.31, 1.47, 1.63, 1.8, 1.96, 2.12, 2.29, 2.45, + 2.61, 2.78, 2.94, 3.1, 3.13, 3.92, 4.97, 5.68, 5.93, 6.97, 7.97, 8.97, 9.97, 10.97, 11.97, + 12.97, 13.97, 14.97, 15.97, 16.97, 17.97, 18.97, 19.97, 20.97, 21.97, 22.97, 23.97, 24.49 + ] +) base = values[0] values = values - base detailed_landing.set_val('time', values, 's') -values = np.array([ - -954.08, -954.06, -915.89, -877.73, -839.57, -801.41, -763.25, -725.08, - -686.92, -648.76, -610.6, -572.43, -534.27, -496.11, -457.95, -419.78, - -381.62, -343.46, -305.3, -267.14, -228.97, -190.81, -152.65, -114.49, - -76.32, -38.16, 0, 38.16, 76.32, 114.49, 152.65, 190.81, - 228.97, 267.14, 305.3, 343.46, 381.62, 419.78, 457.95, 496.11, - 534.27, 572.43, 610.6, 648.76, 686.92, 725.08, 731.46, 917.22, - 1160.47, 1324.21, 1381.29, 1610.61, 1817.53, 2010.56, 2190, 2356.17, - 2509.36, 2649.84, 2777.85, 2893.6, 2997.28, 3089.05, 3169.07, 3237.45, - 3294.31, 3339.73, 3373.78, 3396.51, 3407.96, 3409.47]) +values = np.array( + [ + -954.08, -954.06, -915.89, -877.73, -839.57, -801.41, -763.25, -725.08, -686.92, -648.76, + -610.6, -572.43, -534.27, -496.11, -457.95, -419.78, -381.62, -343.46, -305.3, -267.14, + -228.97, -190.81, -152.65, -114.49, -76.32, -38.16, 0, 38.16, 76.32, 114.49, 152.65, 190.81, + 228.97, 267.14, 305.3, 343.46, 381.62, 419.78, 457.95, 496.11, 534.27, 572.43, 610.6, + 648.76, 686.92, 725.08, 731.46, 917.22, 1160.47, 1324.21, 1381.29, 1610.61, 1817.53, + 2010.56, 2190, 2356.17, 2509.36, 2649.84, 2777.85, 2893.6, 2997.28, 3089.05, 3169.07, + 3237.45, 3294.31, 3339.73, 3373.78, 3396.51, 3407.96, 3409.47 + ] +) +# fmt: on base = values[0] values = values - base detailed_landing.set_val(Dynamic.Mission.DISTANCE, values, 'ft') +# block auto-formatting of tables +# fmt: off detailed_landing.set_val( Dynamic.Mission.ALTITUDE, [ - 100, 100, 98, 96, 94, 92, 90, 88, 86, 84, - 82, 80, 78, 76, 74, 72, 70, 68, 66, 64, - 62, 60, 58, 56, 54, 52, 50, 48, 46, 44, - 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, - 22, 20, 18, 16, 14, 12, 11.67, 2.49, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - 'ft') + 100, 100, 98, 96, 94, 92, 90, 88, 86, 84, 80, 78, 76, 74, 72, 70, 68, 66, 64, 62, 60, 58, + 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, + 11.67, 2.49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + 'ft', +) detailed_landing.set_val( Dynamic.Mission.VELOCITY, - np.array([ - 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, - 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, - 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, - 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, - 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.6, 137.18, 136.12, - 134.43, 126.69, 118.46, 110.31, 102.35, 94.58, 86.97, 79.52, 72.19, 64.99, - 57.88, 50.88, 43.95, 37.09, 30.29, 23.54, 16.82, 10.12, 3.45, 0]), - 'kn') + np.array( + [ + 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, + 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, + 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, + 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, 138.65, + 138.65, 138.65, 138.65, 138.60, 137.18, 136.12, 134.43, 126.69, 118.46, 110.31, 102.35, + 94.58, 86.97, 79.52, 72.19, 64.99, 57.88, 50.88, 43.95, 37.09, 30.29, 23.54, 16.82, + 10.12, 3.45, 0 + ] + ), + 'kn', +) detailed_landing.set_val( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, [ - 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, - 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, - 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, - 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, - 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.206, 0.2039, 0.2023, - 0.1998, 0.1883, 0.1761, 0.1639, 0.1521, 0.1406, 0.1293, 0.1182, 0.1073, 0.0966, - 0.086, 0.0756, 0.0653, 0.0551, 0.045, 0.035, 0.025, 0.015, 0.0051, 0]) + 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, + 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, + 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, + 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, 0.2061, + 0.2061, 0.2061, 0.2061, 0.2060, 0.2039, 0.2023, 0.1998, 0.1883, 0.1761, 0.1639, 0.1521, + 0.1406, 0.1293, 0.1182, 0.1073, 0.0966, 0.086, 0.0756, 0.0653, 0.0551, 0.045, 0.035, 0.025, + 0.015, 0.0051, 0, + ], +) detailed_landing.set_val( - Dynamic.Mission.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, [ - 7614, 7614, 7607.7, 7601, 7593.9, 7586.4, 7578.5, 7570.2, 7561.3, 7551.8, - 7541.8, 7531.1, 7519.7, 7507.6, 7494.6, 7480.6, 7465.7, 7449.7, 7432.5, 7414, - 7394, 7372.3, 7348.9, 7323.5, 7295.9, 7265.8, 7233, 7197.1, 7157.7, 7114.3, - 7066.6, 7013.8, 6955.3, 6890.2, 6817.7, 6736.7, 6645.8, 6543.5, 6428.2, 6297.6, - 6149.5, 5980.9, 5788.7, 5569.3, 5318.5, 5032, 4980.3, 4102, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - 'lbf') + 7614.0, 7614.0, 7607.7, 7601.0, 7593.9, 7586.4, 7578.5, 7570.2, 7561.3, 7551.8, 7541.8, + 7531.1, 7519.7, 7507.6, 7494.6, 7480.6, 7465.7, 7449.7, 7432.5, 7414.0, 7394.0, 7372.3, + 7348.9, 7323.5, 7295.9, 7265.8, 7233.0, 7197.1, 7157.7, 7114.3, 7066.6, 7013.8, 6955.3, + 6890.2, 6817.7, 6736.7, 6645.8, 6543.5, 6428.2, 6297.6, 6149.5, 5980.9, 5788.7, 5569.3, + 5318.5, 5032.0, 4980.3, 4102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ], + 'lbf', +) detailed_landing.set_val( - 'angle_of_attack', + Dynamic.Vehicle.ANGLE_OF_ATTACK, [ - 5.231, 5.231, 5.231, 5.23, 5.23, 5.23, 5.23, 5.23, 5.229, 5.229, - 5.229, 5.229, 5.228, 5.228, 5.227, 5.227, 5.227, 5.226, 5.226, 5.225, - 5.224, 5.224, 5.223, 5.222, 5.221, 5.22, 5.219, 5.218, 5.217, 5.215, - 5.214, 5.212, 5.21, 5.207, 5.204, 5.201, 5.197, 5.193, 5.187, 5.181, - 5.173, 5.163, 5.151, 5.136, 5.117, 5.091, 5.086, 6.834, 5.585, 4.023, - 3.473, 1.185, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 5.231, 5.231, 5.231, 5.23, 5.23, 5.23, 5.23, 5.23, 5.229, 5.229, 5.229, 5.229, 5.228, 5.228, + 5.227, 5.227, 5.227, 5.226, 5.226, 5.225, 5.224, 5.224, 5.223, 5.222, 5.221, 5.22, 5.219, + 5.218, 5.217, 5.215, 5.214, 5.212, 5.21, 5.207, 5.204, 5.201, 5.197, 5.193, 5.187, 5.181, + 5.173, 5.163, 5.151, 5.136, 5.117, 5.091, 5.086, 6.834, 5.585, 4.023, 3.473, 1.185, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], 'deg') # glide slope == flight path angle? detailed_landing.set_val( Dynamic.Mission.FLIGHT_PATH_ANGLE, - np.array([ - -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, - -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, - -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, - -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, - -3, -3, -3, -3, -3, -3, -3, -2.47, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), - 'deg') + np.array( + [ + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -3, -3, -3, -2.47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ] + ), + 'deg', +) +# fmt: on # missing from the default FLOPS output generated by script # RANGE_RATE = VELOCITY * cos(flight_path_angle) @@ -1274,29 +1284,38 @@ def _split_aviary_values(aviary_values, slicing): # NOTE FLOPS output is based on "constant" landing mass - assume reserves weight # - currently neglecting taxi -detailed_landing_mass = 106292. # units='lbm' +detailed_landing_mass = 106292.0 # units='lbm' detailed_landing.set_val( - Dynamic.Mission.MASS, np.full(velocity.shape, detailed_landing_mass), 'lbm') + Dynamic.Vehicle.MASS, np.full(velocity.shape, detailed_landing_mass), 'lbm' +) +# block auto-formatting of tables +# fmt: off # lift/drag is calculated very close to landing altitude (sea level, in this case)... -lift_coeff = np.array([ - 1.4091, 1.4091, 1.4091, 1.4091, 1.4092, 1.4092, 1.4092, 1.4092, 1.4092, 1.4092, - 1.4092, 1.4092, 1.4092, 1.4093, 1.4093, 1.4093, 1.4093, 1.4093, 1.4094, 1.4094, - 1.4094, 1.4094, 1.4095, 1.4095, 1.4095, 1.4096, 1.4096, 1.4096, 1.4097, 1.4097, - 1.4098, 1.4099, 1.4099, 1.41, 1.4101, 1.4102, 1.4103, 1.4105, 1.4106, 1.4108, - 1.4109, 1.4112, 1.4114, 1.4117, 1.412, 1.4124, 1.4124, 1.6667, 1.595, 1.397, - 0.5237, 0.2338, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, - 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046]) - -drag_coeff = np.array([ - 0.1731, 0.1731, 0.173, 0.173, 0.1729, 0.1728, 0.1727, 0.1726, 0.1724, 0.1723, - 0.1722, 0.1721, 0.1719, 0.1718, 0.1716, 0.1714, 0.1712, 0.171, 0.1708, 0.1705, - 0.1703, 0.17, 0.1697, 0.1694, 0.169, 0.1686, 0.1682, 0.1677, 0.1672, 0.1666, - 0.166, 0.1653, 0.1646, 0.1637, 0.1628, 0.1618, 0.1606, 0.1592, 0.1577, 0.1561, - 0.1541, 0.1519, 0.1495, 0.1466, 0.1434, 0.1396, 0.139, 0.13, 0.1207, 0.1099, - 0.1922, 0.1827, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, - 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785]) +lift_coeff = np.array( + [ + 1.4091, 1.4091, 1.4091, 1.4091, 1.4092, 1.4092, 1.4092, 1.4092, 1.4092, 1.4092, 1.4092, + 1.4092, 1.4092, 1.4093, 1.4093, 1.4093, 1.4093, 1.4093, 1.4094, 1.4094, 1.4094, 1.4094, + 1.4095, 1.4095, 1.4095, 1.4096, 1.4096, 1.4096, 1.4097, 1.4097, 1.4098, 1.4099, 1.4099, + 1.41, 1.4101, 1.4102, 1.4103, 1.4105, 1.4106, 1.4108, 1.4109, 1.4112, 1.4114, 1.4117, 1.412, + 1.4124, 1.4124, 1.6667, 1.595, 1.397, 0.5237, 0.2338, 0.046, 0.046, 0.046, 0.046, 0.046, + 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046 + ] +) + +drag_coeff = np.array( + [ + 0.1731, 0.1731, 0.173, 0.173, 0.1729, 0.1728, 0.1727, 0.1726, 0.1724, 0.1723, 0.1722, + 0.1721, 0.1719, 0.1718, 0.1716, 0.1714, 0.1712, 0.171, 0.1708, 0.1705, 0.1703, 0.17, 0.1697, + 0.1694, 0.169, 0.1686, 0.1682, 0.1677, 0.1672, 0.1666, 0.166, 0.1653, 0.1646, 0.1637, + 0.1628, 0.1618, 0.1606, 0.1592, 0.1577, 0.1561, 0.1541, 0.1519, 0.1495, 0.1466, 0.1434, + 0.1396, 0.139, 0.13, 0.1207, 0.1099, 0.1922, 0.1827, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, + 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, 0.1785, + 0.1785, 0.1785 + ] +) +# fmt: on S = inputs.get_val(Aircraft.Wing.AREA, 'm**2') v = detailed_landing.get_val(Dynamic.Mission.VELOCITY, 'm/s') @@ -1306,10 +1325,10 @@ def _split_aviary_values(aviary_values, slicing): RHV2 = 0.5 * rho * v * v * S lift = RHV2 * lift_coeff # N -detailed_landing.set_val(Dynamic.Mission.LIFT, lift, 'N') +detailed_landing.set_val(Dynamic.Vehicle.LIFT, lift, 'N') drag = RHV2 * drag_coeff # N -detailed_landing.set_val(Dynamic.Mission.DRAG, drag, 'N') +detailed_landing.set_val(Dynamic.Vehicle.DRAG, drag, 'N') # Flops variable APRANG apr_angle = -3.0 # deg @@ -1322,133 +1341,131 @@ def _split_aviary_values(aviary_values, slicing): # region - landing approach to mic P3 landing_approach_to_mic_p3_user_options = AviaryValues() -landing_approach_to_mic_p3_user_options.set_val('max_duration', val=50., units='s') -landing_approach_to_mic_p3_user_options.set_val('duration_ref', val=50., units='s') -landing_approach_to_mic_p3_user_options.set_val('initial_ref', val=50.0, units='s') -landing_approach_to_mic_p3_user_options.set_val('distance_max', val=10000., units='ft') -landing_approach_to_mic_p3_user_options.set_val('max_velocity', val=140., units='kn') -landing_approach_to_mic_p3_user_options.set_val('altitude_ref', val=800., units='ft') +landing_approach_to_mic_p3_user_options.set_val('max_duration', val=50.0, units='s') +landing_approach_to_mic_p3_user_options.set_val('time_duration_ref', val=50.0, units='s') +landing_approach_to_mic_p3_user_options.set_val('time_initial_ref', val=50.0, units='s') +landing_approach_to_mic_p3_user_options.set_val('distance_max', val=10000.0, units='ft') +landing_approach_to_mic_p3_user_options.set_val('max_velocity', val=140.0, units='kn') +landing_approach_to_mic_p3_user_options.set_val('altitude_ref', val=800.0, units='ft') -landing_approach_to_mic_p3_user_options.set_val( - 'lower_angle_of_attack', val=0., units='deg') +landing_approach_to_mic_p3_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') -landing_approach_to_mic_p3_user_options.set_val( - 'upper_angle_of_attack', val=12., units='deg') +landing_approach_to_mic_p3_user_options.set_val('upper_angle_of_attack', val=12.0, units='deg') -landing_approach_to_mic_p3_user_options.set_val( - 'angle_of_attack_ref', val=12., units='deg') +landing_approach_to_mic_p3_user_options.set_val('angle_of_attack_ref', val=12.0, units='deg') -landing_approach_to_mic_p3_user_options.set_val('initial_height', val=600., units='ft') +landing_approach_to_mic_p3_user_options.set_val('initial_height', val=600.0, units='ft') landing_approach_to_mic_p3_initial_guesses = AviaryValues() -landing_approach_to_mic_p3_initial_guesses.set_val('time', [-42., 15.], 's') -landing_approach_to_mic_p3_initial_guesses.set_val('distance', [-4000., -2000.], 'ft') -landing_approach_to_mic_p3_initial_guesses.set_val('velocity', 140., 'kn') +landing_approach_to_mic_p3_initial_guesses.set_val('time', [-42.0, 15.0], 's') +landing_approach_to_mic_p3_initial_guesses.set_val('distance', [-4000.0, -2000.0], 'ft') +landing_approach_to_mic_p3_initial_guesses.set_val('velocity', 140.0, 'kn') landing_approach_to_mic_p3_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_approach_to_mic_p3_initial_guesses.set_val('throttle', throttle) -landing_approach_to_mic_p3_initial_guesses.set_val('altitude', [600., 394.], 'ft') +landing_approach_to_mic_p3_initial_guesses.set_val('altitude', [600.0, 394.0], 'ft') landing_approach_to_mic_p3_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg' +) -landing_approach_to_mic_p3_initial_guesses.set_val('angle_of_attack', 5.25, 'deg') +landing_approach_to_mic_p3_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.25, 'deg') landing_approach_to_mic_p3_builder = LandingApproachToMicP3( 'landing_approach_to_mic_p3', core_subsystems=default_mission_subsystems, subsystem_options=landing_subsystem_options, user_options=landing_approach_to_mic_p3_user_options, - initial_guesses=landing_approach_to_mic_p3_initial_guesses) + initial_guesses=landing_approach_to_mic_p3_initial_guesses, +) landing_trajectory_builder.set_approach_to_mic_p3(landing_approach_to_mic_p3_builder) ibeg = 0 iend = 26 -detailed_landing_approach_to_mic_p3 = _split_aviary_values( - detailed_landing, slice(ibeg, iend)) +detailed_landing_approach_to_mic_p3 = _split_aviary_values(detailed_landing, slice(ibeg, iend)) # endregion - landing approach to mic P3 # region - landing mic P3-to-obstacle landing_mic_p3_to_obstacle_user_options = AviaryValues() -landing_mic_p3_to_obstacle_user_options.set_val('max_duration', val=50., units='s') -landing_mic_p3_to_obstacle_user_options.set_val('duration_ref', val=50., units='s') -landing_mic_p3_to_obstacle_user_options.set_val('initial_ref', val=50.0, units='s') -landing_mic_p3_to_obstacle_user_options.set_val('distance_max', val=6000., units='ft') -landing_mic_p3_to_obstacle_user_options.set_val('max_velocity', val=140., units='kn') -landing_mic_p3_to_obstacle_user_options.set_val('altitude_ref', val=400., units='ft') +landing_mic_p3_to_obstacle_user_options.set_val('max_duration', val=50.0, units='s') +landing_mic_p3_to_obstacle_user_options.set_val('time_duration_ref', val=50.0, units='s') +landing_mic_p3_to_obstacle_user_options.set_val('time_initial_ref', val=50.0, units='s') +landing_mic_p3_to_obstacle_user_options.set_val('distance_max', val=6000.0, units='ft') +landing_mic_p3_to_obstacle_user_options.set_val('max_velocity', val=140.0, units='kn') +landing_mic_p3_to_obstacle_user_options.set_val('altitude_ref', val=400.0, units='ft') -landing_mic_p3_to_obstacle_user_options.set_val( - 'lower_angle_of_attack', val=0., units='deg') +landing_mic_p3_to_obstacle_user_options.set_val('lower_angle_of_attack', val=0.0, units='deg') -landing_mic_p3_to_obstacle_user_options.set_val( - 'upper_angle_of_attack', val=12., units='deg') +landing_mic_p3_to_obstacle_user_options.set_val('upper_angle_of_attack', val=12.0, units='deg') -landing_mic_p3_to_obstacle_user_options.set_val( - 'angle_of_attack_ref', val=12., units='deg') +landing_mic_p3_to_obstacle_user_options.set_val('angle_of_attack_ref', val=12.0, units='deg') -landing_mic_p3_to_obstacle_user_options.set_val('initial_height', val=394., units='ft') +landing_mic_p3_to_obstacle_user_options.set_val('initial_height', val=394.0, units='ft') landing_mic_p3_to_obstacle_initial_guesses = AviaryValues() -landing_mic_p3_to_obstacle_initial_guesses.set_val('time', [-27., 27.], 's') -landing_mic_p3_to_obstacle_initial_guesses.set_val('distance', [-2000., 0.], 'ft') -landing_mic_p3_to_obstacle_initial_guesses.set_val('velocity', 140., 'kn') +landing_mic_p3_to_obstacle_initial_guesses.set_val('time', [-27.0, 27.0], 's') +landing_mic_p3_to_obstacle_initial_guesses.set_val('distance', [-2000.0, 0.0], 'ft') +landing_mic_p3_to_obstacle_initial_guesses.set_val('velocity', 140.0, 'kn') landing_mic_p3_to_obstacle_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_mic_p3_to_obstacle_initial_guesses.set_val('throttle', throttle) -landing_mic_p3_to_obstacle_initial_guesses.set_val('altitude', [394., 50.], 'ft') +landing_mic_p3_to_obstacle_initial_guesses.set_val('altitude', [394.0, 50.0], 'ft') landing_mic_p3_to_obstacle_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg' +) -landing_mic_p3_to_obstacle_initial_guesses.set_val('angle_of_attack', 5.25, 'deg') +landing_mic_p3_to_obstacle_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.25, 'deg') landing_mic_p3_to_obstacle_builder = LandingMicP3ToObstacle( 'landing_mic_p3_to_obstacle', core_subsystems=default_mission_subsystems, subsystem_options=landing_subsystem_options, user_options=landing_mic_p3_to_obstacle_user_options, - initial_guesses=landing_mic_p3_to_obstacle_initial_guesses) + initial_guesses=landing_mic_p3_to_obstacle_initial_guesses, +) landing_trajectory_builder.set_mic_p3_to_obstacle(landing_mic_p3_to_obstacle_builder) ibeg = 0 iend = 26 -detailed_landing_mic_p3_to_obstacle = _split_aviary_values( - detailed_landing, slice(ibeg, iend)) +detailed_landing_mic_p3_to_obstacle = _split_aviary_values(detailed_landing, slice(ibeg, iend)) # endregion - mic P3 -to-obstacle # region - landing obstacle-to-flare landing_obstacle_user_options = AviaryValues() -landing_obstacle_user_options.set_val('max_duration', val=5., units='s') -landing_obstacle_user_options.set_val('distance_max', val=800., units='ft') -landing_obstacle_user_options.set_val('max_velocity', val=140., units='kn') -landing_obstacle_user_options.set_val('altitude_ref', val=50., units='ft') +landing_obstacle_user_options.set_val('max_duration', val=5.0, units='s') +landing_obstacle_user_options.set_val('distance_max', val=800.0, units='ft') +landing_obstacle_user_options.set_val('max_velocity', val=140.0, units='kn') +landing_obstacle_user_options.set_val('altitude_ref', val=50.0, units='ft') landing_obstacle_initial_guesses = AviaryValues() -landing_obstacle_initial_guesses.set_val('time', [0., 4.], 's') -landing_obstacle_initial_guesses.set_val('distance', [0., 800.], 'ft') -landing_obstacle_initial_guesses.set_val('velocity', 140., 'kn') +landing_obstacle_initial_guesses.set_val('time', [0.0, 4.0], 's') +landing_obstacle_initial_guesses.set_val('distance', [0.0, 800.0], 'ft') +landing_obstacle_initial_guesses.set_val('velocity', 140.0, 'kn') landing_obstacle_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') landing_obstacle_initial_guesses.set_val('throttle', throttle) -landing_obstacle_initial_guesses.set_val('altitude', [50., 15.], 'ft') +landing_obstacle_initial_guesses.set_val('altitude', [50.0, 15.0], 'ft') landing_obstacle_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg') + Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, apr_angle], 'deg' +) -landing_obstacle_initial_guesses.set_val('angle_of_attack', 5.2, 'deg') +landing_obstacle_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 5.2, 'deg') landing_obstacle_builder = LandingObstacleToFlare( 'landing_obstacle', core_subsystems=default_mission_subsystems, subsystem_options=landing_subsystem_options, user_options=landing_obstacle_user_options, - initial_guesses=landing_obstacle_initial_guesses) + initial_guesses=landing_obstacle_initial_guesses, +) landing_trajectory_builder.set_obstacle_to_flare(landing_obstacle_builder) @@ -1460,35 +1477,35 @@ def _split_aviary_values(aviary_values, slicing): # region - landing flare-to-touchdown landing_flare_user_options = AviaryValues() -landing_flare_user_options.set_val('max_duration', val=7., units='s') -landing_flare_user_options.set_val('duration_ref', val=7., units='s') -landing_flare_user_options.set_val('initial_ref', val=4., units='s') -landing_flare_user_options.set_val('distance_max', val=1000., units='ft') -landing_flare_user_options.set_val('max_velocity', val=140., units='kn') -landing_flare_user_options.set_val('altitude_ref', val=15., units='ft') +landing_flare_user_options.set_val('max_duration', val=7.0, units='s') +landing_flare_user_options.set_val('time_duration_ref', val=7.0, units='s') +landing_flare_user_options.set_val('time_initial_ref', val=4.0, units='s') +landing_flare_user_options.set_val('distance_max', val=1000.0, units='ft') +landing_flare_user_options.set_val('max_velocity', val=140.0, units='kn') +landing_flare_user_options.set_val('altitude_ref', val=15.0, units='ft') landing_flare_user_options.set_val('lower_angle_of_attack', val=5.2, units='deg') -landing_flare_user_options.set_val('upper_angle_of_attack', val=12., units='deg') -landing_flare_user_options.set_val('angle_of_attack_ref', val=12., units='deg') +landing_flare_user_options.set_val('upper_angle_of_attack', val=12.0, units='deg') +landing_flare_user_options.set_val('angle_of_attack_ref', val=12.0, units='deg') landing_flare_initial_guesses = AviaryValues() -landing_flare_initial_guesses.set_val('time', [4., 6.], 's') -landing_flare_initial_guesses.set_val('distance', [800., 1000.], 'ft') -landing_flare_initial_guesses.set_val('velocity', 140., 'kn') +landing_flare_initial_guesses.set_val('time', [4.0, 6.0], 's') +landing_flare_initial_guesses.set_val('distance', [800.0, 1000.0], 'ft') +landing_flare_initial_guesses.set_val('velocity', 140.0, 'kn') landing_flare_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') -landing_flare_initial_guesses.set_val('throttle', [throttle, throttle*4/7]) -landing_flare_initial_guesses.set_val('altitude', [15., 0.], 'ft') -landing_flare_initial_guesses.set_val( - Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, 0.], 'deg') -landing_flare_initial_guesses.set_val('angle_of_attack', [5.2, 7.5], 'deg') +landing_flare_initial_guesses.set_val('throttle', [throttle, throttle * 4 / 7]) +landing_flare_initial_guesses.set_val('altitude', [15.0, 0.0], 'ft') +landing_flare_initial_guesses.set_val(Dynamic.Mission.FLIGHT_PATH_ANGLE, [apr_angle, 0.0], 'deg') +landing_flare_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [5.2, 7.5], 'deg') landing_flare_builder = LandingFlareToTouchdown( 'landing_flare', core_subsystems=default_mission_subsystems, subsystem_options=landing_subsystem_options, user_options=landing_flare_user_options, - initial_guesses=landing_flare_initial_guesses) + initial_guesses=landing_flare_initial_guesses, +) landing_trajectory_builder.set_flare_to_touchdown(landing_flare_builder) @@ -1500,28 +1517,29 @@ def _split_aviary_values(aviary_values, slicing): # region touchdown-to-nose-down landing_touchdown_user_options = AviaryValues() -landing_touchdown_user_options.set_val('max_duration', val=10., units='s') -landing_touchdown_user_options.set_val('duration_ref', val=10., units='s') -landing_touchdown_user_options.set_val('initial_ref', val=6., units='s') -landing_touchdown_user_options.set_val('distance_max', val=3000., units='ft') -landing_touchdown_user_options.set_val('max_velocity', val=140., units='kn') -landing_touchdown_user_options.set_val('max_angle_of_attack', val=8., units='deg') +landing_touchdown_user_options.set_val('max_duration', val=10.0, units='s') +landing_touchdown_user_options.set_val('time_duration_ref', val=10.0, units='s') +landing_touchdown_user_options.set_val('time_initial_ref', val=6.0, units='s') +landing_touchdown_user_options.set_val('distance_max', val=3000.0, units='ft') +landing_touchdown_user_options.set_val('max_velocity', val=140.0, units='kn') +landing_touchdown_user_options.set_val('max_angle_of_attack', val=8.0, units='deg') landing_touchdown_initial_guesses = AviaryValues() -landing_touchdown_initial_guesses.set_val('time', [6., 9.], 's') -landing_touchdown_initial_guesses.set_val('distance', [1000., 1400.], 'ft') -landing_touchdown_initial_guesses.set_val('velocity', [140., 135.], 'kn') +landing_touchdown_initial_guesses.set_val('time', [6.0, 9.0], 's') +landing_touchdown_initial_guesses.set_val('distance', [1000.0, 1400.0], 'ft') +landing_touchdown_initial_guesses.set_val('velocity', [140.0, 135.0], 'kn') landing_touchdown_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') -landing_touchdown_initial_guesses.set_val('throttle', 0.) -landing_touchdown_initial_guesses.set_val('angle_of_attack', [7.5, 0.0], 'deg') +landing_touchdown_initial_guesses.set_val('throttle', 0.0) +landing_touchdown_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [7.5, 0.0], 'deg') landing_touchdown_builder = LandingTouchdownToNoseDown( 'landing_touchdown', core_subsystems=default_mission_subsystems, subsystem_options=landing_subsystem_options, user_options=landing_touchdown_user_options, - initial_guesses=landing_touchdown_initial_guesses) + initial_guesses=landing_touchdown_initial_guesses, +) landing_trajectory_builder.set_touchdown_to_nose_down(landing_touchdown_builder) @@ -1533,27 +1551,28 @@ def _split_aviary_values(aviary_values, slicing): # region nose-down-to-fullstop landing_fullstop_user_options = AviaryValues() -landing_fullstop_user_options.set_val('max_duration', val=30., units='s') -landing_fullstop_user_options.set_val('duration_ref', val=30., units='s') -landing_fullstop_user_options.set_val('initial_ref', val=14., units='s') -landing_fullstop_user_options.set_val('distance_max', val=4400., units='ft') -landing_fullstop_user_options.set_val('max_velocity', val=140., units='kn') +landing_fullstop_user_options.set_val('max_duration', val=30.0, units='s') +landing_fullstop_user_options.set_val('time_duration_ref', val=30.0, units='s') +landing_fullstop_user_options.set_val('time_initial_ref', val=14.0, units='s') +landing_fullstop_user_options.set_val('distance_max', val=4400.0, units='ft') +landing_fullstop_user_options.set_val('max_velocity', val=140.0, units='kn') landing_fullstop_initial_guesses = AviaryValues() -landing_fullstop_initial_guesses.set_val('time', [9., 29.], 's') -landing_fullstop_initial_guesses.set_val('distance', [1400., 3500.], 'ft') -landing_fullstop_initial_guesses.set_val('velocity', [135., 0.01], 'kn') +landing_fullstop_initial_guesses.set_val('time', [9.0, 29.0], 's') +landing_fullstop_initial_guesses.set_val('distance', [1400.0, 3500.0], 'ft') +landing_fullstop_initial_guesses.set_val('velocity', [135.0, 0.01], 'kn') landing_fullstop_initial_guesses.set_val('mass', detailed_landing_mass, 'lbm') -landing_fullstop_initial_guesses.set_val('throttle', 0.) -landing_fullstop_initial_guesses.set_val('angle_of_attack', 0., 'deg') +landing_fullstop_initial_guesses.set_val('throttle', 0.0) +landing_fullstop_initial_guesses.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0.0, 'deg') landing_fullstop_builder = LandingNoseDownToStop( 'landing_fullstop', core_subsystems=default_mission_subsystems, subsystem_options=landing_subsystem_options_spoilers, user_options=landing_fullstop_user_options, - initial_guesses=landing_fullstop_initial_guesses) + initial_guesses=landing_fullstop_initial_guesses, +) landing_trajectory_builder.set_nose_down_to_stop(landing_fullstop_builder) diff --git a/aviary/models/aircraft/advanced_single_aisle/phase_info.py b/aviary/models/aircraft/advanced_single_aisle/phase_info.py new file mode 100644 index 0000000000..4a9bca270a --- /dev/null +++ b/aviary/models/aircraft/advanced_single_aisle/phase_info.py @@ -0,0 +1,127 @@ +from aviary.variable_info.variables import Mission + +# defaults for height energy based phases + +phase_info = { + 'pre_mission': {'include_takeoff': True, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 6, + 'order': 3, + 'mach_optimize': True, + 'mach_ref': (1.0, 'unitless'), + 'mach_bounds': ((0.2, 0.79), 'unitless'), + 'altitude_optimize': True, + 'altitude_bounds': ((0.0, 37000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((12.1, 45.0), 'min'), + 'no_descent': True, + }, + 'initial_guesses': { + 'time': ([0, 45.0], 'min'), + 'altitude': ([35, 35000.0], 'ft'), + 'mach': ([0.2, 0.79], 'unitless'), + }, + }, + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.79, 'unitless'), + 'mach_bounds': ((0.78, 0.80), 'unitless'), + 'altitude_optimize': False, + 'altitude_initial': (35000.0, 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((12.1, 45.0), 'min'), + 'time_duration_bounds': ((203.1, 812.4), 'min'), + }, + 'initial_guesses': { + 'altitude': ([35000.0, 35000.0], 'ft'), + 'mach': ([0.79, 0.79], 'unitless'), + }, + }, + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': True, + 'mach_ref': (1.0, 'unitless'), + 'mach_initial': (0.79, 'unitless'), + 'mach_final': (0.3, 'unitless'), + 'mach_bounds': ((0.3, 0.79), 'unitless'), + 'altitude_optimize': True, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_final': (35.0, 'ft'), + 'altitude_bounds': ((0.0, 38000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((215.1, 872.4), 'min'), + 'time_duration_bounds': ((14.6, 45.0), 'min'), + 'no_climb': True, + }, + 'initial_guesses': { + 'altitude': ([35000.0, 35.0], 'ft'), + 'mach': ([0.79, 0.3], 'unitless'), + }, + }, + 'post_mission': { + 'include_landing': True, + 'constrain_range': True, + 'target_range': (3380.0, 'nmi'), + }, +} + + +def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs): + """ + Modify the values in the phase_info dictionary to accommodate different values + for the following mission design inputs: cruise altitude, cruise Mach number, + cruise range, design gross mass. + + Parameters + ---------- + phase_info : dict + Dictionary of phase settings for a mission profile + post_mission_info : dict + Dictionary of phase settings for a post mission profile + aviary_inputs : + Object containing values and units for all aviary inputs and options + + Returns + ------- + dict + Modified phase_info and post_mission_info that have been changed to match + the new mission parameters + """ + + alt_cruise = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') + mach_cruise = aviary_inputs.get_val(Mission.Summary.CRUISE_MACH) + + # Range + old_range_cruise, range_units = post_mission_info['target_range'] + range_cruise = aviary_inputs.get_val(Mission.Design.RANGE, units=range_units) + if range_cruise != old_range_cruise: + new_val = post_mission_info['target_range'][0] * range_cruise / old_range_cruise + post_mission_info['target_range'] = (new_val, range_units) + + # Altitude + old_alt_cruise = 35000.0 + if alt_cruise != old_alt_cruise: + phase_info['climb']['user_options']['altitude_final'] = (alt_cruise, 'ft') + phase_info['cruise']['user_options']['altitude_initial'] = (alt_cruise, 'ft') + phase_info['cruise']['user_options']['altitude_final'] = (alt_cruise, 'ft') + phase_info['descent']['user_options']['altitude_initial'] = (alt_cruise, 'ft') + + # Mach + old_mach_cruise = 0.79 + if mach_cruise != old_mach_cruise: + phase_info['climb']['user_options']['mach_final'] = (mach_cruise, 'unitless') + phase_info['cruise']['user_options']['mach_initial'] = (mach_cruise, 'unitless') + phase_info['cruise']['user_options']['mach_final'] = (mach_cruise, 'unitless') + phase_info['descent']['user_options']['mach_initial'] = (mach_cruise, 'unitless') + + return phase_info, post_mission_info diff --git a/aviary/models/aircraft/blended_wing_body/generic_BWB_2dof_phase_info.py b/aviary/models/aircraft/blended_wing_body/generic_BWB_2dof_phase_info.py new file mode 100644 index 0000000000..d9427eebbd --- /dev/null +++ b/aviary/models/aircraft/blended_wing_body/generic_BWB_2dof_phase_info.py @@ -0,0 +1,254 @@ +from aviary.variable_info.enums import SpeedType + + +# 2DOF +phase_info = { + 'groundroll': { + 'subsystem_options': {'core_aerodynamics': {'method': 'low_speed'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'time_initial': (0.0, 's'), + 'time_duration_ref': (50.0, 's'), + 'time_duration_bounds': ((1.0, 50.0), 's'), + 'velocity_initial': (0.066, 'kn'), + 'velocity_bounds': ((0, 150), 'kn'), + 'velocity_ref': (100, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_initial': (0.0, 'ft'), + 'distance_bounds': ((0, 7000), 'ft'), + 'distance_ref': (3500, 'ft'), + 'distance_defect_ref': (3000, 'ft'), + }, + 'initial_guesses': { + 'time': ([0.0, 31.0], 's'), + 'velocity': ([0.066, 120.9], 'kn'), + 'distance': ([0.0, 3500.0], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'rotation': { + 'subsystem_options': {'core_aerodynamics': {'method': 'low_speed'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'time_duration_bounds': ((1, 50), 's'), + 'time_duration_ref': (50.0, 's'), + 'velocity_bounds': ((0, 150), 'kn'), + 'velocity_ref': (50, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 5000), 'ft'), + 'distance_ref': (5000, 'ft'), + 'distance_defect_ref': (5000, 'ft'), + 'angle_of_attack_initial': (0.0, 'deg'), + 'angle_of_attack_bounds': ((0.0, 12.0), 'deg'), + 'angle_of_attack_ref': (12.0, 'deg'), + 'normal_ref': (10000, 'lbf'), + }, + 'initial_guesses': { + 'time': ([32.0, 34.0], 's'), + 'angle_of_attack': ([0.0, 10.0], 'deg'), + 'velocity': ([127, 134.0], 'kn'), + 'distance': ([3618.9, 4060.4], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'ascent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'low_speed'}}, + 'user_options': { + 'num_segments': 4, + 'order': 3, + 'velocity_bounds': ((0, 300), 'kn'), + 'velocity_ref': (200, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((50, 10_000), 'ft'), + 'distance_ref': (1e4, 'ft'), + 'distance_defect_ref': (1e4, 'ft'), + 'altitude_bounds': ((0.0, 500.0), 'ft'), + 'altitude_ref': (500, 'ft'), + 'altitude_defect_ref': (500, 'ft'), + 'altitude_initial': (0, 'ft'), + 'altitude_final': (500, 'ft'), + 'altitude_constraint_ref': (500, 'ft'), + 'flight_path_angle_bounds': ((0.0, 13.0), 'deg'), + 'flight_path_angle_ref': (10.0, 'deg'), + 'flight_path_angle_defect_ref': (10.0, 'deg'), + 'flight_path_angle_initial': (0.0, 'deg'), + 'pitch_constraint_bounds': ((0.0, 15.0), 'deg'), + 'pitch_constraint_ref': (15.0, 'deg'), + }, + 'initial_guesses': { + 'time': ([45.0, 25.0], 's'), + 'flight_path_angle': ([0.0, 8.0], 'deg'), + 'angle_of_attack': ([2.5, 1.5], 'deg'), + 'velocity': ([150.0, 185.0], 'kn'), + 'distance': ([4.0e3, 10.0e3], 'ft'), + 'altitude': ([0.0, 500.0], 'ft'), + 'tau_gear': (0.2, 'unitless'), + 'tau_flaps': (0.9, 'unitless'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'accel': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'alt': (500, 'ft'), + 'EAS_constraint_eq': (250, 'kn'), + 'time_duration_bounds': ((5, 200), 's'), + 'time_duration_ref': (200, 's'), + 'velocity_bounds': ((150, 270), 'kn'), + 'velocity_ref': (270, 'kn'), + 'velocity_ref0': (150, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'distance_bounds': ((1, 150.0), 'NM'), + 'distance_ref': (5, 'NM'), + 'distance_defect_ref': (5, 'NM'), + }, + 'initial_guesses': { + 'time': ([70.0, 13.0], 's'), + 'velocity': ([185.0, 250.0], 'kn'), + 'distance': ([10.0e3, 20.0e3], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'climb1': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 2, + 'order': 3, + 'EAS_target': (250, 'kn'), + 'mach_cruise': 0.8, + 'target_mach': False, + 'time_duration_bounds': ((100, 1000), 's'), + 'time_duration_ref': (200, 's'), + 'altitude_initial': (500.0, 'ft'), + 'altitude_final': (10.0e3, 'ft'), + 'altitude_bounds': ((500.0, 10_000.0), 'ft'), + 'altitude_ref': (10.0e3, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 100.0), 'NM'), + 'distance_ref': (20, 'NM'), + }, + 'initial_guesses': { + 'time': ([11.0, 15.0], 'min'), + 'distance': ([18.0e3, 105.0e3], 'ft'), + 'altitude': ([500.0, 10.0e3], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'climb2': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 3, + 'order': 3, + 'EAS_target': (270, 'kn'), + 'mach_cruise': 0.8, + 'target_mach': True, + 'required_available_climb_rate': (0.1, 'ft/min'), + 'time_duration_bounds': ((200, 12_000), 's'), + 'time_duration_ref': (4000, 's'), + 'altitude_final': (41_000, 'ft'), + 'altitude_bounds': ((9000.0, 42_000.0), 'ft'), + 'altitude_ref': (41_000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((10.0, 1000.0), 'NM'), + 'distance_ref': (500, 'NM'), + }, + 'initial_guesses': { + 'time': ([216.0, 1300.0], 's'), + 'distance': ([100.0e3, 200.0e3], 'ft'), + 'altitude': ([10_000, 20_000], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'alt_cruise': (41_000, 'ft'), + 'mach_cruise': 0.8, + }, + 'initial_guesses': { + # [Initial mass, delta mass] for special cruise phase. + 'mass': ([140_000.0, -35_000], 'lbm'), + 'initial_distance': (100.0e3, 'ft'), + 'initial_time': (1_000.0, 's'), + 'altitude': (41_000, 'ft'), + 'mach': (0.8, 'unitless'), + }, + }, + 'desc1': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'EAS_limit': (160, 'kn'), + 'mach_cruise': 0.8, + 'input_speed_type': SpeedType.MACH, + 'time_duration_bounds': ((300.0, 2200.0), 's'), + 'time_duration_ref': (2000, 's'), + 'altitude_final': (10_000, 'ft'), + 'altitude_bounds': ((9000.0, 41_000.0), 'ft'), + 'altitude_ref': (41_000, 'ft'), + 'altitude_constraint_ref': (10000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (140_000, 'lbm'), + 'mass_defect_ref': (140_000, 'lbm'), + 'distance_bounds': ((1_000.0, 3_500.0), 'NM'), + 'distance_ref': (3_000, 'NM'), + 'distance_defect_ref': (100, 'NM'), + }, + 'initial_guesses': { + 'mass': (136000.0, 'lbm'), + 'altitude': ([41_000, 10_000], 'ft'), + 'throttle': ([0.0, 0.0], 'unitless'), + 'distance': ([0.92 * 3500, 0.96 * 3500], 'NM'), + 'time': ([28000.0, 500.0], 's'), + }, + }, + 'desc2': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 1, + 'order': 7, + 'EAS_limit': (250, 'kn'), + 'mach_cruise': 0.80, + 'input_speed_type': SpeedType.EAS, + 'time_duration_bounds': ((100.0, 5000), 's'), + 'time_duration_ref': (500, 's'), + 'altitude_final': (1000, 'ft'), + 'altitude_bounds': ((500.0, 11_000.0), 'ft'), + 'altitude_ref': (10.0e3, 'ft'), + 'altitude_ref0': (1000, 'ft'), + 'altitude_constraint_ref': (1000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((3000.0, 5000.0), 'NM'), + 'distance_ref': (3500, 'NM'), + 'distance_defect_ref': (100, 'NM'), + }, + 'initial_guesses': { + 'mass': (136000.0, 'lbm'), + 'altitude': ([10.0e3, 1.0e3], 'ft'), + 'throttle': ([0.0, 0.0], 'unitless'), + 'distance': ([0.96 * 3500, 3500], 'NM'), + 'time': ([28500.0, 500.0], 's'), + }, + }, + 'post_mission': { + #'constrain_range': True, + #'target_range': (3000.0, 'nmi'), + }, +} diff --git a/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.csv b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.csv new file mode 100644 index 0000000000..c627f18570 --- /dev/null +++ b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.csv @@ -0,0 +1,259 @@ +# created 04/01/25 +# GASP-derived aircraft input deck converted from Generic_HWB_Trade_Study.dat + +# Input Values +aircraft:air_conditioning:mass_coefficient,1.155,unitless +aircraft:anti_icing:mass,236,lbm +aircraft:apu:mass,710,lbm +aircraft:avionics:mass,3225,lbm +aircraft:blended_wing_body_design:passenger_leading_edge_sweep,65,deg +aircraft:controls:cockpit_control_mass_scaler,1,unitless +aircraft:controls:control_mass_increment,0,lbm +aircraft:controls:stability_augmentation_system_mass,0,lbm +aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless +aircraft:crew_and_payload:cargo_mass,0.0,lbm +aircraft:crew_and_payload:catering_items_mass_per_passenger,5,lbm +aircraft:crew_and_payload:design:cargo_mass,0.0,lbm +aircraft:crew_and_payload:design:max_cargo_mass,15000,lbm +aircraft:crew_and_payload:design:num_first_class,11,unitless +aircraft:crew_and_payload:design:num_passengers,150,unitless +aircraft:crew_and_payload:design:num_tourist_class,139,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,18,unitless +aircraft:crew_and_payload:design:seat_pitch_first,36,inch +aircraft:crew_and_payload:design:seat_pitch_tourist,32,inch +aircraft:crew_and_payload:passenger_mass_with_bags,225,lbm +aircraft:crew_and_payload:passenger_service_mass_per_passenger,6,lbm +aircraft:crew_and_payload:uld_mass_per_passenger,0.0667,lbm +aircraft:crew_and_payload:water_mass_per_occupant,3,lbm +aircraft:design:cg_delta,0.25,unitless +aircraft:design:cockpit_control_mass_coefficient,16.5,unitless +aircraft:design:drag_coeff_increment,0.00025,unitless +aircraft:design:emergency_equipment_mass,100,lbm +aircraft:design:max_structural_speed,402.5,mi/h +aircraft:design:part25_structural_category,3,unitless +aircraft:design:reserve_fuel_additional,0.2222,lbm +aircraft:design:static_margin,0.05,unitless +aircraft:design:structural_mass_increment,0,lbm +aircraft:design:drag_divergence_shift,0.025,unitless +aircraft:design:type,BWB,unitless +aircraft:electrical:system_mass_per_passenger,11.45,lbm +aircraft:engine:additional_mass_fraction,0.04373,unitless +aircraft:engine:data_file,models/engines/turbofan_gasp_bwb.csv,unitless +aircraft:engine:global_throttle,True,unitless +aircraft:engine:mass_scaler,1,unitless +aircraft:engine:mass_specific,0.178884,lbm/lbf +aircraft:engine:num_engines,2,unitless +aircraft:engine:num_fuselage_engines,2,unitless +aircraft:engine:pod_mass_scaler,1,unitless +aircraft:engine:pylon_factor,1.25,unitless +aircraft:engine:reference_sls_thrust,19580.2,lbf +aircraft:engine:scaled_sls_thrust,19580.2,lbf +aircraft:engine:type,7,unitless +aircraft:engine:wing_locations,0.0,unitless +aircraft:fuel:density,6.687,lbm/galUS +aircraft:fuel:fuel_margin,10,unitless +aircraft:fuel:fuel_system_mass_coefficient,0.035,unitless +aircraft:fuel:fuel_system_mass_scaler,1,unitless +aircraft:fuel:unusable_fuel_mass_coefficient,12,unitless +aircraft:fuel:wing_fuel_fraction,0.45,unitless +aircraft:furnishings:mass_scaler,40,unitless +aircraft:fuselage:aftbody_mass_per_unit_area,5,lbm/ft**2 +aircraft:fuselage:aisle_width,22,inch +aircraft:fuselage:delta_diameter,5,ft +aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 +aircraft:fuselage:height_to_width_ratio,0.2597,unitless +aircraft:fuselage:lift_coefficient_ratio_body_to_wing,0.35,unitless +aircraft:fuselage:lift_curve_slope_mach0,1.8265,1/rad +aircraft:fuselage:mass_coefficient,0.889,unitless +aircraft:fuselage:nose_fineness,0.6,unitless +aircraft:fuselage:num_aisles,3,unitless +aircraft:fuselage:pilot_compartment_length,7.5,ft +aircraft:fuselage:pressure_differential,10,psi +aircraft:fuselage:pressurized_width_additional,0,ft +aircraft:fuselage:seat_width,21,inch +aircraft:fuselage:tail_fineness,1.75,unitless +aircraft:fuselage:wetted_area_ratio_aftbody_to_total,0.2,unitless +aircraft:fuselage:wetted_area_scaler,1.0001,unitless +aircraft:horizontal_tail:aspect_ratio,1.705,unitless +aircraft:horizontal_tail:mass_coefficient,0.124,unitless +aircraft:horizontal_tail:moment_ratio,0.5463,unitless +aircraft:horizontal_tail:sweep,45,deg +aircraft:horizontal_tail:taper_ratio,0.366,unitless +aircraft:horizontal_tail:thickness_to_chord,0.1,unitless +aircraft:horizontal_tail:vertical_tail_fraction,0,unitless +aircraft:horizontal_tail:volume_coefficient,1e-06,unitless +aircraft:hydraulics:flight_control_mass_coefficient,0.107,unitless +aircraft:hydraulics:gear_mass_coefficient,0.135,unitless +aircraft:instruments:mass_coefficient,0.116,unitless +aircraft:landing_gear:fixed_gear,False,unitless +aircraft:landing_gear:main_gear_location,0,unitless +aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless +aircraft:landing_gear:mass_coefficient,0.052,unitless +aircraft:landing_gear:tail_hook_mass_scaler,1,unitless +aircraft:landing_gear:total_mass_scaler,1,unitless +aircraft:nacelle:clearance_ratio,0.2,unitless +aircraft:nacelle:core_diameter_ratio,1.2205,unitless +aircraft:nacelle:fineness,1.3588,unitless +aircraft:nacelle:form_factor,1.2,unitless +aircraft:nacelle:mass_specific,2.5,lbm/ft**2 +aircraft:nacelle:percent_diam_buried_in_fuselage,0,unitless +aircraft:strut:area_ratio,0,unitless +aircraft:strut:attachment_location,0,ft +aircraft:strut:attachment_location_dimensionless,0,unitless +aircraft:strut:dimensional_location_specified,False,unitless +aircraft:strut:fuselage_interference_factor,0,unitless +aircraft:strut:mass_coefficient,0,unitless +aircraft:strut:thickness_to_chord,0,unitless +aircraft:vertical_tail:aspect_ratio,1.705,unitless +aircraft:vertical_tail:mass_coefficient,0.119,unitless +aircraft:vertical_tail:moment_ratio,5.2615,unitless +aircraft:vertical_tail:sweep,35,deg +aircraft:vertical_tail:taper_ratio,0.366,unitless +aircraft:vertical_tail:thickness_to_chord,0.1,unitless +aircraft:vertical_tail:volume_coefficient,0.015,unitless +aircraft:wing:aspect_ratio,10,unitless +aircraft:wing:center_distance,0.463,unitless +aircraft:wing:choose_fold_location,True,unitless +aircraft:wing:flap_chord_ratio,0.2,unitless +aircraft:wing:flap_deflection_landing,25,deg +aircraft:wing:flap_deflection_takeoff,15,deg +aircraft:wing:flap_drag_increment_optimum,0.1,unitless +aircraft:wing:flap_lift_increment_optimum,1.5,unitless +aircraft:wing:flap_span_ratio,0.61,unitless +aircraft:wing:flap_type,double_slotted,unitless +aircraft:wing:fold_dimensional_location_specified,True,unitless +aircraft:wing:fold_mass_coefficient,0.15,unitless +aircraft:wing:folded_span,118,ft +aircraft:wing:fuselage_interference_factor,1.0,unitless +aircraft:wing:has_fold,True,unitless +aircraft:wing:has_strut,False,unitless +aircraft:wing:height,12.5,ft +aircraft:wing:high_lift_mass_coefficient,1,unitless +aircraft:wing:incidence,1.5,deg +aircraft:design:wing_loading,70,lbf/ft**2 +aircraft:wing:mass_coefficient,75.78,unitless +aircraft:wing:max_lift_ref,1.45,unitless +aircraft:wing:max_slat_deflection_landing,0,deg +aircraft:wing:max_slat_deflection_takeoff,0,deg +aircraft:wing:max_thickness_location,0.325,unitless +aircraft:wing:min_pressure_location,0.275,unitless +aircraft:wing:num_flap_segments,2,unitless +aircraft:wing:optimum_flap_deflection,55,deg +aircraft:wing:optimum_slat_deflection,20,deg +aircraft:wing:slat_chord_ratio,0.0001,unitless +aircraft:wing:slat_lift_increment_optimum,0.93,unitless +aircraft:wing:surface_control_mass_coefficient,0.5,unitless +aircraft:wing:sweep,30,deg +aircraft:wing:taper_ratio,0.27444,unitless +aircraft:wing:thickness_to_chord_root,0.165,unitless +aircraft:wing:thickness_to_chord_tip,0.1,unitless +aircraft:wing:vertical_mount_location,0.5,unitless +aircraft:wing:zero_lift_angle,0,deg +mission:design:cruise_altitude,41000,ft +mission:design:gross_mass,150000,lbm +mission:design:mach,0.8,unitless +mission:design:range,3500,NM +mission:design:rate_of_climb_at_top_of_climb,300,ft/min +mission:landing:airport_altitude,0,ft +mission:landing:braking_delay,1,s +mission:landing:glide_to_stall_ratio,1.3,unitless +mission:landing:maximum_flare_load_factor,1.15,unitless +mission:landing:maximum_sink_rate,900,ft/min +mission:landing:obstacle_height,50,ft +mission:landing:touchdown_sink_rate,5,ft/s +mission:summary:fuel_flow_scaler,1,unitless +mission:takeoff:decision_speed_increment,10,kn +mission:takeoff:rotation_speed_increment,5,kn +mission:taxi:duration,0.1677,h +settings:aerodynamics_method,GASP +settings:equations_of_motion,2DOF +settings:mass_method,GASP + +# Initialization Guesses +actual_takeoff_mass,0 +climb_range,0 +cruise_mass_final,0 +flight_duration,0 +fuel_burn_per_passenger_mile,0 +reserves,0 +rotation_mass,0 +time_to_climb,0 + +# Unconverted Values +.GenericHybrid-WingBodyConfiguration/SacledNASAGRCGTF/FPR,1.45-1 +INGASP.ALR,1.11 +INGASP.BENGOB,0 +INGASP.CINP,0.11 +INGASP.CLIAB,1984 +INGASP.CMF,15 +INGASP.CMV,0.15 +INGASP.CRWOH,15 +INGASP.CW,,0,0,0,0,0,0,0,0,0,0,0,0,0.0667,11.45,0 +INGASP.DCDSE,0.001 +INGASP.DYR,12 +INGASP.EL_FLGC,8 +INGASP.EMCRU,0.8 +INGASP.FCFFC,0.885 +INGASP.FCFFT,0.93 +INGASP.FCFHTC,0.75 +INGASP.FCFHTT,0.926 +INGASP.FCFNC,1.15 +INGASP.FCFNT,0.95 +INGASP.FCFVTC,0.9 +INGASP.FCFVTT,0.926 +INGASP.FCFWC,0.906 +INGASP.FCFWT,0.926 +INGASP.FCKIC,1 +INGASP.FCKIT,1 +INGASP.FCMPC,1 +INGASP.FCSF,2.5 +INGASP.FEXCRT,0.8 +INGASP.FPYLND,1.15 +INGASP.FSA7C,0.85 +INGASP.HBTP,0.465 +INGASP.HIR,0.015 +INGASP.HNCRU,41000 +INGASP.HQBWGLT,0.0607 +INGASP.HRI,2500 +INGASP.HSCREQ,20000 +INGASP.ICLM,3 +INGASP.ICONVRG,1 +INGASP.ICRUS,10 +INGASP.ISWING,0 +INGASP.IWLD,2 +INGASP.JENGSZ,3 +INGASP.KNAC,1 +INGASP.KODEAC,7 +INGASP.KODECL,7 +INGASP.KODETO,5 +INGASP.KODETR,6 +INGASP.MX,0 +INGASP.NFAIL,0 +INGASP.OFALT,0 +INGASP.OFEM,0.78 +INGASP.OHR,350 +INGASP.PRV,0.15 +INGASP.RCCRU,10 +INGASP.RELP,0 +INGASP.RELR,0.4524 +INGASP.RF,2,200,-1,1500,4,3,0,0 +INGASP.RI,0.8 +INGASP.ROSCAB,9999 +INGASP.RWCRTX,0.985 +INGASP.SKPES,0.258 +INGASP.SM1D,0.625 +INGASP.SRPM,18000 +INGASP.TBO,3500 +INGASP.TDELLD,27 +INGASP.TDELTO,27 +INGASP.TDELTX,27 +INGASP.TR,1 +INGASP.UWTWGLT,10 +INGASP.VCLMB,270 +INGASP.VDSCNT,-300 +INGASP.WENG,6130 +INGASP.WLPCT,0.9423 +INGASP.WNAC,0 +INGASP.WPLX,0 +INGASP.WPYLON,0 +INGASP.XTORQ,6950 \ No newline at end of file diff --git a/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.dat b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.dat new file mode 100644 index 0000000000..b9c5679d3f --- /dev/null +++ b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP.dat @@ -0,0 +1,289 @@ + Generic Hybrid-Wing Body Configuration / Sacled NASA GRC GTF/FPR=1.45 -1 + + $INGASP + IHWB=1, ! Hydrid Wing Body Configuration + AS=3., ! Number of aisles in the cabin + AR=10.0, ! Wing aspect ratio + ARHT=1.705, ! Horizontal tail aspect ratio + ARVT=1.705, ! Vertical tail aspect ratio + BOELTV=5.2615, ! wing span/vertical tail moment arm (if VBARVX is input) + COELTH=0.5463, ! wing chord/horizontal tail moment arm (if VBARHX is input) + DBARN =7.50, ! nacelle mean diameter, KNAC=2, in feet + DLMC4=30.0, ! sweep of wing quarter chord, degrees + DWPQCH=45.00, ! vertical tail quarter chord sweep in degrees if LCWING <> 0 + ELN=18.11, ! nacelle length, KNAC=2, in feet + ELPC=7.5, ! length of pilot compartment in feet (4.44) + ELODN=0.60, ! length to diameter ratio of nose cone of fuselage (2) + ELODT=1.75, ! length to diameter ratio of tail cone of fuselage (3.2) + HCK=5., ! mean fuselage cabin diameter minus mean fuselage nose diameter in feet (2.47) + HGTqWID=0.3158, ! Fuselage Height-to-Widath ratio + HTG=12.5, ! wing height about ground during ground run in feet (3.0) + HWING=0.50, ! wing location on fuselage =0, low wing; =1 high wing + HQBWGLT=0.0607, ! winglet height-to-span ratio + PAX=250., ! number of passenger seats excluding crew + PCT_FC=0.075, ! percent first class seating + PS=32.0, ! seat pitch in inches + RELR=0.4524, ! cg of fuselage and contents, fraction fuselage(.4) if LCWING <> 0 + SAB=18., ! seats abreast in fuselage + EL_FLGC=8.0, ! Length of First Class Lav, Galley & Closet + SAH=0., ! horizontal tail location on vertical tail: 0: low tail, 1: T-tail + SF_FAC=7916., ! Fuselage Wetted Area Adjustment factor (1.); if SF_FAC > 10., input as Fuselage Wetted area (ft^2) + SF_FAC=1.0001, ! Body wetted area multiplier + SAFTqS=0.200, ! Aft Body wetted area -to- Total Body wetted area + SLM=.27444, ! wing taper ratio + SLMH=.366, ! taper ratio of horizontal tail + SLMV=0.366, ! taper ratio of vertical tail + STRUT=0., ! attachment location of strut as fraction of half-span + SSTQSW=0., ! strut area divided by wing area + SWP_FB=65.0, ! forebody Sweep angle (deg.) + TCHT=.10, ! horizontal tail root thickness to chord ratio + TCR=.165, ! wing root thickness to chord ratio + TCSTRT = 0., ! strut thickness to chord ratio + TCT=.100, ! wing tip thickness to chord ratio + TCVT=.10, ! Vertical tail root thickness to chord rati + VBARHX=0.000001, ! Hz tail volume coefficient (default function of fus length and diameter) + VBARVX=0.0150, ! vertical tail volume coefficient (default function of fuselage length and diameter) + WAS=22., ! aisle width, in. + WPRFUS=.0 ! additional pressurized fuselage width for Cargo bay(ft) + WS=21., ! seat width, in +! YWFOLD=118.0 ! Folded Wing Span, ft. + YMG=0.0, ! span fraction location of main gear on wing 0: on fuselage 1: at tip + YP=0.0, ! span fraction location of engines on wing 0: on fuselage 1: at tip + XLQDE=1.3588, ! nacelle length to diameter ratio, KNAC=0 or 1 + XWQLF=0.463, ! Distance from Nose to Wing Aerodynamic Center over Fuselage Length (0.40 + ALPHL0=0., ! zero lift angle of attack in degrees + CLBqCLW=0.35, ! Body Lift-to-Wing Lift Ratio (For HWB Configurations) + CLALPH_B0=1.8265 ! lift curft clope of fuselage @ Mach = 0. (per radian) + ! Aerodynamics + CKF=-1.0, ! fuselage drag form factor (numerical function of fuselage fineness ratio) + CKW=-1.0, ! wing form factor (numerical function of TCR and TCT) + CKI=1.0, ! Wing/Fuselage Interference Factor (0.0, i.e No interference drag) + CKN=-1.0, ! nacelle form factor (numerical function of nacelle fineness ratio) + CKN=1.20, ! + CKVT=-1.0, ! vertical tail form factor (numerical function of TCVT) + CKHT=-1.0, ! horizontal tail form factor (numerical function of TCHT and SAH) +! Aero Calibration Factors (Calibration/Adv Aero Boeing 795-097 HWB) + FEXCRT=1.100, ! Excrescence drag factor + FCFWC=0.906, ! Wing + FCFFC=0.885, ! Fuselage + FCFVTC=0.90, ! Vertical tail + FCFHTC=0.750, ! Horizontal tail + FCFNC=1.150, ! Nacelle/Pylon + FPYLND=1.15, ! Pylon drag factor + FCKIC=1.00, ! Interference + FSA7C=0.850, ! Induced + FCMPC=1.0, ! Compressibility + XCPS=0.275, ! peak suction location + XCTCMX=0.325, ! max thickness location + ! Aero Technology Factors + FCFWT=0.926, ! Wing + FCFFT=0.93, ! Fuselage + FCFVTT=0.926, ! Vertical tail + FCFHTT=0.926, ! Horizontal tail + FCFNT=0.95, ! Nacelle/Pylon + FEXCRT=0.80, ! Excrescence + FCKIT=1.0, ! Interference +! End Aero Factors + DELFE = 0.25, ! delta flat plate area for fuselage + DELCD=0.00025, ! increment in CD (.0015) + SCFAC=0.025, ! shift in drag divergence Mach number due to supercritical design (0.) + EYEW=1.5, ! wing incidence to fuselage horizontal reference in degrees + ! KNAC determines nacelle drag bookkeeping + ! 0: nacelle drag computed as penalty to engine performance (turbofans only) + ! 1: nacelle drag part of aircraft drag; nacelle sized by engine size + ! 2: same as 1, except uses nacelle size inputs DRARN, ELN + KNAC=1, + BENGOB=0.0, ! fraction of flap-free wing span due to engines + BTEOB=0.61, ! ratio of flap span to wing span + CFOC=0.20, ! flap chord to wing chord ratio + CLEOC=.0001, ! ratio of leading edge device chord to wing chord (0 for no LED) + DCDOTE=0.10, ! drag coeff increment due to optimally deflected TE flaps + DELLEO=20., ! optimal deflection for leading edge device degrees (45) + DFLPTO=15., ! takeoff flap deflection, degrees + DELLED=0., ! leading edge device deflection, degrees (0) when? + DCLMTE=1.50, ! lift coefficient increment due to optimally deflected TE flaps + DFLPLD=25., ! landing flap deflection, degrees + FLAPN=2., ! number of flap segments per wing panel (1) + ! JFLTYP 1:plain flap, 2:split flap, 3:single slotted flap (default), 4:double slotted flap + ! 5:triple slotted flap, 6:Fowler flap, 7:double slotted Fowler flap + JFLTYP=4, + ! RCLMAX is the CLMAX reference value of basic wing reference conditions: aspect ratio = 12, taper ratio = 1., + ! t/c = 0.10, SweepQC = 0, Re = 6 x 10^6 + RCLMAX=1.45, + WCFLAP=1.00, ! weight trend coefficient in flap weight equation (default is a function of JFLYTYP) + ! CATD structural design category + ! 0 normal design FAR Part 23 + ! 1 utility design FAR 23 + ! 2 aerobatic design FAR 23 + ! 3.0 for transports FAR Part 25 + ! >3 value of input design limit load factor + CATD=3., + DELP=10.0, ! fuselage pressure differential, psi + DELWST=0., ! incremental structural weight, lb. (0.) + FPYL=1.25, ! factor for turbofan engine pylon weight if NTYE=7 and KNAC=2 + SKB=1.0585, ! weight trend coefficient of fuselage (Composite) + SKB=0.995, ! weight trend coefficient of fuselage (Composite) + SKB=0.889, ! Updated Value = ~9% reduction for composite to PRSEUS + SKCC=16.5, ! weight trend coefficient of cockpit controls + SKWF=.45, ! fraction of total theoretical wing volume used for wing fuel + FVOL_MRG=10. ! fuel volume margin,% (0.) + SKFS=.0350, ! weight trend coefficient for fuel system + SKFW=.919, ! weight trend coefficient of fixed wing controls + SKFW=.50, ! wing theoretical fuel volume factpr + SKPEI=.1415, ! weight trend coefficient of engine installation, fraction dry engine + SKPEI=.04373, ! GT Value + SKLG=.0520, ! weight trend coefficient of landing gear, fraction gross weight + SKMG=.85, ! weight trend coefficient main gear, fraction of landing gear + SKPES=0.258, ! weight trend coefficient of engine nacelle, fraction dry engine, if KNAC <> 2 + SKSTRUT=0., ! weight trend coefficient of strut, strut weight/wing weight + SKWFOLD =0.15, ! Wing fold weight factor + SKWW=102.41, ! weight trend coefficient of wing (Metal) + SKWW=85.0, ! weight trend coefficient of wing (Caligration Run - Composite) + SKWW=75.78, ! weight trend coefficient of wing 26% reduction for Al to PRSEUS + SKY=.124, ! weight trend coefficient horizontal tail + SKZ=.119, ! weight trend coefficient vertical tail + UWNAC=2.50, ! nacelle weight/nacelle surface area; lb per sq ft, if KNAC <> 2 + UWPAX=225., ! weight per passenger, including baggage, lb (200.) + UWT_AFT=5.32, ! Aft Body structural areal weight (lbs/sqft) (Metal) + UWT_AFT=5.00, ! Aft Body structural areal weight (lbs/sqft) (Composite) + UWTWGLT=10.0, ! unit areal weight of winglet, lb (5.0) + WCARGO=15000., ! weight of cargo, lb + WENG=6130., ! dry weight of one engine, lb if KNAC = 2 (includes gearbox if propeller) + WG=258210., ! initial gross weight guess, lb + WNAC=0., ! weight of one nacelle, lb if KNAC = 2 + WPLX=0., ! design payload, lb (default function of PAX) + WPYLON=0, ! weight of one pylon, lb, if KNAC=2 and NTYPE=7 + ! CW are weight coefficients for various subsytems. >1 is actual weight in lbsf + CW(1)=710., ! APU + CW(2)=.116, ! instruments + CW(3)=.107, ! hydraulics for flight controls + CW(4)=.135, ! hydraulics for gear + CW(5)=3225., ! avionics + CW(6)=1.155, ! air conditioning + CW(7)=236., ! anti-icing system + CW(8)=-40., ! furnishings + CW(9)=6.0, ! passenger service items lbsf per passenger + CW(10)=3.0, ! water lbsf per occupant + CW(11)=100.0, ! emergency equipment + CW(12)=5., ! catering items lbsf per passenger CW(13)=6.0, + CW(13)=12., ! trapped fuel factor + CW(14)=0.0667, ! cargo handling, number of ULD's per passemger + CW(15)=11.45, ! electrical system weight per passenger (16.0) + CW(16)=0., ! other operating items (0) + CKFF=1.000, ! factor on installed engine fuel flow + DCDSE=-1.0, ! delta CD due to engine out (default is zero), -1: program computes increment + DCDSE=0.0010, ! + DNQDE=1.2205, ! Nacelle Diamter-to-Engine Diameter Ratio + HEBQDN=0.0, ! nacelle diamter burried in fuselage over nacelle diameter(0.) + ENP=2. ! number of engines + KODETO=5, ! engine power setting during takeoff segment if NTYE=7 + KODECL=7, ! engine power setting during climb segment if NTYE=7 + KODETR=6, ! engine power setting during turn segment if NTYE=7 + ! KODEAC is engine power setting during acceleration segment if NTYE = 7 + ! 5: maximum power (default) + ! 6: maximum continuous power + ! 7: maximum climb power + KODEAC=7, + ! NTYE sets the type of engine + ! 1: reciprocating engine with carburetor, 2: reciprocating engine with fuel injection + ! 3: recip engine with fuel injection and geared, 4: rotary combustion engine + ! 5: turboshaft engine, 6: turboprop engine + ! 7: turbojet or turbofan engine + ! 11, 12, 13 same as 1, 2, 3 except HOPWSZ computes geometry and weight + ! 14 same as 4 except RCWSZ computes geometry and weight + NTYE=7, + RELP=0.0, ! engine cg fraction of fuselage length, for fuselage mounted engines, (0.) if LCWING <> 0 + SM1D=0.625, ! engine face Mach number sea level static if NTYE = 7 and KNAC <> 2 + HBTP=0.425, ! turbofan engine face hub/tip ratio + SWSLS=.1903, ! engine specific weight lb/lb thrust + SM1D=0.625, ! GT Value for Refanned 1133 + HBTP=0.465, ! GT Value for Refanned 1133 + SWSLS=.178884, ! GT Value for Refanned 1133 + THIN=37451., ! input thrust for one engine, lbf., if JENGSZ=4 and NTYE=7 + THIN=19580.2, ! copied from "SLS THRUST/ENG" in output + EMCRU=0.80, ! design cruise Mach number for engine sizing (not mission analysis) + HNCRU=41000., ! design cruise altitude in feet + HSCREQ=20000., ! required engine-out service ceiling + ! IWLD 0: landing weight = gross weight (default) 1: landing weight = weight at end of mission + ! 2: landing weight = fraction of gross weight (see WLPCT) + IWLD=2, + ! JENGSZ sets the type of engine sizing + ! 0: size engine for cruise only + ! 1: cruise and takeoff only + ! 2: cruise, takeoff, and climb only + ! 3: size for cruise and climb only + ! 4: engine thrust specified; (input KNAC=2, ELN, DBARN, WENG, WNAC) only if NTYE=7 + JENGSZ=3, + RWCRTX=0.985, ! ratio of cruise weight to gross weight for propulsion sizing (1.0) + VMLFSL=402.5, ! maximum structural design flight speed, mph + WGS=74.887, ! wing loading, psf + ISWING=0, ! hold wing area constant + WLPCT=.9423, ! ratio of landing weight to gross weight, if IWLD=2 + RCCRU=10.0, ! rate of climb at cruise point + ROCTOC=300., ! rate of climb at top of climb ft/min + XTORQ=6950., ! required takeoff distance to clear 35 ft, input if JENGSZ=1 or 2 (99999.) + TDELTO=27.0, ! Increnetal temperature above standard for takeoff + TDELLD=27.0, ! Increnetal temperature above standard for landing + TDELTX=27., ! temperature increment abive STD for takeoff engine sizing + ARNGE(1) = 5000., ! 0: no range or endurance requirement (default) <24: design endurance, hrs >24: design range, nm + ! ARNGE(2) = 0., ! Design Altitude, Short Range + ARNGE(3) = 900., ! Off Design Altitude, Short Range + ! ARNGE(4) = 0., ! Off Design Altitude, Long Range + CRALT =41000., ! mission cruise altitude, ft (HNCRU) + CRMACH=.80, ! mission analysis cruise Mach number (use EMCRU for engine sizing) + DELTT=0.1677, ! time spent taxiing before takeoff and after landing, hours + DV1=10., ! increment of engine failure decision speed above stall, kts (5) + DVR=5., ! increment of takeoff rotation speed above engine failure decision speed above stall, kts (5) + ! ICLM 1: climb at maximum rate of climb (default) 2: climb at maximum allowable operating speed + ! 3: climb at input EAS + ICLM=3, +! ICRUS = 0, cruise at CRALT (default) for cost and range calculation +! ICRUS = 1, cruise at normal power for cost and range calculation +! ICRUS = 2, cruise for best specific range for cost and range calculation +! ICRUS = 3, cruise for best endurance for cost and range calculation +! ICRUS = 10,11,12,13 – Cruise/Climb at constant Mach Number +! ICRUS = 20,21,22,23 – Cruise/Climb at constant True Airspeed, TAS +! ICRUS = 30,31,32,33 – Cruise/Climb at constant Equivalent Airspeed, EAS + ICRUS=10, !cruise specifier + MX=0, ! 0 – No alternate mission profile (default); 1 – Alternate mission profile input in NEWMIS namelist + NFAIL=0, ! 0: computes engine out and accelerate/stop distance, 1: computes only all engine performance (default) + OFALT=0., ! off design mission altitude in feet (0.0) + OFEM=.78, ! off design specified mission Mach number + ROSCAB=9999., ! cabin rate of sink during descent (500.) fpm + RSMX=900., ! maximum allowable rate of sink during landing approach ft per min (1000) + VDSCNT=-300., + FRESF=0.2222, ! Reserve Fuel fraction of mission fuel (minus sign for code trigger) + RF(1)=2.0, ! Reserve Fuel Input: Time for Missed Approach (min) + RF(2)=200., ! Reserve Fuel Input: Range to alternate + RF(3)=-1., ! Reserve Fuel Input: Cruise altitude to alternate + RF(4)=1500., ! Reserve Fuel Input: Holding Altitude + RF(5)=4.0, ! Approach/Landing time, min (0.) + RF(6)=3.0, ! Percent mission fuel reserce, % (0.0) + RF(7)=0., ! Alternate cruise Mach flag (=0: EMCRU ; =1: EMBSR) (1) + RF(8)=0., ! Hold Mach flag (=0: EMBEN ; =1: 1.4*VKST_APP) (0) + SINKTD=5., ! landing touchdown sink rate, ft per sec (3.0) + VCLMB=270., ! climb speed, EAS, kts (input only if ICLM=3) + XLFMX=1.15, ! landing flare load factor if < 4 or landing flare initiation height, ft if > 4. (1.2) + ALR=1.11, ! man-hour labor rate $ per hour ? + CINP=.11, ! cost of annual inspection ? + CLIAB=1984., ! cost of liability insurance ? + CMF=15., ! increment to fixed annual cost ? + CMV=.15, ! increment to hourly operating cost ? + CRWOH=15., ! crew overhead rate ? + DYR=12., ! aircraft depreciation period in years (8) + FCSF=2.5, ! fuel cost, $ per gallon (0.51) + HIR=0.015, ! hull insurance rate; insurance cost/aircraft price (0.02) + HRI=2500., ! hours between annual inspection (100) + OHR=350., ! Overhaul cost of one engine, $ per lb thrust or $ per HP (5.5) + PRV=.15, ! aircraft residual value/original value (0.2) + RI=.8, ! loan interest rate; yearly interest/loan (0.) + SRPM=18000., ! Cabin Attendant Cost ($/yr.) + TBO=3500., ! time between overhauls, hr (0. default which deletes cost computations) + TR=1.0, ! property tax rate; tax/value (0.) + ! Input Values for Trade Study + WG=150000., WGS=70., ICONVRG=1, + ARNGE(1) = 3500., ! + ARNGE(3) = 0., ! + SAB= 18., AS=3., PAX=150., WG=150000., HGTqWID= 0.25970, YWFOLD=118.0, ! 150 PAX & 18 Seats Abreast + $END + diff --git a/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP_aero.csv b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP_aero.csv new file mode 100644 index 0000000000..7e222c1e78 --- /dev/null +++ b/aviary/models/aircraft/blended_wing_body/generic_BWB_GASP_aero.csv @@ -0,0 +1,13596 @@ +# created 07/25/25 at 23:27 (made-up only for demonstration purposes) +# GASP-derived aerodynamics data converted from aero_BWB_modified_GASP.txt +# sref_at: 4876.0 +# cbar_at: 1.0 + +Altitude (ft, input), Mach (input), Angle of Attack (deg, input), CL (output), CD (output) + 0.0, 0.23, 0.0, -0.1539, 0.003657 + 0.0, 0.23, 0.05, -0.1511, 0.003707 + 0.0, 0.23, 0.1, -0.1483, 0.003755 + 0.0, 0.23, 0.15, -0.1455, 0.003801 + 0.0, 0.23, 0.2, -0.1427, 0.003846 + 0.0, 0.23, 0.25, -0.1399, 0.00389 + 0.0, 0.23, 0.3, -0.1371, 0.003932 + 0.0, 0.23, 0.35, -0.1343, 0.003972 + 0.0, 0.23, 0.4, -0.1315, 0.004011 + 0.0, 0.23, 0.45, -0.1288, 0.004048 + 0.0, 0.23, 0.5, -0.126, 0.004084 + 0.0, 0.23, 0.55, -0.1232, 0.004119 + 0.0, 0.23, 0.6, -0.1204, 0.004152 + 0.0, 0.23, 0.65, -0.1176, 0.004185 + 0.0, 0.23, 0.7, -0.1149, 0.004215 + 0.0, 0.23, 0.75, -0.1121, 0.004245 + 0.0, 0.23, 0.8, -0.1093, 0.004274 + 0.0, 0.23, 0.85, -0.1066, 0.004301 + 0.0, 0.23, 0.9, -0.1038, 0.004327 + 0.0, 0.23, 0.95, -0.101, 0.004352 + 0.0, 0.23, 1.0, -0.09826, 0.004376 + 0.0, 0.23, 1.05, -0.0955, 0.0044 + 0.0, 0.23, 1.1, -0.09274, 0.004422 + 0.0, 0.23, 1.15, -0.08998, 0.004443 + 0.0, 0.23, 1.2, -0.08722, 0.004463 + 0.0, 0.23, 1.25, -0.08447, 0.004483 + 0.0, 0.23, 1.3, -0.08171, 0.004501 + 0.0, 0.23, 1.35, -0.07896, 0.004519 + 0.0, 0.23, 1.4, -0.0762, 0.004536 + 0.0, 0.23, 1.45, -0.07345, 0.004553 + 0.0, 0.23, 1.5, -0.0707, 0.004568 + 0.0, 0.23, 1.55, -0.06795, 0.004583 + 0.0, 0.23, 1.6, -0.0652, 0.004598 + 0.0, 0.23, 1.65, -0.06245, 0.004612 + 0.0, 0.23, 1.7, -0.0597, 0.004625 + 0.0, 0.23, 1.75, -0.05695, 0.004638 + 0.0, 0.23, 1.8, -0.0542, 0.00465 + 0.0, 0.23, 1.85, -0.05145, 0.004662 + 0.0, 0.23, 1.9, -0.04871, 0.004673 + 0.0, 0.23, 1.95, -0.04596, 0.004684 + 0.0, 0.23, 2.0, -0.04321, 0.004695 + 0.0, 0.23, 2.05, -0.04046, 0.004705 + 0.0, 0.23, 2.1, -0.03771, 0.004715 + 0.0, 0.23, 2.15, -0.03497, 0.004725 + 0.0, 0.23, 2.2, -0.03222, 0.004735 + 0.0, 0.23, 2.25, -0.02947, 0.004744 + 0.0, 0.23, 2.3, -0.02672, 0.004754 + 0.0, 0.23, 2.35, -0.02397, 0.004763 + 0.0, 0.23, 2.4, -0.02122, 0.004772 + 0.0, 0.23, 2.45, -0.01847, 0.004782 + 0.0, 0.23, 2.5, -0.01572, 0.004791 + 0.0, 0.23, 2.55, -0.01297, 0.0048 + 0.0, 0.23, 2.6, -0.01022, 0.004809 + 0.0, 0.23, 2.65, -0.007462, 0.004819 + 0.0, 0.23, 2.7, -0.004707, 0.004828 + 0.0, 0.23, 2.75, -0.001952, 0.004838 + 0.0, 0.23, 2.8, 0.0008048, 0.004848 + 0.0, 0.23, 2.85, 0.003563, 0.004858 + 0.0, 0.23, 2.9, 0.006322, 0.004869 + 0.0, 0.23, 2.95, 0.009082, 0.004879 + 0.0, 0.23, 3.0, 0.01184, 0.004891 + 0.0, 0.23, 3.05, 0.01461, 0.004902 + 0.0, 0.23, 3.1, 0.01737, 0.004914 + 0.0, 0.23, 3.15, 0.02014, 0.004926 + 0.0, 0.23, 3.2, 0.02291, 0.004939 + 0.0, 0.23, 3.25, 0.02568, 0.004953 + 0.0, 0.23, 3.3, 0.02845, 0.004967 + 0.0, 0.23, 3.35, 0.03122, 0.004981 + 0.0, 0.23, 3.4, 0.034, 0.004997 + 0.0, 0.23, 3.45, 0.03678, 0.005013 + 0.0, 0.23, 3.5, 0.03956, 0.005029 + 0.0, 0.23, 3.55, 0.04234, 0.005047 + 0.0, 0.23, 3.6, 0.04512, 0.005065 + 0.0, 0.23, 3.65, 0.04791, 0.005084 + 0.0, 0.23, 3.7, 0.0507, 0.005103 + 0.0, 0.23, 3.75, 0.05349, 0.005124 + 0.0, 0.23, 3.8, 0.05629, 0.005145 + 0.0, 0.23, 3.85, 0.05908, 0.005168 + 0.0, 0.23, 3.9, 0.06188, 0.005191 + 0.0, 0.23, 3.95, 0.06468, 0.005216 + 0.0, 0.23, 4.0, 0.06749, 0.005241 + 0.0, 0.23, 4.05, 0.07033, 0.005273 + 0.0, 0.23, 4.1, 0.07318, 0.005305 + 0.0, 0.23, 4.15, 0.07602, 0.005338 + 0.0, 0.23, 4.2, 0.07887, 0.005372 + 0.0, 0.23, 4.25, 0.08171, 0.005406 + 0.0, 0.23, 4.3, 0.08456, 0.005442 + 0.0, 0.23, 4.35, 0.0874, 0.005478 + 0.0, 0.23, 4.4, 0.09025, 0.005516 + 0.0, 0.23, 4.45, 0.0931, 0.005554 + 0.0, 0.23, 4.5, 0.09594, 0.005592 + 0.0, 0.23, 4.55, 0.09878, 0.005632 + 0.0, 0.23, 4.6, 0.1016, 0.005672 + 0.0, 0.23, 4.65, 0.1045, 0.005714 + 0.0, 0.23, 4.7, 0.1073, 0.005756 + 0.0, 0.23, 4.75, 0.1102, 0.005799 + 0.0, 0.23, 4.8, 0.113, 0.005843 + 0.0, 0.23, 4.85, 0.1158, 0.005887 + 0.0, 0.23, 4.9, 0.1187, 0.005933 + 0.0, 0.23, 4.95, 0.1215, 0.005979 + 0.0, 0.23, 5.0, 0.1243, 0.006026 + 0.0, 0.23, 5.05, 0.1271, 0.006073 + 0.0, 0.23, 5.1, 0.13, 0.006122 + 0.0, 0.23, 5.15, 0.1328, 0.006171 + 0.0, 0.23, 5.2, 0.1356, 0.006221 + 0.0, 0.23, 5.25, 0.1384, 0.006271 + 0.0, 0.23, 5.3, 0.1412, 0.006323 + 0.0, 0.23, 5.35, 0.144, 0.006375 + 0.0, 0.23, 5.4, 0.1468, 0.006429 + 0.0, 0.23, 5.45, 0.1496, 0.006483 + 0.0, 0.23, 5.5, 0.1524, 0.006538 + 0.0, 0.23, 5.55, 0.1552, 0.006593 + 0.0, 0.23, 5.6, 0.158, 0.00665 + 0.0, 0.23, 5.65, 0.1607, 0.006708 + 0.0, 0.23, 5.7, 0.1635, 0.006766 + 0.0, 0.23, 5.75, 0.1663, 0.006825 + 0.0, 0.23, 5.8, 0.1691, 0.006885 + 0.0, 0.23, 5.85, 0.1718, 0.006946 + 0.0, 0.23, 5.9, 0.1746, 0.007008 + 0.0, 0.23, 5.95, 0.1774, 0.00707 + 0.0, 0.23, 6.0, 0.1801, 0.007134 + 0.0, 0.23, 6.05, 0.1829, 0.007189 + 0.0, 0.23, 6.1, 0.1857, 0.007245 + 0.0, 0.23, 6.15, 0.1884, 0.007302 + 0.0, 0.23, 6.2, 0.1912, 0.007359 + 0.0, 0.23, 6.25, 0.1939, 0.007417 + 0.0, 0.23, 6.3, 0.1967, 0.007476 + 0.0, 0.23, 6.35, 0.1994, 0.007535 + 0.0, 0.23, 6.4, 0.2022, 0.007596 + 0.0, 0.23, 6.45, 0.2049, 0.007657 + 0.0, 0.23, 6.5, 0.2076, 0.00772 + 0.0, 0.23, 6.55, 0.2104, 0.007783 + 0.0, 0.23, 6.6, 0.2131, 0.007848 + 0.0, 0.23, 6.65, 0.2158, 0.007914 + 0.0, 0.23, 6.7, 0.2185, 0.007982 + 0.0, 0.23, 6.75, 0.2212, 0.008051 + 0.0, 0.23, 6.8, 0.2239, 0.008121 + 0.0, 0.23, 6.85, 0.2266, 0.008193 + 0.0, 0.23, 6.9, 0.2293, 0.008266 + 0.0, 0.23, 6.95, 0.2319, 0.008341 + 0.0, 0.23, 7.0, 0.2346, 0.008418 + 0.0, 0.23, 7.05, 0.2372, 0.008496 + 0.0, 0.23, 7.1, 0.2399, 0.008576 + 0.0, 0.23, 7.15, 0.2425, 0.008659 + 0.0, 0.23, 7.2, 0.2451, 0.008743 + 0.0, 0.23, 7.25, 0.2477, 0.008829 + 0.0, 0.23, 7.3, 0.2503, 0.008918 + 0.0, 0.23, 7.35, 0.2529, 0.009008 + 0.0, 0.23, 7.4, 0.2555, 0.009101 + 0.0, 0.23, 7.45, 0.2581, 0.009196 + 0.0, 0.23, 7.5, 0.2606, 0.009294 + 0.0, 0.23, 7.55, 0.2632, 0.009394 + 0.0, 0.23, 7.6, 0.2657, 0.009497 + 0.0, 0.23, 7.65, 0.2683, 0.009602 + 0.0, 0.23, 7.7, 0.2708, 0.00971 + 0.0, 0.23, 7.75, 0.2733, 0.00982 + 0.0, 0.23, 7.8, 0.2758, 0.009934 + 0.0, 0.23, 7.85, 0.2782, 0.01005 + 0.0, 0.23, 7.9, 0.2807, 0.01017 + 0.0, 0.23, 7.95, 0.2831, 0.01029 + 0.0, 0.23, 8.0, 0.2856, 0.01042 + 0.0, 0.23, 8.05, 0.2879, 0.01054 + 0.0, 0.23, 8.1, 0.2902, 0.01068 + 0.0, 0.23, 8.15, 0.2925, 0.01081 + 0.0, 0.23, 8.2, 0.2948, 0.01095 + 0.0, 0.23, 8.25, 0.297, 0.01109 + 0.0, 0.23, 8.3, 0.2993, 0.01123 + 0.0, 0.23, 8.35, 0.3015, 0.01138 + 0.0, 0.23, 8.4, 0.3038, 0.01153 + 0.0, 0.23, 8.45, 0.306, 0.01169 + 0.0, 0.23, 8.5, 0.3082, 0.01185 + 0.0, 0.23, 8.55, 0.3104, 0.01201 + 0.0, 0.23, 8.6, 0.3125, 0.01218 + 0.0, 0.23, 8.65, 0.3147, 0.01235 + 0.0, 0.23, 8.7, 0.3169, 0.01253 + 0.0, 0.23, 8.75, 0.319, 0.0127 + 0.0, 0.23, 8.8, 0.3211, 0.01289 + 0.0, 0.23, 8.85, 0.3232, 0.01308 + 0.0, 0.23, 8.9, 0.3253, 0.01327 + 0.0, 0.23, 8.95, 0.3274, 0.01346 + 0.0, 0.23, 9.0, 0.3295, 0.01366 + 0.0, 0.23, 9.05, 0.3315, 0.01387 + 0.0, 0.23, 9.1, 0.3336, 0.01408 + 0.0, 0.23, 9.15, 0.3356, 0.01429 + 0.0, 0.23, 9.2, 0.3377, 0.01451 + 0.0, 0.23, 9.25, 0.3397, 0.01474 + 0.0, 0.23, 9.3, 0.3417, 0.01497 + 0.0, 0.23, 9.35, 0.3437, 0.0152 + 0.0, 0.23, 9.4, 0.3456, 0.01544 + 0.0, 0.23, 9.45, 0.3476, 0.01568 + 0.0, 0.23, 9.5, 0.3496, 0.01593 + 0.0, 0.23, 9.55, 0.3515, 0.01618 + 0.0, 0.23, 9.6, 0.3535, 0.01644 + 0.0, 0.23, 9.65, 0.3554, 0.01671 + 0.0, 0.23, 9.7, 0.3573, 0.01698 + 0.0, 0.23, 9.75, 0.3592, 0.01725 + 0.0, 0.23, 9.8, 0.3611, 0.01753 + 0.0, 0.23, 9.85, 0.363, 0.01782 + 0.0, 0.23, 9.9, 0.3648, 0.01811 + 0.0, 0.23, 9.95, 0.3667, 0.01841 + 0.0, 0.23, 10.0, 0.3685, 0.01872 + 0.0, 0.23, 10.05, 0.3705, 0.01909 + 0.0, 0.23, 10.1, 0.3724, 0.01947 + 0.0, 0.23, 10.15, 0.3743, 0.01985 + 0.0, 0.23, 10.2, 0.3762, 0.02024 + 0.0, 0.23, 10.25, 0.378, 0.02064 + 0.0, 0.23, 10.3, 0.3799, 0.02104 + 0.0, 0.23, 10.35, 0.3818, 0.02145 + 0.0, 0.23, 10.4, 0.3836, 0.02186 + 0.0, 0.23, 10.45, 0.3854, 0.02227 + 0.0, 0.23, 10.5, 0.3873, 0.02269 + 0.0, 0.23, 10.55, 0.3891, 0.02311 + 0.0, 0.23, 10.6, 0.3909, 0.02354 + 0.0, 0.23, 10.65, 0.3926, 0.02397 + 0.0, 0.23, 10.7, 0.3944, 0.0244 + 0.0, 0.23, 10.75, 0.3962, 0.02484 + 0.0, 0.23, 10.8, 0.3979, 0.02528 + 0.0, 0.23, 10.85, 0.3996, 0.02573 + 0.0, 0.23, 10.9, 0.4014, 0.02618 + 0.0, 0.23, 10.95, 0.4031, 0.02663 + 0.0, 0.23, 11.0, 0.4047, 0.02708 + 0.0, 0.23, 11.05, 0.4064, 0.02754 + 0.0, 0.23, 11.1, 0.4081, 0.02799 + 0.0, 0.23, 11.15, 0.4097, 0.02845 + 0.0, 0.23, 11.2, 0.4113, 0.02891 + 0.0, 0.23, 11.25, 0.413, 0.02938 + 0.0, 0.23, 11.3, 0.4146, 0.02984 + 0.0, 0.23, 11.35, 0.4161, 0.03031 + 0.0, 0.23, 11.4, 0.4177, 0.03078 + 0.0, 0.23, 11.45, 0.4193, 0.03125 + 0.0, 0.23, 11.5, 0.4208, 0.03172 + 0.0, 0.23, 11.55, 0.4223, 0.03219 + 0.0, 0.23, 11.6, 0.4238, 0.03266 + 0.0, 0.23, 11.65, 0.4253, 0.03313 + 0.0, 0.23, 11.7, 0.4267, 0.0336 + 0.0, 0.23, 11.75, 0.4282, 0.03408 + 0.0, 0.23, 11.8, 0.4296, 0.03455 + 0.0, 0.23, 11.85, 0.431, 0.03502 + 0.0, 0.23, 11.9, 0.4324, 0.03549 + 0.0, 0.23, 11.95, 0.4338, 0.03596 + 0.0, 0.23, 12.0, 0.4352, 0.03643 + 0.0, 0.23, 12.05, 0.4365, 0.0369 + 0.0, 0.23, 12.1, 0.4378, 0.03737 + 0.0, 0.23, 12.15, 0.4391, 0.03783 + 0.0, 0.23, 12.2, 0.4404, 0.0383 + 0.0, 0.23, 12.25, 0.4417, 0.03876 + 0.0, 0.23, 12.3, 0.4429, 0.03923 + 0.0, 0.23, 12.35, 0.4441, 0.03968 + 0.0, 0.23, 12.4, 0.4453, 0.04014 + 0.0, 0.23, 12.45, 0.4465, 0.0406 + 0.0, 0.23, 12.5, 0.4477, 0.04105 + 0.0, 0.23, 12.55, 0.4488, 0.0415 + 0.0, 0.23, 12.6, 0.4499, 0.04195 + 0.0, 0.23, 12.65, 0.451, 0.04239 + 0.0, 0.23, 12.7, 0.4521, 0.04283 + 0.0, 0.23, 12.75, 0.4532, 0.04327 + 0.0, 0.23, 12.8, 0.4542, 0.04371 + 0.0, 0.23, 12.85, 0.4552, 0.04414 + 0.0, 0.23, 12.9, 0.4562, 0.04456 + 0.0, 0.23, 12.95, 0.4572, 0.04499 + 0.0, 0.23, 13.0, 0.4581, 0.0454 + 0.0, 0.23, 13.05, 0.459, 0.04582 + 0.0, 0.23, 13.1, 0.4599, 0.04623 + 0.0, 0.23, 13.15, 0.4608, 0.04663 + 0.0, 0.23, 13.2, 0.4617, 0.04703 + 0.0, 0.23, 13.25, 0.4625, 0.04743 + 0.0, 0.23, 13.3, 0.4633, 0.04782 + 0.0, 0.23, 13.35, 0.4641, 0.0482 + 0.0, 0.23, 13.4, 0.4648, 0.04858 + 0.0, 0.23, 13.45, 0.4656, 0.04895 + 0.0, 0.23, 13.5, 0.4663, 0.04932 + 0.0, 0.23, 13.55, 0.467, 0.04968 + 0.0, 0.23, 13.6, 0.4676, 0.05004 + 0.0, 0.23, 13.65, 0.4682, 0.05038 + 0.0, 0.23, 13.7, 0.4688, 0.05073 + 0.0, 0.23, 13.75, 0.4694, 0.05106 + 0.0, 0.23, 13.8, 0.47, 0.05139 + 0.0, 0.23, 13.85, 0.4705, 0.05171 + 0.0, 0.23, 13.9, 0.471, 0.05202 + 0.0, 0.23, 13.95, 0.4715, 0.05233 + 0.0, 0.23, 14.0, 0.4719, 0.05263 + 0.0, 0.23, 14.05, 0.4723, 0.05292 + 0.0, 0.23, 14.1, 0.4727, 0.0532 + 0.0, 0.23, 14.15, 0.4731, 0.05348 + 0.0, 0.23, 14.2, 0.4734, 0.05374 + 0.0, 0.23, 14.25, 0.4737, 0.054 + 0.0, 0.23, 14.3, 0.474, 0.05425 + 0.0, 0.23, 14.35, 0.4743, 0.05449 + 0.0, 0.23, 14.4, 0.4745, 0.05472 + 0.0, 0.23, 14.45, 0.4747, 0.05495 + 0.0, 0.23, 14.5, 0.4749, 0.05516 + 0.0, 0.23, 14.55, 0.475, 0.05536 + 0.0, 0.23, 14.6, 0.4751, 0.05556 + 0.0, 0.23, 14.65, 0.4752, 0.05574 + 0.0, 0.23, 14.7, 0.4752, 0.05592 + 0.0, 0.23, 14.75, 0.4752, 0.05608 + 0.0, 0.23, 14.8, 0.4752, 0.05623 + 0.0, 0.23, 14.85, 0.4752, 0.05638 + 0.0, 0.23, 14.9, 0.4751, 0.05651 + 0.0, 0.23, 14.95, 0.475, 0.05663 + 0.0, 0.23, 15.0, 0.4749, 0.05674 + 0.0, 0.23, 15.05, 0.4747, 0.05684 + 0.0, 0.28, 0.0, -0.1263, -0.02898 + 0.0, 0.28, 0.05, -0.1256, -0.02855 + 0.0, 0.28, 0.1, -0.1248, -0.02811 + 0.0, 0.28, 0.15, -0.1238, -0.02766 + 0.0, 0.28, 0.2, -0.1226, -0.0272 + 0.0, 0.28, 0.25, -0.1214, -0.02673 + 0.0, 0.28, 0.3, -0.12, -0.02625 + 0.0, 0.28, 0.35, -0.1185, -0.02576 + 0.0, 0.28, 0.4, -0.1169, -0.02525 + 0.0, 0.28, 0.45, -0.1151, -0.02474 + 0.0, 0.28, 0.5, -0.1133, -0.02422 + 0.0, 0.28, 0.55, -0.1113, -0.02368 + 0.0, 0.28, 0.6, -0.1092, -0.02314 + 0.0, 0.28, 0.65, -0.107, -0.0226 + 0.0, 0.28, 0.7, -0.1048, -0.02204 + 0.0, 0.28, 0.75, -0.1024, -0.02147 + 0.0, 0.28, 0.8, -0.09992, -0.0209 + 0.0, 0.28, 0.85, -0.09737, -0.02033 + 0.0, 0.28, 0.9, -0.09473, -0.01974 + 0.0, 0.28, 0.95, -0.092, -0.01915 + 0.0, 0.28, 1.0, -0.0892, -0.01855 + 0.0, 0.28, 1.05, -0.08632, -0.01795 + 0.0, 0.28, 1.1, -0.08337, -0.01735 + 0.0, 0.28, 1.15, -0.08034, -0.01674 + 0.0, 0.28, 1.2, -0.07726, -0.01612 + 0.0, 0.28, 1.25, -0.07411, -0.0155 + 0.0, 0.28, 1.3, -0.0709, -0.01488 + 0.0, 0.28, 1.35, -0.06764, -0.01425 + 0.0, 0.28, 1.4, -0.06432, -0.01363 + 0.0, 0.28, 1.45, -0.06096, -0.013 + 0.0, 0.28, 1.5, -0.05755, -0.01237 + 0.0, 0.28, 1.55, -0.0541, -0.01173 + 0.0, 0.28, 1.6, -0.05061, -0.0111 + 0.0, 0.28, 1.65, -0.04709, -0.01046 + 0.0, 0.28, 1.7, -0.04353, -0.009826 + 0.0, 0.28, 1.75, -0.03995, -0.00919 + 0.0, 0.28, 1.8, -0.03634, -0.008555 + 0.0, 0.28, 1.85, -0.03271, -0.00792 + 0.0, 0.28, 1.9, -0.02906, -0.007287 + 0.0, 0.28, 1.95, -0.0254, -0.006655 + 0.0, 0.28, 2.0, -0.02172, -0.006024 + 0.0, 0.28, 2.05, -0.01804, -0.005396 + 0.0, 0.28, 2.1, -0.01436, -0.004771 + 0.0, 0.28, 2.15, -0.01067, -0.004149 + 0.0, 0.28, 2.2, -0.006986, -0.00353 + 0.0, 0.28, 2.25, -0.003308, -0.002914 + 0.0, 0.28, 2.3, 0.0003613, -0.002303 + 0.0, 0.28, 2.35, 0.004018, -0.001697 + 0.0, 0.28, 2.4, 0.007658, -0.001095 + 0.0, 0.28, 2.45, 0.01128, -0.0004983 + 0.0, 0.28, 2.5, 0.01488, 9.267e-05 + 0.0, 0.28, 2.55, 0.01845, 0.0006776 + 0.0, 0.28, 2.6, 0.02199, 0.001256 + 0.0, 0.28, 2.65, 0.0255, 0.001828 + 0.0, 0.28, 2.7, 0.02897, 0.002393 + 0.0, 0.28, 2.75, 0.0324, 0.00295 + 0.0, 0.28, 2.8, 0.03579, 0.003499 + 0.0, 0.28, 2.85, 0.03914, 0.00404 + 0.0, 0.28, 2.9, 0.04243, 0.004573 + 0.0, 0.28, 2.95, 0.04567, 0.005096 + 0.0, 0.28, 3.0, 0.04885, 0.005611 + 0.0, 0.28, 3.05, 0.05197, 0.006115 + 0.0, 0.28, 3.1, 0.05503, 0.006609 + 0.0, 0.28, 3.15, 0.05802, 0.007093 + 0.0, 0.28, 3.2, 0.06094, 0.007566 + 0.0, 0.28, 3.25, 0.06379, 0.008028 + 0.0, 0.28, 3.3, 0.06656, 0.008478 + 0.0, 0.28, 3.35, 0.06924, 0.008916 + 0.0, 0.28, 3.4, 0.07185, 0.009341 + 0.0, 0.28, 3.45, 0.07436, 0.009754 + 0.0, 0.28, 3.5, 0.07679, 0.01015 + 0.0, 0.28, 3.55, 0.07912, 0.01054 + 0.0, 0.28, 3.6, 0.08136, 0.01091 + 0.0, 0.28, 3.65, 0.08349, 0.01127 + 0.0, 0.28, 3.7, 0.08552, 0.01161 + 0.0, 0.28, 3.75, 0.08744, 0.01194 + 0.0, 0.28, 3.8, 0.08924, 0.01226 + 0.0, 0.28, 3.85, 0.09094, 0.01255 + 0.0, 0.28, 3.9, 0.09251, 0.01283 + 0.0, 0.28, 3.95, 0.09397, 0.0131 + 0.0, 0.28, 4.0, 0.0953, 0.01335 + 0.0, 0.28, 4.05, 0.09555, 0.01353 + 0.0, 0.28, 4.1, 0.09573, 0.0137 + 0.0, 0.28, 4.15, 0.09583, 0.01386 + 0.0, 0.28, 4.2, 0.09587, 0.01399 + 0.0, 0.28, 4.25, 0.09585, 0.01412 + 0.0, 0.28, 4.3, 0.09576, 0.01423 + 0.0, 0.28, 4.35, 0.09562, 0.01432 + 0.0, 0.28, 4.4, 0.09542, 0.0144 + 0.0, 0.28, 4.45, 0.09518, 0.01447 + 0.0, 0.28, 4.5, 0.09489, 0.01452 + 0.0, 0.28, 4.55, 0.09456, 0.01455 + 0.0, 0.28, 4.6, 0.09419, 0.01457 + 0.0, 0.28, 4.65, 0.09379, 0.01458 + 0.0, 0.28, 4.7, 0.09336, 0.01456 + 0.0, 0.28, 4.75, 0.09291, 0.01454 + 0.0, 0.28, 4.8, 0.09243, 0.0145 + 0.0, 0.28, 4.85, 0.09193, 0.01444 + 0.0, 0.28, 4.9, 0.09143, 0.01437 + 0.0, 0.28, 4.95, 0.09091, 0.01428 + 0.0, 0.28, 5.0, 0.09039, 0.01418 + 0.0, 0.28, 5.05, 0.08969, 0.01407 + 0.0, 0.28, 5.1, 0.089, 0.01395 + 0.0, 0.28, 5.15, 0.08833, 0.01381 + 0.0, 0.28, 5.2, 0.08766, 0.01365 + 0.0, 0.28, 5.25, 0.08703, 0.01348 + 0.0, 0.28, 5.3, 0.08642, 0.01329 + 0.0, 0.28, 5.35, 0.08585, 0.01309 + 0.0, 0.28, 5.4, 0.08532, 0.01287 + 0.0, 0.28, 5.45, 0.08484, 0.01263 + 0.0, 0.28, 5.5, 0.08442, 0.01238 + 0.0, 0.28, 5.55, 0.08406, 0.01211 + 0.0, 0.28, 5.6, 0.08376, 0.01182 + 0.0, 0.28, 5.65, 0.08354, 0.01152 + 0.0, 0.28, 5.7, 0.08341, 0.0112 + 0.0, 0.28, 5.75, 0.08336, 0.01086 + 0.0, 0.28, 5.8, 0.0834, 0.01051 + 0.0, 0.28, 5.85, 0.08355, 0.01014 + 0.0, 0.28, 5.9, 0.0838, 0.009749 + 0.0, 0.28, 5.95, 0.08416, 0.009342 + 0.0, 0.28, 6.0, 0.08465, 0.008917 + 0.0, 0.28, 6.05, 0.08683, 0.008398 + 0.0, 0.28, 6.1, 0.0892, 0.007858 + 0.0, 0.28, 6.15, 0.09177, 0.007298 + 0.0, 0.28, 6.2, 0.09453, 0.006717 + 0.0, 0.28, 6.25, 0.09747, 0.006116 + 0.0, 0.28, 6.3, 0.1006, 0.005495 + 0.0, 0.28, 6.35, 0.1039, 0.004855 + 0.0, 0.28, 6.4, 0.1073, 0.004196 + 0.0, 0.28, 6.45, 0.1109, 0.003519 + 0.0, 0.28, 6.5, 0.1147, 0.002825 + 0.0, 0.28, 6.55, 0.1186, 0.002112 + 0.0, 0.28, 6.6, 0.1227, 0.001383 + 0.0, 0.28, 6.65, 0.1269, 0.000637 + 0.0, 0.28, 6.7, 0.1313, -0.0001252 + 0.0, 0.28, 6.75, 0.1358, -0.0009032 + 0.0, 0.28, 6.8, 0.1404, -0.001697 + 0.0, 0.28, 6.85, 0.1451, -0.002505 + 0.0, 0.28, 6.9, 0.1499, -0.003328 + 0.0, 0.28, 6.95, 0.1549, -0.004165 + 0.0, 0.28, 7.0, 0.16, -0.005016 + 0.0, 0.28, 7.05, 0.1651, -0.00588 + 0.0, 0.28, 7.1, 0.1704, -0.006757 + 0.0, 0.28, 7.15, 0.1757, -0.007646 + 0.0, 0.28, 7.2, 0.1812, -0.008547 + 0.0, 0.28, 7.25, 0.1867, -0.00946 + 0.0, 0.28, 7.3, 0.1923, -0.01038 + 0.0, 0.28, 7.35, 0.1979, -0.01132 + 0.0, 0.28, 7.4, 0.2037, -0.01226 + 0.0, 0.28, 7.45, 0.2094, -0.01322 + 0.0, 0.28, 7.5, 0.2153, -0.01419 + 0.0, 0.28, 7.55, 0.2212, -0.01516 + 0.0, 0.28, 7.6, 0.2271, -0.01614 + 0.0, 0.28, 7.65, 0.2331, -0.01713 + 0.0, 0.28, 7.7, 0.2391, -0.01813 + 0.0, 0.28, 7.75, 0.2451, -0.01914 + 0.0, 0.28, 7.8, 0.2512, -0.02015 + 0.0, 0.28, 7.85, 0.2573, -0.02117 + 0.0, 0.28, 7.9, 0.2634, -0.0222 + 0.0, 0.28, 7.95, 0.2695, -0.02323 + 0.0, 0.28, 8.0, 0.2756, -0.02426 + 0.0, 0.28, 8.05, 0.2804, -0.02522 + 0.0, 0.28, 8.1, 0.2852, -0.02618 + 0.0, 0.28, 8.15, 0.29, -0.02715 + 0.0, 0.28, 8.2, 0.2948, -0.02812 + 0.0, 0.28, 8.25, 0.2996, -0.0291 + 0.0, 0.28, 8.3, 0.3044, -0.03008 + 0.0, 0.28, 8.35, 0.3092, -0.03106 + 0.0, 0.28, 8.4, 0.3139, -0.03205 + 0.0, 0.28, 8.45, 0.3187, -0.03304 + 0.0, 0.28, 8.5, 0.3235, -0.03404 + 0.0, 0.28, 8.55, 0.3283, -0.03504 + 0.0, 0.28, 8.6, 0.3331, -0.03605 + 0.0, 0.28, 8.65, 0.3378, -0.03705 + 0.0, 0.28, 8.7, 0.3426, -0.03807 + 0.0, 0.28, 8.75, 0.3474, -0.03908 + 0.0, 0.28, 8.8, 0.3521, -0.0401 + 0.0, 0.28, 8.85, 0.3569, -0.04112 + 0.0, 0.28, 8.9, 0.3617, -0.04215 + 0.0, 0.28, 8.95, 0.3664, -0.04318 + 0.0, 0.28, 9.0, 0.3712, -0.04421 + 0.0, 0.28, 9.05, 0.3759, -0.04524 + 0.0, 0.28, 9.1, 0.3807, -0.04628 + 0.0, 0.28, 9.15, 0.3854, -0.04732 + 0.0, 0.28, 9.2, 0.3901, -0.04836 + 0.0, 0.28, 9.25, 0.3949, -0.0494 + 0.0, 0.28, 9.3, 0.3996, -0.05045 + 0.0, 0.28, 9.35, 0.4043, -0.0515 + 0.0, 0.28, 9.4, 0.409, -0.05255 + 0.0, 0.28, 9.45, 0.4137, -0.0536 + 0.0, 0.28, 9.5, 0.4185, -0.05466 + 0.0, 0.28, 9.55, 0.4232, -0.05572 + 0.0, 0.28, 9.6, 0.4279, -0.05678 + 0.0, 0.28, 9.65, 0.4325, -0.05784 + 0.0, 0.28, 9.7, 0.4372, -0.0589 + 0.0, 0.28, 9.75, 0.4419, -0.05996 + 0.0, 0.28, 9.8, 0.4466, -0.06103 + 0.0, 0.28, 9.85, 0.4513, -0.06209 + 0.0, 0.28, 9.9, 0.4559, -0.06316 + 0.0, 0.28, 9.95, 0.4606, -0.06423 + 0.0, 0.28, 10.0, 0.4652, -0.0653 + 0.0, 0.28, 10.05, 0.4699, -0.0664 + 0.0, 0.28, 10.1, 0.4746, -0.0675 + 0.0, 0.28, 10.15, 0.4792, -0.0686 + 0.0, 0.28, 10.2, 0.4839, -0.06971 + 0.0, 0.28, 10.25, 0.4885, -0.07081 + 0.0, 0.28, 10.3, 0.4931, -0.07191 + 0.0, 0.28, 10.35, 0.4978, -0.07302 + 0.0, 0.28, 10.4, 0.5024, -0.07412 + 0.0, 0.28, 10.45, 0.507, -0.07522 + 0.0, 0.28, 10.5, 0.5116, -0.07632 + 0.0, 0.28, 10.55, 0.5162, -0.07741 + 0.0, 0.28, 10.6, 0.5207, -0.07851 + 0.0, 0.28, 10.65, 0.5253, -0.07961 + 0.0, 0.28, 10.7, 0.5299, -0.0807 + 0.0, 0.28, 10.75, 0.5344, -0.08179 + 0.0, 0.28, 10.8, 0.539, -0.08288 + 0.0, 0.28, 10.85, 0.5435, -0.08396 + 0.0, 0.28, 10.9, 0.548, -0.08504 + 0.0, 0.28, 10.95, 0.5525, -0.08612 + 0.0, 0.28, 11.0, 0.557, -0.0872 + 0.0, 0.28, 11.05, 0.5615, -0.08827 + 0.0, 0.28, 11.1, 0.566, -0.08934 + 0.0, 0.28, 11.15, 0.5705, -0.0904 + 0.0, 0.28, 11.2, 0.5749, -0.09146 + 0.0, 0.28, 11.25, 0.5794, -0.09252 + 0.0, 0.28, 11.3, 0.5838, -0.09357 + 0.0, 0.28, 11.35, 0.5882, -0.09461 + 0.0, 0.28, 11.4, 0.5927, -0.09566 + 0.0, 0.28, 11.45, 0.597, -0.09669 + 0.0, 0.28, 11.5, 0.6014, -0.09772 + 0.0, 0.28, 11.55, 0.6058, -0.09874 + 0.0, 0.28, 11.6, 0.6102, -0.09976 + 0.0, 0.28, 11.65, 0.6145, -0.1008 + 0.0, 0.28, 11.7, 0.6188, -0.1018 + 0.0, 0.28, 11.75, 0.6232, -0.1028 + 0.0, 0.28, 11.8, 0.6275, -0.1038 + 0.0, 0.28, 11.85, 0.6318, -0.1048 + 0.0, 0.28, 11.9, 0.636, -0.1057 + 0.0, 0.28, 11.95, 0.6403, -0.1067 + 0.0, 0.28, 12.0, 0.6445, -0.1077 + 0.0, 0.28, 12.05, 0.6488, -0.1086 + 0.0, 0.28, 12.1, 0.653, -0.1096 + 0.0, 0.28, 12.15, 0.6572, -0.1105 + 0.0, 0.28, 12.2, 0.6614, -0.1114 + 0.0, 0.28, 12.25, 0.6655, -0.1123 + 0.0, 0.28, 12.3, 0.6697, -0.1133 + 0.0, 0.28, 12.35, 0.6738, -0.1142 + 0.0, 0.28, 12.4, 0.678, -0.115 + 0.0, 0.28, 12.45, 0.6821, -0.1159 + 0.0, 0.28, 12.5, 0.6861, -0.1168 + 0.0, 0.28, 12.55, 0.6902, -0.1177 + 0.0, 0.28, 12.6, 0.6943, -0.1185 + 0.0, 0.28, 12.65, 0.6983, -0.1194 + 0.0, 0.28, 12.7, 0.7023, -0.1202 + 0.0, 0.28, 12.75, 0.7063, -0.121 + 0.0, 0.28, 12.8, 0.7103, -0.1218 + 0.0, 0.28, 12.85, 0.7143, -0.1226 + 0.0, 0.28, 12.9, 0.7182, -0.1234 + 0.0, 0.28, 12.95, 0.7221, -0.1242 + 0.0, 0.28, 13.0, 0.726, -0.1249 + 0.0, 0.28, 13.05, 0.7299, -0.1257 + 0.0, 0.28, 13.1, 0.7338, -0.1264 + 0.0, 0.28, 13.15, 0.7376, -0.1271 + 0.0, 0.28, 13.2, 0.7415, -0.1278 + 0.0, 0.28, 13.25, 0.7453, -0.1285 + 0.0, 0.28, 13.3, 0.7491, -0.1292 + 0.0, 0.28, 13.35, 0.7528, -0.1299 + 0.0, 0.28, 13.4, 0.7566, -0.1305 + 0.0, 0.28, 13.45, 0.7603, -0.1312 + 0.0, 0.28, 13.5, 0.764, -0.1318 + 0.0, 0.28, 13.55, 0.7677, -0.1324 + 0.0, 0.28, 13.6, 0.7713, -0.133 + 0.0, 0.28, 13.65, 0.775, -0.1336 + 0.0, 0.28, 13.7, 0.7786, -0.1341 + 0.0, 0.28, 13.75, 0.7822, -0.1347 + 0.0, 0.28, 13.8, 0.7858, -0.1352 + 0.0, 0.28, 13.85, 0.7893, -0.1357 + 0.0, 0.28, 13.9, 0.7928, -0.1362 + 0.0, 0.28, 13.95, 0.7963, -0.1367 + 0.0, 0.28, 14.0, 0.7998, -0.1372 + 0.0, 0.28, 14.05, 0.8033, -0.1377 + 0.0, 0.28, 14.1, 0.8067, -0.1381 + 0.0, 0.28, 14.15, 0.8101, -0.1385 + 0.0, 0.28, 14.2, 0.8135, -0.1389 + 0.0, 0.28, 14.25, 0.8168, -0.1393 + 0.0, 0.28, 14.3, 0.8202, -0.1397 + 0.0, 0.28, 14.35, 0.8235, -0.14 + 0.0, 0.28, 14.4, 0.8268, -0.1403 + 0.0, 0.28, 14.45, 0.83, -0.1406 + 0.0, 0.28, 14.5, 0.8333, -0.1409 + 0.0, 0.28, 14.55, 0.8365, -0.1412 + 0.0, 0.28, 14.6, 0.8397, -0.1414 + 0.0, 0.28, 14.65, 0.8428, -0.1417 + 0.0, 0.28, 14.7, 0.8459, -0.1419 + 0.0, 0.28, 14.75, 0.849, -0.1421 + 0.0, 0.28, 14.8, 0.8521, -0.1423 + 0.0, 0.28, 14.85, 0.8552, -0.1424 + 0.0, 0.28, 14.9, 0.8582, -0.1425 + 0.0, 0.28, 14.95, 0.8612, -0.1426 + 0.0, 0.28, 15.0, 0.8642, -0.1427 + 0.0, 0.28, 15.05, 0.8671, -0.1428 + 0.0, 0.33, 0.0, -0.108, -0.04833 + 0.0, 0.33, 0.05, -0.1085, -0.04769 + 0.0, 0.33, 0.1, -0.1088, -0.04702 + 0.0, 0.33, 0.15, -0.1089, -0.04634 + 0.0, 0.33, 0.2, -0.1088, -0.04564 + 0.0, 0.33, 0.25, -0.1085, -0.04492 + 0.0, 0.33, 0.3, -0.108, -0.04417 + 0.0, 0.33, 0.35, -0.1073, -0.04342 + 0.0, 0.33, 0.4, -0.1063, -0.04264 + 0.0, 0.33, 0.45, -0.1052, -0.04185 + 0.0, 0.33, 0.5, -0.1039, -0.04104 + 0.0, 0.33, 0.55, -0.1025, -0.04022 + 0.0, 0.33, 0.6, -0.1009, -0.03938 + 0.0, 0.33, 0.65, -0.09905, -0.03853 + 0.0, 0.33, 0.7, -0.09709, -0.03767 + 0.0, 0.33, 0.75, -0.09498, -0.03679 + 0.0, 0.33, 0.8, -0.09272, -0.0359 + 0.0, 0.33, 0.85, -0.09031, -0.035 + 0.0, 0.33, 0.9, -0.08776, -0.03409 + 0.0, 0.33, 0.95, -0.08509, -0.03316 + 0.0, 0.33, 1.0, -0.08228, -0.03223 + 0.0, 0.33, 1.05, -0.07936, -0.03129 + 0.0, 0.33, 1.1, -0.07631, -0.03034 + 0.0, 0.33, 1.15, -0.07316, -0.02938 + 0.0, 0.33, 1.2, -0.0699, -0.02842 + 0.0, 0.33, 1.25, -0.06654, -0.02745 + 0.0, 0.33, 1.3, -0.06309, -0.02647 + 0.0, 0.33, 1.35, -0.05955, -0.02549 + 0.0, 0.33, 1.4, -0.05592, -0.0245 + 0.0, 0.33, 1.45, -0.05222, -0.02351 + 0.0, 0.33, 1.5, -0.04844, -0.02251 + 0.0, 0.33, 1.55, -0.0446, -0.02152 + 0.0, 0.33, 1.6, -0.0407, -0.02051 + 0.0, 0.33, 1.65, -0.03674, -0.01951 + 0.0, 0.33, 1.7, -0.03273, -0.01851 + 0.0, 0.33, 1.75, -0.02867, -0.01751 + 0.0, 0.33, 1.8, -0.02457, -0.0165 + 0.0, 0.33, 1.85, -0.02044, -0.0155 + 0.0, 0.33, 1.9, -0.01629, -0.0145 + 0.0, 0.33, 1.95, -0.0121, -0.0135 + 0.0, 0.33, 2.0, -0.007905, -0.01251 + 0.0, 0.33, 2.05, -0.003693, -0.01152 + 0.0, 0.33, 2.1, 0.0005262, -0.01053 + 0.0, 0.33, 2.15, 0.004746, -0.009543 + 0.0, 0.33, 2.2, 0.008963, -0.008564 + 0.0, 0.33, 2.25, 0.01317, -0.007591 + 0.0, 0.33, 2.3, 0.01736, -0.006625 + 0.0, 0.33, 2.35, 0.02153, -0.005665 + 0.0, 0.33, 2.4, 0.02568, -0.004713 + 0.0, 0.33, 2.45, 0.02979, -0.003769 + 0.0, 0.33, 2.5, 0.03387, -0.002835 + 0.0, 0.33, 2.55, 0.0379, -0.001909 + 0.0, 0.33, 2.6, 0.04189, -0.0009942 + 0.0, 0.33, 2.65, 0.04582, -8.974e-05 + 0.0, 0.33, 2.7, 0.04969, 0.0008033 + 0.0, 0.33, 2.75, 0.0535, 0.001684 + 0.0, 0.33, 2.8, 0.05724, 0.002553 + 0.0, 0.33, 2.85, 0.06091, 0.003408 + 0.0, 0.33, 2.9, 0.06449, 0.00425 + 0.0, 0.33, 2.95, 0.06799, 0.005077 + 0.0, 0.33, 3.0, 0.0714, 0.005889 + 0.0, 0.33, 3.05, 0.07471, 0.006685 + 0.0, 0.33, 3.1, 0.07791, 0.007465 + 0.0, 0.33, 3.15, 0.08101, 0.008228 + 0.0, 0.33, 3.2, 0.084, 0.008973 + 0.0, 0.33, 3.25, 0.08686, 0.009701 + 0.0, 0.33, 3.3, 0.0896, 0.01041 + 0.0, 0.33, 3.35, 0.09222, 0.0111 + 0.0, 0.33, 3.4, 0.09469, 0.01177 + 0.0, 0.33, 3.45, 0.09703, 0.01242 + 0.0, 0.33, 3.5, 0.09922, 0.01304 + 0.0, 0.33, 3.55, 0.1013, 0.01365 + 0.0, 0.33, 3.6, 0.1031, 0.01423 + 0.0, 0.33, 3.65, 0.1049, 0.01479 + 0.0, 0.33, 3.7, 0.1064, 0.01533 + 0.0, 0.33, 3.75, 0.1078, 0.01584 + 0.0, 0.33, 3.8, 0.109, 0.01633 + 0.0, 0.33, 3.85, 0.11, 0.01679 + 0.0, 0.33, 3.9, 0.1108, 0.01722 + 0.0, 0.33, 3.95, 0.1114, 0.01763 + 0.0, 0.33, 4.0, 0.1119, 0.01801 + 0.0, 0.33, 4.05, 0.1105, 0.01829 + 0.0, 0.33, 4.1, 0.1091, 0.01854 + 0.0, 0.33, 4.15, 0.1076, 0.01876 + 0.0, 0.33, 4.2, 0.1059, 0.01897 + 0.0, 0.33, 4.25, 0.1041, 0.01914 + 0.0, 0.33, 4.3, 0.1023, 0.0193 + 0.0, 0.33, 4.35, 0.1003, 0.01943 + 0.0, 0.33, 4.4, 0.0983, 0.01953 + 0.0, 0.33, 4.45, 0.09619, 0.01962 + 0.0, 0.33, 4.5, 0.09401, 0.01967 + 0.0, 0.33, 4.55, 0.09177, 0.01971 + 0.0, 0.33, 4.6, 0.08947, 0.01972 + 0.0, 0.33, 4.65, 0.08711, 0.0197 + 0.0, 0.33, 4.7, 0.08471, 0.01966 + 0.0, 0.33, 4.75, 0.08227, 0.0196 + 0.0, 0.33, 4.8, 0.0798, 0.01951 + 0.0, 0.33, 4.85, 0.07729, 0.01939 + 0.0, 0.33, 4.9, 0.07477, 0.01926 + 0.0, 0.33, 4.95, 0.07224, 0.0191 + 0.0, 0.33, 5.0, 0.06969, 0.01891 + 0.0, 0.33, 5.05, 0.06689, 0.01871 + 0.0, 0.33, 5.1, 0.0641, 0.01849 + 0.0, 0.33, 5.15, 0.06133, 0.01825 + 0.0, 0.33, 5.2, 0.05858, 0.01798 + 0.0, 0.33, 5.25, 0.05587, 0.01768 + 0.0, 0.33, 5.3, 0.05322, 0.01736 + 0.0, 0.33, 5.35, 0.05062, 0.01701 + 0.0, 0.33, 5.4, 0.04809, 0.01664 + 0.0, 0.33, 5.45, 0.04564, 0.01624 + 0.0, 0.33, 5.5, 0.04329, 0.01581 + 0.0, 0.33, 5.55, 0.04103, 0.01536 + 0.0, 0.33, 5.6, 0.03888, 0.01488 + 0.0, 0.33, 5.65, 0.03685, 0.01437 + 0.0, 0.33, 5.7, 0.03496, 0.01383 + 0.0, 0.33, 5.75, 0.0332, 0.01327 + 0.0, 0.33, 5.8, 0.0316, 0.01268 + 0.0, 0.33, 5.85, 0.03015, 0.01206 + 0.0, 0.33, 5.9, 0.02888, 0.01141 + 0.0, 0.33, 5.95, 0.02779, 0.01073 + 0.0, 0.33, 6.0, 0.02689, 0.01002 + 0.0, 0.33, 6.05, 0.02866, 0.00917 + 0.0, 0.33, 6.1, 0.03074, 0.00828 + 0.0, 0.33, 6.15, 0.03313, 0.007357 + 0.0, 0.33, 6.2, 0.03581, 0.006401 + 0.0, 0.33, 6.25, 0.03879, 0.005411 + 0.0, 0.33, 6.3, 0.04205, 0.00439 + 0.0, 0.33, 6.35, 0.04558, 0.003338 + 0.0, 0.33, 6.4, 0.04938, 0.002255 + 0.0, 0.33, 6.45, 0.05344, 0.001142 + 0.0, 0.33, 6.5, 0.05776, -3.325e-07 + 0.0, 0.33, 6.55, 0.06231, -0.001172 + 0.0, 0.33, 6.6, 0.0671, -0.002371 + 0.0, 0.33, 6.65, 0.07212, -0.003598 + 0.0, 0.33, 6.7, 0.07736, -0.004852 + 0.0, 0.33, 6.75, 0.08281, -0.006132 + 0.0, 0.33, 6.8, 0.08847, -0.007437 + 0.0, 0.33, 6.85, 0.09432, -0.008768 + 0.0, 0.33, 6.9, 0.1004, -0.01012 + 0.0, 0.33, 6.95, 0.1066, -0.0115 + 0.0, 0.33, 7.0, 0.113, -0.0129 + 0.0, 0.33, 7.05, 0.1195, -0.01433 + 0.0, 0.33, 7.1, 0.1263, -0.01577 + 0.0, 0.33, 7.15, 0.1331, -0.01724 + 0.0, 0.33, 7.2, 0.1401, -0.01873 + 0.0, 0.33, 7.25, 0.1473, -0.02024 + 0.0, 0.33, 7.3, 0.1545, -0.02176 + 0.0, 0.33, 7.35, 0.1619, -0.02331 + 0.0, 0.33, 7.4, 0.1694, -0.02487 + 0.0, 0.33, 7.45, 0.177, -0.02645 + 0.0, 0.33, 7.5, 0.1847, -0.02805 + 0.0, 0.33, 7.55, 0.1925, -0.02967 + 0.0, 0.33, 7.6, 0.2003, -0.0313 + 0.0, 0.33, 7.65, 0.2083, -0.03294 + 0.0, 0.33, 7.7, 0.2162, -0.0346 + 0.0, 0.33, 7.75, 0.2243, -0.03627 + 0.0, 0.33, 7.8, 0.2324, -0.03796 + 0.0, 0.33, 7.85, 0.2405, -0.03965 + 0.0, 0.33, 7.9, 0.2487, -0.04136 + 0.0, 0.33, 7.95, 0.2569, -0.04308 + 0.0, 0.33, 8.0, 0.2651, -0.04481 + 0.0, 0.33, 8.05, 0.2713, -0.04642 + 0.0, 0.33, 8.1, 0.2774, -0.04803 + 0.0, 0.33, 8.15, 0.2837, -0.04965 + 0.0, 0.33, 8.2, 0.2899, -0.05128 + 0.0, 0.33, 8.25, 0.2961, -0.05293 + 0.0, 0.33, 8.3, 0.3023, -0.05458 + 0.0, 0.33, 8.35, 0.3085, -0.05624 + 0.0, 0.33, 8.4, 0.3148, -0.0579 + 0.0, 0.33, 8.45, 0.321, -0.05958 + 0.0, 0.33, 8.5, 0.3273, -0.06127 + 0.0, 0.33, 8.55, 0.3335, -0.06296 + 0.0, 0.33, 8.6, 0.3398, -0.06466 + 0.0, 0.33, 8.65, 0.346, -0.06638 + 0.0, 0.33, 8.7, 0.3523, -0.0681 + 0.0, 0.33, 8.75, 0.3586, -0.06982 + 0.0, 0.33, 8.8, 0.3648, -0.07156 + 0.0, 0.33, 8.85, 0.3711, -0.0733 + 0.0, 0.33, 8.9, 0.3774, -0.07506 + 0.0, 0.33, 8.95, 0.3837, -0.07682 + 0.0, 0.33, 9.0, 0.39, -0.07858 + 0.0, 0.33, 9.05, 0.3962, -0.08036 + 0.0, 0.33, 9.1, 0.4025, -0.08214 + 0.0, 0.33, 9.15, 0.4088, -0.08393 + 0.0, 0.33, 9.2, 0.4151, -0.08572 + 0.0, 0.33, 9.25, 0.4214, -0.08753 + 0.0, 0.33, 9.3, 0.4277, -0.08934 + 0.0, 0.33, 9.35, 0.434, -0.09116 + 0.0, 0.33, 9.4, 0.4403, -0.09298 + 0.0, 0.33, 9.45, 0.4466, -0.09481 + 0.0, 0.33, 9.5, 0.4529, -0.09665 + 0.0, 0.33, 9.55, 0.4591, -0.09849 + 0.0, 0.33, 9.6, 0.4654, -0.1003 + 0.0, 0.33, 9.65, 0.4717, -0.1022 + 0.0, 0.33, 9.7, 0.478, -0.1041 + 0.0, 0.33, 9.75, 0.4843, -0.1059 + 0.0, 0.33, 9.8, 0.4906, -0.1078 + 0.0, 0.33, 9.85, 0.4969, -0.1097 + 0.0, 0.33, 9.9, 0.5031, -0.1116 + 0.0, 0.33, 9.95, 0.5094, -0.1134 + 0.0, 0.33, 10.0, 0.5157, -0.1153 + 0.0, 0.33, 10.05, 0.5219, -0.1173 + 0.0, 0.33, 10.1, 0.5282, -0.1193 + 0.0, 0.33, 10.15, 0.5344, -0.1213 + 0.0, 0.33, 10.2, 0.5406, -0.1233 + 0.0, 0.33, 10.25, 0.5469, -0.1253 + 0.0, 0.33, 10.3, 0.5531, -0.1273 + 0.0, 0.33, 10.35, 0.5593, -0.1294 + 0.0, 0.33, 10.4, 0.5655, -0.1314 + 0.0, 0.33, 10.45, 0.5717, -0.1334 + 0.0, 0.33, 10.5, 0.5779, -0.1354 + 0.0, 0.33, 10.55, 0.5841, -0.1374 + 0.0, 0.33, 10.6, 0.5903, -0.1394 + 0.0, 0.33, 10.65, 0.5965, -0.1415 + 0.0, 0.33, 10.7, 0.6027, -0.1435 + 0.0, 0.33, 10.75, 0.6089, -0.1455 + 0.0, 0.33, 10.8, 0.615, -0.1475 + 0.0, 0.33, 10.85, 0.6212, -0.1495 + 0.0, 0.33, 10.9, 0.6273, -0.1515 + 0.0, 0.33, 10.95, 0.6335, -0.1535 + 0.0, 0.33, 11.0, 0.6396, -0.1555 + 0.0, 0.33, 11.05, 0.6457, -0.1575 + 0.0, 0.33, 11.1, 0.6519, -0.1595 + 0.0, 0.33, 11.15, 0.658, -0.1615 + 0.0, 0.33, 11.2, 0.6641, -0.1635 + 0.0, 0.33, 11.25, 0.6702, -0.1655 + 0.0, 0.33, 11.3, 0.6763, -0.1674 + 0.0, 0.33, 11.35, 0.6823, -0.1694 + 0.0, 0.33, 11.4, 0.6884, -0.1713 + 0.0, 0.33, 11.45, 0.6945, -0.1733 + 0.0, 0.33, 11.5, 0.7005, -0.1752 + 0.0, 0.33, 11.55, 0.7066, -0.1771 + 0.0, 0.33, 11.6, 0.7126, -0.1791 + 0.0, 0.33, 11.65, 0.7186, -0.181 + 0.0, 0.33, 11.7, 0.7246, -0.1829 + 0.0, 0.33, 11.75, 0.7306, -0.1848 + 0.0, 0.33, 11.8, 0.7366, -0.1866 + 0.0, 0.33, 11.85, 0.7426, -0.1885 + 0.0, 0.33, 11.9, 0.7486, -0.1904 + 0.0, 0.33, 11.95, 0.7545, -0.1922 + 0.0, 0.33, 12.0, 0.7605, -0.194 + 0.0, 0.33, 12.05, 0.7664, -0.1959 + 0.0, 0.33, 12.1, 0.7723, -0.1977 + 0.0, 0.33, 12.15, 0.7782, -0.1994 + 0.0, 0.33, 12.2, 0.7841, -0.2012 + 0.0, 0.33, 12.25, 0.79, -0.203 + 0.0, 0.33, 12.3, 0.7959, -0.2047 + 0.0, 0.33, 12.35, 0.8017, -0.2064 + 0.0, 0.33, 12.4, 0.8076, -0.2082 + 0.0, 0.33, 12.45, 0.8134, -0.2099 + 0.0, 0.33, 12.5, 0.8192, -0.2115 + 0.0, 0.33, 12.55, 0.825, -0.2132 + 0.0, 0.33, 12.6, 0.8308, -0.2148 + 0.0, 0.33, 12.65, 0.8366, -0.2164 + 0.0, 0.33, 12.7, 0.8423, -0.218 + 0.0, 0.33, 12.75, 0.8481, -0.2196 + 0.0, 0.33, 12.8, 0.8538, -0.2212 + 0.0, 0.33, 12.85, 0.8595, -0.2227 + 0.0, 0.33, 12.9, 0.8652, -0.2242 + 0.0, 0.33, 12.95, 0.8709, -0.2257 + 0.0, 0.33, 13.0, 0.8766, -0.2272 + 0.0, 0.33, 13.05, 0.8822, -0.2287 + 0.0, 0.33, 13.1, 0.8879, -0.2301 + 0.0, 0.33, 13.15, 0.8935, -0.2315 + 0.0, 0.33, 13.2, 0.8991, -0.2329 + 0.0, 0.33, 13.25, 0.9047, -0.2342 + 0.0, 0.33, 13.3, 0.9103, -0.2355 + 0.0, 0.33, 13.35, 0.9158, -0.2369 + 0.0, 0.33, 13.4, 0.9214, -0.2381 + 0.0, 0.33, 13.45, 0.9269, -0.2394 + 0.0, 0.33, 13.5, 0.9324, -0.2406 + 0.0, 0.33, 13.55, 0.9379, -0.2418 + 0.0, 0.33, 13.6, 0.9433, -0.243 + 0.0, 0.33, 13.65, 0.9488, -0.2441 + 0.0, 0.33, 13.7, 0.9542, -0.2452 + 0.0, 0.33, 13.75, 0.9596, -0.2463 + 0.0, 0.33, 13.8, 0.965, -0.2474 + 0.0, 0.33, 13.85, 0.9704, -0.2484 + 0.0, 0.33, 13.9, 0.9757, -0.2494 + 0.0, 0.33, 13.95, 0.9811, -0.2504 + 0.0, 0.33, 14.0, 0.9864, -0.2513 + 0.0, 0.33, 14.05, 0.9917, -0.2522 + 0.0, 0.33, 14.1, 0.9969, -0.2531 + 0.0, 0.33, 14.15, 1.002, -0.2539 + 0.0, 0.33, 14.2, 1.007, -0.2547 + 0.0, 0.33, 14.25, 1.013, -0.2555 + 0.0, 0.33, 14.3, 1.018, -0.2562 + 0.0, 0.33, 14.35, 1.023, -0.2569 + 0.0, 0.33, 14.4, 1.028, -0.2576 + 0.0, 0.33, 14.45, 1.033, -0.2582 + 0.0, 0.33, 14.5, 1.038, -0.2588 + 0.0, 0.33, 14.55, 1.043, -0.2593 + 0.0, 0.33, 14.6, 1.049, -0.2598 + 0.0, 0.33, 14.65, 1.054, -0.2603 + 0.0, 0.33, 14.7, 1.059, -0.2608 + 0.0, 0.33, 14.75, 1.064, -0.2612 + 0.0, 0.33, 14.8, 1.069, -0.2615 + 0.0, 0.33, 14.85, 1.073, -0.2619 + 0.0, 0.33, 14.9, 1.078, -0.2622 + 0.0, 0.33, 14.95, 1.083, -0.2624 + 0.0, 0.33, 15.0, 1.088, -0.2626 + 0.0, 0.33, 15.05, 1.093, -0.2628 + 0.0, 0.38, 0.0, -0.09774, -0.05662 + 0.0, 0.38, 0.05, -0.09886, -0.05589 + 0.0, 0.38, 0.1, -0.09971, -0.05513 + 0.0, 0.38, 0.15, -0.1003, -0.05436 + 0.0, 0.38, 0.2, -0.1007, -0.05355 + 0.0, 0.38, 0.25, -0.1008, -0.05273 + 0.0, 0.38, 0.3, -0.1006, -0.05188 + 0.0, 0.38, 0.35, -0.1003, -0.05102 + 0.0, 0.38, 0.4, -0.09969, -0.05013 + 0.0, 0.38, 0.45, -0.09889, -0.04923 + 0.0, 0.38, 0.5, -0.09787, -0.0483 + 0.0, 0.38, 0.55, -0.09665, -0.04736 + 0.0, 0.38, 0.6, -0.09523, -0.0464 + 0.0, 0.38, 0.65, -0.09362, -0.04542 + 0.0, 0.38, 0.7, -0.09182, -0.04443 + 0.0, 0.38, 0.75, -0.08984, -0.04342 + 0.0, 0.38, 0.8, -0.08769, -0.0424 + 0.0, 0.38, 0.85, -0.08537, -0.04136 + 0.0, 0.38, 0.9, -0.08289, -0.04032 + 0.0, 0.38, 0.95, -0.08026, -0.03926 + 0.0, 0.38, 1.0, -0.07748, -0.03818 + 0.0, 0.38, 1.05, -0.07456, -0.0371 + 0.0, 0.38, 1.1, -0.0715, -0.03601 + 0.0, 0.38, 1.15, -0.06831, -0.03491 + 0.0, 0.38, 1.2, -0.065, -0.0338 + 0.0, 0.38, 1.25, -0.06158, -0.03268 + 0.0, 0.38, 1.3, -0.05804, -0.03155 + 0.0, 0.38, 1.35, -0.0544, -0.03042 + 0.0, 0.38, 1.4, -0.05067, -0.02928 + 0.0, 0.38, 1.45, -0.04684, -0.02814 + 0.0, 0.38, 1.5, -0.04293, -0.02699 + 0.0, 0.38, 1.55, -0.03894, -0.02584 + 0.0, 0.38, 1.6, -0.03488, -0.02469 + 0.0, 0.38, 1.65, -0.03076, -0.02353 + 0.0, 0.38, 1.7, -0.02658, -0.02237 + 0.0, 0.38, 1.75, -0.02234, -0.02122 + 0.0, 0.38, 1.8, -0.01806, -0.02006 + 0.0, 0.38, 1.85, -0.01374, -0.0189 + 0.0, 0.38, 1.9, -0.009383, -0.01775 + 0.0, 0.38, 1.95, -0.005001, -0.01659 + 0.0, 0.38, 2.0, -0.0005991, -0.01544 + 0.0, 0.38, 2.05, 0.003817, -0.0143 + 0.0, 0.38, 2.1, 0.008242, -0.01316 + 0.0, 0.38, 2.15, 0.01267, -0.01202 + 0.0, 0.38, 2.2, 0.01709, -0.01089 + 0.0, 0.38, 2.25, 0.0215, -0.009763 + 0.0, 0.38, 2.3, 0.02589, -0.008646 + 0.0, 0.38, 2.35, 0.03026, -0.007537 + 0.0, 0.38, 2.4, 0.0346, -0.006437 + 0.0, 0.38, 2.45, 0.0389, -0.005346 + 0.0, 0.38, 2.5, 0.04316, -0.004265 + 0.0, 0.38, 2.55, 0.04736, -0.003195 + 0.0, 0.38, 2.6, 0.05152, -0.002137 + 0.0, 0.38, 2.65, 0.05561, -0.001091 + 0.0, 0.38, 2.7, 0.05963, -5.874e-05 + 0.0, 0.38, 2.75, 0.06358, 0.0009602 + 0.0, 0.38, 2.8, 0.06744, 0.001965 + 0.0, 0.38, 2.85, 0.07122, 0.002954 + 0.0, 0.38, 2.9, 0.0749, 0.003927 + 0.0, 0.38, 2.95, 0.07849, 0.004883 + 0.0, 0.38, 3.0, 0.08196, 0.005822 + 0.0, 0.38, 3.05, 0.08533, 0.006743 + 0.0, 0.38, 3.1, 0.08857, 0.007645 + 0.0, 0.38, 3.15, 0.09169, 0.008528 + 0.0, 0.38, 3.2, 0.09468, 0.00939 + 0.0, 0.38, 3.25, 0.09753, 0.01023 + 0.0, 0.38, 3.3, 0.1002, 0.01105 + 0.0, 0.38, 3.35, 0.1028, 0.01185 + 0.0, 0.38, 3.4, 0.1052, 0.01262 + 0.0, 0.38, 3.45, 0.1074, 0.01337 + 0.0, 0.38, 3.5, 0.1095, 0.0141 + 0.0, 0.38, 3.55, 0.1113, 0.0148 + 0.0, 0.38, 3.6, 0.113, 0.01547 + 0.0, 0.38, 3.65, 0.1146, 0.01612 + 0.0, 0.38, 3.7, 0.1159, 0.01674 + 0.0, 0.38, 3.75, 0.117, 0.01733 + 0.0, 0.38, 3.8, 0.1179, 0.01789 + 0.0, 0.38, 3.85, 0.1186, 0.01842 + 0.0, 0.38, 3.9, 0.119, 0.01892 + 0.0, 0.38, 3.95, 0.1193, 0.0194 + 0.0, 0.38, 4.0, 0.1193, 0.01983 + 0.0, 0.38, 4.05, 0.1173, 0.02015 + 0.0, 0.38, 4.1, 0.1151, 0.02043 + 0.0, 0.38, 4.15, 0.1128, 0.02069 + 0.0, 0.38, 4.2, 0.1104, 0.02092 + 0.0, 0.38, 4.25, 0.1078, 0.02113 + 0.0, 0.38, 4.3, 0.1052, 0.0213 + 0.0, 0.38, 4.35, 0.1024, 0.02145 + 0.0, 0.38, 4.4, 0.09958, 0.02157 + 0.0, 0.38, 4.45, 0.09663, 0.02166 + 0.0, 0.38, 4.5, 0.0936, 0.02172 + 0.0, 0.38, 4.55, 0.0905, 0.02176 + 0.0, 0.38, 4.6, 0.08733, 0.02176 + 0.0, 0.38, 4.65, 0.0841, 0.02174 + 0.0, 0.38, 4.7, 0.08082, 0.02169 + 0.0, 0.38, 4.75, 0.07749, 0.02162 + 0.0, 0.38, 4.8, 0.07413, 0.02151 + 0.0, 0.38, 4.85, 0.07073, 0.02138 + 0.0, 0.38, 4.9, 0.06731, 0.02122 + 0.0, 0.38, 4.95, 0.06387, 0.02103 + 0.0, 0.38, 5.0, 0.06043, 0.02081 + 0.0, 0.38, 5.05, 0.05669, 0.02059 + 0.0, 0.38, 5.1, 0.05297, 0.02034 + 0.0, 0.38, 5.15, 0.04927, 0.02006 + 0.0, 0.38, 5.2, 0.0456, 0.01975 + 0.0, 0.38, 5.25, 0.04198, 0.01941 + 0.0, 0.38, 5.3, 0.03842, 0.01904 + 0.0, 0.38, 5.35, 0.03493, 0.01864 + 0.0, 0.38, 5.4, 0.03151, 0.01821 + 0.0, 0.38, 5.45, 0.02819, 0.01775 + 0.0, 0.38, 5.5, 0.02497, 0.01726 + 0.0, 0.38, 5.55, 0.02187, 0.01674 + 0.0, 0.38, 5.6, 0.0189, 0.01619 + 0.0, 0.38, 5.65, 0.01606, 0.0156 + 0.0, 0.38, 5.7, 0.01338, 0.01498 + 0.0, 0.38, 5.75, 0.01085, 0.01434 + 0.0, 0.38, 5.8, 0.008505, 0.01365 + 0.0, 0.38, 5.85, 0.006343, 0.01294 + 0.0, 0.38, 5.9, 0.004377, 0.01219 + 0.0, 0.38, 5.95, 0.002621, 0.01141 + 0.0, 0.38, 6.0, 0.001086, 0.01059 + 0.0, 0.38, 6.05, 0.002599, 0.009598 + 0.0, 0.38, 6.1, 0.004472, 0.008564 + 0.0, 0.38, 6.15, 0.006698, 0.007491 + 0.0, 0.38, 6.2, 0.009267, 0.006378 + 0.0, 0.38, 6.25, 0.01217, 0.005227 + 0.0, 0.38, 6.3, 0.0154, 0.004039 + 0.0, 0.38, 6.35, 0.01894, 0.002813 + 0.0, 0.38, 6.4, 0.0228, 0.001552 + 0.0, 0.38, 6.45, 0.02695, 0.0002544 + 0.0, 0.38, 6.5, 0.03139, -0.001077 + 0.0, 0.38, 6.55, 0.03611, -0.002443 + 0.0, 0.38, 6.6, 0.0411, -0.003842 + 0.0, 0.38, 6.65, 0.04636, -0.005274 + 0.0, 0.38, 6.7, 0.05187, -0.006737 + 0.0, 0.38, 6.75, 0.05762, -0.008232 + 0.0, 0.38, 6.8, 0.06361, -0.009756 + 0.0, 0.38, 6.85, 0.06983, -0.01131 + 0.0, 0.38, 6.9, 0.07626, -0.01289 + 0.0, 0.38, 6.95, 0.08291, -0.01451 + 0.0, 0.38, 7.0, 0.08975, -0.01614 + 0.0, 0.38, 7.05, 0.09679, -0.01781 + 0.0, 0.38, 7.1, 0.104, -0.0195 + 0.0, 0.38, 7.15, 0.1114, -0.02122 + 0.0, 0.38, 7.2, 0.119, -0.02296 + 0.0, 0.38, 7.25, 0.1267, -0.02472 + 0.0, 0.38, 7.3, 0.1345, -0.02651 + 0.0, 0.38, 7.35, 0.1425, -0.02832 + 0.0, 0.38, 7.4, 0.1506, -0.03015 + 0.0, 0.38, 7.45, 0.1589, -0.03201 + 0.0, 0.38, 7.5, 0.1672, -0.03388 + 0.0, 0.38, 7.55, 0.1757, -0.03577 + 0.0, 0.38, 7.6, 0.1843, -0.03768 + 0.0, 0.38, 7.65, 0.1929, -0.03961 + 0.0, 0.38, 7.7, 0.2016, -0.04156 + 0.0, 0.38, 7.75, 0.2104, -0.04352 + 0.0, 0.38, 7.8, 0.2192, -0.0455 + 0.0, 0.38, 7.85, 0.2281, -0.04749 + 0.0, 0.38, 7.9, 0.237, -0.0495 + 0.0, 0.38, 7.95, 0.246, -0.05152 + 0.0, 0.38, 8.0, 0.2549, -0.05355 + 0.0, 0.38, 8.05, 0.2616, -0.05543 + 0.0, 0.38, 8.1, 0.2683, -0.05733 + 0.0, 0.38, 8.15, 0.2751, -0.05923 + 0.0, 0.38, 8.2, 0.2818, -0.06115 + 0.0, 0.38, 8.25, 0.2885, -0.06308 + 0.0, 0.38, 8.3, 0.2953, -0.06502 + 0.0, 0.38, 8.35, 0.3021, -0.06697 + 0.0, 0.38, 8.4, 0.3088, -0.06894 + 0.0, 0.38, 8.45, 0.3156, -0.07091 + 0.0, 0.38, 8.5, 0.3224, -0.0729 + 0.0, 0.38, 8.55, 0.3292, -0.07489 + 0.0, 0.38, 8.6, 0.336, -0.0769 + 0.0, 0.38, 8.65, 0.3429, -0.07892 + 0.0, 0.38, 8.7, 0.3497, -0.08095 + 0.0, 0.38, 8.75, 0.3565, -0.08299 + 0.0, 0.38, 8.8, 0.3634, -0.08504 + 0.0, 0.38, 8.85, 0.3702, -0.0871 + 0.0, 0.38, 8.9, 0.3771, -0.08917 + 0.0, 0.38, 8.95, 0.3839, -0.09124 + 0.0, 0.38, 9.0, 0.3908, -0.09333 + 0.0, 0.38, 9.05, 0.3977, -0.09543 + 0.0, 0.38, 9.1, 0.4046, -0.09754 + 0.0, 0.38, 9.15, 0.4114, -0.09966 + 0.0, 0.38, 9.2, 0.4183, -0.1018 + 0.0, 0.38, 9.25, 0.4252, -0.1039 + 0.0, 0.38, 9.3, 0.4321, -0.1061 + 0.0, 0.38, 9.35, 0.439, -0.1082 + 0.0, 0.38, 9.4, 0.4459, -0.1104 + 0.0, 0.38, 9.45, 0.4528, -0.1126 + 0.0, 0.38, 9.5, 0.4597, -0.1147 + 0.0, 0.38, 9.55, 0.4666, -0.1169 + 0.0, 0.38, 9.6, 0.4735, -0.1191 + 0.0, 0.38, 9.65, 0.4805, -0.1213 + 0.0, 0.38, 9.7, 0.4874, -0.1236 + 0.0, 0.38, 9.75, 0.4943, -0.1258 + 0.0, 0.38, 9.8, 0.5012, -0.128 + 0.0, 0.38, 9.85, 0.5081, -0.1302 + 0.0, 0.38, 9.9, 0.515, -0.1325 + 0.0, 0.38, 9.95, 0.5219, -0.1347 + 0.0, 0.38, 10.0, 0.5288, -0.137 + 0.0, 0.38, 10.05, 0.5357, -0.1394 + 0.0, 0.38, 10.1, 0.5426, -0.1418 + 0.0, 0.38, 10.15, 0.5494, -0.1442 + 0.0, 0.38, 10.2, 0.5563, -0.1466 + 0.0, 0.38, 10.25, 0.5631, -0.149 + 0.0, 0.38, 10.3, 0.57, -0.1514 + 0.0, 0.38, 10.35, 0.5768, -0.1539 + 0.0, 0.38, 10.4, 0.5837, -0.1563 + 0.0, 0.38, 10.45, 0.5905, -0.1587 + 0.0, 0.38, 10.5, 0.5974, -0.1612 + 0.0, 0.38, 10.55, 0.6042, -0.1636 + 0.0, 0.38, 10.6, 0.611, -0.166 + 0.0, 0.38, 10.65, 0.6179, -0.1685 + 0.0, 0.38, 10.7, 0.6247, -0.1709 + 0.0, 0.38, 10.75, 0.6315, -0.1733 + 0.0, 0.38, 10.8, 0.6383, -0.1758 + 0.0, 0.38, 10.85, 0.6451, -0.1782 + 0.0, 0.38, 10.9, 0.6519, -0.1806 + 0.0, 0.38, 10.95, 0.6587, -0.183 + 0.0, 0.38, 11.0, 0.6655, -0.1855 + 0.0, 0.38, 11.05, 0.6723, -0.1879 + 0.0, 0.38, 11.1, 0.6791, -0.1903 + 0.0, 0.38, 11.15, 0.6859, -0.1927 + 0.0, 0.38, 11.2, 0.6927, -0.1951 + 0.0, 0.38, 11.25, 0.6994, -0.1975 + 0.0, 0.38, 11.3, 0.7062, -0.1999 + 0.0, 0.38, 11.35, 0.7129, -0.2023 + 0.0, 0.38, 11.4, 0.7197, -0.2046 + 0.0, 0.38, 11.45, 0.7264, -0.207 + 0.0, 0.38, 11.5, 0.7332, -0.2093 + 0.0, 0.38, 11.55, 0.7399, -0.2117 + 0.0, 0.38, 11.6, 0.7466, -0.214 + 0.0, 0.38, 11.65, 0.7533, -0.2163 + 0.0, 0.38, 11.7, 0.76, -0.2186 + 0.0, 0.38, 11.75, 0.7667, -0.2209 + 0.0, 0.38, 11.8, 0.7734, -0.2232 + 0.0, 0.38, 11.85, 0.7801, -0.2255 + 0.0, 0.38, 11.9, 0.7868, -0.2278 + 0.0, 0.38, 11.95, 0.7934, -0.23 + 0.0, 0.38, 12.0, 0.8001, -0.2322 + 0.0, 0.38, 12.05, 0.8067, -0.2344 + 0.0, 0.38, 12.1, 0.8134, -0.2366 + 0.0, 0.38, 12.15, 0.82, -0.2388 + 0.0, 0.38, 12.2, 0.8266, -0.241 + 0.0, 0.38, 12.25, 0.8332, -0.2431 + 0.0, 0.38, 12.3, 0.8398, -0.2452 + 0.0, 0.38, 12.35, 0.8464, -0.2473 + 0.0, 0.38, 12.4, 0.853, -0.2494 + 0.0, 0.38, 12.45, 0.8596, -0.2515 + 0.0, 0.38, 12.5, 0.8661, -0.2535 + 0.0, 0.38, 12.55, 0.8727, -0.2555 + 0.0, 0.38, 12.6, 0.8792, -0.2575 + 0.0, 0.38, 12.65, 0.8857, -0.2595 + 0.0, 0.38, 12.7, 0.8922, -0.2615 + 0.0, 0.38, 12.75, 0.8987, -0.2634 + 0.0, 0.38, 12.8, 0.9052, -0.2653 + 0.0, 0.38, 12.85, 0.9117, -0.2672 + 0.0, 0.38, 12.9, 0.9182, -0.269 + 0.0, 0.38, 12.95, 0.9246, -0.2709 + 0.0, 0.38, 13.0, 0.9311, -0.2727 + 0.0, 0.38, 13.05, 0.9375, -0.2744 + 0.0, 0.38, 13.1, 0.9439, -0.2762 + 0.0, 0.38, 13.15, 0.9503, -0.2779 + 0.0, 0.38, 13.2, 0.9567, -0.2796 + 0.0, 0.38, 13.25, 0.9631, -0.2812 + 0.0, 0.38, 13.3, 0.9694, -0.2829 + 0.0, 0.38, 13.35, 0.9758, -0.2845 + 0.0, 0.38, 13.4, 0.9821, -0.286 + 0.0, 0.38, 13.45, 0.9884, -0.2876 + 0.0, 0.38, 13.5, 0.9947, -0.2891 + 0.0, 0.38, 13.55, 1.001, -0.2905 + 0.0, 0.38, 13.6, 1.007, -0.2919 + 0.0, 0.38, 13.65, 1.014, -0.2933 + 0.0, 0.38, 13.7, 1.02, -0.2947 + 0.0, 0.38, 13.75, 1.026, -0.296 + 0.0, 0.38, 13.8, 1.032, -0.2973 + 0.0, 0.38, 13.85, 1.038, -0.2986 + 0.0, 0.38, 13.9, 1.045, -0.2998 + 0.0, 0.38, 13.95, 1.051, -0.301 + 0.0, 0.38, 14.0, 1.057, -0.3021 + 0.0, 0.38, 14.05, 1.063, -0.3032 + 0.0, 0.38, 14.1, 1.069, -0.3043 + 0.0, 0.38, 14.15, 1.075, -0.3053 + 0.0, 0.38, 14.2, 1.081, -0.3063 + 0.0, 0.38, 14.25, 1.087, -0.3072 + 0.0, 0.38, 14.3, 1.094, -0.3081 + 0.0, 0.38, 14.35, 1.1, -0.309 + 0.0, 0.38, 14.4, 1.106, -0.3098 + 0.0, 0.38, 14.45, 1.112, -0.3106 + 0.0, 0.38, 14.5, 1.118, -0.3113 + 0.0, 0.38, 14.55, 1.124, -0.312 + 0.0, 0.38, 14.6, 1.129, -0.3126 + 0.0, 0.38, 14.65, 1.135, -0.3132 + 0.0, 0.38, 14.7, 1.141, -0.3137 + 0.0, 0.38, 14.75, 1.147, -0.3142 + 0.0, 0.38, 14.8, 1.153, -0.3147 + 0.0, 0.38, 14.85, 1.159, -0.3151 + 0.0, 0.38, 14.9, 1.165, -0.3154 + 0.0, 0.38, 14.95, 1.171, -0.3157 + 0.0, 0.38, 15.0, 1.176, -0.316 + 0.0, 0.38, 15.05, 1.182, -0.3162 + 0.0, 0.43, 0.0, -0.09462, -0.05606 + 0.0, 0.43, 0.05, -0.09574, -0.05534 + 0.0, 0.43, 0.1, -0.0966, -0.0546 + 0.0, 0.43, 0.15, -0.09721, -0.05384 + 0.0, 0.43, 0.2, -0.09757, -0.05305 + 0.0, 0.43, 0.25, -0.09769, -0.05225 + 0.0, 0.43, 0.3, -0.09757, -0.05142 + 0.0, 0.43, 0.35, -0.09722, -0.05057 + 0.0, 0.43, 0.4, -0.09665, -0.0497 + 0.0, 0.43, 0.45, -0.09587, -0.04881 + 0.0, 0.43, 0.5, -0.09487, -0.0479 + 0.0, 0.43, 0.55, -0.09367, -0.04697 + 0.0, 0.43, 0.6, -0.09227, -0.04603 + 0.0, 0.43, 0.65, -0.09068, -0.04507 + 0.0, 0.43, 0.7, -0.08891, -0.04409 + 0.0, 0.43, 0.75, -0.08696, -0.0431 + 0.0, 0.43, 0.8, -0.08483, -0.0421 + 0.0, 0.43, 0.85, -0.08254, -0.04108 + 0.0, 0.43, 0.9, -0.08009, -0.04005 + 0.0, 0.43, 0.95, -0.07749, -0.039 + 0.0, 0.43, 1.0, -0.07474, -0.03795 + 0.0, 0.43, 1.05, -0.07185, -0.03688 + 0.0, 0.43, 1.1, -0.06883, -0.0358 + 0.0, 0.43, 1.15, -0.06568, -0.03472 + 0.0, 0.43, 1.2, -0.0624, -0.03362 + 0.0, 0.43, 1.25, -0.05901, -0.03252 + 0.0, 0.43, 1.3, -0.05552, -0.03141 + 0.0, 0.43, 1.35, -0.05192, -0.0303 + 0.0, 0.43, 1.4, -0.04822, -0.02917 + 0.0, 0.43, 1.45, -0.04443, -0.02805 + 0.0, 0.43, 1.5, -0.04056, -0.02692 + 0.0, 0.43, 1.55, -0.03661, -0.02578 + 0.0, 0.43, 1.6, -0.0326, -0.02464 + 0.0, 0.43, 1.65, -0.02851, -0.0235 + 0.0, 0.43, 1.7, -0.02437, -0.02236 + 0.0, 0.43, 1.75, -0.02018, -0.02122 + 0.0, 0.43, 1.8, -0.01594, -0.02008 + 0.0, 0.43, 1.85, -0.01166, -0.01893 + 0.0, 0.43, 1.9, -0.007352, -0.01779 + 0.0, 0.43, 1.95, -0.003014, -0.01666 + 0.0, 0.43, 2.0, 0.001344, -0.01552 + 0.0, 0.43, 2.05, 0.005716, -0.01439 + 0.0, 0.43, 2.1, 0.0101, -0.01326 + 0.0, 0.43, 2.15, 0.01448, -0.01214 + 0.0, 0.43, 2.2, 0.01885, -0.01102 + 0.0, 0.43, 2.25, 0.02322, -0.009908 + 0.0, 0.43, 2.3, 0.02756, -0.008804 + 0.0, 0.43, 2.35, 0.03189, -0.007707 + 0.0, 0.43, 2.4, 0.03618, -0.00662 + 0.0, 0.43, 2.45, 0.04044, -0.005541 + 0.0, 0.43, 2.5, 0.04465, -0.004473 + 0.0, 0.43, 2.55, 0.04881, -0.003415 + 0.0, 0.43, 2.6, 0.05292, -0.002368 + 0.0, 0.43, 2.65, 0.05697, -0.001334 + 0.0, 0.43, 2.7, 0.06095, -0.0003121 + 0.0, 0.43, 2.75, 0.06485, 0.0006961 + 0.0, 0.43, 2.8, 0.06867, 0.00169 + 0.0, 0.43, 2.85, 0.07241, 0.002669 + 0.0, 0.43, 2.9, 0.07605, 0.003632 + 0.0, 0.43, 2.95, 0.07959, 0.004579 + 0.0, 0.43, 3.0, 0.08303, 0.005509 + 0.0, 0.43, 3.05, 0.08635, 0.006422 + 0.0, 0.43, 3.1, 0.08956, 0.007315 + 0.0, 0.43, 3.15, 0.09264, 0.00819 + 0.0, 0.43, 3.2, 0.09558, 0.009044 + 0.0, 0.43, 3.25, 0.09839, 0.009878 + 0.0, 0.43, 3.3, 0.1011, 0.01069 + 0.0, 0.43, 3.35, 0.1036, 0.01148 + 0.0, 0.43, 3.4, 0.1059, 0.01225 + 0.0, 0.43, 3.45, 0.1081, 0.01299 + 0.0, 0.43, 3.5, 0.1102, 0.01371 + 0.0, 0.43, 3.55, 0.112, 0.01441 + 0.0, 0.43, 3.6, 0.1137, 0.01508 + 0.0, 0.43, 3.65, 0.1152, 0.01572 + 0.0, 0.43, 3.7, 0.1164, 0.01634 + 0.0, 0.43, 3.75, 0.1175, 0.01692 + 0.0, 0.43, 3.8, 0.1184, 0.01748 + 0.0, 0.43, 3.85, 0.1191, 0.01801 + 0.0, 0.43, 3.9, 0.1195, 0.01851 + 0.0, 0.43, 3.95, 0.1197, 0.01898 + 0.0, 0.43, 4.0, 0.1197, 0.01942 + 0.0, 0.43, 4.05, 0.1177, 0.01973 + 0.0, 0.43, 4.1, 0.1155, 0.02002 + 0.0, 0.43, 4.15, 0.1132, 0.02028 + 0.0, 0.43, 4.2, 0.1108, 0.02051 + 0.0, 0.43, 4.25, 0.1082, 0.02071 + 0.0, 0.43, 4.3, 0.1056, 0.02088 + 0.0, 0.43, 4.35, 0.1028, 0.02103 + 0.0, 0.43, 4.4, 0.09993, 0.02116 + 0.0, 0.43, 4.45, 0.09698, 0.02125 + 0.0, 0.43, 4.5, 0.09395, 0.02132 + 0.0, 0.43, 4.55, 0.09084, 0.02136 + 0.0, 0.43, 4.6, 0.08767, 0.02137 + 0.0, 0.43, 4.65, 0.08444, 0.02136 + 0.0, 0.43, 4.7, 0.08115, 0.02131 + 0.0, 0.43, 4.75, 0.07782, 0.02125 + 0.0, 0.43, 4.8, 0.07446, 0.02115 + 0.0, 0.43, 4.85, 0.07106, 0.02103 + 0.0, 0.43, 4.9, 0.06764, 0.02088 + 0.0, 0.43, 4.95, 0.0642, 0.0207 + 0.0, 0.43, 5.0, 0.06076, 0.0205 + 0.0, 0.43, 5.05, 0.05704, 0.02029 + 0.0, 0.43, 5.1, 0.05334, 0.02006 + 0.0, 0.43, 5.15, 0.04966, 0.0198 + 0.0, 0.43, 5.2, 0.04601, 0.01951 + 0.0, 0.43, 5.25, 0.04241, 0.01919 + 0.0, 0.43, 5.3, 0.03886, 0.01884 + 0.0, 0.43, 5.35, 0.03538, 0.01847 + 0.0, 0.43, 5.4, 0.03198, 0.01806 + 0.0, 0.43, 5.45, 0.02867, 0.01762 + 0.0, 0.43, 5.5, 0.02546, 0.01716 + 0.0, 0.43, 5.55, 0.02236, 0.01666 + 0.0, 0.43, 5.6, 0.01939, 0.01613 + 0.0, 0.43, 5.65, 0.01656, 0.01557 + 0.0, 0.43, 5.7, 0.01387, 0.01498 + 0.0, 0.43, 5.75, 0.01134, 0.01436 + 0.0, 0.43, 5.8, 0.008978, 0.01371 + 0.0, 0.43, 5.85, 0.006799, 0.01302 + 0.0, 0.43, 5.9, 0.004813, 0.0123 + 0.0, 0.43, 5.95, 0.003031, 0.01154 + 0.0, 0.43, 6.0, 0.001464, 0.01075 + 0.0, 0.43, 6.05, 0.002861, 0.009779 + 0.0, 0.43, 6.1, 0.00461, 0.008765 + 0.0, 0.43, 6.15, 0.006702, 0.007711 + 0.0, 0.43, 6.2, 0.009129, 0.006618 + 0.0, 0.43, 6.25, 0.01188, 0.005486 + 0.0, 0.43, 6.3, 0.01495, 0.004316 + 0.0, 0.43, 6.35, 0.01833, 0.003108 + 0.0, 0.43, 6.4, 0.02201, 0.001865 + 0.0, 0.43, 6.45, 0.02598, 0.0005854 + 0.0, 0.43, 6.5, 0.03023, -0.000729 + 0.0, 0.43, 6.55, 0.03476, -0.002078 + 0.0, 0.43, 6.6, 0.03955, -0.00346 + 0.0, 0.43, 6.65, 0.0446, -0.004875 + 0.0, 0.43, 6.7, 0.04989, -0.006322 + 0.0, 0.43, 6.75, 0.05543, -0.0078 + 0.0, 0.43, 6.8, 0.06119, -0.009309 + 0.0, 0.43, 6.85, 0.06718, -0.01085 + 0.0, 0.43, 6.9, 0.07338, -0.01242 + 0.0, 0.43, 6.95, 0.07979, -0.01401 + 0.0, 0.43, 7.0, 0.08639, -0.01564 + 0.0, 0.43, 7.05, 0.09318, -0.01729 + 0.0, 0.43, 7.1, 0.1001, -0.01896 + 0.0, 0.43, 7.15, 0.1073, -0.02067 + 0.0, 0.43, 7.2, 0.1146, -0.02239 + 0.0, 0.43, 7.25, 0.122, -0.02414 + 0.0, 0.43, 7.3, 0.1296, -0.02592 + 0.0, 0.43, 7.35, 0.1374, -0.02772 + 0.0, 0.43, 7.4, 0.1452, -0.02953 + 0.0, 0.43, 7.45, 0.1532, -0.03137 + 0.0, 0.43, 7.5, 0.1613, -0.03323 + 0.0, 0.43, 7.55, 0.1695, -0.03511 + 0.0, 0.43, 7.6, 0.1778, -0.03701 + 0.0, 0.43, 7.65, 0.1861, -0.03893 + 0.0, 0.43, 7.7, 0.1946, -0.04086 + 0.0, 0.43, 7.75, 0.2031, -0.04281 + 0.0, 0.43, 7.8, 0.2116, -0.04478 + 0.0, 0.43, 7.85, 0.2202, -0.04676 + 0.0, 0.43, 7.9, 0.2289, -0.04876 + 0.0, 0.43, 7.95, 0.2376, -0.05077 + 0.0, 0.43, 8.0, 0.2463, -0.05279 + 0.0, 0.43, 8.05, 0.2528, -0.05466 + 0.0, 0.43, 8.1, 0.2593, -0.05654 + 0.0, 0.43, 8.15, 0.2658, -0.05843 + 0.0, 0.43, 8.2, 0.2724, -0.06033 + 0.0, 0.43, 8.25, 0.2789, -0.06225 + 0.0, 0.43, 8.3, 0.2855, -0.06418 + 0.0, 0.43, 8.35, 0.2921, -0.06612 + 0.0, 0.43, 8.4, 0.2987, -0.06807 + 0.0, 0.43, 8.45, 0.3053, -0.07003 + 0.0, 0.43, 8.5, 0.3119, -0.072 + 0.0, 0.43, 8.55, 0.3185, -0.07399 + 0.0, 0.43, 8.6, 0.3252, -0.07598 + 0.0, 0.43, 8.65, 0.3318, -0.07799 + 0.0, 0.43, 8.7, 0.3385, -0.08 + 0.0, 0.43, 8.75, 0.3452, -0.08203 + 0.0, 0.43, 8.8, 0.3518, -0.08407 + 0.0, 0.43, 8.85, 0.3585, -0.08612 + 0.0, 0.43, 8.9, 0.3652, -0.08818 + 0.0, 0.43, 8.95, 0.3719, -0.09025 + 0.0, 0.43, 9.0, 0.3786, -0.09233 + 0.0, 0.43, 9.05, 0.3853, -0.09442 + 0.0, 0.43, 9.1, 0.3921, -0.09652 + 0.0, 0.43, 9.15, 0.3988, -0.09863 + 0.0, 0.43, 9.2, 0.4055, -0.1007 + 0.0, 0.43, 9.25, 0.4123, -0.1029 + 0.0, 0.43, 9.3, 0.419, -0.105 + 0.0, 0.43, 9.35, 0.4257, -0.1072 + 0.0, 0.43, 9.4, 0.4325, -0.1093 + 0.0, 0.43, 9.45, 0.4393, -0.1115 + 0.0, 0.43, 9.5, 0.446, -0.1137 + 0.0, 0.43, 9.55, 0.4528, -0.1158 + 0.0, 0.43, 9.6, 0.4595, -0.118 + 0.0, 0.43, 9.65, 0.4663, -0.1202 + 0.0, 0.43, 9.7, 0.4731, -0.1225 + 0.0, 0.43, 9.75, 0.4799, -0.1247 + 0.0, 0.43, 9.8, 0.4866, -0.1269 + 0.0, 0.43, 9.85, 0.4934, -0.1291 + 0.0, 0.43, 9.9, 0.5002, -0.1314 + 0.0, 0.43, 9.95, 0.507, -0.1336 + 0.0, 0.43, 10.0, 0.5137, -0.1359 + 0.0, 0.43, 10.05, 0.5205, -0.1383 + 0.0, 0.43, 10.1, 0.5272, -0.1407 + 0.0, 0.43, 10.15, 0.5339, -0.1431 + 0.0, 0.43, 10.2, 0.5406, -0.1455 + 0.0, 0.43, 10.25, 0.5473, -0.148 + 0.0, 0.43, 10.3, 0.5541, -0.1504 + 0.0, 0.43, 10.35, 0.5608, -0.1528 + 0.0, 0.43, 10.4, 0.5675, -0.1553 + 0.0, 0.43, 10.45, 0.5742, -0.1577 + 0.0, 0.43, 10.5, 0.5809, -0.1601 + 0.0, 0.43, 10.55, 0.5876, -0.1626 + 0.0, 0.43, 10.6, 0.5943, -0.165 + 0.0, 0.43, 10.65, 0.601, -0.1675 + 0.0, 0.43, 10.7, 0.6077, -0.1699 + 0.0, 0.43, 10.75, 0.6144, -0.1724 + 0.0, 0.43, 10.8, 0.6211, -0.1748 + 0.0, 0.43, 10.85, 0.6278, -0.1773 + 0.0, 0.43, 10.9, 0.6345, -0.1797 + 0.0, 0.43, 10.95, 0.6412, -0.1822 + 0.0, 0.43, 11.0, 0.6479, -0.1846 + 0.0, 0.43, 11.05, 0.6546, -0.187 + 0.0, 0.43, 11.1, 0.6612, -0.1895 + 0.0, 0.43, 11.15, 0.6679, -0.1919 + 0.0, 0.43, 11.2, 0.6746, -0.1943 + 0.0, 0.43, 11.25, 0.6812, -0.1967 + 0.0, 0.43, 11.3, 0.6879, -0.1991 + 0.0, 0.43, 11.35, 0.6946, -0.2015 + 0.0, 0.43, 11.4, 0.7012, -0.2039 + 0.0, 0.43, 11.45, 0.7079, -0.2063 + 0.0, 0.43, 11.5, 0.7145, -0.2087 + 0.0, 0.43, 11.55, 0.7211, -0.211 + 0.0, 0.43, 11.6, 0.7278, -0.2134 + 0.0, 0.43, 11.65, 0.7344, -0.2157 + 0.0, 0.43, 11.7, 0.741, -0.218 + 0.0, 0.43, 11.75, 0.7476, -0.2203 + 0.0, 0.43, 11.8, 0.7542, -0.2226 + 0.0, 0.43, 11.85, 0.7608, -0.2249 + 0.0, 0.43, 11.9, 0.7674, -0.2272 + 0.0, 0.43, 11.95, 0.774, -0.2295 + 0.0, 0.43, 12.0, 0.7806, -0.2317 + 0.0, 0.43, 12.05, 0.7872, -0.2339 + 0.0, 0.43, 12.1, 0.7938, -0.2362 + 0.0, 0.43, 12.15, 0.8003, -0.2384 + 0.0, 0.43, 12.2, 0.8069, -0.2405 + 0.0, 0.43, 12.25, 0.8134, -0.2427 + 0.0, 0.43, 12.3, 0.82, -0.2448 + 0.0, 0.43, 12.35, 0.8265, -0.247 + 0.0, 0.43, 12.4, 0.8331, -0.2491 + 0.0, 0.43, 12.45, 0.8396, -0.2511 + 0.0, 0.43, 12.5, 0.8461, -0.2532 + 0.0, 0.43, 12.55, 0.8526, -0.2552 + 0.0, 0.43, 12.6, 0.8591, -0.2573 + 0.0, 0.43, 12.65, 0.8656, -0.2592 + 0.0, 0.43, 12.7, 0.872, -0.2612 + 0.0, 0.43, 12.75, 0.8785, -0.2632 + 0.0, 0.43, 12.8, 0.885, -0.2651 + 0.0, 0.43, 12.85, 0.8914, -0.267 + 0.0, 0.43, 12.9, 0.8979, -0.2688 + 0.0, 0.43, 12.95, 0.9043, -0.2707 + 0.0, 0.43, 13.0, 0.9107, -0.2725 + 0.0, 0.43, 13.05, 0.9171, -0.2743 + 0.0, 0.43, 13.1, 0.9235, -0.276 + 0.0, 0.43, 13.15, 0.9299, -0.2778 + 0.0, 0.43, 13.2, 0.9363, -0.2795 + 0.0, 0.43, 13.25, 0.9427, -0.2811 + 0.0, 0.43, 13.3, 0.9491, -0.2828 + 0.0, 0.43, 13.35, 0.9554, -0.2844 + 0.0, 0.43, 13.4, 0.9618, -0.286 + 0.0, 0.43, 13.45, 0.9681, -0.2875 + 0.0, 0.43, 13.5, 0.9744, -0.289 + 0.0, 0.43, 13.55, 0.9807, -0.2905 + 0.0, 0.43, 13.6, 0.987, -0.2919 + 0.0, 0.43, 13.65, 0.9933, -0.2934 + 0.0, 0.43, 13.7, 0.9996, -0.2947 + 0.0, 0.43, 13.75, 1.006, -0.2961 + 0.0, 0.43, 13.8, 1.012, -0.2974 + 0.0, 0.43, 13.85, 1.018, -0.2986 + 0.0, 0.43, 13.9, 1.025, -0.2998 + 0.0, 0.43, 13.95, 1.031, -0.301 + 0.0, 0.43, 14.0, 1.037, -0.3022 + 0.0, 0.43, 14.05, 1.043, -0.3033 + 0.0, 0.43, 14.1, 1.049, -0.3044 + 0.0, 0.43, 14.15, 1.055, -0.3054 + 0.0, 0.43, 14.2, 1.062, -0.3064 + 0.0, 0.43, 14.25, 1.068, -0.3073 + 0.0, 0.43, 14.3, 1.074, -0.3082 + 0.0, 0.43, 14.35, 1.08, -0.3091 + 0.0, 0.43, 14.4, 1.086, -0.3099 + 0.0, 0.43, 14.45, 1.092, -0.3107 + 0.0, 0.43, 14.5, 1.098, -0.3114 + 0.0, 0.43, 14.55, 1.104, -0.3121 + 0.0, 0.43, 14.6, 1.11, -0.3127 + 0.0, 0.43, 14.65, 1.116, -0.3133 + 0.0, 0.43, 14.7, 1.122, -0.3138 + 0.0, 0.43, 14.75, 1.128, -0.3143 + 0.0, 0.43, 14.8, 1.134, -0.3147 + 0.0, 0.43, 14.85, 1.14, -0.3151 + 0.0, 0.43, 14.9, 1.146, -0.3155 + 0.0, 0.43, 14.95, 1.152, -0.3158 + 0.0, 0.43, 15.0, 1.158, -0.316 + 0.0, 0.43, 15.05, 1.164, -0.3162 + 0.0, 0.48, 0.0, -0.09756, -0.04885 + 0.0, 0.48, 0.05, -0.09825, -0.04823 + 0.0, 0.48, 0.1, -0.09871, -0.04759 + 0.0, 0.48, 0.15, -0.09895, -0.04692 + 0.0, 0.48, 0.2, -0.09897, -0.04624 + 0.0, 0.48, 0.25, -0.09877, -0.04553 + 0.0, 0.48, 0.3, -0.09837, -0.04481 + 0.0, 0.48, 0.35, -0.09776, -0.04407 + 0.0, 0.48, 0.4, -0.09696, -0.04331 + 0.0, 0.48, 0.45, -0.09597, -0.04253 + 0.0, 0.48, 0.5, -0.09479, -0.04174 + 0.0, 0.48, 0.55, -0.09343, -0.04093 + 0.0, 0.48, 0.6, -0.0919, -0.04011 + 0.0, 0.48, 0.65, -0.0902, -0.03927 + 0.0, 0.48, 0.7, -0.08833, -0.03842 + 0.0, 0.48, 0.75, -0.08631, -0.03756 + 0.0, 0.48, 0.8, -0.08414, -0.03668 + 0.0, 0.48, 0.85, -0.08182, -0.03579 + 0.0, 0.48, 0.9, -0.07936, -0.03489 + 0.0, 0.48, 0.95, -0.07676, -0.03397 + 0.0, 0.48, 1.0, -0.07403, -0.03305 + 0.0, 0.48, 1.05, -0.07119, -0.03212 + 0.0, 0.48, 1.1, -0.06822, -0.03118 + 0.0, 0.48, 1.15, -0.06514, -0.03023 + 0.0, 0.48, 1.2, -0.06195, -0.02927 + 0.0, 0.48, 1.25, -0.05866, -0.02831 + 0.0, 0.48, 1.3, -0.05527, -0.02734 + 0.0, 0.48, 1.35, -0.0518, -0.02636 + 0.0, 0.48, 1.4, -0.04824, -0.02538 + 0.0, 0.48, 1.45, -0.0446, -0.02439 + 0.0, 0.48, 1.5, -0.04088, -0.0234 + 0.0, 0.48, 1.55, -0.0371, -0.02241 + 0.0, 0.48, 1.6, -0.03326, -0.02141 + 0.0, 0.48, 1.65, -0.02936, -0.02042 + 0.0, 0.48, 1.7, -0.0254, -0.01942 + 0.0, 0.48, 1.75, -0.0214, -0.01842 + 0.0, 0.48, 1.8, -0.01737, -0.01742 + 0.0, 0.48, 1.85, -0.01329, -0.01642 + 0.0, 0.48, 1.9, -0.009192, -0.01542 + 0.0, 0.48, 1.95, -0.005066, -0.01442 + 0.0, 0.48, 2.0, -0.000923, -0.01342 + 0.0, 0.48, 2.05, 0.003232, -0.01243 + 0.0, 0.48, 2.1, 0.007394, -0.01144 + 0.0, 0.48, 2.15, 0.01156, -0.01046 + 0.0, 0.48, 2.2, 0.01572, -0.009477 + 0.0, 0.48, 2.25, 0.01986, -0.008502 + 0.0, 0.48, 2.3, 0.024, -0.007533 + 0.0, 0.48, 2.35, 0.02811, -0.006571 + 0.0, 0.48, 2.4, 0.03219, -0.005617 + 0.0, 0.48, 2.45, 0.03624, -0.00467 + 0.0, 0.48, 2.5, 0.04026, -0.003731 + 0.0, 0.48, 2.55, 0.04423, -0.002802 + 0.0, 0.48, 2.6, 0.04815, -0.001883 + 0.0, 0.48, 2.65, 0.05201, -0.0009735 + 0.0, 0.48, 2.7, 0.05582, -7.542e-05 + 0.0, 0.48, 2.75, 0.05956, 0.0008111 + 0.0, 0.48, 2.8, 0.06323, 0.001685 + 0.0, 0.48, 2.85, 0.06682, 0.002547 + 0.0, 0.48, 2.9, 0.07033, 0.003395 + 0.0, 0.48, 2.95, 0.07374, 0.004228 + 0.0, 0.48, 3.0, 0.07707, 0.005047 + 0.0, 0.48, 3.05, 0.0803, 0.005851 + 0.0, 0.48, 3.1, 0.08342, 0.006639 + 0.0, 0.48, 3.15, 0.08643, 0.00741 + 0.0, 0.48, 3.2, 0.08932, 0.008163 + 0.0, 0.48, 3.25, 0.09209, 0.008899 + 0.0, 0.48, 3.3, 0.09474, 0.009617 + 0.0, 0.48, 3.35, 0.09725, 0.01032 + 0.0, 0.48, 3.4, 0.09962, 0.01099 + 0.0, 0.48, 3.45, 0.1018, 0.01165 + 0.0, 0.48, 3.5, 0.1039, 0.01229 + 0.0, 0.48, 3.55, 0.1058, 0.01291 + 0.0, 0.48, 3.6, 0.1076, 0.0135 + 0.0, 0.48, 3.65, 0.1092, 0.01407 + 0.0, 0.48, 3.7, 0.1106, 0.01462 + 0.0, 0.48, 3.75, 0.1119, 0.01514 + 0.0, 0.48, 3.8, 0.1129, 0.01564 + 0.0, 0.48, 3.85, 0.1138, 0.01611 + 0.0, 0.48, 3.9, 0.1145, 0.01656 + 0.0, 0.48, 3.95, 0.115, 0.01698 + 0.0, 0.48, 4.0, 0.1152, 0.01737 + 0.0, 0.48, 4.05, 0.1137, 0.01765 + 0.0, 0.48, 4.1, 0.1121, 0.01791 + 0.0, 0.48, 4.15, 0.1103, 0.01814 + 0.0, 0.48, 4.2, 0.1085, 0.01835 + 0.0, 0.48, 4.25, 0.1065, 0.01854 + 0.0, 0.48, 4.3, 0.1044, 0.0187 + 0.0, 0.48, 4.35, 0.1023, 0.01884 + 0.0, 0.48, 4.4, 0.1, 0.01896 + 0.0, 0.48, 4.45, 0.09773, 0.01905 + 0.0, 0.48, 4.5, 0.09533, 0.01912 + 0.0, 0.48, 4.55, 0.09288, 0.01917 + 0.0, 0.48, 4.6, 0.09036, 0.0192 + 0.0, 0.48, 4.65, 0.08779, 0.0192 + 0.0, 0.48, 4.7, 0.08517, 0.01918 + 0.0, 0.48, 4.75, 0.08251, 0.01913 + 0.0, 0.48, 4.8, 0.07983, 0.01906 + 0.0, 0.48, 4.85, 0.07711, 0.01897 + 0.0, 0.48, 4.9, 0.07437, 0.01886 + 0.0, 0.48, 4.95, 0.07162, 0.01872 + 0.0, 0.48, 5.0, 0.06887, 0.01856 + 0.0, 0.48, 5.05, 0.0659, 0.01841 + 0.0, 0.48, 5.1, 0.06293, 0.01823 + 0.0, 0.48, 5.15, 0.05999, 0.01803 + 0.0, 0.48, 5.2, 0.05707, 0.01781 + 0.0, 0.48, 5.25, 0.05419, 0.01756 + 0.0, 0.48, 5.3, 0.05137, 0.01728 + 0.0, 0.48, 5.35, 0.04859, 0.01699 + 0.0, 0.48, 5.4, 0.04589, 0.01666 + 0.0, 0.48, 5.45, 0.04326, 0.01631 + 0.0, 0.48, 5.5, 0.04073, 0.01593 + 0.0, 0.48, 5.55, 0.03828, 0.01553 + 0.0, 0.48, 5.6, 0.03595, 0.0151 + 0.0, 0.48, 5.65, 0.03373, 0.01464 + 0.0, 0.48, 5.7, 0.03163, 0.01416 + 0.0, 0.48, 5.75, 0.02968, 0.01364 + 0.0, 0.48, 5.8, 0.02786, 0.0131 + 0.0, 0.48, 5.85, 0.02621, 0.01253 + 0.0, 0.48, 5.9, 0.02472, 0.01193 + 0.0, 0.48, 5.95, 0.0234, 0.0113 + 0.0, 0.48, 6.0, 0.02227, 0.01064 + 0.0, 0.48, 6.05, 0.02366, 0.009807 + 0.0, 0.48, 6.1, 0.02536, 0.008936 + 0.0, 0.48, 6.15, 0.02735, 0.008029 + 0.0, 0.48, 6.2, 0.02963, 0.007086 + 0.0, 0.48, 6.25, 0.03219, 0.006109 + 0.0, 0.48, 6.3, 0.03502, 0.005097 + 0.0, 0.48, 6.35, 0.03811, 0.004052 + 0.0, 0.48, 6.4, 0.04146, 0.002974 + 0.0, 0.48, 6.45, 0.04506, 0.001864 + 0.0, 0.48, 6.5, 0.0489, 0.0007226 + 0.0, 0.48, 6.55, 0.05298, -0.0004497 + 0.0, 0.48, 6.6, 0.05728, -0.001652 + 0.0, 0.48, 6.65, 0.0618, -0.002884 + 0.0, 0.48, 6.7, 0.06654, -0.004145 + 0.0, 0.48, 6.75, 0.07148, -0.005434 + 0.0, 0.48, 6.8, 0.07662, -0.00675 + 0.0, 0.48, 6.85, 0.08195, -0.008093 + 0.0, 0.48, 6.9, 0.08746, -0.009463 + 0.0, 0.48, 6.95, 0.09315, -0.01086 + 0.0, 0.48, 7.0, 0.099, -0.01228 + 0.0, 0.48, 7.05, 0.105, -0.01372 + 0.0, 0.48, 7.1, 0.1112, -0.01519 + 0.0, 0.48, 7.15, 0.1175, -0.01668 + 0.0, 0.48, 7.2, 0.124, -0.01819 + 0.0, 0.48, 7.25, 0.1305, -0.01972 + 0.0, 0.48, 7.3, 0.1373, -0.02128 + 0.0, 0.48, 7.35, 0.1441, -0.02285 + 0.0, 0.48, 7.4, 0.151, -0.02445 + 0.0, 0.48, 7.45, 0.1581, -0.02606 + 0.0, 0.48, 7.5, 0.1652, -0.02769 + 0.0, 0.48, 7.55, 0.1724, -0.02934 + 0.0, 0.48, 7.6, 0.1797, -0.031 + 0.0, 0.48, 7.65, 0.1871, -0.03269 + 0.0, 0.48, 7.7, 0.1945, -0.03438 + 0.0, 0.48, 7.75, 0.202, -0.0361 + 0.0, 0.48, 7.8, 0.2096, -0.03782 + 0.0, 0.48, 7.85, 0.2171, -0.03956 + 0.0, 0.48, 7.9, 0.2248, -0.04131 + 0.0, 0.48, 7.95, 0.2324, -0.04308 + 0.0, 0.48, 8.0, 0.2401, -0.04485 + 0.0, 0.48, 8.05, 0.2459, -0.04648 + 0.0, 0.48, 8.1, 0.2517, -0.04813 + 0.0, 0.48, 8.15, 0.2575, -0.04978 + 0.0, 0.48, 8.2, 0.2634, -0.05145 + 0.0, 0.48, 8.25, 0.2693, -0.05312 + 0.0, 0.48, 8.3, 0.2751, -0.0548 + 0.0, 0.48, 8.35, 0.281, -0.0565 + 0.0, 0.48, 8.4, 0.2869, -0.05821 + 0.0, 0.48, 8.45, 0.2928, -0.05992 + 0.0, 0.48, 8.5, 0.2987, -0.06165 + 0.0, 0.48, 8.55, 0.3046, -0.06338 + 0.0, 0.48, 8.6, 0.3106, -0.06513 + 0.0, 0.48, 8.65, 0.3165, -0.06688 + 0.0, 0.48, 8.7, 0.3225, -0.06865 + 0.0, 0.48, 8.75, 0.3284, -0.07042 + 0.0, 0.48, 8.8, 0.3344, -0.0722 + 0.0, 0.48, 8.85, 0.3404, -0.074 + 0.0, 0.48, 8.9, 0.3464, -0.0758 + 0.0, 0.48, 8.95, 0.3524, -0.07761 + 0.0, 0.48, 9.0, 0.3584, -0.07943 + 0.0, 0.48, 9.05, 0.3644, -0.08126 + 0.0, 0.48, 9.1, 0.3704, -0.0831 + 0.0, 0.48, 9.15, 0.3764, -0.08495 + 0.0, 0.48, 9.2, 0.3824, -0.0868 + 0.0, 0.48, 9.25, 0.3885, -0.08867 + 0.0, 0.48, 9.3, 0.3945, -0.09054 + 0.0, 0.48, 9.35, 0.4005, -0.09243 + 0.0, 0.48, 9.4, 0.4066, -0.09432 + 0.0, 0.48, 9.45, 0.4126, -0.09621 + 0.0, 0.48, 9.5, 0.4187, -0.09812 + 0.0, 0.48, 9.55, 0.4247, -0.1 + 0.0, 0.48, 9.6, 0.4308, -0.102 + 0.0, 0.48, 9.65, 0.4369, -0.1039 + 0.0, 0.48, 9.7, 0.4429, -0.1058 + 0.0, 0.48, 9.75, 0.449, -0.1078 + 0.0, 0.48, 9.8, 0.4551, -0.1097 + 0.0, 0.48, 9.85, 0.4611, -0.1117 + 0.0, 0.48, 9.9, 0.4672, -0.1137 + 0.0, 0.48, 9.95, 0.4733, -0.1156 + 0.0, 0.48, 10.0, 0.4794, -0.1176 + 0.0, 0.48, 10.05, 0.4854, -0.1197 + 0.0, 0.48, 10.1, 0.4914, -0.1219 + 0.0, 0.48, 10.15, 0.4974, -0.124 + 0.0, 0.48, 10.2, 0.5035, -0.1261 + 0.0, 0.48, 10.25, 0.5095, -0.1282 + 0.0, 0.48, 10.3, 0.5155, -0.1304 + 0.0, 0.48, 10.35, 0.5215, -0.1325 + 0.0, 0.48, 10.4, 0.5275, -0.1347 + 0.0, 0.48, 10.45, 0.5336, -0.1368 + 0.0, 0.48, 10.5, 0.5396, -0.139 + 0.0, 0.48, 10.55, 0.5456, -0.1411 + 0.0, 0.48, 10.6, 0.5516, -0.1433 + 0.0, 0.48, 10.65, 0.5576, -0.1454 + 0.0, 0.48, 10.7, 0.5637, -0.1476 + 0.0, 0.48, 10.75, 0.5697, -0.1498 + 0.0, 0.48, 10.8, 0.5757, -0.1519 + 0.0, 0.48, 10.85, 0.5817, -0.1541 + 0.0, 0.48, 10.9, 0.5877, -0.1562 + 0.0, 0.48, 10.95, 0.5937, -0.1584 + 0.0, 0.48, 11.0, 0.5997, -0.1605 + 0.0, 0.48, 11.05, 0.6057, -0.1627 + 0.0, 0.48, 11.1, 0.6117, -0.1648 + 0.0, 0.48, 11.15, 0.6177, -0.1669 + 0.0, 0.48, 11.2, 0.6237, -0.1691 + 0.0, 0.48, 11.25, 0.6297, -0.1712 + 0.0, 0.48, 11.3, 0.6357, -0.1733 + 0.0, 0.48, 11.35, 0.6417, -0.1754 + 0.0, 0.48, 11.4, 0.6477, -0.1775 + 0.0, 0.48, 11.45, 0.6536, -0.1796 + 0.0, 0.48, 11.5, 0.6596, -0.1817 + 0.0, 0.48, 11.55, 0.6656, -0.1838 + 0.0, 0.48, 11.6, 0.6716, -0.1859 + 0.0, 0.48, 11.65, 0.6775, -0.1879 + 0.0, 0.48, 11.7, 0.6835, -0.19 + 0.0, 0.48, 11.75, 0.6895, -0.192 + 0.0, 0.48, 11.8, 0.6954, -0.194 + 0.0, 0.48, 11.85, 0.7014, -0.1961 + 0.0, 0.48, 11.9, 0.7073, -0.1981 + 0.0, 0.48, 11.95, 0.7133, -0.2001 + 0.0, 0.48, 12.0, 0.7192, -0.202 + 0.0, 0.48, 12.05, 0.7251, -0.204 + 0.0, 0.48, 12.1, 0.7311, -0.206 + 0.0, 0.48, 12.15, 0.737, -0.2079 + 0.0, 0.48, 12.2, 0.7429, -0.2098 + 0.0, 0.48, 12.25, 0.7488, -0.2117 + 0.0, 0.48, 12.3, 0.7547, -0.2136 + 0.0, 0.48, 12.35, 0.7606, -0.2155 + 0.0, 0.48, 12.4, 0.7665, -0.2173 + 0.0, 0.48, 12.45, 0.7724, -0.2191 + 0.0, 0.48, 12.5, 0.7783, -0.221 + 0.0, 0.48, 12.55, 0.7842, -0.2228 + 0.0, 0.48, 12.6, 0.7901, -0.2245 + 0.0, 0.48, 12.65, 0.796, -0.2263 + 0.0, 0.48, 12.7, 0.8018, -0.228 + 0.0, 0.48, 12.75, 0.8077, -0.2297 + 0.0, 0.48, 12.8, 0.8135, -0.2314 + 0.0, 0.48, 12.85, 0.8194, -0.2331 + 0.0, 0.48, 12.9, 0.8252, -0.2347 + 0.0, 0.48, 12.95, 0.831, -0.2363 + 0.0, 0.48, 13.0, 0.8369, -0.2379 + 0.0, 0.48, 13.05, 0.8427, -0.2395 + 0.0, 0.48, 13.1, 0.8485, -0.2411 + 0.0, 0.48, 13.15, 0.8543, -0.2426 + 0.0, 0.48, 13.2, 0.8601, -0.2441 + 0.0, 0.48, 13.25, 0.8659, -0.2455 + 0.0, 0.48, 13.3, 0.8717, -0.247 + 0.0, 0.48, 13.35, 0.8774, -0.2484 + 0.0, 0.48, 13.4, 0.8832, -0.2498 + 0.0, 0.48, 13.45, 0.8889, -0.2511 + 0.0, 0.48, 13.5, 0.8947, -0.2525 + 0.0, 0.48, 13.55, 0.9004, -0.2537 + 0.0, 0.48, 13.6, 0.9062, -0.255 + 0.0, 0.48, 13.65, 0.9119, -0.2562 + 0.0, 0.48, 13.7, 0.9176, -0.2574 + 0.0, 0.48, 13.75, 0.9233, -0.2586 + 0.0, 0.48, 13.8, 0.929, -0.2597 + 0.0, 0.48, 13.85, 0.9347, -0.2609 + 0.0, 0.48, 13.9, 0.9404, -0.2619 + 0.0, 0.48, 13.95, 0.946, -0.263 + 0.0, 0.48, 14.0, 0.9517, -0.264 + 0.0, 0.48, 14.05, 0.9574, -0.2649 + 0.0, 0.48, 14.1, 0.963, -0.2658 + 0.0, 0.48, 14.15, 0.9686, -0.2667 + 0.0, 0.48, 14.2, 0.9743, -0.2676 + 0.0, 0.48, 14.25, 0.9799, -0.2684 + 0.0, 0.48, 14.3, 0.9855, -0.2692 + 0.0, 0.48, 14.35, 0.9911, -0.2699 + 0.0, 0.48, 14.4, 0.9966, -0.2706 + 0.0, 0.48, 14.45, 1.002, -0.2713 + 0.0, 0.48, 14.5, 1.008, -0.2719 + 0.0, 0.48, 14.55, 1.013, -0.2725 + 0.0, 0.48, 14.6, 1.019, -0.273 + 0.0, 0.48, 14.65, 1.024, -0.2735 + 0.0, 0.48, 14.7, 1.03, -0.274 + 0.0, 0.48, 14.75, 1.035, -0.2744 + 0.0, 0.48, 14.8, 1.041, -0.2748 + 0.0, 0.48, 14.85, 1.046, -0.2751 + 0.0, 0.48, 14.9, 1.052, -0.2754 + 0.0, 0.48, 14.95, 1.057, -0.2756 + 0.0, 0.48, 15.0, 1.063, -0.2758 + 0.0, 0.48, 15.05, 1.068, -0.2759 + 0.0, 0.53, 0.0, -0.1055, -0.03722 + 0.0, 0.53, 0.05, -0.1055, -0.03674 + 0.0, 0.53, 0.1, -0.1052, -0.03625 + 0.0, 0.53, 0.15, -0.1048, -0.03573 + 0.0, 0.53, 0.2, -0.1043, -0.03521 + 0.0, 0.53, 0.25, -0.1035, -0.03466 + 0.0, 0.53, 0.3, -0.1026, -0.03411 + 0.0, 0.53, 0.35, -0.1016, -0.03353 + 0.0, 0.53, 0.4, -0.1003, -0.03295 + 0.0, 0.53, 0.45, -0.09898, -0.03235 + 0.0, 0.53, 0.5, -0.09746, -0.03174 + 0.0, 0.53, 0.55, -0.09581, -0.03112 + 0.0, 0.53, 0.6, -0.09402, -0.03048 + 0.0, 0.53, 0.65, -0.0921, -0.02983 + 0.0, 0.53, 0.7, -0.09005, -0.02918 + 0.0, 0.53, 0.75, -0.08788, -0.02851 + 0.0, 0.53, 0.8, -0.08559, -0.02783 + 0.0, 0.53, 0.85, -0.08318, -0.02714 + 0.0, 0.53, 0.9, -0.08066, -0.02645 + 0.0, 0.53, 0.95, -0.07804, -0.02574 + 0.0, 0.53, 1.0, -0.07531, -0.02503 + 0.0, 0.53, 1.05, -0.07249, -0.02431 + 0.0, 0.53, 1.1, -0.06958, -0.02358 + 0.0, 0.53, 1.15, -0.06657, -0.02285 + 0.0, 0.53, 1.2, -0.06349, -0.02211 + 0.0, 0.53, 1.25, -0.06032, -0.02137 + 0.0, 0.53, 1.3, -0.05708, -0.02062 + 0.0, 0.53, 1.35, -0.05376, -0.01986 + 0.0, 0.53, 1.4, -0.05038, -0.0191 + 0.0, 0.53, 1.45, -0.04694, -0.01834 + 0.0, 0.53, 1.5, -0.04344, -0.01757 + 0.0, 0.53, 1.55, -0.03989, -0.0168 + 0.0, 0.53, 1.6, -0.03629, -0.01603 + 0.0, 0.53, 1.65, -0.03265, -0.01526 + 0.0, 0.53, 1.7, -0.02896, -0.01449 + 0.0, 0.53, 1.75, -0.02524, -0.01371 + 0.0, 0.53, 1.8, -0.02148, -0.01294 + 0.0, 0.53, 1.85, -0.01771, -0.01216 + 0.0, 0.53, 1.9, -0.0139, -0.01139 + 0.0, 0.53, 1.95, -0.01008, -0.01061 + 0.0, 0.53, 2.0, -0.006248, -0.009842 + 0.0, 0.53, 2.05, -0.002405, -0.009073 + 0.0, 0.53, 2.1, 0.001444, -0.008305 + 0.0, 0.53, 2.15, 0.005293, -0.007541 + 0.0, 0.53, 2.2, 0.009138, -0.00678 + 0.0, 0.53, 2.25, 0.01298, -0.006024 + 0.0, 0.53, 2.3, 0.0168, -0.005271 + 0.0, 0.53, 2.35, 0.02061, -0.004524 + 0.0, 0.53, 2.4, 0.02439, -0.003781 + 0.0, 0.53, 2.45, 0.02815, -0.003045 + 0.0, 0.53, 2.5, 0.03188, -0.002315 + 0.0, 0.53, 2.55, 0.03558, -0.001592 + 0.0, 0.53, 2.6, 0.03924, -0.0008756 + 0.0, 0.53, 2.65, 0.04285, -0.0001674 + 0.0, 0.53, 2.7, 0.04642, 0.0005327 + 0.0, 0.53, 2.75, 0.04993, 0.001224 + 0.0, 0.53, 2.8, 0.05339, 0.001906 + 0.0, 0.53, 2.85, 0.05678, 0.002579 + 0.0, 0.53, 2.9, 0.06011, 0.003241 + 0.0, 0.53, 2.95, 0.06338, 0.003893 + 0.0, 0.53, 3.0, 0.06656, 0.004534 + 0.0, 0.53, 3.05, 0.06967, 0.005163 + 0.0, 0.53, 3.1, 0.0727, 0.00578 + 0.0, 0.53, 3.15, 0.07564, 0.006385 + 0.0, 0.53, 3.2, 0.07848, 0.006976 + 0.0, 0.53, 3.25, 0.08124, 0.007555 + 0.0, 0.53, 3.3, 0.08389, 0.008119 + 0.0, 0.53, 3.35, 0.08643, 0.008669 + 0.0, 0.53, 3.4, 0.08887, 0.009204 + 0.0, 0.53, 3.45, 0.09119, 0.009723 + 0.0, 0.53, 3.5, 0.0934, 0.01023 + 0.0, 0.53, 3.55, 0.09548, 0.01071 + 0.0, 0.53, 3.6, 0.09744, 0.01119 + 0.0, 0.53, 3.65, 0.09926, 0.01164 + 0.0, 0.53, 3.7, 0.101, 0.01207 + 0.0, 0.53, 3.75, 0.1025, 0.01249 + 0.0, 0.53, 3.8, 0.1039, 0.01289 + 0.0, 0.53, 3.85, 0.1052, 0.01327 + 0.0, 0.53, 3.9, 0.1063, 0.01363 + 0.0, 0.53, 3.95, 0.1072, 0.01397 + 0.0, 0.53, 4.0, 0.108, 0.01429 + 0.0, 0.53, 4.05, 0.1074, 0.01452 + 0.0, 0.53, 4.1, 0.1067, 0.01473 + 0.0, 0.53, 4.15, 0.1059, 0.01492 + 0.0, 0.53, 4.2, 0.105, 0.0151 + 0.0, 0.53, 4.25, 0.104, 0.01526 + 0.0, 0.53, 4.3, 0.1029, 0.0154 + 0.0, 0.53, 4.35, 0.1018, 0.01553 + 0.0, 0.53, 4.4, 0.1006, 0.01564 + 0.0, 0.53, 4.45, 0.09936, 0.01573 + 0.0, 0.53, 4.5, 0.09805, 0.0158 + 0.0, 0.53, 4.55, 0.09668, 0.01586 + 0.0, 0.53, 4.6, 0.09527, 0.0159 + 0.0, 0.53, 4.65, 0.09382, 0.01592 + 0.0, 0.53, 4.7, 0.09233, 0.01593 + 0.0, 0.53, 4.75, 0.09082, 0.01592 + 0.0, 0.53, 4.8, 0.08927, 0.01589 + 0.0, 0.53, 4.85, 0.08771, 0.01585 + 0.0, 0.53, 4.9, 0.08612, 0.01579 + 0.0, 0.53, 4.95, 0.08453, 0.01571 + 0.0, 0.53, 5.0, 0.08294, 0.01562 + 0.0, 0.53, 5.05, 0.0812, 0.01554 + 0.0, 0.53, 5.1, 0.07947, 0.01544 + 0.0, 0.53, 5.15, 0.07775, 0.01533 + 0.0, 0.53, 5.2, 0.07606, 0.0152 + 0.0, 0.53, 5.25, 0.0744, 0.01505 + 0.0, 0.53, 5.3, 0.07277, 0.01488 + 0.0, 0.53, 5.35, 0.07118, 0.01469 + 0.0, 0.53, 5.4, 0.06964, 0.01449 + 0.0, 0.53, 5.45, 0.06816, 0.01426 + 0.0, 0.53, 5.5, 0.06675, 0.01402 + 0.0, 0.53, 5.55, 0.0654, 0.01375 + 0.0, 0.53, 5.6, 0.06414, 0.01347 + 0.0, 0.53, 5.65, 0.06296, 0.01316 + 0.0, 0.53, 5.7, 0.06188, 0.01283 + 0.0, 0.53, 5.75, 0.06089, 0.01248 + 0.0, 0.53, 5.8, 0.06001, 0.01211 + 0.0, 0.53, 5.85, 0.05925, 0.01172 + 0.0, 0.53, 5.9, 0.05861, 0.0113 + 0.0, 0.53, 5.95, 0.0581, 0.01086 + 0.0, 0.53, 6.0, 0.05773, 0.01039 + 0.0, 0.53, 6.05, 0.05922, 0.009777 + 0.0, 0.53, 6.1, 0.06094, 0.009131 + 0.0, 0.53, 6.15, 0.06287, 0.008455 + 0.0, 0.53, 6.2, 0.06502, 0.007751 + 0.0, 0.53, 6.25, 0.06737, 0.007019 + 0.0, 0.53, 6.3, 0.06992, 0.006259 + 0.0, 0.53, 6.35, 0.07267, 0.005472 + 0.0, 0.53, 6.4, 0.0756, 0.004659 + 0.0, 0.53, 6.45, 0.07873, 0.00382 + 0.0, 0.53, 6.5, 0.08203, 0.002955 + 0.0, 0.53, 6.55, 0.0855, 0.002066 + 0.0, 0.53, 6.6, 0.08915, 0.001152 + 0.0, 0.53, 6.65, 0.09295, 0.0002144 + 0.0, 0.53, 6.7, 0.09691, -0.0007463 + 0.0, 0.53, 6.75, 0.101, -0.00173 + 0.0, 0.53, 6.8, 0.1053, -0.002735 + 0.0, 0.53, 6.85, 0.1097, -0.003762 + 0.0, 0.53, 6.9, 0.1142, -0.00481 + 0.0, 0.53, 6.95, 0.1189, -0.005878 + 0.0, 0.53, 7.0, 0.1237, -0.006966 + 0.0, 0.53, 7.05, 0.1286, -0.008074 + 0.0, 0.53, 7.1, 0.1336, -0.0092 + 0.0, 0.53, 7.15, 0.1388, -0.01034 + 0.0, 0.53, 7.2, 0.144, -0.01151 + 0.0, 0.53, 7.25, 0.1493, -0.01269 + 0.0, 0.53, 7.3, 0.1548, -0.01388 + 0.0, 0.53, 7.35, 0.1603, -0.01509 + 0.0, 0.53, 7.4, 0.1659, -0.01632 + 0.0, 0.53, 7.45, 0.1716, -0.01756 + 0.0, 0.53, 7.5, 0.1773, -0.01882 + 0.0, 0.53, 7.55, 0.1831, -0.02009 + 0.0, 0.53, 7.6, 0.189, -0.02137 + 0.0, 0.53, 7.65, 0.1949, -0.02267 + 0.0, 0.53, 7.7, 0.2009, -0.02398 + 0.0, 0.53, 7.75, 0.2069, -0.0253 + 0.0, 0.53, 7.8, 0.213, -0.02663 + 0.0, 0.53, 7.85, 0.219, -0.02797 + 0.0, 0.53, 7.9, 0.2252, -0.02932 + 0.0, 0.53, 7.95, 0.2313, -0.03068 + 0.0, 0.53, 8.0, 0.2374, -0.03205 + 0.0, 0.53, 8.05, 0.2422, -0.0333 + 0.0, 0.53, 8.1, 0.247, -0.03456 + 0.0, 0.53, 8.15, 0.2518, -0.03582 + 0.0, 0.53, 8.2, 0.2567, -0.0371 + 0.0, 0.53, 8.25, 0.2615, -0.03838 + 0.0, 0.53, 8.3, 0.2663, -0.03967 + 0.0, 0.53, 8.35, 0.2712, -0.04096 + 0.0, 0.53, 8.4, 0.276, -0.04227 + 0.0, 0.53, 8.45, 0.2809, -0.04358 + 0.0, 0.53, 8.5, 0.2858, -0.0449 + 0.0, 0.53, 8.55, 0.2907, -0.04623 + 0.0, 0.53, 8.6, 0.2955, -0.04757 + 0.0, 0.53, 8.65, 0.3004, -0.04891 + 0.0, 0.53, 8.7, 0.3053, -0.05026 + 0.0, 0.53, 8.75, 0.3103, -0.05162 + 0.0, 0.53, 8.8, 0.3152, -0.05298 + 0.0, 0.53, 8.85, 0.3201, -0.05436 + 0.0, 0.53, 8.9, 0.325, -0.05574 + 0.0, 0.53, 8.95, 0.33, -0.05712 + 0.0, 0.53, 9.0, 0.3349, -0.05852 + 0.0, 0.53, 9.05, 0.3399, -0.05992 + 0.0, 0.53, 9.1, 0.3448, -0.06133 + 0.0, 0.53, 9.15, 0.3498, -0.06274 + 0.0, 0.53, 9.2, 0.3548, -0.06416 + 0.0, 0.53, 9.25, 0.3597, -0.06559 + 0.0, 0.53, 9.3, 0.3647, -0.06703 + 0.0, 0.53, 9.35, 0.3697, -0.06847 + 0.0, 0.53, 9.4, 0.3747, -0.06992 + 0.0, 0.53, 9.45, 0.3797, -0.07137 + 0.0, 0.53, 9.5, 0.3847, -0.07283 + 0.0, 0.53, 9.55, 0.3897, -0.0743 + 0.0, 0.53, 9.6, 0.3947, -0.07577 + 0.0, 0.53, 9.65, 0.3997, -0.07726 + 0.0, 0.53, 9.7, 0.4047, -0.07874 + 0.0, 0.53, 9.75, 0.4097, -0.08023 + 0.0, 0.53, 9.8, 0.4147, -0.08173 + 0.0, 0.53, 9.85, 0.4197, -0.08324 + 0.0, 0.53, 9.9, 0.4247, -0.08475 + 0.0, 0.53, 9.95, 0.4297, -0.08627 + 0.0, 0.53, 10.0, 0.4347, -0.08779 + 0.0, 0.53, 10.05, 0.4397, -0.08941 + 0.0, 0.53, 10.1, 0.4447, -0.09104 + 0.0, 0.53, 10.15, 0.4496, -0.09267 + 0.0, 0.53, 10.2, 0.4546, -0.09431 + 0.0, 0.53, 10.25, 0.4596, -0.09595 + 0.0, 0.53, 10.3, 0.4645, -0.0976 + 0.0, 0.53, 10.35, 0.4695, -0.09925 + 0.0, 0.53, 10.4, 0.4745, -0.1009 + 0.0, 0.53, 10.45, 0.4795, -0.1026 + 0.0, 0.53, 10.5, 0.4844, -0.1042 + 0.0, 0.53, 10.55, 0.4894, -0.1059 + 0.0, 0.53, 10.6, 0.4944, -0.1075 + 0.0, 0.53, 10.65, 0.4993, -0.1092 + 0.0, 0.53, 10.7, 0.5043, -0.1108 + 0.0, 0.53, 10.75, 0.5093, -0.1125 + 0.0, 0.53, 10.8, 0.5142, -0.1142 + 0.0, 0.53, 10.85, 0.5192, -0.1158 + 0.0, 0.53, 10.9, 0.5242, -0.1175 + 0.0, 0.53, 10.95, 0.5291, -0.1191 + 0.0, 0.53, 11.0, 0.5341, -0.1208 + 0.0, 0.53, 11.05, 0.5391, -0.1224 + 0.0, 0.53, 11.1, 0.544, -0.1241 + 0.0, 0.53, 11.15, 0.549, -0.1257 + 0.0, 0.53, 11.2, 0.5539, -0.1274 + 0.0, 0.53, 11.25, 0.5589, -0.129 + 0.0, 0.53, 11.3, 0.5639, -0.1306 + 0.0, 0.53, 11.35, 0.5688, -0.1322 + 0.0, 0.53, 11.4, 0.5738, -0.1339 + 0.0, 0.53, 11.45, 0.5787, -0.1355 + 0.0, 0.53, 11.5, 0.5837, -0.1371 + 0.0, 0.53, 11.55, 0.5886, -0.1387 + 0.0, 0.53, 11.6, 0.5935, -0.1403 + 0.0, 0.53, 11.65, 0.5985, -0.1419 + 0.0, 0.53, 11.7, 0.6034, -0.1434 + 0.0, 0.53, 11.75, 0.6084, -0.145 + 0.0, 0.53, 11.8, 0.6133, -0.1466 + 0.0, 0.53, 11.85, 0.6182, -0.1481 + 0.0, 0.53, 11.9, 0.6232, -0.1497 + 0.0, 0.53, 11.95, 0.6281, -0.1512 + 0.0, 0.53, 12.0, 0.633, -0.1527 + 0.0, 0.53, 12.05, 0.6379, -0.1542 + 0.0, 0.53, 12.1, 0.6428, -0.1557 + 0.0, 0.53, 12.15, 0.6478, -0.1572 + 0.0, 0.53, 12.2, 0.6527, -0.1587 + 0.0, 0.53, 12.25, 0.6576, -0.1601 + 0.0, 0.53, 12.3, 0.6625, -0.1616 + 0.0, 0.53, 12.35, 0.6674, -0.163 + 0.0, 0.53, 12.4, 0.6723, -0.1644 + 0.0, 0.53, 12.45, 0.6772, -0.1658 + 0.0, 0.53, 12.5, 0.6821, -0.1672 + 0.0, 0.53, 12.55, 0.6869, -0.1686 + 0.0, 0.53, 12.6, 0.6918, -0.17 + 0.0, 0.53, 12.65, 0.6967, -0.1713 + 0.0, 0.53, 12.7, 0.7016, -0.1726 + 0.0, 0.53, 12.75, 0.7064, -0.1739 + 0.0, 0.53, 12.8, 0.7113, -0.1752 + 0.0, 0.53, 12.85, 0.7162, -0.1765 + 0.0, 0.53, 12.9, 0.721, -0.1778 + 0.0, 0.53, 12.95, 0.7259, -0.179 + 0.0, 0.53, 13.0, 0.7307, -0.1802 + 0.0, 0.53, 13.05, 0.7356, -0.1814 + 0.0, 0.53, 13.1, 0.7404, -0.1826 + 0.0, 0.53, 13.15, 0.7452, -0.1837 + 0.0, 0.53, 13.2, 0.7501, -0.1849 + 0.0, 0.53, 13.25, 0.7549, -0.186 + 0.0, 0.53, 13.3, 0.7597, -0.1871 + 0.0, 0.53, 13.35, 0.7645, -0.1882 + 0.0, 0.53, 13.4, 0.7693, -0.1892 + 0.0, 0.53, 13.45, 0.7741, -0.1902 + 0.0, 0.53, 13.5, 0.7789, -0.1912 + 0.0, 0.53, 13.55, 0.7837, -0.1922 + 0.0, 0.53, 13.6, 0.7885, -0.1932 + 0.0, 0.53, 13.65, 0.7933, -0.1941 + 0.0, 0.53, 13.7, 0.7981, -0.195 + 0.0, 0.53, 13.75, 0.8028, -0.1959 + 0.0, 0.53, 13.8, 0.8076, -0.1968 + 0.0, 0.53, 13.85, 0.8123, -0.1976 + 0.0, 0.53, 13.9, 0.8171, -0.1984 + 0.0, 0.53, 13.95, 0.8218, -0.1992 + 0.0, 0.53, 14.0, 0.8266, -0.1999 + 0.0, 0.53, 14.05, 0.8313, -0.2006 + 0.0, 0.53, 14.1, 0.836, -0.2013 + 0.0, 0.53, 14.15, 0.8407, -0.202 + 0.0, 0.53, 14.2, 0.8454, -0.2026 + 0.0, 0.53, 14.25, 0.8501, -0.2032 + 0.0, 0.53, 14.3, 0.8548, -0.2038 + 0.0, 0.53, 14.35, 0.8595, -0.2044 + 0.0, 0.53, 14.4, 0.8642, -0.2049 + 0.0, 0.53, 14.45, 0.8689, -0.2054 + 0.0, 0.53, 14.5, 0.8736, -0.2058 + 0.0, 0.53, 14.55, 0.8782, -0.2062 + 0.0, 0.53, 14.6, 0.8829, -0.2066 + 0.0, 0.53, 14.65, 0.8875, -0.207 + 0.0, 0.53, 14.7, 0.8921, -0.2073 + 0.0, 0.53, 14.75, 0.8968, -0.2076 + 0.0, 0.53, 14.8, 0.9014, -0.2078 + 0.0, 0.53, 14.85, 0.906, -0.208 + 0.0, 0.53, 14.9, 0.9106, -0.2082 + 0.0, 0.53, 14.95, 0.9152, -0.2084 + 0.0, 0.53, 15.0, 0.9198, -0.2085 + 0.0, 0.53, 15.05, 0.9244, -0.2086 + 0.0, 0.58, 0.0, -0.1174, -0.02338 + 0.0, 0.58, 0.05, -0.1165, -0.02306 + 0.0, 0.58, 0.1, -0.1154, -0.02274 + 0.0, 0.58, 0.15, -0.1142, -0.0224 + 0.0, 0.58, 0.2, -0.1129, -0.02206 + 0.0, 0.58, 0.25, -0.1115, -0.0217 + 0.0, 0.58, 0.3, -0.1099, -0.02134 + 0.0, 0.58, 0.35, -0.1083, -0.02097 + 0.0, 0.58, 0.4, -0.1065, -0.02058 + 0.0, 0.58, 0.45, -0.1047, -0.02019 + 0.0, 0.58, 0.5, -0.1027, -0.01979 + 0.0, 0.58, 0.55, -0.1007, -0.01939 + 0.0, 0.58, 0.6, -0.09856, -0.01897 + 0.0, 0.58, 0.65, -0.09634, -0.01855 + 0.0, 0.58, 0.7, -0.09403, -0.01812 + 0.0, 0.58, 0.75, -0.09164, -0.01769 + 0.0, 0.58, 0.8, -0.08917, -0.01724 + 0.0, 0.58, 0.85, -0.08662, -0.01679 + 0.0, 0.58, 0.9, -0.08399, -0.01634 + 0.0, 0.58, 0.95, -0.0813, -0.01588 + 0.0, 0.58, 1.0, -0.07854, -0.01541 + 0.0, 0.58, 1.05, -0.07571, -0.01494 + 0.0, 0.58, 1.1, -0.07282, -0.01447 + 0.0, 0.58, 1.15, -0.06987, -0.01399 + 0.0, 0.58, 1.2, -0.06686, -0.01351 + 0.0, 0.58, 1.25, -0.0638, -0.01302 + 0.0, 0.58, 1.3, -0.06069, -0.01253 + 0.0, 0.58, 1.35, -0.05753, -0.01204 + 0.0, 0.58, 1.4, -0.05432, -0.01154 + 0.0, 0.58, 1.45, -0.05108, -0.01104 + 0.0, 0.58, 1.5, -0.04779, -0.01054 + 0.0, 0.58, 1.55, -0.04447, -0.01003 + 0.0, 0.58, 1.6, -0.04112, -0.00953 + 0.0, 0.58, 1.65, -0.03774, -0.009024 + 0.0, 0.58, 1.7, -0.03433, -0.008516 + 0.0, 0.58, 1.75, -0.0309, -0.008008 + 0.0, 0.58, 1.8, -0.02744, -0.007499 + 0.0, 0.58, 1.85, -0.02397, -0.00699 + 0.0, 0.58, 1.9, -0.02049, -0.006481 + 0.0, 0.58, 1.95, -0.01699, -0.005973 + 0.0, 0.58, 2.0, -0.01348, -0.005466 + 0.0, 0.58, 2.05, -0.009966, -0.004959 + 0.0, 0.58, 2.1, -0.00645, -0.004454 + 0.0, 0.58, 2.15, -0.002933, -0.00395 + 0.0, 0.58, 2.2, 0.0005809, -0.003449 + 0.0, 0.58, 2.25, 0.004089, -0.00295 + 0.0, 0.58, 2.3, 0.007588, -0.002453 + 0.0, 0.58, 2.35, 0.01108, -0.001959 + 0.0, 0.58, 2.4, 0.01455, -0.001468 + 0.0, 0.58, 2.45, 0.018, -0.0009808 + 0.0, 0.58, 2.5, 0.02144, -0.0004972 + 0.0, 0.58, 2.55, 0.02485, -1.771e-05 + 0.0, 0.58, 2.6, 0.02823, 0.0004575 + 0.0, 0.58, 2.65, 0.03159, 0.000928 + 0.0, 0.58, 2.7, 0.03491, 0.001394 + 0.0, 0.58, 2.75, 0.03819, 0.001854 + 0.0, 0.58, 2.8, 0.04144, 0.002309 + 0.0, 0.58, 2.85, 0.04465, 0.002758 + 0.0, 0.58, 2.9, 0.04781, 0.0032 + 0.0, 0.58, 2.95, 0.05092, 0.003637 + 0.0, 0.58, 3.0, 0.05399, 0.004066 + 0.0, 0.58, 3.05, 0.057, 0.004489 + 0.0, 0.58, 3.1, 0.05995, 0.004904 + 0.0, 0.58, 3.15, 0.06285, 0.005311 + 0.0, 0.58, 3.2, 0.06568, 0.005711 + 0.0, 0.58, 3.25, 0.06845, 0.006102 + 0.0, 0.58, 3.3, 0.07115, 0.006485 + 0.0, 0.58, 3.35, 0.07378, 0.006859 + 0.0, 0.58, 3.4, 0.07633, 0.007224 + 0.0, 0.58, 3.45, 0.07881, 0.007579 + 0.0, 0.58, 3.5, 0.0812, 0.007924 + 0.0, 0.58, 3.55, 0.08352, 0.00826 + 0.0, 0.58, 3.6, 0.08574, 0.008585 + 0.0, 0.58, 3.65, 0.08788, 0.008899 + 0.0, 0.58, 3.7, 0.08993, 0.009203 + 0.0, 0.58, 3.75, 0.09188, 0.009495 + 0.0, 0.58, 3.8, 0.09374, 0.009775 + 0.0, 0.58, 3.85, 0.09549, 0.01004 + 0.0, 0.58, 3.9, 0.09714, 0.0103 + 0.0, 0.58, 3.95, 0.09868, 0.01054 + 0.0, 0.58, 4.0, 0.1001, 0.01078 + 0.0, 0.58, 4.05, 0.1006, 0.01095 + 0.0, 0.58, 4.1, 0.101, 0.0111 + 0.0, 0.58, 4.15, 0.1014, 0.01125 + 0.0, 0.58, 4.2, 0.1017, 0.01139 + 0.0, 0.58, 4.25, 0.1019, 0.01152 + 0.0, 0.58, 4.3, 0.1021, 0.01164 + 0.0, 0.58, 4.35, 0.1022, 0.01174 + 0.0, 0.58, 4.4, 0.1023, 0.01184 + 0.0, 0.58, 4.45, 0.1024, 0.01193 + 0.0, 0.58, 4.5, 0.1024, 0.01201 + 0.0, 0.58, 4.55, 0.1024, 0.01207 + 0.0, 0.58, 4.6, 0.1023, 0.01213 + 0.0, 0.58, 4.65, 0.1022, 0.01218 + 0.0, 0.58, 4.7, 0.1021, 0.01222 + 0.0, 0.58, 4.75, 0.102, 0.01225 + 0.0, 0.58, 4.8, 0.1018, 0.01227 + 0.0, 0.58, 4.85, 0.1017, 0.01228 + 0.0, 0.58, 4.9, 0.1015, 0.01228 + 0.0, 0.58, 4.95, 0.1013, 0.01228 + 0.0, 0.58, 5.0, 0.1011, 0.01226 + 0.0, 0.58, 5.05, 0.1009, 0.01226 + 0.0, 0.58, 5.1, 0.1007, 0.01226 + 0.0, 0.58, 5.15, 0.1005, 0.01224 + 0.0, 0.58, 5.2, 0.1002, 0.01222 + 0.0, 0.58, 5.25, 0.1001, 0.01218 + 0.0, 0.58, 5.3, 0.09989, 0.01214 + 0.0, 0.58, 5.35, 0.09974, 0.01208 + 0.0, 0.58, 5.4, 0.09963, 0.01201 + 0.0, 0.58, 5.45, 0.09955, 0.01193 + 0.0, 0.58, 5.5, 0.0995, 0.01184 + 0.0, 0.58, 5.55, 0.0995, 0.01173 + 0.0, 0.58, 5.6, 0.09955, 0.01161 + 0.0, 0.58, 5.65, 0.09964, 0.01148 + 0.0, 0.58, 5.7, 0.0998, 0.01133 + 0.0, 0.58, 5.75, 0.1, 0.01117 + 0.0, 0.58, 5.8, 0.1003, 0.011 + 0.0, 0.58, 5.85, 0.1006, 0.01081 + 0.0, 0.58, 5.9, 0.101, 0.0106 + 0.0, 0.58, 5.95, 0.1015, 0.01038 + 0.0, 0.58, 6.0, 0.1021, 0.01014 + 0.0, 0.58, 6.05, 0.1038, 0.009784 + 0.0, 0.58, 6.1, 0.1055, 0.009404 + 0.0, 0.58, 6.15, 0.1075, 0.009002 + 0.0, 0.58, 6.2, 0.1095, 0.008581 + 0.0, 0.58, 6.25, 0.1117, 0.008139 + 0.0, 0.58, 6.3, 0.114, 0.007678 + 0.0, 0.58, 6.35, 0.1164, 0.007198 + 0.0, 0.58, 6.4, 0.1189, 0.006699 + 0.0, 0.58, 6.45, 0.1215, 0.006181 + 0.0, 0.58, 6.5, 0.1242, 0.005646 + 0.0, 0.58, 6.55, 0.1271, 0.005093 + 0.0, 0.58, 6.6, 0.13, 0.004523 + 0.0, 0.58, 6.65, 0.133, 0.003937 + 0.0, 0.58, 6.7, 0.1361, 0.003334 + 0.0, 0.58, 6.75, 0.1393, 0.002716 + 0.0, 0.58, 6.8, 0.1426, 0.002082 + 0.0, 0.58, 6.85, 0.146, 0.001432 + 0.0, 0.58, 6.9, 0.1494, 0.0007687 + 0.0, 0.58, 6.95, 0.153, 9.07e-05 + 0.0, 0.58, 7.0, 0.1566, -0.0006011 + 0.0, 0.58, 7.05, 0.1603, -0.001306 + 0.0, 0.58, 7.1, 0.164, -0.002025 + 0.0, 0.58, 7.15, 0.1678, -0.002755 + 0.0, 0.58, 7.2, 0.1717, -0.003498 + 0.0, 0.58, 7.25, 0.1756, -0.004253 + 0.0, 0.58, 7.3, 0.1796, -0.005019 + 0.0, 0.58, 7.35, 0.1836, -0.005797 + 0.0, 0.58, 7.4, 0.1877, -0.006584 + 0.0, 0.58, 7.45, 0.1919, -0.007382 + 0.0, 0.58, 7.5, 0.196, -0.00819 + 0.0, 0.58, 7.55, 0.2002, -0.009007 + 0.0, 0.58, 7.6, 0.2045, -0.009833 + 0.0, 0.58, 7.65, 0.2088, -0.01067 + 0.0, 0.58, 7.7, 0.2131, -0.01151 + 0.0, 0.58, 7.75, 0.2174, -0.01236 + 0.0, 0.58, 7.8, 0.2218, -0.01322 + 0.0, 0.58, 7.85, 0.2261, -0.01408 + 0.0, 0.58, 7.9, 0.2305, -0.01495 + 0.0, 0.58, 7.95, 0.235, -0.01583 + 0.0, 0.58, 8.0, 0.2394, -0.01671 + 0.0, 0.58, 8.05, 0.243, -0.0175 + 0.0, 0.58, 8.1, 0.2467, -0.0183 + 0.0, 0.58, 8.15, 0.2503, -0.0191 + 0.0, 0.58, 8.2, 0.254, -0.0199 + 0.0, 0.58, 8.25, 0.2576, -0.02071 + 0.0, 0.58, 8.3, 0.2613, -0.02153 + 0.0, 0.58, 8.35, 0.265, -0.02235 + 0.0, 0.58, 8.4, 0.2687, -0.02317 + 0.0, 0.58, 8.45, 0.2723, -0.024 + 0.0, 0.58, 8.5, 0.276, -0.02484 + 0.0, 0.58, 8.55, 0.2797, -0.02568 + 0.0, 0.58, 8.6, 0.2834, -0.02652 + 0.0, 0.58, 8.65, 0.2872, -0.02737 + 0.0, 0.58, 8.7, 0.2909, -0.02822 + 0.0, 0.58, 8.75, 0.2946, -0.02908 + 0.0, 0.58, 8.8, 0.2983, -0.02995 + 0.0, 0.58, 8.85, 0.3021, -0.03082 + 0.0, 0.58, 8.9, 0.3058, -0.03169 + 0.0, 0.58, 8.95, 0.3095, -0.03257 + 0.0, 0.58, 9.0, 0.3133, -0.03345 + 0.0, 0.58, 9.05, 0.317, -0.03434 + 0.0, 0.58, 9.1, 0.3208, -0.03523 + 0.0, 0.58, 9.15, 0.3245, -0.03612 + 0.0, 0.58, 9.2, 0.3283, -0.03702 + 0.0, 0.58, 9.25, 0.3321, -0.03793 + 0.0, 0.58, 9.3, 0.3358, -0.03883 + 0.0, 0.58, 9.35, 0.3396, -0.03975 + 0.0, 0.58, 9.4, 0.3434, -0.04066 + 0.0, 0.58, 9.45, 0.3472, -0.04159 + 0.0, 0.58, 9.5, 0.3509, -0.04251 + 0.0, 0.58, 9.55, 0.3547, -0.04344 + 0.0, 0.58, 9.6, 0.3585, -0.04437 + 0.0, 0.58, 9.65, 0.3623, -0.04531 + 0.0, 0.58, 9.7, 0.3661, -0.04625 + 0.0, 0.58, 9.75, 0.3699, -0.0472 + 0.0, 0.58, 9.8, 0.3736, -0.04815 + 0.0, 0.58, 9.85, 0.3774, -0.0491 + 0.0, 0.58, 9.9, 0.3812, -0.05006 + 0.0, 0.58, 9.95, 0.385, -0.05102 + 0.0, 0.58, 10.0, 0.3888, -0.05198 + 0.0, 0.58, 10.05, 0.3926, -0.05302 + 0.0, 0.58, 10.1, 0.3963, -0.05405 + 0.0, 0.58, 10.15, 0.4001, -0.05509 + 0.0, 0.58, 10.2, 0.4039, -0.05614 + 0.0, 0.58, 10.25, 0.4076, -0.05718 + 0.0, 0.58, 10.3, 0.4114, -0.05823 + 0.0, 0.58, 10.35, 0.4152, -0.05928 + 0.0, 0.58, 10.4, 0.4189, -0.06033 + 0.0, 0.58, 10.45, 0.4227, -0.06138 + 0.0, 0.58, 10.5, 0.4265, -0.06244 + 0.0, 0.58, 10.55, 0.4302, -0.06349 + 0.0, 0.58, 10.6, 0.434, -0.06455 + 0.0, 0.58, 10.65, 0.4378, -0.0656 + 0.0, 0.58, 10.7, 0.4415, -0.06666 + 0.0, 0.58, 10.75, 0.4453, -0.06771 + 0.0, 0.58, 10.8, 0.4491, -0.06877 + 0.0, 0.58, 10.85, 0.4528, -0.06982 + 0.0, 0.58, 10.9, 0.4566, -0.07088 + 0.0, 0.58, 10.95, 0.4604, -0.07193 + 0.0, 0.58, 11.0, 0.4641, -0.07298 + 0.0, 0.58, 11.05, 0.4679, -0.07403 + 0.0, 0.58, 11.1, 0.4716, -0.07508 + 0.0, 0.58, 11.15, 0.4754, -0.07612 + 0.0, 0.58, 11.2, 0.4792, -0.07716 + 0.0, 0.58, 11.25, 0.4829, -0.0782 + 0.0, 0.58, 11.3, 0.4867, -0.07924 + 0.0, 0.58, 11.35, 0.4904, -0.08027 + 0.0, 0.58, 11.4, 0.4942, -0.0813 + 0.0, 0.58, 11.45, 0.498, -0.08232 + 0.0, 0.58, 11.5, 0.5017, -0.08334 + 0.0, 0.58, 11.55, 0.5055, -0.08436 + 0.0, 0.58, 11.6, 0.5092, -0.08537 + 0.0, 0.58, 11.65, 0.513, -0.08637 + 0.0, 0.58, 11.7, 0.5167, -0.08737 + 0.0, 0.58, 11.75, 0.5205, -0.08836 + 0.0, 0.58, 11.8, 0.5242, -0.08935 + 0.0, 0.58, 11.85, 0.528, -0.09033 + 0.0, 0.58, 11.9, 0.5317, -0.09131 + 0.0, 0.58, 11.95, 0.5355, -0.09228 + 0.0, 0.58, 12.0, 0.5392, -0.09324 + 0.0, 0.58, 12.05, 0.5429, -0.09419 + 0.0, 0.58, 12.1, 0.5467, -0.09513 + 0.0, 0.58, 12.15, 0.5504, -0.09607 + 0.0, 0.58, 12.2, 0.5541, -0.097 + 0.0, 0.58, 12.25, 0.5579, -0.09792 + 0.0, 0.58, 12.3, 0.5616, -0.09883 + 0.0, 0.58, 12.35, 0.5653, -0.09974 + 0.0, 0.58, 12.4, 0.5691, -0.1006 + 0.0, 0.58, 12.45, 0.5728, -0.1015 + 0.0, 0.58, 12.5, 0.5765, -0.1024 + 0.0, 0.58, 12.55, 0.5802, -0.1032 + 0.0, 0.58, 12.6, 0.584, -0.1041 + 0.0, 0.58, 12.65, 0.5877, -0.1049 + 0.0, 0.58, 12.7, 0.5914, -0.1058 + 0.0, 0.58, 12.75, 0.5951, -0.1066 + 0.0, 0.58, 12.8, 0.5988, -0.1074 + 0.0, 0.58, 12.85, 0.6025, -0.1082 + 0.0, 0.58, 12.9, 0.6062, -0.109 + 0.0, 0.58, 12.95, 0.6099, -0.1098 + 0.0, 0.58, 13.0, 0.6136, -0.1105 + 0.0, 0.58, 13.05, 0.6173, -0.1113 + 0.0, 0.58, 13.1, 0.621, -0.112 + 0.0, 0.58, 13.15, 0.6247, -0.1127 + 0.0, 0.58, 13.2, 0.6284, -0.1134 + 0.0, 0.58, 13.25, 0.6321, -0.1141 + 0.0, 0.58, 13.3, 0.6357, -0.1148 + 0.0, 0.58, 13.35, 0.6394, -0.1154 + 0.0, 0.58, 13.4, 0.6431, -0.1161 + 0.0, 0.58, 13.45, 0.6468, -0.1167 + 0.0, 0.58, 13.5, 0.6504, -0.1173 + 0.0, 0.58, 13.55, 0.6541, -0.1179 + 0.0, 0.58, 13.6, 0.6578, -0.1185 + 0.0, 0.58, 13.65, 0.6614, -0.1191 + 0.0, 0.58, 13.7, 0.6651, -0.1196 + 0.0, 0.58, 13.75, 0.6687, -0.1202 + 0.0, 0.58, 13.8, 0.6724, -0.1207 + 0.0, 0.58, 13.85, 0.676, -0.1212 + 0.0, 0.58, 13.9, 0.6796, -0.1217 + 0.0, 0.58, 13.95, 0.6833, -0.1221 + 0.0, 0.58, 14.0, 0.6869, -0.1226 + 0.0, 0.58, 14.05, 0.6905, -0.123 + 0.0, 0.58, 14.1, 0.6942, -0.1234 + 0.0, 0.58, 14.15, 0.6978, -0.1238 + 0.0, 0.58, 14.2, 0.7014, -0.1242 + 0.0, 0.58, 14.25, 0.705, -0.1245 + 0.0, 0.58, 14.3, 0.7086, -0.1248 + 0.0, 0.58, 14.35, 0.7122, -0.1251 + 0.0, 0.58, 14.4, 0.7158, -0.1254 + 0.0, 0.58, 14.45, 0.7194, -0.1257 + 0.0, 0.58, 14.5, 0.723, -0.1259 + 0.0, 0.58, 14.55, 0.7266, -0.1262 + 0.0, 0.58, 14.6, 0.7302, -0.1264 + 0.0, 0.58, 14.65, 0.7337, -0.1265 + 0.0, 0.58, 14.7, 0.7373, -0.1267 + 0.0, 0.58, 14.75, 0.7409, -0.1268 + 0.0, 0.58, 14.8, 0.7444, -0.127 + 0.0, 0.58, 14.85, 0.748, -0.127 + 0.0, 0.58, 14.9, 0.7515, -0.1271 + 0.0, 0.58, 14.95, 0.7551, -0.1272 + 0.0, 0.58, 15.0, 0.7586, -0.1272 + 0.0, 0.58, 15.05, 0.7622, -0.1272 + 0.0, 0.63, 0.0, -0.1323, -0.009531 + 0.0, 0.63, 0.05, -0.1304, -0.009379 + 0.0, 0.63, 0.1, -0.1284, -0.009223 + 0.0, 0.63, 0.15, -0.1263, -0.009062 + 0.0, 0.63, 0.2, -0.1242, -0.008897 + 0.0, 0.63, 0.25, -0.1221, -0.008727 + 0.0, 0.63, 0.3, -0.1199, -0.008553 + 0.0, 0.63, 0.35, -0.1176, -0.008375 + 0.0, 0.63, 0.4, -0.1153, -0.008193 + 0.0, 0.63, 0.45, -0.1129, -0.008007 + 0.0, 0.63, 0.5, -0.1104, -0.007817 + 0.0, 0.63, 0.55, -0.108, -0.007623 + 0.0, 0.63, 0.6, -0.1054, -0.007426 + 0.0, 0.63, 0.65, -0.1029, -0.007226 + 0.0, 0.63, 0.7, -0.1002, -0.007022 + 0.0, 0.63, 0.75, -0.09758, -0.006815 + 0.0, 0.63, 0.8, -0.09487, -0.006605 + 0.0, 0.63, 0.85, -0.09213, -0.006392 + 0.0, 0.63, 0.9, -0.08934, -0.006177 + 0.0, 0.63, 0.95, -0.08652, -0.005958 + 0.0, 0.63, 1.0, -0.08366, -0.005737 + 0.0, 0.63, 1.05, -0.08077, -0.005514 + 0.0, 0.63, 1.1, -0.07785, -0.005289 + 0.0, 0.63, 1.15, -0.07489, -0.005061 + 0.0, 0.63, 1.2, -0.07191, -0.004831 + 0.0, 0.63, 1.25, -0.0689, -0.0046 + 0.0, 0.63, 1.3, -0.06586, -0.004366 + 0.0, 0.63, 1.35, -0.0628, -0.004131 + 0.0, 0.63, 1.4, -0.05971, -0.003894 + 0.0, 0.63, 1.45, -0.05661, -0.003656 + 0.0, 0.63, 1.5, -0.05348, -0.003417 + 0.0, 0.63, 1.55, -0.05034, -0.003177 + 0.0, 0.63, 1.6, -0.04718, -0.002935 + 0.0, 0.63, 1.65, -0.044, -0.002693 + 0.0, 0.63, 1.7, -0.04081, -0.002449 + 0.0, 0.63, 1.75, -0.03761, -0.002206 + 0.0, 0.63, 1.8, -0.03439, -0.001961 + 0.0, 0.63, 1.85, -0.03117, -0.001716 + 0.0, 0.63, 1.9, -0.02794, -0.001471 + 0.0, 0.63, 1.95, -0.02471, -0.001226 + 0.0, 0.63, 2.0, -0.02147, -0.0009805 + 0.0, 0.63, 2.05, -0.01822, -0.0007352 + 0.0, 0.63, 2.1, -0.01498, -0.0004902 + 0.0, 0.63, 2.15, -0.01174, -0.0002455 + 0.0, 0.63, 2.2, -0.008496, -1.227e-06 + 0.0, 0.63, 2.25, -0.005258, 0.0002424 + 0.0, 0.63, 2.3, -0.002025, 0.0004854 + 0.0, 0.63, 2.35, 0.001201, 0.0007275 + 0.0, 0.63, 2.4, 0.004418, 0.0009687 + 0.0, 0.63, 2.45, 0.007626, 0.001209 + 0.0, 0.63, 2.5, 0.01082, 0.001448 + 0.0, 0.63, 2.55, 0.01401, 0.001685 + 0.0, 0.63, 2.6, 0.01718, 0.001921 + 0.0, 0.63, 2.65, 0.02033, 0.002156 + 0.0, 0.63, 2.7, 0.02346, 0.002389 + 0.0, 0.63, 2.75, 0.02658, 0.00262 + 0.0, 0.63, 2.8, 0.02968, 0.002849 + 0.0, 0.63, 2.85, 0.03275, 0.003076 + 0.0, 0.63, 2.9, 0.0358, 0.0033 + 0.0, 0.63, 2.95, 0.03882, 0.003523 + 0.0, 0.63, 3.0, 0.04182, 0.003743 + 0.0, 0.63, 3.05, 0.04479, 0.00396 + 0.0, 0.63, 3.1, 0.04773, 0.004175 + 0.0, 0.63, 3.15, 0.05064, 0.004386 + 0.0, 0.63, 3.2, 0.05351, 0.004595 + 0.0, 0.63, 3.25, 0.05635, 0.004801 + 0.0, 0.63, 3.3, 0.05915, 0.005004 + 0.0, 0.63, 3.35, 0.06192, 0.005203 + 0.0, 0.63, 3.4, 0.06464, 0.005399 + 0.0, 0.63, 3.45, 0.06733, 0.005591 + 0.0, 0.63, 3.5, 0.06997, 0.00578 + 0.0, 0.63, 3.55, 0.07256, 0.005964 + 0.0, 0.63, 3.6, 0.07512, 0.006145 + 0.0, 0.63, 3.65, 0.07762, 0.006322 + 0.0, 0.63, 3.7, 0.08008, 0.006494 + 0.0, 0.63, 3.75, 0.08248, 0.006662 + 0.0, 0.63, 3.8, 0.08483, 0.006826 + 0.0, 0.63, 3.85, 0.08713, 0.006985 + 0.0, 0.63, 3.9, 0.08938, 0.00714 + 0.0, 0.63, 3.95, 0.09157, 0.007289 + 0.0, 0.63, 4.0, 0.0937, 0.007434 + 0.0, 0.63, 4.05, 0.09532, 0.007546 + 0.0, 0.63, 4.1, 0.09692, 0.007654 + 0.0, 0.63, 4.15, 0.09847, 0.007758 + 0.0, 0.63, 4.2, 0.1, 0.00786 + 0.0, 0.63, 4.25, 0.1015, 0.007958 + 0.0, 0.63, 4.3, 0.103, 0.008053 + 0.0, 0.63, 4.35, 0.1044, 0.008144 + 0.0, 0.63, 4.4, 0.1058, 0.008233 + 0.0, 0.63, 4.45, 0.1072, 0.008319 + 0.0, 0.63, 4.5, 0.1086, 0.008402 + 0.0, 0.63, 4.55, 0.11, 0.008482 + 0.0, 0.63, 4.6, 0.1113, 0.00856 + 0.0, 0.63, 4.65, 0.1126, 0.008635 + 0.0, 0.63, 4.7, 0.1139, 0.008707 + 0.0, 0.63, 4.75, 0.1152, 0.008778 + 0.0, 0.63, 4.8, 0.1165, 0.008845 + 0.0, 0.63, 4.85, 0.1178, 0.008911 + 0.0, 0.63, 4.9, 0.1191, 0.008975 + 0.0, 0.63, 4.95, 0.1204, 0.009037 + 0.0, 0.63, 5.0, 0.1217, 0.009096 + 0.0, 0.63, 5.05, 0.123, 0.009183 + 0.0, 0.63, 5.1, 0.1243, 0.009267 + 0.0, 0.63, 5.15, 0.1256, 0.009349 + 0.0, 0.63, 5.2, 0.1269, 0.009428 + 0.0, 0.63, 5.25, 0.1282, 0.009503 + 0.0, 0.63, 5.3, 0.1296, 0.009576 + 0.0, 0.63, 5.35, 0.1309, 0.009644 + 0.0, 0.63, 5.4, 0.1323, 0.009708 + 0.0, 0.63, 5.45, 0.1336, 0.009768 + 0.0, 0.63, 5.5, 0.135, 0.009823 + 0.0, 0.63, 5.55, 0.1364, 0.009872 + 0.0, 0.63, 5.6, 0.1378, 0.009916 + 0.0, 0.63, 5.65, 0.1392, 0.009954 + 0.0, 0.63, 5.7, 0.1406, 0.009986 + 0.0, 0.63, 5.75, 0.142, 0.01001 + 0.0, 0.63, 5.8, 0.1435, 0.01003 + 0.0, 0.63, 5.85, 0.145, 0.01004 + 0.0, 0.63, 5.9, 0.1465, 0.01004 + 0.0, 0.63, 5.95, 0.148, 0.01004 + 0.0, 0.63, 6.0, 0.1496, 0.01003 + 0.0, 0.63, 6.05, 0.1515, 0.009924 + 0.0, 0.63, 6.1, 0.1534, 0.009809 + 0.0, 0.63, 6.15, 0.1554, 0.009681 + 0.0, 0.63, 6.2, 0.1574, 0.009542 + 0.0, 0.63, 6.25, 0.1594, 0.009391 + 0.0, 0.63, 6.3, 0.1615, 0.009229 + 0.0, 0.63, 6.35, 0.1636, 0.009056 + 0.0, 0.63, 6.4, 0.1657, 0.008872 + 0.0, 0.63, 6.45, 0.1679, 0.008678 + 0.0, 0.63, 6.5, 0.1701, 0.008473 + 0.0, 0.63, 6.55, 0.1724, 0.008258 + 0.0, 0.63, 6.6, 0.1746, 0.008034 + 0.0, 0.63, 6.65, 0.1769, 0.0078 + 0.0, 0.63, 6.7, 0.1793, 0.007557 + 0.0, 0.63, 6.75, 0.1816, 0.007305 + 0.0, 0.63, 6.8, 0.184, 0.007044 + 0.0, 0.63, 6.85, 0.1864, 0.006775 + 0.0, 0.63, 6.9, 0.1888, 0.006498 + 0.0, 0.63, 6.95, 0.1913, 0.006212 + 0.0, 0.63, 7.0, 0.1938, 0.005919 + 0.0, 0.63, 7.05, 0.1963, 0.005619 + 0.0, 0.63, 7.1, 0.1988, 0.005312 + 0.0, 0.63, 7.15, 0.2014, 0.004997 + 0.0, 0.63, 7.2, 0.2039, 0.004676 + 0.0, 0.63, 7.25, 0.2065, 0.004349 + 0.0, 0.63, 7.3, 0.2091, 0.004016 + 0.0, 0.63, 7.35, 0.2117, 0.003677 + 0.0, 0.63, 7.4, 0.2144, 0.003332 + 0.0, 0.63, 7.45, 0.217, 0.002982 + 0.0, 0.63, 7.5, 0.2197, 0.002626 + 0.0, 0.63, 7.55, 0.2224, 0.002267 + 0.0, 0.63, 7.6, 0.2251, 0.001902 + 0.0, 0.63, 7.65, 0.2278, 0.001533 + 0.0, 0.63, 7.7, 0.2305, 0.001161 + 0.0, 0.63, 7.75, 0.2332, 0.0007842 + 0.0, 0.63, 7.8, 0.2359, 0.0004042 + 0.0, 0.63, 7.85, 0.2387, 2.1e-05 + 0.0, 0.63, 7.9, 0.2414, -0.0003652 + 0.0, 0.63, 7.95, 0.2442, -0.000754 + 0.0, 0.63, 8.0, 0.2469, -0.001145 + 0.0, 0.63, 8.05, 0.2494, -0.001473 + 0.0, 0.63, 8.1, 0.252, -0.001803 + 0.0, 0.63, 8.15, 0.2545, -0.002135 + 0.0, 0.63, 8.2, 0.2571, -0.002469 + 0.0, 0.63, 8.25, 0.2596, -0.002805 + 0.0, 0.63, 8.3, 0.2622, -0.003144 + 0.0, 0.63, 8.35, 0.2648, -0.003484 + 0.0, 0.63, 8.4, 0.2673, -0.003827 + 0.0, 0.63, 8.45, 0.2699, -0.004172 + 0.0, 0.63, 8.5, 0.2725, -0.004519 + 0.0, 0.63, 8.55, 0.275, -0.004867 + 0.0, 0.63, 8.6, 0.2776, -0.005218 + 0.0, 0.63, 8.65, 0.2802, -0.005571 + 0.0, 0.63, 8.7, 0.2828, -0.005926 + 0.0, 0.63, 8.75, 0.2854, -0.006283 + 0.0, 0.63, 8.8, 0.288, -0.006642 + 0.0, 0.63, 8.85, 0.2905, -0.007003 + 0.0, 0.63, 8.9, 0.2931, -0.007366 + 0.0, 0.63, 8.95, 0.2957, -0.00773 + 0.0, 0.63, 9.0, 0.2983, -0.008097 + 0.0, 0.63, 9.05, 0.3009, -0.008466 + 0.0, 0.63, 9.1, 0.3035, -0.008836 + 0.0, 0.63, 9.15, 0.3061, -0.009209 + 0.0, 0.63, 9.2, 0.3087, -0.009583 + 0.0, 0.63, 9.25, 0.3114, -0.009959 + 0.0, 0.63, 9.3, 0.314, -0.01034 + 0.0, 0.63, 9.35, 0.3166, -0.01072 + 0.0, 0.63, 9.4, 0.3192, -0.0111 + 0.0, 0.63, 9.45, 0.3218, -0.01148 + 0.0, 0.63, 9.5, 0.3244, -0.01187 + 0.0, 0.63, 9.55, 0.327, -0.01225 + 0.0, 0.63, 9.6, 0.3297, -0.01264 + 0.0, 0.63, 9.65, 0.3323, -0.01303 + 0.0, 0.63, 9.7, 0.3349, -0.01343 + 0.0, 0.63, 9.75, 0.3375, -0.01382 + 0.0, 0.63, 9.8, 0.3401, -0.01422 + 0.0, 0.63, 9.85, 0.3428, -0.01461 + 0.0, 0.63, 9.9, 0.3454, -0.01501 + 0.0, 0.63, 9.95, 0.348, -0.01541 + 0.0, 0.63, 10.0, 0.3506, -0.01582 + 0.0, 0.63, 10.05, 0.3532, -0.01625 + 0.0, 0.63, 10.1, 0.3559, -0.01669 + 0.0, 0.63, 10.15, 0.3585, -0.01713 + 0.0, 0.63, 10.2, 0.3611, -0.01757 + 0.0, 0.63, 10.25, 0.3637, -0.01802 + 0.0, 0.63, 10.3, 0.3663, -0.01846 + 0.0, 0.63, 10.35, 0.3689, -0.0189 + 0.0, 0.63, 10.4, 0.3715, -0.01935 + 0.0, 0.63, 10.45, 0.3741, -0.01979 + 0.0, 0.63, 10.5, 0.3767, -0.02024 + 0.0, 0.63, 10.55, 0.3793, -0.02068 + 0.0, 0.63, 10.6, 0.382, -0.02113 + 0.0, 0.63, 10.65, 0.3846, -0.02158 + 0.0, 0.63, 10.7, 0.3872, -0.02202 + 0.0, 0.63, 10.75, 0.3898, -0.02247 + 0.0, 0.63, 10.8, 0.3924, -0.02291 + 0.0, 0.63, 10.85, 0.395, -0.02336 + 0.0, 0.63, 10.9, 0.3976, -0.0238 + 0.0, 0.63, 10.95, 0.4002, -0.02425 + 0.0, 0.63, 11.0, 0.4028, -0.02469 + 0.0, 0.63, 11.05, 0.4054, -0.02513 + 0.0, 0.63, 11.1, 0.4081, -0.02557 + 0.0, 0.63, 11.15, 0.4107, -0.02601 + 0.0, 0.63, 11.2, 0.4133, -0.02645 + 0.0, 0.63, 11.25, 0.4159, -0.02688 + 0.0, 0.63, 11.3, 0.4185, -0.02732 + 0.0, 0.63, 11.35, 0.4211, -0.02775 + 0.0, 0.63, 11.4, 0.4237, -0.02818 + 0.0, 0.63, 11.45, 0.4263, -0.02861 + 0.0, 0.63, 11.5, 0.4289, -0.02903 + 0.0, 0.63, 11.55, 0.4315, -0.02946 + 0.0, 0.63, 11.6, 0.4341, -0.02988 + 0.0, 0.63, 11.65, 0.4367, -0.0303 + 0.0, 0.63, 11.7, 0.4393, -0.03071 + 0.0, 0.63, 11.75, 0.4419, -0.03112 + 0.0, 0.63, 11.8, 0.4445, -0.03153 + 0.0, 0.63, 11.85, 0.4471, -0.03194 + 0.0, 0.63, 11.9, 0.4498, -0.03234 + 0.0, 0.63, 11.95, 0.4524, -0.03274 + 0.0, 0.63, 12.0, 0.455, -0.03313 + 0.0, 0.63, 12.05, 0.4576, -0.03353 + 0.0, 0.63, 12.1, 0.4602, -0.03391 + 0.0, 0.63, 12.15, 0.4628, -0.0343 + 0.0, 0.63, 12.2, 0.4653, -0.03468 + 0.0, 0.63, 12.25, 0.4679, -0.03505 + 0.0, 0.63, 12.3, 0.4705, -0.03542 + 0.0, 0.63, 12.35, 0.4731, -0.03579 + 0.0, 0.63, 12.4, 0.4757, -0.03615 + 0.0, 0.63, 12.45, 0.4783, -0.0365 + 0.0, 0.63, 12.5, 0.4809, -0.03686 + 0.0, 0.63, 12.55, 0.4835, -0.0372 + 0.0, 0.63, 12.6, 0.4861, -0.03754 + 0.0, 0.63, 12.65, 0.4887, -0.03788 + 0.0, 0.63, 12.7, 0.4913, -0.03821 + 0.0, 0.63, 12.75, 0.4939, -0.03853 + 0.0, 0.63, 12.8, 0.4964, -0.03885 + 0.0, 0.63, 12.85, 0.499, -0.03916 + 0.0, 0.63, 12.9, 0.5016, -0.03947 + 0.0, 0.63, 12.95, 0.5042, -0.03977 + 0.0, 0.63, 13.0, 0.5068, -0.04006 + 0.0, 0.63, 13.05, 0.5094, -0.04035 + 0.0, 0.63, 13.1, 0.5119, -0.04063 + 0.0, 0.63, 13.15, 0.5145, -0.0409 + 0.0, 0.63, 13.2, 0.5171, -0.04117 + 0.0, 0.63, 13.25, 0.5197, -0.04143 + 0.0, 0.63, 13.3, 0.5222, -0.04168 + 0.0, 0.63, 13.35, 0.5248, -0.04193 + 0.0, 0.63, 13.4, 0.5274, -0.04216 + 0.0, 0.63, 13.45, 0.5299, -0.04239 + 0.0, 0.63, 13.5, 0.5325, -0.04262 + 0.0, 0.63, 13.55, 0.5351, -0.04283 + 0.0, 0.63, 13.6, 0.5376, -0.04304 + 0.0, 0.63, 13.65, 0.5402, -0.04323 + 0.0, 0.63, 13.7, 0.5428, -0.04342 + 0.0, 0.63, 13.75, 0.5453, -0.0436 + 0.0, 0.63, 13.8, 0.5479, -0.04378 + 0.0, 0.63, 13.85, 0.5504, -0.04394 + 0.0, 0.63, 13.9, 0.553, -0.0441 + 0.0, 0.63, 13.95, 0.5555, -0.04424 + 0.0, 0.63, 14.0, 0.5581, -0.04438 + 0.0, 0.63, 14.05, 0.5606, -0.04451 + 0.0, 0.63, 14.1, 0.5632, -0.04463 + 0.0, 0.63, 14.15, 0.5657, -0.04474 + 0.0, 0.63, 14.2, 0.5683, -0.04484 + 0.0, 0.63, 14.25, 0.5708, -0.04493 + 0.0, 0.63, 14.3, 0.5733, -0.04501 + 0.0, 0.63, 14.35, 0.5759, -0.04507 + 0.0, 0.63, 14.4, 0.5784, -0.04513 + 0.0, 0.63, 14.45, 0.5809, -0.04518 + 0.0, 0.63, 14.5, 0.5835, -0.04522 + 0.0, 0.63, 14.55, 0.586, -0.04525 + 0.0, 0.63, 14.6, 0.5885, -0.04527 + 0.0, 0.63, 14.65, 0.591, -0.04527 + 0.0, 0.63, 14.7, 0.5936, -0.04527 + 0.0, 0.63, 14.75, 0.5961, -0.04525 + 0.0, 0.63, 14.8, 0.5986, -0.04523 + 0.0, 0.63, 14.85, 0.6011, -0.04519 + 0.0, 0.63, 14.9, 0.6036, -0.04514 + 0.0, 0.63, 14.95, 0.6061, -0.04508 + 0.0, 0.63, 15.0, 0.6086, -0.045 + 0.0, 0.63, 15.05, 0.6111, -0.04492 + 0.0, 0.68, 0.0, -0.149, 0.002105 + 0.0, 0.68, 0.05, -0.1462, 0.002124 + 0.0, 0.68, 0.1, -0.1434, 0.002142 + 0.0, 0.68, 0.15, -0.1406, 0.002161 + 0.0, 0.68, 0.2, -0.1377, 0.00218 + 0.0, 0.68, 0.25, -0.1349, 0.002198 + 0.0, 0.68, 0.3, -0.132, 0.002216 + 0.0, 0.68, 0.35, -0.1291, 0.002234 + 0.0, 0.68, 0.4, -0.1263, 0.002252 + 0.0, 0.68, 0.45, -0.1233, 0.00227 + 0.0, 0.68, 0.5, -0.1204, 0.002288 + 0.0, 0.68, 0.55, -0.1175, 0.002306 + 0.0, 0.68, 0.6, -0.1146, 0.002324 + 0.0, 0.68, 0.65, -0.1116, 0.002341 + 0.0, 0.68, 0.7, -0.1086, 0.002359 + 0.0, 0.68, 0.75, -0.1057, 0.002377 + 0.0, 0.68, 0.8, -0.1027, 0.002396 + 0.0, 0.68, 0.85, -0.09969, 0.002414 + 0.0, 0.68, 0.9, -0.09668, 0.002432 + 0.0, 0.68, 0.95, -0.09367, 0.002451 + 0.0, 0.68, 1.0, -0.09065, 0.00247 + 0.0, 0.68, 1.05, -0.08762, 0.002489 + 0.0, 0.68, 1.1, -0.08458, 0.002508 + 0.0, 0.68, 1.15, -0.08154, 0.002528 + 0.0, 0.68, 1.2, -0.07849, 0.002548 + 0.0, 0.68, 1.25, -0.07543, 0.002568 + 0.0, 0.68, 1.3, -0.07237, 0.002588 + 0.0, 0.68, 1.35, -0.0693, 0.002609 + 0.0, 0.68, 1.4, -0.06622, 0.002631 + 0.0, 0.68, 1.45, -0.06314, 0.002652 + 0.0, 0.68, 1.5, -0.06006, 0.002674 + 0.0, 0.68, 1.55, -0.05697, 0.002697 + 0.0, 0.68, 1.6, -0.05388, 0.00272 + 0.0, 0.68, 1.65, -0.05078, 0.002744 + 0.0, 0.68, 1.7, -0.04768, 0.002768 + 0.0, 0.68, 1.75, -0.04458, 0.002792 + 0.0, 0.68, 1.8, -0.04148, 0.002818 + 0.0, 0.68, 1.85, -0.03837, 0.002844 + 0.0, 0.68, 1.9, -0.03527, 0.00287 + 0.0, 0.68, 1.95, -0.03216, 0.002897 + 0.0, 0.68, 2.0, -0.02905, 0.002925 + 0.0, 0.68, 2.05, -0.02595, 0.002954 + 0.0, 0.68, 2.1, -0.02284, 0.002983 + 0.0, 0.68, 2.15, -0.01973, 0.003013 + 0.0, 0.68, 2.2, -0.01663, 0.003044 + 0.0, 0.68, 2.25, -0.01353, 0.003075 + 0.0, 0.68, 2.3, -0.01043, 0.003108 + 0.0, 0.68, 2.35, -0.007328, 0.003141 + 0.0, 0.68, 2.4, -0.004233, 0.003175 + 0.0, 0.68, 2.45, -0.001141, 0.00321 + 0.0, 0.68, 2.5, 0.001948, 0.003246 + 0.0, 0.68, 2.55, 0.005033, 0.003283 + 0.0, 0.68, 2.6, 0.008112, 0.003321 + 0.0, 0.68, 2.65, 0.01119, 0.003359 + 0.0, 0.68, 2.7, 0.01426, 0.003399 + 0.0, 0.68, 2.75, 0.01732, 0.00344 + 0.0, 0.68, 2.8, 0.02038, 0.003482 + 0.0, 0.68, 2.85, 0.02343, 0.003525 + 0.0, 0.68, 2.9, 0.02648, 0.003569 + 0.0, 0.68, 2.95, 0.02951, 0.003614 + 0.0, 0.68, 3.0, 0.03254, 0.00366 + 0.0, 0.68, 3.05, 0.03556, 0.003708 + 0.0, 0.68, 3.1, 0.03858, 0.003757 + 0.0, 0.68, 3.15, 0.04158, 0.003806 + 0.0, 0.68, 3.2, 0.04457, 0.003858 + 0.0, 0.68, 3.25, 0.04756, 0.00391 + 0.0, 0.68, 3.3, 0.05053, 0.003964 + 0.0, 0.68, 3.35, 0.0535, 0.004019 + 0.0, 0.68, 3.4, 0.05645, 0.004075 + 0.0, 0.68, 3.45, 0.05939, 0.004133 + 0.0, 0.68, 3.5, 0.06232, 0.004192 + 0.0, 0.68, 3.55, 0.06524, 0.004253 + 0.0, 0.68, 3.6, 0.06814, 0.004315 + 0.0, 0.68, 3.65, 0.07103, 0.004378 + 0.0, 0.68, 3.7, 0.07391, 0.004443 + 0.0, 0.68, 3.75, 0.07677, 0.00451 + 0.0, 0.68, 3.8, 0.07962, 0.004577 + 0.0, 0.68, 3.85, 0.08246, 0.004647 + 0.0, 0.68, 3.9, 0.08528, 0.004718 + 0.0, 0.68, 3.95, 0.08808, 0.004791 + 0.0, 0.68, 4.0, 0.09087, 0.004865 + 0.0, 0.68, 4.05, 0.09352, 0.004932 + 0.0, 0.68, 4.1, 0.09617, 0.005001 + 0.0, 0.68, 4.15, 0.0988, 0.005073 + 0.0, 0.68, 4.2, 0.1014, 0.005147 + 0.0, 0.68, 4.25, 0.104, 0.005223 + 0.0, 0.68, 4.3, 0.1067, 0.005302 + 0.0, 0.68, 4.35, 0.1093, 0.005384 + 0.0, 0.68, 4.4, 0.1118, 0.005468 + 0.0, 0.68, 4.45, 0.1144, 0.005555 + 0.0, 0.68, 4.5, 0.117, 0.005645 + 0.0, 0.68, 4.55, 0.1196, 0.005739 + 0.0, 0.68, 4.6, 0.1222, 0.005835 + 0.0, 0.68, 4.65, 0.1247, 0.005935 + 0.0, 0.68, 4.7, 0.1273, 0.006037 + 0.0, 0.68, 4.75, 0.1299, 0.006144 + 0.0, 0.68, 4.8, 0.1324, 0.006253 + 0.0, 0.68, 4.85, 0.135, 0.006367 + 0.0, 0.68, 4.9, 0.1376, 0.006484 + 0.0, 0.68, 4.95, 0.1401, 0.006605 + 0.0, 0.68, 5.0, 0.1427, 0.006729 + 0.0, 0.68, 5.05, 0.1453, 0.006884 + 0.0, 0.68, 5.1, 0.148, 0.007042 + 0.0, 0.68, 5.15, 0.1507, 0.007204 + 0.0, 0.68, 5.2, 0.1533, 0.007368 + 0.0, 0.68, 5.25, 0.156, 0.007536 + 0.0, 0.68, 5.3, 0.1586, 0.007706 + 0.0, 0.68, 5.35, 0.1613, 0.007878 + 0.0, 0.68, 5.4, 0.1639, 0.008052 + 0.0, 0.68, 5.45, 0.1665, 0.008228 + 0.0, 0.68, 5.5, 0.1691, 0.008404 + 0.0, 0.68, 5.55, 0.1717, 0.008582 + 0.0, 0.68, 5.6, 0.1743, 0.008761 + 0.0, 0.68, 5.65, 0.1769, 0.00894 + 0.0, 0.68, 5.7, 0.1795, 0.009119 + 0.0, 0.68, 5.75, 0.182, 0.009298 + 0.0, 0.68, 5.8, 0.1845, 0.009476 + 0.0, 0.68, 5.85, 0.1871, 0.009654 + 0.0, 0.68, 5.9, 0.1895, 0.00983 + 0.0, 0.68, 5.95, 0.192, 0.01001 + 0.0, 0.68, 6.0, 0.1945, 0.01018 + 0.0, 0.68, 6.05, 0.1966, 0.01029 + 0.0, 0.68, 6.1, 0.1987, 0.0104 + 0.0, 0.68, 6.15, 0.2008, 0.0105 + 0.0, 0.68, 6.2, 0.2028, 0.0106 + 0.0, 0.68, 6.25, 0.2048, 0.0107 + 0.0, 0.68, 6.3, 0.2068, 0.01079 + 0.0, 0.68, 6.35, 0.2087, 0.01088 + 0.0, 0.68, 6.4, 0.2106, 0.01096 + 0.0, 0.68, 6.45, 0.2125, 0.01104 + 0.0, 0.68, 6.5, 0.2143, 0.01111 + 0.0, 0.68, 6.55, 0.2161, 0.01119 + 0.0, 0.68, 6.6, 0.2179, 0.01125 + 0.0, 0.68, 6.65, 0.2197, 0.01132 + 0.0, 0.68, 6.7, 0.2214, 0.01138 + 0.0, 0.68, 6.75, 0.2231, 0.01144 + 0.0, 0.68, 6.8, 0.2248, 0.0115 + 0.0, 0.68, 6.85, 0.2265, 0.01155 + 0.0, 0.68, 6.9, 0.2282, 0.0116 + 0.0, 0.68, 6.95, 0.2298, 0.01165 + 0.0, 0.68, 7.0, 0.2314, 0.0117 + 0.0, 0.68, 7.05, 0.233, 0.01174 + 0.0, 0.68, 7.1, 0.2346, 0.01178 + 0.0, 0.68, 7.15, 0.2361, 0.01182 + 0.0, 0.68, 7.2, 0.2377, 0.01186 + 0.0, 0.68, 7.25, 0.2392, 0.0119 + 0.0, 0.68, 7.3, 0.2407, 0.01193 + 0.0, 0.68, 7.35, 0.2422, 0.01197 + 0.0, 0.68, 7.4, 0.2437, 0.012 + 0.0, 0.68, 7.45, 0.2452, 0.01203 + 0.0, 0.68, 7.5, 0.2467, 0.01206 + 0.0, 0.68, 7.55, 0.2481, 0.01209 + 0.0, 0.68, 7.6, 0.2496, 0.01212 + 0.0, 0.68, 7.65, 0.251, 0.01214 + 0.0, 0.68, 7.7, 0.2525, 0.01217 + 0.0, 0.68, 7.75, 0.2539, 0.0122 + 0.0, 0.68, 7.8, 0.2554, 0.01222 + 0.0, 0.68, 7.85, 0.2568, 0.01225 + 0.0, 0.68, 7.9, 0.2582, 0.01228 + 0.0, 0.68, 7.95, 0.2597, 0.0123 + 0.0, 0.68, 8.0, 0.2611, 0.01233 + 0.0, 0.68, 8.05, 0.2628, 0.01239 + 0.0, 0.68, 8.1, 0.2645, 0.01246 + 0.0, 0.68, 8.15, 0.2662, 0.01252 + 0.0, 0.68, 8.2, 0.2678, 0.01259 + 0.0, 0.68, 8.25, 0.2695, 0.01265 + 0.0, 0.68, 8.3, 0.2712, 0.01272 + 0.0, 0.68, 8.35, 0.2729, 0.01278 + 0.0, 0.68, 8.4, 0.2746, 0.01285 + 0.0, 0.68, 8.45, 0.2763, 0.01292 + 0.0, 0.68, 8.5, 0.278, 0.01298 + 0.0, 0.68, 8.55, 0.2797, 0.01305 + 0.0, 0.68, 8.6, 0.2814, 0.01312 + 0.0, 0.68, 8.65, 0.2831, 0.01319 + 0.0, 0.68, 8.7, 0.2848, 0.01325 + 0.0, 0.68, 8.75, 0.2865, 0.01332 + 0.0, 0.68, 8.8, 0.2882, 0.01339 + 0.0, 0.68, 8.85, 0.2899, 0.01346 + 0.0, 0.68, 8.9, 0.2916, 0.01353 + 0.0, 0.68, 8.95, 0.2933, 0.0136 + 0.0, 0.68, 9.0, 0.295, 0.01367 + 0.0, 0.68, 9.05, 0.2967, 0.01374 + 0.0, 0.68, 9.1, 0.2984, 0.01381 + 0.0, 0.68, 9.15, 0.3001, 0.01388 + 0.0, 0.68, 9.2, 0.3018, 0.01395 + 0.0, 0.68, 9.25, 0.3036, 0.01402 + 0.0, 0.68, 9.3, 0.3053, 0.01409 + 0.0, 0.68, 9.35, 0.307, 0.01417 + 0.0, 0.68, 9.4, 0.3087, 0.01424 + 0.0, 0.68, 9.45, 0.3104, 0.01431 + 0.0, 0.68, 9.5, 0.3121, 0.01438 + 0.0, 0.68, 9.55, 0.3138, 0.01445 + 0.0, 0.68, 9.6, 0.3155, 0.01453 + 0.0, 0.68, 9.65, 0.3172, 0.0146 + 0.0, 0.68, 9.7, 0.3189, 0.01467 + 0.0, 0.68, 9.75, 0.3206, 0.01474 + 0.0, 0.68, 9.8, 0.3223, 0.01482 + 0.0, 0.68, 9.85, 0.3241, 0.01489 + 0.0, 0.68, 9.9, 0.3258, 0.01496 + 0.0, 0.68, 9.95, 0.3275, 0.01504 + 0.0, 0.68, 10.0, 0.3292, 0.01511 + 0.0, 0.68, 10.05, 0.3309, 0.01518 + 0.0, 0.68, 10.1, 0.3326, 0.01525 + 0.0, 0.68, 10.15, 0.3343, 0.01532 + 0.0, 0.68, 10.2, 0.336, 0.01538 + 0.0, 0.68, 10.25, 0.3377, 0.01545 + 0.0, 0.68, 10.3, 0.3394, 0.01552 + 0.0, 0.68, 10.35, 0.3411, 0.01559 + 0.0, 0.68, 10.4, 0.3428, 0.01566 + 0.0, 0.68, 10.45, 0.3445, 0.01573 + 0.0, 0.68, 10.5, 0.3462, 0.0158 + 0.0, 0.68, 10.55, 0.348, 0.01587 + 0.0, 0.68, 10.6, 0.3497, 0.01594 + 0.0, 0.68, 10.65, 0.3514, 0.01601 + 0.0, 0.68, 10.7, 0.3531, 0.01608 + 0.0, 0.68, 10.75, 0.3548, 0.01615 + 0.0, 0.68, 10.8, 0.3565, 0.01622 + 0.0, 0.68, 10.85, 0.3582, 0.0163 + 0.0, 0.68, 10.9, 0.3599, 0.01637 + 0.0, 0.68, 10.95, 0.3616, 0.01644 + 0.0, 0.68, 11.0, 0.3633, 0.01651 + 0.0, 0.68, 11.05, 0.365, 0.01659 + 0.0, 0.68, 11.1, 0.3667, 0.01666 + 0.0, 0.68, 11.15, 0.3684, 0.01674 + 0.0, 0.68, 11.2, 0.3701, 0.01681 + 0.0, 0.68, 11.25, 0.3718, 0.01689 + 0.0, 0.68, 11.3, 0.3736, 0.01696 + 0.0, 0.68, 11.35, 0.3753, 0.01704 + 0.0, 0.68, 11.4, 0.377, 0.01711 + 0.0, 0.68, 11.45, 0.3787, 0.01719 + 0.0, 0.68, 11.5, 0.3804, 0.01727 + 0.0, 0.68, 11.55, 0.3821, 0.01735 + 0.0, 0.68, 11.6, 0.3838, 0.01743 + 0.0, 0.68, 11.65, 0.3855, 0.01751 + 0.0, 0.68, 11.7, 0.3872, 0.01759 + 0.0, 0.68, 11.75, 0.3889, 0.01767 + 0.0, 0.68, 11.8, 0.3906, 0.01775 + 0.0, 0.68, 11.85, 0.3923, 0.01783 + 0.0, 0.68, 11.9, 0.394, 0.01791 + 0.0, 0.68, 11.95, 0.3957, 0.018 + 0.0, 0.68, 12.0, 0.3974, 0.01808 + 0.0, 0.68, 12.05, 0.3991, 0.01816 + 0.0, 0.68, 12.1, 0.4008, 0.01825 + 0.0, 0.68, 12.15, 0.4026, 0.01834 + 0.0, 0.68, 12.2, 0.4043, 0.01842 + 0.0, 0.68, 12.25, 0.406, 0.01851 + 0.0, 0.68, 12.3, 0.4077, 0.0186 + 0.0, 0.68, 12.35, 0.4094, 0.01869 + 0.0, 0.68, 12.4, 0.4111, 0.01878 + 0.0, 0.68, 12.45, 0.4128, 0.01887 + 0.0, 0.68, 12.5, 0.4145, 0.01896 + 0.0, 0.68, 12.55, 0.4162, 0.01905 + 0.0, 0.68, 12.6, 0.4179, 0.01914 + 0.0, 0.68, 12.65, 0.4196, 0.01924 + 0.0, 0.68, 12.7, 0.4213, 0.01933 + 0.0, 0.68, 12.75, 0.423, 0.01943 + 0.0, 0.68, 12.8, 0.4247, 0.01953 + 0.0, 0.68, 12.85, 0.4264, 0.01962 + 0.0, 0.68, 12.9, 0.4281, 0.01972 + 0.0, 0.68, 12.95, 0.4298, 0.01982 + 0.0, 0.68, 13.0, 0.4315, 0.01992 + 0.0, 0.68, 13.05, 0.4332, 0.02002 + 0.0, 0.68, 13.1, 0.4349, 0.02013 + 0.0, 0.68, 13.15, 0.4366, 0.02023 + 0.0, 0.68, 13.2, 0.4383, 0.02033 + 0.0, 0.68, 13.25, 0.44, 0.02044 + 0.0, 0.68, 13.3, 0.4417, 0.02055 + 0.0, 0.68, 13.35, 0.4434, 0.02065 + 0.0, 0.68, 13.4, 0.4451, 0.02076 + 0.0, 0.68, 13.45, 0.4468, 0.02087 + 0.0, 0.68, 13.5, 0.4485, 0.02098 + 0.0, 0.68, 13.55, 0.4502, 0.0211 + 0.0, 0.68, 13.6, 0.4519, 0.02121 + 0.0, 0.68, 13.65, 0.4536, 0.02132 + 0.0, 0.68, 13.7, 0.4553, 0.02144 + 0.0, 0.68, 13.75, 0.457, 0.02156 + 0.0, 0.68, 13.8, 0.4587, 0.02167 + 0.0, 0.68, 13.85, 0.4604, 0.02179 + 0.0, 0.68, 13.9, 0.4621, 0.02191 + 0.0, 0.68, 13.95, 0.4638, 0.02203 + 0.0, 0.68, 14.0, 0.4655, 0.02216 + 0.0, 0.68, 14.05, 0.4671, 0.02228 + 0.0, 0.68, 14.1, 0.4688, 0.02241 + 0.0, 0.68, 14.15, 0.4705, 0.02253 + 0.0, 0.68, 14.2, 0.4722, 0.02266 + 0.0, 0.68, 14.25, 0.4739, 0.02279 + 0.0, 0.68, 14.3, 0.4756, 0.02292 + 0.0, 0.68, 14.35, 0.4773, 0.02305 + 0.0, 0.68, 14.4, 0.479, 0.02319 + 0.0, 0.68, 14.45, 0.4807, 0.02332 + 0.0, 0.68, 14.5, 0.4824, 0.02346 + 0.0, 0.68, 14.55, 0.4841, 0.0236 + 0.0, 0.68, 14.6, 0.4857, 0.02374 + 0.0, 0.68, 14.65, 0.4874, 0.02388 + 0.0, 0.68, 14.7, 0.4891, 0.02402 + 0.0, 0.68, 14.75, 0.4908, 0.02416 + 0.0, 0.68, 14.8, 0.4925, 0.02431 + 0.0, 0.68, 14.85, 0.4942, 0.02445 + 0.0, 0.68, 14.9, 0.4959, 0.0246 + 0.0, 0.68, 14.95, 0.4976, 0.02475 + 0.0, 0.68, 15.0, 0.4992, 0.0249 + 0.0, 0.68, 15.05, 0.5009, 0.02505 + 0.0, 0.73, 0.0, -0.1665, 0.009316 + 0.0, 0.73, 0.05, -0.1631, 0.00926 + 0.0, 0.73, 0.1, -0.1596, 0.0092 + 0.0, 0.73, 0.15, -0.1562, 0.009137 + 0.0, 0.73, 0.2, -0.1528, 0.00907 + 0.0, 0.73, 0.25, -0.1494, 0.009001 + 0.0, 0.73, 0.3, -0.146, 0.008929 + 0.0, 0.73, 0.35, -0.1426, 0.008854 + 0.0, 0.73, 0.4, -0.1392, 0.008776 + 0.0, 0.73, 0.45, -0.1359, 0.008696 + 0.0, 0.73, 0.5, -0.1325, 0.008613 + 0.0, 0.73, 0.55, -0.1292, 0.008528 + 0.0, 0.73, 0.6, -0.1258, 0.00844 + 0.0, 0.73, 0.65, -0.1225, 0.008351 + 0.0, 0.73, 0.7, -0.1192, 0.008259 + 0.0, 0.73, 0.75, -0.1159, 0.008166 + 0.0, 0.73, 0.8, -0.1126, 0.008071 + 0.0, 0.73, 0.85, -0.1093, 0.007974 + 0.0, 0.73, 0.9, -0.106, 0.007876 + 0.0, 0.73, 0.95, -0.1027, 0.007776 + 0.0, 0.73, 1.0, -0.09946, 0.007675 + 0.0, 0.73, 1.05, -0.09619, 0.007573 + 0.0, 0.73, 1.1, -0.09293, 0.007469 + 0.0, 0.73, 1.15, -0.08968, 0.007365 + 0.0, 0.73, 1.2, -0.08644, 0.00726 + 0.0, 0.73, 1.25, -0.08319, 0.007155 + 0.0, 0.73, 1.3, -0.07996, 0.007048 + 0.0, 0.73, 1.35, -0.07673, 0.006941 + 0.0, 0.73, 1.4, -0.0735, 0.006834 + 0.0, 0.73, 1.45, -0.07028, 0.006727 + 0.0, 0.73, 1.5, -0.06707, 0.006619 + 0.0, 0.73, 1.55, -0.06385, 0.006512 + 0.0, 0.73, 1.6, -0.06065, 0.006405 + 0.0, 0.73, 1.65, -0.05744, 0.006297 + 0.0, 0.73, 1.7, -0.05424, 0.006191 + 0.0, 0.73, 1.75, -0.05104, 0.006084 + 0.0, 0.73, 1.8, -0.04785, 0.005978 + 0.0, 0.73, 1.85, -0.04466, 0.005873 + 0.0, 0.73, 1.9, -0.04147, 0.005769 + 0.0, 0.73, 1.95, -0.03828, 0.005666 + 0.0, 0.73, 2.0, -0.03509, 0.005563 + 0.0, 0.73, 2.05, -0.03191, 0.005462 + 0.0, 0.73, 2.1, -0.02873, 0.005362 + 0.0, 0.73, 2.15, -0.02554, 0.005264 + 0.0, 0.73, 2.2, -0.02236, 0.005167 + 0.0, 0.73, 2.25, -0.01918, 0.005072 + 0.0, 0.73, 2.3, -0.016, 0.004978 + 0.0, 0.73, 2.35, -0.01282, 0.004886 + 0.0, 0.73, 2.4, -0.009643, 0.004797 + 0.0, 0.73, 2.45, -0.006462, 0.004709 + 0.0, 0.73, 2.5, -0.003281, 0.004624 + 0.0, 0.73, 2.55, -9.861e-05, 0.00454 + 0.0, 0.73, 2.6, 0.003085, 0.00446 + 0.0, 0.73, 2.65, 0.00627, 0.004382 + 0.0, 0.73, 2.7, 0.009456, 0.004306 + 0.0, 0.73, 2.75, 0.01264, 0.004234 + 0.0, 0.73, 2.8, 0.01584, 0.004164 + 0.0, 0.73, 2.85, 0.01903, 0.004098 + 0.0, 0.73, 2.9, 0.02222, 0.004034 + 0.0, 0.73, 2.95, 0.02542, 0.003974 + 0.0, 0.73, 3.0, 0.02863, 0.003917 + 0.0, 0.73, 3.05, 0.03183, 0.003864 + 0.0, 0.73, 3.1, 0.03504, 0.003814 + 0.0, 0.73, 3.15, 0.03826, 0.003768 + 0.0, 0.73, 3.2, 0.04147, 0.003726 + 0.0, 0.73, 3.25, 0.0447, 0.003688 + 0.0, 0.73, 3.3, 0.04792, 0.003654 + 0.0, 0.73, 3.35, 0.05116, 0.003624 + 0.0, 0.73, 3.4, 0.05439, 0.003598 + 0.0, 0.73, 3.45, 0.05764, 0.003577 + 0.0, 0.73, 3.5, 0.06089, 0.003561 + 0.0, 0.73, 3.55, 0.06414, 0.003549 + 0.0, 0.73, 3.6, 0.0674, 0.003542 + 0.0, 0.73, 3.65, 0.07067, 0.00354 + 0.0, 0.73, 3.7, 0.07395, 0.003543 + 0.0, 0.73, 3.75, 0.07723, 0.003551 + 0.0, 0.73, 3.8, 0.08052, 0.003564 + 0.0, 0.73, 3.85, 0.08381, 0.003582 + 0.0, 0.73, 3.9, 0.08712, 0.003607 + 0.0, 0.73, 3.95, 0.09043, 0.003636 + 0.0, 0.73, 4.0, 0.09375, 0.003672 + 0.0, 0.73, 4.05, 0.09715, 0.003718 + 0.0, 0.73, 4.1, 0.1006, 0.00377 + 0.0, 0.73, 4.15, 0.104, 0.003827 + 0.0, 0.73, 4.2, 0.1074, 0.00389 + 0.0, 0.73, 4.25, 0.1108, 0.00396 + 0.0, 0.73, 4.3, 0.1142, 0.004035 + 0.0, 0.73, 4.35, 0.1176, 0.004116 + 0.0, 0.73, 4.4, 0.1211, 0.004204 + 0.0, 0.73, 4.45, 0.1245, 0.004297 + 0.0, 0.73, 4.5, 0.1279, 0.004397 + 0.0, 0.73, 4.55, 0.1314, 0.004504 + 0.0, 0.73, 4.6, 0.1348, 0.004617 + 0.0, 0.73, 4.65, 0.1382, 0.004736 + 0.0, 0.73, 4.7, 0.1417, 0.004862 + 0.0, 0.73, 4.75, 0.1451, 0.004995 + 0.0, 0.73, 4.8, 0.1486, 0.005135 + 0.0, 0.73, 4.85, 0.152, 0.005281 + 0.0, 0.73, 4.9, 0.1555, 0.005435 + 0.0, 0.73, 4.95, 0.1589, 0.005595 + 0.0, 0.73, 5.0, 0.1623, 0.005763 + 0.0, 0.73, 5.05, 0.166, 0.005959 + 0.0, 0.73, 5.1, 0.1696, 0.006163 + 0.0, 0.73, 5.15, 0.1732, 0.006373 + 0.0, 0.73, 5.2, 0.1767, 0.00659 + 0.0, 0.73, 5.25, 0.1803, 0.006813 + 0.0, 0.73, 5.3, 0.1839, 0.007041 + 0.0, 0.73, 5.35, 0.1874, 0.007276 + 0.0, 0.73, 5.4, 0.191, 0.007516 + 0.0, 0.73, 5.45, 0.1945, 0.007761 + 0.0, 0.73, 5.5, 0.198, 0.008011 + 0.0, 0.73, 5.55, 0.2014, 0.008266 + 0.0, 0.73, 5.6, 0.2049, 0.008526 + 0.0, 0.73, 5.65, 0.2083, 0.008789 + 0.0, 0.73, 5.7, 0.2116, 0.009057 + 0.0, 0.73, 5.75, 0.215, 0.009328 + 0.0, 0.73, 5.8, 0.2183, 0.009603 + 0.0, 0.73, 5.85, 0.2215, 0.009881 + 0.0, 0.73, 5.9, 0.2247, 0.01016 + 0.0, 0.73, 5.95, 0.2279, 0.01045 + 0.0, 0.73, 6.0, 0.231, 0.01073 + 0.0, 0.73, 6.05, 0.2334, 0.01098 + 0.0, 0.73, 6.1, 0.2357, 0.01123 + 0.0, 0.73, 6.15, 0.2379, 0.01148 + 0.0, 0.73, 6.2, 0.2401, 0.01173 + 0.0, 0.73, 6.25, 0.2421, 0.01198 + 0.0, 0.73, 6.3, 0.2441, 0.01223 + 0.0, 0.73, 6.35, 0.2461, 0.01249 + 0.0, 0.73, 6.4, 0.2479, 0.01274 + 0.0, 0.73, 6.45, 0.2497, 0.01299 + 0.0, 0.73, 6.5, 0.2514, 0.01325 + 0.0, 0.73, 6.55, 0.2531, 0.0135 + 0.0, 0.73, 6.6, 0.2547, 0.01376 + 0.0, 0.73, 6.65, 0.2563, 0.01401 + 0.0, 0.73, 6.7, 0.2577, 0.01427 + 0.0, 0.73, 6.75, 0.2592, 0.01453 + 0.0, 0.73, 6.8, 0.2605, 0.01479 + 0.0, 0.73, 6.85, 0.2619, 0.01505 + 0.0, 0.73, 6.9, 0.2631, 0.01531 + 0.0, 0.73, 6.95, 0.2644, 0.01557 + 0.0, 0.73, 7.0, 0.2655, 0.01583 + 0.0, 0.73, 7.05, 0.2667, 0.0161 + 0.0, 0.73, 7.1, 0.2678, 0.01636 + 0.0, 0.73, 7.15, 0.2688, 0.01663 + 0.0, 0.73, 7.2, 0.2699, 0.0169 + 0.0, 0.73, 7.25, 0.2708, 0.01717 + 0.0, 0.73, 7.3, 0.2718, 0.01744 + 0.0, 0.73, 7.35, 0.2727, 0.01771 + 0.0, 0.73, 7.4, 0.2736, 0.01798 + 0.0, 0.73, 7.45, 0.2745, 0.01826 + 0.0, 0.73, 7.5, 0.2753, 0.01854 + 0.0, 0.73, 7.55, 0.2762, 0.01881 + 0.0, 0.73, 7.6, 0.277, 0.01909 + 0.0, 0.73, 7.65, 0.2777, 0.01938 + 0.0, 0.73, 7.7, 0.2785, 0.01966 + 0.0, 0.73, 7.75, 0.2793, 0.01994 + 0.0, 0.73, 7.8, 0.28, 0.02023 + 0.0, 0.73, 7.85, 0.2808, 0.02052 + 0.0, 0.73, 7.9, 0.2815, 0.02081 + 0.0, 0.73, 7.95, 0.2822, 0.0211 + 0.0, 0.73, 8.0, 0.2829, 0.02139 + 0.0, 0.73, 8.05, 0.2842, 0.02171 + 0.0, 0.73, 8.1, 0.2855, 0.02202 + 0.0, 0.73, 8.15, 0.2868, 0.02234 + 0.0, 0.73, 8.2, 0.288, 0.02265 + 0.0, 0.73, 8.25, 0.2893, 0.02297 + 0.0, 0.73, 8.3, 0.2906, 0.0233 + 0.0, 0.73, 8.35, 0.2918, 0.02362 + 0.0, 0.73, 8.4, 0.2931, 0.02394 + 0.0, 0.73, 8.45, 0.2944, 0.02427 + 0.0, 0.73, 8.5, 0.2956, 0.0246 + 0.0, 0.73, 8.55, 0.2969, 0.02493 + 0.0, 0.73, 8.6, 0.2982, 0.02526 + 0.0, 0.73, 8.65, 0.2994, 0.0256 + 0.0, 0.73, 8.7, 0.3007, 0.02593 + 0.0, 0.73, 8.75, 0.302, 0.02627 + 0.0, 0.73, 8.8, 0.3032, 0.02661 + 0.0, 0.73, 8.85, 0.3045, 0.02695 + 0.0, 0.73, 8.9, 0.3058, 0.02729 + 0.0, 0.73, 8.95, 0.307, 0.02764 + 0.0, 0.73, 9.0, 0.3083, 0.02798 + 0.0, 0.73, 9.05, 0.3096, 0.02833 + 0.0, 0.73, 9.1, 0.3108, 0.02868 + 0.0, 0.73, 9.15, 0.3121, 0.02903 + 0.0, 0.73, 9.2, 0.3133, 0.02938 + 0.0, 0.73, 9.25, 0.3146, 0.02973 + 0.0, 0.73, 9.3, 0.3159, 0.03009 + 0.0, 0.73, 9.35, 0.3171, 0.03045 + 0.0, 0.73, 9.4, 0.3184, 0.0308 + 0.0, 0.73, 9.45, 0.3196, 0.03116 + 0.0, 0.73, 9.5, 0.3209, 0.03152 + 0.0, 0.73, 9.55, 0.3221, 0.03188 + 0.0, 0.73, 9.6, 0.3234, 0.03225 + 0.0, 0.73, 9.65, 0.3247, 0.03261 + 0.0, 0.73, 9.7, 0.3259, 0.03298 + 0.0, 0.73, 9.75, 0.3272, 0.03335 + 0.0, 0.73, 9.8, 0.3284, 0.03371 + 0.0, 0.73, 9.85, 0.3297, 0.03408 + 0.0, 0.73, 9.9, 0.3309, 0.03445 + 0.0, 0.73, 9.95, 0.3322, 0.03483 + 0.0, 0.73, 10.0, 0.3335, 0.0352 + 0.0, 0.73, 10.05, 0.3347, 0.03559 + 0.0, 0.73, 10.1, 0.336, 0.03597 + 0.0, 0.73, 10.15, 0.3372, 0.03636 + 0.0, 0.73, 10.2, 0.3385, 0.03675 + 0.0, 0.73, 10.25, 0.3398, 0.03714 + 0.0, 0.73, 10.3, 0.341, 0.03753 + 0.0, 0.73, 10.35, 0.3423, 0.03792 + 0.0, 0.73, 10.4, 0.3435, 0.03831 + 0.0, 0.73, 10.45, 0.3448, 0.03871 + 0.0, 0.73, 10.5, 0.346, 0.0391 + 0.0, 0.73, 10.55, 0.3473, 0.03949 + 0.0, 0.73, 10.6, 0.3486, 0.03989 + 0.0, 0.73, 10.65, 0.3498, 0.04028 + 0.0, 0.73, 10.7, 0.3511, 0.04068 + 0.0, 0.73, 10.75, 0.3523, 0.04107 + 0.0, 0.73, 10.8, 0.3536, 0.04147 + 0.0, 0.73, 10.85, 0.3549, 0.04187 + 0.0, 0.73, 10.9, 0.3561, 0.04226 + 0.0, 0.73, 10.95, 0.3574, 0.04266 + 0.0, 0.73, 11.0, 0.3586, 0.04305 + 0.0, 0.73, 11.05, 0.3599, 0.04345 + 0.0, 0.73, 11.1, 0.3612, 0.04385 + 0.0, 0.73, 11.15, 0.3624, 0.04424 + 0.0, 0.73, 11.2, 0.3637, 0.04464 + 0.0, 0.73, 11.25, 0.3649, 0.04503 + 0.0, 0.73, 11.3, 0.3662, 0.04543 + 0.0, 0.73, 11.35, 0.3674, 0.04582 + 0.0, 0.73, 11.4, 0.3687, 0.04622 + 0.0, 0.73, 11.45, 0.37, 0.04661 + 0.0, 0.73, 11.5, 0.3712, 0.04701 + 0.0, 0.73, 11.55, 0.3725, 0.0474 + 0.0, 0.73, 11.6, 0.3737, 0.04779 + 0.0, 0.73, 11.65, 0.375, 0.04818 + 0.0, 0.73, 11.7, 0.3763, 0.04857 + 0.0, 0.73, 11.75, 0.3775, 0.04896 + 0.0, 0.73, 11.8, 0.3788, 0.04935 + 0.0, 0.73, 11.85, 0.38, 0.04974 + 0.0, 0.73, 11.9, 0.3813, 0.05012 + 0.0, 0.73, 11.95, 0.3826, 0.05051 + 0.0, 0.73, 12.0, 0.3838, 0.05089 + 0.0, 0.73, 12.05, 0.3851, 0.05127 + 0.0, 0.73, 12.1, 0.3863, 0.05166 + 0.0, 0.73, 12.15, 0.3876, 0.05204 + 0.0, 0.73, 12.2, 0.3889, 0.05241 + 0.0, 0.73, 12.25, 0.3901, 0.05279 + 0.0, 0.73, 12.3, 0.3914, 0.05317 + 0.0, 0.73, 12.35, 0.3926, 0.05354 + 0.0, 0.73, 12.4, 0.3939, 0.05391 + 0.0, 0.73, 12.45, 0.3952, 0.05428 + 0.0, 0.73, 12.5, 0.3964, 0.05465 + 0.0, 0.73, 12.55, 0.3977, 0.05502 + 0.0, 0.73, 12.6, 0.3989, 0.05538 + 0.0, 0.73, 12.65, 0.4002, 0.05575 + 0.0, 0.73, 12.7, 0.4015, 0.05611 + 0.0, 0.73, 12.75, 0.4027, 0.05646 + 0.0, 0.73, 12.8, 0.404, 0.05682 + 0.0, 0.73, 12.85, 0.4053, 0.05718 + 0.0, 0.73, 12.9, 0.4065, 0.05753 + 0.0, 0.73, 12.95, 0.4078, 0.05788 + 0.0, 0.73, 13.0, 0.4091, 0.05822 + 0.0, 0.73, 13.05, 0.4103, 0.05857 + 0.0, 0.73, 13.1, 0.4116, 0.05891 + 0.0, 0.73, 13.15, 0.4128, 0.05925 + 0.0, 0.73, 13.2, 0.4141, 0.05959 + 0.0, 0.73, 13.25, 0.4154, 0.05992 + 0.0, 0.73, 13.3, 0.4166, 0.06025 + 0.0, 0.73, 13.35, 0.4179, 0.06058 + 0.0, 0.73, 13.4, 0.4192, 0.06091 + 0.0, 0.73, 13.45, 0.4204, 0.06123 + 0.0, 0.73, 13.5, 0.4217, 0.06155 + 0.0, 0.73, 13.55, 0.423, 0.06186 + 0.0, 0.73, 13.6, 0.4242, 0.06218 + 0.0, 0.73, 13.65, 0.4255, 0.06249 + 0.0, 0.73, 13.7, 0.4268, 0.06279 + 0.0, 0.73, 13.75, 0.428, 0.0631 + 0.0, 0.73, 13.8, 0.4293, 0.0634 + 0.0, 0.73, 13.85, 0.4306, 0.06369 + 0.0, 0.73, 13.9, 0.4318, 0.06399 + 0.0, 0.73, 13.95, 0.4331, 0.06428 + 0.0, 0.73, 14.0, 0.4344, 0.06456 + 0.0, 0.73, 14.05, 0.4357, 0.06484 + 0.0, 0.73, 14.1, 0.4369, 0.06512 + 0.0, 0.73, 14.15, 0.4382, 0.0654 + 0.0, 0.73, 14.2, 0.4395, 0.06567 + 0.0, 0.73, 14.25, 0.4407, 0.06593 + 0.0, 0.73, 14.3, 0.442, 0.0662 + 0.0, 0.73, 14.35, 0.4433, 0.06645 + 0.0, 0.73, 14.4, 0.4445, 0.06671 + 0.0, 0.73, 14.45, 0.4458, 0.06696 + 0.0, 0.73, 14.5, 0.4471, 0.06721 + 0.0, 0.73, 14.55, 0.4484, 0.06745 + 0.0, 0.73, 14.6, 0.4496, 0.06768 + 0.0, 0.73, 14.65, 0.4509, 0.06792 + 0.0, 0.73, 14.7, 0.4522, 0.06815 + 0.0, 0.73, 14.75, 0.4535, 0.06837 + 0.0, 0.73, 14.8, 0.4547, 0.06859 + 0.0, 0.73, 14.85, 0.456, 0.0688 + 0.0, 0.73, 14.9, 0.4573, 0.06901 + 0.0, 0.73, 14.95, 0.4586, 0.06922 + 0.0, 0.73, 15.0, 0.4598, 0.06942 + 0.0, 0.73, 15.05, 0.4611, 0.06961 + 0.0, 0.78, 0.0, -0.1839, 0.009891 + 0.0, 0.78, 0.05, -0.1801, 0.009843 + 0.0, 0.78, 0.1, -0.1763, 0.00979 + 0.0, 0.78, 0.15, -0.1726, 0.009734 + 0.0, 0.78, 0.2, -0.1688, 0.009675 + 0.0, 0.78, 0.25, -0.1651, 0.009612 + 0.0, 0.78, 0.3, -0.1614, 0.009546 + 0.0, 0.78, 0.35, -0.1577, 0.009477 + 0.0, 0.78, 0.4, -0.154, 0.009404 + 0.0, 0.78, 0.45, -0.1503, 0.009329 + 0.0, 0.78, 0.5, -0.1466, 0.009251 + 0.0, 0.78, 0.55, -0.1429, 0.00917 + 0.0, 0.78, 0.6, -0.1392, 0.009087 + 0.0, 0.78, 0.65, -0.1356, 0.009001 + 0.0, 0.78, 0.7, -0.1319, 0.008914 + 0.0, 0.78, 0.75, -0.1282, 0.008824 + 0.0, 0.78, 0.8, -0.1246, 0.008731 + 0.0, 0.78, 0.85, -0.1209, 0.008637 + 0.0, 0.78, 0.9, -0.1173, 0.008542 + 0.0, 0.78, 0.95, -0.1137, 0.008444 + 0.0, 0.78, 1.0, -0.11, 0.008346 + 0.0, 0.78, 1.05, -0.1064, 0.008245 + 0.0, 0.78, 1.1, -0.1028, 0.008144 + 0.0, 0.78, 1.15, -0.0992, 0.008041 + 0.0, 0.78, 1.2, -0.0956, 0.007937 + 0.0, 0.78, 1.25, -0.092, 0.007833 + 0.0, 0.78, 1.3, -0.0884, 0.007728 + 0.0, 0.78, 1.35, -0.08481, 0.007622 + 0.0, 0.78, 1.4, -0.08122, 0.007515 + 0.0, 0.78, 1.45, -0.07764, 0.007409 + 0.0, 0.78, 1.5, -0.07406, 0.007301 + 0.0, 0.78, 1.55, -0.07049, 0.007194 + 0.0, 0.78, 1.6, -0.06691, 0.007087 + 0.0, 0.78, 1.65, -0.06334, 0.00698 + 0.0, 0.78, 1.7, -0.05978, 0.006874 + 0.0, 0.78, 1.75, -0.05621, 0.006767 + 0.0, 0.78, 1.8, -0.05265, 0.006662 + 0.0, 0.78, 1.85, -0.04909, 0.006556 + 0.0, 0.78, 1.9, -0.04554, 0.006452 + 0.0, 0.78, 1.95, -0.04198, 0.006349 + 0.0, 0.78, 2.0, -0.03843, 0.006246 + 0.0, 0.78, 2.05, -0.03488, 0.006145 + 0.0, 0.78, 2.1, -0.03133, 0.006045 + 0.0, 0.78, 2.15, -0.02778, 0.005946 + 0.0, 0.78, 2.2, -0.02423, 0.005849 + 0.0, 0.78, 2.25, -0.02069, 0.005754 + 0.0, 0.78, 2.3, -0.01714, 0.00566 + 0.0, 0.78, 2.35, -0.01359, 0.005569 + 0.0, 0.78, 2.4, -0.01005, 0.005479 + 0.0, 0.78, 2.45, -0.006503, 0.005392 + 0.0, 0.78, 2.5, -0.002957, 0.005307 + 0.0, 0.78, 2.55, 0.0005893, 0.005224 + 0.0, 0.78, 2.6, 0.004136, 0.005144 + 0.0, 0.78, 2.65, 0.007683, 0.005067 + 0.0, 0.78, 2.7, 0.01123, 0.004992 + 0.0, 0.78, 2.75, 0.01478, 0.00492 + 0.0, 0.78, 2.8, 0.01833, 0.004852 + 0.0, 0.78, 2.85, 0.02188, 0.004786 + 0.0, 0.78, 2.9, 0.02544, 0.004724 + 0.0, 0.78, 2.95, 0.029, 0.004666 + 0.0, 0.78, 3.0, 0.03255, 0.00461 + 0.0, 0.78, 3.05, 0.03611, 0.004559 + 0.0, 0.78, 3.1, 0.03968, 0.004512 + 0.0, 0.78, 3.15, 0.04324, 0.004468 + 0.0, 0.78, 3.2, 0.04681, 0.004429 + 0.0, 0.78, 3.25, 0.05038, 0.004393 + 0.0, 0.78, 3.3, 0.05396, 0.004362 + 0.0, 0.78, 3.35, 0.05754, 0.004336 + 0.0, 0.78, 3.4, 0.06112, 0.004314 + 0.0, 0.78, 3.45, 0.06471, 0.004297 + 0.0, 0.78, 3.5, 0.0683, 0.004284 + 0.0, 0.78, 3.55, 0.07189, 0.004277 + 0.0, 0.78, 3.6, 0.07549, 0.004275 + 0.0, 0.78, 3.65, 0.07909, 0.004278 + 0.0, 0.78, 3.7, 0.0827, 0.004286 + 0.0, 0.78, 3.75, 0.08632, 0.0043 + 0.0, 0.78, 3.8, 0.08994, 0.004319 + 0.0, 0.78, 3.85, 0.09356, 0.004345 + 0.0, 0.78, 3.9, 0.09719, 0.004376 + 0.0, 0.78, 3.95, 0.1008, 0.004413 + 0.0, 0.78, 4.0, 0.1045, 0.004456 + 0.0, 0.78, 4.05, 0.1082, 0.004515 + 0.0, 0.78, 4.1, 0.1119, 0.004581 + 0.0, 0.78, 4.15, 0.1156, 0.004652 + 0.0, 0.78, 4.2, 0.1193, 0.004729 + 0.0, 0.78, 4.25, 0.123, 0.004812 + 0.0, 0.78, 4.3, 0.1267, 0.004901 + 0.0, 0.78, 4.35, 0.1304, 0.004996 + 0.0, 0.78, 4.4, 0.1341, 0.005097 + 0.0, 0.78, 4.45, 0.1379, 0.005204 + 0.0, 0.78, 4.5, 0.1416, 0.005317 + 0.0, 0.78, 4.55, 0.1453, 0.005437 + 0.0, 0.78, 4.6, 0.149, 0.005563 + 0.0, 0.78, 4.65, 0.1528, 0.005695 + 0.0, 0.78, 4.7, 0.1565, 0.005833 + 0.0, 0.78, 4.75, 0.1602, 0.005978 + 0.0, 0.78, 4.8, 0.1639, 0.006129 + 0.0, 0.78, 4.85, 0.1677, 0.006287 + 0.0, 0.78, 4.9, 0.1714, 0.006451 + 0.0, 0.78, 4.95, 0.1751, 0.006622 + 0.0, 0.78, 5.0, 0.1789, 0.0068 + 0.0, 0.78, 5.05, 0.1828, 0.007 + 0.0, 0.78, 5.1, 0.1867, 0.007207 + 0.0, 0.78, 5.15, 0.1906, 0.00742 + 0.0, 0.78, 5.2, 0.1945, 0.00764 + 0.0, 0.78, 5.25, 0.1983, 0.007865 + 0.0, 0.78, 5.3, 0.2022, 0.008096 + 0.0, 0.78, 5.35, 0.2061, 0.008333 + 0.0, 0.78, 5.4, 0.2099, 0.008574 + 0.0, 0.78, 5.45, 0.2137, 0.008821 + 0.0, 0.78, 5.5, 0.2175, 0.009073 + 0.0, 0.78, 5.55, 0.2212, 0.00933 + 0.0, 0.78, 5.6, 0.2249, 0.009591 + 0.0, 0.78, 5.65, 0.2286, 0.009857 + 0.0, 0.78, 5.7, 0.2323, 0.01013 + 0.0, 0.78, 5.75, 0.2359, 0.0104 + 0.0, 0.78, 5.8, 0.2395, 0.01068 + 0.0, 0.78, 5.85, 0.243, 0.01096 + 0.0, 0.78, 5.9, 0.2465, 0.01124 + 0.0, 0.78, 5.95, 0.2499, 0.01153 + 0.0, 0.78, 6.0, 0.2533, 0.01182 + 0.0, 0.78, 6.05, 0.2559, 0.01209 + 0.0, 0.78, 6.1, 0.2585, 0.01236 + 0.0, 0.78, 6.15, 0.261, 0.01262 + 0.0, 0.78, 6.2, 0.2634, 0.0129 + 0.0, 0.78, 6.25, 0.2657, 0.01317 + 0.0, 0.78, 6.3, 0.2679, 0.01344 + 0.0, 0.78, 6.35, 0.2701, 0.01371 + 0.0, 0.78, 6.4, 0.2722, 0.01399 + 0.0, 0.78, 6.45, 0.2742, 0.01427 + 0.0, 0.78, 6.5, 0.2761, 0.01455 + 0.0, 0.78, 6.55, 0.278, 0.01483 + 0.0, 0.78, 6.6, 0.2798, 0.01511 + 0.0, 0.78, 6.65, 0.2816, 0.0154 + 0.0, 0.78, 6.7, 0.2833, 0.01568 + 0.0, 0.78, 6.75, 0.2849, 0.01597 + 0.0, 0.78, 6.8, 0.2865, 0.01626 + 0.0, 0.78, 6.85, 0.288, 0.01655 + 0.0, 0.78, 6.9, 0.2895, 0.01684 + 0.0, 0.78, 6.95, 0.2909, 0.01714 + 0.0, 0.78, 7.0, 0.2923, 0.01743 + 0.0, 0.78, 7.05, 0.2937, 0.01773 + 0.0, 0.78, 7.1, 0.2949, 0.01803 + 0.0, 0.78, 7.15, 0.2962, 0.01833 + 0.0, 0.78, 7.2, 0.2974, 0.01863 + 0.0, 0.78, 7.25, 0.2986, 0.01894 + 0.0, 0.78, 7.3, 0.2997, 0.01924 + 0.0, 0.78, 7.35, 0.3009, 0.01955 + 0.0, 0.78, 7.4, 0.3019, 0.01986 + 0.0, 0.78, 7.45, 0.303, 0.02017 + 0.0, 0.78, 7.5, 0.304, 0.02049 + 0.0, 0.78, 7.55, 0.305, 0.0208 + 0.0, 0.78, 7.6, 0.306, 0.02112 + 0.0, 0.78, 7.65, 0.307, 0.02144 + 0.0, 0.78, 7.7, 0.308, 0.02176 + 0.0, 0.78, 7.75, 0.3089, 0.02209 + 0.0, 0.78, 7.8, 0.3098, 0.02241 + 0.0, 0.78, 7.85, 0.3108, 0.02274 + 0.0, 0.78, 7.9, 0.3117, 0.02307 + 0.0, 0.78, 7.95, 0.3126, 0.0234 + 0.0, 0.78, 8.0, 0.3135, 0.02373 + 0.0, 0.78, 8.05, 0.315, 0.02408 + 0.0, 0.78, 8.1, 0.3165, 0.02442 + 0.0, 0.78, 8.15, 0.3179, 0.02477 + 0.0, 0.78, 8.2, 0.3194, 0.02512 + 0.0, 0.78, 8.25, 0.3209, 0.02547 + 0.0, 0.78, 8.3, 0.3224, 0.02583 + 0.0, 0.78, 8.35, 0.3239, 0.02618 + 0.0, 0.78, 8.4, 0.3253, 0.02654 + 0.0, 0.78, 8.45, 0.3268, 0.0269 + 0.0, 0.78, 8.5, 0.3283, 0.02726 + 0.0, 0.78, 8.55, 0.3298, 0.02763 + 0.0, 0.78, 8.6, 0.3313, 0.02799 + 0.0, 0.78, 8.65, 0.3327, 0.02836 + 0.0, 0.78, 8.7, 0.3342, 0.02873 + 0.0, 0.78, 8.75, 0.3357, 0.0291 + 0.0, 0.78, 8.8, 0.3372, 0.02947 + 0.0, 0.78, 8.85, 0.3386, 0.02984 + 0.0, 0.78, 8.9, 0.3401, 0.03022 + 0.0, 0.78, 8.95, 0.3416, 0.0306 + 0.0, 0.78, 9.0, 0.3431, 0.03097 + 0.0, 0.78, 9.05, 0.3445, 0.03135 + 0.0, 0.78, 9.1, 0.346, 0.03174 + 0.0, 0.78, 9.15, 0.3475, 0.03212 + 0.0, 0.78, 9.2, 0.3489, 0.0325 + 0.0, 0.78, 9.25, 0.3504, 0.03289 + 0.0, 0.78, 9.3, 0.3519, 0.03328 + 0.0, 0.78, 9.35, 0.3534, 0.03367 + 0.0, 0.78, 9.4, 0.3548, 0.03406 + 0.0, 0.78, 9.45, 0.3563, 0.03445 + 0.0, 0.78, 9.5, 0.3578, 0.03484 + 0.0, 0.78, 9.55, 0.3592, 0.03524 + 0.0, 0.78, 9.6, 0.3607, 0.03563 + 0.0, 0.78, 9.65, 0.3622, 0.03603 + 0.0, 0.78, 9.7, 0.3636, 0.03643 + 0.0, 0.78, 9.75, 0.3651, 0.03683 + 0.0, 0.78, 9.8, 0.3666, 0.03723 + 0.0, 0.78, 9.85, 0.368, 0.03763 + 0.0, 0.78, 9.9, 0.3695, 0.03804 + 0.0, 0.78, 9.95, 0.371, 0.03844 + 0.0, 0.78, 10.0, 0.3725, 0.03885 + 0.0, 0.78, 10.05, 0.3739, 0.03926 + 0.0, 0.78, 10.1, 0.3754, 0.03968 + 0.0, 0.78, 10.15, 0.3769, 0.04011 + 0.0, 0.78, 10.2, 0.3783, 0.04053 + 0.0, 0.78, 10.25, 0.3798, 0.04095 + 0.0, 0.78, 10.3, 0.3813, 0.04137 + 0.0, 0.78, 10.35, 0.3827, 0.0418 + 0.0, 0.78, 10.4, 0.3842, 0.04222 + 0.0, 0.78, 10.45, 0.3857, 0.04265 + 0.0, 0.78, 10.5, 0.3872, 0.04307 + 0.0, 0.78, 10.55, 0.3886, 0.0435 + 0.0, 0.78, 10.6, 0.3901, 0.04393 + 0.0, 0.78, 10.65, 0.3916, 0.04436 + 0.0, 0.78, 10.7, 0.393, 0.04478 + 0.0, 0.78, 10.75, 0.3945, 0.04521 + 0.0, 0.78, 10.8, 0.396, 0.04564 + 0.0, 0.78, 10.85, 0.3974, 0.04607 + 0.0, 0.78, 10.9, 0.3989, 0.0465 + 0.0, 0.78, 10.95, 0.4004, 0.04692 + 0.0, 0.78, 11.0, 0.4019, 0.04735 + 0.0, 0.78, 11.05, 0.4033, 0.04778 + 0.0, 0.78, 11.1, 0.4048, 0.04821 + 0.0, 0.78, 11.15, 0.4063, 0.04863 + 0.0, 0.78, 11.2, 0.4077, 0.04906 + 0.0, 0.78, 11.25, 0.4092, 0.04949 + 0.0, 0.78, 11.3, 0.4107, 0.04991 + 0.0, 0.78, 11.35, 0.4121, 0.05034 + 0.0, 0.78, 11.4, 0.4136, 0.05076 + 0.0, 0.78, 11.45, 0.4151, 0.05119 + 0.0, 0.78, 11.5, 0.4166, 0.05161 + 0.0, 0.78, 11.55, 0.418, 0.05203 + 0.0, 0.78, 11.6, 0.4195, 0.05245 + 0.0, 0.78, 11.65, 0.421, 0.05288 + 0.0, 0.78, 11.7, 0.4224, 0.05329 + 0.0, 0.78, 11.75, 0.4239, 0.05371 + 0.0, 0.78, 11.8, 0.4254, 0.05413 + 0.0, 0.78, 11.85, 0.4269, 0.05455 + 0.0, 0.78, 11.9, 0.4283, 0.05496 + 0.0, 0.78, 11.95, 0.4298, 0.05538 + 0.0, 0.78, 12.0, 0.4313, 0.05579 + 0.0, 0.78, 12.05, 0.4327, 0.0562 + 0.0, 0.78, 12.1, 0.4342, 0.05661 + 0.0, 0.78, 12.15, 0.4357, 0.05701 + 0.0, 0.78, 12.2, 0.4372, 0.05742 + 0.0, 0.78, 12.25, 0.4386, 0.05782 + 0.0, 0.78, 12.3, 0.4401, 0.05823 + 0.0, 0.78, 12.35, 0.4416, 0.05863 + 0.0, 0.78, 12.4, 0.443, 0.05902 + 0.0, 0.78, 12.45, 0.4445, 0.05942 + 0.0, 0.78, 12.5, 0.446, 0.05981 + 0.0, 0.78, 12.55, 0.4475, 0.06021 + 0.0, 0.78, 12.6, 0.4489, 0.0606 + 0.0, 0.78, 12.65, 0.4504, 0.06098 + 0.0, 0.78, 12.7, 0.4519, 0.06137 + 0.0, 0.78, 12.75, 0.4533, 0.06175 + 0.0, 0.78, 12.8, 0.4548, 0.06213 + 0.0, 0.78, 12.85, 0.4563, 0.06251 + 0.0, 0.78, 12.9, 0.4578, 0.06289 + 0.0, 0.78, 12.95, 0.4592, 0.06326 + 0.0, 0.78, 13.0, 0.4607, 0.06363 + 0.0, 0.78, 13.05, 0.4622, 0.06399 + 0.0, 0.78, 13.1, 0.4637, 0.06436 + 0.0, 0.78, 13.15, 0.4651, 0.06472 + 0.0, 0.78, 13.2, 0.4666, 0.06508 + 0.0, 0.78, 13.25, 0.4681, 0.06543 + 0.0, 0.78, 13.3, 0.4696, 0.06579 + 0.0, 0.78, 13.35, 0.471, 0.06613 + 0.0, 0.78, 13.4, 0.4725, 0.06648 + 0.0, 0.78, 13.45, 0.474, 0.06682 + 0.0, 0.78, 13.5, 0.4755, 0.06716 + 0.0, 0.78, 13.55, 0.4769, 0.0675 + 0.0, 0.78, 13.6, 0.4784, 0.06783 + 0.0, 0.78, 13.65, 0.4799, 0.06816 + 0.0, 0.78, 13.7, 0.4814, 0.06848 + 0.0, 0.78, 13.75, 0.4828, 0.0688 + 0.0, 0.78, 13.8, 0.4843, 0.06912 + 0.0, 0.78, 13.85, 0.4858, 0.06943 + 0.0, 0.78, 13.9, 0.4873, 0.06974 + 0.0, 0.78, 13.95, 0.4888, 0.07005 + 0.0, 0.78, 14.0, 0.4902, 0.07035 + 0.0, 0.78, 14.05, 0.4917, 0.07064 + 0.0, 0.78, 14.1, 0.4932, 0.07094 + 0.0, 0.78, 14.15, 0.4947, 0.07123 + 0.0, 0.78, 14.2, 0.4961, 0.07151 + 0.0, 0.78, 14.25, 0.4976, 0.07179 + 0.0, 0.78, 14.3, 0.4991, 0.07207 + 0.0, 0.78, 14.35, 0.5006, 0.07234 + 0.0, 0.78, 14.4, 0.5021, 0.0726 + 0.0, 0.78, 14.45, 0.5035, 0.07287 + 0.0, 0.78, 14.5, 0.505, 0.07312 + 0.0, 0.78, 14.55, 0.5065, 0.07338 + 0.0, 0.78, 14.6, 0.508, 0.07362 + 0.0, 0.78, 14.65, 0.5095, 0.07387 + 0.0, 0.78, 14.7, 0.511, 0.0741 + 0.0, 0.78, 14.75, 0.5124, 0.07434 + 0.0, 0.78, 14.8, 0.5139, 0.07456 + 0.0, 0.78, 14.85, 0.5154, 0.07479 + 0.0, 0.78, 14.9, 0.5169, 0.075 + 0.0, 0.78, 14.95, 0.5184, 0.07521 + 0.0, 0.78, 15.0, 0.5199, 0.07542 + 0.0, 0.78, 15.05, 0.5213, 0.07562 + 0.0, 0.83, 0.0, -0.1999, 0.00292 + 0.0, 0.83, 0.05, -0.1962, 0.002976 + 0.0, 0.83, 0.1, -0.1925, 0.00303 + 0.0, 0.83, 0.15, -0.1888, 0.003083 + 0.0, 0.83, 0.2, -0.185, 0.003135 + 0.0, 0.83, 0.25, -0.1812, 0.003186 + 0.0, 0.83, 0.3, -0.1774, 0.003236 + 0.0, 0.83, 0.35, -0.1736, 0.003285 + 0.0, 0.83, 0.4, -0.1697, 0.003333 + 0.0, 0.83, 0.45, -0.1658, 0.00338 + 0.0, 0.83, 0.5, -0.1619, 0.003427 + 0.0, 0.83, 0.55, -0.158, 0.003473 + 0.0, 0.83, 0.6, -0.1541, 0.003518 + 0.0, 0.83, 0.65, -0.1501, 0.003562 + 0.0, 0.83, 0.7, -0.1461, 0.003606 + 0.0, 0.83, 0.75, -0.1421, 0.00365 + 0.0, 0.83, 0.8, -0.1381, 0.003693 + 0.0, 0.83, 0.85, -0.134, 0.003735 + 0.0, 0.83, 0.9, -0.13, 0.003777 + 0.0, 0.83, 0.95, -0.1259, 0.003819 + 0.0, 0.83, 1.0, -0.1218, 0.003861 + 0.0, 0.83, 1.05, -0.1177, 0.003902 + 0.0, 0.83, 1.1, -0.1136, 0.003943 + 0.0, 0.83, 1.15, -0.1095, 0.003984 + 0.0, 0.83, 1.2, -0.1053, 0.004025 + 0.0, 0.83, 1.25, -0.1012, 0.004066 + 0.0, 0.83, 1.3, -0.09699, 0.004106 + 0.0, 0.83, 1.35, -0.09281, 0.004147 + 0.0, 0.83, 1.4, -0.08862, 0.004188 + 0.0, 0.83, 1.45, -0.08443, 0.004229 + 0.0, 0.83, 1.5, -0.08022, 0.004271 + 0.0, 0.83, 1.55, -0.07601, 0.004312 + 0.0, 0.83, 1.6, -0.07179, 0.004354 + 0.0, 0.83, 1.65, -0.06757, 0.004396 + 0.0, 0.83, 1.7, -0.06334, 0.004439 + 0.0, 0.83, 1.75, -0.05911, 0.004482 + 0.0, 0.83, 1.8, -0.05487, 0.004526 + 0.0, 0.83, 1.85, -0.05063, 0.00457 + 0.0, 0.83, 1.9, -0.04639, 0.004615 + 0.0, 0.83, 1.95, -0.04214, 0.00466 + 0.0, 0.83, 2.0, -0.0379, 0.004706 + 0.0, 0.83, 2.05, -0.03365, 0.004753 + 0.0, 0.83, 2.1, -0.02941, 0.004801 + 0.0, 0.83, 2.15, -0.02516, 0.004849 + 0.0, 0.83, 2.2, -0.02092, 0.004899 + 0.0, 0.83, 2.25, -0.01668, 0.004949 + 0.0, 0.83, 2.3, -0.01244, 0.005 + 0.0, 0.83, 2.35, -0.008212, 0.005053 + 0.0, 0.83, 2.4, -0.003985, 0.005106 + 0.0, 0.83, 2.45, 0.0002371, 0.005161 + 0.0, 0.83, 2.5, 0.004453, 0.005216 + 0.0, 0.83, 2.55, 0.008662, 0.005273 + 0.0, 0.83, 2.6, 0.01286, 0.005332 + 0.0, 0.83, 2.65, 0.01706, 0.005391 + 0.0, 0.83, 2.7, 0.02124, 0.005452 + 0.0, 0.83, 2.75, 0.02541, 0.005515 + 0.0, 0.83, 2.8, 0.02958, 0.005578 + 0.0, 0.83, 2.85, 0.03373, 0.005644 + 0.0, 0.83, 2.9, 0.03787, 0.005711 + 0.0, 0.83, 2.95, 0.042, 0.00578 + 0.0, 0.83, 3.0, 0.04611, 0.00585 + 0.0, 0.83, 3.05, 0.05021, 0.005922 + 0.0, 0.83, 3.1, 0.0543, 0.005996 + 0.0, 0.83, 3.15, 0.05836, 0.006071 + 0.0, 0.83, 3.2, 0.06242, 0.006149 + 0.0, 0.83, 3.25, 0.06645, 0.006228 + 0.0, 0.83, 3.3, 0.07047, 0.00631 + 0.0, 0.83, 3.35, 0.07447, 0.006393 + 0.0, 0.83, 3.4, 0.07845, 0.006479 + 0.0, 0.83, 3.45, 0.08242, 0.006566 + 0.0, 0.83, 3.5, 0.08636, 0.006656 + 0.0, 0.83, 3.55, 0.09028, 0.006748 + 0.0, 0.83, 3.6, 0.09417, 0.006843 + 0.0, 0.83, 3.65, 0.09805, 0.006939 + 0.0, 0.83, 3.7, 0.1019, 0.007038 + 0.0, 0.83, 3.75, 0.1057, 0.00714 + 0.0, 0.83, 3.8, 0.1095, 0.007243 + 0.0, 0.83, 3.85, 0.1133, 0.00735 + 0.0, 0.83, 3.9, 0.1171, 0.007459 + 0.0, 0.83, 3.95, 0.1208, 0.00757 + 0.0, 0.83, 4.0, 0.1245, 0.007684 + 0.0, 0.83, 4.05, 0.128, 0.007809 + 0.0, 0.83, 4.1, 0.1314, 0.007935 + 0.0, 0.83, 4.15, 0.1349, 0.008064 + 0.0, 0.83, 4.2, 0.1383, 0.008195 + 0.0, 0.83, 4.25, 0.1417, 0.008328 + 0.0, 0.83, 4.3, 0.1451, 0.008464 + 0.0, 0.83, 4.35, 0.1485, 0.008602 + 0.0, 0.83, 4.4, 0.1519, 0.008742 + 0.0, 0.83, 4.45, 0.1552, 0.008885 + 0.0, 0.83, 4.5, 0.1586, 0.009029 + 0.0, 0.83, 4.55, 0.1619, 0.009177 + 0.0, 0.83, 4.6, 0.1652, 0.009326 + 0.0, 0.83, 4.65, 0.1685, 0.009478 + 0.0, 0.83, 4.7, 0.1718, 0.009632 + 0.0, 0.83, 4.75, 0.1751, 0.009788 + 0.0, 0.83, 4.8, 0.1784, 0.009946 + 0.0, 0.83, 4.85, 0.1817, 0.01011 + 0.0, 0.83, 4.9, 0.1849, 0.01027 + 0.0, 0.83, 4.95, 0.1882, 0.01044 + 0.0, 0.83, 5.0, 0.1915, 0.0106 + 0.0, 0.83, 5.05, 0.1948, 0.01078 + 0.0, 0.83, 5.1, 0.1981, 0.01096 + 0.0, 0.83, 5.15, 0.2015, 0.01114 + 0.0, 0.83, 5.2, 0.2048, 0.01132 + 0.0, 0.83, 5.25, 0.2081, 0.01151 + 0.0, 0.83, 5.3, 0.2114, 0.0117 + 0.0, 0.83, 5.35, 0.2147, 0.01188 + 0.0, 0.83, 5.4, 0.218, 0.01207 + 0.0, 0.83, 5.45, 0.2213, 0.01226 + 0.0, 0.83, 5.5, 0.2246, 0.01246 + 0.0, 0.83, 5.55, 0.2278, 0.01265 + 0.0, 0.83, 5.6, 0.2311, 0.01284 + 0.0, 0.83, 5.65, 0.2343, 0.01304 + 0.0, 0.83, 5.7, 0.2375, 0.01323 + 0.0, 0.83, 5.75, 0.2407, 0.01343 + 0.0, 0.83, 5.8, 0.2438, 0.01362 + 0.0, 0.83, 5.85, 0.247, 0.01382 + 0.0, 0.83, 5.9, 0.2501, 0.01402 + 0.0, 0.83, 5.95, 0.2532, 0.01421 + 0.0, 0.83, 6.0, 0.2563, 0.01441 + 0.0, 0.83, 6.05, 0.2591, 0.01458 + 0.0, 0.83, 6.1, 0.2619, 0.01475 + 0.0, 0.83, 6.15, 0.2647, 0.01493 + 0.0, 0.83, 6.2, 0.2674, 0.0151 + 0.0, 0.83, 6.25, 0.2701, 0.01526 + 0.0, 0.83, 6.3, 0.2728, 0.01543 + 0.0, 0.83, 6.35, 0.2754, 0.0156 + 0.0, 0.83, 6.4, 0.278, 0.01576 + 0.0, 0.83, 6.45, 0.2806, 0.01593 + 0.0, 0.83, 6.5, 0.2831, 0.01609 + 0.0, 0.83, 6.55, 0.2856, 0.01625 + 0.0, 0.83, 6.6, 0.2881, 0.01642 + 0.0, 0.83, 6.65, 0.2906, 0.01658 + 0.0, 0.83, 6.7, 0.2931, 0.01674 + 0.0, 0.83, 6.75, 0.2955, 0.0169 + 0.0, 0.83, 6.8, 0.2979, 0.01705 + 0.0, 0.83, 6.85, 0.3003, 0.01721 + 0.0, 0.83, 6.9, 0.3027, 0.01737 + 0.0, 0.83, 6.95, 0.305, 0.01753 + 0.0, 0.83, 7.0, 0.3074, 0.01768 + 0.0, 0.83, 7.05, 0.3097, 0.01784 + 0.0, 0.83, 7.1, 0.312, 0.01799 + 0.0, 0.83, 7.15, 0.3143, 0.01815 + 0.0, 0.83, 7.2, 0.3166, 0.0183 + 0.0, 0.83, 7.25, 0.3188, 0.01845 + 0.0, 0.83, 7.3, 0.3211, 0.01861 + 0.0, 0.83, 7.35, 0.3233, 0.01876 + 0.0, 0.83, 7.4, 0.3255, 0.01891 + 0.0, 0.83, 7.45, 0.3278, 0.01907 + 0.0, 0.83, 7.5, 0.33, 0.01922 + 0.0, 0.83, 7.55, 0.3322, 0.01937 + 0.0, 0.83, 7.6, 0.3344, 0.01952 + 0.0, 0.83, 7.65, 0.3366, 0.01967 + 0.0, 0.83, 7.7, 0.3387, 0.01983 + 0.0, 0.83, 7.75, 0.3409, 0.01998 + 0.0, 0.83, 7.8, 0.3431, 0.02013 + 0.0, 0.83, 7.85, 0.3453, 0.02028 + 0.0, 0.83, 7.9, 0.3475, 0.02044 + 0.0, 0.83, 7.95, 0.3496, 0.02059 + 0.0, 0.83, 8.0, 0.3518, 0.02074 + 0.0, 0.83, 8.05, 0.3542, 0.02091 + 0.0, 0.83, 8.1, 0.3567, 0.02107 + 0.0, 0.83, 8.15, 0.3591, 0.02124 + 0.0, 0.83, 8.2, 0.3615, 0.02141 + 0.0, 0.83, 8.25, 0.3639, 0.02157 + 0.0, 0.83, 8.3, 0.3664, 0.02174 + 0.0, 0.83, 8.35, 0.3688, 0.02191 + 0.0, 0.83, 8.4, 0.3712, 0.02208 + 0.0, 0.83, 8.45, 0.3737, 0.02225 + 0.0, 0.83, 8.5, 0.3761, 0.02241 + 0.0, 0.83, 8.55, 0.3785, 0.02258 + 0.0, 0.83, 8.6, 0.381, 0.02275 + 0.0, 0.83, 8.65, 0.3834, 0.02292 + 0.0, 0.83, 8.7, 0.3858, 0.02309 + 0.0, 0.83, 8.75, 0.3883, 0.02326 + 0.0, 0.83, 8.8, 0.3907, 0.02343 + 0.0, 0.83, 8.85, 0.3932, 0.0236 + 0.0, 0.83, 8.9, 0.3956, 0.02376 + 0.0, 0.83, 8.95, 0.398, 0.02393 + 0.0, 0.83, 9.0, 0.4005, 0.0241 + 0.0, 0.83, 9.05, 0.4029, 0.02427 + 0.0, 0.83, 9.1, 0.4054, 0.02444 + 0.0, 0.83, 9.15, 0.4078, 0.02461 + 0.0, 0.83, 9.2, 0.4103, 0.02478 + 0.0, 0.83, 9.25, 0.4127, 0.02495 + 0.0, 0.83, 9.3, 0.4152, 0.02512 + 0.0, 0.83, 9.35, 0.4176, 0.02529 + 0.0, 0.83, 9.4, 0.4201, 0.02546 + 0.0, 0.83, 9.45, 0.4225, 0.02563 + 0.0, 0.83, 9.5, 0.425, 0.0258 + 0.0, 0.83, 9.55, 0.4274, 0.02597 + 0.0, 0.83, 9.6, 0.4299, 0.02614 + 0.0, 0.83, 9.65, 0.4323, 0.02631 + 0.0, 0.83, 9.7, 0.4348, 0.02648 + 0.0, 0.83, 9.75, 0.4372, 0.02665 + 0.0, 0.83, 9.8, 0.4397, 0.02682 + 0.0, 0.83, 9.85, 0.4421, 0.02699 + 0.0, 0.83, 9.9, 0.4446, 0.02715 + 0.0, 0.83, 9.95, 0.447, 0.02732 + 0.0, 0.83, 10.0, 0.4495, 0.02749 + 0.0, 0.83, 10.05, 0.4519, 0.02766 + 0.0, 0.83, 10.1, 0.4544, 0.02782 + 0.0, 0.83, 10.15, 0.4568, 0.02798 + 0.0, 0.83, 10.2, 0.4593, 0.02815 + 0.0, 0.83, 10.25, 0.4617, 0.02831 + 0.0, 0.83, 10.3, 0.4642, 0.02847 + 0.0, 0.83, 10.35, 0.4666, 0.02864 + 0.0, 0.83, 10.4, 0.4691, 0.0288 + 0.0, 0.83, 10.45, 0.4715, 0.02896 + 0.0, 0.83, 10.5, 0.4739, 0.02913 + 0.0, 0.83, 10.55, 0.4764, 0.02929 + 0.0, 0.83, 10.6, 0.4788, 0.02945 + 0.0, 0.83, 10.65, 0.4813, 0.02961 + 0.0, 0.83, 10.7, 0.4837, 0.02978 + 0.0, 0.83, 10.75, 0.4862, 0.02994 + 0.0, 0.83, 10.8, 0.4886, 0.0301 + 0.0, 0.83, 10.85, 0.4911, 0.03027 + 0.0, 0.83, 10.9, 0.4935, 0.03043 + 0.0, 0.83, 10.95, 0.496, 0.03059 + 0.0, 0.83, 11.0, 0.4984, 0.03075 + 0.0, 0.83, 11.05, 0.5009, 0.03092 + 0.0, 0.83, 11.1, 0.5033, 0.03108 + 0.0, 0.83, 11.15, 0.5058, 0.03124 + 0.0, 0.83, 11.2, 0.5082, 0.03141 + 0.0, 0.83, 11.25, 0.5107, 0.03157 + 0.0, 0.83, 11.3, 0.5131, 0.03173 + 0.0, 0.83, 11.35, 0.5156, 0.0319 + 0.0, 0.83, 11.4, 0.518, 0.03206 + 0.0, 0.83, 11.45, 0.5205, 0.03222 + 0.0, 0.83, 11.5, 0.5229, 0.03239 + 0.0, 0.83, 11.55, 0.5254, 0.03255 + 0.0, 0.83, 11.6, 0.5278, 0.03272 + 0.0, 0.83, 11.65, 0.5303, 0.03288 + 0.0, 0.83, 11.7, 0.5327, 0.03304 + 0.0, 0.83, 11.75, 0.5352, 0.03321 + 0.0, 0.83, 11.8, 0.5376, 0.03337 + 0.0, 0.83, 11.85, 0.54, 0.03354 + 0.0, 0.83, 11.9, 0.5425, 0.0337 + 0.0, 0.83, 11.95, 0.5449, 0.03387 + 0.0, 0.83, 12.0, 0.5474, 0.03403 + 0.0, 0.83, 12.05, 0.5498, 0.0342 + 0.0, 0.83, 12.1, 0.5523, 0.03437 + 0.0, 0.83, 12.15, 0.5547, 0.03453 + 0.0, 0.83, 12.2, 0.5572, 0.0347 + 0.0, 0.83, 12.25, 0.5596, 0.03487 + 0.0, 0.83, 12.3, 0.5621, 0.03503 + 0.0, 0.83, 12.35, 0.5645, 0.0352 + 0.0, 0.83, 12.4, 0.567, 0.03537 + 0.0, 0.83, 12.45, 0.5694, 0.03554 + 0.0, 0.83, 12.5, 0.5719, 0.0357 + 0.0, 0.83, 12.55, 0.5743, 0.03587 + 0.0, 0.83, 12.6, 0.5767, 0.03604 + 0.0, 0.83, 12.65, 0.5792, 0.03621 + 0.0, 0.83, 12.7, 0.5816, 0.03638 + 0.0, 0.83, 12.75, 0.5841, 0.03655 + 0.0, 0.83, 12.8, 0.5865, 0.03672 + 0.0, 0.83, 12.85, 0.589, 0.03689 + 0.0, 0.83, 12.9, 0.5914, 0.03706 + 0.0, 0.83, 12.95, 0.5938, 0.03723 + 0.0, 0.83, 13.0, 0.5963, 0.0374 + 0.0, 0.83, 13.05, 0.5987, 0.03758 + 0.0, 0.83, 13.1, 0.6012, 0.03775 + 0.0, 0.83, 13.15, 0.6036, 0.03792 + 0.0, 0.83, 13.2, 0.6061, 0.03809 + 0.0, 0.83, 13.25, 0.6085, 0.03827 + 0.0, 0.83, 13.3, 0.6109, 0.03844 + 0.0, 0.83, 13.35, 0.6134, 0.03862 + 0.0, 0.83, 13.4, 0.6158, 0.03879 + 0.0, 0.83, 13.45, 0.6183, 0.03897 + 0.0, 0.83, 13.5, 0.6207, 0.03914 + 0.0, 0.83, 13.55, 0.6231, 0.03932 + 0.0, 0.83, 13.6, 0.6256, 0.0395 + 0.0, 0.83, 13.65, 0.628, 0.03967 + 0.0, 0.83, 13.7, 0.6305, 0.03985 + 0.0, 0.83, 13.75, 0.6329, 0.04003 + 0.0, 0.83, 13.8, 0.6353, 0.04021 + 0.0, 0.83, 13.85, 0.6378, 0.04039 + 0.0, 0.83, 13.9, 0.6402, 0.04057 + 0.0, 0.83, 13.95, 0.6426, 0.04075 + 0.0, 0.83, 14.0, 0.6451, 0.04093 + 0.0, 0.83, 14.05, 0.6475, 0.04111 + 0.0, 0.83, 14.1, 0.6499, 0.0413 + 0.0, 0.83, 14.15, 0.6524, 0.04148 + 0.0, 0.83, 14.2, 0.6548, 0.04166 + 0.0, 0.83, 14.25, 0.6572, 0.04185 + 0.0, 0.83, 14.3, 0.6597, 0.04203 + 0.0, 0.83, 14.35, 0.6621, 0.04222 + 0.0, 0.83, 14.4, 0.6645, 0.0424 + 0.0, 0.83, 14.45, 0.667, 0.04259 + 0.0, 0.83, 14.5, 0.6694, 0.04278 + 0.0, 0.83, 14.55, 0.6718, 0.04297 + 0.0, 0.83, 14.6, 0.6742, 0.04315 + 0.0, 0.83, 14.65, 0.6767, 0.04334 + 0.0, 0.83, 14.7, 0.6791, 0.04353 + 0.0, 0.83, 14.75, 0.6815, 0.04373 + 0.0, 0.83, 14.8, 0.684, 0.04392 + 0.0, 0.83, 14.85, 0.6864, 0.04411 + 0.0, 0.83, 14.9, 0.6888, 0.0443 + 0.0, 0.83, 14.95, 0.6912, 0.0445 + 0.0, 0.83, 15.0, 0.6937, 0.04469 + 0.0, 0.83, 15.05, 0.6961, 0.04489 + 0.0, 0.88, 0.0, -0.2123, 0.01117 + 0.0, 0.88, 0.05, -0.2081, 0.01117 + 0.0, 0.88, 0.1, -0.2038, 0.01117 + 0.0, 0.88, 0.15, -0.1995, 0.01115 + 0.0, 0.88, 0.2, -0.1951, 0.01114 + 0.0, 0.88, 0.25, -0.1908, 0.01111 + 0.0, 0.88, 0.3, -0.1864, 0.01108 + 0.0, 0.88, 0.35, -0.182, 0.01104 + 0.0, 0.88, 0.4, -0.1777, 0.011 + 0.0, 0.88, 0.45, -0.1732, 0.01095 + 0.0, 0.88, 0.5, -0.1688, 0.0109 + 0.0, 0.88, 0.55, -0.1644, 0.01084 + 0.0, 0.88, 0.6, -0.1599, 0.01077 + 0.0, 0.88, 0.65, -0.1555, 0.01071 + 0.0, 0.88, 0.7, -0.151, 0.01063 + 0.0, 0.88, 0.75, -0.1465, 0.01056 + 0.0, 0.88, 0.8, -0.142, 0.01048 + 0.0, 0.88, 0.85, -0.1375, 0.0104 + 0.0, 0.88, 0.9, -0.133, 0.01031 + 0.0, 0.88, 0.95, -0.1284, 0.01023 + 0.0, 0.88, 1.0, -0.1239, 0.01014 + 0.0, 0.88, 1.05, -0.1193, 0.01005 + 0.0, 0.88, 1.1, -0.1148, 0.009953 + 0.0, 0.88, 1.15, -0.1102, 0.009858 + 0.0, 0.88, 1.2, -0.1056, 0.009763 + 0.0, 0.88, 1.25, -0.1011, 0.009666 + 0.0, 0.88, 1.3, -0.09647, 0.009569 + 0.0, 0.88, 1.35, -0.09188, 0.009472 + 0.0, 0.88, 1.4, -0.08729, 0.009374 + 0.0, 0.88, 1.45, -0.0827, 0.009277 + 0.0, 0.88, 1.5, -0.0781, 0.009181 + 0.0, 0.88, 1.55, -0.07349, 0.009085 + 0.0, 0.88, 1.6, -0.06889, 0.00899 + 0.0, 0.88, 1.65, -0.06428, 0.008897 + 0.0, 0.88, 1.7, -0.05968, 0.008806 + 0.0, 0.88, 1.75, -0.05507, 0.008716 + 0.0, 0.88, 1.8, -0.05046, 0.008629 + 0.0, 0.88, 1.85, -0.04586, 0.008544 + 0.0, 0.88, 1.9, -0.04125, 0.008463 + 0.0, 0.88, 1.95, -0.03665, 0.008384 + 0.0, 0.88, 2.0, -0.03205, 0.008309 + 0.0, 0.88, 2.05, -0.02745, 0.008237 + 0.0, 0.88, 2.1, -0.02286, 0.00817 + 0.0, 0.88, 2.15, -0.01827, 0.008106 + 0.0, 0.88, 2.2, -0.01368, 0.008048 + 0.0, 0.88, 2.25, -0.009103, 0.007994 + 0.0, 0.88, 2.3, -0.004529, 0.007945 + 0.0, 0.88, 2.35, 3.779e-05, 0.007901 + 0.0, 0.88, 2.4, 0.004598, 0.007864 + 0.0, 0.88, 2.45, 0.00915, 0.007832 + 0.0, 0.88, 2.5, 0.01369, 0.007807 + 0.0, 0.88, 2.55, 0.01823, 0.007788 + 0.0, 0.88, 2.6, 0.02275, 0.007776 + 0.0, 0.88, 2.65, 0.02727, 0.007771 + 0.0, 0.88, 2.7, 0.03178, 0.007773 + 0.0, 0.88, 2.75, 0.03627, 0.007783 + 0.0, 0.88, 2.8, 0.04075, 0.007801 + 0.0, 0.88, 2.85, 0.04522, 0.007827 + 0.0, 0.88, 2.9, 0.04968, 0.007862 + 0.0, 0.88, 2.95, 0.05412, 0.007906 + 0.0, 0.88, 3.0, 0.05855, 0.007959 + 0.0, 0.88, 3.05, 0.06297, 0.008021 + 0.0, 0.88, 3.1, 0.06737, 0.008093 + 0.0, 0.88, 3.15, 0.07175, 0.008175 + 0.0, 0.88, 3.2, 0.07612, 0.008267 + 0.0, 0.88, 3.25, 0.08047, 0.008369 + 0.0, 0.88, 3.3, 0.08481, 0.008483 + 0.0, 0.88, 3.35, 0.08912, 0.008607 + 0.0, 0.88, 3.4, 0.09342, 0.008743 + 0.0, 0.88, 3.45, 0.0977, 0.008891 + 0.0, 0.88, 3.5, 0.102, 0.00905 + 0.0, 0.88, 3.55, 0.1062, 0.009222 + 0.0, 0.88, 3.6, 0.1104, 0.009406 + 0.0, 0.88, 3.65, 0.1146, 0.009603 + 0.0, 0.88, 3.7, 0.1188, 0.009813 + 0.0, 0.88, 3.75, 0.1229, 0.01004 + 0.0, 0.88, 3.8, 0.1271, 0.01027 + 0.0, 0.88, 3.85, 0.1312, 0.01052 + 0.0, 0.88, 3.9, 0.1352, 0.01079 + 0.0, 0.88, 3.95, 0.1393, 0.01107 + 0.0, 0.88, 4.0, 0.1433, 0.01136 + 0.0, 0.88, 4.05, 0.1477, 0.01173 + 0.0, 0.88, 4.1, 0.152, 0.0121 + 0.0, 0.88, 4.15, 0.1563, 0.01248 + 0.0, 0.88, 4.2, 0.1606, 0.01288 + 0.0, 0.88, 4.25, 0.1647, 0.01329 + 0.0, 0.88, 4.3, 0.1688, 0.01371 + 0.0, 0.88, 4.35, 0.1729, 0.01415 + 0.0, 0.88, 4.4, 0.1768, 0.01459 + 0.0, 0.88, 4.45, 0.1807, 0.01505 + 0.0, 0.88, 4.5, 0.1845, 0.01552 + 0.0, 0.88, 4.55, 0.1883, 0.016 + 0.0, 0.88, 4.6, 0.1919, 0.01649 + 0.0, 0.88, 4.65, 0.1955, 0.01699 + 0.0, 0.88, 4.7, 0.199, 0.0175 + 0.0, 0.88, 4.75, 0.2023, 0.01802 + 0.0, 0.88, 4.8, 0.2056, 0.01856 + 0.0, 0.88, 4.85, 0.2088, 0.0191 + 0.0, 0.88, 4.9, 0.2119, 0.01966 + 0.0, 0.88, 4.95, 0.2148, 0.02023 + 0.0, 0.88, 5.0, 0.2177, 0.0208 + 0.0, 0.88, 5.05, 0.2197, 0.02137 + 0.0, 0.88, 5.1, 0.2217, 0.02194 + 0.0, 0.88, 5.15, 0.2236, 0.02253 + 0.0, 0.88, 5.2, 0.2254, 0.02312 + 0.0, 0.88, 5.25, 0.227, 0.02373 + 0.0, 0.88, 5.3, 0.2286, 0.02435 + 0.0, 0.88, 5.35, 0.2301, 0.02498 + 0.0, 0.88, 5.4, 0.2316, 0.02562 + 0.0, 0.88, 5.45, 0.2329, 0.02628 + 0.0, 0.88, 5.5, 0.2343, 0.02695 + 0.0, 0.88, 5.55, 0.2355, 0.02763 + 0.0, 0.88, 5.6, 0.2367, 0.02832 + 0.0, 0.88, 5.65, 0.2379, 0.02902 + 0.0, 0.88, 5.7, 0.239, 0.02974 + 0.0, 0.88, 5.75, 0.2401, 0.03048 + 0.0, 0.88, 5.8, 0.2412, 0.03122 + 0.0, 0.88, 5.85, 0.2423, 0.03198 + 0.0, 0.88, 5.9, 0.2433, 0.03276 + 0.0, 0.88, 5.95, 0.2444, 0.03355 + 0.0, 0.88, 6.0, 0.2455, 0.03435 + 0.0, 0.88, 6.05, 0.2476, 0.03526 + 0.0, 0.88, 6.1, 0.2498, 0.0362 + 0.0, 0.88, 6.15, 0.2521, 0.03715 + 0.0, 0.88, 6.2, 0.2544, 0.03812 + 0.0, 0.88, 6.25, 0.2568, 0.0391 + 0.0, 0.88, 6.3, 0.2592, 0.04011 + 0.0, 0.88, 6.35, 0.2617, 0.04113 + 0.0, 0.88, 6.4, 0.2642, 0.04217 + 0.0, 0.88, 6.45, 0.2668, 0.04322 + 0.0, 0.88, 6.5, 0.2694, 0.04429 + 0.0, 0.88, 6.55, 0.2721, 0.04537 + 0.0, 0.88, 6.6, 0.2748, 0.04647 + 0.0, 0.88, 6.65, 0.2775, 0.04758 + 0.0, 0.88, 6.7, 0.2803, 0.04871 + 0.0, 0.88, 6.75, 0.2832, 0.04985 + 0.0, 0.88, 6.8, 0.286, 0.051 + 0.0, 0.88, 6.85, 0.2889, 0.05217 + 0.0, 0.88, 6.9, 0.2918, 0.05334 + 0.0, 0.88, 6.95, 0.2948, 0.05453 + 0.0, 0.88, 7.0, 0.2978, 0.05573 + 0.0, 0.88, 7.05, 0.3008, 0.05694 + 0.0, 0.88, 7.1, 0.3038, 0.05816 + 0.0, 0.88, 7.15, 0.3069, 0.05939 + 0.0, 0.88, 7.2, 0.31, 0.06062 + 0.0, 0.88, 7.25, 0.3131, 0.06187 + 0.0, 0.88, 7.3, 0.3162, 0.06313 + 0.0, 0.88, 7.35, 0.3194, 0.06439 + 0.0, 0.88, 7.4, 0.3225, 0.06566 + 0.0, 0.88, 7.45, 0.3257, 0.06693 + 0.0, 0.88, 7.5, 0.3289, 0.06822 + 0.0, 0.88, 7.55, 0.332, 0.06951 + 0.0, 0.88, 7.6, 0.3352, 0.0708 + 0.0, 0.88, 7.65, 0.3384, 0.0721 + 0.0, 0.88, 7.7, 0.3417, 0.0734 + 0.0, 0.88, 7.75, 0.3449, 0.07471 + 0.0, 0.88, 7.8, 0.3481, 0.07602 + 0.0, 0.88, 7.85, 0.3513, 0.07734 + 0.0, 0.88, 7.9, 0.3545, 0.07866 + 0.0, 0.88, 7.95, 0.3577, 0.07998 + 0.0, 0.88, 8.0, 0.3609, 0.0813 + 0.0, 0.88, 8.05, 0.3636, 0.0825 + 0.0, 0.88, 8.1, 0.3663, 0.0837 + 0.0, 0.88, 8.15, 0.3689, 0.0849 + 0.0, 0.88, 8.2, 0.3716, 0.0861 + 0.0, 0.88, 8.25, 0.3743, 0.08731 + 0.0, 0.88, 8.3, 0.3769, 0.08851 + 0.0, 0.88, 8.35, 0.3796, 0.08972 + 0.0, 0.88, 8.4, 0.3822, 0.09093 + 0.0, 0.88, 8.45, 0.3848, 0.09214 + 0.0, 0.88, 8.5, 0.3875, 0.09335 + 0.0, 0.88, 8.55, 0.3901, 0.09456 + 0.0, 0.88, 8.6, 0.3927, 0.09578 + 0.0, 0.88, 8.65, 0.3953, 0.09699 + 0.0, 0.88, 8.7, 0.3979, 0.09821 + 0.0, 0.88, 8.75, 0.4005, 0.09943 + 0.0, 0.88, 8.8, 0.4031, 0.1007 + 0.0, 0.88, 8.85, 0.4057, 0.1019 + 0.0, 0.88, 8.9, 0.4083, 0.1031 + 0.0, 0.88, 8.95, 0.4109, 0.1043 + 0.0, 0.88, 9.0, 0.4134, 0.1056 + 0.0, 0.88, 9.05, 0.416, 0.1068 + 0.0, 0.88, 9.1, 0.4186, 0.108 + 0.0, 0.88, 9.15, 0.4211, 0.1092 + 0.0, 0.88, 9.2, 0.4237, 0.1105 + 0.0, 0.88, 9.25, 0.4262, 0.1117 + 0.0, 0.88, 9.3, 0.4288, 0.1129 + 0.0, 0.88, 9.35, 0.4313, 0.1142 + 0.0, 0.88, 9.4, 0.4339, 0.1154 + 0.0, 0.88, 9.45, 0.4364, 0.1167 + 0.0, 0.88, 9.5, 0.439, 0.1179 + 0.0, 0.88, 9.55, 0.4415, 0.1192 + 0.0, 0.88, 9.6, 0.4441, 0.1204 + 0.0, 0.88, 9.65, 0.4466, 0.1217 + 0.0, 0.88, 9.7, 0.4491, 0.1229 + 0.0, 0.88, 9.75, 0.4516, 0.1242 + 0.0, 0.88, 9.8, 0.4542, 0.1254 + 0.0, 0.88, 9.85, 0.4567, 0.1267 + 0.0, 0.88, 9.9, 0.4592, 0.1279 + 0.0, 0.88, 9.95, 0.4618, 0.1292 + 0.0, 0.88, 10.0, 0.4643, 0.1305 + 0.0, 0.88, 10.05, 0.4668, 0.1318 + 0.0, 0.88, 10.1, 0.4694, 0.1331 + 0.0, 0.88, 10.15, 0.4719, 0.1344 + 0.0, 0.88, 10.2, 0.4745, 0.1357 + 0.0, 0.88, 10.25, 0.477, 0.137 + 0.0, 0.88, 10.3, 0.4796, 0.1383 + 0.0, 0.88, 10.35, 0.4822, 0.1396 + 0.0, 0.88, 10.4, 0.4847, 0.1409 + 0.0, 0.88, 10.45, 0.4873, 0.1422 + 0.0, 0.88, 10.5, 0.4898, 0.1435 + 0.0, 0.88, 10.55, 0.4924, 0.1448 + 0.0, 0.88, 10.6, 0.4949, 0.1462 + 0.0, 0.88, 10.65, 0.4974, 0.1475 + 0.0, 0.88, 10.7, 0.5, 0.1488 + 0.0, 0.88, 10.75, 0.5025, 0.1501 + 0.0, 0.88, 10.8, 0.5051, 0.1514 + 0.0, 0.88, 10.85, 0.5076, 0.1527 + 0.0, 0.88, 10.9, 0.5102, 0.154 + 0.0, 0.88, 10.95, 0.5127, 0.1553 + 0.0, 0.88, 11.0, 0.5153, 0.1567 + 0.0, 0.88, 11.05, 0.5178, 0.158 + 0.0, 0.88, 11.1, 0.5204, 0.1593 + 0.0, 0.88, 11.15, 0.5229, 0.1606 + 0.0, 0.88, 11.2, 0.5255, 0.1619 + 0.0, 0.88, 11.25, 0.528, 0.1632 + 0.0, 0.88, 11.3, 0.5306, 0.1645 + 0.0, 0.88, 11.35, 0.5331, 0.1658 + 0.0, 0.88, 11.4, 0.5357, 0.1671 + 0.0, 0.88, 11.45, 0.5382, 0.1684 + 0.0, 0.88, 11.5, 0.5408, 0.1697 + 0.0, 0.88, 11.55, 0.5433, 0.171 + 0.0, 0.88, 11.6, 0.5459, 0.1723 + 0.0, 0.88, 11.65, 0.5484, 0.1736 + 0.0, 0.88, 11.7, 0.551, 0.1749 + 0.0, 0.88, 11.75, 0.5535, 0.1762 + 0.0, 0.88, 11.8, 0.5561, 0.1775 + 0.0, 0.88, 11.85, 0.5586, 0.1788 + 0.0, 0.88, 11.9, 0.5612, 0.1801 + 0.0, 0.88, 11.95, 0.5637, 0.1814 + 0.0, 0.88, 12.0, 0.5663, 0.1826 + 0.0, 0.88, 12.05, 0.5688, 0.1839 + 0.0, 0.88, 12.1, 0.5714, 0.1852 + 0.0, 0.88, 12.15, 0.574, 0.1865 + 0.0, 0.88, 12.2, 0.5765, 0.1877 + 0.0, 0.88, 12.25, 0.5791, 0.189 + 0.0, 0.88, 12.3, 0.5816, 0.1903 + 0.0, 0.88, 12.35, 0.5842, 0.1915 + 0.0, 0.88, 12.4, 0.5868, 0.1928 + 0.0, 0.88, 12.45, 0.5893, 0.194 + 0.0, 0.88, 12.5, 0.5919, 0.1953 + 0.0, 0.88, 12.55, 0.5945, 0.1965 + 0.0, 0.88, 12.6, 0.597, 0.1977 + 0.0, 0.88, 12.65, 0.5996, 0.199 + 0.0, 0.88, 12.7, 0.6022, 0.2002 + 0.0, 0.88, 12.75, 0.6047, 0.2014 + 0.0, 0.88, 12.8, 0.6073, 0.2026 + 0.0, 0.88, 12.85, 0.6099, 0.2038 + 0.0, 0.88, 12.9, 0.6125, 0.2051 + 0.0, 0.88, 12.95, 0.615, 0.2063 + 0.0, 0.88, 13.0, 0.6176, 0.2074 + 0.0, 0.88, 13.05, 0.6202, 0.2086 + 0.0, 0.88, 13.1, 0.6228, 0.2098 + 0.0, 0.88, 13.15, 0.6254, 0.211 + 0.0, 0.88, 13.2, 0.6279, 0.2122 + 0.0, 0.88, 13.25, 0.6305, 0.2133 + 0.0, 0.88, 13.3, 0.6331, 0.2145 + 0.0, 0.88, 13.35, 0.6357, 0.2157 + 0.0, 0.88, 13.4, 0.6383, 0.2168 + 0.0, 0.88, 13.45, 0.6409, 0.218 + 0.0, 0.88, 13.5, 0.6435, 0.2191 + 0.0, 0.88, 13.55, 0.6461, 0.2202 + 0.0, 0.88, 13.6, 0.6487, 0.2214 + 0.0, 0.88, 13.65, 0.6513, 0.2225 + 0.0, 0.88, 13.7, 0.6539, 0.2236 + 0.0, 0.88, 13.75, 0.6565, 0.2247 + 0.0, 0.88, 13.8, 0.6591, 0.2258 + 0.0, 0.88, 13.85, 0.6618, 0.2269 + 0.0, 0.88, 13.9, 0.6644, 0.2279 + 0.0, 0.88, 13.95, 0.667, 0.229 + 0.0, 0.88, 14.0, 0.6696, 0.2301 + 0.0, 0.88, 14.05, 0.6722, 0.2311 + 0.0, 0.88, 14.1, 0.6749, 0.2322 + 0.0, 0.88, 14.15, 0.6775, 0.2332 + 0.0, 0.88, 14.2, 0.6801, 0.2343 + 0.0, 0.88, 14.25, 0.6828, 0.2353 + 0.0, 0.88, 14.3, 0.6854, 0.2363 + 0.0, 0.88, 14.35, 0.688, 0.2373 + 0.0, 0.88, 14.4, 0.6907, 0.2383 + 0.0, 0.88, 14.45, 0.6933, 0.2393 + 0.0, 0.88, 14.5, 0.696, 0.2403 + 0.0, 0.88, 14.55, 0.6986, 0.2413 + 0.0, 0.88, 14.6, 0.7013, 0.2422 + 0.0, 0.88, 14.65, 0.7039, 0.2432 + 0.0, 0.88, 14.7, 0.7066, 0.2441 + 0.0, 0.88, 14.75, 0.7093, 0.2451 + 0.0, 0.88, 14.8, 0.7119, 0.246 + 0.0, 0.88, 14.85, 0.7146, 0.2469 + 0.0, 0.88, 14.9, 0.7173, 0.2478 + 0.0, 0.88, 14.95, 0.7199, 0.2487 + 0.0, 0.88, 15.0, 0.7226, 0.2496 + 0.0, 0.88, 15.05, 0.7253, 0.2505 + 0.0, 0.93, 0.0, -0.2189, 0.05964 + 0.0, 0.93, 0.05, -0.2122, 0.05915 + 0.0, 0.93, 0.1, -0.2055, 0.05863 + 0.0, 0.93, 0.15, -0.199, 0.05808 + 0.0, 0.93, 0.2, -0.1926, 0.05749 + 0.0, 0.93, 0.25, -0.1863, 0.05688 + 0.0, 0.93, 0.3, -0.1802, 0.05623 + 0.0, 0.93, 0.35, -0.1741, 0.05555 + 0.0, 0.93, 0.4, -0.1682, 0.05484 + 0.0, 0.93, 0.45, -0.1624, 0.05411 + 0.0, 0.93, 0.5, -0.1566, 0.05335 + 0.0, 0.93, 0.55, -0.151, 0.05257 + 0.0, 0.93, 0.6, -0.1455, 0.05177 + 0.0, 0.93, 0.65, -0.14, 0.05094 + 0.0, 0.93, 0.7, -0.1347, 0.05009 + 0.0, 0.93, 0.75, -0.1294, 0.04923 + 0.0, 0.93, 0.8, -0.1243, 0.04834 + 0.0, 0.93, 0.85, -0.1192, 0.04744 + 0.0, 0.93, 0.9, -0.1142, 0.04653 + 0.0, 0.93, 0.95, -0.1093, 0.0456 + 0.0, 0.93, 1.0, -0.1044, 0.04466 + 0.0, 0.93, 1.05, -0.09966, 0.04371 + 0.0, 0.93, 1.1, -0.09496, 0.04274 + 0.0, 0.93, 1.15, -0.09033, 0.04177 + 0.0, 0.93, 1.2, -0.08576, 0.04079 + 0.0, 0.93, 1.25, -0.08126, 0.03981 + 0.0, 0.93, 1.3, -0.07682, 0.03882 + 0.0, 0.93, 1.35, -0.07243, 0.03782 + 0.0, 0.93, 1.4, -0.0681, 0.03683 + 0.0, 0.93, 1.45, -0.06382, 0.03583 + 0.0, 0.93, 1.5, -0.05959, 0.03483 + 0.0, 0.93, 1.55, -0.05541, 0.03383 + 0.0, 0.93, 1.6, -0.05127, 0.03284 + 0.0, 0.93, 1.65, -0.04717, 0.03185 + 0.0, 0.93, 1.7, -0.04311, 0.03087 + 0.0, 0.93, 1.75, -0.03909, 0.02989 + 0.0, 0.93, 1.8, -0.0351, 0.02892 + 0.0, 0.93, 1.85, -0.03114, 0.02796 + 0.0, 0.93, 1.9, -0.0272, 0.02701 + 0.0, 0.93, 1.95, -0.02329, 0.02607 + 0.0, 0.93, 2.0, -0.0194, 0.02514 + 0.0, 0.93, 2.05, -0.01554, 0.02423 + 0.0, 0.93, 2.1, -0.01168, 0.02333 + 0.0, 0.93, 2.15, -0.007845, 0.02245 + 0.0, 0.93, 2.2, -0.004017, 0.02159 + 0.0, 0.93, 2.25, -0.0001983, 0.02075 + 0.0, 0.93, 2.3, 0.003615, 0.01993 + 0.0, 0.93, 2.35, 0.007426, 0.01912 + 0.0, 0.93, 2.4, 0.01124, 0.01835 + 0.0, 0.93, 2.45, 0.01505, 0.01759 + 0.0, 0.93, 2.5, 0.01887, 0.01687 + 0.0, 0.93, 2.55, 0.0227, 0.01617 + 0.0, 0.93, 2.6, 0.02653, 0.01549 + 0.0, 0.93, 2.65, 0.03038, 0.01485 + 0.0, 0.93, 2.7, 0.03425, 0.01424 + 0.0, 0.93, 2.75, 0.03814, 0.01366 + 0.0, 0.93, 2.8, 0.04205, 0.01311 + 0.0, 0.93, 2.85, 0.04598, 0.0126 + 0.0, 0.93, 2.9, 0.04994, 0.01212 + 0.0, 0.93, 2.95, 0.05393, 0.01168 + 0.0, 0.93, 3.0, 0.05795, 0.01128 + 0.0, 0.93, 3.05, 0.06201, 0.01092 + 0.0, 0.93, 3.1, 0.0661, 0.0106 + 0.0, 0.93, 3.15, 0.07024, 0.01032 + 0.0, 0.93, 3.2, 0.07442, 0.01008 + 0.0, 0.93, 3.25, 0.07865, 0.009894 + 0.0, 0.93, 3.3, 0.08292, 0.00975 + 0.0, 0.93, 3.35, 0.08725, 0.009652 + 0.0, 0.93, 3.4, 0.09163, 0.009604 + 0.0, 0.93, 3.45, 0.09607, 0.009605 + 0.0, 0.93, 3.5, 0.1006, 0.009658 + 0.0, 0.93, 3.55, 0.1051, 0.009762 + 0.0, 0.93, 3.6, 0.1098, 0.009921 + 0.0, 0.93, 3.65, 0.1144, 0.01013 + 0.0, 0.93, 3.7, 0.1192, 0.0104 + 0.0, 0.93, 3.75, 0.1241, 0.01073 + 0.0, 0.93, 3.8, 0.129, 0.01112 + 0.0, 0.93, 3.85, 0.134, 0.01156 + 0.0, 0.93, 3.9, 0.139, 0.01207 + 0.0, 0.93, 3.95, 0.1442, 0.01264 + 0.0, 0.93, 4.0, 0.1494, 0.01327 + 0.0, 0.93, 4.05, 0.1576, 0.01417 + 0.0, 0.93, 4.1, 0.1658, 0.01513 + 0.0, 0.93, 4.15, 0.1738, 0.01614 + 0.0, 0.93, 4.2, 0.1817, 0.0172 + 0.0, 0.93, 4.25, 0.1895, 0.01832 + 0.0, 0.93, 4.3, 0.1971, 0.01949 + 0.0, 0.93, 4.35, 0.2045, 0.02071 + 0.0, 0.93, 4.4, 0.2118, 0.02199 + 0.0, 0.93, 4.45, 0.2188, 0.02332 + 0.0, 0.93, 4.5, 0.2256, 0.0247 + 0.0, 0.93, 4.55, 0.2322, 0.02613 + 0.0, 0.93, 4.6, 0.2385, 0.02762 + 0.0, 0.93, 4.65, 0.2445, 0.02915 + 0.0, 0.93, 4.7, 0.2502, 0.03074 + 0.0, 0.93, 4.75, 0.2556, 0.03237 + 0.0, 0.93, 4.8, 0.2606, 0.03406 + 0.0, 0.93, 4.85, 0.2653, 0.0358 + 0.0, 0.93, 4.9, 0.2696, 0.03759 + 0.0, 0.93, 4.95, 0.2734, 0.03942 + 0.0, 0.93, 5.0, 0.2769, 0.04131 + 0.0, 0.93, 5.05, 0.2771, 0.04315 + 0.0, 0.93, 5.1, 0.277, 0.04504 + 0.0, 0.93, 5.15, 0.2764, 0.04697 + 0.0, 0.93, 5.2, 0.2755, 0.04897 + 0.0, 0.93, 5.25, 0.2742, 0.05101 + 0.0, 0.93, 5.3, 0.2725, 0.05311 + 0.0, 0.93, 5.35, 0.2706, 0.05527 + 0.0, 0.93, 5.4, 0.2684, 0.05748 + 0.0, 0.93, 5.45, 0.2659, 0.05975 + 0.0, 0.93, 5.5, 0.2632, 0.06208 + 0.0, 0.93, 5.55, 0.2602, 0.06447 + 0.0, 0.93, 5.6, 0.257, 0.06693 + 0.0, 0.93, 5.65, 0.2537, 0.06945 + 0.0, 0.93, 5.7, 0.2502, 0.07203 + 0.0, 0.93, 5.75, 0.2466, 0.07467 + 0.0, 0.93, 5.8, 0.2428, 0.07739 + 0.0, 0.93, 5.85, 0.239, 0.08017 + 0.0, 0.93, 5.9, 0.2351, 0.08302 + 0.0, 0.93, 5.95, 0.2311, 0.08594 + 0.0, 0.93, 6.0, 0.2272, 0.08893 + 0.0, 0.93, 6.05, 0.2269, 0.09244 + 0.0, 0.93, 6.1, 0.2269, 0.09605 + 0.0, 0.93, 6.15, 0.227, 0.09974 + 0.0, 0.93, 6.2, 0.2273, 0.1035 + 0.0, 0.93, 6.25, 0.2278, 0.1074 + 0.0, 0.93, 6.3, 0.2284, 0.1113 + 0.0, 0.93, 6.35, 0.2291, 0.1154 + 0.0, 0.93, 6.4, 0.23, 0.1195 + 0.0, 0.93, 6.45, 0.2311, 0.1237 + 0.0, 0.93, 6.5, 0.2322, 0.1279 + 0.0, 0.93, 6.55, 0.2335, 0.1323 + 0.0, 0.93, 6.6, 0.2349, 0.1367 + 0.0, 0.93, 6.65, 0.2365, 0.1412 + 0.0, 0.93, 6.7, 0.2381, 0.1457 + 0.0, 0.93, 6.75, 0.2398, 0.1503 + 0.0, 0.93, 6.8, 0.2416, 0.155 + 0.0, 0.93, 6.85, 0.2436, 0.1598 + 0.0, 0.93, 6.9, 0.2456, 0.1646 + 0.0, 0.93, 6.95, 0.2477, 0.1694 + 0.0, 0.93, 7.0, 0.2498, 0.1743 + 0.0, 0.93, 7.05, 0.2521, 0.1793 + 0.0, 0.93, 7.1, 0.2544, 0.1843 + 0.0, 0.93, 7.15, 0.2567, 0.1893 + 0.0, 0.93, 7.2, 0.2591, 0.1944 + 0.0, 0.93, 7.25, 0.2616, 0.1996 + 0.0, 0.93, 7.3, 0.2641, 0.2048 + 0.0, 0.93, 7.35, 0.2666, 0.21 + 0.0, 0.93, 7.4, 0.2692, 0.2153 + 0.0, 0.93, 7.45, 0.2718, 0.2206 + 0.0, 0.93, 7.5, 0.2744, 0.2259 + 0.0, 0.93, 7.55, 0.277, 0.2313 + 0.0, 0.93, 7.6, 0.2797, 0.2367 + 0.0, 0.93, 7.65, 0.2823, 0.2421 + 0.0, 0.93, 7.7, 0.2849, 0.2476 + 0.0, 0.93, 7.75, 0.2876, 0.253 + 0.0, 0.93, 7.8, 0.2902, 0.2585 + 0.0, 0.93, 7.85, 0.2928, 0.264 + 0.0, 0.93, 7.9, 0.2953, 0.2696 + 0.0, 0.93, 7.95, 0.2979, 0.2751 + 0.0, 0.93, 8.0, 0.3004, 0.2807 + 0.0, 0.93, 8.05, 0.3011, 0.2857 + 0.0, 0.93, 8.1, 0.3018, 0.2907 + 0.0, 0.93, 8.15, 0.3024, 0.2957 + 0.0, 0.93, 8.2, 0.303, 0.3007 + 0.0, 0.93, 8.25, 0.3036, 0.3058 + 0.0, 0.93, 8.3, 0.3041, 0.3108 + 0.0, 0.93, 8.35, 0.3046, 0.3159 + 0.0, 0.93, 8.4, 0.3051, 0.3209 + 0.0, 0.93, 8.45, 0.3055, 0.326 + 0.0, 0.93, 8.5, 0.3059, 0.3311 + 0.0, 0.93, 8.55, 0.3063, 0.3362 + 0.0, 0.93, 8.6, 0.3066, 0.3413 + 0.0, 0.93, 8.65, 0.3069, 0.3465 + 0.0, 0.93, 8.7, 0.3072, 0.3516 + 0.0, 0.93, 8.75, 0.3074, 0.3567 + 0.0, 0.93, 8.8, 0.3077, 0.3619 + 0.0, 0.93, 8.85, 0.3078, 0.3671 + 0.0, 0.93, 8.9, 0.308, 0.3722 + 0.0, 0.93, 8.95, 0.3081, 0.3774 + 0.0, 0.93, 9.0, 0.3082, 0.3826 + 0.0, 0.93, 9.05, 0.3083, 0.3879 + 0.0, 0.93, 9.1, 0.3084, 0.3931 + 0.0, 0.93, 9.15, 0.3084, 0.3983 + 0.0, 0.93, 9.2, 0.3085, 0.4036 + 0.0, 0.93, 9.25, 0.3085, 0.4088 + 0.0, 0.93, 9.3, 0.3085, 0.4141 + 0.0, 0.93, 9.35, 0.3084, 0.4194 + 0.0, 0.93, 9.4, 0.3084, 0.4247 + 0.0, 0.93, 9.45, 0.3083, 0.43 + 0.0, 0.93, 9.5, 0.3082, 0.4353 + 0.0, 0.93, 9.55, 0.3081, 0.4406 + 0.0, 0.93, 9.6, 0.308, 0.446 + 0.0, 0.93, 9.65, 0.3079, 0.4513 + 0.0, 0.93, 9.7, 0.3078, 0.4567 + 0.0, 0.93, 9.75, 0.3077, 0.4621 + 0.0, 0.93, 9.8, 0.3075, 0.4675 + 0.0, 0.93, 9.85, 0.3073, 0.4729 + 0.0, 0.93, 9.9, 0.3072, 0.4783 + 0.0, 0.93, 9.95, 0.307, 0.4837 + 0.0, 0.93, 10.0, 0.3068, 0.4892 + 0.0, 0.93, 10.05, 0.3068, 0.4948 + 0.0, 0.93, 10.1, 0.3068, 0.5005 + 0.0, 0.93, 10.15, 0.3068, 0.5062 + 0.0, 0.93, 10.2, 0.3068, 0.5119 + 0.0, 0.93, 10.25, 0.3068, 0.5176 + 0.0, 0.93, 10.3, 0.3068, 0.5233 + 0.0, 0.93, 10.35, 0.3067, 0.529 + 0.0, 0.93, 10.4, 0.3067, 0.5348 + 0.0, 0.93, 10.45, 0.3067, 0.5405 + 0.0, 0.93, 10.5, 0.3067, 0.5463 + 0.0, 0.93, 10.55, 0.3066, 0.552 + 0.0, 0.93, 10.6, 0.3066, 0.5578 + 0.0, 0.93, 10.65, 0.3065, 0.5635 + 0.0, 0.93, 10.7, 0.3065, 0.5693 + 0.0, 0.93, 10.75, 0.3065, 0.575 + 0.0, 0.93, 10.8, 0.3064, 0.5808 + 0.0, 0.93, 10.85, 0.3064, 0.5865 + 0.0, 0.93, 10.9, 0.3063, 0.5923 + 0.0, 0.93, 10.95, 0.3063, 0.5981 + 0.0, 0.93, 11.0, 0.3062, 0.6038 + 0.0, 0.93, 11.05, 0.3062, 0.6096 + 0.0, 0.93, 11.1, 0.3061, 0.6153 + 0.0, 0.93, 11.15, 0.3061, 0.621 + 0.0, 0.93, 11.2, 0.3061, 0.6268 + 0.0, 0.93, 11.25, 0.306, 0.6325 + 0.0, 0.93, 11.3, 0.306, 0.6382 + 0.0, 0.93, 11.35, 0.3059, 0.6439 + 0.0, 0.93, 11.4, 0.3059, 0.6496 + 0.0, 0.93, 11.45, 0.3058, 0.6553 + 0.0, 0.93, 11.5, 0.3058, 0.661 + 0.0, 0.93, 11.55, 0.3058, 0.6667 + 0.0, 0.93, 11.6, 0.3057, 0.6724 + 0.0, 0.93, 11.65, 0.3057, 0.678 + 0.0, 0.93, 11.7, 0.3057, 0.6837 + 0.0, 0.93, 11.75, 0.3057, 0.6893 + 0.0, 0.93, 11.8, 0.3056, 0.6949 + 0.0, 0.93, 11.85, 0.3056, 0.7005 + 0.0, 0.93, 11.9, 0.3056, 0.7061 + 0.0, 0.93, 11.95, 0.3056, 0.7116 + 0.0, 0.93, 12.0, 0.3056, 0.7172 + 0.0, 0.93, 12.05, 0.3056, 0.7227 + 0.0, 0.93, 12.1, 0.3056, 0.7282 + 0.0, 0.93, 12.15, 0.3056, 0.7337 + 0.0, 0.93, 12.2, 0.3056, 0.7392 + 0.0, 0.93, 12.25, 0.3057, 0.7446 + 0.0, 0.93, 12.3, 0.3057, 0.75 + 0.0, 0.93, 12.35, 0.3057, 0.7554 + 0.0, 0.93, 12.4, 0.3058, 0.7608 + 0.0, 0.93, 12.45, 0.3058, 0.7661 + 0.0, 0.93, 12.5, 0.3059, 0.7715 + 0.0, 0.93, 12.55, 0.3059, 0.7768 + 0.0, 0.93, 12.6, 0.306, 0.782 + 0.0, 0.93, 12.65, 0.3061, 0.7873 + 0.0, 0.93, 12.7, 0.3062, 0.7925 + 0.0, 0.93, 12.75, 0.3062, 0.7977 + 0.0, 0.93, 12.8, 0.3063, 0.8028 + 0.0, 0.93, 12.85, 0.3064, 0.8079 + 0.0, 0.93, 12.9, 0.3066, 0.813 + 0.0, 0.93, 12.95, 0.3067, 0.8181 + 0.0, 0.93, 13.0, 0.3068, 0.8231 + 0.0, 0.93, 13.05, 0.307, 0.8281 + 0.0, 0.93, 13.1, 0.3071, 0.8331 + 0.0, 0.93, 13.15, 0.3073, 0.838 + 0.0, 0.93, 13.2, 0.3075, 0.8429 + 0.0, 0.93, 13.25, 0.3076, 0.8477 + 0.0, 0.93, 13.3, 0.3078, 0.8525 + 0.0, 0.93, 13.35, 0.308, 0.8573 + 0.0, 0.93, 13.4, 0.3082, 0.862 + 0.0, 0.93, 13.45, 0.3085, 0.8667 + 0.0, 0.93, 13.5, 0.3087, 0.8714 + 0.0, 0.93, 13.55, 0.309, 0.876 + 0.0, 0.93, 13.6, 0.3092, 0.8805 + 0.0, 0.93, 13.65, 0.3095, 0.8851 + 0.0, 0.93, 13.7, 0.3098, 0.8895 + 0.0, 0.93, 13.75, 0.3101, 0.894 + 0.0, 0.93, 13.8, 0.3104, 0.8984 + 0.0, 0.93, 13.85, 0.3107, 0.9027 + 0.0, 0.93, 13.9, 0.311, 0.907 + 0.0, 0.93, 13.95, 0.3114, 0.9113 + 0.0, 0.93, 14.0, 0.3118, 0.9155 + 0.0, 0.93, 14.05, 0.3121, 0.9196 + 0.0, 0.93, 14.1, 0.3125, 0.9237 + 0.0, 0.93, 14.15, 0.3129, 0.9278 + 0.0, 0.93, 14.2, 0.3134, 0.9318 + 0.0, 0.93, 14.25, 0.3138, 0.9357 + 0.0, 0.93, 14.3, 0.3143, 0.9396 + 0.0, 0.93, 14.35, 0.3147, 0.9434 + 0.0, 0.93, 14.4, 0.3152, 0.9472 + 0.0, 0.93, 14.45, 0.3157, 0.9509 + 0.0, 0.93, 14.5, 0.3162, 0.9546 + 0.0, 0.93, 14.55, 0.3168, 0.9582 + 0.0, 0.93, 14.6, 0.3173, 0.9618 + 0.0, 0.93, 14.65, 0.3179, 0.9653 + 0.0, 0.93, 14.7, 0.3185, 0.9687 + 0.0, 0.93, 14.75, 0.3191, 0.9721 + 0.0, 0.93, 14.8, 0.3197, 0.9754 + 0.0, 0.93, 14.85, 0.3203, 0.9787 + 0.0, 0.93, 14.9, 0.321, 0.9819 + 0.0, 0.93, 14.95, 0.3216, 0.985 + 0.0, 0.93, 15.0, 0.3223, 0.9881 + 0.0, 0.93, 15.05, 0.323, 0.9911 + 30000.0, 0.23, 0.0, -0.1539, 0.003657 + 30000.0, 0.23, 0.05, -0.1511, 0.003707 + 30000.0, 0.23, 0.1, -0.1483, 0.003755 + 30000.0, 0.23, 0.15, -0.1455, 0.003801 + 30000.0, 0.23, 0.2, -0.1427, 0.003846 + 30000.0, 0.23, 0.25, -0.1399, 0.00389 + 30000.0, 0.23, 0.3, -0.1371, 0.003932 + 30000.0, 0.23, 0.35, -0.1343, 0.003972 + 30000.0, 0.23, 0.4, -0.1315, 0.004011 + 30000.0, 0.23, 0.45, -0.1288, 0.004048 + 30000.0, 0.23, 0.5, -0.126, 0.004084 + 30000.0, 0.23, 0.55, -0.1232, 0.004119 + 30000.0, 0.23, 0.6, -0.1204, 0.004152 + 30000.0, 0.23, 0.65, -0.1176, 0.004185 + 30000.0, 0.23, 0.7, -0.1149, 0.004215 + 30000.0, 0.23, 0.75, -0.1121, 0.004245 + 30000.0, 0.23, 0.8, -0.1093, 0.004274 + 30000.0, 0.23, 0.85, -0.1066, 0.004301 + 30000.0, 0.23, 0.9, -0.1038, 0.004327 + 30000.0, 0.23, 0.95, -0.101, 0.004352 + 30000.0, 0.23, 1.0, -0.09826, 0.004376 + 30000.0, 0.23, 1.05, -0.0955, 0.0044 + 30000.0, 0.23, 1.1, -0.09274, 0.004422 + 30000.0, 0.23, 1.15, -0.08998, 0.004443 + 30000.0, 0.23, 1.2, -0.08722, 0.004463 + 30000.0, 0.23, 1.25, -0.08447, 0.004483 + 30000.0, 0.23, 1.3, -0.08171, 0.004501 + 30000.0, 0.23, 1.35, -0.07896, 0.004519 + 30000.0, 0.23, 1.4, -0.0762, 0.004536 + 30000.0, 0.23, 1.45, -0.07345, 0.004553 + 30000.0, 0.23, 1.5, -0.0707, 0.004568 + 30000.0, 0.23, 1.55, -0.06795, 0.004583 + 30000.0, 0.23, 1.6, -0.0652, 0.004598 + 30000.0, 0.23, 1.65, -0.06245, 0.004612 + 30000.0, 0.23, 1.7, -0.0597, 0.004625 + 30000.0, 0.23, 1.75, -0.05695, 0.004638 + 30000.0, 0.23, 1.8, -0.0542, 0.00465 + 30000.0, 0.23, 1.85, -0.05145, 0.004662 + 30000.0, 0.23, 1.9, -0.04871, 0.004673 + 30000.0, 0.23, 1.95, -0.04596, 0.004684 + 30000.0, 0.23, 2.0, -0.04321, 0.004695 + 30000.0, 0.23, 2.05, -0.04046, 0.004705 + 30000.0, 0.23, 2.1, -0.03771, 0.004715 + 30000.0, 0.23, 2.15, -0.03497, 0.004725 + 30000.0, 0.23, 2.2, -0.03222, 0.004735 + 30000.0, 0.23, 2.25, -0.02947, 0.004744 + 30000.0, 0.23, 2.3, -0.02672, 0.004754 + 30000.0, 0.23, 2.35, -0.02397, 0.004763 + 30000.0, 0.23, 2.4, -0.02122, 0.004772 + 30000.0, 0.23, 2.45, -0.01847, 0.004782 + 30000.0, 0.23, 2.5, -0.01572, 0.004791 + 30000.0, 0.23, 2.55, -0.01297, 0.0048 + 30000.0, 0.23, 2.6, -0.01022, 0.004809 + 30000.0, 0.23, 2.65, -0.007462, 0.004819 + 30000.0, 0.23, 2.7, -0.004707, 0.004828 + 30000.0, 0.23, 2.75, -0.001952, 0.004838 + 30000.0, 0.23, 2.8, 0.0008048, 0.004848 + 30000.0, 0.23, 2.85, 0.003563, 0.004858 + 30000.0, 0.23, 2.9, 0.006322, 0.004869 + 30000.0, 0.23, 2.95, 0.009082, 0.004879 + 30000.0, 0.23, 3.0, 0.01184, 0.004891 + 30000.0, 0.23, 3.05, 0.01461, 0.004902 + 30000.0, 0.23, 3.1, 0.01737, 0.004914 + 30000.0, 0.23, 3.15, 0.02014, 0.004926 + 30000.0, 0.23, 3.2, 0.02291, 0.004939 + 30000.0, 0.23, 3.25, 0.02568, 0.004953 + 30000.0, 0.23, 3.3, 0.02845, 0.004967 + 30000.0, 0.23, 3.35, 0.03122, 0.004981 + 30000.0, 0.23, 3.4, 0.034, 0.004997 + 30000.0, 0.23, 3.45, 0.03678, 0.005013 + 30000.0, 0.23, 3.5, 0.03956, 0.005029 + 30000.0, 0.23, 3.55, 0.04234, 0.005047 + 30000.0, 0.23, 3.6, 0.04512, 0.005065 + 30000.0, 0.23, 3.65, 0.04791, 0.005084 + 30000.0, 0.23, 3.7, 0.0507, 0.005103 + 30000.0, 0.23, 3.75, 0.05349, 0.005124 + 30000.0, 0.23, 3.8, 0.05629, 0.005145 + 30000.0, 0.23, 3.85, 0.05908, 0.005168 + 30000.0, 0.23, 3.9, 0.06188, 0.005191 + 30000.0, 0.23, 3.95, 0.06468, 0.005216 + 30000.0, 0.23, 4.0, 0.06749, 0.005241 + 30000.0, 0.23, 4.05, 0.07033, 0.005273 + 30000.0, 0.23, 4.1, 0.07318, 0.005305 + 30000.0, 0.23, 4.15, 0.07602, 0.005338 + 30000.0, 0.23, 4.2, 0.07887, 0.005372 + 30000.0, 0.23, 4.25, 0.08171, 0.005406 + 30000.0, 0.23, 4.3, 0.08456, 0.005442 + 30000.0, 0.23, 4.35, 0.0874, 0.005478 + 30000.0, 0.23, 4.4, 0.09025, 0.005516 + 30000.0, 0.23, 4.45, 0.0931, 0.005554 + 30000.0, 0.23, 4.5, 0.09594, 0.005592 + 30000.0, 0.23, 4.55, 0.09878, 0.005632 + 30000.0, 0.23, 4.6, 0.1016, 0.005672 + 30000.0, 0.23, 4.65, 0.1045, 0.005714 + 30000.0, 0.23, 4.7, 0.1073, 0.005756 + 30000.0, 0.23, 4.75, 0.1102, 0.005799 + 30000.0, 0.23, 4.8, 0.113, 0.005843 + 30000.0, 0.23, 4.85, 0.1158, 0.005887 + 30000.0, 0.23, 4.9, 0.1187, 0.005933 + 30000.0, 0.23, 4.95, 0.1215, 0.005979 + 30000.0, 0.23, 5.0, 0.1243, 0.006026 + 30000.0, 0.23, 5.05, 0.1271, 0.006073 + 30000.0, 0.23, 5.1, 0.13, 0.006122 + 30000.0, 0.23, 5.15, 0.1328, 0.006171 + 30000.0, 0.23, 5.2, 0.1356, 0.006221 + 30000.0, 0.23, 5.25, 0.1384, 0.006271 + 30000.0, 0.23, 5.3, 0.1412, 0.006323 + 30000.0, 0.23, 5.35, 0.144, 0.006375 + 30000.0, 0.23, 5.4, 0.1468, 0.006429 + 30000.0, 0.23, 5.45, 0.1496, 0.006483 + 30000.0, 0.23, 5.5, 0.1524, 0.006538 + 30000.0, 0.23, 5.55, 0.1552, 0.006593 + 30000.0, 0.23, 5.6, 0.158, 0.00665 + 30000.0, 0.23, 5.65, 0.1607, 0.006708 + 30000.0, 0.23, 5.7, 0.1635, 0.006766 + 30000.0, 0.23, 5.75, 0.1663, 0.006825 + 30000.0, 0.23, 5.8, 0.1691, 0.006885 + 30000.0, 0.23, 5.85, 0.1718, 0.006946 + 30000.0, 0.23, 5.9, 0.1746, 0.007008 + 30000.0, 0.23, 5.95, 0.1774, 0.00707 + 30000.0, 0.23, 6.0, 0.1801, 0.007134 + 30000.0, 0.23, 6.05, 0.1829, 0.007189 + 30000.0, 0.23, 6.1, 0.1857, 0.007245 + 30000.0, 0.23, 6.15, 0.1884, 0.007302 + 30000.0, 0.23, 6.2, 0.1912, 0.007359 + 30000.0, 0.23, 6.25, 0.1939, 0.007417 + 30000.0, 0.23, 6.3, 0.1967, 0.007476 + 30000.0, 0.23, 6.35, 0.1994, 0.007535 + 30000.0, 0.23, 6.4, 0.2022, 0.007596 + 30000.0, 0.23, 6.45, 0.2049, 0.007657 + 30000.0, 0.23, 6.5, 0.2076, 0.00772 + 30000.0, 0.23, 6.55, 0.2104, 0.007783 + 30000.0, 0.23, 6.6, 0.2131, 0.007848 + 30000.0, 0.23, 6.65, 0.2158, 0.007914 + 30000.0, 0.23, 6.7, 0.2185, 0.007982 + 30000.0, 0.23, 6.75, 0.2212, 0.008051 + 30000.0, 0.23, 6.8, 0.2239, 0.008121 + 30000.0, 0.23, 6.85, 0.2266, 0.008193 + 30000.0, 0.23, 6.9, 0.2293, 0.008266 + 30000.0, 0.23, 6.95, 0.2319, 0.008341 + 30000.0, 0.23, 7.0, 0.2346, 0.008418 + 30000.0, 0.23, 7.05, 0.2372, 0.008496 + 30000.0, 0.23, 7.1, 0.2399, 0.008576 + 30000.0, 0.23, 7.15, 0.2425, 0.008659 + 30000.0, 0.23, 7.2, 0.2451, 0.008743 + 30000.0, 0.23, 7.25, 0.2477, 0.008829 + 30000.0, 0.23, 7.3, 0.2503, 0.008918 + 30000.0, 0.23, 7.35, 0.2529, 0.009008 + 30000.0, 0.23, 7.4, 0.2555, 0.009101 + 30000.0, 0.23, 7.45, 0.2581, 0.009196 + 30000.0, 0.23, 7.5, 0.2606, 0.009294 + 30000.0, 0.23, 7.55, 0.2632, 0.009394 + 30000.0, 0.23, 7.6, 0.2657, 0.009497 + 30000.0, 0.23, 7.65, 0.2683, 0.009602 + 30000.0, 0.23, 7.7, 0.2708, 0.00971 + 30000.0, 0.23, 7.75, 0.2733, 0.00982 + 30000.0, 0.23, 7.8, 0.2758, 0.009934 + 30000.0, 0.23, 7.85, 0.2782, 0.01005 + 30000.0, 0.23, 7.9, 0.2807, 0.01017 + 30000.0, 0.23, 7.95, 0.2831, 0.01029 + 30000.0, 0.23, 8.0, 0.2856, 0.01042 + 30000.0, 0.23, 8.05, 0.2879, 0.01054 + 30000.0, 0.23, 8.1, 0.2902, 0.01068 + 30000.0, 0.23, 8.15, 0.2925, 0.01081 + 30000.0, 0.23, 8.2, 0.2948, 0.01095 + 30000.0, 0.23, 8.25, 0.297, 0.01109 + 30000.0, 0.23, 8.3, 0.2993, 0.01123 + 30000.0, 0.23, 8.35, 0.3015, 0.01138 + 30000.0, 0.23, 8.4, 0.3038, 0.01153 + 30000.0, 0.23, 8.45, 0.306, 0.01169 + 30000.0, 0.23, 8.5, 0.3082, 0.01185 + 30000.0, 0.23, 8.55, 0.3104, 0.01201 + 30000.0, 0.23, 8.6, 0.3125, 0.01218 + 30000.0, 0.23, 8.65, 0.3147, 0.01235 + 30000.0, 0.23, 8.7, 0.3169, 0.01253 + 30000.0, 0.23, 8.75, 0.319, 0.0127 + 30000.0, 0.23, 8.8, 0.3211, 0.01289 + 30000.0, 0.23, 8.85, 0.3232, 0.01308 + 30000.0, 0.23, 8.9, 0.3253, 0.01327 + 30000.0, 0.23, 8.95, 0.3274, 0.01346 + 30000.0, 0.23, 9.0, 0.3295, 0.01366 + 30000.0, 0.23, 9.05, 0.3315, 0.01387 + 30000.0, 0.23, 9.1, 0.3336, 0.01408 + 30000.0, 0.23, 9.15, 0.3356, 0.01429 + 30000.0, 0.23, 9.2, 0.3377, 0.01451 + 30000.0, 0.23, 9.25, 0.3397, 0.01474 + 30000.0, 0.23, 9.3, 0.3417, 0.01497 + 30000.0, 0.23, 9.35, 0.3437, 0.0152 + 30000.0, 0.23, 9.4, 0.3456, 0.01544 + 30000.0, 0.23, 9.45, 0.3476, 0.01568 + 30000.0, 0.23, 9.5, 0.3496, 0.01593 + 30000.0, 0.23, 9.55, 0.3515, 0.01618 + 30000.0, 0.23, 9.6, 0.3535, 0.01644 + 30000.0, 0.23, 9.65, 0.3554, 0.01671 + 30000.0, 0.23, 9.7, 0.3573, 0.01698 + 30000.0, 0.23, 9.75, 0.3592, 0.01725 + 30000.0, 0.23, 9.8, 0.3611, 0.01753 + 30000.0, 0.23, 9.85, 0.363, 0.01782 + 30000.0, 0.23, 9.9, 0.3648, 0.01811 + 30000.0, 0.23, 9.95, 0.3667, 0.01841 + 30000.0, 0.23, 10.0, 0.3685, 0.01872 + 30000.0, 0.23, 10.05, 0.3705, 0.01909 + 30000.0, 0.23, 10.1, 0.3724, 0.01947 + 30000.0, 0.23, 10.15, 0.3743, 0.01985 + 30000.0, 0.23, 10.2, 0.3762, 0.02024 + 30000.0, 0.23, 10.25, 0.378, 0.02064 + 30000.0, 0.23, 10.3, 0.3799, 0.02104 + 30000.0, 0.23, 10.35, 0.3818, 0.02145 + 30000.0, 0.23, 10.4, 0.3836, 0.02186 + 30000.0, 0.23, 10.45, 0.3854, 0.02227 + 30000.0, 0.23, 10.5, 0.3873, 0.02269 + 30000.0, 0.23, 10.55, 0.3891, 0.02311 + 30000.0, 0.23, 10.6, 0.3909, 0.02354 + 30000.0, 0.23, 10.65, 0.3926, 0.02397 + 30000.0, 0.23, 10.7, 0.3944, 0.0244 + 30000.0, 0.23, 10.75, 0.3962, 0.02484 + 30000.0, 0.23, 10.8, 0.3979, 0.02528 + 30000.0, 0.23, 10.85, 0.3996, 0.02573 + 30000.0, 0.23, 10.9, 0.4014, 0.02618 + 30000.0, 0.23, 10.95, 0.4031, 0.02663 + 30000.0, 0.23, 11.0, 0.4047, 0.02708 + 30000.0, 0.23, 11.05, 0.4064, 0.02754 + 30000.0, 0.23, 11.1, 0.4081, 0.02799 + 30000.0, 0.23, 11.15, 0.4097, 0.02845 + 30000.0, 0.23, 11.2, 0.4113, 0.02891 + 30000.0, 0.23, 11.25, 0.413, 0.02938 + 30000.0, 0.23, 11.3, 0.4146, 0.02984 + 30000.0, 0.23, 11.35, 0.4161, 0.03031 + 30000.0, 0.23, 11.4, 0.4177, 0.03078 + 30000.0, 0.23, 11.45, 0.4193, 0.03125 + 30000.0, 0.23, 11.5, 0.4208, 0.03172 + 30000.0, 0.23, 11.55, 0.4223, 0.03219 + 30000.0, 0.23, 11.6, 0.4238, 0.03266 + 30000.0, 0.23, 11.65, 0.4253, 0.03313 + 30000.0, 0.23, 11.7, 0.4267, 0.0336 + 30000.0, 0.23, 11.75, 0.4282, 0.03408 + 30000.0, 0.23, 11.8, 0.4296, 0.03455 + 30000.0, 0.23, 11.85, 0.431, 0.03502 + 30000.0, 0.23, 11.9, 0.4324, 0.03549 + 30000.0, 0.23, 11.95, 0.4338, 0.03596 + 30000.0, 0.23, 12.0, 0.4352, 0.03643 + 30000.0, 0.23, 12.05, 0.4365, 0.0369 + 30000.0, 0.23, 12.1, 0.4378, 0.03737 + 30000.0, 0.23, 12.15, 0.4391, 0.03783 + 30000.0, 0.23, 12.2, 0.4404, 0.0383 + 30000.0, 0.23, 12.25, 0.4417, 0.03876 + 30000.0, 0.23, 12.3, 0.4429, 0.03923 + 30000.0, 0.23, 12.35, 0.4441, 0.03968 + 30000.0, 0.23, 12.4, 0.4453, 0.04014 + 30000.0, 0.23, 12.45, 0.4465, 0.0406 + 30000.0, 0.23, 12.5, 0.4477, 0.04105 + 30000.0, 0.23, 12.55, 0.4488, 0.0415 + 30000.0, 0.23, 12.6, 0.4499, 0.04195 + 30000.0, 0.23, 12.65, 0.451, 0.04239 + 30000.0, 0.23, 12.7, 0.4521, 0.04283 + 30000.0, 0.23, 12.75, 0.4532, 0.04327 + 30000.0, 0.23, 12.8, 0.4542, 0.04371 + 30000.0, 0.23, 12.85, 0.4552, 0.04414 + 30000.0, 0.23, 12.9, 0.4562, 0.04456 + 30000.0, 0.23, 12.95, 0.4572, 0.04499 + 30000.0, 0.23, 13.0, 0.4581, 0.0454 + 30000.0, 0.23, 13.05, 0.459, 0.04582 + 30000.0, 0.23, 13.1, 0.4599, 0.04623 + 30000.0, 0.23, 13.15, 0.4608, 0.04663 + 30000.0, 0.23, 13.2, 0.4617, 0.04703 + 30000.0, 0.23, 13.25, 0.4625, 0.04743 + 30000.0, 0.23, 13.3, 0.4633, 0.04782 + 30000.0, 0.23, 13.35, 0.4641, 0.0482 + 30000.0, 0.23, 13.4, 0.4648, 0.04858 + 30000.0, 0.23, 13.45, 0.4656, 0.04895 + 30000.0, 0.23, 13.5, 0.4663, 0.04932 + 30000.0, 0.23, 13.55, 0.467, 0.04968 + 30000.0, 0.23, 13.6, 0.4676, 0.05004 + 30000.0, 0.23, 13.65, 0.4682, 0.05038 + 30000.0, 0.23, 13.7, 0.4688, 0.05073 + 30000.0, 0.23, 13.75, 0.4694, 0.05106 + 30000.0, 0.23, 13.8, 0.47, 0.05139 + 30000.0, 0.23, 13.85, 0.4705, 0.05171 + 30000.0, 0.23, 13.9, 0.471, 0.05202 + 30000.0, 0.23, 13.95, 0.4715, 0.05233 + 30000.0, 0.23, 14.0, 0.4719, 0.05263 + 30000.0, 0.23, 14.05, 0.4723, 0.05292 + 30000.0, 0.23, 14.1, 0.4727, 0.0532 + 30000.0, 0.23, 14.15, 0.4731, 0.05348 + 30000.0, 0.23, 14.2, 0.4734, 0.05374 + 30000.0, 0.23, 14.25, 0.4737, 0.054 + 30000.0, 0.23, 14.3, 0.474, 0.05425 + 30000.0, 0.23, 14.35, 0.4743, 0.05449 + 30000.0, 0.23, 14.4, 0.4745, 0.05472 + 30000.0, 0.23, 14.45, 0.4747, 0.05495 + 30000.0, 0.23, 14.5, 0.4749, 0.05516 + 30000.0, 0.23, 14.55, 0.475, 0.05536 + 30000.0, 0.23, 14.6, 0.4751, 0.05556 + 30000.0, 0.23, 14.65, 0.4752, 0.05574 + 30000.0, 0.23, 14.7, 0.4752, 0.05592 + 30000.0, 0.23, 14.75, 0.4752, 0.05608 + 30000.0, 0.23, 14.8, 0.4752, 0.05623 + 30000.0, 0.23, 14.85, 0.4752, 0.05638 + 30000.0, 0.23, 14.9, 0.4751, 0.05651 + 30000.0, 0.23, 14.95, 0.475, 0.05663 + 30000.0, 0.23, 15.0, 0.4749, 0.05674 + 30000.0, 0.23, 15.05, 0.4747, 0.05684 + 30000.0, 0.28, 0.0, -0.1263, -0.02898 + 30000.0, 0.28, 0.05, -0.1256, -0.02855 + 30000.0, 0.28, 0.1, -0.1248, -0.02811 + 30000.0, 0.28, 0.15, -0.1238, -0.02766 + 30000.0, 0.28, 0.2, -0.1226, -0.0272 + 30000.0, 0.28, 0.25, -0.1214, -0.02673 + 30000.0, 0.28, 0.3, -0.12, -0.02625 + 30000.0, 0.28, 0.35, -0.1185, -0.02576 + 30000.0, 0.28, 0.4, -0.1169, -0.02525 + 30000.0, 0.28, 0.45, -0.1151, -0.02474 + 30000.0, 0.28, 0.5, -0.1133, -0.02422 + 30000.0, 0.28, 0.55, -0.1113, -0.02368 + 30000.0, 0.28, 0.6, -0.1092, -0.02314 + 30000.0, 0.28, 0.65, -0.107, -0.0226 + 30000.0, 0.28, 0.7, -0.1048, -0.02204 + 30000.0, 0.28, 0.75, -0.1024, -0.02147 + 30000.0, 0.28, 0.8, -0.09992, -0.0209 + 30000.0, 0.28, 0.85, -0.09737, -0.02033 + 30000.0, 0.28, 0.9, -0.09473, -0.01974 + 30000.0, 0.28, 0.95, -0.092, -0.01915 + 30000.0, 0.28, 1.0, -0.0892, -0.01855 + 30000.0, 0.28, 1.05, -0.08632, -0.01795 + 30000.0, 0.28, 1.1, -0.08337, -0.01735 + 30000.0, 0.28, 1.15, -0.08034, -0.01674 + 30000.0, 0.28, 1.2, -0.07726, -0.01612 + 30000.0, 0.28, 1.25, -0.07411, -0.0155 + 30000.0, 0.28, 1.3, -0.0709, -0.01488 + 30000.0, 0.28, 1.35, -0.06764, -0.01425 + 30000.0, 0.28, 1.4, -0.06432, -0.01363 + 30000.0, 0.28, 1.45, -0.06096, -0.013 + 30000.0, 0.28, 1.5, -0.05755, -0.01237 + 30000.0, 0.28, 1.55, -0.0541, -0.01173 + 30000.0, 0.28, 1.6, -0.05061, -0.0111 + 30000.0, 0.28, 1.65, -0.04709, -0.01046 + 30000.0, 0.28, 1.7, -0.04353, -0.009826 + 30000.0, 0.28, 1.75, -0.03995, -0.00919 + 30000.0, 0.28, 1.8, -0.03634, -0.008555 + 30000.0, 0.28, 1.85, -0.03271, -0.00792 + 30000.0, 0.28, 1.9, -0.02906, -0.007287 + 30000.0, 0.28, 1.95, -0.0254, -0.006655 + 30000.0, 0.28, 2.0, -0.02172, -0.006024 + 30000.0, 0.28, 2.05, -0.01804, -0.005396 + 30000.0, 0.28, 2.1, -0.01436, -0.004771 + 30000.0, 0.28, 2.15, -0.01067, -0.004149 + 30000.0, 0.28, 2.2, -0.006986, -0.00353 + 30000.0, 0.28, 2.25, -0.003308, -0.002914 + 30000.0, 0.28, 2.3, 0.0003613, -0.002303 + 30000.0, 0.28, 2.35, 0.004018, -0.001697 + 30000.0, 0.28, 2.4, 0.007658, -0.001095 + 30000.0, 0.28, 2.45, 0.01128, -0.0004983 + 30000.0, 0.28, 2.5, 0.01488, 9.267e-05 + 30000.0, 0.28, 2.55, 0.01845, 0.0006776 + 30000.0, 0.28, 2.6, 0.02199, 0.001256 + 30000.0, 0.28, 2.65, 0.0255, 0.001828 + 30000.0, 0.28, 2.7, 0.02897, 0.002393 + 30000.0, 0.28, 2.75, 0.0324, 0.00295 + 30000.0, 0.28, 2.8, 0.03579, 0.003499 + 30000.0, 0.28, 2.85, 0.03914, 0.00404 + 30000.0, 0.28, 2.9, 0.04243, 0.004573 + 30000.0, 0.28, 2.95, 0.04567, 0.005096 + 30000.0, 0.28, 3.0, 0.04885, 0.005611 + 30000.0, 0.28, 3.05, 0.05197, 0.006115 + 30000.0, 0.28, 3.1, 0.05503, 0.006609 + 30000.0, 0.28, 3.15, 0.05802, 0.007093 + 30000.0, 0.28, 3.2, 0.06094, 0.007566 + 30000.0, 0.28, 3.25, 0.06379, 0.008028 + 30000.0, 0.28, 3.3, 0.06656, 0.008478 + 30000.0, 0.28, 3.35, 0.06924, 0.008916 + 30000.0, 0.28, 3.4, 0.07185, 0.009341 + 30000.0, 0.28, 3.45, 0.07436, 0.009754 + 30000.0, 0.28, 3.5, 0.07679, 0.01015 + 30000.0, 0.28, 3.55, 0.07912, 0.01054 + 30000.0, 0.28, 3.6, 0.08136, 0.01091 + 30000.0, 0.28, 3.65, 0.08349, 0.01127 + 30000.0, 0.28, 3.7, 0.08552, 0.01161 + 30000.0, 0.28, 3.75, 0.08744, 0.01194 + 30000.0, 0.28, 3.8, 0.08924, 0.01226 + 30000.0, 0.28, 3.85, 0.09094, 0.01255 + 30000.0, 0.28, 3.9, 0.09251, 0.01283 + 30000.0, 0.28, 3.95, 0.09397, 0.0131 + 30000.0, 0.28, 4.0, 0.0953, 0.01335 + 30000.0, 0.28, 4.05, 0.09555, 0.01353 + 30000.0, 0.28, 4.1, 0.09573, 0.0137 + 30000.0, 0.28, 4.15, 0.09583, 0.01386 + 30000.0, 0.28, 4.2, 0.09587, 0.01399 + 30000.0, 0.28, 4.25, 0.09585, 0.01412 + 30000.0, 0.28, 4.3, 0.09576, 0.01423 + 30000.0, 0.28, 4.35, 0.09562, 0.01432 + 30000.0, 0.28, 4.4, 0.09542, 0.0144 + 30000.0, 0.28, 4.45, 0.09518, 0.01447 + 30000.0, 0.28, 4.5, 0.09489, 0.01452 + 30000.0, 0.28, 4.55, 0.09456, 0.01455 + 30000.0, 0.28, 4.6, 0.09419, 0.01457 + 30000.0, 0.28, 4.65, 0.09379, 0.01458 + 30000.0, 0.28, 4.7, 0.09336, 0.01456 + 30000.0, 0.28, 4.75, 0.09291, 0.01454 + 30000.0, 0.28, 4.8, 0.09243, 0.0145 + 30000.0, 0.28, 4.85, 0.09193, 0.01444 + 30000.0, 0.28, 4.9, 0.09143, 0.01437 + 30000.0, 0.28, 4.95, 0.09091, 0.01428 + 30000.0, 0.28, 5.0, 0.09039, 0.01418 + 30000.0, 0.28, 5.05, 0.08969, 0.01407 + 30000.0, 0.28, 5.1, 0.089, 0.01395 + 30000.0, 0.28, 5.15, 0.08833, 0.01381 + 30000.0, 0.28, 5.2, 0.08766, 0.01365 + 30000.0, 0.28, 5.25, 0.08703, 0.01348 + 30000.0, 0.28, 5.3, 0.08642, 0.01329 + 30000.0, 0.28, 5.35, 0.08585, 0.01309 + 30000.0, 0.28, 5.4, 0.08532, 0.01287 + 30000.0, 0.28, 5.45, 0.08484, 0.01263 + 30000.0, 0.28, 5.5, 0.08442, 0.01238 + 30000.0, 0.28, 5.55, 0.08406, 0.01211 + 30000.0, 0.28, 5.6, 0.08376, 0.01182 + 30000.0, 0.28, 5.65, 0.08354, 0.01152 + 30000.0, 0.28, 5.7, 0.08341, 0.0112 + 30000.0, 0.28, 5.75, 0.08336, 0.01086 + 30000.0, 0.28, 5.8, 0.0834, 0.01051 + 30000.0, 0.28, 5.85, 0.08355, 0.01014 + 30000.0, 0.28, 5.9, 0.0838, 0.009749 + 30000.0, 0.28, 5.95, 0.08416, 0.009342 + 30000.0, 0.28, 6.0, 0.08465, 0.008917 + 30000.0, 0.28, 6.05, 0.08683, 0.008398 + 30000.0, 0.28, 6.1, 0.0892, 0.007858 + 30000.0, 0.28, 6.15, 0.09177, 0.007298 + 30000.0, 0.28, 6.2, 0.09453, 0.006717 + 30000.0, 0.28, 6.25, 0.09747, 0.006116 + 30000.0, 0.28, 6.3, 0.1006, 0.005495 + 30000.0, 0.28, 6.35, 0.1039, 0.004855 + 30000.0, 0.28, 6.4, 0.1073, 0.004196 + 30000.0, 0.28, 6.45, 0.1109, 0.003519 + 30000.0, 0.28, 6.5, 0.1147, 0.002825 + 30000.0, 0.28, 6.55, 0.1186, 0.002112 + 30000.0, 0.28, 6.6, 0.1227, 0.001383 + 30000.0, 0.28, 6.65, 0.1269, 0.000637 + 30000.0, 0.28, 6.7, 0.1313, -0.0001252 + 30000.0, 0.28, 6.75, 0.1358, -0.0009032 + 30000.0, 0.28, 6.8, 0.1404, -0.001697 + 30000.0, 0.28, 6.85, 0.1451, -0.002505 + 30000.0, 0.28, 6.9, 0.1499, -0.003328 + 30000.0, 0.28, 6.95, 0.1549, -0.004165 + 30000.0, 0.28, 7.0, 0.16, -0.005016 + 30000.0, 0.28, 7.05, 0.1651, -0.00588 + 30000.0, 0.28, 7.1, 0.1704, -0.006757 + 30000.0, 0.28, 7.15, 0.1757, -0.007646 + 30000.0, 0.28, 7.2, 0.1812, -0.008547 + 30000.0, 0.28, 7.25, 0.1867, -0.00946 + 30000.0, 0.28, 7.3, 0.1923, -0.01038 + 30000.0, 0.28, 7.35, 0.1979, -0.01132 + 30000.0, 0.28, 7.4, 0.2037, -0.01226 + 30000.0, 0.28, 7.45, 0.2094, -0.01322 + 30000.0, 0.28, 7.5, 0.2153, -0.01419 + 30000.0, 0.28, 7.55, 0.2212, -0.01516 + 30000.0, 0.28, 7.6, 0.2271, -0.01614 + 30000.0, 0.28, 7.65, 0.2331, -0.01713 + 30000.0, 0.28, 7.7, 0.2391, -0.01813 + 30000.0, 0.28, 7.75, 0.2451, -0.01914 + 30000.0, 0.28, 7.8, 0.2512, -0.02015 + 30000.0, 0.28, 7.85, 0.2573, -0.02117 + 30000.0, 0.28, 7.9, 0.2634, -0.0222 + 30000.0, 0.28, 7.95, 0.2695, -0.02323 + 30000.0, 0.28, 8.0, 0.2756, -0.02426 + 30000.0, 0.28, 8.05, 0.2804, -0.02522 + 30000.0, 0.28, 8.1, 0.2852, -0.02618 + 30000.0, 0.28, 8.15, 0.29, -0.02715 + 30000.0, 0.28, 8.2, 0.2948, -0.02812 + 30000.0, 0.28, 8.25, 0.2996, -0.0291 + 30000.0, 0.28, 8.3, 0.3044, -0.03008 + 30000.0, 0.28, 8.35, 0.3092, -0.03106 + 30000.0, 0.28, 8.4, 0.3139, -0.03205 + 30000.0, 0.28, 8.45, 0.3187, -0.03304 + 30000.0, 0.28, 8.5, 0.3235, -0.03404 + 30000.0, 0.28, 8.55, 0.3283, -0.03504 + 30000.0, 0.28, 8.6, 0.3331, -0.03605 + 30000.0, 0.28, 8.65, 0.3378, -0.03705 + 30000.0, 0.28, 8.7, 0.3426, -0.03807 + 30000.0, 0.28, 8.75, 0.3474, -0.03908 + 30000.0, 0.28, 8.8, 0.3521, -0.0401 + 30000.0, 0.28, 8.85, 0.3569, -0.04112 + 30000.0, 0.28, 8.9, 0.3617, -0.04215 + 30000.0, 0.28, 8.95, 0.3664, -0.04318 + 30000.0, 0.28, 9.0, 0.3712, -0.04421 + 30000.0, 0.28, 9.05, 0.3759, -0.04524 + 30000.0, 0.28, 9.1, 0.3807, -0.04628 + 30000.0, 0.28, 9.15, 0.3854, -0.04732 + 30000.0, 0.28, 9.2, 0.3901, -0.04836 + 30000.0, 0.28, 9.25, 0.3949, -0.0494 + 30000.0, 0.28, 9.3, 0.3996, -0.05045 + 30000.0, 0.28, 9.35, 0.4043, -0.0515 + 30000.0, 0.28, 9.4, 0.409, -0.05255 + 30000.0, 0.28, 9.45, 0.4137, -0.0536 + 30000.0, 0.28, 9.5, 0.4185, -0.05466 + 30000.0, 0.28, 9.55, 0.4232, -0.05572 + 30000.0, 0.28, 9.6, 0.4279, -0.05678 + 30000.0, 0.28, 9.65, 0.4325, -0.05784 + 30000.0, 0.28, 9.7, 0.4372, -0.0589 + 30000.0, 0.28, 9.75, 0.4419, -0.05996 + 30000.0, 0.28, 9.8, 0.4466, -0.06103 + 30000.0, 0.28, 9.85, 0.4513, -0.06209 + 30000.0, 0.28, 9.9, 0.4559, -0.06316 + 30000.0, 0.28, 9.95, 0.4606, -0.06423 + 30000.0, 0.28, 10.0, 0.4652, -0.0653 + 30000.0, 0.28, 10.05, 0.4699, -0.0664 + 30000.0, 0.28, 10.1, 0.4746, -0.0675 + 30000.0, 0.28, 10.15, 0.4792, -0.0686 + 30000.0, 0.28, 10.2, 0.4839, -0.06971 + 30000.0, 0.28, 10.25, 0.4885, -0.07081 + 30000.0, 0.28, 10.3, 0.4931, -0.07191 + 30000.0, 0.28, 10.35, 0.4978, -0.07302 + 30000.0, 0.28, 10.4, 0.5024, -0.07412 + 30000.0, 0.28, 10.45, 0.507, -0.07522 + 30000.0, 0.28, 10.5, 0.5116, -0.07632 + 30000.0, 0.28, 10.55, 0.5162, -0.07741 + 30000.0, 0.28, 10.6, 0.5207, -0.07851 + 30000.0, 0.28, 10.65, 0.5253, -0.07961 + 30000.0, 0.28, 10.7, 0.5299, -0.0807 + 30000.0, 0.28, 10.75, 0.5344, -0.08179 + 30000.0, 0.28, 10.8, 0.539, -0.08288 + 30000.0, 0.28, 10.85, 0.5435, -0.08396 + 30000.0, 0.28, 10.9, 0.548, -0.08504 + 30000.0, 0.28, 10.95, 0.5525, -0.08612 + 30000.0, 0.28, 11.0, 0.557, -0.0872 + 30000.0, 0.28, 11.05, 0.5615, -0.08827 + 30000.0, 0.28, 11.1, 0.566, -0.08934 + 30000.0, 0.28, 11.15, 0.5705, -0.0904 + 30000.0, 0.28, 11.2, 0.5749, -0.09146 + 30000.0, 0.28, 11.25, 0.5794, -0.09252 + 30000.0, 0.28, 11.3, 0.5838, -0.09357 + 30000.0, 0.28, 11.35, 0.5882, -0.09461 + 30000.0, 0.28, 11.4, 0.5927, -0.09566 + 30000.0, 0.28, 11.45, 0.597, -0.09669 + 30000.0, 0.28, 11.5, 0.6014, -0.09772 + 30000.0, 0.28, 11.55, 0.6058, -0.09874 + 30000.0, 0.28, 11.6, 0.6102, -0.09976 + 30000.0, 0.28, 11.65, 0.6145, -0.1008 + 30000.0, 0.28, 11.7, 0.6188, -0.1018 + 30000.0, 0.28, 11.75, 0.6232, -0.1028 + 30000.0, 0.28, 11.8, 0.6275, -0.1038 + 30000.0, 0.28, 11.85, 0.6318, -0.1048 + 30000.0, 0.28, 11.9, 0.636, -0.1057 + 30000.0, 0.28, 11.95, 0.6403, -0.1067 + 30000.0, 0.28, 12.0, 0.6445, -0.1077 + 30000.0, 0.28, 12.05, 0.6488, -0.1086 + 30000.0, 0.28, 12.1, 0.653, -0.1096 + 30000.0, 0.28, 12.15, 0.6572, -0.1105 + 30000.0, 0.28, 12.2, 0.6614, -0.1114 + 30000.0, 0.28, 12.25, 0.6655, -0.1123 + 30000.0, 0.28, 12.3, 0.6697, -0.1133 + 30000.0, 0.28, 12.35, 0.6738, -0.1142 + 30000.0, 0.28, 12.4, 0.678, -0.115 + 30000.0, 0.28, 12.45, 0.6821, -0.1159 + 30000.0, 0.28, 12.5, 0.6861, -0.1168 + 30000.0, 0.28, 12.55, 0.6902, -0.1177 + 30000.0, 0.28, 12.6, 0.6943, -0.1185 + 30000.0, 0.28, 12.65, 0.6983, -0.1194 + 30000.0, 0.28, 12.7, 0.7023, -0.1202 + 30000.0, 0.28, 12.75, 0.7063, -0.121 + 30000.0, 0.28, 12.8, 0.7103, -0.1218 + 30000.0, 0.28, 12.85, 0.7143, -0.1226 + 30000.0, 0.28, 12.9, 0.7182, -0.1234 + 30000.0, 0.28, 12.95, 0.7221, -0.1242 + 30000.0, 0.28, 13.0, 0.726, -0.1249 + 30000.0, 0.28, 13.05, 0.7299, -0.1257 + 30000.0, 0.28, 13.1, 0.7338, -0.1264 + 30000.0, 0.28, 13.15, 0.7376, -0.1271 + 30000.0, 0.28, 13.2, 0.7415, -0.1278 + 30000.0, 0.28, 13.25, 0.7453, -0.1285 + 30000.0, 0.28, 13.3, 0.7491, -0.1292 + 30000.0, 0.28, 13.35, 0.7528, -0.1299 + 30000.0, 0.28, 13.4, 0.7566, -0.1305 + 30000.0, 0.28, 13.45, 0.7603, -0.1312 + 30000.0, 0.28, 13.5, 0.764, -0.1318 + 30000.0, 0.28, 13.55, 0.7677, -0.1324 + 30000.0, 0.28, 13.6, 0.7713, -0.133 + 30000.0, 0.28, 13.65, 0.775, -0.1336 + 30000.0, 0.28, 13.7, 0.7786, -0.1341 + 30000.0, 0.28, 13.75, 0.7822, -0.1347 + 30000.0, 0.28, 13.8, 0.7858, -0.1352 + 30000.0, 0.28, 13.85, 0.7893, -0.1357 + 30000.0, 0.28, 13.9, 0.7928, -0.1362 + 30000.0, 0.28, 13.95, 0.7963, -0.1367 + 30000.0, 0.28, 14.0, 0.7998, -0.1372 + 30000.0, 0.28, 14.05, 0.8033, -0.1377 + 30000.0, 0.28, 14.1, 0.8067, -0.1381 + 30000.0, 0.28, 14.15, 0.8101, -0.1385 + 30000.0, 0.28, 14.2, 0.8135, -0.1389 + 30000.0, 0.28, 14.25, 0.8168, -0.1393 + 30000.0, 0.28, 14.3, 0.8202, -0.1397 + 30000.0, 0.28, 14.35, 0.8235, -0.14 + 30000.0, 0.28, 14.4, 0.8268, -0.1403 + 30000.0, 0.28, 14.45, 0.83, -0.1406 + 30000.0, 0.28, 14.5, 0.8333, -0.1409 + 30000.0, 0.28, 14.55, 0.8365, -0.1412 + 30000.0, 0.28, 14.6, 0.8397, -0.1414 + 30000.0, 0.28, 14.65, 0.8428, -0.1417 + 30000.0, 0.28, 14.7, 0.8459, -0.1419 + 30000.0, 0.28, 14.75, 0.849, -0.1421 + 30000.0, 0.28, 14.8, 0.8521, -0.1423 + 30000.0, 0.28, 14.85, 0.8552, -0.1424 + 30000.0, 0.28, 14.9, 0.8582, -0.1425 + 30000.0, 0.28, 14.95, 0.8612, -0.1426 + 30000.0, 0.28, 15.0, 0.8642, -0.1427 + 30000.0, 0.28, 15.05, 0.8671, -0.1428 + 30000.0, 0.33, 0.0, -0.108, -0.04833 + 30000.0, 0.33, 0.05, -0.1085, -0.04769 + 30000.0, 0.33, 0.1, -0.1088, -0.04702 + 30000.0, 0.33, 0.15, -0.1089, -0.04634 + 30000.0, 0.33, 0.2, -0.1088, -0.04564 + 30000.0, 0.33, 0.25, -0.1085, -0.04492 + 30000.0, 0.33, 0.3, -0.108, -0.04417 + 30000.0, 0.33, 0.35, -0.1073, -0.04342 + 30000.0, 0.33, 0.4, -0.1063, -0.04264 + 30000.0, 0.33, 0.45, -0.1052, -0.04185 + 30000.0, 0.33, 0.5, -0.1039, -0.04104 + 30000.0, 0.33, 0.55, -0.1025, -0.04022 + 30000.0, 0.33, 0.6, -0.1009, -0.03938 + 30000.0, 0.33, 0.65, -0.09905, -0.03853 + 30000.0, 0.33, 0.7, -0.09709, -0.03767 + 30000.0, 0.33, 0.75, -0.09498, -0.03679 + 30000.0, 0.33, 0.8, -0.09272, -0.0359 + 30000.0, 0.33, 0.85, -0.09031, -0.035 + 30000.0, 0.33, 0.9, -0.08776, -0.03409 + 30000.0, 0.33, 0.95, -0.08509, -0.03316 + 30000.0, 0.33, 1.0, -0.08228, -0.03223 + 30000.0, 0.33, 1.05, -0.07936, -0.03129 + 30000.0, 0.33, 1.1, -0.07631, -0.03034 + 30000.0, 0.33, 1.15, -0.07316, -0.02938 + 30000.0, 0.33, 1.2, -0.0699, -0.02842 + 30000.0, 0.33, 1.25, -0.06654, -0.02745 + 30000.0, 0.33, 1.3, -0.06309, -0.02647 + 30000.0, 0.33, 1.35, -0.05955, -0.02549 + 30000.0, 0.33, 1.4, -0.05592, -0.0245 + 30000.0, 0.33, 1.45, -0.05222, -0.02351 + 30000.0, 0.33, 1.5, -0.04844, -0.02251 + 30000.0, 0.33, 1.55, -0.0446, -0.02152 + 30000.0, 0.33, 1.6, -0.0407, -0.02051 + 30000.0, 0.33, 1.65, -0.03674, -0.01951 + 30000.0, 0.33, 1.7, -0.03273, -0.01851 + 30000.0, 0.33, 1.75, -0.02867, -0.01751 + 30000.0, 0.33, 1.8, -0.02457, -0.0165 + 30000.0, 0.33, 1.85, -0.02044, -0.0155 + 30000.0, 0.33, 1.9, -0.01629, -0.0145 + 30000.0, 0.33, 1.95, -0.0121, -0.0135 + 30000.0, 0.33, 2.0, -0.007905, -0.01251 + 30000.0, 0.33, 2.05, -0.003693, -0.01152 + 30000.0, 0.33, 2.1, 0.0005262, -0.01053 + 30000.0, 0.33, 2.15, 0.004746, -0.009543 + 30000.0, 0.33, 2.2, 0.008963, -0.008564 + 30000.0, 0.33, 2.25, 0.01317, -0.007591 + 30000.0, 0.33, 2.3, 0.01736, -0.006625 + 30000.0, 0.33, 2.35, 0.02153, -0.005665 + 30000.0, 0.33, 2.4, 0.02568, -0.004713 + 30000.0, 0.33, 2.45, 0.02979, -0.003769 + 30000.0, 0.33, 2.5, 0.03387, -0.002835 + 30000.0, 0.33, 2.55, 0.0379, -0.001909 + 30000.0, 0.33, 2.6, 0.04189, -0.0009942 + 30000.0, 0.33, 2.65, 0.04582, -8.974e-05 + 30000.0, 0.33, 2.7, 0.04969, 0.0008033 + 30000.0, 0.33, 2.75, 0.0535, 0.001684 + 30000.0, 0.33, 2.8, 0.05724, 0.002553 + 30000.0, 0.33, 2.85, 0.06091, 0.003408 + 30000.0, 0.33, 2.9, 0.06449, 0.00425 + 30000.0, 0.33, 2.95, 0.06799, 0.005077 + 30000.0, 0.33, 3.0, 0.0714, 0.005889 + 30000.0, 0.33, 3.05, 0.07471, 0.006685 + 30000.0, 0.33, 3.1, 0.07791, 0.007465 + 30000.0, 0.33, 3.15, 0.08101, 0.008228 + 30000.0, 0.33, 3.2, 0.084, 0.008973 + 30000.0, 0.33, 3.25, 0.08686, 0.009701 + 30000.0, 0.33, 3.3, 0.0896, 0.01041 + 30000.0, 0.33, 3.35, 0.09222, 0.0111 + 30000.0, 0.33, 3.4, 0.09469, 0.01177 + 30000.0, 0.33, 3.45, 0.09703, 0.01242 + 30000.0, 0.33, 3.5, 0.09922, 0.01304 + 30000.0, 0.33, 3.55, 0.1013, 0.01365 + 30000.0, 0.33, 3.6, 0.1031, 0.01423 + 30000.0, 0.33, 3.65, 0.1049, 0.01479 + 30000.0, 0.33, 3.7, 0.1064, 0.01533 + 30000.0, 0.33, 3.75, 0.1078, 0.01584 + 30000.0, 0.33, 3.8, 0.109, 0.01633 + 30000.0, 0.33, 3.85, 0.11, 0.01679 + 30000.0, 0.33, 3.9, 0.1108, 0.01722 + 30000.0, 0.33, 3.95, 0.1114, 0.01763 + 30000.0, 0.33, 4.0, 0.1119, 0.01801 + 30000.0, 0.33, 4.05, 0.1105, 0.01829 + 30000.0, 0.33, 4.1, 0.1091, 0.01854 + 30000.0, 0.33, 4.15, 0.1076, 0.01876 + 30000.0, 0.33, 4.2, 0.1059, 0.01897 + 30000.0, 0.33, 4.25, 0.1041, 0.01914 + 30000.0, 0.33, 4.3, 0.1023, 0.0193 + 30000.0, 0.33, 4.35, 0.1003, 0.01943 + 30000.0, 0.33, 4.4, 0.0983, 0.01953 + 30000.0, 0.33, 4.45, 0.09619, 0.01962 + 30000.0, 0.33, 4.5, 0.09401, 0.01967 + 30000.0, 0.33, 4.55, 0.09177, 0.01971 + 30000.0, 0.33, 4.6, 0.08947, 0.01972 + 30000.0, 0.33, 4.65, 0.08711, 0.0197 + 30000.0, 0.33, 4.7, 0.08471, 0.01966 + 30000.0, 0.33, 4.75, 0.08227, 0.0196 + 30000.0, 0.33, 4.8, 0.0798, 0.01951 + 30000.0, 0.33, 4.85, 0.07729, 0.01939 + 30000.0, 0.33, 4.9, 0.07477, 0.01926 + 30000.0, 0.33, 4.95, 0.07224, 0.0191 + 30000.0, 0.33, 5.0, 0.06969, 0.01891 + 30000.0, 0.33, 5.05, 0.06689, 0.01871 + 30000.0, 0.33, 5.1, 0.0641, 0.01849 + 30000.0, 0.33, 5.15, 0.06133, 0.01825 + 30000.0, 0.33, 5.2, 0.05858, 0.01798 + 30000.0, 0.33, 5.25, 0.05587, 0.01768 + 30000.0, 0.33, 5.3, 0.05322, 0.01736 + 30000.0, 0.33, 5.35, 0.05062, 0.01701 + 30000.0, 0.33, 5.4, 0.04809, 0.01664 + 30000.0, 0.33, 5.45, 0.04564, 0.01624 + 30000.0, 0.33, 5.5, 0.04329, 0.01581 + 30000.0, 0.33, 5.55, 0.04103, 0.01536 + 30000.0, 0.33, 5.6, 0.03888, 0.01488 + 30000.0, 0.33, 5.65, 0.03685, 0.01437 + 30000.0, 0.33, 5.7, 0.03496, 0.01383 + 30000.0, 0.33, 5.75, 0.0332, 0.01327 + 30000.0, 0.33, 5.8, 0.0316, 0.01268 + 30000.0, 0.33, 5.85, 0.03015, 0.01206 + 30000.0, 0.33, 5.9, 0.02888, 0.01141 + 30000.0, 0.33, 5.95, 0.02779, 0.01073 + 30000.0, 0.33, 6.0, 0.02689, 0.01002 + 30000.0, 0.33, 6.05, 0.02866, 0.00917 + 30000.0, 0.33, 6.1, 0.03074, 0.00828 + 30000.0, 0.33, 6.15, 0.03313, 0.007357 + 30000.0, 0.33, 6.2, 0.03581, 0.006401 + 30000.0, 0.33, 6.25, 0.03879, 0.005411 + 30000.0, 0.33, 6.3, 0.04205, 0.00439 + 30000.0, 0.33, 6.35, 0.04558, 0.003338 + 30000.0, 0.33, 6.4, 0.04938, 0.002255 + 30000.0, 0.33, 6.45, 0.05344, 0.001142 + 30000.0, 0.33, 6.5, 0.05776, -3.325e-07 + 30000.0, 0.33, 6.55, 0.06231, -0.001172 + 30000.0, 0.33, 6.6, 0.0671, -0.002371 + 30000.0, 0.33, 6.65, 0.07212, -0.003598 + 30000.0, 0.33, 6.7, 0.07736, -0.004852 + 30000.0, 0.33, 6.75, 0.08281, -0.006132 + 30000.0, 0.33, 6.8, 0.08847, -0.007437 + 30000.0, 0.33, 6.85, 0.09432, -0.008768 + 30000.0, 0.33, 6.9, 0.1004, -0.01012 + 30000.0, 0.33, 6.95, 0.1066, -0.0115 + 30000.0, 0.33, 7.0, 0.113, -0.0129 + 30000.0, 0.33, 7.05, 0.1195, -0.01433 + 30000.0, 0.33, 7.1, 0.1263, -0.01577 + 30000.0, 0.33, 7.15, 0.1331, -0.01724 + 30000.0, 0.33, 7.2, 0.1401, -0.01873 + 30000.0, 0.33, 7.25, 0.1473, -0.02024 + 30000.0, 0.33, 7.3, 0.1545, -0.02176 + 30000.0, 0.33, 7.35, 0.1619, -0.02331 + 30000.0, 0.33, 7.4, 0.1694, -0.02487 + 30000.0, 0.33, 7.45, 0.177, -0.02645 + 30000.0, 0.33, 7.5, 0.1847, -0.02805 + 30000.0, 0.33, 7.55, 0.1925, -0.02967 + 30000.0, 0.33, 7.6, 0.2003, -0.0313 + 30000.0, 0.33, 7.65, 0.2083, -0.03294 + 30000.0, 0.33, 7.7, 0.2162, -0.0346 + 30000.0, 0.33, 7.75, 0.2243, -0.03627 + 30000.0, 0.33, 7.8, 0.2324, -0.03796 + 30000.0, 0.33, 7.85, 0.2405, -0.03965 + 30000.0, 0.33, 7.9, 0.2487, -0.04136 + 30000.0, 0.33, 7.95, 0.2569, -0.04308 + 30000.0, 0.33, 8.0, 0.2651, -0.04481 + 30000.0, 0.33, 8.05, 0.2713, -0.04642 + 30000.0, 0.33, 8.1, 0.2774, -0.04803 + 30000.0, 0.33, 8.15, 0.2837, -0.04965 + 30000.0, 0.33, 8.2, 0.2899, -0.05128 + 30000.0, 0.33, 8.25, 0.2961, -0.05293 + 30000.0, 0.33, 8.3, 0.3023, -0.05458 + 30000.0, 0.33, 8.35, 0.3085, -0.05624 + 30000.0, 0.33, 8.4, 0.3148, -0.0579 + 30000.0, 0.33, 8.45, 0.321, -0.05958 + 30000.0, 0.33, 8.5, 0.3273, -0.06127 + 30000.0, 0.33, 8.55, 0.3335, -0.06296 + 30000.0, 0.33, 8.6, 0.3398, -0.06466 + 30000.0, 0.33, 8.65, 0.346, -0.06638 + 30000.0, 0.33, 8.7, 0.3523, -0.0681 + 30000.0, 0.33, 8.75, 0.3586, -0.06982 + 30000.0, 0.33, 8.8, 0.3648, -0.07156 + 30000.0, 0.33, 8.85, 0.3711, -0.0733 + 30000.0, 0.33, 8.9, 0.3774, -0.07506 + 30000.0, 0.33, 8.95, 0.3837, -0.07682 + 30000.0, 0.33, 9.0, 0.39, -0.07858 + 30000.0, 0.33, 9.05, 0.3962, -0.08036 + 30000.0, 0.33, 9.1, 0.4025, -0.08214 + 30000.0, 0.33, 9.15, 0.4088, -0.08393 + 30000.0, 0.33, 9.2, 0.4151, -0.08572 + 30000.0, 0.33, 9.25, 0.4214, -0.08753 + 30000.0, 0.33, 9.3, 0.4277, -0.08934 + 30000.0, 0.33, 9.35, 0.434, -0.09116 + 30000.0, 0.33, 9.4, 0.4403, -0.09298 + 30000.0, 0.33, 9.45, 0.4466, -0.09481 + 30000.0, 0.33, 9.5, 0.4529, -0.09665 + 30000.0, 0.33, 9.55, 0.4591, -0.09849 + 30000.0, 0.33, 9.6, 0.4654, -0.1003 + 30000.0, 0.33, 9.65, 0.4717, -0.1022 + 30000.0, 0.33, 9.7, 0.478, -0.1041 + 30000.0, 0.33, 9.75, 0.4843, -0.1059 + 30000.0, 0.33, 9.8, 0.4906, -0.1078 + 30000.0, 0.33, 9.85, 0.4969, -0.1097 + 30000.0, 0.33, 9.9, 0.5031, -0.1116 + 30000.0, 0.33, 9.95, 0.5094, -0.1134 + 30000.0, 0.33, 10.0, 0.5157, -0.1153 + 30000.0, 0.33, 10.05, 0.5219, -0.1173 + 30000.0, 0.33, 10.1, 0.5282, -0.1193 + 30000.0, 0.33, 10.15, 0.5344, -0.1213 + 30000.0, 0.33, 10.2, 0.5406, -0.1233 + 30000.0, 0.33, 10.25, 0.5469, -0.1253 + 30000.0, 0.33, 10.3, 0.5531, -0.1273 + 30000.0, 0.33, 10.35, 0.5593, -0.1294 + 30000.0, 0.33, 10.4, 0.5655, -0.1314 + 30000.0, 0.33, 10.45, 0.5717, -0.1334 + 30000.0, 0.33, 10.5, 0.5779, -0.1354 + 30000.0, 0.33, 10.55, 0.5841, -0.1374 + 30000.0, 0.33, 10.6, 0.5903, -0.1394 + 30000.0, 0.33, 10.65, 0.5965, -0.1415 + 30000.0, 0.33, 10.7, 0.6027, -0.1435 + 30000.0, 0.33, 10.75, 0.6089, -0.1455 + 30000.0, 0.33, 10.8, 0.615, -0.1475 + 30000.0, 0.33, 10.85, 0.6212, -0.1495 + 30000.0, 0.33, 10.9, 0.6273, -0.1515 + 30000.0, 0.33, 10.95, 0.6335, -0.1535 + 30000.0, 0.33, 11.0, 0.6396, -0.1555 + 30000.0, 0.33, 11.05, 0.6457, -0.1575 + 30000.0, 0.33, 11.1, 0.6519, -0.1595 + 30000.0, 0.33, 11.15, 0.658, -0.1615 + 30000.0, 0.33, 11.2, 0.6641, -0.1635 + 30000.0, 0.33, 11.25, 0.6702, -0.1655 + 30000.0, 0.33, 11.3, 0.6763, -0.1674 + 30000.0, 0.33, 11.35, 0.6823, -0.1694 + 30000.0, 0.33, 11.4, 0.6884, -0.1713 + 30000.0, 0.33, 11.45, 0.6945, -0.1733 + 30000.0, 0.33, 11.5, 0.7005, -0.1752 + 30000.0, 0.33, 11.55, 0.7066, -0.1771 + 30000.0, 0.33, 11.6, 0.7126, -0.1791 + 30000.0, 0.33, 11.65, 0.7186, -0.181 + 30000.0, 0.33, 11.7, 0.7246, -0.1829 + 30000.0, 0.33, 11.75, 0.7306, -0.1848 + 30000.0, 0.33, 11.8, 0.7366, -0.1866 + 30000.0, 0.33, 11.85, 0.7426, -0.1885 + 30000.0, 0.33, 11.9, 0.7486, -0.1904 + 30000.0, 0.33, 11.95, 0.7545, -0.1922 + 30000.0, 0.33, 12.0, 0.7605, -0.194 + 30000.0, 0.33, 12.05, 0.7664, -0.1959 + 30000.0, 0.33, 12.1, 0.7723, -0.1977 + 30000.0, 0.33, 12.15, 0.7782, -0.1994 + 30000.0, 0.33, 12.2, 0.7841, -0.2012 + 30000.0, 0.33, 12.25, 0.79, -0.203 + 30000.0, 0.33, 12.3, 0.7959, -0.2047 + 30000.0, 0.33, 12.35, 0.8017, -0.2064 + 30000.0, 0.33, 12.4, 0.8076, -0.2082 + 30000.0, 0.33, 12.45, 0.8134, -0.2099 + 30000.0, 0.33, 12.5, 0.8192, -0.2115 + 30000.0, 0.33, 12.55, 0.825, -0.2132 + 30000.0, 0.33, 12.6, 0.8308, -0.2148 + 30000.0, 0.33, 12.65, 0.8366, -0.2164 + 30000.0, 0.33, 12.7, 0.8423, -0.218 + 30000.0, 0.33, 12.75, 0.8481, -0.2196 + 30000.0, 0.33, 12.8, 0.8538, -0.2212 + 30000.0, 0.33, 12.85, 0.8595, -0.2227 + 30000.0, 0.33, 12.9, 0.8652, -0.2242 + 30000.0, 0.33, 12.95, 0.8709, -0.2257 + 30000.0, 0.33, 13.0, 0.8766, -0.2272 + 30000.0, 0.33, 13.05, 0.8822, -0.2287 + 30000.0, 0.33, 13.1, 0.8879, -0.2301 + 30000.0, 0.33, 13.15, 0.8935, -0.2315 + 30000.0, 0.33, 13.2, 0.8991, -0.2329 + 30000.0, 0.33, 13.25, 0.9047, -0.2342 + 30000.0, 0.33, 13.3, 0.9103, -0.2355 + 30000.0, 0.33, 13.35, 0.9158, -0.2369 + 30000.0, 0.33, 13.4, 0.9214, -0.2381 + 30000.0, 0.33, 13.45, 0.9269, -0.2394 + 30000.0, 0.33, 13.5, 0.9324, -0.2406 + 30000.0, 0.33, 13.55, 0.9379, -0.2418 + 30000.0, 0.33, 13.6, 0.9433, -0.243 + 30000.0, 0.33, 13.65, 0.9488, -0.2441 + 30000.0, 0.33, 13.7, 0.9542, -0.2452 + 30000.0, 0.33, 13.75, 0.9596, -0.2463 + 30000.0, 0.33, 13.8, 0.965, -0.2474 + 30000.0, 0.33, 13.85, 0.9704, -0.2484 + 30000.0, 0.33, 13.9, 0.9757, -0.2494 + 30000.0, 0.33, 13.95, 0.9811, -0.2504 + 30000.0, 0.33, 14.0, 0.9864, -0.2513 + 30000.0, 0.33, 14.05, 0.9917, -0.2522 + 30000.0, 0.33, 14.1, 0.9969, -0.2531 + 30000.0, 0.33, 14.15, 1.002, -0.2539 + 30000.0, 0.33, 14.2, 1.007, -0.2547 + 30000.0, 0.33, 14.25, 1.013, -0.2555 + 30000.0, 0.33, 14.3, 1.018, -0.2562 + 30000.0, 0.33, 14.35, 1.023, -0.2569 + 30000.0, 0.33, 14.4, 1.028, -0.2576 + 30000.0, 0.33, 14.45, 1.033, -0.2582 + 30000.0, 0.33, 14.5, 1.038, -0.2588 + 30000.0, 0.33, 14.55, 1.043, -0.2593 + 30000.0, 0.33, 14.6, 1.049, -0.2598 + 30000.0, 0.33, 14.65, 1.054, -0.2603 + 30000.0, 0.33, 14.7, 1.059, -0.2608 + 30000.0, 0.33, 14.75, 1.064, -0.2612 + 30000.0, 0.33, 14.8, 1.069, -0.2615 + 30000.0, 0.33, 14.85, 1.073, -0.2619 + 30000.0, 0.33, 14.9, 1.078, -0.2622 + 30000.0, 0.33, 14.95, 1.083, -0.2624 + 30000.0, 0.33, 15.0, 1.088, -0.2626 + 30000.0, 0.33, 15.05, 1.093, -0.2628 + 30000.0, 0.38, 0.0, -0.09774, -0.05662 + 30000.0, 0.38, 0.05, -0.09886, -0.05589 + 30000.0, 0.38, 0.1, -0.09971, -0.05513 + 30000.0, 0.38, 0.15, -0.1003, -0.05436 + 30000.0, 0.38, 0.2, -0.1007, -0.05355 + 30000.0, 0.38, 0.25, -0.1008, -0.05273 + 30000.0, 0.38, 0.3, -0.1006, -0.05188 + 30000.0, 0.38, 0.35, -0.1003, -0.05102 + 30000.0, 0.38, 0.4, -0.09969, -0.05013 + 30000.0, 0.38, 0.45, -0.09889, -0.04923 + 30000.0, 0.38, 0.5, -0.09787, -0.0483 + 30000.0, 0.38, 0.55, -0.09665, -0.04736 + 30000.0, 0.38, 0.6, -0.09523, -0.0464 + 30000.0, 0.38, 0.65, -0.09362, -0.04542 + 30000.0, 0.38, 0.7, -0.09182, -0.04443 + 30000.0, 0.38, 0.75, -0.08984, -0.04342 + 30000.0, 0.38, 0.8, -0.08769, -0.0424 + 30000.0, 0.38, 0.85, -0.08537, -0.04136 + 30000.0, 0.38, 0.9, -0.08289, -0.04032 + 30000.0, 0.38, 0.95, -0.08026, -0.03926 + 30000.0, 0.38, 1.0, -0.07748, -0.03818 + 30000.0, 0.38, 1.05, -0.07456, -0.0371 + 30000.0, 0.38, 1.1, -0.0715, -0.03601 + 30000.0, 0.38, 1.15, -0.06831, -0.03491 + 30000.0, 0.38, 1.2, -0.065, -0.0338 + 30000.0, 0.38, 1.25, -0.06158, -0.03268 + 30000.0, 0.38, 1.3, -0.05804, -0.03155 + 30000.0, 0.38, 1.35, -0.0544, -0.03042 + 30000.0, 0.38, 1.4, -0.05067, -0.02928 + 30000.0, 0.38, 1.45, -0.04684, -0.02814 + 30000.0, 0.38, 1.5, -0.04293, -0.02699 + 30000.0, 0.38, 1.55, -0.03894, -0.02584 + 30000.0, 0.38, 1.6, -0.03488, -0.02469 + 30000.0, 0.38, 1.65, -0.03076, -0.02353 + 30000.0, 0.38, 1.7, -0.02658, -0.02237 + 30000.0, 0.38, 1.75, -0.02234, -0.02122 + 30000.0, 0.38, 1.8, -0.01806, -0.02006 + 30000.0, 0.38, 1.85, -0.01374, -0.0189 + 30000.0, 0.38, 1.9, -0.009383, -0.01775 + 30000.0, 0.38, 1.95, -0.005001, -0.01659 + 30000.0, 0.38, 2.0, -0.0005991, -0.01544 + 30000.0, 0.38, 2.05, 0.003817, -0.0143 + 30000.0, 0.38, 2.1, 0.008242, -0.01316 + 30000.0, 0.38, 2.15, 0.01267, -0.01202 + 30000.0, 0.38, 2.2, 0.01709, -0.01089 + 30000.0, 0.38, 2.25, 0.0215, -0.009763 + 30000.0, 0.38, 2.3, 0.02589, -0.008646 + 30000.0, 0.38, 2.35, 0.03026, -0.007537 + 30000.0, 0.38, 2.4, 0.0346, -0.006437 + 30000.0, 0.38, 2.45, 0.0389, -0.005346 + 30000.0, 0.38, 2.5, 0.04316, -0.004265 + 30000.0, 0.38, 2.55, 0.04736, -0.003195 + 30000.0, 0.38, 2.6, 0.05152, -0.002137 + 30000.0, 0.38, 2.65, 0.05561, -0.001091 + 30000.0, 0.38, 2.7, 0.05963, -5.874e-05 + 30000.0, 0.38, 2.75, 0.06358, 0.0009602 + 30000.0, 0.38, 2.8, 0.06744, 0.001965 + 30000.0, 0.38, 2.85, 0.07122, 0.002954 + 30000.0, 0.38, 2.9, 0.0749, 0.003927 + 30000.0, 0.38, 2.95, 0.07849, 0.004883 + 30000.0, 0.38, 3.0, 0.08196, 0.005822 + 30000.0, 0.38, 3.05, 0.08533, 0.006743 + 30000.0, 0.38, 3.1, 0.08857, 0.007645 + 30000.0, 0.38, 3.15, 0.09169, 0.008528 + 30000.0, 0.38, 3.2, 0.09468, 0.00939 + 30000.0, 0.38, 3.25, 0.09753, 0.01023 + 30000.0, 0.38, 3.3, 0.1002, 0.01105 + 30000.0, 0.38, 3.35, 0.1028, 0.01185 + 30000.0, 0.38, 3.4, 0.1052, 0.01262 + 30000.0, 0.38, 3.45, 0.1074, 0.01337 + 30000.0, 0.38, 3.5, 0.1095, 0.0141 + 30000.0, 0.38, 3.55, 0.1113, 0.0148 + 30000.0, 0.38, 3.6, 0.113, 0.01547 + 30000.0, 0.38, 3.65, 0.1146, 0.01612 + 30000.0, 0.38, 3.7, 0.1159, 0.01674 + 30000.0, 0.38, 3.75, 0.117, 0.01733 + 30000.0, 0.38, 3.8, 0.1179, 0.01789 + 30000.0, 0.38, 3.85, 0.1186, 0.01842 + 30000.0, 0.38, 3.9, 0.119, 0.01892 + 30000.0, 0.38, 3.95, 0.1193, 0.0194 + 30000.0, 0.38, 4.0, 0.1193, 0.01983 + 30000.0, 0.38, 4.05, 0.1173, 0.02015 + 30000.0, 0.38, 4.1, 0.1151, 0.02043 + 30000.0, 0.38, 4.15, 0.1128, 0.02069 + 30000.0, 0.38, 4.2, 0.1104, 0.02092 + 30000.0, 0.38, 4.25, 0.1078, 0.02113 + 30000.0, 0.38, 4.3, 0.1052, 0.0213 + 30000.0, 0.38, 4.35, 0.1024, 0.02145 + 30000.0, 0.38, 4.4, 0.09958, 0.02157 + 30000.0, 0.38, 4.45, 0.09663, 0.02166 + 30000.0, 0.38, 4.5, 0.0936, 0.02172 + 30000.0, 0.38, 4.55, 0.0905, 0.02176 + 30000.0, 0.38, 4.6, 0.08733, 0.02176 + 30000.0, 0.38, 4.65, 0.0841, 0.02174 + 30000.0, 0.38, 4.7, 0.08082, 0.02169 + 30000.0, 0.38, 4.75, 0.07749, 0.02162 + 30000.0, 0.38, 4.8, 0.07413, 0.02151 + 30000.0, 0.38, 4.85, 0.07073, 0.02138 + 30000.0, 0.38, 4.9, 0.06731, 0.02122 + 30000.0, 0.38, 4.95, 0.06387, 0.02103 + 30000.0, 0.38, 5.0, 0.06043, 0.02081 + 30000.0, 0.38, 5.05, 0.05669, 0.02059 + 30000.0, 0.38, 5.1, 0.05297, 0.02034 + 30000.0, 0.38, 5.15, 0.04927, 0.02006 + 30000.0, 0.38, 5.2, 0.0456, 0.01975 + 30000.0, 0.38, 5.25, 0.04198, 0.01941 + 30000.0, 0.38, 5.3, 0.03842, 0.01904 + 30000.0, 0.38, 5.35, 0.03493, 0.01864 + 30000.0, 0.38, 5.4, 0.03151, 0.01821 + 30000.0, 0.38, 5.45, 0.02819, 0.01775 + 30000.0, 0.38, 5.5, 0.02497, 0.01726 + 30000.0, 0.38, 5.55, 0.02187, 0.01674 + 30000.0, 0.38, 5.6, 0.0189, 0.01619 + 30000.0, 0.38, 5.65, 0.01606, 0.0156 + 30000.0, 0.38, 5.7, 0.01338, 0.01498 + 30000.0, 0.38, 5.75, 0.01085, 0.01434 + 30000.0, 0.38, 5.8, 0.008505, 0.01365 + 30000.0, 0.38, 5.85, 0.006343, 0.01294 + 30000.0, 0.38, 5.9, 0.004377, 0.01219 + 30000.0, 0.38, 5.95, 0.002621, 0.01141 + 30000.0, 0.38, 6.0, 0.001086, 0.01059 + 30000.0, 0.38, 6.05, 0.002599, 0.009598 + 30000.0, 0.38, 6.1, 0.004472, 0.008564 + 30000.0, 0.38, 6.15, 0.006698, 0.007491 + 30000.0, 0.38, 6.2, 0.009267, 0.006378 + 30000.0, 0.38, 6.25, 0.01217, 0.005227 + 30000.0, 0.38, 6.3, 0.0154, 0.004039 + 30000.0, 0.38, 6.35, 0.01894, 0.002813 + 30000.0, 0.38, 6.4, 0.0228, 0.001552 + 30000.0, 0.38, 6.45, 0.02695, 0.0002544 + 30000.0, 0.38, 6.5, 0.03139, -0.001077 + 30000.0, 0.38, 6.55, 0.03611, -0.002443 + 30000.0, 0.38, 6.6, 0.0411, -0.003842 + 30000.0, 0.38, 6.65, 0.04636, -0.005274 + 30000.0, 0.38, 6.7, 0.05187, -0.006737 + 30000.0, 0.38, 6.75, 0.05762, -0.008232 + 30000.0, 0.38, 6.8, 0.06361, -0.009756 + 30000.0, 0.38, 6.85, 0.06983, -0.01131 + 30000.0, 0.38, 6.9, 0.07626, -0.01289 + 30000.0, 0.38, 6.95, 0.08291, -0.01451 + 30000.0, 0.38, 7.0, 0.08975, -0.01614 + 30000.0, 0.38, 7.05, 0.09679, -0.01781 + 30000.0, 0.38, 7.1, 0.104, -0.0195 + 30000.0, 0.38, 7.15, 0.1114, -0.02122 + 30000.0, 0.38, 7.2, 0.119, -0.02296 + 30000.0, 0.38, 7.25, 0.1267, -0.02472 + 30000.0, 0.38, 7.3, 0.1345, -0.02651 + 30000.0, 0.38, 7.35, 0.1425, -0.02832 + 30000.0, 0.38, 7.4, 0.1506, -0.03015 + 30000.0, 0.38, 7.45, 0.1589, -0.03201 + 30000.0, 0.38, 7.5, 0.1672, -0.03388 + 30000.0, 0.38, 7.55, 0.1757, -0.03577 + 30000.0, 0.38, 7.6, 0.1843, -0.03768 + 30000.0, 0.38, 7.65, 0.1929, -0.03961 + 30000.0, 0.38, 7.7, 0.2016, -0.04156 + 30000.0, 0.38, 7.75, 0.2104, -0.04352 + 30000.0, 0.38, 7.8, 0.2192, -0.0455 + 30000.0, 0.38, 7.85, 0.2281, -0.04749 + 30000.0, 0.38, 7.9, 0.237, -0.0495 + 30000.0, 0.38, 7.95, 0.246, -0.05152 + 30000.0, 0.38, 8.0, 0.2549, -0.05355 + 30000.0, 0.38, 8.05, 0.2616, -0.05543 + 30000.0, 0.38, 8.1, 0.2683, -0.05733 + 30000.0, 0.38, 8.15, 0.2751, -0.05923 + 30000.0, 0.38, 8.2, 0.2818, -0.06115 + 30000.0, 0.38, 8.25, 0.2885, -0.06308 + 30000.0, 0.38, 8.3, 0.2953, -0.06502 + 30000.0, 0.38, 8.35, 0.3021, -0.06697 + 30000.0, 0.38, 8.4, 0.3088, -0.06894 + 30000.0, 0.38, 8.45, 0.3156, -0.07091 + 30000.0, 0.38, 8.5, 0.3224, -0.0729 + 30000.0, 0.38, 8.55, 0.3292, -0.07489 + 30000.0, 0.38, 8.6, 0.336, -0.0769 + 30000.0, 0.38, 8.65, 0.3429, -0.07892 + 30000.0, 0.38, 8.7, 0.3497, -0.08095 + 30000.0, 0.38, 8.75, 0.3565, -0.08299 + 30000.0, 0.38, 8.8, 0.3634, -0.08504 + 30000.0, 0.38, 8.85, 0.3702, -0.0871 + 30000.0, 0.38, 8.9, 0.3771, -0.08917 + 30000.0, 0.38, 8.95, 0.3839, -0.09124 + 30000.0, 0.38, 9.0, 0.3908, -0.09333 + 30000.0, 0.38, 9.05, 0.3977, -0.09543 + 30000.0, 0.38, 9.1, 0.4046, -0.09754 + 30000.0, 0.38, 9.15, 0.4114, -0.09966 + 30000.0, 0.38, 9.2, 0.4183, -0.1018 + 30000.0, 0.38, 9.25, 0.4252, -0.1039 + 30000.0, 0.38, 9.3, 0.4321, -0.1061 + 30000.0, 0.38, 9.35, 0.439, -0.1082 + 30000.0, 0.38, 9.4, 0.4459, -0.1104 + 30000.0, 0.38, 9.45, 0.4528, -0.1126 + 30000.0, 0.38, 9.5, 0.4597, -0.1147 + 30000.0, 0.38, 9.55, 0.4666, -0.1169 + 30000.0, 0.38, 9.6, 0.4735, -0.1191 + 30000.0, 0.38, 9.65, 0.4805, -0.1213 + 30000.0, 0.38, 9.7, 0.4874, -0.1236 + 30000.0, 0.38, 9.75, 0.4943, -0.1258 + 30000.0, 0.38, 9.8, 0.5012, -0.128 + 30000.0, 0.38, 9.85, 0.5081, -0.1302 + 30000.0, 0.38, 9.9, 0.515, -0.1325 + 30000.0, 0.38, 9.95, 0.5219, -0.1347 + 30000.0, 0.38, 10.0, 0.5288, -0.137 + 30000.0, 0.38, 10.05, 0.5357, -0.1394 + 30000.0, 0.38, 10.1, 0.5426, -0.1418 + 30000.0, 0.38, 10.15, 0.5494, -0.1442 + 30000.0, 0.38, 10.2, 0.5563, -0.1466 + 30000.0, 0.38, 10.25, 0.5631, -0.149 + 30000.0, 0.38, 10.3, 0.57, -0.1514 + 30000.0, 0.38, 10.35, 0.5768, -0.1539 + 30000.0, 0.38, 10.4, 0.5837, -0.1563 + 30000.0, 0.38, 10.45, 0.5905, -0.1587 + 30000.0, 0.38, 10.5, 0.5974, -0.1612 + 30000.0, 0.38, 10.55, 0.6042, -0.1636 + 30000.0, 0.38, 10.6, 0.611, -0.166 + 30000.0, 0.38, 10.65, 0.6179, -0.1685 + 30000.0, 0.38, 10.7, 0.6247, -0.1709 + 30000.0, 0.38, 10.75, 0.6315, -0.1733 + 30000.0, 0.38, 10.8, 0.6383, -0.1758 + 30000.0, 0.38, 10.85, 0.6451, -0.1782 + 30000.0, 0.38, 10.9, 0.6519, -0.1806 + 30000.0, 0.38, 10.95, 0.6587, -0.183 + 30000.0, 0.38, 11.0, 0.6655, -0.1855 + 30000.0, 0.38, 11.05, 0.6723, -0.1879 + 30000.0, 0.38, 11.1, 0.6791, -0.1903 + 30000.0, 0.38, 11.15, 0.6859, -0.1927 + 30000.0, 0.38, 11.2, 0.6927, -0.1951 + 30000.0, 0.38, 11.25, 0.6994, -0.1975 + 30000.0, 0.38, 11.3, 0.7062, -0.1999 + 30000.0, 0.38, 11.35, 0.7129, -0.2023 + 30000.0, 0.38, 11.4, 0.7197, -0.2046 + 30000.0, 0.38, 11.45, 0.7264, -0.207 + 30000.0, 0.38, 11.5, 0.7332, -0.2093 + 30000.0, 0.38, 11.55, 0.7399, -0.2117 + 30000.0, 0.38, 11.6, 0.7466, -0.214 + 30000.0, 0.38, 11.65, 0.7533, -0.2163 + 30000.0, 0.38, 11.7, 0.76, -0.2186 + 30000.0, 0.38, 11.75, 0.7667, -0.2209 + 30000.0, 0.38, 11.8, 0.7734, -0.2232 + 30000.0, 0.38, 11.85, 0.7801, -0.2255 + 30000.0, 0.38, 11.9, 0.7868, -0.2278 + 30000.0, 0.38, 11.95, 0.7934, -0.23 + 30000.0, 0.38, 12.0, 0.8001, -0.2322 + 30000.0, 0.38, 12.05, 0.8067, -0.2344 + 30000.0, 0.38, 12.1, 0.8134, -0.2366 + 30000.0, 0.38, 12.15, 0.82, -0.2388 + 30000.0, 0.38, 12.2, 0.8266, -0.241 + 30000.0, 0.38, 12.25, 0.8332, -0.2431 + 30000.0, 0.38, 12.3, 0.8398, -0.2452 + 30000.0, 0.38, 12.35, 0.8464, -0.2473 + 30000.0, 0.38, 12.4, 0.853, -0.2494 + 30000.0, 0.38, 12.45, 0.8596, -0.2515 + 30000.0, 0.38, 12.5, 0.8661, -0.2535 + 30000.0, 0.38, 12.55, 0.8727, -0.2555 + 30000.0, 0.38, 12.6, 0.8792, -0.2575 + 30000.0, 0.38, 12.65, 0.8857, -0.2595 + 30000.0, 0.38, 12.7, 0.8922, -0.2615 + 30000.0, 0.38, 12.75, 0.8987, -0.2634 + 30000.0, 0.38, 12.8, 0.9052, -0.2653 + 30000.0, 0.38, 12.85, 0.9117, -0.2672 + 30000.0, 0.38, 12.9, 0.9182, -0.269 + 30000.0, 0.38, 12.95, 0.9246, -0.2709 + 30000.0, 0.38, 13.0, 0.9311, -0.2727 + 30000.0, 0.38, 13.05, 0.9375, -0.2744 + 30000.0, 0.38, 13.1, 0.9439, -0.2762 + 30000.0, 0.38, 13.15, 0.9503, -0.2779 + 30000.0, 0.38, 13.2, 0.9567, -0.2796 + 30000.0, 0.38, 13.25, 0.9631, -0.2812 + 30000.0, 0.38, 13.3, 0.9694, -0.2829 + 30000.0, 0.38, 13.35, 0.9758, -0.2845 + 30000.0, 0.38, 13.4, 0.9821, -0.286 + 30000.0, 0.38, 13.45, 0.9884, -0.2876 + 30000.0, 0.38, 13.5, 0.9947, -0.2891 + 30000.0, 0.38, 13.55, 1.001, -0.2905 + 30000.0, 0.38, 13.6, 1.007, -0.2919 + 30000.0, 0.38, 13.65, 1.014, -0.2933 + 30000.0, 0.38, 13.7, 1.02, -0.2947 + 30000.0, 0.38, 13.75, 1.026, -0.296 + 30000.0, 0.38, 13.8, 1.032, -0.2973 + 30000.0, 0.38, 13.85, 1.038, -0.2986 + 30000.0, 0.38, 13.9, 1.045, -0.2998 + 30000.0, 0.38, 13.95, 1.051, -0.301 + 30000.0, 0.38, 14.0, 1.057, -0.3021 + 30000.0, 0.38, 14.05, 1.063, -0.3032 + 30000.0, 0.38, 14.1, 1.069, -0.3043 + 30000.0, 0.38, 14.15, 1.075, -0.3053 + 30000.0, 0.38, 14.2, 1.081, -0.3063 + 30000.0, 0.38, 14.25, 1.087, -0.3072 + 30000.0, 0.38, 14.3, 1.094, -0.3081 + 30000.0, 0.38, 14.35, 1.1, -0.309 + 30000.0, 0.38, 14.4, 1.106, -0.3098 + 30000.0, 0.38, 14.45, 1.112, -0.3106 + 30000.0, 0.38, 14.5, 1.118, -0.3113 + 30000.0, 0.38, 14.55, 1.124, -0.312 + 30000.0, 0.38, 14.6, 1.129, -0.3126 + 30000.0, 0.38, 14.65, 1.135, -0.3132 + 30000.0, 0.38, 14.7, 1.141, -0.3137 + 30000.0, 0.38, 14.75, 1.147, -0.3142 + 30000.0, 0.38, 14.8, 1.153, -0.3147 + 30000.0, 0.38, 14.85, 1.159, -0.3151 + 30000.0, 0.38, 14.9, 1.165, -0.3154 + 30000.0, 0.38, 14.95, 1.171, -0.3157 + 30000.0, 0.38, 15.0, 1.176, -0.316 + 30000.0, 0.38, 15.05, 1.182, -0.3162 + 30000.0, 0.43, 0.0, -0.09462, -0.05606 + 30000.0, 0.43, 0.05, -0.09574, -0.05534 + 30000.0, 0.43, 0.1, -0.0966, -0.0546 + 30000.0, 0.43, 0.15, -0.09721, -0.05384 + 30000.0, 0.43, 0.2, -0.09757, -0.05305 + 30000.0, 0.43, 0.25, -0.09769, -0.05225 + 30000.0, 0.43, 0.3, -0.09757, -0.05142 + 30000.0, 0.43, 0.35, -0.09722, -0.05057 + 30000.0, 0.43, 0.4, -0.09665, -0.0497 + 30000.0, 0.43, 0.45, -0.09587, -0.04881 + 30000.0, 0.43, 0.5, -0.09487, -0.0479 + 30000.0, 0.43, 0.55, -0.09367, -0.04697 + 30000.0, 0.43, 0.6, -0.09227, -0.04603 + 30000.0, 0.43, 0.65, -0.09068, -0.04507 + 30000.0, 0.43, 0.7, -0.08891, -0.04409 + 30000.0, 0.43, 0.75, -0.08696, -0.0431 + 30000.0, 0.43, 0.8, -0.08483, -0.0421 + 30000.0, 0.43, 0.85, -0.08254, -0.04108 + 30000.0, 0.43, 0.9, -0.08009, -0.04005 + 30000.0, 0.43, 0.95, -0.07749, -0.039 + 30000.0, 0.43, 1.0, -0.07474, -0.03795 + 30000.0, 0.43, 1.05, -0.07185, -0.03688 + 30000.0, 0.43, 1.1, -0.06883, -0.0358 + 30000.0, 0.43, 1.15, -0.06568, -0.03472 + 30000.0, 0.43, 1.2, -0.0624, -0.03362 + 30000.0, 0.43, 1.25, -0.05901, -0.03252 + 30000.0, 0.43, 1.3, -0.05552, -0.03141 + 30000.0, 0.43, 1.35, -0.05192, -0.0303 + 30000.0, 0.43, 1.4, -0.04822, -0.02917 + 30000.0, 0.43, 1.45, -0.04443, -0.02805 + 30000.0, 0.43, 1.5, -0.04056, -0.02692 + 30000.0, 0.43, 1.55, -0.03661, -0.02578 + 30000.0, 0.43, 1.6, -0.0326, -0.02464 + 30000.0, 0.43, 1.65, -0.02851, -0.0235 + 30000.0, 0.43, 1.7, -0.02437, -0.02236 + 30000.0, 0.43, 1.75, -0.02018, -0.02122 + 30000.0, 0.43, 1.8, -0.01594, -0.02008 + 30000.0, 0.43, 1.85, -0.01166, -0.01893 + 30000.0, 0.43, 1.9, -0.007352, -0.01779 + 30000.0, 0.43, 1.95, -0.003014, -0.01666 + 30000.0, 0.43, 2.0, 0.001344, -0.01552 + 30000.0, 0.43, 2.05, 0.005716, -0.01439 + 30000.0, 0.43, 2.1, 0.0101, -0.01326 + 30000.0, 0.43, 2.15, 0.01448, -0.01214 + 30000.0, 0.43, 2.2, 0.01885, -0.01102 + 30000.0, 0.43, 2.25, 0.02322, -0.009908 + 30000.0, 0.43, 2.3, 0.02756, -0.008804 + 30000.0, 0.43, 2.35, 0.03189, -0.007707 + 30000.0, 0.43, 2.4, 0.03618, -0.00662 + 30000.0, 0.43, 2.45, 0.04044, -0.005541 + 30000.0, 0.43, 2.5, 0.04465, -0.004473 + 30000.0, 0.43, 2.55, 0.04881, -0.003415 + 30000.0, 0.43, 2.6, 0.05292, -0.002368 + 30000.0, 0.43, 2.65, 0.05697, -0.001334 + 30000.0, 0.43, 2.7, 0.06095, -0.0003121 + 30000.0, 0.43, 2.75, 0.06485, 0.0006961 + 30000.0, 0.43, 2.8, 0.06867, 0.00169 + 30000.0, 0.43, 2.85, 0.07241, 0.002669 + 30000.0, 0.43, 2.9, 0.07605, 0.003632 + 30000.0, 0.43, 2.95, 0.07959, 0.004579 + 30000.0, 0.43, 3.0, 0.08303, 0.005509 + 30000.0, 0.43, 3.05, 0.08635, 0.006422 + 30000.0, 0.43, 3.1, 0.08956, 0.007315 + 30000.0, 0.43, 3.15, 0.09264, 0.00819 + 30000.0, 0.43, 3.2, 0.09558, 0.009044 + 30000.0, 0.43, 3.25, 0.09839, 0.009878 + 30000.0, 0.43, 3.3, 0.1011, 0.01069 + 30000.0, 0.43, 3.35, 0.1036, 0.01148 + 30000.0, 0.43, 3.4, 0.1059, 0.01225 + 30000.0, 0.43, 3.45, 0.1081, 0.01299 + 30000.0, 0.43, 3.5, 0.1102, 0.01371 + 30000.0, 0.43, 3.55, 0.112, 0.01441 + 30000.0, 0.43, 3.6, 0.1137, 0.01508 + 30000.0, 0.43, 3.65, 0.1152, 0.01572 + 30000.0, 0.43, 3.7, 0.1164, 0.01634 + 30000.0, 0.43, 3.75, 0.1175, 0.01692 + 30000.0, 0.43, 3.8, 0.1184, 0.01748 + 30000.0, 0.43, 3.85, 0.1191, 0.01801 + 30000.0, 0.43, 3.9, 0.1195, 0.01851 + 30000.0, 0.43, 3.95, 0.1197, 0.01898 + 30000.0, 0.43, 4.0, 0.1197, 0.01942 + 30000.0, 0.43, 4.05, 0.1177, 0.01973 + 30000.0, 0.43, 4.1, 0.1155, 0.02002 + 30000.0, 0.43, 4.15, 0.1132, 0.02028 + 30000.0, 0.43, 4.2, 0.1108, 0.02051 + 30000.0, 0.43, 4.25, 0.1082, 0.02071 + 30000.0, 0.43, 4.3, 0.1056, 0.02088 + 30000.0, 0.43, 4.35, 0.1028, 0.02103 + 30000.0, 0.43, 4.4, 0.09993, 0.02116 + 30000.0, 0.43, 4.45, 0.09698, 0.02125 + 30000.0, 0.43, 4.5, 0.09395, 0.02132 + 30000.0, 0.43, 4.55, 0.09084, 0.02136 + 30000.0, 0.43, 4.6, 0.08767, 0.02137 + 30000.0, 0.43, 4.65, 0.08444, 0.02136 + 30000.0, 0.43, 4.7, 0.08115, 0.02131 + 30000.0, 0.43, 4.75, 0.07782, 0.02125 + 30000.0, 0.43, 4.8, 0.07446, 0.02115 + 30000.0, 0.43, 4.85, 0.07106, 0.02103 + 30000.0, 0.43, 4.9, 0.06764, 0.02088 + 30000.0, 0.43, 4.95, 0.0642, 0.0207 + 30000.0, 0.43, 5.0, 0.06076, 0.0205 + 30000.0, 0.43, 5.05, 0.05704, 0.02029 + 30000.0, 0.43, 5.1, 0.05334, 0.02006 + 30000.0, 0.43, 5.15, 0.04966, 0.0198 + 30000.0, 0.43, 5.2, 0.04601, 0.01951 + 30000.0, 0.43, 5.25, 0.04241, 0.01919 + 30000.0, 0.43, 5.3, 0.03886, 0.01884 + 30000.0, 0.43, 5.35, 0.03538, 0.01847 + 30000.0, 0.43, 5.4, 0.03198, 0.01806 + 30000.0, 0.43, 5.45, 0.02867, 0.01762 + 30000.0, 0.43, 5.5, 0.02546, 0.01716 + 30000.0, 0.43, 5.55, 0.02236, 0.01666 + 30000.0, 0.43, 5.6, 0.01939, 0.01613 + 30000.0, 0.43, 5.65, 0.01656, 0.01557 + 30000.0, 0.43, 5.7, 0.01387, 0.01498 + 30000.0, 0.43, 5.75, 0.01134, 0.01436 + 30000.0, 0.43, 5.8, 0.008978, 0.01371 + 30000.0, 0.43, 5.85, 0.006799, 0.01302 + 30000.0, 0.43, 5.9, 0.004813, 0.0123 + 30000.0, 0.43, 5.95, 0.003031, 0.01154 + 30000.0, 0.43, 6.0, 0.001464, 0.01075 + 30000.0, 0.43, 6.05, 0.002861, 0.009779 + 30000.0, 0.43, 6.1, 0.00461, 0.008765 + 30000.0, 0.43, 6.15, 0.006702, 0.007711 + 30000.0, 0.43, 6.2, 0.009129, 0.006618 + 30000.0, 0.43, 6.25, 0.01188, 0.005486 + 30000.0, 0.43, 6.3, 0.01495, 0.004316 + 30000.0, 0.43, 6.35, 0.01833, 0.003108 + 30000.0, 0.43, 6.4, 0.02201, 0.001865 + 30000.0, 0.43, 6.45, 0.02598, 0.0005854 + 30000.0, 0.43, 6.5, 0.03023, -0.000729 + 30000.0, 0.43, 6.55, 0.03476, -0.002078 + 30000.0, 0.43, 6.6, 0.03955, -0.00346 + 30000.0, 0.43, 6.65, 0.0446, -0.004875 + 30000.0, 0.43, 6.7, 0.04989, -0.006322 + 30000.0, 0.43, 6.75, 0.05543, -0.0078 + 30000.0, 0.43, 6.8, 0.06119, -0.009309 + 30000.0, 0.43, 6.85, 0.06718, -0.01085 + 30000.0, 0.43, 6.9, 0.07338, -0.01242 + 30000.0, 0.43, 6.95, 0.07979, -0.01401 + 30000.0, 0.43, 7.0, 0.08639, -0.01564 + 30000.0, 0.43, 7.05, 0.09318, -0.01729 + 30000.0, 0.43, 7.1, 0.1001, -0.01896 + 30000.0, 0.43, 7.15, 0.1073, -0.02067 + 30000.0, 0.43, 7.2, 0.1146, -0.02239 + 30000.0, 0.43, 7.25, 0.122, -0.02414 + 30000.0, 0.43, 7.3, 0.1296, -0.02592 + 30000.0, 0.43, 7.35, 0.1374, -0.02772 + 30000.0, 0.43, 7.4, 0.1452, -0.02953 + 30000.0, 0.43, 7.45, 0.1532, -0.03137 + 30000.0, 0.43, 7.5, 0.1613, -0.03323 + 30000.0, 0.43, 7.55, 0.1695, -0.03511 + 30000.0, 0.43, 7.6, 0.1778, -0.03701 + 30000.0, 0.43, 7.65, 0.1861, -0.03893 + 30000.0, 0.43, 7.7, 0.1946, -0.04086 + 30000.0, 0.43, 7.75, 0.2031, -0.04281 + 30000.0, 0.43, 7.8, 0.2116, -0.04478 + 30000.0, 0.43, 7.85, 0.2202, -0.04676 + 30000.0, 0.43, 7.9, 0.2289, -0.04876 + 30000.0, 0.43, 7.95, 0.2376, -0.05077 + 30000.0, 0.43, 8.0, 0.2463, -0.05279 + 30000.0, 0.43, 8.05, 0.2528, -0.05466 + 30000.0, 0.43, 8.1, 0.2593, -0.05654 + 30000.0, 0.43, 8.15, 0.2658, -0.05843 + 30000.0, 0.43, 8.2, 0.2724, -0.06033 + 30000.0, 0.43, 8.25, 0.2789, -0.06225 + 30000.0, 0.43, 8.3, 0.2855, -0.06418 + 30000.0, 0.43, 8.35, 0.2921, -0.06612 + 30000.0, 0.43, 8.4, 0.2987, -0.06807 + 30000.0, 0.43, 8.45, 0.3053, -0.07003 + 30000.0, 0.43, 8.5, 0.3119, -0.072 + 30000.0, 0.43, 8.55, 0.3185, -0.07399 + 30000.0, 0.43, 8.6, 0.3252, -0.07598 + 30000.0, 0.43, 8.65, 0.3318, -0.07799 + 30000.0, 0.43, 8.7, 0.3385, -0.08 + 30000.0, 0.43, 8.75, 0.3452, -0.08203 + 30000.0, 0.43, 8.8, 0.3518, -0.08407 + 30000.0, 0.43, 8.85, 0.3585, -0.08612 + 30000.0, 0.43, 8.9, 0.3652, -0.08818 + 30000.0, 0.43, 8.95, 0.3719, -0.09025 + 30000.0, 0.43, 9.0, 0.3786, -0.09233 + 30000.0, 0.43, 9.05, 0.3853, -0.09442 + 30000.0, 0.43, 9.1, 0.3921, -0.09652 + 30000.0, 0.43, 9.15, 0.3988, -0.09863 + 30000.0, 0.43, 9.2, 0.4055, -0.1007 + 30000.0, 0.43, 9.25, 0.4123, -0.1029 + 30000.0, 0.43, 9.3, 0.419, -0.105 + 30000.0, 0.43, 9.35, 0.4257, -0.1072 + 30000.0, 0.43, 9.4, 0.4325, -0.1093 + 30000.0, 0.43, 9.45, 0.4393, -0.1115 + 30000.0, 0.43, 9.5, 0.446, -0.1137 + 30000.0, 0.43, 9.55, 0.4528, -0.1158 + 30000.0, 0.43, 9.6, 0.4595, -0.118 + 30000.0, 0.43, 9.65, 0.4663, -0.1202 + 30000.0, 0.43, 9.7, 0.4731, -0.1225 + 30000.0, 0.43, 9.75, 0.4799, -0.1247 + 30000.0, 0.43, 9.8, 0.4866, -0.1269 + 30000.0, 0.43, 9.85, 0.4934, -0.1291 + 30000.0, 0.43, 9.9, 0.5002, -0.1314 + 30000.0, 0.43, 9.95, 0.507, -0.1336 + 30000.0, 0.43, 10.0, 0.5137, -0.1359 + 30000.0, 0.43, 10.05, 0.5205, -0.1383 + 30000.0, 0.43, 10.1, 0.5272, -0.1407 + 30000.0, 0.43, 10.15, 0.5339, -0.1431 + 30000.0, 0.43, 10.2, 0.5406, -0.1455 + 30000.0, 0.43, 10.25, 0.5473, -0.148 + 30000.0, 0.43, 10.3, 0.5541, -0.1504 + 30000.0, 0.43, 10.35, 0.5608, -0.1528 + 30000.0, 0.43, 10.4, 0.5675, -0.1553 + 30000.0, 0.43, 10.45, 0.5742, -0.1577 + 30000.0, 0.43, 10.5, 0.5809, -0.1601 + 30000.0, 0.43, 10.55, 0.5876, -0.1626 + 30000.0, 0.43, 10.6, 0.5943, -0.165 + 30000.0, 0.43, 10.65, 0.601, -0.1675 + 30000.0, 0.43, 10.7, 0.6077, -0.1699 + 30000.0, 0.43, 10.75, 0.6144, -0.1724 + 30000.0, 0.43, 10.8, 0.6211, -0.1748 + 30000.0, 0.43, 10.85, 0.6278, -0.1773 + 30000.0, 0.43, 10.9, 0.6345, -0.1797 + 30000.0, 0.43, 10.95, 0.6412, -0.1822 + 30000.0, 0.43, 11.0, 0.6479, -0.1846 + 30000.0, 0.43, 11.05, 0.6546, -0.187 + 30000.0, 0.43, 11.1, 0.6612, -0.1895 + 30000.0, 0.43, 11.15, 0.6679, -0.1919 + 30000.0, 0.43, 11.2, 0.6746, -0.1943 + 30000.0, 0.43, 11.25, 0.6812, -0.1967 + 30000.0, 0.43, 11.3, 0.6879, -0.1991 + 30000.0, 0.43, 11.35, 0.6946, -0.2015 + 30000.0, 0.43, 11.4, 0.7012, -0.2039 + 30000.0, 0.43, 11.45, 0.7079, -0.2063 + 30000.0, 0.43, 11.5, 0.7145, -0.2087 + 30000.0, 0.43, 11.55, 0.7211, -0.211 + 30000.0, 0.43, 11.6, 0.7278, -0.2134 + 30000.0, 0.43, 11.65, 0.7344, -0.2157 + 30000.0, 0.43, 11.7, 0.741, -0.218 + 30000.0, 0.43, 11.75, 0.7476, -0.2203 + 30000.0, 0.43, 11.8, 0.7542, -0.2226 + 30000.0, 0.43, 11.85, 0.7608, -0.2249 + 30000.0, 0.43, 11.9, 0.7674, -0.2272 + 30000.0, 0.43, 11.95, 0.774, -0.2295 + 30000.0, 0.43, 12.0, 0.7806, -0.2317 + 30000.0, 0.43, 12.05, 0.7872, -0.2339 + 30000.0, 0.43, 12.1, 0.7938, -0.2362 + 30000.0, 0.43, 12.15, 0.8003, -0.2384 + 30000.0, 0.43, 12.2, 0.8069, -0.2405 + 30000.0, 0.43, 12.25, 0.8134, -0.2427 + 30000.0, 0.43, 12.3, 0.82, -0.2448 + 30000.0, 0.43, 12.35, 0.8265, -0.247 + 30000.0, 0.43, 12.4, 0.8331, -0.2491 + 30000.0, 0.43, 12.45, 0.8396, -0.2511 + 30000.0, 0.43, 12.5, 0.8461, -0.2532 + 30000.0, 0.43, 12.55, 0.8526, -0.2552 + 30000.0, 0.43, 12.6, 0.8591, -0.2573 + 30000.0, 0.43, 12.65, 0.8656, -0.2592 + 30000.0, 0.43, 12.7, 0.872, -0.2612 + 30000.0, 0.43, 12.75, 0.8785, -0.2632 + 30000.0, 0.43, 12.8, 0.885, -0.2651 + 30000.0, 0.43, 12.85, 0.8914, -0.267 + 30000.0, 0.43, 12.9, 0.8979, -0.2688 + 30000.0, 0.43, 12.95, 0.9043, -0.2707 + 30000.0, 0.43, 13.0, 0.9107, -0.2725 + 30000.0, 0.43, 13.05, 0.9171, -0.2743 + 30000.0, 0.43, 13.1, 0.9235, -0.276 + 30000.0, 0.43, 13.15, 0.9299, -0.2778 + 30000.0, 0.43, 13.2, 0.9363, -0.2795 + 30000.0, 0.43, 13.25, 0.9427, -0.2811 + 30000.0, 0.43, 13.3, 0.9491, -0.2828 + 30000.0, 0.43, 13.35, 0.9554, -0.2844 + 30000.0, 0.43, 13.4, 0.9618, -0.286 + 30000.0, 0.43, 13.45, 0.9681, -0.2875 + 30000.0, 0.43, 13.5, 0.9744, -0.289 + 30000.0, 0.43, 13.55, 0.9807, -0.2905 + 30000.0, 0.43, 13.6, 0.987, -0.2919 + 30000.0, 0.43, 13.65, 0.9933, -0.2934 + 30000.0, 0.43, 13.7, 0.9996, -0.2947 + 30000.0, 0.43, 13.75, 1.006, -0.2961 + 30000.0, 0.43, 13.8, 1.012, -0.2974 + 30000.0, 0.43, 13.85, 1.018, -0.2986 + 30000.0, 0.43, 13.9, 1.025, -0.2998 + 30000.0, 0.43, 13.95, 1.031, -0.301 + 30000.0, 0.43, 14.0, 1.037, -0.3022 + 30000.0, 0.43, 14.05, 1.043, -0.3033 + 30000.0, 0.43, 14.1, 1.049, -0.3044 + 30000.0, 0.43, 14.15, 1.055, -0.3054 + 30000.0, 0.43, 14.2, 1.062, -0.3064 + 30000.0, 0.43, 14.25, 1.068, -0.3073 + 30000.0, 0.43, 14.3, 1.074, -0.3082 + 30000.0, 0.43, 14.35, 1.08, -0.3091 + 30000.0, 0.43, 14.4, 1.086, -0.3099 + 30000.0, 0.43, 14.45, 1.092, -0.3107 + 30000.0, 0.43, 14.5, 1.098, -0.3114 + 30000.0, 0.43, 14.55, 1.104, -0.3121 + 30000.0, 0.43, 14.6, 1.11, -0.3127 + 30000.0, 0.43, 14.65, 1.116, -0.3133 + 30000.0, 0.43, 14.7, 1.122, -0.3138 + 30000.0, 0.43, 14.75, 1.128, -0.3143 + 30000.0, 0.43, 14.8, 1.134, -0.3147 + 30000.0, 0.43, 14.85, 1.14, -0.3151 + 30000.0, 0.43, 14.9, 1.146, -0.3155 + 30000.0, 0.43, 14.95, 1.152, -0.3158 + 30000.0, 0.43, 15.0, 1.158, -0.316 + 30000.0, 0.43, 15.05, 1.164, -0.3162 + 30000.0, 0.48, 0.0, -0.09756, -0.04885 + 30000.0, 0.48, 0.05, -0.09825, -0.04823 + 30000.0, 0.48, 0.1, -0.09871, -0.04759 + 30000.0, 0.48, 0.15, -0.09895, -0.04692 + 30000.0, 0.48, 0.2, -0.09897, -0.04624 + 30000.0, 0.48, 0.25, -0.09877, -0.04553 + 30000.0, 0.48, 0.3, -0.09837, -0.04481 + 30000.0, 0.48, 0.35, -0.09776, -0.04407 + 30000.0, 0.48, 0.4, -0.09696, -0.04331 + 30000.0, 0.48, 0.45, -0.09597, -0.04253 + 30000.0, 0.48, 0.5, -0.09479, -0.04174 + 30000.0, 0.48, 0.55, -0.09343, -0.04093 + 30000.0, 0.48, 0.6, -0.0919, -0.04011 + 30000.0, 0.48, 0.65, -0.0902, -0.03927 + 30000.0, 0.48, 0.7, -0.08833, -0.03842 + 30000.0, 0.48, 0.75, -0.08631, -0.03756 + 30000.0, 0.48, 0.8, -0.08414, -0.03668 + 30000.0, 0.48, 0.85, -0.08182, -0.03579 + 30000.0, 0.48, 0.9, -0.07936, -0.03489 + 30000.0, 0.48, 0.95, -0.07676, -0.03397 + 30000.0, 0.48, 1.0, -0.07403, -0.03305 + 30000.0, 0.48, 1.05, -0.07119, -0.03212 + 30000.0, 0.48, 1.1, -0.06822, -0.03118 + 30000.0, 0.48, 1.15, -0.06514, -0.03023 + 30000.0, 0.48, 1.2, -0.06195, -0.02927 + 30000.0, 0.48, 1.25, -0.05866, -0.02831 + 30000.0, 0.48, 1.3, -0.05527, -0.02734 + 30000.0, 0.48, 1.35, -0.0518, -0.02636 + 30000.0, 0.48, 1.4, -0.04824, -0.02538 + 30000.0, 0.48, 1.45, -0.0446, -0.02439 + 30000.0, 0.48, 1.5, -0.04088, -0.0234 + 30000.0, 0.48, 1.55, -0.0371, -0.02241 + 30000.0, 0.48, 1.6, -0.03326, -0.02141 + 30000.0, 0.48, 1.65, -0.02936, -0.02042 + 30000.0, 0.48, 1.7, -0.0254, -0.01942 + 30000.0, 0.48, 1.75, -0.0214, -0.01842 + 30000.0, 0.48, 1.8, -0.01737, -0.01742 + 30000.0, 0.48, 1.85, -0.01329, -0.01642 + 30000.0, 0.48, 1.9, -0.009192, -0.01542 + 30000.0, 0.48, 1.95, -0.005066, -0.01442 + 30000.0, 0.48, 2.0, -0.000923, -0.01342 + 30000.0, 0.48, 2.05, 0.003232, -0.01243 + 30000.0, 0.48, 2.1, 0.007394, -0.01144 + 30000.0, 0.48, 2.15, 0.01156, -0.01046 + 30000.0, 0.48, 2.2, 0.01572, -0.009477 + 30000.0, 0.48, 2.25, 0.01986, -0.008502 + 30000.0, 0.48, 2.3, 0.024, -0.007533 + 30000.0, 0.48, 2.35, 0.02811, -0.006571 + 30000.0, 0.48, 2.4, 0.03219, -0.005617 + 30000.0, 0.48, 2.45, 0.03624, -0.00467 + 30000.0, 0.48, 2.5, 0.04026, -0.003731 + 30000.0, 0.48, 2.55, 0.04423, -0.002802 + 30000.0, 0.48, 2.6, 0.04815, -0.001883 + 30000.0, 0.48, 2.65, 0.05201, -0.0009735 + 30000.0, 0.48, 2.7, 0.05582, -7.542e-05 + 30000.0, 0.48, 2.75, 0.05956, 0.0008111 + 30000.0, 0.48, 2.8, 0.06323, 0.001685 + 30000.0, 0.48, 2.85, 0.06682, 0.002547 + 30000.0, 0.48, 2.9, 0.07033, 0.003395 + 30000.0, 0.48, 2.95, 0.07374, 0.004228 + 30000.0, 0.48, 3.0, 0.07707, 0.005047 + 30000.0, 0.48, 3.05, 0.0803, 0.005851 + 30000.0, 0.48, 3.1, 0.08342, 0.006639 + 30000.0, 0.48, 3.15, 0.08643, 0.00741 + 30000.0, 0.48, 3.2, 0.08932, 0.008163 + 30000.0, 0.48, 3.25, 0.09209, 0.008899 + 30000.0, 0.48, 3.3, 0.09474, 0.009617 + 30000.0, 0.48, 3.35, 0.09725, 0.01032 + 30000.0, 0.48, 3.4, 0.09962, 0.01099 + 30000.0, 0.48, 3.45, 0.1018, 0.01165 + 30000.0, 0.48, 3.5, 0.1039, 0.01229 + 30000.0, 0.48, 3.55, 0.1058, 0.01291 + 30000.0, 0.48, 3.6, 0.1076, 0.0135 + 30000.0, 0.48, 3.65, 0.1092, 0.01407 + 30000.0, 0.48, 3.7, 0.1106, 0.01462 + 30000.0, 0.48, 3.75, 0.1119, 0.01514 + 30000.0, 0.48, 3.8, 0.1129, 0.01564 + 30000.0, 0.48, 3.85, 0.1138, 0.01611 + 30000.0, 0.48, 3.9, 0.1145, 0.01656 + 30000.0, 0.48, 3.95, 0.115, 0.01698 + 30000.0, 0.48, 4.0, 0.1152, 0.01737 + 30000.0, 0.48, 4.05, 0.1137, 0.01765 + 30000.0, 0.48, 4.1, 0.1121, 0.01791 + 30000.0, 0.48, 4.15, 0.1103, 0.01814 + 30000.0, 0.48, 4.2, 0.1085, 0.01835 + 30000.0, 0.48, 4.25, 0.1065, 0.01854 + 30000.0, 0.48, 4.3, 0.1044, 0.0187 + 30000.0, 0.48, 4.35, 0.1023, 0.01884 + 30000.0, 0.48, 4.4, 0.1, 0.01896 + 30000.0, 0.48, 4.45, 0.09773, 0.01905 + 30000.0, 0.48, 4.5, 0.09533, 0.01912 + 30000.0, 0.48, 4.55, 0.09288, 0.01917 + 30000.0, 0.48, 4.6, 0.09036, 0.0192 + 30000.0, 0.48, 4.65, 0.08779, 0.0192 + 30000.0, 0.48, 4.7, 0.08517, 0.01918 + 30000.0, 0.48, 4.75, 0.08251, 0.01913 + 30000.0, 0.48, 4.8, 0.07983, 0.01906 + 30000.0, 0.48, 4.85, 0.07711, 0.01897 + 30000.0, 0.48, 4.9, 0.07437, 0.01886 + 30000.0, 0.48, 4.95, 0.07162, 0.01872 + 30000.0, 0.48, 5.0, 0.06887, 0.01856 + 30000.0, 0.48, 5.05, 0.0659, 0.01841 + 30000.0, 0.48, 5.1, 0.06293, 0.01823 + 30000.0, 0.48, 5.15, 0.05999, 0.01803 + 30000.0, 0.48, 5.2, 0.05707, 0.01781 + 30000.0, 0.48, 5.25, 0.05419, 0.01756 + 30000.0, 0.48, 5.3, 0.05137, 0.01728 + 30000.0, 0.48, 5.35, 0.04859, 0.01699 + 30000.0, 0.48, 5.4, 0.04589, 0.01666 + 30000.0, 0.48, 5.45, 0.04326, 0.01631 + 30000.0, 0.48, 5.5, 0.04073, 0.01593 + 30000.0, 0.48, 5.55, 0.03828, 0.01553 + 30000.0, 0.48, 5.6, 0.03595, 0.0151 + 30000.0, 0.48, 5.65, 0.03373, 0.01464 + 30000.0, 0.48, 5.7, 0.03163, 0.01416 + 30000.0, 0.48, 5.75, 0.02968, 0.01364 + 30000.0, 0.48, 5.8, 0.02786, 0.0131 + 30000.0, 0.48, 5.85, 0.02621, 0.01253 + 30000.0, 0.48, 5.9, 0.02472, 0.01193 + 30000.0, 0.48, 5.95, 0.0234, 0.0113 + 30000.0, 0.48, 6.0, 0.02227, 0.01064 + 30000.0, 0.48, 6.05, 0.02366, 0.009807 + 30000.0, 0.48, 6.1, 0.02536, 0.008936 + 30000.0, 0.48, 6.15, 0.02735, 0.008029 + 30000.0, 0.48, 6.2, 0.02963, 0.007086 + 30000.0, 0.48, 6.25, 0.03219, 0.006109 + 30000.0, 0.48, 6.3, 0.03502, 0.005097 + 30000.0, 0.48, 6.35, 0.03811, 0.004052 + 30000.0, 0.48, 6.4, 0.04146, 0.002974 + 30000.0, 0.48, 6.45, 0.04506, 0.001864 + 30000.0, 0.48, 6.5, 0.0489, 0.0007226 + 30000.0, 0.48, 6.55, 0.05298, -0.0004497 + 30000.0, 0.48, 6.6, 0.05728, -0.001652 + 30000.0, 0.48, 6.65, 0.0618, -0.002884 + 30000.0, 0.48, 6.7, 0.06654, -0.004145 + 30000.0, 0.48, 6.75, 0.07148, -0.005434 + 30000.0, 0.48, 6.8, 0.07662, -0.00675 + 30000.0, 0.48, 6.85, 0.08195, -0.008093 + 30000.0, 0.48, 6.9, 0.08746, -0.009463 + 30000.0, 0.48, 6.95, 0.09315, -0.01086 + 30000.0, 0.48, 7.0, 0.099, -0.01228 + 30000.0, 0.48, 7.05, 0.105, -0.01372 + 30000.0, 0.48, 7.1, 0.1112, -0.01519 + 30000.0, 0.48, 7.15, 0.1175, -0.01668 + 30000.0, 0.48, 7.2, 0.124, -0.01819 + 30000.0, 0.48, 7.25, 0.1305, -0.01972 + 30000.0, 0.48, 7.3, 0.1373, -0.02128 + 30000.0, 0.48, 7.35, 0.1441, -0.02285 + 30000.0, 0.48, 7.4, 0.151, -0.02445 + 30000.0, 0.48, 7.45, 0.1581, -0.02606 + 30000.0, 0.48, 7.5, 0.1652, -0.02769 + 30000.0, 0.48, 7.55, 0.1724, -0.02934 + 30000.0, 0.48, 7.6, 0.1797, -0.031 + 30000.0, 0.48, 7.65, 0.1871, -0.03269 + 30000.0, 0.48, 7.7, 0.1945, -0.03438 + 30000.0, 0.48, 7.75, 0.202, -0.0361 + 30000.0, 0.48, 7.8, 0.2096, -0.03782 + 30000.0, 0.48, 7.85, 0.2171, -0.03956 + 30000.0, 0.48, 7.9, 0.2248, -0.04131 + 30000.0, 0.48, 7.95, 0.2324, -0.04308 + 30000.0, 0.48, 8.0, 0.2401, -0.04485 + 30000.0, 0.48, 8.05, 0.2459, -0.04648 + 30000.0, 0.48, 8.1, 0.2517, -0.04813 + 30000.0, 0.48, 8.15, 0.2575, -0.04978 + 30000.0, 0.48, 8.2, 0.2634, -0.05145 + 30000.0, 0.48, 8.25, 0.2693, -0.05312 + 30000.0, 0.48, 8.3, 0.2751, -0.0548 + 30000.0, 0.48, 8.35, 0.281, -0.0565 + 30000.0, 0.48, 8.4, 0.2869, -0.05821 + 30000.0, 0.48, 8.45, 0.2928, -0.05992 + 30000.0, 0.48, 8.5, 0.2987, -0.06165 + 30000.0, 0.48, 8.55, 0.3046, -0.06338 + 30000.0, 0.48, 8.6, 0.3106, -0.06513 + 30000.0, 0.48, 8.65, 0.3165, -0.06688 + 30000.0, 0.48, 8.7, 0.3225, -0.06865 + 30000.0, 0.48, 8.75, 0.3284, -0.07042 + 30000.0, 0.48, 8.8, 0.3344, -0.0722 + 30000.0, 0.48, 8.85, 0.3404, -0.074 + 30000.0, 0.48, 8.9, 0.3464, -0.0758 + 30000.0, 0.48, 8.95, 0.3524, -0.07761 + 30000.0, 0.48, 9.0, 0.3584, -0.07943 + 30000.0, 0.48, 9.05, 0.3644, -0.08126 + 30000.0, 0.48, 9.1, 0.3704, -0.0831 + 30000.0, 0.48, 9.15, 0.3764, -0.08495 + 30000.0, 0.48, 9.2, 0.3824, -0.0868 + 30000.0, 0.48, 9.25, 0.3885, -0.08867 + 30000.0, 0.48, 9.3, 0.3945, -0.09054 + 30000.0, 0.48, 9.35, 0.4005, -0.09243 + 30000.0, 0.48, 9.4, 0.4066, -0.09432 + 30000.0, 0.48, 9.45, 0.4126, -0.09621 + 30000.0, 0.48, 9.5, 0.4187, -0.09812 + 30000.0, 0.48, 9.55, 0.4247, -0.1 + 30000.0, 0.48, 9.6, 0.4308, -0.102 + 30000.0, 0.48, 9.65, 0.4369, -0.1039 + 30000.0, 0.48, 9.7, 0.4429, -0.1058 + 30000.0, 0.48, 9.75, 0.449, -0.1078 + 30000.0, 0.48, 9.8, 0.4551, -0.1097 + 30000.0, 0.48, 9.85, 0.4611, -0.1117 + 30000.0, 0.48, 9.9, 0.4672, -0.1137 + 30000.0, 0.48, 9.95, 0.4733, -0.1156 + 30000.0, 0.48, 10.0, 0.4794, -0.1176 + 30000.0, 0.48, 10.05, 0.4854, -0.1197 + 30000.0, 0.48, 10.1, 0.4914, -0.1219 + 30000.0, 0.48, 10.15, 0.4974, -0.124 + 30000.0, 0.48, 10.2, 0.5035, -0.1261 + 30000.0, 0.48, 10.25, 0.5095, -0.1282 + 30000.0, 0.48, 10.3, 0.5155, -0.1304 + 30000.0, 0.48, 10.35, 0.5215, -0.1325 + 30000.0, 0.48, 10.4, 0.5275, -0.1347 + 30000.0, 0.48, 10.45, 0.5336, -0.1368 + 30000.0, 0.48, 10.5, 0.5396, -0.139 + 30000.0, 0.48, 10.55, 0.5456, -0.1411 + 30000.0, 0.48, 10.6, 0.5516, -0.1433 + 30000.0, 0.48, 10.65, 0.5576, -0.1454 + 30000.0, 0.48, 10.7, 0.5637, -0.1476 + 30000.0, 0.48, 10.75, 0.5697, -0.1498 + 30000.0, 0.48, 10.8, 0.5757, -0.1519 + 30000.0, 0.48, 10.85, 0.5817, -0.1541 + 30000.0, 0.48, 10.9, 0.5877, -0.1562 + 30000.0, 0.48, 10.95, 0.5937, -0.1584 + 30000.0, 0.48, 11.0, 0.5997, -0.1605 + 30000.0, 0.48, 11.05, 0.6057, -0.1627 + 30000.0, 0.48, 11.1, 0.6117, -0.1648 + 30000.0, 0.48, 11.15, 0.6177, -0.1669 + 30000.0, 0.48, 11.2, 0.6237, -0.1691 + 30000.0, 0.48, 11.25, 0.6297, -0.1712 + 30000.0, 0.48, 11.3, 0.6357, -0.1733 + 30000.0, 0.48, 11.35, 0.6417, -0.1754 + 30000.0, 0.48, 11.4, 0.6477, -0.1775 + 30000.0, 0.48, 11.45, 0.6536, -0.1796 + 30000.0, 0.48, 11.5, 0.6596, -0.1817 + 30000.0, 0.48, 11.55, 0.6656, -0.1838 + 30000.0, 0.48, 11.6, 0.6716, -0.1859 + 30000.0, 0.48, 11.65, 0.6775, -0.1879 + 30000.0, 0.48, 11.7, 0.6835, -0.19 + 30000.0, 0.48, 11.75, 0.6895, -0.192 + 30000.0, 0.48, 11.8, 0.6954, -0.194 + 30000.0, 0.48, 11.85, 0.7014, -0.1961 + 30000.0, 0.48, 11.9, 0.7073, -0.1981 + 30000.0, 0.48, 11.95, 0.7133, -0.2001 + 30000.0, 0.48, 12.0, 0.7192, -0.202 + 30000.0, 0.48, 12.05, 0.7251, -0.204 + 30000.0, 0.48, 12.1, 0.7311, -0.206 + 30000.0, 0.48, 12.15, 0.737, -0.2079 + 30000.0, 0.48, 12.2, 0.7429, -0.2098 + 30000.0, 0.48, 12.25, 0.7488, -0.2117 + 30000.0, 0.48, 12.3, 0.7547, -0.2136 + 30000.0, 0.48, 12.35, 0.7606, -0.2155 + 30000.0, 0.48, 12.4, 0.7665, -0.2173 + 30000.0, 0.48, 12.45, 0.7724, -0.2191 + 30000.0, 0.48, 12.5, 0.7783, -0.221 + 30000.0, 0.48, 12.55, 0.7842, -0.2228 + 30000.0, 0.48, 12.6, 0.7901, -0.2245 + 30000.0, 0.48, 12.65, 0.796, -0.2263 + 30000.0, 0.48, 12.7, 0.8018, -0.228 + 30000.0, 0.48, 12.75, 0.8077, -0.2297 + 30000.0, 0.48, 12.8, 0.8135, -0.2314 + 30000.0, 0.48, 12.85, 0.8194, -0.2331 + 30000.0, 0.48, 12.9, 0.8252, -0.2347 + 30000.0, 0.48, 12.95, 0.831, -0.2363 + 30000.0, 0.48, 13.0, 0.8369, -0.2379 + 30000.0, 0.48, 13.05, 0.8427, -0.2395 + 30000.0, 0.48, 13.1, 0.8485, -0.2411 + 30000.0, 0.48, 13.15, 0.8543, -0.2426 + 30000.0, 0.48, 13.2, 0.8601, -0.2441 + 30000.0, 0.48, 13.25, 0.8659, -0.2455 + 30000.0, 0.48, 13.3, 0.8717, -0.247 + 30000.0, 0.48, 13.35, 0.8774, -0.2484 + 30000.0, 0.48, 13.4, 0.8832, -0.2498 + 30000.0, 0.48, 13.45, 0.8889, -0.2511 + 30000.0, 0.48, 13.5, 0.8947, -0.2525 + 30000.0, 0.48, 13.55, 0.9004, -0.2537 + 30000.0, 0.48, 13.6, 0.9062, -0.255 + 30000.0, 0.48, 13.65, 0.9119, -0.2562 + 30000.0, 0.48, 13.7, 0.9176, -0.2574 + 30000.0, 0.48, 13.75, 0.9233, -0.2586 + 30000.0, 0.48, 13.8, 0.929, -0.2597 + 30000.0, 0.48, 13.85, 0.9347, -0.2609 + 30000.0, 0.48, 13.9, 0.9404, -0.2619 + 30000.0, 0.48, 13.95, 0.946, -0.263 + 30000.0, 0.48, 14.0, 0.9517, -0.264 + 30000.0, 0.48, 14.05, 0.9574, -0.2649 + 30000.0, 0.48, 14.1, 0.963, -0.2658 + 30000.0, 0.48, 14.15, 0.9686, -0.2667 + 30000.0, 0.48, 14.2, 0.9743, -0.2676 + 30000.0, 0.48, 14.25, 0.9799, -0.2684 + 30000.0, 0.48, 14.3, 0.9855, -0.2692 + 30000.0, 0.48, 14.35, 0.9911, -0.2699 + 30000.0, 0.48, 14.4, 0.9966, -0.2706 + 30000.0, 0.48, 14.45, 1.002, -0.2713 + 30000.0, 0.48, 14.5, 1.008, -0.2719 + 30000.0, 0.48, 14.55, 1.013, -0.2725 + 30000.0, 0.48, 14.6, 1.019, -0.273 + 30000.0, 0.48, 14.65, 1.024, -0.2735 + 30000.0, 0.48, 14.7, 1.03, -0.274 + 30000.0, 0.48, 14.75, 1.035, -0.2744 + 30000.0, 0.48, 14.8, 1.041, -0.2748 + 30000.0, 0.48, 14.85, 1.046, -0.2751 + 30000.0, 0.48, 14.9, 1.052, -0.2754 + 30000.0, 0.48, 14.95, 1.057, -0.2756 + 30000.0, 0.48, 15.0, 1.063, -0.2758 + 30000.0, 0.48, 15.05, 1.068, -0.2759 + 30000.0, 0.53, 0.0, -0.1055, -0.03722 + 30000.0, 0.53, 0.05, -0.1055, -0.03674 + 30000.0, 0.53, 0.1, -0.1052, -0.03625 + 30000.0, 0.53, 0.15, -0.1048, -0.03573 + 30000.0, 0.53, 0.2, -0.1043, -0.03521 + 30000.0, 0.53, 0.25, -0.1035, -0.03466 + 30000.0, 0.53, 0.3, -0.1026, -0.03411 + 30000.0, 0.53, 0.35, -0.1016, -0.03353 + 30000.0, 0.53, 0.4, -0.1003, -0.03295 + 30000.0, 0.53, 0.45, -0.09898, -0.03235 + 30000.0, 0.53, 0.5, -0.09746, -0.03174 + 30000.0, 0.53, 0.55, -0.09581, -0.03112 + 30000.0, 0.53, 0.6, -0.09402, -0.03048 + 30000.0, 0.53, 0.65, -0.0921, -0.02983 + 30000.0, 0.53, 0.7, -0.09005, -0.02918 + 30000.0, 0.53, 0.75, -0.08788, -0.02851 + 30000.0, 0.53, 0.8, -0.08559, -0.02783 + 30000.0, 0.53, 0.85, -0.08318, -0.02714 + 30000.0, 0.53, 0.9, -0.08066, -0.02645 + 30000.0, 0.53, 0.95, -0.07804, -0.02574 + 30000.0, 0.53, 1.0, -0.07531, -0.02503 + 30000.0, 0.53, 1.05, -0.07249, -0.02431 + 30000.0, 0.53, 1.1, -0.06958, -0.02358 + 30000.0, 0.53, 1.15, -0.06657, -0.02285 + 30000.0, 0.53, 1.2, -0.06349, -0.02211 + 30000.0, 0.53, 1.25, -0.06032, -0.02137 + 30000.0, 0.53, 1.3, -0.05708, -0.02062 + 30000.0, 0.53, 1.35, -0.05376, -0.01986 + 30000.0, 0.53, 1.4, -0.05038, -0.0191 + 30000.0, 0.53, 1.45, -0.04694, -0.01834 + 30000.0, 0.53, 1.5, -0.04344, -0.01757 + 30000.0, 0.53, 1.55, -0.03989, -0.0168 + 30000.0, 0.53, 1.6, -0.03629, -0.01603 + 30000.0, 0.53, 1.65, -0.03265, -0.01526 + 30000.0, 0.53, 1.7, -0.02896, -0.01449 + 30000.0, 0.53, 1.75, -0.02524, -0.01371 + 30000.0, 0.53, 1.8, -0.02148, -0.01294 + 30000.0, 0.53, 1.85, -0.01771, -0.01216 + 30000.0, 0.53, 1.9, -0.0139, -0.01139 + 30000.0, 0.53, 1.95, -0.01008, -0.01061 + 30000.0, 0.53, 2.0, -0.006248, -0.009842 + 30000.0, 0.53, 2.05, -0.002405, -0.009073 + 30000.0, 0.53, 2.1, 0.001444, -0.008305 + 30000.0, 0.53, 2.15, 0.005293, -0.007541 + 30000.0, 0.53, 2.2, 0.009138, -0.00678 + 30000.0, 0.53, 2.25, 0.01298, -0.006024 + 30000.0, 0.53, 2.3, 0.0168, -0.005271 + 30000.0, 0.53, 2.35, 0.02061, -0.004524 + 30000.0, 0.53, 2.4, 0.02439, -0.003781 + 30000.0, 0.53, 2.45, 0.02815, -0.003045 + 30000.0, 0.53, 2.5, 0.03188, -0.002315 + 30000.0, 0.53, 2.55, 0.03558, -0.001592 + 30000.0, 0.53, 2.6, 0.03924, -0.0008756 + 30000.0, 0.53, 2.65, 0.04285, -0.0001674 + 30000.0, 0.53, 2.7, 0.04642, 0.0005327 + 30000.0, 0.53, 2.75, 0.04993, 0.001224 + 30000.0, 0.53, 2.8, 0.05339, 0.001906 + 30000.0, 0.53, 2.85, 0.05678, 0.002579 + 30000.0, 0.53, 2.9, 0.06011, 0.003241 + 30000.0, 0.53, 2.95, 0.06338, 0.003893 + 30000.0, 0.53, 3.0, 0.06656, 0.004534 + 30000.0, 0.53, 3.05, 0.06967, 0.005163 + 30000.0, 0.53, 3.1, 0.0727, 0.00578 + 30000.0, 0.53, 3.15, 0.07564, 0.006385 + 30000.0, 0.53, 3.2, 0.07848, 0.006976 + 30000.0, 0.53, 3.25, 0.08124, 0.007555 + 30000.0, 0.53, 3.3, 0.08389, 0.008119 + 30000.0, 0.53, 3.35, 0.08643, 0.008669 + 30000.0, 0.53, 3.4, 0.08887, 0.009204 + 30000.0, 0.53, 3.45, 0.09119, 0.009723 + 30000.0, 0.53, 3.5, 0.0934, 0.01023 + 30000.0, 0.53, 3.55, 0.09548, 0.01071 + 30000.0, 0.53, 3.6, 0.09744, 0.01119 + 30000.0, 0.53, 3.65, 0.09926, 0.01164 + 30000.0, 0.53, 3.7, 0.101, 0.01207 + 30000.0, 0.53, 3.75, 0.1025, 0.01249 + 30000.0, 0.53, 3.8, 0.1039, 0.01289 + 30000.0, 0.53, 3.85, 0.1052, 0.01327 + 30000.0, 0.53, 3.9, 0.1063, 0.01363 + 30000.0, 0.53, 3.95, 0.1072, 0.01397 + 30000.0, 0.53, 4.0, 0.108, 0.01429 + 30000.0, 0.53, 4.05, 0.1074, 0.01452 + 30000.0, 0.53, 4.1, 0.1067, 0.01473 + 30000.0, 0.53, 4.15, 0.1059, 0.01492 + 30000.0, 0.53, 4.2, 0.105, 0.0151 + 30000.0, 0.53, 4.25, 0.104, 0.01526 + 30000.0, 0.53, 4.3, 0.1029, 0.0154 + 30000.0, 0.53, 4.35, 0.1018, 0.01553 + 30000.0, 0.53, 4.4, 0.1006, 0.01564 + 30000.0, 0.53, 4.45, 0.09936, 0.01573 + 30000.0, 0.53, 4.5, 0.09805, 0.0158 + 30000.0, 0.53, 4.55, 0.09668, 0.01586 + 30000.0, 0.53, 4.6, 0.09527, 0.0159 + 30000.0, 0.53, 4.65, 0.09382, 0.01592 + 30000.0, 0.53, 4.7, 0.09233, 0.01593 + 30000.0, 0.53, 4.75, 0.09082, 0.01592 + 30000.0, 0.53, 4.8, 0.08927, 0.01589 + 30000.0, 0.53, 4.85, 0.08771, 0.01585 + 30000.0, 0.53, 4.9, 0.08612, 0.01579 + 30000.0, 0.53, 4.95, 0.08453, 0.01571 + 30000.0, 0.53, 5.0, 0.08294, 0.01562 + 30000.0, 0.53, 5.05, 0.0812, 0.01554 + 30000.0, 0.53, 5.1, 0.07947, 0.01544 + 30000.0, 0.53, 5.15, 0.07775, 0.01533 + 30000.0, 0.53, 5.2, 0.07606, 0.0152 + 30000.0, 0.53, 5.25, 0.0744, 0.01505 + 30000.0, 0.53, 5.3, 0.07277, 0.01488 + 30000.0, 0.53, 5.35, 0.07118, 0.01469 + 30000.0, 0.53, 5.4, 0.06964, 0.01449 + 30000.0, 0.53, 5.45, 0.06816, 0.01426 + 30000.0, 0.53, 5.5, 0.06675, 0.01402 + 30000.0, 0.53, 5.55, 0.0654, 0.01375 + 30000.0, 0.53, 5.6, 0.06414, 0.01347 + 30000.0, 0.53, 5.65, 0.06296, 0.01316 + 30000.0, 0.53, 5.7, 0.06188, 0.01283 + 30000.0, 0.53, 5.75, 0.06089, 0.01248 + 30000.0, 0.53, 5.8, 0.06001, 0.01211 + 30000.0, 0.53, 5.85, 0.05925, 0.01172 + 30000.0, 0.53, 5.9, 0.05861, 0.0113 + 30000.0, 0.53, 5.95, 0.0581, 0.01086 + 30000.0, 0.53, 6.0, 0.05773, 0.01039 + 30000.0, 0.53, 6.05, 0.05922, 0.009777 + 30000.0, 0.53, 6.1, 0.06094, 0.009131 + 30000.0, 0.53, 6.15, 0.06287, 0.008455 + 30000.0, 0.53, 6.2, 0.06502, 0.007751 + 30000.0, 0.53, 6.25, 0.06737, 0.007019 + 30000.0, 0.53, 6.3, 0.06992, 0.006259 + 30000.0, 0.53, 6.35, 0.07267, 0.005472 + 30000.0, 0.53, 6.4, 0.0756, 0.004659 + 30000.0, 0.53, 6.45, 0.07873, 0.00382 + 30000.0, 0.53, 6.5, 0.08203, 0.002955 + 30000.0, 0.53, 6.55, 0.0855, 0.002066 + 30000.0, 0.53, 6.6, 0.08915, 0.001152 + 30000.0, 0.53, 6.65, 0.09295, 0.0002144 + 30000.0, 0.53, 6.7, 0.09691, -0.0007463 + 30000.0, 0.53, 6.75, 0.101, -0.00173 + 30000.0, 0.53, 6.8, 0.1053, -0.002735 + 30000.0, 0.53, 6.85, 0.1097, -0.003762 + 30000.0, 0.53, 6.9, 0.1142, -0.00481 + 30000.0, 0.53, 6.95, 0.1189, -0.005878 + 30000.0, 0.53, 7.0, 0.1237, -0.006966 + 30000.0, 0.53, 7.05, 0.1286, -0.008074 + 30000.0, 0.53, 7.1, 0.1336, -0.0092 + 30000.0, 0.53, 7.15, 0.1388, -0.01034 + 30000.0, 0.53, 7.2, 0.144, -0.01151 + 30000.0, 0.53, 7.25, 0.1493, -0.01269 + 30000.0, 0.53, 7.3, 0.1548, -0.01388 + 30000.0, 0.53, 7.35, 0.1603, -0.01509 + 30000.0, 0.53, 7.4, 0.1659, -0.01632 + 30000.0, 0.53, 7.45, 0.1716, -0.01756 + 30000.0, 0.53, 7.5, 0.1773, -0.01882 + 30000.0, 0.53, 7.55, 0.1831, -0.02009 + 30000.0, 0.53, 7.6, 0.189, -0.02137 + 30000.0, 0.53, 7.65, 0.1949, -0.02267 + 30000.0, 0.53, 7.7, 0.2009, -0.02398 + 30000.0, 0.53, 7.75, 0.2069, -0.0253 + 30000.0, 0.53, 7.8, 0.213, -0.02663 + 30000.0, 0.53, 7.85, 0.219, -0.02797 + 30000.0, 0.53, 7.9, 0.2252, -0.02932 + 30000.0, 0.53, 7.95, 0.2313, -0.03068 + 30000.0, 0.53, 8.0, 0.2374, -0.03205 + 30000.0, 0.53, 8.05, 0.2422, -0.0333 + 30000.0, 0.53, 8.1, 0.247, -0.03456 + 30000.0, 0.53, 8.15, 0.2518, -0.03582 + 30000.0, 0.53, 8.2, 0.2567, -0.0371 + 30000.0, 0.53, 8.25, 0.2615, -0.03838 + 30000.0, 0.53, 8.3, 0.2663, -0.03967 + 30000.0, 0.53, 8.35, 0.2712, -0.04096 + 30000.0, 0.53, 8.4, 0.276, -0.04227 + 30000.0, 0.53, 8.45, 0.2809, -0.04358 + 30000.0, 0.53, 8.5, 0.2858, -0.0449 + 30000.0, 0.53, 8.55, 0.2907, -0.04623 + 30000.0, 0.53, 8.6, 0.2955, -0.04757 + 30000.0, 0.53, 8.65, 0.3004, -0.04891 + 30000.0, 0.53, 8.7, 0.3053, -0.05026 + 30000.0, 0.53, 8.75, 0.3103, -0.05162 + 30000.0, 0.53, 8.8, 0.3152, -0.05298 + 30000.0, 0.53, 8.85, 0.3201, -0.05436 + 30000.0, 0.53, 8.9, 0.325, -0.05574 + 30000.0, 0.53, 8.95, 0.33, -0.05712 + 30000.0, 0.53, 9.0, 0.3349, -0.05852 + 30000.0, 0.53, 9.05, 0.3399, -0.05992 + 30000.0, 0.53, 9.1, 0.3448, -0.06133 + 30000.0, 0.53, 9.15, 0.3498, -0.06274 + 30000.0, 0.53, 9.2, 0.3548, -0.06416 + 30000.0, 0.53, 9.25, 0.3597, -0.06559 + 30000.0, 0.53, 9.3, 0.3647, -0.06703 + 30000.0, 0.53, 9.35, 0.3697, -0.06847 + 30000.0, 0.53, 9.4, 0.3747, -0.06992 + 30000.0, 0.53, 9.45, 0.3797, -0.07137 + 30000.0, 0.53, 9.5, 0.3847, -0.07283 + 30000.0, 0.53, 9.55, 0.3897, -0.0743 + 30000.0, 0.53, 9.6, 0.3947, -0.07577 + 30000.0, 0.53, 9.65, 0.3997, -0.07726 + 30000.0, 0.53, 9.7, 0.4047, -0.07874 + 30000.0, 0.53, 9.75, 0.4097, -0.08023 + 30000.0, 0.53, 9.8, 0.4147, -0.08173 + 30000.0, 0.53, 9.85, 0.4197, -0.08324 + 30000.0, 0.53, 9.9, 0.4247, -0.08475 + 30000.0, 0.53, 9.95, 0.4297, -0.08627 + 30000.0, 0.53, 10.0, 0.4347, -0.08779 + 30000.0, 0.53, 10.05, 0.4397, -0.08941 + 30000.0, 0.53, 10.1, 0.4447, -0.09104 + 30000.0, 0.53, 10.15, 0.4496, -0.09267 + 30000.0, 0.53, 10.2, 0.4546, -0.09431 + 30000.0, 0.53, 10.25, 0.4596, -0.09595 + 30000.0, 0.53, 10.3, 0.4645, -0.0976 + 30000.0, 0.53, 10.35, 0.4695, -0.09925 + 30000.0, 0.53, 10.4, 0.4745, -0.1009 + 30000.0, 0.53, 10.45, 0.4795, -0.1026 + 30000.0, 0.53, 10.5, 0.4844, -0.1042 + 30000.0, 0.53, 10.55, 0.4894, -0.1059 + 30000.0, 0.53, 10.6, 0.4944, -0.1075 + 30000.0, 0.53, 10.65, 0.4993, -0.1092 + 30000.0, 0.53, 10.7, 0.5043, -0.1108 + 30000.0, 0.53, 10.75, 0.5093, -0.1125 + 30000.0, 0.53, 10.8, 0.5142, -0.1142 + 30000.0, 0.53, 10.85, 0.5192, -0.1158 + 30000.0, 0.53, 10.9, 0.5242, -0.1175 + 30000.0, 0.53, 10.95, 0.5291, -0.1191 + 30000.0, 0.53, 11.0, 0.5341, -0.1208 + 30000.0, 0.53, 11.05, 0.5391, -0.1224 + 30000.0, 0.53, 11.1, 0.544, -0.1241 + 30000.0, 0.53, 11.15, 0.549, -0.1257 + 30000.0, 0.53, 11.2, 0.5539, -0.1274 + 30000.0, 0.53, 11.25, 0.5589, -0.129 + 30000.0, 0.53, 11.3, 0.5639, -0.1306 + 30000.0, 0.53, 11.35, 0.5688, -0.1322 + 30000.0, 0.53, 11.4, 0.5738, -0.1339 + 30000.0, 0.53, 11.45, 0.5787, -0.1355 + 30000.0, 0.53, 11.5, 0.5837, -0.1371 + 30000.0, 0.53, 11.55, 0.5886, -0.1387 + 30000.0, 0.53, 11.6, 0.5935, -0.1403 + 30000.0, 0.53, 11.65, 0.5985, -0.1419 + 30000.0, 0.53, 11.7, 0.6034, -0.1434 + 30000.0, 0.53, 11.75, 0.6084, -0.145 + 30000.0, 0.53, 11.8, 0.6133, -0.1466 + 30000.0, 0.53, 11.85, 0.6182, -0.1481 + 30000.0, 0.53, 11.9, 0.6232, -0.1497 + 30000.0, 0.53, 11.95, 0.6281, -0.1512 + 30000.0, 0.53, 12.0, 0.633, -0.1527 + 30000.0, 0.53, 12.05, 0.6379, -0.1542 + 30000.0, 0.53, 12.1, 0.6428, -0.1557 + 30000.0, 0.53, 12.15, 0.6478, -0.1572 + 30000.0, 0.53, 12.2, 0.6527, -0.1587 + 30000.0, 0.53, 12.25, 0.6576, -0.1601 + 30000.0, 0.53, 12.3, 0.6625, -0.1616 + 30000.0, 0.53, 12.35, 0.6674, -0.163 + 30000.0, 0.53, 12.4, 0.6723, -0.1644 + 30000.0, 0.53, 12.45, 0.6772, -0.1658 + 30000.0, 0.53, 12.5, 0.6821, -0.1672 + 30000.0, 0.53, 12.55, 0.6869, -0.1686 + 30000.0, 0.53, 12.6, 0.6918, -0.17 + 30000.0, 0.53, 12.65, 0.6967, -0.1713 + 30000.0, 0.53, 12.7, 0.7016, -0.1726 + 30000.0, 0.53, 12.75, 0.7064, -0.1739 + 30000.0, 0.53, 12.8, 0.7113, -0.1752 + 30000.0, 0.53, 12.85, 0.7162, -0.1765 + 30000.0, 0.53, 12.9, 0.721, -0.1778 + 30000.0, 0.53, 12.95, 0.7259, -0.179 + 30000.0, 0.53, 13.0, 0.7307, -0.1802 + 30000.0, 0.53, 13.05, 0.7356, -0.1814 + 30000.0, 0.53, 13.1, 0.7404, -0.1826 + 30000.0, 0.53, 13.15, 0.7452, -0.1837 + 30000.0, 0.53, 13.2, 0.7501, -0.1849 + 30000.0, 0.53, 13.25, 0.7549, -0.186 + 30000.0, 0.53, 13.3, 0.7597, -0.1871 + 30000.0, 0.53, 13.35, 0.7645, -0.1882 + 30000.0, 0.53, 13.4, 0.7693, -0.1892 + 30000.0, 0.53, 13.45, 0.7741, -0.1902 + 30000.0, 0.53, 13.5, 0.7789, -0.1912 + 30000.0, 0.53, 13.55, 0.7837, -0.1922 + 30000.0, 0.53, 13.6, 0.7885, -0.1932 + 30000.0, 0.53, 13.65, 0.7933, -0.1941 + 30000.0, 0.53, 13.7, 0.7981, -0.195 + 30000.0, 0.53, 13.75, 0.8028, -0.1959 + 30000.0, 0.53, 13.8, 0.8076, -0.1968 + 30000.0, 0.53, 13.85, 0.8123, -0.1976 + 30000.0, 0.53, 13.9, 0.8171, -0.1984 + 30000.0, 0.53, 13.95, 0.8218, -0.1992 + 30000.0, 0.53, 14.0, 0.8266, -0.1999 + 30000.0, 0.53, 14.05, 0.8313, -0.2006 + 30000.0, 0.53, 14.1, 0.836, -0.2013 + 30000.0, 0.53, 14.15, 0.8407, -0.202 + 30000.0, 0.53, 14.2, 0.8454, -0.2026 + 30000.0, 0.53, 14.25, 0.8501, -0.2032 + 30000.0, 0.53, 14.3, 0.8548, -0.2038 + 30000.0, 0.53, 14.35, 0.8595, -0.2044 + 30000.0, 0.53, 14.4, 0.8642, -0.2049 + 30000.0, 0.53, 14.45, 0.8689, -0.2054 + 30000.0, 0.53, 14.5, 0.8736, -0.2058 + 30000.0, 0.53, 14.55, 0.8782, -0.2062 + 30000.0, 0.53, 14.6, 0.8829, -0.2066 + 30000.0, 0.53, 14.65, 0.8875, -0.207 + 30000.0, 0.53, 14.7, 0.8921, -0.2073 + 30000.0, 0.53, 14.75, 0.8968, -0.2076 + 30000.0, 0.53, 14.8, 0.9014, -0.2078 + 30000.0, 0.53, 14.85, 0.906, -0.208 + 30000.0, 0.53, 14.9, 0.9106, -0.2082 + 30000.0, 0.53, 14.95, 0.9152, -0.2084 + 30000.0, 0.53, 15.0, 0.9198, -0.2085 + 30000.0, 0.53, 15.05, 0.9244, -0.2086 + 30000.0, 0.58, 0.0, -0.1174, -0.02338 + 30000.0, 0.58, 0.05, -0.1165, -0.02306 + 30000.0, 0.58, 0.1, -0.1154, -0.02274 + 30000.0, 0.58, 0.15, -0.1142, -0.0224 + 30000.0, 0.58, 0.2, -0.1129, -0.02206 + 30000.0, 0.58, 0.25, -0.1115, -0.0217 + 30000.0, 0.58, 0.3, -0.1099, -0.02134 + 30000.0, 0.58, 0.35, -0.1083, -0.02097 + 30000.0, 0.58, 0.4, -0.1065, -0.02058 + 30000.0, 0.58, 0.45, -0.1047, -0.02019 + 30000.0, 0.58, 0.5, -0.1027, -0.01979 + 30000.0, 0.58, 0.55, -0.1007, -0.01939 + 30000.0, 0.58, 0.6, -0.09856, -0.01897 + 30000.0, 0.58, 0.65, -0.09634, -0.01855 + 30000.0, 0.58, 0.7, -0.09403, -0.01812 + 30000.0, 0.58, 0.75, -0.09164, -0.01769 + 30000.0, 0.58, 0.8, -0.08917, -0.01724 + 30000.0, 0.58, 0.85, -0.08662, -0.01679 + 30000.0, 0.58, 0.9, -0.08399, -0.01634 + 30000.0, 0.58, 0.95, -0.0813, -0.01588 + 30000.0, 0.58, 1.0, -0.07854, -0.01541 + 30000.0, 0.58, 1.05, -0.07571, -0.01494 + 30000.0, 0.58, 1.1, -0.07282, -0.01447 + 30000.0, 0.58, 1.15, -0.06987, -0.01399 + 30000.0, 0.58, 1.2, -0.06686, -0.01351 + 30000.0, 0.58, 1.25, -0.0638, -0.01302 + 30000.0, 0.58, 1.3, -0.06069, -0.01253 + 30000.0, 0.58, 1.35, -0.05753, -0.01204 + 30000.0, 0.58, 1.4, -0.05432, -0.01154 + 30000.0, 0.58, 1.45, -0.05108, -0.01104 + 30000.0, 0.58, 1.5, -0.04779, -0.01054 + 30000.0, 0.58, 1.55, -0.04447, -0.01003 + 30000.0, 0.58, 1.6, -0.04112, -0.00953 + 30000.0, 0.58, 1.65, -0.03774, -0.009024 + 30000.0, 0.58, 1.7, -0.03433, -0.008516 + 30000.0, 0.58, 1.75, -0.0309, -0.008008 + 30000.0, 0.58, 1.8, -0.02744, -0.007499 + 30000.0, 0.58, 1.85, -0.02397, -0.00699 + 30000.0, 0.58, 1.9, -0.02049, -0.006481 + 30000.0, 0.58, 1.95, -0.01699, -0.005973 + 30000.0, 0.58, 2.0, -0.01348, -0.005466 + 30000.0, 0.58, 2.05, -0.009966, -0.004959 + 30000.0, 0.58, 2.1, -0.00645, -0.004454 + 30000.0, 0.58, 2.15, -0.002933, -0.00395 + 30000.0, 0.58, 2.2, 0.0005809, -0.003449 + 30000.0, 0.58, 2.25, 0.004089, -0.00295 + 30000.0, 0.58, 2.3, 0.007588, -0.002453 + 30000.0, 0.58, 2.35, 0.01108, -0.001959 + 30000.0, 0.58, 2.4, 0.01455, -0.001468 + 30000.0, 0.58, 2.45, 0.018, -0.0009808 + 30000.0, 0.58, 2.5, 0.02144, -0.0004972 + 30000.0, 0.58, 2.55, 0.02485, -1.771e-05 + 30000.0, 0.58, 2.6, 0.02823, 0.0004575 + 30000.0, 0.58, 2.65, 0.03159, 0.000928 + 30000.0, 0.58, 2.7, 0.03491, 0.001394 + 30000.0, 0.58, 2.75, 0.03819, 0.001854 + 30000.0, 0.58, 2.8, 0.04144, 0.002309 + 30000.0, 0.58, 2.85, 0.04465, 0.002758 + 30000.0, 0.58, 2.9, 0.04781, 0.0032 + 30000.0, 0.58, 2.95, 0.05092, 0.003637 + 30000.0, 0.58, 3.0, 0.05399, 0.004066 + 30000.0, 0.58, 3.05, 0.057, 0.004489 + 30000.0, 0.58, 3.1, 0.05995, 0.004904 + 30000.0, 0.58, 3.15, 0.06285, 0.005311 + 30000.0, 0.58, 3.2, 0.06568, 0.005711 + 30000.0, 0.58, 3.25, 0.06845, 0.006102 + 30000.0, 0.58, 3.3, 0.07115, 0.006485 + 30000.0, 0.58, 3.35, 0.07378, 0.006859 + 30000.0, 0.58, 3.4, 0.07633, 0.007224 + 30000.0, 0.58, 3.45, 0.07881, 0.007579 + 30000.0, 0.58, 3.5, 0.0812, 0.007924 + 30000.0, 0.58, 3.55, 0.08352, 0.00826 + 30000.0, 0.58, 3.6, 0.08574, 0.008585 + 30000.0, 0.58, 3.65, 0.08788, 0.008899 + 30000.0, 0.58, 3.7, 0.08993, 0.009203 + 30000.0, 0.58, 3.75, 0.09188, 0.009495 + 30000.0, 0.58, 3.8, 0.09374, 0.009775 + 30000.0, 0.58, 3.85, 0.09549, 0.01004 + 30000.0, 0.58, 3.9, 0.09714, 0.0103 + 30000.0, 0.58, 3.95, 0.09868, 0.01054 + 30000.0, 0.58, 4.0, 0.1001, 0.01078 + 30000.0, 0.58, 4.05, 0.1006, 0.01095 + 30000.0, 0.58, 4.1, 0.101, 0.0111 + 30000.0, 0.58, 4.15, 0.1014, 0.01125 + 30000.0, 0.58, 4.2, 0.1017, 0.01139 + 30000.0, 0.58, 4.25, 0.1019, 0.01152 + 30000.0, 0.58, 4.3, 0.1021, 0.01164 + 30000.0, 0.58, 4.35, 0.1022, 0.01174 + 30000.0, 0.58, 4.4, 0.1023, 0.01184 + 30000.0, 0.58, 4.45, 0.1024, 0.01193 + 30000.0, 0.58, 4.5, 0.1024, 0.01201 + 30000.0, 0.58, 4.55, 0.1024, 0.01207 + 30000.0, 0.58, 4.6, 0.1023, 0.01213 + 30000.0, 0.58, 4.65, 0.1022, 0.01218 + 30000.0, 0.58, 4.7, 0.1021, 0.01222 + 30000.0, 0.58, 4.75, 0.102, 0.01225 + 30000.0, 0.58, 4.8, 0.1018, 0.01227 + 30000.0, 0.58, 4.85, 0.1017, 0.01228 + 30000.0, 0.58, 4.9, 0.1015, 0.01228 + 30000.0, 0.58, 4.95, 0.1013, 0.01228 + 30000.0, 0.58, 5.0, 0.1011, 0.01226 + 30000.0, 0.58, 5.05, 0.1009, 0.01226 + 30000.0, 0.58, 5.1, 0.1007, 0.01226 + 30000.0, 0.58, 5.15, 0.1005, 0.01224 + 30000.0, 0.58, 5.2, 0.1002, 0.01222 + 30000.0, 0.58, 5.25, 0.1001, 0.01218 + 30000.0, 0.58, 5.3, 0.09989, 0.01214 + 30000.0, 0.58, 5.35, 0.09974, 0.01208 + 30000.0, 0.58, 5.4, 0.09963, 0.01201 + 30000.0, 0.58, 5.45, 0.09955, 0.01193 + 30000.0, 0.58, 5.5, 0.0995, 0.01184 + 30000.0, 0.58, 5.55, 0.0995, 0.01173 + 30000.0, 0.58, 5.6, 0.09955, 0.01161 + 30000.0, 0.58, 5.65, 0.09964, 0.01148 + 30000.0, 0.58, 5.7, 0.0998, 0.01133 + 30000.0, 0.58, 5.75, 0.1, 0.01117 + 30000.0, 0.58, 5.8, 0.1003, 0.011 + 30000.0, 0.58, 5.85, 0.1006, 0.01081 + 30000.0, 0.58, 5.9, 0.101, 0.0106 + 30000.0, 0.58, 5.95, 0.1015, 0.01038 + 30000.0, 0.58, 6.0, 0.1021, 0.01014 + 30000.0, 0.58, 6.05, 0.1038, 0.009784 + 30000.0, 0.58, 6.1, 0.1055, 0.009404 + 30000.0, 0.58, 6.15, 0.1075, 0.009002 + 30000.0, 0.58, 6.2, 0.1095, 0.008581 + 30000.0, 0.58, 6.25, 0.1117, 0.008139 + 30000.0, 0.58, 6.3, 0.114, 0.007678 + 30000.0, 0.58, 6.35, 0.1164, 0.007198 + 30000.0, 0.58, 6.4, 0.1189, 0.006699 + 30000.0, 0.58, 6.45, 0.1215, 0.006181 + 30000.0, 0.58, 6.5, 0.1242, 0.005646 + 30000.0, 0.58, 6.55, 0.1271, 0.005093 + 30000.0, 0.58, 6.6, 0.13, 0.004523 + 30000.0, 0.58, 6.65, 0.133, 0.003937 + 30000.0, 0.58, 6.7, 0.1361, 0.003334 + 30000.0, 0.58, 6.75, 0.1393, 0.002716 + 30000.0, 0.58, 6.8, 0.1426, 0.002082 + 30000.0, 0.58, 6.85, 0.146, 0.001432 + 30000.0, 0.58, 6.9, 0.1494, 0.0007687 + 30000.0, 0.58, 6.95, 0.153, 9.07e-05 + 30000.0, 0.58, 7.0, 0.1566, -0.0006011 + 30000.0, 0.58, 7.05, 0.1603, -0.001306 + 30000.0, 0.58, 7.1, 0.164, -0.002025 + 30000.0, 0.58, 7.15, 0.1678, -0.002755 + 30000.0, 0.58, 7.2, 0.1717, -0.003498 + 30000.0, 0.58, 7.25, 0.1756, -0.004253 + 30000.0, 0.58, 7.3, 0.1796, -0.005019 + 30000.0, 0.58, 7.35, 0.1836, -0.005797 + 30000.0, 0.58, 7.4, 0.1877, -0.006584 + 30000.0, 0.58, 7.45, 0.1919, -0.007382 + 30000.0, 0.58, 7.5, 0.196, -0.00819 + 30000.0, 0.58, 7.55, 0.2002, -0.009007 + 30000.0, 0.58, 7.6, 0.2045, -0.009833 + 30000.0, 0.58, 7.65, 0.2088, -0.01067 + 30000.0, 0.58, 7.7, 0.2131, -0.01151 + 30000.0, 0.58, 7.75, 0.2174, -0.01236 + 30000.0, 0.58, 7.8, 0.2218, -0.01322 + 30000.0, 0.58, 7.85, 0.2261, -0.01408 + 30000.0, 0.58, 7.9, 0.2305, -0.01495 + 30000.0, 0.58, 7.95, 0.235, -0.01583 + 30000.0, 0.58, 8.0, 0.2394, -0.01671 + 30000.0, 0.58, 8.05, 0.243, -0.0175 + 30000.0, 0.58, 8.1, 0.2467, -0.0183 + 30000.0, 0.58, 8.15, 0.2503, -0.0191 + 30000.0, 0.58, 8.2, 0.254, -0.0199 + 30000.0, 0.58, 8.25, 0.2576, -0.02071 + 30000.0, 0.58, 8.3, 0.2613, -0.02153 + 30000.0, 0.58, 8.35, 0.265, -0.02235 + 30000.0, 0.58, 8.4, 0.2687, -0.02317 + 30000.0, 0.58, 8.45, 0.2723, -0.024 + 30000.0, 0.58, 8.5, 0.276, -0.02484 + 30000.0, 0.58, 8.55, 0.2797, -0.02568 + 30000.0, 0.58, 8.6, 0.2834, -0.02652 + 30000.0, 0.58, 8.65, 0.2872, -0.02737 + 30000.0, 0.58, 8.7, 0.2909, -0.02822 + 30000.0, 0.58, 8.75, 0.2946, -0.02908 + 30000.0, 0.58, 8.8, 0.2983, -0.02995 + 30000.0, 0.58, 8.85, 0.3021, -0.03082 + 30000.0, 0.58, 8.9, 0.3058, -0.03169 + 30000.0, 0.58, 8.95, 0.3095, -0.03257 + 30000.0, 0.58, 9.0, 0.3133, -0.03345 + 30000.0, 0.58, 9.05, 0.317, -0.03434 + 30000.0, 0.58, 9.1, 0.3208, -0.03523 + 30000.0, 0.58, 9.15, 0.3245, -0.03612 + 30000.0, 0.58, 9.2, 0.3283, -0.03702 + 30000.0, 0.58, 9.25, 0.3321, -0.03793 + 30000.0, 0.58, 9.3, 0.3358, -0.03883 + 30000.0, 0.58, 9.35, 0.3396, -0.03975 + 30000.0, 0.58, 9.4, 0.3434, -0.04066 + 30000.0, 0.58, 9.45, 0.3472, -0.04159 + 30000.0, 0.58, 9.5, 0.3509, -0.04251 + 30000.0, 0.58, 9.55, 0.3547, -0.04344 + 30000.0, 0.58, 9.6, 0.3585, -0.04437 + 30000.0, 0.58, 9.65, 0.3623, -0.04531 + 30000.0, 0.58, 9.7, 0.3661, -0.04625 + 30000.0, 0.58, 9.75, 0.3699, -0.0472 + 30000.0, 0.58, 9.8, 0.3736, -0.04815 + 30000.0, 0.58, 9.85, 0.3774, -0.0491 + 30000.0, 0.58, 9.9, 0.3812, -0.05006 + 30000.0, 0.58, 9.95, 0.385, -0.05102 + 30000.0, 0.58, 10.0, 0.3888, -0.05198 + 30000.0, 0.58, 10.05, 0.3926, -0.05302 + 30000.0, 0.58, 10.1, 0.3963, -0.05405 + 30000.0, 0.58, 10.15, 0.4001, -0.05509 + 30000.0, 0.58, 10.2, 0.4039, -0.05614 + 30000.0, 0.58, 10.25, 0.4076, -0.05718 + 30000.0, 0.58, 10.3, 0.4114, -0.05823 + 30000.0, 0.58, 10.35, 0.4152, -0.05928 + 30000.0, 0.58, 10.4, 0.4189, -0.06033 + 30000.0, 0.58, 10.45, 0.4227, -0.06138 + 30000.0, 0.58, 10.5, 0.4265, -0.06244 + 30000.0, 0.58, 10.55, 0.4302, -0.06349 + 30000.0, 0.58, 10.6, 0.434, -0.06455 + 30000.0, 0.58, 10.65, 0.4378, -0.0656 + 30000.0, 0.58, 10.7, 0.4415, -0.06666 + 30000.0, 0.58, 10.75, 0.4453, -0.06771 + 30000.0, 0.58, 10.8, 0.4491, -0.06877 + 30000.0, 0.58, 10.85, 0.4528, -0.06982 + 30000.0, 0.58, 10.9, 0.4566, -0.07088 + 30000.0, 0.58, 10.95, 0.4604, -0.07193 + 30000.0, 0.58, 11.0, 0.4641, -0.07298 + 30000.0, 0.58, 11.05, 0.4679, -0.07403 + 30000.0, 0.58, 11.1, 0.4716, -0.07508 + 30000.0, 0.58, 11.15, 0.4754, -0.07612 + 30000.0, 0.58, 11.2, 0.4792, -0.07716 + 30000.0, 0.58, 11.25, 0.4829, -0.0782 + 30000.0, 0.58, 11.3, 0.4867, -0.07924 + 30000.0, 0.58, 11.35, 0.4904, -0.08027 + 30000.0, 0.58, 11.4, 0.4942, -0.0813 + 30000.0, 0.58, 11.45, 0.498, -0.08232 + 30000.0, 0.58, 11.5, 0.5017, -0.08334 + 30000.0, 0.58, 11.55, 0.5055, -0.08436 + 30000.0, 0.58, 11.6, 0.5092, -0.08537 + 30000.0, 0.58, 11.65, 0.513, -0.08637 + 30000.0, 0.58, 11.7, 0.5167, -0.08737 + 30000.0, 0.58, 11.75, 0.5205, -0.08836 + 30000.0, 0.58, 11.8, 0.5242, -0.08935 + 30000.0, 0.58, 11.85, 0.528, -0.09033 + 30000.0, 0.58, 11.9, 0.5317, -0.09131 + 30000.0, 0.58, 11.95, 0.5355, -0.09228 + 30000.0, 0.58, 12.0, 0.5392, -0.09324 + 30000.0, 0.58, 12.05, 0.5429, -0.09419 + 30000.0, 0.58, 12.1, 0.5467, -0.09513 + 30000.0, 0.58, 12.15, 0.5504, -0.09607 + 30000.0, 0.58, 12.2, 0.5541, -0.097 + 30000.0, 0.58, 12.25, 0.5579, -0.09792 + 30000.0, 0.58, 12.3, 0.5616, -0.09883 + 30000.0, 0.58, 12.35, 0.5653, -0.09974 + 30000.0, 0.58, 12.4, 0.5691, -0.1006 + 30000.0, 0.58, 12.45, 0.5728, -0.1015 + 30000.0, 0.58, 12.5, 0.5765, -0.1024 + 30000.0, 0.58, 12.55, 0.5802, -0.1032 + 30000.0, 0.58, 12.6, 0.584, -0.1041 + 30000.0, 0.58, 12.65, 0.5877, -0.1049 + 30000.0, 0.58, 12.7, 0.5914, -0.1058 + 30000.0, 0.58, 12.75, 0.5951, -0.1066 + 30000.0, 0.58, 12.8, 0.5988, -0.1074 + 30000.0, 0.58, 12.85, 0.6025, -0.1082 + 30000.0, 0.58, 12.9, 0.6062, -0.109 + 30000.0, 0.58, 12.95, 0.6099, -0.1098 + 30000.0, 0.58, 13.0, 0.6136, -0.1105 + 30000.0, 0.58, 13.05, 0.6173, -0.1113 + 30000.0, 0.58, 13.1, 0.621, -0.112 + 30000.0, 0.58, 13.15, 0.6247, -0.1127 + 30000.0, 0.58, 13.2, 0.6284, -0.1134 + 30000.0, 0.58, 13.25, 0.6321, -0.1141 + 30000.0, 0.58, 13.3, 0.6357, -0.1148 + 30000.0, 0.58, 13.35, 0.6394, -0.1154 + 30000.0, 0.58, 13.4, 0.6431, -0.1161 + 30000.0, 0.58, 13.45, 0.6468, -0.1167 + 30000.0, 0.58, 13.5, 0.6504, -0.1173 + 30000.0, 0.58, 13.55, 0.6541, -0.1179 + 30000.0, 0.58, 13.6, 0.6578, -0.1185 + 30000.0, 0.58, 13.65, 0.6614, -0.1191 + 30000.0, 0.58, 13.7, 0.6651, -0.1196 + 30000.0, 0.58, 13.75, 0.6687, -0.1202 + 30000.0, 0.58, 13.8, 0.6724, -0.1207 + 30000.0, 0.58, 13.85, 0.676, -0.1212 + 30000.0, 0.58, 13.9, 0.6796, -0.1217 + 30000.0, 0.58, 13.95, 0.6833, -0.1221 + 30000.0, 0.58, 14.0, 0.6869, -0.1226 + 30000.0, 0.58, 14.05, 0.6905, -0.123 + 30000.0, 0.58, 14.1, 0.6942, -0.1234 + 30000.0, 0.58, 14.15, 0.6978, -0.1238 + 30000.0, 0.58, 14.2, 0.7014, -0.1242 + 30000.0, 0.58, 14.25, 0.705, -0.1245 + 30000.0, 0.58, 14.3, 0.7086, -0.1248 + 30000.0, 0.58, 14.35, 0.7122, -0.1251 + 30000.0, 0.58, 14.4, 0.7158, -0.1254 + 30000.0, 0.58, 14.45, 0.7194, -0.1257 + 30000.0, 0.58, 14.5, 0.723, -0.1259 + 30000.0, 0.58, 14.55, 0.7266, -0.1262 + 30000.0, 0.58, 14.6, 0.7302, -0.1264 + 30000.0, 0.58, 14.65, 0.7337, -0.1265 + 30000.0, 0.58, 14.7, 0.7373, -0.1267 + 30000.0, 0.58, 14.75, 0.7409, -0.1268 + 30000.0, 0.58, 14.8, 0.7444, -0.127 + 30000.0, 0.58, 14.85, 0.748, -0.127 + 30000.0, 0.58, 14.9, 0.7515, -0.1271 + 30000.0, 0.58, 14.95, 0.7551, -0.1272 + 30000.0, 0.58, 15.0, 0.7586, -0.1272 + 30000.0, 0.58, 15.05, 0.7622, -0.1272 + 30000.0, 0.63, 0.0, -0.1323, -0.009531 + 30000.0, 0.63, 0.05, -0.1304, -0.009379 + 30000.0, 0.63, 0.1, -0.1284, -0.009223 + 30000.0, 0.63, 0.15, -0.1263, -0.009062 + 30000.0, 0.63, 0.2, -0.1242, -0.008897 + 30000.0, 0.63, 0.25, -0.1221, -0.008727 + 30000.0, 0.63, 0.3, -0.1199, -0.008553 + 30000.0, 0.63, 0.35, -0.1176, -0.008375 + 30000.0, 0.63, 0.4, -0.1153, -0.008193 + 30000.0, 0.63, 0.45, -0.1129, -0.008007 + 30000.0, 0.63, 0.5, -0.1104, -0.007817 + 30000.0, 0.63, 0.55, -0.108, -0.007623 + 30000.0, 0.63, 0.6, -0.1054, -0.007426 + 30000.0, 0.63, 0.65, -0.1029, -0.007226 + 30000.0, 0.63, 0.7, -0.1002, -0.007022 + 30000.0, 0.63, 0.75, -0.09758, -0.006815 + 30000.0, 0.63, 0.8, -0.09487, -0.006605 + 30000.0, 0.63, 0.85, -0.09213, -0.006392 + 30000.0, 0.63, 0.9, -0.08934, -0.006177 + 30000.0, 0.63, 0.95, -0.08652, -0.005958 + 30000.0, 0.63, 1.0, -0.08366, -0.005737 + 30000.0, 0.63, 1.05, -0.08077, -0.005514 + 30000.0, 0.63, 1.1, -0.07785, -0.005289 + 30000.0, 0.63, 1.15, -0.07489, -0.005061 + 30000.0, 0.63, 1.2, -0.07191, -0.004831 + 30000.0, 0.63, 1.25, -0.0689, -0.0046 + 30000.0, 0.63, 1.3, -0.06586, -0.004366 + 30000.0, 0.63, 1.35, -0.0628, -0.004131 + 30000.0, 0.63, 1.4, -0.05971, -0.003894 + 30000.0, 0.63, 1.45, -0.05661, -0.003656 + 30000.0, 0.63, 1.5, -0.05348, -0.003417 + 30000.0, 0.63, 1.55, -0.05034, -0.003177 + 30000.0, 0.63, 1.6, -0.04718, -0.002935 + 30000.0, 0.63, 1.65, -0.044, -0.002693 + 30000.0, 0.63, 1.7, -0.04081, -0.002449 + 30000.0, 0.63, 1.75, -0.03761, -0.002206 + 30000.0, 0.63, 1.8, -0.03439, -0.001961 + 30000.0, 0.63, 1.85, -0.03117, -0.001716 + 30000.0, 0.63, 1.9, -0.02794, -0.001471 + 30000.0, 0.63, 1.95, -0.02471, -0.001226 + 30000.0, 0.63, 2.0, -0.02147, -0.0009805 + 30000.0, 0.63, 2.05, -0.01822, -0.0007352 + 30000.0, 0.63, 2.1, -0.01498, -0.0004902 + 30000.0, 0.63, 2.15, -0.01174, -0.0002455 + 30000.0, 0.63, 2.2, -0.008496, -1.227e-06 + 30000.0, 0.63, 2.25, -0.005258, 0.0002424 + 30000.0, 0.63, 2.3, -0.002025, 0.0004854 + 30000.0, 0.63, 2.35, 0.001201, 0.0007275 + 30000.0, 0.63, 2.4, 0.004418, 0.0009687 + 30000.0, 0.63, 2.45, 0.007626, 0.001209 + 30000.0, 0.63, 2.5, 0.01082, 0.001448 + 30000.0, 0.63, 2.55, 0.01401, 0.001685 + 30000.0, 0.63, 2.6, 0.01718, 0.001921 + 30000.0, 0.63, 2.65, 0.02033, 0.002156 + 30000.0, 0.63, 2.7, 0.02346, 0.002389 + 30000.0, 0.63, 2.75, 0.02658, 0.00262 + 30000.0, 0.63, 2.8, 0.02968, 0.002849 + 30000.0, 0.63, 2.85, 0.03275, 0.003076 + 30000.0, 0.63, 2.9, 0.0358, 0.0033 + 30000.0, 0.63, 2.95, 0.03882, 0.003523 + 30000.0, 0.63, 3.0, 0.04182, 0.003743 + 30000.0, 0.63, 3.05, 0.04479, 0.00396 + 30000.0, 0.63, 3.1, 0.04773, 0.004175 + 30000.0, 0.63, 3.15, 0.05064, 0.004386 + 30000.0, 0.63, 3.2, 0.05351, 0.004595 + 30000.0, 0.63, 3.25, 0.05635, 0.004801 + 30000.0, 0.63, 3.3, 0.05915, 0.005004 + 30000.0, 0.63, 3.35, 0.06192, 0.005203 + 30000.0, 0.63, 3.4, 0.06464, 0.005399 + 30000.0, 0.63, 3.45, 0.06733, 0.005591 + 30000.0, 0.63, 3.5, 0.06997, 0.00578 + 30000.0, 0.63, 3.55, 0.07256, 0.005964 + 30000.0, 0.63, 3.6, 0.07512, 0.006145 + 30000.0, 0.63, 3.65, 0.07762, 0.006322 + 30000.0, 0.63, 3.7, 0.08008, 0.006494 + 30000.0, 0.63, 3.75, 0.08248, 0.006662 + 30000.0, 0.63, 3.8, 0.08483, 0.006826 + 30000.0, 0.63, 3.85, 0.08713, 0.006985 + 30000.0, 0.63, 3.9, 0.08938, 0.00714 + 30000.0, 0.63, 3.95, 0.09157, 0.007289 + 30000.0, 0.63, 4.0, 0.0937, 0.007434 + 30000.0, 0.63, 4.05, 0.09532, 0.007546 + 30000.0, 0.63, 4.1, 0.09692, 0.007654 + 30000.0, 0.63, 4.15, 0.09847, 0.007758 + 30000.0, 0.63, 4.2, 0.1, 0.00786 + 30000.0, 0.63, 4.25, 0.1015, 0.007958 + 30000.0, 0.63, 4.3, 0.103, 0.008053 + 30000.0, 0.63, 4.35, 0.1044, 0.008144 + 30000.0, 0.63, 4.4, 0.1058, 0.008233 + 30000.0, 0.63, 4.45, 0.1072, 0.008319 + 30000.0, 0.63, 4.5, 0.1086, 0.008402 + 30000.0, 0.63, 4.55, 0.11, 0.008482 + 30000.0, 0.63, 4.6, 0.1113, 0.00856 + 30000.0, 0.63, 4.65, 0.1126, 0.008635 + 30000.0, 0.63, 4.7, 0.1139, 0.008707 + 30000.0, 0.63, 4.75, 0.1152, 0.008778 + 30000.0, 0.63, 4.8, 0.1165, 0.008845 + 30000.0, 0.63, 4.85, 0.1178, 0.008911 + 30000.0, 0.63, 4.9, 0.1191, 0.008975 + 30000.0, 0.63, 4.95, 0.1204, 0.009037 + 30000.0, 0.63, 5.0, 0.1217, 0.009096 + 30000.0, 0.63, 5.05, 0.123, 0.009183 + 30000.0, 0.63, 5.1, 0.1243, 0.009267 + 30000.0, 0.63, 5.15, 0.1256, 0.009349 + 30000.0, 0.63, 5.2, 0.1269, 0.009428 + 30000.0, 0.63, 5.25, 0.1282, 0.009503 + 30000.0, 0.63, 5.3, 0.1296, 0.009576 + 30000.0, 0.63, 5.35, 0.1309, 0.009644 + 30000.0, 0.63, 5.4, 0.1323, 0.009708 + 30000.0, 0.63, 5.45, 0.1336, 0.009768 + 30000.0, 0.63, 5.5, 0.135, 0.009823 + 30000.0, 0.63, 5.55, 0.1364, 0.009872 + 30000.0, 0.63, 5.6, 0.1378, 0.009916 + 30000.0, 0.63, 5.65, 0.1392, 0.009954 + 30000.0, 0.63, 5.7, 0.1406, 0.009986 + 30000.0, 0.63, 5.75, 0.142, 0.01001 + 30000.0, 0.63, 5.8, 0.1435, 0.01003 + 30000.0, 0.63, 5.85, 0.145, 0.01004 + 30000.0, 0.63, 5.9, 0.1465, 0.01004 + 30000.0, 0.63, 5.95, 0.148, 0.01004 + 30000.0, 0.63, 6.0, 0.1496, 0.01003 + 30000.0, 0.63, 6.05, 0.1515, 0.009924 + 30000.0, 0.63, 6.1, 0.1534, 0.009809 + 30000.0, 0.63, 6.15, 0.1554, 0.009681 + 30000.0, 0.63, 6.2, 0.1574, 0.009542 + 30000.0, 0.63, 6.25, 0.1594, 0.009391 + 30000.0, 0.63, 6.3, 0.1615, 0.009229 + 30000.0, 0.63, 6.35, 0.1636, 0.009056 + 30000.0, 0.63, 6.4, 0.1657, 0.008872 + 30000.0, 0.63, 6.45, 0.1679, 0.008678 + 30000.0, 0.63, 6.5, 0.1701, 0.008473 + 30000.0, 0.63, 6.55, 0.1724, 0.008258 + 30000.0, 0.63, 6.6, 0.1746, 0.008034 + 30000.0, 0.63, 6.65, 0.1769, 0.0078 + 30000.0, 0.63, 6.7, 0.1793, 0.007557 + 30000.0, 0.63, 6.75, 0.1816, 0.007305 + 30000.0, 0.63, 6.8, 0.184, 0.007044 + 30000.0, 0.63, 6.85, 0.1864, 0.006775 + 30000.0, 0.63, 6.9, 0.1888, 0.006498 + 30000.0, 0.63, 6.95, 0.1913, 0.006212 + 30000.0, 0.63, 7.0, 0.1938, 0.005919 + 30000.0, 0.63, 7.05, 0.1963, 0.005619 + 30000.0, 0.63, 7.1, 0.1988, 0.005312 + 30000.0, 0.63, 7.15, 0.2014, 0.004997 + 30000.0, 0.63, 7.2, 0.2039, 0.004676 + 30000.0, 0.63, 7.25, 0.2065, 0.004349 + 30000.0, 0.63, 7.3, 0.2091, 0.004016 + 30000.0, 0.63, 7.35, 0.2117, 0.003677 + 30000.0, 0.63, 7.4, 0.2144, 0.003332 + 30000.0, 0.63, 7.45, 0.217, 0.002982 + 30000.0, 0.63, 7.5, 0.2197, 0.002626 + 30000.0, 0.63, 7.55, 0.2224, 0.002267 + 30000.0, 0.63, 7.6, 0.2251, 0.001902 + 30000.0, 0.63, 7.65, 0.2278, 0.001533 + 30000.0, 0.63, 7.7, 0.2305, 0.001161 + 30000.0, 0.63, 7.75, 0.2332, 0.0007842 + 30000.0, 0.63, 7.8, 0.2359, 0.0004042 + 30000.0, 0.63, 7.85, 0.2387, 2.1e-05 + 30000.0, 0.63, 7.9, 0.2414, -0.0003652 + 30000.0, 0.63, 7.95, 0.2442, -0.000754 + 30000.0, 0.63, 8.0, 0.2469, -0.001145 + 30000.0, 0.63, 8.05, 0.2494, -0.001473 + 30000.0, 0.63, 8.1, 0.252, -0.001803 + 30000.0, 0.63, 8.15, 0.2545, -0.002135 + 30000.0, 0.63, 8.2, 0.2571, -0.002469 + 30000.0, 0.63, 8.25, 0.2596, -0.002805 + 30000.0, 0.63, 8.3, 0.2622, -0.003144 + 30000.0, 0.63, 8.35, 0.2648, -0.003484 + 30000.0, 0.63, 8.4, 0.2673, -0.003827 + 30000.0, 0.63, 8.45, 0.2699, -0.004172 + 30000.0, 0.63, 8.5, 0.2725, -0.004519 + 30000.0, 0.63, 8.55, 0.275, -0.004867 + 30000.0, 0.63, 8.6, 0.2776, -0.005218 + 30000.0, 0.63, 8.65, 0.2802, -0.005571 + 30000.0, 0.63, 8.7, 0.2828, -0.005926 + 30000.0, 0.63, 8.75, 0.2854, -0.006283 + 30000.0, 0.63, 8.8, 0.288, -0.006642 + 30000.0, 0.63, 8.85, 0.2905, -0.007003 + 30000.0, 0.63, 8.9, 0.2931, -0.007366 + 30000.0, 0.63, 8.95, 0.2957, -0.00773 + 30000.0, 0.63, 9.0, 0.2983, -0.008097 + 30000.0, 0.63, 9.05, 0.3009, -0.008466 + 30000.0, 0.63, 9.1, 0.3035, -0.008836 + 30000.0, 0.63, 9.15, 0.3061, -0.009209 + 30000.0, 0.63, 9.2, 0.3087, -0.009583 + 30000.0, 0.63, 9.25, 0.3114, -0.009959 + 30000.0, 0.63, 9.3, 0.314, -0.01034 + 30000.0, 0.63, 9.35, 0.3166, -0.01072 + 30000.0, 0.63, 9.4, 0.3192, -0.0111 + 30000.0, 0.63, 9.45, 0.3218, -0.01148 + 30000.0, 0.63, 9.5, 0.3244, -0.01187 + 30000.0, 0.63, 9.55, 0.327, -0.01225 + 30000.0, 0.63, 9.6, 0.3297, -0.01264 + 30000.0, 0.63, 9.65, 0.3323, -0.01303 + 30000.0, 0.63, 9.7, 0.3349, -0.01343 + 30000.0, 0.63, 9.75, 0.3375, -0.01382 + 30000.0, 0.63, 9.8, 0.3401, -0.01422 + 30000.0, 0.63, 9.85, 0.3428, -0.01461 + 30000.0, 0.63, 9.9, 0.3454, -0.01501 + 30000.0, 0.63, 9.95, 0.348, -0.01541 + 30000.0, 0.63, 10.0, 0.3506, -0.01582 + 30000.0, 0.63, 10.05, 0.3532, -0.01625 + 30000.0, 0.63, 10.1, 0.3559, -0.01669 + 30000.0, 0.63, 10.15, 0.3585, -0.01713 + 30000.0, 0.63, 10.2, 0.3611, -0.01757 + 30000.0, 0.63, 10.25, 0.3637, -0.01802 + 30000.0, 0.63, 10.3, 0.3663, -0.01846 + 30000.0, 0.63, 10.35, 0.3689, -0.0189 + 30000.0, 0.63, 10.4, 0.3715, -0.01935 + 30000.0, 0.63, 10.45, 0.3741, -0.01979 + 30000.0, 0.63, 10.5, 0.3767, -0.02024 + 30000.0, 0.63, 10.55, 0.3793, -0.02068 + 30000.0, 0.63, 10.6, 0.382, -0.02113 + 30000.0, 0.63, 10.65, 0.3846, -0.02158 + 30000.0, 0.63, 10.7, 0.3872, -0.02202 + 30000.0, 0.63, 10.75, 0.3898, -0.02247 + 30000.0, 0.63, 10.8, 0.3924, -0.02291 + 30000.0, 0.63, 10.85, 0.395, -0.02336 + 30000.0, 0.63, 10.9, 0.3976, -0.0238 + 30000.0, 0.63, 10.95, 0.4002, -0.02425 + 30000.0, 0.63, 11.0, 0.4028, -0.02469 + 30000.0, 0.63, 11.05, 0.4054, -0.02513 + 30000.0, 0.63, 11.1, 0.4081, -0.02557 + 30000.0, 0.63, 11.15, 0.4107, -0.02601 + 30000.0, 0.63, 11.2, 0.4133, -0.02645 + 30000.0, 0.63, 11.25, 0.4159, -0.02688 + 30000.0, 0.63, 11.3, 0.4185, -0.02732 + 30000.0, 0.63, 11.35, 0.4211, -0.02775 + 30000.0, 0.63, 11.4, 0.4237, -0.02818 + 30000.0, 0.63, 11.45, 0.4263, -0.02861 + 30000.0, 0.63, 11.5, 0.4289, -0.02903 + 30000.0, 0.63, 11.55, 0.4315, -0.02946 + 30000.0, 0.63, 11.6, 0.4341, -0.02988 + 30000.0, 0.63, 11.65, 0.4367, -0.0303 + 30000.0, 0.63, 11.7, 0.4393, -0.03071 + 30000.0, 0.63, 11.75, 0.4419, -0.03112 + 30000.0, 0.63, 11.8, 0.4445, -0.03153 + 30000.0, 0.63, 11.85, 0.4471, -0.03194 + 30000.0, 0.63, 11.9, 0.4498, -0.03234 + 30000.0, 0.63, 11.95, 0.4524, -0.03274 + 30000.0, 0.63, 12.0, 0.455, -0.03313 + 30000.0, 0.63, 12.05, 0.4576, -0.03353 + 30000.0, 0.63, 12.1, 0.4602, -0.03391 + 30000.0, 0.63, 12.15, 0.4628, -0.0343 + 30000.0, 0.63, 12.2, 0.4653, -0.03468 + 30000.0, 0.63, 12.25, 0.4679, -0.03505 + 30000.0, 0.63, 12.3, 0.4705, -0.03542 + 30000.0, 0.63, 12.35, 0.4731, -0.03579 + 30000.0, 0.63, 12.4, 0.4757, -0.03615 + 30000.0, 0.63, 12.45, 0.4783, -0.0365 + 30000.0, 0.63, 12.5, 0.4809, -0.03686 + 30000.0, 0.63, 12.55, 0.4835, -0.0372 + 30000.0, 0.63, 12.6, 0.4861, -0.03754 + 30000.0, 0.63, 12.65, 0.4887, -0.03788 + 30000.0, 0.63, 12.7, 0.4913, -0.03821 + 30000.0, 0.63, 12.75, 0.4939, -0.03853 + 30000.0, 0.63, 12.8, 0.4964, -0.03885 + 30000.0, 0.63, 12.85, 0.499, -0.03916 + 30000.0, 0.63, 12.9, 0.5016, -0.03947 + 30000.0, 0.63, 12.95, 0.5042, -0.03977 + 30000.0, 0.63, 13.0, 0.5068, -0.04006 + 30000.0, 0.63, 13.05, 0.5094, -0.04035 + 30000.0, 0.63, 13.1, 0.5119, -0.04063 + 30000.0, 0.63, 13.15, 0.5145, -0.0409 + 30000.0, 0.63, 13.2, 0.5171, -0.04117 + 30000.0, 0.63, 13.25, 0.5197, -0.04143 + 30000.0, 0.63, 13.3, 0.5222, -0.04168 + 30000.0, 0.63, 13.35, 0.5248, -0.04193 + 30000.0, 0.63, 13.4, 0.5274, -0.04216 + 30000.0, 0.63, 13.45, 0.5299, -0.04239 + 30000.0, 0.63, 13.5, 0.5325, -0.04262 + 30000.0, 0.63, 13.55, 0.5351, -0.04283 + 30000.0, 0.63, 13.6, 0.5376, -0.04304 + 30000.0, 0.63, 13.65, 0.5402, -0.04323 + 30000.0, 0.63, 13.7, 0.5428, -0.04342 + 30000.0, 0.63, 13.75, 0.5453, -0.0436 + 30000.0, 0.63, 13.8, 0.5479, -0.04378 + 30000.0, 0.63, 13.85, 0.5504, -0.04394 + 30000.0, 0.63, 13.9, 0.553, -0.0441 + 30000.0, 0.63, 13.95, 0.5555, -0.04424 + 30000.0, 0.63, 14.0, 0.5581, -0.04438 + 30000.0, 0.63, 14.05, 0.5606, -0.04451 + 30000.0, 0.63, 14.1, 0.5632, -0.04463 + 30000.0, 0.63, 14.15, 0.5657, -0.04474 + 30000.0, 0.63, 14.2, 0.5683, -0.04484 + 30000.0, 0.63, 14.25, 0.5708, -0.04493 + 30000.0, 0.63, 14.3, 0.5733, -0.04501 + 30000.0, 0.63, 14.35, 0.5759, -0.04507 + 30000.0, 0.63, 14.4, 0.5784, -0.04513 + 30000.0, 0.63, 14.45, 0.5809, -0.04518 + 30000.0, 0.63, 14.5, 0.5835, -0.04522 + 30000.0, 0.63, 14.55, 0.586, -0.04525 + 30000.0, 0.63, 14.6, 0.5885, -0.04527 + 30000.0, 0.63, 14.65, 0.591, -0.04527 + 30000.0, 0.63, 14.7, 0.5936, -0.04527 + 30000.0, 0.63, 14.75, 0.5961, -0.04525 + 30000.0, 0.63, 14.8, 0.5986, -0.04523 + 30000.0, 0.63, 14.85, 0.6011, -0.04519 + 30000.0, 0.63, 14.9, 0.6036, -0.04514 + 30000.0, 0.63, 14.95, 0.6061, -0.04508 + 30000.0, 0.63, 15.0, 0.6086, -0.045 + 30000.0, 0.63, 15.05, 0.6111, -0.04492 + 30000.0, 0.68, 0.0, -0.149, 0.002105 + 30000.0, 0.68, 0.05, -0.1462, 0.002124 + 30000.0, 0.68, 0.1, -0.1434, 0.002142 + 30000.0, 0.68, 0.15, -0.1406, 0.002161 + 30000.0, 0.68, 0.2, -0.1377, 0.00218 + 30000.0, 0.68, 0.25, -0.1349, 0.002198 + 30000.0, 0.68, 0.3, -0.132, 0.002216 + 30000.0, 0.68, 0.35, -0.1291, 0.002234 + 30000.0, 0.68, 0.4, -0.1263, 0.002252 + 30000.0, 0.68, 0.45, -0.1233, 0.00227 + 30000.0, 0.68, 0.5, -0.1204, 0.002288 + 30000.0, 0.68, 0.55, -0.1175, 0.002306 + 30000.0, 0.68, 0.6, -0.1146, 0.002324 + 30000.0, 0.68, 0.65, -0.1116, 0.002341 + 30000.0, 0.68, 0.7, -0.1086, 0.002359 + 30000.0, 0.68, 0.75, -0.1057, 0.002377 + 30000.0, 0.68, 0.8, -0.1027, 0.002396 + 30000.0, 0.68, 0.85, -0.09969, 0.002414 + 30000.0, 0.68, 0.9, -0.09668, 0.002432 + 30000.0, 0.68, 0.95, -0.09367, 0.002451 + 30000.0, 0.68, 1.0, -0.09065, 0.00247 + 30000.0, 0.68, 1.05, -0.08762, 0.002489 + 30000.0, 0.68, 1.1, -0.08458, 0.002508 + 30000.0, 0.68, 1.15, -0.08154, 0.002528 + 30000.0, 0.68, 1.2, -0.07849, 0.002548 + 30000.0, 0.68, 1.25, -0.07543, 0.002568 + 30000.0, 0.68, 1.3, -0.07237, 0.002588 + 30000.0, 0.68, 1.35, -0.0693, 0.002609 + 30000.0, 0.68, 1.4, -0.06622, 0.002631 + 30000.0, 0.68, 1.45, -0.06314, 0.002652 + 30000.0, 0.68, 1.5, -0.06006, 0.002674 + 30000.0, 0.68, 1.55, -0.05697, 0.002697 + 30000.0, 0.68, 1.6, -0.05388, 0.00272 + 30000.0, 0.68, 1.65, -0.05078, 0.002744 + 30000.0, 0.68, 1.7, -0.04768, 0.002768 + 30000.0, 0.68, 1.75, -0.04458, 0.002792 + 30000.0, 0.68, 1.8, -0.04148, 0.002818 + 30000.0, 0.68, 1.85, -0.03837, 0.002844 + 30000.0, 0.68, 1.9, -0.03527, 0.00287 + 30000.0, 0.68, 1.95, -0.03216, 0.002897 + 30000.0, 0.68, 2.0, -0.02905, 0.002925 + 30000.0, 0.68, 2.05, -0.02595, 0.002954 + 30000.0, 0.68, 2.1, -0.02284, 0.002983 + 30000.0, 0.68, 2.15, -0.01973, 0.003013 + 30000.0, 0.68, 2.2, -0.01663, 0.003044 + 30000.0, 0.68, 2.25, -0.01353, 0.003075 + 30000.0, 0.68, 2.3, -0.01043, 0.003108 + 30000.0, 0.68, 2.35, -0.007328, 0.003141 + 30000.0, 0.68, 2.4, -0.004233, 0.003175 + 30000.0, 0.68, 2.45, -0.001141, 0.00321 + 30000.0, 0.68, 2.5, 0.001948, 0.003246 + 30000.0, 0.68, 2.55, 0.005033, 0.003283 + 30000.0, 0.68, 2.6, 0.008112, 0.003321 + 30000.0, 0.68, 2.65, 0.01119, 0.003359 + 30000.0, 0.68, 2.7, 0.01426, 0.003399 + 30000.0, 0.68, 2.75, 0.01732, 0.00344 + 30000.0, 0.68, 2.8, 0.02038, 0.003482 + 30000.0, 0.68, 2.85, 0.02343, 0.003525 + 30000.0, 0.68, 2.9, 0.02648, 0.003569 + 30000.0, 0.68, 2.95, 0.02951, 0.003614 + 30000.0, 0.68, 3.0, 0.03254, 0.00366 + 30000.0, 0.68, 3.05, 0.03556, 0.003708 + 30000.0, 0.68, 3.1, 0.03858, 0.003757 + 30000.0, 0.68, 3.15, 0.04158, 0.003806 + 30000.0, 0.68, 3.2, 0.04457, 0.003858 + 30000.0, 0.68, 3.25, 0.04756, 0.00391 + 30000.0, 0.68, 3.3, 0.05053, 0.003964 + 30000.0, 0.68, 3.35, 0.0535, 0.004019 + 30000.0, 0.68, 3.4, 0.05645, 0.004075 + 30000.0, 0.68, 3.45, 0.05939, 0.004133 + 30000.0, 0.68, 3.5, 0.06232, 0.004192 + 30000.0, 0.68, 3.55, 0.06524, 0.004253 + 30000.0, 0.68, 3.6, 0.06814, 0.004315 + 30000.0, 0.68, 3.65, 0.07103, 0.004378 + 30000.0, 0.68, 3.7, 0.07391, 0.004443 + 30000.0, 0.68, 3.75, 0.07677, 0.00451 + 30000.0, 0.68, 3.8, 0.07962, 0.004577 + 30000.0, 0.68, 3.85, 0.08246, 0.004647 + 30000.0, 0.68, 3.9, 0.08528, 0.004718 + 30000.0, 0.68, 3.95, 0.08808, 0.004791 + 30000.0, 0.68, 4.0, 0.09087, 0.004865 + 30000.0, 0.68, 4.05, 0.09352, 0.004932 + 30000.0, 0.68, 4.1, 0.09617, 0.005001 + 30000.0, 0.68, 4.15, 0.0988, 0.005073 + 30000.0, 0.68, 4.2, 0.1014, 0.005147 + 30000.0, 0.68, 4.25, 0.104, 0.005223 + 30000.0, 0.68, 4.3, 0.1067, 0.005302 + 30000.0, 0.68, 4.35, 0.1093, 0.005384 + 30000.0, 0.68, 4.4, 0.1118, 0.005468 + 30000.0, 0.68, 4.45, 0.1144, 0.005555 + 30000.0, 0.68, 4.5, 0.117, 0.005645 + 30000.0, 0.68, 4.55, 0.1196, 0.005739 + 30000.0, 0.68, 4.6, 0.1222, 0.005835 + 30000.0, 0.68, 4.65, 0.1247, 0.005935 + 30000.0, 0.68, 4.7, 0.1273, 0.006037 + 30000.0, 0.68, 4.75, 0.1299, 0.006144 + 30000.0, 0.68, 4.8, 0.1324, 0.006253 + 30000.0, 0.68, 4.85, 0.135, 0.006367 + 30000.0, 0.68, 4.9, 0.1376, 0.006484 + 30000.0, 0.68, 4.95, 0.1401, 0.006605 + 30000.0, 0.68, 5.0, 0.1427, 0.006729 + 30000.0, 0.68, 5.05, 0.1453, 0.006884 + 30000.0, 0.68, 5.1, 0.148, 0.007042 + 30000.0, 0.68, 5.15, 0.1507, 0.007204 + 30000.0, 0.68, 5.2, 0.1533, 0.007368 + 30000.0, 0.68, 5.25, 0.156, 0.007536 + 30000.0, 0.68, 5.3, 0.1586, 0.007706 + 30000.0, 0.68, 5.35, 0.1613, 0.007878 + 30000.0, 0.68, 5.4, 0.1639, 0.008052 + 30000.0, 0.68, 5.45, 0.1665, 0.008228 + 30000.0, 0.68, 5.5, 0.1691, 0.008404 + 30000.0, 0.68, 5.55, 0.1717, 0.008582 + 30000.0, 0.68, 5.6, 0.1743, 0.008761 + 30000.0, 0.68, 5.65, 0.1769, 0.00894 + 30000.0, 0.68, 5.7, 0.1795, 0.009119 + 30000.0, 0.68, 5.75, 0.182, 0.009298 + 30000.0, 0.68, 5.8, 0.1845, 0.009476 + 30000.0, 0.68, 5.85, 0.1871, 0.009654 + 30000.0, 0.68, 5.9, 0.1895, 0.00983 + 30000.0, 0.68, 5.95, 0.192, 0.01001 + 30000.0, 0.68, 6.0, 0.1945, 0.01018 + 30000.0, 0.68, 6.05, 0.1966, 0.01029 + 30000.0, 0.68, 6.1, 0.1987, 0.0104 + 30000.0, 0.68, 6.15, 0.2008, 0.0105 + 30000.0, 0.68, 6.2, 0.2028, 0.0106 + 30000.0, 0.68, 6.25, 0.2048, 0.0107 + 30000.0, 0.68, 6.3, 0.2068, 0.01079 + 30000.0, 0.68, 6.35, 0.2087, 0.01088 + 30000.0, 0.68, 6.4, 0.2106, 0.01096 + 30000.0, 0.68, 6.45, 0.2125, 0.01104 + 30000.0, 0.68, 6.5, 0.2143, 0.01111 + 30000.0, 0.68, 6.55, 0.2161, 0.01119 + 30000.0, 0.68, 6.6, 0.2179, 0.01125 + 30000.0, 0.68, 6.65, 0.2197, 0.01132 + 30000.0, 0.68, 6.7, 0.2214, 0.01138 + 30000.0, 0.68, 6.75, 0.2231, 0.01144 + 30000.0, 0.68, 6.8, 0.2248, 0.0115 + 30000.0, 0.68, 6.85, 0.2265, 0.01155 + 30000.0, 0.68, 6.9, 0.2282, 0.0116 + 30000.0, 0.68, 6.95, 0.2298, 0.01165 + 30000.0, 0.68, 7.0, 0.2314, 0.0117 + 30000.0, 0.68, 7.05, 0.233, 0.01174 + 30000.0, 0.68, 7.1, 0.2346, 0.01178 + 30000.0, 0.68, 7.15, 0.2361, 0.01182 + 30000.0, 0.68, 7.2, 0.2377, 0.01186 + 30000.0, 0.68, 7.25, 0.2392, 0.0119 + 30000.0, 0.68, 7.3, 0.2407, 0.01193 + 30000.0, 0.68, 7.35, 0.2422, 0.01197 + 30000.0, 0.68, 7.4, 0.2437, 0.012 + 30000.0, 0.68, 7.45, 0.2452, 0.01203 + 30000.0, 0.68, 7.5, 0.2467, 0.01206 + 30000.0, 0.68, 7.55, 0.2481, 0.01209 + 30000.0, 0.68, 7.6, 0.2496, 0.01212 + 30000.0, 0.68, 7.65, 0.251, 0.01214 + 30000.0, 0.68, 7.7, 0.2525, 0.01217 + 30000.0, 0.68, 7.75, 0.2539, 0.0122 + 30000.0, 0.68, 7.8, 0.2554, 0.01222 + 30000.0, 0.68, 7.85, 0.2568, 0.01225 + 30000.0, 0.68, 7.9, 0.2582, 0.01228 + 30000.0, 0.68, 7.95, 0.2597, 0.0123 + 30000.0, 0.68, 8.0, 0.2611, 0.01233 + 30000.0, 0.68, 8.05, 0.2628, 0.01239 + 30000.0, 0.68, 8.1, 0.2645, 0.01246 + 30000.0, 0.68, 8.15, 0.2662, 0.01252 + 30000.0, 0.68, 8.2, 0.2678, 0.01259 + 30000.0, 0.68, 8.25, 0.2695, 0.01265 + 30000.0, 0.68, 8.3, 0.2712, 0.01272 + 30000.0, 0.68, 8.35, 0.2729, 0.01278 + 30000.0, 0.68, 8.4, 0.2746, 0.01285 + 30000.0, 0.68, 8.45, 0.2763, 0.01292 + 30000.0, 0.68, 8.5, 0.278, 0.01298 + 30000.0, 0.68, 8.55, 0.2797, 0.01305 + 30000.0, 0.68, 8.6, 0.2814, 0.01312 + 30000.0, 0.68, 8.65, 0.2831, 0.01319 + 30000.0, 0.68, 8.7, 0.2848, 0.01325 + 30000.0, 0.68, 8.75, 0.2865, 0.01332 + 30000.0, 0.68, 8.8, 0.2882, 0.01339 + 30000.0, 0.68, 8.85, 0.2899, 0.01346 + 30000.0, 0.68, 8.9, 0.2916, 0.01353 + 30000.0, 0.68, 8.95, 0.2933, 0.0136 + 30000.0, 0.68, 9.0, 0.295, 0.01367 + 30000.0, 0.68, 9.05, 0.2967, 0.01374 + 30000.0, 0.68, 9.1, 0.2984, 0.01381 + 30000.0, 0.68, 9.15, 0.3001, 0.01388 + 30000.0, 0.68, 9.2, 0.3018, 0.01395 + 30000.0, 0.68, 9.25, 0.3036, 0.01402 + 30000.0, 0.68, 9.3, 0.3053, 0.01409 + 30000.0, 0.68, 9.35, 0.307, 0.01417 + 30000.0, 0.68, 9.4, 0.3087, 0.01424 + 30000.0, 0.68, 9.45, 0.3104, 0.01431 + 30000.0, 0.68, 9.5, 0.3121, 0.01438 + 30000.0, 0.68, 9.55, 0.3138, 0.01445 + 30000.0, 0.68, 9.6, 0.3155, 0.01453 + 30000.0, 0.68, 9.65, 0.3172, 0.0146 + 30000.0, 0.68, 9.7, 0.3189, 0.01467 + 30000.0, 0.68, 9.75, 0.3206, 0.01474 + 30000.0, 0.68, 9.8, 0.3223, 0.01482 + 30000.0, 0.68, 9.85, 0.3241, 0.01489 + 30000.0, 0.68, 9.9, 0.3258, 0.01496 + 30000.0, 0.68, 9.95, 0.3275, 0.01504 + 30000.0, 0.68, 10.0, 0.3292, 0.01511 + 30000.0, 0.68, 10.05, 0.3309, 0.01518 + 30000.0, 0.68, 10.1, 0.3326, 0.01525 + 30000.0, 0.68, 10.15, 0.3343, 0.01532 + 30000.0, 0.68, 10.2, 0.336, 0.01538 + 30000.0, 0.68, 10.25, 0.3377, 0.01545 + 30000.0, 0.68, 10.3, 0.3394, 0.01552 + 30000.0, 0.68, 10.35, 0.3411, 0.01559 + 30000.0, 0.68, 10.4, 0.3428, 0.01566 + 30000.0, 0.68, 10.45, 0.3445, 0.01573 + 30000.0, 0.68, 10.5, 0.3462, 0.0158 + 30000.0, 0.68, 10.55, 0.348, 0.01587 + 30000.0, 0.68, 10.6, 0.3497, 0.01594 + 30000.0, 0.68, 10.65, 0.3514, 0.01601 + 30000.0, 0.68, 10.7, 0.3531, 0.01608 + 30000.0, 0.68, 10.75, 0.3548, 0.01615 + 30000.0, 0.68, 10.8, 0.3565, 0.01622 + 30000.0, 0.68, 10.85, 0.3582, 0.0163 + 30000.0, 0.68, 10.9, 0.3599, 0.01637 + 30000.0, 0.68, 10.95, 0.3616, 0.01644 + 30000.0, 0.68, 11.0, 0.3633, 0.01651 + 30000.0, 0.68, 11.05, 0.365, 0.01659 + 30000.0, 0.68, 11.1, 0.3667, 0.01666 + 30000.0, 0.68, 11.15, 0.3684, 0.01674 + 30000.0, 0.68, 11.2, 0.3701, 0.01681 + 30000.0, 0.68, 11.25, 0.3718, 0.01689 + 30000.0, 0.68, 11.3, 0.3736, 0.01696 + 30000.0, 0.68, 11.35, 0.3753, 0.01704 + 30000.0, 0.68, 11.4, 0.377, 0.01711 + 30000.0, 0.68, 11.45, 0.3787, 0.01719 + 30000.0, 0.68, 11.5, 0.3804, 0.01727 + 30000.0, 0.68, 11.55, 0.3821, 0.01735 + 30000.0, 0.68, 11.6, 0.3838, 0.01743 + 30000.0, 0.68, 11.65, 0.3855, 0.01751 + 30000.0, 0.68, 11.7, 0.3872, 0.01759 + 30000.0, 0.68, 11.75, 0.3889, 0.01767 + 30000.0, 0.68, 11.8, 0.3906, 0.01775 + 30000.0, 0.68, 11.85, 0.3923, 0.01783 + 30000.0, 0.68, 11.9, 0.394, 0.01791 + 30000.0, 0.68, 11.95, 0.3957, 0.018 + 30000.0, 0.68, 12.0, 0.3974, 0.01808 + 30000.0, 0.68, 12.05, 0.3991, 0.01816 + 30000.0, 0.68, 12.1, 0.4008, 0.01825 + 30000.0, 0.68, 12.15, 0.4026, 0.01834 + 30000.0, 0.68, 12.2, 0.4043, 0.01842 + 30000.0, 0.68, 12.25, 0.406, 0.01851 + 30000.0, 0.68, 12.3, 0.4077, 0.0186 + 30000.0, 0.68, 12.35, 0.4094, 0.01869 + 30000.0, 0.68, 12.4, 0.4111, 0.01878 + 30000.0, 0.68, 12.45, 0.4128, 0.01887 + 30000.0, 0.68, 12.5, 0.4145, 0.01896 + 30000.0, 0.68, 12.55, 0.4162, 0.01905 + 30000.0, 0.68, 12.6, 0.4179, 0.01914 + 30000.0, 0.68, 12.65, 0.4196, 0.01924 + 30000.0, 0.68, 12.7, 0.4213, 0.01933 + 30000.0, 0.68, 12.75, 0.423, 0.01943 + 30000.0, 0.68, 12.8, 0.4247, 0.01953 + 30000.0, 0.68, 12.85, 0.4264, 0.01962 + 30000.0, 0.68, 12.9, 0.4281, 0.01972 + 30000.0, 0.68, 12.95, 0.4298, 0.01982 + 30000.0, 0.68, 13.0, 0.4315, 0.01992 + 30000.0, 0.68, 13.05, 0.4332, 0.02002 + 30000.0, 0.68, 13.1, 0.4349, 0.02013 + 30000.0, 0.68, 13.15, 0.4366, 0.02023 + 30000.0, 0.68, 13.2, 0.4383, 0.02033 + 30000.0, 0.68, 13.25, 0.44, 0.02044 + 30000.0, 0.68, 13.3, 0.4417, 0.02055 + 30000.0, 0.68, 13.35, 0.4434, 0.02065 + 30000.0, 0.68, 13.4, 0.4451, 0.02076 + 30000.0, 0.68, 13.45, 0.4468, 0.02087 + 30000.0, 0.68, 13.5, 0.4485, 0.02098 + 30000.0, 0.68, 13.55, 0.4502, 0.0211 + 30000.0, 0.68, 13.6, 0.4519, 0.02121 + 30000.0, 0.68, 13.65, 0.4536, 0.02132 + 30000.0, 0.68, 13.7, 0.4553, 0.02144 + 30000.0, 0.68, 13.75, 0.457, 0.02156 + 30000.0, 0.68, 13.8, 0.4587, 0.02167 + 30000.0, 0.68, 13.85, 0.4604, 0.02179 + 30000.0, 0.68, 13.9, 0.4621, 0.02191 + 30000.0, 0.68, 13.95, 0.4638, 0.02203 + 30000.0, 0.68, 14.0, 0.4655, 0.02216 + 30000.0, 0.68, 14.05, 0.4671, 0.02228 + 30000.0, 0.68, 14.1, 0.4688, 0.02241 + 30000.0, 0.68, 14.15, 0.4705, 0.02253 + 30000.0, 0.68, 14.2, 0.4722, 0.02266 + 30000.0, 0.68, 14.25, 0.4739, 0.02279 + 30000.0, 0.68, 14.3, 0.4756, 0.02292 + 30000.0, 0.68, 14.35, 0.4773, 0.02305 + 30000.0, 0.68, 14.4, 0.479, 0.02319 + 30000.0, 0.68, 14.45, 0.4807, 0.02332 + 30000.0, 0.68, 14.5, 0.4824, 0.02346 + 30000.0, 0.68, 14.55, 0.4841, 0.0236 + 30000.0, 0.68, 14.6, 0.4857, 0.02374 + 30000.0, 0.68, 14.65, 0.4874, 0.02388 + 30000.0, 0.68, 14.7, 0.4891, 0.02402 + 30000.0, 0.68, 14.75, 0.4908, 0.02416 + 30000.0, 0.68, 14.8, 0.4925, 0.02431 + 30000.0, 0.68, 14.85, 0.4942, 0.02445 + 30000.0, 0.68, 14.9, 0.4959, 0.0246 + 30000.0, 0.68, 14.95, 0.4976, 0.02475 + 30000.0, 0.68, 15.0, 0.4992, 0.0249 + 30000.0, 0.68, 15.05, 0.5009, 0.02505 + 30000.0, 0.73, 0.0, -0.1665, 0.009316 + 30000.0, 0.73, 0.05, -0.1631, 0.00926 + 30000.0, 0.73, 0.1, -0.1596, 0.0092 + 30000.0, 0.73, 0.15, -0.1562, 0.009137 + 30000.0, 0.73, 0.2, -0.1528, 0.00907 + 30000.0, 0.73, 0.25, -0.1494, 0.009001 + 30000.0, 0.73, 0.3, -0.146, 0.008929 + 30000.0, 0.73, 0.35, -0.1426, 0.008854 + 30000.0, 0.73, 0.4, -0.1392, 0.008776 + 30000.0, 0.73, 0.45, -0.1359, 0.008696 + 30000.0, 0.73, 0.5, -0.1325, 0.008613 + 30000.0, 0.73, 0.55, -0.1292, 0.008528 + 30000.0, 0.73, 0.6, -0.1258, 0.00844 + 30000.0, 0.73, 0.65, -0.1225, 0.008351 + 30000.0, 0.73, 0.7, -0.1192, 0.008259 + 30000.0, 0.73, 0.75, -0.1159, 0.008166 + 30000.0, 0.73, 0.8, -0.1126, 0.008071 + 30000.0, 0.73, 0.85, -0.1093, 0.007974 + 30000.0, 0.73, 0.9, -0.106, 0.007876 + 30000.0, 0.73, 0.95, -0.1027, 0.007776 + 30000.0, 0.73, 1.0, -0.09946, 0.007675 + 30000.0, 0.73, 1.05, -0.09619, 0.007573 + 30000.0, 0.73, 1.1, -0.09293, 0.007469 + 30000.0, 0.73, 1.15, -0.08968, 0.007365 + 30000.0, 0.73, 1.2, -0.08644, 0.00726 + 30000.0, 0.73, 1.25, -0.08319, 0.007155 + 30000.0, 0.73, 1.3, -0.07996, 0.007048 + 30000.0, 0.73, 1.35, -0.07673, 0.006941 + 30000.0, 0.73, 1.4, -0.0735, 0.006834 + 30000.0, 0.73, 1.45, -0.07028, 0.006727 + 30000.0, 0.73, 1.5, -0.06707, 0.006619 + 30000.0, 0.73, 1.55, -0.06385, 0.006512 + 30000.0, 0.73, 1.6, -0.06065, 0.006405 + 30000.0, 0.73, 1.65, -0.05744, 0.006297 + 30000.0, 0.73, 1.7, -0.05424, 0.006191 + 30000.0, 0.73, 1.75, -0.05104, 0.006084 + 30000.0, 0.73, 1.8, -0.04785, 0.005978 + 30000.0, 0.73, 1.85, -0.04466, 0.005873 + 30000.0, 0.73, 1.9, -0.04147, 0.005769 + 30000.0, 0.73, 1.95, -0.03828, 0.005666 + 30000.0, 0.73, 2.0, -0.03509, 0.005563 + 30000.0, 0.73, 2.05, -0.03191, 0.005462 + 30000.0, 0.73, 2.1, -0.02873, 0.005362 + 30000.0, 0.73, 2.15, -0.02554, 0.005264 + 30000.0, 0.73, 2.2, -0.02236, 0.005167 + 30000.0, 0.73, 2.25, -0.01918, 0.005072 + 30000.0, 0.73, 2.3, -0.016, 0.004978 + 30000.0, 0.73, 2.35, -0.01282, 0.004886 + 30000.0, 0.73, 2.4, -0.009643, 0.004797 + 30000.0, 0.73, 2.45, -0.006462, 0.004709 + 30000.0, 0.73, 2.5, -0.003281, 0.004624 + 30000.0, 0.73, 2.55, -9.861e-05, 0.00454 + 30000.0, 0.73, 2.6, 0.003085, 0.00446 + 30000.0, 0.73, 2.65, 0.00627, 0.004382 + 30000.0, 0.73, 2.7, 0.009456, 0.004306 + 30000.0, 0.73, 2.75, 0.01264, 0.004234 + 30000.0, 0.73, 2.8, 0.01584, 0.004164 + 30000.0, 0.73, 2.85, 0.01903, 0.004098 + 30000.0, 0.73, 2.9, 0.02222, 0.004034 + 30000.0, 0.73, 2.95, 0.02542, 0.003974 + 30000.0, 0.73, 3.0, 0.02863, 0.003917 + 30000.0, 0.73, 3.05, 0.03183, 0.003864 + 30000.0, 0.73, 3.1, 0.03504, 0.003814 + 30000.0, 0.73, 3.15, 0.03826, 0.003768 + 30000.0, 0.73, 3.2, 0.04147, 0.003726 + 30000.0, 0.73, 3.25, 0.0447, 0.003688 + 30000.0, 0.73, 3.3, 0.04792, 0.003654 + 30000.0, 0.73, 3.35, 0.05116, 0.003624 + 30000.0, 0.73, 3.4, 0.05439, 0.003598 + 30000.0, 0.73, 3.45, 0.05764, 0.003577 + 30000.0, 0.73, 3.5, 0.06089, 0.003561 + 30000.0, 0.73, 3.55, 0.06414, 0.003549 + 30000.0, 0.73, 3.6, 0.0674, 0.003542 + 30000.0, 0.73, 3.65, 0.07067, 0.00354 + 30000.0, 0.73, 3.7, 0.07395, 0.003543 + 30000.0, 0.73, 3.75, 0.07723, 0.003551 + 30000.0, 0.73, 3.8, 0.08052, 0.003564 + 30000.0, 0.73, 3.85, 0.08381, 0.003582 + 30000.0, 0.73, 3.9, 0.08712, 0.003607 + 30000.0, 0.73, 3.95, 0.09043, 0.003636 + 30000.0, 0.73, 4.0, 0.09375, 0.003672 + 30000.0, 0.73, 4.05, 0.09715, 0.003718 + 30000.0, 0.73, 4.1, 0.1006, 0.00377 + 30000.0, 0.73, 4.15, 0.104, 0.003827 + 30000.0, 0.73, 4.2, 0.1074, 0.00389 + 30000.0, 0.73, 4.25, 0.1108, 0.00396 + 30000.0, 0.73, 4.3, 0.1142, 0.004035 + 30000.0, 0.73, 4.35, 0.1176, 0.004116 + 30000.0, 0.73, 4.4, 0.1211, 0.004204 + 30000.0, 0.73, 4.45, 0.1245, 0.004297 + 30000.0, 0.73, 4.5, 0.1279, 0.004397 + 30000.0, 0.73, 4.55, 0.1314, 0.004504 + 30000.0, 0.73, 4.6, 0.1348, 0.004617 + 30000.0, 0.73, 4.65, 0.1382, 0.004736 + 30000.0, 0.73, 4.7, 0.1417, 0.004862 + 30000.0, 0.73, 4.75, 0.1451, 0.004995 + 30000.0, 0.73, 4.8, 0.1486, 0.005135 + 30000.0, 0.73, 4.85, 0.152, 0.005281 + 30000.0, 0.73, 4.9, 0.1555, 0.005435 + 30000.0, 0.73, 4.95, 0.1589, 0.005595 + 30000.0, 0.73, 5.0, 0.1623, 0.005763 + 30000.0, 0.73, 5.05, 0.166, 0.005959 + 30000.0, 0.73, 5.1, 0.1696, 0.006163 + 30000.0, 0.73, 5.15, 0.1732, 0.006373 + 30000.0, 0.73, 5.2, 0.1767, 0.00659 + 30000.0, 0.73, 5.25, 0.1803, 0.006813 + 30000.0, 0.73, 5.3, 0.1839, 0.007041 + 30000.0, 0.73, 5.35, 0.1874, 0.007276 + 30000.0, 0.73, 5.4, 0.191, 0.007516 + 30000.0, 0.73, 5.45, 0.1945, 0.007761 + 30000.0, 0.73, 5.5, 0.198, 0.008011 + 30000.0, 0.73, 5.55, 0.2014, 0.008266 + 30000.0, 0.73, 5.6, 0.2049, 0.008526 + 30000.0, 0.73, 5.65, 0.2083, 0.008789 + 30000.0, 0.73, 5.7, 0.2116, 0.009057 + 30000.0, 0.73, 5.75, 0.215, 0.009328 + 30000.0, 0.73, 5.8, 0.2183, 0.009603 + 30000.0, 0.73, 5.85, 0.2215, 0.009881 + 30000.0, 0.73, 5.9, 0.2247, 0.01016 + 30000.0, 0.73, 5.95, 0.2279, 0.01045 + 30000.0, 0.73, 6.0, 0.231, 0.01073 + 30000.0, 0.73, 6.05, 0.2334, 0.01098 + 30000.0, 0.73, 6.1, 0.2357, 0.01123 + 30000.0, 0.73, 6.15, 0.2379, 0.01148 + 30000.0, 0.73, 6.2, 0.2401, 0.01173 + 30000.0, 0.73, 6.25, 0.2421, 0.01198 + 30000.0, 0.73, 6.3, 0.2441, 0.01223 + 30000.0, 0.73, 6.35, 0.2461, 0.01249 + 30000.0, 0.73, 6.4, 0.2479, 0.01274 + 30000.0, 0.73, 6.45, 0.2497, 0.01299 + 30000.0, 0.73, 6.5, 0.2514, 0.01325 + 30000.0, 0.73, 6.55, 0.2531, 0.0135 + 30000.0, 0.73, 6.6, 0.2547, 0.01376 + 30000.0, 0.73, 6.65, 0.2563, 0.01401 + 30000.0, 0.73, 6.7, 0.2577, 0.01427 + 30000.0, 0.73, 6.75, 0.2592, 0.01453 + 30000.0, 0.73, 6.8, 0.2605, 0.01479 + 30000.0, 0.73, 6.85, 0.2619, 0.01505 + 30000.0, 0.73, 6.9, 0.2631, 0.01531 + 30000.0, 0.73, 6.95, 0.2644, 0.01557 + 30000.0, 0.73, 7.0, 0.2655, 0.01583 + 30000.0, 0.73, 7.05, 0.2667, 0.0161 + 30000.0, 0.73, 7.1, 0.2678, 0.01636 + 30000.0, 0.73, 7.15, 0.2688, 0.01663 + 30000.0, 0.73, 7.2, 0.2699, 0.0169 + 30000.0, 0.73, 7.25, 0.2708, 0.01717 + 30000.0, 0.73, 7.3, 0.2718, 0.01744 + 30000.0, 0.73, 7.35, 0.2727, 0.01771 + 30000.0, 0.73, 7.4, 0.2736, 0.01798 + 30000.0, 0.73, 7.45, 0.2745, 0.01826 + 30000.0, 0.73, 7.5, 0.2753, 0.01854 + 30000.0, 0.73, 7.55, 0.2762, 0.01881 + 30000.0, 0.73, 7.6, 0.277, 0.01909 + 30000.0, 0.73, 7.65, 0.2777, 0.01938 + 30000.0, 0.73, 7.7, 0.2785, 0.01966 + 30000.0, 0.73, 7.75, 0.2793, 0.01994 + 30000.0, 0.73, 7.8, 0.28, 0.02023 + 30000.0, 0.73, 7.85, 0.2808, 0.02052 + 30000.0, 0.73, 7.9, 0.2815, 0.02081 + 30000.0, 0.73, 7.95, 0.2822, 0.0211 + 30000.0, 0.73, 8.0, 0.2829, 0.02139 + 30000.0, 0.73, 8.05, 0.2842, 0.02171 + 30000.0, 0.73, 8.1, 0.2855, 0.02202 + 30000.0, 0.73, 8.15, 0.2868, 0.02234 + 30000.0, 0.73, 8.2, 0.288, 0.02265 + 30000.0, 0.73, 8.25, 0.2893, 0.02297 + 30000.0, 0.73, 8.3, 0.2906, 0.0233 + 30000.0, 0.73, 8.35, 0.2918, 0.02362 + 30000.0, 0.73, 8.4, 0.2931, 0.02394 + 30000.0, 0.73, 8.45, 0.2944, 0.02427 + 30000.0, 0.73, 8.5, 0.2956, 0.0246 + 30000.0, 0.73, 8.55, 0.2969, 0.02493 + 30000.0, 0.73, 8.6, 0.2982, 0.02526 + 30000.0, 0.73, 8.65, 0.2994, 0.0256 + 30000.0, 0.73, 8.7, 0.3007, 0.02593 + 30000.0, 0.73, 8.75, 0.302, 0.02627 + 30000.0, 0.73, 8.8, 0.3032, 0.02661 + 30000.0, 0.73, 8.85, 0.3045, 0.02695 + 30000.0, 0.73, 8.9, 0.3058, 0.02729 + 30000.0, 0.73, 8.95, 0.307, 0.02764 + 30000.0, 0.73, 9.0, 0.3083, 0.02798 + 30000.0, 0.73, 9.05, 0.3096, 0.02833 + 30000.0, 0.73, 9.1, 0.3108, 0.02868 + 30000.0, 0.73, 9.15, 0.3121, 0.02903 + 30000.0, 0.73, 9.2, 0.3133, 0.02938 + 30000.0, 0.73, 9.25, 0.3146, 0.02973 + 30000.0, 0.73, 9.3, 0.3159, 0.03009 + 30000.0, 0.73, 9.35, 0.3171, 0.03045 + 30000.0, 0.73, 9.4, 0.3184, 0.0308 + 30000.0, 0.73, 9.45, 0.3196, 0.03116 + 30000.0, 0.73, 9.5, 0.3209, 0.03152 + 30000.0, 0.73, 9.55, 0.3221, 0.03188 + 30000.0, 0.73, 9.6, 0.3234, 0.03225 + 30000.0, 0.73, 9.65, 0.3247, 0.03261 + 30000.0, 0.73, 9.7, 0.3259, 0.03298 + 30000.0, 0.73, 9.75, 0.3272, 0.03335 + 30000.0, 0.73, 9.8, 0.3284, 0.03371 + 30000.0, 0.73, 9.85, 0.3297, 0.03408 + 30000.0, 0.73, 9.9, 0.3309, 0.03445 + 30000.0, 0.73, 9.95, 0.3322, 0.03483 + 30000.0, 0.73, 10.0, 0.3335, 0.0352 + 30000.0, 0.73, 10.05, 0.3347, 0.03559 + 30000.0, 0.73, 10.1, 0.336, 0.03597 + 30000.0, 0.73, 10.15, 0.3372, 0.03636 + 30000.0, 0.73, 10.2, 0.3385, 0.03675 + 30000.0, 0.73, 10.25, 0.3398, 0.03714 + 30000.0, 0.73, 10.3, 0.341, 0.03753 + 30000.0, 0.73, 10.35, 0.3423, 0.03792 + 30000.0, 0.73, 10.4, 0.3435, 0.03831 + 30000.0, 0.73, 10.45, 0.3448, 0.03871 + 30000.0, 0.73, 10.5, 0.346, 0.0391 + 30000.0, 0.73, 10.55, 0.3473, 0.03949 + 30000.0, 0.73, 10.6, 0.3486, 0.03989 + 30000.0, 0.73, 10.65, 0.3498, 0.04028 + 30000.0, 0.73, 10.7, 0.3511, 0.04068 + 30000.0, 0.73, 10.75, 0.3523, 0.04107 + 30000.0, 0.73, 10.8, 0.3536, 0.04147 + 30000.0, 0.73, 10.85, 0.3549, 0.04187 + 30000.0, 0.73, 10.9, 0.3561, 0.04226 + 30000.0, 0.73, 10.95, 0.3574, 0.04266 + 30000.0, 0.73, 11.0, 0.3586, 0.04305 + 30000.0, 0.73, 11.05, 0.3599, 0.04345 + 30000.0, 0.73, 11.1, 0.3612, 0.04385 + 30000.0, 0.73, 11.15, 0.3624, 0.04424 + 30000.0, 0.73, 11.2, 0.3637, 0.04464 + 30000.0, 0.73, 11.25, 0.3649, 0.04503 + 30000.0, 0.73, 11.3, 0.3662, 0.04543 + 30000.0, 0.73, 11.35, 0.3674, 0.04582 + 30000.0, 0.73, 11.4, 0.3687, 0.04622 + 30000.0, 0.73, 11.45, 0.37, 0.04661 + 30000.0, 0.73, 11.5, 0.3712, 0.04701 + 30000.0, 0.73, 11.55, 0.3725, 0.0474 + 30000.0, 0.73, 11.6, 0.3737, 0.04779 + 30000.0, 0.73, 11.65, 0.375, 0.04818 + 30000.0, 0.73, 11.7, 0.3763, 0.04857 + 30000.0, 0.73, 11.75, 0.3775, 0.04896 + 30000.0, 0.73, 11.8, 0.3788, 0.04935 + 30000.0, 0.73, 11.85, 0.38, 0.04974 + 30000.0, 0.73, 11.9, 0.3813, 0.05012 + 30000.0, 0.73, 11.95, 0.3826, 0.05051 + 30000.0, 0.73, 12.0, 0.3838, 0.05089 + 30000.0, 0.73, 12.05, 0.3851, 0.05127 + 30000.0, 0.73, 12.1, 0.3863, 0.05166 + 30000.0, 0.73, 12.15, 0.3876, 0.05204 + 30000.0, 0.73, 12.2, 0.3889, 0.05241 + 30000.0, 0.73, 12.25, 0.3901, 0.05279 + 30000.0, 0.73, 12.3, 0.3914, 0.05317 + 30000.0, 0.73, 12.35, 0.3926, 0.05354 + 30000.0, 0.73, 12.4, 0.3939, 0.05391 + 30000.0, 0.73, 12.45, 0.3952, 0.05428 + 30000.0, 0.73, 12.5, 0.3964, 0.05465 + 30000.0, 0.73, 12.55, 0.3977, 0.05502 + 30000.0, 0.73, 12.6, 0.3989, 0.05538 + 30000.0, 0.73, 12.65, 0.4002, 0.05575 + 30000.0, 0.73, 12.7, 0.4015, 0.05611 + 30000.0, 0.73, 12.75, 0.4027, 0.05646 + 30000.0, 0.73, 12.8, 0.404, 0.05682 + 30000.0, 0.73, 12.85, 0.4053, 0.05718 + 30000.0, 0.73, 12.9, 0.4065, 0.05753 + 30000.0, 0.73, 12.95, 0.4078, 0.05788 + 30000.0, 0.73, 13.0, 0.4091, 0.05822 + 30000.0, 0.73, 13.05, 0.4103, 0.05857 + 30000.0, 0.73, 13.1, 0.4116, 0.05891 + 30000.0, 0.73, 13.15, 0.4128, 0.05925 + 30000.0, 0.73, 13.2, 0.4141, 0.05959 + 30000.0, 0.73, 13.25, 0.4154, 0.05992 + 30000.0, 0.73, 13.3, 0.4166, 0.06025 + 30000.0, 0.73, 13.35, 0.4179, 0.06058 + 30000.0, 0.73, 13.4, 0.4192, 0.06091 + 30000.0, 0.73, 13.45, 0.4204, 0.06123 + 30000.0, 0.73, 13.5, 0.4217, 0.06155 + 30000.0, 0.73, 13.55, 0.423, 0.06186 + 30000.0, 0.73, 13.6, 0.4242, 0.06218 + 30000.0, 0.73, 13.65, 0.4255, 0.06249 + 30000.0, 0.73, 13.7, 0.4268, 0.06279 + 30000.0, 0.73, 13.75, 0.428, 0.0631 + 30000.0, 0.73, 13.8, 0.4293, 0.0634 + 30000.0, 0.73, 13.85, 0.4306, 0.06369 + 30000.0, 0.73, 13.9, 0.4318, 0.06399 + 30000.0, 0.73, 13.95, 0.4331, 0.06428 + 30000.0, 0.73, 14.0, 0.4344, 0.06456 + 30000.0, 0.73, 14.05, 0.4357, 0.06484 + 30000.0, 0.73, 14.1, 0.4369, 0.06512 + 30000.0, 0.73, 14.15, 0.4382, 0.0654 + 30000.0, 0.73, 14.2, 0.4395, 0.06567 + 30000.0, 0.73, 14.25, 0.4407, 0.06593 + 30000.0, 0.73, 14.3, 0.442, 0.0662 + 30000.0, 0.73, 14.35, 0.4433, 0.06645 + 30000.0, 0.73, 14.4, 0.4445, 0.06671 + 30000.0, 0.73, 14.45, 0.4458, 0.06696 + 30000.0, 0.73, 14.5, 0.4471, 0.06721 + 30000.0, 0.73, 14.55, 0.4484, 0.06745 + 30000.0, 0.73, 14.6, 0.4496, 0.06768 + 30000.0, 0.73, 14.65, 0.4509, 0.06792 + 30000.0, 0.73, 14.7, 0.4522, 0.06815 + 30000.0, 0.73, 14.75, 0.4535, 0.06837 + 30000.0, 0.73, 14.8, 0.4547, 0.06859 + 30000.0, 0.73, 14.85, 0.456, 0.0688 + 30000.0, 0.73, 14.9, 0.4573, 0.06901 + 30000.0, 0.73, 14.95, 0.4586, 0.06922 + 30000.0, 0.73, 15.0, 0.4598, 0.06942 + 30000.0, 0.73, 15.05, 0.4611, 0.06961 + 30000.0, 0.78, 0.0, -0.1839, 0.009891 + 30000.0, 0.78, 0.05, -0.1801, 0.009843 + 30000.0, 0.78, 0.1, -0.1763, 0.00979 + 30000.0, 0.78, 0.15, -0.1726, 0.009734 + 30000.0, 0.78, 0.2, -0.1688, 0.009675 + 30000.0, 0.78, 0.25, -0.1651, 0.009612 + 30000.0, 0.78, 0.3, -0.1614, 0.009546 + 30000.0, 0.78, 0.35, -0.1577, 0.009477 + 30000.0, 0.78, 0.4, -0.154, 0.009404 + 30000.0, 0.78, 0.45, -0.1503, 0.009329 + 30000.0, 0.78, 0.5, -0.1466, 0.009251 + 30000.0, 0.78, 0.55, -0.1429, 0.00917 + 30000.0, 0.78, 0.6, -0.1392, 0.009087 + 30000.0, 0.78, 0.65, -0.1356, 0.009001 + 30000.0, 0.78, 0.7, -0.1319, 0.008914 + 30000.0, 0.78, 0.75, -0.1282, 0.008824 + 30000.0, 0.78, 0.8, -0.1246, 0.008731 + 30000.0, 0.78, 0.85, -0.1209, 0.008637 + 30000.0, 0.78, 0.9, -0.1173, 0.008542 + 30000.0, 0.78, 0.95, -0.1137, 0.008444 + 30000.0, 0.78, 1.0, -0.11, 0.008346 + 30000.0, 0.78, 1.05, -0.1064, 0.008245 + 30000.0, 0.78, 1.1, -0.1028, 0.008144 + 30000.0, 0.78, 1.15, -0.0992, 0.008041 + 30000.0, 0.78, 1.2, -0.0956, 0.007937 + 30000.0, 0.78, 1.25, -0.092, 0.007833 + 30000.0, 0.78, 1.3, -0.0884, 0.007728 + 30000.0, 0.78, 1.35, -0.08481, 0.007622 + 30000.0, 0.78, 1.4, -0.08122, 0.007515 + 30000.0, 0.78, 1.45, -0.07764, 0.007409 + 30000.0, 0.78, 1.5, -0.07406, 0.007301 + 30000.0, 0.78, 1.55, -0.07049, 0.007194 + 30000.0, 0.78, 1.6, -0.06691, 0.007087 + 30000.0, 0.78, 1.65, -0.06334, 0.00698 + 30000.0, 0.78, 1.7, -0.05978, 0.006874 + 30000.0, 0.78, 1.75, -0.05621, 0.006767 + 30000.0, 0.78, 1.8, -0.05265, 0.006662 + 30000.0, 0.78, 1.85, -0.04909, 0.006556 + 30000.0, 0.78, 1.9, -0.04554, 0.006452 + 30000.0, 0.78, 1.95, -0.04198, 0.006349 + 30000.0, 0.78, 2.0, -0.03843, 0.006246 + 30000.0, 0.78, 2.05, -0.03488, 0.006145 + 30000.0, 0.78, 2.1, -0.03133, 0.006045 + 30000.0, 0.78, 2.15, -0.02778, 0.005946 + 30000.0, 0.78, 2.2, -0.02423, 0.005849 + 30000.0, 0.78, 2.25, -0.02069, 0.005754 + 30000.0, 0.78, 2.3, -0.01714, 0.00566 + 30000.0, 0.78, 2.35, -0.01359, 0.005569 + 30000.0, 0.78, 2.4, -0.01005, 0.005479 + 30000.0, 0.78, 2.45, -0.006503, 0.005392 + 30000.0, 0.78, 2.5, -0.002957, 0.005307 + 30000.0, 0.78, 2.55, 0.0005893, 0.005224 + 30000.0, 0.78, 2.6, 0.004136, 0.005144 + 30000.0, 0.78, 2.65, 0.007683, 0.005067 + 30000.0, 0.78, 2.7, 0.01123, 0.004992 + 30000.0, 0.78, 2.75, 0.01478, 0.00492 + 30000.0, 0.78, 2.8, 0.01833, 0.004852 + 30000.0, 0.78, 2.85, 0.02188, 0.004786 + 30000.0, 0.78, 2.9, 0.02544, 0.004724 + 30000.0, 0.78, 2.95, 0.029, 0.004666 + 30000.0, 0.78, 3.0, 0.03255, 0.00461 + 30000.0, 0.78, 3.05, 0.03611, 0.004559 + 30000.0, 0.78, 3.1, 0.03968, 0.004512 + 30000.0, 0.78, 3.15, 0.04324, 0.004468 + 30000.0, 0.78, 3.2, 0.04681, 0.004429 + 30000.0, 0.78, 3.25, 0.05038, 0.004393 + 30000.0, 0.78, 3.3, 0.05396, 0.004362 + 30000.0, 0.78, 3.35, 0.05754, 0.004336 + 30000.0, 0.78, 3.4, 0.06112, 0.004314 + 30000.0, 0.78, 3.45, 0.06471, 0.004297 + 30000.0, 0.78, 3.5, 0.0683, 0.004284 + 30000.0, 0.78, 3.55, 0.07189, 0.004277 + 30000.0, 0.78, 3.6, 0.07549, 0.004275 + 30000.0, 0.78, 3.65, 0.07909, 0.004278 + 30000.0, 0.78, 3.7, 0.0827, 0.004286 + 30000.0, 0.78, 3.75, 0.08632, 0.0043 + 30000.0, 0.78, 3.8, 0.08994, 0.004319 + 30000.0, 0.78, 3.85, 0.09356, 0.004345 + 30000.0, 0.78, 3.9, 0.09719, 0.004376 + 30000.0, 0.78, 3.95, 0.1008, 0.004413 + 30000.0, 0.78, 4.0, 0.1045, 0.004456 + 30000.0, 0.78, 4.05, 0.1082, 0.004515 + 30000.0, 0.78, 4.1, 0.1119, 0.004581 + 30000.0, 0.78, 4.15, 0.1156, 0.004652 + 30000.0, 0.78, 4.2, 0.1193, 0.004729 + 30000.0, 0.78, 4.25, 0.123, 0.004812 + 30000.0, 0.78, 4.3, 0.1267, 0.004901 + 30000.0, 0.78, 4.35, 0.1304, 0.004996 + 30000.0, 0.78, 4.4, 0.1341, 0.005097 + 30000.0, 0.78, 4.45, 0.1379, 0.005204 + 30000.0, 0.78, 4.5, 0.1416, 0.005317 + 30000.0, 0.78, 4.55, 0.1453, 0.005437 + 30000.0, 0.78, 4.6, 0.149, 0.005563 + 30000.0, 0.78, 4.65, 0.1528, 0.005695 + 30000.0, 0.78, 4.7, 0.1565, 0.005833 + 30000.0, 0.78, 4.75, 0.1602, 0.005978 + 30000.0, 0.78, 4.8, 0.1639, 0.006129 + 30000.0, 0.78, 4.85, 0.1677, 0.006287 + 30000.0, 0.78, 4.9, 0.1714, 0.006451 + 30000.0, 0.78, 4.95, 0.1751, 0.006622 + 30000.0, 0.78, 5.0, 0.1789, 0.0068 + 30000.0, 0.78, 5.05, 0.1828, 0.007 + 30000.0, 0.78, 5.1, 0.1867, 0.007207 + 30000.0, 0.78, 5.15, 0.1906, 0.00742 + 30000.0, 0.78, 5.2, 0.1945, 0.00764 + 30000.0, 0.78, 5.25, 0.1983, 0.007865 + 30000.0, 0.78, 5.3, 0.2022, 0.008096 + 30000.0, 0.78, 5.35, 0.2061, 0.008333 + 30000.0, 0.78, 5.4, 0.2099, 0.008574 + 30000.0, 0.78, 5.45, 0.2137, 0.008821 + 30000.0, 0.78, 5.5, 0.2175, 0.009073 + 30000.0, 0.78, 5.55, 0.2212, 0.00933 + 30000.0, 0.78, 5.6, 0.2249, 0.009591 + 30000.0, 0.78, 5.65, 0.2286, 0.009857 + 30000.0, 0.78, 5.7, 0.2323, 0.01013 + 30000.0, 0.78, 5.75, 0.2359, 0.0104 + 30000.0, 0.78, 5.8, 0.2395, 0.01068 + 30000.0, 0.78, 5.85, 0.243, 0.01096 + 30000.0, 0.78, 5.9, 0.2465, 0.01124 + 30000.0, 0.78, 5.95, 0.2499, 0.01153 + 30000.0, 0.78, 6.0, 0.2533, 0.01182 + 30000.0, 0.78, 6.05, 0.2559, 0.01209 + 30000.0, 0.78, 6.1, 0.2585, 0.01236 + 30000.0, 0.78, 6.15, 0.261, 0.01262 + 30000.0, 0.78, 6.2, 0.2634, 0.0129 + 30000.0, 0.78, 6.25, 0.2657, 0.01317 + 30000.0, 0.78, 6.3, 0.2679, 0.01344 + 30000.0, 0.78, 6.35, 0.2701, 0.01371 + 30000.0, 0.78, 6.4, 0.2722, 0.01399 + 30000.0, 0.78, 6.45, 0.2742, 0.01427 + 30000.0, 0.78, 6.5, 0.2761, 0.01455 + 30000.0, 0.78, 6.55, 0.278, 0.01483 + 30000.0, 0.78, 6.6, 0.2798, 0.01511 + 30000.0, 0.78, 6.65, 0.2816, 0.0154 + 30000.0, 0.78, 6.7, 0.2833, 0.01568 + 30000.0, 0.78, 6.75, 0.2849, 0.01597 + 30000.0, 0.78, 6.8, 0.2865, 0.01626 + 30000.0, 0.78, 6.85, 0.288, 0.01655 + 30000.0, 0.78, 6.9, 0.2895, 0.01684 + 30000.0, 0.78, 6.95, 0.2909, 0.01714 + 30000.0, 0.78, 7.0, 0.2923, 0.01743 + 30000.0, 0.78, 7.05, 0.2937, 0.01773 + 30000.0, 0.78, 7.1, 0.2949, 0.01803 + 30000.0, 0.78, 7.15, 0.2962, 0.01833 + 30000.0, 0.78, 7.2, 0.2974, 0.01863 + 30000.0, 0.78, 7.25, 0.2986, 0.01894 + 30000.0, 0.78, 7.3, 0.2997, 0.01924 + 30000.0, 0.78, 7.35, 0.3009, 0.01955 + 30000.0, 0.78, 7.4, 0.3019, 0.01986 + 30000.0, 0.78, 7.45, 0.303, 0.02017 + 30000.0, 0.78, 7.5, 0.304, 0.02049 + 30000.0, 0.78, 7.55, 0.305, 0.0208 + 30000.0, 0.78, 7.6, 0.306, 0.02112 + 30000.0, 0.78, 7.65, 0.307, 0.02144 + 30000.0, 0.78, 7.7, 0.308, 0.02176 + 30000.0, 0.78, 7.75, 0.3089, 0.02209 + 30000.0, 0.78, 7.8, 0.3098, 0.02241 + 30000.0, 0.78, 7.85, 0.3108, 0.02274 + 30000.0, 0.78, 7.9, 0.3117, 0.02307 + 30000.0, 0.78, 7.95, 0.3126, 0.0234 + 30000.0, 0.78, 8.0, 0.3135, 0.02373 + 30000.0, 0.78, 8.05, 0.315, 0.02408 + 30000.0, 0.78, 8.1, 0.3165, 0.02442 + 30000.0, 0.78, 8.15, 0.3179, 0.02477 + 30000.0, 0.78, 8.2, 0.3194, 0.02512 + 30000.0, 0.78, 8.25, 0.3209, 0.02547 + 30000.0, 0.78, 8.3, 0.3224, 0.02583 + 30000.0, 0.78, 8.35, 0.3239, 0.02618 + 30000.0, 0.78, 8.4, 0.3253, 0.02654 + 30000.0, 0.78, 8.45, 0.3268, 0.0269 + 30000.0, 0.78, 8.5, 0.3283, 0.02726 + 30000.0, 0.78, 8.55, 0.3298, 0.02763 + 30000.0, 0.78, 8.6, 0.3313, 0.02799 + 30000.0, 0.78, 8.65, 0.3327, 0.02836 + 30000.0, 0.78, 8.7, 0.3342, 0.02873 + 30000.0, 0.78, 8.75, 0.3357, 0.0291 + 30000.0, 0.78, 8.8, 0.3372, 0.02947 + 30000.0, 0.78, 8.85, 0.3386, 0.02984 + 30000.0, 0.78, 8.9, 0.3401, 0.03022 + 30000.0, 0.78, 8.95, 0.3416, 0.0306 + 30000.0, 0.78, 9.0, 0.3431, 0.03097 + 30000.0, 0.78, 9.05, 0.3445, 0.03135 + 30000.0, 0.78, 9.1, 0.346, 0.03174 + 30000.0, 0.78, 9.15, 0.3475, 0.03212 + 30000.0, 0.78, 9.2, 0.3489, 0.0325 + 30000.0, 0.78, 9.25, 0.3504, 0.03289 + 30000.0, 0.78, 9.3, 0.3519, 0.03328 + 30000.0, 0.78, 9.35, 0.3534, 0.03367 + 30000.0, 0.78, 9.4, 0.3548, 0.03406 + 30000.0, 0.78, 9.45, 0.3563, 0.03445 + 30000.0, 0.78, 9.5, 0.3578, 0.03484 + 30000.0, 0.78, 9.55, 0.3592, 0.03524 + 30000.0, 0.78, 9.6, 0.3607, 0.03563 + 30000.0, 0.78, 9.65, 0.3622, 0.03603 + 30000.0, 0.78, 9.7, 0.3636, 0.03643 + 30000.0, 0.78, 9.75, 0.3651, 0.03683 + 30000.0, 0.78, 9.8, 0.3666, 0.03723 + 30000.0, 0.78, 9.85, 0.368, 0.03763 + 30000.0, 0.78, 9.9, 0.3695, 0.03804 + 30000.0, 0.78, 9.95, 0.371, 0.03844 + 30000.0, 0.78, 10.0, 0.3725, 0.03885 + 30000.0, 0.78, 10.05, 0.3739, 0.03926 + 30000.0, 0.78, 10.1, 0.3754, 0.03968 + 30000.0, 0.78, 10.15, 0.3769, 0.04011 + 30000.0, 0.78, 10.2, 0.3783, 0.04053 + 30000.0, 0.78, 10.25, 0.3798, 0.04095 + 30000.0, 0.78, 10.3, 0.3813, 0.04137 + 30000.0, 0.78, 10.35, 0.3827, 0.0418 + 30000.0, 0.78, 10.4, 0.3842, 0.04222 + 30000.0, 0.78, 10.45, 0.3857, 0.04265 + 30000.0, 0.78, 10.5, 0.3872, 0.04307 + 30000.0, 0.78, 10.55, 0.3886, 0.0435 + 30000.0, 0.78, 10.6, 0.3901, 0.04393 + 30000.0, 0.78, 10.65, 0.3916, 0.04436 + 30000.0, 0.78, 10.7, 0.393, 0.04478 + 30000.0, 0.78, 10.75, 0.3945, 0.04521 + 30000.0, 0.78, 10.8, 0.396, 0.04564 + 30000.0, 0.78, 10.85, 0.3974, 0.04607 + 30000.0, 0.78, 10.9, 0.3989, 0.0465 + 30000.0, 0.78, 10.95, 0.4004, 0.04692 + 30000.0, 0.78, 11.0, 0.4019, 0.04735 + 30000.0, 0.78, 11.05, 0.4033, 0.04778 + 30000.0, 0.78, 11.1, 0.4048, 0.04821 + 30000.0, 0.78, 11.15, 0.4063, 0.04863 + 30000.0, 0.78, 11.2, 0.4077, 0.04906 + 30000.0, 0.78, 11.25, 0.4092, 0.04949 + 30000.0, 0.78, 11.3, 0.4107, 0.04991 + 30000.0, 0.78, 11.35, 0.4121, 0.05034 + 30000.0, 0.78, 11.4, 0.4136, 0.05076 + 30000.0, 0.78, 11.45, 0.4151, 0.05119 + 30000.0, 0.78, 11.5, 0.4166, 0.05161 + 30000.0, 0.78, 11.55, 0.418, 0.05203 + 30000.0, 0.78, 11.6, 0.4195, 0.05245 + 30000.0, 0.78, 11.65, 0.421, 0.05288 + 30000.0, 0.78, 11.7, 0.4224, 0.05329 + 30000.0, 0.78, 11.75, 0.4239, 0.05371 + 30000.0, 0.78, 11.8, 0.4254, 0.05413 + 30000.0, 0.78, 11.85, 0.4269, 0.05455 + 30000.0, 0.78, 11.9, 0.4283, 0.05496 + 30000.0, 0.78, 11.95, 0.4298, 0.05538 + 30000.0, 0.78, 12.0, 0.4313, 0.05579 + 30000.0, 0.78, 12.05, 0.4327, 0.0562 + 30000.0, 0.78, 12.1, 0.4342, 0.05661 + 30000.0, 0.78, 12.15, 0.4357, 0.05701 + 30000.0, 0.78, 12.2, 0.4372, 0.05742 + 30000.0, 0.78, 12.25, 0.4386, 0.05782 + 30000.0, 0.78, 12.3, 0.4401, 0.05823 + 30000.0, 0.78, 12.35, 0.4416, 0.05863 + 30000.0, 0.78, 12.4, 0.443, 0.05902 + 30000.0, 0.78, 12.45, 0.4445, 0.05942 + 30000.0, 0.78, 12.5, 0.446, 0.05981 + 30000.0, 0.78, 12.55, 0.4475, 0.06021 + 30000.0, 0.78, 12.6, 0.4489, 0.0606 + 30000.0, 0.78, 12.65, 0.4504, 0.06098 + 30000.0, 0.78, 12.7, 0.4519, 0.06137 + 30000.0, 0.78, 12.75, 0.4533, 0.06175 + 30000.0, 0.78, 12.8, 0.4548, 0.06213 + 30000.0, 0.78, 12.85, 0.4563, 0.06251 + 30000.0, 0.78, 12.9, 0.4578, 0.06289 + 30000.0, 0.78, 12.95, 0.4592, 0.06326 + 30000.0, 0.78, 13.0, 0.4607, 0.06363 + 30000.0, 0.78, 13.05, 0.4622, 0.06399 + 30000.0, 0.78, 13.1, 0.4637, 0.06436 + 30000.0, 0.78, 13.15, 0.4651, 0.06472 + 30000.0, 0.78, 13.2, 0.4666, 0.06508 + 30000.0, 0.78, 13.25, 0.4681, 0.06543 + 30000.0, 0.78, 13.3, 0.4696, 0.06579 + 30000.0, 0.78, 13.35, 0.471, 0.06613 + 30000.0, 0.78, 13.4, 0.4725, 0.06648 + 30000.0, 0.78, 13.45, 0.474, 0.06682 + 30000.0, 0.78, 13.5, 0.4755, 0.06716 + 30000.0, 0.78, 13.55, 0.4769, 0.0675 + 30000.0, 0.78, 13.6, 0.4784, 0.06783 + 30000.0, 0.78, 13.65, 0.4799, 0.06816 + 30000.0, 0.78, 13.7, 0.4814, 0.06848 + 30000.0, 0.78, 13.75, 0.4828, 0.0688 + 30000.0, 0.78, 13.8, 0.4843, 0.06912 + 30000.0, 0.78, 13.85, 0.4858, 0.06943 + 30000.0, 0.78, 13.9, 0.4873, 0.06974 + 30000.0, 0.78, 13.95, 0.4888, 0.07005 + 30000.0, 0.78, 14.0, 0.4902, 0.07035 + 30000.0, 0.78, 14.05, 0.4917, 0.07064 + 30000.0, 0.78, 14.1, 0.4932, 0.07094 + 30000.0, 0.78, 14.15, 0.4947, 0.07123 + 30000.0, 0.78, 14.2, 0.4961, 0.07151 + 30000.0, 0.78, 14.25, 0.4976, 0.07179 + 30000.0, 0.78, 14.3, 0.4991, 0.07207 + 30000.0, 0.78, 14.35, 0.5006, 0.07234 + 30000.0, 0.78, 14.4, 0.5021, 0.0726 + 30000.0, 0.78, 14.45, 0.5035, 0.07287 + 30000.0, 0.78, 14.5, 0.505, 0.07312 + 30000.0, 0.78, 14.55, 0.5065, 0.07338 + 30000.0, 0.78, 14.6, 0.508, 0.07362 + 30000.0, 0.78, 14.65, 0.5095, 0.07387 + 30000.0, 0.78, 14.7, 0.511, 0.0741 + 30000.0, 0.78, 14.75, 0.5124, 0.07434 + 30000.0, 0.78, 14.8, 0.5139, 0.07456 + 30000.0, 0.78, 14.85, 0.5154, 0.07479 + 30000.0, 0.78, 14.9, 0.5169, 0.075 + 30000.0, 0.78, 14.95, 0.5184, 0.07521 + 30000.0, 0.78, 15.0, 0.5199, 0.07542 + 30000.0, 0.78, 15.05, 0.5213, 0.07562 + 30000.0, 0.83, 0.0, -0.1999, 0.00292 + 30000.0, 0.83, 0.05, -0.1962, 0.002976 + 30000.0, 0.83, 0.1, -0.1925, 0.00303 + 30000.0, 0.83, 0.15, -0.1888, 0.003083 + 30000.0, 0.83, 0.2, -0.185, 0.003135 + 30000.0, 0.83, 0.25, -0.1812, 0.003186 + 30000.0, 0.83, 0.3, -0.1774, 0.003236 + 30000.0, 0.83, 0.35, -0.1736, 0.003285 + 30000.0, 0.83, 0.4, -0.1697, 0.003333 + 30000.0, 0.83, 0.45, -0.1658, 0.00338 + 30000.0, 0.83, 0.5, -0.1619, 0.003427 + 30000.0, 0.83, 0.55, -0.158, 0.003473 + 30000.0, 0.83, 0.6, -0.1541, 0.003518 + 30000.0, 0.83, 0.65, -0.1501, 0.003562 + 30000.0, 0.83, 0.7, -0.1461, 0.003606 + 30000.0, 0.83, 0.75, -0.1421, 0.00365 + 30000.0, 0.83, 0.8, -0.1381, 0.003693 + 30000.0, 0.83, 0.85, -0.134, 0.003735 + 30000.0, 0.83, 0.9, -0.13, 0.003777 + 30000.0, 0.83, 0.95, -0.1259, 0.003819 + 30000.0, 0.83, 1.0, -0.1218, 0.003861 + 30000.0, 0.83, 1.05, -0.1177, 0.003902 + 30000.0, 0.83, 1.1, -0.1136, 0.003943 + 30000.0, 0.83, 1.15, -0.1095, 0.003984 + 30000.0, 0.83, 1.2, -0.1053, 0.004025 + 30000.0, 0.83, 1.25, -0.1012, 0.004066 + 30000.0, 0.83, 1.3, -0.09699, 0.004106 + 30000.0, 0.83, 1.35, -0.09281, 0.004147 + 30000.0, 0.83, 1.4, -0.08862, 0.004188 + 30000.0, 0.83, 1.45, -0.08443, 0.004229 + 30000.0, 0.83, 1.5, -0.08022, 0.004271 + 30000.0, 0.83, 1.55, -0.07601, 0.004312 + 30000.0, 0.83, 1.6, -0.07179, 0.004354 + 30000.0, 0.83, 1.65, -0.06757, 0.004396 + 30000.0, 0.83, 1.7, -0.06334, 0.004439 + 30000.0, 0.83, 1.75, -0.05911, 0.004482 + 30000.0, 0.83, 1.8, -0.05487, 0.004526 + 30000.0, 0.83, 1.85, -0.05063, 0.00457 + 30000.0, 0.83, 1.9, -0.04639, 0.004615 + 30000.0, 0.83, 1.95, -0.04214, 0.00466 + 30000.0, 0.83, 2.0, -0.0379, 0.004706 + 30000.0, 0.83, 2.05, -0.03365, 0.004753 + 30000.0, 0.83, 2.1, -0.02941, 0.004801 + 30000.0, 0.83, 2.15, -0.02516, 0.004849 + 30000.0, 0.83, 2.2, -0.02092, 0.004899 + 30000.0, 0.83, 2.25, -0.01668, 0.004949 + 30000.0, 0.83, 2.3, -0.01244, 0.005 + 30000.0, 0.83, 2.35, -0.008212, 0.005053 + 30000.0, 0.83, 2.4, -0.003985, 0.005106 + 30000.0, 0.83, 2.45, 0.0002371, 0.005161 + 30000.0, 0.83, 2.5, 0.004453, 0.005216 + 30000.0, 0.83, 2.55, 0.008662, 0.005273 + 30000.0, 0.83, 2.6, 0.01286, 0.005332 + 30000.0, 0.83, 2.65, 0.01706, 0.005391 + 30000.0, 0.83, 2.7, 0.02124, 0.005452 + 30000.0, 0.83, 2.75, 0.02541, 0.005515 + 30000.0, 0.83, 2.8, 0.02958, 0.005578 + 30000.0, 0.83, 2.85, 0.03373, 0.005644 + 30000.0, 0.83, 2.9, 0.03787, 0.005711 + 30000.0, 0.83, 2.95, 0.042, 0.00578 + 30000.0, 0.83, 3.0, 0.04611, 0.00585 + 30000.0, 0.83, 3.05, 0.05021, 0.005922 + 30000.0, 0.83, 3.1, 0.0543, 0.005996 + 30000.0, 0.83, 3.15, 0.05836, 0.006071 + 30000.0, 0.83, 3.2, 0.06242, 0.006149 + 30000.0, 0.83, 3.25, 0.06645, 0.006228 + 30000.0, 0.83, 3.3, 0.07047, 0.00631 + 30000.0, 0.83, 3.35, 0.07447, 0.006393 + 30000.0, 0.83, 3.4, 0.07845, 0.006479 + 30000.0, 0.83, 3.45, 0.08242, 0.006566 + 30000.0, 0.83, 3.5, 0.08636, 0.006656 + 30000.0, 0.83, 3.55, 0.09028, 0.006748 + 30000.0, 0.83, 3.6, 0.09417, 0.006843 + 30000.0, 0.83, 3.65, 0.09805, 0.006939 + 30000.0, 0.83, 3.7, 0.1019, 0.007038 + 30000.0, 0.83, 3.75, 0.1057, 0.00714 + 30000.0, 0.83, 3.8, 0.1095, 0.007243 + 30000.0, 0.83, 3.85, 0.1133, 0.00735 + 30000.0, 0.83, 3.9, 0.1171, 0.007459 + 30000.0, 0.83, 3.95, 0.1208, 0.00757 + 30000.0, 0.83, 4.0, 0.1245, 0.007684 + 30000.0, 0.83, 4.05, 0.128, 0.007809 + 30000.0, 0.83, 4.1, 0.1314, 0.007935 + 30000.0, 0.83, 4.15, 0.1349, 0.008064 + 30000.0, 0.83, 4.2, 0.1383, 0.008195 + 30000.0, 0.83, 4.25, 0.1417, 0.008328 + 30000.0, 0.83, 4.3, 0.1451, 0.008464 + 30000.0, 0.83, 4.35, 0.1485, 0.008602 + 30000.0, 0.83, 4.4, 0.1519, 0.008742 + 30000.0, 0.83, 4.45, 0.1552, 0.008885 + 30000.0, 0.83, 4.5, 0.1586, 0.009029 + 30000.0, 0.83, 4.55, 0.1619, 0.009177 + 30000.0, 0.83, 4.6, 0.1652, 0.009326 + 30000.0, 0.83, 4.65, 0.1685, 0.009478 + 30000.0, 0.83, 4.7, 0.1718, 0.009632 + 30000.0, 0.83, 4.75, 0.1751, 0.009788 + 30000.0, 0.83, 4.8, 0.1784, 0.009946 + 30000.0, 0.83, 4.85, 0.1817, 0.01011 + 30000.0, 0.83, 4.9, 0.1849, 0.01027 + 30000.0, 0.83, 4.95, 0.1882, 0.01044 + 30000.0, 0.83, 5.0, 0.1915, 0.0106 + 30000.0, 0.83, 5.05, 0.1948, 0.01078 + 30000.0, 0.83, 5.1, 0.1981, 0.01096 + 30000.0, 0.83, 5.15, 0.2015, 0.01114 + 30000.0, 0.83, 5.2, 0.2048, 0.01132 + 30000.0, 0.83, 5.25, 0.2081, 0.01151 + 30000.0, 0.83, 5.3, 0.2114, 0.0117 + 30000.0, 0.83, 5.35, 0.2147, 0.01188 + 30000.0, 0.83, 5.4, 0.218, 0.01207 + 30000.0, 0.83, 5.45, 0.2213, 0.01226 + 30000.0, 0.83, 5.5, 0.2246, 0.01246 + 30000.0, 0.83, 5.55, 0.2278, 0.01265 + 30000.0, 0.83, 5.6, 0.2311, 0.01284 + 30000.0, 0.83, 5.65, 0.2343, 0.01304 + 30000.0, 0.83, 5.7, 0.2375, 0.01323 + 30000.0, 0.83, 5.75, 0.2407, 0.01343 + 30000.0, 0.83, 5.8, 0.2438, 0.01362 + 30000.0, 0.83, 5.85, 0.247, 0.01382 + 30000.0, 0.83, 5.9, 0.2501, 0.01402 + 30000.0, 0.83, 5.95, 0.2532, 0.01421 + 30000.0, 0.83, 6.0, 0.2563, 0.01441 + 30000.0, 0.83, 6.05, 0.2591, 0.01458 + 30000.0, 0.83, 6.1, 0.2619, 0.01475 + 30000.0, 0.83, 6.15, 0.2647, 0.01493 + 30000.0, 0.83, 6.2, 0.2674, 0.0151 + 30000.0, 0.83, 6.25, 0.2701, 0.01526 + 30000.0, 0.83, 6.3, 0.2728, 0.01543 + 30000.0, 0.83, 6.35, 0.2754, 0.0156 + 30000.0, 0.83, 6.4, 0.278, 0.01576 + 30000.0, 0.83, 6.45, 0.2806, 0.01593 + 30000.0, 0.83, 6.5, 0.2831, 0.01609 + 30000.0, 0.83, 6.55, 0.2856, 0.01625 + 30000.0, 0.83, 6.6, 0.2881, 0.01642 + 30000.0, 0.83, 6.65, 0.2906, 0.01658 + 30000.0, 0.83, 6.7, 0.2931, 0.01674 + 30000.0, 0.83, 6.75, 0.2955, 0.0169 + 30000.0, 0.83, 6.8, 0.2979, 0.01705 + 30000.0, 0.83, 6.85, 0.3003, 0.01721 + 30000.0, 0.83, 6.9, 0.3027, 0.01737 + 30000.0, 0.83, 6.95, 0.305, 0.01753 + 30000.0, 0.83, 7.0, 0.3074, 0.01768 + 30000.0, 0.83, 7.05, 0.3097, 0.01784 + 30000.0, 0.83, 7.1, 0.312, 0.01799 + 30000.0, 0.83, 7.15, 0.3143, 0.01815 + 30000.0, 0.83, 7.2, 0.3166, 0.0183 + 30000.0, 0.83, 7.25, 0.3188, 0.01845 + 30000.0, 0.83, 7.3, 0.3211, 0.01861 + 30000.0, 0.83, 7.35, 0.3233, 0.01876 + 30000.0, 0.83, 7.4, 0.3255, 0.01891 + 30000.0, 0.83, 7.45, 0.3278, 0.01907 + 30000.0, 0.83, 7.5, 0.33, 0.01922 + 30000.0, 0.83, 7.55, 0.3322, 0.01937 + 30000.0, 0.83, 7.6, 0.3344, 0.01952 + 30000.0, 0.83, 7.65, 0.3366, 0.01967 + 30000.0, 0.83, 7.7, 0.3387, 0.01983 + 30000.0, 0.83, 7.75, 0.3409, 0.01998 + 30000.0, 0.83, 7.8, 0.3431, 0.02013 + 30000.0, 0.83, 7.85, 0.3453, 0.02028 + 30000.0, 0.83, 7.9, 0.3475, 0.02044 + 30000.0, 0.83, 7.95, 0.3496, 0.02059 + 30000.0, 0.83, 8.0, 0.3518, 0.02074 + 30000.0, 0.83, 8.05, 0.3542, 0.02091 + 30000.0, 0.83, 8.1, 0.3567, 0.02107 + 30000.0, 0.83, 8.15, 0.3591, 0.02124 + 30000.0, 0.83, 8.2, 0.3615, 0.02141 + 30000.0, 0.83, 8.25, 0.3639, 0.02157 + 30000.0, 0.83, 8.3, 0.3664, 0.02174 + 30000.0, 0.83, 8.35, 0.3688, 0.02191 + 30000.0, 0.83, 8.4, 0.3712, 0.02208 + 30000.0, 0.83, 8.45, 0.3737, 0.02225 + 30000.0, 0.83, 8.5, 0.3761, 0.02241 + 30000.0, 0.83, 8.55, 0.3785, 0.02258 + 30000.0, 0.83, 8.6, 0.381, 0.02275 + 30000.0, 0.83, 8.65, 0.3834, 0.02292 + 30000.0, 0.83, 8.7, 0.3858, 0.02309 + 30000.0, 0.83, 8.75, 0.3883, 0.02326 + 30000.0, 0.83, 8.8, 0.3907, 0.02343 + 30000.0, 0.83, 8.85, 0.3932, 0.0236 + 30000.0, 0.83, 8.9, 0.3956, 0.02376 + 30000.0, 0.83, 8.95, 0.398, 0.02393 + 30000.0, 0.83, 9.0, 0.4005, 0.0241 + 30000.0, 0.83, 9.05, 0.4029, 0.02427 + 30000.0, 0.83, 9.1, 0.4054, 0.02444 + 30000.0, 0.83, 9.15, 0.4078, 0.02461 + 30000.0, 0.83, 9.2, 0.4103, 0.02478 + 30000.0, 0.83, 9.25, 0.4127, 0.02495 + 30000.0, 0.83, 9.3, 0.4152, 0.02512 + 30000.0, 0.83, 9.35, 0.4176, 0.02529 + 30000.0, 0.83, 9.4, 0.4201, 0.02546 + 30000.0, 0.83, 9.45, 0.4225, 0.02563 + 30000.0, 0.83, 9.5, 0.425, 0.0258 + 30000.0, 0.83, 9.55, 0.4274, 0.02597 + 30000.0, 0.83, 9.6, 0.4299, 0.02614 + 30000.0, 0.83, 9.65, 0.4323, 0.02631 + 30000.0, 0.83, 9.7, 0.4348, 0.02648 + 30000.0, 0.83, 9.75, 0.4372, 0.02665 + 30000.0, 0.83, 9.8, 0.4397, 0.02682 + 30000.0, 0.83, 9.85, 0.4421, 0.02699 + 30000.0, 0.83, 9.9, 0.4446, 0.02715 + 30000.0, 0.83, 9.95, 0.447, 0.02732 + 30000.0, 0.83, 10.0, 0.4495, 0.02749 + 30000.0, 0.83, 10.05, 0.4519, 0.02766 + 30000.0, 0.83, 10.1, 0.4544, 0.02782 + 30000.0, 0.83, 10.15, 0.4568, 0.02798 + 30000.0, 0.83, 10.2, 0.4593, 0.02815 + 30000.0, 0.83, 10.25, 0.4617, 0.02831 + 30000.0, 0.83, 10.3, 0.4642, 0.02847 + 30000.0, 0.83, 10.35, 0.4666, 0.02864 + 30000.0, 0.83, 10.4, 0.4691, 0.0288 + 30000.0, 0.83, 10.45, 0.4715, 0.02896 + 30000.0, 0.83, 10.5, 0.4739, 0.02913 + 30000.0, 0.83, 10.55, 0.4764, 0.02929 + 30000.0, 0.83, 10.6, 0.4788, 0.02945 + 30000.0, 0.83, 10.65, 0.4813, 0.02961 + 30000.0, 0.83, 10.7, 0.4837, 0.02978 + 30000.0, 0.83, 10.75, 0.4862, 0.02994 + 30000.0, 0.83, 10.8, 0.4886, 0.0301 + 30000.0, 0.83, 10.85, 0.4911, 0.03027 + 30000.0, 0.83, 10.9, 0.4935, 0.03043 + 30000.0, 0.83, 10.95, 0.496, 0.03059 + 30000.0, 0.83, 11.0, 0.4984, 0.03075 + 30000.0, 0.83, 11.05, 0.5009, 0.03092 + 30000.0, 0.83, 11.1, 0.5033, 0.03108 + 30000.0, 0.83, 11.15, 0.5058, 0.03124 + 30000.0, 0.83, 11.2, 0.5082, 0.03141 + 30000.0, 0.83, 11.25, 0.5107, 0.03157 + 30000.0, 0.83, 11.3, 0.5131, 0.03173 + 30000.0, 0.83, 11.35, 0.5156, 0.0319 + 30000.0, 0.83, 11.4, 0.518, 0.03206 + 30000.0, 0.83, 11.45, 0.5205, 0.03222 + 30000.0, 0.83, 11.5, 0.5229, 0.03239 + 30000.0, 0.83, 11.55, 0.5254, 0.03255 + 30000.0, 0.83, 11.6, 0.5278, 0.03272 + 30000.0, 0.83, 11.65, 0.5303, 0.03288 + 30000.0, 0.83, 11.7, 0.5327, 0.03304 + 30000.0, 0.83, 11.75, 0.5352, 0.03321 + 30000.0, 0.83, 11.8, 0.5376, 0.03337 + 30000.0, 0.83, 11.85, 0.54, 0.03354 + 30000.0, 0.83, 11.9, 0.5425, 0.0337 + 30000.0, 0.83, 11.95, 0.5449, 0.03387 + 30000.0, 0.83, 12.0, 0.5474, 0.03403 + 30000.0, 0.83, 12.05, 0.5498, 0.0342 + 30000.0, 0.83, 12.1, 0.5523, 0.03437 + 30000.0, 0.83, 12.15, 0.5547, 0.03453 + 30000.0, 0.83, 12.2, 0.5572, 0.0347 + 30000.0, 0.83, 12.25, 0.5596, 0.03487 + 30000.0, 0.83, 12.3, 0.5621, 0.03503 + 30000.0, 0.83, 12.35, 0.5645, 0.0352 + 30000.0, 0.83, 12.4, 0.567, 0.03537 + 30000.0, 0.83, 12.45, 0.5694, 0.03554 + 30000.0, 0.83, 12.5, 0.5719, 0.0357 + 30000.0, 0.83, 12.55, 0.5743, 0.03587 + 30000.0, 0.83, 12.6, 0.5767, 0.03604 + 30000.0, 0.83, 12.65, 0.5792, 0.03621 + 30000.0, 0.83, 12.7, 0.5816, 0.03638 + 30000.0, 0.83, 12.75, 0.5841, 0.03655 + 30000.0, 0.83, 12.8, 0.5865, 0.03672 + 30000.0, 0.83, 12.85, 0.589, 0.03689 + 30000.0, 0.83, 12.9, 0.5914, 0.03706 + 30000.0, 0.83, 12.95, 0.5938, 0.03723 + 30000.0, 0.83, 13.0, 0.5963, 0.0374 + 30000.0, 0.83, 13.05, 0.5987, 0.03758 + 30000.0, 0.83, 13.1, 0.6012, 0.03775 + 30000.0, 0.83, 13.15, 0.6036, 0.03792 + 30000.0, 0.83, 13.2, 0.6061, 0.03809 + 30000.0, 0.83, 13.25, 0.6085, 0.03827 + 30000.0, 0.83, 13.3, 0.6109, 0.03844 + 30000.0, 0.83, 13.35, 0.6134, 0.03862 + 30000.0, 0.83, 13.4, 0.6158, 0.03879 + 30000.0, 0.83, 13.45, 0.6183, 0.03897 + 30000.0, 0.83, 13.5, 0.6207, 0.03914 + 30000.0, 0.83, 13.55, 0.6231, 0.03932 + 30000.0, 0.83, 13.6, 0.6256, 0.0395 + 30000.0, 0.83, 13.65, 0.628, 0.03967 + 30000.0, 0.83, 13.7, 0.6305, 0.03985 + 30000.0, 0.83, 13.75, 0.6329, 0.04003 + 30000.0, 0.83, 13.8, 0.6353, 0.04021 + 30000.0, 0.83, 13.85, 0.6378, 0.04039 + 30000.0, 0.83, 13.9, 0.6402, 0.04057 + 30000.0, 0.83, 13.95, 0.6426, 0.04075 + 30000.0, 0.83, 14.0, 0.6451, 0.04093 + 30000.0, 0.83, 14.05, 0.6475, 0.04111 + 30000.0, 0.83, 14.1, 0.6499, 0.0413 + 30000.0, 0.83, 14.15, 0.6524, 0.04148 + 30000.0, 0.83, 14.2, 0.6548, 0.04166 + 30000.0, 0.83, 14.25, 0.6572, 0.04185 + 30000.0, 0.83, 14.3, 0.6597, 0.04203 + 30000.0, 0.83, 14.35, 0.6621, 0.04222 + 30000.0, 0.83, 14.4, 0.6645, 0.0424 + 30000.0, 0.83, 14.45, 0.667, 0.04259 + 30000.0, 0.83, 14.5, 0.6694, 0.04278 + 30000.0, 0.83, 14.55, 0.6718, 0.04297 + 30000.0, 0.83, 14.6, 0.6742, 0.04315 + 30000.0, 0.83, 14.65, 0.6767, 0.04334 + 30000.0, 0.83, 14.7, 0.6791, 0.04353 + 30000.0, 0.83, 14.75, 0.6815, 0.04373 + 30000.0, 0.83, 14.8, 0.684, 0.04392 + 30000.0, 0.83, 14.85, 0.6864, 0.04411 + 30000.0, 0.83, 14.9, 0.6888, 0.0443 + 30000.0, 0.83, 14.95, 0.6912, 0.0445 + 30000.0, 0.83, 15.0, 0.6937, 0.04469 + 30000.0, 0.83, 15.05, 0.6961, 0.04489 + 30000.0, 0.88, 0.0, -0.2123, 0.01117 + 30000.0, 0.88, 0.05, -0.2081, 0.01117 + 30000.0, 0.88, 0.1, -0.2038, 0.01117 + 30000.0, 0.88, 0.15, -0.1995, 0.01115 + 30000.0, 0.88, 0.2, -0.1951, 0.01114 + 30000.0, 0.88, 0.25, -0.1908, 0.01111 + 30000.0, 0.88, 0.3, -0.1864, 0.01108 + 30000.0, 0.88, 0.35, -0.182, 0.01104 + 30000.0, 0.88, 0.4, -0.1777, 0.011 + 30000.0, 0.88, 0.45, -0.1732, 0.01095 + 30000.0, 0.88, 0.5, -0.1688, 0.0109 + 30000.0, 0.88, 0.55, -0.1644, 0.01084 + 30000.0, 0.88, 0.6, -0.1599, 0.01077 + 30000.0, 0.88, 0.65, -0.1555, 0.01071 + 30000.0, 0.88, 0.7, -0.151, 0.01063 + 30000.0, 0.88, 0.75, -0.1465, 0.01056 + 30000.0, 0.88, 0.8, -0.142, 0.01048 + 30000.0, 0.88, 0.85, -0.1375, 0.0104 + 30000.0, 0.88, 0.9, -0.133, 0.01031 + 30000.0, 0.88, 0.95, -0.1284, 0.01023 + 30000.0, 0.88, 1.0, -0.1239, 0.01014 + 30000.0, 0.88, 1.05, -0.1193, 0.01005 + 30000.0, 0.88, 1.1, -0.1148, 0.009953 + 30000.0, 0.88, 1.15, -0.1102, 0.009858 + 30000.0, 0.88, 1.2, -0.1056, 0.009763 + 30000.0, 0.88, 1.25, -0.1011, 0.009666 + 30000.0, 0.88, 1.3, -0.09647, 0.009569 + 30000.0, 0.88, 1.35, -0.09188, 0.009472 + 30000.0, 0.88, 1.4, -0.08729, 0.009374 + 30000.0, 0.88, 1.45, -0.0827, 0.009277 + 30000.0, 0.88, 1.5, -0.0781, 0.009181 + 30000.0, 0.88, 1.55, -0.07349, 0.009085 + 30000.0, 0.88, 1.6, -0.06889, 0.00899 + 30000.0, 0.88, 1.65, -0.06428, 0.008897 + 30000.0, 0.88, 1.7, -0.05968, 0.008806 + 30000.0, 0.88, 1.75, -0.05507, 0.008716 + 30000.0, 0.88, 1.8, -0.05046, 0.008629 + 30000.0, 0.88, 1.85, -0.04586, 0.008544 + 30000.0, 0.88, 1.9, -0.04125, 0.008463 + 30000.0, 0.88, 1.95, -0.03665, 0.008384 + 30000.0, 0.88, 2.0, -0.03205, 0.008309 + 30000.0, 0.88, 2.05, -0.02745, 0.008237 + 30000.0, 0.88, 2.1, -0.02286, 0.00817 + 30000.0, 0.88, 2.15, -0.01827, 0.008106 + 30000.0, 0.88, 2.2, -0.01368, 0.008048 + 30000.0, 0.88, 2.25, -0.009103, 0.007994 + 30000.0, 0.88, 2.3, -0.004529, 0.007945 + 30000.0, 0.88, 2.35, 3.779e-05, 0.007901 + 30000.0, 0.88, 2.4, 0.004598, 0.007864 + 30000.0, 0.88, 2.45, 0.00915, 0.007832 + 30000.0, 0.88, 2.5, 0.01369, 0.007807 + 30000.0, 0.88, 2.55, 0.01823, 0.007788 + 30000.0, 0.88, 2.6, 0.02275, 0.007776 + 30000.0, 0.88, 2.65, 0.02727, 0.007771 + 30000.0, 0.88, 2.7, 0.03178, 0.007773 + 30000.0, 0.88, 2.75, 0.03627, 0.007783 + 30000.0, 0.88, 2.8, 0.04075, 0.007801 + 30000.0, 0.88, 2.85, 0.04522, 0.007827 + 30000.0, 0.88, 2.9, 0.04968, 0.007862 + 30000.0, 0.88, 2.95, 0.05412, 0.007906 + 30000.0, 0.88, 3.0, 0.05855, 0.007959 + 30000.0, 0.88, 3.05, 0.06297, 0.008021 + 30000.0, 0.88, 3.1, 0.06737, 0.008093 + 30000.0, 0.88, 3.15, 0.07175, 0.008175 + 30000.0, 0.88, 3.2, 0.07612, 0.008267 + 30000.0, 0.88, 3.25, 0.08047, 0.008369 + 30000.0, 0.88, 3.3, 0.08481, 0.008483 + 30000.0, 0.88, 3.35, 0.08912, 0.008607 + 30000.0, 0.88, 3.4, 0.09342, 0.008743 + 30000.0, 0.88, 3.45, 0.0977, 0.008891 + 30000.0, 0.88, 3.5, 0.102, 0.00905 + 30000.0, 0.88, 3.55, 0.1062, 0.009222 + 30000.0, 0.88, 3.6, 0.1104, 0.009406 + 30000.0, 0.88, 3.65, 0.1146, 0.009603 + 30000.0, 0.88, 3.7, 0.1188, 0.009813 + 30000.0, 0.88, 3.75, 0.1229, 0.01004 + 30000.0, 0.88, 3.8, 0.1271, 0.01027 + 30000.0, 0.88, 3.85, 0.1312, 0.01052 + 30000.0, 0.88, 3.9, 0.1352, 0.01079 + 30000.0, 0.88, 3.95, 0.1393, 0.01107 + 30000.0, 0.88, 4.0, 0.1433, 0.01136 + 30000.0, 0.88, 4.05, 0.1477, 0.01173 + 30000.0, 0.88, 4.1, 0.152, 0.0121 + 30000.0, 0.88, 4.15, 0.1563, 0.01248 + 30000.0, 0.88, 4.2, 0.1606, 0.01288 + 30000.0, 0.88, 4.25, 0.1647, 0.01329 + 30000.0, 0.88, 4.3, 0.1688, 0.01371 + 30000.0, 0.88, 4.35, 0.1729, 0.01415 + 30000.0, 0.88, 4.4, 0.1768, 0.01459 + 30000.0, 0.88, 4.45, 0.1807, 0.01505 + 30000.0, 0.88, 4.5, 0.1845, 0.01552 + 30000.0, 0.88, 4.55, 0.1883, 0.016 + 30000.0, 0.88, 4.6, 0.1919, 0.01649 + 30000.0, 0.88, 4.65, 0.1955, 0.01699 + 30000.0, 0.88, 4.7, 0.199, 0.0175 + 30000.0, 0.88, 4.75, 0.2023, 0.01802 + 30000.0, 0.88, 4.8, 0.2056, 0.01856 + 30000.0, 0.88, 4.85, 0.2088, 0.0191 + 30000.0, 0.88, 4.9, 0.2119, 0.01966 + 30000.0, 0.88, 4.95, 0.2148, 0.02023 + 30000.0, 0.88, 5.0, 0.2177, 0.0208 + 30000.0, 0.88, 5.05, 0.2197, 0.02137 + 30000.0, 0.88, 5.1, 0.2217, 0.02194 + 30000.0, 0.88, 5.15, 0.2236, 0.02253 + 30000.0, 0.88, 5.2, 0.2254, 0.02312 + 30000.0, 0.88, 5.25, 0.227, 0.02373 + 30000.0, 0.88, 5.3, 0.2286, 0.02435 + 30000.0, 0.88, 5.35, 0.2301, 0.02498 + 30000.0, 0.88, 5.4, 0.2316, 0.02562 + 30000.0, 0.88, 5.45, 0.2329, 0.02628 + 30000.0, 0.88, 5.5, 0.2343, 0.02695 + 30000.0, 0.88, 5.55, 0.2355, 0.02763 + 30000.0, 0.88, 5.6, 0.2367, 0.02832 + 30000.0, 0.88, 5.65, 0.2379, 0.02902 + 30000.0, 0.88, 5.7, 0.239, 0.02974 + 30000.0, 0.88, 5.75, 0.2401, 0.03048 + 30000.0, 0.88, 5.8, 0.2412, 0.03122 + 30000.0, 0.88, 5.85, 0.2423, 0.03198 + 30000.0, 0.88, 5.9, 0.2433, 0.03276 + 30000.0, 0.88, 5.95, 0.2444, 0.03355 + 30000.0, 0.88, 6.0, 0.2455, 0.03435 + 30000.0, 0.88, 6.05, 0.2476, 0.03526 + 30000.0, 0.88, 6.1, 0.2498, 0.0362 + 30000.0, 0.88, 6.15, 0.2521, 0.03715 + 30000.0, 0.88, 6.2, 0.2544, 0.03812 + 30000.0, 0.88, 6.25, 0.2568, 0.0391 + 30000.0, 0.88, 6.3, 0.2592, 0.04011 + 30000.0, 0.88, 6.35, 0.2617, 0.04113 + 30000.0, 0.88, 6.4, 0.2642, 0.04217 + 30000.0, 0.88, 6.45, 0.2668, 0.04322 + 30000.0, 0.88, 6.5, 0.2694, 0.04429 + 30000.0, 0.88, 6.55, 0.2721, 0.04537 + 30000.0, 0.88, 6.6, 0.2748, 0.04647 + 30000.0, 0.88, 6.65, 0.2775, 0.04758 + 30000.0, 0.88, 6.7, 0.2803, 0.04871 + 30000.0, 0.88, 6.75, 0.2832, 0.04985 + 30000.0, 0.88, 6.8, 0.286, 0.051 + 30000.0, 0.88, 6.85, 0.2889, 0.05217 + 30000.0, 0.88, 6.9, 0.2918, 0.05334 + 30000.0, 0.88, 6.95, 0.2948, 0.05453 + 30000.0, 0.88, 7.0, 0.2978, 0.05573 + 30000.0, 0.88, 7.05, 0.3008, 0.05694 + 30000.0, 0.88, 7.1, 0.3038, 0.05816 + 30000.0, 0.88, 7.15, 0.3069, 0.05939 + 30000.0, 0.88, 7.2, 0.31, 0.06062 + 30000.0, 0.88, 7.25, 0.3131, 0.06187 + 30000.0, 0.88, 7.3, 0.3162, 0.06313 + 30000.0, 0.88, 7.35, 0.3194, 0.06439 + 30000.0, 0.88, 7.4, 0.3225, 0.06566 + 30000.0, 0.88, 7.45, 0.3257, 0.06693 + 30000.0, 0.88, 7.5, 0.3289, 0.06822 + 30000.0, 0.88, 7.55, 0.332, 0.06951 + 30000.0, 0.88, 7.6, 0.3352, 0.0708 + 30000.0, 0.88, 7.65, 0.3384, 0.0721 + 30000.0, 0.88, 7.7, 0.3417, 0.0734 + 30000.0, 0.88, 7.75, 0.3449, 0.07471 + 30000.0, 0.88, 7.8, 0.3481, 0.07602 + 30000.0, 0.88, 7.85, 0.3513, 0.07734 + 30000.0, 0.88, 7.9, 0.3545, 0.07866 + 30000.0, 0.88, 7.95, 0.3577, 0.07998 + 30000.0, 0.88, 8.0, 0.3609, 0.0813 + 30000.0, 0.88, 8.05, 0.3636, 0.0825 + 30000.0, 0.88, 8.1, 0.3663, 0.0837 + 30000.0, 0.88, 8.15, 0.3689, 0.0849 + 30000.0, 0.88, 8.2, 0.3716, 0.0861 + 30000.0, 0.88, 8.25, 0.3743, 0.08731 + 30000.0, 0.88, 8.3, 0.3769, 0.08851 + 30000.0, 0.88, 8.35, 0.3796, 0.08972 + 30000.0, 0.88, 8.4, 0.3822, 0.09093 + 30000.0, 0.88, 8.45, 0.3848, 0.09214 + 30000.0, 0.88, 8.5, 0.3875, 0.09335 + 30000.0, 0.88, 8.55, 0.3901, 0.09456 + 30000.0, 0.88, 8.6, 0.3927, 0.09578 + 30000.0, 0.88, 8.65, 0.3953, 0.09699 + 30000.0, 0.88, 8.7, 0.3979, 0.09821 + 30000.0, 0.88, 8.75, 0.4005, 0.09943 + 30000.0, 0.88, 8.8, 0.4031, 0.1007 + 30000.0, 0.88, 8.85, 0.4057, 0.1019 + 30000.0, 0.88, 8.9, 0.4083, 0.1031 + 30000.0, 0.88, 8.95, 0.4109, 0.1043 + 30000.0, 0.88, 9.0, 0.4134, 0.1056 + 30000.0, 0.88, 9.05, 0.416, 0.1068 + 30000.0, 0.88, 9.1, 0.4186, 0.108 + 30000.0, 0.88, 9.15, 0.4211, 0.1092 + 30000.0, 0.88, 9.2, 0.4237, 0.1105 + 30000.0, 0.88, 9.25, 0.4262, 0.1117 + 30000.0, 0.88, 9.3, 0.4288, 0.1129 + 30000.0, 0.88, 9.35, 0.4313, 0.1142 + 30000.0, 0.88, 9.4, 0.4339, 0.1154 + 30000.0, 0.88, 9.45, 0.4364, 0.1167 + 30000.0, 0.88, 9.5, 0.439, 0.1179 + 30000.0, 0.88, 9.55, 0.4415, 0.1192 + 30000.0, 0.88, 9.6, 0.4441, 0.1204 + 30000.0, 0.88, 9.65, 0.4466, 0.1217 + 30000.0, 0.88, 9.7, 0.4491, 0.1229 + 30000.0, 0.88, 9.75, 0.4516, 0.1242 + 30000.0, 0.88, 9.8, 0.4542, 0.1254 + 30000.0, 0.88, 9.85, 0.4567, 0.1267 + 30000.0, 0.88, 9.9, 0.4592, 0.1279 + 30000.0, 0.88, 9.95, 0.4618, 0.1292 + 30000.0, 0.88, 10.0, 0.4643, 0.1305 + 30000.0, 0.88, 10.05, 0.4668, 0.1318 + 30000.0, 0.88, 10.1, 0.4694, 0.1331 + 30000.0, 0.88, 10.15, 0.4719, 0.1344 + 30000.0, 0.88, 10.2, 0.4745, 0.1357 + 30000.0, 0.88, 10.25, 0.477, 0.137 + 30000.0, 0.88, 10.3, 0.4796, 0.1383 + 30000.0, 0.88, 10.35, 0.4822, 0.1396 + 30000.0, 0.88, 10.4, 0.4847, 0.1409 + 30000.0, 0.88, 10.45, 0.4873, 0.1422 + 30000.0, 0.88, 10.5, 0.4898, 0.1435 + 30000.0, 0.88, 10.55, 0.4924, 0.1448 + 30000.0, 0.88, 10.6, 0.4949, 0.1462 + 30000.0, 0.88, 10.65, 0.4974, 0.1475 + 30000.0, 0.88, 10.7, 0.5, 0.1488 + 30000.0, 0.88, 10.75, 0.5025, 0.1501 + 30000.0, 0.88, 10.8, 0.5051, 0.1514 + 30000.0, 0.88, 10.85, 0.5076, 0.1527 + 30000.0, 0.88, 10.9, 0.5102, 0.154 + 30000.0, 0.88, 10.95, 0.5127, 0.1553 + 30000.0, 0.88, 11.0, 0.5153, 0.1567 + 30000.0, 0.88, 11.05, 0.5178, 0.158 + 30000.0, 0.88, 11.1, 0.5204, 0.1593 + 30000.0, 0.88, 11.15, 0.5229, 0.1606 + 30000.0, 0.88, 11.2, 0.5255, 0.1619 + 30000.0, 0.88, 11.25, 0.528, 0.1632 + 30000.0, 0.88, 11.3, 0.5306, 0.1645 + 30000.0, 0.88, 11.35, 0.5331, 0.1658 + 30000.0, 0.88, 11.4, 0.5357, 0.1671 + 30000.0, 0.88, 11.45, 0.5382, 0.1684 + 30000.0, 0.88, 11.5, 0.5408, 0.1697 + 30000.0, 0.88, 11.55, 0.5433, 0.171 + 30000.0, 0.88, 11.6, 0.5459, 0.1723 + 30000.0, 0.88, 11.65, 0.5484, 0.1736 + 30000.0, 0.88, 11.7, 0.551, 0.1749 + 30000.0, 0.88, 11.75, 0.5535, 0.1762 + 30000.0, 0.88, 11.8, 0.5561, 0.1775 + 30000.0, 0.88, 11.85, 0.5586, 0.1788 + 30000.0, 0.88, 11.9, 0.5612, 0.1801 + 30000.0, 0.88, 11.95, 0.5637, 0.1814 + 30000.0, 0.88, 12.0, 0.5663, 0.1826 + 30000.0, 0.88, 12.05, 0.5688, 0.1839 + 30000.0, 0.88, 12.1, 0.5714, 0.1852 + 30000.0, 0.88, 12.15, 0.574, 0.1865 + 30000.0, 0.88, 12.2, 0.5765, 0.1877 + 30000.0, 0.88, 12.25, 0.5791, 0.189 + 30000.0, 0.88, 12.3, 0.5816, 0.1903 + 30000.0, 0.88, 12.35, 0.5842, 0.1915 + 30000.0, 0.88, 12.4, 0.5868, 0.1928 + 30000.0, 0.88, 12.45, 0.5893, 0.194 + 30000.0, 0.88, 12.5, 0.5919, 0.1953 + 30000.0, 0.88, 12.55, 0.5945, 0.1965 + 30000.0, 0.88, 12.6, 0.597, 0.1977 + 30000.0, 0.88, 12.65, 0.5996, 0.199 + 30000.0, 0.88, 12.7, 0.6022, 0.2002 + 30000.0, 0.88, 12.75, 0.6047, 0.2014 + 30000.0, 0.88, 12.8, 0.6073, 0.2026 + 30000.0, 0.88, 12.85, 0.6099, 0.2038 + 30000.0, 0.88, 12.9, 0.6125, 0.2051 + 30000.0, 0.88, 12.95, 0.615, 0.2063 + 30000.0, 0.88, 13.0, 0.6176, 0.2074 + 30000.0, 0.88, 13.05, 0.6202, 0.2086 + 30000.0, 0.88, 13.1, 0.6228, 0.2098 + 30000.0, 0.88, 13.15, 0.6254, 0.211 + 30000.0, 0.88, 13.2, 0.6279, 0.2122 + 30000.0, 0.88, 13.25, 0.6305, 0.2133 + 30000.0, 0.88, 13.3, 0.6331, 0.2145 + 30000.0, 0.88, 13.35, 0.6357, 0.2157 + 30000.0, 0.88, 13.4, 0.6383, 0.2168 + 30000.0, 0.88, 13.45, 0.6409, 0.218 + 30000.0, 0.88, 13.5, 0.6435, 0.2191 + 30000.0, 0.88, 13.55, 0.6461, 0.2202 + 30000.0, 0.88, 13.6, 0.6487, 0.2214 + 30000.0, 0.88, 13.65, 0.6513, 0.2225 + 30000.0, 0.88, 13.7, 0.6539, 0.2236 + 30000.0, 0.88, 13.75, 0.6565, 0.2247 + 30000.0, 0.88, 13.8, 0.6591, 0.2258 + 30000.0, 0.88, 13.85, 0.6618, 0.2269 + 30000.0, 0.88, 13.9, 0.6644, 0.2279 + 30000.0, 0.88, 13.95, 0.667, 0.229 + 30000.0, 0.88, 14.0, 0.6696, 0.2301 + 30000.0, 0.88, 14.05, 0.6722, 0.2311 + 30000.0, 0.88, 14.1, 0.6749, 0.2322 + 30000.0, 0.88, 14.15, 0.6775, 0.2332 + 30000.0, 0.88, 14.2, 0.6801, 0.2343 + 30000.0, 0.88, 14.25, 0.6828, 0.2353 + 30000.0, 0.88, 14.3, 0.6854, 0.2363 + 30000.0, 0.88, 14.35, 0.688, 0.2373 + 30000.0, 0.88, 14.4, 0.6907, 0.2383 + 30000.0, 0.88, 14.45, 0.6933, 0.2393 + 30000.0, 0.88, 14.5, 0.696, 0.2403 + 30000.0, 0.88, 14.55, 0.6986, 0.2413 + 30000.0, 0.88, 14.6, 0.7013, 0.2422 + 30000.0, 0.88, 14.65, 0.7039, 0.2432 + 30000.0, 0.88, 14.7, 0.7066, 0.2441 + 30000.0, 0.88, 14.75, 0.7093, 0.2451 + 30000.0, 0.88, 14.8, 0.7119, 0.246 + 30000.0, 0.88, 14.85, 0.7146, 0.2469 + 30000.0, 0.88, 14.9, 0.7173, 0.2478 + 30000.0, 0.88, 14.95, 0.7199, 0.2487 + 30000.0, 0.88, 15.0, 0.7226, 0.2496 + 30000.0, 0.88, 15.05, 0.7253, 0.2505 + 30000.0, 0.93, 0.0, -0.2189, 0.05964 + 30000.0, 0.93, 0.05, -0.2122, 0.05915 + 30000.0, 0.93, 0.1, -0.2055, 0.05863 + 30000.0, 0.93, 0.15, -0.199, 0.05808 + 30000.0, 0.93, 0.2, -0.1926, 0.05749 + 30000.0, 0.93, 0.25, -0.1863, 0.05688 + 30000.0, 0.93, 0.3, -0.1802, 0.05623 + 30000.0, 0.93, 0.35, -0.1741, 0.05555 + 30000.0, 0.93, 0.4, -0.1682, 0.05484 + 30000.0, 0.93, 0.45, -0.1624, 0.05411 + 30000.0, 0.93, 0.5, -0.1566, 0.05335 + 30000.0, 0.93, 0.55, -0.151, 0.05257 + 30000.0, 0.93, 0.6, -0.1455, 0.05177 + 30000.0, 0.93, 0.65, -0.14, 0.05094 + 30000.0, 0.93, 0.7, -0.1347, 0.05009 + 30000.0, 0.93, 0.75, -0.1294, 0.04923 + 30000.0, 0.93, 0.8, -0.1243, 0.04834 + 30000.0, 0.93, 0.85, -0.1192, 0.04744 + 30000.0, 0.93, 0.9, -0.1142, 0.04653 + 30000.0, 0.93, 0.95, -0.1093, 0.0456 + 30000.0, 0.93, 1.0, -0.1044, 0.04466 + 30000.0, 0.93, 1.05, -0.09966, 0.04371 + 30000.0, 0.93, 1.1, -0.09496, 0.04274 + 30000.0, 0.93, 1.15, -0.09033, 0.04177 + 30000.0, 0.93, 1.2, -0.08576, 0.04079 + 30000.0, 0.93, 1.25, -0.08126, 0.03981 + 30000.0, 0.93, 1.3, -0.07682, 0.03882 + 30000.0, 0.93, 1.35, -0.07243, 0.03782 + 30000.0, 0.93, 1.4, -0.0681, 0.03683 + 30000.0, 0.93, 1.45, -0.06382, 0.03583 + 30000.0, 0.93, 1.5, -0.05959, 0.03483 + 30000.0, 0.93, 1.55, -0.05541, 0.03383 + 30000.0, 0.93, 1.6, -0.05127, 0.03284 + 30000.0, 0.93, 1.65, -0.04717, 0.03185 + 30000.0, 0.93, 1.7, -0.04311, 0.03087 + 30000.0, 0.93, 1.75, -0.03909, 0.02989 + 30000.0, 0.93, 1.8, -0.0351, 0.02892 + 30000.0, 0.93, 1.85, -0.03114, 0.02796 + 30000.0, 0.93, 1.9, -0.0272, 0.02701 + 30000.0, 0.93, 1.95, -0.02329, 0.02607 + 30000.0, 0.93, 2.0, -0.0194, 0.02514 + 30000.0, 0.93, 2.05, -0.01554, 0.02423 + 30000.0, 0.93, 2.1, -0.01168, 0.02333 + 30000.0, 0.93, 2.15, -0.007845, 0.02245 + 30000.0, 0.93, 2.2, -0.004017, 0.02159 + 30000.0, 0.93, 2.25, -0.0001983, 0.02075 + 30000.0, 0.93, 2.3, 0.003615, 0.01993 + 30000.0, 0.93, 2.35, 0.007426, 0.01912 + 30000.0, 0.93, 2.4, 0.01124, 0.01835 + 30000.0, 0.93, 2.45, 0.01505, 0.01759 + 30000.0, 0.93, 2.5, 0.01887, 0.01687 + 30000.0, 0.93, 2.55, 0.0227, 0.01617 + 30000.0, 0.93, 2.6, 0.02653, 0.01549 + 30000.0, 0.93, 2.65, 0.03038, 0.01485 + 30000.0, 0.93, 2.7, 0.03425, 0.01424 + 30000.0, 0.93, 2.75, 0.03814, 0.01366 + 30000.0, 0.93, 2.8, 0.04205, 0.01311 + 30000.0, 0.93, 2.85, 0.04598, 0.0126 + 30000.0, 0.93, 2.9, 0.04994, 0.01212 + 30000.0, 0.93, 2.95, 0.05393, 0.01168 + 30000.0, 0.93, 3.0, 0.05795, 0.01128 + 30000.0, 0.93, 3.05, 0.06201, 0.01092 + 30000.0, 0.93, 3.1, 0.0661, 0.0106 + 30000.0, 0.93, 3.15, 0.07024, 0.01032 + 30000.0, 0.93, 3.2, 0.07442, 0.01008 + 30000.0, 0.93, 3.25, 0.07865, 0.009894 + 30000.0, 0.93, 3.3, 0.08292, 0.00975 + 30000.0, 0.93, 3.35, 0.08725, 0.009652 + 30000.0, 0.93, 3.4, 0.09163, 0.009604 + 30000.0, 0.93, 3.45, 0.09607, 0.009605 + 30000.0, 0.93, 3.5, 0.1006, 0.009658 + 30000.0, 0.93, 3.55, 0.1051, 0.009762 + 30000.0, 0.93, 3.6, 0.1098, 0.009921 + 30000.0, 0.93, 3.65, 0.1144, 0.01013 + 30000.0, 0.93, 3.7, 0.1192, 0.0104 + 30000.0, 0.93, 3.75, 0.1241, 0.01073 + 30000.0, 0.93, 3.8, 0.129, 0.01112 + 30000.0, 0.93, 3.85, 0.134, 0.01156 + 30000.0, 0.93, 3.9, 0.139, 0.01207 + 30000.0, 0.93, 3.95, 0.1442, 0.01264 + 30000.0, 0.93, 4.0, 0.1494, 0.01327 + 30000.0, 0.93, 4.05, 0.1576, 0.01417 + 30000.0, 0.93, 4.1, 0.1658, 0.01513 + 30000.0, 0.93, 4.15, 0.1738, 0.01614 + 30000.0, 0.93, 4.2, 0.1817, 0.0172 + 30000.0, 0.93, 4.25, 0.1895, 0.01832 + 30000.0, 0.93, 4.3, 0.1971, 0.01949 + 30000.0, 0.93, 4.35, 0.2045, 0.02071 + 30000.0, 0.93, 4.4, 0.2118, 0.02199 + 30000.0, 0.93, 4.45, 0.2188, 0.02332 + 30000.0, 0.93, 4.5, 0.2256, 0.0247 + 30000.0, 0.93, 4.55, 0.2322, 0.02613 + 30000.0, 0.93, 4.6, 0.2385, 0.02762 + 30000.0, 0.93, 4.65, 0.2445, 0.02915 + 30000.0, 0.93, 4.7, 0.2502, 0.03074 + 30000.0, 0.93, 4.75, 0.2556, 0.03237 + 30000.0, 0.93, 4.8, 0.2606, 0.03406 + 30000.0, 0.93, 4.85, 0.2653, 0.0358 + 30000.0, 0.93, 4.9, 0.2696, 0.03759 + 30000.0, 0.93, 4.95, 0.2734, 0.03942 + 30000.0, 0.93, 5.0, 0.2769, 0.04131 + 30000.0, 0.93, 5.05, 0.2771, 0.04315 + 30000.0, 0.93, 5.1, 0.277, 0.04504 + 30000.0, 0.93, 5.15, 0.2764, 0.04697 + 30000.0, 0.93, 5.2, 0.2755, 0.04897 + 30000.0, 0.93, 5.25, 0.2742, 0.05101 + 30000.0, 0.93, 5.3, 0.2725, 0.05311 + 30000.0, 0.93, 5.35, 0.2706, 0.05527 + 30000.0, 0.93, 5.4, 0.2684, 0.05748 + 30000.0, 0.93, 5.45, 0.2659, 0.05975 + 30000.0, 0.93, 5.5, 0.2632, 0.06208 + 30000.0, 0.93, 5.55, 0.2602, 0.06447 + 30000.0, 0.93, 5.6, 0.257, 0.06693 + 30000.0, 0.93, 5.65, 0.2537, 0.06945 + 30000.0, 0.93, 5.7, 0.2502, 0.07203 + 30000.0, 0.93, 5.75, 0.2466, 0.07467 + 30000.0, 0.93, 5.8, 0.2428, 0.07739 + 30000.0, 0.93, 5.85, 0.239, 0.08017 + 30000.0, 0.93, 5.9, 0.2351, 0.08302 + 30000.0, 0.93, 5.95, 0.2311, 0.08594 + 30000.0, 0.93, 6.0, 0.2272, 0.08893 + 30000.0, 0.93, 6.05, 0.2269, 0.09244 + 30000.0, 0.93, 6.1, 0.2269, 0.09605 + 30000.0, 0.93, 6.15, 0.227, 0.09974 + 30000.0, 0.93, 6.2, 0.2273, 0.1035 + 30000.0, 0.93, 6.25, 0.2278, 0.1074 + 30000.0, 0.93, 6.3, 0.2284, 0.1113 + 30000.0, 0.93, 6.35, 0.2291, 0.1154 + 30000.0, 0.93, 6.4, 0.23, 0.1195 + 30000.0, 0.93, 6.45, 0.2311, 0.1237 + 30000.0, 0.93, 6.5, 0.2322, 0.1279 + 30000.0, 0.93, 6.55, 0.2335, 0.1323 + 30000.0, 0.93, 6.6, 0.2349, 0.1367 + 30000.0, 0.93, 6.65, 0.2365, 0.1412 + 30000.0, 0.93, 6.7, 0.2381, 0.1457 + 30000.0, 0.93, 6.75, 0.2398, 0.1503 + 30000.0, 0.93, 6.8, 0.2416, 0.155 + 30000.0, 0.93, 6.85, 0.2436, 0.1598 + 30000.0, 0.93, 6.9, 0.2456, 0.1646 + 30000.0, 0.93, 6.95, 0.2477, 0.1694 + 30000.0, 0.93, 7.0, 0.2498, 0.1743 + 30000.0, 0.93, 7.05, 0.2521, 0.1793 + 30000.0, 0.93, 7.1, 0.2544, 0.1843 + 30000.0, 0.93, 7.15, 0.2567, 0.1893 + 30000.0, 0.93, 7.2, 0.2591, 0.1944 + 30000.0, 0.93, 7.25, 0.2616, 0.1996 + 30000.0, 0.93, 7.3, 0.2641, 0.2048 + 30000.0, 0.93, 7.35, 0.2666, 0.21 + 30000.0, 0.93, 7.4, 0.2692, 0.2153 + 30000.0, 0.93, 7.45, 0.2718, 0.2206 + 30000.0, 0.93, 7.5, 0.2744, 0.2259 + 30000.0, 0.93, 7.55, 0.277, 0.2313 + 30000.0, 0.93, 7.6, 0.2797, 0.2367 + 30000.0, 0.93, 7.65, 0.2823, 0.2421 + 30000.0, 0.93, 7.7, 0.2849, 0.2476 + 30000.0, 0.93, 7.75, 0.2876, 0.253 + 30000.0, 0.93, 7.8, 0.2902, 0.2585 + 30000.0, 0.93, 7.85, 0.2928, 0.264 + 30000.0, 0.93, 7.9, 0.2953, 0.2696 + 30000.0, 0.93, 7.95, 0.2979, 0.2751 + 30000.0, 0.93, 8.0, 0.3004, 0.2807 + 30000.0, 0.93, 8.05, 0.3011, 0.2857 + 30000.0, 0.93, 8.1, 0.3018, 0.2907 + 30000.0, 0.93, 8.15, 0.3024, 0.2957 + 30000.0, 0.93, 8.2, 0.303, 0.3007 + 30000.0, 0.93, 8.25, 0.3036, 0.3058 + 30000.0, 0.93, 8.3, 0.3041, 0.3108 + 30000.0, 0.93, 8.35, 0.3046, 0.3159 + 30000.0, 0.93, 8.4, 0.3051, 0.3209 + 30000.0, 0.93, 8.45, 0.3055, 0.326 + 30000.0, 0.93, 8.5, 0.3059, 0.3311 + 30000.0, 0.93, 8.55, 0.3063, 0.3362 + 30000.0, 0.93, 8.6, 0.3066, 0.3413 + 30000.0, 0.93, 8.65, 0.3069, 0.3465 + 30000.0, 0.93, 8.7, 0.3072, 0.3516 + 30000.0, 0.93, 8.75, 0.3074, 0.3567 + 30000.0, 0.93, 8.8, 0.3077, 0.3619 + 30000.0, 0.93, 8.85, 0.3078, 0.3671 + 30000.0, 0.93, 8.9, 0.308, 0.3722 + 30000.0, 0.93, 8.95, 0.3081, 0.3774 + 30000.0, 0.93, 9.0, 0.3082, 0.3826 + 30000.0, 0.93, 9.05, 0.3083, 0.3879 + 30000.0, 0.93, 9.1, 0.3084, 0.3931 + 30000.0, 0.93, 9.15, 0.3084, 0.3983 + 30000.0, 0.93, 9.2, 0.3085, 0.4036 + 30000.0, 0.93, 9.25, 0.3085, 0.4088 + 30000.0, 0.93, 9.3, 0.3085, 0.4141 + 30000.0, 0.93, 9.35, 0.3084, 0.4194 + 30000.0, 0.93, 9.4, 0.3084, 0.4247 + 30000.0, 0.93, 9.45, 0.3083, 0.43 + 30000.0, 0.93, 9.5, 0.3082, 0.4353 + 30000.0, 0.93, 9.55, 0.3081, 0.4406 + 30000.0, 0.93, 9.6, 0.308, 0.446 + 30000.0, 0.93, 9.65, 0.3079, 0.4513 + 30000.0, 0.93, 9.7, 0.3078, 0.4567 + 30000.0, 0.93, 9.75, 0.3077, 0.4621 + 30000.0, 0.93, 9.8, 0.3075, 0.4675 + 30000.0, 0.93, 9.85, 0.3073, 0.4729 + 30000.0, 0.93, 9.9, 0.3072, 0.4783 + 30000.0, 0.93, 9.95, 0.307, 0.4837 + 30000.0, 0.93, 10.0, 0.3068, 0.4892 + 30000.0, 0.93, 10.05, 0.3068, 0.4948 + 30000.0, 0.93, 10.1, 0.3068, 0.5005 + 30000.0, 0.93, 10.15, 0.3068, 0.5062 + 30000.0, 0.93, 10.2, 0.3068, 0.5119 + 30000.0, 0.93, 10.25, 0.3068, 0.5176 + 30000.0, 0.93, 10.3, 0.3068, 0.5233 + 30000.0, 0.93, 10.35, 0.3067, 0.529 + 30000.0, 0.93, 10.4, 0.3067, 0.5348 + 30000.0, 0.93, 10.45, 0.3067, 0.5405 + 30000.0, 0.93, 10.5, 0.3067, 0.5463 + 30000.0, 0.93, 10.55, 0.3066, 0.552 + 30000.0, 0.93, 10.6, 0.3066, 0.5578 + 30000.0, 0.93, 10.65, 0.3065, 0.5635 + 30000.0, 0.93, 10.7, 0.3065, 0.5693 + 30000.0, 0.93, 10.75, 0.3065, 0.575 + 30000.0, 0.93, 10.8, 0.3064, 0.5808 + 30000.0, 0.93, 10.85, 0.3064, 0.5865 + 30000.0, 0.93, 10.9, 0.3063, 0.5923 + 30000.0, 0.93, 10.95, 0.3063, 0.5981 + 30000.0, 0.93, 11.0, 0.3062, 0.6038 + 30000.0, 0.93, 11.05, 0.3062, 0.6096 + 30000.0, 0.93, 11.1, 0.3061, 0.6153 + 30000.0, 0.93, 11.15, 0.3061, 0.621 + 30000.0, 0.93, 11.2, 0.3061, 0.6268 + 30000.0, 0.93, 11.25, 0.306, 0.6325 + 30000.0, 0.93, 11.3, 0.306, 0.6382 + 30000.0, 0.93, 11.35, 0.3059, 0.6439 + 30000.0, 0.93, 11.4, 0.3059, 0.6496 + 30000.0, 0.93, 11.45, 0.3058, 0.6553 + 30000.0, 0.93, 11.5, 0.3058, 0.661 + 30000.0, 0.93, 11.55, 0.3058, 0.6667 + 30000.0, 0.93, 11.6, 0.3057, 0.6724 + 30000.0, 0.93, 11.65, 0.3057, 0.678 + 30000.0, 0.93, 11.7, 0.3057, 0.6837 + 30000.0, 0.93, 11.75, 0.3057, 0.6893 + 30000.0, 0.93, 11.8, 0.3056, 0.6949 + 30000.0, 0.93, 11.85, 0.3056, 0.7005 + 30000.0, 0.93, 11.9, 0.3056, 0.7061 + 30000.0, 0.93, 11.95, 0.3056, 0.7116 + 30000.0, 0.93, 12.0, 0.3056, 0.7172 + 30000.0, 0.93, 12.05, 0.3056, 0.7227 + 30000.0, 0.93, 12.1, 0.3056, 0.7282 + 30000.0, 0.93, 12.15, 0.3056, 0.7337 + 30000.0, 0.93, 12.2, 0.3056, 0.7392 + 30000.0, 0.93, 12.25, 0.3057, 0.7446 + 30000.0, 0.93, 12.3, 0.3057, 0.75 + 30000.0, 0.93, 12.35, 0.3057, 0.7554 + 30000.0, 0.93, 12.4, 0.3058, 0.7608 + 30000.0, 0.93, 12.45, 0.3058, 0.7661 + 30000.0, 0.93, 12.5, 0.3059, 0.7715 + 30000.0, 0.93, 12.55, 0.3059, 0.7768 + 30000.0, 0.93, 12.6, 0.306, 0.782 + 30000.0, 0.93, 12.65, 0.3061, 0.7873 + 30000.0, 0.93, 12.7, 0.3062, 0.7925 + 30000.0, 0.93, 12.75, 0.3062, 0.7977 + 30000.0, 0.93, 12.8, 0.3063, 0.8028 + 30000.0, 0.93, 12.85, 0.3064, 0.8079 + 30000.0, 0.93, 12.9, 0.3066, 0.813 + 30000.0, 0.93, 12.95, 0.3067, 0.8181 + 30000.0, 0.93, 13.0, 0.3068, 0.8231 + 30000.0, 0.93, 13.05, 0.307, 0.8281 + 30000.0, 0.93, 13.1, 0.3071, 0.8331 + 30000.0, 0.93, 13.15, 0.3073, 0.838 + 30000.0, 0.93, 13.2, 0.3075, 0.8429 + 30000.0, 0.93, 13.25, 0.3076, 0.8477 + 30000.0, 0.93, 13.3, 0.3078, 0.8525 + 30000.0, 0.93, 13.35, 0.308, 0.8573 + 30000.0, 0.93, 13.4, 0.3082, 0.862 + 30000.0, 0.93, 13.45, 0.3085, 0.8667 + 30000.0, 0.93, 13.5, 0.3087, 0.8714 + 30000.0, 0.93, 13.55, 0.309, 0.876 + 30000.0, 0.93, 13.6, 0.3092, 0.8805 + 30000.0, 0.93, 13.65, 0.3095, 0.8851 + 30000.0, 0.93, 13.7, 0.3098, 0.8895 + 30000.0, 0.93, 13.75, 0.3101, 0.894 + 30000.0, 0.93, 13.8, 0.3104, 0.8984 + 30000.0, 0.93, 13.85, 0.3107, 0.9027 + 30000.0, 0.93, 13.9, 0.311, 0.907 + 30000.0, 0.93, 13.95, 0.3114, 0.9113 + 30000.0, 0.93, 14.0, 0.3118, 0.9155 + 30000.0, 0.93, 14.05, 0.3121, 0.9196 + 30000.0, 0.93, 14.1, 0.3125, 0.9237 + 30000.0, 0.93, 14.15, 0.3129, 0.9278 + 30000.0, 0.93, 14.2, 0.3134, 0.9318 + 30000.0, 0.93, 14.25, 0.3138, 0.9357 + 30000.0, 0.93, 14.3, 0.3143, 0.9396 + 30000.0, 0.93, 14.35, 0.3147, 0.9434 + 30000.0, 0.93, 14.4, 0.3152, 0.9472 + 30000.0, 0.93, 14.45, 0.3157, 0.9509 + 30000.0, 0.93, 14.5, 0.3162, 0.9546 + 30000.0, 0.93, 14.55, 0.3168, 0.9582 + 30000.0, 0.93, 14.6, 0.3173, 0.9618 + 30000.0, 0.93, 14.65, 0.3179, 0.9653 + 30000.0, 0.93, 14.7, 0.3185, 0.9687 + 30000.0, 0.93, 14.75, 0.3191, 0.9721 + 30000.0, 0.93, 14.8, 0.3197, 0.9754 + 30000.0, 0.93, 14.85, 0.3203, 0.9787 + 30000.0, 0.93, 14.9, 0.321, 0.9819 + 30000.0, 0.93, 14.95, 0.3216, 0.985 + 30000.0, 0.93, 15.0, 0.3223, 0.9881 + 30000.0, 0.93, 15.05, 0.323, 0.9911 + 41000.0, 0.23, 0.0, -0.1539, 0.003657 + 41000.0, 0.23, 0.05, -0.1511, 0.003707 + 41000.0, 0.23, 0.1, -0.1483, 0.003755 + 41000.0, 0.23, 0.15, -0.1455, 0.003801 + 41000.0, 0.23, 0.2, -0.1427, 0.003846 + 41000.0, 0.23, 0.25, -0.1399, 0.00389 + 41000.0, 0.23, 0.3, -0.1371, 0.003932 + 41000.0, 0.23, 0.35, -0.1343, 0.003972 + 41000.0, 0.23, 0.4, -0.1315, 0.004011 + 41000.0, 0.23, 0.45, -0.1288, 0.004048 + 41000.0, 0.23, 0.5, -0.126, 0.004084 + 41000.0, 0.23, 0.55, -0.1232, 0.004119 + 41000.0, 0.23, 0.6, -0.1204, 0.004152 + 41000.0, 0.23, 0.65, -0.1176, 0.004185 + 41000.0, 0.23, 0.7, -0.1149, 0.004215 + 41000.0, 0.23, 0.75, -0.1121, 0.004245 + 41000.0, 0.23, 0.8, -0.1093, 0.004274 + 41000.0, 0.23, 0.85, -0.1066, 0.004301 + 41000.0, 0.23, 0.9, -0.1038, 0.004327 + 41000.0, 0.23, 0.95, -0.101, 0.004352 + 41000.0, 0.23, 1.0, -0.09826, 0.004376 + 41000.0, 0.23, 1.05, -0.0955, 0.0044 + 41000.0, 0.23, 1.1, -0.09274, 0.004422 + 41000.0, 0.23, 1.15, -0.08998, 0.004443 + 41000.0, 0.23, 1.2, -0.08722, 0.004463 + 41000.0, 0.23, 1.25, -0.08447, 0.004483 + 41000.0, 0.23, 1.3, -0.08171, 0.004501 + 41000.0, 0.23, 1.35, -0.07896, 0.004519 + 41000.0, 0.23, 1.4, -0.0762, 0.004536 + 41000.0, 0.23, 1.45, -0.07345, 0.004553 + 41000.0, 0.23, 1.5, -0.0707, 0.004568 + 41000.0, 0.23, 1.55, -0.06795, 0.004583 + 41000.0, 0.23, 1.6, -0.0652, 0.004598 + 41000.0, 0.23, 1.65, -0.06245, 0.004612 + 41000.0, 0.23, 1.7, -0.0597, 0.004625 + 41000.0, 0.23, 1.75, -0.05695, 0.004638 + 41000.0, 0.23, 1.8, -0.0542, 0.00465 + 41000.0, 0.23, 1.85, -0.05145, 0.004662 + 41000.0, 0.23, 1.9, -0.04871, 0.004673 + 41000.0, 0.23, 1.95, -0.04596, 0.004684 + 41000.0, 0.23, 2.0, -0.04321, 0.004695 + 41000.0, 0.23, 2.05, -0.04046, 0.004705 + 41000.0, 0.23, 2.1, -0.03771, 0.004715 + 41000.0, 0.23, 2.15, -0.03497, 0.004725 + 41000.0, 0.23, 2.2, -0.03222, 0.004735 + 41000.0, 0.23, 2.25, -0.02947, 0.004744 + 41000.0, 0.23, 2.3, -0.02672, 0.004754 + 41000.0, 0.23, 2.35, -0.02397, 0.004763 + 41000.0, 0.23, 2.4, -0.02122, 0.004772 + 41000.0, 0.23, 2.45, -0.01847, 0.004782 + 41000.0, 0.23, 2.5, -0.01572, 0.004791 + 41000.0, 0.23, 2.55, -0.01297, 0.0048 + 41000.0, 0.23, 2.6, -0.01022, 0.004809 + 41000.0, 0.23, 2.65, -0.007462, 0.004819 + 41000.0, 0.23, 2.7, -0.004707, 0.004828 + 41000.0, 0.23, 2.75, -0.001952, 0.004838 + 41000.0, 0.23, 2.8, 0.0008048, 0.004848 + 41000.0, 0.23, 2.85, 0.003563, 0.004858 + 41000.0, 0.23, 2.9, 0.006322, 0.004869 + 41000.0, 0.23, 2.95, 0.009082, 0.004879 + 41000.0, 0.23, 3.0, 0.01184, 0.004891 + 41000.0, 0.23, 3.05, 0.01461, 0.004902 + 41000.0, 0.23, 3.1, 0.01737, 0.004914 + 41000.0, 0.23, 3.15, 0.02014, 0.004926 + 41000.0, 0.23, 3.2, 0.02291, 0.004939 + 41000.0, 0.23, 3.25, 0.02568, 0.004953 + 41000.0, 0.23, 3.3, 0.02845, 0.004967 + 41000.0, 0.23, 3.35, 0.03122, 0.004981 + 41000.0, 0.23, 3.4, 0.034, 0.004997 + 41000.0, 0.23, 3.45, 0.03678, 0.005013 + 41000.0, 0.23, 3.5, 0.03956, 0.005029 + 41000.0, 0.23, 3.55, 0.04234, 0.005047 + 41000.0, 0.23, 3.6, 0.04512, 0.005065 + 41000.0, 0.23, 3.65, 0.04791, 0.005084 + 41000.0, 0.23, 3.7, 0.0507, 0.005103 + 41000.0, 0.23, 3.75, 0.05349, 0.005124 + 41000.0, 0.23, 3.8, 0.05629, 0.005145 + 41000.0, 0.23, 3.85, 0.05908, 0.005168 + 41000.0, 0.23, 3.9, 0.06188, 0.005191 + 41000.0, 0.23, 3.95, 0.06468, 0.005216 + 41000.0, 0.23, 4.0, 0.06749, 0.005241 + 41000.0, 0.23, 4.05, 0.07033, 0.005273 + 41000.0, 0.23, 4.1, 0.07318, 0.005305 + 41000.0, 0.23, 4.15, 0.07602, 0.005338 + 41000.0, 0.23, 4.2, 0.07887, 0.005372 + 41000.0, 0.23, 4.25, 0.08171, 0.005406 + 41000.0, 0.23, 4.3, 0.08456, 0.005442 + 41000.0, 0.23, 4.35, 0.0874, 0.005478 + 41000.0, 0.23, 4.4, 0.09025, 0.005516 + 41000.0, 0.23, 4.45, 0.0931, 0.005554 + 41000.0, 0.23, 4.5, 0.09594, 0.005592 + 41000.0, 0.23, 4.55, 0.09878, 0.005632 + 41000.0, 0.23, 4.6, 0.1016, 0.005672 + 41000.0, 0.23, 4.65, 0.1045, 0.005714 + 41000.0, 0.23, 4.7, 0.1073, 0.005756 + 41000.0, 0.23, 4.75, 0.1102, 0.005799 + 41000.0, 0.23, 4.8, 0.113, 0.005843 + 41000.0, 0.23, 4.85, 0.1158, 0.005887 + 41000.0, 0.23, 4.9, 0.1187, 0.005933 + 41000.0, 0.23, 4.95, 0.1215, 0.005979 + 41000.0, 0.23, 5.0, 0.1243, 0.006026 + 41000.0, 0.23, 5.05, 0.1271, 0.006073 + 41000.0, 0.23, 5.1, 0.13, 0.006122 + 41000.0, 0.23, 5.15, 0.1328, 0.006171 + 41000.0, 0.23, 5.2, 0.1356, 0.006221 + 41000.0, 0.23, 5.25, 0.1384, 0.006271 + 41000.0, 0.23, 5.3, 0.1412, 0.006323 + 41000.0, 0.23, 5.35, 0.144, 0.006375 + 41000.0, 0.23, 5.4, 0.1468, 0.006429 + 41000.0, 0.23, 5.45, 0.1496, 0.006483 + 41000.0, 0.23, 5.5, 0.1524, 0.006538 + 41000.0, 0.23, 5.55, 0.1552, 0.006593 + 41000.0, 0.23, 5.6, 0.158, 0.00665 + 41000.0, 0.23, 5.65, 0.1607, 0.006708 + 41000.0, 0.23, 5.7, 0.1635, 0.006766 + 41000.0, 0.23, 5.75, 0.1663, 0.006825 + 41000.0, 0.23, 5.8, 0.1691, 0.006885 + 41000.0, 0.23, 5.85, 0.1718, 0.006946 + 41000.0, 0.23, 5.9, 0.1746, 0.007008 + 41000.0, 0.23, 5.95, 0.1774, 0.00707 + 41000.0, 0.23, 6.0, 0.1801, 0.007134 + 41000.0, 0.23, 6.05, 0.1829, 0.007189 + 41000.0, 0.23, 6.1, 0.1857, 0.007245 + 41000.0, 0.23, 6.15, 0.1884, 0.007302 + 41000.0, 0.23, 6.2, 0.1912, 0.007359 + 41000.0, 0.23, 6.25, 0.1939, 0.007417 + 41000.0, 0.23, 6.3, 0.1967, 0.007476 + 41000.0, 0.23, 6.35, 0.1994, 0.007535 + 41000.0, 0.23, 6.4, 0.2022, 0.007596 + 41000.0, 0.23, 6.45, 0.2049, 0.007657 + 41000.0, 0.23, 6.5, 0.2076, 0.00772 + 41000.0, 0.23, 6.55, 0.2104, 0.007783 + 41000.0, 0.23, 6.6, 0.2131, 0.007848 + 41000.0, 0.23, 6.65, 0.2158, 0.007914 + 41000.0, 0.23, 6.7, 0.2185, 0.007982 + 41000.0, 0.23, 6.75, 0.2212, 0.008051 + 41000.0, 0.23, 6.8, 0.2239, 0.008121 + 41000.0, 0.23, 6.85, 0.2266, 0.008193 + 41000.0, 0.23, 6.9, 0.2293, 0.008266 + 41000.0, 0.23, 6.95, 0.2319, 0.008341 + 41000.0, 0.23, 7.0, 0.2346, 0.008418 + 41000.0, 0.23, 7.05, 0.2372, 0.008496 + 41000.0, 0.23, 7.1, 0.2399, 0.008576 + 41000.0, 0.23, 7.15, 0.2425, 0.008659 + 41000.0, 0.23, 7.2, 0.2451, 0.008743 + 41000.0, 0.23, 7.25, 0.2477, 0.008829 + 41000.0, 0.23, 7.3, 0.2503, 0.008918 + 41000.0, 0.23, 7.35, 0.2529, 0.009008 + 41000.0, 0.23, 7.4, 0.2555, 0.009101 + 41000.0, 0.23, 7.45, 0.2581, 0.009196 + 41000.0, 0.23, 7.5, 0.2606, 0.009294 + 41000.0, 0.23, 7.55, 0.2632, 0.009394 + 41000.0, 0.23, 7.6, 0.2657, 0.009497 + 41000.0, 0.23, 7.65, 0.2683, 0.009602 + 41000.0, 0.23, 7.7, 0.2708, 0.00971 + 41000.0, 0.23, 7.75, 0.2733, 0.00982 + 41000.0, 0.23, 7.8, 0.2758, 0.009934 + 41000.0, 0.23, 7.85, 0.2782, 0.01005 + 41000.0, 0.23, 7.9, 0.2807, 0.01017 + 41000.0, 0.23, 7.95, 0.2831, 0.01029 + 41000.0, 0.23, 8.0, 0.2856, 0.01042 + 41000.0, 0.23, 8.05, 0.2879, 0.01054 + 41000.0, 0.23, 8.1, 0.2902, 0.01068 + 41000.0, 0.23, 8.15, 0.2925, 0.01081 + 41000.0, 0.23, 8.2, 0.2948, 0.01095 + 41000.0, 0.23, 8.25, 0.297, 0.01109 + 41000.0, 0.23, 8.3, 0.2993, 0.01123 + 41000.0, 0.23, 8.35, 0.3015, 0.01138 + 41000.0, 0.23, 8.4, 0.3038, 0.01153 + 41000.0, 0.23, 8.45, 0.306, 0.01169 + 41000.0, 0.23, 8.5, 0.3082, 0.01185 + 41000.0, 0.23, 8.55, 0.3104, 0.01201 + 41000.0, 0.23, 8.6, 0.3125, 0.01218 + 41000.0, 0.23, 8.65, 0.3147, 0.01235 + 41000.0, 0.23, 8.7, 0.3169, 0.01253 + 41000.0, 0.23, 8.75, 0.319, 0.0127 + 41000.0, 0.23, 8.8, 0.3211, 0.01289 + 41000.0, 0.23, 8.85, 0.3232, 0.01308 + 41000.0, 0.23, 8.9, 0.3253, 0.01327 + 41000.0, 0.23, 8.95, 0.3274, 0.01346 + 41000.0, 0.23, 9.0, 0.3295, 0.01366 + 41000.0, 0.23, 9.05, 0.3315, 0.01387 + 41000.0, 0.23, 9.1, 0.3336, 0.01408 + 41000.0, 0.23, 9.15, 0.3356, 0.01429 + 41000.0, 0.23, 9.2, 0.3377, 0.01451 + 41000.0, 0.23, 9.25, 0.3397, 0.01474 + 41000.0, 0.23, 9.3, 0.3417, 0.01497 + 41000.0, 0.23, 9.35, 0.3437, 0.0152 + 41000.0, 0.23, 9.4, 0.3456, 0.01544 + 41000.0, 0.23, 9.45, 0.3476, 0.01568 + 41000.0, 0.23, 9.5, 0.3496, 0.01593 + 41000.0, 0.23, 9.55, 0.3515, 0.01618 + 41000.0, 0.23, 9.6, 0.3535, 0.01644 + 41000.0, 0.23, 9.65, 0.3554, 0.01671 + 41000.0, 0.23, 9.7, 0.3573, 0.01698 + 41000.0, 0.23, 9.75, 0.3592, 0.01725 + 41000.0, 0.23, 9.8, 0.3611, 0.01753 + 41000.0, 0.23, 9.85, 0.363, 0.01782 + 41000.0, 0.23, 9.9, 0.3648, 0.01811 + 41000.0, 0.23, 9.95, 0.3667, 0.01841 + 41000.0, 0.23, 10.0, 0.3685, 0.01872 + 41000.0, 0.23, 10.05, 0.3705, 0.01909 + 41000.0, 0.23, 10.1, 0.3724, 0.01947 + 41000.0, 0.23, 10.15, 0.3743, 0.01985 + 41000.0, 0.23, 10.2, 0.3762, 0.02024 + 41000.0, 0.23, 10.25, 0.378, 0.02064 + 41000.0, 0.23, 10.3, 0.3799, 0.02104 + 41000.0, 0.23, 10.35, 0.3818, 0.02145 + 41000.0, 0.23, 10.4, 0.3836, 0.02186 + 41000.0, 0.23, 10.45, 0.3854, 0.02227 + 41000.0, 0.23, 10.5, 0.3873, 0.02269 + 41000.0, 0.23, 10.55, 0.3891, 0.02311 + 41000.0, 0.23, 10.6, 0.3909, 0.02354 + 41000.0, 0.23, 10.65, 0.3926, 0.02397 + 41000.0, 0.23, 10.7, 0.3944, 0.0244 + 41000.0, 0.23, 10.75, 0.3962, 0.02484 + 41000.0, 0.23, 10.8, 0.3979, 0.02528 + 41000.0, 0.23, 10.85, 0.3996, 0.02573 + 41000.0, 0.23, 10.9, 0.4014, 0.02618 + 41000.0, 0.23, 10.95, 0.4031, 0.02663 + 41000.0, 0.23, 11.0, 0.4047, 0.02708 + 41000.0, 0.23, 11.05, 0.4064, 0.02754 + 41000.0, 0.23, 11.1, 0.4081, 0.02799 + 41000.0, 0.23, 11.15, 0.4097, 0.02845 + 41000.0, 0.23, 11.2, 0.4113, 0.02891 + 41000.0, 0.23, 11.25, 0.413, 0.02938 + 41000.0, 0.23, 11.3, 0.4146, 0.02984 + 41000.0, 0.23, 11.35, 0.4161, 0.03031 + 41000.0, 0.23, 11.4, 0.4177, 0.03078 + 41000.0, 0.23, 11.45, 0.4193, 0.03125 + 41000.0, 0.23, 11.5, 0.4208, 0.03172 + 41000.0, 0.23, 11.55, 0.4223, 0.03219 + 41000.0, 0.23, 11.6, 0.4238, 0.03266 + 41000.0, 0.23, 11.65, 0.4253, 0.03313 + 41000.0, 0.23, 11.7, 0.4267, 0.0336 + 41000.0, 0.23, 11.75, 0.4282, 0.03408 + 41000.0, 0.23, 11.8, 0.4296, 0.03455 + 41000.0, 0.23, 11.85, 0.431, 0.03502 + 41000.0, 0.23, 11.9, 0.4324, 0.03549 + 41000.0, 0.23, 11.95, 0.4338, 0.03596 + 41000.0, 0.23, 12.0, 0.4352, 0.03643 + 41000.0, 0.23, 12.05, 0.4365, 0.0369 + 41000.0, 0.23, 12.1, 0.4378, 0.03737 + 41000.0, 0.23, 12.15, 0.4391, 0.03783 + 41000.0, 0.23, 12.2, 0.4404, 0.0383 + 41000.0, 0.23, 12.25, 0.4417, 0.03876 + 41000.0, 0.23, 12.3, 0.4429, 0.03923 + 41000.0, 0.23, 12.35, 0.4441, 0.03968 + 41000.0, 0.23, 12.4, 0.4453, 0.04014 + 41000.0, 0.23, 12.45, 0.4465, 0.0406 + 41000.0, 0.23, 12.5, 0.4477, 0.04105 + 41000.0, 0.23, 12.55, 0.4488, 0.0415 + 41000.0, 0.23, 12.6, 0.4499, 0.04195 + 41000.0, 0.23, 12.65, 0.451, 0.04239 + 41000.0, 0.23, 12.7, 0.4521, 0.04283 + 41000.0, 0.23, 12.75, 0.4532, 0.04327 + 41000.0, 0.23, 12.8, 0.4542, 0.04371 + 41000.0, 0.23, 12.85, 0.4552, 0.04414 + 41000.0, 0.23, 12.9, 0.4562, 0.04456 + 41000.0, 0.23, 12.95, 0.4572, 0.04499 + 41000.0, 0.23, 13.0, 0.4581, 0.0454 + 41000.0, 0.23, 13.05, 0.459, 0.04582 + 41000.0, 0.23, 13.1, 0.4599, 0.04623 + 41000.0, 0.23, 13.15, 0.4608, 0.04663 + 41000.0, 0.23, 13.2, 0.4617, 0.04703 + 41000.0, 0.23, 13.25, 0.4625, 0.04743 + 41000.0, 0.23, 13.3, 0.4633, 0.04782 + 41000.0, 0.23, 13.35, 0.4641, 0.0482 + 41000.0, 0.23, 13.4, 0.4648, 0.04858 + 41000.0, 0.23, 13.45, 0.4656, 0.04895 + 41000.0, 0.23, 13.5, 0.4663, 0.04932 + 41000.0, 0.23, 13.55, 0.467, 0.04968 + 41000.0, 0.23, 13.6, 0.4676, 0.05004 + 41000.0, 0.23, 13.65, 0.4682, 0.05038 + 41000.0, 0.23, 13.7, 0.4688, 0.05073 + 41000.0, 0.23, 13.75, 0.4694, 0.05106 + 41000.0, 0.23, 13.8, 0.47, 0.05139 + 41000.0, 0.23, 13.85, 0.4705, 0.05171 + 41000.0, 0.23, 13.9, 0.471, 0.05202 + 41000.0, 0.23, 13.95, 0.4715, 0.05233 + 41000.0, 0.23, 14.0, 0.4719, 0.05263 + 41000.0, 0.23, 14.05, 0.4723, 0.05292 + 41000.0, 0.23, 14.1, 0.4727, 0.0532 + 41000.0, 0.23, 14.15, 0.4731, 0.05348 + 41000.0, 0.23, 14.2, 0.4734, 0.05374 + 41000.0, 0.23, 14.25, 0.4737, 0.054 + 41000.0, 0.23, 14.3, 0.474, 0.05425 + 41000.0, 0.23, 14.35, 0.4743, 0.05449 + 41000.0, 0.23, 14.4, 0.4745, 0.05472 + 41000.0, 0.23, 14.45, 0.4747, 0.05495 + 41000.0, 0.23, 14.5, 0.4749, 0.05516 + 41000.0, 0.23, 14.55, 0.475, 0.05536 + 41000.0, 0.23, 14.6, 0.4751, 0.05556 + 41000.0, 0.23, 14.65, 0.4752, 0.05574 + 41000.0, 0.23, 14.7, 0.4752, 0.05592 + 41000.0, 0.23, 14.75, 0.4752, 0.05608 + 41000.0, 0.23, 14.8, 0.4752, 0.05623 + 41000.0, 0.23, 14.85, 0.4752, 0.05638 + 41000.0, 0.23, 14.9, 0.4751, 0.05651 + 41000.0, 0.23, 14.95, 0.475, 0.05663 + 41000.0, 0.23, 15.0, 0.4749, 0.05674 + 41000.0, 0.23, 15.05, 0.4747, 0.05684 + 41000.0, 0.28, 0.0, -0.1263, -0.02898 + 41000.0, 0.28, 0.05, -0.1256, -0.02855 + 41000.0, 0.28, 0.1, -0.1248, -0.02811 + 41000.0, 0.28, 0.15, -0.1238, -0.02766 + 41000.0, 0.28, 0.2, -0.1226, -0.0272 + 41000.0, 0.28, 0.25, -0.1214, -0.02673 + 41000.0, 0.28, 0.3, -0.12, -0.02625 + 41000.0, 0.28, 0.35, -0.1185, -0.02576 + 41000.0, 0.28, 0.4, -0.1169, -0.02525 + 41000.0, 0.28, 0.45, -0.1151, -0.02474 + 41000.0, 0.28, 0.5, -0.1133, -0.02422 + 41000.0, 0.28, 0.55, -0.1113, -0.02368 + 41000.0, 0.28, 0.6, -0.1092, -0.02314 + 41000.0, 0.28, 0.65, -0.107, -0.0226 + 41000.0, 0.28, 0.7, -0.1048, -0.02204 + 41000.0, 0.28, 0.75, -0.1024, -0.02147 + 41000.0, 0.28, 0.8, -0.09992, -0.0209 + 41000.0, 0.28, 0.85, -0.09737, -0.02033 + 41000.0, 0.28, 0.9, -0.09473, -0.01974 + 41000.0, 0.28, 0.95, -0.092, -0.01915 + 41000.0, 0.28, 1.0, -0.0892, -0.01855 + 41000.0, 0.28, 1.05, -0.08632, -0.01795 + 41000.0, 0.28, 1.1, -0.08337, -0.01735 + 41000.0, 0.28, 1.15, -0.08034, -0.01674 + 41000.0, 0.28, 1.2, -0.07726, -0.01612 + 41000.0, 0.28, 1.25, -0.07411, -0.0155 + 41000.0, 0.28, 1.3, -0.0709, -0.01488 + 41000.0, 0.28, 1.35, -0.06764, -0.01425 + 41000.0, 0.28, 1.4, -0.06432, -0.01363 + 41000.0, 0.28, 1.45, -0.06096, -0.013 + 41000.0, 0.28, 1.5, -0.05755, -0.01237 + 41000.0, 0.28, 1.55, -0.0541, -0.01173 + 41000.0, 0.28, 1.6, -0.05061, -0.0111 + 41000.0, 0.28, 1.65, -0.04709, -0.01046 + 41000.0, 0.28, 1.7, -0.04353, -0.009826 + 41000.0, 0.28, 1.75, -0.03995, -0.00919 + 41000.0, 0.28, 1.8, -0.03634, -0.008555 + 41000.0, 0.28, 1.85, -0.03271, -0.00792 + 41000.0, 0.28, 1.9, -0.02906, -0.007287 + 41000.0, 0.28, 1.95, -0.0254, -0.006655 + 41000.0, 0.28, 2.0, -0.02172, -0.006024 + 41000.0, 0.28, 2.05, -0.01804, -0.005396 + 41000.0, 0.28, 2.1, -0.01436, -0.004771 + 41000.0, 0.28, 2.15, -0.01067, -0.004149 + 41000.0, 0.28, 2.2, -0.006986, -0.00353 + 41000.0, 0.28, 2.25, -0.003308, -0.002914 + 41000.0, 0.28, 2.3, 0.0003613, -0.002303 + 41000.0, 0.28, 2.35, 0.004018, -0.001697 + 41000.0, 0.28, 2.4, 0.007658, -0.001095 + 41000.0, 0.28, 2.45, 0.01128, -0.0004983 + 41000.0, 0.28, 2.5, 0.01488, 9.267e-05 + 41000.0, 0.28, 2.55, 0.01845, 0.0006776 + 41000.0, 0.28, 2.6, 0.02199, 0.001256 + 41000.0, 0.28, 2.65, 0.0255, 0.001828 + 41000.0, 0.28, 2.7, 0.02897, 0.002393 + 41000.0, 0.28, 2.75, 0.0324, 0.00295 + 41000.0, 0.28, 2.8, 0.03579, 0.003499 + 41000.0, 0.28, 2.85, 0.03914, 0.00404 + 41000.0, 0.28, 2.9, 0.04243, 0.004573 + 41000.0, 0.28, 2.95, 0.04567, 0.005096 + 41000.0, 0.28, 3.0, 0.04885, 0.005611 + 41000.0, 0.28, 3.05, 0.05197, 0.006115 + 41000.0, 0.28, 3.1, 0.05503, 0.006609 + 41000.0, 0.28, 3.15, 0.05802, 0.007093 + 41000.0, 0.28, 3.2, 0.06094, 0.007566 + 41000.0, 0.28, 3.25, 0.06379, 0.008028 + 41000.0, 0.28, 3.3, 0.06656, 0.008478 + 41000.0, 0.28, 3.35, 0.06924, 0.008916 + 41000.0, 0.28, 3.4, 0.07185, 0.009341 + 41000.0, 0.28, 3.45, 0.07436, 0.009754 + 41000.0, 0.28, 3.5, 0.07679, 0.01015 + 41000.0, 0.28, 3.55, 0.07912, 0.01054 + 41000.0, 0.28, 3.6, 0.08136, 0.01091 + 41000.0, 0.28, 3.65, 0.08349, 0.01127 + 41000.0, 0.28, 3.7, 0.08552, 0.01161 + 41000.0, 0.28, 3.75, 0.08744, 0.01194 + 41000.0, 0.28, 3.8, 0.08924, 0.01226 + 41000.0, 0.28, 3.85, 0.09094, 0.01255 + 41000.0, 0.28, 3.9, 0.09251, 0.01283 + 41000.0, 0.28, 3.95, 0.09397, 0.0131 + 41000.0, 0.28, 4.0, 0.0953, 0.01335 + 41000.0, 0.28, 4.05, 0.09555, 0.01353 + 41000.0, 0.28, 4.1, 0.09573, 0.0137 + 41000.0, 0.28, 4.15, 0.09583, 0.01386 + 41000.0, 0.28, 4.2, 0.09587, 0.01399 + 41000.0, 0.28, 4.25, 0.09585, 0.01412 + 41000.0, 0.28, 4.3, 0.09576, 0.01423 + 41000.0, 0.28, 4.35, 0.09562, 0.01432 + 41000.0, 0.28, 4.4, 0.09542, 0.0144 + 41000.0, 0.28, 4.45, 0.09518, 0.01447 + 41000.0, 0.28, 4.5, 0.09489, 0.01452 + 41000.0, 0.28, 4.55, 0.09456, 0.01455 + 41000.0, 0.28, 4.6, 0.09419, 0.01457 + 41000.0, 0.28, 4.65, 0.09379, 0.01458 + 41000.0, 0.28, 4.7, 0.09336, 0.01456 + 41000.0, 0.28, 4.75, 0.09291, 0.01454 + 41000.0, 0.28, 4.8, 0.09243, 0.0145 + 41000.0, 0.28, 4.85, 0.09193, 0.01444 + 41000.0, 0.28, 4.9, 0.09143, 0.01437 + 41000.0, 0.28, 4.95, 0.09091, 0.01428 + 41000.0, 0.28, 5.0, 0.09039, 0.01418 + 41000.0, 0.28, 5.05, 0.08969, 0.01407 + 41000.0, 0.28, 5.1, 0.089, 0.01395 + 41000.0, 0.28, 5.15, 0.08833, 0.01381 + 41000.0, 0.28, 5.2, 0.08766, 0.01365 + 41000.0, 0.28, 5.25, 0.08703, 0.01348 + 41000.0, 0.28, 5.3, 0.08642, 0.01329 + 41000.0, 0.28, 5.35, 0.08585, 0.01309 + 41000.0, 0.28, 5.4, 0.08532, 0.01287 + 41000.0, 0.28, 5.45, 0.08484, 0.01263 + 41000.0, 0.28, 5.5, 0.08442, 0.01238 + 41000.0, 0.28, 5.55, 0.08406, 0.01211 + 41000.0, 0.28, 5.6, 0.08376, 0.01182 + 41000.0, 0.28, 5.65, 0.08354, 0.01152 + 41000.0, 0.28, 5.7, 0.08341, 0.0112 + 41000.0, 0.28, 5.75, 0.08336, 0.01086 + 41000.0, 0.28, 5.8, 0.0834, 0.01051 + 41000.0, 0.28, 5.85, 0.08355, 0.01014 + 41000.0, 0.28, 5.9, 0.0838, 0.009749 + 41000.0, 0.28, 5.95, 0.08416, 0.009342 + 41000.0, 0.28, 6.0, 0.08465, 0.008917 + 41000.0, 0.28, 6.05, 0.08683, 0.008398 + 41000.0, 0.28, 6.1, 0.0892, 0.007858 + 41000.0, 0.28, 6.15, 0.09177, 0.007298 + 41000.0, 0.28, 6.2, 0.09453, 0.006717 + 41000.0, 0.28, 6.25, 0.09747, 0.006116 + 41000.0, 0.28, 6.3, 0.1006, 0.005495 + 41000.0, 0.28, 6.35, 0.1039, 0.004855 + 41000.0, 0.28, 6.4, 0.1073, 0.004196 + 41000.0, 0.28, 6.45, 0.1109, 0.003519 + 41000.0, 0.28, 6.5, 0.1147, 0.002825 + 41000.0, 0.28, 6.55, 0.1186, 0.002112 + 41000.0, 0.28, 6.6, 0.1227, 0.001383 + 41000.0, 0.28, 6.65, 0.1269, 0.000637 + 41000.0, 0.28, 6.7, 0.1313, -0.0001252 + 41000.0, 0.28, 6.75, 0.1358, -0.0009032 + 41000.0, 0.28, 6.8, 0.1404, -0.001697 + 41000.0, 0.28, 6.85, 0.1451, -0.002505 + 41000.0, 0.28, 6.9, 0.1499, -0.003328 + 41000.0, 0.28, 6.95, 0.1549, -0.004165 + 41000.0, 0.28, 7.0, 0.16, -0.005016 + 41000.0, 0.28, 7.05, 0.1651, -0.00588 + 41000.0, 0.28, 7.1, 0.1704, -0.006757 + 41000.0, 0.28, 7.15, 0.1757, -0.007646 + 41000.0, 0.28, 7.2, 0.1812, -0.008547 + 41000.0, 0.28, 7.25, 0.1867, -0.00946 + 41000.0, 0.28, 7.3, 0.1923, -0.01038 + 41000.0, 0.28, 7.35, 0.1979, -0.01132 + 41000.0, 0.28, 7.4, 0.2037, -0.01226 + 41000.0, 0.28, 7.45, 0.2094, -0.01322 + 41000.0, 0.28, 7.5, 0.2153, -0.01419 + 41000.0, 0.28, 7.55, 0.2212, -0.01516 + 41000.0, 0.28, 7.6, 0.2271, -0.01614 + 41000.0, 0.28, 7.65, 0.2331, -0.01713 + 41000.0, 0.28, 7.7, 0.2391, -0.01813 + 41000.0, 0.28, 7.75, 0.2451, -0.01914 + 41000.0, 0.28, 7.8, 0.2512, -0.02015 + 41000.0, 0.28, 7.85, 0.2573, -0.02117 + 41000.0, 0.28, 7.9, 0.2634, -0.0222 + 41000.0, 0.28, 7.95, 0.2695, -0.02323 + 41000.0, 0.28, 8.0, 0.2756, -0.02426 + 41000.0, 0.28, 8.05, 0.2804, -0.02522 + 41000.0, 0.28, 8.1, 0.2852, -0.02618 + 41000.0, 0.28, 8.15, 0.29, -0.02715 + 41000.0, 0.28, 8.2, 0.2948, -0.02812 + 41000.0, 0.28, 8.25, 0.2996, -0.0291 + 41000.0, 0.28, 8.3, 0.3044, -0.03008 + 41000.0, 0.28, 8.35, 0.3092, -0.03106 + 41000.0, 0.28, 8.4, 0.3139, -0.03205 + 41000.0, 0.28, 8.45, 0.3187, -0.03304 + 41000.0, 0.28, 8.5, 0.3235, -0.03404 + 41000.0, 0.28, 8.55, 0.3283, -0.03504 + 41000.0, 0.28, 8.6, 0.3331, -0.03605 + 41000.0, 0.28, 8.65, 0.3378, -0.03705 + 41000.0, 0.28, 8.7, 0.3426, -0.03807 + 41000.0, 0.28, 8.75, 0.3474, -0.03908 + 41000.0, 0.28, 8.8, 0.3521, -0.0401 + 41000.0, 0.28, 8.85, 0.3569, -0.04112 + 41000.0, 0.28, 8.9, 0.3617, -0.04215 + 41000.0, 0.28, 8.95, 0.3664, -0.04318 + 41000.0, 0.28, 9.0, 0.3712, -0.04421 + 41000.0, 0.28, 9.05, 0.3759, -0.04524 + 41000.0, 0.28, 9.1, 0.3807, -0.04628 + 41000.0, 0.28, 9.15, 0.3854, -0.04732 + 41000.0, 0.28, 9.2, 0.3901, -0.04836 + 41000.0, 0.28, 9.25, 0.3949, -0.0494 + 41000.0, 0.28, 9.3, 0.3996, -0.05045 + 41000.0, 0.28, 9.35, 0.4043, -0.0515 + 41000.0, 0.28, 9.4, 0.409, -0.05255 + 41000.0, 0.28, 9.45, 0.4137, -0.0536 + 41000.0, 0.28, 9.5, 0.4185, -0.05466 + 41000.0, 0.28, 9.55, 0.4232, -0.05572 + 41000.0, 0.28, 9.6, 0.4279, -0.05678 + 41000.0, 0.28, 9.65, 0.4325, -0.05784 + 41000.0, 0.28, 9.7, 0.4372, -0.0589 + 41000.0, 0.28, 9.75, 0.4419, -0.05996 + 41000.0, 0.28, 9.8, 0.4466, -0.06103 + 41000.0, 0.28, 9.85, 0.4513, -0.06209 + 41000.0, 0.28, 9.9, 0.4559, -0.06316 + 41000.0, 0.28, 9.95, 0.4606, -0.06423 + 41000.0, 0.28, 10.0, 0.4652, -0.0653 + 41000.0, 0.28, 10.05, 0.4699, -0.0664 + 41000.0, 0.28, 10.1, 0.4746, -0.0675 + 41000.0, 0.28, 10.15, 0.4792, -0.0686 + 41000.0, 0.28, 10.2, 0.4839, -0.06971 + 41000.0, 0.28, 10.25, 0.4885, -0.07081 + 41000.0, 0.28, 10.3, 0.4931, -0.07191 + 41000.0, 0.28, 10.35, 0.4978, -0.07302 + 41000.0, 0.28, 10.4, 0.5024, -0.07412 + 41000.0, 0.28, 10.45, 0.507, -0.07522 + 41000.0, 0.28, 10.5, 0.5116, -0.07632 + 41000.0, 0.28, 10.55, 0.5162, -0.07741 + 41000.0, 0.28, 10.6, 0.5207, -0.07851 + 41000.0, 0.28, 10.65, 0.5253, -0.07961 + 41000.0, 0.28, 10.7, 0.5299, -0.0807 + 41000.0, 0.28, 10.75, 0.5344, -0.08179 + 41000.0, 0.28, 10.8, 0.539, -0.08288 + 41000.0, 0.28, 10.85, 0.5435, -0.08396 + 41000.0, 0.28, 10.9, 0.548, -0.08504 + 41000.0, 0.28, 10.95, 0.5525, -0.08612 + 41000.0, 0.28, 11.0, 0.557, -0.0872 + 41000.0, 0.28, 11.05, 0.5615, -0.08827 + 41000.0, 0.28, 11.1, 0.566, -0.08934 + 41000.0, 0.28, 11.15, 0.5705, -0.0904 + 41000.0, 0.28, 11.2, 0.5749, -0.09146 + 41000.0, 0.28, 11.25, 0.5794, -0.09252 + 41000.0, 0.28, 11.3, 0.5838, -0.09357 + 41000.0, 0.28, 11.35, 0.5882, -0.09461 + 41000.0, 0.28, 11.4, 0.5927, -0.09566 + 41000.0, 0.28, 11.45, 0.597, -0.09669 + 41000.0, 0.28, 11.5, 0.6014, -0.09772 + 41000.0, 0.28, 11.55, 0.6058, -0.09874 + 41000.0, 0.28, 11.6, 0.6102, -0.09976 + 41000.0, 0.28, 11.65, 0.6145, -0.1008 + 41000.0, 0.28, 11.7, 0.6188, -0.1018 + 41000.0, 0.28, 11.75, 0.6232, -0.1028 + 41000.0, 0.28, 11.8, 0.6275, -0.1038 + 41000.0, 0.28, 11.85, 0.6318, -0.1048 + 41000.0, 0.28, 11.9, 0.636, -0.1057 + 41000.0, 0.28, 11.95, 0.6403, -0.1067 + 41000.0, 0.28, 12.0, 0.6445, -0.1077 + 41000.0, 0.28, 12.05, 0.6488, -0.1086 + 41000.0, 0.28, 12.1, 0.653, -0.1096 + 41000.0, 0.28, 12.15, 0.6572, -0.1105 + 41000.0, 0.28, 12.2, 0.6614, -0.1114 + 41000.0, 0.28, 12.25, 0.6655, -0.1123 + 41000.0, 0.28, 12.3, 0.6697, -0.1133 + 41000.0, 0.28, 12.35, 0.6738, -0.1142 + 41000.0, 0.28, 12.4, 0.678, -0.115 + 41000.0, 0.28, 12.45, 0.6821, -0.1159 + 41000.0, 0.28, 12.5, 0.6861, -0.1168 + 41000.0, 0.28, 12.55, 0.6902, -0.1177 + 41000.0, 0.28, 12.6, 0.6943, -0.1185 + 41000.0, 0.28, 12.65, 0.6983, -0.1194 + 41000.0, 0.28, 12.7, 0.7023, -0.1202 + 41000.0, 0.28, 12.75, 0.7063, -0.121 + 41000.0, 0.28, 12.8, 0.7103, -0.1218 + 41000.0, 0.28, 12.85, 0.7143, -0.1226 + 41000.0, 0.28, 12.9, 0.7182, -0.1234 + 41000.0, 0.28, 12.95, 0.7221, -0.1242 + 41000.0, 0.28, 13.0, 0.726, -0.1249 + 41000.0, 0.28, 13.05, 0.7299, -0.1257 + 41000.0, 0.28, 13.1, 0.7338, -0.1264 + 41000.0, 0.28, 13.15, 0.7376, -0.1271 + 41000.0, 0.28, 13.2, 0.7415, -0.1278 + 41000.0, 0.28, 13.25, 0.7453, -0.1285 + 41000.0, 0.28, 13.3, 0.7491, -0.1292 + 41000.0, 0.28, 13.35, 0.7528, -0.1299 + 41000.0, 0.28, 13.4, 0.7566, -0.1305 + 41000.0, 0.28, 13.45, 0.7603, -0.1312 + 41000.0, 0.28, 13.5, 0.764, -0.1318 + 41000.0, 0.28, 13.55, 0.7677, -0.1324 + 41000.0, 0.28, 13.6, 0.7713, -0.133 + 41000.0, 0.28, 13.65, 0.775, -0.1336 + 41000.0, 0.28, 13.7, 0.7786, -0.1341 + 41000.0, 0.28, 13.75, 0.7822, -0.1347 + 41000.0, 0.28, 13.8, 0.7858, -0.1352 + 41000.0, 0.28, 13.85, 0.7893, -0.1357 + 41000.0, 0.28, 13.9, 0.7928, -0.1362 + 41000.0, 0.28, 13.95, 0.7963, -0.1367 + 41000.0, 0.28, 14.0, 0.7998, -0.1372 + 41000.0, 0.28, 14.05, 0.8033, -0.1377 + 41000.0, 0.28, 14.1, 0.8067, -0.1381 + 41000.0, 0.28, 14.15, 0.8101, -0.1385 + 41000.0, 0.28, 14.2, 0.8135, -0.1389 + 41000.0, 0.28, 14.25, 0.8168, -0.1393 + 41000.0, 0.28, 14.3, 0.8202, -0.1397 + 41000.0, 0.28, 14.35, 0.8235, -0.14 + 41000.0, 0.28, 14.4, 0.8268, -0.1403 + 41000.0, 0.28, 14.45, 0.83, -0.1406 + 41000.0, 0.28, 14.5, 0.8333, -0.1409 + 41000.0, 0.28, 14.55, 0.8365, -0.1412 + 41000.0, 0.28, 14.6, 0.8397, -0.1414 + 41000.0, 0.28, 14.65, 0.8428, -0.1417 + 41000.0, 0.28, 14.7, 0.8459, -0.1419 + 41000.0, 0.28, 14.75, 0.849, -0.1421 + 41000.0, 0.28, 14.8, 0.8521, -0.1423 + 41000.0, 0.28, 14.85, 0.8552, -0.1424 + 41000.0, 0.28, 14.9, 0.8582, -0.1425 + 41000.0, 0.28, 14.95, 0.8612, -0.1426 + 41000.0, 0.28, 15.0, 0.8642, -0.1427 + 41000.0, 0.28, 15.05, 0.8671, -0.1428 + 41000.0, 0.33, 0.0, -0.108, -0.04833 + 41000.0, 0.33, 0.05, -0.1085, -0.04769 + 41000.0, 0.33, 0.1, -0.1088, -0.04702 + 41000.0, 0.33, 0.15, -0.1089, -0.04634 + 41000.0, 0.33, 0.2, -0.1088, -0.04564 + 41000.0, 0.33, 0.25, -0.1085, -0.04492 + 41000.0, 0.33, 0.3, -0.108, -0.04417 + 41000.0, 0.33, 0.35, -0.1073, -0.04342 + 41000.0, 0.33, 0.4, -0.1063, -0.04264 + 41000.0, 0.33, 0.45, -0.1052, -0.04185 + 41000.0, 0.33, 0.5, -0.1039, -0.04104 + 41000.0, 0.33, 0.55, -0.1025, -0.04022 + 41000.0, 0.33, 0.6, -0.1009, -0.03938 + 41000.0, 0.33, 0.65, -0.09905, -0.03853 + 41000.0, 0.33, 0.7, -0.09709, -0.03767 + 41000.0, 0.33, 0.75, -0.09498, -0.03679 + 41000.0, 0.33, 0.8, -0.09272, -0.0359 + 41000.0, 0.33, 0.85, -0.09031, -0.035 + 41000.0, 0.33, 0.9, -0.08776, -0.03409 + 41000.0, 0.33, 0.95, -0.08509, -0.03316 + 41000.0, 0.33, 1.0, -0.08228, -0.03223 + 41000.0, 0.33, 1.05, -0.07936, -0.03129 + 41000.0, 0.33, 1.1, -0.07631, -0.03034 + 41000.0, 0.33, 1.15, -0.07316, -0.02938 + 41000.0, 0.33, 1.2, -0.0699, -0.02842 + 41000.0, 0.33, 1.25, -0.06654, -0.02745 + 41000.0, 0.33, 1.3, -0.06309, -0.02647 + 41000.0, 0.33, 1.35, -0.05955, -0.02549 + 41000.0, 0.33, 1.4, -0.05592, -0.0245 + 41000.0, 0.33, 1.45, -0.05222, -0.02351 + 41000.0, 0.33, 1.5, -0.04844, -0.02251 + 41000.0, 0.33, 1.55, -0.0446, -0.02152 + 41000.0, 0.33, 1.6, -0.0407, -0.02051 + 41000.0, 0.33, 1.65, -0.03674, -0.01951 + 41000.0, 0.33, 1.7, -0.03273, -0.01851 + 41000.0, 0.33, 1.75, -0.02867, -0.01751 + 41000.0, 0.33, 1.8, -0.02457, -0.0165 + 41000.0, 0.33, 1.85, -0.02044, -0.0155 + 41000.0, 0.33, 1.9, -0.01629, -0.0145 + 41000.0, 0.33, 1.95, -0.0121, -0.0135 + 41000.0, 0.33, 2.0, -0.007905, -0.01251 + 41000.0, 0.33, 2.05, -0.003693, -0.01152 + 41000.0, 0.33, 2.1, 0.0005262, -0.01053 + 41000.0, 0.33, 2.15, 0.004746, -0.009543 + 41000.0, 0.33, 2.2, 0.008963, -0.008564 + 41000.0, 0.33, 2.25, 0.01317, -0.007591 + 41000.0, 0.33, 2.3, 0.01736, -0.006625 + 41000.0, 0.33, 2.35, 0.02153, -0.005665 + 41000.0, 0.33, 2.4, 0.02568, -0.004713 + 41000.0, 0.33, 2.45, 0.02979, -0.003769 + 41000.0, 0.33, 2.5, 0.03387, -0.002835 + 41000.0, 0.33, 2.55, 0.0379, -0.001909 + 41000.0, 0.33, 2.6, 0.04189, -0.0009942 + 41000.0, 0.33, 2.65, 0.04582, -8.974e-05 + 41000.0, 0.33, 2.7, 0.04969, 0.0008033 + 41000.0, 0.33, 2.75, 0.0535, 0.001684 + 41000.0, 0.33, 2.8, 0.05724, 0.002553 + 41000.0, 0.33, 2.85, 0.06091, 0.003408 + 41000.0, 0.33, 2.9, 0.06449, 0.00425 + 41000.0, 0.33, 2.95, 0.06799, 0.005077 + 41000.0, 0.33, 3.0, 0.0714, 0.005889 + 41000.0, 0.33, 3.05, 0.07471, 0.006685 + 41000.0, 0.33, 3.1, 0.07791, 0.007465 + 41000.0, 0.33, 3.15, 0.08101, 0.008228 + 41000.0, 0.33, 3.2, 0.084, 0.008973 + 41000.0, 0.33, 3.25, 0.08686, 0.009701 + 41000.0, 0.33, 3.3, 0.0896, 0.01041 + 41000.0, 0.33, 3.35, 0.09222, 0.0111 + 41000.0, 0.33, 3.4, 0.09469, 0.01177 + 41000.0, 0.33, 3.45, 0.09703, 0.01242 + 41000.0, 0.33, 3.5, 0.09922, 0.01304 + 41000.0, 0.33, 3.55, 0.1013, 0.01365 + 41000.0, 0.33, 3.6, 0.1031, 0.01423 + 41000.0, 0.33, 3.65, 0.1049, 0.01479 + 41000.0, 0.33, 3.7, 0.1064, 0.01533 + 41000.0, 0.33, 3.75, 0.1078, 0.01584 + 41000.0, 0.33, 3.8, 0.109, 0.01633 + 41000.0, 0.33, 3.85, 0.11, 0.01679 + 41000.0, 0.33, 3.9, 0.1108, 0.01722 + 41000.0, 0.33, 3.95, 0.1114, 0.01763 + 41000.0, 0.33, 4.0, 0.1119, 0.01801 + 41000.0, 0.33, 4.05, 0.1105, 0.01829 + 41000.0, 0.33, 4.1, 0.1091, 0.01854 + 41000.0, 0.33, 4.15, 0.1076, 0.01876 + 41000.0, 0.33, 4.2, 0.1059, 0.01897 + 41000.0, 0.33, 4.25, 0.1041, 0.01914 + 41000.0, 0.33, 4.3, 0.1023, 0.0193 + 41000.0, 0.33, 4.35, 0.1003, 0.01943 + 41000.0, 0.33, 4.4, 0.0983, 0.01953 + 41000.0, 0.33, 4.45, 0.09619, 0.01962 + 41000.0, 0.33, 4.5, 0.09401, 0.01967 + 41000.0, 0.33, 4.55, 0.09177, 0.01971 + 41000.0, 0.33, 4.6, 0.08947, 0.01972 + 41000.0, 0.33, 4.65, 0.08711, 0.0197 + 41000.0, 0.33, 4.7, 0.08471, 0.01966 + 41000.0, 0.33, 4.75, 0.08227, 0.0196 + 41000.0, 0.33, 4.8, 0.0798, 0.01951 + 41000.0, 0.33, 4.85, 0.07729, 0.01939 + 41000.0, 0.33, 4.9, 0.07477, 0.01926 + 41000.0, 0.33, 4.95, 0.07224, 0.0191 + 41000.0, 0.33, 5.0, 0.06969, 0.01891 + 41000.0, 0.33, 5.05, 0.06689, 0.01871 + 41000.0, 0.33, 5.1, 0.0641, 0.01849 + 41000.0, 0.33, 5.15, 0.06133, 0.01825 + 41000.0, 0.33, 5.2, 0.05858, 0.01798 + 41000.0, 0.33, 5.25, 0.05587, 0.01768 + 41000.0, 0.33, 5.3, 0.05322, 0.01736 + 41000.0, 0.33, 5.35, 0.05062, 0.01701 + 41000.0, 0.33, 5.4, 0.04809, 0.01664 + 41000.0, 0.33, 5.45, 0.04564, 0.01624 + 41000.0, 0.33, 5.5, 0.04329, 0.01581 + 41000.0, 0.33, 5.55, 0.04103, 0.01536 + 41000.0, 0.33, 5.6, 0.03888, 0.01488 + 41000.0, 0.33, 5.65, 0.03685, 0.01437 + 41000.0, 0.33, 5.7, 0.03496, 0.01383 + 41000.0, 0.33, 5.75, 0.0332, 0.01327 + 41000.0, 0.33, 5.8, 0.0316, 0.01268 + 41000.0, 0.33, 5.85, 0.03015, 0.01206 + 41000.0, 0.33, 5.9, 0.02888, 0.01141 + 41000.0, 0.33, 5.95, 0.02779, 0.01073 + 41000.0, 0.33, 6.0, 0.02689, 0.01002 + 41000.0, 0.33, 6.05, 0.02866, 0.00917 + 41000.0, 0.33, 6.1, 0.03074, 0.00828 + 41000.0, 0.33, 6.15, 0.03313, 0.007357 + 41000.0, 0.33, 6.2, 0.03581, 0.006401 + 41000.0, 0.33, 6.25, 0.03879, 0.005411 + 41000.0, 0.33, 6.3, 0.04205, 0.00439 + 41000.0, 0.33, 6.35, 0.04558, 0.003338 + 41000.0, 0.33, 6.4, 0.04938, 0.002255 + 41000.0, 0.33, 6.45, 0.05344, 0.001142 + 41000.0, 0.33, 6.5, 0.05776, -3.325e-07 + 41000.0, 0.33, 6.55, 0.06231, -0.001172 + 41000.0, 0.33, 6.6, 0.0671, -0.002371 + 41000.0, 0.33, 6.65, 0.07212, -0.003598 + 41000.0, 0.33, 6.7, 0.07736, -0.004852 + 41000.0, 0.33, 6.75, 0.08281, -0.006132 + 41000.0, 0.33, 6.8, 0.08847, -0.007437 + 41000.0, 0.33, 6.85, 0.09432, -0.008768 + 41000.0, 0.33, 6.9, 0.1004, -0.01012 + 41000.0, 0.33, 6.95, 0.1066, -0.0115 + 41000.0, 0.33, 7.0, 0.113, -0.0129 + 41000.0, 0.33, 7.05, 0.1195, -0.01433 + 41000.0, 0.33, 7.1, 0.1263, -0.01577 + 41000.0, 0.33, 7.15, 0.1331, -0.01724 + 41000.0, 0.33, 7.2, 0.1401, -0.01873 + 41000.0, 0.33, 7.25, 0.1473, -0.02024 + 41000.0, 0.33, 7.3, 0.1545, -0.02176 + 41000.0, 0.33, 7.35, 0.1619, -0.02331 + 41000.0, 0.33, 7.4, 0.1694, -0.02487 + 41000.0, 0.33, 7.45, 0.177, -0.02645 + 41000.0, 0.33, 7.5, 0.1847, -0.02805 + 41000.0, 0.33, 7.55, 0.1925, -0.02967 + 41000.0, 0.33, 7.6, 0.2003, -0.0313 + 41000.0, 0.33, 7.65, 0.2083, -0.03294 + 41000.0, 0.33, 7.7, 0.2162, -0.0346 + 41000.0, 0.33, 7.75, 0.2243, -0.03627 + 41000.0, 0.33, 7.8, 0.2324, -0.03796 + 41000.0, 0.33, 7.85, 0.2405, -0.03965 + 41000.0, 0.33, 7.9, 0.2487, -0.04136 + 41000.0, 0.33, 7.95, 0.2569, -0.04308 + 41000.0, 0.33, 8.0, 0.2651, -0.04481 + 41000.0, 0.33, 8.05, 0.2713, -0.04642 + 41000.0, 0.33, 8.1, 0.2774, -0.04803 + 41000.0, 0.33, 8.15, 0.2837, -0.04965 + 41000.0, 0.33, 8.2, 0.2899, -0.05128 + 41000.0, 0.33, 8.25, 0.2961, -0.05293 + 41000.0, 0.33, 8.3, 0.3023, -0.05458 + 41000.0, 0.33, 8.35, 0.3085, -0.05624 + 41000.0, 0.33, 8.4, 0.3148, -0.0579 + 41000.0, 0.33, 8.45, 0.321, -0.05958 + 41000.0, 0.33, 8.5, 0.3273, -0.06127 + 41000.0, 0.33, 8.55, 0.3335, -0.06296 + 41000.0, 0.33, 8.6, 0.3398, -0.06466 + 41000.0, 0.33, 8.65, 0.346, -0.06638 + 41000.0, 0.33, 8.7, 0.3523, -0.0681 + 41000.0, 0.33, 8.75, 0.3586, -0.06982 + 41000.0, 0.33, 8.8, 0.3648, -0.07156 + 41000.0, 0.33, 8.85, 0.3711, -0.0733 + 41000.0, 0.33, 8.9, 0.3774, -0.07506 + 41000.0, 0.33, 8.95, 0.3837, -0.07682 + 41000.0, 0.33, 9.0, 0.39, -0.07858 + 41000.0, 0.33, 9.05, 0.3962, -0.08036 + 41000.0, 0.33, 9.1, 0.4025, -0.08214 + 41000.0, 0.33, 9.15, 0.4088, -0.08393 + 41000.0, 0.33, 9.2, 0.4151, -0.08572 + 41000.0, 0.33, 9.25, 0.4214, -0.08753 + 41000.0, 0.33, 9.3, 0.4277, -0.08934 + 41000.0, 0.33, 9.35, 0.434, -0.09116 + 41000.0, 0.33, 9.4, 0.4403, -0.09298 + 41000.0, 0.33, 9.45, 0.4466, -0.09481 + 41000.0, 0.33, 9.5, 0.4529, -0.09665 + 41000.0, 0.33, 9.55, 0.4591, -0.09849 + 41000.0, 0.33, 9.6, 0.4654, -0.1003 + 41000.0, 0.33, 9.65, 0.4717, -0.1022 + 41000.0, 0.33, 9.7, 0.478, -0.1041 + 41000.0, 0.33, 9.75, 0.4843, -0.1059 + 41000.0, 0.33, 9.8, 0.4906, -0.1078 + 41000.0, 0.33, 9.85, 0.4969, -0.1097 + 41000.0, 0.33, 9.9, 0.5031, -0.1116 + 41000.0, 0.33, 9.95, 0.5094, -0.1134 + 41000.0, 0.33, 10.0, 0.5157, -0.1153 + 41000.0, 0.33, 10.05, 0.5219, -0.1173 + 41000.0, 0.33, 10.1, 0.5282, -0.1193 + 41000.0, 0.33, 10.15, 0.5344, -0.1213 + 41000.0, 0.33, 10.2, 0.5406, -0.1233 + 41000.0, 0.33, 10.25, 0.5469, -0.1253 + 41000.0, 0.33, 10.3, 0.5531, -0.1273 + 41000.0, 0.33, 10.35, 0.5593, -0.1294 + 41000.0, 0.33, 10.4, 0.5655, -0.1314 + 41000.0, 0.33, 10.45, 0.5717, -0.1334 + 41000.0, 0.33, 10.5, 0.5779, -0.1354 + 41000.0, 0.33, 10.55, 0.5841, -0.1374 + 41000.0, 0.33, 10.6, 0.5903, -0.1394 + 41000.0, 0.33, 10.65, 0.5965, -0.1415 + 41000.0, 0.33, 10.7, 0.6027, -0.1435 + 41000.0, 0.33, 10.75, 0.6089, -0.1455 + 41000.0, 0.33, 10.8, 0.615, -0.1475 + 41000.0, 0.33, 10.85, 0.6212, -0.1495 + 41000.0, 0.33, 10.9, 0.6273, -0.1515 + 41000.0, 0.33, 10.95, 0.6335, -0.1535 + 41000.0, 0.33, 11.0, 0.6396, -0.1555 + 41000.0, 0.33, 11.05, 0.6457, -0.1575 + 41000.0, 0.33, 11.1, 0.6519, -0.1595 + 41000.0, 0.33, 11.15, 0.658, -0.1615 + 41000.0, 0.33, 11.2, 0.6641, -0.1635 + 41000.0, 0.33, 11.25, 0.6702, -0.1655 + 41000.0, 0.33, 11.3, 0.6763, -0.1674 + 41000.0, 0.33, 11.35, 0.6823, -0.1694 + 41000.0, 0.33, 11.4, 0.6884, -0.1713 + 41000.0, 0.33, 11.45, 0.6945, -0.1733 + 41000.0, 0.33, 11.5, 0.7005, -0.1752 + 41000.0, 0.33, 11.55, 0.7066, -0.1771 + 41000.0, 0.33, 11.6, 0.7126, -0.1791 + 41000.0, 0.33, 11.65, 0.7186, -0.181 + 41000.0, 0.33, 11.7, 0.7246, -0.1829 + 41000.0, 0.33, 11.75, 0.7306, -0.1848 + 41000.0, 0.33, 11.8, 0.7366, -0.1866 + 41000.0, 0.33, 11.85, 0.7426, -0.1885 + 41000.0, 0.33, 11.9, 0.7486, -0.1904 + 41000.0, 0.33, 11.95, 0.7545, -0.1922 + 41000.0, 0.33, 12.0, 0.7605, -0.194 + 41000.0, 0.33, 12.05, 0.7664, -0.1959 + 41000.0, 0.33, 12.1, 0.7723, -0.1977 + 41000.0, 0.33, 12.15, 0.7782, -0.1994 + 41000.0, 0.33, 12.2, 0.7841, -0.2012 + 41000.0, 0.33, 12.25, 0.79, -0.203 + 41000.0, 0.33, 12.3, 0.7959, -0.2047 + 41000.0, 0.33, 12.35, 0.8017, -0.2064 + 41000.0, 0.33, 12.4, 0.8076, -0.2082 + 41000.0, 0.33, 12.45, 0.8134, -0.2099 + 41000.0, 0.33, 12.5, 0.8192, -0.2115 + 41000.0, 0.33, 12.55, 0.825, -0.2132 + 41000.0, 0.33, 12.6, 0.8308, -0.2148 + 41000.0, 0.33, 12.65, 0.8366, -0.2164 + 41000.0, 0.33, 12.7, 0.8423, -0.218 + 41000.0, 0.33, 12.75, 0.8481, -0.2196 + 41000.0, 0.33, 12.8, 0.8538, -0.2212 + 41000.0, 0.33, 12.85, 0.8595, -0.2227 + 41000.0, 0.33, 12.9, 0.8652, -0.2242 + 41000.0, 0.33, 12.95, 0.8709, -0.2257 + 41000.0, 0.33, 13.0, 0.8766, -0.2272 + 41000.0, 0.33, 13.05, 0.8822, -0.2287 + 41000.0, 0.33, 13.1, 0.8879, -0.2301 + 41000.0, 0.33, 13.15, 0.8935, -0.2315 + 41000.0, 0.33, 13.2, 0.8991, -0.2329 + 41000.0, 0.33, 13.25, 0.9047, -0.2342 + 41000.0, 0.33, 13.3, 0.9103, -0.2355 + 41000.0, 0.33, 13.35, 0.9158, -0.2369 + 41000.0, 0.33, 13.4, 0.9214, -0.2381 + 41000.0, 0.33, 13.45, 0.9269, -0.2394 + 41000.0, 0.33, 13.5, 0.9324, -0.2406 + 41000.0, 0.33, 13.55, 0.9379, -0.2418 + 41000.0, 0.33, 13.6, 0.9433, -0.243 + 41000.0, 0.33, 13.65, 0.9488, -0.2441 + 41000.0, 0.33, 13.7, 0.9542, -0.2452 + 41000.0, 0.33, 13.75, 0.9596, -0.2463 + 41000.0, 0.33, 13.8, 0.965, -0.2474 + 41000.0, 0.33, 13.85, 0.9704, -0.2484 + 41000.0, 0.33, 13.9, 0.9757, -0.2494 + 41000.0, 0.33, 13.95, 0.9811, -0.2504 + 41000.0, 0.33, 14.0, 0.9864, -0.2513 + 41000.0, 0.33, 14.05, 0.9917, -0.2522 + 41000.0, 0.33, 14.1, 0.9969, -0.2531 + 41000.0, 0.33, 14.15, 1.002, -0.2539 + 41000.0, 0.33, 14.2, 1.007, -0.2547 + 41000.0, 0.33, 14.25, 1.013, -0.2555 + 41000.0, 0.33, 14.3, 1.018, -0.2562 + 41000.0, 0.33, 14.35, 1.023, -0.2569 + 41000.0, 0.33, 14.4, 1.028, -0.2576 + 41000.0, 0.33, 14.45, 1.033, -0.2582 + 41000.0, 0.33, 14.5, 1.038, -0.2588 + 41000.0, 0.33, 14.55, 1.043, -0.2593 + 41000.0, 0.33, 14.6, 1.049, -0.2598 + 41000.0, 0.33, 14.65, 1.054, -0.2603 + 41000.0, 0.33, 14.7, 1.059, -0.2608 + 41000.0, 0.33, 14.75, 1.064, -0.2612 + 41000.0, 0.33, 14.8, 1.069, -0.2615 + 41000.0, 0.33, 14.85, 1.073, -0.2619 + 41000.0, 0.33, 14.9, 1.078, -0.2622 + 41000.0, 0.33, 14.95, 1.083, -0.2624 + 41000.0, 0.33, 15.0, 1.088, -0.2626 + 41000.0, 0.33, 15.05, 1.093, -0.2628 + 41000.0, 0.38, 0.0, -0.09774, -0.05662 + 41000.0, 0.38, 0.05, -0.09886, -0.05589 + 41000.0, 0.38, 0.1, -0.09971, -0.05513 + 41000.0, 0.38, 0.15, -0.1003, -0.05436 + 41000.0, 0.38, 0.2, -0.1007, -0.05355 + 41000.0, 0.38, 0.25, -0.1008, -0.05273 + 41000.0, 0.38, 0.3, -0.1006, -0.05188 + 41000.0, 0.38, 0.35, -0.1003, -0.05102 + 41000.0, 0.38, 0.4, -0.09969, -0.05013 + 41000.0, 0.38, 0.45, -0.09889, -0.04923 + 41000.0, 0.38, 0.5, -0.09787, -0.0483 + 41000.0, 0.38, 0.55, -0.09665, -0.04736 + 41000.0, 0.38, 0.6, -0.09523, -0.0464 + 41000.0, 0.38, 0.65, -0.09362, -0.04542 + 41000.0, 0.38, 0.7, -0.09182, -0.04443 + 41000.0, 0.38, 0.75, -0.08984, -0.04342 + 41000.0, 0.38, 0.8, -0.08769, -0.0424 + 41000.0, 0.38, 0.85, -0.08537, -0.04136 + 41000.0, 0.38, 0.9, -0.08289, -0.04032 + 41000.0, 0.38, 0.95, -0.08026, -0.03926 + 41000.0, 0.38, 1.0, -0.07748, -0.03818 + 41000.0, 0.38, 1.05, -0.07456, -0.0371 + 41000.0, 0.38, 1.1, -0.0715, -0.03601 + 41000.0, 0.38, 1.15, -0.06831, -0.03491 + 41000.0, 0.38, 1.2, -0.065, -0.0338 + 41000.0, 0.38, 1.25, -0.06158, -0.03268 + 41000.0, 0.38, 1.3, -0.05804, -0.03155 + 41000.0, 0.38, 1.35, -0.0544, -0.03042 + 41000.0, 0.38, 1.4, -0.05067, -0.02928 + 41000.0, 0.38, 1.45, -0.04684, -0.02814 + 41000.0, 0.38, 1.5, -0.04293, -0.02699 + 41000.0, 0.38, 1.55, -0.03894, -0.02584 + 41000.0, 0.38, 1.6, -0.03488, -0.02469 + 41000.0, 0.38, 1.65, -0.03076, -0.02353 + 41000.0, 0.38, 1.7, -0.02658, -0.02237 + 41000.0, 0.38, 1.75, -0.02234, -0.02122 + 41000.0, 0.38, 1.8, -0.01806, -0.02006 + 41000.0, 0.38, 1.85, -0.01374, -0.0189 + 41000.0, 0.38, 1.9, -0.009383, -0.01775 + 41000.0, 0.38, 1.95, -0.005001, -0.01659 + 41000.0, 0.38, 2.0, -0.0005991, -0.01544 + 41000.0, 0.38, 2.05, 0.003817, -0.0143 + 41000.0, 0.38, 2.1, 0.008242, -0.01316 + 41000.0, 0.38, 2.15, 0.01267, -0.01202 + 41000.0, 0.38, 2.2, 0.01709, -0.01089 + 41000.0, 0.38, 2.25, 0.0215, -0.009763 + 41000.0, 0.38, 2.3, 0.02589, -0.008646 + 41000.0, 0.38, 2.35, 0.03026, -0.007537 + 41000.0, 0.38, 2.4, 0.0346, -0.006437 + 41000.0, 0.38, 2.45, 0.0389, -0.005346 + 41000.0, 0.38, 2.5, 0.04316, -0.004265 + 41000.0, 0.38, 2.55, 0.04736, -0.003195 + 41000.0, 0.38, 2.6, 0.05152, -0.002137 + 41000.0, 0.38, 2.65, 0.05561, -0.001091 + 41000.0, 0.38, 2.7, 0.05963, -5.874e-05 + 41000.0, 0.38, 2.75, 0.06358, 0.0009602 + 41000.0, 0.38, 2.8, 0.06744, 0.001965 + 41000.0, 0.38, 2.85, 0.07122, 0.002954 + 41000.0, 0.38, 2.9, 0.0749, 0.003927 + 41000.0, 0.38, 2.95, 0.07849, 0.004883 + 41000.0, 0.38, 3.0, 0.08196, 0.005822 + 41000.0, 0.38, 3.05, 0.08533, 0.006743 + 41000.0, 0.38, 3.1, 0.08857, 0.007645 + 41000.0, 0.38, 3.15, 0.09169, 0.008528 + 41000.0, 0.38, 3.2, 0.09468, 0.00939 + 41000.0, 0.38, 3.25, 0.09753, 0.01023 + 41000.0, 0.38, 3.3, 0.1002, 0.01105 + 41000.0, 0.38, 3.35, 0.1028, 0.01185 + 41000.0, 0.38, 3.4, 0.1052, 0.01262 + 41000.0, 0.38, 3.45, 0.1074, 0.01337 + 41000.0, 0.38, 3.5, 0.1095, 0.0141 + 41000.0, 0.38, 3.55, 0.1113, 0.0148 + 41000.0, 0.38, 3.6, 0.113, 0.01547 + 41000.0, 0.38, 3.65, 0.1146, 0.01612 + 41000.0, 0.38, 3.7, 0.1159, 0.01674 + 41000.0, 0.38, 3.75, 0.117, 0.01733 + 41000.0, 0.38, 3.8, 0.1179, 0.01789 + 41000.0, 0.38, 3.85, 0.1186, 0.01842 + 41000.0, 0.38, 3.9, 0.119, 0.01892 + 41000.0, 0.38, 3.95, 0.1193, 0.0194 + 41000.0, 0.38, 4.0, 0.1193, 0.01983 + 41000.0, 0.38, 4.05, 0.1173, 0.02015 + 41000.0, 0.38, 4.1, 0.1151, 0.02043 + 41000.0, 0.38, 4.15, 0.1128, 0.02069 + 41000.0, 0.38, 4.2, 0.1104, 0.02092 + 41000.0, 0.38, 4.25, 0.1078, 0.02113 + 41000.0, 0.38, 4.3, 0.1052, 0.0213 + 41000.0, 0.38, 4.35, 0.1024, 0.02145 + 41000.0, 0.38, 4.4, 0.09958, 0.02157 + 41000.0, 0.38, 4.45, 0.09663, 0.02166 + 41000.0, 0.38, 4.5, 0.0936, 0.02172 + 41000.0, 0.38, 4.55, 0.0905, 0.02176 + 41000.0, 0.38, 4.6, 0.08733, 0.02176 + 41000.0, 0.38, 4.65, 0.0841, 0.02174 + 41000.0, 0.38, 4.7, 0.08082, 0.02169 + 41000.0, 0.38, 4.75, 0.07749, 0.02162 + 41000.0, 0.38, 4.8, 0.07413, 0.02151 + 41000.0, 0.38, 4.85, 0.07073, 0.02138 + 41000.0, 0.38, 4.9, 0.06731, 0.02122 + 41000.0, 0.38, 4.95, 0.06387, 0.02103 + 41000.0, 0.38, 5.0, 0.06043, 0.02081 + 41000.0, 0.38, 5.05, 0.05669, 0.02059 + 41000.0, 0.38, 5.1, 0.05297, 0.02034 + 41000.0, 0.38, 5.15, 0.04927, 0.02006 + 41000.0, 0.38, 5.2, 0.0456, 0.01975 + 41000.0, 0.38, 5.25, 0.04198, 0.01941 + 41000.0, 0.38, 5.3, 0.03842, 0.01904 + 41000.0, 0.38, 5.35, 0.03493, 0.01864 + 41000.0, 0.38, 5.4, 0.03151, 0.01821 + 41000.0, 0.38, 5.45, 0.02819, 0.01775 + 41000.0, 0.38, 5.5, 0.02497, 0.01726 + 41000.0, 0.38, 5.55, 0.02187, 0.01674 + 41000.0, 0.38, 5.6, 0.0189, 0.01619 + 41000.0, 0.38, 5.65, 0.01606, 0.0156 + 41000.0, 0.38, 5.7, 0.01338, 0.01498 + 41000.0, 0.38, 5.75, 0.01085, 0.01434 + 41000.0, 0.38, 5.8, 0.008505, 0.01365 + 41000.0, 0.38, 5.85, 0.006343, 0.01294 + 41000.0, 0.38, 5.9, 0.004377, 0.01219 + 41000.0, 0.38, 5.95, 0.002621, 0.01141 + 41000.0, 0.38, 6.0, 0.001086, 0.01059 + 41000.0, 0.38, 6.05, 0.002599, 0.009598 + 41000.0, 0.38, 6.1, 0.004472, 0.008564 + 41000.0, 0.38, 6.15, 0.006698, 0.007491 + 41000.0, 0.38, 6.2, 0.009267, 0.006378 + 41000.0, 0.38, 6.25, 0.01217, 0.005227 + 41000.0, 0.38, 6.3, 0.0154, 0.004039 + 41000.0, 0.38, 6.35, 0.01894, 0.002813 + 41000.0, 0.38, 6.4, 0.0228, 0.001552 + 41000.0, 0.38, 6.45, 0.02695, 0.0002544 + 41000.0, 0.38, 6.5, 0.03139, -0.001077 + 41000.0, 0.38, 6.55, 0.03611, -0.002443 + 41000.0, 0.38, 6.6, 0.0411, -0.003842 + 41000.0, 0.38, 6.65, 0.04636, -0.005274 + 41000.0, 0.38, 6.7, 0.05187, -0.006737 + 41000.0, 0.38, 6.75, 0.05762, -0.008232 + 41000.0, 0.38, 6.8, 0.06361, -0.009756 + 41000.0, 0.38, 6.85, 0.06983, -0.01131 + 41000.0, 0.38, 6.9, 0.07626, -0.01289 + 41000.0, 0.38, 6.95, 0.08291, -0.01451 + 41000.0, 0.38, 7.0, 0.08975, -0.01614 + 41000.0, 0.38, 7.05, 0.09679, -0.01781 + 41000.0, 0.38, 7.1, 0.104, -0.0195 + 41000.0, 0.38, 7.15, 0.1114, -0.02122 + 41000.0, 0.38, 7.2, 0.119, -0.02296 + 41000.0, 0.38, 7.25, 0.1267, -0.02472 + 41000.0, 0.38, 7.3, 0.1345, -0.02651 + 41000.0, 0.38, 7.35, 0.1425, -0.02832 + 41000.0, 0.38, 7.4, 0.1506, -0.03015 + 41000.0, 0.38, 7.45, 0.1589, -0.03201 + 41000.0, 0.38, 7.5, 0.1672, -0.03388 + 41000.0, 0.38, 7.55, 0.1757, -0.03577 + 41000.0, 0.38, 7.6, 0.1843, -0.03768 + 41000.0, 0.38, 7.65, 0.1929, -0.03961 + 41000.0, 0.38, 7.7, 0.2016, -0.04156 + 41000.0, 0.38, 7.75, 0.2104, -0.04352 + 41000.0, 0.38, 7.8, 0.2192, -0.0455 + 41000.0, 0.38, 7.85, 0.2281, -0.04749 + 41000.0, 0.38, 7.9, 0.237, -0.0495 + 41000.0, 0.38, 7.95, 0.246, -0.05152 + 41000.0, 0.38, 8.0, 0.2549, -0.05355 + 41000.0, 0.38, 8.05, 0.2616, -0.05543 + 41000.0, 0.38, 8.1, 0.2683, -0.05733 + 41000.0, 0.38, 8.15, 0.2751, -0.05923 + 41000.0, 0.38, 8.2, 0.2818, -0.06115 + 41000.0, 0.38, 8.25, 0.2885, -0.06308 + 41000.0, 0.38, 8.3, 0.2953, -0.06502 + 41000.0, 0.38, 8.35, 0.3021, -0.06697 + 41000.0, 0.38, 8.4, 0.3088, -0.06894 + 41000.0, 0.38, 8.45, 0.3156, -0.07091 + 41000.0, 0.38, 8.5, 0.3224, -0.0729 + 41000.0, 0.38, 8.55, 0.3292, -0.07489 + 41000.0, 0.38, 8.6, 0.336, -0.0769 + 41000.0, 0.38, 8.65, 0.3429, -0.07892 + 41000.0, 0.38, 8.7, 0.3497, -0.08095 + 41000.0, 0.38, 8.75, 0.3565, -0.08299 + 41000.0, 0.38, 8.8, 0.3634, -0.08504 + 41000.0, 0.38, 8.85, 0.3702, -0.0871 + 41000.0, 0.38, 8.9, 0.3771, -0.08917 + 41000.0, 0.38, 8.95, 0.3839, -0.09124 + 41000.0, 0.38, 9.0, 0.3908, -0.09333 + 41000.0, 0.38, 9.05, 0.3977, -0.09543 + 41000.0, 0.38, 9.1, 0.4046, -0.09754 + 41000.0, 0.38, 9.15, 0.4114, -0.09966 + 41000.0, 0.38, 9.2, 0.4183, -0.1018 + 41000.0, 0.38, 9.25, 0.4252, -0.1039 + 41000.0, 0.38, 9.3, 0.4321, -0.1061 + 41000.0, 0.38, 9.35, 0.439, -0.1082 + 41000.0, 0.38, 9.4, 0.4459, -0.1104 + 41000.0, 0.38, 9.45, 0.4528, -0.1126 + 41000.0, 0.38, 9.5, 0.4597, -0.1147 + 41000.0, 0.38, 9.55, 0.4666, -0.1169 + 41000.0, 0.38, 9.6, 0.4735, -0.1191 + 41000.0, 0.38, 9.65, 0.4805, -0.1213 + 41000.0, 0.38, 9.7, 0.4874, -0.1236 + 41000.0, 0.38, 9.75, 0.4943, -0.1258 + 41000.0, 0.38, 9.8, 0.5012, -0.128 + 41000.0, 0.38, 9.85, 0.5081, -0.1302 + 41000.0, 0.38, 9.9, 0.515, -0.1325 + 41000.0, 0.38, 9.95, 0.5219, -0.1347 + 41000.0, 0.38, 10.0, 0.5288, -0.137 + 41000.0, 0.38, 10.05, 0.5357, -0.1394 + 41000.0, 0.38, 10.1, 0.5426, -0.1418 + 41000.0, 0.38, 10.15, 0.5494, -0.1442 + 41000.0, 0.38, 10.2, 0.5563, -0.1466 + 41000.0, 0.38, 10.25, 0.5631, -0.149 + 41000.0, 0.38, 10.3, 0.57, -0.1514 + 41000.0, 0.38, 10.35, 0.5768, -0.1539 + 41000.0, 0.38, 10.4, 0.5837, -0.1563 + 41000.0, 0.38, 10.45, 0.5905, -0.1587 + 41000.0, 0.38, 10.5, 0.5974, -0.1612 + 41000.0, 0.38, 10.55, 0.6042, -0.1636 + 41000.0, 0.38, 10.6, 0.611, -0.166 + 41000.0, 0.38, 10.65, 0.6179, -0.1685 + 41000.0, 0.38, 10.7, 0.6247, -0.1709 + 41000.0, 0.38, 10.75, 0.6315, -0.1733 + 41000.0, 0.38, 10.8, 0.6383, -0.1758 + 41000.0, 0.38, 10.85, 0.6451, -0.1782 + 41000.0, 0.38, 10.9, 0.6519, -0.1806 + 41000.0, 0.38, 10.95, 0.6587, -0.183 + 41000.0, 0.38, 11.0, 0.6655, -0.1855 + 41000.0, 0.38, 11.05, 0.6723, -0.1879 + 41000.0, 0.38, 11.1, 0.6791, -0.1903 + 41000.0, 0.38, 11.15, 0.6859, -0.1927 + 41000.0, 0.38, 11.2, 0.6927, -0.1951 + 41000.0, 0.38, 11.25, 0.6994, -0.1975 + 41000.0, 0.38, 11.3, 0.7062, -0.1999 + 41000.0, 0.38, 11.35, 0.7129, -0.2023 + 41000.0, 0.38, 11.4, 0.7197, -0.2046 + 41000.0, 0.38, 11.45, 0.7264, -0.207 + 41000.0, 0.38, 11.5, 0.7332, -0.2093 + 41000.0, 0.38, 11.55, 0.7399, -0.2117 + 41000.0, 0.38, 11.6, 0.7466, -0.214 + 41000.0, 0.38, 11.65, 0.7533, -0.2163 + 41000.0, 0.38, 11.7, 0.76, -0.2186 + 41000.0, 0.38, 11.75, 0.7667, -0.2209 + 41000.0, 0.38, 11.8, 0.7734, -0.2232 + 41000.0, 0.38, 11.85, 0.7801, -0.2255 + 41000.0, 0.38, 11.9, 0.7868, -0.2278 + 41000.0, 0.38, 11.95, 0.7934, -0.23 + 41000.0, 0.38, 12.0, 0.8001, -0.2322 + 41000.0, 0.38, 12.05, 0.8067, -0.2344 + 41000.0, 0.38, 12.1, 0.8134, -0.2366 + 41000.0, 0.38, 12.15, 0.82, -0.2388 + 41000.0, 0.38, 12.2, 0.8266, -0.241 + 41000.0, 0.38, 12.25, 0.8332, -0.2431 + 41000.0, 0.38, 12.3, 0.8398, -0.2452 + 41000.0, 0.38, 12.35, 0.8464, -0.2473 + 41000.0, 0.38, 12.4, 0.853, -0.2494 + 41000.0, 0.38, 12.45, 0.8596, -0.2515 + 41000.0, 0.38, 12.5, 0.8661, -0.2535 + 41000.0, 0.38, 12.55, 0.8727, -0.2555 + 41000.0, 0.38, 12.6, 0.8792, -0.2575 + 41000.0, 0.38, 12.65, 0.8857, -0.2595 + 41000.0, 0.38, 12.7, 0.8922, -0.2615 + 41000.0, 0.38, 12.75, 0.8987, -0.2634 + 41000.0, 0.38, 12.8, 0.9052, -0.2653 + 41000.0, 0.38, 12.85, 0.9117, -0.2672 + 41000.0, 0.38, 12.9, 0.9182, -0.269 + 41000.0, 0.38, 12.95, 0.9246, -0.2709 + 41000.0, 0.38, 13.0, 0.9311, -0.2727 + 41000.0, 0.38, 13.05, 0.9375, -0.2744 + 41000.0, 0.38, 13.1, 0.9439, -0.2762 + 41000.0, 0.38, 13.15, 0.9503, -0.2779 + 41000.0, 0.38, 13.2, 0.9567, -0.2796 + 41000.0, 0.38, 13.25, 0.9631, -0.2812 + 41000.0, 0.38, 13.3, 0.9694, -0.2829 + 41000.0, 0.38, 13.35, 0.9758, -0.2845 + 41000.0, 0.38, 13.4, 0.9821, -0.286 + 41000.0, 0.38, 13.45, 0.9884, -0.2876 + 41000.0, 0.38, 13.5, 0.9947, -0.2891 + 41000.0, 0.38, 13.55, 1.001, -0.2905 + 41000.0, 0.38, 13.6, 1.007, -0.2919 + 41000.0, 0.38, 13.65, 1.014, -0.2933 + 41000.0, 0.38, 13.7, 1.02, -0.2947 + 41000.0, 0.38, 13.75, 1.026, -0.296 + 41000.0, 0.38, 13.8, 1.032, -0.2973 + 41000.0, 0.38, 13.85, 1.038, -0.2986 + 41000.0, 0.38, 13.9, 1.045, -0.2998 + 41000.0, 0.38, 13.95, 1.051, -0.301 + 41000.0, 0.38, 14.0, 1.057, -0.3021 + 41000.0, 0.38, 14.05, 1.063, -0.3032 + 41000.0, 0.38, 14.1, 1.069, -0.3043 + 41000.0, 0.38, 14.15, 1.075, -0.3053 + 41000.0, 0.38, 14.2, 1.081, -0.3063 + 41000.0, 0.38, 14.25, 1.087, -0.3072 + 41000.0, 0.38, 14.3, 1.094, -0.3081 + 41000.0, 0.38, 14.35, 1.1, -0.309 + 41000.0, 0.38, 14.4, 1.106, -0.3098 + 41000.0, 0.38, 14.45, 1.112, -0.3106 + 41000.0, 0.38, 14.5, 1.118, -0.3113 + 41000.0, 0.38, 14.55, 1.124, -0.312 + 41000.0, 0.38, 14.6, 1.129, -0.3126 + 41000.0, 0.38, 14.65, 1.135, -0.3132 + 41000.0, 0.38, 14.7, 1.141, -0.3137 + 41000.0, 0.38, 14.75, 1.147, -0.3142 + 41000.0, 0.38, 14.8, 1.153, -0.3147 + 41000.0, 0.38, 14.85, 1.159, -0.3151 + 41000.0, 0.38, 14.9, 1.165, -0.3154 + 41000.0, 0.38, 14.95, 1.171, -0.3157 + 41000.0, 0.38, 15.0, 1.176, -0.316 + 41000.0, 0.38, 15.05, 1.182, -0.3162 + 41000.0, 0.43, 0.0, -0.09462, -0.05606 + 41000.0, 0.43, 0.05, -0.09574, -0.05534 + 41000.0, 0.43, 0.1, -0.0966, -0.0546 + 41000.0, 0.43, 0.15, -0.09721, -0.05384 + 41000.0, 0.43, 0.2, -0.09757, -0.05305 + 41000.0, 0.43, 0.25, -0.09769, -0.05225 + 41000.0, 0.43, 0.3, -0.09757, -0.05142 + 41000.0, 0.43, 0.35, -0.09722, -0.05057 + 41000.0, 0.43, 0.4, -0.09665, -0.0497 + 41000.0, 0.43, 0.45, -0.09587, -0.04881 + 41000.0, 0.43, 0.5, -0.09487, -0.0479 + 41000.0, 0.43, 0.55, -0.09367, -0.04697 + 41000.0, 0.43, 0.6, -0.09227, -0.04603 + 41000.0, 0.43, 0.65, -0.09068, -0.04507 + 41000.0, 0.43, 0.7, -0.08891, -0.04409 + 41000.0, 0.43, 0.75, -0.08696, -0.0431 + 41000.0, 0.43, 0.8, -0.08483, -0.0421 + 41000.0, 0.43, 0.85, -0.08254, -0.04108 + 41000.0, 0.43, 0.9, -0.08009, -0.04005 + 41000.0, 0.43, 0.95, -0.07749, -0.039 + 41000.0, 0.43, 1.0, -0.07474, -0.03795 + 41000.0, 0.43, 1.05, -0.07185, -0.03688 + 41000.0, 0.43, 1.1, -0.06883, -0.0358 + 41000.0, 0.43, 1.15, -0.06568, -0.03472 + 41000.0, 0.43, 1.2, -0.0624, -0.03362 + 41000.0, 0.43, 1.25, -0.05901, -0.03252 + 41000.0, 0.43, 1.3, -0.05552, -0.03141 + 41000.0, 0.43, 1.35, -0.05192, -0.0303 + 41000.0, 0.43, 1.4, -0.04822, -0.02917 + 41000.0, 0.43, 1.45, -0.04443, -0.02805 + 41000.0, 0.43, 1.5, -0.04056, -0.02692 + 41000.0, 0.43, 1.55, -0.03661, -0.02578 + 41000.0, 0.43, 1.6, -0.0326, -0.02464 + 41000.0, 0.43, 1.65, -0.02851, -0.0235 + 41000.0, 0.43, 1.7, -0.02437, -0.02236 + 41000.0, 0.43, 1.75, -0.02018, -0.02122 + 41000.0, 0.43, 1.8, -0.01594, -0.02008 + 41000.0, 0.43, 1.85, -0.01166, -0.01893 + 41000.0, 0.43, 1.9, -0.007352, -0.01779 + 41000.0, 0.43, 1.95, -0.003014, -0.01666 + 41000.0, 0.43, 2.0, 0.001344, -0.01552 + 41000.0, 0.43, 2.05, 0.005716, -0.01439 + 41000.0, 0.43, 2.1, 0.0101, -0.01326 + 41000.0, 0.43, 2.15, 0.01448, -0.01214 + 41000.0, 0.43, 2.2, 0.01885, -0.01102 + 41000.0, 0.43, 2.25, 0.02322, -0.009908 + 41000.0, 0.43, 2.3, 0.02756, -0.008804 + 41000.0, 0.43, 2.35, 0.03189, -0.007707 + 41000.0, 0.43, 2.4, 0.03618, -0.00662 + 41000.0, 0.43, 2.45, 0.04044, -0.005541 + 41000.0, 0.43, 2.5, 0.04465, -0.004473 + 41000.0, 0.43, 2.55, 0.04881, -0.003415 + 41000.0, 0.43, 2.6, 0.05292, -0.002368 + 41000.0, 0.43, 2.65, 0.05697, -0.001334 + 41000.0, 0.43, 2.7, 0.06095, -0.0003121 + 41000.0, 0.43, 2.75, 0.06485, 0.0006961 + 41000.0, 0.43, 2.8, 0.06867, 0.00169 + 41000.0, 0.43, 2.85, 0.07241, 0.002669 + 41000.0, 0.43, 2.9, 0.07605, 0.003632 + 41000.0, 0.43, 2.95, 0.07959, 0.004579 + 41000.0, 0.43, 3.0, 0.08303, 0.005509 + 41000.0, 0.43, 3.05, 0.08635, 0.006422 + 41000.0, 0.43, 3.1, 0.08956, 0.007315 + 41000.0, 0.43, 3.15, 0.09264, 0.00819 + 41000.0, 0.43, 3.2, 0.09558, 0.009044 + 41000.0, 0.43, 3.25, 0.09839, 0.009878 + 41000.0, 0.43, 3.3, 0.1011, 0.01069 + 41000.0, 0.43, 3.35, 0.1036, 0.01148 + 41000.0, 0.43, 3.4, 0.1059, 0.01225 + 41000.0, 0.43, 3.45, 0.1081, 0.01299 + 41000.0, 0.43, 3.5, 0.1102, 0.01371 + 41000.0, 0.43, 3.55, 0.112, 0.01441 + 41000.0, 0.43, 3.6, 0.1137, 0.01508 + 41000.0, 0.43, 3.65, 0.1152, 0.01572 + 41000.0, 0.43, 3.7, 0.1164, 0.01634 + 41000.0, 0.43, 3.75, 0.1175, 0.01692 + 41000.0, 0.43, 3.8, 0.1184, 0.01748 + 41000.0, 0.43, 3.85, 0.1191, 0.01801 + 41000.0, 0.43, 3.9, 0.1195, 0.01851 + 41000.0, 0.43, 3.95, 0.1197, 0.01898 + 41000.0, 0.43, 4.0, 0.1197, 0.01942 + 41000.0, 0.43, 4.05, 0.1177, 0.01973 + 41000.0, 0.43, 4.1, 0.1155, 0.02002 + 41000.0, 0.43, 4.15, 0.1132, 0.02028 + 41000.0, 0.43, 4.2, 0.1108, 0.02051 + 41000.0, 0.43, 4.25, 0.1082, 0.02071 + 41000.0, 0.43, 4.3, 0.1056, 0.02088 + 41000.0, 0.43, 4.35, 0.1028, 0.02103 + 41000.0, 0.43, 4.4, 0.09993, 0.02116 + 41000.0, 0.43, 4.45, 0.09698, 0.02125 + 41000.0, 0.43, 4.5, 0.09395, 0.02132 + 41000.0, 0.43, 4.55, 0.09084, 0.02136 + 41000.0, 0.43, 4.6, 0.08767, 0.02137 + 41000.0, 0.43, 4.65, 0.08444, 0.02136 + 41000.0, 0.43, 4.7, 0.08115, 0.02131 + 41000.0, 0.43, 4.75, 0.07782, 0.02125 + 41000.0, 0.43, 4.8, 0.07446, 0.02115 + 41000.0, 0.43, 4.85, 0.07106, 0.02103 + 41000.0, 0.43, 4.9, 0.06764, 0.02088 + 41000.0, 0.43, 4.95, 0.0642, 0.0207 + 41000.0, 0.43, 5.0, 0.06076, 0.0205 + 41000.0, 0.43, 5.05, 0.05704, 0.02029 + 41000.0, 0.43, 5.1, 0.05334, 0.02006 + 41000.0, 0.43, 5.15, 0.04966, 0.0198 + 41000.0, 0.43, 5.2, 0.04601, 0.01951 + 41000.0, 0.43, 5.25, 0.04241, 0.01919 + 41000.0, 0.43, 5.3, 0.03886, 0.01884 + 41000.0, 0.43, 5.35, 0.03538, 0.01847 + 41000.0, 0.43, 5.4, 0.03198, 0.01806 + 41000.0, 0.43, 5.45, 0.02867, 0.01762 + 41000.0, 0.43, 5.5, 0.02546, 0.01716 + 41000.0, 0.43, 5.55, 0.02236, 0.01666 + 41000.0, 0.43, 5.6, 0.01939, 0.01613 + 41000.0, 0.43, 5.65, 0.01656, 0.01557 + 41000.0, 0.43, 5.7, 0.01387, 0.01498 + 41000.0, 0.43, 5.75, 0.01134, 0.01436 + 41000.0, 0.43, 5.8, 0.008978, 0.01371 + 41000.0, 0.43, 5.85, 0.006799, 0.01302 + 41000.0, 0.43, 5.9, 0.004813, 0.0123 + 41000.0, 0.43, 5.95, 0.003031, 0.01154 + 41000.0, 0.43, 6.0, 0.001464, 0.01075 + 41000.0, 0.43, 6.05, 0.002861, 0.009779 + 41000.0, 0.43, 6.1, 0.00461, 0.008765 + 41000.0, 0.43, 6.15, 0.006702, 0.007711 + 41000.0, 0.43, 6.2, 0.009129, 0.006618 + 41000.0, 0.43, 6.25, 0.01188, 0.005486 + 41000.0, 0.43, 6.3, 0.01495, 0.004316 + 41000.0, 0.43, 6.35, 0.01833, 0.003108 + 41000.0, 0.43, 6.4, 0.02201, 0.001865 + 41000.0, 0.43, 6.45, 0.02598, 0.0005854 + 41000.0, 0.43, 6.5, 0.03023, -0.000729 + 41000.0, 0.43, 6.55, 0.03476, -0.002078 + 41000.0, 0.43, 6.6, 0.03955, -0.00346 + 41000.0, 0.43, 6.65, 0.0446, -0.004875 + 41000.0, 0.43, 6.7, 0.04989, -0.006322 + 41000.0, 0.43, 6.75, 0.05543, -0.0078 + 41000.0, 0.43, 6.8, 0.06119, -0.009309 + 41000.0, 0.43, 6.85, 0.06718, -0.01085 + 41000.0, 0.43, 6.9, 0.07338, -0.01242 + 41000.0, 0.43, 6.95, 0.07979, -0.01401 + 41000.0, 0.43, 7.0, 0.08639, -0.01564 + 41000.0, 0.43, 7.05, 0.09318, -0.01729 + 41000.0, 0.43, 7.1, 0.1001, -0.01896 + 41000.0, 0.43, 7.15, 0.1073, -0.02067 + 41000.0, 0.43, 7.2, 0.1146, -0.02239 + 41000.0, 0.43, 7.25, 0.122, -0.02414 + 41000.0, 0.43, 7.3, 0.1296, -0.02592 + 41000.0, 0.43, 7.35, 0.1374, -0.02772 + 41000.0, 0.43, 7.4, 0.1452, -0.02953 + 41000.0, 0.43, 7.45, 0.1532, -0.03137 + 41000.0, 0.43, 7.5, 0.1613, -0.03323 + 41000.0, 0.43, 7.55, 0.1695, -0.03511 + 41000.0, 0.43, 7.6, 0.1778, -0.03701 + 41000.0, 0.43, 7.65, 0.1861, -0.03893 + 41000.0, 0.43, 7.7, 0.1946, -0.04086 + 41000.0, 0.43, 7.75, 0.2031, -0.04281 + 41000.0, 0.43, 7.8, 0.2116, -0.04478 + 41000.0, 0.43, 7.85, 0.2202, -0.04676 + 41000.0, 0.43, 7.9, 0.2289, -0.04876 + 41000.0, 0.43, 7.95, 0.2376, -0.05077 + 41000.0, 0.43, 8.0, 0.2463, -0.05279 + 41000.0, 0.43, 8.05, 0.2528, -0.05466 + 41000.0, 0.43, 8.1, 0.2593, -0.05654 + 41000.0, 0.43, 8.15, 0.2658, -0.05843 + 41000.0, 0.43, 8.2, 0.2724, -0.06033 + 41000.0, 0.43, 8.25, 0.2789, -0.06225 + 41000.0, 0.43, 8.3, 0.2855, -0.06418 + 41000.0, 0.43, 8.35, 0.2921, -0.06612 + 41000.0, 0.43, 8.4, 0.2987, -0.06807 + 41000.0, 0.43, 8.45, 0.3053, -0.07003 + 41000.0, 0.43, 8.5, 0.3119, -0.072 + 41000.0, 0.43, 8.55, 0.3185, -0.07399 + 41000.0, 0.43, 8.6, 0.3252, -0.07598 + 41000.0, 0.43, 8.65, 0.3318, -0.07799 + 41000.0, 0.43, 8.7, 0.3385, -0.08 + 41000.0, 0.43, 8.75, 0.3452, -0.08203 + 41000.0, 0.43, 8.8, 0.3518, -0.08407 + 41000.0, 0.43, 8.85, 0.3585, -0.08612 + 41000.0, 0.43, 8.9, 0.3652, -0.08818 + 41000.0, 0.43, 8.95, 0.3719, -0.09025 + 41000.0, 0.43, 9.0, 0.3786, -0.09233 + 41000.0, 0.43, 9.05, 0.3853, -0.09442 + 41000.0, 0.43, 9.1, 0.3921, -0.09652 + 41000.0, 0.43, 9.15, 0.3988, -0.09863 + 41000.0, 0.43, 9.2, 0.4055, -0.1007 + 41000.0, 0.43, 9.25, 0.4123, -0.1029 + 41000.0, 0.43, 9.3, 0.419, -0.105 + 41000.0, 0.43, 9.35, 0.4257, -0.1072 + 41000.0, 0.43, 9.4, 0.4325, -0.1093 + 41000.0, 0.43, 9.45, 0.4393, -0.1115 + 41000.0, 0.43, 9.5, 0.446, -0.1137 + 41000.0, 0.43, 9.55, 0.4528, -0.1158 + 41000.0, 0.43, 9.6, 0.4595, -0.118 + 41000.0, 0.43, 9.65, 0.4663, -0.1202 + 41000.0, 0.43, 9.7, 0.4731, -0.1225 + 41000.0, 0.43, 9.75, 0.4799, -0.1247 + 41000.0, 0.43, 9.8, 0.4866, -0.1269 + 41000.0, 0.43, 9.85, 0.4934, -0.1291 + 41000.0, 0.43, 9.9, 0.5002, -0.1314 + 41000.0, 0.43, 9.95, 0.507, -0.1336 + 41000.0, 0.43, 10.0, 0.5137, -0.1359 + 41000.0, 0.43, 10.05, 0.5205, -0.1383 + 41000.0, 0.43, 10.1, 0.5272, -0.1407 + 41000.0, 0.43, 10.15, 0.5339, -0.1431 + 41000.0, 0.43, 10.2, 0.5406, -0.1455 + 41000.0, 0.43, 10.25, 0.5473, -0.148 + 41000.0, 0.43, 10.3, 0.5541, -0.1504 + 41000.0, 0.43, 10.35, 0.5608, -0.1528 + 41000.0, 0.43, 10.4, 0.5675, -0.1553 + 41000.0, 0.43, 10.45, 0.5742, -0.1577 + 41000.0, 0.43, 10.5, 0.5809, -0.1601 + 41000.0, 0.43, 10.55, 0.5876, -0.1626 + 41000.0, 0.43, 10.6, 0.5943, -0.165 + 41000.0, 0.43, 10.65, 0.601, -0.1675 + 41000.0, 0.43, 10.7, 0.6077, -0.1699 + 41000.0, 0.43, 10.75, 0.6144, -0.1724 + 41000.0, 0.43, 10.8, 0.6211, -0.1748 + 41000.0, 0.43, 10.85, 0.6278, -0.1773 + 41000.0, 0.43, 10.9, 0.6345, -0.1797 + 41000.0, 0.43, 10.95, 0.6412, -0.1822 + 41000.0, 0.43, 11.0, 0.6479, -0.1846 + 41000.0, 0.43, 11.05, 0.6546, -0.187 + 41000.0, 0.43, 11.1, 0.6612, -0.1895 + 41000.0, 0.43, 11.15, 0.6679, -0.1919 + 41000.0, 0.43, 11.2, 0.6746, -0.1943 + 41000.0, 0.43, 11.25, 0.6812, -0.1967 + 41000.0, 0.43, 11.3, 0.6879, -0.1991 + 41000.0, 0.43, 11.35, 0.6946, -0.2015 + 41000.0, 0.43, 11.4, 0.7012, -0.2039 + 41000.0, 0.43, 11.45, 0.7079, -0.2063 + 41000.0, 0.43, 11.5, 0.7145, -0.2087 + 41000.0, 0.43, 11.55, 0.7211, -0.211 + 41000.0, 0.43, 11.6, 0.7278, -0.2134 + 41000.0, 0.43, 11.65, 0.7344, -0.2157 + 41000.0, 0.43, 11.7, 0.741, -0.218 + 41000.0, 0.43, 11.75, 0.7476, -0.2203 + 41000.0, 0.43, 11.8, 0.7542, -0.2226 + 41000.0, 0.43, 11.85, 0.7608, -0.2249 + 41000.0, 0.43, 11.9, 0.7674, -0.2272 + 41000.0, 0.43, 11.95, 0.774, -0.2295 + 41000.0, 0.43, 12.0, 0.7806, -0.2317 + 41000.0, 0.43, 12.05, 0.7872, -0.2339 + 41000.0, 0.43, 12.1, 0.7938, -0.2362 + 41000.0, 0.43, 12.15, 0.8003, -0.2384 + 41000.0, 0.43, 12.2, 0.8069, -0.2405 + 41000.0, 0.43, 12.25, 0.8134, -0.2427 + 41000.0, 0.43, 12.3, 0.82, -0.2448 + 41000.0, 0.43, 12.35, 0.8265, -0.247 + 41000.0, 0.43, 12.4, 0.8331, -0.2491 + 41000.0, 0.43, 12.45, 0.8396, -0.2511 + 41000.0, 0.43, 12.5, 0.8461, -0.2532 + 41000.0, 0.43, 12.55, 0.8526, -0.2552 + 41000.0, 0.43, 12.6, 0.8591, -0.2573 + 41000.0, 0.43, 12.65, 0.8656, -0.2592 + 41000.0, 0.43, 12.7, 0.872, -0.2612 + 41000.0, 0.43, 12.75, 0.8785, -0.2632 + 41000.0, 0.43, 12.8, 0.885, -0.2651 + 41000.0, 0.43, 12.85, 0.8914, -0.267 + 41000.0, 0.43, 12.9, 0.8979, -0.2688 + 41000.0, 0.43, 12.95, 0.9043, -0.2707 + 41000.0, 0.43, 13.0, 0.9107, -0.2725 + 41000.0, 0.43, 13.05, 0.9171, -0.2743 + 41000.0, 0.43, 13.1, 0.9235, -0.276 + 41000.0, 0.43, 13.15, 0.9299, -0.2778 + 41000.0, 0.43, 13.2, 0.9363, -0.2795 + 41000.0, 0.43, 13.25, 0.9427, -0.2811 + 41000.0, 0.43, 13.3, 0.9491, -0.2828 + 41000.0, 0.43, 13.35, 0.9554, -0.2844 + 41000.0, 0.43, 13.4, 0.9618, -0.286 + 41000.0, 0.43, 13.45, 0.9681, -0.2875 + 41000.0, 0.43, 13.5, 0.9744, -0.289 + 41000.0, 0.43, 13.55, 0.9807, -0.2905 + 41000.0, 0.43, 13.6, 0.987, -0.2919 + 41000.0, 0.43, 13.65, 0.9933, -0.2934 + 41000.0, 0.43, 13.7, 0.9996, -0.2947 + 41000.0, 0.43, 13.75, 1.006, -0.2961 + 41000.0, 0.43, 13.8, 1.012, -0.2974 + 41000.0, 0.43, 13.85, 1.018, -0.2986 + 41000.0, 0.43, 13.9, 1.025, -0.2998 + 41000.0, 0.43, 13.95, 1.031, -0.301 + 41000.0, 0.43, 14.0, 1.037, -0.3022 + 41000.0, 0.43, 14.05, 1.043, -0.3033 + 41000.0, 0.43, 14.1, 1.049, -0.3044 + 41000.0, 0.43, 14.15, 1.055, -0.3054 + 41000.0, 0.43, 14.2, 1.062, -0.3064 + 41000.0, 0.43, 14.25, 1.068, -0.3073 + 41000.0, 0.43, 14.3, 1.074, -0.3082 + 41000.0, 0.43, 14.35, 1.08, -0.3091 + 41000.0, 0.43, 14.4, 1.086, -0.3099 + 41000.0, 0.43, 14.45, 1.092, -0.3107 + 41000.0, 0.43, 14.5, 1.098, -0.3114 + 41000.0, 0.43, 14.55, 1.104, -0.3121 + 41000.0, 0.43, 14.6, 1.11, -0.3127 + 41000.0, 0.43, 14.65, 1.116, -0.3133 + 41000.0, 0.43, 14.7, 1.122, -0.3138 + 41000.0, 0.43, 14.75, 1.128, -0.3143 + 41000.0, 0.43, 14.8, 1.134, -0.3147 + 41000.0, 0.43, 14.85, 1.14, -0.3151 + 41000.0, 0.43, 14.9, 1.146, -0.3155 + 41000.0, 0.43, 14.95, 1.152, -0.3158 + 41000.0, 0.43, 15.0, 1.158, -0.316 + 41000.0, 0.43, 15.05, 1.164, -0.3162 + 41000.0, 0.48, 0.0, -0.09756, -0.04885 + 41000.0, 0.48, 0.05, -0.09825, -0.04823 + 41000.0, 0.48, 0.1, -0.09871, -0.04759 + 41000.0, 0.48, 0.15, -0.09895, -0.04692 + 41000.0, 0.48, 0.2, -0.09897, -0.04624 + 41000.0, 0.48, 0.25, -0.09877, -0.04553 + 41000.0, 0.48, 0.3, -0.09837, -0.04481 + 41000.0, 0.48, 0.35, -0.09776, -0.04407 + 41000.0, 0.48, 0.4, -0.09696, -0.04331 + 41000.0, 0.48, 0.45, -0.09597, -0.04253 + 41000.0, 0.48, 0.5, -0.09479, -0.04174 + 41000.0, 0.48, 0.55, -0.09343, -0.04093 + 41000.0, 0.48, 0.6, -0.0919, -0.04011 + 41000.0, 0.48, 0.65, -0.0902, -0.03927 + 41000.0, 0.48, 0.7, -0.08833, -0.03842 + 41000.0, 0.48, 0.75, -0.08631, -0.03756 + 41000.0, 0.48, 0.8, -0.08414, -0.03668 + 41000.0, 0.48, 0.85, -0.08182, -0.03579 + 41000.0, 0.48, 0.9, -0.07936, -0.03489 + 41000.0, 0.48, 0.95, -0.07676, -0.03397 + 41000.0, 0.48, 1.0, -0.07403, -0.03305 + 41000.0, 0.48, 1.05, -0.07119, -0.03212 + 41000.0, 0.48, 1.1, -0.06822, -0.03118 + 41000.0, 0.48, 1.15, -0.06514, -0.03023 + 41000.0, 0.48, 1.2, -0.06195, -0.02927 + 41000.0, 0.48, 1.25, -0.05866, -0.02831 + 41000.0, 0.48, 1.3, -0.05527, -0.02734 + 41000.0, 0.48, 1.35, -0.0518, -0.02636 + 41000.0, 0.48, 1.4, -0.04824, -0.02538 + 41000.0, 0.48, 1.45, -0.0446, -0.02439 + 41000.0, 0.48, 1.5, -0.04088, -0.0234 + 41000.0, 0.48, 1.55, -0.0371, -0.02241 + 41000.0, 0.48, 1.6, -0.03326, -0.02141 + 41000.0, 0.48, 1.65, -0.02936, -0.02042 + 41000.0, 0.48, 1.7, -0.0254, -0.01942 + 41000.0, 0.48, 1.75, -0.0214, -0.01842 + 41000.0, 0.48, 1.8, -0.01737, -0.01742 + 41000.0, 0.48, 1.85, -0.01329, -0.01642 + 41000.0, 0.48, 1.9, -0.009192, -0.01542 + 41000.0, 0.48, 1.95, -0.005066, -0.01442 + 41000.0, 0.48, 2.0, -0.000923, -0.01342 + 41000.0, 0.48, 2.05, 0.003232, -0.01243 + 41000.0, 0.48, 2.1, 0.007394, -0.01144 + 41000.0, 0.48, 2.15, 0.01156, -0.01046 + 41000.0, 0.48, 2.2, 0.01572, -0.009477 + 41000.0, 0.48, 2.25, 0.01986, -0.008502 + 41000.0, 0.48, 2.3, 0.024, -0.007533 + 41000.0, 0.48, 2.35, 0.02811, -0.006571 + 41000.0, 0.48, 2.4, 0.03219, -0.005617 + 41000.0, 0.48, 2.45, 0.03624, -0.00467 + 41000.0, 0.48, 2.5, 0.04026, -0.003731 + 41000.0, 0.48, 2.55, 0.04423, -0.002802 + 41000.0, 0.48, 2.6, 0.04815, -0.001883 + 41000.0, 0.48, 2.65, 0.05201, -0.0009735 + 41000.0, 0.48, 2.7, 0.05582, -7.542e-05 + 41000.0, 0.48, 2.75, 0.05956, 0.0008111 + 41000.0, 0.48, 2.8, 0.06323, 0.001685 + 41000.0, 0.48, 2.85, 0.06682, 0.002547 + 41000.0, 0.48, 2.9, 0.07033, 0.003395 + 41000.0, 0.48, 2.95, 0.07374, 0.004228 + 41000.0, 0.48, 3.0, 0.07707, 0.005047 + 41000.0, 0.48, 3.05, 0.0803, 0.005851 + 41000.0, 0.48, 3.1, 0.08342, 0.006639 + 41000.0, 0.48, 3.15, 0.08643, 0.00741 + 41000.0, 0.48, 3.2, 0.08932, 0.008163 + 41000.0, 0.48, 3.25, 0.09209, 0.008899 + 41000.0, 0.48, 3.3, 0.09474, 0.009617 + 41000.0, 0.48, 3.35, 0.09725, 0.01032 + 41000.0, 0.48, 3.4, 0.09962, 0.01099 + 41000.0, 0.48, 3.45, 0.1018, 0.01165 + 41000.0, 0.48, 3.5, 0.1039, 0.01229 + 41000.0, 0.48, 3.55, 0.1058, 0.01291 + 41000.0, 0.48, 3.6, 0.1076, 0.0135 + 41000.0, 0.48, 3.65, 0.1092, 0.01407 + 41000.0, 0.48, 3.7, 0.1106, 0.01462 + 41000.0, 0.48, 3.75, 0.1119, 0.01514 + 41000.0, 0.48, 3.8, 0.1129, 0.01564 + 41000.0, 0.48, 3.85, 0.1138, 0.01611 + 41000.0, 0.48, 3.9, 0.1145, 0.01656 + 41000.0, 0.48, 3.95, 0.115, 0.01698 + 41000.0, 0.48, 4.0, 0.1152, 0.01737 + 41000.0, 0.48, 4.05, 0.1137, 0.01765 + 41000.0, 0.48, 4.1, 0.1121, 0.01791 + 41000.0, 0.48, 4.15, 0.1103, 0.01814 + 41000.0, 0.48, 4.2, 0.1085, 0.01835 + 41000.0, 0.48, 4.25, 0.1065, 0.01854 + 41000.0, 0.48, 4.3, 0.1044, 0.0187 + 41000.0, 0.48, 4.35, 0.1023, 0.01884 + 41000.0, 0.48, 4.4, 0.1, 0.01896 + 41000.0, 0.48, 4.45, 0.09773, 0.01905 + 41000.0, 0.48, 4.5, 0.09533, 0.01912 + 41000.0, 0.48, 4.55, 0.09288, 0.01917 + 41000.0, 0.48, 4.6, 0.09036, 0.0192 + 41000.0, 0.48, 4.65, 0.08779, 0.0192 + 41000.0, 0.48, 4.7, 0.08517, 0.01918 + 41000.0, 0.48, 4.75, 0.08251, 0.01913 + 41000.0, 0.48, 4.8, 0.07983, 0.01906 + 41000.0, 0.48, 4.85, 0.07711, 0.01897 + 41000.0, 0.48, 4.9, 0.07437, 0.01886 + 41000.0, 0.48, 4.95, 0.07162, 0.01872 + 41000.0, 0.48, 5.0, 0.06887, 0.01856 + 41000.0, 0.48, 5.05, 0.0659, 0.01841 + 41000.0, 0.48, 5.1, 0.06293, 0.01823 + 41000.0, 0.48, 5.15, 0.05999, 0.01803 + 41000.0, 0.48, 5.2, 0.05707, 0.01781 + 41000.0, 0.48, 5.25, 0.05419, 0.01756 + 41000.0, 0.48, 5.3, 0.05137, 0.01728 + 41000.0, 0.48, 5.35, 0.04859, 0.01699 + 41000.0, 0.48, 5.4, 0.04589, 0.01666 + 41000.0, 0.48, 5.45, 0.04326, 0.01631 + 41000.0, 0.48, 5.5, 0.04073, 0.01593 + 41000.0, 0.48, 5.55, 0.03828, 0.01553 + 41000.0, 0.48, 5.6, 0.03595, 0.0151 + 41000.0, 0.48, 5.65, 0.03373, 0.01464 + 41000.0, 0.48, 5.7, 0.03163, 0.01416 + 41000.0, 0.48, 5.75, 0.02968, 0.01364 + 41000.0, 0.48, 5.8, 0.02786, 0.0131 + 41000.0, 0.48, 5.85, 0.02621, 0.01253 + 41000.0, 0.48, 5.9, 0.02472, 0.01193 + 41000.0, 0.48, 5.95, 0.0234, 0.0113 + 41000.0, 0.48, 6.0, 0.02227, 0.01064 + 41000.0, 0.48, 6.05, 0.02366, 0.009807 + 41000.0, 0.48, 6.1, 0.02536, 0.008936 + 41000.0, 0.48, 6.15, 0.02735, 0.008029 + 41000.0, 0.48, 6.2, 0.02963, 0.007086 + 41000.0, 0.48, 6.25, 0.03219, 0.006109 + 41000.0, 0.48, 6.3, 0.03502, 0.005097 + 41000.0, 0.48, 6.35, 0.03811, 0.004052 + 41000.0, 0.48, 6.4, 0.04146, 0.002974 + 41000.0, 0.48, 6.45, 0.04506, 0.001864 + 41000.0, 0.48, 6.5, 0.0489, 0.0007226 + 41000.0, 0.48, 6.55, 0.05298, -0.0004497 + 41000.0, 0.48, 6.6, 0.05728, -0.001652 + 41000.0, 0.48, 6.65, 0.0618, -0.002884 + 41000.0, 0.48, 6.7, 0.06654, -0.004145 + 41000.0, 0.48, 6.75, 0.07148, -0.005434 + 41000.0, 0.48, 6.8, 0.07662, -0.00675 + 41000.0, 0.48, 6.85, 0.08195, -0.008093 + 41000.0, 0.48, 6.9, 0.08746, -0.009463 + 41000.0, 0.48, 6.95, 0.09315, -0.01086 + 41000.0, 0.48, 7.0, 0.099, -0.01228 + 41000.0, 0.48, 7.05, 0.105, -0.01372 + 41000.0, 0.48, 7.1, 0.1112, -0.01519 + 41000.0, 0.48, 7.15, 0.1175, -0.01668 + 41000.0, 0.48, 7.2, 0.124, -0.01819 + 41000.0, 0.48, 7.25, 0.1305, -0.01972 + 41000.0, 0.48, 7.3, 0.1373, -0.02128 + 41000.0, 0.48, 7.35, 0.1441, -0.02285 + 41000.0, 0.48, 7.4, 0.151, -0.02445 + 41000.0, 0.48, 7.45, 0.1581, -0.02606 + 41000.0, 0.48, 7.5, 0.1652, -0.02769 + 41000.0, 0.48, 7.55, 0.1724, -0.02934 + 41000.0, 0.48, 7.6, 0.1797, -0.031 + 41000.0, 0.48, 7.65, 0.1871, -0.03269 + 41000.0, 0.48, 7.7, 0.1945, -0.03438 + 41000.0, 0.48, 7.75, 0.202, -0.0361 + 41000.0, 0.48, 7.8, 0.2096, -0.03782 + 41000.0, 0.48, 7.85, 0.2171, -0.03956 + 41000.0, 0.48, 7.9, 0.2248, -0.04131 + 41000.0, 0.48, 7.95, 0.2324, -0.04308 + 41000.0, 0.48, 8.0, 0.2401, -0.04485 + 41000.0, 0.48, 8.05, 0.2459, -0.04648 + 41000.0, 0.48, 8.1, 0.2517, -0.04813 + 41000.0, 0.48, 8.15, 0.2575, -0.04978 + 41000.0, 0.48, 8.2, 0.2634, -0.05145 + 41000.0, 0.48, 8.25, 0.2693, -0.05312 + 41000.0, 0.48, 8.3, 0.2751, -0.0548 + 41000.0, 0.48, 8.35, 0.281, -0.0565 + 41000.0, 0.48, 8.4, 0.2869, -0.05821 + 41000.0, 0.48, 8.45, 0.2928, -0.05992 + 41000.0, 0.48, 8.5, 0.2987, -0.06165 + 41000.0, 0.48, 8.55, 0.3046, -0.06338 + 41000.0, 0.48, 8.6, 0.3106, -0.06513 + 41000.0, 0.48, 8.65, 0.3165, -0.06688 + 41000.0, 0.48, 8.7, 0.3225, -0.06865 + 41000.0, 0.48, 8.75, 0.3284, -0.07042 + 41000.0, 0.48, 8.8, 0.3344, -0.0722 + 41000.0, 0.48, 8.85, 0.3404, -0.074 + 41000.0, 0.48, 8.9, 0.3464, -0.0758 + 41000.0, 0.48, 8.95, 0.3524, -0.07761 + 41000.0, 0.48, 9.0, 0.3584, -0.07943 + 41000.0, 0.48, 9.05, 0.3644, -0.08126 + 41000.0, 0.48, 9.1, 0.3704, -0.0831 + 41000.0, 0.48, 9.15, 0.3764, -0.08495 + 41000.0, 0.48, 9.2, 0.3824, -0.0868 + 41000.0, 0.48, 9.25, 0.3885, -0.08867 + 41000.0, 0.48, 9.3, 0.3945, -0.09054 + 41000.0, 0.48, 9.35, 0.4005, -0.09243 + 41000.0, 0.48, 9.4, 0.4066, -0.09432 + 41000.0, 0.48, 9.45, 0.4126, -0.09621 + 41000.0, 0.48, 9.5, 0.4187, -0.09812 + 41000.0, 0.48, 9.55, 0.4247, -0.1 + 41000.0, 0.48, 9.6, 0.4308, -0.102 + 41000.0, 0.48, 9.65, 0.4369, -0.1039 + 41000.0, 0.48, 9.7, 0.4429, -0.1058 + 41000.0, 0.48, 9.75, 0.449, -0.1078 + 41000.0, 0.48, 9.8, 0.4551, -0.1097 + 41000.0, 0.48, 9.85, 0.4611, -0.1117 + 41000.0, 0.48, 9.9, 0.4672, -0.1137 + 41000.0, 0.48, 9.95, 0.4733, -0.1156 + 41000.0, 0.48, 10.0, 0.4794, -0.1176 + 41000.0, 0.48, 10.05, 0.4854, -0.1197 + 41000.0, 0.48, 10.1, 0.4914, -0.1219 + 41000.0, 0.48, 10.15, 0.4974, -0.124 + 41000.0, 0.48, 10.2, 0.5035, -0.1261 + 41000.0, 0.48, 10.25, 0.5095, -0.1282 + 41000.0, 0.48, 10.3, 0.5155, -0.1304 + 41000.0, 0.48, 10.35, 0.5215, -0.1325 + 41000.0, 0.48, 10.4, 0.5275, -0.1347 + 41000.0, 0.48, 10.45, 0.5336, -0.1368 + 41000.0, 0.48, 10.5, 0.5396, -0.139 + 41000.0, 0.48, 10.55, 0.5456, -0.1411 + 41000.0, 0.48, 10.6, 0.5516, -0.1433 + 41000.0, 0.48, 10.65, 0.5576, -0.1454 + 41000.0, 0.48, 10.7, 0.5637, -0.1476 + 41000.0, 0.48, 10.75, 0.5697, -0.1498 + 41000.0, 0.48, 10.8, 0.5757, -0.1519 + 41000.0, 0.48, 10.85, 0.5817, -0.1541 + 41000.0, 0.48, 10.9, 0.5877, -0.1562 + 41000.0, 0.48, 10.95, 0.5937, -0.1584 + 41000.0, 0.48, 11.0, 0.5997, -0.1605 + 41000.0, 0.48, 11.05, 0.6057, -0.1627 + 41000.0, 0.48, 11.1, 0.6117, -0.1648 + 41000.0, 0.48, 11.15, 0.6177, -0.1669 + 41000.0, 0.48, 11.2, 0.6237, -0.1691 + 41000.0, 0.48, 11.25, 0.6297, -0.1712 + 41000.0, 0.48, 11.3, 0.6357, -0.1733 + 41000.0, 0.48, 11.35, 0.6417, -0.1754 + 41000.0, 0.48, 11.4, 0.6477, -0.1775 + 41000.0, 0.48, 11.45, 0.6536, -0.1796 + 41000.0, 0.48, 11.5, 0.6596, -0.1817 + 41000.0, 0.48, 11.55, 0.6656, -0.1838 + 41000.0, 0.48, 11.6, 0.6716, -0.1859 + 41000.0, 0.48, 11.65, 0.6775, -0.1879 + 41000.0, 0.48, 11.7, 0.6835, -0.19 + 41000.0, 0.48, 11.75, 0.6895, -0.192 + 41000.0, 0.48, 11.8, 0.6954, -0.194 + 41000.0, 0.48, 11.85, 0.7014, -0.1961 + 41000.0, 0.48, 11.9, 0.7073, -0.1981 + 41000.0, 0.48, 11.95, 0.7133, -0.2001 + 41000.0, 0.48, 12.0, 0.7192, -0.202 + 41000.0, 0.48, 12.05, 0.7251, -0.204 + 41000.0, 0.48, 12.1, 0.7311, -0.206 + 41000.0, 0.48, 12.15, 0.737, -0.2079 + 41000.0, 0.48, 12.2, 0.7429, -0.2098 + 41000.0, 0.48, 12.25, 0.7488, -0.2117 + 41000.0, 0.48, 12.3, 0.7547, -0.2136 + 41000.0, 0.48, 12.35, 0.7606, -0.2155 + 41000.0, 0.48, 12.4, 0.7665, -0.2173 + 41000.0, 0.48, 12.45, 0.7724, -0.2191 + 41000.0, 0.48, 12.5, 0.7783, -0.221 + 41000.0, 0.48, 12.55, 0.7842, -0.2228 + 41000.0, 0.48, 12.6, 0.7901, -0.2245 + 41000.0, 0.48, 12.65, 0.796, -0.2263 + 41000.0, 0.48, 12.7, 0.8018, -0.228 + 41000.0, 0.48, 12.75, 0.8077, -0.2297 + 41000.0, 0.48, 12.8, 0.8135, -0.2314 + 41000.0, 0.48, 12.85, 0.8194, -0.2331 + 41000.0, 0.48, 12.9, 0.8252, -0.2347 + 41000.0, 0.48, 12.95, 0.831, -0.2363 + 41000.0, 0.48, 13.0, 0.8369, -0.2379 + 41000.0, 0.48, 13.05, 0.8427, -0.2395 + 41000.0, 0.48, 13.1, 0.8485, -0.2411 + 41000.0, 0.48, 13.15, 0.8543, -0.2426 + 41000.0, 0.48, 13.2, 0.8601, -0.2441 + 41000.0, 0.48, 13.25, 0.8659, -0.2455 + 41000.0, 0.48, 13.3, 0.8717, -0.247 + 41000.0, 0.48, 13.35, 0.8774, -0.2484 + 41000.0, 0.48, 13.4, 0.8832, -0.2498 + 41000.0, 0.48, 13.45, 0.8889, -0.2511 + 41000.0, 0.48, 13.5, 0.8947, -0.2525 + 41000.0, 0.48, 13.55, 0.9004, -0.2537 + 41000.0, 0.48, 13.6, 0.9062, -0.255 + 41000.0, 0.48, 13.65, 0.9119, -0.2562 + 41000.0, 0.48, 13.7, 0.9176, -0.2574 + 41000.0, 0.48, 13.75, 0.9233, -0.2586 + 41000.0, 0.48, 13.8, 0.929, -0.2597 + 41000.0, 0.48, 13.85, 0.9347, -0.2609 + 41000.0, 0.48, 13.9, 0.9404, -0.2619 + 41000.0, 0.48, 13.95, 0.946, -0.263 + 41000.0, 0.48, 14.0, 0.9517, -0.264 + 41000.0, 0.48, 14.05, 0.9574, -0.2649 + 41000.0, 0.48, 14.1, 0.963, -0.2658 + 41000.0, 0.48, 14.15, 0.9686, -0.2667 + 41000.0, 0.48, 14.2, 0.9743, -0.2676 + 41000.0, 0.48, 14.25, 0.9799, -0.2684 + 41000.0, 0.48, 14.3, 0.9855, -0.2692 + 41000.0, 0.48, 14.35, 0.9911, -0.2699 + 41000.0, 0.48, 14.4, 0.9966, -0.2706 + 41000.0, 0.48, 14.45, 1.002, -0.2713 + 41000.0, 0.48, 14.5, 1.008, -0.2719 + 41000.0, 0.48, 14.55, 1.013, -0.2725 + 41000.0, 0.48, 14.6, 1.019, -0.273 + 41000.0, 0.48, 14.65, 1.024, -0.2735 + 41000.0, 0.48, 14.7, 1.03, -0.274 + 41000.0, 0.48, 14.75, 1.035, -0.2744 + 41000.0, 0.48, 14.8, 1.041, -0.2748 + 41000.0, 0.48, 14.85, 1.046, -0.2751 + 41000.0, 0.48, 14.9, 1.052, -0.2754 + 41000.0, 0.48, 14.95, 1.057, -0.2756 + 41000.0, 0.48, 15.0, 1.063, -0.2758 + 41000.0, 0.48, 15.05, 1.068, -0.2759 + 41000.0, 0.53, 0.0, -0.1055, -0.03722 + 41000.0, 0.53, 0.05, -0.1055, -0.03674 + 41000.0, 0.53, 0.1, -0.1052, -0.03625 + 41000.0, 0.53, 0.15, -0.1048, -0.03573 + 41000.0, 0.53, 0.2, -0.1043, -0.03521 + 41000.0, 0.53, 0.25, -0.1035, -0.03466 + 41000.0, 0.53, 0.3, -0.1026, -0.03411 + 41000.0, 0.53, 0.35, -0.1016, -0.03353 + 41000.0, 0.53, 0.4, -0.1003, -0.03295 + 41000.0, 0.53, 0.45, -0.09898, -0.03235 + 41000.0, 0.53, 0.5, -0.09746, -0.03174 + 41000.0, 0.53, 0.55, -0.09581, -0.03112 + 41000.0, 0.53, 0.6, -0.09402, -0.03048 + 41000.0, 0.53, 0.65, -0.0921, -0.02983 + 41000.0, 0.53, 0.7, -0.09005, -0.02918 + 41000.0, 0.53, 0.75, -0.08788, -0.02851 + 41000.0, 0.53, 0.8, -0.08559, -0.02783 + 41000.0, 0.53, 0.85, -0.08318, -0.02714 + 41000.0, 0.53, 0.9, -0.08066, -0.02645 + 41000.0, 0.53, 0.95, -0.07804, -0.02574 + 41000.0, 0.53, 1.0, -0.07531, -0.02503 + 41000.0, 0.53, 1.05, -0.07249, -0.02431 + 41000.0, 0.53, 1.1, -0.06958, -0.02358 + 41000.0, 0.53, 1.15, -0.06657, -0.02285 + 41000.0, 0.53, 1.2, -0.06349, -0.02211 + 41000.0, 0.53, 1.25, -0.06032, -0.02137 + 41000.0, 0.53, 1.3, -0.05708, -0.02062 + 41000.0, 0.53, 1.35, -0.05376, -0.01986 + 41000.0, 0.53, 1.4, -0.05038, -0.0191 + 41000.0, 0.53, 1.45, -0.04694, -0.01834 + 41000.0, 0.53, 1.5, -0.04344, -0.01757 + 41000.0, 0.53, 1.55, -0.03989, -0.0168 + 41000.0, 0.53, 1.6, -0.03629, -0.01603 + 41000.0, 0.53, 1.65, -0.03265, -0.01526 + 41000.0, 0.53, 1.7, -0.02896, -0.01449 + 41000.0, 0.53, 1.75, -0.02524, -0.01371 + 41000.0, 0.53, 1.8, -0.02148, -0.01294 + 41000.0, 0.53, 1.85, -0.01771, -0.01216 + 41000.0, 0.53, 1.9, -0.0139, -0.01139 + 41000.0, 0.53, 1.95, -0.01008, -0.01061 + 41000.0, 0.53, 2.0, -0.006248, -0.009842 + 41000.0, 0.53, 2.05, -0.002405, -0.009073 + 41000.0, 0.53, 2.1, 0.001444, -0.008305 + 41000.0, 0.53, 2.15, 0.005293, -0.007541 + 41000.0, 0.53, 2.2, 0.009138, -0.00678 + 41000.0, 0.53, 2.25, 0.01298, -0.006024 + 41000.0, 0.53, 2.3, 0.0168, -0.005271 + 41000.0, 0.53, 2.35, 0.02061, -0.004524 + 41000.0, 0.53, 2.4, 0.02439, -0.003781 + 41000.0, 0.53, 2.45, 0.02815, -0.003045 + 41000.0, 0.53, 2.5, 0.03188, -0.002315 + 41000.0, 0.53, 2.55, 0.03558, -0.001592 + 41000.0, 0.53, 2.6, 0.03924, -0.0008756 + 41000.0, 0.53, 2.65, 0.04285, -0.0001674 + 41000.0, 0.53, 2.7, 0.04642, 0.0005327 + 41000.0, 0.53, 2.75, 0.04993, 0.001224 + 41000.0, 0.53, 2.8, 0.05339, 0.001906 + 41000.0, 0.53, 2.85, 0.05678, 0.002579 + 41000.0, 0.53, 2.9, 0.06011, 0.003241 + 41000.0, 0.53, 2.95, 0.06338, 0.003893 + 41000.0, 0.53, 3.0, 0.06656, 0.004534 + 41000.0, 0.53, 3.05, 0.06967, 0.005163 + 41000.0, 0.53, 3.1, 0.0727, 0.00578 + 41000.0, 0.53, 3.15, 0.07564, 0.006385 + 41000.0, 0.53, 3.2, 0.07848, 0.006976 + 41000.0, 0.53, 3.25, 0.08124, 0.007555 + 41000.0, 0.53, 3.3, 0.08389, 0.008119 + 41000.0, 0.53, 3.35, 0.08643, 0.008669 + 41000.0, 0.53, 3.4, 0.08887, 0.009204 + 41000.0, 0.53, 3.45, 0.09119, 0.009723 + 41000.0, 0.53, 3.5, 0.0934, 0.01023 + 41000.0, 0.53, 3.55, 0.09548, 0.01071 + 41000.0, 0.53, 3.6, 0.09744, 0.01119 + 41000.0, 0.53, 3.65, 0.09926, 0.01164 + 41000.0, 0.53, 3.7, 0.101, 0.01207 + 41000.0, 0.53, 3.75, 0.1025, 0.01249 + 41000.0, 0.53, 3.8, 0.1039, 0.01289 + 41000.0, 0.53, 3.85, 0.1052, 0.01327 + 41000.0, 0.53, 3.9, 0.1063, 0.01363 + 41000.0, 0.53, 3.95, 0.1072, 0.01397 + 41000.0, 0.53, 4.0, 0.108, 0.01429 + 41000.0, 0.53, 4.05, 0.1074, 0.01452 + 41000.0, 0.53, 4.1, 0.1067, 0.01473 + 41000.0, 0.53, 4.15, 0.1059, 0.01492 + 41000.0, 0.53, 4.2, 0.105, 0.0151 + 41000.0, 0.53, 4.25, 0.104, 0.01526 + 41000.0, 0.53, 4.3, 0.1029, 0.0154 + 41000.0, 0.53, 4.35, 0.1018, 0.01553 + 41000.0, 0.53, 4.4, 0.1006, 0.01564 + 41000.0, 0.53, 4.45, 0.09936, 0.01573 + 41000.0, 0.53, 4.5, 0.09805, 0.0158 + 41000.0, 0.53, 4.55, 0.09668, 0.01586 + 41000.0, 0.53, 4.6, 0.09527, 0.0159 + 41000.0, 0.53, 4.65, 0.09382, 0.01592 + 41000.0, 0.53, 4.7, 0.09233, 0.01593 + 41000.0, 0.53, 4.75, 0.09082, 0.01592 + 41000.0, 0.53, 4.8, 0.08927, 0.01589 + 41000.0, 0.53, 4.85, 0.08771, 0.01585 + 41000.0, 0.53, 4.9, 0.08612, 0.01579 + 41000.0, 0.53, 4.95, 0.08453, 0.01571 + 41000.0, 0.53, 5.0, 0.08294, 0.01562 + 41000.0, 0.53, 5.05, 0.0812, 0.01554 + 41000.0, 0.53, 5.1, 0.07947, 0.01544 + 41000.0, 0.53, 5.15, 0.07775, 0.01533 + 41000.0, 0.53, 5.2, 0.07606, 0.0152 + 41000.0, 0.53, 5.25, 0.0744, 0.01505 + 41000.0, 0.53, 5.3, 0.07277, 0.01488 + 41000.0, 0.53, 5.35, 0.07118, 0.01469 + 41000.0, 0.53, 5.4, 0.06964, 0.01449 + 41000.0, 0.53, 5.45, 0.06816, 0.01426 + 41000.0, 0.53, 5.5, 0.06675, 0.01402 + 41000.0, 0.53, 5.55, 0.0654, 0.01375 + 41000.0, 0.53, 5.6, 0.06414, 0.01347 + 41000.0, 0.53, 5.65, 0.06296, 0.01316 + 41000.0, 0.53, 5.7, 0.06188, 0.01283 + 41000.0, 0.53, 5.75, 0.06089, 0.01248 + 41000.0, 0.53, 5.8, 0.06001, 0.01211 + 41000.0, 0.53, 5.85, 0.05925, 0.01172 + 41000.0, 0.53, 5.9, 0.05861, 0.0113 + 41000.0, 0.53, 5.95, 0.0581, 0.01086 + 41000.0, 0.53, 6.0, 0.05773, 0.01039 + 41000.0, 0.53, 6.05, 0.05922, 0.009777 + 41000.0, 0.53, 6.1, 0.06094, 0.009131 + 41000.0, 0.53, 6.15, 0.06287, 0.008455 + 41000.0, 0.53, 6.2, 0.06502, 0.007751 + 41000.0, 0.53, 6.25, 0.06737, 0.007019 + 41000.0, 0.53, 6.3, 0.06992, 0.006259 + 41000.0, 0.53, 6.35, 0.07267, 0.005472 + 41000.0, 0.53, 6.4, 0.0756, 0.004659 + 41000.0, 0.53, 6.45, 0.07873, 0.00382 + 41000.0, 0.53, 6.5, 0.08203, 0.002955 + 41000.0, 0.53, 6.55, 0.0855, 0.002066 + 41000.0, 0.53, 6.6, 0.08915, 0.001152 + 41000.0, 0.53, 6.65, 0.09295, 0.0002144 + 41000.0, 0.53, 6.7, 0.09691, -0.0007463 + 41000.0, 0.53, 6.75, 0.101, -0.00173 + 41000.0, 0.53, 6.8, 0.1053, -0.002735 + 41000.0, 0.53, 6.85, 0.1097, -0.003762 + 41000.0, 0.53, 6.9, 0.1142, -0.00481 + 41000.0, 0.53, 6.95, 0.1189, -0.005878 + 41000.0, 0.53, 7.0, 0.1237, -0.006966 + 41000.0, 0.53, 7.05, 0.1286, -0.008074 + 41000.0, 0.53, 7.1, 0.1336, -0.0092 + 41000.0, 0.53, 7.15, 0.1388, -0.01034 + 41000.0, 0.53, 7.2, 0.144, -0.01151 + 41000.0, 0.53, 7.25, 0.1493, -0.01269 + 41000.0, 0.53, 7.3, 0.1548, -0.01388 + 41000.0, 0.53, 7.35, 0.1603, -0.01509 + 41000.0, 0.53, 7.4, 0.1659, -0.01632 + 41000.0, 0.53, 7.45, 0.1716, -0.01756 + 41000.0, 0.53, 7.5, 0.1773, -0.01882 + 41000.0, 0.53, 7.55, 0.1831, -0.02009 + 41000.0, 0.53, 7.6, 0.189, -0.02137 + 41000.0, 0.53, 7.65, 0.1949, -0.02267 + 41000.0, 0.53, 7.7, 0.2009, -0.02398 + 41000.0, 0.53, 7.75, 0.2069, -0.0253 + 41000.0, 0.53, 7.8, 0.213, -0.02663 + 41000.0, 0.53, 7.85, 0.219, -0.02797 + 41000.0, 0.53, 7.9, 0.2252, -0.02932 + 41000.0, 0.53, 7.95, 0.2313, -0.03068 + 41000.0, 0.53, 8.0, 0.2374, -0.03205 + 41000.0, 0.53, 8.05, 0.2422, -0.0333 + 41000.0, 0.53, 8.1, 0.247, -0.03456 + 41000.0, 0.53, 8.15, 0.2518, -0.03582 + 41000.0, 0.53, 8.2, 0.2567, -0.0371 + 41000.0, 0.53, 8.25, 0.2615, -0.03838 + 41000.0, 0.53, 8.3, 0.2663, -0.03967 + 41000.0, 0.53, 8.35, 0.2712, -0.04096 + 41000.0, 0.53, 8.4, 0.276, -0.04227 + 41000.0, 0.53, 8.45, 0.2809, -0.04358 + 41000.0, 0.53, 8.5, 0.2858, -0.0449 + 41000.0, 0.53, 8.55, 0.2907, -0.04623 + 41000.0, 0.53, 8.6, 0.2955, -0.04757 + 41000.0, 0.53, 8.65, 0.3004, -0.04891 + 41000.0, 0.53, 8.7, 0.3053, -0.05026 + 41000.0, 0.53, 8.75, 0.3103, -0.05162 + 41000.0, 0.53, 8.8, 0.3152, -0.05298 + 41000.0, 0.53, 8.85, 0.3201, -0.05436 + 41000.0, 0.53, 8.9, 0.325, -0.05574 + 41000.0, 0.53, 8.95, 0.33, -0.05712 + 41000.0, 0.53, 9.0, 0.3349, -0.05852 + 41000.0, 0.53, 9.05, 0.3399, -0.05992 + 41000.0, 0.53, 9.1, 0.3448, -0.06133 + 41000.0, 0.53, 9.15, 0.3498, -0.06274 + 41000.0, 0.53, 9.2, 0.3548, -0.06416 + 41000.0, 0.53, 9.25, 0.3597, -0.06559 + 41000.0, 0.53, 9.3, 0.3647, -0.06703 + 41000.0, 0.53, 9.35, 0.3697, -0.06847 + 41000.0, 0.53, 9.4, 0.3747, -0.06992 + 41000.0, 0.53, 9.45, 0.3797, -0.07137 + 41000.0, 0.53, 9.5, 0.3847, -0.07283 + 41000.0, 0.53, 9.55, 0.3897, -0.0743 + 41000.0, 0.53, 9.6, 0.3947, -0.07577 + 41000.0, 0.53, 9.65, 0.3997, -0.07726 + 41000.0, 0.53, 9.7, 0.4047, -0.07874 + 41000.0, 0.53, 9.75, 0.4097, -0.08023 + 41000.0, 0.53, 9.8, 0.4147, -0.08173 + 41000.0, 0.53, 9.85, 0.4197, -0.08324 + 41000.0, 0.53, 9.9, 0.4247, -0.08475 + 41000.0, 0.53, 9.95, 0.4297, -0.08627 + 41000.0, 0.53, 10.0, 0.4347, -0.08779 + 41000.0, 0.53, 10.05, 0.4397, -0.08941 + 41000.0, 0.53, 10.1, 0.4447, -0.09104 + 41000.0, 0.53, 10.15, 0.4496, -0.09267 + 41000.0, 0.53, 10.2, 0.4546, -0.09431 + 41000.0, 0.53, 10.25, 0.4596, -0.09595 + 41000.0, 0.53, 10.3, 0.4645, -0.0976 + 41000.0, 0.53, 10.35, 0.4695, -0.09925 + 41000.0, 0.53, 10.4, 0.4745, -0.1009 + 41000.0, 0.53, 10.45, 0.4795, -0.1026 + 41000.0, 0.53, 10.5, 0.4844, -0.1042 + 41000.0, 0.53, 10.55, 0.4894, -0.1059 + 41000.0, 0.53, 10.6, 0.4944, -0.1075 + 41000.0, 0.53, 10.65, 0.4993, -0.1092 + 41000.0, 0.53, 10.7, 0.5043, -0.1108 + 41000.0, 0.53, 10.75, 0.5093, -0.1125 + 41000.0, 0.53, 10.8, 0.5142, -0.1142 + 41000.0, 0.53, 10.85, 0.5192, -0.1158 + 41000.0, 0.53, 10.9, 0.5242, -0.1175 + 41000.0, 0.53, 10.95, 0.5291, -0.1191 + 41000.0, 0.53, 11.0, 0.5341, -0.1208 + 41000.0, 0.53, 11.05, 0.5391, -0.1224 + 41000.0, 0.53, 11.1, 0.544, -0.1241 + 41000.0, 0.53, 11.15, 0.549, -0.1257 + 41000.0, 0.53, 11.2, 0.5539, -0.1274 + 41000.0, 0.53, 11.25, 0.5589, -0.129 + 41000.0, 0.53, 11.3, 0.5639, -0.1306 + 41000.0, 0.53, 11.35, 0.5688, -0.1322 + 41000.0, 0.53, 11.4, 0.5738, -0.1339 + 41000.0, 0.53, 11.45, 0.5787, -0.1355 + 41000.0, 0.53, 11.5, 0.5837, -0.1371 + 41000.0, 0.53, 11.55, 0.5886, -0.1387 + 41000.0, 0.53, 11.6, 0.5935, -0.1403 + 41000.0, 0.53, 11.65, 0.5985, -0.1419 + 41000.0, 0.53, 11.7, 0.6034, -0.1434 + 41000.0, 0.53, 11.75, 0.6084, -0.145 + 41000.0, 0.53, 11.8, 0.6133, -0.1466 + 41000.0, 0.53, 11.85, 0.6182, -0.1481 + 41000.0, 0.53, 11.9, 0.6232, -0.1497 + 41000.0, 0.53, 11.95, 0.6281, -0.1512 + 41000.0, 0.53, 12.0, 0.633, -0.1527 + 41000.0, 0.53, 12.05, 0.6379, -0.1542 + 41000.0, 0.53, 12.1, 0.6428, -0.1557 + 41000.0, 0.53, 12.15, 0.6478, -0.1572 + 41000.0, 0.53, 12.2, 0.6527, -0.1587 + 41000.0, 0.53, 12.25, 0.6576, -0.1601 + 41000.0, 0.53, 12.3, 0.6625, -0.1616 + 41000.0, 0.53, 12.35, 0.6674, -0.163 + 41000.0, 0.53, 12.4, 0.6723, -0.1644 + 41000.0, 0.53, 12.45, 0.6772, -0.1658 + 41000.0, 0.53, 12.5, 0.6821, -0.1672 + 41000.0, 0.53, 12.55, 0.6869, -0.1686 + 41000.0, 0.53, 12.6, 0.6918, -0.17 + 41000.0, 0.53, 12.65, 0.6967, -0.1713 + 41000.0, 0.53, 12.7, 0.7016, -0.1726 + 41000.0, 0.53, 12.75, 0.7064, -0.1739 + 41000.0, 0.53, 12.8, 0.7113, -0.1752 + 41000.0, 0.53, 12.85, 0.7162, -0.1765 + 41000.0, 0.53, 12.9, 0.721, -0.1778 + 41000.0, 0.53, 12.95, 0.7259, -0.179 + 41000.0, 0.53, 13.0, 0.7307, -0.1802 + 41000.0, 0.53, 13.05, 0.7356, -0.1814 + 41000.0, 0.53, 13.1, 0.7404, -0.1826 + 41000.0, 0.53, 13.15, 0.7452, -0.1837 + 41000.0, 0.53, 13.2, 0.7501, -0.1849 + 41000.0, 0.53, 13.25, 0.7549, -0.186 + 41000.0, 0.53, 13.3, 0.7597, -0.1871 + 41000.0, 0.53, 13.35, 0.7645, -0.1882 + 41000.0, 0.53, 13.4, 0.7693, -0.1892 + 41000.0, 0.53, 13.45, 0.7741, -0.1902 + 41000.0, 0.53, 13.5, 0.7789, -0.1912 + 41000.0, 0.53, 13.55, 0.7837, -0.1922 + 41000.0, 0.53, 13.6, 0.7885, -0.1932 + 41000.0, 0.53, 13.65, 0.7933, -0.1941 + 41000.0, 0.53, 13.7, 0.7981, -0.195 + 41000.0, 0.53, 13.75, 0.8028, -0.1959 + 41000.0, 0.53, 13.8, 0.8076, -0.1968 + 41000.0, 0.53, 13.85, 0.8123, -0.1976 + 41000.0, 0.53, 13.9, 0.8171, -0.1984 + 41000.0, 0.53, 13.95, 0.8218, -0.1992 + 41000.0, 0.53, 14.0, 0.8266, -0.1999 + 41000.0, 0.53, 14.05, 0.8313, -0.2006 + 41000.0, 0.53, 14.1, 0.836, -0.2013 + 41000.0, 0.53, 14.15, 0.8407, -0.202 + 41000.0, 0.53, 14.2, 0.8454, -0.2026 + 41000.0, 0.53, 14.25, 0.8501, -0.2032 + 41000.0, 0.53, 14.3, 0.8548, -0.2038 + 41000.0, 0.53, 14.35, 0.8595, -0.2044 + 41000.0, 0.53, 14.4, 0.8642, -0.2049 + 41000.0, 0.53, 14.45, 0.8689, -0.2054 + 41000.0, 0.53, 14.5, 0.8736, -0.2058 + 41000.0, 0.53, 14.55, 0.8782, -0.2062 + 41000.0, 0.53, 14.6, 0.8829, -0.2066 + 41000.0, 0.53, 14.65, 0.8875, -0.207 + 41000.0, 0.53, 14.7, 0.8921, -0.2073 + 41000.0, 0.53, 14.75, 0.8968, -0.2076 + 41000.0, 0.53, 14.8, 0.9014, -0.2078 + 41000.0, 0.53, 14.85, 0.906, -0.208 + 41000.0, 0.53, 14.9, 0.9106, -0.2082 + 41000.0, 0.53, 14.95, 0.9152, -0.2084 + 41000.0, 0.53, 15.0, 0.9198, -0.2085 + 41000.0, 0.53, 15.05, 0.9244, -0.2086 + 41000.0, 0.58, 0.0, -0.1174, -0.02338 + 41000.0, 0.58, 0.05, -0.1165, -0.02306 + 41000.0, 0.58, 0.1, -0.1154, -0.02274 + 41000.0, 0.58, 0.15, -0.1142, -0.0224 + 41000.0, 0.58, 0.2, -0.1129, -0.02206 + 41000.0, 0.58, 0.25, -0.1115, -0.0217 + 41000.0, 0.58, 0.3, -0.1099, -0.02134 + 41000.0, 0.58, 0.35, -0.1083, -0.02097 + 41000.0, 0.58, 0.4, -0.1065, -0.02058 + 41000.0, 0.58, 0.45, -0.1047, -0.02019 + 41000.0, 0.58, 0.5, -0.1027, -0.01979 + 41000.0, 0.58, 0.55, -0.1007, -0.01939 + 41000.0, 0.58, 0.6, -0.09856, -0.01897 + 41000.0, 0.58, 0.65, -0.09634, -0.01855 + 41000.0, 0.58, 0.7, -0.09403, -0.01812 + 41000.0, 0.58, 0.75, -0.09164, -0.01769 + 41000.0, 0.58, 0.8, -0.08917, -0.01724 + 41000.0, 0.58, 0.85, -0.08662, -0.01679 + 41000.0, 0.58, 0.9, -0.08399, -0.01634 + 41000.0, 0.58, 0.95, -0.0813, -0.01588 + 41000.0, 0.58, 1.0, -0.07854, -0.01541 + 41000.0, 0.58, 1.05, -0.07571, -0.01494 + 41000.0, 0.58, 1.1, -0.07282, -0.01447 + 41000.0, 0.58, 1.15, -0.06987, -0.01399 + 41000.0, 0.58, 1.2, -0.06686, -0.01351 + 41000.0, 0.58, 1.25, -0.0638, -0.01302 + 41000.0, 0.58, 1.3, -0.06069, -0.01253 + 41000.0, 0.58, 1.35, -0.05753, -0.01204 + 41000.0, 0.58, 1.4, -0.05432, -0.01154 + 41000.0, 0.58, 1.45, -0.05108, -0.01104 + 41000.0, 0.58, 1.5, -0.04779, -0.01054 + 41000.0, 0.58, 1.55, -0.04447, -0.01003 + 41000.0, 0.58, 1.6, -0.04112, -0.00953 + 41000.0, 0.58, 1.65, -0.03774, -0.009024 + 41000.0, 0.58, 1.7, -0.03433, -0.008516 + 41000.0, 0.58, 1.75, -0.0309, -0.008008 + 41000.0, 0.58, 1.8, -0.02744, -0.007499 + 41000.0, 0.58, 1.85, -0.02397, -0.00699 + 41000.0, 0.58, 1.9, -0.02049, -0.006481 + 41000.0, 0.58, 1.95, -0.01699, -0.005973 + 41000.0, 0.58, 2.0, -0.01348, -0.005466 + 41000.0, 0.58, 2.05, -0.009966, -0.004959 + 41000.0, 0.58, 2.1, -0.00645, -0.004454 + 41000.0, 0.58, 2.15, -0.002933, -0.00395 + 41000.0, 0.58, 2.2, 0.0005809, -0.003449 + 41000.0, 0.58, 2.25, 0.004089, -0.00295 + 41000.0, 0.58, 2.3, 0.007588, -0.002453 + 41000.0, 0.58, 2.35, 0.01108, -0.001959 + 41000.0, 0.58, 2.4, 0.01455, -0.001468 + 41000.0, 0.58, 2.45, 0.018, -0.0009808 + 41000.0, 0.58, 2.5, 0.02144, -0.0004972 + 41000.0, 0.58, 2.55, 0.02485, -1.771e-05 + 41000.0, 0.58, 2.6, 0.02823, 0.0004575 + 41000.0, 0.58, 2.65, 0.03159, 0.000928 + 41000.0, 0.58, 2.7, 0.03491, 0.001394 + 41000.0, 0.58, 2.75, 0.03819, 0.001854 + 41000.0, 0.58, 2.8, 0.04144, 0.002309 + 41000.0, 0.58, 2.85, 0.04465, 0.002758 + 41000.0, 0.58, 2.9, 0.04781, 0.0032 + 41000.0, 0.58, 2.95, 0.05092, 0.003637 + 41000.0, 0.58, 3.0, 0.05399, 0.004066 + 41000.0, 0.58, 3.05, 0.057, 0.004489 + 41000.0, 0.58, 3.1, 0.05995, 0.004904 + 41000.0, 0.58, 3.15, 0.06285, 0.005311 + 41000.0, 0.58, 3.2, 0.06568, 0.005711 + 41000.0, 0.58, 3.25, 0.06845, 0.006102 + 41000.0, 0.58, 3.3, 0.07115, 0.006485 + 41000.0, 0.58, 3.35, 0.07378, 0.006859 + 41000.0, 0.58, 3.4, 0.07633, 0.007224 + 41000.0, 0.58, 3.45, 0.07881, 0.007579 + 41000.0, 0.58, 3.5, 0.0812, 0.007924 + 41000.0, 0.58, 3.55, 0.08352, 0.00826 + 41000.0, 0.58, 3.6, 0.08574, 0.008585 + 41000.0, 0.58, 3.65, 0.08788, 0.008899 + 41000.0, 0.58, 3.7, 0.08993, 0.009203 + 41000.0, 0.58, 3.75, 0.09188, 0.009495 + 41000.0, 0.58, 3.8, 0.09374, 0.009775 + 41000.0, 0.58, 3.85, 0.09549, 0.01004 + 41000.0, 0.58, 3.9, 0.09714, 0.0103 + 41000.0, 0.58, 3.95, 0.09868, 0.01054 + 41000.0, 0.58, 4.0, 0.1001, 0.01078 + 41000.0, 0.58, 4.05, 0.1006, 0.01095 + 41000.0, 0.58, 4.1, 0.101, 0.0111 + 41000.0, 0.58, 4.15, 0.1014, 0.01125 + 41000.0, 0.58, 4.2, 0.1017, 0.01139 + 41000.0, 0.58, 4.25, 0.1019, 0.01152 + 41000.0, 0.58, 4.3, 0.1021, 0.01164 + 41000.0, 0.58, 4.35, 0.1022, 0.01174 + 41000.0, 0.58, 4.4, 0.1023, 0.01184 + 41000.0, 0.58, 4.45, 0.1024, 0.01193 + 41000.0, 0.58, 4.5, 0.1024, 0.01201 + 41000.0, 0.58, 4.55, 0.1024, 0.01207 + 41000.0, 0.58, 4.6, 0.1023, 0.01213 + 41000.0, 0.58, 4.65, 0.1022, 0.01218 + 41000.0, 0.58, 4.7, 0.1021, 0.01222 + 41000.0, 0.58, 4.75, 0.102, 0.01225 + 41000.0, 0.58, 4.8, 0.1018, 0.01227 + 41000.0, 0.58, 4.85, 0.1017, 0.01228 + 41000.0, 0.58, 4.9, 0.1015, 0.01228 + 41000.0, 0.58, 4.95, 0.1013, 0.01228 + 41000.0, 0.58, 5.0, 0.1011, 0.01226 + 41000.0, 0.58, 5.05, 0.1009, 0.01226 + 41000.0, 0.58, 5.1, 0.1007, 0.01226 + 41000.0, 0.58, 5.15, 0.1005, 0.01224 + 41000.0, 0.58, 5.2, 0.1002, 0.01222 + 41000.0, 0.58, 5.25, 0.1001, 0.01218 + 41000.0, 0.58, 5.3, 0.09989, 0.01214 + 41000.0, 0.58, 5.35, 0.09974, 0.01208 + 41000.0, 0.58, 5.4, 0.09963, 0.01201 + 41000.0, 0.58, 5.45, 0.09955, 0.01193 + 41000.0, 0.58, 5.5, 0.0995, 0.01184 + 41000.0, 0.58, 5.55, 0.0995, 0.01173 + 41000.0, 0.58, 5.6, 0.09955, 0.01161 + 41000.0, 0.58, 5.65, 0.09964, 0.01148 + 41000.0, 0.58, 5.7, 0.0998, 0.01133 + 41000.0, 0.58, 5.75, 0.1, 0.01117 + 41000.0, 0.58, 5.8, 0.1003, 0.011 + 41000.0, 0.58, 5.85, 0.1006, 0.01081 + 41000.0, 0.58, 5.9, 0.101, 0.0106 + 41000.0, 0.58, 5.95, 0.1015, 0.01038 + 41000.0, 0.58, 6.0, 0.1021, 0.01014 + 41000.0, 0.58, 6.05, 0.1038, 0.009784 + 41000.0, 0.58, 6.1, 0.1055, 0.009404 + 41000.0, 0.58, 6.15, 0.1075, 0.009002 + 41000.0, 0.58, 6.2, 0.1095, 0.008581 + 41000.0, 0.58, 6.25, 0.1117, 0.008139 + 41000.0, 0.58, 6.3, 0.114, 0.007678 + 41000.0, 0.58, 6.35, 0.1164, 0.007198 + 41000.0, 0.58, 6.4, 0.1189, 0.006699 + 41000.0, 0.58, 6.45, 0.1215, 0.006181 + 41000.0, 0.58, 6.5, 0.1242, 0.005646 + 41000.0, 0.58, 6.55, 0.1271, 0.005093 + 41000.0, 0.58, 6.6, 0.13, 0.004523 + 41000.0, 0.58, 6.65, 0.133, 0.003937 + 41000.0, 0.58, 6.7, 0.1361, 0.003334 + 41000.0, 0.58, 6.75, 0.1393, 0.002716 + 41000.0, 0.58, 6.8, 0.1426, 0.002082 + 41000.0, 0.58, 6.85, 0.146, 0.001432 + 41000.0, 0.58, 6.9, 0.1494, 0.0007687 + 41000.0, 0.58, 6.95, 0.153, 9.07e-05 + 41000.0, 0.58, 7.0, 0.1566, -0.0006011 + 41000.0, 0.58, 7.05, 0.1603, -0.001306 + 41000.0, 0.58, 7.1, 0.164, -0.002025 + 41000.0, 0.58, 7.15, 0.1678, -0.002755 + 41000.0, 0.58, 7.2, 0.1717, -0.003498 + 41000.0, 0.58, 7.25, 0.1756, -0.004253 + 41000.0, 0.58, 7.3, 0.1796, -0.005019 + 41000.0, 0.58, 7.35, 0.1836, -0.005797 + 41000.0, 0.58, 7.4, 0.1877, -0.006584 + 41000.0, 0.58, 7.45, 0.1919, -0.007382 + 41000.0, 0.58, 7.5, 0.196, -0.00819 + 41000.0, 0.58, 7.55, 0.2002, -0.009007 + 41000.0, 0.58, 7.6, 0.2045, -0.009833 + 41000.0, 0.58, 7.65, 0.2088, -0.01067 + 41000.0, 0.58, 7.7, 0.2131, -0.01151 + 41000.0, 0.58, 7.75, 0.2174, -0.01236 + 41000.0, 0.58, 7.8, 0.2218, -0.01322 + 41000.0, 0.58, 7.85, 0.2261, -0.01408 + 41000.0, 0.58, 7.9, 0.2305, -0.01495 + 41000.0, 0.58, 7.95, 0.235, -0.01583 + 41000.0, 0.58, 8.0, 0.2394, -0.01671 + 41000.0, 0.58, 8.05, 0.243, -0.0175 + 41000.0, 0.58, 8.1, 0.2467, -0.0183 + 41000.0, 0.58, 8.15, 0.2503, -0.0191 + 41000.0, 0.58, 8.2, 0.254, -0.0199 + 41000.0, 0.58, 8.25, 0.2576, -0.02071 + 41000.0, 0.58, 8.3, 0.2613, -0.02153 + 41000.0, 0.58, 8.35, 0.265, -0.02235 + 41000.0, 0.58, 8.4, 0.2687, -0.02317 + 41000.0, 0.58, 8.45, 0.2723, -0.024 + 41000.0, 0.58, 8.5, 0.276, -0.02484 + 41000.0, 0.58, 8.55, 0.2797, -0.02568 + 41000.0, 0.58, 8.6, 0.2834, -0.02652 + 41000.0, 0.58, 8.65, 0.2872, -0.02737 + 41000.0, 0.58, 8.7, 0.2909, -0.02822 + 41000.0, 0.58, 8.75, 0.2946, -0.02908 + 41000.0, 0.58, 8.8, 0.2983, -0.02995 + 41000.0, 0.58, 8.85, 0.3021, -0.03082 + 41000.0, 0.58, 8.9, 0.3058, -0.03169 + 41000.0, 0.58, 8.95, 0.3095, -0.03257 + 41000.0, 0.58, 9.0, 0.3133, -0.03345 + 41000.0, 0.58, 9.05, 0.317, -0.03434 + 41000.0, 0.58, 9.1, 0.3208, -0.03523 + 41000.0, 0.58, 9.15, 0.3245, -0.03612 + 41000.0, 0.58, 9.2, 0.3283, -0.03702 + 41000.0, 0.58, 9.25, 0.3321, -0.03793 + 41000.0, 0.58, 9.3, 0.3358, -0.03883 + 41000.0, 0.58, 9.35, 0.3396, -0.03975 + 41000.0, 0.58, 9.4, 0.3434, -0.04066 + 41000.0, 0.58, 9.45, 0.3472, -0.04159 + 41000.0, 0.58, 9.5, 0.3509, -0.04251 + 41000.0, 0.58, 9.55, 0.3547, -0.04344 + 41000.0, 0.58, 9.6, 0.3585, -0.04437 + 41000.0, 0.58, 9.65, 0.3623, -0.04531 + 41000.0, 0.58, 9.7, 0.3661, -0.04625 + 41000.0, 0.58, 9.75, 0.3699, -0.0472 + 41000.0, 0.58, 9.8, 0.3736, -0.04815 + 41000.0, 0.58, 9.85, 0.3774, -0.0491 + 41000.0, 0.58, 9.9, 0.3812, -0.05006 + 41000.0, 0.58, 9.95, 0.385, -0.05102 + 41000.0, 0.58, 10.0, 0.3888, -0.05198 + 41000.0, 0.58, 10.05, 0.3926, -0.05302 + 41000.0, 0.58, 10.1, 0.3963, -0.05405 + 41000.0, 0.58, 10.15, 0.4001, -0.05509 + 41000.0, 0.58, 10.2, 0.4039, -0.05614 + 41000.0, 0.58, 10.25, 0.4076, -0.05718 + 41000.0, 0.58, 10.3, 0.4114, -0.05823 + 41000.0, 0.58, 10.35, 0.4152, -0.05928 + 41000.0, 0.58, 10.4, 0.4189, -0.06033 + 41000.0, 0.58, 10.45, 0.4227, -0.06138 + 41000.0, 0.58, 10.5, 0.4265, -0.06244 + 41000.0, 0.58, 10.55, 0.4302, -0.06349 + 41000.0, 0.58, 10.6, 0.434, -0.06455 + 41000.0, 0.58, 10.65, 0.4378, -0.0656 + 41000.0, 0.58, 10.7, 0.4415, -0.06666 + 41000.0, 0.58, 10.75, 0.4453, -0.06771 + 41000.0, 0.58, 10.8, 0.4491, -0.06877 + 41000.0, 0.58, 10.85, 0.4528, -0.06982 + 41000.0, 0.58, 10.9, 0.4566, -0.07088 + 41000.0, 0.58, 10.95, 0.4604, -0.07193 + 41000.0, 0.58, 11.0, 0.4641, -0.07298 + 41000.0, 0.58, 11.05, 0.4679, -0.07403 + 41000.0, 0.58, 11.1, 0.4716, -0.07508 + 41000.0, 0.58, 11.15, 0.4754, -0.07612 + 41000.0, 0.58, 11.2, 0.4792, -0.07716 + 41000.0, 0.58, 11.25, 0.4829, -0.0782 + 41000.0, 0.58, 11.3, 0.4867, -0.07924 + 41000.0, 0.58, 11.35, 0.4904, -0.08027 + 41000.0, 0.58, 11.4, 0.4942, -0.0813 + 41000.0, 0.58, 11.45, 0.498, -0.08232 + 41000.0, 0.58, 11.5, 0.5017, -0.08334 + 41000.0, 0.58, 11.55, 0.5055, -0.08436 + 41000.0, 0.58, 11.6, 0.5092, -0.08537 + 41000.0, 0.58, 11.65, 0.513, -0.08637 + 41000.0, 0.58, 11.7, 0.5167, -0.08737 + 41000.0, 0.58, 11.75, 0.5205, -0.08836 + 41000.0, 0.58, 11.8, 0.5242, -0.08935 + 41000.0, 0.58, 11.85, 0.528, -0.09033 + 41000.0, 0.58, 11.9, 0.5317, -0.09131 + 41000.0, 0.58, 11.95, 0.5355, -0.09228 + 41000.0, 0.58, 12.0, 0.5392, -0.09324 + 41000.0, 0.58, 12.05, 0.5429, -0.09419 + 41000.0, 0.58, 12.1, 0.5467, -0.09513 + 41000.0, 0.58, 12.15, 0.5504, -0.09607 + 41000.0, 0.58, 12.2, 0.5541, -0.097 + 41000.0, 0.58, 12.25, 0.5579, -0.09792 + 41000.0, 0.58, 12.3, 0.5616, -0.09883 + 41000.0, 0.58, 12.35, 0.5653, -0.09974 + 41000.0, 0.58, 12.4, 0.5691, -0.1006 + 41000.0, 0.58, 12.45, 0.5728, -0.1015 + 41000.0, 0.58, 12.5, 0.5765, -0.1024 + 41000.0, 0.58, 12.55, 0.5802, -0.1032 + 41000.0, 0.58, 12.6, 0.584, -0.1041 + 41000.0, 0.58, 12.65, 0.5877, -0.1049 + 41000.0, 0.58, 12.7, 0.5914, -0.1058 + 41000.0, 0.58, 12.75, 0.5951, -0.1066 + 41000.0, 0.58, 12.8, 0.5988, -0.1074 + 41000.0, 0.58, 12.85, 0.6025, -0.1082 + 41000.0, 0.58, 12.9, 0.6062, -0.109 + 41000.0, 0.58, 12.95, 0.6099, -0.1098 + 41000.0, 0.58, 13.0, 0.6136, -0.1105 + 41000.0, 0.58, 13.05, 0.6173, -0.1113 + 41000.0, 0.58, 13.1, 0.621, -0.112 + 41000.0, 0.58, 13.15, 0.6247, -0.1127 + 41000.0, 0.58, 13.2, 0.6284, -0.1134 + 41000.0, 0.58, 13.25, 0.6321, -0.1141 + 41000.0, 0.58, 13.3, 0.6357, -0.1148 + 41000.0, 0.58, 13.35, 0.6394, -0.1154 + 41000.0, 0.58, 13.4, 0.6431, -0.1161 + 41000.0, 0.58, 13.45, 0.6468, -0.1167 + 41000.0, 0.58, 13.5, 0.6504, -0.1173 + 41000.0, 0.58, 13.55, 0.6541, -0.1179 + 41000.0, 0.58, 13.6, 0.6578, -0.1185 + 41000.0, 0.58, 13.65, 0.6614, -0.1191 + 41000.0, 0.58, 13.7, 0.6651, -0.1196 + 41000.0, 0.58, 13.75, 0.6687, -0.1202 + 41000.0, 0.58, 13.8, 0.6724, -0.1207 + 41000.0, 0.58, 13.85, 0.676, -0.1212 + 41000.0, 0.58, 13.9, 0.6796, -0.1217 + 41000.0, 0.58, 13.95, 0.6833, -0.1221 + 41000.0, 0.58, 14.0, 0.6869, -0.1226 + 41000.0, 0.58, 14.05, 0.6905, -0.123 + 41000.0, 0.58, 14.1, 0.6942, -0.1234 + 41000.0, 0.58, 14.15, 0.6978, -0.1238 + 41000.0, 0.58, 14.2, 0.7014, -0.1242 + 41000.0, 0.58, 14.25, 0.705, -0.1245 + 41000.0, 0.58, 14.3, 0.7086, -0.1248 + 41000.0, 0.58, 14.35, 0.7122, -0.1251 + 41000.0, 0.58, 14.4, 0.7158, -0.1254 + 41000.0, 0.58, 14.45, 0.7194, -0.1257 + 41000.0, 0.58, 14.5, 0.723, -0.1259 + 41000.0, 0.58, 14.55, 0.7266, -0.1262 + 41000.0, 0.58, 14.6, 0.7302, -0.1264 + 41000.0, 0.58, 14.65, 0.7337, -0.1265 + 41000.0, 0.58, 14.7, 0.7373, -0.1267 + 41000.0, 0.58, 14.75, 0.7409, -0.1268 + 41000.0, 0.58, 14.8, 0.7444, -0.127 + 41000.0, 0.58, 14.85, 0.748, -0.127 + 41000.0, 0.58, 14.9, 0.7515, -0.1271 + 41000.0, 0.58, 14.95, 0.7551, -0.1272 + 41000.0, 0.58, 15.0, 0.7586, -0.1272 + 41000.0, 0.58, 15.05, 0.7622, -0.1272 + 41000.0, 0.63, 0.0, -0.1323, -0.009531 + 41000.0, 0.63, 0.05, -0.1304, -0.009379 + 41000.0, 0.63, 0.1, -0.1284, -0.009223 + 41000.0, 0.63, 0.15, -0.1263, -0.009062 + 41000.0, 0.63, 0.2, -0.1242, -0.008897 + 41000.0, 0.63, 0.25, -0.1221, -0.008727 + 41000.0, 0.63, 0.3, -0.1199, -0.008553 + 41000.0, 0.63, 0.35, -0.1176, -0.008375 + 41000.0, 0.63, 0.4, -0.1153, -0.008193 + 41000.0, 0.63, 0.45, -0.1129, -0.008007 + 41000.0, 0.63, 0.5, -0.1104, -0.007817 + 41000.0, 0.63, 0.55, -0.108, -0.007623 + 41000.0, 0.63, 0.6, -0.1054, -0.007426 + 41000.0, 0.63, 0.65, -0.1029, -0.007226 + 41000.0, 0.63, 0.7, -0.1002, -0.007022 + 41000.0, 0.63, 0.75, -0.09758, -0.006815 + 41000.0, 0.63, 0.8, -0.09487, -0.006605 + 41000.0, 0.63, 0.85, -0.09213, -0.006392 + 41000.0, 0.63, 0.9, -0.08934, -0.006177 + 41000.0, 0.63, 0.95, -0.08652, -0.005958 + 41000.0, 0.63, 1.0, -0.08366, -0.005737 + 41000.0, 0.63, 1.05, -0.08077, -0.005514 + 41000.0, 0.63, 1.1, -0.07785, -0.005289 + 41000.0, 0.63, 1.15, -0.07489, -0.005061 + 41000.0, 0.63, 1.2, -0.07191, -0.004831 + 41000.0, 0.63, 1.25, -0.0689, -0.0046 + 41000.0, 0.63, 1.3, -0.06586, -0.004366 + 41000.0, 0.63, 1.35, -0.0628, -0.004131 + 41000.0, 0.63, 1.4, -0.05971, -0.003894 + 41000.0, 0.63, 1.45, -0.05661, -0.003656 + 41000.0, 0.63, 1.5, -0.05348, -0.003417 + 41000.0, 0.63, 1.55, -0.05034, -0.003177 + 41000.0, 0.63, 1.6, -0.04718, -0.002935 + 41000.0, 0.63, 1.65, -0.044, -0.002693 + 41000.0, 0.63, 1.7, -0.04081, -0.002449 + 41000.0, 0.63, 1.75, -0.03761, -0.002206 + 41000.0, 0.63, 1.8, -0.03439, -0.001961 + 41000.0, 0.63, 1.85, -0.03117, -0.001716 + 41000.0, 0.63, 1.9, -0.02794, -0.001471 + 41000.0, 0.63, 1.95, -0.02471, -0.001226 + 41000.0, 0.63, 2.0, -0.02147, -0.0009805 + 41000.0, 0.63, 2.05, -0.01822, -0.0007352 + 41000.0, 0.63, 2.1, -0.01498, -0.0004902 + 41000.0, 0.63, 2.15, -0.01174, -0.0002455 + 41000.0, 0.63, 2.2, -0.008496, -1.227e-06 + 41000.0, 0.63, 2.25, -0.005258, 0.0002424 + 41000.0, 0.63, 2.3, -0.002025, 0.0004854 + 41000.0, 0.63, 2.35, 0.001201, 0.0007275 + 41000.0, 0.63, 2.4, 0.004418, 0.0009687 + 41000.0, 0.63, 2.45, 0.007626, 0.001209 + 41000.0, 0.63, 2.5, 0.01082, 0.001448 + 41000.0, 0.63, 2.55, 0.01401, 0.001685 + 41000.0, 0.63, 2.6, 0.01718, 0.001921 + 41000.0, 0.63, 2.65, 0.02033, 0.002156 + 41000.0, 0.63, 2.7, 0.02346, 0.002389 + 41000.0, 0.63, 2.75, 0.02658, 0.00262 + 41000.0, 0.63, 2.8, 0.02968, 0.002849 + 41000.0, 0.63, 2.85, 0.03275, 0.003076 + 41000.0, 0.63, 2.9, 0.0358, 0.0033 + 41000.0, 0.63, 2.95, 0.03882, 0.003523 + 41000.0, 0.63, 3.0, 0.04182, 0.003743 + 41000.0, 0.63, 3.05, 0.04479, 0.00396 + 41000.0, 0.63, 3.1, 0.04773, 0.004175 + 41000.0, 0.63, 3.15, 0.05064, 0.004386 + 41000.0, 0.63, 3.2, 0.05351, 0.004595 + 41000.0, 0.63, 3.25, 0.05635, 0.004801 + 41000.0, 0.63, 3.3, 0.05915, 0.005004 + 41000.0, 0.63, 3.35, 0.06192, 0.005203 + 41000.0, 0.63, 3.4, 0.06464, 0.005399 + 41000.0, 0.63, 3.45, 0.06733, 0.005591 + 41000.0, 0.63, 3.5, 0.06997, 0.00578 + 41000.0, 0.63, 3.55, 0.07256, 0.005964 + 41000.0, 0.63, 3.6, 0.07512, 0.006145 + 41000.0, 0.63, 3.65, 0.07762, 0.006322 + 41000.0, 0.63, 3.7, 0.08008, 0.006494 + 41000.0, 0.63, 3.75, 0.08248, 0.006662 + 41000.0, 0.63, 3.8, 0.08483, 0.006826 + 41000.0, 0.63, 3.85, 0.08713, 0.006985 + 41000.0, 0.63, 3.9, 0.08938, 0.00714 + 41000.0, 0.63, 3.95, 0.09157, 0.007289 + 41000.0, 0.63, 4.0, 0.0937, 0.007434 + 41000.0, 0.63, 4.05, 0.09532, 0.007546 + 41000.0, 0.63, 4.1, 0.09692, 0.007654 + 41000.0, 0.63, 4.15, 0.09847, 0.007758 + 41000.0, 0.63, 4.2, 0.1, 0.00786 + 41000.0, 0.63, 4.25, 0.1015, 0.007958 + 41000.0, 0.63, 4.3, 0.103, 0.008053 + 41000.0, 0.63, 4.35, 0.1044, 0.008144 + 41000.0, 0.63, 4.4, 0.1058, 0.008233 + 41000.0, 0.63, 4.45, 0.1072, 0.008319 + 41000.0, 0.63, 4.5, 0.1086, 0.008402 + 41000.0, 0.63, 4.55, 0.11, 0.008482 + 41000.0, 0.63, 4.6, 0.1113, 0.00856 + 41000.0, 0.63, 4.65, 0.1126, 0.008635 + 41000.0, 0.63, 4.7, 0.1139, 0.008707 + 41000.0, 0.63, 4.75, 0.1152, 0.008778 + 41000.0, 0.63, 4.8, 0.1165, 0.008845 + 41000.0, 0.63, 4.85, 0.1178, 0.008911 + 41000.0, 0.63, 4.9, 0.1191, 0.008975 + 41000.0, 0.63, 4.95, 0.1204, 0.009037 + 41000.0, 0.63, 5.0, 0.1217, 0.009096 + 41000.0, 0.63, 5.05, 0.123, 0.009183 + 41000.0, 0.63, 5.1, 0.1243, 0.009267 + 41000.0, 0.63, 5.15, 0.1256, 0.009349 + 41000.0, 0.63, 5.2, 0.1269, 0.009428 + 41000.0, 0.63, 5.25, 0.1282, 0.009503 + 41000.0, 0.63, 5.3, 0.1296, 0.009576 + 41000.0, 0.63, 5.35, 0.1309, 0.009644 + 41000.0, 0.63, 5.4, 0.1323, 0.009708 + 41000.0, 0.63, 5.45, 0.1336, 0.009768 + 41000.0, 0.63, 5.5, 0.135, 0.009823 + 41000.0, 0.63, 5.55, 0.1364, 0.009872 + 41000.0, 0.63, 5.6, 0.1378, 0.009916 + 41000.0, 0.63, 5.65, 0.1392, 0.009954 + 41000.0, 0.63, 5.7, 0.1406, 0.009986 + 41000.0, 0.63, 5.75, 0.142, 0.01001 + 41000.0, 0.63, 5.8, 0.1435, 0.01003 + 41000.0, 0.63, 5.85, 0.145, 0.01004 + 41000.0, 0.63, 5.9, 0.1465, 0.01004 + 41000.0, 0.63, 5.95, 0.148, 0.01004 + 41000.0, 0.63, 6.0, 0.1496, 0.01003 + 41000.0, 0.63, 6.05, 0.1515, 0.009924 + 41000.0, 0.63, 6.1, 0.1534, 0.009809 + 41000.0, 0.63, 6.15, 0.1554, 0.009681 + 41000.0, 0.63, 6.2, 0.1574, 0.009542 + 41000.0, 0.63, 6.25, 0.1594, 0.009391 + 41000.0, 0.63, 6.3, 0.1615, 0.009229 + 41000.0, 0.63, 6.35, 0.1636, 0.009056 + 41000.0, 0.63, 6.4, 0.1657, 0.008872 + 41000.0, 0.63, 6.45, 0.1679, 0.008678 + 41000.0, 0.63, 6.5, 0.1701, 0.008473 + 41000.0, 0.63, 6.55, 0.1724, 0.008258 + 41000.0, 0.63, 6.6, 0.1746, 0.008034 + 41000.0, 0.63, 6.65, 0.1769, 0.0078 + 41000.0, 0.63, 6.7, 0.1793, 0.007557 + 41000.0, 0.63, 6.75, 0.1816, 0.007305 + 41000.0, 0.63, 6.8, 0.184, 0.007044 + 41000.0, 0.63, 6.85, 0.1864, 0.006775 + 41000.0, 0.63, 6.9, 0.1888, 0.006498 + 41000.0, 0.63, 6.95, 0.1913, 0.006212 + 41000.0, 0.63, 7.0, 0.1938, 0.005919 + 41000.0, 0.63, 7.05, 0.1963, 0.005619 + 41000.0, 0.63, 7.1, 0.1988, 0.005312 + 41000.0, 0.63, 7.15, 0.2014, 0.004997 + 41000.0, 0.63, 7.2, 0.2039, 0.004676 + 41000.0, 0.63, 7.25, 0.2065, 0.004349 + 41000.0, 0.63, 7.3, 0.2091, 0.004016 + 41000.0, 0.63, 7.35, 0.2117, 0.003677 + 41000.0, 0.63, 7.4, 0.2144, 0.003332 + 41000.0, 0.63, 7.45, 0.217, 0.002982 + 41000.0, 0.63, 7.5, 0.2197, 0.002626 + 41000.0, 0.63, 7.55, 0.2224, 0.002267 + 41000.0, 0.63, 7.6, 0.2251, 0.001902 + 41000.0, 0.63, 7.65, 0.2278, 0.001533 + 41000.0, 0.63, 7.7, 0.2305, 0.001161 + 41000.0, 0.63, 7.75, 0.2332, 0.0007842 + 41000.0, 0.63, 7.8, 0.2359, 0.0004042 + 41000.0, 0.63, 7.85, 0.2387, 2.1e-05 + 41000.0, 0.63, 7.9, 0.2414, -0.0003652 + 41000.0, 0.63, 7.95, 0.2442, -0.000754 + 41000.0, 0.63, 8.0, 0.2469, -0.001145 + 41000.0, 0.63, 8.05, 0.2494, -0.001473 + 41000.0, 0.63, 8.1, 0.252, -0.001803 + 41000.0, 0.63, 8.15, 0.2545, -0.002135 + 41000.0, 0.63, 8.2, 0.2571, -0.002469 + 41000.0, 0.63, 8.25, 0.2596, -0.002805 + 41000.0, 0.63, 8.3, 0.2622, -0.003144 + 41000.0, 0.63, 8.35, 0.2648, -0.003484 + 41000.0, 0.63, 8.4, 0.2673, -0.003827 + 41000.0, 0.63, 8.45, 0.2699, -0.004172 + 41000.0, 0.63, 8.5, 0.2725, -0.004519 + 41000.0, 0.63, 8.55, 0.275, -0.004867 + 41000.0, 0.63, 8.6, 0.2776, -0.005218 + 41000.0, 0.63, 8.65, 0.2802, -0.005571 + 41000.0, 0.63, 8.7, 0.2828, -0.005926 + 41000.0, 0.63, 8.75, 0.2854, -0.006283 + 41000.0, 0.63, 8.8, 0.288, -0.006642 + 41000.0, 0.63, 8.85, 0.2905, -0.007003 + 41000.0, 0.63, 8.9, 0.2931, -0.007366 + 41000.0, 0.63, 8.95, 0.2957, -0.00773 + 41000.0, 0.63, 9.0, 0.2983, -0.008097 + 41000.0, 0.63, 9.05, 0.3009, -0.008466 + 41000.0, 0.63, 9.1, 0.3035, -0.008836 + 41000.0, 0.63, 9.15, 0.3061, -0.009209 + 41000.0, 0.63, 9.2, 0.3087, -0.009583 + 41000.0, 0.63, 9.25, 0.3114, -0.009959 + 41000.0, 0.63, 9.3, 0.314, -0.01034 + 41000.0, 0.63, 9.35, 0.3166, -0.01072 + 41000.0, 0.63, 9.4, 0.3192, -0.0111 + 41000.0, 0.63, 9.45, 0.3218, -0.01148 + 41000.0, 0.63, 9.5, 0.3244, -0.01187 + 41000.0, 0.63, 9.55, 0.327, -0.01225 + 41000.0, 0.63, 9.6, 0.3297, -0.01264 + 41000.0, 0.63, 9.65, 0.3323, -0.01303 + 41000.0, 0.63, 9.7, 0.3349, -0.01343 + 41000.0, 0.63, 9.75, 0.3375, -0.01382 + 41000.0, 0.63, 9.8, 0.3401, -0.01422 + 41000.0, 0.63, 9.85, 0.3428, -0.01461 + 41000.0, 0.63, 9.9, 0.3454, -0.01501 + 41000.0, 0.63, 9.95, 0.348, -0.01541 + 41000.0, 0.63, 10.0, 0.3506, -0.01582 + 41000.0, 0.63, 10.05, 0.3532, -0.01625 + 41000.0, 0.63, 10.1, 0.3559, -0.01669 + 41000.0, 0.63, 10.15, 0.3585, -0.01713 + 41000.0, 0.63, 10.2, 0.3611, -0.01757 + 41000.0, 0.63, 10.25, 0.3637, -0.01802 + 41000.0, 0.63, 10.3, 0.3663, -0.01846 + 41000.0, 0.63, 10.35, 0.3689, -0.0189 + 41000.0, 0.63, 10.4, 0.3715, -0.01935 + 41000.0, 0.63, 10.45, 0.3741, -0.01979 + 41000.0, 0.63, 10.5, 0.3767, -0.02024 + 41000.0, 0.63, 10.55, 0.3793, -0.02068 + 41000.0, 0.63, 10.6, 0.382, -0.02113 + 41000.0, 0.63, 10.65, 0.3846, -0.02158 + 41000.0, 0.63, 10.7, 0.3872, -0.02202 + 41000.0, 0.63, 10.75, 0.3898, -0.02247 + 41000.0, 0.63, 10.8, 0.3924, -0.02291 + 41000.0, 0.63, 10.85, 0.395, -0.02336 + 41000.0, 0.63, 10.9, 0.3976, -0.0238 + 41000.0, 0.63, 10.95, 0.4002, -0.02425 + 41000.0, 0.63, 11.0, 0.4028, -0.02469 + 41000.0, 0.63, 11.05, 0.4054, -0.02513 + 41000.0, 0.63, 11.1, 0.4081, -0.02557 + 41000.0, 0.63, 11.15, 0.4107, -0.02601 + 41000.0, 0.63, 11.2, 0.4133, -0.02645 + 41000.0, 0.63, 11.25, 0.4159, -0.02688 + 41000.0, 0.63, 11.3, 0.4185, -0.02732 + 41000.0, 0.63, 11.35, 0.4211, -0.02775 + 41000.0, 0.63, 11.4, 0.4237, -0.02818 + 41000.0, 0.63, 11.45, 0.4263, -0.02861 + 41000.0, 0.63, 11.5, 0.4289, -0.02903 + 41000.0, 0.63, 11.55, 0.4315, -0.02946 + 41000.0, 0.63, 11.6, 0.4341, -0.02988 + 41000.0, 0.63, 11.65, 0.4367, -0.0303 + 41000.0, 0.63, 11.7, 0.4393, -0.03071 + 41000.0, 0.63, 11.75, 0.4419, -0.03112 + 41000.0, 0.63, 11.8, 0.4445, -0.03153 + 41000.0, 0.63, 11.85, 0.4471, -0.03194 + 41000.0, 0.63, 11.9, 0.4498, -0.03234 + 41000.0, 0.63, 11.95, 0.4524, -0.03274 + 41000.0, 0.63, 12.0, 0.455, -0.03313 + 41000.0, 0.63, 12.05, 0.4576, -0.03353 + 41000.0, 0.63, 12.1, 0.4602, -0.03391 + 41000.0, 0.63, 12.15, 0.4628, -0.0343 + 41000.0, 0.63, 12.2, 0.4653, -0.03468 + 41000.0, 0.63, 12.25, 0.4679, -0.03505 + 41000.0, 0.63, 12.3, 0.4705, -0.03542 + 41000.0, 0.63, 12.35, 0.4731, -0.03579 + 41000.0, 0.63, 12.4, 0.4757, -0.03615 + 41000.0, 0.63, 12.45, 0.4783, -0.0365 + 41000.0, 0.63, 12.5, 0.4809, -0.03686 + 41000.0, 0.63, 12.55, 0.4835, -0.0372 + 41000.0, 0.63, 12.6, 0.4861, -0.03754 + 41000.0, 0.63, 12.65, 0.4887, -0.03788 + 41000.0, 0.63, 12.7, 0.4913, -0.03821 + 41000.0, 0.63, 12.75, 0.4939, -0.03853 + 41000.0, 0.63, 12.8, 0.4964, -0.03885 + 41000.0, 0.63, 12.85, 0.499, -0.03916 + 41000.0, 0.63, 12.9, 0.5016, -0.03947 + 41000.0, 0.63, 12.95, 0.5042, -0.03977 + 41000.0, 0.63, 13.0, 0.5068, -0.04006 + 41000.0, 0.63, 13.05, 0.5094, -0.04035 + 41000.0, 0.63, 13.1, 0.5119, -0.04063 + 41000.0, 0.63, 13.15, 0.5145, -0.0409 + 41000.0, 0.63, 13.2, 0.5171, -0.04117 + 41000.0, 0.63, 13.25, 0.5197, -0.04143 + 41000.0, 0.63, 13.3, 0.5222, -0.04168 + 41000.0, 0.63, 13.35, 0.5248, -0.04193 + 41000.0, 0.63, 13.4, 0.5274, -0.04216 + 41000.0, 0.63, 13.45, 0.5299, -0.04239 + 41000.0, 0.63, 13.5, 0.5325, -0.04262 + 41000.0, 0.63, 13.55, 0.5351, -0.04283 + 41000.0, 0.63, 13.6, 0.5376, -0.04304 + 41000.0, 0.63, 13.65, 0.5402, -0.04323 + 41000.0, 0.63, 13.7, 0.5428, -0.04342 + 41000.0, 0.63, 13.75, 0.5453, -0.0436 + 41000.0, 0.63, 13.8, 0.5479, -0.04378 + 41000.0, 0.63, 13.85, 0.5504, -0.04394 + 41000.0, 0.63, 13.9, 0.553, -0.0441 + 41000.0, 0.63, 13.95, 0.5555, -0.04424 + 41000.0, 0.63, 14.0, 0.5581, -0.04438 + 41000.0, 0.63, 14.05, 0.5606, -0.04451 + 41000.0, 0.63, 14.1, 0.5632, -0.04463 + 41000.0, 0.63, 14.15, 0.5657, -0.04474 + 41000.0, 0.63, 14.2, 0.5683, -0.04484 + 41000.0, 0.63, 14.25, 0.5708, -0.04493 + 41000.0, 0.63, 14.3, 0.5733, -0.04501 + 41000.0, 0.63, 14.35, 0.5759, -0.04507 + 41000.0, 0.63, 14.4, 0.5784, -0.04513 + 41000.0, 0.63, 14.45, 0.5809, -0.04518 + 41000.0, 0.63, 14.5, 0.5835, -0.04522 + 41000.0, 0.63, 14.55, 0.586, -0.04525 + 41000.0, 0.63, 14.6, 0.5885, -0.04527 + 41000.0, 0.63, 14.65, 0.591, -0.04527 + 41000.0, 0.63, 14.7, 0.5936, -0.04527 + 41000.0, 0.63, 14.75, 0.5961, -0.04525 + 41000.0, 0.63, 14.8, 0.5986, -0.04523 + 41000.0, 0.63, 14.85, 0.6011, -0.04519 + 41000.0, 0.63, 14.9, 0.6036, -0.04514 + 41000.0, 0.63, 14.95, 0.6061, -0.04508 + 41000.0, 0.63, 15.0, 0.6086, -0.045 + 41000.0, 0.63, 15.05, 0.6111, -0.04492 + 41000.0, 0.68, 0.0, -0.149, 0.002105 + 41000.0, 0.68, 0.05, -0.1462, 0.002124 + 41000.0, 0.68, 0.1, -0.1434, 0.002142 + 41000.0, 0.68, 0.15, -0.1406, 0.002161 + 41000.0, 0.68, 0.2, -0.1377, 0.00218 + 41000.0, 0.68, 0.25, -0.1349, 0.002198 + 41000.0, 0.68, 0.3, -0.132, 0.002216 + 41000.0, 0.68, 0.35, -0.1291, 0.002234 + 41000.0, 0.68, 0.4, -0.1263, 0.002252 + 41000.0, 0.68, 0.45, -0.1233, 0.00227 + 41000.0, 0.68, 0.5, -0.1204, 0.002288 + 41000.0, 0.68, 0.55, -0.1175, 0.002306 + 41000.0, 0.68, 0.6, -0.1146, 0.002324 + 41000.0, 0.68, 0.65, -0.1116, 0.002341 + 41000.0, 0.68, 0.7, -0.1086, 0.002359 + 41000.0, 0.68, 0.75, -0.1057, 0.002377 + 41000.0, 0.68, 0.8, -0.1027, 0.002396 + 41000.0, 0.68, 0.85, -0.09969, 0.002414 + 41000.0, 0.68, 0.9, -0.09668, 0.002432 + 41000.0, 0.68, 0.95, -0.09367, 0.002451 + 41000.0, 0.68, 1.0, -0.09065, 0.00247 + 41000.0, 0.68, 1.05, -0.08762, 0.002489 + 41000.0, 0.68, 1.1, -0.08458, 0.002508 + 41000.0, 0.68, 1.15, -0.08154, 0.002528 + 41000.0, 0.68, 1.2, -0.07849, 0.002548 + 41000.0, 0.68, 1.25, -0.07543, 0.002568 + 41000.0, 0.68, 1.3, -0.07237, 0.002588 + 41000.0, 0.68, 1.35, -0.0693, 0.002609 + 41000.0, 0.68, 1.4, -0.06622, 0.002631 + 41000.0, 0.68, 1.45, -0.06314, 0.002652 + 41000.0, 0.68, 1.5, -0.06006, 0.002674 + 41000.0, 0.68, 1.55, -0.05697, 0.002697 + 41000.0, 0.68, 1.6, -0.05388, 0.00272 + 41000.0, 0.68, 1.65, -0.05078, 0.002744 + 41000.0, 0.68, 1.7, -0.04768, 0.002768 + 41000.0, 0.68, 1.75, -0.04458, 0.002792 + 41000.0, 0.68, 1.8, -0.04148, 0.002818 + 41000.0, 0.68, 1.85, -0.03837, 0.002844 + 41000.0, 0.68, 1.9, -0.03527, 0.00287 + 41000.0, 0.68, 1.95, -0.03216, 0.002897 + 41000.0, 0.68, 2.0, -0.02905, 0.002925 + 41000.0, 0.68, 2.05, -0.02595, 0.002954 + 41000.0, 0.68, 2.1, -0.02284, 0.002983 + 41000.0, 0.68, 2.15, -0.01973, 0.003013 + 41000.0, 0.68, 2.2, -0.01663, 0.003044 + 41000.0, 0.68, 2.25, -0.01353, 0.003075 + 41000.0, 0.68, 2.3, -0.01043, 0.003108 + 41000.0, 0.68, 2.35, -0.007328, 0.003141 + 41000.0, 0.68, 2.4, -0.004233, 0.003175 + 41000.0, 0.68, 2.45, -0.001141, 0.00321 + 41000.0, 0.68, 2.5, 0.001948, 0.003246 + 41000.0, 0.68, 2.55, 0.005033, 0.003283 + 41000.0, 0.68, 2.6, 0.008112, 0.003321 + 41000.0, 0.68, 2.65, 0.01119, 0.003359 + 41000.0, 0.68, 2.7, 0.01426, 0.003399 + 41000.0, 0.68, 2.75, 0.01732, 0.00344 + 41000.0, 0.68, 2.8, 0.02038, 0.003482 + 41000.0, 0.68, 2.85, 0.02343, 0.003525 + 41000.0, 0.68, 2.9, 0.02648, 0.003569 + 41000.0, 0.68, 2.95, 0.02951, 0.003614 + 41000.0, 0.68, 3.0, 0.03254, 0.00366 + 41000.0, 0.68, 3.05, 0.03556, 0.003708 + 41000.0, 0.68, 3.1, 0.03858, 0.003757 + 41000.0, 0.68, 3.15, 0.04158, 0.003806 + 41000.0, 0.68, 3.2, 0.04457, 0.003858 + 41000.0, 0.68, 3.25, 0.04756, 0.00391 + 41000.0, 0.68, 3.3, 0.05053, 0.003964 + 41000.0, 0.68, 3.35, 0.0535, 0.004019 + 41000.0, 0.68, 3.4, 0.05645, 0.004075 + 41000.0, 0.68, 3.45, 0.05939, 0.004133 + 41000.0, 0.68, 3.5, 0.06232, 0.004192 + 41000.0, 0.68, 3.55, 0.06524, 0.004253 + 41000.0, 0.68, 3.6, 0.06814, 0.004315 + 41000.0, 0.68, 3.65, 0.07103, 0.004378 + 41000.0, 0.68, 3.7, 0.07391, 0.004443 + 41000.0, 0.68, 3.75, 0.07677, 0.00451 + 41000.0, 0.68, 3.8, 0.07962, 0.004577 + 41000.0, 0.68, 3.85, 0.08246, 0.004647 + 41000.0, 0.68, 3.9, 0.08528, 0.004718 + 41000.0, 0.68, 3.95, 0.08808, 0.004791 + 41000.0, 0.68, 4.0, 0.09087, 0.004865 + 41000.0, 0.68, 4.05, 0.09352, 0.004932 + 41000.0, 0.68, 4.1, 0.09617, 0.005001 + 41000.0, 0.68, 4.15, 0.0988, 0.005073 + 41000.0, 0.68, 4.2, 0.1014, 0.005147 + 41000.0, 0.68, 4.25, 0.104, 0.005223 + 41000.0, 0.68, 4.3, 0.1067, 0.005302 + 41000.0, 0.68, 4.35, 0.1093, 0.005384 + 41000.0, 0.68, 4.4, 0.1118, 0.005468 + 41000.0, 0.68, 4.45, 0.1144, 0.005555 + 41000.0, 0.68, 4.5, 0.117, 0.005645 + 41000.0, 0.68, 4.55, 0.1196, 0.005739 + 41000.0, 0.68, 4.6, 0.1222, 0.005835 + 41000.0, 0.68, 4.65, 0.1247, 0.005935 + 41000.0, 0.68, 4.7, 0.1273, 0.006037 + 41000.0, 0.68, 4.75, 0.1299, 0.006144 + 41000.0, 0.68, 4.8, 0.1324, 0.006253 + 41000.0, 0.68, 4.85, 0.135, 0.006367 + 41000.0, 0.68, 4.9, 0.1376, 0.006484 + 41000.0, 0.68, 4.95, 0.1401, 0.006605 + 41000.0, 0.68, 5.0, 0.1427, 0.006729 + 41000.0, 0.68, 5.05, 0.1453, 0.006884 + 41000.0, 0.68, 5.1, 0.148, 0.007042 + 41000.0, 0.68, 5.15, 0.1507, 0.007204 + 41000.0, 0.68, 5.2, 0.1533, 0.007368 + 41000.0, 0.68, 5.25, 0.156, 0.007536 + 41000.0, 0.68, 5.3, 0.1586, 0.007706 + 41000.0, 0.68, 5.35, 0.1613, 0.007878 + 41000.0, 0.68, 5.4, 0.1639, 0.008052 + 41000.0, 0.68, 5.45, 0.1665, 0.008228 + 41000.0, 0.68, 5.5, 0.1691, 0.008404 + 41000.0, 0.68, 5.55, 0.1717, 0.008582 + 41000.0, 0.68, 5.6, 0.1743, 0.008761 + 41000.0, 0.68, 5.65, 0.1769, 0.00894 + 41000.0, 0.68, 5.7, 0.1795, 0.009119 + 41000.0, 0.68, 5.75, 0.182, 0.009298 + 41000.0, 0.68, 5.8, 0.1845, 0.009476 + 41000.0, 0.68, 5.85, 0.1871, 0.009654 + 41000.0, 0.68, 5.9, 0.1895, 0.00983 + 41000.0, 0.68, 5.95, 0.192, 0.01001 + 41000.0, 0.68, 6.0, 0.1945, 0.01018 + 41000.0, 0.68, 6.05, 0.1966, 0.01029 + 41000.0, 0.68, 6.1, 0.1987, 0.0104 + 41000.0, 0.68, 6.15, 0.2008, 0.0105 + 41000.0, 0.68, 6.2, 0.2028, 0.0106 + 41000.0, 0.68, 6.25, 0.2048, 0.0107 + 41000.0, 0.68, 6.3, 0.2068, 0.01079 + 41000.0, 0.68, 6.35, 0.2087, 0.01088 + 41000.0, 0.68, 6.4, 0.2106, 0.01096 + 41000.0, 0.68, 6.45, 0.2125, 0.01104 + 41000.0, 0.68, 6.5, 0.2143, 0.01111 + 41000.0, 0.68, 6.55, 0.2161, 0.01119 + 41000.0, 0.68, 6.6, 0.2179, 0.01125 + 41000.0, 0.68, 6.65, 0.2197, 0.01132 + 41000.0, 0.68, 6.7, 0.2214, 0.01138 + 41000.0, 0.68, 6.75, 0.2231, 0.01144 + 41000.0, 0.68, 6.8, 0.2248, 0.0115 + 41000.0, 0.68, 6.85, 0.2265, 0.01155 + 41000.0, 0.68, 6.9, 0.2282, 0.0116 + 41000.0, 0.68, 6.95, 0.2298, 0.01165 + 41000.0, 0.68, 7.0, 0.2314, 0.0117 + 41000.0, 0.68, 7.05, 0.233, 0.01174 + 41000.0, 0.68, 7.1, 0.2346, 0.01178 + 41000.0, 0.68, 7.15, 0.2361, 0.01182 + 41000.0, 0.68, 7.2, 0.2377, 0.01186 + 41000.0, 0.68, 7.25, 0.2392, 0.0119 + 41000.0, 0.68, 7.3, 0.2407, 0.01193 + 41000.0, 0.68, 7.35, 0.2422, 0.01197 + 41000.0, 0.68, 7.4, 0.2437, 0.012 + 41000.0, 0.68, 7.45, 0.2452, 0.01203 + 41000.0, 0.68, 7.5, 0.2467, 0.01206 + 41000.0, 0.68, 7.55, 0.2481, 0.01209 + 41000.0, 0.68, 7.6, 0.2496, 0.01212 + 41000.0, 0.68, 7.65, 0.251, 0.01214 + 41000.0, 0.68, 7.7, 0.2525, 0.01217 + 41000.0, 0.68, 7.75, 0.2539, 0.0122 + 41000.0, 0.68, 7.8, 0.2554, 0.01222 + 41000.0, 0.68, 7.85, 0.2568, 0.01225 + 41000.0, 0.68, 7.9, 0.2582, 0.01228 + 41000.0, 0.68, 7.95, 0.2597, 0.0123 + 41000.0, 0.68, 8.0, 0.2611, 0.01233 + 41000.0, 0.68, 8.05, 0.2628, 0.01239 + 41000.0, 0.68, 8.1, 0.2645, 0.01246 + 41000.0, 0.68, 8.15, 0.2662, 0.01252 + 41000.0, 0.68, 8.2, 0.2678, 0.01259 + 41000.0, 0.68, 8.25, 0.2695, 0.01265 + 41000.0, 0.68, 8.3, 0.2712, 0.01272 + 41000.0, 0.68, 8.35, 0.2729, 0.01278 + 41000.0, 0.68, 8.4, 0.2746, 0.01285 + 41000.0, 0.68, 8.45, 0.2763, 0.01292 + 41000.0, 0.68, 8.5, 0.278, 0.01298 + 41000.0, 0.68, 8.55, 0.2797, 0.01305 + 41000.0, 0.68, 8.6, 0.2814, 0.01312 + 41000.0, 0.68, 8.65, 0.2831, 0.01319 + 41000.0, 0.68, 8.7, 0.2848, 0.01325 + 41000.0, 0.68, 8.75, 0.2865, 0.01332 + 41000.0, 0.68, 8.8, 0.2882, 0.01339 + 41000.0, 0.68, 8.85, 0.2899, 0.01346 + 41000.0, 0.68, 8.9, 0.2916, 0.01353 + 41000.0, 0.68, 8.95, 0.2933, 0.0136 + 41000.0, 0.68, 9.0, 0.295, 0.01367 + 41000.0, 0.68, 9.05, 0.2967, 0.01374 + 41000.0, 0.68, 9.1, 0.2984, 0.01381 + 41000.0, 0.68, 9.15, 0.3001, 0.01388 + 41000.0, 0.68, 9.2, 0.3018, 0.01395 + 41000.0, 0.68, 9.25, 0.3036, 0.01402 + 41000.0, 0.68, 9.3, 0.3053, 0.01409 + 41000.0, 0.68, 9.35, 0.307, 0.01417 + 41000.0, 0.68, 9.4, 0.3087, 0.01424 + 41000.0, 0.68, 9.45, 0.3104, 0.01431 + 41000.0, 0.68, 9.5, 0.3121, 0.01438 + 41000.0, 0.68, 9.55, 0.3138, 0.01445 + 41000.0, 0.68, 9.6, 0.3155, 0.01453 + 41000.0, 0.68, 9.65, 0.3172, 0.0146 + 41000.0, 0.68, 9.7, 0.3189, 0.01467 + 41000.0, 0.68, 9.75, 0.3206, 0.01474 + 41000.0, 0.68, 9.8, 0.3223, 0.01482 + 41000.0, 0.68, 9.85, 0.3241, 0.01489 + 41000.0, 0.68, 9.9, 0.3258, 0.01496 + 41000.0, 0.68, 9.95, 0.3275, 0.01504 + 41000.0, 0.68, 10.0, 0.3292, 0.01511 + 41000.0, 0.68, 10.05, 0.3309, 0.01518 + 41000.0, 0.68, 10.1, 0.3326, 0.01525 + 41000.0, 0.68, 10.15, 0.3343, 0.01532 + 41000.0, 0.68, 10.2, 0.336, 0.01538 + 41000.0, 0.68, 10.25, 0.3377, 0.01545 + 41000.0, 0.68, 10.3, 0.3394, 0.01552 + 41000.0, 0.68, 10.35, 0.3411, 0.01559 + 41000.0, 0.68, 10.4, 0.3428, 0.01566 + 41000.0, 0.68, 10.45, 0.3445, 0.01573 + 41000.0, 0.68, 10.5, 0.3462, 0.0158 + 41000.0, 0.68, 10.55, 0.348, 0.01587 + 41000.0, 0.68, 10.6, 0.3497, 0.01594 + 41000.0, 0.68, 10.65, 0.3514, 0.01601 + 41000.0, 0.68, 10.7, 0.3531, 0.01608 + 41000.0, 0.68, 10.75, 0.3548, 0.01615 + 41000.0, 0.68, 10.8, 0.3565, 0.01622 + 41000.0, 0.68, 10.85, 0.3582, 0.0163 + 41000.0, 0.68, 10.9, 0.3599, 0.01637 + 41000.0, 0.68, 10.95, 0.3616, 0.01644 + 41000.0, 0.68, 11.0, 0.3633, 0.01651 + 41000.0, 0.68, 11.05, 0.365, 0.01659 + 41000.0, 0.68, 11.1, 0.3667, 0.01666 + 41000.0, 0.68, 11.15, 0.3684, 0.01674 + 41000.0, 0.68, 11.2, 0.3701, 0.01681 + 41000.0, 0.68, 11.25, 0.3718, 0.01689 + 41000.0, 0.68, 11.3, 0.3736, 0.01696 + 41000.0, 0.68, 11.35, 0.3753, 0.01704 + 41000.0, 0.68, 11.4, 0.377, 0.01711 + 41000.0, 0.68, 11.45, 0.3787, 0.01719 + 41000.0, 0.68, 11.5, 0.3804, 0.01727 + 41000.0, 0.68, 11.55, 0.3821, 0.01735 + 41000.0, 0.68, 11.6, 0.3838, 0.01743 + 41000.0, 0.68, 11.65, 0.3855, 0.01751 + 41000.0, 0.68, 11.7, 0.3872, 0.01759 + 41000.0, 0.68, 11.75, 0.3889, 0.01767 + 41000.0, 0.68, 11.8, 0.3906, 0.01775 + 41000.0, 0.68, 11.85, 0.3923, 0.01783 + 41000.0, 0.68, 11.9, 0.394, 0.01791 + 41000.0, 0.68, 11.95, 0.3957, 0.018 + 41000.0, 0.68, 12.0, 0.3974, 0.01808 + 41000.0, 0.68, 12.05, 0.3991, 0.01816 + 41000.0, 0.68, 12.1, 0.4008, 0.01825 + 41000.0, 0.68, 12.15, 0.4026, 0.01834 + 41000.0, 0.68, 12.2, 0.4043, 0.01842 + 41000.0, 0.68, 12.25, 0.406, 0.01851 + 41000.0, 0.68, 12.3, 0.4077, 0.0186 + 41000.0, 0.68, 12.35, 0.4094, 0.01869 + 41000.0, 0.68, 12.4, 0.4111, 0.01878 + 41000.0, 0.68, 12.45, 0.4128, 0.01887 + 41000.0, 0.68, 12.5, 0.4145, 0.01896 + 41000.0, 0.68, 12.55, 0.4162, 0.01905 + 41000.0, 0.68, 12.6, 0.4179, 0.01914 + 41000.0, 0.68, 12.65, 0.4196, 0.01924 + 41000.0, 0.68, 12.7, 0.4213, 0.01933 + 41000.0, 0.68, 12.75, 0.423, 0.01943 + 41000.0, 0.68, 12.8, 0.4247, 0.01953 + 41000.0, 0.68, 12.85, 0.4264, 0.01962 + 41000.0, 0.68, 12.9, 0.4281, 0.01972 + 41000.0, 0.68, 12.95, 0.4298, 0.01982 + 41000.0, 0.68, 13.0, 0.4315, 0.01992 + 41000.0, 0.68, 13.05, 0.4332, 0.02002 + 41000.0, 0.68, 13.1, 0.4349, 0.02013 + 41000.0, 0.68, 13.15, 0.4366, 0.02023 + 41000.0, 0.68, 13.2, 0.4383, 0.02033 + 41000.0, 0.68, 13.25, 0.44, 0.02044 + 41000.0, 0.68, 13.3, 0.4417, 0.02055 + 41000.0, 0.68, 13.35, 0.4434, 0.02065 + 41000.0, 0.68, 13.4, 0.4451, 0.02076 + 41000.0, 0.68, 13.45, 0.4468, 0.02087 + 41000.0, 0.68, 13.5, 0.4485, 0.02098 + 41000.0, 0.68, 13.55, 0.4502, 0.0211 + 41000.0, 0.68, 13.6, 0.4519, 0.02121 + 41000.0, 0.68, 13.65, 0.4536, 0.02132 + 41000.0, 0.68, 13.7, 0.4553, 0.02144 + 41000.0, 0.68, 13.75, 0.457, 0.02156 + 41000.0, 0.68, 13.8, 0.4587, 0.02167 + 41000.0, 0.68, 13.85, 0.4604, 0.02179 + 41000.0, 0.68, 13.9, 0.4621, 0.02191 + 41000.0, 0.68, 13.95, 0.4638, 0.02203 + 41000.0, 0.68, 14.0, 0.4655, 0.02216 + 41000.0, 0.68, 14.05, 0.4671, 0.02228 + 41000.0, 0.68, 14.1, 0.4688, 0.02241 + 41000.0, 0.68, 14.15, 0.4705, 0.02253 + 41000.0, 0.68, 14.2, 0.4722, 0.02266 + 41000.0, 0.68, 14.25, 0.4739, 0.02279 + 41000.0, 0.68, 14.3, 0.4756, 0.02292 + 41000.0, 0.68, 14.35, 0.4773, 0.02305 + 41000.0, 0.68, 14.4, 0.479, 0.02319 + 41000.0, 0.68, 14.45, 0.4807, 0.02332 + 41000.0, 0.68, 14.5, 0.4824, 0.02346 + 41000.0, 0.68, 14.55, 0.4841, 0.0236 + 41000.0, 0.68, 14.6, 0.4857, 0.02374 + 41000.0, 0.68, 14.65, 0.4874, 0.02388 + 41000.0, 0.68, 14.7, 0.4891, 0.02402 + 41000.0, 0.68, 14.75, 0.4908, 0.02416 + 41000.0, 0.68, 14.8, 0.4925, 0.02431 + 41000.0, 0.68, 14.85, 0.4942, 0.02445 + 41000.0, 0.68, 14.9, 0.4959, 0.0246 + 41000.0, 0.68, 14.95, 0.4976, 0.02475 + 41000.0, 0.68, 15.0, 0.4992, 0.0249 + 41000.0, 0.68, 15.05, 0.5009, 0.02505 + 41000.0, 0.73, 0.0, -0.1665, 0.009316 + 41000.0, 0.73, 0.05, -0.1631, 0.00926 + 41000.0, 0.73, 0.1, -0.1596, 0.0092 + 41000.0, 0.73, 0.15, -0.1562, 0.009137 + 41000.0, 0.73, 0.2, -0.1528, 0.00907 + 41000.0, 0.73, 0.25, -0.1494, 0.009001 + 41000.0, 0.73, 0.3, -0.146, 0.008929 + 41000.0, 0.73, 0.35, -0.1426, 0.008854 + 41000.0, 0.73, 0.4, -0.1392, 0.008776 + 41000.0, 0.73, 0.45, -0.1359, 0.008696 + 41000.0, 0.73, 0.5, -0.1325, 0.008613 + 41000.0, 0.73, 0.55, -0.1292, 0.008528 + 41000.0, 0.73, 0.6, -0.1258, 0.00844 + 41000.0, 0.73, 0.65, -0.1225, 0.008351 + 41000.0, 0.73, 0.7, -0.1192, 0.008259 + 41000.0, 0.73, 0.75, -0.1159, 0.008166 + 41000.0, 0.73, 0.8, -0.1126, 0.008071 + 41000.0, 0.73, 0.85, -0.1093, 0.007974 + 41000.0, 0.73, 0.9, -0.106, 0.007876 + 41000.0, 0.73, 0.95, -0.1027, 0.007776 + 41000.0, 0.73, 1.0, -0.09946, 0.007675 + 41000.0, 0.73, 1.05, -0.09619, 0.007573 + 41000.0, 0.73, 1.1, -0.09293, 0.007469 + 41000.0, 0.73, 1.15, -0.08968, 0.007365 + 41000.0, 0.73, 1.2, -0.08644, 0.00726 + 41000.0, 0.73, 1.25, -0.08319, 0.007155 + 41000.0, 0.73, 1.3, -0.07996, 0.007048 + 41000.0, 0.73, 1.35, -0.07673, 0.006941 + 41000.0, 0.73, 1.4, -0.0735, 0.006834 + 41000.0, 0.73, 1.45, -0.07028, 0.006727 + 41000.0, 0.73, 1.5, -0.06707, 0.006619 + 41000.0, 0.73, 1.55, -0.06385, 0.006512 + 41000.0, 0.73, 1.6, -0.06065, 0.006405 + 41000.0, 0.73, 1.65, -0.05744, 0.006297 + 41000.0, 0.73, 1.7, -0.05424, 0.006191 + 41000.0, 0.73, 1.75, -0.05104, 0.006084 + 41000.0, 0.73, 1.8, -0.04785, 0.005978 + 41000.0, 0.73, 1.85, -0.04466, 0.005873 + 41000.0, 0.73, 1.9, -0.04147, 0.005769 + 41000.0, 0.73, 1.95, -0.03828, 0.005666 + 41000.0, 0.73, 2.0, -0.03509, 0.005563 + 41000.0, 0.73, 2.05, -0.03191, 0.005462 + 41000.0, 0.73, 2.1, -0.02873, 0.005362 + 41000.0, 0.73, 2.15, -0.02554, 0.005264 + 41000.0, 0.73, 2.2, -0.02236, 0.005167 + 41000.0, 0.73, 2.25, -0.01918, 0.005072 + 41000.0, 0.73, 2.3, -0.016, 0.004978 + 41000.0, 0.73, 2.35, -0.01282, 0.004886 + 41000.0, 0.73, 2.4, -0.009643, 0.004797 + 41000.0, 0.73, 2.45, -0.006462, 0.004709 + 41000.0, 0.73, 2.5, -0.003281, 0.004624 + 41000.0, 0.73, 2.55, -9.861e-05, 0.00454 + 41000.0, 0.73, 2.6, 0.003085, 0.00446 + 41000.0, 0.73, 2.65, 0.00627, 0.004382 + 41000.0, 0.73, 2.7, 0.009456, 0.004306 + 41000.0, 0.73, 2.75, 0.01264, 0.004234 + 41000.0, 0.73, 2.8, 0.01584, 0.004164 + 41000.0, 0.73, 2.85, 0.01903, 0.004098 + 41000.0, 0.73, 2.9, 0.02222, 0.004034 + 41000.0, 0.73, 2.95, 0.02542, 0.003974 + 41000.0, 0.73, 3.0, 0.02863, 0.003917 + 41000.0, 0.73, 3.05, 0.03183, 0.003864 + 41000.0, 0.73, 3.1, 0.03504, 0.003814 + 41000.0, 0.73, 3.15, 0.03826, 0.003768 + 41000.0, 0.73, 3.2, 0.04147, 0.003726 + 41000.0, 0.73, 3.25, 0.0447, 0.003688 + 41000.0, 0.73, 3.3, 0.04792, 0.003654 + 41000.0, 0.73, 3.35, 0.05116, 0.003624 + 41000.0, 0.73, 3.4, 0.05439, 0.003598 + 41000.0, 0.73, 3.45, 0.05764, 0.003577 + 41000.0, 0.73, 3.5, 0.06089, 0.003561 + 41000.0, 0.73, 3.55, 0.06414, 0.003549 + 41000.0, 0.73, 3.6, 0.0674, 0.003542 + 41000.0, 0.73, 3.65, 0.07067, 0.00354 + 41000.0, 0.73, 3.7, 0.07395, 0.003543 + 41000.0, 0.73, 3.75, 0.07723, 0.003551 + 41000.0, 0.73, 3.8, 0.08052, 0.003564 + 41000.0, 0.73, 3.85, 0.08381, 0.003582 + 41000.0, 0.73, 3.9, 0.08712, 0.003607 + 41000.0, 0.73, 3.95, 0.09043, 0.003636 + 41000.0, 0.73, 4.0, 0.09375, 0.003672 + 41000.0, 0.73, 4.05, 0.09715, 0.003718 + 41000.0, 0.73, 4.1, 0.1006, 0.00377 + 41000.0, 0.73, 4.15, 0.104, 0.003827 + 41000.0, 0.73, 4.2, 0.1074, 0.00389 + 41000.0, 0.73, 4.25, 0.1108, 0.00396 + 41000.0, 0.73, 4.3, 0.1142, 0.004035 + 41000.0, 0.73, 4.35, 0.1176, 0.004116 + 41000.0, 0.73, 4.4, 0.1211, 0.004204 + 41000.0, 0.73, 4.45, 0.1245, 0.004297 + 41000.0, 0.73, 4.5, 0.1279, 0.004397 + 41000.0, 0.73, 4.55, 0.1314, 0.004504 + 41000.0, 0.73, 4.6, 0.1348, 0.004617 + 41000.0, 0.73, 4.65, 0.1382, 0.004736 + 41000.0, 0.73, 4.7, 0.1417, 0.004862 + 41000.0, 0.73, 4.75, 0.1451, 0.004995 + 41000.0, 0.73, 4.8, 0.1486, 0.005135 + 41000.0, 0.73, 4.85, 0.152, 0.005281 + 41000.0, 0.73, 4.9, 0.1555, 0.005435 + 41000.0, 0.73, 4.95, 0.1589, 0.005595 + 41000.0, 0.73, 5.0, 0.1623, 0.005763 + 41000.0, 0.73, 5.05, 0.166, 0.005959 + 41000.0, 0.73, 5.1, 0.1696, 0.006163 + 41000.0, 0.73, 5.15, 0.1732, 0.006373 + 41000.0, 0.73, 5.2, 0.1767, 0.00659 + 41000.0, 0.73, 5.25, 0.1803, 0.006813 + 41000.0, 0.73, 5.3, 0.1839, 0.007041 + 41000.0, 0.73, 5.35, 0.1874, 0.007276 + 41000.0, 0.73, 5.4, 0.191, 0.007516 + 41000.0, 0.73, 5.45, 0.1945, 0.007761 + 41000.0, 0.73, 5.5, 0.198, 0.008011 + 41000.0, 0.73, 5.55, 0.2014, 0.008266 + 41000.0, 0.73, 5.6, 0.2049, 0.008526 + 41000.0, 0.73, 5.65, 0.2083, 0.008789 + 41000.0, 0.73, 5.7, 0.2116, 0.009057 + 41000.0, 0.73, 5.75, 0.215, 0.009328 + 41000.0, 0.73, 5.8, 0.2183, 0.009603 + 41000.0, 0.73, 5.85, 0.2215, 0.009881 + 41000.0, 0.73, 5.9, 0.2247, 0.01016 + 41000.0, 0.73, 5.95, 0.2279, 0.01045 + 41000.0, 0.73, 6.0, 0.231, 0.01073 + 41000.0, 0.73, 6.05, 0.2334, 0.01098 + 41000.0, 0.73, 6.1, 0.2357, 0.01123 + 41000.0, 0.73, 6.15, 0.2379, 0.01148 + 41000.0, 0.73, 6.2, 0.2401, 0.01173 + 41000.0, 0.73, 6.25, 0.2421, 0.01198 + 41000.0, 0.73, 6.3, 0.2441, 0.01223 + 41000.0, 0.73, 6.35, 0.2461, 0.01249 + 41000.0, 0.73, 6.4, 0.2479, 0.01274 + 41000.0, 0.73, 6.45, 0.2497, 0.01299 + 41000.0, 0.73, 6.5, 0.2514, 0.01325 + 41000.0, 0.73, 6.55, 0.2531, 0.0135 + 41000.0, 0.73, 6.6, 0.2547, 0.01376 + 41000.0, 0.73, 6.65, 0.2563, 0.01401 + 41000.0, 0.73, 6.7, 0.2577, 0.01427 + 41000.0, 0.73, 6.75, 0.2592, 0.01453 + 41000.0, 0.73, 6.8, 0.2605, 0.01479 + 41000.0, 0.73, 6.85, 0.2619, 0.01505 + 41000.0, 0.73, 6.9, 0.2631, 0.01531 + 41000.0, 0.73, 6.95, 0.2644, 0.01557 + 41000.0, 0.73, 7.0, 0.2655, 0.01583 + 41000.0, 0.73, 7.05, 0.2667, 0.0161 + 41000.0, 0.73, 7.1, 0.2678, 0.01636 + 41000.0, 0.73, 7.15, 0.2688, 0.01663 + 41000.0, 0.73, 7.2, 0.2699, 0.0169 + 41000.0, 0.73, 7.25, 0.2708, 0.01717 + 41000.0, 0.73, 7.3, 0.2718, 0.01744 + 41000.0, 0.73, 7.35, 0.2727, 0.01771 + 41000.0, 0.73, 7.4, 0.2736, 0.01798 + 41000.0, 0.73, 7.45, 0.2745, 0.01826 + 41000.0, 0.73, 7.5, 0.2753, 0.01854 + 41000.0, 0.73, 7.55, 0.2762, 0.01881 + 41000.0, 0.73, 7.6, 0.277, 0.01909 + 41000.0, 0.73, 7.65, 0.2777, 0.01938 + 41000.0, 0.73, 7.7, 0.2785, 0.01966 + 41000.0, 0.73, 7.75, 0.2793, 0.01994 + 41000.0, 0.73, 7.8, 0.28, 0.02023 + 41000.0, 0.73, 7.85, 0.2808, 0.02052 + 41000.0, 0.73, 7.9, 0.2815, 0.02081 + 41000.0, 0.73, 7.95, 0.2822, 0.0211 + 41000.0, 0.73, 8.0, 0.2829, 0.02139 + 41000.0, 0.73, 8.05, 0.2842, 0.02171 + 41000.0, 0.73, 8.1, 0.2855, 0.02202 + 41000.0, 0.73, 8.15, 0.2868, 0.02234 + 41000.0, 0.73, 8.2, 0.288, 0.02265 + 41000.0, 0.73, 8.25, 0.2893, 0.02297 + 41000.0, 0.73, 8.3, 0.2906, 0.0233 + 41000.0, 0.73, 8.35, 0.2918, 0.02362 + 41000.0, 0.73, 8.4, 0.2931, 0.02394 + 41000.0, 0.73, 8.45, 0.2944, 0.02427 + 41000.0, 0.73, 8.5, 0.2956, 0.0246 + 41000.0, 0.73, 8.55, 0.2969, 0.02493 + 41000.0, 0.73, 8.6, 0.2982, 0.02526 + 41000.0, 0.73, 8.65, 0.2994, 0.0256 + 41000.0, 0.73, 8.7, 0.3007, 0.02593 + 41000.0, 0.73, 8.75, 0.302, 0.02627 + 41000.0, 0.73, 8.8, 0.3032, 0.02661 + 41000.0, 0.73, 8.85, 0.3045, 0.02695 + 41000.0, 0.73, 8.9, 0.3058, 0.02729 + 41000.0, 0.73, 8.95, 0.307, 0.02764 + 41000.0, 0.73, 9.0, 0.3083, 0.02798 + 41000.0, 0.73, 9.05, 0.3096, 0.02833 + 41000.0, 0.73, 9.1, 0.3108, 0.02868 + 41000.0, 0.73, 9.15, 0.3121, 0.02903 + 41000.0, 0.73, 9.2, 0.3133, 0.02938 + 41000.0, 0.73, 9.25, 0.3146, 0.02973 + 41000.0, 0.73, 9.3, 0.3159, 0.03009 + 41000.0, 0.73, 9.35, 0.3171, 0.03045 + 41000.0, 0.73, 9.4, 0.3184, 0.0308 + 41000.0, 0.73, 9.45, 0.3196, 0.03116 + 41000.0, 0.73, 9.5, 0.3209, 0.03152 + 41000.0, 0.73, 9.55, 0.3221, 0.03188 + 41000.0, 0.73, 9.6, 0.3234, 0.03225 + 41000.0, 0.73, 9.65, 0.3247, 0.03261 + 41000.0, 0.73, 9.7, 0.3259, 0.03298 + 41000.0, 0.73, 9.75, 0.3272, 0.03335 + 41000.0, 0.73, 9.8, 0.3284, 0.03371 + 41000.0, 0.73, 9.85, 0.3297, 0.03408 + 41000.0, 0.73, 9.9, 0.3309, 0.03445 + 41000.0, 0.73, 9.95, 0.3322, 0.03483 + 41000.0, 0.73, 10.0, 0.3335, 0.0352 + 41000.0, 0.73, 10.05, 0.3347, 0.03559 + 41000.0, 0.73, 10.1, 0.336, 0.03597 + 41000.0, 0.73, 10.15, 0.3372, 0.03636 + 41000.0, 0.73, 10.2, 0.3385, 0.03675 + 41000.0, 0.73, 10.25, 0.3398, 0.03714 + 41000.0, 0.73, 10.3, 0.341, 0.03753 + 41000.0, 0.73, 10.35, 0.3423, 0.03792 + 41000.0, 0.73, 10.4, 0.3435, 0.03831 + 41000.0, 0.73, 10.45, 0.3448, 0.03871 + 41000.0, 0.73, 10.5, 0.346, 0.0391 + 41000.0, 0.73, 10.55, 0.3473, 0.03949 + 41000.0, 0.73, 10.6, 0.3486, 0.03989 + 41000.0, 0.73, 10.65, 0.3498, 0.04028 + 41000.0, 0.73, 10.7, 0.3511, 0.04068 + 41000.0, 0.73, 10.75, 0.3523, 0.04107 + 41000.0, 0.73, 10.8, 0.3536, 0.04147 + 41000.0, 0.73, 10.85, 0.3549, 0.04187 + 41000.0, 0.73, 10.9, 0.3561, 0.04226 + 41000.0, 0.73, 10.95, 0.3574, 0.04266 + 41000.0, 0.73, 11.0, 0.3586, 0.04305 + 41000.0, 0.73, 11.05, 0.3599, 0.04345 + 41000.0, 0.73, 11.1, 0.3612, 0.04385 + 41000.0, 0.73, 11.15, 0.3624, 0.04424 + 41000.0, 0.73, 11.2, 0.3637, 0.04464 + 41000.0, 0.73, 11.25, 0.3649, 0.04503 + 41000.0, 0.73, 11.3, 0.3662, 0.04543 + 41000.0, 0.73, 11.35, 0.3674, 0.04582 + 41000.0, 0.73, 11.4, 0.3687, 0.04622 + 41000.0, 0.73, 11.45, 0.37, 0.04661 + 41000.0, 0.73, 11.5, 0.3712, 0.04701 + 41000.0, 0.73, 11.55, 0.3725, 0.0474 + 41000.0, 0.73, 11.6, 0.3737, 0.04779 + 41000.0, 0.73, 11.65, 0.375, 0.04818 + 41000.0, 0.73, 11.7, 0.3763, 0.04857 + 41000.0, 0.73, 11.75, 0.3775, 0.04896 + 41000.0, 0.73, 11.8, 0.3788, 0.04935 + 41000.0, 0.73, 11.85, 0.38, 0.04974 + 41000.0, 0.73, 11.9, 0.3813, 0.05012 + 41000.0, 0.73, 11.95, 0.3826, 0.05051 + 41000.0, 0.73, 12.0, 0.3838, 0.05089 + 41000.0, 0.73, 12.05, 0.3851, 0.05127 + 41000.0, 0.73, 12.1, 0.3863, 0.05166 + 41000.0, 0.73, 12.15, 0.3876, 0.05204 + 41000.0, 0.73, 12.2, 0.3889, 0.05241 + 41000.0, 0.73, 12.25, 0.3901, 0.05279 + 41000.0, 0.73, 12.3, 0.3914, 0.05317 + 41000.0, 0.73, 12.35, 0.3926, 0.05354 + 41000.0, 0.73, 12.4, 0.3939, 0.05391 + 41000.0, 0.73, 12.45, 0.3952, 0.05428 + 41000.0, 0.73, 12.5, 0.3964, 0.05465 + 41000.0, 0.73, 12.55, 0.3977, 0.05502 + 41000.0, 0.73, 12.6, 0.3989, 0.05538 + 41000.0, 0.73, 12.65, 0.4002, 0.05575 + 41000.0, 0.73, 12.7, 0.4015, 0.05611 + 41000.0, 0.73, 12.75, 0.4027, 0.05646 + 41000.0, 0.73, 12.8, 0.404, 0.05682 + 41000.0, 0.73, 12.85, 0.4053, 0.05718 + 41000.0, 0.73, 12.9, 0.4065, 0.05753 + 41000.0, 0.73, 12.95, 0.4078, 0.05788 + 41000.0, 0.73, 13.0, 0.4091, 0.05822 + 41000.0, 0.73, 13.05, 0.4103, 0.05857 + 41000.0, 0.73, 13.1, 0.4116, 0.05891 + 41000.0, 0.73, 13.15, 0.4128, 0.05925 + 41000.0, 0.73, 13.2, 0.4141, 0.05959 + 41000.0, 0.73, 13.25, 0.4154, 0.05992 + 41000.0, 0.73, 13.3, 0.4166, 0.06025 + 41000.0, 0.73, 13.35, 0.4179, 0.06058 + 41000.0, 0.73, 13.4, 0.4192, 0.06091 + 41000.0, 0.73, 13.45, 0.4204, 0.06123 + 41000.0, 0.73, 13.5, 0.4217, 0.06155 + 41000.0, 0.73, 13.55, 0.423, 0.06186 + 41000.0, 0.73, 13.6, 0.4242, 0.06218 + 41000.0, 0.73, 13.65, 0.4255, 0.06249 + 41000.0, 0.73, 13.7, 0.4268, 0.06279 + 41000.0, 0.73, 13.75, 0.428, 0.0631 + 41000.0, 0.73, 13.8, 0.4293, 0.0634 + 41000.0, 0.73, 13.85, 0.4306, 0.06369 + 41000.0, 0.73, 13.9, 0.4318, 0.06399 + 41000.0, 0.73, 13.95, 0.4331, 0.06428 + 41000.0, 0.73, 14.0, 0.4344, 0.06456 + 41000.0, 0.73, 14.05, 0.4357, 0.06484 + 41000.0, 0.73, 14.1, 0.4369, 0.06512 + 41000.0, 0.73, 14.15, 0.4382, 0.0654 + 41000.0, 0.73, 14.2, 0.4395, 0.06567 + 41000.0, 0.73, 14.25, 0.4407, 0.06593 + 41000.0, 0.73, 14.3, 0.442, 0.0662 + 41000.0, 0.73, 14.35, 0.4433, 0.06645 + 41000.0, 0.73, 14.4, 0.4445, 0.06671 + 41000.0, 0.73, 14.45, 0.4458, 0.06696 + 41000.0, 0.73, 14.5, 0.4471, 0.06721 + 41000.0, 0.73, 14.55, 0.4484, 0.06745 + 41000.0, 0.73, 14.6, 0.4496, 0.06768 + 41000.0, 0.73, 14.65, 0.4509, 0.06792 + 41000.0, 0.73, 14.7, 0.4522, 0.06815 + 41000.0, 0.73, 14.75, 0.4535, 0.06837 + 41000.0, 0.73, 14.8, 0.4547, 0.06859 + 41000.0, 0.73, 14.85, 0.456, 0.0688 + 41000.0, 0.73, 14.9, 0.4573, 0.06901 + 41000.0, 0.73, 14.95, 0.4586, 0.06922 + 41000.0, 0.73, 15.0, 0.4598, 0.06942 + 41000.0, 0.73, 15.05, 0.4611, 0.06961 + 41000.0, 0.78, 0.0, -0.1839, 0.009891 + 41000.0, 0.78, 0.05, -0.1801, 0.009843 + 41000.0, 0.78, 0.1, -0.1763, 0.00979 + 41000.0, 0.78, 0.15, -0.1726, 0.009734 + 41000.0, 0.78, 0.2, -0.1688, 0.009675 + 41000.0, 0.78, 0.25, -0.1651, 0.009612 + 41000.0, 0.78, 0.3, -0.1614, 0.009546 + 41000.0, 0.78, 0.35, -0.1577, 0.009477 + 41000.0, 0.78, 0.4, -0.154, 0.009404 + 41000.0, 0.78, 0.45, -0.1503, 0.009329 + 41000.0, 0.78, 0.5, -0.1466, 0.009251 + 41000.0, 0.78, 0.55, -0.1429, 0.00917 + 41000.0, 0.78, 0.6, -0.1392, 0.009087 + 41000.0, 0.78, 0.65, -0.1356, 0.009001 + 41000.0, 0.78, 0.7, -0.1319, 0.008914 + 41000.0, 0.78, 0.75, -0.1282, 0.008824 + 41000.0, 0.78, 0.8, -0.1246, 0.008731 + 41000.0, 0.78, 0.85, -0.1209, 0.008637 + 41000.0, 0.78, 0.9, -0.1173, 0.008542 + 41000.0, 0.78, 0.95, -0.1137, 0.008444 + 41000.0, 0.78, 1.0, -0.11, 0.008346 + 41000.0, 0.78, 1.05, -0.1064, 0.008245 + 41000.0, 0.78, 1.1, -0.1028, 0.008144 + 41000.0, 0.78, 1.15, -0.0992, 0.008041 + 41000.0, 0.78, 1.2, -0.0956, 0.007937 + 41000.0, 0.78, 1.25, -0.092, 0.007833 + 41000.0, 0.78, 1.3, -0.0884, 0.007728 + 41000.0, 0.78, 1.35, -0.08481, 0.007622 + 41000.0, 0.78, 1.4, -0.08122, 0.007515 + 41000.0, 0.78, 1.45, -0.07764, 0.007409 + 41000.0, 0.78, 1.5, -0.07406, 0.007301 + 41000.0, 0.78, 1.55, -0.07049, 0.007194 + 41000.0, 0.78, 1.6, -0.06691, 0.007087 + 41000.0, 0.78, 1.65, -0.06334, 0.00698 + 41000.0, 0.78, 1.7, -0.05978, 0.006874 + 41000.0, 0.78, 1.75, -0.05621, 0.006767 + 41000.0, 0.78, 1.8, -0.05265, 0.006662 + 41000.0, 0.78, 1.85, -0.04909, 0.006556 + 41000.0, 0.78, 1.9, -0.04554, 0.006452 + 41000.0, 0.78, 1.95, -0.04198, 0.006349 + 41000.0, 0.78, 2.0, -0.03843, 0.006246 + 41000.0, 0.78, 2.05, -0.03488, 0.006145 + 41000.0, 0.78, 2.1, -0.03133, 0.006045 + 41000.0, 0.78, 2.15, -0.02778, 0.005946 + 41000.0, 0.78, 2.2, -0.02423, 0.005849 + 41000.0, 0.78, 2.25, -0.02069, 0.005754 + 41000.0, 0.78, 2.3, -0.01714, 0.00566 + 41000.0, 0.78, 2.35, -0.01359, 0.005569 + 41000.0, 0.78, 2.4, -0.01005, 0.005479 + 41000.0, 0.78, 2.45, -0.006503, 0.005392 + 41000.0, 0.78, 2.5, -0.002957, 0.005307 + 41000.0, 0.78, 2.55, 0.0005893, 0.005224 + 41000.0, 0.78, 2.6, 0.004136, 0.005144 + 41000.0, 0.78, 2.65, 0.007683, 0.005067 + 41000.0, 0.78, 2.7, 0.01123, 0.004992 + 41000.0, 0.78, 2.75, 0.01478, 0.00492 + 41000.0, 0.78, 2.8, 0.01833, 0.004852 + 41000.0, 0.78, 2.85, 0.02188, 0.004786 + 41000.0, 0.78, 2.9, 0.02544, 0.004724 + 41000.0, 0.78, 2.95, 0.029, 0.004666 + 41000.0, 0.78, 3.0, 0.03255, 0.00461 + 41000.0, 0.78, 3.05, 0.03611, 0.004559 + 41000.0, 0.78, 3.1, 0.03968, 0.004512 + 41000.0, 0.78, 3.15, 0.04324, 0.004468 + 41000.0, 0.78, 3.2, 0.04681, 0.004429 + 41000.0, 0.78, 3.25, 0.05038, 0.004393 + 41000.0, 0.78, 3.3, 0.05396, 0.004362 + 41000.0, 0.78, 3.35, 0.05754, 0.004336 + 41000.0, 0.78, 3.4, 0.06112, 0.004314 + 41000.0, 0.78, 3.45, 0.06471, 0.004297 + 41000.0, 0.78, 3.5, 0.0683, 0.004284 + 41000.0, 0.78, 3.55, 0.07189, 0.004277 + 41000.0, 0.78, 3.6, 0.07549, 0.004275 + 41000.0, 0.78, 3.65, 0.07909, 0.004278 + 41000.0, 0.78, 3.7, 0.0827, 0.004286 + 41000.0, 0.78, 3.75, 0.08632, 0.0043 + 41000.0, 0.78, 3.8, 0.08994, 0.004319 + 41000.0, 0.78, 3.85, 0.09356, 0.004345 + 41000.0, 0.78, 3.9, 0.09719, 0.004376 + 41000.0, 0.78, 3.95, 0.1008, 0.004413 + 41000.0, 0.78, 4.0, 0.1045, 0.004456 + 41000.0, 0.78, 4.05, 0.1082, 0.004515 + 41000.0, 0.78, 4.1, 0.1119, 0.004581 + 41000.0, 0.78, 4.15, 0.1156, 0.004652 + 41000.0, 0.78, 4.2, 0.1193, 0.004729 + 41000.0, 0.78, 4.25, 0.123, 0.004812 + 41000.0, 0.78, 4.3, 0.1267, 0.004901 + 41000.0, 0.78, 4.35, 0.1304, 0.004996 + 41000.0, 0.78, 4.4, 0.1341, 0.005097 + 41000.0, 0.78, 4.45, 0.1379, 0.005204 + 41000.0, 0.78, 4.5, 0.1416, 0.005317 + 41000.0, 0.78, 4.55, 0.1453, 0.005437 + 41000.0, 0.78, 4.6, 0.149, 0.005563 + 41000.0, 0.78, 4.65, 0.1528, 0.005695 + 41000.0, 0.78, 4.7, 0.1565, 0.005833 + 41000.0, 0.78, 4.75, 0.1602, 0.005978 + 41000.0, 0.78, 4.8, 0.1639, 0.006129 + 41000.0, 0.78, 4.85, 0.1677, 0.006287 + 41000.0, 0.78, 4.9, 0.1714, 0.006451 + 41000.0, 0.78, 4.95, 0.1751, 0.006622 + 41000.0, 0.78, 5.0, 0.1789, 0.0068 + 41000.0, 0.78, 5.05, 0.1828, 0.007 + 41000.0, 0.78, 5.1, 0.1867, 0.007207 + 41000.0, 0.78, 5.15, 0.1906, 0.00742 + 41000.0, 0.78, 5.2, 0.1945, 0.00764 + 41000.0, 0.78, 5.25, 0.1983, 0.007865 + 41000.0, 0.78, 5.3, 0.2022, 0.008096 + 41000.0, 0.78, 5.35, 0.2061, 0.008333 + 41000.0, 0.78, 5.4, 0.2099, 0.008574 + 41000.0, 0.78, 5.45, 0.2137, 0.008821 + 41000.0, 0.78, 5.5, 0.2175, 0.009073 + 41000.0, 0.78, 5.55, 0.2212, 0.00933 + 41000.0, 0.78, 5.6, 0.2249, 0.009591 + 41000.0, 0.78, 5.65, 0.2286, 0.009857 + 41000.0, 0.78, 5.7, 0.2323, 0.01013 + 41000.0, 0.78, 5.75, 0.2359, 0.0104 + 41000.0, 0.78, 5.8, 0.2395, 0.01068 + 41000.0, 0.78, 5.85, 0.243, 0.01096 + 41000.0, 0.78, 5.9, 0.2465, 0.01124 + 41000.0, 0.78, 5.95, 0.2499, 0.01153 + 41000.0, 0.78, 6.0, 0.2533, 0.01182 + 41000.0, 0.78, 6.05, 0.2559, 0.01209 + 41000.0, 0.78, 6.1, 0.2585, 0.01236 + 41000.0, 0.78, 6.15, 0.261, 0.01262 + 41000.0, 0.78, 6.2, 0.2634, 0.0129 + 41000.0, 0.78, 6.25, 0.2657, 0.01317 + 41000.0, 0.78, 6.3, 0.2679, 0.01344 + 41000.0, 0.78, 6.35, 0.2701, 0.01371 + 41000.0, 0.78, 6.4, 0.2722, 0.01399 + 41000.0, 0.78, 6.45, 0.2742, 0.01427 + 41000.0, 0.78, 6.5, 0.2761, 0.01455 + 41000.0, 0.78, 6.55, 0.278, 0.01483 + 41000.0, 0.78, 6.6, 0.2798, 0.01511 + 41000.0, 0.78, 6.65, 0.2816, 0.0154 + 41000.0, 0.78, 6.7, 0.2833, 0.01568 + 41000.0, 0.78, 6.75, 0.2849, 0.01597 + 41000.0, 0.78, 6.8, 0.2865, 0.01626 + 41000.0, 0.78, 6.85, 0.288, 0.01655 + 41000.0, 0.78, 6.9, 0.2895, 0.01684 + 41000.0, 0.78, 6.95, 0.2909, 0.01714 + 41000.0, 0.78, 7.0, 0.2923, 0.01743 + 41000.0, 0.78, 7.05, 0.2937, 0.01773 + 41000.0, 0.78, 7.1, 0.2949, 0.01803 + 41000.0, 0.78, 7.15, 0.2962, 0.01833 + 41000.0, 0.78, 7.2, 0.2974, 0.01863 + 41000.0, 0.78, 7.25, 0.2986, 0.01894 + 41000.0, 0.78, 7.3, 0.2997, 0.01924 + 41000.0, 0.78, 7.35, 0.3009, 0.01955 + 41000.0, 0.78, 7.4, 0.3019, 0.01986 + 41000.0, 0.78, 7.45, 0.303, 0.02017 + 41000.0, 0.78, 7.5, 0.304, 0.02049 + 41000.0, 0.78, 7.55, 0.305, 0.0208 + 41000.0, 0.78, 7.6, 0.306, 0.02112 + 41000.0, 0.78, 7.65, 0.307, 0.02144 + 41000.0, 0.78, 7.7, 0.308, 0.02176 + 41000.0, 0.78, 7.75, 0.3089, 0.02209 + 41000.0, 0.78, 7.8, 0.3098, 0.02241 + 41000.0, 0.78, 7.85, 0.3108, 0.02274 + 41000.0, 0.78, 7.9, 0.3117, 0.02307 + 41000.0, 0.78, 7.95, 0.3126, 0.0234 + 41000.0, 0.78, 8.0, 0.3135, 0.02373 + 41000.0, 0.78, 8.05, 0.315, 0.02408 + 41000.0, 0.78, 8.1, 0.3165, 0.02442 + 41000.0, 0.78, 8.15, 0.3179, 0.02477 + 41000.0, 0.78, 8.2, 0.3194, 0.02512 + 41000.0, 0.78, 8.25, 0.3209, 0.02547 + 41000.0, 0.78, 8.3, 0.3224, 0.02583 + 41000.0, 0.78, 8.35, 0.3239, 0.02618 + 41000.0, 0.78, 8.4, 0.3253, 0.02654 + 41000.0, 0.78, 8.45, 0.3268, 0.0269 + 41000.0, 0.78, 8.5, 0.3283, 0.02726 + 41000.0, 0.78, 8.55, 0.3298, 0.02763 + 41000.0, 0.78, 8.6, 0.3313, 0.02799 + 41000.0, 0.78, 8.65, 0.3327, 0.02836 + 41000.0, 0.78, 8.7, 0.3342, 0.02873 + 41000.0, 0.78, 8.75, 0.3357, 0.0291 + 41000.0, 0.78, 8.8, 0.3372, 0.02947 + 41000.0, 0.78, 8.85, 0.3386, 0.02984 + 41000.0, 0.78, 8.9, 0.3401, 0.03022 + 41000.0, 0.78, 8.95, 0.3416, 0.0306 + 41000.0, 0.78, 9.0, 0.3431, 0.03097 + 41000.0, 0.78, 9.05, 0.3445, 0.03135 + 41000.0, 0.78, 9.1, 0.346, 0.03174 + 41000.0, 0.78, 9.15, 0.3475, 0.03212 + 41000.0, 0.78, 9.2, 0.3489, 0.0325 + 41000.0, 0.78, 9.25, 0.3504, 0.03289 + 41000.0, 0.78, 9.3, 0.3519, 0.03328 + 41000.0, 0.78, 9.35, 0.3534, 0.03367 + 41000.0, 0.78, 9.4, 0.3548, 0.03406 + 41000.0, 0.78, 9.45, 0.3563, 0.03445 + 41000.0, 0.78, 9.5, 0.3578, 0.03484 + 41000.0, 0.78, 9.55, 0.3592, 0.03524 + 41000.0, 0.78, 9.6, 0.3607, 0.03563 + 41000.0, 0.78, 9.65, 0.3622, 0.03603 + 41000.0, 0.78, 9.7, 0.3636, 0.03643 + 41000.0, 0.78, 9.75, 0.3651, 0.03683 + 41000.0, 0.78, 9.8, 0.3666, 0.03723 + 41000.0, 0.78, 9.85, 0.368, 0.03763 + 41000.0, 0.78, 9.9, 0.3695, 0.03804 + 41000.0, 0.78, 9.95, 0.371, 0.03844 + 41000.0, 0.78, 10.0, 0.3725, 0.03885 + 41000.0, 0.78, 10.05, 0.3739, 0.03926 + 41000.0, 0.78, 10.1, 0.3754, 0.03968 + 41000.0, 0.78, 10.15, 0.3769, 0.04011 + 41000.0, 0.78, 10.2, 0.3783, 0.04053 + 41000.0, 0.78, 10.25, 0.3798, 0.04095 + 41000.0, 0.78, 10.3, 0.3813, 0.04137 + 41000.0, 0.78, 10.35, 0.3827, 0.0418 + 41000.0, 0.78, 10.4, 0.3842, 0.04222 + 41000.0, 0.78, 10.45, 0.3857, 0.04265 + 41000.0, 0.78, 10.5, 0.3872, 0.04307 + 41000.0, 0.78, 10.55, 0.3886, 0.0435 + 41000.0, 0.78, 10.6, 0.3901, 0.04393 + 41000.0, 0.78, 10.65, 0.3916, 0.04436 + 41000.0, 0.78, 10.7, 0.393, 0.04478 + 41000.0, 0.78, 10.75, 0.3945, 0.04521 + 41000.0, 0.78, 10.8, 0.396, 0.04564 + 41000.0, 0.78, 10.85, 0.3974, 0.04607 + 41000.0, 0.78, 10.9, 0.3989, 0.0465 + 41000.0, 0.78, 10.95, 0.4004, 0.04692 + 41000.0, 0.78, 11.0, 0.4019, 0.04735 + 41000.0, 0.78, 11.05, 0.4033, 0.04778 + 41000.0, 0.78, 11.1, 0.4048, 0.04821 + 41000.0, 0.78, 11.15, 0.4063, 0.04863 + 41000.0, 0.78, 11.2, 0.4077, 0.04906 + 41000.0, 0.78, 11.25, 0.4092, 0.04949 + 41000.0, 0.78, 11.3, 0.4107, 0.04991 + 41000.0, 0.78, 11.35, 0.4121, 0.05034 + 41000.0, 0.78, 11.4, 0.4136, 0.05076 + 41000.0, 0.78, 11.45, 0.4151, 0.05119 + 41000.0, 0.78, 11.5, 0.4166, 0.05161 + 41000.0, 0.78, 11.55, 0.418, 0.05203 + 41000.0, 0.78, 11.6, 0.4195, 0.05245 + 41000.0, 0.78, 11.65, 0.421, 0.05288 + 41000.0, 0.78, 11.7, 0.4224, 0.05329 + 41000.0, 0.78, 11.75, 0.4239, 0.05371 + 41000.0, 0.78, 11.8, 0.4254, 0.05413 + 41000.0, 0.78, 11.85, 0.4269, 0.05455 + 41000.0, 0.78, 11.9, 0.4283, 0.05496 + 41000.0, 0.78, 11.95, 0.4298, 0.05538 + 41000.0, 0.78, 12.0, 0.4313, 0.05579 + 41000.0, 0.78, 12.05, 0.4327, 0.0562 + 41000.0, 0.78, 12.1, 0.4342, 0.05661 + 41000.0, 0.78, 12.15, 0.4357, 0.05701 + 41000.0, 0.78, 12.2, 0.4372, 0.05742 + 41000.0, 0.78, 12.25, 0.4386, 0.05782 + 41000.0, 0.78, 12.3, 0.4401, 0.05823 + 41000.0, 0.78, 12.35, 0.4416, 0.05863 + 41000.0, 0.78, 12.4, 0.443, 0.05902 + 41000.0, 0.78, 12.45, 0.4445, 0.05942 + 41000.0, 0.78, 12.5, 0.446, 0.05981 + 41000.0, 0.78, 12.55, 0.4475, 0.06021 + 41000.0, 0.78, 12.6, 0.4489, 0.0606 + 41000.0, 0.78, 12.65, 0.4504, 0.06098 + 41000.0, 0.78, 12.7, 0.4519, 0.06137 + 41000.0, 0.78, 12.75, 0.4533, 0.06175 + 41000.0, 0.78, 12.8, 0.4548, 0.06213 + 41000.0, 0.78, 12.85, 0.4563, 0.06251 + 41000.0, 0.78, 12.9, 0.4578, 0.06289 + 41000.0, 0.78, 12.95, 0.4592, 0.06326 + 41000.0, 0.78, 13.0, 0.4607, 0.06363 + 41000.0, 0.78, 13.05, 0.4622, 0.06399 + 41000.0, 0.78, 13.1, 0.4637, 0.06436 + 41000.0, 0.78, 13.15, 0.4651, 0.06472 + 41000.0, 0.78, 13.2, 0.4666, 0.06508 + 41000.0, 0.78, 13.25, 0.4681, 0.06543 + 41000.0, 0.78, 13.3, 0.4696, 0.06579 + 41000.0, 0.78, 13.35, 0.471, 0.06613 + 41000.0, 0.78, 13.4, 0.4725, 0.06648 + 41000.0, 0.78, 13.45, 0.474, 0.06682 + 41000.0, 0.78, 13.5, 0.4755, 0.06716 + 41000.0, 0.78, 13.55, 0.4769, 0.0675 + 41000.0, 0.78, 13.6, 0.4784, 0.06783 + 41000.0, 0.78, 13.65, 0.4799, 0.06816 + 41000.0, 0.78, 13.7, 0.4814, 0.06848 + 41000.0, 0.78, 13.75, 0.4828, 0.0688 + 41000.0, 0.78, 13.8, 0.4843, 0.06912 + 41000.0, 0.78, 13.85, 0.4858, 0.06943 + 41000.0, 0.78, 13.9, 0.4873, 0.06974 + 41000.0, 0.78, 13.95, 0.4888, 0.07005 + 41000.0, 0.78, 14.0, 0.4902, 0.07035 + 41000.0, 0.78, 14.05, 0.4917, 0.07064 + 41000.0, 0.78, 14.1, 0.4932, 0.07094 + 41000.0, 0.78, 14.15, 0.4947, 0.07123 + 41000.0, 0.78, 14.2, 0.4961, 0.07151 + 41000.0, 0.78, 14.25, 0.4976, 0.07179 + 41000.0, 0.78, 14.3, 0.4991, 0.07207 + 41000.0, 0.78, 14.35, 0.5006, 0.07234 + 41000.0, 0.78, 14.4, 0.5021, 0.0726 + 41000.0, 0.78, 14.45, 0.5035, 0.07287 + 41000.0, 0.78, 14.5, 0.505, 0.07312 + 41000.0, 0.78, 14.55, 0.5065, 0.07338 + 41000.0, 0.78, 14.6, 0.508, 0.07362 + 41000.0, 0.78, 14.65, 0.5095, 0.07387 + 41000.0, 0.78, 14.7, 0.511, 0.0741 + 41000.0, 0.78, 14.75, 0.5124, 0.07434 + 41000.0, 0.78, 14.8, 0.5139, 0.07456 + 41000.0, 0.78, 14.85, 0.5154, 0.07479 + 41000.0, 0.78, 14.9, 0.5169, 0.075 + 41000.0, 0.78, 14.95, 0.5184, 0.07521 + 41000.0, 0.78, 15.0, 0.5199, 0.07542 + 41000.0, 0.78, 15.05, 0.5213, 0.07562 + 41000.0, 0.83, 0.0, -0.1999, 0.00292 + 41000.0, 0.83, 0.05, -0.1962, 0.002976 + 41000.0, 0.83, 0.1, -0.1925, 0.00303 + 41000.0, 0.83, 0.15, -0.1888, 0.003083 + 41000.0, 0.83, 0.2, -0.185, 0.003135 + 41000.0, 0.83, 0.25, -0.1812, 0.003186 + 41000.0, 0.83, 0.3, -0.1774, 0.003236 + 41000.0, 0.83, 0.35, -0.1736, 0.003285 + 41000.0, 0.83, 0.4, -0.1697, 0.003333 + 41000.0, 0.83, 0.45, -0.1658, 0.00338 + 41000.0, 0.83, 0.5, -0.1619, 0.003427 + 41000.0, 0.83, 0.55, -0.158, 0.003473 + 41000.0, 0.83, 0.6, -0.1541, 0.003518 + 41000.0, 0.83, 0.65, -0.1501, 0.003562 + 41000.0, 0.83, 0.7, -0.1461, 0.003606 + 41000.0, 0.83, 0.75, -0.1421, 0.00365 + 41000.0, 0.83, 0.8, -0.1381, 0.003693 + 41000.0, 0.83, 0.85, -0.134, 0.003735 + 41000.0, 0.83, 0.9, -0.13, 0.003777 + 41000.0, 0.83, 0.95, -0.1259, 0.003819 + 41000.0, 0.83, 1.0, -0.1218, 0.003861 + 41000.0, 0.83, 1.05, -0.1177, 0.003902 + 41000.0, 0.83, 1.1, -0.1136, 0.003943 + 41000.0, 0.83, 1.15, -0.1095, 0.003984 + 41000.0, 0.83, 1.2, -0.1053, 0.004025 + 41000.0, 0.83, 1.25, -0.1012, 0.004066 + 41000.0, 0.83, 1.3, -0.09699, 0.004106 + 41000.0, 0.83, 1.35, -0.09281, 0.004147 + 41000.0, 0.83, 1.4, -0.08862, 0.004188 + 41000.0, 0.83, 1.45, -0.08443, 0.004229 + 41000.0, 0.83, 1.5, -0.08022, 0.004271 + 41000.0, 0.83, 1.55, -0.07601, 0.004312 + 41000.0, 0.83, 1.6, -0.07179, 0.004354 + 41000.0, 0.83, 1.65, -0.06757, 0.004396 + 41000.0, 0.83, 1.7, -0.06334, 0.004439 + 41000.0, 0.83, 1.75, -0.05911, 0.004482 + 41000.0, 0.83, 1.8, -0.05487, 0.004526 + 41000.0, 0.83, 1.85, -0.05063, 0.00457 + 41000.0, 0.83, 1.9, -0.04639, 0.004615 + 41000.0, 0.83, 1.95, -0.04214, 0.00466 + 41000.0, 0.83, 2.0, -0.0379, 0.004706 + 41000.0, 0.83, 2.05, -0.03365, 0.004753 + 41000.0, 0.83, 2.1, -0.02941, 0.004801 + 41000.0, 0.83, 2.15, -0.02516, 0.004849 + 41000.0, 0.83, 2.2, -0.02092, 0.004899 + 41000.0, 0.83, 2.25, -0.01668, 0.004949 + 41000.0, 0.83, 2.3, -0.01244, 0.005 + 41000.0, 0.83, 2.35, -0.008212, 0.005053 + 41000.0, 0.83, 2.4, -0.003985, 0.005106 + 41000.0, 0.83, 2.45, 0.0002371, 0.005161 + 41000.0, 0.83, 2.5, 0.004453, 0.005216 + 41000.0, 0.83, 2.55, 0.008662, 0.005273 + 41000.0, 0.83, 2.6, 0.01286, 0.005332 + 41000.0, 0.83, 2.65, 0.01706, 0.005391 + 41000.0, 0.83, 2.7, 0.02124, 0.005452 + 41000.0, 0.83, 2.75, 0.02541, 0.005515 + 41000.0, 0.83, 2.8, 0.02958, 0.005578 + 41000.0, 0.83, 2.85, 0.03373, 0.005644 + 41000.0, 0.83, 2.9, 0.03787, 0.005711 + 41000.0, 0.83, 2.95, 0.042, 0.00578 + 41000.0, 0.83, 3.0, 0.04611, 0.00585 + 41000.0, 0.83, 3.05, 0.05021, 0.005922 + 41000.0, 0.83, 3.1, 0.0543, 0.005996 + 41000.0, 0.83, 3.15, 0.05836, 0.006071 + 41000.0, 0.83, 3.2, 0.06242, 0.006149 + 41000.0, 0.83, 3.25, 0.06645, 0.006228 + 41000.0, 0.83, 3.3, 0.07047, 0.00631 + 41000.0, 0.83, 3.35, 0.07447, 0.006393 + 41000.0, 0.83, 3.4, 0.07845, 0.006479 + 41000.0, 0.83, 3.45, 0.08242, 0.006566 + 41000.0, 0.83, 3.5, 0.08636, 0.006656 + 41000.0, 0.83, 3.55, 0.09028, 0.006748 + 41000.0, 0.83, 3.6, 0.09417, 0.006843 + 41000.0, 0.83, 3.65, 0.09805, 0.006939 + 41000.0, 0.83, 3.7, 0.1019, 0.007038 + 41000.0, 0.83, 3.75, 0.1057, 0.00714 + 41000.0, 0.83, 3.8, 0.1095, 0.007243 + 41000.0, 0.83, 3.85, 0.1133, 0.00735 + 41000.0, 0.83, 3.9, 0.1171, 0.007459 + 41000.0, 0.83, 3.95, 0.1208, 0.00757 + 41000.0, 0.83, 4.0, 0.1245, 0.007684 + 41000.0, 0.83, 4.05, 0.128, 0.007809 + 41000.0, 0.83, 4.1, 0.1314, 0.007935 + 41000.0, 0.83, 4.15, 0.1349, 0.008064 + 41000.0, 0.83, 4.2, 0.1383, 0.008195 + 41000.0, 0.83, 4.25, 0.1417, 0.008328 + 41000.0, 0.83, 4.3, 0.1451, 0.008464 + 41000.0, 0.83, 4.35, 0.1485, 0.008602 + 41000.0, 0.83, 4.4, 0.1519, 0.008742 + 41000.0, 0.83, 4.45, 0.1552, 0.008885 + 41000.0, 0.83, 4.5, 0.1586, 0.009029 + 41000.0, 0.83, 4.55, 0.1619, 0.009177 + 41000.0, 0.83, 4.6, 0.1652, 0.009326 + 41000.0, 0.83, 4.65, 0.1685, 0.009478 + 41000.0, 0.83, 4.7, 0.1718, 0.009632 + 41000.0, 0.83, 4.75, 0.1751, 0.009788 + 41000.0, 0.83, 4.8, 0.1784, 0.009946 + 41000.0, 0.83, 4.85, 0.1817, 0.01011 + 41000.0, 0.83, 4.9, 0.1849, 0.01027 + 41000.0, 0.83, 4.95, 0.1882, 0.01044 + 41000.0, 0.83, 5.0, 0.1915, 0.0106 + 41000.0, 0.83, 5.05, 0.1948, 0.01078 + 41000.0, 0.83, 5.1, 0.1981, 0.01096 + 41000.0, 0.83, 5.15, 0.2015, 0.01114 + 41000.0, 0.83, 5.2, 0.2048, 0.01132 + 41000.0, 0.83, 5.25, 0.2081, 0.01151 + 41000.0, 0.83, 5.3, 0.2114, 0.0117 + 41000.0, 0.83, 5.35, 0.2147, 0.01188 + 41000.0, 0.83, 5.4, 0.218, 0.01207 + 41000.0, 0.83, 5.45, 0.2213, 0.01226 + 41000.0, 0.83, 5.5, 0.2246, 0.01246 + 41000.0, 0.83, 5.55, 0.2278, 0.01265 + 41000.0, 0.83, 5.6, 0.2311, 0.01284 + 41000.0, 0.83, 5.65, 0.2343, 0.01304 + 41000.0, 0.83, 5.7, 0.2375, 0.01323 + 41000.0, 0.83, 5.75, 0.2407, 0.01343 + 41000.0, 0.83, 5.8, 0.2438, 0.01362 + 41000.0, 0.83, 5.85, 0.247, 0.01382 + 41000.0, 0.83, 5.9, 0.2501, 0.01402 + 41000.0, 0.83, 5.95, 0.2532, 0.01421 + 41000.0, 0.83, 6.0, 0.2563, 0.01441 + 41000.0, 0.83, 6.05, 0.2591, 0.01458 + 41000.0, 0.83, 6.1, 0.2619, 0.01475 + 41000.0, 0.83, 6.15, 0.2647, 0.01493 + 41000.0, 0.83, 6.2, 0.2674, 0.0151 + 41000.0, 0.83, 6.25, 0.2701, 0.01526 + 41000.0, 0.83, 6.3, 0.2728, 0.01543 + 41000.0, 0.83, 6.35, 0.2754, 0.0156 + 41000.0, 0.83, 6.4, 0.278, 0.01576 + 41000.0, 0.83, 6.45, 0.2806, 0.01593 + 41000.0, 0.83, 6.5, 0.2831, 0.01609 + 41000.0, 0.83, 6.55, 0.2856, 0.01625 + 41000.0, 0.83, 6.6, 0.2881, 0.01642 + 41000.0, 0.83, 6.65, 0.2906, 0.01658 + 41000.0, 0.83, 6.7, 0.2931, 0.01674 + 41000.0, 0.83, 6.75, 0.2955, 0.0169 + 41000.0, 0.83, 6.8, 0.2979, 0.01705 + 41000.0, 0.83, 6.85, 0.3003, 0.01721 + 41000.0, 0.83, 6.9, 0.3027, 0.01737 + 41000.0, 0.83, 6.95, 0.305, 0.01753 + 41000.0, 0.83, 7.0, 0.3074, 0.01768 + 41000.0, 0.83, 7.05, 0.3097, 0.01784 + 41000.0, 0.83, 7.1, 0.312, 0.01799 + 41000.0, 0.83, 7.15, 0.3143, 0.01815 + 41000.0, 0.83, 7.2, 0.3166, 0.0183 + 41000.0, 0.83, 7.25, 0.3188, 0.01845 + 41000.0, 0.83, 7.3, 0.3211, 0.01861 + 41000.0, 0.83, 7.35, 0.3233, 0.01876 + 41000.0, 0.83, 7.4, 0.3255, 0.01891 + 41000.0, 0.83, 7.45, 0.3278, 0.01907 + 41000.0, 0.83, 7.5, 0.33, 0.01922 + 41000.0, 0.83, 7.55, 0.3322, 0.01937 + 41000.0, 0.83, 7.6, 0.3344, 0.01952 + 41000.0, 0.83, 7.65, 0.3366, 0.01967 + 41000.0, 0.83, 7.7, 0.3387, 0.01983 + 41000.0, 0.83, 7.75, 0.3409, 0.01998 + 41000.0, 0.83, 7.8, 0.3431, 0.02013 + 41000.0, 0.83, 7.85, 0.3453, 0.02028 + 41000.0, 0.83, 7.9, 0.3475, 0.02044 + 41000.0, 0.83, 7.95, 0.3496, 0.02059 + 41000.0, 0.83, 8.0, 0.3518, 0.02074 + 41000.0, 0.83, 8.05, 0.3542, 0.02091 + 41000.0, 0.83, 8.1, 0.3567, 0.02107 + 41000.0, 0.83, 8.15, 0.3591, 0.02124 + 41000.0, 0.83, 8.2, 0.3615, 0.02141 + 41000.0, 0.83, 8.25, 0.3639, 0.02157 + 41000.0, 0.83, 8.3, 0.3664, 0.02174 + 41000.0, 0.83, 8.35, 0.3688, 0.02191 + 41000.0, 0.83, 8.4, 0.3712, 0.02208 + 41000.0, 0.83, 8.45, 0.3737, 0.02225 + 41000.0, 0.83, 8.5, 0.3761, 0.02241 + 41000.0, 0.83, 8.55, 0.3785, 0.02258 + 41000.0, 0.83, 8.6, 0.381, 0.02275 + 41000.0, 0.83, 8.65, 0.3834, 0.02292 + 41000.0, 0.83, 8.7, 0.3858, 0.02309 + 41000.0, 0.83, 8.75, 0.3883, 0.02326 + 41000.0, 0.83, 8.8, 0.3907, 0.02343 + 41000.0, 0.83, 8.85, 0.3932, 0.0236 + 41000.0, 0.83, 8.9, 0.3956, 0.02376 + 41000.0, 0.83, 8.95, 0.398, 0.02393 + 41000.0, 0.83, 9.0, 0.4005, 0.0241 + 41000.0, 0.83, 9.05, 0.4029, 0.02427 + 41000.0, 0.83, 9.1, 0.4054, 0.02444 + 41000.0, 0.83, 9.15, 0.4078, 0.02461 + 41000.0, 0.83, 9.2, 0.4103, 0.02478 + 41000.0, 0.83, 9.25, 0.4127, 0.02495 + 41000.0, 0.83, 9.3, 0.4152, 0.02512 + 41000.0, 0.83, 9.35, 0.4176, 0.02529 + 41000.0, 0.83, 9.4, 0.4201, 0.02546 + 41000.0, 0.83, 9.45, 0.4225, 0.02563 + 41000.0, 0.83, 9.5, 0.425, 0.0258 + 41000.0, 0.83, 9.55, 0.4274, 0.02597 + 41000.0, 0.83, 9.6, 0.4299, 0.02614 + 41000.0, 0.83, 9.65, 0.4323, 0.02631 + 41000.0, 0.83, 9.7, 0.4348, 0.02648 + 41000.0, 0.83, 9.75, 0.4372, 0.02665 + 41000.0, 0.83, 9.8, 0.4397, 0.02682 + 41000.0, 0.83, 9.85, 0.4421, 0.02699 + 41000.0, 0.83, 9.9, 0.4446, 0.02715 + 41000.0, 0.83, 9.95, 0.447, 0.02732 + 41000.0, 0.83, 10.0, 0.4495, 0.02749 + 41000.0, 0.83, 10.05, 0.4519, 0.02766 + 41000.0, 0.83, 10.1, 0.4544, 0.02782 + 41000.0, 0.83, 10.15, 0.4568, 0.02798 + 41000.0, 0.83, 10.2, 0.4593, 0.02815 + 41000.0, 0.83, 10.25, 0.4617, 0.02831 + 41000.0, 0.83, 10.3, 0.4642, 0.02847 + 41000.0, 0.83, 10.35, 0.4666, 0.02864 + 41000.0, 0.83, 10.4, 0.4691, 0.0288 + 41000.0, 0.83, 10.45, 0.4715, 0.02896 + 41000.0, 0.83, 10.5, 0.4739, 0.02913 + 41000.0, 0.83, 10.55, 0.4764, 0.02929 + 41000.0, 0.83, 10.6, 0.4788, 0.02945 + 41000.0, 0.83, 10.65, 0.4813, 0.02961 + 41000.0, 0.83, 10.7, 0.4837, 0.02978 + 41000.0, 0.83, 10.75, 0.4862, 0.02994 + 41000.0, 0.83, 10.8, 0.4886, 0.0301 + 41000.0, 0.83, 10.85, 0.4911, 0.03027 + 41000.0, 0.83, 10.9, 0.4935, 0.03043 + 41000.0, 0.83, 10.95, 0.496, 0.03059 + 41000.0, 0.83, 11.0, 0.4984, 0.03075 + 41000.0, 0.83, 11.05, 0.5009, 0.03092 + 41000.0, 0.83, 11.1, 0.5033, 0.03108 + 41000.0, 0.83, 11.15, 0.5058, 0.03124 + 41000.0, 0.83, 11.2, 0.5082, 0.03141 + 41000.0, 0.83, 11.25, 0.5107, 0.03157 + 41000.0, 0.83, 11.3, 0.5131, 0.03173 + 41000.0, 0.83, 11.35, 0.5156, 0.0319 + 41000.0, 0.83, 11.4, 0.518, 0.03206 + 41000.0, 0.83, 11.45, 0.5205, 0.03222 + 41000.0, 0.83, 11.5, 0.5229, 0.03239 + 41000.0, 0.83, 11.55, 0.5254, 0.03255 + 41000.0, 0.83, 11.6, 0.5278, 0.03272 + 41000.0, 0.83, 11.65, 0.5303, 0.03288 + 41000.0, 0.83, 11.7, 0.5327, 0.03304 + 41000.0, 0.83, 11.75, 0.5352, 0.03321 + 41000.0, 0.83, 11.8, 0.5376, 0.03337 + 41000.0, 0.83, 11.85, 0.54, 0.03354 + 41000.0, 0.83, 11.9, 0.5425, 0.0337 + 41000.0, 0.83, 11.95, 0.5449, 0.03387 + 41000.0, 0.83, 12.0, 0.5474, 0.03403 + 41000.0, 0.83, 12.05, 0.5498, 0.0342 + 41000.0, 0.83, 12.1, 0.5523, 0.03437 + 41000.0, 0.83, 12.15, 0.5547, 0.03453 + 41000.0, 0.83, 12.2, 0.5572, 0.0347 + 41000.0, 0.83, 12.25, 0.5596, 0.03487 + 41000.0, 0.83, 12.3, 0.5621, 0.03503 + 41000.0, 0.83, 12.35, 0.5645, 0.0352 + 41000.0, 0.83, 12.4, 0.567, 0.03537 + 41000.0, 0.83, 12.45, 0.5694, 0.03554 + 41000.0, 0.83, 12.5, 0.5719, 0.0357 + 41000.0, 0.83, 12.55, 0.5743, 0.03587 + 41000.0, 0.83, 12.6, 0.5767, 0.03604 + 41000.0, 0.83, 12.65, 0.5792, 0.03621 + 41000.0, 0.83, 12.7, 0.5816, 0.03638 + 41000.0, 0.83, 12.75, 0.5841, 0.03655 + 41000.0, 0.83, 12.8, 0.5865, 0.03672 + 41000.0, 0.83, 12.85, 0.589, 0.03689 + 41000.0, 0.83, 12.9, 0.5914, 0.03706 + 41000.0, 0.83, 12.95, 0.5938, 0.03723 + 41000.0, 0.83, 13.0, 0.5963, 0.0374 + 41000.0, 0.83, 13.05, 0.5987, 0.03758 + 41000.0, 0.83, 13.1, 0.6012, 0.03775 + 41000.0, 0.83, 13.15, 0.6036, 0.03792 + 41000.0, 0.83, 13.2, 0.6061, 0.03809 + 41000.0, 0.83, 13.25, 0.6085, 0.03827 + 41000.0, 0.83, 13.3, 0.6109, 0.03844 + 41000.0, 0.83, 13.35, 0.6134, 0.03862 + 41000.0, 0.83, 13.4, 0.6158, 0.03879 + 41000.0, 0.83, 13.45, 0.6183, 0.03897 + 41000.0, 0.83, 13.5, 0.6207, 0.03914 + 41000.0, 0.83, 13.55, 0.6231, 0.03932 + 41000.0, 0.83, 13.6, 0.6256, 0.0395 + 41000.0, 0.83, 13.65, 0.628, 0.03967 + 41000.0, 0.83, 13.7, 0.6305, 0.03985 + 41000.0, 0.83, 13.75, 0.6329, 0.04003 + 41000.0, 0.83, 13.8, 0.6353, 0.04021 + 41000.0, 0.83, 13.85, 0.6378, 0.04039 + 41000.0, 0.83, 13.9, 0.6402, 0.04057 + 41000.0, 0.83, 13.95, 0.6426, 0.04075 + 41000.0, 0.83, 14.0, 0.6451, 0.04093 + 41000.0, 0.83, 14.05, 0.6475, 0.04111 + 41000.0, 0.83, 14.1, 0.6499, 0.0413 + 41000.0, 0.83, 14.15, 0.6524, 0.04148 + 41000.0, 0.83, 14.2, 0.6548, 0.04166 + 41000.0, 0.83, 14.25, 0.6572, 0.04185 + 41000.0, 0.83, 14.3, 0.6597, 0.04203 + 41000.0, 0.83, 14.35, 0.6621, 0.04222 + 41000.0, 0.83, 14.4, 0.6645, 0.0424 + 41000.0, 0.83, 14.45, 0.667, 0.04259 + 41000.0, 0.83, 14.5, 0.6694, 0.04278 + 41000.0, 0.83, 14.55, 0.6718, 0.04297 + 41000.0, 0.83, 14.6, 0.6742, 0.04315 + 41000.0, 0.83, 14.65, 0.6767, 0.04334 + 41000.0, 0.83, 14.7, 0.6791, 0.04353 + 41000.0, 0.83, 14.75, 0.6815, 0.04373 + 41000.0, 0.83, 14.8, 0.684, 0.04392 + 41000.0, 0.83, 14.85, 0.6864, 0.04411 + 41000.0, 0.83, 14.9, 0.6888, 0.0443 + 41000.0, 0.83, 14.95, 0.6912, 0.0445 + 41000.0, 0.83, 15.0, 0.6937, 0.04469 + 41000.0, 0.83, 15.05, 0.6961, 0.04489 + 41000.0, 0.88, 0.0, -0.2123, 0.01117 + 41000.0, 0.88, 0.05, -0.2081, 0.01117 + 41000.0, 0.88, 0.1, -0.2038, 0.01117 + 41000.0, 0.88, 0.15, -0.1995, 0.01115 + 41000.0, 0.88, 0.2, -0.1951, 0.01114 + 41000.0, 0.88, 0.25, -0.1908, 0.01111 + 41000.0, 0.88, 0.3, -0.1864, 0.01108 + 41000.0, 0.88, 0.35, -0.182, 0.01104 + 41000.0, 0.88, 0.4, -0.1777, 0.011 + 41000.0, 0.88, 0.45, -0.1732, 0.01095 + 41000.0, 0.88, 0.5, -0.1688, 0.0109 + 41000.0, 0.88, 0.55, -0.1644, 0.01084 + 41000.0, 0.88, 0.6, -0.1599, 0.01077 + 41000.0, 0.88, 0.65, -0.1555, 0.01071 + 41000.0, 0.88, 0.7, -0.151, 0.01063 + 41000.0, 0.88, 0.75, -0.1465, 0.01056 + 41000.0, 0.88, 0.8, -0.142, 0.01048 + 41000.0, 0.88, 0.85, -0.1375, 0.0104 + 41000.0, 0.88, 0.9, -0.133, 0.01031 + 41000.0, 0.88, 0.95, -0.1284, 0.01023 + 41000.0, 0.88, 1.0, -0.1239, 0.01014 + 41000.0, 0.88, 1.05, -0.1193, 0.01005 + 41000.0, 0.88, 1.1, -0.1148, 0.009953 + 41000.0, 0.88, 1.15, -0.1102, 0.009858 + 41000.0, 0.88, 1.2, -0.1056, 0.009763 + 41000.0, 0.88, 1.25, -0.1011, 0.009666 + 41000.0, 0.88, 1.3, -0.09647, 0.009569 + 41000.0, 0.88, 1.35, -0.09188, 0.009472 + 41000.0, 0.88, 1.4, -0.08729, 0.009374 + 41000.0, 0.88, 1.45, -0.0827, 0.009277 + 41000.0, 0.88, 1.5, -0.0781, 0.009181 + 41000.0, 0.88, 1.55, -0.07349, 0.009085 + 41000.0, 0.88, 1.6, -0.06889, 0.00899 + 41000.0, 0.88, 1.65, -0.06428, 0.008897 + 41000.0, 0.88, 1.7, -0.05968, 0.008806 + 41000.0, 0.88, 1.75, -0.05507, 0.008716 + 41000.0, 0.88, 1.8, -0.05046, 0.008629 + 41000.0, 0.88, 1.85, -0.04586, 0.008544 + 41000.0, 0.88, 1.9, -0.04125, 0.008463 + 41000.0, 0.88, 1.95, -0.03665, 0.008384 + 41000.0, 0.88, 2.0, -0.03205, 0.008309 + 41000.0, 0.88, 2.05, -0.02745, 0.008237 + 41000.0, 0.88, 2.1, -0.02286, 0.00817 + 41000.0, 0.88, 2.15, -0.01827, 0.008106 + 41000.0, 0.88, 2.2, -0.01368, 0.008048 + 41000.0, 0.88, 2.25, -0.009103, 0.007994 + 41000.0, 0.88, 2.3, -0.004529, 0.007945 + 41000.0, 0.88, 2.35, 3.779e-05, 0.007901 + 41000.0, 0.88, 2.4, 0.004598, 0.007864 + 41000.0, 0.88, 2.45, 0.00915, 0.007832 + 41000.0, 0.88, 2.5, 0.01369, 0.007807 + 41000.0, 0.88, 2.55, 0.01823, 0.007788 + 41000.0, 0.88, 2.6, 0.02275, 0.007776 + 41000.0, 0.88, 2.65, 0.02727, 0.007771 + 41000.0, 0.88, 2.7, 0.03178, 0.007773 + 41000.0, 0.88, 2.75, 0.03627, 0.007783 + 41000.0, 0.88, 2.8, 0.04075, 0.007801 + 41000.0, 0.88, 2.85, 0.04522, 0.007827 + 41000.0, 0.88, 2.9, 0.04968, 0.007862 + 41000.0, 0.88, 2.95, 0.05412, 0.007906 + 41000.0, 0.88, 3.0, 0.05855, 0.007959 + 41000.0, 0.88, 3.05, 0.06297, 0.008021 + 41000.0, 0.88, 3.1, 0.06737, 0.008093 + 41000.0, 0.88, 3.15, 0.07175, 0.008175 + 41000.0, 0.88, 3.2, 0.07612, 0.008267 + 41000.0, 0.88, 3.25, 0.08047, 0.008369 + 41000.0, 0.88, 3.3, 0.08481, 0.008483 + 41000.0, 0.88, 3.35, 0.08912, 0.008607 + 41000.0, 0.88, 3.4, 0.09342, 0.008743 + 41000.0, 0.88, 3.45, 0.0977, 0.008891 + 41000.0, 0.88, 3.5, 0.102, 0.00905 + 41000.0, 0.88, 3.55, 0.1062, 0.009222 + 41000.0, 0.88, 3.6, 0.1104, 0.009406 + 41000.0, 0.88, 3.65, 0.1146, 0.009603 + 41000.0, 0.88, 3.7, 0.1188, 0.009813 + 41000.0, 0.88, 3.75, 0.1229, 0.01004 + 41000.0, 0.88, 3.8, 0.1271, 0.01027 + 41000.0, 0.88, 3.85, 0.1312, 0.01052 + 41000.0, 0.88, 3.9, 0.1352, 0.01079 + 41000.0, 0.88, 3.95, 0.1393, 0.01107 + 41000.0, 0.88, 4.0, 0.1433, 0.01136 + 41000.0, 0.88, 4.05, 0.1477, 0.01173 + 41000.0, 0.88, 4.1, 0.152, 0.0121 + 41000.0, 0.88, 4.15, 0.1563, 0.01248 + 41000.0, 0.88, 4.2, 0.1606, 0.01288 + 41000.0, 0.88, 4.25, 0.1647, 0.01329 + 41000.0, 0.88, 4.3, 0.1688, 0.01371 + 41000.0, 0.88, 4.35, 0.1729, 0.01415 + 41000.0, 0.88, 4.4, 0.1768, 0.01459 + 41000.0, 0.88, 4.45, 0.1807, 0.01505 + 41000.0, 0.88, 4.5, 0.1845, 0.01552 + 41000.0, 0.88, 4.55, 0.1883, 0.016 + 41000.0, 0.88, 4.6, 0.1919, 0.01649 + 41000.0, 0.88, 4.65, 0.1955, 0.01699 + 41000.0, 0.88, 4.7, 0.199, 0.0175 + 41000.0, 0.88, 4.75, 0.2023, 0.01802 + 41000.0, 0.88, 4.8, 0.2056, 0.01856 + 41000.0, 0.88, 4.85, 0.2088, 0.0191 + 41000.0, 0.88, 4.9, 0.2119, 0.01966 + 41000.0, 0.88, 4.95, 0.2148, 0.02023 + 41000.0, 0.88, 5.0, 0.2177, 0.0208 + 41000.0, 0.88, 5.05, 0.2197, 0.02137 + 41000.0, 0.88, 5.1, 0.2217, 0.02194 + 41000.0, 0.88, 5.15, 0.2236, 0.02253 + 41000.0, 0.88, 5.2, 0.2254, 0.02312 + 41000.0, 0.88, 5.25, 0.227, 0.02373 + 41000.0, 0.88, 5.3, 0.2286, 0.02435 + 41000.0, 0.88, 5.35, 0.2301, 0.02498 + 41000.0, 0.88, 5.4, 0.2316, 0.02562 + 41000.0, 0.88, 5.45, 0.2329, 0.02628 + 41000.0, 0.88, 5.5, 0.2343, 0.02695 + 41000.0, 0.88, 5.55, 0.2355, 0.02763 + 41000.0, 0.88, 5.6, 0.2367, 0.02832 + 41000.0, 0.88, 5.65, 0.2379, 0.02902 + 41000.0, 0.88, 5.7, 0.239, 0.02974 + 41000.0, 0.88, 5.75, 0.2401, 0.03048 + 41000.0, 0.88, 5.8, 0.2412, 0.03122 + 41000.0, 0.88, 5.85, 0.2423, 0.03198 + 41000.0, 0.88, 5.9, 0.2433, 0.03276 + 41000.0, 0.88, 5.95, 0.2444, 0.03355 + 41000.0, 0.88, 6.0, 0.2455, 0.03435 + 41000.0, 0.88, 6.05, 0.2476, 0.03526 + 41000.0, 0.88, 6.1, 0.2498, 0.0362 + 41000.0, 0.88, 6.15, 0.2521, 0.03715 + 41000.0, 0.88, 6.2, 0.2544, 0.03812 + 41000.0, 0.88, 6.25, 0.2568, 0.0391 + 41000.0, 0.88, 6.3, 0.2592, 0.04011 + 41000.0, 0.88, 6.35, 0.2617, 0.04113 + 41000.0, 0.88, 6.4, 0.2642, 0.04217 + 41000.0, 0.88, 6.45, 0.2668, 0.04322 + 41000.0, 0.88, 6.5, 0.2694, 0.04429 + 41000.0, 0.88, 6.55, 0.2721, 0.04537 + 41000.0, 0.88, 6.6, 0.2748, 0.04647 + 41000.0, 0.88, 6.65, 0.2775, 0.04758 + 41000.0, 0.88, 6.7, 0.2803, 0.04871 + 41000.0, 0.88, 6.75, 0.2832, 0.04985 + 41000.0, 0.88, 6.8, 0.286, 0.051 + 41000.0, 0.88, 6.85, 0.2889, 0.05217 + 41000.0, 0.88, 6.9, 0.2918, 0.05334 + 41000.0, 0.88, 6.95, 0.2948, 0.05453 + 41000.0, 0.88, 7.0, 0.2978, 0.05573 + 41000.0, 0.88, 7.05, 0.3008, 0.05694 + 41000.0, 0.88, 7.1, 0.3038, 0.05816 + 41000.0, 0.88, 7.15, 0.3069, 0.05939 + 41000.0, 0.88, 7.2, 0.31, 0.06062 + 41000.0, 0.88, 7.25, 0.3131, 0.06187 + 41000.0, 0.88, 7.3, 0.3162, 0.06313 + 41000.0, 0.88, 7.35, 0.3194, 0.06439 + 41000.0, 0.88, 7.4, 0.3225, 0.06566 + 41000.0, 0.88, 7.45, 0.3257, 0.06693 + 41000.0, 0.88, 7.5, 0.3289, 0.06822 + 41000.0, 0.88, 7.55, 0.332, 0.06951 + 41000.0, 0.88, 7.6, 0.3352, 0.0708 + 41000.0, 0.88, 7.65, 0.3384, 0.0721 + 41000.0, 0.88, 7.7, 0.3417, 0.0734 + 41000.0, 0.88, 7.75, 0.3449, 0.07471 + 41000.0, 0.88, 7.8, 0.3481, 0.07602 + 41000.0, 0.88, 7.85, 0.3513, 0.07734 + 41000.0, 0.88, 7.9, 0.3545, 0.07866 + 41000.0, 0.88, 7.95, 0.3577, 0.07998 + 41000.0, 0.88, 8.0, 0.3609, 0.0813 + 41000.0, 0.88, 8.05, 0.3636, 0.0825 + 41000.0, 0.88, 8.1, 0.3663, 0.0837 + 41000.0, 0.88, 8.15, 0.3689, 0.0849 + 41000.0, 0.88, 8.2, 0.3716, 0.0861 + 41000.0, 0.88, 8.25, 0.3743, 0.08731 + 41000.0, 0.88, 8.3, 0.3769, 0.08851 + 41000.0, 0.88, 8.35, 0.3796, 0.08972 + 41000.0, 0.88, 8.4, 0.3822, 0.09093 + 41000.0, 0.88, 8.45, 0.3848, 0.09214 + 41000.0, 0.88, 8.5, 0.3875, 0.09335 + 41000.0, 0.88, 8.55, 0.3901, 0.09456 + 41000.0, 0.88, 8.6, 0.3927, 0.09578 + 41000.0, 0.88, 8.65, 0.3953, 0.09699 + 41000.0, 0.88, 8.7, 0.3979, 0.09821 + 41000.0, 0.88, 8.75, 0.4005, 0.09943 + 41000.0, 0.88, 8.8, 0.4031, 0.1007 + 41000.0, 0.88, 8.85, 0.4057, 0.1019 + 41000.0, 0.88, 8.9, 0.4083, 0.1031 + 41000.0, 0.88, 8.95, 0.4109, 0.1043 + 41000.0, 0.88, 9.0, 0.4134, 0.1056 + 41000.0, 0.88, 9.05, 0.416, 0.1068 + 41000.0, 0.88, 9.1, 0.4186, 0.108 + 41000.0, 0.88, 9.15, 0.4211, 0.1092 + 41000.0, 0.88, 9.2, 0.4237, 0.1105 + 41000.0, 0.88, 9.25, 0.4262, 0.1117 + 41000.0, 0.88, 9.3, 0.4288, 0.1129 + 41000.0, 0.88, 9.35, 0.4313, 0.1142 + 41000.0, 0.88, 9.4, 0.4339, 0.1154 + 41000.0, 0.88, 9.45, 0.4364, 0.1167 + 41000.0, 0.88, 9.5, 0.439, 0.1179 + 41000.0, 0.88, 9.55, 0.4415, 0.1192 + 41000.0, 0.88, 9.6, 0.4441, 0.1204 + 41000.0, 0.88, 9.65, 0.4466, 0.1217 + 41000.0, 0.88, 9.7, 0.4491, 0.1229 + 41000.0, 0.88, 9.75, 0.4516, 0.1242 + 41000.0, 0.88, 9.8, 0.4542, 0.1254 + 41000.0, 0.88, 9.85, 0.4567, 0.1267 + 41000.0, 0.88, 9.9, 0.4592, 0.1279 + 41000.0, 0.88, 9.95, 0.4618, 0.1292 + 41000.0, 0.88, 10.0, 0.4643, 0.1305 + 41000.0, 0.88, 10.05, 0.4668, 0.1318 + 41000.0, 0.88, 10.1, 0.4694, 0.1331 + 41000.0, 0.88, 10.15, 0.4719, 0.1344 + 41000.0, 0.88, 10.2, 0.4745, 0.1357 + 41000.0, 0.88, 10.25, 0.477, 0.137 + 41000.0, 0.88, 10.3, 0.4796, 0.1383 + 41000.0, 0.88, 10.35, 0.4822, 0.1396 + 41000.0, 0.88, 10.4, 0.4847, 0.1409 + 41000.0, 0.88, 10.45, 0.4873, 0.1422 + 41000.0, 0.88, 10.5, 0.4898, 0.1435 + 41000.0, 0.88, 10.55, 0.4924, 0.1448 + 41000.0, 0.88, 10.6, 0.4949, 0.1462 + 41000.0, 0.88, 10.65, 0.4974, 0.1475 + 41000.0, 0.88, 10.7, 0.5, 0.1488 + 41000.0, 0.88, 10.75, 0.5025, 0.1501 + 41000.0, 0.88, 10.8, 0.5051, 0.1514 + 41000.0, 0.88, 10.85, 0.5076, 0.1527 + 41000.0, 0.88, 10.9, 0.5102, 0.154 + 41000.0, 0.88, 10.95, 0.5127, 0.1553 + 41000.0, 0.88, 11.0, 0.5153, 0.1567 + 41000.0, 0.88, 11.05, 0.5178, 0.158 + 41000.0, 0.88, 11.1, 0.5204, 0.1593 + 41000.0, 0.88, 11.15, 0.5229, 0.1606 + 41000.0, 0.88, 11.2, 0.5255, 0.1619 + 41000.0, 0.88, 11.25, 0.528, 0.1632 + 41000.0, 0.88, 11.3, 0.5306, 0.1645 + 41000.0, 0.88, 11.35, 0.5331, 0.1658 + 41000.0, 0.88, 11.4, 0.5357, 0.1671 + 41000.0, 0.88, 11.45, 0.5382, 0.1684 + 41000.0, 0.88, 11.5, 0.5408, 0.1697 + 41000.0, 0.88, 11.55, 0.5433, 0.171 + 41000.0, 0.88, 11.6, 0.5459, 0.1723 + 41000.0, 0.88, 11.65, 0.5484, 0.1736 + 41000.0, 0.88, 11.7, 0.551, 0.1749 + 41000.0, 0.88, 11.75, 0.5535, 0.1762 + 41000.0, 0.88, 11.8, 0.5561, 0.1775 + 41000.0, 0.88, 11.85, 0.5586, 0.1788 + 41000.0, 0.88, 11.9, 0.5612, 0.1801 + 41000.0, 0.88, 11.95, 0.5637, 0.1814 + 41000.0, 0.88, 12.0, 0.5663, 0.1826 + 41000.0, 0.88, 12.05, 0.5688, 0.1839 + 41000.0, 0.88, 12.1, 0.5714, 0.1852 + 41000.0, 0.88, 12.15, 0.574, 0.1865 + 41000.0, 0.88, 12.2, 0.5765, 0.1877 + 41000.0, 0.88, 12.25, 0.5791, 0.189 + 41000.0, 0.88, 12.3, 0.5816, 0.1903 + 41000.0, 0.88, 12.35, 0.5842, 0.1915 + 41000.0, 0.88, 12.4, 0.5868, 0.1928 + 41000.0, 0.88, 12.45, 0.5893, 0.194 + 41000.0, 0.88, 12.5, 0.5919, 0.1953 + 41000.0, 0.88, 12.55, 0.5945, 0.1965 + 41000.0, 0.88, 12.6, 0.597, 0.1977 + 41000.0, 0.88, 12.65, 0.5996, 0.199 + 41000.0, 0.88, 12.7, 0.6022, 0.2002 + 41000.0, 0.88, 12.75, 0.6047, 0.2014 + 41000.0, 0.88, 12.8, 0.6073, 0.2026 + 41000.0, 0.88, 12.85, 0.6099, 0.2038 + 41000.0, 0.88, 12.9, 0.6125, 0.2051 + 41000.0, 0.88, 12.95, 0.615, 0.2063 + 41000.0, 0.88, 13.0, 0.6176, 0.2074 + 41000.0, 0.88, 13.05, 0.6202, 0.2086 + 41000.0, 0.88, 13.1, 0.6228, 0.2098 + 41000.0, 0.88, 13.15, 0.6254, 0.211 + 41000.0, 0.88, 13.2, 0.6279, 0.2122 + 41000.0, 0.88, 13.25, 0.6305, 0.2133 + 41000.0, 0.88, 13.3, 0.6331, 0.2145 + 41000.0, 0.88, 13.35, 0.6357, 0.2157 + 41000.0, 0.88, 13.4, 0.6383, 0.2168 + 41000.0, 0.88, 13.45, 0.6409, 0.218 + 41000.0, 0.88, 13.5, 0.6435, 0.2191 + 41000.0, 0.88, 13.55, 0.6461, 0.2202 + 41000.0, 0.88, 13.6, 0.6487, 0.2214 + 41000.0, 0.88, 13.65, 0.6513, 0.2225 + 41000.0, 0.88, 13.7, 0.6539, 0.2236 + 41000.0, 0.88, 13.75, 0.6565, 0.2247 + 41000.0, 0.88, 13.8, 0.6591, 0.2258 + 41000.0, 0.88, 13.85, 0.6618, 0.2269 + 41000.0, 0.88, 13.9, 0.6644, 0.2279 + 41000.0, 0.88, 13.95, 0.667, 0.229 + 41000.0, 0.88, 14.0, 0.6696, 0.2301 + 41000.0, 0.88, 14.05, 0.6722, 0.2311 + 41000.0, 0.88, 14.1, 0.6749, 0.2322 + 41000.0, 0.88, 14.15, 0.6775, 0.2332 + 41000.0, 0.88, 14.2, 0.6801, 0.2343 + 41000.0, 0.88, 14.25, 0.6828, 0.2353 + 41000.0, 0.88, 14.3, 0.6854, 0.2363 + 41000.0, 0.88, 14.35, 0.688, 0.2373 + 41000.0, 0.88, 14.4, 0.6907, 0.2383 + 41000.0, 0.88, 14.45, 0.6933, 0.2393 + 41000.0, 0.88, 14.5, 0.696, 0.2403 + 41000.0, 0.88, 14.55, 0.6986, 0.2413 + 41000.0, 0.88, 14.6, 0.7013, 0.2422 + 41000.0, 0.88, 14.65, 0.7039, 0.2432 + 41000.0, 0.88, 14.7, 0.7066, 0.2441 + 41000.0, 0.88, 14.75, 0.7093, 0.2451 + 41000.0, 0.88, 14.8, 0.7119, 0.246 + 41000.0, 0.88, 14.85, 0.7146, 0.2469 + 41000.0, 0.88, 14.9, 0.7173, 0.2478 + 41000.0, 0.88, 14.95, 0.7199, 0.2487 + 41000.0, 0.88, 15.0, 0.7226, 0.2496 + 41000.0, 0.88, 15.05, 0.7253, 0.2505 + 41000.0, 0.93, 0.0, -0.2189, 0.05964 + 41000.0, 0.93, 0.05, -0.2122, 0.05915 + 41000.0, 0.93, 0.1, -0.2055, 0.05863 + 41000.0, 0.93, 0.15, -0.199, 0.05808 + 41000.0, 0.93, 0.2, -0.1926, 0.05749 + 41000.0, 0.93, 0.25, -0.1863, 0.05688 + 41000.0, 0.93, 0.3, -0.1802, 0.05623 + 41000.0, 0.93, 0.35, -0.1741, 0.05555 + 41000.0, 0.93, 0.4, -0.1682, 0.05484 + 41000.0, 0.93, 0.45, -0.1624, 0.05411 + 41000.0, 0.93, 0.5, -0.1566, 0.05335 + 41000.0, 0.93, 0.55, -0.151, 0.05257 + 41000.0, 0.93, 0.6, -0.1455, 0.05177 + 41000.0, 0.93, 0.65, -0.14, 0.05094 + 41000.0, 0.93, 0.7, -0.1347, 0.05009 + 41000.0, 0.93, 0.75, -0.1294, 0.04923 + 41000.0, 0.93, 0.8, -0.1243, 0.04834 + 41000.0, 0.93, 0.85, -0.1192, 0.04744 + 41000.0, 0.93, 0.9, -0.1142, 0.04653 + 41000.0, 0.93, 0.95, -0.1093, 0.0456 + 41000.0, 0.93, 1.0, -0.1044, 0.04466 + 41000.0, 0.93, 1.05, -0.09966, 0.04371 + 41000.0, 0.93, 1.1, -0.09496, 0.04274 + 41000.0, 0.93, 1.15, -0.09033, 0.04177 + 41000.0, 0.93, 1.2, -0.08576, 0.04079 + 41000.0, 0.93, 1.25, -0.08126, 0.03981 + 41000.0, 0.93, 1.3, -0.07682, 0.03882 + 41000.0, 0.93, 1.35, -0.07243, 0.03782 + 41000.0, 0.93, 1.4, -0.0681, 0.03683 + 41000.0, 0.93, 1.45, -0.06382, 0.03583 + 41000.0, 0.93, 1.5, -0.05959, 0.03483 + 41000.0, 0.93, 1.55, -0.05541, 0.03383 + 41000.0, 0.93, 1.6, -0.05127, 0.03284 + 41000.0, 0.93, 1.65, -0.04717, 0.03185 + 41000.0, 0.93, 1.7, -0.04311, 0.03087 + 41000.0, 0.93, 1.75, -0.03909, 0.02989 + 41000.0, 0.93, 1.8, -0.0351, 0.02892 + 41000.0, 0.93, 1.85, -0.03114, 0.02796 + 41000.0, 0.93, 1.9, -0.0272, 0.02701 + 41000.0, 0.93, 1.95, -0.02329, 0.02607 + 41000.0, 0.93, 2.0, -0.0194, 0.02514 + 41000.0, 0.93, 2.05, -0.01554, 0.02423 + 41000.0, 0.93, 2.1, -0.01168, 0.02333 + 41000.0, 0.93, 2.15, -0.007845, 0.02245 + 41000.0, 0.93, 2.2, -0.004017, 0.02159 + 41000.0, 0.93, 2.25, -0.0001983, 0.02075 + 41000.0, 0.93, 2.3, 0.003615, 0.01993 + 41000.0, 0.93, 2.35, 0.007426, 0.01912 + 41000.0, 0.93, 2.4, 0.01124, 0.01835 + 41000.0, 0.93, 2.45, 0.01505, 0.01759 + 41000.0, 0.93, 2.5, 0.01887, 0.01687 + 41000.0, 0.93, 2.55, 0.0227, 0.01617 + 41000.0, 0.93, 2.6, 0.02653, 0.01549 + 41000.0, 0.93, 2.65, 0.03038, 0.01485 + 41000.0, 0.93, 2.7, 0.03425, 0.01424 + 41000.0, 0.93, 2.75, 0.03814, 0.01366 + 41000.0, 0.93, 2.8, 0.04205, 0.01311 + 41000.0, 0.93, 2.85, 0.04598, 0.0126 + 41000.0, 0.93, 2.9, 0.04994, 0.01212 + 41000.0, 0.93, 2.95, 0.05393, 0.01168 + 41000.0, 0.93, 3.0, 0.05795, 0.01128 + 41000.0, 0.93, 3.05, 0.06201, 0.01092 + 41000.0, 0.93, 3.1, 0.0661, 0.0106 + 41000.0, 0.93, 3.15, 0.07024, 0.01032 + 41000.0, 0.93, 3.2, 0.07442, 0.01008 + 41000.0, 0.93, 3.25, 0.07865, 0.009894 + 41000.0, 0.93, 3.3, 0.08292, 0.00975 + 41000.0, 0.93, 3.35, 0.08725, 0.009652 + 41000.0, 0.93, 3.4, 0.09163, 0.009604 + 41000.0, 0.93, 3.45, 0.09607, 0.009605 + 41000.0, 0.93, 3.5, 0.1006, 0.009658 + 41000.0, 0.93, 3.55, 0.1051, 0.009762 + 41000.0, 0.93, 3.6, 0.1098, 0.009921 + 41000.0, 0.93, 3.65, 0.1144, 0.01013 + 41000.0, 0.93, 3.7, 0.1192, 0.0104 + 41000.0, 0.93, 3.75, 0.1241, 0.01073 + 41000.0, 0.93, 3.8, 0.129, 0.01112 + 41000.0, 0.93, 3.85, 0.134, 0.01156 + 41000.0, 0.93, 3.9, 0.139, 0.01207 + 41000.0, 0.93, 3.95, 0.1442, 0.01264 + 41000.0, 0.93, 4.0, 0.1494, 0.01327 + 41000.0, 0.93, 4.05, 0.1576, 0.01417 + 41000.0, 0.93, 4.1, 0.1658, 0.01513 + 41000.0, 0.93, 4.15, 0.1738, 0.01614 + 41000.0, 0.93, 4.2, 0.1817, 0.0172 + 41000.0, 0.93, 4.25, 0.1895, 0.01832 + 41000.0, 0.93, 4.3, 0.1971, 0.01949 + 41000.0, 0.93, 4.35, 0.2045, 0.02071 + 41000.0, 0.93, 4.4, 0.2118, 0.02199 + 41000.0, 0.93, 4.45, 0.2188, 0.02332 + 41000.0, 0.93, 4.5, 0.2256, 0.0247 + 41000.0, 0.93, 4.55, 0.2322, 0.02613 + 41000.0, 0.93, 4.6, 0.2385, 0.02762 + 41000.0, 0.93, 4.65, 0.2445, 0.02915 + 41000.0, 0.93, 4.7, 0.2502, 0.03074 + 41000.0, 0.93, 4.75, 0.2556, 0.03237 + 41000.0, 0.93, 4.8, 0.2606, 0.03406 + 41000.0, 0.93, 4.85, 0.2653, 0.0358 + 41000.0, 0.93, 4.9, 0.2696, 0.03759 + 41000.0, 0.93, 4.95, 0.2734, 0.03942 + 41000.0, 0.93, 5.0, 0.2769, 0.04131 + 41000.0, 0.93, 5.05, 0.2771, 0.04315 + 41000.0, 0.93, 5.1, 0.277, 0.04504 + 41000.0, 0.93, 5.15, 0.2764, 0.04697 + 41000.0, 0.93, 5.2, 0.2755, 0.04897 + 41000.0, 0.93, 5.25, 0.2742, 0.05101 + 41000.0, 0.93, 5.3, 0.2725, 0.05311 + 41000.0, 0.93, 5.35, 0.2706, 0.05527 + 41000.0, 0.93, 5.4, 0.2684, 0.05748 + 41000.0, 0.93, 5.45, 0.2659, 0.05975 + 41000.0, 0.93, 5.5, 0.2632, 0.06208 + 41000.0, 0.93, 5.55, 0.2602, 0.06447 + 41000.0, 0.93, 5.6, 0.257, 0.06693 + 41000.0, 0.93, 5.65, 0.2537, 0.06945 + 41000.0, 0.93, 5.7, 0.2502, 0.07203 + 41000.0, 0.93, 5.75, 0.2466, 0.07467 + 41000.0, 0.93, 5.8, 0.2428, 0.07739 + 41000.0, 0.93, 5.85, 0.239, 0.08017 + 41000.0, 0.93, 5.9, 0.2351, 0.08302 + 41000.0, 0.93, 5.95, 0.2311, 0.08594 + 41000.0, 0.93, 6.0, 0.2272, 0.08893 + 41000.0, 0.93, 6.05, 0.2269, 0.09244 + 41000.0, 0.93, 6.1, 0.2269, 0.09605 + 41000.0, 0.93, 6.15, 0.227, 0.09974 + 41000.0, 0.93, 6.2, 0.2273, 0.1035 + 41000.0, 0.93, 6.25, 0.2278, 0.1074 + 41000.0, 0.93, 6.3, 0.2284, 0.1113 + 41000.0, 0.93, 6.35, 0.2291, 0.1154 + 41000.0, 0.93, 6.4, 0.23, 0.1195 + 41000.0, 0.93, 6.45, 0.2311, 0.1237 + 41000.0, 0.93, 6.5, 0.2322, 0.1279 + 41000.0, 0.93, 6.55, 0.2335, 0.1323 + 41000.0, 0.93, 6.6, 0.2349, 0.1367 + 41000.0, 0.93, 6.65, 0.2365, 0.1412 + 41000.0, 0.93, 6.7, 0.2381, 0.1457 + 41000.0, 0.93, 6.75, 0.2398, 0.1503 + 41000.0, 0.93, 6.8, 0.2416, 0.155 + 41000.0, 0.93, 6.85, 0.2436, 0.1598 + 41000.0, 0.93, 6.9, 0.2456, 0.1646 + 41000.0, 0.93, 6.95, 0.2477, 0.1694 + 41000.0, 0.93, 7.0, 0.2498, 0.1743 + 41000.0, 0.93, 7.05, 0.2521, 0.1793 + 41000.0, 0.93, 7.1, 0.2544, 0.1843 + 41000.0, 0.93, 7.15, 0.2567, 0.1893 + 41000.0, 0.93, 7.2, 0.2591, 0.1944 + 41000.0, 0.93, 7.25, 0.2616, 0.1996 + 41000.0, 0.93, 7.3, 0.2641, 0.2048 + 41000.0, 0.93, 7.35, 0.2666, 0.21 + 41000.0, 0.93, 7.4, 0.2692, 0.2153 + 41000.0, 0.93, 7.45, 0.2718, 0.2206 + 41000.0, 0.93, 7.5, 0.2744, 0.2259 + 41000.0, 0.93, 7.55, 0.277, 0.2313 + 41000.0, 0.93, 7.6, 0.2797, 0.2367 + 41000.0, 0.93, 7.65, 0.2823, 0.2421 + 41000.0, 0.93, 7.7, 0.2849, 0.2476 + 41000.0, 0.93, 7.75, 0.2876, 0.253 + 41000.0, 0.93, 7.8, 0.2902, 0.2585 + 41000.0, 0.93, 7.85, 0.2928, 0.264 + 41000.0, 0.93, 7.9, 0.2953, 0.2696 + 41000.0, 0.93, 7.95, 0.2979, 0.2751 + 41000.0, 0.93, 8.0, 0.3004, 0.2807 + 41000.0, 0.93, 8.05, 0.3011, 0.2857 + 41000.0, 0.93, 8.1, 0.3018, 0.2907 + 41000.0, 0.93, 8.15, 0.3024, 0.2957 + 41000.0, 0.93, 8.2, 0.303, 0.3007 + 41000.0, 0.93, 8.25, 0.3036, 0.3058 + 41000.0, 0.93, 8.3, 0.3041, 0.3108 + 41000.0, 0.93, 8.35, 0.3046, 0.3159 + 41000.0, 0.93, 8.4, 0.3051, 0.3209 + 41000.0, 0.93, 8.45, 0.3055, 0.326 + 41000.0, 0.93, 8.5, 0.3059, 0.3311 + 41000.0, 0.93, 8.55, 0.3063, 0.3362 + 41000.0, 0.93, 8.6, 0.3066, 0.3413 + 41000.0, 0.93, 8.65, 0.3069, 0.3465 + 41000.0, 0.93, 8.7, 0.3072, 0.3516 + 41000.0, 0.93, 8.75, 0.3074, 0.3567 + 41000.0, 0.93, 8.8, 0.3077, 0.3619 + 41000.0, 0.93, 8.85, 0.3078, 0.3671 + 41000.0, 0.93, 8.9, 0.308, 0.3722 + 41000.0, 0.93, 8.95, 0.3081, 0.3774 + 41000.0, 0.93, 9.0, 0.3082, 0.3826 + 41000.0, 0.93, 9.05, 0.3083, 0.3879 + 41000.0, 0.93, 9.1, 0.3084, 0.3931 + 41000.0, 0.93, 9.15, 0.3084, 0.3983 + 41000.0, 0.93, 9.2, 0.3085, 0.4036 + 41000.0, 0.93, 9.25, 0.3085, 0.4088 + 41000.0, 0.93, 9.3, 0.3085, 0.4141 + 41000.0, 0.93, 9.35, 0.3084, 0.4194 + 41000.0, 0.93, 9.4, 0.3084, 0.4247 + 41000.0, 0.93, 9.45, 0.3083, 0.43 + 41000.0, 0.93, 9.5, 0.3082, 0.4353 + 41000.0, 0.93, 9.55, 0.3081, 0.4406 + 41000.0, 0.93, 9.6, 0.308, 0.446 + 41000.0, 0.93, 9.65, 0.3079, 0.4513 + 41000.0, 0.93, 9.7, 0.3078, 0.4567 + 41000.0, 0.93, 9.75, 0.3077, 0.4621 + 41000.0, 0.93, 9.8, 0.3075, 0.4675 + 41000.0, 0.93, 9.85, 0.3073, 0.4729 + 41000.0, 0.93, 9.9, 0.3072, 0.4783 + 41000.0, 0.93, 9.95, 0.307, 0.4837 + 41000.0, 0.93, 10.0, 0.3068, 0.4892 + 41000.0, 0.93, 10.05, 0.3068, 0.4948 + 41000.0, 0.93, 10.1, 0.3068, 0.5005 + 41000.0, 0.93, 10.15, 0.3068, 0.5062 + 41000.0, 0.93, 10.2, 0.3068, 0.5119 + 41000.0, 0.93, 10.25, 0.3068, 0.5176 + 41000.0, 0.93, 10.3, 0.3068, 0.5233 + 41000.0, 0.93, 10.35, 0.3067, 0.529 + 41000.0, 0.93, 10.4, 0.3067, 0.5348 + 41000.0, 0.93, 10.45, 0.3067, 0.5405 + 41000.0, 0.93, 10.5, 0.3067, 0.5463 + 41000.0, 0.93, 10.55, 0.3066, 0.552 + 41000.0, 0.93, 10.6, 0.3066, 0.5578 + 41000.0, 0.93, 10.65, 0.3065, 0.5635 + 41000.0, 0.93, 10.7, 0.3065, 0.5693 + 41000.0, 0.93, 10.75, 0.3065, 0.575 + 41000.0, 0.93, 10.8, 0.3064, 0.5808 + 41000.0, 0.93, 10.85, 0.3064, 0.5865 + 41000.0, 0.93, 10.9, 0.3063, 0.5923 + 41000.0, 0.93, 10.95, 0.3063, 0.5981 + 41000.0, 0.93, 11.0, 0.3062, 0.6038 + 41000.0, 0.93, 11.05, 0.3062, 0.6096 + 41000.0, 0.93, 11.1, 0.3061, 0.6153 + 41000.0, 0.93, 11.15, 0.3061, 0.621 + 41000.0, 0.93, 11.2, 0.3061, 0.6268 + 41000.0, 0.93, 11.25, 0.306, 0.6325 + 41000.0, 0.93, 11.3, 0.306, 0.6382 + 41000.0, 0.93, 11.35, 0.3059, 0.6439 + 41000.0, 0.93, 11.4, 0.3059, 0.6496 + 41000.0, 0.93, 11.45, 0.3058, 0.6553 + 41000.0, 0.93, 11.5, 0.3058, 0.661 + 41000.0, 0.93, 11.55, 0.3058, 0.6667 + 41000.0, 0.93, 11.6, 0.3057, 0.6724 + 41000.0, 0.93, 11.65, 0.3057, 0.678 + 41000.0, 0.93, 11.7, 0.3057, 0.6837 + 41000.0, 0.93, 11.75, 0.3057, 0.6893 + 41000.0, 0.93, 11.8, 0.3056, 0.6949 + 41000.0, 0.93, 11.85, 0.3056, 0.7005 + 41000.0, 0.93, 11.9, 0.3056, 0.7061 + 41000.0, 0.93, 11.95, 0.3056, 0.7116 + 41000.0, 0.93, 12.0, 0.3056, 0.7172 + 41000.0, 0.93, 12.05, 0.3056, 0.7227 + 41000.0, 0.93, 12.1, 0.3056, 0.7282 + 41000.0, 0.93, 12.15, 0.3056, 0.7337 + 41000.0, 0.93, 12.2, 0.3056, 0.7392 + 41000.0, 0.93, 12.25, 0.3057, 0.7446 + 41000.0, 0.93, 12.3, 0.3057, 0.75 + 41000.0, 0.93, 12.35, 0.3057, 0.7554 + 41000.0, 0.93, 12.4, 0.3058, 0.7608 + 41000.0, 0.93, 12.45, 0.3058, 0.7661 + 41000.0, 0.93, 12.5, 0.3059, 0.7715 + 41000.0, 0.93, 12.55, 0.3059, 0.7768 + 41000.0, 0.93, 12.6, 0.306, 0.782 + 41000.0, 0.93, 12.65, 0.3061, 0.7873 + 41000.0, 0.93, 12.7, 0.3062, 0.7925 + 41000.0, 0.93, 12.75, 0.3062, 0.7977 + 41000.0, 0.93, 12.8, 0.3063, 0.8028 + 41000.0, 0.93, 12.85, 0.3064, 0.8079 + 41000.0, 0.93, 12.9, 0.3066, 0.813 + 41000.0, 0.93, 12.95, 0.3067, 0.8181 + 41000.0, 0.93, 13.0, 0.3068, 0.8231 + 41000.0, 0.93, 13.05, 0.307, 0.8281 + 41000.0, 0.93, 13.1, 0.3071, 0.8331 + 41000.0, 0.93, 13.15, 0.3073, 0.838 + 41000.0, 0.93, 13.2, 0.3075, 0.8429 + 41000.0, 0.93, 13.25, 0.3076, 0.8477 + 41000.0, 0.93, 13.3, 0.3078, 0.8525 + 41000.0, 0.93, 13.35, 0.308, 0.8573 + 41000.0, 0.93, 13.4, 0.3082, 0.862 + 41000.0, 0.93, 13.45, 0.3085, 0.8667 + 41000.0, 0.93, 13.5, 0.3087, 0.8714 + 41000.0, 0.93, 13.55, 0.309, 0.876 + 41000.0, 0.93, 13.6, 0.3092, 0.8805 + 41000.0, 0.93, 13.65, 0.3095, 0.8851 + 41000.0, 0.93, 13.7, 0.3098, 0.8895 + 41000.0, 0.93, 13.75, 0.3101, 0.894 + 41000.0, 0.93, 13.8, 0.3104, 0.8984 + 41000.0, 0.93, 13.85, 0.3107, 0.9027 + 41000.0, 0.93, 13.9, 0.311, 0.907 + 41000.0, 0.93, 13.95, 0.3114, 0.9113 + 41000.0, 0.93, 14.0, 0.3118, 0.9155 + 41000.0, 0.93, 14.05, 0.3121, 0.9196 + 41000.0, 0.93, 14.1, 0.3125, 0.9237 + 41000.0, 0.93, 14.15, 0.3129, 0.9278 + 41000.0, 0.93, 14.2, 0.3134, 0.9318 + 41000.0, 0.93, 14.25, 0.3138, 0.9357 + 41000.0, 0.93, 14.3, 0.3143, 0.9396 + 41000.0, 0.93, 14.35, 0.3147, 0.9434 + 41000.0, 0.93, 14.4, 0.3152, 0.9472 + 41000.0, 0.93, 14.45, 0.3157, 0.9509 + 41000.0, 0.93, 14.5, 0.3162, 0.9546 + 41000.0, 0.93, 14.55, 0.3168, 0.9582 + 41000.0, 0.93, 14.6, 0.3173, 0.9618 + 41000.0, 0.93, 14.65, 0.3179, 0.9653 + 41000.0, 0.93, 14.7, 0.3185, 0.9687 + 41000.0, 0.93, 14.75, 0.3191, 0.9721 + 41000.0, 0.93, 14.8, 0.3197, 0.9754 + 41000.0, 0.93, 14.85, 0.3203, 0.9787 + 41000.0, 0.93, 14.9, 0.321, 0.9819 + 41000.0, 0.93, 14.95, 0.3216, 0.985 + 41000.0, 0.93, 15.0, 0.3223, 0.9881 + 41000.0, 0.93, 15.05, 0.323, 0.9911 diff --git a/aviary/models/aircraft/large_single_aisle_1/V3_bug_fixed_IO.py b/aviary/models/aircraft/large_single_aisle_1/V3_bug_fixed_IO.py new file mode 100644 index 0000000000..9c12fa554f --- /dev/null +++ b/aviary/models/aircraft/large_single_aisle_1/V3_bug_fixed_IO.py @@ -0,0 +1,173 @@ +""" +Initial cut at a centralized file for the IO +of the large single aisle 1 V3 bug fixed case for the GASP-based +mass calculations and geometry calculations. +""" + +import numpy as np + +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.options import get_option_defaults +from aviary.variable_info.variables import Aircraft, Mission + +V3_bug_fixed_options = get_option_defaults() +V3_bug_fixed_options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') +# we keep CrewPayload.NUM_PASSENGERS here because preprocess_crewpayload is often not run in these +# tests which prevents these values being assigned from Design.NUM_PASSENGERS as would normally happen +V3_bug_fixed_options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') +V3_bug_fixed_options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') +V3_bug_fixed_options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') +V3_bug_fixed_options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' +) +V3_bug_fixed_options.set_val( + Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + + +V3_bug_fixed_options.set_val(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Wing.SWEEP, val=25, units='deg') +V3_bug_fixed_options.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless') +V3_bug_fixed_options.set_val(Mission.Design.GROSS_MASS, val=175400, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.Design.WING_LOADING, val=126, units='lbf/ft**2') +V3_bug_fixed_options.set_val( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf') +V3_bug_fixed_options.set_val(Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, np.array([28690]), units='lbf') +# NOTE override required for mass summation test +V3_bug_fixed_options.set_val(Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + + +V3_bug_fixed_non_metadata = AviaryValues() + + +V3_bug_fixed_options.set_val(Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi') +V3_bug_fixed_options.set_val( + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.NUM_AISLES, 1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') +V3_bug_fixed_options.set_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.WETTED_AREA, 4000, units='ft**2') +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') +V3_bug_fixed_options.set_val(Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Nacelle.FINENESS, 2, units='unitless') + +V3_bug_fixed_options.set_val(Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h') +V3_bug_fixed_options.set_val(Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units='1/rad') +V3_bug_fixed_options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.SWEEP, val=0, units='deg') +V3_bug_fixed_options.set_val(Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless') +V3_bug_fixed_options.set_val( + # TODO: should be lbf/ft**2 I think + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, + val=2.66, + units='unitless', +) +V3_bug_fixed_options.set_val( + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' +) +V3_bug_fixed_options.set_val( + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' +) +V3_bug_fixed_options.set_val( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' +) +V3_bug_fixed_options.set_val(Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless') +V3_bug_fixed_options.set_val( + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf') +V3_bug_fixed_options.set_val(Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2') +V3_bug_fixed_options.set_val(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.APU.MASS, val=928.0, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless') +V3_bug_fixed_options.set_val( + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Avionics.MASS, val=1959.0, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') +V3_bug_fixed_options.set_val( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' +) +V3_bug_fixed_options.set_val(Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm') +V3_bug_fixed_options.set_val( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' +) +V3_bug_fixed_options.set_val( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' +) + +V3_bug_fixed_options.set_val(Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless') + +V3_bug_fixed_options.set_val(Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val(Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm') +V3_bug_fixed_options.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val( + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') +V3_bug_fixed_options.set_val( + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' +) # Based on large single aisle 1 for updated flaps mass model +V3_bug_fixed_options.set_val( + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' +) # Based on large single aisle 1 for updated flaps mass model +V3_bug_fixed_options.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless') +V3_bug_fixed_options.set_val( + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' +) +V3_bug_fixed_options.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3, units='unitless') + +V3_bug_fixed_non_metadata.set_val('pylon_len', val=0, units='ft') +V3_bug_fixed_non_metadata.set_val('MAT', val=0, units='lbm') diff --git a/aviary/models/large_single_aisle_1/__init__.py b/aviary/models/aircraft/large_single_aisle_1/__init__.py similarity index 100% rename from aviary/models/large_single_aisle_1/__init__.py rename to aviary/models/aircraft/large_single_aisle_1/__init__.py diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py similarity index 83% rename from aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py rename to aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py index 9c74cfbd56..e21ace94f5 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_FLOPS_data.py @@ -11,10 +11,10 @@ # Overall Aircraft # --------------------------- -inputs.set_val(Aircraft.Design.BASE_AREA, 0., 'ft**2') +inputs.set_val(Aircraft.Design.BASE_AREA, 0.0, 'ft**2') inputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, 0.0) inputs.set_val(Aircraft.Design.TOUCHDOWN_MASS, 152800.0, 'lbm') -inputs.set_val(Mission.Design.GROSS_MASS, 181200., 'lbm') +inputs.set_val(Mission.Design.GROSS_MASS, 181200.0, 'lbm') inputs.set_val(Aircraft.Design.USE_ALT_MASS, False) inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 0.909839381134961) inputs.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0) @@ -59,11 +59,11 @@ inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW, 2) inputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_GALLEY_CREW, 0) -inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 0., 'lbm') +inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 0.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, 1.0) -inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.) -inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 180., 'lbm') -inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0., 'lbm') +inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 180.0, 'lbm') +inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0.0, 'lbm') # Electrical # --------------------------- @@ -80,7 +80,7 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') -inputs.set_val(Aircraft.Fuel.DENSITY_RATIO, 1.0) +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0, 'lbm') inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) @@ -94,7 +94,7 @@ # Fuselage # --------------------------- inputs.set_val(Aircraft.Fuselage.NUM_FUSELAGES, 1) -inputs.set_val(Aircraft.Fuselage.LENGTH, 128., 'ft') +inputs.set_val(Aircraft.Fuselage.LENGTH, 128.0, 'ft') inputs.set_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, 85.5, 'ft') inputs.set_val(Aircraft.Fuselage.MAX_HEIGHT, 13.17, 'ft') inputs.set_val(Aircraft.Fuselage.MAX_WIDTH, 12.33, 'ft') @@ -106,7 +106,7 @@ # Horizontal Tail # --------------------------- -inputs.set_val(Aircraft.HorizontalTail.AREA, 355., 'ft**2') +inputs.set_val(Aircraft.HorizontalTail.AREA, 355.0, 'ft**2') inputs.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, 6.0) inputs.set_val(Aircraft.HorizontalTail.TAPER_RATIO, 0.22) inputs.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.125) @@ -117,7 +117,7 @@ # Hydraulics # --------------------------- -inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000., 'psi') +inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000.0, 'psi') inputs.set_val(Aircraft.Hydraulics.MASS_SCALER, 1.0) # Instruments @@ -126,7 +126,6 @@ # Landing Gear # --------------------------- -inputs.set_val(Aircraft.LandingGear.CARRIER_BASED, False) inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, 102.0, 'inch') inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, 1.1) inputs.set_val(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, 67.0, 'inch') @@ -148,7 +147,7 @@ inputs.set_val(Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, 1.0) -filename = get_path('models/engines/turbofan_28k.deck') +filename = get_path('models/engines/turbofan_28k.csv') inputs.set_val(Aircraft.Engine.DATA_FILE, filename) inputs.set_val(Aircraft.Engine.MASS, 7400, 'lbm') @@ -160,6 +159,7 @@ inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2) inputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, 0.0) inputs.set_val(Aircraft.Engine.WING_LOCATIONS, 15.8300 / (117.83 / 2)) +inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) inputs.set_val(Aircraft.Engine.SCALE_MASS, True) inputs.set_val(Aircraft.Engine.MASS_SCALER, 1.15) inputs.set_val(Aircraft.Engine.SCALE_PERFORMANCE, True) @@ -180,7 +180,7 @@ # Vertical Tail # --------------------------- inputs.set_val(Aircraft.VerticalTail.NUM_TAILS, 1) -inputs.set_val(Aircraft.VerticalTail.AREA, 284., 'ft**2') +inputs.set_val(Aircraft.VerticalTail.AREA, 284.0, 'ft**2') inputs.set_val(Aircraft.VerticalTail.ASPECT_RATIO, 1.75) inputs.set_val(Aircraft.VerticalTail.TAPER_RATIO, 0.33) inputs.set_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.1195) @@ -194,11 +194,12 @@ inputs.set_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY, 1.92669766647637) inputs.set_val(Aircraft.Wing.AREA, 1370.0, 'ft**2') inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 11.22091) -inputs.set_val(Aircraft.Wing.BENDING_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, np.array([0.31, 0.23, 0.084])) inputs.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.2) inputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 137, 'ft**2') inputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, 0.1) +inputs.set_val(Aircraft.Wing.DETAILED_WING, True) inputs.set_val(Aircraft.Wing.GLOVE_AND_BAT, 134.0, 'ft**2') inputs.set_val(Aircraft.Wing.INPUT_STATION_DIST, np.array([0.0, 0.2759, 0.9367])) inputs.set_val(Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL, 2.0) @@ -216,8 +217,7 @@ inputs.set_val(Aircraft.Wing.SWEEP, 25.0, 'deg') inputs.set_val(Aircraft.Wing.TAPER_RATIO, 0.27800) inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, 0.1300) -inputs.set_val( - Aircraft.Wing.THICKNESS_TO_CHORD_DIST, np.array([0.145, 0.115, 0.104])) +inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_DIST, np.array([0.145, 0.115, 0.104])) inputs.set_val(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.75) inputs.set_val(Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, 0.0) inputs.set_val(Aircraft.Wing.MASS_SCALER, 1.23) @@ -242,7 +242,7 @@ # TODO: should this be a user input or should it be hard coded somewhere assuming it will # # never change? -inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, .0175) +inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.0175) # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 28928.0, 'lbf') @@ -255,21 +255,21 @@ # OUTPUTS # --------------------------- -outputs.set_val(Aircraft.Design.EMPTY_MASS, 92023., 'lbm') +outputs.set_val(Aircraft.Design.EMPTY_MASS, 92023.0, 'lbm') outputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN, 0.0, 'lbm') -outputs.set_val(Aircraft.Design.OPERATING_MASS, 97992., 'lbm') -outputs.set_val(Aircraft.Propulsion.MASS, 16118., 'lbm') -outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 50736., 'lbm') -outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 25169., 'lbm') +outputs.set_val(Mission.Summary.OPERATING_MASS, 97992.0, 'lbm') +outputs.set_val(Aircraft.Propulsion.MASS, 16118.0, 'lbm') +outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 50736.0, 'lbm') +outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 25169.0, 'lbm') outputs.set_val(Aircraft.Design.TOTAL_WETTED_AREA, 8275.86, 'ft**2') -outputs.set_val(Aircraft.Design.ZERO_FUEL_MASS, 135848., 'lbm') -outputs.set_val(Mission.Design.FUEL_MASS, 45352., 'lbm') +outputs.set_val(Mission.Summary.ZERO_FUEL_MASS, 135848.0, 'lbm') +outputs.set_val(Mission.Summary.FUEL_MASS, 45352.0, 'lbm') -outputs.set_val(Aircraft.AirConditioning.MASS, 1602., 'lbm') +outputs.set_val(Aircraft.AirConditioning.MASS, 1602.0, 'lbm') outputs.set_val(Aircraft.AntiIcing.MASS, 208.85, 'lbm') -outputs.set_val(Aircraft.APU.MASS, 1142., 'lbm') +outputs.set_val(Aircraft.APU.MASS, 1142.0, 'lbm') outputs.set_val(Aircraft.Avionics.MASS, 1652.6, 'lbm') @@ -278,14 +278,14 @@ outputs.set_val(Aircraft.Canard.WETTED_AREA, 0.0, 'ft**2') outputs.set_val(Aircraft.Canard.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 7436., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 0., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1400., 'lbm') +outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 7436.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 0.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1400.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS, 450.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, 465.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 3022.74805809, 'lbm') -outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 30420., 'lbm') -outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 37856., 'lbm') +outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 30420.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 37856.0, 'lbm') outputs.set_val(Aircraft.Electrical.MASS, 2464.0, 'lbm') @@ -294,23 +294,23 @@ outputs.set_val(Aircraft.Fins.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.Furnishings.MASS, 15517., 'lbm') +outputs.set_val(Aircraft.Furnishings.MASS, 15517.0, 'lbm') avg_diameter = 12.75 avg_diameter_units = 'ft' outputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, avg_diameter, avg_diameter_units) -outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 128., 'ft') +outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 128.0, 'ft') outputs.set_val( - Aircraft.Fuselage.CROSS_SECTION, - np.pi * (avg_diameter / 2.0)**2.0, f'{avg_diameter_units}**2') + Aircraft.Fuselage.CROSS_SECTION, np.pi * (avg_diameter / 2.0) ** 2.0, f'{avg_diameter_units}**2' +) outputs.set_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.108207) outputs.set_val(Aircraft.Fuselage.FINENESS, 10.0392) outputs.set_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER, 10.039216) -outputs.set_val(Aircraft.Fuselage.MASS, 18357., 'lbm') +outputs.set_val(Aircraft.Fuselage.MASS, 18357.0, 'lbm') outputs.set_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 7.69, 'ft') outputs.set_val(Aircraft.HorizontalTail.FINENESS, 0.1250) -outputs.set_val(Aircraft.HorizontalTail.MASS, 1831., 'lbm') +outputs.set_val(Aircraft.HorizontalTail.MASS, 1831.0, 'lbm') outputs.set_val(Aircraft.Hydraulics.MASS, 1086.7, 'lbm') @@ -325,43 +325,38 @@ nacelle_wetted_area = np.array([273.45]) nacelle_wetted_area_units = 'ft**2' -outputs.set_val( - Aircraft.Nacelle.WETTED_AREA, nacelle_wetted_area, nacelle_wetted_area_units) +outputs.set_val(Aircraft.Nacelle.WETTED_AREA, nacelle_wetted_area, nacelle_wetted_area_units) outputs.set_val( - Aircraft.Nacelle.TOTAL_WETTED_AREA, - 2 * nacelle_wetted_area, nacelle_wetted_area_units) + Aircraft.Nacelle.TOTAL_WETTED_AREA, 2 * nacelle_wetted_area, nacelle_wetted_area_units +) outputs.set_val(Aircraft.Paint.MASS, 306.2, 'lbm') -outputs.set_val( - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 28928.1*2, 'lbf') +outputs.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 28928.1 * 2, 'lbf') -outputs.set_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) engine_ctrls_mass = 88.44 engine_ctrls_mass_units = 'lbm' +outputs.set_val(Aircraft.Engine.CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units) outputs.set_val( - Aircraft.Engine.CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units) -outputs.set_val( - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - engine_ctrls_mass, engine_ctrls_mass_units) + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units +) outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, 130.23, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2) outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 0) -outputs.set_val(Aircraft.Engine.MASS, 14800/2, 'lbm') +outputs.set_val(Aircraft.Engine.MASS, 14800 / 2, 'lbm') outputs.set_val(Aircraft.Engine.POD_MASS, 9000, 'lbm') outputs.set_val(Aircraft.Engine.ADDITIONAL_MASS, 0.0, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_MISC_MASS, 648.83, 'lbm') -outputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) outputs.set_val(Aircraft.Propulsion.TOTAL_STARTER_MASS, 560.39, 'lbm') - outputs.set_val(Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, 0, 'lbm') outputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS, 0, 'lbm') +outputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 28928.1, 'lbf') outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_MASS, 7400 * 2, 'lbm') @@ -369,8 +364,8 @@ outputs.set_val(Aircraft.VerticalTail.FINENESS, 0.1195) outputs.set_val(Aircraft.VerticalTail.MASS, 1221.8, 'lbm') -outputs.set_val(Aircraft.Wing.BENDING_FACTOR, 11.5918) -outputs.set_val(Aircraft.Wing.BENDING_MASS, 8184.8, 'lbm') +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR, 11.5918) +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS, 8184.8, 'lbm') outputs.set_val(Aircraft.Wing.CHARACTERISTIC_LENGTH, 10.49, 'ft') # Not in FLOPS output; calculated from inputs. outputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 137, 'ft**2') diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv similarity index 92% rename from aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv rename to aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv index 7a0a23fd20..b3c556cddf 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.csv +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.csv @@ -7,15 +7,16 @@ aircraft:controls:cockpit_control_mass_scaler,1,unitless aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless -aircraft:crew_and_payload:cargo_mass,10040,lbm aircraft:crew_and_payload:catering_items_mass_per_passenger,7.6,lbm aircraft:crew_and_payload:design:num_passengers,180,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,6,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,29,inch aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:crew_and_payload:passenger_service_mass_per_passenger,5,lbm aircraft:crew_and_payload:water_mass_per_occupant,3,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless -aircraft:design:drag_increment,0.00175,unitless +aircraft:design:drag_coeff_increment,0.00175,unitless aircraft:design:emergency_equipment_mass,50,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless @@ -23,9 +24,11 @@ aircraft:design:reserve_fuel_additional,4998,lbm aircraft:design:reserve_fuel_fraction,0,unitless aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm -aircraft:design:supercritical_drag_shift,0.033,unitless +aircraft:design:drag_divergence_shift,0.033,unitless +aircraft:design:type,transport,unitless aircraft:engine:additional_mass_fraction,0.14,unitless -aircraft:engine:data_file,models/engines/turbofan_23k_1.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_23k_1.csv,unitless +aircraft:engine:global_throttle, True, unitless aircraft:engine:mass_scaler,1,unitless aircraft:engine:mass_specific,0.21366,lbm/lbf aircraft:engine:num_engines,2,unitless @@ -33,6 +36,7 @@ aircraft:engine:pod_mass_scaler,1,unitless aircraft:engine:pylon_factor,1.25,unitless aircraft:engine:reference_diameter,5.8,ft aircraft:engine:reference_sls_thrust,28690,lbf +aircraft:engine:scale_factor,1.0,unitless aircraft:engine:scaled_sls_thrust,28690,lbf aircraft:engine:type,7,unitless aircraft:engine:wing_locations,0.35,unitless @@ -50,14 +54,11 @@ aircraft:fuselage:form_factor,1.25,unitless aircraft:fuselage:mass_coefficient,128,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_seats_abreast,6,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 -aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless aircraft:horizontal_tail:form_factor,1.25,unitless aircraft:horizontal_tail:mass_coefficient,0.232,unitless @@ -88,7 +89,6 @@ aircraft:strut:dimensional_location_specified,False,unitless aircraft:strut:fuselage_interference_factor,0,unitless aircraft:strut:mass_coefficient,0,unitless aircraft:strut:thickness_to_chord,0,unitless -aircraft:vertical_tail:area,0,ft**2 aircraft:vertical_tail:aspect_ratio,1.67,unitless aircraft:vertical_tail:form_factor,1.25,unitless aircraft:vertical_tail:mass_coefficient,0.289,unitless @@ -117,21 +117,21 @@ aircraft:wing:has_strut,False,unitless aircraft:wing:height,8,ft aircraft:wing:high_lift_mass_coefficient,1.9,unitless aircraft:wing:incidence,1.5,deg -aircraft:wing:loading,128,lbf/ft**2 +aircraft:design:wing_loading,128,lbf/ft**2 aircraft:wing:mass_coefficient,102.5,unitless aircraft:wing:max_lift_ref,1.15,unitless aircraft:wing:max_slat_deflection_landing,10,deg aircraft:wing:max_slat_deflection_takeoff,10,deg aircraft:wing:max_thickness_location,0.4,unitless aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:mounting_type,0,unitless +aircraft:wing:vertical_mount_location,0,unitless aircraft:wing:num_flap_segments,2,unitless aircraft:wing:optimum_flap_deflection,55,deg aircraft:wing:optimum_slat_deflection,20,deg aircraft:wing:slat_chord_ratio,0.15,unitless aircraft:wing:slat_lift_increment_optimum,0.93,unitless aircraft:wing:slat_span_ratio,0.9,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.95,unitless +aircraft:wing:surface_control_mass_coefficient,0.95,unitless aircraft:wing:sweep,25,deg aircraft:wing:taper_ratio,0.33,unitless aircraft:wing:thickness_to_chord_root,0.15,unitless @@ -154,6 +154,7 @@ mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.1677,h settings:equations_of_motion,2DOF +settings:aerodynamics_method,GASP settings:mass_method,GASP # Initialization Guesses diff --git a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.dat similarity index 99% rename from aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat rename to aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.dat index 9869b50686..4cc3b30972 100644 --- a/aviary/models/large_single_aisle_1/large_single_aisle_1_GwGm.dat +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.dat @@ -1,5 +1,4 @@ LARGE SINGLE AISLE 1 / 23k SLS thrust turbofan -1 -1 -aircraft:engine:data_file=models/engines/turbofan_23k_1.deck $INGASP XCTCMX=.4 STATIC=.03 diff --git a/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_flaps.csv b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_flaps.csv new file mode 100644 index 0000000000..c13db1fc48 --- /dev/null +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_flaps.csv @@ -0,0 +1,150 @@ +# created 06/11/25 +# GASP_ALT-derived aerodynamics data converted from aero_flaps_GASP.txt +# Incremental Lift and Drag Coeff. for Flaps +# Reference Area = 1370. sqft + +Flap Deflection (deg, input), Mach (input), Angle of Attack (deg, input), Delta CL (output), Delta CD (output) + 10.0, 0.0, -2.0, 0.44098, 0.01046 + 10.0, 0.0, 0.0, 0.44098, 0.01436 + 10.0, 0.0, 2.0, 0.44098, 0.01829 + 10.0, 0.0, 4.0, 0.44098, 0.02224 + 10.0, 0.0, 6.0, 0.44098, 0.02622 + 10.0, 0.0, 8.0, 0.44098, 0.03021 + 10.0, 0.0, 10.0, 0.44098, 0.03423 + 10.0, 0.0, 12.0, 0.44098, 0.03826 + 10.0, 0.0, 14.0, 0.44098, 0.04232 + 10.0, 0.0, 16.0, 0.44098, 0.0464 + 10.0, 0.0, 18.0, 0.44098, 0.05051 + 10.0, 0.0, 19.69, 0.41324, 0.05048 + 10.0, 0.1, -2.0, 0.44086, 0.01083 + 10.0, 0.1, 0.0, 0.44086, 0.01551 + 10.0, 0.1, 2.0, 0.44086, 0.02022 + 10.0, 0.1, 4.0, 0.44086, 0.02495 + 10.0, 0.1, 6.0, 0.44086, 0.02971 + 10.0, 0.1, 8.0, 0.44086, 0.03449 + 10.0, 0.1, 10.0, 0.44086, 0.03931 + 10.0, 0.1, 12.0, 0.44086, 0.04414 + 10.0, 0.1, 14.0, 0.44086, 0.04901 + 10.0, 0.1, 16.0, 0.44086, 0.0539 + 10.0, 0.1, 18.0, 0.44086, 0.05881 + 10.0, 0.1, 19.62, 0.40665, 0.05764 + 10.0, 0.2, -2.0, 0.44049, 0.01076 + 10.0, 0.2, 0.0, 0.44049, 0.01541 + 10.0, 0.2, 2.0, 0.44049, 0.02008 + 10.0, 0.2, 4.0, 0.44049, 0.02477 + 10.0, 0.2, 6.0, 0.44049, 0.02949 + 10.0, 0.2, 8.0, 0.44049, 0.03424 + 10.0, 0.2, 10.0, 0.44049, 0.03901 + 10.0, 0.2, 12.0, 0.44049, 0.04381 + 10.0, 0.2, 14.0, 0.44049, 0.04864 + 10.0, 0.2, 16.0, 0.44049, 0.05349 + 10.0, 0.2, 18.0, 0.44049, 0.05836 + 10.0, 0.2, 19.4, 0.38648, 0.05373 + 10.0, 0.3, -2.0, 0.43986, 0.0107 + 10.0, 0.3, 0.0, 0.43986, 0.01537 + 10.0, 0.3, 2.0, 0.43986, 0.02006 + 10.0, 0.3, 4.0, 0.43986, 0.02478 + 10.0, 0.3, 6.0, 0.43986, 0.02952 + 10.0, 0.3, 8.0, 0.43986, 0.03429 + 10.0, 0.3, 10.0, 0.43986, 0.03909 + 10.0, 0.3, 12.0, 0.43986, 0.04392 + 10.0, 0.3, 14.0, 0.43986, 0.04877 + 10.0, 0.3, 16.0, 0.43986, 0.05365 + 10.0, 0.3, 18.0, 0.43986, 0.05856 + 10.0, 0.3, 19.04, 0.3514, 0.04793 + 10.0, 0.4, -2.0, 0.4389, 0.01062 + 10.0, 0.4, 0.0, 0.4389, 0.01535 + 10.0, 0.4, 2.0, 0.4389, 0.02011 + 10.0, 0.4, 4.0, 0.4389, 0.0249 + 10.0, 0.4, 6.0, 0.4389, 0.02972 + 10.0, 0.4, 8.0, 0.4389, 0.03456 + 10.0, 0.4, 10.0, 0.4389, 0.03943 + 10.0, 0.4, 12.0, 0.4389, 0.04433 + 10.0, 0.4, 14.0, 0.4389, 0.04926 + 10.0, 0.4, 16.0, 0.4389, 0.05421 + 10.0, 0.4, 18.0, 0.4389, 0.05919 + 10.0, 0.4, 18.52, 0.31496, 0.04199 + 10.0, 0.5, -2.0, 0.43757, 0.01052 + 10.0, 0.5, 0.0, 0.43757, 0.01536 + 10.0, 0.5, 2.0, 0.43757, 0.02023 + 10.0, 0.5, 4.0, 0.43757, 0.02514 + 10.0, 0.5, 6.0, 0.43757, 0.03007 + 10.0, 0.5, 8.0, 0.43757, 0.03503 + 10.0, 0.5, 10.0, 0.43757, 0.04002 + 10.0, 0.5, 12.0, 0.43757, 0.04504 + 10.0, 0.5, 14.0, 0.43757, 0.05009 + 10.0, 0.5, 16.0, 0.43757, 0.05517 + 10.0, 0.5, 17.82, 0.41979, 0.05725 + 10.0, 0.5, 17.82, 0.314, 0.04154 + 40.0, 0.0, -2.0, 1.08538, 0.04726 + 40.0, 0.0, 0.0, 1.08538, 0.05416 + 40.0, 0.0, 2.0, 1.08538, 0.06142 + 40.0, 0.0, 4.0, 1.08538, 0.06905 + 40.0, 0.0, 6.0, 1.08538, 0.07704 + 40.0, 0.0, 8.0, 1.08538, 0.0854 + 40.0, 0.0, 10.0, 1.08538, 0.09412 + 40.0, 0.0, 12.0, 1.08538, 0.1032 + 40.0, 0.0, 14.0, 1.08538, 0.11265 + 40.0, 0.0, 16.0, 1.08538, 0.12246 + 40.0, 0.0, 18.0, 1.08538, 0.13264 + 40.0, 0.0, 19.88, 1.07429, 0.14111 + 40.0, 0.1, -2.0, 1.08508, 0.04854 + 40.0, 0.1, 0.0, 1.08508, 0.0568 + 40.0, 0.1, 2.0, 1.08508, 0.0655 + 40.0, 0.1, 4.0, 1.08508, 0.07464 + 40.0, 0.1, 6.0, 1.08508, 0.08422 + 40.0, 0.1, 8.0, 1.08508, 0.09423 + 40.0, 0.1, 10.0, 1.08508, 0.10469 + 40.0, 0.1, 12.0, 1.08508, 0.11558 + 40.0, 0.1, 14.0, 1.08508, 0.1269 + 40.0, 0.1, 16.0, 1.08508, 0.13867 + 40.0, 0.1, 18.0, 1.08508, 0.15088 + 40.0, 0.1, 19.8, 1.06752, 0.15959 + 40.0, 0.2, -2.0, 1.08417, 0.04834 + 40.0, 0.2, 0.0, 1.08417, 0.05653 + 40.0, 0.2, 2.0, 1.08417, 0.06516 + 40.0, 0.2, 4.0, 1.08417, 0.07422 + 40.0, 0.2, 6.0, 1.08417, 0.08373 + 40.0, 0.2, 8.0, 1.08417, 0.09368 + 40.0, 0.2, 10.0, 1.08417, 0.10406 + 40.0, 0.2, 12.0, 1.08417, 0.11488 + 40.0, 0.2, 14.0, 1.08417, 0.12614 + 40.0, 0.2, 16.0, 1.08417, 0.13785 + 40.0, 0.2, 18.0, 1.08417, 0.14999 + 40.0, 0.2, 19.59, 1.0468, 0.15432 + 40.0, 0.3, -2.0, 1.0826, 0.04815 + 40.0, 0.3, 0.0, 1.0826, 0.05637 + 40.0, 0.3, 2.0, 1.0826, 0.06504 + 40.0, 0.3, 4.0, 1.0826, 0.07416 + 40.0, 0.3, 6.0, 1.0826, 0.08373 + 40.0, 0.3, 8.0, 1.0826, 0.09375 + 40.0, 0.3, 10.0, 1.0826, 0.10422 + 40.0, 0.3, 12.0, 1.0826, 0.11513 + 40.0, 0.3, 14.0, 1.0826, 0.1265 + 40.0, 0.3, 16.0, 1.0826, 0.13831 + 40.0, 0.3, 18.0, 1.0826, 0.15058 + 40.0, 0.3, 19.22, 1.01077, 0.14752 + 40.0, 0.4, -2.0, 1.08026, 0.04794 + 40.0, 0.4, 0.0, 1.08026, 0.05626 + 40.0, 0.4, 2.0, 1.08026, 0.06505 + 40.0, 0.4, 4.0, 1.08026, 0.07431 + 40.0, 0.4, 6.0, 1.08026, 0.08404 + 40.0, 0.4, 8.0, 1.08026, 0.09424 + 40.0, 0.4, 10.0, 1.08026, 0.1049 + 40.0, 0.4, 12.0, 1.08026, 0.11603 + 40.0, 0.4, 14.0, 1.08026, 0.12763 + 40.0, 0.4, 16.0, 1.08026, 0.1397 + 40.0, 0.4, 18.0, 1.08026, 0.15224 + 40.0, 0.4, 18.69, 0.97289, 0.14059 + 40.0, 0.5, -2.0, 1.07697, 0.04767 + 40.0, 0.5, 0.0, 1.07697, 0.05616 + 40.0, 0.5, 2.0, 1.07697, 0.06516 + 40.0, 0.5, 4.0, 1.07697, 0.07465 + 40.0, 0.5, 6.0, 1.07697, 0.08464 + 40.0, 0.5, 8.0, 1.07697, 0.09512 + 40.0, 0.5, 10.0, 1.07697, 0.10611 + 40.0, 0.5, 12.0, 1.07697, 0.11758 + 40.0, 0.5, 14.0, 1.07697, 0.12956 + 40.0, 0.5, 16.0, 1.07697, 0.14204 + 40.0, 0.5, 17.96, 1.07572, 0.15474 + 40.0, 0.5, 17.99, 0.96993, 0.13903 diff --git a/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_free.csv b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_free.csv new file mode 100644 index 0000000000..07270af5bd --- /dev/null +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_free.csv @@ -0,0 +1,1806 @@ +# created 06/11/25 +# GASP_ALT-derived aerodynamics data converted from aero_free_GASP.txt +# Clean / Free Air Aerodynamics +# Reference Area = 1370. sqft + +Altitude (ft, input), Mach (input), Angle of Attack (deg, input), CL (output), CD (output) + 0.0, 0.0, -2.0, -0.0715, 0.00363 + 0.0, 0.0, 0.0, 0.1072, 0.00384 + 0.0, 0.0, 2.0, 0.286, 0.00621 + 0.0, 0.0, 4.0, 0.4647, 0.01072 + 0.0, 0.0, 6.0, 0.6434, 0.01737 + 0.0, 0.0, 8.0, 0.8222, 0.02618 + 0.0, 0.0, 10.0, 1.0009, 0.03713 + 0.0, 0.0, 12.0, 1.1797, 0.05023 + 0.0, 0.0, 14.0, 1.3584, 0.06548 + 0.0, 0.0, 16.0, 1.5371, 0.08287 + 0.0, 0.0, 18.0, 1.7159, 0.10241 + 0.0, 0.0, 20.0, 1.8946, 0.1241 + 0.0, 0.2, -2.0, -0.0724, 0.01841 + 0.0, 0.2, 0.0, 0.1086, 0.01867 + 0.0, 0.2, 2.0, 0.2896, 0.02152 + 0.0, 0.2, 4.0, 0.4706, 0.02695 + 0.0, 0.2, 6.0, 0.6517, 0.03498 + 0.0, 0.2, 8.0, 0.8327, 0.04559 + 0.0, 0.2, 10.0, 1.0137, 0.05878 + 0.0, 0.2, 12.0, 1.1947, 0.07457 + 0.0, 0.2, 14.0, 1.3757, 0.09294 + 0.0, 0.2, 16.0, 1.5568, 0.1139 + 0.0, 0.2, 18.0, 1.7378, 0.13745 + 0.0, 0.2, 20.0, 1.9188, 0.16359 + 0.0, 0.4, -2.0, -0.0754, 0.01689 + 0.0, 0.4, 0.0, 0.1131, 0.01716 + 0.0, 0.4, 2.0, 0.3016, 0.0202 + 0.0, 0.4, 4.0, 0.4901, 0.026 + 0.0, 0.4, 6.0, 0.6786, 0.03455 + 0.0, 0.4, 8.0, 0.867, 0.04587 + 0.0, 0.4, 10.0, 1.0555, 0.05995 + 0.0, 0.4, 12.0, 1.244, 0.07678 + 0.0, 0.4, 14.0, 1.4325, 0.09638 + 0.0, 0.4, 16.0, 1.621, 0.11874 + 0.0, 0.4, 18.0, 1.8095, 0.14385 + 0.0, 0.4, 19.8, 1.982, 0.16926 + 0.0, 0.5, -2.0, -0.0779, 0.01639 + 0.0, 0.5, 0.0, 0.1169, 0.01668 + 0.0, 0.5, 2.0, 0.3117, 0.01991 + 0.0, 0.5, 4.0, 0.5065, 0.02607 + 0.0, 0.5, 6.0, 0.7013, 0.03515 + 0.0, 0.5, 8.0, 0.8961, 0.04717 + 0.0, 0.5, 10.0, 1.0909, 0.06212 + 0.0, 0.5, 12.0, 1.2857, 0.08 + 0.0, 0.5, 14.0, 1.4806, 0.10081 + 0.0, 0.5, 16.0, 1.6754, 0.12456 + 0.0, 0.5, 18.0, 1.8702, 0.15123 + 0.0, 0.5, 19.1, 1.976, 0.16695 + 0.0, 0.6, -2.0, -0.0814, 0.01598 + 0.0, 0.6, 0.0, 0.1221, 0.01629 + 0.0, 0.6, 2.0, 0.3257, 0.0198 + 0.0, 0.6, 4.0, 0.5293, 0.02648 + 0.0, 0.6, 6.0, 0.7329, 0.03636 + 0.0, 0.6, 8.0, 0.9365, 0.04941 + 0.0, 0.6, 10.0, 1.1401, 0.06566 + 0.0, 0.6, 12.0, 1.3436, 0.08508 + 0.0, 0.6, 14.0, 1.5472, 0.1077 + 0.0, 0.6, 16.0, 1.7508, 0.13349 + 0.0, 0.6, 18.0, 1.9544, 0.16254 + 0.0, 0.6, 18.1, 1.9677, 0.16456 + 0.0, 0.7, -2.0, -0.0863, 0.01561 + 0.0, 0.7, 0.0, 0.1295, 0.01597 + 0.0, 0.7, 2.0, 0.3454, 0.01989 + 0.0, 0.7, 4.0, 0.5613, 0.02737 + 0.0, 0.7, 6.0, 0.7771, 0.03842 + 0.0, 0.7, 8.0, 0.993, 0.05303 + 0.0, 0.7, 10.0, 1.2089, 0.07136 + 0.0, 0.7, 12.0, 1.4247, 0.09434 + 0.0, 0.7, 14.0, 1.6406, 0.12318 + 0.0, 0.7, 16.0, 1.8565, 0.1591 + 0.0, 0.7, 16.9, 1.9562, 0.17842 + 0.0, 0.7, 16.9, 1.9562, 0.17842 + 0.0, 0.75, -2.0, -0.0896, 0.01545 + 0.0, 0.75, 0.0, 0.1343, 0.01583 + 0.0, 0.75, 2.0, 0.3582, 0.02004 + 0.0, 0.75, 4.0, 0.5822, 0.02807 + 0.0, 0.75, 6.0, 0.8061, 0.04007 + 0.0, 0.75, 8.0, 1.03, 0.05703 + 0.0, 0.75, 10.0, 1.2539, 0.08031 + 0.0, 0.75, 12.0, 1.4778, 0.11124 + 0.0, 0.75, 14.0, 1.7017, 0.15118 + 0.0, 0.75, 16.0, 1.9256, 0.20146 + 0.0, 0.75, 16.2, 1.9488, 0.20733 + 0.0, 0.75, 16.2, 1.9488, 0.20733 + 0.0, 0.8, -2.0, -0.0935, 0.0153 + 0.0, 0.8, 0.0, 0.1402, 0.01571 + 0.0, 0.8, 2.0, 0.374, 0.02036 + 0.0, 0.8, 4.0, 0.6077, 0.0302 + 0.0, 0.8, 6.0, 0.8414, 0.04673 + 0.0, 0.8, 8.0, 1.0751, 0.0715 + 0.0, 0.8, 10.0, 1.3089, 0.10604 + 0.0, 0.8, 12.0, 1.5426, 0.15187 + 0.0, 0.8, 14.0, 1.7763, 0.21052 + 0.0, 0.8, 15.4, 1.9399, 0.26004 + 0.0, 0.8, 15.4, 1.9399, 0.26004 + 0.0, 0.8, 15.4, 1.9399, 0.26004 + 0.0, 0.85, -2.0, -0.0984, 0.01517 + 0.0, 0.85, 0.0, 0.1476, 0.01631 + 0.0, 0.85, 2.0, 0.3936, 0.02441 + 0.0, 0.85, 4.0, 0.6396, 0.04125 + 0.0, 0.85, 6.0, 0.8855, 0.06862 + 0.0, 0.85, 8.0, 1.1315, 0.1083 + 0.0, 0.85, 10.0, 1.3775, 0.16207 + 0.0, 0.85, 12.0, 1.6235, 0.23172 + 0.0, 0.85, 14.0, 1.8695, 0.31903 + 0.0, 0.85, 14.5, 1.929, 0.34301 + 0.0, 0.85, 14.5, 1.929, 0.34301 + 0.0, 0.85, 14.5, 1.929, 0.34301 + 0.0, 0.9, -2.0, -0.1047, 0.01712 + 0.0, 0.9, 0.0, 0.1571, 0.02339 + 0.0, 0.9, 2.0, 0.4188, 0.04088 + 0.0, 0.9, 4.0, 0.6806, 0.07174 + 0.0, 0.9, 6.0, 0.9424, 0.11809 + 0.0, 0.9, 8.0, 1.2041, 0.18211 + 0.0, 0.9, 10.0, 1.4659, 0.26594 + 0.0, 0.9, 12.0, 1.7277, 0.37173 + 0.0, 0.9, 13.4, 1.9152, 0.46224 + 0.0, 0.9, 13.4, 1.9152, 0.46224 + 0.0, 0.9, 13.4, 1.9152, 0.46224 + 0.0, 0.9, 13.4, 1.9152, 0.46224 + 3000.0, 0.0, -2.0, -0.0715, 0.00363 + 3000.0, 0.0, 0.0, 0.1072, 0.00384 + 3000.0, 0.0, 2.0, 0.286, 0.00621 + 3000.0, 0.0, 4.0, 0.4647, 0.01072 + 3000.0, 0.0, 6.0, 0.6434, 0.01737 + 3000.0, 0.0, 8.0, 0.8222, 0.02618 + 3000.0, 0.0, 10.0, 1.0009, 0.03713 + 3000.0, 0.0, 12.0, 1.1797, 0.05023 + 3000.0, 0.0, 14.0, 1.3584, 0.06548 + 3000.0, 0.0, 16.0, 1.5371, 0.08287 + 3000.0, 0.0, 18.0, 1.7159, 0.10241 + 3000.0, 0.0, 20.0, 1.8946, 0.1241 + 3000.0, 0.2, -2.0, -0.0724, 0.01859 + 3000.0, 0.2, 0.0, 0.1086, 0.01885 + 3000.0, 0.2, 2.0, 0.2896, 0.0217 + 3000.0, 0.2, 4.0, 0.4706, 0.02715 + 3000.0, 0.2, 6.0, 0.6517, 0.03519 + 3000.0, 0.2, 8.0, 0.8327, 0.04582 + 3000.0, 0.2, 10.0, 1.0137, 0.05904 + 3000.0, 0.2, 12.0, 1.1947, 0.07485 + 3000.0, 0.2, 14.0, 1.3757, 0.09326 + 3000.0, 0.2, 16.0, 1.5568, 0.11426 + 3000.0, 0.2, 18.0, 1.7378, 0.13785 + 3000.0, 0.2, 20.0, 1.9188, 0.16404 + 3000.0, 0.4, -2.0, -0.0754, 0.01704 + 3000.0, 0.4, 0.0, 0.1131, 0.01732 + 3000.0, 0.4, 2.0, 0.3016, 0.02036 + 3000.0, 0.4, 4.0, 0.4901, 0.02617 + 3000.0, 0.4, 6.0, 0.6786, 0.03474 + 3000.0, 0.4, 8.0, 0.867, 0.04607 + 3000.0, 0.4, 10.0, 1.0555, 0.06017 + 3000.0, 0.4, 12.0, 1.244, 0.07703 + 3000.0, 0.4, 14.0, 1.4325, 0.09666 + 3000.0, 0.4, 16.0, 1.621, 0.11905 + 3000.0, 0.4, 18.0, 1.8095, 0.14421 + 3000.0, 0.4, 19.8, 1.982, 0.16966 + 3000.0, 0.5, -2.0, -0.0779, 0.01654 + 3000.0, 0.5, 0.0, 0.1169, 0.01683 + 3000.0, 0.5, 2.0, 0.3117, 0.02006 + 3000.0, 0.5, 4.0, 0.5065, 0.02623 + 3000.0, 0.5, 6.0, 0.7013, 0.03533 + 3000.0, 0.5, 8.0, 0.8961, 0.04737 + 3000.0, 0.5, 10.0, 1.0909, 0.06234 + 3000.0, 0.5, 12.0, 1.2857, 0.08025 + 3000.0, 0.5, 14.0, 1.4806, 0.10109 + 3000.0, 0.5, 16.0, 1.6754, 0.12487 + 3000.0, 0.5, 18.0, 1.8702, 0.15159 + 3000.0, 0.5, 19.1, 1.976, 0.16733 + 3000.0, 0.6, -2.0, -0.0814, 0.01612 + 3000.0, 0.6, 0.0, 0.1221, 0.01644 + 3000.0, 0.6, 2.0, 0.3257, 0.01994 + 3000.0, 0.6, 4.0, 0.5293, 0.02664 + 3000.0, 0.6, 6.0, 0.7329, 0.03653 + 3000.0, 0.6, 8.0, 0.9365, 0.04961 + 3000.0, 0.6, 10.0, 1.1401, 0.06587 + 3000.0, 0.6, 12.0, 1.3436, 0.08533 + 3000.0, 0.6, 14.0, 1.5472, 0.10797 + 3000.0, 0.6, 16.0, 1.7508, 0.13381 + 3000.0, 0.6, 18.0, 1.9544, 0.16289 + 3000.0, 0.6, 18.1, 1.9677, 0.16492 + 3000.0, 0.7, -2.0, -0.0863, 0.01575 + 3000.0, 0.7, 0.0, 0.1295, 0.01611 + 3000.0, 0.7, 2.0, 0.3454, 0.02003 + 3000.0, 0.7, 4.0, 0.5613, 0.02753 + 3000.0, 0.7, 6.0, 0.7771, 0.03859 + 3000.0, 0.7, 8.0, 0.993, 0.05322 + 3000.0, 0.7, 10.0, 1.2089, 0.07157 + 3000.0, 0.7, 12.0, 1.4247, 0.09458 + 3000.0, 0.7, 14.0, 1.6406, 0.12346 + 3000.0, 0.7, 16.0, 1.8565, 0.15942 + 3000.0, 0.7, 16.9, 1.9562, 0.17876 + 3000.0, 0.7, 16.9, 1.9562, 0.17876 + 3000.0, 0.75, -2.0, -0.0896, 0.01558 + 3000.0, 0.75, 0.0, 0.1343, 0.01597 + 3000.0, 0.75, 2.0, 0.3582, 0.02018 + 3000.0, 0.75, 4.0, 0.5822, 0.02822 + 3000.0, 0.75, 6.0, 0.8061, 0.04024 + 3000.0, 0.75, 8.0, 1.03, 0.05722 + 3000.0, 0.75, 10.0, 1.2539, 0.08052 + 3000.0, 0.75, 12.0, 1.4778, 0.11149 + 3000.0, 0.75, 14.0, 1.7017, 0.15146 + 3000.0, 0.75, 16.0, 1.9256, 0.20179 + 3000.0, 0.75, 16.2, 1.9488, 0.20767 + 3000.0, 0.75, 16.2, 1.9488, 0.20767 + 3000.0, 0.8, -2.0, -0.0935, 0.01543 + 3000.0, 0.8, 0.0, 0.1402, 0.01584 + 3000.0, 0.8, 2.0, 0.374, 0.0205 + 3000.0, 0.8, 4.0, 0.6077, 0.03034 + 3000.0, 0.8, 6.0, 0.8414, 0.0469 + 3000.0, 0.8, 8.0, 1.0751, 0.07169 + 3000.0, 0.8, 10.0, 1.3089, 0.10626 + 3000.0, 0.8, 12.0, 1.5426, 0.15212 + 3000.0, 0.8, 14.0, 1.7763, 0.21082 + 3000.0, 0.8, 15.4, 1.9399, 0.26036 + 3000.0, 0.8, 15.4, 1.9399, 0.26036 + 3000.0, 0.8, 15.4, 1.9399, 0.26036 + 3000.0, 0.85, -2.0, -0.0984, 0.0153 + 3000.0, 0.85, 0.0, 0.1476, 0.01644 + 3000.0, 0.85, 2.0, 0.3936, 0.02454 + 3000.0, 0.85, 4.0, 0.6396, 0.0414 + 3000.0, 0.85, 6.0, 0.8855, 0.06878 + 3000.0, 0.85, 8.0, 1.1315, 0.10849 + 3000.0, 0.85, 10.0, 1.3775, 0.16229 + 3000.0, 0.85, 12.0, 1.6235, 0.23198 + 3000.0, 0.85, 14.0, 1.8695, 0.31934 + 3000.0, 0.85, 14.5, 1.929, 0.34333 + 3000.0, 0.85, 14.5, 1.929, 0.34333 + 3000.0, 0.85, 14.5, 1.929, 0.34333 + 3000.0, 0.9, -2.0, -0.1047, 0.01724 + 3000.0, 0.9, 0.0, 0.1571, 0.02352 + 3000.0, 0.9, 2.0, 0.4188, 0.04102 + 3000.0, 0.9, 4.0, 0.6806, 0.07188 + 3000.0, 0.9, 6.0, 0.9424, 0.11826 + 3000.0, 0.9, 8.0, 1.2041, 0.18231 + 3000.0, 0.9, 10.0, 1.4659, 0.26617 + 3000.0, 0.9, 12.0, 1.7277, 0.372 + 3000.0, 0.9, 13.4, 1.9152, 0.46255 + 3000.0, 0.9, 13.4, 1.9152, 0.46255 + 3000.0, 0.9, 13.4, 1.9152, 0.46255 + 3000.0, 0.9, 13.4, 1.9152, 0.46255 + 6000.0, 0.0, -2.0, -0.0715, 0.00363 + 6000.0, 0.0, 0.0, 0.1072, 0.00384 + 6000.0, 0.0, 2.0, 0.286, 0.00621 + 6000.0, 0.0, 4.0, 0.4647, 0.01072 + 6000.0, 0.0, 6.0, 0.6434, 0.01737 + 6000.0, 0.0, 8.0, 0.8222, 0.02618 + 6000.0, 0.0, 10.0, 1.0009, 0.03713 + 6000.0, 0.0, 12.0, 1.1797, 0.05023 + 6000.0, 0.0, 14.0, 1.3584, 0.06548 + 6000.0, 0.0, 16.0, 1.5371, 0.08287 + 6000.0, 0.0, 18.0, 1.7159, 0.10241 + 6000.0, 0.0, 20.0, 1.8946, 0.1241 + 6000.0, 0.2, -2.0, -0.0724, 0.01878 + 6000.0, 0.2, 0.0, 0.1086, 0.01904 + 6000.0, 0.2, 2.0, 0.2896, 0.0219 + 6000.0, 0.2, 4.0, 0.4706, 0.02735 + 6000.0, 0.2, 6.0, 0.6517, 0.0354 + 6000.0, 0.2, 8.0, 0.8327, 0.04605 + 6000.0, 0.2, 10.0, 1.0137, 0.0593 + 6000.0, 0.2, 12.0, 1.1947, 0.07515 + 6000.0, 0.2, 14.0, 1.3757, 0.09359 + 6000.0, 0.2, 16.0, 1.5568, 0.11463 + 6000.0, 0.2, 18.0, 1.7378, 0.13827 + 6000.0, 0.2, 20.0, 1.9188, 0.1645 + 6000.0, 0.4, -2.0, -0.0754, 0.0172 + 6000.0, 0.4, 0.0, 0.1131, 0.01748 + 6000.0, 0.4, 2.0, 0.3016, 0.02053 + 6000.0, 0.4, 4.0, 0.4901, 0.02634 + 6000.0, 0.4, 6.0, 0.6786, 0.03493 + 6000.0, 0.4, 8.0, 0.867, 0.04628 + 6000.0, 0.4, 10.0, 1.0555, 0.0604 + 6000.0, 0.4, 12.0, 1.244, 0.07729 + 6000.0, 0.4, 14.0, 1.4325, 0.09695 + 6000.0, 0.4, 16.0, 1.621, 0.11938 + 6000.0, 0.4, 18.0, 1.8095, 0.14458 + 6000.0, 0.4, 19.8, 1.982, 0.17007 + 6000.0, 0.5, -2.0, -0.0779, 0.01669 + 6000.0, 0.5, 0.0, 0.1169, 0.01699 + 6000.0, 0.5, 2.0, 0.3117, 0.02022 + 6000.0, 0.5, 4.0, 0.5065, 0.0264 + 6000.0, 0.5, 6.0, 0.7013, 0.03551 + 6000.0, 0.5, 8.0, 0.8961, 0.04757 + 6000.0, 0.5, 10.0, 1.0909, 0.06256 + 6000.0, 0.5, 12.0, 1.2857, 0.0805 + 6000.0, 0.5, 14.0, 1.4806, 0.10138 + 6000.0, 0.5, 16.0, 1.6754, 0.1252 + 6000.0, 0.5, 18.0, 1.8702, 0.15195 + 6000.0, 0.5, 19.1, 1.976, 0.16772 + 6000.0, 0.6, -2.0, -0.0814, 0.01626 + 6000.0, 0.6, 0.0, 0.1221, 0.01658 + 6000.0, 0.6, 2.0, 0.3257, 0.0201 + 6000.0, 0.6, 4.0, 0.5293, 0.0268 + 6000.0, 0.6, 6.0, 0.7329, 0.03671 + 6000.0, 0.6, 8.0, 0.9365, 0.0498 + 6000.0, 0.6, 10.0, 1.1401, 0.06609 + 6000.0, 0.6, 12.0, 1.3436, 0.08558 + 6000.0, 0.6, 14.0, 1.5472, 0.10826 + 6000.0, 0.6, 16.0, 1.7508, 0.13413 + 6000.0, 0.6, 18.0, 1.9544, 0.16326 + 6000.0, 0.6, 18.1, 1.9677, 0.16529 + 6000.0, 0.7, -2.0, -0.0863, 0.01589 + 6000.0, 0.7, 0.0, 0.1295, 0.01625 + 6000.0, 0.7, 2.0, 0.3454, 0.02018 + 6000.0, 0.7, 4.0, 0.5613, 0.02768 + 6000.0, 0.7, 6.0, 0.7771, 0.03876 + 6000.0, 0.7, 8.0, 0.993, 0.05342 + 6000.0, 0.7, 10.0, 1.2089, 0.07179 + 6000.0, 0.7, 12.0, 1.4247, 0.09484 + 6000.0, 0.7, 14.0, 1.6406, 0.12376 + 6000.0, 0.7, 16.0, 1.8565, 0.15975 + 6000.0, 0.7, 16.9, 1.9562, 0.17911 + 6000.0, 0.7, 16.9, 1.9562, 0.17911 + 6000.0, 0.75, -2.0, -0.0896, 0.01572 + 6000.0, 0.75, 0.0, 0.1343, 0.0161 + 6000.0, 0.75, 2.0, 0.3582, 0.02032 + 6000.0, 0.75, 4.0, 0.5822, 0.02838 + 6000.0, 0.75, 6.0, 0.8061, 0.04041 + 6000.0, 0.75, 8.0, 1.03, 0.05742 + 6000.0, 0.75, 10.0, 1.2539, 0.08075 + 6000.0, 0.75, 12.0, 1.4778, 0.11175 + 6000.0, 0.75, 14.0, 1.7017, 0.15176 + 6000.0, 0.75, 16.0, 1.9256, 0.20213 + 6000.0, 0.75, 16.2, 1.9488, 0.20801 + 6000.0, 0.75, 16.2, 1.9488, 0.20801 + 6000.0, 0.8, -2.0, -0.0935, 0.01556 + 6000.0, 0.8, 0.0, 0.1402, 0.01598 + 6000.0, 0.8, 2.0, 0.374, 0.02064 + 6000.0, 0.8, 4.0, 0.6077, 0.0305 + 6000.0, 0.8, 6.0, 0.8414, 0.04707 + 6000.0, 0.8, 8.0, 1.0751, 0.07189 + 6000.0, 0.8, 10.0, 1.3089, 0.10649 + 6000.0, 0.8, 12.0, 1.5426, 0.15239 + 6000.0, 0.8, 14.0, 1.7763, 0.21112 + 6000.0, 0.8, 15.4, 1.9399, 0.2607 + 6000.0, 0.8, 15.4, 1.9399, 0.2607 + 6000.0, 0.8, 15.4, 1.9399, 0.2607 + 6000.0, 0.85, -2.0, -0.0984, 0.01543 + 6000.0, 0.85, 0.0, 0.1476, 0.01657 + 6000.0, 0.85, 2.0, 0.3936, 0.02468 + 6000.0, 0.85, 4.0, 0.6396, 0.04155 + 6000.0, 0.85, 6.0, 0.8855, 0.06896 + 6000.0, 0.85, 8.0, 1.1315, 0.10869 + 6000.0, 0.85, 10.0, 1.3775, 0.16253 + 6000.0, 0.85, 12.0, 1.6235, 0.23225 + 6000.0, 0.85, 14.0, 1.8695, 0.31966 + 6000.0, 0.85, 14.5, 1.929, 0.34366 + 6000.0, 0.85, 14.5, 1.929, 0.34366 + 6000.0, 0.85, 14.5, 1.929, 0.34366 + 6000.0, 0.9, -2.0, -0.1047, 0.01737 + 6000.0, 0.9, 0.0, 0.1571, 0.02365 + 6000.0, 0.9, 2.0, 0.4188, 0.04116 + 6000.0, 0.9, 4.0, 0.6806, 0.07204 + 6000.0, 0.9, 6.0, 0.9424, 0.11844 + 6000.0, 0.9, 8.0, 1.2041, 0.18252 + 6000.0, 0.9, 10.0, 1.4659, 0.26642 + 6000.0, 0.9, 12.0, 1.7277, 0.37229 + 6000.0, 0.9, 13.4, 1.9152, 0.46287 + 6000.0, 0.9, 13.4, 1.9152, 0.46287 + 6000.0, 0.9, 13.4, 1.9152, 0.46287 + 6000.0, 0.9, 13.4, 1.9152, 0.46287 + 9000.0, 0.0, -2.0, -0.0715, 0.00363 + 9000.0, 0.0, 0.0, 0.1072, 0.00384 + 9000.0, 0.0, 2.0, 0.286, 0.00621 + 9000.0, 0.0, 4.0, 0.4647, 0.01072 + 9000.0, 0.0, 6.0, 0.6434, 0.01737 + 9000.0, 0.0, 8.0, 0.8222, 0.02618 + 9000.0, 0.0, 10.0, 1.0009, 0.03713 + 9000.0, 0.0, 12.0, 1.1797, 0.05023 + 9000.0, 0.0, 14.0, 1.3584, 0.06548 + 9000.0, 0.0, 16.0, 1.5371, 0.08287 + 9000.0, 0.0, 18.0, 1.7159, 0.10241 + 9000.0, 0.0, 20.0, 1.8946, 0.1241 + 9000.0, 0.2, -2.0, -0.0724, 0.01898 + 9000.0, 0.2, 0.0, 0.1086, 0.01924 + 9000.0, 0.2, 2.0, 0.2896, 0.0221 + 9000.0, 0.2, 4.0, 0.4706, 0.02756 + 9000.0, 0.2, 6.0, 0.6517, 0.03563 + 9000.0, 0.2, 8.0, 0.8327, 0.0463 + 9000.0, 0.2, 10.0, 1.0137, 0.05958 + 9000.0, 0.2, 12.0, 1.1947, 0.07545 + 9000.0, 0.2, 14.0, 1.3757, 0.09393 + 9000.0, 0.2, 16.0, 1.5568, 0.11501 + 9000.0, 0.2, 18.0, 1.7378, 0.13869 + 9000.0, 0.2, 20.0, 1.9188, 0.16498 + 9000.0, 0.4, -2.0, -0.0754, 0.01737 + 9000.0, 0.4, 0.0, 0.1131, 0.01765 + 9000.0, 0.4, 2.0, 0.3016, 0.0207 + 9000.0, 0.4, 4.0, 0.4901, 0.02653 + 9000.0, 0.4, 6.0, 0.6786, 0.03512 + 9000.0, 0.4, 8.0, 0.867, 0.0465 + 9000.0, 0.4, 10.0, 1.0555, 0.06064 + 9000.0, 0.4, 12.0, 1.244, 0.07756 + 9000.0, 0.4, 14.0, 1.4325, 0.09726 + 9000.0, 0.4, 16.0, 1.621, 0.11973 + 9000.0, 0.4, 18.0, 1.8095, 0.14497 + 9000.0, 0.4, 19.8, 1.982, 0.1705 + 9000.0, 0.5, -2.0, -0.0779, 0.01685 + 9000.0, 0.5, 0.0, 0.1169, 0.01715 + 9000.0, 0.5, 2.0, 0.3117, 0.02039 + 9000.0, 0.5, 4.0, 0.5065, 0.02657 + 9000.0, 0.5, 6.0, 0.7013, 0.0357 + 9000.0, 0.5, 8.0, 0.8961, 0.04778 + 9000.0, 0.5, 10.0, 1.0909, 0.0628 + 9000.0, 0.5, 12.0, 1.2857, 0.08076 + 9000.0, 0.5, 14.0, 1.4806, 0.10168 + 9000.0, 0.5, 16.0, 1.6754, 0.12553 + 9000.0, 0.5, 18.0, 1.8702, 0.15233 + 9000.0, 0.5, 19.1, 1.976, 0.16812 + 9000.0, 0.6, -2.0, -0.0814, 0.01641 + 9000.0, 0.6, 0.0, 0.1221, 0.01673 + 9000.0, 0.6, 2.0, 0.3257, 0.02025 + 9000.0, 0.6, 4.0, 0.5293, 0.02697 + 9000.0, 0.6, 6.0, 0.7329, 0.03689 + 9000.0, 0.6, 8.0, 0.9365, 0.05001 + 9000.0, 0.6, 10.0, 1.1401, 0.06632 + 9000.0, 0.6, 12.0, 1.3436, 0.08584 + 9000.0, 0.6, 14.0, 1.5472, 0.10855 + 9000.0, 0.6, 16.0, 1.7508, 0.13447 + 9000.0, 0.6, 18.0, 1.9544, 0.16365 + 9000.0, 0.6, 18.1, 1.9677, 0.16568 + 9000.0, 0.7, -2.0, -0.0863, 0.01603 + 9000.0, 0.7, 0.0, 0.1295, 0.01639 + 9000.0, 0.7, 2.0, 0.3454, 0.02033 + 9000.0, 0.7, 4.0, 0.5613, 0.02785 + 9000.0, 0.7, 6.0, 0.7771, 0.03894 + 9000.0, 0.7, 8.0, 0.993, 0.05362 + 9000.0, 0.7, 10.0, 1.2089, 0.07202 + 9000.0, 0.7, 12.0, 1.4247, 0.0951 + 9000.0, 0.7, 14.0, 1.6406, 0.12406 + 9000.0, 0.7, 16.0, 1.8565, 0.1601 + 9000.0, 0.7, 16.9, 1.9562, 0.17948 + 9000.0, 0.7, 16.9, 1.9562, 0.17948 + 9000.0, 0.75, -2.0, -0.0896, 0.01586 + 9000.0, 0.75, 0.0, 0.1343, 0.01625 + 9000.0, 0.75, 2.0, 0.3582, 0.02047 + 9000.0, 0.75, 4.0, 0.5822, 0.02854 + 9000.0, 0.75, 6.0, 0.8061, 0.04059 + 9000.0, 0.75, 8.0, 1.03, 0.05762 + 9000.0, 0.75, 10.0, 1.2539, 0.08098 + 9000.0, 0.75, 12.0, 1.4778, 0.11201 + 9000.0, 0.75, 14.0, 1.7017, 0.15207 + 9000.0, 0.75, 16.0, 1.9256, 0.20249 + 9000.0, 0.75, 16.2, 1.9488, 0.20837 + 9000.0, 0.75, 16.2, 1.9488, 0.20837 + 9000.0, 0.8, -2.0, -0.0935, 0.0157 + 9000.0, 0.8, 0.0, 0.1402, 0.01612 + 9000.0, 0.8, 2.0, 0.374, 0.02079 + 9000.0, 0.8, 4.0, 0.6077, 0.03066 + 9000.0, 0.8, 6.0, 0.8414, 0.04725 + 9000.0, 0.8, 8.0, 1.0751, 0.0721 + 9000.0, 0.8, 10.0, 1.3089, 0.10672 + 9000.0, 0.8, 12.0, 1.5426, 0.15266 + 9000.0, 0.8, 14.0, 1.7763, 0.21144 + 9000.0, 0.8, 15.4, 1.9399, 0.26105 + 9000.0, 0.8, 15.4, 1.9399, 0.26105 + 9000.0, 0.8, 15.4, 1.9399, 0.26105 + 9000.0, 0.85, -2.0, -0.0984, 0.01557 + 9000.0, 0.85, 0.0, 0.1476, 0.01671 + 9000.0, 0.85, 2.0, 0.3936, 0.02483 + 9000.0, 0.85, 4.0, 0.6396, 0.04171 + 9000.0, 0.85, 6.0, 0.8855, 0.06914 + 9000.0, 0.85, 8.0, 1.1315, 0.1089 + 9000.0, 0.85, 10.0, 1.3775, 0.16277 + 9000.0, 0.85, 12.0, 1.6235, 0.23254 + 9000.0, 0.85, 14.0, 1.8695, 0.31999 + 9000.0, 0.85, 14.5, 1.929, 0.344 + 9000.0, 0.85, 14.5, 1.929, 0.344 + 9000.0, 0.85, 14.5, 1.929, 0.344 + 9000.0, 0.9, -2.0, -0.1047, 0.01751 + 9000.0, 0.9, 0.0, 0.1571, 0.02379 + 9000.0, 0.9, 2.0, 0.4188, 0.0413 + 9000.0, 0.9, 4.0, 0.6806, 0.0722 + 9000.0, 0.9, 6.0, 0.9424, 0.11862 + 9000.0, 0.9, 8.0, 1.2041, 0.18273 + 9000.0, 0.9, 10.0, 1.4659, 0.26667 + 9000.0, 0.9, 12.0, 1.7277, 0.37258 + 9000.0, 0.9, 13.4, 1.9152, 0.4632 + 9000.0, 0.9, 13.4, 1.9152, 0.4632 + 9000.0, 0.9, 13.4, 1.9152, 0.4632 + 9000.0, 0.9, 13.4, 1.9152, 0.4632 + 12000.0, 0.0, -2.0, -0.0715, 0.00363 + 12000.0, 0.0, 0.0, 0.1072, 0.00384 + 12000.0, 0.0, 2.0, 0.286, 0.00621 + 12000.0, 0.0, 4.0, 0.4647, 0.01072 + 12000.0, 0.0, 6.0, 0.6434, 0.01737 + 12000.0, 0.0, 8.0, 0.8222, 0.02618 + 12000.0, 0.0, 10.0, 1.0009, 0.03713 + 12000.0, 0.0, 12.0, 1.1797, 0.05023 + 12000.0, 0.0, 14.0, 1.3584, 0.06548 + 12000.0, 0.0, 16.0, 1.5371, 0.08287 + 12000.0, 0.0, 18.0, 1.7159, 0.10241 + 12000.0, 0.0, 20.0, 1.8946, 0.1241 + 12000.0, 0.2, -2.0, -0.0724, 0.01918 + 12000.0, 0.2, 0.0, 0.1086, 0.01944 + 12000.0, 0.2, 2.0, 0.2896, 0.02231 + 12000.0, 0.2, 4.0, 0.4706, 0.02778 + 12000.0, 0.2, 6.0, 0.6517, 0.03587 + 12000.0, 0.2, 8.0, 0.8327, 0.04656 + 12000.0, 0.2, 10.0, 1.0137, 0.05986 + 12000.0, 0.2, 12.0, 1.1947, 0.07577 + 12000.0, 0.2, 14.0, 1.3757, 0.09428 + 12000.0, 0.2, 16.0, 1.5568, 0.11541 + 12000.0, 0.2, 18.0, 1.7378, 0.13914 + 12000.0, 0.2, 20.0, 1.9188, 0.16548 + 12000.0, 0.4, -2.0, -0.0754, 0.01755 + 12000.0, 0.4, 0.0, 0.1131, 0.01782 + 12000.0, 0.4, 2.0, 0.3016, 0.02088 + 12000.0, 0.4, 4.0, 0.4901, 0.02672 + 12000.0, 0.4, 6.0, 0.6786, 0.03533 + 12000.0, 0.4, 8.0, 0.867, 0.04672 + 12000.0, 0.4, 10.0, 1.0555, 0.06089 + 12000.0, 0.4, 12.0, 1.244, 0.07784 + 12000.0, 0.4, 14.0, 1.4325, 0.09757 + 12000.0, 0.4, 16.0, 1.621, 0.12008 + 12000.0, 0.4, 18.0, 1.8095, 0.14537 + 12000.0, 0.4, 19.8, 1.982, 0.17095 + 12000.0, 0.5, -2.0, -0.0779, 0.01702 + 12000.0, 0.5, 0.0, 0.1169, 0.01731 + 12000.0, 0.5, 2.0, 0.3117, 0.02056 + 12000.0, 0.5, 4.0, 0.5065, 0.02675 + 12000.0, 0.5, 6.0, 0.7013, 0.0359 + 12000.0, 0.5, 8.0, 0.8961, 0.04799 + 12000.0, 0.5, 10.0, 1.0909, 0.06304 + 12000.0, 0.5, 12.0, 1.2857, 0.08104 + 12000.0, 0.5, 14.0, 1.4806, 0.10198 + 12000.0, 0.5, 16.0, 1.6754, 0.12588 + 12000.0, 0.5, 18.0, 1.8702, 0.15273 + 12000.0, 0.5, 19.1, 1.976, 0.16854 + 12000.0, 0.6, -2.0, -0.0814, 0.01657 + 12000.0, 0.6, 0.0, 0.1221, 0.01689 + 12000.0, 0.6, 2.0, 0.3257, 0.02042 + 12000.0, 0.6, 4.0, 0.5293, 0.02715 + 12000.0, 0.6, 6.0, 0.7329, 0.03708 + 12000.0, 0.6, 8.0, 0.9365, 0.05022 + 12000.0, 0.6, 10.0, 1.1401, 0.06656 + 12000.0, 0.6, 12.0, 1.3436, 0.08611 + 12000.0, 0.6, 14.0, 1.5472, 0.10886 + 12000.0, 0.6, 16.0, 1.7508, 0.13482 + 12000.0, 0.6, 18.0, 1.9544, 0.16404 + 12000.0, 0.6, 18.1, 1.9677, 0.16608 + 12000.0, 0.7, -2.0, -0.0863, 0.01619 + 12000.0, 0.7, 0.0, 0.1295, 0.01654 + 12000.0, 0.7, 2.0, 0.3454, 0.02049 + 12000.0, 0.7, 4.0, 0.5613, 0.02802 + 12000.0, 0.7, 6.0, 0.7771, 0.03913 + 12000.0, 0.7, 8.0, 0.993, 0.05383 + 12000.0, 0.7, 10.0, 1.2089, 0.07226 + 12000.0, 0.7, 12.0, 1.4247, 0.09537 + 12000.0, 0.7, 14.0, 1.6406, 0.12437 + 12000.0, 0.7, 16.0, 1.8565, 0.16046 + 12000.0, 0.7, 16.9, 1.9562, 0.17986 + 12000.0, 0.7, 16.9, 1.9562, 0.17986 + 12000.0, 0.75, -2.0, -0.0896, 0.01601 + 12000.0, 0.75, 0.0, 0.1343, 0.0164 + 12000.0, 0.75, 2.0, 0.3582, 0.02063 + 12000.0, 0.75, 4.0, 0.5822, 0.02871 + 12000.0, 0.75, 6.0, 0.8061, 0.04077 + 12000.0, 0.75, 8.0, 1.03, 0.05783 + 12000.0, 0.75, 10.0, 1.2539, 0.08122 + 12000.0, 0.75, 12.0, 1.4778, 0.11229 + 12000.0, 0.75, 14.0, 1.7017, 0.15239 + 12000.0, 0.75, 16.0, 1.9256, 0.20285 + 12000.0, 0.75, 16.2, 1.9488, 0.20874 + 12000.0, 0.75, 16.2, 1.9488, 0.20874 + 12000.0, 0.8, -2.0, -0.0935, 0.01585 + 12000.0, 0.8, 0.0, 0.1402, 0.01627 + 12000.0, 0.8, 2.0, 0.374, 0.02094 + 12000.0, 0.8, 4.0, 0.6077, 0.03083 + 12000.0, 0.8, 6.0, 0.8414, 0.04744 + 12000.0, 0.8, 8.0, 1.0751, 0.07231 + 12000.0, 0.8, 10.0, 1.3089, 0.10697 + 12000.0, 0.8, 12.0, 1.5426, 0.15294 + 12000.0, 0.8, 14.0, 1.7763, 0.21177 + 12000.0, 0.8, 15.4, 1.9399, 0.26141 + 12000.0, 0.8, 15.4, 1.9399, 0.26141 + 12000.0, 0.8, 15.4, 1.9399, 0.26141 + 12000.0, 0.85, -2.0, -0.0984, 0.01571 + 12000.0, 0.85, 0.0, 0.1476, 0.01685 + 12000.0, 0.85, 2.0, 0.3936, 0.02498 + 12000.0, 0.85, 4.0, 0.6396, 0.04188 + 12000.0, 0.85, 6.0, 0.8855, 0.06933 + 12000.0, 0.85, 8.0, 1.1315, 0.10911 + 12000.0, 0.85, 10.0, 1.3775, 0.16302 + 12000.0, 0.85, 12.0, 1.6235, 0.23283 + 12000.0, 0.85, 14.0, 1.8695, 0.32033 + 12000.0, 0.85, 14.5, 1.929, 0.34436 + 12000.0, 0.85, 14.5, 1.929, 0.34436 + 12000.0, 0.85, 14.5, 1.929, 0.34436 + 12000.0, 0.9, -2.0, -0.1047, 0.01765 + 12000.0, 0.9, 0.0, 0.1571, 0.02393 + 12000.0, 0.9, 2.0, 0.4188, 0.04145 + 12000.0, 0.9, 4.0, 0.6806, 0.07236 + 12000.0, 0.9, 6.0, 0.9424, 0.11881 + 12000.0, 0.9, 8.0, 1.2041, 0.18295 + 12000.0, 0.9, 10.0, 1.4659, 0.26693 + 12000.0, 0.9, 12.0, 1.7277, 0.37289 + 12000.0, 0.9, 13.4, 1.9152, 0.46355 + 12000.0, 0.9, 13.4, 1.9152, 0.46355 + 12000.0, 0.9, 13.4, 1.9152, 0.46355 + 12000.0, 0.9, 13.4, 1.9152, 0.46355 + 15000.0, 0.0, -2.0, -0.0715, 0.00363 + 15000.0, 0.0, 0.0, 0.1072, 0.00384 + 15000.0, 0.0, 2.0, 0.286, 0.00621 + 15000.0, 0.0, 4.0, 0.4647, 0.01072 + 15000.0, 0.0, 6.0, 0.6434, 0.01737 + 15000.0, 0.0, 8.0, 0.8222, 0.02618 + 15000.0, 0.0, 10.0, 1.0009, 0.03713 + 15000.0, 0.0, 12.0, 1.1797, 0.05023 + 15000.0, 0.0, 14.0, 1.3584, 0.06548 + 15000.0, 0.0, 16.0, 1.5371, 0.08287 + 15000.0, 0.0, 18.0, 1.7159, 0.10241 + 15000.0, 0.0, 20.0, 1.8946, 0.1241 + 15000.0, 0.2, -2.0, -0.0724, 0.01939 + 15000.0, 0.2, 0.0, 0.1086, 0.01965 + 15000.0, 0.2, 2.0, 0.2896, 0.02252 + 15000.0, 0.2, 4.0, 0.4706, 0.02801 + 15000.0, 0.2, 6.0, 0.6517, 0.03611 + 15000.0, 0.2, 8.0, 0.8327, 0.04683 + 15000.0, 0.2, 10.0, 1.0137, 0.06016 + 15000.0, 0.2, 12.0, 1.1947, 0.0761 + 15000.0, 0.2, 14.0, 1.3757, 0.09465 + 15000.0, 0.2, 16.0, 1.5568, 0.11582 + 15000.0, 0.2, 18.0, 1.7378, 0.1396 + 15000.0, 0.2, 20.0, 1.9188, 0.166 + 15000.0, 0.4, -2.0, -0.0754, 0.01773 + 15000.0, 0.4, 0.0, 0.1131, 0.018 + 15000.0, 0.4, 2.0, 0.3016, 0.02107 + 15000.0, 0.4, 4.0, 0.4901, 0.02691 + 15000.0, 0.4, 6.0, 0.6786, 0.03554 + 15000.0, 0.4, 8.0, 0.867, 0.04696 + 15000.0, 0.4, 10.0, 1.0555, 0.06115 + 15000.0, 0.4, 12.0, 1.244, 0.07814 + 15000.0, 0.4, 14.0, 1.4325, 0.0979 + 15000.0, 0.4, 16.0, 1.621, 0.12045 + 15000.0, 0.4, 18.0, 1.8095, 0.14579 + 15000.0, 0.4, 19.8, 1.982, 0.17141 + 15000.0, 0.5, -2.0, -0.0779, 0.01719 + 15000.0, 0.5, 0.0, 0.1169, 0.01748 + 15000.0, 0.5, 2.0, 0.3117, 0.02073 + 15000.0, 0.5, 4.0, 0.5065, 0.02694 + 15000.0, 0.5, 6.0, 0.7013, 0.0361 + 15000.0, 0.5, 8.0, 0.8961, 0.04822 + 15000.0, 0.5, 10.0, 1.0909, 0.06329 + 15000.0, 0.5, 12.0, 1.2857, 0.08132 + 15000.0, 0.5, 14.0, 1.4806, 0.10231 + 15000.0, 0.5, 16.0, 1.6754, 0.12624 + 15000.0, 0.5, 18.0, 1.8702, 0.15314 + 15000.0, 0.5, 19.1, 1.976, 0.16898 + 15000.0, 0.6, -2.0, -0.0814, 0.01674 + 15000.0, 0.6, 0.0, 0.1221, 0.01706 + 15000.0, 0.6, 2.0, 0.3257, 0.02059 + 15000.0, 0.6, 4.0, 0.5293, 0.02733 + 15000.0, 0.6, 6.0, 0.7329, 0.03728 + 15000.0, 0.6, 8.0, 0.9365, 0.05044 + 15000.0, 0.6, 10.0, 1.1401, 0.06681 + 15000.0, 0.6, 12.0, 1.3436, 0.08639 + 15000.0, 0.6, 14.0, 1.5472, 0.10918 + 15000.0, 0.6, 16.0, 1.7508, 0.13518 + 15000.0, 0.6, 18.0, 1.9544, 0.16446 + 15000.0, 0.6, 18.1, 1.9677, 0.16649 + 15000.0, 0.7, -2.0, -0.0863, 0.01634 + 15000.0, 0.7, 0.0, 0.1295, 0.0167 + 15000.0, 0.7, 2.0, 0.3454, 0.02065 + 15000.0, 0.7, 4.0, 0.5613, 0.02819 + 15000.0, 0.7, 6.0, 0.7771, 0.03932 + 15000.0, 0.7, 8.0, 0.993, 0.05405 + 15000.0, 0.7, 10.0, 1.2089, 0.07251 + 15000.0, 0.7, 12.0, 1.4247, 0.09566 + 15000.0, 0.7, 14.0, 1.6406, 0.1247 + 15000.0, 0.7, 16.0, 1.8565, 0.16083 + 15000.0, 0.7, 16.9, 1.9562, 0.18026 + 15000.0, 0.7, 16.9, 1.9562, 0.18026 + 15000.0, 0.75, -2.0, -0.0896, 0.01617 + 15000.0, 0.75, 0.0, 0.1343, 0.01655 + 15000.0, 0.75, 2.0, 0.3582, 0.02079 + 15000.0, 0.75, 4.0, 0.5822, 0.02888 + 15000.0, 0.75, 6.0, 0.8061, 0.04097 + 15000.0, 0.75, 8.0, 1.03, 0.05805 + 15000.0, 0.75, 10.0, 1.2539, 0.08147 + 15000.0, 0.75, 12.0, 1.4778, 0.11258 + 15000.0, 0.75, 14.0, 1.7017, 0.15272 + 15000.0, 0.75, 16.0, 1.9256, 0.20324 + 15000.0, 0.75, 16.2, 1.9488, 0.20913 + 15000.0, 0.75, 16.2, 1.9488, 0.20913 + 15000.0, 0.8, -2.0, -0.0935, 0.016 + 15000.0, 0.8, 0.0, 0.1402, 0.01642 + 15000.0, 0.8, 2.0, 0.374, 0.0211 + 15000.0, 0.8, 4.0, 0.6077, 0.031 + 15000.0, 0.8, 6.0, 0.8414, 0.04763 + 15000.0, 0.8, 8.0, 1.0751, 0.07253 + 15000.0, 0.8, 10.0, 1.3089, 0.10722 + 15000.0, 0.8, 12.0, 1.5426, 0.15324 + 15000.0, 0.8, 14.0, 1.7763, 0.21211 + 15000.0, 0.8, 15.4, 1.9399, 0.26179 + 15000.0, 0.8, 15.4, 1.9399, 0.26179 + 15000.0, 0.8, 15.4, 1.9399, 0.26179 + 15000.0, 0.85, -2.0, -0.0984, 0.01586 + 15000.0, 0.85, 0.0, 0.1476, 0.017 + 15000.0, 0.85, 2.0, 0.3936, 0.02514 + 15000.0, 0.85, 4.0, 0.6396, 0.04205 + 15000.0, 0.85, 6.0, 0.8855, 0.06952 + 15000.0, 0.85, 8.0, 1.1315, 0.10934 + 15000.0, 0.85, 10.0, 1.3775, 0.16328 + 15000.0, 0.85, 12.0, 1.6235, 0.23313 + 15000.0, 0.85, 14.0, 1.8695, 0.32068 + 15000.0, 0.85, 14.5, 1.929, 0.34473 + 15000.0, 0.85, 14.5, 1.929, 0.34473 + 15000.0, 0.85, 14.5, 1.929, 0.34473 + 15000.0, 0.9, -2.0, -0.1047, 0.01779 + 15000.0, 0.9, 0.0, 0.1571, 0.02408 + 15000.0, 0.9, 2.0, 0.4188, 0.04161 + 15000.0, 0.9, 4.0, 0.6806, 0.07254 + 15000.0, 0.9, 6.0, 0.9424, 0.11901 + 15000.0, 0.9, 8.0, 1.2041, 0.18318 + 15000.0, 0.9, 10.0, 1.4659, 0.2672 + 15000.0, 0.9, 12.0, 1.7277, 0.37321 + 15000.0, 0.9, 13.4, 1.9152, 0.46391 + 15000.0, 0.9, 13.4, 1.9152, 0.46391 + 15000.0, 0.9, 13.4, 1.9152, 0.46391 + 15000.0, 0.9, 13.4, 1.9152, 0.46391 + 18000.0, 0.0, -2.0, -0.0715, 0.00363 + 18000.0, 0.0, 0.0, 0.1072, 0.00384 + 18000.0, 0.0, 2.0, 0.286, 0.00621 + 18000.0, 0.0, 4.0, 0.4647, 0.01072 + 18000.0, 0.0, 6.0, 0.6434, 0.01737 + 18000.0, 0.0, 8.0, 0.8222, 0.02618 + 18000.0, 0.0, 10.0, 1.0009, 0.03713 + 18000.0, 0.0, 12.0, 1.1797, 0.05023 + 18000.0, 0.0, 14.0, 1.3584, 0.06548 + 18000.0, 0.0, 16.0, 1.5371, 0.08287 + 18000.0, 0.0, 18.0, 1.7159, 0.10241 + 18000.0, 0.0, 20.0, 1.8946, 0.1241 + 18000.0, 0.2, -2.0, -0.0724, 0.01961 + 18000.0, 0.2, 0.0, 0.1086, 0.01987 + 18000.0, 0.2, 2.0, 0.2896, 0.02275 + 18000.0, 0.2, 4.0, 0.4706, 0.02825 + 18000.0, 0.2, 6.0, 0.6517, 0.03637 + 18000.0, 0.2, 8.0, 0.8327, 0.04711 + 18000.0, 0.2, 10.0, 1.0137, 0.06046 + 18000.0, 0.2, 12.0, 1.1947, 0.07644 + 18000.0, 0.2, 14.0, 1.3757, 0.09504 + 18000.0, 0.2, 16.0, 1.5568, 0.11625 + 18000.0, 0.2, 18.0, 1.7378, 0.14009 + 18000.0, 0.2, 20.0, 1.9188, 0.16654 + 18000.0, 0.4, -2.0, -0.0754, 0.01791 + 18000.0, 0.4, 0.0, 0.1131, 0.01819 + 18000.0, 0.4, 2.0, 0.3016, 0.02126 + 18000.0, 0.4, 4.0, 0.4901, 0.02712 + 18000.0, 0.4, 6.0, 0.6786, 0.03576 + 18000.0, 0.4, 8.0, 0.867, 0.0472 + 18000.0, 0.4, 10.0, 1.0555, 0.06143 + 18000.0, 0.4, 12.0, 1.244, 0.07844 + 18000.0, 0.4, 14.0, 1.4325, 0.09824 + 18000.0, 0.4, 16.0, 1.621, 0.12084 + 18000.0, 0.4, 18.0, 1.8095, 0.14622 + 18000.0, 0.4, 19.8, 1.982, 0.17189 + 18000.0, 0.5, -2.0, -0.0779, 0.01737 + 18000.0, 0.5, 0.0, 0.1169, 0.01766 + 18000.0, 0.5, 2.0, 0.3117, 0.02092 + 18000.0, 0.5, 4.0, 0.5065, 0.02714 + 18000.0, 0.5, 6.0, 0.7013, 0.03632 + 18000.0, 0.5, 8.0, 0.8961, 0.04846 + 18000.0, 0.5, 10.0, 1.0909, 0.06356 + 18000.0, 0.5, 12.0, 1.2857, 0.08162 + 18000.0, 0.5, 14.0, 1.4806, 0.10264 + 18000.0, 0.5, 16.0, 1.6754, 0.12662 + 18000.0, 0.5, 18.0, 1.8702, 0.15357 + 18000.0, 0.5, 19.1, 1.976, 0.16944 + 18000.0, 0.6, -2.0, -0.0814, 0.01691 + 18000.0, 0.6, 0.0, 0.1221, 0.01723 + 18000.0, 0.6, 2.0, 0.3257, 0.02077 + 18000.0, 0.6, 4.0, 0.5293, 0.02752 + 18000.0, 0.6, 6.0, 0.7329, 0.03749 + 18000.0, 0.6, 8.0, 0.9365, 0.05067 + 18000.0, 0.6, 10.0, 1.1401, 0.06707 + 18000.0, 0.6, 12.0, 1.3436, 0.08668 + 18000.0, 0.6, 14.0, 1.5472, 0.10951 + 18000.0, 0.6, 16.0, 1.7508, 0.13556 + 18000.0, 0.6, 18.0, 1.9544, 0.16489 + 18000.0, 0.6, 18.1, 1.9677, 0.16693 + 18000.0, 0.7, -2.0, -0.0863, 0.01651 + 18000.0, 0.7, 0.0, 0.1295, 0.01687 + 18000.0, 0.7, 2.0, 0.3454, 0.02082 + 18000.0, 0.7, 4.0, 0.5613, 0.02838 + 18000.0, 0.7, 6.0, 0.7771, 0.03953 + 18000.0, 0.7, 8.0, 0.993, 0.05427 + 18000.0, 0.7, 10.0, 1.2089, 0.07277 + 18000.0, 0.7, 12.0, 1.4247, 0.09595 + 18000.0, 0.7, 14.0, 1.6406, 0.12503 + 18000.0, 0.7, 16.0, 1.8565, 0.16122 + 18000.0, 0.7, 16.9, 1.9562, 0.18067 + 18000.0, 0.7, 16.9, 1.9562, 0.18067 + 18000.0, 0.75, -2.0, -0.0896, 0.01633 + 18000.0, 0.75, 0.0, 0.1343, 0.01671 + 18000.0, 0.75, 2.0, 0.3582, 0.02096 + 18000.0, 0.75, 4.0, 0.5822, 0.02907 + 18000.0, 0.75, 6.0, 0.8061, 0.04117 + 18000.0, 0.75, 8.0, 1.03, 0.05828 + 18000.0, 0.75, 10.0, 1.2539, 0.08173 + 18000.0, 0.75, 12.0, 1.4778, 0.11288 + 18000.0, 0.75, 14.0, 1.7017, 0.15306 + 18000.0, 0.75, 16.0, 1.9256, 0.20363 + 18000.0, 0.75, 16.2, 1.9488, 0.20953 + 18000.0, 0.75, 16.2, 1.9488, 0.20953 + 18000.0, 0.8, -2.0, -0.0935, 0.01616 + 18000.0, 0.8, 0.0, 0.1402, 0.01658 + 18000.0, 0.8, 2.0, 0.374, 0.02127 + 18000.0, 0.8, 4.0, 0.6077, 0.03118 + 18000.0, 0.8, 6.0, 0.8414, 0.04783 + 18000.0, 0.8, 8.0, 1.0751, 0.07276 + 18000.0, 0.8, 10.0, 1.3089, 0.10748 + 18000.0, 0.8, 12.0, 1.5426, 0.15354 + 18000.0, 0.8, 14.0, 1.7763, 0.21246 + 18000.0, 0.8, 15.4, 1.9399, 0.26218 + 18000.0, 0.8, 15.4, 1.9399, 0.26218 + 18000.0, 0.8, 15.4, 1.9399, 0.26218 + 18000.0, 0.85, -2.0, -0.0984, 0.01601 + 18000.0, 0.85, 0.0, 0.1476, 0.01716 + 18000.0, 0.85, 2.0, 0.3936, 0.0253 + 18000.0, 0.85, 4.0, 0.6396, 0.04223 + 18000.0, 0.85, 6.0, 0.8855, 0.06972 + 18000.0, 0.85, 8.0, 1.1315, 0.10957 + 18000.0, 0.85, 10.0, 1.3775, 0.16355 + 18000.0, 0.85, 12.0, 1.6235, 0.23345 + 18000.0, 0.85, 14.0, 1.8695, 0.32105 + 18000.0, 0.85, 14.5, 1.929, 0.34511 + 18000.0, 0.85, 14.5, 1.929, 0.34511 + 18000.0, 0.85, 14.5, 1.929, 0.34511 + 18000.0, 0.9, -2.0, -0.1047, 0.01795 + 18000.0, 0.9, 0.0, 0.1571, 0.02423 + 18000.0, 0.9, 2.0, 0.4188, 0.04177 + 18000.0, 0.9, 4.0, 0.6806, 0.07271 + 18000.0, 0.9, 6.0, 0.9424, 0.11922 + 18000.0, 0.9, 8.0, 1.2041, 0.18342 + 18000.0, 0.9, 10.0, 1.4659, 0.26748 + 18000.0, 0.9, 12.0, 1.7277, 0.37354 + 18000.0, 0.9, 13.4, 1.9152, 0.46428 + 18000.0, 0.9, 13.4, 1.9152, 0.46428 + 18000.0, 0.9, 13.4, 1.9152, 0.46428 + 18000.0, 0.9, 13.4, 1.9152, 0.46428 + 21000.0, 0.0, -2.0, -0.0715, 0.00363 + 21000.0, 0.0, 0.0, 0.1072, 0.00384 + 21000.0, 0.0, 2.0, 0.286, 0.00621 + 21000.0, 0.0, 4.0, 0.4647, 0.01072 + 21000.0, 0.0, 6.0, 0.6434, 0.01737 + 21000.0, 0.0, 8.0, 0.8222, 0.02618 + 21000.0, 0.0, 10.0, 1.0009, 0.03713 + 21000.0, 0.0, 12.0, 1.1797, 0.05023 + 21000.0, 0.0, 14.0, 1.3584, 0.06548 + 21000.0, 0.0, 16.0, 1.5371, 0.08287 + 21000.0, 0.0, 18.0, 1.7159, 0.10241 + 21000.0, 0.0, 20.0, 1.8946, 0.1241 + 21000.0, 0.2, -2.0, -0.0724, 0.01983 + 21000.0, 0.2, 0.0, 0.1086, 0.0201 + 21000.0, 0.2, 2.0, 0.2896, 0.02298 + 21000.0, 0.2, 4.0, 0.4706, 0.0285 + 21000.0, 0.2, 6.0, 0.6517, 0.03663 + 21000.0, 0.2, 8.0, 0.8327, 0.0474 + 21000.0, 0.2, 10.0, 1.0137, 0.06079 + 21000.0, 0.2, 12.0, 1.1947, 0.0768 + 21000.0, 0.2, 14.0, 1.3757, 0.09544 + 21000.0, 0.2, 16.0, 1.5568, 0.1167 + 21000.0, 0.2, 18.0, 1.7378, 0.14059 + 21000.0, 0.2, 20.0, 1.9188, 0.1671 + 21000.0, 0.4, -2.0, -0.0754, 0.01811 + 21000.0, 0.4, 0.0, 0.1131, 0.01839 + 21000.0, 0.4, 2.0, 0.3016, 0.02146 + 21000.0, 0.4, 4.0, 0.4901, 0.02733 + 21000.0, 0.4, 6.0, 0.6786, 0.036 + 21000.0, 0.4, 8.0, 0.867, 0.04745 + 21000.0, 0.4, 10.0, 1.0555, 0.06171 + 21000.0, 0.4, 12.0, 1.244, 0.07876 + 21000.0, 0.4, 14.0, 1.4325, 0.0986 + 21000.0, 0.4, 16.0, 1.621, 0.12124 + 21000.0, 0.4, 18.0, 1.8095, 0.14667 + 21000.0, 0.4, 19.8, 1.982, 0.17239 + 21000.0, 0.5, -2.0, -0.0779, 0.01755 + 21000.0, 0.5, 0.0, 0.1169, 0.01785 + 21000.0, 0.5, 2.0, 0.3117, 0.02111 + 21000.0, 0.5, 4.0, 0.5065, 0.02734 + 21000.0, 0.5, 6.0, 0.7013, 0.03654 + 21000.0, 0.5, 8.0, 0.8961, 0.0487 + 21000.0, 0.5, 10.0, 1.0909, 0.06383 + 21000.0, 0.5, 12.0, 1.2857, 0.08192 + 21000.0, 0.5, 14.0, 1.4806, 0.10299 + 21000.0, 0.5, 16.0, 1.6754, 0.12702 + 21000.0, 0.5, 18.0, 1.8702, 0.15401 + 21000.0, 0.5, 19.1, 1.976, 0.16991 + 21000.0, 0.6, -2.0, -0.0814, 0.01708 + 21000.0, 0.6, 0.0, 0.1221, 0.01741 + 21000.0, 0.6, 2.0, 0.3257, 0.02095 + 21000.0, 0.6, 4.0, 0.5293, 0.02771 + 21000.0, 0.6, 6.0, 0.7329, 0.0377 + 21000.0, 0.6, 8.0, 0.9365, 0.05091 + 21000.0, 0.6, 10.0, 1.1401, 0.06734 + 21000.0, 0.6, 12.0, 1.3436, 0.08699 + 21000.0, 0.6, 14.0, 1.5472, 0.10986 + 21000.0, 0.6, 16.0, 1.7508, 0.13595 + 21000.0, 0.6, 18.0, 1.9544, 0.16533 + 21000.0, 0.6, 18.1, 1.9677, 0.16738 + 21000.0, 0.7, -2.0, -0.0863, 0.01668 + 21000.0, 0.7, 0.0, 0.1295, 0.01704 + 21000.0, 0.7, 2.0, 0.3454, 0.021 + 21000.0, 0.7, 4.0, 0.5613, 0.02857 + 21000.0, 0.7, 6.0, 0.7771, 0.03974 + 21000.0, 0.7, 8.0, 0.993, 0.05451 + 21000.0, 0.7, 10.0, 1.2089, 0.07304 + 21000.0, 0.7, 12.0, 1.4247, 0.09626 + 21000.0, 0.7, 14.0, 1.6406, 0.12539 + 21000.0, 0.7, 16.0, 1.8565, 0.16162 + 21000.0, 0.7, 16.9, 1.9562, 0.1811 + 21000.0, 0.7, 16.9, 1.9562, 0.1811 + 21000.0, 0.75, -2.0, -0.0896, 0.01649 + 21000.0, 0.75, 0.0, 0.1343, 0.01688 + 21000.0, 0.75, 2.0, 0.3582, 0.02113 + 21000.0, 0.75, 4.0, 0.5822, 0.02925 + 21000.0, 0.75, 6.0, 0.8061, 0.04138 + 21000.0, 0.75, 8.0, 1.03, 0.05851 + 21000.0, 0.75, 10.0, 1.2539, 0.082 + 21000.0, 0.75, 12.0, 1.4778, 0.11319 + 21000.0, 0.75, 14.0, 1.7017, 0.15342 + 21000.0, 0.75, 16.0, 1.9256, 0.20405 + 21000.0, 0.75, 16.2, 1.9488, 0.20995 + 21000.0, 0.75, 16.2, 1.9488, 0.20995 + 21000.0, 0.8, -2.0, -0.0935, 0.01632 + 21000.0, 0.8, 0.0, 0.1402, 0.01674 + 21000.0, 0.8, 2.0, 0.374, 0.02144 + 21000.0, 0.8, 4.0, 0.6077, 0.03137 + 21000.0, 0.8, 6.0, 0.8414, 0.04804 + 21000.0, 0.8, 8.0, 1.0751, 0.073 + 21000.0, 0.8, 10.0, 1.3089, 0.10776 + 21000.0, 0.8, 12.0, 1.5426, 0.15386 + 21000.0, 0.8, 14.0, 1.7763, 0.21283 + 21000.0, 0.8, 15.4, 1.9399, 0.26259 + 21000.0, 0.8, 15.4, 1.9399, 0.26259 + 21000.0, 0.8, 15.4, 1.9399, 0.26259 + 21000.0, 0.85, -2.0, -0.0984, 0.01617 + 21000.0, 0.85, 0.0, 0.1476, 0.01732 + 21000.0, 0.85, 2.0, 0.3936, 0.02547 + 21000.0, 0.85, 4.0, 0.6396, 0.04241 + 21000.0, 0.85, 6.0, 0.8855, 0.06993 + 21000.0, 0.85, 8.0, 1.1315, 0.10981 + 21000.0, 0.85, 10.0, 1.3775, 0.16383 + 21000.0, 0.85, 12.0, 1.6235, 0.23378 + 21000.0, 0.85, 14.0, 1.8695, 0.32144 + 21000.0, 0.85, 14.5, 1.929, 0.34551 + 21000.0, 0.85, 14.5, 1.929, 0.34551 + 21000.0, 0.85, 14.5, 1.929, 0.34551 + 21000.0, 0.9, -2.0, -0.1047, 0.0181 + 21000.0, 0.9, 0.0, 0.1571, 0.02439 + 21000.0, 0.9, 2.0, 0.4188, 0.04194 + 21000.0, 0.9, 4.0, 0.6806, 0.0729 + 21000.0, 0.9, 6.0, 0.9424, 0.11943 + 21000.0, 0.9, 8.0, 1.2041, 0.18367 + 21000.0, 0.9, 10.0, 1.4659, 0.26777 + 21000.0, 0.9, 12.0, 1.7277, 0.37389 + 21000.0, 0.9, 13.4, 1.9152, 0.46467 + 21000.0, 0.9, 13.4, 1.9152, 0.46467 + 21000.0, 0.9, 13.4, 1.9152, 0.46467 + 21000.0, 0.9, 13.4, 1.9152, 0.46467 + 24000.0, 0.0, -2.0, -0.0715, 0.00363 + 24000.0, 0.0, 0.0, 0.1072, 0.00384 + 24000.0, 0.0, 2.0, 0.286, 0.00621 + 24000.0, 0.0, 4.0, 0.4647, 0.01072 + 24000.0, 0.0, 6.0, 0.6434, 0.01737 + 24000.0, 0.0, 8.0, 0.8222, 0.02618 + 24000.0, 0.0, 10.0, 1.0009, 0.03713 + 24000.0, 0.0, 12.0, 1.1797, 0.05023 + 24000.0, 0.0, 14.0, 1.3584, 0.06548 + 24000.0, 0.0, 16.0, 1.5371, 0.08287 + 24000.0, 0.0, 18.0, 1.7159, 0.10241 + 24000.0, 0.0, 20.0, 1.8946, 0.1241 + 24000.0, 0.2, -2.0, -0.0724, 0.02007 + 24000.0, 0.2, 0.0, 0.1086, 0.02034 + 24000.0, 0.2, 2.0, 0.2896, 0.02323 + 24000.0, 0.2, 4.0, 0.4706, 0.02876 + 24000.0, 0.2, 6.0, 0.6517, 0.03691 + 24000.0, 0.2, 8.0, 0.8327, 0.0477 + 24000.0, 0.2, 10.0, 1.0137, 0.06112 + 24000.0, 0.2, 12.0, 1.1947, 0.07717 + 24000.0, 0.2, 14.0, 1.3757, 0.09585 + 24000.0, 0.2, 16.0, 1.5568, 0.11717 + 24000.0, 0.2, 18.0, 1.7378, 0.14111 + 24000.0, 0.2, 20.0, 1.9188, 0.16769 + 24000.0, 0.4, -2.0, -0.0754, 0.01831 + 24000.0, 0.4, 0.0, 0.1131, 0.01859 + 24000.0, 0.4, 2.0, 0.3016, 0.02167 + 24000.0, 0.4, 4.0, 0.4901, 0.02756 + 24000.0, 0.4, 6.0, 0.6786, 0.03624 + 24000.0, 0.4, 8.0, 0.867, 0.04772 + 24000.0, 0.4, 10.0, 1.0555, 0.062 + 24000.0, 0.4, 12.0, 1.244, 0.07909 + 24000.0, 0.4, 14.0, 1.4325, 0.09897 + 24000.0, 0.4, 16.0, 1.621, 0.12166 + 24000.0, 0.4, 18.0, 1.8095, 0.14714 + 24000.0, 0.4, 19.8, 1.982, 0.17292 + 24000.0, 0.5, -2.0, -0.0779, 0.01775 + 24000.0, 0.5, 0.0, 0.1169, 0.01804 + 24000.0, 0.5, 2.0, 0.3117, 0.02131 + 24000.0, 0.5, 4.0, 0.5065, 0.02755 + 24000.0, 0.5, 6.0, 0.7013, 0.03677 + 24000.0, 0.5, 8.0, 0.8961, 0.04895 + 24000.0, 0.5, 10.0, 1.0909, 0.06411 + 24000.0, 0.5, 12.0, 1.2857, 0.08225 + 24000.0, 0.5, 14.0, 1.4806, 0.10335 + 24000.0, 0.5, 16.0, 1.6754, 0.12743 + 24000.0, 0.5, 18.0, 1.8702, 0.15447 + 24000.0, 0.5, 19.1, 1.976, 0.17041 + 24000.0, 0.6, -2.0, -0.0814, 0.01727 + 24000.0, 0.6, 0.0, 0.1221, 0.01759 + 24000.0, 0.6, 2.0, 0.3257, 0.02114 + 24000.0, 0.6, 4.0, 0.5293, 0.02792 + 24000.0, 0.6, 6.0, 0.7329, 0.03792 + 24000.0, 0.6, 8.0, 0.9365, 0.05116 + 24000.0, 0.6, 10.0, 1.1401, 0.06762 + 24000.0, 0.6, 12.0, 1.3436, 0.08731 + 24000.0, 0.6, 14.0, 1.5472, 0.11022 + 24000.0, 0.6, 16.0, 1.7508, 0.13636 + 24000.0, 0.6, 18.0, 1.9544, 0.1658 + 24000.0, 0.6, 18.1, 1.9677, 0.16785 + 24000.0, 0.7, -2.0, -0.0863, 0.01685 + 24000.0, 0.7, 0.0, 0.1295, 0.01722 + 24000.0, 0.7, 2.0, 0.3454, 0.02119 + 24000.0, 0.7, 4.0, 0.5613, 0.02877 + 24000.0, 0.7, 6.0, 0.7771, 0.03996 + 24000.0, 0.7, 8.0, 0.993, 0.05476 + 24000.0, 0.7, 10.0, 1.2089, 0.07332 + 24000.0, 0.7, 12.0, 1.4247, 0.09658 + 24000.0, 0.7, 14.0, 1.6406, 0.12575 + 24000.0, 0.7, 16.0, 1.8565, 0.16204 + 24000.0, 0.7, 16.9, 1.9562, 0.18155 + 24000.0, 0.7, 16.9, 1.9562, 0.18155 + 24000.0, 0.75, -2.0, -0.0896, 0.01667 + 24000.0, 0.75, 0.0, 0.1343, 0.01705 + 24000.0, 0.75, 2.0, 0.3582, 0.02132 + 24000.0, 0.75, 4.0, 0.5822, 0.02945 + 24000.0, 0.75, 6.0, 0.8061, 0.0416 + 24000.0, 0.75, 8.0, 1.03, 0.05876 + 24000.0, 0.75, 10.0, 1.2539, 0.08228 + 24000.0, 0.75, 12.0, 1.4778, 0.11352 + 24000.0, 0.75, 14.0, 1.7017, 0.1538 + 24000.0, 0.75, 16.0, 1.9256, 0.20448 + 24000.0, 0.75, 16.2, 1.9488, 0.21039 + 24000.0, 0.75, 16.2, 1.9488, 0.21039 + 24000.0, 0.8, -2.0, -0.0935, 0.01649 + 24000.0, 0.8, 0.0, 0.1402, 0.01691 + 24000.0, 0.8, 2.0, 0.374, 0.02162 + 24000.0, 0.8, 4.0, 0.6077, 0.03156 + 24000.0, 0.8, 6.0, 0.8414, 0.04826 + 24000.0, 0.8, 8.0, 1.0751, 0.07325 + 24000.0, 0.8, 10.0, 1.3089, 0.10805 + 24000.0, 0.8, 12.0, 1.5426, 0.15419 + 24000.0, 0.8, 14.0, 1.7763, 0.21322 + 24000.0, 0.8, 15.4, 1.9399, 0.26302 + 24000.0, 0.8, 15.4, 1.9399, 0.26302 + 24000.0, 0.8, 15.4, 1.9399, 0.26302 + 24000.0, 0.85, -2.0, -0.0984, 0.01634 + 24000.0, 0.85, 0.0, 0.1476, 0.01749 + 24000.0, 0.85, 2.0, 0.3936, 0.02565 + 24000.0, 0.85, 4.0, 0.6396, 0.04261 + 24000.0, 0.85, 6.0, 0.8855, 0.07015 + 24000.0, 0.85, 8.0, 1.1315, 0.11006 + 24000.0, 0.85, 10.0, 1.3775, 0.16412 + 24000.0, 0.85, 12.0, 1.6235, 0.23412 + 24000.0, 0.85, 14.0, 1.8695, 0.32184 + 24000.0, 0.85, 14.5, 1.929, 0.34592 + 24000.0, 0.85, 14.5, 1.929, 0.34592 + 24000.0, 0.85, 14.5, 1.929, 0.34592 + 24000.0, 0.9, -2.0, -0.1047, 0.01827 + 24000.0, 0.9, 0.0, 0.1571, 0.02455 + 24000.0, 0.9, 2.0, 0.4188, 0.04211 + 24000.0, 0.9, 4.0, 0.6806, 0.0731 + 24000.0, 0.9, 6.0, 0.9424, 0.11965 + 24000.0, 0.9, 8.0, 1.2041, 0.18393 + 24000.0, 0.9, 10.0, 1.4659, 0.26808 + 24000.0, 0.9, 12.0, 1.7277, 0.37425 + 24000.0, 0.9, 13.4, 1.9152, 0.46507 + 24000.0, 0.9, 13.4, 1.9152, 0.46507 + 24000.0, 0.9, 13.4, 1.9152, 0.46507 + 24000.0, 0.9, 13.4, 1.9152, 0.46507 + 27000.0, 0.0, -2.0, -0.0715, 0.00363 + 27000.0, 0.0, 0.0, 0.1072, 0.00384 + 27000.0, 0.0, 2.0, 0.286, 0.00621 + 27000.0, 0.0, 4.0, 0.4647, 0.01072 + 27000.0, 0.0, 6.0, 0.6434, 0.01737 + 27000.0, 0.0, 8.0, 0.8222, 0.02618 + 27000.0, 0.0, 10.0, 1.0009, 0.03713 + 27000.0, 0.0, 12.0, 1.1797, 0.05023 + 27000.0, 0.0, 14.0, 1.3584, 0.06548 + 27000.0, 0.0, 16.0, 1.5371, 0.08287 + 27000.0, 0.0, 18.0, 1.7159, 0.10241 + 27000.0, 0.0, 20.0, 1.8946, 0.1241 + 27000.0, 0.2, -2.0, -0.0724, 0.02032 + 27000.0, 0.2, 0.0, 0.1086, 0.02058 + 27000.0, 0.2, 2.0, 0.2896, 0.02349 + 27000.0, 0.2, 4.0, 0.4706, 0.02903 + 27000.0, 0.2, 6.0, 0.6517, 0.0372 + 27000.0, 0.2, 8.0, 0.8327, 0.04802 + 27000.0, 0.2, 10.0, 1.0137, 0.06147 + 27000.0, 0.2, 12.0, 1.1947, 0.07756 + 27000.0, 0.2, 14.0, 1.3757, 0.09629 + 27000.0, 0.2, 16.0, 1.5568, 0.11766 + 27000.0, 0.2, 18.0, 1.7378, 0.14166 + 27000.0, 0.2, 20.0, 1.9188, 0.1683 + 27000.0, 0.4, -2.0, -0.0754, 0.01853 + 27000.0, 0.4, 0.0, 0.1131, 0.01881 + 27000.0, 0.4, 2.0, 0.3016, 0.02189 + 27000.0, 0.4, 4.0, 0.4901, 0.02779 + 27000.0, 0.4, 6.0, 0.6786, 0.03649 + 27000.0, 0.4, 8.0, 0.867, 0.048 + 27000.0, 0.4, 10.0, 1.0555, 0.06231 + 27000.0, 0.4, 12.0, 1.244, 0.07943 + 27000.0, 0.4, 14.0, 1.4325, 0.09936 + 27000.0, 0.4, 16.0, 1.621, 0.12209 + 27000.0, 0.4, 18.0, 1.8095, 0.14763 + 27000.0, 0.4, 19.8, 1.982, 0.17346 + 27000.0, 0.5, -2.0, -0.0779, 0.01795 + 27000.0, 0.5, 0.0, 0.1169, 0.01824 + 27000.0, 0.5, 2.0, 0.3117, 0.02152 + 27000.0, 0.5, 4.0, 0.5065, 0.02778 + 27000.0, 0.5, 6.0, 0.7013, 0.03701 + 27000.0, 0.5, 8.0, 0.8961, 0.04922 + 27000.0, 0.5, 10.0, 1.0909, 0.06441 + 27000.0, 0.5, 12.0, 1.2857, 0.08258 + 27000.0, 0.5, 14.0, 1.4806, 0.10373 + 27000.0, 0.5, 16.0, 1.6754, 0.12785 + 27000.0, 0.5, 18.0, 1.8702, 0.15496 + 27000.0, 0.5, 19.1, 1.976, 0.17092 + 27000.0, 0.6, -2.0, -0.0814, 0.01746 + 27000.0, 0.6, 0.0, 0.1221, 0.01778 + 27000.0, 0.6, 2.0, 0.3257, 0.02134 + 27000.0, 0.6, 4.0, 0.5293, 0.02813 + 27000.0, 0.6, 6.0, 0.7329, 0.03816 + 27000.0, 0.6, 8.0, 0.9365, 0.05142 + 27000.0, 0.6, 10.0, 1.1401, 0.06791 + 27000.0, 0.6, 12.0, 1.3436, 0.08764 + 27000.0, 0.6, 14.0, 1.5472, 0.1106 + 27000.0, 0.6, 16.0, 1.7508, 0.13679 + 27000.0, 0.6, 18.0, 1.9544, 0.16628 + 27000.0, 0.6, 18.1, 1.9677, 0.16834 + 27000.0, 0.7, -2.0, -0.0863, 0.01704 + 27000.0, 0.7, 0.0, 0.1295, 0.0174 + 27000.0, 0.7, 2.0, 0.3454, 0.02138 + 27000.0, 0.7, 4.0, 0.5613, 0.02897 + 27000.0, 0.7, 6.0, 0.7771, 0.04019 + 27000.0, 0.7, 8.0, 0.993, 0.05501 + 27000.0, 0.7, 10.0, 1.2089, 0.07361 + 27000.0, 0.7, 12.0, 1.4247, 0.09692 + 27000.0, 0.7, 14.0, 1.6406, 0.12614 + 27000.0, 0.7, 16.0, 1.8565, 0.16248 + 27000.0, 0.7, 16.9, 1.9562, 0.18201 + 27000.0, 0.7, 16.9, 1.9562, 0.18201 + 27000.0, 0.75, -2.0, -0.0896, 0.01685 + 27000.0, 0.75, 0.0, 0.1343, 0.01724 + 27000.0, 0.75, 2.0, 0.3582, 0.02151 + 27000.0, 0.75, 4.0, 0.5822, 0.02966 + 27000.0, 0.75, 6.0, 0.8061, 0.04182 + 27000.0, 0.75, 8.0, 1.03, 0.05902 + 27000.0, 0.75, 10.0, 1.2539, 0.08258 + 27000.0, 0.75, 12.0, 1.4778, 0.11385 + 27000.0, 0.75, 14.0, 1.7017, 0.15419 + 27000.0, 0.75, 16.0, 1.9256, 0.20492 + 27000.0, 0.75, 16.2, 1.9488, 0.21085 + 27000.0, 0.75, 16.2, 1.9488, 0.21085 + 27000.0, 0.8, -2.0, -0.0935, 0.01667 + 27000.0, 0.8, 0.0, 0.1402, 0.01709 + 27000.0, 0.8, 2.0, 0.374, 0.02181 + 27000.0, 0.8, 4.0, 0.6077, 0.03177 + 27000.0, 0.8, 6.0, 0.8414, 0.04849 + 27000.0, 0.8, 8.0, 1.0751, 0.0735 + 27000.0, 0.8, 10.0, 1.3089, 0.10835 + 27000.0, 0.8, 12.0, 1.5426, 0.15454 + 27000.0, 0.8, 14.0, 1.7763, 0.21362 + 27000.0, 0.8, 15.4, 1.9399, 0.26346 + 27000.0, 0.8, 15.4, 1.9399, 0.26346 + 27000.0, 0.8, 15.4, 1.9399, 0.26346 + 27000.0, 0.85, -2.0, -0.0984, 0.01652 + 27000.0, 0.85, 0.0, 0.1476, 0.01766 + 27000.0, 0.85, 2.0, 0.3936, 0.02583 + 27000.0, 0.85, 4.0, 0.6396, 0.04281 + 27000.0, 0.85, 6.0, 0.8855, 0.07038 + 27000.0, 0.85, 8.0, 1.1315, 0.11033 + 27000.0, 0.85, 10.0, 1.3775, 0.16443 + 27000.0, 0.85, 12.0, 1.6235, 0.23448 + 27000.0, 0.85, 14.0, 1.8695, 0.32225 + 27000.0, 0.85, 14.5, 1.929, 0.34636 + 27000.0, 0.85, 14.5, 1.929, 0.34636 + 27000.0, 0.85, 14.5, 1.929, 0.34636 + 27000.0, 0.9, -2.0, -0.1047, 0.01844 + 27000.0, 0.9, 0.0, 0.1571, 0.02473 + 27000.0, 0.9, 2.0, 0.4188, 0.0423 + 27000.0, 0.9, 4.0, 0.6806, 0.0733 + 27000.0, 0.9, 6.0, 0.9424, 0.11988 + 27000.0, 0.9, 8.0, 1.2041, 0.1842 + 27000.0, 0.9, 10.0, 1.4659, 0.26839 + 27000.0, 0.9, 12.0, 1.7277, 0.37462 + 27000.0, 0.9, 13.4, 1.9152, 0.46549 + 27000.0, 0.9, 13.4, 1.9152, 0.46549 + 27000.0, 0.9, 13.4, 1.9152, 0.46549 + 27000.0, 0.9, 13.4, 1.9152, 0.46549 + 30000.0, 0.0, -2.0, -0.0715, 0.00363 + 30000.0, 0.0, 0.0, 0.1072, 0.00384 + 30000.0, 0.0, 2.0, 0.286, 0.00621 + 30000.0, 0.0, 4.0, 0.4647, 0.01072 + 30000.0, 0.0, 6.0, 0.6434, 0.01737 + 30000.0, 0.0, 8.0, 0.8222, 0.02618 + 30000.0, 0.0, 10.0, 1.0009, 0.03713 + 30000.0, 0.0, 12.0, 1.1797, 0.05023 + 30000.0, 0.0, 14.0, 1.3584, 0.06548 + 30000.0, 0.0, 16.0, 1.5371, 0.08287 + 30000.0, 0.0, 18.0, 1.7159, 0.10241 + 30000.0, 0.0, 20.0, 1.8946, 0.1241 + 30000.0, 0.2, -2.0, -0.0724, 0.02058 + 30000.0, 0.2, 0.0, 0.1086, 0.02085 + 30000.0, 0.2, 2.0, 0.2896, 0.02375 + 30000.0, 0.2, 4.0, 0.4706, 0.02931 + 30000.0, 0.2, 6.0, 0.6517, 0.03751 + 30000.0, 0.2, 8.0, 0.8327, 0.04835 + 30000.0, 0.2, 10.0, 1.0137, 0.06184 + 30000.0, 0.2, 12.0, 1.1947, 0.07797 + 30000.0, 0.2, 14.0, 1.3757, 0.09675 + 30000.0, 0.2, 16.0, 1.5568, 0.11817 + 30000.0, 0.2, 18.0, 1.7378, 0.14223 + 30000.0, 0.2, 20.0, 1.9188, 0.16894 + 30000.0, 0.4, -2.0, -0.0754, 0.01875 + 30000.0, 0.4, 0.0, 0.1131, 0.01903 + 30000.0, 0.4, 2.0, 0.3016, 0.02212 + 30000.0, 0.4, 4.0, 0.4901, 0.02803 + 30000.0, 0.4, 6.0, 0.6786, 0.03675 + 30000.0, 0.4, 8.0, 0.867, 0.04828 + 30000.0, 0.4, 10.0, 1.0555, 0.06263 + 30000.0, 0.4, 12.0, 1.244, 0.07979 + 30000.0, 0.4, 14.0, 1.4325, 0.09976 + 30000.0, 0.4, 16.0, 1.621, 0.12255 + 30000.0, 0.4, 18.0, 1.8095, 0.14814 + 30000.0, 0.4, 19.8, 1.982, 0.17404 + 30000.0, 0.5, -2.0, -0.0779, 0.01816 + 30000.0, 0.5, 0.0, 0.1169, 0.01846 + 30000.0, 0.5, 2.0, 0.3117, 0.02174 + 30000.0, 0.5, 4.0, 0.5065, 0.02801 + 30000.0, 0.5, 6.0, 0.7013, 0.03726 + 30000.0, 0.5, 8.0, 0.8961, 0.0495 + 30000.0, 0.5, 10.0, 1.0909, 0.06472 + 30000.0, 0.5, 12.0, 1.2857, 0.08293 + 30000.0, 0.5, 14.0, 1.4806, 0.10412 + 30000.0, 0.5, 16.0, 1.6754, 0.1283 + 30000.0, 0.5, 18.0, 1.8702, 0.15546 + 30000.0, 0.5, 19.1, 1.976, 0.17146 + 30000.0, 0.6, -2.0, -0.0814, 0.01766 + 30000.0, 0.6, 0.0, 0.1221, 0.01799 + 30000.0, 0.6, 2.0, 0.3257, 0.02155 + 30000.0, 0.6, 4.0, 0.5293, 0.02836 + 30000.0, 0.6, 6.0, 0.7329, 0.0384 + 30000.0, 0.6, 8.0, 0.9365, 0.05169 + 30000.0, 0.6, 10.0, 1.1401, 0.06822 + 30000.0, 0.6, 12.0, 1.3436, 0.08798 + 30000.0, 0.6, 14.0, 1.5472, 0.11099 + 30000.0, 0.6, 16.0, 1.7508, 0.13724 + 30000.0, 0.6, 18.0, 1.9544, 0.16679 + 30000.0, 0.6, 18.1, 1.9677, 0.16885 + 30000.0, 0.7, -2.0, -0.0863, 0.01723 + 30000.0, 0.7, 0.0, 0.1295, 0.01759 + 30000.0, 0.7, 2.0, 0.3454, 0.02158 + 30000.0, 0.7, 4.0, 0.5613, 0.02919 + 30000.0, 0.7, 6.0, 0.7771, 0.04043 + 30000.0, 0.7, 8.0, 0.993, 0.05528 + 30000.0, 0.7, 10.0, 1.2089, 0.07391 + 30000.0, 0.7, 12.0, 1.4247, 0.09726 + 30000.0, 0.7, 14.0, 1.6406, 0.12654 + 30000.0, 0.7, 16.0, 1.8565, 0.16294 + 30000.0, 0.7, 16.9, 1.9562, 0.1825 + 30000.0, 0.7, 16.9, 1.9562, 0.1825 + 30000.0, 0.75, -2.0, -0.0896, 0.01704 + 30000.0, 0.75, 0.0, 0.1343, 0.01743 + 30000.0, 0.75, 2.0, 0.3582, 0.0217 + 30000.0, 0.75, 4.0, 0.5822, 0.02987 + 30000.0, 0.75, 6.0, 0.8061, 0.04206 + 30000.0, 0.75, 8.0, 1.03, 0.05929 + 30000.0, 0.75, 10.0, 1.2539, 0.08289 + 30000.0, 0.75, 12.0, 1.4778, 0.11421 + 30000.0, 0.75, 14.0, 1.7017, 0.15459 + 30000.0, 0.75, 16.0, 1.9256, 0.20539 + 30000.0, 0.75, 16.2, 1.9488, 0.21132 + 30000.0, 0.75, 16.2, 1.9488, 0.21132 + 30000.0, 0.8, -2.0, -0.0935, 0.01686 + 30000.0, 0.8, 0.0, 0.1402, 0.01728 + 30000.0, 0.8, 2.0, 0.374, 0.022 + 30000.0, 0.8, 4.0, 0.6077, 0.03198 + 30000.0, 0.8, 6.0, 0.8414, 0.04873 + 30000.0, 0.8, 8.0, 1.0751, 0.07378 + 30000.0, 0.8, 10.0, 1.3089, 0.10866 + 30000.0, 0.8, 12.0, 1.5426, 0.1549 + 30000.0, 0.8, 14.0, 1.7763, 0.21404 + 30000.0, 0.8, 15.4, 1.9399, 0.26393 + 30000.0, 0.8, 15.4, 1.9399, 0.26393 + 30000.0, 0.8, 15.4, 1.9399, 0.26393 + 30000.0, 0.85, -2.0, -0.0984, 0.0167 + 30000.0, 0.85, 0.0, 0.1476, 0.01785 + 30000.0, 0.85, 2.0, 0.3936, 0.02603 + 30000.0, 0.85, 4.0, 0.6396, 0.04302 + 30000.0, 0.85, 6.0, 0.8855, 0.07062 + 30000.0, 0.85, 8.0, 1.1315, 0.1106 + 30000.0, 0.85, 10.0, 1.3775, 0.16475 + 30000.0, 0.85, 12.0, 1.6235, 0.23485 + 30000.0, 0.85, 14.0, 1.8695, 0.32269 + 30000.0, 0.85, 14.5, 1.929, 0.34681 + 30000.0, 0.85, 14.5, 1.929, 0.34681 + 30000.0, 0.85, 14.5, 1.929, 0.34681 + 30000.0, 0.9, -2.0, -0.1047, 0.01862 + 30000.0, 0.9, 0.0, 0.1571, 0.02491 + 30000.0, 0.9, 2.0, 0.4188, 0.04249 + 30000.0, 0.9, 4.0, 0.6806, 0.07351 + 30000.0, 0.9, 6.0, 0.9424, 0.12012 + 30000.0, 0.9, 8.0, 1.2041, 0.18448 + 30000.0, 0.9, 10.0, 1.4659, 0.26872 + 30000.0, 0.9, 12.0, 1.7277, 0.37501 + 30000.0, 0.9, 13.4, 1.9152, 0.46593 + 30000.0, 0.9, 13.4, 1.9152, 0.46593 + 30000.0, 0.9, 13.4, 1.9152, 0.46593 + 30000.0, 0.9, 13.4, 1.9152, 0.46593 + 33000.0, 0.0, -2.0, -0.0715, 0.00363 + 33000.0, 0.0, 0.0, 0.1072, 0.00384 + 33000.0, 0.0, 2.0, 0.286, 0.00621 + 33000.0, 0.0, 4.0, 0.4647, 0.01072 + 33000.0, 0.0, 6.0, 0.6434, 0.01737 + 33000.0, 0.0, 8.0, 0.8222, 0.02618 + 33000.0, 0.0, 10.0, 1.0009, 0.03713 + 33000.0, 0.0, 12.0, 1.1797, 0.05023 + 33000.0, 0.0, 14.0, 1.3584, 0.06548 + 33000.0, 0.0, 16.0, 1.5371, 0.08287 + 33000.0, 0.0, 18.0, 1.7159, 0.10241 + 33000.0, 0.0, 20.0, 1.8946, 0.1241 + 33000.0, 0.2, -2.0, -0.0724, 0.02085 + 33000.0, 0.2, 0.0, 0.1086, 0.02112 + 33000.0, 0.2, 2.0, 0.2896, 0.02404 + 33000.0, 0.2, 4.0, 0.4706, 0.0296 + 33000.0, 0.2, 6.0, 0.6517, 0.03782 + 33000.0, 0.2, 8.0, 0.8327, 0.0487 + 33000.0, 0.2, 10.0, 1.0137, 0.06222 + 33000.0, 0.2, 12.0, 1.1947, 0.0784 + 33000.0, 0.2, 14.0, 1.3757, 0.09722 + 33000.0, 0.2, 16.0, 1.5568, 0.1187 + 33000.0, 0.2, 18.0, 1.7378, 0.14283 + 33000.0, 0.2, 20.0, 1.9188, 0.16962 + 33000.0, 0.4, -2.0, -0.0754, 0.01898 + 33000.0, 0.4, 0.0, 0.1131, 0.01926 + 33000.0, 0.4, 2.0, 0.3016, 0.02236 + 33000.0, 0.4, 4.0, 0.4901, 0.02829 + 33000.0, 0.4, 6.0, 0.6786, 0.03703 + 33000.0, 0.4, 8.0, 0.867, 0.04859 + 33000.0, 0.4, 10.0, 1.0555, 0.06297 + 33000.0, 0.4, 12.0, 1.244, 0.08017 + 33000.0, 0.4, 14.0, 1.4325, 0.10018 + 33000.0, 0.4, 16.0, 1.621, 0.12302 + 33000.0, 0.4, 18.0, 1.8095, 0.14868 + 33000.0, 0.4, 19.8, 1.982, 0.17463 + 33000.0, 0.5, -2.0, -0.0779, 0.01838 + 33000.0, 0.5, 0.0, 0.1169, 0.01868 + 33000.0, 0.5, 2.0, 0.3117, 0.02197 + 33000.0, 0.5, 4.0, 0.5065, 0.02825 + 33000.0, 0.5, 6.0, 0.7013, 0.03752 + 33000.0, 0.5, 8.0, 0.8961, 0.04979 + 33000.0, 0.5, 10.0, 1.0909, 0.06505 + 33000.0, 0.5, 12.0, 1.2857, 0.0833 + 33000.0, 0.5, 14.0, 1.4806, 0.10454 + 33000.0, 0.5, 16.0, 1.6754, 0.12877 + 33000.0, 0.5, 18.0, 1.8702, 0.15599 + 33000.0, 0.5, 19.1, 1.976, 0.17203 + 33000.0, 0.6, -2.0, -0.0814, 0.01787 + 33000.0, 0.6, 0.0, 0.1221, 0.0182 + 33000.0, 0.6, 2.0, 0.3257, 0.02177 + 33000.0, 0.6, 4.0, 0.5293, 0.02859 + 33000.0, 0.6, 6.0, 0.7329, 0.03866 + 33000.0, 0.6, 8.0, 0.9365, 0.05197 + 33000.0, 0.6, 10.0, 1.1401, 0.06853 + 33000.0, 0.6, 12.0, 1.3436, 0.08834 + 33000.0, 0.6, 14.0, 1.5472, 0.1114 + 33000.0, 0.6, 16.0, 1.7508, 0.13771 + 33000.0, 0.6, 18.0, 1.9544, 0.16732 + 33000.0, 0.6, 18.1, 1.9677, 0.16939 + 33000.0, 0.7, -2.0, -0.0863, 0.01743 + 33000.0, 0.7, 0.0, 0.1295, 0.0178 + 33000.0, 0.7, 2.0, 0.3454, 0.02179 + 33000.0, 0.7, 4.0, 0.5613, 0.02942 + 33000.0, 0.7, 6.0, 0.7771, 0.04067 + 33000.0, 0.7, 8.0, 0.993, 0.05556 + 33000.0, 0.7, 10.0, 1.2089, 0.07423 + 33000.0, 0.7, 12.0, 1.4247, 0.09763 + 33000.0, 0.7, 14.0, 1.6406, 0.12696 + 33000.0, 0.7, 16.0, 1.8565, 0.16342 + 33000.0, 0.7, 16.9, 1.9562, 0.18301 + 33000.0, 0.7, 16.9, 1.9562, 0.18301 + 33000.0, 0.75, -2.0, -0.0896, 0.01723 + 33000.0, 0.75, 0.0, 0.1343, 0.01762 + 33000.0, 0.75, 2.0, 0.3582, 0.02191 + 33000.0, 0.75, 4.0, 0.5822, 0.03009 + 33000.0, 0.75, 6.0, 0.8061, 0.04231 + 33000.0, 0.75, 8.0, 1.03, 0.05957 + 33000.0, 0.75, 10.0, 1.2539, 0.08321 + 33000.0, 0.75, 12.0, 1.4778, 0.11458 + 33000.0, 0.75, 14.0, 1.7017, 0.15502 + 33000.0, 0.75, 16.0, 1.9256, 0.20588 + 33000.0, 0.75, 16.2, 1.9488, 0.21182 + 33000.0, 0.75, 16.2, 1.9488, 0.21182 + 33000.0, 0.8, -2.0, -0.0935, 0.01705 + 33000.0, 0.8, 0.0, 0.1402, 0.01747 + 33000.0, 0.8, 2.0, 0.374, 0.02221 + 33000.0, 0.8, 4.0, 0.6077, 0.0322 + 33000.0, 0.8, 6.0, 0.8414, 0.04897 + 33000.0, 0.8, 8.0, 1.0751, 0.07406 + 33000.0, 0.8, 10.0, 1.3089, 0.10898 + 33000.0, 0.8, 12.0, 1.5426, 0.15528 + 33000.0, 0.8, 14.0, 1.7763, 0.21447 + 33000.0, 0.8, 15.4, 1.9399, 0.26441 + 33000.0, 0.8, 15.4, 1.9399, 0.26441 + 33000.0, 0.8, 15.4, 1.9399, 0.26441 + 33000.0, 0.85, -2.0, -0.0984, 0.01689 + 33000.0, 0.85, 0.0, 0.1476, 0.01804 + 33000.0, 0.85, 2.0, 0.3936, 0.02623 + 33000.0, 0.85, 4.0, 0.6396, 0.04324 + 33000.0, 0.85, 6.0, 0.8855, 0.07087 + 33000.0, 0.85, 8.0, 1.1315, 0.11089 + 33000.0, 0.85, 10.0, 1.3775, 0.16508 + 33000.0, 0.85, 12.0, 1.6235, 0.23524 + 33000.0, 0.85, 14.0, 1.8695, 0.32314 + 33000.0, 0.85, 14.5, 1.929, 0.34728 + 33000.0, 0.85, 14.5, 1.929, 0.34728 + 33000.0, 0.85, 14.5, 1.929, 0.34728 + 33000.0, 0.9, -2.0, -0.1047, 0.01881 + 33000.0, 0.9, 0.0, 0.1571, 0.02509 + 33000.0, 0.9, 2.0, 0.4188, 0.04269 + 33000.0, 0.9, 4.0, 0.6806, 0.07373 + 33000.0, 0.9, 6.0, 0.9424, 0.12038 + 33000.0, 0.9, 8.0, 1.2041, 0.18477 + 33000.0, 0.9, 10.0, 1.4659, 0.26907 + 33000.0, 0.9, 12.0, 1.7277, 0.37542 + 33000.0, 0.9, 13.4, 1.9152, 0.46639 + 33000.0, 0.9, 13.4, 1.9152, 0.46639 + 33000.0, 0.9, 13.4, 1.9152, 0.46639 + 33000.0, 0.9, 13.4, 1.9152, 0.46639 + 36000.0, 0.0, -2.0, -0.0715, 0.00363 + 36000.0, 0.0, 0.0, 0.1072, 0.00384 + 36000.0, 0.0, 2.0, 0.286, 0.00621 + 36000.0, 0.0, 4.0, 0.4647, 0.01072 + 36000.0, 0.0, 6.0, 0.6434, 0.01737 + 36000.0, 0.0, 8.0, 0.8222, 0.02618 + 36000.0, 0.0, 10.0, 1.0009, 0.03713 + 36000.0, 0.0, 12.0, 1.1797, 0.05023 + 36000.0, 0.0, 14.0, 1.3584, 0.06548 + 36000.0, 0.0, 16.0, 1.5371, 0.08287 + 36000.0, 0.0, 18.0, 1.7159, 0.10241 + 36000.0, 0.0, 20.0, 1.8946, 0.1241 + 36000.0, 0.2, -2.0, -0.0724, 0.02114 + 36000.0, 0.2, 0.0, 0.1086, 0.0214 + 36000.0, 0.2, 2.0, 0.2896, 0.02433 + 36000.0, 0.2, 4.0, 0.4706, 0.02991 + 36000.0, 0.2, 6.0, 0.6517, 0.03816 + 36000.0, 0.2, 8.0, 0.8327, 0.04906 + 36000.0, 0.2, 10.0, 1.0137, 0.06262 + 36000.0, 0.2, 12.0, 1.1947, 0.07884 + 36000.0, 0.2, 14.0, 1.3757, 0.09772 + 36000.0, 0.2, 16.0, 1.5568, 0.11926 + 36000.0, 0.2, 18.0, 1.7378, 0.14346 + 36000.0, 0.2, 20.0, 1.9188, 0.17032 + 36000.0, 0.4, -2.0, -0.0754, 0.01922 + 36000.0, 0.4, 0.0, 0.1131, 0.01951 + 36000.0, 0.4, 2.0, 0.3016, 0.02262 + 36000.0, 0.4, 4.0, 0.4901, 0.02855 + 36000.0, 0.4, 6.0, 0.6786, 0.03731 + 36000.0, 0.4, 8.0, 0.867, 0.0489 + 36000.0, 0.4, 10.0, 1.0555, 0.06332 + 36000.0, 0.4, 12.0, 1.244, 0.08056 + 36000.0, 0.4, 14.0, 1.4325, 0.10063 + 36000.0, 0.4, 16.0, 1.621, 0.12352 + 36000.0, 0.4, 18.0, 1.8095, 0.14924 + 36000.0, 0.4, 19.8, 1.982, 0.17526 + 36000.0, 0.5, -2.0, -0.0779, 0.01861 + 36000.0, 0.5, 0.0, 0.1169, 0.01891 + 36000.0, 0.5, 2.0, 0.3117, 0.02221 + 36000.0, 0.5, 4.0, 0.5065, 0.0285 + 36000.0, 0.5, 6.0, 0.7013, 0.0378 + 36000.0, 0.5, 8.0, 0.8961, 0.05009 + 36000.0, 0.5, 10.0, 1.0909, 0.06539 + 36000.0, 0.5, 12.0, 1.2857, 0.08368 + 36000.0, 0.5, 14.0, 1.4806, 0.10497 + 36000.0, 0.5, 16.0, 1.6754, 0.12926 + 36000.0, 0.5, 18.0, 1.8702, 0.15654 + 36000.0, 0.5, 19.1, 1.976, 0.17262 + 36000.0, 0.6, -2.0, -0.0814, 0.01809 + 36000.0, 0.6, 0.0, 0.1221, 0.01842 + 36000.0, 0.6, 2.0, 0.3257, 0.022 + 36000.0, 0.6, 4.0, 0.5293, 0.02883 + 36000.0, 0.6, 6.0, 0.7329, 0.03892 + 36000.0, 0.6, 8.0, 0.9365, 0.05227 + 36000.0, 0.6, 10.0, 1.1401, 0.06887 + 36000.0, 0.6, 12.0, 1.3436, 0.08872 + 36000.0, 0.6, 14.0, 1.5472, 0.11183 + 36000.0, 0.6, 16.0, 1.7508, 0.1382 + 36000.0, 0.6, 18.0, 1.9544, 0.16788 + 36000.0, 0.6, 18.1, 1.9677, 0.16995 + 36000.0, 0.7, -2.0, -0.0863, 0.01765 + 36000.0, 0.7, 0.0, 0.1295, 0.01801 + 36000.0, 0.7, 2.0, 0.3454, 0.02201 + 36000.0, 0.7, 4.0, 0.5613, 0.02965 + 36000.0, 0.7, 6.0, 0.7771, 0.04094 + 36000.0, 0.7, 8.0, 0.993, 0.05586 + 36000.0, 0.7, 10.0, 1.2089, 0.07457 + 36000.0, 0.7, 12.0, 1.4247, 0.09801 + 36000.0, 0.7, 14.0, 1.6406, 0.12739 + 36000.0, 0.7, 16.0, 1.8565, 0.16392 + 36000.0, 0.7, 16.9, 1.9562, 0.18355 + 36000.0, 0.7, 16.9, 1.9562, 0.18355 + 36000.0, 0.75, -2.0, -0.0896, 0.01744 + 36000.0, 0.75, 0.0, 0.1343, 0.01783 + 36000.0, 0.75, 2.0, 0.3582, 0.02213 + 36000.0, 0.75, 4.0, 0.5822, 0.03033 + 36000.0, 0.75, 6.0, 0.8061, 0.04257 + 36000.0, 0.75, 8.0, 1.03, 0.05986 + 36000.0, 0.75, 10.0, 1.2539, 0.08354 + 36000.0, 0.75, 12.0, 1.4778, 0.11496 + 36000.0, 0.75, 14.0, 1.7017, 0.15547 + 36000.0, 0.75, 16.0, 1.9256, 0.2064 + 36000.0, 0.75, 16.2, 1.9488, 0.21234 + 36000.0, 0.75, 16.2, 1.9488, 0.21234 + 36000.0, 0.8, -2.0, -0.0935, 0.01725 + 36000.0, 0.8, 0.0, 0.1402, 0.01768 + 36000.0, 0.8, 2.0, 0.374, 0.02242 + 36000.0, 0.8, 4.0, 0.6077, 0.03243 + 36000.0, 0.8, 6.0, 0.8414, 0.04923 + 36000.0, 0.8, 8.0, 1.0751, 0.07435 + 36000.0, 0.8, 10.0, 1.3089, 0.10932 + 36000.0, 0.8, 12.0, 1.5426, 0.15567 + 36000.0, 0.8, 14.0, 1.7763, 0.21493 + 36000.0, 0.8, 15.4, 1.9399, 0.26492 + 36000.0, 0.8, 15.4, 1.9399, 0.26492 + 36000.0, 0.8, 15.4, 1.9399, 0.26492 + 36000.0, 0.85, -2.0, -0.0984, 0.01709 + 36000.0, 0.85, 0.0, 0.1476, 0.01824 + 36000.0, 0.85, 2.0, 0.3936, 0.02644 + 36000.0, 0.85, 4.0, 0.6396, 0.04347 + 36000.0, 0.85, 6.0, 0.8855, 0.07113 + 36000.0, 0.85, 8.0, 1.1315, 0.11119 + 36000.0, 0.85, 10.0, 1.3775, 0.16543 + 36000.0, 0.85, 12.0, 1.6235, 0.23565 + 36000.0, 0.85, 14.0, 1.8695, 0.32362 + 36000.0, 0.85, 14.5, 1.929, 0.34777 + 36000.0, 0.85, 14.5, 1.929, 0.34777 + 36000.0, 0.85, 14.5, 1.929, 0.34777 + 36000.0, 0.9, -2.0, -0.1047, 0.019 + 36000.0, 0.9, 0.0, 0.1571, 0.02529 + 36000.0, 0.9, 2.0, 0.4188, 0.04289 + 36000.0, 0.9, 4.0, 0.6806, 0.07396 + 36000.0, 0.9, 6.0, 0.9424, 0.12064 + 36000.0, 0.9, 8.0, 1.2041, 0.18508 + 36000.0, 0.9, 10.0, 1.4659, 0.26943 + 36000.0, 0.9, 12.0, 1.7277, 0.37585 + 36000.0, 0.9, 13.4, 1.9152, 0.46687 + 36000.0, 0.9, 13.4, 1.9152, 0.46687 + 36000.0, 0.9, 13.4, 1.9152, 0.46687 + 36000.0, 0.9, 13.4, 1.9152, 0.46687 + 38000.0, 0.0, -2.0, -0.0715, 0.00363 + 38000.0, 0.0, 0.0, 0.1072, 0.00384 + 38000.0, 0.0, 2.0, 0.286, 0.00621 + 38000.0, 0.0, 4.0, 0.4647, 0.01072 + 38000.0, 0.0, 6.0, 0.6434, 0.01737 + 38000.0, 0.0, 8.0, 0.8222, 0.02618 + 38000.0, 0.0, 10.0, 1.0009, 0.03713 + 38000.0, 0.0, 12.0, 1.1797, 0.05023 + 38000.0, 0.0, 14.0, 1.3584, 0.06548 + 38000.0, 0.0, 16.0, 1.5371, 0.08287 + 38000.0, 0.0, 18.0, 1.7159, 0.10241 + 38000.0, 0.0, 20.0, 1.8946, 0.1241 + 38000.0, 0.2, -2.0, -0.0724, 0.0214 + 38000.0, 0.2, 0.0, 0.1086, 0.02166 + 38000.0, 0.2, 2.0, 0.2896, 0.0246 + 38000.0, 0.2, 4.0, 0.4706, 0.0302 + 38000.0, 0.2, 6.0, 0.6517, 0.03846 + 38000.0, 0.2, 8.0, 0.8327, 0.04939 + 38000.0, 0.2, 10.0, 1.0137, 0.06299 + 38000.0, 0.2, 12.0, 1.1947, 0.07925 + 38000.0, 0.2, 14.0, 1.3757, 0.09818 + 38000.0, 0.2, 16.0, 1.5568, 0.11977 + 38000.0, 0.2, 18.0, 1.7378, 0.14404 + 38000.0, 0.2, 20.0, 1.9188, 0.17096 + 38000.0, 0.4, -2.0, -0.0754, 0.01945 + 38000.0, 0.4, 0.0, 0.1131, 0.01973 + 38000.0, 0.4, 2.0, 0.3016, 0.02285 + 38000.0, 0.4, 4.0, 0.4901, 0.02879 + 38000.0, 0.4, 6.0, 0.6786, 0.03758 + 38000.0, 0.4, 8.0, 0.867, 0.04919 + 38000.0, 0.4, 10.0, 1.0555, 0.06364 + 38000.0, 0.4, 12.0, 1.244, 0.08092 + 38000.0, 0.4, 14.0, 1.4325, 0.10103 + 38000.0, 0.4, 16.0, 1.621, 0.12397 + 38000.0, 0.4, 18.0, 1.8095, 0.14975 + 38000.0, 0.4, 19.8, 1.982, 0.17583 + 38000.0, 0.5, -2.0, -0.0779, 0.01882 + 38000.0, 0.5, 0.0, 0.1169, 0.01912 + 38000.0, 0.5, 2.0, 0.3117, 0.02242 + 38000.0, 0.5, 4.0, 0.5065, 0.02874 + 38000.0, 0.5, 6.0, 0.7013, 0.03805 + 38000.0, 0.5, 8.0, 0.8961, 0.05037 + 38000.0, 0.5, 10.0, 1.0909, 0.0657 + 38000.0, 0.5, 12.0, 1.2857, 0.08403 + 38000.0, 0.5, 14.0, 1.4806, 0.10536 + 38000.0, 0.5, 16.0, 1.6754, 0.1297 + 38000.0, 0.5, 18.0, 1.8702, 0.15704 + 38000.0, 0.5, 19.1, 1.976, 0.17315 + 38000.0, 0.6, -2.0, -0.0814, 0.01829 + 38000.0, 0.6, 0.0, 0.1221, 0.01862 + 38000.0, 0.6, 2.0, 0.3257, 0.02221 + 38000.0, 0.6, 4.0, 0.5293, 0.02906 + 38000.0, 0.6, 6.0, 0.7329, 0.03917 + 38000.0, 0.6, 8.0, 0.9365, 0.05254 + 38000.0, 0.6, 10.0, 1.1401, 0.06917 + 38000.0, 0.6, 12.0, 1.3436, 0.08907 + 38000.0, 0.6, 14.0, 1.5472, 0.11222 + 38000.0, 0.6, 16.0, 1.7508, 0.13864 + 38000.0, 0.6, 18.0, 1.9544, 0.16838 + 38000.0, 0.6, 18.1, 1.9677, 0.17046 + 38000.0, 0.7, -2.0, -0.0863, 0.01784 + 38000.0, 0.7, 0.0, 0.1295, 0.0182 + 38000.0, 0.7, 2.0, 0.3454, 0.02221 + 38000.0, 0.7, 4.0, 0.5613, 0.02987 + 38000.0, 0.7, 6.0, 0.7771, 0.04117 + 38000.0, 0.7, 8.0, 0.993, 0.05612 + 38000.0, 0.7, 10.0, 1.2089, 0.07487 + 38000.0, 0.7, 12.0, 1.4247, 0.09836 + 38000.0, 0.7, 14.0, 1.6406, 0.12779 + 38000.0, 0.7, 16.0, 1.8565, 0.16437 + 38000.0, 0.7, 16.9, 1.9562, 0.18403 + 38000.0, 0.7, 16.9, 1.9562, 0.18403 + 38000.0, 0.75, -2.0, -0.0896, 0.01763 + 38000.0, 0.75, 0.0, 0.1343, 0.01802 + 38000.0, 0.75, 2.0, 0.3582, 0.02232 + 38000.0, 0.75, 4.0, 0.5822, 0.03054 + 38000.0, 0.75, 6.0, 0.8061, 0.04281 + 38000.0, 0.75, 8.0, 1.03, 0.06013 + 38000.0, 0.75, 10.0, 1.2539, 0.08385 + 38000.0, 0.75, 12.0, 1.4778, 0.11531 + 38000.0, 0.75, 14.0, 1.7017, 0.15587 + 38000.0, 0.75, 16.0, 1.9256, 0.20686 + 38000.0, 0.75, 16.2, 1.9488, 0.21281 + 38000.0, 0.75, 16.2, 1.9488, 0.21281 + 38000.0, 0.8, -2.0, -0.0935, 0.01744 + 38000.0, 0.8, 0.0, 0.1402, 0.01786 + 38000.0, 0.8, 2.0, 0.374, 0.02261 + 38000.0, 0.8, 4.0, 0.6077, 0.03264 + 38000.0, 0.8, 6.0, 0.8414, 0.04947 + 38000.0, 0.8, 8.0, 1.0751, 0.07462 + 38000.0, 0.8, 10.0, 1.3089, 0.10963 + 38000.0, 0.8, 12.0, 1.5426, 0.15603 + 38000.0, 0.8, 14.0, 1.7763, 0.21535 + 38000.0, 0.8, 15.4, 1.9399, 0.26538 + 38000.0, 0.8, 15.4, 1.9399, 0.26538 + 38000.0, 0.8, 15.4, 1.9399, 0.26538 + 38000.0, 0.85, -2.0, -0.0984, 0.01727 + 38000.0, 0.85, 0.0, 0.1476, 0.01842 + 38000.0, 0.85, 2.0, 0.3936, 0.02663 + 38000.0, 0.85, 4.0, 0.6396, 0.04368 + 38000.0, 0.85, 6.0, 0.8855, 0.07137 + 38000.0, 0.85, 8.0, 1.1315, 0.11146 + 38000.0, 0.85, 10.0, 1.3775, 0.16575 + 38000.0, 0.85, 12.0, 1.6235, 0.23602 + 38000.0, 0.85, 14.0, 1.8695, 0.32405 + 38000.0, 0.85, 14.5, 1.929, 0.34822 + 38000.0, 0.85, 14.5, 1.929, 0.34822 + 38000.0, 0.85, 14.5, 1.929, 0.34822 + 38000.0, 0.9, -2.0, -0.1047, 0.01918 + 38000.0, 0.9, 0.0, 0.1571, 0.02547 + 38000.0, 0.9, 2.0, 0.4188, 0.04308 + 38000.0, 0.9, 4.0, 0.6806, 0.07417 + 38000.0, 0.9, 6.0, 0.9424, 0.12088 + 38000.0, 0.9, 8.0, 1.2041, 0.18536 + 38000.0, 0.9, 10.0, 1.4659, 0.26976 + 38000.0, 0.9, 12.0, 1.7277, 0.37624 + 38000.0, 0.9, 13.4, 1.9152, 0.46731 + 38000.0, 0.9, 13.4, 1.9152, 0.46731 + 38000.0, 0.9, 13.4, 1.9152, 0.46731 + 38000.0, 0.9, 13.4, 1.9152, 0.46731 + 42000.0, 0.0, -2.0, -0.0715, 0.00363 + 42000.0, 0.0, 0.0, 0.1072, 0.00384 + 42000.0, 0.0, 2.0, 0.286, 0.00621 + 42000.0, 0.0, 4.0, 0.4647, 0.01072 + 42000.0, 0.0, 6.0, 0.6434, 0.01737 + 42000.0, 0.0, 8.0, 0.8222, 0.02618 + 42000.0, 0.0, 10.0, 1.0009, 0.03713 + 42000.0, 0.0, 12.0, 1.1797, 0.05023 + 42000.0, 0.0, 14.0, 1.3584, 0.06548 + 42000.0, 0.0, 16.0, 1.5371, 0.08287 + 42000.0, 0.0, 18.0, 1.7159, 0.10241 + 42000.0, 0.0, 20.0, 1.8946, 0.1241 + 42000.0, 0.2, -2.0, -0.0724, 0.02194 + 42000.0, 0.2, 0.0, 0.1086, 0.02221 + 42000.0, 0.2, 2.0, 0.2896, 0.02516 + 42000.0, 0.2, 4.0, 0.4706, 0.03079 + 42000.0, 0.2, 6.0, 0.6517, 0.0391 + 42000.0, 0.2, 8.0, 0.8327, 0.05009 + 42000.0, 0.2, 10.0, 1.0137, 0.06376 + 42000.0, 0.2, 12.0, 1.1947, 0.08011 + 42000.0, 0.2, 14.0, 1.3757, 0.09914 + 42000.0, 0.2, 16.0, 1.5568, 0.12085 + 42000.0, 0.2, 18.0, 1.7378, 0.14524 + 42000.0, 0.2, 20.0, 1.9188, 0.17231 + 42000.0, 0.4, -2.0, -0.0754, 0.01991 + 42000.0, 0.4, 0.0, 0.1131, 0.0202 + 42000.0, 0.4, 2.0, 0.3016, 0.02333 + 42000.0, 0.4, 4.0, 0.4901, 0.0293 + 42000.0, 0.4, 6.0, 0.6786, 0.03812 + 42000.0, 0.4, 8.0, 0.867, 0.04979 + 42000.0, 0.4, 10.0, 1.0555, 0.06431 + 42000.0, 0.4, 12.0, 1.244, 0.08167 + 42000.0, 0.4, 14.0, 1.4325, 0.10187 + 42000.0, 0.4, 16.0, 1.621, 0.12493 + 42000.0, 0.4, 18.0, 1.8095, 0.15082 + 42000.0, 0.4, 19.8, 1.982, 0.17702 + 42000.0, 0.5, -2.0, -0.0779, 0.01926 + 42000.0, 0.5, 0.0, 0.1169, 0.01956 + 42000.0, 0.5, 2.0, 0.3117, 0.02288 + 42000.0, 0.5, 4.0, 0.5065, 0.02922 + 42000.0, 0.5, 6.0, 0.7013, 0.03858 + 42000.0, 0.5, 8.0, 0.8961, 0.05095 + 42000.0, 0.5, 10.0, 1.0909, 0.06634 + 42000.0, 0.5, 12.0, 1.2857, 0.08475 + 42000.0, 0.5, 14.0, 1.4806, 0.10618 + 42000.0, 0.5, 16.0, 1.6754, 0.13063 + 42000.0, 0.5, 18.0, 1.8702, 0.1581 + 42000.0, 0.5, 19.1, 1.976, 0.17428 + 42000.0, 0.6, -2.0, -0.0814, 0.01871 + 42000.0, 0.6, 0.0, 0.1221, 0.01904 + 42000.0, 0.6, 2.0, 0.3257, 0.02264 + 42000.0, 0.6, 4.0, 0.5293, 0.02952 + 42000.0, 0.6, 6.0, 0.7329, 0.03968 + 42000.0, 0.6, 8.0, 0.9365, 0.0531 + 42000.0, 0.6, 10.0, 1.1401, 0.06981 + 42000.0, 0.6, 12.0, 1.3436, 0.08979 + 42000.0, 0.6, 14.0, 1.5472, 0.11304 + 42000.0, 0.6, 16.0, 1.7508, 0.13957 + 42000.0, 0.6, 18.0, 1.9544, 0.16944 + 42000.0, 0.6, 18.1, 1.9677, 0.17152 + 42000.0, 0.7, -2.0, -0.0863, 0.01824 + 42000.0, 0.7, 0.0, 0.1295, 0.0186 + 42000.0, 0.7, 2.0, 0.3454, 0.02263 + 42000.0, 0.7, 4.0, 0.5613, 0.03032 + 42000.0, 0.7, 6.0, 0.7771, 0.04167 + 42000.0, 0.7, 8.0, 0.993, 0.05668 + 42000.0, 0.7, 10.0, 1.2089, 0.07551 + 42000.0, 0.7, 12.0, 1.4247, 0.09908 + 42000.0, 0.7, 14.0, 1.6406, 0.12862 + 42000.0, 0.7, 16.0, 1.8565, 0.16533 + 42000.0, 0.7, 16.9, 1.9562, 0.18504 + 42000.0, 0.7, 16.9, 1.9562, 0.18504 + 42000.0, 0.75, -2.0, -0.0896, 0.01802 + 42000.0, 0.75, 0.0, 0.1343, 0.01842 + 42000.0, 0.75, 2.0, 0.3582, 0.02274 + 42000.0, 0.75, 4.0, 0.5822, 0.03099 + 42000.0, 0.75, 6.0, 0.8061, 0.0433 + 42000.0, 0.75, 8.0, 1.03, 0.06069 + 42000.0, 0.75, 10.0, 1.2539, 0.08449 + 42000.0, 0.75, 12.0, 1.4778, 0.11605 + 42000.0, 0.75, 14.0, 1.7017, 0.15672 + 42000.0, 0.75, 16.0, 1.9256, 0.20784 + 42000.0, 0.75, 16.2, 1.9488, 0.2138 + 42000.0, 0.75, 16.2, 1.9488, 0.2138 + 42000.0, 0.8, -2.0, -0.0935, 0.01782 + 42000.0, 0.8, 0.0, 0.1402, 0.01825 + 42000.0, 0.8, 2.0, 0.374, 0.02302 + 42000.0, 0.8, 4.0, 0.6077, 0.03309 + 42000.0, 0.8, 6.0, 0.8414, 0.04996 + 42000.0, 0.8, 8.0, 1.0751, 0.07519 + 42000.0, 0.8, 10.0, 1.3089, 0.11028 + 42000.0, 0.8, 12.0, 1.5426, 0.15678 + 42000.0, 0.8, 14.0, 1.7763, 0.21622 + 42000.0, 0.8, 15.4, 1.9399, 0.26635 + 42000.0, 0.8, 15.4, 1.9399, 0.26635 + 42000.0, 0.8, 15.4, 1.9399, 0.26635 + 42000.0, 0.85, -2.0, -0.0984, 0.01765 + 42000.0, 0.85, 0.0, 0.1476, 0.0188 + 42000.0, 0.85, 2.0, 0.3936, 0.02703 + 42000.0, 0.85, 4.0, 0.6396, 0.04412 + 42000.0, 0.85, 6.0, 0.8855, 0.07186 + 42000.0, 0.85, 8.0, 1.1315, 0.11203 + 42000.0, 0.85, 10.0, 1.3775, 0.16642 + 42000.0, 0.85, 12.0, 1.6235, 0.2368 + 42000.0, 0.85, 14.0, 1.8695, 0.32496 + 42000.0, 0.85, 14.5, 1.929, 0.34916 + 42000.0, 0.85, 14.5, 1.929, 0.34916 + 42000.0, 0.85, 14.5, 1.929, 0.34916 + 42000.0, 0.9, -2.0, -0.1047, 0.01955 + 42000.0, 0.9, 0.0, 0.1571, 0.02584 + 42000.0, 0.9, 2.0, 0.4188, 0.04348 + 42000.0, 0.9, 4.0, 0.6806, 0.07461 + 42000.0, 0.9, 6.0, 0.9424, 0.12138 + 42000.0, 0.9, 8.0, 1.2041, 0.18595 + 42000.0, 0.9, 10.0, 1.4659, 0.27045 + 42000.0, 0.9, 12.0, 1.7277, 0.37705 + 42000.0, 0.9, 13.4, 1.9152, 0.46822 + 42000.0, 0.9, 13.4, 1.9152, 0.46822 + 42000.0, 0.9, 13.4, 1.9152, 0.46822 + 42000.0, 0.9, 13.4, 1.9152, 0.46822 diff --git a/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_free_reduced_alpha.csv b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_free_reduced_alpha.csv new file mode 100644 index 0000000000..2a1f0f737a --- /dev/null +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_free_reduced_alpha.csv @@ -0,0 +1,1057 @@ +# created 06/11/25 +# GASP_ALT-derived aerodynamics data converted from aero_free_reduced_alpha_GASP.txt +# Clean / Free Air Aerodynamics +# Copy of GASP_aero_free.txt with alpha above 10 removed +# Reference Area = 1370. sqft + +Altitude (ft, input), Mach (input), Angle of Attack (deg, input), CL (output), CD (output) + 0.0, 0.0, -2.0, -0.0715, 0.00363 + 0.0, 0.0, 0.0, 0.1072, 0.00384 + 0.0, 0.0, 2.0, 0.286, 0.00621 + 0.0, 0.0, 4.0, 0.4647, 0.01072 + 0.0, 0.0, 6.0, 0.6434, 0.01737 + 0.0, 0.0, 8.0, 0.8222, 0.02618 + 0.0, 0.0, 10.0, 1.0009, 0.03713 + 0.0, 0.2, -2.0, -0.0724, 0.01841 + 0.0, 0.2, 0.0, 0.1086, 0.01867 + 0.0, 0.2, 2.0, 0.2896, 0.02152 + 0.0, 0.2, 4.0, 0.4706, 0.02695 + 0.0, 0.2, 6.0, 0.6517, 0.03498 + 0.0, 0.2, 8.0, 0.8327, 0.04559 + 0.0, 0.2, 10.0, 1.0137, 0.05878 + 0.0, 0.4, -2.0, -0.0754, 0.01689 + 0.0, 0.4, 0.0, 0.1131, 0.01716 + 0.0, 0.4, 2.0, 0.3016, 0.0202 + 0.0, 0.4, 4.0, 0.4901, 0.026 + 0.0, 0.4, 6.0, 0.6786, 0.03455 + 0.0, 0.4, 8.0, 0.867, 0.04587 + 0.0, 0.4, 10.0, 1.0555, 0.05995 + 0.0, 0.5, -2.0, -0.0779, 0.01639 + 0.0, 0.5, 0.0, 0.1169, 0.01668 + 0.0, 0.5, 2.0, 0.3117, 0.01991 + 0.0, 0.5, 4.0, 0.5065, 0.02607 + 0.0, 0.5, 6.0, 0.7013, 0.03515 + 0.0, 0.5, 8.0, 0.8961, 0.04717 + 0.0, 0.5, 10.0, 1.0909, 0.06212 + 0.0, 0.6, -2.0, -0.0814, 0.01598 + 0.0, 0.6, 0.0, 0.1221, 0.01629 + 0.0, 0.6, 2.0, 0.3257, 0.0198 + 0.0, 0.6, 4.0, 0.5293, 0.02648 + 0.0, 0.6, 6.0, 0.7329, 0.03636 + 0.0, 0.6, 8.0, 0.9365, 0.04941 + 0.0, 0.6, 10.0, 1.1401, 0.06566 + 0.0, 0.7, -2.0, -0.0863, 0.01561 + 0.0, 0.7, 0.0, 0.1295, 0.01597 + 0.0, 0.7, 2.0, 0.3454, 0.01989 + 0.0, 0.7, 4.0, 0.5613, 0.02737 + 0.0, 0.7, 6.0, 0.7771, 0.03842 + 0.0, 0.7, 8.0, 0.993, 0.05303 + 0.0, 0.7, 10.0, 1.2089, 0.07136 + 0.0, 0.75, -2.0, -0.0896, 0.01545 + 0.0, 0.75, 0.0, 0.1343, 0.01583 + 0.0, 0.75, 2.0, 0.3582, 0.02004 + 0.0, 0.75, 4.0, 0.5822, 0.02807 + 0.0, 0.75, 6.0, 0.8061, 0.04007 + 0.0, 0.75, 8.0, 1.03, 0.05703 + 0.0, 0.75, 10.0, 1.2539, 0.08031 + 0.0, 0.8, -2.0, -0.0935, 0.0153 + 0.0, 0.8, 0.0, 0.1402, 0.01571 + 0.0, 0.8, 2.0, 0.374, 0.02036 + 0.0, 0.8, 4.0, 0.6077, 0.0302 + 0.0, 0.8, 6.0, 0.8414, 0.04673 + 0.0, 0.8, 8.0, 1.0751, 0.0715 + 0.0, 0.8, 10.0, 1.3089, 0.10604 + 0.0, 0.85, -2.0, -0.0984, 0.01517 + 0.0, 0.85, 0.0, 0.1476, 0.01631 + 0.0, 0.85, 2.0, 0.3936, 0.02441 + 0.0, 0.85, 4.0, 0.6396, 0.04125 + 0.0, 0.85, 6.0, 0.8855, 0.06862 + 0.0, 0.85, 8.0, 1.1315, 0.1083 + 0.0, 0.85, 10.0, 1.3775, 0.16207 + 0.0, 0.9, -2.0, -0.1047, 0.01712 + 0.0, 0.9, 0.0, 0.1571, 0.02339 + 0.0, 0.9, 2.0, 0.4188, 0.04088 + 0.0, 0.9, 4.0, 0.6806, 0.07174 + 0.0, 0.9, 6.0, 0.9424, 0.11809 + 0.0, 0.9, 8.0, 1.2041, 0.18211 + 0.0, 0.9, 10.0, 1.4659, 0.26594 + 3000.0, 0.0, -2.0, -0.0715, 0.00363 + 3000.0, 0.0, 0.0, 0.1072, 0.00384 + 3000.0, 0.0, 2.0, 0.286, 0.00621 + 3000.0, 0.0, 4.0, 0.4647, 0.01072 + 3000.0, 0.0, 6.0, 0.6434, 0.01737 + 3000.0, 0.0, 8.0, 0.8222, 0.02618 + 3000.0, 0.0, 10.0, 1.0009, 0.03713 + 3000.0, 0.2, -2.0, -0.0724, 0.01859 + 3000.0, 0.2, 0.0, 0.1086, 0.01885 + 3000.0, 0.2, 2.0, 0.2896, 0.0217 + 3000.0, 0.2, 4.0, 0.4706, 0.02715 + 3000.0, 0.2, 6.0, 0.6517, 0.03519 + 3000.0, 0.2, 8.0, 0.8327, 0.04582 + 3000.0, 0.2, 10.0, 1.0137, 0.05904 + 3000.0, 0.4, -2.0, -0.0754, 0.01704 + 3000.0, 0.4, 0.0, 0.1131, 0.01732 + 3000.0, 0.4, 2.0, 0.3016, 0.02036 + 3000.0, 0.4, 4.0, 0.4901, 0.02617 + 3000.0, 0.4, 6.0, 0.6786, 0.03474 + 3000.0, 0.4, 8.0, 0.867, 0.04607 + 3000.0, 0.4, 10.0, 1.0555, 0.06017 + 3000.0, 0.5, -2.0, -0.0779, 0.01654 + 3000.0, 0.5, 0.0, 0.1169, 0.01683 + 3000.0, 0.5, 2.0, 0.3117, 0.02006 + 3000.0, 0.5, 4.0, 0.5065, 0.02623 + 3000.0, 0.5, 6.0, 0.7013, 0.03533 + 3000.0, 0.5, 8.0, 0.8961, 0.04737 + 3000.0, 0.5, 10.0, 1.0909, 0.06234 + 3000.0, 0.6, -2.0, -0.0814, 0.01612 + 3000.0, 0.6, 0.0, 0.1221, 0.01644 + 3000.0, 0.6, 2.0, 0.3257, 0.01994 + 3000.0, 0.6, 4.0, 0.5293, 0.02664 + 3000.0, 0.6, 6.0, 0.7329, 0.03653 + 3000.0, 0.6, 8.0, 0.9365, 0.04961 + 3000.0, 0.6, 10.0, 1.1401, 0.06587 + 3000.0, 0.7, -2.0, -0.0863, 0.01575 + 3000.0, 0.7, 0.0, 0.1295, 0.01611 + 3000.0, 0.7, 2.0, 0.3454, 0.02003 + 3000.0, 0.7, 4.0, 0.5613, 0.02753 + 3000.0, 0.7, 6.0, 0.7771, 0.03859 + 3000.0, 0.7, 8.0, 0.993, 0.05322 + 3000.0, 0.7, 10.0, 1.2089, 0.07157 + 3000.0, 0.75, -2.0, -0.0896, 0.01558 + 3000.0, 0.75, 0.0, 0.1343, 0.01597 + 3000.0, 0.75, 2.0, 0.3582, 0.02018 + 3000.0, 0.75, 4.0, 0.5822, 0.02822 + 3000.0, 0.75, 6.0, 0.8061, 0.04024 + 3000.0, 0.75, 8.0, 1.03, 0.05722 + 3000.0, 0.75, 10.0, 1.2539, 0.08052 + 3000.0, 0.8, -2.0, -0.0935, 0.01543 + 3000.0, 0.8, 0.0, 0.1402, 0.01584 + 3000.0, 0.8, 2.0, 0.374, 0.0205 + 3000.0, 0.8, 4.0, 0.6077, 0.03034 + 3000.0, 0.8, 6.0, 0.8414, 0.0469 + 3000.0, 0.8, 8.0, 1.0751, 0.07169 + 3000.0, 0.8, 10.0, 1.3089, 0.10626 + 3000.0, 0.85, -2.0, -0.0984, 0.0153 + 3000.0, 0.85, 0.0, 0.1476, 0.01644 + 3000.0, 0.85, 2.0, 0.3936, 0.02454 + 3000.0, 0.85, 4.0, 0.6396, 0.0414 + 3000.0, 0.85, 6.0, 0.8855, 0.06878 + 3000.0, 0.85, 8.0, 1.1315, 0.10849 + 3000.0, 0.85, 10.0, 1.3775, 0.16229 + 3000.0, 0.9, -2.0, -0.1047, 0.01724 + 3000.0, 0.9, 0.0, 0.1571, 0.02352 + 3000.0, 0.9, 2.0, 0.4188, 0.04102 + 3000.0, 0.9, 4.0, 0.6806, 0.07188 + 3000.0, 0.9, 6.0, 0.9424, 0.11826 + 3000.0, 0.9, 8.0, 1.2041, 0.18231 + 3000.0, 0.9, 10.0, 1.4659, 0.26617 + 6000.0, 0.0, -2.0, -0.0715, 0.00363 + 6000.0, 0.0, 0.0, 0.1072, 0.00384 + 6000.0, 0.0, 2.0, 0.286, 0.00621 + 6000.0, 0.0, 4.0, 0.4647, 0.01072 + 6000.0, 0.0, 6.0, 0.6434, 0.01737 + 6000.0, 0.0, 8.0, 0.8222, 0.02618 + 6000.0, 0.0, 10.0, 1.0009, 0.03713 + 6000.0, 0.2, -2.0, -0.0724, 0.01878 + 6000.0, 0.2, 0.0, 0.1086, 0.01904 + 6000.0, 0.2, 2.0, 0.2896, 0.0219 + 6000.0, 0.2, 4.0, 0.4706, 0.02735 + 6000.0, 0.2, 6.0, 0.6517, 0.0354 + 6000.0, 0.2, 8.0, 0.8327, 0.04605 + 6000.0, 0.2, 10.0, 1.0137, 0.0593 + 6000.0, 0.4, -2.0, -0.0754, 0.0172 + 6000.0, 0.4, 0.0, 0.1131, 0.01748 + 6000.0, 0.4, 2.0, 0.3016, 0.02053 + 6000.0, 0.4, 4.0, 0.4901, 0.02634 + 6000.0, 0.4, 6.0, 0.6786, 0.03493 + 6000.0, 0.4, 8.0, 0.867, 0.04628 + 6000.0, 0.4, 10.0, 1.0555, 0.0604 + 6000.0, 0.5, -2.0, -0.0779, 0.01669 + 6000.0, 0.5, 0.0, 0.1169, 0.01699 + 6000.0, 0.5, 2.0, 0.3117, 0.02022 + 6000.0, 0.5, 4.0, 0.5065, 0.0264 + 6000.0, 0.5, 6.0, 0.7013, 0.03551 + 6000.0, 0.5, 8.0, 0.8961, 0.04757 + 6000.0, 0.5, 10.0, 1.0909, 0.06256 + 6000.0, 0.6, -2.0, -0.0814, 0.01626 + 6000.0, 0.6, 0.0, 0.1221, 0.01658 + 6000.0, 0.6, 2.0, 0.3257, 0.0201 + 6000.0, 0.6, 4.0, 0.5293, 0.0268 + 6000.0, 0.6, 6.0, 0.7329, 0.03671 + 6000.0, 0.6, 8.0, 0.9365, 0.0498 + 6000.0, 0.6, 10.0, 1.1401, 0.06609 + 6000.0, 0.7, -2.0, -0.0863, 0.01589 + 6000.0, 0.7, 0.0, 0.1295, 0.01625 + 6000.0, 0.7, 2.0, 0.3454, 0.02018 + 6000.0, 0.7, 4.0, 0.5613, 0.02768 + 6000.0, 0.7, 6.0, 0.7771, 0.03876 + 6000.0, 0.7, 8.0, 0.993, 0.05342 + 6000.0, 0.7, 10.0, 1.2089, 0.07179 + 6000.0, 0.75, -2.0, -0.0896, 0.01572 + 6000.0, 0.75, 0.0, 0.1343, 0.0161 + 6000.0, 0.75, 2.0, 0.3582, 0.02032 + 6000.0, 0.75, 4.0, 0.5822, 0.02838 + 6000.0, 0.75, 6.0, 0.8061, 0.04041 + 6000.0, 0.75, 8.0, 1.03, 0.05742 + 6000.0, 0.75, 10.0, 1.2539, 0.08075 + 6000.0, 0.8, -2.0, -0.0935, 0.01556 + 6000.0, 0.8, 0.0, 0.1402, 0.01598 + 6000.0, 0.8, 2.0, 0.374, 0.02064 + 6000.0, 0.8, 4.0, 0.6077, 0.0305 + 6000.0, 0.8, 6.0, 0.8414, 0.04707 + 6000.0, 0.8, 8.0, 1.0751, 0.07189 + 6000.0, 0.8, 10.0, 1.3089, 0.10649 + 6000.0, 0.85, -2.0, -0.0984, 0.01543 + 6000.0, 0.85, 0.0, 0.1476, 0.01657 + 6000.0, 0.85, 2.0, 0.3936, 0.02468 + 6000.0, 0.85, 4.0, 0.6396, 0.04155 + 6000.0, 0.85, 6.0, 0.8855, 0.06896 + 6000.0, 0.85, 8.0, 1.1315, 0.10869 + 6000.0, 0.85, 10.0, 1.3775, 0.16253 + 6000.0, 0.9, -2.0, -0.1047, 0.01737 + 6000.0, 0.9, 0.0, 0.1571, 0.02365 + 6000.0, 0.9, 2.0, 0.4188, 0.04116 + 6000.0, 0.9, 4.0, 0.6806, 0.07204 + 6000.0, 0.9, 6.0, 0.9424, 0.11844 + 6000.0, 0.9, 8.0, 1.2041, 0.18252 + 6000.0, 0.9, 10.0, 1.4659, 0.26642 + 9000.0, 0.0, -2.0, -0.0715, 0.00363 + 9000.0, 0.0, 0.0, 0.1072, 0.00384 + 9000.0, 0.0, 2.0, 0.286, 0.00621 + 9000.0, 0.0, 4.0, 0.4647, 0.01072 + 9000.0, 0.0, 6.0, 0.6434, 0.01737 + 9000.0, 0.0, 8.0, 0.8222, 0.02618 + 9000.0, 0.0, 10.0, 1.0009, 0.03713 + 9000.0, 0.2, -2.0, -0.0724, 0.01898 + 9000.0, 0.2, 0.0, 0.1086, 0.01924 + 9000.0, 0.2, 2.0, 0.2896, 0.0221 + 9000.0, 0.2, 4.0, 0.4706, 0.02756 + 9000.0, 0.2, 6.0, 0.6517, 0.03563 + 9000.0, 0.2, 8.0, 0.8327, 0.0463 + 9000.0, 0.2, 10.0, 1.0137, 0.05958 + 9000.0, 0.4, -2.0, -0.0754, 0.01737 + 9000.0, 0.4, 0.0, 0.1131, 0.01765 + 9000.0, 0.4, 2.0, 0.3016, 0.0207 + 9000.0, 0.4, 4.0, 0.4901, 0.02653 + 9000.0, 0.4, 6.0, 0.6786, 0.03512 + 9000.0, 0.4, 8.0, 0.867, 0.0465 + 9000.0, 0.4, 10.0, 1.0555, 0.06064 + 9000.0, 0.5, -2.0, -0.0779, 0.01685 + 9000.0, 0.5, 0.0, 0.1169, 0.01715 + 9000.0, 0.5, 2.0, 0.3117, 0.02039 + 9000.0, 0.5, 4.0, 0.5065, 0.02657 + 9000.0, 0.5, 6.0, 0.7013, 0.0357 + 9000.0, 0.5, 8.0, 0.8961, 0.04778 + 9000.0, 0.5, 10.0, 1.0909, 0.0628 + 9000.0, 0.6, -2.0, -0.0814, 0.01641 + 9000.0, 0.6, 0.0, 0.1221, 0.01673 + 9000.0, 0.6, 2.0, 0.3257, 0.02025 + 9000.0, 0.6, 4.0, 0.5293, 0.02697 + 9000.0, 0.6, 6.0, 0.7329, 0.03689 + 9000.0, 0.6, 8.0, 0.9365, 0.05001 + 9000.0, 0.6, 10.0, 1.1401, 0.06632 + 9000.0, 0.7, -2.0, -0.0863, 0.01603 + 9000.0, 0.7, 0.0, 0.1295, 0.01639 + 9000.0, 0.7, 2.0, 0.3454, 0.02033 + 9000.0, 0.7, 4.0, 0.5613, 0.02785 + 9000.0, 0.7, 6.0, 0.7771, 0.03894 + 9000.0, 0.7, 8.0, 0.993, 0.05362 + 9000.0, 0.7, 10.0, 1.2089, 0.07202 + 9000.0, 0.75, -2.0, -0.0896, 0.01586 + 9000.0, 0.75, 0.0, 0.1343, 0.01625 + 9000.0, 0.75, 2.0, 0.3582, 0.02047 + 9000.0, 0.75, 4.0, 0.5822, 0.02854 + 9000.0, 0.75, 6.0, 0.8061, 0.04059 + 9000.0, 0.75, 8.0, 1.03, 0.05762 + 9000.0, 0.75, 10.0, 1.2539, 0.08098 + 9000.0, 0.8, -2.0, -0.0935, 0.0157 + 9000.0, 0.8, 0.0, 0.1402, 0.01612 + 9000.0, 0.8, 2.0, 0.374, 0.02079 + 9000.0, 0.8, 4.0, 0.6077, 0.03066 + 9000.0, 0.8, 6.0, 0.8414, 0.04725 + 9000.0, 0.8, 8.0, 1.0751, 0.0721 + 9000.0, 0.8, 10.0, 1.3089, 0.10672 + 9000.0, 0.85, -2.0, -0.0984, 0.01557 + 9000.0, 0.85, 0.0, 0.1476, 0.01671 + 9000.0, 0.85, 2.0, 0.3936, 0.02483 + 9000.0, 0.85, 4.0, 0.6396, 0.04171 + 9000.0, 0.85, 6.0, 0.8855, 0.06914 + 9000.0, 0.85, 8.0, 1.1315, 0.1089 + 9000.0, 0.85, 10.0, 1.3775, 0.16277 + 9000.0, 0.9, -2.0, -0.1047, 0.01751 + 9000.0, 0.9, 0.0, 0.1571, 0.02379 + 9000.0, 0.9, 2.0, 0.4188, 0.0413 + 9000.0, 0.9, 4.0, 0.6806, 0.0722 + 9000.0, 0.9, 6.0, 0.9424, 0.11862 + 9000.0, 0.9, 8.0, 1.2041, 0.18273 + 9000.0, 0.9, 10.0, 1.4659, 0.26667 + 12000.0, 0.0, -2.0, -0.0715, 0.00363 + 12000.0, 0.0, 0.0, 0.1072, 0.00384 + 12000.0, 0.0, 2.0, 0.286, 0.00621 + 12000.0, 0.0, 4.0, 0.4647, 0.01072 + 12000.0, 0.0, 6.0, 0.6434, 0.01737 + 12000.0, 0.0, 8.0, 0.8222, 0.02618 + 12000.0, 0.0, 10.0, 1.0009, 0.03713 + 12000.0, 0.2, -2.0, -0.0724, 0.01918 + 12000.0, 0.2, 0.0, 0.1086, 0.01944 + 12000.0, 0.2, 2.0, 0.2896, 0.02231 + 12000.0, 0.2, 4.0, 0.4706, 0.02778 + 12000.0, 0.2, 6.0, 0.6517, 0.03587 + 12000.0, 0.2, 8.0, 0.8327, 0.04656 + 12000.0, 0.2, 10.0, 1.0137, 0.05986 + 12000.0, 0.4, -2.0, -0.0754, 0.01755 + 12000.0, 0.4, 0.0, 0.1131, 0.01782 + 12000.0, 0.4, 2.0, 0.3016, 0.02088 + 12000.0, 0.4, 4.0, 0.4901, 0.02672 + 12000.0, 0.4, 6.0, 0.6786, 0.03533 + 12000.0, 0.4, 8.0, 0.867, 0.04672 + 12000.0, 0.4, 10.0, 1.0555, 0.06089 + 12000.0, 0.5, -2.0, -0.0779, 0.01702 + 12000.0, 0.5, 0.0, 0.1169, 0.01731 + 12000.0, 0.5, 2.0, 0.3117, 0.02056 + 12000.0, 0.5, 4.0, 0.5065, 0.02675 + 12000.0, 0.5, 6.0, 0.7013, 0.0359 + 12000.0, 0.5, 8.0, 0.8961, 0.04799 + 12000.0, 0.5, 10.0, 1.0909, 0.06304 + 12000.0, 0.6, -2.0, -0.0814, 0.01657 + 12000.0, 0.6, 0.0, 0.1221, 0.01689 + 12000.0, 0.6, 2.0, 0.3257, 0.02042 + 12000.0, 0.6, 4.0, 0.5293, 0.02715 + 12000.0, 0.6, 6.0, 0.7329, 0.03708 + 12000.0, 0.6, 8.0, 0.9365, 0.05022 + 12000.0, 0.6, 10.0, 1.1401, 0.06656 + 12000.0, 0.7, -2.0, -0.0863, 0.01619 + 12000.0, 0.7, 0.0, 0.1295, 0.01654 + 12000.0, 0.7, 2.0, 0.3454, 0.02049 + 12000.0, 0.7, 4.0, 0.5613, 0.02802 + 12000.0, 0.7, 6.0, 0.7771, 0.03913 + 12000.0, 0.7, 8.0, 0.993, 0.05383 + 12000.0, 0.7, 10.0, 1.2089, 0.07226 + 12000.0, 0.75, -2.0, -0.0896, 0.01601 + 12000.0, 0.75, 0.0, 0.1343, 0.0164 + 12000.0, 0.75, 2.0, 0.3582, 0.02063 + 12000.0, 0.75, 4.0, 0.5822, 0.02871 + 12000.0, 0.75, 6.0, 0.8061, 0.04077 + 12000.0, 0.75, 8.0, 1.03, 0.05783 + 12000.0, 0.75, 10.0, 1.2539, 0.08122 + 12000.0, 0.8, -2.0, -0.0935, 0.01585 + 12000.0, 0.8, 0.0, 0.1402, 0.01627 + 12000.0, 0.8, 2.0, 0.374, 0.02094 + 12000.0, 0.8, 4.0, 0.6077, 0.03083 + 12000.0, 0.8, 6.0, 0.8414, 0.04744 + 12000.0, 0.8, 8.0, 1.0751, 0.07231 + 12000.0, 0.8, 10.0, 1.3089, 0.10697 + 12000.0, 0.85, -2.0, -0.0984, 0.01571 + 12000.0, 0.85, 0.0, 0.1476, 0.01685 + 12000.0, 0.85, 2.0, 0.3936, 0.02498 + 12000.0, 0.85, 4.0, 0.6396, 0.04188 + 12000.0, 0.85, 6.0, 0.8855, 0.06933 + 12000.0, 0.85, 8.0, 1.1315, 0.10911 + 12000.0, 0.85, 10.0, 1.3775, 0.16302 + 12000.0, 0.9, -2.0, -0.1047, 0.01765 + 12000.0, 0.9, 0.0, 0.1571, 0.02393 + 12000.0, 0.9, 2.0, 0.4188, 0.04145 + 12000.0, 0.9, 4.0, 0.6806, 0.07236 + 12000.0, 0.9, 6.0, 0.9424, 0.11881 + 12000.0, 0.9, 8.0, 1.2041, 0.18295 + 12000.0, 0.9, 10.0, 1.4659, 0.26693 + 15000.0, 0.0, -2.0, -0.0715, 0.00363 + 15000.0, 0.0, 0.0, 0.1072, 0.00384 + 15000.0, 0.0, 2.0, 0.286, 0.00621 + 15000.0, 0.0, 4.0, 0.4647, 0.01072 + 15000.0, 0.0, 6.0, 0.6434, 0.01737 + 15000.0, 0.0, 8.0, 0.8222, 0.02618 + 15000.0, 0.0, 10.0, 1.0009, 0.03713 + 15000.0, 0.2, -2.0, -0.0724, 0.01939 + 15000.0, 0.2, 0.0, 0.1086, 0.01965 + 15000.0, 0.2, 2.0, 0.2896, 0.02252 + 15000.0, 0.2, 4.0, 0.4706, 0.02801 + 15000.0, 0.2, 6.0, 0.6517, 0.03611 + 15000.0, 0.2, 8.0, 0.8327, 0.04683 + 15000.0, 0.2, 10.0, 1.0137, 0.06016 + 15000.0, 0.4, -2.0, -0.0754, 0.01773 + 15000.0, 0.4, 0.0, 0.1131, 0.018 + 15000.0, 0.4, 2.0, 0.3016, 0.02107 + 15000.0, 0.4, 4.0, 0.4901, 0.02691 + 15000.0, 0.4, 6.0, 0.6786, 0.03554 + 15000.0, 0.4, 8.0, 0.867, 0.04696 + 15000.0, 0.4, 10.0, 1.0555, 0.06115 + 15000.0, 0.5, -2.0, -0.0779, 0.01719 + 15000.0, 0.5, 0.0, 0.1169, 0.01748 + 15000.0, 0.5, 2.0, 0.3117, 0.02073 + 15000.0, 0.5, 4.0, 0.5065, 0.02694 + 15000.0, 0.5, 6.0, 0.7013, 0.0361 + 15000.0, 0.5, 8.0, 0.8961, 0.04822 + 15000.0, 0.5, 10.0, 1.0909, 0.06329 + 15000.0, 0.6, -2.0, -0.0814, 0.01674 + 15000.0, 0.6, 0.0, 0.1221, 0.01706 + 15000.0, 0.6, 2.0, 0.3257, 0.02059 + 15000.0, 0.6, 4.0, 0.5293, 0.02733 + 15000.0, 0.6, 6.0, 0.7329, 0.03728 + 15000.0, 0.6, 8.0, 0.9365, 0.05044 + 15000.0, 0.6, 10.0, 1.1401, 0.06681 + 15000.0, 0.7, -2.0, -0.0863, 0.01634 + 15000.0, 0.7, 0.0, 0.1295, 0.0167 + 15000.0, 0.7, 2.0, 0.3454, 0.02065 + 15000.0, 0.7, 4.0, 0.5613, 0.02819 + 15000.0, 0.7, 6.0, 0.7771, 0.03932 + 15000.0, 0.7, 8.0, 0.993, 0.05405 + 15000.0, 0.7, 10.0, 1.2089, 0.07251 + 15000.0, 0.75, -2.0, -0.0896, 0.01617 + 15000.0, 0.75, 0.0, 0.1343, 0.01655 + 15000.0, 0.75, 2.0, 0.3582, 0.02079 + 15000.0, 0.75, 4.0, 0.5822, 0.02888 + 15000.0, 0.75, 6.0, 0.8061, 0.04097 + 15000.0, 0.75, 8.0, 1.03, 0.05805 + 15000.0, 0.75, 10.0, 1.2539, 0.08147 + 15000.0, 0.8, -2.0, -0.0935, 0.016 + 15000.0, 0.8, 0.0, 0.1402, 0.01642 + 15000.0, 0.8, 2.0, 0.374, 0.0211 + 15000.0, 0.8, 4.0, 0.6077, 0.031 + 15000.0, 0.8, 6.0, 0.8414, 0.04763 + 15000.0, 0.8, 8.0, 1.0751, 0.07253 + 15000.0, 0.8, 10.0, 1.3089, 0.10722 + 15000.0, 0.85, -2.0, -0.0984, 0.01586 + 15000.0, 0.85, 0.0, 0.1476, 0.017 + 15000.0, 0.85, 2.0, 0.3936, 0.02514 + 15000.0, 0.85, 4.0, 0.6396, 0.04205 + 15000.0, 0.85, 6.0, 0.8855, 0.06952 + 15000.0, 0.85, 8.0, 1.1315, 0.10934 + 15000.0, 0.85, 10.0, 1.3775, 0.16328 + 15000.0, 0.9, -2.0, -0.1047, 0.01779 + 15000.0, 0.9, 0.0, 0.1571, 0.02408 + 15000.0, 0.9, 2.0, 0.4188, 0.04161 + 15000.0, 0.9, 4.0, 0.6806, 0.07254 + 15000.0, 0.9, 6.0, 0.9424, 0.11901 + 15000.0, 0.9, 8.0, 1.2041, 0.18318 + 15000.0, 0.9, 10.0, 1.4659, 0.2672 + 18000.0, 0.0, -2.0, -0.0715, 0.00363 + 18000.0, 0.0, 0.0, 0.1072, 0.00384 + 18000.0, 0.0, 2.0, 0.286, 0.00621 + 18000.0, 0.0, 4.0, 0.4647, 0.01072 + 18000.0, 0.0, 6.0, 0.6434, 0.01737 + 18000.0, 0.0, 8.0, 0.8222, 0.02618 + 18000.0, 0.0, 10.0, 1.0009, 0.03713 + 18000.0, 0.2, -2.0, -0.0724, 0.01961 + 18000.0, 0.2, 0.0, 0.1086, 0.01987 + 18000.0, 0.2, 2.0, 0.2896, 0.02275 + 18000.0, 0.2, 4.0, 0.4706, 0.02825 + 18000.0, 0.2, 6.0, 0.6517, 0.03637 + 18000.0, 0.2, 8.0, 0.8327, 0.04711 + 18000.0, 0.2, 10.0, 1.0137, 0.06046 + 18000.0, 0.4, -2.0, -0.0754, 0.01791 + 18000.0, 0.4, 0.0, 0.1131, 0.01819 + 18000.0, 0.4, 2.0, 0.3016, 0.02126 + 18000.0, 0.4, 4.0, 0.4901, 0.02712 + 18000.0, 0.4, 6.0, 0.6786, 0.03576 + 18000.0, 0.4, 8.0, 0.867, 0.0472 + 18000.0, 0.4, 10.0, 1.0555, 0.06143 + 18000.0, 0.5, -2.0, -0.0779, 0.01737 + 18000.0, 0.5, 0.0, 0.1169, 0.01766 + 18000.0, 0.5, 2.0, 0.3117, 0.02092 + 18000.0, 0.5, 4.0, 0.5065, 0.02714 + 18000.0, 0.5, 6.0, 0.7013, 0.03632 + 18000.0, 0.5, 8.0, 0.8961, 0.04846 + 18000.0, 0.5, 10.0, 1.0909, 0.06356 + 18000.0, 0.6, -2.0, -0.0814, 0.01691 + 18000.0, 0.6, 0.0, 0.1221, 0.01723 + 18000.0, 0.6, 2.0, 0.3257, 0.02077 + 18000.0, 0.6, 4.0, 0.5293, 0.02752 + 18000.0, 0.6, 6.0, 0.7329, 0.03749 + 18000.0, 0.6, 8.0, 0.9365, 0.05067 + 18000.0, 0.6, 10.0, 1.1401, 0.06707 + 18000.0, 0.7, -2.0, -0.0863, 0.01651 + 18000.0, 0.7, 0.0, 0.1295, 0.01687 + 18000.0, 0.7, 2.0, 0.3454, 0.02082 + 18000.0, 0.7, 4.0, 0.5613, 0.02838 + 18000.0, 0.7, 6.0, 0.7771, 0.03953 + 18000.0, 0.7, 8.0, 0.993, 0.05427 + 18000.0, 0.7, 10.0, 1.2089, 0.07277 + 18000.0, 0.75, -2.0, -0.0896, 0.01633 + 18000.0, 0.75, 0.0, 0.1343, 0.01671 + 18000.0, 0.75, 2.0, 0.3582, 0.02096 + 18000.0, 0.75, 4.0, 0.5822, 0.02907 + 18000.0, 0.75, 6.0, 0.8061, 0.04117 + 18000.0, 0.75, 8.0, 1.03, 0.05828 + 18000.0, 0.75, 10.0, 1.2539, 0.08173 + 18000.0, 0.8, -2.0, -0.0935, 0.01616 + 18000.0, 0.8, 0.0, 0.1402, 0.01658 + 18000.0, 0.8, 2.0, 0.374, 0.02127 + 18000.0, 0.8, 4.0, 0.6077, 0.03118 + 18000.0, 0.8, 6.0, 0.8414, 0.04783 + 18000.0, 0.8, 8.0, 1.0751, 0.07276 + 18000.0, 0.8, 10.0, 1.3089, 0.10748 + 18000.0, 0.85, -2.0, -0.0984, 0.01601 + 18000.0, 0.85, 0.0, 0.1476, 0.01716 + 18000.0, 0.85, 2.0, 0.3936, 0.0253 + 18000.0, 0.85, 4.0, 0.6396, 0.04223 + 18000.0, 0.85, 6.0, 0.8855, 0.06972 + 18000.0, 0.85, 8.0, 1.1315, 0.10957 + 18000.0, 0.85, 10.0, 1.3775, 0.16355 + 18000.0, 0.9, -2.0, -0.1047, 0.01795 + 18000.0, 0.9, 0.0, 0.1571, 0.02423 + 18000.0, 0.9, 2.0, 0.4188, 0.04177 + 18000.0, 0.9, 4.0, 0.6806, 0.07271 + 18000.0, 0.9, 6.0, 0.9424, 0.11922 + 18000.0, 0.9, 8.0, 1.2041, 0.18342 + 18000.0, 0.9, 10.0, 1.4659, 0.26748 + 21000.0, 0.0, -2.0, -0.0715, 0.00363 + 21000.0, 0.0, 0.0, 0.1072, 0.00384 + 21000.0, 0.0, 2.0, 0.286, 0.00621 + 21000.0, 0.0, 4.0, 0.4647, 0.01072 + 21000.0, 0.0, 6.0, 0.6434, 0.01737 + 21000.0, 0.0, 8.0, 0.8222, 0.02618 + 21000.0, 0.0, 10.0, 1.0009, 0.03713 + 21000.0, 0.2, -2.0, -0.0724, 0.01983 + 21000.0, 0.2, 0.0, 0.1086, 0.0201 + 21000.0, 0.2, 2.0, 0.2896, 0.02298 + 21000.0, 0.2, 4.0, 0.4706, 0.0285 + 21000.0, 0.2, 6.0, 0.6517, 0.03663 + 21000.0, 0.2, 8.0, 0.8327, 0.0474 + 21000.0, 0.2, 10.0, 1.0137, 0.06079 + 21000.0, 0.4, -2.0, -0.0754, 0.01811 + 21000.0, 0.4, 0.0, 0.1131, 0.01839 + 21000.0, 0.4, 2.0, 0.3016, 0.02146 + 21000.0, 0.4, 4.0, 0.4901, 0.02733 + 21000.0, 0.4, 6.0, 0.6786, 0.036 + 21000.0, 0.4, 8.0, 0.867, 0.04745 + 21000.0, 0.4, 10.0, 1.0555, 0.06171 + 21000.0, 0.5, -2.0, -0.0779, 0.01755 + 21000.0, 0.5, 0.0, 0.1169, 0.01785 + 21000.0, 0.5, 2.0, 0.3117, 0.02111 + 21000.0, 0.5, 4.0, 0.5065, 0.02734 + 21000.0, 0.5, 6.0, 0.7013, 0.03654 + 21000.0, 0.5, 8.0, 0.8961, 0.0487 + 21000.0, 0.5, 10.0, 1.0909, 0.06383 + 21000.0, 0.6, -2.0, -0.0814, 0.01708 + 21000.0, 0.6, 0.0, 0.1221, 0.01741 + 21000.0, 0.6, 2.0, 0.3257, 0.02095 + 21000.0, 0.6, 4.0, 0.5293, 0.02771 + 21000.0, 0.6, 6.0, 0.7329, 0.0377 + 21000.0, 0.6, 8.0, 0.9365, 0.05091 + 21000.0, 0.6, 10.0, 1.1401, 0.06734 + 21000.0, 0.7, -2.0, -0.0863, 0.01668 + 21000.0, 0.7, 0.0, 0.1295, 0.01704 + 21000.0, 0.7, 2.0, 0.3454, 0.021 + 21000.0, 0.7, 4.0, 0.5613, 0.02857 + 21000.0, 0.7, 6.0, 0.7771, 0.03974 + 21000.0, 0.7, 8.0, 0.993, 0.05451 + 21000.0, 0.7, 10.0, 1.2089, 0.07304 + 21000.0, 0.75, -2.0, -0.0896, 0.01649 + 21000.0, 0.75, 0.0, 0.1343, 0.01688 + 21000.0, 0.75, 2.0, 0.3582, 0.02113 + 21000.0, 0.75, 4.0, 0.5822, 0.02925 + 21000.0, 0.75, 6.0, 0.8061, 0.04138 + 21000.0, 0.75, 8.0, 1.03, 0.05851 + 21000.0, 0.75, 10.0, 1.2539, 0.082 + 21000.0, 0.8, -2.0, -0.0935, 0.01632 + 21000.0, 0.8, 0.0, 0.1402, 0.01674 + 21000.0, 0.8, 2.0, 0.374, 0.02144 + 21000.0, 0.8, 4.0, 0.6077, 0.03137 + 21000.0, 0.8, 6.0, 0.8414, 0.04804 + 21000.0, 0.8, 8.0, 1.0751, 0.073 + 21000.0, 0.8, 10.0, 1.3089, 0.10776 + 21000.0, 0.85, -2.0, -0.0984, 0.01617 + 21000.0, 0.85, 0.0, 0.1476, 0.01732 + 21000.0, 0.85, 2.0, 0.3936, 0.02547 + 21000.0, 0.85, 4.0, 0.6396, 0.04241 + 21000.0, 0.85, 6.0, 0.8855, 0.06993 + 21000.0, 0.85, 8.0, 1.1315, 0.10981 + 21000.0, 0.85, 10.0, 1.3775, 0.16383 + 21000.0, 0.9, -2.0, -0.1047, 0.0181 + 21000.0, 0.9, 0.0, 0.1571, 0.02439 + 21000.0, 0.9, 2.0, 0.4188, 0.04194 + 21000.0, 0.9, 4.0, 0.6806, 0.0729 + 21000.0, 0.9, 6.0, 0.9424, 0.11943 + 21000.0, 0.9, 8.0, 1.2041, 0.18367 + 21000.0, 0.9, 10.0, 1.4659, 0.26777 + 24000.0, 0.0, -2.0, -0.0715, 0.00363 + 24000.0, 0.0, 0.0, 0.1072, 0.00384 + 24000.0, 0.0, 2.0, 0.286, 0.00621 + 24000.0, 0.0, 4.0, 0.4647, 0.01072 + 24000.0, 0.0, 6.0, 0.6434, 0.01737 + 24000.0, 0.0, 8.0, 0.8222, 0.02618 + 24000.0, 0.0, 10.0, 1.0009, 0.03713 + 24000.0, 0.2, -2.0, -0.0724, 0.02007 + 24000.0, 0.2, 0.0, 0.1086, 0.02034 + 24000.0, 0.2, 2.0, 0.2896, 0.02323 + 24000.0, 0.2, 4.0, 0.4706, 0.02876 + 24000.0, 0.2, 6.0, 0.6517, 0.03691 + 24000.0, 0.2, 8.0, 0.8327, 0.0477 + 24000.0, 0.2, 10.0, 1.0137, 0.06112 + 24000.0, 0.4, -2.0, -0.0754, 0.01831 + 24000.0, 0.4, 0.0, 0.1131, 0.01859 + 24000.0, 0.4, 2.0, 0.3016, 0.02167 + 24000.0, 0.4, 4.0, 0.4901, 0.02756 + 24000.0, 0.4, 6.0, 0.6786, 0.03624 + 24000.0, 0.4, 8.0, 0.867, 0.04772 + 24000.0, 0.4, 10.0, 1.0555, 0.062 + 24000.0, 0.5, -2.0, -0.0779, 0.01775 + 24000.0, 0.5, 0.0, 0.1169, 0.01804 + 24000.0, 0.5, 2.0, 0.3117, 0.02131 + 24000.0, 0.5, 4.0, 0.5065, 0.02755 + 24000.0, 0.5, 6.0, 0.7013, 0.03677 + 24000.0, 0.5, 8.0, 0.8961, 0.04895 + 24000.0, 0.5, 10.0, 1.0909, 0.06411 + 24000.0, 0.6, -2.0, -0.0814, 0.01727 + 24000.0, 0.6, 0.0, 0.1221, 0.01759 + 24000.0, 0.6, 2.0, 0.3257, 0.02114 + 24000.0, 0.6, 4.0, 0.5293, 0.02792 + 24000.0, 0.6, 6.0, 0.7329, 0.03792 + 24000.0, 0.6, 8.0, 0.9365, 0.05116 + 24000.0, 0.6, 10.0, 1.1401, 0.06762 + 24000.0, 0.7, -2.0, -0.0863, 0.01685 + 24000.0, 0.7, 0.0, 0.1295, 0.01722 + 24000.0, 0.7, 2.0, 0.3454, 0.02119 + 24000.0, 0.7, 4.0, 0.5613, 0.02877 + 24000.0, 0.7, 6.0, 0.7771, 0.03996 + 24000.0, 0.7, 8.0, 0.993, 0.05476 + 24000.0, 0.7, 10.0, 1.2089, 0.07332 + 24000.0, 0.75, -2.0, -0.0896, 0.01667 + 24000.0, 0.75, 0.0, 0.1343, 0.01705 + 24000.0, 0.75, 2.0, 0.3582, 0.02132 + 24000.0, 0.75, 4.0, 0.5822, 0.02945 + 24000.0, 0.75, 6.0, 0.8061, 0.0416 + 24000.0, 0.75, 8.0, 1.03, 0.05876 + 24000.0, 0.75, 10.0, 1.2539, 0.08228 + 24000.0, 0.8, -2.0, -0.0935, 0.01649 + 24000.0, 0.8, 0.0, 0.1402, 0.01691 + 24000.0, 0.8, 2.0, 0.374, 0.02162 + 24000.0, 0.8, 4.0, 0.6077, 0.03156 + 24000.0, 0.8, 6.0, 0.8414, 0.04826 + 24000.0, 0.8, 8.0, 1.0751, 0.07325 + 24000.0, 0.8, 10.0, 1.3089, 0.10805 + 24000.0, 0.85, -2.0, -0.0984, 0.01634 + 24000.0, 0.85, 0.0, 0.1476, 0.01749 + 24000.0, 0.85, 2.0, 0.3936, 0.02565 + 24000.0, 0.85, 4.0, 0.6396, 0.04261 + 24000.0, 0.85, 6.0, 0.8855, 0.07015 + 24000.0, 0.85, 8.0, 1.1315, 0.11006 + 24000.0, 0.85, 10.0, 1.3775, 0.16412 + 24000.0, 0.9, -2.0, -0.1047, 0.01827 + 24000.0, 0.9, 0.0, 0.1571, 0.02455 + 24000.0, 0.9, 2.0, 0.4188, 0.04211 + 24000.0, 0.9, 4.0, 0.6806, 0.0731 + 24000.0, 0.9, 6.0, 0.9424, 0.11965 + 24000.0, 0.9, 8.0, 1.2041, 0.18393 + 24000.0, 0.9, 10.0, 1.4659, 0.26808 + 27000.0, 0.0, -2.0, -0.0715, 0.00363 + 27000.0, 0.0, 0.0, 0.1072, 0.00384 + 27000.0, 0.0, 2.0, 0.286, 0.00621 + 27000.0, 0.0, 4.0, 0.4647, 0.01072 + 27000.0, 0.0, 6.0, 0.6434, 0.01737 + 27000.0, 0.0, 8.0, 0.8222, 0.02618 + 27000.0, 0.0, 10.0, 1.0009, 0.03713 + 27000.0, 0.2, -2.0, -0.0724, 0.02032 + 27000.0, 0.2, 0.0, 0.1086, 0.02058 + 27000.0, 0.2, 2.0, 0.2896, 0.02349 + 27000.0, 0.2, 4.0, 0.4706, 0.02903 + 27000.0, 0.2, 6.0, 0.6517, 0.0372 + 27000.0, 0.2, 8.0, 0.8327, 0.04802 + 27000.0, 0.2, 10.0, 1.0137, 0.06147 + 27000.0, 0.4, -2.0, -0.0754, 0.01853 + 27000.0, 0.4, 0.0, 0.1131, 0.01881 + 27000.0, 0.4, 2.0, 0.3016, 0.02189 + 27000.0, 0.4, 4.0, 0.4901, 0.02779 + 27000.0, 0.4, 6.0, 0.6786, 0.03649 + 27000.0, 0.4, 8.0, 0.867, 0.048 + 27000.0, 0.4, 10.0, 1.0555, 0.06231 + 27000.0, 0.5, -2.0, -0.0779, 0.01795 + 27000.0, 0.5, 0.0, 0.1169, 0.01824 + 27000.0, 0.5, 2.0, 0.3117, 0.02152 + 27000.0, 0.5, 4.0, 0.5065, 0.02778 + 27000.0, 0.5, 6.0, 0.7013, 0.03701 + 27000.0, 0.5, 8.0, 0.8961, 0.04922 + 27000.0, 0.5, 10.0, 1.0909, 0.06441 + 27000.0, 0.6, -2.0, -0.0814, 0.01746 + 27000.0, 0.6, 0.0, 0.1221, 0.01778 + 27000.0, 0.6, 2.0, 0.3257, 0.02134 + 27000.0, 0.6, 4.0, 0.5293, 0.02813 + 27000.0, 0.6, 6.0, 0.7329, 0.03816 + 27000.0, 0.6, 8.0, 0.9365, 0.05142 + 27000.0, 0.6, 10.0, 1.1401, 0.06791 + 27000.0, 0.7, -2.0, -0.0863, 0.01704 + 27000.0, 0.7, 0.0, 0.1295, 0.0174 + 27000.0, 0.7, 2.0, 0.3454, 0.02138 + 27000.0, 0.7, 4.0, 0.5613, 0.02897 + 27000.0, 0.7, 6.0, 0.7771, 0.04019 + 27000.0, 0.7, 8.0, 0.993, 0.05501 + 27000.0, 0.7, 10.0, 1.2089, 0.07361 + 27000.0, 0.75, -2.0, -0.0896, 0.01685 + 27000.0, 0.75, 0.0, 0.1343, 0.01724 + 27000.0, 0.75, 2.0, 0.3582, 0.02151 + 27000.0, 0.75, 4.0, 0.5822, 0.02966 + 27000.0, 0.75, 6.0, 0.8061, 0.04182 + 27000.0, 0.75, 8.0, 1.03, 0.05902 + 27000.0, 0.75, 10.0, 1.2539, 0.08258 + 27000.0, 0.8, -2.0, -0.0935, 0.01667 + 27000.0, 0.8, 0.0, 0.1402, 0.01709 + 27000.0, 0.8, 2.0, 0.374, 0.02181 + 27000.0, 0.8, 4.0, 0.6077, 0.03177 + 27000.0, 0.8, 6.0, 0.8414, 0.04849 + 27000.0, 0.8, 8.0, 1.0751, 0.0735 + 27000.0, 0.8, 10.0, 1.3089, 0.10835 + 27000.0, 0.85, -2.0, -0.0984, 0.01652 + 27000.0, 0.85, 0.0, 0.1476, 0.01766 + 27000.0, 0.85, 2.0, 0.3936, 0.02583 + 27000.0, 0.85, 4.0, 0.6396, 0.04281 + 27000.0, 0.85, 6.0, 0.8855, 0.07038 + 27000.0, 0.85, 8.0, 1.1315, 0.11033 + 27000.0, 0.85, 10.0, 1.3775, 0.16443 + 27000.0, 0.9, -2.0, -0.1047, 0.01844 + 27000.0, 0.9, 0.0, 0.1571, 0.02473 + 27000.0, 0.9, 2.0, 0.4188, 0.0423 + 27000.0, 0.9, 4.0, 0.6806, 0.0733 + 27000.0, 0.9, 6.0, 0.9424, 0.11988 + 27000.0, 0.9, 8.0, 1.2041, 0.1842 + 27000.0, 0.9, 10.0, 1.4659, 0.26839 + 30000.0, 0.0, -2.0, -0.0715, 0.00363 + 30000.0, 0.0, 0.0, 0.1072, 0.00384 + 30000.0, 0.0, 2.0, 0.286, 0.00621 + 30000.0, 0.0, 4.0, 0.4647, 0.01072 + 30000.0, 0.0, 6.0, 0.6434, 0.01737 + 30000.0, 0.0, 8.0, 0.8222, 0.02618 + 30000.0, 0.0, 10.0, 1.0009, 0.03713 + 30000.0, 0.2, -2.0, -0.0724, 0.02058 + 30000.0, 0.2, 0.0, 0.1086, 0.02085 + 30000.0, 0.2, 2.0, 0.2896, 0.02375 + 30000.0, 0.2, 4.0, 0.4706, 0.02931 + 30000.0, 0.2, 6.0, 0.6517, 0.03751 + 30000.0, 0.2, 8.0, 0.8327, 0.04835 + 30000.0, 0.2, 10.0, 1.0137, 0.06184 + 30000.0, 0.4, -2.0, -0.0754, 0.01875 + 30000.0, 0.4, 0.0, 0.1131, 0.01903 + 30000.0, 0.4, 2.0, 0.3016, 0.02212 + 30000.0, 0.4, 4.0, 0.4901, 0.02803 + 30000.0, 0.4, 6.0, 0.6786, 0.03675 + 30000.0, 0.4, 8.0, 0.867, 0.04828 + 30000.0, 0.4, 10.0, 1.0555, 0.06263 + 30000.0, 0.5, -2.0, -0.0779, 0.01816 + 30000.0, 0.5, 0.0, 0.1169, 0.01846 + 30000.0, 0.5, 2.0, 0.3117, 0.02174 + 30000.0, 0.5, 4.0, 0.5065, 0.02801 + 30000.0, 0.5, 6.0, 0.7013, 0.03726 + 30000.0, 0.5, 8.0, 0.8961, 0.0495 + 30000.0, 0.5, 10.0, 1.0909, 0.06472 + 30000.0, 0.6, -2.0, -0.0814, 0.01766 + 30000.0, 0.6, 0.0, 0.1221, 0.01799 + 30000.0, 0.6, 2.0, 0.3257, 0.02155 + 30000.0, 0.6, 4.0, 0.5293, 0.02836 + 30000.0, 0.6, 6.0, 0.7329, 0.0384 + 30000.0, 0.6, 8.0, 0.9365, 0.05169 + 30000.0, 0.6, 10.0, 1.1401, 0.06822 + 30000.0, 0.7, -2.0, -0.0863, 0.01723 + 30000.0, 0.7, 0.0, 0.1295, 0.01759 + 30000.0, 0.7, 2.0, 0.3454, 0.02158 + 30000.0, 0.7, 4.0, 0.5613, 0.02919 + 30000.0, 0.7, 6.0, 0.7771, 0.04043 + 30000.0, 0.7, 8.0, 0.993, 0.05528 + 30000.0, 0.7, 10.0, 1.2089, 0.07391 + 30000.0, 0.75, -2.0, -0.0896, 0.01704 + 30000.0, 0.75, 0.0, 0.1343, 0.01743 + 30000.0, 0.75, 2.0, 0.3582, 0.0217 + 30000.0, 0.75, 4.0, 0.5822, 0.02987 + 30000.0, 0.75, 6.0, 0.8061, 0.04206 + 30000.0, 0.75, 8.0, 1.03, 0.05929 + 30000.0, 0.75, 10.0, 1.2539, 0.08289 + 30000.0, 0.8, -2.0, -0.0935, 0.01686 + 30000.0, 0.8, 0.0, 0.1402, 0.01728 + 30000.0, 0.8, 2.0, 0.374, 0.022 + 30000.0, 0.8, 4.0, 0.6077, 0.03198 + 30000.0, 0.8, 6.0, 0.8414, 0.04873 + 30000.0, 0.8, 8.0, 1.0751, 0.07378 + 30000.0, 0.8, 10.0, 1.3089, 0.10866 + 30000.0, 0.85, -2.0, -0.0984, 0.0167 + 30000.0, 0.85, 0.0, 0.1476, 0.01785 + 30000.0, 0.85, 2.0, 0.3936, 0.02603 + 30000.0, 0.85, 4.0, 0.6396, 0.04302 + 30000.0, 0.85, 6.0, 0.8855, 0.07062 + 30000.0, 0.85, 8.0, 1.1315, 0.1106 + 30000.0, 0.85, 10.0, 1.3775, 0.16475 + 30000.0, 0.9, -2.0, -0.1047, 0.01862 + 30000.0, 0.9, 0.0, 0.1571, 0.02491 + 30000.0, 0.9, 2.0, 0.4188, 0.04249 + 30000.0, 0.9, 4.0, 0.6806, 0.07351 + 30000.0, 0.9, 6.0, 0.9424, 0.12012 + 30000.0, 0.9, 8.0, 1.2041, 0.18448 + 30000.0, 0.9, 10.0, 1.4659, 0.26872 + 33000.0, 0.0, -2.0, -0.0715, 0.00363 + 33000.0, 0.0, 0.0, 0.1072, 0.00384 + 33000.0, 0.0, 2.0, 0.286, 0.00621 + 33000.0, 0.0, 4.0, 0.4647, 0.01072 + 33000.0, 0.0, 6.0, 0.6434, 0.01737 + 33000.0, 0.0, 8.0, 0.8222, 0.02618 + 33000.0, 0.0, 10.0, 1.0009, 0.03713 + 33000.0, 0.2, -2.0, -0.0724, 0.02085 + 33000.0, 0.2, 0.0, 0.1086, 0.02112 + 33000.0, 0.2, 2.0, 0.2896, 0.02404 + 33000.0, 0.2, 4.0, 0.4706, 0.0296 + 33000.0, 0.2, 6.0, 0.6517, 0.03782 + 33000.0, 0.2, 8.0, 0.8327, 0.0487 + 33000.0, 0.2, 10.0, 1.0137, 0.06222 + 33000.0, 0.4, -2.0, -0.0754, 0.01898 + 33000.0, 0.4, 0.0, 0.1131, 0.01926 + 33000.0, 0.4, 2.0, 0.3016, 0.02236 + 33000.0, 0.4, 4.0, 0.4901, 0.02829 + 33000.0, 0.4, 6.0, 0.6786, 0.03703 + 33000.0, 0.4, 8.0, 0.867, 0.04859 + 33000.0, 0.4, 10.0, 1.0555, 0.06297 + 33000.0, 0.5, -2.0, -0.0779, 0.01838 + 33000.0, 0.5, 0.0, 0.1169, 0.01868 + 33000.0, 0.5, 2.0, 0.3117, 0.02197 + 33000.0, 0.5, 4.0, 0.5065, 0.02825 + 33000.0, 0.5, 6.0, 0.7013, 0.03752 + 33000.0, 0.5, 8.0, 0.8961, 0.04979 + 33000.0, 0.5, 10.0, 1.0909, 0.06505 + 33000.0, 0.6, -2.0, -0.0814, 0.01787 + 33000.0, 0.6, 0.0, 0.1221, 0.0182 + 33000.0, 0.6, 2.0, 0.3257, 0.02177 + 33000.0, 0.6, 4.0, 0.5293, 0.02859 + 33000.0, 0.6, 6.0, 0.7329, 0.03866 + 33000.0, 0.6, 8.0, 0.9365, 0.05197 + 33000.0, 0.6, 10.0, 1.1401, 0.06853 + 33000.0, 0.7, -2.0, -0.0863, 0.01743 + 33000.0, 0.7, 0.0, 0.1295, 0.0178 + 33000.0, 0.7, 2.0, 0.3454, 0.02179 + 33000.0, 0.7, 4.0, 0.5613, 0.02942 + 33000.0, 0.7, 6.0, 0.7771, 0.04067 + 33000.0, 0.7, 8.0, 0.993, 0.05556 + 33000.0, 0.7, 10.0, 1.2089, 0.07423 + 33000.0, 0.75, -2.0, -0.0896, 0.01723 + 33000.0, 0.75, 0.0, 0.1343, 0.01762 + 33000.0, 0.75, 2.0, 0.3582, 0.02191 + 33000.0, 0.75, 4.0, 0.5822, 0.03009 + 33000.0, 0.75, 6.0, 0.8061, 0.04231 + 33000.0, 0.75, 8.0, 1.03, 0.05957 + 33000.0, 0.75, 10.0, 1.2539, 0.08321 + 33000.0, 0.8, -2.0, -0.0935, 0.01705 + 33000.0, 0.8, 0.0, 0.1402, 0.01747 + 33000.0, 0.8, 2.0, 0.374, 0.02221 + 33000.0, 0.8, 4.0, 0.6077, 0.0322 + 33000.0, 0.8, 6.0, 0.8414, 0.04897 + 33000.0, 0.8, 8.0, 1.0751, 0.07406 + 33000.0, 0.8, 10.0, 1.3089, 0.10898 + 33000.0, 0.85, -2.0, -0.0984, 0.01689 + 33000.0, 0.85, 0.0, 0.1476, 0.01804 + 33000.0, 0.85, 2.0, 0.3936, 0.02623 + 33000.0, 0.85, 4.0, 0.6396, 0.04324 + 33000.0, 0.85, 6.0, 0.8855, 0.07087 + 33000.0, 0.85, 8.0, 1.1315, 0.11089 + 33000.0, 0.85, 10.0, 1.3775, 0.16508 + 33000.0, 0.9, -2.0, -0.1047, 0.01881 + 33000.0, 0.9, 0.0, 0.1571, 0.02509 + 33000.0, 0.9, 2.0, 0.4188, 0.04269 + 33000.0, 0.9, 4.0, 0.6806, 0.07373 + 33000.0, 0.9, 6.0, 0.9424, 0.12038 + 33000.0, 0.9, 8.0, 1.2041, 0.18477 + 33000.0, 0.9, 10.0, 1.4659, 0.26907 + 36000.0, 0.0, -2.0, -0.0715, 0.00363 + 36000.0, 0.0, 0.0, 0.1072, 0.00384 + 36000.0, 0.0, 2.0, 0.286, 0.00621 + 36000.0, 0.0, 4.0, 0.4647, 0.01072 + 36000.0, 0.0, 6.0, 0.6434, 0.01737 + 36000.0, 0.0, 8.0, 0.8222, 0.02618 + 36000.0, 0.0, 10.0, 1.0009, 0.03713 + 36000.0, 0.2, -2.0, -0.0724, 0.02114 + 36000.0, 0.2, 0.0, 0.1086, 0.0214 + 36000.0, 0.2, 2.0, 0.2896, 0.02433 + 36000.0, 0.2, 4.0, 0.4706, 0.02991 + 36000.0, 0.2, 6.0, 0.6517, 0.03816 + 36000.0, 0.2, 8.0, 0.8327, 0.04906 + 36000.0, 0.2, 10.0, 1.0137, 0.06262 + 36000.0, 0.4, -2.0, -0.0754, 0.01922 + 36000.0, 0.4, 0.0, 0.1131, 0.01951 + 36000.0, 0.4, 2.0, 0.3016, 0.02262 + 36000.0, 0.4, 4.0, 0.4901, 0.02855 + 36000.0, 0.4, 6.0, 0.6786, 0.03731 + 36000.0, 0.4, 8.0, 0.867, 0.0489 + 36000.0, 0.4, 10.0, 1.0555, 0.06332 + 36000.0, 0.5, -2.0, -0.0779, 0.01861 + 36000.0, 0.5, 0.0, 0.1169, 0.01891 + 36000.0, 0.5, 2.0, 0.3117, 0.02221 + 36000.0, 0.5, 4.0, 0.5065, 0.0285 + 36000.0, 0.5, 6.0, 0.7013, 0.0378 + 36000.0, 0.5, 8.0, 0.8961, 0.05009 + 36000.0, 0.5, 10.0, 1.0909, 0.06539 + 36000.0, 0.6, -2.0, -0.0814, 0.01809 + 36000.0, 0.6, 0.0, 0.1221, 0.01842 + 36000.0, 0.6, 2.0, 0.3257, 0.022 + 36000.0, 0.6, 4.0, 0.5293, 0.02883 + 36000.0, 0.6, 6.0, 0.7329, 0.03892 + 36000.0, 0.6, 8.0, 0.9365, 0.05227 + 36000.0, 0.6, 10.0, 1.1401, 0.06887 + 36000.0, 0.7, -2.0, -0.0863, 0.01765 + 36000.0, 0.7, 0.0, 0.1295, 0.01801 + 36000.0, 0.7, 2.0, 0.3454, 0.02201 + 36000.0, 0.7, 4.0, 0.5613, 0.02965 + 36000.0, 0.7, 6.0, 0.7771, 0.04094 + 36000.0, 0.7, 8.0, 0.993, 0.05586 + 36000.0, 0.7, 10.0, 1.2089, 0.07457 + 36000.0, 0.75, -2.0, -0.0896, 0.01744 + 36000.0, 0.75, 0.0, 0.1343, 0.01783 + 36000.0, 0.75, 2.0, 0.3582, 0.02213 + 36000.0, 0.75, 4.0, 0.5822, 0.03033 + 36000.0, 0.75, 6.0, 0.8061, 0.04257 + 36000.0, 0.75, 8.0, 1.03, 0.05986 + 36000.0, 0.75, 10.0, 1.2539, 0.08354 + 36000.0, 0.8, -2.0, -0.0935, 0.01725 + 36000.0, 0.8, 0.0, 0.1402, 0.01768 + 36000.0, 0.8, 2.0, 0.374, 0.02242 + 36000.0, 0.8, 4.0, 0.6077, 0.03243 + 36000.0, 0.8, 6.0, 0.8414, 0.04923 + 36000.0, 0.8, 8.0, 1.0751, 0.07435 + 36000.0, 0.8, 10.0, 1.3089, 0.10932 + 36000.0, 0.85, -2.0, -0.0984, 0.01709 + 36000.0, 0.85, 0.0, 0.1476, 0.01824 + 36000.0, 0.85, 2.0, 0.3936, 0.02644 + 36000.0, 0.85, 4.0, 0.6396, 0.04347 + 36000.0, 0.85, 6.0, 0.8855, 0.07113 + 36000.0, 0.85, 8.0, 1.1315, 0.11119 + 36000.0, 0.85, 10.0, 1.3775, 0.16543 + 36000.0, 0.9, -2.0, -0.1047, 0.019 + 36000.0, 0.9, 0.0, 0.1571, 0.02529 + 36000.0, 0.9, 2.0, 0.4188, 0.04289 + 36000.0, 0.9, 4.0, 0.6806, 0.07396 + 36000.0, 0.9, 6.0, 0.9424, 0.12064 + 36000.0, 0.9, 8.0, 1.2041, 0.18508 + 36000.0, 0.9, 10.0, 1.4659, 0.0 + 38000.0, 0.0, -2.0, -0.0715, 0.00363 + 38000.0, 0.0, 0.0, 0.1072, 0.00384 + 38000.0, 0.0, 2.0, 0.286, 0.00621 + 38000.0, 0.0, 4.0, 0.4647, 0.01072 + 38000.0, 0.0, 6.0, 0.6434, 0.01737 + 38000.0, 0.0, 8.0, 0.8222, 0.02618 + 38000.0, 0.0, 10.0, 1.0009, 0.03713 + 38000.0, 0.2, -2.0, -0.0724, 0.0214 + 38000.0, 0.2, 0.0, 0.1086, 0.02166 + 38000.0, 0.2, 2.0, 0.2896, 0.0246 + 38000.0, 0.2, 4.0, 0.4706, 0.0302 + 38000.0, 0.2, 6.0, 0.6517, 0.03846 + 38000.0, 0.2, 8.0, 0.8327, 0.04939 + 38000.0, 0.2, 10.0, 1.0137, 0.06299 + 38000.0, 0.4, -2.0, -0.0754, 0.01945 + 38000.0, 0.4, 0.0, 0.1131, 0.01973 + 38000.0, 0.4, 2.0, 0.3016, 0.02285 + 38000.0, 0.4, 4.0, 0.4901, 0.02879 + 38000.0, 0.4, 6.0, 0.6786, 0.03758 + 38000.0, 0.4, 8.0, 0.867, 0.04919 + 38000.0, 0.4, 10.0, 1.0555, 0.06364 + 38000.0, 0.5, -2.0, -0.0779, 0.01882 + 38000.0, 0.5, 0.0, 0.1169, 0.01912 + 38000.0, 0.5, 2.0, 0.3117, 0.02242 + 38000.0, 0.5, 4.0, 0.5065, 0.02874 + 38000.0, 0.5, 6.0, 0.7013, 0.03805 + 38000.0, 0.5, 8.0, 0.8961, 0.05037 + 38000.0, 0.5, 10.0, 1.0909, 0.0657 + 38000.0, 0.6, -2.0, -0.0814, 0.01829 + 38000.0, 0.6, 0.0, 0.1221, 0.01862 + 38000.0, 0.6, 2.0, 0.3257, 0.02221 + 38000.0, 0.6, 4.0, 0.5293, 0.02906 + 38000.0, 0.6, 6.0, 0.7329, 0.03917 + 38000.0, 0.6, 8.0, 0.9365, 0.05254 + 38000.0, 0.6, 10.0, 1.1401, 0.06917 + 38000.0, 0.7, -2.0, -0.0863, 0.01784 + 38000.0, 0.7, 0.0, 0.1295, 0.0182 + 38000.0, 0.7, 2.0, 0.3454, 0.02221 + 38000.0, 0.7, 4.0, 0.5613, 0.02987 + 38000.0, 0.7, 6.0, 0.7771, 0.04117 + 38000.0, 0.7, 8.0, 0.993, 0.05612 + 38000.0, 0.7, 10.0, 1.2089, 0.07487 + 38000.0, 0.75, -2.0, -0.0896, 0.01763 + 38000.0, 0.75, 0.0, 0.1343, 0.01802 + 38000.0, 0.75, 2.0, 0.3582, 0.02232 + 38000.0, 0.75, 4.0, 0.5822, 0.03054 + 38000.0, 0.75, 6.0, 0.8061, 0.04281 + 38000.0, 0.75, 8.0, 1.03, 0.06013 + 38000.0, 0.75, 10.0, 1.2539, 0.08385 + 38000.0, 0.8, -2.0, -0.0935, 0.01744 + 38000.0, 0.8, 0.0, 0.1402, 0.01786 + 38000.0, 0.8, 2.0, 0.374, 0.02261 + 38000.0, 0.8, 4.0, 0.6077, 0.03264 + 38000.0, 0.8, 6.0, 0.8414, 0.04947 + 38000.0, 0.8, 8.0, 1.0751, 0.07462 + 38000.0, 0.8, 10.0, 1.3089, 0.10963 + 38000.0, 0.85, -2.0, -0.0984, 0.01727 + 38000.0, 0.85, 0.0, 0.1476, 0.01842 + 38000.0, 0.85, 2.0, 0.3936, 0.02663 + 38000.0, 0.85, 4.0, 0.6396, 0.04368 + 38000.0, 0.85, 6.0, 0.8855, 0.07137 + 38000.0, 0.85, 8.0, 1.1315, 0.11146 + 38000.0, 0.85, 10.0, 1.3775, 0.16575 + 38000.0, 0.9, -2.0, -0.1047, 0.01918 + 38000.0, 0.9, 0.0, 0.1571, 0.02547 + 38000.0, 0.9, 2.0, 0.4188, 0.04308 + 38000.0, 0.9, 4.0, 0.6806, 0.07417 + 38000.0, 0.9, 6.0, 0.9424, 0.12088 + 38000.0, 0.9, 8.0, 1.2041, 0.18536 + 38000.0, 0.9, 10.0, 1.4659, 0.26976 + 42000.0, 0.0, -2.0, -0.0715, 0.00363 + 42000.0, 0.0, 0.0, 0.1072, 0.00384 + 42000.0, 0.0, 2.0, 0.286, 0.00621 + 42000.0, 0.0, 4.0, 0.4647, 0.01072 + 42000.0, 0.0, 6.0, 0.6434, 0.01737 + 42000.0, 0.0, 8.0, 0.8222, 0.02618 + 42000.0, 0.0, 10.0, 1.0009, 0.03713 + 42000.0, 0.2, -2.0, -0.0724, 0.02194 + 42000.0, 0.2, 0.0, 0.1086, 0.02221 + 42000.0, 0.2, 2.0, 0.2896, 0.02516 + 42000.0, 0.2, 4.0, 0.4706, 0.03079 + 42000.0, 0.2, 6.0, 0.6517, 0.0391 + 42000.0, 0.2, 8.0, 0.8327, 0.05009 + 42000.0, 0.2, 10.0, 1.0137, 0.06376 + 42000.0, 0.4, -2.0, -0.0754, 0.01991 + 42000.0, 0.4, 0.0, 0.1131, 0.0202 + 42000.0, 0.4, 2.0, 0.3016, 0.02333 + 42000.0, 0.4, 4.0, 0.4901, 0.0293 + 42000.0, 0.4, 6.0, 0.6786, 0.03812 + 42000.0, 0.4, 8.0, 0.867, 0.04979 + 42000.0, 0.4, 10.0, 1.0555, 0.06431 + 42000.0, 0.5, -2.0, -0.0779, 0.01926 + 42000.0, 0.5, 0.0, 0.1169, 0.01956 + 42000.0, 0.5, 2.0, 0.3117, 0.02288 + 42000.0, 0.5, 4.0, 0.5065, 0.02922 + 42000.0, 0.5, 6.0, 0.7013, 0.03858 + 42000.0, 0.5, 8.0, 0.8961, 0.05095 + 42000.0, 0.5, 10.0, 1.0909, 0.06634 + 42000.0, 0.6, -2.0, -0.0814, 0.01871 + 42000.0, 0.6, 0.0, 0.1221, 0.01904 + 42000.0, 0.6, 2.0, 0.3257, 0.02264 + 42000.0, 0.6, 4.0, 0.5293, 0.02952 + 42000.0, 0.6, 6.0, 0.7329, 0.03968 + 42000.0, 0.6, 8.0, 0.9365, 0.0531 + 42000.0, 0.6, 10.0, 1.1401, 0.06981 + 42000.0, 0.7, -2.0, -0.0863, 0.01824 + 42000.0, 0.7, 0.0, 0.1295, 0.0186 + 42000.0, 0.7, 2.0, 0.3454, 0.02263 + 42000.0, 0.7, 4.0, 0.5613, 0.03032 + 42000.0, 0.7, 6.0, 0.7771, 0.04167 + 42000.0, 0.7, 8.0, 0.993, 0.05668 + 42000.0, 0.7, 10.0, 1.2089, 0.07551 + 42000.0, 0.75, -2.0, -0.0896, 0.01802 + 42000.0, 0.75, 0.0, 0.1343, 0.01842 + 42000.0, 0.75, 2.0, 0.3582, 0.02274 + 42000.0, 0.75, 4.0, 0.5822, 0.03099 + 42000.0, 0.75, 6.0, 0.8061, 0.0433 + 42000.0, 0.75, 8.0, 1.03, 0.06069 + 42000.0, 0.75, 10.0, 1.2539, 0.08449 + 42000.0, 0.8, -2.0, -0.0935, 0.01782 + 42000.0, 0.8, 0.0, 0.1402, 0.01825 + 42000.0, 0.8, 2.0, 0.374, 0.02302 + 42000.0, 0.8, 4.0, 0.6077, 0.03309 + 42000.0, 0.8, 6.0, 0.8414, 0.04996 + 42000.0, 0.8, 8.0, 1.0751, 0.07519 + 42000.0, 0.8, 10.0, 1.3089, 0.11028 + 42000.0, 0.85, -2.0, -0.0984, 0.01765 + 42000.0, 0.85, 0.0, 0.1476, 0.0188 + 42000.0, 0.85, 2.0, 0.3936, 0.02703 + 42000.0, 0.85, 4.0, 0.6396, 0.04412 + 42000.0, 0.85, 6.0, 0.8855, 0.07186 + 42000.0, 0.85, 8.0, 1.1315, 0.11203 + 42000.0, 0.85, 10.0, 1.3775, 0.16642 + 42000.0, 0.9, -2.0, -0.1047, 0.01955 + 42000.0, 0.9, 0.0, 0.1571, 0.02584 + 42000.0, 0.9, 2.0, 0.4188, 0.04348 + 42000.0, 0.9, 4.0, 0.6806, 0.07461 + 42000.0, 0.9, 6.0, 0.9424, 0.12138 + 42000.0, 0.9, 8.0, 1.2041, 0.18595 + 42000.0, 0.9, 10.0, 1.4659, 0.27045 diff --git a/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_ground.csv b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_ground.csv new file mode 100644 index 0000000000..8ce1caee90 --- /dev/null +++ b/aviary/models/aircraft/large_single_aisle_1/large_single_aisle_1_aero_ground.csv @@ -0,0 +1,798 @@ +# created 06/11/25 +# GASP_ALT-derived aerodynamics data converted from aero_ground_GASP.txt +# Incremental Lift and Drag Coeff. for Ground Effects +# Reference Area = 1370. sqft / Flap Deflection = 10 deg (T.O. Setting) + +Mach (input), Angle of Attack (deg, input), Hob (output), Delta CL (output), Delta CD (output) + 0.0, -2.0, 0.05, -0.02737, -0.00156 + 0.0, -2.0, 0.1, -0.01769, -0.0012 + 0.0, -2.0, 0.2, -0.01032, -0.00075 + 0.0, -2.0, 0.3, -0.00655, -0.00049 + 0.0, -2.0, 0.4, -0.00431, -0.00033 + 0.0, -2.0, 0.5, -0.00291, -0.00022 + 0.0, -2.0, 0.6, -0.00199, -0.00016 + 0.0, -2.0, 0.8, -0.00097, -8e-05 + 0.0, -2.0, 1.0, -0.00049, -4e-05 + 0.0, -2.0, 1.5, -9e-05, -1e-05 + 0.0, -2.0, 2.0, -1e-05, -0.0 + 0.0, -2.0, 3.0, 0.0, -0.0 + 0.0, 0.0, 0.05, 0.03824, -0.00376 + 0.0, 0.0, 0.1, 0.02525, -0.00269 + 0.0, 0.0, 0.2, 0.01495, -0.00154 + 0.0, 0.0, 0.3, 0.00954, -0.00095 + 0.0, 0.0, 0.4, 0.00628, -0.00062 + 0.0, 0.0, 0.5, 0.00423, -0.00041 + 0.0, 0.0, 0.6, 0.00289, -0.00028 + 0.0, 0.0, 0.8, 0.0014, -0.00014 + 0.0, 0.0, 1.0, 0.00069, -7e-05 + 0.0, 0.0, 1.5, 0.00012, -2e-05 + 0.0, 0.0, 2.0, 1e-05, -0.0 + 0.0, 0.0, 3.0, 0.0, -0.0 + 0.0, 2.0, 0.05, 0.09445, -0.00691 + 0.0, 2.0, 0.1, 0.06394, -0.00476 + 0.0, 2.0, 0.2, 0.03847, -0.00256 + 0.0, 2.0, 0.3, 0.02465, -0.00153 + 0.0, 2.0, 0.4, 0.01626, -0.00097 + 0.0, 2.0, 0.5, 0.01094, -0.00064 + 0.0, 2.0, 0.6, 0.00747, -0.00044 + 0.0, 2.0, 0.8, 0.00358, -0.00021 + 0.0, 2.0, 1.0, 0.00175, -0.00011 + 0.0, 2.0, 1.5, 0.00028, -3e-05 + 0.0, 2.0, 2.0, 1e-05, -1e-05 + 0.0, 2.0, 3.0, 0.0, -0.0 + 0.0, 4.0, 0.05, 0.14127, -0.01115 + 0.0, 4.0, 0.1, 0.09837, -0.00748 + 0.0, 4.0, 0.2, 0.06024, -0.00385 + 0.0, 4.0, 0.3, 0.03878, -0.00224 + 0.0, 4.0, 0.4, 0.02561, -0.0014 + 0.0, 4.0, 0.5, 0.01722, -0.00092 + 0.0, 4.0, 0.6, 0.01173, -0.00062 + 0.0, 4.0, 0.8, 0.00558, -0.00031 + 0.0, 4.0, 1.0, 0.00269, -0.00017 + 0.0, 4.0, 1.5, 0.00038, -4e-05 + 0.0, 4.0, 2.0, 0.0, -2e-05 + 0.0, 4.0, 3.0, 0.0, -0.0 + 0.0, 6.0, 0.05, 0.17869, -0.01661 + 0.0, 6.0, 0.1, 0.12854, -0.01094 + 0.0, 6.0, 0.2, 0.08024, -0.00548 + 0.0, 6.0, 0.3, 0.05193, -0.00312 + 0.0, 6.0, 0.4, 0.03434, -0.00193 + 0.0, 6.0, 0.5, 0.02307, -0.00126 + 0.0, 6.0, 0.6, 0.01568, -0.00085 + 0.0, 6.0, 0.8, 0.00739, -0.00043 + 0.0, 6.0, 1.0, 0.00351, -0.00024 + 0.0, 6.0, 1.5, 0.00043, -7e-05 + 0.0, 6.0, 2.0, 0.0, -2e-05 + 0.0, 6.0, 3.0, 0.0, -0.0 + 0.0, 8.0, 0.05, 0.20671, -0.02343 + 0.0, 8.0, 0.1, 0.15446, -0.01524 + 0.0, 8.0, 0.2, 0.09849, -0.00747 + 0.0, 8.0, 0.3, 0.06411, -0.0042 + 0.0, 8.0, 0.4, 0.04245, -0.00258 + 0.0, 8.0, 0.5, 0.02849, -0.00168 + 0.0, 8.0, 0.6, 0.01931, -0.00114 + 0.0, 8.0, 0.8, 0.00901, -0.00058 + 0.0, 8.0, 1.0, 0.0042, -0.00033 + 0.0, 8.0, 1.5, 0.00042, -0.0001 + 0.0, 8.0, 2.0, 0.0, -3e-05 + 0.0, 8.0, 3.0, 0.0, -0.0 + 0.0, 10.0, 0.05, 0.22534, -0.03174 + 0.0, 10.0, 0.1, 0.17612, -0.02046 + 0.0, 10.0, 0.2, 0.11498, -0.00989 + 0.0, 10.0, 0.3, 0.0753, -0.00552 + 0.0, 10.0, 0.4, 0.04994, -0.00337 + 0.0, 10.0, 0.5, 0.03348, -0.00219 + 0.0, 10.0, 0.6, 0.02263, -0.0015 + 0.0, 10.0, 0.8, 0.01045, -0.00077 + 0.0, 10.0, 1.0, 0.00477, -0.00044 + 0.0, 10.0, 1.5, 0.00035, -0.00015 + 0.0, 10.0, 2.0, 0.0, -4e-05 + 0.0, 10.0, 3.0, 0.0, -0.0 + 0.0, 12.0, 0.05, 0.23457, -0.04167 + 0.0, 12.0, 0.1, 0.19352, -0.02669 + 0.0, 12.0, 0.2, 0.12972, -0.01278 + 0.0, 12.0, 0.3, 0.08552, -0.00709 + 0.0, 12.0, 0.4, 0.0568, -0.00432 + 0.0, 12.0, 0.5, 0.03805, -0.00281 + 0.0, 12.0, 0.6, 0.02564, -0.00193 + 0.0, 12.0, 0.8, 0.01171, -0.00101 + 0.0, 12.0, 1.0, 0.00522, -0.00059 + 0.0, 12.0, 1.5, 0.00023, -0.00021 + 0.0, 12.0, 2.0, 0.0, -5e-05 + 0.0, 12.0, 3.0, 0.0, -0.0 + 0.0, 14.0, 0.05, 0.23441, -0.05335 + 0.0, 14.0, 0.1, 0.20668, -0.034 + 0.0, 14.0, 0.2, 0.1427, -0.01619 + 0.0, 14.0, 0.3, 0.09475, -0.00894 + 0.0, 14.0, 0.4, 0.06303, -0.00545 + 0.0, 14.0, 0.5, 0.04218, -0.00356 + 0.0, 14.0, 0.6, 0.02834, -0.00244 + 0.0, 14.0, 0.8, 0.01277, -0.00129 + 0.0, 14.0, 1.0, 0.00554, -0.00077 + 0.0, 14.0, 1.5, 5e-05, -0.00028 + 0.0, 14.0, 2.0, 0.0, -7e-05 + 0.0, 14.0, 3.0, 0.0, -0.0 + 0.0, 16.0, 0.05, 0.22485, -0.06687 + 0.0, 16.0, 0.1, 0.21557, -0.04249 + 0.0, 16.0, 0.2, 0.15392, -0.02015 + 0.0, 16.0, 0.3, 0.10301, -0.01112 + 0.0, 16.0, 0.4, 0.06865, -0.00678 + 0.0, 16.0, 0.5, 0.04588, -0.00443 + 0.0, 16.0, 0.6, 0.03073, -0.00306 + 0.0, 16.0, 0.8, 0.01366, -0.00164 + 0.0, 16.0, 1.0, 0.00575, -0.00098 + 0.0, 16.0, 1.5, 0.0, -0.00035 + 0.0, 16.0, 2.0, 0.0, -8e-05 + 0.0, 16.0, 3.0, 0.0, -0.0 + 0.0, 18.0, 0.05, 0.15099, -0.08524 + 0.0, 18.0, 0.1, 0.15099, -0.05762 + 0.0, 18.0, 0.2, 0.15099, -0.02604 + 0.0, 18.0, 0.3, 0.11029, -0.01364 + 0.0, 18.0, 0.4, 0.07364, -0.00833 + 0.0, 18.0, 0.5, 0.04916, -0.00546 + 0.0, 18.0, 0.6, 0.0328, -0.00378 + 0.0, 18.0, 0.8, 0.01435, -0.00205 + 0.0, 18.0, 1.0, 0.00583, -0.00124 + 0.0, 18.0, 1.5, 0.0, -0.00042 + 0.0, 18.0, 2.0, 0.0, -9e-05 + 0.0, 18.0, 3.0, 0.0, -0.0 + 0.1, -2.0, 0.05, -0.02752, -0.00188 + 0.1, -2.0, 0.1, -0.01777, -0.00143 + 0.1, -2.0, 0.2, -0.01037, -0.0009 + 0.1, -2.0, 0.3, -0.00658, -0.00059 + 0.1, -2.0, 0.4, -0.00433, -0.00039 + 0.1, -2.0, 0.5, -0.00292, -0.00027 + 0.1, -2.0, 0.6, -0.002, -0.00019 + 0.1, -2.0, 0.8, -0.00097, -9e-05 + 0.1, -2.0, 1.0, -0.00049, -5e-05 + 0.1, -2.0, 1.5, -9e-05, -1e-05 + 0.1, -2.0, 2.0, -1e-05, -0.0 + 0.1, -2.0, 3.0, 0.0, -0.0 + 0.1, 0.0, 0.05, 0.03844, -0.00453 + 0.1, 0.0, 0.1, 0.02537, -0.00323 + 0.1, 0.0, 0.2, 0.01502, -0.00184 + 0.1, 0.0, 0.3, 0.00958, -0.00114 + 0.1, 0.0, 0.4, 0.00631, -0.00074 + 0.1, 0.0, 0.5, 0.00425, -0.0005 + 0.1, 0.0, 0.6, 0.00291, -0.00034 + 0.1, 0.0, 0.8, 0.0014, -0.00017 + 0.1, 0.0, 1.0, 0.0007, -9e-05 + 0.1, 0.0, 1.5, 0.00012, -2e-05 + 0.1, 0.0, 2.0, 1e-05, -1e-05 + 0.1, 0.0, 3.0, 0.0, -0.0 + 0.1, 2.0, 0.05, 0.09493, -0.00831 + 0.1, 2.0, 0.1, 0.06423, -0.00571 + 0.1, 2.0, 0.2, 0.03865, -0.00306 + 0.1, 2.0, 0.3, 0.02476, -0.00183 + 0.1, 2.0, 0.4, 0.01633, -0.00116 + 0.1, 2.0, 0.5, 0.01099, -0.00077 + 0.1, 2.0, 0.6, 0.0075, -0.00052 + 0.1, 2.0, 0.8, 0.0036, -0.00026 + 0.1, 2.0, 1.0, 0.00176, -0.00014 + 0.1, 2.0, 1.5, 0.00028, -3e-05 + 0.1, 2.0, 2.0, 1e-05, -1e-05 + 0.1, 2.0, 3.0, 0.0, -0.0 + 0.1, 4.0, 0.05, 0.14197, -0.0134 + 0.1, 4.0, 0.1, 0.09881, -0.00897 + 0.1, 4.0, 0.2, 0.0605, -0.00462 + 0.1, 4.0, 0.3, 0.03895, -0.00268 + 0.1, 4.0, 0.4, 0.02573, -0.00167 + 0.1, 4.0, 0.5, 0.0173, -0.0011 + 0.1, 4.0, 0.6, 0.01178, -0.00075 + 0.1, 4.0, 0.8, 0.0056, -0.00037 + 0.1, 4.0, 1.0, 0.0027, -0.0002 + 0.1, 4.0, 1.5, 0.00038, -5e-05 + 0.1, 4.0, 2.0, 0.0, -2e-05 + 0.1, 4.0, 3.0, 0.0, -0.0 + 0.1, 6.0, 0.05, 0.17954, -0.01996 + 0.1, 6.0, 0.1, 0.12911, -0.01314 + 0.1, 6.0, 0.2, 0.08059, -0.00657 + 0.1, 6.0, 0.3, 0.05216, -0.00374 + 0.1, 6.0, 0.4, 0.03449, -0.00231 + 0.1, 6.0, 0.5, 0.02317, -0.00151 + 0.1, 6.0, 0.6, 0.01574, -0.00102 + 0.1, 6.0, 0.8, 0.00742, -0.00051 + 0.1, 6.0, 1.0, 0.00352, -0.00028 + 0.1, 6.0, 1.5, 0.00043, -8e-05 + 0.1, 6.0, 2.0, 0.0, -3e-05 + 0.1, 6.0, 3.0, 0.0, -0.0 + 0.1, 8.0, 0.05, 0.20766, -0.02816 + 0.1, 8.0, 0.1, 0.15512, -0.0183 + 0.1, 8.0, 0.2, 0.09891, -0.00896 + 0.1, 8.0, 0.3, 0.06438, -0.00504 + 0.1, 8.0, 0.4, 0.04263, -0.00309 + 0.1, 8.0, 0.5, 0.02861, -0.00201 + 0.1, 8.0, 0.6, 0.01939, -0.00137 + 0.1, 8.0, 0.8, 0.00905, -0.0007 + 0.1, 8.0, 1.0, 0.00422, -0.00039 + 0.1, 8.0, 1.5, 0.00042, -0.00013 + 0.1, 8.0, 2.0, 0.0, -4e-05 + 0.1, 8.0, 3.0, 0.0, -0.0 + 0.1, 10.0, 0.05, 0.22633, -0.03815 + 0.1, 10.0, 0.1, 0.17685, -0.02457 + 0.1, 10.0, 0.2, 0.11546, -0.01187 + 0.1, 10.0, 0.3, 0.07562, -0.00661 + 0.1, 10.0, 0.4, 0.05014, -0.00404 + 0.1, 10.0, 0.5, 0.03362, -0.00263 + 0.1, 10.0, 0.6, 0.02273, -0.00179 + 0.1, 10.0, 0.8, 0.01049, -0.00093 + 0.1, 10.0, 1.0, 0.00479, -0.00053 + 0.1, 10.0, 1.5, 0.00035, -0.00018 + 0.1, 10.0, 2.0, 0.0, -5e-05 + 0.1, 10.0, 3.0, 0.0, -0.0 + 0.1, 12.0, 0.05, 0.23553, -0.05009 + 0.1, 12.0, 0.1, 0.19429, -0.03205 + 0.1, 12.0, 0.2, 0.13024, -0.01534 + 0.1, 12.0, 0.3, 0.08587, -0.0085 + 0.1, 12.0, 0.4, 0.05703, -0.00518 + 0.1, 12.0, 0.5, 0.0382, -0.00337 + 0.1, 12.0, 0.6, 0.02575, -0.00231 + 0.1, 12.0, 0.8, 0.01175, -0.00121 + 0.1, 12.0, 1.0, 0.00524, -0.0007 + 0.1, 12.0, 1.5, 0.00023, -0.00025 + 0.1, 12.0, 2.0, 0.0, -6e-05 + 0.1, 12.0, 3.0, 0.0, -0.0 + 0.1, 14.0, 0.05, 0.23528, -0.06412 + 0.1, 14.0, 0.1, 0.20745, -0.04084 + 0.1, 14.0, 0.2, 0.14326, -0.01943 + 0.1, 14.0, 0.3, 0.09513, -0.01073 + 0.1, 14.0, 0.4, 0.06329, -0.00653 + 0.1, 14.0, 0.5, 0.04235, -0.00427 + 0.1, 14.0, 0.6, 0.02845, -0.00293 + 0.1, 14.0, 0.8, 0.01282, -0.00155 + 0.1, 14.0, 1.0, 0.00556, -0.00092 + 0.1, 14.0, 1.5, 5e-05, -0.00034 + 0.1, 14.0, 2.0, 0.0, -8e-05 + 0.1, 14.0, 3.0, 0.0, -0.0 + 0.1, 16.0, 0.05, 0.22557, -0.08039 + 0.1, 16.0, 0.1, 0.21633, -0.05104 + 0.1, 16.0, 0.2, 0.1545, -0.02419 + 0.1, 16.0, 0.3, 0.10341, -0.01335 + 0.1, 16.0, 0.4, 0.06892, -0.00813 + 0.1, 16.0, 0.5, 0.04606, -0.00532 + 0.1, 16.0, 0.6, 0.03084, -0.00367 + 0.1, 16.0, 0.8, 0.01371, -0.00197 + 0.1, 16.0, 1.0, 0.00577, -0.00118 + 0.1, 16.0, 1.5, 0.0, -0.00043 + 0.1, 16.0, 2.0, 0.0, -0.0001 + 0.1, 16.0, 3.0, 0.0, -0.0 + 0.1, 18.0, 0.05, 0.14509, -0.10285 + 0.1, 18.0, 0.1, 0.14509, -0.06982 + 0.1, 18.0, 0.2, 0.14509, -0.03208 + 0.1, 18.0, 0.3, 0.11071, -0.01638 + 0.1, 18.0, 0.4, 0.07392, -0.00999 + 0.1, 18.0, 0.5, 0.04934, -0.00655 + 0.1, 18.0, 0.6, 0.03292, -0.00454 + 0.1, 18.0, 0.8, 0.0144, -0.00246 + 0.1, 18.0, 1.0, 0.00584, -0.00149 + 0.1, 18.0, 1.5, 0.0, -0.00051 + 0.1, 18.0, 2.0, 0.0, -0.00011 + 0.1, 18.0, 3.0, 0.0, -0.0 + 0.2, -2.0, 0.05, -0.02796, -0.00183 + 0.2, -2.0, 0.1, -0.01803, -0.0014 + 0.2, -2.0, 0.2, -0.01052, -0.00088 + 0.2, -2.0, 0.3, -0.00668, -0.00058 + 0.2, -2.0, 0.4, -0.00439, -0.00039 + 0.2, -2.0, 0.5, -0.00296, -0.00026 + 0.2, -2.0, 0.6, -0.00203, -0.00018 + 0.2, -2.0, 0.8, -0.00099, -9e-05 + 0.2, -2.0, 1.0, -0.0005, -5e-05 + 0.2, -2.0, 1.5, -9e-05, -1e-05 + 0.2, -2.0, 2.0, -2e-05, -0.0 + 0.2, -2.0, 3.0, 0.0, -0.0 + 0.2, 0.0, 0.05, 0.03904, -0.00446 + 0.2, 0.0, 0.1, 0.02574, -0.00318 + 0.2, 0.0, 0.2, 0.01523, -0.00181 + 0.2, 0.0, 0.3, 0.00971, -0.00112 + 0.2, 0.0, 0.4, 0.0064, -0.00073 + 0.2, 0.0, 0.5, 0.00431, -0.00049 + 0.2, 0.0, 0.6, 0.00295, -0.00033 + 0.2, 0.0, 0.8, 0.00142, -0.00016 + 0.2, 0.0, 1.0, 0.00071, -8e-05 + 0.2, 0.0, 1.5, 0.00012, -2e-05 + 0.2, 0.0, 2.0, 1e-05, -1e-05 + 0.2, 0.0, 3.0, 0.0, -0.0 + 0.2, 2.0, 0.05, 0.0964, -0.00821 + 0.2, 2.0, 0.1, 0.06514, -0.00564 + 0.2, 2.0, 0.2, 0.03918, -0.00302 + 0.2, 2.0, 0.3, 0.0251, -0.0018 + 0.2, 2.0, 0.4, 0.01656, -0.00114 + 0.2, 2.0, 0.5, 0.01114, -0.00075 + 0.2, 2.0, 0.6, 0.0076, -0.00051 + 0.2, 2.0, 0.8, 0.00364, -0.00025 + 0.2, 2.0, 1.0, 0.00179, -0.00013 + 0.2, 2.0, 1.5, 0.00028, -3e-05 + 0.2, 2.0, 2.0, 1e-05, -1e-05 + 0.2, 2.0, 3.0, 0.0, -0.0 + 0.2, 4.0, 0.05, 0.1441, -0.01327 + 0.2, 4.0, 0.1, 0.10018, -0.00888 + 0.2, 4.0, 0.2, 0.06132, -0.00456 + 0.2, 4.0, 0.3, 0.03947, -0.00265 + 0.2, 4.0, 0.4, 0.02607, -0.00165 + 0.2, 4.0, 0.5, 0.01753, -0.00108 + 0.2, 4.0, 0.6, 0.01194, -0.00073 + 0.2, 4.0, 0.8, 0.00568, -0.00037 + 0.2, 4.0, 1.0, 0.00274, -0.0002 + 0.2, 4.0, 1.5, 0.00039, -5e-05 + 0.2, 4.0, 2.0, 0.0, -2e-05 + 0.2, 4.0, 3.0, 0.0, -0.0 + 0.2, 6.0, 0.05, 0.18216, -0.01981 + 0.2, 6.0, 0.1, 0.13084, -0.01303 + 0.2, 6.0, 0.2, 0.08165, -0.0065 + 0.2, 6.0, 0.3, 0.05285, -0.0037 + 0.2, 6.0, 0.4, 0.03495, -0.00228 + 0.2, 6.0, 0.5, 0.02348, -0.00149 + 0.2, 6.0, 0.6, 0.01595, -0.00101 + 0.2, 6.0, 0.8, 0.00751, -0.00051 + 0.2, 6.0, 1.0, 0.00356, -0.00028 + 0.2, 6.0, 1.5, 0.00043, -8e-05 + 0.2, 6.0, 2.0, 0.0, -3e-05 + 0.2, 6.0, 3.0, 0.0, -0.0 + 0.2, 8.0, 0.05, 0.21057, -0.02799 + 0.2, 8.0, 0.1, 0.15713, -0.01818 + 0.2, 8.0, 0.2, 0.10019, -0.00889 + 0.2, 8.0, 0.3, 0.06521, -0.00499 + 0.2, 8.0, 0.4, 0.04318, -0.00305 + 0.2, 8.0, 0.5, 0.02898, -0.00199 + 0.2, 8.0, 0.6, 0.01964, -0.00135 + 0.2, 8.0, 0.8, 0.00916, -0.00069 + 0.2, 8.0, 1.0, 0.00427, -0.00039 + 0.2, 8.0, 1.5, 0.00042, -0.00012 + 0.2, 8.0, 2.0, 0.0, -4e-05 + 0.2, 8.0, 3.0, 0.0, -0.0 + 0.2, 10.0, 0.05, 0.22933, -0.03797 + 0.2, 10.0, 0.1, 0.17906, -0.02444 + 0.2, 10.0, 0.2, 0.11692, -0.01178 + 0.2, 10.0, 0.3, 0.07657, -0.00655 + 0.2, 10.0, 0.4, 0.05078, -0.004 + 0.2, 10.0, 0.5, 0.03405, -0.0026 + 0.2, 10.0, 0.6, 0.02301, -0.00178 + 0.2, 10.0, 0.8, 0.01062, -0.00092 + 0.2, 10.0, 1.0, 0.00484, -0.00053 + 0.2, 10.0, 1.5, 0.00035, -0.00018 + 0.2, 10.0, 2.0, 0.0, -5e-05 + 0.2, 10.0, 3.0, 0.0, -0.0 + 0.2, 12.0, 0.05, 0.23844, -0.04991 + 0.2, 12.0, 0.1, 0.19661, -0.03191 + 0.2, 12.0, 0.2, 0.13184, -0.01524 + 0.2, 12.0, 0.3, 0.08693, -0.00843 + 0.2, 12.0, 0.4, 0.05774, -0.00513 + 0.2, 12.0, 0.5, 0.03867, -0.00334 + 0.2, 12.0, 0.6, 0.02606, -0.00229 + 0.2, 12.0, 0.8, 0.01189, -0.0012 + 0.2, 12.0, 1.0, 0.00529, -0.0007 + 0.2, 12.0, 1.5, 0.00022, -0.00025 + 0.2, 12.0, 2.0, 0.0, -6e-05 + 0.2, 12.0, 3.0, 0.0, -0.0 + 0.2, 14.0, 0.05, 0.23791, -0.06395 + 0.2, 14.0, 0.1, 0.2098, -0.0407 + 0.2, 14.0, 0.2, 0.14496, -0.01932 + 0.2, 14.0, 0.3, 0.09628, -0.01066 + 0.2, 14.0, 0.4, 0.06405, -0.00649 + 0.2, 14.0, 0.5, 0.04286, -0.00423 + 0.2, 14.0, 0.6, 0.02879, -0.00291 + 0.2, 14.0, 0.8, 0.01297, -0.00154 + 0.2, 14.0, 1.0, 0.00562, -0.00092 + 0.2, 14.0, 1.5, 4e-05, -0.00034 + 0.2, 14.0, 2.0, 0.0, -8e-05 + 0.2, 14.0, 3.0, 0.0, -0.0 + 0.2, 16.0, 0.05, 0.22773, -0.08024 + 0.2, 16.0, 0.1, 0.21861, -0.05091 + 0.2, 16.0, 0.2, 0.15628, -0.02409 + 0.2, 16.0, 0.3, 0.10463, -0.01327 + 0.2, 16.0, 0.4, 0.06973, -0.00808 + 0.2, 16.0, 0.5, 0.0466, -0.00529 + 0.2, 16.0, 0.6, 0.0312, -0.00365 + 0.2, 16.0, 0.8, 0.01385, -0.00196 + 0.2, 16.0, 1.0, 0.00582, -0.00118 + 0.2, 16.0, 1.5, 0.0, -0.00042 + 0.2, 16.0, 2.0, 0.0, -0.0001 + 0.2, 16.0, 3.0, 0.0, -0.0 + 0.2, 18.0, 0.05, 0.127, -0.1039 + 0.2, 18.0, 0.1, 0.127, -0.07147 + 0.2, 18.0, 0.2, 0.127, -0.03443 + 0.2, 18.0, 0.3, 0.11197, -0.0163 + 0.2, 18.0, 0.4, 0.07477, -0.00994 + 0.2, 18.0, 0.5, 0.0499, -0.00652 + 0.2, 18.0, 0.6, 0.03329, -0.00452 + 0.2, 18.0, 0.8, 0.01455, -0.00245 + 0.2, 18.0, 1.0, 0.00589, -0.00149 + 0.2, 18.0, 1.5, 0.0, -0.00051 + 0.2, 18.0, 2.0, 0.0, -0.00011 + 0.2, 18.0, 3.0, 0.0, -0.0 + 0.3, -2.0, 0.05, -0.02873, -0.0018 + 0.3, -2.0, 0.1, -0.01849, -0.00137 + 0.3, -2.0, 0.2, -0.01077, -0.00086 + 0.3, -2.0, 0.3, -0.00684, -0.00056 + 0.3, -2.0, 0.4, -0.0045, -0.00038 + 0.3, -2.0, 0.5, -0.00303, -0.00026 + 0.3, -2.0, 0.6, -0.00208, -0.00018 + 0.3, -2.0, 0.8, -0.00101, -9e-05 + 0.3, -2.0, 1.0, -0.00051, -5e-05 + 0.3, -2.0, 1.5, -0.0001, -1e-05 + 0.3, -2.0, 2.0, -2e-05, -0.0 + 0.3, -2.0, 3.0, 0.0, -0.0 + 0.3, 0.0, 0.05, 0.0401, -0.00442 + 0.3, 0.0, 0.1, 0.02638, -0.00316 + 0.3, 0.0, 0.2, 0.0156, -0.0018 + 0.3, 0.0, 0.3, 0.00994, -0.00111 + 0.3, 0.0, 0.4, 0.00655, -0.00072 + 0.3, 0.0, 0.5, 0.00441, -0.00048 + 0.3, 0.0, 0.6, 0.00302, -0.00033 + 0.3, 0.0, 0.8, 0.00146, -0.00016 + 0.3, 0.0, 1.0, 0.00072, -8e-05 + 0.3, 0.0, 1.5, 0.00013, -2e-05 + 0.3, 0.0, 2.0, 1e-05, -1e-05 + 0.3, 0.0, 3.0, 0.0, -0.0 + 0.3, 2.0, 0.05, 0.09895, -0.0082 + 0.3, 2.0, 0.1, 0.06672, -0.00563 + 0.3, 2.0, 0.2, 0.04009, -0.00301 + 0.3, 2.0, 0.3, 0.02568, -0.00179 + 0.3, 2.0, 0.4, 0.01694, -0.00113 + 0.3, 2.0, 0.5, 0.0114, -0.00075 + 0.3, 2.0, 0.6, 0.00778, -0.00051 + 0.3, 2.0, 0.8, 0.00373, -0.00025 + 0.3, 2.0, 1.0, 0.00183, -0.00013 + 0.3, 2.0, 1.5, 0.00029, -3e-05 + 0.3, 2.0, 2.0, 1e-05, -1e-05 + 0.3, 2.0, 3.0, 0.0, -0.0 + 0.3, 4.0, 0.05, 0.14781, -0.01332 + 0.3, 4.0, 0.1, 0.10254, -0.00891 + 0.3, 4.0, 0.2, 0.06273, -0.00456 + 0.3, 4.0, 0.3, 0.04038, -0.00264 + 0.3, 4.0, 0.4, 0.02667, -0.00164 + 0.3, 4.0, 0.5, 0.01793, -0.00108 + 0.3, 4.0, 0.6, 0.01221, -0.00073 + 0.3, 4.0, 0.8, 0.0058, -0.00036 + 0.3, 4.0, 1.0, 0.0028, -0.0002 + 0.3, 4.0, 1.5, 0.00039, -5e-05 + 0.3, 4.0, 2.0, 0.0, -2e-05 + 0.3, 4.0, 3.0, 0.0, -0.0 + 0.3, 6.0, 0.05, 0.18669, -0.01995 + 0.3, 6.0, 0.1, 0.13383, -0.0131 + 0.3, 6.0, 0.2, 0.08349, -0.00651 + 0.3, 6.0, 0.3, 0.05403, -0.0037 + 0.3, 6.0, 0.4, 0.03573, -0.00228 + 0.3, 6.0, 0.5, 0.024, -0.00148 + 0.3, 6.0, 0.6, 0.0163, -0.00101 + 0.3, 6.0, 0.8, 0.00768, -0.00051 + 0.3, 6.0, 1.0, 0.00364, -0.00028 + 0.3, 6.0, 1.5, 0.00044, -8e-05 + 0.3, 6.0, 2.0, 0.0, -3e-05 + 0.3, 6.0, 3.0, 0.0, -0.0 + 0.3, 8.0, 0.05, 0.21559, -0.02826 + 0.3, 8.0, 0.1, 0.16061, -0.01832 + 0.3, 8.0, 0.2, 0.10239, -0.00893 + 0.3, 8.0, 0.3, 0.06665, -0.005 + 0.3, 8.0, 0.4, 0.04413, -0.00306 + 0.3, 8.0, 0.5, 0.02962, -0.00199 + 0.3, 8.0, 0.6, 0.02007, -0.00135 + 0.3, 8.0, 0.8, 0.00936, -0.00069 + 0.3, 8.0, 1.0, 0.00435, -0.00039 + 0.3, 8.0, 1.5, 0.00043, -0.00013 + 0.3, 8.0, 2.0, 0.0, -4e-05 + 0.3, 8.0, 3.0, 0.0, -0.0 + 0.3, 10.0, 0.05, 0.2345, -0.03841 + 0.3, 10.0, 0.1, 0.18286, -0.02469 + 0.3, 10.0, 0.2, 0.11942, -0.01186 + 0.3, 10.0, 0.3, 0.07822, -0.00658 + 0.3, 10.0, 0.4, 0.05187, -0.00401 + 0.3, 10.0, 0.5, 0.03478, -0.00261 + 0.3, 10.0, 0.6, 0.0235, -0.00178 + 0.3, 10.0, 0.8, 0.01084, -0.00092 + 0.3, 10.0, 1.0, 0.00494, -0.00053 + 0.3, 10.0, 1.5, 0.00035, -0.00018 + 0.3, 10.0, 2.0, 0.0, -5e-05 + 0.3, 10.0, 3.0, 0.0, -0.0 + 0.3, 12.0, 0.05, 0.24343, -0.05058 + 0.3, 12.0, 0.1, 0.20059, -0.0323 + 0.3, 12.0, 0.2, 0.13459, -0.01537 + 0.3, 12.0, 0.3, 0.08876, -0.00849 + 0.3, 12.0, 0.4, 0.05895, -0.00516 + 0.3, 12.0, 0.5, 0.03948, -0.00336 + 0.3, 12.0, 0.6, 0.0266, -0.0023 + 0.3, 12.0, 0.8, 0.01213, -0.00121 + 0.3, 12.0, 1.0, 0.00539, -0.00071 + 0.3, 12.0, 1.5, 0.00022, -0.00026 + 0.3, 12.0, 2.0, 0.0, -6e-05 + 0.3, 12.0, 3.0, 0.0, -0.0 + 0.3, 14.0, 0.05, 0.24237, -0.06491 + 0.3, 14.0, 0.1, 0.2138, -0.04126 + 0.3, 14.0, 0.2, 0.14788, -0.01953 + 0.3, 14.0, 0.3, 0.09825, -0.01075 + 0.3, 14.0, 0.4, 0.06537, -0.00653 + 0.3, 14.0, 0.5, 0.04373, -0.00426 + 0.3, 14.0, 0.6, 0.02937, -0.00293 + 0.3, 14.0, 0.8, 0.01322, -0.00156 + 0.3, 14.0, 1.0, 0.00571, -0.00093 + 0.3, 14.0, 1.5, 2e-05, -0.00035 + 0.3, 14.0, 2.0, 0.0, -8e-05 + 0.3, 14.0, 3.0, 0.0, -0.0 + 0.3, 16.0, 0.05, 0.23133, -0.08156 + 0.3, 16.0, 0.1, 0.22249, -0.05169 + 0.3, 16.0, 0.2, 0.15932, -0.02439 + 0.3, 16.0, 0.3, 0.10671, -0.01341 + 0.3, 16.0, 0.4, 0.07112, -0.00815 + 0.3, 16.0, 0.5, 0.04752, -0.00533 + 0.3, 16.0, 0.6, 0.03181, -0.00368 + 0.3, 16.0, 0.8, 0.01411, -0.00198 + 0.3, 16.0, 1.0, 0.00591, -0.00119 + 0.3, 16.0, 1.5, 0.0, -0.00043 + 0.3, 16.0, 2.0, 0.0, -0.0001 + 0.3, 16.0, 3.0, 0.0, -0.0 + 0.3, 18.0, 0.05, 0.09556, -0.10771 + 0.3, 18.0, 0.1, 0.09556, -0.07569 + 0.3, 18.0, 0.2, 0.09556, -0.03911 + 0.3, 18.0, 0.3, 0.09556, -0.01911 + 0.3, 18.0, 0.4, 0.07621, -0.01005 + 0.3, 18.0, 0.5, 0.05086, -0.00659 + 0.3, 18.0, 0.6, 0.03391, -0.00457 + 0.3, 18.0, 0.8, 0.0148, -0.00248 + 0.3, 18.0, 1.0, 0.00597, -0.00151 + 0.3, 18.0, 1.5, 0.0, -0.00052 + 0.3, 18.0, 2.0, 0.0, -0.00012 + 0.3, 18.0, 3.0, 0.0, -0.0 + 0.4, -2.0, 0.05, -0.02989, -0.00175 + 0.4, -2.0, 0.1, -0.01917, -0.00134 + 0.4, -2.0, 0.2, -0.01115, -0.00084 + 0.4, -2.0, 0.3, -0.00707, -0.00055 + 0.4, -2.0, 0.4, -0.00466, -0.00037 + 0.4, -2.0, 0.5, -0.00314, -0.00025 + 0.4, -2.0, 0.6, -0.00215, -0.00018 + 0.4, -2.0, 0.8, -0.00105, -9e-05 + 0.4, -2.0, 1.0, -0.00053, -4e-05 + 0.4, -2.0, 1.5, -0.0001, -1e-05 + 0.4, -2.0, 2.0, -2e-05, -0.0 + 0.4, -2.0, 3.0, 0.0, -0.0 + 0.4, 0.0, 0.05, 0.04169, -0.00441 + 0.4, 0.0, 0.1, 0.02732, -0.00314 + 0.4, 0.0, 0.2, 0.01613, -0.00179 + 0.4, 0.0, 0.3, 0.01028, -0.0011 + 0.4, 0.0, 0.4, 0.00677, -0.00072 + 0.4, 0.0, 0.5, 0.00456, -0.00048 + 0.4, 0.0, 0.6, 0.00312, -0.00033 + 0.4, 0.0, 0.8, 0.00151, -0.00016 + 0.4, 0.0, 1.0, 0.00075, -8e-05 + 0.4, 0.0, 1.5, 0.00013, -2e-05 + 0.4, 0.0, 2.0, 1e-05, -0.0 + 0.4, 0.0, 3.0, 0.0, -0.0 + 0.4, 2.0, 0.05, 0.10277, -0.00826 + 0.4, 2.0, 0.1, 0.06906, -0.00566 + 0.4, 2.0, 0.2, 0.04145, -0.00301 + 0.4, 2.0, 0.3, 0.02654, -0.00179 + 0.4, 2.0, 0.4, 0.01751, -0.00113 + 0.4, 2.0, 0.5, 0.01178, -0.00075 + 0.4, 2.0, 0.6, 0.00804, -0.00051 + 0.4, 2.0, 0.8, 0.00385, -0.00025 + 0.4, 2.0, 1.0, 0.00189, -0.00013 + 0.4, 2.0, 1.5, 0.0003, -3e-05 + 0.4, 2.0, 2.0, 1e-05, -1e-05 + 0.4, 2.0, 3.0, 0.0, -0.0 + 0.4, 4.0, 0.05, 0.15335, -0.01349 + 0.4, 4.0, 0.1, 0.10603, -0.009 + 0.4, 4.0, 0.2, 0.06481, -0.00459 + 0.4, 4.0, 0.3, 0.04171, -0.00265 + 0.4, 4.0, 0.4, 0.02755, -0.00165 + 0.4, 4.0, 0.5, 0.01852, -0.00108 + 0.4, 4.0, 0.6, 0.01261, -0.00073 + 0.4, 4.0, 0.8, 0.00599, -0.00036 + 0.4, 4.0, 1.0, 0.00289, -0.0002 + 0.4, 4.0, 1.5, 0.00041, -5e-05 + 0.4, 4.0, 2.0, 0.0, -2e-05 + 0.4, 4.0, 3.0, 0.0, -0.0 + 0.4, 6.0, 0.05, 0.19343, -0.02029 + 0.4, 6.0, 0.1, 0.13826, -0.0133 + 0.4, 6.0, 0.2, 0.08621, -0.00658 + 0.4, 6.0, 0.3, 0.05579, -0.00372 + 0.4, 6.0, 0.4, 0.03689, -0.00229 + 0.4, 6.0, 0.5, 0.02478, -0.00149 + 0.4, 6.0, 0.6, 0.01683, -0.00101 + 0.4, 6.0, 0.8, 0.00792, -0.00051 + 0.4, 6.0, 1.0, 0.00375, -0.00028 + 0.4, 6.0, 1.5, 0.00045, -9e-05 + 0.4, 6.0, 2.0, 0.0, -3e-05 + 0.4, 6.0, 3.0, 0.0, -0.0 + 0.4, 8.0, 0.05, 0.22301, -0.02886 + 0.4, 8.0, 0.1, 0.16572, -0.01868 + 0.4, 8.0, 0.2, 0.10564, -0.00905 + 0.4, 8.0, 0.3, 0.06877, -0.00505 + 0.4, 8.0, 0.4, 0.04553, -0.00308 + 0.4, 8.0, 0.5, 0.03055, -0.002 + 0.4, 8.0, 0.6, 0.0207, -0.00136 + 0.4, 8.0, 0.8, 0.00965, -0.0007 + 0.4, 8.0, 1.0, 0.00448, -0.00039 + 0.4, 8.0, 1.5, 0.00043, -0.00013 + 0.4, 8.0, 2.0, 0.0, -4e-05 + 0.4, 8.0, 3.0, 0.0, -0.0 + 0.4, 10.0, 0.05, 0.2421, -0.03936 + 0.4, 10.0, 0.1, 0.18844, -0.02524 + 0.4, 10.0, 0.2, 0.12311, -0.01207 + 0.4, 10.0, 0.3, 0.08065, -0.00667 + 0.4, 10.0, 0.4, 0.05348, -0.00405 + 0.4, 10.0, 0.5, 0.03585, -0.00263 + 0.4, 10.0, 0.6, 0.02422, -0.0018 + 0.4, 10.0, 0.8, 0.01117, -0.00093 + 0.4, 10.0, 1.0, 0.00508, -0.00054 + 0.4, 10.0, 1.5, 0.00035, -0.00019 + 0.4, 10.0, 2.0, 0.0, -5e-05 + 0.4, 10.0, 3.0, 0.0, -0.0 + 0.4, 12.0, 0.05, 0.25068, -0.05196 + 0.4, 12.0, 0.1, 0.2064, -0.03312 + 0.4, 12.0, 0.2, 0.13861, -0.01569 + 0.4, 12.0, 0.3, 0.09145, -0.00863 + 0.4, 12.0, 0.4, 0.06074, -0.00524 + 0.4, 12.0, 0.5, 0.04067, -0.00341 + 0.4, 12.0, 0.6, 0.0274, -0.00233 + 0.4, 12.0, 0.8, 0.01247, -0.00123 + 0.4, 12.0, 1.0, 0.00553, -0.00072 + 0.4, 12.0, 1.5, 0.00021, -0.00027 + 0.4, 12.0, 2.0, 0.0, -7e-05 + 0.4, 12.0, 3.0, 0.0, -0.0 + 0.4, 14.0, 0.05, 0.24877, -0.06684 + 0.4, 14.0, 0.1, 0.2196, -0.04242 + 0.4, 14.0, 0.2, 0.15216, -0.01999 + 0.4, 14.0, 0.3, 0.10114, -0.01097 + 0.4, 14.0, 0.4, 0.06729, -0.00665 + 0.4, 14.0, 0.5, 0.04501, -0.00434 + 0.4, 14.0, 0.6, 0.03022, -0.00298 + 0.4, 14.0, 0.8, 0.01358, -0.00159 + 0.4, 14.0, 1.0, 0.00585, -0.00095 + 0.4, 14.0, 1.5, 0.0, -0.00036 + 0.4, 14.0, 2.0, 0.0, -8e-05 + 0.4, 14.0, 3.0, 0.0, -0.0 + 0.4, 16.0, 0.05, 0.23636, -0.08415 + 0.4, 16.0, 0.1, 0.22805, -0.05325 + 0.4, 16.0, 0.2, 0.16374, -0.02502 + 0.4, 16.0, 0.3, 0.10975, -0.01371 + 0.4, 16.0, 0.4, 0.07316, -0.00833 + 0.4, 16.0, 0.5, 0.04887, -0.00544 + 0.4, 16.0, 0.6, 0.03269, -0.00376 + 0.4, 16.0, 0.8, 0.01447, -0.00203 + 0.4, 16.0, 1.0, 0.00603, -0.00123 + 0.4, 16.0, 1.5, 0.0, -0.00044 + 0.4, 16.0, 2.0, 0.0, -0.0001 + 0.4, 16.0, 3.0, 0.0, -0.0 + 0.4, 18.0, 0.05, 0.04855, -0.11421 + 0.4, 18.0, 0.1, 0.04855, -0.08256 + 0.4, 18.0, 0.2, 0.04855, -0.0464 + 0.4, 18.0, 0.3, 0.04855, -0.02663 + 0.4, 18.0, 0.4, 0.04855, -0.01478 + 0.4, 18.0, 0.5, 0.04855, -0.00733 + 0.4, 18.0, 0.6, 0.03482, -0.00468 + 0.4, 18.0, 0.8, 0.01516, -0.00255 + 0.4, 18.0, 1.0, 0.00608, -0.00157 + 0.4, 18.0, 1.5, 0.0, -0.00053 + 0.4, 18.0, 2.0, 0.0, -0.00012 + 0.4, 18.0, 3.0, 0.0, -0.0 + 0.5, -2.0, 0.05, -0.03154, -0.0017 + 0.5, -2.0, 0.1, -0.02012, -0.0013 + 0.5, -2.0, 0.2, -0.01168, -0.00082 + 0.5, -2.0, 0.3, -0.00741, -0.00054 + 0.5, -2.0, 0.4, -0.00487, -0.00036 + 0.5, -2.0, 0.5, -0.00328, -0.00025 + 0.5, -2.0, 0.6, -0.00225, -0.00017 + 0.5, -2.0, 0.8, -0.0011, -8e-05 + 0.5, -2.0, 1.0, -0.00055, -4e-05 + 0.5, -2.0, 1.5, -0.00011, -1e-05 + 0.5, -2.0, 2.0, -2e-05, -0.0 + 0.5, -2.0, 3.0, 0.0, -0.0 + 0.5, 0.0, 0.05, 0.04393, -0.00441 + 0.5, 0.0, 0.1, 0.02865, -0.00314 + 0.5, 0.0, 0.2, 0.01689, -0.00178 + 0.5, 0.0, 0.3, 0.01076, -0.0011 + 0.5, 0.0, 0.4, 0.00709, -0.00071 + 0.5, 0.0, 0.5, 0.00477, -0.00048 + 0.5, 0.0, 0.6, 0.00326, -0.00033 + 0.5, 0.0, 0.8, 0.00158, -0.00016 + 0.5, 0.0, 1.0, 0.00078, -8e-05 + 0.5, 0.0, 1.5, 0.00014, -2e-05 + 0.5, 0.0, 2.0, 1e-05, -0.0 + 0.5, 0.0, 3.0, 0.0, -0.0 + 0.5, 2.0, 0.05, 0.10816, -0.00836 + 0.5, 2.0, 0.1, 0.07233, -0.00572 + 0.5, 2.0, 0.2, 0.04336, -0.00303 + 0.5, 2.0, 0.3, 0.02775, -0.00179 + 0.5, 2.0, 0.4, 0.0183, -0.00113 + 0.5, 2.0, 0.5, 0.01231, -0.00075 + 0.5, 2.0, 0.6, 0.0084, -0.00051 + 0.5, 2.0, 0.8, 0.00403, -0.00025 + 0.5, 2.0, 1.0, 0.00197, -0.00013 + 0.5, 2.0, 1.5, 0.00031, -3e-05 + 0.5, 2.0, 2.0, 1e-05, -1e-05 + 0.5, 2.0, 3.0, 0.0, -0.0 + 0.5, 4.0, 0.05, 0.16113, -0.01378 + 0.5, 4.0, 0.1, 0.11091, -0.00918 + 0.5, 4.0, 0.2, 0.06772, -0.00465 + 0.5, 4.0, 0.3, 0.04357, -0.00267 + 0.5, 4.0, 0.4, 0.02877, -0.00166 + 0.5, 4.0, 0.5, 0.01934, -0.00108 + 0.5, 4.0, 0.6, 0.01317, -0.00073 + 0.5, 4.0, 0.8, 0.00626, -0.00037 + 0.5, 4.0, 1.0, 0.00301, -0.0002 + 0.5, 4.0, 1.5, 0.00042, -6e-05 + 0.5, 4.0, 2.0, 0.0, -2e-05 + 0.5, 4.0, 3.0, 0.0, -0.0 + 0.5, 6.0, 0.05, 0.20286, -0.02087 + 0.5, 6.0, 0.1, 0.1444, -0.01365 + 0.5, 6.0, 0.2, 0.08998, -0.00671 + 0.5, 6.0, 0.3, 0.05822, -0.00377 + 0.5, 6.0, 0.4, 0.0385, -0.00231 + 0.5, 6.0, 0.5, 0.02585, -0.0015 + 0.5, 6.0, 0.6, 0.01756, -0.00102 + 0.5, 6.0, 0.8, 0.00826, -0.00052 + 0.5, 6.0, 1.0, 0.00391, -0.00029 + 0.5, 6.0, 1.5, 0.00046, -9e-05 + 0.5, 6.0, 2.0, 0.0, -3e-05 + 0.5, 6.0, 3.0, 0.0, -0.0 + 0.5, 8.0, 0.05, 0.23333, -0.02984 + 0.5, 8.0, 0.1, 0.17279, -0.01926 + 0.5, 8.0, 0.2, 0.11014, -0.00927 + 0.5, 8.0, 0.3, 0.0717, -0.00515 + 0.5, 8.0, 0.4, 0.04748, -0.00313 + 0.5, 8.0, 0.5, 0.03185, -0.00203 + 0.5, 8.0, 0.6, 0.02157, -0.00138 + 0.5, 8.0, 0.8, 0.01005, -0.00071 + 0.5, 8.0, 1.0, 0.00466, -0.0004 + 0.5, 8.0, 1.5, 0.00044, -0.00013 + 0.5, 8.0, 2.0, 0.0, -4e-05 + 0.5, 8.0, 3.0, 0.0, -0.0 + 0.5, 10.0, 0.05, 0.25256, -0.04087 + 0.5, 10.0, 0.1, 0.19609, -0.02615 + 0.5, 10.0, 0.2, 0.12819, -0.01242 + 0.5, 10.0, 0.3, 0.08401, -0.00683 + 0.5, 10.0, 0.4, 0.05571, -0.00414 + 0.5, 10.0, 0.5, 0.03734, -0.00269 + 0.5, 10.0, 0.6, 0.02522, -0.00183 + 0.5, 10.0, 0.8, 0.01161, -0.00096 + 0.5, 10.0, 1.0, 0.00526, -0.00056 + 0.5, 10.0, 1.5, 0.00035, -0.0002 + 0.5, 10.0, 2.0, 0.0, -5e-05 + 0.5, 10.0, 3.0, 0.0, -0.0 + 0.5, 12.0, 0.05, 0.26054, -0.05417 + 0.5, 12.0, 0.1, 0.2143, -0.03444 + 0.5, 12.0, 0.2, 0.14414, -0.01622 + 0.5, 12.0, 0.3, 0.09514, -0.00888 + 0.5, 12.0, 0.4, 0.06319, -0.00537 + 0.5, 12.0, 0.5, 0.04231, -0.00349 + 0.5, 12.0, 0.6, 0.02848, -0.00239 + 0.5, 12.0, 0.8, 0.01295, -0.00127 + 0.5, 12.0, 1.0, 0.00572, -0.00075 + 0.5, 12.0, 1.5, 0.00019, -0.00028 + 0.5, 12.0, 2.0, 0.0, -7e-05 + 0.5, 12.0, 3.0, 0.0, -0.0 + 0.5, 14.0, 0.05, 0.25727, -0.0699 + 0.5, 14.0, 0.1, 0.2274, -0.04426 + 0.5, 14.0, 0.2, 0.15799, -0.02074 + 0.5, 14.0, 0.3, 0.1051, -0.01133 + 0.5, 14.0, 0.4, 0.06994, -0.00686 + 0.5, 14.0, 0.5, 0.04677, -0.00447 + 0.5, 14.0, 0.6, 0.03138, -0.00308 + 0.5, 14.0, 0.8, 0.01406, -0.00165 + 0.5, 14.0, 1.0, 0.00603, -0.00099 + 0.5, 14.0, 1.5, 0.0, -0.00038 + 0.5, 14.0, 2.0, 0.0, -9e-05 + 0.5, 14.0, 3.0, 0.0, -0.0 + 0.5, 16.0, 0.05, 0.17703, -0.09217 + 0.5, 16.0, 0.1, 0.17703, -0.0609 + 0.5, 16.0, 0.2, 0.16973, -0.02605 + 0.5, 16.0, 0.3, 0.11389, -0.01423 + 0.5, 16.0, 0.4, 0.07593, -0.00862 + 0.5, 16.0, 0.5, 0.05071, -0.00563 + 0.5, 16.0, 0.6, 0.0339, -0.0039 + 0.5, 16.0, 0.8, 0.01496, -0.00211 + 0.5, 16.0, 1.0, 0.0062, -0.00129 + 0.5, 16.0, 1.5, 0.0, -0.00047 + 0.5, 16.0, 2.0, 0.0, -0.0001 + 0.5, 16.0, 3.0, 0.0, -0.0 + 0.5, 18.0, 0.05, 0.0, -0.12093 + 0.5, 18.0, 0.1, 0.0, -0.08966 + 0.5, 18.0, 0.2, 0.0, -0.05394 + 0.5, 18.0, 0.3, 0.0, -0.03441 + 0.5, 18.0, 0.4, 0.0, -0.02271 + 0.5, 18.0, 0.5, 0.0, -0.01535 + 0.5, 18.0, 0.6, 0.0, -0.01055 + 0.5, 18.0, 0.8, 0.0, -0.00519 + 0.5, 18.0, 1.0, 0.0, -0.00265 + 0.5, 18.0, 1.5, 0.0, -0.00055 + 0.5, 18.0, 2.0, 0.0, -0.00012 + 0.5, 18.0, 3.0, 0.0, -0.0 diff --git a/aviary/models/large_single_aisle_2/__init__.py b/aviary/models/aircraft/large_single_aisle_2/__init__.py similarity index 100% rename from aviary/models/large_single_aisle_2/__init__.py rename to aviary/models/aircraft/large_single_aisle_2/__init__.py diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py b/aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py similarity index 75% rename from aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py rename to aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py index 3787f9ddcd..80ab17f0fd 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py +++ b/aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_FLOPS_data.py @@ -10,16 +10,16 @@ inputs = LargeSingleAisle2FLOPS['inputs'] = AviaryValues() outputs = LargeSingleAisle2FLOPS['outputs'] = AviaryValues() -''' +""" Large Single Aisle 2 Mission/fixed_gw -''' +""" # Overall Aircraft # --------------------------- -inputs.set_val(Aircraft.Design.BASE_AREA, 0., 'ft**2') +inputs.set_val(Aircraft.Design.BASE_AREA, 0.0, 'ft**2') inputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, 0.00514) inputs.set_val(Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 0.84) -inputs.set_val(Mission.Design.GROSS_MASS, 174200., 'lbm') +inputs.set_val(Mission.Design.GROSS_MASS, 174200.0, 'lbm') inputs.set_val(Aircraft.Design.USE_ALT_MASS, False) inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 1.0) inputs.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0) @@ -59,17 +59,17 @@ inputs.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, 162, units='unitless') inputs.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, 150) -inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35., 'lbm') +inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, 5) inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW, 2) inputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_GALLEY_CREW, 1) -inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077., 'lbm') +inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, 1.0) -inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.) -inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165., 'lbm') -inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0., 'lbm') +inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165.0, 'lbm') +inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0.0, 'lbm') # Electrical # --------------------------- @@ -85,8 +85,8 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') -inputs.set_val(Aircraft.Fuel.CAPACITY_FACTOR, 25.903) -inputs.set_val(Aircraft.Fuel.DENSITY_RATIO, 1.0) +inputs.set_val(Aircraft.Fuel.WING_FUEL_FRACTION, 0.7752) +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) inputs.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 46063.0, 'lbm') @@ -124,7 +124,7 @@ # Hydraulics # --------------------------- -inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000., 'psi') +inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000.0, 'psi') inputs.set_val(Aircraft.Hydraulics.MASS_SCALER, 1.0) # Instruments @@ -133,7 +133,6 @@ # Landing Gear # --------------------------- -inputs.set_val(Aircraft.LandingGear.CARRIER_BASED, False) inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, 84.0, 'inch') inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, 1.0) inputs.set_val(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, 58.8, 'inch') @@ -155,29 +154,17 @@ inputs.set_val(Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, 1.0) -filename = get_path( - 'models/engines/turbofan_24k_1.deck') +filename = get_path('models/engines/turbofan_24k_1.csv') inputs.set_val(Aircraft.Engine.DATA_FILE, filename) -engine_mass = 8071.35 -engine_mass_units = 'lbm' -inputs.set_val(Aircraft.Engine.MASS, engine_mass, engine_mass_units) -inputs.set_val( - Aircraft.Engine.REFERENCE_MASS, - engine_mass, - engine_mass_units) -scaled_sls_thrust = 27301.0 -scaled_sls_thrust_units = 'lbf' -inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - scaled_sls_thrust, scaled_sls_thrust_units) -inputs.set_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, scaled_sls_thrust, scaled_sls_thrust_units) -num_engines = 2 -inputs.set_val(Aircraft.Engine.NUM_ENGINES, num_engines) -num_fuselage_engines = 0 -inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, num_fuselage_engines) -num_wing_engines = 2 -inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, num_wing_engines) +inputs.set_val(Aircraft.Engine.MASS, 8071.35, 'lbm') +inputs.set_val(Aircraft.Engine.REFERENCE_MASS, 8071.35, 'lbm') +inputs.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 27301.0, 'lbf') +inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) +inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 27301.0, 'lbf') +inputs.set_val(Aircraft.Engine.NUM_ENGINES, 2) +inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 0) +inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2) inputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Engine.SCALE_MASS, True) inputs.set_val(Aircraft.Engine.MASS_SCALER, 1.15) @@ -185,8 +172,7 @@ inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) inputs.set_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, 1.0) inputs.set_val(Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER, 1.0) -inputs.set_val( - Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, 0.0) +inputs.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, 0.0) inputs.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM, 0.0) inputs.set_val(Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, 0.0, units='lbm/h') inputs.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.0) @@ -217,7 +203,7 @@ inputs.set_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY, 1.87) inputs.set_val(Aircraft.Wing.AREA, 1341.0, 'ft**2') inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 9.45) -inputs.set_val(Aircraft.Wing.BENDING_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.0) inputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, 0.333) inputs.set_val(Aircraft.Wing.GLOVE_AND_BAT, 0.0, 'ft**2') @@ -245,7 +231,7 @@ # --------------------------- inputs.set_val(Mission.Summary.CRUISE_MACH, 0.785) inputs.set_val(Mission.Summary.FUEL_FLOW_SCALER, 1.0) -inputs.set_val(Mission.Design.RANGE, 2960., 'NM') +inputs.set_val(Mission.Design.RANGE, 2960.0, 'NM') inputs.set_val(Mission.Constraints.MAX_MACH, 0.82) # TODO investigate the origin of these values (taken from benchmark tests) # TODO: where should this get connected from? @@ -258,35 +244,36 @@ inputs.set_val(Mission.Takeoff.LIFT_OVER_DRAG, 17.35) # TODO: should this be a user input or should it be hard coded somewhere assuming it will # never change? -inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, .0175) +inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.0175) # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 27301.0, 'lbf') # Settings # --------------------------- inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.AERODYNAMICS_METHOD, LegacyCode.FLOPS) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- # OUTPUTS # --------------------------- -outputs.set_val(Aircraft.Design.EMPTY_MASS, 88246., 'lbm') +outputs.set_val(Aircraft.Design.EMPTY_MASS, 88246.0, 'lbm') outputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN, 451.3, 'lbm') outputs.set_val(Aircraft.Design.TOUCHDOWN_MASS, 146328.0, 'lbm') -outputs.set_val(Aircraft.Design.OPERATING_MASS, 95007., 'lbm') -outputs.set_val(Aircraft.Propulsion.MASS, 19232., 'lbm') -outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 44389., 'lbm') -outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 24174., 'lbm') +outputs.set_val(Mission.Summary.OPERATING_MASS, 95007.0, 'lbm') +outputs.set_val(Aircraft.Propulsion.MASS, 19232.0, 'lbm') +outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 44389.0, 'lbm') +outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 24174.0, 'lbm') outputs.set_val(Aircraft.Design.TOTAL_WETTED_AREA, 8319.07, 'ft**2') -outputs.set_val(Aircraft.Design.ZERO_FUEL_MASS, 131484., 'lbm') -outputs.set_val(Mission.Design.FUEL_MASS, 42716., 'lbm') +outputs.set_val(Mission.Summary.ZERO_FUEL_MASS, 131484.0, 'lbm') +outputs.set_val(Mission.Summary.FUEL_MASS, 42716.0, 'lbm') outputs.set_val(Aircraft.AirConditioning.MASS, 1603.75, 'lbm') outputs.set_val(Aircraft.AntiIcing.MASS, 195.93, 'lbm') -outputs.set_val(Aircraft.APU.MASS, 1014., 'lbm') +outputs.set_val(Aircraft.APU.MASS, 1014.0, 'lbm') outputs.set_val(Aircraft.Avionics.MASS, 1339.4, 'lbm') @@ -295,14 +282,14 @@ outputs.set_val(Aircraft.Canard.WETTED_AREA, 0.0, 'ft**2') outputs.set_val(Aircraft.Canard.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5670., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1925., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 4077., 'lbm') +outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5670.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1925.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 4077.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS, 450.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, 975.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 2787.30285438, 'lbm') -outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 26730., 'lbm') -outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 36477., 'lbm') +outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 26730.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 36477.0, 'lbm') outputs.set_val(Aircraft.Electrical.MASS, 1935.6, 'lbm') @@ -312,19 +299,15 @@ outputs.set_val(Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 3.9, 'lbm') outputs.set_val(Aircraft.Fuel.UNUSABLE_FUEL_MASS, 497.7, 'lbm') -outputs.set_val(Aircraft.Furnishings.MASS, 14690., 'lbm') +outputs.set_val(Aircraft.Furnishings.MASS, 14690.0, 'lbm') -avg_diameter = (13.0208 + 12.33) / 2 -avg_diameter_units = 'ft' -outputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, avg_diameter, avg_diameter_units) +outputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, (13.0208 + 12.33) / 2, 'ft') outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 124.75, 'ft') -outputs.set_val( - Aircraft.Fuselage.CROSS_SECTION, - pi * (avg_diameter / 2.0)**2.0, 'ft**2') +outputs.set_val(Aircraft.Fuselage.CROSS_SECTION, pi * (12.6754 / 2.0) ** 2.0, 'ft**2') outputs.set_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.112598) outputs.set_val(Aircraft.Fuselage.FINENESS, 9.8419) outputs.set_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER, 9.841898) -outputs.set_val(Aircraft.Fuselage.MASS, 16790., 'lbm') +outputs.set_val(Aircraft.Fuselage.MASS, 16790.0, 'lbm') outputs.set_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 8.65, 'ft') outputs.set_val(Aircraft.HorizontalTail.FINENESS, 0.1195) @@ -332,14 +315,12 @@ outputs.set_val(Aircraft.Hydraulics.MASS, 1075.3, 'lbm') -outputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000., 'psi') +outputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000.0, 'psi') -outputs.set_val(Aircraft.Instruments.MASS, 484., 'lbm') +outputs.set_val(Aircraft.Instruments.MASS, 484.0, 'lbm') -outputs.set_val( - Aircraft.LandingGear.MAIN_GEAR_MASS, 0.0117 * 146328.0**0.95 * 84.0**0.43, 'lbm') -outputs.set_val( - Aircraft.LandingGear.NOSE_GEAR_MASS, 0.048 * 146328.0**0.67 * 58.8**0.43, 'lbm') +outputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS, 0.0117 * 146328.0**0.95 * 84.0**0.43, 'lbm') +outputs.set_val(Aircraft.LandingGear.NOSE_GEAR_MASS, 0.048 * 146328.0**0.67 * 58.8**0.43, 'lbm') outputs.set_val(Aircraft.Nacelle.CHARACTERISTIC_LENGTH, np.array([11.65]), 'ft') outputs.set_val(Aircraft.Nacelle.FINENESS, np.array([1.6643])) @@ -348,64 +329,46 @@ outputs.set_val(Aircraft.Nacelle.WETTED_AREA, np.array([228.34]), 'ft**2') outputs.set_val(Aircraft.Paint.MASS, 582.3, 'lbm') +outputs.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 27301.0 * 2, 'lbf') -outputs.set_val( - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, - scaled_sls_thrust * num_engines, scaled_sls_thrust_units) - -total_num_engines = num_engines -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, total_num_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) ctrls_mass = 0.26 * 2 * 27301.0**0.5 # 85.92 ctrls_mass_units = 'lbm' -outputs.set_val( - Aircraft.Engine.CONTROLS_MASS, - ctrls_mass, ctrls_mass_units) -outputs.set_val( - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - ctrls_mass, ctrls_mass_units) +outputs.set_val(Aircraft.Engine.CONTROLS_MASS, ctrls_mass, ctrls_mass_units) +outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, ctrls_mass, ctrls_mass_units) outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, 125.42, 'lbm') -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, num_wing_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2) -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, num_fuselage_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 2) -outputs.set_val( - Aircraft.Propulsion.TOTAL_ENGINE_MASS, - engine_mass * num_engines, engine_mass_units) +outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_MASS, 16143.0, 'lbm') -outputs.set_val(Aircraft.Engine.MASS, 16143./2.0, 'lbm') +outputs.set_val(Aircraft.Engine.MASS, 16143.0 / 2.0, 'lbm') outputs.set_val(Aircraft.Engine.POD_MASS, 10350, 'lbm') outputs.set_val(Aircraft.Engine.ADDITIONAL_MASS, 0.0, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_MISC_MASS, 550.4, 'lbm') -outputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) -outputs.set_val( - Aircraft.Propulsion.TOTAL_STARTER_MASS, 11.0 * 2 * 0.82**0.32 * 7.0**1.6, 'lbm') - -thrust_reversers_mass = 1856.4 -thrust_reversers_mass_units = 'lbm' -outputs.set_val( - Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) -outputs.set_val( - Aircraft.Engine.THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) +outputs.set_val(Aircraft.Propulsion.TOTAL_STARTER_MASS, 11.0 * 2 * 0.82**0.32 * 7.0**1.6, 'lbm') + +outputs.set_val(Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, 1856.4, 'lbm') +outputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS, 1856.4, 'lbm') outputs.set_val(Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, 11.30, 'ft') outputs.set_val(Aircraft.VerticalTail.FINENESS, 0.1375) outputs.set_val(Aircraft.VerticalTail.MASS, 1035.6, 'lbm') -outputs.set_val(Aircraft.Wing.BENDING_FACTOR, 8.8294) -outputs.set_val(Aircraft.Wing.BENDING_MASS, 6016.9, 'lbm') +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR, 8.8294) +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS, 6016.9, 'lbm') outputs.set_val(Aircraft.Wing.CHARACTERISTIC_LENGTH, 11.91, 'ft') outputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 0.333 * 1341.0, 'ft**2') outputs.set_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR, 0.940000) outputs.set_val(Aircraft.Wing.FINENESS, 0.1317) outputs.set_val(Aircraft.Wing.MISC_MASS, 1718.7, 'lbm') outputs.set_val(Aircraft.Wing.SHEAR_CONTROL_MASS, 7552.6, 'lbm') -outputs.set_val(Aircraft.Wing.SURFACE_CONTROL_MASS, 1835., 'lbm') +outputs.set_val(Aircraft.Wing.SURFACE_CONTROL_MASS, 1835.0, 'lbm') outputs.set_val(Mission.Design.MACH, 0.799) outputs.set_val(Mission.Design.LIFT_COEFFICIENT, 0.523) diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py b/aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py similarity index 81% rename from aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py rename to aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py index 454b605f4d..e39a6ea427 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py +++ b/aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_altwt_FLOPS_data.py @@ -1,4 +1,3 @@ -import numpy as np from numpy import pi from aviary.utils.aviary_values import AviaryValues @@ -10,16 +9,16 @@ inputs = LargeSingleAisle2FLOPSalt['inputs'] = AviaryValues() outputs = LargeSingleAisle2FLOPSalt['outputs'] = AviaryValues() -''' +""" Large Single Aisle 2 Mission/fixed_gw -''' +""" # Overall Aircraft # --------------------------- -inputs.set_val(Aircraft.Design.BASE_AREA, 0., 'ft**2') +inputs.set_val(Aircraft.Design.BASE_AREA, 0.0, 'ft**2') inputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, 0.00514) inputs.set_val(Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 0.84) -inputs.set_val(Mission.Design.GROSS_MASS, 174200., 'lbm') +inputs.set_val(Mission.Design.GROSS_MASS, 174200.0, 'lbm') inputs.set_val(Aircraft.Design.USE_ALT_MASS, True) inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 1.0) inputs.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0) @@ -59,17 +58,17 @@ inputs.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, 162, units='unitless') inputs.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, 150) -inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35., 'lbm') +inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, 5) inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW, 2) inputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_GALLEY_CREW, 1) -inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077., 'lbm') +inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, 1.0) -inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.) -inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165., 'lbm') -inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0., 'lbm') +inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165.0, 'lbm') +inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0.0, 'lbm') # Electrical # --------------------------- @@ -85,8 +84,8 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') -inputs.set_val(Aircraft.Fuel.CAPACITY_FACTOR, 25.903) -inputs.set_val(Aircraft.Fuel.DENSITY_RATIO, 1.0) +inputs.set_val(Aircraft.Fuel.WING_FUEL_FRACTION, 0.7752) +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) inputs.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 46063.0, 'lbm') @@ -124,7 +123,7 @@ # Hydraulics # --------------------------- -inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000., 'psi') +inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000.0, 'psi') inputs.set_val(Aircraft.Hydraulics.MASS_SCALER, 1.0) # Instruments @@ -133,7 +132,6 @@ # Landing Gear # --------------------------- -inputs.set_val(Aircraft.LandingGear.CARRIER_BASED, False) inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, 84.0, 'inch') inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, 1.0) inputs.set_val(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, 58.8, 'inch') @@ -155,12 +153,13 @@ inputs.set_val(Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, 1.0) -filename = get_path('models/engines/turbofan_24k_1.deck') +filename = get_path('models/engines/turbofan_24k_1.csv') inputs.set_val(Aircraft.Engine.DATA_FILE, filename) inputs.set_val(Aircraft.Engine.MASS, 8071.35, 'lbm') inputs.set_val(Aircraft.Engine.REFERENCE_MASS, 8071.35, 'lbm') -inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 27301.0, 'lbf') +inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 28928.1, 'lbf') +inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) inputs.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 27301.0, 'lbf') inputs.set_val(Aircraft.Engine.NUM_ENGINES, 2) inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 0) @@ -204,7 +203,7 @@ inputs.set_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY, 1.87) inputs.set_val(Aircraft.Wing.AREA, 1341.0, 'ft**2') inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 9.45) -inputs.set_val(Aircraft.Wing.BENDING_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.0) inputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, 0.333) inputs.set_val(Aircraft.Wing.GLOVE_AND_BAT, 0.0, 'ft**2') @@ -231,7 +230,7 @@ # Mission # --------------------------- inputs.set_val(Mission.Summary.CRUISE_MACH, 0.785) -inputs.set_val(Mission.Design.RANGE, 2960., 'NM') +inputs.set_val(Mission.Design.RANGE, 2960.0, 'NM') inputs.set_val(Mission.Summary.FUEL_FLOW_SCALER, 1.0) inputs.set_val(Mission.Constraints.MAX_MACH, 0.82) # TODO investigate the origin of these values (taken from benchmark tests) @@ -246,42 +245,42 @@ # TODO: should this be a user input or should it be hard coded somewhere assuming it will # never change? -inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, .0175) +inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.0175) # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 27301.0, 'lbf') # Settings # --------------------------- inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.AERODYNAMICS_METHOD, LegacyCode.FLOPS) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- # OUTPUTS # --------------------------- -outputs.set_val(Aircraft.Design.EMPTY_MASS, 96288., 'lbm') -outputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN, 492., 'lbm') +outputs.set_val(Aircraft.Design.EMPTY_MASS, 96288.0, 'lbm') +outputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN, 492.0, 'lbm') outputs.set_val(Aircraft.Design.TOUCHDOWN_MASS, 146328.0, 'lbm') -outputs.set_val(Aircraft.Design.OPERATING_MASS, 106360., 'lbm') -propulsion_mass = 20275. +outputs.set_val(Mission.Summary.OPERATING_MASS, 106360.0, 'lbm') +propulsion_mass = 20275.0 propulsion_mass_units = 'lbm' outputs.set_val(Aircraft.Propulsion.MASS, propulsion_mass, propulsion_mass_units) -struct_mass = 43288. +struct_mass = 43288.0 struct_mass_units = 'lbm' outputs.set_val(Aircraft.Design.STRUCTURE_MASS, struct_mass, struct_mass_units) -sys_equip_mass = 32232. +sys_equip_mass = 32232.0 sys_equip_mass_units = 'lbm' -outputs.set_val( - Aircraft.Design.SYSTEMS_EQUIP_MASS, sys_equip_mass, sys_equip_mass_units) +outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, sys_equip_mass, sys_equip_mass_units) outputs.set_val(Aircraft.Design.TOTAL_WETTED_AREA, 8319.07, 'ft**2') -outputs.set_val(Aircraft.Design.ZERO_FUEL_MASS, 142837., 'lbm') -outputs.set_val(Mission.Design.FUEL_MASS, 31363., 'lbm') +outputs.set_val(Mission.Summary.ZERO_FUEL_MASS, 142837.0, 'lbm') +outputs.set_val(Mission.Summary.FUEL_MASS, 31363.0, 'lbm') -outputs.set_val(Aircraft.AirConditioning.MASS, 4212., 'lbm') +outputs.set_val(Aircraft.AirConditioning.MASS, 4212.0, 'lbm') outputs.set_val(Aircraft.AntiIcing.MASS, 195.93, 'lbm') -outputs.set_val(Aircraft.APU.MASS, 1014., 'lbm') +outputs.set_val(Aircraft.APU.MASS, 1014.0, 'lbm') outputs.set_val(Aircraft.Avionics.MASS, 1339.4, 'lbm') @@ -290,39 +289,38 @@ outputs.set_val(Aircraft.Canard.WETTED_AREA, 0.0, 'ft**2') outputs.set_val(Aircraft.Canard.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5670., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1925., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 4077., 'lbm') +outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5670.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1925.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 4077.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS, 450.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, 975.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 5135, 'lbm') -outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 26730., 'lbm') -outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 36477., 'lbm') +outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 26730.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 36477.0, 'lbm') outputs.set_val(Aircraft.Electrical.MASS, 2640.6, 'lbm') outputs.set_val(Aircraft.Fins.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS, 1726., 'lbm') +outputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS, 1726.0, 'lbm') outputs.set_val(Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 3.9, 'lbm') outputs.set_val(Aircraft.Fuel.UNUSABLE_FUEL_MASS, 386.93, 'lbm') -furnishings_mass = 17857. +furnishings_mass = 17857.0 furnishings_mass_units = 'lbm' -outputs.set_val( - Aircraft.Furnishings.MASS, furnishings_mass, furnishings_mass_units) +outputs.set_val(Aircraft.Furnishings.MASS, furnishings_mass, furnishings_mass_units) avg_diameter = (13.0208 + 12.33) / 2 avg_diameter_units = 'ft' outputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, avg_diameter, avg_diameter_units) outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 124.75, 'ft') outputs.set_val( - Aircraft.Fuselage.CROSS_SECTION, pi * (avg_diameter / 2.0)**2.0, - f'{avg_diameter_units}**2') + Aircraft.Fuselage.CROSS_SECTION, pi * (avg_diameter / 2.0) ** 2.0, f'{avg_diameter_units}**2' +) outputs.set_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.112598) outputs.set_val(Aircraft.Fuselage.FINENESS, 9.8419) outputs.set_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER, 9.841898) -outputs.set_val(Aircraft.Fuselage.MASS, 16121., 'lbm') +outputs.set_val(Aircraft.Fuselage.MASS, 16121.0, 'lbm') outputs.set_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 8.65, 'ft') outputs.set_val(Aircraft.HorizontalTail.FINENESS, 0.1195) @@ -330,53 +328,52 @@ outputs.set_val(Aircraft.Hydraulics.MASS, 1361.15, 'lbm') -outputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000., 'psi') +outputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000.0, 'psi') -outputs.set_val(Aircraft.Instruments.MASS, 484., 'lbm') +outputs.set_val(Aircraft.Instruments.MASS, 484.0, 'lbm') -outputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS, 0.85 * 5778., 'lbm') -outputs.set_val(Aircraft.LandingGear.NOSE_GEAR_MASS, 0.15 * 5778., 'lbm') +outputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS, 0.85 * 5778.0, 'lbm') +outputs.set_val(Aircraft.LandingGear.NOSE_GEAR_MASS, 0.15 * 5778.0, 'lbm') -outputs.set_val(Aircraft.Nacelle.CHARACTERISTIC_LENGTH, np.array(11.65), 'ft') -outputs.set_val(Aircraft.Nacelle.FINENESS, np.array(1.6643)) +outputs.set_val(Aircraft.Nacelle.CHARACTERISTIC_LENGTH, 11.65, 'ft') +outputs.set_val(Aircraft.Nacelle.FINENESS, 1.6643) outputs.set_val(Aircraft.Nacelle.TOTAL_WETTED_AREA, 2 * 228.34, 'ft**2') outputs.set_val(Aircraft.Nacelle.MASS, 1612.2, 'lbm') -outputs.set_val(Aircraft.Nacelle.WETTED_AREA, np.array(228.34), 'ft**2') +outputs.set_val(Aircraft.Nacelle.WETTED_AREA, 228.34, 'ft**2') outputs.set_val(Aircraft.Paint.MASS, 582.3, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) +inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 27301.0, 'lbf') +outputs.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 27301.0 * 2, 'lbf') outputs.set_val( - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, - 27301.0 * 2, 'lbf') -outputs.set_val( - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - 0.26 * 2 * 27301.0**0.5, 'lbm') # 85.92 -outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, 1200., 'lbm') + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, 0.26 * 2 * 27301.0**0.5, 'lbm' +) # 85.92 +outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, 1200.0, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_MISC_MASS, 550.4, 'lbm') -outputs.set_val( - Aircraft.Propulsion.TOTAL_STARTER_MASS, 11.0 * 2 * 0.82**0.32 * 7.0**1.6, 'lbm') +outputs.set_val(Aircraft.Propulsion.TOTAL_STARTER_MASS, 11.0 * 2 * 0.82**0.32 * 7.0**1.6, 'lbm') thrust_reversers_mass = 1856.4 thrust_reversers_mass_units = 'lbm' outputs.set_val( Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) + thrust_reversers_mass, + thrust_reversers_mass_units, +) outputs.set_val( - Aircraft.Engine.THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) + Aircraft.Engine.THRUST_REVERSERS_MASS, thrust_reversers_mass, thrust_reversers_mass_units +) outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 0) outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2) -outputs.set_val(Aircraft.Engine.MASS, 16143./2.0, 'lbm') +outputs.set_val(Aircraft.Engine.MASS, 16143.0 / 2.0, 'lbm') outputs.set_val(Aircraft.Engine.ADDITIONAL_MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_MASS, 8071.35 * 2, 'lbm') outputs.set_val(Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, 11.30, 'ft') outputs.set_val(Aircraft.VerticalTail.FINENESS, 0.1375) -outputs.set_val(Aircraft.VerticalTail.MASS, 1707., 'lbm') +outputs.set_val(Aircraft.VerticalTail.MASS, 1707.0, 'lbm') -outputs.set_val(Aircraft.Wing.BENDING_FACTOR, 8.8294) -outputs.set_val(Aircraft.Wing.BENDING_MASS, 6016.9, 'lbm') +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR, 8.8294) +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS, 6016.9, 'lbm') outputs.set_val(Aircraft.Wing.CHARACTERISTIC_LENGTH, 11.91, 'ft') outputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 0.333 * 1341.0, 'ft**2') outputs.set_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR, 0.940000) @@ -389,19 +386,16 @@ outputs.set_val(Mission.Design.LIFT_COEFFICIENT, 0.523) # Back out some of the outputs need for validation of alt mass -sys_equip_mass_base = ( - sys_equip_mass - 0.01 * (struct_mass + propulsion_mass)) / 1.01 +sys_equip_mass_base = (sys_equip_mass - 0.01 * (struct_mass + propulsion_mass)) / 1.01 sys_equip_mass_base_units = struct_mass_units outputs.set_val( - Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, - sys_equip_mass_base, sys_equip_mass_base_units + Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, sys_equip_mass_base, sys_equip_mass_base_units ) outputs.set_val( Aircraft.Furnishings.MASS_BASE, - furnishings_mass - - 0.01 * (struct_mass + propulsion_mass + sys_equip_mass_base), - furnishings_mass_units + furnishings_mass - 0.01 * (struct_mass + propulsion_mass + sys_equip_mass_base), + furnishings_mass_units, ) # Some outputs are used as inputs in alt mass diff --git a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py b/aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py similarity index 75% rename from aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py rename to aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py index 63721e4a4f..251516c5c4 100644 --- a/aviary/models/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py +++ b/aviary/models/aircraft/large_single_aisle_2/large_single_aisle_2_detailwing_FLOPS_data.py @@ -11,10 +11,10 @@ # Overall Aircraft # --------------------------- -inputs.set_val(Aircraft.Design.BASE_AREA, 0., 'ft**2') +inputs.set_val(Aircraft.Design.BASE_AREA, 0.0, 'ft**2') inputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, 0.00514) inputs.set_val(Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 0.84) -inputs.set_val(Mission.Design.GROSS_MASS, 174200., 'lbm') +inputs.set_val(Mission.Design.GROSS_MASS, 174200.0, 'lbm') inputs.set_val(Aircraft.Design.USE_ALT_MASS, False) inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 1.0) inputs.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0) @@ -45,7 +45,7 @@ # Crew and Payload # --------------------------- -inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35., 'lbm') +inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, 0) inputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, 5) @@ -53,13 +53,13 @@ inputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 12) inputs.set_val(Aircraft.CrewPayload.NUM_GALLEY_CREW, 1) -inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077., 'lbm') +inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, 162, units='unitless') -inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.) +inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, 150) -inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165., 'lbm') -inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0., 'lbm') +inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165.0, 'lbm') +inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0.0, 'lbm') # Electrical # --------------------------- @@ -76,7 +76,7 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') -inputs.set_val(Aircraft.Fuel.DENSITY_RATIO, 1.0) +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) inputs.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 46063.0, 'lbm') @@ -112,7 +112,7 @@ # Hydraulics # --------------------------- -inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000., 'psi') +inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000.0, 'psi') inputs.set_val(Aircraft.Hydraulics.MASS_SCALER, 1.0) # Instruments @@ -121,7 +121,6 @@ # Landing Gear # --------------------------- -inputs.set_val(Aircraft.LandingGear.CARRIER_BASED, False) inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, 84.0, 'inch') inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, 1.0) inputs.set_val(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, 58.8, 'inch') @@ -143,29 +142,18 @@ inputs.set_val(Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, 1.0) -filename = get_path( - 'models/engines/turbofan_24k_1.deck') +filename = get_path('models/engines/turbofan_24k_1.csv') inputs.set_val(Aircraft.Engine.DATA_FILE, filename) -engine_mass = 8071.35 -engine_mass_units = 'lbm' -inputs.set_val(Aircraft.Engine.MASS, engine_mass, engine_mass_units) -inputs.set_val( - Aircraft.Engine.REFERENCE_MASS, - engine_mass, - engine_mass_units) -scaled_sls_thrust = 27301.0 -scaled_sls_thrust_units = 'lbf' -inputs.set_val( - Aircraft.Engine.SCALED_SLS_THRUST, scaled_sls_thrust, scaled_sls_thrust_units) -inputs.set_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, scaled_sls_thrust, scaled_sls_thrust_units) -num_engines = 2 -inputs.set_val(Aircraft.Engine.NUM_ENGINES, num_engines) -num_fuselage_engines = 0 -inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, num_fuselage_engines) -num_wing_engines = num_engines -inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, num_wing_engines) +inputs.set_val(Aircraft.Engine.MASS, 8071.35, 'lbm') +inputs.set_val(Aircraft.Engine.REFERENCE_MASS, 8071.35, 'lbm') +inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) +inputs.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 27301.0, 'lbf') +inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 27301.0, 'lbf') +inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 27301.0, 'lbf') +inputs.set_val(Aircraft.Engine.NUM_ENGINES, 2) +inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 0) +inputs.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2) inputs.set_val(Aircraft.Engine.WING_LOCATIONS, 0.28131) inputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Engine.SCALE_MASS, True) @@ -173,8 +161,7 @@ inputs.set_val(Aircraft.Engine.SCALE_PERFORMANCE, True) inputs.set_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, 1.0) inputs.set_val(Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER, 1.0) -inputs.set_val( - Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, 0.0) +inputs.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, 0.0) inputs.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM, 0.0) inputs.set_val(Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, 0.0, units='lbm/h') inputs.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.0) @@ -186,7 +173,6 @@ inputs.set_val(Aircraft.Engine.GEOPOTENTIAL_ALT, False) inputs.set_val(Aircraft.Engine.INTERPOLATION_METHOD, 'slinear') - # Vertical Tail # --------------------------- inputs.set_val(Aircraft.VerticalTail.NUM_TAILS, 1) @@ -204,11 +190,11 @@ inputs.set_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY, 1.87) inputs.set_val(Aircraft.Wing.AREA, 1341.0, 'ft**2') inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 9.42519) -inputs.set_val(Aircraft.Wing.BENDING_MASS_SCALER, 1.0) -inputs.set_val( - Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, np.array([0.4441, 0.2313, 0.0729])) +inputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, np.array([0.4441, 0.2313, 0.0729])) inputs.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.0) inputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, 0.333) +inputs.set_val(Aircraft.Wing.DETAILED_WING, True) inputs.set_val(Aircraft.Wing.GLOVE_AND_BAT, 0.0, 'ft**2') inputs.set_val(Aircraft.Wing.INPUT_STATION_DIST, np.array([0.0, 0.3238, 1.0])) inputs.set_val(Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL, 2.0) @@ -226,8 +212,7 @@ inputs.set_val(Aircraft.Wing.SWEEP, 25.03, 'deg') inputs.set_val(Aircraft.Wing.TAPER_RATIO, 0.237343146184852) inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, 0.131732727515702) -inputs.set_val( - Aircraft.Wing.THICKNESS_TO_CHORD_DIST, np.array([0.145, 0.115, 0.104])) +inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_DIST, np.array([0.145, 0.115, 0.104])) inputs.set_val(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.75) inputs.set_val(Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, 0) inputs.set_val(Aircraft.Wing.MASS, 15548, 'lbm') @@ -238,7 +223,7 @@ # Mission # --------------------------- inputs.set_val(Mission.Summary.CRUISE_MACH, 0.785) # was 0.82 -inputs.set_val(Mission.Design.RANGE, 2960., 'NM') +inputs.set_val(Mission.Design.RANGE, 2960.0, 'NM') inputs.set_val(Mission.Summary.FUEL_FLOW_SCALER, 1.0) inputs.set_val(Mission.Constraints.MAX_MACH, 0.82) # TODO investigate the origin of these values (taken from benchmark tests) @@ -253,35 +238,36 @@ # TODO: should this be a user input or should it be hard coded somewhere assuming it will # never change? -inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, .0175) +inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.0175) # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 24555.5, 'lbf') # Settings # --------------------------- inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.AERODYNAMICS_METHOD, LegacyCode.FLOPS) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) # --------------------------- # OUTPUTS # --------------------------- -outputs.set_val(Aircraft.Design.EMPTY_MASS, 88507., 'lbm') +outputs.set_val(Aircraft.Design.EMPTY_MASS, 88507.0, 'lbm') outputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN, 452.6, 'lbm') outputs.set_val(Aircraft.Design.TOUCHDOWN_MASS, 146328.0, 'lbm') -outputs.set_val(Aircraft.Design.OPERATING_MASS, 95267., 'lbm') -outputs.set_val(Aircraft.Propulsion.MASS, 19232., 'lbm') -outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 44648., 'lbm') -outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 24174., 'lbm') +outputs.set_val(Mission.Summary.OPERATING_MASS, 95267.0, 'lbm') +outputs.set_val(Aircraft.Propulsion.MASS, 19232.0, 'lbm') +outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 44648.0, 'lbm') +outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 24174.0, 'lbm') outputs.set_val(Aircraft.Design.TOTAL_WETTED_AREA, 8319.07, 'ft**2') -outputs.set_val(Aircraft.Design.ZERO_FUEL_MASS, 131744., 'lbm') -outputs.set_val(Mission.Design.FUEL_MASS, 42456., 'lbm') +outputs.set_val(Mission.Summary.ZERO_FUEL_MASS, 131744.0, 'lbm') +outputs.set_val(Mission.Summary.FUEL_MASS, 42456.0, 'lbm') outputs.set_val(Aircraft.AirConditioning.MASS, 1603.75, 'lbm') outputs.set_val(Aircraft.AntiIcing.MASS, 195.93, 'lbm') -outputs.set_val(Aircraft.APU.MASS, 1014., 'lbm') +outputs.set_val(Aircraft.APU.MASS, 1014.0, 'lbm') outputs.set_val(Aircraft.Avionics.MASS, 1339.4, 'lbm') @@ -290,14 +276,14 @@ outputs.set_val(Aircraft.Canard.WETTED_AREA, 0.0, 'ft**2') outputs.set_val(Aircraft.Canard.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5670., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1925., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 4077., 'lbm') +outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5670.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1925.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 4077.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS, 450.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, 975.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 2787.30285438, 'lbm') -outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 26730., 'lbm') -outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 36477., 'lbm') +outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 26730.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 36477.0, 'lbm') outputs.set_val(Aircraft.Electrical.MASS, 1935.6, 'lbm') @@ -311,14 +297,14 @@ outputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, avg_diameter, avg_diameter_units) outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 124.75, 'ft') outputs.set_val( - Aircraft.Fuselage.CROSS_SECTION, - np.pi * (avg_diameter / 2.0)**2.0, f'{avg_diameter_units}**2') + Aircraft.Fuselage.CROSS_SECTION, np.pi * (avg_diameter / 2.0) ** 2.0, f'{avg_diameter_units}**2' +) outputs.set_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.112598) outputs.set_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER, 9.841898) -outputs.set_val(Aircraft.Furnishings.MASS, 14690., 'lbm') +outputs.set_val(Aircraft.Furnishings.MASS, 14690.0, 'lbm') outputs.set_val(Aircraft.Fuselage.FINENESS, 9.8419) -outputs.set_val(Aircraft.Fuselage.MASS, 16790., 'lbm') +outputs.set_val(Aircraft.Fuselage.MASS, 16790.0, 'lbm') outputs.set_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 8.65, 'ft') outputs.set_val(Aircraft.HorizontalTail.FINENESS, 0.1195) @@ -328,81 +314,70 @@ outputs.set_val(Aircraft.Instruments.MASS, 484, 'lbm') -outputs.set_val( - Aircraft.LandingGear.MAIN_GEAR_MASS, 0.0117 * 146328.0**0.95 * 84.0**0.43, 'lbm') -outputs.set_val( - Aircraft.LandingGear.NOSE_GEAR_MASS, 0.048 * 146328.0**0.67 * 58.8**0.43, 'lbm') +outputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS, 0.0117 * 146328.0**0.95 * 84.0**0.43, 'lbm') +outputs.set_val(Aircraft.LandingGear.NOSE_GEAR_MASS, 0.048 * 146328.0**0.67 * 58.8**0.43, 'lbm') outputs.set_val(Aircraft.Nacelle.CHARACTERISTIC_LENGTH, np.array([11.65]), 'ft') outputs.set_val(Aircraft.Nacelle.FINENESS, np.array([1.6643])) outputs.set_val(Aircraft.Nacelle.MASS, 1612.2, 'lbm') nacelle_wetted_area = np.array([228.34]) nacelle_wetted_area_units = 'ft**2' +outputs.set_val(Aircraft.Nacelle.WETTED_AREA, nacelle_wetted_area, nacelle_wetted_area_units) outputs.set_val( - Aircraft.Nacelle.WETTED_AREA, nacelle_wetted_area, nacelle_wetted_area_units) -outputs.set_val(Aircraft.Nacelle.TOTAL_WETTED_AREA, - 2 * nacelle_wetted_area, nacelle_wetted_area_units) + Aircraft.Nacelle.TOTAL_WETTED_AREA, 2 * nacelle_wetted_area, nacelle_wetted_area_units +) outputs.set_val(Aircraft.Paint.MASS, 582.3, 'lbm') -dist_thrust_factor = scaled_sls_thrust - -outputs.set_val( - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, - scaled_sls_thrust * num_engines, scaled_sls_thrust_units) +outputs.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 27301.0 * 2, 'lbf') -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, num_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) -dist_count_factor = num_engines - -engine_ctrls_mass = 0.26 * dist_count_factor * dist_thrust_factor**0.5 # 85.92 +engine_ctrls_mass = 0.26 * 2 * 27301.0**0.5 # 85.92 engine_ctrls_mass_units = 'lbm' +outputs.set_val(Aircraft.Engine.CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units) outputs.set_val( - Aircraft.Engine.CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units) -outputs.set_val( - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - engine_ctrls_mass, engine_ctrls_mass_units) + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units +) outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, 125.42, 'lbm') -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, num_wing_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2) -outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, num_fuselage_engines) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 0) -outputs.set_val( - Aircraft.Propulsion.TOTAL_ENGINE_MASS, engine_mass * num_engines, engine_mass_units) +outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_MASS, 16143.0, 'lbm') -outputs.set_val(Aircraft.Engine.MASS, 16143./2.0, 'lbm') +outputs.set_val(Aircraft.Engine.MASS, 16143.0 / 2.0, 'lbm') outputs.set_val(Aircraft.Engine.POD_MASS, 10350, 'lbm') outputs.set_val(Aircraft.Engine.ADDITIONAL_MASS, 0.0, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_MISC_MASS, 550.4, 'lbm') -outputs.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) -outputs.set_val( - Aircraft.Propulsion.TOTAL_STARTER_MASS, - 11.0 * 2 * 0.82**0.32 * 7.0**1.6, 'lbm') +outputs.set_val(Aircraft.Propulsion.TOTAL_STARTER_MASS, 11.0 * 2 * 0.82**0.32 * 7.0**1.6, 'lbm') thrust_reversers_mass = 1856.4 thrust_reversers_mass_units = 'lbm' outputs.set_val( - Aircraft.Engine.THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) + Aircraft.Engine.THRUST_REVERSERS_MASS, thrust_reversers_mass, thrust_reversers_mass_units +) outputs.set_val( Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - thrust_reversers_mass, thrust_reversers_mass_units) + thrust_reversers_mass, + thrust_reversers_mass_units, +) outputs.set_val(Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, 11.30, 'ft') outputs.set_val(Aircraft.VerticalTail.FINENESS, 0.1375) outputs.set_val(Aircraft.VerticalTail.MASS, 1035.6, 'lbm') -outputs.set_val(Aircraft.Wing.BENDING_FACTOR, 9.0236) -outputs.set_val(Aircraft.Wing.BENDING_MASS, 6276.3, 'lbm') +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR, 9.0236) +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS, 6276.3, 'lbm') outputs.set_val(Aircraft.Wing.CHARACTERISTIC_LENGTH, 11.91, 'ft') outputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 0.333 * 1341.0, 'ft**2') outputs.set_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR, 0.959104) outputs.set_val(Aircraft.Wing.FINENESS, 0.1317) outputs.set_val(Aircraft.Wing.MISC_MASS, 1718.7, 'lbm') outputs.set_val(Aircraft.Wing.SHEAR_CONTROL_MASS, 7552.6, 'lbm') -outputs.set_val(Aircraft.Wing.SURFACE_CONTROL_MASS, 1835., 'lbm') +outputs.set_val(Aircraft.Wing.SURFACE_CONTROL_MASS, 1835.0, 'lbm') outputs.set_val(Mission.Design.MACH, 0.799) outputs.set_val(Mission.Design.LIFT_COEFFICIENT, 0.523) diff --git a/aviary/models/multi_engine_single_aisle/__init__.py b/aviary/models/aircraft/large_turboprop_freighter/__init__.py similarity index 100% rename from aviary/models/multi_engine_single_aisle/__init__.py rename to aviary/models/aircraft/large_turboprop_freighter/__init__.py diff --git a/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv b/aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv similarity index 78% rename from aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv rename to aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv index a60b2ab4b5..4777331da0 100644 --- a/aviary/models/large_turboprop_freighter/large_turboprop_freighter.csv +++ b/aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv @@ -1,6 +1,30 @@ -# GASP-derived aircraft input deck converted from large_turboprop_freighter.dat +############ +# SETTINGS # +############ +settings:problem_type, fallout, unitless +settings:equations_of_motion, 2DOF +settings:aerodynamics_method, GASP +settings:mass_method, GASP + +############ +# AIRCRAFT # +############ +aircraft:design:subsonic_drag_coeff_factor, 1.447, unitless -# Input Values +# Design +aircraft:design:cg_delta, 0.25, unitless +aircraft:design:cockpit_control_mass_coefficient, 20, unitless +aircraft:design:drag_coeff_increment, 0.0015, unitless +aircraft:design:emergency_equipment_mass, 25, lbm +aircraft:design:max_structural_speed, 320, mi/h +aircraft:design:part25_structural_category, 3, unitless +aircraft:design:reserve_fuel_additional, 0.667, lbm +aircraft:design:static_margin, 0.05, unitless +aircraft:design:structural_mass_increment, 0, lbm +aircraft:design:drag_divergence_shift, 0, unitless +aircraft:design:type,transport,unitless + +# Misc Systems aircraft:air_conditioning:mass_coefficient, 2.65, unitless aircraft:anti_icing:mass, 644, lbm aircraft:apu:mass, 756, lbm @@ -9,64 +33,72 @@ aircraft:controls:cockpit_control_mass_scaler, 1, unitless aircraft:controls:control_mass_increment, 0, lbm aircraft:controls:stability_augmentation_system_mass, 0, lbm aircraft:controls:stability_augmentation_system_mass_scaler, 1, unitless +aircraft:hydraulics:flight_control_mass_coefficient, 0.102, unitless +aircraft:hydraulics:gear_mass_coefficient, 0.11, unitless +aircraft:instruments:mass_coefficient, 0.0416, unitless + +# Crew and Payload aircraft:crew_and_payload:cargo_mass, 31273, lbm aircraft:crew_and_payload:catering_items_mass_per_passenger, 0, lbm +aircraft:crew_and_payload:design:num_seats_abreast_tourist, 6, unitless +aircraft:crew_and_payload:design:seat_pitch_tourist, 41.24, inch aircraft:crew_and_payload:num_passengers, 60, unitless aircraft:crew_and_payload:passenger_mass_with_bags, 190, lbm aircraft:crew_and_payload:passenger_service_mass_per_passenger, 0, lbm aircraft:crew_and_payload:water_mass_per_occupant, 0, lbm -aircraft:design:cg_delta, 0.25, unitless -aircraft:design:cockpit_control_mass_coefficient, 20, unitless -aircraft:design:drag_increment, 0.0015, unitless -aircraft:design:emergency_equipment_mass, 25, lbm -aircraft:design:max_structural_speed, 320, mi/h -aircraft:design:part25_structural_category, 3, unitless -aircraft:design:reserve_fuel_additional, 0.667, lbm -aircraft:design:static_margin, 0.05, unitless -aircraft:design:structural_mass_increment, 0, lbm -aircraft:design:supercritical_drag_shift, 0, unitless + +# Engine/Propulsion +# setting electrical mass may not do anything +aircraft:electrical:mass, 300, lbm aircraft:engine:additional_mass_fraction, 0.34, unitless +aircraft:engine:data_file, models/engines/turboshaft_4465hp.csv aircraft:engine:mass_scaler, 1, unitless aircraft:engine:mass_specific, 0.37026, lbm/lbf aircraft:engine:num_engines, 4, unitless -aircraft:engine:data_file, models/engines/turboshaft_4465hp.deck +aircraft:engine:propeller:num_blades, 4, unitless aircraft:engine:pod_mass_scaler, 1, unitless +aircraft:engine:propeller:activity_factor, 167, unitless +aircraft:engine:propeller:diameter, 13.5, ft +aircraft:engine:propeller:integrated_lift_coefficient, 0.5, unitless +aircraft:engine:propeller:tip_speed_max, 720, ft/s aircraft:engine:pylon_factor, 0.7, unitless aircraft:engine:reference_diameter, 5.8, ft -aircraft:engine:reference_sls_thrust, 28690, lbf -aircraft:engine:scaled_sls_thrust, 28690, lbf +aircraft:engine:reference_sls_thrust, 5000, lbf +aircraft:engine:rpm_design, 13820, rpm +aircraft:engine:fixed_rpm, 13820, rpm +aircraft:engine:scaled_sls_thrust, 5000, lbf aircraft:engine:type, 6, unitless aircraft:engine:wing_locations, [0.385, 0.385], unitless -aircraft:engine:propeller_diameter, 13.5, ft -aircraft:engine:num_propeller_blades, 4, unitless -aircraft:engine:propeller_activity_factor, 167, unitless -aircraft:engine:propeller_tip_speed_max, 720, ft/s -# aircraft:engine:gearbox:gear_ratio, 13.53, unitless -aircraft:engine:fixed_rpm, 1019, rpm +aircraft:engine:gearbox:gear_ratio, 13.550135501355014, unitless +aircraft:engine:gearbox:efficiency, 1.0, unitless +aircraft:engine:gearbox:shaft_power_design, 4465, hp +aircraft:engine:gearbox:specific_torque, 100.0, N*m/kg + +# Fuel aircraft:fuel:density, 6.687, lbm/galUS aircraft:fuel:fuel_margin, 15, unitless aircraft:fuel:fuel_system_mass_coefficient, 0.065, unitless aircraft:fuel:fuel_system_mass_scaler, 1, unitless aircraft:fuel:unusable_fuel_mass_coefficient, 4.5, unitless aircraft:fuel:wing_fuel_fraction, 0.324, unitless -aircraft:furnishings:mass, 0, lbm + +# Fuselage aircraft:fuselage:aisle_width, 48.8, inch aircraft:fuselage:delta_diameter, 5, ft aircraft:fuselage:flat_plate_area_increment, 2, ft**2 -aircraft:fuselage:form_factor, -1, unitless +aircraft:fuselage:form_factor, 1.25, unitless aircraft:fuselage:mass_coefficient, 145.87, unitless aircraft:fuselage:nose_fineness, 1, unitless aircraft:fuselage:num_aisles, 1, unitless -aircraft:fuselage:num_seats_abreast, 6, unitless aircraft:fuselage:pilot_compartment_length, 10.6, ft aircraft:fuselage:pressure_differential, 6.55, psi -aircraft:fuselage:seat_pitch, 41.24, inch aircraft:fuselage:seat_width, 18, inch aircraft:fuselage:tail_fineness, 2.9, unitless -aircraft:fuselage:wetted_area_factor, 1, unitless -aircraft:horizontal_tail:area, 0, ft**2 +aircraft:fuselage:wetted_area_scaler, 1, unitless + +# H-Tail aircraft:horizontal_tail:aspect_ratio, 6.03, unitless -aircraft:horizontal_tail:form_factor, -1, unitless +aircraft:horizontal_tail:form_factor, 1.25, unitless aircraft:horizontal_tail:mass_coefficient, 0.2285, unitless aircraft:horizontal_tail:moment_ratio, 0.3061, unitless aircraft:horizontal_tail:sweep, 0, deg @@ -74,35 +106,33 @@ aircraft:horizontal_tail:taper_ratio, 0.374, unitless aircraft:horizontal_tail:thickness_to_chord, 0.15, unitless aircraft:horizontal_tail:vertical_tail_fraction, 0, unitless aircraft:horizontal_tail:volume_coefficient, 0.8614, unitless -aircraft:hydraulics:flight_control_mass_coefficient, 0.102, unitless -aircraft:hydraulics:gear_mass_coefficient, 0.11, unitless -aircraft:instruments:mass_coefficient, 0.0416, unitless -aircraft:landing_gear:fixed_gear, True, unitless + +# Landing Gear +aircraft:landing_gear:fixed_gear, False, unitless aircraft:landing_gear:main_gear_location, 0, unitless aircraft:landing_gear:main_gear_mass_coefficient, 0.916, unitless aircraft:landing_gear:mass_coefficient, 0.0337, unitless aircraft:landing_gear:tail_hook_mass_scaler, 1, unitless aircraft:landing_gear:total_mass_scaler, 1, unitless + +# Nacelle aircraft:nacelle:clearance_ratio, 0.2, unitless aircraft:nacelle:core_diameter_ratio, 1.15, unitless aircraft:nacelle:fineness, 0.38, unitless -aircraft:nacelle:form_factor, -1, unitless +aircraft:nacelle:form_factor, 1.5, unitless aircraft:nacelle:mass_specific, 3, lbm/ft**2 -aircraft:strut:area_ratio, 0, unitless -aircraft:strut:attachment_location, 0, ft -aircraft:strut:attachment_location_dimensionless, 0, unitless -aircraft:strut:dimensional_location_specified, False, unitless -aircraft:strut:fuselage_interference_factor, 0, unitless -aircraft:strut:mass_coefficient, 0, unitless -aircraft:vertical_tail:area, 0, ft**2 + +# V-Tail aircraft:vertical_tail:aspect_ratio, 1.81, unitless -aircraft:vertical_tail:form_factor, -1, unitless +aircraft:vertical_tail:form_factor, 1.25, unitless aircraft:vertical_tail:mass_coefficient, 0.2035, unitless aircraft:vertical_tail:moment_ratio, 2.809, unitless aircraft:vertical_tail:sweep, 0, deg aircraft:vertical_tail:taper_ratio, 0.296, unitless aircraft:vertical_tail:thickness_to_chord, 0.15, unitless aircraft:vertical_tail:volume_coefficient, 0.05355, unitless + +# Wing aircraft:wing:aspect_ratio, 10.078, unitless aircraft:wing:center_distance, 0.45, unitless aircraft:wing:choose_fold_location, True, unitless @@ -116,38 +146,56 @@ aircraft:wing:flap_type, double_slotted, unitless aircraft:wing:fold_dimensional_location_specified, False, unitless aircraft:wing:fold_mass_coefficient, 0, unitless aircraft:wing:folded_span, 0, ft -aircraft:wing:form_factor, -1, unitless +aircraft:wing:form_factor, 1.25, unitless aircraft:wing:fuselage_interference_factor, 1, unitless aircraft:wing:has_fold, False, unitless aircraft:wing:has_strut, False, unitless aircraft:wing:height, 14.5, ft aircraft:wing:high_lift_mass_coefficient, 1.2, unitless aircraft:wing:incidence, 2, deg -aircraft:wing:loading, 88.846, lbf/ft**2 +aircraft:design:wing_loading, 88.846, lbf/ft**2 aircraft:wing:mass_coefficient, 131.32, unitless aircraft:wing:max_lift_ref, 1.5, unitless aircraft:wing:max_slat_deflection_landing, 0, deg aircraft:wing:max_slat_deflection_takeoff, 0, deg aircraft:wing:max_thickness_location, 0.35, unitless aircraft:wing:min_pressure_location, 0.3, unitless -aircraft:wing:mounting_type, 1, unitless +aircraft:wing:vertical_mount_location, 1, unitless aircraft:wing:num_flap_segments, 2, unitless aircraft:wing:optimum_flap_deflection, 55, deg aircraft:wing:optimum_slat_deflection, 45, deg aircraft:wing:slat_chord_ratio, 0, unitless aircraft:wing:slat_lift_increment_optimum, 0.93, unitless aircraft:wing:slat_span_ratio, 0.9, unitless -aircraft:wing:surface_ctrl_mass_coefficient, 0.588, unitless +aircraft:wing:surface_control_mass_coefficient, 0.588, unitless aircraft:wing:sweep, 0, deg aircraft:wing:taper_ratio, 0.52, unitless aircraft:wing:thickness_to_chord_root, 0.18, unitless aircraft:wing:thickness_to_chord_tip, 0.12, unitless aircraft:wing:zero_lift_angle, -1, deg + +# Misc Mass (zeroed out) +aircraft:strut:area_ratio, 0, unitless +aircraft:strut:attachment_location, 0, ft +aircraft:strut:attachment_location_dimensionless, 0, unitless +aircraft:strut:dimensional_location_specified, False, unitless +aircraft:strut:fuselage_interference_factor, 0, unitless +aircraft:strut:mass_coefficient, 0, unitless +aircraft:furnishings:mass, 0, lbm + +########### +# MISSION # +########### +mission:summary:fuel_flow_scaler, 1, unitless + +# Design mission:design:cruise_altitude, 21000, ft mission:design:gross_mass, 155000, lbm mission:design:mach, 0.475, unitless -mission:design:range, 0, NM +mission:design:range, 2020, NM mission:design:rate_of_climb_at_top_of_climb, 300, ft/min + +# Takeoff and Landing mission:landing:airport_altitude, 0, ft mission:landing:braking_delay, 2, s mission:landing:glide_to_stall_ratio, 1.3, unitless @@ -155,17 +203,13 @@ mission:landing:maximum_flare_load_factor, 1.15, unitless mission:landing:maximum_sink_rate, 900, ft/min mission:landing:obstacle_height, 50, ft mission:landing:touchdown_sink_rate, 5, ft/s -mission:summary:fuel_flow_scaler, 1, unitless mission:takeoff:decision_speed_increment, 5, kn mission:takeoff:rotation_speed_increment, 5, kn mission:taxi:duration, 0.15, h -settings:problem_type, fallout, unitless -settings:equations_of_motion, 2DOF -settings:mass_method, GASP - -mission:constraints:max_mach, 0.5, unitless -# Initial Guesses +################### +# Initial Guesses # +################### actual_takeoff_mass, 0 climb_range, 0 cruise_mass_final, 0 @@ -175,7 +219,9 @@ reserves, 0 rotation_mass, 0.99 time_to_climb, 0 -# Unconverted Values +###################### +# Unconverted Values # +###################### INGASP.ACDCDR, 1, 1, 1, 1, 1.15, 1.392, 1.7855, 3.5714, 5.36 INGASP.ACLS, 0, 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8 INGASP.BENGOB, 0.05 @@ -222,17 +268,12 @@ INGASP.WLPCT, 0.976 INGASP.WPLX, 25000 INGASP.XLFMAX, 1.2 INGASP.XTORQ, 4500 -INPROP.AF, 167 INPROP.ANCQHP, 0.03405 -INPROP.BL, 4 INPROP.BLANG, 0 -INPROP.CLI, 0.5 INPROP.CTI, 0.2 INPROP.DIST, 1000 -INPROP.DPROP, 13.5 -INPROP.GR, 0.0738 +INPROP.GR, 13.550135501355014 INPROP.HNOYS, 1000 -INPROP.HPMSLS, 4465 INPROP.IDATE, 1980 INPROP.JSIZE, 1 INPROP.KNOYS, -1 @@ -243,7 +284,5 @@ INPROP.PCLER, 0.1724 INPROP.PCNCCL, 1.0228 INPROP.PCNCCR, 1.05357 INPROP.PCNCTO, 1 -INPROP.TSPDMX, 720 INPROP.WKPFAC, 1.1 INPROP.WPROP1, 4500 -INPROP.XNMAX, 13820 \ No newline at end of file diff --git a/aviary/models/large_turboprop_freighter/large_turboprop_freighter.dat b/aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.dat similarity index 100% rename from aviary/models/large_turboprop_freighter/large_turboprop_freighter.dat rename to aviary/models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.dat diff --git a/aviary/models/aircraft/large_turboprop_freighter/phase_info.py b/aviary/models/aircraft/large_turboprop_freighter/phase_info.py new file mode 100644 index 0000000000..67ea298a94 --- /dev/null +++ b/aviary/models/aircraft/large_turboprop_freighter/phase_info.py @@ -0,0 +1,315 @@ +from aviary.variable_info.enums import SpeedType + +# Energy method +energy_phase_info = { + 'pre_mission': {'include_takeoff': False, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_bounds': ((0.08, 0.478), 'unitless'), + 'altitude_optimize': False, + 'altitude_bounds': ((0.0, 22_000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((24.0, 192.0), 'min'), + }, + 'initial_guesses': { + 'altitude': ([0.0, 21_000.0], 'ft'), + 'mach': ([0.2, 0.475], 'unitless'), + }, + }, + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.475, 'unitless'), + 'mach_bounds': ((0.47, 0.48), 'unitless'), + 'altitude_optimize': False, + 'altitude_initial': (21_000.0, 'ft'), + 'altitude_bounds': ((20_000.0, 22_000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((64.0, 192.0), 'min'), + 'time_duration_bounds': ((56.5, 169.5), 'min'), + }, + 'initial_guesses': { + 'altitude': ([21_000, 21_000.0], 'ft'), + 'mach': ([0.475, 0.475], 'unitless'), + }, + }, + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.475, 'unitless'), + 'mach_final': (0.1, 'unitless'), + 'mach_bounds': ((0.08, 0.48), 'unitless'), + 'altitude_optimize': False, + 'altitude_initial': (21_000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'altitude_bounds': ((0.0, 22_000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((100, 361.5), 'min'), + 'time_duration_bounds': ((29.0, 87.0), 'min'), + }, + }, + 'post_mission': { + 'include_landing': False, + 'constrain_range': True, + 'target_range': (2_020.0, 'nmi'), + }, +} + +# 2DOF +two_dof_phase_info = { + 'groundroll': { + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'time_duration_ref': (50.0, 's'), + 'time_duration_bounds': ((1.0, 100.0), 's'), + 'velocity_initial': (0.066, 'kn'), + 'velocity_bounds': ((0, 1000), 'kn'), + 'velocity_ref': (150, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_initial': (0.0, 'ft'), + 'distance_bounds': ((0, 10.0e3), 'ft'), + 'distance_ref': (3000, 'ft'), + 'distance_defect_ref': (3000, 'ft'), + }, + 'initial_guesses': { + 'time': ([0.0, 40.0], 's'), + 'velocity': ([0.066, 143.1], 'kn'), + 'distance': ([0.0, 1000.0], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'rotation': { + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'time_duration_bounds': ((1, 100), 's'), + 'time_duration_ref': (50.0, 's'), + 'velocity_bounds': ((0, 1000), 'kn'), + 'velocity_ref': (100, 'kn'), + 'velocity_ref0': (0, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 10.0e3), 'ft'), + 'distance_ref': (5000, 'ft'), + 'distance_defect_ref': (5000, 'ft'), + 'angle_of_attack_initial': (0.0, 'rad'), + 'angle_of_attack_bounds': ((0.0, 5.0), 'rad'), + 'angle_of_attack_ref': (5.0, 'rad'), + 'angle_of_attack_defect_ref': (5.0, 'rad'), + 'normal_ref': (10000, 'lbf'), + }, + 'initial_guesses': { + 'time': ([40.0, 5.0], 's'), + 'angle_of_attack': ([0.0, 2.5], 'deg'), + 'velocity': ([143, 150.0], 'kn'), + 'distance': ([3680.37217765, 4000], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'ascent': { + 'user_options': { + 'num_segments': 4, + 'order': 3, + 'velocity_bounds': ((0, 700), 'kn'), + 'velocity_ref': (200, 'kn'), + 'velocity_ref0': (0, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 15_000), 'ft'), + 'distance_ref': (1e4, 'ft'), + 'distance_defect_ref': (1e4, 'ft'), + 'altitude_bounds': ((0.0, 700.0), 'ft'), + 'altitude_ref': (1000, 'ft'), + 'altitude_defect_ref': (1000, 'ft'), + 'altitude_final': (500, 'ft'), + 'altitude_constraint_ref': (500, 'ft'), + 'flight_path_angle_bounds': ((-10.0, 20.0), 'rad'), + 'flight_path_angle_ref': (57.2958, 'deg'), + 'flight_path_angle_defect_ref': (57.2958, 'deg'), + 'flight_path_angle_initial': (0.0, 'deg'), + 'pitch_constraint_bounds': ((0.0, 15.0), 'deg'), + 'pitch_constraint_ref': (1.0, 'deg'), + }, + 'initial_guesses': { + 'time': ([45.0, 25.0], 's'), + 'flight_path_angle': ([0.0, 8.0], 'deg'), + 'angle_of_attack': ([2.5, 1.5], 'deg'), + 'velocity': ([150.0, 185.0], 'kn'), + 'distance': ([4.0e3, 10.0e3], 'ft'), + 'altitude': ([0.0, 500.0], 'ft'), + 'tau_gear': (0.2, 'unitless'), + 'tau_flaps': (0.9, 'unitless'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'accel': { + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'alt': (500, 'ft'), + 'EAS_constraint_eq': (250, 'kn'), + 'time_duration_bounds': ((1, 200), 's'), + 'time_duration_ref': (1000, 's'), + 'velocity_bounds': ((150, 270), 'kn'), + 'velocity_ref': (250, 'kn'), + 'velocity_ref0': (150, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 150.0), 'NM'), + 'distance_ref': (5, 'NM'), + 'distance_defect_ref': (5, 'NM'), + }, + 'initial_guesses': { + 'time': ([70.0, 13.0], 's'), + 'velocity': ([185.0, 250.0], 'kn'), + 'distance': ([10.0e3, 20.0e3], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'climb1': { + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'EAS_target': (250, 'kn'), + 'mach_cruise': 0.475, + 'target_mach': False, + 'time_duration_bounds': ((30, 300), 's'), + 'time_duration_ref': (1000, 's'), + 'altitude_final': (10.0e3, 'ft'), + 'altitude_bounds': ((400.0, 11_000.0), 'ft'), + 'altitude_ref': (10.0e3, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 500.0), 'NM'), + 'distance_ref': (10, 'NM'), + 'distance_ref0': (0, 'NM'), + }, + 'initial_guesses': { + 'time': ([1.0, 2.0], 'min'), + 'distance': ([20.0e3, 100.0e3], 'ft'), + 'altitude': ([500.0, 10.0e3], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'climb2': { + 'user_options': { + 'num_segments': 3, + 'order': 3, + 'EAS_target': (160, 'kn'), + 'mach_cruise': 0.475, + 'target_mach': True, + 'required_available_climb_rate': (0.1, 'ft/min'), + 'time_duration_bounds': ((200, 17_000), 's'), + 'time_duration_ref': (5000, 's'), + 'altitude_final': (21_000, 'ft'), + 'altitude_bounds': ((9000.0, 22_000.0), 'ft'), + 'altitude_ref': (20_000, 'ft'), + 'altitude_ref0': (0, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((10.0, 1000.0), 'NM'), + 'distance_ref': (500, 'NM'), + 'distance_ref0': (0, 'NM'), + 'distance_defect_ref': (500, 'NM'), + }, + 'initial_guesses': { + 'time': ([216.0, 1300.0], 's'), + 'distance': ([100.0e3, 200.0e3], 'ft'), + 'altitude': ([10_000, 20_000], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'cruise': { + 'user_options': { + 'alt_cruise': (21_000, 'ft'), + 'mach_cruise': 0.475, + }, + 'initial_guesses': { + # [Initial mass, delta mass] for special cruise phase. + 'mass': ([150_000.0, -35_000], 'lbm'), + 'initial_distance': (100.0e3, 'ft'), + 'initial_time': (1_000.0, 's'), + 'altitude': (21_000, 'ft'), + 'mach': (0.475, 'unitless'), + }, + }, + 'desc1': { + 'user_options': { + 'num_segments': 3, + 'order': 3, + 'EAS_limit': (160, 'kn'), + 'mach_cruise': 0.475, + 'input_speed_type': SpeedType.MACH, + 'time_duration_bounds': ((300.0, 900.0), 's'), + 'time_duration_ref': (1000, 's'), + 'altitude_final': (10_000, 'ft'), + 'altitude_bounds': ((1000.0, 22_000.0), 'ft'), + 'altitude_ref': (20_000, 'ft'), + 'altitude_ref0': (0, 'ft'), + 'altitude_constraint_ref': (10000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (140_000, 'lbm'), + 'mass_ref0': (0, 'lbm'), + 'mass_defect_ref': (140_000, 'lbm'), + 'distance_bounds': ((1_000.0, 3_000.0), 'NM'), + 'distance_ref': (2_020, 'NM'), + 'distance_ref0': (0, 'NM'), + 'distance_defect_ref': (100, 'NM'), + }, + 'initial_guesses': { + 'mass': (136000.0, 'lbm'), + 'altitude': ([20_000, 10_000], 'ft'), + 'throttle': ([0.0, 0.0], 'unitless'), + 'distance': ([0.92 * 2_020, 0.96 * 2_020], 'NM'), + 'time': ([28000.0, 500.0], 's'), + }, + }, + 'desc2': { + 'user_options': { + 'num_segments': 1, + 'order': 7, + 'EAS_limit': (250, 'kn'), + 'mach_cruise': 0.80, + 'input_speed_type': SpeedType.EAS, + 'time_duration_bounds': ((100.0, 5000), 's'), + 'time_duration_ref': (500, 's'), + 'altitude_final': (1000, 'ft'), + 'altitude_bounds': ((500.0, 11_000.0), 'ft'), + 'altitude_ref': (10.0e3, 'ft'), + 'altitude_ref0': (1000, 'ft'), + 'altitude_constraint_ref': (1000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0.0, 5000.0), 'NM'), + 'distance_ref': (3500, 'NM'), + 'distance_defect_ref': (100, 'NM'), + }, + 'initial_guesses': { + 'mass': (136000.0, 'lbm'), + 'altitude': ([10.0e3, 1.0e3], 'ft'), + 'throttle': ([0.0, 0.0], 'unitless'), + 'distance': ([0.96 * 2_020, 2_020], 'NM'), + 'time': ([28500.0, 500.0], 's'), + }, + }, +} diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/__init__.py b/aviary/models/aircraft/multi_engine_single_aisle/__init__.py similarity index 100% rename from aviary/subsystems/aerodynamics/gasp_based/data/__init__.py rename to aviary/models/aircraft/multi_engine_single_aisle/__init__.py diff --git a/aviary/models/multi_engine_single_aisle/multi_engine_single_aisle_data.py b/aviary/models/aircraft/multi_engine_single_aisle/multi_engine_single_aisle_data.py similarity index 84% rename from aviary/models/multi_engine_single_aisle/multi_engine_single_aisle_data.py rename to aviary/models/aircraft/multi_engine_single_aisle/multi_engine_single_aisle_data.py index 0ff0dc67a1..4850b4a5d8 100644 --- a/aviary/models/multi_engine_single_aisle/multi_engine_single_aisle_data.py +++ b/aviary/models/aircraft/multi_engine_single_aisle/multi_engine_single_aisle_data.py @@ -11,10 +11,10 @@ # Overall Aircraft # --------------------------- -inputs.set_val(Aircraft.Design.BASE_AREA, 0., 'ft**2') +inputs.set_val(Aircraft.Design.BASE_AREA, 0.0, 'ft**2') inputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, 0.00514) inputs.set_val(Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, 0.84) -inputs.set_val(Mission.Design.GROSS_MASS, 174200., 'lbm') +inputs.set_val(Mission.Design.GROSS_MASS, 174200.0, 'lbm') inputs.set_val(Aircraft.Design.USE_ALT_MASS, False) inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 1.0) inputs.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0) @@ -54,17 +54,17 @@ inputs.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, 162, units='unitless') inputs.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, 150) -inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35., 'lbm') +inputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 35.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, 5) inputs.set_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW, 2) inputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, 1.0) inputs.set_val(Aircraft.CrewPayload.NUM_GALLEY_CREW, 1) -inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077., 'lbm') +inputs.set_val(Aircraft.CrewPayload.MISC_CARGO, 4077.0, 'lbm') inputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, 1.0) -inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.) -inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165., 'lbm') -inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0., 'lbm') +inputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 165.0, 'lbm') +inputs.set_val(Aircraft.CrewPayload.WING_CARGO, 0.0, 'lbm') # Electrical # --------------------------- @@ -81,7 +81,7 @@ # Fuel # --------------------------- inputs.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') -inputs.set_val(Aircraft.Fuel.DENSITY_RATIO, 1.0) +inputs.set_val(Aircraft.Fuel.DENSITY, 6.7, 'lbm/galUS') inputs.set_val(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0) inputs.set_val(Aircraft.Fuel.NUM_TANKS, 7) inputs.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 46063.0, 'lbm') @@ -117,7 +117,7 @@ # Hydraulics # --------------------------- -inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000., 'psi') +inputs.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 3000.0, 'psi') inputs.set_val(Aircraft.Hydraulics.MASS_SCALER, 1.0) # Instruments @@ -126,7 +126,6 @@ # Landing Gear # --------------------------- -inputs.set_val(Aircraft.LandingGear.CARRIER_BASED, False) inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, 84.0, 'inch') inputs.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, 1.0) inputs.set_val(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, 58.8, 'inch') @@ -149,14 +148,14 @@ inputs.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, 1.0) # Engine 1: turbofan_28k -filename = get_path( - 'models/engines/turbofan_28k.deck') +filename = get_path('models/engines/turbofan_28k.csv') engine_1_inputs = AviaryValues() engine_1_inputs.set_val(Aircraft.Engine.DATA_FILE, filename) engine_1_inputs.set_val(Aircraft.Engine.MASS, 7400, 'lbm') engine_1_inputs.set_val(Aircraft.Engine.REFERENCE_MASS, 7400, 'lbm') -engine_1_inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 28928.1/2, 'lbf') +# engine_1_inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 28928.1/2, 'lbf') +engine_1_inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 0.3837186) # engine_1_inputs.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 28928.1, 'lbf') engine_1_inputs.set_val(Aircraft.Engine.NUM_ENGINES, 2) engine_1_inputs.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 0) @@ -182,13 +181,14 @@ engine_1_inputs.set_val(Mission.Summary.FUEL_FLOW_SCALER, 1.0) # Engine 2: -filename = get_path('models/engines/turbofan_22k.deck') +filename = get_path('models/engines/turbofan_22k.csv') engine_2_inputs = AviaryValues() engine_2_inputs.set_val(Aircraft.Engine.DATA_FILE, filename) engine_2_inputs.set_val(Aircraft.Engine.MASS, 6293.8, 'lbm') engine_2_inputs.set_val(Aircraft.Engine.REFERENCE_MASS, 6293.8, 'lbm') -engine_2_inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 22200.5/2, 'lbf') +# engine_2_inputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 22200.5/2, 'lbf') +engine_2_inputs.set_val(Aircraft.Engine.SCALE_FACTOR, 0.65151911) # engine_2_inputs.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 22200.5, 'lbf') engine_2_inputs.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, 0.0) engine_2_inputs.set_val(Aircraft.Engine.NUM_ENGINES, 2) @@ -230,11 +230,11 @@ inputs.set_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY, 1.87) inputs.set_val(Aircraft.Wing.AREA, 1341.0, 'ft**2') inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 9.42519) -inputs.set_val(Aircraft.Wing.BENDING_MASS_SCALER, 1.0) -inputs.set_val( - Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, np.array([0.4441, 0.2313, 0.0729])) +inputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, 1.0) +inputs.set_val(Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, np.array([0.4441, 0.2313, 0.0729])) inputs.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.0) inputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, 0.333) +inputs.set_val(Aircraft.Wing.DETAILED_WING, True) inputs.set_val(Aircraft.Wing.GLOVE_AND_BAT, 0.0, 'ft**2') inputs.set_val(Aircraft.Wing.INPUT_STATION_DIST, np.array([0.0, 0.3238, 1.0])) inputs.set_val(Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL, 2.0) @@ -252,8 +252,7 @@ inputs.set_val(Aircraft.Wing.SWEEP, 25.03, 'deg') inputs.set_val(Aircraft.Wing.TAPER_RATIO, 0.237343146184852) inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, 0.131732727515702) -inputs.set_val( - Aircraft.Wing.THICKNESS_TO_CHORD_DIST, np.array([0.145, 0.115, 0.104])) +inputs.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_DIST, np.array([0.145, 0.115, 0.104])) inputs.set_val(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.75) inputs.set_val(Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, 0) inputs.set_val(Aircraft.Wing.MASS, 15548, 'lbm') @@ -264,7 +263,7 @@ # Mission # --------------------------- inputs.set_val(Mission.Summary.CRUISE_MACH, 0.785) # was 0.82 -inputs.set_val(Mission.Design.RANGE, 2960., 'NM') +inputs.set_val(Mission.Design.RANGE, 2960.0, 'NM') inputs.set_val(Mission.Summary.FUEL_FLOW_SCALER, 1.0) inputs.set_val(Mission.Constraints.MAX_MACH, 0.82) # TODO investigate the origin of these values (taken from benchmark tests) @@ -279,13 +278,14 @@ # TODO: should this be a user input or should it be hard coded somewhere assuming it will # never change? -inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, .0175) +inputs.set_val(Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, 0.0175) # lbf TODO: where should this get connected from? inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, 24555.5, 'lbf') # Settings # --------------------------- inputs.set_val(Settings.EQUATIONS_OF_MOTION, EquationsOfMotion.HEIGHT_ENERGY) +inputs.set_val(Settings.AERODYNAMICS_METHOD, LegacyCode.FLOPS) inputs.set_val(Settings.MASS_METHOD, LegacyCode.FLOPS) inputs.set_val(Settings.VERBOSITY, 0) @@ -293,21 +293,21 @@ # OUTPUTS # --------------------------- -outputs.set_val(Aircraft.Design.EMPTY_MASS, 92023., 'lbm') +outputs.set_val(Aircraft.Design.EMPTY_MASS, 92023.0, 'lbm') outputs.set_val(Aircraft.Design.EMPTY_MASS_MARGIN, 0.0, 'lbm') -outputs.set_val(Aircraft.Design.OPERATING_MASS, 97992., 'lbm') -outputs.set_val(Aircraft.Propulsion.MASS, 16118., 'lbm') -outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 50736., 'lbm') -outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 25169., 'lbm') +outputs.set_val(Mission.Summary.OPERATING_MASS, 97992.0, 'lbm') +outputs.set_val(Aircraft.Propulsion.MASS, 16118.0, 'lbm') +outputs.set_val(Aircraft.Design.STRUCTURE_MASS, 50736.0, 'lbm') +outputs.set_val(Aircraft.Design.SYSTEMS_EQUIP_MASS, 25169.0, 'lbm') outputs.set_val(Aircraft.Design.TOTAL_WETTED_AREA, 8275.86, 'ft**2') -outputs.set_val(Aircraft.Design.ZERO_FUEL_MASS, 135848., 'lbm') -outputs.set_val(Mission.Design.FUEL_MASS, 45352., 'lbm') +outputs.set_val(Mission.Summary.ZERO_FUEL_MASS, 135848.0, 'lbm') +outputs.set_val(Mission.Summary.FUEL_MASS, 45352.0, 'lbm') -outputs.set_val(Aircraft.AirConditioning.MASS, 1602., 'lbm') +outputs.set_val(Aircraft.AirConditioning.MASS, 1602.0, 'lbm') outputs.set_val(Aircraft.AntiIcing.MASS, 208.85, 'lbm') -outputs.set_val(Aircraft.APU.MASS, 1142., 'lbm') +outputs.set_val(Aircraft.APU.MASS, 1142.0, 'lbm') outputs.set_val(Aircraft.Avionics.MASS, 1652.6, 'lbm') @@ -316,14 +316,14 @@ outputs.set_val(Aircraft.Canard.WETTED_AREA, 0.0, 'ft**2') outputs.set_val(Aircraft.Canard.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 7436., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 0., 'lbm') -outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1400., 'lbm') +outputs.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 7436.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_MASS, 0.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.CARGO_CONTAINER_MASS, 1400.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.FLIGHT_CREW_MASS, 450.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, 465.0, 'lbm') outputs.set_val(Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, 3022.74805809, 'lbm') -outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 30420., 'lbm') -outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 37856., 'lbm') +outputs.set_val(Aircraft.CrewPayload.PASSENGER_MASS, 30420.0, 'lbm') +outputs.set_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 37856.0, 'lbm') outputs.set_val(Aircraft.Electrical.MASS, 2464.0, 'lbm') @@ -332,23 +332,25 @@ outputs.set_val(Aircraft.Fins.MASS, 0.0, 'lbm') -outputs.set_val(Aircraft.Furnishings.MASS, 15517., 'lbm') +outputs.set_val(Aircraft.Furnishings.MASS, 15517.0, 'lbm') avg_diameter = 12.75 avg_diameter_units = 'ft' outputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, avg_diameter, avg_diameter_units) -outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 128., 'ft') +outputs.set_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 128.0, 'ft') outputs.set_val( Aircraft.Fuselage.CROSS_SECTION, - np.pi * (avg_diameter / 2.0)**2.0, f'{avg_diameter_units}**2') + np.pi * (avg_diameter / 2.0) ** 2.0, + f'{avg_diameter_units}**2', +) outputs.set_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.108207) outputs.set_val(Aircraft.Fuselage.FINENESS, 10.0392) outputs.set_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER, 10.039216) -outputs.set_val(Aircraft.Fuselage.MASS, 18357., 'lbm') +outputs.set_val(Aircraft.Fuselage.MASS, 18357.0, 'lbm') outputs.set_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 7.69, 'ft') outputs.set_val(Aircraft.HorizontalTail.FINENESS, 0.1250) -outputs.set_val(Aircraft.HorizontalTail.MASS, 1831., 'lbm') +outputs.set_val(Aircraft.HorizontalTail.MASS, 1831.0, 'lbm') outputs.set_val(Aircraft.Hydraulics.MASS, 1086.7, 'lbm') @@ -363,38 +365,39 @@ nacelle_wetted_area = np.array([273.45]) nacelle_wetted_area_units = 'ft**2' -outputs.set_val( - Aircraft.Nacelle.WETTED_AREA, nacelle_wetted_area, nacelle_wetted_area_units) +outputs.set_val(Aircraft.Nacelle.WETTED_AREA, nacelle_wetted_area, nacelle_wetted_area_units) outputs.set_val( Aircraft.Nacelle.TOTAL_WETTED_AREA, - 2 * nacelle_wetted_area, nacelle_wetted_area_units) + 2 * nacelle_wetted_area, + nacelle_wetted_area_units, +) outputs.set_val(Aircraft.Paint.MASS, 306.2, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 51128.6, 'lbf') -outputs.set_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, 4) +outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 4) engine_ctrls_mass = 88.44 engine_ctrls_mass_units = 'lbm' -outputs.set_val( - Aircraft.Engine.CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units) +outputs.set_val(Aircraft.Engine.CONTROLS_MASS, engine_ctrls_mass, engine_ctrls_mass_units) outputs.set_val( Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - engine_ctrls_mass, engine_ctrls_mass_units) + engine_ctrls_mass, + engine_ctrls_mass_units, +) outputs.set_val(Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, 130.23, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 4) outputs.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 0) -outputs.set_val(Aircraft.Engine.MASS, 14800/2, 'lbm') +outputs.set_val(Aircraft.Engine.SCALED_SLS_THRUST, np.array([28928.1 / 2, 22200.5 / 2]), 'lbf') +outputs.set_val(Aircraft.Engine.MASS, 14800 / 2, 'lbm') outputs.set_val(Aircraft.Engine.POD_MASS, 9000, 'lbm') outputs.set_val(Aircraft.Engine.ADDITIONAL_MASS, 0.0, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_MISC_MASS, 648.83, 'lbm') -outputs.set_val(Aircraft.Engine.SCALE_FACTOR, np.array([0.5, 0.5])) outputs.set_val(Aircraft.Propulsion.TOTAL_STARTER_MASS, 560.39, 'lbm') outputs.set_val(Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, 0, 'lbm') @@ -408,8 +411,8 @@ outputs.set_val(Aircraft.VerticalTail.FINENESS, 0.1195) outputs.set_val(Aircraft.VerticalTail.MASS, 1221.8, 'lbm') -outputs.set_val(Aircraft.Wing.BENDING_FACTOR, 11.5918) -outputs.set_val(Aircraft.Wing.BENDING_MASS, 8184.8, 'lbm') +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR, 11.5918) +outputs.set_val(Aircraft.Wing.BENDING_MATERIAL_MASS, 8184.8, 'lbm') outputs.set_val(Aircraft.Wing.CHARACTERISTIC_LENGTH, 10.49, 'ft') # Not in FLOPS output; calculated from inputs. outputs.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 137, 'ft**2') diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv b/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.csv similarity index 92% rename from aviary/models/small_single_aisle/small_single_aisle_GwGm.csv rename to aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.csv index 505465acdc..d0a70cded2 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.csv +++ b/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.csv @@ -7,15 +7,17 @@ aircraft:controls:cockpit_control_mass_scaler,1,unitless aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless -aircraft:crew_and_payload:cargo_mass,8598,lbm aircraft:crew_and_payload:catering_items_mass_per_passenger,6,lbm aircraft:crew_and_payload:design:num_passengers,96,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,4,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,31,inch aircraft:crew_and_payload:passenger_mass_with_bags,210,lbm aircraft:crew_and_payload:passenger_service_mass_per_passenger,7.6,lbm +aircraft:crew_and_payload:uld_mass_per_passenger,0.11,lbm aircraft:crew_and_payload:water_mass_per_occupant,3,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless -aircraft:design:drag_increment,0.0018,unitless +aircraft:design:drag_coeff_increment,0.0018,unitless aircraft:design:emergency_equipment_mass,50,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless @@ -23,9 +25,11 @@ aircraft:design:reserve_fuel_additional,0,lbm aircraft:design:reserve_fuel_fraction,0.125,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm -aircraft:design:supercritical_drag_shift,0.025,unitless +aircraft:design:drag_divergence_shift,0.025,unitless +aircraft:design:type,transport,unitless aircraft:engine:additional_mass_fraction,0.14,unitless -aircraft:engine:data_file,models/engines/turbofan_23k_1.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_23k_1.csv,unitless +aircraft:engine:global_throttle, True, unitless aircraft:engine:mass_scaler,1,unitless aircraft:engine:mass_specific,0.2153,lbm/lbf aircraft:engine:num_engines,2,unitless @@ -33,6 +37,7 @@ aircraft:engine:pod_mass_scaler,1,unitless aircraft:engine:pylon_factor,0.6,unitless aircraft:engine:reference_diameter,6.04,ft aircraft:engine:reference_sls_thrust,28690,lbf +aircraft:engine:scale_factor,0.8295573370512374,unitless aircraft:engine:scaled_sls_thrust,23800,lbf aircraft:engine:type,7,unitless aircraft:engine:wing_locations,0.272,unitless @@ -50,14 +55,11 @@ aircraft:fuselage:form_factor,1.55,unitless aircraft:fuselage:mass_coefficient,121.2,unitless aircraft:fuselage:nose_fineness,0.845,unitless aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_seats_abreast,4,unitless aircraft:fuselage:pilot_compartment_length,11.7,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_pitch,31,inch aircraft:fuselage:seat_width,24,inch aircraft:fuselage:tail_fineness,3.368,unitless aircraft:fuselage:wetted_area_scaler,1,unitless -aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.26,unitless aircraft:horizontal_tail:form_factor,1.55,unitless aircraft:horizontal_tail:mass_coefficient,0.325,unitless @@ -87,7 +89,6 @@ aircraft:strut:attachment_location_dimensionless,0,unitless aircraft:strut:dimensional_location_specified,False,unitless aircraft:strut:fuselage_interference_factor,0,unitless aircraft:strut:mass_coefficient,0,unitless -aircraft:vertical_tail:area,0,ft**2 aircraft:vertical_tail:aspect_ratio,1.84,unitless aircraft:vertical_tail:form_factor,1.55,unitless aircraft:vertical_tail:mass_coefficient,0.425,unitless @@ -116,21 +117,21 @@ aircraft:wing:has_strut,False,unitless aircraft:wing:height,6.5,ft aircraft:wing:high_lift_mass_coefficient,1.9,unitless aircraft:wing:incidence,1.5,deg -aircraft:wing:loading,112.6,lbf/ft**2 +aircraft:design:wing_loading,112.6,lbf/ft**2 aircraft:wing:mass_coefficient,108.75,unitless aircraft:wing:max_lift_ref,1.4,unitless aircraft:wing:max_slat_deflection_landing,10,deg aircraft:wing:max_slat_deflection_takeoff,10,deg aircraft:wing:max_thickness_location,0.35,unitless aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:mounting_type,0,unitless +aircraft:wing:vertical_mount_location,0,unitless aircraft:wing:num_flap_segments,2,unitless aircraft:wing:optimum_flap_deflection,20,deg aircraft:wing:optimum_slat_deflection,20,deg aircraft:wing:slat_chord_ratio,0.1,unitless aircraft:wing:slat_lift_increment_optimum,0.93,unitless aircraft:wing:slat_span_ratio,0.9,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.845,unitless +aircraft:wing:surface_control_mass_coefficient,0.845,unitless aircraft:wing:sweep,26.34,deg aircraft:wing:taper_ratio,0.301,unitless aircraft:wing:thickness_to_chord_root,0.1125,unitless @@ -154,6 +155,7 @@ mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.3333,h settings:equations_of_motion,2DOF +settings:aerodynamics_method,GASP settings:mass_method,GASP # Initialization Guesses diff --git a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat b/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.dat similarity index 97% rename from aviary/models/small_single_aisle/small_single_aisle_GwGm.dat rename to aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.dat index a46cb52fdf..ae4277db71 100644 --- a/aviary/models/small_single_aisle/small_single_aisle_GwGm.dat +++ b/aviary/models/aircraft/small_single_aisle/small_single_aisle_GASP.dat @@ -1,11 +1,5 @@ Small Single Aisle / turbofan_24k_2 -1 - aircraft:engine:data_file=models/engines/turbofan_24k_2.deck - aircraft:engine:data_file=models/engines/turbofan_23k_1.deck !temporary - mission:summary:gross_mass=124780 - aircraft:engine:reference_diameter=6.04 - - $INGASP AS=1., ! Number of aisles in the cabin AR=11.03, ! Wing aspect ratio @@ -126,7 +120,7 @@ CW(11)=50.0, ! emergency equipment CW(12)=6.0, ! catering items lbsf per passenger CW(13)=6.0, CW(13)=12., ! trapped fuel factor - !CW(14)=0.11, ! cargo handling, number of ULD's per passemger + CW(14)=0.11, ! cargo handling, number of ULD's per passemger !CW(15)=12.5, ! electrical system weight per passenger (16.0) !CW(16)=520., ! other operating items (0) CKFF=1.000, ! factor on installed engine fuel flow diff --git a/aviary/models/aircraft/test_aircraft/GwFm_phase_info.py b/aviary/models/aircraft/test_aircraft/GwFm_phase_info.py new file mode 100644 index 0000000000..f2f35985cc --- /dev/null +++ b/aviary/models/aircraft/test_aircraft/GwFm_phase_info.py @@ -0,0 +1,71 @@ +phase_info = { + 'pre_mission': {'include_takeoff': True, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise', 'solve_alpha': True}}, + 'user_options': { + 'num_segments': 6, + 'order': 3, + 'mach_optimize': True, + 'mach_bounds': ((0.1, 0.8), 'unitless'), + 'altitude_optimize': True, + 'altitude_bounds': ((0.0, 36000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((5.0, 50.0), 'min'), + 'no_descent': True, + }, + 'initial_guesses': { + 'time': ([0, 40.0], 'min'), + 'altitude': ([0, 35000.0], 'ft'), + 'mach': ([0.2, 0.79], 'unitless'), + }, + }, + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise', 'solve_alpha': True}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'mach_optimize': True, + 'mach_polynomial_order': 1, + 'mach_initial': (0.79, 'unitless'), + 'mach_bounds': ((0.78, 0.8), 'unitless'), + 'altitude_optimize': True, + 'altitude_polynomial_order': 1, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_bounds': ((35000.0, 35000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial_bounds': ((64.0, 192.0), 'min'), + 'time_duration_bounds': ((60.0, 7200.0), 'min'), + }, + 'initial_guesses': { + 'time': ([128, 113], 'min'), + 'altitude': ([35000, 35000.0], 'ft'), + 'mach': ([0.79, 0.79], 'unitless'), + }, + }, + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise', 'solve_alpha': True}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': True, + 'mach_initial': (0.79, 'unitless'), + 'mach_final': (0.3, 'unitless'), + 'mach_bounds': ((0.2, 0.8), 'unitless'), + 'altitude_optimize': True, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'altitude_bounds': ((0.0, 35000.0), 'ft'), + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((120.5, 361.5), 'min'), + 'time_duration_bounds': ((5.0, 30.0), 'min'), + 'no_climb': True, + }, + 'initial_guesses': {'time': ([241, 30], 'min')}, + }, + 'post_mission': { + 'include_landing': False, + 'constrain_range': True, + 'target_range': (3360.0, 'nmi'), + }, +} diff --git a/aviary/models/aircraft/test_aircraft/README.txt b/aviary/models/aircraft/test_aircraft/README.txt new file mode 100644 index 0000000000..b5385c6b43 --- /dev/null +++ b/aviary/models/aircraft/test_aircraft/README.txt @@ -0,0 +1,15 @@ +The aircraft in this folder are variations of the existing example models intended for testing Aviary's code. +The models themselves are valid Aviary aircraft that produce physically possible results, but may not be "realistic" due to arbitrary modifications. + +The suite of test aircraft include: +- `aircraft_for_bench_FwFm`: conventional single-aisle transport using all FLOPS-based analysis +- `aircraft_for_bench_FwGm`: conventional single-aisle transport using FLOPS mass, GASP aero, both geometry methods (FLOPS priority), and the 2DOF mission method +- `aircraft_for_bench_GwGm`: conventional single-aisle transport using all GASP-based analysis +- `aircraft_for_bench_GwFm`: conventional single-aisle transport using GASP mass, geometry, and aero, and the energy mission method +- `aircraft_for_bench_FwFm_with_electric`: the FwFm benchmark model using the electrified 28k turbofan engine (no batteries/external subsystems) +- `aircraft_for_bench_solve2dof`: the GwGm benchmark using the "solved 2dof" equations of motion + +Also included in this folder: +`GwFm_phase_info`: the custom phase info needed for the GwFm benchmark +`turbofan_28k_with_electric`: a version of the "turbofan_28k" engine deck with arbitrary electric power consumption. Used for the "aircraft_for_bench_FwFm_with_electric" model. + diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv similarity index 94% rename from aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv rename to aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv index bd9fa34123..cba2d49d8a 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv @@ -25,6 +25,7 @@ aircraft:design:empty_mass_margin_scaler,0.0,unitless aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:reserve_fuel_additional,3000.,lbm +aircraft:design:reserve_fuel_fraction,0,unitless aircraft:design:subsonic_drag_coeff_factor,1.0,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:use_alt_mass,False,unitless @@ -32,7 +33,7 @@ aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless aircraft:electrical:mass_scaler,1.25,unitless aircraft:engine:additional_mass_fraction,0.,unitless aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_28k.csv,unitless aircraft:engine:flight_idle_thrust_fraction,0.0,unitless aircraft:engine:flight_idle_max_fraction,1.0,unitless aircraft:engine:flight_idle_min_fraction,0.08,unitless @@ -49,6 +50,7 @@ aircraft:engine:num_fuselage_engines,0,unitless aircraft:engine:num_wing_engines,2,unitless aircraft:engine:reference_mass,7400,lbm aircraft:engine:reference_sls_thrust,28928.1,lbf +aircraft:engine:scale_factor,1.0,unitless aircraft:engine:scale_mass,True,unitless aircraft:engine:scale_performance,True,unitless aircraft:engine:scaled_sls_thrust,28928.1,lbf @@ -62,7 +64,6 @@ aircraft:fins:mass,0.0,lbm aircraft:fins:num_fins,0,unitless aircraft:fins:taper_ratio,10.0,unitless aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless aircraft:fuel:fuel_system_mass_scaler,1.0,unitless aircraft:fuel:fuselage_fuel_capacity,0.0,lbm aircraft:fuel:num_tanks,7,unitless @@ -90,7 +91,6 @@ aircraft:horizontal_tail:wetted_area,592.65,ft**2 aircraft:hydraulics:mass_scaler,1.0,unitless aircraft:hydraulics:system_pressure,3000,psi aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless aircraft:landing_gear:main_gear_oleo_length,102.0,inch aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless @@ -114,11 +114,12 @@ aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless aircraft:wing:airfoil_technology,1.92669766647637,unitless aircraft:wing:area,1370.0,ft**2 aircraft:wing:aspect_ratio,11.22091,unitless -aircraft:wing:bending_mass_scaler,1.0,unitless +aircraft:wing:bending_material_mass_scaler,1.0,unitless aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless aircraft:wing:composite_fraction,0.2,unitless aircraft:wing:control_surface_area,137,ft**2 aircraft:wing:control_surface_area_ratio,0.1,unitless +aircraft:wing:detailed_wing,True,unitless aircraft:wing:glove_and_bat,134.0,ft**2 aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless aircraft:wing:load_distribution_control,2.0,unitless @@ -132,7 +133,7 @@ aircraft:wing:shear_control_mass_scaler,1.0,unitless aircraft:wing:span_efficiency_reduction,False,unitless aircraft:wing:span,117.83,ft aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless +aircraft:wing:surface_control_mass_scaler,1.0,unitless aircraft:wing:sweep,25.0,deg aircraft:wing:taper_ratio,0.278,unitless aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless @@ -153,4 +154,6 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless settings:equations_of_motion,height_energy -settings:mass_method,FLOPS \ No newline at end of file +settings:aerodynamics_method,FLOPS +settings:mass_method,FLOPS +settings:payload_range,false \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv similarity index 95% rename from aviary/models/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv rename to aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv index 7dcd992889..8057fa3ad2 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv @@ -32,7 +32,7 @@ aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless aircraft:electrical:mass_scaler,1.25,unitless aircraft:engine:additional_mass_fraction,0.,unitless aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_28k_with_electric.deck,unitless +aircraft:engine:data_file,models/aircraft/test_aircraft/turbofan_28k_with_electric.csv,unitless aircraft:engine:flight_idle_thrust_fraction,0.0,unitless aircraft:engine:flight_idle_max_fraction,1.0,unitless aircraft:engine:flight_idle_min_fraction,0.08,unitless @@ -49,6 +49,7 @@ aircraft:engine:num_fuselage_engines,0,unitless aircraft:engine:num_wing_engines,2,unitless aircraft:engine:reference_mass,7400,lbm aircraft:engine:reference_sls_thrust,28928.1,lbf +aircraft:engine:scale_factor,1.0,unitless aircraft:engine:scale_mass,True,unitless aircraft:engine:scale_performance,True,unitless aircraft:engine:scaled_sls_thrust,28928.1,lbf @@ -62,7 +63,6 @@ aircraft:fins:mass,0.0,lbm aircraft:fins:num_fins,0,unitless aircraft:fins:taper_ratio,10.0,unitless aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless aircraft:fuel:fuel_system_mass_scaler,1.0,unitless aircraft:fuel:fuselage_fuel_capacity,0.0,lbm aircraft:fuel:num_tanks,7,unitless @@ -90,7 +90,6 @@ aircraft:horizontal_tail:wetted_area,592.65,ft**2 aircraft:hydraulics:mass_scaler,1.0,unitless aircraft:hydraulics:system_pressure,3000.0,lbf/ft**2 aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless aircraft:landing_gear:main_gear_oleo_length,102.0,inch aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless @@ -114,11 +113,12 @@ aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless aircraft:wing:airfoil_technology,1.92669766647637,unitless aircraft:wing:area,1370.0,ft**2 aircraft:wing:aspect_ratio,11.22091,unitless -aircraft:wing:bending_mass_scaler,1.0,unitless +aircraft:wing:bending_material_mass_scaler,1.0,unitless aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless aircraft:wing:composite_fraction,0.2,unitless aircraft:wing:control_surface_area,137,ft**2 aircraft:wing:control_surface_area_ratio,0.1,unitless +aircraft:wing:detailed_wing,True,unitless aircraft:wing:glove_and_bat,134.0,ft**2 aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless aircraft:wing:load_distribution_control,2.0,unitless @@ -132,7 +132,7 @@ aircraft:wing:shear_control_mass_scaler,1.0,unitless aircraft:wing:span_efficiency_reduction,False,unitless aircraft:wing:span,117.83,ft aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless +aircraft:wing:surface_control_mass_scaler,1.0,unitless aircraft:wing:sweep,25.0,deg aircraft:wing:taper_ratio,0.278,unitless aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless @@ -153,4 +153,5 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless settings:equations_of_motion,height_energy +settings:aerodynamics_method,FLOPS settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv similarity index 93% rename from aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv rename to aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv index 64f8adbfae..4a914f2cb2 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_FwGm.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv @@ -2,19 +2,22 @@ aircraft:controls:cockpit_control_mass_scaler,1,unitless aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,6,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,29,inch aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless -aircraft:design:drag_increment,0.00175,unitless +aircraft:design:drag_coeff_increment,0.00175,unitless aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserve_fuel_additional,3000.,lbm aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm -aircraft:design:supercritical_drag_shift,0.033,unitless +aircraft:design:drag_divergence_shift,0.033,unitless aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_23k_1.deck,unitless -aircraft:engine:enable_sizing,False,unitless +aircraft:engine:data_file,models/engines/turbofan_23k_1.csv,unitless +aircraft:engine:global_throttle, True, unitless +aircraft:engine:scale_performance,False,unitless aircraft:engine:mass_specific,0.21366,lbm/lbf aircraft:engine:fuel_flow_scaler_constant_term,0.,unitless aircraft:engine:fuel_flow_scaler_linear_term,0.,unitless @@ -54,14 +57,11 @@ aircraft:fuselage:form_factor,1.25,unitless aircraft:fuselage:mass_coefficient,128,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_seats_abreast,6,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 -aircraft:horizontal_tail:area,355.0,ft**2 aircraft:horizontal_tail:aspect_ratio,6.0,unitless aircraft:horizontal_tail:form_factor,1.25,unitless aircraft:horizontal_tail:mass_coefficient,0.232,unitless @@ -89,7 +89,6 @@ aircraft:strut:dimensional_location_specified,False,unitless aircraft:strut:fuselage_interference_factor,0,unitless aircraft:strut:mass_coefficient,0,unitless aircraft:strut:thickness_to_chord,0,unitless -aircraft:vertical_tail:area,284.0,ft**2 aircraft:vertical_tail:aspect_ratio,1.75,unitless aircraft:vertical_tail:form_factor,1.25,unitless aircraft:vertical_tail:mass_coefficient,0.289,unitless @@ -118,20 +117,20 @@ aircraft:wing:has_strut,False,unitless aircraft:wing:height,8,ft aircraft:wing:high_lift_mass_coefficient,1.9,unitless aircraft:wing:incidence,1.5,deg -aircraft:wing:loading,128,lbf/ft**2 +aircraft:design:wing_loading,128,lbf/ft**2 aircraft:wing:mass_coefficient,102.5,unitless aircraft:wing:max_lift_ref,1.15,unitless aircraft:wing:max_slat_deflection_landing,10,deg aircraft:wing:max_slat_deflection_takeoff,10,deg aircraft:wing:max_thickness_location,0.4,unitless aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:mounting_type,0,unitless +aircraft:wing:vertical_mount_location,0,unitless aircraft:wing:num_flap_segments,2,unitless aircraft:wing:optimum_flap_deflection,55,deg aircraft:wing:optimum_slat_deflection,20,deg aircraft:wing:slat_chord_ratio,0.15,unitless aircraft:wing:slat_lift_increment_optimum,0.93,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.95,unitless +aircraft:wing:surface_control_mass_coefficient,0.95,unitless aircraft:wing:sweep,25.0,deg aircraft:wing:taper_ratio,0.278,unitless aircraft:wing:thickness_to_chord_root,0.15,unitless @@ -161,6 +160,7 @@ aircraft:avionics:mass_scaler,1.2,unitless aircraft:canard:area,0.0,ft**2 aircraft:canard:aspect_ratio,0.0,unitless aircraft:canard:thickness_to_chord,0.0,unitless +aircraft:crew_and_payload:baggage_mass_per_passenger,44,lbm aircraft:crew_and_payload:cargo_container_mass_scaler,1.0,unitless aircraft:crew_and_payload:design:num_business_class,0,unitless aircraft:crew_and_payload:design:num_first_class,11,unitless @@ -177,12 +177,11 @@ aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless aircraft:crew_and_payload:wing_cargo,0.0,lbm aircraft:design:base_area,0.0,ft**2 aircraft:design:empty_mass_margin_scaler,0.0,unitless -aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless aircraft:design:touchdown_mass,152800.0,lbm aircraft:design:subsonic_drag_coeff_factor,1.0,unitless aircraft:design:supersonic_drag_coeff_factor,1.0,unitless aircraft:design:use_alt_mass,False,unitless -aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless +aircraft:design:type,transport,unitless aircraft:electrical:mass_scaler,1.25,unitless aircraft:fins:area,0.0,ft**2 aircraft:fins:mass_scaler,1.0,unitless @@ -190,7 +189,6 @@ aircraft:fins:mass,0.0,lbm aircraft:fins:num_fins,0,unitless aircraft:fins:taper_ratio,10.0,unitless aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless aircraft:fuel:fuselage_fuel_capacity,0.0,lbm aircraft:fuel:num_tanks,7,unitless aircraft:fuel:total_capacity,45694.0,lbm @@ -207,7 +205,6 @@ aircraft:horizontal_tail:mass_scaler,1.2,unitless aircraft:hydraulics:mass_scaler,1.0,unitless aircraft:hydraulics:system_pressure,3000.0,psi aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless aircraft:landing_gear:main_gear_oleo_length,102.0,inch aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless @@ -220,11 +217,12 @@ aircraft:vertical_tail:mass_scaler,1.0,unitless aircraft:vertical_tail:num_tails,1,unitless aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless aircraft:wing:airfoil_technology,1.92669766647637,unitless -aircraft:wing:bending_mass_scaler,1.0,unitless +aircraft:wing:bending_material_mass_scaler,1.0,unitless aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless aircraft:wing:composite_fraction,0.2,unitless aircraft:wing:control_surface_area,137,ft**2 aircraft:wing:control_surface_area_ratio,0.1,unitless +aircraft:wing:detailed_wing,True,unitless aircraft:wing:glove_and_bat,134.0,ft**2 aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless aircraft:wing:load_distribution_control,2.0,unitless @@ -237,7 +235,7 @@ aircraft:wing:num_integration_stations,50,unitless aircraft:wing:shear_control_mass_scaler,1.0,unitless aircraft:wing:span_efficiency_reduction,False,unitless aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless +aircraft:wing:surface_control_mass_scaler,1.0,unitless aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless aircraft:wing:thickness_to_chord,0.13,unitless aircraft:wing:ultimate_load_factor,3.75,unitless @@ -252,6 +250,7 @@ mission:takeoff:lift_over_drag,17.354,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless aircraft:fuel:burn_per_passenger_mile,0.1 settings:equations_of_motion,2DOF +settings:aerodynamics_method,GASP settings:mass_method,FLOPS # Initialization Guesses diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv similarity index 72% rename from aviary/models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv rename to aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv index 50a63d10d7..e5ec0f6ab7 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv @@ -6,7 +6,11 @@ aircraft:controls:cockpit_control_mass_scaler,1,unitless aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless -aircraft:crew_and_payload:cargo_mass,10040,lbm +aircraft:crew_and_payload:cargo_mass,0,lbm +aircraft:crew_and_payload:design:cargo_mass,0,lbm +aircraft:crew_and_payload:design:max_cargo_mass,10040,lbm +aircraft:crew_and_payload:design:num_seats_abreast_tourist,6,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,29,inch aircraft:crew_and_payload:catering_items_mass_per_passenger,7.6,lbm aircraft:crew_and_payload:design:num_passengers,180,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm @@ -14,17 +18,20 @@ aircraft:crew_and_payload:passenger_service_mass_per_passenger,5,lbm aircraft:crew_and_payload:water_mass_per_occupant,3,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless -aircraft:design:drag_increment,0.00175,unitless -aircraft:crew_and_payload:water_mass_per_occupant,3,lbm +aircraft:design:drag_coeff_increment,0.00175,unitless aircraft:design:emergency_equipment_mass,50,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserve_fuel_additional,4998,lbm aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm -aircraft:design:supercritical_drag_shift,0.033,unitless +aircraft:design:drag_divergence_shift,0.033,unitless +aircraft:design:type,transport,unitless +aircraft:electrical:system_mass_per_passenger,16.0,lbm aircraft:engine:additional_mass_fraction,0.135,unitless -aircraft:engine:data_file,models/engines/turbofan_23k_1_lbm_s.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_28k.csv,unitless +aircraft:engine:generate_flight_idle,True,unitless +aircraft:engine:global_throttle, True, unitless aircraft:engine:mass_scaler,1,unitless aircraft:engine:mass_specific,0.21366,lbm/lbf aircraft:engine:mass_scaler,1,unitless @@ -51,14 +58,11 @@ aircraft:fuselage:form_factor,1.25,unitless aircraft:fuselage:mass_coefficient,128,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_seats_abreast,6,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 -aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless aircraft:horizontal_tail:form_factor,1.25,unitless aircraft:horizontal_tail:mass_coefficient,0.232,unitless @@ -76,7 +80,7 @@ aircraft:landing_gear:main_gear_location,0.15,unitless aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless aircraft:landing_gear:mass_coefficient,0.04,unitless aircraft:landing_gear:tail_hook_mass_scaler,1,unitless -aircraft:landing_gear:total_mass_scaler,1, +aircraft:landing_gear:total_mass_scaler,1,unitless aircraft:nacelle:clearance_ratio,0.2,unitless aircraft:nacelle:core_diameter_ratio,1.25,unitless aircraft:nacelle:fineness,2,unitless @@ -89,7 +93,6 @@ aircraft:strut:dimensional_location_specified,False,unitless aircraft:strut:fuselage_interference_factor,0,unitless aircraft:strut:mass_coefficient,0,unitless aircraft:strut:thickness_to_chord,0,unitless -aircraft:vertical_tail:area,0,ft**2 aircraft:vertical_tail:aspect_ratio,1.67,unitless aircraft:vertical_tail:form_factor,1.25,unitless aircraft:vertical_tail:mass_coefficient,0.289,unitless @@ -118,108 +121,46 @@ aircraft:wing:has_strut,False,unitless aircraft:wing:height,8,ft aircraft:wing:high_lift_mass_coefficient,1.9,unitless aircraft:wing:incidence,1.5,deg -aircraft:wing:loading,128,lbf/ft**2 +aircraft:design:wing_loading,128,lbf/ft**2 aircraft:wing:mass_coefficient,102.5,unitless aircraft:wing:max_lift_ref,1.15,unitless aircraft:wing:max_slat_deflection_landing,10,deg aircraft:wing:max_slat_deflection_takeoff,10,deg aircraft:wing:max_thickness_location,0.4,unitless aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:mounting_type,0,unitless +aircraft:wing:vertical_mount_location,0,unitless aircraft:wing:num_flap_segments,2,unitless aircraft:wing:optimum_flap_deflection,55,deg aircraft:wing:optimum_slat_deflection,20,deg aircraft:wing:slat_chord_ratio,0.15,unitless aircraft:wing:slat_lift_increment_optimum,0.93,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.95,unitless +aircraft:wing:slat_span_ratio,0.9,unitless +aircraft:wing:surface_control_mass_coefficient,0.95,unitless aircraft:wing:sweep,25,deg aircraft:wing:taper_ratio,0.33,unitless aircraft:wing:thickness_to_chord_root,0.15,unitless aircraft:wing:thickness_to_chord_tip,0.12,unitless aircraft:wing:zero_lift_angle,-1.2,deg -mission:design:cruise_altitude,37500,ft -mission:design:gross_mass,175400,lbm +mission:constraints:max_mach,0.785,unitless +mission:design:cruise_altitude,37500,ft # double check against phase_info +mission:design:gross_mass,175400.0,lbm +mission:design:lift_coefficient_max_flaps_up,1.2596,unitless mission:design:mach,0.8,unitless -mission:design:range,3675,NM +mission:design:range,3500,NM +mission:design:thrust_takeoff_per_eng,28928.1,lbf mission:landing:airport_altitude,0,ft -mission:landing:braking_delay,1,s -mission:landing:glide_to_stall_ratio,1.3,unitless -mission:landing:maximum_flare_load_factor,1.15,unitless -mission:landing:maximum_sink_rate,900,ft/min -mission:landing:obstacle_height,50,ft -mission:landing:touchdown_sink_rate,5,ft/s -mission:summary:fuel_flow_scaler,1,unitless -mission:takeoff:decision_speed_increment,10,kn -mission:takeoff:rotation_speed_increment,5,kn -mission:taxi:duration,0.1677,h -settings:equations_of_motion,2DOF -settings:mass_method,GASP - -# Initialization Guesses -actual_takeoff_mass,0 -climb_range,0 -cruise_mass_final,0 -flight_duration,0 -fuel_burn_per_passenger_mile,0 -reserves,0 -rotation_mass,0 -time_to_climb,0 - -INGASP.ALR,1.11 -INGASP.BENGOB,0.05 -INGASP.CINP,0.11 -INGASP.CK10,1 -INGASP.CK11,1 -INGASP.CK18,1 -INGASP.CK7,1 -INGASP.CK8,1 -INGASP.CK9,1 -INGASP.CLIAB,1984 -INGASP.CMF,15 -INGASP.CMV,0.15 -INGASP.CRWOH,15 -INGASP.DCDSE,-1 -INGASP.DYR,12 -INGASP.EMCRU,0.8 -INGASP.FCSF,2.5 -INGASP.FPYLND,1 -INGASP.HBTP,0.333 -INGASP.HIR,0.015 -INGASP.HNCRU,37500 -INGASP.HPORT,0 -INGASP.HRI,2500 -INGASP.HSCREQ,20000 -INGASP.ICLM,3 -INGASP.ICRUS,0 -INGASP.IWLD,2 -INGASP.JENGSZ,4 -INGASP.KNAC,1 -INGASP.KODEAC,7 -INGASP.KODECL,7 -INGASP.KODETO,5 -INGASP.KODETR,6 -INGASP.MX,0 -INGASP.NFAIL,0 -INGASP.OFALT,0 -INGASP.OFEM,0.78 -INGASP.OHR,350 -INGASP.PRV,0.15 -INGASP.RELP,0 -INGASP.RELR,0.4524 -INGASP.RF,0.05,125,20000,25000 -INGASP.RI,0.8 -INGASP.ROCTOC,300 -INGASP.ROSCAB,9999 -INGASP.RWCRTX,0.985 -INGASP.SKPES,0.258 -INGASP.SM1D,0.625 -INGASP.SRPM,18000 -INGASP.TBO,3500 -INGASP.TR,1 -INGASP.VCLMB,270 -INGASP.WENG,6130 -INGASP.WLPCT,0.9423 -INGASP.WNAC,0 -INGASP.WPLX,0 -INGASP.WPYLON,0 -INGASP.XTORQ,8000 +mission:landing:drag_coefficient_flap_increment,0.0406,unitless +mission:landing:lift_coefficient_flap_increment,1.0293,unitless +mission:landing:lift_coefficient_max,2.8155,unitless +mission:summary:cruise_mach,0.785,unitless +mission:summary:fuel_flow_scaler,1.0,unitless +mission:summary:gross_mass,175400,lbm +mission:takeoff:airport_altitude,0,ft +mission:takeoff:drag_coefficient_flap_increment,0.0085,unitless +mission:takeoff:fuel_simple,577,lbm +mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless +mission:takeoff:lift_coefficient_max,3.0,unitless +mission:takeoff:lift_over_drag,17.354,unitless +settings:equations_of_motion,height_energy +settings:aerodynamics_method,GASP +settings:mass_method,GASP \ No newline at end of file diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv similarity index 90% rename from aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv rename to aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv index 2f3c32e0d8..94b22229dc 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwGm.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv @@ -6,7 +6,11 @@ aircraft:controls:cockpit_control_mass_scaler,1,unitless aircraft:controls:control_mass_increment,0,lbm aircraft:controls:stability_augmentation_system_mass,0,lbm aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless -aircraft:crew_and_payload:cargo_mass,10040,lbm +aircraft:crew_and_payload:cargo_mass,0,lbm +aircraft:crew_and_payload:design:cargo_mass,0,lbm +aircraft:crew_and_payload:design:max_cargo_mass,10040,lbm +aircraft:crew_and_payload:design:num_seats_abreast_tourist,6,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,29,inch aircraft:crew_and_payload:catering_items_mass_per_passenger,7.6,lbm aircraft:crew_and_payload:design:num_passengers,180,unitless aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm @@ -14,20 +18,24 @@ aircraft:crew_and_payload:passenger_service_mass_per_passenger,5,lbm aircraft:crew_and_payload:water_mass_per_occupant,3,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,16.5,unitless -aircraft:design:drag_increment,0.00175,unitless +aircraft:design:drag_coeff_increment,0.00175,unitless aircraft:design:emergency_equipment_mass,50,lbm aircraft:design:max_structural_speed,402.5,mi/h aircraft:design:part25_structural_category,3,unitless aircraft:design:reserve_fuel_additional,4998,lbm aircraft:design:static_margin,0.03,unitless aircraft:design:structural_mass_increment,0,lbm -aircraft:design:supercritical_drag_shift,0.033,unitless +aircraft:design:drag_divergence_shift,0.033,unitless +aircraft:design:type,transport,unitless +aircraft:electrical:system_mass_per_passenger,16.0,lbm aircraft:engine:additional_mass_fraction,0.135,unitless -aircraft:engine:data_file,models/engines/turbofan_23k_1.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_23k_1.csv,unitless +aircraft:engine:global_throttle, True, unitless aircraft:engine:mass_scaler,1,unitless aircraft:engine:mass_specific,0.21366,lbm/lbf aircraft:engine:mass_scaler,1,unitless aircraft:engine:num_engines,2,unitless +aircraft:engine:num_wing_engines,2,unitless aircraft:engine:pod_mass_scaler,1,unitless aircraft:engine:pylon_factor,1.25,unitless aircraft:engine:reference_diameter,5.8,ft @@ -50,14 +58,11 @@ aircraft:fuselage:form_factor,1.25,unitless aircraft:fuselage:mass_coefficient,128,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_seats_abreast,6,unitless aircraft:fuselage:pilot_compartment_length,9.5,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_pitch,29,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,3,unitless aircraft:fuselage:wetted_area,4000,ft**2 -aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.75,unitless aircraft:horizontal_tail:form_factor,1.25,unitless aircraft:horizontal_tail:mass_coefficient,0.232,unitless @@ -88,7 +93,6 @@ aircraft:strut:dimensional_location_specified,False,unitless aircraft:strut:fuselage_interference_factor,0,unitless aircraft:strut:mass_coefficient,0,unitless aircraft:strut:thickness_to_chord,0,unitless -aircraft:vertical_tail:area,0,ft**2 aircraft:vertical_tail:aspect_ratio,1.67,unitless aircraft:vertical_tail:form_factor,1.25,unitless aircraft:vertical_tail:mass_coefficient,0.289,unitless @@ -117,20 +121,21 @@ aircraft:wing:has_strut,False,unitless aircraft:wing:height,8,ft aircraft:wing:high_lift_mass_coefficient,1.9,unitless aircraft:wing:incidence,1.5,deg -aircraft:wing:loading,128,lbf/ft**2 +aircraft:design:wing_loading,128,lbf/ft**2 aircraft:wing:mass_coefficient,102.5,unitless aircraft:wing:max_lift_ref,1.15,unitless aircraft:wing:max_slat_deflection_landing,10,deg aircraft:wing:max_slat_deflection_takeoff,10,deg aircraft:wing:max_thickness_location,0.4,unitless aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:mounting_type,0,unitless +aircraft:wing:vertical_mount_location,0,unitless aircraft:wing:num_flap_segments,2,unitless aircraft:wing:optimum_flap_deflection,55,deg aircraft:wing:optimum_slat_deflection,20,deg aircraft:wing:slat_chord_ratio,0.15,unitless aircraft:wing:slat_lift_increment_optimum,0.93,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.95,unitless +aircraft:wing:slat_span_ratio,0.9,unitless +aircraft:wing:surface_control_mass_coefficient,0.95,unitless aircraft:wing:sweep,25,deg aircraft:wing:taper_ratio,0.33,unitless aircraft:wing:thickness_to_chord_root,0.15,unitless @@ -151,6 +156,7 @@ mission:summary:fuel_flow_scaler,1,unitless mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.1677,h +settings:aerodynamics_method,GASP settings:equations_of_motion,2DOF settings:mass_method,GASP diff --git a/aviary/models/test_aircraft/aircraft_for_bench_solved2dof.csv b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_solved2dof.csv similarity index 96% rename from aviary/models/test_aircraft/aircraft_for_bench_solved2dof.csv rename to aviary/models/aircraft/test_aircraft/aircraft_for_bench_solved2dof.csv index b6848994f3..1622f4260d 100644 --- a/aviary/models/test_aircraft/aircraft_for_bench_solved2dof.csv +++ b/aviary/models/aircraft/test_aircraft/aircraft_for_bench_solved2dof.csv @@ -32,7 +32,7 @@ aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless aircraft:electrical:mass_scaler,1.25,unitless aircraft:engine:additional_mass_fraction,0.,unitless aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_28k.csv,unitless aircraft:engine:flight_idle_thrust_fraction,0.0,unitless aircraft:engine:flight_idle_max_fraction,1.0,unitless aircraft:engine:flight_idle_min_fraction,0.08,unitless @@ -49,6 +49,7 @@ aircraft:engine:num_fuselage_engines,0,unitless aircraft:engine:num_wing_engines,2,unitless aircraft:engine:reference_mass,7400,lbm aircraft:engine:reference_sls_thrust,28928.1,lbf +aircraft:engine:scale_factor,1.0,unitless aircraft:engine:scale_mass,True,unitless aircraft:engine:scale_performance,True,unitless aircraft:engine:scaled_sls_thrust,28928.1,lbf @@ -62,7 +63,6 @@ aircraft:fins:mass,0.0,lbm aircraft:fins:num_fins,0,unitless aircraft:fins:taper_ratio,10.0,unitless aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless aircraft:fuel:fuel_system_mass_scaler,1.0,unitless aircraft:fuel:fuselage_fuel_capacity,0.0,lbm aircraft:fuel:num_tanks,7,unitless @@ -90,7 +90,6 @@ aircraft:horizontal_tail:wetted_area,592.65,ft**2 aircraft:hydraulics:mass_scaler,1.0,unitless aircraft:hydraulics:system_pressure,3000.0,psi aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless aircraft:landing_gear:main_gear_oleo_length,102.0,inch aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless @@ -114,11 +113,12 @@ aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless aircraft:wing:airfoil_technology,1.92669766647637,unitless aircraft:wing:area,1370.0,ft**2 aircraft:wing:aspect_ratio,11.22091,unitless -aircraft:wing:bending_mass_scaler,1.0,unitless +aircraft:wing:bending_material_mass_scaler,1.0,unitless aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless aircraft:wing:composite_fraction,0.2,unitless aircraft:wing:control_surface_area,137,ft**2 aircraft:wing:control_surface_area_ratio,0.1,unitless +aircraft:wing:detailed_wing,True,unitless aircraft:wing:glove_and_bat,134.0,ft**2 aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless aircraft:wing:load_distribution_control,2.0,unitless @@ -132,7 +132,7 @@ aircraft:wing:shear_control_mass_scaler,1.0,unitless aircraft:wing:span_efficiency_reduction,False,unitless aircraft:wing:span,117.83,ft aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless +aircraft:wing:surface_control_mass_scaler,1.0,unitless aircraft:wing:sweep,25.0,deg aircraft:wing:taper_ratio,0.278,unitless aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless @@ -153,4 +153,5 @@ mission:takeoff:fuel_simple,577,lbm mission:takeoff:lift_coefficient_max,3.0,unitless mission:takeoff:lift_over_drag,17.354,unitless settings:equations_of_motion,solved_2DOF +settings:aerodynamics_method,FLOPS settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv b/aviary/models/aircraft/test_aircraft/configuration_test_GASP.csv similarity index 92% rename from aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv rename to aviary/models/aircraft/test_aircraft/configuration_test_GASP.csv index 71e5cea397..04879cd8e8 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.csv +++ b/aviary/models/aircraft/test_aircraft/configuration_test_GASP.csv @@ -10,12 +10,14 @@ aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless aircraft:crew_and_payload:cargo_mass,15970,lbm aircraft:crew_and_payload:catering_items_mass_per_passenger,10,lbm aircraft:crew_and_payload:design:num_passengers,154,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,6,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,44.2,inch aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm aircraft:crew_and_payload:passenger_service_mass_per_passenger,5,lbm aircraft:crew_and_payload:water_mass_per_occupant,3,lbm aircraft:design:cg_delta,0.25,unitless aircraft:design:cockpit_control_mass_coefficient,30,unitless -aircraft:design:drag_increment,0.0014,unitless +aircraft:design:drag_coeff_increment,0.0014,unitless aircraft:design:emergency_equipment_mass,0,lbm aircraft:design:max_structural_speed,440,mi/h aircraft:design:part25_structural_category,3,unitless @@ -23,9 +25,11 @@ aircraft:design:reserve_fuel_additional,0,lbm aircraft:design:reserve_fuel_fraction,0.15,unitless aircraft:design:static_margin,0.05,unitless aircraft:design:structural_mass_increment,0,lbm -aircraft:design:supercritical_drag_shift,0.033,unitless +aircraft:design:drag_divergence_shift,0.033,unitless +aircraft:electrical:system_mass_per_passenger,16.0,lbm aircraft:engine:additional_mass_fraction,0.165,unitless -aircraft:engine:data_file,models/engines/turbofan_23k_1.deck,unitless +aircraft:engine:data_file,models/engines/turbofan_23k_1.csv,unitless +aircraft:engine:global_throttle,True aircraft:engine:mass_scaler,1,unitless aircraft:engine:mass_specific,0.21366,lbm/lbf aircraft:engine:num_engines,2,unitless @@ -33,6 +37,7 @@ aircraft:engine:pod_mass_scaler,1,unitless aircraft:engine:pylon_factor,1.25,unitless aircraft:engine:reference_diameter,6.15,ft aircraft:engine:reference_sls_thrust,28690,lbf +aircraft:engine:scale_factor,0.7376089229696758,unitless aircraft:engine:scaled_sls_thrust,21162,lbf aircraft:engine:type,7,unitless aircraft:engine:wing_locations,0.2143,unitless @@ -50,14 +55,11 @@ aircraft:fuselage:form_factor,1.146,unitless aircraft:fuselage:mass_coefficient,102.82,unitless aircraft:fuselage:nose_fineness,1,unitless aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_seats_abreast,6,unitless aircraft:fuselage:pilot_compartment_length,6.85,ft aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_pitch,44.2,inch aircraft:fuselage:seat_width,20.2,inch aircraft:fuselage:tail_fineness,1.18,unitless aircraft:fuselage:wetted_area_scaler,1,unitless -aircraft:horizontal_tail:area,0,ft**2 aircraft:horizontal_tail:aspect_ratio,4.025,unitless aircraft:horizontal_tail:form_factor,1.7,unitless aircraft:horizontal_tail:mass_coefficient,0.2076,unitless @@ -87,7 +89,6 @@ aircraft:strut:dimensional_location_specified,True,unitless aircraft:strut:fuselage_interference_factor,1.125,unitless aircraft:strut:mass_coefficient,0.238,unitless aircraft:strut:thickness_to_chord,0.1,unitless -aircraft:vertical_tail:area,0,ft**2 aircraft:vertical_tail:aspect_ratio,0.825,unitless aircraft:vertical_tail:form_factor,2,unitless aircraft:vertical_tail:mass_coefficient,0.2587,unitless @@ -115,21 +116,21 @@ aircraft:wing:has_strut,True,unitless aircraft:wing:height,15.2,ft aircraft:wing:high_lift_mass_coefficient,1.9,unitless aircraft:wing:incidence,1.5,deg -aircraft:wing:loading,93.1,lbf/ft**2 +aircraft:design:wing_loading,93.1,lbf/ft**2 aircraft:wing:mass_coefficient,106.28,unitless aircraft:wing:max_lift_ref,1.15,unitless aircraft:wing:max_slat_deflection_landing,10,deg aircraft:wing:max_slat_deflection_takeoff,10,deg aircraft:wing:max_thickness_location,0.35,unitless aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:mounting_type,1,unitless +aircraft:wing:vertical_mount_location,1,unitless aircraft:wing:num_flap_segments,2,unitless aircraft:wing:optimum_flap_deflection,55,deg aircraft:wing:optimum_slat_deflection,20,deg aircraft:wing:slat_chord_ratio,0.1,unitless aircraft:wing:slat_lift_increment_optimum,0.93,unitless aircraft:wing:slat_span_ratio,0.9,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.5936,unitless +aircraft:wing:surface_control_mass_coefficient,0.5936,unitless aircraft:wing:sweep,22.47,deg aircraft:wing:taper_ratio,0.346,unitless aircraft:wing:thickness_to_chord_root,0.11,unitless @@ -152,6 +153,7 @@ mission:takeoff:decision_speed_increment,10,kn mission:takeoff:rotation_speed_increment,5,kn mission:taxi:duration,0.1677,h settings:equations_of_motion,2DOF +settings:aerodynamics_method,GASP settings:mass_method,GASP # Initialization Guesses @@ -163,7 +165,7 @@ fuel_burn_per_passenger_mile,0 reserves,0 rotation_mass,0 time_to_climb,0 - + # Unconverted Values INGASP.ALR,1.11 INGASP.BENGOB,0.05 @@ -223,4 +225,4 @@ INGASP.WLPCT,0.9423 INGASP.WNAC,1240 INGASP.WPLX,0 INGASP.WPYLON,0 -INGASP.XTORQ,8000 +INGASP.XTORQ,8000 \ No newline at end of file diff --git a/aviary/models/aircraft/test_aircraft/turbofan_28k_with_electric.csv b/aviary/models/aircraft/test_aircraft/turbofan_28k_with_electric.csv new file mode 100644 index 0000000000..c095de1704 --- /dev/null +++ b/aviary/models/aircraft/test_aircraft/turbofan_28k_with_electric.csv @@ -0,0 +1,1116 @@ +# created 04/22/25 +# custom engine deck derived from turbofan_28k.csv, modified to have arbitrary electric power consumption +# NOTE: this engine is for example/testing purposes only, and does not represent a realistic hybrid-electric turbofan + +Mach_Number, Altitude (ft), Throttle, Gross_Thrust (lbf), Ram_Drag (lbf), Fuel_Flow (lb/h), NOx_Rate (lb/h), Electric_Power (kW) + 0.0, 0.0, 21.0, 1446.4, 0.0, 842.2, 4.7876, 14.464 + 0.0, 0.0, 22.0, 2314.3, 0.0, 976.0, 5.1926, 23.143 + 0.0, 0.0, 24.0, 4049.9, 0.0, 1281.0, 6.6532, 40.499 + 0.0, 0.0, 26.0, 5785.6, 0.0, 1659.9, 8.2234, 57.856 + 0.0, 0.0, 30.0, 9642.7, 0.0, 2621.6, 12.095, 96.427 + 0.0, 0.0, 34.0, 13499.8, 0.0, 3673.3, 15.032, 134.998 + 0.0, 0.0, 38.0, 17356.9, 0.0, 4795.2, 17.588, 173.569 + 0.0, 0.0, 42.0, 21214.0, 0.0, 5979.1, 19.855, 212.14 + 0.0, 0.0, 46.0, 25071.1, 0.0, 7258.1, 33.398, 250.711 + 0.0, 0.0, 48.0, 26999.7, 0.0, 7932.6, 49.218, 269.997 + 0.0, 0.0, 50.0, 28928.1, 0.0, 8662.3, 61.989, 289.281 + 0.0, 2000.0, 21.0, 1446.4, 0.0, 781.8, 5.2521, 14.464 + 0.0, 2000.0, 22.0, 2314.2, 0.0, 914.2, 5.1431, 23.142 + 0.0, 2000.0, 24.0, 4049.9, 0.0, 1220.2, 6.7284, 40.499 + 0.0, 2000.0, 26.0, 5785.6, 0.0, 1608.2, 8.4472, 57.856 + 0.0, 2000.0, 30.0, 9642.7, 0.0, 2572.5, 12.52, 96.427 + 0.0, 2000.0, 34.0, 13499.7, 0.0, 3624.6, 15.601, 134.997 + 0.0, 2000.0, 38.0, 17356.8, 0.0, 4748.2, 18.241, 173.568 + 0.0, 2000.0, 42.0, 21213.8, 0.0, 5953.1, 20.617, 212.138 + 0.0, 2000.0, 46.0, 25070.8, 0.0, 7274.3, 46.519, 250.708 + 0.0, 2000.0, 48.0, 26999.7, 0.0, 8005.4, 61.6, 269.997 + 0.0, 2000.0, 50.0, 28928.0, 0.0, 8769.0, 72.51, 289.28 + 0.0, 5000.0, 21.0, 1338.1, 0.0, 706.8, 6.8008, 13.381 + 0.0, 5000.0, 22.0, 2140.9, 0.0, 828.3, 5.03, 21.409 + 0.0, 5000.0, 24.0, 3746.7, 0.0, 1111.0, 6.2319, 37.467 + 0.0, 5000.0, 26.0, 5352.3, 0.0, 1469.9, 7.9885, 53.523 + 0.0, 5000.0, 30.0, 8920.6, 0.0, 2355.4, 12.028, 89.206 + 0.0, 5000.0, 34.0, 12488.9, 0.0, 3323.4, 15.131, 124.889 + 0.0, 5000.0, 38.0, 16057.1, 0.0, 4353.1, 17.774, 160.571 + 0.0, 5000.0, 42.0, 19625.3, 0.0, 5473.5, 20.181, 196.253 + 0.0, 5000.0, 46.0, 23193.5, 0.0, 6708.4, 39.131, 231.935 + 0.0, 5000.0, 48.0, 24977.9, 0.0, 7391.9, 57.314, 249.779 + 0.0, 5000.0, 50.0, 26761.8, 0.0, 8104.6, 69.258, 267.618 + 0.1, 0.0, 21.0, 2503.9, 1057.5, 905.8, 4.7726, 25.039 + 0.1, 0.0, 22.0, 3575.1, 1260.9, 1088.1, 5.7209, 35.751 + 0.1, 0.0, 24.0, 5626.3, 1576.4, 1525.4, 7.6905, 56.263 + 0.1, 0.0, 26.0, 7615.0, 1829.5, 2001.1, 9.4545, 76.15 + 0.1, 0.0, 30.0, 11922.9, 2280.3, 3129.8, 13.596, 119.229 + 0.1, 0.0, 34.0, 16145.2, 2645.4, 4326.3, 16.588, 161.452 + 0.1, 0.0, 38.0, 20316.5, 2959.7, 5587.6, 19.158, 203.165 + 0.1, 0.0, 42.0, 24452.2, 3238.4, 6932.0, 26.87, 244.522 + 0.1, 0.0, 46.0, 28560.1, 3489.2, 8389.7, 57.658, 285.601 + 0.1, 0.0, 48.0, 30603.9, 3604.5, 9194.3, 69.248, 306.039 + 0.1, 0.0, 50.0, 32642.3, 3714.3, 10032.8, 77.44, 326.423 + 0.1, 2000.0, 21.0, 2330.3, 984.5, 824.4, 4.924, 23.303 + 0.1, 2000.0, 22.0, 3327.1, 1173.8, 991.2, 5.5336, 33.271 + 0.1, 2000.0, 24.0, 5235.7, 1467.4, 1391.5, 7.5234, 52.357 + 0.1, 2000.0, 26.0, 7086.3, 1702.9, 1826.8, 9.2983, 70.863 + 0.1, 2000.0, 30.0, 11094.9, 2122.6, 2859.5, 13.428, 110.949 + 0.1, 2000.0, 34.0, 15023.5, 2462.3, 3960.7, 16.447, 150.235 + 0.1, 2000.0, 38.0, 18904.9, 2754.8, 5117.1, 19.021, 189.049 + 0.1, 2000.0, 42.0, 22752.9, 3013.8, 6361.1, 24.784, 227.529 + 0.1, 2000.0, 46.0, 26574.2, 3246.4, 7721.3, 56.641, 265.742 + 0.1, 2000.0, 48.0, 28476.4, 3353.7, 8462.9, 68.509, 284.764 + 0.1, 2000.0, 50.0, 30372.6, 3455.8, 9235.9, 77.04, 303.726 + 0.1, 5000.0, 21.0, 2084.6, 880.6, 738.0, 6.5816, 20.846 + 0.1, 5000.0, 22.0, 2976.4, 1050.0, 884.8, 4.9156, 29.764 + 0.1, 5000.0, 24.0, 4684.1, 1312.8, 1237.6, 6.8861, 46.841 + 0.1, 5000.0, 26.0, 6339.8, 1523.6, 1621.7, 8.6447, 63.398 + 0.1, 5000.0, 30.0, 9926.1, 1899.3, 2532.7, 12.65, 99.261 + 0.1, 5000.0, 34.0, 13440.9, 2203.3, 3503.2, 15.631, 134.409 + 0.1, 5000.0, 38.0, 16913.5, 2465.1, 4524.4, 18.179, 169.135 + 0.1, 5000.0, 42.0, 20356.6, 2696.9, 5621.1, 20.48, 203.566 + 0.1, 5000.0, 46.0, 23775.6, 2905.2, 6820.1, 42.076, 237.756 + 0.1, 5000.0, 48.0, 25476.8, 3001.2, 7474.2, 58.535, 254.768 + 0.1, 5000.0, 50.0, 27173.2, 3092.6, 8156.2, 69.812, 271.732 + 0.1, 10000.0, 21.0, 1721.9, 727.2, 612.6, 9.402, 17.219 + 0.1, 10000.0, 22.0, 2458.8, 867.2, 730.7, 7.2271, 24.588 + 0.1, 10000.0, 24.0, 3869.8, 1084.5, 1014.8, 5.7309, 38.698 + 0.1, 10000.0, 26.0, 5237.7, 1258.8, 1324.4, 7.4445, 52.377 + 0.1, 10000.0, 30.0, 8200.9, 1569.4, 2059.1, 10.942, 82.009 + 0.1, 10000.0, 34.0, 11104.9, 1820.8, 2841.8, 14.099, 111.049 + 0.1, 10000.0, 38.0, 13974.0, 2037.3, 3665.3, 16.569, 139.74 + 0.1, 10000.0, 42.0, 16818.6, 2229.1, 4548.6, 18.8, 168.186 + 0.1, 10000.0, 46.0, 19643.6, 2401.3, 5515.6, 21.945, 196.436 + 0.1, 10000.0, 48.0, 21049.0, 2480.6, 6042.3, 33.273, 210.49 + 0.1, 10000.0, 50.0, 22450.7, 2556.3, 6592.6, 50.98, 224.507 + 0.2, 0.0, 21.0, 3984.0, 2660.5, 927.8, 4.88, 39.84 + 0.2, 0.0, 22.0, 5132.8, 3015.2, 1158.3, 6.0773, 51.328 + 0.2, 0.0, 24.0, 7290.5, 3584.8, 1655.7, 8.2264, 72.905 + 0.2, 0.0, 26.0, 9344.4, 4050.6, 2168.2, 10.048, 93.444 + 0.2, 0.0, 30.0, 13714.4, 4891.5, 3335.6, 14.183, 137.144 + 0.2, 0.0, 34.0, 17928.1, 5575.9, 4564.4, 17.136, 179.281 + 0.2, 0.0, 38.0, 22048.5, 6167.1, 5839.6, 19.652, 220.485 + 0.2, 0.0, 42.0, 26104.0, 6693.4, 7176.2, 31.254, 261.04 + 0.2, 0.0, 46.0, 30105.5, 7165.7, 8625.1, 60.801, 301.055 + 0.2, 0.0, 48.0, 32088.4, 7383.6, 9408.5, 71.454, 320.884 + 0.2, 0.0, 50.0, 34059.1, 7590.1, 10231.7, 78.754, 340.591 + 0.2, 2000.0, 21.0, 3705.8, 2475.9, 844.5, 4.8026, 37.058 + 0.2, 2000.0, 22.0, 4773.5, 2805.8, 1055.1, 5.8928, 47.735 + 0.2, 2000.0, 24.0, 6779.2, 3335.6, 1509.9, 8.0591, 67.792 + 0.2, 2000.0, 26.0, 8688.2, 3768.8, 1978.1, 9.8731, 86.882 + 0.2, 2000.0, 30.0, 12750.0, 4551.0, 3045.6, 14.013, 127.5 + 0.2, 2000.0, 34.0, 16665.9, 5187.3, 4175.2, 16.989, 166.659 + 0.2, 2000.0, 38.0, 20495.5, 5737.3, 5341.9, 19.504, 204.955 + 0.2, 2000.0, 42.0, 24264.1, 6226.1, 6575.1, 28.173, 242.641 + 0.2, 2000.0, 46.0, 27981.8, 6663.9, 7924.2, 59.521, 279.818 + 0.2, 2000.0, 48.0, 29823.9, 6866.3, 8646.0, 70.578, 298.239 + 0.2, 2000.0, 50.0, 31655.3, 7058.3, 9403.9, 78.279, 316.553 + 0.2, 5000.0, 21.0, 3315.0, 2214.7, 755.5, 6.435, 33.15 + 0.2, 5000.0, 22.0, 4270.4, 2510.0, 941.0, 5.268, 42.704 + 0.2, 5000.0, 24.0, 6064.9, 2984.3, 1342.0, 7.4149, 60.649 + 0.2, 5000.0, 26.0, 7773.0, 3372.1, 1755.4, 9.2124, 77.73 + 0.2, 5000.0, 30.0, 11407.0, 4072.2, 2696.9, 13.226, 114.07 + 0.2, 5000.0, 34.0, 14910.5, 4641.7, 3693.1, 16.168, 149.105 + 0.2, 5000.0, 38.0, 18336.7, 5134.0, 4722.6, 18.655, 183.367 + 0.2, 5000.0, 42.0, 21708.3, 5571.5, 5810.0, 20.901, 217.083 + 0.2, 5000.0, 46.0, 25034.4, 5963.4, 6999.7, 46.548, 250.344 + 0.2, 5000.0, 48.0, 26682.2, 6144.6, 7635.7, 60.797, 266.822 + 0.2, 5000.0, 50.0, 28321.1, 6316.5, 8304.7, 71.484, 283.211 + 0.2, 10000.0, 21.0, 2738.0, 1829.0, 626.4, 9.2804, 27.38 + 0.2, 10000.0, 22.0, 3527.6, 2073.3, 775.5, 6.4797, 35.276 + 0.2, 10000.0, 24.0, 5010.5, 2465.5, 1098.5, 6.2413, 50.105 + 0.2, 10000.0, 26.0, 6421.8, 2786.1, 1431.7, 7.9908, 64.218 + 0.2, 10000.0, 30.0, 9424.6, 3365.1, 2191.4, 11.756, 94.246 + 0.2, 10000.0, 34.0, 12319.4, 3836.1, 2994.6, 14.615, 123.194 + 0.2, 10000.0, 38.0, 15150.2, 4243.1, 3825.2, 17.028, 151.502 + 0.2, 10000.0, 42.0, 17936.1, 4604.8, 4701.2, 19.18, 179.361 + 0.2, 10000.0, 46.0, 20683.4, 4929.0, 5659.9, 23.631, 206.834 + 0.2, 10000.0, 48.0, 22045.5, 5078.8, 6173.0, 36.496, 220.455 + 0.2, 10000.0, 50.0, 23399.5, 5221.0, 6712.2, 53.492, 233.995 + 0.25, 0.0, 21.0, 4982.9, 3711.0, 967.7, 5.1347, 49.829 + 0.25, 0.0, 22.0, 6155.9, 4120.9, 1221.5, 6.4157, 61.559 + 0.25, 0.0, 24.0, 8353.0, 4791.8, 1741.2, 8.5818, 83.53 + 0.25, 0.0, 26.0, 10434.6, 5347.2, 2267.6, 10.748, 104.346 + 0.25, 0.0, 30.0, 14837.1, 6358.1, 3458.3, 14.538, 148.371 + 0.25, 0.0, 34.0, 19055.8, 7185.2, 4700.4, 17.453, 190.558 + 0.25, 0.0, 38.0, 23164.2, 7901.7, 5979.8, 19.93, 231.642 + 0.25, 0.0, 42.0, 27194.4, 8540.4, 7318.7, 34.279, 271.944 + 0.25, 0.0, 46.0, 31158.1, 9112.7, 8772.0, 62.953, 311.581 + 0.25, 0.0, 48.0, 33119.2, 9377.6, 9547.4, 72.817, 331.192 + 0.25, 0.0, 50.0, 35064.8, 9627.7, 10368.8, 79.61, 350.648 + 0.25, 2000.0, 21.0, 4635.4, 3453.6, 881.2, 4.9403, 46.354 + 0.25, 2000.0, 22.0, 5725.7, 3834.8, 1113.2, 6.2358, 57.257 + 0.25, 2000.0, 24.0, 7767.9, 4458.7, 1587.7, 8.4148, 77.679 + 0.25, 2000.0, 26.0, 9702.8, 4975.4, 2068.9, 10.313, 97.028 + 0.25, 2000.0, 30.0, 13794.8, 5915.8, 3157.8, 14.369, 137.948 + 0.25, 2000.0, 34.0, 17715.3, 6684.5, 4299.7, 17.308, 177.153 + 0.25, 2000.0, 38.0, 21533.5, 7351.2, 5470.6, 19.785, 215.335 + 0.25, 2000.0, 42.0, 25278.1, 7944.4, 6705.3, 30.749, 252.781 + 0.25, 2000.0, 46.0, 28960.8, 8474.8, 8057.1, 61.504, 289.608 + 0.25, 2000.0, 48.0, 30782.4, 8720.7, 8773.3, 71.978, 307.824 + 0.25, 2000.0, 50.0, 32590.3, 8953.2, 9529.4, 79.171, 325.903 + 0.25, 5000.0, 21.0, 4146.8, 3089.4, 787.7, 5.8398, 41.468 + 0.25, 5000.0, 22.0, 5122.4, 3430.7, 992.0, 5.6074, 51.224 + 0.25, 5000.0, 24.0, 6949.9, 3989.3, 1411.0, 7.7697, 69.499 + 0.25, 5000.0, 26.0, 8681.0, 4451.7, 1835.5, 9.5548, 86.81 + 0.25, 5000.0, 30.0, 12342.2, 5293.4, 2795.6, 13.576, 123.422 + 0.25, 5000.0, 34.0, 15850.1, 5981.6, 3803.0, 16.482, 158.501 + 0.25, 5000.0, 38.0, 19266.4, 6578.4, 4836.6, 18.932, 192.664 + 0.25, 5000.0, 42.0, 22617.1, 7109.4, 5925.2, 21.995, 226.171 + 0.25, 5000.0, 46.0, 25911.5, 7584.2, 7117.3, 49.402, 259.115 + 0.25, 5000.0, 48.0, 27541.0, 7804.3, 7748.5, 62.576, 275.41 + 0.25, 5000.0, 50.0, 29158.9, 8012.2, 8415.7, 72.732, 291.589 + 0.25, 10000.0, 21.0, 3424.9, 2551.5, 652.1, 8.6939, 34.249 + 0.25, 10000.0, 22.0, 4231.3, 2833.9, 816.4, 5.6904, 42.313 + 0.25, 10000.0, 24.0, 5741.3, 3295.8, 1153.9, 6.5846, 57.413 + 0.25, 10000.0, 26.0, 7171.8, 3678.2, 1496.8, 8.3269, 71.718 + 0.25, 10000.0, 30.0, 10196.9, 4374.2, 2270.9, 12.094, 101.969 + 0.25, 10000.0, 34.0, 13095.1, 4943.3, 3083.3, 14.918, 130.951 + 0.25, 10000.0, 38.0, 15917.5, 5436.7, 3916.9, 17.295, 159.175 + 0.25, 10000.0, 42.0, 18685.9, 5875.8, 4794.1, 19.414, 186.859 + 0.25, 10000.0, 46.0, 21407.5, 6268.5, 5754.5, 25.017, 214.075 + 0.25, 10000.0, 48.0, 22754.0, 6450.6, 6263.1, 38.869, 227.54 + 0.25, 10000.0, 50.0, 24090.7, 6622.7, 6801.4, 55.311, 240.907 + 0.3, 0.0, 21.0, 6173.4, 4945.6, 1022.8, 5.4835, 61.734 + 0.3, 0.0, 22.0, 7364.1, 5399.7, 1289.1, 6.7761, 73.641 + 0.3, 0.0, 24.0, 9594.3, 6156.5, 1828.9, 8.945, 95.943 + 0.3, 0.0, 26.0, 11702.0, 6790.9, 2370.2, 11.37, 117.02 + 0.3, 0.0, 30.0, 16141.2, 7956.0, 3586.7, 14.908, 161.412 + 0.3, 0.0, 34.0, 20374.2, 8914.9, 4845.9, 17.791, 203.742 + 0.3, 0.0, 38.0, 24482.0, 9748.6, 6136.4, 20.242, 244.82 + 0.3, 0.0, 42.0, 28498.9, 10491.9, 7487.2, 38.185, 284.989 + 0.3, 0.0, 46.0, 32440.2, 11158.6, 8946.6, 65.354, 324.402 + 0.3, 0.0, 48.0, 34385.6, 11467.0, 9722.6, 74.456, 343.856 + 0.3, 0.0, 50.0, 36314.3, 11758.7, 10541.1, 80.608, 363.143 + 0.3, 2000.0, 21.0, 5743.4, 4602.6, 931.5, 5.2941, 57.434 + 0.3, 2000.0, 22.0, 6850.3, 5024.9, 1175.0, 6.6001, 68.503 + 0.3, 2000.0, 24.0, 8923.2, 5728.8, 1668.1, 8.7823, 89.232 + 0.3, 2000.0, 26.0, 10882.3, 6318.8, 2161.9, 11.024, 108.823 + 0.3, 2000.0, 30.0, 15008.5, 7402.8, 3275.4, 14.742, 150.085 + 0.3, 2000.0, 34.0, 18942.1, 8294.0, 4433.1, 17.647, 189.421 + 0.3, 2000.0, 38.0, 22759.9, 9069.6, 5614.1, 20.098, 227.599 + 0.3, 2000.0, 42.0, 26492.4, 9759.9, 6860.5, 34.305, 264.924 + 0.3, 2000.0, 46.0, 30152.8, 10377.9, 8215.0, 63.856, 301.528 + 0.3, 2000.0, 48.0, 31959.4, 10663.8, 8934.3, 73.679, 319.594 + 0.3, 2000.0, 50.0, 33752.0, 10934.9, 9687.3, 80.217, 337.52 + 0.3, 5000.0, 21.0, 5137.9, 4117.3, 832.0, 5.0092, 51.379 + 0.3, 5000.0, 22.0, 6128.4, 4495.5, 1046.5, 5.9682, 61.284 + 0.3, 5000.0, 24.0, 7983.1, 5125.5, 1481.4, 8.1293, 79.831 + 0.3, 5000.0, 26.0, 9735.9, 5653.8, 1917.6, 9.9046, 97.359 + 0.3, 5000.0, 30.0, 13427.5, 6623.9, 2899.2, 13.942, 134.275 + 0.3, 5000.0, 34.0, 16946.8, 7421.7, 3920.4, 16.816, 169.468 + 0.3, 5000.0, 38.0, 20362.5, 8115.9, 4962.2, 19.238, 203.625 + 0.3, 5000.0, 42.0, 23701.7, 8733.8, 6061.4, 23.521, 237.017 + 0.3, 5000.0, 46.0, 26976.2, 9286.8, 7256.0, 52.53, 269.762 + 0.3, 5000.0, 48.0, 28592.9, 9543.0, 7890.1, 64.754, 285.929 + 0.3, 5000.0, 50.0, 30196.6, 9785.7, 8554.4, 74.212, 301.966 + 0.3, 10000.0, 21.0, 4243.8, 3400.8, 687.6, 7.8677, 42.438 + 0.3, 10000.0, 22.0, 5062.5, 3713.6, 860.4, 4.908, 50.625 + 0.3, 10000.0, 24.0, 6595.3, 4234.8, 1211.0, 6.9375, 65.953 + 0.3, 10000.0, 26.0, 8043.8, 4671.6, 1563.1, 8.6667, 80.438 + 0.3, 10000.0, 30.0, 11094.2, 5473.9, 2354.8, 12.45, 110.942 + 0.3, 10000.0, 34.0, 14002.0, 6133.6, 3177.8, 15.24, 140.02 + 0.3, 10000.0, 38.0, 16824.1, 6707.5, 4018.5, 17.59, 168.241 + 0.3, 10000.0, 42.0, 19583.3, 7218.6, 4904.6, 19.693, 195.833 + 0.3, 10000.0, 46.0, 22288.8, 7676.1, 5867.0, 26.947, 222.888 + 0.3, 10000.0, 48.0, 23624.2, 7887.9, 6378.4, 42.083, 236.242 + 0.3, 10000.0, 50.0, 24949.6, 8088.6, 6913.7, 57.381, 249.496 + 0.3, 15000.0, 21.0, 3479.6, 2788.1, 567.1, 10.753, 34.796 + 0.3, 15000.0, 22.0, 4151.5, 3045.2, 705.0, 7.7596, 41.515 + 0.3, 15000.0, 24.0, 5409.3, 3473.3, 985.3, 5.6485, 54.093 + 0.3, 15000.0, 26.0, 6597.7, 3831.9, 1267.2, 7.317, 65.977 + 0.3, 15000.0, 30.0, 9100.3, 4490.8, 1900.3, 10.236, 91.003 + 0.3, 15000.0, 34.0, 11486.0, 5032.6, 2558.6, 13.48, 114.86 + 0.3, 15000.0, 38.0, 13801.0, 5503.8, 3231.5, 15.733, 138.01 + 0.3, 15000.0, 42.0, 16064.5, 5923.6, 3939.7, 17.744, 160.645 + 0.3, 15000.0, 46.0, 18284.0, 6299.3, 4708.7, 19.683, 182.84 + 0.3, 15000.0, 48.0, 19379.7, 6473.2, 5117.8, 21.325, 193.797 + 0.3, 15000.0, 50.0, 20466.5, 6637.9, 5546.1, 30.41, 204.665 + 0.35, 0.0, 21.0, 7566.3, 6374.0, 1096.3, 5.9318, 75.663 + 0.35, 0.0, 22.0, 8770.7, 6863.1, 1379.4, 7.2407, 87.707 + 0.35, 0.0, 24.0, 11031.6, 7693.3, 1932.5, 9.3656, 110.316 + 0.35, 0.0, 26.0, 13168.6, 8399.6, 2472.9, 11.765, 131.686 + 0.35, 0.0, 30.0, 17653.6, 9705.4, 3720.3, 15.291, 176.536 + 0.35, 0.0, 34.0, 21914.4, 10786.9, 5002.2, 18.152, 219.144 + 0.35, 0.0, 38.0, 26037.3, 11730.5, 6310.8, 20.585, 260.373 + 0.35, 0.0, 42.0, 30057.1, 12571.0, 7691.3, 43.121, 300.571 + 0.35, 0.0, 46.0, 33993.9, 13328.4, 9155.7, 67.99, 339.939 + 0.35, 0.0, 48.0, 35932.2, 13677.3, 9939.7, 76.316, 359.322 + 0.35, 0.0, 50.0, 37853.7, 14009.0, 10755.8, 81.718, 378.537 + 0.35, 2000.0, 21.0, 7039.8, 5932.0, 999.1, 5.7509, 70.398 + 0.35, 2000.0, 22.0, 8159.4, 6386.9, 1257.8, 7.0693, 81.594 + 0.35, 2000.0, 24.0, 10260.8, 7159.0, 1763.3, 9.2076, 102.608 + 0.35, 2000.0, 26.0, 12247.3, 7816.1, 2255.9, 11.585, 122.473 + 0.35, 2000.0, 30.0, 16416.2, 9030.9, 3397.3, 15.126, 164.162 + 0.35, 2000.0, 34.0, 20375.6, 10036.0, 4575.8, 18.008, 203.756 + 0.35, 2000.0, 38.0, 24207.3, 10913.7, 5773.4, 20.441, 242.073 + 0.35, 2000.0, 42.0, 27941.9, 11694.1, 7047.4, 39.005, 279.419 + 0.35, 2000.0, 46.0, 31598.2, 12396.5, 8403.2, 66.444, 315.982 + 0.35, 2000.0, 48.0, 33398.3, 12719.4, 9133.8, 75.613, 333.983 + 0.35, 2000.0, 50.0, 35183.5, 13027.6, 9884.0, 81.388, 351.835 + 0.35, 5000.0, 21.0, 6297.7, 5306.8, 891.4, 5.1268, 62.977 + 0.35, 5000.0, 22.0, 7299.6, 5714.1, 1119.5, 6.4339, 72.996 + 0.35, 5000.0, 24.0, 9179.9, 6405.3, 1565.3, 8.5499, 91.799 + 0.35, 5000.0, 26.0, 10957.1, 6993.4, 2000.3, 10.262, 109.571 + 0.35, 5000.0, 30.0, 14686.9, 8080.8, 3006.9, 14.321, 146.869 + 0.35, 5000.0, 34.0, 18229.2, 8980.4, 4046.1, 17.171, 182.292 + 0.35, 5000.0, 38.0, 21657.4, 9766.2, 5102.9, 19.576, 216.574 + 0.35, 5000.0, 42.0, 24998.3, 10464.7, 6226.3, 25.926, 249.983 + 0.35, 5000.0, 46.0, 28269.4, 11093.1, 7421.8, 55.81, 282.694 + 0.35, 5000.0, 48.0, 29879.7, 11382.5, 8065.8, 67.275, 298.797 + 0.35, 5000.0, 50.0, 31477.1, 11658.5, 8727.8, 75.918, 314.771 + 0.35, 10000.0, 21.0, 5202.0, 4383.5, 735.2, 6.795, 52.02 + 0.35, 10000.0, 22.0, 6030.2, 4720.6, 919.0, 5.282, 60.302 + 0.35, 10000.0, 24.0, 7584.1, 5292.2, 1278.6, 7.346, 75.841 + 0.35, 10000.0, 26.0, 9052.7, 5778.6, 1629.9, 9.0072, 90.527 + 0.35, 10000.0, 30.0, 12134.6, 6677.8, 2441.6, 12.816, 121.346 + 0.35, 10000.0, 34.0, 15061.4, 7421.8, 3279.3, 15.582, 150.614 + 0.35, 10000.0, 38.0, 17893.8, 8071.6, 4132.1, 17.916, 178.938 + 0.35, 10000.0, 42.0, 20654.1, 8649.1, 5037.3, 20.024, 206.541 + 0.35, 10000.0, 46.0, 23357.0, 9169.2, 6000.8, 29.598, 233.57 + 0.35, 10000.0, 48.0, 24688.2, 9408.4, 6520.4, 45.942, 246.882 + 0.35, 10000.0, 50.0, 26007.2, 9636.6, 7053.3, 59.554, 260.072 + 0.35, 15000.0, 21.0, 4265.5, 3594.1, 604.8, 9.6899, 42.655 + 0.35, 15000.0, 22.0, 4945.3, 3871.2, 751.6, 6.6744, 49.453 + 0.35, 15000.0, 24.0, 6220.4, 4340.7, 1039.2, 6.0427, 62.204 + 0.35, 15000.0, 26.0, 7425.3, 4740.1, 1320.6, 7.6429, 74.253 + 0.35, 15000.0, 30.0, 9953.9, 5478.5, 1969.8, 10.871, 99.539 + 0.35, 15000.0, 34.0, 12355.2, 6089.6, 2639.9, 13.806, 123.552 + 0.35, 15000.0, 38.0, 14678.8, 6623.1, 3322.2, 16.041, 146.788 + 0.35, 15000.0, 42.0, 16943.3, 7097.5, 4045.6, 18.057, 169.433 + 0.35, 15000.0, 46.0, 19160.5, 7524.6, 4816.5, 19.961, 191.605 + 0.35, 15000.0, 48.0, 20251.7, 7720.9, 5231.4, 22.662, 202.517 + 0.35, 15000.0, 50.0, 21334.5, 7908.4, 5657.5, 33.192, 213.345 + 0.4, 2000.0, 21.0, 8528.1, 7446.9, 1080.6, 6.2764, 85.281 + 0.4, 2000.0, 22.0, 9658.0, 7928.2, 1353.5, 7.5936, 96.58 + 0.4, 2000.0, 24.0, 11784.7, 8757.4, 1878.4, 9.7055, 117.847 + 0.4, 2000.0, 26.0, 13797.7, 9473.0, 2382.4, 12.101, 137.977 + 0.4, 2000.0, 30.0, 18018.9, 10811.1, 3529.2, 15.538, 180.189 + 0.4, 2000.0, 34.0, 22012.9, 11922.0, 4732.9, 18.404, 220.129 + 0.4, 2000.0, 38.0, 25869.2, 12895.0, 5956.0, 20.83, 258.692 + 0.4, 2000.0, 42.0, 29617.1, 13759.9, 7260.5, 44.558, 296.171 + 0.4, 2000.0, 46.0, 33282.9, 14542.5, 8623.9, 69.274, 332.829 + 0.4, 2000.0, 48.0, 35081.9, 14900.1, 9368.5, 77.682, 350.819 + 0.4, 2000.0, 50.0, 36867.3, 15243.9, 10120.0, 82.629, 368.673 + 0.4, 5000.0, 21.0, 7629.4, 6662.3, 963.1, 5.6477, 76.294 + 0.4, 5000.0, 22.0, 8640.5, 7093.1, 1203.9, 6.9524, 86.405 + 0.4, 5000.0, 24.0, 10543.4, 7835.5, 1666.8, 9.0427, 105.434 + 0.4, 5000.0, 26.0, 12344.4, 8476.0, 2111.2, 11.188, 123.444 + 0.4, 5000.0, 30.0, 16121.1, 9673.7, 3123.3, 14.728, 161.211 + 0.4, 5000.0, 34.0, 19694.5, 10668.0, 4184.8, 17.56, 196.945 + 0.4, 5000.0, 38.0, 23144.4, 11539.2, 5263.3, 19.957, 231.444 + 0.4, 5000.0, 42.0, 26497.4, 12313.3, 6414.0, 29.514, 264.974 + 0.4, 5000.0, 46.0, 29777.0, 13014.0, 7616.7, 59.083, 297.77 + 0.4, 5000.0, 48.0, 31386.7, 13333.9, 8272.8, 70.033, 313.867 + 0.4, 5000.0, 50.0, 32983.8, 13641.9, 8936.1, 77.81, 329.838 + 0.4, 10000.0, 21.0, 6302.4, 5503.6, 792.8, 5.5515, 63.024 + 0.4, 10000.0, 22.0, 7138.3, 5860.2, 987.2, 5.7899, 71.383 + 0.4, 10000.0, 24.0, 8710.6, 6473.9, 1360.1, 7.8236, 87.106 + 0.4, 10000.0, 26.0, 10198.9, 7003.7, 1718.7, 9.4457, 101.989 + 0.4, 10000.0, 30.0, 13319.7, 7994.3, 2535.4, 13.209, 133.197 + 0.4, 10000.0, 34.0, 16272.3, 8816.6, 3391.4, 15.957, 162.723 + 0.4, 10000.0, 38.0, 19122.7, 9537.0, 4262.0, 18.284, 191.227 + 0.4, 10000.0, 42.0, 21893.2, 10177.2, 5188.5, 20.395, 218.932 + 0.4, 10000.0, 46.0, 24602.9, 10756.8, 6158.4, 33.244, 246.029 + 0.4, 10000.0, 48.0, 25932.9, 11021.4, 6687.2, 50.261, 259.329 + 0.4, 10000.0, 50.0, 27252.3, 11276.0, 7221.2, 62.314, 272.523 + 0.4, 15000.0, 21.0, 5168.0, 4512.9, 650.8, 8.4556, 51.68 + 0.4, 15000.0, 22.0, 5854.1, 4806.0, 806.0, 5.4657, 58.541 + 0.4, 15000.0, 24.0, 7144.6, 5310.3, 1104.8, 6.507, 71.446 + 0.4, 15000.0, 26.0, 8365.6, 5745.3, 1391.4, 8.064, 83.656 + 0.4, 15000.0, 30.0, 10925.8, 6558.6, 2044.8, 11.526, 109.258 + 0.4, 15000.0, 34.0, 13348.1, 7234.0, 2729.6, 14.163, 133.481 + 0.4, 15000.0, 38.0, 15686.6, 7825.6, 3426.3, 16.392, 156.866 + 0.4, 15000.0, 42.0, 17959.2, 8351.4, 4166.5, 18.41, 179.592 + 0.4, 15000.0, 46.0, 20182.2, 8827.3, 4942.1, 20.28, 201.822 + 0.4, 15000.0, 48.0, 21272.7, 9044.6, 5364.6, 24.607, 212.727 + 0.4, 15000.0, 50.0, 22355.5, 9253.8, 5792.4, 36.891, 223.555 + 0.4, 20000.0, 21.0, 4204.2, 3671.1, 533.0, 11.344, 42.042 + 0.4, 20000.0, 22.0, 4763.2, 3910.2, 655.9, 8.3987, 47.632 + 0.4, 20000.0, 24.0, 5814.2, 4321.4, 892.7, 5.1322, 58.142 + 0.4, 20000.0, 26.0, 6808.5, 4676.0, 1119.9, 6.6187, 68.085 + 0.4, 20000.0, 30.0, 8893.2, 5339.0, 1638.7, 9.2928, 88.932 + 0.4, 20000.0, 34.0, 10865.4, 5889.5, 2181.2, 12.258, 108.654 + 0.4, 20000.0, 38.0, 12769.1, 6371.6, 2734.1, 14.37, 127.691 + 0.4, 20000.0, 42.0, 14619.4, 6800.2, 3321.2, 16.28, 146.194 + 0.4, 20000.0, 46.0, 16429.0, 7188.1, 3935.2, 18.048, 164.29 + 0.4, 20000.0, 48.0, 17317.4, 7365.4, 4270.7, 18.955, 173.174 + 0.4, 20000.0, 50.0, 18198.2, 7535.7, 4608.9, 19.817, 181.982 + 0.45, 5000.0, 21.0, 9134.3, 8186.4, 1052.9, 6.2594, 91.343 + 0.45, 5000.0, 22.0, 10153.5, 8637.0, 1297.4, 7.5048, 101.535 + 0.45, 5000.0, 24.0, 12077.2, 9423.1, 1777.2, 9.5637, 120.772 + 0.45, 5000.0, 26.0, 13900.8, 10109.4, 2237.9, 11.895, 139.008 + 0.45, 5000.0, 30.0, 17726.1, 11407.1, 3263.8, 15.21, 177.261 + 0.45, 5000.0, 34.0, 21336.8, 12490.1, 4347.5, 18.009, 213.368 + 0.45, 5000.0, 38.0, 24813.0, 13438.6, 5462.2, 20.42, 248.13 + 0.45, 5000.0, 42.0, 28188.8, 14287.0, 6626.4, 34.59, 281.888 + 0.45, 5000.0, 46.0, 31486.0, 15056.3, 7841.9, 62.504, 314.86 + 0.45, 5000.0, 48.0, 33098.2, 15405.0, 8512.7, 72.975, 330.982 + 0.45, 5000.0, 50.0, 34700.2, 15743.1, 9179.8, 79.815, 347.002 + 0.45, 10000.0, 21.0, 7545.9, 6763.0, 865.0, 5.1128, 75.459 + 0.45, 10000.0, 22.0, 8388.6, 7135.9, 1062.6, 6.3291, 83.886 + 0.45, 10000.0, 24.0, 9978.2, 7786.1, 1449.5, 8.3334, 99.782 + 0.45, 10000.0, 26.0, 11485.1, 8353.6, 1820.8, 9.9346, 114.851 + 0.45, 10000.0, 30.0, 14645.9, 9426.7, 2648.1, 13.672, 146.459 + 0.45, 10000.0, 34.0, 17629.4, 10322.5, 3522.4, 16.391, 176.294 + 0.45, 10000.0, 38.0, 20501.5, 11106.9, 4421.5, 18.73, 205.015 + 0.45, 10000.0, 42.0, 23290.9, 11808.7, 5360.6, 20.812, 232.909 + 0.45, 10000.0, 46.0, 26014.7, 12444.7, 6339.6, 38.018, 260.147 + 0.45, 10000.0, 48.0, 27346.9, 12733.1, 6880.0, 54.809, 273.469 + 0.45, 10000.0, 50.0, 28670.6, 13012.9, 7417.8, 65.545, 286.706 + 0.45, 15000.0, 21.0, 6188.1, 5546.1, 708.2, 7.0161, 61.881 + 0.45, 15000.0, 22.0, 6879.8, 5852.6, 866.3, 5.0623, 68.798 + 0.45, 15000.0, 24.0, 8184.3, 6386.7, 1176.1, 6.9948, 81.843 + 0.45, 15000.0, 26.0, 9420.7, 6852.7, 1473.1, 8.533, 94.207 + 0.45, 15000.0, 30.0, 12014.0, 7734.1, 2135.7, 11.974, 120.14 + 0.45, 15000.0, 34.0, 14461.5, 8469.7, 2834.4, 14.576, 144.615 + 0.45, 15000.0, 38.0, 16817.6, 9113.8, 3553.9, 16.816, 168.176 + 0.45, 15000.0, 42.0, 19105.8, 9690.3, 4304.2, 18.806, 191.058 + 0.45, 15000.0, 46.0, 21340.5, 10212.6, 5087.2, 20.647, 213.405 + 0.45, 15000.0, 48.0, 22433.2, 10449.4, 5519.7, 27.602, 224.332 + 0.45, 15000.0, 50.0, 23518.8, 10679.1, 5949.6, 41.472, 235.188 + 0.45, 20000.0, 21.0, 5034.5, 4512.0, 578.2, 9.9201, 50.345 + 0.45, 20000.0, 22.0, 5598.0, 4762.1, 703.5, 7.1405, 55.98 + 0.45, 20000.0, 24.0, 6660.5, 5197.7, 949.2, 5.5997, 66.605 + 0.45, 20000.0, 26.0, 7667.4, 5577.6, 1184.8, 7.0642, 76.674 + 0.45, 20000.0, 30.0, 9779.0, 6296.0, 1710.7, 9.6704, 97.79 + 0.45, 20000.0, 34.0, 11771.9, 6895.7, 2264.6, 12.648, 117.719 + 0.45, 20000.0, 38.0, 13690.0, 7420.5, 2835.3, 14.769, 136.9 + 0.45, 20000.0, 42.0, 15553.0, 7890.4, 3430.4, 16.652, 155.53 + 0.45, 20000.0, 46.0, 17372.0, 8316.2, 4051.2, 18.392, 173.72 + 0.45, 20000.0, 48.0, 18261.9, 8509.5, 4393.4, 19.298, 182.619 + 0.45, 20000.0, 50.0, 19145.4, 8696.4, 4733.9, 20.481, 191.454 + 0.45, 25000.0, 21.0, 4060.5, 3638.9, 471.3, 12.824, 40.605 + 0.45, 25000.0, 22.0, 4515.9, 3841.4, 569.7, 10.068, 45.159 + 0.45, 25000.0, 24.0, 5374.3, 4193.9, 762.8, 5.6593, 53.743 + 0.45, 25000.0, 26.0, 6187.3, 4501.0, 947.5, 5.5964, 61.873 + 0.45, 25000.0, 30.0, 7892.2, 5081.8, 1360.8, 8.0513, 78.922 + 0.45, 25000.0, 34.0, 9501.3, 5566.7, 1795.6, 10.502, 95.013 + 0.45, 25000.0, 38.0, 11049.7, 5991.0, 2244.5, 12.709, 110.497 + 0.45, 25000.0, 42.0, 12553.9, 6370.9, 2711.4, 14.474, 125.539 + 0.45, 25000.0, 46.0, 14022.2, 6715.2, 3198.7, 16.109, 140.222 + 0.45, 25000.0, 48.0, 14740.5, 6871.3, 3466.7, 16.96, 147.405 + 0.45, 25000.0, 50.0, 15453.9, 7022.7, 3734.8, 17.763, 154.539 + 0.5, 10000.0, 21.0, 8935.3, 8163.6, 961.2, 5.8415, 89.353 + 0.5, 10000.0, 22.0, 9784.6, 8549.9, 1163.5, 6.9976, 97.846 + 0.5, 10000.0, 24.0, 11396.5, 9235.8, 1543.3, 8.8511, 113.965 + 0.5, 10000.0, 26.0, 12924.7, 9838.0, 1929.2, 10.579, 129.247 + 0.5, 10000.0, 30.0, 16130.8, 10986.4, 2783.0, 14.206, 161.308 + 0.5, 10000.0, 34.0, 19153.1, 11950.9, 3679.1, 16.896, 191.531 + 0.5, 10000.0, 38.0, 22058.2, 12798.3, 4602.1, 19.219, 220.582 + 0.5, 10000.0, 42.0, 24877.3, 13559.7, 5557.3, 21.879, 248.773 + 0.5, 10000.0, 46.0, 27624.5, 14249.1, 6554.3, 44.221, 276.245 + 0.5, 10000.0, 48.0, 28965.7, 14561.4, 7104.9, 59.126, 289.657 + 0.5, 10000.0, 50.0, 30298.2, 14865.0, 7650.4, 69.048, 302.982 + 0.5, 15000.0, 21.0, 7328.1, 6695.3, 785.0, 5.2669, 73.281 + 0.5, 15000.0, 22.0, 8025.5, 7012.9, 947.3, 5.7106, 80.255 + 0.5, 15000.0, 24.0, 9348.0, 7576.1, 1250.9, 7.4914, 93.48 + 0.5, 15000.0, 26.0, 10602.1, 8070.9, 1560.0, 9.017, 106.021 + 0.5, 15000.0, 30.0, 13232.8, 9014.0, 2243.0, 12.483, 132.328 + 0.5, 15000.0, 34.0, 15712.4, 9806.1, 2959.9, 15.058, 157.124 + 0.5, 15000.0, 38.0, 18095.8, 10502.0, 3698.5, 17.284, 180.958 + 0.5, 15000.0, 42.0, 20408.6, 11127.3, 4462.3, 19.251, 204.086 + 0.5, 15000.0, 46.0, 22662.5, 11693.7, 5260.4, 22.186, 226.625 + 0.5, 15000.0, 48.0, 23762.9, 11950.1, 5699.8, 31.922, 237.629 + 0.5, 15000.0, 50.0, 24855.4, 12199.1, 6135.5, 46.874, 248.554 + 0.5, 20000.0, 21.0, 5962.3, 5447.4, 638.9, 8.1949, 59.623 + 0.5, 20000.0, 22.0, 6530.4, 5706.6, 767.5, 5.5864, 65.304 + 0.5, 20000.0, 24.0, 7607.5, 6165.9, 1008.8, 6.0754, 76.075 + 0.5, 20000.0, 26.0, 8628.5, 6569.1, 1253.7, 7.5239, 86.285 + 0.5, 20000.0, 30.0, 10770.3, 7337.8, 1795.3, 10.124, 107.703 + 0.5, 20000.0, 34.0, 12788.9, 7983.4, 2363.9, 13.102, 127.889 + 0.5, 20000.0, 38.0, 14729.0, 8550.6, 2949.4, 15.208, 147.29 + 0.5, 20000.0, 42.0, 16611.6, 9060.2, 3555.1, 17.068, 166.116 + 0.5, 20000.0, 46.0, 18446.0, 9521.6, 4187.2, 18.792, 184.46 + 0.5, 20000.0, 48.0, 19341.8, 9731.0, 4535.0, 19.685, 193.418 + 0.5, 20000.0, 50.0, 20231.5, 9934.1, 4880.0, 22.256, 202.315 + 0.5, 25000.0, 21.0, 4809.4, 4393.9, 518.7, 11.107, 48.094 + 0.5, 25000.0, 22.0, 5268.5, 4603.8, 619.7, 8.5392, 52.685 + 0.5, 25000.0, 24.0, 6138.4, 4975.2, 809.4, 4.6585, 61.384 + 0.5, 25000.0, 26.0, 6963.0, 5301.2, 1001.5, 6.0297, 69.63 + 0.5, 25000.0, 30.0, 8692.6, 5923.0, 1426.9, 8.4555, 86.926 + 0.5, 25000.0, 34.0, 10322.4, 6444.9, 1873.7, 11.135, 103.224 + 0.5, 25000.0, 38.0, 11888.8, 6903.5, 2334.1, 13.12, 118.888 + 0.5, 25000.0, 42.0, 13408.7, 7315.6, 2809.6, 14.863, 134.087 + 0.5, 25000.0, 46.0, 14889.7, 7688.8, 3305.8, 16.482, 148.897 + 0.5, 25000.0, 48.0, 15612.7, 7857.9, 3578.7, 17.322, 156.127 + 0.5, 25000.0, 50.0, 16331.0, 8022.2, 3850.1, 18.114, 163.31 + 0.55, 10000.0, 21.0, 10473.2, 9708.0, 1063.1, 6.5663, 104.732 + 0.55, 10000.0, 22.0, 11331.3, 10107.0, 1273.2, 7.684, 113.313 + 0.55, 10000.0, 24.0, 12968.8, 10826.2, 1651.6, 9.4227, 129.688 + 0.55, 10000.0, 26.0, 14524.0, 11463.2, 2046.0, 11.615, 145.24 + 0.55, 10000.0, 30.0, 17784.6, 12683.1, 2929.7, 14.772, 177.846 + 0.55, 10000.0, 34.0, 20855.7, 13713.6, 3852.5, 17.44, 208.557 + 0.55, 10000.0, 38.0, 23804.1, 14621.6, 4806.1, 19.759, 238.041 + 0.55, 10000.0, 42.0, 26664.3, 15441.0, 5782.5, 24.834, 266.643 + 0.55, 10000.0, 46.0, 29445.2, 16181.5, 6806.8, 51.322, 294.452 + 0.55, 10000.0, 48.0, 30801.6, 16517.7, 7366.0, 63.487, 308.016 + 0.55, 10000.0, 50.0, 32151.3, 16847.1, 7921.7, 72.72, 321.513 + 0.55, 15000.0, 21.0, 8589.7, 7962.3, 866.4, 5.2947, 85.897 + 0.55, 15000.0, 22.0, 9294.1, 8290.2, 1034.6, 6.3704, 92.941 + 0.55, 15000.0, 24.0, 10637.7, 8880.9, 1337.3, 8.0399, 106.377 + 0.55, 15000.0, 26.0, 11913.6, 9404.0, 1653.0, 9.52, 119.136 + 0.55, 15000.0, 30.0, 14588.5, 10405.8, 2359.7, 13.02, 145.885 + 0.55, 15000.0, 34.0, 17108.0, 11252.3, 3098.8, 15.578, 171.08 + 0.55, 15000.0, 38.0, 19526.7, 11997.8, 3861.4, 17.796, 195.267 + 0.55, 15000.0, 42.0, 21872.4, 12670.6, 4642.0, 19.745, 218.724 + 0.55, 15000.0, 46.0, 24153.7, 13278.7, 5460.9, 25.174, 241.537 + 0.55, 15000.0, 48.0, 25266.4, 13555.1, 5907.7, 37.782, 252.664 + 0.55, 15000.0, 50.0, 26373.7, 13825.7, 6352.0, 52.652, 263.737 + 0.55, 20000.0, 21.0, 6989.4, 6479.0, 703.3, 6.503, 69.894 + 0.55, 20000.0, 22.0, 7563.3, 6746.5, 837.0, 5.0064, 75.633 + 0.55, 20000.0, 24.0, 8657.4, 7228.1, 1077.2, 6.5972, 86.574 + 0.55, 20000.0, 26.0, 9696.4, 7654.5, 1327.5, 8.0013, 96.964 + 0.55, 20000.0, 30.0, 11874.4, 8471.2, 1888.0, 11.051, 118.744 + 0.55, 20000.0, 34.0, 13925.6, 9161.1, 2474.4, 13.594, 139.256 + 0.55, 20000.0, 38.0, 15894.5, 9768.8, 3078.5, 15.69, 158.945 + 0.55, 20000.0, 42.0, 17804.3, 10317.3, 3698.0, 17.532, 178.043 + 0.55, 20000.0, 46.0, 19661.3, 10813.0, 4347.4, 19.251, 196.613 + 0.55, 20000.0, 48.0, 20567.3, 11038.3, 4701.1, 20.129, 205.673 + 0.55, 20000.0, 50.0, 21468.4, 11258.8, 5053.1, 25.154, 214.684 + 0.55, 25000.0, 21.0, 5638.5, 5226.6, 569.1, 9.4348, 56.385 + 0.55, 25000.0, 22.0, 6102.2, 5443.2, 674.2, 6.9986, 61.022 + 0.55, 25000.0, 24.0, 6985.9, 5832.7, 863.0, 5.1538, 69.859 + 0.55, 25000.0, 26.0, 7825.0, 6177.5, 1059.5, 6.4814, 78.25 + 0.55, 25000.0, 30.0, 9583.8, 6838.0, 1499.7, 8.8813, 95.838 + 0.55, 25000.0, 34.0, 11240.1, 7395.8, 1960.8, 11.598, 112.401 + 0.55, 25000.0, 38.0, 12829.7, 7887.1, 2435.5, 13.57, 128.297 + 0.55, 25000.0, 42.0, 14371.4, 8330.6, 2922.0, 15.297, 143.714 + 0.55, 25000.0, 46.0, 15870.7, 8731.4, 3431.6, 16.909, 158.707 + 0.55, 25000.0, 48.0, 16601.9, 8913.6, 3708.9, 17.733, 166.019 + 0.55, 25000.0, 50.0, 17329.5, 9092.0, 3985.6, 18.518, 173.295 + 0.55, 30000.0, 21.0, 4506.0, 4176.6, 459.6, 12.365, 45.06 + 0.55, 30000.0, 22.0, 4877.6, 4350.6, 541.3, 9.9465, 48.776 + 0.55, 30000.0, 24.0, 5585.4, 4663.2, 688.6, 6.3459, 55.854 + 0.55, 30000.0, 26.0, 6257.1, 4939.6, 841.1, 4.9951, 62.571 + 0.55, 30000.0, 30.0, 7665.1, 5469.3, 1183.3, 7.2442, 76.651 + 0.55, 30000.0, 34.0, 8990.5, 5916.4, 1541.7, 9.1534, 89.905 + 0.55, 30000.0, 38.0, 10262.7, 6310.2, 1910.9, 11.49, 102.627 + 0.55, 30000.0, 42.0, 11496.3, 6665.6, 2289.2, 13.1, 114.963 + 0.55, 30000.0, 46.0, 12696.1, 6986.9, 2685.7, 14.605, 126.961 + 0.55, 30000.0, 48.0, 13281.5, 7133.2, 2900.4, 15.372, 132.815 + 0.55, 30000.0, 50.0, 13863.3, 7275.8, 3114.4, 16.106, 138.633 + 0.6, 15000.0, 21.0, 9973.8, 9348.2, 950.5, 5.9783, 99.738 + 0.6, 15000.0, 22.0, 10687.7, 9686.8, 1124.3, 7.0163, 106.877 + 0.6, 15000.0, 24.0, 12054.5, 10302.9, 1438.6, 8.6443, 120.545 + 0.6, 15000.0, 26.0, 13357.4, 10855.1, 1754.7, 10.048, 133.574 + 0.6, 15000.0, 30.0, 16084.8, 11914.4, 2488.5, 13.592, 160.848 + 0.6, 15000.0, 34.0, 18652.7, 12814.1, 3252.5, 16.138, 186.527 + 0.6, 15000.0, 38.0, 21114.4, 13607.6, 4042.6, 18.351, 211.144 + 0.6, 15000.0, 42.0, 23501.9, 14327.1, 4845.2, 20.289, 235.019 + 0.6, 15000.0, 46.0, 25820.8, 14977.7, 5688.9, 30.203, 258.208 + 0.6, 15000.0, 48.0, 26957.4, 15280.2, 6143.4, 44.833, 269.574 + 0.6, 15000.0, 50.0, 28089.5, 15578.2, 6600.6, 58.064, 280.895 + 0.6, 20000.0, 21.0, 8116.3, 7607.3, 769.9, 4.8739, 81.163 + 0.6, 20000.0, 22.0, 8697.8, 7883.4, 907.9, 5.6219, 86.978 + 0.6, 20000.0, 24.0, 9810.9, 8385.7, 1157.0, 7.1692, 98.109 + 0.6, 20000.0, 26.0, 10872.0, 8836.1, 1408.5, 8.504, 108.72 + 0.6, 20000.0, 30.0, 13092.7, 9699.5, 1989.8, 11.708, 130.927 + 0.6, 20000.0, 34.0, 15183.5, 10432.9, 2596.5, 14.121, 151.835 + 0.6, 20000.0, 38.0, 17187.7, 11079.9, 3223.0, 16.215, 171.877 + 0.6, 20000.0, 42.0, 19131.3, 11666.4, 3858.8, 18.043, 191.313 + 0.6, 20000.0, 46.0, 21019.2, 12196.8, 4528.3, 19.756, 210.192 + 0.6, 20000.0, 48.0, 21944.6, 12443.4, 4888.4, 21.651, 219.446 + 0.6, 20000.0, 50.0, 22865.7, 12685.9, 5250.5, 29.739, 228.657 + 0.6, 25000.0, 21.0, 6548.0, 6137.4, 621.3, 7.8343, 65.48 + 0.6, 25000.0, 22.0, 7018.0, 6361.0, 730.0, 5.5192, 70.18 + 0.6, 25000.0, 24.0, 7917.0, 6767.3, 925.6, 5.6982, 79.17 + 0.6, 25000.0, 26.0, 8773.7, 7131.3, 1123.2, 6.9559, 87.737 + 0.6, 25000.0, 30.0, 10567.1, 7829.7, 1580.2, 9.3365, 105.671 + 0.6, 25000.0, 34.0, 12254.9, 8422.5, 2056.4, 12.09, 122.549 + 0.6, 25000.0, 38.0, 13872.9, 8945.6, 2548.6, 14.059, 138.729 + 0.6, 25000.0, 42.0, 15441.9, 9419.5, 3048.5, 15.774, 154.419 + 0.6, 25000.0, 46.0, 16965.8, 9848.6, 3573.0, 17.377, 169.658 + 0.6, 25000.0, 48.0, 17712.8, 10048.1, 3855.9, 18.185, 177.128 + 0.6, 25000.0, 50.0, 18456.6, 10244.4, 4140.2, 18.967, 184.566 + 0.6, 30000.0, 21.0, 5233.4, 4905.1, 500.0, 10.771, 52.334 + 0.6, 30000.0, 22.0, 5610.0, 5084.7, 584.6, 8.4942, 56.1 + 0.6, 30000.0, 24.0, 6329.9, 5410.6, 736.4, 5.0619, 63.299 + 0.6, 30000.0, 26.0, 7015.7, 5702.4, 890.5, 5.441, 70.157 + 0.6, 30000.0, 30.0, 8451.2, 6262.4, 1245.5, 7.6673, 84.512 + 0.6, 30000.0, 34.0, 9802.1, 6737.8, 1616.1, 9.6371, 98.021 + 0.6, 30000.0, 38.0, 11096.9, 7157.0, 1998.7, 11.943, 110.969 + 0.6, 30000.0, 42.0, 12352.3, 7536.9, 2387.5, 13.542, 123.523 + 0.6, 30000.0, 46.0, 13571.6, 7880.7, 2795.9, 15.04, 135.716 + 0.6, 30000.0, 48.0, 14169.7, 8041.0, 3014.6, 15.79, 141.697 + 0.6, 30000.0, 50.0, 14764.6, 8198.1, 3235.5, 16.524, 147.646 + 0.6, 35000.0, 21.0, 4139.6, 3879.7, 401.9, 13.765, 41.396 + 0.6, 35000.0, 22.0, 4438.7, 4022.7, 467.0, 11.472, 44.387 + 0.6, 35000.0, 24.0, 5009.8, 4281.9, 583.8, 8.0866, 50.098 + 0.6, 35000.0, 26.0, 5553.5, 4513.7, 702.3, 5.2844, 55.535 + 0.6, 35000.0, 30.0, 6691.7, 4958.7, 975.1, 6.0676, 66.917 + 0.6, 35000.0, 34.0, 7762.5, 5336.2, 1259.8, 7.8379, 77.625 + 0.6, 35000.0, 38.0, 8788.5, 5669.1, 1553.9, 9.6313, 87.885 + 0.6, 35000.0, 42.0, 9783.3, 5970.6, 1853.8, 11.406, 97.833 + 0.6, 35000.0, 46.0, 10749.7, 6243.7, 2167.6, 12.793, 107.497 + 0.6, 35000.0, 48.0, 11223.1, 6370.7, 2335.6, 13.49, 112.231 + 0.6, 35000.0, 50.0, 11695.0, 6496.0, 2504.7, 14.172, 116.95 + 0.6, 37000.0, 21.0, 3758.1, 3522.0, 370.0, 14.208, 37.581 + 0.6, 37000.0, 22.0, 4030.2, 3652.4, 428.7, 11.931, 40.302 + 0.6, 37000.0, 24.0, 4549.5, 3888.3, 534.1, 8.6067, 45.495 + 0.6, 37000.0, 26.0, 5043.7, 4099.0, 640.8, 5.8649, 50.437 + 0.6, 37000.0, 30.0, 6078.5, 4504.0, 886.9, 5.62, 60.785 + 0.6, 37000.0, 34.0, 7051.8, 4847.5, 1143.9, 7.3337, 70.518 + 0.6, 37000.0, 38.0, 7984.2, 5150.1, 1409.1, 8.8243, 79.842 + 0.6, 37000.0, 42.0, 8888.2, 5424.2, 1680.1, 10.753, 88.882 + 0.6, 37000.0, 46.0, 9766.3, 5672.7, 1963.0, 12.091, 97.663 + 0.6, 37000.0, 48.0, 10197.0, 5788.4, 2114.5, 12.764, 101.97 + 0.6, 37000.0, 50.0, 10625.8, 5902.3, 2266.3, 13.418, 106.258 + 0.6, 39000.0, 21.0, 3410.5, 3195.9, 342.8, 13.736, 34.105 + 0.6, 39000.0, 22.0, 3658.1, 3314.8, 396.0, 11.525, 36.581 + 0.6, 39000.0, 24.0, 4130.3, 3529.5, 491.6, 8.3235, 41.303 + 0.6, 39000.0, 26.0, 4579.5, 3721.3, 588.5, 5.6738, 45.795 + 0.6, 39000.0, 30.0, 5520.0, 4089.6, 811.7, 5.3948, 55.2 + 0.6, 39000.0, 34.0, 6404.7, 4402.1, 1044.8, 7.0416, 64.047 + 0.6, 39000.0, 38.0, 7251.9, 4677.1, 1285.7, 8.4753, 72.519 + 0.6, 39000.0, 42.0, 8073.2, 4926.2, 1532.0, 10.334, 80.732 + 0.6, 39000.0, 46.0, 8871.3, 5152.2, 1788.5, 11.619, 88.713 + 0.6, 39000.0, 48.0, 9262.7, 5257.5, 1925.9, 12.265, 92.627 + 0.6, 39000.0, 50.0, 9652.5, 5361.2, 2063.4, 12.888, 96.525 + 0.6, 41000.0, 21.0, 3094.4, 2899.4, 318.6, 13.295, 30.944 + 0.6, 41000.0, 22.0, 3320.0, 3008.0, 366.6, 11.145, 33.2 + 0.6, 41000.0, 24.0, 3749.4, 3203.6, 453.0, 8.0632, 37.494 + 0.6, 41000.0, 26.0, 4157.8, 3378.0, 541.0, 5.5011, 41.578 + 0.6, 41000.0, 30.0, 5012.8, 3713.2, 743.4, 5.178, 50.128 + 0.6, 41000.0, 34.0, 5816.8, 3997.3, 954.9, 6.7566, 58.168 + 0.6, 41000.0, 38.0, 6586.8, 4247.5, 1173.9, 8.1404, 65.868 + 0.6, 41000.0, 42.0, 7333.1, 4473.9, 1397.5, 9.9298, 73.331 + 0.6, 41000.0, 46.0, 8058.4, 4679.4, 1630.2, 11.165, 80.584 + 0.6, 41000.0, 48.0, 8414.1, 4775.2, 1754.8, 11.784, 84.141 + 0.6, 41000.0, 50.0, 8768.5, 4869.7, 1878.9, 12.376, 87.685 + 0.65, 15000.0, 21.0, 11481.3, 10854.1, 1035.9, 6.6394, 114.813 + 0.65, 15000.0, 22.0, 12207.7, 11204.2, 1215.3, 7.6447, 122.077 + 0.65, 15000.0, 24.0, 13603.0, 11846.9, 1542.7, 9.2444, 136.03 + 0.65, 15000.0, 26.0, 14935.6, 12427.0, 1867.4, 11.011, 149.356 + 0.65, 15000.0, 30.0, 17724.6, 13543.7, 2628.1, 14.192, 177.246 + 0.65, 15000.0, 34.0, 20349.9, 14496.6, 3420.7, 16.73, 203.499 + 0.65, 15000.0, 38.0, 22863.3, 15337.4, 4243.8, 18.949, 228.633 + 0.65, 15000.0, 42.0, 25300.6, 16102.7, 5073.7, 20.882, 253.006 + 0.65, 15000.0, 46.0, 27684.0, 16813.4, 5945.8, 37.645, 276.84 + 0.65, 15000.0, 48.0, 28853.2, 17146.3, 6412.4, 52.445, 288.532 + 0.65, 15000.0, 50.0, 30016.4, 17473.3, 6885.5, 63.165, 300.164 + 0.65, 20000.0, 21.0, 9343.5, 8833.4, 837.7, 5.2653, 93.435 + 0.65, 20000.0, 22.0, 9935.0, 9118.7, 979.9, 6.2209, 99.35 + 0.65, 20000.0, 24.0, 11071.1, 9642.6, 1239.6, 7.74, 110.711 + 0.65, 20000.0, 26.0, 12156.3, 10115.6, 1497.6, 9.0357, 121.563 + 0.65, 20000.0, 30.0, 14427.2, 11026.1, 2101.3, 12.279, 144.272 + 0.65, 20000.0, 34.0, 16564.3, 11802.7, 2729.9, 14.679, 165.643 + 0.65, 20000.0, 38.0, 18610.2, 12488.0, 3382.1, 16.776, 186.102 + 0.65, 20000.0, 42.0, 20594.6, 13112.0, 4040.1, 18.601, 205.946 + 0.65, 20000.0, 46.0, 22534.2, 13691.1, 4731.2, 20.306, 225.342 + 0.65, 20000.0, 48.0, 23485.7, 13962.4, 5100.5, 24.941, 234.857 + 0.65, 20000.0, 50.0, 24432.6, 14229.1, 5474.5, 36.266, 244.326 + 0.65, 25000.0, 21.0, 7538.7, 7127.2, 674.5, 6.3118, 75.387 + 0.65, 25000.0, 22.0, 8016.8, 7358.3, 786.7, 4.8016, 80.168 + 0.65, 25000.0, 24.0, 8934.3, 7781.9, 990.5, 6.2373, 89.343 + 0.65, 25000.0, 26.0, 9810.5, 8164.3, 1193.3, 7.4577, 98.105 + 0.65, 25000.0, 30.0, 11644.1, 8900.5, 1667.2, 9.8122, 116.441 + 0.65, 25000.0, 34.0, 13369.6, 9528.5, 2161.3, 12.612, 133.696 + 0.65, 25000.0, 38.0, 15021.2, 10082.6, 2673.6, 14.582, 150.212 + 0.65, 25000.0, 42.0, 16623.1, 10587.1, 3190.9, 16.294, 166.231 + 0.65, 25000.0, 46.0, 18188.8, 11055.3, 3733.0, 17.892, 181.888 + 0.65, 25000.0, 48.0, 18957.1, 11274.9, 4023.5, 18.687, 189.571 + 0.65, 25000.0, 50.0, 19721.6, 11490.7, 4316.5, 19.465, 197.216 + 0.65, 30000.0, 21.0, 6025.8, 5696.8, 541.2, 9.2686, 60.258 + 0.65, 30000.0, 22.0, 6408.8, 5882.4, 628.6, 7.1132, 64.088 + 0.65, 30000.0, 24.0, 7143.4, 6222.1, 786.8, 4.7609, 71.434 + 0.65, 30000.0, 26.0, 7844.8, 6528.7, 944.9, 5.9115, 78.448 + 0.65, 30000.0, 30.0, 9312.7, 7119.2, 1313.5, 8.114, 93.127 + 0.65, 30000.0, 34.0, 10693.4, 7622.5, 1697.7, 10.518, 106.934 + 0.65, 30000.0, 38.0, 12015.1, 8066.7, 2096.0, 12.429, 120.151 + 0.65, 30000.0, 42.0, 13296.7, 8470.9, 2498.2, 14.024, 132.967 + 0.65, 30000.0, 46.0, 14549.5, 8846.3, 2919.9, 15.514, 145.495 + 0.65, 30000.0, 48.0, 15164.4, 9022.5, 3145.2, 16.258, 151.644 + 0.65, 30000.0, 50.0, 15776.0, 9195.4, 3372.5, 16.984, 157.76 + 0.65, 35000.0, 21.0, 4767.0, 4506.6, 433.5, 12.248, 47.67 + 0.65, 35000.0, 22.0, 5071.1, 4654.4, 500.8, 10.098, 50.711 + 0.65, 35000.0, 24.0, 5653.7, 4924.4, 622.1, 6.8639, 56.537 + 0.65, 35000.0, 26.0, 6210.0, 5168.0, 743.9, 4.422, 62.1 + 0.65, 35000.0, 30.0, 7373.7, 5637.1, 1027.3, 6.4841, 73.737 + 0.65, 35000.0, 34.0, 8468.2, 6037.1, 1322.7, 8.2441, 84.682 + 0.65, 35000.0, 38.0, 9515.4, 6389.7, 1628.5, 10.363, 95.154 + 0.65, 35000.0, 42.0, 10530.9, 6710.5, 1938.8, 11.854, 105.309 + 0.65, 35000.0, 46.0, 11523.6, 7008.6, 2262.9, 13.234, 115.236 + 0.65, 35000.0, 48.0, 12010.7, 7148.5, 2436.1, 13.925, 120.107 + 0.65, 35000.0, 50.0, 12495.8, 7286.2, 2609.9, 14.597, 124.958 + 0.65, 37000.0, 21.0, 4328.0, 4091.4, 398.3, 12.711, 43.28 + 0.65, 37000.0, 22.0, 4604.7, 4226.1, 459.1, 10.58, 46.047 + 0.65, 37000.0, 24.0, 5134.7, 4472.0, 568.6, 7.4067, 51.347 + 0.65, 37000.0, 26.0, 5640.3, 4693.6, 678.3, 4.7981, 56.403 + 0.65, 37000.0, 30.0, 6698.2, 5120.4, 934.1, 6.0241, 66.982 + 0.65, 37000.0, 34.0, 7693.1, 5484.2, 1200.6, 7.7263, 76.931 + 0.65, 37000.0, 38.0, 8645.0, 5805.0, 1476.6, 9.5229, 86.45 + 0.65, 37000.0, 42.0, 9567.7, 6096.5, 1757.2, 11.188, 95.677 + 0.65, 37000.0, 46.0, 10470.1, 6367.8, 2049.0, 12.517, 104.701 + 0.65, 37000.0, 48.0, 10912.6, 6494.8, 2205.3, 13.184, 109.126 + 0.65, 37000.0, 50.0, 11353.7, 6620.3, 2361.7, 13.83, 113.537 + 0.65, 39000.0, 21.0, 3928.0, 3713.0, 368.4, 12.291, 39.28 + 0.65, 39000.0, 22.0, 4179.8, 3835.7, 423.5, 10.222, 41.798 + 0.65, 39000.0, 24.0, 4661.5, 4059.5, 522.5, 7.1754, 46.615 + 0.65, 39000.0, 26.0, 5121.2, 4261.1, 622.3, 4.6517, 51.212 + 0.65, 39000.0, 30.0, 6082.8, 4649.3, 854.5, 5.7838, 60.828 + 0.65, 39000.0, 34.0, 6987.2, 4980.3, 1096.2, 7.4195, 69.872 + 0.65, 39000.0, 38.0, 7852.3, 5272.0, 1347.0, 9.1325, 78.523 + 0.65, 39000.0, 42.0, 8690.6, 5536.9, 1601.9, 10.752, 86.906 + 0.65, 39000.0, 46.0, 9510.4, 5783.5, 1866.9, 12.031, 95.104 + 0.65, 39000.0, 48.0, 9912.8, 5899.1, 2008.5, 12.671, 99.128 + 0.65, 39000.0, 50.0, 10313.9, 6013.4, 2149.9, 13.285, 103.139 + 0.65, 41000.0, 21.0, 3564.4, 3369.0, 341.4, 11.899, 35.644 + 0.65, 41000.0, 22.0, 3793.7, 3481.1, 391.2, 9.8837, 37.937 + 0.65, 41000.0, 24.0, 4231.9, 3684.9, 480.9, 6.9499, 42.319 + 0.65, 41000.0, 26.0, 4649.7, 3868.3, 571.5, 4.5148, 46.497 + 0.65, 41000.0, 30.0, 5523.7, 4221.4, 782.2, 5.5521, 55.237 + 0.65, 41000.0, 34.0, 6345.8, 4522.5, 1001.6, 7.1247, 63.458 + 0.65, 41000.0, 38.0, 7131.8, 4787.6, 1229.2, 8.7518, 71.318 + 0.65, 41000.0, 42.0, 7893.5, 5028.4, 1460.7, 10.331, 78.935 + 0.65, 41000.0, 46.0, 8638.7, 5252.7, 1701.3, 11.562, 86.387 + 0.65, 41000.0, 48.0, 9004.5, 5357.9, 1829.8, 12.177, 90.045 + 0.65, 41000.0, 50.0, 9369.0, 5462.0, 1957.7, 12.762, 93.69 + 0.7, 15000.0, 21.0, 13112.0, 12479.9, 1130.1, 7.3244, 131.12 + 0.7, 15000.0, 22.0, 13855.4, 12844.0, 1307.0, 8.2542, 138.554 + 0.7, 15000.0, 24.0, 15285.0, 13515.0, 1648.6, 9.8351, 152.85 + 0.7, 15000.0, 26.0, 16649.3, 14120.8, 1994.3, 11.901, 166.493 + 0.7, 15000.0, 30.0, 19512.9, 15298.6, 2780.9, 14.827, 195.129 + 0.7, 15000.0, 34.0, 22204.6, 16304.7, 3606.0, 17.362, 222.046 + 0.7, 15000.0, 38.0, 24778.2, 17192.6, 4465.4, 19.588, 247.782 + 0.7, 15000.0, 42.0, 27296.1, 18024.8, 5329.0, 23.483, 272.961 + 0.7, 15000.0, 46.0, 29762.1, 18805.2, 6235.3, 46.81, 297.621 + 0.7, 15000.0, 48.0, 30970.5, 19170.8, 6719.8, 59.383, 309.705 + 0.7, 15000.0, 50.0, 32171.1, 19528.5, 7209.9, 68.703, 321.711 + 0.7, 20000.0, 21.0, 10671.0, 10156.9, 912.4, 5.9185, 106.71 + 0.7, 20000.0, 22.0, 11276.8, 10454.1, 1053.1, 6.8056, 112.768 + 0.7, 20000.0, 24.0, 12440.5, 11000.8, 1323.8, 8.3011, 124.405 + 0.7, 20000.0, 26.0, 13551.0, 11494.4, 1598.0, 9.6082, 135.51 + 0.7, 20000.0, 30.0, 15882.3, 12454.6, 2221.7, 12.874, 158.823 + 0.7, 20000.0, 34.0, 18073.4, 13274.7, 2876.5, 15.272, 180.734 + 0.7, 20000.0, 38.0, 20168.3, 13998.5, 3557.9, 17.375, 201.683 + 0.7, 20000.0, 42.0, 22217.1, 14676.3, 4242.1, 19.201, 222.171 + 0.7, 20000.0, 46.0, 24224.9, 15312.9, 4960.5, 22.398, 242.249 + 0.7, 20000.0, 48.0, 25208.3, 15610.7, 5344.4, 30.86, 252.083 + 0.7, 20000.0, 50.0, 26185.8, 15902.7, 5731.7, 44.479, 261.858 + 0.7, 25000.0, 21.0, 8610.5, 8195.8, 733.3, 4.7574, 86.105 + 0.7, 25000.0, 22.0, 9099.7, 8436.2, 843.9, 5.3542, 90.997 + 0.7, 25000.0, 24.0, 10039.4, 8878.3, 1056.5, 6.7662, 100.394 + 0.7, 25000.0, 26.0, 10936.2, 9277.4, 1272.2, 7.9972, 109.362 + 0.7, 25000.0, 30.0, 12818.5, 10053.9, 1762.2, 10.809, 128.185 + 0.7, 25000.0, 34.0, 14587.3, 10716.9, 2276.5, 13.166, 145.873 + 0.7, 25000.0, 38.0, 16278.4, 11302.1, 2811.5, 15.14, 162.784 + 0.7, 25000.0, 42.0, 17932.2, 11850.1, 3349.2, 16.853, 179.322 + 0.7, 25000.0, 46.0, 19552.5, 12364.7, 3912.9, 18.449, 195.525 + 0.7, 25000.0, 48.0, 20346.0, 12605.2, 4213.9, 19.242, 203.46 + 0.7, 25000.0, 50.0, 21135.9, 12842.2, 4516.7, 20.805, 211.359 + 0.7, 30000.0, 21.0, 6883.1, 6551.6, 586.9, 7.7444, 68.831 + 0.7, 30000.0, 22.0, 7275.0, 6744.6, 673.2, 5.7924, 72.75 + 0.7, 30000.0, 24.0, 8027.3, 7099.1, 838.4, 5.2616, 80.273 + 0.7, 30000.0, 26.0, 8744.9, 7418.9, 1005.9, 6.4147, 87.449 + 0.7, 30000.0, 30.0, 10251.7, 8041.7, 1387.1, 8.5806, 102.517 + 0.7, 30000.0, 34.0, 11667.2, 8573.2, 1787.1, 11.099, 116.672 + 0.7, 30000.0, 38.0, 13020.3, 9042.3, 2203.0, 12.944, 130.203 + 0.7, 30000.0, 42.0, 14343.5, 9481.5, 2621.7, 14.545, 143.435 + 0.7, 30000.0, 46.0, 15639.9, 9894.0, 3059.8, 16.032, 156.399 + 0.7, 30000.0, 48.0, 16274.9, 10087.0, 3293.1, 16.77, 162.749 + 0.7, 30000.0, 50.0, 16906.9, 10277.0, 3528.3, 17.488, 169.069 + 0.7, 35000.0, 21.0, 5445.9, 5183.5, 468.4, 10.726, 54.459 + 0.7, 35000.0, 22.0, 5757.0, 5337.1, 535.0, 8.7976, 57.57 + 0.7, 35000.0, 24.0, 6353.6, 5618.9, 661.7, 5.6702, 63.536 + 0.7, 35000.0, 26.0, 6922.8, 5873.2, 791.0, 4.8981, 69.228 + 0.7, 35000.0, 30.0, 8117.1, 6367.8, 1083.9, 6.9194, 81.171 + 0.7, 35000.0, 34.0, 9239.1, 6790.1, 1391.6, 8.6731, 92.391 + 0.7, 35000.0, 38.0, 10311.5, 7162.7, 1711.2, 10.844, 103.115 + 0.7, 35000.0, 42.0, 11359.5, 7511.0, 2033.2, 12.334, 113.595 + 0.7, 35000.0, 46.0, 12386.9, 7838.7, 2370.3, 13.714, 123.869 + 0.7, 35000.0, 48.0, 12890.1, 7992.0, 2549.7, 14.401, 128.901 + 0.7, 35000.0, 50.0, 13391.1, 8143.2, 2729.2, 15.063, 133.911 + 0.7, 37000.0, 21.0, 4944.6, 4706.2, 429.8, 11.211, 49.446 + 0.7, 37000.0, 22.0, 5227.7, 4846.2, 489.9, 9.3025, 52.277 + 0.7, 37000.0, 24.0, 5770.2, 5102.7, 604.1, 6.2444, 57.702 + 0.7, 37000.0, 26.0, 6287.7, 5334.1, 720.9, 4.4868, 62.877 + 0.7, 37000.0, 30.0, 7373.4, 5784.0, 985.0, 6.4444, 73.734 + 0.7, 37000.0, 34.0, 8393.3, 6168.3, 1262.6, 8.1407, 83.933 + 0.7, 37000.0, 38.0, 9368.0, 6507.2, 1551.0, 10.209, 93.68 + 0.7, 37000.0, 42.0, 10320.4, 6823.9, 1842.1, 11.651, 103.204 + 0.7, 37000.0, 46.0, 11254.0, 7121.8, 2146.1, 12.982, 112.54 + 0.7, 37000.0, 48.0, 11711.4, 7261.3, 2308.0, 13.645, 117.114 + 0.7, 37000.0, 50.0, 12167.0, 7399.1, 2469.7, 14.282, 121.67 + 0.7, 39000.0, 21.0, 4487.8, 4271.2, 396.9, 10.846, 44.878 + 0.7, 39000.0, 22.0, 4745.4, 4398.8, 451.5, 8.9937, 47.454 + 0.7, 39000.0, 24.0, 5238.7, 4632.3, 555.0, 6.0497, 52.387 + 0.7, 39000.0, 26.0, 5709.1, 4842.7, 660.9, 4.3014, 57.091 + 0.7, 39000.0, 30.0, 6696.0, 5252.1, 900.8, 6.1896, 66.96 + 0.7, 39000.0, 34.0, 7623.1, 5601.6, 1152.7, 7.8201, 76.231 + 0.7, 39000.0, 38.0, 8508.9, 5909.8, 1414.4, 9.8095, 85.089 + 0.7, 39000.0, 42.0, 9374.1, 6197.4, 1678.7, 11.196, 93.741 + 0.7, 39000.0, 46.0, 10222.7, 6468.4, 1955.0, 12.479, 102.227 + 0.7, 39000.0, 48.0, 10638.4, 6595.3, 2101.9, 13.116, 106.384 + 0.7, 39000.0, 50.0, 11052.6, 6720.7, 2248.2, 13.723, 110.526 + 0.7, 41000.0, 21.0, 4072.9, 3876.1, 367.0, 10.5, 40.729 + 0.7, 41000.0, 22.0, 4307.3, 3992.4, 416.6, 8.698, 43.073 + 0.7, 41000.0, 24.0, 4756.0, 4204.9, 510.3, 5.8669, 47.56 + 0.7, 41000.0, 26.0, 5183.6, 4396.4, 606.4, 4.1214, 51.836 + 0.7, 41000.0, 30.0, 6080.8, 4768.8, 824.2, 5.9412, 60.808 + 0.7, 41000.0, 34.0, 6923.7, 5086.9, 1052.9, 7.5111, 69.237 + 0.7, 41000.0, 38.0, 7728.7, 5367.1, 1290.6, 9.4241, 77.287 + 0.7, 41000.0, 42.0, 8515.0, 5628.6, 1531.1, 10.763, 85.15 + 0.7, 41000.0, 46.0, 9286.2, 5874.9, 1781.7, 11.996, 92.862 + 0.7, 41000.0, 48.0, 9664.1, 5990.4, 1914.9, 12.607, 96.641 + 0.7, 41000.0, 50.0, 10040.5, 6104.4, 2047.5, 13.189, 100.405 + 0.7, 43000.0, 21.0, 3695.7, 3516.9, 340.2, 10.182, 36.957 + 0.7, 43000.0, 22.0, 3909.2, 3623.1, 385.1, 8.4342, 39.092 + 0.7, 43000.0, 24.0, 4317.5, 3816.8, 469.8, 5.6921, 43.175 + 0.7, 43000.0, 26.0, 4706.4, 3991.1, 557.2, 3.9488, 47.064 + 0.7, 43000.0, 30.0, 5522.1, 4329.9, 754.8, 5.704, 55.221 + 0.7, 43000.0, 34.0, 6288.3, 4619.3, 962.3, 7.2124, 62.883 + 0.7, 43000.0, 38.0, 7019.9, 4874.0, 1178.2, 9.0518, 70.199 + 0.7, 43000.0, 42.0, 7734.6, 5111.8, 1396.8, 10.344, 77.346 + 0.7, 43000.0, 46.0, 8435.5, 5335.9, 1624.2, 11.53, 84.355 + 0.7, 43000.0, 48.0, 8778.7, 5440.7, 1745.0, 12.116, 87.787 + 0.7, 43000.0, 50.0, 9121.2, 5544.6, 1865.4, 12.676, 91.212 + 0.75, 20000.0, 21.0, 12099.2, 11578.4, 993.4, 6.5843, 120.992 + 0.75, 20000.0, 22.0, 12724.0, 11890.6, 1129.3, 7.3857, 127.24 + 0.75, 20000.0, 24.0, 13920.6, 12462.1, 1410.5, 8.8599, 139.206 + 0.75, 20000.0, 26.0, 15061.0, 12977.4, 1701.9, 10.327, 150.61 + 0.75, 20000.0, 30.0, 17460.5, 13988.0, 2352.5, 13.498, 174.605 + 0.75, 20000.0, 34.0, 19714.1, 14852.5, 3037.5, 15.9, 197.141 + 0.75, 20000.0, 38.0, 21884.6, 15634.1, 3751.2, 18.01, 218.846 + 0.75, 20000.0, 42.0, 24018.9, 16379.3, 4468.2, 19.85, 240.189 + 0.75, 20000.0, 46.0, 26105.5, 17076.8, 5219.0, 27.25, 261.055 + 0.75, 20000.0, 48.0, 27126.2, 17402.8, 5619.3, 39.528, 271.262 + 0.75, 20000.0, 50.0, 28140.0, 17722.3, 6024.0, 53.01, 281.4 + 0.75, 25000.0, 21.0, 9763.6, 9343.5, 797.1, 5.1492, 97.636 + 0.75, 25000.0, 22.0, 10267.9, 9595.8, 903.1, 5.8999, 102.679 + 0.75, 25000.0, 24.0, 11234.1, 10058.0, 1124.6, 7.2923, 112.341 + 0.75, 25000.0, 26.0, 12154.7, 10474.5, 1353.8, 8.5338, 121.547 + 0.75, 25000.0, 30.0, 14092.2, 11291.8, 1864.8, 11.499, 140.922 + 0.75, 25000.0, 34.0, 15911.3, 11990.8, 2403.1, 13.753, 159.113 + 0.75, 25000.0, 38.0, 17663.3, 12622.6, 2963.2, 15.732, 176.633 + 0.75, 25000.0, 42.0, 19385.8, 13225.0, 3526.7, 17.457, 193.858 + 0.75, 25000.0, 46.0, 21070.1, 13789.1, 4116.3, 19.057, 210.701 + 0.75, 25000.0, 48.0, 21894.0, 14052.8, 4429.6, 19.847, 218.94 + 0.75, 25000.0, 50.0, 22712.7, 14311.6, 4746.3, 24.56, 227.127 + 0.75, 30000.0, 21.0, 7805.4, 7469.7, 636.6, 6.2175, 78.054 + 0.75, 30000.0, 22.0, 8209.2, 7672.0, 718.6, 4.557, 82.092 + 0.75, 30000.0, 24.0, 8982.7, 8042.7, 891.3, 5.7565, 89.827 + 0.75, 30000.0, 26.0, 9719.7, 8376.8, 1069.8, 6.9217, 97.197 + 0.75, 30000.0, 30.0, 11270.2, 9032.1, 1467.1, 9.0687, 112.702 + 0.75, 30000.0, 34.0, 12725.6, 9592.3, 1885.5, 11.645, 127.256 + 0.75, 30000.0, 38.0, 14127.3, 10098.7, 2320.9, 13.494, 141.273 + 0.75, 30000.0, 42.0, 15505.2, 10581.3, 2759.3, 15.102, 155.052 + 0.75, 30000.0, 46.0, 16852.7, 11033.5, 3217.1, 16.592, 168.527 + 0.75, 30000.0, 48.0, 17511.6, 11244.9, 3461.0, 17.331, 175.116 + 0.75, 30000.0, 50.0, 18167.3, 11452.9, 3705.8, 18.044, 181.673 + 0.75, 35000.0, 21.0, 6176.3, 5910.6, 506.6, 9.2124, 61.763 + 0.75, 35000.0, 22.0, 6496.8, 6071.7, 569.8, 7.5518, 64.968 + 0.75, 35000.0, 24.0, 7110.0, 6366.1, 702.3, 4.5131, 71.1 + 0.75, 35000.0, 26.0, 7694.4, 6631.6, 839.8, 5.3704, 76.944 + 0.75, 35000.0, 30.0, 8923.6, 7152.1, 1145.3, 7.3736, 89.236 + 0.75, 35000.0, 34.0, 10077.2, 7597.2, 1467.2, 9.1266, 100.772 + 0.75, 35000.0, 38.0, 11187.9, 7999.4, 1801.8, 11.352, 111.879 + 0.75, 35000.0, 42.0, 12279.4, 8382.4, 2139.1, 12.849, 122.794 + 0.75, 35000.0, 46.0, 13347.0, 8741.4, 2491.2, 14.234, 133.47 + 0.75, 35000.0, 48.0, 13869.4, 8909.5, 2678.5, 14.92, 138.694 + 0.75, 35000.0, 50.0, 14389.1, 9075.0, 2865.5, 15.578, 143.891 + 0.75, 37000.0, 21.0, 5608.1, 5366.7, 464.3, 9.7221, 56.081 + 0.75, 37000.0, 22.0, 5899.7, 5513.5, 521.3, 8.0824, 58.997 + 0.75, 37000.0, 24.0, 6457.4, 5781.4, 640.8, 5.1113, 64.574 + 0.75, 37000.0, 26.0, 6988.6, 6023.0, 764.9, 4.9447, 69.886 + 0.75, 37000.0, 30.0, 8106.0, 6496.6, 1040.5, 6.8848, 81.06 + 0.75, 37000.0, 34.0, 9154.7, 6901.6, 1331.0, 8.58, 91.547 + 0.75, 37000.0, 38.0, 10164.2, 7267.4, 1632.9, 10.7, 101.642 + 0.75, 37000.0, 42.0, 11156.1, 7615.6, 1937.4, 12.149, 111.561 + 0.75, 37000.0, 46.0, 12126.5, 7942.2, 2255.5, 13.485, 121.265 + 0.75, 37000.0, 48.0, 12601.0, 8094.8, 2424.1, 14.146, 126.01 + 0.75, 37000.0, 50.0, 13073.6, 8245.6, 2592.2, 14.778, 130.736 + 0.75, 39000.0, 21.0, 5090.3, 4871.0, 428.1, 9.413, 50.903 + 0.75, 39000.0, 22.0, 5355.6, 5004.7, 479.9, 7.8205, 53.556 + 0.75, 39000.0, 24.0, 5862.7, 5248.6, 588.2, 4.959, 58.627 + 0.75, 39000.0, 26.0, 6345.7, 5468.4, 700.9, 4.7432, 63.457 + 0.75, 39000.0, 30.0, 7361.5, 5899.2, 951.1, 6.612, 73.615 + 0.75, 39000.0, 34.0, 8314.7, 6267.5, 1214.7, 8.2426, 83.147 + 0.75, 39000.0, 38.0, 9232.3, 6600.2, 1488.9, 10.284, 92.323 + 0.75, 39000.0, 42.0, 10133.6, 6916.7, 1765.7, 11.679, 101.336 + 0.75, 39000.0, 46.0, 11015.2, 7213.4, 2054.3, 12.964, 110.152 + 0.75, 39000.0, 48.0, 11446.7, 7352.4, 2207.5, 13.6, 114.467 + 0.75, 39000.0, 50.0, 11876.3, 7489.5, 2360.1, 14.206, 118.763 + 0.75, 41000.0, 21.0, 4620.0, 4420.7, 395.3, 9.1163, 46.2 + 0.75, 41000.0, 22.0, 4861.4, 4542.5, 442.3, 7.5735, 48.614 + 0.75, 41000.0, 24.0, 5322.7, 4764.6, 540.6, 4.8099, 53.227 + 0.75, 41000.0, 26.0, 5761.8, 4964.6, 642.9, 4.5487, 57.618 + 0.75, 41000.0, 30.0, 6685.2, 5356.6, 869.9, 6.3495, 66.852 + 0.75, 41000.0, 34.0, 7551.8, 5691.7, 1109.2, 7.9189, 75.518 + 0.75, 41000.0, 38.0, 8385.8, 5994.3, 1358.1, 9.8824, 83.858 + 0.75, 41000.0, 42.0, 9204.8, 6281.8, 1609.8, 11.227, 92.048 + 0.75, 41000.0, 46.0, 10006.1, 6551.7, 1872.0, 12.464, 100.061 + 0.75, 41000.0, 48.0, 10398.3, 6678.1, 2010.9, 13.074, 103.983 + 0.75, 41000.0, 50.0, 10788.7, 6802.8, 2149.4, 13.657, 107.887 + 0.75, 43000.0, 21.0, 4192.7, 4011.6, 365.5, 8.8388, 41.927 + 0.75, 43000.0, 22.0, 4412.3, 4122.6, 408.2, 7.3458, 44.123 + 0.75, 43000.0, 24.0, 4832.0, 4324.9, 497.1, 4.6778, 48.32 + 0.75, 43000.0, 26.0, 5231.3, 4506.9, 590.1, 4.3594, 52.313 + 0.75, 43000.0, 30.0, 6071.0, 4863.7, 796.3, 6.0969, 60.71 + 0.75, 43000.0, 34.0, 6858.8, 5168.6, 1013.4, 7.606, 68.588 + 0.75, 43000.0, 38.0, 7616.8, 5443.7, 1239.5, 9.4944, 76.168 + 0.75, 43000.0, 42.0, 8361.0, 5705.0, 1468.3, 10.791, 83.61 + 0.75, 43000.0, 46.0, 9089.4, 5950.4, 1706.1, 11.98, 90.894 + 0.75, 43000.0, 48.0, 9445.7, 6065.4, 1832.3, 12.567, 94.457 + 0.75, 43000.0, 50.0, 9800.8, 6179.0, 1958.1, 13.127, 98.008 + 0.79, 20000.0, 21.0, 13316.7, 12788.5, 1056.2, 7.085, 133.167 + 0.79, 20000.0, 22.0, 13958.5, 13113.3, 1191.3, 7.8437, 139.585 + 0.79, 20000.0, 24.0, 15183.9, 13704.9, 1486.2, 9.3251, 151.839 + 0.79, 20000.0, 26.0, 16353.4, 14240.4, 1788.3, 11.26, 163.534 + 0.79, 20000.0, 30.0, 18814.0, 15292.3, 2465.9, 14.02, 188.14 + 0.79, 20000.0, 34.0, 21136.0, 16205.7, 3176.5, 16.425, 211.36 + 0.79, 20000.0, 38.0, 23387.7, 17048.6, 3921.0, 18.548, 233.877 + 0.79, 20000.0, 42.0, 25599.2, 17851.6, 4668.4, 20.401, 255.992 + 0.79, 20000.0, 46.0, 27757.9, 18601.6, 5449.7, 33.71, 277.579 + 0.79, 20000.0, 48.0, 28812.4, 18951.7, 5865.5, 47.623, 288.124 + 0.79, 20000.0, 50.0, 29859.3, 19294.4, 6286.5, 58.771, 298.593 + 0.79, 25000.0, 21.0, 10746.2, 10320.3, 846.3, 5.6217, 107.462 + 0.79, 25000.0, 22.0, 11264.8, 10583.2, 952.1, 6.3348, 112.648 + 0.79, 25000.0, 24.0, 12254.3, 11061.5, 1184.1, 7.73, 122.543 + 0.79, 25000.0, 26.0, 13198.3, 11494.4, 1421.7, 8.9669, 131.983 + 0.79, 25000.0, 30.0, 15184.9, 12345.0, 1954.0, 11.988, 151.849 + 0.79, 25000.0, 34.0, 17059.4, 13083.5, 2512.5, 14.244, 170.594 + 0.79, 25000.0, 38.0, 18877.2, 13765.2, 3097.0, 16.235, 188.772 + 0.79, 25000.0, 42.0, 20662.0, 14414.1, 3683.6, 17.97, 206.62 + 0.79, 25000.0, 46.0, 22404.6, 15020.7, 4297.5, 19.578, 224.046 + 0.79, 25000.0, 48.0, 23255.8, 15303.8, 4623.5, 21.98, 232.558 + 0.79, 25000.0, 50.0, 24101.0, 15581.1, 4952.6, 29.779, 241.01 + 0.79, 30000.0, 21.0, 8591.6, 8251.2, 675.0, 5.0944, 85.916 + 0.79, 30000.0, 22.0, 9006.5, 8461.9, 756.7, 4.8532, 90.065 + 0.79, 30000.0, 24.0, 9798.6, 8845.4, 937.1, 6.1642, 97.986 + 0.79, 30000.0, 26.0, 10554.1, 9192.5, 1122.5, 7.3259, 105.541 + 0.79, 30000.0, 30.0, 12143.7, 9874.3, 1536.0, 9.4741, 121.437 + 0.79, 30000.0, 34.0, 13643.5, 10466.3, 1970.6, 12.102, 136.435 + 0.79, 30000.0, 38.0, 15097.6, 11012.7, 2424.8, 13.96, 150.976 + 0.79, 30000.0, 42.0, 16525.2, 11532.5, 2881.4, 15.578, 165.252 + 0.79, 30000.0, 46.0, 17919.4, 12018.9, 3357.8, 17.075, 179.194 + 0.79, 30000.0, 48.0, 18600.1, 12245.8, 3611.2, 17.815, 186.001 + 0.79, 30000.0, 50.0, 19277.1, 12468.8, 3865.8, 18.526, 192.771 + 0.79, 35000.0, 21.0, 6798.9, 6529.5, 536.1, 8.112, 67.989 + 0.79, 35000.0, 22.0, 7128.1, 6697.1, 598.7, 6.5792, 71.281 + 0.79, 35000.0, 24.0, 7756.4, 7002.1, 737.5, 4.6585, 77.564 + 0.79, 35000.0, 26.0, 8355.2, 7277.7, 880.4, 5.7496, 83.552 + 0.79, 35000.0, 30.0, 9615.4, 7819.4, 1198.4, 7.7528, 96.154 + 0.79, 35000.0, 34.0, 10803.8, 8289.5, 1532.7, 9.805, 108.038 + 0.79, 35000.0, 38.0, 11956.1, 8723.4, 1881.7, 11.784, 119.561 + 0.79, 35000.0, 42.0, 13087.1, 9135.9, 2232.9, 13.288, 130.871 + 0.79, 35000.0, 46.0, 14191.7, 9522.2, 2599.6, 14.681, 141.917 + 0.79, 35000.0, 48.0, 14731.2, 9702.5, 2793.6, 15.367, 147.312 + 0.79, 35000.0, 50.0, 15267.9, 9880.0, 2987.8, 16.024, 152.679 + 0.79, 37000.0, 21.0, 6173.6, 5928.9, 490.9, 8.6418, 61.736 + 0.79, 37000.0, 22.0, 6473.1, 6081.5, 547.1, 7.1362, 64.731 + 0.79, 37000.0, 24.0, 7044.4, 6359.1, 672.3, 4.2757, 70.444 + 0.79, 37000.0, 26.0, 7588.8, 6609.9, 801.5, 5.3123, 75.888 + 0.79, 37000.0, 30.0, 8734.3, 7102.7, 1088.2, 7.2492, 87.343 + 0.79, 37000.0, 34.0, 9814.5, 7530.3, 1389.7, 8.9444, 98.145 + 0.79, 37000.0, 38.0, 10862.0, 7925.1, 1704.9, 11.117, 108.62 + 0.79, 37000.0, 42.0, 11889.7, 8300.2, 2022.2, 12.573, 118.897 + 0.79, 37000.0, 46.0, 12893.6, 8651.4, 2352.9, 13.917, 128.936 + 0.79, 37000.0, 48.0, 13383.9, 8815.5, 2528.3, 14.579, 133.839 + 0.79, 37000.0, 50.0, 13871.8, 8977.0, 2703.4, 15.214, 138.718 + 0.79, 39000.0, 21.0, 5603.8, 5381.5, 452.2, 8.3724, 56.038 + 0.79, 39000.0, 22.0, 5876.3, 5520.5, 503.1, 6.9121, 58.763 + 0.79, 39000.0, 24.0, 6395.9, 5773.3, 616.7, 4.1333, 63.959 + 0.79, 39000.0, 26.0, 6890.8, 6001.3, 734.2, 5.0969, 68.908 + 0.79, 39000.0, 30.0, 7932.0, 6449.6, 994.3, 6.962, 79.32 + 0.79, 39000.0, 34.0, 8914.2, 6838.7, 1268.4, 8.5965, 89.142 + 0.79, 39000.0, 38.0, 9866.0, 7197.6, 1554.3, 10.685, 98.66 + 0.79, 39000.0, 42.0, 10799.9, 7538.5, 1842.4, 12.088, 107.999 + 0.79, 39000.0, 46.0, 11712.2, 7857.8, 2143.1, 13.382, 117.122 + 0.79, 39000.0, 48.0, 12157.8, 8007.0, 2302.2, 14.017, 121.578 + 0.79, 39000.0, 50.0, 12601.3, 8153.9, 2461.0, 14.625, 126.013 + 0.79, 41000.0, 21.0, 5086.2, 4884.2, 417.1, 8.114, 50.862 + 0.79, 41000.0, 22.0, 5334.1, 5010.8, 463.4, 6.7051, 53.341 + 0.79, 41000.0, 24.0, 5806.8, 5241.1, 566.2, 3.9985, 58.068 + 0.79, 41000.0, 26.0, 6256.7, 5448.5, 672.9, 4.8879, 62.567 + 0.79, 41000.0, 30.0, 7203.5, 5856.5, 909.4, 6.6888, 72.035 + 0.79, 41000.0, 34.0, 8096.2, 6210.4, 1158.0, 8.2594, 80.962 + 0.79, 41000.0, 38.0, 8961.4, 6536.8, 1417.5, 10.269, 89.614 + 0.79, 41000.0, 42.0, 9810.0, 6846.6, 1679.3, 11.621, 98.1 + 0.79, 41000.0, 46.0, 10639.2, 7136.9, 1952.5, 12.865, 106.392 + 0.79, 41000.0, 48.0, 11044.2, 7272.6, 2096.9, 13.476, 110.442 + 0.79, 41000.0, 50.0, 11447.3, 7406.3, 2241.1, 14.062, 114.473 + 0.8, 20000.0, 21.0, 13631.6, 13101.2, 1071.7, 7.2066, 136.316 + 0.8, 20000.0, 22.0, 14277.9, 13429.2, 1206.9, 7.9564, 142.779 + 0.8, 20000.0, 24.0, 15511.1, 14025.9, 1505.6, 9.4413, 155.111 + 0.8, 20000.0, 26.0, 16688.8, 14567.1, 1810.3, 11.398, 166.888 + 0.8, 20000.0, 30.0, 19165.5, 15629.4, 2495.5, 14.154, 191.655 + 0.8, 20000.0, 34.0, 21509.9, 16559.4, 3213.1, 16.56, 215.099 + 0.8, 20000.0, 38.0, 23783.7, 17418.7, 3966.3, 18.689, 237.837 + 0.8, 20000.0, 42.0, 26016.0, 18236.5, 4721.8, 20.545, 260.16 + 0.8, 20000.0, 46.0, 28194.2, 19000.4, 5512.1, 35.72, 281.942 + 0.8, 20000.0, 48.0, 29257.3, 19356.5, 5932.0, 49.678, 292.573 + 0.8, 20000.0, 50.0, 30313.1, 19704.9, 6356.8, 59.957, 303.131 + 0.8, 25000.0, 21.0, 11000.5, 10572.8, 858.4, 5.7369, 110.005 + 0.8, 25000.0, 22.0, 11522.8, 10838.4, 964.5, 6.4424, 115.228 + 0.8, 25000.0, 24.0, 12518.5, 11320.9, 1199.4, 7.8407, 125.185 + 0.8, 25000.0, 26.0, 13468.9, 11757.9, 1438.7, 9.0737, 134.689 + 0.8, 25000.0, 30.0, 15468.6, 12617.0, 1976.9, 12.111, 154.686 + 0.8, 25000.0, 34.0, 17361.2, 13369.0, 2541.0, 14.37, 173.612 + 0.8, 25000.0, 38.0, 19196.7, 14063.9, 3132.5, 16.366, 191.967 + 0.8, 25000.0, 42.0, 20998.4, 14725.0, 3725.7, 18.104, 209.984 + 0.8, 25000.0, 46.0, 22756.7, 15342.6, 4346.4, 19.716, 227.567 + 0.8, 25000.0, 48.0, 23614.9, 15630.5, 4675.4, 22.812, 236.149 + 0.8, 25000.0, 50.0, 24467.2, 15912.5, 5007.9, 31.446, 244.672 + 0.8, 30000.0, 21.0, 8794.9, 8453.1, 684.4, 4.8251, 87.949 + 0.8, 30000.0, 22.0, 9212.8, 8666.0, 766.2, 4.9546, 92.128 + 0.8, 30000.0, 24.0, 10009.9, 9052.9, 949.1, 6.2683, 100.099 + 0.8, 30000.0, 26.0, 10770.5, 9403.4, 1135.9, 7.4268, 107.705 + 0.8, 30000.0, 30.0, 12370.4, 10092.0, 1554.2, 9.6026, 123.704 + 0.8, 30000.0, 34.0, 13884.6, 10694.7, 1993.0, 12.219, 138.846 + 0.8, 30000.0, 38.0, 15352.8, 11251.5, 2452.3, 14.081, 153.528 + 0.8, 30000.0, 42.0, 16793.7, 11781.1, 2913.8, 15.701, 167.937 + 0.8, 30000.0, 46.0, 18200.3, 12276.3, 3395.6, 17.201, 182.003 + 0.8, 30000.0, 48.0, 18886.8, 12507.0, 3651.1, 17.94, 188.868 + 0.8, 30000.0, 50.0, 19569.5, 12734.0, 3908.4, 18.652, 195.695 + 0.8, 35000.0, 21.0, 6959.9, 6689.4, 543.4, 7.8502, 69.599 + 0.8, 35000.0, 22.0, 7291.5, 6858.8, 606.0, 6.339, 72.915 + 0.8, 35000.0, 24.0, 7923.7, 7166.4, 746.6, 4.7559, 79.237 + 0.8, 35000.0, 26.0, 8526.5, 7444.7, 890.7, 5.8442, 85.265 + 0.8, 35000.0, 30.0, 9794.9, 7991.8, 1212.3, 7.8493, 97.949 + 0.8, 35000.0, 34.0, 10994.6, 8470.3, 1549.7, 9.9967, 109.946 + 0.8, 35000.0, 38.0, 12158.1, 8912.6, 1902.7, 11.895, 121.581 + 0.8, 35000.0, 42.0, 13299.6, 9332.9, 2257.9, 13.403, 132.996 + 0.8, 35000.0, 46.0, 14413.9, 9725.9, 2628.2, 14.796, 144.139 + 0.8, 35000.0, 48.0, 14958.1, 9909.5, 2824.3, 15.483, 149.581 + 0.8, 35000.0, 50.0, 15499.3, 10090.1, 3020.9, 16.142, 154.993 + 0.8, 37000.0, 21.0, 6319.9, 6074.2, 497.4, 8.3849, 63.199 + 0.8, 37000.0, 22.0, 6621.5, 6228.4, 553.7, 6.9012, 66.215 + 0.8, 37000.0, 24.0, 7196.4, 6508.4, 680.6, 4.3469, 71.964 + 0.8, 37000.0, 26.0, 7744.3, 6761.5, 810.7, 5.4024, 77.443 + 0.8, 37000.0, 30.0, 8897.5, 7259.4, 1100.8, 7.3437, 88.975 + 0.8, 37000.0, 34.0, 9988.0, 7694.8, 1405.5, 9.0829, 99.88 + 0.8, 37000.0, 38.0, 11045.4, 8096.9, 1723.9, 11.224, 110.454 + 0.8, 37000.0, 42.0, 12082.7, 8479.1, 2044.4, 12.682, 120.827 + 0.8, 37000.0, 46.0, 13095.6, 8836.7, 2378.8, 14.03, 130.956 + 0.8, 37000.0, 48.0, 13590.1, 9003.6, 2555.9, 14.692, 135.901 + 0.8, 37000.0, 50.0, 14082.1, 9167.9, 2733.1, 15.327, 140.821 + 0.8, 39000.0, 21.0, 5736.6, 5513.4, 458.1, 8.1251, 57.366 + 0.8, 39000.0, 22.0, 6011.0, 5653.8, 509.0, 6.6908, 60.11 + 0.8, 39000.0, 24.0, 6533.9, 5908.8, 624.2, 4.1644, 65.339 + 0.8, 39000.0, 26.0, 7032.1, 6139.1, 742.6, 5.1849, 70.321 + 0.8, 39000.0, 30.0, 8080.3, 6592.0, 1005.9, 7.0545, 80.803 + 0.8, 39000.0, 34.0, 9071.6, 6988.0, 1282.5, 8.7133, 90.716 + 0.8, 39000.0, 38.0, 10032.7, 7353.7, 1571.6, 10.789, 100.327 + 0.8, 39000.0, 42.0, 10975.1, 7701.0, 1862.9, 12.194, 109.751 + 0.8, 39000.0, 46.0, 11895.7, 8026.0, 2166.6, 13.49, 118.957 + 0.8, 39000.0, 48.0, 12345.1, 8177.9, 2327.3, 14.126, 123.451 + 0.8, 39000.0, 50.0, 12792.3, 8327.3, 2488.0, 14.736, 127.923 + 0.8, 41000.0, 21.0, 5206.8, 5004.0, 422.5, 7.8759, 52.068 + 0.8, 41000.0, 22.0, 5456.4, 5131.9, 468.7, 6.4921, 54.564 + 0.8, 41000.0, 24.0, 5932.1, 5364.1, 573.0, 3.9876, 59.321 + 0.8, 41000.0, 26.0, 6385.0, 5573.6, 680.6, 4.9727, 63.85 + 0.8, 41000.0, 30.0, 7338.1, 5985.7, 919.7, 6.7752, 73.381 + 0.8, 41000.0, 34.0, 8239.2, 6346.0, 1170.8, 8.3569, 82.392 + 0.8, 41000.0, 38.0, 9112.8, 6678.6, 1433.3, 10.37, 91.128 + 0.8, 41000.0, 42.0, 9969.4, 6994.3, 1697.9, 11.724, 99.694 + 0.8, 41000.0, 46.0, 10805.8, 7289.8, 1973.9, 12.969, 108.058 + 0.8, 41000.0, 48.0, 11214.3, 7427.8, 2119.8, 13.581, 112.143 + 0.8, 41000.0, 50.0, 11620.8, 7563.8, 2265.5, 14.167, 116.208 + 0.8, 43000.0, 21.0, 4725.6, 4541.3, 390.2, 7.6384, 47.256 + 0.8, 43000.0, 22.0, 4952.6, 4657.7, 432.1, 6.3043, 49.526 + 0.8, 43000.0, 24.0, 5385.5, 4869.4, 526.6, 3.8166, 53.855 + 0.8, 43000.0, 26.0, 5797.4, 5060.1, 624.5, 4.7702, 57.974 + 0.8, 43000.0, 30.0, 6664.0, 5435.0, 841.4, 6.5063, 66.64 + 0.8, 43000.0, 34.0, 7483.3, 5762.9, 1069.3, 8.0181, 74.833 + 0.8, 43000.0, 38.0, 8277.5, 6065.4, 1307.7, 9.9658, 82.775 + 0.8, 43000.0, 42.0, 9055.9, 6352.3, 1548.6, 11.272, 90.559 + 0.8, 43000.0, 46.0, 9816.3, 6621.1, 1799.0, 12.468, 98.163 + 0.8, 43000.0, 48.0, 10187.6, 6746.6, 1931.5, 13.058, 101.876 + 0.8, 43000.0, 50.0, 10556.9, 6870.2, 2063.5, 13.619, 105.569 + 0.85, 20000.0, 21.0, 15269.7, 14726.9, 1148.4, 7.7963, 152.697 + 0.85, 20000.0, 22.0, 15940.5, 15071.8, 1286.4, 8.5229, 159.405 + 0.85, 20000.0, 24.0, 17216.3, 15696.2, 1605.0, 10.037, 172.163 + 0.85, 20000.0, 26.0, 18437.2, 16265.7, 1923.0, 12.046, 184.372 + 0.85, 20000.0, 30.0, 21018.2, 17399.0, 2650.6, 14.837, 210.182 + 0.85, 20000.0, 34.0, 23493.4, 18426.4, 3408.9, 17.264, 234.934 + 0.85, 20000.0, 38.0, 25884.8, 19370.2, 4206.9, 19.414, 258.848 + 0.85, 20000.0, 42.0, 28229.3, 20267.0, 5007.6, 23.798, 282.293 + 0.85, 20000.0, 46.0, 30511.4, 21101.3, 5843.9, 46.826, 305.114 + 0.85, 20000.0, 48.0, 31623.3, 21489.2, 6287.4, 58.579, 316.233 + 0.85, 20000.0, 50.0, 32726.4, 21868.7, 6737.1, 67.29, 327.264 + 0.85, 25000.0, 21.0, 12322.9, 11885.2, 918.3, 6.2921, 123.229 + 0.85, 25000.0, 22.0, 12864.9, 12164.6, 1027.0, 6.9769, 128.649 + 0.85, 25000.0, 24.0, 13894.8, 12669.2, 1277.4, 8.3905, 138.948 + 0.85, 25000.0, 26.0, 14880.2, 13129.4, 1527.5, 9.6187, 148.802 + 0.85, 25000.0, 30.0, 16963.6, 14045.5, 2098.8, 12.751, 169.636 + 0.85, 25000.0, 34.0, 18961.6, 14876.3, 2695.0, 15.027, 189.616 + 0.85, 25000.0, 38.0, 20891.7, 15639.3, 3321.4, 17.042, 208.917 + 0.85, 25000.0, 42.0, 22783.5, 16363.9, 3949.4, 18.8, 227.835 + 0.85, 25000.0, 46.0, 24625.9, 17039.0, 4606.3, 21.726, 246.259 + 0.85, 25000.0, 48.0, 25523.3, 17352.8, 4953.5, 29.253, 255.233 + 0.85, 25000.0, 50.0, 26413.9, 17659.8, 5304.8, 41.448, 264.139 + 0.85, 30000.0, 21.0, 9852.7, 9503.0, 730.5, 4.817, 98.527 + 0.85, 30000.0, 22.0, 10286.3, 9726.8, 814.8, 5.4569, 102.863 + 0.85, 30000.0, 24.0, 11110.8, 10131.7, 1009.8, 6.7844, 111.108 + 0.85, 30000.0, 26.0, 11899.3, 10500.5, 1204.7, 7.9341, 118.993 + 0.85, 30000.0, 30.0, 13566.3, 11234.9, 1649.0, 10.684, 135.663 + 0.85, 30000.0, 34.0, 15164.4, 11900.5, 2112.4, 12.829, 151.644 + 0.85, 30000.0, 38.0, 16708.5, 12512.1, 2599.3, 14.708, 167.085 + 0.85, 30000.0, 42.0, 18221.3, 13092.4, 3087.7, 16.346, 182.213 + 0.85, 30000.0, 46.0, 19695.1, 13633.6, 3597.6, 17.86, 196.951 + 0.85, 30000.0, 48.0, 20413.3, 13885.5, 3867.4, 18.603, 204.133 + 0.85, 30000.0, 50.0, 21126.4, 14132.3, 4139.7, 19.317, 211.264 + 0.85, 35000.0, 21.0, 7797.5, 7520.8, 578.7, 6.6087, 77.975 + 0.85, 35000.0, 22.0, 8141.8, 7699.1, 643.4, 5.1541, 81.418 + 0.85, 35000.0, 24.0, 8795.7, 8020.9, 793.4, 5.2408, 87.957 + 0.85, 35000.0, 26.0, 9420.6, 8313.7, 943.8, 6.3186, 94.206 + 0.85, 35000.0, 30.0, 10741.8, 8897.0, 1284.8, 8.3419, 107.418 + 0.85, 35000.0, 34.0, 12008.4, 9425.6, 1641.7, 10.725, 120.084 + 0.85, 35000.0, 38.0, 13232.1, 9911.4, 2016.1, 12.477, 132.321 + 0.85, 35000.0, 42.0, 14430.9, 10372.2, 2391.9, 13.999, 144.309 + 0.85, 35000.0, 46.0, 15598.6, 10802.0, 2783.9, 15.406, 155.986 + 0.85, 35000.0, 48.0, 16167.5, 11002.0, 2990.7, 16.095, 161.675 + 0.85, 35000.0, 50.0, 16732.6, 11198.0, 3199.2, 16.758, 167.326 + 0.85, 37000.0, 21.0, 7080.7, 6829.3, 529.2, 7.1696, 70.807 + 0.85, 37000.0, 22.0, 7393.9, 6991.7, 587.4, 5.7449, 73.939 + 0.85, 37000.0, 24.0, 7988.5, 7284.6, 722.8, 4.8169, 79.885 + 0.85, 37000.0, 26.0, 8556.5, 7551.0, 858.6, 5.8624, 85.565 + 0.85, 37000.0, 30.0, 9757.7, 8081.8, 1166.5, 7.8217, 97.577 + 0.85, 37000.0, 34.0, 10908.7, 8562.5, 1488.5, 10.073, 109.087 + 0.85, 37000.0, 38.0, 12020.9, 9004.3, 1826.1, 11.786, 120.209 + 0.85, 37000.0, 42.0, 13110.2, 9423.3, 2165.5, 13.259, 131.102 + 0.85, 37000.0, 46.0, 14171.0, 9813.8, 2518.9, 14.617, 141.71 + 0.85, 37000.0, 48.0, 14688.6, 9996.1, 2705.6, 15.283, 146.886 + 0.85, 37000.0, 50.0, 15202.3, 10174.6, 2893.4, 15.924, 152.023 + 0.85, 39000.0, 21.0, 6427.5, 6199.1, 487.0, 6.9546, 64.275 + 0.85, 39000.0, 22.0, 6712.2, 6346.7, 539.4, 5.589, 67.122 + 0.85, 39000.0, 24.0, 7253.1, 6613.6, 662.4, 4.6165, 72.531 + 0.85, 39000.0, 26.0, 7769.4, 6855.8, 785.8, 5.6258, 77.694 + 0.85, 39000.0, 30.0, 8861.3, 7338.7, 1065.5, 7.514, 88.613 + 0.85, 39000.0, 34.0, 9907.4, 7775.8, 1357.5, 9.6651, 99.074 + 0.85, 39000.0, 38.0, 10918.3, 8177.7, 1664.3, 11.33, 109.183 + 0.85, 39000.0, 42.0, 11908.0, 8558.4, 1972.4, 12.748, 119.08 + 0.85, 39000.0, 46.0, 12872.3, 8913.7, 2293.5, 14.056, 128.723 + 0.85, 39000.0, 48.0, 13342.3, 9079.2, 2463.0, 14.695, 133.423 + 0.85, 39000.0, 50.0, 13809.4, 9241.8, 2633.5, 15.311, 138.094 + 0.9, 35000.0, 21.0, 8689.9, 8405.4, 612.6, 5.4642, 86.899 + 0.9, 35000.0, 22.0, 9048.1, 8592.9, 681.7, 4.4604, 90.481 + 0.9, 35000.0, 24.0, 9727.3, 8930.8, 841.5, 5.7208, 97.273 + 0.9, 35000.0, 26.0, 10383.2, 9245.3, 999.3, 6.7969, 103.832 + 0.9, 35000.0, 30.0, 11785.1, 9888.5, 1365.6, 8.8636, 117.851 + 0.9, 35000.0, 34.0, 13126.8, 10471.6, 1745.1, 11.33, 131.268 + 0.9, 35000.0, 38.0, 14418.8, 11005.1, 2142.8, 13.096, 144.188 + 0.9, 35000.0, 42.0, 15682.3, 11509.9, 2543.0, 14.64, 156.823 + 0.9, 35000.0, 46.0, 16909.5, 11978.5, 2959.3, 16.059, 169.095 + 0.9, 35000.0, 48.0, 17506.0, 12195.7, 3179.8, 16.757, 175.06 + 0.9, 35000.0, 50.0, 18098.7, 12409.1, 3401.9, 17.426, 180.987 + 0.9, 37000.0, 21.0, 7891.3, 7632.9, 559.6, 6.0554, 78.913 + 0.9, 37000.0, 22.0, 8217.1, 7803.6, 621.9, 4.6273, 82.171 + 0.9, 37000.0, 24.0, 8834.9, 8111.3, 766.2, 5.2826, 88.349 + 0.9, 37000.0, 26.0, 9431.0, 8397.2, 908.7, 6.3254, 94.31 + 0.9, 37000.0, 30.0, 10705.5, 8982.6, 1239.4, 8.326, 107.055 + 0.9, 37000.0, 34.0, 11924.9, 9512.8, 1581.3, 10.673, 119.249 + 0.9, 37000.0, 38.0, 13099.4, 9998.1, 1940.8, 12.386, 130.994 + 0.9, 37000.0, 42.0, 14247.6, 10457.1, 2302.0, 13.878, 142.476 + 0.9, 37000.0, 46.0, 15363.1, 10883.5, 2678.2, 15.252, 153.631 + 0.9, 37000.0, 48.0, 15905.5, 11081.3, 2876.5, 15.923, 159.055 + 0.9, 37000.0, 50.0, 16443.8, 11275.0, 3076.2, 16.569, 164.438 + 0.9, 39000.0, 21.0, 7163.6, 6928.7, 514.4, 5.8837, 71.636 + 0.9, 39000.0, 22.0, 7459.9, 7084.2, 570.9, 4.5067, 74.599 + 0.9, 39000.0, 24.0, 8021.6, 7364.1, 701.6, 5.0624, 80.216 + 0.9, 39000.0, 26.0, 8563.7, 7624.5, 831.4, 6.0727, 85.637 + 0.9, 39000.0, 30.0, 9722.3, 8156.9, 1131.6, 7.9996, 97.223 + 0.9, 39000.0, 34.0, 10830.8, 8639.2, 1442.2, 10.258, 108.308 + 0.9, 39000.0, 38.0, 11898.0, 9080.3, 1768.2, 11.906, 118.98 + 0.9, 39000.0, 42.0, 12941.4, 9497.6, 2096.6, 13.345, 129.414 + 0.9, 39000.0, 46.0, 13955.2, 9885.2, 2438.2, 14.667, 139.552 + 0.9, 39000.0, 48.0, 14447.9, 10064.9, 2618.2, 15.313, 144.479 + 0.9, 39000.0, 50.0, 14937.5, 10241.3, 2799.5, 15.933, 149.375 diff --git a/aviary/models/engines/propellers/PropFan.csv b/aviary/models/engines/propellers/PropFan.csv new file mode 100644 index 0000000000..ff6687de42 --- /dev/null +++ b/aviary/models/engines/propellers/PropFan.csv @@ -0,0 +1,1207 @@ +# created 06/06/25 +# GASP-derived propeller map converted from PropFan.map +# Propfan format - CT = f(Mach, Adv Ratio & CP) +# Hamilton Standard 10 Bladed Propfan Performance Deck: Ct Tables + +Mach (input), Power Coefficient (input), Advance Ratio (input), Thrust Coefficient (output) + 0.0, 0.0465, 0.0, 0.122634 + 0.0, 0.0465, 0.2, 0.095985 + 0.0, 0.0465, 0.4, 0.066562 + 0.0, 0.0465, 0.6, 0.044919 + 0.0, 0.0465, 0.8, 0.040928 + 0.0, 0.0465, 1.0, 0.026127 + 0.0, 0.0465, 1.2, 0.023982 + 0.0, 0.0465, 1.4, 0.015 + 0.0, 0.0465, 1.6, 0.003438 + 0.0, 0.0465, 2.0, 0.003328 + 0.0, 0.0465, 2.4, -0.000759 + 0.0, 0.0465, 2.8, -0.006488 + 0.0, 0.2137, 0.0, 0.334586 + 0.0, 0.2137, 0.2, 0.306967 + 0.0, 0.2137, 0.4, 0.272467 + 0.0, 0.2137, 0.6, 0.230461 + 0.0, 0.2137, 0.8, 0.198847 + 0.0, 0.2137, 1.0, 0.169543 + 0.0, 0.2137, 1.2, 0.14786 + 0.0, 0.2137, 1.4, 0.127271 + 0.0, 0.2137, 1.6, 0.102498 + 0.0, 0.2137, 2.0, 0.087057 + 0.0, 0.2137, 2.4, 0.066929 + 0.0, 0.2137, 2.8, 0.052326 + 0.0, 0.3808, 0.0, 0.461205 + 0.0, 0.3808, 0.2, 0.45162 + 0.0, 0.3808, 0.4, 0.415794 + 0.0, 0.3808, 0.6, 0.369702 + 0.0, 0.3808, 0.8, 0.326128 + 0.0, 0.3808, 1.0, 0.287241 + 0.0, 0.3808, 1.2, 0.254097 + 0.0, 0.3808, 1.4, 0.225627 + 0.0, 0.3808, 1.6, 0.201559 + 0.0, 0.3808, 2.0, 0.16052 + 0.0, 0.3808, 2.4, 0.1331 + 0.0, 0.3808, 2.8, 0.110613 + 0.0, 0.548, 0.0, 0.534579 + 0.0, 0.548, 0.2, 0.54768 + 0.0, 0.548, 0.4, 0.518784 + 0.0, 0.548, 0.6, 0.474087 + 0.0, 0.548, 0.8, 0.430277 + 0.0, 0.548, 1.0, 0.387471 + 0.0, 0.548, 1.2, 0.347784 + 0.0, 0.548, 1.4, 0.312717 + 0.0, 0.548, 1.6, 0.281581 + 0.0, 0.548, 2.0, 0.234311 + 0.0, 0.548, 2.4, 0.196755 + 0.0, 0.548, 2.8, 0.166748 + 0.0, 0.7151, 0.0, 0.571583 + 0.0, 0.7151, 0.2, 0.602153 + 0.0, 0.7151, 0.4, 0.591597 + 0.0, 0.7151, 0.6, 0.553517 + 0.0, 0.7151, 0.8, 0.511769 + 0.0, 0.7151, 1.0, 0.47011 + 0.0, 0.7151, 1.2, 0.428481 + 0.0, 0.7151, 1.4, 0.390349 + 0.0, 0.7151, 1.6, 0.355478 + 0.0, 0.7151, 2.0, 0.300715 + 0.0, 0.7151, 2.4, 0.256006 + 0.0, 0.7151, 2.8, 0.220462 + 0.0, 0.8823, 0.0, 0.584088 + 0.0, 0.8823, 0.2, 0.645651 + 0.0, 0.8823, 0.4, 0.643189 + 0.0, 0.8823, 0.6, 0.613761 + 0.0, 0.8823, 0.8, 0.576476 + 0.0, 0.8823, 1.0, 0.535848 + 0.0, 0.8823, 1.2, 0.495633 + 0.0, 0.8823, 1.4, 0.458273 + 0.0, 0.8823, 1.6, 0.423739 + 0.0, 0.8823, 2.0, 0.362646 + 0.0, 0.8823, 2.4, 0.311562 + 0.0, 0.8823, 2.8, 0.270245 + 0.0, 1.0494, 0.0, 0.550644 + 0.0, 1.0494, 0.2, 0.674687 + 0.0, 1.0494, 0.4, 0.68984 + 0.0, 1.0494, 0.6, 0.656975 + 0.0, 1.0494, 0.8, 0.628747 + 0.0, 1.0494, 1.0, 0.589171 + 0.0, 1.0494, 1.2, 0.551827 + 0.0, 1.0494, 1.4, 0.517772 + 0.0, 1.0494, 1.6, 0.481586 + 0.0, 1.0494, 2.0, 0.419952 + 0.0, 1.0494, 2.4, 0.364576 + 0.0, 1.0494, 2.8, 0.318111 + 0.0, 1.2166, 0.0, 0.439453 + 0.0, 1.2166, 0.2, 0.692238 + 0.0, 1.2166, 0.4, 0.726767 + 0.0, 1.2166, 0.6, 0.690066 + 0.0, 1.2166, 0.8, 0.666318 + 0.0, 1.2166, 1.0, 0.63358 + 0.0, 1.2166, 1.2, 0.599146 + 0.0, 1.2166, 1.4, 0.564195 + 0.0, 1.2166, 1.6, 0.531366 + 0.0, 1.2166, 2.0, 0.471772 + 0.0, 1.2166, 2.4, 0.414529 + 0.0, 1.2166, 2.8, 0.364169 + 0.0, 1.3837, 0.0, 0.325011 + 0.0, 1.3837, 0.2, 0.709789 + 0.0, 1.3837, 0.4, 0.75688 + 0.0, 1.3837, 0.6, 0.722315 + 0.0, 1.3837, 0.8, 0.69239 + 0.0, 1.3837, 1.0, 0.66975 + 0.0, 1.3837, 1.2, 0.635255 + 0.0, 1.3837, 1.4, 0.605501 + 0.0, 1.3837, 1.6, 0.575087 + 0.0, 1.3837, 2.0, 0.516929 + 0.0, 1.3837, 2.4, 0.460329 + 0.0, 1.3837, 2.8, 0.408155 + 0.0, 1.5509, 0.0, 0.210569 + 0.0, 1.5509, 0.2, 0.727339 + 0.0, 1.5509, 0.4, 0.769496 + 0.0, 1.5509, 0.6, 0.754055 + 0.0, 1.5509, 0.8, 0.715055 + 0.0, 1.5509, 1.0, 0.696096 + 0.0, 1.5509, 1.2, 0.667957 + 0.0, 1.5509, 1.4, 0.642314 + 0.0, 1.5509, 1.6, 0.610222 + 0.0, 1.5509, 2.0, 0.555857 + 0.0, 1.5509, 2.4, 0.501971 + 0.0, 1.5509, 2.8, 0.449725 + 0.0, 1.718, 0.0, 0.096127 + 0.0, 1.718, 0.2, 0.74489 + 0.0, 1.718, 0.4, 0.775735 + 0.0, 1.718, 0.6, 0.765359 + 0.0, 1.718, 0.8, 0.738421 + 0.0, 1.718, 1.0, 0.7136 + 0.0, 1.718, 1.2, 0.696094 + 0.0, 1.718, 1.4, 0.668449 + 0.0, 1.718, 1.6, 0.643122 + 0.0, 1.718, 2.0, 0.589 + 0.0, 1.718, 2.4, 0.538383 + 0.0, 1.718, 2.8, 0.487828 + 0.0, 1.8852, 0.0, -0.018315 + 0.0, 1.8852, 0.2, 0.762441 + 0.0, 1.8852, 0.4, 0.781974 + 0.0, 1.8852, 0.6, 0.776662 + 0.0, 1.8852, 0.8, 0.748482 + 0.0, 1.8852, 1.0, 0.727936 + 0.0, 1.8852, 1.2, 0.711712 + 0.0, 1.8852, 1.4, 0.690797 + 0.0, 1.8852, 1.6, 0.666296 + 0.0, 1.8852, 2.0, 0.617565 + 0.0, 1.8852, 2.4, 0.570733 + 0.0, 1.8852, 2.8, 0.522422 + 0.0, 2.0523, 0.0, -0.132757 + 0.0, 2.0523, 0.2, 0.779992 + 0.0, 2.0523, 0.4, 0.788214 + 0.0, 2.0523, 0.6, 0.787966 + 0.0, 2.0523, 0.8, 0.754657 + 0.0, 2.0523, 1.0, 0.736096 + 0.0, 2.0523, 1.2, 0.721107 + 0.0, 2.0523, 1.4, 0.705706 + 0.0, 2.0523, 1.6, 0.686994 + 0.0, 2.0523, 2.0, 0.644894 + 0.0, 2.0523, 2.4, 0.602184 + 0.0, 2.0523, 2.8, 0.553482 + 0.0, 2.2195, 0.0, -0.247199 + 0.0, 2.2195, 0.2, 0.797542 + 0.0, 2.2195, 0.4, 0.794453 + 0.0, 2.2195, 0.6, 0.799269 + 0.0, 2.2195, 0.8, 0.760832 + 0.0, 2.2195, 1.0, 0.740302 + 0.0, 2.2195, 1.2, 0.730186 + 0.0, 2.2195, 1.4, 0.720616 + 0.0, 2.2195, 1.6, 0.700047 + 0.0, 2.2195, 2.0, 0.672223 + 0.0, 2.2195, 2.4, 0.633636 + 0.0, 2.2195, 2.8, 0.581251 + 0.0, 2.3866, 0.0, -0.361641 + 0.0, 2.3866, 0.2, 0.815093 + 0.0, 2.3866, 0.4, 0.800692 + 0.0, 2.3866, 0.6, 0.810573 + 0.0, 2.3866, 0.8, 0.767008 + 0.0, 2.3866, 1.0, 0.744509 + 0.0, 2.3866, 1.2, 0.739265 + 0.0, 2.3866, 1.4, 0.735525 + 0.0, 2.3866, 1.6, 0.7131 + 0.0, 2.3866, 2.0, 0.699552 + 0.0, 2.3866, 2.4, 0.665087 + 0.0, 2.3866, 2.8, 0.6061 + 0.25, 0.0465, 0.0, 0.122634 + 0.25, 0.0465, 0.2, 0.095985 + 0.25, 0.0465, 0.4, 0.066562 + 0.25, 0.0465, 0.6, 0.044919 + 0.25, 0.0465, 0.8, 0.040928 + 0.25, 0.0465, 1.0, 0.026127 + 0.25, 0.0465, 1.2, 0.023982 + 0.25, 0.0465, 1.4, 0.015 + 0.25, 0.0465, 1.6, 0.003438 + 0.25, 0.0465, 2.0, 0.003328 + 0.25, 0.0465, 2.4, -0.000759 + 0.25, 0.0465, 2.8, -0.006488 + 0.25, 0.2137, 0.0, 0.334586 + 0.25, 0.2137, 0.2, 0.306967 + 0.25, 0.2137, 0.4, 0.272467 + 0.25, 0.2137, 0.6, 0.230461 + 0.25, 0.2137, 0.8, 0.198847 + 0.25, 0.2137, 1.0, 0.169543 + 0.25, 0.2137, 1.2, 0.14786 + 0.25, 0.2137, 1.4, 0.127271 + 0.25, 0.2137, 1.6, 0.102498 + 0.25, 0.2137, 2.0, 0.087057 + 0.25, 0.2137, 2.4, 0.066929 + 0.25, 0.2137, 2.8, 0.052326 + 0.25, 0.3808, 0.0, 0.461205 + 0.25, 0.3808, 0.2, 0.45162 + 0.25, 0.3808, 0.4, 0.415794 + 0.25, 0.3808, 0.6, 0.369702 + 0.25, 0.3808, 0.8, 0.326128 + 0.25, 0.3808, 1.0, 0.287241 + 0.25, 0.3808, 1.2, 0.254097 + 0.25, 0.3808, 1.4, 0.225627 + 0.25, 0.3808, 1.6, 0.201559 + 0.25, 0.3808, 2.0, 0.16052 + 0.25, 0.3808, 2.4, 0.1331 + 0.25, 0.3808, 2.8, 0.110613 + 0.25, 0.548, 0.0, 0.534579 + 0.25, 0.548, 0.2, 0.54768 + 0.25, 0.548, 0.4, 0.518784 + 0.25, 0.548, 0.6, 0.474087 + 0.25, 0.548, 0.8, 0.430277 + 0.25, 0.548, 1.0, 0.387471 + 0.25, 0.548, 1.2, 0.347784 + 0.25, 0.548, 1.4, 0.312717 + 0.25, 0.548, 1.6, 0.281581 + 0.25, 0.548, 2.0, 0.234311 + 0.25, 0.548, 2.4, 0.196755 + 0.25, 0.548, 2.8, 0.166748 + 0.25, 0.7151, 0.0, 0.571583 + 0.25, 0.7151, 0.2, 0.602153 + 0.25, 0.7151, 0.4, 0.591597 + 0.25, 0.7151, 0.6, 0.553517 + 0.25, 0.7151, 0.8, 0.511769 + 0.25, 0.7151, 1.0, 0.47011 + 0.25, 0.7151, 1.2, 0.428481 + 0.25, 0.7151, 1.4, 0.390349 + 0.25, 0.7151, 1.6, 0.355478 + 0.25, 0.7151, 2.0, 0.300715 + 0.25, 0.7151, 2.4, 0.256006 + 0.25, 0.7151, 2.8, 0.220462 + 0.25, 0.8823, 0.0, 0.584088 + 0.25, 0.8823, 0.2, 0.645651 + 0.25, 0.8823, 0.4, 0.643189 + 0.25, 0.8823, 0.6, 0.613761 + 0.25, 0.8823, 0.8, 0.576476 + 0.25, 0.8823, 1.0, 0.535848 + 0.25, 0.8823, 1.2, 0.495633 + 0.25, 0.8823, 1.4, 0.458273 + 0.25, 0.8823, 1.6, 0.423739 + 0.25, 0.8823, 2.0, 0.362646 + 0.25, 0.8823, 2.4, 0.311562 + 0.25, 0.8823, 2.8, 0.270245 + 0.25, 1.0494, 0.0, 0.550644 + 0.25, 1.0494, 0.2, 0.674687 + 0.25, 1.0494, 0.4, 0.68984 + 0.25, 1.0494, 0.6, 0.656975 + 0.25, 1.0494, 0.8, 0.628747 + 0.25, 1.0494, 1.0, 0.589171 + 0.25, 1.0494, 1.2, 0.551827 + 0.25, 1.0494, 1.4, 0.517772 + 0.25, 1.0494, 1.6, 0.481586 + 0.25, 1.0494, 2.0, 0.419952 + 0.25, 1.0494, 2.4, 0.364576 + 0.25, 1.0494, 2.8, 0.318111 + 0.25, 1.2166, 0.0, 0.439453 + 0.25, 1.2166, 0.2, 0.692238 + 0.25, 1.2166, 0.4, 0.726767 + 0.25, 1.2166, 0.6, 0.690066 + 0.25, 1.2166, 0.8, 0.666318 + 0.25, 1.2166, 1.0, 0.63358 + 0.25, 1.2166, 1.2, 0.599146 + 0.25, 1.2166, 1.4, 0.564195 + 0.25, 1.2166, 1.6, 0.531366 + 0.25, 1.2166, 2.0, 0.471772 + 0.25, 1.2166, 2.4, 0.414529 + 0.25, 1.2166, 2.8, 0.364169 + 0.25, 1.3837, 0.0, 0.325011 + 0.25, 1.3837, 0.2, 0.709789 + 0.25, 1.3837, 0.4, 0.75688 + 0.25, 1.3837, 0.6, 0.722315 + 0.25, 1.3837, 0.8, 0.69239 + 0.25, 1.3837, 1.0, 0.66975 + 0.25, 1.3837, 1.2, 0.635255 + 0.25, 1.3837, 1.4, 0.605501 + 0.25, 1.3837, 1.6, 0.575087 + 0.25, 1.3837, 2.0, 0.516929 + 0.25, 1.3837, 2.4, 0.460329 + 0.25, 1.3837, 2.8, 0.408155 + 0.25, 1.5509, 0.0, 0.210569 + 0.25, 1.5509, 0.2, 0.727339 + 0.25, 1.5509, 0.4, 0.769496 + 0.25, 1.5509, 0.6, 0.754055 + 0.25, 1.5509, 0.8, 0.715055 + 0.25, 1.5509, 1.0, 0.696096 + 0.25, 1.5509, 1.2, 0.667957 + 0.25, 1.5509, 1.4, 0.642314 + 0.25, 1.5509, 1.6, 0.610222 + 0.25, 1.5509, 2.0, 0.555857 + 0.25, 1.5509, 2.4, 0.501971 + 0.25, 1.5509, 2.8, 0.449725 + 0.25, 1.718, 0.0, 0.096127 + 0.25, 1.718, 0.2, 0.74489 + 0.25, 1.718, 0.4, 0.775735 + 0.25, 1.718, 0.6, 0.765359 + 0.25, 1.718, 0.8, 0.738421 + 0.25, 1.718, 1.0, 0.7136 + 0.25, 1.718, 1.2, 0.696094 + 0.25, 1.718, 1.4, 0.668449 + 0.25, 1.718, 1.6, 0.643122 + 0.25, 1.718, 2.0, 0.589 + 0.25, 1.718, 2.4, 0.538383 + 0.25, 1.718, 2.8, 0.487828 + 0.25, 1.8852, 0.0, -0.018315 + 0.25, 1.8852, 0.2, 0.762441 + 0.25, 1.8852, 0.4, 0.781974 + 0.25, 1.8852, 0.6, 0.776662 + 0.25, 1.8852, 0.8, 0.748482 + 0.25, 1.8852, 1.0, 0.727936 + 0.25, 1.8852, 1.2, 0.711712 + 0.25, 1.8852, 1.4, 0.690797 + 0.25, 1.8852, 1.6, 0.666296 + 0.25, 1.8852, 2.0, 0.617565 + 0.25, 1.8852, 2.4, 0.570733 + 0.25, 1.8852, 2.8, 0.522422 + 0.25, 2.0523, 0.0, -0.132757 + 0.25, 2.0523, 0.2, 0.779992 + 0.25, 2.0523, 0.4, 0.788214 + 0.25, 2.0523, 0.6, 0.787966 + 0.25, 2.0523, 0.8, 0.754657 + 0.25, 2.0523, 1.0, 0.736096 + 0.25, 2.0523, 1.2, 0.721107 + 0.25, 2.0523, 1.4, 0.705706 + 0.25, 2.0523, 1.6, 0.686994 + 0.25, 2.0523, 2.0, 0.644894 + 0.25, 2.0523, 2.4, 0.602184 + 0.25, 2.0523, 2.8, 0.553482 + 0.25, 2.2195, 0.0, -0.247199 + 0.25, 2.2195, 0.2, 0.797542 + 0.25, 2.2195, 0.4, 0.794453 + 0.25, 2.2195, 0.6, 0.799269 + 0.25, 2.2195, 0.8, 0.760832 + 0.25, 2.2195, 1.0, 0.740302 + 0.25, 2.2195, 1.2, 0.730186 + 0.25, 2.2195, 1.4, 0.720616 + 0.25, 2.2195, 1.6, 0.700047 + 0.25, 2.2195, 2.0, 0.672223 + 0.25, 2.2195, 2.4, 0.633636 + 0.25, 2.2195, 2.8, 0.581251 + 0.25, 2.3866, 0.0, -0.361641 + 0.25, 2.3866, 0.2, 0.815093 + 0.25, 2.3866, 0.4, 0.800692 + 0.25, 2.3866, 0.6, 0.810573 + 0.25, 2.3866, 0.8, 0.767008 + 0.25, 2.3866, 1.0, 0.744509 + 0.25, 2.3866, 1.2, 0.739265 + 0.25, 2.3866, 1.4, 0.735525 + 0.25, 2.3866, 1.6, 0.7131 + 0.25, 2.3866, 2.0, 0.699552 + 0.25, 2.3866, 2.4, 0.665087 + 0.25, 2.3866, 2.8, 0.6061 + 0.55, 0.1943, 2.0, 0.095051 + 0.55, 0.1943, 2.2, 0.071348 + 0.55, 0.1943, 2.4, 0.084495 + 0.55, 0.1943, 2.6, 0.04935 + 0.55, 0.1943, 2.8, 0.042556 + 0.55, 0.1943, 3.0, 0.036789 + 0.55, 0.1943, 3.2, 0.0291 + 0.55, 0.1943, 3.4, 0.024314 + 0.55, 0.3671, 2.0, 0.165081 + 0.55, 0.3671, 2.2, 0.143396 + 0.55, 0.3671, 2.4, 0.140262 + 0.55, 0.3671, 2.6, 0.116429 + 0.55, 0.3671, 2.8, 0.104972 + 0.55, 0.3671, 3.0, 0.094598 + 0.55, 0.3671, 3.2, 0.084901 + 0.55, 0.3671, 3.4, 0.075708 + 0.55, 0.5399, 2.0, 0.23511 + 0.55, 0.5399, 2.2, 0.214859 + 0.55, 0.5399, 2.4, 0.196642 + 0.55, 0.5399, 2.6, 0.180371 + 0.55, 0.5399, 2.8, 0.165257 + 0.55, 0.5399, 3.0, 0.15181 + 0.55, 0.5399, 3.2, 0.138861 + 0.55, 0.5399, 3.4, 0.127103 + 0.55, 0.7127, 2.0, 0.303485 + 0.55, 0.7127, 2.2, 0.280226 + 0.55, 0.7127, 2.4, 0.259289 + 0.55, 0.7127, 2.6, 0.24039 + 0.55, 0.7127, 2.8, 0.222216 + 0.55, 0.7127, 3.0, 0.206041 + 0.55, 0.7127, 3.2, 0.19044 + 0.55, 0.7127, 3.4, 0.176114 + 0.55, 0.8855, 2.0, 0.367171 + 0.55, 0.8855, 2.2, 0.340886 + 0.55, 0.8855, 2.4, 0.317341 + 0.55, 0.8855, 2.6, 0.296258 + 0.55, 0.8855, 2.8, 0.275915 + 0.55, 0.8855, 3.0, 0.257375 + 0.55, 0.8855, 3.2, 0.239678 + 0.55, 0.8855, 3.4, 0.223209 + 0.55, 1.0583, 2.0, 0.426518 + 0.55, 1.0583, 2.2, 0.398307 + 0.55, 1.0583, 2.4, 0.372074 + 0.55, 1.0583, 2.6, 0.348642 + 0.55, 1.0583, 2.8, 0.326551 + 0.55, 1.0583, 3.0, 0.306085 + 0.55, 1.0583, 3.2, 0.287021 + 0.55, 1.0583, 3.4, 0.268568 + 0.55, 1.2311, 2.0, 0.481744 + 0.55, 1.2311, 2.2, 0.45193 + 0.55, 1.2311, 2.4, 0.424074 + 0.55, 1.2311, 2.6, 0.398655 + 0.55, 1.2311, 2.8, 0.374667 + 0.55, 1.2311, 3.0, 0.352496 + 0.55, 1.2311, 3.2, 0.331617 + 0.55, 1.2311, 3.4, 0.312453 + 0.55, 1.4039, 2.0, 0.534008 + 0.55, 1.4039, 2.2, 0.502094 + 0.55, 1.4039, 2.4, 0.473089 + 0.55, 1.4039, 2.6, 0.446355 + 0.55, 1.4039, 2.8, 0.420795 + 0.55, 1.4039, 3.0, 0.388187 + 0.55, 1.4039, 3.2, 0.374658 + 0.55, 1.4039, 3.4, 0.353868 + 0.55, 1.5768, 2.0, 0.582501 + 0.55, 1.5768, 2.2, 0.549919 + 0.55, 1.5768, 2.4, 0.519217 + 0.55, 1.5768, 2.6, 0.491355 + 0.55, 1.5768, 2.8, 0.465026 + 0.55, 1.5768, 3.0, 0.409649 + 0.55, 1.5768, 3.2, 0.416324 + 0.55, 1.5768, 3.4, 0.393655 + 0.55, 1.7496, 2.0, 0.629046 + 0.55, 1.7496, 2.2, 0.594429 + 0.55, 1.7496, 2.4, 0.563787 + 0.55, 1.7496, 2.6, 0.533867 + 0.55, 1.7496, 2.8, 0.506669 + 0.55, 1.7496, 3.0, 0.43111 + 0.55, 1.7496, 3.2, 0.456303 + 0.55, 1.7496, 3.4, 0.43261 + 0.55, 1.9224, 2.0, 0.680686 + 0.55, 1.9224, 2.2, 0.636503 + 0.55, 1.9224, 2.4, 0.608102 + 0.55, 1.9224, 2.6, 0.576217 + 0.55, 1.9224, 2.8, 0.546231 + 0.55, 1.9224, 3.0, 0.503909 + 0.55, 1.9224, 3.2, 0.494194 + 0.55, 1.9224, 3.4, 0.470156 + 0.55, 2.0952, 2.0, 0.732326 + 0.55, 2.0952, 2.2, 0.678577 + 0.55, 2.0952, 2.4, 0.652417 + 0.55, 2.0952, 2.6, 0.618566 + 0.55, 2.0952, 2.8, 0.585606 + 0.55, 2.0952, 3.0, 0.55667 + 0.55, 2.0952, 3.2, 0.530669 + 0.55, 2.0952, 3.4, 0.506565 + 0.55, 2.268, 2.0, 0.783966 + 0.55, 2.268, 2.2, 0.72065 + 0.55, 2.268, 2.4, 0.696732 + 0.55, 2.268, 2.6, 0.660915 + 0.55, 2.268, 2.8, 0.624981 + 0.55, 2.268, 3.0, 0.592957 + 0.55, 2.268, 3.2, 0.565809 + 0.55, 2.268, 3.4, 0.540246 + 0.55, 2.4408, 2.0, 0.835606 + 0.55, 2.4408, 2.2, 0.762724 + 0.55, 2.4408, 2.4, 0.741046 + 0.55, 2.4408, 2.6, 0.703264 + 0.55, 2.4408, 2.8, 0.664356 + 0.55, 2.4408, 3.0, 0.629244 + 0.55, 2.4408, 3.2, 0.601095 + 0.55, 2.4408, 3.4, 0.572992 + 0.55, 2.6136, 2.0, 0.887247 + 0.55, 2.6136, 2.2, 0.804798 + 0.55, 2.6136, 2.4, 0.785361 + 0.55, 2.6136, 2.6, 0.745613 + 0.55, 2.6136, 2.8, 0.703731 + 0.55, 2.6136, 3.0, 0.665532 + 0.55, 2.6136, 3.2, 0.636383 + 0.55, 2.6136, 3.4, 0.605 + 0.6, 0.1965, 2.2, 0.082777 + 0.6, 0.1965, 2.4, 0.063291 + 0.6, 0.1965, 2.6, 0.050137 + 0.6, 0.1965, 2.8, 0.04336 + 0.6, 0.1965, 3.0, 0.03741 + 0.6, 0.1965, 3.2, 0.0277 + 0.6, 0.1965, 3.4, 0.024935 + 0.6, 0.1965, 3.6, 0.017674 + 0.6, 0.3801, 2.2, 0.153398 + 0.6, 0.3801, 2.4, 0.134668 + 0.6, 0.3801, 2.6, 0.121356 + 0.6, 0.3801, 2.8, 0.109602 + 0.6, 0.3801, 3.0, 0.0988 + 0.6, 0.3801, 3.2, 0.086876 + 0.6, 0.3801, 3.4, 0.079452 + 0.6, 0.3801, 3.6, 0.070116 + 0.6, 0.5637, 2.2, 0.224019 + 0.6, 0.5637, 2.4, 0.205456 + 0.6, 0.5637, 2.6, 0.188873 + 0.6, 0.5637, 2.8, 0.173269 + 0.6, 0.5637, 3.0, 0.159221 + 0.6, 0.5637, 3.2, 0.145387 + 0.6, 0.5637, 3.4, 0.133872 + 0.6, 0.5637, 3.6, 0.121578 + 0.6, 0.7473, 2.2, 0.292555 + 0.6, 0.7473, 2.4, 0.271166 + 0.6, 0.7473, 2.6, 0.25177 + 0.6, 0.7473, 2.8, 0.233184 + 0.6, 0.7473, 3.0, 0.216286 + 0.6, 0.7473, 3.2, 0.200275 + 0.6, 0.7473, 3.4, 0.185717 + 0.6, 0.7473, 3.6, 0.171648 + 0.6, 0.931, 2.2, 0.356123 + 0.6, 0.931, 2.4, 0.331904 + 0.6, 0.931, 2.6, 0.310002 + 0.6, 0.931, 2.8, 0.289411 + 0.6, 0.931, 3.0, 0.270575 + 0.6, 0.931, 3.2, 0.251972 + 0.6, 0.931, 3.4, 0.235012 + 0.6, 0.931, 3.6, 0.218814 + 0.6, 1.1146, 2.2, 0.415047 + 0.6, 1.1146, 2.4, 0.389307 + 0.6, 1.1146, 2.6, 0.364888 + 0.6, 1.1146, 2.8, 0.342314 + 0.6, 1.1146, 3.0, 0.321483 + 0.6, 1.1146, 3.2, 0.301686 + 0.6, 1.1146, 3.4, 0.282614 + 0.6, 1.1146, 3.6, 0.264782 + 0.6, 1.2982, 2.2, 0.467139 + 0.6, 1.2982, 2.4, 0.4435 + 0.6, 1.2982, 2.6, 0.417089 + 0.6, 1.2982, 2.8, 0.392629 + 0.6, 1.2982, 3.0, 0.371077 + 0.6, 1.2982, 3.2, 0.348568 + 0.6, 1.2982, 3.4, 0.329055 + 0.6, 1.2982, 3.6, 0.309485 + 0.6, 1.4818, 2.2, 0.523202 + 0.6, 1.4818, 2.4, 0.494257 + 0.6, 1.4818, 2.6, 0.466574 + 0.6, 1.4818, 2.8, 0.440732 + 0.6, 1.4818, 3.0, 0.416591 + 0.6, 1.4818, 3.2, 0.393115 + 0.6, 1.4818, 3.4, 0.371643 + 0.6, 1.4818, 3.6, 0.350791 + 0.6, 1.6654, 2.2, 0.572961 + 0.6, 1.6654, 2.4, 0.541895 + 0.6, 1.6654, 2.6, 0.513242 + 0.6, 1.6654, 2.8, 0.486389 + 0.6, 1.6654, 3.0, 0.460847 + 0.6, 1.6654, 3.2, 0.436458 + 0.6, 1.6654, 3.4, 0.415498 + 0.6, 1.6654, 3.6, 0.391393 + 0.6, 1.849, 2.2, 0.618348 + 0.6, 1.849, 2.4, 0.588873 + 0.6, 1.849, 2.6, 0.557886 + 0.6, 1.849, 2.8, 0.529488 + 0.6, 1.849, 3.0, 0.503149 + 0.6, 1.849, 3.2, 0.478407 + 0.6, 1.849, 3.4, 0.460166 + 0.6, 1.849, 3.6, 0.431296 + 0.6, 2.0326, 2.2, 0.662625 + 0.6, 2.0326, 2.4, 0.635852 + 0.6, 2.0326, 2.6, 0.60253 + 0.6, 2.0326, 2.8, 0.570845 + 0.6, 2.0326, 3.0, 0.543546 + 0.6, 2.0326, 3.2, 0.517791 + 0.6, 2.0326, 3.4, 0.494837 + 0.6, 2.0326, 3.6, 0.469079 + 0.6, 2.2163, 2.2, 0.706901 + 0.6, 2.2163, 2.4, 0.682831 + 0.6, 2.2163, 2.6, 0.647175 + 0.6, 2.2163, 2.8, 0.612203 + 0.6, 2.2163, 3.0, 0.581799 + 0.6, 2.2163, 3.2, 0.555153 + 0.6, 2.2163, 3.4, 0.530052 + 0.6, 2.2163, 3.6, 0.505772 + 0.6, 2.3999, 2.2, 0.751178 + 0.6, 2.3999, 2.4, 0.729809 + 0.6, 2.3999, 2.6, 0.691819 + 0.6, 2.3999, 2.8, 0.653561 + 0.6, 2.3999, 3.0, 0.620052 + 0.6, 2.3999, 3.2, 0.591663 + 0.6, 2.3999, 3.4, 0.565394 + 0.6, 2.3999, 3.6, 0.540336 + 0.6, 2.5835, 2.2, 0.795454 + 0.6, 2.5835, 2.4, 0.776788 + 0.6, 2.5835, 2.6, 0.736463 + 0.6, 2.5835, 2.8, 0.694919 + 0.6, 2.5835, 3.0, 0.658305 + 0.6, 2.5835, 3.2, 0.627654 + 0.6, 2.5835, 3.4, 0.599255 + 0.6, 2.5835, 3.6, 0.573576 + 0.6, 2.7671, 2.2, 0.839731 + 0.6, 2.7671, 2.4, 0.823766 + 0.6, 2.7671, 2.6, 0.781107 + 0.6, 2.7671, 2.8, 0.736277 + 0.6, 2.7671, 3.0, 0.696558 + 0.6, 2.7671, 3.2, 0.663645 + 0.6, 2.7671, 3.4, 0.633116 + 0.6, 2.7671, 3.6, 0.606 + 0.65, 0.1988, 2.4, 0.0646 + 0.65, 0.1988, 2.6, 0.051141 + 0.65, 0.1988, 2.8, 0.044082 + 0.65, 0.1988, 3.0, 0.038172 + 0.65, 0.1988, 3.2, 0.0303 + 0.65, 0.1988, 3.4, 0.025509 + 0.65, 0.1988, 3.6, 0.017231 + 0.65, 0.1988, 3.8, 0.014182 + 0.65, 0.419, 2.4, 0.149797 + 0.65, 0.419, 2.6, 0.136186 + 0.65, 0.419, 2.8, 0.123546 + 0.65, 0.419, 3.0, 0.111668 + 0.65, 0.419, 3.2, 0.101227 + 0.65, 0.419, 3.4, 0.090842 + 0.65, 0.419, 3.6, 0.080751 + 0.65, 0.419, 3.8, 0.071806 + 0.65, 0.6391, 2.4, 0.232833 + 0.65, 0.6391, 2.6, 0.215617 + 0.65, 0.6391, 2.8, 0.198403 + 0.65, 0.6391, 3.0, 0.182684 + 0.65, 0.6391, 3.2, 0.169023 + 0.65, 0.6391, 3.4, 0.155019 + 0.65, 0.6391, 3.6, 0.141856 + 0.65, 0.6391, 3.8, 0.129429 + 0.65, 0.8593, 2.4, 0.308646 + 0.65, 0.8593, 2.6, 0.288255 + 0.65, 0.8593, 2.8, 0.267931 + 0.65, 0.8593, 3.0, 0.249188 + 0.65, 0.8593, 3.2, 0.232202 + 0.65, 0.8593, 3.4, 0.216101 + 0.65, 0.8593, 3.6, 0.20018 + 0.65, 0.8593, 3.8, 0.185312 + 0.65, 1.0795, 2.4, 0.378135 + 0.65, 1.0795, 2.6, 0.354365 + 0.65, 1.0795, 2.8, 0.332832 + 0.65, 1.0795, 3.0, 0.311499 + 0.65, 1.0795, 3.2, 0.292263 + 0.65, 1.0795, 3.4, 0.273701 + 0.65, 1.0795, 3.6, 0.255937 + 0.65, 1.0795, 3.8, 0.239092 + 0.65, 1.2996, 2.4, 0.443359 + 0.65, 1.2996, 2.6, 0.417532 + 0.65, 1.2996, 2.8, 0.393798 + 0.65, 1.2996, 3.0, 0.37006 + 0.65, 1.2996, 3.2, 0.348693 + 0.65, 1.2996, 3.4, 0.32906 + 0.65, 1.2996, 3.6, 0.309425 + 0.65, 1.2996, 3.8, 0.289531 + 0.65, 1.5198, 2.4, 0.50398 + 0.65, 1.5198, 2.6, 0.476151 + 0.65, 1.5198, 2.8, 0.450132 + 0.65, 1.5198, 3.0, 0.425682 + 0.65, 1.5198, 3.2, 0.402471 + 0.65, 1.5198, 3.4, 0.381151 + 0.65, 1.5198, 3.6, 0.359062 + 0.65, 1.5198, 3.8, 0.335254 + 0.65, 1.74, 2.4, 0.560251 + 0.65, 1.74, 2.6, 0.531119 + 0.65, 1.74, 2.8, 0.503845 + 0.65, 1.74, 3.0, 0.478165 + 0.65, 1.74, 3.2, 0.453777 + 0.65, 1.74, 3.4, 0.430482 + 0.65, 1.74, 3.6, 0.407363 + 0.65, 1.74, 3.8, 0.381386 + 0.65, 1.9601, 2.4, 0.615385 + 0.65, 1.9601, 2.6, 0.583506 + 0.65, 1.9601, 2.8, 0.55421 + 0.65, 1.9601, 3.0, 0.527534 + 0.65, 1.9601, 3.2, 0.502146 + 0.65, 1.9601, 3.4, 0.477689 + 0.65, 1.9601, 3.6, 0.454343 + 0.65, 1.9601, 3.8, 0.430581 + 0.65, 2.1803, 2.4, 0.67052 + 0.65, 2.1803, 2.6, 0.635396 + 0.65, 2.1803, 2.8, 0.603297 + 0.65, 2.1803, 3.0, 0.574261 + 0.65, 2.1803, 3.2, 0.5478 + 0.65, 2.1803, 3.4, 0.52296 + 0.65, 2.1803, 3.6, 0.498733 + 0.65, 2.1803, 3.8, 0.473638 + 0.65, 2.4004, 2.4, 0.725654 + 0.65, 2.4004, 2.6, 0.687286 + 0.65, 2.4004, 2.8, 0.652385 + 0.65, 2.4004, 3.0, 0.619868 + 0.65, 2.4004, 3.2, 0.591937 + 0.65, 2.4004, 3.4, 0.565392 + 0.65, 2.4004, 3.6, 0.54016 + 0.65, 2.4004, 3.8, 0.515289 + 0.65, 2.6206, 2.4, 0.780789 + 0.65, 2.6206, 2.6, 0.739176 + 0.65, 2.6206, 2.8, 0.701473 + 0.65, 2.6206, 3.0, 0.665475 + 0.65, 2.6206, 3.2, 0.636074 + 0.65, 2.6206, 3.4, 0.607824 + 0.65, 2.6206, 3.6, 0.581187 + 0.65, 2.6206, 3.8, 0.555929 + 0.65, 2.8408, 2.4, 0.835923 + 0.65, 2.8408, 2.6, 0.791066 + 0.65, 2.8408, 2.8, 0.750561 + 0.65, 2.8408, 3.0, 0.711082 + 0.65, 2.8408, 3.2, 0.680212 + 0.65, 2.8408, 3.4, 0.650255 + 0.65, 2.8408, 3.6, 0.622215 + 0.65, 2.8408, 3.8, 0.59269 + 0.65, 3.0609, 2.4, 0.891057 + 0.65, 3.0609, 2.6, 0.842956 + 0.65, 3.0609, 2.8, 0.799649 + 0.65, 3.0609, 3.0, 0.756689 + 0.65, 3.0609, 3.2, 0.724349 + 0.65, 3.0609, 3.4, 0.692687 + 0.65, 3.0609, 3.6, 0.663243 + 0.65, 3.0609, 3.8, 0.629162 + 0.65, 3.2811, 2.4, 0.946192 + 0.65, 3.2811, 2.6, 0.894846 + 0.65, 3.2811, 2.8, 0.848737 + 0.65, 3.2811, 3.0, 0.802295 + 0.65, 3.2811, 3.2, 0.768486 + 0.65, 3.2811, 3.4, 0.735119 + 0.65, 3.2811, 3.6, 0.70427 + 0.65, 3.2811, 3.8, 0.6654 + 0.7, 0.2019, 2.6, 0.057422 + 0.7, 0.2019, 2.8, 0.045251 + 0.7, 0.2019, 3.0, 0.035573 + 0.7, 0.2019, 3.2, 0.0312 + 0.7, 0.2019, 3.4, 0.026212 + 0.7, 0.2019, 3.6, 0.01884 + 0.7, 0.2019, 3.8, 0.01863 + 0.7, 0.2019, 4.0, 0.007229 + 0.7, 0.2019, 4.2, -0.00021 + 0.7, 0.4143, 2.6, 0.134532 + 0.7, 0.4143, 2.8, 0.121564 + 0.7, 0.4143, 3.0, 0.112426 + 0.7, 0.4143, 3.2, 0.099495 + 0.7, 0.4143, 3.4, 0.089202 + 0.7, 0.4143, 3.6, 0.079332 + 0.7, 0.4143, 3.8, 0.07072 + 0.7, 0.4143, 4.0, 0.060543 + 0.7, 0.4143, 4.2, 0.050923 + 0.7, 0.6267, 2.6, 0.210844 + 0.7, 0.6267, 2.8, 0.193987 + 0.7, 0.6267, 3.0, 0.182135 + 0.7, 0.6267, 3.2, 0.164963 + 0.7, 0.6267, 3.4, 0.15085 + 0.7, 0.6267, 3.6, 0.138227 + 0.7, 0.6267, 3.8, 0.12281 + 0.7, 0.6267, 4.0, 0.113858 + 0.7, 0.6267, 4.2, 0.102056 + 0.7, 0.8392, 2.6, 0.280777 + 0.7, 0.8392, 2.8, 0.261699 + 0.7, 0.8392, 3.0, 0.243057 + 0.7, 0.8392, 3.2, 0.226179 + 0.7, 0.8392, 3.4, 0.208382 + 0.7, 0.8392, 3.6, 0.194922 + 0.7, 0.8392, 3.8, 0.176527 + 0.7, 0.8392, 4.0, 0.165679 + 0.7, 0.8392, 4.2, 0.151711 + 0.7, 1.0516, 2.6, 0.345646 + 0.7, 1.0516, 2.8, 0.324324 + 0.7, 1.0516, 3.0, 0.303706 + 0.7, 1.0516, 3.2, 0.284337 + 0.7, 1.0516, 3.4, 0.265725 + 0.7, 1.0516, 3.6, 0.248775 + 0.7, 1.0516, 3.8, 0.232366 + 0.7, 1.0516, 4.0, 0.216063 + 0.7, 1.0516, 4.2, 0.199785 + 0.7, 1.264, 2.6, 0.406984 + 0.7, 1.264, 2.8, 0.383203 + 0.7, 1.264, 3.0, 0.360547 + 0.7, 1.264, 3.2, 0.339358 + 0.7, 1.264, 3.4, 0.319611 + 0.7, 1.264, 3.6, 0.30027 + 0.7, 1.264, 3.8, 0.281815 + 0.7, 1.264, 4.0, 0.262995 + 0.7, 1.264, 4.2, 0.24555 + 0.7, 1.4764, 2.6, 0.464518 + 0.7, 1.4764, 2.8, 0.439202 + 0.7, 1.4764, 3.0, 0.414706 + 0.7, 1.4764, 3.2, 0.391633 + 0.7, 1.4764, 3.4, 0.37072 + 0.7, 1.4764, 3.6, 0.349106 + 0.7, 1.4764, 3.8, 0.329089 + 0.7, 1.4764, 4.0, 0.309096 + 0.7, 1.4764, 4.2, 0.290563 + 0.7, 1.6888, 2.6, 0.5183 + 0.7, 1.6888, 2.8, 0.491645 + 0.7, 1.6888, 3.0, 0.466167 + 0.7, 1.6888, 3.2, 0.441749 + 0.7, 1.6888, 3.4, 0.419265 + 0.7, 1.6888, 3.6, 0.395724 + 0.7, 1.6888, 3.8, 0.374331 + 0.7, 1.6888, 4.0, 0.354014 + 0.7, 1.6888, 4.2, 0.333626 + 0.7, 1.9013, 2.6, 0.569375 + 0.7, 1.9013, 2.8, 0.541054 + 0.7, 1.9013, 3.0, 0.514454 + 0.7, 1.9013, 3.2, 0.489799 + 0.7, 1.9013, 3.4, 0.465315 + 0.7, 1.9013, 3.6, 0.440677 + 0.7, 1.9013, 3.8, 0.418789 + 0.7, 1.9013, 4.0, 0.396464 + 0.7, 1.9013, 4.2, 0.375742 + 0.7, 2.1137, 2.6, 0.617486 + 0.7, 2.1137, 2.8, 0.588323 + 0.7, 2.1137, 3.0, 0.56022 + 0.7, 2.1137, 3.2, 0.534178 + 0.7, 2.1137, 3.4, 0.509161 + 0.7, 2.1137, 3.6, 0.484425 + 0.7, 2.1137, 3.8, 0.4615 + 0.7, 2.1137, 4.0, 0.437791 + 0.7, 2.1137, 4.2, 0.415256 + 0.7, 2.3261, 2.6, 0.665347 + 0.7, 2.3261, 2.8, 0.635593 + 0.7, 2.3261, 3.0, 0.600821 + 0.7, 2.3261, 3.2, 0.576443 + 0.7, 2.3261, 3.4, 0.550662 + 0.7, 2.3261, 3.6, 0.52493 + 0.7, 2.3261, 3.8, 0.50232 + 0.7, 2.3261, 4.0, 0.478104 + 0.7, 2.3261, 4.2, 0.454244 + 0.7, 2.5385, 2.6, 0.713207 + 0.7, 2.5385, 2.8, 0.682863 + 0.7, 2.5385, 3.0, 0.641422 + 0.7, 2.5385, 3.2, 0.618486 + 0.7, 2.5385, 3.4, 0.590714 + 0.7, 2.5385, 3.6, 0.560496 + 0.7, 2.5385, 3.8, 0.540481 + 0.7, 2.5385, 4.0, 0.51691 + 0.7, 2.5385, 4.2, 0.49267 + 0.7, 2.751, 2.6, 0.761068 + 0.7, 2.751, 2.8, 0.730133 + 0.7, 2.751, 3.0, 0.682023 + 0.7, 2.751, 3.2, 0.660528 + 0.7, 2.751, 3.4, 0.630051 + 0.7, 2.751, 3.6, 0.600672 + 0.7, 2.751, 3.8, 0.577365 + 0.7, 2.751, 4.0, 0.553283 + 0.7, 2.751, 4.2, 0.528695 + 0.7, 2.9634, 2.6, 0.808929 + 0.7, 2.9634, 2.8, 0.777403 + 0.7, 2.9634, 3.0, 0.722624 + 0.7, 2.9634, 3.2, 0.702571 + 0.7, 2.9634, 3.4, 0.669389 + 0.7, 2.9634, 3.6, 0.641153 + 0.7, 2.9634, 3.8, 0.612482 + 0.7, 2.9634, 4.0, 0.58759 + 0.7, 2.9634, 4.2, 0.563587 + 0.7, 3.1758, 2.6, 0.856789 + 0.7, 3.1758, 2.8, 0.824673 + 0.7, 3.1758, 3.0, 0.763224 + 0.7, 3.1758, 3.2, 0.744614 + 0.7, 3.1758, 3.4, 0.708726 + 0.7, 3.1758, 3.6, 0.681634 + 0.7, 3.1758, 3.8, 0.647599 + 0.7, 3.1758, 4.0, 0.621 + 0.7, 3.1758, 4.2, 0.598478 + 0.75, 0.2329, 2.8, 0.05657 + 0.75, 0.2329, 3.0, 0.045131 + 0.75, 0.2329, 3.2, 0.044235 + 0.75, 0.2329, 3.4, 0.035292 + 0.75, 0.2329, 3.6, 0.0274 + 0.75, 0.2329, 3.8, 0.02277 + 0.75, 0.2329, 4.0, 0.014648 + 0.75, 0.2329, 4.2, 0.007632 + 0.75, 0.2329, 4.4, -0.000595 + 0.75, 0.4804, 2.8, 0.144945 + 0.75, 0.4804, 3.0, 0.137513 + 0.75, 0.4804, 3.2, 0.119778 + 0.75, 0.4804, 3.4, 0.108461 + 0.75, 0.4804, 3.6, 0.090983 + 0.75, 0.4804, 3.8, 0.087228 + 0.75, 0.4804, 4.0, 0.076607 + 0.75, 0.4804, 4.2, 0.065893 + 0.75, 0.4804, 4.4, 0.056112 + 0.75, 0.728, 2.8, 0.226204 + 0.75, 0.728, 3.0, 0.211461 + 0.75, 0.728, 3.2, 0.194192 + 0.75, 0.728, 3.4, 0.179193 + 0.75, 0.728, 3.6, 0.163055 + 0.75, 0.728, 3.8, 0.151687 + 0.75, 0.728, 4.0, 0.138566 + 0.75, 0.728, 4.2, 0.124154 + 0.75, 0.728, 4.4, 0.112818 + 0.75, 0.9755, 2.8, 0.301561 + 0.75, 0.9755, 3.0, 0.282465 + 0.75, 0.9755, 3.2, 0.263404 + 0.75, 0.9755, 3.4, 0.245733 + 0.75, 0.9755, 3.6, 0.228946 + 0.75, 0.9755, 3.8, 0.212905 + 0.75, 0.9755, 4.0, 0.197301 + 0.75, 0.9755, 4.2, 0.181239 + 0.75, 0.9755, 4.4, 0.166801 + 0.75, 1.2231, 2.8, 0.371143 + 0.75, 1.2231, 3.0, 0.349669 + 0.75, 1.2231, 3.2, 0.328637 + 0.75, 1.2231, 3.4, 0.308795 + 0.75, 1.2231, 3.6, 0.28914 + 0.75, 1.2231, 3.8, 0.27152 + 0.75, 1.2231, 4.0, 0.253381 + 0.75, 1.2231, 4.2, 0.236229 + 0.75, 1.2231, 4.4, 0.215149 + 0.75, 1.4706, 2.8, 0.436835 + 0.75, 1.4706, 3.0, 0.412805 + 0.75, 1.4706, 3.2, 0.389659 + 0.75, 1.4706, 3.4, 0.368615 + 0.75, 1.4706, 3.6, 0.346546 + 0.75, 1.4706, 3.8, 0.327372 + 0.75, 1.4706, 4.0, 0.307358 + 0.75, 1.4706, 4.2, 0.288416 + 0.75, 1.4706, 4.4, 0.237918 + 0.75, 1.7182, 2.8, 0.497859 + 0.75, 1.7182, 3.0, 0.472752 + 0.75, 1.7182, 3.2, 0.447146 + 0.75, 1.7182, 3.4, 0.424492 + 0.75, 1.7182, 3.6, 0.401578 + 0.75, 1.7182, 3.8, 0.380005 + 0.75, 1.7182, 4.0, 0.360748 + 0.75, 1.7182, 4.2, 0.338667 + 0.75, 1.7182, 4.4, 0.286849 + 0.75, 1.9657, 2.8, 0.554716 + 0.75, 1.9657, 3.0, 0.528032 + 0.75, 1.9657, 3.2, 0.502776 + 0.75, 1.9657, 3.4, 0.478361 + 0.75, 1.9657, 3.6, 0.453378 + 0.75, 1.9657, 3.8, 0.43082 + 0.75, 1.9657, 4.0, 0.409375 + 0.75, 1.9657, 4.2, 0.39154 + 0.75, 1.9657, 4.4, 0.360591 + 0.75, 2.2132, 2.8, 0.609468 + 0.75, 2.2132, 3.0, 0.580434 + 0.75, 2.2132, 3.2, 0.55384 + 0.75, 2.2132, 3.4, 0.528285 + 0.75, 2.2132, 3.6, 0.503617 + 0.75, 2.2132, 3.8, 0.479512 + 0.75, 2.2132, 4.0, 0.455722 + 0.75, 2.2132, 4.2, 0.449955 + 0.75, 2.2132, 4.4, 0.410322 + 0.75, 2.4608, 2.8, 0.6642 + 0.75, 2.4608, 3.0, 0.632836 + 0.75, 2.4608, 3.2, 0.604904 + 0.75, 2.4608, 3.4, 0.575453 + 0.75, 2.4608, 3.6, 0.550292 + 0.75, 2.4608, 3.8, 0.525573 + 0.75, 2.4608, 4.0, 0.501128 + 0.75, 2.4608, 4.2, 0.486949 + 0.75, 2.4608, 4.4, 0.455027 + 0.75, 2.7083, 2.8, 0.718931 + 0.75, 2.7083, 3.0, 0.685238 + 0.75, 2.7083, 3.2, 0.655968 + 0.75, 2.7083, 3.4, 0.621203 + 0.75, 2.7083, 3.6, 0.594506 + 0.75, 2.7083, 3.8, 0.56794 + 0.75, 2.7083, 4.0, 0.544309 + 0.75, 2.7083, 4.2, 0.519824 + 0.75, 2.7083, 4.4, 0.496362 + 0.75, 2.9559, 2.8, 0.773663 + 0.75, 2.9559, 3.0, 0.737639 + 0.75, 2.9559, 3.2, 0.707032 + 0.75, 2.9559, 3.4, 0.666535 + 0.75, 2.9559, 3.6, 0.637817 + 0.75, 2.9559, 3.8, 0.609912 + 0.75, 2.9559, 4.0, 0.585641 + 0.75, 2.9559, 4.2, 0.560674 + 0.75, 2.9559, 4.4, 0.536369 + 0.75, 3.2034, 2.8, 0.828394 + 0.75, 3.2034, 3.0, 0.790041 + 0.75, 3.2034, 3.2, 0.758096 + 0.75, 3.2034, 3.4, 0.711867 + 0.75, 3.2034, 3.6, 0.681127 + 0.75, 3.2034, 3.8, 0.651847 + 0.75, 3.2034, 4.0, 0.624267 + 0.75, 3.2034, 4.2, 0.599079 + 0.75, 3.2034, 4.4, 0.574783 + 0.75, 3.451, 2.8, 0.883126 + 0.75, 3.451, 3.0, 0.842443 + 0.75, 3.451, 3.2, 0.80916 + 0.75, 3.451, 3.4, 0.757199 + 0.75, 3.451, 3.6, 0.724437 + 0.75, 3.451, 3.8, 0.693781 + 0.75, 3.451, 4.0, 0.662893 + 0.75, 3.451, 4.2, 0.635875 + 0.75, 3.451, 4.4, 0.610573 + 0.75, 3.6985, 2.8, 0.937857 + 0.75, 3.6985, 3.0, 0.894845 + 0.75, 3.6985, 3.2, 0.860223 + 0.75, 3.6985, 3.4, 0.802531 + 0.75, 3.6985, 3.6, 0.767747 + 0.75, 3.6985, 3.8, 0.735715 + 0.75, 3.6985, 4.0, 0.701519 + 0.75, 3.6985, 4.2, 0.67267 + 0.75, 3.6985, 4.4, 0.6454 + 0.8, 0.1324, 2.8, 0.020882 + 0.8, 0.1324, 3.0, 0.0132 + 0.8, 0.1324, 3.2, 0.008737 + 0.8, 0.1324, 3.4, 0.006144 + 0.8, 0.1324, 3.6, -0.001478 + 0.8, 0.1324, 3.8, -0.002662 + 0.8, 0.1324, 4.0, -0.010844 + 0.8, 0.3493, 2.8, 0.097679 + 0.8, 0.3493, 3.0, 0.088055 + 0.8, 0.3493, 3.2, 0.078083 + 0.8, 0.3493, 3.4, 0.06972 + 0.8, 0.3493, 3.6, 0.059986 + 0.8, 0.3493, 3.8, 0.053252 + 0.8, 0.3493, 4.0, 0.04323 + 0.8, 0.5662, 2.8, 0.172739 + 0.8, 0.5662, 3.0, 0.159487 + 0.8, 0.5662, 3.2, 0.145541 + 0.8, 0.5662, 3.4, 0.133296 + 0.8, 0.5662, 3.6, 0.120902 + 0.8, 0.5662, 3.8, 0.109167 + 0.8, 0.5662, 4.0, 0.097304 + 0.8, 0.7832, 2.8, 0.242396 + 0.8, 0.7832, 3.0, 0.225694 + 0.8, 0.7832, 3.2, 0.209422 + 0.8, 0.7832, 3.4, 0.193829 + 0.8, 0.7832, 3.6, 0.179296 + 0.8, 0.7832, 3.8, 0.165082 + 0.8, 0.7832, 4.0, 0.151114 + 0.8, 1.0001, 2.8, 0.307342 + 0.8, 1.0001, 3.0, 0.288178 + 0.8, 1.0001, 3.2, 0.269515 + 0.8, 1.0001, 3.4, 0.251438 + 0.8, 1.0001, 3.6, 0.234194 + 0.8, 1.0001, 3.8, 0.217884 + 0.8, 1.0001, 4.0, 0.201995 + 0.8, 1.217, 2.8, 0.367938 + 0.8, 1.217, 3.0, 0.346721 + 0.8, 1.217, 3.2, 0.326686 + 0.8, 1.217, 3.4, 0.306308 + 0.8, 1.217, 3.6, 0.286895 + 0.8, 1.217, 3.8, 0.26843 + 0.8, 1.217, 4.0, 0.251119 + 0.8, 1.4339, 2.8, 0.425328 + 0.8, 1.4339, 3.0, 0.402191 + 0.8, 1.4339, 3.2, 0.380135 + 0.8, 1.4339, 3.4, 0.358573 + 0.8, 1.4339, 3.6, 0.337671 + 0.8, 1.4339, 3.8, 0.316648 + 0.8, 1.4339, 4.0, 0.298142 + 0.8, 1.6509, 2.8, 0.479596 + 0.8, 1.6509, 3.0, 0.454974 + 0.8, 1.6509, 3.2, 0.431353 + 0.8, 1.6509, 3.4, 0.408349 + 0.8, 1.6509, 3.6, 0.385628 + 0.8, 1.6509, 3.8, 0.364866 + 0.8, 1.6509, 4.0, 0.343109 + 0.8, 1.8678, 2.8, 0.530464 + 0.8, 1.8678, 3.0, 0.504883 + 0.8, 1.8678, 3.2, 0.480025 + 0.8, 1.8678, 3.4, 0.456178 + 0.8, 1.8678, 3.6, 0.432252 + 0.8, 1.8678, 3.8, 0.409655 + 0.8, 1.8678, 4.0, 0.387343 + 0.8, 2.0847, 2.8, 0.57847 + 0.8, 2.0847, 3.0, 0.55211 + 0.8, 2.0847, 3.2, 0.526199 + 0.8, 2.0847, 3.4, 0.501827 + 0.8, 2.0847, 3.6, 0.477312 + 0.8, 2.0847, 3.8, 0.45403 + 0.8, 2.0847, 4.0, 0.429986 + 0.8, 2.3016, 2.8, 0.624966 + 0.8, 2.3016, 3.0, 0.597871 + 0.8, 2.3016, 3.2, 0.570167 + 0.8, 2.3016, 3.4, 0.544569 + 0.8, 2.3016, 3.6, 0.51757 + 0.8, 2.3016, 3.8, 0.495366 + 0.8, 2.3016, 4.0, 0.471003 + 0.8, 2.5185, 2.8, 0.671462 + 0.8, 2.5185, 3.0, 0.643632 + 0.8, 2.5185, 3.2, 0.612593 + 0.8, 2.5185, 3.4, 0.585042 + 0.8, 2.5185, 3.6, 0.557991 + 0.8, 2.5185, 3.8, 0.535235 + 0.8, 2.5185, 4.0, 0.509799 + 0.8, 2.7355, 2.8, 0.717958 + 0.8, 2.7355, 3.0, 0.689393 + 0.8, 2.7355, 3.2, 0.655019 + 0.8, 2.7355, 3.4, 0.624813 + 0.8, 2.7355, 3.6, 0.598509 + 0.8, 2.7355, 3.8, 0.572361 + 0.8, 2.7355, 4.0, 0.547046 + 0.8, 2.9524, 2.8, 0.764454 + 0.8, 2.9524, 3.0, 0.735153 + 0.8, 2.9524, 3.2, 0.697445 + 0.8, 2.9524, 3.4, 0.664149 + 0.8, 2.9524, 3.6, 0.639027 + 0.8, 2.9524, 3.8, 0.608752 + 0.8, 2.9524, 4.0, 0.583631 + 0.8, 3.1693, 2.8, 0.81095 + 0.8, 3.1693, 3.0, 0.780914 + 0.8, 3.1693, 3.2, 0.739871 + 0.8, 3.1693, 3.4, 0.703485 + 0.8, 3.1693, 3.6, 0.679545 + 0.8, 3.1693, 3.8, 0.6447 + 0.8, 3.1693, 4.0, 0.620217 + 0.85, 0.1324, 2.8, 0.020671 + 0.85, 0.1324, 3.0, 0.013068 + 0.85, 0.1324, 3.2, 0.0087 + 0.85, 0.1324, 3.4, 0.006044 + 0.85, 0.1324, 3.6, -0.001488 + 0.85, 0.1324, 3.8, -0.002672 + 0.85, 0.1324, 4.0, -0.010944 + 0.85, 0.3493, 2.8, 0.0967 + 0.85, 0.3493, 3.0, 0.08717 + 0.85, 0.3493, 3.2, 0.0773 + 0.85, 0.3493, 3.4, 0.069055 + 0.85, 0.3493, 3.6, 0.0594 + 0.85, 0.3493, 3.8, 0.052719 + 0.85, 0.3493, 4.0, 0.0428 + 0.85, 0.5662, 2.8, 0.170967 + 0.85, 0.5662, 3.0, 0.15789 + 0.85, 0.5662, 3.2, 0.144123 + 0.85, 0.5662, 3.4, 0.132153 + 0.85, 0.5662, 3.6, 0.119777 + 0.85, 0.5662, 3.8, 0.108196 + 0.85, 0.5662, 4.0, 0.096374 + 0.85, 0.7832, 2.8, 0.240022 + 0.85, 0.7832, 3.0, 0.223437 + 0.85, 0.7832, 3.2, 0.207199 + 0.85, 0.7832, 3.4, 0.191896 + 0.85, 0.7832, 3.6, 0.17775 + 0.85, 0.7832, 3.8, 0.163436 + 0.85, 0.7832, 4.0, 0.149656 + 0.85, 1.0001, 2.8, 0.304266 + 0.85, 1.0001, 3.0, 0.285296 + 0.85, 1.0001, 3.2, 0.266876 + 0.85, 1.0001, 3.4, 0.248967 + 0.85, 1.0001, 3.6, 0.231866 + 0.85, 1.0001, 3.8, 0.215708 + 0.85, 1.0001, 4.0, 0.200001 + 0.85, 1.217, 2.8, 0.364275 + 0.85, 1.217, 3.0, 0.343255 + 0.85, 1.217, 3.2, 0.323419 + 0.85, 1.217, 3.4, 0.303246 + 0.85, 1.217, 3.6, 0.28413 + 0.85, 1.217, 3.8, 0.265745 + 0.85, 1.217, 4.0, 0.24868 + 0.85, 1.4339, 2.8, 0.421276 + 0.85, 1.4339, 3.0, 0.398178 + 0.85, 1.4339, 3.2, 0.376339 + 0.85, 1.4339, 3.4, 0.35498 + 0.85, 1.4339, 3.6, 0.334293 + 0.85, 1.4339, 3.8, 0.313335 + 0.85, 1.4339, 4.0, 0.295161 + 0.85, 1.6509, 2.8, 0.474804 + 0.85, 1.6509, 3.0, 0.45045 + 0.85, 1.6509, 3.2, 0.427088 + 0.85, 1.6509, 3.4, 0.40427 + 0.85, 1.6509, 3.6, 0.381774 + 0.85, 1.6509, 3.8, 0.361255 + 0.85, 1.6509, 4.0, 0.339679 + 0.85, 1.8678, 2.8, 0.525195 + 0.85, 1.8678, 3.0, 0.500001 + 0.85, 1.8678, 3.2, 0.47525 + 0.85, 1.8678, 3.4, 0.451687 + 0.85, 1.8678, 3.6, 0.428199 + 0.85, 1.8678, 3.8, 0.40565 + 0.85, 1.8678, 4.0, 0.383466 + 0.85, 2.0847, 2.8, 0.572715 + 0.85, 2.0847, 3.0, 0.546678 + 0.85, 2.0847, 3.2, 0.520938 + 0.85, 2.0847, 3.4, 0.496832 + 0.85, 2.0847, 3.6, 0.472539 + 0.85, 2.0847, 3.8, 0.449556 + 0.85, 2.0847, 4.0, 0.4257 + 0.85, 2.3016, 2.8, 0.61875 + 0.85, 2.3016, 3.0, 0.591895 + 0.85, 2.3016, 3.2, 0.564498 + 0.85, 2.3016, 3.4, 0.539125 + 0.85, 2.3016, 3.6, 0.512394 + 0.85, 2.3016, 3.8, 0.490446 + 0.85, 2.3016, 4.0, 0.466785 + 0.85, 2.5185, 2.8, 0.664785 + 0.85, 2.5185, 3.0, 0.637263 + 0.85, 2.5185, 3.2, 0.606474 + 0.85, 2.5185, 3.4, 0.579249 + 0.85, 2.5185, 3.6, 0.5524 + 0.85, 2.5185, 3.8, 0.529898 + 0.85, 2.5185, 4.0, 0.504702 + 0.85, 2.7355, 2.8, 0.710815 + 0.85, 2.7355, 3.0, 0.682506 + 0.85, 2.7355, 3.2, 0.648549 + 0.85, 2.7355, 3.4, 0.618602 + 0.85, 2.7355, 3.6, 0.592641 + 0.85, 2.7355, 3.8, 0.566676 + 0.85, 2.7355, 4.0, 0.541629 + 0.85, 2.9524, 2.8, 0.756806 + 0.85, 2.9524, 3.0, 0.727848 + 0.85, 2.9524, 3.2, 0.690525 + 0.85, 2.9524, 3.4, 0.657585 + 0.85, 2.9524, 3.6, 0.632719 + 0.85, 2.9524, 3.8, 0.602712 + 0.85, 2.9524, 4.0, 0.57816 + 0.85, 3.1693, 2.8, 0.802396 + 0.85, 3.1693, 3.0, 0.773111 + 0.85, 3.1693, 3.2, 0.7326 + 0.85, 3.1693, 3.4, 0.696465 + 0.85, 3.1693, 3.6, 0.672804 + 0.85, 3.1693, 3.8, 0.638253 + 0.85, 3.1693, 4.0, 0.614025 + \ No newline at end of file diff --git a/aviary/models/propellers/PropFan.map b/aviary/models/engines/propellers/PropFan.map similarity index 100% rename from aviary/models/propellers/PropFan.map rename to aviary/models/engines/propellers/PropFan.map diff --git a/aviary/models/engines/propellers/general_aviation.csv b/aviary/models/engines/propellers/general_aviation.csv new file mode 100644 index 0000000000..657711be99 --- /dev/null +++ b/aviary/models/engines/propellers/general_aviation.csv @@ -0,0 +1,438 @@ +# created 06/23/25 at 17:13 +# GASP-derived propeller map converted from general_aviation.map +# CT = f(Helical Mach at 75% Radius, Adv ratio & CP) +# No. Blades = 3. CLi = 0.62 AF = 104.0 + +Helical Mach (input), Power Coefficient (input), Advance Ratio (input), Thrust Coefficient (output) + 0.7, 0.025, 0.001, 0.1442 + 0.7, 0.025, 0.5, 0.0368 + 0.7, 0.025, 0.75, 0.0254 + 0.7, 0.025, 1.0, 0.0204 + 0.7, 0.025, 1.3, 0.0174 + 0.7, 0.025, 1.6, 0.0129 + 0.7, 0.05, 0.001, 0.1595 + 0.7, 0.05, 0.5, 0.071 + 0.7, 0.05, 0.75, 0.0522 + 0.7, 0.05, 1.0, 0.0413 + 0.7, 0.05, 1.3, 0.0323 + 0.7, 0.05, 1.6, 0.0259 + 0.7, 0.075, 0.001, 0.1762 + 0.7, 0.075, 0.5, 0.1001 + 0.7, 0.075, 0.75, 0.0766 + 0.7, 0.075, 1.0, 0.0615 + 0.7, 0.075, 1.3, 0.0491 + 0.7, 0.075, 1.6, 0.0404 + 0.7, 0.1, 0.001, 0.1887 + 0.7, 0.1, 0.5, 0.1207 + 0.7, 0.1, 0.75, 0.0983 + 0.7, 0.1, 1.0, 0.0806 + 0.7, 0.1, 1.3, 0.0649 + 0.7, 0.1, 1.6, 0.054 + 0.7, 0.125, 0.001, 0.1985 + 0.7, 0.125, 0.5, 0.1359 + 0.7, 0.125, 0.75, 0.1159 + 0.7, 0.125, 1.0, 0.0983 + 0.7, 0.125, 1.3, 0.0803 + 0.7, 0.125, 1.6, 0.0671 + 0.7, 0.15, 0.001, 0.2075 + 0.7, 0.15, 0.5, 0.1464 + 0.7, 0.15, 0.75, 0.1298 + 0.7, 0.15, 1.0, 0.1135 + 0.7, 0.15, 1.3, 0.0949 + 0.7, 0.15, 1.6, 0.08 + 0.7, 0.175, 0.001, 0.2179 + 0.7, 0.175, 0.5, 0.1542 + 0.7, 0.175, 0.75, 0.1404 + 0.7, 0.175, 1.0, 0.1261 + 0.7, 0.175, 1.3, 0.1082 + 0.7, 0.175, 1.6, 0.0923 + 0.7, 0.2, 0.001, 0.2248 + 0.7, 0.2, 0.5, 0.1603 + 0.7, 0.2, 0.75, 0.1481 + 0.7, 0.2, 1.0, 0.1367 + 0.7, 0.2, 1.3, 0.12 + 0.7, 0.2, 1.6, 0.1041 + 0.7, 0.225, 0.001, 0.2302 + 0.7, 0.225, 0.5, 0.1647 + 0.7, 0.225, 0.75, 0.1542 + 0.7, 0.225, 1.0, 0.1449 + 0.7, 0.225, 1.3, 0.1303 + 0.7, 0.225, 1.6, 0.1149 + 0.7, 0.25, 0.001, 0.2346 + 0.7, 0.25, 0.5, 0.1677 + 0.7, 0.25, 0.75, 0.1591 + 0.7, 0.25, 1.0, 0.1513 + 0.7, 0.25, 1.3, 0.1392 + 0.7, 0.25, 1.6, 0.1247 + 0.7, 0.275, 0.001, 0.2384 + 0.7, 0.275, 0.5, 0.1695 + 0.7, 0.275, 0.75, 0.1628 + 0.7, 0.275, 1.0, 0.1563 + 0.7, 0.275, 1.3, 0.1465 + 0.7, 0.275, 1.6, 0.1334 + 0.7, 0.3, 0.001, 0.2418 + 0.7, 0.3, 0.5, 0.1707 + 0.7, 0.3, 0.75, 0.1653 + 0.7, 0.3, 1.0, 0.1605 + 0.7, 0.3, 1.3, 0.1521 + 0.7, 0.3, 1.6, 0.1412 + 0.75, 0.025, 0.001, 0.1443 + 0.75, 0.025, 0.5, 0.0347 + 0.75, 0.025, 0.75, 0.0231 + 0.75, 0.025, 1.0, 0.0193 + 0.75, 0.025, 1.3, 0.0162 + 0.75, 0.025, 1.6, 0.0113 + 0.75, 0.05, 0.001, 0.1609 + 0.75, 0.05, 0.5, 0.068 + 0.75, 0.05, 0.75, 0.0505 + 0.75, 0.05, 1.0, 0.0402 + 0.75, 0.05, 1.3, 0.0308 + 0.75, 0.05, 1.6, 0.0243 + 0.75, 0.075, 0.001, 0.1784 + 0.75, 0.075, 0.5, 0.0978 + 0.75, 0.075, 0.75, 0.0742 + 0.75, 0.075, 1.0, 0.0596 + 0.75, 0.075, 1.3, 0.048 + 0.75, 0.075, 1.6, 0.0392 + 0.75, 0.1, 0.001, 0.1907 + 0.75, 0.1, 0.5, 0.1205 + 0.75, 0.1, 0.75, 0.0962 + 0.75, 0.1, 1.0, 0.0785 + 0.75, 0.1, 1.3, 0.0631 + 0.75, 0.1, 1.6, 0.0528 + 0.75, 0.125, 0.001, 0.2004 + 0.75, 0.125, 0.5, 0.1367 + 0.75, 0.125, 0.75, 0.1152 + 0.75, 0.125, 1.0, 0.0964 + 0.75, 0.125, 1.3, 0.0783 + 0.75, 0.125, 1.6, 0.0654 + 0.75, 0.15, 0.001, 0.2091 + 0.75, 0.15, 0.5, 0.1473 + 0.75, 0.15, 0.75, 0.1302 + 0.75, 0.15, 1.0, 0.1125 + 0.75, 0.15, 1.3, 0.0929 + 0.75, 0.15, 1.6, 0.078 + 0.75, 0.175, 0.001, 0.2171 + 0.75, 0.175, 0.5, 0.1553 + 0.75, 0.175, 0.75, 0.1412 + 0.75, 0.175, 1.0, 0.1261 + 0.75, 0.175, 1.3, 0.1066 + 0.75, 0.175, 1.6, 0.0904 + 0.75, 0.2, 0.001, 0.2239 + 0.75, 0.2, 0.5, 0.1618 + 0.75, 0.2, 0.75, 0.149 + 0.75, 0.2, 1.0, 0.1373 + 0.75, 0.2, 1.3, 0.1192 + 0.75, 0.2, 1.6, 0.1022 + 0.75, 0.225, 0.001, 0.2298 + 0.75, 0.225, 0.5, 0.1664 + 0.75, 0.225, 0.75, 0.1553 + 0.75, 0.225, 1.0, 0.1458 + 0.75, 0.225, 1.3, 0.1302 + 0.75, 0.225, 1.6, 0.1134 + 0.75, 0.25, 0.001, 0.2351 + 0.75, 0.25, 0.5, 0.1694 + 0.75, 0.25, 0.75, 0.1606 + 0.75, 0.25, 1.0, 0.1522 + 0.75, 0.25, 1.3, 0.1397 + 0.75, 0.25, 1.6, 0.1238 + 0.75, 0.275, 0.001, 0.2398 + 0.75, 0.275, 0.5, 0.1712 + 0.75, 0.275, 0.75, 0.1645 + 0.75, 0.275, 1.0, 0.1574 + 0.75, 0.275, 1.3, 0.1473 + 0.75, 0.275, 1.6, 0.1332 + 0.75, 0.3, 0.001, 0.2441 + 0.75, 0.3, 0.5, 0.1722 + 0.75, 0.3, 0.75, 0.1669 + 0.75, 0.3, 1.0, 0.162 + 0.75, 0.3, 1.3, 0.153 + 0.75, 0.3, 1.6, 0.1415 + 0.8, 0.025, 0.001, 0.1435 + 0.8, 0.025, 0.5, 0.0318 + 0.8, 0.025, 0.75, 0.0212 + 0.8, 0.025, 1.0, 0.0184 + 0.8, 0.025, 1.3, 0.0152 + 0.8, 0.025, 1.6, 0.011 + 0.8, 0.05, 0.001, 0.1574 + 0.8, 0.05, 0.5, 0.065 + 0.8, 0.05, 0.75, 0.0487 + 0.8, 0.05, 1.0, 0.0384 + 0.8, 0.05, 1.3, 0.029 + 0.8, 0.05, 1.6, 0.0227 + 0.8, 0.075, 0.001, 0.1758 + 0.8, 0.075, 0.5, 0.0943 + 0.8, 0.075, 0.75, 0.0718 + 0.8, 0.075, 1.0, 0.0578 + 0.8, 0.075, 1.3, 0.0466 + 0.8, 0.075, 1.6, 0.0376 + 0.8, 0.1, 0.001, 0.189 + 0.8, 0.1, 0.5, 0.1168 + 0.8, 0.1, 0.75, 0.0934 + 0.8, 0.1, 1.0, 0.0763 + 0.8, 0.1, 1.3, 0.0614 + 0.8, 0.1, 1.6, 0.0514 + 0.8, 0.125, 0.001, 0.199 + 0.8, 0.125, 0.5, 0.1337 + 0.8, 0.125, 0.75, 0.112 + 0.8, 0.125, 1.0, 0.0939 + 0.8, 0.125, 1.3, 0.0763 + 0.8, 0.125, 1.6, 0.0637 + 0.8, 0.15, 0.001, 0.2076 + 0.8, 0.15, 0.5, 0.1448 + 0.8, 0.15, 0.75, 0.1271 + 0.8, 0.15, 1.0, 0.1096 + 0.8, 0.15, 1.3, 0.0907 + 0.8, 0.15, 1.6, 0.0761 + 0.8, 0.175, 0.001, 0.2149 + 0.8, 0.175, 0.5, 0.1529 + 0.8, 0.175, 0.75, 0.1386 + 0.8, 0.175, 1.0, 0.1231 + 0.8, 0.175, 1.3, 0.1041 + 0.8, 0.175, 1.6, 0.0883 + 0.8, 0.2, 0.001, 0.2217 + 0.8, 0.2, 0.5, 0.1597 + 0.8, 0.2, 0.75, 0.1467 + 0.8, 0.2, 1.0, 0.1345 + 0.8, 0.2, 1.3, 0.1164 + 0.8, 0.2, 1.6, 0.0999 + 0.8, 0.225, 0.001, 0.228 + 0.8, 0.225, 0.5, 0.1647 + 0.8, 0.225, 0.75, 0.1531 + 0.8, 0.225, 1.0, 0.1433 + 0.8, 0.225, 1.3, 0.1273 + 0.8, 0.225, 1.6, 0.1108 + 0.8, 0.25, 0.001, 0.2338 + 0.8, 0.25, 0.5, 0.1679 + 0.8, 0.25, 0.75, 0.1586 + 0.8, 0.25, 1.0, 0.1498 + 0.8, 0.25, 1.3, 0.1369 + 0.8, 0.25, 1.6, 0.121 + 0.8, 0.275, 0.001, 0.2393 + 0.8, 0.275, 0.5, 0.1699 + 0.8, 0.275, 0.75, 0.1627 + 0.8, 0.275, 1.0, 0.1552 + 0.8, 0.275, 1.3, 0.1447 + 0.8, 0.275, 1.6, 0.1302 + 0.8, 0.3, 0.001, 0.2443 + 0.8, 0.3, 0.5, 0.171 + 0.8, 0.3, 0.75, 0.1655 + 0.8, 0.3, 1.0, 0.1599 + 0.8, 0.3, 1.3, 0.1505 + 0.8, 0.3, 1.6, 0.1385 + 0.85, 0.025, 0.001, 0.1234 + 0.85, 0.025, 0.5, 0.0282 + 0.85, 0.025, 0.75, 0.0199 + 0.85, 0.025, 1.0, 0.0176 + 0.85, 0.025, 1.3, 0.0145 + 0.85, 0.025, 1.6, 0.0108 + 0.85, 0.05, 0.001, 0.1487 + 0.85, 0.05, 0.5, 0.0621 + 0.85, 0.05, 0.75, 0.0464 + 0.85, 0.05, 1.0, 0.0361 + 0.85, 0.05, 1.3, 0.0272 + 0.85, 0.05, 1.6, 0.0217 + 0.85, 0.075, 0.001, 0.1677 + 0.85, 0.075, 0.5, 0.0902 + 0.85, 0.075, 0.75, 0.0694 + 0.85, 0.075, 1.0, 0.0558 + 0.85, 0.075, 1.3, 0.0447 + 0.85, 0.075, 1.6, 0.0356 + 0.85, 0.1, 0.001, 0.1827 + 0.85, 0.1, 0.5, 0.1107 + 0.85, 0.1, 0.75, 0.0901 + 0.85, 0.1, 1.0, 0.0741 + 0.85, 0.1, 1.3, 0.0596 + 0.85, 0.1, 1.6, 0.0495 + 0.85, 0.125, 0.001, 0.1939 + 0.85, 0.125, 0.5, 0.1269 + 0.85, 0.125, 0.75, 0.1071 + 0.85, 0.125, 1.0, 0.091 + 0.85, 0.125, 1.3, 0.0743 + 0.85, 0.125, 1.6, 0.0619 + 0.85, 0.15, 0.001, 0.2031 + 0.85, 0.15, 0.5, 0.1389 + 0.85, 0.15, 0.75, 0.1209 + 0.85, 0.15, 1.0, 0.1055 + 0.85, 0.15, 1.3, 0.0883 + 0.85, 0.15, 1.6, 0.0741 + 0.85, 0.175, 0.001, 0.2112 + 0.85, 0.175, 0.5, 0.1472 + 0.85, 0.175, 0.75, 0.1325 + 0.85, 0.175, 1.0, 0.1178 + 0.85, 0.175, 1.3, 0.1009 + 0.85, 0.175, 1.6, 0.0861 + 0.85, 0.2, 0.001, 0.2183 + 0.85, 0.2, 0.5, 0.1539 + 0.85, 0.2, 0.75, 0.1411 + 0.85, 0.2, 1.0, 0.1285 + 0.85, 0.2, 1.3, 0.1121 + 0.85, 0.2, 1.6, 0.0972 + 0.85, 0.225, 0.001, 0.2248 + 0.85, 0.225, 0.5, 0.1594 + 0.85, 0.225, 0.75, 0.1476 + 0.85, 0.225, 1.0, 0.1375 + 0.85, 0.225, 1.3, 0.122 + 0.85, 0.225, 1.6, 0.1074 + 0.85, 0.25, 0.001, 0.2307 + 0.85, 0.25, 0.5, 0.1632 + 0.85, 0.25, 0.75, 0.153 + 0.85, 0.25, 1.0, 0.1442 + 0.85, 0.25, 1.3, 0.131 + 0.85, 0.25, 1.6, 0.1166 + 0.85, 0.275, 0.001, 0.2361 + 0.85, 0.275, 0.5, 0.1656 + 0.85, 0.275, 0.75, 0.1574 + 0.85, 0.275, 1.0, 0.1496 + 0.85, 0.275, 1.3, 0.1386 + 0.85, 0.275, 1.6, 0.125 + 0.85, 0.3, 0.001, 0.2411 + 0.85, 0.3, 0.5, 0.1671 + 0.85, 0.3, 0.75, 0.1606 + 0.85, 0.3, 1.0, 0.1542 + 0.85, 0.3, 1.3, 0.1447 + 0.85, 0.3, 1.6, 0.1325 + 0.9, 0.025, 0.001, 0.1034 + 0.9, 0.025, 0.5, 0.0251 + 0.9, 0.025, 0.75, 0.0192 + 0.9, 0.025, 1.0, 0.0171 + 0.9, 0.025, 1.3, 0.0141 + 0.9, 0.025, 1.6, 0.0108 + 0.9, 0.05, 0.001, 0.1341 + 0.9, 0.05, 0.5, 0.0593 + 0.9, 0.05, 0.75, 0.0436 + 0.9, 0.05, 1.0, 0.0336 + 0.9, 0.05, 1.3, 0.0254 + 0.9, 0.05, 1.6, 0.0209 + 0.9, 0.075, 0.001, 0.1556 + 0.9, 0.075, 0.5, 0.0862 + 0.9, 0.075, 0.75, 0.0671 + 0.9, 0.075, 1.0, 0.0536 + 0.9, 0.075, 1.3, 0.0422 + 0.9, 0.075, 1.6, 0.0335 + 0.9, 0.1, 0.001, 0.1714 + 0.9, 0.1, 0.5, 0.1042 + 0.9, 0.1, 0.75, 0.0868 + 0.9, 0.1, 1.0, 0.072 + 0.9, 0.1, 1.3, 0.0576 + 0.9, 0.1, 1.6, 0.0472 + 0.9, 0.125, 0.001, 0.1842 + 0.9, 0.125, 0.5, 0.1177 + 0.9, 0.125, 0.75, 0.102 + 0.9, 0.125, 1.0, 0.088 + 0.9, 0.125, 1.3, 0.0724 + 0.9, 0.125, 1.6, 0.0599 + 0.9, 0.15, 0.001, 0.1947 + 0.9, 0.15, 0.5, 0.1296 + 0.9, 0.15, 0.75, 0.1135 + 0.9, 0.15, 1.0, 0.1011 + 0.9, 0.15, 1.3, 0.0858 + 0.9, 0.15, 1.6, 0.0723 + 0.9, 0.175, 0.001, 0.2038 + 0.9, 0.175, 0.5, 0.1385 + 0.9, 0.175, 0.75, 0.1238 + 0.9, 0.175, 1.0, 0.1114 + 0.9, 0.175, 1.3, 0.0974 + 0.9, 0.175, 1.6, 0.0839 + 0.9, 0.2, 0.001, 0.2127 + 0.9, 0.2, 0.5, 0.1453 + 0.9, 0.2, 0.75, 0.1325 + 0.9, 0.2, 1.0, 0.1204 + 0.9, 0.2, 1.3, 0.1073 + 0.9, 0.2, 1.6, 0.0943 + 0.9, 0.225, 0.001, 0.2202 + 0.9, 0.225, 0.5, 0.1507 + 0.9, 0.225, 0.75, 0.1392 + 0.9, 0.225, 1.0, 0.1288 + 0.9, 0.225, 1.3, 0.1155 + 0.9, 0.225, 1.6, 0.1036 + 0.9, 0.25, 0.001, 0.2263 + 0.9, 0.25, 0.5, 0.1548 + 0.9, 0.25, 0.75, 0.1445 + 0.9, 0.25, 1.0, 0.1357 + 0.9, 0.25, 1.3, 0.1229 + 0.9, 0.25, 1.6, 0.1117 + 0.9, 0.275, 0.001, 0.2315 + 0.9, 0.275, 0.5, 0.1578 + 0.9, 0.275, 0.75, 0.1488 + 0.9, 0.275, 1.0, 0.1411 + 0.9, 0.275, 1.3, 0.1299 + 0.9, 0.275, 1.6, 0.1184 + 0.9, 0.3, 0.001, 0.236 + 0.9, 0.3, 0.5, 0.1598 + 0.9, 0.3, 0.75, 0.1522 + 0.9, 0.3, 1.0, 0.1455 + 0.9, 0.3, 1.3, 0.1358 + 0.9, 0.3, 1.6, 0.1246 + 0.95, 0.025, 0.001, 0.1014 + 0.95, 0.025, 0.5, 0.0237 + 0.95, 0.025, 0.75, 0.0187 + 0.95, 0.025, 1.0, 0.0167 + 0.95, 0.025, 1.3, 0.0139 + 0.95, 0.025, 1.6, 0.0108 + 0.95, 0.05, 0.001, 0.1185 + 0.95, 0.05, 0.5, 0.0563 + 0.95, 0.05, 0.75, 0.0399 + 0.95, 0.05, 1.0, 0.031 + 0.95, 0.05, 1.3, 0.0238 + 0.95, 0.05, 1.6, 0.0203 + 0.95, 0.075, 0.001, 0.1396 + 0.95, 0.075, 0.5, 0.0826 + 0.95, 0.075, 0.75, 0.0649 + 0.95, 0.075, 1.0, 0.051 + 0.95, 0.075, 1.3, 0.0391 + 0.95, 0.075, 1.6, 0.0313 + 0.95, 0.1, 0.001, 0.1566 + 0.95, 0.1, 0.5, 0.0987 + 0.95, 0.1, 0.75, 0.0836 + 0.95, 0.1, 1.0, 0.0699 + 0.95, 0.1, 1.3, 0.0553 + 0.95, 0.1, 1.6, 0.0442 + 0.95, 0.125, 0.001, 0.17 + 0.95, 0.125, 0.5, 0.1093 + 0.95, 0.125, 0.75, 0.0971 + 0.95, 0.125, 1.0, 0.0851 + 0.95, 0.125, 1.3, 0.0705 + 0.95, 0.125, 1.6, 0.0577 + 0.95, 0.15, 0.001, 0.1812 + 0.95, 0.15, 0.5, 0.1187 + 0.95, 0.15, 0.75, 0.1064 + 0.95, 0.15, 1.0, 0.0967 + 0.95, 0.15, 1.3, 0.0834 + 0.95, 0.15, 1.6, 0.0704 + 0.95, 0.175, 0.001, 0.1914 + 0.95, 0.175, 0.5, 0.1273 + 0.95, 0.175, 0.75, 0.1143 + 0.95, 0.175, 1.0, 0.1053 + 0.95, 0.175, 1.3, 0.0939 + 0.95, 0.175, 1.6, 0.0817 + 0.95, 0.2, 0.001, 0.2007 + 0.95, 0.2, 0.5, 0.1343 + 0.95, 0.2, 0.75, 0.1219 + 0.95, 0.2, 1.0, 0.1122 + 0.95, 0.2, 1.3, 0.1025 + 0.95, 0.2, 1.6, 0.0915 + 0.95, 0.225, 0.001, 0.2113 + 0.95, 0.225, 0.5, 0.1397 + 0.95, 0.225, 0.75, 0.1283 + 0.95, 0.225, 1.0, 0.1187 + 0.95, 0.225, 1.3, 0.1089 + 0.95, 0.225, 1.6, 0.0997 + 0.95, 0.25, 0.001, 0.2207 + 0.95, 0.25, 0.5, 0.1439 + 0.95, 0.25, 0.75, 0.1337 + 0.95, 0.25, 1.0, 0.1249 + 0.95, 0.25, 1.3, 0.1144 + 0.95, 0.25, 1.6, 0.1066 + 0.95, 0.275, 0.001, 0.2265 + 0.95, 0.275, 0.5, 0.1468 + 0.95, 0.275, 0.75, 0.138 + 0.95, 0.275, 1.0, 0.1301 + 0.95, 0.275, 1.3, 0.1197 + 0.95, 0.275, 1.6, 0.1116 + 0.95, 0.3, 0.001, 0.2309 + 0.95, 0.3, 0.5, 0.1491 + 0.95, 0.3, 0.75, 0.1412 + 0.95, 0.3, 1.0, 0.1344 + 0.95, 0.3, 1.3, 0.1248 + 0.95, 0.3, 1.6, 0.1161 diff --git a/aviary/models/propellers/general_aviation.map b/aviary/models/engines/propellers/general_aviation.map similarity index 100% rename from aviary/models/propellers/general_aviation.map rename to aviary/models/engines/propellers/general_aviation.map diff --git a/aviary/models/engines/turbofan_22k.csv b/aviary/models/engines/turbofan_22k.csv new file mode 100644 index 0000000000..e1cc5e71ef --- /dev/null +++ b/aviary/models/engines/turbofan_22k.csv @@ -0,0 +1,617 @@ +# created 06/06/25 +# FLOPS-derived engine deck converted from turbofan_22k.txt + +Mach Number (input), Altitude (ft, input), Throttle (input), Gross Thrust (lbf, output), Ram Drag (lbf, output), Fuel Flow (lb/h, output), NOx Rate (lb/h, output) + 0.0, 0.0, 21.0, 1110.0, 0.0, 500.3, 55.372 + 0.0, 0.0, 26.0, 4440.1, 0.0, 964.9, 23.442 + 0.0, 0.0, 29.0, 6660.2, 0.0, 1368.2, 21.499 + 0.0, 0.0, 32.0, 8880.2, 0.0, 1790.8, 20.979 + 0.0, 0.0, 35.0, 11100.2, 0.0, 2255.1, 20.252 + 0.0, 0.0, 38.0, 13320.3, 0.0, 2756.1, 19.67 + 0.0, 0.0, 41.0, 15540.4, 0.0, 3300.0, 19.097 + 0.0, 0.0, 44.0, 17760.5, 0.0, 3879.8, 18.493 + 0.0, 0.0, 47.0, 19980.5, 0.0, 4500.3, 17.955 + 0.0, 0.0, 50.0, 22200.5, 0.0, 5157.3, 17.737 + 0.0, 2000.0, 21.0, 1061.5, 0.0, 472.8, 54.005 + 0.0, 2000.0, 26.0, 4246.0, 0.0, 917.9, 23.255 + 0.0, 2000.0, 29.0, 6369.0, 0.0, 1302.4, 21.423 + 0.0, 2000.0, 32.0, 8492.0, 0.0, 1706.2, 20.883 + 0.0, 2000.0, 35.0, 10615.1, 0.0, 2149.0, 20.188 + 0.0, 2000.0, 38.0, 12738.0, 0.0, 2632.7, 19.552 + 0.0, 2000.0, 41.0, 14861.1, 0.0, 3149.6, 19.014 + 0.0, 2000.0, 44.0, 16984.1, 0.0, 3709.7, 18.353 + 0.0, 2000.0, 47.0, 19107.0, 0.0, 4307.7, 17.846 + 0.0, 2000.0, 50.0, 21230.1, 0.0, 4936.7, 17.715 + 0.0, 5000.0, 21.0, 989.3, 0.0, 434.8, 52.114 + 0.0, 5000.0, 26.0, 3957.4, 0.0, 850.3, 23.0 + 0.0, 5000.0, 29.0, 5936.0, 0.0, 1206.2, 21.325 + 0.0, 5000.0, 32.0, 7914.8, 0.0, 1582.5, 20.728 + 0.0, 5000.0, 35.0, 9893.3, 0.0, 1991.9, 20.105 + 0.0, 5000.0, 38.0, 11872.1, 0.0, 2448.9, 19.392 + 0.0, 5000.0, 41.0, 13850.8, 0.0, 2930.5, 18.847 + 0.0, 5000.0, 44.0, 15829.6, 0.0, 3456.4, 18.164 + 0.0, 5000.0, 47.0, 17808.1, 0.0, 4018.3, 17.761 + 0.0, 5000.0, 50.0, 19786.8, 0.0, 4611.8, 17.637 + 0.0, 10000.0, 21.0, 870.1, 0.0, 379.9, 49.426 + 0.0, 10000.0, 26.0, 3480.2, 0.0, 743.0, 22.65 + 0.0, 10000.0, 29.0, 5220.4, 0.0, 1051.6, 21.202 + 0.0, 10000.0, 32.0, 6960.4, 0.0, 1381.9, 20.52 + 0.0, 10000.0, 35.0, 8700.6, 0.0, 1739.4, 19.918 + 0.0, 10000.0, 38.0, 10440.6, 0.0, 2143.9, 19.175 + 0.0, 10000.0, 41.0, 12180.8, 0.0, 2575.1, 18.509 + 0.0, 10000.0, 44.0, 13921.0, 0.0, 3039.5, 17.905 + 0.0, 10000.0, 47.0, 15661.0, 0.0, 3533.4, 17.718 + 0.0, 10000.0, 50.0, 17401.2, 0.0, 4085.5, 17.377 + 0.1, 0.0, 21.0, 2380.8, 1399.0, 576.5, 28.966 + 0.1, 0.0, 26.0, 5771.8, 1844.5, 1138.1, 21.215 + 0.1, 0.0, 29.0, 8024.0, 2133.0, 1561.0, 20.506 + 0.1, 0.0, 32.0, 10237.7, 2383.1, 2000.9, 20.126 + 0.1, 0.0, 35.0, 12412.3, 2594.1, 2464.7, 19.731 + 0.1, 0.0, 38.0, 14543.0, 2761.2, 2972.4, 19.161 + 0.1, 0.0, 41.0, 16665.2, 2919.7, 3496.0, 18.761 + 0.1, 0.0, 44.0, 18751.0, 3041.7, 4059.2, 18.179 + 0.1, 0.0, 47.0, 20834.5, 3161.7, 4653.7, 17.75 + 0.1, 0.0, 50.0, 22936.3, 3299.9, 5279.7, 17.625 + 0.1, 2000.0, 21.0, 2245.8, 1304.8, 544.9, 28.744 + 0.1, 2000.0, 26.0, 5496.1, 1731.9, 1080.8, 21.137 + 0.1, 2000.0, 29.0, 7653.6, 2007.4, 1483.6, 20.484 + 0.1, 2000.0, 32.0, 9768.7, 2240.4, 1904.6, 20.058 + 0.1, 2000.0, 35.0, 11852.0, 2441.7, 2346.1, 19.696 + 0.1, 2000.0, 38.0, 13887.4, 2594.9, 2836.1, 19.072 + 0.1, 2000.0, 41.0, 15915.3, 2740.7, 3339.8, 18.634 + 0.1, 2000.0, 44.0, 17912.6, 2856.0, 3879.3, 18.059 + 0.1, 2000.0, 47.0, 19909.3, 2970.8, 4452.6, 17.654 + 0.1, 2000.0, 50.0, 21929.0, 3108.4, 5054.3, 17.606 + 0.1, 5000.0, 21.0, 2051.0, 1172.7, 500.2, 28.439 + 0.1, 5000.0, 26.0, 5084.7, 1571.6, 997.1, 21.039 + 0.1, 5000.0, 29.0, 7096.8, 1827.1, 1368.6, 20.46 + 0.1, 5000.0, 32.0, 9062.6, 2036.3, 1760.2, 19.972 + 0.1, 5000.0, 35.0, 10997.5, 2214.7, 2173.3, 19.535 + 0.1, 5000.0, 38.0, 12896.7, 2357.4, 2628.7, 18.958 + 0.1, 5000.0, 41.0, 14779.7, 2483.7, 3102.4, 18.44 + 0.1, 5000.0, 44.0, 16643.9, 2591.3, 3607.1, 17.904 + 0.1, 5000.0, 47.0, 18516.7, 2707.6, 4144.9, 17.64 + 0.1, 5000.0, 50.0, 20390.2, 2824.5, 4716.9, 17.502 + 0.1, 10000.0, 21.0, 1753.3, 976.5, 435.3, 27.958 + 0.1, 10000.0, 26.0, 4436.9, 1329.4, 867.6, 20.899 + 0.1, 10000.0, 29.0, 6214.2, 1553.0, 1189.3, 20.44 + 0.1, 10000.0, 32.0, 7942.1, 1727.0, 1533.9, 19.855 + 0.1, 10000.0, 35.0, 9640.9, 1872.2, 1902.7, 19.299 + 0.1, 10000.0, 38.0, 11320.4, 1997.9, 2297.7, 18.795 + 0.1, 10000.0, 41.0, 12972.9, 2096.8, 2722.0, 18.154 + 0.1, 10000.0, 44.0, 14621.7, 2191.7, 3172.4, 17.679 + 0.1, 10000.0, 47.0, 16287.8, 2304.0, 3649.0, 17.604 + 0.1, 10000.0, 50.0, 17923.9, 2386.4, 4179.9, 17.256 + 0.2, 0.0, 21.0, 3842.2, 2960.4, 639.9, 20.541 + 0.2, 0.0, 26.0, 7484.3, 3957.2, 1289.5, 19.004 + 0.2, 0.0, 29.0, 9840.7, 4549.9, 1735.6, 19.13 + 0.2, 0.0, 32.0, 12066.9, 5012.5, 2198.3, 18.974 + 0.2, 0.0, 35.0, 14231.2, 5413.3, 2672.2, 18.805 + 0.2, 0.0, 38.0, 16309.0, 5727.5, 3184.6, 18.434 + 0.2, 0.0, 41.0, 18364.7, 6019.6, 3706.3, 18.138 + 0.2, 0.0, 44.0, 20360.0, 6251.2, 4256.6, 17.711 + 0.2, 0.0, 47.0, 22353.3, 6481.1, 4836.8, 17.401 + 0.2, 0.0, 50.0, 24389.7, 6753.8, 5444.7, 17.37 + 0.2, 2000.0, 21.0, 3610.4, 2763.4, 605.0, 20.495 + 0.2, 2000.0, 26.0, 7105.4, 3717.4, 1224.3, 19.003 + 0.2, 2000.0, 29.0, 9365.0, 4282.9, 1649.7, 19.158 + 0.2, 2000.0, 32.0, 11489.5, 4713.4, 2091.2, 18.955 + 0.2, 2000.0, 35.0, 13552.3, 5082.2, 2548.3, 18.731 + 0.2, 2000.0, 38.0, 15547.3, 5383.2, 3037.0, 18.381 + 0.2, 2000.0, 41.0, 17505.4, 5647.2, 3540.4, 18.027 + 0.2, 2000.0, 44.0, 19421.8, 5869.5, 4069.8, 17.619 + 0.2, 2000.0, 47.0, 21345.4, 6099.1, 4628.8, 17.37 + 0.2, 2000.0, 50.0, 23302.1, 6361.8, 5213.3, 17.363 + 0.2, 5000.0, 21.0, 3279.2, 2486.6, 555.4, 20.431 + 0.2, 5000.0, 26.0, 6544.9, 3374.5, 1128.1, 19.004 + 0.2, 5000.0, 29.0, 8651.9, 3896.4, 1521.8, 19.184 + 0.2, 5000.0, 32.0, 10625.2, 4284.6, 1930.3, 18.934 + 0.2, 5000.0, 35.0, 12535.9, 4610.0, 2359.8, 18.634 + 0.2, 5000.0, 38.0, 14401.5, 4890.6, 2811.2, 18.314 + 0.2, 5000.0, 41.0, 16213.6, 5117.5, 3284.8, 17.882 + 0.2, 5000.0, 44.0, 18006.3, 5325.1, 3782.3, 17.501 + 0.2, 5000.0, 47.0, 19823.9, 5557.5, 4307.8, 17.372 + 0.2, 5000.0, 50.0, 21625.5, 5773.9, 4865.7, 17.253 + 0.2, 10000.0, 21.0, 2779.4, 2074.7, 482.1, 20.332 + 0.2, 10000.0, 26.0, 5675.8, 2857.2, 979.8, 19.018 + 0.2, 10000.0, 29.0, 7522.6, 3294.7, 1324.5, 19.103 + 0.2, 10000.0, 32.0, 9273.2, 3635.9, 1679.9, 18.914 + 0.2, 10000.0, 35.0, 10945.4, 3898.9, 2062.7, 18.494 + 0.2, 10000.0, 38.0, 12592.1, 4136.2, 2459.3, 18.154 + 0.2, 10000.0, 41.0, 14186.8, 4321.4, 2880.4, 17.665 + 0.2, 10000.0, 44.0, 15786.4, 4511.9, 3326.7, 17.371 + 0.2, 10000.0, 47.0, 17411.1, 4727.2, 3795.9, 17.347 + 0.2, 10000.0, 50.0, 18971.4, 4878.3, 4312.5, 17.042 + 0.25, 0.0, 21.0, 4659.1, 3819.8, 673.8, 18.267 + 0.25, 0.0, 26.0, 8479.2, 5121.8, 1362.9, 18.077 + 0.25, 0.0, 29.0, 10910.3, 5874.2, 1824.0, 18.469 + 0.25, 0.0, 32.0, 13148.3, 6433.6, 2295.5, 18.409 + 0.25, 0.0, 35.0, 15310.2, 6916.7, 2778.8, 18.307 + 0.25, 0.0, 38.0, 17380.0, 7307.8, 3291.8, 18.054 + 0.25, 0.0, 41.0, 19409.5, 7658.7, 3814.8, 17.805 + 0.25, 0.0, 44.0, 21373.9, 7944.3, 4363.3, 17.458 + 0.25, 0.0, 47.0, 23335.6, 8227.3, 4937.9, 17.205 + 0.25, 0.0, 50.0, 25353.3, 8566.5, 5540.1, 17.214 + 0.25, 2000.0, 21.0, 4374.0, 3566.9, 637.1, 18.253 + 0.25, 2000.0, 26.0, 8041.1, 4812.5, 1293.9, 18.1 + 0.25, 2000.0, 29.0, 10367.5, 5524.5, 1734.3, 18.49 + 0.25, 2000.0, 32.0, 12507.8, 6050.5, 2183.7, 18.411 + 0.25, 2000.0, 35.0, 14566.0, 6494.3, 2649.9, 18.254 + 0.25, 2000.0, 38.0, 16555.0, 6869.1, 3138.9, 18.018 + 0.25, 2000.0, 41.0, 18485.5, 7185.3, 3643.9, 17.712 + 0.25, 2000.0, 44.0, 20373.8, 7459.5, 4172.5, 17.381 + 0.25, 2000.0, 47.0, 22275.4, 7746.7, 4727.0, 17.199 + 0.25, 2000.0, 50.0, 24212.7, 8069.6, 5305.6, 17.215 + 0.25, 5000.0, 21.0, 3967.7, 3211.0, 584.7, 18.233 + 0.25, 5000.0, 26.0, 7396.9, 4370.3, 1192.1, 18.135 + 0.25, 5000.0, 29.0, 9552.3, 5012.4, 1600.4, 18.467 + 0.25, 5000.0, 32.0, 11554.8, 5501.5, 2015.8, 18.418 + 0.25, 5000.0, 35.0, 13458.9, 5892.3, 2453.8, 18.186 + 0.25, 5000.0, 38.0, 15321.7, 6241.9, 2906.1, 17.974 + 0.25, 5000.0, 41.0, 17105.5, 6512.2, 3382.0, 17.59 + 0.25, 5000.0, 44.0, 18875.0, 6768.5, 3878.8, 17.28 + 0.25, 5000.0, 47.0, 20679.7, 7059.9, 4401.4, 17.211 + 0.25, 5000.0, 50.0, 22455.3, 7322.1, 4954.1, 17.109 + 0.25, 10000.0, 21.0, 3355.6, 2681.3, 506.8, 18.205 + 0.25, 10000.0, 26.0, 6399.2, 3701.8, 1034.8, 18.201 + 0.25, 10000.0, 29.0, 8286.0, 4239.8, 1391.5, 18.441 + 0.25, 10000.0, 32.0, 10063.1, 4668.3, 1753.6, 18.431 + 0.25, 10000.0, 35.0, 11727.9, 4984.4, 2143.7, 18.089 + 0.25, 10000.0, 38.0, 13362.3, 5270.0, 2544.2, 17.803 + 0.25, 10000.0, 41.0, 14940.7, 5499.6, 2966.8, 17.408 + 0.25, 10000.0, 44.0, 16530.1, 5740.4, 3412.4, 17.201 + 0.25, 10000.0, 47.0, 18139.4, 6000.9, 3880.6, 17.184 + 0.25, 10000.0, 50.0, 19673.2, 6186.0, 4391.0, 16.919 + 0.3, 0.0, 21.0, 5528.3, 4733.1, 705.1, 16.609 + 0.3, 0.0, 26.0, 9528.0, 6347.3, 1425.4, 17.247 + 0.3, 0.0, 29.0, 12021.9, 7250.9, 1898.7, 17.801 + 0.3, 0.0, 32.0, 14274.4, 7913.0, 2375.2, 17.865 + 0.3, 0.0, 35.0, 16429.0, 8477.3, 2862.2, 17.838 + 0.3, 0.0, 38.0, 18485.1, 8943.1, 3373.6, 17.684 + 0.3, 0.0, 41.0, 20486.0, 9353.6, 3893.3, 17.498 + 0.3, 0.0, 44.0, 22413.3, 9690.4, 4437.3, 17.219 + 0.3, 0.0, 47.0, 24336.6, 10023.5, 5002.1, 17.016 + 0.3, 0.0, 50.0, 26324.7, 10421.4, 5593.4, 17.045 + 0.3, 2000.0, 21.0, 5186.4, 4420.8, 666.7, 16.613 + 0.3, 2000.0, 26.0, 9027.4, 5965.1, 1353.4, 17.289 + 0.3, 2000.0, 29.0, 11402.7, 6809.2, 1805.7, 17.803 + 0.3, 2000.0, 32.0, 13567.2, 7442.7, 2259.6, 17.884 + 0.3, 2000.0, 35.0, 15615.9, 7960.2, 2729.6, 17.803 + 0.3, 2000.0, 38.0, 17593.4, 8406.6, 3217.0, 17.663 + 0.3, 2000.0, 41.0, 19493.4, 8775.5, 3719.1, 17.42 + 0.3, 2000.0, 44.0, 21348.0, 9099.0, 4243.5, 17.155 + 0.3, 2000.0, 47.0, 23216.0, 9435.7, 4789.0, 17.011 + 0.3, 2000.0, 50.0, 25129.1, 9817.7, 5358.1, 17.056 + 0.3, 5000.0, 21.0, 4701.4, 3981.8, 612.1, 16.619 + 0.3, 5000.0, 26.0, 8298.5, 5420.1, 1247.8, 17.351 + 0.3, 5000.0, 29.0, 10498.8, 6181.2, 1667.3, 17.808 + 0.3, 5000.0, 32.0, 12527.8, 6771.0, 2088.0, 17.914 + 0.3, 5000.0, 35.0, 14421.4, 7225.2, 2530.3, 17.759 + 0.3, 5000.0, 38.0, 16278.2, 7642.5, 2981.8, 17.64 + 0.3, 5000.0, 41.0, 18030.4, 7956.0, 3456.5, 17.317 + 0.3, 5000.0, 44.0, 19772.4, 8258.8, 3949.5, 17.07 + 0.3, 5000.0, 47.0, 21556.0, 8603.3, 4465.4, 17.036 + 0.3, 5000.0, 50.0, 23308.7, 8916.7, 5007.5, 16.977 + 0.3, 10000.0, 21.0, 3970.3, 3327.1, 530.0, 16.634 + 0.3, 10000.0, 26.0, 7166.5, 4593.6, 1083.4, 17.458 + 0.3, 10000.0, 29.0, 9090.2, 5230.7, 1450.2, 17.826 + 0.3, 10000.0, 32.0, 10880.8, 5735.0, 1818.3, 17.911 + 0.3, 10000.0, 35.0, 12546.2, 6113.9, 2211.1, 17.7 + 0.3, 10000.0, 38.0, 14166.2, 6447.5, 2612.8, 17.481 + 0.3, 10000.0, 41.0, 15725.1, 6719.8, 3035.3, 17.166 + 0.3, 10000.0, 44.0, 17298.3, 7006.6, 3477.0, 17.018 + 0.3, 10000.0, 47.0, 18894.1, 7315.9, 3940.2, 17.035 + 0.3, 10000.0, 50.0, 20398.8, 7534.2, 4441.2, 16.809 + 0.3, 15000.0, 26.0, 5934.7, 3789.4, 870.3, 17.485 + 0.3, 15000.0, 29.0, 7532.3, 4314.3, 1158.7, 17.834 + 0.3, 15000.0, 32.0, 9018.3, 4727.6, 1447.9, 17.895 + 0.3, 15000.0, 35.0, 10406.6, 5043.3, 1756.8, 17.691 + 0.3, 15000.0, 38.0, 11750.1, 5314.1, 2073.7, 17.446 + 0.3, 15000.0, 41.0, 13050.0, 5541.3, 2406.1, 17.138 + 0.3, 15000.0, 44.0, 14368.6, 5787.3, 2754.6, 17.027 + 0.3, 15000.0, 47.0, 15686.6, 6032.7, 3120.9, 16.999 + 0.3, 15000.0, 50.0, 16939.8, 6213.1, 3515.5, 16.772 + 0.4, 0.0, 21.0, 7463.1, 6739.9, 758.9, 14.345 + 0.4, 0.0, 26.0, 11919.1, 9026.4, 1537.6, 15.848 + 0.4, 0.0, 29.0, 14564.4, 10225.2, 2036.7, 16.565 + 0.4, 0.0, 32.0, 16908.5, 11122.8, 2526.5, 16.858 + 0.4, 0.0, 35.0, 19086.7, 11854.6, 3023.7, 16.966 + 0.4, 0.0, 38.0, 21151.9, 12473.4, 3536.8, 16.968 + 0.4, 0.0, 41.0, 23134.7, 13010.0, 4055.8, 16.903 + 0.4, 0.0, 44.0, 25020.5, 13449.2, 4598.6, 16.742 + 0.4, 0.0, 47.0, 26900.2, 13882.2, 5153.1, 16.628 + 0.4, 0.0, 50.0, 28852.7, 14388.7, 5728.6, 16.686 + 0.4, 2000.0, 21.0, 6995.8, 6297.9, 717.6, 14.368 + 0.4, 2000.0, 26.0, 11277.9, 8486.2, 1460.5, 15.915 + 0.4, 2000.0, 29.0, 13792.9, 9605.4, 1937.9, 16.598 + 0.4, 2000.0, 32.0, 16048.2, 10464.6, 2404.5, 16.905 + 0.4, 2000.0, 35.0, 18112.8, 11133.6, 2884.4, 16.963 + 0.4, 2000.0, 38.0, 20102.3, 11727.1, 3374.3, 16.975 + 0.4, 2000.0, 41.0, 21977.5, 12206.5, 3876.7, 16.855 + 0.4, 2000.0, 44.0, 23794.8, 12628.7, 4400.6, 16.704 + 0.4, 2000.0, 47.0, 25618.1, 13055.4, 4933.9, 16.617 + 0.4, 2000.0, 50.0, 27516.8, 13558.4, 5491.2, 16.716 + 0.4, 5000.0, 21.0, 6336.9, 5677.5, 659.2, 14.403 + 0.4, 5000.0, 26.0, 10357.3, 7719.6, 1348.9, 16.016 + 0.4, 5000.0, 29.0, 12684.6, 8728.0, 1793.0, 16.648 + 0.4, 5000.0, 32.0, 14805.2, 9529.8, 2226.7, 16.977 + 0.4, 5000.0, 35.0, 16707.7, 10113.6, 2679.6, 16.962 + 0.4, 5000.0, 38.0, 18582.3, 10669.3, 3134.9, 16.99 + 0.4, 5000.0, 41.0, 20304.5, 11072.7, 3612.2, 16.79 + 0.4, 5000.0, 44.0, 22019.8, 11469.2, 4105.4, 16.652 + 0.4, 5000.0, 47.0, 23784.9, 11915.4, 4613.6, 16.672 + 0.4, 5000.0, 50.0, 25532.1, 12343.7, 5141.2, 16.707 + 0.4, 10000.0, 21.0, 5344.1, 4750.2, 570.8, 14.463 + 0.4, 10000.0, 26.0, 8928.6, 6553.1, 1174.0, 16.183 + 0.4, 10000.0, 29.0, 10960.1, 7396.7, 1563.2, 16.737 + 0.4, 10000.0, 32.0, 12808.0, 8057.0, 1947.9, 16.977 + 0.4, 10000.0, 35.0, 14506.7, 8567.8, 2348.7, 16.97 + 0.4, 10000.0, 38.0, 16126.1, 8999.4, 2757.6, 16.874 + 0.4, 10000.0, 41.0, 17673.9, 9359.4, 3186.2, 16.698 + 0.4, 10000.0, 44.0, 19239.8, 9737.6, 3626.1, 16.642 + 0.4, 10000.0, 47.0, 20842.3, 10152.3, 4084.3, 16.734 + 0.4, 10000.0, 50.0, 22315.7, 10437.8, 4573.5, 16.584 + 0.4, 15000.0, 26.0, 7440.8, 5430.7, 949.8, 16.248 + 0.4, 15000.0, 29.0, 9142.5, 6127.1, 1259.4, 16.774 + 0.4, 15000.0, 32.0, 10686.8, 6666.6, 1566.7, 16.974 + 0.4, 15000.0, 35.0, 12122.5, 7097.1, 1886.2, 16.976 + 0.4, 15000.0, 38.0, 13473.5, 7443.1, 2215.2, 16.836 + 0.4, 15000.0, 41.0, 14782.4, 7747.1, 2558.2, 16.668 + 0.4, 15000.0, 44.0, 16123.8, 8083.5, 2912.3, 16.673 + 0.4, 15000.0, 47.0, 17447.7, 8402.1, 3282.8, 16.689 + 0.4, 15000.0, 50.0, 18690.1, 8639.4, 3675.7, 16.538 + 0.4, 20000.0, 26.0, 6056.2, 4420.0, 775.9, 16.253 + 0.4, 20000.0, 29.0, 7442.1, 4987.8, 1021.6, 16.779 + 0.4, 20000.0, 32.0, 8700.2, 5427.8, 1263.9, 16.979 + 0.4, 20000.0, 35.0, 9868.8, 5778.4, 1517.4, 16.98 + 0.4, 20000.0, 38.0, 10969.2, 6060.5, 1777.8, 16.839 + 0.4, 20000.0, 41.0, 12035.0, 6308.3, 2049.5, 16.671 + 0.4, 20000.0, 44.0, 13126.8, 6582.1, 2329.9, 16.675 + 0.4, 20000.0, 47.0, 14205.0, 6841.8, 2622.5, 16.691 + 0.4, 20000.0, 50.0, 15216.5, 7035.4, 2932.5, 16.537 + 0.5, 0.0, 21.0, 9760.2, 9097.6, 824.3, 13.022 + 0.5, 0.0, 26.0, 14735.0, 12084.8, 1652.2, 14.848 + 0.5, 0.0, 29.0, 17558.8, 13583.5, 2175.2, 15.635 + 0.5, 0.0, 32.0, 20024.5, 14724.1, 2678.2, 16.056 + 0.5, 0.0, 35.0, 22256.7, 15631.3, 3186.0, 16.263 + 0.5, 0.0, 38.0, 24355.0, 16404.6, 3701.2, 16.37 + 0.5, 0.0, 41.0, 26357.5, 17081.8, 4221.6, 16.411 + 0.5, 0.0, 44.0, 28222.7, 17622.1, 4763.3, 16.338 + 0.5, 0.0, 47.0, 30078.1, 18152.1, 5315.7, 16.293 + 0.5, 0.0, 50.0, 31992.9, 18741.9, 5877.1, 16.352 + 0.5, 2000.0, 21.0, 9144.6, 8503.5, 779.2, 13.054 + 0.5, 2000.0, 26.0, 13929.6, 11365.3, 1570.5, 14.93 + 0.5, 2000.0, 29.0, 16610.5, 12763.9, 2071.0, 15.688 + 0.5, 2000.0, 32.0, 18985.5, 13856.8, 2550.9, 16.123 + 0.5, 2000.0, 35.0, 21093.8, 14683.1, 3040.4, 16.283 + 0.5, 2000.0, 38.0, 23119.3, 15426.2, 3534.7, 16.399 + 0.5, 2000.0, 41.0, 25003.1, 16027.9, 4039.7, 16.387 + 0.5, 2000.0, 44.0, 26805.0, 16547.5, 4563.3, 16.321 + 0.5, 2000.0, 47.0, 28597.6, 17057.8, 5093.0, 16.283 + 0.5, 2000.0, 50.0, 30489.2, 17667.4, 5639.4, 16.405 + 0.5, 5000.0, 21.0, 8280.0, 7670.8, 715.7, 13.103 + 0.5, 5000.0, 26.0, 12786.4, 10349.5, 1453.6, 15.056 + 0.5, 5000.0, 29.0, 15264.6, 11609.3, 1920.9, 15.771 + 0.5, 5000.0, 32.0, 17496.7, 12623.0, 2369.6, 16.215 + 0.5, 5000.0, 35.0, 19441.0, 13348.6, 2831.5, 16.317 + 0.5, 5000.0, 38.0, 21357.0, 14046.3, 3294.1, 16.447 + 0.5, 5000.0, 41.0, 23076.6, 14547.2, 3775.9, 16.355 + 0.5, 5000.0, 44.0, 24784.0, 15036.5, 4272.2, 16.299 + 0.5, 5000.0, 47.0, 26534.9, 15568.8, 4775.2, 16.345 + 0.5, 5000.0, 50.0, 28322.0, 16137.5, 5292.2, 16.476 + 0.5, 10000.0, 21.0, 6975.8, 6423.1, 619.3, 13.184 + 0.5, 10000.0, 26.0, 11007.4, 8796.5, 1267.5, 15.262 + 0.5, 10000.0, 29.0, 13166.2, 9849.8, 1678.6, 15.91 + 0.5, 10000.0, 32.0, 15093.2, 10671.4, 2079.1, 16.253 + 0.5, 10000.0, 35.0, 16846.0, 11318.6, 2489.2, 16.38 + 0.5, 10000.0, 38.0, 18487.4, 11854.6, 2907.3, 16.389 + 0.5, 10000.0, 41.0, 20041.3, 12302.8, 3342.5, 16.314 + 0.5, 10000.0, 44.0, 21605.5, 12761.8, 3785.0, 16.311 + 0.5, 10000.0, 47.0, 23235.4, 13286.3, 4241.8, 16.463 + 0.5, 10000.0, 50.0, 24712.5, 13657.9, 4721.3, 16.405 + 0.5, 15000.0, 26.0, 9266.5, 7346.5, 1040.8, 15.394 + 0.5, 15000.0, 29.0, 11098.6, 8218.7, 1374.9, 16.0 + 0.5, 15000.0, 32.0, 12725.5, 8885.6, 1703.7, 16.28 + 0.5, 15000.0, 35.0, 14242.2, 9442.2, 2038.7, 16.423 + 0.5, 15000.0, 38.0, 15621.2, 9861.3, 2385.7, 16.357 + 0.5, 15000.0, 41.0, 16967.8, 10247.9, 2744.2, 16.295 + 0.5, 15000.0, 44.0, 18364.1, 10684.3, 3111.5, 16.39 + 0.5, 15000.0, 47.0, 19717.0, 11077.3, 3492.0, 16.444 + 0.5, 15000.0, 50.0, 20974.3, 11374.5, 3890.8, 16.354 + 0.5, 20000.0, 26.0, 7541.6, 5978.9, 846.9, 15.396 + 0.5, 20000.0, 29.0, 9034.1, 6690.1, 1112.6, 16.004 + 0.5, 20000.0, 32.0, 10359.3, 7234.1, 1372.2, 16.284 + 0.5, 20000.0, 35.0, 11594.7, 7687.8, 1638.2, 16.426 + 0.5, 20000.0, 38.0, 12717.4, 8029.4, 1913.2, 16.361 + 0.5, 20000.0, 41.0, 13813.8, 8344.4, 2196.9, 16.297 + 0.5, 20000.0, 44.0, 14950.4, 8699.8, 2488.3, 16.391 + 0.5, 20000.0, 47.0, 16052.2, 9020.2, 2788.9, 16.445 + 0.5, 20000.0, 50.0, 17076.0, 9262.6, 3104.1, 16.355 + 0.5, 25000.0, 26.0, 6085.9, 4824.5, 688.7, 15.4 + 0.5, 25000.0, 29.0, 7292.3, 5400.2, 897.5, 16.01 + 0.5, 25000.0, 32.0, 8363.5, 5840.6, 1100.5, 16.29 + 0.5, 25000.0, 35.0, 9360.5, 6206.9, 1308.9, 16.43 + 0.5, 25000.0, 38.0, 10267.7, 6483.4, 1525.1, 16.365 + 0.5, 25000.0, 41.0, 11153.0, 6738.2, 1747.0, 16.301 + 0.5, 25000.0, 44.0, 12070.7, 7024.9, 1976.1, 16.394 + 0.5, 25000.0, 47.0, 12960.6, 7284.2, 2211.5, 16.447 + 0.5, 25000.0, 50.0, 13787.2, 7480.0, 2457.9, 16.355 + 0.5, 30000.0, 26.0, 4865.8, 3856.7, 559.8, 15.404 + 0.5, 30000.0, 29.0, 5832.5, 4318.8, 722.2, 16.018 + 0.5, 30000.0, 32.0, 6690.7, 4672.4, 878.7, 16.299 + 0.5, 30000.0, 35.0, 7489.0, 4966.0, 1039.9, 16.437 + 0.5, 30000.0, 38.0, 8214.9, 5187.5, 1208.5, 16.371 + 0.5, 30000.0, 41.0, 8923.6, 5391.6, 1380.1, 16.305 + 0.5, 30000.0, 44.0, 9657.7, 5621.1, 1558.2, 16.397 + 0.5, 30000.0, 47.0, 10369.9, 5828.9, 1740.9, 16.45 + 0.5, 30000.0, 50.0, 11031.6, 5985.9, 1931.2, 16.357 + 0.6, 15000.0, 26.0, 11463.2, 9588.0, 1147.2, 14.806 + 0.6, 15000.0, 29.0, 13479.8, 10667.1, 1507.9, 15.479 + 0.6, 15000.0, 32.0, 15219.1, 11468.8, 1863.5, 15.805 + 0.6, 15000.0, 35.0, 16855.3, 12167.4, 2221.7, 16.043 + 0.6, 15000.0, 38.0, 18287.1, 12661.6, 2593.8, 16.03 + 0.6, 15000.0, 41.0, 19703.6, 13140.5, 2973.7, 16.045 + 0.6, 15000.0, 44.0, 21190.5, 13690.0, 3362.9, 16.21 + 0.6, 15000.0, 47.0, 22601.2, 14163.0, 3761.2, 16.295 + 0.6, 15000.0, 50.0, 23901.5, 14525.7, 4176.1, 16.255 + 0.6, 20000.0, 26.0, 9330.3, 7804.1, 930.5, 14.809 + 0.6, 20000.0, 29.0, 10972.7, 8683.3, 1217.3, 15.481 + 0.6, 20000.0, 32.0, 12389.9, 9337.5, 1498.6, 15.807 + 0.6, 20000.0, 35.0, 13722.2, 9906.7, 1782.6, 16.045 + 0.6, 20000.0, 38.0, 14888.5, 10309.9, 2077.9, 16.032 + 0.6, 20000.0, 41.0, 16041.6, 10700.0, 2378.9, 16.047 + 0.6, 20000.0, 44.0, 17252.4, 11147.6, 2687.7, 16.211 + 0.6, 20000.0, 47.0, 18401.6, 11533.3, 3003.3, 16.297 + 0.6, 20000.0, 50.0, 19459.8, 11828.8, 3331.0, 16.256 + 0.6, 25000.0, 26.0, 7530.0, 6298.1, 753.5, 14.813 + 0.6, 25000.0, 29.0, 8856.4, 7008.5, 979.9, 15.484 + 0.6, 25000.0, 32.0, 10002.2, 7538.4, 1199.6, 15.812 + 0.6, 25000.0, 35.0, 11079.0, 7998.9, 1422.6, 16.049 + 0.6, 25000.0, 38.0, 12020.5, 8324.7, 1654.6, 16.036 + 0.6, 25000.0, 41.0, 12952.0, 8640.2, 1890.5, 16.05 + 0.6, 25000.0, 44.0, 13929.3, 9001.5, 2133.0, 16.213 + 0.6, 25000.0, 47.0, 14857.3, 9313.5, 2380.3, 16.298 + 0.6, 25000.0, 50.0, 15712.1, 9552.4, 2636.6, 16.256 + 0.6, 30000.0, 26.0, 6020.8, 5035.4, 609.2, 14.819 + 0.6, 30000.0, 29.0, 7082.5, 5604.5, 786.1, 15.489 + 0.6, 30000.0, 32.0, 8001.0, 6030.2, 955.9, 15.818 + 0.6, 30000.0, 35.0, 8862.4, 6399.0, 1128.2, 16.053 + 0.6, 30000.0, 38.0, 9616.6, 6660.5, 1309.0, 16.041 + 0.6, 30000.0, 41.0, 10362.2, 6913.2, 1492.0, 16.054 + 0.6, 30000.0, 44.0, 11144.1, 7202.6, 1680.6, 16.216 + 0.6, 30000.0, 47.0, 11886.8, 7452.5, 1872.5, 16.301 + 0.6, 30000.0, 50.0, 12571.2, 7644.3, 2070.7, 16.258 + 0.6, 35000.0, 26.0, 4765.7, 3985.0, 493.5, 14.827 + 0.6, 35000.0, 29.0, 5608.2, 4437.1, 629.0, 15.497 + 0.6, 35000.0, 32.0, 6337.6, 4776.2, 759.0, 15.828 + 0.6, 35000.0, 35.0, 7020.7, 5068.9, 891.0, 16.061 + 0.6, 35000.0, 38.0, 7618.9, 5276.8, 1029.7, 16.049 + 0.6, 35000.0, 41.0, 8209.9, 5477.4, 1170.0, 16.061 + 0.6, 35000.0, 44.0, 8829.5, 5706.8, 1315.0, 16.221 + 0.6, 35000.0, 47.0, 9418.3, 5905.2, 1462.4, 16.305 + 0.6, 35000.0, 50.0, 9960.8, 6057.4, 1613.7, 16.261 + 0.6, 39000.0, 26.0, 3930.0, 3285.3, 424.1, 14.836 + 0.6, 39000.0, 29.0, 4626.5, 3659.4, 534.7, 15.507 + 0.6, 39000.0, 32.0, 5229.9, 3940.5, 640.7, 15.839 + 0.6, 39000.0, 35.0, 5794.2, 4182.4, 748.2, 16.07 + 0.6, 39000.0, 38.0, 6288.8, 4354.6, 861.0, 16.057 + 0.6, 39000.0, 41.0, 6777.0, 4520.5, 975.6, 16.068 + 0.6, 39000.0, 44.0, 7288.6, 4709.8, 1094.6, 16.227 + 0.6, 39000.0, 47.0, 7774.9, 4873.8, 1215.3, 16.311 + 0.6, 39000.0, 50.0, 8223.0, 4999.5, 1339.1, 16.265 + 0.7, 15000.0, 26.0, 14095.8, 12222.6, 1271.9, 14.436 + 0.7, 15000.0, 29.0, 16379.8, 13570.1, 1665.7, 15.189 + 0.7, 15000.0, 32.0, 18262.9, 14516.5, 2055.2, 15.538 + 0.7, 15000.0, 35.0, 20028.7, 15345.7, 2447.2, 15.806 + 0.7, 15000.0, 38.0, 21569.6, 15950.1, 2851.6, 15.865 + 0.7, 15000.0, 41.0, 23090.5, 16534.1, 3259.8, 15.938 + 0.7, 15000.0, 44.0, 24707.5, 17214.8, 3678.7, 16.157 + 0.7, 15000.0, 47.0, 26203.7, 17774.4, 4104.5, 16.263 + 0.7, 15000.0, 50.0, 27576.3, 18210.4, 4545.7, 16.247 + 0.7, 20000.0, 26.0, 11472.5, 9948.1, 1029.3, 14.436 + 0.7, 20000.0, 29.0, 13332.8, 11046.1, 1342.5, 15.189 + 0.7, 20000.0, 32.0, 14867.6, 11818.7, 1650.7, 15.539 + 0.7, 20000.0, 35.0, 16306.2, 12495.1, 1961.4, 15.808 + 0.7, 20000.0, 38.0, 17561.0, 12987.7, 2281.7, 15.866 + 0.7, 20000.0, 41.0, 18799.2, 13463.5, 2605.4, 15.939 + 0.7, 20000.0, 44.0, 20115.6, 14017.8, 2937.9, 16.158 + 0.7, 20000.0, 47.0, 21334.1, 14474.1, 3275.9, 16.263 + 0.7, 20000.0, 50.0, 22451.6, 14829.3, 3624.5, 16.247 + 0.7, 25000.0, 26.0, 9257.9, 8027.7, 830.3, 14.438 + 0.7, 25000.0, 29.0, 10760.3, 8914.9, 1077.4, 15.19 + 0.7, 25000.0, 32.0, 12001.6, 9541.2, 1318.5, 15.542 + 0.7, 25000.0, 35.0, 13164.1, 10088.6, 1562.1, 15.811 + 0.7, 25000.0, 38.0, 14177.3, 10486.7, 1813.7, 15.869 + 0.7, 25000.0, 41.0, 15176.8, 10870.9, 2068.1, 15.942 + 0.7, 25000.0, 44.0, 16239.6, 11318.8, 2329.7, 16.159 + 0.7, 25000.0, 47.0, 17223.8, 11687.9, 2594.6, 16.265 + 0.7, 25000.0, 50.0, 18126.4, 11975.4, 2867.3, 16.248 + 0.7, 30000.0, 26.0, 7401.8, 6417.7, 668.8, 14.441 + 0.7, 30000.0, 29.0, 8604.9, 7128.8, 861.9, 15.193 + 0.7, 30000.0, 32.0, 9600.6, 7632.4, 1048.4, 15.547 + 0.7, 30000.0, 35.0, 10532.1, 8071.8, 1237.0, 15.816 + 0.7, 30000.0, 38.0, 11343.1, 8390.9, 1432.1, 15.874 + 0.7, 30000.0, 41.0, 12143.2, 8698.7, 1630.7, 15.945 + 0.7, 30000.0, 44.0, 12993.3, 9056.9, 1833.8, 16.162 + 0.7, 30000.0, 47.0, 13781.4, 9353.0, 2039.6, 16.268 + 0.7, 30000.0, 50.0, 14503.9, 9583.4, 2250.7, 16.25 + 0.7, 35000.0, 26.0, 5858.1, 5078.6, 538.3, 14.445 + 0.7, 35000.0, 29.0, 6812.7, 5643.4, 687.2, 15.197 + 0.7, 35000.0, 32.0, 7603.7, 6044.7, 829.8, 15.555 + 0.7, 35000.0, 35.0, 8343.1, 6394.2, 974.5, 15.824 + 0.7, 35000.0, 38.0, 8986.1, 6647.4, 1124.6, 15.88 + 0.7, 35000.0, 41.0, 9620.3, 6891.8, 1276.4, 15.951 + 0.7, 35000.0, 44.0, 10294.2, 7176.0, 1432.9, 16.166 + 0.7, 35000.0, 47.0, 10918.7, 7410.8, 1590.9, 16.271 + 0.7, 35000.0, 50.0, 11491.5, 7593.8, 1752.8, 16.252 + 0.7, 39000.0, 26.0, 4830.1, 4186.3, 460.1, 14.451 + 0.7, 39000.0, 29.0, 5619.5, 4653.8, 582.1, 15.204 + 0.7, 39000.0, 32.0, 6274.4, 4986.9, 698.5, 15.564 + 0.7, 39000.0, 35.0, 6885.8, 5276.3, 816.4, 15.834 + 0.7, 39000.0, 38.0, 7417.2, 5485.8, 938.9, 15.887 + 0.7, 39000.0, 41.0, 7941.2, 5687.9, 1062.8, 15.958 + 0.7, 39000.0, 44.0, 8497.6, 5922.4, 1191.3, 16.172 + 0.7, 39000.0, 47.0, 9013.7, 6116.6, 1321.0, 16.277 + 0.7, 39000.0, 50.0, 9486.6, 6267.6, 1453.2, 16.256 + 0.7, 43000.0, 26.0, 3980.4, 3448.7, 398.8, 14.457 + 0.7, 43000.0, 29.0, 4633.3, 3835.8, 498.6, 15.212 + 0.7, 43000.0, 32.0, 5175.8, 4112.4, 594.3, 15.575 + 0.7, 43000.0, 35.0, 5681.6, 4352.4, 690.9, 15.845 + 0.7, 43000.0, 38.0, 6120.6, 4525.5, 790.9, 15.896 + 0.7, 43000.0, 41.0, 6553.6, 4692.7, 892.8, 15.966 + 0.7, 43000.0, 44.0, 7013.1, 4886.4, 998.6, 16.179 + 0.7, 43000.0, 47.0, 7439.1, 5046.5, 1105.7, 16.283 + 0.7, 43000.0, 50.0, 7829.8, 5171.4, 1214.4, 16.262 + 0.75, 25000.0, 26.0, 10256.2, 9016.7, 874.1, 14.339 + 0.75, 25000.0, 29.0, 11862.4, 10003.2, 1133.2, 15.123 + 0.75, 25000.0, 32.0, 13159.5, 10680.6, 1387.3, 15.481 + 0.75, 25000.0, 35.0, 14372.7, 11274.0, 1642.6, 15.761 + 0.75, 25000.0, 38.0, 15431.3, 11712.8, 1906.9, 15.847 + 0.75, 25000.0, 41.0, 16473.8, 12135.4, 2172.2, 15.941 + 0.75, 25000.0, 44.0, 17588.7, 12630.8, 2445.4, 16.169 + 0.75, 25000.0, 47.0, 18609.0, 13031.3, 2721.9, 16.267 + 0.75, 25000.0, 50.0, 19543.4, 13346.0, 3005.9, 16.249 + 0.75, 30000.0, 26.0, 8199.6, 7208.1, 702.6, 14.34 + 0.75, 30000.0, 29.0, 9486.1, 7998.9, 905.2, 15.124 + 0.75, 30000.0, 32.0, 10526.7, 8543.7, 1101.9, 15.485 + 0.75, 30000.0, 35.0, 11499.0, 9020.3, 1299.9, 15.765 + 0.75, 30000.0, 38.0, 12346.5, 9372.0, 1504.6, 15.851 + 0.75, 30000.0, 41.0, 13180.9, 9710.5, 1711.8, 15.944 + 0.75, 30000.0, 44.0, 14072.5, 10106.7, 1923.6, 16.171 + 0.75, 30000.0, 47.0, 14890.0, 10428.3, 2138.6, 16.269 + 0.75, 30000.0, 50.0, 15637.7, 10680.3, 2358.6, 16.251 + 0.75, 35000.0, 26.0, 6489.2, 5703.9, 564.2, 14.343 + 0.75, 35000.0, 29.0, 7510.0, 6332.0, 720.4, 15.127 + 0.75, 35000.0, 32.0, 8337.0, 6766.3, 871.0, 15.491 + 0.75, 35000.0, 35.0, 9108.9, 7145.5, 1023.0, 15.772 + 0.75, 35000.0, 38.0, 9780.9, 7424.8, 1179.8, 15.857 + 0.75, 35000.0, 41.0, 10442.2, 7693.4, 1338.8, 15.949 + 0.75, 35000.0, 44.0, 11149.2, 8007.7, 1502.2, 16.175 + 0.75, 35000.0, 47.0, 11796.9, 8262.8, 1667.2, 16.273 + 0.75, 35000.0, 50.0, 12389.7, 8462.9, 1836.0, 16.253 + 0.75, 39000.0, 26.0, 5350.2, 4701.6, 480.8, 14.347 + 0.75, 39000.0, 29.0, 6194.2, 5221.4, 609.2, 15.132 + 0.75, 39000.0, 32.0, 6879.2, 5582.1, 732.1, 15.499 + 0.75, 39000.0, 35.0, 7517.6, 5896.2, 856.2, 15.781 + 0.75, 39000.0, 38.0, 8072.9, 6127.2, 984.0, 15.863 + 0.75, 39000.0, 41.0, 8619.3, 6349.3, 1114.0, 15.956 + 0.75, 39000.0, 44.0, 9203.0, 6608.8, 1248.1, 16.181 + 0.75, 39000.0, 47.0, 9738.0, 6819.5, 1383.5, 16.278 + 0.75, 39000.0, 50.0, 10227.7, 6984.9, 1521.3, 16.257 + 0.75, 43000.0, 26.0, 4408.8, 3873.1, 415.4, 14.352 + 0.75, 43000.0, 29.0, 5107.0, 4303.5, 520.8, 15.139 + 0.75, 43000.0, 32.0, 5674.6, 4603.3, 621.9, 15.51 + 0.75, 43000.0, 35.0, 6202.8, 4863.7, 723.6, 15.792 + 0.75, 43000.0, 38.0, 6661.7, 5054.7, 828.1, 15.872 + 0.75, 43000.0, 41.0, 7113.3, 5238.4, 935.0, 15.964 + 0.75, 43000.0, 44.0, 7595.1, 5452.6, 1045.5, 16.187 + 0.75, 43000.0, 47.0, 8037.1, 5626.6, 1157.2, 16.284 + 0.75, 43000.0, 50.0, 8441.5, 5763.2, 1270.7, 16.262 + 0.8, 25000.0, 26.0, 11356.9, 10101.5, 922.2, 14.293 + 0.8, 25000.0, 29.0, 13066.3, 11183.2, 1195.4, 15.087 + 0.8, 25000.0, 32.0, 14436.2, 11925.4, 1463.5, 15.466 + 0.8, 25000.0, 35.0, 15706.3, 12567.8, 1732.5, 15.754 + 0.8, 25000.0, 38.0, 16815.9, 13049.7, 2009.5, 15.854 + 0.8, 25000.0, 41.0, 17907.5, 13513.6, 2288.1, 15.948 + 0.8, 25000.0, 44.0, 19082.5, 14060.9, 2574.7, 16.178 + 0.8, 25000.0, 47.0, 20144.8, 14495.5, 2865.2, 16.268 + 0.8, 25000.0, 50.0, 21116.2, 14839.2, 3162.6, 16.25 + 0.8, 30000.0, 26.0, 9078.8, 8074.8, 739.8, 14.293 + 0.8, 30000.0, 29.0, 10450.2, 8944.2, 952.8, 15.091 + 0.8, 30000.0, 32.0, 11547.3, 9539.2, 1160.6, 15.469 + 0.8, 30000.0, 35.0, 12565.1, 10055.1, 1369.5, 15.757 + 0.8, 30000.0, 38.0, 13453.4, 10441.4, 1584.4, 15.858 + 0.8, 30000.0, 41.0, 14327.1, 10813.0, 1801.4, 15.951 + 0.8, 30000.0, 44.0, 15267.2, 11251.2, 2024.0, 16.18 + 0.8, 30000.0, 47.0, 16118.0, 11599.8, 2250.0, 16.27 + 0.8, 30000.0, 50.0, 16895.3, 11875.3, 2480.5, 16.252 + 0.8, 35000.0, 26.0, 7184.6, 6389.4, 592.6, 14.294 + 0.8, 35000.0, 29.0, 8274.8, 7081.9, 756.9, 15.097 + 0.8, 35000.0, 32.0, 9145.1, 7554.7, 916.1, 15.474 + 0.8, 35000.0, 35.0, 9953.2, 7965.1, 1076.6, 15.764 + 0.8, 35000.0, 38.0, 10657.8, 8272.1, 1240.9, 15.863 + 0.8, 35000.0, 41.0, 11350.4, 8567.0, 1407.9, 15.955 + 0.8, 35000.0, 44.0, 12095.4, 8914.4, 1579.6, 16.184 + 0.8, 35000.0, 47.0, 12769.6, 9191.0, 1752.8, 16.274 + 0.8, 35000.0, 50.0, 13386.0, 9409.8, 1929.5, 16.254 + 0.8, 39000.0, 26.0, 5923.2, 5266.5, 503.9, 14.296 + 0.8, 39000.0, 29.0, 6826.0, 5840.9, 638.9, 15.104 + 0.8, 39000.0, 32.0, 7545.9, 6232.4, 769.0, 15.482 + 0.8, 39000.0, 35.0, 8214.3, 6572.5, 900.1, 15.772 + 0.8, 39000.0, 38.0, 8796.7, 6826.5, 1033.9, 15.869 + 0.8, 39000.0, 41.0, 9368.8, 7070.2, 1170.6, 15.961 + 0.8, 39000.0, 44.0, 9983.9, 7357.0, 1311.5, 16.189 + 0.8, 39000.0, 47.0, 10540.9, 7585.6, 1453.6, 16.279 + 0.8, 39000.0, 50.0, 11050.0, 7766.4, 1598.2, 16.258 + 0.8, 43000.0, 26.0, 4880.9, 4338.5, 433.7, 14.3 + 0.8, 43000.0, 29.0, 5628.9, 4815.3, 545.2, 15.113 + 0.8, 43000.0, 32.0, 6224.2, 5139.5, 652.1, 15.491 + 0.8, 43000.0, 35.0, 6777.5, 5421.5, 759.6, 15.782 + 0.8, 43000.0, 38.0, 7258.8, 5631.6, 869.1, 15.878 + 0.8, 43000.0, 41.0, 7731.5, 5833.1, 981.5, 15.969 + 0.8, 43000.0, 44.0, 8239.6, 6070.0, 1097.7, 16.195 + 0.8, 43000.0, 47.0, 8699.5, 6258.7, 1215.2, 16.285 + 0.8, 43000.0, 50.0, 9120.0, 6408.0, 1334.3, 16.263 + 0.85, 30000.0, 26.0, 10047.3, 9025.7, 780.3, 14.294 + 0.85, 30000.0, 29.0, 11504.3, 9971.8, 1005.3, 15.094 + 0.85, 30000.0, 32.0, 12670.8, 10627.5, 1225.5, 15.491 + 0.85, 30000.0, 35.0, 13739.3, 11185.1, 1445.7, 15.767 + 0.85, 30000.0, 38.0, 14674.6, 11609.6, 1672.5, 15.865 + 0.85, 30000.0, 41.0, 15593.4, 12017.8, 1901.1, 15.957 + 0.85, 30000.0, 44.0, 16587.9, 12501.2, 2136.8, 16.188 + 0.85, 30000.0, 47.0, 17476.4, 12878.8, 2374.8, 16.271 + 0.85, 30000.0, 50.0, 18287.8, 13179.4, 2618.5, 16.252 + 0.85, 35000.0, 26.0, 7950.8, 7141.5, 623.6, 14.293 + 0.85, 35000.0, 29.0, 9109.6, 7895.8, 796.9, 15.098 + 0.85, 35000.0, 32.0, 10034.9, 8416.5, 966.0, 15.496 + 0.85, 35000.0, 35.0, 10883.3, 8860.3, 1135.3, 15.773 + 0.85, 35000.0, 38.0, 11625.4, 9197.7, 1308.8, 15.87 + 0.85, 35000.0, 41.0, 12353.6, 9521.4, 1484.8, 15.961 + 0.85, 35000.0, 44.0, 13141.0, 9904.2, 1665.9, 16.192 + 0.85, 35000.0, 47.0, 13846.2, 10204.7, 1849.1, 16.275 + 0.85, 35000.0, 50.0, 14489.3, 10443.3, 2036.1, 16.255 + 0.85, 39000.0, 26.0, 6554.5, 5886.3, 529.1, 14.294 + 0.85, 39000.0, 29.0, 7514.3, 6512.0, 671.6, 15.104 + 0.85, 39000.0, 32.0, 8279.7, 6943.3, 809.7, 15.502 + 0.85, 39000.0, 35.0, 8981.6, 7311.0, 948.1, 15.78 + 0.85, 39000.0, 38.0, 9595.0, 7590.3, 1089.3, 15.876 + 0.85, 39000.0, 41.0, 10196.6, 7857.8, 1233.8, 15.967 + 0.85, 39000.0, 44.0, 10847.3, 8174.3, 1382.4, 16.196 + 0.85, 39000.0, 47.0, 11428.8, 8421.9, 1532.5, 16.279 + 0.85, 39000.0, 50.0, 11960.5, 8619.4, 1685.4, 16.258 + 0.85, 43000.0, 26.0, 5401.2, 4849.2, 454.3, 14.296 + 0.85, 43000.0, 29.0, 6196.5, 5368.6, 572.0, 15.112 + 0.85, 43000.0, 32.0, 6829.9, 5725.9, 685.6, 15.511 + 0.85, 43000.0, 35.0, 7410.8, 6030.8, 799.3, 15.789 + 0.85, 43000.0, 38.0, 7917.9, 6262.0, 914.8, 15.884 + 0.85, 43000.0, 41.0, 8415.1, 6483.2, 1033.7, 15.974 + 0.85, 43000.0, 44.0, 8952.4, 6744.4, 1156.3, 16.203 + 0.85, 43000.0, 47.0, 9433.1, 6949.2, 1280.6, 16.285 + 0.85, 43000.0, 50.0, 9871.7, 7111.8, 1406.2, 16.263 + 0.9, 35000.0, 26.0, 8794.4, 7967.2, 657.5, 14.337 + 0.9, 35000.0, 29.0, 10027.2, 8786.4, 840.8, 15.127 + 0.9, 35000.0, 32.0, 11014.2, 9359.8, 1020.9, 15.521 + 0.9, 35000.0, 35.0, 11908.2, 9840.2, 1200.3, 15.781 + 0.9, 35000.0, 38.0, 12692.3, 10210.8, 1384.4, 15.877 + 0.9, 35000.0, 41.0, 13460.9, 10565.7, 1571.1, 15.966 + 0.9, 35000.0, 44.0, 14297.2, 10988.4, 1763.3, 16.2 + 0.9, 35000.0, 47.0, 15035.3, 11312.9, 1957.5, 16.275 + 0.9, 35000.0, 50.0, 15708.7, 11572.7, 2156.3, 16.255 + 0.9, 39000.0, 26.0, 7249.8, 6566.7, 556.7, 14.336 + 0.9, 39000.0, 29.0, 8271.3, 7246.6, 707.3, 15.133 + 0.9, 39000.0, 32.0, 9087.5, 7721.4, 854.4, 15.527 + 0.9, 39000.0, 35.0, 9827.3, 8119.6, 1001.4, 15.788 + 0.9, 39000.0, 38.0, 10475.6, 8426.4, 1151.3, 15.883 + 0.9, 39000.0, 41.0, 11110.5, 8719.6, 1304.4, 15.972 + 0.9, 39000.0, 44.0, 11800.9, 9068.6, 1462.1, 16.204 + 0.9, 39000.0, 47.0, 12410.7, 9336.9, 1621.7, 16.28 + 0.9, 39000.0, 50.0, 12967.0, 9551.6, 1783.9, 16.258 + 0.9, 43000.0, 26.0, 5973.7, 5409.5, 476.7, 14.337 + 0.9, 43000.0, 29.0, 6820.3, 5974.0, 601.3, 15.14 + 0.9, 43000.0, 32.0, 7495.8, 6367.4, 722.4, 15.535 + 0.9, 43000.0, 35.0, 8108.0, 6697.6, 843.1, 15.797 + 0.9, 43000.0, 38.0, 8644.2, 6951.7, 965.6, 15.89 + 0.9, 43000.0, 41.0, 9168.7, 7194.0, 1092.0, 15.978 + 0.9, 43000.0, 44.0, 9738.9, 7482.1, 1222.0, 16.21 + 0.9, 43000.0, 47.0, 10242.4, 7703.6, 1353.7, 16.285 + 0.9, 43000.0, 50.0, 10701.9, 7881.0, 1487.5, 16.263 diff --git a/aviary/models/engines/turbofan_22k.deck b/aviary/models/engines/turbofan_22k.deck deleted file mode 100644 index 448cef8260..0000000000 --- a/aviary/models/engines/turbofan_22k.deck +++ /dev/null @@ -1,616 +0,0 @@ -# FLOPS-derived engine deck converted from engdek turbofan_22k.txt - -Mach_Number (unitless), Altitude (ft), Throttle (unitless), Gross_Thrust (lbf), Ram_Drag (lbf), Fuel_Flow (lb/h), NOx_Rate (lb/h) - 0.0, 0.0, 21.0, 1110.0, 0.0, 500.3, 55.372 - 0.0, 0.0, 26.0, 4440.1, 0.0, 964.9, 23.442 - 0.0, 0.0, 29.0, 6660.2, 0.0, 1368.2, 21.499 - 0.0, 0.0, 32.0, 8880.2, 0.0, 1790.8, 20.979 - 0.0, 0.0, 35.0, 11100.2, 0.0, 2255.1, 20.252 - 0.0, 0.0, 38.0, 13320.3, 0.0, 2756.1, 19.67 - 0.0, 0.0, 41.0, 15540.4, 0.0, 3300.0, 19.097 - 0.0, 0.0, 44.0, 17760.5, 0.0, 3879.8, 18.493 - 0.0, 0.0, 47.0, 19980.5, 0.0, 4500.3, 17.955 - 0.0, 0.0, 50.0, 22200.5, 0.0, 5157.3, 17.737 - 0.0, 2000.0, 21.0, 1061.5, 0.0, 472.8, 54.005 - 0.0, 2000.0, 26.0, 4246.0, 0.0, 917.9, 23.255 - 0.0, 2000.0, 29.0, 6369.0, 0.0, 1302.4, 21.423 - 0.0, 2000.0, 32.0, 8492.0, 0.0, 1706.2, 20.883 - 0.0, 2000.0, 35.0, 10615.1, 0.0, 2149.0, 20.188 - 0.0, 2000.0, 38.0, 12738.0, 0.0, 2632.7, 19.552 - 0.0, 2000.0, 41.0, 14861.1, 0.0, 3149.6, 19.014 - 0.0, 2000.0, 44.0, 16984.1, 0.0, 3709.7, 18.353 - 0.0, 2000.0, 47.0, 19107.0, 0.0, 4307.7, 17.846 - 0.0, 2000.0, 50.0, 21230.1, 0.0, 4936.7, 17.715 - 0.0, 5000.0, 21.0, 989.3, 0.0, 434.8, 52.114 - 0.0, 5000.0, 26.0, 3957.4, 0.0, 850.3, 23.0 - 0.0, 5000.0, 29.0, 5936.0, 0.0, 1206.2, 21.325 - 0.0, 5000.0, 32.0, 7914.8, 0.0, 1582.5, 20.728 - 0.0, 5000.0, 35.0, 9893.3, 0.0, 1991.9, 20.105 - 0.0, 5000.0, 38.0, 11872.1, 0.0, 2448.9, 19.392 - 0.0, 5000.0, 41.0, 13850.8, 0.0, 2930.5, 18.847 - 0.0, 5000.0, 44.0, 15829.6, 0.0, 3456.4, 18.164 - 0.0, 5000.0, 47.0, 17808.1, 0.0, 4018.3, 17.761 - 0.0, 5000.0, 50.0, 19786.8, 0.0, 4611.8, 17.637 - 0.0, 10000.0, 21.0, 870.1, 0.0, 379.9, 49.426 - 0.0, 10000.0, 26.0, 3480.2, 0.0, 743.0, 22.65 - 0.0, 10000.0, 29.0, 5220.4, 0.0, 1051.6, 21.202 - 0.0, 10000.0, 32.0, 6960.4, 0.0, 1381.9, 20.52 - 0.0, 10000.0, 35.0, 8700.6, 0.0, 1739.4, 19.918 - 0.0, 10000.0, 38.0, 10440.6, 0.0, 2143.9, 19.175 - 0.0, 10000.0, 41.0, 12180.8, 0.0, 2575.1, 18.509 - 0.0, 10000.0, 44.0, 13921.0, 0.0, 3039.5, 17.905 - 0.0, 10000.0, 47.0, 15661.0, 0.0, 3533.4, 17.718 - 0.0, 10000.0, 50.0, 17401.2, 0.0, 4085.5, 17.377 - 0.1, 0.0, 21.0, 2380.8, 1399.0, 576.5, 28.966 - 0.1, 0.0, 26.0, 5771.8, 1844.5, 1138.1, 21.215 - 0.1, 0.0, 29.0, 8024.0, 2133.0, 1561.0, 20.506 - 0.1, 0.0, 32.0, 10237.7, 2383.1, 2000.9, 20.126 - 0.1, 0.0, 35.0, 12412.3, 2594.1, 2464.7, 19.731 - 0.1, 0.0, 38.0, 14543.0, 2761.2, 2972.4, 19.161 - 0.1, 0.0, 41.0, 16665.2, 2919.7, 3496.0, 18.761 - 0.1, 0.0, 44.0, 18751.0, 3041.7, 4059.2, 18.179 - 0.1, 0.0, 47.0, 20834.5, 3161.7, 4653.7, 17.75 - 0.1, 0.0, 50.0, 22936.3, 3299.9, 5279.7, 17.625 - 0.1, 2000.0, 21.0, 2245.8, 1304.8, 544.9, 28.744 - 0.1, 2000.0, 26.0, 5496.1, 1731.9, 1080.8, 21.137 - 0.1, 2000.0, 29.0, 7653.6, 2007.4, 1483.6, 20.484 - 0.1, 2000.0, 32.0, 9768.7, 2240.4, 1904.6, 20.058 - 0.1, 2000.0, 35.0, 11852.0, 2441.7, 2346.1, 19.696 - 0.1, 2000.0, 38.0, 13887.4, 2594.9, 2836.1, 19.072 - 0.1, 2000.0, 41.0, 15915.3, 2740.7, 3339.8, 18.634 - 0.1, 2000.0, 44.0, 17912.6, 2856.0, 3879.3, 18.059 - 0.1, 2000.0, 47.0, 19909.3, 2970.8, 4452.6, 17.654 - 0.1, 2000.0, 50.0, 21929.0, 3108.4, 5054.3, 17.606 - 0.1, 5000.0, 21.0, 2051.0, 1172.7, 500.2, 28.439 - 0.1, 5000.0, 26.0, 5084.7, 1571.6, 997.1, 21.039 - 0.1, 5000.0, 29.0, 7096.8, 1827.1, 1368.6, 20.46 - 0.1, 5000.0, 32.0, 9062.6, 2036.3, 1760.2, 19.972 - 0.1, 5000.0, 35.0, 10997.5, 2214.7, 2173.3, 19.535 - 0.1, 5000.0, 38.0, 12896.7, 2357.4, 2628.7, 18.958 - 0.1, 5000.0, 41.0, 14779.7, 2483.7, 3102.4, 18.44 - 0.1, 5000.0, 44.0, 16643.9, 2591.3, 3607.1, 17.904 - 0.1, 5000.0, 47.0, 18516.7, 2707.6, 4144.9, 17.64 - 0.1, 5000.0, 50.0, 20390.2, 2824.5, 4716.9, 17.502 - 0.1, 10000.0, 21.0, 1753.3, 976.5, 435.3, 27.958 - 0.1, 10000.0, 26.0, 4436.9, 1329.4, 867.6, 20.899 - 0.1, 10000.0, 29.0, 6214.2, 1553.0, 1189.3, 20.44 - 0.1, 10000.0, 32.0, 7942.1, 1727.0, 1533.9, 19.855 - 0.1, 10000.0, 35.0, 9640.9, 1872.2, 1902.7, 19.299 - 0.1, 10000.0, 38.0, 11320.4, 1997.9, 2297.7, 18.795 - 0.1, 10000.0, 41.0, 12972.9, 2096.8, 2722.0, 18.154 - 0.1, 10000.0, 44.0, 14621.7, 2191.7, 3172.4, 17.679 - 0.1, 10000.0, 47.0, 16287.8, 2304.0, 3649.0, 17.604 - 0.1, 10000.0, 50.0, 17923.9, 2386.4, 4179.9, 17.256 - 0.2, 0.0, 21.0, 3842.2, 2960.4, 639.9, 20.541 - 0.2, 0.0, 26.0, 7484.3, 3957.2, 1289.5, 19.004 - 0.2, 0.0, 29.0, 9840.7, 4549.9, 1735.6, 19.13 - 0.2, 0.0, 32.0, 12066.9, 5012.5, 2198.3, 18.974 - 0.2, 0.0, 35.0, 14231.2, 5413.3, 2672.2, 18.805 - 0.2, 0.0, 38.0, 16309.0, 5727.5, 3184.6, 18.434 - 0.2, 0.0, 41.0, 18364.7, 6019.6, 3706.3, 18.138 - 0.2, 0.0, 44.0, 20360.0, 6251.2, 4256.6, 17.711 - 0.2, 0.0, 47.0, 22353.3, 6481.1, 4836.8, 17.401 - 0.2, 0.0, 50.0, 24389.7, 6753.8, 5444.7, 17.37 - 0.2, 2000.0, 21.0, 3610.4, 2763.4, 605.0, 20.495 - 0.2, 2000.0, 26.0, 7105.4, 3717.4, 1224.3, 19.003 - 0.2, 2000.0, 29.0, 9365.0, 4282.9, 1649.7, 19.158 - 0.2, 2000.0, 32.0, 11489.5, 4713.4, 2091.2, 18.955 - 0.2, 2000.0, 35.0, 13552.3, 5082.2, 2548.3, 18.731 - 0.2, 2000.0, 38.0, 15547.3, 5383.2, 3037.0, 18.381 - 0.2, 2000.0, 41.0, 17505.4, 5647.2, 3540.4, 18.027 - 0.2, 2000.0, 44.0, 19421.8, 5869.5, 4069.8, 17.619 - 0.2, 2000.0, 47.0, 21345.4, 6099.1, 4628.8, 17.37 - 0.2, 2000.0, 50.0, 23302.1, 6361.8, 5213.3, 17.363 - 0.2, 5000.0, 21.0, 3279.2, 2486.6, 555.4, 20.431 - 0.2, 5000.0, 26.0, 6544.9, 3374.5, 1128.1, 19.004 - 0.2, 5000.0, 29.0, 8651.9, 3896.4, 1521.8, 19.184 - 0.2, 5000.0, 32.0, 10625.2, 4284.6, 1930.3, 18.934 - 0.2, 5000.0, 35.0, 12535.9, 4610.0, 2359.8, 18.634 - 0.2, 5000.0, 38.0, 14401.5, 4890.6, 2811.2, 18.314 - 0.2, 5000.0, 41.0, 16213.6, 5117.5, 3284.8, 17.882 - 0.2, 5000.0, 44.0, 18006.3, 5325.1, 3782.3, 17.501 - 0.2, 5000.0, 47.0, 19823.9, 5557.5, 4307.8, 17.372 - 0.2, 5000.0, 50.0, 21625.5, 5773.9, 4865.7, 17.253 - 0.2, 10000.0, 21.0, 2779.4, 2074.7, 482.1, 20.332 - 0.2, 10000.0, 26.0, 5675.8, 2857.2, 979.8, 19.018 - 0.2, 10000.0, 29.0, 7522.6, 3294.7, 1324.5, 19.103 - 0.2, 10000.0, 32.0, 9273.2, 3635.9, 1679.9, 18.914 - 0.2, 10000.0, 35.0, 10945.4, 3898.9, 2062.7, 18.494 - 0.2, 10000.0, 38.0, 12592.1, 4136.2, 2459.3, 18.154 - 0.2, 10000.0, 41.0, 14186.8, 4321.4, 2880.4, 17.665 - 0.2, 10000.0, 44.0, 15786.4, 4511.9, 3326.7, 17.371 - 0.2, 10000.0, 47.0, 17411.1, 4727.2, 3795.9, 17.347 - 0.2, 10000.0, 50.0, 18971.4, 4878.3, 4312.5, 17.042 - 0.25, 0.0, 21.0, 4659.1, 3819.8, 673.8, 18.267 - 0.25, 0.0, 26.0, 8479.2, 5121.8, 1362.9, 18.077 - 0.25, 0.0, 29.0, 10910.3, 5874.2, 1824.0, 18.469 - 0.25, 0.0, 32.0, 13148.3, 6433.6, 2295.5, 18.409 - 0.25, 0.0, 35.0, 15310.2, 6916.7, 2778.8, 18.307 - 0.25, 0.0, 38.0, 17380.0, 7307.8, 3291.8, 18.054 - 0.25, 0.0, 41.0, 19409.5, 7658.7, 3814.8, 17.805 - 0.25, 0.0, 44.0, 21373.9, 7944.3, 4363.3, 17.458 - 0.25, 0.0, 47.0, 23335.6, 8227.3, 4937.9, 17.205 - 0.25, 0.0, 50.0, 25353.3, 8566.5, 5540.1, 17.214 - 0.25, 2000.0, 21.0, 4374.0, 3566.9, 637.1, 18.253 - 0.25, 2000.0, 26.0, 8041.1, 4812.5, 1293.9, 18.1 - 0.25, 2000.0, 29.0, 10367.5, 5524.5, 1734.3, 18.49 - 0.25, 2000.0, 32.0, 12507.8, 6050.5, 2183.7, 18.411 - 0.25, 2000.0, 35.0, 14566.0, 6494.3, 2649.9, 18.254 - 0.25, 2000.0, 38.0, 16555.0, 6869.1, 3138.9, 18.018 - 0.25, 2000.0, 41.0, 18485.5, 7185.3, 3643.9, 17.712 - 0.25, 2000.0, 44.0, 20373.8, 7459.5, 4172.5, 17.381 - 0.25, 2000.0, 47.0, 22275.4, 7746.7, 4727.0, 17.199 - 0.25, 2000.0, 50.0, 24212.7, 8069.6, 5305.6, 17.215 - 0.25, 5000.0, 21.0, 3967.7, 3211.0, 584.7, 18.233 - 0.25, 5000.0, 26.0, 7396.9, 4370.3, 1192.1, 18.135 - 0.25, 5000.0, 29.0, 9552.3, 5012.4, 1600.4, 18.467 - 0.25, 5000.0, 32.0, 11554.8, 5501.5, 2015.8, 18.418 - 0.25, 5000.0, 35.0, 13458.9, 5892.3, 2453.8, 18.186 - 0.25, 5000.0, 38.0, 15321.7, 6241.9, 2906.1, 17.974 - 0.25, 5000.0, 41.0, 17105.5, 6512.2, 3382.0, 17.59 - 0.25, 5000.0, 44.0, 18875.0, 6768.5, 3878.8, 17.28 - 0.25, 5000.0, 47.0, 20679.7, 7059.9, 4401.4, 17.211 - 0.25, 5000.0, 50.0, 22455.3, 7322.1, 4954.1, 17.109 - 0.25, 10000.0, 21.0, 3355.6, 2681.3, 506.8, 18.205 - 0.25, 10000.0, 26.0, 6399.2, 3701.8, 1034.8, 18.201 - 0.25, 10000.0, 29.0, 8286.0, 4239.8, 1391.5, 18.441 - 0.25, 10000.0, 32.0, 10063.1, 4668.3, 1753.6, 18.431 - 0.25, 10000.0, 35.0, 11727.9, 4984.4, 2143.7, 18.089 - 0.25, 10000.0, 38.0, 13362.3, 5270.0, 2544.2, 17.803 - 0.25, 10000.0, 41.0, 14940.7, 5499.6, 2966.8, 17.408 - 0.25, 10000.0, 44.0, 16530.1, 5740.4, 3412.4, 17.201 - 0.25, 10000.0, 47.0, 18139.4, 6000.9, 3880.6, 17.184 - 0.25, 10000.0, 50.0, 19673.2, 6186.0, 4391.0, 16.919 - 0.3, 0.0, 21.0, 5528.3, 4733.1, 705.1, 16.609 - 0.3, 0.0, 26.0, 9528.0, 6347.3, 1425.4, 17.247 - 0.3, 0.0, 29.0, 12021.9, 7250.9, 1898.7, 17.801 - 0.3, 0.0, 32.0, 14274.4, 7913.0, 2375.2, 17.865 - 0.3, 0.0, 35.0, 16429.0, 8477.3, 2862.2, 17.838 - 0.3, 0.0, 38.0, 18485.1, 8943.1, 3373.6, 17.684 - 0.3, 0.0, 41.0, 20486.0, 9353.6, 3893.3, 17.498 - 0.3, 0.0, 44.0, 22413.3, 9690.4, 4437.3, 17.219 - 0.3, 0.0, 47.0, 24336.6, 10023.5, 5002.1, 17.016 - 0.3, 0.0, 50.0, 26324.7, 10421.4, 5593.4, 17.045 - 0.3, 2000.0, 21.0, 5186.4, 4420.8, 666.7, 16.613 - 0.3, 2000.0, 26.0, 9027.4, 5965.1, 1353.4, 17.289 - 0.3, 2000.0, 29.0, 11402.7, 6809.2, 1805.7, 17.803 - 0.3, 2000.0, 32.0, 13567.2, 7442.7, 2259.6, 17.884 - 0.3, 2000.0, 35.0, 15615.9, 7960.2, 2729.6, 17.803 - 0.3, 2000.0, 38.0, 17593.4, 8406.6, 3217.0, 17.663 - 0.3, 2000.0, 41.0, 19493.4, 8775.5, 3719.1, 17.42 - 0.3, 2000.0, 44.0, 21348.0, 9099.0, 4243.5, 17.155 - 0.3, 2000.0, 47.0, 23216.0, 9435.7, 4789.0, 17.011 - 0.3, 2000.0, 50.0, 25129.1, 9817.7, 5358.1, 17.056 - 0.3, 5000.0, 21.0, 4701.4, 3981.8, 612.1, 16.619 - 0.3, 5000.0, 26.0, 8298.5, 5420.1, 1247.8, 17.351 - 0.3, 5000.0, 29.0, 10498.8, 6181.2, 1667.3, 17.808 - 0.3, 5000.0, 32.0, 12527.8, 6771.0, 2088.0, 17.914 - 0.3, 5000.0, 35.0, 14421.4, 7225.2, 2530.3, 17.759 - 0.3, 5000.0, 38.0, 16278.2, 7642.5, 2981.8, 17.64 - 0.3, 5000.0, 41.0, 18030.4, 7956.0, 3456.5, 17.317 - 0.3, 5000.0, 44.0, 19772.4, 8258.8, 3949.5, 17.07 - 0.3, 5000.0, 47.0, 21556.0, 8603.3, 4465.4, 17.036 - 0.3, 5000.0, 50.0, 23308.7, 8916.7, 5007.5, 16.977 - 0.3, 10000.0, 21.0, 3970.3, 3327.1, 530.0, 16.634 - 0.3, 10000.0, 26.0, 7166.5, 4593.6, 1083.4, 17.458 - 0.3, 10000.0, 29.0, 9090.2, 5230.7, 1450.2, 17.826 - 0.3, 10000.0, 32.0, 10880.8, 5735.0, 1818.3, 17.911 - 0.3, 10000.0, 35.0, 12546.2, 6113.9, 2211.1, 17.7 - 0.3, 10000.0, 38.0, 14166.2, 6447.5, 2612.8, 17.481 - 0.3, 10000.0, 41.0, 15725.1, 6719.8, 3035.3, 17.166 - 0.3, 10000.0, 44.0, 17298.3, 7006.6, 3477.0, 17.018 - 0.3, 10000.0, 47.0, 18894.1, 7315.9, 3940.2, 17.035 - 0.3, 10000.0, 50.0, 20398.8, 7534.2, 4441.2, 16.809 - 0.3, 15000.0, 26.0, 5934.7, 3789.4, 870.3, 17.485 - 0.3, 15000.0, 29.0, 7532.3, 4314.3, 1158.7, 17.834 - 0.3, 15000.0, 32.0, 9018.3, 4727.6, 1447.9, 17.895 - 0.3, 15000.0, 35.0, 10406.6, 5043.3, 1756.8, 17.691 - 0.3, 15000.0, 38.0, 11750.1, 5314.1, 2073.7, 17.446 - 0.3, 15000.0, 41.0, 13050.0, 5541.3, 2406.1, 17.138 - 0.3, 15000.0, 44.0, 14368.6, 5787.3, 2754.6, 17.027 - 0.3, 15000.0, 47.0, 15686.6, 6032.7, 3120.9, 16.999 - 0.3, 15000.0, 50.0, 16939.8, 6213.1, 3515.5, 16.772 - 0.4, 0.0, 21.0, 7463.1, 6739.9, 758.9, 14.345 - 0.4, 0.0, 26.0, 11919.1, 9026.4, 1537.6, 15.848 - 0.4, 0.0, 29.0, 14564.4, 10225.2, 2036.7, 16.565 - 0.4, 0.0, 32.0, 16908.5, 11122.8, 2526.5, 16.858 - 0.4, 0.0, 35.0, 19086.7, 11854.6, 3023.7, 16.966 - 0.4, 0.0, 38.0, 21151.9, 12473.4, 3536.8, 16.968 - 0.4, 0.0, 41.0, 23134.7, 13010.0, 4055.8, 16.903 - 0.4, 0.0, 44.0, 25020.5, 13449.2, 4598.6, 16.742 - 0.4, 0.0, 47.0, 26900.2, 13882.2, 5153.1, 16.628 - 0.4, 0.0, 50.0, 28852.7, 14388.7, 5728.6, 16.686 - 0.4, 2000.0, 21.0, 6995.8, 6297.9, 717.6, 14.368 - 0.4, 2000.0, 26.0, 11277.9, 8486.2, 1460.5, 15.915 - 0.4, 2000.0, 29.0, 13792.9, 9605.4, 1937.9, 16.598 - 0.4, 2000.0, 32.0, 16048.2, 10464.6, 2404.5, 16.905 - 0.4, 2000.0, 35.0, 18112.8, 11133.6, 2884.4, 16.963 - 0.4, 2000.0, 38.0, 20102.3, 11727.1, 3374.3, 16.975 - 0.4, 2000.0, 41.0, 21977.5, 12206.5, 3876.7, 16.855 - 0.4, 2000.0, 44.0, 23794.8, 12628.7, 4400.6, 16.704 - 0.4, 2000.0, 47.0, 25618.1, 13055.4, 4933.9, 16.617 - 0.4, 2000.0, 50.0, 27516.8, 13558.4, 5491.2, 16.716 - 0.4, 5000.0, 21.0, 6336.9, 5677.5, 659.2, 14.403 - 0.4, 5000.0, 26.0, 10357.3, 7719.6, 1348.9, 16.016 - 0.4, 5000.0, 29.0, 12684.6, 8728.0, 1793.0, 16.648 - 0.4, 5000.0, 32.0, 14805.2, 9529.8, 2226.7, 16.977 - 0.4, 5000.0, 35.0, 16707.7, 10113.6, 2679.6, 16.962 - 0.4, 5000.0, 38.0, 18582.3, 10669.3, 3134.9, 16.99 - 0.4, 5000.0, 41.0, 20304.5, 11072.7, 3612.2, 16.79 - 0.4, 5000.0, 44.0, 22019.8, 11469.2, 4105.4, 16.652 - 0.4, 5000.0, 47.0, 23784.9, 11915.4, 4613.6, 16.672 - 0.4, 5000.0, 50.0, 25532.1, 12343.7, 5141.2, 16.707 - 0.4, 10000.0, 21.0, 5344.1, 4750.2, 570.8, 14.463 - 0.4, 10000.0, 26.0, 8928.6, 6553.1, 1174.0, 16.183 - 0.4, 10000.0, 29.0, 10960.1, 7396.7, 1563.2, 16.737 - 0.4, 10000.0, 32.0, 12808.0, 8057.0, 1947.9, 16.977 - 0.4, 10000.0, 35.0, 14506.7, 8567.8, 2348.7, 16.97 - 0.4, 10000.0, 38.0, 16126.1, 8999.4, 2757.6, 16.874 - 0.4, 10000.0, 41.0, 17673.9, 9359.4, 3186.2, 16.698 - 0.4, 10000.0, 44.0, 19239.8, 9737.6, 3626.1, 16.642 - 0.4, 10000.0, 47.0, 20842.3, 10152.3, 4084.3, 16.734 - 0.4, 10000.0, 50.0, 22315.7, 10437.8, 4573.5, 16.584 - 0.4, 15000.0, 26.0, 7440.8, 5430.7, 949.8, 16.248 - 0.4, 15000.0, 29.0, 9142.5, 6127.1, 1259.4, 16.774 - 0.4, 15000.0, 32.0, 10686.8, 6666.6, 1566.7, 16.974 - 0.4, 15000.0, 35.0, 12122.5, 7097.1, 1886.2, 16.976 - 0.4, 15000.0, 38.0, 13473.5, 7443.1, 2215.2, 16.836 - 0.4, 15000.0, 41.0, 14782.4, 7747.1, 2558.2, 16.668 - 0.4, 15000.0, 44.0, 16123.8, 8083.5, 2912.3, 16.673 - 0.4, 15000.0, 47.0, 17447.7, 8402.1, 3282.8, 16.689 - 0.4, 15000.0, 50.0, 18690.1, 8639.4, 3675.7, 16.538 - 0.4, 20000.0, 26.0, 6056.2, 4420.0, 775.9, 16.253 - 0.4, 20000.0, 29.0, 7442.1, 4987.8, 1021.6, 16.779 - 0.4, 20000.0, 32.0, 8700.2, 5427.8, 1263.9, 16.979 - 0.4, 20000.0, 35.0, 9868.8, 5778.4, 1517.4, 16.98 - 0.4, 20000.0, 38.0, 10969.2, 6060.5, 1777.8, 16.839 - 0.4, 20000.0, 41.0, 12035.0, 6308.3, 2049.5, 16.671 - 0.4, 20000.0, 44.0, 13126.8, 6582.1, 2329.9, 16.675 - 0.4, 20000.0, 47.0, 14205.0, 6841.8, 2622.5, 16.691 - 0.4, 20000.0, 50.0, 15216.5, 7035.4, 2932.5, 16.537 - 0.5, 0.0, 21.0, 9760.2, 9097.6, 824.3, 13.022 - 0.5, 0.0, 26.0, 14735.0, 12084.8, 1652.2, 14.848 - 0.5, 0.0, 29.0, 17558.8, 13583.5, 2175.2, 15.635 - 0.5, 0.0, 32.0, 20024.5, 14724.1, 2678.2, 16.056 - 0.5, 0.0, 35.0, 22256.7, 15631.3, 3186.0, 16.263 - 0.5, 0.0, 38.0, 24355.0, 16404.6, 3701.2, 16.37 - 0.5, 0.0, 41.0, 26357.5, 17081.8, 4221.6, 16.411 - 0.5, 0.0, 44.0, 28222.7, 17622.1, 4763.3, 16.338 - 0.5, 0.0, 47.0, 30078.1, 18152.1, 5315.7, 16.293 - 0.5, 0.0, 50.0, 31992.9, 18741.9, 5877.1, 16.352 - 0.5, 2000.0, 21.0, 9144.6, 8503.5, 779.2, 13.054 - 0.5, 2000.0, 26.0, 13929.6, 11365.3, 1570.5, 14.93 - 0.5, 2000.0, 29.0, 16610.5, 12763.9, 2071.0, 15.688 - 0.5, 2000.0, 32.0, 18985.5, 13856.8, 2550.9, 16.123 - 0.5, 2000.0, 35.0, 21093.8, 14683.1, 3040.4, 16.283 - 0.5, 2000.0, 38.0, 23119.3, 15426.2, 3534.7, 16.399 - 0.5, 2000.0, 41.0, 25003.1, 16027.9, 4039.7, 16.387 - 0.5, 2000.0, 44.0, 26805.0, 16547.5, 4563.3, 16.321 - 0.5, 2000.0, 47.0, 28597.6, 17057.8, 5093.0, 16.283 - 0.5, 2000.0, 50.0, 30489.2, 17667.4, 5639.4, 16.405 - 0.5, 5000.0, 21.0, 8280.0, 7670.8, 715.7, 13.103 - 0.5, 5000.0, 26.0, 12786.4, 10349.5, 1453.6, 15.056 - 0.5, 5000.0, 29.0, 15264.6, 11609.3, 1920.9, 15.771 - 0.5, 5000.0, 32.0, 17496.7, 12623.0, 2369.6, 16.215 - 0.5, 5000.0, 35.0, 19441.0, 13348.6, 2831.5, 16.317 - 0.5, 5000.0, 38.0, 21357.0, 14046.3, 3294.1, 16.447 - 0.5, 5000.0, 41.0, 23076.6, 14547.2, 3775.9, 16.355 - 0.5, 5000.0, 44.0, 24784.0, 15036.5, 4272.2, 16.299 - 0.5, 5000.0, 47.0, 26534.9, 15568.8, 4775.2, 16.345 - 0.5, 5000.0, 50.0, 28322.0, 16137.5, 5292.2, 16.476 - 0.5, 10000.0, 21.0, 6975.8, 6423.1, 619.3, 13.184 - 0.5, 10000.0, 26.0, 11007.4, 8796.5, 1267.5, 15.262 - 0.5, 10000.0, 29.0, 13166.2, 9849.8, 1678.6, 15.91 - 0.5, 10000.0, 32.0, 15093.2, 10671.4, 2079.1, 16.253 - 0.5, 10000.0, 35.0, 16846.0, 11318.6, 2489.2, 16.38 - 0.5, 10000.0, 38.0, 18487.4, 11854.6, 2907.3, 16.389 - 0.5, 10000.0, 41.0, 20041.3, 12302.8, 3342.5, 16.314 - 0.5, 10000.0, 44.0, 21605.5, 12761.8, 3785.0, 16.311 - 0.5, 10000.0, 47.0, 23235.4, 13286.3, 4241.8, 16.463 - 0.5, 10000.0, 50.0, 24712.5, 13657.9, 4721.3, 16.405 - 0.5, 15000.0, 26.0, 9266.5, 7346.5, 1040.8, 15.394 - 0.5, 15000.0, 29.0, 11098.6, 8218.7, 1374.9, 16.0 - 0.5, 15000.0, 32.0, 12725.5, 8885.6, 1703.7, 16.28 - 0.5, 15000.0, 35.0, 14242.2, 9442.2, 2038.7, 16.423 - 0.5, 15000.0, 38.0, 15621.2, 9861.3, 2385.7, 16.357 - 0.5, 15000.0, 41.0, 16967.8, 10247.9, 2744.2, 16.295 - 0.5, 15000.0, 44.0, 18364.1, 10684.3, 3111.5, 16.39 - 0.5, 15000.0, 47.0, 19717.0, 11077.3, 3492.0, 16.444 - 0.5, 15000.0, 50.0, 20974.3, 11374.5, 3890.8, 16.354 - 0.5, 20000.0, 26.0, 7541.6, 5978.9, 846.9, 15.396 - 0.5, 20000.0, 29.0, 9034.1, 6690.1, 1112.6, 16.004 - 0.5, 20000.0, 32.0, 10359.3, 7234.1, 1372.2, 16.284 - 0.5, 20000.0, 35.0, 11594.7, 7687.8, 1638.2, 16.426 - 0.5, 20000.0, 38.0, 12717.4, 8029.4, 1913.2, 16.361 - 0.5, 20000.0, 41.0, 13813.8, 8344.4, 2196.9, 16.297 - 0.5, 20000.0, 44.0, 14950.4, 8699.8, 2488.3, 16.391 - 0.5, 20000.0, 47.0, 16052.2, 9020.2, 2788.9, 16.445 - 0.5, 20000.0, 50.0, 17076.0, 9262.6, 3104.1, 16.355 - 0.5, 25000.0, 26.0, 6085.9, 4824.5, 688.7, 15.4 - 0.5, 25000.0, 29.0, 7292.3, 5400.2, 897.5, 16.01 - 0.5, 25000.0, 32.0, 8363.5, 5840.6, 1100.5, 16.29 - 0.5, 25000.0, 35.0, 9360.5, 6206.9, 1308.9, 16.43 - 0.5, 25000.0, 38.0, 10267.7, 6483.4, 1525.1, 16.365 - 0.5, 25000.0, 41.0, 11153.0, 6738.2, 1747.0, 16.301 - 0.5, 25000.0, 44.0, 12070.7, 7024.9, 1976.1, 16.394 - 0.5, 25000.0, 47.0, 12960.6, 7284.2, 2211.5, 16.447 - 0.5, 25000.0, 50.0, 13787.2, 7480.0, 2457.9, 16.355 - 0.5, 30000.0, 26.0, 4865.8, 3856.7, 559.8, 15.404 - 0.5, 30000.0, 29.0, 5832.5, 4318.8, 722.2, 16.018 - 0.5, 30000.0, 32.0, 6690.7, 4672.4, 878.7, 16.299 - 0.5, 30000.0, 35.0, 7489.0, 4966.0, 1039.9, 16.437 - 0.5, 30000.0, 38.0, 8214.9, 5187.5, 1208.5, 16.371 - 0.5, 30000.0, 41.0, 8923.6, 5391.6, 1380.1, 16.305 - 0.5, 30000.0, 44.0, 9657.7, 5621.1, 1558.2, 16.397 - 0.5, 30000.0, 47.0, 10369.9, 5828.9, 1740.9, 16.45 - 0.5, 30000.0, 50.0, 11031.6, 5985.9, 1931.2, 16.357 - 0.6, 15000.0, 26.0, 11463.2, 9588.0, 1147.2, 14.806 - 0.6, 15000.0, 29.0, 13479.8, 10667.1, 1507.9, 15.479 - 0.6, 15000.0, 32.0, 15219.1, 11468.8, 1863.5, 15.805 - 0.6, 15000.0, 35.0, 16855.3, 12167.4, 2221.7, 16.043 - 0.6, 15000.0, 38.0, 18287.1, 12661.6, 2593.8, 16.03 - 0.6, 15000.0, 41.0, 19703.6, 13140.5, 2973.7, 16.045 - 0.6, 15000.0, 44.0, 21190.5, 13690.0, 3362.9, 16.21 - 0.6, 15000.0, 47.0, 22601.2, 14163.0, 3761.2, 16.295 - 0.6, 15000.0, 50.0, 23901.5, 14525.7, 4176.1, 16.255 - 0.6, 20000.0, 26.0, 9330.3, 7804.1, 930.5, 14.809 - 0.6, 20000.0, 29.0, 10972.7, 8683.3, 1217.3, 15.481 - 0.6, 20000.0, 32.0, 12389.9, 9337.5, 1498.6, 15.807 - 0.6, 20000.0, 35.0, 13722.2, 9906.7, 1782.6, 16.045 - 0.6, 20000.0, 38.0, 14888.5, 10309.9, 2077.9, 16.032 - 0.6, 20000.0, 41.0, 16041.6, 10700.0, 2378.9, 16.047 - 0.6, 20000.0, 44.0, 17252.4, 11147.6, 2687.7, 16.211 - 0.6, 20000.0, 47.0, 18401.6, 11533.3, 3003.3, 16.297 - 0.6, 20000.0, 50.0, 19459.8, 11828.8, 3331.0, 16.256 - 0.6, 25000.0, 26.0, 7530.0, 6298.1, 753.5, 14.813 - 0.6, 25000.0, 29.0, 8856.4, 7008.5, 979.9, 15.484 - 0.6, 25000.0, 32.0, 10002.2, 7538.4, 1199.6, 15.812 - 0.6, 25000.0, 35.0, 11079.0, 7998.9, 1422.6, 16.049 - 0.6, 25000.0, 38.0, 12020.5, 8324.7, 1654.6, 16.036 - 0.6, 25000.0, 41.0, 12952.0, 8640.2, 1890.5, 16.05 - 0.6, 25000.0, 44.0, 13929.3, 9001.5, 2133.0, 16.213 - 0.6, 25000.0, 47.0, 14857.3, 9313.5, 2380.3, 16.298 - 0.6, 25000.0, 50.0, 15712.1, 9552.4, 2636.6, 16.256 - 0.6, 30000.0, 26.0, 6020.8, 5035.4, 609.2, 14.819 - 0.6, 30000.0, 29.0, 7082.5, 5604.5, 786.1, 15.489 - 0.6, 30000.0, 32.0, 8001.0, 6030.2, 955.9, 15.818 - 0.6, 30000.0, 35.0, 8862.4, 6399.0, 1128.2, 16.053 - 0.6, 30000.0, 38.0, 9616.6, 6660.5, 1309.0, 16.041 - 0.6, 30000.0, 41.0, 10362.2, 6913.2, 1492.0, 16.054 - 0.6, 30000.0, 44.0, 11144.1, 7202.6, 1680.6, 16.216 - 0.6, 30000.0, 47.0, 11886.8, 7452.5, 1872.5, 16.301 - 0.6, 30000.0, 50.0, 12571.2, 7644.3, 2070.7, 16.258 - 0.6, 35000.0, 26.0, 4765.7, 3985.0, 493.5, 14.827 - 0.6, 35000.0, 29.0, 5608.2, 4437.1, 629.0, 15.497 - 0.6, 35000.0, 32.0, 6337.6, 4776.2, 759.0, 15.828 - 0.6, 35000.0, 35.0, 7020.7, 5068.9, 891.0, 16.061 - 0.6, 35000.0, 38.0, 7618.9, 5276.8, 1029.7, 16.049 - 0.6, 35000.0, 41.0, 8209.9, 5477.4, 1170.0, 16.061 - 0.6, 35000.0, 44.0, 8829.5, 5706.8, 1315.0, 16.221 - 0.6, 35000.0, 47.0, 9418.3, 5905.2, 1462.4, 16.305 - 0.6, 35000.0, 50.0, 9960.8, 6057.4, 1613.7, 16.261 - 0.6, 39000.0, 26.0, 3930.0, 3285.3, 424.1, 14.836 - 0.6, 39000.0, 29.0, 4626.5, 3659.4, 534.7, 15.507 - 0.6, 39000.0, 32.0, 5229.9, 3940.5, 640.7, 15.839 - 0.6, 39000.0, 35.0, 5794.2, 4182.4, 748.2, 16.07 - 0.6, 39000.0, 38.0, 6288.8, 4354.6, 861.0, 16.057 - 0.6, 39000.0, 41.0, 6777.0, 4520.5, 975.6, 16.068 - 0.6, 39000.0, 44.0, 7288.6, 4709.8, 1094.6, 16.227 - 0.6, 39000.0, 47.0, 7774.9, 4873.8, 1215.3, 16.311 - 0.6, 39000.0, 50.0, 8223.0, 4999.5, 1339.1, 16.265 - 0.7, 15000.0, 26.0, 14095.8, 12222.6, 1271.9, 14.436 - 0.7, 15000.0, 29.0, 16379.8, 13570.1, 1665.7, 15.189 - 0.7, 15000.0, 32.0, 18262.9, 14516.5, 2055.2, 15.538 - 0.7, 15000.0, 35.0, 20028.7, 15345.7, 2447.2, 15.806 - 0.7, 15000.0, 38.0, 21569.6, 15950.1, 2851.6, 15.865 - 0.7, 15000.0, 41.0, 23090.5, 16534.1, 3259.8, 15.938 - 0.7, 15000.0, 44.0, 24707.5, 17214.8, 3678.7, 16.157 - 0.7, 15000.0, 47.0, 26203.7, 17774.4, 4104.5, 16.263 - 0.7, 15000.0, 50.0, 27576.3, 18210.4, 4545.7, 16.247 - 0.7, 20000.0, 26.0, 11472.5, 9948.1, 1029.3, 14.436 - 0.7, 20000.0, 29.0, 13332.8, 11046.1, 1342.5, 15.189 - 0.7, 20000.0, 32.0, 14867.6, 11818.7, 1650.7, 15.539 - 0.7, 20000.0, 35.0, 16306.2, 12495.1, 1961.4, 15.808 - 0.7, 20000.0, 38.0, 17561.0, 12987.7, 2281.7, 15.866 - 0.7, 20000.0, 41.0, 18799.2, 13463.5, 2605.4, 15.939 - 0.7, 20000.0, 44.0, 20115.6, 14017.8, 2937.9, 16.158 - 0.7, 20000.0, 47.0, 21334.1, 14474.1, 3275.9, 16.263 - 0.7, 20000.0, 50.0, 22451.6, 14829.3, 3624.5, 16.247 - 0.7, 25000.0, 26.0, 9257.9, 8027.7, 830.3, 14.438 - 0.7, 25000.0, 29.0, 10760.3, 8914.9, 1077.4, 15.19 - 0.7, 25000.0, 32.0, 12001.6, 9541.2, 1318.5, 15.542 - 0.7, 25000.0, 35.0, 13164.1, 10088.6, 1562.1, 15.811 - 0.7, 25000.0, 38.0, 14177.3, 10486.7, 1813.7, 15.869 - 0.7, 25000.0, 41.0, 15176.8, 10870.9, 2068.1, 15.942 - 0.7, 25000.0, 44.0, 16239.6, 11318.8, 2329.7, 16.159 - 0.7, 25000.0, 47.0, 17223.8, 11687.9, 2594.6, 16.265 - 0.7, 25000.0, 50.0, 18126.4, 11975.4, 2867.3, 16.248 - 0.7, 30000.0, 26.0, 7401.8, 6417.7, 668.8, 14.441 - 0.7, 30000.0, 29.0, 8604.9, 7128.8, 861.9, 15.193 - 0.7, 30000.0, 32.0, 9600.6, 7632.4, 1048.4, 15.547 - 0.7, 30000.0, 35.0, 10532.1, 8071.8, 1237.0, 15.816 - 0.7, 30000.0, 38.0, 11343.1, 8390.9, 1432.1, 15.874 - 0.7, 30000.0, 41.0, 12143.2, 8698.7, 1630.7, 15.945 - 0.7, 30000.0, 44.0, 12993.3, 9056.9, 1833.8, 16.162 - 0.7, 30000.0, 47.0, 13781.4, 9353.0, 2039.6, 16.268 - 0.7, 30000.0, 50.0, 14503.9, 9583.4, 2250.7, 16.25 - 0.7, 35000.0, 26.0, 5858.1, 5078.6, 538.3, 14.445 - 0.7, 35000.0, 29.0, 6812.7, 5643.4, 687.2, 15.197 - 0.7, 35000.0, 32.0, 7603.7, 6044.7, 829.8, 15.555 - 0.7, 35000.0, 35.0, 8343.1, 6394.2, 974.5, 15.824 - 0.7, 35000.0, 38.0, 8986.1, 6647.4, 1124.6, 15.88 - 0.7, 35000.0, 41.0, 9620.3, 6891.8, 1276.4, 15.951 - 0.7, 35000.0, 44.0, 10294.2, 7176.0, 1432.9, 16.166 - 0.7, 35000.0, 47.0, 10918.7, 7410.8, 1590.9, 16.271 - 0.7, 35000.0, 50.0, 11491.5, 7593.8, 1752.8, 16.252 - 0.7, 39000.0, 26.0, 4830.1, 4186.3, 460.1, 14.451 - 0.7, 39000.0, 29.0, 5619.5, 4653.8, 582.1, 15.204 - 0.7, 39000.0, 32.0, 6274.4, 4986.9, 698.5, 15.564 - 0.7, 39000.0, 35.0, 6885.8, 5276.3, 816.4, 15.834 - 0.7, 39000.0, 38.0, 7417.2, 5485.8, 938.9, 15.887 - 0.7, 39000.0, 41.0, 7941.2, 5687.9, 1062.8, 15.958 - 0.7, 39000.0, 44.0, 8497.6, 5922.4, 1191.3, 16.172 - 0.7, 39000.0, 47.0, 9013.7, 6116.6, 1321.0, 16.277 - 0.7, 39000.0, 50.0, 9486.6, 6267.6, 1453.2, 16.256 - 0.7, 43000.0, 26.0, 3980.4, 3448.7, 398.8, 14.457 - 0.7, 43000.0, 29.0, 4633.3, 3835.8, 498.6, 15.212 - 0.7, 43000.0, 32.0, 5175.8, 4112.4, 594.3, 15.575 - 0.7, 43000.0, 35.0, 5681.6, 4352.4, 690.9, 15.845 - 0.7, 43000.0, 38.0, 6120.6, 4525.5, 790.9, 15.896 - 0.7, 43000.0, 41.0, 6553.6, 4692.7, 892.8, 15.966 - 0.7, 43000.0, 44.0, 7013.1, 4886.4, 998.6, 16.179 - 0.7, 43000.0, 47.0, 7439.1, 5046.5, 1105.7, 16.283 - 0.7, 43000.0, 50.0, 7829.8, 5171.4, 1214.4, 16.262 - 0.75, 25000.0, 26.0, 10256.2, 9016.7, 874.1, 14.339 - 0.75, 25000.0, 29.0, 11862.4, 10003.2, 1133.2, 15.123 - 0.75, 25000.0, 32.0, 13159.5, 10680.6, 1387.3, 15.481 - 0.75, 25000.0, 35.0, 14372.7, 11274.0, 1642.6, 15.761 - 0.75, 25000.0, 38.0, 15431.3, 11712.8, 1906.9, 15.847 - 0.75, 25000.0, 41.0, 16473.8, 12135.4, 2172.2, 15.941 - 0.75, 25000.0, 44.0, 17588.7, 12630.8, 2445.4, 16.169 - 0.75, 25000.0, 47.0, 18609.0, 13031.3, 2721.9, 16.267 - 0.75, 25000.0, 50.0, 19543.4, 13346.0, 3005.9, 16.249 - 0.75, 30000.0, 26.0, 8199.6, 7208.1, 702.6, 14.34 - 0.75, 30000.0, 29.0, 9486.1, 7998.9, 905.2, 15.124 - 0.75, 30000.0, 32.0, 10526.7, 8543.7, 1101.9, 15.485 - 0.75, 30000.0, 35.0, 11499.0, 9020.3, 1299.9, 15.765 - 0.75, 30000.0, 38.0, 12346.5, 9372.0, 1504.6, 15.851 - 0.75, 30000.0, 41.0, 13180.9, 9710.5, 1711.8, 15.944 - 0.75, 30000.0, 44.0, 14072.5, 10106.7, 1923.6, 16.171 - 0.75, 30000.0, 47.0, 14890.0, 10428.3, 2138.6, 16.269 - 0.75, 30000.0, 50.0, 15637.7, 10680.3, 2358.6, 16.251 - 0.75, 35000.0, 26.0, 6489.2, 5703.9, 564.2, 14.343 - 0.75, 35000.0, 29.0, 7510.0, 6332.0, 720.4, 15.127 - 0.75, 35000.0, 32.0, 8337.0, 6766.3, 871.0, 15.491 - 0.75, 35000.0, 35.0, 9108.9, 7145.5, 1023.0, 15.772 - 0.75, 35000.0, 38.0, 9780.9, 7424.8, 1179.8, 15.857 - 0.75, 35000.0, 41.0, 10442.2, 7693.4, 1338.8, 15.949 - 0.75, 35000.0, 44.0, 11149.2, 8007.7, 1502.2, 16.175 - 0.75, 35000.0, 47.0, 11796.9, 8262.8, 1667.2, 16.273 - 0.75, 35000.0, 50.0, 12389.7, 8462.9, 1836.0, 16.253 - 0.75, 39000.0, 26.0, 5350.2, 4701.6, 480.8, 14.347 - 0.75, 39000.0, 29.0, 6194.2, 5221.4, 609.2, 15.132 - 0.75, 39000.0, 32.0, 6879.2, 5582.1, 732.1, 15.499 - 0.75, 39000.0, 35.0, 7517.6, 5896.2, 856.2, 15.781 - 0.75, 39000.0, 38.0, 8072.9, 6127.2, 984.0, 15.863 - 0.75, 39000.0, 41.0, 8619.3, 6349.3, 1114.0, 15.956 - 0.75, 39000.0, 44.0, 9203.0, 6608.8, 1248.1, 16.181 - 0.75, 39000.0, 47.0, 9738.0, 6819.5, 1383.5, 16.278 - 0.75, 39000.0, 50.0, 10227.7, 6984.9, 1521.3, 16.257 - 0.75, 43000.0, 26.0, 4408.8, 3873.1, 415.4, 14.352 - 0.75, 43000.0, 29.0, 5107.0, 4303.5, 520.8, 15.139 - 0.75, 43000.0, 32.0, 5674.6, 4603.3, 621.9, 15.51 - 0.75, 43000.0, 35.0, 6202.8, 4863.7, 723.6, 15.792 - 0.75, 43000.0, 38.0, 6661.7, 5054.7, 828.1, 15.872 - 0.75, 43000.0, 41.0, 7113.3, 5238.4, 935.0, 15.964 - 0.75, 43000.0, 44.0, 7595.1, 5452.6, 1045.5, 16.187 - 0.75, 43000.0, 47.0, 8037.1, 5626.6, 1157.2, 16.284 - 0.75, 43000.0, 50.0, 8441.5, 5763.2, 1270.7, 16.262 - 0.8, 25000.0, 26.0, 11356.9, 10101.5, 922.2, 14.293 - 0.8, 25000.0, 29.0, 13066.3, 11183.2, 1195.4, 15.087 - 0.8, 25000.0, 32.0, 14436.2, 11925.4, 1463.5, 15.466 - 0.8, 25000.0, 35.0, 15706.3, 12567.8, 1732.5, 15.754 - 0.8, 25000.0, 38.0, 16815.9, 13049.7, 2009.5, 15.854 - 0.8, 25000.0, 41.0, 17907.5, 13513.6, 2288.1, 15.948 - 0.8, 25000.0, 44.0, 19082.5, 14060.9, 2574.7, 16.178 - 0.8, 25000.0, 47.0, 20144.8, 14495.5, 2865.2, 16.268 - 0.8, 25000.0, 50.0, 21116.2, 14839.2, 3162.6, 16.25 - 0.8, 30000.0, 26.0, 9078.8, 8074.8, 739.8, 14.293 - 0.8, 30000.0, 29.0, 10450.2, 8944.2, 952.8, 15.091 - 0.8, 30000.0, 32.0, 11547.3, 9539.2, 1160.6, 15.469 - 0.8, 30000.0, 35.0, 12565.1, 10055.1, 1369.5, 15.757 - 0.8, 30000.0, 38.0, 13453.4, 10441.4, 1584.4, 15.858 - 0.8, 30000.0, 41.0, 14327.1, 10813.0, 1801.4, 15.951 - 0.8, 30000.0, 44.0, 15267.2, 11251.2, 2024.0, 16.18 - 0.8, 30000.0, 47.0, 16118.0, 11599.8, 2250.0, 16.27 - 0.8, 30000.0, 50.0, 16895.3, 11875.3, 2480.5, 16.252 - 0.8, 35000.0, 26.0, 7184.6, 6389.4, 592.6, 14.294 - 0.8, 35000.0, 29.0, 8274.8, 7081.9, 756.9, 15.097 - 0.8, 35000.0, 32.0, 9145.1, 7554.7, 916.1, 15.474 - 0.8, 35000.0, 35.0, 9953.2, 7965.1, 1076.6, 15.764 - 0.8, 35000.0, 38.0, 10657.8, 8272.1, 1240.9, 15.863 - 0.8, 35000.0, 41.0, 11350.4, 8567.0, 1407.9, 15.955 - 0.8, 35000.0, 44.0, 12095.4, 8914.4, 1579.6, 16.184 - 0.8, 35000.0, 47.0, 12769.6, 9191.0, 1752.8, 16.274 - 0.8, 35000.0, 50.0, 13386.0, 9409.8, 1929.5, 16.254 - 0.8, 39000.0, 26.0, 5923.2, 5266.5, 503.9, 14.296 - 0.8, 39000.0, 29.0, 6826.0, 5840.9, 638.9, 15.104 - 0.8, 39000.0, 32.0, 7545.9, 6232.4, 769.0, 15.482 - 0.8, 39000.0, 35.0, 8214.3, 6572.5, 900.1, 15.772 - 0.8, 39000.0, 38.0, 8796.7, 6826.5, 1033.9, 15.869 - 0.8, 39000.0, 41.0, 9368.8, 7070.2, 1170.6, 15.961 - 0.8, 39000.0, 44.0, 9983.9, 7357.0, 1311.5, 16.189 - 0.8, 39000.0, 47.0, 10540.9, 7585.6, 1453.6, 16.279 - 0.8, 39000.0, 50.0, 11050.0, 7766.4, 1598.2, 16.258 - 0.8, 43000.0, 26.0, 4880.9, 4338.5, 433.7, 14.3 - 0.8, 43000.0, 29.0, 5628.9, 4815.3, 545.2, 15.113 - 0.8, 43000.0, 32.0, 6224.2, 5139.5, 652.1, 15.491 - 0.8, 43000.0, 35.0, 6777.5, 5421.5, 759.6, 15.782 - 0.8, 43000.0, 38.0, 7258.8, 5631.6, 869.1, 15.878 - 0.8, 43000.0, 41.0, 7731.5, 5833.1, 981.5, 15.969 - 0.8, 43000.0, 44.0, 8239.6, 6070.0, 1097.7, 16.195 - 0.8, 43000.0, 47.0, 8699.5, 6258.7, 1215.2, 16.285 - 0.8, 43000.0, 50.0, 9120.0, 6408.0, 1334.3, 16.263 - 0.85, 30000.0, 26.0, 10047.3, 9025.7, 780.3, 14.294 - 0.85, 30000.0, 29.0, 11504.3, 9971.8, 1005.3, 15.094 - 0.85, 30000.0, 32.0, 12670.8, 10627.5, 1225.5, 15.491 - 0.85, 30000.0, 35.0, 13739.3, 11185.1, 1445.7, 15.767 - 0.85, 30000.0, 38.0, 14674.6, 11609.6, 1672.5, 15.865 - 0.85, 30000.0, 41.0, 15593.4, 12017.8, 1901.1, 15.957 - 0.85, 30000.0, 44.0, 16587.9, 12501.2, 2136.8, 16.188 - 0.85, 30000.0, 47.0, 17476.4, 12878.8, 2374.8, 16.271 - 0.85, 30000.0, 50.0, 18287.8, 13179.4, 2618.5, 16.252 - 0.85, 35000.0, 26.0, 7950.8, 7141.5, 623.6, 14.293 - 0.85, 35000.0, 29.0, 9109.6, 7895.8, 796.9, 15.098 - 0.85, 35000.0, 32.0, 10034.9, 8416.5, 966.0, 15.496 - 0.85, 35000.0, 35.0, 10883.3, 8860.3, 1135.3, 15.773 - 0.85, 35000.0, 38.0, 11625.4, 9197.7, 1308.8, 15.87 - 0.85, 35000.0, 41.0, 12353.6, 9521.4, 1484.8, 15.961 - 0.85, 35000.0, 44.0, 13141.0, 9904.2, 1665.9, 16.192 - 0.85, 35000.0, 47.0, 13846.2, 10204.7, 1849.1, 16.275 - 0.85, 35000.0, 50.0, 14489.3, 10443.3, 2036.1, 16.255 - 0.85, 39000.0, 26.0, 6554.5, 5886.3, 529.1, 14.294 - 0.85, 39000.0, 29.0, 7514.3, 6512.0, 671.6, 15.104 - 0.85, 39000.0, 32.0, 8279.7, 6943.3, 809.7, 15.502 - 0.85, 39000.0, 35.0, 8981.6, 7311.0, 948.1, 15.78 - 0.85, 39000.0, 38.0, 9595.0, 7590.3, 1089.3, 15.876 - 0.85, 39000.0, 41.0, 10196.6, 7857.8, 1233.8, 15.967 - 0.85, 39000.0, 44.0, 10847.3, 8174.3, 1382.4, 16.196 - 0.85, 39000.0, 47.0, 11428.8, 8421.9, 1532.5, 16.279 - 0.85, 39000.0, 50.0, 11960.5, 8619.4, 1685.4, 16.258 - 0.85, 43000.0, 26.0, 5401.2, 4849.2, 454.3, 14.296 - 0.85, 43000.0, 29.0, 6196.5, 5368.6, 572.0, 15.112 - 0.85, 43000.0, 32.0, 6829.9, 5725.9, 685.6, 15.511 - 0.85, 43000.0, 35.0, 7410.8, 6030.8, 799.3, 15.789 - 0.85, 43000.0, 38.0, 7917.9, 6262.0, 914.8, 15.884 - 0.85, 43000.0, 41.0, 8415.1, 6483.2, 1033.7, 15.974 - 0.85, 43000.0, 44.0, 8952.4, 6744.4, 1156.3, 16.203 - 0.85, 43000.0, 47.0, 9433.1, 6949.2, 1280.6, 16.285 - 0.85, 43000.0, 50.0, 9871.7, 7111.8, 1406.2, 16.263 - 0.9, 35000.0, 26.0, 8794.4, 7967.2, 657.5, 14.337 - 0.9, 35000.0, 29.0, 10027.2, 8786.4, 840.8, 15.127 - 0.9, 35000.0, 32.0, 11014.2, 9359.8, 1020.9, 15.521 - 0.9, 35000.0, 35.0, 11908.2, 9840.2, 1200.3, 15.781 - 0.9, 35000.0, 38.0, 12692.3, 10210.8, 1384.4, 15.877 - 0.9, 35000.0, 41.0, 13460.9, 10565.7, 1571.1, 15.966 - 0.9, 35000.0, 44.0, 14297.2, 10988.4, 1763.3, 16.2 - 0.9, 35000.0, 47.0, 15035.3, 11312.9, 1957.5, 16.275 - 0.9, 35000.0, 50.0, 15708.7, 11572.7, 2156.3, 16.255 - 0.9, 39000.0, 26.0, 7249.8, 6566.7, 556.7, 14.336 - 0.9, 39000.0, 29.0, 8271.3, 7246.6, 707.3, 15.133 - 0.9, 39000.0, 32.0, 9087.5, 7721.4, 854.4, 15.527 - 0.9, 39000.0, 35.0, 9827.3, 8119.6, 1001.4, 15.788 - 0.9, 39000.0, 38.0, 10475.6, 8426.4, 1151.3, 15.883 - 0.9, 39000.0, 41.0, 11110.5, 8719.6, 1304.4, 15.972 - 0.9, 39000.0, 44.0, 11800.9, 9068.6, 1462.1, 16.204 - 0.9, 39000.0, 47.0, 12410.7, 9336.9, 1621.7, 16.28 - 0.9, 39000.0, 50.0, 12967.0, 9551.6, 1783.9, 16.258 - 0.9, 43000.0, 26.0, 5973.7, 5409.5, 476.7, 14.337 - 0.9, 43000.0, 29.0, 6820.3, 5974.0, 601.3, 15.14 - 0.9, 43000.0, 32.0, 7495.8, 6367.4, 722.4, 15.535 - 0.9, 43000.0, 35.0, 8108.0, 6697.6, 843.1, 15.797 - 0.9, 43000.0, 38.0, 8644.2, 6951.7, 965.6, 15.89 - 0.9, 43000.0, 41.0, 9168.7, 7194.0, 1092.0, 15.978 - 0.9, 43000.0, 44.0, 9738.9, 7482.1, 1222.0, 16.21 - 0.9, 43000.0, 47.0, 10242.4, 7703.6, 1353.7, 16.285 - 0.9, 43000.0, 50.0, 10701.9, 7881.0, 1487.5, 16.263 diff --git a/aviary/models/engines/turbofan_23k_1.csv b/aviary/models/engines/turbofan_23k_1.csv new file mode 100644 index 0000000000..481efc50c5 --- /dev/null +++ b/aviary/models/engines/turbofan_23k_1.csv @@ -0,0 +1,2809 @@ +# created 06/06/25 +# GASP-derived engine deck converted from turbofan_23k_1.eng +# t4max: 3342.0 +# t4cruise: 3108.0 +# t4climb: 3196.0 +# sls_airflow: 994.36 +# sfn_idle: 1.25 + +Mach Number (input), Altitude (ft, input), Throttle (input), Thrust (lbf, output), Fuel Flow (lb/h, output), T4 (degR, output) + 0.0, 0.0, 0.0, 621.4719, 621.472, 0.0 + 0.0, 0.0, 0.4656, -1979.162, -105.249, 1556.01 + 0.0, 0.0, 0.5432, 1065.323, 539.553, 1815.34 + 0.0, 0.0, 0.6208, 4109.809, 1184.35, 2074.68 + 0.0, 0.0, 0.6984, 7327.181, 1870.66, 2334.02 + 0.0, 0.0, 0.776, 11036.92, 2800.21, 2593.35 + 0.0, 0.0, 0.8536, 15708.88, 4095.82, 2852.68 + 0.0, 0.0, 0.9312, 21836.46, 5870.27, 3112.02 + 0.0, 3000.0, 0.0, 562.8327, 562.833, 0.0 + 0.0, 3000.0, 0.456, -2285.519, -183.506, 1523.92 + 0.0, 3000.0, 0.532, 456.4109, 412.261, 1777.91 + 0.0, 3000.0, 0.608, 3198.341, 1008.03, 2031.89 + 0.0, 3000.0, 0.684, 5972.483, 1620.99, 2285.88 + 0.0, 3000.0, 0.76, 9207.826, 2437.99, 2539.87 + 0.0, 3000.0, 0.836, 13217.8, 3553.47, 2793.85 + 0.0, 3000.0, 0.912, 18617.68, 5114.42, 3047.84 + 0.0, 3000.0, 0.988, 25284.21, 7083.13, 3301.83 + 0.0, 6000.0, 0.0, 508.6672, 508.667, 0.0 + 0.0, 6000.0, 0.4464, -2935.834, -280.32, 1491.84 + 0.0, 6000.0, 0.5208, -197.4633, 275.139, 1740.48 + 0.0, 6000.0, 0.5952, 2540.908, 830.597, 1989.12 + 0.0, 6000.0, 0.6696, 5279.279, 1386.06, 2237.76 + 0.0, 6000.0, 0.744, 8213.525, 2090.9, 2486.4 + 0.0, 6000.0, 0.8184, 11851.38, 3062.07, 2735.04 + 0.0, 6000.0, 0.8928, 16560.29, 4378.63, 2983.67 + 0.0, 6000.0, 0.9672, 22654.55, 6120.23, 3232.31 + 0.0, 9000.0, 0.0, 458.719, 458.719, 0.0 + 0.0, 9000.0, 0.4368, 820.9403, -198.516, 1459.77 + 0.0, 9000.0, 0.5096, 2287.775, 273.478, 1703.06 + 0.0, 9000.0, 0.5824, 3754.602, 745.474, 1946.36 + 0.0, 9000.0, 0.6552, 5221.432, 1217.47, 2189.65 + 0.0, 9000.0, 0.728, 6857.634, 1767.45, 2432.94 + 0.0, 9000.0, 0.8008, 10501.95, 2618.39, 2676.24 + 0.0, 9000.0, 0.8736, 14702.7, 3781.46, 2919.53 + 0.0, 9000.0, 0.9464, 19922.61, 5272.3, 3162.83 + 0.0, 12000.0, 0.0, 412.7369, 412.737, 0.0 + 0.0, 12000.0, 0.4272, -10008.41, -627.123, 1427.7 + 0.0, 12000.0, 0.4984, -5628.271, -88.3646, 1665.65 + 0.0, 12000.0, 0.5696, -1248.108, 450.402, 1903.6 + 0.0, 12000.0, 0.6408, 3132.043, 989.172, 2141.55 + 0.0, 12000.0, 0.712, 7439.102, 1656.58, 2379.5 + 0.0, 12000.0, 0.7832, 10835.88, 2375.84, 2617.45 + 0.0, 12000.0, 0.8544, 10534.27, 2915.17, 2855.4 + 0.0, 12000.0, 0.9256, 17296.46, 4499.26, 3093.35 + 0.0, 12000.0, 0.9968, 22936.55, 6163.15, 3331.3 + 0.0, 15000.0, 0.0, 370.4861, 370.486, 0.0 + 0.0, 15000.0, 0.4176, -4108.327, -953.742, 1395.65 + 0.0, 15000.0, 0.4872, -2085.137, -423.266, 1628.26 + 0.0, 15000.0, 0.5568, -61.8775, 107.23, 1860.87 + 0.0, 15000.0, 0.6264, 1961.358, 637.707, 2093.47 + 0.0, 15000.0, 0.696, 3868.837, 805.198, 2326.08 + 0.0, 15000.0, 0.7656, 9295.393, 2069.67, 2558.69 + 0.0, 15000.0, 0.8352, 8117.555, 2353.52, 2791.3 + 0.0, 15000.0, 0.9048, 22532.67, 5324.89, 3023.91 + 0.0, 15000.0, 0.9744, -366.1336, 2489.81, 3256.52 + 0.0, 18000.0, 0.0, 331.7385, 331.738, 0.0 + 0.0, 18000.0, 0.408, -18660.53, -3371.54, 1363.6 + 0.0, 18000.0, 0.476, -12470.88, -2194.4, 1590.87 + 0.0, 18000.0, 0.544, -6281.174, -1017.32, 1818.14 + 0.0, 18000.0, 0.612, -91.46354, 159.764, 2045.4 + 0.0, 18000.0, 0.68, 1838.842, 794.516, 2272.67 + 0.0, 18000.0, 0.748, 3461.407, 958.955, 2499.94 + 0.0, 18000.0, 0.816, 8465.954, 1595.0, 2727.21 + 0.0, 18000.0, 0.884, 4672.626, 1685.1, 2954.47 + 0.0, 18000.0, 0.952, 30679.14, 5644.58, 3181.74 + 0.0, 21000.0, 0.0, 296.2731, 296.273, 0.0 + 0.0, 21000.0, 0.3984, 5188.337, 3488.55, 1331.57 + 0.0, 21000.0, 0.4648, 4883.055, 2747.02, 1553.5 + 0.0, 21000.0, 0.5312, 4577.828, 2005.5, 1775.43 + 0.0, 21000.0, 0.5977, 4272.565, 1263.94, 1997.35 + 0.0, 21000.0, 0.6641, 4056.199, 908.393, 2219.28 + 0.0, 21000.0, 0.7305, 1.572037, 649.552, 2441.21 + 0.0, 21000.0, 0.7969, 5555.629, 1337.9, 2663.14 + 0.0, 21000.0, 0.8633, 10865.94, 3806.66, 2885.07 + 0.0, 21000.0, 0.9297, 13527.6, 5415.27, 3106.99 + 0.0, 21000.0, 0.9961, 24247.31, 11037.8, 3328.92 + 0.0, 24000.0, 0.0, 263.8809, 263.881, 0.0 + 0.0, 24000.0, 0.3889, -2276.284, -4246.11, 1299.54 + 0.0, 24000.0, 0.4537, -1397.986, -3030.82, 1516.13 + 0.0, 24000.0, 0.5185, -519.6311, -1815.55, 1732.72 + 0.0, 24000.0, 0.5833, 358.6363, -600.279, 1949.31 + 0.0, 24000.0, 0.6481, 3549.538, 1028.19, 2165.9 + 0.0, 24000.0, 0.7129, 7246.497, 2298.21, 2382.49 + 0.0, 24000.0, 0.7777, 8081.882, 2419.34, 2599.08 + 0.0, 24000.0, 0.8425, 10914.13, 2151.44, 2815.67 + 0.0, 24000.0, 0.9073, 8142.089, 2189.65, 3032.26 + 0.0, 24000.0, 0.9721, 9356.254, 3346.39, 3248.85 + 0.0, 27000.0, 0.0, 234.3597, 234.36, 0.0 + 0.0, 27000.0, 0.3793, 31666.47, 15546.0, 1267.53 + 0.0, 27000.0, 0.4425, 22716.75, 11633.7, 1478.78 + 0.0, 27000.0, 0.5057, 13766.91, 7721.39, 1690.03 + 0.0, 27000.0, 0.5689, 4817.089, 3809.05, 1901.29 + 0.0, 27000.0, 0.6321, -4080.9, -421.773, 2112.54 + 0.0, 27000.0, 0.6953, 3533.179, 157.007, 2323.8 + 0.0, 27000.0, 0.7585, 2905.361, 84.2961, 2535.05 + 0.0, 27000.0, 0.8218, -631.5598, 2054.88, 2746.31 + 0.0, 27000.0, 0.885, 10808.44, 2537.84, 2957.56 + 0.0, 27000.0, 0.9482, -1558.288, 3488.26, 3168.81 + 0.0, 30000.0, 0.0, 207.5184, 207.518, 0.0 + 0.0, 30000.0, 0.3697, 423.6084, 2063.46, 1235.52 + 0.0, 30000.0, 0.4313, 2344.484, 1915.56, 1441.44 + 0.0, 30000.0, 0.4929, 4264.665, 1767.88, 1647.35 + 0.0, 30000.0, 0.5545, 6185.203, 1620.07, 1853.27 + 0.0, 30000.0, 0.6162, 4867.514, 174.702, 2059.19 + 0.0, 30000.0, 0.6778, -1357.865, 312.415, 2265.11 + 0.0, 30000.0, 0.7394, 916.2129, -601.59, 2471.03 + 0.0, 30000.0, 0.801, 2808.161, -2068.88, 2676.95 + 0.0, 30000.0, 0.8626, 14043.93, 6579.6, 2882.87 + 0.0, 30000.0, 0.9242, 29400.55, 4365.93, 3088.79 + 0.0, 30000.0, 0.9858, 60041.21, 12221.7, 3294.71 + 0.0, 33000.0, 0.0, 183.1715, 183.171, 0.0 + 0.0, 33000.0, 0.3601, 73148.22, 8353.32, 1203.52 + 0.0, 33000.0, 0.4201, 57096.47, 6361.09, 1404.11 + 0.0, 33000.0, 0.4802, 41044.58, 4368.84, 1604.69 + 0.0, 33000.0, 0.5402, 24992.67, 2376.71, 1805.28 + 0.0, 33000.0, 0.6002, 8940.68, 384.355, 2005.86 + 0.0, 33000.0, 0.6602, -2678.417, -598.454, 2206.45 + 0.0, 33000.0, 0.7202, 11541.78, 4514.57, 2407.04 + 0.0, 33000.0, 0.7803, 10052.41, 3617.19, 2607.62 + 0.0, 33000.0, 0.8403, -5615.761, -4056.63, 2808.21 + 0.0, 33000.0, 0.9003, 3125.791, 1784.91, 3008.8 + 0.0, 33000.0, 0.9603, -53986.26, -34872.5, 3209.38 + 0.0, 36000.0, 0.0, 161.1448, 161.145, 0.0 + 0.0, 36000.0, 0.3505, 69414.82, 6249.21, 1171.53 + 0.0, 36000.0, 0.409, 54979.25, 5111.87, 1366.78 + 0.0, 36000.0, 0.4674, 40543.32, 3974.52, 1562.03 + 0.0, 36000.0, 0.5258, 26107.68, 2837.21, 1757.29 + 0.0, 36000.0, 0.5842, 11671.9, 1699.74, 1952.54 + 0.0, 36000.0, 0.6427, 1488.745, 509.04, 2147.8 + 0.0, 36000.0, 0.7011, 908.5232, 93.532, 2343.05 + 0.0, 36000.0, 0.7595, -22077.38, -3060.69, 2538.31 + 0.0, 36000.0, 0.8179, 47160.97, 10763.0, 2733.56 + 0.0, 36000.0, 0.8764, 16056.51, 5520.05, 2928.81 + 0.0, 36000.0, 0.9348, -24769.22, -23716.9, 3124.07 + 0.0, 39000.0, 0.0, 139.6755, 139.675, 0.0 + 0.0, 39000.0, 0.3501, 476.7687, 100.476, 1169.91 + 0.0, 39000.0, 0.4084, -266.4172, -23.404, 1364.9 + 0.0, 39000.0, 0.4668, -1009.892, -147.275, 1559.88 + 0.0, 39000.0, 0.5251, -1753.168, -271.066, 1754.87 + 0.0, 39000.0, 0.5834, -2496.615, -394.901, 1949.85 + 0.0, 39000.0, 0.6418, -4195.442, -718.928, 2144.84 + 0.0, 39000.0, 0.7001, -200.1008, -10.5781, 2339.82 + 0.0, 39000.0, 0.7585, -4917.31, -2004.88, 2534.81 + 0.0, 39000.0, 0.8168, 6913.46, -4331.27, 2729.79 + 0.0, 39000.0, 0.8752, 11889.89, 4348.43, 2924.78 + 0.0, 39000.0, 0.9335, 120355.9, 68678.6, 3119.76 + 0.0, 42000.0, 0.0, 120.9878, 120.988, 0.0 + 0.0, 42000.0, 0.3501, -462426.5, -178028.0, 1169.91 + 0.0, 42000.0, 0.4084, -362856.0, -139382.0, 1364.9 + 0.0, 42000.0, 0.4668, -263285.6, -100736.0, 1559.88 + 0.0, 42000.0, 0.5251, -163715.4, -62090.5, 1754.87 + 0.0, 42000.0, 0.5834, -64145.01, -23445.0, 1949.85 + 0.0, 42000.0, 0.6418, -17490.57, -5916.43, 2144.84 + 0.0, 42000.0, 0.7001, 9317.001, 942.013, 2339.82 + 0.0, 42000.0, 0.7585, -11674.67, -219.079, 2534.81 + 0.0, 42000.0, 0.8168, 25036.39, 13878.4, 2729.79 + 0.0, 42000.0, 0.8752, -11573.79, -5031.32, 2924.78 + 0.0, 42000.0, 0.9335, 18711.33, 14545.3, 3119.76 + 0.05, 0.0, 0.0, 622.4046, 622.405, 0.0 + 0.05, 0.0, 0.4658, -1937.372, -104.125, 1556.79 + 0.05, 0.0, 0.5435, 906.8547, 545.148, 1816.25 + 0.05, 0.0, 0.6211, 3751.082, 1194.42, 2075.72 + 0.05, 0.0, 0.6987, 6786.726, 1886.27, 2335.18 + 0.05, 0.0, 0.7764, 10343.11, 2825.13, 2594.65 + 0.05, 0.0, 0.854, 14849.09, 4132.93, 2854.11 + 0.05, 0.0, 0.9317, 20803.98, 5925.92, 3113.58 + 0.05, 3000.0, 0.0, 563.6774, 563.677, 0.0 + 0.05, 3000.0, 0.4562, -2248.27, -179.918, 1524.68 + 0.05, 3000.0, 0.5323, 396.6363, 416.518, 1778.8 + 0.05, 3000.0, 0.6083, 3041.543, 1012.95, 2032.91 + 0.05, 3000.0, 0.6843, 5721.067, 1627.13, 2287.02 + 0.05, 3000.0, 0.7604, 8885.487, 2447.13, 2541.14 + 0.05, 3000.0, 0.8364, 12820.92, 3565.8, 2795.25 + 0.05, 3000.0, 0.9124, 18151.57, 5134.59, 3049.37 + 0.05, 3000.0, 0.9885, 24712.7, 7106.73, 3303.48 + 0.05, 6000.0, 0.0, 509.4305, 509.431, 0.0 + 0.05, 6000.0, 0.4466, -2750.051, -271.651, 1492.58 + 0.05, 6000.0, 0.521, -204.4496, 283.846, 1741.35 + 0.05, 6000.0, 0.5955, 2341.152, 839.343, 1990.11 + 0.05, 6000.0, 0.6699, 4887.933, 1395.47, 2238.88 + 0.05, 6000.0, 0.7444, 7675.514, 2103.74, 2487.64 + 0.05, 6000.0, 0.8188, 11181.16, 3080.56, 2736.4 + 0.05, 6000.0, 0.8932, 15767.37, 4411.24, 2985.17 + 0.05, 6000.0, 0.9677, 21640.42, 6158.17, 3233.93 + 0.05, 9000.0, 0.0, 459.4074, 459.407, 0.0 + 0.05, 9000.0, 0.437, -1627.546, -281.515, 1460.5 + 0.05, 9000.0, 0.5098, 358.4682, 213.743, 1703.91 + 0.05, 9000.0, 0.5827, 2344.48, 709.002, 1947.33 + 0.05, 9000.0, 0.6555, 4330.492, 1204.26, 2190.74 + 0.05, 9000.0, 0.7284, 6540.991, 1796.92, 2434.16 + 0.05, 9000.0, 0.8012, 9705.083, 2638.35, 2677.58 + 0.05, 9000.0, 0.874, 13670.45, 3784.25, 2920.99 + 0.05, 9000.0, 0.9469, 18768.78, 5284.29, 3164.41 + 0.05, 12000.0, 0.0, 413.3563, 413.356, 0.0 + 0.05, 12000.0, 0.4274, -5981.429, -454.169, 1428.42 + 0.05, 12000.0, 0.4986, -2971.17, 31.739, 1666.48 + 0.05, 12000.0, 0.5699, 39.10165, 517.652, 1904.55 + 0.05, 12000.0, 0.6411, 3049.367, 1003.57, 2142.62 + 0.05, 12000.0, 0.7124, 6215.423, 1593.54, 2380.69 + 0.05, 12000.0, 0.7836, 9242.337, 2316.04, 2618.76 + 0.05, 12000.0, 0.8548, 10783.71, 3081.6, 2856.83 + 0.05, 12000.0, 0.9261, 16227.54, 4497.38, 3094.9 + 0.05, 12000.0, 0.9973, 21278.34, 6067.84, 3332.97 + 0.05, 15000.0, 0.0, 371.0421, 371.042, 0.0 + 0.05, 15000.0, 0.4178, -3422.131, -736.515, 1396.35 + 0.05, 15000.0, 0.4875, -1572.361, -249.619, 1629.07 + 0.05, 15000.0, 0.5571, 277.4521, 237.289, 1861.8 + 0.05, 15000.0, 0.6267, 2127.25, 724.185, 2094.52 + 0.05, 15000.0, 0.6964, 3919.875, 993.187, 2327.25 + 0.05, 15000.0, 0.766, 8107.05, 2006.61, 2559.97 + 0.05, 15000.0, 0.8356, 8295.775, 2489.49, 2792.69 + 0.05, 15000.0, 0.9053, 18916.62, 4803.55, 3025.42 + 0.05, 15000.0, 0.9749, 5936.334, 3539.5, 3258.14 + 0.05, 18000.0, 0.0, 332.2363, 332.236, 0.0 + 0.05, 18000.0, 0.4082, -13675.57, -2474.18, 1364.28 + 0.05, 18000.0, 0.4763, -8945.339, -1537.78, 1591.67 + 0.05, 18000.0, 0.5443, -4215.065, -601.426, 1819.05 + 0.05, 18000.0, 0.6123, 515.2119, 334.94, 2046.43 + 0.05, 18000.0, 0.6804, 2286.805, 893.93, 2273.81 + 0.05, 18000.0, 0.7484, 3918.886, 1174.02, 2501.19 + 0.05, 18000.0, 0.8164, 7981.962, 1803.38, 2728.57 + 0.05, 18000.0, 0.8845, 6270.014, 2149.15, 2955.95 + 0.05, 18000.0, 0.9525, 25369.33, 5247.76, 3183.33 + 0.05, 21000.0, 0.0, 296.7177, 296.718, 0.0 + 0.05, 21000.0, 0.3986, 2763.043, 2319.55, 1332.23 + 0.05, 21000.0, 0.4651, 2979.908, 1901.57, 1554.27 + 0.05, 21000.0, 0.5315, 3196.813, 1483.59, 1776.31 + 0.05, 21000.0, 0.598, 3413.692, 1065.59, 1998.35 + 0.05, 21000.0, 0.6644, 3661.647, 912.159, 2220.39 + 0.05, 21000.0, 0.7308, 1190.716, 855.518, 2442.43 + 0.05, 21000.0, 0.7973, 5622.829, 1504.08, 2664.47 + 0.05, 21000.0, 0.8637, 10217.83, 3505.38, 2886.51 + 0.05, 21000.0, 0.9301, 12690.26, 4869.68, 3108.55 + 0.05, 21000.0, 0.9966, 20717.67, 9070.13, 3330.59 + 0.05, 24000.0, 0.0, 264.277, 264.277, 0.0 + 0.05, 24000.0, 0.389, -2747.962, -3334.67, 1300.19 + 0.05, 24000.0, 0.4539, -1687.357, -2335.16, 1516.89 + 0.05, 24000.0, 0.5187, -626.7098, -1335.66, 1733.59 + 0.05, 24000.0, 0.5836, 433.8732, -336.157, 1950.29 + 0.05, 24000.0, 0.6484, 3143.998, 952.847, 2166.98 + 0.05, 24000.0, 0.7133, 6284.657, 2004.58, 2383.68 + 0.05, 24000.0, 0.7781, 7322.359, 2223.93, 2600.38 + 0.05, 24000.0, 0.8429, 9905.924, 2188.1, 2817.08 + 0.05, 24000.0, 0.9078, 8487.755, 2430.26, 3033.78 + 0.05, 24000.0, 0.9726, 10105.1, 3585.98, 3250.48 + 0.05, 27000.0, 0.0, 234.7114, 234.711, 0.0 + 0.05, 27000.0, 0.3795, 22931.45, 11532.9, 1268.16 + 0.05, 27000.0, 0.4427, 16521.53, 8669.76, 1479.52 + 0.05, 27000.0, 0.5059, 10111.52, 5806.6, 1690.88 + 0.05, 27000.0, 0.5692, 3701.532, 2943.44, 1902.24 + 0.05, 27000.0, 0.6324, -2626.562, -141.316, 2113.6 + 0.05, 27000.0, 0.6957, 3350.71, 356.181, 2324.96 + 0.05, 27000.0, 0.7589, 3285.4, 427.329, 2536.32 + 0.05, 27000.0, 0.8222, 1028.761, 2045.9, 2747.68 + 0.05, 27000.0, 0.8854, 10204.39, 2577.58, 2959.04 + 0.05, 27000.0, 0.9487, 1146.705, 3424.54, 3170.4 + 0.05, 30000.0, 0.0, 207.8298, 207.83, 0.0 + 0.05, 30000.0, 0.3699, -109.3373, 1478.25, 1236.13 + 0.05, 30000.0, 0.4315, 1570.197, 1424.71, 1442.16 + 0.05, 30000.0, 0.4932, 3249.19, 1371.33, 1648.18 + 0.05, 30000.0, 0.5548, 4928.461, 1317.86, 1854.2 + 0.05, 30000.0, 0.6165, 4116.789, 266.266, 2060.22 + 0.05, 30000.0, 0.6781, -612.2555, 406.931, 2266.25 + 0.05, 30000.0, 0.7398, 1491.772, -206.138, 2472.27 + 0.05, 30000.0, 0.8014, 3295.707, -1231.19, 2678.29 + 0.05, 30000.0, 0.863, 12370.15, 5613.44, 2884.31 + 0.05, 30000.0, 0.9247, 24896.87, 4169.04, 3090.33 + 0.05, 30000.0, 0.9863, 49261.2, 10598.3, 3296.36 + 0.05, 33000.0, 0.0, 183.4464, 183.446, 0.0 + 0.05, 33000.0, 0.3603, 57217.34, 6462.07, 1204.12 + 0.05, 33000.0, 0.4203, 44718.9, 4942.36, 1404.81 + 0.05, 33000.0, 0.4804, 32220.35, 3422.63, 1605.49 + 0.05, 33000.0, 0.5404, 19721.77, 1903.0, 1806.18 + 0.05, 33000.0, 0.6005, 7223.132, 383.198, 2006.87 + 0.05, 33000.0, 0.6605, -1714.225, -318.244, 2207.55 + 0.05, 33000.0, 0.7206, 9696.97, 3766.08, 2408.24 + 0.05, 33000.0, 0.7806, 8800.634, 3135.41, 2608.93 + 0.05, 33000.0, 0.8407, -3143.183, -2751.99, 2809.61 + 0.05, 33000.0, 0.9007, 3650.194, 1749.95, 3010.3 + 0.05, 33000.0, 0.9608, -41981.77, -27546.7, 3210.99 + 0.05, 36000.0, 0.0, 161.3867, 161.387, 0.0 + 0.05, 36000.0, 0.3507, 54083.28, 4792.78, 1172.11 + 0.05, 36000.0, 0.4092, 42879.21, 3942.5, 1367.46 + 0.05, 36000.0, 0.4676, 31674.86, 3092.21, 1562.82 + 0.05, 36000.0, 0.5261, 20470.74, 2241.95, 1758.17 + 0.05, 36000.0, 0.5845, 9266.509, 1391.57, 1953.52 + 0.05, 36000.0, 0.643, 1420.988, 498.889, 2148.87 + 0.05, 36000.0, 0.7014, 1098.675, 214.436, 2344.22 + 0.05, 36000.0, 0.7599, -16849.84, -2203.47, 2539.58 + 0.05, 36000.0, 0.8184, 38222.79, 8790.3, 2734.93 + 0.05, 36000.0, 0.8768, 13946.35, 4859.69, 2930.28 + 0.05, 36000.0, 0.9353, -18581.36, -18345.4, 3125.63 + 0.05, 39000.0, 0.0, 139.8851, 139.885, 0.0 + 0.05, 39000.0, 0.3502, 297.7573, 18.4149, 1170.49 + 0.05, 39000.0, 0.4086, -246.1483, -51.464, 1365.58 + 0.05, 39000.0, 0.467, -790.2804, -121.335, 1560.66 + 0.05, 39000.0, 0.5254, -1334.255, -191.143, 1755.74 + 0.05, 39000.0, 0.5837, -1878.366, -260.985, 1950.82 + 0.05, 39000.0, 0.6421, -3177.828, -503.226, 2145.91 + 0.05, 39000.0, 0.7005, 147.0694, 104.105, 2340.99 + 0.05, 39000.0, 0.7588, -3416.965, -1402.69, 2536.07 + 0.05, 39000.0, 0.8172, 6216.859, -3200.33, 2731.15 + 0.05, 39000.0, 0.8756, 10314.05, 3770.81, 2926.24 + 0.05, 39000.0, 0.934, 95822.43, 54546.0, 3121.32 + 0.05, 42000.0, 0.0, 121.1694, 121.169, 0.0 + 0.05, 42000.0, 0.3502, -379307.8, -145963.0, 1170.49 + 0.05, 42000.0, 0.4086, -297621.7, -114274.0, 1365.58 + 0.05, 42000.0, 0.467, -215935.7, -82585.3, 1560.66 + 0.05, 42000.0, 0.5254, -134249.8, -50896.5, 1755.74 + 0.05, 42000.0, 0.5837, -52563.78, -19207.8, 1950.82 + 0.05, 42000.0, 0.6421, -14077.33, -4743.84, 2145.91 + 0.05, 42000.0, 0.7005, 7763.255, 869.388, 2340.99 + 0.05, 42000.0, 0.7588, -9094.636, -55.9812, 2536.07 + 0.05, 42000.0, 0.8172, 20796.76, 11430.5, 2731.15 + 0.05, 42000.0, 0.8756, -8526.099, -3736.2, 2926.24 + 0.05, 42000.0, 0.934, 16729.98, 12533.8, 3121.32 + 0.1, 0.0, 0.0, 625.2082, 625.208, 0.0 + 0.1, 0.0, 0.4665, -2011.883, -99.3087, 1559.12 + 0.1, 0.0, 0.5443, 630.3653, 552.14, 1818.98 + 0.1, 0.0, 0.622, 3272.614, 1203.59, 2078.83 + 0.1, 0.0, 0.6998, 6125.419, 1899.51, 2338.68 + 0.1, 0.0, 0.7775, 9521.647, 2845.69, 2598.54 + 0.1, 0.0, 0.8553, 13855.3, 4165.01, 2858.39 + 0.1, 0.0, 0.933, 19628.42, 5975.7, 3118.24 + 0.1, 3000.0, 0.0, 566.2165, 566.216, 0.0 + 0.1, 3000.0, 0.4569, -2313.859, -177.017, 1526.97 + 0.1, 3000.0, 0.5331, 193.1631, 421.989, 1781.46 + 0.1, 3000.0, 0.6092, 2700.185, 1020.99, 2035.96 + 0.1, 3000.0, 0.6854, 5250.777, 1639.64, 2290.45 + 0.1, 3000.0, 0.7615, 8308.462, 2467.48, 2544.95 + 0.1, 3000.0, 0.8377, 12111.91, 3595.1, 2799.44 + 0.1, 3000.0, 0.9138, 17311.67, 5179.06, 3053.94 + 0.1, 3000.0, 0.99, 23690.68, 7160.93, 3308.43 + 0.1, 6000.0, 0.0, 511.7253, 511.725, 0.0 + 0.1, 6000.0, 0.4473, -2534.252, -256.571, 1494.82 + 0.1, 6000.0, 0.5218, -211.1178, 297.407, 1743.96 + 0.1, 6000.0, 0.5964, 2112.016, 851.384, 1993.09 + 0.1, 6000.0, 0.6709, 4435.149, 1405.36, 2242.23 + 0.1, 6000.0, 0.7455, 7123.782, 2122.06, 2491.37 + 0.1, 6000.0, 0.82, 10496.66, 3109.14, 2740.51 + 0.1, 6000.0, 0.8946, 14965.5, 4455.73, 2989.64 + 0.1, 6000.0, 0.9691, 20653.14, 6216.63, 3238.78 + 0.1, 9000.0, 0.0, 461.4768, 461.477, 0.0 + 0.1, 9000.0, 0.4377, -2541.08, -310.567, 1462.69 + 0.1, 9000.0, 0.5106, -442.1006, 195.125, 1706.47 + 0.1, 9000.0, 0.5836, 1656.878, 700.818, 1950.25 + 0.1, 9000.0, 0.6565, 3755.857, 1206.51, 2194.03 + 0.1, 9000.0, 0.7294, 6110.103, 1819.85, 2437.81 + 0.1, 9000.0, 0.8024, 9037.513, 2663.94, 2681.59 + 0.1, 9000.0, 0.8753, 12865.36, 3816.21, 2925.37 + 0.1, 9000.0, 0.9483, 17810.15, 5327.4, 3169.15 + 0.1, 12000.0, 0.0, 415.2183, 415.218, 0.0 + 0.1, 12000.0, 0.4281, -3536.913, -348.353, 1430.56 + 0.1, 12000.0, 0.4994, -1373.469, 108.106, 1668.98 + 0.1, 12000.0, 0.5707, 789.9805, 564.567, 1907.41 + 0.1, 12000.0, 0.6421, 2953.427, 1021.03, 2145.84 + 0.1, 12000.0, 0.7134, 5376.871, 1566.42, 2384.26 + 0.1, 12000.0, 0.7848, 8124.962, 2295.05, 2622.69 + 0.1, 12000.0, 0.8561, 10739.45, 3200.65, 2861.11 + 0.1, 12000.0, 0.9275, 15355.03, 4528.34, 3099.54 + 0.1, 12000.0, 0.9988, 20015.49, 6050.92, 3337.97 + 0.1, 15000.0, 0.0, 372.7135, 372.713, 0.0 + 0.1, 15000.0, 0.4184, -2899.16, -571.042, 1398.44 + 0.1, 15000.0, 0.4882, -1193.485, -116.439, 1631.51 + 0.1, 15000.0, 0.5579, 512.2159, 338.17, 1864.59 + 0.1, 15000.0, 0.6277, 2217.908, 792.772, 2097.66 + 0.1, 15000.0, 0.6974, 3920.263, 1137.17, 2330.73 + 0.1, 15000.0, 0.7671, 7199.866, 1975.61, 2563.81 + 0.1, 15000.0, 0.8369, 8379.474, 2608.46, 2796.88 + 0.1, 15000.0, 0.9066, 16168.37, 4441.34, 3029.95 + 0.1, 15000.0, 0.9764, 10308.45, 4306.53, 3263.03 + 0.1, 18000.0, 0.0, 333.7329, 333.733, 0.0 + 0.1, 18000.0, 0.4088, -9788.776, -1769.35, 1366.33 + 0.1, 18000.0, 0.477, -6203.259, -1020.9, 1594.05 + 0.1, 18000.0, 0.5451, -2617.717, -272.481, 1821.77 + 0.1, 18000.0, 0.6133, 967.8267, 475.947, 2049.5 + 0.1, 18000.0, 0.6814, 2611.281, 978.045, 2277.22 + 0.1, 18000.0, 0.7495, 4255.16, 1348.7, 2504.94 + 0.1, 18000.0, 0.8177, 7612.584, 1985.03, 2732.66 + 0.1, 18000.0, 0.8858, 7486.398, 2532.26, 2960.38 + 0.1, 18000.0, 0.954, 21206.84, 4972.58, 3188.1 + 0.1, 21000.0, 0.0, 298.0543, 298.054, 0.0 + 0.1, 21000.0, 0.3992, 927.9313, 1411.72, 1334.23 + 0.1, 21000.0, 0.4658, 1530.867, 1246.38, 1556.6 + 0.1, 21000.0, 0.5323, 2133.83, 1081.05, 1778.98 + 0.1, 21000.0, 0.5988, 2736.775, 915.699, 2001.35 + 0.1, 21000.0, 0.6654, 3334.369, 922.085, 2223.72 + 0.1, 21000.0, 0.7319, 2118.567, 1028.22, 2446.09 + 0.1, 21000.0, 0.7985, 5682.668, 1652.36, 2668.46 + 0.1, 21000.0, 0.865, 9678.7, 3284.28, 2890.84 + 0.1, 21000.0, 0.9315, 12027.24, 4472.15, 3113.21 + 0.1, 21000.0, 0.9981, 17995.24, 7578.15, 3335.58 + 0.1, 24000.0, 0.0, 265.4674, 265.467, 0.0 + 0.1, 24000.0, 0.3896, -3017.822, -2577.09, 1302.14 + 0.1, 24000.0, 0.4546, -1841.305, -1756.18, 1519.16 + 0.1, 24000.0, 0.5195, -664.7591, -935.271, 1736.19 + 0.1, 24000.0, 0.5844, 511.7419, -114.367, 1953.21 + 0.1, 24000.0, 0.6494, 2811.075, 898.286, 2170.23 + 0.1, 24000.0, 0.7143, 5487.854, 1772.89, 2387.26 + 0.1, 24000.0, 0.7793, 6695.067, 2076.14, 2604.28 + 0.1, 24000.0, 0.8442, 9078.895, 2232.97, 2821.3 + 0.1, 24000.0, 0.9091, 8740.784, 2643.13, 3038.33 + 0.1, 24000.0, 0.9741, 10632.69, 3783.04, 3255.35 + 0.1, 27000.0, 0.0, 235.7687, 235.769, 0.0 + 0.1, 27000.0, 0.38, 15827.53, 8247.9, 1270.06 + 0.1, 27000.0, 0.4434, 11485.0, 6244.88, 1481.74 + 0.1, 27000.0, 0.5067, 7142.405, 4241.82, 1693.41 + 0.1, 27000.0, 0.57, 2799.823, 2238.76, 1905.09 + 0.1, 27000.0, 0.6334, -1446.007, 89.4972, 2116.77 + 0.1, 27000.0, 0.6967, 3193.343, 525.597, 2328.44 + 0.1, 27000.0, 0.7601, 3581.758, 714.225, 2540.12 + 0.1, 27000.0, 0.8234, 2379.171, 2047.14, 2751.8 + 0.1, 27000.0, 0.8867, 9673.634, 2621.61, 2963.47 + 0.1, 27000.0, 0.9501, 3357.267, 3398.07, 3175.15 + 0.1, 30000.0, 0.0, 208.766, 208.766, 0.0 + 0.1, 30000.0, 0.3704, -571.8782, 987.135, 1237.99 + 0.1, 30000.0, 0.4322, 906.9156, 1013.53, 1444.32 + 0.1, 30000.0, 0.4939, 2385.297, 1040.06, 1650.65 + 0.1, 30000.0, 0.5556, 3863.889, 1066.52, 1856.98 + 0.1, 30000.0, 0.6174, 3474.275, 344.379, 2063.31 + 0.1, 30000.0, 0.6791, 18.9526, 493.291, 2269.64 + 0.1, 30000.0, 0.7409, 1969.51, 132.613, 2475.97 + 0.1, 30000.0, 0.8026, 3700.864, -519.561, 2682.31 + 0.1, 30000.0, 0.8643, 10959.75, 4812.41, 2888.64 + 0.1, 30000.0, 0.9261, 21054.53, 3993.45, 3094.97 + 0.1, 30000.0, 0.9878, 40095.13, 9195.8, 3301.3 + 0.1, 33000.0, 0.0, 184.2727, 184.273, 0.0 + 0.1, 33000.0, 0.3608, 43687.42, 4856.11, 1205.93 + 0.1, 33000.0, 0.421, 34207.31, 3738.63, 1406.91 + 0.1, 33000.0, 0.4811, 24727.12, 2621.13, 1607.9 + 0.1, 33000.0, 0.5413, 15246.91, 1503.71, 1808.89 + 0.1, 33000.0, 0.6014, 5766.653, 386.151, 2009.88 + 0.1, 33000.0, 0.6615, -903.5495, -79.4511, 2210.86 + 0.1, 33000.0, 0.7217, 8126.707, 3135.4, 2411.85 + 0.1, 33000.0, 0.7818, 7733.799, 2735.11, 2612.84 + 0.1, 33000.0, 0.842, -1066.134, -1643.25, 2813.83 + 0.1, 33000.0, 0.9021, 4131.562, 1761.13, 3014.81 + 0.1, 33000.0, 0.9622, -31625.25, -21203.4, 3215.8 + 0.1, 36000.0, 0.0, 162.1136, 162.114, 0.0 + 0.1, 36000.0, 0.3512, 41090.52, 3556.33, 1173.87 + 0.1, 36000.0, 0.4098, 32625.62, 2950.69, 1369.51 + 0.1, 36000.0, 0.4683, 24160.5, 2345.04, 1565.16 + 0.1, 36000.0, 0.5269, 15695.56, 1739.41, 1760.8 + 0.1, 36000.0, 0.5854, 7230.533, 1133.7, 1956.45 + 0.1, 36000.0, 0.644, 1364.116, 494.616, 2152.09 + 0.1, 36000.0, 0.7025, 1268.325, 324.24, 2347.74 + 0.1, 36000.0, 0.761, -12394.3, -1466.4, 2543.38 + 0.1, 36000.0, 0.8196, 30619.6, 7126.41, 2739.03 + 0.1, 36000.0, 0.8781, 12129.06, 4292.99, 2934.67 + 0.1, 36000.0, 0.9367, -13311.97, -13772.9, 3130.32 + 0.1, 39000.0, 0.0, 140.5152, 140.515, 0.0 + 0.1, 39000.0, 0.3508, 92.9512, -57.5174, 1172.25 + 0.1, 39000.0, 0.4092, -270.2002, -79.7978, 1367.62 + 0.1, 39000.0, 0.4677, -633.5255, -102.072, 1563.0 + 0.1, 39000.0, 0.5261, -996.7287, -124.296, 1758.37 + 0.1, 39000.0, 0.5846, -1360.038, -146.548, 1953.75 + 0.1, 39000.0, 0.6431, -2307.873, -315.054, 2149.12 + 0.1, 39000.0, 0.7015, 446.4424, 207.393, 2344.5 + 0.1, 39000.0, 0.76, -2130.312, -884.72, 2539.87 + 0.1, 39000.0, 0.8184, 5624.611, -2225.96, 2735.25 + 0.1, 39000.0, 0.8769, 8977.311, 3289.46, 2930.62 + 0.1, 39000.0, 0.9354, 75013.81, 42558.8, 3126.0 + 0.1, 42000.0, 0.0, 121.7152, 121.715, 0.0 + 0.1, 42000.0, 0.3508, -306857.2, -118021.0, 1172.25 + 0.1, 42000.0, 0.4092, -240760.7, -92393.3, 1367.62 + 0.1, 42000.0, 0.4677, -174664.2, -66766.0, 1563.0 + 0.1, 42000.0, 0.5261, -108567.8, -41138.7, 1758.37 + 0.1, 42000.0, 0.5846, -42471.32, -15511.6, 1953.75 + 0.1, 42000.0, 0.6431, -11125.22, -3727.21, 2149.12 + 0.1, 42000.0, 0.7015, 6419.422, 806.782, 2344.5 + 0.1, 42000.0, 0.76, -6860.387, 91.4007, 2539.87 + 0.1, 42000.0, 0.8184, 17132.48, 9318.98, 2735.25 + 0.1, 42000.0, 0.8769, -5909.965, -2619.32, 2930.62 + 0.1, 42000.0, 0.9354, 14914.66, 10745.3, 3126.0 + 0.15, 0.0, 0.0, 629.8996, 629.9, 0.0 + 0.15, 0.0, 0.4677, -1595.501, -74.0941, 1563.01 + 0.15, 0.0, 0.5456, 705.9526, 574.91, 1823.51 + 0.15, 0.0, 0.6236, 3007.407, 1223.91, 2084.02 + 0.15, 0.0, 0.7015, 5609.047, 1922.99, 2344.52 + 0.15, 0.0, 0.7795, 8876.09, 2883.8, 2605.02 + 0.15, 0.0, 0.8574, 13067.2, 4221.35, 2865.52 + 0.15, 0.0, 0.9354, 18695.76, 6062.88, 3126.02 + 0.15, 3000.0, 0.0, 570.4652, 570.465, 0.0 + 0.15, 3000.0, 0.458, -2181.347, -165.775, 1530.78 + 0.15, 3000.0, 0.5344, 124.0648, 435.771, 1785.91 + 0.15, 3000.0, 0.6107, 2429.477, 1037.32, 2041.04 + 0.15, 3000.0, 0.6871, 4789.782, 1661.28, 2296.17 + 0.15, 3000.0, 0.7634, 7712.867, 2500.24, 2551.3 + 0.15, 3000.0, 0.8397, 11398.75, 3645.98, 2806.43 + 0.15, 3000.0, 0.9161, 16460.69, 5252.58, 3061.56 + 0.15, 3000.0, 0.9924, 22616.3, 7246.4, 3316.69 + 0.15, 6000.0, 0.0, 515.5651, 515.565, 0.0 + 0.15, 6000.0, 0.4484, -2318.263, -239.717, 1498.55 + 0.15, 6000.0, 0.5231, -200.2143, 314.33, 1748.31 + 0.15, 6000.0, 0.5979, 1917.835, 868.378, 1998.07 + 0.15, 6000.0, 0.6726, 4035.884, 1422.43, 2247.83 + 0.15, 6000.0, 0.7473, 6617.028, 2149.87, 2497.58 + 0.15, 6000.0, 0.8221, 9875.911, 3152.01, 2747.34 + 0.15, 6000.0, 0.8968, 14248.81, 4521.65, 2997.1 + 0.15, 6000.0, 0.9715, 19754.52, 6301.74, 3246.86 + 0.15, 9000.0, 0.0, 464.9396, 464.94, 0.0 + 0.15, 9000.0, 0.4388, -2540.336, -308.143, 1466.34 + 0.15, 9000.0, 0.5119, -555.764, 201.766, 1710.72 + 0.15, 9000.0, 0.585, 1428.809, 711.675, 1955.11 + 0.15, 9000.0, 0.6581, 3413.381, 1221.58, 2199.5 + 0.15, 9000.0, 0.7313, 5666.968, 1844.67, 2443.89 + 0.15, 9000.0, 0.8044, 8495.826, 2700.31, 2688.28 + 0.15, 9000.0, 0.8775, 12251.27, 3875.46, 2932.67 + 0.15, 9000.0, 0.9506, 17028.87, 5402.1, 3177.06 + 0.15, 12000.0, 0.0, 418.3339, 418.334, 0.0 + 0.15, 12000.0, 0.4291, -2305.409, -294.865, 1434.13 + 0.15, 12000.0, 0.5006, -587.8129, 150.674, 1673.15 + 0.15, 12000.0, 0.5722, 1129.784, 596.213, 1912.17 + 0.15, 12000.0, 0.6437, 2847.381, 1041.75, 2151.19 + 0.15, 12000.0, 0.7152, 4844.311, 1569.32, 2390.21 + 0.15, 12000.0, 0.7867, 7393.286, 2307.75, 2629.23 + 0.15, 12000.0, 0.8582, 10501.28, 3290.82, 2868.25 + 0.15, 12000.0, 0.9298, 14658.19, 4591.32, 3107.27 + 0.15, 15000.0, 0.0, 375.5102, 375.51, 0.0 + 0.15, 15000.0, 0.4195, -2520.839, -451.04, 1401.93 + 0.15, 15000.0, 0.4894, -931.7766, -18.3715, 1635.58 + 0.15, 15000.0, 0.5593, 657.2993, 414.3, 1869.24 + 0.15, 15000.0, 0.6292, 2246.371, 846.968, 2102.89 + 0.15, 15000.0, 0.6991, 3880.972, 1245.64, 2336.55 + 0.15, 15000.0, 0.7691, 6536.21, 1973.76, 2570.2 + 0.15, 15000.0, 0.839, 8392.314, 2716.59, 2803.86 + 0.15, 15000.0, 0.9089, 14170.51, 4219.59, 3037.51 + 0.15, 15000.0, 0.9788, 13079.83, 4844.29, 3271.17 + 0.15, 18000.0, 0.0, 336.2371, 336.237, 0.0 + 0.15, 18000.0, 0.4099, -6865.769, -1234.37, 1369.74 + 0.15, 18000.0, 0.4782, -4148.296, -627.051, 1598.03 + 0.15, 18000.0, 0.5465, -1430.809, -19.7463, 1826.32 + 0.15, 18000.0, 0.6148, 1286.679, 587.562, 2054.61 + 0.15, 18000.0, 0.6831, 2829.581, 1049.71, 2282.9 + 0.15, 18000.0, 0.7514, 4487.853, 1490.08, 2511.19 + 0.15, 18000.0, 0.8197, 7344.145, 2145.27, 2739.48 + 0.15, 18000.0, 0.888, 8374.399, 2847.76, 2967.77 + 0.15, 18000.0, 0.9563, 18054.61, 4806.92, 3196.06 + 0.15, 21000.0, 0.0, 300.2908, 300.291, 0.0 + 0.15, 21000.0, 0.4002, -395.5991, 732.692, 1337.56 + 0.15, 21000.0, 0.4669, 476.1362, 758.054, 1560.49 + 0.15, 21000.0, 0.5336, 1347.889, 783.42, 1783.41 + 0.15, 21000.0, 0.6003, 2219.631, 808.77, 2006.34 + 0.15, 21000.0, 0.667, 3067.974, 938.153, 2229.27 + 0.15, 21000.0, 0.7338, 2816.955, 1172.64, 2452.2 + 0.15, 21000.0, 0.8005, 5736.527, 1786.35, 2675.12 + 0.15, 21000.0, 0.8672, 9241.063, 3136.89, 2898.05 + 0.15, 21000.0, 0.9339, 11521.47, 4207.99, 3120.98 + 0.15, 24000.0, 0.0, 267.4594, 267.459, 0.0 + 0.15, 24000.0, 0.3906, -3119.5, -1959.31, 1305.39 + 0.15, 24000.0, 0.4557, -1883.092, -1283.05, 1522.95 + 0.15, 24000.0, 0.5208, -646.6636, -606.797, 1740.52 + 0.15, 24000.0, 0.5859, 589.7343, 69.4563, 1958.08 + 0.15, 24000.0, 0.651, 2543.752, 862.872, 2175.65 + 0.15, 24000.0, 0.7161, 4841.347, 1597.83, 2393.21 + 0.15, 24000.0, 0.7812, 6188.723, 1972.56, 2610.78 + 0.15, 24000.0, 0.8463, 8417.353, 2287.35, 2828.34 + 0.15, 24000.0, 0.9114, 8916.146, 2834.14, 3045.91 + 0.15, 24000.0, 0.9765, 10974.38, 3947.96, 3263.47 + 0.15, 27000.0, 0.0, 237.5378, 237.538, 0.0 + 0.15, 27000.0, 0.381, 10189.28, 5619.15, 1273.23 + 0.15, 27000.0, 0.4445, 7489.484, 4305.92, 1485.43 + 0.15, 27000.0, 0.508, 4789.635, 2992.65, 1697.64 + 0.15, 27000.0, 0.5715, 2089.798, 1679.38, 1909.84 + 0.15, 27000.0, 0.635, -510.8828, 276.448, 2122.05 + 0.15, 27000.0, 0.6985, 3060.009, 669.021, 2334.25 + 0.15, 27000.0, 0.762, 3805.421, 952.091, 2546.46 + 0.15, 27000.0, 0.8255, 3453.048, 2059.67, 2758.66 + 0.15, 27000.0, 0.8889, 9214.581, 2672.26, 2970.87 + 0.15, 27000.0, 0.9524, 5125.502, 3407.13, 3183.07 + 0.15, 30000.0, 0.0, 210.3325, 210.333, 0.0 + 0.15, 30000.0, 0.3714, -967.3588, 582.346, 1241.08 + 0.15, 30000.0, 0.4333, 347.277, 675.53, 1447.92 + 0.15, 30000.0, 0.4951, 1661.607, 768.81, 1654.77 + 0.15, 30000.0, 0.557, 2976.094, 862.034, 1861.61 + 0.15, 30000.0, 0.6189, 2931.884, 410.83, 2068.46 + 0.15, 30000.0, 0.6808, 545.8852, 572.708, 2275.31 + 0.15, 30000.0, 0.7427, 2359.71, 420.658, 2482.15 + 0.15, 30000.0, 0.8046, 4032.818, 78.4913, 2689.0 + 0.15, 30000.0, 0.8665, 9792.3, 4164.31, 2895.84 + 0.15, 30000.0, 0.9284, 17824.35, 3841.95, 3102.69 + 0.15, 30000.0, 0.9903, 32416.96, 8003.05, 3309.54 + 0.15, 33000.0, 0.0, 185.6555, 185.655, 0.0 + 0.15, 33000.0, 0.3617, 32364.6, 3512.65, 1208.93 + 0.15, 33000.0, 0.422, 25411.05, 2732.78, 1410.42 + 0.15, 33000.0, 0.4823, 18457.44, 1952.9, 1611.91 + 0.15, 33000.0, 0.5426, 11503.81, 1173.08, 1813.4 + 0.15, 33000.0, 0.6029, 4550.144, 393.159, 2014.89 + 0.15, 33000.0, 0.6632, -232.5511, 122.149, 2216.38 + 0.15, 33000.0, 0.7235, 6810.179, 2613.89, 2417.87 + 0.15, 33000.0, 0.7838, 6838.791, 2410.76, 2619.36 + 0.15, 33000.0, 0.8441, 651.0773, -712.216, 2820.85 + 0.15, 33000.0, 0.9043, 4571.671, 1813.77, 3022.34 + 0.15, 33000.0, 0.9646, -22795.11, -15770.3, 3223.83 + 0.15, 36000.0, 0.0, 163.3301, 163.33, 0.0 + 0.15, 36000.0, 0.3521, 30245.17, 2522.28, 1176.8 + 0.15, 36000.0, 0.4108, 24067.41, 2122.29, 1372.93 + 0.15, 36000.0, 0.4695, 17889.49, 1722.31, 1569.06 + 0.15, 36000.0, 0.5282, 11711.7, 1322.34, 1765.2 + 0.15, 36000.0, 0.5869, 5533.849, 922.294, 1961.33 + 0.15, 36000.0, 0.6456, 1317.799, 496.143, 2157.46 + 0.15, 36000.0, 0.7042, 1419.468, 424.367, 2353.6 + 0.15, 36000.0, 0.7629, -8648.141, -838.933, 2549.73 + 0.15, 36000.0, 0.8216, 24245.38, 5747.28, 2745.86 + 0.15, 36000.0, 0.8803, 10584.68, 3815.32, 2941.99 + 0.15, 36000.0, 0.939, -8883.05, -9931.01, 3138.13 + 0.15, 39000.0, 0.0, 141.5696, 141.57, 0.0 + 0.15, 39000.0, 0.3516, -131.4163, -127.506, 1175.17 + 0.15, 39000.0, 0.4102, -331.6345, -108.046, 1371.04 + 0.15, 39000.0, 0.4689, -531.9828, -88.5811, 1566.9 + 0.15, 39000.0, 0.5275, -732.2386, -69.0785, 1762.76 + 0.15, 39000.0, 0.5861, -932.5758, -49.5968, 1958.62 + 0.15, 39000.0, 0.6447, -1573.412, -151.909, 2154.49 + 0.15, 39000.0, 0.7033, 702.4008, 300.673, 2350.35 + 0.15, 39000.0, 0.7619, -1039.935, -443.342, 2546.21 + 0.15, 39000.0, 0.8205, 5129.54, -1394.93, 2742.07 + 0.15, 39000.0, 0.8791, 7861.529, 2897.86, 2937.94 + 0.15, 39000.0, 0.9377, 57627.94, 32544.4, 3133.8 + 0.15, 42000.0, 0.0, 122.6285, 122.629, 0.0 + 0.15, 42000.0, 0.3516, -244342.1, -93916.6, 1175.17 + 0.15, 42000.0, 0.4102, -191697.7, -73517.2, 1371.04 + 0.15, 42000.0, 0.4689, -139053.3, -53117.8, 1566.9 + 0.15, 42000.0, 0.5275, -86409.02, -32718.3, 1762.76 + 0.15, 42000.0, 0.5861, -33764.64, -12319.0, 1958.62 + 0.15, 42000.0, 0.6447, -8600.264, -2854.88, 2154.49 + 0.15, 42000.0, 0.7033, 5271.145, 754.249, 2350.35 + 0.15, 42000.0, 0.7619, -4946.085, 224.801, 2546.21 + 0.15, 42000.0, 0.8205, 14003.03, 7520.6, 2742.07 + 0.15, 42000.0, 0.8791, -3691.53, -1665.99, 2937.94 + 0.15, 42000.0, 0.9377, 13262.19, 9169.17, 3133.8 + 0.2, 0.0, 0.0, 636.5069, 636.507, 0.0 + 0.2, 0.0, 0.4693, -1542.081, -64.2361, 1568.46 + 0.2, 0.0, 0.5475, 640.9626, 593.117, 1829.87 + 0.2, 0.0, 0.6258, 2824.006, 1250.47, 2091.28 + 0.2, 0.0, 0.704, 5274.056, 1959.81, 2352.69 + 0.2, 0.0, 0.7822, 8355.228, 2938.65, 2614.1 + 0.2, 0.0, 0.8604, 12458.01, 4302.44, 2875.51 + 0.2, 0.0, 0.9386, 17981.37, 6187.37, 3136.92 + 0.2, 3000.0, 0.0, 576.449, 576.449, 0.0 + 0.2, 3000.0, 0.4596, -1929.121, -149.344, 1536.11 + 0.2, 3000.0, 0.5362, 191.1132, 456.802, 1792.13 + 0.2, 3000.0, 0.6129, 2311.348, 1062.95, 2048.15 + 0.2, 3000.0, 0.6895, 4495.357, 1695.16, 2304.17 + 0.2, 3000.0, 0.7661, 7260.212, 2547.18, 2560.19 + 0.2, 3000.0, 0.8427, 10867.08, 3720.48, 2816.21 + 0.2, 3000.0, 0.9193, 15824.35, 5357.96, 3072.22 + 0.2, 3000.0, 0.9959, 21722.54, 7363.9, 3328.24 + 0.2, 6000.0, 0.0, 520.9731, 520.973, 0.0 + 0.2, 6000.0, 0.45, -2131.915, -225.729, 1503.77 + 0.2, 6000.0, 0.525, -154.4856, 333.127, 1754.4 + 0.2, 6000.0, 0.5999, 1822.944, 891.983, 2005.03 + 0.2, 6000.0, 0.6749, 3805.092, 1453.37, 2255.66 + 0.2, 6000.0, 0.7499, 6213.947, 2191.16, 2506.29 + 0.2, 6000.0, 0.8249, 9396.924, 3213.36, 2756.92 + 0.2, 6000.0, 0.8999, 13711.43, 4618.51, 3007.54 + 0.2, 6000.0, 0.9749, 19006.34, 6419.64, 3258.17 + 0.2, 9000.0, 0.0, 469.8165, 469.817, 0.0 + 0.2, 9000.0, 0.4403, -2245.992, -296.713, 1471.44 + 0.2, 9000.0, 0.5137, -424.355, 217.808, 1716.69 + 0.2, 9000.0, 0.5871, 1397.281, 732.329, 1961.93 + 0.2, 9000.0, 0.6604, 3218.918, 1246.85, 2207.17 + 0.2, 9000.0, 0.7338, 5313.586, 1879.84, 2452.41 + 0.2, 9000.0, 0.8072, 8076.606, 2752.61, 2697.65 + 0.2, 9000.0, 0.8806, 11792.01, 3960.09, 2942.89 + 0.2, 9000.0, 0.954, 16407.08, 5508.87, 3188.13 + 0.2, 12000.0, 0.0, 422.722, 422.722, 0.0 + 0.2, 12000.0, 0.4306, -1917.463, -278.893, 1439.12 + 0.2, 12000.0, 0.5024, -366.8472, 169.381, 1678.98 + 0.2, 12000.0, 0.5742, 1183.768, 617.656, 1918.83 + 0.2, 12000.0, 0.6459, 2734.384, 1065.93, 2158.69 + 0.2, 12000.0, 0.7177, 4538.605, 1596.34, 2398.54 + 0.2, 12000.0, 0.7895, 6956.834, 2349.0, 2638.39 + 0.2, 12000.0, 0.8612, 10168.98, 3370.58, 2878.25 + 0.2, 12000.0, 0.933, 14116.28, 4685.48, 3118.1 + 0.2, 15000.0, 0.0, 379.4491, 379.449, 0.0 + 0.2, 15000.0, 0.4209, -2268.589, -370.224, 1406.81 + 0.2, 15000.0, 0.4911, -770.5034, 49.9402, 1641.28 + 0.2, 15000.0, 0.5613, 727.5877, 470.106, 1875.75 + 0.2, 15000.0, 0.6314, 2225.677, 890.271, 2110.22 + 0.2, 15000.0, 0.7016, 3812.971, 1327.05, 2344.69 + 0.2, 15000.0, 0.7717, 6078.45, 1998.15, 2579.16 + 0.2, 15000.0, 0.8419, 8357.957, 2820.04, 2813.63 + 0.2, 15000.0, 0.9121, 12805.63, 4119.65, 3048.1 + 0.2, 15000.0, 0.9822, 14580.07, 5206.18, 3282.57 + 0.2, 18000.0, 0.0, 339.7641, 339.764, 0.0 + 0.2, 18000.0, 0.4113, -4772.187, -846.551, 1374.51 + 0.2, 18000.0, 0.4798, -2684.109, -339.51, 1603.6 + 0.2, 18000.0, 0.5484, -596.0216, 167.522, 1832.68 + 0.2, 18000.0, 0.6169, 1492.066, 674.557, 2061.77 + 0.2, 18000.0, 0.6855, 2959.017, 1111.79, 2290.85 + 0.2, 18000.0, 0.754, 4634.591, 1605.27, 2519.94 + 0.2, 18000.0, 0.8226, 7162.972, 2289.42, 2749.02 + 0.2, 18000.0, 0.8911, 8986.639, 3109.01, 2978.11 + 0.2, 18000.0, 0.9597, 15775.61, 4738.68, 3207.19 + 0.2, 21000.0, 0.0, 303.4407, 303.441, 0.0 + 0.2, 21000.0, 0.4016, -1286.15, 250.12, 1342.22 + 0.2, 21000.0, 0.4686, -244.0783, 413.181, 1565.93 + 0.2, 21000.0, 0.5355, 798.0037, 576.244, 1789.63 + 0.2, 21000.0, 0.6024, 1840.079, 739.299, 2013.33 + 0.2, 21000.0, 0.6694, 2856.067, 960.346, 2237.04 + 0.2, 21000.0, 0.7363, 3317.715, 1293.72, 2460.74 + 0.2, 21000.0, 0.8032, 5785.787, 1909.66, 2684.44 + 0.2, 21000.0, 0.8702, 8897.441, 3056.74, 2908.15 + 0.2, 21000.0, 0.9371, 11155.84, 4062.54, 3131.85 + 0.2, 24000.0, 0.0, 270.2649, 270.265, 0.0 + 0.2, 24000.0, 0.392, -3086.634, -1467.26, 1309.94 + 0.2, 24000.0, 0.4573, -1835.977, -904.948, 1528.26 + 0.2, 24000.0, 0.5226, -585.3079, -342.635, 1746.58 + 0.2, 24000.0, 0.5879, 665.3423, 219.677, 1964.91 + 0.2, 24000.0, 0.6533, 2335.008, 844.975, 2183.23 + 0.2, 24000.0, 0.7186, 4330.394, 1474.08, 2401.55 + 0.2, 24000.0, 0.7839, 5792.046, 1909.76, 2619.87 + 0.2, 24000.0, 0.8493, 7905.603, 2352.51, 2838.2 + 0.2, 24000.0, 0.9146, 9028.809, 3009.18, 3056.52 + 0.2, 24000.0, 0.9799, 11165.56, 4091.14, 3274.84 + 0.2, 27000.0, 0.0, 240.0294, 240.029, 0.0 + 0.2, 27000.0, 0.3823, 5851.268, 3574.69, 1277.67 + 0.2, 27000.0, 0.446, 4417.294, 2799.7, 1490.61 + 0.2, 27000.0, 0.5097, 2983.288, 2024.69, 1703.55 + 0.2, 27000.0, 0.5735, 1549.289, 1249.67, 1916.5 + 0.2, 27000.0, 0.6372, 207.162, 425.319, 2129.44 + 0.2, 27000.0, 0.7009, 2949.642, 790.221, 2342.39 + 0.2, 27000.0, 0.7646, 3967.373, 1148.04, 2555.33 + 0.2, 27000.0, 0.8283, 4283.771, 2084.62, 2768.28 + 0.2, 27000.0, 0.892, 8825.652, 2731.88, 2981.22 + 0.2, 27000.0, 0.9558, 6503.51, 3450.01, 3194.16 + 0.2, 30000.0, 0.0, 212.5388, 212.539, 0.0 + 0.2, 30000.0, 0.3727, -1299.124, 256.114, 1245.4 + 0.2, 30000.0, 0.4348, -116.08, 404.181, 1452.97 + 0.2, 30000.0, 0.4969, 1066.745, 552.316, 1660.53 + 0.2, 30000.0, 0.559, 2249.681, 700.411, 1868.1 + 0.2, 30000.0, 0.6211, 2481.531, 467.407, 2075.67 + 0.2, 30000.0, 0.6832, 978.6678, 646.392, 2283.23 + 0.2, 30000.0, 0.7453, 2672.655, 663.988, 2490.8 + 0.2, 30000.0, 0.8074, 4300.753, 575.433, 2698.37 + 0.2, 30000.0, 0.8695, 8847.359, 3656.91, 2905.93 + 0.2, 30000.0, 0.9316, 15157.13, 3717.34, 3113.5 + 0.2, 30000.0, 0.9937, 26100.61, 7008.76, 3321.07 + 0.2, 33000.0, 0.0, 187.6029, 187.603, 0.0 + 0.2, 33000.0, 0.363, 23055.02, 2408.87, 1213.15 + 0.2, 33000.0, 0.4235, 18179.43, 1907.7, 1415.34 + 0.2, 33000.0, 0.484, 13303.81, 1406.52, 1617.53 + 0.2, 33000.0, 0.5445, 8428.168, 905.38, 1819.72 + 0.2, 33000.0, 0.605, 3552.505, 404.167, 2021.91 + 0.2, 33000.0, 0.6655, 312.6091, 290.78, 2224.1 + 0.2, 33000.0, 0.726, 5726.573, 2192.92, 2426.29 + 0.2, 33000.0, 0.7865, 6102.495, 2156.79, 2628.48 + 0.2, 33000.0, 0.847, 2044.14, 59.3157, 2830.68 + 0.2, 33000.0, 0.9075, 4972.293, 1903.22, 3032.87 + 0.2, 33000.0, 0.968, -15369.77, -11175.2, 3235.06 + 0.2, 36000.0, 0.0, 165.0433, 165.043, 0.0 + 0.2, 36000.0, 0.3534, 21355.84, 1673.06, 1180.9 + 0.2, 36000.0, 0.4122, 17053.52, 1443.19, 1377.71 + 0.2, 36000.0, 0.4711, 12751.07, 1213.31, 1574.53 + 0.2, 36000.0, 0.53, 8448.72, 983.441, 1771.35 + 0.2, 36000.0, 0.5889, 4146.326, 753.523, 1968.16 + 0.2, 36000.0, 0.6478, 1281.712, 503.394, 2164.98 + 0.2, 36000.0, 0.7067, 1554.098, 516.242, 2361.8 + 0.2, 36000.0, 0.7656, -5548.755, -310.545, 2558.61 + 0.2, 36000.0, 0.8245, 18994.09, 4628.81, 2755.43 + 0.2, 36000.0, 0.8834, 9293.207, 3422.01, 2952.25 + 0.2, 36000.0, 0.9423, -5216.611, -6751.36, 3149.06 + 0.2, 39000.0, 0.0, 143.0546, 143.055, 0.0 + 0.2, 39000.0, 0.3529, -369.1119, -191.736, 1179.27 + 0.2, 39000.0, 0.4117, -423.5128, -135.85, 1375.81 + 0.2, 39000.0, 0.4705, -478.008, -79.9599, 1572.36 + 0.2, 39000.0, 0.5293, -532.4351, -24.0419, 1768.9 + 0.2, 39000.0, 0.5881, -586.9227, 31.8606, 1965.45 + 0.2, 39000.0, 0.6469, -962.282, -11.2916, 2161.99 + 0.2, 39000.0, 0.7057, 919.3272, 385.331, 2358.54 + 0.2, 39000.0, 0.7645, -128.4183, -70.9444, 2555.08 + 0.2, 39000.0, 0.8233, 4724.47, -694.009, 2751.63 + 0.2, 39000.0, 0.8822, 6948.55, 2589.48, 2948.17 + 0.2, 39000.0, 0.941, 43362.67, 24330.3, 3144.72 + 0.2, 42000.0, 0.0, 123.9148, 123.915, 0.0 + 0.2, 42000.0, 0.3529, -191029.9, -73367.2, 1179.27 + 0.2, 42000.0, 0.4117, -149857.6, -57423.6, 1375.81 + 0.2, 42000.0, 0.4705, -108685.3, -41479.9, 1572.36 + 0.2, 42000.0, 0.5293, -67513.03, -25536.1, 1768.9 + 0.2, 42000.0, 0.5881, -26340.74, -9592.5, 1965.45 + 0.2, 42000.0, 0.6469, -6468.489, -2115.2, 2161.99 + 0.2, 42000.0, 0.7057, 4304.068, 711.844, 2358.54 + 0.2, 42000.0, 0.7645, -3325.895, 345.954, 2555.08 + 0.2, 42000.0, 0.8233, 11367.89, 6011.92, 2751.63 + 0.2, 42000.0, 0.8822, -1836.935, -861.512, 2948.17 + 0.2, 42000.0, 0.941, 11769.37, 7794.41, 3144.72 + 0.25, 0.0, 0.0, 645.0697, 645.07, 0.0 + 0.25, 0.0, 0.4714, -1742.039, -58.8918, 1575.46 + 0.25, 0.0, 0.55, 445.6624, 611.552, 1838.04 + 0.25, 0.0, 0.6285, 2633.364, 1282.0, 2100.61 + 0.25, 0.0, 0.7071, 5070.966, 2010.4, 2363.19 + 0.25, 0.0, 0.7857, 8055.823, 3018.43, 2625.77 + 0.25, 0.0, 0.8643, 12000.67, 4407.95, 2888.34 + 0.25, 0.0, 0.9428, 17434.64, 6346.67, 3150.92 + 0.25, 3000.0, 0.0, 584.2039, 584.204, 0.0 + 0.25, 3000.0, 0.4617, -1964.95, -139.765, 1542.97 + 0.25, 3000.0, 0.5386, 108.1192, 476.86, 1800.13 + 0.25, 3000.0, 0.6156, 2181.188, 1093.48, 2057.29 + 0.25, 3000.0, 0.6925, 4326.535, 1741.6, 2314.45 + 0.25, 3000.0, 0.7695, 6980.938, 2613.34, 2571.62 + 0.25, 3000.0, 0.8464, 10488.83, 3818.9, 2828.78 + 0.25, 3000.0, 0.9234, 15330.19, 5492.86, 3085.94 + 0.25, 6000.0, 0.0, 527.9816, 527.982, 0.0 + 0.25, 6000.0, 0.452, -2162.852, -217.173, 1510.49 + 0.25, 6000.0, 0.5273, -225.7294, 351.157, 1762.23 + 0.25, 6000.0, 0.6026, 1711.393, 919.487, 2013.98 + 0.25, 6000.0, 0.678, 3662.199, 1495.2, 2265.73 + 0.25, 6000.0, 0.7533, 6012.335, 2253.91, 2517.48 + 0.25, 6000.0, 0.8286, 9041.071, 3293.78, 2769.22 + 0.25, 6000.0, 0.9039, 13317.45, 4744.83, 3020.97 + 0.25, 6000.0, 0.9793, 18435.92, 6573.85, 3272.72 + 0.25, 9000.0, 0.0, 476.1368, 476.137, 0.0 + 0.25, 9000.0, 0.4423, -2278.72, -298.748, 1478.01 + 0.25, 9000.0, 0.516, -489.7066, 227.393, 1724.35 + 0.25, 9000.0, 0.5897, 1299.307, 753.533, 1970.68 + 0.25, 9000.0, 0.6634, 3088.32, 1279.67, 2217.02 + 0.25, 9000.0, 0.7371, 5151.956, 1933.79, 2463.36 + 0.25, 9000.0, 0.8108, 7776.433, 2825.98, 2709.69 + 0.25, 9000.0, 0.8845, 11451.42, 4068.23, 2956.03 + 0.25, 9000.0, 0.9582, 15926.96, 5648.19, 3202.36 + 0.25, 12000.0, 0.0, 428.4088, 428.409, 0.0 + 0.25, 12000.0, 0.4325, -2003.622, -285.629, 1445.55 + 0.25, 12000.0, 0.5046, -463.2166, 174.166, 1686.47 + 0.25, 12000.0, 0.5767, 1077.189, 633.96, 1927.4 + 0.25, 12000.0, 0.6488, 2617.594, 1093.75, 2168.32 + 0.25, 12000.0, 0.7209, 4380.616, 1641.56, 2409.25 + 0.25, 12000.0, 0.793, 6725.131, 2413.67, 2650.17 + 0.25, 12000.0, 0.8651, 9842.337, 3458.44, 2891.1 + 0.25, 12000.0, 0.9372, 13708.57, 4810.02, 3132.02 + 0.25, 15000.0, 0.0, 384.5537, 384.554, 0.0 + 0.25, 15000.0, 0.4228, -2123.832, -322.312, 1413.09 + 0.25, 15000.0, 0.4933, -692.9334, 93.8514, 1648.61 + 0.25, 15000.0, 0.5638, 737.9665, 510.015, 1884.13 + 0.25, 15000.0, 0.6342, 2168.866, 926.178, 2119.64 + 0.25, 15000.0, 0.7047, 3727.23, 1389.9, 2355.16 + 0.25, 15000.0, 0.7752, 5788.952, 2045.87, 2590.67 + 0.25, 15000.0, 0.8457, 8300.066, 2924.99, 2826.19 + 0.25, 15000.0, 0.9161, 11956.34, 4122.89, 3061.71 + 0.25, 15000.0, 0.9866, 15138.8, 5445.6, 3297.22 + 0.25, 18000.0, 0.0, 344.3348, 344.335, 0.0 + 0.25, 18000.0, 0.4131, -3373.668, -583.207, 1380.65 + 0.25, 18000.0, 0.482, -1714.353, -141.567, 1610.76 + 0.25, 18000.0, 0.5508, -55.0337, 300.068, 1840.86 + 0.25, 18000.0, 0.6197, 1604.285, 741.705, 2070.97 + 0.25, 18000.0, 0.6885, 3016.9, 1167.13, 2301.08 + 0.25, 18000.0, 0.7574, 4712.998, 1701.36, 2531.19 + 0.25, 18000.0, 0.8262, 7055.389, 2422.81, 2761.3 + 0.25, 18000.0, 0.8951, 9375.74, 3329.35, 2991.4 + 0.25, 18000.0, 0.9639, 14232.8, 4755.72, 3221.51 + 0.25, 21000.0, 0.0, 307.5228, 307.523, 0.0 + 0.25, 21000.0, 0.4034, -1822.321, -68.3616, 1348.21 + 0.25, 21000.0, 0.4707, -689.5713, 188.355, 1572.92 + 0.25, 21000.0, 0.5379, 443.1847, 445.072, 1797.62 + 0.25, 21000.0, 0.6051, 1575.938, 701.785, 2022.32 + 0.25, 21000.0, 0.6724, 2692.254, 988.647, 2247.02 + 0.25, 21000.0, 0.7396, 3652.677, 1396.45, 2471.72 + 0.25, 21000.0, 0.8068, 5831.83, 2025.9, 2696.43 + 0.25, 21000.0, 0.8741, 8640.356, 3037.35, 2921.13 + 0.25, 21000.0, 0.9413, 10913.27, 4021.12, 3145.83 + 0.25, 24000.0, 0.0, 273.9007, 273.901, 0.0 + 0.25, 24000.0, 0.3937, -2952.86, -1086.88, 1315.79 + 0.25, 24000.0, 0.4593, -1723.222, -611.031, 1535.08 + 0.25, 24000.0, 0.5249, -493.5767, -135.186, 1754.38 + 0.25, 24000.0, 0.5906, 736.0577, 340.658, 1973.68 + 0.25, 24000.0, 0.6562, 2177.826, 842.966, 2192.98 + 0.25, 24000.0, 0.7218, 3940.251, 1396.32, 2412.27 + 0.25, 24000.0, 0.7874, 5493.754, 1884.35, 2631.57 + 0.25, 24000.0, 0.853, 7527.95, 2429.73, 2850.87 + 0.25, 24000.0, 0.9187, 9093.744, 3174.12, 3070.17 + 0.25, 24000.0, 0.9843, 11241.58, 4223.0, 3289.46 + 0.25, 27000.0, 0.0, 243.2585, 243.258, 0.0 + 0.25, 27000.0, 0.384, 2648.045, 2042.58, 1283.37 + 0.25, 27000.0, 0.448, 2150.753, 1673.07, 1497.26 + 0.25, 27000.0, 0.512, 1653.44, 1303.54, 1711.16 + 0.25, 27000.0, 0.576, 1156.132, 934.01, 1925.05 + 0.25, 27000.0, 0.64, 736.4785, 541.892, 2138.95 + 0.25, 27000.0, 0.704, 2861.175, 892.964, 2352.84 + 0.25, 27000.0, 0.768, 4078.6, 1309.17, 2566.74 + 0.25, 27000.0, 0.832, 4904.717, 2123.07, 2780.63 + 0.25, 27000.0, 0.896, 8505.262, 2802.81, 2994.53 + 0.25, 27000.0, 0.96, 7543.394, 3525.01, 3208.42 + 0.25, 30000.0, 0.0, 215.398, 215.398, 0.0 + 0.25, 30000.0, 0.3743, -1570.517, 0.6667, 1250.96 + 0.25, 30000.0, 0.4367, -490.5171, 192.97, 1459.45 + 0.25, 30000.0, 0.4991, 589.3328, 385.32, 1667.95 + 0.25, 30000.0, 0.5615, 1669.259, 577.643, 1876.44 + 0.25, 30000.0, 0.6239, 2115.128, 515.901, 2084.93 + 0.25, 30000.0, 0.6862, 1327.426, 715.555, 2293.43 + 0.25, 30000.0, 0.7486, 2918.628, 868.597, 2501.92 + 0.25, 30000.0, 0.811, 4513.853, 983.733, 2710.41 + 0.25, 30000.0, 0.8734, 8104.491, 3277.96, 2918.91 + 0.25, 30000.0, 0.9358, 13003.69, 3622.43, 3127.4 + 0.25, 30000.0, 0.9982, 21020.04, 6201.66, 3335.89 + 0.25, 33000.0, 0.0, 190.1266, 190.127, 0.0 + 0.25, 33000.0, 0.3646, 15564.81, 1521.98, 1218.56 + 0.25, 33000.0, 0.4254, 12361.8, 1246.27, 1421.66 + 0.25, 33000.0, 0.4862, 9158.757, 970.551, 1624.75 + 0.25, 33000.0, 0.5469, 5955.706, 694.86, 1827.84 + 0.25, 33000.0, 0.6077, 2752.637, 419.118, 2030.94 + 0.25, 33000.0, 0.6685, 745.7705, 430.668, 2234.03 + 0.25, 33000.0, 0.7292, 4855.081, 1863.85, 2437.13 + 0.25, 33000.0, 0.79, 5511.795, 1967.65, 2640.22 + 0.25, 33000.0, 0.8508, 3148.746, 689.546, 2843.31 + 0.25, 33000.0, 0.9116, 5335.203, 2024.79, 3046.41 + 0.25, 33000.0, 0.9723, -9227.631, -7345.75, 3249.5 + 0.25, 36000.0, 0.0, 167.2636, 167.264, 0.0 + 0.25, 36000.0, 0.3549, 14231.17, 991.107, 1186.17 + 0.25, 36000.0, 0.4141, 11432.87, 899.222, 1383.87 + 0.25, 36000.0, 0.4732, 8634.491, 807.336, 1581.56 + 0.25, 36000.0, 0.5324, 5836.179, 715.46, 1779.26 + 0.25, 36000.0, 0.5915, 3037.836, 623.546, 1976.95 + 0.25, 36000.0, 0.6507, 1255.524, 516.293, 2174.65 + 0.25, 36000.0, 0.7099, 1674.211, 601.287, 2372.34 + 0.25, 36000.0, 0.769, -3033.529, 129.301, 2570.04 + 0.25, 36000.0, 0.8282, 14759.71, 3746.9, 2767.73 + 0.25, 36000.0, 0.8873, 8234.66, 3108.42, 2965.43 + 0.25, 36000.0, 0.9465, -2234.661, -4165.66, 3163.12 + 0.25, 39000.0, 0.0, 144.9791, 144.979, 0.0 + 0.25, 39000.0, 0.3544, -613.9023, -250.394, 1184.53 + 0.25, 39000.0, 0.4135, -538.8967, -162.851, 1381.96 + 0.25, 39000.0, 0.4726, -463.9568, -75.3043, 1579.38 + 0.25, 39000.0, 0.5317, -388.9685, 12.2619, 1776.8 + 0.25, 39000.0, 0.5907, -314.0237, 99.817, 1974.22 + 0.25, 39000.0, 0.6498, -462.3192, 109.299, 2171.65 + 0.25, 39000.0, 0.7089, 1101.604, 462.751, 2369.07 + 0.25, 39000.0, 0.768, 621.6528, 240.091, 2566.49 + 0.25, 39000.0, 0.827, 4402.226, -109.979, 2763.91 + 0.25, 39000.0, 0.8861, 6220.224, 2357.82, 2961.33 + 0.25, 39000.0, 0.9452, 31915.86, 17743.9, 3158.76 + 0.25, 42000.0, 0.0, 125.5818, 125.582, 0.0 + 0.25, 42000.0, 0.3544, -146187.7, -56088.6, 1184.53 + 0.25, 42000.0, 0.4135, -114664.9, -43890.2, 1381.96 + 0.25, 42000.0, 0.4726, -83142.16, -31691.7, 1579.38 + 0.25, 42000.0, 0.5317, -51619.43, -19493.2, 1776.8 + 0.25, 42000.0, 0.5907, -20096.65, -7294.8, 1974.22 + 0.25, 42000.0, 0.6498, -4695.919, -1496.5, 2171.65 + 0.25, 42000.0, 0.7089, 3503.832, 679.622, 2369.07 + 0.25, 42000.0, 0.768, -1973.982, 456.593, 2566.49 + 0.25, 42000.0, 0.827, 9186.537, 4769.56, 2763.91 + 0.25, 42000.0, 0.8861, -312.3219, -191.212, 2961.33 + 0.25, 42000.0, 0.9452, 10432.99, 6610.23, 3158.76 + 0.3, 0.0, 0.0, 655.6391, 655.639, 0.0 + 0.3, 0.0, 0.474, -1722.055, -36.4513, 1584.02 + 0.3, 0.0, 0.553, 377.0143, 641.955, 1848.02 + 0.3, 0.0, 0.632, 2476.083, 1320.36, 2112.02 + 0.3, 0.0, 0.711, 4891.319, 2070.04, 2376.03 + 0.3, 0.0, 0.79, 7905.778, 3118.11, 2640.03 + 0.3, 0.0, 0.869, 11771.34, 4553.49, 2904.03 + 0.3, 0.0, 0.9479, 17009.04, 6539.68, 3168.04 + 0.3, 3000.0, 0.0, 593.776, 593.776, 0.0 + 0.3, 3000.0, 0.4642, -1974.313, -123.055, 1551.35 + 0.3, 3000.0, 0.5416, 44.41066, 503.503, 1809.91 + 0.3, 3000.0, 0.6189, 2063.134, 1130.06, 2068.47 + 0.3, 3000.0, 0.6963, 4178.625, 1795.73, 2327.03 + 0.3, 3000.0, 0.7737, 6845.891, 2698.66, 2585.59 + 0.3, 3000.0, 0.851, 10288.91, 3946.67, 2844.14 + 0.3, 3000.0, 0.9284, 14955.42, 5662.28, 3102.7 + 0.3, 6000.0, 0.0, 536.6326, 536.633, 0.0 + 0.3, 6000.0, 0.4544, -2198.439, -203.615, 1518.69 + 0.3, 6000.0, 0.5302, -298.3211, 374.192, 1771.81 + 0.3, 6000.0, 0.6059, 1601.797, 951.999, 2024.92 + 0.3, 6000.0, 0.6816, 3532.944, 1543.83, 2278.04 + 0.3, 6000.0, 0.7574, 5889.292, 2330.75, 2531.15 + 0.3, 6000.0, 0.8331, 8909.537, 3405.5, 2784.27 + 0.3, 6000.0, 0.9089, 13001.74, 4896.62, 3037.38 + 0.3, 6000.0, 0.9846, 18010.13, 6764.83, 3290.5 + 0.3, 9000.0, 0.0, 483.9383, 483.938, 0.0 + 0.3, 9000.0, 0.4447, -2330.148, -290.164, 1486.04 + 0.3, 9000.0, 0.5188, -563.7825, 245.972, 1733.72 + 0.3, 9000.0, 0.5929, 1202.583, 782.109, 1981.39 + 0.3, 9000.0, 0.667, 2968.949, 1318.25, 2229.06 + 0.3, 9000.0, 0.7411, 5040.57, 1997.88, 2476.74 + 0.3, 9000.0, 0.8152, 7692.805, 2929.59, 2724.41 + 0.3, 9000.0, 0.8893, 11181.07, 4198.12, 2972.08 + 0.3, 9000.0, 0.9634, 15576.66, 5822.22, 3219.76 + 0.3, 12000.0, 0.0, 435.4283, 435.428, 0.0 + 0.3, 12000.0, 0.4349, -2163.182, -299.033, 1453.4 + 0.3, 12000.0, 0.5074, -609.0476, 175.744, 1695.63 + 0.3, 12000.0, 0.5799, 945.0865, 650.521, 1937.87 + 0.3, 12000.0, 0.6523, 2499.22, 1125.3, 2180.1 + 0.3, 12000.0, 0.7248, 4287.447, 1698.78, 2422.33 + 0.3, 12000.0, 0.7973, 6603.436, 2496.39, 2664.57 + 0.3, 12000.0, 0.8698, 9629.066, 3574.47, 2906.8 + 0.3, 12000.0, 0.9423, 13412.54, 4963.87, 3149.03 + 0.3, 15000.0, 0.0, 390.8546, 390.855, 0.0 + 0.3, 15000.0, 0.4251, -2067.99, -301.019, 1420.77 + 0.3, 15000.0, 0.496, -682.3344, 118.718, 1657.57 + 0.3, 15000.0, 0.5668, 703.3211, 538.454, 1894.36 + 0.3, 15000.0, 0.6377, 2088.977, 958.191, 2131.16 + 0.3, 15000.0, 0.7085, 3634.719, 1442.65, 2367.95 + 0.3, 15000.0, 0.7794, 5630.086, 2114.03, 2604.75 + 0.3, 15000.0, 0.8503, 8242.303, 3037.59, 2841.54 + 0.3, 15000.0, 0.9211, 11505.21, 4210.63, 3078.34 + 0.3, 15000.0, 0.992, 15085.61, 5615.94, 3315.13 + 0.3, 18000.0, 0.0, 349.9767, 349.977, 0.0 + 0.3, 18000.0, 0.4154, -2535.845, -421.657, 1388.15 + 0.3, 18000.0, 0.4846, -1142.686, -16.51, 1619.51 + 0.3, 18000.0, 0.5538, 250.4748, 388.636, 1850.86 + 0.3, 18000.0, 0.623, 1643.635, 793.782, 2082.22 + 0.3, 18000.0, 0.6923, 3020.543, 1218.58, 2313.58 + 0.3, 18000.0, 0.7615, 4740.697, 1785.45, 2544.94 + 0.3, 18000.0, 0.8307, 7007.722, 2550.76, 2776.3 + 0.3, 18000.0, 0.9, 9594.321, 3522.12, 3007.65 + 0.3, 18000.0, 0.9692, 13289.14, 4845.93, 3239.01 + 0.3, 21000.0, 0.0, 312.5616, 312.562, 0.0 + 0.3, 21000.0, 0.4056, -2082.716, -255.111, 1355.54 + 0.3, 21000.0, 0.4732, -920.1373, 60.1689, 1581.46 + 0.3, 21000.0, 0.5408, 242.4438, 375.449, 1807.38 + 0.3, 21000.0, 0.6084, 1405.024, 690.727, 2033.31 + 0.3, 21000.0, 0.676, 2570.143, 1023.04, 2259.23 + 0.3, 21000.0, 0.7436, 3853.675, 1485.79, 2485.15 + 0.3, 21000.0, 0.8112, 5876.036, 2138.68, 2711.07 + 0.3, 21000.0, 0.8788, 8462.327, 3072.25, 2937.0 + 0.3, 21000.0, 0.9464, 10776.65, 4069.06, 3162.92 + 0.3, 24000.0, 0.0, 278.3885, 278.389, 0.0 + 0.3, 24000.0, 0.3959, -2751.816, -804.087, 1322.93 + 0.3, 24000.0, 0.4618, -1568.087, -390.469, 1543.42 + 0.3, 24000.0, 0.5278, -384.3544, 23.1485, 1763.91 + 0.3, 24000.0, 0.5938, 799.3725, 436.765, 1984.4 + 0.3, 24000.0, 0.6598, 2065.186, 855.214, 2204.89 + 0.3, 24000.0, 0.7257, 3656.179, 1359.25, 2425.38 + 0.3, 24000.0, 0.7917, 5282.565, 1892.89, 2645.87 + 0.3, 24000.0, 0.8577, 7268.699, 2520.29, 2866.35 + 0.3, 24000.0, 0.9237, 9125.918, 3334.85, 3086.84 + 0.3, 24000.0, 0.9896, 11237.84, 4353.94, 3307.33 + 0.3, 27000.0, 0.0, 247.2443, 247.244, 0.0 + 0.3, 27000.0, 0.3861, 414.1758, 950.876, 1290.34 + 0.3, 27000.0, 0.4504, 572.1775, 872.847, 1505.4 + 0.3, 27000.0, 0.5148, 730.1668, 794.809, 1720.45 + 0.3, 27000.0, 0.5791, 888.1592, 716.771, 1935.51 + 0.3, 27000.0, 0.6435, 1105.418, 631.949, 2150.57 + 0.3, 27000.0, 0.7078, 2793.543, 981.018, 2365.63 + 0.3, 27000.0, 0.7722, 4150.089, 1442.59, 2580.68 + 0.3, 27000.0, 0.8365, 5349.265, 2176.12, 2795.74 + 0.3, 27000.0, 0.9009, 8251.826, 2887.4, 3010.8 + 0.3, 27000.0, 0.9652, 8297.254, 3630.42, 3225.85 + 0.3, 30000.0, 0.0, 218.9273, 218.927, 0.0 + 0.3, 30000.0, 0.3763, -1784.884, -191.766, 1257.76 + 0.3, 30000.0, 0.4391, -783.396, 35.3847, 1467.38 + 0.3, 30000.0, 0.5018, 217.9944, 262.564, 1677.01 + 0.3, 30000.0, 0.5645, 1219.434, 489.727, 1886.63 + 0.3, 30000.0, 0.6272, 1824.588, 558.099, 2096.26 + 0.3, 30000.0, 0.69, 1602.285, 781.407, 2305.88 + 0.3, 30000.0, 0.7527, 3107.913, 1040.48, 2515.51 + 0.3, 30000.0, 0.8154, 4681.304, 1315.86, 2725.14 + 0.3, 30000.0, 0.8781, 7543.26, 3015.25, 2934.76 + 0.3, 30000.0, 0.9409, 11314.85, 3560.03, 3144.39 + 0.3, 33000.0, 0.0, 193.2419, 193.242, 0.0 + 0.3, 33000.0, 0.3666, 9700.131, 829.183, 1225.18 + 0.3, 33000.0, 0.4277, 7807.481, 731.377, 1429.38 + 0.3, 33000.0, 0.4888, 5914.808, 633.569, 1633.58 + 0.3, 33000.0, 0.5499, 4022.131, 535.78, 1837.77 + 0.3, 33000.0, 0.611, 2129.441, 437.956, 2041.97 + 0.3, 33000.0, 0.6721, 1080.772, 546.037, 2246.17 + 0.3, 33000.0, 0.7332, 4174.89, 1618.03, 2450.36 + 0.3, 33000.0, 0.7943, 5053.575, 1837.79, 2654.56 + 0.3, 33000.0, 0.8554, 4000.585, 1196.68, 2858.76 + 0.3, 33000.0, 0.9165, 5662.175, 2173.83, 3062.96 + 0.3, 33000.0, 0.9776, -4247.116, -4209.72, 3267.15 + 0.3, 36000.0, 0.0, 170.0042, 170.004, 0.0 + 0.3, 36000.0, 0.3569, 8679.758, 458.838, 1192.61 + 0.3, 36000.0, 0.4163, 7054.406, 476.263, 1391.38 + 0.3, 36000.0, 0.4758, 5428.997, 493.689, 1590.15 + 0.3, 36000.0, 0.5353, 3803.635, 511.12, 1788.92 + 0.3, 36000.0, 0.5948, 2178.251, 528.527, 1987.69 + 0.3, 36000.0, 0.6542, 1238.908, 534.762, 2186.46 + 0.3, 36000.0, 0.7137, 1781.801, 680.925, 2385.23 + 0.3, 36000.0, 0.7732, -1039.85, 491.14, 2584.0 + 0.3, 36000.0, 0.8327, 11436.2, 3077.45, 2782.76 + 0.3, 36000.0, 0.8921, 7389.053, 2869.9, 2981.53 + 0.3, 36000.0, 0.9516, 140.793, -2105.59, 3180.3 + 0.3, 39000.0, 0.0, 147.3545, 147.355, 0.0 + 0.3, 39000.0, 0.3564, -859.5542, -303.665, 1190.97 + 0.3, 39000.0, 0.4158, -670.8478, -188.689, 1389.46 + 0.3, 39000.0, 0.4752, -482.1849, -73.7106, 1587.96 + 0.3, 39000.0, 0.5345, -293.4891, 41.281, 1786.45 + 0.3, 39000.0, 0.5939, -104.8233, 156.265, 1984.95 + 0.3, 39000.0, 0.6533, -61.3595, 212.364, 2183.44 + 0.3, 39000.0, 0.7127, 1253.614, 534.32, 2381.94 + 0.3, 39000.0, 0.7721, 1227.694, 497.382, 2580.43 + 0.3, 39000.0, 0.8315, 4155.631, 370.388, 2778.93 + 0.3, 39000.0, 0.8909, 5658.4, 2196.35, 2977.42 + 0.3, 39000.0, 0.9503, 22985.38, 12612.7, 3175.92 + 0.3, 42000.0, 0.0, 127.6395, 127.639, 0.0 + 0.3, 42000.0, 0.3564, -109083.1, -41796.9, 1190.97 + 0.3, 42000.0, 0.4158, -85544.63, -32694.8, 1389.46 + 0.3, 42000.0, 0.4752, -62006.2, -23592.6, 1587.96 + 0.3, 42000.0, 0.5345, -38467.81, -14490.5, 1786.45 + 0.3, 42000.0, 0.5939, -14929.38, -5388.43, 1984.95 + 0.3, 42000.0, 0.6533, -3248.578, -987.126, 2183.44 + 0.3, 42000.0, 0.7127, 2856.082, 657.639, 2381.94 + 0.3, 42000.0, 0.7721, -864.5085, 558.453, 2580.43 + 0.3, 42000.0, 0.8315, 7418.438, 3770.11, 2778.93 + 0.3, 42000.0, 0.8909, 916.1667, 359.606, 2977.42 + 0.3, 42000.0, 0.9503, 9249.859, 5605.79, 3175.92 + 0.35, 0.0, 0.0, 668.2784, 668.278, 0.0 + 0.35, 0.0, 0.477, -1643.587, -6.4903, 1594.13 + 0.35, 0.0, 0.5565, 344.1157, 679.138, 1859.82 + 0.35, 0.0, 0.636, 2331.818, 1364.77, 2125.51 + 0.35, 0.0, 0.7155, 4733.674, 2140.12, 2391.2 + 0.35, 0.0, 0.795, 7815.085, 3234.26, 2656.89 + 0.35, 0.0, 0.8745, 11600.21, 4726.71, 2922.58 + 0.35, 0.0, 0.954, 16641.54, 6761.73, 3188.26 + 0.35, 3000.0, 0.0, 605.2227, 605.223, 0.0 + 0.35, 3000.0, 0.4672, -1893.548, -96.6837, 1561.26 + 0.35, 3000.0, 0.545, 35.55024, 538.044, 1821.47 + 0.35, 3000.0, 0.6229, 1964.649, 1172.77, 2081.68 + 0.35, 3000.0, 0.7007, 4025.643, 1856.29, 2341.89 + 0.35, 3000.0, 0.7786, 6721.039, 2796.18, 2602.09 + 0.35, 3000.0, 0.8565, 10200.37, 4099.96, 2862.3 + 0.35, 3000.0, 0.9343, 14801.46, 5884.0, 3122.51 + 0.35, 6000.0, 0.0, 546.9777, 546.978, 0.0 + 0.35, 6000.0, 0.4573, -2126.172, -180.36, 1528.39 + 0.35, 6000.0, 0.5335, -299.722, 405.414, 1783.12 + 0.35, 6000.0, 0.6098, 1526.728, 991.188, 2037.85 + 0.35, 6000.0, 0.686, 3404.545, 1598.95, 2292.58 + 0.35, 6000.0, 0.7622, 5790.661, 2418.86, 2547.31 + 0.35, 6000.0, 0.8384, 8793.25, 3531.68, 2802.04 + 0.35, 6000.0, 0.9147, 12872.85, 5085.37, 3056.77 + 0.35, 6000.0, 0.9909, 17629.5, 6974.84, 3311.51 + 0.35, 9000.0, 0.0, 493.2676, 493.268, 0.0 + 0.35, 9000.0, 0.4475, -2261.055, -272.222, 1495.53 + 0.35, 9000.0, 0.5221, -556.4717, 272.546, 1744.79 + 0.35, 9000.0, 0.5967, 1148.112, 817.314, 1994.04 + 0.35, 9000.0, 0.6712, 2852.695, 1362.08, 2243.3 + 0.35, 9000.0, 0.7458, 4941.803, 2070.98, 2492.55 + 0.35, 9000.0, 0.8204, 7597.169, 3042.7, 2741.81 + 0.35, 9000.0, 0.895, 11125.04, 4371.11, 2991.06 + 0.35, 9000.0, 0.9696, 15347.56, 6032.98, 3240.32 + 0.35, 12000.0, 0.0, 443.8224, 443.822, 0.0 + 0.35, 12000.0, 0.4377, -2276.281, -315.698, 1462.68 + 0.35, 12000.0, 0.5106, -720.8463, 176.735, 1706.46 + 0.35, 12000.0, 0.5836, 834.5879, 669.168, 1950.24 + 0.35, 12000.0, 0.6565, 2390.022, 1161.6, 2194.02 + 0.35, 12000.0, 0.7294, 4204.665, 1764.09, 2437.8 + 0.35, 12000.0, 0.8024, 6529.956, 2593.21, 2681.58 + 0.35, 12000.0, 0.8753, 9575.901, 3725.99, 2925.36 + 0.35, 12000.0, 0.9483, 13217.24, 5147.08, 3169.14 + 0.35, 15000.0, 0.0, 398.3894, 398.389, 0.0 + 0.35, 15000.0, 0.4278, -2082.485, -300.061, 1429.84 + 0.35, 15000.0, 0.4991, -721.9742, 129.895, 1668.15 + 0.35, 15000.0, 0.5705, 638.5369, 559.85, 1906.46 + 0.35, 15000.0, 0.6418, 1999.048, 989.806, 2144.76 + 0.35, 15000.0, 0.7131, 3546.408, 1493.79, 2383.07 + 0.35, 15000.0, 0.7844, 5564.218, 2199.72, 2621.38 + 0.35, 15000.0, 0.8557, 8208.329, 3164.01, 2859.69 + 0.35, 15000.0, 0.927, 11334.86, 4364.24, 3097.99 + 0.35, 15000.0, 0.9983, 14750.12, 5770.6, 3336.3 + 0.35, 18000.0, 0.0, 356.7235, 356.724, 0.0 + 0.35, 18000.0, 0.418, -2124.355, -339.217, 1397.01 + 0.35, 18000.0, 0.4877, -872.7657, 52.3753, 1629.85 + 0.35, 18000.0, 0.5574, 378.8241, 443.967, 1862.68 + 0.35, 18000.0, 0.627, 1630.414, 835.559, 2095.52 + 0.35, 18000.0, 0.6967, 2987.256, 1269.0, 2328.35 + 0.35, 18000.0, 0.7664, 4735.314, 1864.64, 2561.19 + 0.35, 18000.0, 0.836, 7006.298, 2678.58, 2794.02 + 0.35, 18000.0, 0.9057, 9695.005, 3700.67, 3026.86 + 0.35, 18000.0, 0.9754, 12807.59, 4997.19, 3259.69 + 0.35, 21000.0, 0.0, 318.587, 318.587, 0.0 + 0.35, 21000.0, 0.4082, -2145.934, -342.488, 1364.19 + 0.35, 21000.0, 0.4762, -995.571, 5.21663, 1591.56 + 0.35, 21000.0, 0.5443, 154.7926, 352.921, 1818.92 + 0.35, 21000.0, 0.6123, 1305.156, 700.625, 2046.29 + 0.35, 21000.0, 0.6803, 2483.338, 1063.5, 2273.65 + 0.35, 21000.0, 0.7484, 3952.541, 1566.69, 2501.02 + 0.35, 21000.0, 0.8164, 5919.787, 2251.62, 2728.38 + 0.35, 21000.0, 0.8844, 8355.876, 3154.96, 2955.75 + 0.35, 21000.0, 0.9525, 10728.89, 4191.69, 3183.12 + 0.35, 24000.0, 0.0, 283.7553, 283.755, 0.0 + 0.35, 24000.0, 0.3984, -2517.138, -604.821, 1331.38 + 0.35, 24000.0, 0.4648, -1393.833, -232.427, 1553.28 + 0.35, 24000.0, 0.5312, -270.5258, 139.967, 1775.17 + 0.35, 24000.0, 0.5976, 852.7786, 512.361, 1997.07 + 0.35, 24000.0, 0.664, 1990.071, 880.088, 2218.97 + 0.35, 24000.0, 0.7304, 3463.434, 1357.55, 2440.86 + 0.35, 24000.0, 0.7968, 5147.198, 1931.98, 2662.76 + 0.35, 24000.0, 0.8632, 7112.158, 2625.47, 2884.66 + 0.35, 24000.0, 0.9295, 9140.302, 3497.25, 3106.55 + 0.35, 24000.0, 0.9959, 11189.68, 4494.36, 3328.45 + 0.35, 27000.0, 0.0, 252.0106, 252.011, 0.0 + 0.35, 27000.0, 0.3886, -1015.777, 227.647, 1298.58 + 0.35, 27000.0, 0.4533, -436.1125, 345.877, 1515.01 + 0.35, 27000.0, 0.5181, 143.546, 464.102, 1731.44 + 0.35, 27000.0, 0.5828, 723.2062, 582.327, 1947.87 + 0.35, 27000.0, 0.6476, 1342.332, 701.273, 2164.3 + 0.35, 27000.0, 0.7124, 2745.677, 1058.15, 2380.73 + 0.35, 27000.0, 0.7771, 4192.823, 1555.42, 2597.16 + 0.35, 27000.0, 0.8419, 5650.792, 2244.88, 2813.59 + 0.35, 27000.0, 0.9066, 8063.762, 2987.99, 3030.02 + 0.35, 27000.0, 0.9714, 8817.194, 3764.54, 3246.45 + 0.35, 30000.0, 0.0, 223.1478, 223.148, 0.0 + 0.35, 30000.0, 0.3788, -1945.568, -328.953, 1265.79 + 0.35, 30000.0, 0.4419, -1002.078, -75.0909, 1476.75 + 0.35, 30000.0, 0.505, -58.6472, 178.789, 1687.71 + 0.35, 30000.0, 0.5681, 884.8133, 432.658, 1898.68 + 0.35, 30000.0, 0.6313, 1601.825, 595.792, 2109.64 + 0.35, 30000.0, 0.6944, 1813.371, 845.16, 2320.61 + 0.35, 30000.0, 0.7575, 3250.793, 1185.62, 2531.57 + 0.35, 30000.0, 0.8206, 4812.289, 1584.29, 2742.54 + 0.35, 30000.0, 0.8838, 7143.23, 2856.55, 2953.5 + 0.35, 30000.0, 0.9469, 10041.4, 3532.92, 3164.47 + 0.35, 33000.0, 0.0, 196.9671, 196.967, 0.0 + 0.35, 33000.0, 0.3689, 5267.119, 307.666, 1233.0 + 0.35, 33000.0, 0.4304, 4365.809, 345.907, 1438.51 + 0.35, 33000.0, 0.4919, 3464.483, 384.146, 1644.01 + 0.35, 33000.0, 0.5534, 2563.154, 422.396, 1849.51 + 0.35, 33000.0, 0.6149, 1661.818, 460.626, 2055.01 + 0.35, 33000.0, 0.6764, 1331.453, 641.111, 2260.51 + 0.35, 33000.0, 0.7379, 3665.191, 1446.83, 2466.01 + 0.35, 33000.0, 0.7994, 4714.72, 1761.65, 2671.51 + 0.35, 33000.0, 0.8609, 4635.347, 1598.91, 2877.01 + 0.35, 33000.0, 0.9224, 5954.984, 2345.67, 3082.51 + 0.35, 33000.0, 0.9838, -306.6352, -1694.85, 3288.01 + 0.35, 36000.0, 0.0, 173.2815, 173.282, 0.0 + 0.35, 36000.0, 0.3591, 4510.24, 58.6851, 1200.23 + 0.35, 36000.0, 0.419, 3767.056, 160.173, 1400.27 + 0.35, 36000.0, 0.4788, 3023.836, 261.66, 1600.3 + 0.35, 36000.0, 0.5387, 2280.645, 363.151, 1800.34 + 0.35, 36000.0, 0.5986, 1537.441, 464.627, 2000.38 + 0.35, 36000.0, 0.6584, 1231.536, 558.726, 2200.42 + 0.35, 36000.0, 0.7183, 1878.864, 756.58, 2400.46 + 0.35, 36000.0, 0.7781, 494.8921, 785.507, 2600.49 + 0.35, 36000.0, 0.838, 8917.534, 2596.36, 2800.53 + 0.35, 36000.0, 0.8978, 6736.401, 2701.79, 3000.57 + 0.35, 36000.0, 0.9577, 1987.744, -502.83, 3200.61 + 0.35, 39000.0, 0.0, 150.1952, 150.195, 0.0 + 0.35, 39000.0, 0.3586, -1099.834, -351.733, 1198.57 + 0.35, 39000.0, 0.4184, -812.4277, -213.005, 1398.33 + 0.35, 39000.0, 0.4782, -525.048, -74.2751, 1598.1 + 0.35, 39000.0, 0.538, -237.6472, 64.4635, 1797.86 + 0.35, 39000.0, 0.5977, 49.734, 203.197, 1997.62 + 0.35, 39000.0, 0.6575, 252.761, 300.404, 2197.38 + 0.35, 39000.0, 0.7173, 1379.74, 601.424, 2397.15 + 0.35, 39000.0, 0.7771, 1707.121, 708.546, 2596.91 + 0.35, 39000.0, 0.8368, 3977.512, 760.317, 2796.67 + 0.35, 39000.0, 0.8966, 5244.926, 2098.55, 2996.43 + 0.35, 39000.0, 0.9564, 16269.08, 8764.22, 3196.19 + 0.35, 42000.0, 0.0, 130.1001, 130.1, 0.0 + 0.35, 42000.0, 0.3586, -78983.19, -30208.2, 1198.57 + 0.35, 42000.0, 0.4184, -61921.37, -23615.1, 1398.33 + 0.35, 42000.0, 0.4782, -44859.55, -17022.1, 1598.1 + 0.35, 42000.0, 0.538, -27797.76, -10429.0, 1797.86 + 0.35, 42000.0, 0.5977, -10735.95, -3835.97, 1997.62 + 0.35, 42000.0, 0.6575, -2092.492, -575.419, 2197.38 + 0.35, 42000.0, 0.7173, 2346.461, 645.949, 2397.15 + 0.35, 42000.0, 0.7771, 28.35946, 653.266, 2596.91 + 0.35, 42000.0, 0.8368, 6023.07, 2990.2, 2796.67 + 0.35, 42000.0, 0.8966, 1882.389, 805.627, 2996.43 + 0.35, 42000.0, 0.9564, 8216.782, 4770.24, 3196.19 + 0.4, 0.0, 0.0, 683.0628, 683.063, 0.0 + 0.4, 0.0, 0.4805, -1668.094, 21.4155, 1605.8 + 0.4, 0.0, 0.5606, 256.0642, 717.913, 1873.44 + 0.4, 0.0, 0.6407, 2180.222, 1414.41, 2141.07 + 0.4, 0.0, 0.7207, 4596.588, 2222.0, 2408.7 + 0.4, 0.0, 0.8008, 7693.731, 3363.5, 2676.34 + 0.4, 0.0, 0.8809, 11317.47, 4915.3, 2943.97 + 0.4, 0.0, 0.961, 16269.15, 7008.14, 3211.6 + 0.4, 3000.0, 0.0, 618.6121, 618.612, 0.0 + 0.4, 3000.0, 0.4706, -1854.571, -68.078, 1572.69 + 0.4, 3000.0, 0.549, 9.847154, 576.185, 1834.8 + 0.4, 3000.0, 0.6274, 1874.266, 1220.45, 2096.91 + 0.4, 3000.0, 0.7059, 3895.909, 1925.03, 2359.03 + 0.4, 3000.0, 0.7843, 6609.737, 2909.95, 2621.14 + 0.4, 3000.0, 0.8627, 10118.81, 4268.76, 2883.26 + 0.4, 3000.0, 0.9412, 14841.29, 6153.56, 3145.37 + 0.4, 6000.0, 0.0, 559.0785, 559.078, 0.0 + 0.4, 6000.0, 0.4607, -2030.266, -153.789, 1539.58 + 0.4, 6000.0, 0.5375, -276.7292, 441.267, 1796.17 + 0.4, 6000.0, 0.6142, 1476.807, 1036.32, 2052.77 + 0.4, 6000.0, 0.691, 3306.418, 1662.68, 2309.36 + 0.4, 6000.0, 0.7678, 5690.173, 2514.91, 2565.96 + 0.4, 6000.0, 0.8446, 8775.895, 3689.99, 2822.56 + 0.4, 6000.0, 0.9214, 12875.94, 5312.22, 3079.15 + 0.4, 6000.0, 0.9981, 17540.92, 7250.29, 3335.75 + 0.4, 9000.0, 0.0, 504.1802, 504.18, 0.0 + 0.4, 9000.0, 0.4508, -2206.739, -252.414, 1506.48 + 0.4, 9000.0, 0.5259, -551.2397, 302.559, 1757.56 + 0.4, 9000.0, 0.601, 1104.26, 857.532, 2008.64 + 0.4, 9000.0, 0.6762, 2770.129, 1417.12, 2259.72 + 0.4, 9000.0, 0.7513, 4862.408, 2156.26, 2510.8 + 0.4, 9000.0, 0.8264, 7573.585, 3174.47, 2761.88 + 0.4, 9000.0, 0.9015, 11153.25, 4573.71, 3012.96 + 0.4, 9000.0, 0.9767, 15268.13, 6285.81, 3264.04 + 0.4, 12000.0, 0.0, 453.6411, 453.641, 0.0 + 0.4, 12000.0, 0.4409, -2305.549, -320.35, 1473.39 + 0.4, 12000.0, 0.5143, -768.81, 188.171, 1718.95 + 0.4, 12000.0, 0.5878, 767.929, 696.691, 1964.52 + 0.4, 12000.0, 0.6613, 2304.668, 1205.21, 2210.08 + 0.4, 12000.0, 0.7348, 4138.79, 1838.25, 2455.65 + 0.4, 12000.0, 0.8083, 6506.764, 2707.23, 2701.21 + 0.4, 12000.0, 0.8817, 9608.209, 3901.03, 2946.78 + 0.4, 12000.0, 0.9552, 13166.09, 5370.39, 3192.34 + 0.4, 15000.0, 0.0, 407.203, 407.203, 0.0 + 0.4, 15000.0, 0.431, -2148.74, -313.154, 1440.31 + 0.4, 15000.0, 0.5028, -795.1206, 132.738, 1680.36 + 0.4, 15000.0, 0.5746, 558.4993, 578.63, 1920.41 + 0.4, 15000.0, 0.6465, 1912.119, 1024.52, 2160.47 + 0.4, 15000.0, 0.7183, 3473.266, 1551.8, 2400.52 + 0.4, 15000.0, 0.7901, 5553.717, 2300.03, 2640.57 + 0.4, 15000.0, 0.8619, 8221.808, 3310.41, 2880.62 + 0.4, 15000.0, 0.9338, 11327.86, 4565.06, 3120.67 + 0.4, 18000.0, 0.0, 364.6153, 364.615, 0.0 + 0.4, 18000.0, 0.4211, -2004.833, -313.203, 1407.24 + 0.4, 18000.0, 0.4913, -808.2494, 81.8021, 1641.78 + 0.4, 18000.0, 0.5614, 388.3345, 476.807, 1876.32 + 0.4, 18000.0, 0.6316, 1584.918, 871.812, 2110.86 + 0.4, 18000.0, 0.7018, 2934.351, 1321.24, 2345.4 + 0.4, 18000.0, 0.772, 4714.472, 1946.02, 2579.94 + 0.4, 18000.0, 0.8422, 7037.441, 2811.59, 2814.48 + 0.4, 18000.0, 0.9123, 9730.413, 3878.34, 3049.02 + 0.4, 18000.0, 0.9825, 12651.1, 5197.39, 3283.56 + 0.4, 21000.0, 0.0, 325.6352, 325.635, 0.0 + 0.4, 21000.0, 0.4112, -2090.576, -362.852, 1374.18 + 0.4, 21000.0, 0.4797, -975.667, 0.0911616, 1603.21 + 0.4, 21000.0, 0.5482, 139.2426, 363.035, 1832.24 + 0.4, 21000.0, 0.6168, 1254.152, 725.978, 2061.27 + 0.4, 21000.0, 0.6853, 2425.448, 1110.02, 2290.3 + 0.4, 21000.0, 0.7538, 3981.107, 1644.14, 2519.33 + 0.4, 21000.0, 0.8224, 5964.463, 2368.33, 2748.36 + 0.4, 21000.0, 0.8909, 8313.524, 3279.02, 2977.39 + 0.4, 21000.0, 0.9594, 10752.9, 4374.33, 3206.42 + 0.4, 24000.0, 0.0, 290.0328, 290.033, 0.0 + 0.4, 24000.0, 0.4013, -2282.463, -475.015, 1341.13 + 0.4, 24000.0, 0.4682, -1223.719, -126.073, 1564.65 + 0.4, 24000.0, 0.5351, -164.9754, 222.869, 1788.17 + 0.4, 24000.0, 0.6019, 893.7679, 571.81, 2011.69 + 0.4, 24000.0, 0.6688, 1945.462, 915.959, 2235.21 + 0.4, 24000.0, 0.7357, 3347.274, 1385.91, 2458.73 + 0.4, 24000.0, 0.8026, 5076.371, 1998.19, 2682.25 + 0.4, 24000.0, 0.8695, 7042.63, 2746.54, 2905.77 + 0.4, 24000.0, 0.9364, 9151.863, 3667.21, 3129.3 + 0.4, 27000.0, 0.0, 257.5858, 257.586, 0.0 + 0.4, 27000.0, 0.3914, -1807.253, -199.044, 1308.09 + 0.4, 27000.0, 0.4566, -991.7983, 38.9906, 1526.1 + 0.4, 27000.0, 0.5219, -176.3463, 277.023, 1744.12 + 0.4, 27000.0, 0.5871, 639.1066, 515.055, 1962.13 + 0.4, 27000.0, 0.6523, 1475.572, 755.644, 2180.14 + 0.4, 27000.0, 0.7176, 2716.512, 1128.13, 2398.16 + 0.4, 27000.0, 0.7828, 4217.789, 1654.76, 2616.17 + 0.4, 27000.0, 0.8481, 5842.676, 2330.43, 2834.19 + 0.4, 27000.0, 0.9133, 7939.486, 3106.92, 3052.2 + 0.4, 27000.0, 0.9785, 9155.314, 3925.65, 3270.22 + 0.4, 30000.0, 0.0, 228.0845, 228.084, 0.0 + 0.4, 30000.0, 0.3815, -2055.915, -418.668, 1275.05 + 0.4, 30000.0, 0.4451, -1153.926, -144.971, 1487.56 + 0.4, 30000.0, 0.5087, -251.9688, 128.735, 1700.07 + 0.4, 30000.0, 0.5723, 650.004, 402.435, 1912.58 + 0.4, 30000.0, 0.6359, 1438.753, 630.767, 2125.09 + 0.4, 30000.0, 0.6995, 1970.808, 908.024, 2337.6 + 0.4, 30000.0, 0.763, 3357.552, 1310.03, 2550.11 + 0.4, 30000.0, 0.8266, 4915.994, 1801.48, 2762.61 + 0.4, 30000.0, 0.8902, 6883.965, 2789.63, 2975.12 + 0.4, 30000.0, 0.9538, 9134.169, 3543.91, 3187.63 + 0.4, 33000.0, 0.0, 201.3247, 201.325, 0.0 + 0.4, 33000.0, 0.3716, 2071.918, -65.3687, 1242.03 + 0.4, 33000.0, 0.4336, 1886.114, 72.7418, 1449.04 + 0.4, 33000.0, 0.4955, 1700.301, 210.851, 1656.04 + 0.4, 33000.0, 0.5575, 1514.487, 348.967, 1863.05 + 0.4, 33000.0, 0.6194, 1328.668, 487.071, 2070.05 + 0.4, 33000.0, 0.6813, 1511.652, 720.117, 2277.06 + 0.4, 33000.0, 0.7433, 3305.173, 1341.62, 2484.06 + 0.4, 33000.0, 0.8052, 4482.113, 1733.68, 2691.07 + 0.4, 33000.0, 0.8672, 5088.722, 1914.44, 2898.07 + 0.4, 33000.0, 0.9291, 6215.403, 2535.64, 3105.08 + 0.4, 33000.0, 0.991, 2715.399, 271.146, 3312.08 + 0.4, 36000.0, 0.0, 177.115, 177.115, 0.0 + 0.4, 36000.0, 0.3618, 1531.235, -226.922, 1209.01 + 0.4, 36000.0, 0.4221, 1419.755, -63.188, 1410.52 + 0.4, 36000.0, 0.4824, 1308.253, 100.546, 1612.02 + 0.4, 36000.0, 0.5426, 1196.769, 264.283, 1813.52 + 0.4, 36000.0, 0.6029, 1085.277, 428.01, 2015.02 + 0.4, 36000.0, 0.6632, 1233.079, 588.107, 2216.53 + 0.4, 36000.0, 0.7235, 1967.394, 829.674, 2418.03 + 0.4, 36000.0, 0.7838, 1633.311, 1022.94, 2619.53 + 0.4, 36000.0, 0.8441, 7097.68, 2279.54, 2821.03 + 0.4, 36000.0, 0.9044, 6256.716, 2599.46, 3022.54 + 0.4, 36000.0, 0.9647, 3384.185, 710.952, 3224.04 + 0.4, 39000.0, 0.0, 153.518, 153.518, 0.0 + 0.4, 39000.0, 0.3613, -1328.509, -394.786, 1207.35 + 0.4, 39000.0, 0.4215, -956.698, -235.441, 1408.57 + 0.4, 39000.0, 0.4817, -584.9018, -76.0941, 1609.8 + 0.4, 39000.0, 0.5419, -213.0931, 83.2575, 1811.02 + 0.4, 39000.0, 0.6021, 158.7037, 242.606, 2012.25 + 0.4, 39000.0, 0.6623, 492.2062, 375.92, 2213.47 + 0.4, 39000.0, 0.7225, 1484.365, 665.449, 2414.69 + 0.4, 39000.0, 0.7827, 2077.35, 881.199, 2615.92 + 0.4, 39000.0, 0.843, 3860.692, 1073.03, 2817.14 + 0.4, 39000.0, 0.9032, 4961.651, 2057.9, 3018.37 + 0.4, 39000.0, 0.9634, 11464.83, 6025.86, 3219.59 + 0.4, 42000.0, 0.0, 132.9783, 132.978, 0.0 + 0.4, 42000.0, 0.3613, -55155.42, -21038.6, 1207.35 + 0.4, 42000.0, 0.4215, -43219.9, -16429.0, 1408.57 + 0.4, 42000.0, 0.4817, -31284.38, -11819.3, 1609.8 + 0.4, 42000.0, 0.5419, -19348.88, -7209.64, 1811.02 + 0.4, 42000.0, 0.6021, -7413.359, -2600.0, 2012.25 + 0.4, 42000.0, 0.6623, -1193.685, -249.72, 2213.47 + 0.4, 42000.0, 0.7225, 1960.611, 644.608, 2414.69 + 0.4, 42000.0, 0.7827, 730.4578, 742.769, 2615.92 + 0.4, 42000.0, 0.843, 4959.91, 2406.42, 2817.14 + 0.4, 42000.0, 0.9032, 2620.203, 1161.54, 3018.37 + 0.4, 42000.0, 0.9634, 7330.557, 4092.74, 3219.59 + 0.45, 0.0, 0.0, 700.0802, 700.08, 0.0 + 0.45, 0.0, 0.4844, -1957.035, 37.6904, 1619.03 + 0.45, 0.0, 0.5652, 21.9571, 753.093, 1888.87 + 0.45, 0.0, 0.6459, 2000.95, 1468.5, 2158.7 + 0.45, 0.0, 0.7267, 4478.618, 2317.06, 2428.54 + 0.45, 0.0, 0.8074, 7451.707, 3502.42, 2698.38 + 0.45, 0.0, 0.8882, 10753.3, 5106.92, 2968.22 + 0.45, 0.0, 0.9689, 15828.84, 7274.21, 3238.06 + 0.45, 3000.0, 0.0, 634.0238, 634.024, 0.0 + 0.45, 3000.0, 0.4745, -1796.128, -34.7644, 1585.64 + 0.45, 3000.0, 0.5535, -4.540111, 619.56, 1849.91 + 0.45, 3000.0, 0.6326, 1787.048, 1273.88, 2114.19 + 0.45, 3000.0, 0.7117, 3770.802, 2002.15, 2378.46 + 0.45, 3000.0, 0.7908, 6548.779, 3041.31, 2642.73 + 0.45, 3000.0, 0.8698, 10052.93, 4456.01, 2907.01 + 0.45, 3000.0, 0.9489, 14817.91, 6437.99, 3171.28 + 0.45, 6000.0, 0.0, 573.007, 573.007, 0.0 + 0.45, 6000.0, 0.4645, -2049.696, -125.006, 1552.26 + 0.45, 6000.0, 0.5419, -324.2031, 480.806, 1810.97 + 0.45, 6000.0, 0.6193, 1401.29, 1086.62, 2069.68 + 0.45, 6000.0, 0.6967, 3221.156, 1734.35, 2328.39 + 0.45, 6000.0, 0.7741, 5625.921, 2623.1, 2587.09 + 0.45, 6000.0, 0.8515, 8795.059, 3866.76, 2845.8 + 0.45, 6000.0, 0.9289, 12959.43, 5575.21, 3104.51 + 0.45, 9000.0, 0.0, 516.741, 516.741, 0.0 + 0.45, 9000.0, 0.4545, -2181.19, -228.103, 1518.89 + 0.45, 9000.0, 0.5302, -563.1777, 337.462, 1772.03 + 0.45, 9000.0, 0.606, 1054.835, 903.027, 2025.18 + 0.45, 9000.0, 0.6817, 2703.822, 1482.37, 2278.33 + 0.45, 9000.0, 0.7575, 4820.763, 2256.16, 2531.48 + 0.45, 9000.0, 0.8332, 7577.894, 3320.92, 2784.63 + 0.45, 9000.0, 0.909, 11215.82, 4795.23, 3037.77 + 0.45, 9000.0, 0.9847, 15292.75, 6569.53, 3290.92 + 0.45, 12000.0, 0.0, 464.9428, 464.943, 0.0 + 0.45, 12000.0, 0.4445, -2217.088, -298.703, 1485.52 + 0.45, 12000.0, 0.5186, -730.5532, 219.83, 1733.11 + 0.45, 12000.0, 0.5927, 755.9815, 738.363, 1980.7 + 0.45, 12000.0, 0.6668, 2241.808, 1256.58, 2228.29 + 0.45, 12000.0, 0.7408, 4085.418, 1920.4, 2475.87 + 0.45, 12000.0, 0.8149, 6517.659, 2839.27, 2723.46 + 0.45, 12000.0, 0.889, 9678.488, 4098.61, 2971.05 + 0.45, 12000.0, 0.9631, 13226.14, 5635.88, 3218.63 + 0.45, 15000.0, 0.0, 417.3478, 417.348, 0.0 + 0.45, 15000.0, 0.4345, -2248.176, -334.015, 1452.17 + 0.45, 15000.0, 0.5069, -885.0414, 132.603, 1694.2 + 0.45, 15000.0, 0.5794, 478.0937, 599.221, 1936.23 + 0.45, 15000.0, 0.6518, 1841.229, 1065.84, 2178.26 + 0.45, 15000.0, 0.7242, 3426.263, 1625.14, 2420.29 + 0.45, 15000.0, 0.7966, 5560.951, 2412.06, 2662.32 + 0.45, 15000.0, 0.869, 8306.4, 3482.96, 2904.35 + 0.45, 15000.0, 0.9415, 11366.82, 4794.44, 3146.38 + 0.45, 18000.0, 0.0, 373.6991, 373.699, 0.0 + 0.45, 18000.0, 0.4245, -2042.915, -320.931, 1418.83 + 0.45, 18000.0, 0.4953, -852.7942, 88.4838, 1655.3 + 0.45, 18000.0, 0.5661, 337.3264, 497.899, 1891.77 + 0.45, 18000.0, 0.6368, 1527.447, 907.313, 2128.24 + 0.45, 18000.0, 0.7076, 2879.141, 1378.15, 2364.71 + 0.45, 18000.0, 0.7783, 4695.796, 2036.7, 2601.19 + 0.45, 18000.0, 0.8491, 7087.478, 2955.12, 2837.66 + 0.45, 18000.0, 0.9198, 9753.166, 4068.48, 3074.13 + 0.45, 18000.0, 0.9906, 12682.64, 5434.41, 3310.6 + 0.45, 21000.0, 0.0, 333.7479, 333.748, 0.0 + 0.45, 21000.0, 0.4146, -1995.245, -348.564, 1385.5 + 0.45, 21000.0, 0.4837, -920.2199, 21.3858, 1616.41 + 0.45, 21000.0, 0.5528, 154.8055, 391.336, 1847.33 + 0.45, 21000.0, 0.6219, 1229.831, 761.285, 2078.25 + 0.45, 21000.0, 0.691, 2390.078, 1162.57, 2309.16 + 0.45, 21000.0, 0.76, 3971.206, 1723.1, 2540.08 + 0.45, 21000.0, 0.8291, 6011.445, 2492.41, 2771.0 + 0.45, 21000.0, 0.8982, 8327.79, 3437.95, 3001.91 + 0.45, 21000.0, 0.9673, 10831.58, 4602.31, 3232.83 + 0.45, 24000.0, 0.0, 297.2585, 297.259, 0.0 + 0.45, 24000.0, 0.4046, -2081.428, -400.598, 1352.17 + 0.45, 24000.0, 0.472, -1081.008, -60.5732, 1577.53 + 0.45, 24000.0, 0.5395, -80.58787, 279.452, 1802.9 + 0.45, 24000.0, 0.6069, 919.8323, 619.477, 2028.26 + 0.45, 24000.0, 0.6743, 1924.339, 961.196, 2253.62 + 0.45, 24000.0, 0.7418, 3292.958, 1439.02, 2478.98 + 0.45, 24000.0, 0.8092, 5058.803, 2088.12, 2704.35 + 0.45, 24000.0, 0.8766, 7044.422, 2884.79, 2929.71 + 0.45, 24000.0, 0.9441, 9175.572, 3850.6, 3155.07 + 0.45, 27000.0, 0.0, 264.0032, 264.003, 0.0 + 0.45, 27000.0, 0.3946, -2125.69, -401.134, 1318.86 + 0.45, 27000.0, 0.4604, -1212.561, -100.979, 1538.67 + 0.45, 27000.0, 0.5262, -299.4336, 199.174, 1758.48 + 0.45, 27000.0, 0.5919, 613.6945, 499.328, 1978.29 + 0.45, 27000.0, 0.6577, 1533.488, 800.845, 2198.1 + 0.45, 27000.0, 0.7235, 2704.981, 1194.72, 2417.91 + 0.45, 27000.0, 0.7893, 4235.972, 1747.72, 2637.72 + 0.45, 27000.0, 0.855, 5958.296, 2433.89, 2857.53 + 0.45, 27000.0, 0.9208, 7877.412, 3246.53, 3077.34 + 0.45, 27000.0, 0.9866, 9363.716, 4112.05, 3297.15 + 0.45, 30000.0, 0.0, 233.7668, 233.767, 0.0 + 0.45, 30000.0, 0.3847, -2119.268, -468.679, 1285.55 + 0.45, 30000.0, 0.4488, -1246.301, -180.77, 1499.81 + 0.45, 30000.0, 0.5129, -373.3472, 107.142, 1714.07 + 0.45, 30000.0, 0.577, 499.613, 395.052, 1928.33 + 0.45, 30000.0, 0.6411, 1327.284, 664.815, 2142.59 + 0.45, 30000.0, 0.7052, 2084.723, 971.211, 2356.85 + 0.45, 30000.0, 0.7693, 3438.474, 1419.68, 2571.11 + 0.45, 30000.0, 0.8334, 5001.602, 1979.91, 2785.37 + 0.45, 30000.0, 0.8976, 6745.028, 2802.26, 2999.63 + 0.45, 30000.0, 0.9617, 8543.965, 3595.8, 3213.89 + 0.45, 33000.0, 0.0, 206.3403, 206.34, 0.0 + 0.45, 33000.0, 0.3747, -79.32924, -312.722, 1252.26 + 0.45, 33000.0, 0.4372, 217.7307, -105.233, 1460.97 + 0.45, 33000.0, 0.4996, 514.7858, 102.256, 1669.68 + 0.45, 33000.0, 0.5621, 811.8402, 309.749, 1878.39 + 0.45, 33000.0, 0.6245, 1108.892, 517.235, 2087.1 + 0.45, 33000.0, 0.687, 1635.208, 787.277, 2295.81 + 0.45, 33000.0, 0.7494, 3074.026, 1293.74, 2504.52 + 0.45, 33000.0, 0.8119, 4342.639, 1748.32, 2713.23 + 0.45, 33000.0, 0.8743, 5396.402, 2161.48, 2921.94 + 0.45, 33000.0, 0.9368, 6445.206, 2739.07, 3130.65 + 0.45, 33000.0, 0.9992, 4940.575, 1760.52, 3339.36 + 0.45, 36000.0, 0.0, 181.5276, 181.528, 0.0 + 0.45, 36000.0, 0.3647, -448.6355, -415.557, 1218.97 + 0.45, 36000.0, 0.4255, -138.5643, -207.957, 1422.13 + 0.45, 36000.0, 0.4863, 171.4962, -0.3574, 1625.3 + 0.45, 36000.0, 0.5471, 481.5658, 207.243, 1828.46 + 0.45, 36000.0, 0.6079, 791.6309, 414.839, 2031.62 + 0.45, 36000.0, 0.6687, 1243.21, 622.83, 2234.78 + 0.45, 36000.0, 0.7295, 2049.386, 901.631, 2437.95 + 0.45, 36000.0, 0.7903, 2438.017, 1213.96, 2641.11 + 0.45, 36000.0, 0.8511, 5870.608, 2102.88, 2844.27 + 0.45, 36000.0, 0.9119, 5930.014, 2558.24, 3047.43 + 0.45, 36000.0, 0.9726, 4408.108, 1604.07, 3250.59 + 0.45, 39000.0, 0.0, 157.3426, 157.343, 0.0 + 0.45, 39000.0, 0.3642, -1539.346, -433.008, 1217.29 + 0.45, 39000.0, 0.4249, -1096.72, -255.636, 1420.17 + 0.45, 39000.0, 0.4857, -654.102, -78.2639, 1623.06 + 0.45, 39000.0, 0.5464, -211.4771, 99.1111, 1825.94 + 0.45, 39000.0, 0.6071, 231.1413, 276.485, 2028.82 + 0.45, 39000.0, 0.6678, 669.14, 441.412, 2231.7 + 0.45, 39000.0, 0.7285, 1571.87, 727.78, 2434.58 + 0.45, 39000.0, 0.7892, 2355.795, 1022.96, 2637.46 + 0.45, 39000.0, 0.8499, 3797.995, 1321.76, 2840.35 + 0.45, 39000.0, 0.9106, 4790.425, 2067.88, 3043.23 + 0.45, 39000.0, 0.9713, 8270.471, 4225.11, 3246.11 + 0.45, 42000.0, 0.0, 136.2912, 136.291, 0.0 + 0.45, 42000.0, 0.3642, -36867.1, -14004.4, 1217.29 + 0.45, 42000.0, 0.4249, -28864.98, -10914.1, 1420.17 + 0.45, 42000.0, 0.4857, -20862.86, -7823.74, 1623.06 + 0.45, 42000.0, 0.5464, -12860.75, -4733.41, 1825.94 + 0.45, 42000.0, 0.6071, -4858.635, -1643.1, 2028.82 + 0.45, 42000.0, 0.6678, -518.1821, 1.63147, 2231.7 + 0.45, 42000.0, 0.7285, 1684.177, 653.67, 2434.58 + 0.45, 42000.0, 0.7892, 1267.622, 828.694, 2637.46 + 0.45, 42000.0, 0.8499, 4188.432, 1995.4, 2840.35 + 0.45, 42000.0, 0.9106, 3163.467, 1442.04, 3043.23 + 0.45, 42000.0, 0.9713, 6587.986, 3562.45, 3246.11 + 0.5, 0.0, 0.0, 719.4315, 719.431, 0.0 + 0.5, 0.0, 0.4889, -2671.868, 32.7587, 1633.81 + 0.5, 0.0, 0.5704, -449.1081, 779.49, 1906.11 + 0.5, 0.0, 0.6518, 1773.654, 1526.22, 2178.41 + 0.5, 0.0, 0.7333, 4378.322, 2426.67, 2450.72 + 0.5, 0.0, 0.8148, 6999.003, 3647.61, 2723.02 + 0.5, 0.0, 0.8963, 9737.89, 5289.23, 2995.32 + 0.5, 0.0, 0.9777, 15257.61, 7555.28, 3267.62 + 0.5, 3000.0, 0.0, 651.5492, 651.549, 0.0 + 0.5, 3000.0, 0.4788, -1671.107, 5.00538, 1600.12 + 0.5, 3000.0, 0.5586, 13.27505, 669.369, 1866.8 + 0.5, 3000.0, 0.6384, 1697.66, 1333.73, 2133.49 + 0.5, 3000.0, 0.7182, 3635.082, 2087.95, 2400.17 + 0.5, 3000.0, 0.798, 6571.444, 3191.76, 2666.86 + 0.5, 3000.0, 0.8778, 10002.67, 4663.66, 2933.55 + 0.5, 3000.0, 0.9576, 14493.52, 6706.77, 3200.23 + 0.5, 6000.0, 0.0, 588.8458, 588.846, 0.0 + 0.5, 6000.0, 0.4687, -2323.44, -95.1125, 1566.43 + 0.5, 6000.0, 0.5468, -537.0041, 523.082, 1827.5 + 0.5, 6000.0, 0.6249, 1249.434, 1141.28, 2088.57 + 0.5, 6000.0, 0.7031, 3131.35, 1813.32, 2349.64 + 0.5, 6000.0, 0.7812, 5635.994, 2747.63, 2610.72 + 0.5, 6000.0, 0.8593, 8788.324, 4048.32, 2871.79 + 0.5, 6000.0, 0.9374, 13071.73, 5872.37, 3132.86 + 0.5, 9000.0, 0.0, 531.0245, 531.025, 0.0 + 0.5, 9000.0, 0.4586, -2094.958, -195.29, 1532.75 + 0.5, 9000.0, 0.5351, -526.4189, 380.417, 1788.21 + 0.5, 9000.0, 0.6115, 1042.12, 956.124, 2043.67 + 0.5, 9000.0, 0.688, 2662.114, 1556.12, 2299.13 + 0.5, 9000.0, 0.7644, 4775.584, 2364.99, 2554.59 + 0.5, 9000.0, 0.8408, 7591.811, 3485.41, 2810.05 + 0.5, 9000.0, 0.9173, 11306.15, 5046.37, 3065.51 + 0.5, 9000.0, 0.9937, 15293.15, 6872.21, 3320.97 + 0.5, 12000.0, 0.0, 477.7945, 477.795, 0.0 + 0.5, 12000.0, 0.4486, -2187.265, -271.272, 1499.09 + 0.5, 12000.0, 0.5233, -726.794, 257.496, 1748.93 + 0.5, 12000.0, 0.5981, 733.6773, 786.264, 1998.78 + 0.5, 12000.0, 0.6728, 2198.014, 1316.6, 2248.63 + 0.5, 12000.0, 0.7476, 4042.146, 2012.59, 2498.48 + 0.5, 12000.0, 0.8224, 6520.895, 2982.37, 2748.33 + 0.5, 12000.0, 0.8971, 9754.751, 4315.03, 2998.17 + 0.5, 12000.0, 0.9719, 13291.54, 5923.31, 3248.02 + 0.5, 15000.0, 0.0, 428.884, 428.884, 0.0 + 0.5, 15000.0, 0.4385, -2261.084, -339.079, 1465.43 + 0.5, 15000.0, 0.5116, -906.3853, 146.084, 1709.67 + 0.5, 15000.0, 0.5847, 448.3132, 631.248, 1953.91 + 0.5, 15000.0, 0.6577, 1803.012, 1116.41, 2198.15 + 0.5, 15000.0, 0.7308, 3403.829, 1708.31, 2442.39 + 0.5, 15000.0, 0.8039, 5551.821, 2532.89, 2686.62 + 0.5, 15000.0, 0.877, 8343.471, 3664.0, 2930.86 + 0.5, 15000.0, 0.9501, 11431.69, 5044.93, 3175.1 + 0.5, 18000.0, 0.0, 384.0288, 384.029, 0.0 + 0.5, 18000.0, 0.4284, -2094.154, -339.049, 1431.78 + 0.5, 18000.0, 0.4998, -902.8738, 89.6265, 1670.41 + 0.5, 18000.0, 0.5712, 288.4068, 518.302, 1909.04 + 0.5, 18000.0, 0.6426, 1479.687, 946.977, 2147.67 + 0.5, 18000.0, 0.714, 2838.913, 1442.41, 2386.31 + 0.5, 18000.0, 0.7854, 4697.477, 2144.34, 2624.94 + 0.5, 18000.0, 0.8568, 7142.3, 3115.17, 2863.57 + 0.5, 18000.0, 0.9282, 9817.644, 4284.7, 3102.2 + 0.5, 18000.0, 0.9996, 12759.61, 5696.34, 3340.83 + 0.5, 21000.0, 0.0, 342.9732, 342.973, 0.0 + 0.5, 21000.0, 0.4184, -1938.541, -331.982, 1398.15 + 0.5, 21000.0, 0.4881, -889.0242, 45.694, 1631.17 + 0.5, 21000.0, 0.5578, 160.493, 423.37, 1864.2 + 0.5, 21000.0, 0.6275, 1210.01, 801.046, 2097.22 + 0.5, 21000.0, 0.6973, 2370.835, 1221.15, 2330.25 + 0.5, 21000.0, 0.767, 3954.671, 1808.53, 2563.27 + 0.5, 21000.0, 0.8367, 6062.116, 2627.49, 2796.29 + 0.5, 21000.0, 0.9064, 8391.196, 3625.28, 3029.32 + 0.5, 21000.0, 0.9762, 10947.83, 4860.96, 3262.34 + 0.5, 24000.0, 0.0, 305.4752, 305.475, 0.0 + 0.5, 24000.0, 0.4083, -1947.671, -367.505, 1364.52 + 0.5, 24000.0, 0.4763, -988.9591, -25.0946, 1591.94 + 0.5, 24000.0, 0.5444, -30.24772, 317.315, 1819.36 + 0.5, 24000.0, 0.6124, 928.4636, 659.726, 2046.78 + 0.5, 24000.0, 0.6805, 1919.685, 1014.17, 2274.2 + 0.5, 24000.0, 0.7485, 3285.743, 1511.56, 2501.62 + 0.5, 24000.0, 0.8166, 5083.21, 2198.35, 2729.04 + 0.5, 24000.0, 0.8846, 7101.839, 3041.49, 2956.46 + 0.5, 24000.0, 0.9527, 9226.397, 4053.31, 3183.88 + 0.5, 27000.0, 0.0, 271.3006, 271.301, 0.0 + 0.5, 27000.0, 0.3982, -2136.526, -450.559, 1330.9 + 0.5, 27000.0, 0.4646, -1216.083, -127.199, 1552.72 + 0.5, 27000.0, 0.531, -295.6394, 196.16, 1774.54 + 0.5, 27000.0, 0.5974, 624.8041, 519.52, 1996.35 + 0.5, 27000.0, 0.6637, 1544.433, 842.658, 2218.17 + 0.5, 27000.0, 0.7301, 2710.016, 1261.69, 2439.99 + 0.5, 27000.0, 0.7965, 4258.357, 1841.41, 2661.8 + 0.5, 27000.0, 0.8628, 6031.029, 2556.35, 2883.62 + 0.5, 27000.0, 0.9292, 7875.958, 3409.17, 3105.44 + 0.5, 27000.0, 0.9956, 9494.501, 4322.02, 3327.25 + 0.5, 30000.0, 0.0, 240.2285, 240.229, 0.0 + 0.5, 30000.0, 0.3882, -2138.973, -486.757, 1297.29 + 0.5, 30000.0, 0.4529, -1286.564, -189.003, 1513.51 + 0.5, 30000.0, 0.5176, -434.1592, 108.752, 1729.72 + 0.5, 30000.0, 0.5823, 418.2473, 406.507, 1945.94 + 0.5, 30000.0, 0.647, 1259.332, 699.725, 2162.15 + 0.5, 30000.0, 0.7117, 2165.241, 1035.93, 2378.37 + 0.5, 30000.0, 0.7764, 3503.84, 1520.58, 2594.58 + 0.5, 30000.0, 0.8411, 5078.298, 2132.05, 2810.8 + 0.5, 30000.0, 0.9057, 6705.982, 2882.21, 3027.01 + 0.5, 30000.0, 0.9704, 8221.599, 3691.4, 3243.23 + 0.5, 33000.0, 0.0, 212.0439, 212.044, 0.0 + 0.5, 33000.0, 0.3781, -1380.48, -457.197, 1263.69 + 0.5, 33000.0, 0.4411, -790.0098, -205.132, 1474.31 + 0.5, 33000.0, 0.5042, -199.5421, 46.9332, 1684.93 + 0.5, 33000.0, 0.5672, 390.9254, 299.0, 1895.54 + 0.5, 33000.0, 0.6302, 981.3919, 551.064, 2106.16 + 0.5, 33000.0, 0.6932, 1715.961, 846.817, 2316.77 + 0.5, 33000.0, 0.7563, 2950.938, 1294.56, 2527.39 + 0.5, 33000.0, 0.8193, 4283.182, 1800.03, 2738.01 + 0.5, 33000.0, 0.8823, 5594.077, 2358.21, 2948.62 + 0.5, 33000.0, 0.9453, 6646.168, 2951.3, 3159.24 + 0.5, 36000.0, 0.0, 186.5453, 186.545, 0.0 + 0.5, 36000.0, 0.3681, -1620.751, -524.789, 1230.1 + 0.5, 36000.0, 0.4294, -1058.968, -288.272, 1435.12 + 0.5, 36000.0, 0.4908, -497.1895, -51.7556, 1640.14 + 0.5, 36000.0, 0.5521, 64.5929, 184.762, 1845.15 + 0.5, 36000.0, 0.6135, 626.3733, 421.277, 2050.17 + 0.5, 36000.0, 0.6748, 1261.6, 662.818, 2255.19 + 0.5, 36000.0, 0.7361, 2126.836, 973.874, 2460.2 + 0.5, 36000.0, 0.7975, 2971.624, 1369.12, 2665.22 + 0.5, 36000.0, 0.8588, 5130.289, 2042.29, 2870.24 + 0.5, 36000.0, 0.9202, 5736.309, 2573.49, 3075.26 + 0.5, 36000.0, 0.9815, 5137.506, 2244.86, 3280.27 + 0.5, 39000.0, 0.0, 161.6918, 161.692, 0.0 + 0.5, 39000.0, 0.3676, -1726.111, -466.585, 1228.41 + 0.5, 39000.0, 0.4288, -1225.556, -273.233, 1433.14 + 0.5, 39000.0, 0.4901, -725.0043, -79.8808, 1637.87 + 0.5, 39000.0, 0.5513, -224.4495, 113.472, 1842.61 + 0.5, 39000.0, 0.6126, 276.1023, 306.825, 2047.34 + 0.5, 39000.0, 0.6739, 795.7263, 499.382, 2252.08 + 0.5, 39000.0, 0.7351, 1646.639, 789.802, 2456.81 + 0.5, 39000.0, 0.7964, 2559.873, 1141.45, 2661.55 + 0.5, 39000.0, 0.8577, 3782.247, 1519.73, 2866.28 + 0.5, 39000.0, 0.9189, 4713.097, 2121.98, 3071.01 + 0.5, 39000.0, 0.9802, 6383.878, 3189.42, 3275.75 + 0.5, 42000.0, 0.0, 140.0585, 140.059, 0.0 + 0.5, 42000.0, 0.3676, -23385.55, -8821.61, 1228.41 + 0.5, 42000.0, 0.4288, -18281.36, -6848.17, 1433.14 + 0.5, 42000.0, 0.4901, -13177.17, -4874.73, 1637.87 + 0.5, 42000.0, 0.5513, -8072.98, -2901.28, 1842.61 + 0.5, 42000.0, 0.6126, -2968.789, -927.842, 2047.34 + 0.5, 42000.0, 0.6739, -32.00731, 190.293, 2252.08 + 0.5, 42000.0, 0.7351, 1502.801, 673.192, 2456.81 + 0.5, 42000.0, 0.7964, 1665.687, 912.775, 2661.55 + 0.5, 42000.0, 0.8577, 3668.111, 1733.73, 2866.28 + 0.5, 42000.0, 0.9189, 3546.039, 1661.8, 3071.01 + 0.5, 42000.0, 0.9802, 5985.873, 3168.52, 3275.75 + 0.55, 0.0, 0.0, 741.231, 741.231, 0.0 + 0.55, 0.0, 0.4938, -3974.053, -2.9553, 1650.15 + 0.55, 0.0, 0.5761, -1248.034, 791.918, 1925.17 + 0.55, 0.0, 0.6583, 1477.989, 1586.79, 2200.2 + 0.55, 0.0, 0.7406, 4294.257, 2552.23, 2475.22 + 0.55, 0.0, 0.8229, 6245.607, 3795.68, 2750.25 + 0.55, 0.0, 0.9052, 8101.429, 5449.92, 3025.27 + 0.55, 0.0, 0.9875, 14492.44, 7846.66, 3300.3 + 0.55, 3000.0, 0.0, 671.2918, 671.292, 0.0 + 0.55, 3000.0, 0.4836, -1432.398, 52.9797, 1616.12 + 0.55, 3000.0, 0.5642, 84.17923, 726.809, 1885.47 + 0.55, 3000.0, 0.6448, 1600.764, 1400.64, 2154.82 + 0.55, 3000.0, 0.7254, 3473.507, 2182.72, 2424.18 + 0.55, 3000.0, 0.806, 6711.016, 3362.79, 2693.53 + 0.55, 3000.0, 0.8866, 9967.948, 4893.65, 2962.88 + 0.55, 3000.0, 0.9672, 13630.32, 6929.37, 3232.24 + 0.55, 6000.0, 0.0, 606.6884, 606.688, 0.0 + 0.55, 6000.0, 0.4734, -2990.475, -65.2126, 1582.09 + 0.55, 6000.0, 0.5523, -1009.993, 567.149, 1845.78 + 0.55, 6000.0, 0.6312, 970.4946, 1199.51, 2109.46 + 0.55, 6000.0, 0.7101, 3019.591, 1898.92, 2373.14 + 0.55, 6000.0, 0.789, 5758.484, 2892.71, 2636.82 + 0.55, 6000.0, 0.8679, 8693.278, 4221.02, 2900.5 + 0.55, 6000.0, 0.9468, 13161.28, 6201.72, 3164.19 + 0.55, 9000.0, 0.0, 547.1151, 547.115, 0.0 + 0.55, 9000.0, 0.4632, -1970.877, -155.663, 1548.08 + 0.55, 9000.0, 0.5404, -459.3171, 430.155, 1806.1 + 0.55, 9000.0, 0.6176, 1052.242, 1015.97, 2064.11 + 0.55, 9000.0, 0.6948, 2637.095, 1638.62, 2322.12 + 0.55, 9000.0, 0.772, 4737.156, 2485.62, 2580.14 + 0.55, 9000.0, 0.8492, 7626.86, 3671.9, 2838.15 + 0.55, 9000.0, 0.9264, 11417.03, 5327.19, 3096.16 + 0.55, 12000.0, 0.0, 492.2722, 492.272, 0.0 + 0.55, 12000.0, 0.453, -2116.796, -238.519, 1514.08 + 0.55, 12000.0, 0.5286, -692.9639, 300.764, 1766.42 + 0.55, 12000.0, 0.6041, 730.8686, 840.048, 2018.77 + 0.55, 12000.0, 0.6796, 2174.639, 1388.88, 2271.12 + 0.55, 12000.0, 0.7551, 4040.397, 2121.57, 2523.46 + 0.55, 12000.0, 0.8306, 6529.06, 3137.38, 2775.81 + 0.55, 12000.0, 0.9061, 9822.105, 4549.43, 3028.16 + 0.55, 12000.0, 0.9816, 13402.78, 6232.0, 3280.5 + 0.55, 15000.0, 0.0, 441.8796, 441.88, 0.0 + 0.55, 15000.0, 0.4429, -2244.384, -311.117, 1480.09 + 0.55, 15000.0, 0.5167, -904.5432, 184.22, 1726.77 + 0.55, 15000.0, 0.5905, 435.298, 679.558, 1973.45 + 0.55, 15000.0, 0.6643, 1775.139, 1174.9, 2220.13 + 0.55, 15000.0, 0.7381, 3403.266, 1800.47, 2466.81 + 0.55, 15000.0, 0.8119, 5568.139, 2669.28, 2713.49 + 0.55, 15000.0, 0.8857, 8425.525, 3873.22, 2960.17 + 0.55, 15000.0, 0.9596, 11567.98, 5329.79, 3206.85 + 0.55, 18000.0, 0.0, 395.6652, 395.665, 0.0 + 0.55, 18000.0, 0.4327, -2211.982, -357.755, 1446.1 + 0.55, 18000.0, 0.5048, -995.9855, 92.5123, 1687.12 + 0.55, 18000.0, 0.5769, 220.0107, 542.779, 1928.13 + 0.55, 18000.0, 0.6491, 1436.007, 993.047, 2169.15 + 0.55, 18000.0, 0.7212, 2833.161, 1520.37, 2410.17 + 0.55, 18000.0, 0.7933, 4728.22, 2266.31, 2651.19 + 0.55, 18000.0, 0.8654, 7192.649, 3283.88, 2892.2 + 0.55, 18000.0, 0.9375, 9949.779, 4537.13, 3133.22 + 0.55, 21000.0, 0.0, 353.3656, 353.366, 0.0 + 0.55, 21000.0, 0.4225, -2009.057, -348.765, 1412.13 + 0.55, 21000.0, 0.493, -949.5836, 47.1723, 1647.48 + 0.55, 21000.0, 0.5634, 109.8899, 443.11, 1882.84 + 0.55, 21000.0, 0.6338, 1169.363, 839.047, 2118.19 + 0.55, 21000.0, 0.7042, 2361.711, 1285.77, 2353.55 + 0.55, 21000.0, 0.7747, 3964.176, 1905.21, 2588.9 + 0.55, 21000.0, 0.8451, 6116.397, 2777.16, 2824.26 + 0.55, 21000.0, 0.9155, 8496.23, 3834.08, 3059.61 + 0.55, 21000.0, 0.9859, 11078.6, 5133.62, 3294.97 + 0.55, 24000.0, 0.0, 314.7314, 314.731, 0.0 + 0.55, 24000.0, 0.4124, -1920.54, -361.158, 1378.16 + 0.55, 24000.0, 0.4811, -975.1257, -8.44528, 1607.86 + 0.55, 24000.0, 0.5498, -29.71108, 344.268, 1837.55 + 0.55, 24000.0, 0.6186, 915.7035, 696.981, 2067.25 + 0.55, 24000.0, 0.6873, 1924.169, 1073.16, 2296.94 + 0.55, 24000.0, 0.756, 3310.933, 1598.1, 2526.63 + 0.55, 24000.0, 0.8248, 5137.796, 2325.29, 2756.33 + 0.55, 24000.0, 0.8935, 7198.694, 3217.93, 2986.02 + 0.55, 24000.0, 0.9622, 9318.197, 4280.63, 3215.71 + 0.55, 27000.0, 0.0, 279.5213, 279.521, 0.0 + 0.55, 27000.0, 0.4022, -2005.2, -419.256, 1344.21 + 0.55, 27000.0, 0.4693, -1120.044, -92.8357, 1568.25 + 0.55, 27000.0, 0.5363, -234.8871, 233.585, 1792.28 + 0.55, 27000.0, 0.6033, 650.2693, 560.006, 2016.32 + 0.55, 27000.0, 0.6704, 1536.758, 886.865, 2240.35 + 0.55, 27000.0, 0.7374, 2730.552, 1332.81, 2464.39 + 0.55, 27000.0, 0.8044, 4295.929, 1942.93, 2688.42 + 0.55, 27000.0, 0.8715, 6094.254, 2698.9, 2912.46 + 0.55, 27000.0, 0.9385, 7933.54, 3597.18, 3136.49 + 0.55, 30000.0, 0.0, 247.5077, 247.508, 0.0 + 0.55, 30000.0, 0.3921, -2118.373, -480.674, 1310.26 + 0.55, 30000.0, 0.4574, -1282.077, -176.184, 1528.64 + 0.55, 30000.0, 0.5227, -445.7816, 128.305, 1747.02 + 0.55, 30000.0, 0.5881, 390.5139, 432.795, 1965.4 + 0.55, 30000.0, 0.6534, 1226.81, 737.285, 2183.77 + 0.55, 30000.0, 0.7188, 2222.488, 1103.4, 2402.15 + 0.55, 30000.0, 0.7841, 3563.936, 1618.71, 2620.53 + 0.55, 30000.0, 0.8495, 5155.267, 2270.37, 2838.91 + 0.55, 30000.0, 0.9148, 6746.392, 3017.25, 3057.28 + 0.55, 30000.0, 0.9802, 8117.883, 3833.5, 3275.66 + 0.55, 33000.0, 0.0, 218.469, 218.469, 0.0 + 0.55, 33000.0, 0.3819, -2025.39, -521.596, 1276.33 + 0.55, 33000.0, 0.4456, -1287.775, -244.072, 1489.05 + 0.55, 33000.0, 0.5092, -550.1608, 33.4523, 1701.78 + 0.55, 33000.0, 0.5729, 187.4535, 310.977, 1914.5 + 0.55, 33000.0, 0.6365, 925.0675, 588.5, 2127.22 + 0.55, 33000.0, 0.7002, 1767.75, 902.962, 2339.94 + 0.55, 33000.0, 0.7638, 2915.099, 1335.45, 2552.66 + 0.55, 33000.0, 0.8275, 4290.627, 1883.24, 2765.39 + 0.55, 33000.0, 0.8911, 5717.436, 2522.86, 2978.11 + 0.55, 33000.0, 0.9548, 6820.063, 3167.66, 3190.83 + 0.55, 36000.0, 0.0, 192.1978, 192.198, 0.0 + 0.55, 36000.0, 0.3718, -2176.489, -572.192, 1242.4 + 0.55, 36000.0, 0.4337, -1492.523, -318.272, 1449.47 + 0.55, 36000.0, 0.4957, -808.5572, -64.3527, 1656.54 + 0.55, 36000.0, 0.5576, -124.5906, 189.567, 1863.6 + 0.55, 36000.0, 0.6196, 559.3754, 443.486, 2070.67 + 0.55, 36000.0, 0.6815, 1287.921, 707.994, 2277.74 + 0.55, 36000.0, 0.7435, 2201.737, 1047.83, 2484.81 + 0.55, 36000.0, 0.8055, 3296.743, 1498.94, 2691.87 + 0.55, 36000.0, 0.8674, 4770.691, 2073.66, 2898.94 + 0.55, 36000.0, 0.9294, 5655.613, 2640.56, 3106.01 + 0.55, 36000.0, 0.9913, 5650.372, 2701.63, 3313.08 + 0.55, 39000.0, 0.0, 166.5913, 166.591, 0.0 + 0.55, 39000.0, 0.3712, -1882.571, -495.702, 1240.69 + 0.55, 39000.0, 0.4331, -1336.267, -287.871, 1447.47 + 0.55, 39000.0, 0.495, -789.9644, -80.0411, 1654.25 + 0.55, 39000.0, 0.5569, -243.6606, 127.79, 1861.03 + 0.55, 39000.0, 0.6187, 302.6422, 335.62, 2067.82 + 0.55, 39000.0, 0.6806, 884.129, 552.329, 2274.6 + 0.55, 39000.0, 0.7425, 1713.054, 852.903, 2481.38 + 0.55, 39000.0, 0.8044, 2706.998, 1244.27, 2688.16 + 0.55, 39000.0, 0.8662, 3806.271, 1680.16, 2894.94 + 0.55, 39000.0, 0.9281, 4711.515, 2213.67, 3101.72 + 0.55, 39000.0, 0.99, 5502.907, 2746.28, 3308.51 + 0.55, 42000.0, 0.0, 144.3024, 144.302, 0.0 + 0.55, 42000.0, 0.3712, -13978.11, -5206.46, 1240.69 + 0.55, 42000.0, 0.4331, -10893.79, -4009.05, 1447.47 + 0.55, 42000.0, 0.495, -7809.47, -2811.63, 1654.25 + 0.55, 42000.0, 0.5569, -4725.154, -1614.22, 1861.03 + 0.55, 42000.0, 0.6187, -1640.835, -416.809, 2067.82 + 0.55, 42000.0, 0.6806, 298.8143, 327.924, 2274.6 + 0.55, 42000.0, 0.7425, 1402.126, 703.227, 2481.38 + 0.55, 42000.0, 0.8044, 1950.49, 996.746, 2688.16 + 0.55, 42000.0, 0.8662, 3358.422, 1598.04, 2894.94 + 0.55, 42000.0, 0.9281, 3801.777, 1835.52, 3101.72 + 0.55, 42000.0, 0.99, 5521.017, 2900.1, 3308.51 + 0.6, 0.0, 0.0, 765.607, 765.607, 0.0 + 0.6, 0.0, 0.4991, -6025.048, -79.0273, 1668.04 + 0.6, 0.0, 0.5823, -2465.723, 785.189, 1946.05 + 0.6, 0.0, 0.6655, 1093.608, 1649.41, 2224.06 + 0.6, 0.0, 0.7487, 4224.981, 2695.09, 2502.06 + 0.6, 0.0, 0.8319, 5101.51, 3943.21, 2780.07 + 0.6, 0.0, 0.915, 5674.103, 5576.64, 3058.08 + 0.6, 0.0, 0.9982, 13470.32, 8143.67, 3336.09 + 0.6, 3000.0, 0.0, 693.3678, 693.368, 0.0 + 0.6, 3000.0, 0.4888, -1032.888, 110.907, 1633.64 + 0.6, 3000.0, 0.5703, 229.059, 793.078, 1905.92 + 0.6, 3000.0, 0.6518, 1491.022, 1475.26, 2178.19 + 0.6, 3000.0, 0.7332, 3270.838, 2286.77, 2450.46 + 0.6, 3000.0, 0.8147, 7000.776, 3555.9, 2722.74 + 0.6, 3000.0, 0.8962, 9948.701, 5147.93, 2995.01 + 0.6, 3000.0, 0.9776, 11990.53, 7075.25, 3267.29 + 0.6, 6000.0, 0.0, 626.6399, 626.64, 0.0 + 0.6, 6000.0, 0.4785, -4189.777, -36.4088, 1599.25 + 0.6, 6000.0, 0.5583, -1838.029, 612.06, 1865.79 + 0.6, 6000.0, 0.638, 513.7294, 1260.53, 2132.33 + 0.6, 6000.0, 0.7178, 2868.472, 1990.49, 2398.87 + 0.6, 6000.0, 0.7976, 6031.481, 3062.55, 2665.42 + 0.6, 6000.0, 0.8773, 8447.503, 4371.18, 2931.96 + 0.6, 6000.0, 0.9571, 13176.49, 6561.29, 3198.5 + 0.6, 9000.0, 0.0, 565.1075, 565.107, 0.0 + 0.6, 9000.0, 0.4682, -1831.78, -110.909, 1564.87 + 0.6, 9000.0, 0.5463, -380.2262, 485.407, 1825.68 + 0.6, 9000.0, 0.6243, 1071.327, 1081.72, 2086.49 + 0.6, 9000.0, 0.7024, 2620.857, 1730.1, 2347.3 + 0.6, 9000.0, 0.7804, 4715.764, 2620.91, 2608.12 + 0.6, 9000.0, 0.8584, 7694.564, 3884.35, 2868.93 + 0.6, 9000.0, 0.9365, 11541.28, 5637.72, 3129.74 + 0.6, 12000.0, 0.0, 508.461, 508.461, 0.0 + 0.6, 12000.0, 0.458, -2192.806, -209.957, 1530.5 + 0.6, 12000.0, 0.5343, -752.0045, 343.538, 1785.58 + 0.6, 12000.0, 0.6106, 688.7975, 897.033, 2040.66 + 0.6, 12000.0, 0.6869, 2170.09, 1473.03, 2295.74 + 0.6, 12000.0, 0.7633, 4070.513, 2246.4, 2550.83 + 0.6, 12000.0, 0.8396, 6569.497, 3309.11, 2805.91 + 0.6, 12000.0, 0.9159, 9949.594, 4819.66, 3060.99 + 0.6, 12000.0, 0.9922, 13584.53, 6570.46, 3316.08 + 0.6, 15000.0, 0.0, 456.4112, 456.411, 0.0 + 0.6, 15000.0, 0.4477, -2117.791, -273.678, 1496.14 + 0.6, 15000.0, 0.5223, -822.6001, 231.111, 1745.49 + 0.6, 15000.0, 0.5969, 472.5904, 735.901, 1994.85 + 0.6, 15000.0, 0.6715, 1767.781, 1240.69, 2244.2 + 0.6, 15000.0, 0.7461, 3415.828, 1902.12, 2493.56 + 0.6, 15000.0, 0.8207, 5627.755, 2827.28, 2742.92 + 0.6, 15000.0, 0.8954, 8524.869, 4096.89, 2992.27 + 0.6, 15000.0, 0.97, 11754.32, 5646.49, 3241.63 + 0.6, 18000.0, 0.0, 408.677, 408.677, 0.0 + 0.6, 18000.0, 0.4374, -2177.576, -339.751, 1461.78 + 0.6, 18000.0, 0.5103, -974.9719, 123.709, 1705.41 + 0.6, 18000.0, 0.5832, 227.6324, 587.17, 1949.04 + 0.6, 18000.0, 0.6561, 1430.237, 1050.63, 2192.67 + 0.6, 18000.0, 0.729, 2848.307, 1611.5, 2436.3 + 0.6, 18000.0, 0.8019, 4781.004, 2399.85, 2679.93 + 0.6, 18000.0, 0.8748, 7288.045, 3480.61, 2923.56 + 0.6, 18000.0, 0.9477, 10104.97, 4808.75, 3167.2 + 0.6, 21000.0, 0.0, 364.9863, 364.986, 0.0 + 0.6, 21000.0, 0.4271, -2118.027, -375.902, 1427.44 + 0.6, 21000.0, 0.4983, -1031.512, 43.4419, 1665.35 + 0.6, 21000.0, 0.5695, 55.00157, 462.786, 1903.26 + 0.6, 21000.0, 0.6407, 1141.516, 882.13, 2141.16 + 0.6, 21000.0, 0.7119, 2346.907, 1355.14, 2379.07 + 0.6, 21000.0, 0.7831, 4019.284, 2022.04, 2616.98 + 0.6, 21000.0, 0.8542, 6202.804, 2945.76, 2854.88 + 0.6, 21000.0, 0.9254, 8634.537, 4064.84, 3092.79 + 0.6, 21000.0, 0.9966, 11324.82, 5443.8, 3330.7 + 0.6, 24000.0, 0.0, 325.0816, 325.082, 0.0 + 0.6, 24000.0, 0.4168, -1994.749, -371.503, 1393.11 + 0.6, 24000.0, 0.4863, -1033.282, -2.60934, 1625.29 + 0.6, 24000.0, 0.5558, -71.81536, 366.284, 1857.48 + 0.6, 24000.0, 0.6253, 889.6513, 735.178, 2089.66 + 0.6, 24000.0, 0.6947, 1932.715, 1137.06, 2321.85 + 0.6, 24000.0, 0.7642, 3352.635, 1693.83, 2554.03 + 0.6, 24000.0, 0.8337, 5214.156, 2466.32, 2786.22 + 0.6, 24000.0, 0.9032, 7321.433, 3415.31, 3018.4 + 0.6, 24000.0, 0.9726, 9475.582, 4543.18, 3250.59 + 0.6, 27000.0, 0.0, 288.7136, 288.714, 0.0 + 0.6, 27000.0, 0.4066, -1906.462, -382.469, 1358.79 + 0.6, 27000.0, 0.4743, -1048.818, -53.5226, 1585.25 + 0.6, 27000.0, 0.5421, -191.1747, 275.424, 1811.72 + 0.6, 27000.0, 0.6099, 666.4689, 604.37, 2038.18 + 0.6, 27000.0, 0.6776, 1540.753, 939.68, 2264.65 + 0.6, 27000.0, 0.7454, 2765.433, 1411.91, 2491.11 + 0.6, 27000.0, 0.8132, 4360.494, 2059.84, 2717.57 + 0.6, 27000.0, 0.8809, 6182.694, 2862.71, 2944.04 + 0.6, 27000.0, 0.9487, 8049.502, 3813.16, 3170.5 + 0.6, 30000.0, 0.0, 255.6472, 255.647, 0.0 + 0.6, 30000.0, 0.3963, -2060.813, -458.199, 1324.47 + 0.6, 30000.0, 0.4624, -1240.202, -148.828, 1545.22 + 0.6, 30000.0, 0.5284, -419.5912, 160.542, 1765.96 + 0.6, 30000.0, 0.5945, 401.0198, 469.913, 1986.71 + 0.6, 30000.0, 0.6605, 1221.631, 779.284, 2207.46 + 0.6, 30000.0, 0.7266, 2266.589, 1174.82, 2428.2 + 0.6, 30000.0, 0.7926, 3629.044, 1720.08, 2648.95 + 0.6, 30000.0, 0.8587, 5241.692, 2407.33, 2869.69 + 0.6, 30000.0, 0.9247, 6845.821, 3195.16, 3090.44 + 0.6, 30000.0, 0.9908, 8183.629, 4024.91, 3311.18 + 0.6, 33000.0, 0.0, 225.6536, 225.654, 0.0 + 0.6, 33000.0, 0.386, -2207.917, -528.719, 1290.17 + 0.6, 33000.0, 0.4504, -1426.233, -239.167, 1505.2 + 0.6, 33000.0, 0.5147, -644.5488, 50.3848, 1720.23 + 0.6, 33000.0, 0.5791, 137.1355, 339.937, 1935.26 + 0.6, 33000.0, 0.6434, 918.8198, 629.488, 2150.29 + 0.6, 33000.0, 0.7078, 1804.413, 959.936, 2365.32 + 0.6, 33000.0, 0.7721, 2945.699, 1407.77, 2580.34 + 0.6, 33000.0, 0.8364, 4351.858, 1992.41, 2795.37 + 0.6, 33000.0, 0.9008, 5802.171, 2673.61, 3010.4 + 0.6, 33000.0, 0.9651, 6968.664, 3383.48, 3225.43 + 0.6, 36000.0, 0.0, 198.5184, 198.518, 0.0 + 0.6, 36000.0, 0.3758, -2307.229, -575.336, 1255.88 + 0.6, 36000.0, 0.4384, -1590.295, -312.095, 1465.19 + 0.6, 36000.0, 0.501, -873.3605, -48.8532, 1674.5 + 0.6, 36000.0, 0.5637, -156.4261, 214.388, 1883.81 + 0.6, 36000.0, 0.6263, 560.5083, 477.63, 2093.13 + 0.6, 36000.0, 0.6889, 1321.844, 758.283, 2302.44 + 0.6, 36000.0, 0.7516, 2276.085, 1124.91, 2511.75 + 0.6, 36000.0, 0.8142, 3475.986, 1613.96, 2721.06 + 0.6, 36000.0, 0.8768, 4685.784, 2172.91, 2930.38 + 0.6, 36000.0, 0.9395, 5667.943, 2754.79, 3139.69 + 0.6, 39000.0, 0.0, 172.0698, 172.07, 0.0 + 0.6, 39000.0, 0.3753, -2002.492, -520.544, 1254.14 + 0.6, 39000.0, 0.4378, -1421.915, -299.193, 1463.17 + 0.6, 39000.0, 0.5004, -841.338, -77.8411, 1672.19 + 0.6, 39000.0, 0.5629, -260.7607, 143.51, 1881.22 + 0.6, 39000.0, 0.6254, 319.8165, 364.862, 2090.24 + 0.6, 39000.0, 0.688, 946.512, 602.756, 2299.26 + 0.6, 39000.0, 0.7505, 1775.498, 918.468, 2508.29 + 0.6, 39000.0, 0.8131, 2814.587, 1339.06, 2717.31 + 0.6, 39000.0, 0.8756, 3862.892, 1816.28, 2926.33 + 0.6, 39000.0, 0.9382, 4767.528, 2336.44, 3135.36 + 0.6, 42000.0, 0.0, 149.0479, 149.048, 0.0 + 0.6, 42000.0, 0.3753, -7912.093, -2875.07, 1254.14 + 0.6, 42000.0, 0.4378, -6127.017, -2174.44, 1463.17 + 0.6, 42000.0, 0.5004, -4341.94, -1473.82, 1672.19 + 0.6, 42000.0, 0.5629, -2556.865, -773.201, 1881.22 + 0.6, 42000.0, 0.6254, -771.7891, -72.5801, 2090.24 + 0.6, 42000.0, 0.688, 508.2581, 426.184, 2299.26 + 0.6, 42000.0, 0.7505, 1367.796, 743.832, 2508.29 + 0.6, 42000.0, 0.8131, 2147.865, 1082.34, 2717.31 + 0.6, 42000.0, 0.8756, 3218.841, 1564.92, 2926.33 + 0.6, 42000.0, 0.9382, 3964.538, 1977.89, 3135.36 + 0.65, 0.0, 0.0, 792.7024, 792.702, 0.0 + 0.65, 0.0, 0.5049, -8986.311, -205.033, 1687.49 + 0.65, 0.0, 0.5891, -4193.078, 754.115, 1968.74 + 0.65, 0.0, 0.6732, 600.1659, 1713.27, 2249.99 + 0.65, 0.0, 0.7574, 4169.051, 2856.64, 2531.24 + 0.65, 0.0, 0.8416, 3476.701, 4086.8, 2812.49 + 0.65, 0.0, 0.9257, 2286.099, 5657.08, 3093.74 + 0.65, 3000.0, 0.0, 717.9067, 717.907, 0.0 + 0.65, 3000.0, 0.4945, -425.4664, 180.535, 1652.69 + 0.65, 3000.0, 0.5769, 468.8011, 869.374, 1928.14 + 0.65, 3000.0, 0.6594, 1363.097, 1558.23, 2203.59 + 0.65, 3000.0, 0.7418, 3011.832, 2400.38, 2479.04 + 0.65, 3000.0, 0.8242, 7474.006, 3772.59, 2754.49 + 0.65, 3000.0, 0.9066, 9944.853, 5428.43, 3029.94 + 0.65, 3000.0, 0.989, 9336.357, 7113.89, 3305.38 + 0.65, 6000.0, 0.0, 648.8172, 648.817, 0.0 + 0.65, 6000.0, 0.4841, -6060.323, -9.804, 1617.9 + 0.65, 6000.0, 0.5648, -3115.974, 656.869, 1887.55 + 0.65, 6000.0, 0.6455, -171.6051, 1323.54, 2157.2 + 0.65, 6000.0, 0.7262, 2660.584, 2087.39, 2426.85 + 0.65, 6000.0, 0.8069, 6493.076, 3261.33, 2696.5 + 0.65, 6000.0, 0.8875, 7988.587, 4485.14, 2966.15 + 0.65, 6000.0, 0.9682, 13065.79, 6949.11, 3235.8 + 0.65, 9000.0, 0.0, 585.1071, 585.107, 0.0 + 0.65, 9000.0, 0.4737, -1700.503, -62.7174, 1583.12 + 0.65, 9000.0, 0.5527, -307.5, 544.904, 1846.97 + 0.65, 9000.0, 0.6316, 1085.502, 1152.52, 2110.82 + 0.65, 9000.0, 0.7106, 2605.491, 1830.8, 2374.68 + 0.65, 9000.0, 0.7895, 4721.693, 2773.71, 2638.53 + 0.65, 9000.0, 0.8685, 7806.447, 4126.7, 2902.38 + 0.65, 9000.0, 0.9474, 11671.7, 5978.0, 3166.23 + 0.65, 12000.0, 0.0, 526.4558, 526.456, 0.0 + 0.65, 12000.0, 0.4633, -2317.345, -180.203, 1548.34 + 0.65, 12000.0, 0.5405, -839.7218, 389.276, 1806.4 + 0.65, 12000.0, 0.6177, 637.9009, 958.755, 2064.46 + 0.65, 12000.0, 0.6949, 2175.166, 1566.52, 2322.51 + 0.65, 12000.0, 0.7722, 4118.99, 2385.53, 2580.57 + 0.65, 12000.0, 0.8494, 6640.069, 3503.66, 2838.63 + 0.65, 12000.0, 0.9266, 10127.74, 5124.89, 3096.69 + 0.65, 15000.0, 0.0, 472.5639, 472.564, 0.0 + 0.65, 15000.0, 0.4529, -2025.059, -233.983, 1513.58 + 0.65, 15000.0, 0.5284, -767.4877, 281.022, 1765.85 + 0.65, 15000.0, 0.6039, 490.0835, 796.027, 2018.11 + 0.65, 15000.0, 0.6793, 1767.719, 1320.28, 2270.37 + 0.65, 15000.0, 0.7548, 3444.229, 2021.05, 2522.64 + 0.65, 15000.0, 0.8303, 5711.725, 2999.72, 2774.9 + 0.65, 15000.0, 0.9058, 8684.402, 4357.78, 3027.16 + 0.65, 15000.0, 0.9813, 11932.07, 5975.33, 3279.43 + 0.65, 18000.0, 0.0, 423.1404, 423.14, 0.0 + 0.65, 18000.0, 0.4425, -2094.232, -304.124, 1478.83 + 0.65, 18000.0, 0.5162, -920.8063, 168.95, 1725.3 + 0.65, 18000.0, 0.59, 252.6191, 642.024, 1971.77 + 0.65, 18000.0, 0.6637, 1425.986, 1115.07, 2218.24 + 0.65, 18000.0, 0.7375, 2877.673, 1712.42, 2464.71 + 0.65, 18000.0, 0.8112, 4856.519, 2548.91, 2711.18 + 0.65, 18000.0, 0.885, 7428.133, 3703.35, 2957.66 + 0.65, 18000.0, 0.9587, 10309.9, 5113.86, 3204.13 + 0.65, 21000.0, 0.0, 377.9035, 377.903, 0.0 + 0.65, 21000.0, 0.4321, -2065.295, -357.489, 1444.09 + 0.65, 21000.0, 0.5041, -999.6529, 73.783, 1684.77 + 0.65, 21000.0, 0.5761, 65.98912, 505.055, 1925.45 + 0.65, 21000.0, 0.6482, 1131.631, 936.327, 2166.13 + 0.65, 21000.0, 0.7202, 2362.032, 1437.81, 2406.81 + 0.65, 21000.0, 0.7922, 4097.359, 2154.98, 2647.49 + 0.65, 21000.0, 0.8642, 6311.424, 3128.38, 2888.17 + 0.65, 21000.0, 0.9362, 8825.82, 4334.82, 3128.85 + 0.65, 24000.0, 0.0, 336.5865, 336.587, 0.0 + 0.65, 24000.0, 0.4217, -2059.025, -394.485, 1409.35 + 0.65, 24000.0, 0.492, -1079.369, -3.94181, 1644.24 + 0.65, 24000.0, 0.5623, -99.71391, 386.601, 1879.14 + 0.65, 24000.0, 0.6326, 879.9415, 777.144, 2114.03 + 0.65, 24000.0, 0.7028, 1947.246, 1206.79, 2348.92 + 0.65, 24000.0, 0.7731, 3399.062, 1798.55, 2583.81 + 0.65, 24000.0, 0.8434, 5318.819, 2624.81, 2818.7 + 0.65, 24000.0, 0.9137, 7475.729, 3634.96, 3053.6 + 0.65, 24000.0, 0.984, 9731.872, 4859.3, 3288.49 + 0.65, 27000.0, 0.0, 298.9314, 298.931, 0.0 + 0.65, 27000.0, 0.4113, -1946.702, -392.939, 1374.63 + 0.65, 27000.0, 0.4799, -1077.663, -48.0894, 1603.74 + 0.65, 27000.0, 0.5484, -208.6244, 296.76, 1832.84 + 0.65, 27000.0, 0.617, 660.4145, 641.61, 2061.95 + 0.65, 27000.0, 0.6855, 1572.268, 1004.11, 2291.05 + 0.65, 27000.0, 0.7541, 2814.368, 1502.57, 2520.16 + 0.65, 27000.0, 0.8226, 4457.272, 2196.26, 2749.26 + 0.65, 27000.0, 0.8912, 6322.386, 3048.42, 2978.37 + 0.65, 27000.0, 0.9597, 8214.633, 4057.23, 3207.47 + 0.65, 30000.0, 0.0, 264.6947, 264.695, 0.0 + 0.65, 30000.0, 0.4009, -1969.638, -427.104, 1339.92 + 0.65, 30000.0, 0.4678, -1168.301, -113.45, 1563.24 + 0.65, 30000.0, 0.5346, -366.9648, 200.204, 1786.56 + 0.65, 30000.0, 0.6014, 434.372, 513.858, 2009.88 + 0.65, 30000.0, 0.6682, 1235.709, 827.513, 2233.2 + 0.65, 30000.0, 0.735, 2307.669, 1251.41, 2456.51 + 0.65, 30000.0, 0.8019, 3709.448, 1830.67, 2679.83 + 0.65, 30000.0, 0.8687, 5346.76, 2555.4, 2903.15 + 0.65, 30000.0, 0.9355, 6983.832, 3403.71, 3126.47 + 0.65, 33000.0, 0.0, 233.6397, 233.64, 0.0 + 0.65, 33000.0, 0.3905, -2121.918, -501.369, 1305.22 + 0.65, 33000.0, 0.4556, -1356.052, -207.534, 1522.75 + 0.65, 33000.0, 0.5207, -590.1845, 86.3018, 1740.29 + 0.65, 33000.0, 0.5858, 175.6825, 380.137, 1957.82 + 0.65, 33000.0, 0.6509, 941.5496, 673.973, 2175.36 + 0.65, 33000.0, 0.716, 1839.79, 1021.96, 2392.9 + 0.65, 33000.0, 0.7811, 3021.927, 1502.87, 2610.43 + 0.65, 33000.0, 0.8462, 4453.76, 2121.98, 2827.97 + 0.65, 33000.0, 0.9113, 5883.972, 2828.67, 3045.5 + 0.65, 33000.0, 0.9764, 7093.746, 3594.09, 3263.04 + 0.65, 36000.0, 0.0, 205.5441, 205.544, 0.0 + 0.65, 36000.0, 0.3802, -2204.349, -551.794, 1270.52 + 0.65, 36000.0, 0.4435, -1503.351, -283.878, 1482.27 + 0.65, 36000.0, 0.5069, -802.353, -15.9616, 1694.03 + 0.65, 36000.0, 0.5703, -101.355, 251.955, 1905.78 + 0.65, 36000.0, 0.6336, 599.6431, 519.871, 2117.53 + 0.65, 36000.0, 0.697, 1363.042, 813.606, 2329.29 + 0.65, 36000.0, 0.7603, 2351.876, 1206.55, 2541.04 + 0.65, 36000.0, 0.8237, 3571.965, 1724.72, 2752.79 + 0.65, 36000.0, 0.8871, 4769.538, 2315.92, 2964.55 + 0.65, 36000.0, 0.9504, 5753.311, 2911.55, 3176.3 + 0.65, 39000.0, 0.0, 178.1594, 178.159, 0.0 + 0.65, 39000.0, 0.3796, -2079.642, -541.299, 1268.77 + 0.65, 39000.0, 0.4429, -1475.562, -306.838, 1480.23 + 0.65, 39000.0, 0.5062, -871.4808, -72.3771, 1691.69 + 0.65, 39000.0, 0.5695, -267.4001, 162.083, 1903.15 + 0.65, 39000.0, 0.6327, 336.6807, 396.544, 2114.61 + 0.65, 39000.0, 0.696, 995.0392, 653.163, 2326.07 + 0.65, 39000.0, 0.7593, 1838.354, 987.882, 2537.53 + 0.65, 39000.0, 0.8226, 2900.054, 1433.43, 2749.0 + 0.65, 39000.0, 0.8858, 3944.936, 1941.32, 2960.46 + 0.65, 39000.0, 0.9491, 4862.986, 2483.77, 3171.92 + 0.65, 42000.0, 0.0, 154.3229, 154.323, 0.0 + 0.65, 42000.0, 0.3796, -4454.835, -1543.57, 1268.77 + 0.65, 42000.0, 0.4429, -3405.792, -1122.11, 1480.23 + 0.65, 42000.0, 0.5062, -2356.75, -700.654, 1691.69 + 0.65, 42000.0, 0.5695, -1307.707, -279.194, 1903.15 + 0.65, 42000.0, 0.6327, -258.6648, 142.266, 2114.61 + 0.65, 42000.0, 0.696, 630.2994, 496.732, 2326.07 + 0.65, 42000.0, 0.7593, 1385.454, 795.06, 2537.53 + 0.65, 42000.0, 0.8226, 2283.647, 1171.3, 2749.0 + 0.65, 42000.0, 0.8858, 3208.841, 1610.98, 2960.46 + 0.65, 42000.0, 0.9491, 4068.182, 2103.59, 3171.92 + 0.7, 0.0, 0.0, 822.6755, 822.675, 0.0 + 0.7, 0.0, 0.5112, -13019.3, -390.548, 1708.5 + 0.7, 0.0, 0.5964, -6521.001, 693.509, 1993.25 + 0.7, 0.0, 0.6816, -22.6841, 1777.57, 2278.0 + 0.7, 0.0, 0.7668, 4125.025, 3038.26, 2562.75 + 0.7, 0.0, 0.852, 1281.169, 4223.06, 2847.5 + 0.7, 0.0, 0.9372, -2232.395, 5678.89, 3132.25 + 0.7, 3000.0, 0.0, 745.0516, 745.052, 0.0 + 0.7, 3000.0, 0.5007, 436.9774, 263.613, 1673.26 + 0.7, 3000.0, 0.5841, 824.2919, 956.896, 1952.14 + 0.7, 3000.0, 0.6676, 1211.653, 1650.2, 2231.02 + 0.7, 3000.0, 0.751, 2681.25, 2523.87, 2509.9 + 0.7, 3000.0, 0.8345, 8163.986, 4014.35, 2788.77 + 0.7, 3000.0, 0.9179, 9956.331, 5737.11, 3067.65 + 0.7, 6000.0, 0.0, 673.3498, 673.35, 0.0 + 0.7, 6000.0, 0.4901, -8741.09, 13.4989, 1638.04 + 0.7, 6000.0, 0.5718, -4938.687, 700.629, 1911.04 + 0.7, 6000.0, 0.6535, -1136.252, 1387.76, 2184.05 + 0.7, 6000.0, 0.7352, 2378.518, 2188.95, 2457.06 + 0.7, 6000.0, 0.8169, 7181.36, 3493.27, 2730.06 + 0.7, 6000.0, 0.8986, 7254.113, 4549.24, 3003.07 + 0.7, 6000.0, 0.9803, 12777.58, 7363.21, 3276.08 + 0.7, 9000.0, 0.0, 607.2307, 607.231, 0.0 + 0.7, 9000.0, 0.4796, -1599.879, -12.7746, 1602.82 + 0.7, 9000.0, 0.5595, -259.4922, 607.376, 1869.96 + 0.7, 9000.0, 0.6395, 1080.893, 1227.53, 2137.1 + 0.7, 9000.0, 0.7194, 2583.088, 1940.97, 2404.24 + 0.7, 9000.0, 0.7993, 4765.228, 2946.9, 2671.37 + 0.7, 9000.0, 0.8793, 7974.032, 4402.92, 2938.51 + 0.7, 9000.0, 0.9592, 11801.1, 6348.06, 3205.65 + 0.7, 12000.0, 0.0, 546.3618, 546.362, 0.0 + 0.7, 12000.0, 0.4691, -2415.962, -145.155, 1567.62 + 0.7, 12000.0, 0.5472, -907.3567, 440.614, 1828.89 + 0.7, 12000.0, 0.6254, 601.2488, 1026.38, 2090.16 + 0.7, 12000.0, 0.7036, 2181.371, 1667.08, 2351.42 + 0.7, 12000.0, 0.7818, 4172.978, 2537.5, 2612.69 + 0.7, 12000.0, 0.86, 6741.132, 3726.98, 2873.96 + 0.7, 12000.0, 0.9381, 10353.41, 5465.79, 3135.23 + 0.7, 15000.0, 0.0, 490.4322, 490.432, 0.0 + 0.7, 15000.0, 0.4585, -1946.595, -191.273, 1532.42 + 0.7, 15000.0, 0.535, -723.9525, 334.604, 1787.83 + 0.7, 15000.0, 0.6114, 498.69, 860.482, 2043.23 + 0.7, 15000.0, 0.6878, 1775.418, 1410.19, 2298.63 + 0.7, 15000.0, 0.7642, 3490.863, 2154.94, 2554.04 + 0.7, 15000.0, 0.8406, 5818.841, 3191.66, 2809.44 + 0.7, 15000.0, 0.9171, 8894.5, 4655.32, 3064.85 + 0.7, 15000.0, 0.9935, 12116.06, 6324.15, 3320.25 + 0.7, 18000.0, 0.0, 439.1399, 439.14, 0.0 + 0.7, 18000.0, 0.448, -2026.14, -266.43, 1497.24 + 0.7, 18000.0, 0.5227, -873.2838, 217.862, 1746.78 + 0.7, 18000.0, 0.5973, 279.5726, 702.153, 1996.31 + 0.7, 18000.0, 0.672, 1431.716, 1186.15, 2245.85 + 0.7, 18000.0, 0.7467, 2919.174, 1822.11, 2495.39 + 0.7, 18000.0, 0.8213, 4970.509, 2721.65, 2744.93 + 0.7, 18000.0, 0.896, 7601.834, 3947.16, 2994.47 + 0.7, 18000.0, 0.9707, 10552.04, 5448.53, 3244.01 + 0.7, 21000.0, 0.0, 392.1925, 392.192, 0.0 + 0.7, 21000.0, 0.4375, -2058.55, -335.007, 1462.06 + 0.7, 21000.0, 0.5104, -994.0279, 109.717, 1705.74 + 0.7, 21000.0, 0.5833, 70.49416, 554.441, 1949.42 + 0.7, 21000.0, 0.6562, 1135.016, 999.165, 2193.09 + 0.7, 21000.0, 0.7291, 2418.25, 1537.63, 2436.77 + 0.7, 21000.0, 0.802, 4185.786, 2297.99, 2680.45 + 0.7, 21000.0, 0.875, 6471.901, 3341.84, 2924.13 + 0.7, 21000.0, 0.9479, 9049.597, 4628.78, 3167.8 + 0.7, 24000.0, 0.0, 349.3132, 349.313, 0.0 + 0.7, 24000.0, 0.427, -2117.806, -396.037, 1426.9 + 0.7, 24000.0, 0.4981, -1121.716, 11.9713, 1664.71 + 0.7, 24000.0, 0.5693, -125.6263, 419.98, 1902.53 + 0.7, 24000.0, 0.6404, 870.4636, 827.988, 2140.34 + 0.7, 24000.0, 0.7116, 1967.761, 1282.78, 2378.16 + 0.7, 24000.0, 0.7828, 3469.587, 1919.64, 2615.98 + 0.7, 24000.0, 0.8539, 5457.373, 2804.85, 2853.79 + 0.7, 24000.0, 0.9251, 7676.848, 3882.26, 3091.61 + 0.7, 24000.0, 0.9962, 10022.14, 5202.33, 3329.42 + 0.7, 27000.0, 0.0, 310.2344, 310.234, 0.0 + 0.7, 27000.0, 0.4164, -2030.503, -415.977, 1391.74 + 0.7, 27000.0, 0.4858, -1136.723, -50.1449, 1623.7 + 0.7, 27000.0, 0.5553, -242.9425, 315.687, 1855.66 + 0.7, 27000.0, 0.6247, 650.8375, 681.519, 2087.61 + 0.7, 27000.0, 0.6941, 1604.376, 1073.51, 2319.57 + 0.7, 27000.0, 0.7635, 2876.444, 1604.94, 2551.53 + 0.7, 27000.0, 0.8329, 4577.72, 2346.91, 2783.49 + 0.7, 27000.0, 0.9023, 6499.508, 3256.31, 3015.44 + 0.7, 27000.0, 0.9717, 8408.643, 4327.12, 3247.4 + 0.7, 30000.0, 0.0, 274.7032, 274.703, 0.0 + 0.7, 30000.0, 0.4059, -1848.193, -395.159, 1356.6 + 0.7, 30000.0, 0.4736, -1073.736, -76.5637, 1582.7 + 0.7, 30000.0, 0.5412, -299.2792, 242.031, 1808.8 + 0.7, 30000.0, 0.6089, 475.1775, 560.626, 2034.89 + 0.7, 30000.0, 0.6765, 1260.957, 883.758, 2260.99 + 0.7, 30000.0, 0.7442, 2355.854, 1334.38, 2487.09 + 0.7, 30000.0, 0.8118, 3815.43, 1956.47, 2713.19 + 0.7, 30000.0, 0.8795, 5479.653, 2727.06, 2939.29 + 0.7, 30000.0, 0.9472, 7139.989, 3630.67, 3165.39 + 0.7, 33000.0, 0.0, 242.4738, 242.474, 0.0 + 0.7, 33000.0, 0.3954, -1961.491, -461.162, 1321.46 + 0.7, 33000.0, 0.4613, -1228.508, -165.405, 1541.71 + 0.7, 33000.0, 0.5272, -495.5246, 130.352, 1761.95 + 0.7, 33000.0, 0.5931, 237.4587, 426.11, 1982.2 + 0.7, 33000.0, 0.659, 970.442, 721.867, 2202.44 + 0.7, 33000.0, 0.7249, 1889.083, 1093.77, 2422.68 + 0.7, 33000.0, 0.7908, 3121.536, 1611.63, 2642.93 + 0.7, 33000.0, 0.8567, 4583.719, 2265.9, 2863.17 + 0.7, 33000.0, 0.9226, 6002.153, 3007.51, 3083.41 + 0.7, 33000.0, 0.9885, 7187.438, 3789.2, 3303.66 + 0.7, 36000.0, 0.0, 213.316, 213.316, 0.0 + 0.7, 36000.0, 0.3849, -2059.227, -519.138, 1286.34 + 0.7, 36000.0, 0.449, -1382.758, -247.76, 1500.72 + 0.7, 36000.0, 0.5132, -706.2883, 23.6176, 1715.11 + 0.7, 36000.0, 0.5773, -29.8187, 294.995, 1929.5 + 0.7, 36000.0, 0.6415, 646.6509, 566.373, 2143.89 + 0.7, 36000.0, 0.7056, 1411.186, 873.889, 2358.28 + 0.7, 36000.0, 0.7698, 2431.102, 1294.17, 2572.67 + 0.7, 36000.0, 0.8339, 3647.292, 1841.75, 2787.06 + 0.7, 36000.0, 0.8981, 4915.922, 2478.61, 3001.45 + 0.7, 36000.0, 0.9622, 5891.732, 3106.17, 3215.84 + 0.7, 39000.0, 0.0, 184.8959, 184.896, 0.0 + 0.7, 39000.0, 0.3844, -2107.787, -558.149, 1284.56 + 0.7, 39000.0, 0.4484, -1490.268, -310.447, 1498.65 + 0.7, 39000.0, 0.5125, -872.7485, -62.7454, 1712.75 + 0.7, 39000.0, 0.5766, -255.2291, 184.957, 1926.84 + 0.7, 39000.0, 0.6406, 362.2903, 432.659, 2140.94 + 0.7, 39000.0, 0.7047, 1041.874, 706.05, 2355.03 + 0.7, 39000.0, 0.7687, 1906.003, 1062.53, 2569.12 + 0.7, 39000.0, 0.8328, 2980.816, 1534.98, 2783.22 + 0.7, 39000.0, 0.8969, 4045.225, 2068.5, 2997.31 + 0.7, 39000.0, 0.9609, 4979.738, 2649.13, 3211.4 + 0.7, 42000.0, 0.0, 160.158, 160.158, 0.0 + 0.7, 42000.0, 0.3844, -2873.663, -928.134, 1284.56 + 0.7, 42000.0, 0.4484, -2154.867, -629.813, 1498.65 + 0.7, 42000.0, 0.5125, -1436.07, -331.492, 1712.75 + 0.7, 42000.0, 0.5766, -717.2734, -33.1706, 1926.84 + 0.7, 42000.0, 0.6406, 1.523225, 265.151, 2140.94 + 0.7, 42000.0, 0.7047, 698.9133, 551.226, 2355.03 + 0.7, 42000.0, 0.7687, 1440.744, 856.968, 2569.12 + 0.7, 42000.0, 0.8328, 2383.673, 1265.34, 2783.22 + 0.7, 42000.0, 0.8969, 3287.898, 1712.85, 2997.31 + 0.7, 42000.0, 0.9609, 4146.565, 2227.31, 3211.4 + 0.75, 0.0, 0.0, 855.7001, 855.7, 0.0 + 0.75, 0.0, 0.518, -18285.48, -645.148, 1731.06 + 0.75, 0.0, 0.6043, -9540.395, 598.183, 2019.57 + 0.75, 0.0, 0.6906, -795.2881, 1841.53, 2308.08 + 0.75, 0.0, 0.777, 4091.46, 3241.31, 2596.59 + 0.75, 0.0, 0.8633, -1575.097, 4348.57, 2885.1 + 0.75, 0.0, 0.9496, -8051.193, 5629.76, 3173.61 + 0.75, 3000.0, 0.0, 774.9602, 774.96, 0.0 + 0.75, 3000.0, 0.5073, 1601.555, 361.889, 1695.36 + 0.75, 3000.0, 0.5918, 1316.418, 1056.84, 1977.92 + 0.75, 3000.0, 0.6764, 1031.352, 1751.83, 2260.48 + 0.75, 3000.0, 0.7609, 2263.85, 2657.52, 2543.04 + 0.75, 3000.0, 0.8455, 9103.999, 4282.68, 2825.6 + 0.75, 3000.0, 0.93, 9983.064, 6075.91, 3108.16 + 0.75, 6000.0, 0.0, 700.38, 700.38, 0.0 + 0.75, 6000.0, 0.4966, -12371.05, 32.397, 1659.67 + 0.75, 6000.0, 0.5794, -7401.03, 742.393, 1936.28 + 0.75, 6000.0, 0.6621, -2430.955, 1452.39, 2212.89 + 0.75, 6000.0, 0.7449, 2004.867, 2294.51, 2489.5 + 0.75, 6000.0, 0.8277, 8134.424, 3762.57, 2766.12 + 0.75, 6000.0, 0.9105, 6181.667, 4549.81, 3042.73 + 0.75, 6000.0, 0.9932, 12260.31, 7801.61, 3319.34 + 0.75, 9000.0, 0.0, 631.6067, 631.607, 0.0 + 0.75, 9000.0, 0.4859, -1552.742, 37.2315, 1623.99 + 0.75, 9000.0, 0.5669, -254.5568, 671.556, 1894.66 + 0.75, 9000.0, 0.6479, 1043.628, 1305.88, 2165.32 + 0.75, 9000.0, 0.7289, 2545.739, 2060.82, 2435.99 + 0.75, 9000.0, 0.8099, 4856.654, 3143.32, 2706.65 + 0.75, 9000.0, 0.8909, 8208.843, 4716.95, 2977.32 + 0.75, 9000.0, 0.9719, 11922.29, 6747.96, 3247.98 + 0.75, 12000.0, 0.0, 568.2944, 568.294, 0.0 + 0.75, 12000.0, 0.4753, -2414.211, -100.711, 1588.32 + 0.75, 12000.0, 0.5545, -906.1499, 500.189, 1853.04 + 0.75, 12000.0, 0.6337, 601.911, 1101.09, 2117.76 + 0.75, 12000.0, 0.7129, 2180.21, 1772.41, 2382.48 + 0.75, 12000.0, 0.7921, 4219.625, 2700.87, 2647.2 + 0.75, 12000.0, 0.8713, 6873.043, 3985.03, 2911.92 + 0.75, 12000.0, 0.9505, 10623.51, 5843.06, 3176.64 + 0.75, 15000.0, 0.0, 510.1196, 510.12, 0.0 + 0.75, 15000.0, 0.4646, -1862.805, -144.792, 1552.66 + 0.75, 15000.0, 0.542, -676.7411, 392.51, 1811.44 + 0.75, 15000.0, 0.6195, 509.3225, 929.812, 2070.21 + 0.75, 15000.0, 0.6969, 1791.346, 1506.92, 2328.99 + 0.75, 15000.0, 0.7743, 3558.124, 2301.52, 2587.77 + 0.75, 15000.0, 0.8517, 5947.896, 3408.16, 2846.54 + 0.75, 15000.0, 0.9292, 9145.538, 4988.9, 3105.32 + 0.75, 18000.0, 0.0, 456.7683, 456.768, 0.0 + 0.75, 18000.0, 0.4539, -1895.056, -217.852, 1517.01 + 0.75, 18000.0, 0.5296, -787.581, 273.878, 1769.84 + 0.75, 18000.0, 0.6052, 319.894, 765.607, 2022.68 + 0.75, 18000.0, 0.6809, 1455.508, 1269.39, 2275.51 + 0.75, 18000.0, 0.7565, 2998.64, 1952.17, 2528.35 + 0.75, 18000.0, 0.8322, 5096.756, 2906.12, 2781.18 + 0.75, 18000.0, 0.9078, 7828.234, 4228.11, 3034.02 + 0.75, 18000.0, 0.9835, 10768.63, 5803.71, 3286.85 + 0.75, 21000.0, 0.0, 407.9362, 407.936, 0.0 + 0.75, 21000.0, 0.4433, -1994.686, -302.54, 1481.37 + 0.75, 21000.0, 0.5171, -942.6489, 155.04, 1728.27 + 0.75, 21000.0, 0.591, 109.3881, 612.62, 1975.16 + 0.75, 21000.0, 0.6649, 1161.015, 1070.01, 2222.06 + 0.75, 21000.0, 0.7388, 2485.165, 1647.03, 2468.95 + 0.75, 21000.0, 0.8126, 4301.394, 2459.98, 2715.85 + 0.75, 21000.0, 0.8865, 6674.529, 3580.08, 2962.74 + 0.75, 21000.0, 0.9604, 9300.84, 4949.79, 3209.64 + 0.75, 24000.0, 0.0, 363.3357, 363.336, 0.0 + 0.75, 24000.0, 0.4326, -2007.583, -361.605, 1445.74 + 0.75, 24000.0, 0.5047, -1039.137, 55.6593, 1686.7 + 0.75, 24000.0, 0.5768, -70.6904, 472.924, 1927.65 + 0.75, 24000.0, 0.6489, 897.756, 890.189, 2168.61 + 0.75, 24000.0, 0.721, 2011.304, 1370.68, 2409.57 + 0.75, 24000.0, 0.7931, 3583.664, 2062.37, 2650.52 + 0.75, 24000.0, 0.8652, 5630.15, 3003.04, 2891.48 + 0.75, 24000.0, 0.9373, 7910.879, 4166.89, 3132.44 + 0.75, 27000.0, 0.0, 322.6881, 322.688, 0.0 + 0.75, 27000.0, 0.4219, -2119.097, -419.21, 1410.12 + 0.75, 27000.0, 0.4923, -1195.703, -35.7285, 1645.14 + 0.75, 27000.0, 0.5626, -272.3093, 347.753, 1880.16 + 0.75, 27000.0, 0.6329, 651.0844, 731.234, 2115.18 + 0.75, 27000.0, 0.7032, 1645.589, 1148.99, 2350.2 + 0.75, 27000.0, 0.7736, 2951.862, 1717.38, 2585.22 + 0.75, 27000.0, 0.8439, 4733.928, 2516.59, 2820.24 + 0.75, 27000.0, 0.9142, 6696.335, 3488.72, 3055.26 + 0.75, 27000.0, 0.9845, 8694.841, 4653.55, 3290.28 + 0.75, 30000.0, 0.0, 285.7306, 285.731, 0.0 + 0.75, 30000.0, 0.4113, -2108.32, -445.441, 1374.51 + 0.75, 30000.0, 0.4798, -1261.581, -99.4672, 1603.6 + 0.75, 30000.0, 0.5484, -414.8423, 246.507, 1832.68 + 0.75, 30000.0, 0.6169, 431.8966, 592.481, 2061.77 + 0.75, 30000.0, 0.6855, 1309.397, 953.047, 2290.85 + 0.75, 30000.0, 0.754, 2431.752, 1431.94, 2519.94 + 0.75, 30000.0, 0.8226, 3950.679, 2101.51, 2749.02 + 0.75, 30000.0, 0.8911, 5654.978, 2922.05, 2978.11 + 0.75, 30000.0, 0.9597, 7341.822, 3889.14, 3207.19 + 0.75, 33000.0, 0.0, 252.2075, 252.207, 0.0 + 0.75, 33000.0, 0.4006, -1946.436, -443.246, 1338.91 + 0.75, 33000.0, 0.4674, -1210.797, -139.157, 1562.07 + 0.75, 33000.0, 0.5342, -475.1593, 164.933, 1785.22 + 0.75, 33000.0, 0.6009, 260.4789, 469.022, 2008.37 + 0.75, 33000.0, 0.6677, 994.9746, 772.583, 2231.52 + 0.75, 33000.0, 0.7345, 1955.364, 1175.6, 2454.68 + 0.75, 33000.0, 0.8013, 3233.56, 1728.09, 2677.83 + 0.75, 33000.0, 0.868, 4721.14, 2421.34, 2900.98 + 0.75, 33000.0, 0.9348, 6164.251, 3219.2, 3124.13 + 0.75, 36000.0, 0.0, 221.8791, 221.879, 0.0 + 0.75, 36000.0, 0.39, -2063.243, -494.938, 1303.32 + 0.75, 36000.0, 0.455, -1379.581, -217.879, 1520.54 + 0.75, 36000.0, 0.52, -695.92, 59.1799, 1737.76 + 0.75, 36000.0, 0.585, -12.2586, 336.239, 1954.98 + 0.75, 36000.0, 0.65, 671.4028, 613.298, 2172.2 + 0.75, 36000.0, 0.715, 1465.948, 939.054, 2389.42 + 0.75, 36000.0, 0.78, 2515.761, 1389.19, 2606.65 + 0.75, 36000.0, 0.845, 3764.579, 1975.59, 2823.87 + 0.75, 36000.0, 0.91, 5018.906, 2636.88, 3041.09 + 0.75, 36000.0, 0.975, 6063.22, 3334.02, 3258.31 + 0.75, 39000.0, 0.0, 192.3181, 192.318, 0.0 + 0.75, 39000.0, 0.3894, -2080.694, -571.283, 1301.52 + 0.75, 39000.0, 0.4544, -1459.096, -309.662, 1518.45 + 0.75, 39000.0, 0.5193, -837.4968, -48.0423, 1735.37 + 0.75, 39000.0, 0.5842, -215.898, 213.578, 1952.29 + 0.75, 39000.0, 0.6491, 405.7008, 475.198, 2169.21 + 0.75, 39000.0, 0.714, 1099.182, 763.919, 2386.13 + 0.75, 39000.0, 0.7789, 1982.829, 1143.8, 2603.05 + 0.75, 39000.0, 0.8438, 3074.288, 1651.36, 2819.97 + 0.75, 39000.0, 0.9087, 4156.585, 2211.04, 3036.89 + 0.75, 39000.0, 0.9736, 5099.632, 2826.01, 3253.81 + 0.75, 42000.0, 0.0, 166.5872, 166.587, 0.0 + 0.75, 42000.0, 0.3894, -2435.906, -744.892, 1301.52 + 0.75, 42000.0, 0.4544, -1798.99, -475.296, 1518.45 + 0.75, 42000.0, 0.5193, -1162.073, -205.699, 1735.37 + 0.75, 42000.0, 0.5842, -525.1564, 63.8979, 1952.29 + 0.75, 42000.0, 0.6491, 111.7602, 333.495, 2169.21 + 0.75, 42000.0, 0.714, 748.0754, 601.326, 2386.13 + 0.75, 42000.0, 0.7789, 1519.307, 929.611, 2603.05 + 0.75, 42000.0, 0.8438, 2473.778, 1366.22, 2819.97 + 0.75, 42000.0, 0.9087, 3415.488, 1847.12, 3036.89 + 0.75, 42000.0, 0.9736, 4233.546, 2363.74, 3253.81 + 0.8, 0.0, 0.0, 891.9671, 891.967, 0.0 + 0.8, 0.0, 0.5252, -24946.3, -978.409, 1755.18 + 0.8, 0.0, 0.6127, -13342.16, 462.951, 2047.71 + 0.8, 0.0, 0.7003, -1737.992, 1904.33, 2340.24 + 0.8, 0.0, 0.7878, 4066.913, 3467.18, 2632.77 + 0.8, 0.0, 0.8753, -5182.105, 4459.94, 2925.3 + 0.8, 0.0, 0.9628, -15340.11, 5497.34, 3217.83 + 0.8, 3000.0, 0.0, 807.8052, 807.805, 0.0 + 0.8, 3000.0, 0.5144, 3115.377, 477.11, 1718.98 + 0.8, 3000.0, 0.6001, 1966.067, 1170.41, 2005.48 + 0.8, 3000.0, 0.6858, 816.8579, 1863.76, 2291.98 + 0.8, 3000.0, 0.7715, 1744.392, 2801.64, 2578.47 + 0.8, 3000.0, 0.8573, 10327.33, 4579.07, 2864.97 + 0.8, 3000.0, 0.943, 10024.98, 6446.77, 3151.47 + 0.8, 6000.0, 0.0, 730.0641, 730.064, 0.0 + 0.8, 6000.0, 0.5035, -17089.19, 45.7874, 1682.79 + 0.8, 6000.0, 0.5875, -10597.86, 781.213, 1963.26 + 0.8, 6000.0, 0.6714, -4106.457, 1516.64, 2243.72 + 0.8, 6000.0, 0.7553, 1522.221, 2403.42, 2524.19 + 0.8, 6000.0, 0.8392, 9390.359, 4073.43, 2804.65 + 0.8, 6000.0, 0.9231, 4708.833, 4473.19, 3085.12 + 0.8, 9000.0, 0.0, 658.376, 658.376, 0.0 + 0.8, 9000.0, 0.4927, -1581.926, 85.6132, 1646.62 + 0.8, 9000.0, 0.5748, -311.0476, 736.173, 1921.05 + 0.8, 9000.0, 0.6569, 959.8308, 1386.73, 2195.49 + 0.8, 9000.0, 0.7391, 2485.536, 2190.62, 2469.92 + 0.8, 9000.0, 0.8212, 5006.256, 3365.85, 2744.36 + 0.8, 9000.0, 0.9033, 8522.402, 5072.75, 3018.8 + 0.8, 9000.0, 0.9854, 12028.08, 7177.72, 3293.23 + 0.8, 12000.0, 0.0, 592.3803, 592.38, 0.0 + 0.8, 12000.0, 0.4819, -2237.642, -42.7688, 1610.45 + 0.8, 12000.0, 0.5622, -787.3421, 570.638, 1878.86 + 0.8, 12000.0, 0.6425, 662.9575, 1184.04, 2147.26 + 0.8, 12000.0, 0.7228, 2163.187, 1880.23, 2415.67 + 0.8, 12000.0, 0.8031, 4246.081, 2874.18, 2684.08 + 0.8, 12000.0, 0.8834, 7036.158, 4283.76, 2952.49 + 0.8, 12000.0, 0.9638, 10934.91, 6257.37, 3220.9 + 0.8, 15000.0, 0.0, 531.7399, 531.74, 0.0 + 0.8, 15000.0, 0.4711, -1754.094, -93.783, 1574.29 + 0.8, 15000.0, 0.5496, -610.5999, 455.39, 1836.67 + 0.8, 15000.0, 0.6281, 532.8938, 1004.56, 2099.06 + 0.8, 15000.0, 0.7066, 1815.967, 1607.01, 2361.44 + 0.8, 15000.0, 0.7851, 3648.407, 2458.47, 2623.82 + 0.8, 15000.0, 0.8636, 6097.684, 3654.26, 2886.2 + 0.8, 15000.0, 0.9421, 9427.891, 5357.97, 3148.58 + 0.8, 18000.0, 0.0, 476.1274, 476.127, 0.0 + 0.8, 18000.0, 0.4602, -1752.155, -164.554, 1538.14 + 0.8, 18000.0, 0.537, -697.4081, 333.936, 1794.5 + 0.8, 18000.0, 0.6137, 357.3382, 832.425, 2050.86 + 0.8, 18000.0, 0.6904, 1487.066, 1362.3, 2307.22 + 0.8, 18000.0, 0.7671, 3076.799, 2090.86, 2563.57 + 0.8, 18000.0, 0.8438, 5257.202, 3116.57, 2819.93 + 0.8, 18000.0, 0.9205, 8079.039, 4535.61, 3076.29 + 0.8, 18000.0, 0.9972, 11682.75, 6187.11, 3332.65 + 0.8, 21000.0, 0.0, 425.2257, 425.226, 0.0 + 0.8, 21000.0, 0.4494, -1936.362, -261.007, 1502.01 + 0.8, 21000.0, 0.5243, -895.9699, 206.994, 1752.34 + 0.8, 21000.0, 0.5992, 144.4224, 674.995, 2002.68 + 0.8, 21000.0, 0.6742, 1190.551, 1145.69, 2253.01 + 0.8, 21000.0, 0.7491, 2572.761, 1768.72, 2503.35 + 0.8, 21000.0, 0.824, 4454.742, 2643.42, 2753.68 + 0.8, 21000.0, 0.8989, 6906.616, 3843.64, 3004.02 + 0.8, 21000.0, 0.9738, 9576.007, 5301.67, 3254.35 + 0.8, 24000.0, 0.0, 378.7349, 378.735, 0.0 + 0.8, 24000.0, 0.4386, -1867.215, -320.375, 1465.88 + 0.8, 24000.0, 0.5117, -932.3074, 106.167, 1710.2 + 0.8, 24000.0, 0.5848, 2.600157, 532.71, 1954.51 + 0.8, 24000.0, 0.6579, 937.5078, 959.253, 2198.82 + 0.8, 24000.0, 0.731, 2096.598, 1479.21, 2443.14 + 0.8, 24000.0, 0.8041, 3710.548, 2214.74, 2687.45 + 0.8, 24000.0, 0.8772, 5841.67, 3229.44, 2931.76 + 0.8, 24000.0, 0.9504, 8176.213, 4481.95, 3176.08 + 0.8, 27000.0, 0.0, 336.3645, 336.365, 0.0 + 0.8, 27000.0, 0.4278, -1977.188, -375.293, 1429.77 + 0.8, 27000.0, 0.4991, -1083.48, 14.6095, 1668.06 + 0.8, 27000.0, 0.5704, -189.7722, 404.512, 1906.36 + 0.8, 27000.0, 0.6417, 703.9356, 794.415, 2144.65 + 0.8, 27000.0, 0.713, 1692.484, 1230.78, 2382.95 + 0.8, 27000.0, 0.7843, 3068.207, 1849.32, 2621.24 + 0.8, 27000.0, 0.8556, 4908.532, 2704.71, 2859.54 + 0.8, 27000.0, 0.9269, 6922.472, 3748.69, 3097.83 + 0.8, 27000.0, 0.9982, 9102.29, 5050.5, 3336.13 + 0.8, 30000.0, 0.0, 297.8406, 297.841, 0.0 + 0.8, 30000.0, 0.417, -2064.092, -438.634, 1393.66 + 0.8, 30000.0, 0.4865, -1218.425, -77.9119, 1625.94 + 0.8, 30000.0, 0.556, -372.7574, 282.81, 1858.22 + 0.8, 30000.0, 0.6255, 472.9099, 643.532, 2090.49 + 0.8, 30000.0, 0.695, 1370.585, 1028.3, 2322.77 + 0.8, 30000.0, 0.7645, 2530.471, 1542.46, 2555.05 + 0.8, 30000.0, 0.834, 4107.331, 2260.41, 2787.32 + 0.8, 30000.0, 0.9035, 5852.454, 3140.56, 3019.6 + 0.8, 30000.0, 0.973, 7598.472, 4178.73, 3251.88 + 0.8, 33000.0, 0.0, 262.8967, 262.897, 0.0 + 0.8, 33000.0, 0.4062, -2072.612, -464.653, 1357.57 + 0.8, 33000.0, 0.4739, -1296.433, -141.055, 1583.83 + 0.8, 33000.0, 0.5416, -520.2536, 182.543, 1810.09 + 0.8, 33000.0, 0.6093, 255.9259, 506.142, 2036.35 + 0.8, 33000.0, 0.677, 1036.676, 831.855, 2262.62 + 0.8, 33000.0, 0.7447, 2035.166, 1265.56, 2488.88 + 0.8, 33000.0, 0.8124, 3365.894, 1857.87, 2715.14 + 0.8, 33000.0, 0.8801, 4871.02, 2596.61, 2941.4 + 0.8, 33000.0, 0.9478, 6356.582, 3459.17, 3167.66 + 0.8, 36000.0, 0.0, 231.283, 231.283, 0.0 + 0.8, 36000.0, 0.3954, -2093.651, -502.807, 1321.48 + 0.8, 36000.0, 0.4613, -1394.409, -211.882, 1541.73 + 0.8, 36000.0, 0.5272, -695.1683, 79.0429, 1761.98 + 0.8, 36000.0, 0.5931, 4.073, 369.968, 1982.22 + 0.8, 36000.0, 0.659, 703.3141, 660.893, 2202.47 + 0.8, 36000.0, 0.7249, 1537.864, 1014.59, 2422.72 + 0.8, 36000.0, 0.7908, 2605.122, 1502.23, 2642.96 + 0.8, 36000.0, 0.8567, 3906.286, 2121.97, 2863.21 + 0.8, 36000.0, 0.9226, 5160.528, 2819.05, 3083.46 + 0.8, 36000.0, 0.9885, 6214.967, 3542.96, 3303.7 + 0.8, 39000.0, 0.0, 200.4691, 200.469, 0.0 + 0.8, 39000.0, 0.3949, -2166.228, -575.212, 1319.66 + 0.8, 39000.0, 0.4607, -1512.135, -300.627, 1539.6 + 0.8, 39000.0, 0.5265, -858.0406, -26.0431, 1759.54 + 0.8, 39000.0, 0.5923, -203.9467, 248.541, 1979.49 + 0.8, 39000.0, 0.6581, 450.1472, 523.126, 2199.43 + 0.8, 39000.0, 0.7239, 1165.015, 829.214, 2419.37 + 0.8, 39000.0, 0.7897, 2072.46, 1242.1, 2639.32 + 0.8, 39000.0, 0.8556, 3202.957, 1778.11, 2859.26 + 0.8, 39000.0, 0.9214, 4305.413, 2377.56, 3079.2 + 0.8, 39000.0, 0.9872, 5206.17, 2987.71, 3299.15 + 0.8, 42000.0, 0.0, 173.6477, 173.648, 0.0 + 0.8, 42000.0, 0.3949, -2368.167, -692.733, 1319.66 + 0.8, 42000.0, 0.4607, -1730.602, -422.722, 1539.6 + 0.8, 42000.0, 0.5265, -1093.037, -152.71, 1759.54 + 0.8, 42000.0, 0.5923, -455.4724, 117.301, 1979.49 + 0.8, 42000.0, 0.6581, 182.0924, 387.313, 2199.43 + 0.8, 42000.0, 0.7239, 816.2892, 659.968, 2419.37 + 0.8, 42000.0, 0.7897, 1604.931, 1013.43, 2639.32 + 0.8, 42000.0, 0.8556, 2582.459, 1475.46, 2859.26 + 0.8, 42000.0, 0.9214, 3546.213, 1986.9, 3079.2 + 0.8, 42000.0, 0.9872, 4367.351, 2529.56, 3299.15 + 0.85, 0.0, 0.0, 931.6846, 931.685, 0.0 + 0.85, 0.0, 0.5329, -33163.23, -1399.91, 1780.85 + 0.85, 0.0, 0.6217, -18017.21, 282.625, 2077.66 + 0.85, 0.0, 0.7105, -2871.143, 1965.18, 2374.47 + 0.85, 0.0, 0.7993, 4049.943, 3717.24, 2671.28 + 0.85, 0.0, 0.8881, -9629.868, 4553.76, 2968.09 + 0.85, 0.0, 0.9769, -24268.95, 5269.31, 3264.9 + 0.85, 3000.0, 0.0, 843.7751, 843.775, 0.0 + 0.85, 3000.0, 0.5219, 5025.556, 611.026, 1744.13 + 0.85, 3000.0, 0.6089, 2794.123, 1298.8, 2034.82 + 0.85, 3000.0, 0.6958, 562.8325, 1986.64, 2325.5 + 0.85, 3000.0, 0.7828, 1107.634, 2956.52, 2616.19 + 0.85, 3000.0, 0.8698, 11867.25, 4905.02, 2906.88 + 0.85, 3000.0, 0.9568, 10082.0, 6851.63, 3197.57 + 0.85, 6000.0, 0.0, 762.5724, 762.572, 0.0 + 0.85, 6000.0, 0.5109, -23034.48, 52.5672, 1707.41 + 0.85, 6000.0, 0.596, -14624.04, 816.144, 1991.98 + 0.85, 6000.0, 0.6812, -6213.502, 1579.72, 2276.54 + 0.85, 6000.0, 0.7663, 913.1722, 2515.03, 2561.11 + 0.85, 6000.0, 0.8515, 10987.25, 4430.05, 2845.68 + 0.85, 6000.0, 0.9366, 2773.197, 4305.7, 3130.25 + 0.85, 9000.0, 0.0, 687.6922, 687.692, 0.0 + 0.85, 9000.0, 0.4999, -1710.265, 130.683, 1670.7 + 0.85, 9000.0, 0.5832, -447.3183, 799.959, 1949.15 + 0.85, 9000.0, 0.6665, 815.6299, 1469.24, 2227.6 + 0.85, 9000.0, 0.7499, 2394.568, 2330.58, 2506.05 + 0.85, 9000.0, 0.8332, 5224.318, 3617.34, 2784.5 + 0.85, 9000.0, 0.9165, 8926.235, 5474.27, 3062.96 + 0.85, 9000.0, 0.9998, 12111.29, 7637.39, 3341.41 + 0.85, 12000.0, 0.0, 618.7578, 618.758, 0.0 + 0.85, 12000.0, 0.4889, -1811.806, 32.7751, 1634.0 + 0.85, 12000.0, 0.5704, -502.1741, 654.596, 1906.34 + 0.85, 12000.0, 0.6519, 807.4582, 1276.42, 2178.67 + 0.85, 12000.0, 0.7334, 2121.807, 1988.25, 2451.01 + 0.85, 12000.0, 0.8149, 4239.495, 3056.0, 2723.34 + 0.85, 12000.0, 0.8964, 7230.834, 4629.12, 2995.68 + 0.85, 12000.0, 0.9779, 11284.5, 6709.43, 3268.01 + 0.85, 15000.0, 0.0, 555.4172, 555.417, 0.0 + 0.85, 15000.0, 0.478, -1600.868, -37.4875, 1597.32 + 0.85, 15000.0, 0.5576, -510.2755, 523.897, 1863.54 + 0.85, 15000.0, 0.6373, 580.3165, 1085.28, 2129.76 + 0.85, 15000.0, 0.7169, 1849.749, 1706.95, 2395.98 + 0.85, 15000.0, 0.7966, 3764.108, 2623.52, 2662.2 + 0.85, 15000.0, 0.8762, 6266.997, 3935.04, 2928.42 + 0.85, 15000.0, 0.9559, 9731.934, 5761.93, 3194.64 + 0.85, 18000.0, 0.0, 497.3284, 497.328, 0.0 + 0.85, 18000.0, 0.467, -1687.664, -117.824, 1560.64 + 0.85, 18000.0, 0.5448, -658.794, 392.739, 1820.75 + 0.85, 18000.0, 0.6226, 370.0765, 903.302, 2080.86 + 0.85, 18000.0, 0.7005, 1514.095, 1460.13, 2340.97 + 0.85, 18000.0, 0.7783, 3095.699, 2219.6, 2601.07 + 0.85, 18000.0, 0.8561, 5489.965, 3375.71, 2861.18 + 0.85, 18000.0, 0.934, 8311.906, 4850.81, 3121.29 + 0.85, 21000.0, 0.0, 444.1602, 444.16, 0.0 + 0.85, 21000.0, 0.456, -2030.57, -220.875, 1523.98 + 0.85, 21000.0, 0.532, -963.9674, 255.827, 1777.98 + 0.85, 21000.0, 0.608, 102.6354, 732.53, 2031.97 + 0.85, 21000.0, 0.684, 1196.485, 1222.02, 2285.97 + 0.85, 21000.0, 0.76, 2703.484, 1908.75, 2539.97 + 0.85, 21000.0, 0.836, 4652.773, 2847.85, 2793.96 + 0.85, 21000.0, 0.912, 7160.375, 4137.66, 3047.96 + 0.85, 21000.0, 0.988, 9868.794, 5685.47, 3301.96 + 0.85, 24000.0, 0.0, 395.5992, 395.599, 0.0 + 0.85, 24000.0, 0.445, -2172.624, -307.18, 1487.32 + 0.85, 24000.0, 0.5192, -1129.086, 139.101, 1735.21 + 0.85, 24000.0, 0.5934, -85.54757, 585.382, 1983.1 + 0.85, 24000.0, 0.6676, 957.9909, 1031.66, 2230.99 + 0.85, 24000.0, 0.7417, 2199.474, 1595.95, 2478.87 + 0.85, 24000.0, 0.8159, 3874.791, 2387.01, 2726.76 + 0.85, 24000.0, 0.8901, 6064.754, 3480.34, 2974.65 + 0.85, 24000.0, 0.9643, 8458.32, 4809.63, 3222.54 + 0.85, 27000.0, 0.0, 351.3422, 351.342, 0.0 + 0.85, 27000.0, 0.4341, -1979.789, -346.649, 1450.68 + 0.85, 27000.0, 0.5064, -1075.612, 55.2415, 1692.46 + 0.85, 27000.0, 0.5788, -171.4348, 457.133, 1934.24 + 0.85, 27000.0, 0.6511, 732.7424, 859.024, 2176.02 + 0.85, 27000.0, 0.7235, 1756.22, 1325.54, 2417.8 + 0.85, 27000.0, 0.7958, 3233.39, 2003.43, 2659.59 + 0.85, 27000.0, 0.8682, 5107.153, 2912.38, 2901.37 + 0.85, 27000.0, 0.9405, 7204.676, 4059.93, 3143.15 + 0.85, 30000.0, 0.0, 311.1029, 311.103, 0.0 + 0.85, 30000.0, 0.4231, -1029.577, -235.419, 1414.05 + 0.85, 30000.0, 0.4936, -430.8531, 92.3508, 1649.72 + 0.85, 30000.0, 0.5642, 167.8722, 420.12, 1885.4 + 0.85, 30000.0, 0.6347, 766.598, 747.889, 2121.07 + 0.85, 30000.0, 0.7052, 1434.078, 1102.44, 2356.75 + 0.85, 30000.0, 0.7757, 2647.119, 1664.29, 2592.42 + 0.85, 30000.0, 0.8462, 4277.524, 2427.75, 2828.1 + 0.85, 30000.0, 0.9167, 6051.8, 3382.78, 3063.77 + 0.85, 30000.0, 0.9873, 7919.08, 4499.01, 3299.45 + 0.85, 33000.0, 0.0, 274.603, 274.603, 0.0 + 0.85, 33000.0, 0.4122, -2004.589, -492.533, 1377.43 + 0.85, 33000.0, 0.4808, -1230.077, -145.316, 1607.0 + 0.85, 33000.0, 0.5495, -455.5648, 201.901, 1836.57 + 0.85, 33000.0, 0.6182, 318.9473, 549.118, 2066.14 + 0.85, 33000.0, 0.6869, 1132.311, 914.311, 2295.71 + 0.85, 33000.0, 0.7556, 2141.301, 1368.08, 2525.28 + 0.85, 33000.0, 0.8243, 3527.261, 2014.7, 2754.85 + 0.85, 33000.0, 0.893, 5086.398, 2807.67, 2984.43 + 0.85, 33000.0, 0.9617, 6603.009, 3726.83, 3214.0 + 0.85, 36000.0, 0.0, 241.5815, 241.582, 0.0 + 0.85, 36000.0, 0.4012, -1990.32, -480.356, 1340.81 + 0.85, 36000.0, 0.4681, -1303.569, -180.98, 1564.28 + 0.85, 36000.0, 0.5349, -616.8176, 118.397, 1787.75 + 0.85, 36000.0, 0.6018, 69.9334, 417.774, 2011.22 + 0.85, 36000.0, 0.6687, 756.6846, 717.151, 2234.69 + 0.85, 36000.0, 0.7355, 1609.424, 1100.45, 2458.15 + 0.85, 36000.0, 0.8024, 2729.026, 1623.16, 2681.62 + 0.85, 36000.0, 0.8693, 4062.807, 2281.65, 2905.09 + 0.85, 36000.0, 0.9361, 5356.057, 3038.81, 3128.56 + 0.85, 39000.0, 0.0, 209.3956, 209.396, 0.0 + 0.85, 39000.0, 0.4006, -2125.716, -543.844, 1338.96 + 0.85, 39000.0, 0.4674, -1468.462, -264.105, 1562.12 + 0.85, 39000.0, 0.5342, -811.207, 15.6346, 1785.28 + 0.85, 39000.0, 0.601, -153.9524, 295.374, 2008.44 + 0.85, 39000.0, 0.6677, 503.3022, 575.114, 2231.6 + 0.85, 39000.0, 0.7345, 1234.885, 903.308, 2454.76 + 0.85, 39000.0, 0.8013, 2177.383, 1347.02, 2677.92 + 0.85, 39000.0, 0.8681, 3346.728, 1917.08, 2901.08 + 0.85, 39000.0, 0.9348, 4473.484, 2564.73, 3124.24 + 0.85, 42000.0, 0.0, 181.3798, 181.38, 0.0 + 0.85, 42000.0, 0.4006, -2263.573, -625.903, 1338.96 + 0.85, 42000.0, 0.4674, -1632.925, -358.608, 1562.12 + 0.85, 42000.0, 0.5342, -1002.277, -91.3126, 1785.28 + 0.85, 42000.0, 0.601, -371.6294, 175.983, 2008.44 + 0.85, 42000.0, 0.6677, 259.0184, 443.278, 2231.6 + 0.85, 42000.0, 0.7345, 901.3026, 728.585, 2454.76 + 0.85, 42000.0, 0.8013, 1698.112, 1105.39, 2677.92 + 0.85, 42000.0, 0.8681, 2714.253, 1596.34, 2901.08 + 0.85, 42000.0, 0.9348, 3678.52, 2136.85, 3124.24 + 0.9, 0.0, 0.0, 975.0792, 975.079, 0.0 + 0.9, 0.0, 0.541, -43097.71, -1919.22, 1808.08 + 0.9, 0.0, 0.6312, -23656.43, 52.0169, 2109.43 + 0.9, 0.0, 0.7214, -4215.086, 2023.28, 2410.78 + 0.9, 0.0, 0.8115, 4039.106, 3992.87, 2712.13 + 0.9, 0.0, 0.9017, -15008.39, 4626.62, 3013.47 + 0.9, 0.0, 0.9919, -35007.54, 4933.34, 3314.82 + 0.9, 3000.0, 0.0, 883.0752, 883.075, 0.0 + 0.9, 3000.0, 0.5299, 7379.202, 765.384, 1770.8 + 0.9, 3000.0, 0.6182, 3821.476, 1443.2, 2065.93 + 0.9, 3000.0, 0.7065, 263.939, 2121.12, 2361.06 + 0.9, 3000.0, 0.7948, 338.3372, 3122.46, 2656.19 + 0.9, 3000.0, 0.8831, 13757.05, 5262.03, 2951.33 + 0.9, 3000.0, 0.9714, 10154.06, 7292.44, 3246.46 + 0.9, 6000.0, 0.0, 798.0904, 798.09, 0.0 + 0.9, 6000.0, 0.5187, -30345.9, 51.6335, 1733.52 + 0.9, 6000.0, 0.6052, -19574.44, 846.239, 2022.43 + 0.9, 6000.0, 0.6916, -8802.833, 1640.84, 2311.35 + 0.9, 6000.0, 0.7781, 160.3125, 2628.67, 2600.27 + 0.9, 6000.0, 0.8645, 12963.2, 4836.64, 2889.19 + 0.9, 6000.0, 0.951, 312.3435, 4033.69, 3178.11 + 0.9, 9000.0, 0.0, 719.7225, 719.722, 0.0 + 0.9, 9000.0, 0.5076, -1960.594, 170.752, 1696.25 + 0.9, 9000.0, 0.5921, -681.7229, 861.645, 1978.96 + 0.9, 9000.0, 0.6767, 597.1513, 1552.54, 2261.66 + 0.9, 9000.0, 0.7613, 2264.929, 2480.96, 2544.37 + 0.9, 9000.0, 0.8459, 5521.127, 3900.66, 2827.08 + 0.9, 9000.0, 0.9305, 9431.863, 5925.47, 3109.79 + 0.9, 12000.0, 0.0, 647.5774, 647.577, 0.0 + 0.9, 12000.0, 0.4964, -1062.255, 130.023, 1658.99 + 0.9, 12000.0, 0.5791, -1.886726, 754.701, 1935.49 + 0.9, 12000.0, 0.6619, 1058.483, 1379.38, 2211.99 + 0.9, 12000.0, 0.7446, 2047.574, 2094.17, 2488.48 + 0.9, 12000.0, 0.8273, 4187.016, 3244.86, 2764.98 + 0.9, 12000.0, 0.9101, 7457.428, 5027.06, 3041.48 + 0.9, 12000.0, 0.9928, 11669.17, 7199.91, 3317.98 + 0.9, 15000.0, 0.0, 581.2866, 581.287, 0.0 + 0.9, 15000.0, 0.4853, -1383.533, 24.8514, 1621.74 + 0.9, 15000.0, 0.5661, -360.5144, 598.682, 1892.04 + 0.9, 15000.0, 0.647, 662.5033, 1172.51, 2162.33 + 0.9, 15000.0, 0.7279, 1893.157, 1803.28, 2432.62 + 0.9, 15000.0, 0.8088, 3907.621, 2794.37, 2702.91 + 0.9, 15000.0, 0.8896, 6454.629, 4255.54, 2973.2 + 0.9, 15000.0, 0.9705, 10048.04, 6200.19, 3243.49 + 0.9, 18000.0, 0.0, 520.4922, 520.492, 0.0 + 0.9, 18000.0, 0.4741, -1786.476, -88.2785, 1584.51 + 0.9, 18000.0, 0.5531, -724.6719, 445.28, 1848.59 + 0.9, 18000.0, 0.6322, 337.1329, 978.837, 2112.68 + 0.9, 18000.0, 0.7112, 1524.708, 1558.47, 2376.76 + 0.9, 18000.0, 0.7902, 3000.021, 2320.76, 2640.84 + 0.9, 18000.0, 0.8692, 5830.993, 3705.08, 2904.93 + 0.9, 18000.0, 0.9482, 8486.447, 5155.98, 3169.01 + 0.9, 21000.0, 0.0, 464.8476, 464.848, 0.0 + 0.9, 21000.0, 0.463, -2413.971, -191.581, 1547.28 + 0.9, 21000.0, 0.5401, -1249.261, 292.563, 1805.16 + 0.9, 21000.0, 0.6173, -84.5498, 776.71, 2063.04 + 0.9, 21000.0, 0.6945, 1152.819, 1294.96, 2320.92 + 0.9, 21000.0, 0.7716, 2898.082, 2072.72, 2578.81 + 0.9, 21000.0, 0.8488, 4902.84, 3073.16, 2836.69 + 0.9, 21000.0, 0.926, 7427.583, 4466.76, 3094.57 + 0.9, 24000.0, 0.0, 414.0249, 414.025, 0.0 + 0.9, 24000.0, 0.4518, -3380.377, -356.408, 1510.07 + 0.9, 24000.0, 0.5272, -1944.232, 130.35, 1761.74 + 0.9, 24000.0, 0.6025, -508.087, 617.107, 2013.42 + 0.9, 24000.0, 0.6778, 928.0581, 1103.87, 2265.1 + 0.9, 24000.0, 0.7531, 2298.104, 1709.64, 2516.78 + 0.9, 24000.0, 0.8284, 4098.067, 2588.28, 2768.46 + 0.9, 24000.0, 0.9037, 6273.946, 3752.72, 3020.13 + 0.9, 24000.0, 0.979, 8743.34, 5132.8, 3271.81 + 0.9, 27000.0, 0.0, 367.7065, 367.706, 0.0 + 0.9, 27000.0, 0.4407, -2469.044, -390.764, 1472.86 + 0.9, 27000.0, 0.5142, -1423.592, 44.1199, 1718.34 + 0.9, 27000.0, 0.5876, -378.1391, 479.004, 1963.82 + 0.9, 27000.0, 0.6611, 667.3141, 913.889, 2209.3 + 0.9, 27000.0, 0.7345, 1847.188, 1439.59, 2454.77 + 0.9, 27000.0, 0.808, 3456.316, 2182.71, 2700.25 + 0.9, 27000.0, 0.8814, 5334.241, 3140.64, 2945.73 + 0.9, 27000.0, 0.9549, 7568.679, 4445.01, 3191.21 + 0.9, 30000.0, 0.0, 325.593, 325.593, 0.0 + 0.9, 30000.0, 0.4296, 1681.152, 303.522, 1435.67 + 0.9, 30000.0, 0.5012, 1614.546, 515.57, 1674.95 + 0.9, 30000.0, 0.5728, 1547.943, 727.614, 1914.23 + 0.9, 30000.0, 0.6444, 1481.342, 939.66, 2153.5 + 0.9, 30000.0, 0.716, 1489.434, 1168.39, 2392.78 + 0.9, 30000.0, 0.7876, 2776.802, 1795.8, 2632.06 + 0.9, 30000.0, 0.8592, 4453.394, 2598.17, 2871.34 + 0.9, 30000.0, 0.9308, 6232.736, 3648.9, 3110.62 + 0.9, 33000.0, 0.0, 287.3931, 287.393, 0.0 + 0.9, 33000.0, 0.4185, -1438.512, -498.657, 1398.49 + 0.9, 33000.0, 0.4882, -780.1592, -129.684, 1631.57 + 0.9, 33000.0, 0.5579, -121.8053, 239.29, 1864.65 + 0.9, 33000.0, 0.6277, 536.5477, 608.262, 2097.73 + 0.9, 33000.0, 0.6974, 1317.006, 1033.73, 2330.81 + 0.9, 33000.0, 0.7672, 2285.179, 1487.06, 2563.9 + 0.9, 33000.0, 0.8369, 3726.149, 2211.5, 2796.98 + 0.9, 33000.0, 0.9067, 5415.789, 3069.66, 3030.06 + 0.9, 33000.0, 0.9764, 6924.213, 4021.37, 3263.14 + 0.9, 36000.0, 0.0, 252.8336, 252.834, 0.0 + 0.9, 36000.0, 0.4073, -1593.119, -365.198, 1361.31 + 0.9, 36000.0, 0.4752, -983.3862, -76.3822, 1588.2 + 0.9, 36000.0, 0.5431, -373.6523, 212.434, 1815.08 + 0.9, 36000.0, 0.611, 236.0799, 501.25, 2041.97 + 0.9, 36000.0, 0.6789, 845.8141, 790.066, 2268.86 + 0.9, 36000.0, 0.7468, 1663.118, 1196.56, 2495.74 + 0.9, 36000.0, 0.8147, 2917.313, 1741.87, 2722.63 + 0.9, 36000.0, 0.8826, 4224.532, 2455.38, 2949.51 + 0.9, 36000.0, 0.9504, 5620.762, 3309.85, 3176.4 + 0.9, 39000.0, 0.0, 219.1485, 219.149, 0.0 + 0.9, 39000.0, 0.4068, -1720.484, -451.088, 1359.44 + 0.9, 39000.0, 0.4746, -1147.154, -180.858, 1586.01 + 0.9, 39000.0, 0.5424, -573.8231, 89.3732, 1812.58 + 0.9, 39000.0, 0.6102, -0.4923, 359.604, 2039.15 + 0.9, 39000.0, 0.678, 572.8385, 629.834, 2265.73 + 0.9, 39000.0, 0.7458, 1304.305, 987.578, 2492.3 + 0.9, 39000.0, 0.8135, 2300.085, 1448.18, 2718.87 + 0.9, 39000.0, 0.8813, 3485.507, 2070.09, 2945.44 + 0.9, 39000.0, 0.9491, 4642.574, 2769.24, 3172.02 + 0.9, 42000.0, 0.0, 189.8279, 189.828, 0.0 + 0.9, 42000.0, 0.4068, -2081.777, -554.009, 1359.44 + 0.9, 42000.0, 0.4746, -1479.96, -291.827, 1586.01 + 0.9, 42000.0, 0.5424, -878.1438, -29.644, 1812.58 + 0.9, 42000.0, 0.6102, -276.3273, 232.539, 2039.15 + 0.9, 42000.0, 0.678, 325.4889, 494.721, 2265.73 + 0.9, 42000.0, 0.7458, 960.107, 797.097, 2492.3 + 0.9, 42000.0, 0.8135, 1816.055, 1199.02, 2718.87 + 0.9, 42000.0, 0.8813, 2849.73, 1733.87, 2945.44 + 0.9, 42000.0, 0.9491, 3854.696, 2333.19, 3172.02 diff --git a/aviary/models/engines/turbofan_23k_1.deck b/aviary/models/engines/turbofan_23k_1.deck deleted file mode 100644 index 084cc272e7..0000000000 --- a/aviary/models/engines/turbofan_23k_1.deck +++ /dev/null @@ -1,2808 +0,0 @@ -# GASP-derived engine deck converted from GASP_turbofan_23k_1.eng -# t4max: 3342.0 -# t4cruise: 3108.0 -# t4climb: 3196.0 -# sls_airflow: 994.36 -# sfn_idle: 1.25 - -Mach_Number (unitless), Altitude (ft), Throttle (unitless), Thrust (lbf), Fuel_Flow (lb/h), T4 (degR) - 0.0, 0.0, 0.0, 621.4719458090369, 621.4719458090369, 0.0 - 0.0, 0.0, 0.4655924596050269, -1979.1618999999998, -105.24909999999998, 1556.0099999999998 - 0.0, 0.0, 0.5431912028725313, 1065.323499999999, 539.5527999999999, 1815.3449999999998 - 0.0, 0.0, 0.6207899461400359, 4109.808599999997, 1184.3545999999994, 2074.68 - 0.0, 0.0, 0.6983886894075404, 7327.181199999998, 1870.6585999999998, 2334.015 - 0.0, 0.0, 0.7759874326750449, 11036.915999999994, 2800.214400000001, 2593.35 - 0.0, 0.0, 0.8535861759425494, 15708.877899999996, 4095.815400000001, 2852.685 - 0.0, 0.0, 0.9311849192100538, 21836.462899999977, 5870.266599999997, 3112.0199999999995 - 0.0, 3000.0, 0.0, 562.8245919323617, 562.8245919323617, 0.0 - 0.0, 3000.0, 0.45598922800718134, -2285.519, -183.5061, 1523.916 - 0.0, 3000.0, 0.5319874326750449, 456.4108999999994, 412.26110000000006, 1777.902 - 0.0, 3000.0, 0.6079856373429084, 3198.3412999999987, 1008.0283, 2031.888 - 0.0, 3000.0, 0.6839838420107719, 5972.483399999998, 1620.9913, 2285.874 - 0.0, 3000.0, 0.7599820466786354, 9207.826199999998, 2437.9938999999995, 2539.8599999999997 - 0.0, 3000.0, 0.8359802513464991, 13217.797900000009, 3553.4655999999995, 2793.846 - 0.0, 3000.0, 0.9119784560143627, 18617.677700000004, 5114.419399999995, 3047.832 - 0.0, 3000.0, 0.9879766606822261, 25284.21289999999, 7083.126999999999, 3301.8179999999998 - 0.0, 6000.0, 0.0, 508.6372241992847, 508.6372241992847, 0.0 - 0.0, 6000.0, 0.4463850987432675, -2935.8345, -280.32, 1491.819 - 0.0, 6000.0, 0.5207826152004787, -197.46330000000103, 275.13859999999977, 1740.4555 - 0.0, 6000.0, 0.59518013165769, 2540.907699999998, 830.5971999999995, 1989.092 - 0.0, 6000.0, 0.6695776481149013, 5279.279300000001, 1386.0558000000003, 2237.7285 - 0.0, 6000.0, 0.7439751645721125, 8213.525399999993, 2090.8967, 2486.3650000000002 - 0.0, 6000.0, 0.8183726810293238, 11851.381800000008, 3062.070300000002, 2735.0015000000003 - 0.0, 6000.0, 0.892770197486535, 16560.28909999998, 4378.632800000005, 2983.638 - 0.0, 6000.0, 0.9671677139437462, 22654.554700000022, 6120.2305, 3232.2745 - 0.0, 9000.0, 0.0, 458.6569006593942, 458.6569006593942, 0.0 - 0.0, 9000.0, 0.4367818671454219, 820.9403000000008, -198.5158000000001, 1459.725 - 0.0, 9000.0, 0.5095788450029922, 2287.7753999999904, 273.47830000000204, 1703.0125 - 0.0, 9000.0, 0.5823758228605626, 3754.6023999999666, 745.4744000000036, 1946.3 - 0.0, 9000.0, 0.6551728007181329, 5221.432299999996, 1217.471099999993, 2189.5875 - 0.0, 9000.0, 0.7279697785757032, 6857.633999999983, 1767.4456000000362, 2432.875 - 0.0, 9000.0, 0.8007667564332734, 10501.953100000013, 2618.3858000000314, 2676.1625 - 0.0, 9000.0, 0.8735637342908438, 14702.6974000001, 3781.45529999997, 2919.45 - 0.0, 9000.0, 0.946360712148414, 19922.60839999998, 5272.304499999956, 3162.7374999999997 - 0.0, 12000.0, 0.0, 412.6354242729135, 412.6354242729135, 0.0 - 0.0, 12000.0, 0.42717773788150804, -10008.410051999977, -627.1232216000017, 1427.628 - 0.0, 12000.0, 0.498374027528426, -5628.271185599976, -88.36455679999435, 1665.5659999999998 - 0.0, 12000.0, 0.5695703171753441, -1248.10798159995, 450.40240640002145, 1903.504 - 0.0, 12000.0, 0.6407666068222622, 3132.0434624000236, 989.1721031999733, 2141.442 - 0.0, 12000.0, 0.7119628964691802, 7439.101973600087, 1656.5764536000047, 2379.38 - 0.0, 12000.0, 0.783159186116098, 10835.884655199505, 2375.840575199889, 2617.3179999999998 - 0.0, 12000.0, 0.8543554757630161, 10534.273431199275, 2915.174178399845, 2855.256 - 0.0, 12000.0, 0.9255517654099341, 17296.457434399927, 4499.2635783996575, 3093.194 - 0.0, 12000.0, 0.996748055056852, 22936.55361199949, 6163.146618399912, 3331.1319999999996 - 0.0, 15000.0, 0.0, 370.3405482510708, 370.3405482510708, 0.0 - 0.0, 15000.0, 0.4175745062836625, -4108.327400000033, -953.7424000000004, 1395.534 - 0.0, 15000.0, 0.48717025733093955, -2085.1374000001288, -423.265600000019, 1628.123 - 0.0, 15000.0, 0.5567660083782167, -61.87750000035694, 107.2300999999502, 1860.712 - 0.0, 15000.0, 0.6263617594254937, 1961.357899999819, 637.7068999999258, 2093.301 - 0.0, 15000.0, 0.6959575104727708, 3868.836799999729, 805.1977999995336, 2325.89 - 0.0, 15000.0, 0.7655532615200478, 9295.393299999978, 2069.673199999495, 2558.479 - 0.0, 15000.0, 0.835149012567325, 8117.555200000044, 2353.5224000002117, 2791.068 - 0.0, 15000.0, 0.9047447636146021, 22532.67410000153, 5324.8861000002025, 3023.657 - 0.0, 15000.0, 0.9743405146618791, -366.133599999539, 2489.8093999998064, 3256.246 - 0.0, 18000.0, 0.0, 331.5464430756027, 331.5464430756027, 0.0 - 0.0, 18000.0, 0.40797037701974864, -18660.52885679985, -3371.5398183999805, 1363.437 - 0.0, 18000.0, 0.47596543985637346, -12470.878837600028, -2194.4000631999465, 1590.6765 - 0.0, 18000.0, 0.5439605026929982, -6281.173878400109, -1017.3242007998708, 1817.916 - 0.0, 18000.0, 0.6119555655296229, -91.4635384003791, 159.76448639951894, 2045.1554999999998 - 0.0, 18000.0, 0.6799506283662478, 1838.8419391999305, 794.5162264001054, 2272.395 - 0.0, 18000.0, 0.7479456912028726, 3461.4070168009703, 958.9548840003713, 2499.6345 - 0.0, 18000.0, 0.8159407540394973, 8465.954334398888, 1595.0021775992507, 2726.874 - 0.0, 18000.0, 0.8839358168761221, 4672.62643839906, 1685.1043480005942, 2954.1135 - 0.0, 18000.0, 0.9519308797127469, 30679.135772005346, 5644.57566559926, 3181.353 - 0.0, 21000.0, 0.0, 296.0341081608423, 296.0341081608423, 0.0 - 0.0, 21000.0, 0.3983671454219031, 5188.336937600053, 3488.554260800007, 1331.343 - 0.0, 21000.0, 0.46476166965888693, 4883.054692800119, 2747.0215935999963, 1553.2335 - 0.0, 21000.0, 0.5311561938958708, 4577.828439199983, 2005.5017512000343, 1775.124 - 0.0, 21000.0, 0.5975507181328545, 4272.564631200534, 1263.935070399853, 1997.0145 - 0.0, 21000.0, 0.6639452423698384, 4056.199360800366, 908.393472800037, 2218.905 - 0.0, 21000.0, 0.7303397666068223, 1.5720368018537556, 649.5522704002658, 2440.7955 - 0.0, 21000.0, 0.7967342908438062, 5555.628807200999, 1337.8957319992742, 2662.686 - 0.0, 21000.0, 0.86312881508079, 10865.940131196825, 3806.6596968006347, 2884.5765 - 0.0, 21000.0, 0.9295233393177739, 13527.602489597844, 5415.268763999967, 3106.467 - 0.0, 21000.0, 0.9959178635547576, 24247.309808000195, 11037.817901601342, 3328.3575 - 0.0, 24000.0, 0.0, 263.5961389215397, 263.5961389215397, 0.0 - 0.0, 24000.0, 0.38876301615798925, -2276.2842992000774, -4246.114488000014, 1299.246 - 0.0, 24000.0, 0.4535568521843208, -1397.9856888002778, -3030.8239136000325, 1515.787 - 0.0, 24000.0, 0.5183506882106523, -519.6311048008627, -1815.5488624000552, 1732.328 - 0.0, 24000.0, 0.5831445242369838, 358.6362591998643, -600.279003199581, 1948.869 - 0.0, 24000.0, 0.6479383602633153, 3549.5378272005296, 1028.186566400504, 2165.41 - 0.0, 24000.0, 0.7127321962896469, 7246.497172000982, 2298.2067224006373, 2381.951 - 0.0, 24000.0, 0.7775260323159785, 8081.8817984045445, 2419.336496798534, 2598.492 - 0.0, 24000.0, 0.84231986834231, 10914.132656799951, 2151.440016000627, 2815.033 - 0.0, 24000.0, 0.9071137043686416, 8142.089100804155, 2189.648812002002, 3031.574 - 0.0, 24000.0, 0.971907540394973, 9356.254232008245, 3346.386321604228, 3248.115 - 0.0, 27000.0, 0.0, 234.03155056971013, 234.03155056971013, 0.0 - 0.0, 27000.0, 0.37915978456014365, 31666.47125680015, 15545.981836000006, 1267.152 - 0.0, 27000.0, 0.44235308198683426, 22716.749602400203, 11633.723804800002, 1478.344 - 0.0, 27000.0, 0.5055463794135249, 13766.905935999872, 7721.385391999946, 1689.536 - 0.0, 27000.0, 0.5687396768402154, 4817.089456799192, 3809.046979199601, 1900.728 - 0.0, 27000.0, 0.6319329742669061, -4080.8996656005183, -421.7728919999099, 2111.92 - 0.0, 27000.0, 0.6951262716935966, 3533.178786400851, 157.00693919892183, 2323.112 - 0.0, 27000.0, 0.7583195691202873, 2905.361299203511, 84.29607599992141, 2534.304 - 0.0, 27000.0, 0.8215128665469779, -631.5598399957908, 2054.877212800607, 2745.496 - 0.0, 27000.0, 0.8847061639736685, 10808.442852806893, 2537.8370016038916, 2956.688 - 0.0, 27000.0, 0.9478994614003591, -1558.2877904023171, 3488.2616032036394, 3167.88 - 0.0, 30000.0, 0.0, 207.15053647796987, 207.15053647796987, 0.0 - 0.0, 30000.0, 0.3695556552962298, 423.60839999973825, 2063.463199999922, 1235.055 - 0.0, 30000.0, 0.4311482645122681, 2344.484399999737, 1915.561399999787, 1440.8975 - 0.0, 30000.0, 0.4927408737283064, 4264.664800000413, 1767.8806999995636, 1646.74 - 0.0, 30000.0, 0.5543334829443447, 6185.202800000603, 1620.0712000001233, 1852.5825 - 0.0, 30000.0, 0.6159260921603831, 4867.513699999471, 174.7018999992215, 2058.425 - 0.0, 30000.0, 0.6775187013764212, -1357.8645999972396, 312.41500000152246, 2264.2675 - 0.0, 30000.0, 0.7391113105924596, 916.2128999978495, -601.5901000000449, 2470.11 - 0.0, 30000.0, 0.8007039198084979, 2808.1613999994415, -2068.876100000871, 2675.9525 - 0.0, 30000.0, 0.8622965290245362, 14043.931799998172, 6579.604899998823, 2881.795 - 0.0, 30000.0, 0.9238891382405745, 29400.548600009355, 4365.934599993016, 3087.6375 - 0.0, 30000.0, 0.9854817474566128, 60041.21150001316, 12221.730399983775, 3293.48 - 0.0, 33000.0, 0.0, 182.7682627822692, 182.7682627822692, 0.0 - 0.0, 33000.0, 0.3599524236983842, 73148.21513039994, 8353.324134399922, 1202.961 - 0.0, 33000.0, 0.4199444943147816, 57096.465740799256, 6361.086206400059, 1403.4545 - 0.0, 33000.0, 0.479936564931179, 41044.58415039877, 4368.839710400288, 1603.948 - 0.0, 33000.0, 0.5399286355475763, 24992.66943039941, 2376.7084791998554, 1804.4415000000001 - 0.0, 33000.0, 0.5999207061639737, 8940.679883199635, 384.3552863992233, 2004.9350000000002 - 0.0, 33000.0, 0.6599127767803711, -2678.416689599624, -598.4544071998262, 2205.4285 - 0.0, 33000.0, 0.7199048473967684, 11541.777525599551, 4514.568512799082, 2405.922 - 0.0, 33000.0, 0.7798969180131657, 10052.411211202108, 3617.193000001155, 2606.4155 - 0.0, 33000.0, 0.8398889886295632, -5615.760698410661, -4056.6333136032736, 2806.909 - 0.0, 33000.0, 0.8998810592459605, 3125.791250395734, 1784.9111847969689, 3007.4025 - 0.0, 33000.0, 0.959873129862358, -53986.255697611516, -34872.51459441209, 3207.896 - 0.0, 36000.0, 0.0, 160.71110145094153, 160.71110145094153, 0.0 - 0.0, 36000.0, 0.3503482944344704, 69414.82060000008, 6249.212800000052, 1170.864 - 0.0, 36000.0, 0.40873967684021545, 54979.246499999215, 5111.865600000102, 1366.008 - 0.0, 36000.0, 0.4671310592459605, 40543.321499997386, 3974.518400000331, 1561.152 - 0.0, 36000.0, 0.5255224416517056, 26107.675899999722, 2837.2075999997337, 1756.296 - 0.0, 36000.0, 0.5839138240574506, 11671.904299999183, 1699.743499999383, 1951.44 - 0.0, 36000.0, 0.6423052064631957, 1488.745499999287, 509.0396000006642, 2146.584 - 0.0, 36000.0, 0.7006965888689408, 908.5232000010947, 93.53199999941216, 2341.728 - 0.0, 36000.0, 0.7590879712746859, -22077.37859999771, -3060.690900000438, 2536.8720000000003 - 0.0, 36000.0, 0.8174793536804309, 47160.97369998603, 10763.036000004584, 2732.016 - 0.0, 36000.0, 0.8758707360861759, 16056.511699998635, 5520.046099998181, 2927.16 - 0.0, 36000.0, 0.934262118491921, -24769.22380000766, -23716.88120000501, 3122.304 - 0.0, 39000.0, 0.0, 139.18795884474554, 139.18795884474554, 0.0 - 0.0, 39000.0, 0.3500628366247756, 476.76869999981204, 100.47639999994212, 1169.91 - 0.0, 39000.0, 0.40840664272890487, -266.4172000005486, -23.404000000047464, 1364.895 - 0.0, 39000.0, 0.4667504488330341, -1009.8918000026433, -147.2753000001624, 1559.88 - 0.0, 39000.0, 0.5250942549371634, -1753.1675000011428, -271.0661000002216, 1754.8650000000002 - 0.0, 39000.0, 0.5834380610412927, -2496.6146999991975, -394.90099999999177, 1949.8500000000001 - 0.0, 39000.0, 0.641781867145422, -4195.442200001051, -718.9283999993887, 2144.835 - 0.0, 39000.0, 0.7001256732495512, -200.1008000035963, -10.578099999264396, 2339.82 - 0.0, 39000.0, 0.7584694793536805, -4917.309699996938, -2004.8831999995791, 2534.8050000000003 - 0.0, 39000.0, 0.8168132854578097, 6913.459500000736, -4331.268599996136, 2729.79 - 0.0, 39000.0, 0.875157091561939, 11889.88930000615, 4348.427600005591, 2924.775 - 0.0, 39000.0, 0.9335008976660683, 120355.93110000575, 68678.60510001137, 3119.76 - 0.0, 42000.0, 0.0, 120.49820969410051, 120.49820969410051, 0.0 - 0.0, 42000.0, 0.3500628366247756, -462426.45453750144, -178027.53542500042, 1169.91 - 0.0, 42000.0, 0.40840664272890487, -362855.99003750156, -139381.9192750003, 1364.895 - 0.0, 42000.0, 0.4667504488330341, -263285.613987502, -100736.25400625053, 1559.88 - 0.0, 42000.0, 0.5250942549371634, -163715.37123749583, -62090.52693125096, 1754.8650000000002 - 0.0, 42000.0, 0.5834380610412927, -64145.006424998406, -23445.02315625043, 1949.8500000000001 - 0.0, 42000.0, 0.641781867145422, -17490.57143125056, -5916.426600000106, 2144.835 - 0.0, 42000.0, 0.7001256732495512, 9317.000762499272, 942.0129812504897, 2339.82 - 0.0, 42000.0, 0.7584694793536805, -11674.666931250234, -219.07879999847137, 2534.8050000000003 - 0.0, 42000.0, 0.8168132854578097, 25036.390487502504, 13878.411762500029, 2729.79 - 0.0, 42000.0, 0.875157091561939, -11573.788174998015, -5031.318149997111, 2924.775 - 0.0, 42000.0, 0.9335008976660683, 18711.330206260376, 14545.346225007728, 3119.76 - 0.05, 0.0, 0.0, 622.4046199093938, 622.4046199093938, 0.0 - 0.05, 0.0, 0.4658252558348294, -1937.3721000000003, -104.12520000000004, 1556.7880049999999 - 0.05, 0.0, 0.5434627984739676, 906.8547000000044, 545.1483999999999, 1816.2526724999998 - 0.05, 0.0, 0.6211003411131059, 3751.0815000000075, 1194.4219999999982, 2075.7173399999997 - 0.05, 0.0, 0.698737883752244, 6786.725600000015, 1886.2708999999904, 2335.1820074999996 - 0.05, 0.0, 0.7763754263913822, 10343.10549999996, 2825.1267, 2594.6466749999995 - 0.05, 0.0, 0.8540129690305205, 14849.091799999986, 4132.926300000012, 2854.1113424999994 - 0.05, 0.0, 0.9316505116696588, 20803.984399999925, 5925.91989999999, 3113.5760099999998 - 0.05, 3000.0, 0.0, 563.6692510090572, 563.6692510090572, 0.0 - 0.05, 3000.0, 0.4562172226211849, -2248.270464967594, -179.91800799787242, 1524.677958 - 0.05, 3000.0, 0.5322534263913824, 396.6363202068742, 416.5179393489364, 1778.790951 - 0.05, 3000.0, 0.6082896301615799, 3041.5431144829804, 1012.9540865957446, 2032.903944 - 0.05, 3000.0, 0.6843258339317774, 5721.0667973379595, 1627.1265442896877, 2287.016937 - 0.05, 3000.0, 0.7603620377019749, 8885.487061135052, 2447.127690868093, 2541.12993 - 0.05, 3000.0, 0.8363982414721723, 12820.922420032442, 3565.7965681932938, 2795.242923 - 0.05, 3000.0, 0.9124344452423698, 18151.574776620157, 5134.593962625701, 3049.355916 - 0.05, 3000.0, 0.9884706490125672, 24712.702336123915, 7106.733353212599, 3303.4689089999997 - 0.05, 6000.0, 0.0, 509.40056157708136, 509.40056157708136, 0.0 - 0.05, 6000.0, 0.4466082912926391, -2750.0512250000006, -271.6506500000001, 1492.5649094999999 - 0.05, 6000.0, 0.521043006508079, -204.44962500000358, 283.84602499999943, 1741.32572775 - 0.05, 6000.0, 0.5954777217235189, 2341.1521999999923, 839.3429499999986, 1990.086546 - 0.05, 6000.0, 0.6699124369389586, 4887.9331250000205, 1395.473525000012, 2238.84736425 - 0.05, 6000.0, 0.7443471521543986, 7675.51367500001, 2103.741374999999, 2487.6081825 - 0.05, 6000.0, 0.8187818673698384, 11181.158450000074, 3080.5632249999994, 2736.36900075 - 0.05, 6000.0, 0.8932165825852783, 15767.370700000045, 4411.23985000003, 2985.1298189999998 - 0.05, 6000.0, 0.9676512978007181, 21640.416925000085, 6158.170575000004, 3233.89063725 - 0.05, 9000.0, 0.0, 459.3452300603909, 459.3452300603909, 0.0 - 0.05, 9000.0, 0.43700025807899456, -1627.5457999999994, -281.51519999999994, 1460.4548624999998 - 0.05, 9000.0, 0.5098336344254937, 358.4681999999958, 213.74320000000057, 1703.8640062499999 - 0.05, 9000.0, 0.5826670107719928, 2344.4798999999875, 709.002200000001, 1947.2731499999998 - 0.05, 9000.0, 0.6555003871184918, 4330.492300000013, 1204.261499999999, 2190.6822937499996 - 0.05, 9000.0, 0.7283337634649909, 6540.991300000003, 1796.9236000000142, 2434.0914374999998 - 0.05, 9000.0, 0.8011671398114901, 9705.082500000013, 2638.345000000017, 2677.50058125 - 0.05, 9000.0, 0.8740005161579891, 13670.451900000027, 3784.247499999996, 2920.9097249999995 - 0.05, 9000.0, 0.9468338925044882, 18768.78350000001, 5284.293699999993, 3164.3188687499996 - 0.05, 12000.0, 0.0, 413.25468693747047, 413.25468693747047, 0.0 - 0.05, 12000.0, 0.4273913267504488, -5981.428851999989, -454.16947360000074, 1428.3418139999999 - 0.05, 12000.0, 0.4986232145421903, -2971.169757599988, 31.739027200003143, 1666.3987829999999 - 0.05, 12000.0, 0.5698551023339318, 39.101646400030575, 517.6516944000109, 1904.4557519999998 - 0.05, 12000.0, 0.6410869901256733, 3049.3670704000197, 1003.5658071999916, 2142.512721 - 0.05, 12000.0, 0.7123188779174147, 6215.422945600052, 1593.535885600008, 2380.56969 - 0.05, 12000.0, 0.783550765709156, 9242.336699199815, 2316.0362791999564, 2618.6266589999996 - 0.05, 12000.0, 0.8547826535008975, 10783.706455199672, 3081.601726399949, 2856.6836279999998 - 0.05, 12000.0, 0.9260145412926392, 16227.539562400005, 4497.384066399855, 3094.740597 - 0.05, 12000.0, 0.9972464290843805, 21278.34475199975, 6067.844866399971, 3332.7975659999997 - 0.05, 15000.0, 0.0, 370.89633687515106, 370.89633687515106, 0.0 - 0.05, 15000.0, 0.4177832935368042, -3422.1305000000207, -736.5147000000004, 1396.2317669999998 - 0.05, 15000.0, 0.48741384245960495, -1572.361400000081, -249.61880000001355, 1628.9370614999998 - 0.05, 15000.0, 0.5570443913824057, 277.45209999977146, 237.2890999999638, 1861.6423559999998 - 0.05, 15000.0, 0.6266749403052064, 2127.2500999998797, 724.1849999999652, 2094.3476505 - 0.05, 15000.0, 0.6963054892280072, 3919.874699999812, 993.1869999997302, 2327.052945 - 0.05, 15000.0, 0.7659360381508079, 8107.049899999965, 2006.6136999996747, 2559.7582395 - 0.05, 15000.0, 0.8355665870736084, 8295.775200000013, 2489.490100000111, 2792.4635339999995 - 0.05, 15000.0, 0.9051971359964092, 18916.62290000105, 4803.553300000074, 3025.1688284999996 - 0.05, 15000.0, 0.9748276849192099, 5936.33380000024, 3539.5044999998445, 3257.8741229999996 - 0.05, 18000.0, 0.0, 332.04401144149176, 332.04401144149176, 0.0 - 0.05, 18000.0, 0.4081743622082585, -13675.5747847999, -2474.1829223999875, 1364.1187184999999 - 0.05, 18000.0, 0.4762034225763016, -8945.338913600011, -1537.7825151999668, 1591.47183825 - 0.05, 18000.0, 0.5442324829443447, -4215.065122400058, -601.4260287999203, 1818.824958 - 0.05, 18000.0, 0.6122615433123877, 515.2119175997411, 334.93951039966885, 2046.1780777499998 - 0.05, 18000.0, 0.6802906036804308, 2286.805031199906, 893.9298304000711, 2273.5311975 - 0.05, 18000.0, 0.7483196640484739, 3918.8857048007403, 1174.02146400025, 2500.88431725 - 0.05, 18000.0, 0.816348724416517, 7981.962458399246, 1803.377673599487, 2728.2374369999998 - 0.05, 18000.0, 0.8843777847845601, 6270.0137423994165, 2149.1522480003446, 2955.59055675 - 0.05, 18000.0, 0.9524068451526032, 25369.3332520036, 5247.75616159944, 3182.9436765 - 0.05, 21000.0, 0.0, 296.47838138566897, 296.47838138566897, 0.0 - 0.05, 21000.0, 0.398566328994614, 2763.0429736000383, 2319.5498488000057, 1332.0086715 - 0.05, 21000.0, 0.46499405049371634, 2979.9080608000777, 1901.5675495999965, 1554.01011675 - 0.05, 21000.0, 0.5314217719928186, 3196.8131311999755, 1483.5943032000205, 1776.011562 - 0.05, 21000.0, 0.597849493491921, 3413.691863200385, 1065.5872743999143, 1998.0130072499999 - 0.05, 21000.0, 0.6642772149910233, 3661.6466888002374, 912.1589208000045, 2220.0144525 - 0.05, 21000.0, 0.7307049364901257, 1190.716444801279, 855.5184744001613, 2442.01589775 - 0.05, 21000.0, 0.797132657989228, 5622.828899200619, 1504.0795919994812, 2664.017343 - 0.05, 21000.0, 0.8635603794883303, 10217.832863197733, 3505.378684800498, 2886.01878825 - 0.05, 21000.0, 0.9299881009874327, 12690.255665598383, 4869.68210400001, 3108.0202335 - 0.05, 21000.0, 0.9964158224865349, 20717.669268000252, 9070.129177600902, 3330.02167875 - 0.05, 24000.0, 0.0, 263.9917308599757, 263.9917308599757, 0.0 - 0.05, 24000.0, 0.3889573976660682, -2747.962127200054, -3334.670248000009, 1299.895623 - 0.05, 24000.0, 0.4537836306104128, -1687.356540800203, -2335.1570976000203, 1516.5448934999997 - 0.05, 24000.0, 0.5186098635547576, -626.7097768006313, -1335.6551584000363, 1733.1941639999998 - 0.05, 24000.0, 0.5834360964991023, 433.87318719989594, -336.15743119970176, 1949.8434344999998 - 0.05, 24000.0, 0.648262329443447, 3143.9980152003727, 952.8473424003423, 2166.4927049999997 - 0.05, 24000.0, 0.7130885623877916, 6284.657012000669, 2004.5825584004442, 2383.1419754999997 - 0.05, 24000.0, 0.7779147953321364, 7322.359334403292, 2223.9269887989576, 2599.791246 - 0.05, 24000.0, 0.8427410282764811, 9905.92378879997, 2188.0958360004597, 2816.4405165 - 0.05, 24000.0, 0.9075672612208256, 8487.754812803025, 2430.261232001468, 3033.0897869999994 - 0.05, 24000.0, 0.9723934941651704, 10105.103932006055, 3585.9838056030603, 3249.7390574999995 - 0.05, 27000.0, 0.0, 234.38277344848157, 234.38277344848157, 0.0 - 0.05, 27000.0, 0.3793493644524237, 22931.447128800115, 11532.861036000008, 1267.785576 - 0.05, 27000.0, 0.44257425852782767, 16521.53009840016, 8669.762336800008, 1479.083172 - 0.05, 27000.0, 0.5057991526032316, 10111.520655999933, 5806.60227199996, 1690.380768 - 0.05, 27000.0, 0.5690240466786355, 3701.5320287993823, 2943.4422071996933, 1901.6783639999999 - 0.05, 27000.0, 0.6322489407540395, -2626.5623496004064, -141.31583199991428, 2112.9759599999998 - 0.05, 27000.0, 0.6954738348294435, 3350.7104024006403, 356.18118719919494, 2324.273556 - 0.05, 27000.0, 0.7586987289048474, 3285.400167202547, 427.32905599995183, 2535.571152 - 0.05, 27000.0, 0.8219236229802513, 1028.7607800030892, 2045.9029448004476, 2746.868748 - 0.05, 27000.0, 0.8851485170556553, 10204.392964805276, 2577.580525602925, 2958.166344 - 0.05, 27000.0, 0.9483734111310592, 1146.70465359841, 3424.544991202748, 3169.46394 - 0.05, 30000.0, 0.0, 207.46141767148293, 207.46141767148293, 0.0 - 0.05, 30000.0, 0.3697404331238779, -109.33730000020205, 1478.25049999994, 1235.6725275 - 0.05, 30000.0, 0.4313638386445242, 1570.1974999998001, 1424.7061999998389, 1441.6179487499999 - 0.05, 30000.0, 0.49298724416517054, 3249.19040000033, 1371.3333999996703, 1647.5633699999998 - 0.05, 30000.0, 0.5546106496858169, 4928.461400000473, 1317.8605000000866, 1853.5087912499998 - 0.05, 30000.0, 0.6162340552064631, 4116.789099999579, 266.26629999940724, 2059.4542125 - 0.05, 30000.0, 0.6778574607271095, -612.2554999978711, 406.93060000118476, 2265.39963375 - 0.05, 30000.0, 0.7394808662477558, 1491.7724999983147, -206.13820000002852, 2471.345055 - 0.05, 30000.0, 0.801104271768402, 3295.7065999993756, -1231.193500000736, 2677.2904762499998 - 0.05, 30000.0, 0.8627276772890484, 12370.150599998626, 5613.435199999098, 2883.2358974999997 - 0.05, 30000.0, 0.9243510828096947, 24896.868800007083, 4169.043399994513, 3089.1813187499997 - 0.05, 30000.0, 0.9859744883303411, 49261.19940000991, 10598.273799987335, 3295.1267399999997 - 0.05, 33000.0, 0.0, 183.04255227548572, 183.04255227548572, 0.0 - 0.05, 33000.0, 0.3601323999102334, 57217.343818399924, 6462.072042399937, 1203.5624805 - 0.05, 33000.0, 0.42015446656193894, 44718.897576799376, 4942.357114400042, 1404.15622725 - 0.05, 33000.0, 0.48017653321364456, 32220.345998398952, 3422.6348784002153, 1604.749974 - 0.05, 33000.0, 0.5401985998653501, 19721.768598399525, 1903.0035631998846, 1805.34372075 - 0.05, 33000.0, 0.6002206665170557, 7223.1322471996955, 383.1977143994138, 2005.9374675000001 - 0.05, 33000.0, 0.6602427331687613, -1714.2249415997085, -318.24391119986103, 2206.53121425 - 0.05, 33000.0, 0.7202647998204668, 9696.97021759965, 3766.076648799335, 2407.124961 - 0.05, 33000.0, 0.7802868664721724, 8800.633575201666, 3135.405660000881, 2607.7187077500002 - 0.05, 33000.0, 0.8403089331238779, -3143.1828664080604, -2751.989865602409, 2808.3124545 - 0.05, 33000.0, 0.9003309997755836, 3650.193898396974, 1749.952720797708, 3008.9062012500003 - 0.05, 33000.0, 0.9603530664272891, -41981.766809608176, -27546.718622409186, 3209.499948 - 0.05, 36000.0, 0.0, 160.95228865653291, 160.95228865653291, 0.0 - 0.05, 36000.0, 0.3505234685816876, 54083.27970000006, 4792.784600000039, 1171.449432 - 0.05, 36000.0, 0.40894404667863554, 42879.20929999936, 3942.496200000078, 1366.691004 - 0.05, 36000.0, 0.46736462477558344, 31674.8617999979, 3092.207800000253, 1561.932576 - 0.05, 36000.0, 0.5257852028725314, 20470.73539999975, 2241.9479999997834, 1757.1741479999998 - 0.05, 36000.0, 0.5842057809694794, 9266.508899999362, 1391.5672999995181, 1952.41572 - 0.05, 36000.0, 0.6426263590664273, 1420.9881999994286, 498.8894000005236, 2147.657292 - 0.05, 36000.0, 0.7010469371633752, 1098.6751000008371, 214.43559999949366, 2342.898864 - 0.05, 36000.0, 0.7594675152603231, -16849.840799998157, -2203.470900000322, 2538.1404359999997 - 0.05, 36000.0, 0.8178880933572711, 38222.791599989054, 8790.296900003581, 2733.382008 - 0.05, 36000.0, 0.876308671454219, 13946.345999998986, 4859.685299998545, 2928.62358 - 0.05, 36000.0, 0.9347292495511669, -18581.36350000577, -18345.44450000399, 3123.865152 - 0.05, 39000.0, 0.0, 139.3968451913803, 139.3968451913803, 0.0 - 0.05, 39000.0, 0.350237868043088, 297.757299999859, 18.414899999952333, 1170.4949550000001 - 0.05, 39000.0, 0.4086108460502693, -246.14830000040837, -51.46400000004387, 1365.5774475 - 0.05, 39000.0, 0.46698382405745065, -790.2804000019916, -121.33510000014391, 1560.65994 - 0.05, 39000.0, 0.525356802064632, -1334.2551000009205, -191.14250000017324, 1755.7424325 - 0.05, 39000.0, 0.5837297800718133, -1878.366299999376, -260.9849999999968, 1950.824925 - 0.05, 39000.0, 0.6421027580789946, -3177.8280000008413, -503.2264999995277, 2145.9074175 - 0.05, 39000.0, 0.700475736086176, 147.0693999971736, 104.10470000056785, 2340.9899100000002 - 0.05, 39000.0, 0.7588487140933573, -3416.964799997586, -1402.6942999996454, 2536.0724025 - 0.05, 39000.0, 0.8172216921005386, 6216.859300000682, -3200.3317999969577, 2731.154895 - 0.05, 39000.0, 0.8755946701077199, 10314.047300004764, 3770.8095000044123, 2926.2373875 - 0.05, 39000.0, 0.9339676481149013, 95822.42960000428, 54546.04500000883, 3121.31988 - 0.05, 42000.0, 0.0, 120.67904739736119, 120.67904739736119, 0.0 - 0.05, 42000.0, 0.350237868043088, -379307.7606125012, -145962.87767500032, 1170.4949550000001 - 0.05, 42000.0, 0.4086108460502693, -297621.68383750133, -114274.11562500028, 1365.5774475 - 0.05, 42000.0, 0.46698382405745065, -215935.67748750158, -82585.31414375041, 1560.65994 - 0.05, 42000.0, 0.525356802064632, -134249.78061249654, -50896.46209375078, 1755.7424325 - 0.05, 42000.0, 0.5837297800718133, -52563.78404999875, -19207.791393750365, 1950.824925 - 0.05, 42000.0, 0.6421027580789946, -14077.329793750476, -4743.836325000113, 2145.9074175 - 0.05, 42000.0, 0.700475736086176, 7763.2552124993745, 869.3884437504009, 2340.9899100000002 - 0.05, 42000.0, 0.7588487140933573, -9094.635568750207, -55.98124999876745, 2536.0724025 - 0.05, 42000.0, 0.8172216921005386, 20796.75561250199, 11430.454387500024, 2731.154895 - 0.05, 42000.0, 0.8755946701077199, -8526.098524998582, -3736.200024997728, 2926.2373875 - 0.05, 42000.0, 0.9339676481149013, 16729.975118757982, 12533.790800006158, 3121.31988 - 0.1, 0.0, 0.0, 625.2082401190163, 625.2082401190163, 0.0 - 0.1, 0.0, 0.46652364452423695, -2011.8833999999993, -99.3087000000001, 1559.1220199999998 - 0.1, 0.0, 0.5442775852782764, 630.3653000000087, 552.14, 1818.9756899999998 - 0.1, 0.0, 0.6220315260323159, 3272.6143000000093, 1203.5886999999977, 2078.8293599999997 - 0.1, 0.0, 0.6997854667863553, 6125.41890000003, 1899.5097999999746, 2338.6830299999997 - 0.1, 0.0, 0.7775394075403949, 9521.64749999987, 2845.689899999991, 2598.5366999999997 - 0.1, 0.0, 0.8552933482944344, 13855.2959, 4165.00540000004, 2858.3903699999996 - 0.1, 0.0, 0.9330472890484739, 19628.417999999874, 5975.702099999982, 3118.2440399999996 - 0.1, 3000.0, 0.0, 566.2082978816558, 566.2082978816558, 0.0 - 0.1, 3000.0, 0.45690120646319565, -2313.858908054023, -177.01747961324494, 1526.963832 - 0.1, 3000.0, 0.5330514075403949, 193.16308879568584, 421.9886124946206, 1781.457804 - 0.1, 3000.0, 0.6092016086175942, 2700.1851220770013, 1020.9947294587513, 2035.9517759999999 - 0.1, 3000.0, 0.6853518096947936, 5250.776911976781, 1639.6440126681327, 2290.445748 - 0.1, 3000.0, 0.7615020107719928, 8308.462378657994, 2467.4811311975077, 2544.93972 - 0.1, 3000.0, 0.837652211849192, 12111.905933439019, 3595.1033628732494, 2799.4336919999996 - 0.1, 3000.0, 0.9138024129263913, 17311.674484508192, 5179.058747362689, 3053.927664 - 0.1, 3000.0, 0.9899526140035907, 23690.67883839665, 7160.928613317563, 3308.421636 - 0.1, 6000.0, 0.0, 511.6951552602684, 511.6951552602684, 0.0 - 0.1, 6000.0, 0.44727786894075405, -2534.251500000002, -256.57050000000027, 1494.8026380000001 - 0.1, 6000.0, 0.5218241804308797, -211.1178000000086, 297.40659999999843, 1743.9364110000001 - 0.1, 6000.0, 0.5963704919210054, 2112.016099999982, 851.3837999999968, 1993.0701840000002 - 0.1, 6000.0, 0.6709168034111311, 4435.149400000046, 1405.3610000000385, 2242.203957 - 0.1, 6000.0, 0.7454631149012568, 7123.782200000019, 2122.0649000000017, 2491.33773 - 0.1, 6000.0, 0.8200094263913825, 10496.662100000101, 3109.141799999993, 2740.471503 - 0.1, 6000.0, 0.8945557378815081, 14965.501000000098, 4455.733900000038, 2989.6052760000002 - 0.1, 6000.0, 0.9691020493716338, 20653.14060000009, 6216.630900000005, 3238.7390490000003 - 0.1, 9000.0, 0.0, 461.4143496154138, 461.4143496154138, 0.0 - 0.1, 9000.0, 0.4376554308797127, -2541.0796, -310.5673, 1462.6444499999998 - 0.1, 9000.0, 0.5105980026929982, -442.10060000000067, 195.12520000000004, 1706.4185249999998 - 0.1, 9000.0, 0.5835405745062836, 1656.8783999999987, 700.8176999999998, 1950.1925999999999 - 0.1, 9000.0, 0.656483146319569, 3755.8574000000044, 1206.5102999999988, 2193.9666749999997 - 0.1, 9000.0, 0.7294257181328545, 6110.102999999994, 1819.8495000000003, 2437.74075 - 0.1, 9000.0, 0.80236828994614, 9037.512700000003, 2663.9382000000014, 2681.5148249999997 - 0.1, 9000.0, 0.8753108617594254, 12865.362299999997, 3816.2123999999976, 2925.2888999999996 - 0.1, 9000.0, 0.9482534335727109, 17810.1504, 5327.397900000005, 3169.062975 - 0.1, 12000.0, 0.0, 415.11619174472565, 415.11619174472565, 0.0 - 0.1, 12000.0, 0.4280320933572711, -3536.912951999994, -348.3532856000002, 1430.483256 - 0.1, 12000.0, 0.4993707755834829, -1373.4686895999937, 108.10603120000133, 1668.8971319999998 - 0.1, 12000.0, 0.5707094578096947, 789.9805144000145, 564.5670224000042, 1907.311008 - 0.1, 12000.0, 0.6420481400359066, 2953.4273184000126, 1021.0286311999994, 2145.7248839999997 - 0.1, 12000.0, 0.7133868222621185, 5376.871477600019, 1566.419477600006, 2384.13876 - 0.1, 12000.0, 0.7847255044883303, 8124.962063199958, 2295.050403199987, 2622.552636 - 0.1, 12000.0, 0.8560641867145422, 10739.448999199909, 3200.65221439999, 2860.966512 - 0.1, 12000.0, 0.9274028689407541, 15355.029330400024, 4528.343394399963, 3099.380388 - 0.1, 12000.0, 0.9987415511669658, 20015.49159199992, 6050.922054400002, 3337.7942639999997 - 0.1, 15000.0, 0.0, 372.56703858988044, 372.56703858988044, 0.0 - 0.1, 15000.0, 0.4184096552962298, -2899.1604000000116, -571.0417000000004, 1398.325068 - 0.1, 15000.0, 0.48814459784560144, -1193.4852000000462, -116.439300000009, 1631.379246 - 0.1, 15000.0, 0.5578795403949731, 512.2158999998668, 338.17009999997555, 1864.433424 - 0.1, 15000.0, 0.6276144829443447, 2217.9079999999267, 792.7724999999884, 2097.487602 - 0.1, 15000.0, 0.6973494254937164, 3920.2631999998775, 1137.1745999998623, 2330.54178 - 0.1, 15000.0, 0.7670843680430879, 7199.866299999964, 1975.6096999998085, 2563.595958 - 0.1, 15000.0, 0.8368193105924596, 8379.474099999994, 2608.4565000000475, 2796.650136 - 0.1, 15000.0, 0.9065542531418312, 16168.369900000678, 4441.337700000001, 3029.704314 - 0.1, 15000.0, 0.9762891956912029, 10308.451100000098, 4306.532599999886, 3262.758492 - 0.1, 18000.0, 0.0, 333.53970294374477, 333.53970294374477, 0.0 - 0.1, 18000.0, 0.4087863177737881, -9788.776232799933, -1769.3549863999924, 1366.1638739999999 - 0.1, 18000.0, 0.47691737073608614, -6203.259029600001, -1020.9038471999805, 1593.857853 - 0.1, 18000.0, 0.5450484236983841, -2617.7170264000206, -272.4812767999553, 1821.5518319999999 - 0.1, 18000.0, 0.6131794766606822, 967.8267135998315, 475.94739439978537, 2049.245811 - 0.1, 18000.0, 0.6813105296229802, 2611.2808031999007, 978.0446944000453, 2276.93979 - 0.1, 18000.0, 0.7494415825852783, 4255.159712800536, 1348.6968440001574, 2504.633769 - 0.1, 18000.0, 0.8175726355475762, 7612.584242399513, 1985.0263095996686, 2732.3277479999997 - 0.1, 18000.0, 0.8857036885098742, 7486.39750639966, 2532.255948000171, 2960.021727 - 0.1, 18000.0, 0.9538347414721723, 21206.83883200227, 4972.578097599593, 3187.715706 - 0.1, 21000.0, 0.0, 297.8138675873782, 297.8138675873782, 0.0 - 0.1, 21000.0, 0.39916387971274686, 927.9313496000241, 1411.7156568000032, 1334.005686 - 0.1, 21000.0, 0.4656911929982047, 1530.8667488000458, 1246.3805455999952, 1556.3399670000001 - 0.1, 21000.0, 0.5322185062836625, 2133.82950319997, 1081.0515352000098, 1778.674248 - 0.1, 21000.0, 0.5987458195691203, 2736.7746752002636, 915.6991383999566, 2001.008529 - 0.1, 21000.0, 0.6652731328545781, 3334.3694368001447, 922.0845887999857, 2223.34281 - 0.1, 21000.0, 0.7318004461400359, 2118.5667728008425, 1028.2248384000904, 2445.677091 - 0.1, 21000.0, 0.7983277594254937, 5682.667971200344, 1652.3594519996477, 2668.011372 - 0.1, 21000.0, 0.8648550727109515, 9678.700175198457, 3284.279992800378, 2890.345653 - 0.1, 21000.0, 0.9313823859964094, 12027.24358159884, 4472.147044000036, 3112.6799340000002 - 0.1, 21000.0, 0.9979096992818672, 17995.243828000264, 7578.1478936005715, 3335.014215 - 0.1, 24000.0, 0.0, 265.18088101750504, 265.18088101750504, 0.0 - 0.1, 24000.0, 0.38954054219030526, -3017.821735200037, -2577.092508000005, 1301.8444920000002 - 0.1, 24000.0, 0.4544639658886894, -1841.3050128001446, -1756.1777216000125, 1518.8185740000001 - 0.1, 24000.0, 0.5193873895870736, -664.7590688004458, -935.270714400022, 1735.792656 - 0.1, 24000.0, 0.5843108132854579, 511.7418951999231, -114.36703919979641, 1952.766738 - 0.1, 24000.0, 0.649234236983842, 2811.075483200248, 898.2858784002192, 2169.74082 - 0.1, 24000.0, 0.7141576606822263, 5487.854352000431, 1772.8944544002939, 2386.714902 - 0.1, 24000.0, 0.7790810843806105, 6695.0670304022915, 2076.138700799292, 2603.6889840000003 - 0.1, 24000.0, 0.8440045080789946, 9078.89544079998, 2232.9741560003217, 2820.663066 - 0.1, 24000.0, 0.9089279317773789, 8740.784044802118, 2643.1322520010326, 3037.6371480000003 - 0.1, 24000.0, 0.973851355475763, 10632.689832004275, 3783.039529602125, 3254.61123 - 0.1, 27000.0, 0.0, 235.43855012398765, 235.43855012398765, 0.0 - 0.1, 27000.0, 0.3799181041292639, 15827.530820800092, 8247.896836000007, 1269.686304 - 0.1, 27000.0, 0.4432377881508079, 11485.00185440013, 6244.882188800003, 1481.300688 - 0.1, 27000.0, 0.5065574721723519, 7142.404875999978, 4241.821951999971, 1692.915072 - 0.1, 27000.0, 0.5698771561938959, 2799.823420799544, 2238.761715199774, 1904.529456 - 0.1, 27000.0, 0.6331968402154399, -1446.0071736003028, 89.49722800007748, 2116.14384 - 0.1, 27000.0, 0.6965165242369838, 3193.342578400463, 525.5966151994144, 2327.758224 - 0.1, 27000.0, 0.7598362082585278, 3581.758115201774, 714.2247359999725, 2539.372608 - 0.1, 27000.0, 0.8231558922800718, 2379.170800002188, 2047.1357968003167, 2750.986992 - 0.1, 27000.0, 0.8864755763016158, 9673.63379680392, 2621.606589602129, 2962.601376 - 0.1, 27000.0, 0.9497952603231598, 3357.267337598957, 3398.0692592020064, 3174.21576 - 0.1, 30000.0, 0.0, 208.39592716047972, 208.39592716047972, 0.0 - 0.1, 30000.0, 0.37029476660682226, -571.878200000151, 987.1350999999564, 1237.52511 - 0.1, 30000.0, 0.43201056104129265, 906.9155999998543, 1013.5340999998823, 1443.779295 - 0.1, 30000.0, 0.49372635547576305, 2385.29680000026, 1040.0629999997593, 1650.03348 - 0.1, 30000.0, 0.5554421499102334, 3863.889300000365, 1066.5159000000576, 1856.287665 - 0.1, 30000.0, 0.6171579443447038, 3474.2748999996747, 344.3792999995592, 2062.54185 - 0.1, 30000.0, 0.6788737387791742, 18.95260000160397, 493.291300000898, 2268.7960350000003 - 0.1, 30000.0, 0.7405895332136445, 1969.5103999987045, 132.61349999998208, 2475.05022 - 0.1, 30000.0, 0.8023053276481149, 3700.863899999357, -519.5609000006107, 2681.304405 - 0.1, 30000.0, 0.8640211220825853, 10959.752299999, 4812.414299999331, 2887.55859 - 0.1, 30000.0, 0.9257369165170558, 21054.53140000521, 3993.446599995782, 3093.8127750000003 - 0.1, 30000.0, 0.9874527109515261, 40095.13330000725, 9195.802199990372, 3300.06696 - 0.1, 33000.0, 0.0, 183.86706704026236, 183.86706704026236, 0.0 - 0.1, 33000.0, 0.36067232854578096, 43687.42464639996, 4856.1138903999545, 1205.366922 - 0.1, 33000.0, 0.4207843833034111, 34207.31479279952, 3738.626262400031, 1406.261409 - 0.1, 33000.0, 0.48089643806104126, 24727.12258639917, 2621.132486400157, 1607.155896 - 0.1, 33000.0, 0.5410084928186715, 15246.910706399654, 1503.70896719991, 1808.050383 - 0.1, 33000.0, 0.6011205475763016, 5766.653331199744, 386.15108239957067, 2008.94487 - 0.1, 33000.0, 0.6612326023339318, -903.5494535997732, -79.45113519989218, 2209.839357 - 0.1, 33000.0, 0.7213446570915619, 8126.707469599733, 3135.3974647995365, 2410.733844 - 0.1, 33000.0, 0.7814567118491921, 7733.798859201299, 2735.111420000656, 2611.628331 - 0.1, 33000.0, 0.8415687666068222, -1066.133674405919, -1643.2512776016938, 2812.522818 - 0.1, 33000.0, 0.9016808213644524, 4131.562286397973, 1761.128736798335, 3013.417305 - 0.1, 33000.0, 0.9617928761220825, -31625.246981605524, -21203.411290406788, 3214.311792 - 0.1, 36000.0, 0.0, 161.6772978785534, 161.6772978785534, 0.0 - 0.1, 36000.0, 0.3510489910233393, 41090.522300000055, 3556.3316000000327, 1173.205728 - 0.1, 36000.0, 0.4095571561938959, 32625.619599999514, 2950.6852000000613, 1368.740016 - 0.1, 36000.0, 0.46806532136445245, 24160.50249999836, 2345.0388000001926, 1564.274304 - 0.1, 36000.0, 0.526573486535009, 15695.556899999803, 1739.4143999998284, 1759.808592 - 0.1, 36000.0, 0.5850816517055656, 7230.533299999508, 1133.6965999996314, 1955.3428800000002 - 0.1, 36000.0, 0.643589816876122, 1364.1155999995503, 494.616100000404, 2150.877168 - 0.1, 36000.0, 0.7020979820466786, 1268.3249000006144, 324.23969999956853, 2346.411456 - 0.1, 36000.0, 0.7606061472172352, -12394.298899998597, -1466.3963000002295, 2541.945744 - 0.1, 36000.0, 0.8191143123877918, 30619.60469999179, 7126.412500002727, 2737.480032 - 0.1, 36000.0, 0.8776224775583483, 12129.063899999252, 4292.991999998852, 2933.01432 - 0.1, 36000.0, 0.9361306427289049, -13311.96980000427, -13772.927200003138, 3128.548608 - 0.1, 39000.0, 0.0, 140.0247579668238, 140.0247579668238, 0.0 - 0.1, 39000.0, 0.3507629622980251, 92.95119999989765, -57.51740000003838, 1172.24982 - 0.1, 39000.0, 0.40922345601436266, -270.2002000002934, -79.79780000003927, 1367.62479 - 0.1, 39000.0, 0.4676839497307002, -633.5255000014547, -102.0716000001247, 1562.9997600000002 - 0.1, 39000.0, 0.5261444434470378, -996.728700000728, -124.29600000013255, 1758.3747300000002 - 0.1, 39000.0, 0.5846049371633754, -1360.0384999995274, -146.5478000000005, 1953.7497000000003 - 0.1, 39000.0, 0.6430654308797128, -2307.8725000006643, -315.05359999964435, 2149.12467 - 0.1, 39000.0, 0.7015259245960502, 446.4423999978226, 207.393200000427, 2344.49964 - 0.1, 39000.0, 0.7599864183123879, -2130.3115999981565, -884.7197999997097, 2539.8746100000003 - 0.1, 39000.0, 0.8184469120287253, 5624.611300000615, -2225.959799997656, 2735.24958 - 0.1, 39000.0, 0.876907405745063, 8977.310800003586, 3289.4589000034102, 2930.6245500000005 - 0.1, 39000.0, 0.9353678994614004, 75013.8125000032, 42558.82880000677, 3125.9995200000003 - 0.1, 42000.0, 0.0, 121.22264589476711, 121.22264589476711, 0.0 - 0.1, 42000.0, 0.3507629622980251, -306857.214587501, -118020.50972500029, 1172.24982 - 0.1, 42000.0, 0.40922345601436266, -240760.67613750108, -92393.28337500025, 1367.62479 - 0.1, 42000.0, 0.4676839497307002, -174664.1926875013, -66766.02593125033, 1562.9997600000002 - 0.1, 42000.0, 0.5261444434470378, -108567.79788749729, -41138.72770625061, 1758.3747300000002 - 0.1, 42000.0, 0.5846049371633754, -42471.32287499902, -15511.574481250282, 1953.7497000000003 - 0.1, 42000.0, 0.6430654308797128, -11125.219006250369, -3727.2074500001227, 2149.12467 - 0.1, 42000.0, 0.7015259245960502, 6419.422362499474, 806.7819562503171, 2344.49964 - 0.1, 42000.0, 0.7599864183123879, -6860.386856250087, 91.40070000099331, 2539.8746100000003 - 0.1, 42000.0, 0.8184469120287253, 17132.477837501516, 9318.980712500015, 2735.24958 - 0.1, 42000.0, 0.876907405745063, -5909.965074998996, -2619.3184999982404, 2930.6245500000005 - 0.1, 42000.0, 0.9353678994614004, 14914.661481256073, 10745.344975004875, 3125.9995200000003 - 0.15000000000000002, 0.0, 0.0, 629.8996281297979, 629.8996281297979, 0.0 - 0.15000000000000002, 0.0, 0.4676876256732495, -1595.5012000000004, -74.09410000000001, 1563.012045 - 0.15000000000000002, 0.0, 0.5456355632854578, 705.9526000000034, 574.9103999999979, 1823.5140525 - 0.15000000000000002, 0.0, 0.623583500897666, 3007.406500000004, 1223.9147999999923, 2084.01606 - 0.15000000000000002, 0.0, 0.7015314385098743, 5609.046899999981, 1922.9932999999915, 2344.5180675 - 0.15000000000000002, 0.0, 0.7794793761220825, 8876.089799999943, 2883.797399999987, 2605.020075 - 0.15000000000000002, 0.0, 0.8574273137342907, 13067.203099999975, 4221.34909999999, 2865.5220824999997 - 0.15000000000000002, 0.0, 0.935375251346499, 18695.761699999897, 6062.876999999946, 3126.02409 - 0.15000000000000002, 3000.0, 0.0, 570.4569668047991, 570.4569668047991, 0.0 - 0.15000000000000002, 3000.0, 0.4580411795332136, -2181.3472891817923, -165.77451829906997, 1530.773622 - 0.15000000000000002, 3000.0, 0.5343813761220826, 124.06477920695296, 435.77105681481623, 1785.9025589999999 - 0.15000000000000002, 3000.0, 0.6107215727109515, 2429.4768844882688, 1037.3165467991184, 2041.0314959999998 - 0.15000000000000002, 3000.0, 0.6870617692998204, 4789.78216733112, 1661.2813600811971, 2296.160433 - 0.15000000000000002, 3000.0, 0.7634019658886894, 7712.867227276924, 2500.2356125440488, 2551.28937 - 0.15000000000000002, 3000.0, 0.8397421624775583, 11398.747732624584, 3645.975555671739, 2806.418307 - 0.15000000000000002, 3000.0, 0.9160823590664272, 16460.686836097182, 5252.5780265567855, 3061.547244 - 0.15000000000000002, 3000.0, 0.9924225556552961, 22616.30261168905, 7246.400828948473, 3316.676181 - 0.15000000000000002, 6000.0, 0.0, 515.5347727869121, 515.5347727869121, 0.0 - 0.15000000000000002, 6000.0, 0.44839383168761227, -2318.263399999999, -239.7174, 1498.5321855000002 - 0.15000000000000002, 6000.0, 0.523126136968881, -200.21429999999452, 314.3302000000002, 1748.2875497500002 - 0.15000000000000002, 6000.0, 0.5978584422501496, 1917.8348000000158, 868.3776999999989, 1998.042914 - 0.15000000000000002, 6000.0, 0.6725907475314185, 4035.8837999999832, 1422.4252999999953, 2247.7982782500003 - 0.15000000000000002, 6000.0, 0.7473230528126871, 6617.027800000002, 2149.8712999999966, 2497.5536425 - 0.15000000000000002, 6000.0, 0.8220553580939558, 9875.911099999976, 3152.006099999995, 2747.30900675 - 0.15000000000000002, 6000.0, 0.8967876633752245, 14248.810499999892, 4521.647499999981, 2997.0643710000004 - 0.15000000000000002, 6000.0, 0.9715199686564931, 19754.517599999926, 6301.743199999965, 3246.81973525 - 0.15000000000000002, 9000.0, 0.0, 464.87667402012113, 464.87667402012113, 0.0 - 0.15000000000000002, 9000.0, 0.4387473855475763, -2540.3364000000015, -308.14290000000017, 1466.2937625 - 0.15000000000000002, 9000.0, 0.5118719498055057, -555.763999999999, 201.76619999999988, 1710.6760562499999 - 0.15000000000000002, 9000.0, 0.584996514063435, 1428.808600000002, 711.6751999999983, 1955.0583499999998 - 0.15000000000000002, 9000.0, 0.6581210783213644, 3413.381299999983, 1221.5841999999934, 2199.4406437499997 - 0.15000000000000002, 9000.0, 0.7312456425792937, 5666.968299999971, 1844.6710999999873, 2443.8229374999996 - 0.15000000000000002, 9000.0, 0.804370206837223, 8495.826200000007, 2700.310799999986, 2688.2052312499995 - 0.15000000000000002, 9000.0, 0.8774947710951526, 12251.267599999976, 3875.458299999995, 2932.587525 - 0.15000000000000002, 9000.0, 0.950619335353082, 17028.86519999999, 5402.095699999995, 3176.96981875 - 0.15000000000000002, 12000.0, 0.0, 418.23110770402536, 418.23110770402536, 0.0 - 0.15000000000000002, 12000.0, 0.42910003770197486, -2305.4088519999987, -294.86455760000007, 1434.052326 - 0.15000000000000002, 12000.0, 0.500616710652304, -587.812881599999, 150.6742552000002, 1673.061047 - 0.15000000000000002, 12000.0, 0.5721333836026331, 1129.7842224000021, 596.2134904000005, 1912.0697679999998 - 0.15000000000000002, 12000.0, 0.6436500565529623, 2847.380806400004, 1041.7528752000007, 2151.078489 - 0.15000000000000002, 12000.0, 0.7151667295032913, 4844.310969600002, 1569.321629600002, 2390.0872099999997 - 0.15000000000000002, 12000.0, 0.7866834024536206, 7393.286047199999, 2307.7492471999963, 2629.095931 - 0.15000000000000002, 12000.0, 0.8582000754039497, 10501.281363200009, 3290.8157423999987, 2868.104652 - 0.15000000000000002, 12000.0, 0.9297167483542788, 14658.189338400009, 4591.318162400003, 3107.1133729999997 - 0.15000000000000002, 15000.0, 0.0, 375.36267758804877, 375.36267758804877, 0.0 - 0.15000000000000002, 15000.0, 0.41945359156193895, -2520.8392000000063, -451.0395000000004, 1401.813903 - 0.15000000000000002, 15000.0, 0.48936252348892884, -931.7766000000236, -18.371500000005252, 1635.4495535 - 0.15000000000000002, 15000.0, 0.5592714554159186, 657.2992999999323, 414.30009999998543, 1869.085204 - 0.15000000000000002, 15000.0, 0.6291803873429084, 2246.3705999999597, 846.9680999999999, 2102.7208545 - 0.15000000000000002, 15000.0, 0.6990893192698981, 3880.9720999999263, 1245.6378999999426, 2336.3565049999997 - 0.15000000000000002, 15000.0, 0.7689982511968881, 6536.210299999967, 1973.7554999999015, 2569.9921555 - 0.15000000000000002, 15000.0, 0.8389071831238779, 8392.314099999989, 2716.585600000013, 2803.627806 - 0.15000000000000002, 15000.0, 0.9088161150508677, 14170.508800000393, 4219.588499999971, 3037.2634565 - 0.15000000000000002, 15000.0, 0.9787250469778577, 13079.827900000022, 4844.291799999926, 3270.899107 - 0.15000000000000002, 18000.0, 0.0, 336.0424917157098, 336.0424917157098, 0.0 - 0.15000000000000002, 18000.0, 0.40980624371633745, -6865.768600799958, -1234.3722103999953, 1369.5724664999998 - 0.15000000000000002, 18000.0, 0.4781072843357271, -4148.296485599993, -627.0506591999892, 1597.83454425 - 0.15000000000000002, 18000.0, 0.5464083249551166, -1430.8092903999986, -19.7463447999778, 1826.0966219999998 - 0.15000000000000002, 18000.0, 0.6147093655745062, 1286.6786495998972, 587.561838399872, 2054.3586997499997 - 0.15000000000000002, 18000.0, 0.6830104061938959, 2829.580855199914, 1049.714018400027, 2282.6207775 - 0.15000000000000002, 18000.0, 0.7513114468132854, 4487.85344080036, 1490.0790240000913, 2510.88285525 - 0.15000000000000002, 18000.0, 0.8196124874326749, 7344.145386399712, 2145.268385599801, 2739.1449329999996 - 0.15000000000000002, 18000.0, 0.8879135280520646, 8374.398930399811, 2847.7599480000604, 2967.4070107499997 - 0.15000000000000002, 18000.0, 0.9562145686714542, 18054.61251200129, 4806.923773599721, 3195.6690885 - 0.15000000000000002, 21000.0, 0.0, 300.04857966919246, 300.04857966919246, 0.0 - 0.15000000000000002, 21000.0, 0.4001597975763016, -395.59913439998513, 732.6920848000025, 1337.3340435 - 0.15000000000000002, 21000.0, 0.46685309717235185, 476.13615680002414, 758.0538815999962, 1560.2230507499999 - 0.15000000000000002, 21000.0, 0.5335463967684021, 1347.8891551999695, 783.4195472000034, 1783.112058 - 0.15000000000000002, 21000.0, 0.6002396963644524, 2219.6311672001702, 808.7698623999845, 2006.00106525 - 0.15000000000000002, 21000.0, 0.6669329959605027, 3067.974004800082, 938.1528767999782, 2228.8900725 - 0.15000000000000002, 21000.0, 0.7336262955565529, 2816.9554208005247, 1172.638062400046, 2451.7790797499997 - 0.15000000000000002, 21000.0, 0.8003195951526032, 5736.527123200167, 1786.3473119997775, 2674.668087 - 0.15000000000000002, 21000.0, 0.8670128947486535, 9241.062667199014, 3136.890520800275, 2897.55709425 - 0.15000000000000002, 21000.0, 0.9337061943447037, 11521.471537599215, 4207.990584000048, 3120.4461014999997 - 0.15000000000000002, 24000.0, 0.0, 267.17072428261804, 267.17072428261804, 0.0 - 0.15000000000000002, 24000.0, 0.3905124497307002, -3119.5000232000234, -1959.3132680000026, 1305.092607 - 0.15000000000000002, 24000.0, 0.4555978580191502, -1883.0917048000972, -1283.0524856000065, 1522.6080415 - 0.15000000000000002, 24000.0, 0.5206832663076002, -646.6635808002998, -606.7968304000125, 1740.123476 - 0.15000000000000002, 24000.0, 0.5857686745960503, 589.7342831999448, 69.45627280013055, 1957.6389105 - 0.15000000000000002, 24000.0, 0.6508540828845003, 2543.7516312001544, 862.8719744001287, 2175.154345 - 0.15000000000000002, 24000.0, 0.7159394911729503, 4841.347192000255, 1597.8297104001808, 2392.6697795 - 0.15000000000000002, 24000.0, 0.7810248994614004, 6188.723186401513, 1972.5562327995472, 2610.185214 - 0.15000000000000002, 24000.0, 0.8461103077498504, 8417.353212799979, 2287.3539760002122, 2827.7006485 - 0.15000000000000002, 24000.0, 0.9111957160383004, 8916.145896801427, 2834.144372000686, 3045.216083 - 0.15000000000000002, 24000.0, 0.9762811243267504, 10974.383932002864, 3947.958193601398, 3262.7315175 - 0.15000000000000002, 27000.0, 0.0, 237.20521524522326, 237.20521524522326, 0.0 - 0.15000000000000002, 27000.0, 0.3808660035906642, 10189.283932800066, 5619.152736000004, 1272.8541839999998 - 0.15000000000000002, 27000.0, 0.4443436708557749, 7489.483670400098, 4305.916960800002, 1484.9965479999998 - 0.15000000000000002, 27000.0, 0.5078213381208857, 4789.635096000009, 2992.6484319999795, 1697.138912 - 0.15000000000000002, 27000.0, 0.5712990053859964, 2089.7977327996723, 1679.379903199837, 1909.281276 - 0.15000000000000002, 27000.0, 0.6347766726511072, -510.8828376002166, 276.4482880000653, 2121.42364 - 0.15000000000000002, 27000.0, 0.6982543399162178, 3060.00861440032, 669.020623199593, 2333.566004 - 0.15000000000000002, 27000.0, 0.7617320071813284, 3805.4205432011745, 952.091115999985, 2545.7083679999996 - 0.15000000000000002, 27000.0, 0.8252096744464392, 3453.048220001474, 2059.674868800212, 2757.850732 - 0.15000000000000002, 27000.0, 0.8886873417115498, 9214.581448802797, 2672.258393601492, 2969.9930959999997 - 0.15000000000000002, 27000.0, 0.9521650089766607, 5125.501961599364, 3407.1268072014045, 3182.13546 - 0.15000000000000002, 30000.0, 0.0, 209.95967199210608, 209.95967199210608, 0.0 - 0.15000000000000002, 30000.0, 0.3712186557450628, -967.3588000001105, 582.3463999999688, 1240.6127474999998 - 0.15000000000000002, 30000.0, 0.4330884317025733, 347.2769999998956, 675.5304999999167, 1447.38153875 - 0.15000000000000002, 30000.0, 0.49495820766008375, 1661.6072000001973, 768.8101999998297, 1654.15033 - 0.15000000000000002, 30000.0, 0.5568279836175942, 2976.093500000273, 862.0338000000352, 1860.91912125 - 0.15000000000000002, 30000.0, 0.6186977595751048, 2931.8843999997534, 410.82999999968274, 2067.6879125 - 0.15000000000000002, 30000.0, 0.6805675355326152, 545.8852000011739, 572.7082000006617, 2274.45670375 - 0.15000000000000002, 30000.0, 0.7424373114901256, 2359.7099999990287, 420.6579999999891, 2481.2254949999997 - 0.15000000000000002, 30000.0, 0.804307087447636, 4032.8177999993854, 78.49129999950446, 2687.9942862499997 - 0.15000000000000002, 30000.0, 0.8661768634051465, 9792.300499999297, 4164.313899999511, 2894.7630775 - 0.15000000000000002, 30000.0, 0.9280466393626571, 17824.3484000037, 3841.94529999685, 3101.53186875 - 0.15000000000000002, 30000.0, 0.9899164153201675, 32416.9565000051, 8003.051599992887, 3308.30066 - 0.15000000000000002, 33000.0, 0.0, 185.24675415655173, 185.24675415655173, 0.0 - 0.15000000000000002, 33000.0, 0.36157220960502695, 32364.60071439996, 3512.6477783999653, 1208.3743245 - 0.15000000000000002, 33000.0, 0.4218342445391981, 25411.04958879962, 2732.77825040002, 1409.77004525 - 0.15000000000000002, 33000.0, 0.48209627947336925, 18457.435514399338, 1952.9036344001117, 1611.165766 - 0.15000000000000002, 33000.0, 0.5423583144075405, 11503.806854399732, 1173.0819911999308, 1812.56148675 - 0.15000000000000002, 33000.0, 0.6026203493417116, 4550.143935199789, 393.15949039969667, 2013.9572075 - 0.15000000000000002, 33000.0, 0.6628823842758828, -232.55112559983718, 122.14862080008288, 2215.3529282500003 - 0.15000000000000002, 33000.0, 0.7231444192100539, 6810.178681599793, 2613.892160799697, 2416.748649 - 0.15000000000000002, 33000.0, 0.7834064541442249, 6838.791363200984, 2410.756280000477, 2618.14436975 - 0.15000000000000002, 33000.0, 0.8436684890783962, 651.0772775957994, -712.2164496011355, 2819.5400905 - 0.15000000000000002, 33000.0, 0.9039305240125675, 4571.670514398742, 1813.7719327988307, 3020.9358112500004 - 0.15000000000000002, 33000.0, 0.9641925589467385, -22795.109113603437, -15770.325198404862, 3222.331532 - 0.15000000000000002, 36000.0, 0.0, 162.89047916474146, 162.89047916474146, 0.0 - 0.15000000000000002, 36000.0, 0.35192486175942544, 30245.169900000037, 2522.2821000000245, 1176.1328879999999 - 0.15000000000000002, 36000.0, 0.4105790053859964, 24067.410899999617, 2122.294500000045, 1372.1550359999999 - 0.15000000000000002, 36000.0, 0.4692331490125673, 17889.489999998736, 1722.3069000001415, 1568.177184 - 0.15000000000000002, 36000.0, 0.5278872926391383, 11711.698999999831, 1322.3357999998664, 1764.199332 - 0.15000000000000002, 36000.0, 0.5865414362657091, 5533.848599999634, 922.2942999997248, 1960.22148 - 0.15000000000000002, 36000.0, 0.6451955798922799, 1317.7994999996508, 496.14320000030364, 2156.2436279999997 - 0.15000000000000002, 36000.0, 0.7038497235188509, 1419.4675000004427, 424.36749999963945, 2352.2657759999997 - 0.15000000000000002, 36000.0, 0.7625038671454218, -8648.140899998929, -838.9325000001536, 2548.2879239999997 - 0.15000000000000002, 36000.0, 0.8211580107719928, 24245.382599993958, 5747.28430000202, 2744.3100719999998 - 0.15000000000000002, 36000.0, 0.8798121543985636, 10584.679499999496, 3815.31629999911, 2940.33222 - 0.15000000000000002, 36000.0, 0.9384662980251346, -8883.050000003015, -9931.0064000024, 3136.354368 - 0.15000000000000002, 39000.0, 0.0, 141.07546464115214, 141.07546464115214, 0.0 - 0.15000000000000002, 39000.0, 0.35163811938958706, -131.41630000007183, -127.50600000003047, 1175.174595 - 0.15000000000000002, 39000.0, 0.4102444726211849, -331.6345000002014, -108.04630000003417, 1371.0370275 - 0.15000000000000002, 39000.0, 0.4688508258527828, -531.9828000010212, -88.58110000010522, 1566.89946 - 0.15000000000000002, 39000.0, 0.5274571790843806, -732.2386000005616, -69.07850000009851, 1762.7618925000002 - 0.15000000000000002, 39000.0, 0.5860635323159785, -932.5757999996501, -49.59680000000274, 1958.6243250000002 - 0.15000000000000002, 39000.0, 0.6446698855475764, -1573.411800000511, -151.9088999997399, 2154.4867575000003 - 0.15000000000000002, 39000.0, 0.7032762387791741, 702.400799998366, 300.67320000031214, 2350.34919 - 0.15000000000000002, 39000.0, 0.761882592010772, -1039.9345999986217, -443.3422999997647, 2546.2116225 - 0.15000000000000002, 39000.0, 0.8204889452423698, 5129.540000000539, -1394.9271999982398, 2742.074055 - 0.15000000000000002, 39000.0, 0.8790952984739677, 7861.528800002612, 2897.856600002564, 2937.9364875 - 0.15000000000000002, 39000.0, 0.9377016517055656, 57627.93950000226, 32544.422700005016, 3133.79892 - 0.15000000000000002, 42000.0, 0.0, 122.13226677160911, 122.13226677160911, 0.0 - 0.15000000000000002, 42000.0, 0.35163811938958706, -244342.14466250074, -93916.57837500022, 1175.174595 - 0.15000000000000002, 42000.0, 0.4102444726211849, -191697.7169375008, -73517.17732500022, 1371.0370275 - 0.15000000000000002, 42000.0, 0.4688508258527828, -139053.3311875009, -53117.752268750264, 1566.89946 - 0.15000000000000002, 42000.0, 0.5274571790843806, -86409.01606249786, -32718.294868750454, 1762.7618925000002 - 0.15000000000000002, 42000.0, 0.5860635323159785, -33764.637499999255, -12318.951318750222, 1958.6243250000002 - 0.15000000000000002, 42000.0, 0.6446698855475764, -8600.26376875029, -2854.88097500012, 2154.4867575000003 - 0.15000000000000002, 42000.0, 0.7032762387791741, 5271.145412499565, 754.2486187502542, 2350.34919 - 0.15000000000000002, 42000.0, 0.761882592010772, -4946.085293750068, 224.80105000077128, 2546.2116225 - 0.15000000000000002, 42000.0, 0.8204889452423698, 14003.032162501113, 7520.600137500009, 2742.074055 - 0.15000000000000002, 42000.0, 0.8790952984739677, -3691.5298249993357, -1665.9853749986542, 2937.9364875 - 0.15000000000000002, 42000.0, 0.9377016517055656, 13262.191193754406, 9169.165350003794, 3133.79892 - 0.2, 0.0, 0.0, 636.5069133156856, 636.5069133156856, 0.0 - 0.2, 0.0, 0.4693171992818671, -1542.0807000000013, -64.23610000000006, 1568.4580799999999 - 0.2, 0.0, 0.5475367324955116, 640.9626000000038, 593.1168999999926, 1829.8677599999999 - 0.2, 0.0, 0.6257562657091561, 2824.005899999999, 1250.4697999999769, 2091.27744 - 0.2, 0.0, 0.7039757989228006, 5274.056199999932, 1959.8085999999817, 2352.6871199999996 - 0.2, 0.0, 0.7821953321364452, 8355.228499999828, 2938.650899999966, 2614.0968 - 0.2, 0.0, 0.8604148653500898, 12458.0088, 4302.437499999974, 2875.50648 - 0.2, 0.0, 0.9386343985637342, 17981.37299999976, 6187.372099999855, 3136.9161599999998 - 0.2, 3000.0, 0.0, 576.4407326265805, 576.4407326265805, 0.0 - 0.2, 3000.0, 0.4596371418312387, -1929.1214185806396, -149.3436167180688, 1536.1073279999998 - 0.2, 3000.0, 0.5362433321364453, 191.11317695078907, 456.80206959578834, 1792.125216 - 0.2, 3000.0, 0.6128495224416516, 2311.3476922983014, 1062.947794255317, 2048.1431039999998 - 0.2, 3000.0, 0.689455712746858, 4495.356589577711, 1695.1622411824285, 2304.1609919999996 - 0.2, 3000.0, 0.7660619030520645, 7260.212017364856, 2547.1789124652673, 2560.1788799999995 - 0.2, 3000.0, 0.842668093357271, 10867.078763726378, 3720.4781029514843, 2816.196768 - 0.2, 3000.0, 0.9192742836624774, 15824.345569312045, 5357.960955607783, 3072.2146559999996 - 0.2, 3000.0, 0.9958804739676839, 21722.538066858622, 7363.900334681744, 3328.2325439999995 - 0.2, 6000.0, 0.0, 520.9424363493725, 520.9424363493725, 0.0 - 0.2, 6000.0, 0.4499561795332137, -2131.9149999999995, -225.72919999999996, 1503.7535520000001 - 0.2, 6000.0, 0.5249488761220826, -154.48559999998412, 333.12669999999974, 1754.379144 - 0.2, 6000.0, 0.5999415727109516, 1822.943700000052, 891.9825999999932, 2005.004736 - 0.2, 6000.0, 0.6749342692998205, 3805.0919999999605, 1453.3734999999926, 2255.630328 - 0.2, 6000.0, 0.7499269658886895, 6213.947300000026, 2191.1645999999864, 2506.25592 - 0.2, 6000.0, 0.8249196624775583, 9396.923799999935, 3213.3561999999943, 2756.881512 - 0.2, 6000.0, 0.8999123590664274, 13711.429699999668, 4618.513199999946, 3007.5071040000003 - 0.2, 6000.0, 0.9749050556552963, 19006.339799999892, 6419.63919999992, 3258.132696 - 0.2, 9000.0, 0.0, 469.7529632324795, 469.7529632324795, 0.0 - 0.2, 9000.0, 0.4402761220825853, -2245.991500000004, -296.7128000000004, 1471.4028 - 0.2, 9000.0, 0.5136554757630162, -424.35499999999854, 217.80809999999943, 1716.6366 - 0.2, 9000.0, 0.5870348294434471, 1397.281199999999, 732.3289999999951, 1961.8704 - 0.2, 9000.0, 0.660414183123878, 3218.9176999999613, 1246.8498999999854, 2207.1042 - 0.2, 9000.0, 0.7337935368043088, 5313.586399999949, 1879.8361999999693, 2452.338 - 0.2, 9000.0, 0.8071728904847397, 8076.6055000000415, 2752.6081999999706, 2697.5718 - 0.2, 9000.0, 0.8805522441651706, 11792.00679999996, 3960.0935000000063, 2942.8056 - 0.2, 9000.0, 0.9539315978456014, 16407.08400000003, 5508.865699999968, 3188.0394 - 0.2, 12000.0, 0.0, 422.6181117262611, 422.6181117262611, 0.0 - 0.2, 12000.0, 0.43059515978456014, -1917.4630520000003, -278.8931896, 1439.049024 - 0.2, 12000.0, 0.5023610197486534, -366.8472335999993, 169.3814992000001, 1678.890528 - 0.2, 12000.0, 0.5741268797127468, 1183.7683704000008, 617.6561984000002, 1918.732032 - 0.2, 12000.0, 0.6458927396768401, 2734.3841343999993, 1065.9308391999998, 2158.573536 - 0.2, 12000.0, 0.7176585996409335, 4538.604821600007, 1596.3367416, 2398.41504 - 0.2, 12000.0, 0.7894244596050269, 6956.8339511999875, 2348.9991112000002, 2638.256544 - 0.2, 12000.0, 0.8611903195691203, 10168.983847199988, 3370.5824104000035, 2878.098048 - 0.2, 12000.0, 0.9329561795332136, 14116.282186399978, 4685.484970399994, 3117.939552 - 0.2, 15000.0, 0.0, 379.30001640872143, 379.30001640872143, 0.0 - 0.2, 15000.0, 0.4209151023339318, -2268.5890000000027, -370.22420000000034, 1406.698272 - 0.2, 15000.0, 0.49106761938958704, -770.503400000009, 49.94019999999748, 1641.147984 - 0.2, 15000.0, 0.5612201364452424, 727.5876999999736, 470.1060999999929, 1875.597696 - 0.2, 15000.0, 0.6313726535008977, 2225.6768999999827, 890.2705000000028, 2110.047408 - 0.2, 15000.0, 0.701525170556553, 3812.9711999999613, 1327.0541999999837, 2344.49712 - 0.2, 15000.0, 0.7716776876122082, 6078.449699999975, 1998.1453999999608, 2578.946832 - 0.2, 15000.0, 0.8418302046678636, 8357.957399999987, 2820.0413999999987, 2813.396544 - 0.2, 15000.0, 0.9119827217235189, 12805.633300000201, 4119.654899999968, 3047.8462560000003 - 0.2, 15000.0, 0.9821352387791741, 14580.073799999982, 5206.180199999959, 3282.295968 - 0.2, 18000.0, 0.0, 339.5673843782666, 339.5673843782666, 0.0 - 0.2, 18000.0, 0.41123414003590664, -4772.187288799978, -846.5507943999977, 1374.344496 - 0.2, 18000.0, 0.47977316337522435, -2684.1085815999927, -339.5095511999953, 1603.4019119999998 - 0.2, 18000.0, 0.5483121867145422, -596.0216143999896, 167.52236720000874, 1832.459328 - 0.2, 18000.0, 0.61685121005386, 1492.0655255999425, 674.5565423999328, 2061.516744 - 0.2, 18000.0, 0.6853902333931777, 2959.0167871999374, 1111.7910024000155, 2290.57416 - 0.2, 18000.0, 0.7539292567324954, 4634.591288800215, 1605.2660040000465, 2519.6315759999998 - 0.2, 18000.0, 0.8224682800718133, 7162.971590399846, 2289.424201599894, 2748.688992 - 0.2, 18000.0, 0.8910073034111311, 8986.639214399886, 3109.008747999999, 2977.746408 - 0.2, 18000.0, 0.9595463267504487, 15775.614292000631, 4738.675489599826, 3206.8038239999996 - 0.2, 21000.0, 0.0, 303.1959168749328, 303.1959168749328, 0.0 - 0.2, 21000.0, 0.4015540825852783, -1286.149678399992, 250.11953280000162, 1341.993744 - 0.2, 21000.0, 0.468479763016158, -244.0783151999903, 413.1808575999969, 1565.659368 - 0.2, 21000.0, 0.5354054434470378, 798.003687199972, 576.2444391999999, 1789.324992 - 0.2, 21000.0, 0.6023311238779174, 1840.0794392001014, 739.2986463999998, 2012.990616 - 0.2, 21000.0, 0.6692568043087972, 2856.0667928000416, 960.346184799979, 2236.6562400000003 - 0.2, 21000.0, 0.7361824847396768, 3317.7147888003046, 1293.7248464000222, 2460.321864 - 0.2, 21000.0, 0.8031081651705566, 5785.787455200061, 1909.6551719998736, 2683.987488 - 0.2, 21000.0, 0.8700338456014363, 8897.440939199427, 3056.7371688001904, 2907.653112 - 0.2, 21000.0, 0.936959526032316, 11155.844833599513, 4062.5397240000484, 3131.318736 - 0.2, 24000.0, 0.0, 269.97319167555275, 269.97319167555275, 0.0 - 0.2, 24000.0, 0.39187312028725313, -3086.6338912000133, -1467.264528000001, 1309.639968 - 0.2, 24000.0, 0.4571853070017953, -1835.9772168000611, -904.9480896000025, 1527.913296 - 0.2, 24000.0, 0.5224974937163375, -585.3079128001888, -342.6348064000065, 1746.186624 - 0.2, 24000.0, 0.5878096804308797, 665.3422511999618, 219.67660480007714, 1964.459952 - 0.2, 24000.0, 0.6531218671454219, 2335.0078592000855, 844.975430400066, 2182.73328 - 0.2, 24000.0, 0.718434053859964, 4330.393532000133, 1474.0756264001006, 2401.0066079999997 - 0.2, 24000.0, 0.7837462405745063, 5792.046102400926, 1909.764184799733, 2619.279936 - 0.2, 24000.0, 0.8490584272890486, 7905.602704799972, 2352.5142960001285, 2837.553264 - 0.2, 24000.0, 0.9143706140035907, 9028.809468800908, 3009.1800920004225, 3055.826592 - 0.2, 24000.0, 0.9796828007181327, 11165.558232001782, 4091.1444976008543, 3274.0999199999997 - 0.2, 27000.0, 0.0, 239.6933616652464, 239.6933616652464, 0.0 - 0.2, 27000.0, 0.3821930628366248, 5851.268064800048, 3574.6922360000026, 1277.2892160000001 - 0.2, 27000.0, 0.44589190664272893, 4417.294346400074, 2799.7002528000016, 1490.170752 - 0.2, 27000.0, 0.5095907504488331, 2983.287816000025, 2024.685711999986, 1703.052288 - 0.2, 27000.0, 0.5732895942549372, 1549.2890647997772, 1249.6711711998873, 1915.9338240000002 - 0.2, 27000.0, 0.6369884380610413, 207.16195839984994, 425.31934800005274, 2128.81536 - 0.2, 27000.0, 0.7006872818671454, 2949.6418104002087, 790.2206111997298, 2341.696896 - 0.2, 27000.0, 0.7643861256732496, 3967.3728512007283, 1148.0361959999918, 2554.5784320000002 - 0.2, 27000.0, 0.8280849694793537, 4283.771040000926, 2084.619260800131, 2767.459968 - 0.2, 27000.0, 0.8917838132854579, 8825.652020801903, 2731.879137600994, 2980.341504 - 0.2, 27000.0, 0.955482657091562, 6503.510225599652, 3450.010035200928, 3193.2230400000003 - 0.2, 30000.0, 0.0, 212.1620283175196, 212.1620283175196, 0.0 - 0.2, 30000.0, 0.3725121005385996, -1299.1236000000777, 256.11379999997877, 1244.93544 - 0.2, 30000.0, 0.43459745062836624, -116.08000000007144, 404.18079999994404, 1452.42468 - 0.2, 30000.0, 0.49668280071813287, 1066.744800000144, 552.3156999998861, 1659.91392 - 0.2, 30000.0, 0.5587681508078994, 2249.6810000001974, 700.4106000000195, 1867.4031599999998 - 0.2, 30000.0, 0.620853500897666, 2481.530899999819, 467.40749999978067, 2074.8923999999997 - 0.2, 30000.0, 0.6829388509874327, 978.6678000008255, 646.3924000004699, 2282.38164 - 0.2, 30000.0, 0.7450242010771992, 2672.6546999992934, 663.9882999999927, 2489.87088 - 0.2, 30000.0, 0.8071095511669658, 4300.752799999445, 575.4326999996099, 2697.36012 - 0.2, 30000.0, 0.8691949012567325, 8847.358799999522, 3656.905699999661, 2904.84936 - 0.2, 30000.0, 0.9312802513464992, 15157.131800002508, 3717.340599997726, 3112.3386 - 0.2, 30000.0, 0.9933656014362657, 26100.612300003435, 7008.75799999493, 3319.82784 - 0.2, 33000.0, 0.0, 187.1898861728484, 187.1898861728484, 0.0 - 0.2, 33000.0, 0.3628320430879713, 23055.01512239997, 2408.871806399976, 1212.5846880000001 - 0.2, 33000.0, 0.42330405026929985, 18179.434164799713, 1907.697678400014, 1414.6821360000001 - 0.2, 33000.0, 0.4837760574506284, 13303.806382399483, 1406.5194224000763, 1616.779584 - 0.2, 33000.0, 0.544248064631957, 8428.168142399802, 905.3799351999479, 1818.877032 - 0.2, 33000.0, 0.6047200718132855, 3552.504859199834, 404.16703839979493, 2020.97448 - 0.2, 33000.0, 0.6651920789946141, 312.609142400117, 290.78005680006254, 2223.0719280000003 - 0.2, 33000.0, 0.7256640861759426, 5726.573253599845, 2192.9219367998166, 2425.1693760000003 - 0.2, 33000.0, 0.7861360933572712, 6102.49538720074, 2156.7862400003332, 2627.2668240000003 - 0.2, 33000.0, 0.8466081005385997, 2044.1403895971544, 59.31571839928711, 2829.3642720000003 - 0.2, 33000.0, 0.9070801077199283, 4972.292682399329, 1903.2150087992359, 3031.4617200000002 - 0.2, 33000.0, 0.9675521149012568, -15369.76610560192, -11175.192946403346, 3233.559168 - 0.2, 36000.0, 0.0, 164.59910670132666, 164.59910670132666, 0.0 - 0.2, 36000.0, 0.3531510807899461, 21355.844000000034, 1673.0644000000184, 1180.230912 - 0.2, 36000.0, 0.41200959425493716, 17053.516699999716, 1443.186000000033, 1376.936064 - 0.2, 36000.0, 0.4708681077199282, 12751.070699999062, 1213.307600000101, 1573.641216 - 0.2, 36000.0, 0.5297266211849192, 8448.720299999866, 983.441199999898, 1770.346368 - 0.2, 36000.0, 0.5885851346499102, 4146.325899999729, 753.5232999998013, 1967.05152 - 0.2, 36000.0, 0.6474436481149013, 1281.7116999997365, 503.39420000022164, 2163.756672 - 0.2, 36000.0, 0.7063021615798922, 1554.097800000296, 516.2421999997059, 2360.461824 - 0.2, 36000.0, 0.7651606750448833, -5548.754799999206, -310.544900000099, 2557.166976 - 0.2, 36000.0, 0.8240191885098743, 18994.094899995718, 4628.813800001455, 2753.872128 - 0.2, 36000.0, 0.8828777019748654, 9293.206899999655, 3422.0082999993347, 2950.57728 - 0.2, 36000.0, 0.9417362154398564, -5216.611400002032, -6751.359200001797, 3147.282432 - 0.2, 39000.0, 0.0, 142.55526520935254, 142.55526520935254, 0.0 - 0.2, 39000.0, 0.3528633393177738, -369.11190000004785, -191.73640000002348, 1179.26928 - 0.2, 39000.0, 0.4116738958707361, -423.51280000012986, -135.85040000002857, 1375.8141600000001 - 0.2, 39000.0, 0.4704844524236984, -478.0080000006811, -79.959900000086, 1572.35904 - 0.2, 39000.0, 0.5292950089766607, -532.4351000004209, -24.04190000007076, 1768.90392 - 0.2, 39000.0, 0.588105565529623, -586.922699999749, 31.860599999995912, 1965.4488000000001 - 0.2, 39000.0, 0.6469161220825853, -962.2820000003819, -11.29159999981718, 2161.99368 - 0.2, 39000.0, 0.7057266786355476, 919.3271999988092, 385.33050000021944, 2358.53856 - 0.2, 39000.0, 0.7645372351885098, -128.4182999990062, -70.94439999981466, 2555.08344 - 0.2, 39000.0, 0.8233477917414722, 4724.469900000452, -694.0085999987191, 2751.6283200000003 - 0.2, 39000.0, 0.8821583482944345, 6948.5503000018325, 2589.483400001871, 2948.1732 - 0.2, 39000.0, 0.9409689048473968, 43362.67030000154, 24330.292900003617, 3144.71808 - 0.2, 42000.0, 0.0, 123.41336407810354, 123.41336407810354, 0.0 - 0.2, 42000.0, 0.3528633393177738, -191029.8790375006, -73367.23042500016, 1179.26928 - 0.2, 42000.0, 0.4116738958707361, -149857.55623750068, -57423.55227500014, 1375.8141600000001 - 0.2, 42000.0, 0.4704844524236984, -108685.2645875007, -41479.85605625019, 1572.35904 - 0.2, 42000.0, 0.5292950089766607, -67513.02813749838, -25536.134681250333, 1768.90392 - 0.2, 42000.0, 0.588105565529623, -26340.74252499945, -9592.500806250164, 1965.4488000000001 - 0.2, 42000.0, 0.6469161220825853, -6468.488781250213, -2115.197900000113, 2161.99368 - 0.2, 42000.0, 0.7057266786355476, 4304.067562499638, 711.843531250193, 2358.53856 - 0.2, 42000.0, 0.7645372351885098, -3325.8953812500113, 345.9538000005905, 2555.08344 - 0.2, 42000.0, 0.8233477917414722, 11367.893587500846, 6011.922062500005, 2751.6283200000003 - 0.2, 42000.0, 0.8821583482944345, -1836.9347749995577, -861.5124499989979, 2948.1732 - 0.2, 42000.0, 0.9409689048473968, 11769.366156253061, 7794.408525002873, 3144.71808 - 0.25, 0.0, 0.0, 645.069672563868, 645.069672563868, 0.0 - 0.25, 0.0, 0.4714123653500898, -1742.0389000000018, -58.891800000000146, 1575.460125 - 0.25, 0.0, 0.5499810929084381, 445.66239999999954, 611.5524999999957, 1838.0368125 - 0.25, 0.0, 0.6285498204667863, 2633.363799999994, 1281.9967999999851, 2100.6135 - 0.25, 0.0, 0.7071185480251346, 5070.965799999945, 2010.3996999999918, 2363.1901875 - 0.25, 0.0, 0.7856872755834828, 8055.822799999946, 3018.434599999992, 2625.766875 - 0.25, 0.0, 0.8642560031418312, 12000.668900000195, 4407.951699999887, 2888.3435624999997 - 0.25, 0.0, 0.9428247307001796, 17434.64259999971, 6346.668900000043, 3150.92025 - 0.25, 3000.0, 0.0, 584.1954374240745, 584.1954374240745, 0.0 - 0.25, 3000.0, 0.4616890933572711, -1964.949746766025, -139.76529304589238, 1542.96495 - 0.25, 3000.0, 0.538637275583483, 108.11919704801501, 476.8597159877361, 1800.125775 - 0.25, 3000.0, 0.6155854578096948, 2181.1881420929094, 1093.4848311978913, 2057.2866 - 0.25, 3000.0, 0.6925336400359066, 4326.535310526286, 1741.598934762304, 2314.447425 - 0.25, 3000.0, 0.7694818222621185, 6980.937827104638, 2613.340844112933, 2571.6082499999998 - 0.25, 3000.0, 0.8464300044883303, 10488.830165588359, 3818.898385857153, 2828.7690749999997 - 0.25, 3000.0, 0.9233781867145422, 15330.186727978782, 5492.86061972634, 3085.9299 - 0.25, 6000.0, 0.0, 527.9505372376796, 527.9505372376796, 0.0 - 0.25, 6000.0, 0.4519649124775584, -2162.851800000002, -217.17300000000043, 1510.4667375000001 - 0.25, 6000.0, 0.5272923978904848, -225.72940000000025, 351.15710000000183, 1762.2111937500001 - 0.25, 6000.0, 0.6026198833034112, 1711.3927999999876, 919.487200000006, 2013.95565 - 0.25, 6000.0, 0.6779473687163377, 3662.1987000000377, 1495.1986999999938, 2265.7001062500003 - 0.25, 6000.0, 0.753274854129264, 6012.335000000035, 2253.9147999999814, 2517.4445625000003 - 0.25, 6000.0, 0.8286023395421904, 9041.07130000012, 3293.782700000007, 2769.1890187500003 - 0.25, 6000.0, 0.9039298249551168, 13317.44529999992, 4744.825699999964, 3020.9334750000003 - 0.25, 6000.0, 0.9792573103680432, 18435.918000000012, 6573.845699999974, 3272.6779312500003 - 0.25, 9000.0, 0.0, 476.0724256705646, 476.0724256705646, 0.0 - 0.25, 9000.0, 0.44224164048473963, -2278.7202000000034, -298.7478000000004, 1477.9715625 - 0.25, 9000.0, 0.5159485805655296, -489.7066000000096, 227.3927999999987, 1724.3001562499999 - 0.25, 9000.0, 0.5896555206463195, 1299.3068999999755, 753.5333999999959, 1970.6287499999999 - 0.25, 9000.0, 0.6633624607271095, 3088.3203000000094, 1279.6740999999804, 2216.95734375 - 0.25, 9000.0, 0.7370694008078994, 5151.956499999974, 1933.79259999998, 2463.2859375 - 0.25, 9000.0, 0.8107763408886893, 7776.433100000033, 2825.9757999999924, 2709.61453125 - 0.25, 9000.0, 0.8844832809694793, 11451.41889999997, 4068.226299999982, 2955.943125 - 0.25, 9000.0, 0.9581902210502692, 15926.962899999764, 5648.186499999971, 3202.2717187499998 - 0.25, 12000.0, 0.0, 428.30348146683866, 428.30348146683866, 0.0 - 0.25, 12000.0, 0.43251745960502685, -2003.6220519999995, -285.62908160000006, 1445.4733499999998 - 0.25, 12000.0, 0.5046037028725313, -463.21664559999226, 174.16556320000086, 1686.3855749999998 - 0.25, 12000.0, 0.5766899461400359, 1077.188558400014, 633.9602464000027, 1927.2977999999998 - 0.25, 12000.0, 0.6487761894075403, 2617.5939023999977, 1093.7548231999997, 2168.210025 - 0.25, 12000.0, 0.7208624326750449, 4380.616433600048, 1641.559213600004, 2409.12225 - 0.25, 12000.0, 0.7929486759425494, 6725.131075199985, 2413.666295200011, 2650.034475 - 0.25, 12000.0, 0.8650349192100537, 9842.336751199888, 3458.4423184000325, 2890.9466999999995 - 0.25, 12000.0, 0.9371211624775582, 13708.570474399963, 4810.020418399966, 3131.8589249999995 - 0.25, 15000.0, 0.0, 384.4026392638619, 384.4026392638619, 0.0 - 0.25, 15000.0, 0.42279418761220816, -2123.8319000000006, -322.3119000000002, 1412.9781749999997 - 0.25, 15000.0, 0.4932598855475762, -692.9334000000017, 93.85139999999924, 1648.4745374999998 - 0.25, 15000.0, 0.5637255834829443, 737.9664999999944, 510.015099999998, 1883.9708999999998 - 0.25, 15000.0, 0.6341912814183124, 2168.865899999995, 926.1784000000018, 2119.4672625 - 0.25, 15000.0, 0.7046569793536804, 3727.2302999999856, 1389.900799999998, 2354.963625 - 0.25, 15000.0, 0.7751226772890485, 5788.952299999985, 2045.8736999999917, 2590.4599875 - 0.25, 15000.0, 0.8455883752244163, 8300.066199999992, 2924.9878999999987, 2825.9563499999995 - 0.25, 15000.0, 0.9160540731597844, 11956.337100000073, 4122.886099999982, 3061.4527124999995 - 0.25, 15000.0, 0.9865197710951524, 15138.798399999987, 5445.595899999984, 3296.9490749999995 - 0.25, 18000.0, 0.0, 344.13549463777605, 344.13549463777605, 0.0 - 0.25, 18000.0, 0.41307000673249544, -3373.6676967999897, -583.2069383999991, 1380.4799624999998 - 0.25, 18000.0, 0.481915007854578, -1714.3526175999937, -141.56712319999838, 1610.5599562499997 - 0.25, 18000.0, 0.5507600089766607, -55.033698399987784, 300.06845920000217, 1840.6399499999998 - 0.25, 18000.0, 0.6196050100987432, 1604.2851415999726, 741.7052063999719, 2070.71994375 - 0.25, 18000.0, 0.6884500112208258, 3016.900199199963, 1167.1288464000077, 2300.7999375 - 0.25, 18000.0, 0.7572950123429083, 4712.997656800105, 1701.35578400002, 2530.8799312499996 - 0.25, 18000.0, 0.8261400134649909, 7055.3885543999295, 2422.8140575999532, 2760.9599249999997 - 0.25, 18000.0, 0.8949850145870736, 9375.739558399926, 3329.346847999977, 2991.0399187499997 - 0.25, 18000.0, 0.963830015709156, 14232.80417200023, 4755.715545599903, 3221.1199124999994 - 0.25, 21000.0, 0.0, 307.2747313966918, 307.2747313966918, 0.0 - 0.25, 21000.0, 0.40334673473967686, -1822.321482399996, -68.36159919999898, 1347.9847875 - 0.25, 21000.0, 0.47057119052962293, -689.5712671999983, 188.35477359999797, 1572.64891875 - 0.25, 21000.0, 0.5377956463195691, 443.18469919997705, 445.0723111999984, 1797.31305 - 0.25, 21000.0, 0.6050201021095153, 1575.9375912000526, 701.7846904000062, 2021.97718125 - 0.25, 21000.0, 0.6722445578994614, 2692.25420080002, 988.6469127999845, 2246.6413125 - 0.25, 21000.0, 0.7394690136894075, 3652.6772768001633, 1396.4518904000124, 2471.30544375 - 0.25, 21000.0, 0.8066934694793537, 5831.830067200013, 2025.8950319999406, 2695.969575 - 0.25, 21000.0, 0.8739179252692999, 8640.355591199714, 3037.3468368001204, 2920.63370625 - 0.25, 21000.0, 0.9411423810592459, 10913.268769599736, 4021.121464000041, 3145.2978375 - 0.25, 24000.0, 0.0, 273.60506965742564, 273.60506965742564, 0.0 - 0.25, 24000.0, 0.3936225538599641, -2952.860239200006, -1086.8782880000003, 1315.486575 - 0.25, 24000.0, 0.4592263128366248, -1723.2221488000348, -611.0312336000009, 1534.7343375 - 0.25, 24000.0, 0.5248300718132854, -493.57666480010795, -135.18594240000309, 1753.9821 - 0.25, 24000.0, 0.590433830789946, 736.0576991999754, 340.6580568000406, 1973.2298624999999 - 0.25, 24000.0, 0.6560375897666069, 2177.825567200038, 842.9660464000267, 2192.477625 - 0.25, 24000.0, 0.7216413487432676, 3940.2513720000516, 1396.3195024000481, 2411.7253875 - 0.25, 24000.0, 0.7872451077199282, 5493.7540784005105, 1884.3471567998606, 2630.97315 - 0.25, 24000.0, 0.8528488666965889, 7527.949516799967, 2429.7341160000665, 2850.2209125 - 0.25, 24000.0, 0.9184526256732496, 9093.743860800534, 3174.121912000228, 3069.468675 - 0.25, 24000.0, 0.9840563846499102, 11241.584732000993, 4223.0031416004695, 3288.7164374999998 - 0.25, 27000.0, 0.0, 242.917893098276, 242.917893098276, 0.0 - 0.25, 27000.0, 0.3838992818671454, 2648.044816800032, 2042.5788360000024, 1282.9913999999999 - 0.25, 27000.0, 0.44788249551166964, 2150.7526824000515, 1673.0656648000024, 1496.8233 - 0.25, 27000.0, 0.5118657091561939, 1653.4395360000315, 1303.5377919999926, 1710.6552 - 0.25, 27000.0, 0.5758489228007181, 1156.1315167998582, 934.0099191999275, 1924.4870999999998 - 0.25, 27000.0, 0.6398321364452424, 736.4785143999034, 541.892408000039, 2138.319 - 0.25, 27000.0, 0.7038153500897666, 2861.175466400128, 892.9639791998325, 2352.1509 - 0.25, 27000.0, 0.7677985637342908, 4078.6004392004093, 1309.1679759999934, 2565.9827999999998 - 0.25, 27000.0, 0.8317817773788151, 4904.717260000526, 2123.0680728000707, 2779.8147 - 0.25, 27000.0, 0.8957649910233393, 8505.26161280121, 2802.812021600619, 2993.6466 - 0.25, 27000.0, 0.9597482046678635, 7543.393829599838, 3525.0113432005637, 3207.4784999999997 - 0.25, 30000.0, 0.0, 215.0161880007593, 215.0161880007593, 0.0 - 0.25, 30000.0, 0.3741751009874327, -1570.5171000000523, 0.6666999999864061, 1250.4931875 - 0.25, 30000.0, 0.43653761781867145, -490.5171000000467, 192.97039999996466, 1458.90871875 - 0.25, 30000.0, 0.4989001346499102, 589.3328000001002, 385.3201999999282, 1667.32425 - 0.25, 30000.0, 0.561262651481149, 1669.258800000136, 577.6427000000085, 1875.7397812499999 - 0.25, 30000.0, 0.6236251683123878, 2115.127699999875, 515.9008999998551, 2084.1553125 - 0.25, 30000.0, 0.6859876851436265, 1327.4259000005518, 715.5550000003176, 2292.5708437499998 - 0.25, 30000.0, 0.7483502019748653, 2918.627899999504, 868.5973999999931, 2500.986375 - 0.25, 30000.0, 0.8107127188061041, 4513.853399999529, 983.7328999997039, 2709.4019062499997 - 0.25, 30000.0, 0.8730752356373429, 8104.490799999696, 3277.9613999997746, 2917.8174375 - 0.25, 30000.0, 0.9354377524685815, 13003.693600001605, 3622.433599998433, 3126.2329687499996 - 0.25, 30000.0, 0.9978002692998204, 21020.044000002174, 6201.657399996548, 3334.6485 - 0.25, 33000.0, 0.0, 189.70810222904672, 189.70810222904672, 0.0 - 0.25, 33000.0, 0.36445182899461404, 15564.810970399976, 1521.9840743999832, 1217.9980125000002 - 0.25, 33000.0, 0.42519380049371636, 12361.800720799785, 1246.2691464000075, 1420.9976812500001 - 0.25, 33000.0, 0.4859357719928187, 9158.75679039961, 970.5509504000481, 1623.99735 - 0.25, 33000.0, 0.546677743491921, 5955.705670399858, 694.8600991999621, 1826.99701875 - 0.25, 33000.0, 0.6074197149910233, 2752.6369031998756, 419.1178263998696, 2029.9966875 - 0.25, 33000.0, 0.6681616864901258, 745.7704504000822, 430.667872800046, 2232.99635625 - 0.25, 33000.0, 0.7289036579892281, 4855.080585599885, 1863.8479927999024, 2435.9960250000004 - 0.25, 33000.0, 0.7896456294883304, 5511.795231200532, 1967.6473000002243, 2638.99569375 - 0.25, 33000.0, 0.8503876009874327, 3148.7460615981845, 689.5463263996025, 2841.9953625000003 - 0.25, 33000.0, 0.911129572486535, 5335.202890399731, 2024.7906647995278, 3044.99503125 - 0.25, 33000.0, 0.9718715439856374, -9227.630857600823, -7345.747134402151, 3247.9947 - 0.25, 36000.0, 0.0, 166.81341497302694, 166.81341497302694, 0.0 - 0.25, 36000.0, 0.35472764811490126, 14231.166100000022, 991.1068000000133, 1185.4998 - 0.25, 36000.0, 0.41384892280071817, 11432.870499999794, 899.2216000000234, 1383.0831 - 0.25, 36000.0, 0.472970197486535, 8634.490999999323, 807.3364000000697, 1580.6664 - 0.25, 36000.0, 0.5320914721723519, 5836.179399999893, 715.4595999999253, 1778.2497 - 0.25, 36000.0, 0.5912127468581688, 3037.8362999998103, 623.5464999998621, 1975.833 - 0.25, 36000.0, 0.6503340215439856, 1255.5239999998107, 516.292600000156, 2173.4163 - 0.25, 36000.0, 0.7094552962298025, 1674.2107000001897, 601.2869999997665, 2370.9996 - 0.25, 36000.0, 0.7685765709156195, -3033.5285999994267, 129.3010999999442, 2568.5829000000003 - 0.25, 36000.0, 0.8276978456014363, 14759.711199997131, 3746.902500000996, 2766.1662 - 0.25, 36000.0, 0.8868191202872531, 8234.660199999773, 3108.4180999995124, 2963.7495 - 0.25, 36000.0, 0.94594039497307, -2234.6613000013313, -4165.6627000013095, 3161.3328 - 0.25, 39000.0, 0.0, 144.47302350861406, 144.47302350861406, 0.0 - 0.25, 39000.0, 0.3544386220825853, -613.9023000000302, -250.3941000000176, 1184.533875 - 0.25, 39000.0, 0.41351172576301615, -538.8967000000765, -162.8510000000229, 1381.9561875 - 0.25, 39000.0, 0.47258482944344704, -463.95680000042336, -75.30430000006756, 1579.3785 - 0.25, 39000.0, 0.531657933123878, -388.9685000003036, 12.261899999951396, 1776.8008125000001 - 0.25, 39000.0, 0.5907310368043088, -314.0236999998268, 99.81699999999553, 1974.223125 - 0.25, 39000.0, 0.6498041404847397, -462.31920000027606, 109.2991000001223, 2171.6454375 - 0.25, 39000.0, 0.7088772441651706, 1101.6041999991653, 462.7509000001477, 2369.06775 - 0.25, 39000.0, 0.7679503478456015, 621.6528000006874, 240.0913000001408, 2566.4900625 - 0.25, 39000.0, 0.8270234515260323, 4402.225500000371, -109.97859999910588, 2763.912375 - 0.25, 39000.0, 0.8860965552064632, 6220.224300001228, 2357.8201000013105, 2961.3346875 - 0.25, 39000.0, 0.9451696588868941, 31915.864600000932, 17743.905600002487, 3158.757 - 0.25, 42000.0, 0.0, 125.07361144148916, 125.07361144148916, 0.0 - 0.25, 42000.0, 0.3544386220825853, -146187.74591250042, -56088.61267500013, 1184.533875 - 0.25, 42000.0, 0.41351172576301615, -114664.94403750049, -43890.16302500011, 1381.9561875 - 0.25, 42000.0, 0.47258482944344704, -83142.16448750047, -31691.700193750134, 1579.3785 - 0.25, 42000.0, 0.531657933123878, -51619.42711249878, -19493.218243750238, 1776.8008125000001 - 0.25, 42000.0, 0.5907310368043088, -20096.652549999606, -7294.801843750125, 1974.223125 - 0.25, 42000.0, 0.6498041404847397, -4695.9187437501405, -1496.4992250001055, 2171.6454375 - 0.25, 42000.0, 0.7088772441651706, 3503.8320124997153, 679.6217937501436, 2369.06775 - 0.25, 42000.0, 0.7679503478456015, -1973.9816187499964, 456.5929500004386, 2566.4900625 - 0.25, 42000.0, 0.8270234515260323, 9186.537112500584, 4769.555887500006, 2763.912375 - 0.25, 42000.0, 0.8860965552064632, -312.3219249997783, -191.21152499929667, 2961.3346875 - 0.25, 42000.0, 0.9451696588868941, 10432.988268752, 6610.231100002129, 3158.757 - 0.30000000000000004, 0.0, 0.0, 655.6391260384394, 655.6391260384394, 0.0 - 0.30000000000000004, 0.0, 0.47397312387791735, -1722.0547000000013, -36.45129999999998, 1584.0181799999998 - 0.30000000000000004, 0.0, 0.552968644524237, 377.01429999999834, 641.9552999999967, 1848.0212099999999 - 0.30000000000000004, 0.0, 0.6319641651705564, 2476.0832999999984, 1320.3618999999903, 2112.0242399999997 - 0.30000000000000004, 0.0, 0.710959685816876, 4891.319299999995, 2070.0437000000306, 2376.0272699999996 - 0.30000000000000004, 0.0, 0.7899552064631955, 7905.778300000102, 3118.1068999999975, 2640.0302999999994 - 0.30000000000000004, 0.0, 0.8689507271095152, 11771.340800000096, 4553.486800000054, 2904.0333299999998 - 0.30000000000000004, 0.0, 0.9479462477558347, 17009.03710000029, 6539.682600000079, 3168.0363599999996 - 0.30000000000000004, 3000.0, 0.0, 593.7674677930876, 593.7674677930876, 0.0 - 0.30000000000000004, 3000.0, 0.46419703411131064, -1974.312731018013, -123.05548376985443, 1551.3464880000001 - 0.30000000000000004, 3000.0, 0.5415632064631957, 44.41065904002425, 503.5027981613902, 1809.904236 - 0.30000000000000004, 3000.0, 0.6189293788150808, 2063.1340961042174, 1130.0611899839755, 2068.461984 - 0.30000000000000004, 3000.0, 0.696295551166966, 4178.625497813836, 1795.7270179819875, 2327.019732 - 0.30000000000000004, 3000.0, 0.773661723518851, 6845.890952974329, 2698.6560064776054, 2585.57748 - 0.30000000000000004, 3000.0, 0.8510278958707361, 10288.908661126477, 3946.674394161047, 2844.135228 - 0.30000000000000004, 3000.0, 0.9283940682226213, 14955.41640422129, 5662.275117429667, 3102.6929760000003 - 0.30000000000000004, 6000.0, 0.0, 536.6009960602593, 536.6009960602593, 0.0 - 0.30000000000000004, 6000.0, 0.45442003052064633, -2198.4389999999994, -203.61509999999998, 1518.671742 - 0.30000000000000004, 6000.0, 0.5301567022740874, -298.3211000000016, 374.1918000000013, 1771.783699 - 0.30000000000000004, 6000.0, 0.6058933740275285, 1601.796599999996, 951.9988000000036, 2024.8956560000001 - 0.30000000000000004, 6000.0, 0.6816300457809695, 3532.944300000014, 1543.8254000000013, 2278.007613 - 0.30000000000000004, 6000.0, 0.7573667175344106, 5889.292000000001, 2330.751200000017, 2531.1195700000003 - 0.30000000000000004, 6000.0, 0.8331033892878517, 8909.537099999992, 3405.4990000000075, 2784.2315270000004 - 0.30000000000000004, 6000.0, 0.9088400610412927, 13001.74120000004, 4896.623500000034, 3037.343484 - 0.30000000000000004, 6000.0, 0.9845767327947337, 18010.134800000007, 6764.826699999997, 3290.455441 - 0.30000000000000004, 9000.0, 0.0, 483.87286268948714, 483.87286268948714, 0.0 - 0.30000000000000004, 9000.0, 0.4446439407540395, -2330.1484000000005, -290.16430000000014, 1486.00005 - 0.30000000000000004, 9000.0, 0.5187512642130461, -563.7825000000029, 245.97229999999956, 1733.666725 - 0.30000000000000004, 9000.0, 0.5928585876720527, 1202.583399999992, 782.1088999999985, 1981.3334 - 0.30000000000000004, 9000.0, 0.6669659111310592, 2968.9492000000055, 1318.245500000004, 2229.000075 - 0.30000000000000004, 9000.0, 0.7410732345900658, 5040.569799999995, 1997.8845000000047, 2476.66675 - 0.30000000000000004, 9000.0, 0.8151805580490723, 7692.805200000018, 2929.594499999995, 2724.333425 - 0.30000000000000004, 9000.0, 0.889287881508079, 11181.069299999976, 4198.12259999999, 2972.0001 - 0.30000000000000004, 9000.0, 0.9633952049670856, 15576.658200000007, 5822.217300000024, 3219.666775 - 0.30000000000000004, 12000.0, 0.0, 435.32122530583854, 435.32122530583854, 0.0 - 0.30000000000000004, 12000.0, 0.4348669371633752, -2163.1815911999993, -299.03306240000006, 1453.325304 - 0.30000000000000004, 12000.0, 0.5073447600239377, -609.0475615999985, 175.74389039999997, 1695.5461879999998 - 0.30000000000000004, 12000.0, 0.5798225828845003, 945.0864592000006, 650.5209159999996, 1937.7670719999999 - 0.30000000000000004, 12000.0, 0.6523004057450629, 2499.220427999975, 1125.2978248000068, 2179.987956 - 0.30000000000000004, 12000.0, 0.7247782286056254, 4287.446582399997, 1698.784959999999, 2422.20884 - 0.30000000000000004, 12000.0, 0.7972560514661878, 6603.43610719999, 2496.3871072, 2664.4297239999996 - 0.30000000000000004, 12000.0, 0.8697338743267504, 9629.066372000018, 3574.470187199962, 2906.650608 - 0.30000000000000004, 12000.0, 0.9422116971873129, 13412.543775199965, 4963.872883999996, 3148.8714919999998 - 0.30000000000000004, 15000.0, 0.0, 390.70106869560607, 390.70106869560607, 0.0 - 0.30000000000000004, 15000.0, 0.42509084739676845, -2067.99, -301.0187, 1420.653612 - 0.30000000000000004, 15000.0, 0.4959393219628965, -682.3344000000002, 118.71769999999994, 1657.429214 - 0.30000000000000004, 15000.0, 0.5667877965290246, 703.3210999999991, 538.4540999999999, 1894.204816 - 0.30000000000000004, 15000.0, 0.6376362710951526, 2088.976599999998, 958.1905000000003, 2130.980418 - 0.30000000000000004, 15000.0, 0.7084847456612806, 3634.7191999999995, 1442.6549999999988, 2367.75602 - 0.30000000000000004, 15000.0, 0.7793332202274087, 5630.085899999996, 2114.0347000000015, 2604.531622 - 0.30000000000000004, 15000.0, 0.8501816947935369, 8242.302700000006, 3037.5891, 2841.307224 - 0.30000000000000004, 15000.0, 0.9210301693596649, 11505.213899999999, 4210.631299999998, 3078.082826 - 0.30000000000000004, 15000.0, 0.991878643925793, 15085.611299999993, 5615.936999999995, 3314.858428 - 0.30000000000000004, 18000.0, 0.0, 349.77414772321083, 349.77414772321083, 0.0 - 0.30000000000000004, 18000.0, 0.4153138438061041, -2535.845224799996, -421.65684239999973, 1387.978866 - 0.30000000000000004, 18000.0, 0.48453281777378815, -1142.685893599996, -16.50997519999962, 1619.308677 - 0.30000000000000004, 18000.0, 0.5537517917414722, 250.47475760000808, 388.63553120000006, 1850.638488 - 0.30000000000000004, 18000.0, 0.6229707657091562, 1643.6352975999891, 793.7815303999928, 2081.968299 - 0.30000000000000004, 18000.0, 0.6921897396768403, 3020.542691199985, 1218.5807504000034, 2313.29811 - 0.30000000000000004, 18000.0, 0.7614087136445243, 4740.696944800034, 1785.446364000006, 2544.6279210000002 - 0.30000000000000004, 18000.0, 0.8306276876122082, 7007.7219783999735, 2550.7582535999854, 2775.957732 - 0.30000000000000004, 18000.0, 0.8998466615798922, 9594.32116239995, 3522.1187479999785, 3007.287543 - 0.30000000000000004, 18000.0, 0.9690656355475763, 13289.14215200003, 4845.92624159996, 3238.617354 - 0.30000000000000004, 21000.0, 0.0, 312.3094216255789, 312.3094216255789, 0.0 - 0.30000000000000004, 21000.0, 0.4055377540394973, -2082.715746399999, -255.1109111999996, 1355.307174 - 0.30000000000000004, 21000.0, 0.47312737971274693, -920.1372992000021, 60.16892959999867, 1581.1917030000002 - 0.30000000000000004, 21000.0, 0.5407170053859964, 242.44379119998368, 375.4492631999985, 1807.0762320000001 - 0.30000000000000004, 21000.0, 0.608306631059246, 1405.0237232000215, 690.7271944000063, 2032.960761 - 0.30000000000000004, 21000.0, 0.6758962567324955, 2570.1426288000093, 1023.0374607999923, 2258.84529 - 0.30000000000000004, 21000.0, 0.7434858824057451, 3853.675284800081, 1485.7858944000095, 2484.729819 - 0.30000000000000004, 21000.0, 0.8110755080789946, 5876.0360592, 2138.678891999982, 2710.614348 - 0.30000000000000004, 21000.0, 0.8786651337522442, 8462.327223199887, 3072.246424800067, 2936.498877 - 0.30000000000000004, 21000.0, 0.9462547594254939, 10776.648645599891, 4069.0628040000292, 3162.3834060000004 - 0.30000000000000004, 24000.0, 0.0, 278.08808316301673, 278.08808316301673, 0.0 - 0.30000000000000004, 24000.0, 0.395760750448833, -2751.8159672000024, -804.0865479999995, 1322.632428 - 0.30000000000000004, 24000.0, 0.46172087552363855, -1568.0871008000174, -390.46861759999956, 1543.071166 - 0.30000000000000004, 24000.0, 0.527681000598444, -384.35443680005415, 23.14846159999894, 1763.509904 - 0.30000000000000004, 24000.0, 0.5936411256732496, 799.3725271999853, 436.76472880001756, 1983.948642 - 0.30000000000000004, 24000.0, 0.6596012507480551, 2065.18615520001, 855.2136224000054, 2204.38738 - 0.30000000000000004, 24000.0, 0.7255613758228605, 3656.178712000009, 1359.2486384000163, 2424.826118 - 0.30000000000000004, 24000.0, 0.791521500897666, 5282.565414400236, 1892.8897487999411, 2645.264856 - 0.30000000000000004, 24000.0, 0.8574816259724716, 7268.69924879996, 2520.292436000026, 2865.703594 - 0.30000000000000004, 24000.0, 0.9234417510472771, 9125.918172800291, 3334.852332000099, 3086.142332 - 0.30000000000000004, 24000.0, 0.9894018761220826, 11237.83543200046, 4353.938825600216, 3306.58107 - 0.30000000000000004, 27000.0, 0.0, 246.8980978396312, 246.8980978396312, 0.0 - 0.30000000000000004, 27000.0, 0.3859846606822262, 414.1757888000175, 950.8760360000006, 1289.960736 - 0.30000000000000004, 27000.0, 0.4503154374625973, 572.1774784000326, 872.8467968000009, 1504.9541920000001 - 0.30000000000000004, 27000.0, 0.5146462142429683, 730.1667560000297, 794.8086719999955, 1719.947648 - 0.30000000000000004, 27000.0, 0.5789769910233393, 888.1591887999183, 716.7705471999561, 1934.941104 - 0.30000000000000004, 27000.0, 0.6433077678037104, 1105.4181303999449, 631.9494680000264, 2149.93456 - 0.30000000000000004, 27000.0, 0.7076385445840815, 2793.542882400072, 981.0181271999061, 2364.9280160000003 - 0.30000000000000004, 27000.0, 0.7719693213644524, 4150.088707200199, 1442.5944559999928, 2579.921472 - 0.30000000000000004, 27000.0, 0.8363000981448235, 5349.264880000251, 2176.1204048000295, 2794.914928 - 0.30000000000000004, 27000.0, 0.9006308749251946, 8251.826324800684, 2887.40024560035, 3009.9083840000003 - 0.30000000000000004, 27000.0, 0.9649616517055656, 8297.254473599945, 3630.423131200299, 3224.90184 - 0.30000000000000004, 30000.0, 0.0, 218.53922387116555, 218.53922387116555, 0.0 - 0.30000000000000004, 30000.0, 0.3762076570915619, -1784.8838000000333, -191.76550000000816, 1257.2859899999999 - 0.30000000000000004, 30000.0, 0.4389089332734889, -783.3960000000288, 35.38469999997946, 1466.833655 - 0.30000000000000004, 30000.0, 0.5016102094554159, 217.9944000000644, 262.5643999999586, 1676.38132 - 0.30000000000000004, 30000.0, 0.5643114856373429, 1219.433900000088, 489.7265000000019, 1885.928985 - 0.30000000000000004, 30000.0, 0.6270127618192699, 1824.5880999999167, 558.0992999999105, 2095.47665 - 0.30000000000000004, 30000.0, 0.6897140380011969, 1602.2850000003464, 781.4071000002007, 2305.024315 - 0.30000000000000004, 30000.0, 0.7524153141831238, 3107.9129999996703, 1040.4782999999925, 2514.5719799999997 - 0.30000000000000004, 30000.0, 0.8151165903650508, 4681.3040999996265, 1315.8614999997862, 2724.1196449999998 - 0.30000000000000004, 30000.0, 0.8778178665469778, 7543.260099999814, 3015.252699999859, 2933.66731 - 0.30000000000000004, 30000.0, 0.9405191427289048, 11314.845800000947, 3560.025399998981, 3143.214975 - 0.30000000000000004, 33000.0, 0.0, 192.8164656284447, 192.8164656284447, 0.0 - 0.30000000000000004, 33000.0, 0.36643156732495513, 9700.131358399978, 829.182682399989, 1224.614298 - 0.30000000000000004, 33000.0, 0.4275034952124477, 7807.481456799842, 731.3772544000034, 1428.716681 - 0.30000000000000004, 33000.0, 0.4885754230999402, 5914.8083383997155, 633.5693184000281, 1632.819064 - 0.30000000000000004, 33000.0, 0.5496473509874327, 4022.1305383999047, 535.7797831999727, 1836.921447 - 0.30000000000000004, 33000.0, 0.6107192788749253, 2129.4408671999095, 437.9559543999235, 2041.02383 - 0.30000000000000004, 33000.0, 0.6717912067624178, 1080.7718984000546, 546.0367688000329, 2245.126213 - 0.30000000000000004, 33000.0, 0.7328631346499103, 4174.890077599918, 1618.031528799959, 2449.228596 - 0.30000000000000004, 33000.0, 0.7939350625374028, 5053.575195200373, 1837.7854600001444, 2653.330979 - 0.30000000000000004, 33000.0, 0.8550069904248954, 4000.5846935989316, 1196.6764743998133, 2857.433362 - 0.30000000000000004, 33000.0, 0.9160789183123879, 5662.175238399976, 2173.8316007997437, 3061.535745 - 0.30000000000000004, 33000.0, 0.9771508461998804, -4247.116269600148, -4209.720362401287, 3265.638128 - 0.30000000000000004, 36000.0, 0.0, 169.54664938704636, 169.54664938704636, 0.0 - 0.30000000000000004, 36000.0, 0.3566545637342909, 8679.757700000011, 458.83760000000876, 1191.939552 - 0.30000000000000004, 36000.0, 0.41609699102333936, 7054.405799999855, 476.26320000001556, 1390.596144 - 0.30000000000000004, 36000.0, 0.47553941831238783, 5428.997299999534, 493.688800000046, 1589.2527360000001 - 0.30000000000000004, 36000.0, 0.5349818456014364, 3803.6348999999177, 511.1199999999469, 1787.9093280000002 - 0.30000000000000004, 36000.0, 0.5944242728904848, 2178.250899999871, 528.5267999999088, 1986.5659200000002 - 0.30000000000000004, 36000.0, 0.6538667001795333, 1238.9081999998675, 534.7619000001046, 2185.2225120000003 - 0.30000000000000004, 36000.0, 0.7133091274685818, 1781.8011000001097, 680.9250999998211, 2383.879104 - 0.30000000000000004, 36000.0, 0.7727515547576302, -1039.8502999996108, 491.140099999976, 2582.5356960000004 - 0.30000000000000004, 36000.0, 0.8321939820466787, 11436.201099998172, 3077.4519000006494, 2781.192288 - 0.30000000000000004, 36000.0, 0.8916364093357273, 7389.053499999863, 2869.8957999996564, 2979.8488800000005 - 0.30000000000000004, 36000.0, 0.9510788366247757, 140.7929999991975, -2105.5940000009036, 3178.5054720000003 - 0.30000000000000004, 39000.0, 0.0, 146.8402110625349, 146.8402110625349, 0.0 - 0.30000000000000004, 39000.0, 0.35636396768402157, -859.5542000000174, -303.66460000001274, 1190.96838 - 0.30000000000000004, 39000.0, 0.4157579622980252, -670.8478000000384, -188.68900000001744, 1389.4631100000001 - 0.30000000000000004, 39000.0, 0.4751519569120287, -482.18490000023604, -73.71060000005036, 1587.95784 - 0.30000000000000004, 39000.0, 0.5345459515260323, -293.48910000020805, 41.28099999996853, 1786.45257 - 0.30000000000000004, 39000.0, 0.5939399461400359, -104.82329999988507, 156.26499999999578, 1984.9473 - 0.30000000000000004, 39000.0, 0.6533339407540395, -61.35950000019034, 212.36400000007677, 2183.44203 - 0.30000000000000004, 39000.0, 0.7127279353680431, 1253.6143999994406, 534.3202000000931, 2381.93676 - 0.30000000000000004, 39000.0, 0.7721219299820467, 1227.694200000447, 497.3822000001031, 2580.43149 - 0.30000000000000004, 39000.0, 0.8315159245960504, 4155.631300000281, 370.38820000059354, 2778.9262200000003 - 0.30000000000000004, 39000.0, 0.8909099192100539, 5658.399800000765, 2196.3475000008725, 2977.42095 - 0.30000000000000004, 39000.0, 0.9503039138240574, 22985.382100000505, 12612.727000001616, 3175.91568 - 0.30000000000000004, 42000.0, 0.0, 127.12294002296355, 127.12294002296355, 0.0 - 0.30000000000000004, 42000.0, 0.35636396768402157, -109083.07348750031, -41796.87192500009, 1190.96838 - 0.30000000000000004, 42000.0, 0.4157579622980252, -85544.63033750035, -32694.764375000075, 1389.4631100000001 - 0.30000000000000004, 42000.0, 0.4751519569120287, -62006.20248750035, -23592.647581250098, 1587.95784 - 0.30000000000000004, 42000.0, 0.5345459515260323, -38467.805987499116, -14490.516656250167, 1786.45257 - 0.30000000000000004, 42000.0, 0.5939399461400359, -14929.382174999748, -5388.433331250087, 1984.9473 - 0.30000000000000004, 42000.0, 0.6533339407540395, -3248.578356250089, -987.1259500000924, 2183.44203 - 0.30000000000000004, 42000.0, 0.7127279353680431, 2856.0819624997694, 657.6385062501067, 2381.93676 - 0.30000000000000004, 42000.0, 0.7721219299820467, -864.5085062499747, 558.4525000003114, 2580.43149 - 0.30000000000000004, 42000.0, 0.8315159245960504, 7418.437737500386, 3770.111012500003, 2778.9262200000003 - 0.30000000000000004, 42000.0, 0.8909099192100539, 916.1667250000646, 359.6056000004701, 2977.42095 - 0.30000000000000004, 42000.0, 0.9503039138240574, 9249.859431251229, 5605.789675001492, 3175.91568 - 0.35000000000000003, 0.0, 0.0, 668.2783888765358, 668.2783888765358, 0.0 - 0.35000000000000003, 0.0, 0.47699947486535005, -1643.5868250000021, -6.490299999999955, 1594.1322449999998 - 0.35000000000000003, 0.0, 0.5564993873429084, 344.1157499999982, 679.1378999999911, 1859.8209524999997 - 0.35000000000000003, 0.0, 0.6359992998204667, 2331.8182250000036, 1364.7660999999753, 2125.5096599999997 - 0.35000000000000003, 0.0, 0.715499212298025, 4733.674174999985, 2140.1169000000614, 2391.1983674999997 - 0.35000000000000003, 0.0, 0.7949991247755833, 7815.084525000263, 3234.264324999983, 2656.8870749999996 - 0.35000000000000003, 0.0, 0.8744990372531417, 11600.211700000209, 4726.712575000102, 2922.5757824999996 - 0.35000000000000003, 0.0, 0.9539989497307001, 16641.543900000517, 6761.731950000154, 3188.2644899999996 - 0.35000000000000003, 3000.0, 0.0, 605.2139827921145, 605.2139827921145, 0.0 - 0.35000000000000003, 3000.0, 0.4671609640933572, -1893.5480637232197, -96.68371348198275, 1561.2519419999999 - 0.35000000000000003, 3000.0, 0.5450211247755834, 35.55024366739556, 538.0440708611612, 1821.4605989999998 - 0.35000000000000003, 3000.0, 0.6228812854578096, 1964.6485508357673, 1172.7718859203503, 2081.6692559999997 - 0.35000000000000003, 3000.0, 0.7007414461400359, 4025.642942430229, 1856.2850790931543, 2341.877913 - 0.35000000000000003, 3000.0, 0.778601606822262, 6721.039340682, 2796.180356596486, 2602.0865699999995 - 0.35000000000000003, 3000.0, 0.8564617675044882, 10200.373970351768, 4099.958938889455, 2862.2952269999996 - 0.35000000000000003, 3000.0, 0.9343219281867144, 14801.456835400393, 5884.001489814689, 3122.5038839999997 - 0.35000000000000003, 6000.0, 0.0, 546.9454687420075, 546.9454687420075, 0.0 - 0.35000000000000003, 6000.0, 0.4573215336624775, -2126.1723999999995, -180.35979999999995, 1528.3685655 - 0.35000000000000003, 6000.0, 0.5335417892728905, -299.72200000000015, 405.4138000000008, 1783.09665975 - 0.35000000000000003, 6000.0, 0.6097620448833034, 1526.7283999999997, 991.1875000000025, 2037.824754 - 0.35000000000000003, 6000.0, 0.6859823004937163, 3404.544699999999, 1598.9492000000062, 2292.55284825 - 0.35000000000000003, 6000.0, 0.7622025561041292, 5790.660600000009, 2418.8593999999916, 2547.2809425 - 0.35000000000000003, 6000.0, 0.8384228117145422, 8793.249999999989, 3531.679400000014, 2802.00903675 - 0.35000000000000003, 6000.0, 0.914643067324955, 12872.850599999958, 5085.368700000043, 3056.737131 - 0.35000000000000003, 6000.0, 0.990863322935368, 17629.503899999945, 6974.8364000000065, 3311.46522525 - 0.35000000000000003, 9000.0, 0.0, 493.2008543374353, 493.2008543374353, 0.0 - 0.35000000000000003, 9000.0, 0.44748302289048475, -2261.0546999999992, -272.22209999999984, 1495.4882625 - 0.35000000000000003, 9000.0, 0.5220635267055654, -556.4716999999989, 272.5457999999998, 1744.7363062499999 - 0.35000000000000003, 9000.0, 0.5966440305206463, 1148.111700000002, 817.3137999999987, 1993.98435 - 0.35000000000000003, 9000.0, 0.6712245343357272, 2852.695099999994, 1362.0818000000008, 2243.23239375 - 0.35000000000000003, 9000.0, 0.7458050381508079, 4941.802700000021, 2070.978500000004, 2492.4804375 - 0.35000000000000003, 9000.0, 0.8203855419658886, 7597.169399999982, 3042.699000000014, 2741.7284812499997 - 0.35000000000000003, 9000.0, 0.8949660457809695, 11125.042000000005, 4371.106400000022, 2990.976525 - 0.35000000000000003, 9000.0, 0.9695465495960502, 15347.561500000023, 6032.982399999997, 3240.22456875 - 0.35000000000000003, 12000.0, 0.0, 443.71324946536083, 443.71324946536083, 0.0 - 0.35000000000000003, 12000.0, 0.437643592459605, -2276.280639999999, -315.6978864000002, 1462.6048859999999 - 0.35000000000000003, 12000.0, 0.5105841912028725, -720.8462687999943, 176.73515359999897, 1706.372367 - 0.35000000000000003, 12000.0, 0.58352478994614, 834.5878952000091, 669.1681479999974, 1950.1398479999998 - 0.35000000000000003, 12000.0, 0.6564653886894074, 2390.0219471999867, 1161.6011711999965, 2193.9073289999997 - 0.35000000000000003, 12000.0, 0.7294059874326749, 4204.665229599948, 1764.086832799984, 2437.6748099999995 - 0.35000000000000003, 12000.0, 0.8023465861759425, 6529.955508800013, 2593.206882400016, 2681.442291 - 0.35000000000000003, 12000.0, 0.87528718491921, 9575.901431999913, 3725.99008639998, 2925.2097719999997 - 0.35000000000000003, 12000.0, 0.9482277836624774, 13217.24354319993, 5147.080213599976, 3168.9772529999996 - 0.35000000000000003, 15000.0, 0.0, 398.23291556418263, 398.23291556418263, 0.0 - 0.35000000000000003, 15000.0, 0.42780508168761217, -2082.485399999999, -300.06069999999977, 1429.724583 - 0.35000000000000003, 15000.0, 0.4991059286355476, -721.9742000000019, 129.89469999999943, 1668.0120135 - 0.35000000000000003, 15000.0, 0.570406775583483, 638.5368999999927, 559.850099999999, 1906.299444 - 0.35000000000000003, 15000.0, 0.6417076225314182, 1999.0479999999943, 989.8055000000024, 2144.5868745 - 0.35000000000000003, 15000.0, 0.7130084694793536, 3546.407700000006, 1493.7940999999996, 2382.874305 - 0.35000000000000003, 15000.0, 0.784309316427289, 5564.218300000008, 2199.7226999999943, 2621.1617355 - 0.35000000000000003, 15000.0, 0.8556101633752243, 8208.329100000015, 3164.0089999999987, 2859.449166 - 0.35000000000000003, 15000.0, 0.9269110103231597, 11334.85739999997, 4364.239700000006, 3097.7365965 - 0.35000000000000003, 15000.0, 0.9982118572710952, 14750.12209999999, 5770.601599999988, 3336.024027 - 0.35000000000000003, 18000.0, 0.0, 356.51701466246317, 356.51701466246317, 0.0 - 0.35000000000000003, 18000.0, 0.4179656512567324, -2124.3552727999995, -339.21670639999996, 1396.8412064999998 - 0.35000000000000003, 18000.0, 0.4876265931328545, -872.7657095999995, 52.37529280000007, 1629.6480742499998 - 0.35000000000000003, 18000.0, 0.5572875350089767, 378.8240536000003, 443.9671832, 1862.4549419999998 - 0.35000000000000003, 18000.0, 0.6269484768850987, 1630.4137935999977, 835.5592143999997, 2095.26180975 - 0.35000000000000003, 18000.0, 0.6966094187612208, 2987.2558631999964, 1268.9999144000012, 2328.0686775 - 0.35000000000000003, 18000.0, 0.7662703606373429, 4735.313552800001, 1864.6357440000006, 2560.87554525 - 0.35000000000000003, 18000.0, 0.8359313025134648, 7006.297562399993, 2678.577089600001, 2793.6824129999995 - 0.35000000000000003, 18000.0, 0.905592244389587, 9695.005226399984, 3700.6689479999927, 3026.4892807499996 - 0.35000000000000003, 18000.0, 0.975253186265709, 12807.588231999995, 4997.189877599993, 3259.2961484999996 - 0.35000000000000003, 21000.0, 0.0, 318.3300520455337, 318.3300520455337, 0.0 - 0.35000000000000003, 21000.0, 0.4081271404847397, -2145.9336703999998, -342.48800319999987, 1363.9609035 - 0.35000000000000003, 21000.0, 0.47614833056552963, -995.5710112000022, 5.216625599999403, 1591.28772075 - 0.35000000000000003, 21000.0, 0.5441695206463196, 154.79256319999118, 352.9213951999991, 1818.614538 - 0.35000000000000003, 21000.0, 0.6121907107271095, 1305.1559352000045, 700.6253584000035, 2045.94135525 - 0.35000000000000003, 21000.0, 0.6802119008078995, 2483.338476800004, 1063.5002287999985, 2273.2681725 - 0.35000000000000003, 21000.0, 0.7482330908886894, 3952.541212800035, 1566.6935584000087, 2500.59498975 - 0.35000000000000003, 21000.0, 0.8162542809694794, 5919.786531200003, 2251.6187520000017, 2727.921807 - 0.35000000000000003, 21000.0, 0.8842754710502693, 8355.876435199978, 3154.9628328000267, 2955.24862425 - 0.35000000000000003, 21000.0, 0.9522966611310593, 10728.889761599974, 4191.690744000012, 3182.5754415 - 0.35000000000000003, 24000.0, 0.0, 283.44900235720434, 283.44900235720434, 0.0 - 0.35000000000000003, 24000.0, 0.39828771005385993, -2517.1379752, -604.8213079999996, 1331.077527 - 0.35000000000000003, 24000.0, 0.4646689950628366, -1393.832672800006, -232.4269415999996, 1552.9237815 - 0.35000000000000003, 24000.0, 0.5310502800718132, -270.5258288000205, 139.96710559999946, 1774.770036 - 0.35000000000000003, 24000.0, 0.5974315650807899, 852.7786351999922, 512.3607208000052, 1996.6162904999999 - 0.35000000000000003, 24000.0, 0.6638128500897665, 1990.071023199997, 880.0879583999972, 2218.462545 - 0.35000000000000003, 24000.0, 0.7301941350987432, 3463.433551999991, 1357.5503344000012, 2440.3087994999996 - 0.35000000000000003, 24000.0, 0.7965754201077199, 5147.198410400079, 1931.9765607999832, 2662.155054 - 0.35000000000000003, 24000.0, 0.8629567051166966, 7112.157500799964, 2625.468256000004, 2884.0013085 - 0.35000000000000003, 24000.0, 0.9293379901256732, 9140.30150480013, 3497.253852000024, 3105.847563 - 0.35000000000000003, 24000.0, 0.9957192751346498, 11189.682332000142, 4494.35624960007, 3327.6938174999996 - 0.35000000000000003, 27000.0, 0.0, 251.65774354850882, 251.65774354850882, 0.0 - 0.35000000000000003, 27000.0, 0.38844919928186716, -1015.7774191999902, 227.64733600000045, 1298.197224 - 0.35000000000000003, 27000.0, 0.45319073249551173, -436.11246559998, 345.87724880000087, 1514.5634280000002 - 0.35000000000000003, 27000.0, 0.5179322657091562, 143.54597600002435, 464.1023519999982, 1730.929632 - 0.35000000000000003, 27000.0, 0.5826737989228007, 723.2061807999596, 582.3274551999768, 1947.295836 - 0.35000000000000003, 27000.0, 0.6474153321364453, 1342.3321063999733, 701.2725280000153, 2163.66204 - 0.35000000000000003, 27000.0, 0.7121568653500898, 2745.6773584000366, 1058.1504551999537, 2380.028244 - 0.35000000000000003, 27000.0, 0.7768983985637343, 4192.823055200075, 1555.4236359999916, 2596.394448 - 0.35000000000000003, 27000.0, 0.8416399317773788, 5650.791900000082, 2244.8753568000043, 2812.760652 - 0.35000000000000003, 27000.0, 0.9063814649910235, 8063.762256800326, 2987.98700960017, 3029.1268560000003 - 0.35000000000000003, 27000.0, 0.971122998204668, 8817.193857599992, 3764.537799200125, 3245.4930600000002 - 0.35000000000000003, 30000.0, 0.0, 222.75217361934654, 222.75217361934654, 0.0 - 0.35000000000000003, 30000.0, 0.37860976885098746, -1945.5682000000193, -328.9534000000042, 1265.3138475 - 0.35000000000000003, 30000.0, 0.4417113969928187, -1002.0784000000164, -75.0909000000103, 1476.19948875 - 0.35000000000000003, 30000.0, 0.5048130251346499, -58.64719999996268, 178.7889999999794, 1687.08513 - 0.35000000000000003, 30000.0, 0.5679146532764812, 884.8133000000524, 432.6583999999985, 1897.9707712499999 - 0.35000000000000003, 30000.0, 0.6310162814183123, 1601.8253999999492, 595.7917999999488, 2108.8564125 - 0.35000000000000003, 30000.0, 0.6941179095601435, 1813.370600000197, 845.1598000001154, 2319.7420537499997 - 0.35000000000000003, 30000.0, 0.7572195377019749, 3250.793399999793, 1185.623999999991, 2530.627695 - 0.35000000000000003, 30000.0, 0.8203211658438061, 4812.289399999729, 1584.2880999998556, 2741.51333625 - 0.35000000000000003, 30000.0, 0.8834227939856374, 7143.230299999894, 2856.5512999999182, 2952.3989775 - 0.35000000000000003, 30000.0, 0.9465244221274686, 10041.400400000499, 3532.9170999993935, 3163.28461875 - 0.35000000000000003, 33000.0, 0.0, 196.53353785888967, 196.53353785888967, 0.0 - 0.35000000000000003, 33000.0, 0.36877125807899463, 5267.119386399985, 307.6657303999933, 1232.4335445000002 - 0.35000000000000003, 33000.0, 0.4302331344254937, 4365.808572799895, 345.9066024000011, 1437.83913525 - 0.35000000000000003, 33000.0, 0.49169501077199285, 3464.482626399804, 384.1456264000144, 1643.2447260000001 - 0.35000000000000003, 33000.0, 0.553156887118492, 2563.1538463999377, 422.3962871999813, 1848.6503167500002 - 0.35000000000000003, 33000.0, 0.614618763464991, 1661.8175511999393, 460.6255223999601, 2054.0559075 - 0.35000000000000003, 33000.0, 0.6760806398114901, 1331.4525864000343, 641.1114448000225, 2259.46149825 - 0.35000000000000003, 33000.0, 0.7375425161579893, 3665.191129599942, 1446.833744799994, 2464.8670890000003 - 0.35000000000000003, 33000.0, 0.7990043925044884, 4714.719579200251, 1761.6467200000882, 2670.2726797500004 - 0.35000000000000003, 33000.0, 0.8604662688509874, 4635.346685599444, 1598.9072623999446, 2875.6782705 - 0.35000000000000003, 33000.0, 0.9219281451974866, 5954.983826400115, 2345.6705167998875, 3081.08386125 - 0.35000000000000003, 33000.0, 0.9833900215439857, -306.63524159978624, -1694.845230400675, 3286.4894520000003 - 0.35000000000000003, 36000.0, 0.0, 172.8151313610703, 172.8151313610703, 0.0 - 0.35000000000000003, 36000.0, 0.3589318276481149, 4510.2403000000095, 58.68510000000589, 1199.550168 - 0.35000000000000003, 36000.0, 0.4187537989228007, 3767.0560999999075, 160.1727000000104, 1399.4751959999999 - 0.35000000000000003, 36000.0, 0.47857577019748654, 3023.8359999997037, 261.6603000000293, 1599.400224 - 0.35000000000000003, 36000.0, 0.5383977414721723, 2280.645399999944, 363.15139999996495, 1799.325252 - 0.35000000000000003, 36000.0, 0.5982197127468581, 1537.4407999999187, 464.62709999994354, 1999.25028 - 0.35000000000000003, 36000.0, 0.658041684021544, 1231.5360999999134, 558.7256000000657, 2199.175308 - 0.35000000000000003, 36000.0, 0.7178636552962298, 1878.8639000000571, 756.5796999998695, 2399.100336 - 0.35000000000000003, 36000.0, 0.7776856265709157, 494.8921000002565, 785.5066999999945, 2599.025364 - 0.35000000000000003, 36000.0, 0.8375075978456014, 8917.534199998934, 2596.3635000003906, 2798.9503919999997 - 0.35000000000000003, 36000.0, 0.8973295691202872, 6736.400899999915, 2701.7914999997724, 2998.87542 - 0.35000000000000003, 36000.0, 0.9571515403949731, 1987.7441999995171, -502.830200000597, 3198.800448 - 0.35000000000000003, 39000.0, 0.0, 149.67096345224525, 149.67096345224525, 0.0 - 0.35000000000000003, 39000.0, 0.3586393761220826, -1099.8343000000089, -351.7334000000086, 1198.572795 - 0.35000000000000003, 39000.0, 0.41841260547576303, -812.4277000000135, -213.00530000001217, 1398.3349275 - 0.35000000000000003, 39000.0, 0.4781858348294435, -525.0480000001095, -74.27510000003471, 1598.09706 - 0.35000000000000003, 39000.0, 0.5379590641831239, -237.64720000013287, 64.46349999998127, 1797.8591925 - 0.35000000000000003, 39000.0, 0.5977322935368043, 49.734000000072186, 203.1971999999966, 1997.621325 - 0.35000000000000003, 39000.0, 0.6575055228904848, 252.7609999998765, 300.4039000000438, 2197.3834575 - 0.35000000000000003, 39000.0, 0.7172787522441652, 1379.740399999649, 601.424200000054, 2397.14559 - 0.35000000000000003, 39000.0, 0.7770519815978456, 1707.121400000267, 708.545700000071, 2596.9077225 - 0.35000000000000003, 39000.0, 0.8368252109515261, 3977.511800000203, 760.317200000367, 2796.669855 - 0.35000000000000003, 39000.0, 0.8965984403052065, 5244.925800000429, 2098.5464000005422, 2996.4319875 - 0.35000000000000003, 39000.0, 0.956371669658887, 16269.082500000211, 8764.223300000975, 3196.19412 - 0.35000000000000003, 42000.0, 0.0, 129.57358731945757, 129.57358731945757, 0.0 - 0.35000000000000003, 42000.0, 0.3586393761220826, -78983.18996250023, -30208.154975000063, 1198.572795 - 0.35000000000000003, 42000.0, 0.41841260547576303, -61921.365137500245, -23615.111125000058, 1398.3349275 - 0.35000000000000003, 42000.0, 0.4781858348294435, -44859.5501875002, -17022.061118750058, 1598.09706 - 0.35000000000000003, 42000.0, 0.5379590641831239, -27797.75776249939, -10429.001018750107, 1797.8591925 - 0.35000000000000003, 42000.0, 0.5977322935368043, -10735.945999999847, -3835.9741687500605, 1997.621325 - 0.35000000000000003, 42000.0, 0.6575055228904848, -2092.4923187500654, -575.4190750000789, 2197.3834575 - 0.35000000000000003, 42000.0, 0.7172787522441652, 2346.460612499827, 645.948768750075, 2397.14559 - 0.35000000000000003, 42000.0, 0.7770519815978456, 28.359456250032963, 653.2664500002124, 2596.9077225 - 0.35000000000000003, 42000.0, 0.8368252109515261, 6023.070462500245, 2990.1968375000033, 2796.669855 - 0.35000000000000003, 42000.0, 0.8965984403052065, 1882.3891749999802, 805.6271250002965, 2996.4319875 - 0.35000000000000003, 42000.0, 0.956371669658887, 8216.781543750672, 4770.240850001006, 3196.19412 - 0.4, 0.0, 0.0, 683.0627788169501, 683.0627788169501, 0.0 - 0.4, 0.0, 0.48049141831238773, -1668.0940000000032, 21.415500000000065, 1605.8023199999998 - 0.4, 0.0, 0.5605733213644524, 256.0641999999999, 717.9128999999815, 1873.4360399999998 - 0.4, 0.0, 0.640655224416517, 2180.222400000022, 1414.4103999999504, 2141.06976 - 0.4, 0.0, 0.7207371274685815, 4596.58789999996, 2221.995600000102, 2408.7034799999997 - 0.4, 0.0, 0.8008190305206463, 7693.731000000509, 3363.503399999954, 2676.3372 - 0.4, 0.0, 0.8809009335727109, 11317.468800000395, 4915.298800000162, 2943.9709199999998 - 0.4, 0.0, 0.9609828366247755, 16269.150400000764, 7008.135700000263, 3211.6046399999996 - 0.4, 3000.0, 0.0, 618.6031925405131, 618.6031925405131, 0.0 - 0.4, 3000.0, 0.470580883303411, -1854.5714780096203, -68.07804690458273, 1572.6813119999997 - 0.4, 3000.0, 0.5490110305206463, 9.84715404219795, 576.1846389829623, 1834.7948639999997 - 0.4, 3000.0, 0.6274411777378814, 1874.265552771971, 1220.4472001755557, 2096.9084159999998 - 0.4, 3000.0, 0.7058713249551166, 3895.9089664878247, 1925.0278098149508, 2359.0219679999996 - 0.4, 3000.0, 0.7843014721723518, 6609.737412566807, 2909.9493632845124, 2621.13552 - 0.4, 3000.0, 0.862731619389587, 10118.806898024477, 4268.758614599299, 2883.2490719999996 - 0.4, 3000.0, 0.941161766606822, 14841.293317746662, 6153.5577474078045, 3145.3626239999994 - 0.4, 6000.0, 0.0, 559.0455982997187, 559.0455982997187, 0.0 - 0.4, 6000.0, 0.4606694219030521, -2030.2658999999994, -153.78899999999996, 1539.5572080000002 - 0.4, 6000.0, 0.5374476588868942, -276.72920000000084, 441.2673000000023, 1796.1500760000001 - 0.4, 6000.0, 0.6142258958707361, 1476.8073999999945, 1036.3237000000072, 2052.742944 - 0.4, 6000.0, 0.6910041328545782, 3306.417999999998, 1662.677200000013, 2309.3358120000003 - 0.4, 6000.0, 0.7677823698384201, 5690.17330000006, 2514.907199999978, 2565.92868 - 0.4, 6000.0, 0.8445606068222622, 8775.895499999911, 3689.9866000000475, 2822.521548 - 0.4, 6000.0, 0.9213388438061042, 12875.938499999873, 5312.222200000114, 3079.1144160000003 - 0.4, 6000.0, 0.9981170807899462, 17540.921899999903, 7250.2881000000125, 3335.707284 - 0.4, 9000.0, 0.0, 504.1119863908427, 504.1119863908427, 0.0 - 0.4, 9000.0, 0.45075888689407545, -2206.7392999999993, -252.41399999999948, 1506.4362 - 0.4, 9000.0, 0.5258853680430879, -551.2396999999955, 302.5590999999988, 1757.5089 - 0.4, 9000.0, 0.6010118491921005, 1104.2596000000121, 857.5321999999938, 2008.5816 - 0.4, 9000.0, 0.6761383303411131, 2770.1293999999843, 1417.1211000000014, 2259.6543 - 0.4, 9000.0, 0.7512648114901256, 4862.40820000004, 2156.256800000008, 2510.727 - 0.4, 9000.0, 0.8263912926391382, 7573.585399999938, 3174.4724000000497, 2761.7997 - 0.4, 9000.0, 0.9015177737881509, 11153.245099999987, 4573.711400000064, 3012.8724 - 0.4, 9000.0, 0.9766442549371633, 15268.127000000233, 6285.814899999968, 3263.9451 - 0.4, 12000.0, 0.0, 453.5295622640622, 453.5295622640622, 0.0 - 0.4, 12000.0, 0.4408474254937163, -2305.549203999999, -320.3495999999999, 1473.3120959999999 - 0.4, 12000.0, 0.5143219964093356, -768.8100287999936, 188.17093920000084, 1718.8641119999997 - 0.4, 12000.0, 0.5877965673249551, 767.9290016000155, 696.6913720000006, 1964.4161279999998 - 0.4, 12000.0, 0.6612711382405745, 2304.667965599983, 1205.211939999997, 2209.968144 - 0.4, 12000.0, 0.7347457091561939, 4138.79025039993, 1838.253679200001, 2455.52016 - 0.4, 12000.0, 0.8082202800718132, 6506.763993599975, 2707.2267823999746, 2701.0721759999997 - 0.4, 12000.0, 0.8816948509874326, 9608.208797599986, 3901.03119599998, 2946.6241919999998 - 0.4, 12000.0, 0.955169421903052, 13166.092933599939, 5370.391927999954, 3192.176208 - 0.4, 15000.0, 0.0, 407.0430623664859, 407.0430623664859, 0.0 - 0.4, 15000.0, 0.4309368904847397, -2148.7401999999984, -313.1539999999996, 1440.191088 - 0.4, 15000.0, 0.5027597055655296, -795.1206000000053, 132.7379999999977, 1680.222936 - 0.4, 15000.0, 0.5745825206463195, 558.4992999999782, 578.6300999999945, 1920.254784 - 0.4, 15000.0, 0.6464053357271095, 1912.1190999999872, 1024.5221000000122, 2160.286632 - 0.4, 15000.0, 0.7182281508078995, 3473.2656000000047, 1551.7954000000118, 2400.31848 - 0.4, 15000.0, 0.7900509658886894, 5553.717300000019, 2300.0319999999783, 2640.350328 - 0.4, 15000.0, 0.8618737809694794, 8221.80760000003, 3310.4115999999863, 2880.382176 - 0.4, 15000.0, 0.9336965960502693, 11327.861299999973, 4565.060499999995, 3120.414024 - 0.4, 18000.0, 0.0, 364.40427639783564, 364.40427639783564, 0.0 - 0.4, 18000.0, 0.4210254290843806, -2004.8332407999997, -313.20273039999995, 1407.066984 - 0.4, 18000.0, 0.4911963339317774, -808.2493656000019, 81.80208079999984, 1641.578148 - 0.4, 18000.0, 0.5613672387791742, 388.33448959999333, 476.80701519999946, 1876.089312 - 0.4, 18000.0, 0.6315381436265709, 1584.918429600003, 871.8119583999967, 2110.600476 - 0.4, 18000.0, 0.7017090484739678, 2934.3513151999905, 1321.2395383999988, 2345.11164 - 0.4, 18000.0, 0.7718799533213645, 4714.4718808000125, 1946.0219240000013, 2579.622804 - 0.4, 18000.0, 0.8420508581687612, 7037.441006399993, 2811.5908656000042, 2814.133968 - 0.4, 18000.0, 0.912221763016158, 9730.412950400061, 3878.3419480000066, 3048.645132 - 0.4, 18000.0, 0.9823926678635548, 12651.102412000062, 5197.388753600004, 3283.156296 - 0.4, 21000.0, 0.0, 325.3724997702096, 325.3724997702096, 0.0 - 0.4, 21000.0, 0.41111489407540397, -2090.5764544, -362.85247519999996, 1373.945976 - 0.4, 21000.0, 0.47963404308797125, -975.6670032000005, 0.091161599999859, 1602.936972 - 0.4, 21000.0, 0.5481531921005386, 139.24261519999845, 363.0348071999997, 1831.927968 - 0.4, 21000.0, 0.6166723411131059, 1254.152327199999, 725.9783824000007, 2060.918964 - 0.4, 21000.0, 0.6851914901256733, 2425.448144799999, 1110.0176167999998, 2289.90996 - 0.4, 21000.0, 0.7537106391382405, 3981.1074608000063, 1644.1415824000026, 2518.900956 - 0.4, 21000.0, 0.8222297881508079, 5964.462583200006, 2368.326612000003, 2747.891952 - 0.4, 21000.0, 0.8907489371633752, 8313.523827199995, 3279.022960800002, 2976.882948 - 0.4, 21000.0, 0.9592680861759425, 10752.8974176, 4374.332284, 3205.873944 - 0.4, 24000.0, 0.0, 289.71977311505464, 289.71977311505464, 0.0 - 0.4, 24000.0, 0.4012034326750449, -2282.4631631999996, -475.01456799999977, 1340.821872 - 0.4, 24000.0, 0.46807067145421904, -1223.719464800001, -126.07290559999987, 1564.2921840000001 - 0.4, 24000.0, 0.5349379102333932, -164.97544080000424, 222.86868959999956, 1787.762496 - 0.4, 24000.0, 0.6018051490125673, 893.7679231999969, 571.8101328000002, 2011.232808 - 0.4, 24000.0, 0.6686723877917415, 1945.4615711999954, 915.9588543999971, 2234.70312 - 0.4, 24000.0, 0.7355396265709157, 3347.2738919999906, 1385.9118903999984, 2458.173432 - 0.4, 24000.0, 0.8024068653500898, 5076.371366400005, 1998.1921927999983, 2681.643744 - 0.4, 24000.0, 0.8692741041292639, 7042.629872799978, 2746.5405759999967, 2905.114056 - 0.4, 24000.0, 0.9361413429084381, 9151.862956800043, 3667.2089719999926, 3128.5843680000003 - 0.4, 27000.0, 0.0, 257.22519309360155, 257.22519309360155, 0.0 - 0.4, 27000.0, 0.3912928976660683, -1807.2532071999956, -199.04376399999987, 1307.7008640000001 - 0.4, 27000.0, 0.456508380610413, -991.7983495999897, 38.99062080000045, 1525.6510080000003 - 0.4, 27000.0, 0.5217238635547576, -176.34630399998437, 277.0228319999996, 1743.6011520000002 - 0.4, 27000.0, 0.5869393464991024, 639.1065927999852, 515.0550431999899, 1961.551296 - 0.4, 27000.0, 0.652154829443447, 1475.5717423999913, 755.6435880000065, 2179.50144 - 0.4, 27000.0, 0.7173703123877918, 2716.5121944000152, 1128.1283631999827, 2397.4515840000004 - 0.4, 27000.0, 0.7825857953321366, 4217.788883200014, 1654.7635159999916, 2615.4017280000003 - 0.4, 27000.0, 0.8478012782764812, 5842.676319999998, 2330.4320287999926, 2833.351872 - 0.4, 27000.0, 0.913016761220826, 7939.485508800103, 3106.915513600064, 3051.3020160000005 - 0.4, 27000.0, 0.9782322441651707, 9155.313681600006, 3925.6477472000247, 3269.2521600000005 - 0.4, 30000.0, 0.0, 227.6801423366946, 227.6801423366946, 0.0 - 0.4, 30000.0, 0.38138143626570914, -2055.9148000000105, -418.6676000000018, 1274.57676 - 0.4, 30000.0, 0.44494500897666067, -1153.926000000009, -144.97100000000415, 1487.00622 - 0.4, 30000.0, 0.5085085816876123, -251.96879999998282, 128.73469999999205, 1699.43568 - 0.4, 30000.0, 0.5720721543985637, 650.004000000027, 402.4347999999976, 1911.86514 - 0.4, 30000.0, 0.6356357271095153, 1438.752899999973, 630.767499999974, 2124.2946 - 0.4, 30000.0, 0.6991992998204668, 1970.8082000000961, 908.0242000000571, 2336.72406 - 0.4, 30000.0, 0.7627628725314183, 3357.552499999883, 1310.0274999999901, 2549.15352 - 0.4, 30000.0, 0.8263264452423699, 4915.993799999826, 1801.4822999999126, 2761.58298 - 0.4, 30000.0, 0.8898900179533213, 6883.9649999999465, 2789.628899999958, 2974.01244 - 0.4, 30000.0, 0.9534535906642729, 9134.169400000219, 3543.909799999683, 3186.4419000000003 - 0.4, 33000.0, 0.0, 200.881469063069, 200.881469063069, 0.0 - 0.4, 33000.0, 0.37147090125673254, 2071.918154399991, -65.3686816000037, 1241.455752 - 0.4, 33000.0, 0.4333827181328546, 1886.1142687999345, 72.74179039999981, 1448.3650440000001 - 0.4, 33000.0, 0.4952945350089767, 1700.3012543998755, 210.85097440000592, 1655.2743360000002 - 0.4, 33000.0, 0.5572063518850988, 1514.4866943999625, 348.96691119998786, 1862.1836280000002 - 0.4, 33000.0, 0.6191181687612208, 1328.6677551999628, 487.07063039998286, 2069.09292 - 0.4, 33000.0, 0.681029985637343, 1511.6516144000207, 720.1166008000149, 2276.0022120000003 - 0.4, 33000.0, 0.7429418025134651, 3305.1731415999616, 1341.6158408000108, 2482.911504 - 0.4, 33000.0, 0.8048536193895872, 4482.11268320016, 1733.6770800000518, 2689.8207960000004 - 0.4, 33000.0, 0.8667654362657092, 5088.722437599762, 1914.439790400013, 2896.7300880000003 - 0.4, 33000.0, 0.9286772531418314, 6215.402754400155, 2535.6401127999734, 3103.6393800000005 - 0.4, 33000.0, 0.9905890700179534, 2715.3993264003475, 271.1456615997158, 3310.5486720000004 - 0.4, 36000.0, 0.0, 176.63833787526158, 176.63833787526158, 0.0 - 0.4, 36000.0, 0.36155943985637345, 1531.2354000000068, -226.92239999999637, 1208.331648 - 0.4, 36000.0, 0.42181934649910235, 1419.7548999999472, -63.18799999999332, 1409.720256 - 0.4, 36000.0, 0.48207925314183125, 1308.2534999998284, 100.54640000001775, 1611.108864 - 0.4, 36000.0, 0.5423391597845602, 1196.7694999999637, 264.2827999999786, 1812.497472 - 0.4, 36000.0, 0.602599066427289, 1085.277099999953, 428.01029999996814, 2013.88608 - 0.4, 36000.0, 0.662858973070018, 1233.0794999999466, 588.1072000000377, 2215.274688 - 0.4, 36000.0, 0.7231188797127469, 1967.3940000000218, 829.6739999999113, 2416.663296 - 0.4, 36000.0, 0.7833787863554758, 1633.3106000001612, 1022.9355000000044, 2618.051904 - 0.4, 36000.0, 0.8436386929982047, 7097.680099999437, 2279.5388000002094, 2819.440512 - 0.4, 36000.0, 0.9038985996409336, 6256.716499999935, 2599.4552999998587, 3020.82912 - 0.4, 36000.0, 0.9641585062836625, 3384.1849999997285, 710.9515999996339, 3222.217728 - 0.4, 39000.0, 0.0, 152.9821492144476, 152.9821492144476, 0.0 - 0.4, 39000.0, 0.36126484739676845, -1328.5093000000038, -394.78600000000546, 1207.3471200000001 - 0.4, 39000.0, 0.4214756552962298, -956.6979999999991, -235.44080000000758, 1408.5716400000001 - 0.4, 39000.0, 0.48168646319569125, -584.9018000000325, -76.09410000002143, 1609.79616 - 0.4, 39000.0, 0.5418972710951526, -213.0931000000762, 83.25749999999019, 1811.02068 - 0.4, 39000.0, 0.602108078994614, 158.70370000004257, 242.60619999999753, 2012.2452 - 0.4, 39000.0, 0.6623188868940754, 492.2061999999267, 375.91960000002126, 2213.46972 - 0.4, 39000.0, 0.7225296947935369, 1484.3647999997984, 665.4487000000278, 2414.6942400000003 - 0.4, 39000.0, 0.7827405026929982, 2077.3499000001393, 881.1992000000447, 2615.91876 - 0.4, 39000.0, 0.8429513105924596, 3860.6915000001327, 1073.0338000002043, 2817.1432800000002 - 0.4, 39000.0, 0.903162118491921, 4961.6513000002, 2057.897600000303, 3018.3678 - 0.4, 39000.0, 0.9633729263913825, 11464.825500000024, 6025.860700000524, 3219.59232 - 0.4, 42000.0, 0.0, 132.44015681024968, 132.44015681024968, 0.0 - 0.4, 42000.0, 0.36126484739676845, -55155.42353750015, -21038.60862500004, 1207.3471200000001 - 0.4, 42000.0, 0.4214756552962298, -43219.89843750017, -16428.95807500004, 1408.5716400000001 - 0.4, 42000.0, 0.48168646319569125, -31284.37918750012, -11819.303706250035, 1609.79616 - 0.4, 42000.0, 0.5418972710951526, -19348.87543749961, -7209.642431250066, 1811.02068 - 0.4, 42000.0, 0.602108078994614, -7413.35862499991, -2600.003256250041, 2012.2452 - 0.4, 42000.0, 0.6623188868940754, -1193.6853312500402, -249.71960000006322, 2213.46972 - 0.4, 42000.0, 0.7225296947935369, 1960.611162499872, 644.6076812500502, 2414.6942400000003 - 0.4, 42000.0, 0.7827405026929982, 730.4577687500287, 742.7688000001347, 2615.91876 - 0.4, 42000.0, 0.8429513105924596, 4959.910287500137, 2406.4227625000008, 2817.1432800000002 - 0.4, 42000.0, 0.903162118491921, 2620.2034249999306, 1161.5412500001694, 3018.3678 - 0.4, 42000.0, 0.9633729263913825, 7330.556506250279, 4092.741225000631, 3219.59232 - 0.45, 0.0, 0.0, 700.0801797612189, 700.0801797612189, 0.0 - 0.45, 0.0, 0.48444895421903045, -1957.0349500000066, 37.69040000000001, 1619.0284049999998 - 0.45, 0.0, 0.5651904465888689, 21.957100000003265, 753.092899999968, 1888.8664724999999 - 0.45, 0.0, 0.6459319389587073, 2000.9496500000573, 1468.495799999914, 2158.7045399999997 - 0.45, 0.0, 0.7266734313285457, 4478.61794999991, 2317.0561000001526, 2428.5426074999996 - 0.45, 0.0, 0.8074149236983841, 7451.707250000847, 3502.420649999905, 2698.3806749999994 - 0.45, 0.0, 0.8881564160682225, 10753.29930000068, 5106.915250000233, 2968.2187424999997 - 0.45, 0.0, 0.9688979084380609, 15828.844000001009, 7274.212600000403, 3238.0568099999996 - 0.45, 3000.0, 0.0, 634.0146874708897, 634.0146874708897, 0.0 - 0.45, 3000.0, 0.47445679174147215, -1796.1283514960214, -34.76444812718276, 1585.6345979999999 - 0.45, 3000.0, 0.5535329236983841, -4.540111182996828, 619.5601725047652, 1849.9070309999997 - 0.45, 3000.0, 0.6326090556552961, 1787.0484633081803, 1273.8849800307673, 2114.179464 - 0.45, 3000.0, 0.7116851876122082, 3770.802263345414, 2002.1491059367556, 2378.451897 - 0.45, 3000.0, 0.7907613195691203, 6548.778538851607, 3041.3102339725506, 2642.72433 - 0.45, 3000.0, 0.8698374515260322, 10052.928444097217, 4456.011219709164, 2906.9967629999996 - 0.45, 3000.0, 0.9489135834829443, 14817.911338693037, 6437.99158460088, 3171.2691959999997 - 0.45, 6000.0, 0.0, 572.9733123948596, 572.9733123948596, 0.0 - 0.45, 6000.0, 0.4644636952423699, -2049.6963000000005, -125.00559999999997, 1552.2376695000003 - 0.45, 6000.0, 0.5418743111160982, -324.203100000003, 480.8055000000044, 1810.9439477500002 - 0.45, 6000.0, 0.6192849269898265, 1401.2902999999785, 1086.6167000000137, 2069.650226 - 0.45, 6000.0, 0.6966955428635548, 3221.1557999999964, 1734.3525000000222, 2328.3565042500004 - 0.45, 6000.0, 0.7741061587372831, 5625.920900000156, 2623.0971999999456, 2587.0627825 - 0.45, 6000.0, 0.8515167746110115, 8795.058599999751, 3866.755400000111, 2845.7690607500003 - 0.45, 6000.0, 0.9289273904847398, 12959.425799999723, 5575.212400000224, 3104.4753390000005 - 0.45, 9000.0, 0.0, 516.6711186686733, 516.6711186686733, 0.0 - 0.45, 9000.0, 0.45447153276481145, -2181.190200000001, -228.1026999999999, 1518.8438625 - 0.45, 9000.0, 0.5302167882256134, -563.1777000000128, 337.4621000000017, 1771.9845062499999 - 0.45, 9000.0, 0.6059620436864153, 1054.834699999966, 903.0270000000058, 2025.1251499999998 - 0.45, 9000.0, 0.6817072991472172, 2703.822300000023, 1482.3687999999972, 2278.26579375 - 0.45, 9000.0, 0.7574525546080191, 4820.762700000048, 2256.1581999999953, 2531.4064375 - 0.45, 9000.0, 0.833197810068821, 7577.894000000029, 3320.918000000023, 2784.54708125 - 0.45, 9000.0, 0.9089430655296229, 11215.82320000009, 4795.226099999938, 3037.687725 - 0.45, 9000.0, 0.9846883209904248, 15292.752900000112, 6569.528800000084, 3290.8283687499998 - 0.45, 12000.0, 0.0, 464.82851550887733, 464.82851550887733, 0.0 - 0.45, 12000.0, 0.4444784362657091, -2217.087730399999, -298.7033951999998, 1485.4469339999998 - 0.45, 12000.0, 0.5185581756433273, -730.5531519999992, 219.82969840000158, 1733.0214229999997 - 0.45, 12000.0, 0.5926379150209454, 755.9814679999953, 738.3626920000032, 1980.5959119999998 - 0.45, 12000.0, 0.6667176543985637, 2241.808226400012, 1256.5811488000033, 2228.170401 - 0.45, 12000.0, 0.7407973937761819, 4085.417782399986, 1920.3996080000038, 2475.74489 - 0.45, 12000.0, 0.8148771331538, 6517.659347200003, 2839.2711984000275, 2723.3193789999996 - 0.45, 12000.0, 0.8889568725314182, 9678.488119199943, 4098.610881600032, 2970.8938679999997 - 0.45, 12000.0, 0.9630366119090364, 13226.14387360014, 5635.884553599994, 3218.4683569999997 - 0.45, 15000.0, 0.0, 417.18387988529514, 417.18387988529514, 0.0 - 0.45, 15000.0, 0.4344862737881508, -2248.1764999999987, -334.01469999999927, 1452.053127 - 0.45, 15000.0, 0.5069006527528426, -885.0414000000102, 132.60320000000033, 1694.0619815 - 0.45, 15000.0, 0.5793150317175344, 478.0936999999731, 599.2211000000017, 1936.0708359999999 - 0.45, 15000.0, 0.6517294106822261, 1841.228900000012, 1065.8390000000138, 2178.0796904999997 - 0.45, 15000.0, 0.724143789646918, 3426.262700000081, 1625.1362000000022, 2420.0885449999996 - 0.45, 15000.0, 0.7965581686116098, 5560.950700000007, 2412.0569000000614, 2662.0973995 - 0.45, 15000.0, 0.8689725475763016, 8306.400400000102, 3482.9608999999764, 2904.106254 - 0.45, 15000.0, 0.9413869265409933, 11366.819300000034, 4794.442900000058, 3146.1151084999997 - 0.45, 18000.0, 0.0, 373.4828177407096, 373.4828177407096, 0.0 - 0.45, 18000.0, 0.42449317728904845, -2042.914528799998, -320.9311143999999, 1418.6561984999998 - 0.45, 18000.0, 0.4952420401705565, -852.7941616000021, 88.48378879999879, 1655.0988982499998 - 0.45, 18000.0, 0.5659909030520646, 337.32636559999014, 497.8986271999961, 1891.5415979999998 - 0.45, 18000.0, 0.6367397659335726, 1527.447005600008, 907.3134623999873, 2127.9842977499998 - 0.45, 18000.0, 0.7074886288150807, 2879.140647199961, 1378.1528223999953, 2364.4269974999997 - 0.45, 18000.0, 0.7782374916965887, 4695.796328800072, 2036.702904000002, 2600.8696972499997 - 0.45, 18000.0, 0.8489863545780969, 7087.478010399991, 2955.119881600004, 2837.3123969999997 - 0.45, 18000.0, 0.919735217459605, 9753.165534400208, 4068.4822480000066, 3073.7550967499997 - 0.45, 18000.0, 0.990484080341113, 12682.644692000187, 5434.405169599993, 3310.1977964999996 - 0.45, 21000.0, 0.0, 333.4786277229266, 333.4786277229266, 0.0 - 0.45, 21000.0, 0.4145010148114901, -1995.2452983999997, -348.56392719999997, 1385.2623915 - 0.45, 21000.0, 0.4835845172800718, -920.2198751999987, 21.385837599999846, 1616.13945675 - 0.45, 21000.0, 0.5526680197486534, 154.8055472000045, 391.33559919999914, 1847.016522 - 0.45, 21000.0, 0.6217515222172351, 1229.830999200002, 761.285466400001, 2077.8935872499997 - 0.45, 21000.0, 0.6908350246858168, 2390.0780327999887, 1162.5720247999934, 2308.7706525 - 0.45, 21000.0, 0.7599185271543986, 3971.2064287999724, 1723.096666399986, 2539.64771775 - 0.45, 21000.0, 0.8290020296229802, 6011.445315199985, 2492.4144719999917, 2770.524783 - 0.45, 21000.0, 0.8980855320915618, 8327.789999199958, 3437.953708799992, 3001.4018482499996 - 0.45, 21000.0, 0.9671690345601436, 10831.576913599956, 4602.314423999992, 3232.2789135 - 0.45, 24000.0, 0.0, 296.937671225563, 296.937671225563, 0.0 - 0.45, 24000.0, 0.4045079183123878, -2081.4284312, -400.59832800000004, 1351.865463 - 0.45, 24000.0, 0.4719259046977857, -1081.0080767999998, -60.5732096000001, 1577.1763735 - 0.45, 24000.0, 0.5393438910831837, -80.58787279999936, 279.4519135999998, 1802.487284 - 0.45, 24000.0, 0.6067618774685817, 919.8322911999998, 619.4770647999999, 2027.7981945000001 - 0.45, 24000.0, 0.6741798638539797, 1924.3391992000036, 961.1961104000004, 2253.109105 - 0.45, 24000.0, 0.7415978502393776, 3292.9577319999994, 1439.0206064000013, 2478.4200155 - 0.45, 24000.0, 0.8090158366247756, 5058.8025824, 2088.121244799998, 2703.730926 - 0.45, 24000.0, 0.8764338230101736, 7044.421964800007, 2884.7883960000054, 2929.0418365 - 0.45, 24000.0, 0.9438518093955715, 9175.571628799988, 3850.600191999998, 3154.352747 - 0.45, 27000.0, 0.0, 263.6335414615541, 263.6335414615541, 0.0 - 0.45, 27000.0, 0.39451575583482945, -2125.6899751999995, -401.133764, 1318.471656 - 0.45, 27000.0, 0.46026838180730095, -1212.5613735999973, -100.97948719999977, 1538.2169319999998 - 0.45, 27000.0, 0.5260210077797726, -299.4335839999948, 199.1741120000002, 1757.962208 - 0.45, 27000.0, 0.5917736337522441, 613.694524799997, 499.3277111999971, 1977.707484 - 0.45, 27000.0, 0.6575262597247158, 1533.4883383999988, 800.8446480000013, 2197.45276 - 0.45, 27000.0, 0.7232788856971872, 2704.9806904000047, 1194.7192511999965, 2417.198036 - 0.45, 27000.0, 0.7890315116696589, 4235.971591199998, 1747.7220959999943, 2636.943312 - 0.45, 27000.0, 0.8547841376421305, 5958.2961399999795, 2433.889520799993, 2856.688588 - 0.45, 27000.0, 0.9205367636146019, 7877.412180800003, 3246.5289576000127, 3076.4338639999996 - 0.45, 27000.0, 0.9862893895870736, 9363.715645600007, 4112.045375199989, 3296.1791399999997 - 0.45, 30000.0, 0.0, 233.3524236984492, 233.3524236984492, 0.0 - 0.45, 30000.0, 0.38452265933572716, -2119.268100000005, -468.67870000000056, 1285.0747275 - 0.45, 30000.0, 0.448609769225015, -1246.3005000000046, -180.77020000000107, 1499.25384875 - 0.45, 30000.0, 0.5126968791143028, -373.3471999999951, 107.14219999999837, 1713.43297 - 0.45, 30000.0, 0.5767839890035906, 499.6130000000109, 395.0520999999982, 1927.61209125 - 0.45, 30000.0, 0.6408710988928786, 1327.2838999999876, 664.8154999999888, 2141.7912125000003 - 0.45, 30000.0, 0.7049582087821664, 2084.7233000000356, 971.2114000000213, 2355.97033375 - 0.45, 30000.0, 0.7690453186714543, 3438.4736999999427, 1419.6817999999903, 2570.149455 - 0.45, 30000.0, 0.8331324285607421, 5001.601799999912, 1979.9136999999562, 2784.32857625 - 0.45, 30000.0, 0.89721953845003, 6745.027799999972, 2802.2571999999814, 2998.5076975 - 0.45, 30000.0, 0.9613066483393178, 8543.964800000062, 3595.8045999998685, 3212.68681875 - 0.45, 33000.0, 0.0, 205.88610495794342, 205.88610495794342, 0.0 - 0.45, 33000.0, 0.3745304968581688, -79.32923760000472, -312.7224536000017, 1251.6809205000002 - 0.45, 33000.0, 0.4369522463345303, 217.7307447999642, -105.2325816000006, 1460.2944072500002 - 0.45, 33000.0, 0.49937399581089176, 514.7858223999299, 102.25646240000151, 1668.9078940000002 - 0.45, 33000.0, 0.5617957452872532, 811.840182399979, 309.74895519999257, 1877.5213807500002 - 0.45, 33000.0, 0.6242174947636148, 1108.8922791999812, 517.2353783999948, 2086.1348675000004 - 0.45, 33000.0, 0.6866392442399761, 1635.2080824000109, 787.2769368000093, 2294.7483542500004 - 0.45, 33000.0, 0.7490609937163376, 3074.0255135999737, 1293.7390168000143, 2503.3618410000004 - 0.45, 33000.0, 0.8114827431926991, 4342.638807200094, 1748.3225400000283, 2711.9753277500004 - 0.45, 33000.0, 0.8739044926690606, 5396.402349599932, 2161.4751584000355, 2920.5888145000004 - 0.45, 33000.0, 0.936326242145422, 6445.206122400138, 2739.0730888000144, 3129.2023012500003 - 0.45, 33000.0, 0.9987479916217835, 4940.57453440031, 1760.5197135999297, 3337.8157880000003 - 0.45, 36000.0, 0.0, 181.03899548825387, 181.03899548825387, 0.0 - 0.45, 36000.0, 0.36453740035906645, -448.6354999999958, -415.55659999999807, 1218.2839920000001 - 0.45, 36000.0, 0.42529363375224416, -138.56430000002547, -207.956999999996, 1421.331324 - 0.45, 36000.0, 0.4860498671454219, 171.49619999991523, -0.3573999999896953, 1624.378656 - 0.45, 36000.0, 0.5468061005385997, 481.56579999997996, 207.2431999999886, 1827.4259880000002 - 0.45, 36000.0, 0.6075623339317774, 791.6308999999759, 414.8392999999842, 2030.47332 - 0.45, 36000.0, 0.6683185673249552, 1243.2101999999709, 622.8302000000187, 2233.520652 - 0.45, 36000.0, 0.7290748007181329, 2049.386300000002, 901.6311999999454, 2436.5679840000003 - 0.45, 36000.0, 0.7898310341113107, 2438.017200000094, 1213.961100000009, 2639.6153160000003 - 0.45, 36000.0, 0.8505872675044883, 5870.608399999759, 2102.879300000094, 2842.662648 - 0.45, 36000.0, 0.9113435008976661, 5930.014399999951, 2558.23729999992, 3045.70998 - 0.45, 36000.0, 0.9720997342908438, 4408.108099999841, 1604.074299999797, 3248.757312 - 0.45, 39000.0, 0.0, 156.79345126637196, 156.79345126637196, 0.0 - 0.45, 39000.0, 0.364240381508079, -1539.345900000001, -433.007900000003, 1217.291355 - 0.45, 39000.0, 0.4249471117594255, -1096.7202999999934, -255.6364000000038, 1420.1732475000001 - 0.45, 39000.0, 0.48565384201077205, -654.1019999999937, -78.26390000001078, 1623.0551400000002 - 0.45, 39000.0, 0.5463605722621185, -211.47710000003616, 99.11109999999593, 1825.9370325000002 - 0.45, 39000.0, 0.6070673025134651, 231.1413000000233, 276.48459999999864, 2028.8189250000003 - 0.45, 39000.0, 0.6677740327648115, 669.1399999999619, 441.4119000000078, 2231.7008175 - 0.45, 39000.0, 0.728480763016158, 1571.8701999998975, 727.7795000000114, 2434.58271 - 0.45, 39000.0, 0.7891874932675046, 2355.795200000056, 1022.9601000000242, 2637.4646025 - 0.45, 39000.0, 0.849894223518851, 3797.994900000074, 1321.7634000000967, 2840.3464950000002 - 0.45, 39000.0, 0.9106009537701976, 4790.425300000062, 2067.881900000144, 3043.2283875000003 - 0.45, 39000.0, 0.9713076840215441, 8270.470799999934, 4225.105400000233, 3246.1102800000003 - 0.45, 42000.0, 0.0, 135.7396884484182, 135.7396884484182, 0.0 - 0.45, 42000.0, 0.364240381508079, -36867.1024125001, -14004.379675000027, 1217.291355 - 0.45, 42000.0, 0.4249471117594255, -28864.980237500098, -10914.060025000024, 1420.1732475000001 - 0.45, 42000.0, 0.48565384201077205, -20862.86108750005, -7823.738243750025, 1623.0551400000002 - 0.45, 42000.0, 0.5463605722621185, -12860.752012499768, -4733.411993750035, 1825.9370325000002 - 0.45, 42000.0, 0.6070673025134651, -4858.6346499999545, -1643.099493750024, 2028.8189250000003 - 0.45, 42000.0, 0.6677740327648115, -518.1820937500195, 1.6314749999515925, 2231.7008175 - 0.45, 42000.0, 0.728480763016158, 1684.176812499912, 653.6703437500308, 2434.58271 - 0.45, 42000.0, 0.7891874932675046, 1267.6219312500225, 828.6935500000769, 2637.4646025 - 0.45, 42000.0, 0.849894223518851, 4188.432212500062, 1995.3981874999993, 2840.3464950000002 - 0.45, 42000.0, 0.9106009537701976, 3163.467474999914, 1442.0361750000816, 3043.2283875000003 - 0.45, 42000.0, 0.9713076840215441, 6587.986218750055, 3562.4474000003593, 3246.1102800000003 - 0.5, 0.0, 0.0, 719.4314612671865, 719.4314612671865, 0.0 - 0.5, 0.0, 0.4888720825852782, -2671.868400000012, 32.758699999999806, 1633.8104999999998 - 0.5, 0.0, 0.570350763016158, -449.10809999999054, 779.4904999999499, 1906.1122499999997 - 0.5, 0.0, 0.6518294434470376, 1773.6538000001156, 1526.2232999998648, 2178.4139999999998 - 0.5, 0.0, 0.7333081238779173, 4378.321799999829, 2426.6747000002115, 2450.71575 - 0.5, 0.0, 0.8147868043087971, 6999.002800001287, 3647.612599999831, 2723.0175 - 0.5, 0.0, 0.8962654847396767, 9737.890400001086, 5289.231700000313, 2995.3192499999996 - 0.5, 0.0, 0.9777441651705564, 15257.612100001203, 7555.28140000058, 3267.6209999999996 - 0.5, 3000.0, 0.0, 651.5398182357003, 651.5398182357003, 0.0 - 0.5, 3000.0, 0.4787886894075404, -1671.1074841824238, 5.00538285021716, 1600.1118 - 0.5, 3000.0, 0.558586804308797, 13.275047991812663, 669.3687714265706, 1866.7970999999998 - 0.5, 3000.0, 0.6383849192100538, 1697.6601824443974, 1333.7336254859874, 2133.4824 - 0.5, 3000.0, 0.7181830341113106, 3635.0820330029937, 2087.9470674585764, 2400.1677 - 0.5, 3000.0, 0.7979811490125673, 6571.444319536395, 3191.7589686606066, 2666.853 - 0.5, 3000.0, 0.877779263913824, 10002.666208570048, 4663.660854219054, 2933.5382999999997 - 0.5, 3000.0, 0.9575773788150808, 14493.51879823957, 6706.772401393939, 3200.2236 - 0.5, 6000.0, 0.0, 588.8111666636969, 588.8111666636969, 0.0 - 0.5, 6000.0, 0.46870435368043095, -2323.4404000000004, -95.11250000000001, 1566.4099500000002 - 0.5, 6000.0, 0.5468217459605027, -537.0041000000043, 523.0816000000067, 1827.4782750000002 - 0.5, 6000.0, 0.6249391382405746, 1249.4337999999539, 1141.2758000000201, 2088.5466 - 0.5, 6000.0, 0.7030565305206464, 3131.3496999999998, 1813.3182000000352, 2349.6149250000003 - 0.5, 6000.0, 0.7811739228007182, 5635.994200000299, 2747.6319999998914, 2610.68325 - 0.5, 6000.0, 0.85929131508079, 8788.324299999487, 4048.3206000002106, 2871.7515750000002 - 0.5, 6000.0, 0.9374087073608619, 13071.733399999477, 5872.367700000376, 3132.8199000000004 - 0.5, 9000.0, 0.0, 530.9526946258313, 530.9526946258313, 0.0 - 0.5, 9000.0, 0.458620960502693, -2094.9580000000024, -195.28970000000027, 1532.71125 - 0.5, 9000.0, 0.5350577872531418, -526.4188999999924, 380.4171000000015, 1788.163125 - 0.5, 9000.0, 0.6114946140035906, 1042.120000000015, 956.124000000001, 2043.615 - 0.5, 9000.0, 0.6879314407540394, 2662.1138000000014, 1556.1228000000012, 2299.066875 - 0.5, 9000.0, 0.7643682675044884, 4775.583500000009, 2364.992699999983, 2554.51875 - 0.5, 9000.0, 0.8408050942549371, 7591.811000000019, 3485.4104000000293, 2809.970625 - 0.5, 9000.0, 0.917241921005386, 11306.148399999965, 5046.372599999943, 3065.4225 - 0.5, 9000.0, 0.9936787477558348, 15293.14839999986, 6872.208499999927, 3320.874375 - 0.5, 12000.0, 0.0, 477.6770830239316, 477.6770830239316, 0.0 - 0.5, 12000.0, 0.4485366247755835, -2187.2654264000016, -271.27167760000015, 1499.0094 - 0.5, 12000.0, 0.5232927289048473, -726.7940200000031, 257.4959855999987, 1748.8443 - 0.5, 12000.0, 0.5980488330341113, 733.6773127999961, 786.2635487999963, 1998.6792 - 0.5, 12000.0, 0.6728049371633752, 2198.0139392000056, 1316.603116000014, 2248.5141 - 0.5, 12000.0, 0.7475610412926392, 4042.146279200021, 2012.5947200000026, 2498.349 - 0.5, 12000.0, 0.822317145421903, 6520.894839200028, 2982.3744815999744, 2748.1839 - 0.5, 12000.0, 0.897073249551167, 9754.751044000044, 4315.032924000043, 2998.0188 - 0.5, 12000.0, 0.9718293536804309, 13291.537559200007, 5923.305263999999, 3247.8537 - 0.5, 15000.0, 0.0, 428.71547716914586, 428.71547716914586, 0.0 - 0.5, 15000.0, 0.4384532315978456, -2261.0836999999988, -339.07929999999993, 1465.3107 - 0.5, 15000.0, 0.5115287701974865, -906.3853000000013, 146.08440000000186, 1709.52915 - 0.5, 15000.0, 0.5846043087971275, 448.31319999998357, 631.2480000000036, 1953.7476000000001 - 0.5, 15000.0, 0.6576798473967684, 1803.0116999999882, 1116.4117000000044, 2197.96605 - 0.5, 15000.0, 0.7307553859964094, 3403.829100000003, 1708.3110000000179, 2442.1845000000003 - 0.5, 15000.0, 0.8038309245960503, 5551.820799999937, 2532.8901000000446, 2686.40295 - 0.5, 15000.0, 0.8769064631956912, 8343.470700000102, 3663.9961000000026, 2930.6214 - 0.5, 15000.0, 0.9499820017953322, 11431.692400000118, 5044.930700000068, 3174.8398500000003 - 0.5, 18000.0, 0.0, 383.8064511653947, 383.8064511653947, 0.0 - 0.5, 18000.0, 0.4283688958707361, -2094.154205600001, -339.0485783999998, 1431.60885 - 0.5, 18000.0, 0.4997637118491921, -902.8737943999985, 89.6265032000017, 1670.210325 - 0.5, 18000.0, 0.5711585278276481, 288.4068280000008, 518.3015552000043, 1908.8118 - 0.5, 18000.0, 0.6425533438061041, 1479.6873872000026, 946.9766072000012, 2147.413275 - 0.5, 18000.0, 0.71394815978456, 2838.9128223999755, 1442.4125631999755, 2386.01475 - 0.5, 18000.0, 0.785342975763016, 4697.477005600005, 2144.3397479999567, 2624.6162249999998 - 0.5, 18000.0, 0.8567377917414722, 7142.300167199911, 3115.1651495999827, 2863.2177 - 0.5, 18000.0, 0.9281326077199282, 9817.644064799792, 4284.701770399893, 3101.819175 - 0.5, 18000.0, 0.9995274236983842, 12759.608622399688, 5696.337651200022, 3340.42065 - 0.5, 21000.0, 0.0, 342.6964844596952, 342.6964844596952, 0.0 - 0.5, 21000.0, 0.41828550269299825, -1938.541402399999, -331.9819591999999, 1397.9101500000002 - 0.5, 21000.0, 0.48799975314183125, -889.0242271999971, 45.69395359999921, 1630.895175 - 0.5, 21000.0, 0.5577140035906643, 160.49295920000904, 423.3698711999971, 1863.8802 - 0.5, 21000.0, 0.6274282540394973, 1210.0100512000092, 801.0458104000076, 2096.865225 - 0.5, 21000.0, 0.6971425044883304, 2370.8345407999664, 1221.1458527999764, 2329.85025 - 0.5, 21000.0, 0.7668567549371633, 3954.6705167999135, 1808.525510399951, 2562.835275 - 0.5, 21000.0, 0.8365710053859965, 6062.115827199925, 2627.49433199997, 2795.8203000000003 - 0.5, 21000.0, 0.9062852558348296, 8391.195551199897, 3625.281976799994, 3028.8053250000003 - 0.5, 21000.0, 0.9759995062836625, 10947.833549599862, 4860.964163999991, 3261.79035 - 0.5, 24000.0, 0.0, 305.14548031904746, 305.14548031904746, 0.0 - 0.5, 24000.0, 0.4082011669658887, -1947.6706792000007, -367.5045880000001, 1364.2083 - 0.5, 24000.0, 0.4762346947935368, -988.9591088000013, -25.094553599999745, 1591.57635 - 0.5, 24000.0, 0.5442682226211849, -30.247724800001567, 317.31547760000126, 1818.9444 - 0.5, 24000.0, 0.6123017504488331, 928.4636392000017, 659.7256168000013, 2046.3124500000001 - 0.5, 24000.0, 0.6803352782764811, 1919.6853072000154, 1014.1695264000023, 2273.6805 - 0.5, 24000.0, 0.7483688061041293, 3285.743072000008, 1511.5637824000041, 2501.04855 - 0.5, 24000.0, 0.8164023339317774, 5083.210358400028, 2198.3483167999907, 2728.4166 - 0.5, 24000.0, 0.8844358617594255, 7101.83937680006, 3041.490716000025, 2955.78465 - 0.5, 24000.0, 0.9524693895870736, 9226.396620799947, 4053.310012000032, 3183.1527 - 0.5, 27000.0, 0.0, 270.9207737282607, 270.9207737282607, 0.0 - 0.5, 27000.0, 0.39811777378815083, -2136.5261232000003, -450.559164, 1330.5096 - 0.5, 27000.0, 0.464470736086176, -1216.0827376000009, -127.19947520000007, 1552.2612000000001 - 0.5, 27000.0, 0.5308236983842012, -295.63936400000284, 196.16019199999985, 1774.0128000000002 - 0.5, 27000.0, 0.5971766606822263, 624.8040767999979, 519.5198592, 1995.7644000000003 - 0.5, 27000.0, 0.6635296229802514, 1544.4331943999975, 842.6577080000003, 2217.516 - 0.5, 27000.0, 0.7298825852782765, 2710.016146400001, 1261.6905192, 2439.2676 - 0.5, 27000.0, 0.7962355475763017, 4258.356579200003, 1841.4073760000022, 2661.0192 - 0.5, 27000.0, 0.8625885098743268, 6031.02936, 2556.346932800003, 2882.7708000000002 - 0.5, 27000.0, 0.928941472172352, 7875.958372800001, 3409.170541600001, 3104.5224000000003 - 0.5, 27000.0, 0.9952944344703771, 9494.501449600015, 4322.023083200004, 3326.2740000000003 - 0.5, 30000.0, 0.0, 239.8026397903099, 239.8026397903099, 0.0 - 0.5, 30000.0, 0.3880334380610413, -2138.9726000000014, -486.7573, 1296.80775 - 0.5, 30000.0, 0.4527056777378815, -1286.5636000000013, -189.00309999999993, 1512.942375 - 0.5, 30000.0, 0.5173779174147217, -434.1592000000003, 108.7522000000004, 1729.077 - 0.5, 30000.0, 0.5820501570915619, 418.2473000000023, 406.50669999999934, 1945.211625 - 0.5, 30000.0, 0.6467223967684022, 1259.3316999999965, 699.7248999999965, 2161.34625 - 0.5, 30000.0, 0.7113946364452425, 2165.2414000000063, 1035.9325000000042, 2377.480875 - 0.5, 30000.0, 0.7760668761220826, 3503.840399999981, 1520.5798999999922, 2593.6155 - 0.5, 30000.0, 0.8407391157989228, 5078.297899999971, 2132.051899999985, 2809.750125 - 0.5, 30000.0, 0.905411355475763, 6705.98229999999, 2882.2078999999935, 3025.88475 - 0.5, 30000.0, 0.9700835951526032, 8221.598600000001, 3691.4025999999676, 3242.019375 - 0.5, 33000.0, 0.0, 211.57711020332442, 211.57711020332442, 0.0 - 0.5, 33000.0, 0.3779500448833034, -1380.4796896000018, -457.1974856000007, 1263.10905 - 0.5, 33000.0, 0.4409417190305207, -790.0097992000158, -205.13191360000062, 1473.6272250000002 - 0.5, 33000.0, 0.5039333931777379, -199.5420696000317, 46.93319039999984, 1684.1454 - 0.5, 33000.0, 0.5669250673249552, 390.9254103999895, 298.99971919999604, 1894.663575 - 0.5, 33000.0, 0.6299167414721724, 981.391923199993, 551.0638663999994, 2105.18175 - 0.5, 33000.0, 0.6929084156193897, 1715.9610904000047, 846.8171528000048, 2315.6999250000003 - 0.5, 33000.0, 0.7559000897666068, 2950.937645599985, 1294.5644728000098, 2526.2181 - 0.5, 33000.0, 0.8188917639138241, 4283.182251200047, 1800.029100000015, 2736.736275 - 0.5, 33000.0, 0.8818834380610414, 5594.076821599999, 2358.2144664000275, 2947.2544500000004 - 0.5, 33000.0, 0.9448751122082586, 6646.168030400089, 2951.302144800023, 3157.772625 - 0.5, 36000.0, 0.0, 186.04318881714622, 186.04318881714622, 0.0 - 0.5, 36000.0, 0.36786570915619393, -1620.7508999999977, -524.7891999999991, 1229.4072 - 0.5, 36000.0, 0.42917666068222626, -1058.9680000000083, -288.27239999999773, 1434.3084000000001 - 0.5, 36000.0, 0.4904876122082586, -497.18950000003053, -51.75559999999432, 1639.2096000000001 - 0.5, 36000.0, 0.5517985637342909, 64.59289999999119, 184.76159999999524, 1844.1108000000002 - 0.5, 36000.0, 0.6131095152603232, 626.3732999999901, 421.27699999999356, 2049.012 - 0.5, 36000.0, 0.6744204667863555, 1261.599999999987, 662.8181000000078, 2253.9132 - 0.5, 36000.0, 0.7357314183123879, 2126.835699999995, 973.874499999972, 2458.8144 - 0.5, 36000.0, 0.7970423698384203, 2971.6239000000483, 1369.118100000008, 2663.7156000000004 - 0.5, 36000.0, 0.8583533213644525, 5130.288699999933, 2042.286500000029, 2868.6168000000002 - 0.5, 36000.0, 0.9196642728904848, 5736.3086999999605, 2573.4875999999626, 3073.518 - 0.5, 36000.0, 0.9809752244165172, 5137.506199999903, 2244.860799999908, 3278.4192000000003 - 0.5, 39000.0, 0.0, 161.12746085764857, 161.12746085764857, 0.0 - 0.5, 39000.0, 0.36756597845601446, -1726.1108000000002, -466.5846000000014, 1228.4055000000003 - 0.5, 39000.0, 0.42882697486535015, -1225.5561999999936, -273.23300000000114, 1433.1397500000003 - 0.5, 39000.0, 0.4900879712746859, -725.0042999999833, -79.88080000000339, 1637.8740000000003 - 0.5, 39000.0, 0.5513489676840216, -224.4495000000117, 113.472399999999, 1842.6082500000002 - 0.5, 39000.0, 0.6126099640933573, 276.1023000000118, 306.8249999999995, 2047.3425000000002 - 0.5, 39000.0, 0.673870960502693, 795.7262999999846, 499.381600000001, 2252.07675 - 0.5, 39000.0, 0.7351319569120289, 1646.6391999999578, 789.8024000000033, 2456.8110000000006 - 0.5, 39000.0, 0.7963929533213646, 2559.87280000001, 1141.44580000001, 2661.5452500000006 - 0.5, 39000.0, 0.8576539497307003, 3782.2465000000298, 1519.7314000000338, 2866.2795000000006 - 0.5, 39000.0, 0.9189149461400361, 4713.096799999996, 2121.9801000000493, 3071.0137500000005 - 0.5, 39000.0, 0.9801759425493718, 6383.878099999913, 3189.4236000000706, 3275.7480000000005 - 0.5, 42000.0, 0.0, 139.49173999713312, 139.49173999713312, 0.0 - 0.5, 42000.0, 0.36756597845601446, -23385.55478750006, -8821.614925000016, 1228.4055000000003 - 0.5, 42000.0, 0.42882697486535015, -18281.360537500044, -6848.171775000014, 1433.1397500000003 - 0.5, 42000.0, 0.4900879712746859, -13177.167487500014, -4874.7276312500135, 1637.8740000000003 - 0.5, 42000.0, 0.5513489676840216, -8072.980487499877, -2901.280806250016, 1842.6082500000002 - 0.5, 42000.0, 0.6126099640933573, -2968.7886749999857, -927.8417812500142, 2047.3425000000002 - 0.5, 42000.0, 0.673870960502693, -32.007306250009265, 190.2931499999671, 2252.07675 - 0.5, 42000.0, 0.7351319569120289, 1502.8007624999439, 673.1918562500176, 2456.8110000000006 - 0.5, 42000.0, 0.7963929533213646, 1665.6874437500146, 912.774700000037, 2661.5452500000006 - 0.5, 42000.0, 0.8576539497307003, 3668.1112375000225, 1733.7325124999986, 2866.2795000000006 - 0.5, 42000.0, 0.9189149461400361, 3546.0393249999197, 1661.8001000000272, 3071.0137500000005 - 0.5, 42000.0, 0.9801759425493718, 5985.872581249946, 3168.515975000172, 3275.7480000000005 - 0.55, 0.0, 0.0, 741.2309539750436, 741.2309539750436, 0.0 - 0.55, 0.0, 0.49376080341113104, -3974.053075000018, -2.9553000000003067, 1650.1486049999999 - 0.55, 0.0, 0.5760542706463195, -1248.0339499999784, 791.9182999999266, 1925.1733725 - 0.55, 0.0, 0.658347737881508, 1477.9886750002056, 1586.7938999998005, 2200.19814 - 0.55, 0.0, 0.7406412051166966, 4294.25692499971, 2552.22770000028, 2475.2229075 - 0.55, 0.0, 0.8229346723518851, 6245.607175001839, 3795.675774999729, 2750.247675 - 0.55, 0.0, 0.9052281395870736, 8101.429300001626, 5449.917925000403, 3025.2724425 - 0.55, 0.0, 0.9875216068222621, 14492.442100001324, 7846.6608500008, 3300.2972099999997 - 0.55, 3000.0, 0.0, 671.2821262680602, 671.2821262680602, 0.0 - 0.55, 3000.0, 0.48357657630161577, -1432.3976760688272, 52.97974602761698, 1616.1129179999998 - 0.55, 3000.0, 0.5641726723518851, 84.1792315666284, 726.8085357483799, 1885.4650709999999 - 0.55, 3000.0, 0.6447687684021544, 1600.763610180626, 1400.6415365412192, 2154.817224 - 0.55, 3000.0, 0.7253648644524237, 3473.5074754605685, 2182.71979438042, 2424.1693769999997 - 0.55, 3000.0, 0.805960960502693, 6711.016354621169, 3362.7915673486837, 2693.52153 - 0.55, 3000.0, 0.8865570565529622, 9967.947791443024, 4893.651618128972, 2962.873683 - 0.55, 3000.0, 0.9671531526032315, 13630.323596386326, 6929.369597786992, 3232.2258359999996 - 0.55, 6000.0, 0.0, 606.6527338247736, 606.6527338247736, 0.0 - 0.55, 6000.0, 0.4733913972172353, -2990.475000000001, -65.21260000000004, 1582.0740495000002 - 0.55, 6000.0, 0.5522899634201077, -1009.9926000000062, 567.1488000000096, 1845.7530577500002 - 0.55, 6000.0, 0.6311885296229803, 970.494599999917, 1199.5103000000274, 2109.4320660000003 - 0.55, 6000.0, 0.7100870958258529, 3019.591300000012, 1898.9174000000519, 2373.1110742500005 - 0.55, 6000.0, 0.7889856620287254, 5758.484000000499, 2892.714199999804, 2636.7900825000006 - 0.55, 6000.0, 0.8678842282315979, 8693.277599999106, 4221.0170000003645, 2900.4690907500003 - 0.55, 6000.0, 0.9467827944344706, 13161.28219999912, 6201.716500000577, 3164.1480990000005 - 0.55, 9000.0, 0.0, 547.0410922256885, 547.0410922256885, 0.0 - 0.55, 9000.0, 0.4632071701077199, -1970.8767410714336, -155.66269285714333, 1548.0383625 - 0.55, 9000.0, 0.5404083651256733, -459.31712678569954, 430.15506607143146, 1806.0447562499999 - 0.55, 9000.0, 0.6176095601436266, 1052.2420142857447, 1015.9728607142878, 2064.05115 - 0.55, 9000.0, 0.6948107551615798, 2637.095010714283, 1638.6212839285743, 2322.0575437499997 - 0.55, 9000.0, 0.7720119501795331, 4737.155516071457, 2485.621998214252, 2580.0639374999996 - 0.55, 9000.0, 0.8492131451974864, 7626.859844642899, 3671.9032053572005, 2838.0703312499995 - 0.55, 9000.0, 0.9264143402154398, 11417.029544642775, 5327.190191071331, 3096.076725 - 0.55, 12000.0, 0.0, 492.15117631663975, 492.15117631663975, 0.0 - 0.55, 12000.0, 0.4530219910233393, -2116.7963591856064, -238.51940353535358, 1513.999494 - 0.55, 12000.0, 0.5285256561938958, -692.9638733901463, 300.76422051767537, 1766.332743 - 0.55, 12000.0, 0.6040293213644524, 730.8686215593578, 840.0477441287824, 2018.665992 - 0.55, 12000.0, 0.6795329865350089, 2174.6392446969744, 1388.8844814078263, 2270.999241 - 0.55, 12000.0, 0.7550366517055654, 4040.3970987689113, 2121.569023042914, 2523.33249 - 0.55, 12000.0, 0.8305403168761221, 6529.060111805493, 3137.3830963067867, 2775.665739 - 0.55, 12000.0, 0.9060439820466786, 9822.104707260094, 4549.432408270185, 3027.998988 - 0.55, 12000.0, 0.9815476472172352, 13402.779552051634, 6231.9989891413825, 3280.332237 - 0.55, 15000.0, 0.0, 441.7059848428481, 441.7059848428481, 0.0 - 0.55, 15000.0, 0.442837763913824, -2244.3843000000015, -311.1171000000001, 1479.9638069999999 - 0.55, 15000.0, 0.5166440578994613, -904.5432000000011, 184.2204000000013, 1726.6244414999999 - 0.55, 15000.0, 0.5904503518850988, 435.2979999999981, 679.5579000000037, 1973.285076 - 0.55, 15000.0, 0.664256645870736, 1775.1393000000053, 1174.895500000011, 2219.9457104999997 - 0.55, 15000.0, 0.7380629398563734, 3403.266100000056, 1800.471300000021, 2466.6063449999997 - 0.55, 15000.0, 0.8118692338420107, 5568.138700000022, 2669.2791000000393, 2713.2669794999997 - 0.55, 15000.0, 0.885675527827648, 8425.525400000059, 3873.221400000082, 2959.9276139999997 - 0.55, 15000.0, 0.9594818218132853, 11567.98339999998, 5329.789100000073, 3206.5882484999997 - 0.55, 18000.0, 0.0, 395.4361704421573, 395.4361704421573, 0.0 - 0.55, 18000.0, 0.4326525848294434, -2211.9815415999974, -357.7548824000003, 1445.9249384999998 - 0.55, 18000.0, 0.504761348967684, -995.985499999996, 92.51225280000001, 1686.91242825 - 0.55, 18000.0, 0.5768701131059245, 220.01065520000793, 542.7794776000015, 1927.8999179999998 - 0.55, 18000.0, 0.6489788772441651, 1436.0066944000073, 993.046702400003, 2168.88740775 - 0.55, 18000.0, 0.7210876413824057, 2833.160671200017, 1520.3672440000319, 2409.8748975 - 0.55, 18000.0, 0.7931964055206463, 4728.219522400015, 2266.3068320000116, 2650.8623872499998 - 0.55, 18000.0, 0.8653051696588868, 7192.648788000011, 3283.88278720003, 2891.8498769999997 - 0.55, 18000.0, 0.9374139337971273, 9949.77938000013, 4537.130186400038, 3132.8373667499995 - 0.55, 21000.0, 0.0, 353.08053063530826, 353.08053063530826, 0.0 - 0.55, 21000.0, 0.4224683577199282, -2009.0573200000017, -348.76510560000025, 1411.8892515 - 0.55, 21000.0, 0.4928797506732495, -949.5835648000021, 47.17231039999943, 1647.20412675 - 0.55, 21000.0, 0.563291143626571, 109.8899311999936, 443.10964480000007, 1882.519002 - 0.55, 21000.0, 0.6337025365798923, 1169.3634872000032, 839.0469760000057, 2117.83387725 - 0.55, 21000.0, 0.7041139295332137, 2361.7107808000314, 1285.765008000014, 2353.1487525000002 - 0.55, 21000.0, 0.7745253224865349, 3964.1757631999753, 1905.2080752000113, 2588.46362775 - 0.55, 21000.0, 0.8449367154398564, 6116.397459200073, 2777.1616560000057, 2823.778503 - 0.55, 21000.0, 0.9153481083931778, 8496.229542400033, 3834.083450400037, 3059.09337825 - 0.55, 21000.0, 0.985759501346499, 11078.59967360022, 5133.61709920006, 3294.4082535 - 0.55, 24000.0, 0.0, 314.39169351819487, 314.39169351819487, 0.0 - 0.55, 24000.0, 0.4122831786355476, -1920.5404488000006, -361.15846159999984, 1377.850383 - 0.55, 24000.0, 0.4809970417414722, -975.1257144000039, -8.445279199999785, 1607.4921135 - 0.55, 24000.0, 0.5497109048473967, -29.711075200012726, 344.26792480000046, 1837.133844 - 0.55, 24000.0, 0.6184247679533214, 915.7034959999933, 696.9812136000028, 2066.7755745 - 0.55, 24000.0, 0.687138631059246, 1924.1688184000097, 1073.163849600008, 2296.417305 - 0.55, 24000.0, 0.7558524941651705, 3310.932916799993, 1598.1045296000134, 2526.0590355 - 0.55, 24000.0, 0.8245663572710952, 5137.79604720003, 2325.293103200006, 2755.700766 - 0.55, 24000.0, 0.8932802203770197, 7198.693903999972, 3217.927966400006, 2985.3424965 - 0.55, 24000.0, 0.9619940834829444, 9318.197458400025, 4280.6321256000265, 3214.984227 - 0.55, 27000.0, 0.0, 279.1299440930007, 279.1299440930007, 0.0 - 0.55, 27000.0, 0.40209895152603237, -2005.200051199999, -419.2564639999998, 1343.8146960000001 - 0.55, 27000.0, 0.46911544344703776, -1120.043641600003, -92.83574320000031, 1567.7838120000001 - 0.55, 27000.0, 0.5361319353680432, -234.88714400000705, 233.58507199999892, 1791.752928 - 0.55, 27000.0, 0.6031484272890485, 650.269348799991, 560.0058871999997, 2015.722044 - 0.55, 27000.0, 0.6701649192100539, 1536.7576103999888, 886.8647680000053, 2239.6911600000003 - 0.55, 27000.0, 0.7371814111310593, 2730.5518623999983, 1332.8095671999984, 2463.660276 - 0.55, 27000.0, 0.8041979030520647, 4295.929247200005, 1942.9273560000163, 2687.6293920000003 - 0.55, 27000.0, 0.8712143949730701, 6094.253980000046, 2698.9033648000195, 2911.598508 - 0.55, 27000.0, 0.9382308868940755, 7933.540184800076, 3597.1834656000115, 3135.5676240000003 - 0.55, 30000.0, 0.0, 247.06889957859602, 247.06889957859602, 0.0 - 0.55, 30000.0, 0.39191377244165176, -2118.3728, -480.674, 1309.7758275 - 0.55, 30000.0, 0.4572327345152603, -1282.0769999999998, -176.1843000000001, 1528.07179875 - 0.55, 30000.0, 0.5225516965888689, -445.78159999999923, 128.30539999999974, 1746.36777 - 0.55, 30000.0, 0.5878706586624776, 390.5138999999999, 432.7950000000001, 1964.6637412500002 - 0.55, 30000.0, 0.6531896207360862, 1226.8095999999996, 737.2847999999999, 2182.9597125 - 0.55, 30000.0, 0.7185085828096949, 2222.487999999998, 1103.398600000001, 2401.25568375 - 0.55, 30000.0, 0.7838275448833035, 3563.936000000004, 1618.714799999998, 2619.551655 - 0.55, 30000.0, 0.8491465069569121, 5155.266599999999, 2270.3665000000005, 2837.8476262500003 - 0.55, 30000.0, 0.9144654690305206, 6746.392100000003, 3017.2527, 3056.1435975 - 0.55, 30000.0, 0.9797844311041293, 8117.882799999992, 3833.504899999997, 3274.43956875 - 0.55, 33000.0, 0.0, 217.98810821959532, 217.98810821959532, 0.0 - 0.55, 33000.0, 0.3817295453321365, -2025.390101600001, -521.5956776000002, 1275.7401405 - 0.55, 33000.0, 0.44535113622082584, -1287.7751632000045, -244.07160560000014, 1488.36349725 - 0.55, 33000.0, 0.5089727271095152, -550.1608216000086, 33.452258399999884, 1700.986854 - 0.55, 33000.0, 0.5725943179982047, 187.4534783999959, 310.9765031999984, 1913.61021075 - 0.55, 33000.0, 0.636215908886894, 925.0674871999988, 588.5001944000004, 2126.2335675 - 0.55, 33000.0, 0.6998374997755834, 1767.7497384000012, 902.9619488000017, 2338.85692425 - 0.55, 33000.0, 0.763459090664273, 2915.098937599995, 1335.4534088000032, 2551.480281 - 0.55, 33000.0, 0.8270806815529623, 4290.627315200017, 1883.2427600000058, 2764.10363775 - 0.55, 33000.0, 0.8907022724416517, 5717.436253600007, 2522.8588144000096, 2976.7269945 - 0.55, 33000.0, 0.9543238633303411, 6820.062578400031, 3167.6599808000124, 3189.35035125 - 0.55, 36000.0, 0.0, 191.68048348149455, 191.68048348149455, 0.0 - 0.55, 36000.0, 0.37154436624775583, -2176.4892999999997, -572.1918999999998, 1241.701272 - 0.55, 36000.0, 0.43346842728904844, -1492.5227000000007, -318.27229999999895, 1448.651484 - 0.55, 36000.0, 0.4953924883303411, -808.5572000000044, -64.35269999999731, 1655.601696 - 0.55, 36000.0, 0.5573165493716338, -124.59060000000258, 189.56699999999898, 1862.551908 - 0.55, 36000.0, 0.6192406104129264, 559.3753999999972, 443.48629999999815, 2069.50212 - 0.55, 36000.0, 0.681164671454219, 1287.9206999999963, 707.9944000000021, 2276.452332 - 0.55, 36000.0, 0.7430887324955117, 2201.7370999999966, 1047.8270999999902, 2483.402544 - 0.55, 36000.0, 0.8050127935368042, 3296.7427000000207, 1498.9411000000052, 2690.3527559999998 - 0.55, 36000.0, 0.8669368545780969, 4770.690599999995, 2073.6619000000005, 2897.302968 - 0.55, 36000.0, 0.9288609156193895, 5655.613499999973, 2640.556299999988, 3104.2531799999997 - 0.55, 36000.0, 0.9907849766606822, 5650.371999999944, 2701.633999999972, 3311.203392 - 0.55, 39000.0, 0.0, 166.0097840490962, 166.0097840490962, 0.0 - 0.55, 39000.0, 0.37124163824057455, -1882.5707, -495.7016000000004, 1240.6895550000002 - 0.55, 39000.0, 0.43311524461400364, -1336.2672999999963, -287.8714999999998, 1447.4711475000001 - 0.55, 39000.0, 0.4949888509874327, -789.9643999999896, -80.04109999999962, 1654.2527400000001 - 0.55, 39000.0, 0.5568624573608618, -243.66060000000058, 127.78950000000023, 1861.0343325000001 - 0.55, 39000.0, 0.6187360637342909, 302.64220000000506, 335.62000000000006, 2067.8159250000003 - 0.55, 39000.0, 0.68060967010772, 884.1289999999966, 552.3294999999989, 2274.5975175000003 - 0.55, 39000.0, 0.7424832764811491, 1713.054399999989, 852.9032000000002, 2481.3791100000003 - 0.55, 39000.0, 0.8043568828545782, 2706.998199999994, 1244.2737000000025, 2688.1607025000003 - 0.55, 39000.0, 0.8662304892280073, 3806.2708000000052, 1680.163200000005, 2894.9422950000003 - 0.55, 39000.0, 0.9281040956014364, 4711.514799999981, 2213.673000000006, 3101.7238875000003 - 0.55, 39000.0, 0.9899777019748655, 5502.907099999938, 2746.281500000002, 3308.5054800000003 - 0.55, 42000.0, 0.0, 143.71847921078623, 143.71847921078623, 0.0 - 0.55, 42000.0, 0.37124163824057455, -13978.108862500023, -5206.461175000006, 1240.6895550000002 - 0.55, 42000.0, 0.43311524461400364, -10893.789337500013, -4009.0481250000066, 1447.4711475000001 - 0.55, 42000.0, 0.4949888509874327, -7809.469987499985, -2811.6347687500033, 1654.2527400000001 - 0.55, 42000.0, 0.5568624573608618, -4725.153862499943, -1614.219968750006, 1861.0343325000001 - 0.55, 42000.0, 0.6187360637342909, -1640.8352999999956, -416.80901875000654, 2067.8159250000003 - 0.55, 42000.0, 0.68060967010772, 298.81433124999626, 327.9244249999797, 2274.5975175000003 - 0.55, 42000.0, 0.7424832764811491, 1402.1262124999685, 703.2273187500086, 2481.3791100000003 - 0.55, 42000.0, 0.8043568828545782, 1950.4898062500074, 996.7462500000124, 2688.1607025000003 - 0.55, 42000.0, 0.8662304892280073, 3358.4223624999986, 1598.0351374999987, 2894.9422950000003 - 0.55, 42000.0, 0.9281040956014364, 3801.7769749999406, 1835.5212249999995, 3101.7238875000003 - 0.55, 42000.0, 0.9899777019748655, 5521.01749374992, 2900.1035500000585, 3308.5054800000003 - 0.6000000000000001, 0.0, 0.0, 765.6069809658406, 765.6069809658406, 0.0 - 0.6000000000000001, 0.0, 0.49911511669658887, -6025.047700000032, -79.02730000000076, 1668.04272 - 0.6000000000000001, 0.0, 0.5823009694793536, -2465.722999999966, 785.1888999998976, 1946.04984 - 0.6000000000000001, 0.0, 0.6654868222621184, 1093.608100000325, 1649.4085999997192, 2224.05696 - 0.6000000000000001, 0.0, 0.7486726750448833, 4224.980799999542, 2695.0914000003568, 2502.06408 - 0.6000000000000001, 0.0, 0.831858527827648, 5101.5099000025075, 3943.206699999594, 2780.0712 - 0.6000000000000001, 0.0, 0.9150443806104128, 5674.10320000233, 5576.643700000501, 3058.0783199999996 - 0.6000000000000001, 0.0, 0.9982302333931777, 13470.32140000134, 8143.669700001068, 3336.08544 - 0.6000000000000001, 3000.0, 0.0, 693.3578249967735, 693.3578249967735, 0.0 - 0.6000000000000001, 3000.0, 0.48882045242369837, -1032.887727155233, 110.90694140501671, 1633.637952 - 0.6000000000000001, 3000.0, 0.5702905278276481, 229.05903954145114, 793.0775654701936, 1905.910944 - 0.6000000000000001, 3000.0, 0.6517606032315978, 1491.02164651687, 1475.2571131964648, 2178.183936 - 0.6000000000000001, 3000.0, 0.7332306786355476, 3270.8377907181393, 2286.7653867022946, 2450.456928 - 0.6000000000000001, 3000.0, 0.8147007540394973, 7000.776244105932, 3555.9040300367856, 2722.7299199999998 - 0.6000000000000001, 3000.0, 0.8961708294434471, 9948.700792716194, 5147.92761143892, 2995.002912 - 0.6000000000000001, 3000.0, 0.9776409048473967, 11990.533633133324, 7075.252573780068, 3267.275904 - 0.6000000000000001, 6000.0, 0.0, 626.6030385637355, 626.6030385637355, 0.0 - 0.6000000000000001, 6000.0, 0.4785248258527828, -4189.776900000001, -36.40880000000005, 1599.229968 - 0.6000000000000001, 6000.0, 0.5582789634949132, -1838.0290000000075, 612.0603000000128, 1865.7682960000002 - 0.6000000000000001, 6000.0, 0.6380331011370438, 513.729399999868, 1260.529500000035, 2132.3066240000003 - 0.6000000000000001, 6000.0, 0.7177872387791743, 2868.472200000034, 1990.4932000000745, 2398.8449520000004 - 0.6000000000000001, 6000.0, 0.7975413764213047, 6031.481100000747, 3062.5463999996746, 2665.3832800000005 - 0.6000000000000001, 6000.0, 0.8772955140634352, 8447.503499998587, 4371.179400000585, 2931.9216080000006 - 0.6000000000000001, 6000.0, 0.9570496517055656, 13176.49309999862, 6561.287200000834, 3198.459936 - 0.6000000000000001, 9000.0, 0.0, 565.0310160917361, 565.0310160917361, 0.0 - 0.6000000000000001, 9000.0, 0.46823016157989233, -1831.7804642857227, -110.90937142857213, 1564.8252000000002 - 0.6000000000000001, 9000.0, 0.5462685218432077, -380.2262071428327, 485.406964285719, 1825.6294000000003 - 0.6000000000000001, 9000.0, 0.6243068821065231, 1071.3272571429072, 1081.7232428571447, 2086.4336000000003 - 0.6000000000000001, 9000.0, 0.7023452423698385, 2620.857042857131, 1730.1024357142883, 2347.2378000000003 - 0.6000000000000001, 9000.0, 0.7803836026331539, 4715.763664285782, 2620.907792857088, 2608.0420000000004 - 0.6000000000000001, 9000.0, 0.8584219628964693, 7694.563978571501, 3884.35002142866, 2868.8462000000004 - 0.6000000000000001, 9000.0, 0.9364603231597847, 11541.275478571273, 5637.71816428556, 3129.6504000000004 - 0.6000000000000001, 12000.0, 0.0, 508.33599738099446, 508.33599738099446, 0.0 - 0.6000000000000001, 12000.0, 0.4579345350089767, -2192.806423257575, -209.95658585858573, 1530.417216 - 0.6000000000000001, 12000.0, 0.5342569575104728, -752.0044664393831, 343.5381979292898, 1785.486752 - 0.6000000000000001, 12000.0, 0.6105793800119689, 688.7974737626541, 897.0328834848356, 2040.556288 - 0.6000000000000001, 12000.0, 0.686901802513465, 2170.0898012121265, 1473.026894368681, 2295.625824 - 0.6000000000000001, 12000.0, 0.7632242250149611, 4070.513064924184, 2246.4019278282426, 2550.69536 - 0.6000000000000001, 12000.0, 0.8395466475164572, 6569.497112777638, 3309.109334772652, 2805.764896 - 0.6000000000000001, 12000.0, 0.9158690700179534, 9949.594150959572, 4819.664426919146, 3060.834432 - 0.6000000000000001, 12000.0, 0.9921914925194495, 13584.53113179258, 6570.464643434266, 3315.903968 - 0.6000000000000001, 15000.0, 0.0, 456.23187174865643, 456.23187174865643, 0.0 - 0.6000000000000001, 15000.0, 0.4476398707360862, -2117.7908, -273.67820000000006, 1496.012448 - 0.6000000000000001, 15000.0, 0.5222465158587672, -822.6001000000006, 231.11120000000003, 1745.347856 - 0.6000000000000001, 15000.0, 0.5968531609814482, 472.5903999999954, 735.9005999999983, 1994.683264 - 0.6000000000000001, 15000.0, 0.6714598061041294, 1767.780999999998, 1240.6901000000028, 2244.018672 - 0.6000000000000001, 15000.0, 0.7460664512268104, 3415.828399999991, 1902.1244999999974, 2493.35408 - 0.6000000000000001, 15000.0, 0.8206730963494914, 5627.755399999985, 2827.2825000000053, 2742.689488 - 0.6000000000000001, 15000.0, 0.8952797414721724, 8524.86909999998, 4096.89109999999, 2992.024896 - 0.6000000000000001, 15000.0, 0.9698863865948534, 11754.323199999999, 5646.494599999994, 3241.360304 - 0.6000000000000001, 18000.0, 0.0, 408.4404341094299, 408.4404341094299, 0.0 - 0.6000000000000001, 18000.0, 0.43734424416517054, -2177.5759967999975, -339.75120799999996, 1461.604464 - 0.6000000000000001, 18000.0, 0.5102349515260324, -974.9718839999963, 123.70919039999988, 1705.205208 - 0.6000000000000001, 18000.0, 0.5831256588868942, 227.6324120000049, 587.1696104000007, 1948.8059520000002 - 0.6000000000000001, 18000.0, 0.6560163662477558, 1430.2367760000086, 1050.6300303999874, 2192.406696 - 0.6000000000000001, 18000.0, 0.7289070736086177, 2848.3074672000175, 1611.5032296000218, 2436.0074400000003 - 0.6000000000000001, 18000.0, 0.8017977809694794, 4781.003586400024, 2399.85449279998, 2679.608184 - 0.6000000000000001, 18000.0, 0.8746884883303411, 7288.045300000037, 3480.612922400052, 2923.208928 - 0.6000000000000001, 18000.0, 0.947579195691203, 10104.970703200119, 4808.753145599993, 3166.8096720000003 - 0.6000000000000001, 21000.0, 0.0, 364.6918921125046, 364.6918921125046, 0.0 - 0.6000000000000001, 21000.0, 0.4270495798922801, -2118.026526399999, -375.90203359999987, 1427.1996960000001 - 0.6000000000000001, 21000.0, 0.4982245098743268, -1031.5124464000105, 43.441929599999085, 1665.0663120000002 - 0.6000000000000001, 21000.0, 0.5693994398563735, 55.00156879997306, 462.78577999999777, 1902.9329280000002 - 0.6000000000000001, 21000.0, 0.6405743698384202, 1141.5156999999906, 882.129635200003, 2140.7995440000004 - 0.6000000000000001, 21000.0, 0.7117492998204669, 2346.906501600018, 1355.1385416000142, 2378.66616 - 0.6000000000000001, 21000.0, 0.7829242298025134, 4019.284399999974, 2022.0448288000173, 2616.532776 - 0.6000000000000001, 21000.0, 0.8540991597845602, 6202.803570400104, 2945.7587832000013, 2854.3993920000003 - 0.6000000000000001, 21000.0, 0.925274089766607, 8634.536793600086, 4064.8407240000224, 3092.2660080000005 - 0.6000000000000001, 21000.0, 0.9964490197486536, 11324.821619200115, 5443.804922399995, 3330.1326240000003 - 0.6000000000000001, 24000.0, 0.0, 324.73073881276036, 324.73073881276036, 0.0 - 0.6000000000000001, 24000.0, 0.4167539533213645, -1994.7486216000007, -371.5027344, 1392.7917120000002 - 0.6000000000000001, 24000.0, 0.4862129455415919, -1033.2819392000015, -2.6093448000001023, 1624.9236640000001 - 0.6000000000000001, 24000.0, 0.5556719377618193, -71.81535999999934, 366.28413119999993, 1857.055616 - 0.6000000000000001, 24000.0, 0.6251309299820468, 889.6513319999993, 735.1775775999968, 2089.1875680000003 - 0.6000000000000001, 24000.0, 0.6945899222022741, 1932.7154008000007, 1137.0621960000046, 2321.31952 - 0.6000000000000001, 24000.0, 0.7640489144225016, 3352.6347416000162, 1693.830697600002, 2553.451472 - 0.6000000000000001, 24000.0, 0.833507906642729, 5214.156200000017, 2466.3221327999972, 2785.5834240000004 - 0.6000000000000001, 24000.0, 0.9029668988629563, 7321.43309679997, 3415.3068103999935, 3017.715376 - 0.6000000000000001, 24000.0, 0.9724258910831838, 9475.582279999917, 4543.178333599979, 3249.8473280000003 - 0.6000000000000001, 27000.0, 0.0, 288.3093759754148, 288.3093759754148, 0.0 - 0.6000000000000001, 27000.0, 0.406459289048474, -1906.4619864000001, -382.46877199999983, 1358.386944 - 0.6000000000000001, 27000.0, 0.4742025038898863, -1048.8183544, -53.522560000000404, 1584.784768 - 0.6000000000000001, 27000.0, 0.5419457187312987, -191.17470559999865, 275.42362559999987, 1811.182592 - 0.6000000000000001, 27000.0, 0.609688933572711, 666.4689432000011, 604.3698080000012, 2037.5804160000002 - 0.6000000000000001, 27000.0, 0.6774321484141234, 1540.7525855999975, 939.6804871999987, 2263.9782400000004 - 0.6000000000000001, 27000.0, 0.7451753632555356, 2765.4334776000023, 1411.9077695999974, 2490.376064 - 0.6000000000000001, 27000.0, 0.812918578096948, 4360.493993599985, 2059.8433800000043, 2716.773888 - 0.6000000000000001, 27000.0, 0.8806617929383603, 6182.694176000022, 2862.712054399992, 2943.1717120000003 - 0.6000000000000001, 27000.0, 0.9484050077797725, 8049.501908799987, 3813.161476799994, 3169.569536 - 0.6000000000000001, 30000.0, 0.0, 255.19397602395614, 255.19397602395614, 0.0 - 0.6000000000000001, 30000.0, 0.3961636624775583, -2060.813199999999, -458.1994000000001, 1323.97896 - 0.6000000000000001, 30000.0, 0.4621909395571514, -1240.2023999999974, -148.82840000000058, 1544.64212 - 0.6000000000000001, 30000.0, 0.5282182166367445, -419.59119999999155, 160.54249999999828, 1765.30528 - 0.6000000000000001, 30000.0, 0.5942454937163375, 401.01980000000225, 469.9133999999995, 1985.96844 - 0.6000000000000001, 30000.0, 0.6602727707959306, 1221.630899999998, 779.2843000000023, 2206.6316 - 0.6000000000000001, 30000.0, 0.7263000478755237, 2266.588600000004, 1174.8208000000072, 2427.29476 - 0.6000000000000001, 30000.0, 0.7923273249551166, 3629.043900000017, 1720.0795000000076, 2647.95792 - 0.6000000000000001, 30000.0, 0.8583546020347097, 5241.692399999984, 2407.327100000001, 2868.62108 - 0.6000000000000001, 30000.0, 0.9243818791143028, 6845.82080000002, 3195.163300000004, 3089.28424 - 0.6000000000000001, 30000.0, 0.9904091561938959, 8183.629399999993, 4024.9125999999733, 3309.9474 - 0.6000000000000001, 33000.0, 0.0, 225.15683745457622, 225.15683745457622, 0.0 - 0.6000000000000001, 33000.0, 0.38586899820466797, -2207.9173736000002, -528.7189295999999, 1289.5741920000003 - 0.6000000000000001, 33000.0, 0.4501804979054459, -1426.2331471999996, -239.1670575999997, 1504.5032240000003 - 0.6000000000000001, 33000.0, 0.5144919976062239, -644.5488335999992, 50.38476640000041, 1719.4322560000003 - 0.6000000000000001, 33000.0, 0.5788034973070019, 137.13548640000013, 339.93660720000025, 1934.3612880000003 - 0.6000000000000001, 33000.0, 0.64311499700778, 918.8197711999989, 629.4884624000003, 2149.2903200000005 - 0.6000000000000001, 33000.0, 0.707426496708558, 1804.4131263999977, 959.9360247999986, 2364.2193520000005 - 0.6000000000000001, 33000.0, 0.7717379964093359, 2945.698789600005, 1407.7670247999984, 2579.1483840000005 - 0.6000000000000001, 33000.0, 0.8360494961101139, 4351.858299199991, 1992.4095199999974, 2794.0774160000005 - 0.6000000000000001, 33000.0, 0.9003609958108918, 5802.171045599996, 2673.6093023999947, 3009.0064480000005 - 0.6000000000000001, 33000.0, 0.9646724955116698, 6968.663866399994, 3383.479296799996, 3223.9354800000006 - 0.6000000000000001, 36000.0, 0.0, 197.98406351130433, 197.98406351130433, 0.0 - 0.6000000000000001, 36000.0, 0.37557337163375226, -2307.2292, -575.3364, 1255.166208 - 0.6000000000000001, 36000.0, 0.43816893357271103, -1590.2949, -312.09479999999996, 1464.3605760000003 - 0.6000000000000001, 36000.0, 0.5007644955116697, -873.3605000000006, -48.85319999999993, 1673.5549440000002 - 0.6000000000000001, 36000.0, 0.5633600574506284, -156.4261000000016, 214.3884000000002, 1882.7493120000001 - 0.6000000000000001, 36000.0, 0.6259556193895872, 560.5083, 477.6300999999998, 2091.9436800000003 - 0.6000000000000001, 36000.0, 0.6885511813285459, 1321.8441000000003, 758.2826000000002, 2301.1380480000003 - 0.6000000000000001, 36000.0, 0.7511467432675045, 2276.085399999999, 1124.9122, 2510.332416 - 0.6000000000000001, 36000.0, 0.8137423052064633, 3475.9856000000013, 1613.9647000000016, 2719.526784 - 0.6000000000000001, 36000.0, 0.8763378671454221, 4685.783700000002, 2172.9069999999974, 2928.7211520000005 - 0.6000000000000001, 36000.0, 0.9389334290843807, 5667.942900000003, 2754.7935000000016, 3137.9155200000005 - 0.6000000000000001, 39000.0, 0.0, 171.46916071842696, 171.46916071842696, 0.0 - 0.6000000000000001, 39000.0, 0.37526736086175944, -2002.4923000000001, -520.5444, 1254.14352 - 0.6000000000000001, 39000.0, 0.4378119210053861, -1421.915200000001, -299.1927999999999, 1463.1674400000002 - 0.6000000000000001, 39000.0, 0.5003564811490127, -841.3380000000025, -77.84109999999998, 1672.1913600000003 - 0.6000000000000001, 39000.0, 0.5629010412926393, -260.7607000000015, 143.51049999999998, 1881.2152800000003 - 0.6000000000000001, 39000.0, 0.6254456014362658, 319.8165000000001, 364.86220000000003, 2090.2392000000004 - 0.6000000000000001, 39000.0, 0.6879901615798925, 946.5119999999996, 602.7563999999996, 2299.2631200000005 - 0.6000000000000001, 39000.0, 0.7505347217235189, 1775.498400000001, 918.4677000000001, 2508.28704 - 0.6000000000000001, 39000.0, 0.8130792818671455, 2814.586899999998, 1339.0612, 2717.3109600000003 - 0.6000000000000001, 39000.0, 0.8756238420107721, 3862.892300000001, 1816.284200000001, 2926.3348800000003 - 0.6000000000000001, 39000.0, 0.9381684021543987, 4767.528299999998, 2336.4414, 3135.3588000000004 - 0.6000000000000001, 42000.0, 0.0, 148.4447868609608, 148.4447868609608, 0.0 - 0.6000000000000001, 42000.0, 0.37526736086175944, -7912.092837500004, -2875.0652250000007, 1254.14352 - 0.6000000000000001, 42000.0, 0.4378119210053861, -6127.016637499996, -2174.4438750000013, 1463.1674400000002 - 0.6000000000000001, 42000.0, 0.5003564811490127, -4341.940187499981, -1473.8225562499993, 1672.1913600000003 - 0.6000000000000001, 42000.0, 0.5629010412926393, -2556.865137499981, -773.2005812500008, 1881.2152800000003 - 0.6000000000000001, 42000.0, 0.6254456014362658, -771.7891250000013, -72.58010625000193, 2090.2392000000004 - 0.6000000000000001, 42000.0, 0.6879901615798925, 508.2581187499988, 426.18429999999046, 2299.2631200000005 - 0.6000000000000001, 42000.0, 0.7505347217235189, 1367.7963624999861, 743.8318312500035, 2508.28704 - 0.6000000000000001, 42000.0, 0.8130792818671455, 2147.8645187500006, 1082.3422000000003, 2717.3109600000003 - 0.6000000000000001, 42000.0, 0.8756238420107721, 3218.840587499993, 1564.915462499999, 2926.3348800000003 - 0.6000000000000001, 42000.0, 0.9381684021543987, 3964.538424999968, 1977.8877499999903, 3135.3588000000004 - 0.65, 0.0, 0.0, 792.7024450524767, 792.7024450524767, 0.0 - 0.65, 0.0, 0.5049350224416517, -8986.311000000043, -205.03300000000138, 1687.492845 - 0.65, 0.0, 0.5890908595152603, -4193.077799999944, 754.1148999998619, 1968.7416524999999 - 0.65, 0.0, 0.6732466965888689, 600.1659000004893, 1713.2683999996198, 2249.99046 - 0.65, 0.0, 0.7574025336624776, 4169.050899999325, 2856.64210000044, 2531.2392675 - 0.65, 0.0, 0.8415583707360862, 3476.700500003306, 4086.801899999419, 2812.488075 - 0.65, 0.0, 0.9257142078096947, 2286.0993000032213, 5657.078800000607, 3093.7368825 - 0.65, 3000.0, 0.0, 717.8963317155706, 717.8963317155706, 0.0 - 0.65, 3000.0, 0.49452031777378813, -425.46643744164294, 180.53526898241603, 1652.686902 - 0.65, 3000.0, 0.5769403707360862, 468.8010719162818, 869.373960592012, 1928.134719 - 0.65, 3000.0, 0.6593604236983842, 1363.0971914531324, 1558.2287554517266, 2203.582536 - 0.65, 3000.0, 0.7417804766606823, 3011.832178775709, 2400.3819444242067, 2479.030353 - 0.65, 3000.0, 0.8242005296229802, 7474.005587990672, 3772.592356724915, 2754.47817 - 0.65, 3000.0, 0.9066205825852781, 9944.852812389632, 5428.432934148905, 3029.9259869999996 - 0.65, 3000.0, 0.9890406355475763, 9336.35680848069, 7113.890729373179, 3305.373804 - 0.65, 6000.0, 0.0, 648.7790381955078, 648.7790381955078, 0.0 - 0.65, 6000.0, 0.4841046395870736, -6060.3228999999965, -9.804000000000144, 1617.8777055 - 0.65, 6000.0, 0.5647887461849193, -3115.973700000006, 656.869300000016, 1887.52398975 - 0.65, 6000.0, 0.6454728527827648, -171.6051000001944, 1323.5427000000427, 2157.170274 - 0.65, 6000.0, 0.7261569593806104, 2660.584000000071, 2087.388700000104, 2426.81655825 - 0.65, 6000.0, 0.8068410659784561, 6493.076300001056, 3261.3311999994967, 2696.4628425 - 0.65, 6000.0, 0.8875251725763016, 7988.586999997913, 4485.14260000088, 2966.10912675 - 0.65, 6000.0, 0.9682092791741472, 13065.786999997952, 6949.1082000011465, 3235.755411 - 0.65, 9000.0, 0.0, 585.0279309383524, 585.0279309383524, 0.0 - 0.65, 9000.0, 0.47368993491921, -1700.5032107142983, -62.71742857142971, 1583.0717625 - 0.65, 9000.0, 0.552638257405745, -307.4999678571064, 544.903760714292, 1846.9170562499999 - 0.65, 9000.0, 0.6315865798922801, 1085.5022428572167, 1152.5248071428578, 2110.76235 - 0.65, 9000.0, 0.7105349023788151, 2605.4910071428308, 1830.804439285713, 2374.60764375 - 0.65, 9000.0, 0.7894832248653502, 4721.692860714421, 2773.7117821427755, 2638.4529375 - 0.65, 9000.0, 0.8684315473518851, 7806.446846428692, 4126.704453571549, 2902.29823125 - 0.65, 9000.0, 0.94737986983842, 11671.6950464283, 5977.995810714067, 3166.143525 - 0.65, 12000.0, 0.0, 526.3264286380411, 526.3264286380411, 0.0 - 0.65, 12000.0, 0.46327425673249556, -2317.3446076893906, -180.2026797979794, 1548.262566 - 0.65, 12000.0, 0.5404866328545782, -839.7218247348305, 389.27596239898526, 1806.3063270000002 - 0.65, 12000.0, 0.6176990089766607, 637.9008869823653, 958.7545196211898, 2064.350088 - 0.65, 12000.0, 0.6949113850987433, 2175.165540303032, 1566.5214721338264, 2322.393849 - 0.65, 12000.0, 0.7721237612208258, 4118.99016185597, 2385.5284565403285, 2580.43761 - 0.65, 12000.0, 0.8493361373429086, 6640.0689186108675, 3503.6583655680424, 2838.4813710000003 - 0.65, 12000.0, 0.9265485134649911, 10127.735213156528, 5124.887838813041, 3096.525132 - 0.65, 15000.0, 0.0, 472.37829491808674, 472.37829491808674, 0.0 - 0.65, 15000.0, 0.45285955206463196, -2025.0591000000013, -233.98270000000022, 1513.456623 - 0.65, 15000.0, 0.528336144075404, -767.4877000000035, 281.021899999999, 1765.6993935 - 0.65, 15000.0, 0.6038127360861759, 490.08349999998507, 796.0265999999918, 2017.942164 - 0.65, 15000.0, 0.679289328096948, 1767.7185999999904, 1320.2819000000059, 2270.1849345 - 0.65, 15000.0, 0.7547659201077199, 3444.22899999998, 2021.0459999999955, 2522.427705 - 0.65, 15000.0, 0.830242512118492, 5711.7250999999715, 2999.7244000000214, 2774.6704755 - 0.65, 15000.0, 0.9057191041292639, 8684.402299999936, 4357.783199999955, 3026.913246 - 0.65, 15000.0, 0.9811956961400359, 11932.069300000001, 5975.329599999968, 3279.1560165 - 0.65, 18000.0, 0.0, 422.89547878519926, 422.89547878519926, 0.0 - 0.65, 18000.0, 0.4424438738779174, -2094.231596000001, -304.1237879999997, 1478.6474265 - 0.65, 18000.0, 0.5161845195242369, -920.8062992000014, 168.95020639999888, 1725.08866425 - 0.65, 18000.0, 0.5899251651705566, 252.61912400000503, 642.0242023999981, 1971.529902 - 0.65, 18000.0, 0.6636658108168761, 1425.9856712000028, 1115.0722592000102, 2217.97113975 - 0.65, 18000.0, 0.7374064564631957, 2877.673352, 1712.4198959999967, 2464.4123775 - 0.65, 18000.0, 0.8111471021095152, 4856.519299199997, 2548.907502400006, 2710.85361525 - 0.65, 18000.0, 0.8848877477558348, 7428.133271200024, 3703.352770400024, 2957.294853 - 0.65, 18000.0, 0.9586283934021544, 10309.897340000027, 5113.859144800022, 3203.73609075 - 0.65, 21000.0, 0.0, 377.5986397141995, 377.5986397141995, 0.0 - 0.65, 21000.0, 0.4320291692100539, -2065.2949208, -357.48915600000015, 1443.8414835 - 0.65, 21000.0, 0.5040340307450629, -999.6529008000002, 73.78299760000081, 1684.4817307500002 - 0.65, 21000.0, 0.5760388922800719, 65.98912399999438, 505.05521920000234, 1925.1219780000001 - 0.65, 21000.0, 0.6480437538150808, 1131.6310856000116, 936.3273495999962, 2165.76222525 - 0.65, 21000.0, 0.7200486153500898, 2362.0323344000203, 1437.808717600006, 2406.4024725 - 0.65, 21000.0, 0.7920534768850989, 4097.359209600052, 2154.9833528, 2647.0427197500003 - 0.65, 21000.0, 0.8640583384201078, 6311.4237696000455, 3128.3837111999783, 2887.682967 - 0.65, 21000.0, 0.9360631999551168, 8825.819702399976, 4334.821096799998, 3128.32321425 - 0.65, 24000.0, 0.0, 336.22322815791756, 336.22322815791756, 0.0 - 0.65, 24000.0, 0.42161349102333934, -2059.0245456000007, -394.48459120000007, 1409.032287 - 0.65, 24000.0, 0.4918824061938959, -1079.369190400006, -3.9418064000003485, 1643.8710015000001 - 0.65, 24000.0, 0.5621513213644524, -99.71391040001508, 386.6009735999998, 1878.709716 - 0.65, 24000.0, 0.632420236535009, 879.9414511999969, 777.1436888000015, 2113.5484305 - 0.65, 24000.0, 0.7026891517055656, 1947.2460103999983, 1206.7936095999987, 2348.387145 - 0.65, 24000.0, 0.7729580668761221, 3399.061526400003, 1798.5545215999973, 2583.2258595000003 - 0.65, 24000.0, 0.8432269820466787, 5318.818936000035, 2624.811353600009, 2818.064574 - 0.65, 24000.0, 0.9134958972172352, 7475.729080000036, 3634.958116800016, 3052.9032885 - 0.65, 24000.0, 0.9837648123877918, 9731.872028000087, 4859.2952552000115, 3287.7420030000003 - 0.65, 27000.0, 0.0, 298.5128831753196, 298.5128831753196, 0.0 - 0.65, 27000.0, 0.4111987863554758, -1946.7021096000008, -392.9390351999998, 1374.2263440000002 - 0.65, 27000.0, 0.47973191741472176, -1077.6632888000022, -48.089382400000055, 1603.2640680000002 - 0.65, 27000.0, 0.5482650484739677, -208.6243848000024, 296.76018399999987, 1832.3017920000002 - 0.65, 27000.0, 0.6167981795332137, 660.4145191999962, 641.6097719999997, 2061.339516 - 0.65, 27000.0, 0.6853313105924597, 1572.2684152000002, 1004.1083232000009, 2290.3772400000003 - 0.65, 27000.0, 0.7538644416517057, 2814.3681048000094, 1502.5744048000015, 2519.4149640000005 - 0.65, 27000.0, 0.8223975727109516, 4457.272203199989, 2196.2597152000176, 2748.4526880000003 - 0.65, 27000.0, 0.8909307037701976, 6322.386402400014, 3048.4214056000087, 2977.490412 - 0.65, 27000.0, 0.9594638348294435, 8214.63322560003, 4057.2307831999897, 3206.5281360000004 - 0.65, 30000.0, 0.0, 264.22550183862404, 264.22550183862404, 0.0 - 0.65, 30000.0, 0.4007831081687612, -1969.638299999999, -427.10410000000013, 1339.4171475 - 0.65, 30000.0, 0.4675802928635548, -1168.301499999994, -113.45000000000057, 1562.65333875 - 0.65, 30000.0, 0.5343774775583483, -366.964799999979, 200.2041999999978, 1785.8895300000001 - 0.65, 30000.0, 0.6011746622531419, 434.3720000000084, 513.8582999999969, 2009.1257212500002 - 0.65, 30000.0, 0.6679718469479353, 1235.7088999999933, 827.5125000000068, 2232.3619125 - 0.65, 30000.0, 0.7347690316427289, 2307.668700000013, 1251.410200000019, 2455.59810375 - 0.65, 30000.0, 0.8015662163375225, 3709.447500000026, 1830.667000000022, 2678.834295 - 0.65, 30000.0, 0.868363401032316, 5346.759799999919, 2555.403299999985, 2902.07048625 - 0.65, 30000.0, 0.9351605857271096, 6983.832000000056, 3403.71140000001, 3125.3066775 - 0.65, 33000.0, 0.0, 233.12532409953172, 233.12532409953172, 0.0 - 0.65, 33000.0, 0.3903684035008977, -2121.918405600001, -501.3691415999998, 1304.6112045 - 0.65, 33000.0, 0.45542980408438066, -1356.0515512000009, -207.5336695999996, 1522.0464052500001 - 0.65, 33000.0, 0.5204912046678636, -590.1845056000025, 86.30181440000011, 1739.481606 - 0.65, 33000.0, 0.5855526052513464, 175.68253440000333, 380.1373312000019, 1956.91680675 - 0.65, 33000.0, 0.6506140058348295, 941.5495751999918, 673.9727704000029, 2174.3520075 - 0.65, 33000.0, 0.7156754064183125, 1839.7903543999932, 1021.9640807999955, 2391.7872082500003 - 0.65, 33000.0, 0.7807368070017954, 3021.9266016000174, 1502.8665208000011, 2609.222409 - 0.65, 33000.0, 0.8457982075852783, 4453.759503199965, 2121.975379999983, 2826.65760975 - 0.65, 33000.0, 0.9108596081687613, 5883.971597600017, 2828.667030400002, 3044.0928105000003 - 0.65, 33000.0, 0.9759210087522442, 7093.745994400008, 3594.092792799984, 3261.52801125 - 0.65, 36000.0, 0.0, 204.9908832190209, 204.9908832190209, 0.0 - 0.65, 36000.0, 0.37995272531418317, -2204.349100000001, -551.7944, 1269.8020080000001 - 0.65, 36000.0, 0.44327817953321363, -1503.3511000000067, -283.8780000000012, 1481.435676 - 0.65, 36000.0, 0.5066036337522442, -802.3530000000152, -15.961600000003456, 1693.069344 - 0.65, 36000.0, 0.5699290879712746, -101.35500000000665, 251.95479999999918, 1904.703012 - 0.65, 36000.0, 0.6332545421903052, 599.6431000000001, 519.8713000000002, 2116.33668 - 0.65, 36000.0, 0.6965799964093357, 1363.042, 813.6062000000007, 2327.970348 - 0.65, 36000.0, 0.7599054506283663, 2351.8755000000024, 1206.553000000001, 2539.6040160000002 - 0.65, 36000.0, 0.8232309048473968, 3571.964599999986, 1724.7234999999996, 2751.237684 - 0.65, 36000.0, 0.8865563590664273, 4769.537599999995, 2315.9233000000045, 2962.871352 - 0.65, 36000.0, 0.9498818132854578, 5753.311000000053, 2911.5493000000074, 3174.50502 - 0.65, 39000.0, 0.0, 177.53759609286755, 177.53759609286755, 0.0 - 0.65, 39000.0, 0.37964314631956914, -2079.6422999999986, -541.2985000000002, 1268.767395 - 0.65, 39000.0, 0.44291700403949735, -1475.5615000000034, -306.837800000002, 1480.2286275000001 - 0.65, 39000.0, 0.5061908617594255, -871.48080000001, -72.37710000000514, 1691.6898600000002 - 0.65, 39000.0, 0.5694647194793537, -267.40010000001234, 162.0834999999989, 1903.1510925000002 - 0.65, 39000.0, 0.6327385771992818, 336.68069999999454, 396.5441999999992, 2114.612325 - 0.65, 39000.0, 0.6960124349192102, 995.0391999999958, 653.1631000000007, 2326.0735575000003 - 0.65, 39000.0, 0.7592862926391383, 1838.353800000003, 987.8817000000003, 2537.53479 - 0.65, 39000.0, 0.8225601503590666, 2900.0544000000154, 1433.4257000000036, 2748.9960225000004 - 0.65, 39000.0, 0.8858340080789947, 3944.9355000000214, 1941.3198000000118, 2960.4572550000003 - 0.65, 39000.0, 0.9491078657989229, 4862.986300000031, 2483.766100000017, 3171.9184875000005 - 0.65, 42000.0, 0.0, 153.69837060723933, 153.69837060723933, 0.0 - 0.65, 42000.0, 0.37964314631956914, -4454.834912500002, -1543.5738750000007, 1268.767395 - 0.65, 42000.0, 0.44291700403949735, -3405.7924374999993, -1122.1138250000008, 1480.2286275000001 - 0.65, 42000.0, 0.5061908617594255, -2356.749687499993, -700.6538937500003, 1691.6898600000002 - 0.65, 42000.0, 0.5694647194793537, -1307.7073125000002, -279.1937437499995, 1903.1510925000002 - 0.65, 42000.0, 0.6327385771992818, -258.66475000000065, 142.26605624999942, 2114.612325 - 0.65, 42000.0, 0.6960124349192102, 630.2993562499995, 496.7317749999977, 2326.0735575000003 - 0.65, 42000.0, 0.7592862926391383, 1385.454412499997, 795.0604937500008, 2537.53479 - 0.65, 42000.0, 0.8225601503590666, 2283.647081249999, 1171.2965499999975, 2748.9960225000004 - 0.65, 42000.0, 0.8858340080789947, 3208.840912499997, 1610.9828875, 2960.4572550000003 - 0.65, 42000.0, 0.9491078657989229, 4068.1816749999925, 2103.5878749999924, 3171.9184875000005 - 0.7000000000000001, 0.0, 0.0, 822.675472003164, 822.675472003164, 0.0 - 0.7000000000000001, 0.0, 0.5112205206463195, -13019.30170000006, -390.5481000000018, 1708.4989799999998 - 0.7000000000000001, 0.0, 0.5964239407540395, -6521.000899999917, 693.5088999998198, 1993.2488099999998 - 0.7000000000000001, 0.0, 0.6816273608617593, -22.684099999303726, 1777.5742999995, 2277.99864 - 0.7000000000000001, 0.0, 0.7668307809694792, 4125.024699999041, 3038.2561000005308, 2562.7484699999995 - 0.7000000000000001, 0.0, 0.8520342010771992, 1281.1685000042562, 4223.057899999199, 2847.4982999999997 - 0.7000000000000001, 0.0, 0.9372376211849192, -2232.39519999567, 5678.893000000723, 3132.24813 - 0.7000000000000001, 3000.0, 0.0, 745.0408501065614, 745.0408501065614, 0.0 - 0.7000000000000001, 3000.0, 0.5006761723518852, 436.9773930719457, 263.6130287598152, 1673.2597680000003 - 0.7000000000000001, 3000.0, 0.5841222010771994, 824.2919286911242, 956.8958211138371, 1952.1363960000003 - 0.7000000000000001, 3000.0, 0.6675682298025135, 1211.6531449894173, 1650.2048633070076, 2231.0130240000003 - 0.7000000000000001, 3000.0, 0.7510142585278278, 2681.2498396332776, 2523.8675675461645, 2509.8896520000003 - 0.7000000000000001, 3000.0, 0.8344602872531419, 8163.985986275406, 4014.352547413081, 2788.7662800000003 - 0.7000000000000001, 3000.0, 0.9179063159784561, 9956.331450463373, 5737.1116862589215, 3067.6429080000003 - 0.7000000000000001, 6000.0, 0.0, 673.310149103823, 673.310149103823, 0.0 - 0.7000000000000001, 6000.0, 0.49013083842010774, -8741.089799999994, 13.498899999999836, 1638.017262 - 0.7000000000000001, 6000.0, 0.5718193114901258, -4938.687100000005, 700.6290000000191, 1911.0201390000002 - 0.7000000000000001, 6000.0, 0.6535077845601437, -1136.2522000002714, 1387.7592000000504, 2184.023016 - 0.7000000000000001, 6000.0, 0.7351962576301616, 2378.5183000001252, 2188.9470000001415, 2457.025893 - 0.7000000000000001, 6000.0, 0.8168847307001795, 7181.3604000014275, 3493.2711999992603, 2730.02877 - 0.7000000000000001, 6000.0, 0.8985732037701976, 7254.113099997037, 4549.241400001265, 3003.0316470000002 - 0.7000000000000001, 6000.0, 0.9802616768402155, 12777.58479999708, 7363.207900001526, 3276.034524 - 0.7000000000000001, 9000.0, 0.0, 607.1485362807002, 607.1485362807002, 0.0 - 0.7000000000000001, 9000.0, 0.4795864901256733, -1599.8790214285884, -12.77455714285859, 1602.7780500000001 - 0.7000000000000001, 9000.0, 0.5595175718132854, -259.4922357142348, 607.3764214285794, 1869.907725 - 0.7000000000000001, 9000.0, 0.6394486535008977, 1080.8934857143863, 1227.5272142857118, 2137.0374 - 0.7000000000000001, 9000.0, 0.71937973518851, 2583.088014285665, 1940.965478571419, 2404.1670750000003 - 0.7000000000000001, 9000.0, 0.7993108168761223, 4765.228021428801, 2946.8956642856006, 2671.2967500000004 - 0.7000000000000001, 9000.0, 0.8792418985637344, 7974.031892857328, 4402.920107143004, 2938.426425 - 0.7000000000000001, 9000.0, 0.9591729802513466, 11801.097092856715, 6348.0624214282825, 3205.5561000000002 - 0.7000000000000001, 12000.0, 0.0, 546.2274600135438, 546.2274600135438, 0.0 - 0.7000000000000001, 12000.0, 0.4690411561938958, -2415.9622841666596, -145.15512222222156, 1567.5355439999998 - 0.7000000000000001, 12000.0, 0.5472146822262118, -907.3567091666404, 440.61407611110434, 1828.791468 - 0.7000000000000001, 12000.0, 0.6253882082585278, 601.2487619445025, 1026.3832216666335, 2090.047392 - 0.7000000000000001, 12000.0, 0.7035617342908438, 2181.3708066666563, 1667.0794752777572, 2351.303316 - 0.7000000000000001, 12000.0, 0.7817352603231598, 4172.977625833213, 2537.499840555433, 2612.55924 - 0.7000000000000001, 12000.0, 0.8599087863554757, 6741.132032777397, 3726.981897499777, 2873.815164 - 0.7000000000000001, 12000.0, 0.9380823123877916, 10353.412192777745, 5465.789210555413, 3135.0710879999997 - 0.7000000000000001, 15000.0, 0.0, 490.2394828743851, 490.2394828743851, 0.0 - 0.7000000000000001, 15000.0, 0.45849680789946146, -1946.5950800000019, -191.27324000000033, 1532.2963320000001 - 0.7000000000000001, 15000.0, 0.5349129425493717, -723.9525200000068, 334.60414999999705, 1787.6790540000002 - 0.7000000000000001, 15000.0, 0.611329077199282, 498.68997999996895, 860.481739999981, 2043.0617760000002 - 0.7000000000000001, 15000.0, 0.6877452118491922, 1775.4181499999763, 1410.187560000008, 2298.4444980000003 - 0.7000000000000001, 15000.0, 0.7641613464991024, 3490.8625899999643, 2154.941179999995, 2553.82722 - 0.7000000000000001, 15000.0, 0.8405774811490127, 5818.840939999965, 3191.662840000045, 2809.2099420000004 - 0.7000000000000001, 15000.0, 0.9169936157989229, 8894.500169999897, 4655.315229999899, 3064.5926640000002 - 0.7000000000000001, 15000.0, 0.9934097504488332, 12116.06083000001, 6324.152319999926, 3319.9753860000005 - 0.7000000000000001, 18000.0, 0.0, 438.88566231757557, 438.88566231757557, 0.0 - 0.7000000000000001, 18000.0, 0.44795147396768403, -2026.1402031999996, -266.42978800000003, 1497.053826 - 0.7000000000000001, 18000.0, 0.522610052962298, -873.2838232000041, 217.8617768000008, 1746.562797 - 0.7000000000000001, 18000.0, 0.597268631956912, 279.57257679999043, 702.1532600000029, 1996.071768 - 0.7000000000000001, 18000.0, 0.6719272109515261, 1431.7158903999962, 1186.1548136000079, 2245.580739 - 0.7000000000000001, 18000.0, 0.7465857899461401, 2919.1741656000113, 1822.108252800007, 2495.08971 - 0.7000000000000001, 18000.0, 0.821244368940754, 4970.509167200026, 2721.648908799995, 2744.598681 - 0.7000000000000001, 18000.0, 0.8959029479353681, 7601.833837599994, 3947.158848000014, 2994.107652 - 0.7000000000000001, 18000.0, 0.970561526929982, 10552.041460799983, 5448.533919199945, 3243.616623 - 0.7000000000000001, 21000.0, 0.0, 391.8760956187884, 391.8760956187884, 0.0 - 0.7000000000000001, 21000.0, 0.4374071256732496, -2058.5499064000014, -335.0074879999997, 1461.8146140000001 - 0.7000000000000001, 21000.0, 0.5103083132854579, -994.0279152000105, 109.71660320000024, 1705.450383 - 0.7000000000000001, 21000.0, 0.5832095008976661, 70.49416239997012, 554.4407240000005, 1949.086152 - 0.7000000000000001, 21000.0, 0.6561106885098744, 1135.0161287999797, 999.1649048000115, 2192.7219210000003 - 0.7000000000000001, 21000.0, 0.7290118761220826, 2418.2501247999735, 1537.6253976000207, 2436.3576900000003 - 0.7000000000000001, 21000.0, 0.8019130637342909, 4185.78582800004, 2297.9855528000157, 2679.9934590000003 - 0.7000000000000001, 21000.0, 0.8748142513464991, 6471.901385600066, 3341.8394368000595, 2923.6292280000002 - 0.7000000000000001, 21000.0, 0.9477154389587075, 9049.596870400062, 4628.783739999933, 3167.264997 - 0.7000000000000001, 24000.0, 0.0, 348.9362302962637, 348.9362302962637, 0.0 - 0.7000000000000001, 24000.0, 0.4268617917414722, -2117.806280000001, -396.03726000000006, 1426.572108 - 0.7000000000000001, 24000.0, 0.49800542369838424, -1121.7162855999968, 11.971268799999827, 1664.3341260000002 - 0.7000000000000001, 24000.0, 0.5691490556552963, -125.62632639999075, 419.9797943999992, 1902.096144 - 0.7000000000000001, 24000.0, 0.6402926876122083, 870.4636280000061, 827.9884175999965, 2139.858162 - 0.7000000000000001, 24000.0, 0.7114363195691202, 1967.7611927999963, 1282.7801839999945, 2377.62018 - 0.7000000000000001, 24000.0, 0.7825799515260324, 3469.5872823999894, 1919.6414463999868, 2615.3821980000002 - 0.7000000000000001, 24000.0, 0.8537235834829444, 5457.3734527999895, 2804.8510808000015, 2853.144216 - 0.7000000000000001, 24000.0, 0.9248672154398564, 7676.847810399934, 3882.259772799949, 3090.906234 - 0.7000000000000001, 24000.0, 0.9960108473967685, 10022.141392000012, 5202.3329432, 3328.6682520000004 - 0.7000000000000001, 27000.0, 0.0, 309.80001209536334, 309.80001209536334, 0.0 - 0.7000000000000001, 27000.0, 0.41631744344703775, -2030.5025640000001, -415.9767512000001, 1391.3328960000001 - 0.7000000000000001, 27000.0, 0.485703684021544, -1136.7225391999993, -50.14491600000081, 1623.221712 - 0.7000000000000001, 27000.0, 0.5550899245960503, -242.9424975999958, 315.6869239999984, 1855.1105280000002 - 0.7000000000000001, 27000.0, 0.6244761651705566, 650.8375472000016, 681.5188536000011, 2086.9993440000003 - 0.7000000000000001, 27000.0, 0.693862405745063, 1604.3760575999977, 1073.508332000001, 2318.8881600000004 - 0.7000000000000001, 27000.0, 0.7632486463195691, 2876.44361599999, 1604.9369904000048, 2550.776976 - 0.7000000000000001, 27000.0, 0.8326348868940755, 4577.720181600009, 2346.9107568000077, 2782.6657920000002 - 0.7000000000000001, 27000.0, 0.9020211274685818, 6499.507540000001, 3256.3135439999824, 3014.5546080000004 - 0.7000000000000001, 27000.0, 0.971407368043088, 8408.642636000033, 4327.124971999997, 3246.443424 - 0.7000000000000001, 30000.0, 0.0, 274.21618388722516, 274.21618388722516, 0.0 - 0.7000000000000001, 30000.0, 0.4057721095152603, -1848.1926000000003, -395.1587, 1356.09039 - 0.7000000000000001, 30000.0, 0.4734007944344704, -1073.7360000000003, -76.56369999999973, 1582.1054550000001 - 0.7000000000000001, 30000.0, 0.5410294793536805, -299.2791999999998, 242.0312000000011, 1808.1205200000002 - 0.7000000000000001, 30000.0, 0.6086581642728905, 475.1775000000036, 560.6260999999989, 2034.1355850000002 - 0.7000000000000001, 30000.0, 0.6762868491921006, 1260.9569000000017, 883.7584999999957, 2260.15065 - 0.7000000000000001, 30000.0, 0.7439155341113106, 2355.853799999982, 1334.3778999999956, 2486.165715 - 0.7000000000000001, 30000.0, 0.8115442190305207, 3815.430199999983, 1956.4703000000018, 2712.18078 - 0.7000000000000001, 30000.0, 0.8791729039497308, 5479.653299999997, 2727.064699999983, 2938.195845 - 0.7000000000000001, 30000.0, 0.9468015888689408, 7139.989300000011, 3630.668700000011, 3164.2109100000002 - 0.7000000000000001, 33000.0, 0.0, 241.94007125432375, 241.94007125432375, 0.0 - 0.7000000000000001, 33000.0, 0.39522776122082587, -1961.4912111999995, -461.1621055999996, 1320.8511780000001 - 0.7000000000000001, 33000.0, 0.4610990547576302, -1228.5079368000036, -165.4048584000006, 1540.9930410000002 - 0.7000000000000001, 33000.0, 0.5269703482944346, -495.5246472000059, 130.35234959999892, 1761.1349040000002 - 0.7000000000000001, 33000.0, 0.5928416418312389, 237.45868159999532, 426.1096640000017, 1981.2767670000003 - 0.7000000000000001, 33000.0, 0.6587129353680431, 970.4420496000007, 721.8667992000085, 2201.41863 - 0.7000000000000001, 33000.0, 0.7245842289048475, 1889.0833775999988, 1093.7703032000031, 2421.5604930000004 - 0.7000000000000001, 33000.0, 0.7904555224416517, 3121.5364655999983, 1611.628215200007, 2641.7023560000002 - 0.7000000000000001, 33000.0, 0.8563268159784562, 4583.718986400011, 2265.904840799988, 2861.8442190000005 - 0.7000000000000001, 33000.0, 0.9221981095152604, 6002.152556800032, 3007.508638400013, 3081.9860820000004 - 0.7000000000000001, 33000.0, 0.9880694030520648, 7187.438087200046, 3789.1980624000244, 3302.1279450000006 - 0.7000000000000001, 36000.0, 0.0, 212.74183353551976, 212.74183353551976, 0.0 - 0.7000000000000001, 36000.0, 0.38468242728904856, -2059.2274999999995, -519.1376, 1285.6086720000003 - 0.7000000000000001, 36000.0, 0.44879616517055665, -1382.7578000000003, -247.75999999999942, 1499.8767840000003 - 0.7000000000000001, 36000.0, 0.5129099030520647, -706.2883000000003, 23.617600000001527, 1714.1448960000002 - 0.7000000000000001, 36000.0, 0.5770236409335727, -29.818699999995776, 294.9951999999993, 1928.4130080000002 - 0.7000000000000001, 36000.0, 0.6411373788150808, 646.6509000000017, 566.3728000000002, 2142.68112 - 0.7000000000000001, 36000.0, 0.705251116696589, 1411.1861999999949, 873.8886999999995, 2356.9492320000004 - 0.7000000000000001, 36000.0, 0.7693648545780971, 2431.1022999999936, 1294.1727, 2571.2173440000006 - 0.7000000000000001, 36000.0, 0.8334785924596051, 3647.29169999999, 1841.7520999999933, 2785.4854560000003 - 0.7000000000000001, 36000.0, 0.8975923303411133, 4915.921900000033, 2478.612299999982, 2999.7535680000005 - 0.7000000000000001, 36000.0, 0.9617060682226213, 5891.731899999996, 3106.173800000009, 3214.0216800000003 - 0.7000000000000001, 39000.0, 0.0, 184.25050480869658, 184.25050480869658, 0.0 - 0.7000000000000001, 39000.0, 0.38436899461400365, -2107.7874000000006, -558.1493999999998, 1284.5611800000001 - 0.7000000000000001, 39000.0, 0.4484304937163376, -1490.2678000000017, -310.44739999999916, 1498.6547100000003 - 0.7000000000000001, 39000.0, 0.5124919928186715, -872.7485000000016, -62.74539999999781, 1712.7482400000004 - 0.7000000000000001, 39000.0, 0.5765534919210055, -255.22909999999308, 184.95659999999972, 1926.8417700000005 - 0.7000000000000001, 39000.0, 0.6406149910233395, 362.29030000000097, 432.65859999999856, 2140.9353000000006 - 0.7000000000000001, 39000.0, 0.7046764901256735, 1041.8744999999979, 706.050400000001, 2355.0288300000007 - 0.7000000000000001, 39000.0, 0.7687379892280073, 1906.0031999999928, 1062.530999999998, 2569.1223600000003 - 0.7000000000000001, 39000.0, 0.8327994883303412, 2980.816200000006, 1534.984599999994, 2783.2158900000004 - 0.7000000000000001, 39000.0, 0.8968609874326752, 4045.224899999976, 2068.4953999999934, 2997.3094200000005 - 0.7000000000000001, 39000.0, 0.9609224865350091, 4979.737799999997, 2649.1279000000054, 3211.4029500000006 - 0.7000000000000001, 42000.0, 0.0, 159.50988971285093, 159.50988971285093, 0.0 - 0.7000000000000001, 42000.0, 0.38436899461400365, -2873.6632874999996, -928.1339249999993, 1284.5611800000001 - 0.7000000000000001, 42000.0, 0.4484304937163376, -2154.866737500005, -629.8127749999996, 1498.6547100000003 - 0.7000000000000001, 42000.0, 0.5124919928186715, -1436.0700875000114, -331.4916812500007, 1712.7482400000004 - 0.7000000000000001, 42000.0, 0.5765534919210055, -717.273387500001, -33.17055624999973, 1926.8417700000005 - 0.7000000000000001, 42000.0, 0.6406149910233395, 1.5232250000012106, 265.15056875000033, 2140.9353000000006 - 0.7000000000000001, 42000.0, 0.7046764901256735, 698.9133437499992, 551.2258500000008, 2355.0288300000007 - 0.7000000000000001, 42000.0, 0.7687379892280073, 1440.7435625000016, 856.9684062500002, 2569.1223600000003 - 0.7000000000000001, 42000.0, 0.8327994883303412, 2383.6729937500036, 1265.3433000000025, 2783.2158900000004 - 0.7000000000000001, 42000.0, 0.8968609874326752, 3287.898337500004, 1712.8468125000027, 2997.3094200000005 - 0.7000000000000001, 42000.0, 0.9609224865350091, 4146.564725000006, 2227.3098000000005, 3211.4029500000006 - 0.75, 0.0, 0.0, 855.7001096973654, 855.7001096973654, 0.0 - 0.75, 0.0, 0.5179716113105923, -18285.478525000093, -645.1483000000035, 1731.0611249999997 - 0.75, 0.0, 0.6043002131956912, -9540.39484999989, 598.1834999997695, 2019.5713124999997 - 0.75, 0.0, 0.6906288150807899, -795.2880749990491, 1841.5272999993576, 2308.0815 - 0.75, 0.0, 0.7769574169658886, 4091.459674998692, 3241.3097000006283, 2596.5916875 - 0.75, 0.0, 0.8632860188509874, -1575.0965749946627, 4348.571224998934, 2885.101875 - 0.75, 0.0, 0.9496146207360862, -8051.193099994358, 5629.756075000845, 3173.6120625 - 0.75, 3000.0, 0.0, 774.9490034179007, 774.9490034179007, 0.0 - 0.75, 3000.0, 0.5072880161579892, 1601.5549643855284, 361.888520737214, 1695.35655 - 0.75, 3000.0, 0.5918360188509874, 1316.418209865977, 1056.841247035669, 1977.915975 - 0.75, 3000.0, 0.6763840215439856, 1031.352407125728, 1751.8338367623105, 2260.4754 - 0.75, 3000.0, 0.7609320242369838, 2263.8499732908494, 2657.520356068175, 2543.0348249999997 - 0.75, 3000.0, 0.8454800269299819, 9103.999038960108, 4282.6806021012835, 2825.5942499999996 - 0.75, 3000.0, 0.9300280296229801, 9983.064306937486, 6075.907967768982, 3108.1536749999996 - 0.75, 6000.0, 0.0, 700.338818958097, 700.338818958097, 0.0 - 0.75, 6000.0, 0.4966034223518852, -12371.054399999986, 32.396999999999764, 1659.6486375000004 - 0.75, 6000.0, 0.5793706594105328, -7401.029599999999, 742.3926000000225, 1936.2567437500004 - 0.75, 6000.0, 0.6621378964691802, -2430.9552000003628, 1452.3883000000574, 2212.8648500000004 - 0.75, 6000.0, 0.7449051335278278, 2004.8667000001983, 2294.5112000001873, 2489.4729562500006 - 0.75, 6000.0, 0.8276723705864752, 8134.424200001864, 3762.568999998957, 2766.0810625000004 - 0.75, 6000.0, 0.9104396076451229, 6181.666799995997, 4549.810600001754, 3042.6891687500006 - 0.75, 6000.0, 0.9932068447037704, 12260.307399996025, 7801.6147000019755, 3319.297275000001 - 0.75, 9000.0, 0.0, 631.5212824237357, 631.5212824237357, 0.0 - 0.75, 9000.0, 0.48591982719928184, -1552.7419375000215, 37.23154999999814, 1623.9440625 - 0.75, 9000.0, 0.5669064650658288, -254.55683749993216, 671.5559125000093, 1894.6014062499999 - 0.75, 9000.0, 0.6478931029323758, 1043.62750000013, 1305.880124999991, 2165.25875 - 0.75, 9000.0, 0.7288797407989228, 2545.7391749999206, 2060.823737499976, 2435.91609375 - 0.75, 9000.0, 0.8098663786654698, 4856.654062500365, 3143.3211374998496, 2706.5734375 - 0.75, 9000.0, 0.8908530165320168, 8208.842562500264, 4716.950587500167, 2977.23078125 - 0.75, 9000.0, 0.9718396543985637, 11922.290462499355, 6747.957287499631, 3247.888125 - 0.75, 12000.0, 0.0, 568.1546531528352, 568.1546531528352, 0.0 - 0.75, 12000.0, 0.4752352333931778, -2414.210824374989, -100.71134999999924, 1588.2361500000002 - 0.75, 12000.0, 0.5544411056253741, -906.1498806249656, 500.18910124999115, 1852.9421750000001 - 0.75, 12000.0, 0.6336469778575703, 601.910999375073, 1101.089558749955, 2117.6482 - 0.75, 12000.0, 0.7128528500897666, 2180.2099449999732, 1772.4121643749666, 2382.354225 - 0.75, 12000.0, 0.792058722321963, 4219.624693124859, 2700.8673112498186, 2647.06025 - 0.75, 12000.0, 0.8712645945541592, 6873.0429587494455, 3985.0316393746716, 2911.766275 - 0.75, 12000.0, 0.9504704667863556, 10623.509388750004, 5843.055108749798, 3176.4723000000004 - 0.75, 15000.0, 0.0, 509.9191522656429, 509.9191522656429, 0.0 - 0.75, 15000.0, 0.4645516382405745, -1862.8046200000044, -144.7924600000006, 1552.531575 - 0.75, 15000.0, 0.5419769112806703, -676.7410800000129, 392.509599999994, 1811.2868375 - 0.75, 15000.0, 0.619402184320766, 509.32251999994423, 929.8118599999656, 2070.0421 - 0.75, 15000.0, 0.6968274573608617, 1791.3456999999582, 1506.92374000001, 2328.7973625 - 0.75, 15000.0, 0.7742527304009575, 3558.123859999942, 2301.515419999996, 2587.5526250000003 - 0.75, 15000.0, 0.8516780034410533, 5947.896059999968, 3408.1558600000812, 2846.3078875 - 0.75, 15000.0, 0.929103276481149, 9145.537879999885, 4988.904719999826, 3105.06315 - 0.75, 18000.0, 0.0, 456.5038367745404, 456.5038367745404, 0.0 - 0.75, 18000.0, 0.45386704443447035, -1895.0560814285711, -217.85175857142866, 1516.8236625 - 0.75, 18000.0, 0.5295115518402155, -787.580977142858, 273.87789857142786, 1769.62760625 - 0.75, 18000.0, 0.6051560592459605, 319.894041428566, 765.6074528571417, 2022.43155 - 0.75, 18000.0, 0.6808005666517055, 1455.5080100000002, 1269.3942185714275, 2275.23549375 - 0.75, 18000.0, 0.7564450740574507, 2998.6396071428335, 1952.1675628571531, 2528.0394375 - 0.75, 18000.0, 0.8320895814631958, 5096.756127142885, 2906.1171314285775, 2780.84338125 - 0.75, 18000.0, 0.9077340888689407, 7828.234138571509, 4228.108160000011, 3033.647325 - 0.75, 18000.0, 0.9833785962746858, 10768.633251428544, 5803.71074571435, 3286.45126875 - 0.75, 21000.0, 0.0, 407.6071663985174, 407.6071663985174, 0.0 - 0.75, 21000.0, 0.44318344928186715, -1994.6858039999997, -302.54007679999984, 1481.1190875 - 0.75, 21000.0, 0.5170473574955117, -942.6488511999995, 155.040208, 1727.97226875 - 0.75, 21000.0, 0.5909112657091562, 109.3881231999998, 612.6203983999997, 1974.82545 - 0.75, 21000.0, 0.6647751739228007, 1161.0153512000147, 1070.0083592000099, 2221.67863125 - 0.75, 21000.0, 0.7386390821364452, 2485.164615200006, 1647.0263584000202, 2468.5318125 - 0.75, 21000.0, 0.8125029903500898, 4301.394192799989, 2459.976487999987, 2715.38499375 - 0.75, 21000.0, 0.8863668985637343, 6674.529284799966, 3580.0849944000006, 2962.238175 - 0.75, 21000.0, 0.9602308067773788, 9300.840274399947, 4949.787423199967, 3209.09135625 - 0.75, 24000.0, 0.0, 362.9435673034746, 362.9435673034746, 0.0 - 0.75, 24000.0, 0.432498855475763, -2007.5833095999992, -361.60537839999984, 1445.411175 - 0.75, 24000.0, 0.5045819980550569, -1039.136756799998, 55.65934800000037, 1686.3130375 - 0.75, 24000.0, 0.5766651406343507, -70.69039519999548, 472.9240992000011, 1927.2149 - 0.75, 24000.0, 0.6487482832136444, 897.755963200003, 890.1888023999949, 2168.1167625 - 0.75, 24000.0, 0.7208314257929382, 2011.3042271999866, 1370.678020800001, 2409.0186249999997 - 0.75, 24000.0, 0.7929145683722322, 3583.6642232000054, 2062.3739848000064, 2649.9204875 - 0.75, 24000.0, 0.864997710951526, 5630.150037599998, 3003.0377831999936, 2890.82235 - 0.75, 24000.0, 0.9370808535308198, 7910.878530399985, 4166.8922007999845, 3131.7242125 - 0.75, 27000.0, 0.0, 322.2363050265196, 322.2363050265196, 0.0 - 0.75, 27000.0, 0.42181526032315986, -2119.096680000001, -419.20960000000014, 1409.7066000000002 - 0.75, 27000.0, 0.49211780371035313, -1195.7030408000037, -35.728532000000165, 1644.6577000000002 - 0.75, 27000.0, 0.5624203470975464, -272.3093120000112, 347.75253280000027, 1879.6088000000002 - 0.75, 27000.0, 0.6327228904847397, 651.0843952000021, 731.2335711999981, 2114.5599 - 0.75, 27000.0, 0.7030254338719331, 1645.588803999999, 1148.9930671999957, 2349.5110000000004 - 0.75, 27000.0, 0.7733279772591263, 2951.861701599997, 1717.383557599986, 2584.4621 - 0.75, 27000.0, 0.8436305206463197, 4733.9284415999655, 2516.5905071999987, 2819.4132000000004 - 0.75, 27000.0, 0.9139330640335129, 6696.334550399998, 3488.7168504000247, 3054.3643 - 0.75, 27000.0, 0.9842356074207063, 8694.8410816, 4653.553852799981, 3289.3154000000004 - 0.75, 30000.0, 0.0, 285.2240362311289, 285.2240362311289, 0.0 - 0.75, 30000.0, 0.41113066651705565, -2108.3202999999985, -445.44129999999967, 1373.9986875 - 0.75, 30000.0, 0.4796524442698983, -1261.581299999999, -99.46719999999878, 1602.99846875 - 0.75, 30000.0, 0.5481742220227409, -414.84229999999917, 246.50700000000393, 1831.99825 - 0.75, 30000.0, 0.6166959997755835, 431.89660000002067, 592.4810999999994, 2060.99803125 - 0.75, 30000.0, 0.6852177775284262, 1309.3966000000087, 953.0467999999876, 2289.9978125000002 - 0.75, 30000.0, 0.7537395552812688, 2431.7521999999644, 1431.941199999993, 2518.9975937500003 - 0.75, 30000.0, 0.8222613330341113, 3950.678999999937, 2101.5139000000145, 2747.997375 - 0.75, 30000.0, 0.8907831107869539, 5654.978000000027, 2922.052699999952, 2976.99715625 - 0.75, 30000.0, 0.9593048885397966, 7341.8223000000335, 3889.1440000000557, 3205.9969375 - 0.75, 33000.0, 0.0, 251.6522645417062, 251.6522645417062, 0.0 - 0.75, 33000.0, 0.4004470713644525, -1946.4356087999988, -443.24627119999985, 1338.2941125000002 - 0.75, 33000.0, 0.46718824992519453, -1210.7973839999972, -139.1566712000004, 1561.3431312500002 - 0.75, 33000.0, 0.5339294284859366, -475.15928879999615, 164.93281119999878, 1784.3921500000001 - 0.75, 33000.0, 0.6006706070466786, 260.4789239999961, 469.02240479999654, 2007.44116875 - 0.75, 33000.0, 0.6674117856074208, 994.9745520000021, 772.5832200000028, 2230.4901875 - 0.75, 33000.0, 0.7341529641681628, 1955.3644784000073, 1175.602210400012, 2453.53920625 - 0.75, 33000.0, 0.800894142728905, 3233.559563200008, 1728.0857511999939, 2676.5882250000004 - 0.75, 33000.0, 0.867635321289647, 4721.139566399974, 2421.335973600044, 2899.6372437500004 - 0.75, 33000.0, 0.9343764998503891, 6164.250866400064, 3219.19642400001, 3122.6862625000003 - 0.75, 36000.0, 0.0, 221.28192281009532, 221.28192281009532, 0.0 - 0.75, 36000.0, 0.3897624775583483, -2063.2428999999993, -494.9377000000003, 1302.5862 - 0.75, 36000.0, 0.4547228904847397, -1379.5814999999977, -217.87889999999837, 1519.6839 - 0.75, 36000.0, 0.5196833034111311, -695.9199999999915, 59.17990000000403, 1736.7816 - 0.75, 36000.0, 0.5846437163375224, -12.258599999987538, 336.2385999999983, 1953.8793 - 0.75, 36000.0, 0.6496041292639138, 671.4028000000025, 613.2975000000015, 2170.977 - 0.75, 36000.0, 0.7145645421903053, 1465.9484999999856, 939.0536000000008, 2388.0747 - 0.75, 36000.0, 0.7795249551166966, 2515.7606999999834, 1389.1945000000037, 2605.1724 - 0.75, 36000.0, 0.844485368043088, 3764.5788999999695, 1975.5850999999932, 2822.2701 - 0.75, 36000.0, 0.9094457809694794, 5018.906200000103, 2636.8754999999487, 3039.3678 - 0.75, 36000.0, 0.9744061938958708, 6063.219699999988, 3334.0171000000305, 3256.4655000000002 - 0.75, 39000.0, 0.0, 191.64686749769822, 191.64686749769822, 0.0 - 0.75, 39000.0, 0.38944490574506285, -2080.6943000000015, -571.2825999999994, 1301.524875 - 0.75, 39000.0, 0.45435239003590666, -1459.0957000000028, -309.66249999999735, 1518.4456875 - 0.75, 39000.0, 0.5192598743267505, -837.4968000000039, -48.04229999999392, 1735.3665 - 0.75, 39000.0, 0.5841673586175943, -215.89799999998587, 213.5778999999992, 1952.2873125 - 0.75, 39000.0, 0.6490748429084381, 405.70080000000223, 475.1979999999941, 2169.208125 - 0.75, 39000.0, 0.7139823271992819, 1099.181799999985, 763.9191000000053, 2386.1289375 - 0.75, 39000.0, 0.7788898114901257, 1982.8291999999897, 1143.8013999999948, 2603.04975 - 0.75, 39000.0, 0.8437972957809695, 3074.287800000015, 1651.355299999991, 2819.9705625 - 0.75, 39000.0, 0.9087047800718133, 4156.584999999953, 2211.0363999999727, 3036.891375 - 0.75, 39000.0, 0.9736122643626571, 5099.631799999978, 2826.007600000027, 3253.8121875 - 0.75, 42000.0, 0.0, 165.91309060515698, 165.91309060515698, 0.0 - 0.75, 42000.0, 0.38944490574506285, -2435.906162500001, -744.892174999999, 1301.524875 - 0.75, 42000.0, 0.45435239003590666, -1798.9895375000158, -475.2955249999995, 1518.4456875 - 0.75, 42000.0, 0.5192598743267505, -1162.072987500036, -205.69881875000127, 1735.3665 - 0.75, 42000.0, 0.5841673586175943, -525.1563624999966, 63.89788125000091, 1952.2873125 - 0.75, 42000.0, 0.6490748429084381, 111.76020000000042, 333.4945312500009, 2169.208125 - 0.75, 42000.0, 0.7139823271992819, 748.0753812500001, 601.3255249999985, 2386.1289375 - 0.75, 42000.0, 0.7788898114901257, 1519.3070124999995, 929.6106687500013, 2603.04975 - 0.75, 42000.0, 0.8437972957809695, 2473.777756250016, 1366.2164500000126, 2819.9705625 - 0.75, 42000.0, 0.9087047800718133, 3415.487862500008, 1847.1166375000055, 3036.891375 - 0.75, 42000.0, 0.9736122643626571, 4233.545575, 2363.7417250000076, 3253.8121875 - 0.8, 0.0, 0.0, 891.9670832142106, 891.9670832142106, 0.0 - 0.8, 0.0, 0.5251882944344703, -24946.30020000012, -978.4093000000046, 1755.1792799999998 - 0.8, 0.0, 0.6127196768402154, -13342.162199999842, 462.9512999997122, 2047.7091599999999 - 0.8, 0.0, 0.7002510592459604, -1737.9921999987346, 1904.3283999991927, 2340.23904 - 0.8, 0.0, 0.7877824416517055, 4066.913299998261, 3467.1792000007335, 2632.76892 - 0.8, 0.0, 0.8753138240574506, -5182.105199993435, 4459.938399998611, 2925.2988 - 0.8, 0.0, 0.9628452064631957, -15340.10719999278, 5497.337800000968, 3217.82868 - 0.8, 3000.0, 0.0, 807.7935182956683, 807.7935182956683, 0.0 - 0.8, 3000.0, 0.5143558491921005, 3115.3774764991103, 477.1100449146126, 1718.9772480000001 - 0.8, 3000.0, 0.6000818240574507, 1966.0665154408453, 1170.4083383575091, 2005.4734560000002 - 0.8, 3000.0, 0.6858077989228007, 816.8578778620677, 1863.7640758176378, 2291.969664 - 0.8, 3000.0, 0.7715337737881509, 1744.3917797484191, 2801.638409990247, 2578.465872 - 0.8, 3000.0, 0.857259748653501, 10327.326346044792, 4579.072520789531, 2864.9620800000002 - 0.8, 3000.0, 0.942985723518851, 10024.978981812033, 6446.765878679083, 3151.4582880000003 - 0.8, 6000.0, 0.0, 730.0211447076573, 730.0211447076573, 0.0 - 0.8, 6000.0, 0.5035223913824058, -17089.193499999972, 45.787399999999735, 1682.7718320000004 - 0.8, 6000.0, 0.5874427899461402, -10597.861599999984, 781.213300000026, 1963.2338040000004 - 0.8, 6000.0, 0.6713631885098744, -4106.457400000468, 1516.639300000064, 2243.6957760000005 - 0.8, 6000.0, 0.7552835870736088, 1522.2208000002993, 2403.424400000244, 2524.1577480000005 - 0.8, 6000.0, 0.8392039856373431, 9390.35850000236, 4073.4271999985795, 2804.6197200000006 - 0.8, 6000.0, 0.9231243842010773, 4708.833099994736, 4473.1850000023505, 3085.0816920000007 - 0.8, 9000.0, 0.0, 658.2869277303441, 658.2869277303441, 0.0 - 0.8, 9000.0, 0.492689946140036, -1581.9260000000265, 85.61319999999782, 1646.5698000000002 - 0.8, 9000.0, 0.5748049371633753, -311.04759999991313, 736.1732000000105, 1920.9981000000002 - 0.8, 9000.0, 0.6569199281867146, 959.8308000001607, 1386.733199999981, 2195.4264000000003 - 0.8, 9000.0, 0.7390349192100539, 2485.5355999998797, 2190.617399999954, 2469.8547000000003 - 0.8, 9000.0, 0.8211499102333932, 5006.255900000543, 3365.8498999998087, 2744.2830000000004 - 0.8, 9000.0, 0.9032649012567326, 8522.402300000365, 5072.7495000001745, 3018.7113000000004 - 0.8, 9000.0, 0.985379892280072, 12028.083999999071, 7177.7196999995485, 3293.1396000000004 - 0.8, 12000.0, 0.0, 592.2346427728596, 592.2346427728596, 0.0 - 0.8, 12000.0, 0.4818564883303411, -2237.6415999999836, -42.76879999999909, 1610.364384 - 0.8, 12000.0, 0.5621659030520646, -787.3420999999566, 570.6375999999894, 1878.758448 - 0.8, 12000.0, 0.6424753177737882, 662.9575000000891, 1184.044099999943, 2147.152512 - 0.8, 12000.0, 0.7227847324955117, 2163.187299999944, 1880.2307999999502, 2415.546576 - 0.8, 12000.0, 0.8030941472172353, 4246.08059999985, 2874.182099999748, 2683.9406400000003 - 0.8, 12000.0, 0.8834035619389589, 7036.15819999923, 4283.759299999549, 2952.3347040000003 - 0.8, 12000.0, 0.9637129766606822, 10934.911100000085, 6257.372099999738, 3220.728768 - 0.8, 15000.0, 0.0, 531.5309578285645, 531.5309578285645, 0.0 - 0.8, 15000.0, 0.47102404308797136, -1754.0936000000079, -93.78300000000088, 1574.1623520000003 - 0.8, 15000.0, 0.5495280502693, -610.5999000000205, 455.3898999999899, 1836.5227440000003 - 0.8, 15000.0, 0.6280320574506285, 532.8937999999116, 1004.5627999999449, 2098.8831360000004 - 0.8, 15000.0, 0.7065360646319571, 1815.9672999999357, 1607.0071000000114, 2361.2435280000004 - 0.8, 15000.0, 0.7850400718132856, 3648.40749999991, 2458.4741000000004, 2623.6039200000005 - 0.8, 15000.0, 0.8635440789946142, 6097.683599999989, 3654.2615000001324, 2885.9643120000005 - 0.8, 15000.0, 0.9420480861759427, 9427.890599999919, 5357.9691999997385, 3148.3247040000006 - 0.8, 18000.0, 0.0, 475.8517512728752, 475.8517512728752, 0.0 - 0.8, 18000.0, 0.4601905852782765, -1752.1545000000006, -164.55400000000054, 1537.956936 - 0.8, 18000.0, 0.5368890161579892, -697.4080999999998, 333.935799999998, 1794.2830920000001 - 0.8, 18000.0, 0.6135874470377021, 357.3381999999945, 832.4254999999966, 2050.609248 - 0.8, 18000.0, 0.6902858779174148, 1487.065700000014, 1362.2966000000101, 2306.9354040000003 - 0.8, 18000.0, 0.7669843087971275, 3076.798799999934, 2090.8596000000243, 2563.2615600000004 - 0.8, 18000.0, 0.8436827396768404, 5257.201700000051, 3116.5737000000263, 2819.5877160000005 - 0.8, 18000.0, 0.920381170556553, 8079.039100000138, 4535.61280000001, 3075.913872 - 0.8, 18000.0, 0.9970796014362657, 11682.747099999984, 6187.112300000163, 3332.240028 - 0.8, 21000.0, 0.0, 424.8827027009254, 424.8827027009254, 0.0 - 0.8, 21000.0, 0.4493581400359067, -1936.3623439999992, -261.0069447999997, 1501.7549040000001 - 0.8, 21000.0, 0.5242511633752245, -895.9699431999968, 206.99386800000124, 1752.0473880000002 - 0.8, 21000.0, 0.5991441867145423, 144.42243520000366, 674.9947024000022, 2002.3398720000002 - 0.8, 21000.0, 0.67403721005386, 1190.5510232000318, 1145.6883312000218, 2252.632356 - 0.8, 21000.0, 0.7489302333931778, 2572.7608472000024, 1768.718302400065, 2502.92484 - 0.8, 21000.0, 0.8238232567324956, 4454.742440800006, 2643.417227999981, 2753.217324 - 0.8, 21000.0, 0.8987162800718134, 6906.615712799916, 3843.6439783999976, 3003.5098080000002 - 0.8, 21000.0, 0.9736093034111312, 9576.006558399831, 5301.669015199899, 3253.8022920000003 - 0.8, 24000.0, 0.0, 378.32613485761414, 378.32613485761414, 0.0 - 0.8, 24000.0, 0.4385246822262119, -1867.215133599996, -320.37543439999956, 1465.549488 - 0.8, 24000.0, 0.5116121292639139, -932.3074487999932, 106.1674480000007, 1709.807736 - 0.8, 24000.0, 0.5846995763016158, 2.6001568000203186, 532.7104272000039, 1954.065984 - 0.8, 24000.0, 0.6577870233393177, 937.5077712000124, 959.2531983999899, 2198.324232 - 0.8, 24000.0, 0.7308744703770198, 2096.598395199967, 1479.2069728000095, 2442.58248 - 0.8, 24000.0, 0.8039619174147218, 3710.5476312000374, 2214.739116800036, 2686.840728 - 0.8, 24000.0, 0.8770493644524238, 5841.670121600021, 3229.441011200005, 2931.098976 - 0.8, 24000.0, 0.9501368114901257, 8176.213386400026, 4481.946372799968, 3175.3572240000003 - 0.8, 27000.0, 0.0, 335.8935844964216, 335.8935844964216, 0.0 - 0.8, 27000.0, 0.42769223698384207, -1977.1880400000023, -375.29336000000023, 1429.3474560000002 - 0.8, 27000.0, 0.4989742764811491, -1083.480112800013, 14.609547999999618, 1667.5720320000003 - 0.8, 27000.0, 0.5702563159784562, -189.7722120000353, 404.5124648000015, 1905.7966080000003 - 0.8, 27000.0, 0.6415383554757631, 703.9355832000083, 794.4152791999975, 2144.021184 - 0.8, 27000.0, 0.71282039497307, 1692.4839440000023, 1230.7780751999899, 2382.2457600000002 - 0.8, 27000.0, 0.7841024344703771, 3068.2069456000063, 1849.3239215999743, 2620.4703360000003 - 0.8, 27000.0, 0.8553844739676841, 4908.5317655999415, 2704.7064952000183, 2858.6949120000004 - 0.8, 27000.0, 0.9266665134649912, 6922.4723264000595, 3748.6854464001153, 3096.9194880000005 - 0.8, 27000.0, 0.9979485529622982, 9102.29008560007, 5050.496244799962, 3335.1440640000005 - 0.8, 30000.0, 0.0, 297.3126318163514, 297.3126318163514, 0.0 - 0.8, 30000.0, 0.41685877917414726, -2064.091799999998, -438.63399999999945, 1393.1420400000002 - 0.8, 30000.0, 0.48633524236983844, -1218.424599999998, -77.91189999999746, 1625.33238 - 0.8, 30000.0, 0.5558117055655297, -372.75739999999854, 282.81030000000845, 1857.5227200000002 - 0.8, 30000.0, 0.6252881687612208, 472.90990000005195, 643.5324000000016, 2089.71306 - 0.8, 30000.0, 0.6947646319569121, 1370.5848000000206, 1028.2997999999736, 2321.9034 - 0.8, 30000.0, 0.7642410951526033, 2530.4713999999485, 1542.4593999999915, 2554.0937400000003 - 0.8, 30000.0, 0.8337175583482945, 4107.3310999998575, 2260.4058000000323, 2786.2840800000004 - 0.8, 30000.0, 0.9031940215439858, 5852.453600000058, 3140.5597999999054, 3018.4744200000005 - 0.8, 30000.0, 0.9726704847396769, 7598.472200000073, 4178.72850000015, 3250.66476 - 0.8, 33000.0, 0.0, 262.31799417076513, 262.31799417076513, 0.0 - 0.8, 33000.0, 0.4060263339317774, -2072.612344799997, -464.65303519999986, 1356.940008 - 0.8, 33000.0, 0.47369738958707364, -1296.432943999991, -141.05483520000112, 1583.0966760000001 - 0.8, 33000.0, 0.5413684452423699, -520.2535647999858, 182.54331519999724, 1809.2533440000002 - 0.8, 33000.0, 0.6090395008976661, 255.9258639999875, 506.1415207999882, 2035.4100120000003 - 0.8, 33000.0, 0.6767105565529624, 1036.6761520000123, 831.8546400000043, 2261.5666800000004 - 0.8, 33000.0, 0.7443816122082587, 2035.1663264000142, 1265.5596984000265, 2487.7233480000004 - 0.8, 33000.0, 0.8120526678635548, 3365.893767200005, 1857.8651751999726, 2713.880016 - 0.8, 33000.0, 0.8797237235188511, 4871.020294399914, 2596.612225600116, 2940.036684 - 0.8, 33000.0, 0.9473947791741473, 6356.582314400168, 3459.1663840000238, 3166.1933520000002 - 0.8, 36000.0, 0.0, 230.66047207444984, 230.66047207444984, 0.0 - 0.8, 36000.0, 0.39519287612208265, -2093.650599999999, -502.8068000000006, 1320.7345920000002 - 0.8, 36000.0, 0.46105835547576307, -1394.4093999999925, -211.88190000000276, 1540.8570240000001 - 0.8, 36000.0, 0.5269238348294435, -695.1682999999791, 79.0428999999939, 1760.9794560000003 - 0.8, 36000.0, 0.592789314183124, 4.073000000006379, 369.9678000000034, 1981.1018880000004 - 0.8, 36000.0, 0.6586547935368043, 703.3140999999993, 660.8927000000034, 2201.2243200000003 - 0.8, 36000.0, 0.7245202728904848, 1537.8642999999938, 1014.5940999999863, 2421.3467520000004 - 0.8, 36000.0, 0.7903857522441653, 2605.121800000032, 1502.2316999999891, 2641.4691840000005 - 0.8, 36000.0, 0.8562512315978458, 3906.2864000000573, 2121.9667999999783, 2861.5916160000006 - 0.8, 36000.0, 0.9221167109515261, 5160.527799999968, 2819.0461000000205, 3081.7140480000003 - 0.8, 36000.0, 0.9879821903052066, 6214.967299999988, 3542.957500000002, 3301.8364800000004 - 0.8, 39000.0, 0.0, 199.76939990053197, 199.76939990053197, 0.0 - 0.8, 39000.0, 0.3948708797127469, -2166.228299999999, -575.2118999999985, 1319.6584800000003 - 0.8, 39000.0, 0.46068269299820475, -1512.1345000000047, -300.6273999999964, 1539.6015600000003 - 0.8, 39000.0, 0.5264945062836626, -858.0406000000104, -26.04309999998924, 1759.5446400000003 - 0.8, 39000.0, 0.5923063195691204, -203.9466999999877, 248.5413000000005, 1979.4877200000003 - 0.8, 39000.0, 0.6581181328545782, 450.14720000000364, 523.125700000005, 2199.4308000000005 - 0.8, 39000.0, 0.723929946140036, 1165.0148999999974, 829.2135999999978, 2419.3738800000006 - 0.8, 39000.0, 0.7897417594254938, 2072.4602000000255, 1242.0977000000141, 2639.3169600000006 - 0.8, 39000.0, 0.8555535727109517, 3202.9565000000207, 1778.1105000000325, 2859.2600400000006 - 0.8, 39000.0, 0.9213653859964095, 4305.4131, 2377.555700000009, 3079.2031200000006 - 0.8, 39000.0, 0.9871771992818673, 5206.169899999987, 2987.7084999999847, 3299.1462000000006 - 0.8, 42000.0, 0.0, 172.944953280976, 172.944953280976, 0.0 - 0.8, 42000.0, 0.3948708797127469, -2368.166799999999, -692.7329874999996, 1319.6584800000003 - 0.8, 42000.0, 0.46068269299820475, -1730.601950000005, -422.7216750000016, 1539.6015600000003 - 0.8, 42000.0, 0.5264945062836626, -1093.0371000000114, -152.71024375000368, 1759.5446400000003 - 0.8, 42000.0, 0.5923063195691204, -455.4723625000194, 117.30118124999811, 1979.4877200000003 - 0.8, 42000.0, 0.6581181328545782, 182.0924374999938, 387.3125562500025, 2199.4308000000005 - 0.8, 42000.0, 0.723929946140036, 816.289218749999, 659.9683937500035, 2419.3738800000006 - 0.8, 42000.0, 0.7897417594254938, 1604.931393750002, 1013.4273500000048, 2639.3169600000006 - 0.8, 42000.0, 0.8555535727109517, 2582.4594437500164, 1475.4576624999977, 2859.2600400000006 - 0.8, 42000.0, 0.9213653859964095, 3546.2131375000176, 1986.8950687500085, 3079.2031200000006 - 0.8, 42000.0, 0.9871771992818673, 4367.351431250019, 2529.5573250000166, 3299.1462000000006 - 0.8500000000000001, 0.0, 0.0, 931.6846058533836, 931.6846058533836, 0.0 - 0.8500000000000001, 0.0, 0.5328705700179532, -33163.22545000017, -1399.9068000000066, 1780.8534449999997 - 0.8500000000000001, 0.0, 0.6216823316876122, -18017.205499999804, 282.62489999964583, 2077.6623525 - 0.8500000000000001, 0.0, 0.710494093357271, -2871.1426499983463, 1965.1785999990016, 2374.47126 - 0.8500000000000001, 0.0, 0.7993058550269299, 4049.943049997757, 3717.240900000844, 2671.2801674999996 - 0.8500000000000001, 0.0, 0.8881176166965888, -9629.867849992013, 4553.7559499982335, 2968.089075 - 0.8500000000000001, 0.0, 0.9769293783662476, -24268.95029999093, 5269.307950001098, 3264.8979824999997 - 0.8500000000000001, 3000.0, 0.0, 843.7629592699609, 843.7629592699609, 0.0 - 0.8500000000000001, 3000.0, 0.521879671454219, 5025.556129412688, 611.025901292011, 1744.121862 - 0.8500000000000001, 3000.0, 0.6088596166965888, 2794.123445415729, 1298.7951950793586, 2034.808839 - 0.8500000000000001, 3000.0, 0.6958395619389587, 562.8324571984385, 1986.6439804729926, 2325.495816 - 0.8500000000000001, 3000.0, 0.7828195071813285, 1107.6344590059998, 2956.5198293123876, 2616.182793 - 0.8500000000000001, 3000.0, 0.8697994524236985, 11867.249507529436, 4905.024303477822, 2906.8697700000002 - 0.8500000000000001, 3000.0, 0.9567793976660682, 10082.003075087057, 6851.6295189892335, 3197.556747 - 0.8500000000000001, 6000.0, 0.0, 762.5275363533208, 762.5275363533208, 0.0 - 0.8500000000000001, 6000.0, 0.5108877455116697, -23034.483899999967, 52.5671999999997, 1707.3868455000002 - 0.8500000000000001, 6000.0, 0.596035703096948, -14624.043499999978, 816.1443000000294, 1991.9513197500003 - 0.8500000000000001, 6000.0, 0.6811836606822264, -6213.502100000596, 1579.72150000007, 2276.5157940000004 - 0.8500000000000001, 6000.0, 0.7663316182675045, 913.1722000004283, 2515.0297000003125, 2561.0802682500002 - 0.8500000000000001, 6000.0, 0.8514795758527829, 10987.254100002923, 4430.04839999812, 2845.6447425000006 - 0.8500000000000001, 6000.0, 0.9366275334380612, 2773.1969999932335, 4305.699400003077, 3130.2092167500005 - 0.8500000000000001, 9000.0, 0.0, 687.5991371685959, 687.5991371685959, 0.0 - 0.8500000000000001, 9000.0, 0.4998968469479354, -1710.2652500000313, 130.68269999999754, 1670.6552625000002 - 0.8500000000000001, 9000.0, 0.5832129881059247, -447.31834999989195, 799.9592500000107, 1949.0978062500003 - 0.8500000000000001, 9000.0, 0.6665291292639139, 815.6299000001924, 1469.236099999967, 2227.54035 - 0.8500000000000001, 9000.0, 0.7498452704219031, 2394.568399999829, 2330.5846499999247, 2505.98289375 - 0.8500000000000001, 9000.0, 0.8331614115798923, 5224.318450000771, 3617.3436499997624, 2784.4254375 - 0.8500000000000001, 9000.0, 0.9164775527378817, 8926.234550000489, 5474.270450000165, 3062.8679812500004 - 0.8500000000000001, 9000.0, 0.9997936938958708, 12111.286549998713, 7637.388949999461, 3341.3105250000003 - 0.8500000000000001, 12000.0, 0.0, 618.6056751513992, 618.6056751513992, 0.0 - 0.8500000000000001, 12000.0, 0.488904921005386, -1811.805982727251, 32.7750909090918, 1633.9202460000001 - 0.8500000000000001, 12000.0, 0.5703890745062837, -502.1741281817674, 654.596134545443, 1906.240287 - 0.8500000000000001, 12000.0, 0.6518732280071813, 807.4581645455567, 1276.4174145453858, 2178.560328 - 0.8500000000000001, 12000.0, 0.7333573815080789, 2121.807216363542, 1988.2466427272022, 2450.880369 - 0.8500000000000001, 12000.0, 0.8148415350089766, 4239.494582727135, 3055.995438181486, 2723.20041 - 0.8500000000000001, 12000.0, 0.8963256885098743, 7230.834259998971, 4629.116588181222, 2995.520451 - 0.8500000000000001, 12000.0, 0.977809842010772, 11284.50162545477, 6709.4267509087695, 3267.8404920000003 - 0.8500000000000001, 15000.0, 0.0, 555.1989756828818, 555.1989756828818, 0.0 - 0.8500000000000001, 15000.0, 0.4779140224416518, -1600.8679000000138, -37.48750000000122, 1597.1886630000004 - 0.8500000000000001, 15000.0, 0.5575663595152605, -510.2755000000307, 523.8966999999848, 1863.3867735000003 - 0.8500000000000001, 15000.0, 0.6372186965888691, 580.316499999869, 1085.2803999999194, 2129.5848840000003 - 0.8500000000000001, 15000.0, 0.7168710336624776, 1849.748999999912, 1706.954300000012, 2395.7829945000003 - 0.8500000000000001, 15000.0, 0.7965233707360863, 3764.1081999998705, 2623.5226000000093, 2661.9811050000003 - 0.8500000000000001, 15000.0, 0.8761757078096949, 6266.996700000038, 3935.0378000002, 2928.1792155000003 - 0.8500000000000001, 15000.0, 0.9558280448833036, 9731.933500000026, 5761.926199999636, 3194.3773260000007 - 0.8500000000000001, 18000.0, 0.0, 497.04048464627, 497.04048464627, 0.0 - 0.8500000000000001, 18000.0, 0.4669220964991024, -1687.6643150000018, -117.82439500000135, 1560.4536465 - 0.8500000000000001, 18000.0, 0.5447424459156194, -658.7939799999959, 392.73890499999624, 1820.5292542500001 - 0.8500000000000001, 18000.0, 0.6225627953321364, 370.07645499999757, 903.3020149999953, 2080.604862 - 0.8500000000000001, 18000.0, 0.7003831447486536, 1514.0949650000405, 1460.1270850000383, 2340.68046975 - 0.8500000000000001, 18000.0, 0.7782034941651707, 3095.6987249998615, 2219.59968000004, 2600.7560775 - 0.8500000000000001, 18000.0, 0.8560238435816877, 5489.965405000091, 3375.713290000069, 2860.83168525 - 0.8500000000000001, 18000.0, 0.9338441929982048, 8311.905815000237, 4850.812890000003, 3120.907293 - 0.8500000000000001, 21000.0, 0.0, 443.80188557335464, 443.80188557335464, 0.0 - 0.8500000000000001, 21000.0, 0.45593119793536807, -2030.5699839999986, -220.87503279999947, 1523.7220635 - 0.8500000000000001, 21000.0, 0.5319197309245961, -963.9674151999925, 255.8271280000035, 1777.6757407500002 - 0.8500000000000001, 21000.0, 0.6079082639138241, 102.63542720000945, 732.5299664000062, 2031.6294180000002 - 0.8500000000000001, 21000.0, 0.683896796903052, 1196.4849752000518, 1222.023383200036, 2285.58309525 - 0.8500000000000001, 21000.0, 0.7598853298922801, 2703.48355919998, 1908.7494064001414, 2539.5367725 - 0.8500000000000001, 21000.0, 0.8358738628815081, 4652.772908800035, 2847.8459679999723, 2793.49044975 - 0.8500000000000001, 21000.0, 0.9118623958707361, 7160.375460799806, 4137.662922399976, 3047.444127 - 0.8500000000000001, 21000.0, 0.9878509288599642, 9868.793802399614, 5685.472187199768, 3301.3978042500003 - 0.8500000000000001, 24000.0, 0.0, 395.17224623209586, 395.17224623209586, 0.0 - 0.8500000000000001, 24000.0, 0.4449392719928187, -2172.624297599993, -307.1800503999991, 1486.987047 - 0.8500000000000001, 24000.0, 0.5190958173249551, -1129.0858607999887, 139.10084800000098, 1734.8182215 - 0.8500000000000001, 24000.0, 0.5932523626570916, -85.54757119995851, 585.381535200008, 1982.649396 - 0.8500000000000001, 24000.0, 0.6674089079892279, 957.9908592000262, 1031.6623543999842, 2230.4805705 - 0.8500000000000001, 24000.0, 0.7415654533213645, 2199.4739431999415, 1595.9512448000323, 2478.311745 - 0.8500000000000001, 24000.0, 0.8157219986535009, 3874.790819200108, 2387.0070688001, 2726.1429195 - 0.8500000000000001, 24000.0, 0.8898785439856374, 6064.753545600091, 3480.3374192000456, 2973.974094 - 0.8500000000000001, 24000.0, 0.9640350893177738, 8458.319502400163, 4809.629764799953, 3221.8052685000002 - 0.8500000000000001, 27000.0, 0.0, 350.8502586805358, 350.8502586805358, 0.0 - 0.8500000000000001, 27000.0, 0.4339483734290844, -1979.789100000006, -346.64932000000044, 1450.255464 - 0.8500000000000001, 27000.0, 0.5062731023339317, -1075.611904800031, 55.24152799999922, 1691.964708 - 0.8500000000000001, 27000.0, 0.5785978312387792, -171.43481200007818, 457.1325168000036, 1933.673952 - 0.8500000000000001, 27000.0, 0.6509225601436266, 732.7423512000179, 859.0235672000003, 2175.383196 - 0.8500000000000001, 27000.0, 0.723247289048474, 1756.2202840000068, 1325.537763199979, 2417.0924400000004 - 0.8500000000000001, 27000.0, 0.7955720179533213, 3233.389629600036, 2003.429225599963, 2658.801684 - 0.8500000000000001, 27000.0, 0.8678967468581688, 5107.153129599948, 2912.376763200078, 2900.510928 - 0.8500000000000001, 27000.0, 0.9402214757630163, 7204.675762400198, 4059.925602400287, 3142.2201720000003 - 0.8500000000000001, 30000.0, 0.0, 310.55137280500526, 310.55137280500526, 0.0 - 0.8500000000000001, 30000.0, 0.42295644748653505, -1029.5774999999921, -235.41889999999853, 1413.5204475 - 0.8500000000000001, 30000.0, 0.4934491887342909, -430.8530999999906, 92.35080000000485, 1649.1071887500002 - 0.8500000000000001, 30000.0, 0.5639419299820467, 167.87220000001005, 420.11980000001483, 1884.6939300000001 - 0.8500000000000001, 30000.0, 0.6344346712298026, 766.5980000001027, 747.8891000000071, 2120.28067125 - 0.8500000000000001, 30000.0, 0.7049274124775584, 1434.0783000000406, 1102.439899999954, 2355.8674125000002 - 0.8500000000000001, 30000.0, 0.7754201537253143, 2647.118899999943, 1664.2917999999909, 2591.4541537500004 - 0.8500000000000001, 30000.0, 0.8459128949730701, 4277.523699999738, 2427.7540000000527, 2827.040895 - 0.8500000000000001, 30000.0, 0.9164056362208259, 6051.799800000066, 3382.778499999846, 3062.6276362500003 - 0.8500000000000001, 30000.0, 0.9868983774685818, 7919.080200000133, 4499.013400000312, 3298.2143775000004 - 0.8500000000000001, 33000.0, 0.0, 273.9984934495011, 273.9984934495011, 0.0 - 0.8500000000000001, 33000.0, 0.4119655489228008, -2004.5891607999945, -492.53271919999975, 1376.7888645000003 - 0.8500000000000001, 33000.0, 0.48062647374326756, -1230.077203999981, -145.31591920000213, 1606.2536752500002 - 0.8500000000000001, 33000.0, 0.5492873985637343, -455.5648207999708, 201.90113919999445, 1835.7184860000002 - 0.8500000000000001, 33000.0, 0.6179483233842012, 318.9473039999698, 549.1179167999743, 2065.1832967500004 - 0.8500000000000001, 33000.0, 0.686609248204668, 1132.3110520000323, 914.3112600000022, 2294.6481075 - 0.8500000000000001, 33000.0, 0.7552701730251348, 2141.3011144000175, 1368.0828264000447, 2524.1129182500003 - 0.8500000000000001, 33000.0, 0.8239310978456016, 3527.2610911999896, 2014.699119199929, 2753.5777290000005 - 0.8500000000000001, 33000.0, 0.8925920226660683, 5086.397962399796, 2807.667837600225, 2983.0425397500003 - 0.8500000000000001, 33000.0, 0.9612529474865351, 6603.00940240035, 3726.8325440000453, 3212.5073505000005 - 0.8500000000000001, 36000.0, 0.0, 240.9313247706801, 240.9313247706801, 0.0 - 0.8500000000000001, 36000.0, 0.4009736229802514, -1990.319599999999, -480.356400000001, 1340.0538480000002 - 0.8500000000000001, 36000.0, 0.46780256014362664, -1303.5685999999923, -180.97950000000668, 1563.3961560000002 - 0.8500000000000001, 36000.0, 0.5346314973070019, -616.8175999999737, 118.39739999998554, 1786.7384640000002 - 0.8500000000000001, 36000.0, 0.6014604344703771, 69.9333999999996, 417.7744000000083, 2010.0807720000003 - 0.8500000000000001, 36000.0, 0.6682893716337523, 756.6846000000004, 717.15120000001, 2233.4230800000005 - 0.8500000000000001, 36000.0, 0.7351183087971276, 1609.4240999999963, 1100.4500999999834, 2456.7653880000003 - 0.8500000000000001, 36000.0, 0.8019472459605028, 2729.0259000000847, 1623.1648999999843, 2680.1076960000005 - 0.8500000000000001, 36000.0, 0.8687761831238779, 4062.8066000001627, 2281.646999999975, 2903.4500040000003 - 0.8500000000000001, 36000.0, 0.9356051202872533, 5356.056599999936, 3038.809800000109, 3126.7923120000005 - 0.8500000000000001, 39000.0, 0.0, 208.66473450701983, 208.66473450701983, 0.0 - 0.8500000000000001, 39000.0, 0.4006469165170557, -2125.716099999996, -543.8444999999965, 1338.9619950000001 - 0.8500000000000001, 39000.0, 0.4674214026032317, -1468.4615000000124, -264.10489999999305, 1562.1223275000002 - 0.8500000000000001, 39000.0, 0.5341958886894076, -811.2070000000255, 15.634600000020747, 1785.2826600000003 - 0.8500000000000001, 39000.0, 0.6009703747755836, -153.9523999999854, 295.3741000000012, 2008.4429925000004 - 0.8500000000000001, 39000.0, 0.6677448608617595, 503.3022000000066, 575.113600000014, 2231.6033250000005 - 0.8500000000000001, 39000.0, 0.7345193469479355, 1234.885399999997, 903.3082999999999, 2454.7636575000006 - 0.8500000000000001, 39000.0, 0.8012938330341114, 2177.3831000000637, 1347.0217000000405, 2677.9239900000002 - 0.8500000000000001, 39000.0, 0.8680683191202874, 3346.727800000066, 1917.0786000000792, 2901.0843225000003 - 0.8500000000000001, 39000.0, 0.9348428052064633, 4473.484400000025, 2564.7319000000352, 3124.2446550000004 - 0.8500000000000001, 42000.0, 0.0, 180.64584855674735, 180.64584855674735, 0.0 - 0.8500000000000001, 42000.0, 0.4006469165170557, -2263.572899999997, -625.9026624999993, 1338.9619950000001 - 0.8500000000000001, 42000.0, 0.4674214026032317, -1632.9250750000117, -358.60762500000374, 1562.1223275000002 - 0.8500000000000001, 42000.0, 0.5341958886894076, -1002.2771250000262, -91.31255625000874, 1785.2826600000003 - 0.8500000000000001, 42000.0, 0.6009703747755836, -371.62938750005037, 175.9825437499955, 2008.4429925000004 - 0.8500000000000001, 42000.0, 0.6677448608617595, 259.01843749998704, 443.27764375000606, 2231.6033250000005 - 0.8500000000000001, 42000.0, 0.7345193469479355, 901.3025562499994, 728.5847062500076, 2454.7636575000006 - 0.8500000000000001, 42000.0, 0.8012938330341114, 1698.1124562500038, 1105.3938000000114, 2677.9239900000002 - 0.8500000000000001, 42000.0, 0.8680683191202874, 2714.2529562500267, 1596.3396374999934, 2901.0843225000003 - 0.8500000000000001, 42000.0, 0.9348428052064633, 3678.5199625000514, 2136.845056250046, 3124.2446550000004 - 0.9, 0.0, 0.0, 975.0792460884875, 975.0792460884875, 0.0 - 0.9, 0.0, 0.5410184380610412, -43097.71300000017, -1919.2165000000068, 1808.0836199999999 - 0.9, 0.0, 0.6311881777378814, -23656.427299999723, 52.01689999957068, 2109.4308899999996 - 0.9, 0.0, 0.7213579174147217, -4215.085599997899, 2023.2788999987815, 2410.77816 - 0.9, 0.0, 0.8115276570915619, 4039.106399997152, 3992.8711000009575, 2712.12543 - 0.9, 0.0, 0.9016973967684021, -15008.394999990429, 4626.620399997793, 3013.4727 - 0.9, 0.0, 0.9918671364452423, -35007.53519998872, 4933.336300001234, 3314.8199699999996 - 0.9, 3000.0, 0.0, 883.0625138951971, 883.0625138951971, 0.0 - 0.9, 3000.0, 0.5298594829443446, 7379.202123126254, 765.3843898694084, 1770.7903919999997 - 0.9, 3000.0, 0.6181693967684021, 3821.475599790627, 1443.199917201217, 2065.9221239999997 - 0.9, 3000.0, 0.7064793105924595, 263.93904513484995, 2121.1219507283768, 2361.0538559999995 - 0.9, 3000.0, 0.7947892244165169, 338.33721106358644, 3122.462714034603, 2656.1855879999994 - 0.9, 3000.0, 0.8830991382405743, 13757.050123414076, 5262.031950166164, 2951.317319999999 - 0.9, 3000.0, 0.9714090520646318, 10154.064186762618, 7292.442988699428, 3246.4490519999995 - 0.9, 6000.0, 0.0, 798.0434264963205, 798.0434264963205, 0.0 - 0.9, 6000.0, 0.5186994847396769, -30345.902399999955, 51.63349999999974, 1733.493678 - 0.9, 6000.0, 0.6051493988629563, -19574.43569999997, 846.2388000000326, 2022.409291 - 0.9, 6000.0, 0.6915993129862358, -8802.832600000746, 1640.8442000000748, 2311.324904 - 0.9, 6000.0, 0.7780492271095153, 160.31250000057844, 2628.670200000392, 2600.240517 - 0.9, 6000.0, 0.8644991412327948, 12963.201800003575, 4836.635199997567, 2889.1561300000003 - 0.9, 6000.0, 0.9509490553560742, 312.3434999914898, 4033.688600003943, 3178.071743 - 0.9, 9000.0, 0.0, 719.6251221381219, 719.6251221381219, 0.0 - 0.9, 9000.0, 0.5075405296229802, -1960.593728571465, 170.7523571428543, 1696.2004499999998 - 0.9, 9000.0, 0.5921306178934769, -681.7229142855833, 861.6450285714388, 1978.9005249999998 - 0.9, 9000.0, 0.6767207061639736, 597.1513142859377, 1552.5384857142335, 2261.6005999999998 - 0.9, 9000.0, 0.7613107944344703, 2264.9286857140532, 2480.963671428456, 2544.3006749999995 - 0.9, 9000.0, 0.845900882704967, 5521.126628572485, 3900.6640857139973, 2827.0007499999997 - 0.9, 9000.0, 0.9304909709754637, 9431.862757143494, 5925.467042857279, 3109.700825 - 0.9, 12000.0, 0.0, 647.4181837534927, 647.4181837534927, 0.0 - 0.9, 12000.0, 0.4963805314183123, -1062.2553442423978, 130.02288585858622, 1658.9037359999998 - 0.9, 12000.0, 0.579110619988031, -1.886726060549023, 754.7012670706948, 1935.3876919999998 - 0.9, 12000.0, 0.6618407085577498, 1058.4828937374864, 1379.380071515072, 2211.871648 - 0.9, 12000.0, 0.7445707971274685, 2047.5740387877322, 2094.170953131217, 2488.355604 - 0.9, 12000.0, 0.8273008856971873, 4187.015877575652, 3244.858557171291, 2764.83956 - 0.9, 12000.0, 0.910030974266906, 7457.427642220891, 5027.055212726513, 3041.323516 - 0.9, 12000.0, 0.9927610628366246, 11669.165264040837, 7199.905628080427, 3317.8074719999995 - 0.9, 15000.0, 0.0, 581.0582199564191, 581.0582199564191, 0.0 - 0.9, 15000.0, 0.4852215763016158, -1383.5334000000228, 24.851399999998264, 1621.610508 - 0.9, 15000.0, 0.5660918390185518, -360.5144000000438, 598.6816499999785, 1891.8789259999999 - 0.9, 15000.0, 0.6469621017354877, 662.5032999998161, 1172.510499999888, 2162.147344 - 0.9, 15000.0, 0.7278323644524237, 1893.1568499998843, 1803.2820000000097, 2432.415762 - 0.9, 15000.0, 0.8087026271693597, 3907.6206499998166, 2794.3663000000224, 2702.68418 - 0.9, 15000.0, 0.8895728898862956, 6454.628500000117, 4255.542800000285, 2972.952598 - 0.9, 15000.0, 0.9704431526032316, 10048.04175000023, 6200.193249999521, 3243.221016 - 0.9, 18000.0, 0.0, 520.19090795261, 520.19090795261, 0.0 - 0.9, 18000.0, 0.4740615780969478, -1786.4760800000033, -88.2784733333358, 1584.3137939999997 - 0.9, 18000.0, 0.5530718411131058, -724.6719266666552, 445.2796599999942, 1848.3660929999996 - 0.9, 18000.0, 0.6320821041292638, 337.13286000000505, 978.8373133333287, 2112.4183919999996 - 0.9, 18000.0, 0.7110923671454218, 1524.7078466667488, 1558.4659533334238, 2376.4706909999995 - 0.9, 18000.0, 0.7901026301615798, 3000.020899999749, 2320.7601600000553, 2640.5229899999995 - 0.9, 18000.0, 0.8691128931777377, 5830.9932600001675, 3705.0837466668113, 2904.5752889999994 - 0.9, 18000.0, 0.9481231561938956, 8486.446980000375, 5155.982346666653, 3168.6275879999994 - 0.9, 21000.0, 0.0, 464.47263943053196, 464.47263943053196, 0.0 - 0.9, 21000.0, 0.46290262298025125, -2413.9707239999975, -191.58074079999918, 1547.0205659999997 - 0.9, 21000.0, 0.5400530601436265, -1249.2608671999858, 292.563488000007, 1804.8573269999997 - 0.9, 21000.0, 0.6172034973070017, -84.54980079998339, 776.7098904000111, 2062.6940879999997 - 0.9, 21000.0, 0.694353934470377, 1152.8188072000742, 1294.964615200052, 2320.5308489999998 - 0.9, 21000.0, 0.7715043716337522, 2898.081851199932, 2072.7193704002534, 2578.36761 - 0.9, 21000.0, 0.8486548087971274, 4902.840496800075, 3073.1607079999576, 2836.204371 - 0.9, 21000.0, 0.9258052459605025, 7427.583428799606, 4466.756526399922, 3094.0411319999994 - 0.9, 24000.0, 0.0, 413.57800001229543, 413.57800001229543, 0.0 - 0.9, 24000.0, 0.4517426247755834, -3380.3770015999858, -356.4080263999983, 1509.7238519999999 - 0.9, 24000.0, 0.5270330622381807, -1944.2315927999834, 130.35004800000118, 1761.344494 - 0.9, 24000.0, 0.6023234997007779, -508.08697919993085, 617.1068232000135, 2012.9651359999998 - 0.9, 24000.0, 0.6776139371633751, 928.0581272000454, 1103.8650703999788, 2264.5857779999997 - 0.9, 24000.0, 0.7529043746259724, 2298.10427119991, 1709.643436800076, 2516.2064199999995 - 0.9, 24000.0, 0.8281948120885697, 4098.066687200226, 2588.2789408002095, 2767.827062 - 0.9, 24000.0, 0.9034852495511668, 6273.94600960022, 3752.7204072001286, 3019.4477039999997 - 0.9, 24000.0, 0.978775687013764, 8743.34017840045, 5132.795476799943, 3271.0683459999996 - 0.9, 27000.0, 0.0, 367.19164787617416, 367.19164787617416, 0.0 - 0.9, 27000.0, 0.4405836696588869, -2469.0438600000098, -390.76398000000063, 1472.430624 - 0.9, 27000.0, 0.5140142812687014, -1423.591516800057, 44.119907999998674, 1717.835728 - 0.9, 27000.0, 0.5874448928785159, -378.1391120001402, 479.00428880000646, 1963.240832 - 0.9, 27000.0, 0.6608755044883303, 667.3140992000291, 913.8893352000094, 2208.645936 - 0.9, 27000.0, 0.7343061160981448, 1847.1878240000085, 1439.5940311999611, 2454.05104 - 0.9, 27000.0, 0.8077367277079592, 3456.315953600096, 2182.7071695999566, 2699.4561439999998 - 0.9, 27000.0, 0.8811673393177738, 5334.240733600002, 3140.6402112001924, 2944.861248 - 0.9, 27000.0, 0.9545979509275883, 7568.678658400436, 4445.009118400557, 3190.266352 - 0.9, 30000.0, 0.0, 325.0157795502978, 325.0157795502978, 0.0 - 0.9, 30000.0, 0.42942367145421895, 1681.152200000004, 303.5219000000011, 1435.1339099999998 - 0.9, 30000.0, 0.5009942833632555, 1614.546000000012, 515.5695000000067, 1674.3228949999998 - 0.9, 30000.0, 0.5725648952722919, 1547.9432000000197, 727.6142000000225, 1913.5118799999998 - 0.9, 30000.0, 0.6441355071813285, 1481.341500000173, 939.6603000000168, 2152.700865 - 0.9, 30000.0, 0.715706119090365, 1489.4339000000646, 1168.3894999999263, 2391.8898499999996 - 0.9, 30000.0, 0.7872767309994015, 2776.802199999951, 1795.7976999999923, 2631.078835 - 0.9, 30000.0, 0.8588473429084379, 4453.393999999567, 2598.1665000000708, 2870.2678199999996 - 0.9, 30000.0, 0.9304179548174745, 6232.736300000024, 3648.901299999773, 3109.456805 - 0.9, 33000.0, 0.0, 286.7603937465558, 286.7603937465558, 0.0 - 0.9, 33000.0, 0.41826471633752244, -1438.5117567999932, -498.65712319999983, 1397.840682 - 0.9, 33000.0, 0.48797550239377613, -780.1591639999696, -129.6842232000039, 1630.8141289999999 - 0.9, 33000.0, 0.5576862884500299, -121.80525679995309, 239.28958319998964, 1863.787576 - 0.9, 33000.0, 0.6273970745062837, 536.5477439999379, 608.262292799954, 2096.761023 - 0.9, 33000.0, 0.6971078605625374, 1317.005752000066, 1033.7325799999935, 2329.73447 - 0.9, 33000.0, 0.7668186466187911, 2285.1789424000153, 1487.0621944000677, 2562.7079169999997 - 0.9, 33000.0, 0.8365294326750449, 3726.1488351999583, 2211.4953831998587, 2795.681364 - 0.9, 33000.0, 0.9062402187312986, 5415.78917039959, 3069.661709600374, 3028.654811 - 0.9, 33000.0, 0.9759510047875523, 6924.213230400632, 4021.3689040000822, 3261.6282579999997 - 0.9, 36000.0, 0.0, 252.15307094326414, 252.15307094326414, 0.0 - 0.9, 36000.0, 0.40710471813285454, -1593.1188999999995, -365.1980000000017, 1360.543968 - 0.9, 36000.0, 0.47495550448833035, -983.3861999999942, -76.38220000001319, 1587.301296 - 0.9, 36000.0, 0.5428062908438062, -373.6522999999742, 212.43419999997226, 1814.058624 - 0.9, 36000.0, 0.6106570771992819, 236.07989999997807, 501.25000000001575, 2040.815952 - 0.9, 36000.0, 0.6785078635547577, 845.8141000000041, 790.0658000000207, 2267.57328 - 0.9, 36000.0, 0.7463586499102335, 1663.118400000005, 1196.5614999999877, 2494.330608 - 0.9, 36000.0, 0.8142094362657091, 2917.3133000001694, 1741.874699999983, 2721.087936 - 0.9, 36000.0, 0.8820602226211849, 4224.531900000347, 2455.3754999999805, 2947.845264 - 0.9, 36000.0, 0.9499110089766607, 5620.762499999893, 3309.852300000278, 3174.602592 - 0.9, 39000.0, 0.0, 218.38361472334765, 218.38361472334765, 0.0 - 0.9, 39000.0, 0.4067730161579892, -1720.4843999999916, -451.08759999999364, 1359.43542 - 0.9, 39000.0, 0.47456851885098744, -1147.1540000000284, -180.85779999998888, 1586.00799 - 0.9, 39000.0, 0.5423640215439857, -573.823100000053, 89.37320000003467, 1812.58056 - 0.9, 39000.0, 0.6101595242369839, -0.4922999999927779, 359.60360000000304, 2039.1531300000001 - 0.9, 39000.0, 0.677955026929982, 572.8385000000095, 629.8336000000298, 2265.7257 - 0.9, 39000.0, 0.7457505296229803, 1304.3049000000003, 987.5776000000088, 2492.2982700000002 - 0.9, 39000.0, 0.8135460323159784, 2300.08480000012, 1448.1752000000852, 2718.87084 - 0.9, 39000.0, 0.8813415350089767, 3485.5072000001546, 2070.0880000001534, 2945.4434100000003 - 0.9, 39000.0, 0.9491370377019749, 4642.574100000079, 2769.2436000000844, 3172.01598 - 0.9, 42000.0, 0.0, 189.05970616353355, 189.05970616353355, 0.0 - 0.9, 42000.0, 0.4067730161579892, -2081.7765999999956, -554.0094374999989, 1359.43542 - 0.9, 42000.0, 0.47456851885098744, -1479.960000000024, -291.8265750000066, 1586.00799 - 0.9, 42000.0, 0.5423640215439857, -878.1437500000504, -29.64401875001523, 1812.58056 - 0.9, 42000.0, 0.6101595242369839, -276.3273125000989, 232.53875624999074, 2039.1531300000001 - 0.9, 42000.0, 0.677955026929982, 325.48893749997995, 494.72118125001214, 2265.7257 - 0.9, 42000.0, 0.7457505296229803, 960.1070437500007, 797.0973687500137, 2492.2982700000002 - 0.9, 42000.0, 0.8135460323159784, 1816.0550687500097, 1199.02065000002, 2718.87084 - 0.9, 42000.0, 0.8813415350089767, 2849.730018750023, 1733.8661124999928, 2945.4434100000003 - 0.9, 42000.0, 0.9491370377019749, 3854.696287500119, 2333.1897937501267, 3172.01598 diff --git a/aviary/models/engines/turbofan_23k_1_lbm_s.deck b/aviary/models/engines/turbofan_23k_1_lbm_s.deck deleted file mode 100644 index 90836e18ef..0000000000 --- a/aviary/models/engines/turbofan_23k_1_lbm_s.deck +++ /dev/null @@ -1,2808 +0,0 @@ -# GASP-derived engine deck converted from GASP_turbofan_23k_1.eng -# t4max: 3342.0 -# t4cruise: 3108.0 -# t4climb: 3196.0 -# sls_airflow: 994.36 -# sfn_idle: 1.25 - -Mach_Number (unitless), Altitude (ft), Throttle (unitless), Thrust (lbf), Fuel_Flow (lbm/s), T4 (degR) -0, 0, 0, 621.4719458, 0.172631096, 0 -0, 0, 0.46559246, -1979.1619, -0.029235861, 1556.01 -0, 0, 0.543191203, 1065.3235, 0.149875778, 1815.345 -0, 0, 0.620789946, 4109.8086, 0.328987389, 2074.68 -0, 0, 0.698388689, 7327.1812, 0.519627389, 2334.015 -0, 0, 0.775987433, 11036.916, 0.777837333, 2593.35 -0, 0, 0.853586176, 15708.8779, 1.1377265, 2852.685 -0, 0, 0.931184919, 21836.4629, 1.630629611, 3112.02 -0, 3000, 0, 562.8245919, 0.156340164, 0 -0, 3000, 0.455989228, -2285.519, -0.050973917, 1523.916 -0, 3000, 0.531987433, 456.4109, 0.114516972, 1777.902 -0, 3000, 0.607985637, 3198.3413, 0.280007861, 2031.888 -0, 3000, 0.683983842, 5972.4834, 0.450275361, 2285.874 -0, 3000, 0.759982047, 9207.8262, 0.677220528, 2539.86 -0, 3000, 0.835980251, 13217.7979, 0.987073778, 2793.846 -0, 3000, 0.911978456, 18617.6777, 1.420672056, 3047.832 -0, 3000, 0.987976661, 25284.2129, 1.967535278, 3301.818 -0, 6000, 0, 508.6372242, 0.141288118, 0 -0, 6000, 0.446385099, -2935.8345, -0.077866667, 1491.819 -0, 6000, 0.520782615, -197.4633, 0.076427389, 1740.4555 -0, 6000, 0.595180132, 2540.9077, 0.230721444, 1989.092 -0, 6000, 0.669577648, 5279.2793, 0.3850155, 2237.7285 -0, 6000, 0.743975165, 8213.5254, 0.580804639, 2486.365 -0, 6000, 0.818372681, 11851.3818, 0.850575083, 2735.0015 -0, 6000, 0.892770197, 16560.2891, 1.216286889, 2983.638 -0, 6000, 0.967167714, 22654.5547, 1.700064028, 3232.2745 -0, 9000, 0, 458.6569007, 0.127404695, 0 -0, 9000, 0.436781867, 820.9403, -0.055143278, 1459.725 -0, 9000, 0.509578845, 2287.7754, 0.075966194, 1703.0125 -0, 9000, 0.582375823, 3754.6024, 0.207076222, 1946.3 -0, 9000, 0.655172801, 5221.4323, 0.338186417, 2189.5875 -0, 9000, 0.727969779, 6857.634, 0.490957111, 2432.875 -0, 9000, 0.800766756, 10501.9531, 0.727329389, 2676.1625 -0, 9000, 0.873563734, 14702.6974, 1.05040425, 2919.45 -0, 9000, 0.946360712, 19922.6084, 1.464529028, 3162.7375 -0, 12000, 0, 412.6354243, 0.114620951, 0 -0, 12000, 0.427177738, -10008.41005, -0.174200895, 1427.628 -0, 12000, 0.498374028, -5628.271186, -0.02454571, 1665.566 -0, 12000, 0.569570317, -1248.107982, 0.12511178, 1903.504 -0, 12000, 0.640766607, 3132.043462, 0.274770029, 2141.442 -0, 12000, 0.711962896, 7439.101974, 0.460160126, 2379.38 -0, 12000, 0.783159186, 10835.88466, 0.659955715, 2617.318 -0, 12000, 0.854355476, 10534.27343, 0.809770605, 2855.256 -0, 12000, 0.925551765, 17296.45743, 1.249795438, 3093.194 -0, 12000, 0.996748055, 22936.55361, 1.711985172, 3331.132 -0, 15000, 0, 370.3405483, 0.102872375, 0 -0, 15000, 0.417574506, -4108.3274, -0.264928444, 1395.534 -0, 15000, 0.487170257, -2085.1374, -0.117573778, 1628.123 -0, 15000, 0.556766008, -61.8775, 0.029786139, 1860.712 -0, 15000, 0.626361759, 1961.3579, 0.177140806, 2093.301 -0, 15000, 0.69595751, 3868.8368, 0.223666056, 2325.89 -0, 15000, 0.765553262, 9295.3933, 0.574909222, 2558.479 -0, 15000, 0.835149013, 8117.5552, 0.653756222, 2791.068 -0, 15000, 0.904744764, 22532.6741, 1.479135028, 3023.657 -0, 15000, 0.974340515, -366.1336, 0.691613722, 3256.246 -0, 18000, 0, 331.5464431, 0.092096234, 0 -0, 18000, 0.407970377, -18660.52886, -0.936538838, 1363.437 -0, 18000, 0.47596544, -12470.87884, -0.609555573, 1590.6765 -0, 18000, 0.543960503, -6281.173878, -0.282590056, 1817.916 -0, 18000, 0.611955566, -91.4635384, 0.044379024, 2045.1555 -0, 18000, 0.679950628, 1838.841939, 0.220698952, 2272.395 -0, 18000, 0.747945691, 3461.407017, 0.266376357, 2499.6345 -0, 18000, 0.815940754, 8465.954334, 0.44305616, 2726.874 -0, 18000, 0.883935817, 4672.626438, 0.468084541, 2954.1135 -0, 18000, 0.95193088, 30679.13577, 1.567937685, 3181.353 -0, 21000, 0, 296.0341082, 0.082231697, 0 -0, 21000, 0.398367145, 5188.336938, 0.96904285, 1331.343 -0, 21000, 0.46476167, 4883.054693, 0.763061554, 1553.2335 -0, 21000, 0.531156194, 4577.828439, 0.55708382, 1775.124 -0, 21000, 0.597550718, 4272.564631, 0.351093075, 1997.0145 -0, 21000, 0.663945242, 4056.199361, 0.25233152, 2218.905 -0, 21000, 0.730339767, 1.572036802, 0.180431186, 2440.7955 -0, 21000, 0.796734291, 5555.628807, 0.371637703, 2662.686 -0, 21000, 0.863128815, 10865.94013, 1.057405471, 2884.5765 -0, 21000, 0.929523339, 13527.60249, 1.504241323, 3106.467 -0, 21000, 0.995917864, 24247.30981, 3.066060528, 3328.3575 -0, 24000, 0, 263.5961389, 0.07322115, 0 -0, 24000, 0.388763016, -2276.284299, -1.179476247, 1299.246 -0, 24000, 0.453556852, -1397.985689, -0.841895532, 1515.787 -0, 24000, 0.518350688, -519.6311048, -0.504319128, 1732.328 -0, 24000, 0.583144524, 358.6362592, -0.166744168, 1948.869 -0, 24000, 0.64793836, 3549.537827, 0.28560738, 2165.41 -0, 24000, 0.712732196, 7246.497172, 0.638390756, 2381.951 -0, 24000, 0.777526032, 8081.881798, 0.672037916, 2598.492 -0, 24000, 0.842319868, 10914.13266, 0.597622227, 2815.033 -0, 24000, 0.907113704, 8142.089101, 0.608235781, 3031.574 -0, 24000, 0.97190754, 9356.254232, 0.929551756, 3248.115 -0, 27000, 0, 234.0315506, 0.065008764, 0 -0, 27000, 0.379159785, 31666.47126, 4.318328288, 1267.152 -0, 27000, 0.442353082, 22716.7496, 3.231589946, 1478.344 -0, 27000, 0.505546379, 13766.90594, 2.144829276, 1689.536 -0, 27000, 0.568739677, 4817.089457, 1.058068605, 1900.728 -0, 27000, 0.631932974, -4080.899666, -0.117159137, 2111.92 -0, 27000, 0.695126272, 3533.178786, 0.043613039, 2323.112 -0, 27000, 0.758319569, 2905.361299, 0.023415577, 2534.304 -0, 27000, 0.821512867, -631.55984, 0.570799226, 2745.496 -0, 27000, 0.884706164, 10808.44285, 0.704954723, 2956.688 -0, 27000, 0.947899461, -1558.28779, 0.968961556, 3167.88 -0, 30000, 0, 207.1505365, 0.057541816, 0 -0, 30000, 0.369555655, 423.6084, 0.573184222, 1235.055 -0, 30000, 0.431148265, 2344.4844, 0.532100389, 1440.8975 -0, 30000, 0.492740874, 4264.6648, 0.491077972, 1646.74 -0, 30000, 0.554333483, 6185.2028, 0.450019778, 1852.5825 -0, 30000, 0.615926092, 4867.5137, 0.048528306, 2058.425 -0, 30000, 0.677518701, -1357.8646, 0.086781944, 2264.2675 -0, 30000, 0.739111311, 916.2129, -0.167108361, 2470.11 -0, 30000, 0.80070392, 2808.1614, -0.574687806, 2675.9525 -0, 30000, 0.862296529, 14043.9318, 1.827668028, 2881.795 -0, 30000, 0.923889138, 29400.5486, 1.212759611, 3087.6375 -0, 30000, 0.985481747, 60041.2115, 3.394925111, 3293.48 -0, 33000, 0, 182.7682628, 0.050768962, 0 -0, 33000, 0.359952424, 73148.21513, 2.320367815, 1202.961 -0, 33000, 0.419944494, 57096.46574, 1.766968391, 1403.4545 -0, 33000, 0.479936565, 41044.58415, 1.213566586, 1603.948 -0, 33000, 0.539928636, 24992.66943, 0.6601968, 1804.4415 -0, 33000, 0.599920706, 8940.679883, 0.106765357, 2004.935 -0, 33000, 0.659912777, -2678.41669, -0.166237335, 2205.4285 -0, 33000, 0.719904847, 11541.77753, 1.254046809, 2405.922 -0, 33000, 0.779896918, 10052.41121, 1.004775833, 2606.4155 -0, 33000, 0.839888989, -5615.760698, -1.126842587, 2806.909 -0, 33000, 0.899881059, 3125.79125, 0.495808662, 3007.4025 -0, 33000, 0.95987313, -53986.2557, -9.68680961, 3207.896 -0, 36000, 0, 160.7111015, 0.044641973, 0 -0, 36000, 0.350348294, 69414.8206, 1.735892444, 1170.864 -0, 36000, 0.408739677, 54979.2465, 1.419962667, 1366.008 -0, 36000, 0.467131059, 40543.3215, 1.104032889, 1561.152 -0, 36000, 0.525522442, 26107.6759, 0.788113222, 1756.296 -0, 36000, 0.583913824, 11671.9043, 0.472150972, 1951.44 -0, 36000, 0.642305206, 1488.7455, 0.141399889, 2146.584 -0, 36000, 0.700696589, 908.5232, 0.025981111, 2341.728 -0, 36000, 0.759087971, -22077.3786, -0.850191917, 2536.872 -0, 36000, 0.817479354, 47160.9737, 2.989732222, 2732.016 -0, 36000, 0.875870736, 16056.5117, 1.533346139, 2927.16 -0, 36000, 0.934262118, -24769.2238, -6.588022556, 3122.304 -0, 39000, 0, 139.1879588, 0.038663322, 0 -0, 39000, 0.350062837, 476.7687, 0.027910111, 1169.91 -0, 39000, 0.408406643, -266.4172, -0.006501111, 1364.895 -0, 39000, 0.466750449, -1009.8918, -0.040909806, 1559.88 -0, 39000, 0.525094255, -1753.1675, -0.075296139, 1754.865 -0, 39000, 0.583438061, -2496.6147, -0.109694722, 1949.85 -0, 39000, 0.641781867, -4195.4422, -0.199702333, 2144.835 -0, 39000, 0.700125673, -200.1008, -0.002938361, 2339.82 -0, 39000, 0.758469479, -4917.3097, -0.556912, 2534.805 -0, 39000, 0.816813285, 6913.4595, -1.203130167, 2729.79 -0, 39000, 0.875157092, 11889.8893, 1.207896556, 2924.775 -0, 39000, 0.933500898, 120355.9311, 19.07739031, 3119.76 -0, 42000, 0, 120.4982097, 0.033471725, 0 -0, 42000, 0.350062837, -462426.4545, -49.45209317, 1169.91 -0, 42000, 0.408406643, -362855.99, -38.7171998, 1364.895 -0, 42000, 0.466750449, -263285.614, -27.98229278, 1559.88 -0, 42000, 0.525094255, -163715.3712, -17.24736859, 1754.865 -0, 42000, 0.583438061, -64145.00642, -6.512506432, 1949.85 -0, 42000, 0.641781867, -17490.57143, -1.643451833, 2144.835 -0, 42000, 0.700125673, 9317.000762, 0.261670273, 2339.82 -0, 42000, 0.758469479, -11674.66693, -0.060855222, 2534.805 -0, 42000, 0.816813285, 25036.39049, 3.855114378, 2729.79 -0, 42000, 0.875157092, -11573.78817, -1.397588375, 2924.775 -0, 42000, 0.933500898, 18711.33021, 4.040373951, 3119.76 -0.05, 0, 0, 622.4046199, 0.172890172, 0 -0.05, 0, 0.465825256, -1937.3721, -0.028923667, 1556.788005 -0.05, 0, 0.543462798, 906.8547, 0.151430111, 1816.252672 -0.05, 0, 0.621100341, 3751.0815, 0.331783889, 2075.71734 -0.05, 0, 0.698737884, 6786.7256, 0.523964139, 2335.182007 -0.05, 0, 0.776375426, 10343.1055, 0.784757417, 2594.646675 -0.05, 0, 0.854012969, 14849.0918, 1.148035083, 2854.111342 -0.05, 0, 0.931650512, 20803.9844, 1.646088861, 3113.57601 -0.05, 3000, 0, 563.669251, 0.156574792, 0 -0.05, 3000, 0.456217223, -2248.270465, -0.049977224, 1524.677958 -0.05, 3000, 0.532253426, 396.6363202, 0.115699428, 1778.790951 -0.05, 3000, 0.60828963, 3041.543114, 0.281376135, 2032.903944 -0.05, 3000, 0.684325834, 5721.066797, 0.451979596, 2287.016937 -0.05, 3000, 0.760362038, 8885.487061, 0.679757692, 2541.12993 -0.05, 3000, 0.836398241, 12820.92242, 0.990499047, 2795.242923 -0.05, 3000, 0.912434445, 18151.57478, 1.426276101, 3049.355916 -0.05, 3000, 0.988470649, 24712.70234, 1.974092598, 3303.468909 -0.05, 6000, 0, 509.4005616, 0.141500156, 0 -0.05, 6000, 0.446608291, -2750.051225, -0.075458514, 1492.564909 -0.05, 6000, 0.521043007, -204.449625, 0.078846118, 1741.325728 -0.05, 6000, 0.595477722, 2341.1522, 0.233150819, 1990.086546 -0.05, 6000, 0.669912437, 4887.933125, 0.387631535, 2238.847364 -0.05, 6000, 0.744347152, 7675.513675, 0.584372604, 2487.608183 -0.05, 6000, 0.818781867, 11181.15845, 0.855712007, 2736.369001 -0.05, 6000, 0.893216583, 15767.3707, 1.225344403, 2985.129819 -0.05, 6000, 0.967651298, 21640.41693, 1.710602938, 3233.890637 -0.05, 9000, 0, 459.3452301, 0.127595897, 0 -0.05, 9000, 0.437000258, -1627.5458, -0.078198667, 1460.454862 -0.05, 9000, 0.509833634, 358.4682, 0.059373111, 1703.864006 -0.05, 9000, 0.582667011, 2344.4799, 0.196945056, 1947.27315 -0.05, 9000, 0.655500387, 4330.4923, 0.334517083, 2190.682294 -0.05, 9000, 0.728333763, 6540.9913, 0.499145444, 2434.091437 -0.05, 9000, 0.80116714, 9705.0825, 0.732873611, 2677.500581 -0.05, 9000, 0.874000516, 13670.4519, 1.051179861, 2920.909725 -0.05, 9000, 0.946833893, 18768.7835, 1.467859361, 3164.318869 -0.05, 12000, 0, 413.2546869, 0.114792969, 0 -0.05, 12000, 0.427391327, -5981.428852, -0.126158187, 1428.341814 -0.05, 12000, 0.498623215, -2971.169758, 0.008816396, 1666.398783 -0.05, 12000, 0.569855102, 39.1016464, 0.143792137, 1904.455752 -0.05, 12000, 0.64108699, 3049.36707, 0.27876828, 2142.512721 -0.05, 12000, 0.712318878, 6215.422946, 0.442648857, 2380.56969 -0.05, 12000, 0.783550766, 9242.336699, 0.643343411, 2618.626659 -0.05, 12000, 0.854782654, 10783.70646, 0.85600048, 2856.683628 -0.05, 12000, 0.926014541, 16227.53956, 1.249273352, 3094.740597 -0.05, 12000, 0.997246429, 21278.34475, 1.685512463, 3332.797566 -0.05, 15000, 0, 370.8963369, 0.10302676, 0 -0.05, 15000, 0.417783294, -3422.1305, -0.204587417, 1396.231767 -0.05, 15000, 0.487413842, -1572.3614, -0.069338556, 1628.937061 -0.05, 15000, 0.557044391, 277.4521, 0.065913639, 1861.642356 -0.05, 15000, 0.62667494, 2127.2501, 0.2011625, 2094.347651 -0.05, 15000, 0.696305489, 3919.8747, 0.275885278, 2327.052945 -0.05, 15000, 0.765936038, 8107.0499, 0.557392694, 2559.75824 -0.05, 15000, 0.835566587, 8295.7752, 0.691525028, 2792.463534 -0.05, 15000, 0.905197136, 18916.6229, 1.334320361, 3025.168828 -0.05, 15000, 0.974827685, 5936.3338, 0.983195694, 3257.874123 -0.05, 18000, 0, 332.0440114, 0.092234448, 0 -0.05, 18000, 0.408174362, -13675.57478, -0.687273034, 1364.118718 -0.05, 18000, 0.476203423, -8945.338914, -0.42716181, 1591.471838 -0.05, 18000, 0.544232483, -4215.065122, -0.167062786, 1818.824958 -0.05, 18000, 0.612261543, 515.2119176, 0.093038753, 2046.178078 -0.05, 18000, 0.680290604, 2286.805031, 0.248313842, 2273.531198 -0.05, 18000, 0.748319664, 3918.885705, 0.326117073, 2500.884317 -0.05, 18000, 0.816348724, 7981.962458, 0.500938243, 2728.237437 -0.05, 18000, 0.884377785, 6270.013742, 0.596986736, 2955.590557 -0.05, 18000, 0.952406845, 25369.33325, 1.457710045, 3182.943677 -0.05, 21000, 0, 296.4783814, 0.082355106, 0 -0.05, 21000, 0.398566329, 2763.042974, 0.644319402, 1332.008672 -0.05, 21000, 0.46499405, 2979.908061, 0.528213208, 1554.010117 -0.05, 21000, 0.531421772, 3196.813131, 0.412109529, 1776.011562 -0.05, 21000, 0.597849493, 3413.691863, 0.295996465, 1998.013007 -0.05, 21000, 0.664277215, 3661.646689, 0.253377478, 2220.014453 -0.05, 21000, 0.730704936, 1190.716445, 0.237644021, 2442.015898 -0.05, 21000, 0.797132658, 5622.828899, 0.417799887, 2664.017343 -0.05, 21000, 0.863560379, 10217.83286, 0.973716301, 2886.018788 -0.05, 21000, 0.929988101, 12690.25567, 1.352689473, 3108.020234 -0.05, 21000, 0.996415822, 20717.66927, 2.519480327, 3330.021679 -0.05, 24000, 0, 263.9917309, 0.073331036, 0 -0.05, 24000, 0.388957398, -2747.962127, -0.926297291, 1299.895623 -0.05, 24000, 0.453783631, -1687.356541, -0.648654749, 1516.544893 -0.05, 24000, 0.518609864, -626.7097768, -0.371015322, 1733.194164 -0.05, 24000, 0.583436096, 433.8731872, -0.093377064, 1949.843434 -0.05, 24000, 0.648262329, 3143.998015, 0.264679817, 2166.492705 -0.05, 24000, 0.713088562, 6284.657012, 0.556828488, 2383.141975 -0.05, 24000, 0.777914795, 7322.359334, 0.617757497, 2599.791246 -0.05, 24000, 0.842741028, 9905.923789, 0.607804399, 2816.440517 -0.05, 24000, 0.907567261, 8487.754813, 0.675072564, 3033.089787 -0.05, 24000, 0.972393494, 10105.10393, 0.996106613, 3249.739057 -0.05, 27000, 0, 234.3827734, 0.065106326, 0 -0.05, 27000, 0.379349364, 22931.44713, 3.20357251, 1267.785576 -0.05, 27000, 0.442574259, 16521.5301, 2.408267316, 1479.083172 -0.05, 27000, 0.505799153, 10111.52066, 1.612945076, 1690.380768 -0.05, 27000, 0.569024047, 3701.532029, 0.817622835, 1901.678364 -0.05, 27000, 0.632248941, -2626.56235, -0.039254398, 2112.97596 -0.05, 27000, 0.695473835, 3350.710402, 0.098939219, 2324.273556 -0.05, 27000, 0.758698729, 3285.400167, 0.118702516, 2535.571152 -0.05, 27000, 0.821923623, 1028.76078, 0.568306374, 2746.868748 -0.05, 27000, 0.885148517, 10204.39296, 0.71599459, 2958.166344 -0.05, 27000, 0.948373411, 1146.704654, 0.951262498, 3169.46394 -0.05, 30000, 0, 207.4614177, 0.057628172, 0 -0.05, 30000, 0.369740433, -109.3373, 0.410625139, 1235.672528 -0.05, 30000, 0.431363839, 1570.1975, 0.395751722, 1441.617949 -0.05, 30000, 0.492987244, 3249.1904, 0.380925944, 1647.56337 -0.05, 30000, 0.55461065, 4928.4614, 0.366072361, 1853.508791 -0.05, 30000, 0.616234055, 4116.7891, 0.073962861, 2059.454213 -0.05, 30000, 0.677857461, -612.2555, 0.113036278, 2265.399634 -0.05, 30000, 0.739480866, 1491.7725, -0.057260611, 2471.345055 -0.05, 30000, 0.801104272, 3295.7066, -0.341998194, 2677.290476 -0.05, 30000, 0.862727677, 12370.1506, 1.559287556, 2883.235897 -0.05, 30000, 0.924351083, 24896.8688, 1.158067611, 3089.181319 -0.05, 30000, 0.985974488, 49261.1994, 2.943964944, 3295.12674 -0.05, 33000, 0, 183.0425523, 0.050845153, 0 -0.05, 33000, 0.3601324, 57217.34382, 1.795020012, 1203.562481 -0.05, 33000, 0.420154467, 44718.89758, 1.372876976, 1404.156227 -0.05, 33000, 0.480176533, 32220.346, 0.950731911, 1604.749974 -0.05, 33000, 0.5401986, 19721.7686, 0.528612101, 1805.343721 -0.05, 33000, 0.600220667, 7223.132247, 0.10644381, 2005.937468 -0.05, 33000, 0.660242733, -1714.224942, -0.088401086, 2206.531214 -0.05, 33000, 0.7202648, 9696.970218, 1.046132402, 2407.124961 -0.05, 33000, 0.780286866, 8800.633575, 0.870946017, 2607.718708 -0.05, 33000, 0.840308933, -3143.182866, -0.764441629, 2808.312455 -0.05, 33000, 0.900331, 3650.193898, 0.486097978, 3008.906201 -0.05, 33000, 0.960353066, -41981.76681, -7.651866284, 3209.499948 -0.05, 36000, 0, 160.9522887, 0.044708969, 0 -0.05, 36000, 0.350523469, 54083.2797, 1.331329056, 1171.449432 -0.05, 36000, 0.408944047, 42879.2093, 1.095137833, 1366.691004 -0.05, 36000, 0.467364625, 31674.8618, 0.858946611, 1561.932576 -0.05, 36000, 0.525785203, 20470.7354, 0.622763333, 1757.174148 -0.05, 36000, 0.584205781, 9266.5089, 0.386546472, 1952.41572 -0.05, 36000, 0.642626359, 1420.9882, 0.138580389, 2147.657292 -0.05, 36000, 0.701046937, 1098.6751, 0.059565444, 2342.898864 -0.05, 36000, 0.759467515, -16849.8408, -0.61207525, 2538.140436 -0.05, 36000, 0.817888093, 38222.7916, 2.441749139, 2733.382008 -0.05, 36000, 0.876308671, 13946.346, 1.349912583, 2928.62358 -0.05, 36000, 0.93472925, -18581.3635, -5.095956806, 3123.865152 -0.05, 39000, 0, 139.3968452, 0.038721346, 0 -0.05, 39000, 0.350237868, 297.7573, 0.00511525, 1170.494955 -0.05, 39000, 0.408610846, -246.1483, -0.014295556, 1365.577448 -0.05, 39000, 0.466983824, -790.2804, -0.033704194, 1560.65994 -0.05, 39000, 0.525356802, -1334.2551, -0.053095139, 1755.742433 -0.05, 39000, 0.58372978, -1878.3663, -0.072495833, 1950.824925 -0.05, 39000, 0.642102758, -3177.828, -0.139785139, 2145.907418 -0.05, 39000, 0.700475736, 147.0694, 0.028917972, 2340.98991 -0.05, 39000, 0.758848714, -3416.9648, -0.389637306, 2536.072403 -0.05, 39000, 0.817221692, 6216.8593, -0.888981056, 2731.154895 -0.05, 39000, 0.87559467, 10314.0473, 1.047447083, 2926.237388 -0.05, 39000, 0.933967648, 95822.4296, 15.15167917, 3121.31988 -0.05, 42000, 0, 120.6790474, 0.033521958, 0 -0.05, 42000, 0.350237868, -379307.7606, -40.5452438, 1170.494955 -0.05, 42000, 0.408610846, -297621.6838, -31.7428099, 1365.577448 -0.05, 42000, 0.466983824, -215935.6775, -22.94036504, 1560.65994 -0.05, 42000, 0.525356802, -134249.7806, -14.13790614, 1755.742433 -0.05, 42000, 0.58372978, -52563.78405, -5.335497609, 1950.824925 -0.05, 42000, 0.642102758, -14077.32979, -1.317732313, 2145.907418 -0.05, 42000, 0.700475736, 7763.255212, 0.24149679, 2340.98991 -0.05, 42000, 0.758848714, -9094.635569, -0.015550347, 2536.072403 -0.05, 42000, 0.817221692, 20796.75561, 3.175126219, 2731.154895 -0.05, 42000, 0.87559467, -8526.098525, -1.03783334, 2926.237388 -0.05, 42000, 0.933967648, 16729.97512, 3.481608556, 3121.31988 -0.1, 0, 0, 625.2082401, 0.173668956, 0 -0.1, 0, 0.466523645, -2011.8834, -0.02758575, 1559.12202 -0.1, 0, 0.544277585, 630.3653, 0.153372222, 1818.97569 -0.1, 0, 0.622031526, 3272.6143, 0.334330194, 2078.82936 -0.1, 0, 0.699785467, 6125.4189, 0.527641611, 2338.68303 -0.1, 0, 0.777539408, 9521.6475, 0.790469417, 2598.5367 -0.1, 0, 0.855293348, 13855.2959, 1.156945944, 2858.39037 -0.1, 0, 0.933047289, 19628.418, 1.65991725, 3118.24404 -0.1, 3000, 0, 566.2082979, 0.157280083, 0 -0.1, 3000, 0.456901206, -2313.858908, -0.049171522, 1526.963832 -0.1, 3000, 0.533051408, 193.1630888, 0.117219059, 1781.457804 -0.1, 3000, 0.609201609, 2700.185122, 0.283609647, 2035.951776 -0.1, 3000, 0.68535181, 5250.776912, 0.45545667, 2290.445748 -0.1, 3000, 0.761502011, 8308.462379, 0.685411425, 2544.93972 -0.1, 3000, 0.837652212, 12111.90593, 0.998639823, 2799.433692 -0.1, 3000, 0.913802413, 17311.67448, 1.43862743, 3053.927664 -0.1, 3000, 0.989952614, 23690.67884, 1.989146837, 3308.421636 -0.1, 6000, 0, 511.6951553, 0.142137543, 0 -0.1, 6000, 0.447277869, -2534.2515, -0.071269583, 1494.802638 -0.1, 6000, 0.52182418, -211.1178, 0.082612944, 1743.936411 -0.1, 6000, 0.596370492, 2112.0161, 0.2364955, 1993.070184 -0.1, 6000, 0.670916803, 4435.1494, 0.390378056, 2242.203957 -0.1, 6000, 0.745463115, 7123.7822, 0.589462472, 2491.33773 -0.1, 6000, 0.820009426, 10496.6621, 0.8636505, 2740.471503 -0.1, 6000, 0.894555738, 14965.501, 1.237703861, 2989.605276 -0.1, 6000, 0.969102049, 20653.1406, 1.726841917, 3238.739049 -0.1, 9000, 0, 461.4143496, 0.128170653, 0 -0.1, 9000, 0.437655431, -2541.0796, -0.086268694, 1462.64445 -0.1, 9000, 0.510598003, -442.1006, 0.054201444, 1706.418525 -0.1, 9000, 0.583540575, 1656.8784, 0.194671583, 1950.1926 -0.1, 9000, 0.656483146, 3755.8574, 0.33514175, 2193.966675 -0.1, 9000, 0.729425718, 6110.103, 0.50551375, 2437.74075 -0.1, 9000, 0.80236829, 9037.5127, 0.739982833, 2681.514825 -0.1, 9000, 0.875310862, 12865.3623, 1.060059, 2925.2889 -0.1, 9000, 0.948253434, 17810.1504, 1.47983275, 3169.062975 -0.1, 12000, 0, 415.1161917, 0.115310053, 0 -0.1, 12000, 0.428032093, -3536.912952, -0.096764802, 1430.483256 -0.1, 12000, 0.499370776, -1373.46869, 0.030029453, 1668.897132 -0.1, 12000, 0.570709458, 789.9805144, 0.156824173, 1907.311008 -0.1, 12000, 0.64204814, 2953.427318, 0.283619064, 2145.724884 -0.1, 12000, 0.713386822, 5376.871478, 0.435116522, 2384.13876 -0.1, 12000, 0.784725504, 8124.962063, 0.637514001, 2622.552636 -0.1, 12000, 0.856064187, 10739.449, 0.88907006, 2860.966512 -0.1, 12000, 0.927402869, 15355.02933, 1.257873165, 3099.380388 -0.1, 12000, 0.998741551, 20015.49159, 1.680811682, 3337.794264 -0.1, 15000, 0, 372.5670386, 0.103490844, 0 -0.1, 15000, 0.418409655, -2899.1604, -0.158622694, 1398.325068 -0.1, 15000, 0.488144598, -1193.4852, -0.03234425, 1631.379246 -0.1, 15000, 0.55787954, 512.2159, 0.093936139, 1864.433424 -0.1, 15000, 0.627614483, 2217.908, 0.220214583, 2097.487602 -0.1, 15000, 0.697349425, 3920.2632, 0.315881833, 2330.54178 -0.1, 15000, 0.767084368, 7199.8663, 0.548780472, 2563.595958 -0.1, 15000, 0.836819311, 8379.4741, 0.72457125, 2796.650136 -0.1, 15000, 0.906554253, 16168.3699, 1.233704917, 3029.704314 -0.1, 15000, 0.976289196, 10308.4511, 1.196259056, 3262.758492 -0.1, 18000, 0, 333.5397029, 0.092649917, 0 -0.1, 18000, 0.408786318, -9788.776233, -0.491487496, 1366.163874 -0.1, 18000, 0.476917371, -6203.25903, -0.283584402, 1593.857853 -0.1, 18000, 0.545048424, -2617.717026, -0.075689244, 1821.551832 -0.1, 18000, 0.613179477, 967.8267136, 0.13220761, 2049.245811 -0.1, 18000, 0.68131053, 2611.280803, 0.271679082, 2276.93979 -0.1, 18000, 0.749441583, 4255.159713, 0.374638012, 2504.633769 -0.1, 18000, 0.817572636, 7612.584242, 0.551396197, 2732.327748 -0.1, 18000, 0.885703689, 7486.397506, 0.70340443, 2960.021727 -0.1, 18000, 0.953834741, 21206.83883, 1.381271694, 3187.715706 -0.1, 21000, 0, 297.8138676, 0.082726074, 0 -0.1, 21000, 0.39916388, 927.9313496, 0.392143238, 1334.005686 -0.1, 21000, 0.465691193, 1530.866749, 0.346216818, 1556.339967 -0.1, 21000, 0.532218506, 2133.829503, 0.300292093, 1778.674248 -0.1, 21000, 0.59874582, 2736.774675, 0.254360872, 2001.008529 -0.1, 21000, 0.665273133, 3334.369437, 0.256134608, 2223.34281 -0.1, 21000, 0.731800446, 2118.566773, 0.285618011, 2445.677091 -0.1, 21000, 0.798327759, 5682.667971, 0.458988737, 2668.011372 -0.1, 21000, 0.864855073, 9678.700175, 0.912299998, 2890.345653 -0.1, 21000, 0.931382386, 12027.24358, 1.242263068, 3112.679934 -0.1, 21000, 0.997909699, 17995.24383, 2.105041082, 3335.014215 -0.1, 24000, 0, 265.180881, 0.073661356, 0 -0.1, 24000, 0.389540542, -3017.821735, -0.71585903, 1301.844492 -0.1, 24000, 0.454463966, -1841.305013, -0.487827145, 1518.818574 -0.1, 24000, 0.51938739, -664.7590688, -0.259797421, 1735.792656 -0.1, 24000, 0.584310813, 511.7418952, -0.031768622, 1952.766738 -0.1, 24000, 0.649234237, 2811.075483, 0.249523855, 2169.74082 -0.1, 24000, 0.714157661, 5487.854352, 0.492470682, 2386.714902 -0.1, 24000, 0.779081084, 6695.06703, 0.576705195, 2603.688984 -0.1, 24000, 0.844004508, 9078.895441, 0.620270599, 2820.663066 -0.1, 24000, 0.908927932, 8740.784045, 0.734203403, 3037.637148 -0.1, 24000, 0.973851355, 10632.68983, 1.050844314, 3254.61123 -0.1, 27000, 0, 235.4385501, 0.065399597, 0 -0.1, 27000, 0.379918104, 15827.53082, 2.291082454, 1269.686304 -0.1, 27000, 0.443237788, 11485.00185, 1.734689497, 1481.300688 -0.1, 27000, 0.506557472, 7142.404876, 1.178283876, 1692.915072 -0.1, 27000, 0.569877156, 2799.823421, 0.621878254, 1904.529456 -0.1, 27000, 0.63319684, -1446.007174, 0.024860341, 2116.14384 -0.1, 27000, 0.696516524, 3193.342578, 0.14599906, 2327.758224 -0.1, 27000, 0.759836208, 3581.758115, 0.19839576, 2539.372608 -0.1, 27000, 0.823155892, 2379.1708, 0.568648832, 2750.986992 -0.1, 27000, 0.886475576, 9673.633797, 0.728224053, 2962.601376 -0.1, 27000, 0.94979526, 3357.267338, 0.943908128, 3174.21576 -0.1, 30000, 0, 208.3959272, 0.057887758, 0 -0.1, 30000, 0.370294767, -571.8782, 0.274204194, 1237.52511 -0.1, 30000, 0.432010561, 906.9156, 0.28153725, 1443.779295 -0.1, 30000, 0.493726355, 2385.2968, 0.288906389, 1650.03348 -0.1, 30000, 0.55544215, 3863.8893, 0.296254417, 1856.287665 -0.1, 30000, 0.617157944, 3474.2749, 0.095660917, 2062.54185 -0.1, 30000, 0.678873739, 18.9526, 0.137025361, 2268.796035 -0.1, 30000, 0.740589533, 1969.5104, 0.036837083, 2475.05022 -0.1, 30000, 0.802305328, 3700.8639, -0.144322472, 2681.304405 -0.1, 30000, 0.864021122, 10959.7523, 1.33678175, 2887.55859 -0.1, 30000, 0.925736917, 21054.5314, 1.109290722, 3093.812775 -0.1, 30000, 0.987452711, 40095.1333, 2.5543895, 3300.06696 -0.1, 33000, 0, 183.867067, 0.051074185, 0 -0.1, 33000, 0.360672329, 43687.42465, 1.348920525, 1205.366922 -0.1, 33000, 0.420784383, 34207.31479, 1.038507295, 1406.261409 -0.1, 33000, 0.480896438, 24727.12259, 0.728092357, 1607.155896 -0.1, 33000, 0.541008493, 15246.91071, 0.417696935, 1808.050383 -0.1, 33000, 0.601120548, 5766.653331, 0.10726419, 2008.94487 -0.1, 33000, 0.661232602, -903.5494536, -0.02206976, 2209.839357 -0.1, 33000, 0.721344657, 8126.70747, 0.87094374, 2410.733844 -0.1, 33000, 0.781456712, 7733.798859, 0.759753172, 2611.628331 -0.1, 33000, 0.841568767, -1066.133674, -0.456458688, 2812.522818 -0.1, 33000, 0.901680821, 4131.562286, 0.489202427, 3013.417305 -0.1, 33000, 0.961792876, -31625.24698, -5.88983647, 3214.311792 -0.1, 36000, 0, 161.6772979, 0.044910361, 0 -0.1, 36000, 0.351048991, 41090.5223, 0.987869889, 1173.205728 -0.1, 36000, 0.409557156, 32625.6196, 0.819634778, 1368.740016 -0.1, 36000, 0.468065321, 24160.5025, 0.651399667, 1564.274304 -0.1, 36000, 0.526573487, 15695.5569, 0.483170667, 1759.808592 -0.1, 36000, 0.585081652, 7230.5333, 0.314915722, 1955.34288 -0.1, 36000, 0.643589817, 1364.1156, 0.137393361, 2150.877168 -0.1, 36000, 0.702097982, 1268.3249, 0.090066583, 2346.411456 -0.1, 36000, 0.760606147, -12394.2989, -0.407332306, 2541.945744 -0.1, 36000, 0.819114312, 30619.6047, 1.979559028, 2737.480032 -0.1, 36000, 0.877622478, 12129.0639, 1.192497778, 2933.01432 -0.1, 36000, 0.936130643, -13311.9698, -3.825813111, 3128.548608 -0.1, 39000, 0, 140.024758, 0.038895766, 0 -0.1, 39000, 0.350762962, 92.9512, -0.015977056, 1172.24982 -0.1, 39000, 0.409223456, -270.2002, -0.022166056, 1367.62479 -0.1, 39000, 0.46768395, -633.5255, -0.028353222, 1562.99976 -0.1, 39000, 0.526144443, -996.7287, -0.034526667, 1758.37473 -0.1, 39000, 0.584604937, -1360.0385, -0.040707722, 1953.7497 -0.1, 39000, 0.643065431, -2307.8725, -0.087514889, 2149.12467 -0.1, 39000, 0.701525925, 446.4424, 0.057609222, 2344.49964 -0.1, 39000, 0.759986418, -2130.3116, -0.2457555, 2539.87461 -0.1, 39000, 0.818446912, 5624.6113, -0.618322167, 2735.24958 -0.1, 39000, 0.876907406, 8977.3108, 0.913738583, 2930.62455 -0.1, 39000, 0.935367899, 75013.8125, 11.82189689, 3125.99952 -0.1, 42000, 0, 121.2226459, 0.033672957, 0 -0.1, 42000, 0.350762962, -306857.2146, -32.78347492, 1172.24982 -0.1, 42000, 0.409223456, -240760.6761, -25.66480094, 1367.62479 -0.1, 42000, 0.46768395, -174664.1927, -18.54611831, 1562.99976 -0.1, 42000, 0.526144443, -108567.7979, -11.42742436, 1758.37473 -0.1, 42000, 0.584604937, -42471.32287, -4.308770689, 1953.7497 -0.1, 42000, 0.643065431, -11125.21901, -1.035335403, 2149.12467 -0.1, 42000, 0.701525925, 6419.422362, 0.224106099, 2344.49964 -0.1, 42000, 0.759986418, -6860.386856, 0.025389083, 2539.87461 -0.1, 42000, 0.818446912, 17132.47784, 2.588605753, 2735.24958 -0.1, 42000, 0.876907406, -5909.965075, -0.727588472, 2930.62455 -0.1, 42000, 0.935367899, 14914.66148, 2.984818049, 3125.99952 -0.15, 0, 0, 629.8996281, 0.174972119, 0 -0.15, 0, 0.467687626, -1595.5012, -0.020581694, 1563.012045 -0.15, 0, 0.545635563, 705.9526, 0.159697333, 1823.514053 -0.15, 0, 0.623583501, 3007.4065, 0.339976333, 2084.01606 -0.15, 0, 0.701531439, 5609.0469, 0.534164806, 2344.518068 -0.15, 0, 0.779479376, 8876.0898, 0.801054833, 2605.020075 -0.15, 0, 0.857427314, 13067.2031, 1.172596972, 2865.522082 -0.15, 0, 0.935375251, 18695.7617, 1.6841325, 3126.02409 -0.15, 3000, 0, 570.4569668, 0.158460269, 0 -0.15, 3000, 0.45804118, -2181.347289, -0.046048477, 1530.773622 -0.15, 3000, 0.534381376, 124.0647792, 0.121047516, 1785.902559 -0.15, 3000, 0.610721573, 2429.476884, 0.288143485, 2041.031496 -0.15, 3000, 0.687061769, 4789.782167, 0.461467044, 2296.160433 -0.15, 3000, 0.763401966, 7712.867227, 0.694509892, 2551.28937 -0.15, 3000, 0.839742162, 11398.74773, 1.012770988, 2806.418307 -0.15, 3000, 0.916082359, 16460.68684, 1.459049452, 3061.547244 -0.15, 3000, 0.992422556, 22616.30261, 2.012889119, 3316.676181 -0.15, 6000, 0, 515.5347728, 0.143204104, 0 -0.15, 6000, 0.448393832, -2318.2634, -0.066588167, 1498.532186 -0.15, 6000, 0.523126137, -200.2143, 0.087313944, 1748.28755 -0.15, 6000, 0.597858442, 1917.8348, 0.241216028, 1998.042914 -0.15, 6000, 0.672590748, 4035.8838, 0.395118139, 2247.798278 -0.15, 6000, 0.747323053, 6617.0278, 0.597186472, 2497.553643 -0.15, 6000, 0.822055358, 9875.9111, 0.87555725, 2747.309007 -0.15, 6000, 0.896787663, 14248.8105, 1.256013194, 2997.064371 -0.15, 6000, 0.971519969, 19754.5176, 1.750484222, 3246.819735 -0.15, 9000, 0, 464.876674, 0.129132409, 0 -0.15, 9000, 0.438747386, -2540.3364, -0.08559525, 1466.293763 -0.15, 9000, 0.51187195, -555.764, 0.056046167, 1710.676056 -0.15, 9000, 0.584996514, 1428.8086, 0.197687556, 1955.05835 -0.15, 9000, 0.658121078, 3413.3813, 0.339328944, 2199.440644 -0.15, 9000, 0.731245643, 5666.9683, 0.512408639, 2443.822937 -0.15, 9000, 0.804370207, 8495.8262, 0.750086333, 2688.205231 -0.15, 9000, 0.877494771, 12251.2676, 1.076516194, 2932.587525 -0.15, 9000, 0.950619335, 17028.8652, 1.500582139, 3176.969819 -0.15, 12000, 0, 418.2311077, 0.116175308, 0 -0.15, 12000, 0.429100038, -2305.408852, -0.081906822, 1434.052326 -0.15, 12000, 0.500616711, -587.8128816, 0.04185396, 1673.061047 -0.15, 12000, 0.572133384, 1129.784222, 0.165614858, 1912.069768 -0.15, 12000, 0.643650057, 2847.380806, 0.289375799, 2151.078489 -0.15, 12000, 0.71516673, 4844.31097, 0.435922675, 2390.08721 -0.15, 12000, 0.786683402, 7393.286047, 0.641041458, 2629.095931 -0.15, 12000, 0.858200075, 10501.28136, 0.914115484, 2868.104652 -0.15, 12000, 0.929716748, 14658.18934, 1.275366156, 3107.113373 -0.15, 15000, 0, 375.3626776, 0.10426741, 0 -0.15, 15000, 0.419453592, -2520.8392, -0.12528875, 1401.813903 -0.15, 15000, 0.489362523, -931.7766, -0.005103194, 1635.449554 -0.15, 15000, 0.559271455, 657.2993, 0.115083361, 1869.085204 -0.15, 15000, 0.629180387, 2246.3706, 0.235268917, 2102.720855 -0.15, 15000, 0.699089319, 3880.9721, 0.346010528, 2336.356505 -0.15, 15000, 0.768998251, 6536.2103, 0.548265417, 2569.992156 -0.15, 15000, 0.838907183, 8392.3141, 0.754607111, 2803.627806 -0.15, 15000, 0.908816115, 14170.5088, 1.172107917, 3037.263457 -0.15, 15000, 0.978725047, 13079.8279, 1.345636611, 3270.899107 -0.15, 18000, 0, 336.0424917, 0.093345137, 0 -0.15, 18000, 0.409806244, -6865.768601, -0.34288117, 1369.572466 -0.15, 18000, 0.478107284, -4148.296486, -0.174180739, 1597.834544 -0.15, 18000, 0.546408325, -1430.80929, -0.005485096, 1826.096622 -0.15, 18000, 0.614709366, 1286.67865, 0.163211622, 2054.3587 -0.15, 18000, 0.683010406, 2829.580855, 0.291587227, 2282.620778 -0.15, 18000, 0.751311447, 4487.853441, 0.41391084, 2510.882855 -0.15, 18000, 0.819612487, 7344.145386, 0.595907885, 2739.144933 -0.15, 18000, 0.887913528, 8374.39893, 0.79104443, 2967.407011 -0.15, 18000, 0.956214569, 18054.61251, 1.335256604, 3195.669089 -0.15, 21000, 0, 300.0485797, 0.083346828, 0 -0.15, 21000, 0.400159798, -395.5991344, 0.203525579, 1337.334044 -0.15, 21000, 0.466853097, 476.1361568, 0.210570523, 1560.223051 -0.15, 21000, 0.533546397, 1347.889155, 0.217616541, 1783.112058 -0.15, 21000, 0.600239696, 2219.631167, 0.224658295, 2006.001065 -0.15, 21000, 0.666932996, 3067.974005, 0.260598021, 2228.890073 -0.15, 21000, 0.733626296, 2816.955421, 0.325732795, 2451.77908 -0.15, 21000, 0.800319595, 5736.527123, 0.496207587, 2674.668087 -0.15, 21000, 0.867012895, 9241.062667, 0.871358478, 2897.557094 -0.15, 21000, 0.933706194, 11521.47154, 1.168886273, 3120.446101 -0.15, 24000, 0, 267.1707243, 0.07421409, 0 -0.15, 24000, 0.39051245, -3119.500023, -0.544253686, 1305.092607 -0.15, 24000, 0.455597858, -1883.091705, -0.356403468, 1522.608042 -0.15, 24000, 0.520683266, -646.6635808, -0.168554675, 1740.123476 -0.15, 24000, 0.585768675, 589.7342832, 0.019293409, 1957.638911 -0.15, 24000, 0.650854083, 2543.751631, 0.23968666, 2175.154345 -0.15, 24000, 0.715939491, 4841.347192, 0.443841586, 2392.66978 -0.15, 24000, 0.781024899, 6188.723186, 0.547932287, 2610.185214 -0.15, 24000, 0.846110308, 8417.353213, 0.635376104, 2827.700649 -0.15, 24000, 0.911195716, 8916.145897, 0.787262326, 3045.216083 -0.15, 24000, 0.976281124, 10974.38393, 1.096655054, 3262.731518 -0.15, 27000, 0, 237.2052152, 0.065890338, 0 -0.15, 27000, 0.380866004, 10189.28393, 1.56087576, 1272.854184 -0.15, 27000, 0.444343671, 7489.48367, 1.196088045, 1484.996548 -0.15, 27000, 0.507821338, 4789.635096, 0.831291231, 1697.138912 -0.15, 27000, 0.571299005, 2089.797733, 0.466494418, 1909.281276 -0.15, 27000, 0.634776673, -510.8828376, 0.076791191, 2121.42364 -0.15, 27000, 0.69825434, 3060.008614, 0.185839062, 2333.566004 -0.15, 27000, 0.761732007, 3805.420543, 0.264469754, 2545.708368 -0.15, 27000, 0.825209674, 3453.04822, 0.572131908, 2757.850732 -0.15, 27000, 0.888687342, 9214.581449, 0.742293998, 2969.993096 -0.15, 27000, 0.952165009, 5125.501962, 0.946424113, 3182.13546 -0.15, 30000, 0, 209.959672, 0.058322131, 0 -0.15, 30000, 0.371218656, -967.3588, 0.161762889, 1240.612747 -0.15, 30000, 0.433088432, 347.277, 0.187647361, 1447.381539 -0.15, 30000, 0.494958208, 1661.6072, 0.213558389, 1654.15033 -0.15, 30000, 0.556827984, 2976.0935, 0.239453833, 1860.919121 -0.15, 30000, 0.61869776, 2931.8844, 0.114119444, 2067.687913 -0.15, 30000, 0.680567536, 545.8852, 0.159085611, 2274.456704 -0.15, 30000, 0.742437311, 2359.71, 0.116849444, 2481.225495 -0.15, 30000, 0.804307087, 4032.8178, 0.021803139, 2687.994286 -0.15, 30000, 0.866176863, 9792.3005, 1.156753861, 2894.763078 -0.15, 30000, 0.928046639, 17824.3484, 1.067207028, 3101.531869 -0.15, 30000, 0.989916415, 32416.9565, 2.223069889, 3308.30066 -0.15, 33000, 0, 185.2467542, 0.051457432, 0 -0.15, 33000, 0.36157221, 32364.60071, 0.975735494, 1208.374325 -0.15, 33000, 0.421834245, 25411.04959, 0.75910507, 1409.770045 -0.15, 33000, 0.482096279, 18457.43551, 0.542473232, 1611.165766 -0.15, 33000, 0.542358314, 11503.80685, 0.325856109, 1812.561487 -0.15, 33000, 0.602620349, 4550.143935, 0.10921097, 2013.957208 -0.15, 33000, 0.662882384, -232.5511256, 0.033930172, 2215.352928 -0.15, 33000, 0.723144419, 6810.178682, 0.726081156, 2416.748649 -0.15, 33000, 0.783406454, 6838.791363, 0.669654522, 2618.14437 -0.15, 33000, 0.843668489, 651.0772776, -0.197837903, 2819.540091 -0.15, 33000, 0.903930524, 4571.670514, 0.503825537, 3020.935811 -0.15, 33000, 0.964192559, -22795.10911, -4.380645888, 3222.331532 -0.15, 36000, 0, 162.8904792, 0.045247355, 0 -0.15, 36000, 0.351924862, 30245.1699, 0.700633917, 1176.132888 -0.15, 36000, 0.410579005, 24067.4109, 0.58952625, 1372.155036 -0.15, 36000, 0.469233149, 17889.49, 0.478418583, 1568.177184 -0.15, 36000, 0.527887293, 11711.699, 0.3673155, 1764.199332 -0.15, 36000, 0.586541436, 5533.8486, 0.256192861, 1960.22148 -0.15, 36000, 0.64519558, 1317.7995, 0.137817556, 2156.243628 -0.15, 36000, 0.703849724, 1419.4675, 0.117879861, 2352.265776 -0.15, 36000, 0.762503867, -8648.1409, -0.233036806, 2548.287924 -0.15, 36000, 0.821158011, 24245.3826, 1.596467861, 2744.310072 -0.15, 36000, 0.879812154, 10584.6795, 1.059810083, 2940.33222 -0.15, 36000, 0.938466298, -8883.05, -2.758612889, 3136.354368 -0.15, 39000, 0, 141.0754646, 0.039187629, 0 -0.15, 39000, 0.351638119, -131.4163, -0.035418333, 1175.174595 -0.15, 39000, 0.410244473, -331.6345, -0.030012861, 1371.037028 -0.15, 39000, 0.468850826, -531.9828, -0.024605861, 1566.89946 -0.15, 39000, 0.527457179, -732.2386, -0.019188472, 1762.761893 -0.15, 39000, 0.586063532, -932.5758, -0.013776889, 1958.624325 -0.15, 39000, 0.644669886, -1573.4118, -0.042196917, 2154.486758 -0.15, 39000, 0.703276239, 702.4008, 0.083520333, 2350.34919 -0.15, 39000, 0.761882592, -1039.9346, -0.123150639, 2546.211623 -0.15, 39000, 0.820488945, 5129.54, -0.387479778, 2742.074055 -0.15, 39000, 0.879095298, 7861.5288, 0.804960167, 2937.936488 -0.15, 39000, 0.937701652, 57627.9395, 9.040117417, 3133.79892 -0.15, 42000, 0, 122.1322668, 0.03392563, 0 -0.15, 42000, 0.351638119, -244342.1447, -26.08793844, 1175.174595 -0.15, 42000, 0.410244473, -191697.7169, -20.42143815, 1371.037028 -0.15, 42000, 0.468850826, -139053.3312, -14.75493119, 1566.89946 -0.15, 42000, 0.527457179, -86409.01606, -9.088415241, 1762.761893 -0.15, 42000, 0.586063532, -33764.6375, -3.421930922, 1958.624325 -0.15, 42000, 0.644669886, -8600.263769, -0.793022493, 2154.486758 -0.15, 42000, 0.703276239, 5271.145412, 0.209513505, 2350.34919 -0.15, 42000, 0.761882592, -4946.085294, 0.062444736, 2546.211623 -0.15, 42000, 0.820488945, 14003.03216, 2.089055594, 2742.074055 -0.15, 42000, 0.879095298, -3691.529825, -0.462773715, 2937.936488 -0.15, 42000, 0.937701652, 13262.19119, 2.546990375, 3133.79892 -0.2, 0, 0, 636.5069133, 0.176807476, 0 -0.2, 0, 0.469317199, -1542.0807, -0.017843361, 1568.45808 -0.2, 0, 0.547536732, 640.9626, 0.164754694, 1829.86776 -0.2, 0, 0.625756266, 2824.0059, 0.347352722, 2091.27744 -0.2, 0, 0.703975799, 5274.0562, 0.544391278, 2352.68712 -0.2, 0, 0.782195332, 8355.2285, 0.816291917, 2614.0968 -0.2, 0, 0.860414865, 12458.0088, 1.195121528, 2875.50648 -0.2, 0, 0.938634399, 17981.373, 1.718714472, 3136.91616 -0.2, 3000, 0, 576.4407326, 0.160122426, 0 -0.2, 3000, 0.459637142, -1929.121419, -0.041484338, 1536.107328 -0.2, 3000, 0.536243332, 191.113177, 0.126889464, 1792.125216 -0.2, 3000, 0.612849522, 2311.347692, 0.295263276, 2048.143104 -0.2, 3000, 0.689455713, 4495.35659, 0.4708784, 2304.160992 -0.2, 3000, 0.766061903, 7260.212017, 0.707549698, 2560.17888 -0.2, 3000, 0.842668093, 10867.07876, 1.03346614, 2816.196768 -0.2, 3000, 0.919274284, 15824.34557, 1.488322488, 3072.214656 -0.2, 3000, 0.995880474, 21722.53807, 2.045527871, 3328.232544 -0.2, 6000, 0, 520.9424363, 0.144706232, 0 -0.2, 6000, 0.44995618, -2131.915, -0.062702556, 1503.753552 -0.2, 6000, 0.524948876, -154.4856, 0.092535194, 1754.379144 -0.2, 6000, 0.599941573, 1822.9437, 0.247772944, 2005.004736 -0.2, 6000, 0.674934269, 3805.092, 0.403714861, 2255.630328 -0.2, 6000, 0.749926966, 6213.9473, 0.608656833, 2506.25592 -0.2, 6000, 0.824919662, 9396.9238, 0.892598944, 2756.881512 -0.2, 6000, 0.899912359, 13711.4297, 1.282920333, 3007.507104 -0.2, 6000, 0.974905056, 19006.3398, 1.783233111, 3258.132696 -0.2, 9000, 0, 469.7529632, 0.130486934, 0 -0.2, 9000, 0.440276122, -2245.9915, -0.082420222, 1471.4028 -0.2, 9000, 0.513655476, -424.355, 0.06050225, 1716.6366 -0.2, 9000, 0.587034829, 1397.2812, 0.203424722, 1961.8704 -0.2, 9000, 0.660414183, 3218.9177, 0.346347194, 2207.1042 -0.2, 9000, 0.733793537, 5313.5864, 0.522176722, 2452.338 -0.2, 9000, 0.80717289, 8076.6055, 0.764613389, 2697.5718 -0.2, 9000, 0.880552244, 11792.0068, 1.100025972, 2942.8056 -0.2, 9000, 0.953931598, 16407.084, 1.530240472, 3188.0394 -0.2, 12000, 0, 422.6181117, 0.11739392, 0 -0.2, 12000, 0.43059516, -1917.463052, -0.07747033, 1439.049024 -0.2, 12000, 0.50236102, -366.8472336, 0.047050416, 1678.890528 -0.2, 12000, 0.57412688, 1183.76837, 0.171571166, 1918.732032 -0.2, 12000, 0.64589274, 2734.384134, 0.2960919, 2158.573536 -0.2, 12000, 0.7176586, 4538.604822, 0.443426873, 2398.41504 -0.2, 12000, 0.78942446, 6956.833951, 0.652499753, 2638.256544 -0.2, 12000, 0.86119032, 10168.98385, 0.936272892, 2878.098048 -0.2, 12000, 0.93295618, 14116.28219, 1.301523603, 3117.939552 -0.2, 15000, 0, 379.3000164, 0.105361116, 0 -0.2, 15000, 0.420915102, -2268.589, -0.102840056, 1406.698272 -0.2, 15000, 0.491067619, -770.5034, 0.013872278, 1641.147984 -0.2, 15000, 0.561220136, 727.5877, 0.130585028, 1875.597696 -0.2, 15000, 0.631372654, 2225.6769, 0.247297361, 2110.047408 -0.2, 15000, 0.701525171, 3812.9712, 0.368626167, 2344.49712 -0.2, 15000, 0.771677688, 6078.4497, 0.555040389, 2578.946832 -0.2, 15000, 0.841830205, 8357.9574, 0.783344833, 2813.396544 -0.2, 15000, 0.911982722, 12805.6333, 1.144348583, 3047.846256 -0.2, 15000, 0.982135239, 14580.0738, 1.446161167, 3282.295968 -0.2, 18000, 0, 339.5673844, 0.094324273, 0 -0.2, 18000, 0.41123414, -4772.187289, -0.235152998, 1374.344496 -0.2, 18000, 0.479773163, -2684.108582, -0.094308209, 1603.401912 -0.2, 18000, 0.548312187, -596.0216144, 0.046533991, 1832.459328 -0.2, 18000, 0.61685121, 1492.065526, 0.187376817, 2061.516744 -0.2, 18000, 0.685390233, 2959.016787, 0.308830834, 2290.57416 -0.2, 18000, 0.753929257, 4634.591289, 0.445907223, 2519.631576 -0.2, 18000, 0.82246828, 7162.97159, 0.635951167, 2748.688992 -0.2, 18000, 0.891007303, 8986.639214, 0.863613541, 2977.746408 -0.2, 18000, 0.959546327, 15775.61429, 1.316298747, 3206.803824 -0.2, 21000, 0, 303.1959169, 0.084221088, 0 -0.2, 21000, 0.401554083, -1286.149678, 0.069477648, 1341.993744 -0.2, 21000, 0.468479763, -244.0783152, 0.11477246, 1565.659368 -0.2, 21000, 0.535405443, 798.0036872, 0.1600679, 1789.324992 -0.2, 21000, 0.602331124, 1840.079439, 0.205360735, 2012.990616 -0.2, 21000, 0.669256804, 2856.066793, 0.266762829, 2236.65624 -0.2, 21000, 0.736182485, 3317.714789, 0.359368013, 2460.321864 -0.2, 21000, 0.803108165, 5785.787455, 0.53045977, 2683.987488 -0.2, 21000, 0.870033846, 8897.440939, 0.849093658, 2907.653112 -0.2, 21000, 0.936959526, 11155.84483, 1.128483257, 3131.318736 -0.2, 24000, 0, 269.9731917, 0.074992553, 0 -0.2, 24000, 0.39187312, -3086.633891, -0.40757348, 1309.639968 -0.2, 24000, 0.457185307, -1835.977217, -0.251374469, 1527.913296 -0.2, 24000, 0.522497494, -585.3079128, -0.095176335, 1746.186624 -0.2, 24000, 0.58780968, 665.3422512, 0.061021279, 1964.459952 -0.2, 24000, 0.653121867, 2335.007859, 0.234715397, 2182.73328 -0.2, 24000, 0.718434054, 4330.393532, 0.409465452, 2401.006608 -0.2, 24000, 0.783746241, 5792.046102, 0.530490051, 2619.279936 -0.2, 24000, 0.849058427, 7905.602705, 0.653476193, 2837.553264 -0.2, 24000, 0.914370614, 9028.809469, 0.835883359, 3055.826592 -0.2, 24000, 0.979682801, 11165.55823, 1.136429027, 3274.09992 -0.2, 27000, 0, 239.6933617, 0.066581489, 0 -0.2, 27000, 0.382193063, 5851.268065, 0.992970066, 1277.289216 -0.2, 27000, 0.445891907, 4417.294346, 0.777694515, 1490.170752 -0.2, 27000, 0.50959075, 2983.287816, 0.562412698, 1703.052288 -0.2, 27000, 0.573289594, 1549.289065, 0.347130881, 1915.933824 -0.2, 27000, 0.636988438, 207.1619584, 0.118144263, 2128.81536 -0.2, 27000, 0.700687282, 2949.64181, 0.219505725, 2341.696896 -0.2, 27000, 0.764386126, 3967.372851, 0.318898943, 2554.578432 -0.2, 27000, 0.828084969, 4283.77104, 0.579060906, 2767.459968 -0.2, 27000, 0.891783813, 8825.652021, 0.758855316, 2980.341504 -0.2, 27000, 0.955482657, 6503.510226, 0.958336121, 3193.22304 -0.2, 30000, 0, 212.1620283, 0.058933897, 0 -0.2, 30000, 0.372512101, -1299.1236, 0.071142722, 1244.93544 -0.2, 30000, 0.434597451, -116.08, 0.112272444, 1452.42468 -0.2, 30000, 0.496682801, 1066.7448, 0.153421028, 1659.91392 -0.2, 30000, 0.558768151, 2249.681, 0.1945585, 1867.40316 -0.2, 30000, 0.620853501, 2481.5309, 0.129835417, 2074.8924 -0.2, 30000, 0.682938851, 978.6678, 0.179553444, 2282.38164 -0.2, 30000, 0.745024201, 2672.6547, 0.184441194, 2489.87088 -0.2, 30000, 0.807109551, 4300.7528, 0.159842417, 2697.36012 -0.2, 30000, 0.869194901, 8847.3588, 1.015807139, 2904.84936 -0.2, 30000, 0.931280251, 15157.1318, 1.032594611, 3112.3386 -0.2, 30000, 0.993365601, 26100.6123, 1.946877222, 3319.82784 -0.2, 33000, 0, 187.1898862, 0.051997191, 0 -0.2, 33000, 0.362832043, 23055.01512, 0.669131057, 1212.584688 -0.2, 33000, 0.42330405, 18179.43416, 0.529916022, 1414.682136 -0.2, 33000, 0.483776057, 13303.80638, 0.39069984, 1616.779584 -0.2, 33000, 0.544248065, 8428.168142, 0.251494426, 1818.877032 -0.2, 33000, 0.604720072, 3552.504859, 0.112268622, 2020.97448 -0.2, 33000, 0.665192079, 312.6091424, 0.080772238, 2223.071928 -0.2, 33000, 0.725664086, 5726.573254, 0.609144982, 2425.169376 -0.2, 33000, 0.786136093, 6102.495387, 0.599107289, 2627.266824 -0.2, 33000, 0.846608101, 2044.14039, 0.016476588, 2829.364272 -0.2, 33000, 0.907080108, 4972.292682, 0.528670836, 3031.46172 -0.2, 33000, 0.967552115, -15369.76611, -3.104220263, 3233.559168 -0.2, 36000, 0, 164.5991067, 0.045721974, 0 -0.2, 36000, 0.353151081, 21355.844, 0.464740111, 1180.230912 -0.2, 36000, 0.412009594, 17053.5167, 0.400885, 1376.936064 -0.2, 36000, 0.470868108, 12751.0707, 0.337029889, 1573.641216 -0.2, 36000, 0.529726621, 8448.7203, 0.273178111, 1770.346368 -0.2, 36000, 0.588585135, 4146.3259, 0.209312028, 1967.05152 -0.2, 36000, 0.647443648, 1281.7117, 0.139831722, 2163.756672 -0.2, 36000, 0.706302162, 1554.0978, 0.143400611, 2360.461824 -0.2, 36000, 0.765160675, -5548.7548, -0.086262472, 2557.166976 -0.2, 36000, 0.824019189, 18994.0949, 1.285781611, 2753.872128 -0.2, 36000, 0.882877702, 9293.2069, 0.950557861, 2950.57728 -0.2, 36000, 0.941736215, -5216.6114, -1.875377556, 3147.282432 -0.2, 39000, 0, 142.5552652, 0.039598685, 0 -0.2, 39000, 0.352863339, -369.1119, -0.053260111, 1179.26928 -0.2, 39000, 0.411673896, -423.5128, -0.037736222, 1375.81416 -0.2, 39000, 0.470484452, -478.008, -0.022211083, 1572.35904 -0.2, 39000, 0.529295009, -532.4351, -0.006678306, 1768.90392 -0.2, 39000, 0.588105566, -586.9227, 0.008850167, 1965.4488 -0.2, 39000, 0.646916122, -962.282, -0.003136556, 2161.99368 -0.2, 39000, 0.705726679, 919.3272, 0.10703625, 2358.53856 -0.2, 39000, 0.764537235, -128.4183, -0.019706778, 2555.08344 -0.2, 39000, 0.823347792, 4724.4699, -0.192780167, 2751.62832 -0.2, 39000, 0.882158348, 6948.5503, 0.719300944, 2948.1732 -0.2, 39000, 0.940968905, 43362.6703, 6.758414694, 3144.71808 -0.2, 42000, 0, 123.4133641, 0.03428149, 0 -0.2, 42000, 0.352863339, -191029.879, -20.37978623, 1179.26928 -0.2, 42000, 0.411673896, -149857.5562, -15.95098674, 1375.81416 -0.2, 42000, 0.470484452, -108685.2646, -11.52218224, 1572.35904 -0.2, 42000, 0.529295009, -67513.02814, -7.093370745, 1768.90392 -0.2, 42000, 0.588105566, -26340.74252, -2.664583557, 1965.4488 -0.2, 42000, 0.646916122, -6468.488781, -0.587554972, 2161.99368 -0.2, 42000, 0.705726679, 4304.067562, 0.197734314, 2358.53856 -0.2, 42000, 0.764537235, -3325.895381, 0.096098278, 2555.08344 -0.2, 42000, 0.823347792, 11367.89359, 1.669978351, 2751.62832 -0.2, 42000, 0.882158348, -1836.934775, -0.239309014, 2948.1732 -0.2, 42000, 0.940968905, 11769.36616, 2.165113479, 3144.71808 -0.25, 0, 0, 645.0696726, 0.17918602, 0 -0.25, 0, 0.471412365, -1742.0389, -0.016358833, 1575.460125 -0.25, 0, 0.549981093, 445.6624, 0.169875694, 1838.036813 -0.25, 0, 0.62854982, 2633.3638, 0.356110222, 2100.6135 -0.25, 0, 0.707118548, 5070.9658, 0.558444361, 2363.190188 -0.25, 0, 0.785687276, 8055.8228, 0.838454056, 2625.766875 -0.25, 0, 0.864256003, 12000.6689, 1.224431028, 2888.343562 -0.25, 0, 0.942824731, 17434.6426, 1.762963583, 3150.92025 -0.25, 3000, 0, 584.1954374, 0.16227651, 0 -0.25, 3000, 0.461689093, -1964.949747, -0.038823693, 1542.96495 -0.25, 3000, 0.538637276, 108.119197, 0.132461032, 1800.125775 -0.25, 3000, 0.615585458, 2181.188142, 0.303745786, 2057.2866 -0.25, 3000, 0.69253364, 4326.535311, 0.483777482, 2314.447425 -0.25, 3000, 0.769481822, 6980.937827, 0.725928012, 2571.60825 -0.25, 3000, 0.846430004, 10488.83017, 1.060805107, 2828.769075 -0.25, 3000, 0.923378187, 15330.18673, 1.525794617, 3085.9299 -0.25, 6000, 0, 527.9505372, 0.146652927, 0 -0.25, 6000, 0.451964912, -2162.8518, -0.060325833, 1510.466738 -0.25, 6000, 0.527292398, -225.7294, 0.097543639, 1762.211194 -0.25, 6000, 0.602619883, 1711.3928, 0.255413111, 2013.95565 -0.25, 6000, 0.677947369, 3662.1987, 0.415332972, 2265.700106 -0.25, 6000, 0.753274854, 6012.335, 0.626087444, 2517.444563 -0.25, 6000, 0.82860234, 9041.0713, 0.914939639, 2769.189019 -0.25, 6000, 0.903929825, 13317.4453, 1.318007139, 3020.933475 -0.25, 6000, 0.97925731, 18435.918, 1.82606825, 3272.677931 -0.25, 9000, 0, 476.0724257, 0.13224234, 0 -0.25, 9000, 0.44224164, -2278.7202, -0.0829855, 1477.971563 -0.25, 9000, 0.515948581, -489.7066, 0.063164667, 1724.300156 -0.25, 9000, 0.589655521, 1299.3069, 0.209314833, 1970.62875 -0.25, 9000, 0.663362461, 3088.3203, 0.355465028, 2216.957344 -0.25, 9000, 0.737069401, 5151.9565, 0.537164611, 2463.285938 -0.25, 9000, 0.810776341, 7776.4331, 0.784993278, 2709.614531 -0.25, 9000, 0.884483281, 11451.4189, 1.130062861, 2955.943125 -0.25, 9000, 0.958190221, 15926.9629, 1.568940694, 3202.271719 -0.25, 12000, 0, 428.3034815, 0.118973189, 0 -0.25, 12000, 0.43251746, -2003.622052, -0.079341412, 1445.47335 -0.25, 12000, 0.504603703, -463.2166456, 0.048379323, 1686.385575 -0.25, 12000, 0.576689946, 1077.188558, 0.176100068, 1927.2978 -0.25, 12000, 0.648776189, 2617.593902, 0.303820784, 2168.210025 -0.25, 12000, 0.720862433, 4380.616434, 0.45598867, 2409.12225 -0.25, 12000, 0.792948676, 6725.131075, 0.67046286, 2650.034475 -0.25, 12000, 0.865034919, 9842.336751, 0.960678422, 2890.9467 -0.25, 12000, 0.937121162, 13708.57047, 1.336116783, 3131.858925 -0.25, 15000, 0, 384.4026393, 0.106778511, 0 -0.25, 15000, 0.422794188, -2123.8319, -0.089531083, 1412.978175 -0.25, 15000, 0.493259886, -692.9334, 0.026069833, 1648.474537 -0.25, 15000, 0.563725583, 737.9665, 0.141670861, 1883.9709 -0.25, 15000, 0.634191281, 2168.8659, 0.257271778, 2119.467263 -0.25, 15000, 0.704656979, 3727.2303, 0.386083556, 2354.963625 -0.25, 15000, 0.775122677, 5788.9523, 0.56829825, 2590.459988 -0.25, 15000, 0.845588375, 8300.0662, 0.812496639, 2825.95635 -0.25, 15000, 0.916054073, 11956.3371, 1.145246139, 3061.452712 -0.25, 15000, 0.986519771, 15138.7984, 1.512665528, 3296.949075 -0.25, 18000, 0, 344.1354946, 0.095593193, 0 -0.25, 18000, 0.413070007, -3373.667697, -0.162001927, 1380.479962 -0.25, 18000, 0.481915008, -1714.352618, -0.039324201, 1610.559956 -0.25, 18000, 0.550760009, -55.0336984, 0.08335235, 1840.63995 -0.25, 18000, 0.61960501, 1604.285142, 0.206029224, 2070.719944 -0.25, 18000, 0.688450011, 3016.900199, 0.324202457, 2300.799938 -0.25, 18000, 0.757295012, 4712.997657, 0.472598829, 2530.879931 -0.25, 18000, 0.826140013, 7055.388554, 0.673003905, 2760.959925 -0.25, 18000, 0.894985015, 9375.739558, 0.924818569, 2991.039919 -0.25, 18000, 0.963830016, 14232.80417, 1.321032096, 3221.119912 -0.25, 21000, 0, 307.2747314, 0.085354092, 0 -0.25, 21000, 0.403346735, -1822.321482, -0.018989333, 1347.984788 -0.25, 21000, 0.470571191, -689.5712672, 0.05232077, 1572.648919 -0.25, 21000, 0.537795646, 443.1846992, 0.123631198, 1797.31305 -0.25, 21000, 0.605020102, 1575.937591, 0.194940192, 2021.977181 -0.25, 21000, 0.672244558, 2692.254201, 0.274624142, 2246.641313 -0.25, 21000, 0.739469014, 3652.677277, 0.387903303, 2471.305444 -0.25, 21000, 0.806693469, 5831.830067, 0.56274862, 2695.969575 -0.25, 21000, 0.873917925, 8640.355591, 0.843707455, 2920.633706 -0.25, 21000, 0.941142381, 10913.26877, 1.116978184, 3145.297838 -0.25, 24000, 0, 273.6050697, 0.076001408, 0 -0.25, 24000, 0.393622554, -2952.860239, -0.301910636, 1315.486575 -0.25, 24000, 0.459226313, -1723.222149, -0.169730898, 1534.734338 -0.25, 24000, 0.524830072, -493.5766648, -0.037551651, 1753.9821 -0.25, 24000, 0.590433831, 736.0576992, 0.094627238, 1973.229862 -0.25, 24000, 0.65603759, 2177.825567, 0.234157235, 2192.477625 -0.25, 24000, 0.721641349, 3940.251372, 0.387866528, 2411.725388 -0.25, 24000, 0.787245108, 5493.754078, 0.523429766, 2630.97315 -0.25, 24000, 0.852848867, 7527.949517, 0.674926143, 2850.220913 -0.25, 24000, 0.918452626, 9093.743861, 0.881700531, 3069.468675 -0.25, 24000, 0.984056385, 11241.58473, 1.173056428, 3288.716437 -0.25, 27000, 0, 242.9178931, 0.067477193, 0 -0.25, 27000, 0.383899282, 2648.044817, 0.56738301, 1282.9914 -0.25, 27000, 0.447882496, 2150.752682, 0.464740462, 1496.8233 -0.25, 27000, 0.511865709, 1653.439536, 0.362093831, 1710.6552 -0.25, 27000, 0.575848923, 1156.131517, 0.2594472, 1924.4871 -0.25, 27000, 0.639832136, 736.4785144, 0.150525669, 2138.319 -0.25, 27000, 0.70381535, 2861.175466, 0.24804555, 2352.1509 -0.25, 27000, 0.767798564, 4078.600439, 0.363657771, 2565.9828 -0.25, 27000, 0.831781777, 4904.71726, 0.589741131, 2779.8147 -0.25, 27000, 0.895764991, 8505.261613, 0.778558895, 2993.6466 -0.25, 27000, 0.959748205, 7543.39383, 0.979169818, 3207.4785 -0.25, 30000, 0, 215.016188, 0.059726719, 0 -0.25, 30000, 0.374175101, -1570.5171, 0.000185194, 1250.493188 -0.25, 30000, 0.436537618, -490.5171, 0.053602889, 1458.908719 -0.25, 30000, 0.498900135, 589.3328, 0.107033389, 1667.32425 -0.25, 30000, 0.561262651, 1669.2588, 0.160456306, 1875.739781 -0.25, 30000, 0.623625168, 2115.1277, 0.143305806, 2084.155313 -0.25, 30000, 0.685987685, 1327.4259, 0.198765278, 2292.570844 -0.25, 30000, 0.748350202, 2918.6279, 0.241277056, 2500.986375 -0.25, 30000, 0.810712719, 4513.8534, 0.273259139, 2709.401906 -0.25, 30000, 0.873075236, 8104.4908, 0.910544833, 2917.817438 -0.25, 30000, 0.935437752, 13003.6936, 1.006231556, 3126.232969 -0.25, 30000, 0.997800269, 21020.044, 1.722682611, 3334.6485 -0.25, 33000, 0, 189.7081022, 0.052696695, 0 -0.25, 33000, 0.364451829, 15564.81097, 0.422773354, 1217.998013 -0.25, 33000, 0.4251938, 12361.80072, 0.346185874, 1420.997681 -0.25, 33000, 0.485935772, 9158.75679, 0.269597486, 1623.99735 -0.25, 33000, 0.546677743, 5955.70567, 0.193016694, 1826.997019 -0.25, 33000, 0.607419715, 2752.636903, 0.116421618, 2029.996688 -0.25, 33000, 0.668161686, 745.7704504, 0.119629965, 2232.996356 -0.25, 33000, 0.728903658, 4855.080586, 0.517735554, 2435.996025 -0.25, 33000, 0.789645629, 5511.795231, 0.546568694, 2638.995694 -0.25, 33000, 0.850387601, 3148.746062, 0.191540646, 2841.995363 -0.25, 33000, 0.911129572, 5335.20289, 0.562441851, 3044.995031 -0.25, 33000, 0.971871544, -9227.630858, -2.040485315, 3247.9947 -0.25, 36000, 0, 166.813415, 0.04633706, 0 -0.25, 36000, 0.354727648, 14231.1661, 0.275307444, 1185.4998 -0.25, 36000, 0.413848923, 11432.8705, 0.249783778, 1383.0831 -0.25, 36000, 0.472970197, 8634.491, 0.224260111, 1580.6664 -0.25, 36000, 0.532091472, 5836.1794, 0.198738778, 1778.2497 -0.25, 36000, 0.591212747, 3037.8363, 0.173207361, 1975.833 -0.25, 36000, 0.650334022, 1255.524, 0.143414611, 2173.4163 -0.25, 36000, 0.709455296, 1674.2107, 0.167024167, 2370.9996 -0.25, 36000, 0.768576571, -3033.5286, 0.035916972, 2568.5829 -0.25, 36000, 0.827697846, 14759.7112, 1.04080625, 2766.1662 -0.25, 36000, 0.88681912, 8234.6602, 0.863449472, 2963.7495 -0.25, 36000, 0.945940395, -2234.6613, -1.157128528, 3161.3328 -0.25, 39000, 0, 144.4730235, 0.040131395, 0 -0.25, 39000, 0.354438622, -613.9023, -0.069553917, 1184.533875 -0.25, 39000, 0.413511726, -538.8967, -0.045236389, 1381.956188 -0.25, 39000, 0.472584829, -463.9568, -0.020917861, 1579.3785 -0.25, 39000, 0.531657933, -388.9685, 0.003406083, 1776.800813 -0.25, 39000, 0.590731037, -314.0237, 0.027726944, 1974.223125 -0.25, 39000, 0.64980414, -462.3192, 0.030360861, 2171.645438 -0.25, 39000, 0.708877244, 1101.6042, 0.128541917, 2369.06775 -0.25, 39000, 0.767950348, 621.6528, 0.066692028, 2566.490063 -0.25, 39000, 0.827023452, 4402.2255, -0.030549611, 2763.912375 -0.25, 39000, 0.886096555, 6220.2243, 0.654950028, 2961.334688 -0.25, 39000, 0.945169659, 31915.8646, 4.928862667, 3158.757 -0.25, 42000, 0, 125.0736114, 0.03474267, 0 -0.25, 42000, 0.354438622, -146187.7459, -15.58017019, 1184.533875 -0.25, 42000, 0.413511726, -114664.944, -12.19171195, 1381.956188 -0.25, 42000, 0.472584829, -83142.16449, -8.803250054, 1579.3785 -0.25, 42000, 0.531657933, -51619.42711, -5.414782845, 1776.800813 -0.25, 42000, 0.590731037, -20096.65255, -2.026333845, 1974.223125 -0.25, 42000, 0.64980414, -4695.918744, -0.415694229, 2171.645438 -0.25, 42000, 0.708877244, 3503.832012, 0.188783832, 2369.06775 -0.25, 42000, 0.767950348, -1973.981619, 0.126831375, 2566.490063 -0.25, 42000, 0.827023452, 9186.537113, 1.324876635, 2763.912375 -0.25, 42000, 0.886096555, -312.321925, -0.053114312, 2961.334688 -0.25, 42000, 0.945169659, 10432.98827, 1.836175306, 3158.757 -0.3, 0, 0, 655.639126, 0.182121979, 0 -0.3, 0, 0.473973124, -1722.0547, -0.010125361, 1584.01818 -0.3, 0, 0.552968645, 377.0143, 0.178320917, 1848.02121 -0.3, 0, 0.631964165, 2476.0833, 0.366767194, 2112.02424 -0.3, 0, 0.710959686, 4891.3193, 0.575012139, 2376.02727 -0.3, 0, 0.789955206, 7905.7783, 0.866140806, 2640.0303 -0.3, 0, 0.868950727, 11771.3408, 1.264857444, 2904.03333 -0.3, 0, 0.947946248, 17009.0371, 1.8165785, 3168.03636 -0.3, 3000, 0, 593.7674678, 0.164935408, 0 -0.3, 3000, 0.464197034, -1974.312731, -0.034182079, 1551.346488 -0.3, 3000, 0.541563206, 44.41065904, 0.139861888, 1809.904236 -0.3, 3000, 0.618929379, 2063.134096, 0.313905886, 2068.461984 -0.3, 3000, 0.696295551, 4178.625498, 0.498813061, 2327.019732 -0.3, 3000, 0.773661724, 6845.890953, 0.749626668, 2585.57748 -0.3, 3000, 0.851027896, 10288.90866, 1.096298443, 2844.135228 -0.3, 3000, 0.928394068, 14955.4164, 1.572854199, 3102.692976 -0.3, 6000, 0, 536.6009961, 0.149055832, 0 -0.3, 6000, 0.454420031, -2198.439, -0.05655975, 1518.671742 -0.3, 6000, 0.530156702, -298.3211, 0.103942167, 1771.783699 -0.3, 6000, 0.605893374, 1601.7966, 0.264444111, 2024.895656 -0.3, 6000, 0.681630046, 3532.9443, 0.428840389, 2278.007613 -0.3, 6000, 0.757366718, 5889.292, 0.647430889, 2531.11957 -0.3, 6000, 0.833103389, 8909.5371, 0.945971944, 2784.231527 -0.3, 6000, 0.908840061, 13001.7412, 1.360173194, 3037.343484 -0.3, 6000, 0.984576733, 18010.1348, 1.879118528, 3290.455441 -0.3, 9000, 0, 483.8728627, 0.134409129, 0 -0.3, 9000, 0.444643941, -2330.1484, -0.080601194, 1486.00005 -0.3, 9000, 0.518751264, -563.7825, 0.068325639, 1733.666725 -0.3, 9000, 0.592858588, 1202.5834, 0.217252472, 1981.3334 -0.3, 9000, 0.666965911, 2968.9492, 0.366179306, 2229.000075 -0.3, 9000, 0.741073235, 5040.5698, 0.554967917, 2476.66675 -0.3, 9000, 0.815180558, 7692.8052, 0.81377625, 2724.333425 -0.3, 9000, 0.889287882, 11181.0693, 1.166145167, 2972.0001 -0.3, 9000, 0.963395205, 15576.6582, 1.617282583, 3219.666775 -0.3, 12000, 0, 435.3212253, 0.120922563, 0 -0.3, 12000, 0.434866937, -2163.181591, -0.08306474, 1453.325304 -0.3, 12000, 0.50734476, -609.0475616, 0.048817747, 1695.546188 -0.3, 12000, 0.579822583, 945.0864592, 0.180700254, 1937.767072 -0.3, 12000, 0.652300406, 2499.220428, 0.312582729, 2179.987956 -0.3, 12000, 0.724778229, 4287.446582, 0.471884711, 2422.20884 -0.3, 12000, 0.797256051, 6603.436107, 0.693440863, 2664.429724 -0.3, 12000, 0.869733874, 9629.066372, 0.992908385, 2906.650608 -0.3, 12000, 0.942211697, 13412.54378, 1.378853579, 3148.871492 -0.3, 15000, 0, 390.7010687, 0.108528075, 0 -0.3, 15000, 0.425090847, -2067.99, -0.083616306, 1420.653612 -0.3, 15000, 0.495939322, -682.3344, 0.032977139, 1657.429214 -0.3, 15000, 0.566787797, 703.3211, 0.149570583, 1894.204816 -0.3, 15000, 0.637636271, 2088.9766, 0.266164028, 2130.980418 -0.3, 15000, 0.708484746, 3634.7192, 0.4007375, 2367.75602 -0.3, 15000, 0.77933322, 5630.0859, 0.587231861, 2604.531622 -0.3, 15000, 0.850181695, 8242.3027, 0.84377475, 2841.307224 -0.3, 15000, 0.921030169, 11505.2139, 1.169619806, 3078.082826 -0.3, 15000, 0.991878644, 15085.6113, 1.5599825, 3314.858428 -0.3, 18000, 0, 349.7741477, 0.097159485, 0 -0.3, 18000, 0.415313844, -2535.845225, -0.117126901, 1387.978866 -0.3, 18000, 0.484532818, -1142.685894, -0.004586104, 1619.308677 -0.3, 18000, 0.553751792, 250.4747576, 0.107954314, 1850.638488 -0.3, 18000, 0.622970766, 1643.635298, 0.22049487, 2081.968299 -0.3, 18000, 0.69218974, 3020.542691, 0.338494653, 2313.29811 -0.3, 18000, 0.761408714, 4740.696945, 0.495957323, 2544.627921 -0.3, 18000, 0.830627688, 7007.721978, 0.708543959, 2775.957732 -0.3, 18000, 0.899846662, 9594.321162, 0.978366319, 3007.287543 -0.3, 18000, 0.969065636, 13289.14215, 1.346090623, 3238.617354 -0.3, 21000, 0, 312.3094216, 0.086752617, 0 -0.3, 21000, 0.405537754, -2082.715746, -0.070864142, 1355.307174 -0.3, 21000, 0.47312738, -920.1372992, 0.016713592, 1581.191703 -0.3, 21000, 0.540717005, 242.4437912, 0.104291462, 1807.076232 -0.3, 21000, 0.608306631, 1405.023723, 0.191868665, 2032.960761 -0.3, 21000, 0.675896257, 2570.142629, 0.284177072, 2258.84529 -0.3, 21000, 0.743485882, 3853.675285, 0.412718304, 2484.729819 -0.3, 21000, 0.811075508, 5876.036059, 0.59407747, 2710.614348 -0.3, 21000, 0.878665134, 8462.327223, 0.853401785, 2936.498877 -0.3, 21000, 0.946254759, 10776.64865, 1.130295223, 3162.383406 -0.3, 24000, 0, 278.0880832, 0.07724669, 0 -0.3, 24000, 0.39576075, -2751.815967, -0.223357374, 1322.632428 -0.3, 24000, 0.461720876, -1568.087101, -0.108463505, 1543.071166 -0.3, 24000, 0.527681001, -384.3544368, 0.006430128, 1763.509904 -0.3, 24000, 0.593641126, 799.3725272, 0.121323536, 1983.948642 -0.3, 24000, 0.659601251, 2065.186155, 0.23755934, 2204.38738 -0.3, 24000, 0.725561376, 3656.178712, 0.377569066, 2424.826118 -0.3, 24000, 0.791521501, 5282.565414, 0.525802708, 2645.264856 -0.3, 24000, 0.857481626, 7268.699249, 0.700081232, 2865.703594 -0.3, 24000, 0.923441751, 9125.918173, 0.92634787, 3086.142332 -0.3, 24000, 0.989401876, 11237.83543, 1.209427452, 3306.58107 -0.3, 27000, 0, 246.8980978, 0.068582805, 0 -0.3, 27000, 0.385984661, 414.1757888, 0.264132232, 1289.960736 -0.3, 27000, 0.450315437, 572.1774784, 0.242457444, 1504.954192 -0.3, 27000, 0.514646214, 730.166756, 0.220780187, 1719.947648 -0.3, 27000, 0.578976991, 888.1591888, 0.19910293, 1934.941104 -0.3, 27000, 0.643307768, 1105.41813, 0.175541519, 2149.93456 -0.3, 27000, 0.707638545, 2793.542882, 0.272505035, 2364.928016 -0.3, 27000, 0.771969321, 4150.088707, 0.400720682, 2579.921472 -0.3, 27000, 0.836300098, 5349.26488, 0.60447789, 2794.914928 -0.3, 27000, 0.900630875, 8251.826325, 0.802055624, 3009.908384 -0.3, 27000, 0.964961652, 8297.254474, 1.00845087, 3224.90184 -0.3, 30000, 0, 218.5392239, 0.06070534, 0 -0.3, 30000, 0.376207657, -1784.8838, -0.053268194, 1257.28599 -0.3, 30000, 0.438908933, -783.396, 0.009829083, 1466.833655 -0.3, 30000, 0.501610209, 217.9944, 0.072934556, 1676.38132 -0.3, 30000, 0.564311486, 1219.4339, 0.136035139, 1885.928985 -0.3, 30000, 0.627012762, 1824.5881, 0.155027583, 2095.47665 -0.3, 30000, 0.689714038, 1602.285, 0.217057528, 2305.024315 -0.3, 30000, 0.752415314, 3107.913, 0.28902175, 2514.57198 -0.3, 30000, 0.81511659, 4681.3041, 0.365517083, 2724.119645 -0.3, 30000, 0.877817867, 7543.2601, 0.837570194, 2933.66731 -0.3, 30000, 0.940519143, 11314.8458, 0.988895944, 3143.214975 -0.3, 33000, 0, 192.8164656, 0.053560129, 0 -0.3, 33000, 0.366431567, 9700.131358, 0.230328523, 1224.614298 -0.3, 33000, 0.427503495, 7807.481457, 0.203160348, 1428.716681 -0.3, 33000, 0.488575423, 5914.808338, 0.175991477, 1632.819064 -0.3, 33000, 0.549647351, 4022.130538, 0.148827718, 1836.921447 -0.3, 33000, 0.610719279, 2129.440867, 0.121654432, 2041.02383 -0.3, 33000, 0.671791207, 1080.771898, 0.15167688, 2245.126213 -0.3, 33000, 0.732863135, 4174.890078, 0.449453202, 2449.228596 -0.3, 33000, 0.793935063, 5053.575195, 0.510495961, 2653.330979 -0.3, 33000, 0.85500699, 4000.584694, 0.332410132, 2857.433362 -0.3, 33000, 0.916078918, 5662.175238, 0.603842111, 3061.535745 -0.3, 33000, 0.977150846, -4247.11627, -1.169366767, 3265.638128 -0.3, 36000, 0, 169.5466494, 0.047096291, 0 -0.3, 36000, 0.356654564, 8679.7577, 0.127454889, 1191.939552 -0.3, 36000, 0.416096991, 7054.4058, 0.132295333, 1390.596144 -0.3, 36000, 0.475539418, 5428.9973, 0.137135778, 1589.252736 -0.3, 36000, 0.534981846, 3803.6349, 0.141977778, 1787.909328 -0.3, 36000, 0.594424273, 2178.2509, 0.146813, 1986.56592 -0.3, 36000, 0.6538667, 1238.9082, 0.148544972, 2185.222512 -0.3, 36000, 0.713309127, 1781.8011, 0.189145861, 2383.879104 -0.3, 36000, 0.772751555, -1039.8503, 0.136427806, 2582.535696 -0.3, 36000, 0.832193982, 11436.2011, 0.85484775, 2781.192288 -0.3, 36000, 0.891636409, 7389.0535, 0.797193278, 2979.84888 -0.3, 36000, 0.951078837, 140.793, -0.584887222, 3178.505472 -0.3, 39000, 0, 146.8402111, 0.040788948, 0 -0.3, 39000, 0.356363968, -859.5542, -0.084351278, 1190.96838 -0.3, 39000, 0.415757962, -670.8478, -0.052413611, 1389.46311 -0.3, 39000, 0.475151957, -482.1849, -0.020475167, 1587.95784 -0.3, 39000, 0.534545952, -293.4891, 0.011466944, 1786.45257 -0.3, 39000, 0.593939946, -104.8233, 0.043406944, 1984.9473 -0.3, 39000, 0.653333941, -61.3595, 0.05899, 2183.44203 -0.3, 39000, 0.712727935, 1253.6144, 0.148422278, 2381.93676 -0.3, 39000, 0.77212193, 1227.6942, 0.138161722, 2580.43149 -0.3, 39000, 0.831515925, 4155.6313, 0.102885611, 2778.92622 -0.3, 39000, 0.890909919, 5658.3998, 0.610096528, 2977.42095 -0.3, 39000, 0.950303914, 22985.3821, 3.503535278, 3175.91568 -0.3, 42000, 0, 127.12294, 0.035311928, 0 -0.3, 42000, 0.356363968, -109083.0735, -11.6102422, 1190.96838 -0.3, 42000, 0.415757962, -85544.63034, -9.081878993, 1389.46311 -0.3, 42000, 0.475151957, -62006.20249, -6.553513217, 1587.95784 -0.3, 42000, 0.534545952, -38467.80599, -4.025143516, 1786.45257 -0.3, 42000, 0.593939946, -14929.38217, -1.496787036, 1984.9473 -0.3, 42000, 0.653333941, -3248.578356, -0.274201653, 2183.44203 -0.3, 42000, 0.712727935, 2856.081962, 0.182677363, 2381.93676 -0.3, 42000, 0.77212193, -864.5085062, 0.155125694, 2580.43149 -0.3, 42000, 0.831515925, 7418.437738, 1.047253059, 2778.92622 -0.3, 42000, 0.890909919, 916.166725, 0.099890444, 2977.42095 -0.3, 42000, 0.950303914, 9249.859431, 1.557163799, 3175.91568 -0.35, 0, 0, 668.2783889, 0.185632886, 0 -0.35, 0, 0.476999475, -1643.586825, -0.001802861, 1594.132245 -0.35, 0, 0.556499387, 344.11575, 0.188649417, 1859.820952 -0.35, 0, 0.6359993, 2331.818225, 0.379101694, 2125.50966 -0.35, 0, 0.715499212, 4733.674175, 0.594476917, 2391.198367 -0.35, 0, 0.794999125, 7815.084525, 0.898406757, 2656.887075 -0.35, 0, 0.874499037, 11600.2117, 1.312975715, 2922.575782 -0.35, 0, 0.95399895, 16641.5439, 1.878258875, 3188.26449 -0.35, 3000, 0, 605.2139828, 0.168114995, 0 -0.35, 3000, 0.467160964, -1893.548064, -0.026856587, 1561.251942 -0.35, 3000, 0.545021125, 35.55024367, 0.149456686, 1821.460599 -0.35, 3000, 0.622881285, 1964.648551, 0.325769968, 2081.669256 -0.35, 3000, 0.700741446, 4025.642942, 0.515634744, 2341.877913 -0.35, 3000, 0.778601607, 6721.039341, 0.776716766, 2602.08657 -0.35, 3000, 0.856461768, 10200.37397, 1.138877483, 2862.295227 -0.35, 3000, 0.934321928, 14801.45684, 1.634444858, 3122.503884 -0.35, 6000, 0, 546.9454687, 0.151929297, 0 -0.35, 6000, 0.457321534, -2126.1724, -0.050099944, 1528.368566 -0.35, 6000, 0.533541789, -299.722, 0.112614944, 1783.09666 -0.35, 6000, 0.609762045, 1526.7284, 0.275329861, 2037.824754 -0.35, 6000, 0.6859823, 3404.5447, 0.444152556, 2292.552848 -0.35, 6000, 0.762202556, 5790.6606, 0.671905389, 2547.280943 -0.35, 6000, 0.838422812, 8793.25, 0.981022056, 2802.009037 -0.35, 6000, 0.914643067, 12872.8506, 1.412602417, 3056.737131 -0.35, 6000, 0.990863323, 17629.5039, 1.937454556, 3311.465225 -0.35, 9000, 0, 493.2008543, 0.137000237, 0 -0.35, 9000, 0.447483023, -2261.0547, -0.07561725, 1495.488263 -0.35, 9000, 0.522063527, -556.4717, 0.075707167, 1744.736306 -0.35, 9000, 0.596644031, 1148.1117, 0.227031611, 1993.98435 -0.35, 9000, 0.671224534, 2852.6951, 0.378356056, 2243.232394 -0.35, 9000, 0.745805038, 4941.8027, 0.575271806, 2492.480438 -0.35, 9000, 0.820385542, 7597.1694, 0.845194167, 2741.728481 -0.35, 9000, 0.894966046, 11125.042, 1.214196222, 2990.976525 -0.35, 9000, 0.96954655, 15347.5615, 1.675828444, 3240.224569 -0.35, 12000, 0, 443.7132495, 0.12325368, 0 -0.35, 12000, 0.437643592, -2276.28064, -0.087693857, 1462.604886 -0.35, 12000, 0.510584191, -720.8462688, 0.049093098, 1706.372367 -0.35, 12000, 0.58352479, 834.5878952, 0.185880041, 1950.139848 -0.35, 12000, 0.656465389, 2390.021947, 0.322666992, 2193.907329 -0.35, 12000, 0.729405987, 4204.66523, 0.49002412, 2437.67481 -0.35, 12000, 0.802346586, 6529.955509, 0.720335245, 2681.442291 -0.35, 12000, 0.875287185, 9575.901432, 1.034997246, 2925.209772 -0.35, 12000, 0.948227784, 13217.24354, 1.429744504, 3168.977253 -0.35, 15000, 0, 398.2329156, 0.110620254, 0 -0.35, 15000, 0.427805082, -2082.4854, -0.083350194, 1429.724583 -0.35, 15000, 0.499105929, -721.9742, 0.036081861, 1668.012014 -0.35, 15000, 0.570406776, 638.5369, 0.155513917, 1906.299444 -0.35, 15000, 0.641707623, 1999.048, 0.274945972, 2144.586875 -0.35, 15000, 0.713008469, 3546.4077, 0.414942806, 2382.874305 -0.35, 15000, 0.784309316, 5564.2183, 0.611034083, 2621.161736 -0.35, 15000, 0.855610163, 8208.3291, 0.878891389, 2859.449166 -0.35, 15000, 0.92691101, 11334.8574, 1.212288806, 3097.736597 -0.35, 15000, 0.998211857, 14750.1221, 1.602944889, 3336.024027 -0.35, 18000, 0, 356.5170147, 0.099032504, 0 -0.35, 18000, 0.417965651, -2124.355273, -0.094226863, 1396.841206 -0.35, 18000, 0.487626593, -872.7657096, 0.014548692, 1629.648074 -0.35, 18000, 0.557287535, 378.8240536, 0.123324218, 1862.454942 -0.35, 18000, 0.626948477, 1630.413794, 0.232099782, 2095.26181 -0.35, 18000, 0.696609419, 2987.255863, 0.352499976, 2328.068678 -0.35, 18000, 0.766270361, 4735.313553, 0.517954373, 2560.875545 -0.35, 18000, 0.835931303, 7006.297562, 0.744049192, 2793.682413 -0.35, 18000, 0.905592244, 9695.005226, 1.027963597, 3026.489281 -0.35, 18000, 0.975253186, 12807.58823, 1.388108299, 3259.296148 -0.35, 21000, 0, 318.330052, 0.088425014, 0 -0.35, 21000, 0.40812714, -2145.93367, -0.095135556, 1363.960904 -0.35, 21000, 0.476148331, -995.5710112, 0.001449063, 1591.287721 -0.35, 21000, 0.544169521, 154.7925632, 0.098033721, 1818.614538 -0.35, 21000, 0.612190711, 1305.155935, 0.194618155, 2045.941355 -0.35, 21000, 0.680211901, 2483.338477, 0.29541673, 2273.268173 -0.35, 21000, 0.748233091, 3952.541213, 0.435192655, 2500.59499 -0.35, 21000, 0.816254281, 5919.786531, 0.625449653, 2727.921807 -0.35, 21000, 0.884275471, 8355.876435, 0.876378565, 2955.248624 -0.35, 21000, 0.952296661, 10728.88976, 1.16435854, 3182.575442 -0.35, 24000, 0, 283.4490024, 0.078735834, 0 -0.35, 24000, 0.39828771, -2517.137975, -0.168005919, 1331.077527 -0.35, 24000, 0.464668995, -1393.832673, -0.064563039, 1552.923782 -0.35, 24000, 0.53105028, -270.5258288, 0.038879752, 1774.770036 -0.35, 24000, 0.597431565, 852.7786352, 0.142322422, 1996.61629 -0.35, 24000, 0.66381285, 1990.071023, 0.244468877, 2218.462545 -0.35, 24000, 0.730194135, 3463.433552, 0.377097315, 2440.308799 -0.35, 24000, 0.79657542, 5147.19841, 0.536660156, 2662.155054 -0.35, 24000, 0.862956705, 7112.157501, 0.729296738, 2884.001309 -0.35, 24000, 0.92933799, 9140.301505, 0.971459403, 3105.847563 -0.35, 24000, 0.995719275, 11189.68233, 1.248432292, 3327.693817 -0.35, 27000, 0, 251.6577435, 0.069904929, 0 -0.35, 27000, 0.388449199, -1015.777419, 0.063235371, 1298.197224 -0.35, 27000, 0.453190732, -436.1124656, 0.096077014, 1514.563428 -0.35, 27000, 0.517932266, 143.545976, 0.12891732, 1730.929632 -0.35, 27000, 0.582673799, 723.2061808, 0.161757626, 1947.295836 -0.35, 27000, 0.647415332, 1342.332106, 0.194797924, 2163.66204 -0.35, 27000, 0.712156865, 2745.677358, 0.293930682, 2380.028244 -0.35, 27000, 0.776898399, 4192.823055, 0.432062121, 2596.394448 -0.35, 27000, 0.841639932, 5650.7919, 0.623576488, 2812.760652 -0.35, 27000, 0.906381465, 8063.762257, 0.829996392, 3029.126856 -0.35, 27000, 0.971122998, 8817.193858, 1.045704944, 3245.49306 -0.35, 30000, 0, 222.7521736, 0.061875604, 0 -0.35, 30000, 0.378609769, -1945.5682, -0.091375944, 1265.313848 -0.35, 30000, 0.441711397, -1002.0784, -0.020858583, 1476.199489 -0.35, 30000, 0.504813025, -58.6472, 0.049663611, 1687.08513 -0.35, 30000, 0.567914653, 884.8133, 0.120182889, 1897.970771 -0.35, 30000, 0.631016281, 1601.8254, 0.165497722, 2108.856413 -0.35, 30000, 0.69411791, 1813.3706, 0.234766611, 2319.742054 -0.35, 30000, 0.757219538, 3250.7934, 0.32934, 2530.627695 -0.35, 30000, 0.820321166, 4812.2894, 0.440080028, 2741.513336 -0.35, 30000, 0.883422794, 7143.2303, 0.793486472, 2952.398978 -0.35, 30000, 0.946524422, 10041.4004, 0.981365861, 3163.284619 -0.35, 33000, 0, 196.5335379, 0.054592649, 0 -0.35, 33000, 0.368771258, 5267.119386, 0.085462703, 1232.433545 -0.35, 33000, 0.430233134, 4365.808573, 0.096085167, 1437.839135 -0.35, 33000, 0.491695011, 3464.482626, 0.106707118, 1643.244726 -0.35, 33000, 0.553156887, 2563.153846, 0.117332302, 1848.650317 -0.35, 33000, 0.614618763, 1661.817551, 0.127951534, 2054.055908 -0.35, 33000, 0.67608064, 1331.452586, 0.178086512, 2259.461498 -0.35, 33000, 0.737542516, 3665.19113, 0.401898262, 2464.867089 -0.35, 33000, 0.799004393, 4714.719579, 0.489346311, 2670.27268 -0.35, 33000, 0.860466269, 4635.346686, 0.444140906, 2875.678271 -0.35, 33000, 0.921928145, 5954.983826, 0.651575144, 3081.083861 -0.35, 33000, 0.983390022, -306.6352416, -0.470790342, 3286.489452 -0.35, 36000, 0, 172.8151314, 0.048004203, 0 -0.35, 36000, 0.358931828, 4510.2403, 0.016301417, 1199.550168 -0.35, 36000, 0.418753799, 3767.0561, 0.044492417, 1399.475196 -0.35, 36000, 0.47857577, 3023.836, 0.072683417, 1599.400224 -0.35, 36000, 0.538397741, 2280.6454, 0.100875389, 1799.325252 -0.35, 36000, 0.598219713, 1537.4408, 0.129063083, 1999.25028 -0.35, 36000, 0.658041684, 1231.5361, 0.155201556, 2199.175308 -0.35, 36000, 0.717863655, 1878.8639, 0.210161028, 2399.100336 -0.35, 36000, 0.777685627, 494.8921, 0.218196306, 2599.025364 -0.35, 36000, 0.837507598, 8917.5342, 0.721212083, 2798.950392 -0.35, 36000, 0.897329569, 6736.4009, 0.750497639, 2998.87542 -0.35, 36000, 0.95715154, 1987.7442, -0.139675056, 3198.800448 -0.35, 39000, 0, 149.6709635, 0.041575268, 0 -0.35, 39000, 0.358639376, -1099.8343, -0.097703722, 1198.572795 -0.35, 39000, 0.418412605, -812.4277, -0.059168139, 1398.334928 -0.35, 39000, 0.478185835, -525.048, -0.020631972, 1598.09706 -0.35, 39000, 0.537959064, -237.6472, 0.017906528, 1797.859193 -0.35, 39000, 0.597732294, 49.734, 0.056443667, 1997.621325 -0.35, 39000, 0.657505523, 252.761, 0.083445528, 2197.383458 -0.35, 39000, 0.717278752, 1379.7404, 0.167062278, 2397.14559 -0.35, 39000, 0.777051982, 1707.1214, 0.19681825, 2596.907723 -0.35, 39000, 0.836825211, 3977.5118, 0.211199222, 2796.669855 -0.35, 39000, 0.89659844, 5244.9258, 0.582929556, 2996.431988 -0.35, 39000, 0.95637167, 16269.0825, 2.434506472, 3196.19412 -0.35, 42000, 0, 129.5735873, 0.035992663, 0 -0.35, 42000, 0.358639376, -78983.18996, -8.39115416, 1198.572795 -0.35, 42000, 0.418412605, -61921.36514, -6.55975309, 1398.334928 -0.35, 42000, 0.478185835, -44859.55019, -4.728350311, 1598.09706 -0.35, 42000, 0.537959064, -27797.75776, -2.896944727, 1797.859193 -0.35, 42000, 0.597732294, -10735.946, -1.06554838, 1997.621325 -0.35, 42000, 0.657505523, -2092.492319, -0.159838632, 2197.383458 -0.35, 42000, 0.717278752, 2346.460612, 0.179430214, 2397.14559 -0.35, 42000, 0.777051982, 28.35945625, 0.181462903, 2596.907723 -0.35, 42000, 0.836825211, 6023.070463, 0.830610233, 2796.669855 -0.35, 42000, 0.89659844, 1882.389175, 0.223785313, 2996.431988 -0.35, 42000, 0.95637167, 8216.781544, 1.325066903, 3196.19412 -0.4, 0, 0, 683.0627788, 0.189739661, 0 -0.4, 0, 0.480491418, -1668.094, 0.00594875, 1605.80232 -0.4, 0, 0.560573321, 256.0642, 0.19942025, 1873.43604 -0.4, 0, 0.640655224, 2180.2224, 0.392891778, 2141.06976 -0.4, 0, 0.720737127, 4596.5879, 0.617221, 2408.70348 -0.4, 0, 0.800819031, 7693.731, 0.9343065, 2676.3372 -0.4, 0, 0.880900934, 11317.4688, 1.365360778, 2943.97092 -0.4, 0, 0.960982837, 16269.1504, 1.946704361, 3211.60464 -0.4, 3000, 0, 618.6031925, 0.17183422, 0 -0.4, 3000, 0.470580883, -1854.571478, -0.018910569, 1572.681312 -0.4, 3000, 0.549011031, 9.847154042, 0.160051289, 1834.794864 -0.4, 3000, 0.627441178, 1874.265553, 0.339013111, 2096.908416 -0.4, 3000, 0.705871325, 3895.908966, 0.534729947, 2359.021968 -0.4, 3000, 0.784301472, 6609.737413, 0.808319268, 2621.13552 -0.4, 3000, 0.862731619, 10118.8069, 1.185766282, 2883.249072 -0.4, 3000, 0.941161767, 14841.29332, 1.709321597, 3145.362624 -0.4, 6000, 0, 559.0455983, 0.155290444, 0 -0.4, 6000, 0.460669422, -2030.2659, -0.042719167, 1539.557208 -0.4, 6000, 0.537447659, -276.7292, 0.12257425, 1796.150076 -0.4, 6000, 0.614225896, 1476.8074, 0.287867694, 2052.742944 -0.4, 6000, 0.691004133, 3306.418, 0.461854778, 2309.335812 -0.4, 6000, 0.76778237, 5690.1733, 0.698585333, 2565.92868 -0.4, 6000, 0.844560607, 8775.8955, 1.024996278, 2822.521548 -0.4, 6000, 0.921338844, 12875.9385, 1.475617278, 3079.114416 -0.4, 6000, 0.998117081, 17540.9219, 2.013968917, 3335.707284 -0.4, 9000, 0, 504.1119864, 0.140031107, 0 -0.4, 9000, 0.450758887, -2206.7393, -0.070115, 1506.4362 -0.4, 9000, 0.525885368, -551.2397, 0.084044194, 1757.5089 -0.4, 9000, 0.601011849, 1104.2596, 0.238203389, 2008.5816 -0.4, 9000, 0.67613833, 2770.1294, 0.39364475, 2259.6543 -0.4, 9000, 0.751264811, 4862.4082, 0.598960222, 2510.727 -0.4, 9000, 0.826391293, 7573.5854, 0.881797889, 2761.7997 -0.4, 9000, 0.901517774, 11153.2451, 1.270475389, 3012.8724 -0.4, 9000, 0.976644255, 15268.127, 1.746059694, 3263.9451 -0.4, 12000, 0, 453.5295623, 0.125980434, 0 -0.4, 12000, 0.440847425, -2305.549204, -0.088986, 1473.312096 -0.4, 12000, 0.514321996, -768.8100288, 0.052269705, 1718.864112 -0.4, 12000, 0.587796567, 767.9290016, 0.193525381, 1964.416128 -0.4, 12000, 0.661271138, 2304.667966, 0.334781094, 2209.968144 -0.4, 12000, 0.734745709, 4138.79025, 0.510626022, 2455.52016 -0.4, 12000, 0.80822028, 6506.763994, 0.75200744, 2701.072176 -0.4, 12000, 0.881694851, 9608.208798, 1.083619777, 2946.624192 -0.4, 12000, 0.955169422, 13166.09293, 1.491775536, 3192.176208 -0.4, 15000, 0, 407.0430624, 0.113067517, 0 -0.4, 15000, 0.43093689, -2148.7402, -0.086987222, 1440.191088 -0.4, 15000, 0.502759706, -795.1206, 0.036871667, 1680.222936 -0.4, 15000, 0.574582521, 558.4993, 0.160730583, 1920.254784 -0.4, 15000, 0.646405336, 1912.1191, 0.284589472, 2160.286632 -0.4, 15000, 0.718228151, 3473.2656, 0.431054278, 2400.31848 -0.4, 15000, 0.790050966, 5553.7173, 0.638897778, 2640.350328 -0.4, 15000, 0.861873781, 8221.8076, 0.919558778, 2880.382176 -0.4, 15000, 0.933696596, 11327.8613, 1.268072361, 3120.414024 -0.4, 18000, 0, 364.4042764, 0.10122341, 0 -0.4, 18000, 0.421025429, -2004.833241, -0.087000758, 1407.066984 -0.4, 18000, 0.491196334, -808.2493656, 0.0227228, 1641.578148 -0.4, 18000, 0.561367239, 388.3344896, 0.132446393, 1876.089312 -0.4, 18000, 0.631538144, 1584.91843, 0.242169988, 2110.600476 -0.4, 18000, 0.701709048, 2934.351315, 0.367010983, 2345.11164 -0.4, 18000, 0.771879953, 4714.471881, 0.540561646, 2579.622804 -0.4, 18000, 0.842050858, 7037.441006, 0.780997463, 2814.133968 -0.4, 18000, 0.912221763, 9730.41295, 1.077317208, 3048.645132 -0.4, 18000, 0.982392668, 12651.10241, 1.443719098, 3283.156296 -0.4, 21000, 0, 325.3724998, 0.09038125, 0 -0.4, 21000, 0.411114894, -2090.576454, -0.100792354, 1373.945976 -0.4, 21000, 0.479634043, -975.6670032, 2.53227E-05, 1602.936972 -0.4, 21000, 0.548153192, 139.2426152, 0.100843002, 1831.927968 -0.4, 21000, 0.616672341, 1254.152327, 0.201660662, 2060.918964 -0.4, 21000, 0.68519149, 2425.448145, 0.308338227, 2289.90996 -0.4, 21000, 0.753710639, 3981.107461, 0.456705995, 2518.900956 -0.4, 21000, 0.822229788, 5964.462583, 0.657868503, 2747.891952 -0.4, 21000, 0.890748937, 8313.523827, 0.910839711, 2976.882948 -0.4, 21000, 0.959268086, 10752.89742, 1.215092301, 3205.873944 -0.4, 24000, 0, 289.7197731, 0.080477715, 0 -0.4, 24000, 0.401203433, -2282.463163, -0.131948491, 1340.821872 -0.4, 24000, 0.468070671, -1223.719465, -0.035020252, 1564.292184 -0.4, 24000, 0.53493791, -164.9754408, 0.061907969, 1787.762496 -0.4, 24000, 0.601805149, 893.7679232, 0.158836148, 2011.232808 -0.4, 24000, 0.668672388, 1945.461571, 0.254433015, 2234.70312 -0.4, 24000, 0.735539627, 3347.273892, 0.384975525, 2458.173432 -0.4, 24000, 0.802406865, 5076.371366, 0.555053387, 2681.643744 -0.4, 24000, 0.869274104, 7042.629873, 0.762927938, 2905.114056 -0.4, 24000, 0.936141343, 9151.862957, 1.018669159, 3128.584368 -0.4, 27000, 0, 257.2251931, 0.071451443, 0 -0.4, 27000, 0.391292898, -1807.253207, -0.055289934, 1307.700864 -0.4, 27000, 0.456508381, -991.7983496, 0.010830728, 1525.651008 -0.4, 27000, 0.521723864, -176.346304, 0.076950787, 1743.601152 -0.4, 27000, 0.586939346, 639.1065928, 0.143070845, 1961.551296 -0.4, 27000, 0.652154829, 1475.571742, 0.209900997, 2179.50144 -0.4, 27000, 0.717370312, 2716.512194, 0.31336899, 2397.451584 -0.4, 27000, 0.782585795, 4217.788883, 0.459656532, 2615.401728 -0.4, 27000, 0.847801278, 5842.67632, 0.64734223, 2833.351872 -0.4, 27000, 0.913016761, 7939.485509, 0.863032087, 3051.302016 -0.4, 27000, 0.978232244, 9155.313682, 1.090457708, 3269.25216 -0.4, 30000, 0, 227.6801423, 0.063244484, 0 -0.4, 30000, 0.381381436, -2055.9148, -0.116296556, 1274.57676 -0.4, 30000, 0.444945009, -1153.926, -0.040269722, 1487.00622 -0.4, 30000, 0.508508582, -251.9688, 0.035759639, 1699.43568 -0.4, 30000, 0.572072154, 650.004, 0.111787444, 1911.86514 -0.4, 30000, 0.635635727, 1438.7529, 0.175213194, 2124.2946 -0.4, 30000, 0.6991993, 1970.8082, 0.252228944, 2336.72406 -0.4, 30000, 0.762762873, 3357.5525, 0.363896528, 2549.15352 -0.4, 30000, 0.826326445, 4915.9938, 0.50041175, 2761.58298 -0.4, 30000, 0.889890018, 6883.965, 0.774896917, 2974.01244 -0.4, 30000, 0.953453591, 9134.1694, 0.984419389, 3186.4419 -0.4, 33000, 0, 200.8814691, 0.055800408, 0 -0.4, 33000, 0.371470901, 2071.918154, -0.018157967, 1241.455752 -0.4, 33000, 0.433382718, 1886.114269, 0.020206053, 1448.365044 -0.4, 33000, 0.495294535, 1700.301254, 0.058569715, 1655.274336 -0.4, 33000, 0.557206352, 1514.486694, 0.096935253, 1862.183628 -0.4, 33000, 0.619118169, 1328.667755, 0.135297397, 2069.09292 -0.4, 33000, 0.681029986, 1511.651614, 0.200032389, 2276.002212 -0.4, 33000, 0.742941803, 3305.173142, 0.372671067, 2482.911504 -0.4, 33000, 0.804853619, 4482.112683, 0.481576967, 2689.820796 -0.4, 33000, 0.866765436, 5088.722438, 0.531788831, 2896.730088 -0.4, 33000, 0.928677253, 6215.402754, 0.704344476, 3103.63938 -0.4, 33000, 0.99058907, 2715.399326, 0.075318239, 3310.548672 -0.4, 36000, 0, 176.6383379, 0.049066205, 0 -0.4, 36000, 0.36155944, 1531.2354, -0.063034, 1208.331648 -0.4, 36000, 0.421819346, 1419.7549, -0.017552222, 1409.720256 -0.4, 36000, 0.482079253, 1308.2535, 0.027929556, 1611.108864 -0.4, 36000, 0.54233916, 1196.7695, 0.073411889, 1812.497472 -0.4, 36000, 0.602599066, 1085.2771, 0.11889175, 2013.88608 -0.4, 36000, 0.662858973, 1233.0795, 0.163363111, 2215.274688 -0.4, 36000, 0.72311888, 1967.394, 0.230465, 2416.663296 -0.4, 36000, 0.783378786, 1633.3106, 0.28414875, 2618.051904 -0.4, 36000, 0.843638693, 7097.6801, 0.633205222, 2819.440512 -0.4, 36000, 0.9038986, 6256.7165, 0.722070917, 3020.82912 -0.4, 36000, 0.964158506, 3384.185, 0.197486556, 3222.217728 -0.4, 39000, 0, 152.9821492, 0.042495041, 0 -0.4, 39000, 0.361264847, -1328.5093, -0.109662778, 1207.34712 -0.4, 39000, 0.421475655, -956.698, -0.065400222, 1408.57164 -0.4, 39000, 0.481686463, -584.9018, -0.02113725, 1609.79616 -0.4, 39000, 0.541897271, -213.0931, 0.023127083, 1811.02068 -0.4, 39000, 0.602108079, 158.7037, 0.067390611, 2012.2452 -0.4, 39000, 0.662318887, 492.2062, 0.104422111, 2213.46972 -0.4, 39000, 0.722529695, 1484.3648, 0.184846861, 2414.69424 -0.4, 39000, 0.782740503, 2077.3499, 0.244777556, 2615.91876 -0.4, 39000, 0.842951311, 3860.6915, 0.298064944, 2817.14328 -0.4, 39000, 0.903162118, 4961.6513, 0.571638222, 3018.3678 -0.4, 39000, 0.963372926, 11464.8255, 1.673850194, 3219.59232 -0.4, 42000, 0, 132.4401568, 0.036788932, 0 -0.4, 42000, 0.361264847, -55155.42354, -5.844057951, 1207.34712 -0.4, 42000, 0.421475655, -43219.89844, -4.563599465, 1408.57164 -0.4, 42000, 0.481686463, -31284.37919, -3.283139918, 1609.79616 -0.4, 42000, 0.541897271, -19348.87544, -2.002678453, 1811.02068 -0.4, 42000, 0.602108079, -7413.358625, -0.722223127, 2012.2452 -0.4, 42000, 0.662318887, -1193.685331, -0.069366556, 2213.46972 -0.4, 42000, 0.722529695, 1960.611162, 0.179057689, 2414.69424 -0.4, 42000, 0.782740503, 730.4577688, 0.206324667, 2615.91876 -0.4, 42000, 0.842951311, 4959.910288, 0.668450767, 2817.14328 -0.4, 42000, 0.903162118, 2620.203425, 0.322650347, 3018.3678 -0.4, 42000, 0.963372926, 7330.556506, 1.136872563, 3219.59232 -0.45, 0, 0, 700.0801798, 0.194466717, 0 -0.45, 0, 0.484448954, -1957.03495, 0.010469556, 1619.028405 -0.45, 0, 0.565190447, 21.9571, 0.209192472, 1888.866472 -0.45, 0, 0.645931939, 2000.94965, 0.4079155, 2158.70454 -0.45, 0, 0.726673431, 4478.61795, 0.643626694, 2428.542607 -0.45, 0, 0.807414924, 7451.70725, 0.972894625, 2698.380675 -0.45, 0, 0.888156416, 10753.2993, 1.418587569, 2968.218742 -0.45, 0, 0.968897908, 15828.844, 2.020614611, 3238.05681 -0.45, 3000, 0, 634.0146875, 0.176115191, 0 -0.45, 3000, 0.474456792, -1796.128351, -0.009656791, 1585.634598 -0.45, 3000, 0.553532924, -4.540111183, 0.172100048, 1849.907031 -0.45, 3000, 0.632609056, 1787.048463, 0.353856939, 2114.179464 -0.45, 3000, 0.711685188, 3770.802263, 0.556152529, 2378.451897 -0.45, 3000, 0.79076132, 6548.778539, 0.844808398, 2642.72433 -0.45, 3000, 0.869837452, 10052.92844, 1.237780894, 2906.996763 -0.45, 3000, 0.948913583, 14817.91134, 1.788330996, 3171.269196 -0.45, 6000, 0, 572.9733124, 0.159159253, 0 -0.45, 6000, 0.464463695, -2049.6963, -0.034723778, 1552.23767 -0.45, 6000, 0.541874311, -324.2031, 0.133557083, 1810.943948 -0.45, 6000, 0.619284927, 1401.2903, 0.301837972, 2069.650226 -0.45, 6000, 0.696695543, 3221.1558, 0.481764583, 2328.356504 -0.45, 6000, 0.774106159, 5625.9209, 0.728638111, 2587.062783 -0.45, 6000, 0.851516775, 8795.0586, 1.074098722, 2845.769061 -0.45, 6000, 0.92892739, 12959.4258, 1.548670111, 3104.475339 -0.45, 9000, 0, 516.6711187, 0.143519755, 0 -0.45, 9000, 0.454471533, -2181.1902, -0.063361861, 1518.843863 -0.45, 9000, 0.530216788, -563.1777, 0.093739472, 1771.984506 -0.45, 9000, 0.605962044, 1054.8347, 0.250840833, 2025.12515 -0.45, 9000, 0.681707299, 2703.8223, 0.411769111, 2278.265794 -0.45, 9000, 0.757452555, 4820.7627, 0.626710611, 2531.406438 -0.45, 9000, 0.83319781, 7577.894, 0.922477222, 2784.547081 -0.45, 9000, 0.908943066, 11215.8232, 1.33200725, 3037.687725 -0.45, 9000, 0.984688321, 15292.7529, 1.824869111, 3290.828369 -0.45, 12000, 0, 464.8285155, 0.129119032, 0 -0.45, 12000, 0.444478436, -2217.08773, -0.082973165, 1485.446934 -0.45, 12000, 0.518558176, -730.553152, 0.061063805, 1733.021423 -0.45, 12000, 0.592637915, 755.981468, 0.205100748, 1980.595912 -0.45, 12000, 0.666717654, 2241.808226, 0.349050319, 2228.170401 -0.45, 12000, 0.740797394, 4085.417782, 0.533444336, 2475.74489 -0.45, 12000, 0.814877133, 6517.659347, 0.788686444, 2723.319379 -0.45, 12000, 0.888956873, 9678.488119, 1.138503023, 2970.893868 -0.45, 12000, 0.963036612, 13226.14387, 1.565523487, 3218.468357 -0.45, 15000, 0, 417.1838799, 0.115884411, 0 -0.45, 15000, 0.434486274, -2248.1765, -0.092781861, 1452.053127 -0.45, 15000, 0.506900653, -885.0414, 0.036834222, 1694.061982 -0.45, 15000, 0.579315032, 478.0937, 0.166450306, 1936.070836 -0.45, 15000, 0.651729411, 1841.2289, 0.296066389, 2178.07969 -0.45, 15000, 0.72414379, 3426.2627, 0.451426722, 2420.088545 -0.45, 15000, 0.796558169, 5560.9507, 0.670015806, 2662.0974 -0.45, 15000, 0.868972548, 8306.4004, 0.967489139, 2904.106254 -0.45, 15000, 0.941386927, 11366.8193, 1.331789694, 3146.115108 -0.45, 18000, 0, 373.4828177, 0.103745227, 0 -0.45, 18000, 0.424493177, -2042.914529, -0.089147532, 1418.656198 -0.45, 18000, 0.49524204, -852.7941616, 0.02457883, 1655.098898 -0.45, 18000, 0.565990903, 337.3263656, 0.138305174, 1891.541598 -0.45, 18000, 0.636739766, 1527.447006, 0.252031517, 2127.984298 -0.45, 18000, 0.707488629, 2879.140647, 0.382820228, 2364.426997 -0.45, 18000, 0.778237492, 4695.796329, 0.565750807, 2600.869697 -0.45, 18000, 0.848986355, 7087.47801, 0.820866634, 2837.312397 -0.45, 18000, 0.919735217, 9753.165534, 1.130133958, 3073.755097 -0.45, 18000, 0.99048408, 12682.64469, 1.509556992, 3310.197796 -0.45, 21000, 0, 333.4786277, 0.092632952, 0 -0.45, 21000, 0.414501015, -1995.245298, -0.096823313, 1385.262392 -0.45, 21000, 0.483584517, -920.2198752, 0.00594051, 1616.139457 -0.45, 21000, 0.55266802, 154.8055472, 0.108704333, 1847.016522 -0.45, 21000, 0.621751522, 1229.830999, 0.211468185, 2077.893587 -0.45, 21000, 0.690835025, 2390.078033, 0.322936674, 2308.770653 -0.45, 21000, 0.759918527, 3971.206429, 0.478637963, 2539.647718 -0.45, 21000, 0.82900203, 6011.445315, 0.692337353, 2770.524783 -0.45, 21000, 0.898085532, 8327.789999, 0.954987141, 3001.401848 -0.45, 21000, 0.967169035, 10831.57691, 1.278420673, 3232.278914 -0.45, 24000, 0, 296.9376712, 0.082482686, 0 -0.45, 24000, 0.404507918, -2081.428431, -0.111277313, 1351.865463 -0.45, 24000, 0.471925905, -1081.008077, -0.016825892, 1577.176374 -0.45, 24000, 0.539343891, -80.5878728, 0.077625532, 1802.487284 -0.45, 24000, 0.606761877, 919.8322912, 0.172076962, 2027.798195 -0.45, 24000, 0.674179864, 1924.339199, 0.26699892, 2253.109105 -0.45, 24000, 0.74159785, 3292.957732, 0.399727946, 2478.420016 -0.45, 24000, 0.809015837, 5058.802582, 0.580033679, 2703.730926 -0.45, 24000, 0.876433823, 7044.421965, 0.80133011, 2929.041837 -0.45, 24000, 0.943851809, 9175.571629, 1.069611164, 3154.352747 -0.45, 27000, 0, 263.6335415, 0.073231539, 0 -0.45, 27000, 0.394515756, -2125.689975, -0.111426046, 1318.471656 -0.45, 27000, 0.460268382, -1212.561374, -0.028049858, 1538.216932 -0.45, 27000, 0.526021008, -299.433584, 0.055326142, 1757.962208 -0.45, 27000, 0.591773634, 613.6945248, 0.138702142, 1977.707484 -0.45, 27000, 0.65752626, 1533.488338, 0.222456847, 2197.45276 -0.45, 27000, 0.723278886, 2704.98069, 0.331866459, 2417.198036 -0.45, 27000, 0.789031512, 4235.971591, 0.48547836, 2636.943312 -0.45, 27000, 0.854784138, 5958.29614, 0.676080422, 2856.688588 -0.45, 27000, 0.920536764, 7877.412181, 0.901813599, 3076.433864 -0.45, 27000, 0.98628939, 9363.715646, 1.142234826, 3296.17914 -0.45, 30000, 0, 233.3524237, 0.064820118, 0 -0.45, 30000, 0.384522659, -2119.2681, -0.130188528, 1285.074728 -0.45, 30000, 0.448609769, -1246.3005, -0.050213944, 1499.253849 -0.45, 30000, 0.512696879, -373.3472, 0.029761722, 1713.43297 -0.45, 30000, 0.576783989, 499.613, 0.109736694, 1927.612091 -0.45, 30000, 0.640871099, 1327.2839, 0.184670972, 2141.791213 -0.45, 30000, 0.704958209, 2084.7233, 0.269780944, 2355.970334 -0.45, 30000, 0.769045319, 3438.4737, 0.394356056, 2570.149455 -0.45, 30000, 0.833132429, 5001.6018, 0.549976028, 2784.328576 -0.45, 30000, 0.897219538, 6745.0278, 0.778404778, 2998.507698 -0.45, 30000, 0.961306648, 8543.9648, 0.998834611, 3212.686819 -0.45, 33000, 0, 205.886105, 0.057190585, 0 -0.45, 33000, 0.374530497, -79.3292376, -0.086867348, 1251.680921 -0.45, 33000, 0.436952246, 217.7307448, -0.029231273, 1460.294407 -0.45, 33000, 0.499373996, 514.7858224, 0.028404573, 1668.907894 -0.45, 33000, 0.561795745, 811.8401824, 0.086041376, 1877.521381 -0.45, 33000, 0.624217495, 1108.892279, 0.143676494, 2086.134868 -0.45, 33000, 0.686639244, 1635.208082, 0.218688038, 2294.748354 -0.45, 33000, 0.749060994, 3074.025514, 0.359371949, 2503.361841 -0.45, 33000, 0.811482743, 4342.638807, 0.48564515, 2711.975328 -0.45, 33000, 0.873904493, 5396.40235, 0.600409766, 2920.588815 -0.45, 33000, 0.936326242, 6445.206122, 0.760853636, 3129.202301 -0.45, 33000, 0.998747992, 4940.574534, 0.489033254, 3337.815788 -0.45, 36000, 0, 181.0389955, 0.05028861, 0 -0.45, 36000, 0.3645374, -448.6355, -0.115432389, 1218.283992 -0.45, 36000, 0.425293634, -138.5643, -0.057765833, 1421.331324 -0.45, 36000, 0.486049867, 171.4962, -9.92778E-05, 1624.378656 -0.45, 36000, 0.546806101, 481.5658, 0.057567556, 1827.425988 -0.45, 36000, 0.607562334, 791.6309, 0.115233139, 2030.47332 -0.45, 36000, 0.668318567, 1243.2102, 0.173008389, 2233.520652 -0.45, 36000, 0.729074801, 2049.3863, 0.250453111, 2436.567984 -0.45, 36000, 0.789831034, 2438.0172, 0.337211417, 2639.615316 -0.45, 36000, 0.850587268, 5870.6084, 0.584133139, 2842.662648 -0.45, 36000, 0.911343501, 5930.0144, 0.710621472, 3045.70998 -0.45, 36000, 0.972099734, 4408.1081, 0.445576194, 3248.757312 -0.45, 39000, 0, 156.7934513, 0.043553736, 0 -0.45, 39000, 0.364240382, -1539.3459, -0.120279972, 1217.291355 -0.45, 39000, 0.424947112, -1096.7203, -0.071010111, 1420.173248 -0.45, 39000, 0.485653842, -654.102, -0.021739972, 1623.05514 -0.45, 39000, 0.546360572, -211.4771, 0.027530861, 1825.937033 -0.45, 39000, 0.607067303, 231.1413, 0.076801278, 2028.818925 -0.45, 39000, 0.667774033, 669.14, 0.122614417, 2231.700818 -0.45, 39000, 0.728480763, 1571.8702, 0.202160972, 2434.58271 -0.45, 39000, 0.789187493, 2355.7952, 0.284155583, 2637.464603 -0.45, 39000, 0.849894224, 3797.9949, 0.3671565, 2840.346495 -0.45, 39000, 0.910600954, 4790.4253, 0.574411639, 3043.228388 -0.45, 39000, 0.971307684, 8270.4708, 1.173640389, 3246.11028 -0.45, 42000, 0, 135.7396884, 0.037705469, 0 -0.45, 42000, 0.364240382, -36867.10241, -3.890105465, 1217.291355 -0.45, 42000, 0.424947112, -28864.98024, -3.03168334, 1420.173248 -0.45, 42000, 0.485653842, -20862.86109, -2.173260623, 1623.05514 -0.45, 42000, 0.546360572, -12860.75201, -1.314836665, 1825.937033 -0.45, 42000, 0.607067303, -4858.63465, -0.456416526, 2028.818925 -0.45, 42000, 0.667774033, -518.1820938, 0.000453187, 2231.700818 -0.45, 42000, 0.728480763, 1684.176812, 0.181575095, 2434.58271 -0.45, 42000, 0.789187493, 1267.621931, 0.230192653, 2637.464603 -0.45, 42000, 0.849894224, 4188.432213, 0.554277274, 2840.346495 -0.45, 42000, 0.910600954, 3163.467475, 0.400565604, 3043.228388 -0.45, 42000, 0.971307684, 6587.986219, 0.989568722, 3246.11028 -0.5, 0, 0, 719.4314613, 0.199842073, 0 -0.5, 0, 0.488872083, -2671.8684, 0.009099639, 1633.8105 -0.5, 0, 0.570350763, -449.1081, 0.216525139, 1906.11225 -0.5, 0, 0.651829443, 1773.6538, 0.423950917, 2178.414 -0.5, 0, 0.733308124, 4378.3218, 0.674076306, 2450.71575 -0.5, 0, 0.814786804, 6999.0028, 1.013225722, 2723.0175 -0.5, 0, 0.896265485, 9737.8904, 1.469231028, 2995.31925 -0.5, 0, 0.977744165, 15257.6121, 2.098689278, 3267.621 -0.5, 3000, 0, 651.5398182, 0.180983283, 0 -0.5, 3000, 0.478788689, -1671.107484, 0.001390384, 1600.1118 -0.5, 3000, 0.558586804, 13.27504799, 0.18593577, 1866.7971 -0.5, 3000, 0.638384919, 1697.660182, 0.370481563, 2133.4824 -0.5, 3000, 0.718183034, 3635.082033, 0.579985297, 2400.1677 -0.5, 3000, 0.797981149, 6571.44432, 0.886599714, 2666.853 -0.5, 3000, 0.877779264, 10002.66621, 1.295461348, 2933.5383 -0.5, 3000, 0.957577379, 14493.5188, 1.862992334, 3200.2236 -0.5, 6000, 0, 588.8111667, 0.163558657, 0 -0.5, 6000, 0.468704354, -2323.4404, -0.026420139, 1566.40995 -0.5, 6000, 0.546821746, -537.0041, 0.145300444, 1827.478275 -0.5, 6000, 0.624939138, 1249.4338, 0.317021056, 2088.5466 -0.5, 6000, 0.703056531, 3131.3497, 0.5036995, 2349.614925 -0.5, 6000, 0.781173923, 5635.9942, 0.763231111, 2610.68325 -0.5, 6000, 0.859291315, 8788.3243, 1.1245335, 2871.751575 -0.5, 6000, 0.937408707, 13071.7334, 1.63121325, 3132.8199 -0.5, 9000, 0, 530.9526946, 0.14748686, 0 -0.5, 9000, 0.458620961, -2094.958, -0.054247139, 1532.71125 -0.5, 9000, 0.535057787, -526.4189, 0.105671417, 1788.163125 -0.5, 9000, 0.611494614, 1042.12, 0.26559, 2043.615 -0.5, 9000, 0.687931441, 2662.1138, 0.432256333, 2299.066875 -0.5, 9000, 0.764368268, 4775.5835, 0.656942417, 2554.51875 -0.5, 9000, 0.840805094, 7591.811, 0.968169556, 2809.970625 -0.5, 9000, 0.917241921, 11306.1484, 1.401770167, 3065.4225 -0.5, 9000, 0.993678748, 15293.1484, 1.908946806, 3320.874375 -0.5, 12000, 0, 477.677083, 0.132688079, 0 -0.5, 12000, 0.448536625, -2187.265426, -0.075353244, 1499.0094 -0.5, 12000, 0.523292729, -726.79402, 0.071526663, 1748.8443 -0.5, 12000, 0.598048833, 733.6773128, 0.218406541, 1998.6792 -0.5, 12000, 0.672804937, 2198.013939, 0.365723088, 2248.5141 -0.5, 12000, 0.747561041, 4042.146279, 0.559054089, 2498.349 -0.5, 12000, 0.822317145, 6520.894839, 0.828437356, 2748.1839 -0.5, 12000, 0.89707325, 9754.751044, 1.198620257, 2998.0188 -0.5, 12000, 0.971829354, 13291.53756, 1.645362573, 3247.8537 -0.5, 15000, 0, 428.7154772, 0.119087633, 0 -0.5, 15000, 0.438453232, -2261.0837, -0.094188694, 1465.3107 -0.5, 15000, 0.51152877, -906.3853, 0.040579, 1709.52915 -0.5, 15000, 0.584604309, 448.3132, 0.175346667, 1953.7476 -0.5, 15000, 0.657679847, 1803.0117, 0.310114361, 2197.96605 -0.5, 15000, 0.730755386, 3403.8291, 0.474530833, 2442.1845 -0.5, 15000, 0.803830925, 5551.8208, 0.703580583, 2686.40295 -0.5, 15000, 0.876906463, 8343.4707, 1.017776694, 2930.6214 -0.5, 15000, 0.949982002, 11431.6924, 1.401369639, 3174.83985 -0.5, 18000, 0, 383.8064512, 0.106612903, 0 -0.5, 18000, 0.428368896, -2094.154206, -0.094180161, 1431.60885 -0.5, 18000, 0.499763712, -902.8737944, 0.024896251, 1670.210325 -0.5, 18000, 0.571158528, 288.406828, 0.143972654, 1908.8118 -0.5, 18000, 0.642553344, 1479.687387, 0.263049058, 2147.413275 -0.5, 18000, 0.71394816, 2838.912822, 0.400670156, 2386.01475 -0.5, 18000, 0.785342976, 4697.477006, 0.59564993, 2624.616225 -0.5, 18000, 0.856737792, 7142.300167, 0.865323653, 2863.2177 -0.5, 18000, 0.928132608, 9817.644065, 1.190194936, 3101.819175 -0.5, 18000, 0.999527424, 12759.60862, 1.582316014, 3340.42065 -0.5, 21000, 0, 342.6964845, 0.095193468, 0 -0.5, 21000, 0.418285503, -1938.541402, -0.092217211, 1397.91015 -0.5, 21000, 0.487999753, -889.0242272, 0.012692765, 1630.895175 -0.5, 21000, 0.557714004, 160.4929592, 0.117602742, 1863.8802 -0.5, 21000, 0.627428254, 1210.010051, 0.222512725, 2096.865225 -0.5, 21000, 0.697142504, 2370.834541, 0.339207181, 2329.85025 -0.5, 21000, 0.766856755, 3954.670517, 0.502368197, 2562.835275 -0.5, 21000, 0.836571005, 6062.115827, 0.729859537, 2795.8203 -0.5, 21000, 0.906285256, 8391.195551, 1.007022771, 3028.805325 -0.5, 21000, 0.975999506, 10947.83355, 1.350267823, 3261.79035 -0.5, 24000, 0, 305.1454803, 0.084762633, 0 -0.5, 24000, 0.408201167, -1947.670679, -0.102084608, 1364.2083 -0.5, 24000, 0.476234695, -988.9591088, -0.006970709, 1591.57635 -0.5, 24000, 0.544268223, -30.2477248, 0.088143188, 1818.9444 -0.5, 24000, 0.61230175, 928.4636392, 0.183257116, 2046.31245 -0.5, 24000, 0.680335278, 1919.685307, 0.281713757, 2273.6805 -0.5, 24000, 0.748368806, 3285.743072, 0.419878828, 2501.04855 -0.5, 24000, 0.816402334, 5083.210358, 0.61065231, 2728.4166 -0.5, 24000, 0.884435862, 7101.839377, 0.844858532, 2955.78465 -0.5, 24000, 0.95246939, 9226.396621, 1.125919448, 3183.1527 -0.5, 27000, 0, 270.9207737, 0.07525577, 0 -0.5, 27000, 0.398117774, -2136.526123, -0.125155323, 1330.5096 -0.5, 27000, 0.464470736, -1216.082738, -0.035333188, 1552.2612 -0.5, 27000, 0.530823698, -295.639364, 0.054488942, 1774.0128 -0.5, 27000, 0.597176661, 624.8040768, 0.144311072, 1995.7644 -0.5, 27000, 0.663529623, 1544.433194, 0.234071586, 2217.516 -0.5, 27000, 0.729882585, 2710.016146, 0.350469589, 2439.2676 -0.5, 27000, 0.796235548, 4258.356579, 0.511502049, 2661.0192 -0.5, 27000, 0.86258851, 6031.02936, 0.71009637, 2882.7708 -0.5, 27000, 0.928941472, 7875.958373, 0.946991817, 3104.5224 -0.5, 27000, 0.995294434, 9494.50145, 1.200561968, 3326.274 -0.5, 30000, 0, 239.8026398, 0.066611844, 0 -0.5, 30000, 0.388033438, -2138.9726, -0.135210361, 1296.80775 -0.5, 30000, 0.452705678, -1286.5636, -0.052500861, 1512.942375 -0.5, 30000, 0.517377917, -434.1592, 0.030208944, 1729.077 -0.5, 30000, 0.582050157, 418.2473, 0.112918528, 1945.211625 -0.5, 30000, 0.646722397, 1259.3317, 0.194368028, 2161.34625 -0.5, 30000, 0.711394636, 2165.2414, 0.287759028, 2377.480875 -0.5, 30000, 0.776066876, 3503.8404, 0.422383306, 2593.6155 -0.5, 30000, 0.840739116, 5078.2979, 0.592236639, 2809.750125 -0.5, 30000, 0.905411355, 6705.9823, 0.800613306, 3025.88475 -0.5, 30000, 0.970083595, 8221.5986, 1.025389611, 3242.019375 -0.5, 33000, 0, 211.5771102, 0.05877142, 0 -0.5, 33000, 0.377950045, -1380.47969, -0.126999302, 1263.10905 -0.5, 33000, 0.440941719, -790.0097992, -0.056981087, 1473.627225 -0.5, 33000, 0.503933393, -199.5420696, 0.013036997, 1684.1454 -0.5, 33000, 0.566925067, 390.9254104, 0.083055478, 1894.663575 -0.5, 33000, 0.629916741, 981.3919232, 0.153073296, 2105.18175 -0.5, 33000, 0.692908416, 1715.96109, 0.235226987, 2315.699925 -0.5, 33000, 0.75590009, 2950.937646, 0.359601242, 2526.2181 -0.5, 33000, 0.818891764, 4283.182251, 0.500008083, 2736.736275 -0.5, 33000, 0.881883438, 5594.076822, 0.655059574, 2947.25445 -0.5, 33000, 0.944875112, 6646.16803, 0.819806151, 3157.772625 -0.5, 36000, 0, 186.0431888, 0.051678664, 0 -0.5, 36000, 0.367865709, -1620.7509, -0.145774778, 1229.4072 -0.5, 36000, 0.429176661, -1058.968, -0.080075667, 1434.3084 -0.5, 36000, 0.490487612, -497.1895, -0.014376556, 1639.2096 -0.5, 36000, 0.551798564, 64.5929, 0.051322667, 1844.1108 -0.5, 36000, 0.613109515, 626.3733, 0.117021389, 2049.012 -0.5, 36000, 0.674420467, 1261.6, 0.184116139, 2253.9132 -0.5, 36000, 0.735731418, 2126.8357, 0.270520694, 2458.8144 -0.5, 36000, 0.79704237, 2971.6239, 0.380310583, 2663.7156 -0.5, 36000, 0.858353321, 5130.2887, 0.567301806, 2868.6168 -0.5, 36000, 0.919664273, 5736.3087, 0.714857667, 3073.518 -0.5, 36000, 0.980975224, 5137.5062, 0.623572444, 3278.4192 -0.5, 39000, 0, 161.1274609, 0.044757628, 0 -0.5, 39000, 0.367565978, -1726.1108, -0.129606833, 1228.4055 -0.5, 39000, 0.428826975, -1225.5562, -0.075898056, 1433.13975 -0.5, 39000, 0.490087971, -725.0043, -0.022189111, 1637.874 -0.5, 39000, 0.551348968, -224.4495, 0.031520111, 1842.60825 -0.5, 39000, 0.612609964, 276.1023, 0.085229167, 2047.3425 -0.5, 39000, 0.673870961, 795.7263, 0.138717111, 2252.07675 -0.5, 39000, 0.735131957, 1646.6392, 0.219389556, 2456.811 -0.5, 39000, 0.796392953, 2559.8728, 0.317068278, 2661.54525 -0.5, 39000, 0.85765395, 3782.2465, 0.422147611, 2866.2795 -0.5, 39000, 0.918914946, 4713.0968, 0.589438917, 3071.01375 -0.5, 39000, 0.980175943, 6383.8781, 0.885951, 3275.748 -0.5, 42000, 0, 139.49174, 0.038747706, 0 -0.5, 42000, 0.367565978, -23385.55479, -2.45044859, 1228.4055 -0.5, 42000, 0.428826975, -18281.36054, -1.902269938, 1433.13975 -0.5, 42000, 0.490087971, -13177.16749, -1.354091009, 1637.874 -0.5, 42000, 0.551348968, -8072.980487, -0.805911335, 1842.60825 -0.5, 42000, 0.612609964, -2968.788675, -0.257733828, 2047.3425 -0.5, 42000, 0.673870961, -32.00730625, 0.052859208, 2252.07675 -0.5, 42000, 0.735131957, 1502.800762, 0.186997738, 2456.811 -0.5, 42000, 0.796392953, 1665.687444, 0.253548528, 2661.54525 -0.5, 42000, 0.85765395, 3668.111238, 0.481592365, 2866.2795 -0.5, 42000, 0.918914946, 3546.039325, 0.461611139, 3071.01375 -0.5, 42000, 0.980175943, 5985.872581, 0.880143326, 3275.748 -0.55, 0, 0, 741.230954, 0.205897487, 0 -0.55, 0, 0.493760803, -3974.053075, -0.000820917, 1650.148605 -0.55, 0, 0.576054271, -1248.03395, 0.219977306, 1925.173373 -0.55, 0, 0.658347738, 1477.988675, 0.440776083, 2200.19814 -0.55, 0, 0.740641205, 4294.256925, 0.708952139, 2475.222908 -0.55, 0, 0.822934672, 6245.607175, 1.054354382, 2750.247675 -0.55, 0, 0.90522814, 8101.4293, 1.51386609, 3025.272443 -0.55, 0, 0.987521607, 14492.4421, 2.179628014, 3300.29721 -0.55, 3000, 0, 671.2821263, 0.186467257, 0 -0.55, 3000, 0.483576576, -1432.397676, 0.014716596, 1616.112918 -0.55, 3000, 0.564172672, 84.17923157, 0.20189126, 1885.465071 -0.55, 3000, 0.644768768, 1600.76361, 0.389067093, 2154.817224 -0.55, 3000, 0.725364864, 3473.507475, 0.606311054, 2424.169377 -0.55, 3000, 0.805960961, 6711.016355, 0.934108769, 2693.52153 -0.55, 3000, 0.886557057, 9967.947791, 1.359347672, 2962.873683 -0.55, 3000, 0.967153153, 13630.3236, 1.924824888, 3232.225836 -0.55, 6000, 0, 606.6527338, 0.168514648, 0 -0.55, 6000, 0.473391397, -2990.475, -0.018114611, 1582.07405 -0.55, 6000, 0.552289963, -1009.9926, 0.157541333, 1845.753058 -0.55, 6000, 0.63118853, 970.4946, 0.333197306, 2109.432066 -0.55, 6000, 0.710087096, 3019.5913, 0.527477056, 2373.111074 -0.55, 6000, 0.788985662, 5758.484, 0.803531722, 2636.790083 -0.55, 6000, 0.867884228, 8693.2776, 1.172504722, 2900.469091 -0.55, 6000, 0.946782794, 13161.2822, 1.722699028, 3164.148099 -0.55, 9000, 0, 547.0410922, 0.151955859, 0 -0.55, 9000, 0.46320717, -1970.876741, -0.043239637, 1548.038363 -0.55, 9000, 0.540408365, -459.3171268, 0.119487518, 1806.044756 -0.55, 9000, 0.61760956, 1052.242014, 0.282214684, 2064.05115 -0.55, 9000, 0.694810755, 2637.095011, 0.455172579, 2322.057544 -0.55, 9000, 0.77201195, 4737.155516, 0.690450555, 2580.063937 -0.55, 9000, 0.849213145, 7626.859845, 1.019973113, 2838.070331 -0.55, 9000, 0.92641434, 11417.02954, 1.479775053, 3096.076725 -0.55, 12000, 0, 492.1511763, 0.13670866, 0 -0.55, 12000, 0.453021991, -2116.796359, -0.06625539, 1513.999494 -0.55, 12000, 0.528525656, -692.9638734, 0.083545617, 1766.332743 -0.55, 12000, 0.604029321, 730.8686216, 0.233346596, 2018.665992 -0.55, 12000, 0.679532987, 2174.639245, 0.385801245, 2270.999241 -0.55, 12000, 0.755036652, 4040.397099, 0.589324729, 2523.33249 -0.55, 12000, 0.830540317, 6529.060112, 0.871495305, 2775.665739 -0.55, 12000, 0.906043982, 9822.104707, 1.263731225, 3027.998988 -0.55, 12000, 0.981547647, 13402.77955, 1.73111083, 3280.332237 -0.55, 15000, 0, 441.7059848, 0.122696107, 0 -0.55, 15000, 0.442837764, -2244.3843, -0.086421417, 1479.963807 -0.55, 15000, 0.516644058, -904.5432, 0.051172333, 1726.624441 -0.55, 15000, 0.590450352, 435.298, 0.188766083, 1973.285076 -0.55, 15000, 0.664256646, 1775.1393, 0.326359861, 2219.94571 -0.55, 15000, 0.73806294, 3403.2661, 0.500130917, 2466.606345 -0.55, 15000, 0.811869234, 5568.1387, 0.741466417, 2713.266979 -0.55, 15000, 0.885675528, 8425.5254, 1.075894833, 2959.927614 -0.55, 15000, 0.959481822, 11567.9834, 1.480496972, 3206.588248 -0.55, 18000, 0, 395.4361704, 0.109843381, 0 -0.55, 18000, 0.432652585, -2211.981542, -0.099376356, 1445.924938 -0.55, 18000, 0.504761349, -995.9855, 0.025697848, 1686.912428 -0.55, 18000, 0.576870113, 220.0106552, 0.150772077, 1927.899918 -0.55, 18000, 0.648978877, 1436.006694, 0.275846306, 2168.887408 -0.55, 18000, 0.721087641, 2833.160671, 0.422324234, 2409.874898 -0.55, 18000, 0.793196406, 4728.219522, 0.629529676, 2650.862387 -0.55, 18000, 0.86530517, 7192.648788, 0.912189663, 2891.849877 -0.55, 18000, 0.937413934, 9949.77938, 1.260313941, 3132.837367 -0.55, 21000, 0, 353.0805306, 0.098077925, 0 -0.55, 21000, 0.422468358, -2009.05732, -0.096879196, 1411.889252 -0.55, 21000, 0.492879751, -949.5835648, 0.01310342, 1647.204127 -0.55, 21000, 0.563291144, 109.8899312, 0.123086012, 1882.519002 -0.55, 21000, 0.633702537, 1169.363487, 0.233068604, 2117.833877 -0.55, 21000, 0.70411393, 2361.710781, 0.357156947, 2353.148753 -0.55, 21000, 0.774525322, 3964.175763, 0.529224465, 2588.463628 -0.55, 21000, 0.844936715, 6116.397459, 0.771433793, 2823.778503 -0.55, 21000, 0.915348108, 8496.229542, 1.065023181, 3059.093378 -0.55, 21000, 0.985759501, 11078.59967, 1.42600475, 3294.408254 -0.55, 24000, 0, 314.3916935, 0.087331026, 0 -0.55, 24000, 0.412283179, -1920.540449, -0.100321795, 1377.850383 -0.55, 24000, 0.480997042, -975.1257144, -0.002345911, 1607.492114 -0.55, 24000, 0.549710905, -29.7110752, 0.095629979, 1837.133844 -0.55, 24000, 0.618424768, 915.703496, 0.193605893, 2066.775575 -0.55, 24000, 0.687138631, 1924.168818, 0.298101069, 2296.417305 -0.55, 24000, 0.755852494, 3310.932917, 0.443917925, 2526.059036 -0.55, 24000, 0.824566357, 5137.796047, 0.645914751, 2755.700766 -0.55, 24000, 0.89328022, 7198.693904, 0.89386888, 2985.342497 -0.55, 24000, 0.961994083, 9318.197458, 1.189064479, 3214.984227 -0.55, 27000, 0, 279.1299441, 0.077536096, 0 -0.55, 27000, 0.402098952, -2005.200051, -0.116460129, 1343.814696 -0.55, 27000, 0.469115443, -1120.043642, -0.025787706, 1567.783812 -0.55, 27000, 0.536131935, -234.887144, 0.064884742, 1791.752928 -0.55, 27000, 0.603148427, 650.2693488, 0.155557191, 2015.722044 -0.55, 27000, 0.670164919, 1536.75761, 0.246351324, 2239.69116 -0.55, 27000, 0.737181411, 2730.551862, 0.37022488, 2463.660276 -0.55, 27000, 0.804197903, 4295.929247, 0.539702043, 2687.629392 -0.55, 27000, 0.871214395, 6094.25398, 0.749695379, 2911.598508 -0.55, 27000, 0.938230887, 7933.540185, 0.999217629, 3135.567624 -0.55, 30000, 0, 247.0688996, 0.06863025, 0 -0.55, 30000, 0.391913772, -2118.3728, -0.133520556, 1309.775828 -0.55, 30000, 0.457232735, -1282.077, -0.048940083, 1528.071799 -0.55, 30000, 0.522551697, -445.7816, 0.035640389, 1746.36777 -0.55, 30000, 0.587870659, 390.5139, 0.120220833, 1964.663741 -0.55, 30000, 0.653189621, 1226.8096, 0.204801333, 2182.959713 -0.55, 30000, 0.718508583, 2222.488, 0.306499611, 2401.255684 -0.55, 30000, 0.783827545, 3563.936, 0.449643, 2619.551655 -0.55, 30000, 0.849146507, 5155.2666, 0.630657361, 2837.847626 -0.55, 30000, 0.914465469, 6746.3921, 0.83812575, 3056.143598 -0.55, 30000, 0.979784431, 8117.8828, 1.064862472, 3274.439569 -0.55, 33000, 0, 217.9881082, 0.060552252, 0 -0.55, 33000, 0.381729545, -2025.390102, -0.144887688, 1275.740141 -0.55, 33000, 0.445351136, -1287.775163, -0.067797668, 1488.363497 -0.55, 33000, 0.508972727, -550.1608216, 0.009292294, 1700.986854 -0.55, 33000, 0.572594318, 187.4534784, 0.086382362, 1913.610211 -0.55, 33000, 0.636215909, 925.0674872, 0.163472276, 2126.233568 -0.55, 33000, 0.6998375, 1767.749738, 0.250822764, 2338.856924 -0.55, 33000, 0.763459091, 2915.098938, 0.37095928, 2551.480281 -0.55, 33000, 0.827080682, 4290.627315, 0.523122989, 2764.103638 -0.55, 33000, 0.890702272, 5717.436254, 0.700794115, 2976.726995 -0.55, 33000, 0.954323863, 6820.062578, 0.87990555, 3189.350351 -0.55, 36000, 0, 191.6804835, 0.053244579, 0 -0.55, 36000, 0.371544366, -2176.4893, -0.158942194, 1241.701272 -0.55, 36000, 0.433468427, -1492.5227, -0.088408972, 1448.651484 -0.55, 36000, 0.495392488, -808.5572, -0.01787575, 1655.601696 -0.55, 36000, 0.557316549, -124.5906, 0.0526575, 1862.551908 -0.55, 36000, 0.61924061, 559.3754, 0.123190639, 2069.50212 -0.55, 36000, 0.681164671, 1287.9207, 0.196665111, 2276.452332 -0.55, 36000, 0.743088732, 2201.7371, 0.291063083, 2483.402544 -0.55, 36000, 0.805012794, 3296.7427, 0.416372528, 2690.352756 -0.55, 36000, 0.866936855, 4770.6906, 0.576017194, 2897.302968 -0.55, 36000, 0.928860916, 5655.6135, 0.733487861, 3104.25318 -0.55, 36000, 0.990784977, 5650.372, 0.750453889, 3311.203392 -0.55, 39000, 0, 166.009784, 0.046113829, 0 -0.55, 39000, 0.371241638, -1882.5707, -0.137694889, 1240.689555 -0.55, 39000, 0.433115245, -1336.2673, -0.079964306, 1447.471148 -0.55, 39000, 0.494988851, -789.9644, -0.022233639, 1654.25274 -0.55, 39000, 0.556862457, -243.6606, 0.035497083, 1861.034333 -0.55, 39000, 0.618736064, 302.6422, 0.093227778, 2067.815925 -0.55, 39000, 0.68060967, 884.129, 0.153424861, 2274.597518 -0.55, 39000, 0.742483276, 1713.0544, 0.236917556, 2481.37911 -0.55, 39000, 0.804356883, 2706.9982, 0.345631583, 2688.160703 -0.55, 39000, 0.866230489, 3806.2708, 0.466712, 2894.942295 -0.55, 39000, 0.928104096, 4711.5148, 0.614909167, 3101.723888 -0.55, 39000, 0.989977702, 5502.9071, 0.762855972, 3308.50548 -0.55, 42000, 0, 143.7184792, 0.0399218, 0 -0.55, 42000, 0.371241638, -13978.10886, -1.446239215, 1240.689555 -0.55, 42000, 0.433115245, -10893.78934, -1.113624479, 1447.471148 -0.55, 42000, 0.494988851, -7809.469987, -0.781009658, 1654.25274 -0.55, 42000, 0.556862457, -4725.153862, -0.448394436, 1861.034333 -0.55, 42000, 0.618736064, -1640.8353, -0.115780283, 2067.815925 -0.55, 42000, 0.68060967, 298.8143312, 0.091090118, 2274.597518 -0.55, 42000, 0.742483276, 1402.126212, 0.195340922, 2481.37911 -0.55, 42000, 0.804356883, 1950.489806, 0.276873958, 2688.160703 -0.55, 42000, 0.866230489, 3358.422362, 0.443898649, 2894.942295 -0.55, 42000, 0.928104096, 3801.776975, 0.509867007, 3101.723888 -0.55, 42000, 0.989977702, 5521.017494, 0.805584319, 3308.50548 -0.6, 0, 0, 765.606981, 0.212668606, 0 -0.6, 0, 0.499115117, -6025.0477, -0.021952028, 1668.04272 -0.6, 0, 0.582300969, -2465.723, 0.218108028, 1946.04984 -0.6, 0, 0.665486822, 1093.6081, 0.458169056, 2224.05696 -0.6, 0, 0.748672675, 4224.9808, 0.7486365, 2502.06408 -0.6, 0, 0.831858528, 5101.5099, 1.095335194, 2780.0712 -0.6, 0, 0.915044381, 5674.1032, 1.549067694, 3058.07832 -0.6, 0, 0.998230233, 13470.3214, 2.262130472, 3336.08544 -0.6, 3000, 0, 693.357825, 0.192599396, 0 -0.6, 3000, 0.488820452, -1032.887727, 0.030807484, 1633.637952 -0.6, 3000, 0.570290528, 229.0590395, 0.220299324, 1905.910944 -0.6, 3000, 0.651760603, 1491.021647, 0.409793643, 2178.183936 -0.6, 3000, 0.733230679, 3270.837791, 0.635212607, 2450.456928 -0.6, 3000, 0.814700754, 7000.776244, 0.987751119, 2722.72992 -0.6, 3000, 0.896170829, 9948.700793, 1.429979892, 2995.002912 -0.6, 3000, 0.977640905, 11990.53363, 1.965347937, 3267.275904 -0.6, 6000, 0, 626.6030386, 0.1740564, 0 -0.6, 6000, 0.478524826, -4189.7769, -0.010113556, 1599.229968 -0.6, 6000, 0.558278963, -1838.029, 0.17001675, 1865.768296 -0.6, 6000, 0.638033101, 513.7294, 0.350147083, 2132.306624 -0.6, 6000, 0.717787239, 2868.4722, 0.552914778, 2398.844952 -0.6, 6000, 0.797541376, 6031.4811, 0.850707333, 2665.38328 -0.6, 6000, 0.877295514, 8447.5035, 1.2142165, 2931.921608 -0.6, 6000, 0.957049652, 13176.4931, 1.822579778, 3198.459936 -0.6, 9000, 0, 565.0310161, 0.15695306, 0 -0.6, 9000, 0.468230162, -1831.780464, -0.030808159, 1564.8252 -0.6, 9000, 0.546268522, -380.2262071, 0.134835268, 1825.6294 -0.6, 9000, 0.624306882, 1071.327257, 0.300478679, 2086.4336 -0.6, 9000, 0.702345242, 2620.857043, 0.48058401, 2347.2378 -0.6, 9000, 0.780383603, 4715.763664, 0.728029942, 2608.042 -0.6, 9000, 0.858421963, 7694.563979, 1.078986117, 2868.8462 -0.6, 9000, 0.936460323, 11541.27548, 1.566032823, 3129.6504 -0.6, 12000, 0, 508.3359974, 0.141204444, 0 -0.6, 12000, 0.457934535, -2192.806423, -0.058321274, 1530.417216 -0.6, 12000, 0.534256958, -752.0044664, 0.095427277, 1785.486752 -0.6, 12000, 0.61057938, 688.7974738, 0.249175801, 2040.556288 -0.6, 12000, 0.686901803, 2170.089801, 0.409174137, 2295.625824 -0.6, 12000, 0.763224225, 4070.513065, 0.624000536, 2550.69536 -0.6, 12000, 0.839546648, 6569.497113, 0.919197037, 2805.764896 -0.6, 12000, 0.91586907, 9949.594151, 1.338795674, 3060.834432 -0.6, 12000, 0.992191493, 13584.53113, 1.825129068, 3315.903968 -0.6, 15000, 0, 456.2318717, 0.126731075, 0 -0.6, 15000, 0.447639871, -2117.7908, -0.076021722, 1496.012448 -0.6, 15000, 0.522246516, -822.6001, 0.064197556, 1745.347856 -0.6, 15000, 0.596853161, 472.5904, 0.204416833, 1994.683264 -0.6, 15000, 0.671459806, 1767.781, 0.344636139, 2244.018672 -0.6, 15000, 0.746066451, 3415.8284, 0.528367917, 2493.35408 -0.6, 15000, 0.820673096, 5627.7554, 0.78535625, 2742.689488 -0.6, 15000, 0.895279741, 8524.8691, 1.138025306, 2992.024896 -0.6, 15000, 0.969886387, 11754.3232, 1.568470722, 3241.360304 -0.6, 18000, 0, 408.4404341, 0.113455676, 0 -0.6, 18000, 0.437344244, -2177.575997, -0.094375336, 1461.604464 -0.6, 18000, 0.510234952, -974.971884, 0.034363664, 1705.205208 -0.6, 18000, 0.583125659, 227.632412, 0.16310267, 1948.805952 -0.6, 18000, 0.656016366, 1430.236776, 0.291841675, 2192.406696 -0.6, 18000, 0.728907074, 2848.307467, 0.447639786, 2436.00744 -0.6, 18000, 0.801797781, 4781.003586, 0.666626248, 2679.608184 -0.6, 18000, 0.874688488, 7288.0453, 0.966836923, 2923.208928 -0.6, 18000, 0.947579196, 10104.9707, 1.335764763, 3166.809672 -0.6, 21000, 0, 364.6918921, 0.101303303, 0 -0.6, 21000, 0.42704958, -2118.026526, -0.104417232, 1427.199696 -0.6, 21000, 0.49822451, -1031.512446, 0.012067203, 1665.066312 -0.6, 21000, 0.56939944, 55.0015688, 0.128551606, 1902.932928 -0.6, 21000, 0.64057437, 1141.5157, 0.24503601, 2140.799544 -0.6, 21000, 0.7117493, 2346.906502, 0.376427373, 2378.66616 -0.6, 21000, 0.78292423, 4019.2844, 0.561679119, 2616.532776 -0.6, 21000, 0.85409916, 6202.80357, 0.818266329, 2854.399392 -0.6, 21000, 0.92527409, 8634.536794, 1.129122423, 3092.266008 -0.6, 21000, 0.99644902, 11324.82162, 1.512168034, 3330.132624 -0.6, 24000, 0, 324.7307388, 0.090202983, 0 -0.6, 24000, 0.416753953, -1994.748622, -0.103195204, 1392.791712 -0.6, 24000, 0.486212946, -1033.281939, -0.000724818, 1624.923664 -0.6, 24000, 0.555671938, -71.81536, 0.101745592, 1857.055616 -0.6, 24000, 0.62513093, 889.651332, 0.204215994, 2089.187568 -0.6, 24000, 0.694589922, 1932.715401, 0.31585061, 2321.31952 -0.6, 24000, 0.764048914, 3352.634742, 0.470508527, 2553.451472 -0.6, 24000, 0.833507907, 5214.1562, 0.685089481, 2785.583424 -0.6, 24000, 0.902966899, 7321.433097, 0.948696336, 3017.715376 -0.6, 24000, 0.972425891, 9475.58228, 1.261993982, 3249.847328 -0.6, 27000, 0, 288.309376, 0.080085938, 0 -0.6, 27000, 0.406459289, -1906.461986, -0.106241326, 1358.386944 -0.6, 27000, 0.474202504, -1048.818354, -0.014867378, 1584.784768 -0.6, 27000, 0.541945719, -191.1747056, 0.076506563, 1811.182592 -0.6, 27000, 0.609688934, 666.4689432, 0.167880502, 2037.580416 -0.6, 27000, 0.677432148, 1540.752586, 0.261022358, 2263.97824 -0.6, 27000, 0.745175363, 2765.433478, 0.392196603, 2490.376064 -0.6, 27000, 0.812918578, 4360.493994, 0.572178717, 2716.773888 -0.6, 27000, 0.880661793, 6182.694176, 0.795197793, 2943.171712 -0.6, 27000, 0.948405008, 8049.501909, 1.059211521, 3169.569536 -0.6, 30000, 0, 255.193976, 0.070887216, 0 -0.6, 30000, 0.396163662, -2060.8132, -0.127277611, 1323.97896 -0.6, 30000, 0.46219094, -1240.2024, -0.041341222, 1544.64212 -0.6, 30000, 0.528218217, -419.5912, 0.044595139, 1765.30528 -0.6, 30000, 0.594245494, 401.0198, 0.1305315, 1985.96844 -0.6, 30000, 0.660272771, 1221.6309, 0.216467861, 2206.6316 -0.6, 30000, 0.726300048, 2266.5886, 0.326339111, 2427.29476 -0.6, 30000, 0.792327325, 3629.0439, 0.477799861, 2647.95792 -0.6, 30000, 0.858354602, 5241.6924, 0.668701972, 2868.62108 -0.6, 30000, 0.924381879, 6845.8208, 0.887545361, 3089.28424 -0.6, 30000, 0.990409156, 8183.6294, 1.118031278, 3309.9474 -0.6, 33000, 0, 225.1568375, 0.062543566, 0 -0.6, 33000, 0.385868998, -2207.917374, -0.146866369, 1289.574192 -0.6, 33000, 0.450180498, -1426.233147, -0.066435294, 1504.503224 -0.6, 33000, 0.514491998, -644.5488336, 0.013995768, 1719.432256 -0.6, 33000, 0.578803497, 137.1354864, 0.094426835, 1934.361288 -0.6, 33000, 0.643114997, 918.8197712, 0.174857906, 2149.29032 -0.6, 33000, 0.707426497, 1804.413126, 0.266648896, 2364.219352 -0.6, 33000, 0.771737996, 2945.69879, 0.391046396, 2579.148384 -0.6, 33000, 0.836049496, 4351.858299, 0.553447089, 2794.077416 -0.6, 33000, 0.900360996, 5802.171046, 0.742669251, 3009.006448 -0.6, 33000, 0.964672496, 6968.663866, 0.93985536, 3223.93548 -0.6, 36000, 0, 197.9840635, 0.054995573, 0 -0.6, 36000, 0.375573372, -2307.2292, -0.159815667, 1255.166208 -0.6, 36000, 0.438168934, -1590.2949, -0.086693, 1464.360576 -0.6, 36000, 0.500764496, -873.3605, -0.013570333, 1673.554944 -0.6, 36000, 0.563360057, -156.4261, 0.059552333, 1882.749312 -0.6, 36000, 0.625955619, 560.5083, 0.132675028, 2091.94368 -0.6, 36000, 0.688551181, 1321.8441, 0.210634056, 2301.138048 -0.6, 36000, 0.751146743, 2276.0854, 0.312475611, 2510.332416 -0.6, 36000, 0.813742305, 3475.9856, 0.448323528, 2719.526784 -0.6, 36000, 0.876337867, 4685.7837, 0.603585278, 2928.721152 -0.6, 36000, 0.938933429, 5667.9429, 0.765220417, 3137.91552 -0.6, 39000, 0, 171.4691607, 0.047630322, 0 -0.6, 39000, 0.375267361, -2002.4923, -0.144595667, 1254.14352 -0.6, 39000, 0.437811921, -1421.9152, -0.083109111, 1463.16744 -0.6, 39000, 0.500356481, -841.338, -0.021622528, 1672.19136 -0.6, 39000, 0.562901041, -260.7607, 0.039864028, 1881.21528 -0.6, 39000, 0.625445601, 319.8165, 0.101350611, 2090.2392 -0.6, 39000, 0.687990162, 946.512, 0.167432333, 2299.26312 -0.6, 39000, 0.750534722, 1775.4984, 0.255129917, 2508.28704 -0.6, 39000, 0.813079282, 2814.5869, 0.371961444, 2717.31096 -0.6, 39000, 0.875623842, 3862.8923, 0.504523389, 2926.33488 -0.6, 39000, 0.938168402, 4767.5283, 0.6490115, 3135.3588 -0.6, 42000, 0, 148.4447869, 0.041234663, 0 -0.6, 42000, 0.375267361, -7912.092838, -0.798629229, 1254.14352 -0.6, 42000, 0.437811921, -6127.016637, -0.604012188, 1463.16744 -0.6, 42000, 0.500356481, -4341.940187, -0.409395155, 1672.19136 -0.6, 42000, 0.562901041, -2556.865137, -0.214777939, 1881.21528 -0.6, 42000, 0.625445601, -771.789125, -0.020161141, 2090.2392 -0.6, 42000, 0.687990162, 508.2581187, 0.118384528, 2299.26312 -0.6, 42000, 0.750534722, 1367.796362, 0.206619953, 2508.28704 -0.6, 42000, 0.813079282, 2147.864519, 0.300650611, 2717.31096 -0.6, 42000, 0.875623842, 3218.840587, 0.43469874, 2926.33488 -0.6, 42000, 0.938168402, 3964.538425, 0.549413264, 3135.3588 -0.65, 0, 0, 792.7024451, 0.220195124, 0 -0.65, 0, 0.504935022, -8986.311, -0.056953611, 1687.492845 -0.65, 0, 0.58909086, -4193.0778, 0.209476361, 1968.741652 -0.65, 0, 0.673246697, 600.1659, 0.475907889, 2249.99046 -0.65, 0, 0.757402534, 4169.0509, 0.793511694, 2531.239268 -0.65, 0, 0.841558371, 3476.7005, 1.13522275, 2812.488075 -0.65, 0, 0.925714208, 2286.0993, 1.571410778, 3093.736883 -0.65, 3000, 0, 717.8963317, 0.199415648, 0 -0.65, 3000, 0.494520318, -425.4664374, 0.050148686, 1652.686902 -0.65, 3000, 0.576940371, 468.8010719, 0.241492767, 1928.134719 -0.65, 3000, 0.659360424, 1363.097191, 0.432841321, 2203.582536 -0.65, 3000, 0.741780477, 3011.832179, 0.666772762, 2479.030353 -0.65, 3000, 0.82420053, 7474.005588, 1.047942321, 2754.47817 -0.65, 3000, 0.906620583, 9944.852812, 1.507898037, 3029.925987 -0.65, 3000, 0.989040636, 9336.356808, 1.976080758, 3305.373804 -0.65, 6000, 0, 648.7790382, 0.180216399, 0 -0.65, 6000, 0.48410464, -6060.3229, -0.002723333, 1617.877706 -0.65, 6000, 0.564788746, -3115.9737, 0.182463694, 1887.52399 -0.65, 6000, 0.645472853, -171.6051, 0.36765075, 2157.170274 -0.65, 6000, 0.726156959, 2660.584, 0.579830194, 2426.816558 -0.65, 6000, 0.806841066, 6493.0763, 0.905925333, 2696.462843 -0.65, 6000, 0.887525173, 7988.587, 1.245872944, 2966.109127 -0.65, 6000, 0.968209279, 13065.787, 1.930307833, 3235.755411 -0.65, 9000, 0, 585.0279309, 0.162507759, 0 -0.65, 9000, 0.473689935, -1700.503211, -0.017421508, 1583.071763 -0.65, 9000, 0.552638257, -307.4999679, 0.151362156, 1846.917056 -0.65, 9000, 0.63158658, 1085.502243, 0.32014578, 2110.76235 -0.65, 9000, 0.710534902, 2605.491007, 0.508556789, 2374.607644 -0.65, 9000, 0.789483225, 4721.692861, 0.770475495, 2638.452938 -0.65, 9000, 0.868431547, 7806.446846, 1.146306793, 2902.298231 -0.65, 9000, 0.94737987, 11671.69505, 1.660554392, 3166.143525 -0.65, 12000, 0, 526.3264286, 0.146201786, 0 -0.65, 12000, 0.463274257, -2317.344608, -0.0500563, 1548.262566 -0.65, 12000, 0.540486633, -839.7218247, 0.108132212, 1806.306327 -0.65, 12000, 0.617699009, 637.900887, 0.2663207, 2064.350088 -0.65, 12000, 0.694911385, 2175.16554, 0.435144853, 2322.393849 -0.65, 12000, 0.772123761, 4118.990162, 0.662646793, 2580.43761 -0.65, 12000, 0.849336137, 6640.068919, 0.973238435, 2838.481371 -0.65, 12000, 0.926548513, 10127.73521, 1.423579955, 3096.525132 -0.65, 15000, 0, 472.3782949, 0.131216193, 0 -0.65, 15000, 0.452859552, -2025.0591, -0.064995194, 1513.456623 -0.65, 15000, 0.528336144, -767.4877, 0.078061639, 1765.699394 -0.65, 15000, 0.603812736, 490.0835, 0.2211185, 2017.942164 -0.65, 15000, 0.679289328, 1767.7186, 0.366744972, 2270.184935 -0.65, 15000, 0.75476592, 3444.229, 0.561401667, 2522.427705 -0.65, 15000, 0.830242512, 5711.7251, 0.833256778, 2774.670476 -0.65, 15000, 0.905719104, 8684.4023, 1.210495333, 3026.913246 -0.65, 15000, 0.981195696, 11932.0693, 1.659813778, 3279.156017 -0.65, 18000, 0, 422.8954788, 0.117470966, 0 -0.65, 18000, 0.442443874, -2094.231596, -0.08447883, 1478.647427 -0.65, 18000, 0.51618452, -920.8062992, 0.046930613, 1725.088664 -0.65, 18000, 0.589925165, 252.619124, 0.178340056, 1971.529902 -0.65, 18000, 0.663665811, 1425.985671, 0.309742294, 2217.97114 -0.65, 18000, 0.737406456, 2877.673352, 0.475672193, 2464.412378 -0.65, 18000, 0.811147102, 4856.519299, 0.708029862, 2710.853615 -0.65, 18000, 0.884887748, 7428.133271, 1.028709103, 2957.294853 -0.65, 18000, 0.958628393, 10309.89734, 1.420516429, 3203.736091 -0.65, 21000, 0, 377.5986397, 0.104888511, 0 -0.65, 21000, 0.432029169, -2065.294921, -0.099302543, 1443.841484 -0.65, 21000, 0.504034031, -999.6529008, 0.020495277, 1684.481731 -0.65, 21000, 0.576038892, 65.989124, 0.140293116, 1925.121978 -0.65, 21000, 0.648043754, 1131.631086, 0.26009093, 2165.762225 -0.65, 21000, 0.720048615, 2362.032334, 0.39939131, 2406.402473 -0.65, 21000, 0.792053477, 4097.35921, 0.598606487, 2647.04272 -0.65, 21000, 0.864058338, 6311.42377, 0.868995475, 2887.682967 -0.65, 21000, 0.9360632, 8825.819702, 1.204116971, 3128.323214 -0.65, 24000, 0, 336.2232282, 0.093395341, 0 -0.65, 24000, 0.421613491, -2059.024546, -0.109579053, 1409.032287 -0.65, 24000, 0.491882406, -1079.36919, -0.001094946, 1643.871002 -0.65, 24000, 0.562151321, -99.7139104, 0.107389159, 1878.709716 -0.65, 24000, 0.632420237, 879.9414512, 0.215873247, 2113.548431 -0.65, 24000, 0.702689152, 1947.24601, 0.335220447, 2348.387145 -0.65, 24000, 0.772958067, 3399.061526, 0.499598478, 2583.22586 -0.65, 24000, 0.843226982, 5318.818936, 0.729114265, 2818.064574 -0.65, 24000, 0.913495897, 7475.72908, 1.009710588, 3052.903289 -0.65, 24000, 0.983764812, 9731.872028, 1.349804238, 3287.742003 -0.65, 27000, 0, 298.5128832, 0.082920245, 0 -0.65, 27000, 0.411198786, -1946.70211, -0.109149732, 1374.226344 -0.65, 27000, 0.479731917, -1077.663289, -0.013358162, 1603.264068 -0.65, 27000, 0.548265048, -208.6243848, 0.082433384, 1832.301792 -0.65, 27000, 0.61679818, 660.4145192, 0.178224937, 2061.339516 -0.65, 27000, 0.685331311, 1572.268415, 0.278918979, 2290.37724 -0.65, 27000, 0.753864442, 2814.368105, 0.417381779, 2519.414964 -0.65, 27000, 0.822397573, 4457.272203, 0.610072143, 2748.452688 -0.65, 27000, 0.890930704, 6322.386402, 0.846783724, 2977.490412 -0.65, 27000, 0.959463835, 8214.633226, 1.127008551, 3206.528136 -0.65, 30000, 0, 264.2255018, 0.073395973, 0 -0.65, 30000, 0.400783108, -1969.6383, -0.118640028, 1339.417148 -0.65, 30000, 0.467580293, -1168.3015, -0.031513889, 1562.653339 -0.65, 30000, 0.534377478, -366.9648, 0.055612278, 1785.88953 -0.65, 30000, 0.601174662, 434.372, 0.142738417, 2009.125721 -0.65, 30000, 0.667971847, 1235.7089, 0.229864583, 2232.361913 -0.65, 30000, 0.734769032, 2307.6687, 0.347613944, 2455.598104 -0.65, 30000, 0.801566216, 3709.4475, 0.508518611, 2678.834295 -0.65, 30000, 0.868363401, 5346.7598, 0.70983425, 2902.070486 -0.65, 30000, 0.935160586, 6983.832, 0.945475389, 3125.306678 -0.65, 33000, 0, 233.1253241, 0.064757034, 0 -0.65, 33000, 0.390368404, -2121.918406, -0.139269206, 1304.611205 -0.65, 33000, 0.455429804, -1356.051551, -0.057648242, 1522.046405 -0.65, 33000, 0.520491205, -590.1845056, 0.023972726, 1739.481606 -0.65, 33000, 0.585552605, 175.6825344, 0.105593703, 1956.916807 -0.65, 33000, 0.650614006, 941.5495752, 0.187214658, 2174.352008 -0.65, 33000, 0.715675406, 1839.790354, 0.283878911, 2391.787208 -0.65, 33000, 0.780736807, 3021.926602, 0.417462922, 2609.222409 -0.65, 33000, 0.845798208, 4453.759503, 0.589437606, 2826.65761 -0.65, 33000, 0.910859608, 5883.971598, 0.785740842, 3044.092811 -0.65, 33000, 0.975921009, 7093.745994, 0.998359109, 3261.528011 -0.65, 36000, 0, 204.9908832, 0.056941912, 0 -0.65, 36000, 0.379952725, -2204.3491, -0.153276222, 1269.802008 -0.65, 36000, 0.44327818, -1503.3511, -0.078855, 1481.435676 -0.65, 36000, 0.506603634, -802.353, -0.004433778, 1693.069344 -0.65, 36000, 0.569929088, -101.355, 0.069987444, 1904.703012 -0.65, 36000, 0.633254542, 599.6431, 0.144408694, 2116.33668 -0.65, 36000, 0.696579996, 1363.042, 0.226001722, 2327.970348 -0.65, 36000, 0.759905451, 2351.8755, 0.335153611, 2539.604016 -0.65, 36000, 0.823230905, 3571.9646, 0.479089861, 2751.237684 -0.65, 36000, 0.886556359, 4769.5376, 0.643312028, 2962.871352 -0.65, 36000, 0.949881813, 5753.311, 0.808763694, 3174.50502 -0.65, 39000, 0, 177.5375961, 0.049315999, 0 -0.65, 39000, 0.379643146, -2079.6423, -0.150360694, 1268.767395 -0.65, 39000, 0.442917004, -1475.5615, -0.085232722, 1480.228628 -0.65, 39000, 0.506190862, -871.4808, -0.02010475, 1691.68986 -0.65, 39000, 0.569464719, -267.4001, 0.045023194, 1903.151093 -0.65, 39000, 0.632738577, 336.6807, 0.110151167, 2114.612325 -0.65, 39000, 0.696012435, 995.0392, 0.181434194, 2326.073558 -0.65, 39000, 0.759286293, 1838.3538, 0.274411583, 2537.53479 -0.65, 39000, 0.82256015, 2900.0544, 0.398173806, 2748.996023 -0.65, 39000, 0.885834008, 3944.9355, 0.5392555, 2960.457255 -0.65, 39000, 0.949107866, 4862.9863, 0.689935028, 3171.918488 -0.65, 42000, 0, 153.6983706, 0.042693992, 0 -0.65, 42000, 0.379643146, -4454.834913, -0.428770521, 1268.767395 -0.65, 42000, 0.442917004, -3405.792437, -0.311698285, 1480.228628 -0.65, 42000, 0.506190862, -2356.749687, -0.194626082, 1691.68986 -0.65, 42000, 0.569464719, -1307.707313, -0.077553818, 1903.151093 -0.65, 42000, 0.632738577, -258.66475, 0.039518349, 2114.612325 -0.65, 42000, 0.696012435, 630.2993562, 0.137981049, 2326.073558 -0.65, 42000, 0.759286293, 1385.454412, 0.220850137, 2537.53479 -0.65, 42000, 0.82256015, 2283.647081, 0.325360153, 2748.996023 -0.65, 42000, 0.885834008, 3208.840912, 0.447495247, 2960.457255 -0.65, 42000, 0.949107866, 4068.181675, 0.584329965, 3171.918488 -0.7, 0, 0, 822.675472, 0.228520964, 0 -0.7, 0, 0.511220521, -13019.3017, -0.108485583, 1708.49898 -0.7, 0, 0.596423941, -6521.0009, 0.192641361, 1993.24881 -0.7, 0, 0.681627361, -22.6841, 0.493770639, 2277.99864 -0.7, 0, 0.766830781, 4125.0247, 0.843960028, 2562.74847 -0.7, 0, 0.852034201, 1281.1685, 1.173071639, 2847.4983 -0.7, 0, 0.937237621, -2232.3952, 1.577470278, 3132.24813 -0.7, 3000, 0, 745.0408501, 0.206955792, 0 -0.7, 3000, 0.500676172, 436.9773931, 0.073225841, 1673.259768 -0.7, 3000, 0.584122201, 824.2919287, 0.265804395, 1952.136396 -0.7, 3000, 0.66756823, 1211.653145, 0.45839024, 2231.013024 -0.7, 3000, 0.751014259, 2681.24984, 0.701074324, 2509.889652 -0.7, 3000, 0.834460287, 8163.985986, 1.11509793, 2788.76628 -0.7, 3000, 0.917906316, 9956.33145, 1.593642135, 3067.642908 -0.7, 6000, 0, 673.3101491, 0.187030597, 0 -0.7, 6000, 0.490130838, -8741.0898, 0.003749694, 1638.017262 -0.7, 6000, 0.571819311, -4938.6871, 0.194619167, 1911.020139 -0.7, 6000, 0.653507785, -1136.2522, 0.385488667, 2184.023016 -0.7, 6000, 0.735196258, 2378.5183, 0.608040833, 2457.025893 -0.7, 6000, 0.816884731, 7181.3604, 0.970353111, 2730.02877 -0.7, 6000, 0.898573204, 7254.1131, 1.263678167, 3003.031647 -0.7, 6000, 0.980261677, 12777.5848, 2.045335528, 3276.034524 -0.7, 9000, 0, 607.1485363, 0.168652371, 0 -0.7, 9000, 0.47958649, -1599.879021, -0.003548488, 1602.77805 -0.7, 9000, 0.559517572, -259.4922357, 0.168715673, 1869.907725 -0.7, 9000, 0.639448654, 1080.893486, 0.340979782, 2137.0374 -0.7, 9000, 0.719379735, 2583.088014, 0.539157077, 2404.167075 -0.7, 9000, 0.799310817, 4765.228021, 0.818582129, 2671.29675 -0.7, 9000, 0.879241899, 7974.031893, 1.223033363, 2938.426425 -0.7, 9000, 0.95917298, 11801.09709, 1.763350673, 3205.5561 -0.7, 12000, 0, 546.22746, 0.15172985, 0 -0.7, 12000, 0.469041156, -2415.962284, -0.040320867, 1567.535544 -0.7, 12000, 0.547214682, -907.3567092, 0.122392799, 1828.791468 -0.7, 12000, 0.625388208, 601.2487619, 0.28510645, 2090.047392 -0.7, 12000, 0.703561734, 2181.370807, 0.463077632, 2351.303316 -0.7, 12000, 0.78173526, 4172.977626, 0.704861067, 2612.55924 -0.7, 12000, 0.859908786, 6741.132033, 1.035272749, 2873.815164 -0.7, 12000, 0.938082312, 10353.41219, 1.518274781, 3135.071088 -0.7, 15000, 0, 490.2394829, 0.136177634, 0 -0.7, 15000, 0.458496808, -1946.59508, -0.053131456, 1532.296332 -0.7, 15000, 0.534912943, -723.95252, 0.092945597, 1787.679054 -0.7, 15000, 0.611329077, 498.68998, 0.239022706, 2043.061776 -0.7, 15000, 0.687745212, 1775.41815, 0.391718767, 2298.444498 -0.7, 15000, 0.764161346, 3490.86259, 0.598594772, 2553.82722 -0.7, 15000, 0.840577481, 5818.84094, 0.886573011, 2809.209942 -0.7, 15000, 0.916993616, 8894.50017, 1.293143119, 3064.592664 -0.7, 15000, 0.99340975, 12116.06083, 1.756708978, 3319.975386 -0.7, 18000, 0, 438.8856623, 0.121912684, 0 -0.7, 18000, 0.447951474, -2026.140203, -0.074008274, 1497.053826 -0.7, 18000, 0.522610053, -873.2838232, 0.06051716, 1746.562797 -0.7, 18000, 0.597268632, 279.5725768, 0.195042572, 1996.071768 -0.7, 18000, 0.671927211, 1431.71589, 0.329487448, 2245.580739 -0.7, 18000, 0.74658579, 2919.174166, 0.506141181, 2495.08971 -0.7, 18000, 0.821244369, 4970.509167, 0.756013586, 2744.598681 -0.7, 18000, 0.895902948, 7601.833838, 1.096433013, 2994.107652 -0.7, 18000, 0.970561527, 10552.04146, 1.513481644, 3243.616623 -0.7, 21000, 0, 391.8760956, 0.108854471, 0 -0.7, 21000, 0.437407126, -2058.549906, -0.093057636, 1461.814614 -0.7, 21000, 0.510308313, -994.0279152, 0.030476834, 1705.450383 -0.7, 21000, 0.583209501, 70.4941624, 0.154011312, 1949.086152 -0.7, 21000, 0.656110689, 1135.016129, 0.277545807, 2192.721921 -0.7, 21000, 0.729011876, 2418.250125, 0.427118166, 2436.35769 -0.7, 21000, 0.801913064, 4185.785828, 0.63832932, 2679.993459 -0.7, 21000, 0.874814251, 6471.901386, 0.928288732, 2923.629228 -0.7, 21000, 0.947715439, 9049.59687, 1.285773261, 3167.264997 -0.7, 24000, 0, 348.9362303, 0.096926731, 0 -0.7, 24000, 0.426861792, -2117.80628, -0.11001035, 1426.572108 -0.7, 24000, 0.498005424, -1121.716286, 0.003325352, 1664.334126 -0.7, 24000, 0.569149056, -125.6263264, 0.116661054, 1902.096144 -0.7, 24000, 0.640292688, 870.463628, 0.229996783, 2139.858162 -0.7, 24000, 0.71143632, 1967.761193, 0.356327829, 2377.62018 -0.7, 24000, 0.782579952, 3469.587282, 0.533233735, 2615.382198 -0.7, 24000, 0.853723583, 5457.373453, 0.7791253, 2853.144216 -0.7, 24000, 0.924867215, 7676.84781, 1.078405492, 3090.906234 -0.7, 24000, 0.996010847, 10022.14139, 1.445092484, 3328.668252 -0.7, 27000, 0, 309.8000121, 0.086055559, 0 -0.7, 27000, 0.416317443, -2030.502564, -0.115549098, 1391.332896 -0.7, 27000, 0.485703684, -1136.722539, -0.013929143, 1623.221712 -0.7, 27000, 0.555089925, -242.9424976, 0.087690812, 1855.110528 -0.7, 27000, 0.624476165, 650.8375472, 0.189310793, 2086.999344 -0.7, 27000, 0.693862406, 1604.376058, 0.298196759, 2318.88816 -0.7, 27000, 0.763248646, 2876.443616, 0.445815831, 2550.776976 -0.7, 27000, 0.832634887, 4577.720182, 0.651919655, 2782.665792 -0.7, 27000, 0.902021127, 6499.50754, 0.90453154, 3014.554608 -0.7, 27000, 0.971407368, 8408.642636, 1.201979159, 3246.443424 -0.7, 30000, 0, 274.2161839, 0.076171162, 0 -0.7, 30000, 0.40577211, -1848.1926, -0.109766306, 1356.09039 -0.7, 30000, 0.473400794, -1073.736, -0.021267694, 1582.105455 -0.7, 30000, 0.541029479, -299.2792, 0.067230889, 1808.12052 -0.7, 30000, 0.608658164, 475.1775, 0.155729472, 2034.135585 -0.7, 30000, 0.676286849, 1260.9569, 0.245488472, 2260.15065 -0.7, 30000, 0.743915534, 2355.8538, 0.370660528, 2486.165715 -0.7, 30000, 0.811544219, 3815.4302, 0.543463972, 2712.18078 -0.7, 30000, 0.879172904, 5479.6533, 0.757517972, 2938.195845 -0.7, 30000, 0.946801589, 7139.9893, 1.008519083, 3164.21091 -0.7, 33000, 0, 241.9400713, 0.067205575, 0 -0.7, 33000, 0.395227761, -1961.491211, -0.128100585, 1320.851178 -0.7, 33000, 0.461099055, -1228.507937, -0.045945794, 1540.993041 -0.7, 33000, 0.526970348, -495.5246472, 0.036208986, 1761.134904 -0.7, 33000, 0.592841642, 237.4586816, 0.118363796, 1981.276767 -0.7, 33000, 0.658712935, 970.4420496, 0.200518555, 2201.41863 -0.7, 33000, 0.724584229, 1889.083378, 0.303825084, 2421.560493 -0.7, 33000, 0.790455522, 3121.536466, 0.447674504, 2641.702356 -0.7, 33000, 0.856326816, 4583.718986, 0.629418011, 2861.844219 -0.7, 33000, 0.92219811, 6002.152557, 0.835419066, 3081.986082 -0.7, 33000, 0.988069403, 7187.438087, 1.052555017, 3302.127945 -0.7, 36000, 0, 212.7418335, 0.059094954, 0 -0.7, 36000, 0.384682427, -2059.2275, -0.144204889, 1285.608672 -0.7, 36000, 0.448796165, -1382.7578, -0.068822222, 1499.876784 -0.7, 36000, 0.512909903, -706.2883, 0.006560444, 1714.144896 -0.7, 36000, 0.577023641, -29.8187, 0.081943111, 1928.413008 -0.7, 36000, 0.641137379, 646.6509, 0.157325778, 2142.68112 -0.7, 36000, 0.705251117, 1411.1862, 0.242746861, 2356.949232 -0.7, 36000, 0.769364855, 2431.1023, 0.359492417, 2571.217344 -0.7, 36000, 0.833478592, 3647.2917, 0.511597806, 2785.485456 -0.7, 36000, 0.89759233, 4915.9219, 0.688503417, 2999.753568 -0.7, 36000, 0.961706068, 5891.7319, 0.862826056, 3214.02168 -0.7, 39000, 0, 184.2505048, 0.051180696, 0 -0.7, 39000, 0.384368995, -2107.7874, -0.1550415, 1284.56118 -0.7, 39000, 0.448430494, -1490.2678, -0.086235389, 1498.65471 -0.7, 39000, 0.512491993, -872.7485, -0.017429278, 1712.74824 -0.7, 39000, 0.576553492, -255.2291, 0.051376833, 1926.84177 -0.7, 39000, 0.640614991, 362.2903, 0.120182944, 2140.9353 -0.7, 39000, 0.70467649, 1041.8745, 0.196125111, 2355.02883 -0.7, 39000, 0.768737989, 1906.0032, 0.2951475, 2569.12236 -0.7, 39000, 0.832799488, 2980.8162, 0.426384611, 2783.21589 -0.7, 39000, 0.896860987, 4045.2249, 0.574582056, 2997.30942 -0.7, 39000, 0.960922487, 4979.7378, 0.735868861, 3211.40295 -0.7, 42000, 0, 159.5098897, 0.044308303, 0 -0.7, 42000, 0.384368995, -2873.663287, -0.257814979, 1284.56118 -0.7, 42000, 0.448430494, -2154.866738, -0.174947993, 1498.65471 -0.7, 42000, 0.512491993, -1436.070088, -0.092081023, 1712.74824 -0.7, 42000, 0.576553492, -717.2733875, -0.009214043, 1926.84177 -0.7, 42000, 0.640614991, 1.523225, 0.073652936, 2140.9353 -0.7, 42000, 0.70467649, 698.9133437, 0.153118292, 2355.02883 -0.7, 42000, 0.768737989, 1440.743563, 0.23804678, 2569.12236 -0.7, 42000, 0.832799488, 2383.672994, 0.35148425, 2783.21589 -0.7, 42000, 0.896860987, 3287.898338, 0.475790781, 2997.30942 -0.7, 42000, 0.960922487, 4146.564725, 0.618697167, 3211.40295 -0.75, 0, 0, 855.7001097, 0.237694475, 0 -0.75, 0, 0.517971611, -18285.47853, -0.179207861, 1731.061125 -0.75, 0, 0.604300213, -9540.39485, 0.166162083, 2019.571312 -0.75, 0, 0.690628815, -795.288075, 0.511535361, 2308.0815 -0.75, 0, 0.776957417, 4091.459675, 0.900363806, 2596.591688 -0.75, 0, 0.863286019, -1575.096575, 1.207936451, 2885.101875 -0.75, 0, 0.949614621, -8051.1931, 1.563821132, 3173.612063 -0.75, 3000, 0, 774.9490034, 0.215263612, 0 -0.75, 3000, 0.507288016, 1601.554964, 0.100524589, 1695.35655 -0.75, 3000, 0.591836019, 1316.41821, 0.293567013, 1977.915975 -0.75, 3000, 0.676384022, 1031.352407, 0.48662051, 2260.4754 -0.75, 3000, 0.760932024, 2263.849973, 0.738200099, 2543.034825 -0.75, 3000, 0.845480027, 9103.999039, 1.189633501, 2825.59425 -0.75, 3000, 0.93002803, 9983.064307, 1.687752213, 3108.153675 -0.75, 6000, 0, 700.338819, 0.194538561, 0 -0.75, 6000, 0.496603422, -12371.0544, 0.008999167, 1659.648638 -0.75, 6000, 0.579370659, -7401.0296, 0.206220167, 1936.256744 -0.75, 6000, 0.662137896, -2430.9552, 0.403441194, 2212.86485 -0.75, 6000, 0.744905134, 2004.8667, 0.637364222, 2489.472956 -0.75, 6000, 0.827672371, 8134.4242, 1.045158056, 2766.081063 -0.75, 6000, 0.910439608, 6181.6668, 1.263836278, 3042.689169 -0.75, 6000, 0.993206845, 12260.3074, 2.167115194, 3319.297275 -0.75, 9000, 0, 631.5212824, 0.175422578, 0 -0.75, 9000, 0.485919827, -1552.741938, 0.010342097, 1623.944063 -0.75, 9000, 0.566906465, -254.5568375, 0.186543309, 1894.601406 -0.75, 9000, 0.647893103, 1043.6275, 0.362744479, 2165.25875 -0.75, 9000, 0.728879741, 2545.739175, 0.572451038, 2435.916094 -0.75, 9000, 0.809866379, 4856.654063, 0.87314476, 2706.573438 -0.75, 9000, 0.890853017, 8208.842563, 1.310264052, 2977.230781 -0.75, 9000, 0.971839654, 11922.29046, 1.87443258, 3247.888125 -0.75, 12000, 0, 568.1546532, 0.157820737, 0 -0.75, 12000, 0.475235233, -2414.210824, -0.027975375, 1588.23615 -0.75, 12000, 0.554441106, -906.1498806, 0.138941417, 1852.942175 -0.75, 12000, 0.633646978, 601.9109994, 0.305858211, 2117.6482 -0.75, 12000, 0.71285285, 2180.209945, 0.492336712, 2382.354225 -0.75, 12000, 0.792058722, 4219.624693, 0.75024092, 2647.06025 -0.75, 12000, 0.871264595, 6873.042959, 1.106953233, 2911.766275 -0.75, 12000, 0.950470467, 10623.50939, 1.623070864, 3176.4723 -0.75, 15000, 0, 509.9191523, 0.141644209, 0 -0.75, 15000, 0.464551638, -1862.80462, -0.040220128, 1552.531575 -0.75, 15000, 0.541976911, -676.74108, 0.109030444, 1811.286838 -0.75, 15000, 0.619402184, 509.32252, 0.258281072, 2070.0421 -0.75, 15000, 0.696827457, 1791.3457, 0.418589928, 2328.797363 -0.75, 15000, 0.77425273, 3558.12386, 0.639309839, 2587.552625 -0.75, 15000, 0.851678003, 5947.89606, 0.946709961, 2846.307888 -0.75, 15000, 0.929103276, 9145.53788, 1.385806867, 3105.06315 -0.75, 18000, 0, 456.5038368, 0.126806621, 0 -0.75, 18000, 0.453867044, -1895.056081, -0.060514377, 1516.823663 -0.75, 18000, 0.529511552, -787.5809771, 0.076077194, 1769.627606 -0.75, 18000, 0.605156059, 319.8940414, 0.212668737, 2022.43155 -0.75, 18000, 0.680800567, 1455.50801, 0.352609505, 2275.235494 -0.75, 18000, 0.756445074, 2998.639607, 0.542268767, 2528.039438 -0.75, 18000, 0.832089581, 5096.756127, 0.807254759, 2780.843381 -0.75, 18000, 0.907734089, 7828.234139, 1.174474489, 3033.647325 -0.75, 18000, 0.983378596, 10768.63325, 1.612141874, 3286.451269 -0.75, 21000, 0, 407.6071664, 0.113224213, 0 -0.75, 21000, 0.443183449, -1994.685804, -0.08403891, 1481.119088 -0.75, 21000, 0.517047357, -942.6488512, 0.043066724, 1727.972269 -0.75, 21000, 0.590911266, 109.3881232, 0.170172333, 1974.82545 -0.75, 21000, 0.664775174, 1161.015351, 0.297224544, 2221.678631 -0.75, 21000, 0.738639082, 2485.164615, 0.457507322, 2468.531813 -0.75, 21000, 0.81250299, 4301.394193, 0.683326802, 2715.384994 -0.75, 21000, 0.886366899, 6674.529285, 0.994468054, 2962.238175 -0.75, 21000, 0.960230807, 9300.840274, 1.374940951, 3209.091356 -0.75, 24000, 0, 362.9435673, 0.100817658, 0 -0.75, 24000, 0.432498855, -2007.58331, -0.100445938, 1445.411175 -0.75, 24000, 0.504581998, -1039.136757, 0.01546093, 1686.313038 -0.75, 24000, 0.576665141, -70.6903952, 0.131367805, 1927.2149 -0.75, 24000, 0.648748283, 897.7559632, 0.247274667, 2168.116763 -0.75, 24000, 0.720831426, 2011.304227, 0.380743895, 2409.018625 -0.75, 24000, 0.792914568, 3583.664223, 0.572881662, 2649.920488 -0.75, 24000, 0.864997711, 5630.150038, 0.834177162, 2890.82235 -0.75, 24000, 0.937080854, 7910.87853, 1.157470056, 3131.724213 -0.75, 27000, 0, 322.236305, 0.089510085, 0 -0.75, 27000, 0.42181526, -2119.09668, -0.116447111, 1409.7066 -0.75, 27000, 0.492117804, -1195.703041, -0.009924592, 1644.6577 -0.75, 27000, 0.562420347, -272.309312, 0.096597926, 1879.6088 -0.75, 27000, 0.63272289, 651.0843952, 0.203120436, 2114.5599 -0.75, 27000, 0.703025434, 1645.588804, 0.319164741, 2349.511 -0.75, 27000, 0.773327977, 2951.861702, 0.477050988, 2584.4621 -0.75, 27000, 0.843630521, 4733.928442, 0.699052919, 2819.4132 -0.75, 27000, 0.913933064, 6696.33455, 0.969088014, 3054.3643 -0.75, 27000, 0.984235607, 8694.841082, 1.292653848, 3289.3154 -0.75, 30000, 0, 285.2240362, 0.079228899, 0 -0.75, 30000, 0.411130667, -2108.3203, -0.123733694, 1373.998688 -0.75, 30000, 0.479652444, -1261.5813, -0.027629778, 1602.998469 -0.75, 30000, 0.548174222, -414.8423, 0.068474167, 1831.99825 -0.75, 30000, 0.616696, 431.8966, 0.164578083, 2060.998031 -0.75, 30000, 0.685217778, 1309.3966, 0.264735222, 2289.997813 -0.75, 30000, 0.753739555, 2431.7522, 0.397761444, 2518.997594 -0.75, 30000, 0.822261333, 3950.679, 0.583753861, 2747.997375 -0.75, 30000, 0.890783111, 5654.978, 0.811681306, 2976.997156 -0.75, 30000, 0.959304889, 7341.8223, 1.080317778, 3205.996938 -0.75, 33000, 0, 251.6522645, 0.069903407, 0 -0.75, 33000, 0.400447071, -1946.435609, -0.123123964, 1338.294113 -0.75, 33000, 0.46718825, -1210.797384, -0.038654631, 1561.343131 -0.75, 33000, 0.533929428, -475.1592888, 0.04581467, 1784.39215 -0.75, 33000, 0.600670607, 260.478924, 0.130284001, 2007.441169 -0.75, 33000, 0.667411786, 994.974552, 0.21460645, 2230.490188 -0.75, 33000, 0.734152964, 1955.364478, 0.32655617, 2453.539206 -0.75, 33000, 0.800894143, 3233.559563, 0.48002382, 2676.588225 -0.75, 33000, 0.867635321, 4721.139566, 0.672593326, 2899.637244 -0.75, 33000, 0.9343765, 6164.250866, 0.894221229, 3122.686263 -0.75, 36000, 0, 221.2819228, 0.061467201, 0 -0.75, 36000, 0.389762478, -2063.2429, -0.137482694, 1302.5862 -0.75, 36000, 0.45472289, -1379.5815, -0.060521917, 1519.6839 -0.75, 36000, 0.519683303, -695.92, 0.016438861, 1736.7816 -0.75, 36000, 0.584643716, -12.2586, 0.093399611, 1953.8793 -0.75, 36000, 0.649604129, 671.4028, 0.170360417, 2170.977 -0.75, 36000, 0.714564542, 1465.9485, 0.260848222, 2388.0747 -0.75, 36000, 0.779524955, 2515.7607, 0.385887361, 2605.1724 -0.75, 36000, 0.844485368, 3764.5789, 0.548773639, 2822.2701 -0.75, 36000, 0.909445781, 5018.9062, 0.732465417, 3039.3678 -0.75, 36000, 0.974406194, 6063.2197, 0.926115861, 3256.4655 -0.75, 39000, 0, 191.6468675, 0.053235241, 0 -0.75, 39000, 0.389444906, -2080.6943, -0.158689611, 1301.524875 -0.75, 39000, 0.45435239, -1459.0957, -0.086017361, 1518.445688 -0.75, 39000, 0.519259874, -837.4968, -0.013345083, 1735.3665 -0.75, 39000, 0.584167359, -215.898, 0.059327194, 1952.287313 -0.75, 39000, 0.649074843, 405.7008, 0.131999444, 2169.208125 -0.75, 39000, 0.713982327, 1099.1818, 0.21219975, 2386.128938 -0.75, 39000, 0.778889811, 1982.8292, 0.317722611, 2603.04975 -0.75, 39000, 0.843797296, 3074.2878, 0.458709806, 2819.970563 -0.75, 39000, 0.90870478, 4156.585, 0.614176778, 3036.891375 -0.75, 39000, 0.973612264, 5099.6318, 0.785002111, 3253.812188 -0.75, 42000, 0, 165.9130906, 0.04608697, 0 -0.75, 42000, 0.389444906, -2435.906163, -0.206914493, 1301.524875 -0.75, 42000, 0.45435239, -1798.989538, -0.132026535, 1518.445688 -0.75, 42000, 0.519259874, -1162.072988, -0.057138561, 1735.3665 -0.75, 42000, 0.584167359, -525.1563625, 0.017749411, 1952.287313 -0.75, 42000, 0.649074843, 111.7602, 0.09263737, 2169.208125 -0.75, 42000, 0.713982327, 748.0753813, 0.167034868, 2386.128938 -0.75, 42000, 0.778889811, 1519.307012, 0.258225186, 2603.04975 -0.75, 42000, 0.843797296, 2473.777756, 0.379504569, 2819.970563 -0.75, 42000, 0.90870478, 3415.487863, 0.513087955, 3036.891375 -0.75, 42000, 0.973612264, 4233.545575, 0.656594924, 3253.812188 -0.8, 0, 0, 891.9670832, 0.247768634, 0 -0.8, 0, 0.525188294, -24946.3002, -0.271780361, 1755.17928 -0.8, 0, 0.612719677, -13342.1622, 0.128597583, 2047.70916 -0.8, 0, 0.700251059, -1737.9922, 0.528980111, 2340.23904 -0.8, 0, 0.787782442, 4066.9133, 0.963105333, 2632.76892 -0.8, 0, 0.875313824, -5182.1052, 1.238871778, 2925.2988 -0.8, 0, 0.962845206, -15340.1072, 1.527038278, 3217.82868 -0.8, 3000, 0, 807.7935183, 0.224387088, 0 -0.8, 3000, 0.514355849, 3115.377476, 0.132530568, 1718.977248 -0.8, 3000, 0.600081824, 1966.066515, 0.325113427, 2005.473456 -0.8, 3000, 0.685807799, 816.8578779, 0.517712243, 2291.969664 -0.8, 3000, 0.771533774, 1744.39178, 0.778232892, 2578.465872 -0.8, 3000, 0.857259749, 10327.32635, 1.271964589, 2864.96208 -0.8, 3000, 0.942985724, 10024.97898, 1.7907683, 3151.458288 -0.8, 6000, 0, 730.0211447, 0.202783651, 0 -0.8, 6000, 0.503522391, -17089.1935, 0.012718722, 1682.771832 -0.8, 6000, 0.58744279, -10597.8616, 0.217003694, 1963.233804 -0.8, 6000, 0.671363189, -4106.4574, 0.421288694, 2243.695776 -0.8, 6000, 0.755283587, 1522.2208, 0.667617889, 2524.157748 -0.8, 6000, 0.839203986, 9390.3585, 1.131507556, 2804.61972 -0.8, 6000, 0.923124384, 4708.8331, 1.242551389, 3085.081692 -0.8, 9000, 0, 658.2869277, 0.18285748, 0 -0.8, 9000, 0.492689946, -1581.926, 0.023781444, 1646.5698 -0.8, 9000, 0.574804937, -311.0476, 0.204492556, 1920.9981 -0.8, 9000, 0.656919928, 959.8308, 0.385203667, 2195.4264 -0.8, 9000, 0.739034919, 2485.5356, 0.608504833, 2469.8547 -0.8, 9000, 0.82114991, 5006.2559, 0.934958306, 2744.283 -0.8, 9000, 0.903264901, 8522.4023, 1.409097083, 3018.7113 -0.8, 9000, 0.985379892, 12028.084, 1.993811028, 3293.1396 -0.8, 12000, 0, 592.2346428, 0.164509623, 0 -0.8, 12000, 0.481856488, -2237.6416, -0.011880222, 1610.364384 -0.8, 12000, 0.562165903, -787.3421, 0.158510444, 1878.758448 -0.8, 12000, 0.642475318, 662.9575, 0.328901139, 2147.152512 -0.8, 12000, 0.722784732, 2163.1873, 0.522286333, 2415.546576 -0.8, 12000, 0.803094147, 4246.0806, 0.798383917, 2683.94064 -0.8, 12000, 0.883403562, 7036.1582, 1.189933139, 2952.334704 -0.8, 12000, 0.963712977, 10934.9111, 1.738158917, 3220.728768 -0.8, 15000, 0, 531.5309578, 0.147647488, 0 -0.8, 15000, 0.471024043, -1754.0936, -0.026050833, 1574.162352 -0.8, 15000, 0.54952805, -610.5999, 0.126497194, 1836.522744 -0.8, 15000, 0.628032057, 532.8938, 0.279045222, 2098.883136 -0.8, 15000, 0.706536065, 1815.9673, 0.446390861, 2361.243528 -0.8, 15000, 0.785040072, 3648.4075, 0.682909472, 2623.60392 -0.8, 15000, 0.863544079, 6097.6836, 1.015072639, 2885.964312 -0.8, 15000, 0.942048086, 9427.8906, 1.488324778, 3148.324704 -0.8, 18000, 0, 475.8517513, 0.132181042, 0 -0.8, 18000, 0.460190585, -1752.1545, -0.045709444, 1537.956936 -0.8, 18000, 0.536889016, -697.4081, 0.092759944, 1794.283092 -0.8, 18000, 0.613587447, 357.3382, 0.231229306, 2050.609248 -0.8, 18000, 0.690285878, 1487.0657, 0.378415722, 2306.935404 -0.8, 18000, 0.766984309, 3076.7988, 0.580794333, 2563.26156 -0.8, 18000, 0.84368274, 5257.2017, 0.865714917, 2819.587716 -0.8, 18000, 0.920381171, 8079.0391, 1.259892444, 3075.913872 -0.8, 18000, 0.997079601, 11682.7471, 1.718642306, 3332.240028 -0.8, 21000, 0, 424.8827027, 0.118022973, 0 -0.8, 21000, 0.44935814, -1936.362344, -0.072501929, 1501.754904 -0.8, 21000, 0.524251163, -895.9699432, 0.057498297, 1752.047388 -0.8, 21000, 0.599144187, 144.4224352, 0.187498528, 2002.339872 -0.8, 21000, 0.67403721, 1190.551023, 0.318246759, 2252.632356 -0.8, 21000, 0.748930233, 2572.760847, 0.49131064, 2502.92484 -0.8, 21000, 0.823823257, 4454.742441, 0.734282563, 2753.217324 -0.8, 21000, 0.89871628, 6906.615713, 1.067678883, 3003.509808 -0.8, 21000, 0.973609303, 9576.006558, 1.472685838, 3253.802292 -0.8, 24000, 0, 378.3261349, 0.105090593, 0 -0.8, 24000, 0.438524682, -1867.215134, -0.088993176, 1465.549488 -0.8, 24000, 0.511612129, -932.3074488, 0.029490958, 1709.807736 -0.8, 24000, 0.584699576, 2.6001568, 0.147975119, 1954.065984 -0.8, 24000, 0.657787023, 937.5077712, 0.266459222, 2198.324232 -0.8, 24000, 0.73087447, 2096.598395, 0.410890826, 2442.58248 -0.8, 24000, 0.803961917, 3710.547631, 0.61520531, 2686.840728 -0.8, 24000, 0.877049364, 5841.670122, 0.897066948, 2931.098976 -0.8, 24000, 0.950136811, 8176.213386, 1.244985104, 3175.357224 -0.8, 27000, 0, 335.8935845, 0.093303773, 0 -0.8, 27000, 0.427692237, -1977.18804, -0.104248156, 1429.347456 -0.8, 27000, 0.498974276, -1083.480113, 0.004058208, 1667.572032 -0.8, 27000, 0.570256316, -189.772212, 0.112364574, 1905.796608 -0.8, 27000, 0.641538355, 703.9355832, 0.220670911, 2144.021184 -0.8, 27000, 0.712820395, 1692.483944, 0.341882799, 2382.24576 -0.8, 27000, 0.784102434, 3068.206946, 0.513701089, 2620.470336 -0.8, 27000, 0.855384474, 4908.531766, 0.75130736, 2858.694912 -0.8, 27000, 0.926666513, 6922.472326, 1.041301513, 3096.919488 -0.8, 27000, 0.997948553, 9102.290086, 1.402915624, 3335.144064 -0.8, 30000, 0, 297.3126318, 0.082586842, 0 -0.8, 30000, 0.416858779, -2064.0918, -0.121842778, 1393.14204 -0.8, 30000, 0.486335242, -1218.4246, -0.021642194, 1625.33238 -0.8, 30000, 0.555811706, -372.7574, 0.078558417, 1857.52272 -0.8, 30000, 0.625288169, 472.9099, 0.178759, 2089.71306 -0.8, 30000, 0.694764632, 1370.5848, 0.285638833, 2321.9034 -0.8, 30000, 0.764241095, 2530.4714, 0.428460944, 2554.09374 -0.8, 30000, 0.833717558, 4107.3311, 0.6278905, 2786.28408 -0.8, 30000, 0.903194022, 5852.4536, 0.872377722, 3018.47442 -0.8, 30000, 0.972670485, 7598.4722, 1.160757917, 3250.66476 -0.8, 33000, 0, 262.3179942, 0.072866109, 0 -0.8, 33000, 0.406026334, -2072.612345, -0.129070288, 1356.940008 -0.8, 33000, 0.47369739, -1296.432944, -0.039181899, 1583.096676 -0.8, 33000, 0.541368445, -520.2535648, 0.050706476, 1809.253344 -0.8, 33000, 0.609039501, 255.925864, 0.140594867, 2035.410012 -0.8, 33000, 0.676710557, 1036.676152, 0.231070733, 2261.56668 -0.8, 33000, 0.744381612, 2035.166326, 0.351544361, 2487.723348 -0.8, 33000, 0.812052668, 3365.893767, 0.51607366, 2713.880016 -0.8, 33000, 0.879723724, 4871.020294, 0.721281174, 2940.036684 -0.8, 33000, 0.947394779, 6356.582314, 0.960879551, 3166.193352 -0.8, 36000, 0, 230.6604721, 0.064072353, 0 -0.8, 36000, 0.395192876, -2093.6506, -0.139668556, 1320.734592 -0.8, 36000, 0.461058355, -1394.4094, -0.058856083, 1540.857024 -0.8, 36000, 0.526923835, -695.1683, 0.021956361, 1760.979456 -0.8, 36000, 0.592789314, 4.073, 0.102768833, 1981.101888 -0.8, 36000, 0.658654794, 703.3141, 0.183581306, 2201.22432 -0.8, 36000, 0.724520273, 1537.8643, 0.281831694, 2421.346752 -0.8, 36000, 0.790385752, 2605.1218, 0.417286583, 2641.469184 -0.8, 36000, 0.856251232, 3906.2864, 0.589435222, 2861.591616 -0.8, 36000, 0.922116711, 5160.5278, 0.783068361, 3081.714048 -0.8, 36000, 0.98798219, 6214.9673, 0.984154861, 3301.83648 -0.8, 39000, 0, 199.7693999, 0.0554915, 0 -0.8, 39000, 0.39487088, -2166.2283, -0.159781083, 1319.65848 -0.8, 39000, 0.460682693, -1512.1345, -0.083507611, 1539.60156 -0.8, 39000, 0.526494506, -858.0406, -0.007234194, 1759.54464 -0.8, 39000, 0.59230632, -203.9467, 0.06903925, 1979.48772 -0.8, 39000, 0.658118133, 450.1472, 0.145312694, 2199.4308 -0.8, 39000, 0.723929946, 1165.0149, 0.230337111, 2419.37388 -0.8, 39000, 0.789741759, 2072.4602, 0.345027139, 2639.31696 -0.8, 39000, 0.855553573, 3202.9565, 0.493919583, 2859.26004 -0.8, 39000, 0.921365386, 4305.4131, 0.660432139, 3079.20312 -0.8, 39000, 0.987177199, 5206.1699, 0.829919028, 3299.1462 -0.8, 42000, 0, 172.9449533, 0.048040265, 0 -0.8, 42000, 0.39487088, -2368.1668, -0.19242583, 1319.65848 -0.8, 42000, 0.460682693, -1730.60195, -0.117422688, 1539.60156 -0.8, 42000, 0.526494506, -1093.0371, -0.042419512, 1759.54464 -0.8, 42000, 0.59230632, -455.4723625, 0.032583661, 1979.48772 -0.8, 42000, 0.658118133, 182.0924375, 0.107586821, 2199.4308 -0.8, 42000, 0.723929946, 816.2892187, 0.183324554, 2419.37388 -0.8, 42000, 0.789741759, 1604.931394, 0.281507597, 2639.31696 -0.8, 42000, 0.855553573, 2582.459444, 0.409849351, 2859.26004 -0.8, 42000, 0.921365386, 3546.213138, 0.551915297, 3079.20312 -0.8, 42000, 0.987177199, 4367.351431, 0.702654813, 3299.1462 -0.85, 0, 0, 931.6846059, 0.258801279, 0 -0.85, 0, 0.53287057, -33163.22545, -0.388863, 1780.853445 -0.85, 0, 0.621682332, -18017.2055, 0.078506917, 2077.662353 -0.85, 0, 0.710494093, -2871.14265, 0.545882944, 2374.47126 -0.85, 0, 0.799305855, 4049.94305, 1.032566917, 2671.280167 -0.85, 0, 0.888117617, -9629.86785, 1.264932208, 2968.089075 -0.85, 0, 0.976929378, -24268.9503, 1.463696653, 3264.897982 -0.85, 3000, 0, 843.7629593, 0.2343786, 0 -0.85, 3000, 0.521879671, 5025.556129, 0.169729417, 1744.121862 -0.85, 3000, 0.608859617, 2794.123445, 0.360776443, 2034.808839 -0.85, 3000, 0.695839562, 562.8324572, 0.55184555, 2325.495816 -0.85, 3000, 0.782819507, 1107.634459, 0.821255508, 2616.182793 -0.85, 3000, 0.869799452, 11867.24951, 1.362506751, 2906.86977 -0.85, 3000, 0.956779398, 10082.00308, 1.903230422, 3197.556747 -0.85, 6000, 0, 762.5275364, 0.211813205, 0 -0.85, 6000, 0.510887746, -23034.4839, 0.014602, 1707.386846 -0.85, 6000, 0.596035703, -14624.0435, 0.22670675, 1991.95132 -0.85, 6000, 0.681183661, -6213.5021, 0.438811528, 2276.515794 -0.85, 6000, 0.766331618, 913.1722, 0.698619361, 2561.080268 -0.85, 6000, 0.851479576, 10987.2541, 1.230569, 2845.644743 -0.85, 6000, 0.936627533, 2773.197, 1.196027611, 3130.209217 -0.85, 9000, 0, 687.5991372, 0.19099976, 0 -0.85, 9000, 0.499896847, -1710.26525, 0.03630075, 1670.655263 -0.85, 9000, 0.583212988, -447.31835, 0.222210903, 1949.097806 -0.85, 9000, 0.666529129, 815.6299, 0.408121139, 2227.54035 -0.85, 9000, 0.74984527, 2394.5684, 0.647384625, 2505.982894 -0.85, 9000, 0.833161412, 5224.31845, 1.004817681, 2784.425438 -0.85, 9000, 0.916477553, 8926.23455, 1.520630681, 3062.867981 -0.85, 9000, 0.999793694, 12111.28655, 2.121496931, 3341.310525 -0.85, 12000, 0, 618.6056752, 0.17183491, 0 -0.85, 12000, 0.488904921, -1811.805983, 0.009104192, 1633.920246 -0.85, 12000, 0.570389075, -502.1741282, 0.18183226, 1906.240287 -0.85, 12000, 0.651873228, 807.4581645, 0.354560393, 2178.560328 -0.85, 12000, 0.733357382, 2121.807216, 0.552290734, 2450.880369 -0.85, 12000, 0.814841535, 4239.494583, 0.848887622, 2723.20041 -0.85, 12000, 0.896325689, 7230.83426, 1.285865719, 2995.520451 -0.85, 12000, 0.977809842, 11284.50163, 1.863729653, 3267.840492 -0.85, 15000, 0, 555.1989757, 0.154221938, 0 -0.85, 15000, 0.477914022, -1600.8679, -0.010413194, 1597.188663 -0.85, 15000, 0.55756636, -510.2755, 0.145526861, 1863.386774 -0.85, 15000, 0.637218697, 580.3165, 0.301466778, 2129.584884 -0.85, 15000, 0.716871034, 1849.749, 0.474153972, 2395.782995 -0.85, 15000, 0.796523371, 3764.1082, 0.728756278, 2661.981105 -0.85, 15000, 0.876175708, 6266.9967, 1.093066056, 2928.179216 -0.85, 15000, 0.955828045, 9731.9335, 1.600535056, 3194.377326 -0.85, 18000, 0, 497.0404846, 0.138066801, 0 -0.85, 18000, 0.466922096, -1687.664315, -0.032728999, 1560.453647 -0.85, 18000, 0.544742446, -658.79398, 0.10909414, 1820.529254 -0.85, 18000, 0.622562795, 370.076455, 0.250917226, 2080.604862 -0.85, 18000, 0.700383145, 1514.094965, 0.405590857, 2340.68047 -0.85, 18000, 0.778203494, 3095.698725, 0.616555467, 2600.756078 -0.85, 18000, 0.856023844, 5489.965405, 0.937698136, 2860.831685 -0.85, 18000, 0.933844193, 8311.905815, 1.347448025, 3120.907293 -0.85, 21000, 0, 443.8018856, 0.123278302, 0 -0.85, 21000, 0.455931198, -2030.569984, -0.061354176, 1523.722064 -0.85, 21000, 0.531919731, -963.9674152, 0.071063091, 1777.675741 -0.85, 21000, 0.607908264, 102.6354272, 0.203480546, 2031.629418 -0.85, 21000, 0.683896797, 1196.484975, 0.33945094, 2285.583095 -0.85, 21000, 0.75988533, 2703.483559, 0.530208168, 2539.536773 -0.85, 21000, 0.835873863, 4652.772909, 0.791068324, 2793.49045 -0.85, 21000, 0.911862396, 7160.375461, 1.149350812, 3047.444127 -0.85, 21000, 0.987850929, 9868.793802, 1.57929783, 3301.397804 -0.85, 24000, 0, 395.1722462, 0.109770068, 0 -0.85, 24000, 0.444939272, -2172.624298, -0.085327792, 1486.987047 -0.85, 24000, 0.519095817, -1129.085861, 0.038639124, 1734.818222 -0.85, 24000, 0.593252363, -85.5475712, 0.162605982, 1982.649396 -0.85, 24000, 0.667408908, 957.9908592, 0.286572876, 2230.480571 -0.85, 24000, 0.741565453, 2199.473943, 0.44331979, 2478.311745 -0.85, 24000, 0.815721999, 3874.790819, 0.663057519, 2726.14292 -0.85, 24000, 0.889878544, 6064.753546, 0.966760394, 2973.974094 -0.85, 24000, 0.964035089, 8458.319502, 1.336008268, 3221.805269 -0.85, 27000, 0, 350.8502587, 0.097458405, 0 -0.85, 27000, 0.433948373, -1979.7891, -0.096291478, 1450.255464 -0.85, 27000, 0.506273102, -1075.611905, 0.015344869, 1691.964708 -0.85, 27000, 0.578597831, -171.434812, 0.126981255, 1933.673952 -0.85, 27000, 0.65092256, 732.7423512, 0.238617658, 2175.383196 -0.85, 27000, 0.723247289, 1756.220284, 0.368204934, 2417.09244 -0.85, 27000, 0.795572018, 3233.38963, 0.556508118, 2658.801684 -0.85, 27000, 0.867896747, 5107.15313, 0.808993545, 2900.510928 -0.85, 27000, 0.940221476, 7204.675762, 1.127757112, 3142.220172 -0.85, 30000, 0, 310.5513728, 0.08626427, 0 -0.85, 30000, 0.422956447, -1029.5775, -0.065394139, 1413.520448 -0.85, 30000, 0.493449189, -430.8531, 0.025653, 1649.107189 -0.85, 30000, 0.56394193, 167.8722, 0.116699944, 1884.69393 -0.85, 30000, 0.634434671, 766.598, 0.207746972, 2120.280671 -0.85, 30000, 0.704927412, 1434.0783, 0.306233306, 2355.867413 -0.85, 30000, 0.775420154, 2647.1189, 0.462303278, 2591.454154 -0.85, 30000, 0.845912895, 4277.5237, 0.674376111, 2827.040895 -0.85, 30000, 0.916405636, 6051.7998, 0.939660694, 3062.627636 -0.85, 30000, 0.986898377, 7919.0802, 1.249725944, 3298.214378 -0.85, 33000, 0, 273.9984934, 0.076110693, 0 -0.85, 33000, 0.411965549, -2004.589161, -0.136814644, 1376.788865 -0.85, 33000, 0.480626474, -1230.077204, -0.040365533, 1606.253675 -0.85, 33000, 0.549287399, -455.5648208, 0.05608365, 1835.718486 -0.85, 33000, 0.617948323, 318.947304, 0.152532755, 2065.183297 -0.85, 33000, 0.686609248, 1132.311052, 0.25397535, 2294.648108 -0.85, 33000, 0.755270173, 2141.301114, 0.380023007, 2524.112918 -0.85, 33000, 0.823931098, 3527.261091, 0.559638644, 2753.577729 -0.85, 33000, 0.892592023, 5086.397962, 0.779907733, 2983.04254 -0.85, 33000, 0.961252947, 6603.009402, 1.035231262, 3212.507351 -0.85, 36000, 0, 240.9313248, 0.066925368, 0 -0.85, 36000, 0.400973623, -1990.3196, -0.133432333, 1340.053848 -0.85, 36000, 0.46780256, -1303.5686, -0.050272083, 1563.396156 -0.85, 36000, 0.534631497, -616.8176, 0.032888167, 1786.738464 -0.85, 36000, 0.601460434, 69.9334, 0.116048444, 2010.080772 -0.85, 36000, 0.668289372, 756.6846, 0.199208667, 2233.42308 -0.85, 36000, 0.735118309, 1609.4241, 0.305680583, 2456.765388 -0.85, 36000, 0.801947246, 2729.0259, 0.450879139, 2680.107696 -0.85, 36000, 0.868776183, 4062.8066, 0.633790833, 2903.450004 -0.85, 36000, 0.93560512, 5356.0566, 0.844113833, 3126.792312 -0.85, 39000, 0, 208.6647345, 0.057962426, 0 -0.85, 39000, 0.400646917, -2125.7161, -0.151067917, 1338.961995 -0.85, 39000, 0.467421403, -1468.4615, -0.073362472, 1562.122328 -0.85, 39000, 0.534195889, -811.207, 0.004342944, 1785.28266 -0.85, 39000, 0.600970375, -153.9524, 0.082048361, 2008.442993 -0.85, 39000, 0.667744861, 503.3022, 0.159753778, 2231.603325 -0.85, 39000, 0.734519347, 1234.8854, 0.250918972, 2454.763658 -0.85, 39000, 0.801293833, 2177.3831, 0.374172694, 2677.92399 -0.85, 39000, 0.868068319, 3346.7278, 0.532521833, 2901.084323 -0.85, 39000, 0.934842805, 4473.4844, 0.712425528, 3124.244655 -0.85, 42000, 0, 180.6458486, 0.050179402, 0 -0.85, 42000, 0.400646917, -2263.5729, -0.173861851, 1338.961995 -0.85, 42000, 0.467421403, -1632.925075, -0.099613229, 1562.122328 -0.85, 42000, 0.534195889, -1002.277125, -0.025364599, 1785.28266 -0.85, 42000, 0.600970375, -371.6293875, 0.04888404, 2008.442993 -0.85, 42000, 0.667744861, 259.0184375, 0.123132679, 2231.603325 -0.85, 42000, 0.734519347, 901.3025562, 0.202384641, 2454.763658 -0.85, 42000, 0.801293833, 1698.112456, 0.307053833, 2677.92399 -0.85, 42000, 0.868068319, 2714.252956, 0.443427677, 2901.084323 -0.85, 42000, 0.934842805, 3678.519963, 0.593568071, 3124.244655 -0.9, 0, 0, 975.0792461, 0.270855346, 0 -0.9, 0, 0.541018438, -43097.713, -0.533115694, 1808.08362 -0.9, 0, 0.631188178, -23656.4273, 0.014449139, 2109.43089 -0.9, 0, 0.721357917, -4215.0856, 0.562021917, 2410.77816 -0.9, 0, 0.811527657, 4039.1064, 1.109130861, 2712.12543 -0.9, 0, 0.901697397, -15008.395, 1.285172333, 3013.4727 -0.9, 0, 0.991867136, -35007.5352, 1.370371194, 3314.81997 -0.9, 3000, 0, 883.0625139, 0.245295143, 0 -0.9, 3000, 0.529859483, 7379.202123, 0.212606775, 1770.790392 -0.9, 3000, 0.618169397, 3821.4756, 0.400888866, 2065.922124 -0.9, 3000, 0.706479311, 263.9390451, 0.589200542, 2361.053856 -0.9, 3000, 0.794789224, 338.3372111, 0.867350754, 2656.185588 -0.9, 3000, 0.883099138, 13757.05012, 1.461675542, 2951.31732 -0.9, 3000, 0.971409052, 10154.06419, 2.025678608, 3246.449052 -0.9, 6000, 0, 798.0434265, 0.22167873, 0 -0.9, 6000, 0.518699485, -30345.9024, 0.014342639, 1733.493678 -0.9, 6000, 0.605149399, -19574.4357, 0.235066333, 2022.409291 -0.9, 6000, 0.691599313, -8802.8326, 0.455790056, 2311.324904 -0.9, 6000, 0.778049227, 160.3125, 0.730186167, 2600.240517 -0.9, 6000, 0.864499141, 12963.2018, 1.343509778, 2889.15613 -0.9, 6000, 0.950949055, 312.3435, 1.120469056, 3178.071743 -0.9, 9000, 0, 719.6251221, 0.199895867, 0 -0.9, 9000, 0.50754053, -1960.593729, 0.04743121, 1696.20045 -0.9, 9000, 0.592130618, -681.7229143, 0.239345841, 1978.900525 -0.9, 9000, 0.676720706, 597.1513143, 0.43126069, 2261.6006 -0.9, 9000, 0.761310794, 2264.928686, 0.689156575, 2544.300675 -0.9, 9000, 0.845900883, 5521.126629, 1.083517802, 2827.00075 -0.9, 9000, 0.930490971, 9431.862757, 1.645963067, 3109.700825 -0.9, 12000, 0, 647.4181838, 0.179838384, 0 -0.9, 12000, 0.496380531, -1062.255344, 0.036117468, 1658.903736 -0.9, 12000, 0.57911062, -1.886726061, 0.209639241, 1935.387692 -0.9, 12000, 0.661840709, 1058.482894, 0.383161131, 2211.871648 -0.9, 12000, 0.744570797, 2047.574039, 0.581714154, 2488.355604 -0.9, 12000, 0.827300886, 4187.015878, 0.901349599, 2764.83956 -0.9, 12000, 0.910030974, 7457.427642, 1.396404226, 3041.323516 -0.9, 12000, 0.992761063, 11669.16526, 1.999973786, 3317.807472 -0.9, 15000, 0, 581.05822, 0.161405061, 0 -0.9, 15000, 0.485221576, -1383.5334, 0.006903167, 1621.610508 -0.9, 15000, 0.566091839, -360.5144, 0.166300458, 1891.878926 -0.9, 15000, 0.646962102, 662.5033, 0.325697361, 2162.147344 -0.9, 15000, 0.727832364, 1893.15685, 0.500911667, 2432.415762 -0.9, 15000, 0.808702627, 3907.62065, 0.776212861, 2702.68418 -0.9, 15000, 0.88957289, 6454.6285, 1.182095222, 2972.952598 -0.9, 15000, 0.970443153, 10048.04175, 1.722275903, 3243.221016 -0.9, 18000, 0, 520.190908, 0.144497474, 0 -0.9, 18000, 0.474061578, -1786.47608, -0.024521798, 1584.313794 -0.9, 18000, 0.553071841, -724.6719267, 0.123688794, 1848.366093 -0.9, 18000, 0.632082104, 337.13286, 0.271899254, 2112.418392 -0.9, 18000, 0.711092367, 1524.707847, 0.432907209, 2376.470691 -0.9, 18000, 0.79010263, 3000.0209, 0.6446556, 2640.52299 -0.9, 18000, 0.869112893, 5830.99326, 1.02918993, 2904.575289 -0.9, 18000, 0.948123156, 8486.44698, 1.432217319, 3168.627588 -0.9, 21000, 0, 464.4726394, 0.129020178, 0 -0.9, 21000, 0.462902623, -2413.970724, -0.053216872, 1547.020566 -0.9, 21000, 0.54005306, -1249.260867, 0.081267636, 1804.857327 -0.9, 21000, 0.617203497, -84.5498008, 0.215752747, 2062.694088 -0.9, 21000, 0.694353934, 1152.818807, 0.359712393, 2320.530849 -0.9, 21000, 0.771504372, 2898.081851, 0.575755381, 2578.36761 -0.9, 21000, 0.848654809, 4902.840497, 0.853655752, 2836.204371 -0.9, 21000, 0.925805246, 7427.583429, 1.240765702, 3094.041132 -0.9, 24000, 0, 413.578, 0.114882778, 0 -0.9, 24000, 0.451742625, -3380.377002, -0.09900223, 1509.723852 -0.9, 24000, 0.527033062, -1944.231593, 0.036208347, 1761.344494 -0.9, 24000, 0.6023235, -508.0869792, 0.171418562, 2012.965136 -0.9, 24000, 0.677613937, 928.0581272, 0.306629186, 2264.585778 -0.9, 24000, 0.752904375, 2298.104271, 0.474900955, 2516.20642 -0.9, 24000, 0.828194812, 4098.066687, 0.718966372, 2767.827062 -0.9, 24000, 0.90348525, 6273.94601, 1.042422335, 3019.447704 -0.9, 24000, 0.978775687, 8743.340178, 1.425776521, 3271.068346 -0.9, 27000, 0, 367.1916479, 0.10199768, 0 -0.9, 27000, 0.44058367, -2469.04386, -0.10854555, 1472.430624 -0.9, 27000, 0.514014281, -1423.591517, 0.01225553, 1717.835728 -0.9, 27000, 0.587444893, -378.139112, 0.133056747, 1963.240832 -0.9, 27000, 0.660875504, 667.3140992, 0.253858149, 2208.645936 -0.9, 27000, 0.734306116, 1847.187824, 0.399887231, 2454.05104 -0.9, 27000, 0.807736728, 3456.315954, 0.606307547, 2699.456144 -0.9, 27000, 0.881167339, 5334.240734, 0.872400059, 2944.861248 -0.9, 27000, 0.954597951, 7568.678658, 1.234724755, 3190.266352 -0.9, 30000, 0, 325.0157796, 0.090282161, 0 -0.9, 30000, 0.429423671, 1681.1522, 0.084311639, 1435.13391 -0.9, 30000, 0.500994283, 1614.546, 0.14321375, 1674.322895 -0.9, 30000, 0.572564895, 1547.9432, 0.202115056, 1913.51188 -0.9, 30000, 0.644135507, 1481.3415, 0.26101675, 2152.700865 -0.9, 30000, 0.715706119, 1489.4339, 0.324552639, 2391.88985 -0.9, 30000, 0.787276731, 2776.8022, 0.498832694, 2631.078835 -0.9, 30000, 0.858847343, 4453.394, 0.721712917, 2870.26782 -0.9, 30000, 0.930417955, 6232.7363, 1.013583694, 3109.456805 -0.9, 33000, 0, 286.7603937, 0.079655665, 0 -0.9, 33000, 0.418264716, -1438.511757, -0.138515868, 1397.840682 -0.9, 33000, 0.487975502, -780.159164, -0.036023395, 1630.814129 -0.9, 33000, 0.557686288, -121.8052568, 0.066469329, 1863.787576 -0.9, 33000, 0.627397075, 536.547744, 0.168961748, 2096.761023 -0.9, 33000, 0.697107861, 1317.005752, 0.287147939, 2329.73447 -0.9, 33000, 0.766818647, 2285.178942, 0.413072832, 2562.707917 -0.9, 33000, 0.836529433, 3726.148835, 0.614304273, 2795.681364 -0.9, 33000, 0.906240219, 5415.78917, 0.852683808, 3028.654811 -0.9, 33000, 0.975951005, 6924.21323, 1.117046918, 3261.628258 -0.9, 36000, 0, 252.1530709, 0.07004252, 0 -0.9, 36000, 0.407104718, -1593.1189, -0.101443889, 1360.543968 -0.9, 36000, 0.474955504, -983.3862, -0.021217278, 1587.301296 -0.9, 36000, 0.542806291, -373.6523, 0.0590095, 1814.058624 -0.9, 36000, 0.610657077, 236.0799, 0.139236111, 2040.815952 -0.9, 36000, 0.678507864, 845.8141, 0.219462722, 2267.57328 -0.9, 36000, 0.74635865, 1663.1184, 0.332378194, 2494.330608 -0.9, 36000, 0.814209436, 2917.3133, 0.483854083, 2721.087936 -0.9, 36000, 0.882060223, 4224.5319, 0.68204875, 2947.845264 -0.9, 36000, 0.949911009, 5620.7625, 0.919403417, 3174.602592 -0.9, 39000, 0, 218.3836147, 0.060662115, 0 -0.9, 39000, 0.406773016, -1720.4844, -0.125302111, 1359.43542 -0.9, 39000, 0.474568519, -1147.154, -0.050238278, 1586.00799 -0.9, 39000, 0.542364022, -573.8231, 0.024825889, 1812.58056 -0.9, 39000, 0.610159524, -0.4923, 0.099889889, 2039.15313 -0.9, 39000, 0.677955027, 572.8385, 0.174953778, 2265.7257 -0.9, 39000, 0.74575053, 1304.3049, 0.274327111, 2492.29827 -0.9, 39000, 0.813546032, 2300.0848, 0.402270889, 2718.87084 -0.9, 39000, 0.881341535, 3485.5072, 0.575024444, 2945.44341 -0.9, 39000, 0.949137038, 4642.5741, 0.769234333, 3172.01598 -0.9, 42000, 0, 189.0597062, 0.052516585, 0 -0.9, 42000, 0.406773016, -2081.7766, -0.15389151, 1359.43542 -0.9, 42000, 0.474568519, -1479.96, -0.081062938, 1586.00799 -0.9, 42000, 0.542364022, -878.14375, -0.00823445, 1812.58056 -0.9, 42000, 0.610159524, -276.3273125, 0.064594099, 2039.15313 -0.9, 42000, 0.677955027, 325.4889375, 0.13742255, 2265.7257 -0.9, 42000, 0.74575053, 960.1070438, 0.221415936, 2492.29827 -0.9, 42000, 0.813546032, 1816.055069, 0.333061292, 2718.87084 -0.9, 42000, 0.881341535, 2849.730019, 0.481629476, 2945.44341 -0.9, 42000, 0.949137038, 3854.696288, 0.648108276, 3172.01598 \ No newline at end of file diff --git a/aviary/models/engines/turbofan_24k_1.csv b/aviary/models/engines/turbofan_24k_1.csv new file mode 100644 index 0000000000..5200f43625 --- /dev/null +++ b/aviary/models/engines/turbofan_24k_1.csv @@ -0,0 +1,281 @@ +# created 04/22/25 +# GASP-derived engine deck converted from turbofan_24k_1.eng +# t4max: 3100.0 +# t4cruise: 2770.0 +# t4climb: 3030.0 +# sls_airflow: 794.67 +# sfn_idle: -10.0 + +Mach Number (input), Altitude (ft, input), Throttle (input), Thrust (lbf, output), Fuel Flow (lb/h, output), T4 (degR, output) + 0.0, 0.0, 0.1635, 119.332, 721.477, 1556.01 + 0.2, 0.0, 0.1703, 14.3682, 743.087, 1568.46 + 0.35, 0.0, 0.1842, -95.7382, 813.656, 1594.13 + 0.0, 0.0, 0.4445, 5986.566, 2297.7, 2074.68 + 0.2, 0.0, 0.4535, 4426.987, 2382.66, 2091.28 + 0.35, 0.0, 0.4721, 4101.651, 2636.71, 2125.51 + 0.0, 0.0, 0.7255, 14508.13, 5221.82, 2593.35 + 0.2, 0.0, 0.7368, 11986.3, 5504.79, 2614.1 + 0.35, 0.0, 0.7599, 11371.35, 6035.54, 2656.89 + 0.0, 0.0, 0.866, 20704.66, 7578.19, 2852.68 + 0.2, 0.0, 0.8784, 17494.34, 7922.15, 2875.51 + 0.35, 0.0, 0.9039, 16450.91, 8616.74, 2922.58 + 0.0, 5000.0, 0.1346, -283.8691, 483.933, 1502.52 + 0.2, 5000.0, 0.1411, -337.63, 486.006, 1514.54 + 0.35, 5000.0, 0.1545, -460.2864, 533.324, 1539.33 + 0.4, 5000.0, 0.1606, -633.109, 492.154, 1550.6 + 0.0, 5000.0, 0.4059, 4645.601, 1810.41, 2003.36 + 0.2, 5000.0, 0.4146, 3457.767, 1896.61, 2019.38 + 0.35, 5000.0, 0.4325, 3183.522, 2084.19, 2052.44 + 0.4, 5000.0, 0.4406, 3191.026, 2195.39, 2067.46 + 0.0, 5000.0, 0.6772, 11501.64, 4088.9, 2504.2 + 0.2, 5000.0, 0.6881, 9535.886, 4341.24, 2524.23 + 0.35, 5000.0, 0.7105, 9117.894, 4799.56, 2565.55 + 0.4, 5000.0, 0.7206, 9141.541, 5010.49, 2584.33 + 0.0, 5000.0, 0.8129, 16675.2, 6008.35, 2754.61 + 0.2, 5000.0, 0.8248, 14081.46, 6303.14, 2776.65 + 0.35, 5000.0, 0.8494, 13356.37, 6889.18, 2822.1 + 0.4, 5000.0, 0.8606, 13355.59, 7170.43, 2842.76 + 0.0, 5000.0, 0.9486, 22470.09, 8456.29, 3005.03 + 0.2, 5000.0, 0.9616, 19249.47, 8807.35, 3029.07 + 0.35, 5000.0, 0.9884, 18039.3, 9468.23, 3078.66 + 0.2, 10000.0, 0.1119, -822.5745, 215.055, 1460.62 + 0.35, 10000.0, 0.1248, -901.472, 242.334, 1484.53 + 0.4, 10000.0, 0.1307, -905.2738, 264.281, 1495.39 + 0.5, 10000.0, 0.1448, -999.016, 295.96, 1521.48 + 0.2, 10000.0, 0.3756, 2609.62, 1489.96, 1947.49 + 0.35, 10000.0, 0.3929, 2421.376, 1644.7, 1979.37 + 0.4, 10000.0, 0.4007, 2389.483, 1714.19, 1993.86 + 0.5, 10000.0, 0.4196, 2366.19, 1880.47, 2028.63 + 0.2, 10000.0, 0.6394, 7380.86, 3369.47, 2434.36 + 0.35, 10000.0, 0.661, 7050.941, 3714.57, 2474.21 + 0.4, 10000.0, 0.6708, 7070.985, 3873.8, 2492.32 + 0.5, 10000.0, 0.6943, 7255.23, 4292.97, 2535.79 + 0.2, 10000.0, 0.7713, 10938.29, 4854.72, 2677.8 + 0.35, 10000.0, 0.795, 10456.38, 5342.26, 2721.63 + 0.4, 10000.0, 0.8058, 10500.52, 5588.38, 2741.55 + 0.5, 10000.0, 0.8317, 10706.16, 6161.32, 2789.37 + 0.2, 10000.0, 0.9032, 15233.12, 6841.98, 2921.23 + 0.35, 10000.0, 0.9291, 14328.62, 7440.02, 2969.05 + 0.4, 10000.0, 0.9408, 14275.58, 7734.59, 2990.79 + 0.5, 10000.0, 0.9691, 14450.2, 8450.32, 3042.95 + 0.35, 15000.0, 0.09512, -1098.672, 78.2106, 1429.72 + 0.4, 15000.0, 0.1008, -1100.22, 89.7779, 1440.19 + 0.5, 15000.0, 0.1144, -1181.386, 101.745, 1465.31 + 0.6, 15000.0, 0.131, -1205.296, 142.077, 1496.01 + 0.7, 15000.0, 0.1507, -1225.874, 196.291, 1532.3 + 0.35, 15000.0, 0.3533, 1717.688, 1241.42, 1906.3 + 0.4, 15000.0, 0.3609, 1702.991, 1297.32, 1920.25 + 0.5, 15000.0, 0.379, 1693.102, 1430.43, 1953.75 + 0.6, 15000.0, 0.4012, 1755.838, 1608.94, 1994.68 + 0.7, 15000.0, 0.4274, 1869.824, 1831.44, 2043.06 + 0.35, 15000.0, 0.6115, 5423.801, 2846.33, 2382.87 + 0.4, 15000.0, 0.6209, 5452.809, 2978.82, 2400.32 + 0.5, 15000.0, 0.6436, 5590.974, 3300.17, 2442.18 + 0.6, 15000.0, 0.6713, 5780.798, 3683.47, 2493.35 + 0.7, 15000.0, 0.7041, 6126.108, 4189.83, 2553.83 + 0.35, 15000.0, 0.7406, 8155.56, 4126.18, 2621.16 + 0.4, 15000.0, 0.751, 8198.816, 4310.97, 2640.35 + 0.5, 15000.0, 0.7759, 8349.123, 4735.96, 2686.4 + 0.6, 15000.0, 0.8064, 8647.966, 5296.4, 2742.69 + 0.7, 15000.0, 0.8425, 9090.652, 5980.95, 2809.21 + 0.35, 15000.0, 0.8697, 11302.95, 5732.93, 2859.45 + 0.4, 15000.0, 0.881, 11277.78, 5955.89, 2880.38 + 0.5, 15000.0, 0.9082, 11415.64, 6538.39, 2930.62 + 0.6, 15000.0, 0.9415, 11752.59, 7287.6, 2992.02 + 0.7, 15000.0, 0.9808, 12278.04, 8162.44, 3064.59 + 0.35, 15000.0, 0.9988, 14194.8, 7561.24, 3097.74 + 0.4, 20000.0, 0.07088, -1282.788, -58.1917, 1384.99 + 0.5, 20000.0, 0.08397, -1291.402, -35.9897, 1409.14 + 0.6, 20000.0, 0.09997, -1314.794, -13.7096, 1438.67 + 0.7, 20000.0, 0.1189, -1317.359, 30.5004, 1473.56 + 0.75, 20000.0, 0.1294, -1303.031, 62.9165, 1493.02 + 0.8, 20000.0, 0.1407, -1300.5, 95.539, 1513.82 + 0.85, 20000.0, 0.1527, -1314.866, 130.448, 1535.97 + 0.4, 20000.0, 0.321, -1314.866, 130.448, 1846.65 + 0.5, 20000.0, 0.3384, 1127.843, 1057.41, 1878.86 + 0.6, 20000.0, 0.3598, 1177.52, 1194.44, 1918.22 + 0.7, 20000.0, 0.385, 1283.902, 1371.99, 1964.75 + 0.75, 20000.0, 0.399, 1351.935, 1479.62, 1990.69 + 0.8, 20000.0, 0.4141, 1422.987, 1597.03, 2018.43 + 0.85, 20000.0, 0.4301, 1497.18, 1726.39, 2047.95 + 0.4, 20000.0, 0.5711, 1497.18, 1726.39, 2308.31 + 0.5, 20000.0, 0.5929, 4188.075, 2486.64, 2348.57 + 0.6, 20000.0, 0.6196, 4391.124, 2806.66, 2397.78 + 0.7, 20000.0, 0.6511, 4681.468, 3193.51, 2455.94 + 0.75, 20000.0, 0.6686, 4836.753, 3409.62, 2488.37 + 0.8, 20000.0, 0.6874, 5033.242, 3666.79, 2523.04 + 0.85, 20000.0, 0.7074, 5249.044, 3954.81, 2559.94 + 0.4, 20000.0, 0.6962, 5249.044, 3954.81, 2539.14 + 0.5, 20000.0, 0.7201, 6433.359, 3625.65, 2583.43 + 0.6, 20000.0, 0.7495, 6678.287, 4049.0, 2637.56 + 0.7, 20000.0, 0.7841, 7040.174, 4558.11, 2701.53 + 0.75, 20000.0, 0.8035, 7289.055, 4889.89, 2737.2 + 0.8, 20000.0, 0.8241, 7562.413, 5254.91, 2775.34 + 0.85, 20000.0, 0.8461, 7834.74, 5635.73, 2815.94 + 0.4, 20000.0, 0.8212, 7834.74, 5635.73, 2769.97 + 0.5, 20000.0, 0.8474, 8923.83, 5014.87, 2818.29 + 0.6, 20000.0, 0.8794, 9235.125, 5567.93, 2877.34 + 0.7, 20000.0, 0.9172, 9644.44, 6284.76, 2947.12 + 0.75, 20000.0, 0.9383, 9927.171, 6715.83, 2986.04 + 0.8, 20000.0, 0.9608, 10270.23, 7187.08, 3027.64 + 0.85, 20000.0, 0.9848, 10602.98, 7673.83, 3071.93 + 0.4, 20000.0, 0.9463, 10602.98, 7673.83, 3000.8 + 0.5, 20000.0, 0.9746, 11176.31, 6563.2, 3053.14 + 0.5, 25000.0, 0.05354, -1465.406, -188.139, 1352.98 + 0.6, 25000.0, 0.0689, -1426.801, -149.687, 1381.32 + 0.7, 25000.0, 0.08705, -1363.875, -100.697, 1414.83 + 0.75, 25000.0, 0.09717, -1356.431, -78.4116, 1433.51 + 0.8, 25000.0, 0.108, -1372.119, -60.3519, 1453.48 + 0.85, 25000.0, 0.1195, -1366.258, -27.7235, 1474.74 + 0.5, 25000.0, 0.2979, 623.2464, 740.755, 1803.97 + 0.6, 25000.0, 0.3183, 694.4828, 854.783, 1841.76 + 0.7, 25000.0, 0.3425, 796.8191, 995.955, 1886.43 + 0.75, 25000.0, 0.356, 854.2121, 1078.93, 1911.35 + 0.8, 25000.0, 0.3705, 912.9566, 1170.19, 1937.98 + 0.85, 25000.0, 0.3858, 987.3726, 1275.2, 1966.32 + 0.5, 25000.0, 0.5422, 3099.161, 1863.29, 2254.96 + 0.6, 25000.0, 0.5678, 3197.128, 2070.85, 2302.21 + 0.7, 25000.0, 0.598, 3467.033, 2388.35, 2358.04 + 0.75, 25000.0, 0.6149, 3629.552, 2572.88, 2389.18 + 0.8, 25000.0, 0.6329, 3795.544, 2768.61, 2422.47 + 0.85, 25000.0, 0.6521, 3972.008, 2983.75, 2457.91 + 0.5, 25000.0, 0.6644, 4847.604, 2713.73, 2480.45 + 0.6, 25000.0, 0.6925, 5057.584, 3047.0, 2532.43 + 0.7, 25000.0, 0.7258, 5390.559, 3467.18, 2593.85 + 0.75, 25000.0, 0.7443, 5582.87, 3706.47, 2628.1 + 0.8, 25000.0, 0.7642, 5794.822, 3969.08, 2664.72 + 0.85, 25000.0, 0.7853, 6021.867, 4255.47, 2703.7 + 0.5, 25000.0, 0.7865, 6847.717, 3776.69, 2705.95 + 0.6, 25000.0, 0.8172, 7105.216, 4227.37, 2762.65 + 0.7, 25000.0, 0.8535, 7488.496, 4771.25, 2829.65 + 0.75, 25000.0, 0.8738, 7730.909, 5085.5, 2867.02 + 0.8, 25000.0, 0.8954, 7994.97, 5443.12, 2906.96 + 0.85, 25000.0, 0.9185, 8268.126, 5859.89, 2949.49 + 0.5, 25000.0, 0.9087, 8774.722, 5016.14, 2931.45 + 0.6, 25000.0, 0.942, 8996.73, 5546.04, 2992.87 + 0.7, 25000.0, 0.9813, 9364.914, 6212.13, 3065.46 + 0.6, 30000.0, 0.03783, -1641.908, -317.498, 1323.98 + 0.7, 30000.0, 0.05523, -1494.146, -242.854, 1356.09 + 0.75, 30000.0, 0.06493, -1459.656, -214.792, 1374.0 + 0.8, 30000.0, 0.0753, -1417.609, -182.93, 1393.14 + 0.85, 30000.0, 0.08634, -1385.292, -151.67, 1413.52 + 0.6, 30000.0, 0.2769, 227.7136, 551.0, 1765.31 + 0.7, 30000.0, 0.3001, 366.4952, 678.618, 1808.12 + 0.75, 30000.0, 0.3131, 426.1066, 746.987, 1832.0 + 0.8, 30000.0, 0.3269, 492.9079, 822.784, 1857.52 + 0.85, 30000.0, 0.3416, 558.5389, 904.978, 1884.69 + 0.6, 30000.0, 0.516, 2331.627, 1545.65, 2206.63 + 0.7, 30000.0, 0.545, 2501.732, 1756.81, 2260.15 + 0.75, 30000.0, 0.5612, 2588.335, 1872.98, 2290.0 + 0.8, 30000.0, 0.5785, 2727.027, 2023.14, 2321.9 + 0.85, 30000.0, 0.5969, 2904.058, 2206.67, 2355.87 + 0.6, 30000.0, 0.6356, 3759.659, 2264.38, 2427.29 + 0.7, 30000.0, 0.6675, 4001.111, 2563.06, 2486.17 + 0.75, 30000.0, 0.6852, 4169.214, 2752.16, 2519.0 + 0.8, 30000.0, 0.7043, 4352.509, 2964.09, 2554.09 + 0.85, 30000.0, 0.7245, 4551.049, 3195.96, 2591.45 + 0.6, 30000.0, 0.7551, 5374.098, 3151.97, 2647.96 + 0.7, 30000.0, 0.7899, 5683.326, 3554.63, 2712.18 + 0.75, 30000.0, 0.8093, 5885.228, 3809.9, 2748.0 + 0.8, 30000.0, 0.83, 6105.729, 4092.36, 2786.28 + 0.85, 30000.0, 0.8521, 6346.24, 4394.33, 2827.04 + 0.6, 30000.0, 0.8746, 6929.994, 4177.77, 2868.62 + 0.7, 30000.0, 0.9123, 7279.868, 4698.11, 2938.2 + 0.75, 30000.0, 0.9334, 7486.411, 5003.85, 2977.0 + 0.8, 30000.0, 0.9558, 7707.456, 5339.51, 3018.47 + 0.85, 30000.0, 0.9798, 7972.898, 5724.67, 3062.63 + 0.6, 30000.0, 0.9942, 8212.215, 5181.89, 3089.28 + 0.6, 35000.0, 0.006767, -2123.249, -584.908, 1266.63 + 0.7, 35000.0, 0.02341, -1820.109, -457.538, 1297.36 + 0.75, 35000.0, 0.03269, -1716.425, -406.073, 1314.49 + 0.8, 35000.0, 0.04261, -1619.994, -355.844, 1332.8 + 0.85, 35000.0, 0.05318, -1548.727, -319.7, 1352.3 + 0.6, 35000.0, 0.2355, -356.928, 224.827, 1688.85 + 0.7, 35000.0, 0.2577, -140.5189, 361.974, 1729.81 + 0.75, 35000.0, 0.2701, -51.8074, 430.49, 1752.65 + 0.8, 35000.0, 0.2833, 37.8187, 502.893, 1777.07 + 0.85, 35000.0, 0.2974, 113.3275, 573.957, 1803.06 + 0.6, 35000.0, 0.4642, 1454.712, 1061.75, 2111.06 + 0.7, 35000.0, 0.492, 1646.254, 1245.0, 2162.26 + 0.75, 35000.0, 0.5074, 1745.044, 1347.31, 2190.81 + 0.8, 35000.0, 0.524, 1852.81, 1456.89, 2221.34 + 0.85, 35000.0, 0.5416, 1957.771, 1573.32, 2253.83 + 0.6, 35000.0, 0.5786, 2586.562, 1613.24, 2322.16 + 0.7, 35000.0, 0.6091, 2820.207, 1856.68, 2378.48 + 0.75, 35000.0, 0.6261, 2947.749, 1991.99, 2409.89 + 0.8, 35000.0, 0.6443, 3081.256, 2140.07, 2443.47 + 0.85, 35000.0, 0.6637, 3229.069, 2303.38, 2479.21 + 0.6, 35000.0, 0.693, 3896.791, 2298.65, 2533.27 + 0.7, 35000.0, 0.7263, 4133.758, 2599.0, 2594.71 + 0.75, 35000.0, 0.7448, 4280.896, 2775.23, 2628.98 + 0.8, 35000.0, 0.7647, 4453.606, 2973.55, 2665.6 + 0.85, 35000.0, 0.7858, 4645.331, 3191.27, 2704.6 + 0.6, 35000.0, 0.8073, 5179.454, 3073.77, 2744.37 + 0.7, 35000.0, 0.8434, 5378.286, 3439.03, 2810.94 + 0.75, 35000.0, 0.8635, 5558.421, 3673.33, 2848.06 + 0.8, 35000.0, 0.885, 5782.972, 3937.84, 2887.74 + 0.85, 35000.0, 0.9079, 6003.707, 4228.51, 2929.98 + 0.6, 35000.0, 0.9217, 6185.666, 3843.91, 2955.48 + 0.7, 35000.0, 0.9605, 6448.75, 4289.66, 3027.16 + 0.75, 35000.0, 0.9822, 6643.832, 4566.88, 3067.14 + 0.6, 39000.0, 0.0, -2891.208, -973.342, 1254.14 + 0.7, 39000.0, 0.01648, -2274.489, -723.646, 1284.56 + 0.75, 39000.0, 0.02567, -2074.369, -635.461, 1301.52 + 0.8, 39000.0, 0.03549, -1901.474, -554.759, 1319.66 + 0.85, 39000.0, 0.04595, -1727.47, -492.054, 1338.96 + 0.6, 39000.0, 0.2265, -1016.096, -113.678, 1672.19 + 0.7, 39000.0, 0.2485, -619.0324, 85.2694, 1712.75 + 0.75, 39000.0, 0.2607, -475.6894, 169.386, 1735.37 + 0.8, 39000.0, 0.2738, -345.4908, 251.975, 1759.54 + 0.85, 39000.0, 0.2877, -224.3491, 330.348, 1785.28 + 0.6, 39000.0, 0.453, 858.6461, 745.928, 2090.24 + 0.7, 39000.0, 0.4804, 1057.115, 908.061, 2140.94 + 0.75, 39000.0, 0.4957, 1160.698, 999.603, 2169.21 + 0.8, 39000.0, 0.5121, 1260.005, 1095.5, 2199.43 + 0.85, 39000.0, 0.5295, 1360.948, 1198.18, 2231.6 + 0.6, 39000.0, 0.5662, 1822.37, 1207.35, 2299.26 + 0.7, 39000.0, 0.5964, 2034.892, 1413.62, 2355.03 + 0.75, 39000.0, 0.6133, 2152.665, 1530.2, 2386.13 + 0.8, 39000.0, 0.6313, 2276.074, 1655.85, 2419.37 + 0.85, 39000.0, 0.6504, 2411.04, 1792.45, 2454.76 + 0.6, 39000.0, 0.6794, 2928.707, 1774.62, 2508.29 + 0.7, 39000.0, 0.7124, 3140.615, 2027.7, 2569.12 + 0.75, 39000.0, 0.7308, 3269.289, 2173.53, 2603.05 + 0.8, 39000.0, 0.7504, 3409.46, 2331.61, 2639.32 + 0.85, 39000.0, 0.7713, 3569.955, 2506.55, 2677.92 + 0.6, 39000.0, 0.7927, 4031.943, 2418.16, 2717.31 + 0.7, 39000.0, 0.8284, 4201.459, 2716.34, 2783.22 + 0.75, 39000.0, 0.8483, 4342.344, 2902.64, 2819.97 + 0.8, 39000.0, 0.8696, 4520.568, 3115.11, 2859.26 + 0.85, 39000.0, 0.8922, 4733.972, 3355.81, 2901.08 + 0.6, 39000.0, 0.9059, 4911.553, 3072.96, 2926.33 + 0.7, 39000.0, 0.9444, 5093.338, 3415.35, 2997.31 + 0.75, 39000.0, 0.9658, 5267.201, 3645.85, 3036.89 + 0.8, 39000.0, 0.9887, 5457.755, 3898.71, 3079.2 + 0.7, 43000.0, 0.01648, -3281.681, -1263.14, 1284.56 + 0.75, 43000.0, 0.02567, -2792.323, -1044.27, 1301.52 + 0.8, 43000.0, 0.03549, -2422.325, -874.493, 1319.66 + 0.85, 43000.0, 0.04595, -2115.358, -755.321, 1338.96 + 0.7, 43000.0, 0.2485, -1400.321, -335.28, 1712.75 + 0.75, 43000.0, 0.2607, -1085.215, -177.679, 1735.37 + 0.8, 43000.0, 0.2738, -839.2385, -47.0228, 1759.54 + 0.85, 43000.0, 0.2877, -638.0304, 58.5412, 1785.28 + 0.7, 43000.0, 0.4804, 473.8456, 589.921, 2140.94 + 0.75, 43000.0, 0.4957, 620.6105, 690.346, 2169.21 + 0.8, 43000.0, 0.5121, 749.7365, 788.146, 2199.43 + 0.85, 43000.0, 0.5295, 863.3511, 885.173, 2231.6 + 0.7, 43000.0, 0.5964, 1387.936, 1053.56, 2355.03 + 0.75, 43000.0, 0.6133, 1505.226, 1156.55, 2386.13 + 0.8, 43000.0, 0.6313, 1626.737, 1265.72, 2419.37 + 0.85, 43000.0, 0.6504, 1753.599, 1381.55, 2454.76 + 0.7, 43000.0, 0.7124, 2339.499, 1573.7, 2569.12 + 0.75, 43000.0, 0.7308, 2457.54, 1694.2, 2603.05 + 0.8, 43000.0, 0.7504, 2579.125, 1823.57, 2639.32 + 0.85, 43000.0, 0.7713, 2720.036, 1971.68, 2677.92 + 0.7, 43000.0, 0.8284, 3260.128, 2150.56, 2783.22 + 0.75, 43000.0, 0.8483, 3384.106, 2302.19, 2819.97 + 0.8, 43000.0, 0.8696, 3539.302, 2476.94, 2859.26 + 0.85, 43000.0, 0.8922, 3710.6, 2667.44, 2901.08 + 0.7, 43000.0, 0.9444, 4031.806, 2740.03, 2997.31 + 0.75, 43000.0, 0.9658, 4170.438, 2924.73, 3036.89 + 0.8, 43000.0, 0.9887, 4324.192, 3131.44, 3079.2 diff --git a/aviary/models/engines/turbofan_24k_1.deck b/aviary/models/engines/turbofan_24k_1.deck deleted file mode 100644 index 1ff909dfb2..0000000000 --- a/aviary/models/engines/turbofan_24k_1.deck +++ /dev/null @@ -1,280 +0,0 @@ -# GASP-derived engine deck converted from GASP_turbofan_24k_1.eng -# t4max: 3100.0 -# t4cruise: 2770.0 -# t4climb: 3030.0 -# sls_airflow: 794.67 -# sfn_idle: -10.0 - -Mach_Number (unitless),Altitude (ft),Throttle (unitless),Thrust (lbf),Fuel_Flow (lb/h),T4 (degR) -0.0,0.0,0.16353735150633147,119.332,721.4768,1556.0099999999998 -0.2,0.0,0.17028114775207215,14.3682,743.0868,1568.4580799999999 -0.35,0.0,0.18419022750891215,-95.7382,813.6561,1594.1322449999998 -0.0,0.0,0.4445288617455241,5986.5659,2297.7,2074.68 -0.2,0.0,0.4535205900731783,4426.9868,2382.6592,2091.27744 -0.35,0.0,0.47206602974896494,4101.6514,2636.7056,2125.5096599999997 -0.0,0.0,0.7255203719847167,14508.1279,5221.8164,2593.35 -0.2,0.0,0.7367600323942844,11986.2969,5504.7871,2614.0968 -0.35,0.0,0.7599418319890177,11371.3486,6035.5361,2656.8870749999996 -0.0,0.0,0.8660161271043131,20704.6621,7578.1924,2852.685 -0.2,0.0,0.8783797535548376,17494.3438,7922.1538,2875.50648 -0.35,0.0,0.9038797331090441,16450.9082,8616.7412,2922.5757824999996 -0.0,5000.0,0.13455730859421963,-283.8691,483.9326,1502.517 -0.2,5000.0,0.14106926449666327,-337.63,486.0058,1514.537136 -0.35,5000.0,0.15450017354545342,-460.2864,533.3245,1539.3286664999998 -0.4,5000.0,0.1606051322039946,-633.109,492.154,1550.5975440000002 -0.0,5000.0,0.40588880452937487,4645.6011,1810.4146,2003.356 -0.2,5000.0,0.41457141239929984,3457.7671,1896.6125,2019.382848 -0.35,5000.0,0.43247929113101996,3183.5225,2084.186,2052.4382219999998 -0.4,5000.0,0.4406192360090748,3191.0259,2195.3877,2067.463392 -0.0,5000.0,0.6772203004645302,11501.6416,4088.8958,2504.195 -0.2,5000.0,0.6880735603019363,9535.8857,4341.2363,2524.22856 -0.35,5000.0,0.7104584087165866,9117.8936,4799.5552,2565.5477775 -0.4,5000.0,0.720633339814155,9141.541,5010.4902,2584.32924 -0.0,5000.0,0.8128860484321079,16675.2012,6008.3486,2754.6145 -0.2,5000.0,0.8248246342532547,14081.458,6303.144,2776.651416 -0.35,5000.0,0.8494479675093697,13356.3652,6889.1826,2822.1025552499996 -0.4,5000.0,0.8606403917166953,13355.5928,7170.4268,2842.762164 -0.0,5000.0,0.9485517963996855,22470.0859,8456.2871,3005.034 -0.2,5000.0,0.9615757082045728,19249.4688,8807.3457,3029.074272 -0.35,5000.0,0.9884375263021531,18039.3008,9468.2324,3078.6573329999997 -0.2,10000.0,0.1118573812412544,-822.5745,215.0546,1460.616192 -0.35,10000.0,0.1248101195819947,-901.472,242.3344,1484.5250879999999 -0.4,10000.0,0.13069772791869488,-905.2738,264.2812,1495.392768 -0.5,10000.0,0.14482798792677534,-999.016,295.9601,1521.4752 -0.2,10000.0,0.3756222347254212,2609.6204,1489.958,1947.4882559999999 -0.35,10000.0,0.392892552513075,2421.3765,1644.6975,1979.3667839999998 -0.4,10000.0,0.4007426969620086,2389.4829,1714.1914,1993.857024 -0.5,10000.0,0.4195830436394492,2366.1904,1880.4651,2028.6336000000001 -0.2,10000.0,0.6393870882095881,7380.8604,3369.4685,2434.36032 -0.35,10000.0,0.6609749854441553,7050.9414,3714.5696,2474.20848 -0.4,10000.0,0.6707876660053224,7070.9849,3873.8013,2492.32128 -0.5,10000.0,0.6943380993521232,7255.2305,4292.9683,2535.7920000000004 -0.2,10000.0,0.7712695149516715,10938.293,4854.7241,2677.796352 -0.35,10000.0,0.7950162019096956,10456.3809,5342.2646,2721.629328 -0.4,10000.0,0.8058101505269791,10500.5176,5588.375,2741.5534079999998 -0.5,10000.0,0.8317156272084599,10706.1602,6161.3193,2789.3712 -0.2,10000.0,0.903151941693755,15233.1191,6841.9819,2921.232384 -0.35,10000.0,0.9290574183752356,14328.6211,7440.0151,2969.0501759999997 -0.4,10000.0,0.940832635048636,14275.5801,7734.5859,2990.785536 -0.5,10000.0,0.9690931550647969,14450.1992,8450.3193,3042.9504 -0.35,15000.0,0.09512173069923609,-1098.6724,78.2106,1429.724583 -0.4,15000.0,0.10079200090355886,-1100.22,89.7779,1440.191088 -0.5,15000.0,0.11440064939393334,-1181.3855,101.7453,1465.3107 -0.6,15000.0,0.13103344199327993,-1205.2955,142.0774,1496.012448 -0.7,15000.0,0.15069037870159863,-1225.8739,196.2914,1532.296332 -0.35,15000.0,0.35330803400273025,1717.6884,1241.4174,1906.299444 -0.4,15000.0,0.3608683942751605,1702.991,1297.3217,1920.254784 -0.5,15000.0,0.3790132589289933,1693.1018,1430.4333,1953.7476000000001 -0.6,15000.0,0.401190315728122,1755.8381,1608.9412,1994.683264 -0.7,15000.0,0.42739956467254686,1869.8241,1831.4385,2043.0617759999998 -0.35,15000.0,0.6114943373062243,5423.8013,2846.3318,2382.874305 -0.4,15000.0,0.6209447876467622,5452.8086,2978.8232,2400.31848 -0.5,15000.0,0.6436258684640532,5590.9741,3300.1682,2442.1845000000003 -0.6,15000.0,0.6713471894629641,5780.7983,3683.4683,2493.35408 -0.7,15000.0,0.7041087506434951,6126.1079,4189.8335,2553.8272199999997 -0.35,15000.0,0.7405874889579713,8155.5605,4126.1772,2621.1617355 -0.4,15000.0,0.750982984332563,8198.8164,4310.9678,2640.350328 -0.5,15000.0,0.775932173231583,8349.123,4735.9551,2686.40295 -0.6,15000.0,0.8064256263303851,8647.9658,5296.4033,2742.689488 -0.7,15000.0,0.8424633436289692,9090.6523,5980.9526,2809.2099419999995 -0.35,15000.0,0.8696806406097184,11302.9482,5732.9326,2859.449166 -0.4,15000.0,0.8810211810183639,11277.7783,5955.8916,2880.382176 -0.5,15000.0,0.908238477999113,11415.6416,6538.3872,2930.6214 -0.6,15000.0,0.9415040631978061,11752.5889,7287.6011,2992.024896 -0.7,15000.0,0.9808179366144435,12278.0391,8162.4443,3064.592664 -0.35,15000.0,0.9987737922614655,14194.7988,7561.2437,3097.7365965 -0.4,20000.0,0.07088459661825924,-1282.7881,-58.1917,1384.986312 -0.5,20000.0,0.08397160433621581,-1291.4023,-35.9897,1409.1430500000001 -0.6,20000.0,0.0999668359914959,-1314.7943,-13.7096,1438.667952 -0.7,20000.0,0.11887029158409965,-1317.3593,30.5004,1473.5610179999999 -0.75,20000.0,0.129412603356898,-1303.0309,62.9165,1493.0206125 -0.8,20000.0,0.14068197111402717,-1300.4995,95.539,1513.822248 -0.85,20000.0,0.1526783948554872,-1314.8655,130.4481,1535.9659244999998 -0.4,20000.0,0.3209918552280944,-1314.8655,130.4481,1846.648416 -0.5,20000.0,0.33844119885203644,1127.8431,1057.4075,1878.8574 -0.6,20000.0,0.35976817439241,1177.5199,1194.4406,1918.223936 -0.7,20000.0,0.3849727818492149,1283.9022,1371.9934,1964.7480239999998 -0.75,20000.0,0.3990291975462794,1351.9348,1479.6199,1990.69415 -0.8,20000.0,0.4140550212224517,1422.9874,1597.0325,2018.429664 -0.85,20000.0,0.43005025287773163,1497.1804,1726.3944,2047.9545659999997 -0.4,20000.0,0.5710991138379296,1497.1804,1726.3944,2308.31052 -0.5,20000.0,0.5929107933678571,4188.0752,2486.6428,2348.57175 -0.6,20000.0,0.619569512793324,4391.1245,2806.6602,2397.77992 -0.7,20000.0,0.6510752721143301,4681.4683,3193.5149,2455.9350299999996 -0.75,20000.0,0.6686457917356609,4836.7534,3409.625,2488.3676875 -0.8,20000.0,0.6874280713308761,5033.2417,3666.7864,2523.03708 -0.85,20000.0,0.7074221108999761,5249.0439,3954.8074,2559.9432074999995 -0.4,20000.0,0.6961527431428471,5249.0439,3954.8074,2539.141572 -0.5,20000.0,0.7201455906257674,6433.3589,3625.6497,2583.428925 -0.6,20000.0,0.7494701819937811,6678.2866,4049.002,2637.557912 -0.7,20000.0,0.7841265172468879,7040.1738,4558.1138,2701.5285329999997 -0.75,20000.0,0.8034540888303515,7289.0552,4889.8906,2737.20445625 -0.8,20000.0,0.8241145963850883,7562.4126,5254.9111,2775.340788 -0.85,20000.0,0.8461080399110984,7834.7402,5635.7271,2815.9375282499996 -0.4,20000.0,0.8212063724477647,7834.7402,5635.7271,2769.972624 -0.5,20000.0,0.8473803878836779,8923.8301,5014.8716,2818.2861000000003 -0.6,20000.0,0.8793708511942381,9235.125,5567.9268,2877.335904 -0.7,20000.0,0.9171777623794455,9644.4395,6284.7583,2947.1220359999998 -0.75,20000.0,0.9382623859250422,9927.1709,6715.8271,2986.041225 -0.8,20000.0,0.9608011214393005,10270.2266,7187.0791,3027.644496 -0.85,20000.0,0.9847939689222206,10602.9805,7673.8276,3071.9318489999996 -0.4,20000.0,0.9462600017526823,10602.9805,7673.8276,3000.803676 -0.5,20000.0,0.9746151851415882,11176.3115,6563.2012,3053.1432750000004 -0.5,25000.0,0.053542559278498165,-1465.4062,-188.1391,1352.9754 -0.6,25000.0,0.06890022998971188,-1426.801,-149.6866,1381.323456 -0.7,25000.0,0.08705020446660067,-1363.875,-100.6971,1414.8257039999999 -0.75,25000.0,0.09717230561717351,-1356.431,-78.4116,1433.5096500000002 -0.8,25000.0,0.10799248270916502,-1372.119,-60.3519,1453.4821440000003 -0.85,25000.0,0.11951073574257509,-1366.2582,-27.7235,1474.743186 -0.5,25000.0,0.29786913877507964,623.2464,740.7552,1803.9672 -0.6,25000.0,0.31834603305669795,694.4828,854.7831,1841.7646080000002 -0.7,25000.0,0.34254599902588306,796.8191,995.9554,1886.434272 -0.75,25000.0,0.3560421338933134,854.2121,1078.9293,1911.3462000000002 -0.8,25000.0,0.3704690366826354,912.9566,1170.1919,1937.9761920000003 -0.85,25000.0,0.3858267073938489,987.3726,1275.196,1966.324248 -0.5,25000.0,0.542195718271661,3099.1606,1863.2922,2254.959 -0.6,25000.0,0.567791836123684,3197.1284,2070.8472,2302.2057600000003 -0.7,25000.0,0.5980417935851654,3467.0327,2388.3503,2358.04284 -0.75,25000.0,0.6149119621694533,3629.5518,2572.8838,2389.1827500000004 -0.8,25000.0,0.6329455906561059,3795.5439,2768.6123,2422.4702400000006 -0.85,25000.0,0.6521426790451228,3972.0083,2983.749,2457.90531 -0.5,25000.0,0.6643590080199518,4847.6045,2713.7314,2480.4549 -0.6,25000.0,0.6925147376571771,5057.584,3047.0024,2532.4263360000004 -0.7,25000.0,0.7257896908648065,5390.5591,3467.1848,2593.847124 -0.75,25000.0,0.7443468763075233,5582.8701,3706.4697,2628.1010250000004 -0.8,25000.0,0.764183867642841,5794.8218,3969.082,2664.7172640000003 -0.85,25000.0,0.7853006648707594,6021.8667,4255.4692,2703.6958409999997 -0.5,25000.0,0.7865222977682426,6847.7173,3776.6926,2705.9508 -0.6,25000.0,0.8172376391906699,7105.2158,4227.3726,2762.646912 -0.7,25000.0,0.8535375881444476,7488.4961,4771.2456,2829.6514079999997 -0.75,25000.0,0.8737817904455932,7730.9092,5085.4976,2867.0193000000004 -0.8,25000.0,0.8954221446295763,7994.9702,5443.1182,2906.9642880000006 -0.85,25000.0,0.9184586506963964,8268.126,5859.8896,2949.486372 -0.5,25000.0,0.9086855875165333,8774.7217,5016.1353,2931.4467 -0.6,25000.0,0.9419605407241631,8996.7305,5546.0391,2992.8674880000003 -0.7,25000.0,0.9812854854240889,9364.9141,6212.1289,3065.455692 -0.6,30000.0,0.03783362398792773,-1641.9077,-317.4978,1323.97896 -0.7,30000.0,0.05523011734910169,-1494.1465,-242.8544,1356.0903899999998 -0.75,30000.0,0.06493200787744878,-1459.6558,-214.7922,1373.9986875 -0.8,30000.0,0.07530299430430264,-1417.6088,-182.9302,1393.1420400000002 -0.85,30000.0,0.08634307662966285,-1385.2917,-151.6695,1413.5204474999998 -0.6,30000.0,0.2769238917209858,227.7136,550.9996,1765.30528 -0.7,30000.0,0.30011921620255094,366.4952,678.6176,1808.1205199999997 -0.75,30000.0,0.3130550702403472,426.1066,746.9874,1831.99825 -0.8,30000.0,0.3268830521428189,492.9079,822.7838,1857.5227200000002 -0.85,30000.0,0.34160316190996587,558.5389,904.9783,1884.6939299999997 -0.6,30000.0,0.5160141594540438,2331.6267,1545.6548,2206.6316 -0.7,30000.0,0.5450083150560002,2501.7324,1756.8065,2260.1506499999996 -0.75,30000.0,0.5611781326032457,2588.3354,1872.9819,2289.9978125000002 -0.8,30000.0,0.5784631099813351,2727.0273,2023.1437,2321.9034 -0.85,30000.0,0.596863247190269,2904.0581,2206.6726,2355.8674125 -0.6,30000.0,0.6355592933205729,3759.6587,2264.3767,2427.29476 -0.7,30000.0,0.6674528644827249,4001.1108,2563.0559,2486.1657149999996 -0.75,30000.0,0.6852396637846948,4169.2144,2752.1565,2518.9975937500003 -0.8,30000.0,0.7042531389005933,4352.5088,2964.0923,2554.0937400000003 -0.85,30000.0,0.7244932898304203,4551.0488,3195.9551,2591.4541537499995 -0.6,30000.0,0.7551044271871017,5374.0977,3151.9736,2647.95792 -0.7,30000.0,0.7898974139094496,5683.3257,3554.6294,2712.1807799999997 -0.75,30000.0,0.8093011949661438,5885.228,3809.8965,2747.997375 -0.8,30000.0,0.8300431678198514,6105.729,4092.3638,2786.2840800000004 -0.85,30000.0,0.8521233324705719,6346.2397,4394.3291,2827.0408949999996 -0.6,30000.0,0.8746495610536307,6929.9941,4177.7715,2868.62108 -0.7,30000.0,0.9123419633361742,7279.8677,4698.106,2938.1958449999997 -0.75,30000.0,0.933362726147593,7486.4111,5003.8521,2976.99715625 -0.8,30000.0,0.9558331967391097,7707.4565,5339.5127,3018.4744200000005 -0.85,30000.0,0.9797533751107234,7972.8979,5724.6699,3062.6276362499993 -0.6,30000.0,0.9941946949201598,8212.2148,5181.8916,3089.28424 -0.6,35000.0,0.006767017986143824,-2123.249,-584.9083,1266.6344640000002 -0.7,35000.0,0.0234100302316027,-1820.1091,-457.5376,1297.3550759999998 -0.75,35000.0,0.032691710137724185,-1716.4246,-406.0729,1314.487725 -0.8,35000.0,0.04261350589944024,-1619.9938,-355.8443,1332.801936 -0.85,35000.0,0.05317541751675062,-1548.7271,-319.6995,1352.2977089999997 -0.6,35000.0,0.23550175038527377,-356.928,224.8273,1688.8459520000001 -0.7,35000.0,0.257692433379219,-140.5189,361.974,1729.8067679999997 -0.75,35000.0,0.270068006587381,-51.8074,430.4904,1752.6503 -0.8,35000.0,0.28329706760300233,37.8187,502.8929,1777.069248 -0.85,35000.0,0.29737961642608296,113.3275,573.9567,1803.0636119999997 -0.6,35000.0,0.4642364827844037,1454.7124,1061.7505,2111.05744 -0.7,35000.0,0.4919748365268352,1646.2544,1245.0011,2162.2584599999996 -0.75,35000.0,0.5074443030370379,1745.0444,1347.3065,2190.812875 -0.8,35000.0,0.5239806293065646,1852.8096,1456.8871,2221.33656 -0.85,35000.0,0.5415838153354151,1957.7714,1573.3245,2253.8295149999994 -0.6,35000.0,0.5786038489839687,2586.5618,1613.2426,2322.163184 -0.7,35000.0,0.6091160381006433,2820.207,1856.6794,2378.4843059999994 -0.75,35000.0,0.6261324512618663,2947.7493,1991.9904,2409.8941625 -0.8,35000.0,0.6443224101583457,3081.2561,2140.0664,2443.470216 -0.85,35000.0,0.6636859147900814,3229.0686,2303.3765,2479.2124664999997 -0.6,35000.0,0.6929712151835339,3896.791,2298.6492,2533.2689280000004 -0.7,35000.0,0.7262572396744517,4133.7578,2598.9985,2594.7101519999997 -0.75,35000.0,0.7448205994866945,4280.896,2775.2344,2628.97545 -0.8,35000.0,0.7646641910101267,4453.6055,2973.5544,2665.603872 -0.85,35000.0,0.7857880142447474,4645.3311,3191.2744,2704.5954179999994 -0.6,35000.0,0.8073385813830989,5179.4541,3073.7734,2744.3746720000004 -0.7,35000.0,0.8433984412482597,5378.2861,3439.0317,2810.9359979999995 -0.75,35000.0,0.8635087477115231,5558.4214,3673.3267,2848.0567375 -0.8,35000.0,0.8850059718619078,5782.9717,3937.8389,2887.737528 -0.85,35000.0,0.9078901136994137,6003.707,4228.5078,2929.9783694999996 -0.6,35000.0,0.9217059475826638,6185.6665,3843.9114,2955.4804160000003 -0.7,35000.0,0.9605396428220678,6448.7495,4289.6572,3027.1618439999993 -0.75,35000.0,0.9821968959363515,6643.8325,4566.875,3067.138025 -0.6,39000.0,0.0,-2891.208,-973.3418,1254.14352 -0.7,39000.0,0.0164788868092279,-2274.4888,-723.6464,1284.56118 -0.75,39000.0,0.025669035222066663,-2074.3691,-635.4612,1301.524875 -0.8,39000.0,0.03549298697372193,-1901.4742,-554.7587,1319.6584800000003 -0.85,39000.0,0.04595074206419332,-1727.4702,-492.0538,1338.961995 -0.6,39000.0,0.22647905973708216,-1016.0961,-113.6783,1672.1913600000003 -0.7,39000.0,0.2484509088160526,-619.0324,85.2694,1712.74824 -0.75,39000.0,0.26070444003317095,-475.6894,169.3863,1735.3665 -0.8,39000.0,0.2738030423687113,-345.4908,251.9748,1759.5446400000003 -0.85,39000.0,0.28774671582267314,-224.3491,330.3477,1785.2826599999999 -0.6,39000.0,0.4529581194741643,858.6461,745.9283,2090.2392000000004 -0.7,39000.0,0.48042293082287746,1057.115,908.0612,2140.9353 -0.75,39000.0,0.49573984484427525,1160.6975,999.6034,2169.208125 -0.8,39000.0,0.5121130977637007,1260.0049,1095.5002,2199.4308000000005 -0.85,39000.0,0.5295426895811531,1360.948,1198.1838,2231.603325 -0.6,39000.0,0.5661976493427054,1822.3699,1207.3475,2299.2631200000005 -0.7,39000.0,0.5964089418262896,2034.8923,1413.623,2355.0288299999997 -0.75,39000.0,0.6132575472498274,2152.665,1530.2035,2386.1289375 -0.8,39000.0,0.6312681254611954,2276.0742,1655.8514,2419.3738800000006 -0.85,39000.0,0.6504406764603928,2411.04,1792.4537,2454.7636574999997 -0.6,39000.0,0.6794371792112462,2928.707,1774.6229,2508.28704 -0.7,39000.0,0.712394952829702,3140.615,2027.7026,2569.12236 -0.75,39000.0,0.7307752496553795,3269.2891,2173.5259,2603.04975 -0.8,39000.0,0.7504231531586901,3409.4595,2331.6143,2639.3169600000006 -0.85,39000.0,0.7713386633396329,3569.9548,2506.552,2677.92399 -0.6,39000.0,0.7926767090797873,4031.9429,2418.1599,2717.3109600000003 -0.7,39000.0,0.8283809638331144,4201.459,2716.3413,2783.21589 -0.75,39000.0,0.8482929520609317,4342.3438,2902.6355,2819.9705625 -0.8,39000.0,0.8695781808561848,4520.5684,3115.1143,2859.2600400000006 -0.85,39000.0,0.8922366502188729,4733.9717,3355.8064,2901.0843225 -0.6,39000.0,0.9059162389483284,4911.5527,3072.9634,2926.3348800000003 -0.7,39000.0,0.9443669748365267,5093.3384,3415.3503,2997.3094199999996 -0.75,39000.0,0.9658106544664838,5267.2007,3645.8479,3036.891375 -0.8,39000.0,0.9887332085536794,5457.7554,3898.7056,3079.2031200000006 -0.7,43000.0,0.0164788868092279,-3281.6809,-1263.1353,1284.56118 -0.75,43000.0,0.025669035222066663,-2792.3232,-1044.274,1301.524875 -0.8,43000.0,0.03549298697372193,-2422.3247,-874.4929,1319.6584800000003 -0.85,43000.0,0.04595074206419332,-2115.3579,-755.3212,1338.961995 -0.7,43000.0,0.2484509088160526,-1400.321,-335.28,1712.74824 -0.75,43000.0,0.26070444003317095,-1085.2146,-177.6793,1735.3665 -0.8,43000.0,0.2738030423687113,-839.2385,-47.0228,1759.5446400000003 -0.85,43000.0,0.28774671582267314,-638.0304,58.5412,1785.2826599999999 -0.7,43000.0,0.48042293082287746,473.8456,589.921,2140.9353 -0.75,43000.0,0.49573984484427525,620.6105,690.3464,2169.208125 -0.8,43000.0,0.5121130977637007,749.7365,788.1461,2199.4308000000005 -0.85,43000.0,0.5295426895811531,863.3511,885.1731,2231.603325 -0.7,43000.0,0.5964089418262896,1387.9363,1053.5619,2355.0288299999997 -0.75,43000.0,0.6132575472498274,1505.2258,1156.5454,2386.1289375 -0.8,43000.0,0.6312681254611954,1626.7366,1265.7191,2419.3738800000006 -0.85,43000.0,0.6504406764603928,1753.5994,1381.5503,2454.7636574999997 -0.7,43000.0,0.712394952829702,2339.4993,1573.6965,2569.12236 -0.75,43000.0,0.7307752496553795,2457.5403,1694.1971,2603.04975 -0.8,43000.0,0.7504231531586901,2579.1248,1823.5708,2639.3169600000006 -0.85,43000.0,0.7713386633396329,2720.0356,1971.6774,2677.92399 -0.7,43000.0,0.8283809638331144,3260.1284,2150.562,2783.21589 -0.75,43000.0,0.8482929520609317,3384.1062,2302.1875,2819.9705625 -0.8,43000.0,0.8695781808561848,3539.3022,2476.9392,2859.2600400000006 -0.85,43000.0,0.8922366502188729,3710.6001,2667.4424,2901.0843225 -0.7,43000.0,0.9443669748365267,4031.8059,2740.031,2997.3094199999996 -0.75,43000.0,0.9658106544664838,4170.4385,2924.7302,3036.891375 -0.8,43000.0,0.9887332085536794,4324.1924,3131.4419,3079.2031200000006 diff --git a/aviary/models/engines/turbofan_24k_2.csv b/aviary/models/engines/turbofan_24k_2.csv new file mode 100644 index 0000000000..c9d2bee655 --- /dev/null +++ b/aviary/models/engines/turbofan_24k_2.csv @@ -0,0 +1,13233 @@ +# created 04/22/25 +# GASP-derived engine deck converted from GASP_turbofan_24_2.eng +# t4max: 50.0 +# t4cruise: 44.5 +# t4climb: 50.0 +# sls_airflow: 926.2 +# sfn_idle: 1.115 + +Mach_Number, Altitude (ft), Throttle, Thrust (lbf), Fuel_Flow (lb/h) + 0.0, 0.0, 0.0, 516.354, 516.354 + 0.0, 0.0, 22.0, 1905.1, 712.7 + 0.0, 0.0, 22.5, 2266.681, 780.073 + 0.0, 0.0, 23.0, 2624.53, 848.367 + 0.0, 0.0, 23.5, 2979.889, 917.778 + 0.0, 0.0, 24.0, 3334.0, 988.5 + 0.0, 0.0, 24.5, 3688.105, 1060.73 + 0.0, 0.0, 25.0, 4043.445, 1134.66 + 0.0, 0.0, 25.5, 4401.263, 1210.48 + 0.0, 0.0, 26.0, 4762.8, 1288.4 + 0.0, 0.0, 26.5, 5142.331, 1370.66 + 0.0, 0.0, 27.0, 5528.81, 1455.52 + 0.0, 0.0, 27.5, 5921.244, 1542.83 + 0.0, 0.0, 28.0, 6318.64, 1632.41 + 0.0, 0.0, 28.5, 6720.006, 1724.12 + 0.0, 0.0, 29.0, 7124.35, 1817.79 + 0.0, 0.0, 29.5, 7530.679, 1913.27 + 0.0, 0.0, 30.0, 7938.0, 2010.4 + 0.0, 0.0, 30.5, 8334.9, 2107.9 + 0.0, 0.0, 31.0, 8731.8, 2206.84 + 0.0, 0.0, 31.5, 9128.7, 2307.17 + 0.0, 0.0, 32.0, 9525.6, 2408.83 + 0.0, 0.0, 32.5, 9922.5, 2511.78 + 0.0, 0.0, 33.0, 10319.4, 2615.96 + 0.0, 0.0, 33.5, 10716.3, 2721.31 + 0.0, 0.0, 34.0, 11113.2, 2827.8 + 0.0, 0.0, 34.5, 11510.1, 2936.01 + 0.0, 0.0, 35.0, 11907.0, 3045.19 + 0.0, 0.0, 35.5, 12303.9, 3155.21 + 0.0, 0.0, 36.0, 12700.8, 3265.97 + 0.0, 0.0, 36.5, 13097.7, 3377.36 + 0.0, 0.0, 37.0, 13494.6, 3489.25 + 0.0, 0.0, 37.5, 13891.5, 3601.53 + 0.0, 0.0, 38.0, 14288.4, 3714.1 + 0.0, 0.0, 38.5, 14685.3, 3826.48 + 0.0, 0.0, 39.0, 15082.2, 3939.1 + 0.0, 0.0, 39.5, 15479.1, 4051.92 + 0.0, 0.0, 40.0, 15876.0, 4164.9 + 0.0, 0.0, 40.5, 16272.9, 4278.62 + 0.0, 0.0, 41.0, 16669.8, 4392.19 + 0.0, 0.0, 41.5, 17066.7, 4505.35 + 0.0, 0.0, 42.0, 17463.6, 4617.8 + 0.0, 0.0, 42.5, 17860.19, 4727.43 + 0.0, 0.0, 43.0, 18256.91, 4836.55 + 0.0, 0.0, 43.5, 18653.87, 4945.62 + 0.0, 0.0, 44.0, 19051.2, 5055.1 + 0.0, 0.0, 44.5, 19450.26, 5167.85 + 0.0, 0.0, 45.0, 19849.44, 5280.98 + 0.0, 0.0, 45.5, 20248.38, 5394.0 + 0.0, 0.0, 46.0, 20646.7, 5506.4 + 0.0, 0.0, 46.5, 21042.18, 5615.12 + 0.0, 0.0, 47.0, 21437.04, 5723.27 + 0.0, 0.0, 47.5, 21831.66, 5831.39 + 0.0, 0.0, 48.0, 22226.4, 5940.0 + 0.0, 0.0, 48.5, 22621.63, 6049.64 + 0.0, 0.0, 49.0, 23017.73, 6160.85 + 0.0, 0.0, 49.5, 23415.06, 6274.16 + 0.0, 0.0, 50.0, 23814.0, 6390.1 + 0.0, 2000.0, 0.0, 483.4466, 483.447 + 0.0, 2000.0, 22.0, 1886.2, 685.4 + 0.0, 2000.0, 22.5, 2244.132, 753.18 + 0.0, 2000.0, 23.0, 2598.392, 821.536 + 0.0, 2000.0, 23.5, 2950.206, 890.724 + 0.0, 2000.0, 24.0, 3300.8, 961.0 + 0.0, 2000.0, 24.5, 3651.4, 1032.62 + 0.0, 2000.0, 25.0, 4003.233, 1105.84 + 0.0, 2000.0, 25.5, 4357.524, 1180.91 + 0.0, 2000.0, 26.0, 4715.5, 1258.1 + 0.0, 2000.0, 26.5, 5091.266, 1340.16 + 0.0, 2000.0, 27.0, 5473.905, 1424.99 + 0.0, 2000.0, 27.5, 5862.435, 1512.41 + 0.0, 2000.0, 28.0, 6255.875, 1602.25 + 0.0, 2000.0, 28.5, 6653.243, 1694.33 + 0.0, 2000.0, 29.0, 7053.558, 1788.48 + 0.0, 2000.0, 29.5, 7455.837, 1884.53 + 0.0, 2000.0, 30.0, 7859.1, 1982.3 + 0.0, 2000.0, 30.5, 8252.061, 2080.75 + 0.0, 2000.0, 31.0, 8645.023, 2180.67 + 0.0, 2000.0, 31.5, 9037.987, 2281.94 + 0.0, 2000.0, 32.0, 9430.95, 2384.49 + 0.0, 2000.0, 32.5, 9823.913, 2488.23 + 0.0, 2000.0, 33.0, 10216.88, 2593.05 + 0.0, 2000.0, 33.5, 10609.84, 2698.87 + 0.0, 2000.0, 34.0, 11002.8, 2805.6 + 0.0, 2000.0, 34.5, 11395.75, 2912.85 + 0.0, 2000.0, 35.0, 11788.69, 3020.86 + 0.0, 2000.0, 35.5, 12181.64, 3129.55 + 0.0, 2000.0, 36.0, 12574.59, 3238.87 + 0.0, 2000.0, 36.5, 12967.53, 3348.75 + 0.0, 2000.0, 37.0, 13360.49, 3459.12 + 0.0, 2000.0, 37.5, 13753.44, 3569.93 + 0.0, 2000.0, 38.0, 14146.4, 3681.1 + 0.0, 2000.0, 38.5, 14539.38, 3793.54 + 0.0, 2000.0, 39.0, 14932.35, 3905.72 + 0.0, 2000.0, 39.5, 15325.33, 4017.37 + 0.0, 2000.0, 40.0, 15718.3, 4128.2 + 0.0, 2000.0, 40.5, 16111.26, 4235.99 + 0.0, 2000.0, 41.0, 16504.21, 4343.18 + 0.0, 2000.0, 41.5, 16897.15, 4450.29 + 0.0, 2000.0, 42.0, 17290.1, 4557.8 + 0.0, 2000.0, 42.5, 17682.74, 4668.68 + 0.0, 2000.0, 43.0, 18075.51, 4779.99 + 0.0, 2000.0, 43.5, 18468.52, 4891.26 + 0.0, 2000.0, 44.0, 18861.9, 5002.0 + 0.0, 2000.0, 44.5, 19257.01, 5109.55 + 0.0, 2000.0, 45.0, 19652.24, 5216.48 + 0.0, 2000.0, 45.5, 20047.23, 5323.2 + 0.0, 2000.0, 46.0, 20441.6, 5430.1 + 0.0, 2000.0, 46.5, 20833.15, 5538.34 + 0.0, 2000.0, 47.0, 21224.09, 5647.24 + 0.0, 2000.0, 47.5, 21614.79, 5756.9 + 0.0, 2000.0, 48.0, 22005.6, 5867.4 + 0.0, 2000.0, 48.5, 22396.9, 5978.83 + 0.0, 2000.0, 49.0, 22789.06, 6091.28 + 0.0, 2000.0, 49.5, 23182.43, 6204.84 + 0.0, 2000.0, 50.0, 23577.4, 6319.6 + 0.0, 5000.0, 0.0, 437.2125, 437.213 + 0.0, 5000.0, 22.0, 1789.5, 634.7 + 0.0, 5000.0, 22.5, 2129.087, 699.776 + 0.0, 5000.0, 23.0, 2465.191, 765.105 + 0.0, 5000.0, 23.5, 2798.974, 830.981 + 0.0, 5000.0, 24.0, 3131.6, 897.7 + 0.0, 5000.0, 24.5, 3464.232, 965.556 + 0.0, 5000.0, 25.0, 3798.034, 1034.85 + 0.0, 5000.0, 25.5, 4134.169, 1105.86 + 0.0, 5000.0, 26.0, 4473.8, 1178.9 + 0.0, 5000.0, 26.5, 4830.31, 1257.1 + 0.0, 5000.0, 27.0, 5193.341, 1338.07 + 0.0, 5000.0, 27.5, 5561.962, 1421.62 + 0.0, 5000.0, 28.0, 5935.24, 1507.56 + 0.0, 5000.0, 28.5, 6312.245, 1595.71 + 0.0, 5000.0, 29.0, 6692.044, 1685.85 + 0.0, 5000.0, 29.5, 7073.706, 1777.82 + 0.0, 5000.0, 30.0, 7456.3, 1871.4 + 0.0, 5000.0, 30.5, 7829.112, 1965.33 + 0.0, 5000.0, 31.0, 8201.925, 2060.59 + 0.0, 5000.0, 31.5, 8574.738, 2157.11 + 0.0, 5000.0, 32.0, 8947.55, 2254.79 + 0.0, 5000.0, 32.5, 9320.362, 2353.55 + 0.0, 5000.0, 33.0, 9693.175, 2453.3 + 0.0, 5000.0, 33.5, 10065.99, 2553.94 + 0.0, 5000.0, 34.0, 10438.8, 2655.4 + 0.0, 5000.0, 34.5, 10811.61, 2758.03 + 0.0, 5000.0, 35.0, 11184.42, 2861.25 + 0.0, 5000.0, 35.5, 11557.23, 2964.92 + 0.0, 5000.0, 36.0, 11930.04, 3068.93 + 0.0, 5000.0, 36.5, 12302.85, 3173.13 + 0.0, 5000.0, 37.0, 12675.67, 3277.4 + 0.0, 5000.0, 37.5, 13048.48, 3381.6 + 0.0, 5000.0, 38.0, 13421.3, 3485.6 + 0.0, 5000.0, 38.5, 13794.13, 3588.67 + 0.0, 5000.0, 39.0, 14166.96, 3691.59 + 0.0, 5000.0, 39.5, 14539.78, 3794.36 + 0.0, 5000.0, 40.0, 14912.6, 3897.0 + 0.0, 5000.0, 40.5, 15285.4, 3999.58 + 0.0, 5000.0, 41.0, 15658.2, 4102.0 + 0.0, 5000.0, 41.5, 16031.0, 4204.22 + 0.0, 5000.0, 42.0, 16403.8, 4306.2 + 0.0, 5000.0, 42.5, 16776.33, 4407.45 + 0.0, 5000.0, 43.0, 17148.98, 4508.59 + 0.0, 5000.0, 43.5, 17521.87, 4609.79 + 0.0, 5000.0, 44.0, 17895.1, 4711.2 + 0.0, 5000.0, 44.5, 18269.95, 4813.32 + 0.0, 5000.0, 45.0, 18644.92, 4915.84 + 0.0, 5000.0, 45.5, 19019.65, 5018.79 + 0.0, 5000.0, 46.0, 19393.8, 5122.2 + 0.0, 5000.0, 46.5, 19765.28, 5225.91 + 0.0, 5000.0, 47.0, 20136.17, 5330.22 + 0.0, 5000.0, 47.5, 20506.83, 5435.21 + 0.0, 5000.0, 48.0, 20877.6, 5541.0 + 0.0, 5000.0, 48.5, 21248.84, 5647.68 + 0.0, 5000.0, 49.0, 21620.88, 5755.36 + 0.0, 5000.0, 49.5, 21994.09, 5864.13 + 0.0, 5000.0, 50.0, 22368.8, 5974.1 + 0.0, 10000.0, 0.0, 367.9769, 367.977 + 0.0, 10000.0, 22.0, 1639.5, 619.3 + 0.0, 10000.0, 22.5, 1949.738, 632.806 + 0.0, 10000.0, 23.0, 2256.992, 652.978 + 0.0, 10000.0, 23.5, 2562.3, 679.511 + 0.0, 10000.0, 24.0, 2866.7, 712.1 + 0.0, 10000.0, 24.5, 3171.231, 750.439 + 0.0, 10000.0, 25.0, 3476.933, 794.222 + 0.0, 10000.0, 25.5, 3784.843, 843.144 + 0.0, 10000.0, 26.0, 4096.0, 896.9 + 0.0, 10000.0, 26.5, 4422.491, 950.571 + 0.0, 10000.0, 27.0, 4754.939, 1008.2 + 0.0, 10000.0, 27.5, 5092.487, 1070.28 + 0.0, 10000.0, 28.0, 5434.28, 1137.28 + 0.0, 10000.0, 28.5, 5779.463, 1209.7 + 0.0, 10000.0, 29.0, 6127.181, 1288.02 + 0.0, 10000.0, 29.5, 6476.579, 1372.72 + 0.0, 10000.0, 30.0, 6826.8, 1464.3 + 0.0, 10000.0, 30.5, 7167.938, 1586.59 + 0.0, 10000.0, 31.0, 7509.051, 1714.49 + 0.0, 10000.0, 31.5, 7850.146, 1846.27 + 0.0, 10000.0, 32.0, 8191.231, 1980.19 + 0.0, 10000.0, 32.5, 8532.312, 2114.52 + 0.0, 10000.0, 33.0, 8873.396, 2247.5 + 0.0, 10000.0, 33.5, 9214.49, 2377.41 + 0.0, 10000.0, 34.0, 9555.6, 2502.5 + 0.0, 10000.0, 34.5, 9896.944, 2588.02 + 0.0, 10000.0, 35.0, 10238.3, 2668.38 + 0.0, 10000.0, 35.5, 10579.65, 2745.01 + 0.0, 10000.0, 36.0, 10920.98, 2819.29 + 0.0, 10000.0, 36.5, 11262.29, 2892.65 + 0.0, 10000.0, 37.0, 11603.55, 2966.48 + 0.0, 10000.0, 37.5, 11944.76, 3042.2 + 0.0, 10000.0, 38.0, 12285.9, 3121.2 + 0.0, 10000.0, 38.5, 12626.71, 3210.95 + 0.0, 10000.0, 39.0, 12967.55, 3303.66 + 0.0, 10000.0, 39.5, 13308.46, 3399.39 + 0.0, 10000.0, 40.0, 13649.5, 3498.2 + 0.0, 10000.0, 40.5, 13990.93, 3605.57 + 0.0, 10000.0, 41.0, 14332.48, 3713.97 + 0.0, 10000.0, 41.5, 14674.08, 3821.28 + 0.0, 10000.0, 42.0, 15015.7, 3925.4 + 0.0, 10000.0, 42.5, 15356.85, 4015.02 + 0.0, 10000.0, 43.0, 15698.08, 4100.9 + 0.0, 10000.0, 43.5, 16039.52, 4184.6 + 0.0, 10000.0, 44.0, 16381.3, 4267.7 + 0.0, 10000.0, 44.5, 16724.73, 4354.76 + 0.0, 10000.0, 45.0, 17068.26, 4443.14 + 0.0, 10000.0, 45.5, 17411.53, 4533.2 + 0.0, 10000.0, 46.0, 17754.2, 4625.3 + 0.0, 10000.0, 46.5, 18094.06, 4720.83 + 0.0, 10000.0, 47.0, 18433.34, 4818.71 + 0.0, 10000.0, 47.5, 18772.42, 4918.88 + 0.0, 10000.0, 48.0, 19111.7, 5021.3 + 0.0, 10000.0, 48.5, 19451.55, 5125.91 + 0.0, 10000.0, 49.0, 19792.36, 5232.67 + 0.0, 10000.0, 49.5, 20134.52, 5341.51 + 0.0, 10000.0, 50.0, 20478.4, 5452.4 + 0.0, 15000.0, 0.0, 307.6998, 307.7 + 0.0, 15000.0, 22.0, -18404.9, -6240.2 + 0.0, 15000.0, 22.5, -21899.51, -7443.83 + 0.0, 15000.0, 23.0, -25357.13, -8590.23 + 0.0, 15000.0, 23.5, -28789.9, -9693.96 + 0.0, 15000.0, 24.0, -32209.9, -10769.6 + 0.0, 15000.0, 24.5, -35629.25, -11831.7 + 0.0, 15000.0, 25.0, -39060.07, -12894.8 + 0.0, 15000.0, 25.5, -42514.44, -13973.5 + 0.0, 15000.0, 26.0, -46004.5, -15082.4 + 0.0, 15000.0, 26.5, -49668.54, -16329.8 + 0.0, 15000.0, 27.0, -53399.68, -17641.8 + 0.0, 15000.0, 27.5, -57188.4, -19016.9 + 0.0, 15000.0, 28.0, -61025.18, -20453.7 + 0.0, 15000.0, 28.5, -64900.48, -21950.5 + 0.0, 15000.0, 29.0, -68804.79, -23505.9 + 0.0, 15000.0, 29.5, -72728.57, -25118.4 + 0.0, 15000.0, 30.0, -76662.3, -26786.4 + 0.0, 15000.0, 30.5, -80497.55, -28659.3 + 0.0, 15000.0, 31.0, -84333.13, -30570.3 + 0.0, 15000.0, 31.5, -88168.91, -32503.6 + 0.0, 15000.0, 32.0, -92004.8, -34443.2 + 0.0, 15000.0, 32.5, -95840.69, -36373.3 + 0.0, 15000.0, 33.0, -99676.48, -38278.1 + 0.0, 15000.0, 33.5, -103512.0, -40141.6 + 0.0, 15000.0, 34.0, -107347.3, -41947.9 + 0.0, 15000.0, 34.5, -111178.3, -43271.5 + 0.0, 15000.0, 35.0, -115009.1, -44545.3 + 0.0, 15000.0, 35.5, -118840.1, -45792.2 + 0.0, 15000.0, 36.0, -122671.3, -47035.6 + 0.0, 15000.0, 36.5, -126503.2, -48298.4 + 0.0, 15000.0, 37.0, -130336.0, -49603.8 + 0.0, 15000.0, 37.5, -134169.8, -50975.0 + 0.0, 15000.0, 38.0, -138005.1, -52435.1 + 0.0, 15000.0, 38.5, -141845.7, -54147.3 + 0.0, 15000.0, 39.0, -145686.3, -55922.0 + 0.0, 15000.0, 39.5, -149526.3, -57751.2 + 0.0, 15000.0, 40.0, -153365.1, -59626.9 + 0.0, 15000.0, 40.5, -157200.1, -61502.3 + 0.0, 15000.0, 41.0, -161033.6, -63423.6 + 0.0, 15000.0, 41.5, -164866.1, -65398.4 + 0.0, 15000.0, 42.0, -168697.8, -67434.1 + 0.0, 15000.0, 42.5, -172526.4, -69643.1 + 0.0, 15000.0, 43.0, -176355.8, -71886.1 + 0.0, 15000.0, 43.5, -180187.6, -74128.6 + 0.0, 15000.0, 44.0, -184022.9, -76336.0 + 0.0, 15000.0, 44.5, -187876.4, -78266.5 + 0.0, 15000.0, 45.0, -191731.0, -80176.0 + 0.0, 15000.0, 45.5, -195582.7, -82112.9 + 0.0, 15000.0, 46.0, -199427.7, -84125.8 + 0.0, 15000.0, 46.5, -203241.5, -86400.3 + 0.0, 15000.0, 47.0, -207048.9, -88792.8 + 0.0, 15000.0, 47.5, -210854.2, -91296.8 + 0.0, 15000.0, 48.0, -214661.8, -93905.9 + 0.0, 15000.0, 48.5, -218475.9, -96613.7 + 0.0, 15000.0, 49.0, -222300.7, -99413.7 + 0.0, 15000.0, 49.5, -226140.7, -102300.0 + 0.0, 15000.0, 50.0, -230000.1, -105265.0 + 0.0, 20000.0, 0.0, 255.5048, 255.505 + 0.0, 20000.0, 22.0, 886.1, 130.7 + 0.0, 20000.0, 22.5, 1079.251, 574.656 + 0.0, 20000.0, 23.0, 1264.516, 829.636 + 0.0, 20000.0, 23.5, 1443.447, 924.297 + 0.0, 20000.0, 24.0, 1617.6, 887.3 + 0.0, 20000.0, 24.5, 1788.528, 747.303 + 0.0, 20000.0, 25.0, 1957.784, 532.964 + 0.0, 20000.0, 25.5, 2126.924, 272.944 + 0.0, 20000.0, 26.0, 2297.5, -4.1 + 0.0, 20000.0, 26.5, 2486.409, -54.9521 + 0.0, 20000.0, 27.0, 2680.74, -53.2491 + 0.0, 20000.0, 27.5, 2879.416, -7.1127 + 0.0, 20000.0, 28.0, 3081.36, 75.335 + 0.0, 20000.0, 28.5, 3285.497, 185.972 + 0.0, 20000.0, 29.0, 3490.75, 316.677 + 0.0, 20000.0, 29.5, 3696.043, 459.327 + 0.0, 20000.0, 30.0, 3900.3, 605.8 + 0.0, 20000.0, 30.5, 4085.26, 630.253 + 0.0, 20000.0, 31.0, 4268.668, 653.498 + 0.0, 20000.0, 31.5, 4451.084, 678.623 + 0.0, 20000.0, 32.0, 4633.069, 708.719 + 0.0, 20000.0, 32.5, 4815.182, 746.875 + 0.0, 20000.0, 33.0, 4997.985, 796.18 + 0.0, 20000.0, 33.5, 5182.038, 859.726 + 0.0, 20000.0, 34.0, 5367.9, 940.6 + 0.0, 20000.0, 34.5, 5571.777, 1268.18 + 0.0, 20000.0, 35.0, 5777.095, 1597.72 + 0.0, 20000.0, 35.5, 5982.924, 1910.75 + 0.0, 20000.0, 36.0, 6188.335, 2188.82 + 0.0, 20000.0, 36.5, 6392.397, 2413.46 + 0.0, 20000.0, 37.0, 6594.182, 2566.21 + 0.0, 20000.0, 37.5, 6792.76, 2628.61 + 0.0, 20000.0, 38.0, 6987.2, 2582.2 + 0.0, 20000.0, 38.5, 7166.841, 2145.19 + 0.0, 20000.0, 39.0, 7345.533, 1698.98 + 0.0, 20000.0, 39.5, 7524.508, 1283.63 + 0.0, 20000.0, 40.0, 7705.0, 939.2 + 0.0, 20000.0, 40.5, 7893.216, 839.489 + 0.0, 20000.0, 41.0, 8083.425, 837.3 + 0.0, 20000.0, 41.5, 8274.872, 919.186 + 0.0, 20000.0, 42.0, 8466.8, 1071.7 + 0.0, 20000.0, 42.5, 8657.164, 1267.78 + 0.0, 20000.0, 43.0, 8847.012, 1513.04 + 0.0, 20000.0, 43.5, 9036.105, 1799.48 + 0.0, 20000.0, 44.0, 9224.2, 2119.1 + 0.0, 20000.0, 44.5, 9406.714, 2494.51 + 0.0, 20000.0, 45.0, 9589.487, 2874.84 + 0.0, 20000.0, 45.5, 9774.017, 3239.86 + 0.0, 20000.0, 46.0, 9961.8, 3569.3 + 0.0, 20000.0, 46.5, 10162.59, 3778.77 + 0.0, 20000.0, 47.0, 10366.33, 3937.84 + 0.0, 20000.0, 47.5, 10571.2, 4051.91 + 0.0, 20000.0, 48.0, 10775.4, 4126.4 + 0.0, 20000.0, 48.5, 10977.12, 4166.72 + 0.0, 20000.0, 49.0, 11174.54, 4178.29 + 0.0, 20000.0, 49.5, 11365.87, 4166.51 + 0.0, 20000.0, 50.0, 11549.3, 4136.8 + 0.0, 25000.0, 0.0, 210.5652, 210.565 + 0.0, 25000.0, 22.0, 308.1, 661.0 + 0.0, 25000.0, 22.5, 396.8693, -145.131 + 0.0, 25000.0, 23.0, 478.0453, -587.439 + 0.0, 25000.0, 23.5, 552.9236, -723.353 + 0.0, 25000.0, 24.0, 622.8, -610.3 + 0.0, 25000.0, 24.5, 688.9701, -305.71 + 0.0, 25000.0, 25.0, 752.7297, 132.989 + 0.0, 25000.0, 25.5, 815.3744, 648.369 + 0.0, 25000.0, 26.0, 878.2, 1183.0 + 0.0, 25000.0, 26.5, 954.4883, 1204.27 + 0.0, 25000.0, 27.0, 1034.234, 1102.78 + 0.0, 25000.0, 27.5, 1116.677, 902.565 + 0.0, 25000.0, 28.0, 1201.06, 627.655 + 0.0, 25000.0, 28.5, 1286.623, 302.081 + 0.0, 25000.0, 29.0, 1372.606, -50.1234 + 0.0, 25000.0, 29.5, 1458.252, -404.928 + 0.0, 25000.0, 30.0, 1542.8, -738.3 + 0.0, 25000.0, 30.5, 1613.865, -687.996 + 0.0, 25000.0, 31.0, 1683.423, -600.406 + 0.0, 25000.0, 31.5, 1751.82, -483.711 + 0.0, 25000.0, 32.0, 1819.406, -346.087 + 0.0, 25000.0, 32.5, 1886.529, -195.716 + 0.0, 25000.0, 33.0, 1953.537, -40.775 + 0.0, 25000.0, 33.5, 2020.778, 110.557 + 0.0, 25000.0, 34.0, 2088.6, 250.1 + 0.0, 25000.0, 34.5, 2164.425, 42.1754 + 0.0, 25000.0, 35.0, 2240.855, -162.705 + 0.0, 25000.0, 35.5, 2317.563, -341.529 + 0.0, 25000.0, 36.0, 2394.225, -471.285 + 0.0, 25000.0, 36.5, 2470.515, -528.962 + 0.0, 25000.0, 37.0, 2546.108, -491.548 + 0.0, 25000.0, 37.5, 2620.678, -336.031 + 0.0, 25000.0, 38.0, 2693.9, -39.4 + 0.0, 25000.0, 38.5, 2757.829, 947.407 + 0.0, 25000.0, 39.0, 2823.709, 1848.58 + 0.0, 25000.0, 39.5, 2892.911, 2570.24 + 0.0, 25000.0, 40.0, 2966.8, 3018.5 + 0.0, 25000.0, 40.5, 3058.986, 2601.37 + 0.0, 25000.0, 41.0, 3153.7, 1922.3 + 0.0, 25000.0, 41.5, 3247.414, 1086.63 + 0.0, 25000.0, 42.0, 3336.6, 199.7 + 0.0, 25000.0, 42.5, 3397.445, -416.012 + 0.0, 25000.0, 43.0, 3454.819, -959.131 + 0.0, 25000.0, 43.5, 3513.309, -1411.16 + 0.0, 25000.0, 44.0, 3577.5, -1753.6 + 0.0, 25000.0, 44.5, 3678.123, -1852.46 + 0.0, 25000.0, 45.0, 3783.163, -1850.93 + 0.0, 25000.0, 45.5, 3886.745, -1776.71 + 0.0, 25000.0, 46.0, 3983.0, -1657.5 + 0.0, 25000.0, 46.5, 4038.379, -1683.54 + 0.0, 25000.0, 47.0, 4085.756, -1654.96 + 0.0, 25000.0, 47.5, 4130.33, -1534.46 + 0.0, 25000.0, 48.0, 4177.3, -1284.7 + 0.0, 25000.0, 48.5, 4231.863, -868.375 + 0.0, 25000.0, 49.0, 4299.219, -248.162 + 0.0, 25000.0, 49.5, 4384.565, 613.256 + 0.0, 25000.0, 50.0, 4493.1, 1753.2 + 0.0, 30000.0, 0.0, 172.1124, 172.112 + 0.0, 30000.0, 22.0, -319.4, -160.2 + 0.0, 30000.0, 22.5, -390.6154, 123.011 + 0.0, 30000.0, 23.0, -457.1391, 204.725 + 0.0, 30000.0, 23.5, -519.6182, 120.777 + 0.0, 30000.0, 24.0, -578.7, -93.0 + 0.0, 30000.0, 24.5, -635.0318, -400.77 + 0.0, 30000.0, 25.0, -689.2609, -766.7 + 0.0, 30000.0, 25.5, -742.0346, -1154.95 + 0.0, 30000.0, 26.0, -794.0, -1529.7 + 0.0, 30000.0, 26.5, -849.3059, -1500.6 + 0.0, 30000.0, 27.0, -905.2981, -1366.06 + 0.0, 30000.0, 27.5, -962.0238, -1151.03 + 0.0, 30000.0, 28.0, -1019.53, -880.43 + 0.0, 30000.0, 28.5, -1077.864, -579.212 + 0.0, 30000.0, 29.0, -1137.072, -272.309 + 0.0, 30000.0, 29.5, -1197.202, 15.3405 + 0.0, 30000.0, 30.0, -1258.3, 258.8 + 0.0, 30000.0, 30.5, -1322.827, 35.354 + 0.0, 30000.0, 31.0, -1388.187, -244.274 + 0.0, 30000.0, 31.5, -1454.198, -567.139 + 0.0, 30000.0, 32.0, -1520.675, -920.294 + 0.0, 30000.0, 32.5, -1587.437, -1290.79 + 0.0, 30000.0, 33.0, -1654.3, -1665.69 + 0.0, 30000.0, 33.5, -1721.082, -2032.04 + 0.0, 30000.0, 34.0, -1787.6, -2376.9 + 0.0, 30000.0, 34.5, -1844.049, -2567.32 + 0.0, 30000.0, 35.0, -1900.784, -2721.78 + 0.0, 30000.0, 35.5, -1958.54, -2838.77 + 0.0, 30000.0, 36.0, -2018.05, -2916.76 + 0.0, 30000.0, 36.5, -2080.047, -2954.25 + 0.0, 30000.0, 37.0, -2145.266, -2949.72 + 0.0, 30000.0, 37.5, -2214.439, -2901.64 + 0.0, 30000.0, 38.0, -2288.3, -2808.5 + 0.0, 30000.0, 38.5, -2386.293, -2510.69 + 0.0, 30000.0, 39.0, -2480.741, -2246.77 + 0.0, 30000.0, 39.5, -2568.218, -2050.33 + 0.0, 30000.0, 40.0, -2645.3, -1955.0 + 0.0, 30000.0, 40.5, -2686.335, -2152.49 + 0.0, 30000.0, 41.0, -2719.019, -2455.08 + 0.0, 30000.0, 41.5, -2748.818, -2833.12 + 0.0, 30000.0, 42.0, -2781.2, -3257.0 + 0.0, 30000.0, 42.5, -2837.62, -3905.66 + 0.0, 30000.0, 43.0, -2901.163, -4457.46 + 0.0, 30000.0, 43.5, -2970.898, -4799.36 + 0.0, 30000.0, 44.0, -3045.9, -4818.3 + 0.0, 30000.0, 44.5, -3127.446, -3623.25 + 0.0, 30000.0, 45.0, -3211.519, -2190.32 + 0.0, 30000.0, 45.5, -3296.307, -717.624 + 0.0, 30000.0, 46.0, -3380.0, 596.7 + 0.0, 30000.0, 46.5, -3457.576, 1003.33 + 0.0, 30000.0, 47.0, -3531.719, 1075.81 + 0.0, 30000.0, 47.5, -3601.902, 836.486 + 0.0, 30000.0, 48.0, -3667.6, 307.7 + 0.0, 30000.0, 48.5, -3728.285, -488.198 + 0.0, 30000.0, 49.0, -3783.431, -1528.86 + 0.0, 30000.0, 49.5, -3832.512, -2791.95 + 0.0, 30000.0, 50.0, -3875.0, -4255.1 + 0.0, 35000.0, 0.0, 139.4306, 139.431 + 0.0, 35000.0, 22.0, 1045.8, -150.9 + 0.0, 35000.0, 22.5, 1291.873, -241.677 + 0.0, 35000.0, 23.0, 1523.694, -199.0 + 0.0, 35000.0, 23.5, 1743.418, -48.4984 + 0.0, 35000.0, 24.0, 1953.2, 184.2 + 0.0, 35000.0, 24.5, 2155.195, 473.467 + 0.0, 35000.0, 25.0, 2351.556, 793.675 + 0.0, 35000.0, 25.5, 2544.44, 1119.2 + 0.0, 35000.0, 26.0, 2736.0, 1424.4 + 0.0, 35000.0, 26.5, 2942.497, 1414.03 + 0.0, 35000.0, 27.0, 3152.785, 1316.69 + 0.0, 35000.0, 27.5, 3366.603, 1152.96 + 0.0, 35000.0, 28.0, 3583.685, 943.435 + 0.0, 35000.0, 28.5, 3803.769, 708.714 + 0.0, 35000.0, 29.0, 4026.592, 469.389 + 0.0, 35000.0, 29.5, 4251.89, 246.053 + 0.0, 35000.0, 30.0, 4479.4, 59.3 + 0.0, 35000.0, 30.5, 4711.021, 333.031 + 0.0, 35000.0, 31.0, 4944.121, 646.123 + 0.0, 35000.0, 31.5, 5178.231, 980.757 + 0.0, 35000.0, 32.0, 5412.881, 1319.12 + 0.0, 35000.0, 32.5, 5647.603, 1643.39 + 0.0, 35000.0, 33.0, 5881.926, 1935.76 + 0.0, 35000.0, 33.5, 6115.381, 2178.4 + 0.0, 35000.0, 34.0, 6347.5, 2353.5 + 0.0, 35000.0, 34.5, 6554.733, 1960.26 + 0.0, 35000.0, 35.0, 6761.888, 1509.84 + 0.0, 35000.0, 35.5, 6970.694, 1030.44 + 0.0, 35000.0, 36.0, 7182.88, 550.22 + 0.0, 35000.0, 36.5, 7400.175, 97.3758 + 0.0, 35000.0, 37.0, 7624.308, -299.914 + 0.0, 35000.0, 37.5, 7857.006, -613.466 + 0.0, 35000.0, 38.0, 8100.0, -815.1 + 0.0, 35000.0, 38.5, 8387.582, -1110.19 + 0.0, 35000.0, 39.0, 8672.031, -1115.89 + 0.0, 35000.0, 39.5, 8947.84, -752.122 + 0.0, 35000.0, 40.0, 9209.5, 61.2 + 0.0, 35000.0, 40.5, 9419.102, 2251.19 + 0.0, 35000.0, 41.0, 9616.5, 4712.09 + 0.0, 35000.0, 41.5, 9809.148, 7185.17 + 0.0, 35000.0, 42.0, 10004.5, 9411.7 + 0.0, 35000.0, 42.5, 10241.27, 10589.7 + 0.0, 35000.0, 43.0, 10483.15, 11221.0 + 0.0, 35000.0, 43.5, 10725.08, 11264.1 + 0.0, 35000.0, 44.0, 10962.0, 10677.7 + 0.0, 35000.0, 44.5, 11161.29, 8495.28 + 0.0, 35000.0, 45.0, 11356.5, 5970.39 + 0.0, 35000.0, 45.5, 11553.61, 3431.58 + 0.0, 35000.0, 46.0, 11758.6, 1207.4 + 0.0, 35000.0, 46.5, 12006.27, 800.196 + 0.0, 35000.0, 47.0, 12262.25, 895.206 + 0.0, 35000.0, 47.5, 12520.98, 1351.46 + 0.0, 35000.0, 48.0, 12776.9, 2028.0 + 0.0, 35000.0, 48.5, 13024.47, 2783.85 + 0.0, 35000.0, 49.0, 13258.13, 3478.04 + 0.0, 35000.0, 49.5, 13472.32, 3969.62 + 0.0, 35000.0, 50.0, 13661.5, 4117.6 + 0.0, 39000.0, 0.0, 115.6452, 115.645 + 0.0, 39000.0, 22.0, 684.7, -524.2 + 0.0, 39000.0, 22.5, 862.0838, -808.27 + 0.0, 39000.0, 23.0, 1022.467, -851.814 + 0.0, 39000.0, 23.5, 1168.892, -697.301 + 0.0, 39000.0, 24.0, 1304.4, -387.2 + 0.0, 39000.0, 24.5, 1432.033, 36.0197 + 0.0, 39000.0, 25.0, 1554.833, 529.889 + 0.0, 39000.0, 25.5, 1675.841, 1051.94 + 0.0, 39000.0, 26.0, 1798.1, 1559.7 + 0.0, 39000.0, 26.5, 1953.023, 1641.32 + 0.0, 39000.0, 27.0, 2116.901, 1602.6 + 0.0, 39000.0, 27.5, 2287.912, 1464.41 + 0.0, 39000.0, 28.0, 2464.235, 1247.59 + 0.0, 39000.0, 28.5, 2644.047, 972.989 + 0.0, 39000.0, 29.0, 2825.527, 661.473 + 0.0, 39000.0, 29.5, 3006.852, 333.893 + 0.0, 39000.0, 30.0, 3186.2, 11.1 + 0.0, 39000.0, 30.5, 3333.582, -24.8719 + 0.0, 39000.0, 31.0, 3478.026, -39.2219 + 0.0, 39000.0, 31.5, 3620.393, -35.9703 + 0.0, 39000.0, 32.0, 3761.544, -19.1375 + 0.0, 39000.0, 32.5, 3902.339, 7.25625 + 0.0, 39000.0, 33.0, 4043.64, 39.1906 + 0.0, 39000.0, 33.5, 4186.307, 72.6453 + 0.0, 39000.0, 34.0, 4331.2, 103.6 + 0.0, 39000.0, 34.5, 4504.343, 216.278 + 0.0, 39000.0, 35.0, 4679.037, 310.011 + 0.0, 39000.0, 35.5, 4853.748, 372.375 + 0.0, 39000.0, 36.0, 5026.94, 390.945 + 0.0, 39000.0, 36.5, 5197.077, 353.297 + 0.0, 39000.0, 37.0, 5362.622, 247.007 + 0.0, 39000.0, 37.5, 5522.042, 59.649 + 0.0, 39000.0, 38.0, 5673.8, -221.2 + 0.0, 39000.0, 38.5, 5791.489, -1036.12 + 0.0, 39000.0, 39.0, 5911.341, -1747.38 + 0.0, 39000.0, 39.5, 6037.347, -2272.24 + 0.0, 39000.0, 40.0, 6173.5, -2528.0 + 0.0, 39000.0, 40.5, 6345.097, -2174.51 + 0.0, 39000.0, 41.0, 6526.3, -1489.43 + 0.0, 39000.0, 41.5, 6712.578, -493.013 + 0.0, 39000.0, 42.0, 6899.4, 794.5 + 0.0, 39000.0, 42.5, 7054.801, 2709.55 + 0.0, 39000.0, 43.0, 7212.656, 4732.53 + 0.0, 39000.0, 43.5, 7379.409, 6700.52 + 0.0, 39000.0, 44.0, 7561.5, 8450.6 + 0.0, 39000.0, 44.5, 7829.314, 9582.59 + 0.0, 39000.0, 45.0, 8099.775, 10265.7 + 0.0, 39000.0, 45.5, 8353.748, 10432.1 + 0.0, 39000.0, 46.0, 8572.1, 10013.5 + 0.0, 39000.0, 46.5, 8627.035, 8156.87 + 0.0, 39000.0, 47.0, 8651.544, 5893.45 + 0.0, 39000.0, 47.5, 8669.955, 3469.3 + 0.0, 39000.0, 48.0, 8706.6, 1130.5 + 0.0, 39000.0, 48.5, 8785.807, -876.883 + 0.0, 39000.0, 49.0, 8931.906, -2306.78 + 0.0, 39000.0, 49.5, 9169.227, -2913.1 + 0.0, 39000.0, 50.0, 9522.1, -2449.8 + 0.0, 43000.0, 0.0, 95.4187, 95.4187 + 0.0, 43000.0, 22.0, -1065.5, 1347.5 + 0.0, 43000.0, 22.5, -1181.135, 459.62 + 0.0, 43000.0, 23.0, -1304.083, -276.506 + 0.0, 43000.0, 23.5, -1434.239, -880.854 + 0.0, 43000.0, 24.0, -1571.5, -1373.4 + 0.0, 43000.0, 24.5, -1715.761, -1774.12 + 0.0, 43000.0, 25.0, -1866.917, -2102.99 + 0.0, 43000.0, 25.5, -2024.865, -2379.99 + 0.0, 43000.0, 26.0, -2189.5, -2625.1 + 0.0, 43000.0, 26.5, -2365.748, -3077.68 + 0.0, 43000.0, 27.0, -2548.761, -3550.86 + 0.0, 43000.0, 27.5, -2737.574, -4027.0 + 0.0, 43000.0, 28.0, -2931.22, -4488.46 + 0.0, 43000.0, 28.5, -3128.732, -4917.62 + 0.0, 43000.0, 29.0, -3329.144, -5296.83 + 0.0, 43000.0, 29.5, -3531.489, -5608.47 + 0.0, 43000.0, 30.0, -3734.8, -5834.9 + 0.0, 43000.0, 30.5, -3930.719, -5752.82 + 0.0, 43000.0, 31.0, -4126.375, -5569.86 + 0.0, 43000.0, 31.5, -4321.506, -5287.95 + 0.0, 43000.0, 32.0, -4515.85, -4909.06 + 0.0, 43000.0, 32.5, -4709.144, -4435.14 + 0.0, 43000.0, 33.0, -4901.125, -3868.14 + 0.0, 43000.0, 33.5, -5091.531, -3210.01 + 0.0, 43000.0, 34.0, -5280.1, -2462.7 + 0.0, 43000.0, 34.5, -5443.99, -345.789 + 0.0, 43000.0, 35.0, -5607.669, 1734.26 + 0.0, 43000.0, 35.5, -5773.023, 3653.36 + 0.0, 43000.0, 36.0, -5941.94, 5287.43 + 0.0, 43000.0, 36.5, -6116.309, 6512.38 + 0.0, 43000.0, 37.0, -6298.016, 7204.14 + 0.0, 43000.0, 37.5, -6488.951, 7238.6 + 0.0, 43000.0, 38.0, -6691.0, 6491.7 + 0.0, 43000.0, 38.5, -6952.888, 3295.36 + 0.0, 43000.0, 39.0, -7205.381, -129.934 + 0.0, 43000.0, 39.5, -7439.959, -3565.16 + 0.0, 43000.0, 40.0, -7648.1, -6791.3 + 0.0, 43000.0, 40.5, -7754.102, -9171.64 + 0.0, 43000.0, 41.0, -7843.5, -11071.9 + 0.0, 43000.0, 41.5, -7934.648, -12440.2 + 0.0, 43000.0, 42.0, -8045.9, -13224.5 + 0.0, 43000.0, 42.5, -8284.354, -12790.9 + 0.0, 43000.0, 43.0, -8544.119, -11902.3 + 0.0, 43000.0, 43.5, -8808.049, -10739.4 + 0.0, 43000.0, 44.0, -9059.0, -9483.1 + 0.0, 43000.0, 44.5, -9199.263, -8634.27 + 0.0, 43000.0, 45.0, -9324.481, -7925.76 + 0.0, 43000.0, 45.5, -9449.734, -7410.42 + 0.0, 43000.0, 46.0, -9590.1, -7141.1 + 0.0, 43000.0, 46.5, -9826.434, -7604.73 + 0.0, 43000.0, 47.0, -10081.73, -8246.45 + 0.0, 43000.0, 47.5, -10344.76, -8945.5 + 0.0, 43000.0, 48.0, -10604.3, -9581.1 + 0.0, 43000.0, 48.5, -10849.11, -10032.5 + 0.0, 43000.0, 49.0, -11067.97, -10178.9 + 0.0, 43000.0, 49.5, -11249.64, -9899.45 + 0.0, 43000.0, 50.0, -11382.9, -9073.5 + 0.0, 48000.0, 0.0, 75.03536, 75.0354 + 0.0, 48000.0, 22.0, -967.1, 1139.0 + 0.0, 48000.0, 22.5, -990.8191, 419.225 + 0.0, 48000.0, 23.0, -1044.822, -168.091 + 0.0, 48000.0, 23.5, -1125.314, -641.211 + 0.0, 48000.0, 24.0, -1228.5, -1018.4 + 0.0, 48000.0, 24.5, -1350.586, -1317.92 + 0.0, 48000.0, 25.0, -1487.778, -1558.03 + 0.0, 48000.0, 25.5, -1636.281, -1757.01 + 0.0, 48000.0, 26.0, -1792.3, -1933.1 + 0.0, 48000.0, 26.5, -1925.203, -2304.21 + 0.0, 48000.0, 27.0, -2056.5, -2700.37 + 0.0, 48000.0, 27.5, -2186.997, -3105.63 + 0.0, 48000.0, 28.0, -2317.5, -3504.03 + 0.0, 48000.0, 28.5, -2448.816, -3879.6 + 0.0, 48000.0, 29.0, -2581.75, -4216.39 + 0.0, 48000.0, 29.5, -2717.109, -4498.45 + 0.0, 48000.0, 30.0, -2855.7, -4709.8 + 0.0, 48000.0, 30.5, -3015.998, -4639.3 + 0.0, 48000.0, 31.0, -3179.456, -4484.77 + 0.0, 48000.0, 31.5, -3345.199, -4248.84 + 0.0, 48000.0, 32.0, -3512.35, -3934.16 + 0.0, 48000.0, 32.5, -3680.032, -3543.34 + 0.0, 48000.0, 33.0, -3847.369, -3079.02 + 0.0, 48000.0, 33.5, -4013.484, -2543.83 + 0.0, 48000.0, 34.0, -4177.5, -1940.4 + 0.0, 48000.0, 34.5, -4306.69, -290.777 + 0.0, 48000.0, 35.0, -4435.063, 1328.43 + 0.0, 48000.0, 35.5, -4564.773, 2821.2 + 0.0, 48000.0, 36.0, -4697.98, 4091.52 + 0.0, 48000.0, 36.5, -4836.839, 5043.36 + 0.0, 48000.0, 37.0, -4983.508, 5580.7 + 0.0, 48000.0, 37.5, -5140.142, 5607.52 + 0.0, 48000.0, 38.0, -5308.9, 5027.8 + 0.0, 48000.0, 38.5, -5550.173, 2554.34 + 0.0, 48000.0, 39.0, -5777.687, -100.056 + 0.0, 48000.0, 39.5, -5980.658, -2766.7 + 0.0, 48000.0, 40.0, -6148.3, -5276.9 + 0.0, 48000.0, 40.5, -6180.447, -7148.88 + 0.0, 48000.0, 41.0, -6191.45, -8652.29 + 0.0, 48000.0, 41.5, -6206.278, -9743.68 + 0.0, 48000.0, 42.0, -6249.9, -10379.6 + 0.0, 48000.0, 42.5, -6462.066, -10058.2 + 0.0, 48000.0, 43.0, -6707.05, -9377.83 + 0.0, 48000.0, 43.5, -6963.909, -8478.36 + 0.0, 48000.0, 44.0, -7211.7, -7499.7 + 0.0, 48000.0, 44.5, -7351.791, -6818.94 + 0.0, 48000.0, 45.0, -7472.0, -6243.96 + 0.0, 48000.0, 45.5, -7582.459, -5819.79 + 0.0, 48000.0, 46.0, -7693.3, -5591.5 + 0.0, 48000.0, 46.5, -7846.118, -5963.06 + 0.0, 48000.0, 47.0, -8006.994, -6477.0 + 0.0, 48000.0, 47.5, -8173.473, -7034.79 + 0.0, 48000.0, 48.0, -8343.1, -7537.9 + 0.0, 48000.0, 48.5, -8513.421, -7887.8 + 0.0, 48000.0, 49.0, -8681.981, -7985.95 + 0.0, 48000.0, 49.5, -8846.326, -7733.83 + 0.0, 48000.0, 50.0, -9004.0, -7032.9 + 0.05, 0.0, 0.0, 517.1289, 517.129 + 0.05, 0.0, 22.0, 1838.07, 769.58 + 0.05, 0.0, 22.5, 2186.9, 844.22 + 0.05, 0.0, 23.0, 2532.125, 918.382 + 0.05, 0.0, 23.5, 2874.946, 992.441 + 0.05, 0.0, 24.0, 3216.56, 1066.77 + 0.05, 0.0, 24.5, 3558.167, 1141.75 + 0.05, 0.0, 25.0, 3900.965, 1217.74 + 0.05, 0.0, 25.5, 4246.153, 1295.14 + 0.05, 0.0, 26.0, 4594.93, 1374.3 + 0.05, 0.0, 26.5, 4961.076, 1458.67 + 0.05, 0.0, 27.0, 5333.927, 1545.73 + 0.05, 0.0, 27.5, 5712.526, 1635.34 + 0.05, 0.0, 28.0, 6095.914, 1727.34 + 0.05, 0.0, 28.5, 6483.133, 1821.6 + 0.05, 0.0, 29.0, 6873.226, 1917.95 + 0.05, 0.0, 29.5, 7265.234, 2016.26 + 0.05, 0.0, 30.0, 7658.2, 2116.37 + 0.05, 0.0, 30.5, 8041.105, 2217.63 + 0.05, 0.0, 31.0, 8424.009, 2320.45 + 0.05, 0.0, 31.5, 8806.913, 2424.71 + 0.05, 0.0, 32.0, 9189.816, 2530.33 + 0.05, 0.0, 32.5, 9572.72, 2637.19 + 0.05, 0.0, 33.0, 9955.623, 2745.2 + 0.05, 0.0, 33.5, 10338.53, 2854.25 + 0.05, 0.0, 34.0, 10721.43, 2964.25 + 0.05, 0.0, 34.5, 11104.33, 3075.18 + 0.05, 0.0, 35.0, 11487.23, 3186.83 + 0.05, 0.0, 35.5, 11870.13, 3299.12 + 0.05, 0.0, 36.0, 12253.04, 3411.91 + 0.05, 0.0, 36.5, 12635.95, 3525.11 + 0.05, 0.0, 37.0, 13018.85, 3638.6 + 0.05, 0.0, 37.5, 13401.77, 3752.28 + 0.05, 0.0, 38.0, 13784.68, 3866.03 + 0.05, 0.0, 38.5, 14167.6, 3979.67 + 0.05, 0.0, 39.0, 14550.53, 4093.21 + 0.05, 0.0, 39.5, 14933.45, 4206.55 + 0.05, 0.0, 40.0, 15316.38, 4319.59 + 0.05, 0.0, 40.5, 15699.31, 4431.82 + 0.05, 0.0, 41.0, 16082.23, 4543.74 + 0.05, 0.0, 41.5, 16465.15, 4655.42 + 0.05, 0.0, 42.0, 16848.06, 4766.94 + 0.05, 0.0, 42.5, 17230.66, 4878.42 + 0.05, 0.0, 43.0, 17613.36, 4989.87 + 0.05, 0.0, 43.5, 17996.31, 5101.34 + 0.05, 0.0, 44.0, 18379.61, 5212.91 + 0.05, 0.0, 44.5, 18764.59, 5325.12 + 0.05, 0.0, 45.0, 19149.68, 5437.34 + 0.05, 0.0, 45.5, 19534.55, 5549.42 + 0.05, 0.0, 46.0, 19918.82, 5661.22 + 0.05, 0.0, 46.5, 20300.36, 5771.53 + 0.05, 0.0, 47.0, 20681.32, 5881.7 + 0.05, 0.0, 47.5, 21062.03, 5992.02 + 0.05, 0.0, 48.0, 21442.86, 6102.79 + 0.05, 0.0, 48.5, 21824.16, 6214.29 + 0.05, 0.0, 49.0, 22206.29, 6326.8 + 0.05, 0.0, 49.5, 22589.61, 6440.61 + 0.05, 0.0, 50.0, 22974.46, 6556.02 + 0.05, 2000.0, 0.0, 484.1721, 484.172 + 0.05, 2000.0, 22.0, 1788.26, 733.03 + 0.05, 2000.0, 22.5, 2127.651, 806.051 + 0.05, 2000.0, 23.0, 2463.546, 878.37 + 0.05, 2000.0, 23.5, 2797.111, 950.396 + 0.05, 2000.0, 24.0, 3129.51, 1022.54 + 0.05, 2000.0, 24.5, 3461.908, 1095.21 + 0.05, 2000.0, 25.0, 3795.469, 1168.82 + 0.05, 2000.0, 25.5, 4131.358, 1243.77 + 0.05, 2000.0, 26.0, 4470.74, 1320.48 + 0.05, 2000.0, 26.5, 4827.007, 1402.64 + 0.05, 2000.0, 27.0, 5189.794, 1487.57 + 0.05, 2000.0, 27.5, 5558.17, 1575.1 + 0.05, 2000.0, 28.0, 5931.203, 1665.09 + 0.05, 2000.0, 28.5, 6307.962, 1757.38 + 0.05, 2000.0, 29.0, 6687.516, 1851.81 + 0.05, 2000.0, 29.5, 7068.932, 1948.24 + 0.05, 2000.0, 30.0, 7451.28, 2046.5 + 0.05, 2000.0, 30.5, 7823.845, 2146.26 + 0.05, 2000.0, 31.0, 8196.41, 2247.57 + 0.05, 2000.0, 31.5, 8568.975, 2350.29 + 0.05, 2000.0, 32.0, 8941.54, 2454.28 + 0.05, 2000.0, 32.5, 9314.105, 2559.41 + 0.05, 2000.0, 33.0, 9686.67, 2665.53 + 0.05, 2000.0, 33.5, 10059.23, 2772.52 + 0.05, 2000.0, 34.0, 10431.8, 2880.24 + 0.05, 2000.0, 34.5, 10804.37, 2987.66 + 0.05, 2000.0, 35.0, 11176.94, 3095.61 + 0.05, 2000.0, 35.5, 11549.5, 3204.05 + 0.05, 2000.0, 36.0, 11922.07, 3312.92 + 0.05, 2000.0, 36.5, 12294.64, 3422.18 + 0.05, 2000.0, 37.0, 12667.21, 3531.76 + 0.05, 2000.0, 37.5, 13039.77, 3641.63 + 0.05, 2000.0, 38.0, 13412.34, 3751.72 + 0.05, 2000.0, 38.5, 13784.9, 3862.96 + 0.05, 2000.0, 39.0, 14157.47, 3973.81 + 0.05, 2000.0, 39.5, 14530.03, 4084.02 + 0.05, 2000.0, 40.0, 14902.59, 4193.31 + 0.05, 2000.0, 40.5, 15275.15, 4299.41 + 0.05, 2000.0, 41.0, 15647.71, 4404.86 + 0.05, 2000.0, 41.5, 16020.26, 4510.2 + 0.05, 2000.0, 42.0, 16392.81, 4615.98 + 0.05, 2000.0, 42.5, 16765.05, 4725.21 + 0.05, 2000.0, 43.0, 17137.42, 4834.95 + 0.05, 2000.0, 43.5, 17510.02, 4944.75 + 0.05, 2000.0, 44.0, 17882.98, 5054.15 + 0.05, 2000.0, 44.5, 18257.62, 5160.73 + 0.05, 2000.0, 45.0, 18632.38, 5266.78 + 0.05, 2000.0, 45.5, 19006.9, 5372.64 + 0.05, 2000.0, 46.0, 19380.84, 5478.65 + 0.05, 2000.0, 46.5, 19752.04, 5585.82 + 0.05, 2000.0, 47.0, 20122.65, 5693.52 + 0.05, 2000.0, 47.5, 20493.03, 5801.81 + 0.05, 2000.0, 48.0, 20863.52, 5910.74 + 0.05, 2000.0, 48.5, 21234.49, 6020.37 + 0.05, 2000.0, 49.0, 21606.28, 6130.75 + 0.05, 2000.0, 49.5, 21979.27, 6241.94 + 0.05, 2000.0, 50.0, 22353.79, 6353.99 + 0.05, 5000.0, 0.0, 437.8687, 437.869 + 0.05, 5000.0, 22.0, 1697.14, 716.79 + 0.05, 5000.0, 22.5, 2019.147, 785.05 + 0.05, 5000.0, 23.0, 2337.86, 857.572 + 0.05, 5000.0, 23.5, 2654.38, 933.658 + 0.05, 5000.0, 24.0, 2969.81, 1012.61 + 0.05, 5000.0, 24.5, 3285.251, 1093.73 + 0.05, 5000.0, 25.0, 3601.805, 1176.32 + 0.05, 5000.0, 25.5, 3920.574, 1259.69 + 0.05, 5000.0, 26.0, 4242.66, 1343.13 + 0.05, 5000.0, 26.5, 4580.74, 1417.71 + 0.05, 5000.0, 27.0, 4925.001, 1490.49 + 0.05, 5000.0, 27.5, 5274.562, 1562.2 + 0.05, 5000.0, 28.0, 5628.538, 1633.55 + 0.05, 5000.0, 28.5, 5986.049, 1705.26 + 0.05, 5000.0, 29.0, 6346.212, 1778.05 + 0.05, 5000.0, 29.5, 6708.143, 1852.62 + 0.05, 5000.0, 30.0, 7070.96, 1929.7 + 0.05, 5000.0, 30.5, 7424.522, 2021.09 + 0.05, 5000.0, 31.0, 7778.088, 2115.37 + 0.05, 5000.0, 31.5, 8131.655, 2212.18 + 0.05, 5000.0, 32.0, 8485.223, 2311.2 + 0.05, 5000.0, 32.5, 8838.792, 2412.07 + 0.05, 5000.0, 33.0, 9192.359, 2514.46 + 0.05, 5000.0, 33.5, 9545.926, 2618.02 + 0.05, 5000.0, 34.0, 9899.49, 2722.42 + 0.05, 5000.0, 34.5, 10253.03, 2825.09 + 0.05, 5000.0, 35.0, 10606.57, 2928.12 + 0.05, 5000.0, 35.5, 10960.11, 3031.4 + 0.05, 5000.0, 36.0, 11313.65, 3134.78 + 0.05, 5000.0, 36.5, 11667.19, 3238.14 + 0.05, 5000.0, 37.0, 12020.73, 3341.35 + 0.05, 5000.0, 37.5, 12374.27, 3444.28 + 0.05, 5000.0, 38.0, 12727.82, 3546.8 + 0.05, 5000.0, 38.5, 13081.38, 3647.75 + 0.05, 5000.0, 39.0, 13434.94, 3748.57 + 0.05, 5000.0, 39.5, 13788.51, 3849.37 + 0.05, 5000.0, 40.0, 14142.07, 3950.24 + 0.05, 5000.0, 40.5, 14495.63, 4051.92 + 0.05, 5000.0, 41.0, 14849.19, 4153.63 + 0.05, 5000.0, 41.5, 15202.74, 4255.21 + 0.05, 5000.0, 42.0, 15556.3, 4356.52 + 0.05, 5000.0, 42.5, 15909.57, 4456.47 + 0.05, 5000.0, 43.0, 16262.96, 4556.23 + 0.05, 5000.0, 43.5, 16616.56, 4656.01 + 0.05, 5000.0, 44.0, 16970.5, 4756.04 + 0.05, 5000.0, 44.5, 17325.99, 4857.24 + 0.05, 5000.0, 45.0, 17681.59, 4958.87 + 0.05, 5000.0, 45.5, 18036.97, 5060.85 + 0.05, 5000.0, 46.0, 18391.79, 5163.14 + 0.05, 5000.0, 46.5, 18744.06, 5265.12 + 0.05, 5000.0, 47.0, 19095.78, 5367.52 + 0.05, 5000.0, 47.5, 19447.27, 5470.5 + 0.05, 5000.0, 48.0, 19798.88, 5574.23 + 0.05, 5000.0, 48.5, 20150.94, 5678.87 + 0.05, 5000.0, 49.0, 20503.78, 5784.59 + 0.05, 5000.0, 49.5, 20857.73, 5891.55 + 0.05, 5000.0, 50.0, 21213.13, 5999.92 + 0.05, 10000.0, 0.0, 368.5291, 368.529 + 0.05, 10000.0, 22.0, 1541.45, 612.65 + 0.05, 10000.0, 22.5, 1833.668, 659.796 + 0.05, 10000.0, 23.0, 2122.954, 708.92 + 0.05, 10000.0, 23.5, 2410.3, 760.133 + 0.05, 10000.0, 24.0, 2696.7, 813.55 + 0.05, 10000.0, 24.5, 2983.147, 869.282 + 0.05, 10000.0, 25.0, 3270.634, 927.443 + 0.05, 10000.0, 25.5, 3560.154, 988.145 + 0.05, 10000.0, 26.0, 3852.7, 1051.5 + 0.05, 10000.0, 26.5, 4159.743, 1118.05 + 0.05, 10000.0, 27.0, 4472.398, 1187.5 + 0.05, 10000.0, 27.5, 4789.861, 1259.89 + 0.05, 10000.0, 28.0, 5111.33, 1335.27 + 0.05, 10000.0, 28.5, 5436.001, 1413.67 + 0.05, 10000.0, 29.0, 5763.072, 1495.13 + 0.05, 10000.0, 29.5, 6091.739, 1579.69 + 0.05, 10000.0, 30.0, 6421.2, 1667.4 + 0.05, 10000.0, 30.5, 6742.2, 1765.35 + 0.05, 10000.0, 31.0, 7063.192, 1865.85 + 0.05, 10000.0, 31.5, 7384.179, 1968.27 + 0.05, 10000.0, 32.0, 7705.162, 2071.96 + 0.05, 10000.0, 32.5, 8026.144, 2176.31 + 0.05, 10000.0, 33.0, 8347.127, 2280.67 + 0.05, 10000.0, 33.5, 8668.111, 2384.41 + 0.05, 10000.0, 34.0, 8989.1, 2486.9 + 0.05, 10000.0, 34.5, 9310.158, 2576.98 + 0.05, 10000.0, 35.0, 9631.219, 2665.55 + 0.05, 10000.0, 35.5, 9952.277, 2752.98 + 0.05, 10000.0, 36.0, 10273.33, 2839.62 + 0.05, 10000.0, 36.5, 10594.37, 2925.86 + 0.05, 10000.0, 37.0, 10915.4, 3012.05 + 0.05, 10000.0, 37.5, 11236.41, 3098.58 + 0.05, 10000.0, 38.0, 11557.4, 3185.8 + 0.05, 10000.0, 38.5, 11878.28, 3275.52 + 0.05, 10000.0, 39.0, 12199.17, 3365.94 + 0.05, 10000.0, 39.5, 12520.09, 3457.09 + 0.05, 10000.0, 40.0, 12841.05, 3549.05 + 0.05, 10000.0, 40.5, 13162.13, 3643.43 + 0.05, 10000.0, 41.0, 13483.25, 3738.08 + 0.05, 10000.0, 41.5, 13804.4, 3832.41 + 0.05, 10000.0, 42.0, 14125.55, 3925.85 + 0.05, 10000.0, 42.5, 14446.4, 4014.98 + 0.05, 10000.0, 43.0, 14767.35, 4103.18 + 0.05, 10000.0, 43.5, 15088.5, 4191.01 + 0.05, 10000.0, 44.0, 15409.95, 4279.0 + 0.05, 10000.0, 44.5, 15732.85, 4368.57 + 0.05, 10000.0, 45.0, 16055.84, 4459.07 + 0.05, 10000.0, 45.5, 16378.61, 4550.69 + 0.05, 10000.0, 46.0, 16700.85, 4643.65 + 0.05, 10000.0, 46.5, 17020.65, 4738.56 + 0.05, 10000.0, 47.0, 17339.93, 4835.04 + 0.05, 10000.0, 47.5, 17659.03, 4933.14 + 0.05, 10000.0, 48.0, 17978.25, 5032.9 + 0.05, 10000.0, 48.5, 18297.93, 5134.35 + 0.05, 10000.0, 49.0, 18618.4, 5237.53 + 0.05, 10000.0, 49.5, 18939.98, 5342.49 + 0.05, 10000.0, 50.0, 19263.0, 5449.25 + 0.05, 15000.0, 0.0, 308.1616, 308.162 + 0.05, 15000.0, 22.0, -11315.7, -3791.3 + 0.05, 15000.0, 22.5, -13464.46, -4536.63 + 0.05, 15000.0, 23.0, -15590.43, -5246.46 + 0.05, 15000.0, 23.5, -17701.06, -5929.82 + 0.05, 15000.0, 24.0, -19803.8, -6595.7 + 0.05, 15000.0, 24.5, -21906.1, -7253.13 + 0.05, 15000.0, 25.0, -24015.42, -7911.11 + 0.05, 15000.0, 25.5, -26139.2, -8578.67 + 0.05, 15000.0, 26.0, -28284.9, -9264.8 + 0.05, 15000.0, 26.5, -30537.59, -10035.3 + 0.05, 15000.0, 27.0, -32831.55, -10845.6 + 0.05, 15000.0, 27.5, -35160.9, -11695.0 + 0.05, 15000.0, 28.0, -37519.81, -12582.9 + 0.05, 15000.0, 28.5, -39902.4, -13508.5 + 0.05, 15000.0, 29.0, -42302.84, -14471.1 + 0.05, 15000.0, 29.5, -44715.25, -15469.9 + 0.05, 15000.0, 30.0, -47133.8, -16504.3 + 0.05, 15000.0, 30.5, -49491.86, -17673.6 + 0.05, 15000.0, 31.0, -51850.13, -18867.4 + 0.05, 15000.0, 31.5, -54208.53, -20075.7 + 0.05, 15000.0, 32.0, -56567.0, -21288.0 + 0.05, 15000.0, 32.5, -58925.47, -22494.3 + 0.05, 15000.0, 33.0, -61283.87, -23684.2 + 0.05, 15000.0, 33.5, -63642.14, -24847.5 + 0.05, 15000.0, 34.0, -66000.2, -25974.0 + 0.05, 15000.0, 34.5, -68355.52, -26788.0 + 0.05, 15000.0, 35.0, -70710.74, -27570.0 + 0.05, 15000.0, 35.5, -73066.01, -28335.0 + 0.05, 15000.0, 36.0, -75421.51, -29098.0 + 0.05, 15000.0, 36.5, -77777.41, -29874.1 + 0.05, 15000.0, 37.0, -80133.86, -30678.3 + 0.05, 15000.0, 37.5, -82491.03, -31525.6 + 0.05, 15000.0, 38.0, -84849.1, -32431.1 + 0.05, 15000.0, 38.5, -87210.6, -33501.6 + 0.05, 15000.0, 39.0, -89572.1, -34612.8 + 0.05, 15000.0, 39.5, -91933.22, -35759.2 + 0.05, 15000.0, 40.0, -94293.6, -36935.5 + 0.05, 15000.0, 40.5, -96651.48, -38111.1 + 0.05, 15000.0, 41.0, -99008.46, -39316.0 + 0.05, 15000.0, 41.5, -101364.7, -40554.8 + 0.05, 15000.0, 42.0, -103720.5, -41832.3 + 0.05, 15000.0, 42.5, -106074.4, -43220.8 + 0.05, 15000.0, 43.0, -108428.7, -44630.4 + 0.05, 15000.0, 43.5, -110784.5, -46038.8 + 0.05, 15000.0, 44.0, -113142.5, -47423.7 + 0.05, 15000.0, 44.5, -115511.7, -48628.8 + 0.05, 15000.0, 45.0, -117881.5, -49819.5 + 0.05, 15000.0, 45.5, -120249.6, -51027.0 + 0.05, 15000.0, 46.0, -122613.5, -52282.7 + 0.05, 15000.0, 46.5, -124958.2, -53706.7 + 0.05, 15000.0, 47.0, -127299.0, -55206.0 + 0.05, 15000.0, 47.5, -129638.5, -56776.4 + 0.05, 15000.0, 48.0, -131979.4, -58413.7 + 0.05, 15000.0, 48.5, -134324.3, -60113.7 + 0.05, 15000.0, 49.0, -136675.9, -61872.3 + 0.05, 15000.0, 49.5, -139036.9, -63685.2 + 0.05, 15000.0, 50.0, -141409.8, -65548.2 + 0.05, 20000.0, 0.0, 255.8882, 255.888 + 0.05, 20000.0, 22.0, 891.4, 224.3 + 0.05, 20000.0, 22.5, 1078.256, 552.39 + 0.05, 20000.0, 23.0, 1259.028, 746.495 + 0.05, 20000.0, 23.5, 1434.986, 826.953 + 0.05, 20000.0, 24.0, 1607.4, 814.1 + 0.05, 20000.0, 24.5, 1777.539, 728.272 + 0.05, 20000.0, 25.0, 1946.672, 589.805 + 0.05, 20000.0, 25.5, 2116.069, 419.035 + 0.05, 20000.0, 26.0, 2287.0, 236.3 + 0.05, 20000.0, 26.5, 2473.385, 214.062 + 0.05, 20000.0, 27.0, 2664.565, 229.223 + 0.05, 20000.0, 27.5, 2859.641, 276.042 + 0.05, 20000.0, 28.0, 3057.715, 348.775 + 0.05, 20000.0, 28.5, 3257.887, 441.68 + 0.05, 20000.0, 29.0, 3459.258, 549.014 + 0.05, 20000.0, 29.5, 3660.929, 665.035 + 0.05, 20000.0, 30.0, 3862.0, 784.0 + 0.05, 20000.0, 30.5, 4047.953, 816.482 + 0.05, 20000.0, 31.0, 4232.805, 848.394 + 0.05, 20000.0, 31.5, 4416.954, 881.961 + 0.05, 20000.0, 32.0, 4600.8, 919.412 + 0.05, 20000.0, 32.5, 4784.739, 962.975 + 0.05, 20000.0, 33.0, 4969.17, 1014.87 + 0.05, 20000.0, 33.5, 5154.491, 1077.34 + 0.05, 20000.0, 34.0, 5341.1, 1152.6 + 0.05, 20000.0, 34.5, 5540.528, 1406.27 + 0.05, 20000.0, 35.0, 5740.98, 1661.62 + 0.05, 20000.0, 35.5, 5941.793, 1905.33 + 0.05, 20000.0, 36.0, 6142.305, 2124.05 + 0.05, 20000.0, 36.5, 6341.854, 2304.47 + 0.05, 20000.0, 37.0, 6539.778, 2433.24 + 0.05, 20000.0, 37.5, 6735.414, 2497.03 + 0.05, 20000.0, 38.0, 6928.1, 2482.5 + 0.05, 20000.0, 38.5, 7110.23, 2187.35 + 0.05, 20000.0, 39.0, 7291.686, 1885.2 + 0.05, 20000.0, 39.5, 7473.349, 1604.73 + 0.05, 20000.0, 40.0, 7656.1, 1374.6 + 0.05, 20000.0, 40.5, 7844.389, 1318.99 + 0.05, 20000.0, 41.0, 8034.1, 1332.84 + 0.05, 20000.0, 41.5, 8224.686, 1406.59 + 0.05, 20000.0, 42.0, 8415.6, 1530.7 + 0.05, 20000.0, 42.5, 8605.287, 1685.54 + 0.05, 20000.0, 43.0, 8794.612, 1875.68 + 0.05, 20000.0, 43.5, 8983.431, 2095.61 + 0.05, 20000.0, 44.0, 9171.6, 2339.8 + 0.05, 20000.0, 44.5, 9356.088, 2625.06 + 0.05, 20000.0, 45.0, 9540.794, 2914.63 + 0.05, 20000.0, 45.5, 9726.727, 3194.09 + 0.05, 20000.0, 46.0, 9914.9, 3449.0 + 0.05, 20000.0, 46.5, 10111.95, 3619.03 + 0.05, 20000.0, 47.0, 10311.01, 3753.99 + 0.05, 20000.0, 47.5, 10510.84, 3857.81 + 0.05, 20000.0, 48.0, 10710.2, 3934.4 + 0.05, 20000.0, 48.5, 10907.86, 3987.68 + 0.05, 20000.0, 49.0, 11102.57, 4021.58 + 0.05, 20000.0, 49.5, 11293.1, 4040.01 + 0.05, 20000.0, 50.0, 11478.2, 4046.9 + 0.05, 25000.0, 0.0, 210.8812, 210.881 + 0.05, 25000.0, 22.0, 421.7, 590.7 + 0.05, 25000.0, 22.5, 524.0678, 5.51406 + 0.05, 25000.0, 23.0, 620.4328, -311.125 + 0.05, 25000.0, 23.5, 711.8814, -401.577 + 0.05, 25000.0, 24.0, 799.5, -308.2 + 0.05, 25000.0, 24.5, 884.3748, -73.3547 + 0.05, 25000.0, 25.0, 967.5922, 260.6 + 0.05, 25000.0, 25.5, 1050.238, 651.305 + 0.05, 25000.0, 26.0, 1133.4, 1056.4 + 0.05, 25000.0, 26.5, 1228.372, 1083.21 + 0.05, 25000.0, 27.0, 1326.615, 1019.67 + 0.05, 25000.0, 27.5, 1427.466, 883.476 + 0.05, 25000.0, 28.0, 1530.26, 692.33 + 0.05, 25000.0, 28.5, 1634.334, 463.924 + 0.05, 25000.0, 29.0, 1739.025, 215.953 + 0.05, 25000.0, 29.5, 1843.668, -33.8866 + 0.05, 25000.0, 30.0, 1947.6, -267.9 + 0.05, 25000.0, 30.5, 2040.478, -219.731 + 0.05, 25000.0, 31.0, 2132.24, -144.026 + 0.05, 25000.0, 31.5, 2223.142, -46.7722 + 0.05, 25000.0, 32.0, 2313.444, 66.0438 + 0.05, 25000.0, 32.5, 2403.402, 188.435 + 0.05, 25000.0, 33.0, 2493.276, 314.416 + 0.05, 25000.0, 33.5, 2583.322, 438.0 + 0.05, 25000.0, 34.0, 2673.8, 553.2 + 0.05, 25000.0, 34.5, 2770.208, 414.214 + 0.05, 25000.0, 35.0, 2867.064, 277.711 + 0.05, 25000.0, 35.5, 2964.127, 160.544 + 0.05, 25000.0, 36.0, 3061.155, 79.565 + 0.05, 25000.0, 36.5, 3157.908, 51.6283 + 0.05, 25000.0, 37.0, 3254.143, 93.5866 + 0.05, 25000.0, 37.5, 3349.621, 222.293 + 0.05, 25000.0, 38.0, 3444.1, 454.6 + 0.05, 25000.0, 38.5, 3531.702, 1194.48 + 0.05, 25000.0, 39.0, 3620.745, 1870.93 + 0.05, 25000.0, 39.5, 3712.241, 2414.8 + 0.05, 25000.0, 40.0, 3807.2, 2756.9 + 0.05, 25000.0, 40.5, 3915.659, 2460.45 + 0.05, 25000.0, 41.0, 4025.994, 1970.93 + 0.05, 25000.0, 41.5, 4135.607, 1366.22 + 0.05, 25000.0, 42.0, 4241.9, 724.2 + 0.05, 25000.0, 42.5, 4327.337, 283.47 + 0.05, 25000.0, 43.0, 4410.231, -103.125 + 0.05, 25000.0, 43.5, 4493.96, -422.008 + 0.05, 25000.0, 44.0, 4581.9, -659.6 + 0.05, 25000.0, 44.5, 4696.744, -716.855 + 0.05, 25000.0, 45.0, 4814.825, -699.85 + 0.05, 25000.0, 45.5, 4931.794, -629.195 + 0.05, 25000.0, 46.0, 5043.3, -525.5 + 0.05, 25000.0, 46.5, 5124.443, -529.67 + 0.05, 25000.0, 47.0, 5199.644, -493.9 + 0.05, 25000.0, 47.5, 5272.773, -390.68 + 0.05, 25000.0, 48.0, 5347.7, -192.5 + 0.05, 25000.0, 48.5, 5428.296, 128.148 + 0.05, 25000.0, 49.0, 5518.431, 598.775 + 0.05, 25000.0, 49.5, 5621.976, 1246.89 + 0.05, 25000.0, 50.0, 5742.8, 2100.0 + 0.05, 30000.0, 0.0, 172.3707, 172.371 + 0.05, 30000.0, 22.0, -125.1, -48.1 + 0.05, 30000.0, 22.5, -157.2557, 175.436 + 0.05, 30000.0, 23.0, -185.9172, 243.361 + 0.05, 30000.0, 23.5, -211.5201, 183.405 + 0.05, 30000.0, 24.0, -234.5, 23.3 + 0.05, 30000.0, 24.5, -255.2924, -209.224 + 0.05, 30000.0, 25.0, -274.3328, -486.436 + 0.05, 30000.0, 25.5, -292.0568, -780.605 + 0.05, 30000.0, 26.0, -308.9, -1064.0 + 0.05, 30000.0, 26.5, -327.2652, -1034.32 + 0.05, 30000.0, 27.0, -345.7331, -922.708 + 0.05, 30000.0, 27.5, -364.402, -748.513 + 0.05, 30000.0, 28.0, -383.37, -531.07 + 0.05, 30000.0, 28.5, -402.7355, -289.718 + 0.05, 30000.0, 29.0, -422.5969, -43.7969 + 0.05, 30000.0, 29.5, -443.0523, 187.356 + 0.05, 30000.0, 30.0, -464.2, 384.4 + 0.05, 30000.0, 30.5, -488.6592, 220.126 + 0.05, 30000.0, 31.0, -513.7672, 12.3867 + 0.05, 30000.0, 31.5, -539.3822, -228.835 + 0.05, 30000.0, 32.0, -565.3625, -493.556 + 0.05, 30000.0, 32.5, -591.5662, -771.796 + 0.05, 30000.0, 33.0, -617.8516, -1053.57 + 0.05, 30000.0, 33.5, -644.0768, -1328.9 + 0.05, 30000.0, 34.0, -670.1, -1587.8 + 0.05, 30000.0, 34.5, -688.3384, -1728.76 + 0.05, 30000.0, 35.0, -706.8, -1842.05 + 0.05, 30000.0, 35.5, -726.0516, -1926.4 + 0.05, 30000.0, 36.0, -746.66, -1980.53 + 0.05, 30000.0, 36.5, -769.1922, -2003.2 + 0.05, 30000.0, 37.0, -794.215, -1993.13 + 0.05, 30000.0, 37.5, -822.2953, -1949.05 + 0.05, 30000.0, 38.0, -854.0, -1869.7 + 0.05, 30000.0, 38.5, -904.3895, -1630.43 + 0.05, 30000.0, 39.0, -952.0219, -1417.33 + 0.05, 30000.0, 39.5, -994.2434, -1256.57 + 0.05, 30000.0, 40.0, -1028.4, -1174.3 + 0.05, 30000.0, 40.5, -1034.594, -1320.03 + 0.05, 30000.0, 41.0, -1034.313, -1547.22 + 0.05, 30000.0, 41.5, -1031.8, -1832.67 + 0.05, 30000.0, 42.0, -1031.3, -2153.2 + 0.05, 30000.0, 42.5, -1049.47, -2645.96 + 0.05, 30000.0, 43.0, -1073.175, -3063.27 + 0.05, 30000.0, 43.5, -1101.692, -3317.83 + 0.05, 30000.0, 44.0, -1134.3, -3322.3 + 0.05, 30000.0, 44.5, -1171.999, -2387.24 + 0.05, 30000.0, 45.0, -1211.656, -1268.29 + 0.05, 30000.0, 45.5, -1251.86, -118.967 + 0.05, 30000.0, 46.0, -1291.2, 907.2 + 0.05, 30000.0, 46.5, -1325.722, 1229.32 + 0.05, 30000.0, 47.0, -1357.575, 1292.19 + 0.05, 30000.0, 47.5, -1386.366, 1113.24 + 0.05, 30000.0, 48.0, -1411.7, 709.9 + 0.05, 30000.0, 48.5, -1433.184, 99.5867 + 0.05, 30000.0, 49.0, -1450.425, -700.269 + 0.05, 30000.0, 49.5, -1463.028, -1672.24 + 0.05, 30000.0, 50.0, -1470.6, -2798.9 + 0.05, 35000.0, 0.0, 139.6398, 139.64 + 0.05, 35000.0, 22.0, 918.5, -52.0 + 0.05, 35000.0, 22.5, 1130.548, -123.686 + 0.05, 35000.0, 23.0, 1331.119, -88.0125 + 0.05, 35000.0, 23.5, 1521.98, 34.4922 + 0.05, 35000.0, 24.0, 1704.9, 223.3 + 0.05, 35000.0, 24.5, 1881.645, 457.883 + 0.05, 35000.0, 25.0, 2053.981, 717.713 + 0.05, 35000.0, 25.5, 2223.677, 982.261 + 0.05, 35000.0, 26.0, 2392.5, 1231.0 + 0.05, 35000.0, 26.5, 2574.017, 1227.99 + 0.05, 35000.0, 27.0, 2758.868, 1155.8 + 0.05, 35000.0, 27.5, 2946.8, 1030.84 + 0.05, 35000.0, 28.0, 3137.555, 869.5 + 0.05, 35000.0, 28.5, 3330.878, 688.188 + 0.05, 35000.0, 29.0, 3526.514, 503.3 + 0.05, 35000.0, 29.5, 3724.207, 331.238 + 0.05, 35000.0, 30.0, 3923.7, 188.4 + 0.05, 35000.0, 30.5, 4125.95, 411.78 + 0.05, 35000.0, 31.0, 4329.375, 666.652 + 0.05, 35000.0, 31.5, 4533.603, 938.884 + 0.05, 35000.0, 32.0, 4738.263, 1214.34 + 0.05, 35000.0, 32.5, 4942.983, 1478.9 + 0.05, 35000.0, 33.0, 5147.394, 1718.41 + 0.05, 35000.0, 33.5, 5351.123, 1918.76 + 0.05, 35000.0, 34.0, 5553.8, 2065.8 + 0.05, 35000.0, 34.5, 5736.834, 1764.06 + 0.05, 35000.0, 35.0, 5919.808, 1417.08 + 0.05, 35000.0, 35.5, 6104.087, 1047.03 + 0.05, 35000.0, 36.0, 6291.035, 676.095 + 0.05, 35000.0, 36.5, 6482.016, 326.472 + 0.05, 35000.0, 37.0, 6678.395, 20.3409 + 0.05, 35000.0, 37.5, 6881.535, -220.112 + 0.05, 35000.0, 38.0, 7092.8, -372.7 + 0.05, 35000.0, 38.5, 7339.271, -600.601 + 0.05, 35000.0, 39.0, 7583.261, -600.153 + 0.05, 35000.0, 39.5, 7820.421, -307.979 + 0.05, 35000.0, 40.0, 8046.4, 339.3 + 0.05, 35000.0, 40.5, 8231.234, 2074.28 + 0.05, 35000.0, 41.0, 8406.431, 4023.42 + 0.05, 35000.0, 41.5, 8577.888, 5982.44 + 0.05, 35000.0, 42.0, 8751.5, 7747.0 + 0.05, 35000.0, 42.5, 8957.9, 8685.92 + 0.05, 35000.0, 43.0, 9168.35, 9192.52 + 0.05, 35000.0, 43.5, 9378.85, 9233.27 + 0.05, 35000.0, 44.0, 9585.4, 8774.6 + 0.05, 35000.0, 44.5, 9762.242, 7046.15 + 0.05, 35000.0, 45.0, 9935.838, 5045.91 + 0.05, 35000.0, 45.5, 10110.89, 3035.03 + 0.05, 35000.0, 46.0, 10292.1, 1274.7 + 0.05, 35000.0, 46.5, 10506.78, 959.268 + 0.05, 35000.0, 47.0, 10727.98, 1043.44 + 0.05, 35000.0, 47.5, 10951.37, 1415.12 + 0.05, 35000.0, 48.0, 11172.6, 1962.2 + 0.05, 35000.0, 48.5, 11387.34, 2572.57 + 0.05, 35000.0, 49.0, 11591.24, 3134.13 + 0.05, 35000.0, 49.5, 11779.98, 3534.78 + 0.05, 35000.0, 50.0, 11949.2, 3662.4 + 0.05, 39000.0, 0.0, 115.8188, 115.819 + 0.05, 39000.0, 22.0, 614.2, -362.3 + 0.05, 39000.0, 22.5, 768.4713, -583.372 + 0.05, 39000.0, 23.0, 909.1047, -613.963 + 0.05, 39000.0, 23.5, 1038.561, -487.697 + 0.05, 39000.0, 24.0, 1159.3, -238.2 + 0.05, 39000.0, 24.5, 1273.783, 100.903 + 0.05, 39000.0, 25.0, 1384.47, 495.987 + 0.05, 39000.0, 25.5, 1493.822, 913.428 + 0.05, 39000.0, 26.0, 1604.3, 1319.6 + 0.05, 39000.0, 26.5, 1741.358, 1388.43 + 0.05, 39000.0, 27.0, 1885.777, 1362.02 + 0.05, 39000.0, 27.5, 2036.075, 1256.9 + 0.05, 39000.0, 28.0, 2190.77, 1089.57 + 0.05, 39000.0, 28.5, 2348.382, 876.528 + 0.05, 39000.0, 29.0, 2507.428, 634.298 + 0.05, 39000.0, 29.5, 2666.428, 379.386 + 0.05, 39000.0, 30.0, 2823.9, 128.3 + 0.05, 39000.0, 30.5, 2955.655, 104.087 + 0.05, 39000.0, 31.0, 3085.081, 97.0492 + 0.05, 39000.0, 31.5, 3212.861, 104.026 + 0.05, 39000.0, 32.0, 3339.675, 121.856 + 0.05, 39000.0, 32.5, 3466.205, 147.38 + 0.05, 39000.0, 33.0, 3593.131, 177.435 + 0.05, 39000.0, 33.5, 3721.136, 208.862 + 0.05, 39000.0, 34.0, 3850.9, 238.5 + 0.05, 39000.0, 34.5, 4002.981, 333.11 + 0.05, 39000.0, 35.0, 4156.291, 412.95 + 0.05, 39000.0, 35.5, 4309.618, 468.2 + 0.05, 39000.0, 36.0, 4461.75, 489.04 + 0.05, 39000.0, 36.5, 4611.476, 465.65 + 0.05, 39000.0, 37.0, 4757.584, 388.21 + 0.05, 39000.0, 37.5, 4898.863, 246.9 + 0.05, 39000.0, 38.0, 5034.1, 31.9 + 0.05, 39000.0, 38.5, 5142.477, -604.481 + 0.05, 39000.0, 39.0, 5252.556, -1159.0 + 0.05, 39000.0, 39.5, 5367.482, -1566.39 + 0.05, 39000.0, 40.0, 5490.4, -1761.4 + 0.05, 39000.0, 40.5, 5641.213, -1475.34 + 0.05, 39000.0, 41.0, 5799.606, -927.731 + 0.05, 39000.0, 41.5, 5962.021, -134.684 + 0.05, 39000.0, 42.0, 6124.9, 887.7 + 0.05, 39000.0, 42.5, 6263.193, 2404.4 + 0.05, 39000.0, 43.0, 6403.431, 4005.8 + 0.05, 39000.0, 43.5, 6550.654, 5563.35 + 0.05, 39000.0, 44.0, 6709.9, 6948.5 + 0.05, 39000.0, 44.5, 6936.38, 7846.84 + 0.05, 39000.0, 45.0, 7164.894, 8390.06 + 0.05, 39000.0, 45.5, 7380.41, 8523.97 + 0.05, 39000.0, 46.0, 7567.9, 8194.4 + 0.05, 39000.0, 46.5, 7626.877, 6722.72 + 0.05, 39000.0, 47.0, 7661.95, 4928.95 + 0.05, 39000.0, 47.5, 7692.273, 3008.68 + 0.05, 39000.0, 48.0, 7737.0, 1157.5 + 0.05, 39000.0, 48.5, 7815.283, -429.006 + 0.05, 39000.0, 49.0, 7946.275, -1555.25 + 0.05, 39000.0, 49.5, 8149.13, -2025.64 + 0.05, 39000.0, 50.0, 8443.0, -1644.6 + 0.05, 43000.0, 0.0, 95.56189, 95.5619 + 0.05, 43000.0, 22.0, -818.9, 1149.3 + 0.05, 43000.0, 22.5, -903.8055, 422.449 + 0.05, 43000.0, 23.0, -994.7313, -179.117 + 0.05, 43000.0, 23.5, -1091.566, -671.85 + 0.05, 43000.0, 24.0, -1194.2, -1072.2 + 0.05, 43000.0, 24.5, -1302.521, -1396.62 + 0.05, 43000.0, 25.0, -1416.419, -1661.56 + 0.05, 43000.0, 25.5, -1535.782, -1883.47 + 0.05, 43000.0, 26.0, -1660.5, -2078.8 + 0.05, 43000.0, 26.5, -1794.273, -2443.7 + 0.05, 43000.0, 27.0, -1933.398, -2825.19 + 0.05, 43000.0, 27.5, -2077.108, -3208.92 + 0.05, 43000.0, 28.0, -2224.64, -3580.54 + 0.05, 43000.0, 28.5, -2375.23, -3925.68 + 0.05, 43000.0, 29.0, -2528.112, -4230.01 + 0.05, 43000.0, 29.5, -2682.524, -4479.17 + 0.05, 43000.0, 30.0, -2837.7, -4658.8 + 0.05, 43000.0, 30.5, -2987.116, -4586.45 + 0.05, 43000.0, 31.0, -3136.316, -4431.87 + 0.05, 43000.0, 31.5, -3285.085, -4196.73 + 0.05, 43000.0, 32.0, -3433.206, -3882.68 + 0.05, 43000.0, 32.5, -3580.464, -3491.37 + 0.05, 43000.0, 33.0, -3726.643, -3024.47 + 0.05, 43000.0, 33.5, -3871.527, -2483.63 + 0.05, 43000.0, 34.0, -4014.9, -1870.5 + 0.05, 43000.0, 34.5, -4138.039, -140.55 + 0.05, 43000.0, 35.0, -4260.998, 1558.73 + 0.05, 43000.0, 35.5, -4385.325, 3126.05 + 0.05, 43000.0, 36.0, -4512.565, 4460.11 + 0.05, 43000.0, 36.5, -4644.266, 5459.63 + 0.05, 43000.0, 37.0, -4781.974, 6023.29 + 0.05, 43000.0, 37.5, -4927.237, 6049.81 + 0.05, 43000.0, 38.0, -5081.6, 5437.9 + 0.05, 43000.0, 38.5, -5284.947, 2824.26 + 0.05, 43000.0, 39.0, -5480.611, 23.9688 + 0.05, 43000.0, 39.5, -5661.619, -2783.84 + 0.05, 43000.0, 40.0, -5821.0, -5420.0 + 0.05, 43000.0, 40.5, -5896.823, -7364.43 + 0.05, 43000.0, 41.0, -5959.056, -8915.31 + 0.05, 43000.0, 41.5, -6022.712, -10029.9 + 0.05, 43000.0, 42.0, -6102.8, -10665.3 + 0.05, 43000.0, 42.5, -6286.891, -10301.0 + 0.05, 43000.0, 43.0, -6488.413, -9563.16 + 0.05, 43000.0, 43.5, -6693.353, -8600.28 + 0.05, 43000.0, 44.0, -6887.7, -7560.7 + 0.05, 43000.0, 44.5, -6991.609, -6855.82 + 0.05, 43000.0, 45.0, -7083.231, -6265.84 + 0.05, 43000.0, 45.5, -7174.888, -5833.97 + 0.05, 43000.0, 46.0, -7278.9, -5603.4 + 0.05, 43000.0, 46.5, -7461.317, -5971.08 + 0.05, 43000.0, 47.0, -7659.238, -6484.96 + 0.05, 43000.0, 47.5, -7863.489, -7046.74 + 0.05, 43000.0, 48.0, -8064.9, -7558.1 + 0.05, 43000.0, 48.5, -8254.298, -7920.75 + 0.05, 43000.0, 49.0, -8422.513, -8036.39 + 0.05, 43000.0, 49.5, -8560.37, -7806.7 + 0.05, 43000.0, 50.0, -8658.7, -7133.4 + 0.05, 48000.0, 0.0, 75.14797, 75.148 + 0.05, 48000.0, 22.0, -749.5, 969.0 + 0.05, 48000.0, 22.5, -761.2676, 379.624 + 0.05, 48000.0, 23.0, -797.8594, -100.445 + 0.05, 48000.0, 23.5, -856.1465, -486.242 + 0.05, 48000.0, 24.0, -933.0, -792.8 + 0.05, 48000.0, 24.5, -1025.291, -1035.15 + 0.05, 48000.0, 25.0, -1129.891, -1228.33 + 0.05, 48000.0, 25.5, -1243.67, -1387.37 + 0.05, 48000.0, 26.0, -1363.5, -1527.3 + 0.05, 48000.0, 26.5, -1464.008, -1826.69 + 0.05, 48000.0, 27.0, -1563.038, -2146.39 + 0.05, 48000.0, 27.5, -1661.273, -2473.4 + 0.05, 48000.0, 28.0, -1759.4, -2794.7 + 0.05, 48000.0, 28.5, -1858.102, -3097.3 + 0.05, 48000.0, 29.0, -1958.063, -3368.21 + 0.05, 48000.0, 29.5, -2059.967, -3594.41 + 0.05, 48000.0, 30.0, -2164.5, -3762.9 + 0.05, 48000.0, 30.5, -2287.078, -3701.04 + 0.05, 48000.0, 31.0, -2412.25, -3570.68 + 0.05, 48000.0, 31.5, -2539.297, -3374.02 + 0.05, 48000.0, 32.0, -2667.5, -3113.26 + 0.05, 48000.0, 32.5, -2796.141, -2790.6 + 0.05, 48000.0, 33.0, -2924.5, -2408.26 + 0.05, 48000.0, 33.5, -3051.859, -1968.42 + 0.05, 48000.0, 34.0, -3177.5, -1473.3 + 0.05, 48000.0, 34.5, -3274.643, -125.241 + 0.05, 48000.0, 35.0, -3371.113, 1197.52 + 0.05, 48000.0, 35.5, -3468.67, 2416.61 + 0.05, 48000.0, 36.0, -3569.08, 3453.63 + 0.05, 48000.0, 36.5, -3674.105, 4230.23 + 0.05, 48000.0, 37.0, -3785.508, 4668.01 + 0.05, 48000.0, 37.5, -3905.052, 4688.59 + 0.05, 48000.0, 38.0, -4034.5, 4213.6 + 0.05, 48000.0, 38.5, -4223.22, 2191.07 + 0.05, 48000.0, 39.0, -4400.687, 21.0281 + 0.05, 48000.0, 39.5, -4558.086, -2158.55 + 0.05, 48000.0, 40.0, -4686.6, -4209.7 + 0.05, 48000.0, 40.5, -4704.344, -5738.93 + 0.05, 48000.0, 41.0, -4704.8, -6965.98 + 0.05, 48000.0, 41.5, -4708.381, -7855.09 + 0.05, 48000.0, 42.0, -4735.5, -8370.5 + 0.05, 48000.0, 42.5, -4900.381, -8099.93 + 0.05, 48000.0, 43.0, -5092.1, -7534.72 + 0.05, 48000.0, 43.5, -5293.544, -6789.7 + 0.05, 48000.0, 44.0, -5487.6, -5979.7 + 0.05, 48000.0, 44.5, -5593.719, -5414.62 + 0.05, 48000.0, 45.0, -5683.6, -4936.19 + 0.05, 48000.0, 45.5, -5765.506, -4581.22 + 0.05, 48000.0, 46.0, -5847.7, -4386.5 + 0.05, 48000.0, 46.5, -5964.069, -4681.36 + 0.05, 48000.0, 47.0, -6087.0, -5093.06 + 0.05, 48000.0, 47.5, -6214.506, -5541.41 + 0.05, 48000.0, 48.0, -6344.6, -5946.2 + 0.05, 48000.0, 48.5, -6475.294, -6227.22 + 0.05, 48000.0, 49.0, -6604.6, -6304.26 + 0.05, 48000.0, 49.5, -6730.531, -6097.12 + 0.05, 48000.0, 50.0, -6851.1, -5525.6 + 0.1, 0.0, 0.0, 519.4583, 519.458 + 0.1, 0.0, 22.0, 1752.4, 804.7 + 0.1, 0.0, 22.5, 2084.944, 884.718 + 0.1, 0.0, 23.0, 2414.064, 964.028 + 0.1, 0.0, 23.5, 2740.903, 1043.02 + 0.1, 0.0, 24.0, 3066.6, 1122.1 + 0.1, 0.0, 24.5, 3392.297, 1201.65 + 0.1, 0.0, 25.0, 3719.136, 1282.07 + 0.1, 0.0, 25.5, 4048.256, 1363.76 + 0.1, 0.0, 26.0, 4380.8, 1447.1 + 0.1, 0.0, 26.5, 4729.888, 1535.99 + 0.1, 0.0, 27.0, 5085.366, 1627.52 + 0.1, 0.0, 27.5, 5446.321, 1721.5 + 0.1, 0.0, 28.0, 5811.84, 1817.72 + 0.1, 0.0, 28.5, 6181.01, 1915.97 + 0.1, 0.0, 29.0, 6552.919, 2016.06 + 0.1, 0.0, 29.5, 6926.653, 2117.77 + 0.1, 0.0, 30.0, 7301.3, 2220.9 + 0.1, 0.0, 30.5, 7666.363, 2323.8 + 0.1, 0.0, 31.0, 8031.425, 2427.86 + 0.1, 0.0, 31.5, 8396.488, 2533.0 + 0.1, 0.0, 32.0, 8761.55, 2639.16 + 0.1, 0.0, 32.5, 9126.613, 2746.28 + 0.1, 0.0, 33.0, 9491.675, 2854.29 + 0.1, 0.0, 33.5, 9856.738, 2963.11 + 0.1, 0.0, 34.0, 10221.8, 3072.7 + 0.1, 0.0, 34.5, 10586.86, 3183.22 + 0.1, 0.0, 35.0, 10951.92, 3294.34 + 0.1, 0.0, 35.5, 11316.98, 3405.97 + 0.1, 0.0, 36.0, 11682.04, 3518.03 + 0.1, 0.0, 36.5, 12047.1, 3630.42 + 0.1, 0.0, 37.0, 12412.17, 3743.05 + 0.1, 0.0, 37.5, 12777.23, 3855.84 + 0.1, 0.0, 38.0, 13142.3, 3968.7 + 0.1, 0.0, 38.5, 13507.37, 4081.73 + 0.1, 0.0, 39.0, 13872.45, 4194.55 + 0.1, 0.0, 39.5, 14237.52, 4307.02 + 0.1, 0.0, 40.0, 14602.6, 4419.0 + 0.1, 0.0, 40.5, 14967.68, 4529.45 + 0.1, 0.0, 41.0, 15332.76, 4639.51 + 0.1, 0.0, 41.5, 15697.83, 4749.41 + 0.1, 0.0, 42.0, 16062.9, 4859.4 + 0.1, 0.0, 42.5, 16427.67, 4970.61 + 0.1, 0.0, 43.0, 16792.55, 5082.01 + 0.1, 0.0, 43.5, 17157.65, 5193.45 + 0.1, 0.0, 44.0, 17523.1, 5304.8 + 0.1, 0.0, 44.5, 17890.14, 5415.53 + 0.1, 0.0, 45.0, 18257.3, 5526.08 + 0.1, 0.0, 45.5, 18624.23, 5636.45 + 0.1, 0.0, 46.0, 18990.6, 5746.7 + 0.1, 0.0, 46.5, 19354.36, 5856.34 + 0.1, 0.0, 47.0, 19717.56, 5966.11 + 0.1, 0.0, 47.5, 20080.52, 6076.22 + 0.1, 0.0, 48.0, 20443.6, 6186.9 + 0.1, 0.0, 48.5, 20807.13, 6298.38 + 0.1, 0.0, 49.0, 21171.44, 6410.89 + 0.1, 0.0, 49.5, 21536.89, 6524.66 + 0.1, 0.0, 50.0, 21903.8, 6639.9 + 0.1, 2000.0, 0.0, 486.3531, 486.353 + 0.1, 2000.0, 22.0, 1691.4, 763.7 + 0.1, 2000.0, 22.5, 2012.404, 841.423 + 0.1, 2000.0, 23.0, 2330.105, 918.142 + 0.1, 2000.0, 23.5, 2645.603, 994.29 + 0.1, 2000.0, 24.0, 2960.0, 1070.3 + 0.1, 2000.0, 24.5, 3274.397, 1146.6 + 0.1, 2000.0, 25.0, 3589.895, 1223.63 + 0.1, 2000.0, 25.5, 3907.596, 1301.82 + 0.1, 2000.0, 26.0, 4228.6, 1381.6 + 0.1, 2000.0, 26.5, 4565.571, 1467.12 + 0.1, 2000.0, 27.0, 4908.709, 1555.31 + 0.1, 2000.0, 27.5, 5257.132, 1645.96 + 0.1, 2000.0, 28.0, 5609.96, 1738.87 + 0.1, 2000.0, 28.5, 5966.312, 1833.83 + 0.1, 2000.0, 29.0, 6325.306, 1930.64 + 0.1, 2000.0, 29.5, 6686.063, 2029.1 + 0.1, 2000.0, 30.0, 7047.7, 2129.0 + 0.1, 2000.0, 30.5, 7400.088, 2228.92 + 0.1, 2000.0, 31.0, 7752.475, 2329.99 + 0.1, 2000.0, 31.5, 8104.863, 2432.12 + 0.1, 2000.0, 32.0, 8457.25, 2535.21 + 0.1, 2000.0, 32.5, 8809.638, 2639.19 + 0.1, 2000.0, 33.0, 9162.025, 2743.95 + 0.1, 2000.0, 33.5, 9514.413, 2849.42 + 0.1, 2000.0, 34.0, 9866.8, 2955.5 + 0.1, 2000.0, 34.5, 10219.19, 3061.74 + 0.1, 2000.0, 35.0, 10571.58, 3168.44 + 0.1, 2000.0, 35.5, 10923.97, 3275.56 + 0.1, 2000.0, 36.0, 11276.36, 3383.05 + 0.1, 2000.0, 36.5, 11628.75, 3490.83 + 0.1, 2000.0, 37.0, 11981.13, 3598.88 + 0.1, 2000.0, 37.5, 12333.52, 3707.12 + 0.1, 2000.0, 38.0, 12685.9, 3815.5 + 0.1, 2000.0, 38.5, 13038.28, 3924.77 + 0.1, 2000.0, 39.0, 13390.65, 4033.66 + 0.1, 2000.0, 39.5, 13743.03, 4141.95 + 0.1, 2000.0, 40.0, 14095.4, 4249.4 + 0.1, 2000.0, 40.5, 14447.78, 4354.0 + 0.1, 2000.0, 41.0, 14800.15, 4458.02 + 0.1, 2000.0, 41.5, 15152.53, 4561.92 + 0.1, 2000.0, 42.0, 15504.9, 4666.2 + 0.1, 2000.0, 42.5, 15856.99, 4773.53 + 0.1, 2000.0, 43.0, 16209.2, 4881.3 + 0.1, 2000.0, 43.5, 16561.63, 4989.13 + 0.1, 2000.0, 44.0, 16914.4, 5096.6 + 0.1, 2000.0, 44.5, 17268.74, 5201.55 + 0.1, 2000.0, 45.0, 17623.19, 5306.06 + 0.1, 2000.0, 45.5, 17977.43, 5410.44 + 0.1, 2000.0, 46.0, 18331.1, 5515.0 + 0.1, 2000.0, 46.5, 18682.2, 5620.67 + 0.1, 2000.0, 47.0, 19032.75, 5726.89 + 0.1, 2000.0, 47.5, 19383.07, 5833.75 + 0.1, 2000.0, 48.0, 19733.5, 5941.3 + 0.1, 2000.0, 48.5, 20084.37, 6049.61 + 0.1, 2000.0, 49.0, 20436.02, 6158.76 + 0.1, 2000.0, 49.5, 20788.79, 6268.8 + 0.1, 2000.0, 50.0, 21143.0, 6379.8 + 0.1, 5000.0, 0.0, 439.8411, 439.841 + 0.1, 5000.0, 22.0, 1606.1, 706.9 + 0.1, 5000.0, 22.5, 1910.829, 780.924 + 0.1, 5000.0, 23.0, 2212.444, 853.723 + 0.1, 5000.0, 23.5, 2511.987, 925.762 + 0.1, 5000.0, 24.0, 2810.5, 997.5 + 0.1, 5000.0, 24.5, 3109.026, 1069.4 + 0.1, 5000.0, 25.0, 3408.606, 1141.93 + 0.1, 5000.0, 25.5, 3710.284, 1215.54 + 0.1, 5000.0, 26.0, 4015.1, 1290.7 + 0.1, 5000.0, 26.5, 4335.049, 1371.87 + 0.1, 5000.0, 27.0, 4660.847, 1455.75 + 0.1, 5000.0, 27.5, 4991.659, 1542.1 + 0.1, 5000.0, 28.0, 5326.65, 1630.71 + 0.1, 5000.0, 28.5, 5664.985, 1721.34 + 0.1, 5000.0, 29.0, 6005.828, 1813.79 + 0.1, 5000.0, 29.5, 6348.345, 1907.81 + 0.1, 5000.0, 30.0, 6691.7, 2003.2 + 0.1, 5000.0, 30.5, 7026.297, 2098.27 + 0.1, 5000.0, 31.0, 7360.897, 2194.4 + 0.1, 5000.0, 31.5, 7695.498, 2291.49 + 0.1, 5000.0, 32.0, 8030.1, 2389.46 + 0.1, 5000.0, 32.5, 8364.702, 2488.22 + 0.1, 5000.0, 33.0, 8699.303, 2587.69 + 0.1, 5000.0, 33.5, 9033.903, 2687.77 + 0.1, 5000.0, 34.0, 9368.5, 2788.4 + 0.1, 5000.0, 34.5, 9703.074, 2890.01 + 0.1, 5000.0, 35.0, 10037.65, 2991.94 + 0.1, 5000.0, 35.5, 10372.22, 3094.04 + 0.1, 5000.0, 36.0, 10706.79, 3196.18 + 0.1, 5000.0, 36.5, 11041.36, 3298.22 + 0.1, 5000.0, 37.0, 11375.94, 3400.03 + 0.1, 5000.0, 37.5, 11710.52, 3501.47 + 0.1, 5000.0, 38.0, 12045.1, 3602.4 + 0.1, 5000.0, 38.5, 12379.7, 3701.36 + 0.1, 5000.0, 39.0, 12714.3, 3800.23 + 0.1, 5000.0, 39.5, 13048.9, 3899.16 + 0.1, 5000.0, 40.0, 13383.5, 3998.3 + 0.1, 5000.0, 40.5, 13718.1, 4098.8 + 0.1, 5000.0, 41.0, 14052.71, 4199.44 + 0.1, 5000.0, 41.5, 14387.31, 4299.98 + 0.1, 5000.0, 42.0, 14721.9, 4400.2 + 0.1, 5000.0, 42.5, 15056.21, 4498.59 + 0.1, 5000.0, 43.0, 15390.63, 4596.69 + 0.1, 5000.0, 43.5, 15725.26, 4694.77 + 0.1, 5000.0, 44.0, 16060.2, 4793.1 + 0.1, 5000.0, 44.5, 16396.63, 4892.72 + 0.1, 5000.0, 45.0, 16733.17, 4992.83 + 0.1, 5000.0, 45.5, 17069.5, 5093.36 + 0.1, 5000.0, 46.0, 17405.3, 5194.3 + 0.1, 5000.0, 46.5, 17738.67, 5295.15 + 0.1, 5000.0, 47.0, 18071.52, 5396.5 + 0.1, 5000.0, 47.5, 18404.16, 5498.47 + 0.1, 5000.0, 48.0, 18736.9, 5601.2 + 0.1, 5000.0, 48.5, 19070.07, 5704.82 + 0.1, 5000.0, 49.0, 19403.98, 5809.48 + 0.1, 5000.0, 49.5, 19738.95, 5915.29 + 0.1, 5000.0, 50.0, 20075.3, 6022.4 + 0.1, 10000.0, 0.0, 370.1891, 370.189 + 0.1, 10000.0, 22.0, 1454.2, 619.1 + 0.1, 10000.0, 22.5, 1730.148, 684.743 + 0.1, 10000.0, 23.0, 2003.267, 749.808 + 0.1, 10000.0, 23.5, 2274.503, 814.644 + 0.1, 10000.0, 24.0, 2544.8, 879.6 + 0.1, 10000.0, 24.5, 2815.103, 945.025 + 0.1, 10000.0, 25.0, 3086.358, 1011.27 + 0.1, 10000.0, 25.5, 3359.508, 1078.68 + 0.1, 10000.0, 26.0, 3635.5, 1147.6 + 0.1, 10000.0, 26.5, 3925.203, 1221.52 + 0.1, 10000.0, 27.0, 4220.205, 1297.84 + 0.1, 10000.0, 27.5, 4519.747, 1376.36 + 0.1, 10000.0, 28.0, 4823.075, 1456.89 + 0.1, 10000.0, 28.5, 5129.431, 1539.25 + 0.1, 10000.0, 29.0, 5438.058, 1623.25 + 0.1, 10000.0, 29.5, 5748.2, 1708.69 + 0.1, 10000.0, 30.0, 6059.1, 1795.4 + 0.1, 10000.0, 30.5, 6362.061, 1882.43 + 0.1, 10000.0, 31.0, 6665.023, 1970.42 + 0.1, 10000.0, 31.5, 6967.987, 2059.24 + 0.1, 10000.0, 32.0, 7270.95, 2148.78 + 0.1, 10000.0, 32.5, 7573.913, 2238.93 + 0.1, 10000.0, 33.0, 7876.877, 2329.56 + 0.1, 10000.0, 33.5, 8179.839, 2420.55 + 0.1, 10000.0, 34.0, 8482.8, 2511.8 + 0.1, 10000.0, 34.5, 8785.753, 2602.71 + 0.1, 10000.0, 35.0, 9088.705, 2693.68 + 0.1, 10000.0, 35.5, 9391.655, 2784.64 + 0.1, 10000.0, 36.0, 9694.605, 2875.51 + 0.1, 10000.0, 36.5, 9997.554, 2966.23 + 0.1, 10000.0, 37.0, 10300.5, 3056.71 + 0.1, 10000.0, 37.5, 10603.45, 3146.9 + 0.1, 10000.0, 38.0, 10906.4, 3236.7 + 0.1, 10000.0, 38.5, 11209.35, 3325.57 + 0.1, 10000.0, 39.0, 11512.3, 3414.17 + 0.1, 10000.0, 39.5, 11815.25, 3502.53 + 0.1, 10000.0, 40.0, 12118.2, 3590.7 + 0.1, 10000.0, 40.5, 12421.15, 3678.44 + 0.1, 10000.0, 41.0, 12724.09, 3766.16 + 0.1, 10000.0, 41.5, 13027.04, 3854.0 + 0.1, 10000.0, 42.0, 13330.0, 3942.1 + 0.1, 10000.0, 42.5, 13632.74, 4030.81 + 0.1, 10000.0, 43.0, 13935.57, 4119.98 + 0.1, 10000.0, 43.5, 14238.59, 4209.66 + 0.1, 10000.0, 44.0, 14541.9, 4299.9 + 0.1, 10000.0, 44.5, 14846.52, 4390.69 + 0.1, 10000.0, 45.0, 15151.24, 4482.19 + 0.1, 10000.0, 45.5, 15455.76, 4574.46 + 0.1, 10000.0, 46.0, 15759.8, 4667.6 + 0.1, 10000.0, 46.5, 16061.65, 4761.59 + 0.1, 10000.0, 47.0, 16363.02, 4856.64 + 0.1, 10000.0, 47.5, 16664.21, 4952.87 + 0.1, 10000.0, 48.0, 16965.5, 5050.4 + 0.1, 10000.0, 48.5, 17267.17, 5149.34 + 0.1, 10000.0, 49.0, 17569.52, 5249.81 + 0.1, 10000.0, 49.5, 17872.84, 5351.92 + 0.1, 10000.0, 50.0, 18177.4, 5455.8 + 0.1, 15000.0, 0.0, 309.5497, 309.55 + 0.1, 15000.0, 22.0, -6163.5, -1999.5 + 0.1, 15000.0, 22.5, -7334.094, -2411.06 + 0.1, 15000.0, 23.0, -8492.214, -2802.79 + 0.1, 15000.0, 23.5, -9641.928, -3179.7 + 0.1, 15000.0, 24.0, -10787.3, -3546.8 + 0.1, 15000.0, 24.5, -11932.4, -3909.1 + 0.1, 15000.0, 25.0, -13081.29, -4271.61 + 0.1, 15000.0, 25.5, -14238.03, -4639.34 + 0.1, 15000.0, 26.0, -15406.7, -5017.3 + 0.1, 15000.0, 26.5, -16633.67, -5440.78 + 0.1, 15000.0, 27.0, -17883.11, -5886.25 + 0.1, 15000.0, 27.5, -19151.84, -6353.51 + 0.1, 15000.0, 28.0, -20436.66, -6842.38 + 0.1, 15000.0, 28.5, -21734.4, -7352.69 + 0.1, 15000.0, 29.0, -23041.86, -7884.25 + 0.1, 15000.0, 29.5, -24355.85, -8436.88 + 0.1, 15000.0, 30.0, -25673.2, -9010.4 + 0.1, 15000.0, 30.5, -26957.67, -9666.7 + 0.1, 15000.0, 31.0, -28242.26, -10337.6 + 0.1, 15000.0, 31.5, -29526.94, -11017.0 + 0.1, 15000.0, 32.0, -30811.65, -11698.9 + 0.1, 15000.0, 32.5, -32096.36, -12377.0 + 0.1, 15000.0, 33.0, -33381.04, -13045.5 + 0.1, 15000.0, 33.5, -34665.63, -13698.0 + 0.1, 15000.0, 34.0, -35950.1, -14328.6 + 0.1, 15000.0, 34.5, -37232.94, -14772.0 + 0.1, 15000.0, 35.0, -38515.72, -15196.4 + 0.1, 15000.0, 35.5, -39798.53, -15610.9 + 0.1, 15000.0, 36.0, -41081.48, -16024.5 + 0.1, 15000.0, 36.5, -42364.66, -16446.3 + 0.1, 15000.0, 37.0, -43648.18, -16885.4 + 0.1, 15000.0, 37.5, -44932.12, -17350.9 + 0.1, 15000.0, 38.0, -46216.6, -17851.7 + 0.1, 15000.0, 38.5, -47503.13, -18453.0 + 0.1, 15000.0, 39.0, -48789.65, -19078.8 + 0.1, 15000.0, 39.5, -50075.94, -19725.7 + 0.1, 15000.0, 40.0, -51361.8, -20390.4 + 0.1, 15000.0, 40.5, -52646.16, -21054.3 + 0.1, 15000.0, 41.0, -53929.99, -21735.3 + 0.1, 15000.0, 41.5, -55213.39, -22436.1 + 0.1, 15000.0, 42.0, -56496.5, -23159.5 + 0.1, 15000.0, 42.5, -57778.57, -23948.2 + 0.1, 15000.0, 43.0, -59060.91, -24748.9 + 0.1, 15000.0, 43.5, -60344.0, -25548.1 + 0.1, 15000.0, 44.0, -61628.3, -26332.5 + 0.1, 15000.0, 44.5, -62918.71, -27008.6 + 0.1, 15000.0, 45.0, -64209.48, -27675.4 + 0.1, 15000.0, 45.5, -65499.28, -28351.3 + 0.1, 15000.0, 46.0, -66786.8, -29055.3 + 0.1, 15000.0, 46.5, -68063.8, -29859.2 + 0.1, 15000.0, 47.0, -69338.66, -30707.1 + 0.1, 15000.0, 47.5, -70612.84, -31596.6 + 0.1, 15000.0, 48.0, -71887.8, -32525.1 + 0.1, 15000.0, 48.5, -73164.99, -33490.0 + 0.1, 15000.0, 49.0, -74445.86, -34488.6 + 0.1, 15000.0, 49.5, -75731.88, -35518.5 + 0.1, 15000.0, 50.0, -77024.5, -36577.1 + 0.1, 20000.0, 0.0, 257.0409, 257.041 + 0.1, 20000.0, 22.0, 891.4, 303.1 + 0.1, 20000.0, 22.5, 1072.526, 540.367 + 0.1, 20000.0, 23.0, 1248.989, 686.836 + 0.1, 20000.0, 23.5, 1421.832, 756.312 + 0.1, 20000.0, 24.0, 1592.1, 762.6 + 0.1, 20000.0, 24.5, 1760.837, 719.507 + 0.1, 20000.0, 25.0, 1929.086, 640.839 + 0.1, 20000.0, 25.5, 2097.892, 540.401 + 0.1, 20000.0, 26.0, 2268.3, 432.0 + 0.1, 20000.0, 26.5, 2451.865, 432.636 + 0.1, 20000.0, 27.0, 2639.721, 458.817 + 0.1, 20000.0, 27.5, 2831.108, 506.658 + 0.1, 20000.0, 28.0, 3025.27, 572.275 + 0.1, 20000.0, 28.5, 3221.448, 651.782 + 0.1, 20000.0, 29.0, 3418.884, 741.295 + 0.1, 20000.0, 29.5, 3616.821, 836.929 + 0.1, 20000.0, 30.0, 3814.5, 934.8 + 0.1, 20000.0, 30.5, 4000.366, 974.062 + 0.1, 20000.0, 31.0, 4185.487, 1013.21 + 0.1, 20000.0, 31.5, 4370.134, 1053.8 + 0.1, 20000.0, 32.0, 4554.575, 1097.36 + 0.1, 20000.0, 32.5, 4739.082, 1145.42 + 0.1, 20000.0, 33.0, 4923.925, 1199.54 + 0.1, 20000.0, 33.5, 5109.374, 1261.26 + 0.1, 20000.0, 34.0, 5295.7, 1332.1 + 0.1, 20000.0, 34.5, 5490.751, 1526.88 + 0.1, 20000.0, 35.0, 5686.497, 1723.09 + 0.1, 20000.0, 35.5, 5882.487, 1911.48 + 0.1, 20000.0, 36.0, 6078.27, 2082.79 + 0.1, 20000.0, 36.5, 6273.394, 2227.79 + 0.1, 20000.0, 37.0, 6467.408, 2337.22 + 0.1, 20000.0, 37.5, 6659.861, 2401.84 + 0.1, 20000.0, 38.0, 6850.3, 2412.4 + 0.1, 20000.0, 38.5, 7033.533, 2229.62 + 0.1, 20000.0, 39.0, 7216.309, 2041.72 + 0.1, 20000.0, 39.5, 7399.231, 1868.33 + 0.1, 20000.0, 40.0, 7582.9, 1729.1 + 0.1, 20000.0, 40.5, 7770.374, 1708.99 + 0.1, 20000.0, 41.0, 7958.819, 1736.21 + 0.1, 20000.0, 41.5, 8147.854, 1804.31 + 0.1, 20000.0, 42.0, 8337.1, 1906.8 + 0.1, 20000.0, 42.5, 8525.404, 2030.02 + 0.1, 20000.0, 43.0, 8713.469, 2177.57 + 0.1, 20000.0, 43.5, 8901.224, 2345.87 + 0.1, 20000.0, 44.0, 9088.6, 2531.3 + 0.1, 20000.0, 44.5, 9273.776, 2745.92 + 0.1, 20000.0, 45.0, 9459.131, 2964.24 + 0.1, 20000.0, 45.5, 9645.296, 3176.42 + 0.1, 20000.0, 46.0, 9832.9, 3372.6 + 0.1, 20000.0, 46.5, 10026.12, 3511.49 + 0.1, 20000.0, 47.0, 10220.62, 3627.26 + 0.1, 20000.0, 47.5, 10415.61, 3722.66 + 0.1, 20000.0, 48.0, 10610.3, 3800.4 + 0.1, 20000.0, 48.5, 10803.89, 3863.22 + 0.1, 20000.0, 49.0, 10995.6, 3913.86 + 0.1, 20000.0, 49.5, 11184.63, 3955.04 + 0.1, 20000.0, 50.0, 11370.2, 3989.5 + 0.1, 25000.0, 0.0, 211.8311, 211.831 + 0.1, 25000.0, 22.0, 509.5, 536.9 + 0.1, 25000.0, 22.5, 622.0902, 130.63 + 0.1, 25000.0, 23.0, 729.9781, -84.2188 + 0.1, 25000.0, 23.5, 834.077, -137.809 + 0.1, 25000.0, 24.0, 935.3, -60.3 + 0.1, 25000.0, 24.5, 1034.561, 118.146 + 0.1, 25000.0, 25.0, 1132.772, 367.369 + 0.1, 25000.0, 25.5, 1230.847, 657.207 + 0.1, 25000.0, 26.0, 1329.7, 957.5 + 0.1, 25000.0, 26.5, 1438.977, 988.824 + 0.1, 25000.0, 27.0, 1551.357, 956.037 + 0.1, 25000.0, 27.5, 1666.256, 871.709 + 0.1, 25000.0, 28.0, 1783.09, 748.41 + 0.1, 25000.0, 28.5, 1901.275, 598.71 + 0.1, 25000.0, 29.0, 2020.228, 435.178 + 0.1, 25000.0, 29.5, 2139.364, 270.385 + 0.1, 25000.0, 30.0, 2258.1, 116.9 + 0.1, 25000.0, 30.5, 2367.78, 163.637 + 0.1, 25000.0, 31.0, 2476.661, 230.027 + 0.1, 25000.0, 31.5, 2584.927, 311.846 + 0.1, 25000.0, 32.0, 2692.763, 404.869 + 0.1, 25000.0, 32.5, 2800.353, 504.87 + 0.1, 25000.0, 33.0, 2907.883, 607.626 + 0.1, 25000.0, 33.5, 3015.537, 708.911 + 0.1, 25000.0, 34.0, 3123.5, 804.5 + 0.1, 25000.0, 34.5, 3235.711, 720.843 + 0.1, 25000.0, 35.0, 3348.244, 639.167 + 0.1, 25000.0, 35.5, 3460.924, 571.374 + 0.1, 25000.0, 36.0, 3573.58, 529.365 + 0.1, 25000.0, 36.5, 3686.038, 525.042 + 0.1, 25000.0, 37.0, 3798.126, 570.305 + 0.1, 25000.0, 37.5, 3909.671, 677.058 + 0.1, 25000.0, 38.0, 4020.5, 857.2 + 0.1, 25000.0, 38.5, 4126.412, 1397.58 + 0.1, 25000.0, 39.0, 4233.352, 1892.59 + 0.1, 25000.0, 39.5, 4342.04, 2293.03 + 0.1, 25000.0, 40.0, 4453.2, 2549.7 + 0.1, 25000.0, 40.5, 4573.977, 2351.36 + 0.1, 25000.0, 41.0, 4696.1, 2015.67 + 0.1, 25000.0, 41.5, 4817.723, 1598.24 + 0.1, 25000.0, 42.0, 4937.0, 1154.7 + 0.1, 25000.0, 42.5, 5041.462, 855.673 + 0.1, 25000.0, 43.0, 5144.131, 595.756 + 0.1, 25000.0, 43.5, 5247.41, 384.562 + 0.1, 25000.0, 44.0, 5353.7, 231.7 + 0.1, 25000.0, 44.5, 5479.211, 207.915 + 0.1, 25000.0, 45.0, 5607.013, 237.231 + 0.1, 25000.0, 45.5, 5733.983, 304.807 + 0.1, 25000.0, 46.0, 5857.0, 395.8 + 0.1, 25000.0, 46.5, 5958.149, 409.305 + 0.1, 25000.0, 47.0, 6055.019, 450.969 + 0.1, 25000.0, 47.5, 6150.404, 540.373 + 0.1, 25000.0, 48.0, 6247.1, 697.1 + 0.1, 25000.0, 48.5, 6347.902, 940.734 + 0.1, 25000.0, 49.0, 6455.606, 1290.86 + 0.1, 25000.0, 49.5, 6573.007, 1767.05 + 0.1, 25000.0, 50.0, 6702.9, 2388.9 + 0.1, 30000.0, 0.0, 173.1471, 173.147 + 0.1, 30000.0, 22.0, 36.3, 47.7 + 0.1, 30000.0, 22.5, 36.64238, 221.647 + 0.1, 30000.0, 23.0, 39.46094, 278.384 + 0.1, 30000.0, 23.5, 44.49902, 238.854 + 0.1, 30000.0, 24.0, 51.5, 124.0 + 0.1, 30000.0, 24.5, 60.20723, -45.2355 + 0.1, 30000.0, 25.0, 70.36406, -247.909 + 0.1, 30000.0, 25.5, 81.71387, -463.079 + 0.1, 30000.0, 26.0, 94.0, -669.8 + 0.1, 30000.0, 26.5, 106.2904, -639.541 + 0.1, 30000.0, 27.0, 118.9653, -547.087 + 0.1, 30000.0, 27.5, 131.8838, -407.08 + 0.1, 30000.0, 28.0, 144.905, -234.165 + 0.1, 30000.0, 28.5, 157.8881, -42.9857 + 0.1, 30000.0, 29.0, 170.6922, 151.814 + 0.1, 30000.0, 29.5, 183.1764, 335.591 + 0.1, 30000.0, 30.0, 195.2, 493.7 + 0.1, 30000.0, 30.5, 204.015, 378.935 + 0.1, 30000.0, 31.0, 212.3359, 231.364 + 0.1, 30000.0, 31.5, 220.2701, 58.4924 + 0.1, 30000.0, 32.0, 227.925, -132.175 + 0.1, 30000.0, 32.5, 235.408, -333.133 + 0.1, 30000.0, 33.0, 242.8266, -536.877 + 0.1, 30000.0, 33.5, 250.2881, -735.901 + 0.1, 30000.0, 34.0, 257.9, -922.7 + 0.1, 30000.0, 34.5, 271.3856, -1021.89 + 0.1, 30000.0, 35.0, 284.7016, -1100.31 + 0.1, 30000.0, 35.5, 297.4205, -1156.92 + 0.1, 30000.0, 36.0, 309.115, -1190.67 + 0.1, 30000.0, 36.5, 319.3576, -1200.54 + 0.1, 30000.0, 37.0, 327.7209, -1185.48 + 0.1, 30000.0, 37.5, 333.7775, -1144.45 + 0.1, 30000.0, 38.0, 337.1, -1076.4 + 0.1, 30000.0, 38.5, 326.3006, -886.14 + 0.1, 30000.0, 39.0, 317.5953, -715.614 + 0.1, 30000.0, 39.5, 312.9924, -584.706 + 0.1, 30000.0, 40.0, 314.5, -513.3 + 0.1, 30000.0, 40.5, 337.1898, -615.377 + 0.1, 30000.0, 41.0, 364.7812, -779.088 + 0.1, 30000.0, 41.5, 394.057, -986.68 + 0.1, 30000.0, 42.0, 421.8, -1220.4 + 0.1, 30000.0, 42.5, 435.375, -1582.64 + 0.1, 30000.0, 43.0, 444.75, -1887.44 + 0.1, 30000.0, 43.5, 450.475, -2069.0 + 0.1, 30000.0, 44.0, 453.1, -2061.5 + 0.1, 30000.0, 44.5, 451.8742, -1344.28 + 0.1, 30000.0, 45.0, 449.1687, -488.331 + 0.1, 30000.0, 45.5, 446.0539, 390.207 + 0.1, 30000.0, 46.0, 443.6, 1175.2 + 0.1, 30000.0, 46.5, 444.8305, 1426.94 + 0.1, 30000.0, 47.0, 448.0812, 1482.29 + 0.1, 30000.0, 47.5, 453.6414, 1354.54 + 0.1, 30000.0, 48.0, 461.8, 1057.0 + 0.1, 30000.0, 48.5, 472.8461, 602.95 + 0.1, 30000.0, 49.0, 487.0687, 5.6875 + 0.1, 30000.0, 49.5, 504.757, -721.494 + 0.1, 30000.0, 50.0, 526.2, -1565.3 + 0.1, 35000.0, 0.0, 140.2688, 140.269 + 0.1, 35000.0, 22.0, 808.3, 32.2 + 0.1, 35000.0, 22.5, 991.0244, -22.5156 + 0.1, 35000.0, 23.0, 1164.642, 7.6625 + 0.1, 35000.0, 23.5, 1330.589, 106.584 + 0.1, 35000.0, 24.0, 1490.3, 258.1 + 0.1, 35000.0, 24.5, 1645.211, 446.059 + 0.1, 35000.0, 25.0, 1796.758, 654.313 + 0.1, 35000.0, 25.5, 1946.376, 866.709 + 0.1, 35000.0, 26.0, 2095.5, 1067.1 + 0.1, 35000.0, 26.5, 2255.388, 1070.37 + 0.1, 35000.0, 27.0, 2418.216, 1019.69 + 0.1, 35000.0, 27.5, 2583.734, 927.851 + 0.1, 35000.0, 28.0, 2751.695, 807.685 + 0.1, 35000.0, 28.5, 2921.85, 672.002 + 0.1, 35000.0, 29.0, 3093.952, 533.617 + 0.1, 35000.0, 29.5, 3267.751, 405.345 + 0.1, 35000.0, 30.0, 3443.0, 300.0 + 0.1, 35000.0, 30.5, 3619.863, 480.387 + 0.1, 35000.0, 31.0, 3797.641, 685.522 + 0.1, 35000.0, 31.5, 3976.045, 904.412 + 0.1, 35000.0, 32.0, 4154.788, 1126.06 + 0.1, 35000.0, 32.5, 4333.582, 1339.48 + 0.1, 35000.0, 33.0, 4512.141, 1533.67 + 0.1, 35000.0, 33.5, 4690.176, 1697.64 + 0.1, 35000.0, 34.0, 4867.4, 1820.4 + 0.1, 35000.0, 34.5, 5029.435, 1595.92 + 0.1, 35000.0, 35.0, 5191.427, 1336.33 + 0.1, 35000.0, 35.5, 5354.428, 1058.74 + 0.1, 35000.0, 36.0, 5519.495, 780.265 + 0.1, 35000.0, 36.5, 5687.681, 517.996 + 0.1, 35000.0, 37.0, 5860.041, 289.043 + 0.1, 35000.0, 37.5, 6037.629, 110.509 + 0.1, 35000.0, 38.0, 6221.5, -0.5 + 0.1, 35000.0, 38.5, 6432.604, -171.132 + 0.1, 35000.0, 39.0, 6641.783, -165.233 + 0.1, 35000.0, 39.5, 6845.671, 66.3576 + 0.1, 35000.0, 40.0, 7040.9, 572.8 + 0.1, 35000.0, 40.5, 7204.262, 1921.35 + 0.1, 35000.0, 41.0, 7360.169, 3435.83 + 0.1, 35000.0, 41.5, 7513.191, 4958.17 + 0.1, 35000.0, 42.0, 7667.9, 6330.3 + 0.1, 35000.0, 42.5, 7848.048, 7065.75 + 0.1, 35000.0, 43.0, 8031.35, 7466.17 + 0.1, 35000.0, 43.5, 8214.702, 7504.87 + 0.1, 35000.0, 44.0, 8395.0, 7155.1 + 0.1, 35000.0, 44.5, 8552.334, 5814.21 + 0.1, 35000.0, 45.0, 8707.131, 4261.8 + 0.1, 35000.0, 45.5, 8863.013, 2701.51 + 0.1, 35000.0, 46.0, 9023.6, 1337.0 + 0.1, 35000.0, 46.5, 9209.844, 1099.7 + 0.1, 35000.0, 47.0, 9401.1, 1174.37 + 0.1, 35000.0, 47.5, 9594.056, 1473.56 + 0.1, 35000.0, 48.0, 9785.4, 1909.8 + 0.1, 35000.0, 48.5, 9971.819, 2395.64 + 0.1, 35000.0, 49.0, 10150.0, 2843.63 + 0.1, 35000.0, 49.5, 10316.63, 3166.3 + 0.1, 35000.0, 50.0, 10468.4, 3276.2 + 0.1, 39000.0, 0.0, 116.3405, 116.34 + 0.1, 39000.0, 22.0, 552.8, -223.4 + 0.1, 39000.0, 22.5, 687.1117, -390.852 + 0.1, 39000.0, 23.0, 810.6562, -410.422 + 0.1, 39000.0, 23.5, 925.3977, -308.206 + 0.1, 39000.0, 24.0, 1033.3, -110.3 + 0.1, 39000.0, 24.5, 1136.327, 157.2 + 0.1, 39000.0, 25.0, 1236.444, 468.197 + 0.1, 39000.0, 25.5, 1335.613, 796.596 + 0.1, 39000.0, 26.0, 1435.8, 1116.3 + 0.1, 39000.0, 26.5, 1557.37, 1174.26 + 0.1, 39000.0, 27.0, 1684.937, 1158.37 + 0.1, 39000.0, 27.5, 1817.311, 1081.43 + 0.1, 39000.0, 28.0, 1953.3, 956.25 + 0.1, 39000.0, 28.5, 2091.714, 795.65 + 0.1, 39000.0, 29.0, 2231.362, 612.434 + 0.1, 39000.0, 29.5, 2371.055, 419.414 + 0.1, 39000.0, 30.0, 2509.6, 229.4 + 0.1, 39000.0, 30.5, 2627.757, 215.254 + 0.1, 39000.0, 31.0, 2744.105, 214.491 + 0.1, 39000.0, 31.5, 2859.172, 224.678 + 0.1, 39000.0, 32.0, 2973.488, 243.381 + 0.1, 39000.0, 32.5, 3087.579, 268.168 + 0.1, 39000.0, 33.0, 3201.977, 296.605 + 0.1, 39000.0, 33.5, 3317.207, 326.26 + 0.1, 39000.0, 34.0, 3433.8, 354.7 + 0.1, 39000.0, 34.5, 3567.668, 433.806 + 0.1, 39000.0, 35.0, 3702.491, 501.658 + 0.1, 39000.0, 35.5, 3837.33, 550.649 + 0.1, 39000.0, 36.0, 3971.25, 573.175 + 0.1, 39000.0, 36.5, 4103.314, 561.629 + 0.1, 39000.0, 37.0, 4232.584, 508.405 + 0.1, 39000.0, 37.5, 4358.125, 405.897 + 0.1, 39000.0, 38.0, 4479.0, 246.5 + 0.1, 39000.0, 38.5, 4579.131, -238.607 + 0.1, 39000.0, 39.0, 4680.573, -660.37 + 0.1, 39000.0, 39.5, 4785.754, -968.349 + 0.1, 39000.0, 40.0, 4897.1, -1112.1 + 0.1, 39000.0, 40.5, 5029.945, -883.664 + 0.1, 39000.0, 41.0, 5168.65, -453.125 + 0.1, 39000.0, 41.5, 5310.48, 166.952 + 0.1, 39000.0, 42.0, 5452.7, 964.0 + 0.1, 39000.0, 42.5, 5576.1, 2142.43 + 0.1, 39000.0, 43.0, 5701.013, 3385.91 + 0.1, 39000.0, 43.5, 5831.294, 4595.09 + 0.1, 39000.0, 44.0, 5970.8, 5670.6 + 0.1, 39000.0, 44.5, 6161.927, 6370.6 + 0.1, 39000.0, 45.0, 6354.575, 6795.22 + 0.1, 39000.0, 45.5, 6537.186, 6902.11 + 0.1, 39000.0, 46.0, 6698.2, 6648.9 + 0.1, 39000.0, 46.5, 6760.238, 5506.1 + 0.1, 39000.0, 47.0, 6803.888, 4113.34 + 0.1, 39000.0, 47.5, 6843.919, 2623.11 + 0.1, 39000.0, 48.0, 6895.1, 1187.9 + 0.1, 39000.0, 48.5, 6972.2, -39.7992 + 0.1, 39000.0, 49.0, 7089.987, -907.494 + 0.1, 39000.0, 49.5, 7263.231, -1262.69 + 0.1, 39000.0, 50.0, 7506.7, -952.9 + 0.1, 43000.0, 0.0, 95.99235, 95.9924 + 0.1, 43000.0, 22.0, -605.4, 976.8 + 0.1, 43000.0, 22.5, -663.7398, 390.708 + 0.1, 43000.0, 23.0, -726.9813, -93.3125 + 0.1, 43000.0, 23.5, -795.007, -488.627 + 0.1, 43000.0, 24.0, -867.7, -808.6 + 0.1, 43000.0, 24.5, -944.943, -1066.6 + 0.1, 43000.0, 25.0, -1026.619, -1275.99 + 0.1, 43000.0, 25.5, -1112.61, -1450.13 + 0.1, 43000.0, 26.0, -1202.8, -1602.4 + 0.1, 43000.0, 26.5, -1299.822, -1891.24 + 0.1, 43000.0, 27.0, -1400.965, -2193.22 + 0.1, 43000.0, 27.5, -1505.641, -2496.84 + 0.1, 43000.0, 28.0, -1613.26, -2790.6 + 0.1, 43000.0, 28.5, -1723.234, -3062.97 + 0.1, 43000.0, 29.0, -1834.975, -3302.47 + 0.1, 43000.0, 29.5, -1947.893, -3497.58 + 0.1, 43000.0, 30.0, -2061.4, -3636.8 + 0.1, 43000.0, 30.5, -2170.562, -3573.21 + 0.1, 43000.0, 31.0, -2279.55, -3443.61 + 0.1, 43000.0, 31.5, -2388.187, -3249.39 + 0.1, 43000.0, 32.0, -2496.3, -2991.95 + 0.1, 43000.0, 32.5, -2603.712, -2672.67 + 0.1, 43000.0, 33.0, -2710.25, -2292.94 + 0.1, 43000.0, 33.5, -2815.737, -1854.15 + 0.1, 43000.0, 34.0, -2920.0, -1357.7 + 0.1, 43000.0, 34.5, -3007.907, 35.8892 + 0.1, 43000.0, 35.0, -3095.663, 1404.28 + 0.1, 43000.0, 35.5, -3184.517, 2666.01 + 0.1, 43000.0, 36.0, -3275.72, 3739.59 + 0.1, 43000.0, 36.5, -3370.52, 4543.57 + 0.1, 43000.0, 37.0, -3470.168, 4996.46 + 0.1, 43000.0, 37.5, -3575.911, 5016.79 + 0.1, 43000.0, 38.0, -3689.0, 4523.1 + 0.1, 43000.0, 38.5, -3841.612, 2417.4 + 0.1, 43000.0, 39.0, -3988.031, 161.808 + 0.1, 43000.0, 39.5, -4122.635, -2099.27 + 0.1, 43000.0, 40.0, -4239.8, -4221.4 + 0.1, 43000.0, 40.5, -4289.594, -5785.98 + 0.1, 43000.0, 41.0, -4328.425, -7032.47 + 0.1, 43000.0, 41.5, -4368.394, -7926.12 + 0.1, 43000.0, 42.0, -4421.6, -8432.2 + 0.1, 43000.0, 42.5, -4558.609, -8128.95 + 0.1, 43000.0, 43.0, -4709.669, -7523.45 + 0.1, 43000.0, 43.5, -4863.495, -6735.78 + 0.1, 43000.0, 44.0, -5008.8, -5886.0 + 0.1, 43000.0, 44.5, -5081.284, -5307.36 + 0.1, 43000.0, 45.0, -5143.881, -4821.48 + 0.1, 43000.0, 45.5, -5206.513, -4463.16 + 0.1, 43000.0, 46.0, -5279.1, -4267.2 + 0.1, 43000.0, 46.5, -5414.82, -4552.41 + 0.1, 43000.0, 47.0, -5563.031, -4955.96 + 0.1, 43000.0, 47.5, -5716.352, -5399.06 + 0.1, 43000.0, 48.0, -5867.4, -5802.9 + 0.1, 43000.0, 48.5, -6008.791, -6088.67 + 0.1, 43000.0, 49.0, -6133.144, -6177.56 + 0.1, 43000.0, 49.5, -6233.074, -5990.78 + 0.1, 43000.0, 50.0, -6301.2, -5449.5 + 0.1, 48000.0, 0.0, 75.48648, 75.4865 + 0.1, 48000.0, 22.0, -561.0, 821.0 + 0.1, 48000.0, 22.5, -562.5166, 345.619 + 0.1, 48000.0, 23.0, -584.1047, -40.7531 + 0.1, 48000.0, 23.5, -623.2154, -350.324 + 0.1, 48000.0, 24.0, -677.3, -595.3 + 0.1, 48000.0, 24.5, -743.8096, -787.889 + 0.1, 48000.0, 25.0, -820.1953, -940.297 + 0.1, 48000.0, 25.5, -903.9084, -1064.73 + 0.1, 48000.0, 26.0, -992.4, -1173.4 + 0.1, 48000.0, 26.5, -1064.886, -1410.58 + 0.1, 48000.0, 27.0, -1136.01, -1663.95 + 0.1, 48000.0, 27.5, -1206.351, -1923.08 + 0.1, 48000.0, 28.0, -1276.485, -2177.55 + 0.1, 48000.0, 28.5, -1346.99, -2416.9 + 0.1, 48000.0, 29.0, -1418.442, -2630.72 + 0.1, 48000.0, 29.5, -1491.42, -2808.56 + 0.1, 48000.0, 30.0, -1566.5, -2940.0 + 0.1, 48000.0, 30.5, -1656.422, -2885.91 + 0.1, 48000.0, 31.0, -1748.443, -2776.81 + 0.1, 48000.0, 31.5, -1841.981, -2614.51 + 0.1, 48000.0, 32.0, -1936.456, -2400.84 + 0.1, 48000.0, 32.5, -2031.287, -2137.63 + 0.1, 48000.0, 33.0, -2125.891, -1826.68 + 0.1, 48000.0, 33.5, -2219.69, -1469.83 + 0.1, 48000.0, 34.0, -2312.1, -1068.9 + 0.1, 48000.0, 34.5, -2381.527, 17.0337 + 0.1, 48000.0, 35.0, -2450.406, 1082.19 + 0.1, 48000.0, 35.5, -2520.157, 2063.53 + 0.1, 48000.0, 36.0, -2592.2, 2898.03 + 0.1, 48000.0, 36.5, -2667.955, 3522.64 + 0.1, 48000.0, 37.0, -2748.844, 3874.33 + 0.1, 48000.0, 37.5, -2836.285, 3890.06 + 0.1, 48000.0, 38.0, -2931.7, 3506.8 + 0.1, 48000.0, 38.5, -3074.857, 1877.35 + 0.1, 48000.0, 39.0, -3208.944, 129.436 + 0.1, 48000.0, 39.5, -3326.859, -1625.72 + 0.1, 48000.0, 40.0, -3421.5, -3276.9 + 0.1, 48000.0, 40.5, -3426.899, -4507.45 + 0.1, 48000.0, 41.0, -3418.369, -5493.74 + 0.1, 48000.0, 41.5, -3412.354, -6206.74 + 0.1, 48000.0, 42.0, -3425.3, -6617.4 + 0.1, 48000.0, 42.5, -3549.211, -6391.7 + 0.1, 48000.0, 43.0, -3694.75, -5927.54 + 0.1, 48000.0, 43.5, -3848.139, -5317.86 + 0.1, 48000.0, 44.0, -3995.6, -4655.6 + 0.1, 48000.0, 44.5, -4072.312, -4191.95 + 0.1, 48000.0, 45.0, -4135.956, -3798.28 + 0.1, 48000.0, 45.5, -4193.173, -3504.22 + 0.1, 48000.0, 46.0, -4250.6, -3339.4 + 0.1, 48000.0, 46.5, -4335.436, -3568.3 + 0.1, 48000.0, 47.0, -4425.538, -3891.77 + 0.1, 48000.0, 47.5, -4519.32, -4245.51 + 0.1, 48000.0, 48.0, -4615.2, -4565.2 + 0.1, 48000.0, 48.5, -4711.592, -4786.54 + 0.1, 48000.0, 49.0, -4806.913, -4845.22 + 0.1, 48000.0, 49.5, -4899.577, -4676.95 + 0.1, 48000.0, 50.0, -4988.0, -4217.4 + 0.15, 0.0, 0.0, 523.3562, 523.356 + 0.15, 0.0, 22.0, 1659.205, 830.42 + 0.15, 0.0, 22.5, 1974.051, 914.331 + 0.15, 0.0, 23.0, 2285.671, 997.697 + 0.15, 0.0, 23.5, 2595.141, 1080.88 + 0.15, 0.0, 24.0, 2903.54, 1164.26 + 0.15, 0.0, 24.5, 3211.947, 1248.18 + 0.15, 0.0, 25.0, 3521.439, 1333.02 + 0.15, 0.0, 25.5, 3833.096, 1419.13 + 0.15, 0.0, 26.0, 4147.995, 1506.9 + 0.15, 0.0, 26.5, 4478.542, 1600.44 + 0.15, 0.0, 27.0, 4815.136, 1696.58 + 0.15, 0.0, 27.5, 5156.911, 1795.03 + 0.15, 0.0, 28.0, 5503.006, 1895.51 + 0.15, 0.0, 28.5, 5852.556, 1997.73 + 0.15, 0.0, 29.0, 6204.697, 2101.43 + 0.15, 0.0, 29.5, 6558.566, 2206.31 + 0.15, 0.0, 30.0, 6913.3, 2312.1 + 0.15, 0.0, 30.5, 7258.967, 2415.65 + 0.15, 0.0, 31.0, 7604.635, 2519.81 + 0.15, 0.0, 31.5, 7950.303, 2624.59 + 0.15, 0.0, 32.0, 8295.971, 2729.97 + 0.15, 0.0, 32.5, 8641.64, 2835.95 + 0.15, 0.0, 33.0, 8987.308, 2942.52 + 0.15, 0.0, 33.5, 9332.977, 3049.68 + 0.15, 0.0, 34.0, 9678.645, 3157.42 + 0.15, 0.0, 34.5, 10024.31, 3266.39 + 0.15, 0.0, 35.0, 10369.98, 3375.86 + 0.15, 0.0, 35.5, 10715.65, 3485.77 + 0.15, 0.0, 36.0, 11061.31, 3596.04 + 0.15, 0.0, 36.5, 11406.98, 3706.6 + 0.15, 0.0, 37.0, 11752.64, 3817.4 + 0.15, 0.0, 37.5, 12098.31, 3928.35 + 0.15, 0.0, 38.0, 12443.97, 4039.39 + 0.15, 0.0, 38.5, 12789.63, 4150.79 + 0.15, 0.0, 39.0, 13135.29, 4261.96 + 0.15, 0.0, 39.5, 13480.96, 4372.77 + 0.15, 0.0, 40.0, 13826.62, 4483.08 + 0.15, 0.0, 40.5, 14172.29, 4591.72 + 0.15, 0.0, 41.0, 14517.95, 4699.98 + 0.15, 0.0, 41.5, 14863.62, 4808.13 + 0.15, 0.0, 42.0, 15209.29, 4916.46 + 0.15, 0.0, 42.5, 15554.69, 5026.35 + 0.15, 0.0, 43.0, 15900.2, 5136.5 + 0.15, 0.0, 43.5, 16245.92, 5246.73 + 0.15, 0.0, 44.0, 16591.96, 5356.87 + 0.15, 0.0, 44.5, 16939.52, 5466.12 + 0.15, 0.0, 45.0, 17287.18, 5575.16 + 0.15, 0.0, 45.5, 17634.62, 5684.03 + 0.15, 0.0, 46.0, 17981.53, 5792.78 + 0.15, 0.0, 46.5, 18325.96, 5900.97 + 0.15, 0.0, 47.0, 18669.85, 6009.37 + 0.15, 0.0, 47.5, 19013.52, 6118.22 + 0.15, 0.0, 48.0, 19357.29, 6227.79 + 0.15, 0.0, 48.5, 19701.49, 6338.32 + 0.15, 0.0, 49.0, 20046.44, 6450.09 + 0.15, 0.0, 49.5, 20392.47, 6563.34 + 0.15, 0.0, 50.0, 20739.89, 6678.33 + 0.15, 2000.0, 0.0, 490.0025, 490.003 + 0.15, 2000.0, 22.0, 1599.24, 787.695 + 0.15, 2000.0, 22.5, 1902.729, 869.244 + 0.15, 2000.0, 23.0, 2203.103, 949.864 + 0.15, 2000.0, 23.5, 2501.402, 1029.96 + 0.15, 2000.0, 24.0, 2798.665, 1109.96 + 0.15, 2000.0, 24.5, 3095.932, 1190.26 + 0.15, 2000.0, 25.0, 3394.244, 1271.28 + 0.15, 2000.0, 25.5, 3694.64, 1353.43 + 0.15, 2000.0, 26.0, 3998.16, 1437.12 + 0.15, 2000.0, 26.5, 4316.765, 1526.8 + 0.15, 2000.0, 27.0, 4641.199, 1619.07 + 0.15, 2000.0, 27.5, 4970.628, 1713.67 + 0.15, 2000.0, 28.0, 5304.22, 1810.3 + 0.15, 2000.0, 28.5, 5641.142, 1908.68 + 0.15, 2000.0, 29.0, 5980.563, 2008.55 + 0.15, 2000.0, 29.5, 6321.65, 2109.61 + 0.15, 2000.0, 30.0, 6663.57, 2211.6 + 0.15, 2000.0, 30.5, 6996.754, 2311.48 + 0.15, 2000.0, 31.0, 7329.939, 2411.99 + 0.15, 2000.0, 31.5, 7663.124, 2513.1 + 0.15, 2000.0, 32.0, 7996.31, 2614.79 + 0.15, 2000.0, 32.5, 8329.496, 2717.05 + 0.15, 2000.0, 33.0, 8662.681, 2819.86 + 0.15, 2000.0, 33.5, 8995.866, 2923.2 + 0.15, 2000.0, 34.0, 9329.05, 3027.06 + 0.15, 2000.0, 34.5, 9662.23, 3131.86 + 0.15, 2000.0, 35.0, 9995.41, 3237.1 + 0.15, 2000.0, 35.5, 10328.59, 3342.71 + 0.15, 2000.0, 36.0, 10661.76, 3448.63 + 0.15, 2000.0, 36.5, 10994.94, 3554.8 + 0.15, 2000.0, 37.0, 11328.11, 3661.16 + 0.15, 2000.0, 37.5, 11661.29, 3767.64 + 0.15, 2000.0, 38.0, 11994.46, 3874.18 + 0.15, 2000.0, 38.5, 12327.63, 3981.23 + 0.15, 2000.0, 39.0, 12660.8, 4087.96 + 0.15, 2000.0, 39.5, 12993.97, 4194.19 + 0.15, 2000.0, 40.0, 13327.13, 4299.77 + 0.15, 2000.0, 40.5, 13660.3, 4403.09 + 0.15, 2000.0, 41.0, 13993.47, 4505.97 + 0.15, 2000.0, 41.5, 14326.64, 4608.79 + 0.15, 2000.0, 42.0, 14659.82, 4711.92 + 0.15, 2000.0, 42.5, 14992.74, 4817.59 + 0.15, 2000.0, 43.0, 15325.77, 4923.62 + 0.15, 2000.0, 43.5, 15659.02, 5029.68 + 0.15, 2000.0, 44.0, 15992.57, 5135.43 + 0.15, 2000.0, 44.5, 16327.57, 5238.92 + 0.15, 2000.0, 45.0, 16662.68, 5342.05 + 0.15, 2000.0, 45.5, 16997.58, 5445.12 + 0.15, 2000.0, 46.0, 17331.96, 5548.43 + 0.15, 2000.0, 46.5, 17663.95, 5652.78 + 0.15, 2000.0, 47.0, 17995.42, 5757.76 + 0.15, 2000.0, 47.5, 18326.68, 5863.45 + 0.15, 2000.0, 48.0, 18658.03, 5969.96 + 0.15, 2000.0, 48.5, 18989.79, 6077.37 + 0.15, 2000.0, 49.0, 19322.27, 6185.77 + 0.15, 2000.0, 49.5, 19655.79, 6295.26 + 0.15, 2000.0, 50.0, 19990.63, 6405.94 + 0.15, 5000.0, 0.0, 443.1415, 443.141 + 0.15, 5000.0, 22.0, 1519.06, 690.835 + 0.15, 5000.0, 22.5, 1807.297, 769.993 + 0.15, 5000.0, 23.0, 2092.586, 842.755 + 0.15, 5000.0, 23.5, 2375.913, 910.701 + 0.15, 5000.0, 24.0, 2658.265, 975.415 + 0.15, 5000.0, 24.5, 2940.628, 1038.48 + 0.15, 5000.0, 25.0, 3223.987, 1101.48 + 0.15, 5000.0, 25.5, 3509.329, 1165.99 + 0.15, 5000.0, 26.0, 3797.64, 1233.59 + 0.15, 5000.0, 26.5, 4100.269, 1321.98 + 0.15, 5000.0, 27.0, 4408.431, 1417.55 + 0.15, 5000.0, 27.5, 4721.335, 1519.12 + 0.15, 5000.0, 28.0, 5038.193, 1625.52 + 0.15, 5000.0, 28.5, 5358.212, 1735.57 + 0.15, 5000.0, 29.0, 5680.604, 1848.09 + 0.15, 5000.0, 29.5, 6004.576, 1961.91 + 0.15, 5000.0, 30.0, 6329.34, 2075.85 + 0.15, 5000.0, 30.5, 6645.809, 2174.43 + 0.15, 5000.0, 31.0, 6962.278, 2272.13 + 0.15, 5000.0, 31.5, 7278.747, 2369.15 + 0.15, 5000.0, 32.0, 7595.216, 2465.67 + 0.15, 5000.0, 32.5, 7911.685, 2561.87 + 0.15, 5000.0, 33.0, 8228.152, 2657.94 + 0.15, 5000.0, 33.5, 8544.619, 2754.06 + 0.15, 5000.0, 34.0, 8861.085, 2850.43 + 0.15, 5000.0, 34.5, 9177.537, 2950.6 + 0.15, 5000.0, 35.0, 9493.988, 3051.06 + 0.15, 5000.0, 35.5, 9810.44, 3151.68 + 0.15, 5000.0, 36.0, 10126.89, 3252.31 + 0.15, 5000.0, 36.5, 10443.35, 3352.82 + 0.15, 5000.0, 37.0, 10759.8, 3453.07 + 0.15, 5000.0, 37.5, 11076.26, 3552.92 + 0.15, 5000.0, 38.0, 11392.73, 3652.25 + 0.15, 5000.0, 38.5, 11709.21, 3749.46 + 0.15, 5000.0, 39.0, 12025.69, 3846.62 + 0.15, 5000.0, 39.5, 12342.17, 3943.91 + 0.15, 5000.0, 40.0, 12658.65, 4041.51 + 0.15, 5000.0, 40.5, 12975.13, 4140.77 + 0.15, 5000.0, 41.0, 13291.61, 4240.25 + 0.15, 5000.0, 41.5, 13608.08, 4339.68 + 0.15, 5000.0, 42.0, 13924.55, 4438.78 + 0.15, 5000.0, 42.5, 14240.75, 4535.9 + 0.15, 5000.0, 43.0, 14557.05, 4632.69 + 0.15, 5000.0, 43.5, 14873.55, 4729.44 + 0.15, 5000.0, 44.0, 15190.35, 4826.41 + 0.15, 5000.0, 44.5, 15508.57, 4924.55 + 0.15, 5000.0, 45.0, 15826.89, 5023.2 + 0.15, 5000.0, 45.5, 16145.01, 5122.38 + 0.15, 5000.0, 46.0, 16462.64, 5222.11 + 0.15, 5000.0, 46.5, 16777.96, 5322.24 + 0.15, 5000.0, 47.0, 17092.78, 5422.99 + 0.15, 5000.0, 47.5, 17407.4, 5524.46 + 0.15, 5000.0, 48.0, 17722.12, 5626.7 + 0.15, 5000.0, 48.5, 18037.24, 5729.79 + 0.15, 5000.0, 49.0, 18353.06, 5833.81 + 0.15, 5000.0, 49.5, 18669.88, 5938.83 + 0.15, 5000.0, 50.0, 18988.0, 6044.93 + 0.15, 10000.0, 0.0, 372.9669, 372.967 + 0.15, 10000.0, 22.0, 1376.725, 636.425 + 0.15, 10000.0, 22.5, 1638.051, 709.66 + 0.15, 10000.0, 23.0, 1896.683, 781.277 + 0.15, 10000.0, 23.5, 2153.517, 851.731 + 0.15, 10000.0, 24.0, 2409.45, 921.475 + 0.15, 10000.0, 24.5, 2665.378, 990.965 + 0.15, 10000.0, 25.0, 2922.198, 1060.65 + 0.15, 10000.0, 25.5, 3180.806, 1131.0 + 0.15, 10000.0, 26.0, 3442.1, 1202.45 + 0.15, 10000.0, 26.5, 3716.381, 1279.67 + 0.15, 10000.0, 27.0, 3995.678, 1359.14 + 0.15, 10000.0, 27.5, 4279.274, 1440.6 + 0.15, 10000.0, 28.0, 4566.455, 1523.79 + 0.15, 10000.0, 28.5, 4856.504, 1608.45 + 0.15, 10000.0, 29.0, 5148.705, 1694.29 + 0.15, 10000.0, 29.5, 5442.342, 1781.06 + 0.15, 10000.0, 30.0, 5736.7, 1868.5 + 0.15, 10000.0, 30.5, 6023.556, 1953.51 + 0.15, 10000.0, 31.0, 6310.416, 2038.92 + 0.15, 10000.0, 31.5, 6597.279, 2124.73 + 0.15, 10000.0, 32.0, 6884.144, 2210.95 + 0.15, 10000.0, 32.5, 7171.009, 2297.58 + 0.15, 10000.0, 33.0, 7457.874, 2384.62 + 0.15, 10000.0, 33.5, 7744.738, 2472.08 + 0.15, 10000.0, 34.0, 8031.6, 2559.95 + 0.15, 10000.0, 34.5, 8318.435, 2649.59 + 0.15, 10000.0, 35.0, 8605.269, 2739.53 + 0.15, 10000.0, 35.5, 8892.102, 2829.64 + 0.15, 10000.0, 36.0, 9178.935, 2919.8 + 0.15, 10000.0, 36.5, 9465.77, 3009.87 + 0.15, 10000.0, 37.0, 9752.609, 3099.74 + 0.15, 10000.0, 37.5, 10039.45, 3189.27 + 0.15, 10000.0, 38.0, 10326.3, 3278.35 + 0.15, 10000.0, 38.5, 10613.18, 3366.23 + 0.15, 10000.0, 39.0, 10900.05, 3453.72 + 0.15, 10000.0, 39.5, 11186.92, 3540.83 + 0.15, 10000.0, 40.0, 11473.77, 3627.57 + 0.15, 10000.0, 40.5, 11760.6, 3713.19 + 0.15, 10000.0, 41.0, 12047.41, 3798.76 + 0.15, 10000.0, 41.5, 12334.22, 3884.62 + 0.15, 10000.0, 42.0, 12621.02, 3971.07 + 0.15, 10000.0, 42.5, 12907.63, 4059.45 + 0.15, 10000.0, 43.0, 13194.34, 4148.66 + 0.15, 10000.0, 43.5, 13481.22, 4238.64 + 0.15, 10000.0, 44.0, 13768.37, 4329.3 + 0.15, 10000.0, 44.5, 14056.77, 4420.39 + 0.15, 10000.0, 45.0, 14345.25, 4512.08 + 0.15, 10000.0, 45.5, 14633.56, 4604.36 + 0.15, 10000.0, 46.0, 14921.43, 4697.22 + 0.15, 10000.0, 46.5, 15207.25, 4790.19 + 0.15, 10000.0, 47.0, 15492.64, 4883.91 + 0.15, 10000.0, 47.5, 15777.84, 4978.55 + 0.15, 10000.0, 48.0, 16063.12, 5074.3 + 0.15, 10000.0, 48.5, 16348.76, 5171.33 + 0.15, 10000.0, 49.0, 16635.01, 5269.82 + 0.15, 10000.0, 49.5, 16922.13, 5369.94 + 0.15, 10000.0, 50.0, 17210.4, 5471.87 + 0.15, 15000.0, 0.0, 311.8725, 311.872 + 0.15, 15000.0, 22.0, -2648.9, -763.0 + 0.15, 15000.0, 22.5, -3152.176, -946.063 + 0.15, 15000.0, 23.0, -3650.031, -1119.86 + 0.15, 15000.0, 23.5, -4144.221, -1286.7 + 0.15, 15000.0, 24.0, -4636.5, -1448.9 + 0.15, 15000.0, 24.5, -5128.623, -1608.76 + 0.15, 15000.0, 25.0, -5622.344, -1768.59 + 0.15, 15000.0, 25.5, -6119.418, -1930.7 + 0.15, 15000.0, 26.0, -6621.6, -2097.4 + 0.15, 15000.0, 26.5, -7148.857, -2283.71 + 0.15, 15000.0, 27.0, -7685.772, -2479.94 + 0.15, 15000.0, 27.5, -8230.977, -2686.25 + 0.15, 15000.0, 28.0, -8783.105, -2902.74 + 0.15, 15000.0, 28.5, -9340.789, -3129.57 + 0.15, 15000.0, 29.0, -9902.661, -3366.85 + 0.15, 15000.0, 29.5, -10467.35, -3614.72 + 0.15, 15000.0, 30.0, -11033.5, -3873.3 + 0.15, 15000.0, 30.5, -11585.6, -4177.91 + 0.15, 15000.0, 31.0, -12137.76, -4490.15 + 0.15, 15000.0, 31.5, -12689.97, -4806.79 + 0.15, 15000.0, 32.0, -13242.2, -5124.63 + 0.15, 15000.0, 32.5, -13794.43, -5440.44 + 0.15, 15000.0, 33.0, -14346.64, -5751.0 + 0.15, 15000.0, 33.5, -14898.8, -6053.09 + 0.15, 15000.0, 34.0, -15450.9, -6343.5 + 0.15, 15000.0, 34.5, -16002.14, -6533.73 + 0.15, 15000.0, 35.0, -16553.34, -6713.96 + 0.15, 15000.0, 35.5, -17104.56, -6889.08 + 0.15, 15000.0, 36.0, -17655.85, -7064.0 + 0.15, 15000.0, 36.5, -18207.27, -7243.62 + 0.15, 15000.0, 37.0, -18758.87, -7432.84 + 0.15, 15000.0, 37.5, -19310.69, -7636.57 + 0.15, 15000.0, 38.0, -19862.8, -7859.7 + 0.15, 15000.0, 38.5, -20416.0, -8137.88 + 0.15, 15000.0, 39.0, -20969.19, -8429.32 + 0.15, 15000.0, 39.5, -21522.26, -8732.1 + 0.15, 15000.0, 40.0, -22075.1, -9044.3 + 0.15, 15000.0, 40.5, -22627.14, -9355.8 + 0.15, 15000.0, 41.0, -23178.89, -9676.13 + 0.15, 15000.0, 41.5, -23730.43, -10006.6 + 0.15, 15000.0, 42.0, -24281.8, -10348.6 + 0.15, 15000.0, 42.5, -24832.73, -10724.6 + 0.15, 15000.0, 43.0, -25383.77, -11106.4 + 0.15, 15000.0, 43.5, -25935.13, -11486.7 + 0.15, 15000.0, 44.0, -26487.0, -11858.4 + 0.15, 15000.0, 44.5, -27041.53, -12171.7 + 0.15, 15000.0, 45.0, -27596.2, -12479.3 + 0.15, 15000.0, 45.5, -28150.45, -12791.1 + 0.15, 15000.0, 46.0, -28703.7, -13117.0 + 0.15, 15000.0, 46.5, -29252.34, -13495.6 + 0.15, 15000.0, 47.0, -29800.06, -13896.8 + 0.15, 15000.0, 47.5, -30347.5, -14319.2 + 0.15, 15000.0, 48.0, -30895.3, -14761.3 + 0.15, 15000.0, 48.5, -31444.11, -15221.6 + 0.15, 15000.0, 49.0, -31994.56, -15698.7 + 0.15, 15000.0, 49.5, -32547.31, -16191.1 + 0.15, 15000.0, 50.0, -33103.0, -16697.3 + 0.15, 20000.0, 0.0, 258.9696, 258.97 + 0.15, 20000.0, 22.0, 886.9, 369.3 + 0.15, 20000.0, 22.5, 1062.826, 537.807 + 0.15, 20000.0, 23.0, 1235.17, 648.308 + 0.15, 20000.0, 23.5, 1404.805, 709.655 + 0.15, 20000.0, 24.0, 1572.6, 730.7 + 0.15, 20000.0, 24.5, 1739.426, 720.295 + 0.15, 20000.0, 25.0, 1906.155, 687.292 + 0.15, 20000.0, 25.5, 2073.656, 640.543 + 0.15, 20000.0, 26.0, 2242.8, 588.9 + 0.15, 20000.0, 26.5, 2423.321, 607.344 + 0.15, 20000.0, 27.0, 2607.732, 642.377 + 0.15, 20000.0, 27.5, 2795.387, 691.514 + 0.15, 20000.0, 28.0, 2985.635, 752.27 + 0.15, 20000.0, 28.5, 3177.829, 822.161 + 0.15, 20000.0, 29.0, 3371.32, 898.703 + 0.15, 20000.0, 29.5, 3565.46, 979.411 + 0.15, 20000.0, 30.0, 3759.6, 1061.8 + 0.15, 20000.0, 30.5, 3944.465, 1106.71 + 0.15, 20000.0, 31.0, 4128.855, 1151.83 + 0.15, 20000.0, 31.5, 4312.942, 1198.17 + 0.15, 20000.0, 32.0, 4496.9, 1246.72 + 0.15, 20000.0, 32.5, 4680.902, 1298.5 + 0.15, 20000.0, 33.0, 4865.12, 1354.52 + 0.15, 20000.0, 33.5, 5049.729, 1415.78 + 0.15, 20000.0, 34.0, 5234.9, 1483.3 + 0.15, 20000.0, 34.5, 5425.673, 1632.56 + 0.15, 20000.0, 35.0, 5616.892, 1783.0 + 0.15, 20000.0, 35.5, 5808.266, 1928.53 + 0.15, 20000.0, 36.0, 5999.505, 2063.06 + 0.15, 20000.0, 36.5, 6190.318, 2180.51 + 0.15, 20000.0, 37.0, 6380.415, 2274.79 + 0.15, 20000.0, 37.5, 6569.506, 2339.82 + 0.15, 20000.0, 38.0, 6757.3, 2369.5 + 0.15, 20000.0, 38.5, 6940.449, 2273.06 + 0.15, 20000.0, 39.0, 7123.306, 2173.03 + 0.15, 20000.0, 39.5, 7306.26, 2082.13 + 0.15, 20000.0, 40.0, 7489.7, 2013.1 + 0.15, 20000.0, 40.5, 7675.612, 2020.83 + 0.15, 20000.0, 41.0, 7862.15, 2059.04 + 0.15, 20000.0, 41.5, 8049.062, 2123.6 + 0.15, 20000.0, 42.0, 8236.1, 2210.4 + 0.15, 20000.0, 42.5, 8422.43, 2310.41 + 0.15, 20000.0, 43.0, 8608.619, 2426.36 + 0.15, 20000.0, 43.5, 8794.648, 2556.08 + 0.15, 20000.0, 44.0, 8980.5, 2697.4 + 0.15, 20000.0, 44.5, 9165.264, 2858.58 + 0.15, 20000.0, 45.0, 9350.175, 3022.86 + 0.15, 20000.0, 45.5, 9535.573, 3183.88 + 0.15, 20000.0, 46.0, 9721.8, 3335.3 + 0.15, 20000.0, 46.5, 9911.168, 3450.4 + 0.15, 20000.0, 47.0, 10101.26, 3551.37 + 0.15, 20000.0, 47.5, 10291.62, 3640.04 + 0.15, 20000.0, 48.0, 10481.8, 3718.2 + 0.15, 20000.0, 48.5, 10671.36, 3787.67 + 0.15, 20000.0, 49.0, 10859.84, 3850.27 + 0.15, 20000.0, 49.5, 11046.81, 3907.81 + 0.15, 20000.0, 50.0, 11231.8, 3962.1 + 0.15, 25000.0, 0.0, 213.4206, 213.421 + 0.15, 25000.0, 22.0, 574.5, 498.3 + 0.15, 25000.0, 22.5, 694.3463, 233.346 + 0.15, 25000.0, 23.0, 810.5297, 98.9328 + 0.15, 25000.0, 23.5, 923.8232, 74.5283 + 0.15, 25000.0, 24.0, 1035.0, 139.6 + 0.15, 25000.0, 24.5, 1144.833, 273.615 + 0.15, 25000.0, 25.0, 1254.095, 456.042 + 0.15, 25000.0, 25.5, 1363.56, 666.348 + 0.15, 25000.0, 26.0, 1474.0, 884.0 + 0.15, 25000.0, 26.5, 1593.72, 918.949 + 0.15, 25000.0, 27.0, 1716.393, 910.492 + 0.15, 25000.0, 27.5, 1841.498, 867.158 + 0.15, 25000.0, 28.0, 1968.52, 797.475 + 0.15, 25000.0, 28.5, 2096.939, 709.97 + 0.15, 25000.0, 29.0, 2226.237, 613.17 + 0.15, 25000.0, 29.5, 2355.897, 515.604 + 0.15, 25000.0, 30.0, 2485.4, 425.8 + 0.15, 25000.0, 30.5, 2607.457, 471.718 + 0.15, 25000.0, 31.0, 2728.965, 531.078 + 0.15, 25000.0, 31.5, 2850.052, 601.034 + 0.15, 25000.0, 32.0, 2970.844, 678.738 + 0.15, 25000.0, 32.5, 3091.468, 761.343 + 0.15, 25000.0, 33.0, 3212.051, 846.003 + 0.15, 25000.0, 33.5, 3332.719, 929.871 + 0.15, 25000.0, 34.0, 3453.6, 1010.1 + 0.15, 25000.0, 34.5, 3577.397, 969.678 + 0.15, 25000.0, 35.0, 3701.414, 930.795 + 0.15, 25000.0, 35.5, 3825.533, 901.479 + 0.15, 25000.0, 36.0, 3949.635, 889.755 + 0.15, 25000.0, 36.5, 4073.601, 903.649 + 0.15, 25000.0, 37.0, 4197.313, 951.187 + 0.15, 25000.0, 37.5, 4320.653, 1040.4 + 0.15, 25000.0, 38.0, 4443.5, 1179.3 + 0.15, 25000.0, 38.5, 4562.981, 1562.63 + 0.15, 25000.0, 39.0, 4683.162, 1914.9 + 0.15, 25000.0, 39.5, 4804.537, 2202.65 + 0.15, 25000.0, 40.0, 4927.6, 2392.4 + 0.15, 25000.0, 40.5, 5057.215, 2271.95 + 0.15, 25000.0, 41.0, 5187.756, 2058.08 + 0.15, 25000.0, 41.5, 5317.97, 1788.82 + 0.15, 25000.0, 42.0, 5446.6, 1502.2 + 0.15, 25000.0, 42.5, 5565.166, 1315.1 + 0.15, 25000.0, 43.0, 5682.531, 1155.17 + 0.15, 25000.0, 43.5, 5800.33, 1028.9 + 0.15, 25000.0, 44.0, 5920.2, 942.8 + 0.15, 25000.0, 44.5, 6053.256, 945.243 + 0.15, 25000.0, 45.0, 6187.863, 984.081 + 0.15, 25000.0, 45.5, 6321.863, 1049.05 + 0.15, 25000.0, 46.0, 6453.1, 1129.9 + 0.15, 25000.0, 46.5, 6569.161, 1157.35 + 0.15, 25000.0, 47.0, 6682.25, 1203.76 + 0.15, 25000.0, 47.5, 6794.314, 1282.46 + 0.15, 25000.0, 48.0, 6907.3, 1406.8 + 0.15, 25000.0, 48.5, 7023.155, 1590.11 + 0.15, 25000.0, 49.0, 7143.825, 1845.74 + 0.15, 25000.0, 49.5, 7271.258, 2187.02 + 0.15, 25000.0, 50.0, 7407.4, 2627.3 + 0.15, 30000.0, 0.0, 174.4463, 174.446 + 0.15, 30000.0, 22.0, 167.8, 129.0 + 0.15, 30000.0, 22.5, 194.6727, 262.547 + 0.15, 30000.0, 23.0, 223.1688, 310.459 + 0.15, 30000.0, 23.5, 253.1805, 288.092 + 0.15, 30000.0, 24.0, 284.6, 210.8 + 0.15, 30000.0, 24.5, 317.3195, 93.9395 + 0.15, 30000.0, 25.0, 351.2313, -47.1344 + 0.15, 30000.0, 25.5, 386.2273, -197.066 + 0.15, 30000.0, 26.0, 422.2, -340.5 + 0.15, 30000.0, 26.5, 459.4365, -309.661 + 0.15, 30000.0, 27.0, 497.4566, -232.904 + 0.15, 30000.0, 27.5, 536.0846, -121.003 + 0.15, 30000.0, 28.0, 575.145, 15.27 + 0.15, 30000.0, 28.5, 614.4623, 165.14 + 0.15, 30000.0, 29.0, 653.8609, 317.834 + 0.15, 30000.0, 29.5, 693.1654, 462.579 + 0.15, 30000.0, 30.0, 732.2, 588.6 + 0.15, 30000.0, 30.5, 768.1155, 514.553 + 0.15, 30000.0, 31.0, 803.6648, 416.48 + 0.15, 30000.0, 31.5, 838.9271, 299.854 + 0.15, 30000.0, 32.0, 873.9813, 170.144 + 0.15, 30000.0, 32.5, 908.9065, 32.8222 + 0.15, 30000.0, 33.0, 943.782, -106.64 + 0.15, 30000.0, 33.5, 978.6868, -242.771 + 0.15, 30000.0, 34.0, 1013.7, -370.1 + 0.15, 30000.0, 34.5, 1053.016, -434.529 + 0.15, 30000.0, 35.0, 1092.206, -483.845 + 0.15, 30000.0, 35.5, 1130.959, -517.207 + 0.15, 30000.0, 36.0, 1168.96, -533.775 + 0.15, 30000.0, 36.5, 1205.898, -532.708 + 0.15, 30000.0, 37.0, 1241.459, -513.167 + 0.15, 30000.0, 37.5, 1275.33, -474.311 + 0.15, 30000.0, 38.0, 1307.2, -415.3 + 0.15, 30000.0, 38.5, 1328.704, -265.357 + 0.15, 30000.0, 39.0, 1351.755, -129.842 + 0.15, 30000.0, 39.5, 1377.828, -23.4561 + 0.15, 30000.0, 40.0, 1408.4, 39.1 + 0.15, 30000.0, 40.5, 1454.563, -26.718 + 0.15, 30000.0, 41.0, 1504.331, -137.831 + 0.15, 30000.0, 41.5, 1555.334, -281.004 + 0.15, 30000.0, 42.0, 1605.2, -443.0 + 0.15, 30000.0, 42.5, 1644.611, -697.83 + 0.15, 30000.0, 43.0, 1680.925, -910.112 + 0.15, 30000.0, 43.5, 1714.552, -1031.71 + 0.15, 30000.0, 44.0, 1745.9, -1014.5 + 0.15, 30000.0, 44.5, 1774.442, -476.656 + 0.15, 30000.0, 45.0, 1801.9, 162.8 + 0.15, 30000.0, 45.5, 1829.058, 818.531 + 0.15, 30000.0, 46.0, 1856.7, 1405.2 + 0.15, 30000.0, 46.5, 1887.048, 1599.43 + 0.15, 30000.0, 47.0, 1918.875, 1649.13 + 0.15, 30000.0, 47.5, 1952.389, 1564.2 + 0.15, 30000.0, 48.0, 1987.8, 1354.5 + 0.15, 30000.0, 48.5, 2025.317, 1029.92 + 0.15, 30000.0, 49.0, 2065.15, 600.344 + 0.15, 30000.0, 49.5, 2107.508, 75.643 + 0.15, 30000.0, 50.0, 2152.6, -534.3 + 0.15, 35000.0, 0.0, 141.3214, 141.321 + 0.15, 35000.0, 22.0, 714.0, 103.3 + 0.15, 35000.0, 22.5, 871.7598, 63.5615 + 0.15, 35000.0, 23.0, 1022.409, 89.6078 + 0.15, 35000.0, 23.5, 1167.104, 169.0 + 0.15, 35000.0, 24.0, 1307.0, 289.3 + 0.15, 35000.0, 24.5, 1443.252, 438.069 + 0.15, 35000.0, 25.0, 1577.016, 602.867 + 0.15, 35000.0, 25.5, 1709.446, 771.257 + 0.15, 35000.0, 26.0, 1841.7, 930.8 + 0.15, 35000.0, 26.5, 1983.077, 939.387 + 0.15, 35000.0, 27.0, 2127.054, 906.84 + 0.15, 35000.0, 27.5, 2273.388, 842.949 + 0.15, 35000.0, 28.0, 2421.84, 757.505 + 0.15, 35000.0, 28.5, 2572.168, 660.297 + 0.15, 35000.0, 29.0, 2724.131, 561.117 + 0.15, 35000.0, 29.5, 2877.489, 469.755 + 0.15, 35000.0, 30.0, 3032.0, 396.0 + 0.15, 35000.0, 30.5, 3187.176, 540.186 + 0.15, 35000.0, 31.0, 3343.048, 703.413 + 0.15, 35000.0, 31.5, 3499.397, 877.326 + 0.15, 35000.0, 32.0, 3656.006, 1053.57 + 0.15, 35000.0, 32.5, 3812.659, 1223.78 + 0.15, 35000.0, 33.0, 3969.137, 1379.61 + 0.15, 35000.0, 33.5, 4125.223, 1512.71 + 0.15, 35000.0, 34.0, 4280.7, 1614.7 + 0.15, 35000.0, 34.5, 4424.718, 1454.43 + 0.15, 35000.0, 35.0, 4568.705, 1267.58 + 0.15, 35000.0, 35.5, 4713.455, 1067.0 + 0.15, 35000.0, 36.0, 4859.765, 865.55 + 0.15, 35000.0, 36.5, 5008.429, 676.104 + 0.15, 35000.0, 37.0, 5160.243, 511.522 + 0.15, 35000.0, 37.5, 5316.001, 384.666 + 0.15, 35000.0, 38.0, 5476.5, 308.4 + 0.15, 35000.0, 38.5, 5657.556, 185.921 + 0.15, 35000.0, 39.0, 5837.153, 196.622 + 0.15, 35000.0, 39.5, 6012.749, 377.737 + 0.15, 35000.0, 40.0, 6181.8, 766.5 + 0.15, 35000.0, 40.5, 6326.758, 1791.65 + 0.15, 35000.0, 41.0, 6466.088, 2942.31 + 0.15, 35000.0, 41.5, 6603.248, 4099.11 + 0.15, 35000.0, 42.0, 6741.7, 5142.7 + 0.15, 35000.0, 42.5, 6899.425, 5707.45 + 0.15, 35000.0, 43.0, 7059.55, 6018.74 + 0.15, 35000.0, 43.5, 7219.725, 6055.72 + 0.15, 35000.0, 44.0, 7377.6, 5797.5 + 0.15, 35000.0, 44.5, 7518.165, 4783.0 + 0.15, 35000.0, 45.0, 7656.794, 3607.68 + 0.15, 35000.0, 45.5, 7796.201, 2426.73 + 0.15, 35000.0, 46.0, 7939.1, 1395.4 + 0.15, 35000.0, 46.5, 8101.135, 1223.69 + 0.15, 35000.0, 47.0, 8266.919, 1290.12 + 0.15, 35000.0, 47.5, 8433.993, 1527.99 + 0.15, 35000.0, 48.0, 8599.9, 1870.6 + 0.15, 35000.0, 48.5, 8762.182, 2251.26 + 0.15, 35000.0, 49.0, 8918.381, 2603.28 + 0.15, 35000.0, 49.5, 9066.04, 2859.96 + 0.15, 35000.0, 50.0, 9202.7, 2954.6 + 0.15, 39000.0, 0.0, 117.2135, 117.213 + 0.15, 39000.0, 22.0, 499.9, -105.4 + 0.15, 39000.0, 22.5, 617.1787, -227.844 + 0.15, 39000.0, 23.0, 726.1078, -238.158 + 0.15, 39000.0, 23.5, 828.233, -156.117 + 0.15, 39000.0, 24.0, 925.1, -1.5 + 0.15, 39000.0, 24.5, 1018.254, 205.917 + 0.15, 39000.0, 25.0, 1109.242, 446.358 + 0.15, 39000.0, 25.5, 1199.609, 700.044 + 0.15, 39000.0, 26.0, 1290.9, 947.2 + 0.15, 39000.0, 26.5, 1399.195, 996.073 + 0.15, 39000.0, 27.0, 1512.336, 989.035 + 0.15, 39000.0, 27.5, 1629.378, 935.789 + 0.15, 39000.0, 28.0, 1749.375, 846.04 + 0.15, 39000.0, 28.5, 1871.381, 729.492 + 0.15, 39000.0, 29.0, 1994.452, 595.85 + 0.15, 39000.0, 29.5, 2117.64, 454.818 + 0.15, 39000.0, 30.0, 2240.0, 316.1 + 0.15, 39000.0, 30.5, 2346.453, 310.472 + 0.15, 39000.0, 31.0, 2451.533, 315.036 + 0.15, 39000.0, 31.5, 2555.64, 327.967 + 0.15, 39000.0, 32.0, 2659.175, 347.437 + 0.15, 39000.0, 32.5, 2762.538, 371.622 + 0.15, 39000.0, 33.0, 2866.13, 398.695 + 0.15, 39000.0, 33.5, 2970.35, 426.83 + 0.15, 39000.0, 34.0, 3075.6, 454.2 + 0.15, 39000.0, 34.5, 3193.903, 520.185 + 0.15, 39000.0, 35.0, 3312.93, 577.828 + 0.15, 39000.0, 35.5, 3431.972, 621.38 + 0.15, 39000.0, 36.0, 3550.325, 645.09 + 0.15, 39000.0, 36.5, 3667.281, 643.207 + 0.15, 39000.0, 37.0, 3782.133, 609.982 + 0.15, 39000.0, 37.5, 3894.175, 539.663 + 0.15, 39000.0, 38.0, 4002.7, 426.5 + 0.15, 39000.0, 38.5, 4095.595, 67.667 + 0.15, 39000.0, 39.0, 4189.475, -243.323 + 0.15, 39000.0, 39.5, 4286.167, -468.427 + 0.15, 39000.0, 40.0, 4387.5, -569.6 + 0.15, 39000.0, 40.5, 4504.993, -389.734 + 0.15, 39000.0, 41.0, 4626.906, -57.475 + 0.15, 39000.0, 41.5, 4751.191, 417.597 + 0.15, 39000.0, 42.0, 4875.8, 1025.9 + 0.15, 39000.0, 42.5, 4986.375, 1921.26 + 0.15, 39000.0, 43.0, 5098.1, 2865.32 + 0.15, 39000.0, 43.5, 5213.85, 3783.15 + 0.15, 39000.0, 44.0, 5336.5, 4599.8 + 0.15, 39000.0, 44.5, 5497.788, 5133.92 + 0.15, 39000.0, 45.0, 5660.181, 5459.54 + 0.15, 39000.0, 45.5, 5815.009, 5544.3 + 0.15, 39000.0, 46.0, 5953.6, 5355.8 + 0.15, 39000.0, 46.5, 6017.832, 4490.23 + 0.15, 39000.0, 47.0, 6068.269, 3435.23 + 0.15, 39000.0, 47.5, 6116.021, 2307.02 + 0.15, 39000.0, 48.0, 6172.2, 1221.8 + 0.15, 39000.0, 48.5, 6247.916, 295.773 + 0.15, 39000.0, 49.0, 6354.281, -354.856 + 0.15, 39000.0, 49.5, 6502.405, -613.882 + 0.15, 39000.0, 50.0, 6703.4, -365.1 + 0.15, 43000.0, 0.0, 96.71265, 96.7127 + 0.15, 43000.0, 22.0, -422.6, 828.5 + 0.15, 43000.0, 22.5, -458.2318, 364.261 + 0.15, 43000.0, 23.0, -497.8078, -18.075 + 0.15, 43000.0, 23.5, -541.2049, -329.198 + 0.15, 43000.0, 24.0, -588.3, -579.8 + 0.15, 43000.0, 24.5, -638.9701, -780.57 + 0.15, 43000.0, 25.0, -693.0922, -942.2 + 0.15, 43000.0, 25.5, -750.5432, -1075.38 + 0.15, 43000.0, 26.0, -811.2, -1190.8 + 0.15, 43000.0, 26.5, -876.7758, -1414.37 + 0.15, 43000.0, 27.0, -945.4163, -1648.15 + 0.15, 43000.0, 27.5, -1016.684, -1883.08 + 0.15, 43000.0, 28.0, -1090.14, -2110.09 + 0.15, 43000.0, 28.5, -1165.348, -2320.11 + 0.15, 43000.0, 29.0, -1241.869, -2504.1 + 0.15, 43000.0, 29.5, -1319.265, -2652.98 + 0.15, 43000.0, 30.0, -1397.1, -2757.7 + 0.15, 43000.0, 30.5, -1471.804, -2701.95 + 0.15, 43000.0, 31.0, -1546.368, -2594.12 + 0.15, 43000.0, 31.5, -1620.653, -2435.37 + 0.15, 43000.0, 32.0, -1694.519, -2226.84 + 0.15, 43000.0, 32.5, -1767.826, -1969.7 + 0.15, 43000.0, 33.0, -1840.435, -1665.1 + 0.15, 43000.0, 33.5, -1912.206, -1314.18 + 0.15, 43000.0, 34.0, -1983.0, -918.1 + 0.15, 43000.0, 34.5, -2040.788, 186.205 + 0.15, 43000.0, 35.0, -2098.452, 1270.11 + 0.15, 43000.0, 35.5, -2156.983, 2269.2 + 0.15, 43000.0, 36.0, -2217.375, 3119.07 + 0.15, 43000.0, 36.5, -2280.62, 3755.31 + 0.15, 43000.0, 37.0, -2347.711, 4113.5 + 0.15, 43000.0, 37.5, -2419.64, 4129.23 + 0.15, 43000.0, 38.0, -2497.4, 3738.1 + 0.15, 43000.0, 38.5, -2606.521, 2070.7 + 0.15, 43000.0, 39.0, -2710.734, 285.017 + 0.15, 43000.0, 39.5, -2805.581, -1504.48 + 0.15, 43000.0, 40.0, -2886.6, -3183.3 + 0.15, 43000.0, 40.5, -2914.205, -4420.24 + 0.15, 43000.0, 41.0, -2933.112, -5404.26 + 0.15, 43000.0, 41.5, -2952.914, -6107.57 + 0.15, 43000.0, 42.0, -2983.2, -6502.4 + 0.15, 43000.0, 42.5, -3079.881, -6252.55 + 0.15, 43000.0, 43.0, -3187.7, -5762.02 + 0.15, 43000.0, 43.5, -3297.719, -5126.41 + 0.15, 43000.0, 44.0, -3401.0, -4441.3 + 0.15, 43000.0, 44.5, -3446.626, -3972.35 + 0.15, 43000.0, 45.0, -3484.431, -3577.05 + 0.15, 43000.0, 45.5, -3522.271, -3282.98 + 0.15, 43000.0, 46.0, -3568.0, -3117.7 + 0.15, 43000.0, 46.5, -3663.719, -3332.87 + 0.15, 43000.0, 47.0, -3769.338, -3642.33 + 0.15, 43000.0, 47.5, -3879.013, -3984.0 + 0.15, 43000.0, 48.0, -3986.9, -4295.8 + 0.15, 43000.0, 48.5, -4087.156, -4515.66 + 0.15, 43000.0, 49.0, -4173.938, -4581.52 + 0.15, 43000.0, 49.5, -4241.4, -4431.29 + 0.15, 43000.0, 50.0, -4283.7, -4002.9 + 0.15, 48000.0, 0.0, 76.05291, 76.0529 + 0.15, 48000.0, 22.0, -399.5, 693.7 + 0.15, 48000.0, 22.5, -392.3336, 317.013 + 0.15, 48000.0, 23.0, -401.1437, 11.7062 + 0.15, 48000.0, 23.5, -423.882, -231.979 + 0.15, 48000.0, 24.0, -458.5, -423.8 + 0.15, 48000.0, 24.5, -502.9492, -573.515 + 0.15, 48000.0, 25.0, -555.1812, -690.881 + 0.15, 48000.0, 25.5, -613.1477, -785.657 + 0.15, 48000.0, 26.0, -674.8, -867.6 + 0.15, 48000.0, 26.5, -723.3174, -1051.38 + 0.15, 48000.0, 27.0, -770.5797, -1247.84 + 0.15, 48000.0, 27.5, -817.0709, -1448.74 + 0.15, 48000.0, 28.0, -863.275, -1645.88 + 0.15, 48000.0, 28.5, -909.676, -1831.0 + 0.15, 48000.0, 29.0, -956.7578, -1995.9 + 0.15, 48000.0, 29.5, -1005.004, -2132.34 + 0.15, 48000.0, 30.0, -1054.9, -2232.1 + 0.15, 48000.0, 30.5, -1116.862, -2184.95 + 0.15, 48000.0, 31.0, -1180.495, -2094.37 + 0.15, 48000.0, 31.5, -1245.337, -1961.86 + 0.15, 48000.0, 32.0, -1310.925, -1788.89 + 0.15, 48000.0, 32.5, -1376.797, -1576.97 + 0.15, 48000.0, 33.0, -1442.492, -1327.57 + 0.15, 48000.0, 33.5, -1507.547, -1042.19 + 0.15, 48000.0, 34.0, -1571.5, -722.3 + 0.15, 48000.0, 34.5, -1617.225, 138.203 + 0.15, 48000.0, 35.0, -1662.511, 981.887 + 0.15, 48000.0, 35.5, -1708.483, 1758.92 + 0.15, 48000.0, 36.0, -1756.265, 2419.48 + 0.15, 48000.0, 36.5, -1806.983, 2913.73 + 0.15, 48000.0, 37.0, -1861.762, 3191.83 + 0.15, 48000.0, 37.5, -1921.726, 3203.97 + 0.15, 48000.0, 38.0, -1988.0, 2900.3 + 0.15, 48000.0, 38.5, -2092.083, 1610.04 + 0.15, 48000.0, 39.0, -2188.977, 226.302 + 0.15, 48000.0, 39.5, -2273.057, -1162.77 + 0.15, 48000.0, 40.0, -2338.7, -2469.0 + 0.15, 48000.0, 40.5, -2333.652, -3441.91 + 0.15, 48000.0, 41.0, -2317.569, -4220.59 + 0.15, 48000.0, 41.5, -2303.476, -4781.83 + 0.15, 48000.0, 42.0, -2304.4, -5102.4 + 0.15, 48000.0, 42.5, -2393.2, -4915.98 + 0.15, 48000.0, 43.0, -2499.138, -4539.66 + 0.15, 48000.0, 43.5, -2611.306, -4047.47 + 0.15, 48000.0, 44.0, -2718.8, -3513.4 + 0.15, 48000.0, 44.5, -2770.337, -3137.85 + 0.15, 48000.0, 45.0, -2811.537, -2817.89 + 0.15, 48000.0, 45.5, -2847.644, -2576.99 + 0.15, 48000.0, 46.0, -2883.9, -2438.6 + 0.15, 48000.0, 46.5, -2941.761, -2611.49 + 0.15, 48000.0, 47.0, -3003.775, -2859.69 + 0.15, 48000.0, 47.5, -3068.702, -3132.55 + 0.15, 48000.0, 48.0, -3135.3, -3379.4 + 0.15, 48000.0, 48.5, -3202.33, -3549.59 + 0.15, 48000.0, 49.0, -3268.55, -3592.46 + 0.15, 48000.0, 49.5, -3332.72, -3457.35 + 0.15, 48000.0, 50.0, -3393.6, -3093.6 + 0.2, 0.0, 0.0, 528.8459, 528.846 + 0.2, 0.0, 22.0, 1569.6, 859.1 + 0.2, 0.0, 22.5, 1867.462, 945.823 + 0.2, 0.0, 23.0, 2162.269, 1031.78 + 0.2, 0.0, 23.5, 2455.041, 1117.37 + 0.2, 0.0, 24.0, 2746.8, 1203.0 + 0.2, 0.0, 24.5, 3038.565, 1289.06 + 0.2, 0.0, 25.0, 3331.356, 1375.94 + 0.2, 0.0, 25.5, 3626.195, 1464.06 + 0.2, 0.0, 26.0, 3924.1, 1553.8 + 0.2, 0.0, 26.5, 4236.812, 1649.85 + 0.2, 0.0, 27.0, 4555.244, 1748.57 + 0.2, 0.0, 27.5, 4878.579, 1849.62 + 0.2, 0.0, 28.0, 5206.0, 1952.66 + 0.2, 0.0, 28.5, 5536.69, 2057.37 + 0.2, 0.0, 29.0, 5869.831, 2163.4 + 0.2, 0.0, 29.5, 6204.607, 2270.43 + 0.2, 0.0, 30.0, 6540.2, 2378.1 + 0.2, 0.0, 30.5, 6867.213, 2482.4 + 0.2, 0.0, 31.0, 7194.225, 2587.04 + 0.2, 0.0, 31.5, 7521.238, 2692.03 + 0.2, 0.0, 32.0, 7848.25, 2797.37 + 0.2, 0.0, 32.5, 8175.263, 2903.1 + 0.2, 0.0, 33.0, 8502.275, 3009.22 + 0.2, 0.0, 33.5, 8829.288, 3115.75 + 0.2, 0.0, 34.0, 9156.3, 3222.7 + 0.2, 0.0, 34.5, 9483.316, 3330.94 + 0.2, 0.0, 35.0, 9810.331, 3439.55 + 0.2, 0.0, 35.5, 10137.35, 3548.47 + 0.2, 0.0, 36.0, 10464.36, 3657.63 + 0.2, 0.0, 36.5, 10791.37, 3766.97 + 0.2, 0.0, 37.0, 11118.38, 3876.43 + 0.2, 0.0, 37.5, 11445.39, 3985.92 + 0.2, 0.0, 38.0, 11772.4, 4095.4 + 0.2, 0.0, 38.5, 12099.4, 4204.96 + 0.2, 0.0, 39.0, 12426.4, 4314.29 + 0.2, 0.0, 39.5, 12753.4, 4423.27 + 0.2, 0.0, 40.0, 13080.4, 4531.8 + 0.2, 0.0, 40.5, 13407.4, 4638.86 + 0.2, 0.0, 41.0, 13734.39, 4745.64 + 0.2, 0.0, 41.5, 14061.39, 4852.4 + 0.2, 0.0, 42.0, 14388.4, 4959.4 + 0.2, 0.0, 42.5, 14715.17, 5067.96 + 0.2, 0.0, 43.0, 15042.04, 5176.89 + 0.2, 0.0, 43.5, 15369.12, 5286.02 + 0.2, 0.0, 44.0, 15696.5, 5395.2 + 0.2, 0.0, 44.5, 16025.31, 5503.94 + 0.2, 0.0, 45.0, 16354.21, 5612.57 + 0.2, 0.0, 45.5, 16682.91, 5721.06 + 0.2, 0.0, 46.0, 17011.1, 5829.4 + 0.2, 0.0, 46.5, 17336.94, 5936.82 + 0.2, 0.0, 47.0, 17662.26, 6044.35 + 0.2, 0.0, 47.5, 17987.38, 6152.28 + 0.2, 0.0, 48.0, 18312.6, 6260.9 + 0.2, 0.0, 48.5, 18638.23, 6370.49 + 0.2, 0.0, 49.0, 18964.56, 6481.32 + 0.2, 0.0, 49.5, 19291.92, 6593.7 + 0.2, 0.0, 50.0, 19620.6, 6707.9 + 0.2, 2000.0, 0.0, 495.1424, 495.142 + 0.2, 2000.0, 22.0, 1515.4, 815.3 + 0.2, 2000.0, 22.5, 1802.962, 899.463 + 0.2, 2000.0, 23.0, 2087.577, 982.544 + 0.2, 2000.0, 23.5, 2370.228, 1064.98 + 0.2, 2000.0, 24.0, 2651.9, 1147.2 + 0.2, 2000.0, 24.5, 2933.579, 1229.65 + 0.2, 2000.0, 25.0, 3216.248, 1312.76 + 0.2, 2000.0, 25.5, 3500.894, 1396.96 + 0.2, 2000.0, 26.0, 3788.5, 1482.7 + 0.2, 2000.0, 26.5, 4090.396, 1574.89 + 0.2, 2000.0, 27.0, 4397.812, 1669.75 + 0.2, 2000.0, 27.5, 4709.962, 1766.93 + 0.2, 2000.0, 28.0, 5026.055, 1866.11 + 0.2, 2000.0, 28.5, 5345.304, 1966.94 + 0.2, 2000.0, 29.0, 5666.92, 2069.11 + 0.2, 2000.0, 29.5, 5990.115, 2172.27 + 0.2, 2000.0, 30.0, 6314.1, 2276.1 + 0.2, 2000.0, 30.5, 6629.811, 2376.69 + 0.2, 2000.0, 31.0, 6945.523, 2477.62 + 0.2, 2000.0, 31.5, 7261.237, 2578.89 + 0.2, 2000.0, 32.0, 7576.95, 2680.51 + 0.2, 2000.0, 32.5, 7892.663, 2782.48 + 0.2, 2000.0, 33.0, 8208.377, 2884.82 + 0.2, 2000.0, 33.5, 8524.089, 2987.52 + 0.2, 2000.0, 34.0, 8839.8, 3090.6 + 0.2, 2000.0, 34.5, 9155.503, 3194.81 + 0.2, 2000.0, 35.0, 9471.205, 3299.34 + 0.2, 2000.0, 35.5, 9786.905, 3404.12 + 0.2, 2000.0, 36.0, 10102.61, 3509.08 + 0.2, 2000.0, 36.5, 10418.3, 3614.17 + 0.2, 2000.0, 37.0, 10734.0, 3719.31 + 0.2, 2000.0, 37.5, 11049.7, 3824.44 + 0.2, 2000.0, 38.0, 11365.4, 3929.5 + 0.2, 2000.0, 38.5, 11681.1, 4034.57 + 0.2, 2000.0, 39.0, 11996.8, 4139.37 + 0.2, 2000.0, 39.5, 12312.5, 4243.77 + 0.2, 2000.0, 40.0, 12628.2, 4347.7 + 0.2, 2000.0, 40.5, 12943.9, 4450.0 + 0.2, 2000.0, 41.0, 13259.59, 4552.03 + 0.2, 2000.0, 41.5, 13575.29, 4654.13 + 0.2, 2000.0, 42.0, 13891.0, 4756.6 + 0.2, 2000.0, 42.5, 14206.48, 4861.35 + 0.2, 2000.0, 43.0, 14522.06, 4966.49 + 0.2, 2000.0, 43.5, 14837.83, 5071.71 + 0.2, 2000.0, 44.0, 15153.9, 5176.7 + 0.2, 2000.0, 44.5, 15471.32, 5279.74 + 0.2, 2000.0, 45.0, 15788.84, 5382.49 + 0.2, 2000.0, 45.5, 16106.17, 5485.23 + 0.2, 2000.0, 46.0, 16423.0, 5588.2 + 0.2, 2000.0, 46.5, 16737.6, 5692.06 + 0.2, 2000.0, 47.0, 17051.7, 5796.51 + 0.2, 2000.0, 47.5, 17365.6, 5901.66 + 0.2, 2000.0, 48.0, 17679.6, 6007.6 + 0.2, 2000.0, 48.5, 17993.98, 6114.43 + 0.2, 2000.0, 49.0, 18309.02, 6222.26 + 0.2, 2000.0, 49.5, 18625.04, 6331.18 + 0.2, 2000.0, 50.0, 18942.3, 6441.3 + 0.2, 5000.0, 0.0, 447.7898, 447.79 + 0.2, 5000.0, 22.0, 1438.7, 754.4 + 0.2, 5000.0, 22.5, 1711.714, 834.858 + 0.2, 5000.0, 23.0, 1981.928, 913.862 + 0.2, 5000.0, 23.5, 2250.279, 991.886 + 0.2, 5000.0, 24.0, 2517.7, 1069.4 + 0.2, 5000.0, 24.5, 2785.128, 1146.88 + 0.2, 5000.0, 25.0, 3053.497, 1224.79 + 0.2, 5000.0, 25.5, 3323.743, 1303.6 + 0.2, 5000.0, 26.0, 3596.8, 1383.8 + 0.2, 5000.0, 26.5, 3883.43, 1470.41 + 0.2, 5000.0, 27.0, 4175.304, 1559.6 + 0.2, 5000.0, 27.5, 4471.672, 1651.06 + 0.2, 5000.0, 28.0, 4771.785, 1744.49 + 0.2, 5000.0, 28.5, 5074.894, 1839.57 + 0.2, 5000.0, 29.0, 5380.248, 1935.98 + 0.2, 5000.0, 29.5, 5687.1, 2033.43 + 0.2, 5000.0, 30.0, 5994.7, 2131.6 + 0.2, 5000.0, 30.5, 6294.428, 2227.11 + 0.2, 5000.0, 31.0, 6594.155, 2323.02 + 0.2, 5000.0, 31.5, 6893.881, 2419.3 + 0.2, 5000.0, 32.0, 7193.606, 2515.93 + 0.2, 5000.0, 32.5, 7493.33, 2612.89 + 0.2, 5000.0, 33.0, 7793.054, 2710.17 + 0.2, 5000.0, 33.5, 8092.777, 2807.75 + 0.2, 5000.0, 34.0, 8392.5, 2905.6 + 0.2, 5000.0, 34.5, 8692.218, 3004.67 + 0.2, 5000.0, 35.0, 8991.938, 3103.88 + 0.2, 5000.0, 35.5, 9291.658, 3203.14 + 0.2, 5000.0, 36.0, 9591.38, 3302.33 + 0.2, 5000.0, 36.5, 9891.105, 3401.34 + 0.2, 5000.0, 37.0, 10190.83, 3500.06 + 0.2, 5000.0, 37.5, 10490.56, 3598.38 + 0.2, 5000.0, 38.0, 10790.3, 3696.2 + 0.2, 5000.0, 38.5, 11090.05, 3792.0 + 0.2, 5000.0, 39.0, 11389.8, 3887.8 + 0.2, 5000.0, 39.5, 11689.55, 3983.8 + 0.2, 5000.0, 40.0, 11989.3, 4080.2 + 0.2, 5000.0, 40.5, 12289.03, 4178.36 + 0.2, 5000.0, 41.0, 12588.76, 4276.86 + 0.2, 5000.0, 41.5, 12888.48, 4375.43 + 0.2, 5000.0, 42.0, 13188.2, 4473.8 + 0.2, 5000.0, 42.5, 13487.69, 4570.49 + 0.2, 5000.0, 43.0, 13787.27, 4666.94 + 0.2, 5000.0, 43.5, 14087.04, 4763.37 + 0.2, 5000.0, 44.0, 14387.1, 4860.0 + 0.2, 5000.0, 44.5, 14688.49, 4957.51 + 0.2, 5000.0, 45.0, 14989.97, 5055.48 + 0.2, 5000.0, 45.5, 15291.27, 5153.96 + 0.2, 5000.0, 46.0, 15592.1, 5253.0 + 0.2, 5000.0, 46.5, 15890.75, 5352.6 + 0.2, 5000.0, 47.0, 16188.93, 5452.85 + 0.2, 5000.0, 47.5, 16486.92, 5553.8 + 0.2, 5000.0, 48.0, 16785.0, 5655.5 + 0.2, 5000.0, 48.5, 17083.46, 5758.01 + 0.2, 5000.0, 49.0, 17382.57, 5861.38 + 0.2, 5000.0, 49.5, 17682.62, 5965.65 + 0.2, 5000.0, 50.0, 17983.9, 6070.9 + 0.2, 10000.0, 0.0, 376.8791, 376.879 + 0.2, 10000.0, 22.0, 1308.0, 662.4 + 0.2, 10000.0, 22.5, 1556.253, 736.561 + 0.2, 10000.0, 23.0, 1801.953, 808.961 + 0.2, 10000.0, 23.5, 2045.952, 880.08 + 0.2, 10000.0, 24.0, 2289.1, 950.4 + 0.2, 10000.0, 24.5, 2532.248, 1020.4 + 0.2, 10000.0, 25.0, 2776.247, 1090.56 + 0.2, 10000.0, 25.5, 3021.947, 1161.37 + 0.2, 10000.0, 26.0, 3270.2, 1233.3 + 0.2, 10000.0, 26.5, 3530.786, 1311.15 + 0.2, 10000.0, 27.0, 3796.137, 1391.32 + 0.2, 10000.0, 27.5, 4065.571, 1473.57 + 0.2, 10000.0, 28.0, 4338.41, 1557.64 + 0.2, 10000.0, 28.5, 4613.972, 1643.26 + 0.2, 10000.0, 29.0, 4891.578, 1730.19 + 0.2, 10000.0, 29.5, 5170.547, 1818.15 + 0.2, 10000.0, 30.0, 5450.2, 1906.9 + 0.2, 10000.0, 30.5, 5722.72, 1994.28 + 0.2, 10000.0, 31.0, 5995.243, 2082.1 + 0.2, 10000.0, 31.5, 6267.768, 2170.29 + 0.2, 10000.0, 32.0, 6540.294, 2258.78 + 0.2, 10000.0, 32.5, 6812.821, 2347.48 + 0.2, 10000.0, 33.0, 7085.348, 2436.32 + 0.2, 10000.0, 33.5, 7357.874, 2525.22 + 0.2, 10000.0, 34.0, 7630.4, 2614.1 + 0.2, 10000.0, 34.5, 7902.912, 2702.03 + 0.2, 10000.0, 35.0, 8175.423, 2789.87 + 0.2, 10000.0, 35.5, 8447.934, 2877.62 + 0.2, 10000.0, 36.0, 8720.445, 2965.29 + 0.2, 10000.0, 36.5, 8992.956, 3052.87 + 0.2, 10000.0, 37.0, 9265.469, 3140.39 + 0.2, 10000.0, 37.5, 9537.983, 3227.83 + 0.2, 10000.0, 38.0, 9810.5, 3315.2 + 0.2, 10000.0, 38.5, 10083.03, 3402.64 + 0.2, 10000.0, 39.0, 10355.56, 3489.96 + 0.2, 10000.0, 39.5, 10628.08, 3577.12 + 0.2, 10000.0, 40.0, 10900.6, 3664.1 + 0.2, 10000.0, 40.5, 11173.11, 3750.26 + 0.2, 10000.0, 41.0, 11445.61, 3836.43 + 0.2, 10000.0, 41.5, 11718.1, 3922.84 + 0.2, 10000.0, 42.0, 11990.6, 4009.7 + 0.2, 10000.0, 42.5, 12262.89, 4097.81 + 0.2, 10000.0, 43.0, 12535.26, 4186.59 + 0.2, 10000.0, 43.5, 12807.8, 4276.03 + 0.2, 10000.0, 44.0, 13080.6, 4366.1 + 0.2, 10000.0, 44.5, 13354.6, 4456.94 + 0.2, 10000.0, 45.0, 13628.68, 4548.34 + 0.2, 10000.0, 45.5, 13902.6, 4640.25 + 0.2, 10000.0, 46.0, 14176.1, 4732.6 + 0.2, 10000.0, 46.5, 14447.66, 4824.63 + 0.2, 10000.0, 47.0, 14718.79, 4917.24 + 0.2, 10000.0, 47.5, 14989.76, 5010.66 + 0.2, 10000.0, 48.0, 15260.8, 5105.1 + 0.2, 10000.0, 48.5, 15532.17, 5200.77 + 0.2, 10000.0, 49.0, 15804.13, 5297.88 + 0.2, 10000.0, 49.5, 16076.92, 5396.65 + 0.2, 10000.0, 50.0, 16350.8, 5497.3 + 0.2, 15000.0, 0.0, 315.1439, 315.144 + 0.2, 15000.0, 22.0, -472.5, 20.0 + 0.2, 15000.0, 22.5, -562.4891, -20.5805 + 0.2, 15000.0, 23.0, -651.4375, -58.3312 + 0.2, 15000.0, 23.5, -739.6672, -93.9164 + 0.2, 15000.0, 24.0, -827.5, -128.0 + 0.2, 15000.0, 24.5, -915.2578, -161.246 + 0.2, 15000.0, 25.0, -1003.262, -194.319 + 0.2, 15000.0, 25.5, -1091.836, -227.882 + 0.2, 15000.0, 26.0, -1181.3, -262.6 + 0.2, 15000.0, 26.5, -1275.258, -301.413 + 0.2, 15000.0, 27.0, -1370.937, -342.839 + 0.2, 15000.0, 27.5, -1468.098, -387.152 + 0.2, 15000.0, 28.0, -1566.5, -434.625 + 0.2, 15000.0, 28.5, -1665.902, -485.533 + 0.2, 15000.0, 29.0, -1766.062, -540.148 + 0.2, 15000.0, 29.5, -1866.742, -598.746 + 0.2, 15000.0, 30.0, -1967.7, -661.6 + 0.2, 15000.0, 30.5, -2066.267, -746.448 + 0.2, 15000.0, 31.0, -2164.863, -834.436 + 0.2, 15000.0, 31.5, -2263.477, -924.175 + 0.2, 15000.0, 32.0, -2362.1, -1014.28 + 0.2, 15000.0, 32.5, -2460.723, -1103.35 + 0.2, 15000.0, 33.0, -2559.338, -1190.0 + 0.2, 15000.0, 33.5, -2657.933, -1272.85 + 0.2, 15000.0, 34.0, -2756.5, -1350.5 + 0.2, 15000.0, 34.5, -2854.688, -1383.59 + 0.2, 15000.0, 35.0, -2952.862, -1412.32 + 0.2, 15000.0, 35.5, -3051.045, -1438.92 + 0.2, 15000.0, 36.0, -3149.26, -1465.61 + 0.2, 15000.0, 36.5, -3247.53, -1494.63 + 0.2, 15000.0, 37.0, -3345.877, -1528.2 + 0.2, 15000.0, 37.5, -3444.327, -1568.55 + 0.2, 15000.0, 38.0, -3542.9, -1617.9 + 0.2, 15000.0, 38.5, -3641.955, -1692.81 + 0.2, 15000.0, 39.0, -3741.008, -1773.75 + 0.2, 15000.0, 39.5, -3840.006, -1859.77 + 0.2, 15000.0, 40.0, -3938.9, -1949.9 + 0.2, 15000.0, 40.5, -4037.435, -2039.57 + 0.2, 15000.0, 41.0, -4135.844, -2132.89 + 0.2, 15000.0, 41.5, -4234.155, -2230.37 + 0.2, 15000.0, 42.0, -4332.4, -2332.5 + 0.2, 15000.0, 42.5, -4430.576, -2448.95 + 0.2, 15000.0, 43.0, -4528.756, -2567.37 + 0.2, 15000.0, 43.5, -4626.984, -2684.58 + 0.2, 15000.0, 44.0, -4725.3, -2797.4 + 0.2, 15000.0, 44.5, -4824.134, -2883.78 + 0.2, 15000.0, 45.0, -4922.988, -2966.96 + 0.2, 15000.0, 45.5, -5021.747, -3051.31 + 0.2, 15000.0, 46.0, -5120.3, -3141.2 + 0.2, 15000.0, 46.5, -5217.898, -3253.86 + 0.2, 15000.0, 47.0, -5315.319, -3375.65 + 0.2, 15000.0, 47.5, -5412.705, -3505.79 + 0.2, 15000.0, 48.0, -5510.2, -3643.5 + 0.2, 15000.0, 48.5, -5607.945, -3788.0 + 0.2, 15000.0, 49.0, -5706.081, -3938.52 + 0.2, 15000.0, 49.5, -5804.752, -4094.28 + 0.2, 15000.0, 50.0, -5904.1, -4254.5 + 0.2, 20000.0, 0.0, 261.6861, 261.686 + 0.2, 20000.0, 22.0, 878.7, 425.1 + 0.2, 20000.0, 22.5, 1049.916, 543.925 + 0.2, 20000.0, 23.0, 1218.344, 628.561 + 0.2, 20000.0, 23.5, 1384.724, 684.266 + 0.2, 20000.0, 24.0, 1549.8, 716.3 + 0.2, 20000.0, 24.5, 1714.313, 729.921 + 0.2, 20000.0, 25.0, 1879.006, 730.389 + 0.2, 20000.0, 25.5, 2044.621, 722.962 + 0.2, 20000.0, 26.0, 2211.9, 712.9 + 0.2, 20000.0, 26.5, 2389.22, 744.76 + 0.2, 20000.0, 27.0, 2570.124, 786.747 + 0.2, 20000.0, 27.5, 2754.046, 837.385 + 0.2, 20000.0, 28.0, 2940.42, 895.195 + 0.2, 20000.0, 28.5, 3128.679, 958.699 + 0.2, 20000.0, 29.0, 3318.256, 1026.42 + 0.2, 20000.0, 29.5, 3508.585, 1096.88 + 0.2, 20000.0, 30.0, 3699.1, 1168.6 + 0.2, 20000.0, 30.5, 3882.212, 1218.16 + 0.2, 20000.0, 31.0, 4065.045, 1268.12 + 0.2, 20000.0, 31.5, 4247.7, 1319.09 + 0.2, 20000.0, 32.0, 4430.281, 1371.67 + 0.2, 20000.0, 32.5, 4612.89, 1426.48 + 0.2, 20000.0, 33.0, 4795.627, 1484.13 + 0.2, 20000.0, 33.5, 4978.597, 1545.23 + 0.2, 20000.0, 34.0, 5161.9, 1610.4 + 0.2, 20000.0, 34.5, 5348.524, 1725.85 + 0.2, 20000.0, 35.0, 5535.411, 1842.24 + 0.2, 20000.0, 35.5, 5722.389, 1955.84 + 0.2, 20000.0, 36.0, 5909.285, 2062.92 + 0.2, 20000.0, 36.5, 6095.927, 2159.75 + 0.2, 20000.0, 37.0, 6282.142, 2242.59 + 0.2, 20000.0, 37.5, 6467.757, 2307.72 + 0.2, 20000.0, 38.0, 6652.6, 2351.4 + 0.2, 20000.0, 38.5, 6834.676, 2318.69 + 0.2, 20000.0, 39.0, 7016.58, 2283.63 + 0.2, 20000.0, 39.5, 7198.544, 2253.85 + 0.2, 20000.0, 40.0, 7380.8, 2237.0 + 0.2, 20000.0, 40.5, 7564.545, 2265.88 + 0.2, 20000.0, 41.0, 7748.662, 2312.93 + 0.2, 20000.0, 41.5, 7932.998, 2375.74 + 0.2, 20000.0, 42.0, 8117.4, 2451.9 + 0.2, 20000.0, 42.5, 8301.284, 2535.9 + 0.2, 20000.0, 43.0, 8485.1, 2629.68 + 0.2, 20000.0, 43.5, 8668.866, 2732.07 + 0.2, 20000.0, 44.0, 8852.6, 2841.9 + 0.2, 20000.0, 44.5, 9036.041, 2964.52 + 0.2, 20000.0, 45.0, 9219.6, 3089.64 + 0.2, 20000.0, 45.5, 9403.409, 3213.49 + 0.2, 20000.0, 46.0, 9587.6, 3332.3 + 0.2, 20000.0, 46.5, 9773.127, 3430.02 + 0.2, 20000.0, 47.0, 9958.969, 3520.06 + 0.2, 20000.0, 47.5, 10144.93, 3603.54 + 0.2, 20000.0, 48.0, 10330.8, 3681.6 + 0.2, 20000.0, 48.5, 10516.39, 3755.36 + 0.2, 20000.0, 49.0, 10701.51, 3825.96 + 0.2, 20000.0, 49.5, 10885.94, 3894.53 + 0.2, 20000.0, 50.0, 11069.5, 3962.2 + 0.2, 25000.0, 0.0, 215.6593, 215.659 + 0.2, 25000.0, 22.0, 619.7, 473.6 + 0.2, 25000.0, 22.5, 744.2455, 316.788 + 0.2, 25000.0, 23.0, 865.9359, 243.983 + 0.2, 25000.0, 23.5, 985.4334, 242.011 + 0.2, 25000.0, 24.0, 1103.4, 297.7 + 0.2, 25000.0, 24.5, 1220.498, 397.876 + 0.2, 25000.0, 25.0, 1337.389, 529.367 + 0.2, 25000.0, 25.5, 1454.736, 678.999 + 0.2, 25000.0, 26.0, 1573.2, 833.6 + 0.2, 25000.0, 26.5, 1700.019, 871.408 + 0.2, 25000.0, 27.0, 1829.655, 881.634 + 0.2, 25000.0, 27.5, 1961.644, 869.719 + 0.2, 25000.0, 28.0, 2095.52, 841.105 + 0.2, 25000.0, 28.5, 2230.819, 801.234 + 0.2, 25000.0, 29.0, 2367.075, 755.548 + 0.2, 25000.0, 29.5, 2503.824, 709.49 + 0.2, 25000.0, 30.0, 2640.6, 668.5 + 0.2, 25000.0, 30.5, 2771.193, 714.123 + 0.2, 25000.0, 31.0, 2901.43, 768.452 + 0.2, 25000.0, 31.5, 3031.395, 829.679 + 0.2, 25000.0, 32.0, 3161.169, 896.0 + 0.2, 25000.0, 32.5, 3290.834, 965.608 + 0.2, 25000.0, 33.0, 3420.473, 1036.7 + 0.2, 25000.0, 33.5, 3550.167, 1107.46 + 0.2, 25000.0, 34.0, 3680.0, 1176.1 + 0.2, 25000.0, 34.5, 3811.726, 1168.33 + 0.2, 25000.0, 35.0, 3943.595, 1161.73 + 0.2, 25000.0, 35.5, 4075.531, 1161.38 + 0.2, 25000.0, 36.0, 4207.455, 1172.37 + 0.2, 25000.0, 36.5, 4339.291, 1199.82 + 0.2, 25000.0, 37.0, 4470.962, 1248.81 + 0.2, 25000.0, 37.5, 4602.391, 1324.44 + 0.2, 25000.0, 38.0, 4733.5, 1431.8 + 0.2, 25000.0, 38.5, 4862.431, 1695.53 + 0.2, 25000.0, 39.0, 4991.812, 1939.21 + 0.2, 25000.0, 39.5, 5121.962, 2141.35 + 0.2, 25000.0, 40.0, 5253.2, 2280.5 + 0.2, 25000.0, 40.5, 5388.648, 2220.07 + 0.2, 25000.0, 41.0, 5524.7, 2099.74 + 0.2, 25000.0, 41.5, 5660.552, 1944.09 + 0.2, 25000.0, 42.0, 5795.4, 1777.7 + 0.2, 25000.0, 42.5, 5923.798, 1676.25 + 0.2, 25000.0, 43.0, 6051.444, 1592.77 + 0.2, 25000.0, 43.5, 6179.393, 1531.37 + 0.2, 25000.0, 44.0, 6308.7, 1496.2 + 0.2, 25000.0, 44.5, 6446.611, 1518.52 + 0.2, 25000.0, 45.0, 6585.513, 1564.47 + 0.2, 25000.0, 45.5, 6723.983, 1627.3 + 0.2, 25000.0, 46.0, 6860.6, 1700.3 + 0.2, 25000.0, 46.5, 6987.141, 1738.44 + 0.2, 25000.0, 47.0, 7111.706, 1788.6 + 0.2, 25000.0, 47.5, 7235.593, 1859.36 + 0.2, 25000.0, 48.0, 7360.1, 1959.3 + 0.2, 25000.0, 48.5, 7486.526, 2097.01 + 0.2, 25000.0, 49.0, 7616.169, 2281.08 + 0.2, 25000.0, 49.5, 7750.327, 2520.08 + 0.2, 25000.0, 50.0, 7890.3, 2822.6 + 0.2, 30000.0, 0.0, 176.2762, 176.276 + 0.2, 30000.0, 22.0, 272.4, 197.6 + 0.2, 30000.0, 22.5, 320.4291, 299.039 + 0.2, 30000.0, 23.0, 369.3797, 340.25 + 0.2, 30000.0, 23.5, 419.2654, 332.086 + 0.2, 30000.0, 24.0, 470.1, 285.4 + 0.2, 30000.0, 24.5, 521.8971, 211.045 + 0.2, 30000.0, 25.0, 574.6703, 119.875 + 0.2, 30000.0, 25.5, 628.4334, 22.7422 + 0.2, 30000.0, 26.0, 683.2, -69.5 + 0.2, 30000.0, 26.5, 740.2484, -38.0672 + 0.2, 30000.0, 27.0, 798.4, 26.13 + 0.2, 30000.0, 27.5, 857.4516, 115.442 + 0.2, 30000.0, 28.0, 917.2, 222.22 + 0.2, 30000.0, 28.5, 977.4422, 338.814 + 0.2, 30000.0, 29.0, 1037.975, 457.575 + 0.2, 30000.0, 29.5, 1098.595, 570.853 + 0.2, 30000.0, 30.0, 1159.1, 671.0 + 0.2, 30000.0, 30.5, 1216.563, 629.751 + 0.2, 30000.0, 31.0, 1273.763, 571.559 + 0.2, 30000.0, 31.5, 1330.756, 500.26 + 0.2, 30000.0, 32.0, 1387.6, 419.694 + 0.2, 30000.0, 32.5, 1444.35, 333.697 + 0.2, 30000.0, 33.0, 1501.063, 246.107 + 0.2, 30000.0, 33.5, 1557.794, 160.762 + 0.2, 30000.0, 34.0, 1614.6, 81.5 + 0.2, 30000.0, 34.5, 1674.445, 45.4771 + 0.2, 30000.0, 35.0, 1734.2, 20.0391 + 0.2, 30000.0, 35.5, 1793.645, 5.8502 + 0.2, 30000.0, 36.0, 1852.56, 3.575 + 0.2, 30000.0, 36.5, 1910.723, 13.8779 + 0.2, 30000.0, 37.0, 1967.915, 37.4234 + 0.2, 30000.0, 37.5, 2023.914, 74.876 + 0.2, 30000.0, 38.0, 2078.5, 126.9 + 0.2, 30000.0, 38.5, 2125.748, 244.405 + 0.2, 30000.0, 39.0, 2174.1, 351.758 + 0.2, 30000.0, 39.5, 2224.602, 438.456 + 0.2, 30000.0, 40.0, 2278.3, 494.0 + 0.2, 30000.0, 40.5, 2343.074, 457.752 + 0.2, 30000.0, 41.0, 2410.406, 389.4 + 0.2, 30000.0, 41.5, 2478.61, 298.498 + 0.2, 30000.0, 42.0, 2546.0, 194.6 + 0.2, 30000.0, 42.5, 2605.933, 26.3281 + 0.2, 30000.0, 43.0, 2663.662, -111.462 + 0.2, 30000.0, 43.5, 2719.486, -184.847 + 0.2, 30000.0, 44.0, 2773.7, -159.9 + 0.2, 30000.0, 44.5, 2825.973, 233.346 + 0.2, 30000.0, 45.0, 2877.481, 698.356 + 0.2, 30000.0, 45.5, 2928.774, 1174.64 + 0.2, 30000.0, 46.0, 2980.4, 1601.7 + 0.2, 30000.0, 46.5, 3033.899, 1750.03 + 0.2, 30000.0, 47.0, 3088.431, 1795.76 + 0.2, 30000.0, 47.5, 3144.148, 1746.01 + 0.2, 30000.0, 48.0, 3201.2, 1607.9 + 0.2, 30000.0, 48.5, 3259.74, 1388.54 + 0.2, 30000.0, 49.0, 3319.919, 1095.04 + 0.2, 30000.0, 49.5, 3381.888, 734.52 + 0.2, 30000.0, 50.0, 3445.8, 314.1 + 0.2, 35000.0, 0.0, 142.8038, 142.804 + 0.2, 35000.0, 22.0, 634.4, 162.9 + 0.2, 35000.0, 22.5, 771.2105, 136.273 + 0.2, 35000.0, 23.0, 902.5656, 159.406 + 0.2, 35000.0, 23.5, 1029.388, 222.962 + 0.2, 35000.0, 24.0, 1152.6, 317.6 + 0.2, 35000.0, 24.5, 1273.125, 433.982 + 0.2, 35000.0, 25.0, 1391.884, 562.769 + 0.2, 35000.0, 25.5, 1509.802, 694.621 + 0.2, 35000.0, 26.0, 1627.8, 820.2 + 0.2, 35000.0, 26.5, 1753.548, 833.226 + 0.2, 35000.0, 27.0, 1881.608, 815.761 + 0.2, 35000.0, 27.5, 2011.745, 775.084 + 0.2, 35000.0, 28.0, 2143.725, 718.475 + 0.2, 35000.0, 28.5, 2277.315, 653.213 + 0.2, 35000.0, 29.0, 2412.28, 586.577 + 0.2, 35000.0, 29.5, 2548.386, 525.846 + 0.2, 35000.0, 30.0, 2685.4, 478.3 + 0.2, 35000.0, 30.5, 2822.306, 592.511 + 0.2, 35000.0, 31.0, 2959.726, 721.009 + 0.2, 35000.0, 31.5, 3097.5, 857.616 + 0.2, 35000.0, 32.0, 3235.469, 996.156 + 0.2, 35000.0, 32.5, 3373.473, 1130.45 + 0.2, 35000.0, 33.0, 3511.352, 1254.33 + 0.2, 35000.0, 33.5, 3648.948, 1361.6 + 0.2, 35000.0, 34.0, 3786.1, 1446.1 + 0.2, 35000.0, 34.5, 3914.862, 1338.23 + 0.2, 35000.0, 35.0, 4043.603, 1210.8 + 0.2, 35000.0, 35.5, 4172.905, 1073.18 + 0.2, 35000.0, 36.0, 4303.35, 934.77 + 0.2, 35000.0, 36.5, 4435.52, 804.95 + 0.2, 35000.0, 37.0, 4569.997, 693.108 + 0.2, 35000.0, 37.5, 4707.363, 608.629 + 0.2, 35000.0, 38.0, 4848.2, 560.9 + 0.2, 35000.0, 38.5, 5004.101, 478.258 + 0.2, 35000.0, 39.0, 5158.928, 493.162 + 0.2, 35000.0, 39.5, 5310.816, 633.011 + 0.2, 35000.0, 40.0, 5457.9, 925.2 + 0.2, 35000.0, 40.5, 5587.294, 1684.41 + 0.2, 35000.0, 41.0, 5712.563, 2535.84 + 0.2, 35000.0, 41.5, 5836.25, 3391.98 + 0.2, 35000.0, 42.0, 5960.9, 4165.3 + 0.2, 35000.0, 42.5, 6099.736, 4589.29 + 0.2, 35000.0, 43.0, 6240.35, 4827.02 + 0.2, 35000.0, 43.5, 6381.014, 4862.6 + 0.2, 35000.0, 44.0, 6520.0, 4680.1 + 0.2, 35000.0, 44.5, 6646.338, 3936.07 + 0.2, 35000.0, 45.0, 6771.238, 3073.14 + 0.2, 35000.0, 45.5, 6896.669, 2206.42 + 0.2, 35000.0, 46.0, 7024.6, 1451.0 + 0.2, 35000.0, 46.5, 7166.32, 1333.46 + 0.2, 35000.0, 47.0, 7310.75, 1392.83 + 0.2, 35000.0, 47.5, 7456.13, 1579.64 + 0.2, 35000.0, 48.0, 7600.7, 1844.4 + 0.2, 35000.0, 48.5, 7742.702, 2137.62 + 0.2, 35000.0, 49.0, 7880.375, 2409.82 + 0.2, 35000.0, 49.5, 8011.961, 2611.51 + 0.2, 35000.0, 50.0, 8135.7, 2693.2 + 0.2, 39000.0, 0.0, 118.443, 118.443 + 0.2, 39000.0, 22.0, 454.9, -6.2 + 0.2, 39000.0, 22.5, 557.8459, -91.483 + 0.2, 39000.0, 23.0, 654.4453, -94.1359 + 0.2, 39000.0, 23.5, 745.8971, -28.7209 + 0.2, 39000.0, 24.0, 833.4, 90.2 + 0.2, 39000.0, 24.5, 918.1529, 248.065 + 0.2, 39000.0, 25.0, 1001.355, 430.311 + 0.2, 39000.0, 25.5, 1084.204, 622.377 + 0.2, 39000.0, 26.0, 1167.9, 809.7 + 0.2, 39000.0, 26.5, 1264.967, 851.12 + 0.2, 39000.0, 27.0, 1365.925, 851.438 + 0.2, 39000.0, 27.5, 1470.032, 817.797 + 0.2, 39000.0, 28.0, 1576.545, 757.335 + 0.2, 39000.0, 28.5, 1684.721, 677.194 + 0.2, 39000.0, 29.0, 1793.817, 584.514 + 0.2, 39000.0, 29.5, 1903.091, 486.436 + 0.2, 39000.0, 30.0, 2011.8, 390.1 + 0.2, 39000.0, 30.5, 2108.308, 391.58 + 0.2, 39000.0, 31.0, 2203.802, 400.614 + 0.2, 39000.0, 31.5, 2298.579, 415.872 + 0.2, 39000.0, 32.0, 2392.931, 436.025 + 0.2, 39000.0, 32.5, 2487.155, 459.744 + 0.2, 39000.0, 33.0, 2581.545, 485.698 + 0.2, 39000.0, 33.5, 2676.395, 512.56 + 0.2, 39000.0, 34.0, 2772.0, 539.0 + 0.2, 39000.0, 34.5, 2877.184, 594.064 + 0.2, 39000.0, 35.0, 2982.9, 643.155 + 0.2, 39000.0, 35.5, 3088.631, 682.049 + 0.2, 39000.0, 36.0, 3193.86, 706.525 + 0.2, 39000.0, 36.5, 3298.069, 712.36 + 0.2, 39000.0, 37.0, 3400.74, 695.333 + 0.2, 39000.0, 37.5, 3501.356, 651.22 + 0.2, 39000.0, 38.0, 3599.4, 575.8 + 0.2, 39000.0, 38.5, 3686.013, 320.506 + 0.2, 39000.0, 39.0, 3773.344, 100.305 + 0.2, 39000.0, 39.5, 3862.727, -56.9486 + 0.2, 39000.0, 40.0, 3955.5, -123.4 + 0.2, 39000.0, 40.5, 4060.056, 16.2023 + 0.2, 39000.0, 41.0, 4167.85, 267.356 + 0.2, 39000.0, 41.5, 4277.394, 622.957 + 0.2, 39000.0, 42.0, 4387.2, 1075.9 + 0.2, 39000.0, 42.5, 4486.871, 1738.51 + 0.2, 39000.0, 43.0, 4587.394, 2436.48 + 0.2, 39000.0, 43.5, 4690.845, 3114.93 + 0.2, 39000.0, 44.0, 4799.3, 3719.0 + 0.2, 39000.0, 44.5, 4935.802, 4116.83 + 0.2, 39000.0, 45.0, 5073.075, 4361.31 + 0.2, 39000.0, 45.5, 5204.811, 4428.36 + 0.2, 39000.0, 46.0, 5324.7, 4293.9 + 0.2, 39000.0, 46.5, 5390.374, 3658.28 + 0.2, 39000.0, 47.0, 5446.006, 2883.21 + 0.2, 39000.0, 47.5, 5499.71, 2054.84 + 0.2, 39000.0, 48.0, 5559.6, 1259.3 + 0.2, 39000.0, 48.5, 5633.79, 582.744 + 0.2, 39000.0, 49.0, 5730.394, 111.312 + 0.2, 39000.0, 49.5, 5857.526, -68.85 + 0.2, 39000.0, 50.0, 6023.3, 128.4 + 0.2, 43000.0, 0.0, 97.72711, 97.7271 + 0.2, 43000.0, 22.0, -268.1, 702.9 + 0.2, 43000.0, 22.5, -284.5752, 342.973 + 0.2, 43000.0, 23.0, -304.1859, 47.6125 + 0.2, 43000.0, 23.5, -326.8037, -191.58 + 0.2, 43000.0, 24.0, -352.3, -383.0 + 0.2, 43000.0, 24.5, -380.5463, -535.045 + 0.2, 43000.0, 25.0, -411.4141, -656.113 + 0.2, 43000.0, 25.5, -444.7748, -754.598 + 0.2, 43000.0, 26.0, -480.5, -838.9 + 0.2, 43000.0, 26.5, -519.518, -1007.17 + 0.2, 43000.0, 27.0, -560.7038, -1183.18 + 0.2, 43000.0, 27.5, -603.7477, -1359.93 + 0.2, 43000.0, 28.0, -648.34, -1530.45 + 0.2, 43000.0, 28.5, -694.1711, -1687.73 + 0.2, 43000.0, 29.0, -740.9312, -1824.8 + 0.2, 43000.0, 29.5, -788.3108, -1934.65 + 0.2, 43000.0, 30.0, -836.0, -2010.3 + 0.2, 43000.0, 30.5, -881.5859, -1961.49 + 0.2, 43000.0, 31.0, -927.0625, -1872.42 + 0.2, 43000.0, 31.5, -972.3203, -1744.05 + 0.2, 43000.0, 32.0, -1017.25, -1577.31 + 0.2, 43000.0, 32.5, -1061.742, -1373.15 + 0.2, 43000.0, 33.0, -1105.687, -1132.5 + 0.2, 43000.0, 33.5, -1148.977, -856.299 + 0.2, 43000.0, 34.0, -1191.5, -545.5 + 0.2, 43000.0, 34.5, -1223.879, 313.077 + 0.2, 43000.0, 35.0, -1256.156, 1155.41 + 0.2, 43000.0, 35.5, -1289.105, 1931.6 + 0.2, 43000.0, 36.0, -1323.5, 2591.74 + 0.2, 43000.0, 36.5, -1360.113, 3085.92 + 0.2, 43000.0, 37.0, -1399.719, 3364.25 + 0.2, 43000.0, 37.5, -1443.09, 3376.81 + 0.2, 43000.0, 38.0, -1491.0, 3073.7 + 0.2, 43000.0, 38.5, -1563.312, 1780.08 + 0.2, 43000.0, 39.0, -1631.812, 395.031 + 0.2, 43000.0, 39.5, -1693.031, -992.487 + 0.2, 43000.0, 40.0, -1743.5, -2293.5 + 0.2, 43000.0, 40.5, -1752.445, -3251.15 + 0.2, 43000.0, 41.0, -1754.625, -4011.51 + 0.2, 43000.0, 41.5, -1757.492, -4552.77 + 0.2, 43000.0, 42.0, -1768.5, -4853.1 + 0.2, 43000.0, 42.5, -1831.082, -4649.47 + 0.2, 43000.0, 43.0, -1902.319, -4257.78 + 0.2, 43000.0, 43.5, -1975.271, -3752.69 + 0.2, 43000.0, 44.0, -2043.0, -3208.9 + 0.2, 43000.0, 44.5, -2065.973, -2834.22 + 0.2, 43000.0, 45.0, -2082.881, -2516.92 + 0.2, 43000.0, 45.5, -2099.824, -2278.41 + 0.2, 43000.0, 46.0, -2122.9, -2140.1 + 0.2, 43000.0, 46.5, -2184.793, -2296.67 + 0.2, 43000.0, 47.0, -2254.381, -2526.95 + 0.2, 43000.0, 47.5, -2327.129, -2783.06 + 0.2, 43000.0, 48.0, -2398.5, -3017.1 + 0.2, 43000.0, 48.5, -2463.959, -3181.18 + 0.2, 43000.0, 49.0, -2518.969, -3227.4 + 0.2, 43000.0, 49.5, -2558.995, -3107.87 + 0.2, 43000.0, 50.0, -2579.5, -2774.7 + 0.2, 48000.0, 0.0, 76.85066, 76.8507 + 0.2, 48000.0, 22.0, -262.9, 585.8 + 0.2, 48000.0, 22.5, -248.4859, 293.611 + 0.2, 48000.0, 23.0, -246.5625, 57.6531 + 0.2, 48000.0, 23.5, -255.5078, -129.731 + 0.2, 48000.0, 24.0, -273.7, -276.2 + 0.2, 48000.0, 24.5, -299.5172, -389.413 + 0.2, 48000.0, 25.0, -331.3375, -477.028 + 0.2, 48000.0, 25.5, -367.5391, -546.704 + 0.2, 48000.0, 26.0, -406.5, -606.1 + 0.2, 48000.0, 26.5, -434.7832, -744.619 + 0.2, 48000.0, 27.0, -461.9069, -892.847 + 0.2, 48000.0, 27.5, -488.2746, -1044.43 + 0.2, 48000.0, 28.0, -514.29, -1193.01 + 0.2, 48000.0, 28.5, -540.3566, -1332.23 + 0.2, 48000.0, 29.0, -566.8781, -1455.74 + 0.2, 48000.0, 29.5, -594.258, -1557.18 + 0.2, 48000.0, 30.0, -622.9, -1630.2 + 0.2, 48000.0, 30.5, -661.2311, -1589.17 + 0.2, 48000.0, 31.0, -700.8672, -1514.56 + 0.2, 48000.0, 31.5, -741.4479, -1407.57 + 0.2, 48000.0, 32.0, -782.6125, -1269.38 + 0.2, 48000.0, 32.5, -824.0006, -1101.2 + 0.2, 48000.0, 33.0, -865.2516, -904.207 + 0.2, 48000.0, 33.5, -906.0049, -679.61 + 0.2, 48000.0, 34.0, -945.9, -428.6 + 0.2, 48000.0, 34.5, -971.6195, 240.42 + 0.2, 48000.0, 35.0, -996.9938, 896.056 + 0.2, 48000.0, 35.5, -1022.896, 1499.7 + 0.2, 48000.0, 36.0, -1050.2, 2012.76 + 0.2, 48000.0, 36.5, -1079.779, 2396.62 + 0.2, 48000.0, 37.0, -1112.506, 2612.68 + 0.2, 48000.0, 37.5, -1149.255, 2622.34 + 0.2, 48000.0, 38.0, -1190.9, 2387.0 + 0.2, 48000.0, 38.5, -1261.896, 1386.01 + 0.2, 48000.0, 39.0, -1327.306, 312.759 + 0.2, 48000.0, 39.5, -1382.763, -764.25 + 0.2, 48000.0, 40.0, -1423.9, -1776.5 + 0.2, 48000.0, 40.5, -1410.142, -2529.78 + 0.2, 48000.0, 41.0, -1387.813, -3131.55 + 0.2, 48000.0, 41.5, -1367.027, -3563.57 + 0.2, 48000.0, 42.0, -1357.9, -3807.6 + 0.2, 48000.0, 42.5, -1416.994, -3655.22 + 0.2, 48000.0, 43.0, -1489.4, -3354.46 + 0.2, 48000.0, 43.5, -1566.656, -2963.14 + 0.2, 48000.0, 44.0, -1640.3, -2539.1 + 0.2, 48000.0, 44.5, -1670.564, -2239.24 + 0.2, 48000.0, 45.0, -1692.812, -1982.72 + 0.2, 48000.0, 45.5, -1711.105, -1787.73 + 0.2, 48000.0, 46.0, -1729.5, -1672.5 + 0.2, 48000.0, 46.5, -1764.585, -1798.49 + 0.2, 48000.0, 47.0, -1802.881, -1983.35 + 0.2, 48000.0, 47.5, -1843.437, -2187.98 + 0.2, 48000.0, 48.0, -1885.3, -2373.3 + 0.2, 48000.0, 48.5, -1927.52, -2500.2 + 0.2, 48000.0, 49.0, -1969.144, -2529.6 + 0.2, 48000.0, 49.5, -2009.221, -2422.4 + 0.2, 48000.0, 50.0, -2046.8, -2139.5 + 0.25, 0.0, 0.0, 535.9603, 535.96 + 0.25, 0.0, 22.0, 1494.7, 903.1 + 0.25, 0.0, 22.5, 1778.413, 991.958 + 0.25, 0.0, 23.0, 2059.183, 1078.67 + 0.25, 0.0, 23.5, 2337.986, 1163.85 + 0.25, 0.0, 24.0, 2615.8, 1248.1 + 0.25, 0.0, 24.5, 2893.601, 1332.02 + 0.25, 0.0, 25.0, 3172.367, 1416.23 + 0.25, 0.0, 25.5, 3453.074, 1501.32 + 0.25, 0.0, 26.0, 3736.7, 1587.9 + 0.25, 0.0, 26.5, 4034.471, 1682.02 + 0.25, 0.0, 27.0, 4337.699, 1779.16 + 0.25, 0.0, 27.5, 4645.606, 1878.98 + 0.25, 0.0, 28.0, 4957.41, 1981.17 + 0.25, 0.0, 28.5, 5272.332, 2085.39 + 0.25, 0.0, 29.0, 5589.591, 2191.32 + 0.25, 0.0, 29.5, 5908.407, 2298.63 + 0.25, 0.0, 30.0, 6228.0, 2407.0 + 0.25, 0.0, 30.5, 6539.392, 2513.31 + 0.25, 0.0, 31.0, 6850.782, 2620.29 + 0.25, 0.0, 31.5, 7162.17, 2727.88 + 0.25, 0.0, 32.0, 7473.556, 2836.02 + 0.25, 0.0, 32.5, 7784.942, 2944.64 + 0.25, 0.0, 33.0, 8096.327, 3053.68 + 0.25, 0.0, 33.5, 8407.713, 3163.09 + 0.25, 0.0, 34.0, 8719.1, 3272.8 + 0.25, 0.0, 34.5, 9030.497, 3383.11 + 0.25, 0.0, 35.0, 9341.895, 3493.57 + 0.25, 0.0, 35.5, 9653.295, 3604.07 + 0.25, 0.0, 36.0, 9964.695, 3714.53 + 0.25, 0.0, 36.5, 10276.1, 3824.85 + 0.25, 0.0, 37.0, 10587.5, 3934.93 + 0.25, 0.0, 37.5, 10898.9, 4044.68 + 0.25, 0.0, 38.0, 11210.3, 4154.0 + 0.25, 0.0, 38.5, 11521.71, 4262.39 + 0.25, 0.0, 39.0, 11833.11, 4370.37 + 0.25, 0.0, 39.5, 12144.51, 4477.94 + 0.25, 0.0, 40.0, 12455.9, 4585.1 + 0.25, 0.0, 40.5, 12767.28, 4691.1 + 0.25, 0.0, 41.0, 13078.65, 4796.97 + 0.25, 0.0, 41.5, 13390.02, 4903.01 + 0.25, 0.0, 42.0, 13701.4, 5009.5 + 0.25, 0.0, 42.5, 14012.55, 5117.78 + 0.25, 0.0, 43.0, 14323.81, 5226.69 + 0.25, 0.0, 43.5, 14635.26, 5336.1 + 0.25, 0.0, 44.0, 14947.0, 5445.9 + 0.25, 0.0, 44.5, 15260.1, 5556.03 + 0.25, 0.0, 45.0, 15573.29, 5666.27 + 0.25, 0.0, 45.5, 15886.29, 5776.48 + 0.25, 0.0, 46.0, 16198.8, 5886.5 + 0.25, 0.0, 46.5, 16509.09, 5995.27 + 0.25, 0.0, 47.0, 16818.89, 6103.92 + 0.25, 0.0, 47.5, 17128.5, 6212.66 + 0.25, 0.0, 48.0, 17438.2, 6321.7 + 0.25, 0.0, 48.5, 17748.29, 6431.26 + 0.25, 0.0, 49.0, 18059.06, 6541.56 + 0.25, 0.0, 49.5, 18370.8, 6652.8 + 0.25, 0.0, 50.0, 18683.8, 6765.2 + 0.25, 2000.0, 0.0, 501.8034, 501.803 + 0.25, 2000.0, 22.0, 1443.5, 856.8 + 0.25, 2000.0, 22.5, 1717.439, 942.028 + 0.25, 2000.0, 23.0, 1988.559, 1025.19 + 0.25, 2000.0, 23.5, 2257.8, 1106.89 + 0.25, 2000.0, 24.0, 2526.1, 1187.7 + 0.25, 2000.0, 24.5, 2794.4, 1268.23 + 0.25, 2000.0, 25.0, 3063.641, 1349.06 + 0.25, 2000.0, 25.5, 3334.761, 1430.78 + 0.25, 2000.0, 26.0, 3608.7, 1514.0 + 0.25, 2000.0, 26.5, 3896.267, 1604.61 + 0.25, 2000.0, 27.0, 4189.098, 1698.2 + 0.25, 2000.0, 27.5, 4486.439, 1794.44 + 0.25, 2000.0, 28.0, 4787.54, 1893.02 + 0.25, 2000.0, 28.5, 5091.648, 1993.61 + 0.25, 2000.0, 29.0, 5398.013, 2095.91 + 0.25, 2000.0, 29.5, 5705.88, 2199.57 + 0.25, 2000.0, 30.0, 6014.5, 2304.3 + 0.25, 2000.0, 30.5, 6315.225, 2407.29 + 0.25, 2000.0, 31.0, 6615.95, 2510.94 + 0.25, 2000.0, 31.5, 6916.675, 2615.16 + 0.25, 2000.0, 32.0, 7217.4, 2719.86 + 0.25, 2000.0, 32.5, 7518.125, 2824.95 + 0.25, 2000.0, 33.0, 7818.85, 2930.37 + 0.25, 2000.0, 33.5, 8119.575, 3036.01 + 0.25, 2000.0, 34.0, 8420.3, 3141.8 + 0.25, 2000.0, 34.5, 8721.025, 3247.34 + 0.25, 2000.0, 35.0, 9021.75, 3352.89 + 0.25, 2000.0, 35.5, 9322.475, 3458.39 + 0.25, 2000.0, 36.0, 9623.2, 3563.79 + 0.25, 2000.0, 36.5, 9923.925, 3669.02 + 0.25, 2000.0, 37.0, 10224.65, 3774.04 + 0.25, 2000.0, 37.5, 10525.38, 3878.78 + 0.25, 2000.0, 38.0, 10826.1, 3983.2 + 0.25, 2000.0, 38.5, 11126.82, 4087.05 + 0.25, 2000.0, 39.0, 11427.55, 4190.56 + 0.25, 2000.0, 39.5, 11728.27, 4293.71 + 0.25, 2000.0, 40.0, 12029.0, 4396.5 + 0.25, 2000.0, 40.5, 12329.72, 4498.02 + 0.25, 2000.0, 41.0, 12630.45, 4599.51 + 0.25, 2000.0, 41.5, 12931.17, 4701.29 + 0.25, 2000.0, 42.0, 13231.9, 4803.7 + 0.25, 2000.0, 42.5, 13532.39, 4908.77 + 0.25, 2000.0, 43.0, 13832.97, 5014.48 + 0.25, 2000.0, 43.5, 14133.74, 5120.5 + 0.25, 2000.0, 44.0, 14434.8, 5226.5 + 0.25, 2000.0, 44.5, 14737.19, 5330.91 + 0.25, 2000.0, 45.0, 15039.68, 5435.13 + 0.25, 2000.0, 45.5, 15341.97, 5539.31 + 0.25, 2000.0, 46.0, 15643.8, 5643.6 + 0.25, 2000.0, 46.5, 15943.45, 5748.41 + 0.25, 2000.0, 47.0, 16242.63, 5853.56 + 0.25, 2000.0, 47.5, 16541.62, 5959.1 + 0.25, 2000.0, 48.0, 16840.7, 6065.1 + 0.25, 2000.0, 48.5, 17140.16, 6171.61 + 0.25, 2000.0, 49.0, 17440.27, 6278.69 + 0.25, 2000.0, 49.5, 17741.32, 6386.4 + 0.25, 2000.0, 50.0, 18043.6, 6494.8 + 0.25, 5000.0, 0.0, 453.8138, 453.814 + 0.25, 5000.0, 22.0, 1367.7, 983.4 + 0.25, 5000.0, 22.5, 1627.244, 1058.11 + 0.25, 5000.0, 23.0, 1884.114, 1156.24 + 0.25, 5000.0, 23.5, 2139.203, 1272.73 + 0.25, 5000.0, 24.0, 2393.4, 1402.5 + 0.25, 5000.0, 24.5, 2647.597, 1540.51 + 0.25, 5000.0, 25.0, 2902.686, 1681.68 + 0.25, 5000.0, 25.5, 3159.556, 1820.97 + 0.25, 5000.0, 26.0, 3419.1, 1953.3 + 0.25, 5000.0, 26.5, 3691.565, 2019.54 + 0.25, 5000.0, 27.0, 3969.019, 2065.62 + 0.25, 5000.0, 27.5, 4250.75, 2095.74 + 0.25, 5000.0, 28.0, 4536.045, 2114.13 + 0.25, 5000.0, 28.5, 4824.19, 2124.97 + 0.25, 5000.0, 29.0, 5114.473, 2132.49 + 0.25, 5000.0, 29.5, 5406.181, 2140.9 + 0.25, 5000.0, 30.0, 5698.6, 2154.4 + 0.25, 5000.0, 30.5, 5983.528, 2233.9 + 0.25, 5000.0, 31.0, 6268.455, 2321.51 + 0.25, 5000.0, 31.5, 6553.381, 2416.05 + 0.25, 5000.0, 32.0, 6838.306, 2516.33 + 0.25, 5000.0, 32.5, 7123.23, 2621.15 + 0.25, 5000.0, 33.0, 7408.154, 2729.33 + 0.25, 5000.0, 33.5, 7693.077, 2839.67 + 0.25, 5000.0, 34.0, 7978.0, 2951.0 + 0.25, 5000.0, 34.5, 8262.918, 3050.01 + 0.25, 5000.0, 35.0, 8547.838, 3148.78 + 0.25, 5000.0, 35.5, 8832.758, 3247.26 + 0.25, 5000.0, 36.0, 9117.68, 3345.42 + 0.25, 5000.0, 36.5, 9402.605, 3443.22 + 0.25, 5000.0, 37.0, 9687.533, 3540.62 + 0.25, 5000.0, 37.5, 9972.464, 3637.59 + 0.25, 5000.0, 38.0, 10257.4, 3734.1 + 0.25, 5000.0, 38.5, 10542.36, 3828.94 + 0.25, 5000.0, 39.0, 10827.31, 3923.84 + 0.25, 5000.0, 39.5, 11112.26, 4019.02 + 0.25, 5000.0, 40.0, 11397.2, 4114.7 + 0.25, 5000.0, 40.5, 11682.1, 4212.14 + 0.25, 5000.0, 41.0, 11967.0, 4310.09 + 0.25, 5000.0, 41.5, 12251.9, 4408.38 + 0.25, 5000.0, 42.0, 12536.8, 4506.8 + 0.25, 5000.0, 42.5, 12821.52, 4604.46 + 0.25, 5000.0, 43.0, 13106.34, 4702.14 + 0.25, 5000.0, 43.5, 13391.34, 4799.92 + 0.25, 5000.0, 44.0, 13676.6, 4897.9 + 0.25, 5000.0, 44.5, 13963.09, 4996.4 + 0.25, 5000.0, 45.0, 14249.66, 5095.16 + 0.25, 5000.0, 45.5, 14536.05, 5194.16 + 0.25, 5000.0, 46.0, 14822.0, 5293.4 + 0.25, 5000.0, 46.5, 15105.9, 5392.48 + 0.25, 5000.0, 47.0, 15389.36, 5491.91 + 0.25, 5000.0, 47.5, 15672.63, 5591.84 + 0.25, 5000.0, 48.0, 15956.0, 5692.4 + 0.25, 5000.0, 48.5, 16239.72, 5793.73 + 0.25, 5000.0, 49.0, 16524.07, 5895.96 + 0.25, 5000.0, 49.5, 16809.31, 5999.24 + 0.25, 5000.0, 50.0, 17095.7, 6103.7 + 0.25, 10000.0, 0.0, 381.9492, 381.949 + 0.25, 10000.0, 22.0, 1247.0, 694.8 + 0.25, 10000.0, 22.5, 1483.626, 767.46 + 0.25, 10000.0, 23.0, 1717.828, 838.494 + 0.25, 10000.0, 23.5, 1950.416, 908.38 + 0.25, 10000.0, 24.0, 2182.2, 977.6 + 0.25, 10000.0, 24.5, 2413.99, 1046.63 + 0.25, 10000.0, 25.0, 2646.597, 1115.96 + 0.25, 10000.0, 25.5, 2880.83, 1186.05 + 0.25, 10000.0, 26.0, 3117.5, 1257.4 + 0.25, 10000.0, 26.5, 3365.929, 1334.63 + 0.25, 10000.0, 27.0, 3618.901, 1414.31 + 0.25, 10000.0, 27.5, 3875.768, 1496.2 + 0.25, 10000.0, 28.0, 4135.88, 1580.08 + 0.25, 10000.0, 28.5, 4398.588, 1665.71 + 0.25, 10000.0, 29.0, 4663.244, 1752.86 + 0.25, 10000.0, 29.5, 4929.197, 1841.3 + 0.25, 10000.0, 30.0, 5195.8, 1930.8 + 0.25, 10000.0, 30.5, 5455.587, 2020.42 + 0.25, 10000.0, 31.0, 5715.375, 2110.69 + 0.25, 10000.0, 31.5, 5975.162, 2201.47 + 0.25, 10000.0, 32.0, 6234.95, 2292.57 + 0.25, 10000.0, 32.5, 6494.737, 2383.84 + 0.25, 10000.0, 33.0, 6754.525, 2475.11 + 0.25, 10000.0, 33.5, 7014.312, 2566.22 + 0.25, 10000.0, 34.0, 7274.1, 2657.0 + 0.25, 10000.0, 34.5, 7533.891, 2744.41 + 0.25, 10000.0, 35.0, 7793.681, 2831.45 + 0.25, 10000.0, 35.5, 8053.471, 2918.2 + 0.25, 10000.0, 36.0, 8313.26, 3004.8 + 0.25, 10000.0, 36.5, 8573.048, 3091.33 + 0.25, 10000.0, 37.0, 8832.834, 3177.92 + 0.25, 10000.0, 37.5, 9092.618, 3264.68 + 0.25, 10000.0, 38.0, 9352.4, 3351.7 + 0.25, 10000.0, 38.5, 9612.171, 3439.94 + 0.25, 10000.0, 39.0, 9871.944, 3528.24 + 0.25, 10000.0, 39.5, 10131.72, 3616.52 + 0.25, 10000.0, 40.0, 10391.5, 3704.7 + 0.25, 10000.0, 40.5, 10651.3, 3792.24 + 0.25, 10000.0, 41.0, 10911.1, 3879.72 + 0.25, 10000.0, 41.5, 11170.9, 3967.24 + 0.25, 10000.0, 42.0, 11430.7, 4054.9 + 0.25, 10000.0, 42.5, 11690.27, 4142.85 + 0.25, 10000.0, 43.0, 11949.92, 4231.15 + 0.25, 10000.0, 43.5, 12209.74, 4319.9 + 0.25, 10000.0, 44.0, 12469.8, 4409.2 + 0.25, 10000.0, 44.5, 12731.02, 4499.6 + 0.25, 10000.0, 45.0, 12992.32, 4590.55 + 0.25, 10000.0, 45.5, 13253.46, 4681.98 + 0.25, 10000.0, 46.0, 13514.2, 4773.8 + 0.25, 10000.0, 46.5, 13773.07, 4865.16 + 0.25, 10000.0, 47.0, 14031.52, 4957.05 + 0.25, 10000.0, 47.5, 14289.82, 5049.69 + 0.25, 10000.0, 48.0, 14548.2, 5143.3 + 0.25, 10000.0, 48.5, 14806.9, 5238.1 + 0.25, 10000.0, 49.0, 15066.17, 5334.32 + 0.25, 10000.0, 49.5, 15326.26, 5432.18 + 0.25, 10000.0, 50.0, 15587.4, 5531.9 + 0.25, 15000.0, 0.0, 319.3834, 319.383 + 0.25, 15000.0, 22.0, 665.1, 451.3 + 0.25, 15000.0, 22.5, 791.1873, 486.446 + 0.25, 15000.0, 23.0, 916.0141, 521.147 + 0.25, 15000.0, 23.5, 1040.009, 555.575 + 0.25, 15000.0, 24.0, 1163.6, 589.9 + 0.25, 15000.0, 24.5, 1287.216, 624.294 + 0.25, 15000.0, 25.0, 1411.286, 658.928 + 0.25, 15000.0, 25.5, 1536.238, 693.973 + 0.25, 15000.0, 26.0, 1662.5, 729.6 + 0.25, 15000.0, 26.5, 1795.032, 768.712 + 0.25, 15000.0, 27.0, 1929.991, 808.904 + 0.25, 15000.0, 27.5, 2067.028, 849.879 + 0.25, 15000.0, 28.0, 2205.795, 891.34 + 0.25, 15000.0, 28.5, 2345.944, 932.99 + 0.25, 15000.0, 29.0, 2487.127, 974.531 + 0.25, 15000.0, 29.5, 2628.995, 1015.67 + 0.25, 15000.0, 30.0, 2771.2, 1056.1 + 0.25, 15000.0, 30.5, 2909.71, 1088.44 + 0.25, 15000.0, 31.0, 3048.211, 1120.15 + 0.25, 15000.0, 31.5, 3186.707, 1151.63 + 0.25, 15000.0, 32.0, 3325.2, 1183.24 + 0.25, 15000.0, 32.5, 3463.693, 1215.36 + 0.25, 15000.0, 33.0, 3602.189, 1248.38 + 0.25, 15000.0, 33.5, 3740.69, 1282.66 + 0.25, 15000.0, 34.0, 3879.2, 1318.6 + 0.25, 15000.0, 34.5, 4017.822, 1368.13 + 0.25, 15000.0, 35.0, 4156.448, 1418.96 + 0.25, 15000.0, 35.5, 4295.072, 1470.37 + 0.25, 15000.0, 36.0, 4433.685, 1521.65 + 0.25, 15000.0, 36.5, 4572.281, 1572.06 + 0.25, 15000.0, 37.0, 4710.854, 1620.89 + 0.25, 15000.0, 37.5, 4849.396, 1667.41 + 0.25, 15000.0, 38.0, 4987.9, 1710.9 + 0.25, 15000.0, 38.5, 5126.256, 1745.74 + 0.25, 15000.0, 39.0, 5264.614, 1778.64 + 0.25, 15000.0, 39.5, 5402.99, 1809.97 + 0.25, 15000.0, 40.0, 5541.4, 1840.1 + 0.25, 15000.0, 40.5, 5679.927, 1870.45 + 0.25, 15000.0, 41.0, 5818.494, 1899.91 + 0.25, 15000.0, 41.5, 5957.088, 1928.41 + 0.25, 15000.0, 42.0, 6095.7, 1955.9 + 0.25, 15000.0, 42.5, 6234.185, 1979.71 + 0.25, 15000.0, 43.0, 6372.719, 2003.43 + 0.25, 15000.0, 43.5, 6511.343, 2028.03 + 0.25, 15000.0, 44.0, 6650.1, 2054.5 + 0.25, 15000.0, 44.5, 6789.454, 2089.45 + 0.25, 15000.0, 45.0, 6928.856, 2125.99 + 0.25, 15000.0, 45.5, 7068.18, 2162.83 + 0.25, 15000.0, 46.0, 7207.3, 2198.7 + 0.25, 15000.0, 46.5, 7345.475, 2228.14 + 0.25, 15000.0, 47.0, 7483.437, 2255.76 + 0.25, 15000.0, 47.5, 7621.306, 2281.94 + 0.25, 15000.0, 48.0, 7759.2, 2307.1 + 0.25, 15000.0, 48.5, 7897.237, 2331.64 + 0.25, 15000.0, 49.0, 8035.537, 2355.97 + 0.25, 15000.0, 49.5, 8174.219, 2380.49 + 0.25, 15000.0, 50.0, 8313.4, 2405.6 + 0.25, 20000.0, 0.0, 265.2065, 265.206 + 0.25, 20000.0, 22.0, 867.6, 472.7 + 0.25, 20000.0, 22.5, 1034.562, 557.94 + 0.25, 20000.0, 23.0, 1199.281, 625.245 + 0.25, 20000.0, 23.5, 1362.41, 677.428 + 0.25, 20000.0, 24.0, 1524.6, 717.3 + 0.25, 20000.0, 24.5, 1686.502, 747.672 + 0.25, 20000.0, 25.0, 1848.769, 771.355 + 0.25, 20000.0, 25.5, 2012.051, 791.16 + 0.25, 20000.0, 26.0, 2177.0, 809.9 + 0.25, 20000.0, 26.5, 2351.031, 851.456 + 0.25, 20000.0, 27.0, 2528.42, 898.773 + 0.25, 20000.0, 27.5, 2708.657, 951.049 + 0.25, 20000.0, 28.0, 2891.235, 1007.48 + 0.25, 20000.0, 28.5, 3075.646, 1067.28 + 0.25, 20000.0, 29.0, 3261.383, 1129.63 + 0.25, 20000.0, 29.5, 3447.937, 1193.74 + 0.25, 20000.0, 30.0, 3634.8, 1258.8 + 0.25, 20000.0, 30.5, 3815.57, 1312.13 + 0.25, 20000.0, 31.0, 3996.195, 1365.95 + 0.25, 20000.0, 31.5, 4176.729, 1420.59 + 0.25, 20000.0, 32.0, 4357.225, 1476.37 + 0.25, 20000.0, 32.5, 4537.737, 1533.64 + 0.25, 20000.0, 33.0, 4718.317, 1592.71 + 0.25, 20000.0, 33.5, 4899.021, 1653.92 + 0.25, 20000.0, 34.0, 5079.9, 1717.6 + 0.25, 20000.0, 34.5, 5262.53, 1809.26 + 0.25, 20000.0, 35.0, 5445.298, 1901.66 + 0.25, 20000.0, 35.5, 5628.114, 1992.73 + 0.25, 20000.0, 36.0, 5810.885, 2080.39 + 0.25, 20000.0, 36.5, 5993.521, 2162.59 + 0.25, 20000.0, 37.0, 6175.929, 2237.25 + 0.25, 20000.0, 37.5, 6358.019, 2302.31 + 0.25, 20000.0, 38.0, 6539.7, 2355.7 + 0.25, 20000.0, 38.5, 6719.912, 2367.55 + 0.25, 20000.0, 39.0, 6900.033, 2378.01 + 0.25, 20000.0, 39.5, 7080.188, 2391.19 + 0.25, 20000.0, 40.0, 7260.5, 2411.2 + 0.25, 20000.0, 40.5, 7441.614, 2455.49 + 0.25, 20000.0, 41.0, 7622.925, 2509.49 + 0.25, 20000.0, 41.5, 7804.348, 2571.97 + 0.25, 20000.0, 42.0, 7985.8, 2641.7 + 0.25, 20000.0, 42.5, 8166.883, 2715.68 + 0.25, 20000.0, 43.0, 8347.95, 2795.17 + 0.25, 20000.0, 43.5, 8529.042, 2879.65 + 0.25, 20000.0, 44.0, 8710.2, 2968.6 + 0.25, 20000.0, 44.5, 8891.593, 3065.21 + 0.25, 20000.0, 45.0, 9073.081, 3163.78 + 0.25, 20000.0, 45.5, 9254.654, 3262.31 + 0.25, 20000.0, 46.0, 9436.3, 3358.8 + 0.25, 20000.0, 46.5, 9618.048, 3444.62 + 0.25, 20000.0, 47.0, 9799.831, 3527.06 + 0.25, 20000.0, 47.5, 9981.624, 3606.76 + 0.25, 20000.0, 48.0, 10163.4, 3684.4 + 0.25, 20000.0, 48.5, 10345.13, 3760.62 + 0.25, 20000.0, 49.0, 10526.79, 3836.07 + 0.25, 20000.0, 49.5, 10708.36, 3911.41 + 0.25, 20000.0, 50.0, 10889.8, 3987.3 + 0.25, 25000.0, 0.0, 218.5605, 218.56 + 0.25, 25000.0, 22.0, 648.1, 461.5 + 0.25, 25000.0, 22.5, 775.1975, 384.085 + 0.25, 25000.0, 23.0, 900.0453, 356.584 + 0.25, 25000.0, 23.5, 1023.221, 371.217 + 0.25, 25000.0, 24.0, 1145.3, 420.2 + 0.25, 25000.0, 24.5, 1266.861, 495.752 + 0.25, 25000.0, 25.0, 1388.48, 590.091 + 0.25, 25000.0, 25.5, 1510.734, 695.434 + 0.25, 25000.0, 26.0, 1634.2, 804.0 + 0.25, 25000.0, 26.5, 1765.289, 844.03 + 0.25, 25000.0, 27.0, 1899.078, 868.064 + 0.25, 25000.0, 27.5, 2035.142, 879.285 + 0.25, 25000.0, 28.0, 2173.06, 880.88 + 0.25, 25000.0, 28.5, 2312.408, 876.034 + 0.25, 25000.0, 29.0, 2452.762, 867.931 + 0.25, 25000.0, 29.5, 2593.701, 859.758 + 0.25, 25000.0, 30.0, 2734.8, 854.7 + 0.25, 25000.0, 30.5, 2870.675, 900.464 + 0.25, 25000.0, 31.0, 3006.337, 951.473 + 0.25, 25000.0, 31.5, 3141.835, 1006.67 + 0.25, 25000.0, 32.0, 3277.219, 1065.01 + 0.25, 25000.0, 32.5, 3412.538, 1125.42 + 0.25, 25000.0, 33.0, 3547.841, 1186.86 + 0.25, 25000.0, 33.5, 3683.179, 1248.27 + 0.25, 25000.0, 34.0, 3818.6, 1308.6 + 0.25, 25000.0, 34.5, 3955.161, 1324.43 + 0.25, 25000.0, 35.0, 4091.808, 1341.09 + 0.25, 25000.0, 35.5, 4228.495, 1361.58 + 0.25, 25000.0, 36.0, 4365.175, 1388.87 + 0.25, 25000.0, 36.5, 4501.802, 1425.93 + 0.25, 25000.0, 37.0, 4638.33, 1475.76 + 0.25, 25000.0, 37.5, 4774.711, 1541.32 + 0.25, 25000.0, 38.0, 4910.9, 1625.6 + 0.25, 25000.0, 38.5, 5045.785, 1802.19 + 0.25, 25000.0, 39.0, 5180.936, 1966.85 + 0.25, 25000.0, 39.5, 5316.544, 2106.86 + 0.25, 25000.0, 40.0, 5452.8, 2209.5 + 0.25, 25000.0, 40.5, 5591.552, 2193.54 + 0.25, 25000.0, 41.0, 5730.669, 2142.21 + 0.25, 25000.0, 41.5, 5869.676, 2070.19 + 0.25, 25000.0, 42.0, 6008.1, 1992.2 + 0.25, 25000.0, 42.5, 6142.702, 1953.64 + 0.25, 25000.0, 43.0, 6276.881, 1926.21 + 0.25, 25000.0, 43.5, 6411.27, 1912.33 + 0.25, 25000.0, 44.0, 6546.5, 1914.4 + 0.25, 25000.0, 44.5, 6687.006, 1951.15 + 0.25, 25000.0, 45.0, 6828.1, 2002.16 + 0.25, 25000.0, 45.5, 6968.894, 2063.32 + 0.25, 25000.0, 46.0, 7108.5, 2130.5 + 0.25, 25000.0, 46.5, 7241.754, 2176.53 + 0.25, 25000.0, 47.0, 7373.756, 2229.6 + 0.25, 25000.0, 47.5, 7505.33, 2294.82 + 0.25, 25000.0, 48.0, 7637.3, 2377.3 + 0.25, 25000.0, 48.5, 7770.488, 2482.16 + 0.25, 25000.0, 49.0, 7905.719, 2614.53 + 0.25, 25000.0, 49.5, 8043.815, 2779.5 + 0.25, 25000.0, 50.0, 8185.6, 2982.2 + 0.25, 30000.0, 0.0, 178.6476, 178.648 + 0.25, 30000.0, 22.0, 353.1, 255.3 + 0.25, 30000.0, 22.5, 417.5057, 332.026 + 0.25, 30000.0, 23.0, 482.2672, 368.42 + 0.25, 30000.0, 23.5, 547.4951, 371.805 + 0.25, 30000.0, 24.0, 613.3, 349.5 + 0.25, 30000.0, 24.5, 679.7924, 308.826 + 0.25, 30000.0, 25.0, 747.0828, 257.105 + 0.25, 30000.0, 25.5, 815.2818, 201.656 + 0.25, 30000.0, 26.0, 884.5, 149.8 + 0.25, 30000.0, 26.5, 956.8016, 181.851 + 0.25, 30000.0, 27.0, 1030.455, 236.308 + 0.25, 30000.0, 27.5, 1105.236, 307.979 + 0.25, 30000.0, 28.0, 1180.92, 391.67 + 0.25, 30000.0, 28.5, 1257.283, 482.19 + 0.25, 30000.0, 29.0, 1334.1, 574.347 + 0.25, 30000.0, 29.5, 1411.147, 662.948 + 0.25, 30000.0, 30.0, 1488.2, 742.8 + 0.25, 30000.0, 30.5, 1562.276, 727.3 + 0.25, 30000.0, 31.0, 1636.172, 700.421 + 0.25, 30000.0, 31.5, 1709.925, 664.724 + 0.25, 30000.0, 32.0, 1783.575, 622.769 + 0.25, 30000.0, 32.5, 1857.159, 577.118 + 0.25, 30000.0, 33.0, 1930.716, 530.332 + 0.25, 30000.0, 33.5, 2004.283, 484.972 + 0.25, 30000.0, 34.0, 2077.9, 443.6 + 0.25, 30000.0, 34.5, 2153.565, 430.294 + 0.25, 30000.0, 35.0, 2229.169, 424.048 + 0.25, 30000.0, 35.5, 2304.563, 425.375 + 0.25, 30000.0, 36.0, 2379.6, 434.785 + 0.25, 30000.0, 36.5, 2454.13, 452.791 + 0.25, 30000.0, 37.0, 2528.006, 479.904 + 0.25, 30000.0, 37.5, 2601.079, 516.637 + 0.25, 30000.0, 38.0, 2673.2, 563.5 + 0.25, 30000.0, 38.5, 2740.361, 655.629 + 0.25, 30000.0, 39.0, 2808.275, 740.959 + 0.25, 30000.0, 39.5, 2877.652, 812.311 + 0.25, 30000.0, 40.0, 2949.2, 862.5 + 0.25, 30000.0, 40.5, 3028.27, 849.84 + 0.25, 30000.0, 41.0, 3109.075, 815.456 + 0.25, 30000.0, 41.5, 3190.467, 765.97 + 0.25, 30000.0, 42.0, 3271.3, 708.0 + 0.25, 30000.0, 42.5, 3347.036, 607.703 + 0.25, 30000.0, 43.0, 3421.275, 528.35 + 0.25, 30000.0, 43.5, 3494.227, 492.747 + 0.25, 30000.0, 44.0, 3566.1, 523.7 + 0.25, 30000.0, 44.5, 3636.734, 803.445 + 0.25, 30000.0, 45.0, 3706.856, 1131.59 + 0.25, 30000.0, 45.5, 3776.826, 1467.16 + 0.25, 30000.0, 46.0, 3847.0, 1769.2 + 0.25, 30000.0, 46.5, 3918.35, 1881.99 + 0.25, 30000.0, 47.0, 3990.375, 1925.22 + 0.25, 30000.0, 47.5, 4063.187, 1903.81 + 0.25, 30000.0, 48.0, 4136.9, 1822.7 + 0.25, 30000.0, 48.5, 4211.625, 1686.82 + 0.25, 30000.0, 49.0, 4287.475, 1501.11 + 0.25, 30000.0, 49.5, 4364.562, 1270.49 + 0.25, 30000.0, 50.0, 4443.0, 999.9 + 0.25, 35000.0, 0.0, 144.7249, 144.725 + 0.25, 35000.0, 22.0, 568.3, 212.6 + 0.25, 35000.0, 22.5, 687.8336, 197.345 + 0.25, 35000.0, 23.0, 803.2563, 218.641 + 0.25, 35000.0, 23.5, 915.3008, 269.691 + 0.25, 35000.0, 24.0, 1024.7, 343.7 + 0.25, 35000.0, 24.5, 1132.187, 433.871 + 0.25, 35000.0, 25.0, 1238.494, 533.409 + 0.25, 35000.0, 25.5, 1344.354, 635.518 + 0.25, 35000.0, 26.0, 1450.5, 733.4 + 0.25, 35000.0, 26.5, 1563.266, 750.086 + 0.25, 35000.0, 27.0, 1678.104, 744.943 + 0.25, 35000.0, 27.5, 1794.786, 723.207 + 0.25, 35000.0, 28.0, 1913.085, 690.11 + 0.25, 35000.0, 28.5, 2032.773, 650.887 + 0.25, 35000.0, 29.0, 2153.623, 610.772 + 0.25, 35000.0, 29.5, 2275.408, 574.998 + 0.25, 35000.0, 30.0, 2397.9, 548.8 + 0.25, 35000.0, 30.5, 2519.669, 638.696 + 0.25, 35000.0, 31.0, 2641.805, 738.99 + 0.25, 35000.0, 31.5, 2764.194, 845.268 + 0.25, 35000.0, 32.0, 2886.725, 953.119 + 0.25, 35000.0, 32.5, 3009.284, 1058.13 + 0.25, 35000.0, 33.0, 3131.758, 1155.89 + 0.25, 35000.0, 33.5, 3254.034, 1241.98 + 0.25, 35000.0, 34.0, 3376.0, 1312.0 + 0.25, 35000.0, 34.5, 3492.048, 1245.93 + 0.25, 35000.0, 35.0, 3608.083, 1165.96 + 0.25, 35000.0, 35.5, 3724.515, 1078.7 + 0.25, 35000.0, 36.0, 3841.755, 990.745 + 0.25, 35000.0, 36.5, 3960.213, 908.689 + 0.25, 35000.0, 37.0, 4080.3, 839.132 + 0.25, 35000.0, 37.5, 4202.425, 788.669 + 0.25, 35000.0, 38.0, 4327.0, 763.9 + 0.25, 35000.0, 38.5, 4462.214, 713.581 + 0.25, 35000.0, 39.0, 4596.664, 732.141 + 0.25, 35000.0, 39.5, 4729.032, 839.03 + 0.25, 35000.0, 40.0, 4858.0, 1053.7 + 0.25, 35000.0, 40.5, 4974.441, 1598.88 + 0.25, 35000.0, 41.0, 5087.969, 2209.44 + 0.25, 35000.0, 41.5, 5200.387, 2823.5 + 0.25, 35000.0, 42.0, 5313.5, 3379.2 + 0.25, 35000.0, 42.5, 5436.687, 3689.51 + 0.25, 35000.0, 43.0, 5561.15, 3867.81 + 0.25, 35000.0, 43.5, 5685.662, 3902.31 + 0.25, 35000.0, 44.0, 5809.0, 3781.2 + 0.25, 35000.0, 44.5, 5923.453, 3256.94 + 0.25, 35000.0, 45.0, 6036.875, 2647.79 + 0.25, 35000.0, 45.5, 6150.634, 2036.28 + 0.25, 35000.0, 46.0, 6266.1, 1504.9 + 0.25, 35000.0, 46.5, 6391.066, 1431.2 + 0.25, 35000.0, 47.0, 6517.906, 1484.64 + 0.25, 35000.0, 47.5, 6645.418, 1629.74 + 0.25, 35000.0, 48.0, 6772.4, 1831.0 + 0.25, 35000.0, 48.5, 6897.651, 2052.91 + 0.25, 35000.0, 49.0, 7019.969, 2259.98 + 0.25, 35000.0, 49.5, 7138.152, 2416.71 + 0.25, 35000.0, 50.0, 7251.0, 2487.6 + 0.25, 39000.0, 0.0, 120.0363, 120.036 + 0.25, 39000.0, 22.0, 417.2, 76.3 + 0.25, 39000.0, 22.5, 508.2869, 21.098 + 0.25, 39000.0, 23.0, 594.6547, 24.6781 + 0.25, 39000.0, 23.5, 677.2201, 76.6941 + 0.25, 39000.0, 24.0, 756.9, 166.8 + 0.25, 39000.0, 24.5, 834.6111, 284.65 + 0.25, 39000.0, 25.0, 911.2703, 419.897 + 0.25, 39000.0, 25.5, 987.7943, 562.196 + 0.25, 39000.0, 26.0, 1065.1, 701.2 + 0.25, 39000.0, 26.5, 1152.823, 736.653 + 0.25, 39000.0, 27.0, 1243.659, 742.982 + 0.25, 39000.0, 27.5, 1337.03, 725.254 + 0.25, 39000.0, 28.0, 1432.36, 688.535 + 0.25, 39000.0, 28.5, 1529.07, 637.893 + 0.25, 39000.0, 29.0, 1626.581, 578.395 + 0.25, 39000.0, 29.5, 1724.317, 515.109 + 0.25, 39000.0, 30.0, 1821.7, 453.1 + 0.25, 39000.0, 30.5, 1909.886, 460.422 + 0.25, 39000.0, 31.0, 1997.35, 473.157 + 0.25, 39000.0, 31.5, 2084.302, 490.375 + 0.25, 39000.0, 32.0, 2170.95, 511.144 + 0.25, 39000.0, 32.5, 2257.505, 534.532 + 0.25, 39000.0, 33.0, 2344.175, 559.609 + 0.25, 39000.0, 33.5, 2431.17, 585.442 + 0.25, 39000.0, 34.0, 2518.7, 611.1 + 0.25, 39000.0, 34.5, 2613.008, 657.264 + 0.25, 39000.0, 35.0, 2707.694, 699.331 + 0.25, 39000.0, 35.5, 2802.393, 734.313 + 0.25, 39000.0, 36.0, 2896.74, 759.22 + 0.25, 39000.0, 36.5, 2990.37, 771.062 + 0.25, 39000.0, 37.0, 3082.916, 766.849 + 0.25, 39000.0, 37.5, 3174.015, 743.591 + 0.25, 39000.0, 38.0, 3263.3, 698.3 + 0.25, 39000.0, 38.5, 3344.53, 526.075 + 0.25, 39000.0, 39.0, 3426.263, 378.678 + 0.25, 39000.0, 39.5, 3509.439, 275.768 + 0.25, 39000.0, 40.0, 3595.0, 237.0 + 0.25, 39000.0, 40.5, 3688.835, 343.898 + 0.25, 39000.0, 41.0, 3784.956, 529.506 + 0.25, 39000.0, 41.5, 3882.324, 788.737 + 0.25, 39000.0, 42.0, 3979.9, 1116.5 + 0.25, 39000.0, 42.5, 4070.441, 1591.81 + 0.25, 39000.0, 43.0, 4161.594, 2091.84 + 0.25, 39000.0, 43.5, 4254.799, 2577.84 + 0.25, 39000.0, 44.0, 4351.5, 3011.1 + 0.25, 39000.0, 44.5, 4467.802, 3299.36 + 0.25, 39000.0, 45.0, 4584.619, 3478.81 + 0.25, 39000.0, 45.5, 4697.526, 3532.13 + 0.25, 39000.0, 46.0, 4802.1, 3442.0 + 0.25, 39000.0, 46.5, 4868.578, 2993.47 + 0.25, 39000.0, 47.0, 4928.013, 2445.89 + 0.25, 39000.0, 47.5, 4986.116, 1860.99 + 0.25, 39000.0, 48.0, 5048.6, 1300.5 + 0.25, 39000.0, 48.5, 5121.178, 826.148 + 0.25, 39000.0, 49.0, 5209.562, 499.662 + 0.25, 39000.0, 49.5, 5319.466, 382.77 + 0.25, 39000.0, 50.0, 5456.6, 537.2 + 0.25, 43000.0, 0.0, 99.04181, 99.0418 + 0.25, 43000.0, 22.0, -139.5, 598.5 + 0.25, 43000.0, 22.5, -140.0637, 326.71 + 0.25, 43000.0, 23.0, -143.0906, 104.767 + 0.25, 43000.0, 23.5, -148.4473, -73.7846 + 0.25, 43000.0, 24.0, -156.0, -215.4 + 0.25, 43000.0, 24.5, -165.6152, -326.534 + 0.25, 43000.0, 25.0, -177.1594, -413.642 + 0.25, 43000.0, 25.5, -190.4988, -483.179 + 0.25, 43000.0, 26.0, -205.5, -541.6 + 0.25, 43000.0, 26.5, -222.4313, -663.695 + 0.25, 43000.0, 27.0, -240.78, -791.488 + 0.25, 43000.0, 27.5, -260.3438, -919.722 + 0.25, 43000.0, 28.0, -280.92, -1043.14 + 0.25, 43000.0, 28.5, -302.3063, -1156.47 + 0.25, 43000.0, 29.0, -324.3, -1254.46 + 0.25, 43000.0, 29.5, -346.6987, -1331.86 + 0.25, 43000.0, 30.0, -369.3, -1383.4 + 0.25, 43000.0, 30.5, -390.6548, -1340.67 + 0.25, 43000.0, 31.0, -411.9258, -1267.57 + 0.25, 43000.0, 31.5, -433.0292, -1164.87 + 0.25, 43000.0, 32.0, -453.8812, -1033.31 + 0.25, 43000.0, 32.5, -474.3981, -873.664 + 0.25, 43000.0, 33.0, -494.4961, -686.675 + 0.25, 43000.0, 33.5, -514.0913, -473.102 + 0.25, 43000.0, 34.0, -533.1, -233.7 + 0.25, 43000.0, 34.5, -544.3743, 419.183 + 0.25, 43000.0, 35.0, -555.5672, 1059.39 + 0.25, 43000.0, 35.5, -567.2678, 1649.18 + 0.25, 43000.0, 36.0, -580.065, 2150.8 + 0.25, 43000.0, 36.5, -594.5479, 2526.52 + 0.25, 43000.0, 37.0, -611.3053, 2738.57 + 0.25, 43000.0, 37.5, -630.9264, 2749.21 + 0.25, 43000.0, 38.0, -654.0, 2520.7 + 0.25, 43000.0, 38.5, -695.6256, 1541.47 + 0.25, 43000.0, 39.0, -734.3578, 493.284 + 0.25, 43000.0, 39.5, -767.5611, -556.322 + 0.25, 43000.0, 40.0, -792.6, -1539.8 + 0.25, 43000.0, 40.5, -786.1055, -2262.66 + 0.25, 43000.0, 41.0, -774.4687, -2835.08 + 0.25, 43000.0, 41.5, -763.3477, -3240.28 + 0.25, 43000.0, 42.0, -758.4, -3461.5 + 0.25, 43000.0, 42.5, -792.5844, -3297.42 + 0.25, 43000.0, 43.0, -833.3375, -2989.63 + 0.25, 43000.0, 43.5, -875.3969, -2595.17 + 0.25, 43000.0, 44.0, -913.5, -2171.1 + 0.25, 43000.0, 44.5, -917.6617, -1876.45 + 0.25, 43000.0, 45.0, -917.2313, -1625.48 + 0.25, 43000.0, 45.5, -916.8352, -1434.45 + 0.25, 43000.0, 46.0, -921.1, -1319.6 + 0.25, 43000.0, 46.5, -954.8203, -1427.96 + 0.25, 43000.0, 47.0, -994.3875, -1592.7 + 0.25, 43000.0, 47.5, -1036.361, -1777.77 + 0.25, 43000.0, 48.0, -1077.3, -1947.1 + 0.25, 43000.0, 48.5, -1113.764, -2064.65 + 0.25, 43000.0, 49.0, -1142.313, -2094.35 + 0.25, 43000.0, 49.5, -1159.505, -2000.15 + 0.25, 43000.0, 50.0, -1161.9, -1746.0 + 0.25, 48000.0, 0.0, 77.88451, 77.8845 + 0.25, 48000.0, 22.0, -149.1, 496.0 + 0.25, 48000.0, 22.5, -128.741, 275.215 + 0.25, 48000.0, 23.0, -117.9469, 97.8078 + 0.25, 48000.0, 23.5, -115.4543, -42.1029 + 0.25, 48000.0, 24.0, -120.0, -150.4 + 0.25, 48000.0, 24.5, -130.3207, -232.966 + 0.25, 48000.0, 25.0, -145.1531, -295.683 + 0.25, 48000.0, 25.5, -163.234, -344.433 + 0.25, 48000.0, 26.0, -183.3, -385.1 + 0.25, 48000.0, 26.5, -194.7637, -485.82 + 0.25, 48000.0, 27.0, -205.1531, -593.778 + 0.25, 48000.0, 27.5, -214.8035, -704.185 + 0.25, 48000.0, 28.0, -224.05, -812.25 + 0.25, 48000.0, 28.5, -233.2277, -913.184 + 0.25, 48000.0, 29.0, -242.6719, -1002.2 + 0.25, 48000.0, 29.5, -252.7176, -1074.5 + 0.25, 48000.0, 30.0, -263.7, -1125.3 + 0.25, 48000.0, 30.5, -282.3609, -1089.63 + 0.25, 48000.0, 31.0, -302.0188, -1028.6 + 0.25, 48000.0, 31.5, -322.3984, -943.175 + 0.25, 48000.0, 32.0, -343.225, -834.281 + 0.25, 48000.0, 32.5, -364.2234, -702.865 + 0.25, 48000.0, 33.0, -385.1188, -549.868 + 0.25, 48000.0, 33.5, -405.6359, -376.232 + 0.25, 48000.0, 34.0, -425.5, -182.9 + 0.25, 48000.0, 34.5, -434.5938, 325.841 + 0.25, 48000.0, 35.0, -443.4219, 824.142 + 0.25, 48000.0, 35.5, -452.6465, 1282.81 + 0.25, 48000.0, 36.0, -462.93, 1672.64 + 0.25, 48000.0, 36.5, -474.9348, 1964.46 + 0.25, 48000.0, 37.0, -489.3231, 2129.05 + 0.25, 48000.0, 37.5, -506.7574, 2137.23 + 0.25, 48000.0, 38.0, -527.9, 1959.8 + 0.25, 48000.0, 38.5, -571.2965, 1202.13 + 0.25, 48000.0, 39.0, -610.4531, 389.944 + 0.25, 48000.0, 39.5, -642.0582, -424.737 + 0.25, 48000.0, 40.0, -662.8, -1189.9 + 0.25, 48000.0, 40.5, -641.9078, -1758.54 + 0.25, 48000.0, 41.0, -614.5125, -2211.63 + 0.25, 48000.0, 41.5, -588.2859, -2535.16 + 0.25, 48000.0, 42.0, -570.9, -2715.1 + 0.25, 48000.0, 42.5, -605.2375, -2591.9 + 0.25, 48000.0, 43.0, -649.675, -2355.3 + 0.25, 48000.0, 43.5, -697.8, -2049.5 + 0.25, 48000.0, 44.0, -743.2, -1718.7 + 0.25, 48000.0, 44.5, -755.7594, -1483.07 + 0.25, 48000.0, 45.0, -762.25, -1280.46 + 0.25, 48000.0, 45.5, -765.7406, -1124.66 + 0.25, 48000.0, 46.0, -769.3, -1029.5 + 0.25, 48000.0, 46.5, -785.45, -1116.9 + 0.25, 48000.0, 47.0, -804.025, -1249.31 + 0.25, 48000.0, 47.5, -824.3125, -1397.29 + 0.25, 48000.0, 48.0, -845.6, -1531.4 + 0.25, 48000.0, 48.5, -867.175, -1622.2 + 0.25, 48000.0, 49.0, -888.325, -1640.26 + 0.25, 48000.0, 49.5, -908.3375, -1556.14 + 0.25, 48000.0, 50.0, -926.5, -1340.4 + 0.3, 0.0, 0.0, 544.742, 544.742 + 0.3, 0.0, 22.0, 1428.9, 952.7 + 0.3, 0.0, 22.5, 1700.12, 1041.65 + 0.3, 0.0, 23.0, 1968.539, 1128.83 + 0.3, 0.0, 23.5, 2235.088, 1214.75 + 0.3, 0.0, 24.0, 2500.7, 1299.9 + 0.3, 0.0, 24.5, 2766.305, 1384.78 + 0.3, 0.0, 25.0, 3032.836, 1469.89 + 0.3, 0.0, 25.5, 3301.224, 1555.73 + 0.3, 0.0, 26.0, 3572.4, 1642.8 + 0.3, 0.0, 26.5, 3857.073, 1735.87 + 0.3, 0.0, 27.0, 4146.958, 1831.4 + 0.3, 0.0, 27.5, 4441.308, 1929.17 + 0.3, 0.0, 28.0, 4739.38, 2028.95 + 0.3, 0.0, 28.5, 5040.43, 2130.49 + 0.3, 0.0, 29.0, 5343.713, 2233.57 + 0.3, 0.0, 29.5, 5648.484, 2337.95 + 0.3, 0.0, 30.0, 5954.0, 2443.4 + 0.3, 0.0, 30.5, 6251.7, 2547.81 + 0.3, 0.0, 31.0, 6549.4, 2653.01 + 0.3, 0.0, 31.5, 6847.1, 2758.93 + 0.3, 0.0, 32.0, 7144.8, 2865.52 + 0.3, 0.0, 32.5, 7442.5, 2972.73 + 0.3, 0.0, 33.0, 7740.2, 3080.5 + 0.3, 0.0, 33.5, 8037.9, 3188.77 + 0.3, 0.0, 34.0, 8335.6, 3297.5 + 0.3, 0.0, 34.5, 8633.3, 3406.18 + 0.3, 0.0, 35.0, 8931.0, 3515.24 + 0.3, 0.0, 35.5, 9228.7, 3624.68 + 0.3, 0.0, 36.0, 9526.4, 3734.47 + 0.3, 0.0, 36.5, 9824.1, 3844.61 + 0.3, 0.0, 37.0, 10121.8, 3955.09 + 0.3, 0.0, 37.5, 10419.5, 4065.89 + 0.3, 0.0, 38.0, 10717.2, 4177.0 + 0.3, 0.0, 38.5, 11014.9, 4288.69 + 0.3, 0.0, 39.0, 11312.6, 4400.52 + 0.3, 0.0, 39.5, 11610.3, 4512.41 + 0.3, 0.0, 40.0, 11908.0, 4624.3 + 0.3, 0.0, 40.5, 12205.7, 4735.81 + 0.3, 0.0, 41.0, 12503.39, 4847.29 + 0.3, 0.0, 41.5, 12801.09, 4958.77 + 0.3, 0.0, 42.0, 13098.8, 5070.3 + 0.3, 0.0, 42.5, 13396.29, 5182.35 + 0.3, 0.0, 43.0, 13693.88, 5294.37 + 0.3, 0.0, 43.5, 13991.65, 5406.23 + 0.3, 0.0, 44.0, 14289.7, 5517.8 + 0.3, 0.0, 44.5, 14589.02, 5628.62 + 0.3, 0.0, 45.0, 14888.42, 5739.03 + 0.3, 0.0, 45.5, 15187.64, 5849.02 + 0.3, 0.0, 46.0, 15486.4, 5958.6 + 0.3, 0.0, 46.5, 15783.04, 6067.17 + 0.3, 0.0, 47.0, 16079.22, 6175.57 + 0.3, 0.0, 47.5, 16375.21, 6284.04 + 0.3, 0.0, 48.0, 16671.3, 6392.8 + 0.3, 0.0, 48.5, 16967.76, 6502.1 + 0.3, 0.0, 49.0, 17264.86, 6612.17 + 0.3, 0.0, 49.5, 17562.88, 6723.26 + 0.3, 0.0, 50.0, 17862.1, 6835.6 + 0.3, 2000.0, 0.0, 510.0254, 510.025 + 0.3, 2000.0, 22.0, 1380.6, 902.8 + 0.3, 2000.0, 22.5, 1642.582, 988.438 + 0.3, 2000.0, 23.0, 1901.878, 1072.24 + 0.3, 2000.0, 23.5, 2159.385, 1154.73 + 0.3, 2000.0, 24.0, 2416.0, 1236.4 + 0.3, 2000.0, 24.5, 2672.621, 1317.77 + 0.3, 2000.0, 25.0, 2930.147, 1399.36 + 0.3, 2000.0, 25.5, 3189.474, 1481.66 + 0.3, 2000.0, 26.0, 3451.5, 1565.2 + 0.3, 2000.0, 26.5, 3726.555, 1654.91 + 0.3, 2000.0, 27.0, 4006.644, 1747.14 + 0.3, 2000.0, 27.5, 4291.047, 1841.62 + 0.3, 2000.0, 28.0, 4579.045, 1938.11 + 0.3, 2000.0, 28.5, 4869.919, 2036.36 + 0.3, 2000.0, 29.0, 5162.948, 2136.13 + 0.3, 2000.0, 29.5, 5457.415, 2237.16 + 0.3, 2000.0, 30.0, 5752.6, 2339.2 + 0.3, 2000.0, 30.5, 6040.228, 2439.89 + 0.3, 2000.0, 31.0, 6327.855, 2541.31 + 0.3, 2000.0, 31.5, 6615.481, 2643.39 + 0.3, 2000.0, 32.0, 6903.106, 2746.09 + 0.3, 2000.0, 32.5, 7190.73, 2849.38 + 0.3, 2000.0, 33.0, 7478.354, 2953.19 + 0.3, 2000.0, 33.5, 7765.977, 3057.48 + 0.3, 2000.0, 34.0, 8053.6, 3162.2 + 0.3, 2000.0, 34.5, 8341.218, 3266.92 + 0.3, 2000.0, 35.0, 8628.837, 3372.02 + 0.3, 2000.0, 35.5, 8916.458, 3477.49 + 0.3, 2000.0, 36.0, 9204.08, 3583.3 + 0.3, 2000.0, 36.5, 9491.705, 3689.47 + 0.3, 2000.0, 37.0, 9779.332, 3795.96 + 0.3, 2000.0, 37.5, 10066.96, 3902.77 + 0.3, 2000.0, 38.0, 10354.6, 4009.9 + 0.3, 2000.0, 38.5, 10642.25, 4117.72 + 0.3, 2000.0, 39.0, 10929.9, 4225.62 + 0.3, 2000.0, 39.5, 11217.55, 4333.52 + 0.3, 2000.0, 40.0, 11505.2, 4441.3 + 0.3, 2000.0, 40.5, 11792.83, 4548.61 + 0.3, 2000.0, 41.0, 12080.46, 4655.73 + 0.3, 2000.0, 41.5, 12368.08, 4762.66 + 0.3, 2000.0, 42.0, 12655.7, 4869.4 + 0.3, 2000.0, 42.5, 12943.1, 4976.17 + 0.3, 2000.0, 43.0, 13230.59, 5082.69 + 0.3, 2000.0, 43.5, 13518.26, 5188.89 + 0.3, 2000.0, 44.0, 13806.2, 5294.7 + 0.3, 2000.0, 44.5, 14095.41, 5399.47 + 0.3, 2000.0, 45.0, 14384.71, 5503.94 + 0.3, 2000.0, 45.5, 14673.83, 5608.26 + 0.3, 2000.0, 46.0, 14962.5, 5712.6 + 0.3, 2000.0, 46.5, 15249.11, 5817.33 + 0.3, 2000.0, 47.0, 15535.26, 5922.31 + 0.3, 2000.0, 47.5, 15821.24, 6027.61 + 0.3, 2000.0, 48.0, 16107.3, 6133.3 + 0.3, 2000.0, 48.5, 16393.72, 6239.45 + 0.3, 2000.0, 49.0, 16680.76, 6346.14 + 0.3, 2000.0, 49.5, 16968.7, 6453.43 + 0.3, 2000.0, 50.0, 17257.8, 6561.4 + 0.3, 5000.0, 0.0, 461.2495, 461.25 + 0.3, 5000.0, 22.0, 1307.4, 831.8 + 0.3, 5000.0, 22.5, 1555.504, 912.654 + 0.3, 5000.0, 23.0, 1801.055, 991.555 + 0.3, 5000.0, 23.5, 2044.903, 1069.03 + 0.3, 5000.0, 24.0, 2287.9, 1145.6 + 0.3, 5000.0, 24.5, 2530.897, 1221.8 + 0.3, 5000.0, 25.0, 2774.745, 1298.15 + 0.3, 5000.0, 25.5, 3020.296, 1375.17 + 0.3, 5000.0, 26.0, 3268.4, 1453.4 + 0.3, 5000.0, 26.5, 3528.846, 1537.94 + 0.3, 5000.0, 27.0, 3794.059, 1625.0 + 0.3, 5000.0, 27.5, 4063.357, 1714.32 + 0.3, 5000.0, 28.0, 4336.06, 1805.63 + 0.3, 5000.0, 28.5, 4611.487, 1898.69 + 0.3, 5000.0, 29.0, 4888.956, 1993.23 + 0.3, 5000.0, 29.5, 5167.788, 2088.98 + 0.3, 5000.0, 30.0, 5447.3, 2185.7 + 0.3, 5000.0, 30.5, 5719.663, 2280.84 + 0.3, 5000.0, 31.0, 5992.025, 2376.63 + 0.3, 5000.0, 31.5, 6264.388, 2473.05 + 0.3, 5000.0, 32.0, 6536.75, 2570.04 + 0.3, 5000.0, 32.5, 6809.113, 2667.56 + 0.3, 5000.0, 33.0, 7081.475, 2765.57 + 0.3, 5000.0, 33.5, 7353.838, 2864.03 + 0.3, 5000.0, 34.0, 7626.2, 2962.9 + 0.3, 5000.0, 34.5, 7898.559, 3062.28 + 0.3, 5000.0, 35.0, 8170.919, 3161.96 + 0.3, 5000.0, 35.5, 8443.279, 3261.9 + 0.3, 5000.0, 36.0, 8715.64, 3362.03 + 0.3, 5000.0, 36.5, 8988.002, 3462.31 + 0.3, 5000.0, 37.0, 9260.366, 3562.66 + 0.3, 5000.0, 37.5, 9532.732, 3663.05 + 0.3, 5000.0, 38.0, 9805.1, 3763.4 + 0.3, 5000.0, 38.5, 10077.47, 3863.31 + 0.3, 5000.0, 39.0, 10349.85, 3963.27 + 0.3, 5000.0, 39.5, 10622.22, 4063.29 + 0.3, 5000.0, 40.0, 10894.6, 4163.4 + 0.3, 5000.0, 40.5, 11166.98, 4264.19 + 0.3, 5000.0, 41.0, 11439.35, 4364.88 + 0.3, 5000.0, 41.5, 11711.73, 4465.29 + 0.3, 5000.0, 42.0, 11984.1, 4565.2 + 0.3, 5000.0, 42.5, 12256.26, 4663.31 + 0.3, 5000.0, 43.0, 12528.51, 4760.97 + 0.3, 5000.0, 43.5, 12800.93, 4858.42 + 0.3, 5000.0, 44.0, 13073.6, 4955.9 + 0.3, 5000.0, 44.5, 13347.46, 5054.31 + 0.3, 5000.0, 45.0, 13621.39, 5152.98 + 0.3, 5000.0, 45.5, 13895.16, 5251.88 + 0.3, 5000.0, 46.0, 14168.5, 5351.0 + 0.3, 5000.0, 46.5, 14439.88, 5449.94 + 0.3, 5000.0, 47.0, 14710.84, 5549.21 + 0.3, 5000.0, 47.5, 14981.63, 5648.92 + 0.3, 5000.0, 48.0, 15252.5, 5749.2 + 0.3, 5000.0, 48.5, 15523.72, 5850.18 + 0.3, 5000.0, 49.0, 15795.54, 5951.99 + 0.3, 5000.0, 49.5, 16068.21, 6054.76 + 0.3, 5000.0, 50.0, 16342.0, 6158.6 + 0.3, 10000.0, 0.0, 388.2074, 388.207 + 0.3, 10000.0, 22.0, 1192.7, 731.4 + 0.3, 10000.0, 22.5, 1419.046, 804.371 + 0.3, 10000.0, 23.0, 1643.059, 875.509 + 0.3, 10000.0, 23.5, 1865.518, 945.318 + 0.3, 10000.0, 24.0, 2087.2, 1014.3 + 0.3, 10000.0, 24.5, 2308.882, 1082.96 + 0.3, 10000.0, 25.0, 2531.341, 1151.79 + 0.3, 10000.0, 25.5, 2755.354, 1221.3 + 0.3, 10000.0, 26.0, 2981.7, 1292.0 + 0.3, 10000.0, 26.5, 3219.319, 1368.79 + 0.3, 10000.0, 27.0, 3461.29, 1448.01 + 0.3, 10000.0, 27.5, 3706.993, 1529.43 + 0.3, 10000.0, 28.0, 3955.805, 1612.77 + 0.3, 10000.0, 28.5, 4207.104, 1697.79 + 0.3, 10000.0, 29.0, 4460.267, 1784.24 + 0.3, 10000.0, 29.5, 4714.673, 1871.86 + 0.3, 10000.0, 30.0, 4969.7, 1960.4 + 0.3, 10000.0, 30.5, 5218.193, 2047.62 + 0.3, 10000.0, 31.0, 5466.684, 2135.43 + 0.3, 10000.0, 31.5, 5715.174, 2223.79 + 0.3, 10000.0, 32.0, 5963.663, 2312.62 + 0.3, 10000.0, 32.5, 6212.149, 2401.86 + 0.3, 10000.0, 33.0, 6460.634, 2491.44 + 0.3, 10000.0, 33.5, 6709.118, 2581.31 + 0.3, 10000.0, 34.0, 6957.6, 2671.4 + 0.3, 10000.0, 34.5, 7206.078, 2761.15 + 0.3, 10000.0, 35.0, 7454.555, 2851.03 + 0.3, 10000.0, 35.5, 7703.03, 2941.03 + 0.3, 10000.0, 36.0, 7951.505, 3031.14 + 0.3, 10000.0, 36.5, 8199.979, 3121.34 + 0.3, 10000.0, 37.0, 8448.453, 3211.61 + 0.3, 10000.0, 37.5, 8696.926, 3301.94 + 0.3, 10000.0, 38.0, 8945.4, 3392.3 + 0.3, 10000.0, 38.5, 9193.87, 3483.26 + 0.3, 10000.0, 39.0, 9442.342, 3573.93 + 0.3, 10000.0, 39.5, 9690.819, 3664.16 + 0.3, 10000.0, 40.0, 9939.3, 3753.8 + 0.3, 10000.0, 40.5, 10187.8, 3841.73 + 0.3, 10000.0, 41.0, 10436.3, 3929.18 + 0.3, 10000.0, 41.5, 10684.8, 4016.38 + 0.3, 10000.0, 42.0, 10933.3, 4103.6 + 0.3, 10000.0, 42.5, 11181.59, 4191.48 + 0.3, 10000.0, 43.0, 11429.94, 4279.7 + 0.3, 10000.0, 43.5, 11678.46, 4368.35 + 0.3, 10000.0, 44.0, 11927.2, 4457.5 + 0.3, 10000.0, 44.5, 12177.04, 4547.63 + 0.3, 10000.0, 45.0, 12426.96, 4638.29 + 0.3, 10000.0, 45.5, 12676.73, 4729.4 + 0.3, 10000.0, 46.0, 12926.1, 4820.9 + 0.3, 10000.0, 46.5, 13173.67, 4912.06 + 0.3, 10000.0, 47.0, 13420.86, 5003.73 + 0.3, 10000.0, 47.5, 13667.89, 5096.11 + 0.3, 10000.0, 48.0, 13915.0, 5189.4 + 0.3, 10000.0, 48.5, 14162.43, 5283.79 + 0.3, 10000.0, 49.0, 14410.42, 5379.47 + 0.3, 10000.0, 49.5, 14659.2, 5476.64 + 0.3, 10000.0, 50.0, 14909.0, 5575.5 + 0.3, 15000.0, 0.0, 324.6165, 324.616 + 0.3, 15000.0, 22.0, 1063.3, 632.7 + 0.3, 15000.0, 22.5, 1265.074, 696.074 + 0.3, 15000.0, 23.0, 1464.77, 757.92 + 0.3, 15000.0, 23.5, 1663.081, 818.681 + 0.3, 15000.0, 24.0, 1860.7, 878.8 + 0.3, 15000.0, 24.5, 2058.319, 938.719 + 0.3, 15000.0, 25.0, 2256.63, 998.88 + 0.3, 15000.0, 25.5, 2456.326, 1059.73 + 0.3, 15000.0, 26.0, 2658.1, 1121.7 + 0.3, 15000.0, 26.5, 2869.916, 1189.29 + 0.3, 15000.0, 27.0, 3085.611, 1259.12 + 0.3, 15000.0, 27.5, 3304.63, 1330.95 + 0.3, 15000.0, 28.0, 3526.42, 1404.52 + 0.3, 15000.0, 28.5, 3750.426, 1479.58 + 0.3, 15000.0, 29.0, 3976.094, 1555.88 + 0.3, 15000.0, 29.5, 4202.87, 1633.17 + 0.3, 15000.0, 30.0, 4430.2, 1711.2 + 0.3, 15000.0, 30.5, 4651.712, 1787.5 + 0.3, 15000.0, 31.0, 4873.225, 1864.25 + 0.3, 15000.0, 31.5, 5094.737, 1941.42 + 0.3, 15000.0, 32.0, 5316.25, 2018.95 + 0.3, 15000.0, 32.5, 5537.762, 2096.81 + 0.3, 15000.0, 33.0, 5759.275, 2174.97 + 0.3, 15000.0, 33.5, 5980.787, 2253.38 + 0.3, 15000.0, 34.0, 6202.3, 2332.0 + 0.3, 15000.0, 34.5, 6423.816, 2411.1 + 0.3, 15000.0, 35.0, 6645.331, 2490.31 + 0.3, 15000.0, 35.5, 6866.846, 2569.55 + 0.3, 15000.0, 36.0, 7088.36, 2648.76 + 0.3, 15000.0, 36.5, 7309.873, 2727.87 + 0.3, 15000.0, 37.0, 7531.384, 2806.81 + 0.3, 15000.0, 37.5, 7752.893, 2885.51 + 0.3, 15000.0, 38.0, 7974.4, 2963.9 + 0.3, 15000.0, 38.5, 8195.896, 3041.28 + 0.3, 15000.0, 39.0, 8417.394, 3118.54 + 0.3, 15000.0, 39.5, 8638.895, 3195.76 + 0.3, 15000.0, 40.0, 8860.4, 3273.0 + 0.3, 15000.0, 40.5, 9081.923, 3350.32 + 0.3, 15000.0, 41.0, 9303.45, 3427.82 + 0.3, 15000.0, 41.5, 9524.977, 3505.59 + 0.3, 15000.0, 42.0, 9746.5, 3583.7 + 0.3, 15000.0, 42.5, 9967.83, 3662.32 + 0.3, 15000.0, 43.0, 10189.23, 3741.42 + 0.3, 15000.0, 43.5, 10410.76, 3821.06 + 0.3, 15000.0, 44.0, 10632.5, 3901.3 + 0.3, 15000.0, 44.5, 10855.23, 3982.26 + 0.3, 15000.0, 45.0, 11078.03, 4063.9 + 0.3, 15000.0, 45.5, 11300.69, 4146.24 + 0.3, 15000.0, 46.0, 11523.0, 4229.3 + 0.3, 15000.0, 46.5, 11743.71, 4312.55 + 0.3, 15000.0, 47.0, 11964.08, 4396.8 + 0.3, 15000.0, 47.5, 12184.3, 4482.3 + 0.3, 15000.0, 48.0, 12404.6, 4569.3 + 0.3, 15000.0, 48.5, 12625.18, 4658.05 + 0.3, 15000.0, 49.0, 12846.25, 4748.8 + 0.3, 15000.0, 49.5, 13068.02, 4841.8 + 0.3, 15000.0, 50.0, 13290.7, 4937.3 + 0.3, 20000.0, 0.0, 269.5519, 269.552 + 0.3, 20000.0, 22.0, 854.4, 514.3 + 0.3, 20000.0, 22.5, 1017.524, 579.067 + 0.3, 20000.0, 23.0, 1178.755, 636.011 + 0.3, 20000.0, 23.5, 1338.683, 686.424 + 0.3, 20000.0, 24.0, 1497.9, 731.6 + 0.3, 20000.0, 24.5, 1656.999, 772.832 + 0.3, 20000.0, 25.0, 1816.57, 811.414 + 0.3, 20000.0, 25.5, 1977.207, 848.639 + 0.3, 20000.0, 26.0, 2139.5, 885.8 + 0.3, 20000.0, 26.5, 2310.225, 934.007 + 0.3, 20000.0, 27.0, 2484.144, 985.298 + 0.3, 20000.0, 27.5, 2660.789, 1039.28 + 0.3, 20000.0, 28.0, 2839.69, 1095.57 + 0.3, 20000.0, 28.5, 3020.38, 1153.78 + 0.3, 20000.0, 29.0, 3202.391, 1213.51 + 0.3, 20000.0, 29.5, 3385.253, 1274.38 + 0.3, 20000.0, 30.0, 3568.5, 1336.0 + 0.3, 20000.0, 30.5, 3746.503, 1392.35 + 0.3, 20000.0, 31.0, 3924.445, 1449.2 + 0.3, 20000.0, 31.5, 4102.349, 1506.71 + 0.3, 20000.0, 32.0, 4280.237, 1565.01 + 0.3, 20000.0, 32.5, 4458.134, 1624.25 + 0.3, 20000.0, 33.0, 4636.061, 1684.58 + 0.3, 20000.0, 33.5, 4814.042, 1746.15 + 0.3, 20000.0, 34.0, 4992.1, 1809.1 + 0.3, 20000.0, 34.5, 5170.92, 1885.35 + 0.3, 20000.0, 35.0, 5349.8, 1962.16 + 0.3, 20000.0, 35.5, 5528.7, 2038.54 + 0.3, 20000.0, 36.0, 5707.58, 2113.53 + 0.3, 20000.0, 36.5, 5886.4, 2186.14 + 0.3, 20000.0, 37.0, 6065.12, 2255.41 + 0.3, 20000.0, 37.5, 6243.7, 2320.35 + 0.3, 20000.0, 38.0, 6422.1, 2380.0 + 0.3, 20000.0, 38.5, 6599.854, 2420.68 + 0.3, 20000.0, 39.0, 6777.569, 2460.69 + 0.3, 20000.0, 39.5, 6955.299, 2501.88 + 0.3, 20000.0, 40.0, 7133.1, 2546.1 + 0.3, 20000.0, 40.5, 7311.26, 2601.02 + 0.3, 20000.0, 41.0, 7489.506, 2660.34 + 0.3, 20000.0, 41.5, 7667.799, 2723.56 + 0.3, 20000.0, 42.0, 7846.1, 2790.2 + 0.3, 20000.0, 42.5, 8024.143, 2858.94 + 0.3, 20000.0, 43.0, 8202.206, 2930.46 + 0.3, 20000.0, 43.5, 8380.341, 3004.63 + 0.3, 20000.0, 44.0, 8558.6, 3081.3 + 0.3, 20000.0, 44.5, 8737.409, 3162.13 + 0.3, 20000.0, 45.0, 8916.294, 3244.44 + 0.3, 20000.0, 45.5, 9095.157, 3327.36 + 0.3, 20000.0, 46.0, 9273.9, 3410.0 + 0.3, 20000.0, 46.5, 9451.975, 3488.44 + 0.3, 20000.0, 47.0, 9629.912, 3566.09 + 0.3, 20000.0, 47.5, 9807.794, 3643.29 + 0.3, 20000.0, 48.0, 9985.7, 3720.4 + 0.3, 20000.0, 48.5, 10163.71, 3797.77 + 0.3, 20000.0, 49.0, 10341.91, 3875.74 + 0.3, 20000.0, 49.5, 10520.38, 3954.67 + 0.3, 20000.0, 50.0, 10699.2, 4034.9 + 0.3, 25000.0, 0.0, 222.1416, 222.142 + 0.3, 25000.0, 22.0, 662.7, 460.7 + 0.3, 25000.0, 22.5, 790.6117, 438.364 + 0.3, 25000.0, 23.0, 916.7063, 442.391 + 0.3, 25000.0, 23.5, 1041.498, 468.722 + 0.3, 25000.0, 24.0, 1165.5, 513.3 + 0.3, 25000.0, 24.5, 1289.227, 572.065 + 0.3, 25000.0, 25.0, 1413.194, 640.959 + 0.3, 25000.0, 25.5, 1537.913, 715.924 + 0.3, 25000.0, 26.0, 1663.9, 792.9 + 0.3, 25000.0, 26.5, 1796.948, 834.642 + 0.3, 25000.0, 27.0, 1932.593, 868.383 + 0.3, 25000.0, 27.5, 2070.444, 895.752 + 0.3, 25000.0, 28.0, 2210.11, 918.38 + 0.3, 25000.0, 28.5, 2351.2, 937.898 + 0.3, 25000.0, 29.0, 2493.322, 955.938 + 0.3, 25000.0, 29.5, 2636.086, 974.128 + 0.3, 25000.0, 30.0, 2779.1, 994.1 + 0.3, 25000.0, 30.5, 2917.588, 1040.35 + 0.3, 25000.0, 31.0, 3055.963, 1089.47 + 0.3, 25000.0, 31.5, 3194.249, 1140.9 + 0.3, 25000.0, 32.0, 3332.475, 1194.11 + 0.3, 25000.0, 32.5, 3470.666, 1248.54 + 0.3, 25000.0, 33.0, 3608.85, 1303.64 + 0.3, 25000.0, 33.5, 3747.052, 1358.88 + 0.3, 25000.0, 34.0, 3885.3, 1413.7 + 0.3, 25000.0, 34.5, 4024.163, 1445.57 + 0.3, 25000.0, 35.0, 4163.072, 1478.02 + 0.3, 25000.0, 35.5, 4302.003, 1512.61 + 0.3, 25000.0, 36.0, 4440.93, 1550.87 + 0.3, 25000.0, 36.5, 4579.829, 1594.35 + 0.3, 25000.0, 37.0, 4718.673, 1644.6 + 0.3, 25000.0, 37.5, 4857.439, 1703.17 + 0.3, 25000.0, 38.0, 4996.1, 1771.6 + 0.3, 25000.0, 38.5, 5134.063, 1888.52 + 0.3, 25000.0, 39.0, 5272.167, 1999.17 + 0.3, 25000.0, 39.5, 5410.512, 2096.86 + 0.3, 25000.0, 40.0, 5549.2, 2174.9 + 0.3, 25000.0, 40.5, 5689.202, 2190.22 + 0.3, 25000.0, 41.0, 5829.4, 2187.06 + 0.3, 25000.0, 41.5, 5969.548, 2173.26 + 0.3, 25000.0, 42.0, 6109.4, 2156.7 + 0.3, 25000.0, 42.5, 6247.227, 2161.76 + 0.3, 25000.0, 43.0, 6384.856, 2173.16 + 0.3, 25000.0, 43.5, 6522.632, 2192.12 + 0.3, 25000.0, 44.0, 6660.9, 2219.9 + 0.3, 25000.0, 44.5, 6802.173, 2266.52 + 0.3, 25000.0, 45.0, 6943.763, 2320.93 + 0.3, 25000.0, 45.5, 7085.145, 2380.85 + 0.3, 25000.0, 46.0, 7225.8, 2444.0 + 0.3, 25000.0, 46.5, 7362.662, 2495.59 + 0.3, 25000.0, 47.0, 7498.769, 2550.88 + 0.3, 25000.0, 47.5, 7634.616, 2612.61 + 0.3, 25000.0, 48.0, 7770.7, 2683.5 + 0.3, 25000.0, 48.5, 7907.515, 2766.3 + 0.3, 25000.0, 49.0, 8045.556, 2863.74 + 0.3, 25000.0, 49.5, 8185.32, 2978.56 + 0.3, 25000.0, 50.0, 8327.3, 3113.5 + 0.3, 30000.0, 0.0, 181.5747, 181.575 + 0.3, 30000.0, 22.0, 412.9, 303.9 + 0.3, 30000.0, 22.5, 489.4963, 362.41 + 0.3, 30000.0, 23.0, 566.0047, 395.634 + 0.3, 30000.0, 23.5, 642.6107, 408.217 + 0.3, 30000.0, 24.0, 719.5, 404.8 + 0.3, 30000.0, 24.5, 796.858, 390.027 + 0.3, 30000.0, 25.0, 874.8703, 368.541 + 0.3, 30000.0, 25.5, 953.7225, 344.984 + 0.3, 30000.0, 26.0, 1033.6, 324.0 + 0.3, 30000.0, 26.5, 1117.171, 356.704 + 0.3, 30000.0, 27.0, 1202.281, 403.922 + 0.3, 30000.0, 27.5, 1288.689, 462.33 + 0.3, 30000.0, 28.0, 1376.155, 528.605 + 0.3, 30000.0, 28.5, 1464.439, 599.423 + 0.3, 30000.0, 29.0, 1553.302, 671.461 + 0.3, 30000.0, 29.5, 1642.502, 741.394 + 0.3, 30000.0, 30.0, 1731.8, 805.9 + 0.3, 30000.0, 30.5, 1818.177, 809.972 + 0.3, 30000.0, 31.0, 1904.436, 806.891 + 0.3, 30000.0, 31.5, 1990.602, 798.255 + 0.3, 30000.0, 32.0, 2076.7, 785.662 + 0.3, 30000.0, 32.5, 2162.754, 770.712 + 0.3, 30000.0, 33.0, 2248.789, 755.003 + 0.3, 30000.0, 33.5, 2334.829, 740.133 + 0.3, 30000.0, 34.0, 2420.9, 727.7 + 0.3, 30000.0, 34.5, 2508.269, 732.084 + 0.3, 30000.0, 35.0, 2595.598, 740.886 + 0.3, 30000.0, 35.5, 2682.795, 754.486 + 0.3, 30000.0, 36.0, 2769.765, 773.265 + 0.3, 30000.0, 36.5, 2856.414, 797.605 + 0.3, 30000.0, 37.0, 2942.649, 827.887 + 0.3, 30000.0, 37.5, 3028.376, 864.491 + 0.3, 30000.0, 38.0, 3113.5, 907.8 + 0.3, 30000.0, 38.5, 3195.469, 980.794 + 0.3, 30000.0, 39.0, 3277.923, 1049.54 + 0.3, 30000.0, 39.5, 3361.316, 1109.38 + 0.3, 30000.0, 40.0, 3446.1, 1155.7 + 0.3, 30000.0, 40.5, 3535.699, 1161.35 + 0.3, 30000.0, 41.0, 3626.406, 1153.19 + 0.3, 30000.0, 41.5, 3717.485, 1135.55 + 0.3, 30000.0, 42.0, 3808.2, 1112.8 + 0.3, 30000.0, 42.5, 3895.616, 1064.16 + 0.3, 30000.0, 43.0, 3982.075, 1029.16 + 0.3, 30000.0, 43.5, 4067.722, 1022.21 + 0.3, 30000.0, 44.0, 4152.7, 1057.7 + 0.3, 30000.0, 44.5, 4236.993, 1251.36 + 0.3, 30000.0, 45.0, 4320.969, 1475.74 + 0.3, 30000.0, 45.5, 4404.835, 1704.73 + 0.3, 30000.0, 46.0, 4488.8, 1912.2 + 0.3, 30000.0, 46.5, 4573.368, 1998.56 + 0.3, 30000.0, 47.0, 4658.331, 2040.54 + 0.3, 30000.0, 47.5, 4743.779, 2041.4 + 0.3, 30000.0, 48.0, 4829.8, 2004.4 + 0.3, 30000.0, 48.5, 4916.484, 1932.81 + 0.3, 30000.0, 49.0, 5003.919, 1829.89 + 0.3, 30000.0, 49.5, 5092.195, 1698.9 + 0.3, 30000.0, 50.0, 5181.4, 1543.1 + 0.3, 35000.0, 0.0, 147.0962, 147.096 + 0.3, 35000.0, 22.0, 514.5, 254.0 + 0.3, 35000.0, 22.5, 620.0857, 248.505 + 0.3, 35000.0, 23.0, 722.6266, 268.894 + 0.3, 35000.0, 23.5, 822.7041, 310.41 + 0.3, 35000.0, 24.0, 920.9, 368.3 + 0.3, 35000.0, 24.5, 1017.796, 437.809 + 0.3, 35000.0, 25.0, 1113.973, 514.181 + 0.3, 35000.0, 25.5, 1210.014, 592.663 + 0.3, 35000.0, 26.0, 1306.5, 668.5 + 0.3, 35000.0, 26.5, 1408.696, 688.162 + 0.3, 35000.0, 27.0, 1512.768, 692.883 + 0.3, 35000.0, 27.5, 1618.495, 686.268 + 0.3, 35000.0, 28.0, 1725.655, 671.925 + 0.3, 35000.0, 28.5, 1834.027, 653.46 + 0.3, 35000.0, 29.0, 1943.389, 634.48 + 0.3, 35000.0, 29.5, 2053.521, 618.591 + 0.3, 35000.0, 30.0, 2164.2, 609.4 + 0.3, 35000.0, 30.5, 2273.682, 680.076 + 0.3, 35000.0, 31.0, 2383.414, 758.039 + 0.3, 35000.0, 31.5, 2493.321, 840.27 + 0.3, 35000.0, 32.0, 2603.325, 923.75 + 0.3, 35000.0, 32.5, 2713.351, 1005.46 + 0.3, 35000.0, 33.0, 2823.323, 1082.39 + 0.3, 35000.0, 33.5, 2933.165, 1151.5 + 0.3, 35000.0, 34.0, 3042.8, 1209.8 + 0.3, 35000.0, 34.5, 3148.456, 1176.13 + 0.3, 35000.0, 35.0, 3254.105, 1133.05 + 0.3, 35000.0, 35.5, 3360.022, 1084.96 + 0.3, 35000.0, 36.0, 3466.485, 1036.3 + 0.3, 35000.0, 36.5, 3573.768, 991.476 + 0.3, 35000.0, 37.0, 3682.148, 954.922 + 0.3, 35000.0, 37.5, 3791.9, 931.056 + 0.3, 35000.0, 38.0, 3903.3, 924.3 + 0.3, 35000.0, 38.5, 4021.868, 899.591 + 0.3, 35000.0, 39.0, 4139.917, 921.308 + 0.3, 35000.0, 39.5, 4256.558, 1002.65 + 0.3, 35000.0, 40.0, 4370.9, 1156.8 + 0.3, 35000.0, 40.5, 4476.773, 1534.3 + 0.3, 35000.0, 41.0, 4580.681, 1956.08 + 0.3, 35000.0, 41.5, 4683.849, 2380.39 + 0.3, 35000.0, 42.0, 4787.5, 2765.5 + 0.3, 35000.0, 42.5, 4897.986, 2986.39 + 0.3, 35000.0, 43.0, 5009.35, 3117.9 + 0.3, 35000.0, 43.5, 5120.764, 3151.61 + 0.3, 35000.0, 44.0, 5231.4, 3079.1 + 0.3, 35000.0, 44.5, 5336.113, 2729.16 + 0.3, 35000.0, 45.0, 5440.119, 2321.25 + 0.3, 35000.0, 45.5, 5544.315, 1912.04 + 0.3, 35000.0, 46.0, 5649.6, 1558.2 + 0.3, 35000.0, 46.5, 5761.041, 1519.12 + 0.3, 35000.0, 47.0, 5873.7, 1567.69 + 0.3, 35000.0, 47.5, 5986.809, 1679.52 + 0.3, 35000.0, 48.0, 6099.6, 1830.2 + 0.3, 35000.0, 48.5, 6211.303, 1995.33 + 0.3, 35000.0, 49.0, 6321.15, 2150.51 + 0.3, 35000.0, 49.5, 6428.372, 2271.33 + 0.3, 35000.0, 50.0, 6532.2, 2333.4 + 0.3, 39000.0, 0.0, 122.0031, 122.003 + 0.3, 39000.0, 22.0, 386.2, 144.2 + 0.3, 39000.0, 22.5, 467.6754, 112.765 + 0.3, 39000.0, 23.0, 545.7219, 121.319 + 0.3, 39000.0, 23.5, 621.0324, 162.838 + 0.3, 39000.0, 24.0, 694.3, 230.3 + 0.3, 39000.0, 24.5, 766.2176, 316.68 + 0.3, 39000.0, 25.0, 837.4781, 414.956 + 0.3, 39000.0, 25.5, 908.7746, 518.104 + 0.3, 39000.0, 26.0, 980.8, 619.1 + 0.3, 39000.0, 26.5, 1060.897, 649.928 + 0.3, 39000.0, 27.0, 1143.489, 661.073 + 0.3, 39000.0, 27.5, 1228.129, 655.966 + 0.3, 39000.0, 28.0, 1314.37, 638.04 + 0.3, 39000.0, 28.5, 1401.764, 610.728 + 0.3, 39000.0, 29.0, 1489.866, 577.463 + 0.3, 39000.0, 29.5, 1578.226, 541.676 + 0.3, 39000.0, 30.0, 1666.4, 506.8 + 0.3, 39000.0, 30.5, 1747.752, 518.837 + 0.3, 39000.0, 31.0, 1828.613, 534.596 + 0.3, 39000.0, 31.5, 1909.123, 553.456 + 0.3, 39000.0, 32.0, 1989.425, 574.794 + 0.3, 39000.0, 32.5, 2069.662, 597.989 + 0.3, 39000.0, 33.0, 2149.975, 622.42 + 0.3, 39000.0, 33.5, 2230.507, 647.464 + 0.3, 39000.0, 34.0, 2311.4, 672.5 + 0.3, 39000.0, 34.5, 2396.873, 711.601 + 0.3, 39000.0, 35.0, 2482.603, 748.052 + 0.3, 39000.0, 35.5, 2568.344, 779.83 + 0.3, 39000.0, 36.0, 2653.85, 804.915 + 0.3, 39000.0, 36.5, 2738.875, 821.286 + 0.3, 39000.0, 37.0, 2823.172, 826.921 + 0.3, 39000.0, 37.5, 2906.496, 819.799 + 0.3, 39000.0, 38.0, 2988.6, 797.9 + 0.3, 39000.0, 38.5, 3065.289, 690.539 + 0.3, 39000.0, 39.0, 3142.314, 599.961 + 0.3, 39000.0, 39.5, 3220.307, 539.402 + 0.3, 39000.0, 40.0, 3299.9, 522.1 + 0.3, 39000.0, 40.5, 3385.03, 603.103 + 0.3, 39000.0, 41.0, 3471.7, 737.112 + 0.3, 39000.0, 41.5, 3559.22, 920.641 + 0.3, 39000.0, 42.0, 3646.9, 1150.2 + 0.3, 39000.0, 42.5, 3729.939, 1478.8 + 0.3, 39000.0, 43.0, 3813.4, 1823.86 + 0.3, 39000.0, 43.5, 3898.236, 2159.29 + 0.3, 39000.0, 44.0, 3985.4, 2459.0 + 0.3, 39000.0, 44.5, 4085.627, 2661.54 + 0.3, 39000.0, 45.0, 4186.175, 2790.34 + 0.3, 39000.0, 45.5, 4284.086, 2833.44 + 0.3, 39000.0, 46.0, 4376.4, 2778.9 + 0.3, 39000.0, 46.5, 4443.158, 2478.98 + 0.3, 39000.0, 47.0, 4505.2, 2111.86 + 0.3, 39000.0, 47.5, 4566.367, 1719.9 + 0.3, 39000.0, 48.0, 4630.5, 1345.5 + 0.3, 39000.0, 48.5, 4701.439, 1031.02 + 0.3, 39000.0, 49.0, 4783.025, 818.844 + 0.3, 39000.0, 49.5, 4879.098, 751.345 + 0.3, 39000.0, 50.0, 4993.5, 870.9 + 0.3, 43000.0, 0.0, 100.6646, 100.665 + 0.3, 43000.0, 22.0, -34.4, 513.8 + 0.3, 43000.0, 22.5, -21.99102, 315.337 + 0.3, 43000.0, 23.0, -11.49688, 154.406 + 0.3, 43000.0, 23.5, -2.779297, 26.1727 + 0.3, 43000.0, 24.0, 4.3, -74.2 + 0.3, 43000.0, 24.5, 9.879297, -151.548 + 0.3, 43000.0, 25.0, 14.09687, -210.706 + 0.3, 43000.0, 25.5, 17.09102, -256.512 + 0.3, 43000.0, 26.0, 19.0, -293.8 + 0.3, 43000.0, 26.5, 20.10156, -378.016 + 0.3, 43000.0, 27.0, 20.4025, -466.279 + 0.3, 43000.0, 27.5, 20.01719, -554.749 + 0.3, 43000.0, 28.0, 19.06, -639.585 + 0.3, 43000.0, 28.5, 17.64531, -716.948 + 0.3, 43000.0, 29.0, 15.8875, -782.998 + 0.3, 43000.0, 29.5, 13.90094, -833.896 + 0.3, 43000.0, 30.0, 11.8, -865.8 + 0.3, 43000.0, 30.5, 10.24375, -828.314 + 0.3, 43000.0, 31.0, 8.75, -768.589 + 0.3, 43000.0, 31.5, 7.38125, -687.22 + 0.3, 43000.0, 32.0, 6.2, -584.8 + 0.3, 43000.0, 32.5, 5.26875, -461.924 + 0.3, 43000.0, 33.0, 4.65, -319.186 + 0.3, 43000.0, 33.5, 4.40625, -157.18 + 0.3, 43000.0, 34.0, 4.6, 23.5 + 0.3, 43000.0, 34.5, 10.53062, 507.2 + 0.3, 43000.0, 35.0, 16.525, 981.248 + 0.3, 43000.0, 35.5, 22.14687, 1417.91 + 0.3, 43000.0, 36.0, 26.96, 1789.46 + 0.3, 43000.0, 36.5, 30.52812, 2068.17 + 0.3, 43000.0, 37.0, 32.415, 2226.3 + 0.3, 43000.0, 37.5, 32.18437, 2236.12 + 0.3, 43000.0, 38.0, 29.4, 2069.9 + 0.3, 43000.0, 38.5, 12.90156, 1350.8 + 0.3, 43000.0, 39.0, -1.4625, 581.211 + 0.3, 43000.0, 39.5, -11.74531, -189.004 + 0.3, 43000.0, 40.0, -16.0, -910.0 + 0.3, 43000.0, 40.5, 3.025, -1438.72 + 0.3, 43000.0, 41.0, 25.85, -1855.81 + 0.3, 43000.0, 41.5, 48.3, -2148.69 + 0.3, 43000.0, 42.0, 66.2, -2304.8 + 0.3, 43000.0, 42.5, 55.23828, -2174.09 + 0.3, 43000.0, 43.0, 39.43125, -1936.48 + 0.3, 43000.0, 43.5, 22.65859, -1634.37 + 0.3, 43000.0, 44.0, 8.8, -1310.2 + 0.3, 43000.0, 44.5, 19.96953, -1082.47 + 0.3, 43000.0, 45.0, 34.51875, -887.094 + 0.3, 43000.0, 45.5, 49.03359, -736.073 + 0.3, 43000.0, 46.0, 60.1, -641.4 + 0.3, 43000.0, 46.5, 49.42109, -710.934 + 0.3, 43000.0, 47.0, 34.41875, -822.463 + 0.3, 43000.0, 47.5, 17.63203, -949.634 + 0.3, 43000.0, 48.0, 1.6, -1066.1 + 0.3, 43000.0, 48.5, -11.13828, -1145.51 + 0.3, 43000.0, 49.0, -18.04375, -1161.51 + 0.3, 43000.0, 49.5, -16.57734, -1087.76 + 0.3, 43000.0, 50.0, -4.2, -897.9 + 0.3, 48000.0, 0.0, 79.16064, 79.1606 + 0.3, 48000.0, 22.0, -56.0, 423.0 + 0.3, 48000.0, 22.5, -30.86621, 261.629 + 0.3, 48000.0, 23.0, -12.88281, 132.891 + 0.3, 48000.0, 23.5, -1.083008, 32.3816 + 0.3, 48000.0, 24.0, 5.5, -44.3 + 0.3, 48000.0, 24.5, 7.833008, -101.557 + 0.3, 48000.0, 25.0, 6.882813, -143.791 + 0.3, 48000.0, 25.5, 3.616211, -175.404 + 0.3, 48000.0, 26.0, -1.0, -200.8 + 0.3, 48000.0, 26.5, 1.260742, -270.502 + 0.3, 48000.0, 27.0, 4.520312, -345.427 + 0.3, 48000.0, 27.5, 8.500977, -422.069 + 0.3, 48000.0, 28.0, 12.925, -496.925 + 0.3, 48000.0, 28.5, 17.51465, -566.49 + 0.3, 48000.0, 29.0, 21.99219, -627.261 + 0.3, 48000.0, 29.5, 26.07988, -675.732 + 0.3, 48000.0, 30.0, 29.5, -708.4 + 0.3, 48000.0, 30.5, 26.91553, -677.338 + 0.3, 48000.0, 31.0, 23.58984, -627.695 + 0.3, 48000.0, 31.5, 19.72705, -560.196 + 0.3, 48000.0, 32.0, 15.53125, -475.569 + 0.3, 48000.0, 32.5, 11.20654, -374.539 + 0.3, 48000.0, 33.0, 6.957031, -257.834 + 0.3, 48000.0, 33.5, 2.986816, -126.178 + 0.3, 48000.0, 34.0, -0.5, 19.7 + 0.3, 48000.0, 34.5, 3.969062, 396.619 + 0.3, 48000.0, 35.0, 8.6375, 765.591 + 0.3, 48000.0, 35.5, 13.01719, 1105.17 + 0.3, 48000.0, 36.0, 16.62, 1393.91 + 0.3, 48000.0, 36.5, 18.95781, 1610.37 + 0.3, 48000.0, 37.0, 19.5425, 1733.1 + 0.3, 48000.0, 37.5, 17.88594, 1740.66 + 0.3, 48000.0, 38.0, 13.5, 1611.6 + 0.3, 48000.0, 38.5, -7.282812, 1055.25 + 0.3, 48000.0, 39.0, -24.9375, 458.989 + 0.3, 48000.0, 39.5, -37.02344, -138.788 + 0.3, 48000.0, 40.0, -41.1, -699.7 + 0.3, 48000.0, 40.5, -14.48828, -1115.65 + 0.3, 48000.0, 41.0, 16.91875, -1445.86 + 0.3, 48000.0, 41.5, 47.46641, -1679.81 + 0.3, 48000.0, 42.0, 71.5, -1807.0 + 0.3, 48000.0, 42.5, 57.42344, -1708.47 + 0.3, 48000.0, 43.0, 35.9, -1525.57 + 0.3, 48000.0, 43.5, 11.65156, -1291.18 + 0.3, 48000.0, 44.0, -10.6, -1038.2 + 0.3, 48000.0, 44.5, -8.691406, -856.258 + 0.3, 48000.0, 45.0, -2.31875, -698.788 + 0.3, 48000.0, 45.5, 6.263281, -575.973 + 0.3, 48000.0, 46.0, 14.8, -498.0 + 0.3, 48000.0, 46.5, 14.10313, -554.309 + 0.3, 48000.0, 47.0, 11.625, -644.125 + 0.3, 48000.0, 47.5, 7.884375, -745.928 + 0.3, 48000.0, 48.0, 3.4, -838.2 + 0.3, 48000.0, 48.5, -1.309375, -899.422 + 0.3, 48000.0, 49.0, -5.725, -908.075 + 0.3, 48000.0, 49.5, -9.328125, -842.641 + 0.3, 48000.0, 50.0, -11.6, -681.6 + 0.35, 0.0, 0.0, 555.2434, 555.243 + 0.35, 0.0, 22.0, 1375.5, 1009.9 + 0.35, 0.0, 22.5, 1636.535, 1099.96 + 0.35, 0.0, 23.0, 1894.883, 1188.02 + 0.35, 0.0, 23.5, 2151.439, 1274.62 + 0.35, 0.0, 24.0, 2407.1, 1360.3 + 0.35, 0.0, 24.5, 2662.761, 1445.59 + 0.35, 0.0, 25.0, 2919.317, 1531.03 + 0.35, 0.0, 25.5, 3177.665, 1617.16 + 0.35, 0.0, 26.0, 3438.7, 1704.5 + 0.35, 0.0, 26.5, 3712.724, 1798.47 + 0.35, 0.0, 27.0, 3991.764, 1895.01 + 0.35, 0.0, 27.5, 4275.103, 1993.82 + 0.35, 0.0, 28.0, 4562.025, 2094.6 + 0.35, 0.0, 28.5, 4851.812, 2197.04 + 0.35, 0.0, 29.0, 5143.748, 2300.86 + 0.35, 0.0, 29.5, 5437.117, 2405.74 + 0.35, 0.0, 30.0, 5731.2, 2511.4 + 0.35, 0.0, 30.5, 6017.751, 2613.99 + 0.35, 0.0, 31.0, 6304.302, 2717.09 + 0.35, 0.0, 31.5, 6590.851, 2820.74 + 0.35, 0.0, 32.0, 6877.4, 2924.96 + 0.35, 0.0, 32.5, 7163.949, 3029.8 + 0.35, 0.0, 33.0, 7450.498, 3135.3 + 0.35, 0.0, 33.5, 7737.049, 3241.49 + 0.35, 0.0, 34.0, 8023.6, 3348.4 + 0.35, 0.0, 34.5, 8310.163, 3457.91 + 0.35, 0.0, 35.0, 8596.727, 3568.05 + 0.35, 0.0, 35.5, 8883.291, 3678.68 + 0.35, 0.0, 36.0, 9169.855, 3789.65 + 0.35, 0.0, 36.5, 9456.419, 3900.84 + 0.35, 0.0, 37.0, 9742.981, 4012.11 + 0.35, 0.0, 37.5, 10029.54, 4123.3 + 0.35, 0.0, 38.0, 10316.1, 4234.3 + 0.35, 0.0, 38.5, 10602.65, 4344.19 + 0.35, 0.0, 39.0, 10889.19, 4454.0 + 0.35, 0.0, 39.5, 11175.74, 4563.76 + 0.35, 0.0, 40.0, 11462.3, 4673.5 + 0.35, 0.0, 40.5, 11748.88, 4783.09 + 0.35, 0.0, 41.0, 12035.46, 4892.79 + 0.35, 0.0, 41.5, 12322.03, 5002.69 + 0.35, 0.0, 42.0, 12608.6, 5112.9 + 0.35, 0.0, 42.5, 12894.91, 5223.72 + 0.35, 0.0, 43.0, 13181.29, 5334.95 + 0.35, 0.0, 43.5, 13467.86, 5446.61 + 0.35, 0.0, 44.0, 13754.7, 5558.7 + 0.35, 0.0, 44.5, 14042.83, 5671.62 + 0.35, 0.0, 45.0, 14331.05, 5784.85 + 0.35, 0.0, 45.5, 14619.1, 5898.26 + 0.35, 0.0, 46.0, 14906.7, 6011.7 + 0.35, 0.0, 46.5, 15192.23, 6124.31 + 0.35, 0.0, 47.0, 15477.31, 6236.97 + 0.35, 0.0, 47.5, 15762.21, 6349.85 + 0.35, 0.0, 48.0, 16047.2, 6463.1 + 0.35, 0.0, 48.5, 16332.56, 6576.88 + 0.35, 0.0, 49.0, 16618.54, 6691.36 + 0.35, 0.0, 49.5, 16905.44, 6806.68 + 0.35, 0.0, 50.0, 17193.5, 6923.0 + 0.35, 2000.0, 0.0, 519.8576, 519.858 + 0.35, 2000.0, 22.0, 1328.1, 956.1 + 0.35, 2000.0, 22.5, 1580.088, 1042.25 + 0.35, 2000.0, 23.0, 1829.492, 1126.56 + 0.35, 2000.0, 23.5, 2077.175, 1209.54 + 0.35, 2000.0, 24.0, 2324.0, 1291.7 + 0.35, 2000.0, 24.5, 2570.831, 1373.55 + 0.35, 2000.0, 25.0, 2818.533, 1455.59 + 0.35, 2000.0, 25.5, 3067.968, 1538.34 + 0.35, 2000.0, 26.0, 3320.0, 1622.3 + 0.35, 2000.0, 26.5, 3584.567, 1712.61 + 0.35, 2000.0, 27.0, 3853.977, 1805.41 + 0.35, 2000.0, 27.5, 4127.539, 1900.43 + 0.35, 2000.0, 28.0, 4404.56, 1997.38 + 0.35, 2000.0, 28.5, 4684.348, 2095.97 + 0.35, 2000.0, 29.0, 4966.213, 2195.93 + 0.35, 2000.0, 29.5, 5249.46, 2296.96 + 0.35, 2000.0, 30.0, 5533.4, 2398.8 + 0.35, 2000.0, 30.5, 5810.073, 2498.01 + 0.35, 2000.0, 31.0, 6086.746, 2597.76 + 0.35, 2000.0, 31.5, 6363.42, 2698.05 + 0.35, 2000.0, 32.0, 6640.094, 2798.89 + 0.35, 2000.0, 32.5, 6916.769, 2900.32 + 0.35, 2000.0, 33.0, 7193.445, 3002.33 + 0.35, 2000.0, 33.5, 7470.122, 3104.96 + 0.35, 2000.0, 34.0, 7746.8, 3208.2 + 0.35, 2000.0, 34.5, 8023.494, 3313.42 + 0.35, 2000.0, 35.0, 8300.189, 3419.16 + 0.35, 2000.0, 35.5, 8576.883, 3525.32 + 0.35, 2000.0, 36.0, 8853.575, 3631.78 + 0.35, 2000.0, 36.5, 9130.264, 3738.43 + 0.35, 2000.0, 37.0, 9406.948, 3845.16 + 0.35, 2000.0, 37.5, 9683.628, 3951.85 + 0.35, 2000.0, 38.0, 9960.3, 4058.4 + 0.35, 2000.0, 38.5, 10236.94, 4164.14 + 0.35, 2000.0, 39.0, 10513.59, 4269.8 + 0.35, 2000.0, 39.5, 10790.24, 4375.38 + 0.35, 2000.0, 40.0, 11066.9, 4480.9 + 0.35, 2000.0, 40.5, 11343.59, 4586.02 + 0.35, 2000.0, 41.0, 11620.29, 4691.23 + 0.35, 2000.0, 41.5, 11897.0, 4796.67 + 0.35, 2000.0, 42.0, 12173.7, 4902.5 + 0.35, 2000.0, 42.5, 12450.17, 5009.4 + 0.35, 2000.0, 43.0, 12726.71, 5116.76 + 0.35, 2000.0, 43.5, 13003.43, 5224.51 + 0.35, 2000.0, 44.0, 13280.4, 5332.6 + 0.35, 2000.0, 44.5, 13558.58, 5440.88 + 0.35, 2000.0, 45.0, 13836.85, 5549.38 + 0.35, 2000.0, 45.5, 14114.94, 5658.06 + 0.35, 2000.0, 46.0, 14392.6, 5766.9 + 0.35, 2000.0, 46.5, 14668.26, 5875.54 + 0.35, 2000.0, 47.0, 14943.49, 5984.38 + 0.35, 2000.0, 47.5, 15218.55, 6093.5 + 0.35, 2000.0, 48.0, 15493.7, 6203.0 + 0.35, 2000.0, 48.5, 15769.2, 6312.96 + 0.35, 2000.0, 49.0, 16045.31, 6423.48 + 0.35, 2000.0, 49.5, 16322.29, 6534.63 + 0.35, 2000.0, 50.0, 16600.4, 6646.5 + 0.35, 5000.0, 0.0, 470.1414, 470.141 + 0.35, 5000.0, 22.0, 1255.3, 879.2 + 0.35, 5000.0, 22.5, 1493.553, 959.774 + 0.35, 5000.0, 23.0, 1729.341, 1038.65 + 0.35, 5000.0, 23.5, 1963.483, 1116.29 + 0.35, 5000.0, 24.0, 2196.8, 1193.2 + 0.35, 5000.0, 24.5, 2430.111, 1269.84 + 0.35, 5000.0, 25.0, 2664.234, 1346.7 + 0.35, 5000.0, 25.5, 2899.991, 1424.26 + 0.35, 5000.0, 26.0, 3138.2, 1503.0 + 0.35, 5000.0, 26.5, 3388.283, 1587.69 + 0.35, 5000.0, 27.0, 3642.949, 1674.75 + 0.35, 5000.0, 27.5, 3901.543, 1763.95 + 0.35, 5000.0, 28.0, 4163.41, 1855.02 + 0.35, 5000.0, 28.5, 4427.894, 1947.7 + 0.35, 5000.0, 29.0, 4694.341, 2041.75 + 0.35, 5000.0, 29.5, 4962.094, 2136.9 + 0.35, 5000.0, 30.0, 5230.5, 2232.9 + 0.35, 5000.0, 30.5, 5492.017, 2327.04 + 0.35, 5000.0, 31.0, 5753.532, 2421.75 + 0.35, 5000.0, 31.5, 6015.045, 2517.02 + 0.35, 5000.0, 32.0, 6276.556, 2612.81 + 0.35, 5000.0, 32.5, 6538.067, 2709.1 + 0.35, 5000.0, 33.0, 6799.577, 2805.88 + 0.35, 5000.0, 33.5, 7061.088, 2903.12 + 0.35, 5000.0, 34.0, 7322.6, 3000.8 + 0.35, 5000.0, 34.5, 7584.122, 3099.58 + 0.35, 5000.0, 35.0, 7845.645, 3198.69 + 0.35, 5000.0, 35.5, 8107.17, 3298.04 + 0.35, 5000.0, 36.0, 8368.695, 3397.54 + 0.35, 5000.0, 36.5, 8630.221, 3497.12 + 0.35, 5000.0, 37.0, 8891.747, 3596.68 + 0.35, 5000.0, 37.5, 9153.274, 3696.14 + 0.35, 5000.0, 38.0, 9414.8, 3795.4 + 0.35, 5000.0, 38.5, 9676.33, 3893.52 + 0.35, 5000.0, 39.0, 9937.858, 3991.73 + 0.35, 5000.0, 39.5, 10199.38, 4090.12 + 0.35, 5000.0, 40.0, 10460.9, 4188.8 + 0.35, 5000.0, 40.5, 10722.4, 4288.3 + 0.35, 5000.0, 41.0, 10983.89, 4388.12 + 0.35, 5000.0, 41.5, 11245.39, 4488.21 + 0.35, 5000.0, 42.0, 11506.9, 4588.5 + 0.35, 5000.0, 42.5, 11768.24, 4688.53 + 0.35, 5000.0, 43.0, 12029.67, 4788.78 + 0.35, 5000.0, 43.5, 12291.26, 4889.34 + 0.35, 5000.0, 44.0, 12553.1, 4990.3 + 0.35, 5000.0, 44.5, 12816.06, 5092.14 + 0.35, 5000.0, 45.0, 13079.09, 5194.39 + 0.35, 5000.0, 45.5, 13341.95, 5297.0 + 0.35, 5000.0, 46.0, 13604.4, 5399.9 + 0.35, 5000.0, 46.5, 13864.97, 5502.84 + 0.35, 5000.0, 47.0, 14125.12, 5605.99 + 0.35, 5000.0, 47.5, 14385.12, 5709.38 + 0.35, 5000.0, 48.0, 14645.2, 5813.0 + 0.35, 5000.0, 48.5, 14905.61, 5916.86 + 0.35, 5000.0, 49.0, 15166.6, 6020.96 + 0.35, 5000.0, 49.5, 15428.41, 6125.3 + 0.35, 5000.0, 50.0, 15691.3, 6229.9 + 0.35, 10000.0, 0.0, 395.6912, 395.691 + 0.35, 10000.0, 22.0, 1143.4, 771.6 + 0.35, 10000.0, 22.5, 1360.404, 843.666 + 0.35, 10000.0, 23.0, 1575.177, 914.345 + 0.35, 10000.0, 23.5, 1788.46, 984.052 + 0.35, 10000.0, 24.0, 2001.0, 1053.2 + 0.35, 10000.0, 24.5, 2213.54, 1122.2 + 0.35, 10000.0, 25.0, 2426.823, 1191.48 + 0.35, 10000.0, 25.5, 2641.596, 1261.44 + 0.35, 10000.0, 26.0, 2858.6, 1332.5 + 0.35, 10000.0, 26.5, 3086.395, 1408.61 + 0.35, 10000.0, 27.0, 3318.356, 1486.84 + 0.35, 10000.0, 27.5, 3553.89, 1567.02 + 0.35, 10000.0, 28.0, 3792.4, 1648.94 + 0.35, 10000.0, 28.5, 4033.291, 1732.42 + 0.35, 10000.0, 29.0, 4275.969, 1817.27 + 0.35, 10000.0, 29.5, 4519.837, 1903.29 + 0.35, 10000.0, 30.0, 4764.3, 1990.3 + 0.35, 10000.0, 30.5, 5002.512, 2077.19 + 0.35, 10000.0, 31.0, 5240.725, 2164.77 + 0.35, 10000.0, 31.5, 5478.937, 2252.94 + 0.35, 10000.0, 32.0, 5717.15, 2341.59 + 0.35, 10000.0, 32.5, 5955.362, 2430.61 + 0.35, 10000.0, 33.0, 6193.575, 2519.91 + 0.35, 10000.0, 33.5, 6431.787, 2609.37 + 0.35, 10000.0, 34.0, 6670.0, 2698.9 + 0.35, 10000.0, 34.5, 6908.216, 2786.82 + 0.35, 10000.0, 35.0, 7146.431, 2874.75 + 0.35, 10000.0, 35.5, 7384.646, 2962.72 + 0.35, 10000.0, 36.0, 7622.86, 3050.79 + 0.35, 10000.0, 36.5, 7861.073, 3139.0 + 0.35, 10000.0, 37.0, 8099.284, 3227.39 + 0.35, 10000.0, 37.5, 8337.493, 3316.01 + 0.35, 10000.0, 38.0, 8575.7, 3404.9 + 0.35, 10000.0, 38.5, 8813.891, 3494.47 + 0.35, 10000.0, 39.0, 9052.086, 3584.22 + 0.35, 10000.0, 39.5, 9290.288, 3674.11 + 0.35, 10000.0, 40.0, 9528.5, 3764.1 + 0.35, 10000.0, 40.5, 9766.747, 3853.86 + 0.35, 10000.0, 41.0, 10005.0, 3943.77 + 0.35, 10000.0, 41.5, 10243.25, 4033.92 + 0.35, 10000.0, 42.0, 10481.5, 4124.4 + 0.35, 10000.0, 42.5, 10719.52, 4215.46 + 0.35, 10000.0, 43.0, 10957.61, 4306.95 + 0.35, 10000.0, 43.5, 11195.85, 4398.89 + 0.35, 10000.0, 44.0, 11434.3, 4491.3 + 0.35, 10000.0, 44.5, 11673.81, 4584.64 + 0.35, 10000.0, 45.0, 11913.39, 4678.31 + 0.35, 10000.0, 45.5, 12152.83, 4772.15 + 0.35, 10000.0, 46.0, 12391.9, 4866.0 + 0.35, 10000.0, 46.5, 12629.26, 4958.63 + 0.35, 10000.0, 47.0, 12866.24, 5051.39 + 0.35, 10000.0, 47.5, 13103.08, 5144.55 + 0.35, 10000.0, 48.0, 13340.0, 5238.4 + 0.35, 10000.0, 48.5, 13577.22, 5333.2 + 0.35, 10000.0, 49.0, 13814.96, 5429.24 + 0.35, 10000.0, 49.5, 14053.44, 5526.78 + 0.35, 10000.0, 50.0, 14292.9, 5626.1 + 0.35, 15000.0, 0.0, 330.8744, 330.874 + 0.35, 15000.0, 22.0, 1021.5, 666.0 + 0.35, 15000.0, 22.5, 1215.392, 729.363 + 0.35, 15000.0, 23.0, 1407.278, 791.336 + 0.35, 15000.0, 23.5, 1597.825, 852.316 + 0.35, 15000.0, 24.0, 1787.7, 912.7 + 0.35, 15000.0, 24.5, 1977.568, 972.884 + 0.35, 15000.0, 25.0, 2168.097, 1033.26 + 0.35, 15000.0, 25.5, 2359.952, 1094.24 + 0.35, 15000.0, 26.0, 2553.8, 1156.2 + 0.35, 15000.0, 26.5, 2757.298, 1222.94 + 0.35, 15000.0, 27.0, 2964.521, 1291.65 + 0.35, 15000.0, 27.5, 3174.937, 1362.15 + 0.35, 15000.0, 28.0, 3388.015, 1434.26 + 0.35, 15000.0, 28.5, 3603.222, 1507.8 + 0.35, 15000.0, 29.0, 3820.027, 1582.57 + 0.35, 15000.0, 29.5, 4037.897, 1658.4 + 0.35, 15000.0, 30.0, 4256.3, 1735.1 + 0.35, 15000.0, 30.5, 4469.124, 1811.5 + 0.35, 15000.0, 31.0, 4681.948, 1888.49 + 0.35, 15000.0, 31.5, 4894.774, 1965.99 + 0.35, 15000.0, 32.0, 5107.6, 2043.91 + 0.35, 15000.0, 32.5, 5320.426, 2122.14 + 0.35, 15000.0, 33.0, 5533.252, 2200.62 + 0.35, 15000.0, 33.5, 5746.076, 2279.23 + 0.35, 15000.0, 34.0, 5958.9, 2357.9 + 0.35, 15000.0, 34.5, 6171.712, 2435.02 + 0.35, 15000.0, 35.0, 6384.523, 2512.16 + 0.35, 15000.0, 35.5, 6597.334, 2589.37 + 0.35, 15000.0, 36.0, 6810.145, 2666.7 + 0.35, 15000.0, 36.5, 7022.956, 2744.2 + 0.35, 15000.0, 37.0, 7235.769, 2821.94 + 0.35, 15000.0, 37.5, 7448.583, 2899.95 + 0.35, 15000.0, 38.0, 7661.4, 2978.3 + 0.35, 15000.0, 38.5, 7874.224, 3057.33 + 0.35, 15000.0, 39.0, 8087.048, 3136.64 + 0.35, 15000.0, 39.5, 8299.874, 3216.24 + 0.35, 15000.0, 40.0, 8512.7, 3296.1 + 0.35, 15000.0, 40.5, 8725.529, 3376.07 + 0.35, 15000.0, 41.0, 8938.356, 3456.35 + 0.35, 15000.0, 41.5, 9151.18, 3536.98 + 0.35, 15000.0, 42.0, 9364.0, 3618.0 + 0.35, 15000.0, 42.5, 9576.638, 3699.81 + 0.35, 15000.0, 43.0, 9789.338, 3781.98 + 0.35, 15000.0, 43.5, 10002.17, 3864.41 + 0.35, 15000.0, 44.0, 10215.2, 3947.0 + 0.35, 15000.0, 44.5, 10429.17, 4028.92 + 0.35, 15000.0, 45.0, 10643.21, 4111.12 + 0.35, 15000.0, 45.5, 10857.12, 4193.81 + 0.35, 15000.0, 46.0, 11070.7, 4277.2 + 0.35, 15000.0, 46.5, 11282.75, 4361.48 + 0.35, 15000.0, 47.0, 11494.46, 4446.88 + 0.35, 15000.0, 47.5, 11706.05, 4533.61 + 0.35, 15000.0, 48.0, 11917.7, 4621.9 + 0.35, 15000.0, 48.5, 12129.62, 4711.96 + 0.35, 15000.0, 49.0, 12342.01, 4804.0 + 0.35, 15000.0, 49.5, 12555.07, 4898.24 + 0.35, 15000.0, 50.0, 12769.0, 4994.9 + 0.35, 20000.0, 0.0, 274.7482, 274.748 + 0.35, 20000.0, 22.0, 839.9, 552.1 + 0.35, 20000.0, 22.5, 999.5674, 606.526 + 0.35, 20000.0, 23.0, 1157.536, 658.508 + 0.35, 20000.0, 23.5, 1314.362, 708.536 + 0.35, 20000.0, 24.0, 1470.6, 757.1 + 0.35, 20000.0, 24.5, 1626.807, 804.689 + 0.35, 20000.0, 25.0, 1783.539, 851.792 + 0.35, 20000.0, 25.5, 1941.351, 898.899 + 0.35, 20000.0, 26.0, 2100.8, 946.5 + 0.35, 20000.0, 26.5, 2268.271, 998.987 + 0.35, 20000.0, 27.0, 2438.822, 1053.17 + 0.35, 20000.0, 27.5, 2612.012, 1108.87 + 0.35, 20000.0, 28.0, 2787.395, 1165.9 + 0.35, 20000.0, 28.5, 2964.529, 1224.09 + 0.35, 20000.0, 29.0, 3142.97, 1283.26 + 0.35, 20000.0, 29.5, 3322.275, 1343.22 + 0.35, 20000.0, 30.0, 3502.0, 1403.8 + 0.35, 20000.0, 30.5, 3676.975, 1462.53 + 0.35, 20000.0, 31.0, 3851.933, 1521.74 + 0.35, 20000.0, 31.5, 4026.881, 1581.46 + 0.35, 20000.0, 32.0, 4201.825, 1641.73 + 0.35, 20000.0, 32.5, 4376.772, 1702.59 + 0.35, 20000.0, 33.0, 4551.73, 1764.08 + 0.35, 20000.0, 33.5, 4726.703, 1826.24 + 0.35, 20000.0, 34.0, 4901.7, 1889.1 + 0.35, 20000.0, 34.5, 5076.922, 1956.65 + 0.35, 20000.0, 35.0, 5252.161, 2024.6 + 0.35, 20000.0, 35.5, 5427.406, 2092.62 + 0.35, 20000.0, 36.0, 5602.645, 2160.36 + 0.35, 20000.0, 36.5, 5777.866, 2227.5 + 0.35, 20000.0, 37.0, 5953.057, 2293.7 + 0.35, 20000.0, 37.5, 6128.205, 2358.61 + 0.35, 20000.0, 38.0, 6303.3, 2421.9 + 0.35, 20000.0, 38.5, 6478.201, 2479.1 + 0.35, 20000.0, 39.0, 6653.091, 2536.14 + 0.35, 20000.0, 39.5, 6827.985, 2593.61 + 0.35, 20000.0, 40.0, 7002.9, 2652.1 + 0.35, 20000.0, 40.5, 7177.925, 2713.84 + 0.35, 20000.0, 41.0, 7352.975, 2777.09 + 0.35, 20000.0, 41.5, 7528.037, 2841.77 + 0.35, 20000.0, 42.0, 7703.1, 2907.8 + 0.35, 20000.0, 42.5, 7877.982, 2974.86 + 0.35, 20000.0, 43.0, 8052.906, 3043.2 + 0.35, 20000.0, 43.5, 8227.927, 3112.84 + 0.35, 20000.0, 44.0, 8403.1, 3183.8 + 0.35, 20000.0, 44.5, 8578.975, 3256.76 + 0.35, 20000.0, 45.0, 8754.912, 3330.81 + 0.35, 20000.0, 45.5, 8930.769, 3405.67 + 0.35, 20000.0, 46.0, 9106.4, 3481.1 + 0.35, 20000.0, 46.5, 9280.955, 3555.75 + 0.35, 20000.0, 47.0, 9455.281, 3630.89 + 0.35, 20000.0, 47.5, 9629.516, 3706.71 + 0.35, 20000.0, 48.0, 9803.8, 3783.4 + 0.35, 20000.0, 48.5, 9978.271, 3861.14 + 0.35, 20000.0, 49.0, 10153.07, 3940.11 + 0.35, 20000.0, 49.5, 10328.33, 4020.5 + 0.35, 20000.0, 50.0, 10504.2, 4102.5 + 0.35, 25000.0, 0.0, 226.424, 226.424 + 0.35, 25000.0, 22.0, 666.5, 469.9 + 0.35, 25000.0, 22.5, 793.8979, 482.753 + 0.35, 25000.0, 23.0, 919.7672, 507.055 + 0.35, 25000.0, 23.5, 1044.578, 541.104 + 0.35, 25000.0, 24.0, 1168.8, 583.2 + 0.35, 25000.0, 24.5, 1292.903, 631.639 + 0.35, 25000.0, 25.0, 1417.358, 684.72 + 0.35, 25000.0, 25.5, 1542.633, 740.741 + 0.35, 25000.0, 26.0, 1669.2, 798.0 + 0.35, 25000.0, 26.5, 1802.413, 841.071 + 0.35, 25000.0, 27.0, 1938.135, 881.192 + 0.35, 25000.0, 27.5, 2076.0, 919.013 + 0.35, 25000.0, 28.0, 2215.64, 955.185 + 0.35, 25000.0, 28.5, 2356.688, 990.359 + 0.35, 25000.0, 29.0, 2498.775, 1025.19 + 0.35, 25000.0, 29.5, 2641.535, 1060.32 + 0.35, 25000.0, 30.0, 2784.6, 1096.4 + 0.35, 25000.0, 30.5, 2923.619, 1143.39 + 0.35, 25000.0, 31.0, 3062.587, 1191.76 + 0.35, 25000.0, 31.5, 3201.516, 1241.25 + 0.35, 25000.0, 32.0, 3340.419, 1291.65 + 0.35, 25000.0, 32.5, 3479.307, 1342.71 + 0.35, 25000.0, 33.0, 3618.191, 1394.19 + 0.35, 25000.0, 33.5, 3757.085, 1445.87 + 0.35, 25000.0, 34.0, 3896.0, 1497.5 + 0.35, 25000.0, 34.5, 4035.193, 1539.38 + 0.35, 25000.0, 35.0, 4174.408, 1581.65 + 0.35, 25000.0, 35.5, 4313.632, 1624.97 + 0.35, 25000.0, 36.0, 4452.855, 1670.02 + 0.35, 25000.0, 36.5, 4592.065, 1717.44 + 0.35, 25000.0, 37.0, 4731.25, 1767.92 + 0.35, 25000.0, 37.5, 4870.399, 1822.12 + 0.35, 25000.0, 38.0, 5009.5, 1880.7 + 0.35, 25000.0, 38.5, 5148.29, 1960.41 + 0.35, 25000.0, 39.0, 5287.141, 2037.51 + 0.35, 25000.0, 39.5, 5426.096, 2109.07 + 0.35, 25000.0, 40.0, 5565.2, 2172.2 + 0.35, 25000.0, 40.5, 5704.871, 2207.95 + 0.35, 25000.0, 41.0, 5844.631, 2235.86 + 0.35, 25000.0, 41.5, 5984.376, 2259.44 + 0.35, 25000.0, 42.0, 6124.0, 2282.2 + 0.35, 25000.0, 42.5, 6262.72, 2315.13 + 0.35, 25000.0, 43.0, 6401.381, 2351.26 + 0.35, 25000.0, 43.5, 6540.152, 2391.11 + 0.35, 25000.0, 44.0, 6679.2, 2435.2 + 0.35, 25000.0, 44.5, 6819.844, 2488.03 + 0.35, 25000.0, 45.0, 6960.637, 2544.54 + 0.35, 25000.0, 45.5, 7101.287, 2603.66 + 0.35, 25000.0, 46.0, 7241.5, 2664.3 + 0.35, 25000.0, 46.5, 7379.528, 2719.58 + 0.35, 25000.0, 47.0, 7517.113, 2776.56 + 0.35, 25000.0, 47.5, 7654.541, 2836.49 + 0.35, 25000.0, 48.0, 7792.1, 2900.6 + 0.35, 25000.0, 48.5, 7930.078, 2970.15 + 0.35, 25000.0, 49.0, 8068.762, 3046.39 + 0.35, 25000.0, 49.5, 8208.441, 3130.55 + 0.35, 25000.0, 50.0, 8349.4, 3223.9 + 0.35, 30000.0, 0.0, 185.0751, 185.075 + 0.35, 30000.0, 22.0, 454.8, 345.2 + 0.35, 30000.0, 22.5, 539.9949, 391.095 + 0.35, 30000.0, 23.0, 624.7656, 422.556 + 0.35, 30000.0, 23.5, 709.3535, 442.29 + 0.35, 30000.0, 24.0, 794.0, 453.0 + 0.35, 30000.0, 24.5, 878.9465, 457.391 + 0.35, 30000.0, 25.0, 964.4344, 458.169 + 0.35, 30000.0, 25.5, 1050.705, 458.037 + 0.35, 30000.0, 26.0, 1138.0, 459.7 + 0.35, 30000.0, 26.5, 1229.433, 493.1 + 0.35, 30000.0, 27.0, 1322.537, 535.262 + 0.35, 30000.0, 27.5, 1417.062, 584.22 + 0.35, 30000.0, 28.0, 1512.755, 638.01 + 0.35, 30000.0, 28.5, 1609.367, 694.668 + 0.35, 30000.0, 29.0, 1706.645, 752.228 + 0.35, 30000.0, 29.5, 1804.34, 808.727 + 0.35, 30000.0, 30.0, 1902.2, 862.2 + 0.35, 30000.0, 30.5, 1997.184, 880.537 + 0.35, 30000.0, 31.0, 2092.098, 894.79 + 0.35, 30000.0, 31.5, 2186.954, 905.865 + 0.35, 30000.0, 32.0, 2281.769, 914.669 + 0.35, 30000.0, 32.5, 2376.556, 922.108 + 0.35, 30000.0, 33.0, 2471.33, 929.088 + 0.35, 30000.0, 33.5, 2566.107, 936.517 + 0.35, 30000.0, 34.0, 2660.9, 945.3 + 0.35, 30000.0, 34.5, 2756.449, 963.011 + 0.35, 30000.0, 35.0, 2851.975, 983.255 + 0.35, 30000.0, 35.5, 2947.423, 1006.3 + 0.35, 30000.0, 36.0, 3042.74, 1032.43 + 0.35, 30000.0, 36.5, 3137.87, 1061.89 + 0.35, 30000.0, 37.0, 3232.76, 1094.98 + 0.35, 30000.0, 37.5, 3327.355, 1131.96 + 0.35, 30000.0, 38.0, 3421.6, 1173.1 + 0.35, 30000.0, 38.5, 3514.0, 1232.38 + 0.35, 30000.0, 39.0, 3606.689, 1289.26 + 0.35, 30000.0, 39.5, 3699.934, 1340.96 + 0.35, 30000.0, 40.0, 3794.0, 1384.7 + 0.35, 30000.0, 40.5, 3890.909, 1404.1 + 0.35, 30000.0, 41.0, 3988.469, 1415.44 + 0.35, 30000.0, 41.5, 4086.245, 1421.39 + 0.35, 30000.0, 42.0, 4183.8, 1424.6 + 0.35, 30000.0, 42.5, 4279.367, 1413.57 + 0.35, 30000.0, 43.0, 4374.375, 1410.81 + 0.35, 30000.0, 43.5, 4468.92, 1424.68 + 0.35, 30000.0, 44.0, 4563.1, 1463.5 + 0.35, 30000.0, 44.5, 4657.019, 1594.8 + 0.35, 30000.0, 45.0, 4750.762, 1744.07 + 0.35, 30000.0, 45.5, 4844.425, 1895.98 + 0.35, 30000.0, 46.0, 4938.1, 2035.2 + 0.35, 30000.0, 46.5, 5031.92, 2102.97 + 0.35, 30000.0, 47.0, 5125.925, 2144.76 + 0.35, 30000.0, 47.5, 5220.192, 2162.59 + 0.35, 30000.0, 48.0, 5314.8, 2158.5 + 0.35, 30000.0, 48.5, 5409.827, 2134.53 + 0.35, 30000.0, 49.0, 5505.35, 2092.72 + 0.35, 30000.0, 49.5, 5601.448, 2035.1 + 0.35, 30000.0, 50.0, 5698.2, 1963.7 + 0.35, 35000.0, 0.0, 149.9319, 149.932 + 0.35, 35000.0, 22.0, 471.8, 288.7 + 0.35, 35000.0, 22.5, 566.4238, 291.481 + 0.35, 35000.0, 23.0, 658.8219, 311.748 + 0.35, 35000.0, 23.5, 749.459, 346.341 + 0.35, 35000.0, 24.0, 838.8, 392.1 + 0.35, 35000.0, 24.5, 927.3098, 445.865 + 0.35, 35000.0, 25.0, 1015.453, 504.477 + 0.35, 35000.0, 25.5, 1103.695, 564.775 + 0.35, 35000.0, 26.0, 1192.5, 623.6 + 0.35, 35000.0, 26.5, 1286.304, 645.653 + 0.35, 35000.0, 27.0, 1381.827, 658.076 + 0.35, 35000.0, 27.5, 1478.854, 663.22 + 0.35, 35000.0, 28.0, 1577.17, 663.435 + 0.35, 35000.0, 28.5, 1676.558, 661.071 + 0.35, 35000.0, 29.0, 1776.803, 658.477 + 0.35, 35000.0, 29.5, 1877.689, 658.003 + 0.35, 35000.0, 30.0, 1979.0, 662.0 + 0.35, 35000.0, 30.5, 2078.761, 717.985 + 0.35, 35000.0, 31.0, 2178.684, 778.838 + 0.35, 35000.0, 31.5, 2278.719, 842.608 + 0.35, 35000.0, 32.0, 2378.819, 907.344 + 0.35, 35000.0, 32.5, 2478.935, 971.092 + 0.35, 35000.0, 33.0, 2579.02, 1031.9 + 0.35, 35000.0, 33.5, 2679.024, 1087.82 + 0.35, 35000.0, 34.0, 2778.9, 1136.9 + 0.35, 35000.0, 34.5, 2876.266, 1127.47 + 0.35, 35000.0, 35.0, 2973.63, 1112.03 + 0.35, 35000.0, 35.5, 3071.165, 1093.35 + 0.35, 35000.0, 36.0, 3169.045, 1074.24 + 0.35, 35000.0, 36.5, 3267.445, 1057.46 + 0.35, 35000.0, 37.0, 3366.538, 1045.81 + 0.35, 35000.0, 37.5, 3466.498, 1042.06 + 0.35, 35000.0, 38.0, 3567.5, 1049.0 + 0.35, 35000.0, 38.5, 3673.038, 1043.99 + 0.35, 35000.0, 39.0, 3778.244, 1068.42 + 0.35, 35000.0, 39.5, 3882.552, 1130.71 + 0.35, 35000.0, 40.0, 3985.4, 1239.3 + 0.35, 35000.0, 40.5, 4082.859, 1489.91 + 0.35, 35000.0, 41.0, 4179.075, 1768.77 + 0.35, 35000.0, 41.5, 4274.828, 2049.39 + 0.35, 35000.0, 42.0, 4370.9, 2305.3 + 0.35, 35000.0, 42.5, 4471.337, 2458.16 + 0.35, 35000.0, 43.0, 4572.35, 2554.08 + 0.35, 35000.0, 43.5, 4673.412, 2587.31 + 0.35, 35000.0, 44.0, 4774.0, 2552.1 + 0.35, 35000.0, 44.5, 4870.92, 2336.28 + 0.35, 35000.0, 45.0, 4967.381, 2083.11 + 0.35, 35000.0, 45.5, 5063.927, 1829.41 + 0.35, 35000.0, 46.0, 5161.1, 1612.0 + 0.35, 35000.0, 46.5, 5261.91, 1599.43 + 0.35, 35000.0, 47.0, 5363.444, 1644.12 + 0.35, 35000.0, 47.5, 5465.255, 1730.2 + 0.35, 35000.0, 48.0, 5566.9, 1841.8 + 0.35, 35000.0, 48.5, 5667.932, 1963.07 + 0.35, 35000.0, 49.0, 5767.906, 2078.13 + 0.35, 35000.0, 49.5, 5866.377, 2171.13 + 0.35, 35000.0, 50.0, 5962.9, 2226.2 + 0.35, 39000.0, 0.0, 124.3551, 124.355 + 0.35, 39000.0, 22.0, 361.3, 199.6 + 0.35, 39000.0, 22.5, 435.185, 186.383 + 0.35, 39000.0, 23.0, 506.6328, 198.82 + 0.35, 39000.0, 23.5, 576.1643, 232.422 + 0.35, 39000.0, 24.0, 644.3, 282.7 + 0.35, 39000.0, 24.5, 711.5607, 345.165 + 0.35, 39000.0, 25.0, 778.4672, 415.33 + 0.35, 39000.0, 25.5, 845.54, 488.704 + 0.35, 39000.0, 26.0, 913.3, 560.8 + 0.35, 39000.0, 26.5, 987.3264, 588.198 + 0.35, 39000.0, 27.0, 1063.37, 603.116 + 0.35, 39000.0, 27.5, 1141.085, 607.738 + 0.35, 39000.0, 28.0, 1220.125, 604.25 + 0.35, 39000.0, 28.5, 1300.143, 594.837 + 0.35, 39000.0, 29.0, 1380.792, 581.684 + 0.35, 39000.0, 29.5, 1461.727, 566.977 + 0.35, 39000.0, 30.0, 1542.6, 552.9 + 0.35, 39000.0, 30.5, 1618.472, 568.668 + 0.35, 39000.0, 31.0, 1694.027, 586.862 + 0.35, 39000.0, 31.5, 1769.356, 607.095 + 0.35, 39000.0, 32.0, 1844.55, 628.975 + 0.35, 39000.0, 32.5, 1919.701, 652.115 + 0.35, 39000.0, 33.0, 1994.898, 676.125 + 0.35, 39000.0, 33.5, 2070.235, 700.616 + 0.35, 39000.0, 34.0, 2145.8, 725.2 + 0.35, 39000.0, 34.5, 2224.278, 758.896 + 0.35, 39000.0, 35.0, 2302.92, 791.009 + 0.35, 39000.0, 35.5, 2381.571, 820.256 + 0.35, 39000.0, 36.0, 2460.075, 845.35 + 0.35, 39000.0, 36.5, 2538.276, 865.007 + 0.35, 39000.0, 37.0, 2616.017, 877.941 + 0.35, 39000.0, 37.5, 2693.144, 882.867 + 0.35, 39000.0, 38.0, 2769.5, 878.5 + 0.35, 39000.0, 38.5, 2842.435, 820.065 + 0.35, 39000.0, 39.0, 2915.581, 772.317 + 0.35, 39000.0, 39.5, 2989.337, 743.636 + 0.35, 39000.0, 40.0, 3064.1, 742.4 + 0.35, 39000.0, 40.5, 3142.34, 803.57 + 0.35, 39000.0, 41.0, 3221.556, 898.312 + 0.35, 39000.0, 41.5, 3301.32, 1024.37 + 0.35, 39000.0, 42.0, 3381.2, 1179.5 + 0.35, 39000.0, 42.5, 3458.217, 1397.11 + 0.35, 39000.0, 43.0, 3535.513, 1625.01 + 0.35, 39000.0, 43.5, 3613.677, 1846.68 + 0.35, 39000.0, 44.0, 3693.3, 2045.6 + 0.35, 39000.0, 44.5, 3781.11, 2183.43 + 0.35, 39000.0, 45.0, 3869.106, 2274.19 + 0.35, 39000.0, 45.5, 3955.424, 2310.11 + 0.35, 39000.0, 46.0, 4038.2, 2283.4 + 0.35, 39000.0, 46.5, 4104.827, 2098.02 + 0.35, 39000.0, 47.0, 4168.481, 1869.72 + 0.35, 39000.0, 47.5, 4231.595, 1626.01 + 0.35, 39000.0, 48.0, 4296.6, 1394.4 + 0.35, 39000.0, 48.5, 4365.93, 1202.4 + 0.35, 39000.0, 49.0, 4442.019, 1077.51 + 0.35, 39000.0, 49.5, 4527.298, 1047.24 + 0.35, 39000.0, 50.0, 4624.2, 1139.1 + 0.35, 43000.0, 0.0, 102.6052, 102.605 + 0.35, 43000.0, 22.0, 49.6, 447.3 + 0.35, 43000.0, 22.5, 72.34902, 308.718 + 0.35, 43000.0, 23.0, 93.62031, 197.547 + 0.35, 43000.0, 23.5, 113.5564, 110.278 + 0.35, 43000.0, 24.0, 132.3, 43.4 + 0.35, 43000.0, 24.5, 149.9936, -6.59648 + 0.35, 43000.0, 25.0, 166.7797, -43.2219 + 0.35, 43000.0, 25.5, 182.801, -69.9863 + 0.35, 43000.0, 26.0, 198.2, -90.4 + 0.35, 43000.0, 26.5, 213.6977, -144.202 + 0.35, 43000.0, 27.0, 228.8912, -200.744 + 0.35, 43000.0, 27.5, 243.8242, -257.325 + 0.35, 43000.0, 28.0, 258.54, -311.245 + 0.35, 43000.0, 28.5, 273.082, -359.803 + 0.35, 43000.0, 29.0, 287.4937, -400.298 + 0.35, 43000.0, 29.5, 301.8186, -430.031 + 0.35, 43000.0, 30.0, 316.1, -446.3 + 0.35, 43000.0, 30.5, 330.3638, -413.265 + 0.35, 43000.0, 31.0, 344.6727, -364.521 + 0.35, 43000.0, 31.5, 359.0718, -300.525 + 0.35, 43000.0, 32.0, 373.6063, -221.731 + 0.35, 43000.0, 32.5, 388.3212, -128.596 + 0.35, 43000.0, 33.0, 403.2617, -21.5758 + 0.35, 43000.0, 33.5, 418.4729, 98.8749 + 0.35, 43000.0, 34.0, 434.0, 232.3 + 0.35, 43000.0, 34.5, 453.6405, 579.807 + 0.35, 43000.0, 35.0, 473.3297, 920.181 + 0.35, 43000.0, 35.5, 492.7553, 1233.77 + 0.35, 43000.0, 36.0, 511.605, 1500.92 + 0.35, 43000.0, 36.5, 529.5666, 1701.98 + 0.35, 43000.0, 37.0, 546.3278, 1817.3 + 0.35, 43000.0, 37.5, 561.5764, 1827.22 + 0.35, 43000.0, 38.0, 575.0, 1712.1 + 0.35, 43000.0, 38.5, 578.6305, 1203.97 + 0.35, 43000.0, 39.0, 583.7813, 660.245 + 0.35, 43000.0, 39.5, 591.8414, 116.446 + 0.35, 43000.0, 40.0, 604.2, -391.9 + 0.35, 43000.0, 40.5, 633.1563, -763.271 + 0.35, 43000.0, 41.0, 664.825, -1054.53 + 0.35, 43000.0, 41.5, 696.2313, -1256.55 + 0.35, 43000.0, 42.0, 724.4, -1360.2 + 0.35, 43000.0, 42.5, 732.0125, -1257.2 + 0.35, 43000.0, 43.0, 736.175, -1077.23 + 0.35, 43000.0, 43.5, 739.65, -850.821 + 0.35, 43000.0, 44.0, 745.2, -608.5 + 0.35, 43000.0, 44.5, 768.5836, -435.731 + 0.35, 43000.0, 45.0, 794.3687, -286.137 + 0.35, 43000.0, 45.5, 820.1195, -168.275 + 0.35, 43000.0, 46.0, 843.4, -90.7 + 0.35, 43000.0, 46.5, 851.1531, -129.77 + 0.35, 43000.0, 47.0, 855.8125, -199.119 + 0.35, 43000.0, 47.5, 859.1906, -280.184 + 0.35, 43000.0, 48.0, 863.1, -354.4 + 0.35, 43000.0, 48.5, 869.3531, -403.204 + 0.35, 43000.0, 49.0, 879.7625, -408.031 + 0.35, 43000.0, 49.5, 896.1406, -350.318 + 0.35, 43000.0, 50.0, 920.3, -211.5 + 0.35, 48000.0, 0.0, 80.68669, 80.6867 + 0.35, 48000.0, 22.0, 18.5, 365.5 + 0.35, 48000.0, 22.5, 47.37109, 252.658 + 0.35, 48000.0, 23.0, 71.04375, 163.622 + 0.35, 48000.0, 23.5, 90.24453, 95.1996 + 0.35, 48000.0, 24.0, 105.7, 44.2 + 0.35, 48000.0, 24.5, 118.1367, 7.43164 + 0.35, 48000.0, 25.0, 128.2813, -18.2969 + 0.35, 48000.0, 25.5, 136.8602, -36.177 + 0.35, 48000.0, 26.0, 144.6, -49.4 + 0.35, 48000.0, 26.5, 157.8096, -94.1873 + 0.35, 48000.0, 27.0, 171.9522, -142.588 + 0.35, 48000.0, 27.5, 186.7975, -192.131 + 0.35, 48000.0, 28.0, 202.115, -240.345 + 0.35, 48000.0, 28.5, 217.6744, -284.76 + 0.35, 48000.0, 29.0, 233.2453, -322.905 + 0.35, 48000.0, 29.5, 248.5973, -352.308 + 0.35, 48000.0, 30.0, 263.5, -370.5 + 0.35, 48000.0, 30.5, 273.7658, -343.341 + 0.35, 48000.0, 31.0, 283.4984, -303.045 + 0.35, 48000.0, 31.5, 292.8443, -250.155 + 0.35, 48000.0, 32.0, 301.95, -185.219 + 0.35, 48000.0, 32.5, 310.9619, -108.78 + 0.35, 48000.0, 33.0, 320.0266, -21.3836 + 0.35, 48000.0, 33.5, 329.2904, 76.4247 + 0.35, 48000.0, 34.0, 338.9, 184.1 + 0.35, 48000.0, 34.5, 354.1861, 454.909 + 0.35, 48000.0, 35.0, 369.6172, 719.847 + 0.35, 48000.0, 35.5, 384.8459, 963.718 + 0.35, 48000.0, 36.0, 399.525, 1171.33 + 0.35, 48000.0, 36.5, 413.3072, 1327.49 + 0.35, 48000.0, 37.0, 425.8453, 1417.0 + 0.35, 48000.0, 37.5, 436.792, 1424.67 + 0.35, 48000.0, 38.0, 445.8, 1335.3 + 0.35, 48000.0, 38.5, 443.1459, 942.237 + 0.35, 48000.0, 39.0, 442.7203, 521.03 + 0.35, 48000.0, 39.5, 446.2596, 99.0326 + 0.35, 48000.0, 40.0, 455.5, -296.4 + 0.35, 48000.0, 40.5, 486.5773, -588.595 + 0.35, 48000.0, 41.0, 521.0687, -819.244 + 0.35, 48000.0, 41.5, 554.9508, -980.721 + 0.35, 48000.0, 42.0, 584.2, -1065.4 + 0.35, 48000.0, 42.5, 586.3437, -987.392 + 0.35, 48000.0, 43.0, 583.1875, -848.637 + 0.35, 48000.0, 43.5, 578.0875, -672.814 + 0.35, 48000.0, 44.0, 574.4, -483.6 + 0.35, 48000.0, 44.5, 587.8719, -345.728 + 0.35, 48000.0, 45.0, 604.5125, -225.4 + 0.35, 48000.0, 45.5, 622.7219, -129.872 + 0.35, 48000.0, 46.0, 640.9, -66.4 + 0.35, 48000.0, 46.5, 652.5328, -98.2953 + 0.35, 48000.0, 47.0, 662.9, -154.337 + 0.35, 48000.0, 47.5, 672.3672, -219.361 + 0.35, 48000.0, 48.0, 681.3, -278.2 + 0.35, 48000.0, 48.5, 690.0641, -315.689 + 0.35, 48000.0, 49.0, 699.025, -316.662 + 0.35, 48000.0, 49.5, 708.5484, -265.955 + 0.35, 48000.0, 50.0, 719.0, -148.4 + 0.4, 0.0, 0.0, 567.5271, 567.527 + 0.4, 0.0, 22.0, 1337.8, 1076.7 + 0.4, 0.0, 22.5, 1591.61, 1171.94 + 0.4, 0.0, 23.0, 1842.759, 1261.98 + 0.4, 0.0, 23.5, 2092.129, 1348.01 + 0.4, 0.0, 24.0, 2340.6, 1431.2 + 0.4, 0.0, 24.5, 2589.052, 1512.72 + 0.4, 0.0, 25.0, 2838.366, 1593.74 + 0.4, 0.0, 25.5, 3089.421, 1675.44 + 0.4, 0.0, 26.0, 3343.1, 1759.0 + 0.4, 0.0, 26.5, 3609.527, 1856.92 + 0.4, 0.0, 27.0, 3880.865, 1959.69 + 0.4, 0.0, 27.5, 4156.411, 2066.54 + 0.4, 0.0, 28.0, 4435.46, 2176.71 + 0.4, 0.0, 28.5, 4717.308, 2289.41 + 0.4, 0.0, 29.0, 5001.25, 2403.89 + 0.4, 0.0, 29.5, 5286.582, 2519.38 + 0.4, 0.0, 30.0, 5572.6, 2635.1 + 0.4, 0.0, 30.5, 5851.162, 2739.94 + 0.4, 0.0, 31.0, 6129.709, 2844.47 + 0.4, 0.0, 31.5, 6408.246, 2948.89 + 0.4, 0.0, 32.0, 6686.775, 3053.44 + 0.4, 0.0, 32.5, 6965.301, 3158.31 + 0.4, 0.0, 33.0, 7243.828, 3263.74 + 0.4, 0.0, 33.5, 7522.36, 3369.93 + 0.4, 0.0, 34.0, 7800.9, 3477.1 + 0.4, 0.0, 34.5, 8079.523, 3596.08 + 0.4, 0.0, 35.0, 8358.156, 3715.47 + 0.4, 0.0, 35.5, 8636.796, 3834.47 + 0.4, 0.0, 36.0, 8915.44, 3952.28 + 0.4, 0.0, 36.5, 9194.085, 4068.12 + 0.4, 0.0, 37.0, 9472.729, 4181.18 + 0.4, 0.0, 37.5, 9751.368, 4290.67 + 0.4, 0.0, 38.0, 10030.0, 4395.8 + 0.4, 0.0, 38.5, 10308.6, 4489.23 + 0.4, 0.0, 39.0, 10587.2, 4580.11 + 0.4, 0.0, 39.5, 10865.8, 4669.08 + 0.4, 0.0, 40.0, 11144.4, 4756.8 + 0.4, 0.0, 40.5, 11423.04, 4843.01 + 0.4, 0.0, 41.0, 11701.67, 4929.66 + 0.4, 0.0, 41.5, 11980.26, 5017.78 + 0.4, 0.0, 42.0, 12258.8, 5108.4 + 0.4, 0.0, 42.5, 12536.91, 5203.9 + 0.4, 0.0, 43.0, 12815.08, 5303.41 + 0.4, 0.0, 43.5, 13093.43, 5407.42 + 0.4, 0.0, 44.0, 13372.1, 5516.4 + 0.4, 0.0, 44.5, 13652.27, 5634.91 + 0.4, 0.0, 45.0, 13932.59, 5757.74 + 0.4, 0.0, 45.5, 14212.76, 5883.75 + 0.4, 0.0, 46.0, 14492.5, 6011.8 + 0.4, 0.0, 46.5, 14770.08, 6138.44 + 0.4, 0.0, 47.0, 15047.2, 6265.75 + 0.4, 0.0, 47.5, 15324.15, 6393.51 + 0.4, 0.0, 48.0, 15601.2, 6521.5 + 0.4, 0.0, 48.5, 15878.63, 6649.5 + 0.4, 0.0, 49.0, 16156.72, 6777.27 + 0.4, 0.0, 49.5, 16435.75, 6904.62 + 0.4, 0.0, 50.0, 16716.0, 7031.3 + 0.4, 2000.0, 0.0, 531.3585, 531.358 + 0.4, 2000.0, 22.0, 1073.9, 941.4 + 0.4, 2000.0, 22.5, 1277.736, 1013.93 + 0.4, 2000.0, 23.0, 1479.464, 1085.32 + 0.4, 2000.0, 23.5, 1679.785, 1155.9 + 0.4, 2000.0, 24.0, 1879.4, 1226.0 + 0.4, 2000.0, 24.5, 2079.008, 1295.95 + 0.4, 2000.0, 25.0, 2279.311, 1366.08 + 0.4, 2000.0, 25.5, 2481.008, 1436.72 + 0.4, 2000.0, 26.0, 2684.8, 1508.2 + 0.4, 2000.0, 26.5, 2898.736, 1583.95 + 0.4, 2000.0, 27.0, 3116.588, 1661.37 + 0.4, 2000.0, 27.5, 3337.795, 1740.25 + 0.4, 2000.0, 28.0, 3561.8, 1820.41 + 0.4, 2000.0, 28.5, 3788.042, 1901.62 + 0.4, 2000.0, 29.0, 4015.963, 1983.69 + 0.4, 2000.0, 29.5, 4245.002, 2066.42 + 0.4, 2000.0, 30.0, 4474.6, 2149.6 + 0.4, 2000.0, 30.5, 4698.323, 2230.62 + 0.4, 2000.0, 31.0, 4922.046, 2311.91 + 0.4, 2000.0, 31.5, 5145.77, 2393.5 + 0.4, 2000.0, 32.0, 5369.494, 2475.42 + 0.4, 2000.0, 32.5, 5593.219, 2557.69 + 0.4, 2000.0, 33.0, 5816.945, 2640.35 + 0.4, 2000.0, 33.5, 6040.672, 2723.41 + 0.4, 2000.0, 34.0, 6264.4, 2806.9 + 0.4, 2000.0, 34.5, 6488.138, 2891.41 + 0.4, 2000.0, 35.0, 6711.877, 2976.35 + 0.4, 2000.0, 35.5, 6935.616, 3061.7 + 0.4, 2000.0, 36.0, 7159.355, 3147.43 + 0.4, 2000.0, 36.5, 7383.094, 3233.51 + 0.4, 2000.0, 37.0, 7606.831, 3319.92 + 0.4, 2000.0, 37.5, 7830.567, 3406.62 + 0.4, 2000.0, 38.0, 8054.3, 3493.6 + 0.4, 2000.0, 38.5, 8278.021, 3580.82 + 0.4, 2000.0, 39.0, 8501.744, 3668.27 + 0.4, 2000.0, 39.5, 8725.47, 3755.9 + 0.4, 2000.0, 40.0, 8949.2, 3843.7 + 0.4, 2000.0, 40.5, 9172.948, 3931.44 + 0.4, 2000.0, 41.0, 9396.7, 4019.37 + 0.4, 2000.0, 41.5, 9620.452, 4107.54 + 0.4, 2000.0, 42.0, 9844.2, 4196.0 + 0.4, 2000.0, 42.5, 10067.75, 4285.04 + 0.4, 2000.0, 43.0, 10291.37, 4374.38 + 0.4, 2000.0, 43.5, 10515.13, 4463.98 + 0.4, 2000.0, 44.0, 10739.1, 4553.8 + 0.4, 2000.0, 44.5, 10964.06, 4643.92 + 0.4, 2000.0, 45.0, 11189.08, 4734.14 + 0.4, 2000.0, 45.5, 11413.97, 4824.36 + 0.4, 2000.0, 46.0, 11638.5, 4914.5 + 0.4, 2000.0, 46.5, 11861.41, 5004.0 + 0.4, 2000.0, 47.0, 12083.97, 5093.43 + 0.4, 2000.0, 47.5, 12306.4, 5182.9 + 0.4, 2000.0, 48.0, 12528.9, 5272.5 + 0.4, 2000.0, 48.5, 12751.69, 5362.34 + 0.4, 2000.0, 49.0, 12974.97, 5452.52 + 0.4, 2000.0, 49.5, 13198.97, 5543.14 + 0.4, 2000.0, 50.0, 13423.9, 5634.3 + 0.4, 5000.0, 0.0, 480.5424, 480.542 + 0.4, 5000.0, 22.0, 1019.1, 864.7 + 0.4, 5000.0, 22.5, 1212.498, 933.29 + 0.4, 5000.0, 23.0, 1403.905, 1000.59 + 0.4, 5000.0, 23.5, 1593.984, 1066.94 + 0.4, 5000.0, 24.0, 1783.4, 1132.7 + 0.4, 5000.0, 24.5, 1972.816, 1198.21 + 0.4, 5000.0, 25.0, 2162.895, 1263.81 + 0.4, 5000.0, 25.5, 2354.302, 1329.86 + 0.4, 5000.0, 26.0, 2547.7, 1396.7 + 0.4, 5000.0, 26.5, 2750.722, 1467.86 + 0.4, 5000.0, 27.0, 2957.462, 1540.68 + 0.4, 5000.0, 27.5, 3167.386, 1614.97 + 0.4, 5000.0, 28.0, 3379.965, 1690.54 + 0.4, 5000.0, 28.5, 3594.667, 1767.18 + 0.4, 5000.0, 29.0, 3810.961, 1844.71 + 0.4, 5000.0, 29.5, 4028.316, 1922.91 + 0.4, 5000.0, 30.0, 4246.2, 2001.6 + 0.4, 5000.0, 30.5, 4458.499, 2078.35 + 0.4, 5000.0, 31.0, 4670.798, 2155.41 + 0.4, 5000.0, 31.5, 4883.096, 2232.78 + 0.4, 5000.0, 32.0, 5095.394, 2310.48 + 0.4, 5000.0, 32.5, 5307.693, 2388.53 + 0.4, 5000.0, 33.0, 5519.993, 2466.94 + 0.4, 5000.0, 33.5, 5732.295, 2545.72 + 0.4, 5000.0, 34.0, 5944.6, 2624.9 + 0.4, 5000.0, 34.5, 6156.926, 2705.01 + 0.4, 5000.0, 35.0, 6369.253, 2785.49 + 0.4, 5000.0, 35.5, 6581.582, 2866.3 + 0.4, 5000.0, 36.0, 6793.91, 2947.4 + 0.4, 5000.0, 36.5, 7006.237, 3028.78 + 0.4, 5000.0, 37.0, 7218.562, 3110.37 + 0.4, 5000.0, 37.5, 7430.883, 3192.16 + 0.4, 5000.0, 38.0, 7643.2, 3274.1 + 0.4, 5000.0, 38.5, 7855.503, 3355.76 + 0.4, 5000.0, 39.0, 8067.803, 3437.7 + 0.4, 5000.0, 39.5, 8280.102, 3520.0 + 0.4, 5000.0, 40.0, 8492.4, 3602.7 + 0.4, 5000.0, 40.5, 8704.7, 3686.23 + 0.4, 5000.0, 41.0, 8917.0, 3770.12 + 0.4, 5000.0, 41.5, 9129.3, 3854.28 + 0.4, 5000.0, 42.0, 9341.6, 3938.6 + 0.4, 5000.0, 42.5, 9553.732, 4022.72 + 0.4, 5000.0, 43.0, 9765.931, 4106.91 + 0.4, 5000.0, 43.5, 9978.265, 4191.2 + 0.4, 5000.0, 44.0, 10190.8, 4275.6 + 0.4, 5000.0, 44.5, 10404.27, 4360.31 + 0.4, 5000.0, 45.0, 10617.81, 4445.08 + 0.4, 5000.0, 45.5, 10831.22, 4529.83 + 0.4, 5000.0, 46.0, 11044.3, 4614.5 + 0.4, 5000.0, 46.5, 11255.85, 4698.7 + 0.4, 5000.0, 47.0, 11467.06, 4782.81 + 0.4, 5000.0, 47.5, 11678.15, 4866.89 + 0.4, 5000.0, 48.0, 11889.3, 4951.0 + 0.4, 5000.0, 48.5, 12100.72, 5035.21 + 0.4, 5000.0, 49.0, 12312.61, 5119.57 + 0.4, 5000.0, 49.5, 12525.17, 5204.15 + 0.4, 5000.0, 50.0, 12738.6, 5289.0 + 0.4, 10000.0, 0.0, 404.4451, 404.445 + 0.4, 10000.0, 22.0, 936.2, 758.0 + 0.4, 10000.0, 22.5, 1113.883, 820.313 + 0.4, 10000.0, 23.0, 1289.737, 881.286 + 0.4, 10000.0, 23.5, 1464.373, 941.266 + 0.4, 10000.0, 24.0, 1638.4, 1000.6 + 0.4, 10000.0, 24.5, 1812.427, 1059.63 + 0.4, 10000.0, 25.0, 1987.062, 1118.71 + 0.4, 10000.0, 25.5, 2162.917, 1178.19 + 0.4, 10000.0, 26.0, 2340.6, 1238.4 + 0.4, 10000.0, 26.5, 2527.119, 1302.76 + 0.4, 10000.0, 27.0, 2717.05, 1368.74 + 0.4, 10000.0, 27.5, 2909.906, 1436.14 + 0.4, 10000.0, 28.0, 3105.2, 1504.78 + 0.4, 10000.0, 28.5, 3302.444, 1574.51 + 0.4, 10000.0, 29.0, 3501.15, 1645.12 + 0.4, 10000.0, 29.5, 3700.831, 1716.44 + 0.4, 10000.0, 30.0, 3901.0, 1788.3 + 0.4, 10000.0, 30.5, 4096.048, 1858.68 + 0.4, 10000.0, 31.0, 4291.096, 1929.4 + 0.4, 10000.0, 31.5, 4486.145, 2000.48 + 0.4, 10000.0, 32.0, 4681.194, 2071.89 + 0.4, 10000.0, 32.5, 4876.244, 2143.65 + 0.4, 10000.0, 33.0, 5071.295, 2215.74 + 0.4, 10000.0, 33.5, 5266.347, 2288.16 + 0.4, 10000.0, 34.0, 5461.4, 2360.9 + 0.4, 10000.0, 34.5, 5656.463, 2433.9 + 0.4, 10000.0, 35.0, 5851.527, 2507.22 + 0.4, 10000.0, 35.5, 6046.591, 2580.87 + 0.4, 10000.0, 36.0, 6241.655, 2654.85 + 0.4, 10000.0, 36.5, 6436.719, 2729.16 + 0.4, 10000.0, 37.0, 6631.781, 2803.8 + 0.4, 10000.0, 37.5, 6826.842, 2878.78 + 0.4, 10000.0, 38.0, 7021.9, 2954.1 + 0.4, 10000.0, 38.5, 7216.951, 3030.1 + 0.4, 10000.0, 39.0, 7412.002, 3106.26 + 0.4, 10000.0, 39.5, 7607.051, 3182.52 + 0.4, 10000.0, 40.0, 7802.1, 3258.8 + 0.4, 10000.0, 40.5, 7997.15, 3334.73 + 0.4, 10000.0, 41.0, 8192.2, 3410.65 + 0.4, 10000.0, 41.5, 8387.25, 3486.63 + 0.4, 10000.0, 42.0, 8582.3, 3562.7 + 0.4, 10000.0, 42.5, 8777.198, 3639.17 + 0.4, 10000.0, 43.0, 8972.156, 3715.75 + 0.4, 10000.0, 43.5, 9167.237, 3792.37 + 0.4, 10000.0, 44.0, 9362.5, 3869.0 + 0.4, 10000.0, 44.5, 9558.616, 3945.37 + 0.4, 10000.0, 45.0, 9754.794, 4021.72 + 0.4, 10000.0, 45.5, 9950.849, 4098.09 + 0.4, 10000.0, 46.0, 10146.6, 4174.5 + 0.4, 10000.0, 46.5, 10340.95, 4250.92 + 0.4, 10000.0, 47.0, 10534.99, 4327.47 + 0.4, 10000.0, 47.5, 10728.92, 4404.21 + 0.4, 10000.0, 48.0, 10922.9, 4481.2 + 0.4, 10000.0, 48.5, 11117.13, 4558.5 + 0.4, 10000.0, 49.0, 11311.78, 4636.16 + 0.4, 10000.0, 49.5, 11507.04, 4714.24 + 0.4, 10000.0, 50.0, 11703.1, 4792.8 + 0.4, 15000.0, 0.0, 338.1943, 338.194 + 0.4, 15000.0, 22.0, 839.1, 653.0 + 0.4, 15000.0, 22.5, 998.3613, 707.37 + 0.4, 15000.0, 23.0, 1155.984, 760.741 + 0.4, 15000.0, 23.5, 1312.515, 813.391 + 0.4, 15000.0, 24.0, 1468.5, 865.6 + 0.4, 15000.0, 24.5, 1624.485, 917.646 + 0.4, 15000.0, 25.0, 1781.016, 969.809 + 0.4, 15000.0, 25.5, 1938.639, 1022.37 + 0.4, 15000.0, 26.0, 2097.9, 1075.6 + 0.4, 15000.0, 26.5, 2265.08, 1132.28 + 0.4, 15000.0, 27.0, 2435.318, 1190.32 + 0.4, 15000.0, 27.5, 2608.177, 1249.6 + 0.4, 15000.0, 28.0, 2783.22, 1309.95 + 0.4, 15000.0, 28.5, 2960.011, 1371.24 + 0.4, 15000.0, 29.0, 3138.112, 1433.31 + 0.4, 15000.0, 29.5, 3317.088, 1496.01 + 0.4, 15000.0, 30.0, 3496.5, 1559.2 + 0.4, 15000.0, 30.5, 3671.325, 1621.18 + 0.4, 15000.0, 31.0, 3846.15, 1683.5 + 0.4, 15000.0, 31.5, 4020.975, 1746.16 + 0.4, 15000.0, 32.0, 4195.8, 1809.15 + 0.4, 15000.0, 32.5, 4370.625, 1872.48 + 0.4, 15000.0, 33.0, 4545.45, 1936.15 + 0.4, 15000.0, 33.5, 4720.275, 2000.16 + 0.4, 15000.0, 34.0, 4895.1, 2064.5 + 0.4, 15000.0, 34.5, 5069.932, 2129.57 + 0.4, 15000.0, 35.0, 5244.762, 2194.94 + 0.4, 15000.0, 35.5, 5419.592, 2260.57 + 0.4, 15000.0, 36.0, 5594.42, 2326.43 + 0.4, 15000.0, 36.5, 5769.245, 2392.46 + 0.4, 15000.0, 37.0, 5944.067, 2458.65 + 0.4, 15000.0, 37.5, 6118.886, 2524.94 + 0.4, 15000.0, 38.0, 6293.7, 2591.3 + 0.4, 15000.0, 38.5, 6468.497, 2657.39 + 0.4, 15000.0, 39.0, 6643.295, 2723.64 + 0.4, 15000.0, 39.5, 6818.096, 2790.07 + 0.4, 15000.0, 40.0, 6992.9, 2856.7 + 0.4, 15000.0, 40.5, 7167.72, 2923.77 + 0.4, 15000.0, 41.0, 7342.544, 2991.03 + 0.4, 15000.0, 41.5, 7517.371, 3058.42 + 0.4, 15000.0, 42.0, 7692.2, 3125.9 + 0.4, 15000.0, 42.5, 7866.888, 3193.15 + 0.4, 15000.0, 43.0, 8041.631, 3260.49 + 0.4, 15000.0, 43.5, 8216.484, 3327.95 + 0.4, 15000.0, 44.0, 8391.5, 3395.6 + 0.4, 15000.0, 44.5, 8567.278, 3463.7 + 0.4, 15000.0, 45.0, 8743.113, 3531.99 + 0.4, 15000.0, 45.5, 8918.841, 3600.43 + 0.4, 15000.0, 46.0, 9094.3, 3669.0 + 0.4, 15000.0, 46.5, 9268.52, 3737.05 + 0.4, 15000.0, 47.0, 9442.469, 3805.38 + 0.4, 15000.0, 47.5, 9616.309, 3874.19 + 0.4, 15000.0, 48.0, 9790.2, 3943.7 + 0.4, 15000.0, 48.5, 9964.304, 4014.1 + 0.4, 15000.0, 49.0, 10138.78, 4085.6 + 0.4, 15000.0, 49.5, 10313.79, 4158.4 + 0.4, 15000.0, 50.0, 10489.5, 4232.7 + 0.4, 20000.0, 0.0, 280.8265, 280.827 + 0.4, 20000.0, 22.0, 824.9, 588.3 + 0.4, 20000.0, 22.5, 981.4535, 639.531 + 0.4, 20000.0, 23.0, 1136.397, 690.386 + 0.4, 20000.0, 23.5, 1290.267, 741.047 + 0.4, 20000.0, 24.0, 1443.6, 791.7 + 0.4, 20000.0, 24.5, 1596.933, 842.528 + 0.4, 20000.0, 25.0, 1750.803, 893.714 + 0.4, 20000.0, 25.5, 1905.746, 945.444 + 0.4, 20000.0, 26.0, 2062.3, 997.9 + 0.4, 20000.0, 26.5, 2226.636, 1052.97 + 0.4, 20000.0, 27.0, 2393.978, 1109.23 + 0.4, 20000.0, 27.5, 2563.895, 1166.57 + 0.4, 20000.0, 28.0, 2735.96, 1224.9 + 0.4, 20000.0, 28.5, 2909.742, 1284.09 + 0.4, 20000.0, 29.0, 3084.813, 1344.04 + 0.4, 20000.0, 29.5, 3260.742, 1404.65 + 0.4, 20000.0, 30.0, 3437.1, 1465.8 + 0.4, 20000.0, 30.5, 3608.948, 1526.4 + 0.4, 20000.0, 31.0, 3780.796, 1587.44 + 0.4, 20000.0, 31.5, 3952.645, 1648.88 + 0.4, 20000.0, 32.0, 4124.494, 1710.72 + 0.4, 20000.0, 32.5, 4296.344, 1772.95 + 0.4, 20000.0, 33.0, 4468.195, 1835.54 + 0.4, 20000.0, 33.5, 4640.047, 1898.5 + 0.4, 20000.0, 34.0, 4811.9, 1961.8 + 0.4, 20000.0, 34.5, 4983.763, 2025.68 + 0.4, 20000.0, 35.0, 5155.627, 2089.86 + 0.4, 20000.0, 35.5, 5327.491, 2154.29 + 0.4, 20000.0, 36.0, 5499.355, 2218.94 + 0.4, 20000.0, 36.5, 5671.219, 2283.77 + 0.4, 20000.0, 37.0, 5843.081, 2348.75 + 0.4, 20000.0, 37.5, 6014.942, 2413.84 + 0.4, 20000.0, 38.0, 6186.8, 2479.0 + 0.4, 20000.0, 38.5, 6358.651, 2543.85 + 0.4, 20000.0, 39.0, 6530.502, 2608.87 + 0.4, 20000.0, 39.5, 6702.351, 2674.11 + 0.4, 20000.0, 40.0, 6874.2, 2739.6 + 0.4, 20000.0, 40.5, 7046.05, 2805.29 + 0.4, 20000.0, 41.0, 7217.9, 2871.35 + 0.4, 20000.0, 41.5, 7389.75, 2937.86 + 0.4, 20000.0, 42.0, 7561.6, 3004.9 + 0.4, 20000.0, 42.5, 7733.317, 3072.64 + 0.4, 20000.0, 43.0, 7905.088, 3141.02 + 0.4, 20000.0, 43.5, 8076.964, 3210.09 + 0.4, 20000.0, 44.0, 8249.0, 3279.9 + 0.4, 20000.0, 44.5, 8421.78, 3350.58 + 0.4, 20000.0, 45.0, 8594.612, 3422.04 + 0.4, 20000.0, 45.5, 8767.339, 3494.28 + 0.4, 20000.0, 46.0, 8939.8, 3567.3 + 0.4, 20000.0, 46.5, 9111.035, 3640.79 + 0.4, 20000.0, 47.0, 9282.006, 3715.19 + 0.4, 20000.0, 47.5, 9452.874, 3790.62 + 0.4, 20000.0, 48.0, 9623.8, 3867.2 + 0.4, 20000.0, 48.5, 9794.945, 3945.07 + 0.4, 20000.0, 49.0, 9966.469, 4024.34 + 0.4, 20000.0, 49.5, 10138.53, 4105.14 + 0.4, 20000.0, 50.0, 10311.3, 4187.6 + 0.4, 25000.0, 0.0, 231.4332, 231.433 + 0.4, 25000.0, 22.0, 662.5, 487.8 + 0.4, 25000.0, 22.5, 788.4654, 520.379 + 0.4, 25000.0, 23.0, 913.0766, 556.23 + 0.4, 25000.0, 23.5, 1036.774, 594.94 + 0.4, 25000.0, 24.0, 1160.0, 636.1 + 0.4, 25000.0, 24.5, 1283.194, 679.297 + 0.4, 25000.0, 25.0, 1406.798, 724.12 + 0.4, 25000.0, 25.5, 1531.253, 770.158 + 0.4, 25000.0, 26.0, 1657.0, 817.0 + 0.4, 25000.0, 26.5, 1789.099, 861.144 + 0.4, 25000.0, 27.0, 1923.636, 905.092 + 0.4, 25000.0, 27.5, 2060.26, 948.963 + 0.4, 25000.0, 28.0, 2198.62, 992.875 + 0.4, 25000.0, 28.5, 2338.365, 1036.95 + 0.4, 25000.0, 29.0, 2479.144, 1081.3 + 0.4, 25000.0, 29.5, 2620.606, 1126.04 + 0.4, 25000.0, 30.0, 2762.4, 1171.3 + 0.4, 25000.0, 30.5, 2900.452, 1219.21 + 0.4, 25000.0, 31.0, 3038.488, 1267.67 + 0.4, 25000.0, 31.5, 3176.514, 1316.62 + 0.4, 25000.0, 32.0, 3314.531, 1365.99 + 0.4, 25000.0, 32.5, 3452.545, 1415.69 + 0.4, 25000.0, 33.0, 3590.559, 1465.66 + 0.4, 25000.0, 33.5, 3728.576, 1515.82 + 0.4, 25000.0, 34.0, 3866.6, 1566.1 + 0.4, 25000.0, 34.5, 4004.714, 1613.48 + 0.4, 25000.0, 35.0, 4142.836, 1661.11 + 0.4, 25000.0, 35.5, 4280.961, 1709.2 + 0.4, 25000.0, 36.0, 4419.085, 1757.96 + 0.4, 25000.0, 36.5, 4557.205, 1807.59 + 0.4, 25000.0, 37.0, 4695.317, 1858.3 + 0.4, 25000.0, 37.5, 4833.416, 1910.3 + 0.4, 25000.0, 38.0, 4971.5, 1963.8 + 0.4, 25000.0, 38.5, 5109.487, 2023.79 + 0.4, 25000.0, 39.0, 5247.491, 2083.21 + 0.4, 25000.0, 39.5, 5385.524, 2141.2 + 0.4, 25000.0, 40.0, 5523.6, 2196.9 + 0.4, 25000.0, 40.5, 5661.836, 2244.56 + 0.4, 25000.0, 41.0, 5800.1, 2290.18 + 0.4, 25000.0, 41.5, 5938.364, 2334.85 + 0.4, 25000.0, 42.0, 6076.6, 2379.7 + 0.4, 25000.0, 42.5, 6214.526, 2428.23 + 0.4, 25000.0, 43.0, 6352.469, 2478.17 + 0.4, 25000.0, 43.5, 6490.502, 2529.65 + 0.4, 25000.0, 44.0, 6628.7, 2582.8 + 0.4, 25000.0, 44.5, 6767.748, 2639.07 + 0.4, 25000.0, 45.0, 6906.862, 2696.77 + 0.4, 25000.0, 45.5, 7045.87, 2755.51 + 0.4, 25000.0, 46.0, 7184.6, 2814.9 + 0.4, 25000.0, 46.5, 7322.016, 2872.47 + 0.4, 25000.0, 47.0, 7459.156, 2930.76 + 0.4, 25000.0, 47.5, 7596.193, 2990.22 + 0.4, 25000.0, 48.0, 7733.3, 3051.3 + 0.4, 25000.0, 48.5, 7870.651, 3114.45 + 0.4, 25000.0, 49.0, 8008.419, 3180.11 + 0.4, 25000.0, 49.5, 8146.777, 3248.75 + 0.4, 25000.0, 50.0, 8285.9, 3320.8 + 0.4, 30000.0, 0.0, 189.1695, 189.17 + 0.4, 30000.0, 22.0, 481.8, 381.0 + 0.4, 30000.0, 22.5, 572.5955, 418.983 + 0.4, 30000.0, 23.0, 662.7234, 449.85 + 0.4, 30000.0, 23.5, 752.4646, 474.992 + 0.4, 30000.0, 24.0, 842.1, 495.8 + 0.4, 30000.0, 24.5, 931.9104, 513.664 + 0.4, 30000.0, 25.0, 1022.177, 529.975 + 0.4, 30000.0, 25.5, 1113.179, 546.123 + 0.4, 30000.0, 26.0, 1205.2, 563.5 + 0.4, 30000.0, 26.5, 1301.662, 597.651 + 0.4, 30000.0, 27.0, 1399.883, 636.621 + 0.4, 30000.0, 27.5, 1499.605, 679.372 + 0.4, 30000.0, 28.0, 1600.57, 724.87 + 0.4, 30000.0, 28.5, 1702.52, 772.078 + 0.4, 30000.0, 29.0, 1805.197, 819.959 + 0.4, 30000.0, 29.5, 1908.343, 867.479 + 0.4, 30000.0, 30.0, 2011.7, 913.6 + 0.4, 30000.0, 30.5, 2112.22, 941.767 + 0.4, 30000.0, 31.0, 2212.7, 967.941 + 0.4, 30000.0, 31.5, 2313.149, 992.566 + 0.4, 30000.0, 32.0, 2413.575, 1016.08 + 0.4, 30000.0, 32.5, 2513.985, 1038.93 + 0.4, 30000.0, 33.0, 2614.388, 1061.56 + 0.4, 30000.0, 33.5, 2714.79, 1084.4 + 0.4, 30000.0, 34.0, 2815.2, 1107.9 + 0.4, 30000.0, 34.5, 2915.998, 1135.24 + 0.4, 30000.0, 35.0, 3016.784, 1163.86 + 0.4, 30000.0, 35.5, 3117.531, 1193.94 + 0.4, 30000.0, 36.0, 3218.21, 1225.68 + 0.4, 30000.0, 36.5, 3318.794, 1259.23 + 0.4, 30000.0, 37.0, 3419.256, 1294.8 + 0.4, 30000.0, 37.5, 3519.567, 1332.57 + 0.4, 30000.0, 38.0, 3619.7, 1372.7 + 0.4, 30000.0, 38.5, 3718.881, 1422.88 + 0.4, 30000.0, 39.0, 3818.216, 1471.91 + 0.4, 30000.0, 39.5, 3917.843, 1518.31 + 0.4, 30000.0, 40.0, 4017.9, 1560.6 + 0.4, 30000.0, 40.5, 4119.446, 1589.9 + 0.4, 30000.0, 41.0, 4221.331, 1615.07 + 0.4, 30000.0, 41.5, 4323.326, 1637.62 + 0.4, 30000.0, 42.0, 4425.2, 1659.0 + 0.4, 30000.0, 42.5, 4525.986, 1673.79 + 0.4, 30000.0, 43.0, 4626.487, 1693.14 + 0.4, 30000.0, 43.5, 4726.77, 1721.29 + 0.4, 30000.0, 44.0, 4826.9, 1762.5 + 0.4, 30000.0, 44.5, 4927.079, 1851.5 + 0.4, 30000.0, 45.0, 5027.181, 1949.83 + 0.4, 30000.0, 45.5, 5127.218, 2049.55 + 0.4, 30000.0, 46.0, 5227.2, 2142.7 + 0.4, 30000.0, 46.5, 5326.974, 2198.48 + 0.4, 30000.0, 47.0, 5426.781, 2240.91 + 0.4, 30000.0, 47.5, 5526.698, 2271.19 + 0.4, 30000.0, 48.0, 5626.8, 2290.5 + 0.4, 30000.0, 48.5, 5727.165, 2300.02 + 0.4, 30000.0, 49.0, 5827.869, 2300.94 + 0.4, 30000.0, 49.5, 5928.988, 2294.44 + 0.4, 30000.0, 50.0, 6030.6, 2281.7 + 0.4, 35000.0, 0.0, 153.2488, 153.249 + 0.4, 35000.0, 22.0, 439.0, 318.3 + 0.4, 35000.0, 22.5, 525.3047, 328.0 + 0.4, 35000.0, 23.0, 609.9875, 348.788 + 0.4, 35000.0, 23.5, 693.4266, 378.706 + 0.4, 35000.0, 24.0, 776.0, 415.8 + 0.4, 35000.0, 24.5, 858.0859, 458.113 + 0.4, 35000.0, 25.0, 940.0625, 503.688 + 0.4, 35000.0, 25.5, 1022.308, 550.569 + 0.4, 35000.0, 26.0, 1105.2, 596.8 + 0.4, 35000.0, 26.5, 1192.553, 620.753 + 0.4, 35000.0, 27.0, 1281.505, 639.018 + 0.4, 35000.0, 27.5, 1371.846, 653.014 + 0.4, 35000.0, 28.0, 1463.365, 664.155 + 0.4, 35000.0, 28.5, 1555.851, 673.858 + 0.4, 35000.0, 29.0, 1649.092, 683.539 + 0.4, 35000.0, 29.5, 1742.879, 694.614 + 0.4, 35000.0, 30.0, 1837.0, 708.5 + 0.4, 35000.0, 30.5, 1929.324, 753.756 + 0.4, 35000.0, 31.0, 2021.743, 802.07 + 0.4, 35000.0, 31.5, 2114.23, 852.272 + 0.4, 35000.0, 32.0, 2206.756, 903.194 + 0.4, 35000.0, 32.5, 2299.294, 953.667 + 0.4, 35000.0, 33.0, 2391.816, 1002.52 + 0.4, 35000.0, 33.5, 2484.294, 1048.59 + 0.4, 35000.0, 34.0, 2576.7, 1090.7 + 0.4, 35000.0, 34.5, 2667.659, 1098.55 + 0.4, 35000.0, 35.0, 2758.619, 1102.88 + 0.4, 35000.0, 35.5, 2849.679, 1105.29 + 0.4, 35000.0, 36.0, 2940.94, 1107.4 + 0.4, 35000.0, 36.5, 3032.502, 1110.81 + 0.4, 35000.0, 37.0, 3124.466, 1117.13 + 0.4, 35000.0, 37.5, 3216.932, 1127.95 + 0.4, 35000.0, 38.0, 3310.0, 1144.9 + 0.4, 35000.0, 38.5, 3405.698, 1154.48 + 0.4, 35000.0, 39.0, 3501.2, 1181.22 + 0.4, 35000.0, 39.5, 3596.177, 1230.07 + 0.4, 35000.0, 40.0, 3690.3, 1306.0 + 0.4, 35000.0, 40.5, 3781.273, 1464.94 + 0.4, 35000.0, 41.0, 3871.525, 1640.49 + 0.4, 35000.0, 41.5, 3961.514, 1817.22 + 0.4, 35000.0, 42.0, 4051.7, 1979.7 + 0.4, 35000.0, 42.5, 4144.448, 2083.1 + 0.4, 35000.0, 43.0, 4237.55, 2153.15 + 0.4, 35000.0, 43.5, 4330.702, 2186.17 + 0.4, 35000.0, 44.0, 4423.6, 2178.5 + 0.4, 35000.0, 44.5, 4514.473, 2061.84 + 0.4, 35000.0, 45.0, 4605.075, 1922.99 + 0.4, 35000.0, 45.5, 4695.689, 1784.12 + 0.4, 35000.0, 46.0, 4786.6, 1667.4 + 0.4, 35000.0, 46.5, 4879.342, 1674.34 + 0.4, 35000.0, 47.0, 4972.45, 1716.06 + 0.4, 35000.0, 47.5, 5065.708, 1782.99 + 0.4, 35000.0, 48.0, 5158.9, 1865.6 + 0.4, 35000.0, 48.5, 5251.811, 1954.32 + 0.4, 35000.0, 49.0, 5344.225, 2039.59 + 0.4, 35000.0, 49.5, 5435.927, 2111.87 + 0.4, 35000.0, 50.0, 5526.7, 2161.6 + 0.4, 39000.0, 0.0, 127.1062, 127.106 + 0.4, 39000.0, 22.0, 341.9, 244.6 + 0.4, 39000.0, 22.5, 409.9893, 244.82 + 0.4, 39000.0, 23.0, 476.3734, 260.217 + 0.4, 39000.0, 23.5, 541.4459, 288.156 + 0.4, 39000.0, 24.0, 605.6, 326.0 + 0.4, 39000.0, 24.5, 669.2291, 371.113 + 0.4, 39000.0, 25.0, 732.7266, 420.858 + 0.4, 39000.0, 25.5, 796.4857, 472.599 + 0.4, 39000.0, 26.0, 860.9, 523.7 + 0.4, 39000.0, 26.5, 930.2455, 548.717 + 0.4, 39000.0, 27.0, 1001.255, 566.518 + 0.4, 39000.0, 27.5, 1073.655, 578.376 + 0.4, 39000.0, 28.0, 1147.175, 585.565 + 0.4, 39000.0, 28.5, 1221.542, 589.358 + 0.4, 39000.0, 29.0, 1296.483, 591.03 + 0.4, 39000.0, 29.5, 1371.726, 591.852 + 0.4, 39000.0, 30.0, 1447.0, 593.1 + 0.4, 39000.0, 30.5, 1518.609, 611.756 + 0.4, 39000.0, 31.0, 1590.029, 631.887 + 0.4, 39000.0, 31.5, 1661.314, 653.272 + 0.4, 39000.0, 32.0, 1732.519, 675.687 + 0.4, 39000.0, 32.5, 1803.696, 698.911 + 0.4, 39000.0, 33.0, 1874.899, 722.719 + 0.4, 39000.0, 33.5, 1946.183, 746.889 + 0.4, 39000.0, 34.0, 2017.6, 771.2 + 0.4, 39000.0, 34.5, 2090.72, 800.966 + 0.4, 39000.0, 35.0, 2163.937, 829.898 + 0.4, 39000.0, 35.5, 2237.161, 857.248 + 0.4, 39000.0, 36.0, 2310.3, 882.265 + 0.4, 39000.0, 36.5, 2383.264, 904.199 + 0.4, 39000.0, 37.0, 2455.962, 922.299 + 0.4, 39000.0, 37.5, 2528.305, 935.816 + 0.4, 39000.0, 38.0, 2600.2, 944.0 + 0.4, 39000.0, 38.5, 2670.113, 920.817 + 0.4, 39000.0, 39.0, 2740.147, 903.911 + 0.4, 39000.0, 39.5, 2810.532, 898.149 + 0.4, 39000.0, 40.0, 2881.5, 908.4 + 0.4, 39000.0, 40.5, 2954.466, 955.051 + 0.4, 39000.0, 41.0, 3028.0, 1021.24 + 0.4, 39000.0, 41.5, 3101.859, 1105.64 + 0.4, 39000.0, 42.0, 3175.8, 1206.9 + 0.4, 39000.0, 42.5, 3248.129, 1344.35 + 0.4, 39000.0, 43.0, 3320.631, 1487.73 + 0.4, 39000.0, 43.5, 3393.643, 1627.41 + 0.4, 39000.0, 44.0, 3467.5, 1753.8 + 0.4, 39000.0, 44.5, 3546.089, 1845.04 + 0.4, 39000.0, 45.0, 3624.775, 1908.67 + 0.4, 39000.0, 45.5, 3702.473, 1939.99 + 0.4, 39000.0, 46.0, 3778.1, 1934.3 + 0.4, 39000.0, 46.5, 3844.301, 1833.78 + 0.4, 39000.0, 47.0, 3908.769, 1708.07 + 0.4, 39000.0, 47.5, 3972.927, 1573.74 + 0.4, 39000.0, 48.0, 4038.2, 1447.3 + 0.4, 39000.0, 48.5, 4106.01, 1345.31 + 0.4, 39000.0, 49.0, 4177.781, 1284.3 + 0.4, 39000.0, 49.5, 4254.937, 1280.82 + 0.4, 39000.0, 50.0, 4338.9, 1351.4 + 0.4, 43000.0, 0.0, 104.8751, 104.875 + 0.4, 43000.0, 22.0, 114.9, 397.5 + 0.4, 43000.0, 22.5, 145.6627, 306.718 + 0.4, 43000.0, 23.0, 175.2859, 235.206 + 0.4, 43000.0, 23.5, 203.9162, 180.516 + 0.4, 43000.0, 24.0, 231.7, 140.2 + 0.4, 43000.0, 24.5, 258.7838, 111.809 + 0.4, 43000.0, 25.0, 285.3141, 92.8938 + 0.4, 43000.0, 25.5, 311.4373, 81.007 + 0.4, 43000.0, 26.0, 337.3, 73.7 + 0.4, 43000.0, 26.5, 363.9742, 43.6797 + 0.4, 43000.0, 27.0, 390.7337, 11.9225 + 0.4, 43000.0, 27.5, 417.5664, -19.7609 + 0.4, 43000.0, 28.0, 444.46, -49.56 + 0.4, 43000.0, 28.5, 471.4023, -75.6641 + 0.4, 43000.0, 29.0, 498.3812, -96.2625 + 0.4, 43000.0, 29.5, 525.3845, -109.545 + 0.4, 43000.0, 30.0, 552.4, -113.7 + 0.4, 43000.0, 30.5, 578.9594, -84.3502 + 0.4, 43000.0, 31.0, 605.55, -44.4016 + 0.4, 43000.0, 31.5, 632.2031, 5.80723 + 0.4, 43000.0, 32.0, 658.95, 65.9375 + 0.4, 43000.0, 32.5, 685.8219, 135.651 + 0.4, 43000.0, 33.0, 712.85, 214.608 + 0.4, 43000.0, 33.5, 740.0656, 302.471 + 0.4, 43000.0, 34.0, 767.5, 398.9 + 0.4, 43000.0, 34.5, 797.7602, 639.683 + 0.4, 43000.0, 35.0, 828.0562, 875.391 + 0.4, 43000.0, 35.5, 858.1742, 1092.72 + 0.4, 43000.0, 36.0, 887.9, 1278.37 + 0.4, 43000.0, 36.5, 917.0195, 1419.04 + 0.4, 43000.0, 37.0, 945.3187, 1501.41 + 0.4, 43000.0, 37.5, 972.5836, 1512.2 + 0.4, 43000.0, 38.0, 998.6, 1438.1 + 0.4, 43000.0, 38.5, 1017.923, 1096.93 + 0.4, 43000.0, 39.0, 1038.281, 731.822 + 0.4, 43000.0, 39.5, 1060.624, 367.004 + 0.4, 43000.0, 40.0, 1085.9, 26.7 + 0.4, 43000.0, 40.5, 1122.498, -220.259 + 0.4, 43000.0, 41.0, 1160.95, -412.1 + 0.4, 43000.0, 41.5, 1199.227, -542.441 + 0.4, 43000.0, 42.0, 1235.3, -604.9 + 0.4, 43000.0, 42.5, 1257.365, -524.441 + 0.4, 43000.0, 43.0, 1277.081, -390.8 + 0.4, 43000.0, 43.5, 1296.332, -225.059 + 0.4, 43000.0, 44.0, 1317.0, -48.3 + 0.4, 43000.0, 44.5, 1349.843, 80.3109 + 0.4, 43000.0, 45.0, 1384.319, 193.013 + 0.4, 43000.0, 45.5, 1418.76, 283.958 + 0.4, 43000.0, 46.0, 1451.5, 347.3 + 0.4, 43000.0, 46.5, 1473.598, 331.356 + 0.4, 43000.0, 47.0, 1493.569, 294.45 + 0.4, 43000.0, 47.5, 1512.655, 249.069 + 0.4, 43000.0, 48.0, 1532.1, 207.7 + 0.4, 43000.0, 48.5, 1553.145, 182.831 + 0.4, 43000.0, 49.0, 1577.031, 186.95 + 0.4, 43000.0, 49.5, 1605.002, 232.544 + 0.4, 43000.0, 50.0, 1638.3, 332.1 + 0.4, 48000.0, 0.0, 82.47173, 82.4717 + 0.4, 48000.0, 22.0, 76.5, 322.2 + 0.4, 48000.0, 22.5, 108.2035, 248.105 + 0.4, 48000.0, 23.0, 136.2469, 190.722 + 0.4, 48000.0, 23.5, 161.1668, 147.828 + 0.4, 48000.0, 24.0, 183.5, 117.2 + 0.4, 48000.0, 24.5, 203.7832, 96.616 + 0.4, 48000.0, 25.0, 222.5531, 83.8531 + 0.4, 48000.0, 25.5, 240.3465, 76.6887 + 0.4, 48000.0, 26.0, 257.7, 72.9 + 0.4, 48000.0, 26.5, 279.4023, 47.6033 + 0.4, 48000.0, 27.0, 301.9812, 19.9422 + 0.4, 48000.0, 27.5, 325.2445, -8.42129 + 0.4, 48000.0, 28.0, 349.0, -35.825 + 0.4, 48000.0, 28.5, 373.0555, -60.6068 + 0.4, 48000.0, 29.0, 397.2187, -81.1047 + 0.4, 48000.0, 29.5, 421.2977, -95.6564 + 0.4, 48000.0, 30.0, 445.1, -102.6 + 0.4, 48000.0, 30.5, 465.3574, -78.6683 + 0.4, 48000.0, 31.0, 485.2469, -45.8617 + 0.4, 48000.0, 31.5, 504.8691, -4.57588 + 0.4, 48000.0, 32.0, 524.325, 44.7937 + 0.4, 48000.0, 32.5, 543.7152, 101.852 + 0.4, 48000.0, 33.0, 563.1406, 166.202 + 0.4, 48000.0, 33.5, 582.702, 237.45 + 0.4, 48000.0, 34.0, 602.5, 315.2 + 0.4, 48000.0, 34.5, 626.1744, 502.866 + 0.4, 48000.0, 35.0, 649.95, 686.356 + 0.4, 48000.0, 35.5, 673.5906, 855.388 + 0.4, 48000.0, 36.0, 696.86, 999.68 + 0.4, 48000.0, 36.5, 719.5219, 1108.95 + 0.4, 48000.0, 37.0, 741.34, 1172.91 + 0.4, 48000.0, 37.5, 762.0781, 1181.29 + 0.4, 48000.0, 38.0, 781.5, 1123.8 + 0.4, 48000.0, 38.5, 792.9906, 859.962 + 0.4, 48000.0, 39.0, 806.0, 577.2 + 0.4, 48000.0, 39.5, 821.7094, 294.162 + 0.4, 48000.0, 40.0, 841.3, 29.5 + 0.4, 48000.0, 40.5, 875.75, -164.833 + 0.4, 48000.0, 41.0, 912.525, -316.813 + 0.4, 48000.0, 41.5, 948.8875, -421.111 + 0.4, 48000.0, 42.0, 982.1, -472.4 + 0.4, 48000.0, 42.5, 996.8781, -411.129 + 0.4, 48000.0, 43.0, 1008.05, -307.881 + 0.4, 48000.0, 43.5, 1017.897, -179.018 + 0.4, 48000.0, 44.0, 1028.7, -40.9 + 0.4, 48000.0, 44.5, 1051.163, 61.5883 + 0.4, 48000.0, 45.0, 1075.775, 152.019 + 0.4, 48000.0, 45.5, 1101.45, 225.44 + 0.4, 48000.0, 46.0, 1127.1, 276.9 + 0.4, 48000.0, 46.5, 1148.298, 263.553 + 0.4, 48000.0, 47.0, 1168.631, 233.5 + 0.4, 48000.0, 47.5, 1188.349, 196.947 + 0.4, 48000.0, 48.0, 1207.7, 164.1 + 0.4, 48000.0, 48.5, 1226.932, 145.166 + 0.4, 48000.0, 49.0, 1246.294, 150.35 + 0.4, 48000.0, 49.5, 1266.034, 189.859 + 0.4, 48000.0, 50.0, 1286.4, 273.9 + 0.45, 0.0, 0.0, 581.6661, 581.666 + 0.45, 0.0, 22.0, 1319.1, 1155.1 + 0.45, 0.0, 22.5, 1569.297, 1262.66 + 0.45, 0.0, 23.0, 1816.714, 1356.49 + 0.45, 0.0, 23.5, 2062.249, 1439.48 + 0.45, 0.0, 24.0, 2306.8, 1514.5 + 0.45, 0.0, 24.5, 2551.263, 1584.42 + 0.45, 0.0, 25.0, 2796.536, 1652.11 + 0.45, 0.0, 25.5, 3043.516, 1720.44 + 0.45, 0.0, 26.0, 3293.1, 1792.3 + 0.45, 0.0, 26.5, 3555.585, 1898.3 + 0.45, 0.0, 27.0, 3823.006, 2015.15 + 0.45, 0.0, 27.5, 4094.649, 2140.97 + 0.45, 0.0, 28.0, 4369.8, 2273.87 + 0.45, 0.0, 28.5, 4647.745, 2411.96 + 0.45, 0.0, 29.0, 4927.769, 2553.37 + 0.45, 0.0, 29.5, 5209.159, 2696.21 + 0.45, 0.0, 30.0, 5491.2, 2838.6 + 0.45, 0.0, 30.5, 5765.548, 2953.75 + 0.45, 0.0, 31.0, 6039.846, 3067.05 + 0.45, 0.0, 31.5, 6314.107, 3178.98 + 0.45, 0.0, 32.0, 6588.344, 3290.03 + 0.45, 0.0, 32.5, 6862.569, 3400.69 + 0.45, 0.0, 33.0, 7136.795, 3511.45 + 0.45, 0.0, 33.5, 7411.034, 3622.79 + 0.45, 0.0, 34.0, 7685.3, 3735.2 + 0.45, 0.0, 34.5, 7959.819, 3878.46 + 0.45, 0.0, 35.0, 8234.37, 4020.98 + 0.45, 0.0, 35.5, 8508.945, 4160.45 + 0.45, 0.0, 36.0, 8783.535, 4294.56 + 0.45, 0.0, 36.5, 9058.133, 4421.01 + 0.45, 0.0, 37.0, 9332.732, 4537.51 + 0.45, 0.0, 37.5, 9607.324, 4641.74 + 0.45, 0.0, 38.0, 9881.9, 4731.4 + 0.45, 0.0, 38.5, 10156.43, 4784.15 + 0.45, 0.0, 39.0, 10430.95, 4828.11 + 0.45, 0.0, 39.5, 10705.44, 4865.45 + 0.45, 0.0, 40.0, 10979.9, 4898.3 + 0.45, 0.0, 40.5, 11254.42, 4925.66 + 0.45, 0.0, 41.0, 11528.86, 4954.11 + 0.45, 0.0, 41.5, 11803.2, 4987.05 + 0.45, 0.0, 42.0, 12077.4, 5027.9 + 0.45, 0.0, 42.5, 12350.82, 5084.93 + 0.45, 0.0, 43.0, 12624.26, 5154.76 + 0.45, 0.0, 43.5, 12897.92, 5238.86 + 0.45, 0.0, 44.0, 13172.0, 5338.7 + 0.45, 0.0, 44.5, 13448.1, 5468.4 + 0.45, 0.0, 45.0, 13724.46, 5611.73 + 0.45, 0.0, 45.5, 14000.75, 5765.09 + 0.45, 0.0, 46.0, 14276.6, 5924.9 + 0.45, 0.0, 46.5, 14550.02, 6081.35 + 0.45, 0.0, 47.0, 14822.95, 6239.57 + 0.45, 0.0, 47.5, 15095.71, 6398.45 + 0.45, 0.0, 48.0, 15368.6, 6556.9 + 0.45, 0.0, 48.5, 15641.93, 6713.82 + 0.45, 0.0, 49.0, 15916.0, 6868.11 + 0.45, 0.0, 49.5, 16191.12, 7018.67 + 0.45, 0.0, 50.0, 16467.6, 7164.4 + 0.45, 2000.0, 0.0, 544.5964, 544.596 + 0.45, 2000.0, 22.0, 405.9, 783.4 + 0.45, 2000.0, 22.5, 483.3023, 813.929 + 0.45, 2000.0, 23.0, 559.8562, 845.68 + 0.45, 2000.0, 23.5, 635.832, 878.365 + 0.45, 2000.0, 24.0, 711.5, 911.7 + 0.45, 2000.0, 24.5, 787.1305, 945.397 + 0.45, 2000.0, 25.0, 862.9937, 979.17 + 0.45, 2000.0, 25.5, 939.3602, 1012.73 + 0.45, 2000.0, 26.0, 1016.5, 1045.8 + 0.45, 2000.0, 26.5, 1097.495, 1075.19 + 0.45, 2000.0, 27.0, 1179.964, 1103.34 + 0.45, 2000.0, 27.5, 1263.696, 1130.47 + 0.45, 2000.0, 28.0, 1348.48, 1156.79 + 0.45, 2000.0, 28.5, 1434.104, 1182.5 + 0.45, 2000.0, 29.0, 1520.356, 1207.82 + 0.45, 2000.0, 29.5, 1607.025, 1232.95 + 0.45, 2000.0, 30.0, 1693.9, 1258.1 + 0.45, 2000.0, 30.5, 1778.543, 1286.66 + 0.45, 2000.0, 31.0, 1863.18, 1315.37 + 0.45, 2000.0, 31.5, 1947.811, 1344.12 + 0.45, 2000.0, 32.0, 2032.438, 1372.83 + 0.45, 2000.0, 32.5, 2117.059, 1401.41 + 0.45, 2000.0, 33.0, 2201.677, 1429.76 + 0.45, 2000.0, 33.5, 2286.29, 1457.78 + 0.45, 2000.0, 34.0, 2370.9, 1485.4 + 0.45, 2000.0, 34.5, 2455.434, 1505.48 + 0.45, 2000.0, 35.0, 2539.972, 1525.64 + 0.45, 2000.0, 35.5, 2624.521, 1546.44 + 0.45, 2000.0, 36.0, 2709.09, 1568.47 + 0.45, 2000.0, 36.5, 2793.685, 1592.31 + 0.45, 2000.0, 37.0, 2878.313, 1618.52 + 0.45, 2000.0, 37.5, 2962.982, 1647.69 + 0.45, 2000.0, 38.0, 3047.7, 1680.4 + 0.45, 2000.0, 38.5, 3132.608, 1722.26 + 0.45, 2000.0, 39.0, 3217.509, 1766.19 + 0.45, 2000.0, 39.5, 3302.381, 1811.65 + 0.45, 2000.0, 40.0, 3387.2, 1858.1 + 0.45, 2000.0, 40.5, 3471.833, 1906.09 + 0.45, 2000.0, 41.0, 3556.413, 1953.54 + 0.45, 2000.0, 41.5, 3640.961, 1999.47 + 0.45, 2000.0, 42.0, 3725.5, 2042.9 + 0.45, 2000.0, 42.5, 3810.032, 2079.67 + 0.45, 2000.0, 43.0, 3894.606, 2113.23 + 0.45, 2000.0, 43.5, 3979.252, 2143.88 + 0.45, 2000.0, 44.0, 4064.0, 2171.9 + 0.45, 2000.0, 44.5, 4149.164, 2197.4 + 0.45, 2000.0, 45.0, 4234.375, 2220.92 + 0.45, 2000.0, 45.5, 4319.548, 2242.8 + 0.45, 2000.0, 46.0, 4404.6, 2263.4 + 0.45, 2000.0, 46.5, 4489.043, 2283.69 + 0.45, 2000.0, 47.0, 4573.356, 2303.16 + 0.45, 2000.0, 47.5, 4657.616, 2321.93 + 0.45, 2000.0, 48.0, 4741.9, 2340.1 + 0.45, 2000.0, 48.5, 4826.284, 2357.78 + 0.45, 2000.0, 49.0, 4910.844, 2375.09 + 0.45, 2000.0, 49.5, 4995.657, 2392.12 + 0.45, 2000.0, 50.0, 5080.8, 2409.0 + 0.45, 5000.0, 0.0, 492.5143, 492.514 + 0.45, 5000.0, 22.0, 992.7, 926.2 + 0.45, 5000.0, 22.5, 1181.128, 995.775 + 0.45, 5000.0, 23.0, 1367.605, 1063.92 + 0.45, 5000.0, 23.5, 1552.779, 1131.04 + 0.45, 5000.0, 24.0, 1737.3, 1197.5 + 0.45, 5000.0, 24.5, 1921.814, 1263.7 + 0.45, 5000.0, 25.0, 2106.97, 1330.02 + 0.45, 5000.0, 25.5, 2293.416, 1396.86 + 0.45, 5000.0, 26.0, 2481.8, 1464.6 + 0.45, 5000.0, 26.5, 2679.569, 1537.42 + 0.45, 5000.0, 27.0, 2880.96, 1612.13 + 0.45, 5000.0, 27.5, 3085.456, 1688.47 + 0.45, 5000.0, 28.0, 3292.54, 1766.17 + 0.45, 5000.0, 28.5, 3501.694, 1844.98 + 0.45, 5000.0, 29.0, 3712.4, 1924.63 + 0.45, 5000.0, 29.5, 3924.141, 2004.86 + 0.45, 5000.0, 30.0, 4136.4, 2085.4 + 0.45, 5000.0, 30.5, 4343.225, 2162.91 + 0.45, 5000.0, 31.0, 4550.05, 2240.51 + 0.45, 5000.0, 31.5, 4756.875, 2318.22 + 0.45, 5000.0, 32.0, 4963.7, 2396.07 + 0.45, 5000.0, 32.5, 5170.525, 2474.11 + 0.45, 5000.0, 33.0, 5377.35, 2552.36 + 0.45, 5000.0, 33.5, 5584.175, 2630.84 + 0.45, 5000.0, 34.0, 5791.0, 2709.6 + 0.45, 5000.0, 34.5, 5997.832, 2788.98 + 0.45, 5000.0, 35.0, 6204.663, 2868.67 + 0.45, 5000.0, 35.5, 6411.492, 2948.66 + 0.45, 5000.0, 36.0, 6618.32, 3028.95 + 0.45, 5000.0, 36.5, 6825.145, 3109.55 + 0.45, 5000.0, 37.0, 7031.968, 3190.46 + 0.45, 5000.0, 37.5, 7238.786, 3271.68 + 0.45, 5000.0, 38.0, 7445.6, 3353.2 + 0.45, 5000.0, 38.5, 7652.397, 3435.27 + 0.45, 5000.0, 39.0, 7859.195, 3517.53 + 0.45, 5000.0, 39.5, 8065.996, 3599.92 + 0.45, 5000.0, 40.0, 8272.8, 3682.4 + 0.45, 5000.0, 40.5, 8479.62, 3764.63 + 0.45, 5000.0, 41.0, 8686.444, 3846.95 + 0.45, 5000.0, 41.5, 8893.271, 3929.42 + 0.45, 5000.0, 42.0, 9100.1, 4012.1 + 0.45, 5000.0, 42.5, 9306.765, 4095.03 + 0.45, 5000.0, 43.0, 9513.494, 4178.3 + 0.45, 5000.0, 43.5, 9720.351, 4261.97 + 0.45, 5000.0, 44.0, 9927.4, 4346.1 + 0.45, 5000.0, 44.5, 10135.35, 4431.21 + 0.45, 5000.0, 45.0, 10343.36, 4516.73 + 0.45, 5000.0, 45.5, 10551.24, 4602.57 + 0.45, 5000.0, 46.0, 10758.8, 4688.6 + 0.45, 5000.0, 46.5, 10964.86, 4774.4 + 0.45, 5000.0, 47.0, 11170.61, 4860.3 + 0.45, 5000.0, 47.5, 11376.22, 4946.33 + 0.45, 5000.0, 48.0, 11581.9, 5032.5 + 0.45, 5000.0, 48.5, 11787.84, 5118.83 + 0.45, 5000.0, 49.0, 11994.24, 5205.35 + 0.45, 5000.0, 49.5, 12201.3, 5292.07 + 0.45, 5000.0, 50.0, 12409.2, 5379.0 + 0.45, 10000.0, 0.0, 414.5212, 414.521 + 0.45, 10000.0, 22.0, 909.4, 807.9 + 0.45, 10000.0, 22.5, 1081.956, 870.628 + 0.45, 10000.0, 23.0, 1252.748, 932.128 + 0.45, 10000.0, 23.5, 1422.366, 992.739 + 0.45, 10000.0, 24.0, 1591.4, 1052.8 + 0.45, 10000.0, 24.5, 1760.44, 1112.65 + 0.45, 10000.0, 25.0, 1930.077, 1172.62 + 0.45, 10000.0, 25.5, 2100.9, 1233.06 + 0.45, 10000.0, 26.0, 2273.5, 1294.3 + 0.45, 10000.0, 26.5, 2454.669, 1359.92 + 0.45, 10000.0, 27.0, 2639.15, 1427.19 + 0.45, 10000.0, 27.5, 2826.469, 1495.92 + 0.45, 10000.0, 28.0, 3016.155, 1565.88 + 0.45, 10000.0, 28.5, 3207.734, 1636.85 + 0.45, 10000.0, 29.0, 3400.733, 1708.62 + 0.45, 10000.0, 29.5, 3594.679, 1780.98 + 0.45, 10000.0, 30.0, 3789.1, 1853.7 + 0.45, 10000.0, 30.5, 3978.559, 1924.12 + 0.45, 10000.0, 31.0, 4168.02, 1994.71 + 0.45, 10000.0, 31.5, 4357.481, 2065.49 + 0.45, 10000.0, 32.0, 4546.944, 2136.46 + 0.45, 10000.0, 32.5, 4736.407, 2207.65 + 0.45, 10000.0, 33.0, 4925.871, 2279.08 + 0.45, 10000.0, 33.5, 5115.335, 2350.76 + 0.45, 10000.0, 34.0, 5304.8, 2422.7 + 0.45, 10000.0, 34.5, 5494.266, 2495.28 + 0.45, 10000.0, 35.0, 5683.731, 2568.13 + 0.45, 10000.0, 35.5, 5873.196, 2641.24 + 0.45, 10000.0, 36.0, 6062.66, 2714.57 + 0.45, 10000.0, 36.5, 6252.123, 2788.12 + 0.45, 10000.0, 37.0, 6441.584, 2861.87 + 0.45, 10000.0, 37.5, 6631.043, 2935.8 + 0.45, 10000.0, 38.0, 6820.5, 3009.9 + 0.45, 10000.0, 38.5, 7009.946, 3084.08 + 0.45, 10000.0, 39.0, 7199.394, 3158.42 + 0.45, 10000.0, 39.5, 7388.845, 3232.93 + 0.45, 10000.0, 40.0, 7578.3, 3307.6 + 0.45, 10000.0, 40.5, 7767.773, 3382.17 + 0.45, 10000.0, 41.0, 7957.25, 3457.0 + 0.45, 10000.0, 41.5, 8146.727, 3532.21 + 0.45, 10000.0, 42.0, 8336.2, 3607.9 + 0.45, 10000.0, 42.5, 8525.507, 3684.69 + 0.45, 10000.0, 43.0, 8714.869, 3761.97 + 0.45, 10000.0, 43.5, 8904.346, 3839.64 + 0.45, 10000.0, 44.0, 9094.0, 3917.6 + 0.45, 10000.0, 44.5, 9284.485, 3995.57 + 0.45, 10000.0, 45.0, 9475.031, 4073.71 + 0.45, 10000.0, 45.5, 9665.462, 4151.99 + 0.45, 10000.0, 46.0, 9855.6, 4230.4 + 0.45, 10000.0, 46.5, 10044.39, 4308.69 + 0.45, 10000.0, 47.0, 10232.89, 4387.15 + 0.45, 10000.0, 47.5, 10421.27, 4465.83 + 0.45, 10000.0, 48.0, 10609.7, 4544.8 + 0.45, 10000.0, 48.5, 10798.37, 4624.12 + 0.45, 10000.0, 49.0, 10987.44, 4703.85 + 0.45, 10000.0, 49.5, 11177.09, 4784.06 + 0.45, 10000.0, 50.0, 11367.5, 4864.8 + 0.45, 15000.0, 0.0, 346.6199, 346.62 + 0.45, 15000.0, 22.0, 815.5, 695.5 + 0.45, 15000.0, 22.5, 970.2033, 751.154 + 0.45, 15000.0, 23.0, 1123.336, 805.481 + 0.45, 15000.0, 23.5, 1275.426, 858.818 + 0.45, 15000.0, 24.0, 1427.0, 911.5 + 0.45, 15000.0, 24.5, 1578.587, 963.863 + 0.45, 15000.0, 25.0, 1730.714, 1016.24 + 0.45, 15000.0, 25.5, 1883.909, 1068.98 + 0.45, 15000.0, 26.0, 2038.7, 1122.4 + 0.45, 15000.0, 26.5, 2201.165, 1179.92 + 0.45, 15000.0, 27.0, 2366.598, 1238.98 + 0.45, 15000.0, 27.5, 2534.576, 1299.39 + 0.45, 15000.0, 28.0, 2704.675, 1360.95 + 0.45, 15000.0, 28.5, 2876.471, 1423.47 + 0.45, 15000.0, 29.0, 3049.539, 1486.77 + 0.45, 15000.0, 29.5, 3223.457, 1550.64 + 0.45, 15000.0, 30.0, 3397.8, 1614.9 + 0.45, 15000.0, 30.5, 3567.699, 1677.3 + 0.45, 15000.0, 31.0, 3737.598, 1739.9 + 0.45, 15000.0, 31.5, 3907.499, 1802.71 + 0.45, 15000.0, 32.0, 4077.4, 1865.72 + 0.45, 15000.0, 32.5, 4247.301, 1928.96 + 0.45, 15000.0, 33.0, 4417.202, 1992.41 + 0.45, 15000.0, 33.5, 4587.101, 2056.09 + 0.45, 15000.0, 34.0, 4757.0, 2120.0 + 0.45, 15000.0, 34.5, 4926.894, 2184.43 + 0.45, 15000.0, 35.0, 5096.786, 2249.08 + 0.45, 15000.0, 35.5, 5266.676, 2313.91 + 0.45, 15000.0, 36.0, 5436.565, 2378.91 + 0.45, 15000.0, 36.5, 5606.452, 2444.05 + 0.45, 15000.0, 37.0, 5776.337, 2509.31 + 0.45, 15000.0, 37.5, 5946.219, 2574.67 + 0.45, 15000.0, 38.0, 6116.1, 2640.1 + 0.45, 15000.0, 38.5, 6285.976, 2705.0 + 0.45, 15000.0, 39.0, 6455.852, 2770.23 + 0.45, 15000.0, 39.5, 6625.726, 2835.89 + 0.45, 15000.0, 40.0, 6795.6, 2902.1 + 0.45, 15000.0, 40.5, 6965.471, 2969.47 + 0.45, 15000.0, 41.0, 7135.344, 3037.39 + 0.45, 15000.0, 41.5, 7305.22, 3105.76 + 0.45, 15000.0, 42.0, 7475.1, 3174.5 + 0.45, 15000.0, 42.5, 7644.862, 3243.28 + 0.45, 15000.0, 43.0, 7814.681, 3312.31 + 0.45, 15000.0, 43.5, 7984.61, 3381.59 + 0.45, 15000.0, 44.0, 8154.7, 3451.1 + 0.45, 15000.0, 44.5, 8325.534, 3520.88 + 0.45, 15000.0, 45.0, 8496.419, 3590.85 + 0.45, 15000.0, 45.5, 8667.195, 3661.0 + 0.45, 15000.0, 46.0, 8837.7, 3731.3 + 0.45, 15000.0, 46.5, 9006.966, 3801.38 + 0.45, 15000.0, 47.0, 9175.962, 3871.69 + 0.45, 15000.0, 47.5, 9344.853, 3942.36 + 0.45, 15000.0, 48.0, 9513.8, 4013.5 + 0.45, 15000.0, 48.5, 9682.966, 4085.22 + 0.45, 15000.0, 49.0, 9852.513, 4157.63 + 0.45, 15000.0, 49.5, 10022.6, 4230.85 + 0.45, 15000.0, 50.0, 10193.4, 4305.0 + 0.45, 20000.0, 0.0, 287.8229, 287.823 + 0.45, 20000.0, 22.0, 810.2, 625.1 + 0.45, 20000.0, 22.5, 963.9457, 677.302 + 0.45, 20000.0, 23.0, 1116.109, 729.295 + 0.45, 20000.0, 23.5, 1267.218, 781.241 + 0.45, 20000.0, 24.0, 1417.8, 833.3 + 0.45, 20000.0, 24.5, 1568.382, 885.634 + 0.45, 20000.0, 25.0, 1719.491, 938.405 + 0.45, 20000.0, 25.5, 1871.654, 991.773 + 0.45, 20000.0, 26.0, 2025.4, 1045.9 + 0.45, 20000.0, 26.5, 2186.791, 1102.53 + 0.45, 20000.0, 27.0, 2351.135, 1160.32 + 0.45, 20000.0, 27.5, 2518.01, 1219.18 + 0.45, 20000.0, 28.0, 2686.995, 1279.0 + 0.45, 20000.0, 28.5, 2857.668, 1339.65 + 0.45, 20000.0, 29.0, 3029.608, 1401.05 + 0.45, 20000.0, 29.5, 3202.392, 1463.06 + 0.45, 20000.0, 30.0, 3375.6, 1525.6 + 0.45, 20000.0, 30.5, 3544.386, 1587.69 + 0.45, 20000.0, 31.0, 3713.173, 1650.17 + 0.45, 20000.0, 31.5, 3881.962, 1712.99 + 0.45, 20000.0, 32.0, 4050.75, 1776.14 + 0.45, 20000.0, 32.5, 4219.538, 1839.58 + 0.45, 20000.0, 33.0, 4388.327, 1903.29 + 0.45, 20000.0, 33.5, 4557.114, 1967.24 + 0.45, 20000.0, 34.0, 4725.9, 2031.4 + 0.45, 20000.0, 34.5, 4894.671, 2094.99 + 0.45, 20000.0, 35.0, 5063.442, 2158.81 + 0.45, 20000.0, 35.5, 5232.213, 2222.89 + 0.45, 20000.0, 36.0, 5400.985, 2287.29 + 0.45, 20000.0, 36.5, 5569.759, 2352.05 + 0.45, 20000.0, 37.0, 5738.535, 2417.21 + 0.45, 20000.0, 37.5, 5907.315, 2482.81 + 0.45, 20000.0, 38.0, 6076.1, 2548.9 + 0.45, 20000.0, 38.5, 6244.903, 2615.97 + 0.45, 20000.0, 39.0, 6413.705, 2683.38 + 0.45, 20000.0, 39.5, 6582.504, 2751.07 + 0.45, 20000.0, 40.0, 6751.3, 2819.0 + 0.45, 20000.0, 40.5, 6920.077, 2886.74 + 0.45, 20000.0, 41.0, 7088.85, 2954.74 + 0.45, 20000.0, 41.5, 7257.623, 3023.1 + 0.45, 20000.0, 42.0, 7426.4, 3091.9 + 0.45, 20000.0, 42.5, 7595.066, 3161.46 + 0.45, 20000.0, 43.0, 7763.788, 3231.56 + 0.45, 20000.0, 43.5, 7932.616, 3302.2 + 0.45, 20000.0, 44.0, 8101.6, 3373.4 + 0.45, 20000.0, 44.5, 8271.31, 3445.07 + 0.45, 20000.0, 45.0, 8441.069, 3517.33 + 0.45, 20000.0, 45.5, 8610.718, 3590.23 + 0.45, 20000.0, 46.0, 8780.1, 3663.8 + 0.45, 20000.0, 46.5, 8948.26, 3737.83 + 0.45, 20000.0, 47.0, 9116.156, 3812.72 + 0.45, 20000.0, 47.5, 9283.949, 3888.59 + 0.45, 20000.0, 48.0, 9451.8, 3965.6 + 0.45, 20000.0, 48.5, 9619.87, 4043.87 + 0.45, 20000.0, 49.0, 9788.319, 4123.56 + 0.45, 20000.0, 49.5, 9957.309, 4204.79 + 0.45, 20000.0, 50.0, 10127.0, 4287.7 + 0.45, 25000.0, 0.0, 237.199, 237.199 + 0.45, 25000.0, 22.0, 653.7, 513.1 + 0.45, 25000.0, 22.5, 777.724, 554.371 + 0.45, 25000.0, 23.0, 900.4828, 595.569 + 0.45, 25000.0, 23.5, 1022.4, 636.807 + 0.45, 25000.0, 24.0, 1143.9, 678.2 + 0.45, 25000.0, 24.5, 1265.406, 719.862 + 0.45, 25000.0, 25.0, 1387.342, 761.906 + 0.45, 25000.0, 25.5, 1510.132, 804.448 + 0.45, 25000.0, 26.0, 1634.2, 847.6 + 0.45, 25000.0, 26.5, 1764.425, 892.689 + 0.45, 25000.0, 27.0, 1897.03, 938.686 + 0.45, 25000.0, 27.5, 2031.675, 985.497 + 0.45, 25000.0, 28.0, 2168.02, 1033.03 + 0.45, 25000.0, 28.5, 2305.725, 1081.19 + 0.45, 25000.0, 29.0, 2444.45, 1129.88 + 0.45, 25000.0, 29.5, 2583.855, 1179.02 + 0.45, 25000.0, 30.0, 2723.6, 1228.5 + 0.45, 25000.0, 30.5, 2859.773, 1277.4 + 0.45, 25000.0, 31.0, 2995.946, 1326.53 + 0.45, 25000.0, 31.5, 3132.12, 1375.9 + 0.45, 25000.0, 32.0, 3268.294, 1425.47 + 0.45, 25000.0, 32.5, 3404.469, 1475.24 + 0.45, 25000.0, 33.0, 3540.645, 1525.19 + 0.45, 25000.0, 33.5, 3676.822, 1575.32 + 0.45, 25000.0, 34.0, 3813.0, 1625.6 + 0.45, 25000.0, 34.5, 3949.188, 1675.47 + 0.45, 25000.0, 35.0, 4085.377, 1725.52 + 0.45, 25000.0, 35.5, 4221.566, 1775.8 + 0.45, 25000.0, 36.0, 4357.755, 1826.32 + 0.45, 25000.0, 36.5, 4493.944, 1877.15 + 0.45, 25000.0, 37.0, 4630.131, 1928.31 + 0.45, 25000.0, 37.5, 4766.317, 1979.85 + 0.45, 25000.0, 38.0, 4902.5, 2031.8 + 0.45, 25000.0, 38.5, 5038.676, 2084.55 + 0.45, 25000.0, 39.0, 5174.852, 2137.62 + 0.45, 25000.0, 39.5, 5311.026, 2190.94 + 0.45, 25000.0, 40.0, 5447.2, 2244.5 + 0.45, 25000.0, 40.5, 5583.371, 2297.9 + 0.45, 25000.0, 41.0, 5719.544, 2351.58 + 0.45, 25000.0, 41.5, 5855.72, 2405.65 + 0.45, 25000.0, 42.0, 5991.9, 2460.2 + 0.45, 25000.0, 42.5, 6127.993, 2515.59 + 0.45, 25000.0, 43.0, 6264.131, 2571.55 + 0.45, 25000.0, 43.5, 6400.354, 2628.09 + 0.45, 25000.0, 44.0, 6536.7, 2685.2 + 0.45, 25000.0, 44.5, 6673.619, 2743.04 + 0.45, 25000.0, 45.0, 6810.575, 2801.37 + 0.45, 25000.0, 45.5, 6947.444, 2860.15 + 0.45, 25000.0, 46.0, 7084.1, 2919.3 + 0.45, 25000.0, 46.5, 7219.79, 2978.22 + 0.45, 25000.0, 47.0, 7355.269, 3037.6 + 0.45, 25000.0, 47.5, 7490.663, 3097.58 + 0.45, 25000.0, 48.0, 7626.1, 3158.3 + 0.45, 25000.0, 48.5, 7761.705, 3219.92 + 0.45, 25000.0, 49.0, 7897.606, 3282.58 + 0.45, 25000.0, 49.5, 8033.929, 3346.42 + 0.45, 25000.0, 50.0, 8170.8, 3411.6 + 0.45, 30000.0, 0.0, 193.8824, 193.882 + 0.45, 30000.0, 22.0, 496.9, 413.1 + 0.45, 30000.0, 22.5, 590.892, 446.978 + 0.45, 30000.0, 23.0, 684.0516, 478.18 + 0.45, 30000.0, 23.5, 776.6854, 507.292 + 0.45, 30000.0, 24.0, 869.1, 534.9 + 0.45, 30000.0, 24.5, 961.6021, 561.589 + 0.45, 30000.0, 25.0, 1054.498, 587.945 + 0.45, 30000.0, 25.5, 1148.096, 614.554 + 0.45, 30000.0, 26.0, 1242.7, 642.0 + 0.45, 30000.0, 26.5, 1341.934, 676.966 + 0.45, 30000.0, 27.0, 1442.978, 714.289 + 0.45, 30000.0, 27.5, 1545.571, 753.511 + 0.45, 30000.0, 28.0, 1649.45, 794.17 + 0.45, 30000.0, 28.5, 1754.354, 835.808 + 0.45, 30000.0, 29.0, 1860.022, 877.966 + 0.45, 30000.0, 29.5, 1966.191, 920.183 + 0.45, 30000.0, 30.0, 2072.6, 962.0 + 0.45, 30000.0, 30.5, 2176.202, 996.433 + 0.45, 30000.0, 31.0, 2279.786, 1030.17 + 0.45, 30000.0, 31.5, 2383.355, 1063.37 + 0.45, 30000.0, 32.0, 2486.913, 1096.19 + 0.45, 30000.0, 32.5, 2590.462, 1128.81 + 0.45, 30000.0, 33.0, 2694.008, 1161.37 + 0.45, 30000.0, 33.5, 2797.553, 1194.05 + 0.45, 30000.0, 34.0, 2901.1, 1227.0 + 0.45, 30000.0, 34.5, 3004.809, 1260.93 + 0.45, 30000.0, 35.0, 3108.512, 1295.4 + 0.45, 30000.0, 35.5, 3212.2, 1330.53 + 0.45, 30000.0, 36.0, 3315.86, 1366.42 + 0.45, 30000.0, 36.5, 3419.481, 1403.2 + 0.45, 30000.0, 37.0, 3523.052, 1440.96 + 0.45, 30000.0, 37.5, 3626.562, 1479.83 + 0.45, 30000.0, 38.0, 3730.0, 1519.9 + 0.45, 30000.0, 38.5, 3833.039, 1564.76 + 0.45, 30000.0, 39.0, 3936.147, 1609.25 + 0.45, 30000.0, 39.5, 4039.381, 1652.72 + 0.45, 30000.0, 40.0, 4142.8, 1694.5 + 0.45, 30000.0, 40.5, 4246.859, 1730.54 + 0.45, 30000.0, 41.0, 4351.062, 1764.93 + 0.45, 30000.0, 41.5, 4455.309, 1798.39 + 0.45, 30000.0, 42.0, 4559.5, 1831.6 + 0.45, 30000.0, 42.5, 4663.167, 1862.69 + 0.45, 30000.0, 43.0, 4766.725, 1895.98 + 0.45, 30000.0, 43.5, 4870.22, 1933.2 + 0.45, 30000.0, 44.0, 4973.7, 1976.1 + 0.45, 30000.0, 44.5, 5077.441, 2039.15 + 0.45, 30000.0, 45.0, 5181.169, 2106.26 + 0.45, 30000.0, 45.5, 5284.837, 2174.06 + 0.45, 30000.0, 46.0, 5388.4, 2239.2 + 0.45, 30000.0, 46.5, 5491.497, 2288.31 + 0.45, 30000.0, 47.0, 5594.525, 2332.04 + 0.45, 30000.0, 47.5, 5697.566, 2371.03 + 0.45, 30000.0, 48.0, 5800.7, 2405.9 + 0.45, 30000.0, 48.5, 5904.009, 2437.31 + 0.45, 30000.0, 49.0, 6007.575, 2465.88 + 0.45, 30000.0, 49.5, 6111.478, 2492.27 + 0.45, 30000.0, 50.0, 6215.8, 2517.1 + 0.45, 35000.0, 0.0, 157.0668, 157.067 + 0.45, 35000.0, 22.0, 414.9, 344.4 + 0.45, 35000.0, 22.5, 495.1852, 359.788 + 0.45, 35000.0, 23.0, 574.2688, 381.594 + 0.45, 35000.0, 23.5, 652.468, 408.727 + 0.45, 35000.0, 24.0, 730.1, 440.1 + 0.45, 35000.0, 24.5, 807.482, 474.623 + 0.45, 35000.0, 25.0, 884.9312, 511.206 + 0.45, 35000.0, 25.5, 962.7648, 548.762 + 0.45, 35000.0, 26.0, 1041.3, 586.2 + 0.45, 35000.0, 26.5, 1123.91, 611.659 + 0.45, 35000.0, 27.0, 1208.03, 634.206 + 0.45, 35000.0, 27.5, 1293.454, 654.601 + 0.45, 35000.0, 28.0, 1379.975, 673.6 + 0.45, 35000.0, 28.5, 1467.387, 691.962 + 0.45, 35000.0, 29.0, 1555.483, 710.444 + 0.45, 35000.0, 29.5, 1644.056, 729.804 + 0.45, 35000.0, 30.0, 1732.9, 750.8 + 0.45, 35000.0, 30.5, 1819.786, 788.724 + 0.45, 35000.0, 31.0, 1906.722, 828.415 + 0.45, 35000.0, 31.5, 1993.694, 869.247 + 0.45, 35000.0, 32.0, 2080.688, 910.594 + 0.45, 35000.0, 32.5, 2167.689, 951.829 + 0.45, 35000.0, 33.0, 2254.684, 992.326 + 0.45, 35000.0, 33.5, 2341.659, 1031.46 + 0.45, 35000.0, 34.0, 2428.6, 1068.6 + 0.45, 35000.0, 34.5, 2514.815, 1087.99 + 0.45, 35000.0, 35.0, 2601.033, 1105.57 + 0.45, 35000.0, 35.5, 2687.303, 1122.17 + 0.45, 35000.0, 36.0, 2773.675, 1138.6 + 0.45, 35000.0, 36.5, 2860.201, 1155.67 + 0.45, 35000.0, 37.0, 2946.93, 1174.2 + 0.45, 35000.0, 37.5, 3033.913, 1195.0 + 0.45, 35000.0, 38.0, 3121.2, 1218.9 + 0.45, 35000.0, 38.5, 3209.823, 1238.76 + 0.45, 35000.0, 39.0, 3298.342, 1267.46 + 0.45, 35000.0, 39.5, 3386.59, 1307.58 + 0.45, 35000.0, 40.0, 3474.4, 1361.7 + 0.45, 35000.0, 40.5, 3560.587, 1458.64 + 0.45, 35000.0, 41.0, 3646.406, 1564.25 + 0.45, 35000.0, 41.5, 3732.098, 1670.61 + 0.45, 35000.0, 42.0, 3817.9, 1769.8 + 0.45, 35000.0, 42.5, 3905.025, 1839.46 + 0.45, 35000.0, 43.0, 3992.35, 1891.9 + 0.45, 35000.0, 43.5, 4079.725, 1924.99 + 0.45, 35000.0, 44.0, 4167.0, 1936.6 + 0.45, 35000.0, 44.5, 4253.377, 1889.37 + 0.45, 35000.0, 45.0, 4339.613, 1830.48 + 0.45, 35000.0, 45.5, 4425.817, 1771.87 + 0.45, 35000.0, 46.0, 4512.1, 1725.5 + 0.45, 35000.0, 46.5, 4599.004, 1746.05 + 0.45, 35000.0, 47.0, 4686.031, 1785.64 + 0.45, 35000.0, 47.5, 4773.118, 1839.14 + 0.45, 35000.0, 48.0, 4860.2, 1901.4 + 0.45, 35000.0, 48.5, 4947.213, 1967.28 + 0.45, 35000.0, 49.0, 5034.094, 2031.63 + 0.45, 35000.0, 49.5, 5120.777, 2089.32 + 0.45, 35000.0, 50.0, 5207.2, 2135.2 + 0.45, 39000.0, 0.0, 130.2728, 130.273 + 0.45, 39000.0, 22.0, 327.4, 281.3 + 0.45, 39000.0, 22.5, 391.2619, 290.94 + 0.45, 39000.0, 23.0, 453.9297, 308.544 + 0.45, 39000.0, 23.5, 515.7076, 332.751 + 0.45, 39000.0, 24.0, 576.9, 362.2 + 0.45, 39000.0, 24.5, 637.8111, 395.53 + 0.45, 39000.0, 25.0, 698.7453, 431.381 + 0.45, 39000.0, 25.5, 760.0068, 468.391 + 0.45, 39000.0, 26.0, 821.9, 505.2 + 0.45, 39000.0, 26.5, 887.7902, 528.739 + 0.45, 39000.0, 27.0, 955.0956, 548.685 + 0.45, 39000.0, 27.5, 1023.596, 565.685 + 0.45, 39000.0, 28.0, 1093.07, 580.385 + 0.45, 39000.0, 28.5, 1163.298, 593.43 + 0.45, 39000.0, 29.0, 1234.059, 605.467 + 0.45, 39000.0, 29.5, 1305.134, 617.142 + 0.45, 39000.0, 30.0, 1376.3, 629.1 + 0.45, 39000.0, 30.5, 1444.728, 649.942 + 0.45, 39000.0, 31.0, 1513.056, 671.602 + 0.45, 39000.0, 31.5, 1581.313, 693.969 + 0.45, 39000.0, 32.0, 1649.525, 716.931 + 0.45, 39000.0, 32.5, 1717.722, 740.377 + 0.45, 39000.0, 33.0, 1785.931, 764.195 + 0.45, 39000.0, 33.5, 1854.181, 788.273 + 0.45, 39000.0, 34.0, 1922.5, 812.5 + 0.45, 39000.0, 34.5, 1991.698, 839.63 + 0.45, 39000.0, 35.0, 2060.947, 866.412 + 0.45, 39000.0, 35.5, 2130.2, 892.464 + 0.45, 39000.0, 36.0, 2199.41, 917.4 + 0.45, 39000.0, 36.5, 2268.532, 940.836 + 0.45, 39000.0, 37.0, 2337.518, 962.387 + 0.45, 39000.0, 37.5, 2406.323, 981.67 + 0.45, 39000.0, 38.0, 2474.9, 998.3 + 0.45, 39000.0, 38.5, 2542.466, 998.962 + 0.45, 39000.0, 39.0, 2610.094, 1002.91 + 0.45, 39000.0, 39.5, 2677.899, 1012.62 + 0.45, 39000.0, 40.0, 2746.0, 1030.6 + 0.45, 39000.0, 40.5, 2815.107, 1067.3 + 0.45, 39000.0, 41.0, 2884.506, 1114.04 + 0.45, 39000.0, 41.5, 2954.077, 1170.14 + 0.45, 39000.0, 42.0, 3023.7, 1234.9 + 0.45, 39000.0, 42.5, 3092.527, 1318.17 + 0.45, 39000.0, 43.0, 3161.456, 1404.48 + 0.45, 39000.0, 43.5, 3230.657, 1488.89 + 0.45, 39000.0, 44.0, 3300.3, 1566.5 + 0.45, 39000.0, 44.5, 3372.399, 1626.41 + 0.45, 39000.0, 45.0, 3444.544, 1672.06 + 0.45, 39000.0, 45.5, 3516.166, 1700.9 + 0.45, 39000.0, 46.0, 3586.7, 1710.4 + 0.45, 39000.0, 46.5, 3652.292, 1669.45 + 0.45, 39000.0, 47.0, 3716.975, 1615.52 + 0.45, 39000.0, 47.5, 3781.495, 1557.51 + 0.45, 39000.0, 48.0, 3846.6, 1504.3 + 0.45, 39000.0, 48.5, 3913.036, 1464.79 + 0.45, 39000.0, 49.0, 3981.55, 1447.87 + 0.45, 39000.0, 49.5, 4052.889, 1462.45 + 0.45, 39000.0, 50.0, 4127.8, 1517.4 + 0.45, 43000.0, 0.0, 107.4879, 107.488 + 0.45, 43000.0, 22.0, 163.9, 362.9 + 0.45, 43000.0, 22.5, 200.6562, 309.203 + 0.45, 43000.0, 23.0, 236.525, 268.402 + 0.45, 43000.0, 23.5, 271.6562, 238.874 + 0.45, 43000.0, 24.0, 306.2, 219.0 + 0.45, 43000.0, 24.5, 340.3062, 207.157 + 0.45, 43000.0, 25.0, 374.125, 201.723 + 0.45, 43000.0, 25.5, 407.8062, 201.078 + 0.45, 43000.0, 26.0, 441.5, 203.6 + 0.45, 43000.0, 26.5, 476.5484, 191.562 + 0.45, 43000.0, 27.0, 511.9775, 178.527 + 0.45, 43000.0, 27.5, 547.7328, 165.635 + 0.45, 43000.0, 28.0, 583.76, 154.025 + 0.45, 43000.0, 28.5, 620.0047, 144.837 + 0.45, 43000.0, 29.0, 656.4125, 139.211 + 0.45, 43000.0, 29.5, 692.9291, 138.285 + 0.45, 43000.0, 30.0, 729.5, 143.2 + 0.45, 43000.0, 30.5, 765.2847, 169.597 + 0.45, 43000.0, 31.0, 801.0898, 202.733 + 0.45, 43000.0, 31.5, 836.936, 242.364 + 0.45, 43000.0, 32.0, 872.8438, 288.25 + 0.45, 43000.0, 32.5, 908.8335, 340.148 + 0.45, 43000.0, 33.0, 944.9258, 397.817 + 0.45, 43000.0, 33.5, 981.1411, 461.015 + 0.45, 43000.0, 34.0, 1017.5, 529.5 + 0.45, 43000.0, 34.5, 1055.694, 689.504 + 0.45, 43000.0, 35.0, 1093.914, 846.077 + 0.45, 43000.0, 35.5, 1132.021, 990.739 + 0.45, 43000.0, 36.0, 1169.875, 1115.01 + 0.45, 43000.0, 36.5, 1207.339, 1210.43 + 0.45, 43000.0, 37.0, 1244.273, 1268.5 + 0.45, 43000.0, 37.5, 1280.54, 1280.75 + 0.45, 43000.0, 38.0, 1316.0, 1238.7 + 0.45, 43000.0, 38.5, 1347.14, 1025.59 + 0.45, 43000.0, 39.0, 1378.945, 797.375 + 0.45, 43000.0, 39.5, 1412.028, 569.65 + 0.45, 43000.0, 40.0, 1447.0, 358.0 + 0.45, 43000.0, 40.5, 1489.262, 206.368 + 0.45, 43000.0, 41.0, 1532.719, 90.6437 + 0.45, 43000.0, 41.5, 1576.066, 15.0727 + 0.45, 43000.0, 42.0, 1618.0, -16.1 + 0.45, 43000.0, 42.5, 1650.922, 46.4844 + 0.45, 43000.0, 43.0, 1682.337, 143.912 + 0.45, 43000.0, 43.5, 1713.459, 262.384 + 0.45, 43000.0, 44.0, 1745.5, 388.1 + 0.45, 43000.0, 44.5, 1785.41, 482.209 + 0.45, 43000.0, 45.0, 1826.369, 565.981 + 0.45, 43000.0, 45.5, 1867.293, 635.638 + 0.45, 43000.0, 46.0, 1907.1, 687.4 + 0.45, 43000.0, 46.5, 1939.977, 688.264 + 0.45, 43000.0, 47.0, 1971.462, 675.362 + 0.45, 43000.0, 47.5, 2002.367, 656.605 + 0.45, 43000.0, 48.0, 2033.5, 639.9 + 0.45, 43000.0, 48.5, 2065.67, 633.158 + 0.45, 43000.0, 49.0, 2099.687, 644.287 + 0.45, 43000.0, 49.5, 2136.361, 681.198 + 0.45, 43000.0, 50.0, 2176.5, 751.8 + 0.45, 48000.0, 0.0, 84.52637, 84.5264 + 0.45, 48000.0, 22.0, 120.1, 291.8 + 0.45, 48000.0, 22.5, 153.8637, 247.774 + 0.45, 48000.0, 23.0, 185.1406, 214.911 + 0.45, 48000.0, 23.5, 214.3223, 191.743 + 0.45, 48000.0, 24.0, 241.8, 176.8 + 0.45, 48000.0, 24.5, 267.9652, 168.613 + 0.45, 48000.0, 25.0, 293.2094, 165.714 + 0.45, 48000.0, 25.5, 317.9238, 166.633 + 0.45, 48000.0, 26.0, 342.5, 169.9 + 0.45, 48000.0, 26.5, 370.5586, 159.348 + 0.45, 48000.0, 27.0, 399.4462, 147.367 + 0.45, 48000.0, 27.5, 429.0008, 135.008 + 0.45, 48000.0, 28.0, 459.06, 123.32 + 0.45, 48000.0, 28.5, 489.4617, 113.355 + 0.45, 48000.0, 29.0, 520.0437, 106.162 + 0.45, 48000.0, 29.5, 550.6439, 102.794 + 0.45, 48000.0, 30.0, 581.1, 104.3 + 0.45, 48000.0, 30.5, 608.8578, 125.648 + 0.45, 48000.0, 31.0, 636.375, 152.646 + 0.45, 48000.0, 31.5, 663.7172, 185.02 + 0.45, 48000.0, 32.0, 690.95, 222.494 + 0.45, 48000.0, 32.5, 718.1391, 264.794 + 0.45, 48000.0, 33.0, 745.35, 311.645 + 0.45, 48000.0, 33.5, 772.6484, 362.772 + 0.45, 48000.0, 34.0, 800.1, 417.9 + 0.45, 48000.0, 34.5, 830.0508, 542.644 + 0.45, 48000.0, 35.0, 860.0687, 664.564 + 0.45, 48000.0, 35.5, 890.0023, 777.111 + 0.45, 48000.0, 36.0, 919.7, 873.735 + 0.45, 48000.0, 36.5, 949.0102, 947.886 + 0.45, 48000.0, 37.0, 977.7812, 993.013 + 0.45, 48000.0, 37.5, 1005.862, 1002.57 + 0.45, 48000.0, 38.0, 1033.1, 970.0 + 0.45, 48000.0, 38.5, 1055.252, 805.288 + 0.45, 48000.0, 39.0, 1078.381, 628.634 + 0.45, 48000.0, 39.5, 1103.245, 452.039 + 0.45, 48000.0, 40.0, 1130.6, 287.5 + 0.45, 48000.0, 40.5, 1167.491, 168.16 + 0.45, 48000.0, 41.0, 1205.875, 76.4187 + 0.45, 48000.0, 41.5, 1243.997, 15.818 + 0.45, 48000.0, 42.0, 1280.1, -10.1 + 0.45, 48000.0, 42.5, 1304.381, 37.8594 + 0.45, 48000.0, 43.0, 1326.35, 113.325 + 0.45, 48000.0, 43.5, 1347.469, 205.578 + 0.45, 48000.0, 44.0, 1369.2, 303.9 + 0.45, 48000.0, 44.5, 1398.413, 378.763 + 0.45, 48000.0, 45.0, 1429.0, 445.781 + 0.45, 48000.0, 45.5, 1460.263, 501.759 + 0.45, 48000.0, 46.0, 1491.5, 543.5 + 0.45, 48000.0, 46.5, 1519.856, 543.65 + 0.45, 48000.0, 47.0, 1547.65, 532.838 + 0.45, 48000.0, 47.5, 1575.044, 517.531 + 0.45, 48000.0, 48.0, 1602.2, 504.2 + 0.45, 48000.0, 48.5, 1629.281, 499.313 + 0.45, 48000.0, 49.0, 1656.45, 509.338 + 0.45, 48000.0, 49.5, 1683.869, 540.744 + 0.45, 48000.0, 50.0, 1711.7, 600.0 + 0.5, 0.0, 0.0, 597.7443, 597.744 + 0.5, 0.0, 22.0, 1322.7, 1247.1 + 0.5, 0.0, 22.5, 1573.548, 1377.17 + 0.5, 0.0, 23.0, 1821.292, 1477.3 + 0.5, 0.0, 23.5, 2066.89, 1553.58 + 0.5, 0.0, 24.0, 2311.3, 1612.1 + 0.5, 0.0, 24.5, 2555.478, 1658.95 + 0.5, 0.0, 25.0, 2800.383, 1700.23 + 0.5, 0.0, 25.5, 3046.971, 1742.01 + 0.5, 0.0, 26.0, 3296.2, 1790.4 + 0.5, 0.0, 26.5, 3559.004, 1909.69 + 0.5, 0.0, 27.0, 3826.934, 2051.09 + 0.5, 0.0, 27.5, 4099.237, 2210.71 + 0.5, 0.0, 28.0, 4375.16, 2384.67 + 0.5, 0.0, 28.5, 4653.951, 2569.06 + 0.5, 0.0, 29.0, 4934.856, 2760.0 + 0.5, 0.0, 29.5, 5217.124, 2953.61 + 0.5, 0.0, 30.0, 5500.0, 3146.0 + 0.5, 0.0, 30.5, 5774.525, 3283.5 + 0.5, 0.0, 31.0, 6048.934, 3416.74 + 0.5, 0.0, 31.5, 6323.258, 3546.57 + 0.5, 0.0, 32.0, 6597.525, 3673.83 + 0.5, 0.0, 32.5, 6871.764, 3799.39 + 0.5, 0.0, 33.0, 7146.003, 3924.08 + 0.5, 0.0, 33.5, 7420.272, 4048.77 + 0.5, 0.0, 34.0, 7694.6, 4174.3 + 0.5, 0.0, 34.5, 7969.489, 4362.82 + 0.5, 0.0, 35.0, 8244.45, 4548.05 + 0.5, 0.0, 35.5, 8519.466, 4725.0 + 0.5, 0.0, 36.0, 8794.52, 4888.68 + 0.5, 0.0, 36.5, 9069.597, 5034.11 + 0.5, 0.0, 37.0, 9344.68, 5156.29 + 0.5, 0.0, 37.5, 9619.753, 5250.25 + 0.5, 0.0, 38.0, 9894.8, 5311.0 + 0.5, 0.0, 38.5, 10169.8, 5289.26 + 0.5, 0.0, 39.0, 10444.74, 5247.3 + 0.5, 0.0, 39.5, 10719.61, 5189.96 + 0.5, 0.0, 40.0, 10994.4, 5122.1 + 0.5, 0.0, 40.5, 11269.22, 5041.12 + 0.5, 0.0, 41.0, 11543.87, 4962.31 + 0.5, 0.0, 41.5, 11818.29, 4893.49 + 0.5, 0.0, 42.0, 12092.4, 4842.5 + 0.5, 0.0, 42.5, 12365.15, 4828.84 + 0.5, 0.0, 43.0, 12637.87, 4844.0 + 0.5, 0.0, 43.5, 12910.87, 4891.13 + 0.5, 0.0, 44.0, 13184.5, 4973.4 + 0.5, 0.0, 44.5, 13461.06, 5121.98 + 0.5, 0.0, 45.0, 13738.1, 5300.81 + 0.5, 0.0, 45.5, 14015.17, 5501.83 + 0.5, 0.0, 46.0, 14291.8, 5717.0 + 0.5, 0.0, 46.5, 14565.47, 5924.82 + 0.5, 0.0, 47.0, 14838.61, 6136.07 + 0.5, 0.0, 47.5, 15111.56, 6348.09 + 0.5, 0.0, 48.0, 15384.7, 6558.2 + 0.5, 0.0, 48.5, 15658.38, 6763.73 + 0.5, 0.0, 49.0, 15932.97, 6962.02 + 0.5, 0.0, 49.5, 16208.82, 7150.4 + 0.5, 0.0, 50.0, 16486.3, 7326.2 + 0.5, 2000.0, 0.0, 559.6499, 559.65 + 0.5, 2000.0, 22.0, -888.0, 406.8 + 0.5, 2000.0, 22.5, -1055.434, 352.722 + 0.5, 2000.0, 23.0, -1221.269, 304.825 + 0.5, 2000.0, 23.5, -1386.07, 261.516 + 0.5, 2000.0, 24.0, -1550.4, 221.2 + 0.5, 2000.0, 24.5, -1714.824, 182.284 + 0.5, 2000.0, 25.0, -1879.906, 143.175 + 0.5, 2000.0, 25.5, -2046.21, 102.278 + 0.5, 2000.0, 26.0, -2214.3, 58.0 + 0.5, 2000.0, 26.5, -2390.724, -7.40781 + 0.5, 2000.0, 27.0, -2570.404, -80.3075 + 0.5, 2000.0, 27.5, -2752.878, -159.523 + 0.5, 2000.0, 28.0, -2937.685, -243.88 + 0.5, 2000.0, 28.5, -3124.362, -332.202 + 0.5, 2000.0, 29.0, -3312.448, -423.312 + 0.5, 2000.0, 29.5, -3501.482, -516.037 + 0.5, 2000.0, 30.0, -3691.0, -609.2 + 0.5, 2000.0, 30.5, -3875.703, -684.886 + 0.5, 2000.0, 31.0, -4060.429, -760.254 + 0.5, 2000.0, 31.5, -4245.176, -835.721 + 0.5, 2000.0, 32.0, -4429.944, -911.706 + 0.5, 2000.0, 32.5, -4614.731, -988.628 + 0.5, 2000.0, 33.0, -4799.537, -1066.91 + 0.5, 2000.0, 33.5, -4984.36, -1146.96 + 0.5, 2000.0, 34.0, -5169.2, -1229.2 + 0.5, 2000.0, 34.5, -5354.332, -1339.78 + 0.5, 2000.0, 35.0, -5539.453, -1450.94 + 0.5, 2000.0, 35.5, -5724.535, -1560.64 + 0.5, 2000.0, 36.0, -5909.55, -1666.87 + 0.5, 2000.0, 36.5, -6094.471, -1767.57 + 0.5, 2000.0, 37.0, -6279.272, -1860.74 + 0.5, 2000.0, 37.5, -6463.924, -1944.32 + 0.5, 2000.0, 38.0, -6648.4, -2016.3 + 0.5, 2000.0, 38.5, -6832.172, -2057.06 + 0.5, 2000.0, 39.0, -7015.973, -2091.26 + 0.5, 2000.0, 39.5, -7199.888, -2120.78 + 0.5, 2000.0, 40.0, -7384.0, -2147.5 + 0.5, 2000.0, 40.5, -7568.818, -2168.82 + 0.5, 2000.0, 41.0, -7753.831, -2192.87 + 0.5, 2000.0, 41.5, -7938.954, -2223.31 + 0.5, 2000.0, 42.0, -8124.1, -2263.8 + 0.5, 2000.0, 42.5, -8308.836, -2330.13 + 0.5, 2000.0, 43.0, -8493.562, -2408.99 + 0.5, 2000.0, 43.5, -8678.333, -2499.17 + 0.5, 2000.0, 44.0, -8863.2, -2599.5 + 0.5, 2000.0, 44.5, -9048.752, -2709.89 + 0.5, 2000.0, 45.0, -9234.294, -2827.59 + 0.5, 2000.0, 45.5, -9419.663, -2950.97 + 0.5, 2000.0, 46.0, -9604.7, -3078.4 + 0.5, 2000.0, 46.5, -9788.356, -3204.42 + 0.5, 2000.0, 47.0, -9971.713, -3332.75 + 0.5, 2000.0, 47.5, -10154.96, -3463.28 + 0.5, 2000.0, 48.0, -10338.3, -3595.9 + 0.5, 2000.0, 48.5, -10521.92, -3730.51 + 0.5, 2000.0, 49.0, -10706.01, -3867.0 + 0.5, 2000.0, 49.5, -10890.78, -4005.27 + 0.5, 2000.0, 50.0, -11076.4, -4145.2 + 0.5, 5000.0, 0.0, 506.1282, 506.128 + 0.5, 5000.0, 22.0, 1570.0, 1201.6 + 0.5, 5000.0, 22.5, 1868.23, 1309.8 + 0.5, 5000.0, 23.0, 2163.298, 1415.19 + 0.5, 5000.0, 23.5, 2456.243, 1518.64 + 0.5, 5000.0, 24.0, 2748.1, 1621.0 + 0.5, 5000.0, 24.5, 3039.907, 1723.14 + 0.5, 5000.0, 25.0, 3332.702, 1825.91 + 0.5, 5000.0, 25.5, 3627.52, 1930.18 + 0.5, 5000.0, 26.0, 3925.4, 2036.8 + 0.5, 5000.0, 26.5, 4238.227, 2155.34 + 0.5, 5000.0, 27.0, 4556.809, 2278.45 + 0.5, 5000.0, 27.5, 4880.325, 2405.51 + 0.5, 5000.0, 28.0, 5207.95, 2535.88 + 0.5, 5000.0, 28.5, 5538.863, 2668.94 + 0.5, 5000.0, 29.0, 5872.241, 2804.05 + 0.5, 5000.0, 29.5, 6207.261, 2940.58 + 0.5, 5000.0, 30.0, 6543.1, 3077.9 + 0.5, 5000.0, 30.5, 6870.311, 3208.86 + 0.5, 5000.0, 31.0, 7197.517, 3339.96 + 0.5, 5000.0, 31.5, 7524.718, 3471.22 + 0.5, 5000.0, 32.0, 7851.913, 3602.6 + 0.5, 5000.0, 32.5, 8179.099, 3734.11 + 0.5, 5000.0, 33.0, 8506.277, 3865.74 + 0.5, 5000.0, 33.5, 8833.444, 3997.47 + 0.5, 5000.0, 34.0, 9160.6, 4129.3 + 0.5, 5000.0, 34.5, 9487.702, 4261.91 + 0.5, 5000.0, 35.0, 9814.794, 4394.53 + 0.5, 5000.0, 35.5, 10141.88, 4527.09 + 0.5, 5000.0, 36.0, 10468.96, 4659.51 + 0.5, 5000.0, 36.5, 10796.04, 4791.73 + 0.5, 5000.0, 37.0, 11123.12, 4923.67 + 0.5, 5000.0, 37.5, 11450.21, 5055.25 + 0.5, 5000.0, 38.0, 11777.3, 5186.4 + 0.5, 5000.0, 38.5, 12104.42, 5317.34 + 0.5, 5000.0, 39.0, 12431.55, 5447.54 + 0.5, 5000.0, 39.5, 12758.67, 5576.88 + 0.5, 5000.0, 40.0, 13085.8, 5705.2 + 0.5, 5000.0, 40.5, 13412.89, 5830.13 + 0.5, 5000.0, 41.0, 13740.0, 5954.67 + 0.5, 5000.0, 41.5, 14067.13, 6079.57 + 0.5, 5000.0, 42.0, 14394.3, 6205.6 + 0.5, 5000.0, 42.5, 14721.36, 6334.65 + 0.5, 5000.0, 43.0, 15048.55, 6465.88 + 0.5, 5000.0, 43.5, 15375.94, 6599.6 + 0.5, 5000.0, 44.0, 15703.6, 6736.1 + 0.5, 5000.0, 44.5, 16032.54, 6877.17 + 0.5, 5000.0, 45.0, 16361.53, 7021.03 + 0.5, 5000.0, 45.5, 16690.28, 7167.41 + 0.5, 5000.0, 46.0, 17018.5, 7316.0 + 0.5, 5000.0, 46.5, 17344.37, 7466.8 + 0.5, 5000.0, 47.0, 17669.71, 7619.13 + 0.5, 5000.0, 47.5, 17994.85, 7772.6 + 0.5, 5000.0, 48.0, 18320.1, 7926.8 + 0.5, 5000.0, 48.5, 18645.77, 8081.34 + 0.5, 5000.0, 49.0, 18972.16, 8235.82 + 0.5, 5000.0, 49.5, 19299.6, 8389.84 + 0.5, 5000.0, 50.0, 19628.4, 8543.0 + 0.5, 10000.0, 0.0, 425.9792, 425.979 + 0.5, 10000.0, 22.0, 883.2, 864.0 + 0.5, 10000.0, 22.5, 1050.827, 925.985 + 0.5, 10000.0, 23.0, 1216.719, 987.467 + 0.5, 10000.0, 23.5, 1381.451, 1048.67 + 0.5, 10000.0, 24.0, 1545.6, 1109.8 + 0.5, 10000.0, 24.5, 1709.743, 1171.09 + 0.5, 10000.0, 25.0, 1874.456, 1232.76 + 0.5, 10000.0, 25.5, 2040.316, 1295.02 + 0.5, 10000.0, 26.0, 2207.9, 1358.1 + 0.5, 10000.0, 26.5, 2383.832, 1424.42 + 0.5, 10000.0, 27.0, 2562.986, 1492.11 + 0.5, 10000.0, 27.5, 2744.902, 1561.04 + 0.5, 10000.0, 28.0, 2929.12, 1631.02 + 0.5, 10000.0, 28.5, 3115.179, 1701.92 + 0.5, 10000.0, 29.0, 3302.619, 1773.57 + 0.5, 10000.0, 29.5, 3490.979, 1845.82 + 0.5, 10000.0, 30.0, 3679.8, 1918.5 + 0.5, 10000.0, 30.5, 3863.785, 1989.99 + 0.5, 10000.0, 31.0, 4047.771, 2061.74 + 0.5, 10000.0, 31.5, 4231.757, 2133.73 + 0.5, 10000.0, 32.0, 4415.744, 2205.96 + 0.5, 10000.0, 32.5, 4599.731, 2278.39 + 0.5, 10000.0, 33.0, 4783.72, 2351.02 + 0.5, 10000.0, 33.5, 4967.709, 2423.83 + 0.5, 10000.0, 34.0, 5151.7, 2496.8 + 0.5, 10000.0, 34.5, 5335.697, 2569.73 + 0.5, 10000.0, 35.0, 5519.695, 2642.81 + 0.5, 10000.0, 35.5, 5703.695, 2716.03 + 0.5, 10000.0, 36.0, 5887.695, 2789.4 + 0.5, 10000.0, 36.5, 6071.696, 2862.91 + 0.5, 10000.0, 37.0, 6255.697, 2936.56 + 0.5, 10000.0, 37.5, 6439.699, 3010.36 + 0.5, 10000.0, 38.0, 6623.7, 3084.3 + 0.5, 10000.0, 38.5, 6807.7, 3158.1 + 0.5, 10000.0, 39.0, 6991.7, 3232.2 + 0.5, 10000.0, 39.5, 7175.7, 3306.64 + 0.5, 10000.0, 40.0, 7359.7, 3381.5 + 0.5, 10000.0, 40.5, 7543.704, 3457.18 + 0.5, 10000.0, 41.0, 7727.706, 3533.26 + 0.5, 10000.0, 41.5, 7911.705, 3609.66 + 0.5, 10000.0, 42.0, 8095.7, 3686.3 + 0.5, 10000.0, 42.5, 8279.536, 3762.83 + 0.5, 10000.0, 43.0, 8463.425, 3839.55 + 0.5, 10000.0, 43.5, 8647.427, 3916.5 + 0.5, 10000.0, 44.0, 8831.6, 3993.7 + 0.5, 10000.0, 44.5, 9016.583, 4071.43 + 0.5, 10000.0, 45.0, 9201.625, 4149.38 + 0.5, 10000.0, 45.5, 9386.555, 4227.49 + 0.5, 10000.0, 46.0, 9571.2, 4305.7 + 0.5, 10000.0, 46.5, 9754.53, 4383.4 + 0.5, 10000.0, 47.0, 9937.575, 4461.28 + 0.5, 10000.0, 47.5, 10120.51, 4539.49 + 0.5, 10000.0, 48.0, 10303.5, 4618.2 + 0.5, 10000.0, 48.5, 10486.72, 4697.55 + 0.5, 10000.0, 49.0, 10670.35, 4777.7 + 0.5, 10000.0, 49.5, 10854.55, 4858.8 + 0.5, 10000.0, 50.0, 11039.5, 4941.0 + 0.5, 15000.0, 0.0, 356.201, 356.201 + 0.5, 15000.0, 22.0, 793.1, 742.8 + 0.5, 15000.0, 22.5, 943.6236, 797.829 + 0.5, 15000.0, 23.0, 1092.586, 852.266 + 0.5, 15000.0, 23.5, 1240.505, 906.319 + 0.5, 15000.0, 24.0, 1387.9, 960.2 + 0.5, 15000.0, 24.5, 1535.288, 1014.12 + 0.5, 15000.0, 25.0, 1683.189, 1068.28 + 0.5, 15000.0, 25.5, 1832.12, 1122.91 + 0.5, 15000.0, 26.0, 1982.6, 1178.2 + 0.5, 15000.0, 26.5, 2140.584, 1236.31 + 0.5, 15000.0, 27.0, 2301.465, 1295.62 + 0.5, 15000.0, 27.5, 2464.828, 1356.0 + 0.5, 15000.0, 28.0, 2630.26, 1417.34 + 0.5, 15000.0, 28.5, 2797.347, 1479.51 + 0.5, 15000.0, 29.0, 2965.675, 1542.39 + 0.5, 15000.0, 29.5, 3134.831, 1605.86 + 0.5, 15000.0, 30.0, 3304.4, 1669.8 + 0.5, 15000.0, 30.5, 3469.627, 1733.09 + 0.5, 15000.0, 31.0, 3634.854, 1796.69 + 0.5, 15000.0, 31.5, 3800.08, 1860.58 + 0.5, 15000.0, 32.0, 3965.306, 1924.73 + 0.5, 15000.0, 32.5, 4130.531, 1989.12 + 0.5, 15000.0, 33.0, 4295.755, 2053.71 + 0.5, 15000.0, 33.5, 4460.978, 2118.48 + 0.5, 15000.0, 34.0, 4626.2, 2183.4 + 0.5, 15000.0, 34.5, 4791.412, 2248.0 + 0.5, 15000.0, 35.0, 4956.623, 2312.74 + 0.5, 15000.0, 35.5, 5121.834, 2377.63 + 0.5, 15000.0, 36.0, 5287.045, 2442.68 + 0.5, 15000.0, 36.5, 5452.256, 2507.93 + 0.5, 15000.0, 37.0, 5617.469, 2573.37 + 0.5, 15000.0, 37.5, 5782.683, 2639.02 + 0.5, 15000.0, 38.0, 5947.9, 2704.9 + 0.5, 15000.0, 38.5, 6113.124, 2771.02 + 0.5, 15000.0, 39.0, 6278.348, 2837.4 + 0.5, 15000.0, 39.5, 6443.574, 2904.05 + 0.5, 15000.0, 40.0, 6608.8, 2971.0 + 0.5, 15000.0, 40.5, 6774.029, 3038.36 + 0.5, 15000.0, 41.0, 6939.256, 3106.01 + 0.5, 15000.0, 41.5, 7104.48, 3173.89 + 0.5, 15000.0, 42.0, 7269.7, 3242.0 + 0.5, 15000.0, 42.5, 7434.773, 3310.11 + 0.5, 15000.0, 43.0, 7599.894, 3378.44 + 0.5, 15000.0, 43.5, 7765.118, 3447.06 + 0.5, 15000.0, 44.0, 7930.5, 3516.0 + 0.5, 15000.0, 44.5, 8096.622, 3585.41 + 0.5, 15000.0, 45.0, 8262.8, 3655.19 + 0.5, 15000.0, 45.5, 8428.878, 3725.36 + 0.5, 15000.0, 46.0, 8594.7, 3795.9 + 0.5, 15000.0, 46.5, 8759.332, 3866.75 + 0.5, 15000.0, 47.0, 8923.706, 3938.03 + 0.5, 15000.0, 47.5, 9087.977, 4009.77 + 0.5, 15000.0, 48.0, 9252.3, 4082.0 + 0.5, 15000.0, 48.5, 9416.829, 4154.76 + 0.5, 15000.0, 49.0, 9581.719, 4228.09 + 0.5, 15000.0, 49.5, 9747.124, 4302.03 + 0.5, 15000.0, 50.0, 9913.2, 4376.6 + 0.5, 20000.0, 0.0, 295.7787, 295.779 + 0.5, 20000.0, 22.0, 796.6, 664.7 + 0.5, 20000.0, 22.5, 947.8068, 719.055 + 0.5, 20000.0, 23.0, 1097.445, 772.886 + 0.5, 20000.0, 23.5, 1246.036, 826.399 + 0.5, 20000.0, 24.0, 1394.1, 879.8 + 0.5, 20000.0, 24.5, 1542.158, 933.295 + 0.5, 20000.0, 25.0, 1690.73, 987.089 + 0.5, 20000.0, 25.5, 1840.337, 1041.39 + 0.5, 20000.0, 26.0, 1991.5, 1096.4 + 0.5, 20000.0, 26.5, 2150.204, 1154.23 + 0.5, 20000.0, 27.0, 2311.818, 1213.29 + 0.5, 20000.0, 27.5, 2475.925, 1273.47 + 0.5, 20000.0, 28.0, 2642.11, 1334.64 + 0.5, 20000.0, 28.5, 2809.956, 1396.67 + 0.5, 20000.0, 29.0, 2979.047, 1459.46 + 0.5, 20000.0, 29.5, 3148.967, 1522.87 + 0.5, 20000.0, 30.0, 3319.3, 1586.8 + 0.5, 20000.0, 30.5, 3485.253, 1650.12 + 0.5, 20000.0, 31.0, 3651.203, 1713.8 + 0.5, 20000.0, 31.5, 3817.152, 1777.82 + 0.5, 20000.0, 32.0, 3983.1, 1842.16 + 0.5, 20000.0, 32.5, 4149.048, 1906.78 + 0.5, 20000.0, 33.0, 4314.997, 1971.66 + 0.5, 20000.0, 33.5, 4480.947, 2036.77 + 0.5, 20000.0, 34.0, 4646.9, 2102.1 + 0.5, 20000.0, 34.5, 4812.876, 2167.11 + 0.5, 20000.0, 35.0, 4978.853, 2232.33 + 0.5, 20000.0, 35.5, 5144.832, 2297.77 + 0.5, 20000.0, 36.0, 5310.81, 2363.47 + 0.5, 20000.0, 36.5, 5476.787, 2429.44 + 0.5, 20000.0, 37.0, 5642.762, 2495.7 + 0.5, 20000.0, 37.5, 5808.733, 2562.28 + 0.5, 20000.0, 38.0, 5974.7, 2629.2 + 0.5, 20000.0, 38.5, 6140.653, 2696.49 + 0.5, 20000.0, 39.0, 6306.603, 2764.15 + 0.5, 20000.0, 39.5, 6472.552, 2832.22 + 0.5, 20000.0, 40.0, 6638.5, 2900.7 + 0.5, 20000.0, 40.5, 6804.446, 2969.54 + 0.5, 20000.0, 41.0, 6970.394, 3038.86 + 0.5, 20000.0, 41.5, 7136.345, 3108.73 + 0.5, 20000.0, 42.0, 7302.3, 3179.2 + 0.5, 20000.0, 42.5, 7468.145, 3250.51 + 0.5, 20000.0, 43.0, 7634.044, 3322.45 + 0.5, 20000.0, 43.5, 7800.046, 3394.99 + 0.5, 20000.0, 44.0, 7966.2, 3468.1 + 0.5, 20000.0, 44.5, 8133.054, 3541.7 + 0.5, 20000.0, 45.0, 8299.956, 3615.84 + 0.5, 20000.0, 45.5, 8466.755, 3690.54 + 0.5, 20000.0, 46.0, 8633.3, 3765.8 + 0.5, 20000.0, 46.5, 8798.677, 3841.13 + 0.5, 20000.0, 47.0, 8963.8, 3917.21 + 0.5, 20000.0, 47.5, 9128.823, 3994.24 + 0.5, 20000.0, 48.0, 9293.9, 4072.4 + 0.5, 20000.0, 48.5, 9459.183, 4151.89 + 0.5, 20000.0, 49.0, 9624.825, 4232.91 + 0.5, 20000.0, 49.5, 9790.98, 4315.65 + 0.5, 20000.0, 50.0, 9957.8, 4400.3 + 0.5, 25000.0, 0.0, 243.7555, 243.755 + 0.5, 25000.0, 22.0, 643.1, 544.5 + 0.5, 25000.0, 22.5, 765.0832, 587.856 + 0.5, 25000.0, 23.0, 885.8344, 630.725 + 0.5, 25000.0, 23.5, 1005.768, 673.281 + 0.5, 25000.0, 24.0, 1125.3, 715.7 + 0.5, 25000.0, 24.5, 1244.844, 758.156 + 0.5, 25000.0, 25.0, 1364.816, 800.825 + 0.5, 25000.0, 25.5, 1485.629, 843.881 + 0.5, 25000.0, 26.0, 1607.7, 887.5 + 0.5, 25000.0, 26.5, 1735.807, 933.532 + 0.5, 25000.0, 27.0, 1866.249, 980.573 + 0.5, 25000.0, 27.5, 1998.695, 1028.51 + 0.5, 25000.0, 28.0, 2132.81, 1077.23 + 0.5, 25000.0, 28.5, 2268.261, 1126.62 + 0.5, 25000.0, 29.0, 2404.716, 1176.57 + 0.5, 25000.0, 29.5, 2541.84, 1226.97 + 0.5, 25000.0, 30.0, 2679.3, 1277.7 + 0.5, 25000.0, 30.5, 2813.268, 1327.58 + 0.5, 25000.0, 31.0, 2947.239, 1377.67 + 0.5, 25000.0, 31.5, 3081.212, 1427.96 + 0.5, 25000.0, 32.0, 3215.187, 1478.44 + 0.5, 25000.0, 32.5, 3349.164, 1529.11 + 0.5, 25000.0, 33.0, 3483.142, 1579.95 + 0.5, 25000.0, 33.5, 3617.121, 1630.95 + 0.5, 25000.0, 34.0, 3751.1, 1682.1 + 0.5, 25000.0, 34.5, 3885.075, 1732.98 + 0.5, 25000.0, 35.0, 4019.05, 1784.03 + 0.5, 25000.0, 35.5, 4153.025, 1835.28 + 0.5, 25000.0, 36.0, 4287.0, 1886.77 + 0.5, 25000.0, 36.5, 4420.975, 1938.51 + 0.5, 25000.0, 37.0, 4554.95, 1990.54 + 0.5, 25000.0, 37.5, 4688.925, 2042.9 + 0.5, 25000.0, 38.0, 4822.9, 2095.6 + 0.5, 25000.0, 38.5, 4956.88, 2148.61 + 0.5, 25000.0, 39.0, 5090.858, 2202.07 + 0.5, 25000.0, 39.5, 5224.831, 2256.02 + 0.5, 25000.0, 40.0, 5358.8, 2310.5 + 0.5, 25000.0, 40.5, 5492.752, 2365.81 + 0.5, 25000.0, 41.0, 5626.7, 2421.64 + 0.5, 25000.0, 41.5, 5760.648, 2477.96 + 0.5, 25000.0, 42.0, 5894.6, 2534.7 + 0.5, 25000.0, 42.5, 6028.468, 2591.69 + 0.5, 25000.0, 43.0, 6162.381, 2649.06 + 0.5, 25000.0, 43.5, 6296.379, 2706.79 + 0.5, 25000.0, 44.0, 6430.5, 2764.9 + 0.5, 25000.0, 44.5, 6565.186, 2823.32 + 0.5, 25000.0, 45.0, 6699.913, 2882.13 + 0.5, 25000.0, 45.5, 6834.558, 2941.35 + 0.5, 25000.0, 46.0, 6969.0, 3001.0 + 0.5, 25000.0, 46.5, 7102.512, 3060.8 + 0.5, 25000.0, 47.0, 7235.819, 3121.19 + 0.5, 25000.0, 47.5, 7369.041, 3182.31 + 0.5, 25000.0, 48.0, 7502.3, 3244.3 + 0.5, 25000.0, 48.5, 7635.715, 3307.29 + 0.5, 25000.0, 49.0, 7769.406, 3371.43 + 0.5, 25000.0, 49.5, 7903.495, 3436.85 + 0.5, 25000.0, 50.0, 8038.1, 3503.7 + 0.5, 30000.0, 0.0, 199.2416, 199.242 + 0.5, 30000.0, 22.0, 503.1, 443.3 + 0.5, 30000.0, 22.5, 598.4783, 475.982 + 0.5, 30000.0, 23.0, 692.9234, 508.209 + 0.5, 30000.0, 23.5, 786.7568, 540.157 + 0.5, 30000.0, 24.0, 880.3, 572.0 + 0.5, 30000.0, 24.5, 973.8744, 603.911 + 0.5, 30000.0, 25.0, 1067.802, 636.066 + 0.5, 30000.0, 25.5, 1162.403, 668.637 + 0.5, 30000.0, 26.0, 1258.0, 701.8 + 0.5, 30000.0, 26.5, 1358.324, 737.655 + 0.5, 30000.0, 27.0, 1460.482, 774.56 + 0.5, 30000.0, 27.5, 1564.21, 812.358 + 0.5, 30000.0, 28.0, 1669.245, 850.895 + 0.5, 30000.0, 28.5, 1775.325, 890.013 + 0.5, 30000.0, 29.0, 1882.186, 929.558 + 0.5, 30000.0, 29.5, 1989.565, 969.372 + 0.5, 30000.0, 30.0, 2097.2, 1009.3 + 0.5, 30000.0, 30.5, 2202.053, 1047.31 + 0.5, 30000.0, 31.0, 2306.898, 1085.29 + 0.5, 30000.0, 31.5, 2411.739, 1123.28 + 0.5, 30000.0, 32.0, 2516.575, 1161.3 + 0.5, 30000.0, 32.5, 2621.408, 1199.37 + 0.5, 30000.0, 33.0, 2726.239, 1237.51 + 0.5, 30000.0, 33.5, 2831.069, 1275.74 + 0.5, 30000.0, 34.0, 2935.9, 1314.1 + 0.5, 30000.0, 34.5, 3040.773, 1352.24 + 0.5, 30000.0, 35.0, 3145.645, 1390.58 + 0.5, 30000.0, 35.5, 3250.513, 1429.18 + 0.5, 30000.0, 36.0, 3355.375, 1468.08 + 0.5, 30000.0, 36.5, 3460.227, 1507.37 + 0.5, 30000.0, 37.0, 3565.067, 1547.07 + 0.5, 30000.0, 37.5, 3669.892, 1587.27 + 0.5, 30000.0, 38.0, 3774.7, 1628.0 + 0.5, 30000.0, 38.5, 3879.403, 1670.51 + 0.5, 30000.0, 39.0, 3984.127, 1713.06 + 0.5, 30000.0, 39.5, 4088.887, 1755.46 + 0.5, 30000.0, 40.0, 4193.7, 1797.5 + 0.5, 30000.0, 40.5, 4298.696, 1837.84 + 0.5, 30000.0, 41.0, 4403.731, 1877.86 + 0.5, 30000.0, 41.5, 4508.776, 1917.83 + 0.5, 30000.0, 42.0, 4613.8, 1958.0 + 0.5, 30000.0, 42.5, 4718.606, 1998.13 + 0.5, 30000.0, 43.0, 4823.4, 2039.16 + 0.5, 30000.0, 43.5, 4928.219, 2081.54 + 0.5, 30000.0, 44.0, 5033.1, 2125.7 + 0.5, 30000.0, 44.5, 5138.374, 2175.5 + 0.5, 30000.0, 45.0, 5243.669, 2226.62 + 0.5, 30000.0, 45.5, 5348.904, 2278.16 + 0.5, 30000.0, 46.0, 5454.0, 2329.2 + 0.5, 30000.0, 46.5, 5558.455, 2375.73 + 0.5, 30000.0, 47.0, 5662.781, 2421.19 + 0.5, 30000.0, 47.5, 5767.066, 2465.9 + 0.5, 30000.0, 48.0, 5871.4, 2510.2 + 0.5, 30000.0, 48.5, 5975.871, 2554.42 + 0.5, 30000.0, 49.0, 6080.569, 2598.89 + 0.5, 30000.0, 49.5, 6185.582, 2643.94 + 0.5, 30000.0, 50.0, 6291.0, 2689.9 + 0.5, 35000.0, 0.0, 161.4083, 161.408 + 0.5, 35000.0, 22.0, 398.3, 368.6 + 0.5, 35000.0, 22.5, 474.5221, 388.573 + 0.5, 35000.0, 23.0, 549.8109, 411.75 + 0.5, 35000.0, 23.5, 624.4443, 437.627 + 0.5, 35000.0, 24.0, 698.7, 465.7 + 0.5, 35000.0, 24.5, 772.8557, 495.467 + 0.5, 35000.0, 25.0, 847.1891, 526.425 + 0.5, 35000.0, 25.5, 921.9779, 558.07 + 0.5, 35000.0, 26.0, 997.5, 589.9 + 0.5, 35000.0, 26.5, 1076.838, 616.567 + 0.5, 35000.0, 27.0, 1157.626, 642.135 + 0.5, 35000.0, 27.5, 1239.659, 666.932 + 0.5, 35000.0, 28.0, 1322.735, 691.285 + 0.5, 35000.0, 28.5, 1406.65, 715.521 + 0.5, 35000.0, 29.0, 1491.202, 739.967 + 0.5, 35000.0, 29.5, 1576.186, 764.951 + 0.5, 35000.0, 30.0, 1661.4, 790.8 + 0.5, 35000.0, 30.5, 1744.564, 824.222 + 0.5, 35000.0, 31.0, 1827.75, 858.556 + 0.5, 35000.0, 31.5, 1910.951, 893.521 + 0.5, 35000.0, 32.0, 1994.163, 928.837 + 0.5, 35000.0, 32.5, 2077.379, 964.224 + 0.5, 35000.0, 33.0, 2160.594, 999.4 + 0.5, 35000.0, 33.5, 2243.803, 1034.09 + 0.5, 35000.0, 34.0, 2327.0, 1068.0 + 0.5, 35000.0, 34.5, 2409.915, 1094.4 + 0.5, 35000.0, 35.0, 2492.833, 1120.09 + 0.5, 35000.0, 35.5, 2575.773, 1145.39 + 0.5, 35000.0, 36.0, 2658.755, 1170.65 + 0.5, 35000.0, 36.5, 2741.799, 1196.19 + 0.5, 35000.0, 37.0, 2824.925, 1222.36 + 0.5, 35000.0, 37.5, 2908.152, 1249.48 + 0.5, 35000.0, 38.0, 2991.5, 1277.9 + 0.5, 35000.0, 38.5, 3075.386, 1304.53 + 0.5, 35000.0, 39.0, 3159.227, 1334.9 + 0.5, 35000.0, 39.5, 3242.954, 1370.09 + 0.5, 35000.0, 40.0, 3326.5, 1411.2 + 0.5, 35000.0, 40.5, 3409.371, 1470.25 + 0.5, 35000.0, 41.0, 3492.094, 1533.03 + 0.5, 35000.0, 41.5, 3574.77, 1596.27 + 0.5, 35000.0, 42.0, 3657.5, 1656.7 + 0.5, 35000.0, 42.5, 3740.773, 1705.49 + 0.5, 35000.0, 43.0, 3824.15, 1747.12 + 0.5, 35000.0, 43.5, 3907.577, 1780.55 + 0.5, 35000.0, 44.0, 3991.0, 1804.7 + 0.5, 35000.0, 44.5, 4074.23, 1802.43 + 0.5, 35000.0, 45.0, 4157.406, 1795.2 + 0.5, 35000.0, 45.5, 4240.529, 1788.4 + 0.5, 35000.0, 46.0, 4323.6, 1787.4 + 0.5, 35000.0, 46.5, 4406.562, 1816.77 + 0.5, 35000.0, 47.0, 4489.5, 1855.02 + 0.5, 35000.0, 47.5, 4572.438, 1899.86 + 0.5, 35000.0, 48.0, 4655.4, 1949.0 + 0.5, 35000.0, 48.5, 4738.413, 2000.14 + 0.5, 35000.0, 49.0, 4821.5, 2050.98 + 0.5, 35000.0, 49.5, 4904.688, 2099.23 + 0.5, 35000.0, 50.0, 4988.0, 2142.6 + 0.5, 39000.0, 0.0, 133.8738, 133.874 + 0.5, 39000.0, 22.0, 317.2, 311.8 + 0.5, 39000.0, 22.5, 378.1766, 327.61 + 0.5, 39000.0, 23.0, 438.2875, 346.834 + 0.5, 39000.0, 23.5, 497.7797, 368.917 + 0.5, 39000.0, 24.0, 556.9, 393.3 + 0.5, 39000.0, 24.5, 615.8953, 419.427 + 0.5, 39000.0, 25.0, 675.0125, 446.741 + 0.5, 39000.0, 25.5, 734.4984, 474.684 + 0.5, 39000.0, 26.0, 794.6, 502.7 + 0.5, 39000.0, 26.5, 858.0961, 525.518 + 0.5, 39000.0, 27.0, 922.8462, 547.024 + 0.5, 39000.0, 27.5, 988.6633, 567.471 + 0.5, 39000.0, 28.0, 1055.36, 587.11 + 0.5, 39000.0, 28.5, 1122.749, 606.191 + 0.5, 39000.0, 29.0, 1190.644, 624.966 + 0.5, 39000.0, 29.5, 1258.856, 643.685 + 0.5, 39000.0, 30.0, 1327.2, 662.6 + 0.5, 39000.0, 30.5, 1393.395, 685.068 + 0.5, 39000.0, 31.0, 1459.545, 707.938 + 0.5, 39000.0, 31.5, 1525.664, 731.166 + 0.5, 39000.0, 32.0, 1591.763, 754.706 + 0.5, 39000.0, 32.5, 1657.853, 778.515 + 0.5, 39000.0, 33.0, 1723.948, 802.546 + 0.5, 39000.0, 33.5, 1790.06, 826.756 + 0.5, 39000.0, 34.0, 1856.2, 851.1 + 0.5, 39000.0, 34.5, 1922.71, 876.706 + 0.5, 39000.0, 35.0, 1989.241, 902.245 + 0.5, 39000.0, 35.5, 2055.774, 927.56 + 0.5, 39000.0, 36.0, 2122.29, 952.495 + 0.5, 39000.0, 36.5, 2188.77, 976.893 + 0.5, 39000.0, 37.0, 2255.194, 1000.6 + 0.5, 39000.0, 37.5, 2321.544, 1023.45 + 0.5, 39000.0, 38.0, 2387.8, 1045.3 + 0.5, 39000.0, 38.5, 2453.64, 1060.66 + 0.5, 39000.0, 39.0, 2519.505, 1077.47 + 0.5, 39000.0, 39.5, 2585.442, 1096.74 + 0.5, 39000.0, 40.0, 2651.5, 1119.5 + 0.5, 39000.0, 40.5, 2717.964, 1150.06 + 0.5, 39000.0, 41.0, 2784.55, 1184.85 + 0.5, 39000.0, 41.5, 2851.211, 1223.59 + 0.5, 39000.0, 42.0, 2917.9, 1266.0 + 0.5, 39000.0, 42.5, 2984.266, 1316.19 + 0.5, 39000.0, 43.0, 3050.688, 1367.71 + 0.5, 39000.0, 43.5, 3117.241, 1418.53 + 0.5, 39000.0, 44.0, 3184.0, 1466.6 + 0.5, 39000.0, 44.5, 3251.877, 1507.59 + 0.5, 39000.0, 45.0, 3319.775, 1542.65 + 0.5, 39000.0, 45.5, 3387.436, 1570.66 + 0.5, 39000.0, 46.0, 3454.6, 1590.5 + 0.5, 39000.0, 46.5, 3519.516, 1588.24 + 0.5, 39000.0, 47.0, 3584.013, 1580.67 + 0.5, 39000.0, 47.5, 3648.428, 1571.76 + 0.5, 39000.0, 48.0, 3713.1, 1565.5 + 0.5, 39000.0, 48.5, 3778.366, 1565.88 + 0.5, 39000.0, 49.0, 3844.563, 1576.88 + 0.5, 39000.0, 49.5, 3912.028, 1602.49 + 0.5, 39000.0, 50.0, 3981.1, 1646.7 + 0.5, 43000.0, 0.0, 110.4591, 110.459 + 0.5, 43000.0, 22.0, 199.0, 342.0 + 0.5, 43000.0, 22.5, 240.0359, 316.037 + 0.5, 43000.0, 23.0, 280.3625, 298.15 + 0.5, 43000.0, 23.5, 320.1328, 287.337 + 0.5, 43000.0, 24.0, 359.5, 282.6 + 0.5, 43000.0, 24.5, 398.6172, 282.938 + 0.5, 43000.0, 25.0, 437.6375, 287.35 + 0.5, 43000.0, 25.5, 476.7141, 294.838 + 0.5, 43000.0, 26.0, 516.0, 304.4 + 0.5, 43000.0, 26.5, 557.0375, 305.376 + 0.5, 43000.0, 27.0, 598.67, 305.874 + 0.5, 43000.0, 27.5, 640.8125, 306.552 + 0.5, 43000.0, 28.0, 683.38, 308.065 + 0.5, 43000.0, 28.5, 726.2875, 311.07 + 0.5, 43000.0, 29.0, 769.45, 316.223 + 0.5, 43000.0, 29.5, 812.7825, 324.181 + 0.5, 43000.0, 30.0, 856.2, 335.6 + 0.5, 43000.0, 30.5, 898.5938, 359.746 + 0.5, 43000.0, 31.0, 941.0, 387.845 + 0.5, 43000.0, 31.5, 983.4313, 419.735 + 0.5, 43000.0, 32.0, 1025.9, 455.25 + 0.5, 43000.0, 32.5, 1068.419, 494.228 + 0.5, 43000.0, 33.0, 1111.0, 536.505 + 0.5, 43000.0, 33.5, 1153.656, 581.917 + 0.5, 43000.0, 34.0, 1196.4, 630.3 + 0.5, 43000.0, 34.5, 1240.248, 731.95 + 0.5, 43000.0, 35.0, 1284.112, 831.439 + 0.5, 43000.0, 35.5, 1327.911, 923.797 + 0.5, 43000.0, 36.0, 1371.56, 1004.05 + 0.5, 43000.0, 36.5, 1414.977, 1067.24 + 0.5, 43000.0, 37.0, 1458.077, 1108.39 + 0.5, 43000.0, 37.5, 1500.78, 1122.54 + 0.5, 43000.0, 38.0, 1543.0, 1104.7 + 0.5, 43000.0, 38.5, 1582.643, 985.873 + 0.5, 43000.0, 39.0, 1622.681, 858.339 + 0.5, 43000.0, 39.5, 1663.479, 731.36 + 0.5, 43000.0, 40.0, 1705.4, 614.2 + 0.5, 43000.0, 40.5, 1751.656, 532.665 + 0.5, 43000.0, 41.0, 1798.625, 472.856 + 0.5, 43000.0, 41.5, 1845.531, 437.42 + 0.5, 43000.0, 42.0, 1891.6, 429.0 + 0.5, 43000.0, 42.5, 1932.31, 477.872 + 0.5, 43000.0, 43.0, 1972.131, 548.0 + 0.5, 43000.0, 43.5, 2011.787, 630.978 + 0.5, 43000.0, 44.0, 2052.0, 718.4 + 0.5, 43000.0, 44.5, 2096.948, 786.512 + 0.5, 43000.0, 45.0, 2142.519, 848.394 + 0.5, 43000.0, 45.5, 2188.055, 901.779 + 0.5, 43000.0, 46.0, 2232.9, 944.4 + 0.5, 43000.0, 46.5, 2273.512, 956.775 + 0.5, 43000.0, 47.0, 2313.269, 960.737 + 0.5, 43000.0, 47.5, 2352.666, 960.906 + 0.5, 43000.0, 48.0, 2392.2, 961.9 + 0.5, 43000.0, 48.5, 2432.365, 968.337 + 0.5, 43000.0, 49.0, 2473.656, 984.837 + 0.5, 43000.0, 49.5, 2516.57, 1016.02 + 0.5, 43000.0, 50.0, 2561.6, 1066.5 + 0.5, 48000.0, 0.0, 86.86281, 86.8628 + 0.5, 48000.0, 22.0, 151.4, 273.0 + 0.5, 48000.0, 22.5, 186.5842, 251.468 + 0.5, 48000.0, 23.0, 220.1391, 236.909 + 0.5, 48000.0, 23.5, 252.3494, 228.421 + 0.5, 48000.0, 24.0, 283.5, 225.1 + 0.5, 48000.0, 24.5, 313.8756, 226.041 + 0.5, 48000.0, 25.0, 343.7609, 230.341 + 0.5, 48000.0, 25.5, 373.4408, 237.095 + 0.5, 48000.0, 26.0, 403.2, 245.4 + 0.5, 48000.0, 26.5, 435.7979, 245.527 + 0.5, 48000.0, 27.0, 469.1859, 244.892 + 0.5, 48000.0, 27.5, 503.2248, 244.105 + 0.5, 48000.0, 28.0, 537.775, 243.775 + 0.5, 48000.0, 28.5, 572.6971, 244.51 + 0.5, 48000.0, 29.0, 607.8516, 246.92 + 0.5, 48000.0, 29.5, 643.099, 251.614 + 0.5, 48000.0, 30.0, 678.3, 259.2 + 0.5, 48000.0, 30.5, 711.4345, 278.575 + 0.5, 48000.0, 31.0, 744.4227, 301.271 + 0.5, 48000.0, 31.5, 777.3042, 327.108 + 0.5, 48000.0, 32.0, 810.1187, 355.906 + 0.5, 48000.0, 32.5, 842.906, 387.485 + 0.5, 48000.0, 33.0, 875.7055, 421.663 + 0.5, 48000.0, 33.5, 908.5569, 458.262 + 0.5, 48000.0, 34.0, 941.5, 497.1 + 0.5, 48000.0, 34.5, 975.9323, 576.397 + 0.5, 48000.0, 35.0, 1010.406, 653.916 + 0.5, 48000.0, 35.5, 1044.832, 725.819 + 0.5, 48000.0, 36.0, 1079.12, 788.27 + 0.5, 48000.0, 36.5, 1113.18, 837.431 + 0.5, 48000.0, 37.0, 1146.924, 869.464 + 0.5, 48000.0, 37.5, 1180.26, 880.533 + 0.5, 48000.0, 38.0, 1213.1, 866.8 + 0.5, 48000.0, 38.5, 1242.932, 775.078 + 0.5, 48000.0, 39.0, 1273.344, 676.467 + 0.5, 48000.0, 39.5, 1304.784, 578.098 + 0.5, 48000.0, 40.0, 1337.7, 487.1 + 0.5, 48000.0, 40.5, 1376.26, 422.913 + 0.5, 48000.0, 41.0, 1415.706, 375.431 + 0.5, 48000.0, 41.5, 1454.999, 346.859 + 0.5, 48000.0, 42.0, 1493.1, 339.4 + 0.5, 48000.0, 42.5, 1524.208, 377.112 + 0.5, 48000.0, 43.0, 1553.95, 431.606 + 0.5, 48000.0, 43.5, 1583.192, 496.348 + 0.5, 48000.0, 44.0, 1612.8, 564.8 + 0.5, 48000.0, 44.5, 1646.854, 618.869 + 0.5, 48000.0, 45.0, 1681.719, 668.2 + 0.5, 48000.0, 45.5, 1716.974, 710.881 + 0.5, 48000.0, 46.0, 1752.2, 745.0 + 0.5, 48000.0, 46.5, 1785.667, 754.409 + 0.5, 48000.0, 47.0, 1818.787, 757.125 + 0.5, 48000.0, 47.5, 1851.664, 756.928 + 0.5, 48000.0, 48.0, 1884.4, 757.6 + 0.5, 48000.0, 48.5, 1917.098, 762.922 + 0.5, 48000.0, 49.0, 1949.862, 776.675 + 0.5, 48000.0, 49.5, 1982.795, 802.641 + 0.5, 48000.0, 50.0, 2016.0, 844.6 + 0.55, 0.0, 0.0, 615.8565, 615.857 + 0.55, 0.0, 22.0, 1351.9, 1354.7 + 0.55, 0.0, 22.5, 1608.315, 1520.54 + 0.55, 0.0, 23.0, 1861.039, 1630.16 + 0.55, 0.0, 23.5, 2111.143, 1694.85 + 0.55, 0.0, 24.0, 2359.7, 1725.9 + 0.55, 0.0, 24.5, 2607.782, 1734.58 + 0.55, 0.0, 25.0, 2856.461, 1732.19 + 0.55, 0.0, 25.5, 3106.81, 1730.0 + 0.55, 0.0, 26.0, 3359.9, 1739.3 + 0.55, 0.0, 26.5, 3627.887, 1878.18 + 0.55, 0.0, 27.0, 3901.393, 2057.23 + 0.55, 0.0, 27.5, 4179.592, 2269.41 + 0.55, 0.0, 28.0, 4461.655, 2507.7 + 0.55, 0.0, 28.5, 4746.755, 2765.06 + 0.55, 0.0, 29.0, 5034.064, 3034.49 + 0.55, 0.0, 29.5, 5322.755, 3308.94 + 0.55, 0.0, 30.0, 5612.0, 3581.4 + 0.55, 0.0, 30.5, 5891.708, 3757.29 + 0.55, 0.0, 31.0, 6171.197, 3925.46 + 0.55, 0.0, 31.5, 6450.522, 4087.24 + 0.55, 0.0, 32.0, 6729.737, 4243.92 + 0.55, 0.0, 32.5, 7008.898, 4396.83 + 0.55, 0.0, 33.0, 7288.059, 4547.27 + 0.55, 0.0, 33.5, 7567.275, 4696.56 + 0.55, 0.0, 34.0, 7846.6, 4846.0 + 0.55, 0.0, 34.5, 8126.971, 5106.93 + 0.55, 0.0, 35.0, 8407.477, 5360.15 + 0.55, 0.0, 35.5, 8688.088, 5596.52 + 0.55, 0.0, 36.0, 8968.775, 5806.84 + 0.55, 0.0, 36.5, 9249.509, 5981.97 + 0.55, 0.0, 37.0, 9530.261, 6112.74 + 0.55, 0.0, 37.5, 9811.001, 6189.97 + 0.55, 0.0, 38.0, 10091.7, 6204.5 + 0.55, 0.0, 38.5, 10372.36, 6064.91 + 0.55, 0.0, 39.0, 10652.9, 5886.95 + 0.55, 0.0, 39.5, 10933.29, 5679.7 + 0.55, 0.0, 40.0, 11213.5, 5452.3 + 0.55, 0.0, 40.5, 11493.67, 5199.48 + 0.55, 0.0, 41.0, 11773.52, 4950.47 + 0.55, 0.0, 41.5, 12052.93, 4720.13 + 0.55, 0.0, 42.0, 12331.8, 4523.3 + 0.55, 0.0, 42.5, 12608.43, 4397.66 + 0.55, 0.0, 43.0, 12884.94, 4326.12 + 0.55, 0.0, 43.5, 13161.86, 4314.43 + 0.55, 0.0, 44.0, 13439.7, 4368.3 + 0.55, 0.0, 44.5, 13721.9, 4545.55 + 0.55, 0.0, 45.0, 14004.92, 4779.0 + 0.55, 0.0, 45.5, 14288.14, 5053.55 + 0.55, 0.0, 46.0, 14570.9, 5354.1 + 0.55, 0.0, 46.5, 14849.88, 5640.62 + 0.55, 0.0, 47.0, 15128.22, 5932.92 + 0.55, 0.0, 47.5, 15406.38, 6225.85 + 0.55, 0.0, 48.0, 15684.8, 6514.3 + 0.55, 0.0, 48.5, 15963.94, 6793.13 + 0.55, 0.0, 49.0, 16244.23, 7057.21 + 0.55, 0.0, 49.5, 16526.14, 7301.41 + 0.55, 0.0, 50.0, 16810.1, 7520.6 + 0.55, 2000.0, 0.0, 576.6078, 576.608 + 0.55, 2000.0, 22.0, -3019.9, -263.7 + 0.55, 2000.0, 22.5, -3590.694, -459.233 + 0.55, 2000.0, 23.0, -4155.848, -640.077 + 0.55, 2000.0, 23.5, -4717.304, -810.082 + 0.55, 2000.0, 24.0, -5277.0, -973.1 + 0.55, 2000.0, 24.5, -5836.878, -1132.98 + 0.55, 2000.0, 25.0, -6398.877, -1293.57 + 0.55, 2000.0, 25.5, -6964.937, -1458.73 + 0.55, 2000.0, 26.0, -7537.0, -1632.3 + 0.55, 2000.0, 26.5, -8137.487, -1857.59 + 0.55, 2000.0, 27.0, -8749.026, -2101.25 + 0.55, 2000.0, 27.5, -9370.048, -2360.36 + 0.55, 2000.0, 28.0, -9998.98, -2632.01 + 0.55, 2000.0, 28.5, -10634.25, -2913.3 + 0.55, 2000.0, 29.0, -11274.29, -3201.3 + 0.55, 2000.0, 29.5, -11917.53, -3493.11 + 0.55, 2000.0, 30.0, -12562.4, -3785.8 + 0.55, 2000.0, 30.5, -13190.85, -4035.07 + 0.55, 2000.0, 31.0, -13819.36, -4283.34 + 0.55, 2000.0, 31.5, -14447.91, -4531.65 + 0.55, 2000.0, 32.0, -15076.52, -4781.03 + 0.55, 2000.0, 32.5, -15705.17, -5032.5 + 0.55, 2000.0, 33.0, -16333.87, -5287.1 + 0.55, 2000.0, 33.5, -16962.62, -5545.86 + 0.55, 2000.0, 34.0, -17591.4, -5809.8 + 0.55, 2000.0, 34.5, -18220.88, -6139.79 + 0.55, 2000.0, 35.0, -18850.33, -6471.33 + 0.55, 2000.0, 35.5, -19479.69, -6799.74 + 0.55, 2000.0, 36.0, -20108.89, -7120.37 + 0.55, 2000.0, 36.5, -20737.88, -7428.54 + 0.55, 2000.0, 37.0, -21366.59, -7719.58 + 0.55, 2000.0, 37.5, -21994.95, -7988.82 + 0.55, 2000.0, 38.0, -22622.9, -8231.6 + 0.55, 2000.0, 38.5, -23249.2, -8402.63 + 0.55, 2000.0, 39.0, -23875.56, -8558.92 + 0.55, 2000.0, 39.5, -24502.2, -8704.82 + 0.55, 2000.0, 40.0, -25129.3, -8844.7 + 0.55, 2000.0, 40.5, -25758.07, -8972.08 + 0.55, 2000.0, 41.0, -26387.29, -9106.49 + 0.55, 2000.0, 41.5, -27016.77, -9256.6 + 0.55, 2000.0, 42.0, -27646.3, -9431.1 + 0.55, 2000.0, 42.5, -28274.68, -9667.78 + 0.55, 2000.0, 43.0, -28903.1, -9934.59 + 0.55, 2000.0, 43.5, -29531.74, -10228.6 + 0.55, 2000.0, 44.0, -30160.8, -10546.8 + 0.55, 2000.0, 44.5, -30792.35, -10889.2 + 0.55, 2000.0, 45.0, -31423.95, -11248.7 + 0.55, 2000.0, 45.5, -32055.02, -11621.3 + 0.55, 2000.0, 46.0, -32685.0, -12002.9 + 0.55, 2000.0, 46.5, -33310.3, -12379.4 + 0.55, 2000.0, 47.0, -33934.58, -12760.6 + 0.55, 2000.0, 47.5, -34558.5, -13146.6 + 0.55, 2000.0, 48.0, -35182.7, -13537.2 + 0.55, 2000.0, 48.5, -35807.82, -13932.3 + 0.55, 2000.0, 49.0, -36434.52, -14331.9 + 0.55, 2000.0, 49.5, -37063.43, -14735.9 + 0.55, 2000.0, 50.0, -37695.2, -15144.1 + 0.55, 5000.0, 0.0, 521.4643, 521.464 + 0.55, 5000.0, 22.0, 3144.9, 1828.8 + 0.55, 5000.0, 22.5, 3742.593, 2037.94 + 0.55, 5000.0, 23.0, 4333.844, 2240.93 + 0.55, 5000.0, 23.5, 4920.748, 2439.81 + 0.55, 5000.0, 24.0, 5505.4, 2636.6 + 0.55, 5000.0, 24.5, 6089.896, 2833.33 + 0.55, 5000.0, 25.0, 6676.331, 3032.02 + 0.55, 5000.0, 25.5, 7266.801, 3234.7 + 0.55, 5000.0, 26.0, 7863.4, 3443.4 + 0.55, 5000.0, 26.5, 8490.102, 3680.59 + 0.55, 5000.0, 27.0, 9128.374, 3929.01 + 0.55, 5000.0, 27.5, 9776.562, 4187.2 + 0.55, 5000.0, 28.0, 10433.01, 4453.66 + 0.55, 5000.0, 28.5, 11096.06, 4726.92 + 0.55, 5000.0, 29.0, 11764.07, 5005.5 + 0.55, 5000.0, 29.5, 12435.36, 5287.92 + 0.55, 5000.0, 30.0, 13108.3, 5572.7 + 0.55, 5000.0, 30.5, 13763.87, 5844.33 + 0.55, 5000.0, 31.0, 14419.43, 6116.69 + 0.55, 5000.0, 31.5, 15074.96, 6389.65 + 0.55, 5000.0, 32.0, 15730.47, 6663.07 + 0.55, 5000.0, 32.5, 16385.95, 6936.79 + 0.55, 5000.0, 33.0, 17041.4, 7210.69 + 0.55, 5000.0, 33.5, 17696.82, 7484.6 + 0.55, 5000.0, 34.0, 18352.2, 7758.4 + 0.55, 5000.0, 34.5, 19007.4, 8034.19 + 0.55, 5000.0, 35.0, 19662.57, 8309.37 + 0.55, 5000.0, 35.5, 20317.72, 8583.57 + 0.55, 5000.0, 36.0, 20972.87, 8856.43 + 0.55, 5000.0, 36.5, 21628.02, 9127.61 + 0.55, 5000.0, 37.0, 22283.18, 9396.73 + 0.55, 5000.0, 37.5, 22938.37, 9663.45 + 0.55, 5000.0, 38.0, 23593.6, 9927.4 + 0.55, 5000.0, 38.5, 24248.98, 10187.2 + 0.55, 5000.0, 39.0, 24904.36, 10444.1 + 0.55, 5000.0, 39.5, 25559.74, 10697.9 + 0.55, 5000.0, 40.0, 26215.1, 10948.4 + 0.55, 5000.0, 40.5, 26870.26, 11189.4 + 0.55, 5000.0, 41.0, 27525.44, 11429.3 + 0.55, 5000.0, 41.5, 28180.71, 11670.7 + 0.55, 5000.0, 42.0, 28836.1, 11915.7 + 0.55, 5000.0, 42.5, 29491.55, 12170.7 + 0.55, 5000.0, 43.0, 30147.29, 12432.6 + 0.55, 5000.0, 43.5, 30803.44, 12702.1 + 0.55, 5000.0, 44.0, 31460.1, 12979.9 + 0.55, 5000.0, 44.5, 32119.08, 13270.6 + 0.55, 5000.0, 45.0, 32778.11, 13569.7 + 0.55, 5000.0, 45.5, 33436.61, 13876.5 + 0.55, 5000.0, 46.0, 34094.0, 14190.5 + 0.55, 5000.0, 46.5, 34746.69, 14512.8 + 0.55, 5000.0, 47.0, 35398.34, 14840.0 + 0.55, 5000.0, 47.5, 36049.56, 15170.6 + 0.55, 5000.0, 48.0, 36701.0, 15503.2 + 0.55, 5000.0, 48.5, 37353.28, 15836.3 + 0.55, 5000.0, 49.0, 38007.04, 16168.5 + 0.55, 5000.0, 49.5, 38662.9, 16498.2 + 0.55, 5000.0, 50.0, 39321.5, 16824.1 + 0.55, 10000.0, 0.0, 438.8868, 438.887 + 0.55, 10000.0, 22.0, 856.3, 922.0 + 0.55, 10000.0, 22.5, 1018.801, 983.793 + 0.55, 10000.0, 23.0, 1179.63, 1045.67 + 0.55, 10000.0, 23.5, 1339.344, 1107.73 + 0.55, 10000.0, 24.0, 1498.5, 1170.1 + 0.55, 10000.0, 24.5, 1657.656, 1232.88 + 0.55, 10000.0, 25.0, 1817.37, 1296.18 + 0.55, 10000.0, 25.5, 1978.199, 1360.12 + 0.55, 10000.0, 26.0, 2140.7, 1424.8 + 0.55, 10000.0, 26.5, 2311.282, 1491.5 + 0.55, 10000.0, 27.0, 2484.986, 1559.23 + 0.55, 10000.0, 27.5, 2661.365, 1627.91 + 0.55, 10000.0, 28.0, 2839.975, 1697.43 + 0.55, 10000.0, 28.5, 3020.369, 1767.73 + 0.55, 10000.0, 29.0, 3202.102, 1838.7 + 0.55, 10000.0, 29.5, 3384.727, 1910.25 + 0.55, 10000.0, 30.0, 3567.8, 1982.3 + 0.55, 10000.0, 30.5, 3746.197, 2054.26 + 0.55, 10000.0, 31.0, 3924.595, 2126.58 + 0.55, 10000.0, 31.5, 4102.994, 2199.22 + 0.55, 10000.0, 32.0, 4281.394, 2272.16 + 0.55, 10000.0, 32.5, 4459.795, 2345.33 + 0.55, 10000.0, 33.0, 4638.196, 2418.71 + 0.55, 10000.0, 33.5, 4816.598, 2492.24 + 0.55, 10000.0, 34.0, 4995.0, 2565.9 + 0.55, 10000.0, 34.5, 5173.407, 2638.95 + 0.55, 10000.0, 35.0, 5351.812, 2712.1 + 0.55, 10000.0, 35.5, 5530.217, 2785.38 + 0.55, 10000.0, 36.0, 5708.62, 2858.81 + 0.55, 10000.0, 36.5, 5887.02, 2932.41 + 0.55, 10000.0, 37.0, 6065.417, 3006.21 + 0.55, 10000.0, 37.5, 6243.811, 3080.23 + 0.55, 10000.0, 38.0, 6422.2, 3154.5 + 0.55, 10000.0, 38.5, 6600.572, 3229.05 + 0.55, 10000.0, 39.0, 6778.945, 3303.88 + 0.55, 10000.0, 39.5, 6957.321, 3379.03 + 0.55, 10000.0, 40.0, 7135.7, 3454.5 + 0.55, 10000.0, 40.5, 7314.095, 3530.47 + 0.55, 10000.0, 41.0, 7492.494, 3606.75 + 0.55, 10000.0, 41.5, 7670.896, 3683.31 + 0.55, 10000.0, 42.0, 7849.3, 3760.1 + 0.55, 10000.0, 42.5, 8027.563, 3836.92 + 0.55, 10000.0, 43.0, 8205.881, 3913.97 + 0.55, 10000.0, 43.5, 8384.309, 3991.29 + 0.55, 10000.0, 44.0, 8562.9, 4068.9 + 0.55, 10000.0, 44.5, 8742.261, 4147.15 + 0.55, 10000.0, 45.0, 8921.675, 4225.64 + 0.55, 10000.0, 45.5, 9100.977, 4304.28 + 0.55, 10000.0, 46.0, 9280.0, 4383.0 + 0.55, 10000.0, 46.5, 9457.748, 4461.24 + 0.55, 10000.0, 47.0, 9635.219, 4539.56 + 0.55, 10000.0, 47.5, 9812.58, 4618.04 + 0.55, 10000.0, 48.0, 9990.0, 4696.8 + 0.55, 10000.0, 48.5, 10167.64, 4775.92 + 0.55, 10000.0, 49.0, 10345.68, 4855.49 + 0.55, 10000.0, 49.5, 10524.28, 4935.62 + 0.55, 10000.0, 50.0, 10703.6, 5016.4 + 0.55, 15000.0, 0.0, 366.9943, 366.994 + 0.55, 15000.0, 22.0, 772.6, 792.1 + 0.55, 15000.0, 22.5, 919.2096, 846.839 + 0.55, 15000.0, 23.0, 1064.311, 901.6 + 0.55, 15000.0, 23.5, 1208.407, 956.486 + 0.55, 15000.0, 24.0, 1352.0, 1011.6 + 0.55, 15000.0, 24.5, 1495.593, 1067.05 + 0.55, 15000.0, 25.0, 1639.689, 1122.92 + 0.55, 15000.0, 25.5, 1784.79, 1179.34 + 0.55, 15000.0, 26.0, 1931.4, 1236.4 + 0.55, 15000.0, 26.5, 2085.298, 1295.21 + 0.55, 15000.0, 27.0, 2242.011, 1354.91 + 0.55, 15000.0, 27.5, 2401.137, 1415.46 + 0.55, 15000.0, 28.0, 2562.275, 1476.77 + 0.55, 15000.0, 28.5, 2725.022, 1538.78 + 0.55, 15000.0, 29.0, 2888.977, 1601.42 + 0.55, 15000.0, 29.5, 3053.737, 1664.61 + 0.55, 15000.0, 30.0, 3218.9, 1728.3 + 0.55, 15000.0, 30.5, 3379.847, 1792.08 + 0.55, 15000.0, 31.0, 3540.795, 1856.25 + 0.55, 15000.0, 31.5, 3701.744, 1920.77 + 0.55, 15000.0, 32.0, 3862.694, 1985.59 + 0.55, 15000.0, 32.5, 4023.645, 2050.68 + 0.55, 15000.0, 33.0, 4184.596, 2116.0 + 0.55, 15000.0, 33.5, 4345.548, 2181.52 + 0.55, 15000.0, 34.0, 4506.5, 2247.2 + 0.55, 15000.0, 34.5, 4667.45, 2312.34 + 0.55, 15000.0, 35.0, 4828.4, 2377.62 + 0.55, 15000.0, 35.5, 4989.35, 2443.08 + 0.55, 15000.0, 36.0, 5150.3, 2508.72 + 0.55, 15000.0, 36.5, 5311.25, 2574.58 + 0.55, 15000.0, 37.0, 5472.2, 2640.68 + 0.55, 15000.0, 37.5, 5633.15, 2707.05 + 0.55, 15000.0, 38.0, 5794.1, 2773.7 + 0.55, 15000.0, 38.5, 5955.05, 2840.83 + 0.55, 15000.0, 39.0, 6116.0, 2908.22 + 0.55, 15000.0, 39.5, 6276.95, 2975.84 + 0.55, 15000.0, 40.0, 6437.9, 3043.7 + 0.55, 15000.0, 40.5, 6598.85, 3111.74 + 0.55, 15000.0, 41.0, 6759.8, 3180.0 + 0.55, 15000.0, 41.5, 6920.75, 3248.49 + 0.55, 15000.0, 42.0, 7081.7, 3317.2 + 0.55, 15000.0, 42.5, 7242.525, 3386.13 + 0.55, 15000.0, 43.0, 7403.4, 3455.3 + 0.55, 15000.0, 43.5, 7564.375, 3524.72 + 0.55, 15000.0, 44.0, 7725.5, 3594.4 + 0.55, 15000.0, 44.5, 7887.325, 3664.46 + 0.55, 15000.0, 45.0, 8049.2, 3734.76 + 0.55, 15000.0, 45.5, 8210.975, 3805.25 + 0.55, 15000.0, 46.0, 8372.5, 3875.9 + 0.55, 15000.0, 46.5, 8532.875, 3946.33 + 0.55, 15000.0, 47.0, 8693.0, 4016.98 + 0.55, 15000.0, 47.5, 8853.025, 4087.97 + 0.55, 15000.0, 48.0, 9013.1, 4159.4 + 0.55, 15000.0, 48.5, 9173.375, 4231.37 + 0.55, 15000.0, 49.0, 9334.0, 4303.99 + 0.55, 15000.0, 49.5, 9495.125, 4377.37 + 0.55, 15000.0, 50.0, 9656.9, 4451.6 + 0.55, 20000.0, 0.0, 304.7411, 304.741 + 0.55, 20000.0, 22.0, 784.9, 709.3 + 0.55, 20000.0, 22.5, 933.7998, 764.007 + 0.55, 20000.0, 23.0, 1081.177, 818.808 + 0.55, 20000.0, 23.5, 1227.54, 873.805 + 0.55, 20000.0, 24.0, 1373.4, 929.1 + 0.55, 20000.0, 24.5, 1519.266, 984.795 + 0.55, 20000.0, 25.0, 1665.648, 1040.99 + 0.55, 20000.0, 25.5, 1813.056, 1097.79 + 0.55, 20000.0, 26.0, 1962.0, 1155.3 + 0.55, 20000.0, 26.5, 2118.346, 1214.66 + 0.55, 20000.0, 27.0, 2277.552, 1274.99 + 0.55, 20000.0, 27.5, 2439.212, 1336.21 + 0.55, 20000.0, 28.0, 2602.915, 1398.25 + 0.55, 20000.0, 28.5, 2768.254, 1461.02 + 0.55, 20000.0, 29.0, 2934.82, 1524.46 + 0.55, 20000.0, 29.5, 3102.205, 1588.48 + 0.55, 20000.0, 30.0, 3270.0, 1653.0 + 0.55, 20000.0, 30.5, 3433.511, 1717.41 + 0.55, 20000.0, 31.0, 3597.023, 1782.22 + 0.55, 20000.0, 31.5, 3760.537, 1847.41 + 0.55, 20000.0, 32.0, 3924.05, 1912.94 + 0.55, 20000.0, 32.5, 4087.563, 1978.81 + 0.55, 20000.0, 33.0, 4251.077, 2044.97 + 0.55, 20000.0, 33.5, 4414.589, 2111.41 + 0.55, 20000.0, 34.0, 4578.1, 2178.1 + 0.55, 20000.0, 34.5, 4741.603, 2244.58 + 0.55, 20000.0, 35.0, 4905.105, 2311.29 + 0.55, 20000.0, 35.5, 5068.605, 2378.26 + 0.55, 20000.0, 36.0, 5232.105, 2445.51 + 0.55, 20000.0, 36.5, 5395.604, 2513.03 + 0.55, 20000.0, 37.0, 5559.103, 2580.87 + 0.55, 20000.0, 37.5, 5722.601, 2649.02 + 0.55, 20000.0, 38.0, 5886.1, 2717.5 + 0.55, 20000.0, 38.5, 6049.6, 2786.45 + 0.55, 20000.0, 39.0, 6213.1, 2855.7 + 0.55, 20000.0, 39.5, 6376.6, 2925.26 + 0.55, 20000.0, 40.0, 6540.1, 2995.1 + 0.55, 20000.0, 40.5, 6703.6, 3065.05 + 0.55, 20000.0, 41.0, 6867.1, 3135.34 + 0.55, 20000.0, 41.5, 7030.6, 3206.03 + 0.55, 20000.0, 42.0, 7194.1, 3277.2 + 0.55, 20000.0, 42.5, 7357.471, 3348.99 + 0.55, 20000.0, 43.0, 7520.894, 3421.34 + 0.55, 20000.0, 43.5, 7684.42, 3494.27 + 0.55, 20000.0, 44.0, 7848.1, 3567.8 + 0.55, 20000.0, 44.5, 8012.498, 3641.95 + 0.55, 20000.0, 45.0, 8176.95, 3716.76 + 0.55, 20000.0, 45.5, 8341.302, 3792.26 + 0.55, 20000.0, 46.0, 8505.4, 3868.5 + 0.55, 20000.0, 46.5, 8668.33, 3944.94 + 0.55, 20000.0, 47.0, 8831.006, 4022.4 + 0.55, 20000.0, 47.5, 8993.579, 4101.13 + 0.55, 20000.0, 48.0, 9156.2, 4181.4 + 0.55, 20000.0, 48.5, 9319.021, 4263.45 + 0.55, 20000.0, 49.0, 9482.194, 4347.55 + 0.55, 20000.0, 49.5, 9645.87, 4433.95 + 0.55, 20000.0, 50.0, 9810.2, 4522.9 + 0.55, 25000.0, 0.0, 251.1415, 251.142 + 0.55, 25000.0, 22.0, 633.7, 580.7 + 0.55, 25000.0, 22.5, 753.9525, 623.962 + 0.55, 25000.0, 23.0, 872.9797, 667.352 + 0.55, 25000.0, 23.5, 991.192, 710.94 + 0.55, 25000.0, 24.0, 1109.0, 754.8 + 0.55, 25000.0, 24.5, 1226.814, 799.004 + 0.55, 25000.0, 25.0, 1345.045, 843.623 + 0.55, 25000.0, 25.5, 1464.104, 888.731 + 0.55, 25000.0, 26.0, 1584.4, 934.4 + 0.55, 25000.0, 26.5, 1710.661, 981.503 + 0.55, 25000.0, 27.0, 1839.227, 1029.36 + 0.55, 25000.0, 27.5, 1969.77, 1077.9 + 0.55, 25000.0, 28.0, 2101.96, 1127.06 + 0.55, 25000.0, 28.5, 2235.467, 1176.77 + 0.55, 25000.0, 29.0, 2369.962, 1226.98 + 0.55, 25000.0, 29.5, 2505.117, 1277.61 + 0.55, 25000.0, 30.0, 2640.6, 1328.6 + 0.55, 25000.0, 30.5, 2772.623, 1379.36 + 0.55, 25000.0, 31.0, 2904.646, 1430.4 + 0.55, 25000.0, 31.5, 3036.67, 1481.71 + 0.55, 25000.0, 32.0, 3168.694, 1533.26 + 0.55, 25000.0, 32.5, 3300.719, 1585.06 + 0.55, 25000.0, 33.0, 3432.745, 1637.07 + 0.55, 25000.0, 33.5, 3564.772, 1689.29 + 0.55, 25000.0, 34.0, 3696.8, 1741.7 + 0.55, 25000.0, 34.5, 3828.838, 1793.62 + 0.55, 25000.0, 35.0, 3960.877, 1845.76 + 0.55, 25000.0, 35.5, 4092.916, 1898.17 + 0.55, 25000.0, 36.0, 4224.955, 1950.92 + 0.55, 25000.0, 36.5, 4356.994, 2004.03 + 0.55, 25000.0, 37.0, 4489.031, 2057.56 + 0.55, 25000.0, 37.5, 4621.067, 2111.57 + 0.55, 25000.0, 38.0, 4753.1, 2166.1 + 0.55, 25000.0, 38.5, 4885.121, 2221.87 + 0.55, 25000.0, 39.0, 5017.144, 2277.91 + 0.55, 25000.0, 39.5, 5149.17, 2334.12 + 0.55, 25000.0, 40.0, 5281.2, 2390.4 + 0.55, 25000.0, 40.5, 5413.252, 2446.13 + 0.55, 25000.0, 41.0, 5545.306, 2501.93 + 0.55, 25000.0, 41.5, 5677.357, 2557.92 + 0.55, 25000.0, 42.0, 5809.4, 2614.2 + 0.55, 25000.0, 42.5, 5941.298, 2671.05 + 0.55, 25000.0, 43.0, 6073.231, 2728.34 + 0.55, 25000.0, 43.5, 6205.249, 2786.11 + 0.55, 25000.0, 44.0, 6337.4, 2844.4 + 0.55, 25000.0, 44.5, 6470.181, 2903.32 + 0.55, 25000.0, 45.0, 6603.013, 2962.81 + 0.55, 25000.0, 45.5, 6735.763, 3022.86 + 0.55, 25000.0, 46.0, 6868.3, 3083.5 + 0.55, 25000.0, 46.5, 6999.845, 3144.17 + 0.55, 25000.0, 47.0, 7131.175, 3205.66 + 0.55, 25000.0, 47.5, 7262.417, 3268.2 + 0.55, 25000.0, 48.0, 7393.7, 3332.0 + 0.55, 25000.0, 48.5, 7525.152, 3397.3 + 0.55, 25000.0, 49.0, 7656.9, 3464.34 + 0.55, 25000.0, 49.5, 7789.073, 3533.33 + 0.55, 25000.0, 50.0, 7921.8, 3604.5 + 0.55, 30000.0, 0.0, 205.2788, 205.279 + 0.55, 30000.0, 22.0, 503.4, 473.4 + 0.55, 30000.0, 22.5, 598.9484, 506.898 + 0.55, 30000.0, 23.0, 693.5125, 540.603 + 0.55, 30000.0, 23.5, 787.4203, 574.557 + 0.55, 30000.0, 24.0, 881.0, 608.8 + 0.55, 30000.0, 24.5, 974.5797, 643.375 + 0.55, 30000.0, 25.0, 1068.487, 678.322 + 0.55, 30000.0, 25.5, 1163.052, 713.683 + 0.55, 30000.0, 26.0, 1258.6, 749.5 + 0.55, 30000.0, 26.5, 1358.908, 786.328 + 0.55, 30000.0, 27.0, 1461.053, 823.723 + 0.55, 30000.0, 27.5, 1564.773, 861.639 + 0.55, 30000.0, 28.0, 1669.805, 900.03 + 0.55, 30000.0, 28.5, 1775.887, 938.848 + 0.55, 30000.0, 29.0, 1882.755, 978.047 + 0.55, 30000.0, 29.5, 1990.147, 1017.58 + 0.55, 30000.0, 30.0, 2097.8, 1057.4 + 0.55, 30000.0, 30.5, 2202.691, 1097.16 + 0.55, 30000.0, 31.0, 2307.58, 1137.14 + 0.55, 30000.0, 31.5, 2412.469, 1177.32 + 0.55, 30000.0, 32.0, 2517.356, 1217.69 + 0.55, 30000.0, 32.5, 2622.243, 1258.24 + 0.55, 30000.0, 33.0, 2727.129, 1298.93 + 0.55, 30000.0, 33.5, 2832.015, 1339.76 + 0.55, 30000.0, 34.0, 2936.9, 1380.7 + 0.55, 30000.0, 34.5, 3041.784, 1421.34 + 0.55, 30000.0, 35.0, 3146.669, 1462.1 + 0.55, 30000.0, 35.5, 3251.554, 1503.01 + 0.55, 30000.0, 36.0, 3356.44, 1544.06 + 0.55, 30000.0, 36.5, 3461.327, 1585.3 + 0.55, 30000.0, 37.0, 3566.216, 1626.74 + 0.55, 30000.0, 37.5, 3671.107, 1668.4 + 0.55, 30000.0, 38.0, 3776.0, 1710.3 + 0.55, 30000.0, 38.5, 3880.899, 1752.6 + 0.55, 30000.0, 39.0, 3985.798, 1795.11 + 0.55, 30000.0, 39.5, 4090.699, 1837.82 + 0.55, 30000.0, 40.0, 4195.6, 1880.7 + 0.55, 30000.0, 40.5, 4300.504, 1923.6 + 0.55, 30000.0, 41.0, 4405.406, 1966.72 + 0.55, 30000.0, 41.5, 4510.305, 2010.1 + 0.55, 30000.0, 42.0, 4615.2, 2053.8 + 0.55, 30000.0, 42.5, 4719.998, 2097.99 + 0.55, 30000.0, 43.0, 4824.825, 2142.54 + 0.55, 30000.0, 43.5, 4929.714, 2187.44 + 0.55, 30000.0, 44.0, 5034.7, 2232.7 + 0.55, 30000.0, 44.5, 5140.145, 2278.24 + 0.55, 30000.0, 45.0, 5245.625, 2324.15 + 0.55, 30000.0, 45.5, 5351.042, 2370.46 + 0.55, 30000.0, 46.0, 5456.3, 2417.2 + 0.55, 30000.0, 46.5, 5560.817, 2463.97 + 0.55, 30000.0, 47.0, 5665.175, 2511.38 + 0.55, 30000.0, 47.5, 5769.47, 2559.63 + 0.55, 30000.0, 48.0, 5873.8, 2608.9 + 0.55, 30000.0, 48.5, 5978.261, 2659.39 + 0.55, 30000.0, 49.0, 6082.95, 2711.29 + 0.55, 30000.0, 49.5, 6187.964, 2764.8 + 0.55, 30000.0, 50.0, 6293.4, 2820.1 + 0.55, 35000.0, 0.0, 166.2992, 166.299 + 0.55, 35000.0, 22.0, 388.0, 392.5 + 0.55, 35000.0, 22.5, 461.7723, 416.083 + 0.55, 35000.0, 23.0, 534.7594, 440.839 + 0.55, 35000.0, 23.5, 607.2168, 466.626 + 0.55, 35000.0, 24.0, 679.4, 493.3 + 0.55, 35000.0, 24.5, 751.5645, 520.718 + 0.55, 35000.0, 25.0, 823.9656, 548.736 + 0.55, 35000.0, 25.5, 896.859, 577.211 + 0.55, 35000.0, 26.0, 970.5, 606.0 + 0.55, 35000.0, 26.5, 1047.805, 633.674 + 0.55, 35000.0, 27.0, 1126.52, 661.302 + 0.55, 35000.0, 27.5, 1206.445, 688.96 + 0.55, 35000.0, 28.0, 1287.38, 716.725 + 0.55, 35000.0, 28.5, 1369.123, 744.675 + 0.55, 35000.0, 29.0, 1451.475, 772.886 + 0.55, 35000.0, 29.5, 1534.234, 801.435 + 0.55, 35000.0, 30.0, 1617.2, 830.4 + 0.55, 35000.0, 30.5, 1698.076, 861.586 + 0.55, 35000.0, 31.0, 1778.957, 893.176 + 0.55, 35000.0, 31.5, 1859.842, 925.083 + 0.55, 35000.0, 32.0, 1940.731, 957.219 + 0.55, 35000.0, 32.5, 2021.622, 989.496 + 0.55, 35000.0, 33.0, 2102.515, 1021.83 + 0.55, 35000.0, 33.5, 2183.408, 1054.12 + 0.55, 35000.0, 34.0, 2264.3, 1086.3 + 0.55, 35000.0, 34.5, 2345.139, 1116.41 + 0.55, 35000.0, 35.0, 2425.98, 1146.4 + 0.55, 35000.0, 35.5, 2506.827, 1176.35 + 0.55, 35000.0, 36.0, 2587.685, 1206.37 + 0.55, 35000.0, 36.5, 2668.557, 1236.53 + 0.55, 35000.0, 37.0, 2749.448, 1266.93 + 0.55, 35000.0, 37.5, 2830.361, 1297.66 + 0.55, 35000.0, 38.0, 2911.3, 1328.8 + 0.55, 35000.0, 38.5, 2992.361, 1359.5 + 0.55, 35000.0, 39.0, 3073.409, 1391.28 + 0.55, 35000.0, 39.5, 3154.428, 1424.45 + 0.55, 35000.0, 40.0, 3235.4, 1459.3 + 0.55, 35000.0, 40.5, 3316.198, 1499.0 + 0.55, 35000.0, 41.0, 3396.963, 1539.83 + 0.55, 35000.0, 41.5, 3477.72, 1580.95 + 0.55, 35000.0, 42.0, 3558.5, 1621.5 + 0.55, 35000.0, 42.5, 3639.4, 1659.45 + 0.55, 35000.0, 43.0, 3720.35, 1695.62 + 0.55, 35000.0, 43.5, 3801.35, 1729.63 + 0.55, 35000.0, 44.0, 3882.4, 1761.1 + 0.55, 35000.0, 44.5, 3963.637, 1784.54 + 0.55, 35000.0, 45.0, 4044.869, 1806.75 + 0.55, 35000.0, 45.5, 4126.041, 1829.41 + 0.55, 35000.0, 46.0, 4207.1, 1854.2 + 0.55, 35000.0, 46.5, 4287.685, 1888.7 + 0.55, 35000.0, 47.0, 4368.169, 1926.32 + 0.55, 35000.0, 47.5, 4448.618, 1966.38 + 0.55, 35000.0, 48.0, 4529.1, 2008.2 + 0.55, 35000.0, 48.5, 4609.682, 2051.09 + 0.55, 35000.0, 49.0, 4690.431, 2094.38 + 0.55, 35000.0, 49.5, 4771.415, 2137.38 + 0.55, 35000.0, 50.0, 4852.7, 2179.4 + 0.55, 39000.0, 0.0, 137.9303, 137.93 + 0.55, 39000.0, 22.0, 310.7, 338.2 + 0.55, 39000.0, 22.5, 369.9068, 357.696 + 0.55, 39000.0, 23.0, 428.4328, 378.123 + 0.55, 39000.0, 23.5, 486.4924, 399.365 + 0.55, 39000.0, 24.0, 544.3, 421.3 + 0.55, 39000.0, 24.5, 602.0701, 443.81 + 0.55, 39000.0, 25.0, 660.0172, 466.777 + 0.55, 39000.0, 25.5, 718.3557, 490.079 + 0.55, 39000.0, 26.0, 777.3, 513.6 + 0.55, 39000.0, 26.5, 839.2986, 536.307 + 0.55, 39000.0, 27.0, 902.4597, 558.941 + 0.55, 39000.0, 27.5, 966.6146, 581.54 + 0.55, 39000.0, 28.0, 1031.595, 604.14 + 0.55, 39000.0, 28.5, 1097.232, 626.779 + 0.55, 39000.0, 29.0, 1163.358, 649.494 + 0.55, 39000.0, 29.5, 1229.803, 672.322 + 0.55, 39000.0, 30.0, 1296.4, 695.3 + 0.55, 39000.0, 30.5, 1361.173, 718.975 + 0.55, 39000.0, 31.0, 1425.933, 742.827 + 0.55, 39000.0, 31.5, 1490.682, 766.843 + 0.55, 39000.0, 32.0, 1555.425, 791.012 + 0.55, 39000.0, 32.5, 1620.165, 815.324 + 0.55, 39000.0, 33.0, 1684.905, 839.767 + 0.55, 39000.0, 33.5, 1749.649, 864.329 + 0.55, 39000.0, 34.0, 1814.4, 889.0 + 0.55, 39000.0, 34.5, 1879.253, 914.014 + 0.55, 39000.0, 35.0, 1944.111, 939.091 + 0.55, 39000.0, 35.5, 2008.97, 964.194 + 0.55, 39000.0, 36.0, 2073.825, 989.29 + 0.55, 39000.0, 36.5, 2138.671, 1014.34 + 0.55, 39000.0, 37.0, 2203.502, 1039.32 + 0.55, 39000.0, 37.5, 2268.313, 1064.18 + 0.55, 39000.0, 38.0, 2333.1, 1088.9 + 0.55, 39000.0, 38.5, 2397.778, 1112.09 + 0.55, 39000.0, 39.0, 2462.463, 1135.76 + 0.55, 39000.0, 39.5, 2527.166, 1160.17 + 0.55, 39000.0, 40.0, 2591.9, 1185.6 + 0.55, 39000.0, 40.5, 2656.737, 1213.09 + 0.55, 39000.0, 41.0, 2721.606, 1241.8 + 0.55, 39000.0, 41.5, 2786.498, 1271.69 + 0.55, 39000.0, 42.0, 2851.4, 1302.7 + 0.55, 39000.0, 42.5, 2916.197, 1336.03 + 0.55, 39000.0, 43.0, 2981.025, 1369.89 + 0.55, 39000.0, 43.5, 3045.916, 1403.73 + 0.55, 39000.0, 44.0, 3110.9, 1437.0 + 0.55, 39000.0, 44.5, 3176.357, 1468.59 + 0.55, 39000.0, 45.0, 3241.831, 1498.74 + 0.55, 39000.0, 45.5, 3307.215, 1527.12 + 0.55, 39000.0, 46.0, 3372.4, 1553.4 + 0.55, 39000.0, 46.5, 3436.685, 1573.35 + 0.55, 39000.0, 47.0, 3500.794, 1592.11 + 0.55, 39000.0, 47.5, 3564.855, 1610.91 + 0.55, 39000.0, 48.0, 3629.0, 1631.0 + 0.55, 39000.0, 48.5, 3693.357, 1653.61 + 0.55, 39000.0, 49.0, 3758.056, 1679.97 + 0.55, 39000.0, 49.5, 3823.227, 1711.32 + 0.55, 39000.0, 50.0, 3889.0, 1748.9 + 0.55, 43000.0, 0.0, 113.8061, 113.806 + 0.55, 43000.0, 22.0, 222.6, 333.3 + 0.55, 43000.0, 22.5, 266.508, 327.087 + 0.55, 43000.0, 23.0, 309.8234, 325.469 + 0.55, 43000.0, 23.5, 352.7021, 327.891 + 0.55, 43000.0, 24.0, 395.3, 333.8 + 0.55, 43000.0, 24.5, 437.7729, 342.64 + 0.55, 43000.0, 25.0, 480.2766, 353.856 + 0.55, 43000.0, 25.5, 522.967, 366.895 + 0.55, 43000.0, 26.0, 566.0, 381.2 + 0.55, 43000.0, 26.5, 611.0586, 391.054 + 0.55, 43000.0, 27.0, 656.8587, 400.771 + 0.55, 43000.0, 27.5, 703.2945, 410.681 + 0.55, 43000.0, 28.0, 750.26, 421.115 + 0.55, 43000.0, 28.5, 797.6492, 432.403 + 0.55, 43000.0, 29.0, 845.3562, 444.877 + 0.55, 43000.0, 29.5, 893.2752, 458.865 + 0.55, 43000.0, 30.0, 941.3, 474.7 + 0.55, 43000.0, 30.5, 988.1407, 497.263 + 0.55, 43000.0, 31.0, 1034.988, 521.899 + 0.55, 43000.0, 31.5, 1081.85, 548.506 + 0.55, 43000.0, 32.0, 1128.731, 576.981 + 0.55, 43000.0, 32.5, 1175.64, 607.221 + 0.55, 43000.0, 33.0, 1222.584, 639.123 + 0.55, 43000.0, 33.5, 1269.568, 672.583 + 0.55, 43000.0, 34.0, 1316.6, 707.5 + 0.55, 43000.0, 34.5, 1364.225, 769.699 + 0.55, 43000.0, 35.0, 1411.861, 830.678 + 0.55, 43000.0, 35.5, 1459.462, 887.866 + 0.55, 43000.0, 36.0, 1506.985, 938.69 + 0.55, 43000.0, 36.5, 1554.385, 980.578 + 0.55, 43000.0, 37.0, 1601.617, 1010.96 + 0.55, 43000.0, 37.5, 1648.637, 1027.26 + 0.55, 43000.0, 38.0, 1695.4, 1026.9 + 0.55, 43000.0, 38.5, 1740.794, 973.71 + 0.55, 43000.0, 39.0, 1786.397, 916.148 + 0.55, 43000.0, 39.5, 1832.401, 859.113 + 0.55, 43000.0, 40.0, 1879.0, 807.5 + 0.55, 43000.0, 40.5, 1927.892, 774.685 + 0.55, 43000.0, 41.0, 1977.163, 753.694 + 0.55, 43000.0, 41.5, 2026.402, 746.03 + 0.55, 43000.0, 42.0, 2075.2, 753.2 + 0.55, 43000.0, 42.5, 2121.156, 792.02 + 0.55, 43000.0, 43.0, 2166.65, 842.556 + 0.55, 43000.0, 43.5, 2212.069, 900.19 + 0.55, 43000.0, 44.0, 2257.8, 960.3 + 0.55, 43000.0, 44.5, 2306.118, 1009.77 + 0.55, 43000.0, 45.0, 2354.769, 1055.87 + 0.55, 43000.0, 45.5, 2403.385, 1097.39 + 0.55, 43000.0, 46.0, 2451.6, 1133.1 + 0.55, 43000.0, 46.5, 2497.425, 1152.71 + 0.55, 43000.0, 47.0, 2542.762, 1167.69 + 0.55, 43000.0, 47.5, 2587.894, 1180.46 + 0.55, 43000.0, 48.0, 2633.1, 1193.4 + 0.55, 43000.0, 48.5, 2678.662, 1208.93 + 0.55, 43000.0, 49.0, 2724.862, 1229.46 + 0.55, 43000.0, 49.5, 2771.981, 1257.38 + 0.55, 43000.0, 50.0, 2820.3, 1295.1 + 0.55, 48000.0, 0.0, 89.49484, 89.4948 + 0.55, 48000.0, 22.0, 172.5, 264.5 + 0.55, 48000.0, 22.5, 208.5977, 258.991 + 0.55, 48000.0, 23.0, 243.6563, 257.437 + 0.55, 48000.0, 23.5, 277.8867, 259.341 + 0.55, 48000.0, 24.0, 311.5, 264.2 + 0.55, 48000.0, 24.5, 344.707, 271.516 + 0.55, 48000.0, 25.0, 377.7188, 280.787 + 0.55, 48000.0, 25.5, 410.7461, 291.516 + 0.55, 48000.0, 26.0, 444.0, 303.2 + 0.55, 48000.0, 26.5, 479.6396, 310.617 + 0.55, 48000.0, 27.0, 516.0391, 317.72 + 0.55, 48000.0, 27.5, 553.0752, 324.82 + 0.55, 48000.0, 28.0, 590.625, 332.225 + 0.55, 48000.0, 28.5, 628.5654, 340.246 + 0.55, 48000.0, 29.0, 666.7734, 349.192 + 0.55, 48000.0, 29.5, 705.126, 359.374 + 0.55, 48000.0, 30.0, 743.5, 371.1 + 0.55, 48000.0, 30.5, 780.2549, 389.08 + 0.55, 48000.0, 31.0, 816.9297, 408.805 + 0.55, 48000.0, 31.5, 853.5459, 430.167 + 0.55, 48000.0, 32.0, 890.125, 453.056 + 0.55, 48000.0, 32.5, 926.6885, 477.363 + 0.55, 48000.0, 33.0, 963.2578, 502.979 + 0.55, 48000.0, 33.5, 999.8545, 529.794 + 0.55, 48000.0, 34.0, 1036.5, 557.7 + 0.55, 48000.0, 34.5, 1073.936, 606.28 + 0.55, 48000.0, 35.0, 1111.395, 653.856 + 0.55, 48000.0, 35.5, 1148.831, 698.445 + 0.55, 48000.0, 36.0, 1186.195, 738.06 + 0.55, 48000.0, 36.5, 1223.441, 770.718 + 0.55, 48000.0, 37.0, 1260.522, 794.434 + 0.55, 48000.0, 37.5, 1297.391, 807.223 + 0.55, 48000.0, 38.0, 1334.0, 807.1 + 0.55, 48000.0, 38.5, 1369.031, 766.196 + 0.55, 48000.0, 39.0, 1404.367, 721.833 + 0.55, 48000.0, 39.5, 1440.245, 677.778 + 0.55, 48000.0, 40.0, 1476.9, 637.8 + 0.55, 48000.0, 40.5, 1516.52, 611.955 + 0.55, 48000.0, 41.0, 1556.606, 595.206 + 0.55, 48000.0, 41.5, 1596.615, 588.804 + 0.55, 48000.0, 42.0, 1636.0, 594.0 + 0.55, 48000.0, 42.5, 1671.712, 624.167 + 0.55, 48000.0, 43.0, 1706.712, 663.588 + 0.55, 48000.0, 43.5, 1741.456, 708.664 + 0.55, 48000.0, 44.0, 1776.4, 755.8 + 0.55, 48000.0, 44.5, 1813.719, 794.977 + 0.55, 48000.0, 45.0, 1851.463, 831.588 + 0.55, 48000.0, 45.5, 1889.4, 864.605 + 0.55, 48000.0, 46.0, 1927.3, 893.0 + 0.55, 48000.0, 46.5, 1964.189, 908.245 + 0.55, 48000.0, 47.0, 2000.875, 919.813 + 0.55, 48000.0, 47.5, 2037.423, 929.673 + 0.55, 48000.0, 48.0, 2073.9, 939.8 + 0.55, 48000.0, 48.5, 2110.37, 952.164 + 0.55, 48000.0, 49.0, 2146.9, 968.738 + 0.55, 48000.0, 49.5, 2183.555, 991.492 + 0.55, 48000.0, 50.0, 2220.4, 1022.4 + 0.6, 0.0, 0.0, 636.1095, 636.109 + 0.6, 0.0, 22.0, 1410.0, 1479.9 + 0.6, 0.0, 22.5, 1677.552, 1697.82 + 0.6, 0.0, 23.0, 1940.5, 1820.84 + 0.6, 0.0, 23.5, 2200.098, 1867.86 + 0.6, 0.0, 24.0, 2457.6, 1857.8 + 0.6, 0.0, 24.5, 2714.258, 1809.57 + 0.6, 0.0, 25.0, 2971.325, 1742.09 + 0.6, 0.0, 25.5, 3230.055, 1674.26 + 0.6, 0.0, 26.0, 3491.7, 1625.0 + 0.6, 0.0, 26.5, 3770.338, 1790.86 + 0.6, 0.0, 27.0, 4055.131, 2023.26 + 0.6, 0.0, 27.5, 4345.134, 2310.67 + 0.6, 0.0, 28.0, 4639.4, 2641.55 + 0.6, 0.0, 28.5, 4936.985, 3004.34 + 0.6, 0.0, 29.0, 5236.944, 3387.53 + 0.6, 0.0, 29.5, 5538.33, 3779.56 + 0.6, 0.0, 30.0, 5840.2, 4168.9 + 0.6, 0.0, 30.5, 6130.713, 4403.2 + 0.6, 0.0, 31.0, 6420.856, 4625.13 + 0.6, 0.0, 31.5, 6710.721, 4836.58 + 0.6, 0.0, 32.0, 7000.4, 5039.4 + 0.6, 0.0, 32.5, 7289.985, 5235.47 + 0.6, 0.0, 33.0, 7579.569, 5426.67 + 0.6, 0.0, 33.5, 7869.243, 5614.85 + 0.6, 0.0, 34.0, 8159.1, 5801.9 + 0.6, 0.0, 34.5, 8450.702, 6168.55 + 0.6, 0.0, 35.0, 8742.531, 6520.77 + 0.6, 0.0, 35.5, 9034.54, 6843.39 + 0.6, 0.0, 36.0, 9326.68, 7121.25 + 0.6, 0.0, 36.5, 9618.904, 7339.19 + 0.6, 0.0, 37.0, 9911.164, 7482.04 + 0.6, 0.0, 37.5, 10203.41, 7534.63 + 0.6, 0.0, 38.0, 10495.6, 7481.8 + 0.6, 0.0, 38.5, 10787.77, 7171.43 + 0.6, 0.0, 39.0, 11079.73, 6796.33 + 0.6, 0.0, 39.5, 11371.43, 6371.76 + 0.6, 0.0, 40.0, 11662.8, 5913.0 + 0.6, 0.0, 40.5, 11954.0, 5410.82 + 0.6, 0.0, 41.0, 12244.64, 4914.79 + 0.6, 0.0, 41.5, 12534.56, 4449.96 + 0.6, 0.0, 42.0, 12823.6, 4041.4 + 0.6, 0.0, 42.5, 13109.17, 3753.41 + 0.6, 0.0, 43.0, 13394.51, 3556.14 + 0.6, 0.0, 43.5, 13680.42, 3458.94 + 0.6, 0.0, 44.0, 13967.7, 3471.2 + 0.6, 0.0, 44.5, 14261.38, 3689.01 + 0.6, 0.0, 45.0, 14556.36, 4000.32 + 0.6, 0.0, 45.5, 14851.76, 4379.82 + 0.6, 0.0, 46.0, 15146.7, 4802.2 + 0.6, 0.0, 46.5, 15436.65, 5200.54 + 0.6, 0.0, 47.0, 15725.84, 5607.75 + 0.6, 0.0, 47.5, 16014.83, 6015.16 + 0.6, 0.0, 48.0, 16304.2, 6414.1 + 0.6, 0.0, 48.5, 16594.53, 6795.88 + 0.6, 0.0, 49.0, 16886.39, 7151.82 + 0.6, 0.0, 49.5, 17180.35, 7473.26 + 0.6, 0.0, 50.0, 17477.0, 7751.5 + 0.6, 2000.0, 0.0, 595.5701, 595.57 + 0.6, 2000.0, 22.0, -6201.9, -1303.4 + 0.6, 2000.0, 22.5, -7374.701, -1711.47 + 0.6, 2000.0, 23.0, -8535.82, -2091.85 + 0.6, 2000.0, 23.5, -9689.255, -2451.86 + 0.6, 2000.0, 24.0, -10839.0, -2798.8 + 0.6, 2000.0, 24.5, -11989.05, -3139.99 + 0.6, 2000.0, 25.0, -13143.4, -3482.75 + 0.6, 2000.0, 25.5, -14306.06, -3834.38 + 0.6, 2000.0, 26.0, -15481.0, -4202.2 + 0.6, 2000.0, 26.5, -16714.36, -4669.1 + 0.6, 2000.0, 27.0, -17970.41, -5171.13 + 0.6, 2000.0, 27.5, -19245.93, -5702.65 + 0.6, 2000.0, 28.0, -20537.69, -6258.02 + 0.6, 2000.0, 28.5, -21842.46, -6831.61 + 0.6, 2000.0, 29.0, -23157.02, -7417.76 + 0.6, 2000.0, 29.5, -24478.14, -8010.84 + 0.6, 2000.0, 30.0, -25802.6, -8605.2 + 0.6, 2000.0, 30.5, -27093.34, -9114.92 + 0.6, 2000.0, 31.0, -28384.18, -9622.29 + 0.6, 2000.0, 31.5, -29675.12, -10129.3 + 0.6, 2000.0, 32.0, -30966.16, -10638.0 + 0.6, 2000.0, 32.5, -32257.29, -11150.3 + 0.6, 2000.0, 33.0, -33548.51, -11668.3 + 0.6, 2000.0, 33.5, -34839.81, -12194.0 + 0.6, 2000.0, 34.0, -36131.2, -12729.3 + 0.6, 2000.0, 34.5, -37423.91, -13390.0 + 0.6, 2000.0, 35.0, -38716.58, -14053.5 + 0.6, 2000.0, 35.5, -40009.07, -14711.1 + 0.6, 2000.0, 36.0, -41301.27, -15353.8 + 0.6, 2000.0, 36.5, -42593.06, -15973.0 + 0.6, 2000.0, 37.0, -43884.31, -16559.7 + 0.6, 2000.0, 37.5, -45174.9, -17105.2 + 0.6, 2000.0, 38.0, -46464.7, -17600.6 + 0.6, 2000.0, 38.5, -47751.34, -17960.0 + 0.6, 2000.0, 39.0, -49038.12, -18291.6 + 0.6, 2000.0, 39.5, -50325.42, -18603.9 + 0.6, 2000.0, 40.0, -51613.6, -18905.1 + 0.6, 2000.0, 40.5, -52904.98, -19182.5 + 0.6, 2000.0, 41.0, -54197.24, -19473.9 + 0.6, 2000.0, 41.5, -55489.97, -19796.2 + 0.6, 2000.0, 42.0, -56782.8, -20166.0 + 0.6, 2000.0, 42.5, -58073.34, -20656.7 + 0.6, 2000.0, 43.0, -59363.97, -21205.9 + 0.6, 2000.0, 43.5, -60655.1, -21807.7 + 0.6, 2000.0, 44.0, -61947.1, -22456.4 + 0.6, 2000.0, 44.5, -63244.3, -23151.6 + 0.6, 2000.0, 45.0, -64541.62, -23879.7 + 0.6, 2000.0, 45.5, -65837.87, -24632.5 + 0.6, 2000.0, 46.0, -67131.9, -25402.1 + 0.6, 2000.0, 46.5, -68416.29, -26160.2 + 0.6, 2000.0, 47.0, -69698.6, -26926.8 + 0.6, 2000.0, 47.5, -70980.16, -27701.9 + 0.6, 2000.0, 48.0, -72262.3, -28485.5 + 0.6, 2000.0, 48.5, -73546.34, -29277.5 + 0.6, 2000.0, 49.0, -74833.6, -30077.9 + 0.6, 2000.0, 49.5, -76125.41, -30886.6 + 0.6, 2000.0, 50.0, -77423.1, -31703.5 + 0.6, 5000.0, 0.0, 538.6131, 538.613 + 0.6, 5000.0, 22.0, 6111.3, 2945.7 + 0.6, 5000.0, 22.5, 7273.005, 3342.75 + 0.6, 5000.0, 23.0, 8422.098, 3727.68 + 0.6, 5000.0, 23.5, 9562.668, 4104.61 + 0.6, 5000.0, 24.0, 10698.8, 4477.7 + 0.6, 5000.0, 24.5, 11834.58, 4851.09 + 0.6, 5000.0, 25.0, 12974.1, 5228.92 + 0.6, 5000.0, 25.5, 14121.45, 5615.35 + 0.6, 5000.0, 26.0, 15280.7, 6014.5 + 0.6, 5000.0, 26.5, 16498.6, 6472.13 + 0.6, 5000.0, 27.0, 17739.02, 6953.16 + 0.6, 5000.0, 27.5, 18998.74, 7454.61 + 0.6, 5000.0, 28.0, 20274.53, 7973.47 + 0.6, 5000.0, 28.5, 21563.18, 8506.77 + 0.6, 5000.0, 29.0, 22861.46, 9051.52 + 0.6, 5000.0, 29.5, 24166.14, 9604.72 + 0.6, 5000.0, 30.0, 25474.0, 10163.4 + 0.6, 5000.0, 30.5, 26748.03, 10697.5 + 0.6, 5000.0, 31.0, 28022.01, 11233.6 + 0.6, 5000.0, 31.5, 29295.94, 11771.4 + 0.6, 5000.0, 32.0, 30569.81, 12310.5 + 0.6, 5000.0, 32.5, 31843.61, 12850.4 + 0.6, 5000.0, 33.0, 33117.35, 13390.8 + 0.6, 5000.0, 33.5, 34391.01, 13931.2 + 0.6, 5000.0, 34.0, 35664.6, 14471.3 + 0.6, 5000.0, 34.5, 36937.78, 15016.3 + 0.6, 5000.0, 35.0, 38210.9, 15559.5 + 0.6, 5000.0, 35.5, 39483.99, 16100.1 + 0.6, 5000.0, 36.0, 40757.07, 16637.0 + 0.6, 5000.0, 36.5, 42030.17, 17169.5 + 0.6, 5000.0, 37.0, 43303.3, 17696.4 + 0.6, 5000.0, 37.5, 44576.51, 18216.8 + 0.6, 5000.0, 38.0, 45849.8, 18729.9 + 0.6, 5000.0, 38.5, 47123.48, 19230.2 + 0.6, 5000.0, 39.0, 48397.16, 19723.5 + 0.6, 5000.0, 39.5, 49670.81, 20209.8 + 0.6, 5000.0, 40.0, 50944.4, 20689.3 + 0.6, 5000.0, 40.5, 52217.46, 21149.0 + 0.6, 5000.0, 41.0, 53490.55, 21607.1 + 0.6, 5000.0, 41.5, 54763.82, 22068.7 + 0.6, 5000.0, 42.0, 56037.4, 22539.0 + 0.6, 5000.0, 42.5, 57311.35, 23032.4 + 0.6, 5000.0, 43.0, 58585.92, 23541.4 + 0.6, 5000.0, 43.5, 59861.28, 24067.3 + 0.6, 5000.0, 44.0, 61137.6, 24611.8 + 0.6, 5000.0, 44.5, 62418.24, 25183.7 + 0.6, 5000.0, 45.0, 63698.9, 25774.3 + 0.6, 5000.0, 45.5, 64978.49, 26382.2 + 0.6, 5000.0, 46.0, 66255.9, 27005.9 + 0.6, 5000.0, 46.5, 67524.19, 27649.2 + 0.6, 5000.0, 47.0, 68790.44, 28303.4 + 0.6, 5000.0, 47.5, 70055.86, 28965.2 + 0.6, 5000.0, 48.0, 71321.7, 29631.0 + 0.6, 5000.0, 48.5, 72589.18, 30297.4 + 0.6, 5000.0, 49.0, 73859.54, 30960.9 + 0.6, 5000.0, 49.5, 75134.0, 31618.1 + 0.6, 5000.0, 50.0, 76413.8, 32265.4 + 0.6, 10000.0, 0.0, 453.32, 453.32 + 0.6, 10000.0, 22.0, 827.4, 977.6 + 0.6, 10000.0, 22.5, 984.1828, 1041.46 + 0.6, 10000.0, 23.0, 1139.463, 1105.09 + 0.6, 10000.0, 23.5, 1293.761, 1168.63 + 0.6, 10000.0, 24.0, 1447.6, 1232.2 + 0.6, 10000.0, 24.5, 1601.502, 1295.93 + 0.6, 10000.0, 25.0, 1755.988, 1359.96 + 0.6, 10000.0, 25.5, 1911.58, 1424.4 + 0.6, 10000.0, 26.0, 2068.8, 1489.4 + 0.6, 10000.0, 26.5, 2233.694, 1556.4 + 0.6, 10000.0, 27.0, 2401.575, 1624.29 + 0.6, 10000.0, 27.5, 2572.019, 1692.96 + 0.6, 10000.0, 28.0, 2744.6, 1762.32 + 0.6, 10000.0, 28.5, 2918.894, 1832.28 + 0.6, 10000.0, 29.0, 3094.475, 1902.72 + 0.6, 10000.0, 29.5, 3270.919, 1973.56 + 0.6, 10000.0, 30.0, 3447.8, 2044.7 + 0.6, 10000.0, 30.5, 3620.262, 2114.92 + 0.6, 10000.0, 31.0, 3792.734, 2185.34 + 0.6, 10000.0, 31.5, 3965.212, 2255.98 + 0.6, 10000.0, 32.0, 4137.694, 2326.84 + 0.6, 10000.0, 32.5, 4310.176, 2397.94 + 0.6, 10000.0, 33.0, 4482.657, 2469.27 + 0.6, 10000.0, 33.5, 4655.133, 2540.86 + 0.6, 10000.0, 34.0, 4827.6, 2612.7 + 0.6, 10000.0, 34.5, 5000.045, 2684.63 + 0.6, 10000.0, 35.0, 5172.477, 2756.85 + 0.6, 10000.0, 35.5, 5344.894, 2829.39 + 0.6, 10000.0, 36.0, 5517.295, 2902.27 + 0.6, 10000.0, 36.5, 5689.678, 2975.52 + 0.6, 10000.0, 37.0, 5862.041, 3049.15 + 0.6, 10000.0, 37.5, 6034.382, 3123.21 + 0.6, 10000.0, 38.0, 6206.7, 3197.7 + 0.6, 10000.0, 38.5, 6378.923, 3273.77 + 0.6, 10000.0, 39.0, 6551.155, 3349.76 + 0.6, 10000.0, 39.5, 6723.409, 3425.45 + 0.6, 10000.0, 40.0, 6895.7, 3500.6 + 0.6, 10000.0, 40.5, 7068.098, 3572.72 + 0.6, 10000.0, 41.0, 7240.538, 3644.77 + 0.6, 10000.0, 41.5, 7413.008, 3717.47 + 0.6, 10000.0, 42.0, 7585.5, 3791.5 + 0.6, 10000.0, 42.5, 7757.868, 3870.29 + 0.6, 10000.0, 43.0, 7930.294, 3950.7 + 0.6, 10000.0, 43.5, 8102.823, 4032.34 + 0.6, 10000.0, 44.0, 8275.5, 4114.8 + 0.6, 10000.0, 44.5, 8448.871, 4196.91 + 0.6, 10000.0, 45.0, 8622.281, 4279.36 + 0.6, 10000.0, 45.5, 8795.576, 4362.05 + 0.6, 10000.0, 46.0, 8968.6, 4444.9 + 0.6, 10000.0, 46.5, 9140.426, 4528.44 + 0.6, 10000.0, 47.0, 9311.981, 4611.71 + 0.6, 10000.0, 47.5, 9483.421, 4694.34 + 0.6, 10000.0, 48.0, 9654.9, 4776.0 + 0.6, 10000.0, 48.5, 9826.573, 4856.34 + 0.6, 10000.0, 49.0, 9998.594, 4935.02 + 0.6, 10000.0, 49.5, 10171.12, 5011.69 + 0.6, 10000.0, 50.0, 10344.3, 5086.0 + 0.6, 15000.0, 0.0, 379.0632, 379.063 + 0.6, 15000.0, 22.0, 751.2, 841.2 + 0.6, 15000.0, 22.5, 893.7604, 899.68 + 0.6, 15000.0, 23.0, 1034.855, 957.097 + 0.6, 15000.0, 23.5, 1174.972, 1013.72 + 0.6, 15000.0, 24.0, 1314.6, 1069.8 + 0.6, 15000.0, 24.5, 1454.228, 1125.62 + 0.6, 15000.0, 25.0, 1594.345, 1181.43 + 0.6, 15000.0, 25.5, 1735.44, 1237.5 + 0.6, 15000.0, 26.0, 1878.0, 1294.1 + 0.6, 15000.0, 26.5, 2027.646, 1353.92 + 0.6, 15000.0, 27.0, 2180.029, 1414.94 + 0.6, 15000.0, 27.5, 2334.757, 1477.0 + 0.6, 15000.0, 28.0, 2491.44, 1539.95 + 0.6, 15000.0, 28.5, 2649.687, 1603.64 + 0.6, 15000.0, 29.0, 2809.106, 1667.91 + 0.6, 15000.0, 29.5, 2969.308, 1732.62 + 0.6, 15000.0, 30.0, 3129.9, 1797.6 + 0.6, 15000.0, 30.5, 3286.385, 1860.9 + 0.6, 15000.0, 31.0, 3442.871, 1924.34 + 0.6, 15000.0, 31.5, 3599.357, 1987.95 + 0.6, 15000.0, 32.0, 3755.844, 2051.74 + 0.6, 15000.0, 32.5, 3912.331, 2115.75 + 0.6, 15000.0, 33.0, 4068.82, 2179.98 + 0.6, 15000.0, 33.5, 4225.309, 2244.45 + 0.6, 15000.0, 34.0, 4381.8, 2309.2 + 0.6, 15000.0, 34.5, 4538.297, 2374.36 + 0.6, 15000.0, 35.0, 4694.795, 2439.81 + 0.6, 15000.0, 35.5, 4851.295, 2505.57 + 0.6, 15000.0, 36.0, 5007.795, 2571.64 + 0.6, 15000.0, 36.5, 5164.296, 2638.03 + 0.6, 15000.0, 37.0, 5320.797, 2704.75 + 0.6, 15000.0, 37.5, 5477.299, 2771.8 + 0.6, 15000.0, 38.0, 5633.8, 2839.2 + 0.6, 15000.0, 38.5, 5790.3, 2907.19 + 0.6, 15000.0, 39.0, 5946.8, 2975.41 + 0.6, 15000.0, 39.5, 6103.3, 3043.83 + 0.6, 15000.0, 40.0, 6259.8, 3112.4 + 0.6, 15000.0, 40.5, 6416.304, 3180.91 + 0.6, 15000.0, 41.0, 6572.806, 3249.54 + 0.6, 15000.0, 41.5, 6729.305, 3318.33 + 0.6, 15000.0, 42.0, 6885.8, 3387.3 + 0.6, 15000.0, 42.5, 7042.152, 3456.48 + 0.6, 15000.0, 43.0, 7198.55, 3525.88 + 0.6, 15000.0, 43.5, 7355.048, 3595.51 + 0.6, 15000.0, 44.0, 7511.7, 3665.4 + 0.6, 15000.0, 44.5, 7669.066, 3735.69 + 0.6, 15000.0, 45.0, 7826.488, 3806.22 + 0.6, 15000.0, 45.5, 7983.816, 3876.93 + 0.6, 15000.0, 46.0, 8140.9, 3947.8 + 0.6, 15000.0, 46.5, 8296.848, 4018.44 + 0.6, 15000.0, 47.0, 8452.55, 4089.28 + 0.6, 15000.0, 47.5, 8608.152, 4160.44 + 0.6, 15000.0, 48.0, 8763.8, 4232.0 + 0.6, 15000.0, 48.5, 8919.642, 4304.07 + 0.6, 15000.0, 49.0, 9075.825, 4376.74 + 0.6, 15000.0, 49.5, 9232.495, 4450.12 + 0.6, 15000.0, 50.0, 9389.8, 4524.3 + 0.6, 20000.0, 0.0, 314.7628, 314.763 + 0.6, 20000.0, 22.0, 776.6, 758.6 + 0.6, 20000.0, 22.5, 923.9941, 816.388 + 0.6, 20000.0, 23.0, 1069.872, 873.83 + 0.6, 20000.0, 23.5, 1214.739, 931.081 + 0.6, 20000.0, 24.0, 1359.1, 988.3 + 0.6, 20000.0, 24.5, 1503.461, 1045.64 + 0.6, 20000.0, 25.0, 1648.328, 1103.27 + 0.6, 20000.0, 25.5, 1794.206, 1161.34 + 0.6, 20000.0, 26.0, 1941.6, 1220.0 + 0.6, 20000.0, 26.5, 2096.325, 1280.88 + 0.6, 20000.0, 27.0, 2253.88, 1342.76 + 0.6, 20000.0, 27.5, 2413.862, 1405.54 + 0.6, 20000.0, 28.0, 2575.865, 1469.12 + 0.6, 20000.0, 28.5, 2739.485, 1533.43 + 0.6, 20000.0, 29.0, 2904.317, 1598.35 + 0.6, 20000.0, 29.5, 3069.957, 1663.81 + 0.6, 20000.0, 30.0, 3236.0, 1729.7 + 0.6, 20000.0, 30.5, 3397.789, 1794.88 + 0.6, 20000.0, 31.0, 3559.577, 1860.41 + 0.6, 20000.0, 31.5, 3721.363, 1926.3 + 0.6, 20000.0, 32.0, 3883.15, 1992.55 + 0.6, 20000.0, 32.5, 4044.937, 2059.17 + 0.6, 20000.0, 33.0, 4206.723, 2126.16 + 0.6, 20000.0, 33.5, 4368.511, 2193.54 + 0.6, 20000.0, 34.0, 4530.3, 2261.3 + 0.6, 20000.0, 34.5, 4692.097, 2329.79 + 0.6, 20000.0, 35.0, 4853.895, 2398.66 + 0.6, 20000.0, 35.5, 5015.695, 2467.87 + 0.6, 20000.0, 36.0, 5177.495, 2537.4 + 0.6, 20000.0, 36.5, 5339.296, 2607.22 + 0.6, 20000.0, 37.0, 5501.097, 2677.31 + 0.6, 20000.0, 37.5, 5662.899, 2747.65 + 0.6, 20000.0, 38.0, 5824.7, 2818.2 + 0.6, 20000.0, 38.5, 5986.5, 2888.78 + 0.6, 20000.0, 39.0, 6148.3, 2959.61 + 0.6, 20000.0, 39.5, 6310.1, 3030.72 + 0.6, 20000.0, 40.0, 6471.9, 3102.1 + 0.6, 20000.0, 40.5, 6633.7, 3173.61 + 0.6, 20000.0, 41.0, 6795.5, 3245.49 + 0.6, 20000.0, 41.5, 6957.3, 3317.83 + 0.6, 20000.0, 42.0, 7119.1, 3390.7 + 0.6, 20000.0, 42.5, 7280.771, 3464.48 + 0.6, 20000.0, 43.0, 7442.494, 3538.82 + 0.6, 20000.0, 43.5, 7604.32, 3613.71 + 0.6, 20000.0, 44.0, 7766.3, 3689.1 + 0.6, 20000.0, 44.5, 7928.998, 3764.75 + 0.6, 20000.0, 45.0, 8091.75, 3840.91 + 0.6, 20000.0, 45.5, 8254.402, 3917.61 + 0.6, 20000.0, 46.0, 8416.8, 3994.9 + 0.6, 20000.0, 46.5, 8578.034, 4071.85 + 0.6, 20000.0, 47.0, 8739.013, 4149.84 + 0.6, 20000.0, 47.5, 8899.884, 4229.32 + 0.6, 20000.0, 48.0, 9060.8, 4310.7 + 0.6, 20000.0, 48.5, 9221.909, 4394.41 + 0.6, 20000.0, 49.0, 9383.363, 4480.88 + 0.6, 20000.0, 49.5, 9545.309, 4570.54 + 0.6, 20000.0, 50.0, 9707.9, 4663.8 + 0.6, 25000.0, 0.0, 259.4005, 259.401 + 0.6, 25000.0, 22.0, 628.5, 620.4 + 0.6, 25000.0, 22.5, 747.7416, 665.817 + 0.6, 25000.0, 23.0, 865.7672, 711.102 + 0.6, 25000.0, 23.5, 982.9842, 756.36 + 0.6, 25000.0, 24.0, 1099.8, 801.7 + 0.6, 25000.0, 24.5, 1216.622, 847.227 + 0.6, 25000.0, 25.0, 1333.858, 893.048 + 0.6, 25000.0, 25.5, 1451.915, 939.271 + 0.6, 25000.0, 26.0, 1571.2, 986.0 + 0.6, 25000.0, 26.5, 1696.405, 1034.43 + 0.6, 25000.0, 27.0, 1823.897, 1083.64 + 0.6, 25000.0, 27.5, 1953.352, 1133.55 + 0.6, 25000.0, 28.0, 2084.44, 1184.08 + 0.6, 25000.0, 28.5, 2216.836, 1235.17 + 0.6, 25000.0, 29.0, 2350.212, 1286.72 + 0.6, 25000.0, 29.5, 2484.243, 1338.65 + 0.6, 25000.0, 30.0, 2618.6, 1390.9 + 0.6, 25000.0, 30.5, 2749.523, 1442.35 + 0.6, 25000.0, 31.0, 2880.446, 1494.05 + 0.6, 25000.0, 31.5, 3011.37, 1546.02 + 0.6, 25000.0, 32.0, 3142.294, 1598.27 + 0.6, 25000.0, 32.5, 3273.219, 1650.83 + 0.6, 25000.0, 33.0, 3404.145, 1703.71 + 0.6, 25000.0, 33.5, 3535.072, 1756.92 + 0.6, 25000.0, 34.0, 3666.0, 1810.5 + 0.6, 25000.0, 34.5, 3796.938, 1865.0 + 0.6, 25000.0, 35.0, 3927.877, 1919.84 + 0.6, 25000.0, 35.5, 4058.816, 1974.99 + 0.6, 25000.0, 36.0, 4189.755, 2030.41 + 0.6, 25000.0, 36.5, 4320.694, 2086.08 + 0.6, 25000.0, 37.0, 4451.631, 2141.96 + 0.6, 25000.0, 37.5, 4582.567, 2198.01 + 0.6, 25000.0, 38.0, 4713.5, 2254.2 + 0.6, 25000.0, 38.5, 4844.421, 2310.24 + 0.6, 25000.0, 39.0, 4975.344, 2366.48 + 0.6, 25000.0, 39.5, 5106.27, 2422.96 + 0.6, 25000.0, 40.0, 5237.2, 2479.7 + 0.6, 25000.0, 40.5, 5368.148, 2536.7 + 0.6, 25000.0, 41.0, 5499.1, 2594.01 + 0.6, 25000.0, 41.5, 5630.052, 2651.67 + 0.6, 25000.0, 42.0, 5761.0, 2709.7 + 0.6, 25000.0, 42.5, 5891.829, 2768.17 + 0.6, 25000.0, 43.0, 6022.694, 2827.07 + 0.6, 25000.0, 43.5, 6153.637, 2886.41 + 0.6, 25000.0, 44.0, 6284.7, 2946.2 + 0.6, 25000.0, 44.5, 6416.336, 3006.43 + 0.6, 25000.0, 45.0, 6548.013, 3067.17 + 0.6, 25000.0, 45.5, 6679.608, 3128.45 + 0.6, 25000.0, 46.0, 6811.0, 3190.3 + 0.6, 25000.0, 46.5, 6941.454, 3252.3 + 0.6, 25000.0, 47.0, 7071.706, 3315.12 + 0.6, 25000.0, 47.5, 7201.88, 3378.99 + 0.6, 25000.0, 48.0, 7332.1, 3444.1 + 0.6, 25000.0, 48.5, 7462.488, 3510.68 + 0.6, 25000.0, 49.0, 7593.169, 3578.95 + 0.6, 25000.0, 49.5, 7724.265, 3649.12 + 0.6, 25000.0, 50.0, 7855.9, 3721.4 + 0.6, 30000.0, 0.0, 212.0296, 212.03 + 0.6, 30000.0, 22.0, 500.8, 505.2 + 0.6, 30000.0, 22.5, 595.8963, 540.63 + 0.6, 30000.0, 23.0, 689.9922, 576.025 + 0.6, 30000.0, 23.5, 783.417, 611.458 + 0.6, 30000.0, 24.0, 876.5, 647.0 + 0.6, 30000.0, 24.5, 969.5705, 682.723 + 0.6, 30000.0, 25.0, 1062.958, 718.7 + 0.6, 30000.0, 25.5, 1156.991, 755.002 + 0.6, 30000.0, 26.0, 1252.0, 791.7 + 0.6, 30000.0, 26.5, 1351.76, 829.595 + 0.6, 30000.0, 27.0, 1453.351, 868.071 + 0.6, 30000.0, 27.5, 1556.512, 907.077 + 0.6, 30000.0, 28.0, 1660.98, 946.56 + 0.6, 30000.0, 28.5, 1766.495, 986.466 + 0.6, 30000.0, 29.0, 1872.794, 1026.74 + 0.6, 30000.0, 29.5, 1979.616, 1067.34 + 0.6, 30000.0, 30.0, 2086.7, 1108.2 + 0.6, 30000.0, 30.5, 2191.038, 1148.76 + 0.6, 30000.0, 31.0, 2295.375, 1189.52 + 0.6, 30000.0, 31.5, 2399.713, 1230.5 + 0.6, 30000.0, 32.0, 2504.05, 1271.67 + 0.6, 30000.0, 32.5, 2608.388, 1313.04 + 0.6, 30000.0, 33.0, 2712.725, 1354.6 + 0.6, 30000.0, 33.5, 2817.063, 1396.36 + 0.6, 30000.0, 34.0, 2921.4, 1438.3 + 0.6, 30000.0, 34.5, 3025.734, 1480.4 + 0.6, 30000.0, 35.0, 3130.069, 1522.68 + 0.6, 30000.0, 35.5, 3234.404, 1565.14 + 0.6, 30000.0, 36.0, 3338.74, 1607.77 + 0.6, 30000.0, 36.5, 3443.077, 1650.59 + 0.6, 30000.0, 37.0, 3547.416, 1693.59 + 0.6, 30000.0, 37.5, 3651.757, 1736.76 + 0.6, 30000.0, 38.0, 3756.1, 1780.1 + 0.6, 30000.0, 38.5, 3860.454, 1823.53 + 0.6, 30000.0, 39.0, 3964.806, 1867.18 + 0.6, 30000.0, 39.5, 4069.155, 1911.07 + 0.6, 30000.0, 40.0, 4173.5, 1955.2 + 0.6, 30000.0, 40.5, 4277.83, 1999.64 + 0.6, 30000.0, 41.0, 4382.156, 2044.35 + 0.6, 30000.0, 41.5, 4486.479, 2089.34 + 0.6, 30000.0, 42.0, 4590.8, 2134.6 + 0.6, 30000.0, 42.5, 4695.039, 2180.12 + 0.6, 30000.0, 43.0, 4799.312, 2225.94 + 0.6, 30000.0, 43.5, 4903.655, 2272.06 + 0.6, 30000.0, 44.0, 5008.1, 2318.5 + 0.6, 30000.0, 44.5, 5113.023, 2365.1 + 0.6, 30000.0, 45.0, 5217.981, 2412.11 + 0.6, 30000.0, 45.5, 5322.874, 2459.61 + 0.6, 30000.0, 46.0, 5427.6, 2507.7 + 0.6, 30000.0, 46.5, 5531.549, 2556.27 + 0.6, 30000.0, 47.0, 5635.331, 2605.66 + 0.6, 30000.0, 47.5, 5739.048, 2656.02 + 0.6, 30000.0, 48.0, 5842.8, 2707.5 + 0.6, 30000.0, 48.5, 5946.69, 2760.25 + 0.6, 30000.0, 49.0, 6050.819, 2814.44 + 0.6, 30000.0, 49.5, 6155.288, 2870.2 + 0.6, 30000.0, 50.0, 6260.2, 2927.7 + 0.6, 35000.0, 0.0, 171.768, 171.768 + 0.6, 35000.0, 22.0, 382.8, 417.7 + 0.6, 35000.0, 22.5, 455.3926, 444.043 + 0.6, 35000.0, 23.0, 527.2594, 470.444 + 0.6, 35000.0, 23.5, 598.6465, 496.948 + 0.6, 35000.0, 24.0, 669.8, 523.6 + 0.6, 35000.0, 24.5, 740.966, 550.446 + 0.6, 35000.0, 25.0, 812.3906, 577.531 + 0.6, 35000.0, 25.5, 884.3199, 604.901 + 0.6, 35000.0, 26.0, 957.0, 632.6 + 0.6, 35000.0, 26.5, 1033.273, 661.176 + 0.6, 35000.0, 27.0, 1110.938, 690.201 + 0.6, 35000.0, 27.5, 1189.795, 719.634 + 0.6, 35000.0, 28.0, 1269.645, 749.435 + 0.6, 35000.0, 28.5, 1350.29, 779.563 + 0.6, 35000.0, 29.0, 1431.53, 809.977 + 0.6, 35000.0, 29.5, 1513.166, 840.636 + 0.6, 35000.0, 30.0, 1595.0, 871.5 + 0.6, 35000.0, 30.5, 1674.737, 902.148 + 0.6, 35000.0, 31.0, 1754.473, 932.955 + 0.6, 35000.0, 31.5, 1834.208, 963.918 + 0.6, 35000.0, 32.0, 1913.944, 995.031 + 0.6, 35000.0, 32.5, 1993.68, 1026.29 + 0.6, 35000.0, 33.0, 2073.418, 1057.69 + 0.6, 35000.0, 33.5, 2153.158, 1089.23 + 0.6, 35000.0, 34.0, 2232.9, 1120.9 + 0.6, 35000.0, 34.5, 2312.666, 1152.62 + 0.6, 35000.0, 35.0, 2392.434, 1184.48 + 0.6, 35000.0, 35.5, 2472.203, 1216.47 + 0.6, 35000.0, 36.0, 2551.97, 1248.59 + 0.6, 35000.0, 36.5, 2631.735, 1280.85 + 0.6, 35000.0, 37.0, 2711.496, 1313.26 + 0.6, 35000.0, 37.5, 2791.251, 1345.81 + 0.6, 35000.0, 38.0, 2871.0, 1378.5 + 0.6, 35000.0, 38.5, 2950.724, 1411.36 + 0.6, 35000.0, 39.0, 3030.447, 1444.37 + 0.6, 35000.0, 39.5, 3110.171, 1477.51 + 0.6, 35000.0, 40.0, 3189.9, 1510.8 + 0.6, 35000.0, 40.5, 3269.641, 1544.14 + 0.6, 35000.0, 41.0, 3349.388, 1577.64 + 0.6, 35000.0, 41.5, 3429.141, 1611.35 + 0.6, 35000.0, 42.0, 3508.9, 1645.3 + 0.6, 35000.0, 42.5, 3588.611, 1679.6 + 0.6, 35000.0, 43.0, 3668.35, 1714.18 + 0.6, 35000.0, 43.5, 3748.139, 1749.01 + 0.6, 35000.0, 44.0, 3828.0, 1784.1 + 0.6, 35000.0, 44.5, 3908.197, 1819.25 + 0.6, 35000.0, 45.0, 3988.412, 1854.74 + 0.6, 35000.0, 45.5, 4068.572, 1890.63 + 0.6, 35000.0, 46.0, 4148.6, 1927.0 + 0.6, 35000.0, 46.5, 4228.039, 1964.05 + 0.6, 35000.0, 47.0, 4307.35, 2001.68 + 0.6, 35000.0, 47.5, 4386.611, 2039.92 + 0.6, 35000.0, 48.0, 4465.9, 2078.8 + 0.6, 35000.0, 48.5, 4545.295, 2118.34 + 0.6, 35000.0, 49.0, 4624.875, 2158.57 + 0.6, 35000.0, 49.5, 4704.717, 2199.51 + 0.6, 35000.0, 50.0, 4784.9, 2241.2 + 0.6, 39000.0, 0.0, 142.4663, 142.466 + 0.6, 39000.0, 22.0, 307.3, 362.6 + 0.6, 39000.0, 22.5, 365.6264, 384.063 + 0.6, 39000.0, 23.0, 423.3516, 405.445 + 0.6, 39000.0, 23.5, 480.676, 426.805 + 0.6, 39000.0, 24.0, 537.8, 448.2 + 0.6, 39000.0, 24.5, 594.924, 469.689 + 0.6, 39000.0, 25.0, 652.2484, 491.33 + 0.6, 39000.0, 25.5, 709.9736, 513.181 + 0.6, 39000.0, 26.0, 768.3, 535.3 + 0.6, 39000.0, 26.5, 829.5334, 558.361 + 0.6, 39000.0, 27.0, 891.8891, 581.842 + 0.6, 39000.0, 27.5, 955.2064, 605.696 + 0.6, 39000.0, 28.0, 1019.325, 629.875 + 0.6, 39000.0, 28.5, 1084.084, 654.332 + 0.6, 39000.0, 29.0, 1149.323, 679.02 + 0.6, 39000.0, 29.5, 1214.882, 703.892 + 0.6, 39000.0, 30.0, 1280.6, 728.9 + 0.6, 39000.0, 30.5, 1344.628, 753.505 + 0.6, 39000.0, 31.0, 1408.655, 778.198 + 0.6, 39000.0, 31.5, 1472.681, 802.98 + 0.6, 39000.0, 32.0, 1536.706, 827.85 + 0.6, 39000.0, 32.5, 1600.73, 852.807 + 0.6, 39000.0, 33.0, 1664.754, 877.852 + 0.6, 39000.0, 33.5, 1728.777, 902.983 + 0.6, 39000.0, 34.0, 1792.8, 928.2 + 0.6, 39000.0, 34.5, 1856.825, 953.372 + 0.6, 39000.0, 35.0, 1920.85, 978.642 + 0.6, 39000.0, 35.5, 1984.875, 1004.02 + 0.6, 39000.0, 36.0, 2048.9, 1029.52 + 0.6, 39000.0, 36.5, 2112.925, 1055.16 + 0.6, 39000.0, 37.0, 2176.95, 1080.95 + 0.6, 39000.0, 37.5, 2240.975, 1106.89 + 0.6, 39000.0, 38.0, 2305.0, 1133.0 + 0.6, 39000.0, 38.5, 2369.025, 1159.4 + 0.6, 39000.0, 39.0, 2433.05, 1185.94 + 0.6, 39000.0, 39.5, 2497.075, 1212.61 + 0.6, 39000.0, 40.0, 2561.1, 1239.4 + 0.6, 39000.0, 40.5, 2625.125, 1266.14 + 0.6, 39000.0, 41.0, 2689.15, 1293.03 + 0.6, 39000.0, 41.5, 2753.175, 1320.14 + 0.6, 39000.0, 42.0, 2817.2, 1347.5 + 0.6, 39000.0, 42.5, 2881.174, 1375.34 + 0.6, 39000.0, 43.0, 2945.169, 1403.48 + 0.6, 39000.0, 43.5, 3009.204, 1431.9 + 0.6, 39000.0, 44.0, 3073.3, 1460.6 + 0.6, 39000.0, 44.5, 3137.677, 1489.47 + 0.6, 39000.0, 45.0, 3202.075, 1518.63 + 0.6, 39000.0, 45.5, 3266.436, 1548.1 + 0.6, 39000.0, 46.0, 3330.7, 1577.9 + 0.6, 39000.0, 46.5, 3394.515, 1607.96 + 0.6, 39000.0, 47.0, 3458.231, 1638.44 + 0.6, 39000.0, 47.5, 3521.907, 1669.4 + 0.6, 39000.0, 48.0, 3585.6, 1700.9 + 0.6, 39000.0, 48.5, 3649.368, 1733.01 + 0.6, 39000.0, 49.0, 3713.269, 1765.79 + 0.6, 39000.0, 49.5, 3777.36, 1799.3 + 0.6, 39000.0, 50.0, 3841.7, 1833.6 + 0.6, 43000.0, 0.0, 117.5487, 117.549 + 0.6, 43000.0, 22.0, 237.1, 335.3 + 0.6, 43000.0, 22.5, 282.7787, 342.216 + 0.6, 43000.0, 23.0, 327.9328, 351.375 + 0.6, 43000.0, 23.5, 372.7205, 362.522 + 0.6, 43000.0, 24.0, 417.3, 375.4 + 0.6, 43000.0, 24.5, 461.8295, 389.753 + 0.6, 43000.0, 25.0, 506.4672, 405.325 + 0.6, 43000.0, 25.5, 551.3713, 421.859 + 0.6, 43000.0, 26.0, 596.7, 439.1 + 0.6, 43000.0, 26.5, 644.2289, 454.529 + 0.6, 43000.0, 27.0, 692.5912, 470.023 + 0.6, 43000.0, 27.5, 741.668, 485.713 + 0.6, 43000.0, 28.0, 791.34, 501.73 + 0.6, 43000.0, 28.5, 841.4883, 518.206 + 0.6, 43000.0, 29.0, 891.9937, 535.272 + 0.6, 43000.0, 29.5, 942.7373, 553.059 + 0.6, 43000.0, 30.0, 993.6, 571.7 + 0.6, 43000.0, 30.5, 1043.18, 593.316 + 0.6, 43000.0, 31.0, 1092.763, 615.858 + 0.6, 43000.0, 31.5, 1142.352, 639.268 + 0.6, 43000.0, 32.0, 1191.95, 663.487 + 0.6, 43000.0, 32.5, 1241.561, 688.459 + 0.6, 43000.0, 33.0, 1291.188, 714.123 + 0.6, 43000.0, 33.5, 1340.833, 740.423 + 0.6, 43000.0, 34.0, 1390.5, 767.3 + 0.6, 43000.0, 34.5, 1440.432, 805.428 + 0.6, 43000.0, 35.0, 1490.369, 842.994 + 0.6, 43000.0, 35.5, 1540.291, 878.918 + 0.6, 43000.0, 36.0, 1590.18, 912.12 + 0.6, 43000.0, 36.5, 1640.015, 941.52 + 0.6, 43000.0, 37.0, 1689.776, 966.036 + 0.6, 43000.0, 37.5, 1739.445, 984.59 + 0.6, 43000.0, 38.0, 1789.0, 996.1 + 0.6, 43000.0, 38.5, 1837.955, 985.02 + 0.6, 43000.0, 39.0, 1887.0, 972.238 + 0.6, 43000.0, 39.5, 1936.22, 959.886 + 0.6, 43000.0, 40.0, 1985.7, 950.1 + 0.6, 43000.0, 40.5, 2036.18, 948.483 + 0.6, 43000.0, 41.0, 2086.825, 952.312 + 0.6, 43000.0, 41.5, 2137.458, 962.336 + 0.6, 43000.0, 42.0, 2187.9, 979.3 + 0.6, 43000.0, 42.5, 2237.087, 1011.22 + 0.6, 43000.0, 43.0, 2286.081, 1048.67 + 0.6, 43000.0, 43.5, 2335.06, 1089.49 + 0.6, 43000.0, 44.0, 2384.2, 1131.5 + 0.6, 43000.0, 44.5, 2434.584, 1168.53 + 0.6, 43000.0, 45.0, 2485.119, 1204.05 + 0.6, 43000.0, 45.5, 2535.62, 1237.49 + 0.6, 43000.0, 46.0, 2585.9, 1268.3 + 0.6, 43000.0, 46.5, 2634.938, 1291.89 + 0.6, 43000.0, 47.0, 2683.719, 1313.35 + 0.6, 43000.0, 47.5, 2732.39, 1333.73 + 0.6, 43000.0, 48.0, 2781.1, 1354.1 + 0.6, 43000.0, 48.5, 2829.998, 1375.5 + 0.6, 43000.0, 49.0, 2879.231, 1399.0 + 0.6, 43000.0, 49.5, 2928.949, 1425.65 + 0.6, 43000.0, 50.0, 2979.3, 1456.5 + 0.6, 48000.0, 0.0, 92.43796, 92.438 + 0.6, 48000.0, 22.0, 185.5, 265.0 + 0.6, 48000.0, 22.5, 222.1367, 270.146 + 0.6, 48000.0, 23.0, 258.1063, 277.216 + 0.6, 48000.0, 23.5, 293.5727, 285.977 + 0.6, 48000.0, 24.0, 328.7, 296.2 + 0.6, 48000.0, 24.5, 363.6523, 307.654 + 0.6, 48000.0, 25.0, 398.5938, 320.109 + 0.6, 48000.0, 25.5, 433.6883, 333.335 + 0.6, 48000.0, 26.0, 469.1, 347.1 + 0.6, 48000.0, 26.5, 506.6035, 359.098 + 0.6, 48000.0, 27.0, 544.8444, 371.056 + 0.6, 48000.0, 27.5, 583.7105, 383.1 + 0.6, 48000.0, 28.0, 623.09, 395.355 + 0.6, 48000.0, 28.5, 662.8707, 407.947 + 0.6, 48000.0, 29.0, 702.9406, 421.002 + 0.6, 48000.0, 29.5, 743.1877, 434.644 + 0.6, 48000.0, 30.0, 783.5, 449.0 + 0.6, 48000.0, 30.5, 822.4865, 466.131 + 0.6, 48000.0, 31.0, 861.4359, 484.041 + 0.6, 48000.0, 31.5, 900.358, 502.674 + 0.6, 48000.0, 32.0, 939.2625, 521.969 + 0.6, 48000.0, 32.5, 978.1592, 541.868 + 0.6, 48000.0, 33.0, 1017.058, 562.312 + 0.6, 48000.0, 33.5, 1055.968, 583.242 + 0.6, 48000.0, 34.0, 1094.9, 604.6 + 0.6, 48000.0, 34.5, 1134.179, 634.447 + 0.6, 48000.0, 35.0, 1173.469, 663.831 + 0.6, 48000.0, 35.5, 1212.749, 691.92 + 0.6, 48000.0, 36.0, 1252.0, 717.88 + 0.6, 48000.0, 36.5, 1291.201, 740.88 + 0.6, 48000.0, 37.0, 1330.331, 760.089 + 0.6, 48000.0, 37.5, 1369.371, 774.673 + 0.6, 48000.0, 38.0, 1408.3, 783.8 + 0.6, 48000.0, 38.5, 1446.549, 775.507 + 0.6, 48000.0, 39.0, 1484.931, 765.866 + 0.6, 48000.0, 39.5, 1523.548, 756.516 + 0.6, 48000.0, 40.0, 1562.5, 749.1 + 0.6, 48000.0, 40.5, 1602.73, 747.816 + 0.6, 48000.0, 41.0, 1643.163, 750.725 + 0.6, 48000.0, 41.5, 1683.564, 758.447 + 0.6, 48000.0, 42.0, 1723.7, 771.6 + 0.6, 48000.0, 42.5, 1762.25, 796.565 + 0.6, 48000.0, 43.0, 1800.5, 825.894 + 0.6, 48000.0, 43.5, 1838.65, 857.901 + 0.6, 48000.0, 44.0, 1876.9, 890.9 + 0.6, 48000.0, 44.5, 1916.239, 920.159 + 0.6, 48000.0, 45.0, 1955.763, 948.256 + 0.6, 48000.0, 45.5, 1995.355, 974.726 + 0.6, 48000.0, 46.0, 2034.9, 999.1 + 0.6, 48000.0, 46.5, 2073.88, 1017.57 + 0.6, 48000.0, 47.0, 2112.744, 1034.35 + 0.6, 48000.0, 47.5, 2151.535, 1050.3 + 0.6, 48000.0, 48.0, 2190.3, 1066.3 + 0.6, 48000.0, 48.5, 2229.084, 1083.21 + 0.6, 48000.0, 49.0, 2267.931, 1101.9 + 0.6, 48000.0, 49.5, 2306.888, 1123.24 + 0.6, 48000.0, 50.0, 2346.0, 1148.1 + 0.65, 0.0, 0.0, 658.6219, 658.622 + 0.65, 0.0, 22.0, 1500.3, 1624.7 + 0.65, 0.0, 22.5, 1785.208, 1914.08 + 0.65, 0.0, 23.0, 2064.22, 2055.09 + 0.65, 0.0, 23.5, 2338.847, 2077.15 + 0.65, 0.0, 24.0, 2610.6, 2009.7 + 0.65, 0.0, 24.5, 2880.99, 1882.18 + 0.65, 0.0, 25.0, 3151.53, 1724.01 + 0.65, 0.0, 25.5, 3423.729, 1564.64 + 0.65, 0.0, 26.0, 3699.1, 1433.5 + 0.65, 0.0, 26.5, 3994.462, 1634.8 + 0.65, 0.0, 27.0, 4296.893, 1938.9 + 0.65, 0.0, 27.5, 4605.28, 2328.13 + 0.65, 0.0, 28.0, 4918.51, 2784.81 + 0.65, 0.0, 28.5, 5235.47, 3291.26 + 0.65, 0.0, 29.0, 5555.047, 3829.83 + 0.65, 0.0, 29.5, 5876.128, 4382.83 + 0.65, 0.0, 30.0, 6197.6, 4932.6 + 0.65, 0.0, 30.5, 6505.157, 5249.32 + 0.65, 0.0, 31.0, 6812.135, 5547.66 + 0.65, 0.0, 31.5, 7118.679, 5830.16 + 0.65, 0.0, 32.0, 7424.931, 6099.34 + 0.65, 0.0, 32.5, 7731.036, 6357.75 + 0.65, 0.0, 33.0, 8037.137, 6607.91 + 0.65, 0.0, 33.5, 8343.377, 6852.35 + 0.65, 0.0, 34.0, 8649.9, 7093.6 + 0.65, 0.0, 34.5, 8959.121, 7605.46 + 0.65, 0.0, 35.0, 9268.695, 8093.37 + 0.65, 0.0, 35.5, 9578.551, 8534.02 + 0.65, 0.0, 36.0, 9888.615, 8904.11 + 0.65, 0.0, 36.5, 10198.81, 9180.33 + 0.65, 0.0, 37.0, 10509.08, 9339.39 + 0.65, 0.0, 37.5, 10819.33, 9357.98 + 0.65, 0.0, 38.0, 11129.5, 9212.8 + 0.65, 0.0, 38.5, 11439.69, 8669.15 + 0.65, 0.0, 39.0, 11749.56, 8024.73 + 0.65, 0.0, 39.5, 12059.0, 7303.23 + 0.65, 0.0, 40.0, 12367.9, 6528.3 + 0.65, 0.0, 40.5, 12676.43, 5685.23 + 0.65, 0.0, 41.0, 12984.08, 4851.44 + 0.65, 0.0, 41.5, 13290.61, 4065.99 + 0.65, 0.0, 42.0, 13595.8, 3367.9 + 0.65, 0.0, 42.5, 13895.9, 2858.14 + 0.65, 0.0, 43.0, 14195.61, 2489.04 + 0.65, 0.0, 43.5, 14496.11, 2274.87 + 0.65, 0.0, 44.0, 14798.6, 2229.9 + 0.65, 0.0, 44.5, 15110.25, 2502.24 + 0.65, 0.0, 45.0, 15423.84, 2918.78 + 0.65, 0.0, 45.5, 15738.16, 3440.22 + 0.65, 0.0, 46.0, 16052.0, 4027.3 + 0.65, 0.0, 46.5, 16359.23, 4576.33 + 0.65, 0.0, 47.0, 16665.51, 5138.22 + 0.65, 0.0, 47.5, 16971.59, 5699.44 + 0.65, 0.0, 48.0, 17278.2, 6246.5 + 0.65, 0.0, 48.5, 17586.1, 6765.87 + 0.65, 0.0, 49.0, 17896.04, 7244.06 + 0.65, 0.0, 49.5, 18208.75, 7667.54 + 0.65, 0.0, 50.0, 18525.0, 8022.8 + 0.65, 2000.0, 0.0, 616.6478, 616.648 + 0.65, 2000.0, 22.0, -10646.1, -2787.6 + 0.65, 2000.0, 22.5, -12659.68, -3493.53 + 0.65, 2000.0, 23.0, -14653.12, -4153.33 + 0.65, 2000.0, 23.5, -16633.31, -4779.24 + 0.65, 2000.0, 24.0, -18607.1, -5383.5 + 0.65, 2000.0, 24.5, -20581.37, -5978.35 + 0.65, 2000.0, 25.0, -22562.98, -6576.02 + 0.65, 2000.0, 25.5, -24558.8, -7188.76 + 0.65, 2000.0, 26.0, -26575.7, -7828.8 + 0.65, 2000.0, 26.5, -28692.91, -8635.67 + 0.65, 2000.0, 27.0, -30849.07, -9501.6 + 0.65, 2000.0, 27.5, -33038.65, -10417.0 + 0.65, 2000.0, 28.0, -35256.1, -11372.3 + 0.65, 2000.0, 28.5, -37495.89, -12357.9 + 0.65, 2000.0, 29.0, -39752.47, -13364.3 + 0.65, 2000.0, 29.5, -42020.32, -14381.8 + 0.65, 2000.0, 30.0, -44293.9, -15400.9 + 0.65, 2000.0, 30.5, -46509.59, -16275.5 + 0.65, 2000.0, 31.0, -48725.47, -17145.5 + 0.65, 2000.0, 31.5, -50941.51, -18014.3 + 0.65, 2000.0, 32.0, -53157.72, -18885.4 + 0.65, 2000.0, 32.5, -55374.1, -19762.1 + 0.65, 2000.0, 33.0, -57590.62, -20648.0 + 0.65, 2000.0, 33.5, -59807.29, -21546.3 + 0.65, 2000.0, 34.0, -62024.1, -22460.6 + 0.65, 2000.0, 34.5, -64243.15, -23585.7 + 0.65, 2000.0, 35.0, -66462.13, -24715.4 + 0.65, 2000.0, 35.5, -68680.82, -25834.8 + 0.65, 2000.0, 36.0, -70899.02, -26929.0 + 0.65, 2000.0, 36.5, -73116.51, -27983.3 + 0.65, 2000.0, 37.0, -75333.1, -28982.9 + 0.65, 2000.0, 37.5, -77548.56, -29912.8 + 0.65, 2000.0, 38.0, -79762.7, -30758.4 + 0.65, 2000.0, 38.5, -81971.49, -31374.5 + 0.65, 2000.0, 39.0, -84180.51, -31944.2 + 0.65, 2000.0, 39.5, -86390.4, -32481.4 + 0.65, 2000.0, 40.0, -88601.8, -33000.3 + 0.65, 2000.0, 40.5, -90818.62, -33478.8 + 0.65, 2000.0, 41.0, -93036.92, -33981.8 + 0.65, 2000.0, 41.5, -95256.04, -34537.8 + 0.65, 2000.0, 42.0, -97475.3, -35175.5 + 0.65, 2000.0, 42.5, -99690.65, -36020.3 + 0.65, 2000.0, 43.0, -101906.2, -36965.2 + 0.65, 2000.0, 43.5, -104122.5, -38000.1 + 0.65, 2000.0, 44.0, -106340.4, -39114.7 + 0.65, 2000.0, 44.5, -108567.3, -40308.5 + 0.65, 2000.0, 45.0, -110794.3, -41557.9 + 0.65, 2000.0, 45.5, -113019.6, -42849.1 + 0.65, 2000.0, 46.0, -115241.0, -44168.0 + 0.65, 2000.0, 46.5, -117445.8, -45465.8 + 0.65, 2000.0, 47.0, -119647.1, -46777.5 + 0.65, 2000.0, 47.5, -121847.1, -48103.1 + 0.65, 2000.0, 48.0, -124048.1, -49442.5 + 0.65, 2000.0, 48.5, -126252.4, -50795.8 + 0.65, 2000.0, 49.0, -128462.2, -52163.0 + 0.65, 2000.0, 49.5, -130679.8, -53544.1 + 0.65, 2000.0, 50.0, -132907.6, -54939.2 + 0.65, 5000.0, 0.0, 557.6751, 557.675 + 0.65, 5000.0, 22.0, 10863.1, 4690.2 + 0.65, 5000.0, 22.5, 12928.25, 5386.83 + 0.65, 5000.0, 23.0, 14970.92, 6061.97 + 0.65, 5000.0, 23.5, 16998.38, 6723.1 + 0.65, 5000.0, 24.0, 19017.9, 7377.7 + 0.65, 5000.0, 24.5, 21036.77, 8033.23 + 0.65, 5000.0, 25.0, 23062.25, 8697.18 + 0.65, 5000.0, 25.5, 25101.64, 9377.01 + 0.65, 5000.0, 26.0, 27162.2, 10080.2 + 0.65, 5000.0, 26.5, 29327.12, 10888.9 + 0.65, 5000.0, 27.0, 31532.11, 11740.3 + 0.65, 5000.0, 27.5, 33771.43, 12628.8 + 0.65, 5000.0, 28.0, 36039.34, 13549.3 + 0.65, 5000.0, 28.5, 38330.11, 14496.3 + 0.65, 5000.0, 29.0, 40638.0, 15464.6 + 0.65, 5000.0, 29.5, 42957.28, 16448.8 + 0.65, 5000.0, 30.0, 45282.2, 17443.6 + 0.65, 5000.0, 30.5, 47546.89, 18396.4 + 0.65, 5000.0, 31.0, 49811.49, 19353.6 + 0.65, 5000.0, 31.5, 52075.98, 20314.4 + 0.65, 5000.0, 32.0, 54340.36, 21277.9 + 0.65, 5000.0, 32.5, 56604.62, 22243.3 + 0.65, 5000.0, 33.0, 58868.75, 23209.7 + 0.65, 5000.0, 33.5, 61132.75, 24176.4 + 0.65, 5000.0, 34.0, 63396.6, 25142.4 + 0.65, 5000.0, 34.5, 65659.71, 26118.5 + 0.65, 5000.0, 35.0, 67922.72, 27091.2 + 0.65, 5000.0, 35.5, 70185.67, 28058.6 + 0.65, 5000.0, 36.0, 72448.61, 29018.7 + 0.65, 5000.0, 36.5, 74711.58, 29969.6 + 0.65, 5000.0, 37.0, 76974.64, 30909.3 + 0.65, 5000.0, 37.5, 79237.83, 31836.0 + 0.65, 5000.0, 38.0, 81501.2, 32747.6 + 0.65, 5000.0, 38.5, 83765.33, 33631.5 + 0.65, 5000.0, 39.0, 86029.45, 34502.1 + 0.65, 5000.0, 39.5, 88293.5, 35359.8 + 0.65, 5000.0, 40.0, 90557.4, 36205.2 + 0.65, 5000.0, 40.5, 92820.22, 37015.7 + 0.65, 5000.0, 41.0, 95083.09, 37823.9 + 0.65, 5000.0, 41.5, 97346.3, 38639.5 + 0.65, 5000.0, 42.0, 99610.1, 39472.1 + 0.65, 5000.0, 42.5, 101874.8, 40349.0 + 0.65, 5000.0, 43.0, 104140.6, 41255.2 + 0.65, 5000.0, 43.5, 106407.9, 42193.3 + 0.65, 5000.0, 44.0, 108676.8, 43166.1 + 0.65, 5000.0, 44.5, 110953.2, 44189.0 + 0.65, 5000.0, 45.0, 113229.7, 45246.7 + 0.65, 5000.0, 45.5, 115504.2, 46336.5 + 0.65, 5000.0, 46.0, 117774.8, 47456.0 + 0.65, 5000.0, 46.5, 120029.2, 48612.9 + 0.65, 5000.0, 47.0, 122280.0, 49790.2 + 0.65, 5000.0, 47.5, 124529.3, 50981.3 + 0.65, 5000.0, 48.0, 126779.3, 52179.5 + 0.65, 5000.0, 48.5, 129032.3, 53378.1 + 0.65, 5000.0, 49.0, 131290.3, 54570.5 + 0.65, 5000.0, 49.5, 133555.7, 55750.0 + 0.65, 5000.0, 50.0, 135830.6, 56910.0 + 0.65, 10000.0, 0.0, 469.3634, 469.363 + 0.65, 10000.0, 22.0, 795.2, 1026.5 + 0.65, 10000.0, 22.5, 945.2783, 1096.39 + 0.65, 10000.0, 23.0, 1094.198, 1164.11 + 0.65, 10000.0, 23.5, 1242.419, 1230.04 + 0.65, 10000.0, 24.0, 1390.4, 1294.6 + 0.65, 10000.0, 24.5, 1538.599, 1358.17 + 0.65, 10000.0, 25.0, 1687.477, 1421.14 + 0.65, 10000.0, 25.5, 1837.49, 1483.92 + 0.65, 10000.0, 26.0, 1989.1, 1546.9 + 0.65, 10000.0, 26.5, 2147.741, 1614.36 + 0.65, 10000.0, 27.0, 2309.18, 1683.02 + 0.65, 10000.0, 27.5, 2473.022, 1752.63 + 0.65, 10000.0, 28.0, 2638.875, 1822.91 + 0.65, 10000.0, 28.5, 2806.343, 1893.59 + 0.65, 10000.0, 29.0, 2975.033, 1964.39 + 0.65, 10000.0, 29.5, 3144.55, 2035.05 + 0.65, 10000.0, 30.0, 3314.5, 2105.3 + 0.65, 10000.0, 30.5, 3480.451, 2169.96 + 0.65, 10000.0, 31.0, 3646.432, 2234.13 + 0.65, 10000.0, 31.5, 3812.433, 2298.02 + 0.65, 10000.0, 32.0, 3978.444, 2361.8 + 0.65, 10000.0, 32.5, 4144.456, 2425.68 + 0.65, 10000.0, 33.0, 4310.459, 2489.87 + 0.65, 10000.0, 33.5, 4476.443, 2554.54 + 0.65, 10000.0, 34.0, 4642.4, 2619.9 + 0.65, 10000.0, 34.5, 4808.261, 2688.48 + 0.65, 10000.0, 35.0, 4974.081, 2757.91 + 0.65, 10000.0, 35.5, 5139.855, 2828.18 + 0.65, 10000.0, 36.0, 5305.58, 2899.25 + 0.65, 10000.0, 36.5, 5471.251, 2971.11 + 0.65, 10000.0, 37.0, 5636.864, 3043.72 + 0.65, 10000.0, 37.5, 5802.415, 3117.06 + 0.65, 10000.0, 38.0, 5967.9, 3191.1 + 0.65, 10000.0, 38.5, 6133.111, 3269.14 + 0.65, 10000.0, 39.0, 6298.353, 3346.12 + 0.65, 10000.0, 39.5, 6463.669, 3421.26 + 0.65, 10000.0, 40.0, 6629.1, 3493.8 + 0.65, 10000.0, 40.5, 6794.869, 3554.62 + 0.65, 10000.0, 41.0, 6960.763, 3614.65 + 0.65, 10000.0, 41.5, 7126.75, 3676.48 + 0.65, 10000.0, 42.0, 7292.8, 3742.7 + 0.65, 10000.0, 42.5, 7458.729, 3826.26 + 0.65, 10000.0, 43.0, 7624.719, 3915.22 + 0.65, 10000.0, 43.5, 7790.799, 4007.99 + 0.65, 10000.0, 44.0, 7957.0, 4103.0 + 0.65, 10000.0, 44.5, 8123.765, 4194.92 + 0.65, 10000.0, 45.0, 8290.544, 4287.44 + 0.65, 10000.0, 45.5, 8457.201, 4380.49 + 0.65, 10000.0, 46.0, 8623.6, 4474.0 + 0.65, 10000.0, 46.5, 8788.945, 4571.23 + 0.65, 10000.0, 47.0, 8954.025, 4667.44 + 0.65, 10000.0, 47.5, 9118.967, 4761.23 + 0.65, 10000.0, 48.0, 9283.9, 4851.2 + 0.65, 10000.0, 48.5, 9448.952, 4935.95 + 0.65, 10000.0, 49.0, 9614.25, 5014.06 + 0.65, 10000.0, 49.5, 9779.923, 5084.15 + 0.65, 10000.0, 50.0, 9946.1, 5144.8 + 0.65, 15000.0, 0.0, 392.4785, 392.479 + 0.65, 15000.0, 22.0, 731.1, 904.1 + 0.65, 15000.0, 22.5, 869.8977, 962.248 + 0.65, 15000.0, 23.0, 1007.244, 1019.63 + 0.65, 15000.0, 23.5, 1143.618, 1076.47 + 0.65, 15000.0, 24.0, 1279.5, 1133.0 + 0.65, 15000.0, 24.5, 1415.37, 1189.45 + 0.65, 15000.0, 25.0, 1551.706, 1246.05 + 0.65, 15000.0, 25.5, 1688.99, 1303.02 + 0.65, 15000.0, 26.0, 1827.7, 1360.6 + 0.65, 15000.0, 26.5, 1973.344, 1421.33 + 0.65, 15000.0, 27.0, 2121.66, 1483.26 + 0.65, 15000.0, 27.5, 2272.268, 1546.22 + 0.65, 15000.0, 28.0, 2424.785, 1610.04 + 0.65, 15000.0, 28.5, 2578.829, 1674.54 + 0.65, 15000.0, 29.0, 2734.017, 1739.56 + 0.65, 15000.0, 29.5, 2889.968, 1804.94 + 0.65, 15000.0, 30.0, 3046.3, 1870.5 + 0.65, 15000.0, 30.5, 3198.616, 1934.02 + 0.65, 15000.0, 31.0, 3350.93, 1997.57 + 0.65, 15000.0, 31.5, 3503.244, 2061.2 + 0.65, 15000.0, 32.0, 3655.556, 2124.92 + 0.65, 15000.0, 32.5, 3807.868, 2188.76 + 0.65, 15000.0, 33.0, 3960.179, 2252.76 + 0.65, 15000.0, 33.5, 4112.49, 2316.93 + 0.65, 15000.0, 34.0, 4264.8, 2381.3 + 0.65, 15000.0, 34.5, 4417.116, 2445.73 + 0.65, 15000.0, 35.0, 4569.431, 2510.43 + 0.65, 15000.0, 35.5, 4721.746, 2575.45 + 0.65, 15000.0, 36.0, 4874.06, 2640.84 + 0.65, 15000.0, 36.5, 5026.373, 2706.63 + 0.65, 15000.0, 37.0, 5178.684, 2772.88 + 0.65, 15000.0, 37.5, 5330.993, 2839.62 + 0.65, 15000.0, 38.0, 5483.3, 2906.9 + 0.65, 15000.0, 38.5, 5635.596, 2975.33 + 0.65, 15000.0, 39.0, 5787.894, 3044.09 + 0.65, 15000.0, 39.5, 5940.195, 3113.11 + 0.65, 15000.0, 40.0, 6092.5, 3182.3 + 0.65, 15000.0, 40.5, 6244.823, 3251.35 + 0.65, 15000.0, 41.0, 6397.15, 3320.5 + 0.65, 15000.0, 41.5, 6549.477, 3389.78 + 0.65, 15000.0, 42.0, 6701.8, 3459.2 + 0.65, 15000.0, 42.5, 6853.984, 3528.72 + 0.65, 15000.0, 43.0, 7006.212, 3598.43 + 0.65, 15000.0, 43.5, 7158.534, 3668.38 + 0.65, 15000.0, 44.0, 7311.0, 3738.6 + 0.65, 15000.0, 44.5, 7464.14, 3809.43 + 0.65, 15000.0, 45.0, 7617.331, 3880.5 + 0.65, 15000.0, 45.5, 7770.432, 3951.72 + 0.65, 15000.0, 46.0, 7923.3, 4023.0 + 0.65, 15000.0, 46.5, 8075.086, 4093.71 + 0.65, 15000.0, 47.0, 8226.637, 4164.55 + 0.65, 15000.0, 47.5, 8378.095, 4235.67 + 0.65, 15000.0, 48.0, 8529.6, 4307.2 + 0.65, 15000.0, 48.5, 8681.292, 4379.3 + 0.65, 15000.0, 49.0, 8833.312, 4452.1 + 0.65, 15000.0, 49.5, 8985.802, 4525.75 + 0.65, 15000.0, 50.0, 9138.9, 4600.4 + 0.65, 20000.0, 0.0, 325.9025, 325.903 + 0.65, 20000.0, 22.0, 769.0, 815.8 + 0.65, 20000.0, 22.5, 914.9676, 877.023 + 0.65, 20000.0, 23.0, 1059.422, 936.902 + 0.65, 20000.0, 23.5, 1202.865, 995.754 + 0.65, 20000.0, 24.0, 1345.8, 1053.9 + 0.65, 20000.0, 24.5, 1488.729, 1111.66 + 0.65, 20000.0, 25.0, 1632.153, 1169.35 + 0.65, 20000.0, 25.5, 1776.576, 1227.29 + 0.65, 20000.0, 26.0, 1922.5, 1285.8 + 0.65, 20000.0, 26.5, 2075.697, 1348.1 + 0.65, 20000.0, 27.0, 2231.702, 1411.76 + 0.65, 20000.0, 27.5, 2390.111, 1476.63 + 0.65, 20000.0, 28.0, 2550.525, 1542.51 + 0.65, 20000.0, 28.5, 2712.542, 1609.24 + 0.65, 20000.0, 29.0, 2875.761, 1676.63 + 0.65, 20000.0, 29.5, 3039.781, 1744.51 + 0.65, 20000.0, 30.0, 3204.2, 1812.7 + 0.65, 20000.0, 30.5, 3364.399, 1878.58 + 0.65, 20000.0, 31.0, 3524.598, 1944.64 + 0.65, 20000.0, 31.5, 3684.796, 2010.95 + 0.65, 20000.0, 32.0, 3844.994, 2077.56 + 0.65, 20000.0, 32.5, 4005.193, 2144.52 + 0.65, 20000.0, 33.0, 4165.393, 2211.89 + 0.65, 20000.0, 33.5, 4325.595, 2279.74 + 0.65, 20000.0, 34.0, 4485.8, 2348.1 + 0.65, 20000.0, 34.5, 4646.026, 2418.21 + 0.65, 20000.0, 35.0, 4806.253, 2488.84 + 0.65, 20000.0, 35.5, 4966.482, 2559.94 + 0.65, 20000.0, 36.0, 5126.71, 2631.45 + 0.65, 20000.0, 36.5, 5286.937, 2703.32 + 0.65, 20000.0, 37.0, 5447.162, 2775.48 + 0.65, 20000.0, 37.5, 5607.383, 2847.9 + 0.65, 20000.0, 38.0, 5767.6, 2920.5 + 0.65, 20000.0, 38.5, 5927.803, 2992.93 + 0.65, 20000.0, 39.0, 6088.003, 3065.6 + 0.65, 20000.0, 39.5, 6248.202, 3138.52 + 0.65, 20000.0, 40.0, 6408.4, 3211.7 + 0.65, 20000.0, 40.5, 6568.6, 3285.03 + 0.65, 20000.0, 41.0, 6728.8, 3358.7 + 0.65, 20000.0, 41.5, 6889.0, 3432.77 + 0.65, 20000.0, 42.0, 7049.2, 3507.3 + 0.65, 20000.0, 42.5, 7209.271, 3582.56 + 0.65, 20000.0, 43.0, 7369.394, 3658.33 + 0.65, 20000.0, 43.5, 7529.62, 3734.58 + 0.65, 20000.0, 44.0, 7690.0, 3811.3 + 0.65, 20000.0, 44.5, 7851.095, 3887.9 + 0.65, 20000.0, 45.0, 8012.244, 3965.14 + 0.65, 20000.0, 45.5, 8173.296, 4043.24 + 0.65, 20000.0, 46.0, 8334.1, 4122.4 + 0.65, 20000.0, 46.5, 8493.754, 4202.95 + 0.65, 20000.0, 47.0, 8653.156, 4284.91 + 0.65, 20000.0, 47.5, 8812.455, 4368.45 + 0.65, 20000.0, 48.0, 8971.8, 4453.7 + 0.65, 20000.0, 48.5, 9131.338, 4540.83 + 0.65, 20000.0, 49.0, 9291.219, 4629.99 + 0.65, 20000.0, 49.5, 9451.59, 4721.33 + 0.65, 20000.0, 50.0, 9612.6, 4815.0 + 0.65, 25000.0, 0.0, 268.5809, 268.581 + 0.65, 25000.0, 22.0, 623.9, 665.0 + 0.65, 25000.0, 22.5, 742.3381, 712.879 + 0.65, 25000.0, 23.0, 859.5453, 760.055 + 0.65, 25000.0, 23.5, 975.9299, 806.728 + 0.65, 25000.0, 24.0, 1091.9, 853.1 + 0.65, 25000.0, 24.5, 1207.864, 899.372 + 0.65, 25000.0, 25.0, 1324.23, 945.745 + 0.65, 25000.0, 25.5, 1441.406, 992.421 + 0.65, 25000.0, 26.0, 1559.8, 1039.6 + 0.65, 25000.0, 26.5, 1684.103, 1089.36 + 0.65, 25000.0, 27.0, 1810.685, 1140.14 + 0.65, 25000.0, 27.5, 1939.221, 1191.81 + 0.65, 25000.0, 28.0, 2069.385, 1244.24 + 0.65, 25000.0, 28.5, 2200.851, 1297.33 + 0.65, 25000.0, 29.0, 2333.292, 1350.95 + 0.65, 25000.0, 29.5, 2466.384, 1404.98 + 0.65, 25000.0, 30.0, 2599.8, 1459.3 + 0.65, 25000.0, 30.5, 2729.791, 1512.31 + 0.65, 25000.0, 31.0, 2859.78, 1565.5 + 0.65, 25000.0, 31.5, 2989.769, 1618.9 + 0.65, 25000.0, 32.0, 3119.756, 1672.52 + 0.65, 25000.0, 32.5, 3249.743, 1726.4 + 0.65, 25000.0, 33.0, 3379.729, 1780.54 + 0.65, 25000.0, 33.5, 3509.715, 1834.97 + 0.65, 25000.0, 34.0, 3639.7, 1889.7 + 0.65, 25000.0, 34.5, 3769.691, 1945.06 + 0.65, 25000.0, 35.0, 3899.681, 2000.74 + 0.65, 25000.0, 35.5, 4029.671, 2056.73 + 0.65, 25000.0, 36.0, 4159.66, 2113.01 + 0.65, 25000.0, 36.5, 4289.648, 2169.6 + 0.65, 25000.0, 37.0, 4419.634, 2226.46 + 0.65, 25000.0, 37.5, 4549.618, 2283.6 + 0.65, 25000.0, 38.0, 4679.6, 2341.0 + 0.65, 25000.0, 38.5, 4809.576, 2398.67 + 0.65, 25000.0, 39.0, 4939.552, 2456.58 + 0.65, 25000.0, 39.5, 5069.526, 2514.73 + 0.65, 25000.0, 40.0, 5199.5, 2573.1 + 0.65, 25000.0, 40.5, 5329.471, 2631.54 + 0.65, 25000.0, 41.0, 5459.444, 2690.24 + 0.65, 25000.0, 41.5, 5589.42, 2749.25 + 0.65, 25000.0, 42.0, 5719.4, 2808.6 + 0.65, 25000.0, 42.5, 5849.297, 2868.43 + 0.65, 25000.0, 43.0, 5979.237, 2928.66 + 0.65, 25000.0, 43.5, 6109.259, 2989.32 + 0.65, 25000.0, 44.0, 6239.4, 3050.4 + 0.65, 25000.0, 44.5, 6370.088, 3111.66 + 0.65, 25000.0, 45.0, 6500.813, 3173.48 + 0.65, 25000.0, 45.5, 6631.456, 3235.99 + 0.65, 25000.0, 46.0, 6761.9, 3299.3 + 0.65, 25000.0, 46.5, 6891.427, 3363.58 + 0.65, 25000.0, 47.0, 7020.756, 3428.89 + 0.65, 25000.0, 47.5, 7150.007, 3495.33 + 0.65, 25000.0, 48.0, 7279.3, 3563.0 + 0.65, 25000.0, 48.5, 7408.755, 3632.0 + 0.65, 25000.0, 49.0, 7538.494, 3702.43 + 0.65, 25000.0, 49.5, 7668.635, 3774.4 + 0.65, 25000.0, 50.0, 7799.3, 3848.0 + 0.65, 30000.0, 0.0, 219.5335, 219.533 + 0.65, 30000.0, 22.0, 498.3, 540.5 + 0.65, 30000.0, 22.5, 592.9158, 578.079 + 0.65, 30000.0, 23.0, 686.5359, 615.139 + 0.65, 30000.0, 23.5, 779.4881, 651.829 + 0.65, 30000.0, 24.0, 872.1, 688.3 + 0.65, 30000.0, 24.5, 964.6994, 724.702 + 0.65, 30000.0, 25.0, 1057.614, 761.186 + 0.65, 30000.0, 25.5, 1151.172, 797.902 + 0.65, 30000.0, 26.0, 1245.7, 835.0 + 0.65, 30000.0, 26.5, 1344.957, 874.065 + 0.65, 30000.0, 27.0, 1446.036, 913.896 + 0.65, 30000.0, 27.5, 1548.677, 954.396 + 0.65, 30000.0, 28.0, 1652.62, 995.47 + 0.65, 30000.0, 28.5, 1757.604, 1037.02 + 0.65, 30000.0, 29.0, 1863.369, 1078.96 + 0.65, 30000.0, 29.5, 1969.654, 1121.18 + 0.65, 30000.0, 30.0, 2076.2, 1163.6 + 0.65, 30000.0, 30.5, 2180.013, 1204.88 + 0.65, 30000.0, 31.0, 2283.825, 1246.28 + 0.65, 30000.0, 31.5, 2387.638, 1287.82 + 0.65, 30000.0, 32.0, 2491.45, 1329.52 + 0.65, 30000.0, 32.5, 2595.263, 1371.41 + 0.65, 30000.0, 33.0, 2699.075, 1413.5 + 0.65, 30000.0, 33.5, 2802.888, 1455.82 + 0.65, 30000.0, 34.0, 2906.7, 1498.4 + 0.65, 30000.0, 34.5, 3010.516, 1541.57 + 0.65, 30000.0, 35.0, 3114.331, 1585.0 + 0.65, 30000.0, 35.5, 3218.146, 1628.69 + 0.65, 30000.0, 36.0, 3321.96, 1672.62 + 0.65, 30000.0, 36.5, 3425.773, 1716.8 + 0.65, 30000.0, 37.0, 3529.584, 1761.21 + 0.65, 30000.0, 37.5, 3633.393, 1805.85 + 0.65, 30000.0, 38.0, 3737.2, 1850.7 + 0.65, 30000.0, 38.5, 3840.996, 1895.77 + 0.65, 30000.0, 39.0, 3944.794, 1941.04 + 0.65, 30000.0, 39.5, 4048.595, 1986.49 + 0.65, 30000.0, 40.0, 4152.4, 2032.1 + 0.65, 30000.0, 40.5, 4256.223, 2077.76 + 0.65, 30000.0, 41.0, 4360.05, 2123.61 + 0.65, 30000.0, 41.5, 4463.877, 2169.68 + 0.65, 30000.0, 42.0, 4567.7, 2216.0 + 0.65, 30000.0, 42.5, 4671.423, 2262.4 + 0.65, 30000.0, 43.0, 4775.175, 2309.2 + 0.65, 30000.0, 43.5, 4878.989, 2356.53 + 0.65, 30000.0, 44.0, 4982.9, 2404.5 + 0.65, 30000.0, 44.5, 5087.274, 2453.79 + 0.65, 30000.0, 45.0, 5191.681, 2503.74 + 0.65, 30000.0, 45.5, 5296.023, 2554.24 + 0.65, 30000.0, 46.0, 5400.2, 2605.2 + 0.65, 30000.0, 46.5, 5503.619, 2655.89 + 0.65, 30000.0, 47.0, 5606.875, 2707.07 + 0.65, 30000.0, 47.5, 5710.069, 2758.89 + 0.65, 30000.0, 48.0, 5813.3, 2811.5 + 0.65, 30000.0, 48.5, 5916.669, 2865.04 + 0.65, 30000.0, 49.0, 6020.275, 2919.66 + 0.65, 30000.0, 49.5, 6124.219, 2975.49 + 0.65, 30000.0, 50.0, 6228.6, 3032.7 + 0.65, 35000.0, 0.0, 177.8471, 177.847 + 0.65, 35000.0, 22.0, 381.5, 445.8 + 0.65, 35000.0, 22.5, 453.8398, 474.182 + 0.65, 35000.0, 23.0, 525.4563, 502.147 + 0.65, 35000.0, 23.5, 596.5945, 529.814 + 0.65, 35000.0, 24.0, 667.5, 557.3 + 0.65, 35000.0, 24.5, 738.418, 584.724 + 0.65, 35000.0, 25.0, 809.5938, 612.203 + 0.65, 35000.0, 25.5, 881.2727, 639.856 + 0.65, 35000.0, 26.0, 953.7, 667.8 + 0.65, 35000.0, 26.5, 1029.709, 697.269 + 0.65, 35000.0, 27.0, 1107.105, 727.329 + 0.65, 35000.0, 27.5, 1185.69, 757.907 + 0.65, 35000.0, 28.0, 1265.265, 788.93 + 0.65, 35000.0, 28.5, 1345.632, 820.324 + 0.65, 35000.0, 29.0, 1426.592, 852.016 + 0.65, 35000.0, 29.5, 1507.948, 883.932 + 0.65, 35000.0, 30.0, 1589.5, 916.0 + 0.65, 35000.0, 30.5, 1668.964, 947.243 + 0.65, 35000.0, 31.0, 1748.427, 978.577 + 0.65, 35000.0, 31.5, 1827.888, 1010.01 + 0.65, 35000.0, 32.0, 1907.35, 1041.57 + 0.65, 35000.0, 32.5, 1986.812, 1073.25 + 0.65, 35000.0, 33.0, 2066.273, 1105.08 + 0.65, 35000.0, 33.5, 2145.736, 1137.05 + 0.65, 35000.0, 34.0, 2225.2, 1169.2 + 0.65, 35000.0, 34.5, 2304.679, 1201.66 + 0.65, 35000.0, 35.0, 2384.158, 1234.3 + 0.65, 35000.0, 35.5, 2463.637, 1267.13 + 0.65, 35000.0, 36.0, 2543.115, 1300.12 + 0.65, 35000.0, 36.5, 2622.591, 1333.3 + 0.65, 35000.0, 37.0, 2702.065, 1366.66 + 0.65, 35000.0, 37.5, 2781.535, 1400.19 + 0.65, 35000.0, 38.0, 2861.0, 1433.9 + 0.65, 35000.0, 38.5, 2940.447, 1467.82 + 0.65, 35000.0, 39.0, 3019.895, 1501.9 + 0.65, 35000.0, 39.5, 3099.346, 1536.13 + 0.65, 35000.0, 40.0, 3178.8, 1570.5 + 0.65, 35000.0, 40.5, 3258.27, 1604.9 + 0.65, 35000.0, 41.0, 3337.744, 1639.46 + 0.65, 35000.0, 41.5, 3417.221, 1674.22 + 0.65, 35000.0, 42.0, 3496.7, 1709.2 + 0.65, 35000.0, 42.5, 3576.113, 1744.2 + 0.65, 35000.0, 43.0, 3655.55, 1779.59 + 0.65, 35000.0, 43.5, 3735.038, 1815.48 + 0.65, 35000.0, 44.0, 3814.6, 1852.0 + 0.65, 35000.0, 44.5, 3894.513, 1890.11 + 0.65, 35000.0, 45.0, 3974.45, 1928.77 + 0.65, 35000.0, 45.5, 4054.338, 1967.77 + 0.65, 35000.0, 46.0, 4134.1, 2006.9 + 0.65, 35000.0, 46.5, 4213.291, 2045.03 + 0.65, 35000.0, 47.0, 4292.356, 2083.24 + 0.65, 35000.0, 47.5, 4371.368, 2121.71 + 0.65, 35000.0, 48.0, 4450.4, 2160.6 + 0.65, 35000.0, 48.5, 4529.526, 2200.07 + 0.65, 35000.0, 49.0, 4608.819, 2240.28 + 0.65, 35000.0, 49.5, 4688.352, 2281.4 + 0.65, 35000.0, 50.0, 4768.2, 2323.6 + 0.65, 39000.0, 0.0, 147.5083, 147.508 + 0.65, 39000.0, 22.0, 306.4, 387.1 + 0.65, 39000.0, 22.5, 364.5088, 409.579 + 0.65, 39000.0, 23.0, 422.0297, 431.834 + 0.65, 39000.0, 23.5, 479.1607, 453.948 + 0.65, 39000.0, 24.0, 536.1, 476.0 + 0.65, 39000.0, 24.5, 593.0455, 498.071 + 0.65, 39000.0, 25.0, 650.1953, 520.241 + 0.65, 39000.0, 25.5, 707.7475, 542.59 + 0.65, 39000.0, 26.0, 765.9, 565.2 + 0.65, 39000.0, 26.5, 826.9359, 588.934 + 0.65, 39000.0, 27.0, 889.0875, 613.133 + 0.65, 39000.0, 27.5, 952.1953, 637.745 + 0.65, 39000.0, 28.0, 1016.1, 662.715 + 0.65, 39000.0, 28.5, 1080.642, 687.989 + 0.65, 39000.0, 29.0, 1145.663, 713.514 + 0.65, 39000.0, 29.5, 1211.002, 739.236 + 0.65, 39000.0, 30.0, 1276.5, 765.1 + 0.65, 39000.0, 30.5, 1340.325, 790.499 + 0.65, 39000.0, 31.0, 1404.15, 815.985 + 0.65, 39000.0, 31.5, 1467.975, 841.559 + 0.65, 39000.0, 32.0, 1531.8, 867.219 + 0.65, 39000.0, 32.5, 1595.625, 892.964 + 0.65, 39000.0, 33.0, 1659.45, 918.793 + 0.65, 39000.0, 33.5, 1723.275, 944.705 + 0.65, 39000.0, 34.0, 1787.1, 970.7 + 0.65, 39000.0, 34.5, 1850.925, 996.598 + 0.65, 39000.0, 35.0, 1914.75, 1022.59 + 0.65, 39000.0, 35.5, 1978.575, 1048.7 + 0.65, 39000.0, 36.0, 2042.4, 1074.94 + 0.65, 39000.0, 36.5, 2106.225, 1101.32 + 0.65, 39000.0, 37.0, 2170.05, 1127.87 + 0.65, 39000.0, 37.5, 2233.875, 1154.59 + 0.65, 39000.0, 38.0, 2297.7, 1181.5 + 0.65, 39000.0, 38.5, 2361.525, 1208.77 + 0.65, 39000.0, 39.0, 2425.35, 1236.18 + 0.65, 39000.0, 39.5, 2489.175, 1263.73 + 0.65, 39000.0, 40.0, 2553.0, 1291.4 + 0.65, 39000.0, 40.5, 2616.829, 1318.96 + 0.65, 39000.0, 41.0, 2680.656, 1346.68 + 0.65, 39000.0, 41.5, 2744.48, 1374.64 + 0.65, 39000.0, 42.0, 2808.3, 1402.9 + 0.65, 39000.0, 42.5, 2872.051, 1431.73 + 0.65, 39000.0, 43.0, 2935.819, 1460.91 + 0.65, 39000.0, 43.5, 2999.627, 1490.44 + 0.65, 39000.0, 44.0, 3063.5, 1520.3 + 0.65, 39000.0, 44.5, 3127.671, 1550.26 + 0.65, 39000.0, 45.0, 3191.869, 1580.61 + 0.65, 39000.0, 45.5, 3256.032, 1611.43 + 0.65, 39000.0, 46.0, 3320.1, 1642.8 + 0.65, 39000.0, 46.5, 3383.719, 1675.28 + 0.65, 39000.0, 47.0, 3447.238, 1708.26 + 0.65, 39000.0, 47.5, 3510.713, 1741.64 + 0.65, 39000.0, 48.0, 3574.2, 1775.3 + 0.65, 39000.0, 48.5, 3637.756, 1809.12 + 0.65, 39000.0, 49.0, 3701.438, 1842.99 + 0.65, 39000.0, 49.5, 3765.3, 1876.79 + 0.65, 39000.0, 50.0, 3829.4, 1910.4 + 0.65, 43000.0, 0.0, 121.7088, 121.709 + 0.65, 43000.0, 22.0, 244.9, 346.5 + 0.65, 43000.0, 22.5, 291.5543, 361.289 + 0.65, 43000.0, 23.0, 337.7156, 376.886 + 0.65, 43000.0, 23.5, 383.5441, 393.215 + 0.65, 43000.0, 24.0, 429.2, 410.2 + 0.65, 43000.0, 24.5, 474.8434, 427.767 + 0.65, 43000.0, 25.0, 520.6344, 445.839 + 0.65, 43000.0, 25.5, 566.7332, 464.342 + 0.65, 43000.0, 26.0, 613.3, 483.2 + 0.65, 43000.0, 26.5, 662.1656, 501.733 + 0.65, 43000.0, 27.0, 711.915, 520.437 + 0.65, 43000.0, 27.5, 762.4219, 539.338 + 0.65, 43000.0, 28.0, 813.56, 558.465 + 0.65, 43000.0, 28.5, 865.2031, 577.847 + 0.65, 43000.0, 29.0, 917.225, 597.511 + 0.65, 43000.0, 29.5, 969.4994, 617.486 + 0.65, 43000.0, 30.0, 1021.9, 637.8 + 0.65, 43000.0, 30.5, 1072.965, 659.073 + 0.65, 43000.0, 31.0, 1124.03, 680.684 + 0.65, 43000.0, 31.5, 1175.098, 702.607 + 0.65, 43000.0, 32.0, 1226.169, 724.813 + 0.65, 43000.0, 32.5, 1277.243, 747.273 + 0.65, 43000.0, 33.0, 1328.323, 769.959 + 0.65, 43000.0, 33.5, 1379.408, 792.845 + 0.65, 43000.0, 34.0, 1430.5, 815.9 + 0.65, 43000.0, 34.5, 1481.672, 841.815 + 0.65, 43000.0, 35.0, 1532.845, 867.586 + 0.65, 43000.0, 35.5, 1584.015, 892.925 + 0.65, 43000.0, 36.0, 1635.175, 917.545 + 0.65, 43000.0, 36.5, 1686.319, 941.16 + 0.65, 43000.0, 37.0, 1737.442, 963.482 + 0.65, 43000.0, 37.5, 1788.538, 984.224 + 0.65, 43000.0, 38.0, 1839.6, 1003.1 + 0.65, 43000.0, 38.5, 1890.486, 1015.73 + 0.65, 43000.0, 39.0, 1941.398, 1028.04 + 0.65, 43000.0, 39.5, 1992.362, 1040.66 + 0.65, 43000.0, 40.0, 2043.4, 1054.2 + 0.65, 43000.0, 40.5, 2094.729, 1070.11 + 0.65, 43000.0, 41.0, 2146.106, 1087.87 + 0.65, 43000.0, 41.5, 2197.48, 1107.77 + 0.65, 43000.0, 42.0, 2248.8, 1130.1 + 0.65, 43000.0, 42.5, 2299.728, 1157.79 + 0.65, 43000.0, 43.0, 2350.613, 1187.45 + 0.65, 43000.0, 43.5, 2401.516, 1218.34 + 0.65, 43000.0, 44.0, 2452.5, 1249.7 + 0.65, 43000.0, 44.5, 2504.007, 1279.35 + 0.65, 43000.0, 45.0, 2555.569, 1308.54 + 0.65, 43000.0, 45.5, 2607.096, 1337.09 + 0.65, 43000.0, 46.0, 2658.5, 1364.8 + 0.65, 43000.0, 46.5, 2709.273, 1390.14 + 0.65, 43000.0, 47.0, 2759.912, 1414.83 + 0.65, 43000.0, 47.5, 2810.495, 1439.23 + 0.65, 43000.0, 48.0, 2861.1, 1463.7 + 0.65, 43000.0, 48.5, 2911.805, 1488.61 + 0.65, 43000.0, 49.0, 2962.687, 1514.33 + 0.65, 43000.0, 49.5, 3013.827, 1541.2 + 0.65, 43000.0, 50.0, 3065.3, 1569.6 + 0.65, 48000.0, 0.0, 95.70941, 95.7094 + 0.65, 48000.0, 22.0, 192.5, 273.2 + 0.65, 48000.0, 22.5, 229.434, 284.739 + 0.65, 48000.0, 23.0, 265.9031, 296.964 + 0.65, 48000.0, 23.5, 302.0457, 309.807 + 0.65, 48000.0, 24.0, 338.0, 323.2 + 0.65, 48000.0, 24.5, 373.9043, 337.074 + 0.65, 48000.0, 25.0, 409.8969, 351.361 + 0.65, 48000.0, 25.5, 446.116, 365.992 + 0.65, 48000.0, 26.0, 482.7, 380.9 + 0.65, 48000.0, 26.5, 521.209, 395.448 + 0.65, 48000.0, 27.0, 560.4406, 410.103 + 0.65, 48000.0, 27.5, 600.2895, 424.894 + 0.65, 48000.0, 28.0, 640.65, 439.85 + 0.65, 48000.0, 28.5, 681.4168, 455.0 + 0.65, 48000.0, 29.0, 722.4844, 470.372 + 0.65, 48000.0, 29.5, 763.7473, 485.996 + 0.65, 48000.0, 30.0, 805.1, 501.9 + 0.65, 48000.0, 30.5, 845.2969, 518.694 + 0.65, 48000.0, 31.0, 885.4812, 535.771 + 0.65, 48000.0, 31.5, 925.6562, 553.105 + 0.65, 48000.0, 32.0, 965.825, 570.669 + 0.65, 48000.0, 32.5, 1005.991, 588.437 + 0.65, 48000.0, 33.0, 1046.156, 606.382 + 0.65, 48000.0, 33.5, 1086.325, 624.479 + 0.65, 48000.0, 34.0, 1126.5, 642.7 + 0.65, 48000.0, 34.5, 1166.778, 663.054 + 0.65, 48000.0, 35.0, 1207.059, 683.286 + 0.65, 48000.0, 35.5, 1247.339, 703.176 + 0.65, 48000.0, 36.0, 1287.61, 722.505 + 0.65, 48000.0, 36.5, 1327.868, 741.052 + 0.65, 48000.0, 37.0, 1368.106, 758.597 + 0.65, 48000.0, 37.5, 1408.318, 774.919 + 0.65, 48000.0, 38.0, 1448.5, 789.8 + 0.65, 48000.0, 38.5, 1488.489, 799.877 + 0.65, 48000.0, 39.0, 1528.516, 809.7 + 0.65, 48000.0, 39.5, 1568.61, 819.748 + 0.65, 48000.0, 40.0, 1608.8, 830.5 + 0.65, 48000.0, 40.5, 1649.352, 843.023 + 0.65, 48000.0, 41.0, 1689.963, 856.969 + 0.65, 48000.0, 41.5, 1730.567, 872.58 + 0.65, 48000.0, 42.0, 1771.1, 890.1 + 0.65, 48000.0, 42.5, 1811.175, 911.844 + 0.65, 48000.0, 43.0, 1851.175, 935.15 + 0.65, 48000.0, 43.5, 1891.162, 959.431 + 0.65, 48000.0, 44.0, 1931.2, 984.1 + 0.65, 48000.0, 44.5, 1971.647, 1007.49 + 0.65, 48000.0, 45.0, 2012.15, 1030.52 + 0.65, 48000.0, 45.5, 2052.653, 1053.04 + 0.65, 48000.0, 46.0, 2093.1, 1074.9 + 0.65, 48000.0, 46.5, 2133.2, 1094.8 + 0.65, 48000.0, 47.0, 2173.225, 1114.19 + 0.65, 48000.0, 47.5, 2213.212, 1133.35 + 0.65, 48000.0, 48.0, 2253.2, 1152.6 + 0.65, 48000.0, 48.5, 2293.225, 1172.23 + 0.65, 48000.0, 49.0, 2333.325, 1192.54 + 0.65, 48000.0, 49.5, 2373.537, 1213.83 + 0.65, 48000.0, 50.0, 2413.9, 1236.4 + 0.7, 0.0, 0.0, 683.5252, 683.525 + 0.7, 0.0, 22.0, 1626.1, 1791.1 + 0.7, 0.0, 22.5, 1935.238, 2174.38 + 0.7, 0.0, 23.0, 2236.745, 2338.66 + 0.7, 0.0, 23.5, 2532.48, 2327.27 + 0.7, 0.0, 24.0, 2824.3, 2183.5 + 0.7, 0.0, 24.5, 3114.064, 1950.66 + 0.7, 0.0, 25.0, 3403.63, 1672.06 + 0.7, 0.0, 25.5, 3694.856, 1391.0 + 0.7, 0.0, 26.0, 3989.6, 1150.8 + 0.7, 0.0, 26.5, 4308.363, 1397.1 + 0.7, 0.0, 27.0, 4635.425, 1793.86 + 0.7, 0.0, 27.5, 4969.45, 2315.4 + 0.7, 0.0, 28.0, 5309.1, 2936.07 + 0.7, 0.0, 28.5, 5653.038, 3630.18 + 0.7, 0.0, 29.0, 5999.925, 4372.09 + 0.7, 0.0, 29.5, 6348.425, 5136.12 + 0.7, 0.0, 30.0, 6697.2, 5896.6 + 0.7, 0.0, 30.5, 7028.654, 6323.74 + 0.7, 0.0, 31.0, 7359.256, 6724.96 + 0.7, 0.0, 31.5, 7689.218, 7103.56 + 0.7, 0.0, 32.0, 8018.75, 7462.84 + 0.7, 0.0, 32.5, 8348.063, 7806.1 + 0.7, 0.0, 33.0, 8677.369, 8136.63 + 0.7, 0.0, 33.5, 9006.877, 8457.73 + 0.7, 0.0, 34.0, 9336.8, 8772.7 + 0.7, 0.0, 34.5, 9670.665, 9475.44 + 0.7, 0.0, 35.0, 10005.05, 10141.4 + 0.7, 0.0, 35.5, 10339.85, 10736.8 + 0.7, 0.0, 36.0, 10674.96, 11227.6 + 0.7, 0.0, 36.5, 11010.27, 11580.0 + 0.7, 0.0, 37.0, 11345.69, 11760.0 + 0.7, 0.0, 37.5, 11681.1, 11733.8 + 0.7, 0.0, 38.0, 12016.4, 11467.4 + 0.7, 0.0, 38.5, 12351.79, 10618.4 + 0.7, 0.0, 39.0, 12686.71, 9621.43 + 0.7, 0.0, 39.5, 13020.97, 8511.18 + 0.7, 0.0, 40.0, 13354.4, 7322.3 + 0.7, 0.0, 40.5, 13687.18, 6032.77 + 0.7, 0.0, 41.0, 14018.64, 4756.64 + 0.7, 0.0, 41.5, 14348.49, 3551.23 + 0.7, 0.0, 42.0, 14676.4, 2473.9 + 0.7, 0.0, 42.5, 14997.11, 1673.85 + 0.7, 0.0, 43.0, 15317.26, 1079.82 + 0.7, 0.0, 43.5, 15638.49, 712.408 + 0.7, 0.0, 44.0, 15962.5, 592.2 + 0.7, 0.0, 44.5, 16299.24, 935.162 + 0.7, 0.0, 45.0, 16638.77, 1488.38 + 0.7, 0.0, 45.5, 16979.44, 2194.31 + 0.7, 0.0, 46.0, 17319.6, 2995.4 + 0.7, 0.0, 46.5, 17651.04, 3739.79 + 0.7, 0.0, 47.0, 17981.29, 4501.97 + 0.7, 0.0, 47.5, 18311.32, 5262.12 + 0.7, 0.0, 48.0, 18642.1, 6000.4 + 0.7, 0.0, 48.5, 18974.6, 6696.99 + 0.7, 0.0, 49.0, 19309.78, 7332.07 + 0.7, 0.0, 49.5, 19648.63, 7885.82 + 0.7, 0.0, 50.0, 19992.1, 8338.4 + 0.7, 2000.0, 0.0, 639.964, 639.964 + 0.7, 2000.0, 22.0, -16564.6, -4791.6 + 0.7, 2000.0, 22.5, -19697.84, -5894.95 + 0.7, 2000.0, 23.0, -22799.69, -6927.34 + 0.7, 2000.0, 23.5, -25880.85, -7907.66 + 0.7, 2000.0, 24.0, -28952.0, -8854.8 + 0.7, 2000.0, 24.5, -32023.85, -9787.64 + 0.7, 2000.0, 25.0, -35107.08, -10725.1 + 0.7, 2000.0, 25.5, -38212.4, -11685.9 + 0.7, 2000.0, 26.0, -41350.5, -12689.2 + 0.7, 2000.0, 26.5, -44644.71, -13951.1 + 0.7, 2000.0, 27.0, -47999.52, -15304.3 + 0.7, 2000.0, 27.5, -51406.32, -16734.1 + 0.7, 2000.0, 28.0, -54856.49, -18225.3 + 0.7, 2000.0, 28.5, -58341.42, -19763.1 + 0.7, 2000.0, 29.0, -61852.5, -21332.5 + 0.7, 2000.0, 29.5, -65381.09, -22918.6 + 0.7, 2000.0, 30.0, -68918.6, -24506.4 + 0.7, 2000.0, 30.5, -72366.06, -25867.8 + 0.7, 2000.0, 31.0, -75813.8, -27221.3 + 0.7, 2000.0, 31.5, -79261.82, -28572.3 + 0.7, 2000.0, 32.0, -82710.09, -29926.1 + 0.7, 2000.0, 32.5, -86158.62, -31288.1 + 0.7, 2000.0, 33.0, -89607.39, -32663.6 + 0.7, 2000.0, 33.5, -93056.39, -34058.0 + 0.7, 2000.0, 34.0, -96505.6, -35476.6 + 0.7, 2000.0, 34.5, -99958.32, -37222.5 + 0.7, 2000.0, 35.0, -103410.9, -38975.0 + 0.7, 2000.0, 35.5, -106863.1, -40711.0 + 0.7, 2000.0, 36.0, -110314.5, -42407.7 + 0.7, 2000.0, 36.5, -113764.8, -44041.9 + 0.7, 2000.0, 37.0, -117213.6, -45590.7 + 0.7, 2000.0, 37.5, -120660.7, -47031.1 + 0.7, 2000.0, 38.0, -124105.8, -48340.1 + 0.7, 2000.0, 38.5, -127542.5, -49291.9 + 0.7, 2000.0, 39.0, -130979.6, -50171.4 + 0.7, 2000.0, 39.5, -134418.0, -51000.7 + 0.7, 2000.0, 40.0, -137858.8, -51801.9 + 0.7, 2000.0, 40.5, -141308.1, -52539.9 + 0.7, 2000.0, 41.0, -144759.6, -53316.8 + 0.7, 2000.0, 41.5, -148212.4, -54177.4 + 0.7, 2000.0, 42.0, -151665.5, -55166.6 + 0.7, 2000.0, 42.5, -155112.4, -56482.0 + 0.7, 2000.0, 43.0, -158559.6, -57954.9 + 0.7, 2000.0, 43.5, -162008.1, -59568.9 + 0.7, 2000.0, 44.0, -165459.0, -61308.1 + 0.7, 2000.0, 44.5, -168923.9, -63170.9 + 0.7, 2000.0, 45.0, -172389.1, -65120.6 + 0.7, 2000.0, 45.5, -175851.5, -67135.2 + 0.7, 2000.0, 46.0, -179307.9, -69192.6 + 0.7, 2000.0, 46.5, -182738.5, -71215.5 + 0.7, 2000.0, 47.0, -186163.5, -73259.2 + 0.7, 2000.0, 47.5, -189586.5, -75324.0 + 0.7, 2000.0, 48.0, -193011.1, -77409.9 + 0.7, 2000.0, 48.5, -196440.8, -79517.0 + 0.7, 2000.0, 49.0, -199879.2, -81645.5 + 0.7, 2000.0, 49.5, -203329.8, -83795.5 + 0.7, 2000.0, 50.0, -206796.2, -85967.0 + 0.7, 5000.0, 0.0, 578.7615, 578.761 + 0.7, 5000.0, 22.0, 17794.2, 7200.2 + 0.7, 5000.0, 22.5, 21177.13, 8332.73 + 0.7, 5000.0, 23.0, 24523.17, 9430.35 + 0.7, 5000.0, 23.5, 27844.25, 10505.4 + 0.7, 5000.0, 24.0, 31152.3, 11570.0 + 0.7, 5000.0, 24.5, 34459.25, 12636.6 + 0.7, 5000.0, 25.0, 37777.03, 13717.3 + 0.7, 5000.0, 25.5, 41117.57, 14824.6 + 0.7, 5000.0, 26.0, 44492.8, 15970.6 + 0.7, 5000.0, 26.5, 48039.08, 17290.0 + 0.7, 5000.0, 27.0, 51651.01, 18679.6 + 0.7, 5000.0, 27.5, 55319.2, 20130.9 + 0.7, 5000.0, 28.0, 59034.24, 21635.1 + 0.7, 5000.0, 28.5, 62786.73, 23183.5 + 0.7, 5000.0, 29.0, 66567.27, 24767.4 + 0.7, 5000.0, 29.5, 70366.46, 26378.1 + 0.7, 5000.0, 30.0, 74174.9, 28006.9 + 0.7, 5000.0, 30.5, 77884.58, 29569.3 + 0.7, 5000.0, 31.0, 81594.1, 31139.6 + 0.7, 5000.0, 31.5, 85303.43, 32716.4 + 0.7, 5000.0, 32.0, 89012.58, 34298.3 + 0.7, 5000.0, 32.5, 92721.52, 35883.6 + 0.7, 5000.0, 33.0, 96430.24, 37471.0 + 0.7, 5000.0, 33.5, 100138.7, 39059.0 + 0.7, 5000.0, 34.0, 103847.0, 40646.1 + 0.7, 5000.0, 34.5, 107554.1, 42251.4 + 0.7, 5000.0, 35.0, 111260.9, 43850.8 + 0.7, 5000.0, 35.5, 114967.7, 45441.1 + 0.7, 5000.0, 36.0, 118674.5, 47018.7 + 0.7, 5000.0, 36.5, 122381.4, 48580.2 + 0.7, 5000.0, 37.0, 126088.4, 50122.3 + 0.7, 5000.0, 37.5, 129795.6, 51641.4 + 0.7, 5000.0, 38.0, 133503.1, 53134.2 + 0.7, 5000.0, 38.5, 137211.9, 54576.4 + 0.7, 5000.0, 39.0, 140920.7, 55996.2 + 0.7, 5000.0, 39.5, 144629.4, 57394.8 + 0.7, 5000.0, 40.0, 148337.8, 58773.4 + 0.7, 5000.0, 40.5, 152044.3, 60096.0 + 0.7, 5000.0, 41.0, 155750.9, 61415.9 + 0.7, 5000.0, 41.5, 159458.0, 62749.0 + 0.7, 5000.0, 42.0, 163166.1, 64111.6 + 0.7, 5000.0, 42.5, 166875.9, 65549.5 + 0.7, 5000.0, 43.0, 170587.6, 67036.9 + 0.7, 5000.0, 43.5, 174301.6, 68578.1 + 0.7, 5000.0, 44.0, 178018.4, 70177.1 + 0.7, 5000.0, 44.5, 181747.3, 71858.9 + 0.7, 5000.0, 45.0, 185476.3, 73598.5 + 0.7, 5000.0, 45.5, 189202.0, 75391.8 + 0.7, 5000.0, 46.0, 192921.3, 77234.6 + 0.7, 5000.0, 46.5, 196614.1, 79140.8 + 0.7, 5000.0, 47.0, 200300.9, 81081.0 + 0.7, 5000.0, 47.5, 203985.3, 83043.8 + 0.7, 5000.0, 48.0, 207670.9, 85018.0 + 0.7, 5000.0, 48.5, 211361.3, 86992.2 + 0.7, 5000.0, 49.0, 215060.1, 88954.9 + 0.7, 5000.0, 49.5, 218770.9, 90895.0 + 0.7, 5000.0, 50.0, 222497.2, 92801.0 + 0.7, 10000.0, 0.0, 487.1105, 487.111 + 0.7, 10000.0, 22.0, 758.4, 1064.4 + 0.7, 10000.0, 22.5, 900.393, 1145.99 + 0.7, 10000.0, 23.0, 1041.819, 1221.07 + 0.7, 10000.0, 23.5, 1183.035, 1290.67 + 0.7, 10000.0, 24.0, 1324.4, 1355.8 + 0.7, 10000.0, 24.5, 1466.271, 1417.5 + 0.7, 10000.0, 25.0, 1609.006, 1476.8 + 0.7, 10000.0, 25.5, 1752.963, 1534.72 + 0.7, 10000.0, 26.0, 1898.5, 1592.3 + 0.7, 10000.0, 26.5, 2050.098, 1660.6 + 0.7, 10000.0, 27.0, 2204.226, 1731.18 + 0.7, 10000.0, 27.5, 2360.537, 1803.34 + 0.7, 10000.0, 28.0, 2518.68, 1876.4 + 0.7, 10000.0, 28.5, 2678.307, 1949.66 + 0.7, 10000.0, 29.0, 2839.069, 2022.43 + 0.7, 10000.0, 29.5, 3000.616, 2094.01 + 0.7, 10000.0, 30.0, 3162.6, 2163.7 + 0.7, 10000.0, 30.5, 3321.234, 2217.38 + 0.7, 10000.0, 31.0, 3479.934, 2269.06 + 0.7, 10000.0, 31.5, 3638.677, 2319.34 + 0.7, 10000.0, 32.0, 3797.444, 2368.81 + 0.7, 10000.0, 32.5, 3956.211, 2418.04 + 0.7, 10000.0, 33.0, 4114.957, 2467.62 + 0.7, 10000.0, 33.5, 4273.661, 2518.15 + 0.7, 10000.0, 34.0, 4432.3, 2570.2 + 0.7, 10000.0, 34.5, 4590.707, 2632.18 + 0.7, 10000.0, 35.0, 4749.02, 2696.12 + 0.7, 10000.0, 35.5, 4907.232, 2761.85 + 0.7, 10000.0, 36.0, 5065.335, 2829.22 + 0.7, 10000.0, 36.5, 5223.321, 2898.07 + 0.7, 10000.0, 37.0, 5381.182, 2968.24 + 0.7, 10000.0, 37.5, 5538.911, 3039.57 + 0.7, 10000.0, 38.0, 5696.5, 3111.9 + 0.7, 10000.0, 38.5, 5853.495, 3192.03 + 0.7, 10000.0, 39.0, 6010.566, 3269.24 + 0.7, 10000.0, 39.5, 6167.804, 3341.83 + 0.7, 10000.0, 40.0, 6325.3, 3408.1 + 0.7, 10000.0, 40.5, 6483.559, 3446.86 + 0.7, 10000.0, 41.0, 6642.094, 3483.69 + 0.7, 10000.0, 41.5, 6800.832, 3524.67 + 0.7, 10000.0, 42.0, 6959.7, 3575.9 + 0.7, 10000.0, 42.5, 7118.425, 3668.18 + 0.7, 10000.0, 43.0, 7277.213, 3773.0 + 0.7, 10000.0, 43.5, 7436.069, 3886.57 + 0.7, 10000.0, 44.0, 7595.0, 4005.1 + 0.7, 10000.0, 44.5, 7754.294, 4115.36 + 0.7, 10000.0, 45.0, 7913.562, 4226.77 + 0.7, 10000.0, 45.5, 8072.7, 4339.29 + 0.7, 10000.0, 46.0, 8231.6, 4452.9 + 0.7, 10000.0, 46.5, 8389.688, 4575.8 + 0.7, 10000.0, 47.0, 8547.513, 4696.46 + 0.7, 10000.0, 47.5, 8705.156, 4811.57 + 0.7, 10000.0, 48.0, 8862.7, 4917.8 + 0.7, 10000.0, 48.5, 9020.225, 5011.85 + 0.7, 10000.0, 49.0, 9177.813, 5090.41 + 0.7, 10000.0, 49.5, 9335.544, 5150.17 + 0.7, 10000.0, 50.0, 9493.5, 5187.8 + 0.7, 15000.0, 0.0, 407.3186, 407.319 + 0.7, 15000.0, 22.0, 709.5, 971.6 + 0.7, 15000.0, 22.5, 844.1012, 1027.85 + 0.7, 15000.0, 23.0, 977.3281, 1084.23 + 0.7, 15000.0, 23.5, 1109.641, 1140.85 + 0.7, 15000.0, 24.0, 1241.5, 1197.8 + 0.7, 15000.0, 24.5, 1373.365, 1255.17 + 0.7, 15000.0, 25.0, 1505.697, 1313.04 + 0.7, 15000.0, 25.5, 1638.955, 1371.52 + 0.7, 15000.0, 26.0, 1773.6, 1430.7 + 0.7, 15000.0, 26.5, 1914.926, 1491.96 + 0.7, 15000.0, 27.0, 2058.836, 1554.17 + 0.7, 15000.0, 27.5, 2204.96, 1617.21 + 0.7, 15000.0, 28.0, 2352.93, 1680.95 + 0.7, 15000.0, 28.5, 2502.378, 1745.26 + 0.7, 15000.0, 29.0, 2652.934, 1810.0 + 0.7, 15000.0, 29.5, 2804.231, 1875.06 + 0.7, 15000.0, 30.0, 2955.9, 1940.3 + 0.7, 15000.0, 30.5, 3103.71, 2004.14 + 0.7, 15000.0, 31.0, 3251.522, 2068.04 + 0.7, 15000.0, 31.5, 3399.336, 2132.01 + 0.7, 15000.0, 32.0, 3547.15, 2196.06 + 0.7, 15000.0, 32.5, 3694.964, 2260.21 + 0.7, 15000.0, 33.0, 3842.778, 2324.46 + 0.7, 15000.0, 33.5, 3990.59, 2388.82 + 0.7, 15000.0, 34.0, 4138.4, 2453.3 + 0.7, 15000.0, 34.5, 4286.19, 2517.69 + 0.7, 15000.0, 35.0, 4433.978, 2582.24 + 0.7, 15000.0, 35.5, 4581.764, 2646.99 + 0.7, 15000.0, 36.0, 4729.55, 2711.96 + 0.7, 15000.0, 36.5, 4877.336, 2777.19 + 0.7, 15000.0, 37.0, 5025.122, 2842.7 + 0.7, 15000.0, 37.5, 5172.91, 2908.52 + 0.7, 15000.0, 38.0, 5320.7, 2974.7 + 0.7, 15000.0, 38.5, 5468.499, 3041.26 + 0.7, 15000.0, 39.0, 5616.298, 3108.23 + 0.7, 15000.0, 39.5, 5764.099, 3175.63 + 0.7, 15000.0, 40.0, 5911.9, 3243.5 + 0.7, 15000.0, 40.5, 6059.7, 3312.11 + 0.7, 15000.0, 41.0, 6207.5, 3381.14 + 0.7, 15000.0, 41.5, 6355.3, 3450.52 + 0.7, 15000.0, 42.0, 6503.1, 3520.2 + 0.7, 15000.0, 42.5, 6650.783, 3589.89 + 0.7, 15000.0, 43.0, 6798.512, 3659.81 + 0.7, 15000.0, 43.5, 6946.336, 3729.98 + 0.7, 15000.0, 44.0, 7094.3, 3800.4 + 0.7, 15000.0, 44.5, 7242.924, 3871.24 + 0.7, 15000.0, 45.0, 7391.594, 3942.29 + 0.7, 15000.0, 45.5, 7540.166, 4013.53 + 0.7, 15000.0, 46.0, 7688.5, 4084.9 + 0.7, 15000.0, 46.5, 7835.734, 4156.03 + 0.7, 15000.0, 47.0, 7982.731, 4227.34 + 0.7, 15000.0, 47.5, 8129.638, 4298.9 + 0.7, 15000.0, 48.0, 8276.6, 4370.8 + 0.7, 15000.0, 48.5, 8423.762, 4443.13 + 0.7, 15000.0, 49.0, 8571.269, 4515.96 + 0.7, 15000.0, 49.5, 8719.266, 4589.39 + 0.7, 15000.0, 50.0, 8867.9, 4663.5 + 0.7, 20000.0, 0.0, 338.2253, 338.225 + 0.7, 20000.0, 22.0, 765.7, 882.1 + 0.7, 20000.0, 22.5, 911.0357, 942.84 + 0.7, 20000.0, 23.0, 1054.864, 1002.93 + 0.7, 20000.0, 23.5, 1197.685, 1062.61 + 0.7, 20000.0, 24.0, 1340.0, 1122.1 + 0.7, 20000.0, 24.5, 1482.308, 1181.63 + 0.7, 20000.0, 25.0, 1625.111, 1241.44 + 0.7, 20000.0, 25.5, 1768.908, 1301.75 + 0.7, 20000.0, 26.0, 1914.2, 1362.8 + 0.7, 20000.0, 26.5, 2066.736, 1427.14 + 0.7, 20000.0, 27.0, 2222.068, 1492.8 + 0.7, 20000.0, 27.5, 2379.795, 1559.62 + 0.7, 20000.0, 28.0, 2539.52, 1627.44 + 0.7, 20000.0, 28.5, 2700.842, 1696.07 + 0.7, 20000.0, 29.0, 2863.363, 1765.35 + 0.7, 20000.0, 29.5, 3026.682, 1835.12 + 0.7, 20000.0, 30.0, 3190.4, 1905.2 + 0.7, 20000.0, 30.5, 3349.927, 1973.24 + 0.7, 20000.0, 31.0, 3509.454, 2041.47 + 0.7, 20000.0, 31.5, 3668.98, 2109.92 + 0.7, 20000.0, 32.0, 3828.506, 2178.64 + 0.7, 20000.0, 32.5, 3988.031, 2247.65 + 0.7, 20000.0, 33.0, 4147.555, 2317.01 + 0.7, 20000.0, 33.5, 4307.078, 2386.75 + 0.7, 20000.0, 34.0, 4466.6, 2456.9 + 0.7, 20000.0, 34.5, 4626.112, 2528.03 + 0.7, 20000.0, 35.0, 4785.623, 2599.61 + 0.7, 20000.0, 35.5, 4945.134, 2671.63 + 0.7, 20000.0, 36.0, 5104.645, 2744.08 + 0.7, 20000.0, 36.5, 5264.156, 2816.93 + 0.7, 20000.0, 37.0, 5423.669, 2890.2 + 0.7, 20000.0, 37.5, 5583.183, 2963.86 + 0.7, 20000.0, 38.0, 5742.7, 3037.9 + 0.7, 20000.0, 38.5, 5902.224, 3112.41 + 0.7, 20000.0, 39.0, 6061.748, 3187.24 + 0.7, 20000.0, 39.5, 6221.274, 3262.34 + 0.7, 20000.0, 40.0, 6380.8, 3337.7 + 0.7, 20000.0, 40.5, 6540.325, 3413.01 + 0.7, 20000.0, 41.0, 6699.85, 3488.61 + 0.7, 20000.0, 41.5, 6859.375, 3564.58 + 0.7, 20000.0, 42.0, 7018.9, 3641.0 + 0.7, 20000.0, 42.5, 7178.3, 3717.96 + 0.7, 20000.0, 43.0, 7337.75, 3795.51 + 0.7, 20000.0, 43.5, 7497.3, 3873.74 + 0.7, 20000.0, 44.0, 7657.0, 3952.7 + 0.7, 20000.0, 44.5, 7817.404, 4032.35 + 0.7, 20000.0, 45.0, 7977.856, 4112.94 + 0.7, 20000.0, 45.5, 8138.205, 4194.58 + 0.7, 20000.0, 46.0, 8298.3, 4277.4 + 0.7, 20000.0, 46.5, 8457.223, 4361.72 + 0.7, 20000.0, 47.0, 8615.894, 4447.39 + 0.7, 20000.0, 47.5, 8774.468, 4534.43 + 0.7, 20000.0, 48.0, 8933.1, 4622.9 + 0.7, 20000.0, 48.5, 9091.945, 4712.83 + 0.7, 20000.0, 49.0, 9251.156, 4804.26 + 0.7, 20000.0, 49.5, 9410.89, 4897.24 + 0.7, 20000.0, 50.0, 9571.3, 4991.8 + 0.7, 25000.0, 0.0, 278.7363, 278.736 + 0.7, 25000.0, 22.0, 623.2, 716.6 + 0.7, 25000.0, 22.5, 741.432, 765.63 + 0.7, 25000.0, 23.0, 858.4563, 814.137 + 0.7, 25000.0, 23.5, 974.6773, 862.302 + 0.7, 25000.0, 24.0, 1090.5, 910.3 + 0.7, 25000.0, 24.5, 1206.329, 958.311 + 0.7, 25000.0, 25.0, 1322.569, 1006.51 + 0.7, 25000.0, 25.5, 1439.624, 1055.08 + 0.7, 25000.0, 26.0, 1557.9, 1104.2 + 0.7, 25000.0, 26.5, 1682.057, 1155.81 + 0.7, 25000.0, 27.0, 1808.487, 1208.43 + 0.7, 25000.0, 27.5, 1936.864, 1261.92 + 0.7, 25000.0, 28.0, 2066.865, 1316.17 + 0.7, 25000.0, 28.5, 2198.164, 1371.05 + 0.7, 25000.0, 29.0, 2330.436, 1426.43 + 0.7, 25000.0, 29.5, 2463.356, 1482.19 + 0.7, 25000.0, 30.0, 2596.6, 1538.2 + 0.7, 25000.0, 30.5, 2726.428, 1592.78 + 0.7, 25000.0, 31.0, 2856.255, 1647.52 + 0.7, 25000.0, 31.5, 2986.081, 1702.43 + 0.7, 25000.0, 32.0, 3115.906, 1757.54 + 0.7, 25000.0, 32.5, 3245.73, 1812.87 + 0.7, 25000.0, 33.0, 3375.554, 1868.44 + 0.7, 25000.0, 33.5, 3505.377, 1924.27 + 0.7, 25000.0, 34.0, 3635.2, 1980.4 + 0.7, 25000.0, 34.5, 3765.025, 2037.11 + 0.7, 25000.0, 35.0, 3894.85, 2094.14 + 0.7, 25000.0, 35.5, 4024.675, 2151.47 + 0.7, 25000.0, 36.0, 4154.5, 2209.1 + 0.7, 25000.0, 36.5, 4284.325, 2267.03 + 0.7, 25000.0, 37.0, 4414.15, 2325.26 + 0.7, 25000.0, 37.5, 4543.975, 2383.79 + 0.7, 25000.0, 38.0, 4673.8, 2442.6 + 0.7, 25000.0, 38.5, 4803.625, 2501.81 + 0.7, 25000.0, 39.0, 4933.45, 2561.24 + 0.7, 25000.0, 39.5, 5063.275, 2620.88 + 0.7, 25000.0, 40.0, 5193.1, 2680.7 + 0.7, 25000.0, 40.5, 5322.925, 2740.26 + 0.7, 25000.0, 41.0, 5452.75, 2800.1 + 0.7, 25000.0, 41.5, 5582.575, 2860.37 + 0.7, 25000.0, 42.0, 5712.4, 2921.2 + 0.7, 25000.0, 42.5, 5842.12, 2983.24 + 0.7, 25000.0, 43.0, 5971.881, 3045.91 + 0.7, 25000.0, 43.5, 6101.727, 3109.15 + 0.7, 25000.0, 44.0, 6231.7, 3172.9 + 0.7, 25000.0, 44.5, 6362.259, 3236.71 + 0.7, 25000.0, 45.0, 6492.862, 3301.05 + 0.7, 25000.0, 45.5, 6623.384, 3366.02 + 0.7, 25000.0, 46.0, 6753.7, 3431.7 + 0.7, 25000.0, 46.5, 6883.063, 3498.07 + 0.7, 25000.0, 47.0, 7012.219, 3565.38 + 0.7, 25000.0, 47.5, 7141.29, 3633.78 + 0.7, 25000.0, 48.0, 7270.4, 3703.4 + 0.7, 25000.0, 48.5, 7399.673, 3774.38 + 0.7, 25000.0, 49.0, 7529.231, 3846.87 + 0.7, 25000.0, 49.5, 7659.199, 3920.99 + 0.7, 25000.0, 50.0, 7789.7, 3996.9 + 0.7, 30000.0, 0.0, 227.8343, 227.834 + 0.7, 30000.0, 22.0, 498.9, 581.1 + 0.7, 30000.0, 22.5, 593.601, 620.15 + 0.7, 30000.0, 23.0, 687.3172, 658.609 + 0.7, 30000.0, 23.5, 780.3748, 696.639 + 0.7, 30000.0, 24.0, 873.1, 734.4 + 0.7, 30000.0, 24.5, 965.8189, 772.055 + 0.7, 30000.0, 25.0, 1058.858, 809.766 + 0.7, 30000.0, 25.5, 1152.543, 847.693 + 0.7, 30000.0, 26.0, 1247.2, 886.0 + 0.7, 30000.0, 26.5, 1346.574, 926.35 + 0.7, 30000.0, 27.0, 1447.767, 967.488 + 0.7, 30000.0, 27.5, 1550.521, 1009.32 + 0.7, 30000.0, 28.0, 1654.575, 1051.75 + 0.7, 30000.0, 28.5, 1759.67, 1094.67 + 0.7, 30000.0, 29.0, 1865.545, 1138.0 + 0.7, 30000.0, 29.5, 1971.942, 1181.65 + 0.7, 30000.0, 30.0, 2078.6, 1225.5 + 0.7, 30000.0, 30.5, 2182.536, 1268.29 + 0.7, 30000.0, 31.0, 2286.473, 1311.22 + 0.7, 30000.0, 31.5, 2390.412, 1354.29 + 0.7, 30000.0, 32.0, 2494.35, 1397.54 + 0.7, 30000.0, 32.5, 2598.288, 1440.96 + 0.7, 30000.0, 33.0, 2702.227, 1484.59 + 0.7, 30000.0, 33.5, 2806.164, 1528.43 + 0.7, 30000.0, 34.0, 2910.1, 1572.5 + 0.7, 30000.0, 34.5, 3014.021, 1617.01 + 0.7, 30000.0, 35.0, 3117.942, 1661.77 + 0.7, 30000.0, 35.5, 3221.863, 1706.78 + 0.7, 30000.0, 36.0, 3325.785, 1752.02 + 0.7, 30000.0, 36.5, 3429.709, 1797.51 + 0.7, 30000.0, 37.0, 3533.635, 1843.24 + 0.7, 30000.0, 37.5, 3637.565, 1889.2 + 0.7, 30000.0, 38.0, 3741.5, 1935.4 + 0.7, 30000.0, 38.5, 3845.453, 1981.81 + 0.7, 30000.0, 39.0, 3949.405, 2028.46 + 0.7, 30000.0, 39.5, 4053.354, 2075.36 + 0.7, 30000.0, 40.0, 4157.3, 2122.5 + 0.7, 30000.0, 40.5, 4261.23, 2169.77 + 0.7, 30000.0, 41.0, 4365.156, 2217.34 + 0.7, 30000.0, 41.5, 4469.079, 2265.26 + 0.7, 30000.0, 42.0, 4573.0, 2313.6 + 0.7, 30000.0, 42.5, 4676.847, 2362.68 + 0.7, 30000.0, 43.0, 4780.725, 2412.16 + 0.7, 30000.0, 43.5, 4884.666, 2461.99 + 0.7, 30000.0, 44.0, 4988.7, 2512.1 + 0.7, 30000.0, 44.5, 5093.168, 2562.03 + 0.7, 30000.0, 45.0, 5197.669, 2612.29 + 0.7, 30000.0, 45.5, 5302.11, 2662.98 + 0.7, 30000.0, 46.0, 5406.4, 2714.2 + 0.7, 30000.0, 46.5, 5509.993, 2766.05 + 0.7, 30000.0, 47.0, 5613.431, 2818.64 + 0.7, 30000.0, 47.5, 5716.804, 2872.05 + 0.7, 30000.0, 48.0, 5820.2, 2926.4 + 0.7, 30000.0, 48.5, 5923.709, 2981.78 + 0.7, 30000.0, 49.0, 6027.419, 3038.29 + 0.7, 30000.0, 49.5, 6131.42, 3096.03 + 0.7, 30000.0, 50.0, 6235.8, 3155.1 + 0.7, 35000.0, 0.0, 184.5717, 184.572 + 0.7, 35000.0, 22.0, 382.9, 478.4 + 0.7, 35000.0, 22.5, 455.5709, 508.226 + 0.7, 35000.0, 23.0, 527.4953, 537.531 + 0.7, 35000.0, 23.5, 598.9221, 566.446 + 0.7, 35000.0, 24.0, 670.1, 595.1 + 0.7, 35000.0, 24.5, 741.2779, 623.623 + 0.7, 35000.0, 25.0, 812.7047, 652.144 + 0.7, 35000.0, 25.5, 884.6291, 680.793 + 0.7, 35000.0, 26.0, 957.3, 709.7 + 0.7, 35000.0, 26.5, 1033.578, 740.15 + 0.7, 35000.0, 27.0, 1111.248, 771.183 + 0.7, 35000.0, 27.5, 1190.114, 802.731 + 0.7, 35000.0, 28.0, 1269.975, 834.725 + 0.7, 35000.0, 28.5, 1350.633, 867.097 + 0.7, 35000.0, 29.0, 1431.889, 899.78 + 0.7, 35000.0, 29.5, 1513.544, 932.703 + 0.7, 35000.0, 30.0, 1595.4, 965.8 + 0.7, 35000.0, 30.5, 1675.174, 998.206 + 0.7, 35000.0, 31.0, 1754.948, 1030.72 + 0.7, 35000.0, 31.5, 1834.724, 1063.36 + 0.7, 35000.0, 32.0, 1914.5, 1096.12 + 0.7, 35000.0, 32.5, 1994.276, 1129.02 + 0.7, 35000.0, 33.0, 2074.052, 1162.06 + 0.7, 35000.0, 33.5, 2153.826, 1195.25 + 0.7, 35000.0, 34.0, 2233.6, 1228.6 + 0.7, 35000.0, 34.5, 2313.356, 1262.14 + 0.7, 35000.0, 35.0, 2393.111, 1295.85 + 0.7, 35000.0, 35.5, 2472.867, 1329.73 + 0.7, 35000.0, 36.0, 2552.625, 1363.8 + 0.7, 35000.0, 36.5, 2632.386, 1398.04 + 0.7, 35000.0, 37.0, 2712.152, 1432.47 + 0.7, 35000.0, 37.5, 2791.922, 1467.09 + 0.7, 35000.0, 38.0, 2871.7, 1501.9 + 0.7, 35000.0, 38.5, 2951.506, 1536.58 + 0.7, 35000.0, 39.0, 3031.311, 1571.64 + 0.7, 35000.0, 39.5, 3111.11, 1607.15 + 0.7, 35000.0, 40.0, 3190.9, 1643.2 + 0.7, 35000.0, 40.5, 3270.657, 1680.53 + 0.7, 35000.0, 41.0, 3350.406, 1718.28 + 0.7, 35000.0, 41.5, 3430.152, 1756.27 + 0.7, 35000.0, 42.0, 3509.9, 1794.3 + 0.7, 35000.0, 42.5, 3589.611, 1831.5 + 0.7, 35000.0, 43.0, 3669.35, 1868.65 + 0.7, 35000.0, 43.5, 3749.139, 1905.82 + 0.7, 35000.0, 44.0, 3829.0, 1943.1 + 0.7, 35000.0, 44.5, 3909.185, 1980.65 + 0.7, 35000.0, 45.0, 3989.394, 2018.45 + 0.7, 35000.0, 45.5, 4069.555, 2056.55 + 0.7, 35000.0, 46.0, 4149.6, 2095.0 + 0.7, 35000.0, 46.5, 4229.109, 2133.84 + 0.7, 35000.0, 47.0, 4308.5, 2173.14 + 0.7, 35000.0, 47.5, 4387.841, 2212.98 + 0.7, 35000.0, 48.0, 4467.2, 2253.4 + 0.7, 35000.0, 48.5, 4546.647, 2294.47 + 0.7, 35000.0, 49.0, 4626.25, 2336.26 + 0.7, 35000.0, 49.5, 4706.078, 2378.81 + 0.7, 35000.0, 50.0, 4786.2, 2422.2 + 0.7, 39000.0, 0.0, 153.0857, 153.086 + 0.7, 39000.0, 22.0, 307.4, 413.8 + 0.7, 39000.0, 22.5, 365.7277, 437.108 + 0.7, 39000.0, 23.0, 423.4531, 460.325 + 0.7, 39000.0, 23.5, 480.777, 483.505 + 0.7, 39000.0, 24.0, 537.9, 506.7 + 0.7, 39000.0, 24.5, 595.023, 529.964 + 0.7, 39000.0, 25.0, 652.3469, 553.35 + 0.7, 39000.0, 25.5, 710.0723, 576.911 + 0.7, 39000.0, 26.0, 768.4, 600.7 + 0.7, 39000.0, 26.5, 829.6418, 625.279 + 0.7, 39000.0, 27.0, 892.0081, 650.221 + 0.7, 39000.0, 27.5, 955.3379, 675.493 + 0.7, 39000.0, 28.0, 1019.47, 701.06 + 0.7, 39000.0, 28.5, 1084.243, 726.888 + 0.7, 39000.0, 29.0, 1149.497, 752.944 + 0.7, 39000.0, 29.5, 1215.069, 779.192 + 0.7, 39000.0, 30.0, 1280.8, 805.6 + 0.7, 39000.0, 30.5, 1344.828, 831.798 + 0.7, 39000.0, 31.0, 1408.853, 858.118 + 0.7, 39000.0, 31.5, 1472.877, 884.559 + 0.7, 39000.0, 32.0, 1536.9, 911.119 + 0.7, 39000.0, 32.5, 1600.923, 937.795 + 0.7, 39000.0, 33.0, 1664.947, 964.585 + 0.7, 39000.0, 33.5, 1728.972, 991.488 + 0.7, 39000.0, 34.0, 1793.0, 1018.5 + 0.7, 39000.0, 34.5, 1857.051, 1045.51 + 0.7, 39000.0, 35.0, 1921.103, 1072.64 + 0.7, 39000.0, 35.5, 1985.157, 1099.89 + 0.7, 39000.0, 36.0, 2049.21, 1127.28 + 0.7, 39000.0, 36.5, 2113.262, 1154.8 + 0.7, 39000.0, 37.0, 2177.312, 1182.47 + 0.7, 39000.0, 37.5, 2241.358, 1210.3 + 0.7, 39000.0, 38.0, 2305.4, 1238.3 + 0.7, 39000.0, 38.5, 2369.422, 1266.35 + 0.7, 39000.0, 39.0, 2433.445, 1294.65 + 0.7, 39000.0, 39.5, 2497.471, 1323.22 + 0.7, 39000.0, 40.0, 2561.5, 1352.1 + 0.7, 39000.0, 40.5, 2625.548, 1381.3 + 0.7, 39000.0, 41.0, 2689.6, 1410.89 + 0.7, 39000.0, 41.5, 2753.652, 1440.91 + 0.7, 39000.0, 42.0, 2817.7, 1471.4 + 0.7, 39000.0, 42.5, 2881.68, 1502.83 + 0.7, 39000.0, 43.0, 2945.675, 1534.66 + 0.7, 39000.0, 43.5, 3009.708, 1566.76 + 0.7, 39000.0, 44.0, 3073.8, 1599.0 + 0.7, 39000.0, 44.5, 3138.177, 1630.98 + 0.7, 39000.0, 45.0, 3202.575, 1662.96 + 0.7, 39000.0, 45.5, 3266.936, 1694.94 + 0.7, 39000.0, 46.0, 3331.2, 1726.9 + 0.7, 39000.0, 46.5, 3395.011, 1758.5 + 0.7, 39000.0, 47.0, 3458.725, 1790.18 + 0.7, 39000.0, 47.5, 3522.402, 1822.08 + 0.7, 39000.0, 48.0, 3586.1, 1854.3 + 0.7, 39000.0, 48.5, 3649.88, 1886.97 + 0.7, 39000.0, 49.0, 3713.8, 1920.22 + 0.7, 39000.0, 49.5, 3777.92, 1954.15 + 0.7, 39000.0, 50.0, 3842.3, 1988.9 + 0.7, 43000.0, 0.0, 126.3108, 126.311 + 0.7, 43000.0, 22.0, 248.4, 365.4 + 0.7, 43000.0, 22.5, 295.541, 384.173 + 0.7, 43000.0, 23.0, 342.1969, 403.019 + 0.7, 43000.0, 23.5, 388.5293, 421.955 + 0.7, 43000.0, 24.0, 434.7, 441.0 + 0.7, 43000.0, 24.5, 480.8707, 460.17 + 0.7, 43000.0, 25.0, 527.2031, 479.481 + 0.7, 43000.0, 25.5, 573.859, 498.952 + 0.7, 43000.0, 26.0, 621.0, 518.6 + 0.7, 43000.0, 26.5, 670.4859, 538.599 + 0.7, 43000.0, 27.0, 720.8775, 558.817 + 0.7, 43000.0, 27.5, 772.0453, 579.246 + 0.7, 43000.0, 28.0, 823.86, 599.875 + 0.7, 43000.0, 28.5, 876.1922, 620.695 + 0.7, 43000.0, 29.0, 928.9125, 641.695 + 0.7, 43000.0, 29.5, 981.8916, 662.867 + 0.7, 43000.0, 30.0, 1035.0, 684.2 + 0.7, 43000.0, 30.5, 1086.75, 705.701 + 0.7, 43000.0, 31.0, 1138.5, 727.342 + 0.7, 43000.0, 31.5, 1190.25, 749.112 + 0.7, 43000.0, 32.0, 1242.0, 771.0 + 0.7, 43000.0, 32.5, 1293.75, 792.994 + 0.7, 43000.0, 33.0, 1345.5, 815.083 + 0.7, 43000.0, 33.5, 1397.25, 837.255 + 0.7, 43000.0, 34.0, 1449.0, 859.5 + 0.7, 43000.0, 34.5, 1500.75, 881.54 + 0.7, 43000.0, 35.0, 1552.5, 903.655 + 0.7, 43000.0, 35.5, 1604.25, 925.858 + 0.7, 43000.0, 36.0, 1656.0, 948.165 + 0.7, 43000.0, 36.5, 1707.75, 970.588 + 0.7, 43000.0, 37.0, 1759.5, 993.143 + 0.7, 43000.0, 37.5, 1811.25, 1015.84 + 0.7, 43000.0, 38.0, 1863.0, 1038.7 + 0.7, 43000.0, 38.5, 1914.75, 1061.76 + 0.7, 43000.0, 39.0, 1966.5, 1084.99 + 0.7, 43000.0, 39.5, 2018.25, 1108.4 + 0.7, 43000.0, 40.0, 2070.0, 1132.0 + 0.7, 43000.0, 40.5, 2121.75, 1155.63 + 0.7, 43000.0, 41.0, 2173.5, 1179.52 + 0.7, 43000.0, 41.5, 2225.25, 1203.75 + 0.7, 43000.0, 42.0, 2277.0, 1228.4 + 0.7, 43000.0, 42.5, 2328.707, 1254.0 + 0.7, 43000.0, 43.0, 2380.431, 1279.98 + 0.7, 43000.0, 43.5, 2432.19, 1306.21 + 0.7, 43000.0, 44.0, 2484.0, 1332.6 + 0.7, 43000.0, 44.5, 2536.051, 1358.78 + 0.7, 43000.0, 45.0, 2588.119, 1384.98 + 0.7, 43000.0, 45.5, 2640.152, 1411.19 + 0.7, 43000.0, 46.0, 2692.1, 1437.4 + 0.7, 43000.0, 46.5, 2743.652, 1463.27 + 0.7, 43000.0, 47.0, 2795.119, 1489.24 + 0.7, 43000.0, 47.5, 2846.551, 1515.41 + 0.7, 43000.0, 48.0, 2898.0, 1541.9 + 0.7, 43000.0, 48.5, 2949.518, 1568.82 + 0.7, 43000.0, 49.0, 3001.156, 1596.29 + 0.7, 43000.0, 49.5, 3052.966, 1624.41 + 0.7, 43000.0, 50.0, 3105.0, 1653.3 + 0.7, 48000.0, 0.0, 99.3283, 99.3283 + 0.7, 48000.0, 22.0, 195.6, 287.8 + 0.7, 48000.0, 22.5, 232.7221, 302.571 + 0.7, 48000.0, 23.0, 269.4609, 317.403 + 0.7, 48000.0, 23.5, 305.9443, 332.308 + 0.7, 48000.0, 24.0, 342.3, 347.3 + 0.7, 48000.0, 24.5, 378.6557, 362.392 + 0.7, 48000.0, 25.0, 415.1391, 377.597 + 0.7, 48000.0, 25.5, 451.8779, 392.929 + 0.7, 48000.0, 26.0, 489.0, 408.4 + 0.7, 48000.0, 26.5, 527.9756, 424.146 + 0.7, 48000.0, 27.0, 567.6666, 440.066 + 0.7, 48000.0, 27.5, 607.9705, 456.151 + 0.7, 48000.0, 28.0, 648.785, 472.395 + 0.7, 48000.0, 28.5, 690.0076, 488.789 + 0.7, 48000.0, 29.0, 731.5359, 505.327 + 0.7, 48000.0, 29.5, 773.2675, 521.999 + 0.7, 48000.0, 30.0, 815.1, 538.8 + 0.7, 48000.0, 30.5, 855.8534, 555.738 + 0.7, 48000.0, 31.0, 896.6055, 572.787 + 0.7, 48000.0, 31.5, 937.3563, 589.938 + 0.7, 48000.0, 32.0, 978.1063, 607.181 + 0.7, 48000.0, 32.5, 1018.855, 624.508 + 0.7, 48000.0, 33.0, 1059.604, 641.91 + 0.7, 48000.0, 33.5, 1100.352, 659.377 + 0.7, 48000.0, 34.0, 1141.1, 676.9 + 0.7, 48000.0, 34.5, 1181.85, 694.254 + 0.7, 48000.0, 35.0, 1222.6, 711.666 + 0.7, 48000.0, 35.5, 1263.35, 729.147 + 0.7, 48000.0, 36.0, 1304.1, 746.71 + 0.7, 48000.0, 36.5, 1344.85, 764.365 + 0.7, 48000.0, 37.0, 1385.6, 782.124 + 0.7, 48000.0, 37.5, 1426.35, 799.999 + 0.7, 48000.0, 38.0, 1467.1, 818.0 + 0.7, 48000.0, 38.5, 1507.85, 836.168 + 0.7, 48000.0, 39.0, 1548.6, 854.47 + 0.7, 48000.0, 39.5, 1589.35, 872.913 + 0.7, 48000.0, 40.0, 1630.1, 891.5 + 0.7, 48000.0, 40.5, 1670.846, 910.105 + 0.7, 48000.0, 41.0, 1711.594, 928.919 + 0.7, 48000.0, 41.5, 1752.345, 947.998 + 0.7, 48000.0, 42.0, 1793.1, 967.4 + 0.7, 48000.0, 42.5, 1833.842, 987.543 + 0.7, 48000.0, 43.0, 1874.6, 1007.98 + 0.7, 48000.0, 43.5, 1915.383, 1028.63 + 0.7, 48000.0, 44.0, 1956.2, 1049.4 + 0.7, 48000.0, 44.5, 1997.174, 1070.03 + 0.7, 48000.0, 45.0, 2038.156, 1090.69 + 0.7, 48000.0, 45.5, 2079.11, 1111.35 + 0.7, 48000.0, 46.0, 2120.0, 1132.0 + 0.7, 48000.0, 46.5, 2160.606, 1152.35 + 0.7, 48000.0, 47.0, 2201.15, 1172.78 + 0.7, 48000.0, 47.5, 2241.669, 1193.36 + 0.7, 48000.0, 48.0, 2282.2, 1214.2 + 0.7, 48000.0, 48.5, 2322.781, 1235.39 + 0.7, 48000.0, 49.0, 2363.45, 1257.03 + 0.7, 48000.0, 49.5, 2404.244, 1279.2 + 0.7, 48000.0, 50.0, 2445.2, 1302.0 + 0.75, 0.0, 0.0, 710.9639, 710.964 + 0.75, 0.0, 22.0, 1790.7, 1981.1 + 0.75, 0.0, 22.5, 2131.593, 2483.77 + 0.75, 0.0, 23.0, 2462.62, 2677.33 + 0.75, 0.0, 23.5, 2786.088, 2622.78 + 0.75, 0.0, 24.0, 3104.3, 2381.1 + 0.75, 0.0, 24.5, 3419.562, 2013.28 + 0.75, 0.0, 25.0, 3734.18, 1580.32 + 0.75, 0.0, 25.5, 4050.457, 1143.2 + 0.75, 0.0, 26.0, 4370.7, 762.9 + 0.75, 0.0, 26.5, 4720.144, 1064.83 + 0.75, 0.0, 27.0, 5079.473, 1577.83 + 0.75, 0.0, 27.5, 5447.062, 2266.11 + 0.75, 0.0, 28.0, 5821.285, 3093.92 + 0.75, 0.0, 28.5, 6200.516, 4025.47 + 0.75, 0.0, 29.0, 6583.13, 5025.02 + 0.75, 0.0, 29.5, 6967.5, 6056.78 + 0.75, 0.0, 30.0, 7352.0, 7085.0 + 0.75, 0.0, 30.5, 7714.821, 7654.55 + 0.75, 0.0, 31.0, 8076.442, 8188.95 + 0.75, 0.0, 31.5, 8437.162, 8692.37 + 0.75, 0.0, 32.0, 8797.275, 9168.99 + 0.75, 0.0, 32.5, 9157.079, 9622.97 + 0.75, 0.0, 33.0, 9516.87, 10058.5 + 0.75, 0.0, 33.5, 9876.945, 10479.7 + 0.75, 0.0, 34.0, 10237.6, 10890.8 + 0.75, 0.0, 34.5, 10603.77, 11836.2 + 0.75, 0.0, 35.0, 10970.68, 12728.4 + 0.75, 0.0, 35.5, 11338.17, 13520.1 + 0.75, 0.0, 36.0, 11706.09, 14164.0 + 0.75, 0.0, 36.5, 12074.32, 14612.7 + 0.75, 0.0, 37.0, 12442.69, 14819.1 + 0.75, 0.0, 37.5, 12811.07, 14735.8 + 0.75, 0.0, 38.0, 13179.3, 14315.5 + 0.75, 0.0, 38.5, 13547.73, 13079.5 + 0.75, 0.0, 39.0, 13915.48, 11635.7 + 0.75, 0.0, 39.5, 14282.28, 10032.7 + 0.75, 0.0, 40.0, 14647.9, 8319.1 + 0.75, 0.0, 40.5, 15012.47, 6463.55 + 0.75, 0.0, 41.0, 15375.18, 4626.56 + 0.75, 0.0, 41.5, 15735.63, 2888.69 + 0.75, 0.0, 42.0, 16093.4, 1330.5 + 0.75, 0.0, 42.5, 16441.35, 162.6 + 0.75, 0.0, 43.0, 16788.49, -716.5 + 0.75, 0.0, 43.5, 17137.12, -1278.25 + 0.75, 0.0, 44.0, 17489.5, -1494.1 + 0.75, 0.0, 44.5, 17859.13, -1062.34 + 0.75, 0.0, 45.0, 18232.6, -336.85 + 0.75, 0.0, 45.5, 18607.72, 601.669 + 0.75, 0.0, 46.0, 18982.3, 1672.5 + 0.75, 0.0, 46.5, 19345.51, 2662.69 + 0.75, 0.0, 47.0, 19707.23, 3676.67 + 0.75, 0.0, 47.5, 20068.71, 4686.61 + 0.75, 0.0, 48.0, 20431.2, 5664.7 + 0.75, 0.0, 48.5, 20795.95, 6583.12 + 0.75, 0.0, 49.0, 21164.22, 7414.06 + 0.75, 0.0, 49.5, 21537.25, 8129.69 + 0.75, 0.0, 50.0, 21916.3, 8702.2 + 0.75, 2000.0, 0.0, 665.654, 665.654 + 0.75, 2000.0, 22.0, -24169.5, -7390.7 + 0.75, 2000.0, 22.5, -28741.42, -9005.27 + 0.75, 2000.0, 23.0, -33267.46, -10516.7 + 0.75, 2000.0, 23.5, -37763.25, -11952.6 + 0.75, 2000.0, 24.0, -42244.4, -13340.3 + 0.75, 2000.0, 24.5, -46726.51, -14707.5 + 0.75, 2000.0, 25.0, -51225.21, -16081.5 + 0.75, 2000.0, 25.5, -55756.1, -17490.0 + 0.75, 2000.0, 26.0, -60334.8, -18960.5 + 0.75, 2000.0, 26.5, -65141.32, -20809.0 + 0.75, 2000.0, 27.0, -70036.26, -22791.0 + 0.75, 2000.0, 27.5, -75007.07, -24884.4 + 0.75, 2000.0, 28.0, -80041.16, -27067.4 + 0.75, 2000.0, 28.5, -85125.97, -29317.9 + 0.75, 2000.0, 29.0, -90248.92, -31614.1 + 0.75, 2000.0, 29.5, -95397.46, -33933.8 + 0.75, 2000.0, 30.0, -100559.0, -36255.2 + 0.75, 2000.0, 30.5, -105589.2, -38242.9 + 0.75, 2000.0, 31.0, -110619.8, -40218.2 + 0.75, 2000.0, 31.5, -115650.8, -42188.9 + 0.75, 2000.0, 32.0, -120682.1, -44163.0 + 0.75, 2000.0, 32.5, -125713.9, -46148.2 + 0.75, 2000.0, 33.0, -130746.0, -48152.6 + 0.75, 2000.0, 33.5, -135778.4, -50184.0 + 0.75, 2000.0, 34.0, -140811.2, -52250.2 + 0.75, 2000.0, 34.5, -145849.1, -54795.7 + 0.75, 2000.0, 35.0, -150886.9, -57350.2 + 0.75, 2000.0, 35.5, -155924.0, -59880.1 + 0.75, 2000.0, 36.0, -160959.9, -62351.6 + 0.75, 2000.0, 36.5, -165994.3, -64731.2 + 0.75, 2000.0, 37.0, -171026.5, -66985.0 + 0.75, 2000.0, 37.5, -176056.2, -69079.5 + 0.75, 2000.0, 38.0, -181082.9, -70980.8 + 0.75, 2000.0, 38.5, -186097.3, -72357.5 + 0.75, 2000.0, 39.0, -191112.2, -73628.2 + 0.75, 2000.0, 39.5, -196129.1, -74825.3 + 0.75, 2000.0, 40.0, -201149.5, -75981.5 + 0.75, 2000.0, 40.5, -206182.3, -77044.5 + 0.75, 2000.0, 41.0, -211218.6, -78165.4 + 0.75, 2000.0, 41.5, -216256.7, -79410.5 + 0.75, 2000.0, 42.0, -221295.1, -80846.3 + 0.75, 2000.0, 42.5, -226324.5, -82765.3 + 0.75, 2000.0, 43.0, -231354.3, -84917.1 + 0.75, 2000.0, 43.5, -236386.0, -87277.8 + 0.75, 2000.0, 44.0, -241421.2, -89823.0 + 0.75, 2000.0, 44.5, -246476.8, -92550.2 + 0.75, 2000.0, 45.0, -251532.9, -95405.1 + 0.75, 2000.0, 45.5, -256584.9, -98355.3 + 0.75, 2000.0, 46.0, -261628.2, -101368.0 + 0.75, 2000.0, 46.5, -266633.7, -104328.0 + 0.75, 2000.0, 47.0, -271631.1, -107318.0 + 0.75, 2000.0, 47.5, -276625.5, -110339.0 + 0.75, 2000.0, 48.0, -281622.3, -113389.0 + 0.75, 2000.0, 48.5, -286626.6, -116471.0 + 0.75, 2000.0, 49.0, -291643.5, -119584.0 + 0.75, 2000.0, 49.5, -296678.4, -122727.0 + 0.75, 2000.0, 50.0, -301736.4, -125903.0 + 0.75, 5000.0, 0.0, 601.9947, 601.995 + 0.75, 5000.0, 22.0, 27298.5, 10613.6 + 0.75, 5000.0, 22.5, 32488.41, 12343.0 + 0.75, 5000.0, 23.0, 37621.7, 14019.4 + 0.75, 5000.0, 23.5, 42716.66, 15661.4 + 0.75, 5000.0, 24.0, 47791.6, 17288.0 + 0.75, 5000.0, 24.5, 52864.84, 18917.9 + 0.75, 5000.0, 25.0, 57954.68, 20570.0 + 0.75, 5000.0, 25.5, 63079.43, 22263.0 + 0.75, 5000.0, 26.0, 68257.4, 24015.8 + 0.75, 5000.0, 26.5, 73697.87, 26034.2 + 0.75, 5000.0, 27.0, 79239.08, 28160.7 + 0.75, 5000.0, 27.5, 84866.62, 30382.0 + 0.75, 5000.0, 28.0, 90566.05, 32684.9 + 0.75, 5000.0, 28.5, 96322.94, 35056.0 + 0.75, 5000.0, 29.0, 102122.9, 37482.3 + 0.75, 5000.0, 29.5, 107951.4, 39950.3 + 0.75, 5000.0, 30.0, 113794.1, 42446.9 + 0.75, 5000.0, 30.5, 119485.2, 44844.3 + 0.75, 5000.0, 31.0, 125176.1, 47254.6 + 0.75, 5000.0, 31.5, 130866.6, 49675.5 + 0.75, 5000.0, 32.0, 136556.9, 52104.6 + 0.75, 5000.0, 32.5, 142246.8, 54539.7 + 0.75, 5000.0, 33.0, 147936.4, 56978.3 + 0.75, 5000.0, 33.5, 153625.7, 59418.1 + 0.75, 5000.0, 34.0, 159314.6, 61856.8 + 0.75, 5000.0, 34.5, 165001.7, 64325.2 + 0.75, 5000.0, 35.0, 170688.5, 66784.6 + 0.75, 5000.0, 35.5, 176375.2, 69229.5 + 0.75, 5000.0, 36.0, 182061.8, 71654.4 + 0.75, 5000.0, 36.5, 187748.6, 74053.7 + 0.75, 5000.0, 37.0, 193435.6, 76422.0 + 0.75, 5000.0, 37.5, 199123.0, 78753.7 + 0.75, 5000.0, 38.0, 204810.8, 81043.4 + 0.75, 5000.0, 38.5, 210500.7, 83250.2 + 0.75, 5000.0, 39.0, 216190.5, 85422.2 + 0.75, 5000.0, 39.5, 221880.1, 87561.8 + 0.75, 5000.0, 40.0, 227569.3, 89671.2 + 0.75, 5000.0, 40.5, 233255.4, 91696.6 + 0.75, 5000.0, 41.0, 238941.6, 93719.1 + 0.75, 5000.0, 41.5, 244628.6, 95763.3 + 0.75, 5000.0, 42.0, 250317.3, 97854.1 + 0.75, 5000.0, 42.5, 256008.7, 100063.0 + 0.75, 5000.0, 43.0, 261703.0, 102350.0 + 0.75, 5000.0, 43.5, 267401.0, 104719.0 + 0.75, 5000.0, 44.0, 273103.1, 107179.0 + 0.75, 5000.0, 44.5, 278823.8, 109766.0 + 0.75, 5000.0, 45.0, 284544.4, 112441.0 + 0.75, 5000.0, 45.5, 290260.1, 115200.0 + 0.75, 5000.0, 46.0, 295966.0, 118036.0 + 0.75, 5000.0, 46.5, 301631.2, 120970.0 + 0.75, 5000.0, 47.0, 307287.1, 123956.0 + 0.75, 5000.0, 47.5, 312939.5, 126978.0 + 0.75, 5000.0, 48.0, 318593.6, 130016.0 + 0.75, 5000.0, 48.5, 324255.1, 133053.0 + 0.75, 5000.0, 49.0, 329929.5, 136072.0 + 0.75, 5000.0, 49.5, 335622.2, 139054.0 + 0.75, 5000.0, 50.0, 341338.9, 141982.0 + 0.75, 10000.0, 0.0, 506.6646, 506.665 + 0.75, 10000.0, 22.0, 715.7, 1087.0 + 0.75, 10000.0, 22.5, 847.8322, 1187.68 + 0.75, 10000.0, 23.0, 980.3047, 1274.36 + 0.75, 10000.0, 23.5, 1113.325, 1349.18 + 0.75, 10000.0, 24.0, 1247.1, 1414.3 + 0.75, 10000.0, 24.5, 1381.838, 1471.85 + 0.75, 10000.0, 25.0, 1517.745, 1523.99 + 0.75, 10000.0, 25.5, 1655.03, 1572.86 + 0.75, 10000.0, 26.0, 1793.9, 1620.6 + 0.75, 10000.0, 26.5, 1937.438, 1690.36 + 0.75, 10000.0, 27.0, 2083.141, 1764.49 + 0.75, 10000.0, 27.5, 2230.722, 1841.53 + 0.75, 10000.0, 28.0, 2379.895, 1920.02 + 0.75, 10000.0, 28.5, 2530.375, 1998.52 + 0.75, 10000.0, 29.0, 2681.877, 2075.57 + 0.75, 10000.0, 29.5, 2834.113, 2149.72 + 0.75, 10000.0, 30.0, 2986.8, 2219.5 + 0.75, 10000.0, 30.5, 3137.079, 2255.15 + 0.75, 10000.0, 31.0, 3287.482, 2286.23 + 0.75, 10000.0, 31.5, 3437.967, 2313.98 + 0.75, 10000.0, 32.0, 3588.494, 2339.64 + 0.75, 10000.0, 32.5, 3739.021, 2364.47 + 0.75, 10000.0, 33.0, 3889.509, 2389.69 + 0.75, 10000.0, 33.5, 4039.915, 2416.55 + 0.75, 10000.0, 34.0, 4190.2, 2446.3 + 0.75, 10000.0, 34.5, 4340.032, 2497.45 + 0.75, 10000.0, 35.0, 4489.687, 2552.33 + 0.75, 10000.0, 35.5, 4639.155, 2610.53 + 0.75, 10000.0, 36.0, 4788.42, 2671.65 + 0.75, 10000.0, 36.5, 4937.47, 2735.29 + 0.75, 10000.0, 37.0, 5086.292, 2801.05 + 0.75, 10000.0, 37.5, 5234.873, 2868.52 + 0.75, 10000.0, 38.0, 5383.2, 2937.3 + 0.75, 10000.0, 38.5, 5530.435, 3019.29 + 0.75, 10000.0, 39.0, 5677.817, 3095.41 + 0.75, 10000.0, 39.5, 5825.515, 3162.52 + 0.75, 10000.0, 40.0, 5973.7, 3217.5 + 0.75, 10000.0, 40.5, 6123.321, 3220.14 + 0.75, 10000.0, 41.0, 6273.456, 3219.2 + 0.75, 10000.0, 41.5, 6423.963, 3226.36 + 0.75, 10000.0, 42.0, 6574.7, 3253.3 + 0.75, 10000.0, 42.5, 6725.235, 3359.36 + 0.75, 10000.0, 43.0, 6875.831, 3489.52 + 0.75, 10000.0, 43.5, 7026.462, 3636.42 + 0.75, 10000.0, 44.0, 7177.1, 3792.7 + 0.75, 10000.0, 44.5, 7327.809, 3932.43 + 0.75, 10000.0, 45.0, 7478.437, 4074.23 + 0.75, 10000.0, 45.5, 7628.922, 4218.13 + 0.75, 10000.0, 46.0, 7779.2, 4364.2 + 0.75, 10000.0, 46.5, 7929.034, 4528.39 + 0.75, 10000.0, 47.0, 8078.606, 4688.49 + 0.75, 10000.0, 47.5, 8227.926, 4838.2 + 0.75, 10000.0, 48.0, 8377.0, 4971.2 + 0.75, 10000.0, 48.5, 8525.837, 5081.19 + 0.75, 10000.0, 49.0, 8674.444, 5161.86 + 0.75, 10000.0, 49.5, 8822.829, 5206.9 + 0.75, 10000.0, 50.0, 8971.0, 5210.0 + 0.75, 15000.0, 0.0, 423.6696, 423.67 + 0.75, 15000.0, 22.0, 683.6, 1034.5 + 0.75, 15000.0, 22.5, 812.8506, 1089.78 + 0.75, 15000.0, 23.0, 940.9578, 1145.95 + 0.75, 15000.0, 23.5, 1068.336, 1202.97 + 0.75, 15000.0, 24.0, 1195.4, 1260.8 + 0.75, 15000.0, 24.5, 1322.564, 1319.38 + 0.75, 15000.0, 25.0, 1450.242, 1378.68 + 0.75, 15000.0, 25.5, 1578.849, 1438.63 + 0.75, 15000.0, 26.0, 1708.8, 1499.2 + 0.75, 15000.0, 26.5, 1844.93, 1560.32 + 0.75, 15000.0, 27.0, 1983.485, 1621.97 + 0.75, 15000.0, 27.5, 2124.121, 1684.09 + 0.75, 15000.0, 28.0, 2266.495, 1746.64 + 0.75, 15000.0, 28.5, 2410.263, 1809.58 + 0.75, 15000.0, 29.0, 2555.083, 1872.87 + 0.75, 15000.0, 29.5, 2700.609, 1936.46 + 0.75, 15000.0, 30.0, 2846.5, 2000.3 + 0.75, 15000.0, 30.5, 2988.839, 2063.95 + 0.75, 15000.0, 31.0, 3131.195, 2127.81 + 0.75, 15000.0, 31.5, 3273.564, 2191.87 + 0.75, 15000.0, 32.0, 3415.944, 2256.12 + 0.75, 15000.0, 32.5, 3558.331, 2320.57 + 0.75, 15000.0, 33.0, 3700.721, 2385.2 + 0.75, 15000.0, 33.5, 3843.112, 2450.01 + 0.75, 15000.0, 34.0, 3985.5, 2515.0 + 0.75, 15000.0, 34.5, 4127.804, 2581.49 + 0.75, 15000.0, 35.0, 4270.106, 2648.01 + 0.75, 15000.0, 35.5, 4412.41, 2714.44 + 0.75, 15000.0, 36.0, 4554.72, 2780.64 + 0.75, 15000.0, 36.5, 4697.04, 2846.48 + 0.75, 15000.0, 37.0, 4839.374, 2911.82 + 0.75, 15000.0, 37.5, 4981.726, 2976.54 + 0.75, 15000.0, 38.0, 5124.1, 3040.5 + 0.75, 15000.0, 38.5, 5266.568, 3101.0 + 0.75, 15000.0, 39.0, 5409.031, 3161.81 + 0.75, 15000.0, 39.5, 5551.479, 3223.37 + 0.75, 15000.0, 40.0, 5693.9, 3286.1 + 0.75, 15000.0, 40.5, 5836.225, 3352.24 + 0.75, 15000.0, 41.0, 5978.525, 3419.72 + 0.75, 15000.0, 41.5, 6120.812, 3488.27 + 0.75, 15000.0, 42.0, 6263.1, 3557.6 + 0.75, 15000.0, 42.5, 6405.306, 3627.05 + 0.75, 15000.0, 43.0, 6547.575, 3696.89 + 0.75, 15000.0, 43.5, 6689.956, 3766.98 + 0.75, 15000.0, 44.0, 6832.5, 3837.2 + 0.75, 15000.0, 44.5, 6975.795, 3906.65 + 0.75, 15000.0, 45.0, 7119.137, 3976.29 + 0.75, 15000.0, 45.5, 7262.361, 4046.31 + 0.75, 15000.0, 46.0, 7405.3, 4116.9 + 0.75, 15000.0, 46.5, 7546.937, 4189.29 + 0.75, 15000.0, 47.0, 7688.3, 4262.19 + 0.75, 15000.0, 47.5, 7829.562, 4335.38 + 0.75, 15000.0, 48.0, 7970.9, 4408.6 + 0.75, 15000.0, 48.5, 8112.487, 4481.63 + 0.75, 15000.0, 49.0, 8254.5, 4554.23 + 0.75, 15000.0, 49.5, 8397.112, 4626.17 + 0.75, 15000.0, 50.0, 8540.5, 4697.2 + 0.75, 20000.0, 0.0, 351.8026, 351.803 + 0.75, 20000.0, 22.0, 763.5, 950.4 + 0.75, 20000.0, 22.5, 908.4303, 1013.21 + 0.75, 20000.0, 23.0, 1051.858, 1075.41 + 0.75, 20000.0, 23.5, 1194.281, 1137.24 + 0.75, 20000.0, 24.0, 1336.2, 1198.9 + 0.75, 20000.0, 24.5, 1478.112, 1260.63 + 0.75, 20000.0, 25.0, 1620.517, 1322.64 + 0.75, 20000.0, 25.5, 1763.913, 1385.15 + 0.75, 20000.0, 26.0, 1908.8, 1448.4 + 0.75, 20000.0, 26.5, 2060.908, 1514.81 + 0.75, 20000.0, 27.0, 2215.803, 1582.52 + 0.75, 20000.0, 27.5, 2373.086, 1651.38 + 0.75, 20000.0, 28.0, 2532.36, 1721.22 + 0.75, 20000.0, 28.5, 2693.227, 1791.89 + 0.75, 20000.0, 29.0, 2855.288, 1863.23 + 0.75, 20000.0, 29.5, 3018.145, 1935.09 + 0.75, 20000.0, 30.0, 3181.4, 2007.3 + 0.75, 20000.0, 30.5, 3340.477, 2077.91 + 0.75, 20000.0, 31.0, 3499.554, 2148.74 + 0.75, 20000.0, 31.5, 3658.63, 2219.8 + 0.75, 20000.0, 32.0, 3817.706, 2291.09 + 0.75, 20000.0, 32.5, 3976.781, 2362.65 + 0.75, 20000.0, 33.0, 4135.855, 2434.48 + 0.75, 20000.0, 33.5, 4294.928, 2506.59 + 0.75, 20000.0, 34.0, 4454.0, 2579.0 + 0.75, 20000.0, 34.5, 4613.069, 2651.81 + 0.75, 20000.0, 35.0, 4772.136, 2724.93 + 0.75, 20000.0, 35.5, 4931.201, 2798.39 + 0.75, 20000.0, 36.0, 5090.265, 2872.18 + 0.75, 20000.0, 36.5, 5249.327, 2946.3 + 0.75, 20000.0, 37.0, 5408.387, 3020.78 + 0.75, 20000.0, 37.5, 5567.444, 3095.61 + 0.75, 20000.0, 38.0, 5726.5, 3170.8 + 0.75, 20000.0, 38.5, 5885.541, 3246.3 + 0.75, 20000.0, 39.0, 6044.586, 3322.2 + 0.75, 20000.0, 39.5, 6203.638, 3398.53 + 0.75, 20000.0, 40.0, 6362.7, 3475.3 + 0.75, 20000.0, 40.5, 6521.797, 3552.34 + 0.75, 20000.0, 41.0, 6680.9, 3629.93 + 0.75, 20000.0, 41.5, 6840.003, 3708.19 + 0.75, 20000.0, 42.0, 6999.1, 3787.2 + 0.75, 20000.0, 42.5, 7158.032, 3867.53 + 0.75, 20000.0, 43.0, 7317.006, 3948.63 + 0.75, 20000.0, 43.5, 7476.077, 4030.41 + 0.75, 20000.0, 44.0, 7635.3, 4112.8 + 0.75, 20000.0, 44.5, 7795.245, 4194.99 + 0.75, 20000.0, 45.0, 7955.244, 4277.91 + 0.75, 20000.0, 45.5, 8115.146, 4361.74 + 0.75, 20000.0, 46.0, 8274.8, 4446.7 + 0.75, 20000.0, 46.5, 8433.304, 4533.4 + 0.75, 20000.0, 47.0, 8591.556, 4621.46 + 0.75, 20000.0, 47.5, 8749.705, 4710.91 + 0.75, 20000.0, 48.0, 8907.9, 4801.8 + 0.75, 20000.0, 48.5, 9066.288, 4894.16 + 0.75, 20000.0, 49.0, 9225.019, 4988.02 + 0.75, 20000.0, 49.5, 9384.24, 5083.42 + 0.75, 20000.0, 50.0, 9544.1, 5180.4 + 0.75, 25000.0, 0.0, 289.9256, 289.926 + 0.75, 25000.0, 22.0, 623.9, 776.2 + 0.75, 25000.0, 22.5, 742.3205, 826.073 + 0.75, 25000.0, 23.0, 859.5234, 875.742 + 0.75, 25000.0, 23.5, 975.9146, 925.34 + 0.75, 25000.0, 24.0, 1091.9, 975.0 + 0.75, 25000.0, 24.5, 1207.885, 1024.85 + 0.75, 25000.0, 25.0, 1324.277, 1075.03 + 0.75, 25000.0, 25.5, 1441.479, 1125.67 + 0.75, 25000.0, 26.0, 1559.9, 1176.9 + 0.75, 25000.0, 26.5, 1684.205, 1230.25 + 0.75, 25000.0, 27.0, 1810.784, 1284.53 + 0.75, 25000.0, 27.5, 1939.31, 1339.64 + 0.75, 25000.0, 28.0, 2069.46, 1395.48 + 0.75, 25000.0, 28.5, 2200.909, 1451.92 + 0.75, 25000.0, 29.0, 2333.331, 1508.88 + 0.75, 25000.0, 29.5, 2466.403, 1566.24 + 0.75, 25000.0, 30.0, 2599.8, 1623.9 + 0.75, 25000.0, 30.5, 2729.788, 1680.56 + 0.75, 25000.0, 31.0, 2859.775, 1737.41 + 0.75, 25000.0, 31.5, 2989.763, 1794.46 + 0.75, 25000.0, 32.0, 3119.75, 1851.72 + 0.75, 25000.0, 32.5, 3249.738, 1909.2 + 0.75, 25000.0, 33.0, 3379.725, 1966.9 + 0.75, 25000.0, 33.5, 3509.713, 2024.83 + 0.75, 25000.0, 34.0, 3639.7, 2083.0 + 0.75, 25000.0, 34.5, 3769.684, 2141.42 + 0.75, 25000.0, 35.0, 3899.669, 2200.09 + 0.75, 25000.0, 35.5, 4029.654, 2259.01 + 0.75, 25000.0, 36.0, 4159.64, 2318.19 + 0.75, 25000.0, 36.5, 4289.627, 2377.63 + 0.75, 25000.0, 37.0, 4419.616, 2437.34 + 0.75, 25000.0, 37.5, 4549.607, 2497.33 + 0.75, 25000.0, 38.0, 4679.6, 2557.6 + 0.75, 25000.0, 38.5, 4809.604, 2618.2 + 0.75, 25000.0, 39.0, 4939.606, 2679.07 + 0.75, 25000.0, 39.5, 5069.605, 2740.2 + 0.75, 25000.0, 40.0, 5199.6, 2801.6 + 0.75, 25000.0, 40.5, 5329.577, 2862.96 + 0.75, 25000.0, 41.0, 5459.55, 2924.69 + 0.75, 25000.0, 41.5, 5589.523, 2986.9 + 0.75, 25000.0, 42.0, 5719.5, 3049.7 + 0.75, 25000.0, 42.5, 5849.397, 3113.64 + 0.75, 25000.0, 43.0, 5979.337, 3178.22 + 0.75, 25000.0, 43.5, 6109.359, 3243.39 + 0.75, 25000.0, 44.0, 6239.5, 3309.1 + 0.75, 25000.0, 44.5, 6370.187, 3374.91 + 0.75, 25000.0, 45.0, 6500.912, 3441.29 + 0.75, 25000.0, 45.5, 6631.556, 3508.32 + 0.75, 25000.0, 46.0, 6762.0, 3576.1 + 0.75, 25000.0, 46.5, 6891.527, 3644.56 + 0.75, 25000.0, 47.0, 7020.856, 3714.01 + 0.75, 25000.0, 47.5, 7150.107, 3784.6 + 0.75, 25000.0, 48.0, 7279.4, 3856.5 + 0.75, 25000.0, 48.5, 7408.855, 3929.85 + 0.75, 25000.0, 49.0, 7538.594, 4004.82 + 0.75, 25000.0, 49.5, 7668.735, 4081.55 + 0.75, 25000.0, 50.0, 7799.4, 4160.2 + 0.75, 30000.0, 0.0, 236.9802, 236.98 + 0.75, 30000.0, 22.0, 500.9, 628.5 + 0.75, 30000.0, 22.5, 595.9828, 668.548 + 0.75, 30000.0, 23.0, 690.075, 708.094 + 0.75, 30000.0, 23.5, 783.5047, 747.293 + 0.75, 30000.0, 24.0, 876.6, 786.3 + 0.75, 30000.0, 24.5, 969.6891, 825.27 + 0.75, 30000.0, 25.0, 1063.1, 864.356 + 0.75, 30000.0, 25.5, 1157.161, 903.715 + 0.75, 30000.0, 26.0, 1252.2, 943.5 + 0.75, 30000.0, 26.5, 1351.987, 985.343 + 0.75, 30000.0, 27.0, 1453.604, 1028.01 + 0.75, 30000.0, 27.5, 1556.791, 1071.39 + 0.75, 30000.0, 28.0, 1661.285, 1115.4 + 0.75, 30000.0, 28.5, 1766.825, 1159.93 + 0.75, 30000.0, 29.0, 1873.148, 1204.89 + 0.75, 30000.0, 29.5, 1979.994, 1250.18 + 0.75, 30000.0, 30.0, 2087.1, 1295.7 + 0.75, 30000.0, 30.5, 2191.453, 1340.14 + 0.75, 30000.0, 31.0, 2295.805, 1384.73 + 0.75, 30000.0, 31.5, 2400.156, 1429.48 + 0.75, 30000.0, 32.0, 2504.506, 1474.41 + 0.75, 30000.0, 32.5, 2608.855, 1519.54 + 0.75, 30000.0, 33.0, 2713.204, 1564.89 + 0.75, 30000.0, 33.5, 2817.552, 1610.47 + 0.75, 30000.0, 34.0, 2921.9, 1656.3 + 0.75, 30000.0, 34.5, 3026.25, 1702.8 + 0.75, 30000.0, 35.0, 3130.6, 1749.55 + 0.75, 30000.0, 35.5, 3234.95, 1796.52 + 0.75, 30000.0, 36.0, 3339.3, 1843.69 + 0.75, 30000.0, 36.5, 3443.65, 1891.03 + 0.75, 30000.0, 37.0, 3548.0, 1938.53 + 0.75, 30000.0, 37.5, 3652.35, 1986.16 + 0.75, 30000.0, 38.0, 3756.7, 2033.9 + 0.75, 30000.0, 38.5, 3861.05, 2081.57 + 0.75, 30000.0, 39.0, 3965.4, 2129.38 + 0.75, 30000.0, 39.5, 4069.75, 2177.35 + 0.75, 30000.0, 40.0, 4174.1, 2225.5 + 0.75, 30000.0, 40.5, 4278.45, 2273.61 + 0.75, 30000.0, 41.0, 4382.8, 2322.02 + 0.75, 30000.0, 41.5, 4487.15, 2370.81 + 0.75, 30000.0, 42.0, 4591.5, 2420.1 + 0.75, 30000.0, 42.5, 4695.768, 2470.43 + 0.75, 30000.0, 43.0, 4800.069, 2521.27 + 0.75, 30000.0, 43.5, 4904.435, 2572.56 + 0.75, 30000.0, 44.0, 5008.9, 2624.2 + 0.75, 30000.0, 44.5, 5113.82, 2675.7 + 0.75, 30000.0, 45.0, 5218.775, 2727.57 + 0.75, 30000.0, 45.5, 5323.667, 2779.91 + 0.75, 30000.0, 46.0, 5428.4, 2832.8 + 0.75, 30000.0, 46.5, 5532.4, 2886.24 + 0.75, 30000.0, 47.0, 5636.238, 2940.47 + 0.75, 30000.0, 47.5, 5740.006, 2995.61 + 0.75, 30000.0, 48.0, 5843.8, 3051.8 + 0.75, 30000.0, 48.5, 5947.713, 3109.17 + 0.75, 30000.0, 49.0, 6051.838, 3167.86 + 0.75, 30000.0, 49.5, 6156.269, 3227.99 + 0.75, 30000.0, 50.0, 6261.1, 3289.7 + 0.75, 35000.0, 0.0, 191.9809, 191.981 + 0.75, 35000.0, 22.0, 385.8, 517.1 + 0.75, 35000.0, 22.5, 459.0426, 547.903 + 0.75, 35000.0, 23.0, 531.5219, 578.18 + 0.75, 35000.0, 23.5, 603.4902, 608.067 + 0.75, 35000.0, 24.0, 675.2, 637.7 + 0.75, 35000.0, 24.5, 746.9035, 667.214 + 0.75, 35000.0, 25.0, 818.8531, 696.745 + 0.75, 35000.0, 25.5, 891.3012, 726.429 + 0.75, 35000.0, 26.0, 964.5, 756.4 + 0.75, 35000.0, 26.5, 1041.343, 788.014 + 0.75, 35000.0, 27.0, 1119.593, 820.257 + 0.75, 35000.0, 27.5, 1199.049, 853.055 + 0.75, 35000.0, 28.0, 1279.51, 886.335 + 0.75, 35000.0, 28.5, 1360.776, 920.023 + 0.75, 35000.0, 29.0, 1442.647, 954.045 + 0.75, 35000.0, 29.5, 1524.922, 988.329 + 0.75, 35000.0, 30.0, 1607.4, 1022.8 + 0.75, 35000.0, 30.5, 1687.783, 1056.37 + 0.75, 35000.0, 31.0, 1768.168, 1090.08 + 0.75, 35000.0, 31.5, 1848.555, 1123.94 + 0.75, 35000.0, 32.0, 1928.944, 1157.99 + 0.75, 35000.0, 32.5, 2009.333, 1192.25 + 0.75, 35000.0, 33.0, 2089.723, 1226.74 + 0.75, 35000.0, 33.5, 2170.112, 1261.48 + 0.75, 35000.0, 34.0, 2250.5, 1296.5 + 0.75, 35000.0, 34.5, 2330.878, 1332.68 + 0.75, 35000.0, 35.0, 2411.255, 1369.09 + 0.75, 35000.0, 35.5, 2491.63, 1405.69 + 0.75, 35000.0, 36.0, 2572.005, 1442.42 + 0.75, 35000.0, 36.5, 2652.379, 1479.21 + 0.75, 35000.0, 37.0, 2732.753, 1516.01 + 0.75, 35000.0, 37.5, 2813.126, 1552.76 + 0.75, 35000.0, 38.0, 2893.5, 1589.4 + 0.75, 35000.0, 38.5, 2973.875, 1625.34 + 0.75, 35000.0, 39.0, 3054.25, 1661.33 + 0.75, 35000.0, 39.5, 3134.625, 1697.43 + 0.75, 35000.0, 40.0, 3215.0, 1733.7 + 0.75, 35000.0, 40.5, 3295.375, 1770.26 + 0.75, 35000.0, 41.0, 3375.75, 1807.09 + 0.75, 35000.0, 41.5, 3456.125, 1844.23 + 0.75, 35000.0, 42.0, 3536.5, 1881.7 + 0.75, 35000.0, 42.5, 3616.813, 1919.77 + 0.75, 35000.0, 43.0, 3697.15, 1958.16 + 0.75, 35000.0, 43.5, 3777.538, 1996.82 + 0.75, 35000.0, 44.0, 3858.0, 2035.7 + 0.75, 35000.0, 44.5, 3938.816, 2074.42 + 0.75, 35000.0, 45.0, 4019.656, 2113.39 + 0.75, 35000.0, 45.5, 4100.443, 2152.69 + 0.75, 35000.0, 46.0, 4181.1, 2192.4 + 0.75, 35000.0, 46.5, 4261.16, 2232.69 + 0.75, 35000.0, 47.0, 4341.094, 2273.52 + 0.75, 35000.0, 47.5, 4420.98, 2314.94 + 0.75, 35000.0, 48.0, 4500.9, 2357.0 + 0.75, 35000.0, 48.5, 4580.932, 2399.75 + 0.75, 35000.0, 49.0, 4661.156, 2443.23 + 0.75, 35000.0, 49.5, 4741.652, 2487.5 + 0.75, 35000.0, 50.0, 4822.5, 2532.6 + 0.75, 39000.0, 0.0, 159.231, 159.231 + 0.75, 39000.0, 22.0, 309.7, 444.8 + 0.75, 39000.0, 22.5, 368.4568, 469.517 + 0.75, 39000.0, 23.0, 426.6078, 493.952 + 0.75, 39000.0, 23.5, 484.3549, 518.185 + 0.75, 39000.0, 24.0, 541.9, 542.3 + 0.75, 39000.0, 24.5, 599.4451, 566.377 + 0.75, 39000.0, 25.0, 657.1922, 590.498 + 0.75, 39000.0, 25.5, 715.3432, 614.746 + 0.75, 39000.0, 26.0, 774.1, 639.2 + 0.75, 39000.0, 26.5, 835.7865, 664.65 + 0.75, 39000.0, 27.0, 898.6041, 690.512 + 0.75, 39000.0, 27.5, 962.3908, 716.745 + 0.75, 39000.0, 28.0, 1026.985, 743.31 + 0.75, 39000.0, 28.5, 1092.225, 770.168 + 0.75, 39000.0, 29.0, 1157.948, 797.278 + 0.75, 39000.0, 29.5, 1223.994, 824.602 + 0.75, 39000.0, 30.0, 1290.2, 852.1 + 0.75, 39000.0, 30.5, 1354.701, 879.243 + 0.75, 39000.0, 31.0, 1419.202, 906.528 + 0.75, 39000.0, 31.5, 1483.701, 933.961 + 0.75, 39000.0, 32.0, 1548.2, 961.55 + 0.75, 39000.0, 32.5, 1612.699, 989.301 + 0.75, 39000.0, 33.0, 1677.198, 1017.22 + 0.75, 39000.0, 33.5, 1741.699, 1045.32 + 0.75, 39000.0, 34.0, 1806.2, 1073.6 + 0.75, 39000.0, 34.5, 1870.7, 1101.93 + 0.75, 39000.0, 35.0, 1935.202, 1130.47 + 0.75, 39000.0, 35.5, 1999.706, 1159.24 + 0.75, 39000.0, 36.0, 2064.215, 1188.27 + 0.75, 39000.0, 36.5, 2128.728, 1217.57 + 0.75, 39000.0, 37.0, 2193.246, 1247.16 + 0.75, 39000.0, 37.5, 2257.77, 1277.06 + 0.75, 39000.0, 38.0, 2322.3, 1307.3 + 0.75, 39000.0, 38.5, 2386.862, 1338.32 + 0.75, 39000.0, 39.0, 2451.419, 1369.5 + 0.75, 39000.0, 39.5, 2515.966, 1400.75 + 0.75, 39000.0, 40.0, 2580.5, 1432.0 + 0.75, 39000.0, 40.5, 2644.984, 1462.92 + 0.75, 39000.0, 41.0, 2709.456, 1493.79 + 0.75, 39000.0, 41.5, 2773.926, 1524.64 + 0.75, 39000.0, 42.0, 2838.4, 1555.5 + 0.75, 39000.0, 42.5, 2902.914, 1586.29 + 0.75, 39000.0, 43.0, 2967.438, 1617.18 + 0.75, 39000.0, 43.5, 3031.967, 1648.26 + 0.75, 39000.0, 44.0, 3096.5, 1679.6 + 0.75, 39000.0, 44.5, 3161.029, 1711.68 + 0.75, 39000.0, 45.0, 3225.556, 1743.99 + 0.75, 39000.0, 45.5, 3290.08, 1776.46 + 0.75, 39000.0, 46.0, 3354.6, 1809.0 + 0.75, 39000.0, 46.5, 3419.105, 1840.81 + 0.75, 39000.0, 47.0, 3483.606, 1872.79 + 0.75, 39000.0, 47.5, 3548.104, 1905.13 + 0.75, 39000.0, 48.0, 3612.6, 1938.0 + 0.75, 39000.0, 48.5, 3677.096, 1971.61 + 0.75, 39000.0, 49.0, 3741.594, 2006.13 + 0.75, 39000.0, 49.5, 3806.095, 2041.77 + 0.75, 39000.0, 50.0, 3870.6, 2078.7 + 0.75, 43000.0, 0.0, 131.3813, 131.381 + 0.75, 43000.0, 22.0, 250.0, 390.5 + 0.75, 43000.0, 22.5, 297.4451, 410.731 + 0.75, 43000.0, 23.0, 344.4016, 430.791 + 0.75, 43000.0, 23.5, 391.0322, 450.73 + 0.75, 43000.0, 24.0, 437.5, 470.6 + 0.75, 43000.0, 24.5, 483.9678, 490.451 + 0.75, 43000.0, 25.0, 530.5984, 510.334 + 0.75, 43000.0, 25.5, 577.5549, 530.3 + 0.75, 43000.0, 26.0, 625.0, 550.4 + 0.75, 43000.0, 26.5, 674.807, 571.057 + 0.75, 43000.0, 27.0, 725.5262, 591.971 + 0.75, 43000.0, 27.5, 777.0273, 613.128 + 0.75, 43000.0, 28.0, 829.18, 634.515 + 0.75, 43000.0, 28.5, 881.8539, 656.119 + 0.75, 43000.0, 29.0, 934.9187, 677.927 + 0.75, 43000.0, 29.5, 988.2442, 699.925 + 0.75, 43000.0, 30.0, 1041.7, 722.1 + 0.75, 43000.0, 30.5, 1093.79, 744.368 + 0.75, 43000.0, 31.0, 1145.879, 766.795 + 0.75, 43000.0, 31.5, 1197.968, 789.372 + 0.75, 43000.0, 32.0, 1250.056, 812.094 + 0.75, 43000.0, 32.5, 1302.144, 834.954 + 0.75, 43000.0, 33.0, 1354.23, 857.946 + 0.75, 43000.0, 33.5, 1406.316, 881.064 + 0.75, 43000.0, 34.0, 1458.4, 904.3 + 0.75, 43000.0, 34.5, 1510.471, 927.279 + 0.75, 43000.0, 35.0, 1562.542, 950.4 + 0.75, 43000.0, 35.5, 1614.613, 973.691 + 0.75, 43000.0, 36.0, 1666.685, 997.18 + 0.75, 43000.0, 36.5, 1718.759, 1020.9 + 0.75, 43000.0, 37.0, 1770.835, 1044.87 + 0.75, 43000.0, 37.5, 1822.915, 1069.13 + 0.75, 43000.0, 38.0, 1875.0, 1093.7 + 0.75, 43000.0, 38.5, 1927.108, 1119.04 + 0.75, 43000.0, 39.0, 1979.212, 1144.53 + 0.75, 43000.0, 39.5, 2031.311, 1170.1 + 0.75, 43000.0, 40.0, 2083.4, 1195.7 + 0.75, 43000.0, 40.5, 2135.453, 1221.08 + 0.75, 43000.0, 41.0, 2187.5, 1246.42 + 0.75, 43000.0, 41.5, 2239.547, 1271.72 + 0.75, 43000.0, 42.0, 2291.6, 1297.0 + 0.75, 43000.0, 42.5, 2343.65, 1322.16 + 0.75, 43000.0, 43.0, 2395.725, 1347.34 + 0.75, 43000.0, 43.5, 2447.837, 1372.58 + 0.75, 43000.0, 44.0, 2500.0, 1397.9 + 0.75, 43000.0, 44.5, 2552.377, 1423.36 + 0.75, 43000.0, 45.0, 2604.769, 1448.99 + 0.75, 43000.0, 45.5, 2657.126, 1474.82 + 0.75, 43000.0, 46.0, 2709.4, 1500.9 + 0.75, 43000.0, 46.5, 2761.297, 1527.11 + 0.75, 43000.0, 47.0, 2813.112, 1553.71 + 0.75, 43000.0, 47.5, 2864.897, 1580.77 + 0.75, 43000.0, 48.0, 2916.7, 1608.4 + 0.75, 43000.0, 48.5, 2968.572, 1636.69 + 0.75, 43000.0, 49.0, 3020.562, 1665.74 + 0.75, 43000.0, 49.5, 3072.722, 1695.65 + 0.75, 43000.0, 50.0, 3125.1, 1726.5 + 0.75, 48000.0, 0.0, 103.3156, 103.316 + 0.75, 48000.0, 22.0, 196.9, 307.5 + 0.75, 48000.0, 22.5, 234.2336, 323.448 + 0.75, 48000.0, 23.0, 271.1937, 339.253 + 0.75, 48000.0, 23.5, 307.907, 354.957 + 0.75, 48000.0, 24.0, 344.5, 370.6 + 0.75, 48000.0, 24.5, 381.0992, 386.225 + 0.75, 48000.0, 25.0, 417.8313, 401.872 + 0.75, 48000.0, 25.5, 454.8227, 417.583 + 0.75, 48000.0, 26.0, 492.2, 433.4 + 0.75, 48000.0, 26.5, 531.4229, 449.671 + 0.75, 48000.0, 27.0, 571.3609, 466.148 + 0.75, 48000.0, 27.5, 611.9123, 482.82 + 0.75, 48000.0, 28.0, 652.975, 499.675 + 0.75, 48000.0, 28.5, 694.4471, 516.702 + 0.75, 48000.0, 29.0, 736.2266, 533.889 + 0.75, 48000.0, 29.5, 778.2115, 551.226 + 0.75, 48000.0, 30.0, 820.3, 568.7 + 0.75, 48000.0, 30.5, 861.3236, 586.229 + 0.75, 48000.0, 31.0, 902.3484, 603.88 + 0.75, 48000.0, 31.5, 943.374, 621.649 + 0.75, 48000.0, 32.0, 984.4, 639.531 + 0.75, 48000.0, 32.5, 1025.426, 657.522 + 0.75, 48000.0, 33.0, 1066.452, 675.616 + 0.75, 48000.0, 33.5, 1107.476, 693.811 + 0.75, 48000.0, 34.0, 1148.5, 712.1 + 0.75, 48000.0, 34.5, 1189.512, 730.201 + 0.75, 48000.0, 35.0, 1230.523, 748.416 + 0.75, 48000.0, 35.5, 1271.534, 766.764 + 0.75, 48000.0, 36.0, 1312.545, 785.27 + 0.75, 48000.0, 36.5, 1353.556, 803.954 + 0.75, 48000.0, 37.0, 1394.569, 822.839 + 0.75, 48000.0, 37.5, 1435.583, 841.947 + 0.75, 48000.0, 38.0, 1476.6, 861.3 + 0.75, 48000.0, 38.5, 1517.634, 881.246 + 0.75, 48000.0, 39.0, 1558.664, 901.311 + 0.75, 48000.0, 39.5, 1599.687, 921.446 + 0.75, 48000.0, 40.0, 1640.7, 941.6 + 0.75, 48000.0, 40.5, 1681.674, 961.593 + 0.75, 48000.0, 41.0, 1722.644, 981.556 + 0.75, 48000.0, 41.5, 1763.616, 1001.49 + 0.75, 48000.0, 42.0, 1804.6, 1021.4 + 0.75, 48000.0, 42.5, 1845.606, 1041.2 + 0.75, 48000.0, 43.0, 1886.637, 1061.01 + 0.75, 48000.0, 43.5, 1927.7, 1080.87 + 0.75, 48000.0, 44.0, 1968.8, 1100.8 + 0.75, 48000.0, 44.5, 2010.053, 1120.87 + 0.75, 48000.0, 45.0, 2051.312, 1141.08 + 0.75, 48000.0, 45.5, 2092.541, 1161.44 + 0.75, 48000.0, 46.0, 2133.7, 1182.0 + 0.75, 48000.0, 46.5, 2174.558, 1202.64 + 0.75, 48000.0, 47.0, 2215.35, 1223.56 + 0.75, 48000.0, 47.5, 2256.117, 1244.86 + 0.75, 48000.0, 48.0, 2296.9, 1266.6 + 0.75, 48000.0, 48.5, 2337.739, 1288.87 + 0.75, 48000.0, 49.0, 2378.675, 1311.74 + 0.75, 48000.0, 49.5, 2419.748, 1335.29 + 0.75, 48000.0, 50.0, 2461.0, 1359.6 + 0.8, 0.0, 0.0, 741.0966, 741.097 + 0.8, 0.0, 22.0, 1997.4, 2196.7 + 0.8, 0.0, 22.5, 2378.225, 2847.31 + 0.8, 0.0, 23.0, 2746.391, 3076.84 + 0.8, 0.0, 23.5, 3104.761, 2968.22 + 0.8, 0.0, 24.0, 3456.2, 2604.4 + 0.8, 0.0, 24.5, 3803.57, 2068.31 + 0.8, 0.0, 25.0, 4149.734, 1442.88 + 0.8, 0.0, 25.5, 4497.557, 811.069 + 0.8, 0.0, 26.0, 4849.9, 255.8 + 0.8, 0.0, 26.5, 5237.909, 625.092 + 0.8, 0.0, 27.0, 5637.783, 1280.53 + 0.8, 0.0, 27.5, 6047.534, 2173.88 + 0.8, 0.0, 28.0, 6465.18, 3256.95 + 0.8, 0.0, 28.5, 6888.734, 4481.5 + 0.8, 0.0, 29.0, 7316.213, 5799.32 + 0.8, 0.0, 29.5, 7745.629, 7162.19 + 0.8, 0.0, 30.0, 8175.0, 8521.9 + 0.8, 0.0, 30.5, 8577.272, 9269.83 + 0.8, 0.0, 31.0, 8977.916, 9971.53 + 0.8, 0.0, 31.5, 9377.332, 10632.2 + 0.8, 0.0, 32.0, 9775.925, 11256.9 + 0.8, 0.0, 32.5, 10174.1, 11850.8 + 0.8, 0.0, 33.0, 10572.25, 12419.1 + 0.8, 0.0, 33.5, 10970.78, 12967.0 + 0.8, 0.0, 34.0, 11370.1, 13499.5 + 0.8, 0.0, 34.5, 11776.88, 14745.6 + 0.8, 0.0, 35.0, 12184.66, 15917.8 + 0.8, 0.0, 35.5, 12593.23, 16952.3 + 0.8, 0.0, 36.0, 13002.4, 17785.3 + 0.8, 0.0, 36.5, 13411.98, 18353.1 + 0.8, 0.0, 37.0, 13821.77, 18591.8 + 0.8, 0.0, 37.5, 14231.57, 18437.7 + 0.8, 0.0, 38.0, 14641.2, 17827.0 + 0.8, 0.0, 38.5, 15051.16, 16112.8 + 0.8, 0.0, 39.0, 15460.19, 14116.9 + 0.8, 0.0, 39.5, 15867.92, 11904.9 + 0.8, 0.0, 40.0, 16274.0, 9542.8 + 0.8, 0.0, 40.5, 16678.52, 6987.65 + 0.8, 0.0, 41.0, 17080.52, 4457.41 + 0.8, 0.0, 41.5, 17479.45, 2061.37 + 0.8, 0.0, 42.0, 17874.8, -91.2 + 0.8, 0.0, 42.5, 18257.12, -1713.6 + 0.8, 0.0, 43.0, 18638.35, -2944.94 + 0.8, 0.0, 43.5, 19021.53, -3746.91 + 0.8, 0.0, 44.0, 19409.7, -4081.2 + 0.8, 0.0, 44.5, 19820.64, -3540.38 + 0.8, 0.0, 45.0, 20236.74, -2602.91 + 0.8, 0.0, 45.5, 20655.11, -1378.13 + 0.8, 0.0, 46.0, 21072.9, 24.6 + 0.8, 0.0, 46.5, 21476.07, 1316.81 + 0.8, 0.0, 47.0, 21877.37, 2639.95 + 0.8, 0.0, 47.5, 22278.42, 3956.34 + 0.8, 0.0, 48.0, 22680.8, 5228.3 + 0.8, 0.0, 48.5, 23086.11, 6418.14 + 0.8, 0.0, 49.0, 23495.95, 7488.17 + 0.8, 0.0, 49.5, 23911.91, 8400.72 + 0.8, 0.0, 50.0, 24335.6, 9118.1 + 0.8, 2000.0, 0.0, 693.8663, 693.866 + 0.8, 2000.0, 22.0, -33672.9, -10660.2 + 0.8, 2000.0, 22.5, -40042.63, -12914.0 + 0.8, 2000.0, 23.0, -46348.38, -15024.3 + 0.8, 2000.0, 23.5, -52611.92, -17029.3 + 0.8, 2000.0, 24.0, -58855.0, -18967.6 + 0.8, 2000.0, 24.5, -65099.39, -20877.4 + 0.8, 2000.0, 25.0, -71366.85, -22797.1 + 0.8, 2000.0, 25.5, -77679.13, -24765.1 + 0.8, 2000.0, 26.0, -84058.0, -26819.8 + 0.8, 2000.0, 26.5, -90754.31, -29403.3 + 0.8, 2000.0, 27.0, -97573.81, -32173.2 + 0.8, 2000.0, 27.5, -104499.0, -35098.7 + 0.8, 2000.0, 28.0, -111512.4, -38149.0 + 0.8, 2000.0, 28.5, -118596.4, -41293.2 + 0.8, 2000.0, 29.0, -125733.6, -44500.5 + 0.8, 2000.0, 29.5, -132906.4, -47740.0 + 0.8, 2000.0, 30.0, -140097.4, -50980.8 + 0.8, 2000.0, 30.5, -147105.4, -53751.8 + 0.8, 2000.0, 31.0, -154113.9, -56504.4 + 0.8, 2000.0, 31.5, -161123.0, -59249.7 + 0.8, 2000.0, 32.0, -168132.7, -61998.8 + 0.8, 2000.0, 32.5, -175142.9, -64762.7 + 0.8, 2000.0, 33.0, -182153.6, -67552.5 + 0.8, 2000.0, 33.5, -189164.8, -70379.4 + 0.8, 2000.0, 34.0, -196176.4, -73254.3 + 0.8, 2000.0, 34.5, -203195.3, -76800.7 + 0.8, 2000.0, 35.0, -210213.9, -80359.0 + 0.8, 2000.0, 35.5, -217231.6, -83882.1 + 0.8, 2000.0, 36.0, -224247.7, -87322.7 + 0.8, 2000.0, 36.5, -231261.6, -90633.5 + 0.8, 2000.0, 37.0, -238272.5, -93767.5 + 0.8, 2000.0, 37.5, -245279.9, -96677.2 + 0.8, 2000.0, 38.0, -252282.9, -99315.6 + 0.8, 2000.0, 38.5, -259268.7, -101217.0 + 0.8, 2000.0, 39.0, -266255.2, -102969.0 + 0.8, 2000.0, 39.5, -273244.6, -104619.0 + 0.8, 2000.0, 40.0, -280238.8, -106211.0 + 0.8, 2000.0, 40.5, -287250.5, -107671.0 + 0.8, 2000.0, 41.0, -294267.1, -109214.0 + 0.8, 2000.0, 41.5, -301286.2, -110933.0 + 0.8, 2000.0, 42.0, -308305.8, -112922.0 + 0.8, 2000.0, 42.5, -315312.8, -115593.0 + 0.8, 2000.0, 43.0, -322320.2, -118594.0 + 0.8, 2000.0, 43.5, -329330.3, -121890.0 + 0.8, 2000.0, 44.0, -336345.3, -125446.0 + 0.8, 2000.0, 44.5, -343388.8, -129257.0 + 0.8, 2000.0, 45.0, -350432.9, -133249.0 + 0.8, 2000.0, 45.5, -357471.3, -137374.0 + 0.8, 2000.0, 46.0, -364497.5, -141586.0 + 0.8, 2000.0, 46.5, -371471.0, -145723.0 + 0.8, 2000.0, 47.0, -378433.2, -149901.0 + 0.8, 2000.0, 47.5, -385391.3, -154121.0 + 0.8, 2000.0, 48.0, -392352.7, -158383.0 + 0.8, 2000.0, 48.5, -399324.6, -162688.0 + 0.8, 2000.0, 49.0, -406314.2, -167035.0 + 0.8, 2000.0, 49.5, -413328.8, -171427.0 + 0.8, 2000.0, 50.0, -420375.7, -175862.0 + 0.8, 5000.0, 0.0, 627.5089, 627.509 + 0.8, 5000.0, 22.0, 39769.9, 15068.3 + 0.8, 5000.0, 22.5, 47330.9, 17580.3 + 0.8, 5000.0, 23.0, 54809.37, 20015.5 + 0.8, 5000.0, 23.5, 62231.97, 22401.4 + 0.8, 5000.0, 24.0, 69625.4, 24765.1 + 0.8, 5000.0, 24.5, 77016.33, 27134.1 + 0.8, 5000.0, 25.0, 84431.43, 29535.7 + 0.8, 5000.0, 25.5, 91897.4, 31997.2 + 0.8, 5000.0, 26.0, 99440.9, 34545.9 + 0.8, 5000.0, 26.5, 107366.9, 37480.6 + 0.8, 5000.0, 27.0, 115439.7, 40572.7 + 0.8, 5000.0, 27.5, 123638.3, 43803.1 + 0.8, 5000.0, 28.0, 131941.6, 47152.6 + 0.8, 5000.0, 28.5, 140328.6, 50601.9 + 0.8, 5000.0, 29.0, 148778.4, 54131.9 + 0.8, 5000.0, 29.5, 157269.8, 57723.4 + 0.8, 5000.0, 30.0, 165781.8, 61357.2 + 0.8, 5000.0, 30.5, 174072.9, 64849.5 + 0.8, 5000.0, 31.0, 182363.6, 68361.3 + 0.8, 5000.0, 31.5, 190653.9, 71889.4 + 0.8, 5000.0, 32.0, 198943.7, 75430.0 + 0.8, 5000.0, 32.5, 207233.1, 78979.8 + 0.8, 5000.0, 33.0, 215522.0, 82535.2 + 0.8, 5000.0, 33.5, 223810.3, 86092.7 + 0.8, 5000.0, 34.0, 232098.2, 89648.9 + 0.8, 5000.0, 34.5, 240383.4, 93250.5 + 0.8, 5000.0, 35.0, 248668.3, 96838.9 + 0.8, 5000.0, 35.5, 256952.9, 100406.0 + 0.8, 5000.0, 36.0, 265237.6, 103943.0 + 0.8, 5000.0, 36.5, 273522.4, 107442.0 + 0.8, 5000.0, 37.0, 281807.6, 110895.0 + 0.8, 5000.0, 37.5, 290093.2, 114293.0 + 0.8, 5000.0, 38.0, 298379.6, 117629.0 + 0.8, 5000.0, 38.5, 306669.0, 120838.0 + 0.8, 5000.0, 39.0, 314958.4, 123996.0 + 0.8, 5000.0, 39.5, 323247.3, 127108.0 + 0.8, 5000.0, 40.0, 331535.6, 130176.0 + 0.8, 5000.0, 40.5, 339819.3, 133124.0 + 0.8, 5000.0, 41.0, 348103.1, 136070.0 + 0.8, 5000.0, 41.5, 356388.2, 139048.0 + 0.8, 5000.0, 42.0, 364675.6, 142096.0 + 0.8, 5000.0, 42.5, 372967.2, 145319.0 + 0.8, 5000.0, 43.0, 381263.1, 148656.0 + 0.8, 5000.0, 43.5, 389564.3, 152116.0 + 0.8, 5000.0, 44.0, 397871.6, 155706.0 + 0.8, 5000.0, 44.5, 406205.9, 159481.0 + 0.8, 5000.0, 45.0, 414540.0, 163387.0 + 0.8, 5000.0, 45.5, 422866.9, 167414.0 + 0.8, 5000.0, 46.0, 431179.5, 171553.0 + 0.8, 5000.0, 46.5, 439432.8, 175836.0 + 0.8, 5000.0, 47.0, 447672.7, 180197.0 + 0.8, 5000.0, 47.5, 455907.3, 184608.0 + 0.8, 5000.0, 48.0, 464144.5, 189042.0 + 0.8, 5000.0, 48.5, 472392.5, 193474.0 + 0.8, 5000.0, 49.0, 480659.2, 197878.0 + 0.8, 5000.0, 49.5, 488952.7, 202227.0 + 0.8, 5000.0, 50.0, 497281.0, 206495.0 + 0.8, 10000.0, 0.0, 528.1385, 528.138 + 0.8, 10000.0, 22.0, 665.8, 1090.0 + 0.8, 10000.0, 22.5, 785.9016, 1218.85 + 0.8, 10000.0, 23.0, 907.6375, 1322.32 + 0.8, 10000.0, 23.5, 1031.005, 1404.28 + 0.8, 10000.0, 24.0, 1156.0, 1468.6 + 0.8, 10000.0, 24.5, 1282.62, 1519.14 + 0.8, 10000.0, 25.0, 1410.863, 1559.78 + 0.8, 10000.0, 25.5, 1540.723, 1594.37 + 0.8, 10000.0, 26.0, 1672.2, 1626.8 + 0.8, 10000.0, 26.5, 1806.438, 1698.88 + 0.8, 10000.0, 27.0, 1942.35, 1778.7 + 0.8, 10000.0, 27.5, 2079.738, 1863.61 + 0.8, 10000.0, 28.0, 2218.4, 1950.99 + 0.8, 10000.0, 28.5, 2358.138, 2038.18 + 0.8, 10000.0, 29.0, 2498.75, 2122.55 + 0.8, 10000.0, 29.5, 2640.038, 2201.47 + 0.8, 10000.0, 30.0, 2781.8, 2272.3 + 0.8, 10000.0, 30.5, 2922.457, 2281.27 + 0.8, 10000.0, 31.0, 3063.321, 2281.74 + 0.8, 10000.0, 31.5, 3204.323, 2275.94 + 0.8, 10000.0, 32.0, 3345.394, 2266.09 + 0.8, 10000.0, 32.5, 3486.466, 2254.44 + 0.8, 10000.0, 33.0, 3627.47, 2243.2 + 0.8, 10000.0, 33.5, 3768.337, 2234.61 + 0.8, 10000.0, 34.0, 3909.0, 2230.9 + 0.8, 10000.0, 34.5, 4048.885, 2265.98 + 0.8, 10000.0, 35.0, 4188.477, 2307.38 + 0.8, 10000.0, 35.5, 4327.753, 2354.32 + 0.8, 10000.0, 36.0, 4466.695, 2406.01 + 0.8, 10000.0, 36.5, 4605.281, 2461.66 + 0.8, 10000.0, 37.0, 4743.491, 2520.48 + 0.8, 10000.0, 37.5, 4881.304, 2581.69 + 0.8, 10000.0, 38.0, 5018.7, 2644.5 + 0.8, 10000.0, 38.5, 5154.291, 2727.79 + 0.8, 10000.0, 39.0, 5290.133, 2800.92 + 0.8, 10000.0, 39.5, 5426.508, 2858.7 + 0.8, 10000.0, 40.0, 5563.7, 2896.0 + 0.8, 10000.0, 40.5, 5703.309, 2845.16 + 0.8, 10000.0, 41.0, 5843.775, 2788.5 + 0.8, 10000.0, 41.5, 5984.853, 2745.87 + 0.8, 10000.0, 42.0, 6126.3, 2737.1 + 0.8, 10000.0, 42.5, 6267.438, 2863.12 + 0.8, 10000.0, 43.0, 6408.631, 3030.25 + 0.8, 10000.0, 43.5, 6549.809, 3225.87 + 0.8, 10000.0, 44.0, 6690.9, 3437.4 + 0.8, 10000.0, 44.5, 6831.663, 3620.32 + 0.8, 10000.0, 45.0, 6972.269, 3806.7 + 0.8, 10000.0, 45.5, 7112.715, 3996.71 + 0.8, 10000.0, 46.0, 7253.0, 4190.5 + 0.8, 10000.0, 46.5, 7393.365, 4415.21 + 0.8, 10000.0, 47.0, 7533.469, 4633.24 + 0.8, 10000.0, 47.5, 7673.213, 4833.98 + 0.8, 10000.0, 48.0, 7812.5, 5006.8 + 0.8, 10000.0, 48.5, 7951.23, 5141.07 + 0.8, 10000.0, 49.0, 8089.306, 5226.18 + 0.8, 10000.0, 49.5, 8226.629, 5251.5 + 0.8, 10000.0, 50.0, 8363.1, 5206.4 + 0.8, 15000.0, 0.0, 441.6259, 441.626 + 0.8, 15000.0, 22.0, 650.6, 1083.6 + 0.8, 15000.0, 22.5, 772.6256, 1141.34 + 0.8, 15000.0, 23.0, 893.9828, 1199.82 + 0.8, 15000.0, 23.5, 1014.999, 1258.94 + 0.8, 15000.0, 24.0, 1136.0, 1318.6 + 0.8, 15000.0, 24.5, 1257.314, 1378.72 + 0.8, 15000.0, 25.0, 1379.267, 1439.21 + 0.8, 15000.0, 25.5, 1502.187, 1499.96 + 0.8, 15000.0, 26.0, 1626.4, 1560.9 + 0.8, 15000.0, 26.5, 1755.891, 1620.95 + 0.8, 15000.0, 27.0, 1887.537, 1680.94 + 0.8, 15000.0, 27.5, 2021.041, 1740.95 + 0.8, 15000.0, 28.0, 2156.1, 1801.05 + 0.8, 15000.0, 28.5, 2292.416, 1861.3 + 0.8, 15000.0, 29.0, 2429.687, 1921.8 + 0.8, 15000.0, 29.5, 2567.616, 1982.61 + 0.8, 15000.0, 30.0, 2705.9, 2043.8 + 0.8, 15000.0, 30.5, 2841.175, 2106.15 + 0.8, 15000.0, 31.0, 2976.498, 2168.97 + 0.8, 15000.0, 31.5, 3111.861, 2232.27 + 0.8, 15000.0, 32.0, 3247.256, 2296.06 + 0.8, 15000.0, 32.5, 3382.676, 2360.33 + 0.8, 15000.0, 33.0, 3518.112, 2425.11 + 0.8, 15000.0, 33.5, 3653.556, 2490.4 + 0.8, 15000.0, 34.0, 3789.0, 2556.2 + 0.8, 15000.0, 34.5, 3924.242, 2628.36 + 0.8, 15000.0, 35.0, 4059.486, 2700.5 + 0.8, 15000.0, 35.5, 4194.744, 2772.07 + 0.8, 15000.0, 36.0, 4330.025, 2842.52 + 0.8, 15000.0, 36.5, 4465.341, 2911.31 + 0.8, 15000.0, 37.0, 4600.702, 2977.88 + 0.8, 15000.0, 37.5, 4736.118, 3041.69 + 0.8, 15000.0, 38.0, 4871.6, 3102.2 + 0.8, 15000.0, 38.5, 5007.364, 3150.56 + 0.8, 15000.0, 39.0, 5143.109, 3198.82 + 0.8, 15000.0, 39.5, 5278.8, 3248.27 + 0.8, 15000.0, 40.0, 5414.4, 3300.2 + 0.8, 15000.0, 40.5, 5549.69, 3360.81 + 0.8, 15000.0, 41.0, 5684.894, 3424.53 + 0.8, 15000.0, 41.5, 5820.051, 3490.72 + 0.8, 15000.0, 42.0, 5955.2, 3558.7 + 0.8, 15000.0, 42.5, 6090.314, 3627.26 + 0.8, 15000.0, 43.0, 6225.525, 3696.52 + 0.8, 15000.0, 43.5, 6360.898, 3766.04 + 0.8, 15000.0, 44.0, 6496.5, 3835.4 + 0.8, 15000.0, 44.5, 6633.13, 3901.24 + 0.8, 15000.0, 45.0, 6769.825, 3967.19 + 0.8, 15000.0, 45.5, 6906.358, 4034.01 + 0.8, 15000.0, 46.0, 7042.5, 4102.4 + 0.8, 15000.0, 46.5, 7176.844, 4177.36 + 0.8, 15000.0, 47.0, 7310.812, 4253.67 + 0.8, 15000.0, 47.5, 7444.65, 4330.34 + 0.8, 15000.0, 48.0, 7578.6, 4406.4 + 0.8, 15000.0, 48.5, 7712.906, 4480.88 + 0.8, 15000.0, 49.0, 7847.812, 4552.81 + 0.8, 15000.0, 49.5, 7983.562, 4621.2 + 0.8, 15000.0, 50.0, 8120.4, 4685.1 + 0.8, 20000.0, 0.0, 366.713, 366.713 + 0.8, 20000.0, 22.0, 751.0, 1019.0 + 0.8, 20000.0, 22.5, 893.4732, 1081.28 + 0.8, 20000.0, 23.0, 1034.489, 1143.73 + 0.8, 20000.0, 23.5, 1174.535, 1206.43 + 0.8, 20000.0, 24.0, 1314.1, 1269.5 + 0.8, 20000.0, 24.5, 1453.671, 1333.05 + 0.8, 20000.0, 25.0, 1593.736, 1397.18 + 0.8, 20000.0, 25.5, 1734.783, 1461.99 + 0.8, 20000.0, 26.0, 1877.3, 1527.6 + 0.8, 20000.0, 26.5, 2026.903, 1595.42 + 0.8, 20000.0, 27.0, 2179.245, 1664.31 + 0.8, 20000.0, 27.5, 2333.934, 1734.17 + 0.8, 20000.0, 28.0, 2490.58, 1804.87 + 0.8, 20000.0, 28.5, 2648.791, 1876.31 + 0.8, 20000.0, 29.0, 2808.175, 1948.35 + 0.8, 20000.0, 29.5, 2968.342, 2020.89 + 0.8, 20000.0, 30.0, 3128.9, 2093.8 + 0.8, 20000.0, 30.5, 3285.35, 2165.8 + 0.8, 20000.0, 31.0, 3441.8, 2238.05 + 0.8, 20000.0, 31.5, 3598.25, 2310.54 + 0.8, 20000.0, 32.0, 3754.7, 2383.27 + 0.8, 20000.0, 32.5, 3911.15, 2456.24 + 0.8, 20000.0, 33.0, 4067.6, 2529.44 + 0.8, 20000.0, 33.5, 4224.05, 2602.86 + 0.8, 20000.0, 34.0, 4380.5, 2676.5 + 0.8, 20000.0, 34.5, 4536.95, 2749.93 + 0.8, 20000.0, 35.0, 4693.4, 2823.6 + 0.8, 20000.0, 35.5, 4849.85, 2897.56 + 0.8, 20000.0, 36.0, 5006.3, 2971.83 + 0.8, 20000.0, 36.5, 5162.75, 3046.44 + 0.8, 20000.0, 37.0, 5319.2, 3121.43 + 0.8, 20000.0, 37.5, 5475.65, 3196.84 + 0.8, 20000.0, 38.0, 5632.1, 3272.7 + 0.8, 20000.0, 38.5, 5788.555, 3349.29 + 0.8, 20000.0, 39.0, 5945.008, 3426.27 + 0.8, 20000.0, 39.5, 6101.456, 3503.61 + 0.8, 20000.0, 40.0, 6257.9, 3581.3 + 0.8, 20000.0, 40.5, 6414.323, 3658.8 + 0.8, 20000.0, 41.0, 6570.744, 3736.81 + 0.8, 20000.0, 41.5, 6727.168, 3815.51 + 0.8, 20000.0, 42.0, 6883.6, 3895.1 + 0.8, 20000.0, 42.5, 7039.951, 3976.63 + 0.8, 20000.0, 43.0, 7196.356, 4059.06 + 0.8, 20000.0, 43.5, 7352.859, 4142.24 + 0.8, 20000.0, 44.0, 7509.5, 4226.0 + 0.8, 20000.0, 44.5, 7666.78, 4309.41 + 0.8, 20000.0, 45.0, 7824.1, 4393.39 + 0.8, 20000.0, 45.5, 7981.32, 4478.07 + 0.8, 20000.0, 46.0, 8138.3, 4563.6 + 0.8, 20000.0, 46.5, 8294.187, 4650.18 + 0.8, 20000.0, 47.0, 8449.837, 4737.87 + 0.8, 20000.0, 47.5, 8605.394, 4826.81 + 0.8, 20000.0, 48.0, 8761.0, 4917.1 + 0.8, 20000.0, 48.5, 8916.8, 5008.87 + 0.8, 20000.0, 49.0, 9072.937, 5102.25 + 0.8, 20000.0, 49.5, 9229.556, 5197.35 + 0.8, 20000.0, 50.0, 9386.8, 5294.3 + 0.8, 25000.0, 0.0, 302.2135, 302.213 + 0.8, 25000.0, 22.0, 626.5, 839.1 + 0.8, 25000.0, 22.5, 745.4023, 891.168 + 0.8, 25000.0, 23.0, 863.0813, 943.003 + 0.8, 25000.0, 23.5, 979.9445, 994.736 + 0.8, 25000.0, 24.0, 1096.4, 1046.5 + 0.8, 25000.0, 24.5, 1212.855, 1098.43 + 0.8, 25000.0, 25.0, 1329.719, 1150.65 + 0.8, 25000.0, 25.5, 1447.398, 1203.29 + 0.8, 25000.0, 26.0, 1566.3, 1256.5 + 0.8, 25000.0, 26.5, 1691.116, 1311.76 + 0.8, 25000.0, 27.0, 1818.215, 1367.91 + 0.8, 25000.0, 27.5, 1947.272, 1424.87 + 0.8, 25000.0, 28.0, 2077.96, 1482.52 + 0.8, 25000.0, 28.5, 2209.953, 1540.77 + 0.8, 25000.0, 29.0, 2342.925, 1599.52 + 0.8, 25000.0, 29.5, 2476.549, 1658.66 + 0.8, 25000.0, 30.0, 2610.5, 1718.1 + 0.8, 25000.0, 30.5, 2741.025, 1776.59 + 0.8, 25000.0, 31.0, 2871.55, 1835.28 + 0.8, 25000.0, 31.5, 3002.075, 1894.18 + 0.8, 25000.0, 32.0, 3132.6, 1953.3 + 0.8, 25000.0, 32.5, 3263.125, 2012.64 + 0.8, 25000.0, 33.0, 3393.65, 2072.22 + 0.8, 25000.0, 33.5, 3524.175, 2132.04 + 0.8, 25000.0, 34.0, 3654.7, 2192.1 + 0.8, 25000.0, 34.5, 3785.225, 2252.47 + 0.8, 25000.0, 35.0, 3915.75, 2313.09 + 0.8, 25000.0, 35.5, 4046.275, 2373.98 + 0.8, 25000.0, 36.0, 4176.8, 2435.14 + 0.8, 25000.0, 36.5, 4307.325, 2496.57 + 0.8, 25000.0, 37.0, 4437.85, 2558.27 + 0.8, 25000.0, 37.5, 4568.375, 2620.24 + 0.8, 25000.0, 38.0, 4698.9, 2682.5 + 0.8, 25000.0, 38.5, 4829.425, 2744.97 + 0.8, 25000.0, 39.0, 4959.95, 2807.76 + 0.8, 25000.0, 39.5, 5090.475, 2870.9 + 0.8, 25000.0, 40.0, 5221.0, 2934.4 + 0.8, 25000.0, 40.5, 5351.521, 2998.12 + 0.8, 25000.0, 41.0, 5482.044, 3062.3 + 0.8, 25000.0, 41.5, 5612.57, 3127.03 + 0.8, 25000.0, 42.0, 5743.1, 3192.4 + 0.8, 25000.0, 42.5, 5873.551, 3258.86 + 0.8, 25000.0, 43.0, 6004.044, 3325.98 + 0.8, 25000.0, 43.5, 6134.615, 3393.68 + 0.8, 25000.0, 44.0, 6265.3, 3461.9 + 0.8, 25000.0, 44.5, 6396.518, 3529.98 + 0.8, 25000.0, 45.0, 6527.769, 3598.68 + 0.8, 25000.0, 45.5, 6658.935, 3668.16 + 0.8, 25000.0, 46.0, 6789.9, 3738.6 + 0.8, 25000.0, 46.5, 6919.952, 3810.67 + 0.8, 25000.0, 47.0, 7049.806, 3883.84 + 0.8, 25000.0, 47.5, 7179.582, 3958.06 + 0.8, 25000.0, 48.0, 7309.4, 4033.3 + 0.8, 25000.0, 48.5, 7439.38, 4109.53 + 0.8, 25000.0, 49.0, 7569.644, 4186.71 + 0.8, 25000.0, 49.5, 7700.31, 4264.81 + 0.8, 25000.0, 50.0, 7831.5, 4343.8 + 0.8, 30000.0, 0.0, 247.0241, 247.024 + 0.8, 30000.0, 22.0, 504.8, 678.2 + 0.8, 30000.0, 22.5, 600.6025, 718.903 + 0.8, 30000.0, 23.0, 695.4172, 759.525 + 0.8, 30000.0, 23.5, 789.5732, 800.159 + 0.8, 30000.0, 24.0, 883.4, 840.9 + 0.8, 30000.0, 24.5, 977.2268, 881.841 + 0.8, 30000.0, 25.0, 1071.383, 923.075 + 0.8, 30000.0, 25.5, 1166.197, 964.697 + 0.8, 30000.0, 26.0, 1262.0, 1006.8 + 0.8, 30000.0, 26.5, 1362.58, 1050.46 + 0.8, 30000.0, 27.0, 1465.004, 1094.85 + 0.8, 30000.0, 27.5, 1569.009, 1139.89 + 0.8, 30000.0, 28.0, 1674.33, 1185.5 + 0.8, 30000.0, 28.5, 1780.704, 1231.62 + 0.8, 30000.0, 29.0, 1887.866, 1278.15 + 0.8, 30000.0, 29.5, 1995.552, 1325.04 + 0.8, 30000.0, 30.0, 2103.5, 1372.2 + 0.8, 30000.0, 30.5, 2208.665, 1418.85 + 0.8, 30000.0, 31.0, 2313.828, 1465.69 + 0.8, 30000.0, 31.5, 2418.989, 1512.72 + 0.8, 30000.0, 32.0, 2524.15, 1559.92 + 0.8, 30000.0, 32.5, 2629.311, 1607.28 + 0.8, 30000.0, 33.0, 2734.472, 1654.81 + 0.8, 30000.0, 33.5, 2839.635, 1702.48 + 0.8, 30000.0, 34.0, 2944.8, 1750.3 + 0.8, 30000.0, 34.5, 3049.985, 1798.01 + 0.8, 30000.0, 35.0, 3155.172, 1845.88 + 0.8, 30000.0, 35.5, 3260.361, 1893.91 + 0.8, 30000.0, 36.0, 3365.55, 1942.11 + 0.8, 30000.0, 36.5, 3470.739, 1990.51 + 0.8, 30000.0, 37.0, 3575.928, 2039.11 + 0.8, 30000.0, 37.5, 3681.115, 2087.94 + 0.8, 30000.0, 38.0, 3786.3, 2137.0 + 0.8, 30000.0, 38.5, 3891.476, 2186.35 + 0.8, 30000.0, 39.0, 3996.652, 2235.94 + 0.8, 30000.0, 39.5, 4101.826, 2285.79 + 0.8, 30000.0, 40.0, 4207.0, 2335.9 + 0.8, 30000.0, 40.5, 4312.179, 2386.12 + 0.8, 30000.0, 41.0, 4417.356, 2436.67 + 0.8, 30000.0, 41.5, 4522.53, 2487.65 + 0.8, 30000.0, 42.0, 4627.7, 2539.1 + 0.8, 30000.0, 42.5, 4732.77, 2591.43 + 0.8, 30000.0, 43.0, 4837.869, 2644.26 + 0.8, 30000.0, 43.5, 4943.034, 2697.53 + 0.8, 30000.0, 44.0, 5048.3, 2751.2 + 0.8, 30000.0, 44.5, 5154.044, 2804.8 + 0.8, 30000.0, 45.0, 5259.825, 2858.84 + 0.8, 30000.0, 45.5, 5365.544, 2913.44 + 0.8, 30000.0, 46.0, 5471.1, 2968.7 + 0.8, 30000.0, 46.5, 5575.898, 3024.97 + 0.8, 30000.0, 47.0, 5680.531, 3082.02 + 0.8, 30000.0, 47.5, 5785.099, 3139.9 + 0.8, 30000.0, 48.0, 5889.7, 3198.6 + 0.8, 30000.0, 48.5, 5994.432, 3258.15 + 0.8, 30000.0, 49.0, 6099.394, 3318.57 + 0.8, 30000.0, 49.5, 6204.684, 3379.88 + 0.8, 30000.0, 50.0, 6310.4, 3442.1 + 0.8, 35000.0, 0.0, 200.1176, 200.118 + 0.8, 35000.0, 22.0, 390.0, 557.8 + 0.8, 35000.0, 22.5, 463.9975, 589.103 + 0.8, 35000.0, 23.0, 537.2453, 620.173 + 0.8, 35000.0, 23.5, 609.9955, 651.107 + 0.8, 35000.0, 24.0, 682.5, 682.0 + 0.8, 35000.0, 24.5, 755.0107, 712.949 + 0.8, 35000.0, 25.0, 827.7797, 744.052 + 0.8, 35000.0, 25.5, 901.0588, 775.403 + 0.8, 35000.0, 26.0, 975.1, 807.1 + 0.8, 35000.0, 26.5, 1052.806, 840.065 + 0.8, 35000.0, 27.0, 1131.93, 873.616 + 0.8, 35000.0, 27.5, 1212.269, 907.708 + 0.8, 35000.0, 28.0, 1293.62, 942.295 + 0.8, 35000.0, 28.5, 1375.781, 977.333 + 0.8, 35000.0, 29.0, 1458.55, 1012.78 + 0.8, 35000.0, 29.5, 1541.724, 1048.58 + 0.8, 35000.0, 30.0, 1625.1, 1084.7 + 0.8, 35000.0, 30.5, 1706.35, 1121.0 + 0.8, 35000.0, 31.0, 1787.6, 1157.54 + 0.8, 35000.0, 31.5, 1868.85, 1194.28 + 0.8, 35000.0, 32.0, 1950.1, 1231.17 + 0.8, 35000.0, 32.5, 2031.35, 1268.18 + 0.8, 35000.0, 33.0, 2112.6, 1305.29 + 0.8, 35000.0, 33.5, 2193.85, 1342.44 + 0.8, 35000.0, 34.0, 2275.1, 1379.6 + 0.8, 35000.0, 34.5, 2356.343, 1416.03 + 0.8, 35000.0, 35.0, 2437.587, 1452.46 + 0.8, 35000.0, 35.5, 2518.833, 1488.92 + 0.8, 35000.0, 36.0, 2600.08, 1525.46 + 0.8, 35000.0, 36.5, 2681.33, 1562.09 + 0.8, 35000.0, 37.0, 2762.582, 1598.86 + 0.8, 35000.0, 37.5, 2843.839, 1635.78 + 0.8, 35000.0, 38.0, 2925.1, 1672.9 + 0.8, 35000.0, 38.5, 3006.378, 1710.37 + 0.8, 35000.0, 39.0, 3087.655, 1748.02 + 0.8, 35000.0, 39.5, 3168.929, 1785.87 + 0.8, 35000.0, 40.0, 3250.2, 1823.9 + 0.8, 35000.0, 40.5, 3331.455, 1862.0 + 0.8, 35000.0, 41.0, 3412.706, 1900.35 + 0.8, 35000.0, 41.5, 3493.954, 1939.0 + 0.8, 35000.0, 42.0, 3575.2, 1978.0 + 0.8, 35000.0, 42.5, 3656.384, 2017.66 + 0.8, 35000.0, 43.0, 3737.594, 2057.68 + 0.8, 35000.0, 43.5, 3818.857, 2098.01 + 0.8, 35000.0, 44.0, 3900.2, 2138.6 + 0.8, 35000.0, 44.5, 3981.915, 2178.96 + 0.8, 35000.0, 45.0, 4063.656, 2219.66 + 0.8, 35000.0, 45.5, 4145.345, 2260.83 + 0.8, 35000.0, 46.0, 4226.9, 2302.6 + 0.8, 35000.0, 46.5, 4307.845, 2345.32 + 0.8, 35000.0, 47.0, 4388.656, 2388.82 + 0.8, 35000.0, 47.5, 4469.415, 2433.13 + 0.8, 35000.0, 48.0, 4550.2, 2478.3 + 0.8, 35000.0, 48.5, 4631.091, 2524.37 + 0.8, 35000.0, 49.0, 4712.169, 2571.38 + 0.8, 35000.0, 49.5, 4793.512, 2619.38 + 0.8, 35000.0, 50.0, 4875.2, 2668.4 + 0.8, 39000.0, 0.0, 165.9797, 165.98 + 0.8, 39000.0, 22.0, 312.3, 479.2 + 0.8, 39000.0, 22.5, 371.5609, 503.898 + 0.8, 39000.0, 23.0, 430.2125, 528.6 + 0.8, 39000.0, 23.5, 488.4578, 553.352 + 0.8, 39000.0, 24.0, 546.5, 578.2 + 0.8, 39000.0, 24.5, 604.5422, 603.192 + 0.8, 39000.0, 25.0, 662.7875, 628.375 + 0.8, 39000.0, 25.5, 721.4391, 653.795 + 0.8, 39000.0, 26.0, 780.7, 679.5 + 0.8, 39000.0, 26.5, 842.9062, 705.945 + 0.8, 39000.0, 27.0, 906.25, 732.791 + 0.8, 39000.0, 27.5, 970.5687, 760.015 + 0.8, 39000.0, 28.0, 1035.7, 787.595 + 0.8, 39000.0, 28.5, 1101.481, 815.506 + 0.8, 39000.0, 29.0, 1167.75, 843.727 + 0.8, 39000.0, 29.5, 1234.344, 872.232 + 0.8, 39000.0, 30.0, 1301.1, 901.0 + 0.8, 39000.0, 30.5, 1366.148, 929.856 + 0.8, 39000.0, 31.0, 1431.196, 958.941 + 0.8, 39000.0, 31.5, 1496.245, 988.249 + 0.8, 39000.0, 32.0, 1561.294, 1017.77 + 0.8, 39000.0, 32.5, 1626.344, 1047.49 + 0.8, 39000.0, 33.0, 1691.395, 1077.41 + 0.8, 39000.0, 33.5, 1756.447, 1107.52 + 0.8, 39000.0, 34.0, 1821.5, 1137.8 + 0.8, 39000.0, 34.5, 1886.563, 1168.6 + 0.8, 39000.0, 35.0, 1951.627, 1199.53 + 0.8, 39000.0, 35.5, 2016.691, 1230.54 + 0.8, 39000.0, 36.0, 2081.755, 1261.6 + 0.8, 39000.0, 36.5, 2146.819, 1292.66 + 0.8, 39000.0, 37.0, 2211.881, 1323.67 + 0.8, 39000.0, 37.5, 2276.942, 1354.6 + 0.8, 39000.0, 38.0, 2342.0, 1385.4 + 0.8, 39000.0, 38.5, 2407.046, 1415.6 + 0.8, 39000.0, 39.0, 2472.094, 1445.81 + 0.8, 39000.0, 39.5, 2537.145, 1476.09 + 0.8, 39000.0, 40.0, 2602.2, 1506.5 + 0.8, 39000.0, 40.5, 2667.273, 1537.16 + 0.8, 39000.0, 41.0, 2732.35, 1568.03 + 0.8, 39000.0, 41.5, 2797.427, 1599.14 + 0.8, 39000.0, 42.0, 2862.5, 1630.5 + 0.8, 39000.0, 42.5, 2927.505, 1662.3 + 0.8, 39000.0, 43.0, 2992.525, 1694.35 + 0.8, 39000.0, 43.5, 3057.583, 1726.63 + 0.8, 39000.0, 44.0, 3122.7, 1759.1 + 0.8, 39000.0, 44.5, 3188.105, 1791.52 + 0.8, 39000.0, 45.0, 3253.531, 1824.15 + 0.8, 39000.0, 45.5, 3318.916, 1857.06 + 0.8, 39000.0, 46.0, 3384.2, 1890.3 + 0.8, 39000.0, 46.5, 3449.016, 1923.75 + 0.8, 39000.0, 47.0, 3513.731, 1957.72 + 0.8, 39000.0, 47.5, 3578.405, 1992.33 + 0.8, 39000.0, 48.0, 3643.1, 2027.7 + 0.8, 39000.0, 48.5, 3707.876, 2063.97 + 0.8, 39000.0, 49.0, 3772.794, 2101.26 + 0.8, 39000.0, 49.5, 3837.915, 2139.69 + 0.8, 39000.0, 50.0, 3903.3, 2179.4 + 0.8, 43000.0, 0.0, 136.9496, 136.95 + 0.8, 43000.0, 22.0, 252.1, 420.3 + 0.8, 43000.0, 22.5, 299.9729, 440.829 + 0.8, 43000.0, 23.0, 347.3547, 461.219 + 0.8, 43000.0, 23.5, 394.4092, 481.524 + 0.8, 43000.0, 24.0, 441.3, 501.8 + 0.8, 43000.0, 24.5, 488.1908, 522.101 + 0.8, 43000.0, 25.0, 535.2453, 542.481 + 0.8, 43000.0, 25.5, 582.6271, 562.996 + 0.8, 43000.0, 26.0, 630.5, 583.7 + 0.8, 43000.0, 26.5, 680.7461, 605.041 + 0.8, 43000.0, 27.0, 731.9087, 626.704 + 0.8, 43000.0, 27.5, 783.857, 648.674 + 0.8, 43000.0, 28.0, 836.46, 670.94 + 0.8, 43000.0, 28.5, 889.5867, 693.488 + 0.8, 43000.0, 29.0, 943.1062, 716.306 + 0.8, 43000.0, 29.5, 996.8877, 739.381 + 0.8, 43000.0, 30.0, 1050.8, 762.7 + 0.8, 43000.0, 30.5, 1103.338, 786.243 + 0.8, 43000.0, 31.0, 1155.875, 810.005 + 0.8, 43000.0, 31.5, 1208.413, 833.974 + 0.8, 43000.0, 32.0, 1260.95, 858.138 + 0.8, 43000.0, 32.5, 1313.488, 882.484 + 0.8, 43000.0, 33.0, 1366.025, 907.002 + 0.8, 43000.0, 33.5, 1418.563, 931.678 + 0.8, 43000.0, 34.0, 1471.1, 956.5 + 0.8, 43000.0, 34.5, 1523.641, 981.712 + 0.8, 43000.0, 35.0, 1576.181, 1007.02 + 0.8, 43000.0, 35.5, 1628.721, 1032.39 + 0.8, 43000.0, 36.0, 1681.26, 1057.79 + 0.8, 43000.0, 36.5, 1733.798, 1083.18 + 0.8, 43000.0, 37.0, 1786.334, 1108.51 + 0.8, 43000.0, 37.5, 1838.868, 1133.77 + 0.8, 43000.0, 38.0, 1891.4, 1158.9 + 0.8, 43000.0, 38.5, 1943.921, 1183.48 + 0.8, 43000.0, 39.0, 1996.444, 1208.08 + 0.8, 43000.0, 39.5, 2048.97, 1232.73 + 0.8, 43000.0, 40.0, 2101.5, 1257.5 + 0.8, 43000.0, 40.5, 2154.048, 1282.52 + 0.8, 43000.0, 41.0, 2206.6, 1307.72 + 0.8, 43000.0, 41.5, 2259.152, 1333.11 + 0.8, 43000.0, 42.0, 2311.7, 1358.7 + 0.8, 43000.0, 42.5, 2364.184, 1384.58 + 0.8, 43000.0, 43.0, 2416.681, 1410.65 + 0.8, 43000.0, 43.5, 2469.213, 1436.9 + 0.8, 43000.0, 44.0, 2521.8, 1463.3 + 0.8, 43000.0, 44.5, 2574.649, 1489.65 + 0.8, 43000.0, 45.0, 2627.519, 1516.19 + 0.8, 43000.0, 45.5, 2680.354, 1542.99 + 0.8, 43000.0, 46.0, 2733.1, 1570.1 + 0.8, 43000.0, 46.5, 2785.429, 1597.49 + 0.8, 43000.0, 47.0, 2837.669, 1625.35 + 0.8, 43000.0, 47.5, 2889.874, 1653.79 + 0.8, 43000.0, 48.0, 2942.1, 1682.9 + 0.8, 43000.0, 48.5, 2994.401, 1712.79 + 0.8, 43000.0, 49.0, 3046.831, 1743.55 + 0.8, 43000.0, 49.5, 3099.446, 1775.29 + 0.8, 43000.0, 50.0, 3152.3, 1808.1 + 0.8, 48000.0, 0.0, 107.6944, 107.694 + 0.8, 48000.0, 22.0, 198.5, 331.0 + 0.8, 48000.0, 22.5, 236.2012, 347.172 + 0.8, 48000.0, 23.0, 273.5156, 363.234 + 0.8, 48000.0, 23.5, 310.5723, 379.229 + 0.8, 48000.0, 24.0, 347.5, 395.2 + 0.8, 48000.0, 24.5, 384.4277, 411.189 + 0.8, 48000.0, 25.0, 421.4844, 427.241 + 0.8, 48000.0, 25.5, 458.7988, 443.396 + 0.8, 48000.0, 26.0, 496.5, 459.7 + 0.8, 48000.0, 26.5, 536.0703, 476.502 + 0.8, 48000.0, 27.0, 576.3625, 493.555 + 0.8, 48000.0, 27.5, 617.2734, 510.849 + 0.8, 48000.0, 28.0, 658.7, 528.375 + 0.8, 48000.0, 28.5, 700.5391, 546.123 + 0.8, 48000.0, 29.0, 742.6875, 564.083 + 0.8, 48000.0, 29.5, 785.0422, 582.245 + 0.8, 48000.0, 30.0, 827.5, 600.6 + 0.8, 48000.0, 30.5, 868.875, 619.136 + 0.8, 48000.0, 31.0, 910.25, 637.845 + 0.8, 48000.0, 31.5, 951.625, 656.717 + 0.8, 48000.0, 32.0, 993.0, 675.744 + 0.8, 48000.0, 32.5, 1034.375, 694.915 + 0.8, 48000.0, 33.0, 1075.75, 714.221 + 0.8, 48000.0, 33.5, 1117.125, 733.653 + 0.8, 48000.0, 34.0, 1158.5, 753.2 + 0.8, 48000.0, 34.5, 1199.882, 773.052 + 0.8, 48000.0, 35.0, 1241.262, 792.981 + 0.8, 48000.0, 35.5, 1282.642, 812.96 + 0.8, 48000.0, 36.0, 1324.02, 832.96 + 0.8, 48000.0, 36.5, 1365.395, 852.952 + 0.8, 48000.0, 37.0, 1406.768, 872.909 + 0.8, 48000.0, 37.5, 1448.136, 892.801 + 0.8, 48000.0, 38.0, 1489.5, 912.6 + 0.8, 48000.0, 38.5, 1530.842, 931.974 + 0.8, 48000.0, 39.0, 1572.187, 951.356 + 0.8, 48000.0, 39.5, 1613.539, 970.785 + 0.8, 48000.0, 40.0, 1654.9, 990.3 + 0.8, 48000.0, 40.5, 1696.297, 1010.01 + 0.8, 48000.0, 41.0, 1737.7, 1029.86 + 0.8, 48000.0, 41.5, 1779.103, 1049.85 + 0.8, 48000.0, 42.0, 1820.5, 1070.0 + 0.8, 48000.0, 42.5, 1861.822, 1090.36 + 0.8, 48000.0, 43.0, 1903.15, 1110.87 + 0.8, 48000.0, 43.5, 1944.503, 1131.52 + 0.8, 48000.0, 44.0, 1985.9, 1152.3 + 0.8, 48000.0, 44.5, 2027.516, 1173.07 + 0.8, 48000.0, 45.0, 2069.15, 1193.99 + 0.8, 48000.0, 45.5, 2110.759, 1215.12 + 0.8, 48000.0, 46.0, 2152.3, 1236.5 + 0.8, 48000.0, 46.5, 2193.513, 1258.07 + 0.8, 48000.0, 47.0, 2234.656, 1280.0 + 0.8, 48000.0, 47.5, 2275.771, 1302.38 + 0.8, 48000.0, 48.0, 2316.9, 1325.3 + 0.8, 48000.0, 48.5, 2358.085, 1348.83 + 0.8, 48000.0, 49.0, 2399.369, 1373.05 + 0.8, 48000.0, 49.5, 2440.793, 1398.05 + 0.8, 48000.0, 50.0, 2482.4, 1423.9 + 0.85, 0.0, 0.0, 774.0961, 774.096 + 0.85, 0.0, 22.0, 2249.5, 2439.9 + 0.85, 0.0, 22.5, 2679.086, 3270.07 + 0.85, 0.0, 23.0, 3092.602, 3542.95 + 0.85, 0.0, 23.5, 3493.592, 3368.16 + 0.85, 0.0, 24.0, 3885.6, 2855.3 + 0.85, 0.0, 24.5, 4272.171, 2113.99 + 0.85, 0.0, 25.0, 4656.848, 1253.85 + 0.85, 0.0, 25.5, 5043.177, 384.477 + 0.85, 0.0, 26.0, 5434.7, -384.5 + 0.85, 0.0, 26.5, 5869.764, 64.9568 + 0.85, 0.0, 27.0, 6319.1, 891.657 + 0.85, 0.0, 27.5, 6780.286, 2032.34 + 0.85, 0.0, 28.0, 7250.9, 3423.75 + 0.85, 0.0, 28.5, 7728.52, 5002.61 + 0.85, 0.0, 29.0, 8210.725, 6705.69 + 0.85, 0.0, 29.5, 8695.092, 8469.7 + 0.85, 0.0, 30.0, 9179.2, 10231.4 + 0.85, 0.0, 30.5, 9629.625, 11197.7 + 0.85, 0.0, 31.0, 10077.9, 12104.6 + 0.85, 0.0, 31.5, 10524.55, 12958.5 + 0.85, 0.0, 32.0, 10970.12, 13765.6 + 0.85, 0.0, 32.5, 11415.13, 14532.0 + 0.85, 0.0, 33.0, 11860.1, 15264.1 + 0.85, 0.0, 33.5, 12305.59, 15968.2 + 0.85, 0.0, 34.0, 12752.1, 16650.4 + 0.85, 0.0, 34.5, 13208.43, 18261.4 + 0.85, 0.0, 35.0, 13666.07, 19773.1 + 0.85, 0.0, 35.5, 14124.76, 21101.9 + 0.85, 0.0, 36.0, 14584.25, 22164.0 + 0.85, 0.0, 36.5, 15044.29, 22875.7 + 0.85, 0.0, 37.0, 15504.61, 23153.4 + 0.85, 0.0, 37.5, 15964.97, 22913.3 + 0.85, 0.0, 38.0, 16425.1, 22071.8 + 0.85, 0.0, 38.5, 16885.75, 19778.7 + 0.85, 0.0, 39.0, 17345.15, 17114.1 + 0.85, 0.0, 39.5, 17802.83, 14164.9 + 0.85, 0.0, 40.0, 18258.3, 11017.5 + 0.85, 0.0, 40.5, 18711.57, 7615.14 + 0.85, 0.0, 41.0, 19161.49, 4245.38 + 0.85, 0.0, 41.5, 19607.39, 1052.28 + 0.85, 0.0, 42.0, 20048.6, -1820.1 + 0.85, 0.0, 42.5, 20472.94, -3992.71 + 0.85, 0.0, 43.0, 20895.86, -5650.49 + 0.85, 0.0, 43.5, 21321.3, -6743.37 + 0.85, 0.0, 44.0, 21753.2, -7221.3 + 0.85, 0.0, 44.5, 22214.55, -6549.04 + 0.85, 0.0, 45.0, 22682.61, -5355.77 + 0.85, 0.0, 45.5, 23153.72, -3785.52 + 0.85, 0.0, 46.0, 23624.2, -1982.3 + 0.85, 0.0, 46.5, 24076.14, -326.085 + 0.85, 0.0, 47.0, 24525.77, 1369.47 + 0.85, 0.0, 47.5, 24975.12, 3054.74 + 0.85, 0.0, 48.0, 25426.2, 4680.1 + 0.85, 0.0, 48.5, 25881.01, 6195.93 + 0.85, 0.0, 49.0, 26341.57, 7552.61 + 0.85, 0.0, 49.5, 26809.9, 8700.5 + 0.85, 0.0, 50.0, 27288.0, 9590.0 + 0.85, 2000.0, 0.0, 724.7628, 724.763 + 0.85, 2000.0, 22.0, -45286.9, -14675.4 + 0.85, 2000.0, 22.5, -53853.69, -17710.7 + 0.85, 2000.0, 23.0, -62334.38, -20552.8 + 0.85, 2000.0, 23.5, -70758.22, -23253.5 + 0.85, 2000.0, 24.0, -79154.5, -25864.3 + 0.85, 2000.0, 24.5, -87552.49, -28437.1 + 0.85, 2000.0, 25.0, -95981.48, -31023.5 + 0.85, 2000.0, 25.5, -104470.7, -33675.3 + 0.85, 2000.0, 26.0, -113049.5, -36444.2 + 0.85, 2000.0, 26.5, -122055.2, -39927.6 + 0.85, 2000.0, 27.0, -131226.7, -43662.6 + 0.85, 2000.0, 27.5, -140540.3, -47607.5 + 0.85, 2000.0, 28.0, -149972.4, -51720.5 + 0.85, 2000.0, 28.5, -159499.7, -55959.8 + 0.85, 2000.0, 29.0, -169098.4, -60283.4 + 0.85, 2000.0, 29.5, -178745.0, -64649.7 + 0.85, 2000.0, 30.0, -188416.1, -69016.7 + 0.85, 2000.0, 30.5, -197841.1, -72745.6 + 0.85, 2000.0, 31.0, -207266.8, -76448.5 + 0.85, 2000.0, 31.5, -216693.4, -80140.4 + 0.85, 2000.0, 32.0, -226120.7, -83836.4 + 0.85, 2000.0, 32.5, -235548.7, -87551.5 + 0.85, 2000.0, 33.0, -244977.4, -91300.7 + 0.85, 2000.0, 33.5, -254406.7, -95099.2 + 0.85, 2000.0, 34.0, -263836.7, -98961.8 + 0.85, 2000.0, 34.5, -273276.5, -103733.0 + 0.85, 2000.0, 35.0, -282716.0, -108519.0 + 0.85, 2000.0, 35.5, -292154.2, -113257.0 + 0.85, 2000.0, 36.0, -301590.2, -117883.0 + 0.85, 2000.0, 36.5, -311023.2, -122331.0 + 0.85, 2000.0, 37.0, -320452.3, -126540.0 + 0.85, 2000.0, 37.5, -329876.4, -130444.0 + 0.85, 2000.0, 38.0, -339294.7, -133980.0 + 0.85, 2000.0, 38.5, -348689.6, -136515.0 + 0.85, 2000.0, 39.0, -358085.5, -138850.0 + 0.85, 2000.0, 39.5, -367485.2, -141044.0 + 0.85, 2000.0, 40.0, -376891.6, -143161.0 + 0.85, 2000.0, 40.5, -386321.7, -145099.0 + 0.85, 2000.0, 41.0, -395758.4, -147150.0 + 0.85, 2000.0, 41.5, -405198.5, -149441.0 + 0.85, 2000.0, 42.0, -414639.3, -152099.0 + 0.85, 2000.0, 42.5, -424063.0, -155690.0 + 0.85, 2000.0, 43.0, -433487.3, -159729.0 + 0.85, 2000.0, 43.5, -442915.2, -164169.0 + 0.85, 2000.0, 44.0, -452349.6, -168963.0 + 0.85, 2000.0, 44.5, -461822.4, -174104.0 + 0.85, 2000.0, 45.0, -471296.0, -179489.0 + 0.85, 2000.0, 45.5, -480761.9, -185055.0 + 0.85, 2000.0, 46.0, -490211.4, -190739.0 + 0.85, 2000.0, 46.5, -499589.9, -196318.0 + 0.85, 2000.0, 47.0, -508953.2, -201953.0 + 0.85, 2000.0, 47.5, -518311.1, -207644.0 + 0.85, 2000.0, 48.0, -527673.3, -213391.0 + 0.85, 2000.0, 48.5, -537049.7, -219196.0 + 0.85, 2000.0, 49.0, -546450.0, -225059.0 + 0.85, 2000.0, 49.5, -555884.0, -230981.0 + 0.85, 2000.0, 50.0, -565361.6, -236961.0 + 0.85, 5000.0, 0.0, 655.4506, 655.451 + 0.85, 5000.0, 22.0, 55602.3, 20702.2 + 0.85, 5000.0, 22.5, 66173.38, 24207.1 + 0.85, 5000.0, 23.0, 76629.04, 27605.4 + 0.85, 5000.0, 23.5, 87006.57, 30935.2 + 0.85, 5000.0, 24.0, 97343.3, 34234.7 + 0.85, 5000.0, 24.5, 107676.5, 37541.9 + 0.85, 5000.0, 25.0, 118043.5, 40894.9 + 0.85, 5000.0, 25.5, 128481.7, 44331.9 + 0.85, 5000.0, 26.0, 139028.2, 47891.0 + 0.85, 5000.0, 26.5, 150109.6, 51988.1 + 0.85, 5000.0, 27.0, 161396.2, 56305.2 + 0.85, 5000.0, 27.5, 172858.7, 60815.4 + 0.85, 5000.0, 28.0, 184467.7, 65492.2 + 0.85, 5000.0, 28.5, 196193.7, 70308.8 + 0.85, 5000.0, 29.0, 208007.3, 75238.7 + 0.85, 5000.0, 29.5, 219879.2, 80255.1 + 0.85, 5000.0, 30.0, 231780.0, 85331.4 + 0.85, 5000.0, 30.5, 243371.8, 90213.0 + 0.85, 5000.0, 31.0, 254963.0, 95122.9 + 0.85, 5000.0, 31.5, 266553.6, 100056.0 + 0.85, 5000.0, 32.0, 278143.5, 105007.0 + 0.85, 5000.0, 32.5, 289732.8, 109972.0 + 0.85, 5000.0, 33.0, 301321.5, 114945.0 + 0.85, 5000.0, 33.5, 312909.4, 119922.0 + 0.85, 5000.0, 34.0, 324496.6, 124897.0 + 0.85, 5000.0, 34.5, 336080.2, 129938.0 + 0.85, 5000.0, 35.0, 347663.2, 134960.0 + 0.85, 5000.0, 35.5, 359246.0, 139952.0 + 0.85, 5000.0, 36.0, 370828.8, 144902.0 + 0.85, 5000.0, 36.5, 382411.8, 149798.0 + 0.85, 5000.0, 37.0, 393995.3, 154629.0 + 0.85, 5000.0, 37.5, 405579.6, 159381.0 + 0.85, 5000.0, 38.0, 417164.8, 164044.0 + 0.85, 5000.0, 38.5, 428754.3, 168526.0 + 0.85, 5000.0, 39.0, 440343.7, 172935.0 + 0.85, 5000.0, 39.5, 451932.6, 177280.0 + 0.85, 5000.0, 40.0, 463520.4, 181565.0 + 0.85, 5000.0, 40.5, 475101.7, 185685.0 + 0.85, 5000.0, 41.0, 486683.1, 189803.0 + 0.85, 5000.0, 41.5, 498266.3, 193970.0 + 0.85, 5000.0, 42.0, 509852.9, 198234.0 + 0.85, 5000.0, 42.5, 521445.4, 202746.0 + 0.85, 5000.0, 43.0, 533044.0, 207419.0 + 0.85, 5000.0, 43.5, 544650.0, 212264.0 + 0.85, 5000.0, 44.0, 556264.6, 217293.0 + 0.85, 5000.0, 44.5, 567916.7, 222579.0 + 0.85, 5000.0, 45.0, 579568.7, 228047.0 + 0.85, 5000.0, 45.5, 591210.6, 233685.0 + 0.85, 5000.0, 46.0, 602832.4, 239479.0 + 0.85, 5000.0, 46.5, 614371.3, 245478.0 + 0.85, 5000.0, 47.0, 625891.5, 251584.0 + 0.85, 5000.0, 47.5, 637404.2, 257759.0 + 0.85, 5000.0, 48.0, 648920.7, 263967.0 + 0.85, 5000.0, 48.5, 660452.1, 270170.0 + 0.85, 5000.0, 49.0, 672009.8, 276332.0 + 0.85, 5000.0, 49.5, 683605.0, 282415.0 + 0.85, 5000.0, 50.0, 695248.8, 288383.0 + 0.85, 10000.0, 0.0, 551.6554, 551.655 + 0.85, 10000.0, 22.0, 607.4, 1069.1 + 0.85, 10000.0, 22.5, 712.9064, 1236.92 + 0.85, 10000.0, 23.0, 821.7984, 1363.33 + 0.85, 10000.0, 23.5, 933.7912, 1454.66 + 0.85, 10000.0, 24.0, 1048.6, 1517.2 + 0.85, 10000.0, 24.5, 1165.94, 1557.28 + 0.85, 10000.0, 25.0, 1285.527, 1581.22 + 0.85, 10000.0, 25.5, 1407.075, 1595.32 + 0.85, 10000.0, 26.0, 1530.3, 1605.9 + 0.85, 10000.0, 26.5, 1653.769, 1681.39 + 0.85, 10000.0, 27.0, 1778.28, 1769.54 + 0.85, 10000.0, 27.5, 1903.744, 1866.02 + 0.85, 10000.0, 28.0, 2030.075, 1966.5 + 0.85, 10000.0, 28.5, 2157.184, 2066.64 + 0.85, 10000.0, 29.0, 2284.983, 2162.11 + 0.85, 10000.0, 29.5, 2413.384, 2248.57 + 0.85, 10000.0, 30.0, 2542.3, 2321.7 + 0.85, 10000.0, 30.5, 2671.837, 2293.73 + 0.85, 10000.0, 31.0, 2801.695, 2251.7 + 0.85, 10000.0, 31.5, 2931.766, 2199.24 + 0.85, 10000.0, 32.0, 3061.944, 2139.94 + 0.85, 10000.0, 32.5, 3192.123, 2077.42 + 0.85, 10000.0, 33.0, 3322.196, 2015.3 + 0.85, 10000.0, 33.5, 3452.057, 1957.19 + 0.85, 10000.0, 34.0, 3581.6, 1906.7 + 0.85, 10000.0, 34.5, 3709.918, 1919.47 + 0.85, 10000.0, 35.0, 3837.781, 1942.13 + 0.85, 10000.0, 35.5, 3965.159, 1973.35 + 0.85, 10000.0, 36.0, 4092.02, 2011.77 + 0.85, 10000.0, 36.5, 4218.335, 2056.06 + 0.85, 10000.0, 37.0, 4344.074, 2104.87 + 0.85, 10000.0, 37.5, 4469.205, 2156.87 + 0.85, 10000.0, 38.0, 4593.7, 2210.7 + 0.85, 10000.0, 38.5, 4715.422, 2294.41 + 0.85, 10000.0, 39.0, 4837.538, 2362.04 + 0.85, 10000.0, 39.5, 4960.484, 2405.73 + 0.85, 10000.0, 40.0, 5084.7, 2417.6 + 0.85, 10000.0, 40.5, 5212.677, 2292.59 + 0.85, 10000.0, 41.0, 5341.975, 2158.9 + 0.85, 10000.0, 41.5, 5472.211, 2047.53 + 0.85, 10000.0, 42.0, 5603.0, 1989.5 + 0.85, 10000.0, 42.5, 5733.313, 2142.81 + 0.85, 10000.0, 43.0, 5863.669, 2360.67 + 0.85, 10000.0, 43.5, 5993.94, 2623.26 + 0.85, 10000.0, 44.0, 6124.0, 2910.8 + 0.85, 10000.0, 44.5, 6253.207, 3153.21 + 0.85, 10000.0, 45.0, 6382.156, 3401.08 + 0.85, 10000.0, 45.5, 6510.927, 3654.71 + 0.85, 10000.0, 46.0, 6639.6, 3914.4 + 0.85, 10000.0, 46.5, 6769.063, 4222.47 + 0.85, 10000.0, 47.0, 6898.263, 4520.42 + 0.85, 10000.0, 47.5, 7026.956, 4791.77 + 0.85, 10000.0, 48.0, 7154.9, 5020.0 + 0.85, 10000.0, 48.5, 7281.85, 5188.63 + 0.85, 10000.0, 49.0, 7407.563, 5281.17 + 0.85, 10000.0, 49.5, 7531.794, 5281.13 + 0.85, 10000.0, 50.0, 7654.3, 5172.0 + 0.85, 15000.0, 0.0, 461.2906, 461.291 + 0.85, 15000.0, 22.0, 607.7, 1109.7 + 0.85, 15000.0, 22.5, 719.9059, 1175.85 + 0.85, 15000.0, 23.0, 832.2531, 1240.88 + 0.85, 15000.0, 23.5, 944.9238, 1304.84 + 0.85, 15000.0, 24.0, 1058.1, 1367.8 + 0.85, 15000.0, 24.5, 1171.964, 1429.8 + 0.85, 15000.0, 25.0, 1286.697, 1490.9 + 0.85, 15000.0, 25.5, 1402.482, 1551.15 + 0.85, 15000.0, 26.0, 1519.5, 1610.6 + 0.85, 15000.0, 26.5, 1640.344, 1668.37 + 0.85, 15000.0, 27.0, 1762.924, 1725.4 + 0.85, 15000.0, 27.5, 1887.008, 1781.91 + 0.85, 15000.0, 28.0, 2012.365, 1838.11 + 0.85, 15000.0, 28.5, 2138.764, 1894.21 + 0.85, 15000.0, 29.0, 2265.973, 1950.43 + 0.85, 15000.0, 29.5, 2393.763, 2006.99 + 0.85, 15000.0, 30.0, 2521.9, 2064.1 + 0.85, 15000.0, 30.5, 2647.889, 2123.43 + 0.85, 15000.0, 31.0, 2773.98, 2183.61 + 0.85, 15000.0, 31.5, 2900.158, 2244.71 + 0.85, 15000.0, 32.0, 3026.406, 2306.81 + 0.85, 15000.0, 32.5, 3152.71, 2369.98 + 0.85, 15000.0, 33.0, 3279.054, 2434.3 + 0.85, 15000.0, 33.5, 3405.422, 2499.85 + 0.85, 15000.0, 34.0, 3531.8, 2566.7 + 0.85, 15000.0, 34.5, 3657.786, 2649.55 + 0.85, 15000.0, 35.0, 3783.787, 2732.47 + 0.85, 15000.0, 35.5, 3909.825, 2814.14 + 0.85, 15000.0, 36.0, 4035.92, 2893.24 + 0.85, 15000.0, 36.5, 4162.094, 2968.46 + 0.85, 15000.0, 37.0, 4288.367, 3038.49 + 0.85, 15000.0, 37.5, 4414.762, 3102.01 + 0.85, 15000.0, 38.0, 4541.3, 3157.7 + 0.85, 15000.0, 38.5, 4668.448, 3185.94 + 0.85, 15000.0, 39.0, 4795.55, 3213.22 + 0.85, 15000.0, 39.5, 4922.527, 3242.29 + 0.85, 15000.0, 40.0, 5049.3, 3275.9 + 0.85, 15000.0, 40.5, 5175.386, 3326.85 + 0.85, 15000.0, 41.0, 5301.275, 3383.82 + 0.85, 15000.0, 41.5, 5427.052, 3445.56 + 0.85, 15000.0, 42.0, 5552.8, 3510.8 + 0.85, 15000.0, 42.5, 5678.566, 3577.56 + 0.85, 15000.0, 43.0, 5804.488, 3645.57 + 0.85, 15000.0, 43.5, 5930.666, 3713.84 + 0.85, 15000.0, 44.0, 6057.2, 3781.4 + 0.85, 15000.0, 44.5, 6185.304, 3840.54 + 0.85, 15000.0, 45.0, 6313.519, 3899.69 + 0.85, 15000.0, 45.5, 6441.499, 3960.54 + 0.85, 15000.0, 46.0, 6568.9, 4024.8 + 0.85, 15000.0, 46.5, 6693.598, 4104.14 + 0.85, 15000.0, 47.0, 6817.737, 4186.31 + 0.85, 15000.0, 47.5, 6941.683, 4269.03 + 0.85, 15000.0, 48.0, 7065.8, 4350.0 + 0.85, 15000.0, 48.5, 7190.455, 4426.95 + 0.85, 15000.0, 49.0, 7316.012, 4497.59 + 0.85, 15000.0, 49.5, 7442.839, 4559.63 + 0.85, 15000.0, 50.0, 7571.3, 4610.8 + 0.85, 20000.0, 0.0, 383.042, 383.042 + 0.85, 20000.0, 22.0, 733.1, 1093.7 + 0.85, 20000.0, 22.5, 872.2059, 1156.91 + 0.85, 20000.0, 23.0, 1009.891, 1220.25 + 0.85, 20000.0, 23.5, 1146.63, 1283.82 + 0.85, 20000.0, 24.0, 1282.9, 1347.7 + 0.85, 20000.0, 24.5, 1419.176, 1412.0 + 0.85, 20000.0, 25.0, 1555.934, 1476.82 + 0.85, 20000.0, 25.5, 1693.65, 1542.26 + 0.85, 20000.0, 26.0, 1832.8, 1608.4 + 0.85, 20000.0, 26.5, 1978.862, 1676.46 + 0.85, 20000.0, 27.0, 2127.594, 1745.49 + 0.85, 20000.0, 27.5, 2278.616, 1815.39 + 0.85, 20000.0, 28.0, 2431.545, 1886.08 + 0.85, 20000.0, 28.5, 2586.0, 1957.47 + 0.85, 20000.0, 29.0, 2741.598, 2029.47 + 0.85, 20000.0, 29.5, 2897.959, 2101.97 + 0.85, 20000.0, 30.0, 3054.7, 2174.9 + 0.85, 20000.0, 30.5, 3207.426, 2247.44 + 0.85, 20000.0, 31.0, 3360.152, 2320.28 + 0.85, 20000.0, 31.5, 3512.876, 2393.41 + 0.85, 20000.0, 32.0, 3665.6, 2466.79 + 0.85, 20000.0, 32.5, 3818.324, 2540.42 + 0.85, 20000.0, 33.0, 3971.048, 2614.26 + 0.85, 20000.0, 33.5, 4123.774, 2688.3 + 0.85, 20000.0, 34.0, 4276.5, 2762.5 + 0.85, 20000.0, 34.5, 4429.238, 2835.94 + 0.85, 20000.0, 35.0, 4581.977, 2909.58 + 0.85, 20000.0, 35.5, 4734.716, 2983.51 + 0.85, 20000.0, 36.0, 4887.455, 3057.77 + 0.85, 20000.0, 36.5, 5040.194, 3132.44 + 0.85, 20000.0, 37.0, 5192.931, 3207.57 + 0.85, 20000.0, 37.5, 5345.667, 3283.24 + 0.85, 20000.0, 38.0, 5498.4, 3359.5 + 0.85, 20000.0, 38.5, 5651.121, 3436.92 + 0.85, 20000.0, 39.0, 5803.844, 3514.81 + 0.85, 20000.0, 39.5, 5956.57, 3593.12 + 0.85, 20000.0, 40.0, 6109.3, 3671.8 + 0.85, 20000.0, 40.5, 6262.048, 3750.45 + 0.85, 20000.0, 41.0, 6414.8, 3829.52 + 0.85, 20000.0, 41.5, 6567.552, 3909.1 + 0.85, 20000.0, 42.0, 6720.3, 3989.3 + 0.85, 20000.0, 42.5, 6872.909, 4070.52 + 0.85, 20000.0, 43.0, 7025.563, 4152.41 + 0.85, 20000.0, 43.5, 7178.309, 4234.95 + 0.85, 20000.0, 44.0, 7331.2, 4318.1 + 0.85, 20000.0, 44.5, 7484.773, 4401.96 + 0.85, 20000.0, 45.0, 7638.394, 4486.32 + 0.85, 20000.0, 45.5, 7791.918, 4571.09 + 0.85, 20000.0, 46.0, 7945.2, 4656.2 + 0.85, 20000.0, 46.5, 8097.368, 4740.27 + 0.85, 20000.0, 47.0, 8249.294, 4825.02 + 0.85, 20000.0, 47.5, 8401.123, 4910.89 + 0.85, 20000.0, 48.0, 8553.0, 4998.3 + 0.85, 20000.0, 48.5, 8705.071, 5087.68 + 0.85, 20000.0, 49.0, 8857.481, 5179.47 + 0.85, 20000.0, 49.5, 9010.376, 5274.1 + 0.85, 20000.0, 50.0, 9163.9, 5372.0 + 0.85, 25000.0, 0.0, 315.6704, 315.67 + 0.85, 25000.0, 22.0, 631.6, 911.4 + 0.85, 25000.0, 22.5, 751.4086, 963.572 + 0.85, 25000.0, 23.0, 870.0063, 1016.05 + 0.85, 25000.0, 23.5, 987.8008, 1068.91 + 0.85, 25000.0, 24.0, 1105.2, 1122.2 + 0.85, 25000.0, 24.5, 1222.612, 1176.0 + 0.85, 25000.0, 25.0, 1340.444, 1230.37 + 0.85, 25000.0, 25.5, 1459.104, 1285.38 + 0.85, 25000.0, 26.0, 1579.0, 1341.1 + 0.85, 25000.0, 26.5, 1704.833, 1398.53 + 0.85, 25000.0, 27.0, 1832.962, 1456.85 + 0.85, 25000.0, 27.5, 1963.061, 1515.97 + 0.85, 25000.0, 28.0, 2094.8, 1575.78 + 0.85, 25000.0, 28.5, 2227.852, 1636.2 + 0.85, 25000.0, 29.0, 2361.887, 1697.12 + 0.85, 25000.0, 29.5, 2496.58, 1758.46 + 0.85, 25000.0, 30.0, 2631.6, 1820.1 + 0.85, 25000.0, 30.5, 2763.175, 1880.88 + 0.85, 25000.0, 31.0, 2894.75, 1941.89 + 0.85, 25000.0, 31.5, 3026.325, 2003.13 + 0.85, 25000.0, 32.0, 3157.9, 2064.61 + 0.85, 25000.0, 32.5, 3289.475, 2126.32 + 0.85, 25000.0, 33.0, 3421.05, 2188.29 + 0.85, 25000.0, 33.5, 3552.625, 2250.51 + 0.85, 25000.0, 34.0, 3684.2, 2313.0 + 0.85, 25000.0, 34.5, 3815.775, 2375.68 + 0.85, 25000.0, 35.0, 3947.35, 2438.65 + 0.85, 25000.0, 35.5, 4078.925, 2501.91 + 0.85, 25000.0, 36.0, 4210.5, 2565.48 + 0.85, 25000.0, 36.5, 4342.075, 2629.37 + 0.85, 25000.0, 37.0, 4473.65, 2693.6 + 0.85, 25000.0, 37.5, 4605.225, 2758.17 + 0.85, 25000.0, 38.0, 4736.8, 2823.1 + 0.85, 25000.0, 38.5, 4868.37, 2888.4 + 0.85, 25000.0, 39.0, 4999.942, 2954.09 + 0.85, 25000.0, 39.5, 5131.519, 3020.18 + 0.85, 25000.0, 40.0, 5263.1, 3086.7 + 0.85, 25000.0, 40.5, 5394.698, 3153.56 + 0.85, 25000.0, 41.0, 5526.3, 3220.92 + 0.85, 25000.0, 41.5, 5657.902, 3288.81 + 0.85, 25000.0, 42.0, 5789.5, 3357.3 + 0.85, 25000.0, 42.5, 5920.975, 3426.7 + 0.85, 25000.0, 43.0, 6052.488, 3496.69 + 0.85, 25000.0, 43.5, 6184.081, 3567.21 + 0.85, 25000.0, 44.0, 6315.8, 3638.2 + 0.85, 25000.0, 44.5, 6448.109, 3708.88 + 0.85, 25000.0, 45.0, 6580.463, 3780.2 + 0.85, 25000.0, 45.5, 6712.734, 3852.4 + 0.85, 25000.0, 46.0, 6844.8, 3925.7 + 0.85, 25000.0, 46.5, 6975.913, 4001.19 + 0.85, 25000.0, 47.0, 7106.819, 4077.91 + 0.85, 25000.0, 47.5, 7237.64, 4155.75 + 0.85, 25000.0, 48.0, 7368.5, 4234.6 + 0.85, 25000.0, 48.5, 7499.523, 4314.35 + 0.85, 25000.0, 49.0, 7630.831, 4394.89 + 0.85, 25000.0, 49.5, 7762.549, 4476.11 + 0.85, 25000.0, 50.0, 7894.8, 4557.9 + 0.85, 30000.0, 0.0, 258.0236, 258.024 + 0.85, 30000.0, 22.0, 510.8, 734.6 + 0.85, 30000.0, 22.5, 607.7014, 776.242 + 0.85, 30000.0, 23.0, 703.6141, 818.18 + 0.85, 30000.0, 23.5, 798.8697, 860.453 + 0.85, 30000.0, 24.0, 893.8, 903.1 + 0.85, 30000.0, 24.5, 988.7365, 946.16 + 0.85, 30000.0, 25.0, 1084.011, 989.67 + 0.85, 30000.0, 25.5, 1179.955, 1033.67 + 0.85, 30000.0, 26.0, 1276.9, 1078.2 + 0.85, 30000.0, 26.5, 1378.667, 1123.93 + 0.85, 30000.0, 27.0, 1482.298, 1170.29 + 0.85, 30000.0, 27.5, 1587.526, 1217.23 + 0.85, 30000.0, 28.0, 1694.085, 1264.67 + 0.85, 30000.0, 28.5, 1801.708, 1312.55 + 0.85, 30000.0, 29.0, 1910.13, 1360.8 + 0.85, 30000.0, 29.5, 2019.082, 1409.33 + 0.85, 30000.0, 30.0, 2128.3, 1458.1 + 0.85, 30000.0, 30.5, 2234.718, 1506.2 + 0.85, 30000.0, 31.0, 2341.134, 1554.47 + 0.85, 30000.0, 31.5, 2447.549, 1602.92 + 0.85, 30000.0, 32.0, 2553.963, 1651.55 + 0.85, 30000.0, 32.5, 2660.374, 1700.37 + 0.85, 30000.0, 33.0, 2766.784, 1749.4 + 0.85, 30000.0, 33.5, 2873.193, 1798.64 + 0.85, 30000.0, 34.0, 2979.6, 1848.1 + 0.85, 30000.0, 34.5, 3085.996, 1897.82 + 0.85, 30000.0, 35.0, 3192.392, 1947.78 + 0.85, 30000.0, 35.5, 3298.788, 1997.98 + 0.85, 30000.0, 36.0, 3405.185, 2048.42 + 0.85, 30000.0, 36.5, 3511.584, 2099.12 + 0.85, 30000.0, 37.0, 3617.985, 2150.08 + 0.85, 30000.0, 37.5, 3724.39, 2201.31 + 0.85, 30000.0, 38.0, 3830.8, 2252.8 + 0.85, 30000.0, 38.5, 3937.228, 2304.56 + 0.85, 30000.0, 39.0, 4043.655, 2356.61 + 0.85, 30000.0, 39.5, 4150.079, 2408.95 + 0.85, 30000.0, 40.0, 4256.5, 2461.6 + 0.85, 30000.0, 40.5, 4362.902, 2514.48 + 0.85, 30000.0, 41.0, 4469.3, 2567.72 + 0.85, 30000.0, 41.5, 4575.698, 2621.34 + 0.85, 30000.0, 42.0, 4682.1, 2675.4 + 0.85, 30000.0, 42.5, 4788.438, 2730.09 + 0.85, 30000.0, 43.0, 4894.813, 2785.23 + 0.85, 30000.0, 43.5, 5001.256, 2840.77 + 0.85, 30000.0, 44.0, 5107.8, 2896.7 + 0.85, 30000.0, 44.5, 5214.803, 2952.6 + 0.85, 30000.0, 45.0, 5321.838, 3008.98 + 0.85, 30000.0, 45.5, 5428.803, 3065.97 + 0.85, 30000.0, 46.0, 5535.6, 3123.7 + 0.85, 30000.0, 46.5, 5641.624, 3182.51 + 0.85, 30000.0, 47.0, 5747.481, 3242.22 + 0.85, 30000.0, 47.5, 5853.273, 3302.87 + 0.85, 30000.0, 48.0, 5959.1, 3364.5 + 0.85, 30000.0, 48.5, 6065.065, 3427.15 + 0.85, 30000.0, 49.0, 6171.269, 3490.86 + 0.85, 30000.0, 49.5, 6277.813, 3555.66 + 0.85, 30000.0, 50.0, 6384.8, 3621.6 + 0.85, 35000.0, 0.0, 209.0285, 209.028 + 0.85, 35000.0, 22.0, 396.0, 604.7 + 0.85, 35000.0, 22.5, 471.1746, 636.469 + 0.85, 35000.0, 23.0, 545.5781, 668.27 + 0.85, 35000.0, 23.5, 619.4676, 700.186 + 0.85, 35000.0, 24.0, 693.1, 732.3 + 0.85, 35000.0, 24.5, 766.7324, 764.695 + 0.85, 35000.0, 25.0, 840.6219, 797.455 + 0.85, 35000.0, 25.5, 915.0254, 830.662 + 0.85, 35000.0, 26.0, 990.2, 864.4 + 0.85, 35000.0, 26.5, 1069.099, 899.92 + 0.85, 35000.0, 27.0, 1149.437, 936.203 + 0.85, 35000.0, 27.5, 1231.009, 973.134 + 0.85, 35000.0, 28.0, 1313.61, 1010.6 + 0.85, 35000.0, 28.5, 1397.035, 1048.47 + 0.85, 35000.0, 29.0, 1481.078, 1086.64 + 0.85, 35000.0, 29.5, 1565.535, 1124.99 + 0.85, 35000.0, 30.0, 1650.2, 1163.4 + 0.85, 35000.0, 30.5, 1732.72, 1200.18 + 0.85, 35000.0, 31.0, 1815.243, 1236.95 + 0.85, 35000.0, 31.5, 1897.768, 1273.72 + 0.85, 35000.0, 32.0, 1980.294, 1310.54 + 0.85, 35000.0, 32.5, 2062.821, 1347.43 + 0.85, 35000.0, 33.0, 2145.348, 1384.43 + 0.85, 35000.0, 33.5, 2227.874, 1421.58 + 0.85, 35000.0, 34.0, 2310.4, 1458.9 + 0.85, 35000.0, 34.5, 2392.919, 1496.82 + 0.85, 35000.0, 35.0, 2475.436, 1534.95 + 0.85, 35000.0, 35.5, 2557.951, 1573.28 + 0.85, 35000.0, 36.0, 2640.465, 1611.8 + 0.85, 35000.0, 36.5, 2722.977, 1650.5 + 0.85, 35000.0, 37.0, 2805.487, 1689.39 + 0.85, 35000.0, 37.5, 2887.994, 1728.46 + 0.85, 35000.0, 38.0, 2970.5, 1767.7 + 0.85, 35000.0, 38.5, 3052.991, 1807.0 + 0.85, 35000.0, 39.0, 3135.486, 1846.52 + 0.85, 35000.0, 39.5, 3217.988, 1886.28 + 0.85, 35000.0, 40.0, 3300.5, 1926.3 + 0.85, 35000.0, 40.5, 3383.047, 1966.46 + 0.85, 35000.0, 41.0, 3465.6, 2006.97 + 0.85, 35000.0, 41.5, 3548.153, 2047.93 + 0.85, 35000.0, 42.0, 3630.7, 2089.4 + 0.85, 35000.0, 42.5, 3713.145, 2132.05 + 0.85, 35000.0, 43.0, 3795.606, 2175.13 + 0.85, 35000.0, 43.5, 3878.115, 2218.5 + 0.85, 35000.0, 44.0, 3960.7, 2262.0 + 0.85, 35000.0, 44.5, 4043.661, 2304.72 + 0.85, 35000.0, 45.0, 4126.65, 2347.56 + 0.85, 35000.0, 45.5, 4209.589, 2390.67 + 0.85, 35000.0, 46.0, 4292.4, 2434.2 + 0.85, 35000.0, 46.5, 4374.614, 2478.38 + 0.85, 35000.0, 47.0, 4456.7, 2523.24 + 0.85, 35000.0, 47.5, 4538.736, 2568.91 + 0.85, 35000.0, 48.0, 4620.8, 2615.5 + 0.85, 35000.0, 48.5, 4702.97, 2663.13 + 0.85, 35000.0, 49.0, 4785.325, 2711.91 + 0.85, 35000.0, 49.5, 4867.942, 2761.96 + 0.85, 35000.0, 50.0, 4950.9, 2813.4 + 0.85, 39000.0, 0.0, 173.3704, 173.37 + 0.85, 39000.0, 22.0, 318.3, 518.7 + 0.85, 39000.0, 22.5, 378.7395, 543.758 + 0.85, 39000.0, 23.0, 438.5469, 569.073 + 0.85, 39000.0, 23.5, 497.9309, 594.677 + 0.85, 39000.0, 24.0, 557.1, 620.6 + 0.85, 39000.0, 24.5, 616.2629, 646.873 + 0.85, 39000.0, 25.0, 675.6281, 673.527 + 0.85, 39000.0, 25.5, 735.4043, 700.592 + 0.85, 39000.0, 26.0, 795.8, 728.1 + 0.85, 39000.0, 26.5, 859.2086, 756.574 + 0.85, 39000.0, 27.0, 923.7788, 785.58 + 0.85, 39000.0, 27.5, 989.3445, 815.065 + 0.85, 39000.0, 28.0, 1055.74, 844.975 + 0.85, 39000.0, 28.5, 1122.799, 875.257 + 0.85, 39000.0, 29.0, 1190.356, 905.858 + 0.85, 39000.0, 29.5, 1258.245, 936.723 + 0.85, 39000.0, 30.0, 1326.3, 967.8 + 0.85, 39000.0, 30.5, 1392.613, 998.698 + 0.85, 39000.0, 31.0, 1458.925, 1029.73 + 0.85, 39000.0, 31.5, 1525.238, 1060.88 + 0.85, 39000.0, 32.0, 1591.55, 1092.13 + 0.85, 39000.0, 32.5, 1657.863, 1123.44 + 0.85, 39000.0, 33.0, 1724.175, 1154.8 + 0.85, 39000.0, 33.5, 1790.488, 1186.2 + 0.85, 39000.0, 34.0, 1856.8, 1217.6 + 0.85, 39000.0, 34.5, 1923.116, 1248.49 + 0.85, 39000.0, 35.0, 1989.431, 1279.4 + 0.85, 39000.0, 35.5, 2055.746, 1310.34 + 0.85, 39000.0, 36.0, 2122.06, 1341.34 + 0.85, 39000.0, 36.5, 2188.373, 1372.44 + 0.85, 39000.0, 37.0, 2254.684, 1403.64 + 0.85, 39000.0, 37.5, 2320.993, 1434.99 + 0.85, 39000.0, 38.0, 2387.3, 1466.5 + 0.85, 39000.0, 38.5, 2453.596, 1498.3 + 0.85, 39000.0, 39.0, 2519.894, 1530.26 + 0.85, 39000.0, 39.5, 2586.195, 1562.4 + 0.85, 39000.0, 40.0, 2652.5, 1594.7 + 0.85, 39000.0, 40.5, 2718.823, 1627.12 + 0.85, 39000.0, 41.0, 2785.15, 1659.74 + 0.85, 39000.0, 41.5, 2851.477, 1692.59 + 0.85, 39000.0, 42.0, 2917.8, 1725.7 + 0.85, 39000.0, 42.5, 2984.047, 1759.18 + 0.85, 39000.0, 43.0, 3050.313, 1792.93 + 0.85, 39000.0, 43.5, 3116.622, 1826.94 + 0.85, 39000.0, 44.0, 3183.0, 1861.2 + 0.85, 39000.0, 44.5, 3249.702, 1895.42 + 0.85, 39000.0, 45.0, 3316.431, 1929.98 + 0.85, 39000.0, 45.5, 3383.12, 1964.97 + 0.85, 39000.0, 46.0, 3449.7, 2000.5 + 0.85, 39000.0, 46.5, 3515.777, 2036.81 + 0.85, 39000.0, 47.0, 3581.744, 2073.79 + 0.85, 39000.0, 47.5, 3647.663, 2111.48 + 0.85, 39000.0, 48.0, 3713.6, 2149.9 + 0.85, 39000.0, 48.5, 3779.618, 2189.1 + 0.85, 39000.0, 49.0, 3845.781, 2229.11 + 0.85, 39000.0, 49.5, 3912.154, 2269.96 + 0.85, 39000.0, 50.0, 3978.8, 2311.7 + 0.85, 43000.0, 0.0, 143.0477, 143.048 + 0.85, 43000.0, 22.0, 257.1, 453.3 + 0.85, 43000.0, 22.5, 305.8305, 474.332 + 0.85, 43000.0, 23.0, 354.0813, 495.32 + 0.85, 43000.0, 23.5, 402.0164, 516.324 + 0.85, 43000.0, 24.0, 449.8, 537.4 + 0.85, 43000.0, 24.5, 497.5961, 558.608 + 0.85, 43000.0, 25.0, 545.5688, 580.005 + 0.85, 43000.0, 25.5, 593.882, 601.649 + 0.85, 43000.0, 26.0, 642.7, 623.6 + 0.85, 43000.0, 26.5, 693.9203, 646.483 + 0.85, 43000.0, 27.0, 746.0725, 669.822 + 0.85, 43000.0, 27.5, 799.0234, 693.575 + 0.85, 43000.0, 28.0, 852.64, 717.705 + 0.85, 43000.0, 28.5, 906.7891, 742.172 + 0.85, 43000.0, 29.0, 961.3375, 766.936 + 0.85, 43000.0, 29.5, 1016.152, 791.958 + 0.85, 43000.0, 30.0, 1071.1, 817.2 + 0.85, 43000.0, 30.5, 1124.648, 842.492 + 0.85, 43000.0, 31.0, 1178.196, 867.936 + 0.85, 43000.0, 31.5, 1231.745, 893.506 + 0.85, 43000.0, 32.0, 1285.294, 919.175 + 0.85, 43000.0, 32.5, 1338.844, 944.916 + 0.85, 43000.0, 33.0, 1392.395, 970.702 + 0.85, 43000.0, 33.5, 1445.947, 996.505 + 0.85, 43000.0, 34.0, 1499.5, 1022.3 + 0.85, 43000.0, 34.5, 1553.063, 1047.52 + 0.85, 43000.0, 35.0, 1606.627, 1072.72 + 0.85, 43000.0, 35.5, 1660.191, 1097.94 + 0.85, 43000.0, 36.0, 1713.755, 1123.19 + 0.85, 43000.0, 36.5, 1767.319, 1148.51 + 0.85, 43000.0, 37.0, 1820.881, 1173.92 + 0.85, 43000.0, 37.5, 1874.442, 1199.44 + 0.85, 43000.0, 38.0, 1928.0, 1225.1 + 0.85, 43000.0, 38.5, 1981.551, 1251.02 + 0.85, 43000.0, 39.0, 2035.102, 1277.08 + 0.85, 43000.0, 39.5, 2088.651, 1303.27 + 0.85, 43000.0, 40.0, 2142.2, 1329.6 + 0.85, 43000.0, 40.5, 2195.746, 1356.02 + 0.85, 43000.0, 41.0, 2249.294, 1382.59 + 0.85, 43000.0, 41.5, 2302.845, 1409.35 + 0.85, 43000.0, 42.0, 2356.4, 1436.3 + 0.85, 43000.0, 42.5, 2409.934, 1463.54 + 0.85, 43000.0, 43.0, 2463.488, 1490.99 + 0.85, 43000.0, 43.5, 2517.072, 1518.64 + 0.85, 43000.0, 44.0, 2570.7, 1546.5 + 0.85, 43000.0, 44.5, 2624.529, 1574.19 + 0.85, 43000.0, 45.0, 2678.369, 1602.21 + 0.85, 43000.0, 45.5, 2732.174, 1630.7 + 0.85, 43000.0, 46.0, 2785.9, 1659.8 + 0.85, 43000.0, 46.5, 2839.27, 1690.21 + 0.85, 43000.0, 47.0, 2892.563, 1721.29 + 0.85, 43000.0, 47.5, 2945.823, 1752.95 + 0.85, 43000.0, 48.0, 2999.1, 1785.1 + 0.85, 43000.0, 48.5, 3052.439, 1817.67 + 0.85, 43000.0, 49.0, 3105.888, 1850.56 + 0.85, 43000.0, 49.5, 3159.492, 1883.7 + 0.85, 43000.0, 50.0, 3213.3, 1917.0 + 0.85, 48000.0, 0.0, 112.4899, 112.49 + 0.85, 48000.0, 22.0, 202.5, 357.0 + 0.85, 48000.0, 22.5, 240.8574, 373.548 + 0.85, 48000.0, 23.0, 278.8406, 390.067 + 0.85, 48000.0, 23.5, 316.5785, 406.603 + 0.85, 48000.0, 24.0, 354.2, 423.2 + 0.85, 48000.0, 24.5, 391.834, 439.903 + 0.85, 48000.0, 25.0, 429.6094, 456.758 + 0.85, 48000.0, 25.5, 467.6551, 473.808 + 0.85, 48000.0, 26.0, 506.1, 491.1 + 0.85, 48000.0, 26.5, 546.4375, 509.116 + 0.85, 48000.0, 27.0, 587.51, 527.489 + 0.85, 48000.0, 27.5, 629.2125, 546.187 + 0.85, 48000.0, 28.0, 671.44, 565.18 + 0.85, 48000.0, 28.5, 714.0875, 584.438 + 0.85, 48000.0, 29.0, 757.05, 603.931 + 0.85, 48000.0, 29.5, 800.2225, 623.629 + 0.85, 48000.0, 30.0, 843.5, 643.5 + 0.85, 48000.0, 30.5, 885.675, 663.425 + 0.85, 48000.0, 31.0, 927.85, 683.471 + 0.85, 48000.0, 31.5, 970.025, 703.618 + 0.85, 48000.0, 32.0, 1012.2, 723.844 + 0.85, 48000.0, 32.5, 1054.375, 744.126 + 0.85, 48000.0, 33.0, 1096.55, 764.445 + 0.85, 48000.0, 33.5, 1138.725, 784.776 + 0.85, 48000.0, 34.0, 1180.9, 805.1 + 0.85, 48000.0, 34.5, 1223.075, 824.959 + 0.85, 48000.0, 35.0, 1265.25, 844.808 + 0.85, 48000.0, 35.5, 1307.425, 864.667 + 0.85, 48000.0, 36.0, 1349.6, 884.555 + 0.85, 48000.0, 36.5, 1391.775, 904.493 + 0.85, 48000.0, 37.0, 1433.95, 924.5 + 0.85, 48000.0, 37.5, 1476.125, 944.596 + 0.85, 48000.0, 38.0, 1518.3, 964.8 + 0.85, 48000.0, 38.5, 1560.475, 985.218 + 0.85, 48000.0, 39.0, 1602.65, 1005.74 + 0.85, 48000.0, 39.5, 1644.825, 1026.37 + 0.85, 48000.0, 40.0, 1687.0, 1047.1 + 0.85, 48000.0, 40.5, 1729.175, 1067.9 + 0.85, 48000.0, 41.0, 1771.35, 1088.82 + 0.85, 48000.0, 41.5, 1813.525, 1109.88 + 0.85, 48000.0, 42.0, 1855.7, 1131.1 + 0.85, 48000.0, 42.5, 1897.844, 1152.55 + 0.85, 48000.0, 43.0, 1940.0, 1174.18 + 0.85, 48000.0, 43.5, 1982.181, 1195.96 + 0.85, 48000.0, 44.0, 2024.4, 1217.9 + 0.85, 48000.0, 44.5, 2066.794, 1239.7 + 0.85, 48000.0, 45.0, 2109.2, 1261.76 + 0.85, 48000.0, 45.5, 2151.581, 1284.19 + 0.85, 48000.0, 46.0, 2193.9, 1307.1 + 0.85, 48000.0, 46.5, 2235.931, 1331.06 + 0.85, 48000.0, 47.0, 2277.9, 1355.54 + 0.85, 48000.0, 47.5, 2319.844, 1380.48 + 0.85, 48000.0, 48.0, 2361.8, 1405.8 + 0.85, 48000.0, 48.5, 2403.806, 1431.44 + 0.85, 48000.0, 49.0, 2445.9, 1457.34 + 0.85, 48000.0, 49.5, 2488.119, 1483.41 + 0.85, 48000.0, 50.0, 2530.5, 1509.6 + 0.9, 0.0, 0.0, 810.1509, 810.151 + 0.9, 0.0, 22.0, 2550.3, 2712.7 + 0.9, 0.0, 22.5, 3038.128, 3757.11 + 0.9, 0.0, 23.0, 3505.798, 4081.43 + 0.9, 0.0, 23.5, 3957.669, 3827.14 + 0.9, 0.0, 24.0, 4398.1, 3135.7 + 0.9, 0.0, 24.5, 4831.449, 2148.6 + 0.9, 0.0, 25.0, 5262.077, 1007.3 + 0.9, 0.0, 25.5, 5694.34, -146.728 + 0.9, 0.0, 26.0, 6132.6, -1172.0 + 0.9, 0.0, 26.5, 6623.812, -628.486 + 0.9, 0.0, 27.0, 7132.171, 400.928 + 0.9, 0.0, 27.5, 7654.735, 1835.1 + 0.9, 0.0, 28.0, 8188.56, 3592.91 + 0.9, 0.0, 28.5, 8730.702, 5593.19 + 0.9, 0.0, 29.0, 9278.219, 7754.83 + 0.9, 0.0, 29.5, 9828.166, 9996.68 + 0.9, 0.0, 30.0, 10377.6, 12237.6 + 0.9, 0.0, 30.5, 10885.49, 13466.2 + 0.9, 0.0, 31.0, 11390.62, 14620.2 + 0.9, 0.0, 31.5, 11893.65, 15707.0 + 0.9, 0.0, 32.0, 12395.28, 16734.2 + 0.9, 0.0, 32.5, 12896.18, 17709.1 + 0.9, 0.0, 33.0, 13397.05, 18639.2 + 0.9, 0.0, 33.5, 13898.56, 19532.1 + 0.9, 0.0, 34.0, 14401.4, 20395.1 + 0.9, 0.0, 34.5, 14916.86, 22441.3 + 0.9, 0.0, 35.0, 15434.0, 24357.8 + 0.9, 0.0, 35.5, 15952.5, 26037.2 + 0.9, 0.0, 36.0, 16472.04, 27372.1 + 0.9, 0.0, 36.5, 16992.28, 28255.1 + 0.9, 0.0, 37.0, 17512.91, 28579.0 + 0.9, 0.0, 37.5, 18033.59, 28236.4 + 0.9, 0.0, 38.0, 18554.0, 27119.8 + 0.9, 0.0, 38.5, 19075.16, 24137.3 + 0.9, 0.0, 39.0, 19594.7, 20676.8 + 0.9, 0.0, 39.5, 20111.99, 16849.7 + 0.9, 0.0, 40.0, 20626.4, 12767.3 + 0.9, 0.0, 40.5, 21137.82, 8356.11 + 0.9, 0.0, 41.0, 21644.92, 3986.66 + 0.9, 0.0, 41.5, 22146.85, -155.569 + 0.9, 0.0, 42.0, 22642.8, -3885.1 + 0.9, 0.0, 42.5, 23117.33, -6712.71 + 0.9, 0.0, 43.0, 23590.04, -8878.15 + 0.9, 0.0, 43.5, 24065.96, -10317.4 + 0.9, 0.0, 44.0, 24550.1, -10966.6 + 0.9, 0.0, 44.5, 25071.58, -10138.4 + 0.9, 0.0, 45.0, 25601.65, -8641.44 + 0.9, 0.0, 45.5, 26135.67, -6660.93 + 0.9, 0.0, 46.0, 26669.0, -4382.2 + 0.9, 0.0, 46.5, 27179.15, -2294.21 + 0.9, 0.0, 47.0, 27686.48, -157.125 + 0.9, 0.0, 47.5, 28193.5, 1965.22 + 0.9, 0.0, 48.0, 28702.7, 4009.0 + 0.9, 0.0, 48.5, 29216.6, 5910.38 + 0.9, 0.0, 49.0, 29737.69, 7605.52 + 0.9, 0.0, 49.5, 30268.49, 9030.61 + 0.9, 0.0, 50.0, 30811.5, 10121.8 + 0.9, 2000.0, 0.0, 758.5197, 758.52 + 0.9, 2000.0, 22.0, -59223.6, -19511.6 + 0.9, 2000.0, 22.5, -70426.84, -23485.0 + 0.9, 2000.0, 23.0, -81517.39, -27205.3 + 0.9, 2000.0, 23.5, -92533.54, -30740.3 + 0.9, 2000.0, 24.0, -103513.6, -34158.0 + 0.9, 2000.0, 24.5, -114495.9, -37526.1 + 0.9, 2000.0, 25.0, -125518.6, -40912.3 + 0.9, 2000.0, 25.5, -136620.1, -44384.6 + 0.9, 2000.0, 26.0, -147838.7, -48010.8 + 0.9, 2000.0, 26.5, -159615.7, -52575.6 + 0.9, 2000.0, 27.0, -171609.4, -57470.9 + 0.9, 2000.0, 27.5, -183788.9, -62641.5 + 0.9, 2000.0, 28.0, -196123.6, -68032.4 + 0.9, 2000.0, 28.5, -208582.6, -73588.4 + 0.9, 2000.0, 29.0, -221135.1, -79254.5 + 0.9, 2000.0, 29.5, -233750.3, -84975.5 + 0.9, 2000.0, 30.0, -246397.4, -90696.4 + 0.9, 2000.0, 30.5, -258722.7, -95575.3 + 0.9, 2000.0, 31.0, -271049.1, -100419.0 + 0.9, 2000.0, 31.5, -283376.5, -105247.0 + 0.9, 2000.0, 32.0, -295704.9, -110079.0 + 0.9, 2000.0, 32.5, -308034.3, -114935.0 + 0.9, 2000.0, 33.0, -320364.6, -119835.0 + 0.9, 2000.0, 33.5, -332695.7, -124798.0 + 0.9, 2000.0, 34.0, -345027.6, -129846.0 + 0.9, 2000.0, 34.5, -357372.5, -136088.0 + 0.9, 2000.0, 35.0, -369717.0, -142349.0 + 0.9, 2000.0, 35.5, -382059.8, -148546.0 + 0.9, 2000.0, 36.0, -394399.8, -154593.0 + 0.9, 2000.0, 36.5, -406735.7, -160407.0 + 0.9, 2000.0, 37.0, -419066.4, -165904.0 + 0.9, 2000.0, 37.5, -431390.6, -170999.0 + 0.9, 2000.0, 38.0, -443707.2, -175608.0 + 0.9, 2000.0, 38.5, -455992.9, -178899.0 + 0.9, 2000.0, 39.0, -468279.9, -181924.0 + 0.9, 2000.0, 39.5, -480572.0, -184765.0 + 0.9, 2000.0, 40.0, -492872.8, -187504.0 + 0.9, 2000.0, 40.5, -505205.0, -190007.0 + 0.9, 2000.0, 41.0, -517545.7, -192660.0 + 0.9, 2000.0, 41.5, -529891.1, -195630.0 + 0.9, 2000.0, 42.0, -542237.3, -199087.0 + 0.9, 2000.0, 42.5, -554561.0, -203778.0 + 0.9, 2000.0, 43.0, -566885.6, -209063.0 + 0.9, 2000.0, 43.5, -579214.7, -214878.0 + 0.9, 2000.0, 44.0, -591552.4, -221161.0 + 0.9, 2000.0, 44.5, -603940.3, -227901.0 + 0.9, 2000.0, 45.0, -616329.3, -234963.0 + 0.9, 2000.0, 45.5, -628708.1, -242263.0 + 0.9, 2000.0, 46.0, -641065.5, -249718.0 + 0.9, 2000.0, 46.5, -653329.9, -257034.0 + 0.9, 2000.0, 47.0, -665574.5, -264421.0 + 0.9, 2000.0, 47.5, -677811.9, -271882.0 + 0.9, 2000.0, 48.0, -690055.1, -279417.0 + 0.9, 2000.0, 48.5, -702316.8, -287027.0 + 0.9, 2000.0, 49.0, -714610.0, -294713.0 + 0.9, 2000.0, 49.5, -726947.3, -302475.0 + 0.9, 2000.0, 50.0, -739341.6, -310315.0 + 0.9, 5000.0, 0.0, 685.9793, 685.979 + 0.9, 5000.0, 22.0, 75189.6, 27653.2 + 0.9, 5000.0, 22.5, 89484.63, 32386.0 + 0.9, 5000.0, 23.0, 103623.6, 36975.5 + 0.9, 5000.0, 23.5, 117656.8, 41473.1 + 0.9, 5000.0, 24.0, 131634.9, 45930.2 + 0.9, 5000.0, 24.5, 145608.2, 50398.1 + 0.9, 5000.0, 25.0, 159627.2, 54928.4 + 0.9, 5000.0, 25.5, 173742.4, 59572.2 + 0.9, 5000.0, 26.0, 188004.2, 64381.2 + 0.9, 5000.0, 26.5, 202989.3, 69915.8 + 0.9, 5000.0, 27.0, 218252.0, 75747.3 + 0.9, 5000.0, 27.5, 233752.5, 81839.9 + 0.9, 5000.0, 28.0, 249451.1, 88157.7 + 0.9, 5000.0, 28.5, 265308.0, 94664.8 + 0.9, 5000.0, 29.0, 281283.4, 101325.0 + 0.9, 5000.0, 29.5, 297337.5, 108103.0 + 0.9, 5000.0, 30.0, 313430.7, 114963.0 + 0.9, 5000.0, 30.5, 329105.9, 121563.0 + 0.9, 5000.0, 31.0, 344780.4, 128202.0 + 0.9, 5000.0, 31.5, 360454.0, 134873.0 + 0.9, 5000.0, 32.0, 376126.7, 141570.0 + 0.9, 5000.0, 32.5, 391798.6, 148285.0 + 0.9, 5000.0, 33.0, 407469.6, 155012.0 + 0.9, 5000.0, 33.5, 423139.6, 161744.0 + 0.9, 5000.0, 34.0, 438808.6, 168475.0 + 0.9, 5000.0, 34.5, 454472.8, 175297.0 + 0.9, 5000.0, 35.0, 470136.3, 182094.0 + 0.9, 5000.0, 35.5, 485799.4, 188850.0 + 0.9, 5000.0, 36.0, 501462.6, 195549.0 + 0.9, 5000.0, 36.5, 517126.0, 202174.0 + 0.9, 5000.0, 37.0, 532790.1, 208709.0 + 0.9, 5000.0, 37.5, 548455.3, 215138.0 + 0.9, 5000.0, 38.0, 564121.7, 221444.0 + 0.9, 5000.0, 38.5, 579794.0, 227498.0 + 0.9, 5000.0, 39.0, 595466.1, 233455.0 + 0.9, 5000.0, 39.5, 611137.5, 239325.0 + 0.9, 5000.0, 40.0, 626807.4, 245115.0 + 0.9, 5000.0, 40.5, 642468.4, 250687.0 + 0.9, 5000.0, 41.0, 658129.5, 256257.0 + 0.9, 5000.0, 41.5, 673793.0, 261894.0 + 0.9, 5000.0, 42.0, 689461.1, 267666.0 + 0.9, 5000.0, 42.5, 705137.4, 273774.0 + 0.9, 5000.0, 43.0, 720822.0, 280102.0 + 0.9, 5000.0, 43.5, 736516.6, 286664.0 + 0.9, 5000.0, 44.0, 752222.8, 293474.0 + 0.9, 5000.0, 44.5, 767979.7, 300630.0 + 0.9, 5000.0, 45.0, 783736.4, 308033.0 + 0.9, 5000.0, 45.5, 799479.4, 315666.0 + 0.9, 5000.0, 46.0, 815195.3, 323510.0 + 0.9, 5000.0, 46.5, 830799.1, 331631.0 + 0.9, 5000.0, 47.0, 846377.6, 339897.0 + 0.9, 5000.0, 47.5, 861945.9, 348256.0 + 0.9, 5000.0, 48.0, 877519.3, 356658.0 + 0.9, 5000.0, 48.5, 893113.0, 365053.0 + 0.9, 5000.0, 49.0, 908742.1, 373391.0 + 0.9, 5000.0, 49.5, 924421.9, 381620.0 + 0.9, 5000.0, 50.0, 940167.6, 389691.0 + 0.9, 10000.0, 0.0, 577.3496, 577.35 + 0.9, 10000.0, 22.0, 539.2, 1020.0 + 0.9, 10000.0, 22.5, 627.1523, 1239.29 + 0.9, 10000.0, 23.0, 720.7688, 1395.75 + 0.9, 10000.0, 23.5, 819.4008, 1498.99 + 0.9, 10000.0, 24.0, 922.4, 1558.6 + 0.9, 10000.0, 24.5, 1029.118, 1584.19 + 0.9, 10000.0, 25.0, 1138.906, 1585.37 + 0.9, 10000.0, 25.5, 1251.116, 1571.74 + 0.9, 10000.0, 26.0, 1365.1, 1552.9 + 0.9, 10000.0, 26.5, 1476.107, 1633.13 + 0.9, 10000.0, 27.0, 1587.356, 1732.77 + 0.9, 10000.0, 27.5, 1698.902, 1845.19 + 0.9, 10000.0, 28.0, 1810.8, 1963.79 + 0.9, 10000.0, 28.5, 1923.104, 2081.92 + 0.9, 10000.0, 29.0, 2035.869, 2192.96 + 0.9, 10000.0, 29.5, 2149.149, 2290.3 + 0.9, 10000.0, 30.0, 2263.0, 2367.3 + 0.9, 10000.0, 30.5, 2379.689, 2290.51 + 0.9, 10000.0, 31.0, 2496.846, 2192.22 + 0.9, 10000.0, 31.5, 2614.317, 2077.89 + 0.9, 10000.0, 32.0, 2731.944, 1952.96 + 0.9, 10000.0, 32.5, 2849.572, 1822.89 + 0.9, 10000.0, 33.0, 2967.045, 1693.14 + 0.9, 10000.0, 33.5, 3084.206, 1569.15 + 0.9, 10000.0, 34.0, 3200.9, 1456.4 + 0.9, 10000.0, 34.5, 3315.781, 1439.62 + 0.9, 10000.0, 35.0, 3429.995, 1437.43 + 0.9, 10000.0, 35.5, 3543.501, 1447.72 + 0.9, 10000.0, 36.0, 3656.255, 1468.4 + 0.9, 10000.0, 36.5, 3768.215, 1497.38 + 0.9, 10000.0, 37.0, 3879.337, 1532.55 + 0.9, 10000.0, 37.5, 3989.58, 1571.82 + 0.9, 10000.0, 38.0, 4098.9, 1613.1 + 0.9, 10000.0, 38.5, 4204.187, 1696.0 + 0.9, 10000.0, 39.0, 4310.056, 1755.08 + 0.9, 10000.0, 39.5, 4417.148, 1778.97 + 0.9, 10000.0, 40.0, 4526.1, 1756.3 + 0.9, 10000.0, 40.5, 4640.576, 1533.14 + 0.9, 10000.0, 41.0, 4756.981, 1297.71 + 0.9, 10000.0, 41.5, 4874.746, 1095.68 + 0.9, 10000.0, 42.0, 4993.3, 972.7 + 0.9, 10000.0, 42.5, 5111.139, 1161.75 + 0.9, 10000.0, 43.0, 5229.0, 1446.25 + 0.9, 10000.0, 43.5, 5346.686, 1796.92 + 0.9, 10000.0, 44.0, 5464.0, 2184.5 + 0.9, 10000.0, 44.5, 5579.792, 2505.31 + 0.9, 10000.0, 45.0, 5695.2, 2834.26 + 0.9, 10000.0, 45.5, 5810.408, 3171.82 + 0.9, 10000.0, 46.0, 5925.6, 3518.5 + 0.9, 10000.0, 46.5, 6042.508, 3936.4 + 0.9, 10000.0, 47.0, 6159.15, 4339.75 + 0.9, 10000.0, 47.5, 6275.092, 4704.4 + 0.9, 10000.0, 48.0, 6389.9, 5006.2 + 0.9, 10000.0, 48.5, 6503.139, 5220.99 + 0.9, 10000.0, 49.0, 6614.375, 5324.62 + 0.9, 10000.0, 49.5, 6723.173, 5292.95 + 0.9, 10000.0, 50.0, 6829.1, 5101.8 + 0.9, 15000.0, 0.0, 482.776, 482.776 + 0.9, 15000.0, 22.0, 552.1, 1103.6 + 0.9, 15000.0, 22.5, 651.1711, 1186.59 + 0.9, 15000.0, 23.0, 751.6188, 1264.17 + 0.9, 15000.0, 23.5, 853.407, 1336.81 + 0.9, 15000.0, 24.0, 956.5, 1405.0 + 0.9, 15000.0, 24.5, 1060.862, 1469.24 + 0.9, 15000.0, 25.0, 1166.456, 1530.01 + 0.9, 15000.0, 25.5, 1273.248, 1587.8 + 0.9, 15000.0, 26.0, 1381.2, 1643.1 + 0.9, 15000.0, 26.5, 1490.827, 1697.11 + 0.9, 15000.0, 27.0, 1601.574, 1749.64 + 0.9, 15000.0, 27.5, 1713.312, 1801.07 + 0.9, 15000.0, 28.0, 1825.91, 1851.76 + 0.9, 15000.0, 28.5, 1939.238, 1902.08 + 0.9, 15000.0, 29.0, 2053.166, 1952.4 + 0.9, 15000.0, 29.5, 2167.563, 2003.08 + 0.9, 15000.0, 30.0, 2282.3, 2054.5 + 0.9, 15000.0, 30.5, 2396.154, 2108.49 + 0.9, 15000.0, 31.0, 2510.192, 2163.8 + 0.9, 15000.0, 31.5, 2624.387, 2220.67 + 0.9, 15000.0, 32.0, 2738.712, 2279.32 + 0.9, 15000.0, 32.5, 2853.143, 2339.99 + 0.9, 15000.0, 33.0, 2967.652, 2402.88 + 0.9, 15000.0, 33.5, 3082.213, 2468.25 + 0.9, 15000.0, 34.0, 3196.8, 2536.3 + 0.9, 15000.0, 34.5, 3310.722, 2636.3 + 0.9, 15000.0, 35.0, 3424.681, 2736.68 + 0.9, 15000.0, 35.5, 3538.715, 2834.91 + 0.9, 15000.0, 36.0, 3652.86, 2928.44 + 0.9, 15000.0, 36.5, 3767.154, 3014.74 + 0.9, 15000.0, 37.0, 3881.634, 3091.28 + 0.9, 15000.0, 37.5, 3996.337, 3155.51 + 0.9, 15000.0, 38.0, 4111.3, 3204.9 + 0.9, 15000.0, 38.5, 4227.38, 3203.16 + 0.9, 15000.0, 39.0, 4343.37, 3199.01 + 0.9, 15000.0, 39.5, 4459.125, 3197.4 + 0.9, 15000.0, 40.0, 4574.5, 3203.3 + 0.9, 15000.0, 40.5, 4688.605, 3239.42 + 0.9, 15000.0, 41.0, 4802.337, 3285.87 + 0.9, 15000.0, 41.5, 4915.852, 3340.51 + 0.9, 15000.0, 42.0, 5029.3, 3401.2 + 0.9, 15000.0, 42.5, 5142.82, 3465.01 + 0.9, 15000.0, 43.0, 5256.588, 3530.9 + 0.9, 15000.0, 43.5, 5370.761, 3597.04 + 0.9, 15000.0, 44.0, 5485.5, 3661.6 + 0.9, 15000.0, 44.5, 5602.695, 3710.13 + 0.9, 15000.0, 45.0, 5720.081, 3758.47 + 0.9, 15000.0, 45.5, 5837.127, 3809.85 + 0.9, 15000.0, 46.0, 5953.3, 3867.5 + 0.9, 15000.0, 46.5, 6065.348, 3953.51 + 0.9, 15000.0, 47.0, 6176.544, 4044.68 + 0.9, 15000.0, 47.5, 6287.443, 4136.68 + 0.9, 15000.0, 48.0, 6398.6, 4225.2 + 0.9, 15000.0, 48.5, 6510.57, 4305.91 + 0.9, 15000.0, 49.0, 6623.906, 4374.48 + 0.9, 15000.0, 49.5, 6739.165, 4426.58 + 0.9, 15000.0, 50.0, 6856.9, 4457.9 + 0.9, 20000.0, 0.0, 400.8828, 400.883 + 0.9, 20000.0, 22.0, 714.7, 1180.3 + 0.9, 20000.0, 22.5, 850.6693, 1249.95 + 0.9, 20000.0, 23.0, 985.1953, 1317.39 + 0.9, 20000.0, 23.5, 1118.749, 1383.03 + 0.9, 20000.0, 24.0, 1251.8, 1447.3 + 0.9, 20000.0, 24.5, 1384.82, 1510.6 + 0.9, 20000.0, 25.0, 1518.28, 1573.34 + 0.9, 20000.0, 25.5, 1652.649, 1635.94 + 0.9, 20000.0, 26.0, 1788.4, 1698.8 + 0.9, 20000.0, 26.5, 1930.923, 1765.45 + 0.9, 20000.0, 27.0, 2076.049, 1833.37 + 0.9, 20000.0, 27.5, 2223.405, 1902.44 + 0.9, 20000.0, 28.0, 2372.62, 1972.54 + 0.9, 20000.0, 28.5, 2523.32, 2043.54 + 0.9, 20000.0, 29.0, 2675.131, 2115.33 + 0.9, 20000.0, 29.5, 2827.682, 2187.79 + 0.9, 20000.0, 30.0, 2980.6, 2260.8 + 0.9, 20000.0, 30.5, 3129.587, 2333.37 + 0.9, 20000.0, 31.0, 3278.568, 2406.33 + 0.9, 20000.0, 31.5, 3427.545, 2479.64 + 0.9, 20000.0, 32.0, 3576.519, 2553.26 + 0.9, 20000.0, 32.5, 3725.49, 2627.16 + 0.9, 20000.0, 33.0, 3874.46, 2701.29 + 0.9, 20000.0, 33.5, 4023.43, 2775.61 + 0.9, 20000.0, 34.0, 4172.4, 2850.1 + 0.9, 20000.0, 34.5, 4321.414, 2923.36 + 0.9, 20000.0, 35.0, 4470.427, 2996.83 + 0.9, 20000.0, 35.5, 4619.435, 3070.6 + 0.9, 20000.0, 36.0, 4768.435, 3144.76 + 0.9, 20000.0, 36.5, 4917.425, 3219.4 + 0.9, 20000.0, 37.0, 5066.401, 3294.61 + 0.9, 20000.0, 37.5, 5215.36, 3370.48 + 0.9, 20000.0, 38.0, 5364.3, 3447.1 + 0.9, 20000.0, 38.5, 5513.092, 3524.75 + 0.9, 20000.0, 39.0, 5661.923, 3603.23 + 0.9, 20000.0, 39.5, 5810.818, 3682.6 + 0.9, 20000.0, 40.0, 5959.8, 3762.9 + 0.9, 20000.0, 40.5, 6109.12, 3845.35 + 0.9, 20000.0, 41.0, 6258.487, 3928.36 + 0.9, 20000.0, 41.5, 6407.836, 4011.51 + 0.9, 20000.0, 42.0, 6557.1, 4094.4 + 0.9, 20000.0, 42.5, 6705.761, 4174.45 + 0.9, 20000.0, 43.0, 6854.388, 4254.26 + 0.9, 20000.0, 43.5, 7003.095, 4334.26 + 0.9, 20000.0, 44.0, 7152.0, 4414.9 + 0.9, 20000.0, 44.5, 7301.987, 4498.99 + 0.9, 20000.0, 45.0, 7452.094, 4583.64 + 0.9, 20000.0, 45.5, 7602.129, 4668.35 + 0.9, 20000.0, 46.0, 7751.9, 4752.6 + 0.9, 20000.0, 46.5, 7900.34, 4831.88 + 0.9, 20000.0, 47.0, 8048.481, 4911.29 + 0.9, 20000.0, 47.5, 8196.482, 4991.93 + 0.9, 20000.0, 48.0, 8344.5, 5074.9 + 0.9, 20000.0, 48.5, 8492.693, 5161.3 + 0.9, 20000.0, 49.0, 8641.219, 5252.21 + 0.9, 20000.0, 49.5, 8790.235, 5348.75 + 0.9, 20000.0, 50.0, 8939.9, 5452.0 + 0.9, 25000.0, 0.0, 330.3733, 330.373 + 0.9, 25000.0, 22.0, 639.8, 999.2 + 0.9, 25000.0, 22.5, 761.0703, 1045.94 + 0.9, 25000.0, 23.0, 881.175, 1095.02 + 0.9, 25000.0, 23.5, 1000.517, 1146.26 + 0.9, 25000.0, 24.0, 1119.5, 1199.5 + 0.9, 25000.0, 24.5, 1238.527, 1254.55 + 0.9, 25000.0, 25.0, 1358.0, 1311.23 + 0.9, 25000.0, 25.5, 1478.323, 1369.37 + 0.9, 25000.0, 26.0, 1599.9, 1428.8 + 0.9, 25000.0, 26.5, 1727.403, 1488.77 + 0.9, 25000.0, 27.0, 1857.208, 1549.64 + 0.9, 25000.0, 27.5, 1988.989, 1611.33 + 0.9, 25000.0, 28.0, 2122.415, 1673.75 + 0.9, 25000.0, 28.5, 2257.158, 1736.83 + 0.9, 25000.0, 29.0, 2392.889, 1800.48 + 0.9, 25000.0, 29.5, 2529.279, 1864.63 + 0.9, 25000.0, 30.0, 2666.0, 1929.2 + 0.9, 25000.0, 30.5, 2799.272, 1993.44 + 0.9, 25000.0, 31.0, 2932.545, 2058.0 + 0.9, 25000.0, 31.5, 3065.819, 2122.85 + 0.9, 25000.0, 32.0, 3199.094, 2187.99 + 0.9, 25000.0, 32.5, 3332.37, 2253.39 + 0.9, 25000.0, 33.0, 3465.646, 2319.04 + 0.9, 25000.0, 33.5, 3598.923, 2384.91 + 0.9, 25000.0, 34.0, 3732.2, 2451.0 + 0.9, 25000.0, 34.5, 3865.462, 2516.5 + 0.9, 25000.0, 35.0, 3998.725, 2582.24 + 0.9, 25000.0, 35.5, 4131.991, 2648.3 + 0.9, 25000.0, 36.0, 4265.26, 2714.72 + 0.9, 25000.0, 36.5, 4398.534, 2781.56 + 0.9, 25000.0, 37.0, 4531.815, 2848.89 + 0.9, 25000.0, 37.5, 4665.103, 2916.75 + 0.9, 25000.0, 38.0, 4798.4, 2985.2 + 0.9, 25000.0, 38.5, 4931.72, 3054.76 + 0.9, 25000.0, 39.0, 5065.044, 3124.8 + 0.9, 25000.0, 39.5, 5198.371, 3195.26 + 0.9, 25000.0, 40.0, 5331.7, 3266.1 + 0.9, 25000.0, 40.5, 5465.048, 3337.14 + 0.9, 25000.0, 41.0, 5598.388, 3408.53 + 0.9, 25000.0, 41.5, 5731.708, 3480.28 + 0.9, 25000.0, 42.0, 5865.0, 3552.4 + 0.9, 25000.0, 42.5, 5998.063, 3624.93 + 0.9, 25000.0, 43.0, 6131.156, 3697.86 + 0.9, 25000.0, 43.5, 6264.346, 3771.18 + 0.9, 25000.0, 44.0, 6397.7, 3844.9 + 0.9, 25000.0, 44.5, 6531.82, 3918.58 + 0.9, 25000.0, 45.0, 6666.025, 3992.85 + 0.9, 25000.0, 45.5, 6800.167, 4067.9 + 0.9, 25000.0, 46.0, 6934.1, 4143.9 + 0.9, 25000.0, 46.5, 7066.985, 4220.89 + 0.9, 25000.0, 47.0, 7199.644, 4299.27 + 0.9, 25000.0, 47.5, 7332.205, 4379.29 + 0.9, 25000.0, 48.0, 7464.8, 4461.2 + 0.9, 25000.0, 48.5, 7597.557, 4545.25 + 0.9, 25000.0, 49.0, 7730.606, 4631.68 + 0.9, 25000.0, 49.5, 7864.077, 4720.75 + 0.9, 25000.0, 50.0, 7998.1, 4812.7 + 0.9, 30000.0, 0.0, 270.0415, 270.041 + 0.9, 30000.0, 22.0, 519.1, 802.1 + 0.9, 30000.0, 22.5, 617.5205, 845.588 + 0.9, 30000.0, 23.0, 714.9359, 889.334 + 0.9, 30000.0, 23.5, 811.6834, 933.389 + 0.9, 30000.0, 24.0, 908.1, 977.8 + 0.9, 30000.0, 24.5, 1004.523, 1022.62 + 0.9, 30000.0, 25.0, 1101.289, 1067.89 + 0.9, 30000.0, 25.5, 1198.736, 1113.67 + 0.9, 30000.0, 26.0, 1297.2, 1160.0 + 0.9, 30000.0, 26.5, 1400.56, 1207.94 + 0.9, 30000.0, 27.0, 1505.814, 1256.59 + 0.9, 30000.0, 27.5, 1612.692, 1305.83 + 0.9, 30000.0, 28.0, 1720.925, 1355.52 + 0.9, 30000.0, 28.5, 1830.242, 1405.57 + 0.9, 30000.0, 29.0, 1940.373, 1455.82 + 0.9, 30000.0, 29.5, 2051.049, 1506.18 + 0.9, 30000.0, 30.0, 2162.0, 1556.5 + 0.9, 30000.0, 30.5, 2270.158, 1603.97 + 0.9, 30000.0, 31.0, 2378.317, 1651.41 + 0.9, 30000.0, 31.5, 2486.474, 1698.98 + 0.9, 30000.0, 32.0, 2594.625, 1746.8 + 0.9, 30000.0, 32.5, 2702.767, 1795.01 + 0.9, 30000.0, 33.0, 2810.895, 1843.74 + 0.9, 30000.0, 33.5, 2919.008, 1893.12 + 0.9, 30000.0, 34.0, 3027.1, 1943.3 + 0.9, 30000.0, 34.5, 3135.056, 1997.41 + 0.9, 30000.0, 35.0, 3242.995, 2052.29 + 0.9, 30000.0, 35.5, 3350.926, 2107.8 + 0.9, 30000.0, 36.0, 3458.855, 2163.77 + 0.9, 30000.0, 36.5, 3566.79, 2220.08 + 0.9, 30000.0, 37.0, 3674.737, 2276.55 + 0.9, 30000.0, 37.5, 3782.705, 2333.04 + 0.9, 30000.0, 38.0, 3890.7, 2389.4 + 0.9, 30000.0, 38.5, 3998.799, 2444.61 + 0.9, 30000.0, 39.0, 4106.905, 2499.84 + 0.9, 30000.0, 39.5, 4215.008, 2555.12 + 0.9, 30000.0, 40.0, 4323.1, 2610.5 + 0.9, 30000.0, 40.5, 4431.102, 2665.92 + 0.9, 30000.0, 41.0, 4539.106, 2721.56 + 0.9, 30000.0, 41.5, 4647.132, 2777.5 + 0.9, 30000.0, 42.0, 4755.2, 2833.8 + 0.9, 30000.0, 42.5, 4863.358, 2890.84 + 0.9, 30000.0, 43.0, 4971.588, 2948.3 + 0.9, 30000.0, 43.5, 5079.898, 3006.13 + 0.9, 30000.0, 44.0, 5188.3, 3064.3 + 0.9, 30000.0, 44.5, 5297.063, 3122.38 + 0.9, 30000.0, 45.0, 5405.831, 3180.88 + 0.9, 30000.0, 45.5, 5514.509, 3239.91 + 0.9, 30000.0, 46.0, 5623.0, 3299.6 + 0.9, 30000.0, 46.5, 5730.718, 3359.16 + 0.9, 30000.0, 47.0, 5838.256, 3419.96 + 0.9, 30000.0, 47.5, 5945.716, 3482.48 + 0.9, 30000.0, 48.0, 6053.2, 3547.2 + 0.9, 30000.0, 48.5, 6160.809, 3614.58 + 0.9, 30000.0, 49.0, 6268.644, 3685.11 + 0.9, 30000.0, 49.5, 6376.807, 3759.26 + 0.9, 30000.0, 50.0, 6485.4, 3837.5 + 0.9, 35000.0, 0.0, 218.7643, 218.764 + 0.9, 35000.0, 22.0, 402.9, 669.2 + 0.9, 35000.0, 22.5, 479.366, 701.515 + 0.9, 35000.0, 23.0, 555.0469, 734.63 + 0.9, 35000.0, 23.5, 630.2043, 768.479 + 0.9, 35000.0, 24.0, 705.1, 803.0 + 0.9, 35000.0, 24.5, 779.9957, 838.127 + 0.9, 35000.0, 25.0, 855.1531, 873.795 + 0.9, 35000.0, 25.5, 930.834, 909.941 + 0.9, 35000.0, 26.0, 1007.3, 946.5 + 0.9, 35000.0, 26.5, 1087.558, 983.126 + 0.9, 35000.0, 27.0, 1169.282, 1020.02 + 0.9, 35000.0, 27.5, 1252.262, 1057.16 + 0.9, 35000.0, 28.0, 1336.29, 1094.55 + 0.9, 35000.0, 28.5, 1421.157, 1132.15 + 0.9, 35000.0, 29.0, 1506.653, 1169.95 + 0.9, 35000.0, 29.5, 1592.571, 1207.94 + 0.9, 35000.0, 30.0, 1678.7, 1246.1 + 0.9, 35000.0, 30.5, 1762.647, 1284.11 + 0.9, 35000.0, 31.0, 1846.597, 1322.28 + 0.9, 35000.0, 31.5, 1930.548, 1360.64 + 0.9, 35000.0, 32.0, 2014.5, 1399.19 + 0.9, 35000.0, 32.5, 2098.452, 1437.95 + 0.9, 35000.0, 33.0, 2182.403, 1476.92 + 0.9, 35000.0, 33.5, 2266.353, 1516.14 + 0.9, 35000.0, 34.0, 2350.3, 1555.6 + 0.9, 35000.0, 34.5, 2434.218, 1595.71 + 0.9, 35000.0, 35.0, 2518.134, 1636.05 + 0.9, 35000.0, 35.5, 2602.051, 1676.61 + 0.9, 35000.0, 36.0, 2685.97, 1717.37 + 0.9, 35000.0, 36.5, 2769.893, 1758.28 + 0.9, 35000.0, 37.0, 2853.821, 1799.34 + 0.9, 35000.0, 37.5, 2937.756, 1840.52 + 0.9, 35000.0, 38.0, 3021.7, 1881.8 + 0.9, 35000.0, 38.5, 3105.68, 1922.88 + 0.9, 35000.0, 39.0, 3189.659, 1964.15 + 0.9, 35000.0, 39.5, 3273.634, 2005.64 + 0.9, 35000.0, 40.0, 3357.6, 2047.4 + 0.9, 35000.0, 40.5, 3441.532, 2089.53 + 0.9, 35000.0, 41.0, 3525.456, 2131.96 + 0.9, 35000.0, 41.5, 3609.377, 2174.72 + 0.9, 35000.0, 42.0, 3693.3, 2217.8 + 0.9, 35000.0, 42.5, 3777.182, 2261.28 + 0.9, 35000.0, 43.0, 3861.094, 2305.09 + 0.9, 35000.0, 43.5, 3945.059, 2349.2 + 0.9, 35000.0, 44.0, 4029.1, 2393.6 + 0.9, 35000.0, 44.5, 4113.491, 2438.05 + 0.9, 35000.0, 45.0, 4197.906, 2482.84 + 0.9, 35000.0, 45.5, 4282.268, 2528.07 + 0.9, 35000.0, 46.0, 4366.5, 2573.8 + 0.9, 35000.0, 46.5, 4450.143, 2619.94 + 0.9, 35000.0, 47.0, 4533.656, 2666.81 + 0.9, 35000.0, 47.5, 4617.116, 2714.55 + 0.9, 35000.0, 48.0, 4700.6, 2763.3 + 0.9, 35000.0, 48.5, 4784.184, 2813.21 + 0.9, 35000.0, 49.0, 4867.944, 2864.41 + 0.9, 35000.0, 49.5, 4951.957, 2917.06 + 0.9, 35000.0, 50.0, 5036.3, 2971.3 + 0.9, 39000.0, 0.0, 181.4454, 181.445 + 0.9, 39000.0, 22.0, 324.1, 572.6 + 0.9, 39000.0, 22.5, 385.5748, 597.287 + 0.9, 39000.0, 23.0, 446.4266, 623.233 + 0.9, 39000.0, 23.5, 506.865, 650.313 + 0.9, 39000.0, 24.0, 567.1, 678.4 + 0.9, 39000.0, 24.5, 627.3412, 707.369 + 0.9, 39000.0, 25.0, 687.7984, 737.092 + 0.9, 39000.0, 25.5, 748.6814, 767.445 + 0.9, 39000.0, 26.0, 810.2, 798.3 + 0.9, 39000.0, 26.5, 874.7746, 828.986 + 0.9, 39000.0, 27.0, 940.5306, 859.892 + 0.9, 39000.0, 27.5, 1007.299, 890.984 + 0.9, 39000.0, 28.0, 1074.91, 922.23 + 0.9, 39000.0, 28.5, 1143.195, 953.597 + 0.9, 39000.0, 29.0, 1211.984, 985.053 + 0.9, 39000.0, 29.5, 1281.109, 1016.56 + 0.9, 39000.0, 30.0, 1350.4, 1048.1 + 0.9, 39000.0, 30.5, 1417.903, 1079.02 + 0.9, 39000.0, 31.0, 1485.403, 1109.96 + 0.9, 39000.0, 31.5, 1552.902, 1140.94 + 0.9, 39000.0, 32.0, 1620.4, 1171.98 + 0.9, 39000.0, 32.5, 1687.898, 1203.11 + 0.9, 39000.0, 33.0, 1755.397, 1234.36 + 0.9, 39000.0, 33.5, 1822.897, 1265.75 + 0.9, 39000.0, 34.0, 1890.4, 1297.3 + 0.9, 39000.0, 34.5, 1957.919, 1329.44 + 0.9, 39000.0, 35.0, 2025.441, 1361.75 + 0.9, 39000.0, 35.5, 2092.964, 1394.23 + 0.9, 39000.0, 36.0, 2160.49, 1426.85 + 0.9, 39000.0, 36.5, 2228.017, 1459.62 + 0.9, 39000.0, 37.0, 2295.544, 1492.51 + 0.9, 39000.0, 37.5, 2363.072, 1525.5 + 0.9, 39000.0, 38.0, 2430.6, 1558.6 + 0.9, 39000.0, 38.5, 2498.13, 1591.38 + 0.9, 39000.0, 39.0, 2565.658, 1624.43 + 0.9, 39000.0, 39.5, 2633.181, 1657.85 + 0.9, 39000.0, 40.0, 2700.7, 1691.7 + 0.9, 39000.0, 40.5, 2768.198, 1726.56 + 0.9, 39000.0, 41.0, 2835.694, 1761.82 + 0.9, 39000.0, 41.5, 2903.193, 1797.34 + 0.9, 39000.0, 42.0, 2970.7, 1833.0 + 0.9, 39000.0, 42.5, 3038.196, 1868.26 + 0.9, 39000.0, 43.0, 3105.719, 1903.59 + 0.9, 39000.0, 43.5, 3173.282, 1939.02 + 0.9, 39000.0, 44.0, 3240.9, 1974.6 + 0.9, 39000.0, 44.5, 3308.762, 2010.29 + 0.9, 39000.0, 45.0, 3376.637, 2046.26 + 0.9, 39000.0, 45.5, 3444.469, 2082.57 + 0.9, 39000.0, 46.0, 3512.2, 2119.3 + 0.9, 39000.0, 46.5, 3579.49, 2156.37 + 0.9, 39000.0, 47.0, 3646.681, 2194.08 + 0.9, 39000.0, 47.5, 3713.832, 2232.58 + 0.9, 39000.0, 48.0, 3781.0, 2272.0 + 0.9, 39000.0, 48.5, 3848.243, 2312.49 + 0.9, 39000.0, 49.0, 3915.619, 2354.19 + 0.9, 39000.0, 49.5, 3983.185, 2397.25 + 0.9, 39000.0, 50.0, 4051.0, 2441.8 + 0.9, 43000.0, 0.0, 149.7104, 149.71 + 0.9, 43000.0, 22.0, 261.9, 498.3 + 0.9, 43000.0, 22.5, 311.5975, 518.004 + 0.9, 43000.0, 23.0, 360.7828, 538.891 + 0.9, 43000.0, 23.5, 409.6268, 560.832 + 0.9, 43000.0, 24.0, 458.3, 583.7 + 0.9, 43000.0, 24.5, 506.9732, 607.368 + 0.9, 43000.0, 25.0, 555.8172, 631.709 + 0.9, 43000.0, 25.5, 605.0025, 656.596 + 0.9, 43000.0, 26.0, 654.7, 681.9 + 0.9, 43000.0, 26.5, 706.8727, 706.841 + 0.9, 43000.0, 27.0, 760.0012, 731.909 + 0.9, 43000.0, 27.5, 813.9492, 757.087 + 0.9, 43000.0, 28.0, 868.58, 782.36 + 0.9, 43000.0, 28.5, 923.757, 807.713 + 0.9, 43000.0, 29.0, 979.3437, 833.131 + 0.9, 43000.0, 29.5, 1035.204, 858.599 + 0.9, 43000.0, 30.0, 1091.2, 884.1 + 0.9, 43000.0, 30.5, 1145.765, 909.269 + 0.9, 43000.0, 31.0, 1200.329, 934.474 + 0.9, 43000.0, 31.5, 1254.893, 959.735 + 0.9, 43000.0, 32.0, 1309.456, 985.069 + 0.9, 43000.0, 32.5, 1364.019, 1010.49 + 0.9, 43000.0, 33.0, 1418.58, 1036.03 + 0.9, 43000.0, 33.5, 1473.141, 1061.69 + 0.9, 43000.0, 34.0, 1527.7, 1087.5 + 0.9, 43000.0, 34.5, 1582.246, 1113.81 + 0.9, 43000.0, 35.0, 1636.792, 1140.28 + 0.9, 43000.0, 35.5, 1691.338, 1166.88 + 0.9, 43000.0, 36.0, 1745.885, 1193.59 + 0.9, 43000.0, 36.5, 1800.434, 1220.42 + 0.9, 43000.0, 37.0, 1854.985, 1247.34 + 0.9, 43000.0, 37.5, 1909.54, 1274.34 + 0.9, 43000.0, 38.0, 1964.1, 1301.4 + 0.9, 43000.0, 38.5, 2018.678, 1328.18 + 0.9, 43000.0, 39.0, 2073.255, 1355.17 + 0.9, 43000.0, 39.5, 2127.829, 1382.42 + 0.9, 43000.0, 40.0, 2182.4, 1410.0 + 0.9, 43000.0, 40.5, 2236.952, 1438.29 + 0.9, 43000.0, 41.0, 2291.5, 1466.88 + 0.9, 43000.0, 41.5, 2346.048, 1495.71 + 0.9, 43000.0, 42.0, 2400.6, 1524.7 + 0.9, 43000.0, 42.5, 2455.127, 1553.58 + 0.9, 43000.0, 43.0, 2509.675, 1582.55 + 0.9, 43000.0, 43.5, 2564.261, 1611.62 + 0.9, 43000.0, 44.0, 2618.9, 1640.8 + 0.9, 43000.0, 44.5, 2673.78, 1669.74 + 0.9, 43000.0, 45.0, 2728.675, 1698.93 + 0.9, 43000.0, 45.5, 2783.533, 1728.54 + 0.9, 43000.0, 46.0, 2838.3, 1758.7 + 0.9, 43000.0, 46.5, 2892.658, 1790.1 + 0.9, 43000.0, 47.0, 2946.925, 1822.14 + 0.9, 43000.0, 47.5, 3001.155, 1854.76 + 0.9, 43000.0, 48.0, 3055.4, 1887.9 + 0.9, 43000.0, 48.5, 3109.714, 1921.49 + 0.9, 43000.0, 49.0, 3164.15, 1955.46 + 0.9, 43000.0, 49.5, 3218.761, 1989.75 + 0.9, 43000.0, 50.0, 3273.6, 2024.3 + 0.9, 48000.0, 0.0, 117.7292, 117.729 + 0.9, 48000.0, 22.0, 206.2, 392.4 + 0.9, 48000.0, 22.5, 245.3439, 407.94 + 0.9, 48000.0, 23.0, 284.0859, 424.403 + 0.9, 48000.0, 23.5, 322.56, 441.689 + 0.9, 48000.0, 24.0, 360.9, 459.7 + 0.9, 48000.0, 24.5, 399.24, 478.336 + 0.9, 48000.0, 25.0, 437.7141, 497.497 + 0.9, 48000.0, 25.5, 476.4561, 517.085 + 0.9, 48000.0, 26.0, 515.6, 537.0 + 0.9, 48000.0, 26.5, 556.6854, 556.635 + 0.9, 48000.0, 27.0, 598.5209, 576.369 + 0.9, 48000.0, 27.5, 640.9998, 596.192 + 0.9, 48000.0, 28.0, 684.015, 616.09 + 0.9, 48000.0, 28.5, 727.4596, 636.052 + 0.9, 48000.0, 29.0, 771.2266, 656.066 + 0.9, 48000.0, 29.5, 815.209, 676.119 + 0.9, 48000.0, 30.0, 859.3, 696.2 + 0.9, 48000.0, 30.5, 902.2757, 716.021 + 0.9, 48000.0, 31.0, 945.2523, 735.871 + 0.9, 48000.0, 31.5, 988.2294, 755.766 + 0.9, 48000.0, 32.0, 1031.206, 775.719 + 0.9, 48000.0, 32.5, 1074.182, 795.744 + 0.9, 48000.0, 33.0, 1117.157, 815.857 + 0.9, 48000.0, 33.5, 1160.13, 836.071 + 0.9, 48000.0, 34.0, 1203.1, 856.4 + 0.9, 48000.0, 34.5, 1246.049, 877.131 + 0.9, 48000.0, 35.0, 1288.997, 897.98 + 0.9, 48000.0, 35.5, 1331.943, 918.935 + 0.9, 48000.0, 36.0, 1374.89, 939.985 + 0.9, 48000.0, 36.5, 1417.838, 961.118 + 0.9, 48000.0, 37.0, 1460.788, 982.323 + 0.9, 48000.0, 37.5, 1503.742, 1003.59 + 0.9, 48000.0, 38.0, 1546.7, 1024.9 + 0.9, 48000.0, 38.5, 1589.672, 1045.99 + 0.9, 48000.0, 39.0, 1632.647, 1067.24 + 0.9, 48000.0, 39.5, 1675.623, 1088.69 + 0.9, 48000.0, 40.0, 1718.6, 1110.4 + 0.9, 48000.0, 40.5, 1761.575, 1132.67 + 0.9, 48000.0, 41.0, 1804.55, 1155.18 + 0.9, 48000.0, 41.5, 1847.525, 1177.88 + 0.9, 48000.0, 42.0, 1890.5, 1200.7 + 0.9, 48000.0, 42.5, 1933.44, 1223.43 + 0.9, 48000.0, 43.0, 1976.394, 1246.24 + 0.9, 48000.0, 43.5, 2019.376, 1269.13 + 0.9, 48000.0, 44.0, 2062.4, 1292.1 + 0.9, 48000.0, 44.5, 2105.625, 1314.9 + 0.9, 48000.0, 45.0, 2148.862, 1337.91 + 0.9, 48000.0, 45.5, 2192.069, 1361.24 + 0.9, 48000.0, 46.0, 2235.2, 1385.0 + 0.9, 48000.0, 46.5, 2277.99, 1409.72 + 0.9, 48000.0, 47.0, 2320.706, 1434.94 + 0.9, 48000.0, 47.5, 2363.395, 1460.62 + 0.9, 48000.0, 48.0, 2406.1, 1486.7 + 0.9, 48000.0, 48.5, 2448.868, 1513.14 + 0.9, 48000.0, 49.0, 2491.744, 1539.88 + 0.9, 48000.0, 49.5, 2534.773, 1566.89 + 0.9, 48000.0, 50.0, 2578.0, 1594.1 diff --git a/aviary/models/engines/turbofan_24k_2.deck b/aviary/models/engines/turbofan_24k_2.deck deleted file mode 100644 index 9981e42565..0000000000 --- a/aviary/models/engines/turbofan_24k_2.deck +++ /dev/null @@ -1,13232 +0,0 @@ -# GASP-derived engine deck converted from GASP_turbofan_24_2.eng -# t4max: 50.0 -# t4cruise: 44.5 -# t4climb: 50.0 -# sls_airflow: 926.2 -# sfn_idle: 1.115 - -Mach_Number (unitless), Altitude (ft), Throttle (unitless), Thrust (lbf), Fuel_Flow (lb/h) - 0.0, 0.0, 0.0, 516.3539624057992, 516.3539624057992 - 0.0, 0.0, 22.0, 1905.1, 712.7 - 0.0, 0.0, 22.5, 2266.6806640625, 780.0728515625 - 0.0, 0.0, 23.0, 2624.5296875, 848.3671874999999 - 0.0, 0.0, 23.5, 2979.8888671874993, 917.7779296875 - 0.0, 0.0, 24.0, 3333.999999999999, 988.5 - 0.0, 0.0, 24.5, 3688.1048828124995, 1060.7283203124998 - 0.0, 0.0, 25.0, 4043.4453124999986, 1134.6578124999999 - 0.0, 0.0, 25.5, 4401.2630859374985, 1210.4833984375 - 0.0, 0.0, 26.0, 4762.799999999997, 1288.4 - 0.0, 0.0, 26.5, 5142.33125, 1370.6628906250003 - 0.0, 0.0, 27.0, 5528.81, 1455.5243750000004 - 0.0, 0.0, 27.5, 5921.243750000001, 1542.8261718750005 - 0.0, 0.0, 28.0, 6318.639999999999, 1632.4100000000003 - 0.0, 0.0, 28.5, 6720.0062499999985, 1724.1175781250004 - 0.0, 0.0, 29.0, 7124.3499999999985, 1817.7906250000005 - 0.0, 0.0, 29.5, 7530.678749999999, 1913.2708593750006 - 0.0, 0.0, 30.0, 7937.999999999998, 2010.4000000000005 - 0.0, 0.0, 30.5, 8334.899999999998, 2107.901269531251 - 0.0, 0.0, 31.0, 8731.799999999996, 2206.841406250001 - 0.0, 0.0, 31.5, 9128.699999999997, 2307.168652343751 - 0.0, 0.0, 32.0, 9525.599999999993, 2408.831250000001 - 0.0, 0.0, 32.5, 9922.499999999995, 2511.7774414062515 - 0.0, 0.0, 33.0, 10319.399999999992, 2615.9554687500013 - 0.0, 0.0, 33.5, 10716.299999999994, 2721.3135742187515 - 0.0, 0.0, 34.0, 11113.19999999999, 2827.8000000000015 - 0.0, 0.0, 34.5, 11510.099999999995, 2936.0130859374976 - 0.0, 0.0, 35.0, 11906.999999999995, 3045.1890624999974 - 0.0, 0.0, 35.5, 12303.899999999994, 3155.2142578124967 - 0.0, 0.0, 36.0, 12700.799999999992, 3265.9749999999963 - 0.0, 0.0, 36.5, 13097.699999999992, 3377.3576171874956 - 0.0, 0.0, 37.0, 13494.599999999991, 3489.248437499995 - 0.0, 0.0, 37.5, 13891.499999999989, 3601.533789062494 - 0.0, 0.0, 38.0, 14288.399999999987, 3714.0999999999935 - 0.0, 0.0, 38.5, 14685.299999999988, 3826.480078125004 - 0.0, 0.0, 39.0, 15082.199999999986, 3939.0968750000043 - 0.0, 0.0, 39.5, 15479.099999999982, 4051.9152343750047 - 0.0, 0.0, 40.0, 15875.999999999978, 4164.900000000006 - 0.0, 0.0, 40.5, 16272.900000000003, 4278.6195312499985 - 0.0, 0.0, 41.0, 16669.800000000007, 4392.1937499999985 - 0.0, 0.0, 41.5, 17066.700000000004, 4505.346093749998 - 0.0, 0.0, 42.0, 17463.600000000006, 4617.799999999997 - 0.0, 0.0, 42.5, 17860.19140624999, 4727.431250000003 - 0.0, 0.0, 43.0, 18256.906249999993, 4836.550000000004 - 0.0, 0.0, 43.5, 18653.867968749986, 4945.618750000004 - 0.0, 0.0, 44.0, 19051.199999999983, 5055.100000000005 - 0.0, 0.0, 44.5, 19450.26015625001, 5167.850781250002 - 0.0, 0.0, 45.0, 19849.44375000001, 5280.9812500000035 - 0.0, 0.0, 45.5, 20248.380468750012, 5393.9960937500055 - 0.0, 0.0, 46.0, 20646.700000000015, 5506.400000000006 - 0.0, 0.0, 46.5, 21042.18046875001, 5615.123437499996 - 0.0, 0.0, 47.0, 21437.04375000001, 5723.274999999994 - 0.0, 0.0, 47.5, 21831.660156250015, 5831.389062499993 - 0.0, 0.0, 48.0, 22226.40000000002, 5939.999999999992 - 0.0, 0.0, 48.5, 22621.633593750023, 6049.6421874999905 - 0.0, 0.0, 49.0, 23017.731250000026, 6160.8499999999885 - 0.0, 0.0, 49.5, 23415.063281250033, 6274.157812499988 - 0.0, 0.0, 50.0, 23814.000000000036, 6390.099999999986 - 0.0, 2000.0, 0.0, 483.4465959273738, 483.4465959273738 - 0.0, 2000.0, 22.0, 1886.2, 685.4 - 0.0, 2000.0, 22.5, 2244.1322265625, 753.1798828125 - 0.0, 2000.0, 23.0, 2598.3921874999996, 821.5359374999999 - 0.0, 2000.0, 23.5, 2950.2060546875, 890.7240234374999 - 0.0, 2000.0, 24.0, 3300.7999999999993, 960.9999999999998 - 0.0, 2000.0, 24.5, 3651.400195312499, 1032.6197265624996 - 0.0, 2000.0, 25.0, 4003.2328124999985, 1105.8390624999995 - 0.0, 2000.0, 25.5, 4357.524023437499, 1180.9138671874994 - 0.0, 2000.0, 26.0, 4715.499999999998, 1258.0999999999992 - 0.0, 2000.0, 26.5, 5091.2658203125, 1340.1607421875003 - 0.0, 2000.0, 27.0, 5473.904687500001, 1424.9878125000002 - 0.0, 2000.0, 27.5, 5862.434960937501, 1512.4072265625005 - 0.0, 2000.0, 28.0, 6255.875000000002, 1602.2450000000008 - 0.0, 2000.0, 28.5, 6653.243164062502, 1694.327148437501 - 0.0, 2000.0, 29.0, 7053.557812500002, 1788.4796875000006 - 0.0, 2000.0, 29.5, 7455.837304687503, 1884.528632812501 - 0.0, 2000.0, 30.0, 7859.100000000004, 1982.300000000001 - 0.0, 2000.0, 30.5, 8252.061132812507, 2080.75478515625 - 0.0, 2000.0, 31.0, 8645.023437500007, 2180.66640625 - 0.0, 2000.0, 31.5, 9037.986523437507, 2281.9432617187504 - 0.0, 2000.0, 32.0, 9430.950000000008, 2384.4937499999996 - 0.0, 2000.0, 32.5, 9823.913476562508, 2488.22626953125 - 0.0, 2000.0, 33.0, 10216.87656250001, 2593.0492187500004 - 0.0, 2000.0, 33.5, 10609.838867187513, 2698.87099609375 - 0.0, 2000.0, 34.0, 11002.800000000012, 2805.6 - 0.0, 2000.0, 34.5, 11395.7464453125, 2912.853828124999 - 0.0, 2000.0, 35.0, 11788.692187500003, 3020.8593749999986 - 0.0, 2000.0, 35.5, 12181.638085937502, 3129.5527343749995 - 0.0, 2000.0, 36.0, 12574.585000000005, 3238.8699999999994 - 0.0, 2000.0, 36.5, 12967.533789062505, 3348.747265625 - 0.0, 2000.0, 37.0, 13360.485312500006, 3459.120625 - 0.0, 2000.0, 37.5, 13753.44042968751, 3569.926171875 - 0.0, 2000.0, 38.0, 14146.40000000001, 3681.1000000000013 - 0.0, 2000.0, 38.5, 14539.377539062507, 3793.542187499996 - 0.0, 2000.0, 39.0, 14932.354687500007, 3905.724999999996 - 0.0, 2000.0, 39.5, 15325.329492187508, 4017.3703124999947 - 0.0, 2000.0, 40.0, 15718.30000000001, 4128.199999999994 - 0.0, 2000.0, 40.5, 16111.255468749994, 4235.986718749999 - 0.0, 2000.0, 41.0, 16504.206249999992, 4343.181249999999 - 0.0, 2000.0, 41.5, 16897.15390624999, 4450.285156249998 - 0.0, 2000.0, 42.0, 17290.099999999988, 4557.799999999998 - 0.0, 2000.0, 42.5, 17682.741406249996, 4668.680468750002 - 0.0, 2000.0, 43.0, 18075.50624999999, 4779.993750000003 - 0.0, 2000.0, 43.5, 18468.51796874999, 4891.260156250003 - 0.0, 2000.0, 44.0, 18861.89999999999, 5002.000000000004 - 0.0, 2000.0, 44.5, 19257.006250000006, 5109.54609375 - 0.0, 2000.0, 45.0, 19652.23750000001, 5216.481249999999 - 0.0, 2000.0, 45.5, 20047.225000000013, 5323.200781250001 - 0.0, 2000.0, 46.0, 20441.600000000017, 5430.1 - 0.0, 2000.0, 46.5, 20833.153906249998, 5538.339843750004 - 0.0, 2000.0, 47.0, 21224.093749999996, 5647.243750000006 - 0.0, 2000.0, 47.5, 21614.786718749998, 5756.900781250006 - 0.0, 2000.0, 48.0, 22005.599999999995, 5867.400000000008 - 0.0, 2000.0, 48.5, 22396.900781249995, 5978.8304687500095 - 0.0, 2000.0, 49.0, 22789.05624999999, 6091.281250000012 - 0.0, 2000.0, 49.5, 23182.433593749993, 6204.841406250013 - 0.0, 2000.0, 50.0, 23577.39999999999, 6319.600000000017 - 0.0, 5000.0, 0.0, 437.2125257544623, 437.2125257544623 - 0.0, 5000.0, 22.0, 1789.5, 634.7 - 0.0, 5000.0, 22.5, 2129.0871093749993, 699.7759765625001 - 0.0, 5000.0, 23.0, 2465.1906249999997, 765.1046875 - 0.0, 5000.0, 23.5, 2798.9738281249993, 830.9810546875001 - 0.0, 5000.0, 24.0, 3131.5999999999995, 897.7 - 0.0, 5000.0, 24.5, 3464.232421874999, 965.5564453125 - 0.0, 5000.0, 25.0, 3798.0343749999984, 1034.8453124999999 - 0.0, 5000.0, 25.5, 4134.169140624997, 1105.8615234375002 - 0.0, 5000.0, 26.0, 4473.799999999998, 1178.8999999999999 - 0.0, 5000.0, 26.5, 4830.3101562500015, 1257.0966796875002 - 0.0, 5000.0, 27.0, 5193.341250000001, 1338.0678125 - 0.0, 5000.0, 27.5, 5561.961718750002, 1421.6212890625 - 0.0, 5000.0, 28.0, 5935.240000000002, 1507.565 - 0.0, 5000.0, 28.5, 6312.244531250002, 1595.7068359375 - 0.0, 5000.0, 29.0, 6692.043750000002, 1685.8546875 - 0.0, 5000.0, 29.5, 7073.706093750004, 1777.8164453125003 - 0.0, 5000.0, 30.0, 7456.300000000004, 1871.4000000000003 - 0.0, 5000.0, 30.5, 7829.1125, 1965.3250976562506 - 0.0, 5000.0, 31.0, 8201.925, 2060.591406250001 - 0.0, 5000.0, 31.5, 8574.737500000001, 2157.110449218751 - 0.0, 5000.0, 32.0, 8947.550000000001, 2254.7937500000007 - 0.0, 5000.0, 32.5, 9320.3625, 2353.5528320312515 - 0.0, 5000.0, 33.0, 9693.175, 2453.299218750001 - 0.0, 5000.0, 33.5, 10065.9875, 2553.944433593751 - 0.0, 5000.0, 34.0, 10438.8, 2655.4000000000015 - 0.0, 5000.0, 34.5, 10811.609218749982, 2758.028203124999 - 0.0, 5000.0, 35.0, 11184.418749999979, 2861.246874999999 - 0.0, 5000.0, 35.5, 11557.228906249977, 2964.9246093749994 - 0.0, 5000.0, 36.0, 11930.039999999972, 3068.929999999999 - 0.0, 5000.0, 36.5, 12302.852343749966, 3173.131640624999 - 0.0, 5000.0, 37.0, 12675.666249999964, 3277.398124999999 - 0.0, 5000.0, 37.5, 13048.48203124996, 3381.598046874999 - 0.0, 5000.0, 38.0, 13421.299999999952, 3485.599999999999 - 0.0, 5000.0, 38.5, 13794.128906249996, 3588.667187499999 - 0.0, 5000.0, 39.0, 14166.956249999997, 3691.587499999999 - 0.0, 5000.0, 39.5, 14539.780468749997, 3794.3640624999994 - 0.0, 5000.0, 40.0, 14912.599999999997, 3896.999999999999 - 0.0, 5000.0, 40.5, 15285.401562500008, 3999.584375000001 - 0.0, 5000.0, 41.0, 15658.20000000001, 4102.000000000002 - 0.0, 5000.0, 41.5, 16030.998437500013, 4204.215625000001 - 0.0, 5000.0, 42.0, 16403.800000000014, 4306.200000000002 - 0.0, 5000.0, 42.5, 16776.330468749988, 4407.445312499999 - 0.0, 5000.0, 43.0, 17148.981249999986, 4508.587499999998 - 0.0, 5000.0, 43.5, 17521.86640624998, 4609.785937499997 - 0.0, 5000.0, 44.0, 17895.099999999977, 4711.199999999996 - 0.0, 5000.0, 44.5, 18269.952343749992, 4813.3171875 - 0.0, 5000.0, 45.0, 18644.918749999993, 4915.8375 - 0.0, 5000.0, 45.5, 19019.650781249988, 5018.7890625 - 0.0, 5000.0, 46.0, 19393.79999999999, 5122.2 - 0.0, 5000.0, 46.5, 19765.27578125, 5225.914843749999 - 0.0, 5000.0, 47.0, 20136.168749999993, 5330.218749999999 - 0.0, 5000.0, 47.5, 20506.827343749992, 5435.2132812499985 - 0.0, 5000.0, 48.0, 20877.59999999999, 5540.999999999999 - 0.0, 5000.0, 48.5, 21248.835156249992, 5647.680468749999 - 0.0, 5000.0, 49.0, 21620.881249999988, 5755.356249999999 - 0.0, 5000.0, 49.5, 21994.086718749983, 5864.128906249999 - 0.0, 5000.0, 50.0, 22368.79999999998, 5974.1 - 0.0, 10000.0, 0.0, 367.97685968937094, 367.97685968937094 - 0.0, 10000.0, 22.0, 1639.5000000000014, 619.3000000000005 - 0.0, 10000.0, 22.5, 1949.7384765624988, 632.8058593749994 - 0.0, 10000.0, 23.0, 2256.9921874999973, 652.978124999999 - 0.0, 10000.0, 23.5, 2562.299804687494, 679.5113281249983 - 0.0, 10000.0, 24.0, 2866.6999999999903, 712.0999999999979 - 0.0, 10000.0, 24.5, 3171.2314453124873, 750.4386718749972 - 0.0, 10000.0, 25.0, 3476.932812499983, 794.2218749999969 - 0.0, 10000.0, 25.5, 3784.8427734374773, 843.1441406249966 - 0.0, 10000.0, 26.0, 4095.9999999999704, 896.8999999999955 - 0.0, 10000.0, 26.5, 4422.491406250018, 950.5710937500002 - 0.0, 10000.0, 27.0, 4754.938750000018, 1008.2012499999995 - 0.0, 10000.0, 27.5, 5092.486718750019, 1070.2757812499976 - 0.0, 10000.0, 28.0, 5434.280000000021, 1137.2799999999963 - 0.0, 10000.0, 28.5, 5779.46328125002, 1209.699218749995 - 0.0, 10000.0, 29.0, 6127.181250000019, 1288.0187499999936 - 0.0, 10000.0, 29.5, 6476.578593750019, 1372.723906249992 - 0.0, 10000.0, 30.0, 6826.80000000002, 1464.2999999999906 - 0.0, 10000.0, 30.5, 7167.937597656241, 1586.586230468753 - 0.0, 10000.0, 31.0, 7509.050781249985, 1714.4898437500026 - 0.0, 10000.0, 31.5, 7850.146386718729, 1846.2719726562518 - 0.0, 10000.0, 32.0, 8191.231249999974, 1980.1937500000006 - 0.0, 10000.0, 32.5, 8532.312207031215, 2114.5163085937493 - 0.0, 10000.0, 33.0, 8873.396093749956, 2247.5007812499966 - 0.0, 10000.0, 33.5, 9214.489746093697, 2377.408300781245 - 0.0, 10000.0, 34.0, 9555.599999999933, 2502.499999999992 - 0.0, 10000.0, 34.5, 9896.944101562352, 2588.015742187481 - 0.0, 10000.0, 35.0, 10238.298437499827, 2668.382812499975 - 0.0, 10000.0, 35.5, 10579.6498046873, 2745.007226562467 - 0.0, 10000.0, 36.0, 10920.984999999773, 2819.2949999999596 - 0.0, 10000.0, 36.5, 11262.290820312239, 2892.6521484374503 - 0.0, 10000.0, 37.0, 11603.55406249971, 2966.484687499939 - 0.0, 10000.0, 37.5, 11944.761523437177, 3042.198632812427 - 0.0, 10000.0, 38.0, 12285.899999999647, 3121.1999999999152 - 0.0, 10000.0, 38.5, 12626.70527343752, 3210.9529296874425 - 0.0, 10000.0, 39.0, 12967.545312500028, 3303.664062499934 - 0.0, 10000.0, 39.5, 13308.46269531254, 3399.3931640624273 - 0.0, 10000.0, 40.0, 13649.50000000006, 3498.1999999999216 - 0.0, 10000.0, 40.5, 13990.93125000004, 3605.571093749989 - 0.0, 10000.0, 41.0, 14332.475000000048, 3713.968749999984 - 0.0, 10000.0, 41.5, 14674.081250000054, 3821.2820312499766 - 0.0, 10000.0, 42.0, 15015.700000000064, 3925.3999999999673 - 0.0, 10000.0, 42.5, 15356.847656249978, 4015.0203124999784 - 0.0, 10000.0, 43.0, 15698.081249999957, 4100.899999999965 - 0.0, 10000.0, 43.5, 16039.524218749933, 4184.604687499949 - 0.0, 10000.0, 44.0, 16381.299999999905, 4267.6999999999325 - 0.0, 10000.0, 44.5, 16724.72734375001, 4354.763281250004 - 0.0, 10000.0, 45.0, 17068.25625000001, 4443.143750000015 - 0.0, 10000.0, 45.5, 17411.532031250015, 4533.202343750028 - 0.0, 10000.0, 46.0, 17754.200000000008, 4625.300000000044 - 0.0, 10000.0, 46.5, 18094.057812500054, 4720.8289062500135 - 0.0, 10000.0, 47.0, 18433.337500000063, 4818.706250000013 - 0.0, 10000.0, 47.5, 18772.423437500067, 4918.880468750014 - 0.0, 10000.0, 48.0, 19111.700000000066, 5021.300000000011 - 0.0, 10000.0, 48.5, 19451.551562500066, 5125.913281250008 - 0.0, 10000.0, 49.0, 19792.36250000007, 5232.668750000006 - 0.0, 10000.0, 49.5, 20134.517187500056, 5341.51484375 - 0.0, 10000.0, 50.0, 20478.400000000045, 5452.399999999995 - 0.0, 15000.0, 0.0, 307.6998259028988, 307.6998259028988 - 0.0, 15000.0, 22.0, -18404.899999999947, -6240.199999999977 - 0.0, 15000.0, 22.5, -21899.50507812494, -7443.827734374982 - 0.0, 15000.0, 23.0, -25357.134374999947, -8590.22812499999 - 0.0, 15000.0, 23.5, -28789.896484374956, -9693.964453125007 - 0.0, 15000.0, 24.0, -32209.89999999998, -10769.600000000028 - 0.0, 15000.0, 24.5, -35629.25351562502, -11831.698046875053 - 0.0, 15000.0, 25.0, -39060.065625000054, -12894.821875000081 - 0.0, 15000.0, 25.5, -42514.444921875096, -13973.534765625105 - 0.0, 15000.0, 26.0, -46004.50000000016, -15082.400000000142 - 0.0, 15000.0, 26.5, -49668.53906250002, -16329.779492187476 - 0.0, 15000.0, 27.0, -53399.682500000075, -17641.797812499957 - 0.0, 15000.0, 27.5, -57188.404687500115, -19016.938476562438 - 0.0, 15000.0, 28.0, -61025.18000000016, -20453.684999999925 - 0.0, 15000.0, 28.5, -64900.482812500224, -21950.52089843739 - 0.0, 15000.0, 29.0, -68804.78750000033, -23505.92968749986 - 0.0, 15000.0, 29.5, -72728.56843750039, -25118.394882812347 - 0.0, 15000.0, 30.0, -76662.30000000047, -26786.399999999816 - 0.0, 15000.0, 30.5, -80497.55312500018, -28659.27089843745 - 0.0, 15000.0, 31.0, -84333.1250000002, -30570.28281249994 - 0.0, 15000.0, 31.5, -88168.9093750002, -32503.553320312418 - 0.0, 15000.0, 32.0, -92004.80000000024, -34443.19999999991 - 0.0, 15000.0, 32.5, -95840.69062500025, -36373.34042968739 - 0.0, 15000.0, 33.0, -99676.47500000028, -38278.092187499875 - 0.0, 15000.0, 33.5, -103512.04687500033, -40141.57285156235 - 0.0, 15000.0, 34.0, -107347.30000000038, -41947.89999999983 - 0.0, 15000.0, 34.5, -111178.30218749968, -43271.54355468732 - 0.0, 15000.0, 35.0, -115009.13749999969, -44545.28281249978 - 0.0, 15000.0, 35.5, -118840.06406249973, -45792.24941406225 - 0.0, 15000.0, 36.0, -122671.3399999998, -47035.57499999971 - 0.0, 15000.0, 36.5, -126503.22343749985, -48298.391210937174 - 0.0, 15000.0, 37.0, -130335.9724999999, -49603.829687499616 - 0.0, 15000.0, 37.5, -134169.84531249997, -50975.02207031209 - 0.0, 15000.0, 38.0, -138005.1000000001, -52435.09999999953 - 0.0, 15000.0, 38.5, -141845.6892578094, -54147.326171874265 - 0.0, 15000.0, 39.0, -145686.26093749626, -55922.040624999165 - 0.0, 15000.0, 39.5, -149526.252148433, -57751.23476562405 - 0.0, 15000.0, 40.0, -153365.09999999474, -59626.89999999895 - 0.0, 15000.0, 40.5, -157200.06484374966, -61502.283593750224 - 0.0, 15000.0, 41.0, -161033.63124999963, -63423.618750000336 - 0.0, 15000.0, 41.5, -164866.1070312497, -65398.39453125046 - 0.0, 15000.0, 42.0, -168697.7999999997, -67434.10000000062 - 0.0, 15000.0, 42.5, -172526.37734374913, -69643.14999999951 - 0.0, 15000.0, 43.0, -176355.84374999886, -71886.13749999939 - 0.0, 15000.0, 43.5, -180187.56328124856, -74128.58124999923 - 0.0, 15000.0, 44.0, -184022.8999999982, -76335.99999999907 - 0.0, 15000.0, 44.5, -187876.409375, -78266.52187500017 - 0.0, 15000.0, 45.0, -191730.98750000013, -80176.01250000026 - 0.0, 15000.0, 45.5, -195582.7218750001, -82112.94687500033 - 0.0, 15000.0, 46.0, -199427.7, -84125.80000000041 - 0.0, 15000.0, 46.5, -203241.4898437507, -86400.30468749945 - 0.0, 15000.0, 47.0, -207048.90625000084, -88792.7749999994 - 0.0, 15000.0, 47.5, -210854.24453125114, -91296.78281249934 - 0.0, 15000.0, 48.0, -214661.80000000139, -93905.89999999931 - 0.0, 15000.0, 48.5, -218475.86796875167, -96613.69843749932 - 0.0, 15000.0, 49.0, -222300.74375000206, -99413.74999999935 - 0.0, 15000.0, 49.5, -226140.7226562526, -102299.62656249941 - 0.0, 15000.0, 50.0, -230000.10000000318, -105264.89999999956 - 0.0, 20000.0, 0.0, 255.50477954477057, 255.50477954477057 - 0.0, 20000.0, 22.0, 886.0999999999364, 130.70000000001386 - 0.0, 20000.0, 22.5, 1079.2511718748754, 574.6564453125048 - 0.0, 20000.0, 23.0, 1264.515624999812, 829.6359374999861 - 0.0, 20000.0, 23.5, 1443.4472656247456, 924.297460937459 - 0.0, 20000.0, 24.0, 1617.599999999673, 887.2999999999219 - 0.0, 20000.0, 24.5, 1788.5277343745927, 747.3025390623766 - 0.0, 20000.0, 25.0, 1957.7843749995025, 532.9640624998224 - 0.0, 20000.0, 25.5, 2126.9238281244006, 272.9435546872594 - 0.0, 20000.0, 26.0, 2297.499999999287, -4.100000000311638 - 0.0, 20000.0, 26.5, 2486.4093749998415, -54.95214843771057 - 0.0, 20000.0, 27.0, 2680.739999999824, -53.249062500236704 - 0.0, 20000.0, 27.5, 2879.415624999805, -7.112695312759058 - 0.0, 20000.0, 28.0, 3081.359999999783, 75.33499999972298 - 0.0, 20000.0, 28.5, 3285.4968749997624, 185.97207031220876 - 0.0, 20000.0, 29.0, 3490.749999999737, 316.6765624996988 - 0.0, 20000.0, 29.5, 3696.0431249997096, 459.326523437192 - 0.0, 20000.0, 30.0, 3900.2999999996778, 605.7999999996912 - 0.0, 20000.0, 30.5, 4085.260058593457, 630.2532226559747 - 0.0, 20000.0, 31.0, 4268.6679687496735, 653.4976562496602 - 0.0, 20000.0, 31.5, 4451.0840820308995, 678.6229492183379 - 0.0, 20000.0, 32.0, 4633.068749999643, 708.7187499995091 - 0.0, 20000.0, 32.5, 4815.182324218399, 746.8747070306731 - 0.0, 20000.0, 33.0, 4997.985156249679, 796.1804687493301 - 0.0, 20000.0, 33.5, 5182.037597655983, 859.725683592981 - 0.0, 20000.0, 34.0, 5367.899999999811, 940.5999999991255 - 0.0, 20000.0, 34.5, 5571.777304683587, 1268.180781248168 - 0.0, 20000.0, 35.0, 5777.095312495407, 1597.718749997795 - 0.0, 20000.0, 35.5, 5982.924414057165, 1910.7523437473706 - 0.0, 20000.0, 36.0, 6188.334999993862, 2188.819999996895 - 0.0, 20000.0, 36.5, 6392.397460930488, 2413.4601562463586 - 0.0, 20000.0, 37.0, 6594.182187492048, 2566.211249995761 - 0.0, 20000.0, 37.5, 6792.759570303529, 2628.611718745098 - 0.0, 20000.0, 38.0, 6987.199999989933, 2582.199999994369 - 0.0, 20000.0, 38.5, 7166.8412109373285, 2145.1896484386452 - 0.0, 20000.0, 39.0, 7345.532812500353, 1698.9828125015752 - 0.0, 20000.0, 39.5, 7524.50800781348, 1283.6345703145685 - 0.0, 20000.0, 40.0, 7705.000000001708, 939.2000000026228 - 0.0, 20000.0, 40.5, 7893.21562499913, 839.4890625006344 - 0.0, 20000.0, 41.0, 8083.424999998693, 837.3000000008176 - 0.0, 20000.0, 41.5, 8274.871874998056, 919.1859375010449 - 0.0, 20000.0, 42.0, 8466.799999997189, 1071.7000000013281 - 0.0, 20000.0, 42.5, 8657.16406249838, 1267.7820312486704 - 0.0, 20000.0, 43.0, 8847.012499998085, 1513.0437499982745 - 0.0, 20000.0, 43.5, 9036.104687497816, 1799.4835937478406 - 0.0, 20000.0, 44.0, 9224.199999997592, 2119.0999999973733 - 0.0, 20000.0, 44.5, 9406.714062499266, 2494.5085937489857 - 0.0, 20000.0, 45.0, 9589.48749999929, 2874.843749998784 - 0.0, 20000.0, 45.5, 9774.017187499403, 3239.857031248522 - 0.0, 20000.0, 46.0, 9961.799999999603, 3569.299999998182 - 0.0, 20000.0, 46.5, 10162.594531248842, 3778.771874999531 - 0.0, 20000.0, 47.0, 10366.331249998659, 3937.837499999435 - 0.0, 20000.0, 47.5, 10571.202343748464, 4051.909374999323 - 0.0, 20000.0, 48.0, 10775.399999998257, 4126.399999999203 - 0.0, 20000.0, 48.5, 10977.116406248044, 4166.721874999079 - 0.0, 20000.0, 49.0, 11174.543749997823, 4178.287499998958 - 0.0, 20000.0, 49.5, 11365.874218747595, 4166.509374998843 - 0.0, 20000.0, 50.0, 11549.29999999736, 4136.799999998742 - 0.0, 25000.0, 0.0, 210.56516088799634, 210.56516088799634 - 0.0, 25000.0, 22.0, 308.1000000000403, 661.0000000000533 - 0.0, 25000.0, 22.5, 396.8693359375318, -145.13105468748137 - 0.0, 25000.0, 23.0, 478.045312500008, -587.4390624999991 - 0.0, 25000.0, 23.5, 552.9236328124703, -723.3525390625031 - 0.0, 25000.0, 24.0, 622.7999999999196, -610.2999999999945 - 0.0, 25000.0, 24.5, 688.9701171873579, -305.7099609374782 - 0.0, 25000.0, 25.0, 752.7296874997866, 132.9890625000478 - 0.0, 25000.0, 25.5, 815.3744140622063, 648.3685546875754 - 0.0, 25000.0, 26.0, 878.1999999996191, 1183.000000000105 - 0.0, 25000.0, 26.5, 954.4882812500601, 1204.269726562663 - 0.0, 25000.0, 27.0, 1034.2337500000335, 1102.7809375002016 - 0.0, 25000.0, 27.5, 1116.6773437499978, 902.5654296877366 - 0.0, 25000.0, 28.0, 1201.0599999999527, 627.6550000002675 - 0.0, 25000.0, 28.5, 1286.6226562498996, 302.0814453127955 - 0.0, 25000.0, 29.0, 1372.6062499998375, -50.12343749967795 - 0.0, 25000.0, 29.5, 1458.251718749769, -404.92785156215814 - 0.0, 25000.0, 30.0, 1542.7999999996925, -738.2999999996382 - 0.0, 25000.0, 30.5, 1613.8653320318554, -687.9957031245525 - 0.0, 25000.0, 31.0, 1683.4226562507988, -600.4062499993988 - 0.0, 25000.0, 31.5, 1751.820214844765, -483.71054687422975 - 0.0, 25000.0, 32.0, 1819.4062500012524, -346.0874999990449 - 0.0, 25000.0, 32.5, 1886.5290039077615, -195.7160156238474 - 0.0, 25000.0, 33.0, 1953.5367187517918, -40.77499999863585 - 0.0, 25000.0, 33.5, 2020.7776367208419, 110.55664062658707 - 0.0, 25000.0, 34.0, 2088.60000000241, 250.100000001823 - 0.0, 25000.0, 34.5, 2164.4251953149555, 42.175429687431006 - 0.0, 25000.0, 35.0, 2240.854687502967, -162.70468750016562 - 0.0, 25000.0, 35.5, 2317.5630859410135, -341.5287109377814 - 0.0, 25000.0, 36.0, 2394.225000004093, -471.2850000004164 - 0.0, 25000.0, 36.5, 2470.5150390672034, -528.9619140630621 - 0.0, 25000.0, 37.0, 2546.107812505342, -491.54781250072756 - 0.0, 25000.0, 37.5, 2620.6779296935038, -336.0310546884066 - 0.0, 25000.0, 38.0, 2693.900000006691, -39.400000001098306 - 0.0, 25000.0, 38.5, 2757.8285156246534, 947.4066406270667 - 0.0, 25000.0, 39.0, 2823.7093749992164, 1848.584375002376 - 0.0, 25000.0, 39.5, 2892.9105468737603, 2570.244921877722 - 0.0, 25000.0, 40.0, 2966.7999999983035, 3018.5000000030923 - 0.0, 25000.0, 40.5, 3058.9859375022147, 2601.3734375012127 - 0.0, 25000.0, 41.0, 3153.7000000030116, 1922.3000000016416 - 0.0, 25000.0, 41.5, 3247.4140625040022, 1086.626562502132 - 0.0, 25000.0, 42.0, 3336.600000005194, 199.70000000267828 - 0.0, 25000.0, 42.5, 3397.44453125262, -416.0117187504279 - 0.0, 25000.0, 43.0, 3454.818750003794, -959.1312500004548 - 0.0, 25000.0, 43.5, 3513.3085937551145, -1411.1601562504845 - 0.0, 25000.0, 44.0, 3577.500000006562, -1753.6000000005222 - 0.0, 25000.0, 44.5, 3678.123437500981, -1852.460156248066 - 0.0, 25000.0, 45.0, 3783.162500001884, -1850.931249997359 - 0.0, 25000.0, 45.5, 3886.745312503042, -1776.7117187465435 - 0.0, 25000.0, 46.0, 3983.000000004478, -1657.4999999956176 - 0.0, 25000.0, 46.5, 4038.3789062523947, -1683.5374999982305 - 0.0, 25000.0, 47.0, 4085.756250002798, -1654.9624999976004 - 0.0, 25000.0, 47.5, 4130.3304687531645, -1534.4562499968517 - 0.0, 25000.0, 48.0, 4177.30000000349, -1284.6999999959744 - 0.0, 25000.0, 48.5, 4231.863281253773, -868.3749999949619 - 0.0, 25000.0, 49.0, 4299.218750004009, -248.16249999380534 - 0.0, 25000.0, 49.5, 4384.5648437541995, 613.2562500074991 - 0.0, 25000.0, 50.0, 4493.100000004338, 1753.200000008963 - 0.0, 30000.0, 0.0, 172.11235526591872, 172.11235526591872 - 0.0, 30000.0, 22.0, -319.39999999999253, -160.20000000008247 - 0.0, 30000.0, 22.5, -390.61542968745164, 123.01093749996038 - 0.0, 30000.0, 23.0, -457.13906249990765, 204.72500000001045 - 0.0, 30000.0, 23.5, -519.6181640623562, 120.77656250007006 - 0.0, 30000.0, 24.0, -578.6999999997926, -92.99999999985926 - 0.0, 30000.0, 24.5, -635.0318359372131, -400.7703124997752 - 0.0, 30000.0, 25.0, -689.2609374996129, -766.6999999996755 - 0.0, 30000.0, 25.5, -742.0345703119877, -1154.9546874995576 - 0.0, 30000.0, 26.0, -793.9999999993331, -1529.6999999994205 - 0.0, 30000.0, 26.5, -849.3058593751852, -1500.5980468751295 - 0.0, 30000.0, 27.0, -905.2981250002616, -1366.0606250001415 - 0.0, 30000.0, 27.5, -962.0238281253617, -1151.0253906251535 - 0.0, 30000.0, 28.0, -1019.5300000004889, -880.4300000001679 - 0.0, 30000.0, 28.5, -1077.8636718756482, -579.2121093751823 - 0.0, 30000.0, 29.0, -1137.0718750008439, -272.30937500019854 - 0.0, 30000.0, 29.5, -1197.2016406260796, 15.34054687478465 - 0.0, 30000.0, 30.0, -1258.3000000013594, 258.799999999771 - 0.0, 30000.0, 30.5, -1322.8273437498785, 35.35400390609516 - 0.0, 30000.0, 31.0, -1388.187499999906, -244.27421875013283 - 0.0, 30000.0, 31.5, -1454.197656249943, -567.1387695313597 - 0.0, 30000.0, 32.0, -1520.674999999988, -920.2937500000912 - 0.0, 30000.0, 32.5, -1587.4367187500409, -1290.7932617188276 - 0.0, 30000.0, 33.0, -1654.3000000001011, -1665.6914062500646 - 0.0, 30000.0, 33.5, -1721.0820312501696, -2032.0422851563071 - 0.0, 30000.0, 34.0, -1787.6000000002446, -2376.9000000000606 - 0.0, 30000.0, 34.5, -1844.0488281246323, -2567.318007812309 - 0.0, 30000.0, 35.0, -1900.784374999607, -2721.7796874997007 - 0.0, 30000.0, 35.5, -1958.5402343745986, -2838.7677734370754 - 0.0, 30000.0, 36.0, -2018.049999999609, -2916.764999999429 - 0.0, 30000.0, 36.5, -2080.047265624643, -2954.2541015617635 - 0.0, 30000.0, 37.0, -2145.265624999704, -2949.7178124990764 - 0.0, 30000.0, 37.5, -2214.4386718747955, -2901.638867186367 - 0.0, 30000.0, 38.0, -2288.299999999922, -2808.4999999986335 - 0.0, 30000.0, 38.5, -2386.293359386994, -2510.6947265641024 - 0.0, 30000.0, 39.0, -2480.7406250142276, -2246.7671875020314 - 0.0, 30000.0, 39.5, -2568.217578141748, -2050.331054690014 - 0.0, 30000.0, 40.0, -2645.3000000195852, -1955.0000000030477 - 0.0, 30000.0, 40.5, -2686.3351562517278, -2152.4921875011314 - 0.0, 30000.0, 41.0, -2719.018750002438, -2455.0750000014996 - 0.0, 30000.0, 41.5, -2748.8179687532856, -2833.1203125019356 - 0.0, 30000.0, 42.0, -2781.200000004277, -3257.0000000024456 - 0.0, 30000.0, 42.5, -2837.6203125016295, -3905.6562499999104 - 0.0, 30000.0, 43.0, -2901.162500002127, -4457.462499999814 - 0.0, 30000.0, 43.5, -2970.8984375026685, -4799.362499999717 - 0.0, 30000.0, 44.0, -3045.900000003241, -4818.299999999632 - 0.0, 30000.0, 44.5, -3127.446093751279, -3623.253906250151 - 0.0, 30000.0, 45.0, -3211.5187500013635, -2190.3187499999635 - 0.0, 30000.0, 45.5, -3296.3070312514583, -717.6242187496573 - 0.0, 30000.0, 46.0, -3380.0000000015752, 596.7000000007756 - 0.0, 30000.0, 46.5, -3457.575781250796, 1003.3328124999867 - 0.0, 30000.0, 47.0, -3531.718750000826, 1075.812499999777 - 0.0, 30000.0, 47.5, -3601.9023437508795, 836.4859374994999 - 0.0, 30000.0, 48.0, -3667.600000000949, 307.6999999991575 - 0.0, 30000.0, 48.5, -3728.2851562510336, -488.1984375012437 - 0.0, 30000.0, 49.0, -3783.4312500011265, -1528.8625000017137 - 0.0, 30000.0, 49.5, -3832.511718751223, -2791.9453125022437 - 0.0, 30000.0, 50.0, -3875.0000000013206, -4255.100000002849 - 0.0, 35000.0, 0.0, 139.43057451782246, 139.43057451782246 - 0.0, 35000.0, 22.0, 1045.7999999999993, -150.899999999979 - 0.0, 35000.0, 22.5, 1291.8726562500399, -241.67656249993257 - 0.0, 35000.0, 23.0, 1523.6937500000422, -198.99999999990328 - 0.0, 35000.0, 23.5, 1743.4179687500098, -48.49843749989012 - 0.0, 35000.0, 24.0, 1953.1999999999457, 184.20000000010785 - 0.0, 35000.0, 24.5, 2155.194531249853, 473.4671875000921 - 0.0, 35000.0, 25.0, 2351.5562499997354, 793.6750000000627 - 0.0, 35000.0, 25.5, 2544.4398437495947, 1119.1953125000214 - 0.0, 35000.0, 26.0, 2735.9999999994357, 1424.399999999969 - 0.0, 35000.0, 26.5, 2942.4966796871076, 1414.0337890627125 - 0.0, 35000.0, 27.0, 3152.785312499555, 1316.688437500223 - 0.0, 35000.0, 27.5, 3366.602539062007, 1152.957617187733 - 0.0, 35000.0, 28.0, 3583.684999999461, 943.4350000002457 - 0.0, 35000.0, 28.5, 3803.769335936916, 708.7142578127593 - 0.0, 35000.0, 29.0, 4026.5921874993737, 469.3890625002764 - 0.0, 35000.0, 29.5, 4251.89019531183, 246.0530859377982 - 0.0, 35000.0, 30.0, 4479.3999999992875, 59.300000000326236 - 0.0, 35000.0, 30.5, 4711.020996094387, 333.0313476554004 - 0.0, 35000.0, 31.0, 4944.121093750742, 646.1226562490424 - 0.0, 35000.0, 31.5, 5178.230957032103, 980.7573242176891 - 0.0, 35000.0, 32.0, 5412.8812500009635, 1319.1187499988405 - 0.0, 35000.0, 32.5, 5647.602636719829, 1643.3903320299978 - 0.0, 35000.0, 33.0, 5881.925781251198, 1935.7554687486654 - 0.0, 35000.0, 33.5, 6115.381347657567, 2178.3975585923417 - 0.0, 35000.0, 34.0, 6347.500000001437, 2353.499999998525 - 0.0, 35000.0, 34.5, 6554.732500003433, 1960.2589062500927 - 0.0, 35000.0, 35.0, 6761.8875000037815, 1509.8437500001332 - 0.0, 35000.0, 35.5, 6970.6937500041195, 1030.436718750168 - 0.0, 35000.0, 36.0, 7182.880000004439, 550.2200000002058 - 0.0, 35000.0, 36.5, 7400.175000004741, 97.37578125024265 - 0.0, 35000.0, 37.0, 7624.30750000502, -299.9137499997287 - 0.0, 35000.0, 37.5, 7857.006250005283, -613.4664062497013 - 0.0, 35000.0, 38.0, 8100.000000005519, -815.0999999996766 - 0.0, 35000.0, 38.5, 8387.582031251623, -1110.1886718760334 - 0.0, 35000.0, 39.0, 8672.03125000192, -1115.8906250014024 - 0.0, 35000.0, 39.5, 8947.839843752276, -752.1222656268455 - 0.0, 35000.0, 40.0, 9209.500000002687, 61.19999999765787 - 0.0, 35000.0, 40.5, 9419.10156250299, 2251.1929687490265 - 0.0, 35000.0, 41.0, 9616.500000004226, 4712.093749998573 - 0.0, 35000.0, 41.5, 9809.14843750567, 7185.172656248038 - 0.0, 35000.0, 42.0, 10004.500000007329, 9411.699999997409 - 0.0, 35000.0, 42.5, 10241.273437500324, 10589.707812498613 - 0.0, 35000.0, 43.0, 10483.149999999509, 11220.999999998046 - 0.0, 35000.0, 43.5, 10725.076562498316, 11264.142187497353 - 0.0, 35000.0, 44.0, 10961.999999996697, 10677.699999996523 - 0.0, 35000.0, 44.5, 11161.289062500337, 8495.278125000741 - 0.0, 35000.0, 45.0, 11356.500000000673, 5970.387500001042 - 0.0, 35000.0, 45.5, 11553.610937501146, 3431.5781250014224 - 0.0, 35000.0, 46.0, 11758.600000001763, 1207.4000000019114 - 0.0, 35000.0, 46.5, 12006.273437499807, 800.1960937488047 - 0.0, 35000.0, 47.0, 12262.250000000111, 895.2062499984636 - 0.0, 35000.0, 47.5, 12520.976562500568, 1351.4632812480359 - 0.0, 35000.0, 48.0, 12776.900000001177, 2027.9999999975262 - 0.0, 35000.0, 48.5, 13024.467187501934, 2783.8492187468983 - 0.0, 35000.0, 49.0, 13258.125000002847, 3478.043749996141 - 0.0, 35000.0, 49.5, 13472.320312503922, 3969.616406245248 - 0.0, 35000.0, 50.0, 13661.500000005164, 4117.599999994203 - 0.0, 39000.0, 0.0, 115.64521062185423, 115.64521062185423 - 0.0, 39000.0, 22.0, 684.7000000000178, -524.1999999999624 - 0.0, 39000.0, 22.5, 862.0837890624756, -808.2701171874858 - 0.0, 39000.0, 23.0, 1022.4671874999307, -851.8140625000073 - 0.0, 39000.0, 23.5, 1168.8919921873812, -697.3009765625293 - 0.0, 39000.0, 24.0, 1304.3999999998257, -387.2000000000538 - 0.0, 39000.0, 24.5, 1432.0330078122618, 36.019726562417986 - 0.0, 39000.0, 25.0, 1554.8328124996888, 529.8890624998837 - 0.0, 39000.0, 25.5, 1675.8412109371038, 1051.9388671873405 - 0.0, 39000.0, 26.0, 1798.0999999995065, 1559.6999999997888 - 0.0, 39000.0, 26.5, 1953.022851562409, 1641.3193359375648 - 0.0, 39000.0, 27.0, 2116.900937499887, 1602.604062500085 - 0.0, 39000.0, 27.5, 2287.912304687366, 1464.4080078126126 - 0.0, 39000.0, 28.0, 2464.2349999998473, 1247.5850000001476 - 0.0, 39000.0, 28.5, 2644.0470703123333, 972.9888671876944 - 0.0, 39000.0, 29.0, 2825.5265624998246, 661.4734375002499 - 0.0, 39000.0, 29.5, 3006.8515234373244, 333.89253906281374 - 0.0, 39000.0, 30.0, 3186.1999999998334, 11.100000000390537 - 0.0, 39000.0, 30.5, 3333.581738281381, -24.871875000494015 - 0.0, 39000.0, 31.0, 3478.025781250212, -39.221875000603404 - 0.0, 39000.0, 31.5, 3620.3928710940577, -35.970312500726095 - 0.0, 39000.0, 32.0, 3761.5437500004186, -19.137500000862474 - 0.0, 39000.0, 32.5, 3902.339160156794, 7.256249998987187 - 0.0, 39000.0, 33.0, 4043.6398437506864, 39.19062499882284 - 0.0, 39000.0, 33.5, 4186.3065429695935, 72.64531249864513 - 0.0, 39000.0, 34.0, 4331.200000001018, 103.59999999845058 - 0.0, 39000.0, 34.5, 4504.342812499881, 216.2778515619416 - 0.0, 39000.0, 35.0, 4679.037499999793, 310.0109374993285 - 0.0, 39000.0, 35.5, 4853.74843749967, 372.3748046867063 - 0.0, 39000.0, 36.0, 5026.939999999514, 390.94499999907384 - 0.0, 39000.0, 36.5, 5197.076562499316, 353.297070311432 - 0.0, 39000.0, 37.0, 5362.622499999074, 247.00656249878193 - 0.0, 39000.0, 37.5, 5522.042187498782, 59.64902343612084 - 0.0, 39000.0, 38.0, 5673.7999999984395, -221.20000000154687 - 0.0, 39000.0, 38.5, 5791.4886718766165, -1036.1216796859808 - 0.0, 39000.0, 39.0, 5911.3406250019625, -1747.3765624981916 - 0.0, 39000.0, 39.5, 6037.347265627368, -2272.243164060348 - 0.0, 39000.0, 40.0, 6173.500000002847, -2527.9999999974425 - 0.0, 39000.0, 40.5, 6345.096875000336, -2174.5085937500753 - 0.0, 39000.0, 41.0, 6526.300000000065, -1489.4312499999746 - 0.0, 39000.0, 41.5, 6712.578124999761, -493.0132812498242 - 0.0, 39000.0, 42.0, 6899.399999999447, 794.5000000003838 - 0.0, 39000.0, 42.5, 7054.800781250944, 2709.546875000764 - 0.0, 39000.0, 43.0, 7212.656250001675, 4732.525000000905 - 0.0, 39000.0, 43.5, 7379.40859375241, 6700.51562500103 - 0.0, 39000.0, 44.0, 7561.500000003079, 8450.60000000113 - 0.0, 39000.0, 44.5, 7829.314062500506, 9582.589843749065 - 0.0, 39000.0, 45.0, 8099.775000001174, 10265.743749998906 - 0.0, 39000.0, 45.5, 8353.74843750216, 10432.050781248803 - 0.0, 39000.0, 46.0, 8572.100000003542, 10013.499999998741 - 0.0, 39000.0, 46.5, 8627.03515625021, 8156.873437499312 - 0.0, 39000.0, 47.0, 8651.543749999943, 5893.4499999986765 - 0.0, 39000.0, 47.5, 8669.955468749558, 3469.30156249788 - 0.0, 39000.0, 48.0, 8706.599999999025, 1130.499999996915 - 0.0, 39000.0, 48.5, 8785.807031248312, -876.88281250422 - 0.0, 39000.0, 49.0, 8931.906249997392, -2306.7750000055457 - 0.0, 39000.0, 49.5, 9169.227343746234, -2913.1046875070533 - 0.0, 39000.0, 50.0, 9522.099999994804, -2449.800000008756 - 0.0, 43000.0, 0.0, 95.41869532410733, 95.41869532410733 - 0.0, 43000.0, 22.0, -1065.5000000000264, 1347.4999999999918 - 0.0, 43000.0, 22.5, -1181.1349609376582, 459.6195312499154 - 0.0, 43000.0, 23.0, -1304.082812500297, -276.50625000012724 - 0.0, 43000.0, 23.5, -1434.2392578129513, -880.8539062501445 - 0.0, 43000.0, 24.0, -1571.5000000006285, -1373.4000000001463 - 0.0, 43000.0, 24.5, -1715.7607421883376, -1774.1210937501407 - 0.0, 43000.0, 25.0, -1866.9171875010852, -2102.9937500001374 - 0.0, 43000.0, 25.5, -2024.8650390638802, -2379.9945312501463 - 0.0, 43000.0, 26.0, -2189.5000000017303, -2625.1000000001745 - 0.0, 43000.0, 26.5, -2365.7476562501174, -3077.6820312503482 - 0.0, 43000.0, 27.0, -2548.7612500001073, -3550.8587500004087 - 0.0, 43000.0, 27.5, -2737.574218750077, -4026.9960937504698 - 0.0, 43000.0, 28.0, -2931.220000000022, -4488.460000000526 - 0.0, 43000.0, 28.5, -3128.7320312499382, -4917.616406250575 - 0.0, 43000.0, 29.0, -3329.143749999823, -5296.831250000612 - 0.0, 43000.0, 29.5, -3531.488593749672, -5608.470468750632 - 0.0, 43000.0, 30.0, -3734.7999999994813, -5834.900000000631 - 0.0, 43000.0, 30.5, -3930.7187499999022, -5752.824414063477 - 0.0, 43000.0, 31.0, -4126.374999999936, -5569.857812501158 - 0.0, 43000.0, 31.5, -4321.5062499999685, -5287.952929688851 - 0.0, 43000.0, 32.0, -4515.849999999998, -4909.062500001554 - 0.0, 43000.0, 32.5, -4709.143750000024, -4435.139257814269 - 0.0, 43000.0, 33.0, -4901.125000000045, -3868.1359375019942 - 0.0, 43000.0, 33.5, -5091.531250000058, -3210.005273439735 - 0.0, 43000.0, 34.0, -5280.100000000062, -2462.7000000024823 - 0.0, 43000.0, 34.5, -5443.990468752586, -345.78898437594216 - 0.0, 43000.0, 35.0, -5607.668750003152, 1734.2593749988355 - 0.0, 43000.0, 35.5, -5773.022656253821, 3653.3605468736096 - 0.0, 43000.0, 36.0, -5941.940000004605, 5287.42999999836 - 0.0, 43000.0, 36.5, -6116.308593755519, 6512.383203123056 - 0.0, 43000.0, 37.0, -6298.0162500065735, 7204.13562499774 - 0.0, 43000.0, 37.5, -6488.950781257781, 7238.602734372391 - 0.0, 43000.0, 38.0, -6691.000000009155, 6491.699999997014 - 0.0, 43000.0, 38.5, -6952.888281247559, 3295.3605468774203 - 0.0, 43000.0, 39.0, -7205.381249996846, -129.93437499671927 - 0.0, 43000.0, 39.5, -7439.958593746023, -3565.1621093707654 - 0.0, 43000.0, 40.0, -7648.099999995086, -6791.299999994677 - 0.0, 43000.0, 40.5, -7754.101562499583, -9171.643750001485 - 0.0, 43000.0, 41.0, -7843.499999999681, -11071.925000001824 - 0.0, 43000.0, 41.5, -7934.648437499773, -12440.193750002241 - 0.0, 43000.0, 42.0, -8045.899999999843, -13224.500000002734 - 0.0, 43000.0, 42.5, -8284.3539062523, -12790.909375002546 - 0.0, 43000.0, 43.0, -8544.118750002854, -11902.250000003638 - 0.0, 43000.0, 43.5, -8808.049218753624, -10739.365625004886 - 0.0, 43000.0, 44.0, -9059.000000004693, -9483.100000006243 - 0.0, 43000.0, 44.5, -9199.26328125211, -8634.273437499596 - 0.0, 43000.0, 45.0, -9324.481250002907, -7925.762499999429 - 0.0, 43000.0, 45.5, -9449.733593753668, -7410.420312499259 - 0.0, 43000.0, 46.0, -9590.100000004299, -7141.099999999111 - 0.0, 43000.0, 46.5, -9826.433593754733, -7604.725000002919 - 0.0, 43000.0, 47.0, -10081.731250006405, -8246.45000000346 - 0.0, 43000.0, 47.5, -10344.763281258416, -8945.500000004044 - 0.0, 43000.0, 48.0, -10604.30000001082, -9581.100000004668 - 0.0, 43000.0, 48.5, -10849.111718763674, -10032.475000005337 - 0.0, 43000.0, 49.0, -11067.968750017033, -10178.850000006052 - 0.0, 43000.0, 49.5, -11249.641406270957, -9899.450000006822 - 0.0, 43000.0, 50.0, -11382.900000025504, -9073.50000000765 - 0.0, 48000.0, 0.0, 75.03536334593275, 75.03536334593275 - 0.0, 48000.0, 22.0, -967.1000000000374, 1138.9999999998654 - 0.0, 48000.0, 22.5, -990.8191406250248, 419.2253906248594 - 0.0, 48000.0, 23.0, -1044.821874999993, -168.09062500015278 - 0.0, 48000.0, 23.5, -1125.313671874942, -641.2113281251723 - 0.0, 48000.0, 24.0, -1228.499999999874, -1018.4000000001992 - 0.0, 48000.0, 24.5, -1350.5863281247878, -1317.9199218752356 - 0.0, 48000.0, 25.0, -1487.7781249996865, -1558.0343750002799 - 0.0, 48000.0, 25.5, -1636.2808593745701, -1757.0066406253345 - 0.0, 48000.0, 26.0, -1792.299999999439, -1933.1000000004015 - 0.0, 48000.0, 26.5, -1925.2031250001874, -2304.207617187643 - 0.0, 48000.0, 27.0, -2056.5000000001755, -2700.370312500165 - 0.0, 48000.0, 27.5, -2186.9968750001544, -3105.629101562683 - 0.0, 48000.0, 28.0, -2317.5000000001223, -3504.025000000198 - 0.0, 48000.0, 28.5, -2448.8156250000816, -3879.599023437707 - 0.0, 48000.0, 29.0, -2581.7500000000323, -4216.392187500209 - 0.0, 48000.0, 29.5, -2717.109374999973, -4498.445507812705 - 0.0, 48000.0, 30.0, -2855.6999999999084, -4709.800000000188 - 0.0, 48000.0, 30.5, -3015.997656250574, -4639.29716796954 - 0.0, 48000.0, 31.0, -3179.4562500007073, -4484.767968750963 - 0.0, 48000.0, 31.5, -3345.199218750855, -4248.843847657403 - 0.0, 48000.0, 32.0, -3512.3500000010167, -3934.1562500013665 - 0.0, 48000.0, 32.5, -3680.032031251192, -3543.3366210953527 - 0.0, 48000.0, 33.0, -3847.368750001383, -3079.016406251867 - 0.0, 48000.0, 33.5, -4013.483593751587, -2543.8270507833986 - 0.0, 48000.0, 34.0, -4177.500000001806, -1940.4000000024598 - 0.0, 48000.0, 34.5, -4306.690312500881, -290.7770312511275 - 0.0, 48000.0, 35.0, -4435.062500000975, 1328.43124999863 - 0.0, 48000.0, 35.5, -4564.773437501079, 2821.203906248362 - 0.0, 48000.0, 36.0, -4697.9800000011965, 4091.519999998036 - 0.0, 48000.0, 36.5, -4836.83906250133, 5043.358593747675 - 0.0, 48000.0, 37.0, -4983.507500001484, 5580.698749997238 - 0.0, 48000.0, 37.5, -5140.142187501663, 5607.519531246748 - 0.0, 48000.0, 38.0, -5308.900000001871, 5027.799999996205 - 0.0, 48000.0, 38.5, -5550.173437494491, 2554.338281248858 - 0.0, 48000.0, 39.0, -5777.6874999934, -100.05625000117288 - 0.0, 48000.0, 39.5, -5980.657812492154, -2766.6976562511772 - 0.0, 48000.0, 40.0, -6148.299999990737, -5276.900000001093 - 0.0, 48000.0, 40.5, -6180.44687500117, -7148.87968750121 - 0.0, 48000.0, 41.0, -6191.450000001457, -8652.28750000151 - 0.0, 48000.0, 41.5, -6206.278125001768, -9743.676562501827 - 0.0, 48000.0, 42.0, -6249.900000002106, -10379.600000002169 - 0.0, 48000.0, 42.5, -6462.0656250008615, -10058.216406248917 - 0.0, 48000.0, 43.0, -6707.050000001043, -9377.831249998722 - 0.0, 48000.0, 43.5, -6963.909375001241, -8478.355468748578 - 0.0, 48000.0, 44.0, -7211.700000001467, -7499.699999998509 - 0.0, 48000.0, 44.5, -7351.790624999468, -6818.939843751966 - 0.0, 48000.0, 45.0, -7471.999999999247, -6243.956250002508 - 0.0, 48000.0, 45.5, -7582.459374999, -5819.7945312530865 - 0.0, 48000.0, 46.0, -7693.299999998728, -5591.500000003692 - 0.0, 48000.0, 46.5, -7846.117968749787, -5963.059374999187 - 0.0, 48000.0, 47.0, -8006.993750000006, -6476.99999999904 - 0.0, 48000.0, 47.5, -8173.472656250189, -7034.790624998862 - 0.0, 48000.0, 48.0, -8343.100000000297, -7537.899999998641 - 0.0, 48000.0, 48.5, -8513.421093750303, -7887.796874998368 - 0.0, 48000.0, 49.0, -8681.981250000164, -7985.949999998016 - 0.0, 48000.0, 49.5, -8846.325781249854, -7733.828124997599 - 0.0, 48000.0, 50.0, -9003.999999999332, -7032.899999997084 - 0.05, 0.0, 0.0, 517.1288806794237, 517.1288806794237 - 0.05, 0.0, 22.0, 1838.0700000000004, 769.5800000000004 - 0.05, 0.0, 22.5, 2186.899511718751, 844.2204882812505 - 0.05, 0.0, 23.0, 2532.125156250001, 918.3823437500004 - 0.05, 0.0, 23.5, 2874.945722656252, 992.4405273437505 - 0.05, 0.0, 24.0, 3216.5600000000018, 1066.7700000000007 - 0.05, 0.0, 24.5, 3558.1667773437516, 1141.7457226562503 - 0.05, 0.0, 25.0, 3900.9648437500005, 1217.742656250001 - 0.05, 0.0, 25.5, 4246.152988281251, 1295.1357617187507 - 0.05, 0.0, 26.0, 4594.929999999999, 1374.3000000000006 - 0.05, 0.0, 26.5, 4961.075937500004, 1458.6662695312502 - 0.05, 0.0, 27.0, 5333.9272500000025, 1545.72821875 - 0.05, 0.0, 27.5, 5712.525937500003, 1635.3369335937498 - 0.05, 0.0, 28.0, 6095.914000000002, 1727.3434999999997 - 0.05, 0.0, 28.5, 6483.1334375000015, 1821.5990039062497 - 0.05, 0.0, 29.0, 6873.226249999998, 1917.9545312499997 - 0.05, 0.0, 29.5, 7265.234437499999, 2016.2611679687489 - 0.05, 0.0, 30.0, 7658.199999999998, 2116.369999999999 - 0.05, 0.0, 30.5, 8041.1047070312525, 2217.6330761718777 - 0.05, 0.0, 31.0, 8424.008906250001, 2320.448046875002 - 0.05, 0.0, 31.5, 8806.912714843755, 2424.7135253906267 - 0.05, 0.0, 32.0, 9189.816250000005, 2530.3281250000023 - 0.05, 0.0, 32.5, 9572.719628906258, 2637.1904589843775 - 0.05, 0.0, 33.0, 9955.622968750004, 2745.1991406250027 - 0.05, 0.0, 33.5, 10338.52638671876, 2854.252783203128 - 0.05, 0.0, 34.0, 10721.430000000008, 2964.2500000000036 - 0.05, 0.0, 34.5, 11104.330726562512, 3075.1760703124996 - 0.05, 0.0, 35.0, 11487.232187500014, 3186.8346874999997 - 0.05, 0.0, 35.5, 11870.13480468751, 3299.1162109375 - 0.05, 0.0, 36.0, 12253.03900000001, 3411.9110000000005 - 0.05, 0.0, 36.5, 12635.945195312506, 3525.1094140625 - 0.05, 0.0, 37.0, 13018.853812500007, 3638.6018125 - 0.05, 0.0, 37.5, 13401.765273437508, 3752.2785546875007 - 0.05, 0.0, 38.0, 13784.680000000004, 3866.0300000000007 - 0.05, 0.0, 38.5, 14167.604003906205, 3979.6744726562483 - 0.05, 0.0, 39.0, 14550.529218749942, 4093.211718749997 - 0.05, 0.0, 39.5, 14933.454824218677, 4206.548105468744 - 0.05, 0.0, 40.0, 15316.379999999908, 4319.589999999993 - 0.05, 0.0, 40.5, 15699.306171875005, 4431.821015625 - 0.05, 0.0, 41.0, 16082.22937500001, 4543.739375 - 0.05, 0.0, 41.5, 16465.14789062501, 4655.420546875 - 0.05, 0.0, 42.0, 16848.060000000016, 4766.939999999999 - 0.05, 0.0, 42.5, 17230.655390624994, 4878.4165625000105 - 0.05, 0.0, 43.0, 17613.364374999994, 4989.865000000015 - 0.05, 0.0, 43.5, 17996.308671874987, 5101.343437500021 - 0.05, 0.0, 44.0, 18379.60999999998, 5212.910000000025 - 0.05, 0.0, 44.5, 18764.58617187503, 5325.122812500011 - 0.05, 0.0, 45.0, 19149.684375000037, 5437.340000000014 - 0.05, 0.0, 45.5, 19534.54789062505, 5549.419687500016 - 0.05, 0.0, 46.0, 19918.820000000072, 5661.220000000022 - 0.05, 0.0, 46.5, 20300.364296875046, 5771.525624999999 - 0.05, 0.0, 47.0, 20681.315625000057, 5881.6975 - 0.05, 0.0, 47.5, 21062.029140625076, 5992.023124999998 - 0.05, 0.0, 48.0, 21442.8600000001, 6102.789999999996 - 0.05, 0.0, 48.5, 21824.163359375118, 6214.285624999997 - 0.05, 0.0, 49.0, 22206.294375000147, 6326.797499999992 - 0.05, 0.0, 49.5, 22589.60820312518, 6440.613124999993 - 0.05, 0.0, 50.0, 22974.460000000206, 6556.019999999988 - 0.05, 2000.0, 0.0, 484.17212846664245, 484.17212846664245 - 0.05, 2000.0, 22.0, 1788.2600000000002, 733.0300000000002 - 0.05, 2000.0, 22.5, 2127.650507812499, 806.0506835937501 - 0.05, 2000.0, 23.0, 2463.5459375, 878.3695312500005 - 0.05, 2000.0, 23.5, 2797.1108984374996, 950.3961132812506 - 0.05, 2000.0, 24.0, 3129.5099999999984, 1022.5400000000008 - 0.05, 2000.0, 24.5, 3461.9078515624974, 1095.2107617187505 - 0.05, 2000.0, 25.0, 3795.4690624999957, 1168.817968750001 - 0.05, 2000.0, 25.5, 4131.3582421874935, 1243.7711914062515 - 0.05, 2000.0, 26.0, 4470.7399999999925, 1320.480000000002 - 0.05, 2000.0, 26.5, 4827.006523437505, 1402.6427343750017 - 0.05, 2000.0, 27.0, 5189.793562500005, 1487.5681250000016 - 0.05, 2000.0, 27.5, 5558.169570312505, 1575.101953125002 - 0.05, 2000.0, 28.0, 5931.203000000007, 1665.0900000000026 - 0.05, 2000.0, 28.5, 6307.962304687508, 1757.3780468750035 - 0.05, 2000.0, 29.0, 6687.515937500007, 1851.811875000004 - 0.05, 2000.0, 29.5, 7068.93235156251, 1948.2372656250043 - 0.05, 2000.0, 30.0, 7451.280000000009, 2046.5000000000048 - 0.05, 2000.0, 30.5, 7823.845273437516, 2146.261699218752 - 0.05, 2000.0, 31.0, 8196.41031250002, 2247.5698437500023 - 0.05, 2000.0, 31.5, 8568.975195312523, 2350.2877539062533 - 0.05, 2000.0, 32.0, 8941.540000000025, 2454.278750000004 - 0.05, 2000.0, 32.5, 9314.10480468753, 2559.406152343755 - 0.05, 2000.0, 33.0, 9686.66968750003, 2665.5332812500055 - 0.05, 2000.0, 33.5, 10059.234726562534, 2772.523457031256 - 0.05, 2000.0, 34.0, 10431.800000000037, 2880.2400000000075 - 0.05, 2000.0, 34.5, 10804.368210937522, 2987.655945312503 - 0.05, 2000.0, 35.0, 11176.936562500026, 3095.609687500002 - 0.05, 2000.0, 35.5, 11549.504882812533, 3204.049335937504 - 0.05, 2000.0, 36.0, 11922.073000000037, 3312.923000000005 - 0.05, 2000.0, 36.5, 12294.640742187541, 3422.178789062506 - 0.05, 2000.0, 37.0, 12667.207937500049, 3531.764812500007 - 0.05, 2000.0, 37.5, 13039.774414062555, 3641.629179687508 - 0.05, 2000.0, 38.0, 13412.340000000064, 3751.720000000009 - 0.05, 2000.0, 38.5, 13784.90462890618, 3862.955273437496 - 0.05, 2000.0, 39.0, 14157.467968749914, 3973.810312499994 - 0.05, 2000.0, 39.5, 14530.029824218642, 4084.0176953124915 - 0.05, 2000.0, 40.0, 14902.58999999987, 4193.3099999999895 - 0.05, 2000.0, 40.5, 15275.148593750026, 4299.40671875 - 0.05, 2000.0, 41.0, 15647.705000000033, 4404.858749999999 - 0.05, 2000.0, 41.5, 16020.25890625004, 4510.203906250002 - 0.05, 2000.0, 42.0, 16392.810000000045, 4615.980000000003 - 0.05, 2000.0, 42.5, 16765.05484375, 4725.208828125008 - 0.05, 2000.0, 43.0, 17137.4175, 4834.950625000014 - 0.05, 2000.0, 43.5, 17510.018906250007, 4944.749609375015 - 0.05, 2000.0, 44.0, 17882.980000000007, 5054.150000000021 - 0.05, 2000.0, 44.5, 18257.61742187504, 5160.726093750002 - 0.05, 2000.0, 45.0, 18632.37812500005, 5266.780000000003 - 0.05, 2000.0, 45.5, 19006.904765625066, 5372.643906250003 - 0.05, 2000.0, 46.0, 19380.84000000008, 5478.650000000003 - 0.05, 2000.0, 46.5, 19752.043671875, 5585.821484375003 - 0.05, 2000.0, 47.0, 20122.654375, 5693.523125000006 - 0.05, 2000.0, 47.5, 20493.027890625, 5801.810703125008 - 0.05, 2000.0, 48.0, 20863.51999999999, 5910.740000000011 - 0.05, 2000.0, 48.5, 21234.486484374986, 6020.366796875015 - 0.05, 2000.0, 49.0, 21606.283124999976, 6130.746875000019 - 0.05, 2000.0, 49.5, 21979.26570312497, 6241.936015625022 - 0.05, 2000.0, 50.0, 22353.789999999957, 6353.99000000003 - 0.05, 5000.0, 0.0, 437.8686725071398, 437.8686725071398 - 0.05, 5000.0, 22.0, 1697.1400000000003, 716.79 - 0.05, 5000.0, 22.5, 2019.1469140625002, 785.05048828125 - 0.05, 5000.0, 23.0, 2337.8596875, 857.5723437499998 - 0.05, 5000.0, 23.5, 2654.3801171874984, 933.6580273437501 - 0.05, 5000.0, 24.0, 2969.809999999997, 1012.6100000000002 - 0.05, 5000.0, 24.5, 3285.251132812496, 1093.7307226562502 - 0.05, 5000.0, 25.0, 3601.8053124999947, 1176.3226562500001 - 0.05, 5000.0, 25.5, 3920.5743359374937, 1259.68826171875 - 0.05, 5000.0, 26.0, 4242.659999999992, 1343.1300000000003 - 0.05, 5000.0, 26.5, 4580.739667968749, 1417.7053710937507 - 0.05, 5000.0, 27.0, 4925.001031250001, 1490.4906562500012 - 0.05, 5000.0, 27.5, 5274.561503906249, 1562.2017382812514 - 0.05, 5000.0, 28.0, 5628.538499999999, 1633.5545000000022 - 0.05, 5000.0, 28.5, 5986.0494335937465, 1705.2648242187522 - 0.05, 5000.0, 29.0, 6346.211718749997, 1778.0485937500018 - 0.05, 5000.0, 29.5, 6708.142769531247, 1852.6216914062518 - 0.05, 5000.0, 30.0, 7070.959999999994, 1929.7000000000028 - 0.05, 5000.0, 30.5, 7424.522490234384, 2021.094580078128 - 0.05, 5000.0, 31.0, 7778.08773437501, 2115.369453125003 - 0.05, 5000.0, 31.5, 8131.654892578135, 2212.1838183593786 - 0.05, 5000.0, 32.0, 8485.223125000013, 2311.1968750000033 - 0.05, 5000.0, 32.5, 8838.79159179689, 2412.0678222656297 - 0.05, 5000.0, 33.0, 9192.359453125016, 2514.4558593750053 - 0.05, 5000.0, 33.5, 9545.925869140645, 2618.020185546881 - 0.05, 5000.0, 34.0, 9899.49000000002, 2722.420000000006 - 0.05, 5000.0, 34.5, 10253.031687499983, 2825.089445312506 - 0.05, 5000.0, 35.0, 10606.571249999983, 2928.124687500007 - 0.05, 5000.0, 35.5, 10960.109687499982, 3031.3968359375094 - 0.05, 5000.0, 36.0, 11313.64799999998, 3134.7770000000096 - 0.05, 5000.0, 36.5, 11667.187187499972, 3238.1362890625123 - 0.05, 5000.0, 37.0, 12020.728249999971, 3341.345812500014 - 0.05, 5000.0, 37.5, 12374.272187499968, 3444.276679687516 - 0.05, 5000.0, 38.0, 12727.819999999958, 3546.8000000000193 - 0.05, 5000.0, 38.5, 13081.38123046872, 3647.7494921874927 - 0.05, 5000.0, 39.0, 13434.943906249962, 3748.5715624999907 - 0.05, 5000.0, 39.5, 13788.507128906207, 3849.3678515624897 - 0.05, 5000.0, 40.0, 14142.069999999949, 3950.239999999987 - 0.05, 5000.0, 40.5, 14495.629765625015, 4051.918750000003 - 0.05, 5000.0, 41.0, 14849.18812500002, 4153.625000000004 - 0.05, 5000.0, 41.5, 15202.744921875026, 4255.208750000004 - 0.05, 5000.0, 42.0, 15556.30000000003, 4356.520000000005 - 0.05, 5000.0, 42.5, 15909.574687500013, 4456.473593750005 - 0.05, 5000.0, 43.0, 16262.958750000014, 4556.228750000008 - 0.05, 5000.0, 43.5, 16616.56343750001, 4656.009531250009 - 0.05, 5000.0, 44.0, 16970.500000000015, 4756.040000000009 - 0.05, 5000.0, 44.5, 17325.989453125, 4857.244609375004 - 0.05, 5000.0, 45.0, 17681.589375000007, 4958.866875000008 - 0.05, 5000.0, 45.5, 18036.967109374997, 5060.850703125011 - 0.05, 5000.0, 46.0, 18391.79000000001, 5163.140000000014 - 0.05, 5000.0, 46.5, 18744.05937500006, 5265.123984375005 - 0.05, 5000.0, 47.0, 19095.77500000007, 5367.523125000008 - 0.05, 5000.0, 47.5, 19447.27062500009, 5470.503203125009 - 0.05, 5000.0, 48.0, 19798.88000000011, 5574.2300000000105 - 0.05, 5000.0, 48.5, 20150.93687500014, 5678.8692968750165 - 0.05, 5000.0, 49.0, 20503.775000000158, 5784.58687500002 - 0.05, 5000.0, 49.5, 20857.728125000183, 5891.548515625022 - 0.05, 5000.0, 50.0, 21213.130000000212, 5999.920000000029 - 0.05, 10000.0, 0.0, 368.52910100754684, 368.52910100754684 - 0.05, 10000.0, 22.0, 1541.4500000000007, 612.6500000000003 - 0.05, 10000.0, 22.5, 1833.6682617187498, 659.7959960937499 - 0.05, 10000.0, 23.0, 2122.9539062499985, 708.9195312499997 - 0.05, 10000.0, 23.5, 2410.300097656247, 760.1333007812493 - 0.05, 10000.0, 24.0, 2696.699999999996, 813.549999999999 - 0.05, 10000.0, 24.5, 2983.146777343744, 869.2823242187487 - 0.05, 10000.0, 25.0, 3270.6335937499916, 927.4429687499983 - 0.05, 10000.0, 25.5, 3560.1536132812384, 988.1446289062477 - 0.05, 10000.0, 26.0, 3852.6999999999853, 1051.499999999997 - 0.05, 10000.0, 26.5, 4159.743359375006, 1118.0476562500005 - 0.05, 10000.0, 27.0, 4472.398125000007, 1187.4987500000002 - 0.05, 10000.0, 27.5, 4789.861328125007, 1259.8929687500001 - 0.05, 10000.0, 28.0, 5111.330000000007, 1335.2699999999995 - 0.05, 10000.0, 28.5, 5436.001171875007, 1413.66953125 - 0.05, 10000.0, 29.0, 5763.071875000009, 1495.1312499999992 - 0.05, 10000.0, 29.5, 6091.739140625005, 1579.694843749999 - 0.05, 10000.0, 30.0, 6421.200000000006, 1667.3999999999992 - 0.05, 10000.0, 30.5, 6742.1998046875, 1765.3517578125022 - 0.05, 10000.0, 31.0, 7063.192187499998, 1865.8515625000023 - 0.05, 10000.0, 31.5, 7384.179101562497, 1968.2662109375015 - 0.05, 10000.0, 32.0, 7705.162499999995, 2071.962500000002 - 0.05, 10000.0, 32.5, 8026.1443359374925, 2176.307226562501 - 0.05, 10000.0, 33.0, 8347.126562499989, 2280.667187500001 - 0.05, 10000.0, 33.5, 8668.11113281249, 2384.4091796875 - 0.05, 10000.0, 34.0, 8989.099999999982, 2486.8999999999987 - 0.05, 10000.0, 34.5, 9310.158281249935, 2576.984296874991 - 0.05, 10000.0, 35.0, 9631.218749999918, 2665.5531249999876 - 0.05, 10000.0, 35.5, 9952.277343749909, 2752.9753906249853 - 0.05, 10000.0, 36.0, 10273.329999999893, 2839.6199999999812 - 0.05, 10000.0, 36.5, 10594.372656249883, 2925.8558593749776 - 0.05, 10000.0, 37.0, 10915.40124999987, 3012.0518749999737 - 0.05, 10000.0, 37.5, 11236.411718749849, 3098.5769531249684 - 0.05, 10000.0, 38.0, 11557.39999999983, 3185.7999999999647 - 0.05, 10000.0, 38.5, 11878.281347656284, 3275.520605468745 - 0.05, 10000.0, 39.0, 12199.174218750046, 3365.935156249995 - 0.05, 10000.0, 39.5, 12520.092480468806, 3457.0946289062454 - 0.05, 10000.0, 40.0, 12841.05000000007, 3549.0499999999975 - 0.05, 10000.0, 40.5, 13162.132421875016, 3643.432812499995 - 0.05, 10000.0, 41.0, 13483.25312500002, 3738.0812499999943 - 0.05, 10000.0, 41.5, 13804.39726562502, 3832.4140624999923 - 0.05, 10000.0, 42.0, 14125.550000000025, 3925.8499999999904 - 0.05, 10000.0, 42.5, 14446.401562500007, 4014.9816406249956 - 0.05, 10000.0, 43.0, 14767.350000000008, 4103.184374999992 - 0.05, 10000.0, 43.5, 15088.49843750001, 4191.00742187499 - 0.05, 10000.0, 44.0, 15409.950000000015, 4278.9999999999845 - 0.05, 10000.0, 44.5, 15732.846874999997, 4368.572656250002 - 0.05, 10000.0, 45.0, 16055.837499999992, 4459.068750000008 - 0.05, 10000.0, 45.5, 16378.609374999995, 4550.6929687500115 - 0.05, 10000.0, 46.0, 16700.849999999984, 4643.650000000016 - 0.05, 10000.0, 46.5, 17020.65117187502, 4738.558593750013 - 0.05, 10000.0, 47.0, 17339.934375000026, 4835.043750000016 - 0.05, 10000.0, 47.5, 17659.025390625036, 4933.144531250017 - 0.05, 10000.0, 48.0, 17978.25000000003, 5032.900000000021 - 0.05, 10000.0, 48.5, 18297.933984375042, 5134.349218750026 - 0.05, 10000.0, 49.0, 18618.40312500003, 5237.531250000029 - 0.05, 10000.0, 49.5, 18939.98320312503, 5342.4851562500335 - 0.05, 10000.0, 50.0, 19263.000000000022, 5449.250000000038 - 0.05, 15000.0, 0.0, 308.16160645508495, 308.16160645508495 - 0.05, 15000.0, 22.0, -11315.699999999966, -3791.2999999999856 - 0.05, 15000.0, 22.5, -13464.463085937465, -4536.628124999989 - 0.05, 15000.0, 23.0, -15590.432812499963, -5246.462499999996 - 0.05, 15000.0, 23.5, -17701.06113281247, -5929.815625000007 - 0.05, 15000.0, 24.0, -19803.799999999974, -6595.700000000019 - 0.05, 15000.0, 24.5, -21906.10136718749, -7253.128125000031 - 0.05, 15000.0, 25.0, -24015.417187500007, -7911.1125000000475 - 0.05, 15000.0, 25.5, -26139.19941406254, -8578.665625000067 - 0.05, 15000.0, 26.0, -28284.900000000074, -9264.800000000087 - 0.05, 15000.0, 26.5, -30537.59433593751, -10035.269140624987 - 0.05, 15000.0, 27.0, -32831.54656250003, -10845.586874999975 - 0.05, 15000.0, 27.5, -35160.901757812564, -11695.038671874967 - 0.05, 15000.0, 28.0, -37519.805000000095, -12582.90999999995 - 0.05, 15000.0, 28.5, -39902.40136718763, -13508.48632812494 - 0.05, 15000.0, 29.0, -42302.835937500175, -14471.053124999926 - 0.05, 15000.0, 29.5, -44715.25378906272, -15469.895859374912 - 0.05, 15000.0, 30.0, -47133.80000000028, -16504.29999999989 - 0.05, 15000.0, 30.5, -49491.86074218762, -17673.566796874977 - 0.05, 15000.0, 31.0, -51850.126562500125, -18867.440624999967 - 0.05, 15000.0, 31.5, -54208.529101562635, -20075.681640624964 - 0.05, 15000.0, 32.0, -56567.00000000015, -21288.04999999996 - 0.05, 15000.0, 32.5, -58925.470898437656, -22494.30585937495 - 0.05, 15000.0, 33.0, -61283.87343750018, -23684.209374999937 - 0.05, 15000.0, 33.5, -63642.13925781271, -24847.52070312493 - 0.05, 15000.0, 34.0, -66000.20000000024, -25973.999999999916 - 0.05, 15000.0, 34.5, -68355.52308593725, -26788.023203124867 - 0.05, 15000.0, 35.0, -70710.73906249976, -27570.00937499984 - 0.05, 15000.0, 35.5, -73066.0142578123, -28334.993359374817 - 0.05, 15000.0, 36.0, -75421.51499999982, -29098.009999999784 - 0.05, 15000.0, 36.5, -77777.40761718733, -29874.094140624755 - 0.05, 15000.0, 37.0, -80133.85843749989, -30678.280624999723 - 0.05, 15000.0, 37.5, -82491.03378906239, -31525.60429687469 - 0.05, 15000.0, 38.0, -84849.09999999998, -32431.099999999642 - 0.05, 15000.0, 38.5, -87210.60488281045, -33501.62050781198 - 0.05, 15000.0, 39.0, -89572.09843749754, -34612.77343749941 - 0.05, 15000.0, 39.5, -91933.21777343462, -35759.18964843684 - 0.05, 15000.0, 40.0, -94293.59999999657, -36935.49999999925 - 0.05, 15000.0, 40.5, -96651.47890624974, -38111.10781250016 - 0.05, 15000.0, 41.0, -99008.45624999978, -39315.962500000234 - 0.05, 15000.0, 41.5, -101364.73046874977, -40554.785937500325 - 0.05, 15000.0, 42.0, -103720.49999999978, -41832.300000000425 - 0.05, 15000.0, 42.5, -106074.35390624941, -43220.77343749973 - 0.05, 15000.0, 43.0, -108428.74374999924, -44630.36249999964 - 0.05, 15000.0, 43.5, -110784.51171874904, -46038.77031249955 - 0.05, 15000.0, 44.0, -113142.49999999885, -47423.69999999946 - 0.05, 15000.0, 44.5, -115511.67578125003, -48628.81562500011 - 0.05, 15000.0, 45.0, -117881.50625000006, -49819.47500000017 - 0.05, 15000.0, 45.5, -120249.58359375008, -51026.99687500024 - 0.05, 15000.0, 46.0, -122613.50000000006, -52282.70000000029 - 0.05, 15000.0, 46.5, -124958.2031250004, -53706.68828124961 - 0.05, 15000.0, 47.0, -127298.98750000048, -55205.98124999956 - 0.05, 15000.0, 47.5, -129638.50312500064, -56776.38359374953 - 0.05, 15000.0, 48.0, -131979.40000000075, -58413.69999999949 - 0.05, 15000.0, 48.5, -134324.32812500102, -60113.73515624948 - 0.05, 15000.0, 49.0, -136675.9375000012, -61872.293749999495 - 0.05, 15000.0, 49.5, -139036.87812500147, -63685.1804687495 - 0.05, 15000.0, 50.0, -141409.80000000185, -65548.19999999958 - 0.05, 20000.0, 0.0, 255.88822837461043, 255.88822837461043 - 0.05, 20000.0, 22.0, 891.399999999955, 224.3000000000086 - 0.05, 20000.0, 22.5, 1078.2558593749102, 552.3896484375016 - 0.05, 20000.0, 23.0, 1259.0281249998634, 746.4953124999879 - 0.05, 20000.0, 23.5, 1434.9863281248136, 826.9533203124674 - 0.05, 20000.0, 24.0, 1607.3999999997588, 814.0999999999405 - 0.05, 20000.0, 24.5, 1777.5386718746984, 728.2716796874065 - 0.05, 20000.0, 25.0, 1946.6718749996298, 589.8046874998668 - 0.05, 20000.0, 25.5, 2116.0691406245523, 419.035351562321 - 0.05, 20000.0, 26.0, 2286.9999999994643, 236.29999999976883 - 0.05, 20000.0, 26.5, 2473.3845703123975, 214.0619140623532 - 0.05, 20000.0, 27.0, 2664.5646874998874, 229.22343749983537 - 0.05, 20000.0, 27.5, 2859.6412109373787, 276.04199218732066 - 0.05, 20000.0, 28.0, 3057.714999999868, 348.7749999998084 - 0.05, 20000.0, 28.5, 3257.8869140623574, 441.67988281229964 - 0.05, 20000.0, 29.0, 3459.2578124998463, 549.0140624997936 - 0.05, 20000.0, 29.5, 3660.9285546873343, 665.0349609372898 - 0.05, 20000.0, 30.0, 3861.9999999998186, 783.9999999997899 - 0.05, 20000.0, 30.5, 4047.952539062284, 816.4824218748056 - 0.05, 20000.0, 31.0, 4232.804687499759, 848.3937499997604 - 0.05, 20000.0, 31.5, 4416.954492187242, 881.9613281247099 - 0.05, 20000.0, 32.0, 4600.799999999734, 919.4124999996543 - 0.05, 20000.0, 32.5, 4784.739257812237, 962.9746093745935 - 0.05, 20000.0, 33.0, 4969.170312499757, 1014.8749999995282 - 0.05, 20000.0, 33.5, 5154.491210937288, 1077.3410156244581 - 0.05, 20000.0, 34.0, 5341.099999999842, 1152.5999999993844 - 0.05, 20000.0, 34.5, 5540.528007809719, 1406.2666796862077 - 0.05, 20000.0, 35.0, 5740.979687496741, 1661.6203124984447 - 0.05, 20000.0, 35.5, 5941.792773433718, 1905.3275390606457 - 0.05, 20000.0, 36.0, 6142.304999995654, 2124.0549999978093 - 0.05, 20000.0, 36.5, 6341.85410155754, 2304.4693359349326 - 0.05, 20000.0, 37.0, 6539.777812494377, 2433.2371874970145 - 0.05, 20000.0, 37.5, 6735.413867181162, 2497.0251953090474 - 0.05, 20000.0, 38.0, 6928.099999992893, 2482.499999996029 - 0.05, 20000.0, 38.5, 7110.229882812457, 2187.345117188307 - 0.05, 20000.0, 39.0, 7291.68593750034, 1885.2015625011106 - 0.05, 20000.0, 39.5, 7473.349023438296, 1604.732226563959 - 0.05, 20000.0, 40.0, 7656.100000001325, 1374.6000000018512 - 0.05, 20000.0, 40.5, 7844.389062499345, 1318.9921875004447 - 0.05, 20000.0, 41.0, 8034.09999999903, 1332.8375000005758 - 0.05, 20000.0, 41.5, 8224.68593749858, 1406.5890625007396 - 0.05, 20000.0, 42.0, 8415.599999997963, 1530.7000000009455 - 0.05, 20000.0, 42.5, 8605.287499998849, 1685.5414062490418 - 0.05, 20000.0, 43.0, 8794.612499998637, 1875.6812499987552 - 0.05, 20000.0, 43.5, 8983.431249998448, 2095.6054687484407 - 0.05, 20000.0, 44.0, 9171.599999998281, 2339.7999999981007 - 0.05, 20000.0, 44.5, 9356.088281249395, 2625.055468749302 - 0.05, 20000.0, 45.0, 9540.793749999393, 2914.631249999169 - 0.05, 20000.0, 45.5, 9726.727343749453, 3194.0914062489974 - 0.05, 20000.0, 46.0, 9914.89999999957, 3448.9999999987735 - 0.05, 20000.0, 46.5, 10111.947656249158, 3619.0304687496305 - 0.05, 20000.0, 47.0, 10311.006249999016, 3753.9937499995503 - 0.05, 20000.0, 47.5, 10510.83671874886, 3857.8101562494594 - 0.05, 20000.0, 48.0, 10710.199999998695, 3934.3999999993625 - 0.05, 20000.0, 48.5, 10907.857031248517, 3987.6835937492597 - 0.05, 20000.0, 49.0, 11102.568749998327, 4021.58124999916 - 0.05, 20000.0, 49.5, 11293.096093748129, 4040.013281249062 - 0.05, 20000.0, 50.0, 11478.199999997922, 4046.8999999989746 - 0.05, 25000.0, 0.0, 210.88116657951966, 210.88116657951966 - 0.05, 25000.0, 22.0, 421.70000000002904, 590.700000000038 - 0.05, 25000.0, 22.5, 524.0677734375236, 5.514062500012177 - 0.05, 25000.0, 23.0, 620.4328125000072, -311.12500000000114 - 0.05, 25000.0, 23.5, 711.88144531248, -401.57656250000366 - 0.05, 25000.0, 24.0, 799.499999999944, -308.1999999999982 - 0.05, 25000.0, 24.5, 884.3748046873993, -73.35468749998398 - 0.05, 25000.0, 25.0, 967.5921874998472, 260.6000000000339 - 0.05, 25000.0, 25.5, 1050.2384765622896, 651.3046875000557 - 0.05, 25000.0, 26.0, 1133.3999999997268, 1056.4000000000779 - 0.05, 25000.0, 26.5, 1228.371875000042, 1083.2066406251236 - 0.05, 25000.0, 27.0, 1326.6150000000227, 1019.6668750001537 - 0.05, 25000.0, 27.5, 1427.465624999997, 883.4761718751818 - 0.05, 25000.0, 28.0, 1530.2599999999652, 692.3300000002071 - 0.05, 25000.0, 28.5, 1634.334374999927, 463.92382812523067 - 0.05, 25000.0, 29.0, 1739.024999999883, 215.95312500025125 - 0.05, 25000.0, 29.5, 1843.668124999833, -33.88664062472935 - 0.05, 25000.0, 30.0, 1947.599999999779, -267.89999999971224 - 0.05, 25000.0, 30.5, 2040.478417969173, -219.7305664059317 - 0.05, 25000.0, 31.0, 2132.2398437505612, -144.0257812495721 - 0.05, 25000.0, 31.5, 2223.1422851569673, -46.77216796820005 - 0.05, 25000.0, 32.0, 2313.4437500008894, 66.04375000068217 - 0.05, 25000.0, 32.5, 2403.402246094825, 188.43544921957482 - 0.05, 25000.0, 33.0, 2493.2757812512764, 314.41640625097625 - 0.05, 25000.0, 33.5, 2583.322363282743, 438.0000976573865 - 0.05, 25000.0, 34.0, 2673.8000000017214, 553.200000001304 - 0.05, 25000.0, 34.5, 2770.208085939355, 414.21410156247055 - 0.05, 25000.0, 35.0, 2867.06406250224, 277.71093749990496 - 0.05, 25000.0, 35.5, 2964.126757815152, 160.54355468732547 - 0.05, 25000.0, 36.0, 3061.1550000030866, 79.56499999973494 - 0.05, 25000.0, 36.5, 3157.907617191046, 51.62832031213429 - 0.05, 25000.0, 37.0, 3254.1434375040253, 93.5865624995231 - 0.05, 25000.0, 37.5, 3349.6212890670245, 222.29277343689864 - 0.05, 25000.0, 38.0, 3444.1000000050394, 454.59999999926913 - 0.05, 25000.0, 38.5, 3531.702148437129, 1194.4769531264674 - 0.05, 25000.0, 39.0, 3620.745312499294, 1870.9343750016942 - 0.05, 25000.0, 39.5, 3712.2408203114464, 2414.7996093769416 - 0.05, 25000.0, 40.0, 3807.1999999985997, 2756.9000000022115 - 0.05, 25000.0, 40.5, 3915.658593751579, 2460.4476562508835 - 0.05, 25000.0, 41.0, 4025.9937500021497, 1970.9312500011997 - 0.05, 25000.0, 41.5, 4135.60703125286, 1366.2242187515608 - 0.05, 25000.0, 42.0, 4241.900000003716, 724.2000000019661 - 0.05, 25000.0, 42.5, 4327.336718751927, 283.47031249969535 - 0.05, 25000.0, 43.0, 4410.231250002792, -103.12500000032333 - 0.05, 25000.0, 43.5, 4493.960156253766, -422.0078125003433 - 0.05, 25000.0, 44.0, 4581.9000000048345, -659.6000000003694 - 0.05, 25000.0, 44.5, 4696.743750000672, -716.8546874986243 - 0.05, 25000.0, 45.0, 4814.8250000013095, -699.8499999981178 - 0.05, 25000.0, 45.5, 4931.793750002127, -629.1953124975332 - 0.05, 25000.0, 46.0, 5043.300000003139, -525.4999999968694 - 0.05, 25000.0, 46.5, 5124.442968751659, -529.6703124987469 - 0.05, 25000.0, 47.0, 5199.643750001926, -493.8999999982997 - 0.05, 25000.0, 47.5, 5272.772656252163, -390.6796874977673 - 0.05, 25000.0, 48.0, 5347.700000002368, -192.4999999971435 - 0.05, 25000.0, 48.5, 5428.296093752541, 128.14843750357795 - 0.05, 25000.0, 49.0, 5518.431250002676, 598.7750000044002 - 0.05, 25000.0, 49.5, 5621.975781252778, 1246.8890625053332 - 0.05, 25000.0, 50.0, 5742.80000000284, 2100.000000006377 - 0.05, 30000.0, 0.0, 172.37065290459807, 172.37065290459807 - 0.05, 30000.0, 22.0, -125.09999999999366, -48.100000000063915 - 0.05, 30000.0, 22.5, -157.25566406246008, 175.43613281247013 - 0.05, 30000.0, 23.0, -185.9171874999228, 243.3609375000099 - 0.05, 30000.0, 23.5, -211.52011718737833, 183.405273437557 - 0.05, 30000.0, 24.0, -234.49999999982342, 23.300000000113187 - 0.05, 30000.0, 24.5, -255.29238281225446, -209.22402343731977 - 0.05, 30000.0, 25.0, -274.33281249966797, -486.4359374997405 - 0.05, 30000.0, 25.5, -292.0568359370607, -780.6048828121466 - 0.05, 30000.0, 26.0, -308.89999999942916, -1063.999999999538 - 0.05, 30000.0, 26.5, -327.265234375152, -1034.316796875107 - 0.05, 30000.0, 27.0, -345.7331250002137, -922.7081250001165 - 0.05, 30000.0, 27.5, -364.4019531252941, -748.5128906251284 - 0.05, 30000.0, 28.0, -383.37000000039666, -531.0700000001398 - 0.05, 30000.0, 28.5, -402.7355468755246, -289.71835937515334 - 0.05, 30000.0, 29.0, -422.5968750006811, -43.7968750001678 - 0.05, 30000.0, 29.5, -443.0522656258698, 187.35554687482 - 0.05, 30000.0, 30.0, -464.2000000010936, 384.3999999998059 - 0.05, 30000.0, 30.5, -488.65917968736204, 220.12568359362547 - 0.05, 30000.0, 31.0, -513.7671874998784, 12.386718749891543 - 0.05, 30000.0, 31.5, -539.3822265624008, -228.83466796884431 - 0.05, 30000.0, 32.0, -565.3624999999294, -493.5562500000815 - 0.05, 30000.0, 32.5, -591.5662109374637, -771.7958007813204 - 0.05, 30000.0, 33.0, -617.8515625000031, -1053.5710937500662 - 0.05, 30000.0, 33.5, -644.0767578125474, -1328.8999023438137 - 0.05, 30000.0, 34.0, -670.1000000000972, -1587.8000000000684 - 0.05, 30000.0, 34.5, -688.3384374997872, -1728.764023437368 - 0.05, 30000.0, 35.0, -706.7999999997775, -1842.0515624997886 - 0.05, 30000.0, 35.5, -726.0515624997804, -1926.3970703121952 - 0.05, 30000.0, 36.0, -746.6599999997992, -1980.5349999995883 - 0.05, 30000.0, 36.5, -769.1921874998369, -2003.1998046869655 - 0.05, 30000.0, 37.0, -794.214999999896, -1993.1259374993274 - 0.05, 30000.0, 37.5, -822.2953124999797, -1949.0478515616735 - 0.05, 30000.0, 38.0, -854.000000000091, -1869.699999999002 - 0.05, 30000.0, 38.5, -904.3894531345018, -1630.4257812512878 - 0.05, 30000.0, 39.0, -952.0218750112699, -1417.3312500016245 - 0.05, 30000.0, 39.5, -994.2433593882643, -1256.5710937520007 - 0.05, 30000.0, 40.0, -1028.4000000155065, -1174.3000000024167 - 0.05, 30000.0, 40.5, -1034.5937500012506, -1320.032031250871 - 0.05, 30000.0, 41.0, -1034.3125000017794, -1547.218750001156 - 0.05, 30000.0, 41.5, -1031.8000000024163, -1832.6710937514931 - 0.05, 30000.0, 42.0, -1031.3000000031652, -2153.200000001889 - 0.05, 30000.0, 42.5, -1049.4703125012747, -2645.956249999912 - 0.05, 30000.0, 43.0, -1073.1750000016618, -3063.2749999998323 - 0.05, 30000.0, 43.5, -1101.6921875020787, -3317.8312499997537 - 0.05, 30000.0, 44.0, -1134.3000000025154, -3322.299999999681 - 0.05, 30000.0, 44.5, -1171.999218751052, -2387.2390625001417 - 0.05, 30000.0, 45.0, -1211.6562500011319, -1268.2875 - 0.05, 30000.0, 45.5, -1251.860156251217, -118.96718749977845 - 0.05, 30000.0, 46.0, -1291.2000000013168, 907.2000000005391 - 0.05, 30000.0, 46.5, -1325.7218750007578, 1229.3210937499714 - 0.05, 30000.0, 47.0, -1357.5750000008406, 1292.1937499998064 - 0.05, 30000.0, 47.5, -1386.3656250009522, 1113.2445312495943 - 0.05, 30000.0, 48.0, -1411.7000000010885, 709.8999999993321 - 0.05, 30000.0, 48.5, -1433.1843750012463, 99.58671874902325 - 0.05, 30000.0, 49.0, -1450.4250000014213, -700.2687500013385 - 0.05, 30000.0, 49.5, -1463.0281250016105, -1672.2398437517504 - 0.05, 30000.0, 50.0, -1470.6000000018103, -2798.900000002215 - 0.05, 35000.0, 0.0, 139.63982496995885, 139.63982496995885 - 0.05, 35000.0, 22.0, 918.4999999999991, -51.999999999983515 - 0.05, 35000.0, 22.5, 1130.5476562500314, -123.68593749994669 - 0.05, 35000.0, 23.0, 1331.118750000034, -88.01249999992324 - 0.05, 35000.0, 23.5, 1521.9804687500105, 34.49218750008778 - 0.05, 35000.0, 24.0, 1704.8999999999617, 223.30000000008698 - 0.05, 35000.0, 24.5, 1881.6445312498913, 457.8828125000754 - 0.05, 35000.0, 25.0, 2053.981249999803, 717.7125000000536 - 0.05, 35000.0, 25.5, 2223.677343749696, 982.260937500023 - 0.05, 35000.0, 26.0, 2392.4999999995757, 1230.999999999984 - 0.05, 35000.0, 26.5, 2574.016601562183, 1227.9875000001628 - 0.05, 35000.0, 27.0, 2758.8684374996405, 1155.8000000001705 - 0.05, 35000.0, 27.5, 2946.799804687101, 1030.8375000001788 - 0.05, 35000.0, 28.0, 3137.554999999564, 869.5000000001876 - 0.05, 35000.0, 28.5, 3330.87832031203, 688.1875000001976 - 0.05, 35000.0, 29.0, 3526.514062499495, 503.3000000002139 - 0.05, 35000.0, 29.5, 3724.206523436962, 331.2375000002319 - 0.05, 35000.0, 30.0, 3923.6999999994273, 188.40000000025248 - 0.05, 35000.0, 30.5, 4125.950390625514, 411.77998046808125 - 0.05, 35000.0, 31.0, 4329.3750000005975, 666.6523437492453 - 0.05, 35000.0, 31.5, 4533.602734375688, 938.8844726554153 - 0.05, 35000.0, 32.0, 4738.262500000778, 1214.3437499990914 - 0.05, 35000.0, 32.5, 4942.983203125875, 1478.8975585927683 - 0.05, 35000.0, 33.0, 5147.393750000966, 1718.413281248956 - 0.05, 35000.0, 33.5, 5351.123046876066, 1918.7583007801513 - 0.05, 35000.0, 34.0, 5553.800000001163, 2065.799999998846 - 0.05, 35000.0, 34.5, 5736.833554690215, 1764.0633984375818 - 0.05, 35000.0, 35.0, 5919.80781250299, 1417.0765625001109 - 0.05, 35000.0, 35.5, 6104.086914065758, 1047.025195312643 - 0.05, 35000.0, 36.0, 6291.035000003509, 676.0950000001721 - 0.05, 35000.0, 36.5, 6482.016210941248, 326.4716796877037 - 0.05, 35000.0, 37.0, 6678.39468750397, 20.340937500228392 - 0.05, 35000.0, 37.5, 6881.534570316677, -220.11152343725553 - 0.05, 35000.0, 38.0, 7092.800000004363, -372.69999999973334 - 0.05, 35000.0, 38.5, 7339.270507813725, -600.6011718758509 - 0.05, 35000.0, 39.0, 7583.260937501458, -600.1531250011503 - 0.05, 35000.0, 39.5, 7820.420898439235, -307.9785156265061 - 0.05, 35000.0, 40.0, 8046.400000002058, 339.29999999808206 - 0.05, 35000.0, 40.5, 8231.233593752359, 2074.2765624992635 - 0.05, 35000.0, 41.0, 8406.431250003328, 4023.4249999989142 - 0.05, 35000.0, 41.5, 8577.888281254456, 5982.4359374985 - 0.05, 35000.0, 42.0, 8751.500000005752, 7746.999999998021 - 0.05, 35000.0, 42.5, 8957.90000000022, 8685.917187498892 - 0.05, 35000.0, 43.0, 9168.349999999567, 9192.524999998435 - 0.05, 35000.0, 43.5, 9378.84999999862, 9233.270312497876 - 0.05, 35000.0, 44.0, 9585.399999997333, 8774.599999997221 - 0.05, 35000.0, 44.5, 9762.242187500278, 7046.152343750609 - 0.05, 35000.0, 45.0, 9935.83750000055, 5045.906250000862 - 0.05, 35000.0, 45.5, 10110.889062500939, 3035.0320312511776 - 0.05, 35000.0, 46.0, 10292.100000001446, 1274.7000000015687 - 0.05, 35000.0, 46.5, 10506.778906249858, 959.2679687490754 - 0.05, 35000.0, 47.0, 10727.981250000103, 1043.4437499988107 - 0.05, 35000.0, 47.5, 10951.367968750465, 1415.122656248478 - 0.05, 35000.0, 48.0, 11172.600000000952, 1962.1999999980735 - 0.05, 35000.0, 48.5, 11387.338281251563, 2572.571093747578 - 0.05, 35000.0, 49.0, 11591.243750002297, 3134.1312499969863 - 0.05, 35000.0, 49.5, 11779.977343753166, 3534.7757812462696 - 0.05, 35000.0, 50.0, 11949.20000000417, 3662.3999999954467 - 0.05, 39000.0, 0.0, 115.81876518615061, 115.81876518615061 - 0.05, 39000.0, 22.0, 614.200000000014, -362.2999999999698 - 0.05, 39000.0, 22.5, 768.4712890624797, -583.3718749999882 - 0.05, 39000.0, 23.0, 909.1046874999432, -613.9625000000055 - 0.05, 39000.0, 23.5, 1038.5607421874035, -487.69687500002306 - 0.05, 39000.0, 24.0, 1159.2999999998594, -238.2000000000425 - 0.05, 39000.0, 24.5, 1273.7830078123088, 100.90312499993519 - 0.05, 39000.0, 25.0, 1384.4703124997504, 495.98749999990787 - 0.05, 39000.0, 25.5, 1493.8224609371835, 913.4281249998744 - 0.05, 39000.0, 26.0, 1604.2999999996066, 1319.5999999998337 - 0.05, 39000.0, 26.5, 1741.358203124927, 1388.4271484375456 - 0.05, 39000.0, 27.0, 1885.7768749999088, 1362.0240625000608 - 0.05, 39000.0, 27.5, 2036.0746093748917, 1256.9001953125826 - 0.05, 39000.0, 28.0, 2190.7699999998763, 1089.56500000011 - 0.05, 39000.0, 28.5, 2348.3816406248648, 876.5279296876456 - 0.05, 39000.0, 29.0, 2507.428124999857, 634.2984375001888 - 0.05, 39000.0, 29.5, 2666.4280468748557, 379.3859765627408 - 0.05, 39000.0, 30.0, 2823.899999999861, 128.30000000029713 - 0.05, 39000.0, 30.5, 2955.654687500112, 104.0870117183643 - 0.05, 39000.0, 31.0, 3085.0812500001766, 97.04921874952879 - 0.05, 39000.0, 31.5, 3212.860937500253, 104.02587890568327 - 0.05, 39000.0, 32.0, 3339.67500000034, 121.85624999932872 - 0.05, 39000.0, 32.5, 3466.2046875004394, 147.37958984296165 - 0.05, 39000.0, 33.0, 3593.131250000551, 177.43515624908423 - 0.05, 39000.0, 33.5, 3721.1359375006755, 208.86220703019626 - 0.05, 39000.0, 34.0, 3850.9000000008123, 238.4999999987956 - 0.05, 39000.0, 34.5, 4002.980859374901, 333.10999999956596 - 0.05, 39000.0, 35.0, 4156.29062499983, 412.94999999947686 - 0.05, 39000.0, 35.5, 4309.617578124733, 468.19999999937863 - 0.05, 39000.0, 36.0, 4461.749999999606, 489.0399999992735 - 0.05, 39000.0, 36.5, 4611.476171874448, 465.6499999991597 - 0.05, 39000.0, 37.0, 4757.584374999253, 388.2099999990387 - 0.05, 39000.0, 37.5, 4898.862890624019, 246.89999999891052 - 0.05, 39000.0, 38.0, 5034.099999998742, 31.899999998772728 - 0.05, 39000.0, 38.5, 5142.477343751252, -604.4812499988429 - 0.05, 39000.0, 39.0, 5252.556250001516, -1158.999999998624 - 0.05, 39000.0, 39.5, 5367.482031251829, -1566.393749998355 - 0.05, 39000.0, 40.0, 5490.400000002195, -1761.3999999980479 - 0.05, 39000.0, 40.5, 5641.213281250239, -1475.3382812500568 - 0.05, 39000.0, 41.0, 5799.606250000018, -927.731249999981 - 0.05, 39000.0, 41.5, 5962.021093749767, -134.68359374986136 - 0.05, 39000.0, 42.0, 6124.8999999995085, 887.7000000002996 - 0.05, 39000.0, 42.5, 6263.192968750743, 2404.404687500597 - 0.05, 39000.0, 43.0, 6403.431250001323, 4005.8000000007073 - 0.05, 39000.0, 43.5, 6550.653906251907, 5563.3453125008045 - 0.05, 39000.0, 44.0, 6709.90000000244, 6948.500000000879 - 0.05, 39000.0, 44.5, 6936.3804687504135, 7846.8367187492595 - 0.05, 39000.0, 45.0, 7164.893750000944, 8390.056249999136 - 0.05, 39000.0, 45.5, 7380.410156251724, 8523.972656249049 - 0.05, 39000.0, 46.0, 7567.9000000028245, 8194.399999999005 - 0.05, 39000.0, 46.5, 7626.876562500223, 6722.718749999458 - 0.05, 39000.0, 47.0, 7661.95000000003, 4928.949999998966 - 0.05, 39000.0, 47.5, 7692.27343749974, 3008.6812499983434 - 0.05, 39000.0, 48.0, 7736.999999999339, 1157.4999999975898 - 0.05, 39000.0, 48.5, 7815.282812498792, -429.00625000330365 - 0.05, 39000.0, 49.0, 7946.274999998086, -1555.250000004351 - 0.05, 39000.0, 49.5, 8149.129687497191, -2025.6437500055144 - 0.05, 39000.0, 50.0, 8442.99999999608, -1644.6000000068598 - 0.05, 43000.0, 0.0, 95.5618949430423, 95.5618949430423 - 0.05, 43000.0, 22.0, -818.9000000000212, 1149.299999999993 - 0.05, 43000.0, 22.5, -903.805468750126, 422.4490234374325 - 0.05, 43000.0, 23.0, -994.731250000237, -179.11718750010039 - 0.05, 43000.0, 23.5, -1091.5664062503613, -671.8498046876117 - 0.05, 43000.0, 24.0, -1194.2000000005037, -1072.2000000001108 - 0.05, 43000.0, 24.5, -1302.5210937506718, -1396.6189453126026 - 0.05, 43000.0, 25.0, -1416.4187500008718, -1661.5578125000957 - 0.05, 43000.0, 25.5, -1535.78203125111, -1883.4677734375985 - 0.05, 43000.0, 26.0, -1660.5000000013924, -2078.800000000118 - 0.05, 43000.0, 26.5, -1794.2734375001019, -2443.6978515627816 - 0.05, 43000.0, 27.0, -1933.3975000000958, -2825.188437500331 - 0.05, 43000.0, 27.5, -2077.107812500073, -3208.9185546878803 - 0.05, 43000.0, 28.0, -2224.6400000000317, -3580.535000000426 - 0.05, 43000.0, 28.5, -2375.2296874999683, -3925.6845703129675 - 0.05, 43000.0, 29.0, -2528.112499999879, -4230.014062500498 - 0.05, 43000.0, 29.5, -2682.5240624997623, -4479.170273438016 - 0.05, 43000.0, 30.0, -2837.6999999996137, -4658.8000000005195 - 0.05, 43000.0, 30.5, -2987.116113281137, -4586.446679688281 - 0.05, 43000.0, 31.0, -3136.3164062499063, -4431.870312500923 - 0.05, 43000.0, 31.5, -3285.085058593677, -4196.727539063575 - 0.05, 43000.0, 32.0, -3433.206249999944, -3882.675000001236 - 0.05, 43000.0, 32.5, -3580.4641601562075, -3491.3693359389063 - 0.05, 43000.0, 33.0, -3726.6429687499667, -3024.467187501582 - 0.05, 43000.0, 33.5, -3871.5268554687186, -2483.6251953142714 - 0.05, 43000.0, 34.0, -4014.899999999963, -1870.500000001966 - 0.05, 43000.0, 34.5, -4138.039101564561, -140.54957031327285 - 0.05, 43000.0, 35.0, -4260.9984375025115, 1558.7328124990618 - 0.05, 43000.0, 35.5, -4385.3248046905455, 3126.0525390613584 - 0.05, 43000.0, 36.0, -4512.56500000367, 4460.114999998656 - 0.05, 43000.0, 36.5, -4644.265820316899, 5459.625585935926 - 0.05, 43000.0, 37.0, -4781.974062505242, 6023.289687498174 - 0.05, 43000.0, 37.5, -4927.236523443706, 6049.812695310415 - 0.05, 43000.0, 38.0, -5081.6000000073045, 5437.899999997608 - 0.05, 43000.0, 38.5, -5284.94707031056, 2824.263281251926 - 0.05, 43000.0, 39.0, -5480.610937497496, 23.96875000259024 - 0.05, 43000.0, 39.5, -5661.619335934341, -2783.835156246634 - 0.05, 43000.0, 40.0, -5820.999999996097, -5419.99999999578 - 0.05, 43000.0, 40.5, -5896.822656249609, -7364.432031251204 - 0.05, 43000.0, 41.0, -5959.056249999671, -8915.30625000148 - 0.05, 43000.0, 41.5, -6022.711718749725, -10029.852343751812 - 0.05, 43000.0, 42.0, -6102.799999999762, -10665.300000002208 - 0.05, 43000.0, 42.5, -6286.890625001825, -10300.96875000204 - 0.05, 43000.0, 43.0, -6488.412500002259, -9563.16250000293 - 0.05, 43000.0, 43.5, -6693.35312500287, -8600.275000003938 - 0.05, 43000.0, 44.0, -6887.700000003712, -7560.700000005041 - 0.05, 43000.0, 44.5, -6991.608593751698, -6855.8195312497 - 0.05, 43000.0, 45.0, -7083.23125000235, -6265.843749999563 - 0.05, 43000.0, 45.5, -7174.888281252965, -5833.971093749429 - 0.05, 43000.0, 46.0, -7278.9000000034775, -5603.39999999931 - 0.05, 43000.0, 46.5, -7461.317187503838, -5971.082812502346 - 0.05, 43000.0, 47.0, -7659.237500005194, -6484.962500002783 - 0.05, 43000.0, 47.5, -7863.489062506824, -7046.735937503249 - 0.05, 43000.0, 48.0, -8064.900000008775, -7558.100000003747 - 0.05, 43000.0, 48.5, -8254.298437511094, -7920.751562504283 - 0.05, 43000.0, 49.0, -8422.512500013829, -8036.387500004859 - 0.05, 43000.0, 49.5, -8560.370312517025, -7806.704687505473 - 0.05, 43000.0, 50.0, -8658.70000002073, -7133.40000000615 - 0.05, 48000.0, 0.0, 75.14797267685356, 75.14797267685356 - 0.05, 48000.0, 22.0, -749.5000000000309, 968.9999999998904 - 0.05, 48000.0, 22.5, -761.2675781250189, 379.62441406238577 - 0.05, 48000.0, 23.0, -797.8593749999911, -100.4453125001235 - 0.05, 48000.0, 23.5, -856.1464843749472, -486.24238281263865 - 0.05, 48000.0, 24.0, -932.9999999998887, -792.8000000001595 - 0.05, 48000.0, 24.5, -1025.2910156248151, -1035.1513671876878 - 0.05, 48000.0, 25.0, -1129.890624999728, -1228.3296875002234 - 0.05, 48000.0, 25.5, -1243.6699218746276, -1387.368164062766 - 0.05, 48000.0, 26.0, -1363.4999999995146, -1527.3000000003176 - 0.05, 48000.0, 26.5, -1464.007812500153, -1826.694531250119 - 0.05, 48000.0, 27.0, -1563.0375000001447, -2146.393750000138 - 0.05, 48000.0, 27.5, -1661.273437500129, -2473.3960937501543 - 0.05, 48000.0, 28.0, -1759.4000000001058, -2794.7000000001685 - 0.05, 48000.0, 28.5, -1858.1015625000753, -3097.3039062501775 - 0.05, 48000.0, 29.0, -1958.0625000000384, -3368.2062500001834 - 0.05, 48000.0, 29.5, -2059.967187499996, -3594.405468750182 - 0.05, 48000.0, 30.0, -2164.499999999946, -3762.9000000001756 - 0.05, 48000.0, 30.5, -2287.0781250004725, -3701.0411132818836 - 0.05, 48000.0, 31.0, -2412.250000000582, -3570.6789062507705 - 0.05, 48000.0, 31.5, -2539.296875000703, -3374.0163085946765 - 0.05, 48000.0, 32.0, -2667.5000000008367, -3113.256250001094 - 0.05, 48000.0, 32.5, -2796.1406250009827, -2790.6016601575348 - 0.05, 48000.0, 33.0, -2924.5000000011405, -2408.2554687514976 - 0.05, 48000.0, 33.5, -3051.8593750013097, -1968.4206054704732 - 0.05, 48000.0, 34.0, -3177.500000001491, -1473.300000001972 - 0.05, 48000.0, 34.5, -3274.64343750071, -125.24144531340062 - 0.05, 48000.0, 35.0, -3371.1125000007837, 1197.5203124989166 - 0.05, 48000.0, 35.5, -3468.6703125008653, 2416.6056640611896 - 0.05, 48000.0, 36.0, -3569.0800000009576, 3453.6349999984377 - 0.05, 48000.0, 36.5, -3674.1046875010625, 4230.22871093564 - 0.05, 48000.0, 37.0, -3785.507500001184, 4668.007187497806 - 0.05, 48000.0, 37.5, -3905.051562501326, 4688.590820309917 - 0.05, 48000.0, 38.0, -4034.5000000014925, 4213.599999996972 - 0.05, 48000.0, 38.5, -4223.2203124956595, 2191.0699218740483 - 0.05, 48000.0, 39.0, -4400.687499994803, 21.028124999018473 - 0.05, 48000.0, 39.5, -4558.08593749382, -2158.5527343759786 - 0.05, 48000.0, 40.0, -4686.599999992698, -4209.7000000009575 - 0.05, 48000.0, 40.5, -4704.343750000932, -5738.927343750969 - 0.05, 48000.0, 41.0, -4704.80000000116, -6965.981250001209 - 0.05, 48000.0, 41.5, -4708.3812500014055, -7855.094531251463 - 0.05, 48000.0, 42.0, -4735.500000001671, -8370.500000001732 - 0.05, 48000.0, 42.5, -4900.381250000686, -8099.934374999112 - 0.05, 48000.0, 43.0, -5092.100000000835, -7534.724999998956 - 0.05, 48000.0, 43.5, -5293.543750000999, -6789.703124998838 - 0.05, 48000.0, 44.0, -5487.600000001184, -5979.699999998771 - 0.05, 48000.0, 44.5, -5593.718749999555, -5414.6210937515425 - 0.05, 48000.0, 45.0, -5683.599999999366, -4936.193750001967 - 0.05, 48000.0, 45.5, -5765.50624999916, -4581.21953125242 - 0.05, 48000.0, 46.0, -5847.699999998936, -4386.500000002894 - 0.05, 48000.0, 46.5, -5964.0687499998385, -4681.356249999318 - 0.05, 48000.0, 47.0, -6087.000000000023, -5093.062499999189 - 0.05, 48000.0, 47.5, -6214.506250000178, -5541.412499999033 - 0.05, 48000.0, 48.0, -6344.60000000027, -5946.199999998835 - 0.05, 48000.0, 48.5, -6475.293750000273, -6227.218749998591 - 0.05, 48000.0, 49.0, -6604.600000000157, -6304.262499998291 - 0.05, 48000.0, 49.5, -6730.531249999892, -6097.124999997923 - 0.05, 48000.0, 50.0, -6851.099999999452, -5525.599999997485 - 0.1, 0.0, 0.0, 519.4582865586143, 519.4582865586143 - 0.1, 0.0, 22.0, 1752.4000000000012, 804.7000000000004 - 0.1, 0.0, 22.5, 2084.9435546875025, 884.7183593750012 - 0.1, 0.0, 23.0, 2414.0640625000037, 964.0281250000014 - 0.1, 0.0, 23.5, 2740.9025390625047, 1043.0238281250017 - 0.1, 0.0, 24.0, 3066.6000000000063, 1122.1000000000026 - 0.1, 0.0, 24.5, 3392.297460937506, 1201.6511718750028 - 0.1, 0.0, 25.0, 3719.1359375000056, 1282.0718750000033 - 0.1, 0.0, 25.5, 4048.256445312506, 1363.7566406250037 - 0.1, 0.0, 26.0, 4380.800000000007, 1447.1000000000042 - 0.1, 0.0, 26.5, 4729.888281250006, 1535.9882812500005 - 0.1, 0.0, 27.0, 5085.366250000005, 1627.5237500000003 - 0.1, 0.0, 27.5, 5446.321093750005, 1721.5023437500001 - 0.1, 0.0, 28.0, 5811.840000000004, 1817.72 - 0.1, 0.0, 28.5, 6181.010156250001, 1915.9726562499995 - 0.1, 0.0, 29.0, 6552.91875, 2016.0562499999992 - 0.1, 0.0, 29.5, 6926.652968749997, 2117.7667187499987 - 0.1, 0.0, 30.0, 7301.299999999993, 2220.899999999997 - 0.1, 0.0, 30.5, 7666.36250000001, 2323.8025390625007 - 0.1, 0.0, 31.0, 8031.425000000011, 2427.8578125000013 - 0.1, 0.0, 31.5, 8396.487500000008, 2532.999804687502 - 0.1, 0.0, 32.0, 8761.55000000001, 2639.1625000000013 - 0.1, 0.0, 32.5, 9126.612500000016, 2746.2798828125015 - 0.1, 0.0, 33.0, 9491.675000000014, 2854.285937500001 - 0.1, 0.0, 33.5, 9856.73750000002, 2963.1146484375004 - 0.1, 0.0, 34.0, 10221.800000000021, 3072.7000000000007 - 0.1, 0.0, 34.5, 10586.859218750024, 3183.219609374997 - 0.1, 0.0, 35.0, 10951.918750000026, 3294.340624999998 - 0.1, 0.0, 35.5, 11316.978906250028, 3405.973828124998 - 0.1, 0.0, 36.0, 11682.040000000026, 3518.029999999998 - 0.1, 0.0, 36.5, 12047.102343750026, 3630.4199218749986 - 0.1, 0.0, 37.0, 12412.166250000024, 3743.054374999998 - 0.1, 0.0, 37.5, 12777.232031250021, 3855.844140624998 - 0.1, 0.0, 38.0, 13142.30000000002, 3968.6999999999994 - 0.1, 0.0, 38.5, 13507.373632812383, 4081.7341796874944 - 0.1, 0.0, 39.0, 13872.44843749985, 4194.55156249999 - 0.1, 0.0, 39.5, 14237.524023437312, 4307.018164062484 - 0.1, 0.0, 40.0, 14602.599999999768, 4418.999999999978 - 0.1, 0.0, 40.5, 14967.678906250001, 4529.446093749998 - 0.1, 0.0, 41.0, 15332.756250000004, 4639.506249999996 - 0.1, 0.0, 41.5, 15697.830468749997, 4749.413281249992 - 0.1, 0.0, 42.0, 16062.899999999996, 4859.39999999999 - 0.1, 0.0, 42.5, 16427.670312500006, 4970.613281250024 - 0.1, 0.0, 43.0, 16792.550000000003, 5082.006250000033 - 0.1, 0.0, 43.5, 17157.65468749999, 5193.446093750041 - 0.1, 0.0, 44.0, 17523.099999999977, 5304.800000000053 - 0.1, 0.0, 44.5, 17890.142187500038, 5415.5328125000115 - 0.1, 0.0, 45.0, 18257.300000000065, 5526.075000000016 - 0.1, 0.0, 45.5, 18624.232812500082, 5636.454687500021 - 0.1, 0.0, 46.0, 18990.60000000012, 5746.7000000000235 - 0.1, 0.0, 46.5, 19354.3617187501, 5856.3429687500075 - 0.1, 0.0, 47.0, 19717.55625000013, 5966.106250000004 - 0.1, 0.0, 47.5, 20080.522656250152, 6076.216406250004 - 0.1, 0.0, 48.0, 20443.600000000188, 6186.900000000003 - 0.1, 0.0, 48.5, 20807.127343750224, 6298.38359375 - 0.1, 0.0, 49.0, 21171.443750000264, 6410.893749999997 - 0.1, 0.0, 49.5, 21536.888281250318, 6524.6570312499925 - 0.1, 0.0, 50.0, 21903.800000000367, 6639.8999999999905 - 0.1, 2000.0, 0.0, 486.3530807296619, 486.3530807296619 - 0.1, 2000.0, 22.0, 1691.3999999999999, 763.7000000000005 - 0.1, 2000.0, 22.5, 2012.4041015624998, 841.422851562501 - 0.1, 2000.0, 23.0, 2330.1046874999993, 918.1421875000015 - 0.1, 2000.0, 23.5, 2645.602929687499, 994.290429687502 - 0.1, 2000.0, 24.0, 2959.999999999996, 1070.300000000003 - 0.1, 2000.0, 24.5, 3274.397070312496, 1146.6033203125035 - 0.1, 2000.0, 25.0, 3589.895312499994, 1223.6328125000043 - 0.1, 2000.0, 25.5, 3907.5958984374925, 1301.820898437505 - 0.1, 2000.0, 26.0, 4228.599999999989, 1381.6000000000067 - 0.1, 2000.0, 26.5, 4565.571093750005, 1467.118554687502 - 0.1, 2000.0, 27.0, 4908.708750000009, 1555.3053125000022 - 0.1, 2000.0, 27.5, 5257.132031250011, 1645.9556640625033 - 0.1, 2000.0, 28.0, 5609.960000000014, 1738.8650000000048 - 0.1, 2000.0, 28.5, 5966.311718750013, 1833.8287109375053 - 0.1, 2000.0, 29.0, 6325.306250000014, 1930.6421875000058 - 0.1, 2000.0, 29.5, 6686.062656250016, 2029.100820312507 - 0.1, 2000.0, 30.0, 7047.700000000014, 2129.000000000008 - 0.1, 2000.0, 30.5, 7400.087500000024, 2228.9218750000055 - 0.1, 2000.0, 31.0, 7752.475000000027, 2329.990625000007 - 0.1, 2000.0, 31.5, 8104.862500000031, 2432.117187500008 - 0.1, 2000.0, 32.0, 8457.250000000036, 2535.2125000000096 - 0.1, 2000.0, 32.5, 8809.637500000033, 2639.1875000000105 - 0.1, 2000.0, 33.0, 9162.025000000041, 2743.9531250000136 - 0.1, 2000.0, 33.5, 9514.412500000046, 2849.4203125000154 - 0.1, 2000.0, 34.0, 9866.800000000048, 2955.5000000000173 - 0.1, 2000.0, 34.5, 10219.190781250038, 3061.7364453125037 - 0.1, 2000.0, 35.0, 10571.581250000052, 3168.442187500003 - 0.1, 2000.0, 35.5, 10923.971093750059, 3275.563085937504 - 0.1, 2000.0, 36.0, 11276.360000000073, 3383.045000000005 - 0.1, 2000.0, 36.5, 11628.747656250081, 3490.8337890625057 - 0.1, 2000.0, 37.0, 11981.133750000094, 3598.8753125000067 - 0.1, 2000.0, 37.5, 12333.517968750108, 3707.1154296875056 - 0.1, 2000.0, 38.0, 12685.90000000012, 3815.5000000000077 - 0.1, 2000.0, 38.5, 13038.276367187329, 3924.7701171875015 - 0.1, 2000.0, 39.0, 13390.651562499785, 4033.6640625000023 - 0.1, 2000.0, 39.5, 13743.025976562234, 4141.9509765625 - 0.1, 2000.0, 40.0, 14095.399999999678, 4249.4 - 0.1, 2000.0, 40.5, 14447.775000000045, 4354.003906250006 - 0.1, 2000.0, 41.0, 14800.150000000056, 4458.01875000001 - 0.1, 2000.0, 41.5, 15152.525000000065, 4561.924218750014 - 0.1, 2000.0, 42.0, 15504.900000000074, 4666.200000000015 - 0.1, 2000.0, 42.5, 15856.993750000007, 4773.525000000014 - 0.1, 2000.0, 43.0, 16209.200000000006, 4881.30000000002 - 0.1, 2000.0, 43.5, 16561.631250000013, 4989.125000000026 - 0.1, 2000.0, 44.0, 16914.400000000016, 5096.600000000032 - 0.1, 2000.0, 44.5, 17268.739843750096, 5201.547656250004 - 0.1, 2000.0, 45.0, 17623.19375000013, 5306.056250000005 - 0.1, 2000.0, 45.5, 17977.42578125016, 5410.436718750007 - 0.1, 2000.0, 46.0, 18331.100000000184, 5515.0000000000055 - 0.1, 2000.0, 46.5, 18682.20468749997, 5620.666406250013 - 0.1, 2000.0, 47.0, 19032.749999999956, 5726.893750000021 - 0.1, 2000.0, 47.5, 19383.070312499956, 5833.749218750028 - 0.1, 2000.0, 48.0, 19733.499999999938, 5941.300000000037 - 0.1, 2000.0, 48.5, 20084.373437499922, 6049.613281250048 - 0.1, 2000.0, 49.0, 20436.0249999999, 6158.7562500000595 - 0.1, 2000.0, 49.5, 20788.789062499884, 6268.796093750073 - 0.1, 2000.0, 50.0, 21142.999999999858, 6379.800000000088 - 0.1, 5000.0, 0.0, 439.84105095699834, 439.84105095699834 - 0.1, 5000.0, 22.0, 1606.1000000000006, 706.9000000000001 - 0.1, 5000.0, 22.5, 1910.8289062499998, 780.9236328125002 - 0.1, 5000.0, 23.0, 2212.443749999999, 853.7234375 - 0.1, 5000.0, 23.5, 2511.986718749997, 925.7615234374997 - 0.1, 5000.0, 24.0, 2810.499999999996, 997.4999999999995 - 0.1, 5000.0, 24.5, 3109.0257812499945, 1069.4009765624996 - 0.1, 5000.0, 25.0, 3408.606249999992, 1141.926562499999 - 0.1, 5000.0, 25.5, 3710.2835937499894, 1215.5388671874982 - 0.1, 5000.0, 26.0, 4015.0999999999863, 1290.6999999999982 - 0.1, 5000.0, 26.5, 4335.048828125001, 1371.8724609375024 - 0.1, 5000.0, 27.0, 4660.846874999998, 1455.7465625000027 - 0.1, 5000.0, 27.5, 4991.658984374998, 1542.098632812503 - 0.1, 5000.0, 28.0, 5326.649999999996, 1630.7050000000033 - 0.1, 5000.0, 28.5, 5664.984765624994, 1721.3419921875036 - 0.1, 5000.0, 29.0, 6005.828124999992, 1813.785937500005 - 0.1, 5000.0, 29.5, 6348.344921874992, 1907.8131640625043 - 0.1, 5000.0, 30.0, 6691.699999999987, 2003.2000000000062 - 0.1, 5000.0, 30.5, 7026.297265625021, 2098.274511718754 - 0.1, 5000.0, 31.0, 7360.896875000025, 2194.399218750005 - 0.1, 5000.0, 31.5, 7695.498046875027, 2291.488378906256 - 0.1, 5000.0, 32.0, 8030.100000000033, 2389.4562500000056 - 0.1, 5000.0, 32.5, 8364.701953125035, 2488.217089843757 - 0.1, 5000.0, 33.0, 8699.30312500004, 2587.685156250008 - 0.1, 5000.0, 33.5, 9033.902734375044, 2687.774707031259 - 0.1, 5000.0, 34.0, 9368.500000000051, 2788.400000000009 - 0.1, 5000.0, 34.5, 9703.074453124987, 2890.0121875000095 - 0.1, 5000.0, 35.0, 10037.64687499999, 2991.937500000013 - 0.1, 5000.0, 35.5, 10372.21835937499, 3094.0390625000173 - 0.1, 5000.0, 36.0, 10706.789999999986, 3196.18000000002 - 0.1, 5000.0, 36.5, 11041.362890624987, 3298.2234375000244 - 0.1, 5000.0, 37.0, 11375.93812499999, 3400.0325000000275 - 0.1, 5000.0, 37.5, 11710.51679687499, 3501.470312500033 - 0.1, 5000.0, 38.0, 12045.099999999986, 3602.400000000037 - 0.1, 5000.0, 38.5, 12379.69726562494, 3701.362109374987 - 0.1, 5000.0, 39.0, 12714.29687499992, 3800.2281249999833 - 0.1, 5000.0, 39.5, 13048.898046874903, 3899.155078124979 - 0.1, 5000.0, 40.0, 13383.499999999876, 3998.299999999972 - 0.1, 5000.0, 40.5, 13718.103906250044, 4098.798437500005 - 0.1, 5000.0, 41.0, 14052.706250000056, 4199.437500000007 - 0.1, 5000.0, 41.5, 14387.305468750068, 4299.982812500009 - 0.1, 5000.0, 42.0, 14721.900000000083, 4400.200000000012 - 0.1, 5000.0, 42.5, 15056.214843750027, 4498.592968750017 - 0.1, 5000.0, 43.0, 15390.631250000031, 4596.6937500000195 - 0.1, 5000.0, 43.5, 15725.257031250036, 4694.772656250024 - 0.1, 5000.0, 44.0, 16060.200000000043, 4793.100000000029 - 0.1, 5000.0, 44.5, 16396.63046875, 4892.723437500012 - 0.1, 5000.0, 45.0, 16733.168750000008, 4992.825000000016 - 0.1, 5000.0, 45.5, 17069.49765625001, 5093.364062500022 - 0.1, 5000.0, 46.0, 17405.300000000014, 5194.30000000003 - 0.1, 5000.0, 46.5, 17738.672656250124, 5295.154687500012 - 0.1, 5000.0, 47.0, 18071.51875000016, 5396.500000000016 - 0.1, 5000.0, 47.5, 18404.155468750207, 5498.4703125000215 - 0.1, 5000.0, 48.0, 18736.900000000245, 5601.200000000028 - 0.1, 5000.0, 48.5, 19070.06953125029, 5704.823437500037 - 0.1, 5000.0, 49.0, 19403.981250000343, 5809.475000000044 - 0.1, 5000.0, 49.5, 19738.9523437504, 5915.289062500053 - 0.1, 5000.0, 50.0, 20075.300000000472, 6022.400000000065 - 0.1, 10000.0, 0.0, 370.1891395136383, 370.1891395136383 - 0.1, 10000.0, 22.0, 1454.2, 619.1 - 0.1, 10000.0, 22.5, 1730.1478515625, 684.7427734375 - 0.1, 10000.0, 23.0, 2003.2671874999996, 749.8078125000001 - 0.1, 10000.0, 23.5, 2274.5029296875, 814.6439453125 - 0.1, 10000.0, 24.0, 2544.7999999999997, 879.5999999999999 - 0.1, 10000.0, 24.5, 2815.103320312499, 945.0248046874998 - 0.1, 10000.0, 25.0, 3086.3578124999985, 1011.2671874999996 - 0.1, 10000.0, 25.5, 3359.5083984374983, 1078.6759765624997 - 0.1, 10000.0, 26.0, 3635.499999999998, 1147.5999999999997 - 0.1, 10000.0, 26.5, 3925.203320312501, 1221.5230468750005 - 0.1, 10000.0, 27.0, 4220.2046875000015, 1297.8381250000004 - 0.1, 10000.0, 27.5, 4519.747460937501, 1376.3566406250004 - 0.1, 10000.0, 28.0, 4823.075000000002, 1456.8900000000006 - 0.1, 10000.0, 28.5, 5129.430664062502, 1539.2496093750008 - 0.1, 10000.0, 29.0, 5438.057812500002, 1623.2468750000005 - 0.1, 10000.0, 29.5, 5748.199804687502, 1708.6932031250005 - 0.1, 10000.0, 30.0, 6059.100000000004, 1795.4000000000008 - 0.1, 10000.0, 30.5, 6362.061132812504, 1882.4309570312512 - 0.1, 10000.0, 31.0, 6665.023437500005, 1970.4164062500013 - 0.1, 10000.0, 31.5, 6967.986523437506, 2059.238964843751 - 0.1, 10000.0, 32.0, 7270.950000000006, 2148.7812500000014 - 0.1, 10000.0, 32.5, 7573.913476562507, 2238.9258789062515 - 0.1, 10000.0, 33.0, 7876.876562500007, 2329.5554687500016 - 0.1, 10000.0, 33.5, 8179.838867187508, 2420.552636718752 - 0.1, 10000.0, 34.0, 8482.800000000008, 2511.800000000002 - 0.1, 10000.0, 34.5, 8785.753007812498, 2602.711367187498 - 0.1, 10000.0, 35.0, 9088.704687499998, 2693.6828124999975 - 0.1, 10000.0, 35.5, 9391.6552734375, 2784.6416015624973 - 0.1, 10000.0, 36.0, 9694.604999999998, 2875.514999999997 - 0.1, 10000.0, 36.5, 9997.554101562499, 2966.230273437497 - 0.1, 10000.0, 37.0, 10300.5028125, 3056.714687499996 - 0.1, 10000.0, 37.5, 10603.4513671875, 3146.895507812496 - 0.1, 10000.0, 38.0, 10906.4, 3236.6999999999957 - 0.1, 10000.0, 38.5, 11209.349999999999, 3325.568164062502 - 0.1, 10000.0, 39.0, 11512.299999999997, 3414.1671875000025 - 0.1, 10000.0, 39.5, 11815.249999999996, 3502.532617187503 - 0.1, 10000.0, 40.0, 12118.199999999997, 3590.7000000000044 - 0.1, 10000.0, 40.5, 12421.146093750007, 3678.442187499998 - 0.1, 10000.0, 41.0, 12724.093750000013, 3766.1624999999976 - 0.1, 10000.0, 41.5, 13027.044531250014, 3854.001562499997 - 0.1, 10000.0, 42.0, 13330.000000000016, 3942.0999999999967 - 0.1, 10000.0, 42.5, 13632.735156250003, 4030.8132812499985 - 0.1, 10000.0, 43.0, 13935.568750000002, 4119.981249999998 - 0.1, 10000.0, 43.5, 14238.592968750005, 4209.658593749998 - 0.1, 10000.0, 44.0, 14541.900000000005, 4299.899999999997 - 0.1, 10000.0, 44.5, 14846.523437499998, 4390.693749999999 - 0.1, 10000.0, 45.0, 15151.237499999996, 4482.1875 - 0.1, 10000.0, 45.5, 15455.757812499995, 4574.4625 - 0.1, 10000.0, 46.0, 15759.799999999992, 4667.599999999999 - 0.1, 10000.0, 46.5, 16061.649999999998, 4761.591406250002 - 0.1, 10000.0, 47.0, 16363.024999999996, 4856.643750000003 - 0.1, 10000.0, 47.5, 16664.212499999998, 4952.874218750004 - 0.1, 10000.0, 48.0, 16965.499999999993, 5050.400000000004 - 0.1, 10000.0, 48.5, 17267.174999999992, 5149.338281250005 - 0.1, 10000.0, 49.0, 17569.52499999999, 5249.806250000007 - 0.1, 10000.0, 49.5, 17872.83749999999, 5351.9210937500075 - 0.1, 10000.0, 50.0, 18177.399999999994, 5455.80000000001 - 0.1, 15000.0, 0.0, 309.5497197178256, 309.5497197178256 - 0.1, 15000.0, 22.0, -6163.499999999978, -1999.4999999999914 - 0.1, 15000.0, 22.5, -7334.093554687475, -2411.0591796874933 - 0.1, 15000.0, 23.0, -8492.21406249997, -2802.7890624999973 - 0.1, 15000.0, 23.5, -9641.927539062468, -3179.699414062502 - 0.1, 15000.0, 24.0, -10787.29999999997, -3546.800000000009 - 0.1, 15000.0, 24.5, -11932.397460937478, -3909.1005859375173 - 0.1, 15000.0, 25.0, -13081.285937499984, -4271.610937500026 - 0.1, 15000.0, 25.5, -14238.031445312496, -4639.3408203125355 - 0.1, 15000.0, 26.0, -15406.700000000004, -5017.300000000047 - 0.1, 15000.0, 26.5, -16633.667968749996, -5440.784179687493 - 0.1, 15000.0, 27.0, -17883.10875000001, -5886.247812499988 - 0.1, 15000.0, 27.5, -19151.835156250025, -6353.508789062481 - 0.1, 15000.0, 28.0, -20436.66000000004, -6842.384999999973 - 0.1, 15000.0, 28.5, -21734.396093750056, -7352.694335937466 - 0.1, 15000.0, 29.0, -23041.856250000084, -7884.254687499959 - 0.1, 15000.0, 29.5, -24355.8532812501, -8436.88394531245 - 0.1, 15000.0, 30.0, -25673.200000000135, -9010.399999999943 - 0.1, 15000.0, 30.5, -26957.670312500064, -9666.697070312486 - 0.1, 15000.0, 31.0, -28242.262500000063, -10337.604687499987 - 0.1, 15000.0, 31.5, -29526.93593750008, -11017.028710937484 - 0.1, 15000.0, 32.0, -30811.650000000074, -11698.874999999982 - 0.1, 15000.0, 32.5, -32096.36406250009, -12377.049414062478 - 0.1, 15000.0, 33.0, -33381.0375000001, -13045.457812499972 - 0.1, 15000.0, 33.5, -34665.62968750011, -13698.006054687468 - 0.1, 15000.0, 34.0, -35950.10000000012, -14328.599999999959 - 0.1, 15000.0, 34.5, -37232.94109374983, -14771.980273437399 - 0.1, 15000.0, 35.0, -38515.718749999825, -15196.376562499887 - 0.1, 15000.0, 35.5, -39798.532031249844, -15610.853320312366 - 0.1, 15000.0, 36.0, -41081.47999999984, -16024.474999999848 - 0.1, 15000.0, 36.5, -42364.66171874985, -16446.306054687324 - 0.1, 15000.0, 37.0, -43648.17624999986, -16885.410937499797 - 0.1, 15000.0, 37.5, -44932.122656249885, -17350.854101562276 - 0.1, 15000.0, 38.0, -46216.599999999904, -17851.699999999742 - 0.1, 15000.0, 38.5, -47503.1269531238, -18452.97480468717 - 0.1, 15000.0, 39.0, -48789.64687499858, -19078.76406249962 - 0.1, 15000.0, 39.5, -50075.94335937328, -19725.696289062063 - 0.1, 15000.0, 40.0, -51361.79999999797, -20390.3999999995 - 0.1, 15000.0, 40.5, -52646.16249999983, -21054.29765625009 - 0.1, 15000.0, 41.0, -53929.98749999983, -21735.306250000136 - 0.1, 15000.0, 41.5, -55213.393749999836, -22436.1367187502 - 0.1, 15000.0, 42.0, -56496.499999999854, -23159.500000000266 - 0.1, 15000.0, 42.5, -57778.56562499963, -23948.247656249838 - 0.1, 15000.0, 43.0, -59060.912499999526, -24748.893749999803 - 0.1, 15000.0, 43.5, -60344.00312499944, -25548.092968749763 - 0.1, 15000.0, 44.0, -61628.299999999326, -26332.499999999713 - 0.1, 15000.0, 44.5, -62918.71093750001, -27008.64062500007 - 0.1, 15000.0, 45.0, -64209.47500000004, -27675.350000000108 - 0.1, 15000.0, 45.5, -65499.27656250006, -28351.33437500015 - 0.1, 15000.0, 46.0, -66786.80000000006, -29055.300000000192 - 0.1, 15000.0, 46.5, -68063.80000000018, -29859.156249999745 - 0.1, 15000.0, 47.0, -69338.66250000024, -30707.124999999716 - 0.1, 15000.0, 47.5, -70612.84375000035, -31596.63124999968 - 0.1, 15000.0, 48.0, -71887.8000000004, -32525.09999999966 - 0.1, 15000.0, 48.5, -73164.98750000051, -33489.95624999964 - 0.1, 15000.0, 49.0, -74445.86250000061, -34488.62499999963 - 0.1, 15000.0, 49.5, -75731.88125000075, -35518.53124999963 - 0.1, 15000.0, 50.0, -77024.50000000095, -36577.09999999962 - 0.1, 20000.0, 0.0, 257.040876323432, 257.040876323432 - 0.1, 20000.0, 22.0, 891.3999999999696, 303.10000000000474 - 0.1, 20000.0, 22.5, 1072.5263671874382, 540.3673828124996 - 0.1, 20000.0, 23.0, 1248.9890624999052, 686.8359374999895 - 0.1, 20000.0, 23.5, 1421.832226562369, 756.3115234374751 - 0.1, 20000.0, 24.0, 1592.0999999998303, 762.599999999956 - 0.1, 20000.0, 24.5, 1760.8365234372857, 719.5072265624323 - 0.1, 20000.0, 25.0, 1929.0859374997356, 640.839062499904 - 0.1, 20000.0, 25.5, 2097.8923828121788, 540.401367187372 - 0.1, 20000.0, 26.0, 2268.299999999615, 431.99999999983527 - 0.1, 20000.0, 26.5, 2451.865234374938, 432.6361328124023 - 0.1, 20000.0, 27.0, 2639.7206249999335, 458.8171874998909 - 0.1, 20000.0, 27.5, 2831.108203124932, 506.6583984373813 - 0.1, 20000.0, 28.0, 3025.2699999999295, 572.2749999998741 - 0.1, 20000.0, 28.5, 3221.4480468749257, 651.7822265623686 - 0.1, 20000.0, 29.0, 3418.8843749999232, 741.2953124998653 - 0.1, 20000.0, 29.5, 3616.8210156249197, 836.9294921873645 - 0.1, 20000.0, 30.0, 3814.499999999917, 934.7999999998658 - 0.1, 20000.0, 30.5, 4000.3664062498465, 974.061621093619 - 0.1, 20000.0, 31.0, 4185.487499999828, 1013.2148437498383 - 0.1, 20000.0, 31.5, 4370.133593749815, 1053.7997070310541 - 0.1, 20000.0, 32.0, 4554.574999999808, 1097.3562499997668 - 0.1, 20000.0, 32.5, 4739.082031249808, 1145.4245117184764 - 0.1, 20000.0, 33.0, 4923.924999999817, 1199.5445312496822 - 0.1, 20000.0, 33.5, 5109.37421874984, 1261.2563476558853 - 0.1, 20000.0, 34.0, 5295.69999999987, 1332.0999999995856 - 0.1, 20000.0, 34.5, 5490.75070312311, 1526.8830468741307 - 0.1, 20000.0, 35.0, 5686.496874997788, 1723.0906249989541 - 0.1, 20000.0, 35.5, 5882.487109372437, 1911.4753906237547 - 0.1, 20000.0, 36.0, 6078.269999997058, 2082.78999999853 - 0.1, 20000.0, 36.5, 6273.3941406216445, 2227.787109373276 - 0.1, 20000.0, 37.0, 6467.408124996201, 2337.2193749979942 - 0.1, 20000.0, 37.5, 6659.860546870722, 2401.8394531226813 - 0.1, 20000.0, 38.0, 6850.299999995205, 2412.399999997332 - 0.1, 20000.0, 38.5, 7033.533203125035, 2229.6244140630433 - 0.1, 20000.0, 39.0, 7216.3093750003045, 2041.7171875007461 - 0.1, 20000.0, 39.5, 7399.230859375622, 1868.3263671884815 - 0.1, 20000.0, 40.0, 7582.90000000099, 1729.100000001245 - 0.1, 20000.0, 40.5, 7770.374218749523, 1708.9859375002945 - 0.1, 20000.0, 41.0, 7958.818749999308, 1736.212500000384 - 0.1, 20000.0, 41.5, 8147.853906249004, 1804.3078125004965 - 0.1, 20000.0, 42.0, 8337.09999999859, 1906.8000000006386 - 0.1, 20000.0, 42.5, 8525.403906249221, 2030.0218749993392 - 0.1, 20000.0, 43.0, 8713.468749999076, 2177.5749999991417 - 0.1, 20000.0, 43.5, 8901.224218748941, 2345.8656249989217 - 0.1, 20000.0, 44.0, 9088.599999998825, 2531.2999999986832 - 0.1, 20000.0, 44.5, 9273.775781249518, 2745.9210937495413 - 0.1, 20000.0, 45.0, 9459.131249999502, 2964.24374999946 - 0.1, 20000.0, 45.5, 9645.296093749519, 3176.419531249355 - 0.1, 20000.0, 46.0, 9832.899999999581, 3372.599999999214 - 0.1, 20000.0, 46.5, 10026.123437499415, 3511.487499999722 - 0.1, 20000.0, 47.0, 10220.624999999309, 3627.262499999658 - 0.1, 20000.0, 47.5, 10415.61406249919, 3722.656249999586 - 0.1, 20000.0, 48.0, 10610.29999999906, 3800.3999999995094 - 0.1, 20000.0, 48.5, 10803.892187498917, 3863.2249999994287 - 0.1, 20000.0, 49.0, 10995.59999999876, 3913.862499999348 - 0.1, 20000.0, 49.5, 11184.632812498598, 3955.043749999268 - 0.1, 20000.0, 50.0, 11370.199999998418, 3989.499999999197 - 0.1, 25000.0, 0.0, 211.8310803197763, 211.8310803197763 - 0.1, 25000.0, 22.0, 509.50000000002, 536.9000000000258 - 0.1, 25000.0, 22.5, 622.090234375017, 130.63046875000742 - 0.1, 25000.0, 23.0, 729.978125000006, -84.21875000000195 - 0.1, 25000.0, 23.5, 834.0769531249874, -137.80859375000387 - 0.1, 25000.0, 24.0, 935.2999999999622, -60.299999999999486 - 0.1, 25000.0, 24.5, 1034.5605468749309, 118.14609375000964 - 0.1, 25000.0, 25.0, 1132.771874999895, 367.3687500000234 - 0.1, 25000.0, 25.5, 1230.8472656248543, 657.207031250039 - 0.1, 25000.0, 26.0, 1329.6999999998118, 957.5000000000564 - 0.1, 25000.0, 26.5, 1438.9769531250286, 988.8238281250922 - 0.1, 25000.0, 27.0, 1551.3568750000152, 956.0368750001144 - 0.1, 25000.0, 27.5, 1666.2558593749977, 871.7089843751357 - 0.1, 25000.0, 28.0, 1783.0899999999756, 748.4100000001556 - 0.1, 25000.0, 28.5, 1901.2753906249502, 598.7097656251739 - 0.1, 25000.0, 29.0, 2020.2281249999191, 435.178125000194 - 0.1, 25000.0, 29.5, 2139.364296874887, 270.38492187520774 - 0.1, 25000.0, 30.0, 2258.09999999985, 116.90000000022565 - 0.1, 25000.0, 30.5, 2367.780273437781, 163.63701171896702 - 0.1, 25000.0, 31.0, 2476.6609375003773, 230.027343750292 - 0.1, 25000.0, 31.5, 2584.9267578129848, 311.84619140662573 - 0.1, 25000.0, 32.0, 2692.7625000006037, 404.86875000046666 - 0.1, 25000.0, 32.5, 2800.352929688232, 504.87021484431455 - 0.1, 25000.0, 33.0, 2907.8828125008713, 607.6257812506703 - 0.1, 25000.0, 33.5, 3015.5369140635216, 708.9106445320299 - 0.1, 25000.0, 34.0, 3123.50000000118, 804.5000000008949 - 0.1, 25000.0, 34.5, 3235.7114062513565, 720.8430078124966 - 0.1, 25000.0, 35.0, 3348.243750001638, 639.167187499955 - 0.1, 25000.0, 35.5, 3460.9242187519376, 571.3740234374038 - 0.1, 25000.0, 36.0, 3573.5800000022555, 529.3649999998465 - 0.1, 25000.0, 36.5, 3686.0382812525904, 525.0416015622823 - 0.1, 25000.0, 37.0, 3798.126250002939, 570.30531249971 - 0.1, 25000.0, 37.5, 3909.6710937533007, 677.0576171871312 - 0.1, 25000.0, 38.0, 4020.5000000036766, 857.1999999995469 - 0.1, 25000.0, 38.5, 4126.412304687145, 1397.583593751001 - 0.1, 25000.0, 39.0, 4233.351562499397, 1892.5937500011514 - 0.1, 25000.0, 39.5, 4342.0400390616405, 2293.0320312513213 - 0.1, 25000.0, 40.0, 4453.199999998889, 2549.700000001507 - 0.1, 25000.0, 40.5, 4573.976562501076, 2351.3601562506165 - 0.1, 25000.0, 41.0, 4696.100000001468, 2015.6687500008404 - 0.1, 25000.0, 41.5, 4817.723437501958, 1598.2429687510985 - 0.1, 25000.0, 42.0, 4937.000000002548, 1154.7000000013884 - 0.1, 25000.0, 42.5, 5041.461718751365, 855.6726562497923 - 0.1, 25000.0, 43.0, 5144.13125000198, 595.7562499997806 - 0.1, 25000.0, 43.5, 5247.410156252675, 384.5617187497677 - 0.1, 25000.0, 44.0, 5353.700000003439, 231.69999999975067 - 0.1, 25000.0, 44.5, 5479.210937500432, 207.91484375093674 - 0.1, 25000.0, 45.0, 5607.01250000086, 237.23125000128522 - 0.1, 25000.0, 45.5, 5733.98281250141, 304.80703125168696 - 0.1, 25000.0, 46.0, 5857.000000002088, 395.8000000021426 - 0.1, 25000.0, 46.5, 5958.149218751092, 409.30546875084724 - 0.1, 25000.0, 47.0, 6055.018750001256, 450.9687500011504 - 0.1, 25000.0, 47.5, 6150.4039062514, 540.3726562515121 - 0.1, 25000.0, 48.0, 6247.100000001516, 697.1000000019366 - 0.1, 25000.0, 48.5, 6347.902343751608, 940.733593752427 - 0.1, 25000.0, 49.0, 6455.6062500016715, 1290.856250002988 - 0.1, 25000.0, 49.5, 6573.007031251712, 1767.0507812536232 - 0.1, 25000.0, 50.0, 6702.900000001721, 2388.9000000043357 - 0.1, 30000.0, 0.0, 173.14709612267626, 173.14709612267626 - 0.1, 30000.0, 22.0, 36.3000000000049, 47.69999999995147 - 0.1, 30000.0, 22.5, 36.64238281253189, 221.64726562497802 - 0.1, 30000.0, 23.0, 39.46093750006276, 278.3843750000088 - 0.1, 30000.0, 23.5, 44.4990234376001, 238.85429687504543 - 0.1, 30000.0, 24.0, 51.50000000014659, 124.00000000008882 - 0.1, 30000.0, 24.5, 60.20722656270492, -45.23554687485898 - 0.1, 30000.0, 25.0, 70.36406250027767, -247.9093749997972 - 0.1, 30000.0, 25.5, 81.71386718786763, -463.0785156247247 - 0.1, 30000.0, 26.0, 94.00000000047726, -669.7999999996393 - 0.1, 30000.0, 26.5, 106.2904296873769, -639.5412109375873 - 0.1, 30000.0, 27.0, 118.96531249982795, -547.0865625000957 - 0.1, 30000.0, 27.5, 131.88378906226444, -407.07988281260543 - 0.1, 30000.0, 28.0, 144.90499999968367, -234.16500000011592 - 0.1, 30000.0, 28.5, 157.8880859370831, -42.98574218762633 - 0.1, 30000.0, 29.0, 170.69218749946023, 151.81406249986253 - 0.1, 30000.0, 29.5, 183.1764453118123, 335.5905859373506 - 0.1, 30000.0, 30.0, 195.19999999913705, 493.69999999984066 - 0.1, 30000.0, 30.5, 204.0150390626407, 378.9349609374006 - 0.1, 30000.0, 31.0, 212.33593750013304, 231.3640624999116 - 0.1, 30000.0, 31.5, 220.27011718762097, 58.49238281242083 - 0.1, 30000.0, 32.0, 227.92500000010492, -132.1750000000718 - 0.1, 30000.0, 32.5, 235.4080078125847, -333.13300781256544 - 0.1, 30000.0, 33.0, 242.82656250006124, -536.8765625000638 - 0.1, 30000.0, 33.5, 250.28808593753507, -735.9005859375657 - 0.1, 30000.0, 34.0, 257.90000000000487, -922.7000000000735 - 0.1, 30000.0, 34.5, 271.3855859375972, -1021.8888671874155 - 0.1, 30000.0, 35.0, 284.7015625000963, -1100.3078124998585 - 0.1, 30000.0, 35.5, 297.42050781258536, -1156.9166015622932 - 0.1, 30000.0, 36.0, 309.1150000000619, -1190.674999999717 - 0.1, 30000.0, 36.5, 319.3576171875238, -1200.5427734371299 - 0.1, 30000.0, 37.0, 327.72093749996856, -1185.4796874995313 - 0.1, 30000.0, 37.5, 333.7775390623948, -1144.445507811922 - 0.1, 30000.0, 38.0, 337.0999999997989, -1076.3999999992993 - 0.1, 30000.0, 38.5, 326.3005859301343, -886.1404296885166 - 0.1, 30000.0, 39.0, 317.59531249126536, -715.6140625012724 - 0.1, 30000.0, 39.5, 312.9923828022223, -584.7056640640599 - 0.1, 30000.0, 40.0, 314.4999999879883, -513.3000000018756 - 0.1, 30000.0, 40.5, 337.1898437491268, -615.3765625006552 - 0.1, 30000.0, 41.0, 364.78124999874444, -779.0875000008696 - 0.1, 30000.0, 41.5, 394.05703124828005, -986.679687501125 - 0.1, 30000.0, 42.0, 421.79999999772997, -1220.4000000014253 - 0.1, 30000.0, 42.5, 435.37499999902263, -1582.6359374999197 - 0.1, 30000.0, 43.0, 444.74999999872847, -1887.4374999998558 - 0.1, 30000.0, 43.5, 450.4749999984151, -2068.995312499793 - 0.1, 30000.0, 44.0, 453.0999999980906, -2061.4999999997317 - 0.1, 30000.0, 44.5, 451.8742187491457, -1344.2789062501292 - 0.1, 30000.0, 45.0, 449.16874999907304, -488.331250000032 - 0.1, 30000.0, 45.5, 446.0539062489976, 390.20703125012733 - 0.1, 30000.0, 46.0, 443.59999999891295, 1175.2000000003563 - 0.1, 30000.0, 46.5, 444.8304687493004, 1426.9374999999611 - 0.1, 30000.0, 47.0, 448.0812499991851, 1482.287499999838 - 0.1, 30000.0, 47.5, 453.6414062490389, 1354.543749999677 - 0.1, 30000.0, 48.0, 461.7999999988639, 1056.999999999483 - 0.1, 30000.0, 48.5, 472.84609374866346, 602.9499999992478 - 0.1, 30000.0, 49.0, 487.0687499984399, 5.687499998976364 - 0.1, 30000.0, 49.5, 504.75703124819626, -721.493750001332 - 0.1, 30000.0, 50.0, 526.1999999979352, -1565.3000000016782 - 0.1, 35000.0, 0.0, 140.2688322472682, 140.2688322472682 - 0.1, 35000.0, 22.0, 808.2999999999993, 32.200000000012494 - 0.1, 35000.0, 22.5, 991.0244140625246, -22.515624999958952 - 0.1, 35000.0, 23.0, 1164.6421875000274, 7.6625000000594845 - 0.1, 35000.0, 23.5, 1330.5888671875102, 106.58437500006858 - 0.1, 35000.0, 24.0, 1490.299999999975, 258.10000000006875 - 0.1, 35000.0, 24.5, 1645.211132812423, 446.05937500006087 - 0.1, 35000.0, 25.0, 1796.7578124998574, 654.3125000000455 - 0.1, 35000.0, 25.5, 1946.3755859372798, 866.7093750000232 - 0.1, 35000.0, 26.0, 2095.4999999996908, 1067.0999999999954 - 0.1, 35000.0, 26.5, 2255.3884765622493, 1070.3732421876216 - 0.1, 35000.0, 27.0, 2418.2159374997163, 1019.6853125001272 - 0.1, 35000.0, 27.5, 2583.7341796871847, 927.8509765626327 - 0.1, 35000.0, 28.0, 2751.6949999996555, 807.68500000014 - 0.1, 35000.0, 28.5, 2921.850195312128, 672.002148437649 - 0.1, 35000.0, 29.0, 3093.951562499601, 533.6171875001603 - 0.1, 35000.0, 29.5, 3267.7508984370756, 405.3448828126743 - 0.1, 35000.0, 30.0, 3442.999999999549, 300.00000000019213 - 0.1, 35000.0, 30.5, 3619.8632812504075, 480.38671874948386 - 0.1, 35000.0, 31.0, 3797.6406250004748, 685.5218749994192 - 0.1, 35000.0, 31.5, 3976.044531250546, 904.4117187493598 - 0.1, 35000.0, 32.0, 4154.787500000619, 1126.0624999993033 - 0.1, 35000.0, 32.5, 4333.582031250693, 1339.4804687492488 - 0.1, 35000.0, 33.0, 4512.140625000769, 1533.671874999201 - 0.1, 35000.0, 33.5, 4690.1757812508495, 1697.6429687491582 - 0.1, 35000.0, 34.0, 4867.400000000927, 1820.399999999121 - 0.1, 35000.0, 34.5, 5029.435273439605, 1595.9164453125672 - 0.1, 35000.0, 35.0, 5191.426562502319, 1336.3296875000929 - 0.1, 35000.0, 35.5, 5354.428320315024, 1058.7443359376175 - 0.1, 35000.0, 36.0, 5519.49500000272, 780.2650000001445 - 0.1, 35000.0, 36.5, 5687.681054690405, 517.9962890626675 - 0.1, 35000.0, 37.0, 5860.040937503078, 289.0428125001881 - 0.1, 35000.0, 37.5, 6037.629101565737, 110.509179687705 - 0.1, 35000.0, 38.0, 6221.50000000338, -0.4999999997799023 - 0.1, 35000.0, 38.5, 6432.603710938399, -171.13183593818803 - 0.1, 35000.0, 39.0, 6641.782812501076, -165.2328125009317 - 0.1, 35000.0, 39.5, 6845.6705078137875, 66.35761718628237 - 0.1, 35000.0, 40.0, 7040.900000001535, 572.7999999984531 - 0.1, 35000.0, 40.5, 7204.2617187518235, 1921.347656249458 - 0.1, 35000.0, 41.0, 7360.168750002567, 3435.8312499992 - 0.1, 35000.0, 41.5, 7513.191406253432, 4958.174218748891 - 0.1, 35000.0, 42.0, 7667.900000004422, 6330.299999998533 - 0.1, 35000.0, 42.5, 7848.048437500139, 7065.74531249913 - 0.1, 35000.0, 43.0, 8031.349999999629, 7466.174999998774 - 0.1, 35000.0, 43.5, 8214.701562498889, 7504.867187498341 - 0.1, 35000.0, 44.0, 8394.99999999789, 7155.099999997825 - 0.1, 35000.0, 44.5, 8552.333593750223, 5814.214062500501 - 0.1, 35000.0, 45.0, 8707.131250000448, 4261.800000000704 - 0.1, 35000.0, 45.5, 8863.013281250756, 2701.510937500956 - 0.1, 35000.0, 46.0, 9023.600000001165, 1337.000000001275 - 0.1, 35000.0, 46.5, 9209.843749999898, 1099.6976562492962 - 0.1, 35000.0, 47.0, 9401.100000000093, 1174.3687499990951 - 0.1, 35000.0, 47.5, 9594.05625000038, 1473.5554687488439 - 0.1, 35000.0, 48.0, 9785.400000000762, 1909.7999999985313 - 0.1, 35000.0, 48.5, 9971.818750001243, 2395.6445312481474 - 0.1, 35000.0, 49.0, 10150.000000001823, 2843.631249997683 - 0.1, 35000.0, 49.5, 10316.631250002512, 3166.302343747131 - 0.1, 35000.0, 50.0, 10468.400000003308, 3276.199999996479 - 0.1, 39000.0, 0.0, 116.3404705532745, 116.3404705532745 - 0.1, 39000.0, 22.0, 552.8000000000109, -223.39999999997656 - 0.1, 39000.0, 22.5, 687.1117187499835, -390.85195312499104 - 0.1, 39000.0, 23.0, 810.6562499999545, -410.42187500000455 - 0.1, 39000.0, 23.5, 925.3976562499237, -308.20585937501835 - 0.1, 39000.0, 24.0, 1033.299999999889, -110.30000000003338 - 0.1, 39000.0, 24.5, 1136.3273437498497, 157.1996093749492 - 0.1, 39000.0, 25.0, 1236.4437499998046, 468.1968749999286 - 0.1, 39000.0, 25.5, 1335.613281249753, 796.5957031249025 - 0.1, 39000.0, 26.0, 1435.799999999693, 1116.2999999998715 - 0.1, 39000.0, 26.5, 1557.3703124999433, 1174.2605468750312 - 0.1, 39000.0, 27.0, 1684.9374999999281, 1158.3656250000415 - 0.1, 39000.0, 27.5, 1817.3109374999146, 1081.425390625058 - 0.1, 39000.0, 28.0, 1953.2999999999022, 956.2500000000791 - 0.1, 39000.0, 28.5, 2091.714062499892, 795.6496093751061 - 0.1, 39000.0, 29.0, 2231.3624999998856, 612.4343750001384 - 0.1, 39000.0, 29.5, 2371.054687499883, 419.4144531251766 - 0.1, 39000.0, 30.0, 2509.5999999998876, 229.40000000022337 - 0.1, 39000.0, 30.5, 2627.756835937594, 215.2543945309551 - 0.1, 39000.0, 31.0, 2744.1046875001452, 214.49140624964036 - 0.1, 39000.0, 31.5, 2859.1720703127057, 224.67802734331855 - 0.1, 39000.0, 32.0, 2973.487500000272, 243.38124999948843 - 0.1, 39000.0, 32.5, 3087.5794921878496, 268.16806640564994 - 0.1, 39000.0, 33.0, 3201.9765625004356, 296.6054687493032 - 0.1, 39000.0, 33.5, 3317.2072265630304, 326.26044921794846 - 0.1, 39000.0, 34.0, 3433.800000000635, 354.6999999990844 - 0.1, 39000.0, 34.5, 3567.6683593749194, 433.80605468716954 - 0.1, 39000.0, 35.0, 3702.490624999863, 501.6578124995999 - 0.1, 39000.0, 35.5, 3837.330078124787, 550.6494140620239 - 0.1, 39000.0, 36.0, 3971.249999999687, 573.1749999994408 - 0.1, 39000.0, 36.5, 4103.313671874562, 561.6287109368523 - 0.1, 39000.0, 37.0, 4232.584374999407, 508.4046874992564 - 0.1, 39000.0, 37.5, 4358.125390624223, 405.89707031165335 - 0.1, 39000.0, 38.0, 4478.999999999005, 246.49999999904503 - 0.1, 39000.0, 38.5, 4579.131445313448, -238.6068359366427 - 0.1, 39000.0, 39.0, 4680.573437501145, -660.3703124989806 - 0.1, 39000.0, 39.5, 4785.7537109388795, -968.3486328112886 - 0.1, 39000.0, 40.0, 4897.100000001656, -1112.0999999985543 - 0.1, 39000.0, 40.5, 5029.945312500164, -883.6640625000448 - 0.1, 39000.0, 41.0, 5168.649999999985, -453.124999999986 - 0.1, 39000.0, 41.5, 5310.479687499785, 166.95156250010393 - 0.1, 39000.0, 42.0, 5452.699999999574, 964.0000000002271 - 0.1, 39000.0, 42.5, 5576.100000000574, 2142.4312500004557 - 0.1, 39000.0, 43.0, 5701.012500001026, 3385.9125000005397 - 0.1, 39000.0, 43.5, 5831.2937500014805, 4595.087500000613 - 0.1, 39000.0, 44.0, 5970.800000001897, 5670.600000000668 - 0.1, 39000.0, 44.5, 6161.926562500333, 6370.601562499429 - 0.1, 39000.0, 45.0, 6354.575000000745, 6795.224999999335 - 0.1, 39000.0, 45.5, 6537.185937501352, 6902.110937499265 - 0.1, 39000.0, 46.0, 6698.200000002206, 6648.899999999228 - 0.1, 39000.0, 46.5, 6760.237500000227, 5506.103906249584 - 0.1, 39000.0, 47.0, 6803.88750000009, 4113.343749999205 - 0.1, 39000.0, 47.5, 6843.9187499998825, 2623.1117187487316 - 0.1, 39000.0, 48.0, 6895.099999999584, 1187.8999999981534 - 0.1, 39000.0, 48.5, 6972.199999999179, -39.7992187525324 - 0.1, 39000.0, 49.0, 7089.98749999865, -907.4937500033266 - 0.1, 39000.0, 49.5, 7263.2312499979735, -1262.6914062542273 - 0.1, 39000.0, 50.0, 7506.699999997134, -952.900000005262 - 0.1, 43000.0, 0.0, 95.9923532837454, 95.9923532837454 - 0.1, 43000.0, 22.0, -605.4000000000174, 976.7999999999943 - 0.1, 43000.0, 22.5, -663.7398437500992, 390.7078124999468 - 0.1, 43000.0, 23.0, -726.9812500001866, -93.31250000007772 - 0.1, 43000.0, 23.5, -795.0070312502842, -488.6265625000851 - 0.1, 43000.0, 24.0, -867.7000000003973, -808.6000000000812 - 0.1, 43000.0, 24.5, -944.9429687505306, -1066.5984375000721 - 0.1, 43000.0, 25.0, -1026.6187500006893, -1275.9875000000638 - 0.1, 43000.0, 25.5, -1112.6101562508782, -1450.1328125000614 - 0.1, 43000.0, 26.0, -1202.8000000011018, -1602.4000000000715 - 0.1, 43000.0, 26.5, -1299.8218750000883, -1891.2392578127256 - 0.1, 43000.0, 27.0, -1400.9650000000854, -2193.222187500265 - 0.1, 43000.0, 27.5, -1505.64062500007, -2496.842773437805 - 0.1, 43000.0, 28.0, -1613.2600000000402, -2790.595000000343 - 0.1, 43000.0, 28.5, -1723.2343749999927, -3062.972851562876 - 0.1, 43000.0, 29.0, -1834.9749999999253, -3302.4703125004025 - 0.1, 43000.0, 29.5, -1947.8931249998368, -3497.5813671879177 - 0.1, 43000.0, 30.0, -2061.399999999724, -3636.8000000004213 - 0.1, 43000.0, 30.5, -2170.5624999998786, -3573.2095703131117 - 0.1, 43000.0, 31.0, -2279.5499999998906, -3443.610937500723 - 0.1, 43000.0, 31.5, -2388.1874999999, -3249.394335938341 - 0.1, 43000.0, 32.0, -2496.299999999908, -2991.950000000966 - 0.1, 43000.0, 32.5, -2603.7124999999114, -2672.668164063598 - 0.1, 43000.0, 33.0, -2710.249999999912, -2292.9390625012347 - 0.1, 43000.0, 33.5, -2815.7374999999065, -1854.152929688878 - 0.1, 43000.0, 34.0, -2919.9999999998936, -1357.7000000015303 - 0.1, 43000.0, 34.5, -3007.9065625016133, 35.88917968687838 - 0.1, 43000.0, 35.0, -3095.6625000019662, 1404.2828124992484 - 0.1, 43000.0, 35.5, -3184.5171875023834, 2666.0087890616014 - 0.1, 43000.0, 36.0, -3275.7200000028747, 3739.5949999989316 - 0.1, 43000.0, 36.5, -3370.5203125034463, 4543.569335936256 - 0.1, 43000.0, 37.0, -3470.167500004107, 4996.459687498558 - 0.1, 43000.0, 37.5, -3575.9109375048643, 5016.793945310856 - 0.1, 43000.0, 38.0, -3689.000000005726, 4523.099999998114 - 0.1, 43000.0, 38.5, -3841.6117187484897, 2417.4021484390014 - 0.1, 43000.0, 39.0, -3988.031249998049, 161.80781250200744 - 0.1, 43000.0, 39.5, -4122.635156247541, -2099.2654296848923 - 0.1, 43000.0, 40.0, -4239.799999996959, -4221.39999999672 - 0.1, 43000.0, 40.5, -4289.5937499996435, -5785.982031250963 - 0.1, 43000.0, 41.0, -4328.424999999676, -7032.468750001179 - 0.1, 43000.0, 41.5, -4368.393749999703, -7926.121093751443 - 0.1, 43000.0, 42.0, -4421.59999999971, -8432.200000001756 - 0.1, 43000.0, 42.5, -4558.60859375142, -8128.946875001612 - 0.1, 43000.0, 43.0, -4709.668750001754, -7523.450000002325 - 0.1, 43000.0, 43.5, -4863.494531252226, -6735.778125003126 - 0.1, 43000.0, 44.0, -5008.800000002882, -5886.000000004001 - 0.1, 43000.0, 44.5, -5081.283593751347, -5307.360156249784 - 0.1, 43000.0, 45.0, -5143.881250001868, -4821.481249999678 - 0.1, 43000.0, 45.5, -5206.5132812523625, -4463.161718749576 - 0.1, 43000.0, 46.0, -5279.10000000277, -4267.199999999484 - 0.1, 43000.0, 46.5, -5414.81953125307, -4552.406250001855 - 0.1, 43000.0, 47.0, -5563.03125000415, -4955.962500002199 - 0.1, 43000.0, 47.5, -5716.35234375545, -5399.062500002567 - 0.1, 43000.0, 48.0, -5867.40000000701, -5802.900000002959 - 0.1, 43000.0, 48.5, -6008.791406258866, -6088.668750003384 - 0.1, 43000.0, 49.0, -6133.143750011056, -6177.562500003838 - 0.1, 43000.0, 49.5, -6233.074218763621, -5990.775000004327 - 0.1, 43000.0, 50.0, -6301.200000016598, -5449.500000004846 - 0.1, 48000.0, 0.0, 75.48647655065139, 75.48647655065139 - 0.1, 48000.0, 22.0, -561.0000000000256, 820.9999999999125 - 0.1, 48000.0, 22.5, -562.5166015625147, 345.61914062490877 - 0.1, 48000.0, 23.0, -584.1046874999904, -40.75312500009846 - 0.1, 48000.0, 23.5, -623.215429687453, -350.3238281251101 - 0.1, 48000.0, 24.0, -677.2999999999032, -595.3000000001259 - 0.1, 48000.0, 24.5, -743.809570312341, -787.8886718751472 - 0.1, 48000.0, 25.0, -820.195312499767, -940.2968750001749 - 0.1, 48000.0, 25.5, -903.9083984371813, -1064.7316406252075 - 0.1, 48000.0, 26.0, -992.3999999995847, -1173.4000000002466 - 0.1, 48000.0, 26.5, -1064.8857421876241, -1410.577929687599 - 0.1, 48000.0, 27.0, -1136.0103125001187, -1663.9503125001152 - 0.1, 48000.0, 27.5, -1206.3509765626077, -1923.0837890626299 - 0.1, 48000.0, 28.0, -1276.4850000000913, -2177.545000000143 - 0.1, 48000.0, 28.5, -1346.9896484375695, -2416.900585937653 - 0.1, 48000.0, 29.0, -1418.442187500044, -2630.71718750016 - 0.1, 48000.0, 29.5, -1491.419882812512, -2808.5614453126623 - 0.1, 48000.0, 30.0, -1566.499999999977, -2940.00000000016 - 0.1, 48000.0, 30.5, -1656.4221679691339, -2885.913378906751 - 0.1, 48000.0, 31.0, -1748.442968750473, -2776.8101562506076 - 0.1, 48000.0, 31.5, -1841.981347656822, -2614.5127929694804 - 0.1, 48000.0, 32.0, -1936.4562500006812, -2400.843750000865 - 0.1, 48000.0, 32.5, -2031.2866210945494, -2137.6254882822636 - 0.1, 48000.0, 33.0, -2125.8914062509284, -1826.680468751178 - 0.1, 48000.0, 33.5, -2219.6895507823165, -1469.8311523451061 - 0.1, 48000.0, 34.0, -2312.100000001215, -1068.9000000015544 - 0.1, 48000.0, 34.5, -2381.527343750565, 17.03367187429285 - 0.1, 48000.0, 35.0, -2450.4062500006216, 1082.190624999148 - 0.1, 48000.0, 35.5, -2520.157031250684, 2063.534765623981 - 0.1, 48000.0, 36.0, -2592.2000000007547, 2898.0299999987783 - 0.1, 48000.0, 36.5, -2667.955468750836, 3522.64023437355 - 0.1, 48000.0, 37.0, -2748.843750000931, 3874.3293749982804 - 0.1, 48000.0, 37.5, -2836.285156251041, 3890.0613281229853 - 0.1, 48000.0, 38.0, -2931.7000000011703, 3506.7999999976273 - 0.1, 48000.0, 38.5, -3074.8570312466536, 1877.3501953117302 - 0.1, 48000.0, 39.0, -3208.9437499959904, 129.4359374991909 - 0.1, 48000.0, 39.5, -3326.8585937452303, -1625.7212890633164 - 0.1, 48000.0, 40.0, -3421.499999994364, -3276.900000000802 - 0.1, 48000.0, 40.5, -3426.8992187507292, -4507.4460937507665 - 0.1, 48000.0, 41.0, -3418.368750000908, -5493.743750000955 - 0.1, 48000.0, 41.5, -3412.353906251097, -6206.744531251151 - 0.1, 48000.0, 42.0, -3425.3000000013035, -6617.400000001359 - 0.1, 48000.0, 42.5, -3549.210937500538, -6391.700781249289 - 0.1, 48000.0, 43.0, -3694.7500000006585, -5927.54374999916 - 0.1, 48000.0, 43.5, -3848.139062500791, -5317.864843749055 - 0.1, 48000.0, 44.0, -3995.6000000009417, -4655.599999999 - 0.1, 48000.0, 44.5, -4072.311718749634, -4191.946875001186 - 0.1, 48000.0, 45.0, -4135.956249999479, -3798.275000001511 - 0.1, 48000.0, 45.5, -4193.172656249306, -3504.215625001856 - 0.1, 48000.0, 46.0, -4250.599999999123, -3339.4000000022206 - 0.1, 48000.0, 46.5, -4335.435937499886, -3568.3031249994383 - 0.1, 48000.0, 47.0, -4425.5375000000395, -3891.7749999993252 - 0.1, 48000.0, 47.5, -4519.320312500167, -4245.5093749991875 - 0.1, 48000.0, 48.0, -4615.200000000245, -4565.199999999017 - 0.1, 48000.0, 48.5, -4711.592187500246, -4786.540624998803 - 0.1, 48000.0, 49.0, -4806.9125000001495, -4845.224999998543 - 0.1, 48000.0, 49.5, -4899.57656249993, -4676.946874998228 - 0.1, 48000.0, 50.0, -4987.999999999562, -4217.399999997851 - 0.15000000000000002, 0.0, 0.0, 523.3561564542483, 523.3561564542483 - 0.15000000000000002, 0.0, 22.0, 1659.2050000000022, 830.4200000000006 - 0.15000000000000002, 0.0, 22.5, 1974.0514160156306, 914.3309277343772 - 0.15000000000000002, 0.0, 23.0, 2285.6705468750088, 997.6969531250033 - 0.15000000000000002, 0.0, 23.5, 2595.1406542968843, 1080.8832519531297 - 0.15000000000000002, 0.0, 24.0, 2903.540000000012, 1164.255000000006 - 0.15000000000000002, 0.0, 24.5, 3211.9468457031385, 1248.1773730468822 - 0.15000000000000002, 0.0, 25.0, 3521.439453125014, 1333.0155468750086 - 0.15000000000000002, 0.0, 25.5, 3833.096083984389, 1419.134697265635 - 0.15000000000000002, 0.0, 26.0, 4147.9950000000135, 1506.9000000000117 - 0.15000000000000002, 0.0, 26.5, 4478.542226562509, 1600.4443261718752 - 0.15000000000000002, 0.0, 27.0, 4815.135562500008, 1696.5804531250005 - 0.15000000000000002, 0.0, 27.5, 5156.911367187505, 1795.027666015625 - 0.15000000000000002, 0.0, 28.0, 5503.006000000002, 1895.5052499999995 - 0.15000000000000002, 0.0, 28.5, 5852.555820312497, 1997.7324902343744 - 0.15000000000000002, 0.0, 29.0, 6204.697187499994, 2101.428671874999 - 0.15000000000000002, 0.0, 29.5, 6558.566460937489, 2206.3130800781237 - 0.15000000000000002, 0.0, 30.0, 6913.299999999981, 2312.104999999997 - 0.15000000000000002, 0.0, 30.5, 7258.96716796876, 2415.6472705078095 - 0.15000000000000002, 0.0, 31.0, 7604.634843750013, 2519.809570312498 - 0.15000000000000002, 0.0, 31.5, 7950.302910156263, 2624.5851318359346 - 0.15000000000000002, 0.0, 32.0, 8295.971250000015, 2729.9671874999954 - 0.15000000000000002, 0.0, 32.5, 8641.639746093768, 2835.9489697265585 - 0.15000000000000002, 0.0, 33.0, 8987.30828125002, 2942.523710937495 - 0.15000000000000002, 0.0, 33.5, 9332.976738281272, 3049.684643554681 - 0.15000000000000002, 0.0, 34.0, 9678.645000000022, 3157.424999999992 - 0.15000000000000002, 0.0, 34.5, 10024.31204687505, 3266.3913710937422 - 0.15000000000000002, 0.0, 35.0, 10369.978750000048, 3375.8614062499914 - 0.15000000000000002, 0.0, 35.5, 10715.64507812505, 3485.766113281241 - 0.15000000000000002, 0.0, 36.0, 11061.311000000049, 3596.036499999991 - 0.15000000000000002, 0.0, 36.5, 11406.976484375047, 3706.60357421874 - 0.15000000000000002, 0.0, 37.0, 11752.641500000049, 3817.3983437499905 - 0.15000000000000002, 0.0, 37.5, 12098.306015625045, 3928.3518164062393 - 0.15000000000000002, 0.0, 38.0, 12443.970000000038, 4039.394999999989 - 0.15000000000000002, 0.0, 38.5, 12789.631787109114, 4150.787490234365 - 0.15000000000000002, 0.0, 39.0, 13135.293828124672, 4261.961328124981 - 0.15000000000000002, 0.0, 39.5, 13480.956455077712, 4372.774501953095 - 0.15000000000000002, 0.0, 40.0, 13826.619999999495, 4483.08499999996 - 0.15000000000000002, 0.0, 40.5, 14172.286210937478, 4591.71824218749 - 0.15000000000000002, 0.0, 41.0, 14517.953437499964, 4699.977812499986 - 0.15000000000000002, 0.0, 41.5, 14863.621445312452, 4808.134726562479 - 0.15000000000000002, 0.0, 42.0, 15209.289999999939, 4916.459999999974 - 0.15000000000000002, 0.0, 42.5, 15554.689335937519, 5026.352187500042 - 0.15000000000000002, 0.0, 43.0, 15900.196562500005, 5136.503750000056 - 0.15000000000000002, 0.0, 43.5, 16245.919257812493, 5246.734687500068 - 0.15000000000000002, 0.0, 44.0, 16591.964999999967, 5356.865000000083 - 0.15000000000000002, 0.0, 44.5, 16939.51871093755, 5466.124843750009 - 0.15000000000000002, 0.0, 45.0, 17287.179687500084, 5575.160000000011 - 0.15000000000000002, 0.0, 45.5, 17634.624570312626, 5684.026406250011 - 0.15000000000000002, 0.0, 46.0, 17981.530000000166, 5792.780000000013 - 0.15000000000000002, 0.0, 46.5, 18325.957773437665, 5900.973984375014 - 0.15000000000000002, 0.0, 47.0, 18669.8453125002, 6009.368125000013 - 0.15000000000000002, 0.0, 47.5, 19013.515195312735, 6118.2194531250125 - 0.15000000000000002, 0.0, 48.0, 19357.290000000285, 6227.78500000001 - 0.15000000000000002, 0.0, 48.5, 19701.492304687836, 6338.321796875004 - 0.15000000000000002, 0.0, 49.0, 20046.444687500378, 6450.086875 - 0.15000000000000002, 0.0, 49.5, 20392.469726562955, 6563.337265624996 - 0.15000000000000002, 0.0, 50.0, 20739.89000000051, 6678.329999999987 - 0.15000000000000002, 2000.0, 0.0, 490.00253840716675, 490.00253840716675 - 0.15000000000000002, 2000.0, 22.0, 1599.2399999999998, 787.6950000000008 - 0.15000000000000002, 2000.0, 22.5, 1902.7292773437498, 869.2443847656264 - 0.15000000000000002, 2000.0, 23.0, 2203.1032812499993, 949.8636718750025 - 0.15000000000000002, 2000.0, 23.5, 2501.4018945312487, 1029.964873046879 - 0.15000000000000002, 2000.0, 24.0, 2798.6649999999977, 1109.9600000000053 - 0.15000000000000002, 2000.0, 24.5, 3095.9324804687462, 1190.261064453132 - 0.15000000000000002, 2000.0, 25.0, 3394.244218749995, 1271.2800781250094 - 0.15000000000000002, 2000.0, 25.5, 3694.6400976562427, 1353.4290527343865 - 0.15000000000000002, 2000.0, 26.0, 3998.159999999991, 1437.1200000000138 - 0.15000000000000002, 2000.0, 26.5, 4316.765449218761, 1526.7984765625026 - 0.15000000000000002, 2000.0, 27.0, 4641.198781250012, 1619.0734375000031 - 0.15000000000000002, 2000.0, 27.5, 4970.627597656265, 1713.665429687504 - 0.15000000000000002, 2000.0, 28.0, 5304.219500000015, 1810.2950000000048 - 0.15000000000000002, 2000.0, 28.5, 5641.142089843767, 1908.6826953125064 - 0.15000000000000002, 2000.0, 29.0, 5980.562968750016, 2008.5490625000073 - 0.15000000000000002, 2000.0, 29.5, 6321.649738281269, 2109.614648437508 - 0.15000000000000002, 2000.0, 30.0, 6663.570000000015, 2211.6000000000095 - 0.15000000000000002, 2000.0, 30.5, 6996.754042968771, 2311.4825390625106 - 0.15000000000000002, 2000.0, 31.0, 7329.938906250022, 2411.9871875000126 - 0.15000000000000002, 2000.0, 31.5, 7663.124316406275, 2513.0957421875155 - 0.15000000000000002, 2000.0, 32.0, 7996.310000000028, 2614.790000000018 - 0.15000000000000002, 2000.0, 32.5, 8329.49568359378, 2717.0517578125205 - 0.15000000000000002, 2000.0, 33.0, 8662.681093750036, 2819.862812500024 - 0.15000000000000002, 2000.0, 33.5, 8995.865957031288, 2923.204960937528 - 0.15000000000000002, 2000.0, 34.0, 9329.050000000041, 3027.0600000000327 - 0.15000000000000002, 2000.0, 34.5, 9662.230324218817, 3131.8648359375006 - 0.15000000000000002, 2000.0, 35.0, 9995.409531250085, 3237.1028125 - 0.15000000000000002, 2000.0, 35.5, 10328.587597656353, 3342.7123828125 - 0.15000000000000002, 2000.0, 36.0, 10661.764500000118, 3448.6320000000005 - 0.15000000000000002, 2000.0, 36.5, 10994.940214843891, 3554.8001171875 - 0.15000000000000002, 2000.0, 37.0, 11328.114718750161, 3661.155187499998 - 0.15000000000000002, 2000.0, 37.5, 11661.287988281434, 3767.6356640624977 - 0.15000000000000002, 2000.0, 38.0, 11994.460000000206, 3874.179999999996 - 0.15000000000000002, 2000.0, 38.5, 12327.62930664031, 3981.229101562511 - 0.15000000000000002, 2000.0, 39.0, 12660.798046874605, 4087.9584375000136 - 0.15000000000000002, 2000.0, 39.5, 12993.966513671388, 4194.194804687516 - 0.15000000000000002, 2000.0, 40.0, 13327.13499999941, 4299.765000000017 - 0.15000000000000002, 2000.0, 40.5, 13660.30179687505, 4403.09484375002 - 0.15000000000000002, 2000.0, 41.0, 13993.47000000006, 4505.972500000024 - 0.15000000000000002, 2000.0, 41.5, 14326.640703125058, 4608.78515625003 - 0.15000000000000002, 2000.0, 42.0, 14659.815000000055, 4711.920000000034 - 0.15000000000000002, 2000.0, 42.5, 14992.740468750006, 4817.585898437517 - 0.15000000000000002, 2000.0, 43.0, 15325.773125000009, 4923.619687500025 - 0.15000000000000002, 2000.0, 43.5, 15659.015468750013, 5029.679882812533 - 0.15000000000000002, 2000.0, 44.0, 15992.570000000018, 5135.425000000043 - 0.15000000000000002, 2000.0, 44.5, 16327.574960937678, 5238.916093750007 - 0.15000000000000002, 2000.0, 45.0, 16662.682812500232, 5342.0481250000075 - 0.15000000000000002, 2000.0, 45.5, 16997.581757812786, 5445.1185937500095 - 0.15000000000000002, 2000.0, 46.0, 17331.96000000036, 5548.425000000009 - 0.15000000000000002, 2000.0, 46.5, 17663.95066406243, 5652.7779296875315 - 0.15000000000000002, 2000.0, 47.0, 17995.419062499903, 5757.756562500048 - 0.15000000000000002, 2000.0, 47.5, 18326.675429687377, 5863.453164062563 - 0.15000000000000002, 2000.0, 48.0, 18658.029999999835, 5969.960000000084 - 0.15000000000000002, 2000.0, 48.5, 18989.7930078123, 6077.3693359376075 - 0.15000000000000002, 2000.0, 49.0, 19322.274687499754, 6185.773437500135 - 0.15000000000000002, 2000.0, 49.5, 19655.78527343721, 6295.264570312662 - 0.15000000000000002, 2000.0, 50.0, 19990.63499999966, 6405.935000000197 - 0.15000000000000002, 5000.0, 0.0, 443.14149535407853, 443.14149535407853 - 0.15000000000000002, 5000.0, 22.0, 1519.0600000000009, 690.835 - 0.15000000000000002, 5000.0, 22.5, 1807.2966406249996, 769.9934082031251 - 0.15000000000000002, 5000.0, 23.0, 2092.585624999999, 842.7546093749999 - 0.15000000000000002, 5000.0, 23.5, 2375.9130468749963, 910.7010058593743 - 0.15000000000000002, 5000.0, 24.0, 2658.2649999999944, 975.4149999999985 - 0.15000000000000002, 5000.0, 24.5, 2940.6275781249933, 1038.4789941406223 - 0.15000000000000002, 5000.0, 25.0, 3223.9868749999914, 1101.4753906249953 - 0.15000000000000002, 5000.0, 25.5, 3509.328984374988, 1165.9865917968689 - 0.15000000000000002, 5000.0, 26.0, 3797.639999999985, 1233.594999999992 - 0.15000000000000002, 5000.0, 26.5, 4100.268681640628, 1321.9797363281293 - 0.15000000000000002, 5000.0, 27.0, 4408.430609375002, 1417.5462968750048 - 0.15000000000000002, 5000.0, 27.5, 4721.335419921874, 1519.1176464843802 - 0.15000000000000002, 5000.0, 28.0, 5038.192749999997, 1625.5167500000061 - 0.15000000000000002, 5000.0, 28.5, 5358.2122363281205, 1735.566572265632 - 0.15000000000000002, 5000.0, 29.0, 5680.603515624994, 1848.0900781250084 - 0.15000000000000002, 5000.0, 29.5, 6004.576224609365, 1961.910232421885 - 0.15000000000000002, 5000.0, 30.0, 6329.339999999987, 2075.8500000000113 - 0.15000000000000002, 5000.0, 30.5, 6645.808637695352, 2174.4269775390676 - 0.15000000000000002, 5000.0, 31.0, 6962.277695312547, 2272.1319140625064 - 0.15000000000000002, 5000.0, 31.5, 7278.746889648492, 2369.1501904296942 - 0.15000000000000002, 5000.0, 32.0, 7595.215937500061, 2465.6671875000065 - 0.15000000000000002, 5000.0, 32.5, 7911.684555664131, 2561.868286132819 - 0.15000000000000002, 5000.0, 33.0, 8228.152460937576, 2657.938867187507 - 0.15000000000000002, 5000.0, 33.5, 8544.619370117272, 2754.0643115234457 - 0.15000000000000002, 5000.0, 34.0, 8861.085000000092, 2850.43000000001 - 0.15000000000000002, 5000.0, 34.5, 9177.536906249994, 2950.6027031250155 - 0.15000000000000002, 5000.0, 35.0, 9493.988124999996, 3051.064375000019 - 0.15000000000000002, 5000.0, 35.5, 9810.439531250007, 3151.6783593750265 - 0.15000000000000002, 5000.0, 36.0, 10126.892000000013, 3252.308000000032 - 0.15000000000000002, 5000.0, 36.5, 10443.346406250024, 3352.816640625039 - 0.15000000000000002, 5000.0, 37.0, 10759.80362500003, 3453.067625000046 - 0.15000000000000002, 5000.0, 37.5, 11076.264531250046, 3552.9242968750536 - 0.15000000000000002, 5000.0, 38.0, 11392.730000000054, 3652.250000000063 - 0.15000000000000002, 5000.0, 38.5, 11709.210029296764, 3749.4611523437216 - 0.15000000000000002, 5000.0, 39.0, 12025.691640624855, 3846.618281249962 - 0.15000000000000002, 5000.0, 39.5, 12342.173681640441, 3943.9062695312014 - 0.15000000000000002, 5000.0, 40.0, 12658.65499999977, 4041.509999999939 - 0.15000000000000002, 5000.0, 40.5, 12975.134101562591, 4140.766015625006 - 0.15000000000000002, 5000.0, 41.0, 13291.610312500114, 4240.246875000011 - 0.15000000000000002, 5000.0, 41.5, 13608.082617187649, 4339.676796875014 - 0.15000000000000002, 5000.0, 42.0, 13924.550000000185, 4438.780000000018 - 0.15000000000000002, 5000.0, 42.5, 14240.751875000042, 4535.899453125026 - 0.15000000000000002, 5000.0, 43.0, 14557.050625000045, 4632.693125000033 - 0.15000000000000002, 5000.0, 43.5, 14873.54906250005, 4729.437734375042 - 0.15000000000000002, 5000.0, 44.0, 15190.350000000053, 4826.410000000046 - 0.15000000000000002, 5000.0, 44.5, 15508.566601562494, 4924.546601562519 - 0.15000000000000002, 5000.0, 45.0, 15826.887187499995, 5023.2003125000265 - 0.15000000000000002, 5000.0, 45.5, 16145.010429687502, 5122.383867187536 - 0.15000000000000002, 5000.0, 46.0, 16462.63500000001, 5222.110000000045 - 0.15000000000000002, 5000.0, 46.5, 16777.956640625216, 5322.237148437524 - 0.15000000000000002, 5000.0, 47.0, 17092.778125000266, 5422.994062500034 - 0.15000000000000002, 5000.0, 47.5, 17407.39929687533, 5524.455195312544 - 0.15000000000000002, 5000.0, 48.0, 17722.12000000041, 5626.695000000058 - 0.15000000000000002, 5000.0, 48.5, 18037.240078125487, 5729.787929687572 - 0.15000000000000002, 5000.0, 49.0, 18353.059375000572, 5833.808437500088 - 0.15000000000000002, 5000.0, 49.5, 18669.877734375666, 5938.830976562605 - 0.15000000000000002, 5000.0, 50.0, 18987.995000000763, 6044.930000000126 - 0.15000000000000002, 10000.0, 0.0, 372.96693542129486, 372.96693542129486 - 0.15000000000000002, 10000.0, 22.0, 1376.7249999999995, 636.4249999999997 - 0.15000000000000002, 10000.0, 22.5, 1638.0513183593744, 709.6599121093748 - 0.15000000000000002, 10000.0, 23.0, 1896.683203125, 781.2769531249997 - 0.15000000000000002, 10000.0, 23.5, 2153.5172363281254, 851.7305175781246 - 0.15000000000000002, 10000.0, 24.0, 2409.4500000000016, 921.4749999999997 - 0.15000000000000002, 10000.0, 24.5, 2665.378076171876, 990.9647949218743 - 0.15000000000000002, 10000.0, 25.0, 2922.1980468750025, 1060.6542968749993 - 0.15000000000000002, 10000.0, 25.5, 3180.8064941406287, 1130.9979003906242 - 0.15000000000000002, 10000.0, 26.0, 3442.100000000006, 1202.4499999999991 - 0.15000000000000002, 10000.0, 26.5, 3716.381054687501, 1279.6660156249998 - 0.15000000000000002, 10000.0, 27.0, 3995.6778125000023, 1359.1393749999997 - 0.15000000000000002, 10000.0, 27.5, 4279.274414062504, 1440.604296875 - 0.15000000000000002, 10000.0, 28.0, 4566.455000000005, 1523.7949999999996 - 0.15000000000000002, 10000.0, 28.5, 4856.503710937506, 1608.4457031250001 - 0.15000000000000002, 10000.0, 29.0, 5148.704687500009, 1694.2906250000003 - 0.15000000000000002, 10000.0, 29.5, 5442.342070312511, 1781.063984375 - 0.15000000000000002, 10000.0, 30.0, 5736.7000000000135, 1868.5 - 0.15000000000000002, 10000.0, 30.5, 6023.556347656252, 1953.5104003906254 - 0.15000000000000002, 10000.0, 31.0, 6310.416406250002, 2038.9207031250007 - 0.15000000000000002, 10000.0, 31.5, 6597.279199218754, 2124.733935546876 - 0.15000000000000002, 10000.0, 32.0, 6884.143750000005, 2210.953125 - 0.15000000000000002, 10000.0, 32.5, 7171.009082031257, 2297.581298828126 - 0.15000000000000002, 10000.0, 33.0, 7457.874218750009, 2384.621484375001 - 0.15000000000000002, 10000.0, 33.5, 7744.73818359376, 2472.076708984376 - 0.15000000000000002, 10000.0, 34.0, 8031.600000000013, 2559.950000000002 - 0.15000000000000002, 10000.0, 34.5, 8318.435312500058, 2649.5940039062557 - 0.15000000000000002, 10000.0, 35.0, 8605.268750000072, 2739.533593750007 - 0.15000000000000002, 10000.0, 35.5, 8892.101562500091, 2829.6432617187584 - 0.15000000000000002, 10000.0, 36.0, 9178.935000000103, 2919.797500000011 - 0.15000000000000002, 10000.0, 36.5, 9465.770312500126, 3009.8708007812625 - 0.15000000000000002, 10000.0, 37.0, 9752.608750000147, 3099.737656250014 - 0.15000000000000002, 10000.0, 37.5, 10039.451562500166, 3189.272558593767 - 0.15000000000000002, 10000.0, 38.0, 10326.300000000196, 3278.3500000000195 - 0.15000000000000002, 10000.0, 38.5, 10613.177197265515, 3366.2309082030806 - 0.15000000000000002, 10000.0, 39.0, 10900.051171874866, 3453.721484374948 - 0.15000000000000002, 10000.0, 39.5, 11186.918310546713, 3540.8325683593143 - 0.15000000000000002, 10000.0, 40.0, 11473.774999999807, 3627.57499999993 - 0.15000000000000002, 10000.0, 40.5, 11760.595898437485, 3713.187890624998 - 0.15000000000000002, 10000.0, 41.0, 12047.40781249999, 3798.7624999999957 - 0.15000000000000002, 10000.0, 41.5, 12334.21582031249, 3884.6183593749934 - 0.15000000000000002, 10000.0, 42.0, 12621.024999999992, 3971.0749999999903 - 0.15000000000000002, 10000.0, 42.5, 12907.634374999961, 4059.447070312489 - 0.15000000000000002, 10000.0, 43.0, 13194.337499999945, 4148.660937499987 - 0.15000000000000002, 10000.0, 43.5, 13481.221874999927, 4238.638085937483 - 0.15000000000000002, 10000.0, 44.0, 13768.374999999902, 4329.299999999978 - 0.15000000000000002, 10000.0, 44.5, 14056.769140625016, 4420.393359374997 - 0.15000000000000002, 10000.0, 45.0, 14345.253125000023, 4512.084374999997 - 0.15000000000000002, 10000.0, 45.5, 14633.560546875025, 4604.364453124998 - 0.15000000000000002, 10000.0, 46.0, 14921.425000000036, 4697.224999999997 - 0.15000000000000002, 10000.0, 46.5, 15207.252929687445, 4790.192578124985 - 0.15000000000000002, 10000.0, 47.0, 15492.635937499937, 4883.90937499998 - 0.15000000000000002, 10000.0, 47.5, 15777.838476562434, 4978.552734374972 - 0.15000000000000002, 10000.0, 48.0, 16063.124999999929, 5074.299999999964 - 0.15000000000000002, 10000.0, 48.5, 16348.759960937428, 5171.328515624956 - 0.15000000000000002, 10000.0, 49.0, 16635.007812499935, 5269.815624999947 - 0.15000000000000002, 10000.0, 49.5, 16922.13300781244, 5369.938671874937 - 0.15000000000000002, 10000.0, 50.0, 17210.399999999958, 5471.874999999925 - 0.15000000000000002, 15000.0, 0.0, 311.87249435615803, 311.87249435615803 - 0.15000000000000002, 15000.0, 22.0, -2648.899999999987, -762.9999999999952 - 0.15000000000000002, 15000.0, 22.5, -3152.1757812499827, -946.0626953124964 - 0.15000000000000002, 15000.0, 23.0, -3650.031249999981, -1119.8609374999985 - 0.15000000000000002, 15000.0, 23.5, -4144.2210937499785, -1286.703710937501 - 0.15000000000000002, 15000.0, 24.0, -4636.499999999976, -1448.9000000000042 - 0.15000000000000002, 15000.0, 24.5, -5128.622656249975, -1608.7587890625073 - 0.15000000000000002, 15000.0, 25.0, -5622.343749999977, -1768.589062500011 - 0.15000000000000002, 15000.0, 25.5, -6119.417968749978, -1930.699804687516 - 0.15000000000000002, 15000.0, 26.0, -6621.599999999978, -2097.400000000021 - 0.15000000000000002, 15000.0, 26.5, -7148.856835937488, -2283.7052734374956 - 0.15000000000000002, 15000.0, 27.0, -7685.771562499993, -2479.9440624999934 - 0.15000000000000002, 15000.0, 27.5, -8230.976757812497, -2686.247070312491 - 0.15000000000000002, 15000.0, 28.0, -8783.105000000005, -2902.744999999987 - 0.15000000000000002, 15000.0, 28.5, -9340.788867187512, -3129.5685546874834 - 0.15000000000000002, 15000.0, 29.0, -9902.660937500023, -3366.8484374999794 - 0.15000000000000002, 15000.0, 29.5, -10467.353789062528, -3614.715351562476 - 0.15000000000000002, 15000.0, 30.0, -11033.50000000004, -3873.2999999999734 - 0.15000000000000002, 15000.0, 30.5, -11585.599804687525, -4177.9084960937425 - 0.15000000000000002, 15000.0, 31.0, -12137.764062500028, -4490.146093749994 - 0.15000000000000002, 15000.0, 31.5, -12689.97128906253, -4806.793457031244 - 0.15000000000000002, 15000.0, 32.0, -13242.200000000033, -5124.631249999992 - 0.15000000000000002, 15000.0, 32.5, -13794.42871093754, -5440.440136718743 - 0.15000000000000002, 15000.0, 33.0, -14346.635937500045, -5751.000781249992 - 0.15000000000000002, 15000.0, 33.5, -14898.800195312551, -6053.09384765624 - 0.15000000000000002, 15000.0, 34.0, -15450.900000000054, -6343.499999999987 - 0.15000000000000002, 15000.0, 34.5, -16002.136210937382, -6533.7304687499345 - 0.15000000000000002, 15000.0, 35.0, -16553.33906249988, -6713.956249999924 - 0.15000000000000002, 15000.0, 35.5, -17104.561132812378, -6889.0789062499125 - 0.15000000000000002, 15000.0, 36.0, -17655.854999999883, -7063.999999999901 - 0.15000000000000002, 15000.0, 36.5, -18207.273242187377, -7243.621093749886 - 0.15000000000000002, 15000.0, 37.0, -18758.868437499874, -7432.843749999873 - 0.15000000000000002, 15000.0, 37.5, -19310.69316406238, -7636.569531249855 - 0.15000000000000002, 15000.0, 38.0, -19862.79999999988, -7859.699999999837 - 0.15000000000000002, 15000.0, 38.5, -20415.996679686887, -8137.875585937302 - 0.15000000000000002, 15000.0, 39.0, -20969.18906249926, -8429.320312499769 - 0.15000000000000002, 15000.0, 39.5, -21522.26191406163, -8732.104882812233 - 0.15000000000000002, 15000.0, 40.0, -22075.09999999896, -9044.299999999696 - 0.15000000000000002, 15000.0, 40.5, -22627.139843749905, -9355.801562500059 - 0.15000000000000002, 15000.0, 41.0, -23178.893749999905, -9676.125000000082 - 0.15000000000000002, 15000.0, 41.5, -23730.42578124991, -10006.610937500112 - 0.15000000000000002, 15000.0, 42.0, -24281.79999999992, -10348.600000000148 - 0.15000000000000002, 15000.0, 42.5, -24832.732812499802, -10724.624218749927 - 0.15000000000000002, 15000.0, 43.0, -25383.774999999758, -11106.356249999908 - 0.15000000000000002, 15000.0, 43.5, -25935.129687499713, -11486.660156249887 - 0.15000000000000002, 15000.0, 44.0, -26486.999999999665, -11858.39999999987 - 0.15000000000000002, 15000.0, 44.5, -27041.526562500007, -12171.721093750033 - 0.15000000000000002, 15000.0, 45.0, -27596.200000000026, -12479.293750000055 - 0.15000000000000002, 15000.0, 45.5, -28150.44843750004, -12791.069531250077 - 0.15000000000000002, 15000.0, 46.0, -28703.700000000037, -13117.000000000106 - 0.15000000000000002, 15000.0, 46.5, -29252.343750000084, -13495.587499999852 - 0.15000000000000002, 15000.0, 47.0, -29800.06250000011, -13896.812499999827 - 0.15000000000000002, 15000.0, 47.5, -30347.50000000014, -14319.206249999806 - 0.15000000000000002, 15000.0, 48.0, -30895.30000000018, -14761.299999999788 - 0.15000000000000002, 15000.0, 48.5, -31444.106250000223, -15221.624999999774 - 0.15000000000000002, 15000.0, 49.0, -31994.56250000028, -15698.712499999756 - 0.15000000000000002, 15000.0, 49.5, -32547.31250000035, -16191.093749999753 - 0.15000000000000002, 15000.0, 50.0, -33103.00000000044, -16697.29999999975 - 0.15000000000000002, 20000.0, 0.0, 258.9696392668553, 258.9696392668553 - 0.15000000000000002, 20000.0, 22.0, 886.8999999999807, 369.3000000000022 - 0.15000000000000002, 20000.0, 22.5, 1062.82558593746, 537.8068359374985 - 0.15000000000000002, 20000.0, 23.0, 1235.1703124999372, 648.3078124999917 - 0.15000000000000002, 20000.0, 23.5, 1404.804882812413, 709.6548828124818 - 0.15000000000000002, 20000.0, 24.0, 1572.5999999998864, 730.6999999999692 - 0.15000000000000002, 20000.0, 24.5, 1739.426367187356, 720.2951171874536 - 0.15000000000000002, 20000.0, 25.0, 1906.1546874998212, 687.2921874999347 - 0.15000000000000002, 20000.0, 25.5, 2073.6556640622816, 640.5431640624132 - 0.15000000000000002, 20000.0, 26.0, 2242.7999999997364, 588.8999999998891 - 0.15000000000000002, 20000.0, 26.5, 2423.3205078124683, 607.3441406249392 - 0.15000000000000002, 20000.0, 27.0, 2607.7321874999666, 642.3768749999323 - 0.15000000000000002, 20000.0, 27.5, 2795.3865234374684, 691.5136718749269 - 0.15000000000000002, 20000.0, 28.0, 2985.6349999999693, 752.2699999999228 - 0.15000000000000002, 20000.0, 28.5, 3177.829101562471, 822.1613281249199 - 0.15000000000000002, 20000.0, 29.0, 3371.320312499973, 898.7031249999185 - 0.15000000000000002, 20000.0, 29.5, 3565.4601171874756, 979.4108593749183 - 0.15000000000000002, 20000.0, 30.0, 3759.599999999978, 1061.79999999992 - 0.15000000000000002, 20000.0, 30.5, 3944.4650390623956, 1106.7143554686668 - 0.15000000000000002, 20000.0, 31.0, 4128.854687499883, 1151.8335937498969 - 0.15000000000000002, 20000.0, 31.5, 4312.9419921873705, 1198.1657226561256 - 0.15000000000000002, 20000.0, 32.0, 4496.899999999864, 1246.7187499998515 - 0.15000000000000002, 20000.0, 32.5, 4680.901757812364, 1298.500683593576 - 0.15000000000000002, 20000.0, 33.0, 4865.120312499868, 1354.5195312497979 - 0.15000000000000002, 20000.0, 33.5, 5049.728710937378, 1415.7833007810182 - 0.15000000000000002, 20000.0, 34.0, 5234.899999999895, 1483.2999999997364 - 0.15000000000000002, 20000.0, 34.5, 5425.67332031129, 1632.5648828119515 - 0.15000000000000002, 20000.0, 35.0, 5616.8921874985845, 1783.004687499341 - 0.15000000000000002, 20000.0, 35.5, 5808.266210935863, 1928.5333984367153 - 0.15000000000000002, 20000.0, 36.0, 5999.504999998122, 2063.064999999074 - 0.15000000000000002, 20000.0, 36.5, 6190.318164060362, 2180.5134765614157 - 0.15000000000000002, 20000.0, 37.0, 6380.415312497582, 2274.7928124987375 - 0.15000000000000002, 20000.0, 37.5, 6569.50605468478, 2339.816992186041 - 0.15000000000000002, 20000.0, 38.0, 6757.299999996954, 2369.499999998322 - 0.15000000000000002, 20000.0, 38.5, 6940.449218750074, 2273.0623046878422 - 0.15000000000000002, 20000.0, 39.0, 7123.3062500002525, 2173.0265625004704 - 0.15000000000000002, 20000.0, 39.5, 7306.260156250462, 2082.127539063118 - 0.15000000000000002, 20000.0, 40.0, 7489.700000000706, 2013.1000000007837 - 0.15000000000000002, 20000.0, 40.5, 7675.61249999967, 2020.8281250001817 - 0.15000000000000002, 20000.0, 41.0, 7862.149999999532, 2059.0375000002377 - 0.15000000000000002, 20000.0, 41.5, 8049.062499999338, 2123.6031250003102 - 0.15000000000000002, 20000.0, 42.0, 8236.099999999074, 2210.400000000402 - 0.15000000000000002, 20000.0, 42.5, 8422.430468749499, 2310.41249999957 - 0.15000000000000002, 20000.0, 43.0, 8608.618749999407, 2426.3624999994395 - 0.15000000000000002, 20000.0, 43.5, 8794.647656249315, 2556.0812499992962 - 0.15000000000000002, 20000.0, 44.0, 8980.499999999238, 2697.399999999139 - 0.15000000000000002, 20000.0, 44.5, 9165.264062499633, 2858.583593749718 - 0.15000000000000002, 20000.0, 45.0, 9350.17499999961, 3022.8562499996724 - 0.15000000000000002, 20000.0, 45.5, 9535.573437499603, 3183.875781249611 - 0.15000000000000002, 20000.0, 46.0, 9721.799999999625, 3335.2999999995313 - 0.15000000000000002, 20000.0, 46.5, 9911.167968749613, 3450.3999999998 - 0.15000000000000002, 20000.0, 47.0, 10101.256249999537, 3551.374999999753 - 0.15000000000000002, 20000.0, 47.5, 10291.616406249448, 3640.0374999996984 - 0.15000000000000002, 20000.0, 48.0, 10481.79999999935, 3718.1999999996406 - 0.15000000000000002, 20000.0, 48.5, 10671.358593749243, 3787.674999999581 - 0.15000000000000002, 20000.0, 49.0, 10859.843749999123, 3850.27499999952 - 0.15000000000000002, 20000.0, 49.5, 11046.807031248989, 3907.8124999994593 - 0.15000000000000002, 20000.0, 50.0, 11231.79999999885, 3962.0999999994037 - 0.15000000000000002, 25000.0, 0.0, 213.4206015812585, 213.4206015812585 - 0.15000000000000002, 25000.0, 22.0, 574.5000000000131, 498.30000000001655 - 0.15000000000000002, 25000.0, 22.5, 694.3462890625116, 233.34589843750396 - 0.15000000000000002, 25000.0, 23.0, 810.5296875000046, 98.93281249999731 - 0.15000000000000002, 25000.0, 23.5, 923.8232421874924, 74.52832031249582 - 0.15000000000000002, 25000.0, 24.0, 1034.999999999975, 139.5999999999989 - 0.15000000000000002, 25000.0, 24.5, 1144.833007812455, 273.6154296875053 - 0.15000000000000002, 25000.0, 25.0, 1254.0953124999305, 456.04218750001473 - 0.15000000000000002, 25000.0, 25.5, 1363.5599609374037, 666.3478515625263 - 0.15000000000000002, 25000.0, 26.0, 1473.999999999875, 884.0000000000392 - 0.15000000000000002, 25000.0, 26.5, 1593.7203125000187, 918.9486328125654 - 0.15000000000000002, 25000.0, 27.0, 1716.3925000000097, 910.4921875000821 - 0.15000000000000002, 25000.0, 27.5, 1841.4984374999988, 867.1583984375976 - 0.15000000000000002, 25000.0, 28.0, 1968.5199999999845, 797.4750000001129 - 0.15000000000000002, 25000.0, 28.5, 2096.9390624999683, 709.9697265626278 - 0.15000000000000002, 25000.0, 29.0, 2226.2374999999483, 613.1703125001414 - 0.15000000000000002, 25000.0, 29.5, 2355.897187499929, 515.604492187656 - 0.15000000000000002, 25000.0, 30.0, 2485.3999999999037, 425.800000000169 - 0.15000000000000002, 25000.0, 30.5, 2607.4565429689246, 471.71796875013865 - 0.15000000000000002, 25000.0, 31.0, 2728.964843750238, 531.0781250001885 - 0.15000000000000002, 25000.0, 31.5, 2850.0516601565587, 601.0335937502427 - 0.15000000000000002, 25000.0, 32.0, 2970.8437500003865, 678.7375000003015 - 0.15000000000000002, 25000.0, 32.5, 3091.4678710942203, 761.3429687503657 - 0.15000000000000002, 25000.0, 33.0, 3212.050781250563, 846.0031250004338 - 0.15000000000000002, 25000.0, 33.5, 3332.7192382819107, 929.8710937505061 - 0.15000000000000002, 25000.0, 34.0, 3453.600000000766, 1010.1000000005811 - 0.15000000000000002, 25000.0, 34.5, 3577.3968359384517, 969.677617187512 - 0.15000000000000002, 25000.0, 35.0, 3701.4140625011482, 930.795312499987 - 0.15000000000000002, 25000.0, 35.5, 3825.5330078138577, 901.4791015624576 - 0.15000000000000002, 25000.0, 36.0, 3949.635000001581, 889.754999999924 - 0.15000000000000002, 25000.0, 36.5, 4073.6013671893134, 903.649023437386 - 0.15000000000000002, 25000.0, 37.0, 4197.313437502056, 951.1871874998415 - 0.15000000000000002, 25000.0, 37.5, 4320.652539064809, 1040.3955078122945 - 0.15000000000000002, 25000.0, 38.0, 4443.500000002569, 1179.2999999997458 - 0.15000000000000002, 25000.0, 38.5, 4562.981249999691, 1562.6337890631444 - 0.15000000000000002, 25000.0, 39.0, 4683.1624999995165, 1914.9046875007461 - 0.15000000000000002, 25000.0, 39.5, 4804.53749999934, 2202.6482421883534 - 0.15000000000000002, 25000.0, 40.0, 4927.5999999991645, 2392.4000000009737 - 0.15000000000000002, 25000.0, 40.5, 5057.214843750693, 2271.952343750407 - 0.15000000000000002, 25000.0, 41.0, 5187.756250000946, 2058.0812500005595 - 0.15000000000000002, 25000.0, 41.5, 5317.969531251265, 1788.819531250735 - 0.15000000000000002, 25000.0, 42.0, 5446.60000000165, 1502.2000000009334 - 0.15000000000000002, 25000.0, 42.5, 5565.166406250918, 1315.099218749866 - 0.15000000000000002, 25000.0, 43.0, 5682.531250001337, 1155.1687499998584 - 0.15000000000000002, 25000.0, 43.5, 5800.330468751809, 1028.9039062498516 - 0.15000000000000002, 25000.0, 44.0, 5920.20000000233, 942.7999999998409 - 0.15000000000000002, 25000.0, 44.5, 6053.256250000255, 945.2429687506005 - 0.15000000000000002, 25000.0, 45.0, 6187.862500000524, 984.0812500008265 - 0.15000000000000002, 25000.0, 45.5, 6321.862500000868, 1049.0539062510877 - 0.15000000000000002, 25000.0, 46.0, 6453.100000001296, 1129.900000001384 - 0.15000000000000002, 25000.0, 46.5, 6569.16093750067, 1157.3546875005375 - 0.15000000000000002, 25000.0, 47.0, 6682.250000000764, 1203.7625000007308 - 0.15000000000000002, 25000.0, 47.5, 6794.314062500839, 1282.4640625009622 - 0.15000000000000002, 25000.0, 48.0, 6907.300000000894, 1406.800000001234 - 0.15000000000000002, 25000.0, 48.5, 7023.154687500932, 1590.1109375015483 - 0.15000000000000002, 25000.0, 49.0, 7143.82500000095, 1845.7375000019088 - 0.15000000000000002, 25000.0, 49.5, 7271.257812500951, 2187.020312502317 - 0.15000000000000002, 25000.0, 50.0, 7407.400000000931, 2627.3000000027773 - 0.15000000000000002, 30000.0, 0.0, 174.44634357132938, 174.44634357132938 - 0.15000000000000002, 30000.0, 22.0, 167.80000000000382, 128.99999999996433 - 0.15000000000000002, 30000.0, 22.5, 194.67265625002506, 262.54726562498433 - 0.15000000000000002, 30000.0, 23.0, 223.16875000004998, 310.4593750000076 - 0.15000000000000002, 30000.0, 23.5, 253.18046875008056, 288.09179687503513 - 0.15000000000000002, 30000.0, 24.0, 284.60000000011877, 210.8000000000681 - 0.15000000000000002, 30000.0, 24.5, 317.31953125016696, 93.93945312510773 - 0.15000000000000002, 30000.0, 25.0, 351.23125000022657, -47.13437499984542 - 0.15000000000000002, 30000.0, 25.5, 386.22734375030007, -197.06601562479045 - 0.15000000000000002, 30000.0, 26.0, 422.2000000003893, -340.49999999972476 - 0.15000000000000002, 30000.0, 26.5, 459.4365234374036, -309.6613281250685 - 0.15000000000000002, 30000.0, 27.0, 497.4565624998657, -232.9043750000757 - 0.15000000000000002, 30000.0, 27.5, 536.084570312317, -121.00273437508338 - 0.15000000000000002, 30000.0, 28.0, 575.1449999997551, 15.269999999907782 - 0.15000000000000002, 30000.0, 28.5, 614.4623046871781, 165.14023437489902 - 0.15000000000000002, 30000.0, 29.0, 653.8609374995845, 317.8343749998901 - 0.15000000000000002, 30000.0, 29.5, 693.1653515619714, 462.5788281248813 - 0.15000000000000002, 30000.0, 30.0, 732.1999999993378, 588.5999999998721 - 0.15000000000000002, 30000.0, 30.5, 768.1155273438856, 514.5530273436736 - 0.15000000000000002, 30000.0, 31.0, 803.664843750134, 416.48046874992974 - 0.15000000000000002, 30000.0, 31.5, 838.9270507813798, 299.8536132811852 - 0.15000000000000002, 30000.0, 32.0, 873.9812500001224, 170.14374999993947 - 0.15000000000000002, 30000.0, 32.5, 908.9065429688627, 32.82216796869079 - 0.15000000000000002, 30000.0, 33.0, 943.7820312501009, -106.63984375006021 - 0.15000000000000002, 30000.0, 33.5, 978.6868164063377, -242.7709960938132 - 0.15000000000000002, 30000.0, 34.0, 1013.7000000000724, -370.10000000007176 - 0.15000000000000002, 30000.0, 34.5, 1053.015781250019, -434.52949218744953 - 0.15000000000000002, 30000.0, 35.0, 1092.206250000012, -483.8453124999112 - 0.15000000000000002, 30000.0, 35.5, 1130.9585937499967, -517.2072265623661 - 0.15000000000000002, 30000.0, 36.0, 1168.9599999999718, -533.774999999814 - 0.15000000000000002, 30000.0, 36.5, 1205.8976562499356, -532.7083984372547 - 0.15000000000000002, 30000.0, 37.0, 1241.458749999887, -513.1671874996878 - 0.15000000000000002, 30000.0, 37.5, 1275.3304687498232, -474.31113281211265 - 0.15000000000000002, 30000.0, 38.0, 1307.1999999997429, -415.2999999995291 - 0.15000000000000002, 30000.0, 38.5, 1328.7041015569446, -265.35722656328335 - 0.15000000000000002, 30000.0, 39.0, 1351.7546874934133, -129.8421875009733 - 0.15000000000000002, 30000.0, 39.5, 1377.8279296797512, -23.45605468868598 - 0.15000000000000002, 30000.0, 40.0, 1408.3999999909468, 39.09999999858064 - 0.15000000000000002, 30000.0, 40.5, 1454.563281249421, -26.717968750476842 - 0.15000000000000002, 30000.0, 41.0, 1504.3312499991548, -137.83125000063387 - 0.15000000000000002, 30000.0, 41.5, 1555.3335937488278, -281.00390625082105 - 0.15000000000000002, 30000.0, 42.0, 1605.1999999984375, -443.0000000010423 - 0.15000000000000002, 30000.0, 42.5, 1644.6109374992727, -697.8296874999281 - 0.15000000000000002, 30000.0, 43.0, 1680.924999999056, -910.1124999998799 - 0.15000000000000002, 30000.0, 43.5, 1714.5515624988268, -1031.7140624998297 - 0.15000000000000002, 30000.0, 44.0, 1745.8999999985936, -1014.4999999997808 - 0.15000000000000002, 30000.0, 44.5, 1774.4421874993245, -476.6562500001147 - 0.15000000000000002, 30000.0, 45.0, 1801.8999999992598, 162.79999999994902 - 0.15000000000000002, 30000.0, 45.5, 1829.0578124991941, 818.5312500000559 - 0.15000000000000002, 30000.0, 46.0, 1856.6999999991244, 1405.2000000002154 - 0.15000000000000002, 30000.0, 46.5, 1887.0484374993812, 1599.425781249956 - 0.15000000000000002, 30000.0, 47.0, 1918.8749999992515, 1649.1312499998658 - 0.15000000000000002, 30000.0, 47.5, 1952.3890624990906, 1564.19609374975 - 0.15000000000000002, 30000.0, 48.0, 1987.799999998901, 1354.4999999996069 - 0.15000000000000002, 30000.0, 48.5, 2025.3171874986833, 1029.9226562494382 - 0.15000000000000002, 30000.0, 49.0, 2065.149999998441, 600.3437499992406 - 0.15000000000000002, 30000.0, 49.5, 2107.507812498175, 75.64296874901697 - 0.15000000000000002, 30000.0, 50.0, 2152.599999997887, -534.3000000012357 - 0.15000000000000002, 35000.0, 0.0, 141.3213703868261, 141.3213703868261 - 0.15000000000000002, 35000.0, 22.0, 713.9999999999993, 103.30000000000933 - 0.15000000000000002, 35000.0, 22.5, 871.7597656250184, 63.561523437531015 - 0.15000000000000002, 35000.0, 23.0, 1022.4093750000217, 89.6078125000452 - 0.15000000000000002, 35000.0, 23.5, 1167.1042968750096, 169.00019531255236 - 0.15000000000000002, 35000.0, 24.0, 1306.9999999999848, 289.30000000005316 - 0.15000000000000002, 35000.0, 24.5, 1443.251953124948, 438.06855468754804 - 0.15000000000000002, 35000.0, 25.0, 1577.0156249999015, 602.8671875000376 - 0.15000000000000002, 35000.0, 25.5, 1709.446484374845, 771.2572265625223 - 0.15000000000000002, 35000.0, 26.0, 1841.699999999783, 930.8000000000025 - 0.15000000000000002, 35000.0, 26.5, 1983.0773437498049, 939.3873046875879 - 0.15000000000000002, 35000.0, 27.0, 2127.0537499997795, 906.8403125000916 - 0.15000000000000002, 35000.0, 27.5, 2273.3882812497554, 842.9494140625957 - 0.15000000000000002, 35000.0, 28.0, 2421.839999999732, 757.505000000101 - 0.15000000000000002, 35000.0, 28.5, 2572.167968749712, 660.2974609376085 - 0.15000000000000002, 35000.0, 29.0, 2724.1312499996916, 561.1171875001164 - 0.15000000000000002, 35000.0, 29.5, 2877.488906249672, 469.7545703126274 - 0.15000000000000002, 35000.0, 30.0, 3031.9999999996503, 396.00000000014256 - 0.15000000000000002, 35000.0, 30.5, 3187.1762695315647, 540.1856445308608 - 0.15000000000000002, 35000.0, 31.0, 3343.0476562503686, 703.4132812495636 - 0.15000000000000002, 35000.0, 31.5, 3499.396777344173, 877.3264648432696 - 0.15000000000000002, 35000.0, 32.0, 3656.006250000479, 1053.5687499994765 - 0.15000000000000002, 35000.0, 32.5, 3812.658691406788, 1223.783691405688 - 0.15000000000000002, 35000.0, 33.0, 3969.136718750599, 1379.614843749404 - 0.15000000000000002, 35000.0, 33.5, 4125.222949219409, 1512.7057617181235 - 0.15000000000000002, 35000.0, 34.0, 4280.700000000721, 1614.699999999346 - 0.15000000000000002, 35000.0, 34.5, 4424.718007814092, 1454.4339843750577 - 0.15000000000000002, 35000.0, 35.0, 4568.704687501752, 1267.5781250000762 - 0.15000000000000002, 35000.0, 35.5, 4713.455273439407, 1066.995703125096 - 0.15000000000000002, 35000.0, 36.0, 4859.765000002057, 865.5500000001152 - 0.15000000000000002, 35000.0, 36.5, 5008.429101564694, 676.1042968751353 - 0.15000000000000002, 35000.0, 37.0, 5160.242812502327, 511.52187500015134 - 0.15000000000000002, 35000.0, 37.5, 5316.001367189945, 384.66601562516644 - 0.15000000000000002, 35000.0, 38.0, 5476.500000002551, 308.4000000001788 - 0.15000000000000002, 35000.0, 38.5, 5657.555859375631, 185.92070312445458 - 0.15000000000000002, 35000.0, 39.0, 5837.153125000761, 196.62187499925858 - 0.15000000000000002, 35000.0, 39.5, 6012.748828125918, 377.73710937403484 - 0.15000000000000002, 35000.0, 40.0, 6181.800000001103, 766.499999998774 - 0.15000000000000002, 35000.0, 40.5, 6326.757812501374, 1791.646093749614 - 0.15000000000000002, 35000.0, 41.0, 6466.087500001929, 2942.306249999427 - 0.15000000000000002, 35000.0, 41.5, 6603.248437502574, 4099.113281249203 - 0.15000000000000002, 35000.0, 42.0, 6741.700000003311, 5142.699999998939 - 0.15000000000000002, 35000.0, 42.5, 6899.425000000073, 5707.4492187493315 - 0.15000000000000002, 35000.0, 43.0, 7059.549999999685, 6018.743749999061 - 0.15000000000000002, 35000.0, 43.5, 7219.724999999121, 6055.716406248725 - 0.15000000000000002, 35000.0, 44.0, 7377.59999999836, 5797.499999998333 - 0.15000000000000002, 35000.0, 44.5, 7518.164843750174, 4783.004687500398 - 0.15000000000000002, 35000.0, 45.0, 7656.793750000352, 3607.6750000005604 - 0.15000000000000002, 35000.0, 45.5, 7796.200781250595, 2426.732812500758 - 0.15000000000000002, 35000.0, 46.0, 7939.100000000916, 1395.40000000101 - 0.15000000000000002, 35000.0, 46.5, 8101.13515624993, 1223.6914062494818 - 0.15000000000000002, 35000.0, 47.0, 8266.918750000079, 1290.1187499993323 - 0.15000000000000002, 35000.0, 47.5, 8433.992968750299, 1527.986718749144 - 0.15000000000000002, 35000.0, 48.0, 8599.90000000059, 1870.599999998909 - 0.15000000000000002, 35000.0, 48.5, 8762.182031250963, 2251.2632812486218 - 0.15000000000000002, 35000.0, 49.0, 8918.381250001414, 2603.28124999827 - 0.15000000000000002, 35000.0, 49.5, 9066.039843751945, 2859.9585937478496 - 0.15000000000000002, 35000.0, 50.0, 9202.700000002562, 2954.59999999735 - 0.15000000000000002, 39000.0, 0.0, 117.21345694996432, 117.21345694996432 - 0.15000000000000002, 39000.0, 22.0, 499.9000000000082, -105.39999999998196 - 0.15000000000000002, 39000.0, 22.5, 617.1787109374867, -227.84433593749299 - 0.15000000000000002, 39000.0, 23.0, 726.1078124999644, -238.15781250000327 - 0.15000000000000002, 39000.0, 23.5, 828.2330078124406, -156.1173828125139 - 0.15000000000000002, 39000.0, 24.0, 925.0999999999142, -1.5000000000251532 - 0.15000000000000002, 39000.0, 24.5, 1018.2544921873844, 205.91738281246148 - 0.15000000000000002, 39000.0, 25.0, 1109.2421874998506, 446.35781249994557 - 0.15000000000000002, 39000.0, 25.5, 1199.6087890623116, 700.044335937426 - 0.15000000000000002, 39000.0, 26.0, 1290.8999999997666, 947.1999999999025 - 0.15000000000000002, 39000.0, 26.5, 1399.1947265624563, 996.0734375000193 - 0.15000000000000002, 39000.0, 27.0, 1512.3359374999445, 989.0350000000267 - 0.15000000000000002, 39000.0, 27.5, 1629.3779296874334, 935.789062500038 - 0.15000000000000002, 39000.0, 28.0, 1749.3749999999234, 846.0400000000541 - 0.15000000000000002, 39000.0, 28.5, 1871.3814453124155, 729.4921875000734 - 0.15000000000000002, 39000.0, 29.0, 1994.4515624999096, 595.8500000000977 - 0.15000000000000002, 39000.0, 29.5, 2117.639648437408, 454.81781250012705 - 0.15000000000000002, 39000.0, 30.0, 2239.9999999999104, 316.1000000001602 - 0.15000000000000002, 39000.0, 30.5, 2346.4529296875776, 310.47167968728036 - 0.15000000000000002, 39000.0, 31.0, 2451.5328125001165, 315.03593749973305 - 0.15000000000000002, 39000.0, 31.5, 2555.6400390626613, 327.96660156217973 - 0.15000000000000002, 39000.0, 32.0, 2659.175000000213, 347.4374999996205 - 0.15000000000000002, 39000.0, 32.5, 2762.53808593777, 371.62246093705556 - 0.15000000000000002, 39000.0, 33.0, 2866.1296875003354, 398.69531249948454 - 0.15000000000000002, 39000.0, 33.5, 2970.3501953129075, 426.82988281190705 - 0.15000000000000002, 39000.0, 34.0, 3075.600000000485, 454.1999999993229 - 0.15000000000000002, 39000.0, 34.5, 3193.9033203124336, 520.1846093747547 - 0.15000000000000002, 39000.0, 35.0, 3312.9296874998913, 577.8281249997019 - 0.15000000000000002, 39000.0, 35.5, 3431.9724609373334, 621.380078124644 - 0.15000000000000002, 39000.0, 36.0, 3550.3249999997547, 645.08999999958 - 0.15000000000000002, 39000.0, 36.5, 3667.2806640621584, 643.2074218745117 - 0.15000000000000002, 39000.0, 37.0, 3782.13281249954, 609.9818749994379 - 0.15000000000000002, 39000.0, 37.5, 3894.174804686896, 539.6628906243586 - 0.15000000000000002, 39000.0, 38.0, 4002.699999999227, 426.49999999927377 - 0.15000000000000002, 39000.0, 38.5, 4095.595312500695, 67.66699218811209 - 0.15000000000000002, 39000.0, 39.0, 4189.47500000084, -243.3234374992735 - 0.15000000000000002, 39000.0, 39.5, 4286.167187501009, -468.4271484366345 - 0.15000000000000002, 39000.0, 40.0, 4387.5000000012105, -569.5999999989681 - 0.15000000000000002, 39000.0, 40.5, 4504.992968750104, -389.73437500003337 - 0.15000000000000002, 39000.0, 41.0, 4626.906249999963, -57.47499999999019 - 0.15000000000000002, 39000.0, 41.5, 4751.191406249805, 417.596875000075 - 0.15000000000000002, 39000.0, 42.0, 4875.799999999638, 1025.9000000001656 - 0.15000000000000002, 39000.0, 42.5, 4986.37500000043, 1921.2554687503387 - 0.15000000000000002, 39000.0, 43.0, 5098.100000000774, 2865.3187500004005 - 0.15000000000000002, 39000.0, 43.5, 5213.850000001119, 3783.147656250453 - 0.15000000000000002, 39000.0, 44.0, 5336.500000001438, 4599.800000000492 - 0.15000000000000002, 39000.0, 44.5, 5497.788281250257, 5133.9195312495685 - 0.15000000000000002, 39000.0, 45.0, 5660.181250000572, 5459.543749999498 - 0.15000000000000002, 39000.0, 45.5, 5815.008593751032, 5544.296093749443 - 0.15000000000000002, 39000.0, 46.0, 5953.600000001679, 5355.7999999994145 - 0.15000000000000002, 39000.0, 46.5, 6017.832031250219, 4490.225781249689 - 0.15000000000000002, 39000.0, 47.0, 6068.2687500001275, 3435.2312499994055 - 0.15000000000000002, 39000.0, 47.5, 6116.021093749981, 2307.0210937490474 - 0.15000000000000002, 39000.0, 48.0, 6172.199999999771, 1221.7999999986214 - 0.15000000000000002, 39000.0, 48.5, 6247.916406249479, 295.77265624811116 - 0.15000000000000002, 39000.0, 49.0, 6354.281249999093, -354.8562500024873 - 0.15000000000000002, 39000.0, 49.5, 6502.405468748599, -613.8820312531716 - 0.15000000000000002, 39000.0, 50.0, 6703.399999997981, -365.1000000039421 - 0.15000000000000002, 43000.0, 0.0, 96.71265309175232, 96.71265309175232 - 0.15000000000000002, 43000.0, 22.0, -422.6000000000135, 828.4999999999949 - 0.15000000000000002, 43000.0, 22.5, -458.2318359375761, 364.2609374999589 - 0.15000000000000002, 43000.0, 23.0, -497.8078125001431, -18.075000000058672 - 0.15000000000000002, 43000.0, 23.5, -541.2048828127187, -329.19843750006237 - 0.15000000000000002, 43000.0, 24.0, -588.3000000003063, -579.8000000000575 - 0.15000000000000002, 43000.0, 24.5, -638.9701171879098, -780.5703125000475 - 0.15000000000000002, 43000.0, 25.0, -693.0921875005332, -942.2000000000373 - 0.15000000000000002, 43000.0, 25.5, -750.5431640631799, -1075.3796875000326 - 0.15000000000000002, 43000.0, 26.0, -811.2000000008538, -1190.800000000036 - 0.15000000000000002, 43000.0, 26.5, -876.7757812500739, -1414.3740234376753 - 0.15000000000000002, 43000.0, 27.0, -945.4162500000734, -1648.1540625002067 - 0.15000000000000002, 43000.0, 27.5, -1016.6835937500633, -1883.0783203127387 - 0.15000000000000002, 43000.0, 28.0, -1090.1400000000424, -2110.0850000002683 - 0.15000000000000002, 43000.0, 28.5, -1165.3476562500084, -2320.112304687795 - 0.15000000000000002, 43000.0, 29.0, -1241.8687499999596, -2504.0984375003163 - 0.15000000000000002, 43000.0, 29.5, -1319.2654687498944, -2652.98160156283 - 0.15000000000000002, 43000.0, 30.0, -1397.0999999998105, -2757.7000000003336 - 0.15000000000000002, 43000.0, 30.5, -1471.8038085936275, -2701.945410156718 - 0.15000000000000002, 43000.0, 31.0, -1546.3679687498807, -2594.1164062505522 - 0.15000000000000002, 43000.0, 31.5, -1620.6528320311338, -2435.365136719392 - 0.15000000000000002, 43000.0, 32.0, -1694.5187499998838, -2226.8437500007362 - 0.15000000000000002, 43000.0, 32.5, -1767.8260742186314, -1969.7043945320854 - 0.15000000000000002, 43000.0, 33.0, -1840.4351562498748, -1665.099218750939 - 0.15000000000000002, 43000.0, 33.5, -1912.206347656113, -1314.180371094796 - 0.15000000000000002, 43000.0, 34.0, -1982.9999999998456, -918.1000000011588 - 0.15000000000000002, 43000.0, 34.5, -2040.788085938735, 186.20539062451644 - 0.15000000000000002, 43000.0, 35.0, -2098.4515625015047, 1270.1093749994116 - 0.15000000000000002, 43000.0, 35.5, -2156.9830078143254, 2269.2011718742924 - 0.15000000000000002, 43000.0, 36.0, -2217.375000002202, 3119.069999999174 - 0.15000000000000002, 43000.0, 36.5, -2280.620117190141, 3755.3050781240345 - 0.15000000000000002, 43000.0, 37.0, -2347.7109375031487, 4113.495624998886 - 0.15000000000000002, 43000.0, 37.5, -2419.6400390662307, 4129.230859373729 - 0.15000000000000002, 43000.0, 38.0, -2497.4000000043934, 3738.0999999985434 - 0.15000000000000002, 43000.0, 38.5, -2606.520703123844, 2070.7009765636203 - 0.15000000000000002, 43000.0, 39.0, -2710.7343749985075, 285.01718750152213 - 0.15000000000000002, 43000.0, 39.5, -2805.580859373121, -1504.4751953105188 - 0.15000000000000002, 43000.0, 40.0, -2886.599999997677, -3183.2999999975145 - 0.15000000000000002, 43000.0, 40.5, -2914.204687499679, -4420.239843750754 - 0.15000000000000002, 43000.0, 41.0, -2933.1124999996873, -5404.256250000922 - 0.15000000000000002, 43000.0, 41.5, -2952.9140624996917, -6107.569531251123 - 0.15000000000000002, 43000.0, 42.0, -2983.199999999681, -6502.400000001364 - 0.15000000000000002, 43000.0, 42.5, -3079.8812500010777, -6252.546093751246 - 0.15000000000000002, 43000.0, 43.0, -3187.700000001328, -5762.0187500018 - 0.15000000000000002, 43000.0, 43.5, -3297.718750001683, -5126.407031252426 - 0.15000000000000002, 43000.0, 44.0, -3401.00000000218, -4441.300000003108 - 0.15000000000000002, 43000.0, 44.5, -3446.6257812510466, -3972.345312499849 - 0.15000000000000002, 43000.0, 45.0, -3484.4312500014557, -3577.049999999771 - 0.15000000000000002, 43000.0, 45.5, -3522.271093751843, -3282.979687499692 - 0.15000000000000002, 43000.0, 46.0, -3568.0000000021637, -3117.6999999996224 - 0.15000000000000002, 43000.0, 46.5, -3663.7187500024042, -3332.8742187514363 - 0.15000000000000002, 43000.0, 47.0, -3769.337500003249, -3642.3312500017 - 0.15000000000000002, 43000.0, 47.5, -3879.0125000042685, -3983.9976562519832 - 0.15000000000000002, 43000.0, 48.0, -3986.9000000054907, -4295.800000002287 - 0.15000000000000002, 43000.0, 48.5, -4087.1562500069494, -4515.664843752615 - 0.15000000000000002, 43000.0, 49.0, -4173.937500008674, -4581.518750002966 - 0.15000000000000002, 43000.0, 49.5, -4241.400000010696, -4431.288281253339 - 0.15000000000000002, 43000.0, 50.0, -4283.700000013047, -4002.900000003743 - 0.15000000000000002, 48000.0, 0.0, 76.05290598702356, 76.05290598702356 - 0.15000000000000002, 48000.0, 22.0, -399.50000000002035, 693.699999999931 - 0.15000000000000002, 48000.0, 22.5, -392.3335937500104, 317.0132812499284 - 0.15000000000000002, 48000.0, 23.0, -401.14374999998955, 11.706249999923125 - 0.15000000000000002, 48000.0, 23.5, -423.8820312499582, -231.97890625008523 - 0.15000000000000002, 48000.0, 24.0, -458.49999999991627, -423.80000000009727 - 0.15000000000000002, 48000.0, 24.5, -502.9492187498643, -573.5148437501128 - 0.15000000000000002, 48000.0, 25.0, -555.1812499998023, -690.8812500001325 - 0.15000000000000002, 48000.0, 25.5, -613.1476562497304, -785.6570312501568 - 0.15000000000000002, 48000.0, 26.0, -674.7999999996488, -867.6000000001866 - 0.15000000000000002, 48000.0, 26.5, -723.317382812598, -1051.37910156258 - 0.15000000000000002, 48000.0, 27.0, -770.579687500095, -1247.835937500093 - 0.15000000000000002, 48000.0, 27.5, -817.0708984375879, -1448.7435546876065 - 0.15000000000000002, 48000.0, 28.0, -863.2750000000766, -1645.8750000001185 - 0.15000000000000002, 48000.0, 28.5, -909.6759765625618, -1831.0033203126281 - 0.15000000000000002, 48000.0, 29.0, -956.7578125000442, -1995.9015625001364 - 0.15000000000000002, 48000.0, 29.5, -1005.0044921875227, -2132.34277343764 - 0.15000000000000002, 48000.0, 30.0, -1054.8999999999985, -2232.1000000001413 - 0.15000000000000002, 48000.0, 30.5, -1116.8623046878056, -2184.946582031637 - 0.15000000000000002, 48000.0, 31.0, -1180.495312500377, -2094.3695312504688 - 0.15000000000000002, 48000.0, 31.5, -1245.3369140629563, -1961.856152344312 - 0.15000000000000002, 48000.0, 32.0, -1310.9250000005436, -1788.8937500006666 - 0.15000000000000002, 48000.0, 32.5, -1376.797460938139, -1576.9696289070312 - 0.15000000000000002, 48000.0, 33.0, -1442.4921875007424, -1327.571093750908 - 0.15000000000000002, 48000.0, 33.5, -1507.547070313354, -1042.1854492197958 - 0.15000000000000002, 48000.0, 34.0, -1571.5000000009732, -722.3000000011987 - 0.15000000000000002, 48000.0, 34.5, -1617.225039062938, 138.20281249945856 - 0.15000000000000002, 48000.0, 35.0, -1662.5109375004808, 981.8874999993486 - 0.15000000000000002, 48000.0, 35.5, -1708.4826171880275, 1758.9234374992138 - 0.15000000000000002, 48000.0, 36.0, -1756.2650000005808, 2419.4799999990664 - 0.15000000000000002, 48000.0, 36.5, -1806.983007813142, 2913.7265624988886 - 0.15000000000000002, 48000.0, 37.0, -1861.7615625007136, 3191.832499998687 - 0.15000000000000002, 48000.0, 37.5, -1921.7255859382979, 3203.9671874984633 - 0.15000000000000002, 48000.0, 38.0, -1988.0000000008968, 2900.2999999981876 - 0.15000000000000002, 48000.0, 38.5, -2092.082617184978, 1610.0435546868757 - 0.15000000000000002, 48000.0, 39.0, -2188.976562496978, 226.30156249933862 - 0.15000000000000002, 48000.0, 39.5, -2273.0572265589044, -1162.766210938169 - 0.15000000000000002, 48000.0, 40.0, -2338.6999999957497, -2469.000000000673 - 0.15000000000000002, 48000.0, 40.5, -2333.6523437505552, -3441.9070312505887 - 0.15000000000000002, 48000.0, 41.0, -2317.5687500006893, -4220.593750000734 - 0.15000000000000002, 48000.0, 41.5, -2303.475781250835, -4781.833593750884 - 0.15000000000000002, 48000.0, 42.0, -2304.400000000989, -5102.400000001041 - 0.15000000000000002, 48000.0, 42.5, -2393.200000000411, -4915.976562499438 - 0.15000000000000002, 48000.0, 43.0, -2499.1375000005064, -4539.662499999329 - 0.15000000000000002, 48000.0, 43.5, -2611.306250000613, -4047.467187499247 - 0.15000000000000002, 48000.0, 44.0, -2718.8000000007332, -3513.3999999991993 - 0.15000000000000002, 48000.0, 44.5, -2770.3374999997004, -3137.845312500888 - 0.15000000000000002, 48000.0, 45.0, -2811.537499999573, -2817.887500001129 - 0.15000000000000002, 48000.0, 45.5, -2847.6437499994313, -2576.9859375013866 - 0.15000000000000002, 48000.0, 46.0, -2883.899999999282, -2438.6000000016566 - 0.15000000000000002, 48000.0, 46.5, -2941.7609374999183, -2611.4859374995417 - 0.15000000000000002, 48000.0, 47.0, -3003.7750000000447, -2859.6874999994434 - 0.15000000000000002, 48000.0, 47.5, -3068.70156250015, -3132.5453124993246 - 0.15000000000000002, 48000.0, 48.0, -3135.3000000002135, -3379.3999999991756 - 0.15000000000000002, 48000.0, 48.5, -3202.329687500216, -3549.5921874989917 - 0.15000000000000002, 48000.0, 49.0, -3268.550000000136, -3592.462499998772 - 0.15000000000000002, 48000.0, 49.5, -3332.720312499954, -3457.3515624984993 - 0.15000000000000002, 48000.0, 50.0, -3393.599999999652, -3093.599999998183 - 0.2, 0.0, 0.0, 528.8458618375491, 528.8458618375491 - 0.2, 0.0, 22.0, 1569.6000000000038, 859.1000000000009 - 0.2, 0.0, 22.5, 1867.4617187500098, 945.8226562500038 - 0.2, 0.0, 23.0, 2162.2687500000156, 1031.781250000006 - 0.2, 0.0, 23.5, 2455.041406250019, 1117.3742187500081 - 0.2, 0.0, 24.0, 2746.8000000000216, 1203.0000000000107 - 0.2, 0.0, 24.5, 3038.5648437500236, 1289.0570312500133 - 0.2, 0.0, 25.0, 3331.3562500000253, 1375.9437500000163 - 0.2, 0.0, 25.5, 3626.1945312500275, 1464.05859375002 - 0.2, 0.0, 26.0, 3924.1000000000295, 1553.8000000000234 - 0.2, 0.0, 26.5, 4236.811718750011, 1649.8498046875009 - 0.2, 0.0, 27.0, 4555.243750000007, 1748.5678125000009 - 0.2, 0.0, 27.5, 4878.578906250002, 1849.6181640625007 - 0.2, 0.0, 28.0, 5205.999999999995, 1952.665 - 0.2, 0.0, 28.5, 5536.689843749988, 2057.3724609374995 - 0.2, 0.0, 29.0, 5869.831249999979, 2163.4046874999985 - 0.2, 0.0, 29.5, 6204.6070312499705, 2270.4258203124987 - 0.2, 0.0, 30.0, 6540.199999999955, 2378.0999999999967 - 0.2, 0.0, 30.5, 6867.212500000008, 2482.4048828124905 - 0.2, 0.0, 31.0, 7194.2250000000095, 2587.0421874999897 - 0.2, 0.0, 31.5, 7521.237500000008, 2692.027148437488 - 0.2, 0.0, 32.0, 7848.25000000001, 2797.3749999999845 - 0.2, 0.0, 32.5, 8175.262500000012, 2903.100976562483 - 0.2, 0.0, 33.0, 8502.275000000012, 3009.2203124999796 - 0.2, 0.0, 33.5, 8829.287500000013, 3115.7482421874774 - 0.2, 0.0, 34.0, 9156.300000000017, 3222.6999999999753 - 0.2, 0.0, 34.5, 9483.315781250076, 3330.9390234374855 - 0.2, 0.0, 35.0, 9810.331250000085, 3439.5515624999844 - 0.2, 0.0, 35.5, 10137.346093750088, 3548.472070312484 - 0.2, 0.0, 36.0, 10464.360000000093, 3657.6349999999825 - 0.2, 0.0, 36.5, 10791.372656250094, 3766.974804687482 - 0.2, 0.0, 37.0, 11118.383750000092, 3876.4259374999824 - 0.2, 0.0, 37.5, 11445.392968750093, 3985.9228515624814 - 0.2, 0.0, 38.0, 11772.40000000009, 4095.399999999982 - 0.2, 0.0, 38.5, 12099.401367186996, 4204.962695312484 - 0.2, 0.0, 39.0, 12426.401562499364, 4314.28593749997 - 0.2, 0.0, 39.5, 12753.400976561712, 4423.2662109374505 - 0.2, 0.0, 40.0, 13080.399999999034, 4531.799999999929 - 0.2, 0.0, 40.5, 13407.39609374993, 4638.860937499979 - 0.2, 0.0, 41.0, 13734.393749999897, 4745.6374999999725 - 0.2, 0.0, 41.5, 14061.394531249864, 4852.395312499963 - 0.2, 0.0, 42.0, 14388.399999999834, 4959.399999999951 - 0.2, 0.0, 42.5, 14715.165625000018, 5067.964062500068 - 0.2, 0.0, 43.0, 15042.037500000002, 5176.887500000084 - 0.2, 0.0, 43.5, 15369.115624999971, 5286.017187500104 - 0.2, 0.0, 44.0, 15696.499999999936, 5395.200000000124 - 0.2, 0.0, 44.5, 16025.306250000074, 5503.942968749996 - 0.2, 0.0, 45.0, 16354.212500000112, 5612.568749999991 - 0.2, 0.0, 45.5, 16682.912500000166, 5721.060156249985 - 0.2, 0.0, 46.0, 17011.10000000024, 5829.399999999976 - 0.2, 0.0, 46.5, 17336.93750000023, 5936.817187500025 - 0.2, 0.0, 47.0, 17662.262500000274, 6044.350000000024 - 0.2, 0.0, 47.5, 17987.381250000333, 6152.28281250002 - 0.2, 0.0, 48.0, 18312.600000000384, 6260.900000000014 - 0.2, 0.0, 48.5, 18638.22500000045, 6370.485937500007 - 0.2, 0.0, 49.0, 18964.56250000051, 6481.324999999998 - 0.2, 0.0, 49.5, 19291.91875000058, 6593.701562499989 - 0.2, 0.0, 50.0, 19620.60000000065, 6707.899999999973 - 0.2, 2000.0, 0.0, 495.1423835007058, 495.1423835007058 - 0.2, 2000.0, 22.0, 1515.3999999999992, 815.3000000000014 - 0.2, 2000.0, 22.5, 1802.9623046874997, 899.4632812500025 - 0.2, 2000.0, 23.0, 2087.576562500001, 982.5437500000043 - 0.2, 2000.0, 23.5, 2370.227539062501, 1064.9773437500064 - 0.2, 2000.0, 24.0, 2651.9000000000015, 1147.2000000000094 - 0.2, 2000.0, 24.5, 2933.5787109375015, 1229.6476562500122 - 0.2, 2000.0, 25.0, 3216.2484375000013, 1312.7562500000154 - 0.2, 2000.0, 25.5, 3500.8939453125026, 1396.9617187500196 - 0.2, 2000.0, 26.0, 3788.5000000000027, 1482.7000000000232 - 0.2, 2000.0, 26.5, 4090.3955078125123, 1574.8927734375025 - 0.2, 2000.0, 27.0, 4397.812187500014, 1669.7465625000027 - 0.2, 2000.0, 27.5, 4709.961523437517, 1766.928320312504 - 0.2, 2000.0, 28.0, 5026.0550000000185, 1866.1050000000043 - 0.2, 2000.0, 28.5, 5345.304101562519, 1966.9435546875056 - 0.2, 2000.0, 29.0, 5666.920312500019, 2069.1109375000065 - 0.2, 2000.0, 29.5, 5990.115117187516, 2172.274101562508 - 0.2, 2000.0, 30.0, 6314.100000000015, 2276.1000000000095 - 0.2, 2000.0, 30.5, 6629.811132812505, 2376.6909179687677 - 0.2, 2000.0, 31.0, 6945.5234375000055, 2477.6179687500207 - 0.2, 2000.0, 31.5, 7261.236523437504, 2578.8875976562754 - 0.2, 2000.0, 32.0, 7576.950000000003, 2680.50625000003 - 0.2, 2000.0, 32.5, 7892.663476562502, 2782.4803710937854 - 0.2, 2000.0, 33.0, 8208.376562500005, 2884.8164062500405 - 0.2, 2000.0, 33.5, 8524.088867187505, 2987.520800781297 - 0.2, 2000.0, 34.0, 8839.8, 3090.6000000000536 - 0.2, 2000.0, 34.5, 9155.503007812607, 3194.8106249999955 - 0.2, 2000.0, 35.0, 9471.204687500132, 3299.3374999999946 - 0.2, 2000.0, 35.5, 9786.90527343766, 3404.1156249999935 - 0.2, 2000.0, 36.0, 10102.605000000192, 3509.0799999999913 - 0.2, 2000.0, 36.5, 10418.30410156272, 3614.1656249999883 - 0.2, 2000.0, 37.0, 10734.00281250026, 3719.3074999999853 - 0.2, 2000.0, 37.5, 11049.701367187798, 3824.4406249999815 - 0.2, 2000.0, 38.0, 11365.400000000336, 3929.4999999999764 - 0.2, 2000.0, 38.5, 11681.099999999471, 4034.5746093750204 - 0.2, 2000.0, 39.0, 11996.799999999344, 4139.365625000024 - 0.2, 2000.0, 39.5, 12312.499999999196, 4243.773828125029 - 0.2, 2000.0, 40.0, 12628.199999999031, 4347.700000000035 - 0.2, 2000.0, 40.5, 12943.896093750041, 4449.996093750037 - 0.2, 2000.0, 41.0, 13259.593750000033, 4552.031250000045 - 0.2, 2000.0, 41.5, 13575.294531250018, 4654.125781250049 - 0.2, 2000.0, 42.0, 13890.999999999987, 4756.6000000000595 - 0.2, 2000.0, 42.5, 14206.477343749999, 4861.348437500017 - 0.2, 2000.0, 43.0, 14522.056249999996, 4966.487500000026 - 0.2, 2000.0, 43.5, 14837.832031249995, 5071.707812500037 - 0.2, 2000.0, 44.0, 15153.899999999996, 5176.700000000048 - 0.2, 2000.0, 44.5, 15471.32421875028, 5279.736718750012 - 0.2, 2000.0, 45.0, 15788.843750000367, 5382.493750000011 - 0.2, 2000.0, 45.5, 16106.166406250471, 5485.22890625001 - 0.2, 2000.0, 46.0, 16423.000000000582, 5588.20000000001 - 0.2, 2000.0, 46.5, 16737.595312499863, 5692.059375000062 - 0.2, 2000.0, 47.0, 17051.699999999804, 5796.51250000009 - 0.2, 2000.0, 47.5, 17365.604687499752, 5901.659375000118 - 0.2, 2000.0, 48.0, 17679.599999999686, 6007.600000000156 - 0.2, 2000.0, 48.5, 17993.976562499614, 6114.434375000199 - 0.2, 2000.0, 49.0, 18309.024999999532, 6222.262500000249 - 0.2, 2000.0, 49.5, 18625.035937499448, 6331.184375000305 - 0.2, 2000.0, 50.0, 18942.299999999363, 6441.300000000368 - 0.2, 5000.0, 0.0, 447.7897950303274, 447.7897950303274 - 0.2, 5000.0, 22.0, 1438.7000000000016, 754.4000000000002 - 0.2, 5000.0, 22.5, 1711.713671875, 834.8578125000005 - 0.2, 5000.0, 23.0, 1981.9281249999988, 913.8624999999994 - 0.2, 5000.0, 23.5, 2250.2785156249965, 991.885937499998 - 0.2, 5000.0, 24.0, 2517.6999999999966, 1069.3999999999962 - 0.2, 5000.0, 24.5, 2785.1277343749944, 1146.8765624999937 - 0.2, 5000.0, 25.0, 3053.4968749999925, 1224.7874999999894 - 0.2, 5000.0, 25.5, 3323.7425781249904, 1303.6046874999847 - 0.2, 5000.0, 26.0, 3596.799999999987, 1383.7999999999804 - 0.2, 5000.0, 26.5, 3883.430273437506, 1470.4089843750064 - 0.2, 5000.0, 27.0, 4175.304062500005, 1559.6006250000073 - 0.2, 5000.0, 27.5, 4471.672070312505, 1651.06445312501 - 0.2, 5000.0, 28.0, 4771.7850000000035, 1744.4900000000105 - 0.2, 5000.0, 28.5, 5074.893554687502, 1839.5667968750113 - 0.2, 5000.0, 29.0, 5380.248437499997, 1935.9843750000155 - 0.2, 5000.0, 29.5, 5687.100351562493, 2033.4322656250151 - 0.2, 5000.0, 30.0, 5994.699999999989, 2131.600000000016 - 0.2, 5000.0, 30.5, 6294.428417968816, 2227.1140625000035 - 0.2, 5000.0, 31.0, 6594.155468750076, 2323.018750000004 - 0.2, 5000.0, 31.5, 6893.881347656336, 2419.295312500004 - 0.2, 5000.0, 32.0, 7193.606250000099, 2515.9250000000047 - 0.2, 5000.0, 32.5, 7493.3303710938635, 2612.889062500005 - 0.2, 5000.0, 33.0, 7793.0539062501275, 2710.1687500000035 - 0.2, 5000.0, 33.5, 8092.77705078139, 2807.7453125000043 - 0.2, 5000.0, 34.0, 8392.500000000155, 2905.6000000000026 - 0.2, 5000.0, 34.5, 8692.218437500007, 3004.667265625022 - 0.2, 5000.0, 35.0, 8991.937500000022, 3103.884375000029 - 0.2, 5000.0, 35.5, 9291.657812500041, 3203.1417968750384 - 0.2, 5000.0, 36.0, 9591.38000000006, 3302.3300000000495 - 0.2, 5000.0, 36.5, 9891.104687500085, 3401.33945312506 - 0.2, 5000.0, 37.0, 10190.832500000111, 3500.060625000071 - 0.2, 5000.0, 37.5, 10490.564062500142, 3598.3839843750843 - 0.2, 5000.0, 38.0, 10790.300000000174, 3696.200000000099 - 0.2, 5000.0, 38.5, 11090.052539062319, 3792.002734374937 - 0.2, 5000.0, 39.0, 11389.804687499756, 3887.803124999919 - 0.2, 5000.0, 39.5, 11689.554492187182, 3983.801953124897 - 0.2, 5000.0, 40.0, 11989.299999999601, 4080.1999999998725 - 0.2, 5000.0, 40.5, 12289.030468750156, 4178.36406250001 - 0.2, 5000.0, 41.0, 12588.756250000204, 4276.862500000014 - 0.2, 5000.0, 41.5, 12888.47890625026, 4375.429687500019 - 0.2, 5000.0, 42.0, 13188.200000000325, 4473.800000000026 - 0.2, 5000.0, 42.5, 13487.686718750045, 4570.489062500036 - 0.2, 5000.0, 43.0, 13787.268750000048, 4666.9375000000455 - 0.2, 5000.0, 43.5, 14087.041406250051, 4763.367187500054 - 0.2, 5000.0, 44.0, 14387.100000000059, 4860.000000000063 - 0.2, 5000.0, 44.5, 14688.489062499984, 4957.507031250031 - 0.2, 5000.0, 45.0, 14989.974999999982, 5055.481250000041 - 0.2, 5000.0, 45.5, 15291.273437499984, 5153.9648437500555 - 0.2, 5000.0, 46.0, 15592.099999999995, 5253.000000000068 - 0.2, 5000.0, 46.5, 15890.752343750311, 5352.601562500046 - 0.2, 5000.0, 47.0, 16188.931250000396, 5452.850000000064 - 0.2, 5000.0, 47.5, 16486.9195312505, 5553.798437500084 - 0.2, 5000.0, 48.0, 16785.000000000604, 5655.500000000108 - 0.2, 5000.0, 48.5, 17083.455468750723, 5758.007812500134 - 0.2, 5000.0, 49.0, 17382.568750000843, 5861.375000000166 - 0.2, 5000.0, 49.5, 17682.622656250976, 5965.654687500199 - 0.2, 5000.0, 50.0, 17983.900000001122, 6070.900000000235 - 0.2, 10000.0, 0.0, 376.8791442831284, 376.8791442831284 - 0.2, 10000.0, 22.0, 1307.9999999999986, 662.3999999999995 - 0.2, 10000.0, 22.5, 1556.2527343749985, 736.5611328124993 - 0.2, 10000.0, 23.0, 1801.9531249999982, 808.9609374999986 - 0.2, 10000.0, 23.5, 2045.9519531249982, 880.0802734374981 - 0.2, 10000.0, 24.0, 2289.099999999998, 950.3999999999969 - 0.2, 10000.0, 24.5, 2532.248046875, 1020.4009765624959 - 0.2, 10000.0, 25.0, 2776.2468750000007, 1090.5640624999949 - 0.2, 10000.0, 25.5, 3021.9472656250027, 1161.3701171874939 - 0.2, 10000.0, 26.0, 3270.200000000004, 1233.299999999992 - 0.2, 10000.0, 26.5, 3530.7863281250093, 1311.1453125000007 - 0.2, 10000.0, 27.0, 3796.1368750000124, 1391.3225000000004 - 0.2, 10000.0, 27.5, 4065.571484375015, 1473.5734375000004 - 0.2, 10000.0, 28.0, 4338.410000000018, 1557.6400000000006 - 0.2, 10000.0, 28.5, 4613.972265625023, 1643.2640625000004 - 0.2, 10000.0, 29.0, 4891.578125000026, 1730.1874999999993 - 0.2, 10000.0, 29.5, 5170.54742187503, 1818.152187499999 - 0.2, 10000.0, 30.0, 5450.200000000034, 1906.8999999999987 - 0.2, 10000.0, 30.5, 5722.7202148437445, 1994.2766601562498 - 0.2, 10000.0, 31.0, 5995.242968749995, 2082.1007812499997 - 0.2, 10000.0, 31.5, 6267.767675781245, 2170.294824218749 - 0.2, 10000.0, 32.0, 6540.2937499999925, 2258.781249999999 - 0.2, 10000.0, 32.5, 6812.820605468744, 2347.4825195312487 - 0.2, 10000.0, 33.0, 7085.3476562499945, 2436.3210937499994 - 0.2, 10000.0, 33.5, 7357.874316406247, 2525.219433593749 - 0.2, 10000.0, 34.0, 7630.399999999997, 2614.0999999999976 - 0.2, 10000.0, 34.5, 7902.912226562633, 2702.0292578125163 - 0.2, 10000.0, 35.0, 8175.423437500164, 2789.8671875000205 - 0.2, 10000.0, 35.5, 8447.9341796877, 2877.617773437523 - 0.2, 10000.0, 36.0, 8720.445000000245, 2965.2850000000276 - 0.2, 10000.0, 36.5, 8992.956445312782, 3052.872851562532 - 0.2, 10000.0, 37.0, 9265.469062500333, 3140.3853125000373 - 0.2, 10000.0, 37.5, 9537.983398437886, 3227.8263671875416 - 0.2, 10000.0, 38.0, 9810.500000000442, 3315.200000000046 - 0.2, 10000.0, 38.5, 10083.02890624969, 3402.6441406248478 - 0.2, 10000.0, 39.0, 10355.556249999625, 3489.9593749998207 - 0.2, 10000.0, 39.5, 10628.080468749553, 3577.119921874791 - 0.2, 10000.0, 40.0, 10900.59999999947, 3664.0999999997603 - 0.2, 10000.0, 40.5, 11173.105468749929, 3750.258593749997 - 0.2, 10000.0, 41.0, 11445.606249999919, 3836.431249999991 - 0.2, 10000.0, 41.5, 11718.103906249911, 3922.8382812499844 - 0.2, 10000.0, 42.0, 11990.59999999991, 4009.6999999999753 - 0.2, 10000.0, 42.5, 12262.885156249882, 4097.814843749972 - 0.2, 10000.0, 43.0, 12535.256249999833, 4186.593749999964 - 0.2, 10000.0, 43.5, 12807.799218749782, 4276.025781249952 - 0.2, 10000.0, 44.0, 13080.59999999971, 4366.099999999939 - 0.2, 10000.0, 44.5, 13354.596093750048, 4456.93828125 - 0.2, 10000.0, 45.0, 13628.681250000072, 4548.343750000003 - 0.2, 10000.0, 45.5, 13902.600781250096, 4640.252343750006 - 0.2, 10000.0, 46.0, 14176.10000000012, 4732.600000000014 - 0.2, 10000.0, 46.5, 14447.658593749866, 4824.62734374996 - 0.2, 10000.0, 47.0, 14718.793749999842, 4917.243749999946 - 0.2, 10000.0, 47.5, 14989.75703124983, 5010.66328124993 - 0.2, 10000.0, 48.0, 15260.799999999817, 5105.09999999991 - 0.2, 10000.0, 48.5, 15532.17421874982, 5200.767968749888 - 0.2, 10000.0, 49.0, 15804.131249999833, 5297.881249999864 - 0.2, 10000.0, 49.5, 16076.922656249857, 5396.653906249835 - 0.2, 10000.0, 50.0, 16350.799999999901, 5497.299999999804 - 0.2, 15000.0, 0.0, 315.14385763345257, 315.14385763345257 - 0.2, 15000.0, 22.0, -472.49999999999443, 20.000000000002075 - 0.2, 15000.0, 22.5, -562.4890624999925, -20.58046874999856 - 0.2, 15000.0, 23.0, -651.4374999999903, -58.33124999999939 - 0.2, 15000.0, 23.5, -739.6671874999884, -93.91640625000049 - 0.2, 15000.0, 24.0, -827.4999999999865, -128.0000000000017 - 0.2, 15000.0, 24.5, -915.2578124999845, -161.24609375000318 - 0.2, 15000.0, 25.0, -1003.2624999999828, -194.31875000000474 - 0.2, 15000.0, 25.5, -1091.835937499981, -227.88203125000652 - 0.2, 15000.0, 26.0, -1181.2999999999793, -262.6000000000083 - 0.2, 15000.0, 26.5, -1275.2578124999918, -301.4130859374987 - 0.2, 15000.0, 27.0, -1370.9374999999925, -342.8390624999978 - 0.2, 15000.0, 27.5, -1468.0984374999935, -387.1517578124965 - 0.2, 15000.0, 28.0, -1566.4999999999948, -434.62499999999534 - 0.2, 15000.0, 28.5, -1665.9015624999965, -485.53261718749405 - 0.2, 15000.0, 29.0, -1766.062499999999, -540.1484374999927 - 0.2, 15000.0, 29.5, -1866.7421875000025, -598.7462890624914 - 0.2, 15000.0, 30.0, -1967.7000000000053, -661.5999999999908 - 0.2, 15000.0, 30.5, -2066.2671875000133, -746.4478515624984 - 0.2, 15000.0, 31.0, -2164.8625000000143, -834.435937499999 - 0.2, 15000.0, 31.5, -2263.4765625000155, -924.1748046874995 - 0.2, 15000.0, 32.0, -2362.1000000000176, -1014.2750000000003 - 0.2, 15000.0, 32.5, -2460.723437500019, -1103.3470703125006 - 0.2, 15000.0, 33.0, -2559.3375000000206, -1190.0015625000008 - 0.2, 15000.0, 33.5, -2657.9328125000234, -1272.8490234375008 - 0.2, 15000.0, 34.0, -2756.5000000000273, -1350.5000000000014 - 0.2, 15000.0, 34.5, -2854.6884374999354, -1383.5894921874665 - 0.2, 15000.0, 35.0, -2952.862499999932, -1412.3203124999611 - 0.2, 15000.0, 35.5, -3051.0453124999285, -1438.9197265624557 - 0.2, 15000.0, 36.0, -3149.2599999999243, -1465.6149999999489 - 0.2, 15000.0, 36.5, -3247.5296874999217, -1494.6333984374428 - 0.2, 15000.0, 37.0, -3345.8774999999155, -1528.202187499935 - 0.2, 15000.0, 37.5, -3444.3265624999112, -1568.5486328124273 - 0.2, 15000.0, 38.0, -3542.8999999999064, -1617.8999999999194 - 0.2, 15000.0, 38.5, -3641.9552734372674, -1692.809374999905 - 0.2, 15000.0, 39.0, -3741.0078124997203, -1773.749999999889 - 0.2, 15000.0, 39.5, -3840.0064453121663, -1859.7656249998709 - 0.2, 15000.0, 40.0, -3938.899999999603, -1949.8999999998516 - 0.2, 15000.0, 40.5, -4037.4351562499733, -2039.5679687500296 - 0.2, 15000.0, 41.0, -4135.843749999978, -2132.893750000042 - 0.2, 15000.0, 41.5, -4234.155468749985, -2230.3726562500574 - 0.2, 15000.0, 42.0, -4332.399999999994, -2332.500000000074 - 0.2, 15000.0, 42.5, -4430.575781249926, -2448.954687499976 - 0.2, 15000.0, 43.0, -4528.756249999915, -2567.3749999999723 - 0.2, 15000.0, 43.5, -4626.983593749906, -2684.5828124999675 - 0.2, 15000.0, 44.0, -4725.2999999998965, -2797.399999999962 - 0.2, 15000.0, 44.5, -4824.134375000019, -2883.781250000015 - 0.2, 15000.0, 45.0, -4922.987500000035, -2966.962500000026 - 0.2, 15000.0, 45.5, -5021.746875000048, -3051.312500000037 - 0.2, 15000.0, 46.0, -5120.300000000057, -3141.200000000051 - 0.2, 15000.0, 46.5, -5217.897656250041, -3253.8609374999355 - 0.2, 15000.0, 47.0, -5315.318750000055, -3375.649999999925 - 0.2, 15000.0, 47.5, -5412.705468750071, -3505.7890624999145 - 0.2, 15000.0, 48.0, -5510.200000000089, -3643.499999999904 - 0.2, 15000.0, 48.5, -5607.9445312501075, -3788.0046874998948 - 0.2, 15000.0, 49.0, -5706.081250000131, -3938.524999999886 - 0.2, 15000.0, 49.5, -5804.752343750158, -4094.282812499879 - 0.2, 15000.0, 50.0, -5904.10000000019, -4254.499999999873 - 0.2, 20000.0, 0.0, 261.6860819899648, 261.6860819899648 - 0.2, 20000.0, 22.0, 878.6999999999886, 425.1000000000006 - 0.2, 20000.0, 22.5, 1049.9164062499758, 543.9251953124981 - 0.2, 20000.0, 23.0, 1218.343749999962, 628.5609374999937 - 0.2, 20000.0, 23.5, 1384.7242187499467, 684.2662109374876 - 0.2, 20000.0, 24.0, 1549.79999999993, 716.2999999999796 - 0.2, 20000.0, 24.5, 1714.313281249911, 729.9212890624701 - 0.2, 20000.0, 25.0, 1879.0062499998887, 730.3890624999584 - 0.2, 20000.0, 25.5, 2044.6210937498624, 722.9623046874453 - 0.2, 20000.0, 26.0, 2211.8999999998346, 712.8999999999302 - 0.2, 20000.0, 26.5, 2389.219531249986, 744.7595703124651 - 0.2, 20000.0, 27.0, 2570.1237499999875, 786.7471874999616 - 0.2, 20000.0, 27.5, 2754.0460937499906, 837.3849609374586 - 0.2, 20000.0, 28.0, 2940.4199999999933, 895.1949999999568 - 0.2, 20000.0, 28.5, 3128.678906249997, 958.6994140624555 - 0.2, 20000.0, 29.0, 3318.2562500000013, 1026.4203124999551 - 0.2, 20000.0, 29.5, 3508.5854687500055, 1096.8798046874554 - 0.2, 20000.0, 30.0, 3699.100000000011, 1168.5999999999565 - 0.2, 20000.0, 30.5, 3882.21181640618, 1218.1641601562005 - 0.2, 20000.0, 31.0, 4065.044531249922, 1268.1226562499394 - 0.2, 20000.0, 31.5, 4247.700292968663, 1319.0870117186766 - 0.2, 20000.0, 32.0, 4430.28124999991, 1371.668749999912 - 0.2, 20000.0, 32.5, 4612.889550781157, 1426.4793945311467 - 0.2, 20000.0, 33.0, 4795.627343749907, 1484.1304687498805 - 0.2, 20000.0, 33.5, 4978.596777343661, 1545.2334960936128 - 0.2, 20000.0, 34.0, 5161.899999999917, 1610.3999999998448 - 0.2, 20000.0, 34.5, 5348.523789061784, 1725.847187499684 - 0.2, 20000.0, 35.0, 5535.410937499163, 1842.2374999996205 - 0.2, 20000.0, 35.5, 5722.388867186533, 1955.839062499549 - 0.2, 20000.0, 36.0, 5909.284999998893, 2062.919999999468 - 0.2, 20000.0, 36.5, 6095.92675781124, 2159.7484374993765 - 0.2, 20000.0, 37.0, 6282.141562498578, 2242.5924999992753 - 0.2, 20000.0, 37.5, 6467.756835935904, 2307.720312499162 - 0.2, 20000.0, 38.0, 6652.599999998216, 2351.3999999990374 - 0.2, 20000.0, 38.5, 6834.675976562581, 2318.693554687697 - 0.2, 20000.0, 39.0, 7016.5796875001915, 2283.6265625002707 - 0.2, 20000.0, 39.5, 7198.543554687822, 2253.8462890628552 - 0.2, 20000.0, 40.0, 7380.8000000004695, 2237.0000000004507 - 0.2, 20000.0, 40.5, 7564.545312499787, 2265.8765625001 - 0.2, 20000.0, 41.0, 7748.662499999705, 2312.925000000132 - 0.2, 20000.0, 41.5, 7932.99843749959, 2375.735937500174 - 0.2, 20000.0, 42.0, 8117.3999999994385, 2451.900000000228 - 0.2, 20000.0, 42.5, 8301.284374999705, 2535.902343749741 - 0.2, 20000.0, 43.0, 8485.099999999646, 2629.6812499996636 - 0.2, 20000.0, 43.5, 8668.865624999591, 2732.069531249576 - 0.2, 20000.0, 44.0, 8852.59999999954, 2841.89999999948 - 0.2, 20000.0, 44.5, 9036.040624999736, 2964.5210937498396 - 0.2, 20000.0, 45.0, 9219.59999999971, 3089.643749999816 - 0.2, 20000.0, 45.5, 9403.409374999696, 3213.494531249785 - 0.2, 20000.0, 46.0, 9587.599999999693, 3332.2999999997437 - 0.2, 20000.0, 46.5, 9773.127343749758, 3430.0249999998664 - 0.2, 20000.0, 47.0, 9958.968749999707, 3520.062499999833 - 0.2, 20000.0, 47.5, 10144.925781249647, 3603.543749999796 - 0.2, 20000.0, 48.0, 10330.799999999577, 3681.599999999756 - 0.2, 20000.0, 48.5, 10516.392968749504, 3755.362499999715 - 0.2, 20000.0, 49.0, 10701.506249999415, 3825.9624999996727 - 0.2, 20000.0, 49.5, 10885.941406249316, 3894.531249999629 - 0.2, 20000.0, 50.0, 11069.49999999921, 3962.199999999589 - 0.2, 25000.0, 0.0, 215.65926106956113, 215.65926106956113 - 0.2, 25000.0, 22.0, 619.700000000008, 473.6000000000098 - 0.2, 25000.0, 22.5, 744.2455078125075, 316.78808593750165 - 0.2, 25000.0, 23.0, 865.9359375000031, 243.98281249999712 - 0.2, 25000.0, 23.5, 985.4333984374957, 242.01113281249616 - 0.2, 25000.0, 24.0, 1103.399999999985, 297.69999999999794 - 0.2, 25000.0, 24.5, 1220.4978515624719, 397.87636718750224 - 0.2, 25000.0, 25.0, 1337.3890624999565, 529.3671875000084 - 0.2, 25000.0, 25.5, 1454.7357421874397, 678.999414062516 - 0.2, 25000.0, 26.0, 1573.1999999999214, 833.6000000000245 - 0.2, 25000.0, 26.5, 1700.0187500000113, 871.4083984375446 - 0.2, 25000.0, 27.0, 1829.655000000006, 881.6340625000558 - 0.2, 25000.0, 27.5, 1961.64375, 869.7189453125668 - 0.2, 25000.0, 28.0, 2095.5199999999913, 841.1050000000777 - 0.2, 25000.0, 28.5, 2230.8187499999813, 801.2341796875885 - 0.2, 25000.0, 29.0, 2367.074999999971, 755.5484375000992 - 0.2, 25000.0, 29.5, 2503.8237499999586, 709.4897265626097 - 0.2, 25000.0, 30.0, 2640.599999999946, 668.500000000121 - 0.2, 25000.0, 30.5, 2771.192871093848, 714.1232421875818 - 0.2, 25000.0, 31.0, 2901.430468750137, 768.4515625001118 - 0.2, 25000.0, 31.5, 3031.3950195314305, 829.6791015626447 - 0.2, 25000.0, 32.0, 3161.168750000228, 896.0000000001808 - 0.2, 25000.0, 32.5, 3290.8338867190296, 965.6083984377196 - 0.2, 25000.0, 33.0, 3420.472656250336, 1036.6984375002608 - 0.2, 25000.0, 33.5, 3550.1672851566473, 1107.4642578128044 - 0.2, 25000.0, 34.0, 3680.000000000461, 1176.1000000003492 - 0.2, 25000.0, 34.5, 3811.726054688132, 1168.333398437518 - 0.2, 25000.0, 35.0, 3943.5953125007622, 1161.7265625000057 - 0.2, 25000.0, 35.5, 4075.5306640634008, 1161.3751953124906 - 0.2, 25000.0, 36.0, 4207.455000001048, 1172.3749999999736 - 0.2, 25000.0, 36.5, 4339.291210938699, 1199.821679687453 - 0.2, 25000.0, 37.0, 4470.962187501363, 1248.8109374999299 - 0.2, 25000.0, 37.5, 4602.390820314029, 1324.4384765624052 - 0.2, 25000.0, 38.0, 4733.500000001701, 1431.7999999998783 - 0.2, 25000.0, 38.5, 4862.431249999757, 1695.5347656253844 - 0.2, 25000.0, 39.0, 4991.812499999645, 1939.2093750004456 - 0.2, 25000.0, 39.5, 5121.962499999528, 2141.3542968755114 - 0.2, 25000.0, 40.0, 5253.199999999416, 2280.500000000585 - 0.2, 25000.0, 40.5, 5388.64843750041, 2220.0656250002503 - 0.2, 25000.0, 41.0, 5524.700000000565, 2099.737500000345 - 0.2, 25000.0, 41.5, 5660.551562500757, 1944.0906250004575 - 0.2, 25000.0, 42.0, 5795.400000000991, 1777.7000000005855 - 0.2, 25000.0, 42.5, 5923.797656250579, 1676.2539062499197 - 0.2, 25000.0, 43.0, 6051.443750000845, 1592.7687499999158 - 0.2, 25000.0, 43.5, 6179.392968751149, 1531.3742187499113 - 0.2, 25000.0, 44.0, 6308.700000001483, 1496.1999999999052 - 0.2, 25000.0, 44.5, 6446.610937500127, 1518.5242187503547 - 0.2, 25000.0, 45.0, 6585.512500000283, 1564.4687500004911 - 0.2, 25000.0, 45.5, 6723.982812500481, 1627.3039062506484 - 0.2, 25000.0, 46.0, 6860.600000000726, 1700.3000000008265 - 0.2, 25000.0, 46.5, 6987.141406250375, 1738.442187500312 - 0.2, 25000.0, 47.0, 7111.70625000042, 1788.6000000004256 - 0.2, 25000.0, 47.5, 7235.592968750451, 1859.3578125005615 - 0.2, 25000.0, 48.0, 7360.10000000047, 1959.3000000007214 - 0.2, 25000.0, 48.5, 7486.525781250475, 2097.010937500908 - 0.2, 25000.0, 49.0, 7616.168750000466, 2281.075000001121 - 0.2, 25000.0, 49.5, 7750.327343750447, 2520.0765625013632 - 0.2, 25000.0, 50.0, 7890.300000000413, 2822.600000001637 - 0.2, 30000.0, 0.0, 176.27618548603778, 176.27618548603778 - 0.2, 30000.0, 22.0, 272.40000000000293, 197.59999999997467 - 0.2, 30000.0, 22.5, 320.429101562519, 299.03906249998926 - 0.2, 30000.0, 23.0, 369.3796875000385, 340.2500000000063 - 0.2, 30000.0, 23.5, 419.26542968756274, 332.0859375000263 - 0.2, 30000.0, 24.0, 470.1000000000935, 285.4000000000507 - 0.2, 30000.0, 24.5, 521.8970703126315, 211.04531250007938 - 0.2, 30000.0, 25.0, 574.6703125001789, 119.87500000011363 - 0.2, 30000.0, 25.5, 628.433398437737, 22.742187500154557 - 0.2, 30000.0, 26.0, 683.2000000003071, -69.49999999979764 - 0.2, 30000.0, 26.5, 740.2484374999264, -38.06718750005231 - 0.2, 30000.0, 27.0, 798.399999999898, 26.129999999942072 - 0.2, 30000.0, 27.5, 857.4515624998619, 115.44218749993598 - 0.2, 30000.0, 28.0, 917.199999999816, 222.2199999999292 - 0.2, 30000.0, 28.5, 977.442187499759, 338.8140624999222 - 0.2, 30000.0, 29.0, 1037.9749999996893, 457.5749999999151 - 0.2, 30000.0, 29.5, 1098.595312499606, 570.853437499908 - 0.2, 30000.0, 30.0, 1159.0999999995074, 670.9999999999013 - 0.2, 30000.0, 30.5, 1216.5625000001228, 629.7510742186917 - 0.2, 30000.0, 31.0, 1273.762500000125, 571.5585937499452 - 0.2, 30000.0, 31.5, 1330.7562500001256, 500.26025390619816 - 0.2, 30000.0, 32.0, 1387.6000000001243, 419.69374999995 - 0.2, 30000.0, 32.5, 1444.3500000001213, 333.69677734369964 - 0.2, 30000.0, 33.0, 1501.062500000118, 246.10703124994677 - 0.2, 30000.0, 33.5, 1557.7937500001133, 160.76220703119134 - 0.2, 30000.0, 34.0, 1614.6000000001084, 81.49999999993497 - 0.2, 30000.0, 34.5, 1674.4446874999708, 45.477148437526075 - 0.2, 30000.0, 35.0, 1734.1999999999598, 20.03906250005062 - 0.2, 30000.0, 35.5, 1793.6453124999432, 5.850195312579633 - 0.2, 30000.0, 36.0, 1852.5599999999195, 3.575000000113082 - 0.2, 30000.0, 36.5, 1910.7234374998866, 13.877929687651278 - 0.2, 30000.0, 37.0, 1967.9149999998456, 37.42343750019479 - 0.2, 30000.0, 37.5, 2023.9140624997929, 74.87597656274315 - 0.2, 30000.0, 38.0, 2078.4999999997285, 126.90000000029718 - 0.2, 30000.0, 38.5, 2125.74843749595, 244.4052734369144 - 0.2, 30000.0, 39.0, 2174.0999999951982, 351.75781249927843 - 0.2, 30000.0, 39.5, 2224.6015624943534, 438.4564453116243 - 0.2, 30000.0, 40.0, 2278.299999993404, 493.9999999989557 - 0.2, 30000.0, 40.5, 2343.074218749639, 457.75156249966574 - 0.2, 30000.0, 41.0, 2410.4062499994616, 389.399999999555 - 0.2, 30000.0, 41.5, 2478.6101562492427, 298.49843749942244 - 0.2, 30000.0, 42.0, 2545.999999998978, 194.5999999992659 - 0.2, 30000.0, 42.5, 2605.9328124994768, 26.32812500005997 - 0.2, 30000.0, 43.0, 2663.6624999993223, -111.46249999990323 - 0.2, 30000.0, 43.5, 2719.4859374991597, -184.84687499986626 - 0.2, 30000.0, 44.0, 2773.6999999989994, -159.89999999982865 - 0.2, 30000.0, 44.5, 2825.972656249478, 233.34609374990168 - 0.2, 30000.0, 45.0, 2877.481249999423, 698.3562499999407 - 0.2, 30000.0, 45.5, 2928.7742187493686, 1174.6382812500092 - 0.2, 30000.0, 46.0, 2980.39999999931, 1601.700000000114 - 0.2, 30000.0, 46.5, 3033.8992187494737, 1750.029687499957 - 0.2, 30000.0, 47.0, 3088.431249999344, 1795.7624999998934 - 0.2, 30000.0, 47.5, 3144.1476562491844, 1746.014062499811 - 0.2, 30000.0, 48.0, 3201.199999998998, 1607.8999999997116 - 0.2, 30000.0, 48.5, 3259.739843748785, 1388.5359374995928 - 0.2, 30000.0, 49.0, 3319.918749998546, 1095.0374999994547 - 0.2, 30000.0, 49.5, 3381.8882812482843, 734.5203124992985 - 0.2, 30000.0, 50.0, 3445.7999999979993, 314.0999999991194 - 0.2, 35000.0, 0.0, 142.80375036501178, 142.80375036501178 - 0.2, 35000.0, 22.0, 634.3999999999994, 162.90000000000666 - 0.2, 35000.0, 22.5, 771.2105468750135, 136.27265625002264 - 0.2, 35000.0, 23.0, 902.5656250000163, 159.40625000003325 - 0.2, 35000.0, 23.5, 1029.3878906250086, 222.96171875003884 - 0.2, 35000.0, 24.0, 1152.5999999999922, 317.60000000004 - 0.2, 35000.0, 24.5, 1273.1246093749667, 433.9820312500369 - 0.2, 35000.0, 25.0, 1391.884374999935, 562.7687500000302 - 0.2, 35000.0, 25.5, 1509.8019531248974, 694.62109375002 - 0.2, 35000.0, 26.0, 1627.7999999998544, 820.2000000000073 - 0.2, 35000.0, 26.5, 1753.5482421873523, 833.2259765625613 - 0.2, 35000.0, 27.0, 1881.6078124998332, 815.7609375000638 - 0.2, 35000.0, 27.5, 2011.744726562315, 775.0841796875665 - 0.2, 35000.0, 28.0, 2143.724999999798, 718.4750000000704 - 0.2, 35000.0, 28.5, 2277.3146484372824, 653.2126953125752 - 0.2, 35000.0, 29.0, 2412.2796874997675, 586.5765625000822 - 0.2, 35000.0, 29.5, 2548.386132812253, 525.8458984375909 - 0.2, 35000.0, 30.0, 2685.3999999997377, 478.30000000010284 - 0.2, 35000.0, 30.5, 2822.3059570314877, 592.5108398434667 - 0.2, 35000.0, 31.0, 2959.725781250278, 721.0085937496816 - 0.2, 35000.0, 31.5, 3097.499902344069, 857.6161132809 - 0.2, 35000.0, 32.0, 3235.468750000362, 996.1562499996191 - 0.2, 35000.0, 32.5, 3373.472753906656, 1130.4518554683427 - 0.2, 35000.0, 33.0, 3511.3523437504527, 1254.3257812495692 - 0.2, 35000.0, 33.5, 3648.9479492192486, 1361.6008789057964 - 0.2, 35000.0, 34.0, 3786.1000000005474, 1446.0999999995283 - 0.2, 35000.0, 34.5, 3914.8621093761676, 1338.2319531250462 - 0.2, 35000.0, 35.0, 4043.603125001286, 1210.7968750000614 - 0.2, 35000.0, 35.5, 4172.9050781263995, 1073.180859375077 - 0.2, 35000.0, 36.0, 4303.350000001507, 934.7700000000928 - 0.2, 35000.0, 36.5, 4435.519921876608, 804.9503906251075 - 0.2, 35000.0, 37.0, 4569.996875001706, 693.1081250001221 - 0.2, 35000.0, 37.5, 4707.362890626791, 608.629296875135 - 0.2, 35000.0, 38.0, 4848.200000001872, 560.9000000001461 - 0.2, 35000.0, 38.5, 5004.101171875422, 478.257812499573 - 0.2, 35000.0, 39.0, 5158.9281250005115, 493.1624999994251 - 0.2, 35000.0, 39.5, 5310.816015625623, 633.0109374992508 - 0.2, 35000.0, 40.0, 5457.900000000758, 925.1999999990517 - 0.2, 35000.0, 40.5, 5587.293750001003, 1684.411718749737 - 0.2, 35000.0, 41.0, 5712.562500001407, 2535.8437499996057 - 0.2, 35000.0, 41.5, 5836.250000001873, 3391.9789062494474 - 0.2, 35000.0, 42.0, 5960.9000000024025, 4165.299999999265 - 0.2, 35000.0, 42.5, 6099.73593750003, 4589.285937499501 - 0.2, 35000.0, 43.0, 6240.349999999737, 4827.024999999299 - 0.2, 35000.0, 43.5, 6381.01406249932, 4862.601562499053 - 0.2, 35000.0, 44.0, 6519.999999998755, 4680.099999998761 - 0.2, 35000.0, 44.5, 6646.337500000132, 3936.0656250003094 - 0.2, 35000.0, 45.0, 6771.2375000002685, 3073.1375000004373 - 0.2, 35000.0, 45.5, 6896.6687500004555, 2206.4156250005917 - 0.2, 35000.0, 46.0, 7024.600000000703, 1451.000000000785 - 0.2, 35000.0, 46.5, 7166.320312499954, 1333.455468749631 - 0.2, 35000.0, 47.0, 7310.750000000065, 1392.8312499995247 - 0.2, 35000.0, 47.5, 7456.129687500227, 1579.6414062493907 - 0.2, 35000.0, 48.0, 7600.7000000004455, 1844.399999999218 - 0.2, 35000.0, 48.5, 7742.7015625007225, 2137.621093749008 - 0.2, 35000.0, 49.0, 7880.375000001062, 2409.818749998748 - 0.2, 35000.0, 49.5, 8011.960937501462, 2611.507031248435 - 0.2, 35000.0, 50.0, 8135.700000001935, 2693.1999999980635 - 0.2, 39000.0, 0.0, 118.44295876756594, 118.44295876756594 - 0.2, 39000.0, 22.0, 454.900000000006, -6.199999999986545 - 0.2, 39000.0, 22.5, 557.8458984374896, -91.48300781249479 - 0.2, 39000.0, 23.0, 654.4453124999727, -94.13593750000246 - 0.2, 39000.0, 23.5, 745.8970703124552, -28.72089843751031 - 0.2, 39000.0, 24.0, 833.3999999999356, 90.1999999999813 - 0.2, 39000.0, 24.5, 918.1529296874139, 248.0646484374715 - 0.2, 39000.0, 25.0, 1001.3546874998893, 430.31093749995983 - 0.2, 39000.0, 25.5, 1084.2041015623608, 622.3767578124459 - 0.2, 39000.0, 26.0, 1167.8999999998282, 809.6999999999288 - 0.2, 39000.0, 26.5, 1264.9669921874674, 851.1197265625108 - 0.2, 39000.0, 27.0, 1365.9253124999584, 851.4384375000158 - 0.2, 39000.0, 27.5, 1470.03222656245, 817.7966796875231 - 0.2, 39000.0, 28.0, 1576.5449999999423, 757.3350000000341 - 0.2, 39000.0, 28.5, 1684.7208984374354, 677.1939453125482 - 0.2, 39000.0, 29.0, 1793.8171874999314, 584.5140625000663 - 0.2, 39000.0, 29.5, 1903.0911328124291, 486.43589843758605 - 0.2, 39000.0, 30.0, 2011.7999999999304, 390.10000000011064 - 0.2, 39000.0, 30.5, 2108.3077148438115, 391.58027343734193 - 0.2, 39000.0, 31.0, 2203.802343750091, 400.6140624998079 - 0.2, 39000.0, 31.5, 2298.578613281374, 415.8720703122699 - 0.2, 39000.0, 32.0, 2392.931250000162, 436.0249999997277 - 0.2, 39000.0, 32.5, 2487.1549804689544, 459.74355468718136 - 0.2, 39000.0, 33.0, 2581.544531250251, 485.69843749963104 - 0.2, 39000.0, 33.5, 2676.394628906553, 512.5603515620754 - 0.2, 39000.0, 34.0, 2772.0000000003597, 538.9999999995155 - 0.2, 39000.0, 34.5, 2877.1837499999483, 594.064257812323 - 0.2, 39000.0, 35.0, 2982.8999999999155, 643.1546874997842 - 0.2, 39000.0, 35.5, 3088.6312499998708, 682.049023437241 - 0.2, 39000.0, 36.0, 3193.859999999813, 706.5249999996934 - 0.2, 39000.0, 36.5, 3298.0687499997407, 712.3603515621417 - 0.2, 39000.0, 37.0, 3400.73999999965, 695.3328124995862 - 0.2, 39000.0, 37.5, 3501.3562499995423, 651.2201171870258 - 0.2, 39000.0, 38.0, 3599.3999999994153, 575.7999999994606 - 0.2, 39000.0, 38.5, 3686.0132812504935, 320.5056640629173 - 0.2, 39000.0, 39.0, 3773.3437500005944, 100.30468750049886 - 0.2, 39000.0, 39.5, 3862.7273437507147, -56.94863281190919 - 0.2, 39000.0, 40.0, 3955.5000000008545, -123.39999999929296 - 0.2, 39000.0, 40.5, 4060.0562500000606, 16.20234374997439 - 0.2, 39000.0, 41.0, 4167.849999999952, 267.3562500000053 - 0.2, 39000.0, 41.5, 4277.393749999831, 622.9570312500509 - 0.2, 39000.0, 42.0, 4387.199999999703, 1075.900000000117 - 0.2, 39000.0, 42.5, 4486.871093750314, 1738.5062500002432 - 0.2, 39000.0, 43.0, 4587.393750000567, 2436.475000000287 - 0.2, 39000.0, 43.5, 4690.844531250823, 3114.9312500003234 - 0.2, 39000.0, 44.0, 4799.300000001059, 3719.000000000353 - 0.2, 39000.0, 44.5, 4935.801562500191, 4116.825781249684 - 0.2, 39000.0, 45.0, 5073.075000000423, 4361.306249999632 - 0.2, 39000.0, 45.5, 5204.8109375007625, 4428.358593749593 - 0.2, 39000.0, 46.0, 5324.700000001238, 4293.89999999957 - 0.2, 39000.0, 46.5, 5390.374218750199, 3658.2812499997744 - 0.2, 39000.0, 47.0, 5446.006250000142, 2883.2124999995713 - 0.2, 39000.0, 47.5, 5499.710156250047, 2054.8374999993134 - 0.2, 39000.0, 48.0, 5559.599999999903, 1259.2999999989988 - 0.2, 39000.0, 48.5, 5633.789843749702, 582.7437499986299 - 0.2, 39000.0, 49.0, 5730.393749999432, 111.31249999820375 - 0.2, 39000.0, 49.5, 5857.525781249083, -68.85000000229411 - 0.2, 39000.0, 50.0, 6023.299999998644, 128.39999999714928 - 0.2, 43000.0, 0.0, 97.72711325576016, 97.72711325576016 - 0.2, 43000.0, 22.0, -268.1000000000104, 702.8999999999958 - 0.2, 43000.0, 22.5, -284.57519531255696, 342.9734374999691 - 0.2, 43000.0, 23.0, -304.1859375001073, 47.61249999995688 - 0.2, 43000.0, 23.5, -326.8037109376643, -191.57968750004432 - 0.2, 43000.0, 24.0, -352.30000000023074, -383.0000000000383 - 0.2, 43000.0, 24.5, -380.54628906280936, -535.0453125000288 - 0.2, 43000.0, 25.0, -411.414062500403, -656.1125000000184 - 0.2, 43000.0, 25.5, -444.77480468801457, -754.5984375000116 - 0.2, 43000.0, 26.0, -480.50000000064665, -838.9000000000109 - 0.2, 43000.0, 26.5, -519.5179687500613, -1007.1699218751339 - 0.2, 43000.0, 27.0, -560.7037500000623, -1183.1781250001582 - 0.2, 43000.0, 27.5, -603.7476562500566, -1359.9347656251832 - 0.2, 43000.0, 28.0, -648.3400000000427, -1530.450000000207 - 0.2, 43000.0, 28.5, -694.1710937500193, -1687.733984375227 - 0.2, 43000.0, 29.0, -740.9312499999849, -1824.7968750002447 - 0.2, 43000.0, 29.5, -788.3107812499386, -1934.6488281252557 - 0.2, 43000.0, 30.0, -835.9999999998786, -2010.30000000026 - 0.2, 43000.0, 30.5, -881.5859374998817, -1961.4865234378492 - 0.2, 43000.0, 31.0, -927.0624999998802, -1872.4234375004119 - 0.2, 43000.0, 31.5, -972.3203124998778, -1744.051757812979 - 0.2, 43000.0, 32.0, -1017.2499999998731, -1577.312500000547 - 0.2, 43000.0, 32.5, -1061.7421874998658, -1373.1466796881193 - 0.2, 43000.0, 33.0, -1105.6874999998547, -1132.4953125006941 - 0.2, 43000.0, 33.5, -1148.97656249984, -856.299414063274 - 0.2, 43000.0, 34.0, -1191.49999999982, -545.5000000008552 - 0.2, 43000.0, 34.5, -1223.8789062509222, 313.0771874996308 - 0.2, 43000.0, 35.0, -1256.1562500011244, 1155.4124999995538 - 0.2, 43000.0, 35.5, -1289.105468751364, 1931.6015624994625 - 0.2, 43000.0, 36.0, -1323.5000000016462, 2591.7399999993686 - 0.2, 43000.0, 36.5, -1360.1132812519745, 3085.9234374992684 - 0.2, 43000.0, 37.0, -1399.7187500023551, 3364.2474999991573 - 0.2, 43000.0, 37.5, -1443.0898437527917, 3376.8078124990243 - 0.2, 43000.0, 38.0, -1491.0000000032892, 3073.6999999989057 - 0.2, 43000.0, 38.5, -1563.312499999137, 1780.083593750831 - 0.2, 43000.0, 39.0, -1631.8124999988868, 395.03125000112414 - 0.2, 43000.0, 39.5, -1693.0312499985982, -992.4867187485415 - 0.2, 43000.0, 40.0, -1743.4999999982704, -2293.49999999817 - 0.2, 43000.0, 40.5, -1752.445312499716, -3251.1515625005773 - 0.2, 43000.0, 41.0, -1754.62499999971, -4011.5125000007056 - 0.2, 43000.0, 41.5, -1757.4921874996976, -4552.7671875008555 - 0.2, 43000.0, 42.0, -1768.4999999996744, -4853.100000001037 - 0.2, 43000.0, 42.5, -1831.0820312507951, -4649.468750000941 - 0.2, 43000.0, 43.0, -1902.3187500009772, -4257.775000001362 - 0.2, 43000.0, 43.5, -1975.271093751236, -3752.6937500018394 - 0.2, 43000.0, 44.0, -2043.0000000016016, -3208.900000002362 - 0.2, 43000.0, 44.5, -2065.9726562507954, -2834.2249999999035 - 0.2, 43000.0, 45.0, -2082.8812500011095, -2516.924999999844 - 0.2, 43000.0, 45.5, -2099.8242187514084, -2278.4124999997857 - 0.2, 43000.0, 46.0, -2122.9000000016545, -2140.0999999997343 - 0.2, 43000.0, 46.5, -2184.792968751844, -2296.665625001085 - 0.2, 43000.0, 47.0, -2254.3812500024906, -2526.9500000012845 - 0.2, 43000.0, 47.5, -2327.128906253271, -2783.0593750014978 - 0.2, 43000.0, 48.0, -2398.50000000421, -3017.1000000017257 - 0.2, 43000.0, 48.5, -2463.958593755332, -3181.1781250019703 - 0.2, 43000.0, 49.0, -2518.968750006662, -3227.4000000022343 - 0.2, 43000.0, 49.5, -2558.994531258224, -3107.87187500252 - 0.2, 43000.0, 50.0, -2579.500000010042, -2774.700000002824 - 0.2, 48000.0, 0.0, 76.8506572741036, 76.8506572741036 - 0.2, 48000.0, 22.0, -262.9000000000161, 585.7999999999469 - 0.2, 48000.0, 22.5, -248.48593750000725, 293.6105468749449 - 0.2, 48000.0, 23.0, -246.5624999999897, 57.65312499994127 - 0.2, 48000.0, 23.5, -255.50781249996368, -129.73085937506477 - 0.2, 48000.0, 24.0, -273.6999999999293, -276.2000000000733 - 0.2, 48000.0, 24.5, -299.51718749988646, -389.4128906250845 - 0.2, 48000.0, 25.0, -331.3374999998352, -477.0281250000985 - 0.2, 48000.0, 25.5, -367.53906249977564, -546.7042968751159 - 0.2, 48000.0, 26.0, -406.49999999970794, -606.100000000137 - 0.2, 48000.0, 26.5, -434.7832031250764, -744.619335937563 - 0.2, 48000.0, 27.0, -461.906875000075, -892.8465625000749 - 0.2, 48000.0, 27.5, -488.27460937507084, -1044.4267578125862 - 0.2, 48000.0, 28.0, -514.290000000064, -1193.005000000097 - 0.2, 48000.0, 28.5, -540.3566406250548, -1332.2263671876062 - 0.2, 48000.0, 29.0, -566.8781250000433, -1455.7359375001145 - 0.2, 48000.0, 29.5, -594.2580468750299, -1557.1787890626208 - 0.2, 48000.0, 30.0, -622.9000000000144, -1630.200000000124 - 0.2, 48000.0, 30.5, -661.2310546877395, -1589.1733398440417 - 0.2, 48000.0, 31.0, -700.8671875002955, -1514.5648437503532 - 0.2, 48000.0, 31.5, -741.4478515628577, -1407.5692382816728 - 0.2, 48000.0, 32.0, -782.612500000427, -1269.3812500005013 - 0.2, 48000.0, 32.5, -824.000585938002, -1101.1956054693387 - 0.2, 48000.0, 33.0, -865.2515625005836, -904.2070312506833 - 0.2, 48000.0, 33.5, -906.0048828131717, -679.6102539070386 - 0.2, 48000.0, 34.0, -945.9000000007659, -428.6000000009028 - 0.2, 48000.0, 34.5, -971.6195312503331, 240.4204687495926 - 0.2, 48000.0, 35.0, -996.9937500003638, 896.0562499995121 - 0.2, 48000.0, 35.5, -1022.8960937503981, 1499.7039062494132 - 0.2, 48000.0, 36.0, -1050.2000000004366, 2012.7599999993026 - 0.2, 48000.0, 36.5, -1079.778906250482, 2396.621093749176 - 0.2, 48000.0, 37.0, -1112.5062500005345, 2612.6837499990233 - 0.2, 48000.0, 37.5, -1149.255468750597, 2622.344531248853 - 0.2, 48000.0, 38.0, -1190.9000000006704, 2386.999999998661 - 0.2, 48000.0, 38.5, -1261.8960937481556, 1386.0144531245123 - 0.2, 48000.0, 39.0, -1327.3062499977898, 312.7593749994794 - 0.2, 48000.0, 39.5, -1382.763281247369, -764.250390625537 - 0.2, 48000.0, 40.0, -1423.8999999968887, -1776.5000000005402 - 0.2, 48000.0, 40.5, -1410.142187500413, -2529.781250000443 - 0.2, 48000.0, 41.0, -1387.8125000005123, -3131.55000000055 - 0.2, 48000.0, 41.5, -1367.0265625006177, -3563.5687500006616 - 0.2, 48000.0, 42.0, -1357.9000000007306, -3807.6000000007784 - 0.2, 48000.0, 42.5, -1416.9937500003068, -3655.2226562495657 - 0.2, 48000.0, 43.0, -1489.4000000003814, -3354.4562499994786 - 0.2, 48000.0, 43.5, -1566.6562500004652, -2963.1367187494116 - 0.2, 48000.0, 44.0, -1640.3000000005593, -2539.0999999993705 - 0.2, 48000.0, 44.5, -1670.5640624997602, -2239.2445312506416 - 0.2, 48000.0, 45.0, -1692.8124999996573, -1982.7187500008163 - 0.2, 48000.0, 45.5, -1711.104687499544, -1787.7335937510013 - 0.2, 48000.0, 46.0, -1729.499999999425, -1672.500000001195 - 0.2, 48000.0, 46.5, -1764.5851562499458, -1798.490624999633 - 0.2, 48000.0, 47.0, -1802.8812500000479, -1983.3499999995493 - 0.2, 48000.0, 47.5, -1843.4367187501327, -2187.984374999447 - 0.2, 48000.0, 48.0, -1885.3000000001844, -2373.299999999321 - 0.2, 48000.0, 48.5, -1927.519531250186, -2500.203124999167 - 0.2, 48000.0, 49.0, -1969.1437500001211, -2529.599999998981 - 0.2, 48000.0, 49.5, -2009.221093749975, -2422.3968749987544 - 0.2, 48000.0, 50.0, -2046.79999999973, -2139.4999999984866 - 0.25, 0.0, 0.0, 535.960285419727, 535.960285419727 - 0.25, 0.0, 22.0, 1494.6999999999998, 903.0999999999987 - 0.25, 0.0, 22.5, 1778.413085937506, 991.9580078124986 - 0.25, 0.0, 23.0, 2059.1828125000106, 1078.6734374999983 - 0.25, 0.0, 23.5, 2337.9861328125144, 1163.8521484374985 - 0.25, 0.0, 24.0, 2615.8000000000175, 1248.0999999999979 - 0.25, 0.0, 24.5, 2893.6013671875194, 1332.0228515624985 - 0.25, 0.0, 25.0, 3172.367187500022, 1416.2265624999993 - 0.25, 0.0, 25.5, 3453.0744140625247, 1501.3169921875003 - 0.25, 0.0, 26.0, 3736.7000000000285, 1587.9000000000015 - 0.25, 0.0, 26.5, 4034.4707031250327, 1682.0201171875037 - 0.25, 0.0, 27.0, 4337.699375000037, 1779.1553125000028 - 0.25, 0.0, 27.5, 4645.60585937504, 1878.9791015625026 - 0.25, 0.0, 28.0, 4957.410000000044, 1981.1650000000009 - 0.25, 0.0, 28.5, 5272.331640625041, 2085.3865234374985 - 0.25, 0.0, 29.0, 5589.59062500004, 2191.3171874999966 - 0.25, 0.0, 29.5, 5908.406796875034, 2298.6305078124933 - 0.25, 0.0, 30.0, 6228.000000000028, 2406.99999999999 - 0.25, 0.0, 30.5, 6539.392285156158, 2513.3129882812473 - 0.25, 0.0, 31.0, 6850.782031249893, 2620.294531249997 - 0.25, 0.0, 31.5, 7162.169824218627, 2727.883496093746 - 0.25, 0.0, 32.0, 7473.55624999986, 2836.0187499999943 - 0.25, 0.0, 32.5, 7784.941894531094, 2944.6391601562427 - 0.25, 0.0, 33.0, 8096.327343749825, 3053.6835937499905 - 0.25, 0.0, 33.5, 8407.713183593552, 3163.0909179687364 - 0.25, 0.0, 34.0, 8719.09999999978, 3272.799999999984 - 0.25, 0.0, 34.5, 9030.496992187545, 3383.110234375094 - 0.25, 0.0, 35.0, 9341.895312500079, 3493.565625000115 - 0.25, 0.0, 35.5, 9653.294726562617, 3604.0707031251377 - 0.25, 0.0, 36.0, 9964.695000000162, 3714.530000000162 - 0.25, 0.0, 36.5, 10276.095898437712, 3824.848046875189 - 0.25, 0.0, 37.0, 10587.497187500276, 3934.929375000219 - 0.25, 0.0, 37.5, 10898.898632812838, 4044.6785156252513 - 0.25, 0.0, 38.0, 11210.300000000416, 4154.000000000286 - 0.25, 0.0, 38.5, 11521.70527343685, 4262.388085937293 - 0.25, 0.0, 39.0, 11833.107812499245, 4370.370312499757 - 0.25, 0.0, 39.5, 12144.506445311643, 4477.942382812221 - 0.25, 0.0, 40.0, 12455.899999999023, 4585.099999999678 - 0.25, 0.0, 40.5, 12767.276562499621, 4691.0976562499945 - 0.25, 0.0, 41.0, 13078.649999999527, 4796.968749999998 - 0.25, 0.0, 41.5, 13390.023437499442, 4903.005468750006 - 0.25, 0.0, 42.0, 13701.39999999935, 5009.500000000018 - 0.25, 0.0, 42.5, 14012.552343749896, 5117.779687500002 - 0.25, 0.0, 43.0, 14323.806249999823, 5226.687500000008 - 0.25, 0.0, 43.5, 14635.25703124974, 5336.101562500016 - 0.25, 0.0, 44.0, 14946.999999999634, 5445.900000000026 - 0.25, 0.0, 44.5, 15260.095312499865, 5556.03124999998 - 0.25, 0.0, 45.0, 15573.287499999802, 5666.274999999975 - 0.25, 0.0, 45.5, 15886.285937499717, 5776.481249999965 - 0.25, 0.0, 46.0, 16198.799999999617, 5886.49999999995 - 0.25, 0.0, 46.5, 16509.08593749971, 5995.271093749992 - 0.25, 0.0, 47.0, 16818.887499999615, 6103.918749999988 - 0.25, 0.0, 47.5, 17128.495312499494, 6212.657031249981 - 0.25, 0.0, 48.0, 17438.19999999935, 6321.69999999997 - 0.25, 0.0, 48.5, 17748.292187499184, 6431.261718749956 - 0.25, 0.0, 49.0, 18059.062499998996, 6541.556249999938 - 0.25, 0.0, 49.5, 18370.801562498782, 6652.797656249918 - 0.25, 0.0, 50.0, 18683.799999998544, 6765.199999999891 - 0.25, 2000.0, 0.0, 501.80340309812374, 501.80340309812374 - 0.25, 2000.0, 22.0, 1443.4999999999993, 856.7999999999994 - 0.25, 2000.0, 22.5, 1717.4394531250007, 942.0275390625021 - 0.25, 2000.0, 23.0, 1988.5593750000037, 1025.1921875000055 - 0.25, 2000.0, 23.5, 2257.7996093750094, 1106.885742187511 - 0.25, 2000.0, 24.0, 2526.1000000000154, 1187.7000000000178 - 0.25, 2000.0, 24.5, 2794.4003906250264, 1268.2267578125259 - 0.25, 2000.0, 25.0, 3063.6406250000387, 1349.0578125000357 - 0.25, 2000.0, 25.5, 3334.7605468750526, 1430.7849609375462 - 0.25, 2000.0, 26.0, 3608.7000000000708, 1514.00000000006 - 0.25, 2000.0, 26.5, 3896.267187500031, 1604.6117187499926 - 0.25, 2000.0, 27.0, 4189.097500000035, 1698.1987499999907 - 0.25, 2000.0, 27.5, 4486.439062500041, 1794.4414062499884 - 0.25, 2000.0, 28.0, 4787.540000000042, 1893.019999999985 - 0.25, 2000.0, 28.5, 5091.648437500043, 1993.6148437499814 - 0.25, 2000.0, 29.0, 5398.012500000039, 2095.906249999977 - 0.25, 2000.0, 29.5, 5705.880312500037, 2199.5745312499716 - 0.25, 2000.0, 30.0, 6014.50000000003, 2304.299999999966 - 0.25, 2000.0, 30.5, 6315.224999999979, 2407.2942382812366 - 0.25, 2000.0, 31.0, 6615.949999999973, 2510.9414062499836 - 0.25, 2000.0, 31.5, 6916.674999999967, 2615.1569335937274 - 0.25, 2000.0, 32.0, 7217.399999999964, 2719.856249999974 - 0.25, 2000.0, 32.5, 7518.124999999962, 2824.95478515622 - 0.25, 2000.0, 33.0, 7818.849999999956, 2930.367968749963 - 0.25, 2000.0, 33.5, 8119.57499999995, 3036.011230468707 - 0.25, 2000.0, 34.0, 8420.299999999945, 3141.7999999999493 - 0.25, 2000.0, 34.5, 8721.025000000325, 3247.3433203126147 - 0.25, 2000.0, 35.0, 9021.7500000004, 3352.8921875001433 - 0.25, 2000.0, 35.5, 9322.475000000484, 3458.391210937676 - 0.25, 2000.0, 36.0, 9623.20000000057, 3563.7850000002113 - 0.25, 2000.0, 36.5, 9923.92500000067, 3669.0181640627516 - 0.25, 2000.0, 37.0, 10224.650000000778, 3774.0353125002944 - 0.25, 2000.0, 37.5, 10525.375000000888, 3878.781054687842 - 0.25, 2000.0, 38.0, 10826.100000001014, 3983.2000000003936 - 0.25, 2000.0, 38.5, 11126.824999998971, 4087.049023437098 - 0.25, 2000.0, 39.0, 11427.549999998751, 4190.557812499519 - 0.25, 2000.0, 39.5, 11728.274999998508, 4293.712695311934 - 0.25, 2000.0, 40.0, 12028.999999998234, 4396.49999999934 - 0.25, 2000.0, 40.5, 12329.724999999786, 4498.024218749953 - 0.25, 2000.0, 41.0, 12630.449999999733, 4599.506249999939 - 0.25, 2000.0, 41.5, 12931.174999999672, 4701.285156249926 - 0.25, 2000.0, 42.0, 13231.899999999621, 4803.699999999908 - 0.25, 2000.0, 42.5, 13532.386718750033, 4908.769531249876 - 0.25, 2000.0, 43.0, 13832.968750000055, 5014.481249999837 - 0.25, 2000.0, 43.5, 14133.741406250085, 5120.502343749789 - 0.25, 2000.0, 44.0, 14434.800000000125, 5226.499999999734 - 0.25, 2000.0, 44.5, 14737.189062500123, 5330.914843750009 - 0.25, 2000.0, 45.0, 15039.675000000168, 5435.131250000022 - 0.25, 2000.0, 45.5, 15341.97343750022, 5539.307031250035 - 0.25, 2000.0, 46.0, 15643.80000000028, 5643.600000000051 - 0.25, 2000.0, 46.5, 15943.45234374981, 5748.414062499915 - 0.25, 2000.0, 47.0, 16242.631249999771, 5853.562499999893 - 0.25, 2000.0, 47.5, 16541.619531249737, 5959.104687499875 - 0.25, 2000.0, 48.0, 16840.699999999706, 6065.099999999858 - 0.25, 2000.0, 48.5, 17140.155468749697, 6171.607812499839 - 0.25, 2000.0, 49.0, 17440.268749999694, 6278.687499999827 - 0.25, 2000.0, 49.5, 17741.322656249715, 6386.398437499815 - 0.25, 2000.0, 50.0, 18043.59999999975, 6494.799999999809 - 0.25, 5000.0, 0.0, 453.8137927724164, 453.8137927724164 - 0.25, 5000.0, 22.0, 1367.7000000000005, 983.4000000000015 - 0.25, 5000.0, 22.5, 1627.2435546875029, 1058.1148437499992 - 0.25, 5000.0, 23.0, 1884.1140625000073, 1156.2437499999974 - 0.25, 5000.0, 23.5, 2139.2025390625136, 1272.7257812499956 - 0.25, 5000.0, 24.0, 2393.4000000000233, 1402.499999999994 - 0.25, 5000.0, 24.5, 2647.597460937534, 1540.5054687499935 - 0.25, 5000.0, 25.0, 2902.685937500046, 1681.6812499999937 - 0.25, 5000.0, 25.5, 3159.5564453125608, 1820.9664062499946 - 0.25, 5000.0, 26.0, 3419.100000000076, 1953.299999999992 - 0.25, 5000.0, 26.5, 3691.564648437521, 2019.5419921875182 - 0.25, 5000.0, 27.0, 3969.019062500028, 2065.6203125000247 - 0.25, 5000.0, 27.5, 4250.750195312539, 2095.744726562527 - 0.25, 5000.0, 28.0, 4536.045000000051, 2114.1250000000355 - 0.25, 5000.0, 28.5, 4824.190429687563, 2124.970898437534 - 0.25, 5000.0, 29.0, 5114.473437500075, 2132.4921875000427 - 0.25, 5000.0, 29.5, 5406.1809765625885, 2140.898632812554 - 0.25, 5000.0, 30.0, 5698.600000000103, 2154.400000000056 - 0.25, 5000.0, 30.5, 5983.528417968654, 2233.8978515625286 - 0.25, 5000.0, 31.0, 6268.455468749888, 2321.510937500035 - 0.25, 5000.0, 31.5, 6553.381347656124, 2416.049804687532 - 0.25, 5000.0, 32.0, 6838.306249999854, 2516.3250000000426 - 0.25, 5000.0, 32.5, 7123.230371093587, 2621.1470703125524 - 0.25, 5000.0, 33.0, 7408.15390624982, 2729.3265625000604 - 0.25, 5000.0, 33.5, 7693.077050781049, 2839.6740234375666 - 0.25, 5000.0, 34.0, 7977.999999999778, 2951.0000000000837 - 0.25, 5000.0, 34.5, 8262.918437500251, 3050.012148437516 - 0.25, 5000.0, 35.0, 8547.837500000322, 3148.7765625000293 - 0.25, 5000.0, 35.5, 8832.757812500398, 3247.2564453125437 - 0.25, 5000.0, 36.0, 9117.68000000049, 3345.4150000000627 - 0.25, 5000.0, 36.5, 9402.60468750059, 3443.215429687585 - 0.25, 5000.0, 37.0, 9687.5325000007, 3540.6209375001113 - 0.25, 5000.0, 37.5, 9972.464062500825, 3637.594726562641 - 0.25, 5000.0, 38.0, 10257.400000000967, 3734.1000000001754 - 0.25, 5000.0, 38.5, 10542.357812499797, 3828.942968749899 - 0.25, 5000.0, 39.0, 10827.312499999756, 3923.843749999877 - 0.25, 5000.0, 39.5, 11112.260937499721, 4019.0226562498515 - 0.25, 5000.0, 40.0, 11397.199999999679, 4114.6999999998225 - 0.25, 5000.0, 40.5, 11682.103125000083, 4212.135156249919 - 0.25, 5000.0, 41.0, 11967.00000000014, 4310.093749999896 - 0.25, 5000.0, 41.5, 12251.896875000213, 4408.380468749869 - 0.25, 5000.0, 42.0, 12536.800000000303, 4506.7999999998365 - 0.25, 5000.0, 42.5, 12821.520312499908, 4604.4578125000735 - 0.25, 5000.0, 43.0, 13106.337499999887, 4702.137500000103 - 0.25, 5000.0, 43.5, 13391.335937499873, 4799.923437500135 - 0.25, 5000.0, 44.0, 13676.599999999873, 4897.90000000017 - 0.25, 5000.0, 44.5, 13963.089062500128, 4996.397656249954 - 0.25, 5000.0, 45.0, 14249.662500000173, 5095.156249999928 - 0.25, 5000.0, 45.5, 14536.054687500227, 5194.161718749898 - 0.25, 5000.0, 46.0, 14822.000000000278, 5293.399999999863 - 0.25, 5000.0, 46.5, 15105.900781249811, 5392.47812499984 - 0.25, 5000.0, 47.0, 15389.356249999732, 5491.912499999782 - 0.25, 5000.0, 47.5, 15672.633593749635, 5591.8406249997115 - 0.25, 5000.0, 48.0, 15955.999999999527, 5692.399999999635 - 0.25, 5000.0, 48.5, 16239.722656249409, 5793.728124999546 - 0.25, 5000.0, 49.0, 16524.068749999275, 5895.962499999448 - 0.25, 5000.0, 49.5, 16809.305468749146, 5999.24062499934 - 0.25, 5000.0, 50.0, 17095.699999998997, 6103.69999999922 - 0.25, 10000.0, 0.0, 381.94919978550575, 381.94919978550575 - 0.25, 10000.0, 22.0, 1246.9999999999986, 694.7999999999992 - 0.25, 10000.0, 22.5, 1483.626171874997, 767.460156249998 - 0.25, 10000.0, 23.0, 1717.8281249999964, 838.4937499999963 - 0.25, 10000.0, 23.5, 1950.4160156249952, 908.3804687499937 - 0.25, 10000.0, 24.0, 2182.199999999994, 977.599999999991 - 0.25, 10000.0, 24.5, 2413.9902343749936, 1046.6320312499874 - 0.25, 10000.0, 25.0, 2646.5968749999925, 1115.9562499999836 - 0.25, 10000.0, 25.5, 2880.830078124992, 1186.0523437499794 - 0.25, 10000.0, 26.0, 3117.4999999999905, 1257.3999999999737 - 0.25, 10000.0, 26.5, 3365.928906250026, 1334.6296875000025 - 0.25, 10000.0, 27.0, 3618.901250000032, 1414.3075000000028 - 0.25, 10000.0, 27.5, 3875.7679687500367, 1496.2015625000029 - 0.25, 10000.0, 28.0, 4135.880000000042, 1580.0800000000024 - 0.25, 10000.0, 28.5, 4398.588281250048, 1665.7109375000027 - 0.25, 10000.0, 29.0, 4663.243750000055, 1752.862500000003 - 0.25, 10000.0, 29.5, 4929.19734375006, 1841.302812500002 - 0.25, 10000.0, 30.0, 5195.800000000068, 1930.800000000002 - 0.25, 10000.0, 30.5, 5455.587499999984, 2020.4163085937498 - 0.25, 10000.0, 31.0, 5715.37499999998, 2110.6929687499996 - 0.25, 10000.0, 31.5, 5975.162499999977, 2201.4653320312477 - 0.25, 10000.0, 32.0, 6234.949999999975, 2292.5687499999963 - 0.25, 10000.0, 32.5, 6494.737499999973, 2383.838574218746 - 0.25, 10000.0, 33.0, 6754.52499999997, 2475.1101562499944 - 0.25, 10000.0, 33.5, 7014.312499999968, 2566.2188476562437 - 0.25, 10000.0, 34.0, 7274.099999999969, 2656.999999999992 - 0.25, 10000.0, 34.5, 7533.89078125023, 2744.4141796875356 - 0.25, 10000.0, 35.0, 7793.68125000029, 2831.445312500042 - 0.25, 10000.0, 35.5, 8053.471093750353, 2918.20253906255 - 0.25, 10000.0, 36.0, 8313.260000000426, 3004.7950000000565 - 0.25, 10000.0, 36.5, 8573.047656250505, 3091.3318359375635 - 0.25, 10000.0, 37.0, 8832.833750000596, 3177.9221875000703 - 0.25, 10000.0, 37.5, 9092.617968750692, 3264.6751953125795 - 0.25, 10000.0, 38.0, 9352.400000000802, 3351.700000000086 - 0.25, 10000.0, 38.5, 9612.171093749379, 3439.94316406217 - 0.25, 10000.0, 39.0, 9871.94374999925, 3528.2421874996126 - 0.25, 10000.0, 39.5, 10131.71953124911, 3616.5201171870503 - 0.25, 10000.0, 40.0, 10391.499999998952, 3704.6999999994837 - 0.25, 10000.0, 40.5, 10651.298437499809, 3792.2429687499944 - 0.25, 10000.0, 41.0, 10911.099999999775, 3879.718749999985 - 0.25, 10000.0, 41.5, 11170.901562499743, 3967.235156249973 - 0.25, 10000.0, 42.0, 11430.699999999722, 4054.8999999999555 - 0.25, 10000.0, 42.5, 11690.273437499762, 4142.848437499945 - 0.25, 10000.0, 43.0, 11949.924999999675, 4231.14999999993 - 0.25, 10000.0, 43.5, 12209.739062499571, 4319.901562499908 - 0.25, 10000.0, 44.0, 12469.799999999452, 4409.199999999885 - 0.25, 10000.0, 44.5, 12731.016406250097, 4499.595312500009 - 0.25, 10000.0, 45.0, 12992.318750000144, 4590.550000000019 - 0.25, 10000.0, 45.5, 13253.461718750197, 4681.979687500035 - 0.25, 10000.0, 46.0, 13514.200000000252, 4773.800000000049 - 0.25, 10000.0, 46.5, 13773.065624999752, 4865.160937499932 - 0.25, 10000.0, 47.0, 14031.52499999971, 4957.049999999906 - 0.25, 10000.0, 47.5, 14289.821874999678, 5049.68906249988 - 0.25, 10000.0, 48.0, 14548.199999999662, 5143.299999999847 - 0.25, 10000.0, 48.5, 14806.903124999668, 5238.10468749981 - 0.25, 10000.0, 49.0, 15066.17499999969, 5334.324999999771 - 0.25, 10000.0, 49.5, 15326.259374999745, 5432.182812499721 - 0.25, 10000.0, 50.0, 15587.399999999827, 5531.89999999967 - 0.25, 15000.0, 0.0, 319.383404643872, 319.383404643872 - 0.25, 15000.0, 22.0, 665.1000000000016, 451.3000000000007 - 0.25, 15000.0, 22.5, 791.1873046875024, 486.4457031250005 - 0.25, 15000.0, 23.0, 916.0140625000033, 521.1468749999998 - 0.25, 15000.0, 23.5, 1040.008789062504, 555.5746093749998 - 0.25, 15000.0, 24.0, 1163.6000000000054, 589.8999999999994 - 0.25, 15000.0, 24.5, 1287.2162109375063, 624.2941406249987 - 0.25, 15000.0, 25.0, 1411.2859375000075, 658.9281249999983 - 0.25, 15000.0, 25.5, 1536.2376953125092, 693.9730468749981 - 0.25, 15000.0, 26.0, 1662.5000000000105, 729.5999999999972 - 0.25, 15000.0, 26.5, 1795.0322265625039, 768.7117187500007 - 0.25, 15000.0, 27.0, 1929.990937500004, 808.903750000001 - 0.25, 15000.0, 27.5, 2067.027929687505, 849.8789062500011 - 0.25, 15000.0, 28.0, 2205.795000000005, 891.3400000000015 - 0.25, 15000.0, 28.5, 2345.943945312506, 932.9898437500021 - 0.25, 15000.0, 29.0, 2487.1265625000055, 974.5312500000022 - 0.25, 15000.0, 29.5, 2628.9946484375055, 1015.6670312500024 - 0.25, 15000.0, 30.0, 2771.2000000000057, 1056.1000000000026 - 0.25, 15000.0, 30.5, 2909.7095703124946, 1088.4380859375008 - 0.25, 15000.0, 31.0, 3048.210937499993, 1120.1546874999997 - 0.25, 15000.0, 31.5, 3186.706835937493, 1151.6283203125004 - 0.25, 15000.0, 32.0, 3325.1999999999916, 1183.2374999999997 - 0.25, 15000.0, 32.5, 3463.6931640624916, 1215.360742187499 - 0.25, 15000.0, 33.0, 3602.18906249999, 1248.3765624999985 - 0.25, 15000.0, 33.5, 3740.690429687489, 1282.6634765624983 - 0.25, 15000.0, 34.0, 3879.199999999988, 1318.5999999999979 - 0.25, 15000.0, 34.5, 4017.8222265625236, 1368.1269531250111 - 0.25, 15000.0, 35.0, 4156.4484375000275, 1418.9593750000126 - 0.25, 15000.0, 35.5, 4295.07167968753, 1470.3746093750146 - 0.25, 15000.0, 36.0, 4433.685000000032, 1521.6500000000158 - 0.25, 15000.0, 36.5, 4572.281445312536, 1572.0628906250179 - 0.25, 15000.0, 37.0, 4710.8540625000405, 1620.8906250000196 - 0.25, 15000.0, 37.5, 4849.395898437546, 1667.410546875021 - 0.25, 15000.0, 38.0, 4987.900000000051, 1710.9000000000233 - 0.25, 15000.0, 38.5, 5126.256054687546, 1745.7373046875305 - 0.25, 15000.0, 39.0, 5264.6140625000535, 1778.6390625000363 - 0.25, 15000.0, 39.5, 5402.990039062564, 1809.9712890625424 - 0.25, 15000.0, 40.0, 5541.400000000077, 1840.1000000000492 - 0.25, 15000.0, 40.5, 5679.927343749993, 1870.4546874999894 - 0.25, 15000.0, 41.0, 5818.493749999986, 1899.912499999984 - 0.25, 15000.0, 41.5, 5957.08828124998, 1928.4140624999795 - 0.25, 15000.0, 42.0, 6095.699999999971, 1955.8999999999737 - 0.25, 15000.0, 42.5, 6234.1851562500115, 1979.709375000002 - 0.25, 15000.0, 43.0, 6372.718750000008, 2003.425000000001 - 0.25, 15000.0, 43.5, 6511.342968750005, 2028.0281250000005 - 0.25, 15000.0, 44.0, 6650.100000000001, 2054.5 - 0.25, 15000.0, 44.5, 6789.453906249983, 2089.454687499996 - 0.25, 15000.0, 45.0, 6928.856249999975, 2125.9874999999934 - 0.25, 15000.0, 45.5, 7068.180468749968, 2162.8265624999894 - 0.25, 15000.0, 46.0, 7207.2999999999565, 2198.6999999999844 - 0.25, 15000.0, 46.5, 7345.474999999979, 2228.1445312500173 - 0.25, 15000.0, 47.0, 7483.437499999973, 2255.75625000002 - 0.25, 15000.0, 47.5, 7621.306249999968, 2281.9398437500226 - 0.25, 15000.0, 48.0, 7759.199999999956, 2307.100000000026 - 0.25, 15000.0, 48.5, 7897.237499999947, 2331.641406250029 - 0.25, 15000.0, 49.0, 8035.53749999994, 2355.9687500000314 - 0.25, 15000.0, 49.5, 8174.218749999931, 2380.4867187500345 - 0.25, 15000.0, 50.0, 8313.39999999992, 2405.6000000000377 - 0.25, 20000.0, 0.0, 265.20647567588355, 265.20647567588355 - 0.25, 20000.0, 22.0, 867.5999999999941, 472.6999999999999 - 0.25, 20000.0, 22.5, 1034.561718749987, 557.9396484374982 - 0.25, 20000.0, 23.0, 1199.2812499999795, 625.245312499996 - 0.25, 20000.0, 23.5, 1362.4101562499711, 677.4283203124924 - 0.25, 20000.0, 24.0, 1524.599999999962, 717.2999999999878 - 0.25, 20000.0, 24.5, 1686.5023437499508, 747.6716796874827 - 0.25, 20000.0, 25.0, 1848.7687499999386, 771.3546874999765 - 0.25, 20000.0, 25.5, 2012.0507812499247, 791.1603515624697 - 0.25, 20000.0, 26.0, 2176.9999999999077, 809.8999999999614 - 0.25, 20000.0, 26.5, 2351.031445312498, 851.4560546874824 - 0.25, 20000.0, 27.0, 2528.4196875, 898.7728124999807 - 0.25, 20000.0, 27.5, 2708.6568359375024, 951.0494140624793 - 0.25, 20000.0, 28.0, 2891.2350000000038, 1007.4849999999789 - 0.25, 20000.0, 28.5, 3075.6462890625085, 1067.2787109374783 - 0.25, 20000.0, 29.0, 3261.3828125000123, 1129.6296874999782 - 0.25, 20000.0, 29.5, 3447.936679687517, 1193.737070312479 - 0.25, 20000.0, 30.0, 3634.8000000000216, 1258.79999999998 - 0.25, 20000.0, 30.5, 3815.570117187458, 1312.1345703124734 - 0.25, 20000.0, 31.0, 3996.1953124999527, 1365.9546874999678 - 0.25, 20000.0, 31.5, 4176.729101562446, 1420.5912109374608 - 0.25, 20000.0, 32.0, 4357.224999999943, 1476.3749999999534 - 0.25, 20000.0, 32.5, 4537.73652343744, 1533.6369140624454 - 0.25, 20000.0, 33.0, 4718.317187499939, 1592.7078124999364 - 0.25, 20000.0, 33.5, 4899.020507812436, 1653.918554687427 - 0.25, 20000.0, 34.0, 5079.89999999994, 1717.5999999999171 - 0.25, 20000.0, 34.5, 5262.530039062122, 1809.2649609373407 - 0.25, 20000.0, 35.0, 5445.2984374995585, 1901.6640624998092 - 0.25, 20000.0, 35.5, 5628.11386718699, 1992.729882812274 - 0.25, 20000.0, 36.0, 5810.88499999942, 2080.3949999997344 - 0.25, 20000.0, 36.5, 5993.520507811841, 2162.5919921871887 - 0.25, 20000.0, 37.0, 6175.929062499258, 2237.253437499638 - 0.25, 20000.0, 37.5, 6358.019335936667, 2302.311914062083 - 0.25, 20000.0, 38.0, 6539.6999999990685, 2355.6999999995205 - 0.25, 20000.0, 38.5, 6719.911523437567, 2367.552929687598 - 0.25, 20000.0, 39.0, 6900.032812500129, 2378.014062500135 - 0.25, 20000.0, 39.5, 7080.1876953127, 2391.1931640626785 - 0.25, 20000.0, 40.0, 7260.500000000281, 2411.2000000002263 - 0.25, 20000.0, 40.5, 7441.614062499877, 2455.489062500044 - 0.25, 20000.0, 41.0, 7622.924999999835, 2509.4875000000598 - 0.25, 20000.0, 41.5, 7804.348437499775, 2571.96718750008 - 0.25, 20000.0, 42.0, 7985.7999999996955, 2641.7000000001067 - 0.25, 20000.0, 42.5, 8166.882812499845, 2715.680468749862 - 0.25, 20000.0, 43.0, 8347.949999999813, 2795.1687499998193 - 0.25, 20000.0, 43.5, 8529.042187499781, 2879.6476562497733 - 0.25, 20000.0, 44.0, 8710.199999999753, 2968.599999999722 - 0.25, 20000.0, 44.5, 8891.592968749828, 3065.2117187499202 - 0.25, 20000.0, 45.0, 9073.081249999805, 3163.7812499999086 - 0.25, 20000.0, 45.5, 9254.653906249787, 3262.3101562498946 - 0.25, 20000.0, 46.0, 9436.299999999772, 3358.7999999998756 - 0.25, 20000.0, 46.5, 9618.047656249873, 3444.619531249921 - 0.25, 20000.0, 47.0, 9799.83124999984, 3527.0562499999 - 0.25, 20000.0, 47.5, 9981.6242187498, 3606.7648437498765 - 0.25, 20000.0, 48.0, 10163.399999999756, 3684.3999999998523 - 0.25, 20000.0, 48.5, 10345.132031249705, 3760.616406249827 - 0.25, 20000.0, 49.0, 10526.793749999648, 3836.068749999801 - 0.25, 20000.0, 49.5, 10708.358593749583, 3911.4117187497736 - 0.25, 20000.0, 50.0, 10889.799999999512, 3987.2999999997483 - 0.25, 25000.0, 0.0, 218.56046810054232, 218.56046810054232 - 0.25, 25000.0, 22.0, 648.1000000000045, 461.5000000000052 - 0.25, 25000.0, 22.5, 775.1974609375043, 384.0847656250001 - 0.25, 25000.0, 23.0, 900.0453125000017, 356.5843749999974 - 0.25, 25000.0, 23.5, 1023.2205078124974, 371.21679687499665 - 0.25, 25000.0, 24.0, 1145.299999999991, 420.19999999999766 - 0.25, 25000.0, 24.5, 1266.860742187483, 495.75195312500034 - 0.25, 25000.0, 25.0, 1388.4796874999743, 590.090625000004 - 0.25, 25000.0, 25.5, 1510.7337890624644, 695.4339843750084 - 0.25, 25000.0, 26.0, 1634.1999999999534, 804.0000000000136 - 0.25, 25000.0, 26.5, 1765.2890625000064, 844.0304687500284 - 0.25, 25000.0, 27.0, 1899.0775000000033, 868.0637500000355 - 0.25, 25000.0, 27.5, 2035.1421875000008, 879.2851562500429 - 0.25, 25000.0, 28.0, 2173.0599999999963, 880.8800000000502 - 0.25, 25000.0, 28.5, 2312.4078124999915, 876.0335937500574 - 0.25, 25000.0, 29.0, 2452.762499999987, 867.9312500000649 - 0.25, 25000.0, 29.5, 2593.7009374999807, 859.7582812500729 - 0.25, 25000.0, 30.0, 2734.799999999975, 854.7000000000806 - 0.25, 25000.0, 30.5, 2870.6749023437974, 900.4637695312929 - 0.25, 25000.0, 31.0, 3006.33671875007, 951.4726562500589 - 0.25, 25000.0, 31.5, 3141.834863281343, 1006.6717773438273 - 0.25, 25000.0, 32.0, 3277.2187500001196, 1065.0062500000968 - 0.25, 25000.0, 32.5, 3412.537792968898, 1125.4211914063683 - 0.25, 25000.0, 33.0, 3547.8414062501806, 1186.8617187501407 - 0.25, 25000.0, 33.5, 3683.1790039064645, 1248.2729492189142 - 0.25, 25000.0, 34.0, 3818.6000000002496, 1308.600000000189 - 0.25, 25000.0, 34.5, 3955.1607421878875, 1324.4258203125187 - 0.25, 25000.0, 35.0, 4091.8078125004677, 1341.092187500013 - 0.25, 25000.0, 35.5, 4228.494726563052, 1361.578710937507 - 0.25, 25000.0, 36.0, 4365.175000000642, 1388.8650000000002 - 0.25, 25000.0, 36.5, 4501.802148438235, 1425.9306640624914 - 0.25, 25000.0, 37.0, 4638.329687500835, 1475.755312499982 - 0.25, 25000.0, 37.5, 4774.711132813436, 1541.318554687471 - 0.25, 25000.0, 38.0, 4910.900000001042, 1625.5999999999594 - 0.25, 25000.0, 38.5, 5045.784570312332, 1802.1937500002064 - 0.25, 25000.0, 39.0, 5180.935937499765, 1966.8500000002402 - 0.25, 25000.0, 39.5, 5316.544335937198, 2106.856250000277 - 0.25, 25000.0, 40.0, 5452.7999999996355, 2209.5000000003174 - 0.25, 25000.0, 40.5, 5591.552343750215, 2193.5414062501372 - 0.25, 25000.0, 41.0, 5730.668750000298, 2142.206250000192 - 0.25, 25000.0, 41.5, 5869.675781250405, 2070.192968750257 - 0.25, 25000.0, 42.0, 6008.100000000533, 1992.2000000003304 - 0.25, 25000.0, 42.5, 6142.7023437503285, 1953.6406249999566 - 0.25, 25000.0, 43.0, 6276.881250000485, 1926.2124999999548 - 0.25, 25000.0, 43.5, 6411.269531250666, 1912.328124999953 - 0.25, 25000.0, 44.0, 6546.500000000862, 1914.3999999999492 - 0.25, 25000.0, 44.5, 6687.006250000044, 1951.1531250001854 - 0.25, 25000.0, 45.0, 6828.100000000121, 2002.1625000002591 - 0.25, 25000.0, 45.5, 6968.89375000022, 2063.315625000344 - 0.25, 25000.0, 46.0, 7108.500000000341, 2130.50000000044 - 0.25, 25000.0, 46.5, 7241.753906250184, 2176.5328125001583 - 0.25, 25000.0, 47.0, 7373.7562500001995, 2229.6000000002164 - 0.25, 25000.0, 47.5, 7505.330468750206, 2294.817187500287 - 0.25, 25000.0, 48.0, 7637.300000000205, 2377.3000000003703 - 0.25, 25000.0, 48.5, 7770.488281250192, 2482.1640625004684 - 0.25, 25000.0, 49.0, 7905.718750000174, 2614.5250000005794 - 0.25, 25000.0, 49.5, 8043.814843750147, 2779.4984375007084 - 0.25, 25000.0, 50.0, 8185.600000000114, 2982.2000000008525 - 0.25, 30000.0, 0.0, 178.64758241186544, 178.64758241186544 - 0.25, 30000.0, 22.0, 353.10000000000196, 255.2999999999828 - 0.25, 30000.0, 22.5, 417.5056640625137, 332.02558593749296 - 0.25, 30000.0, 23.0, 482.2671875000283, 368.42031250000485 - 0.25, 30000.0, 23.5, 547.4951171875467, 371.80488281251877 - 0.25, 30000.0, 24.0, 613.3000000000698, 349.50000000003564 - 0.25, 30000.0, 24.5, 679.792382812599, 308.826367187556 - 0.25, 30000.0, 25.0, 747.082812500135, 257.1046875000801 - 0.25, 30000.0, 25.5, 815.2818359376788, 201.65566406260876 - 0.25, 30000.0, 26.0, 884.5000000002318, 149.8000000001428 - 0.25, 30000.0, 26.5, 956.8015624999464, 181.85117187496152 - 0.25, 30000.0, 27.0, 1030.4549999999263, 236.30812499995744 - 0.25, 30000.0, 27.5, 1105.2359374999003, 307.9785156249529 - 0.25, 30000.0, 28.0, 1180.919999999868, 391.6699999999478 - 0.25, 30000.0, 28.5, 1257.282812499827, 482.1902343749425 - 0.25, 30000.0, 29.0, 1334.0999999997782, 574.346874999937 - 0.25, 30000.0, 29.5, 1411.1471874997192, 662.9475781249324 - 0.25, 30000.0, 30.0, 1488.1999999996494, 742.799999999927 - 0.25, 30000.0, 30.5, 1562.2761718751046, 727.3002929687079 - 0.25, 30000.0, 31.0, 1636.1718750001087, 700.4210937499594 - 0.25, 30000.0, 31.5, 1709.925390625112, 664.7235351562094 - 0.25, 30000.0, 32.0, 1783.5750000001135, 622.7687499999598 - 0.25, 30000.0, 32.5, 1857.1589843751153, 577.1178710937088 - 0.25, 30000.0, 33.0, 1930.715625000117, 530.3320312499559 - 0.25, 30000.0, 33.5, 2004.2832031251191, 484.9723632811998 - 0.25, 30000.0, 34.0, 2077.9000000001197, 443.59999999994307 - 0.25, 30000.0, 34.5, 2153.5648437499467, 430.2941015625098 - 0.25, 30000.0, 35.0, 2229.1687499999352, 424.0484375000243 - 0.25, 30000.0, 35.5, 2304.56328124992, 425.3748046875419 - 0.25, 30000.0, 36.0, 2379.599999999898, 434.78500000006176 - 0.25, 30000.0, 36.5, 2454.1304687498714, 452.7908203125848 - 0.25, 30000.0, 37.0, 2528.006249999838, 479.90406250011085 - 0.25, 30000.0, 37.5, 2601.0789062497965, 516.6365234376397 - 0.25, 30000.0, 38.0, 2673.199999999747, 563.5000000001721 - 0.25, 30000.0, 38.5, 2740.3609374971747, 655.6285156245779 - 0.25, 30000.0, 39.0, 2808.2749999966513, 740.9593749994833 - 0.25, 30000.0, 39.5, 2877.651562496063, 812.3105468743785 - 0.25, 30000.0, 40.0, 2949.1999999954032, 862.4999999992626 - 0.25, 30000.0, 40.5, 3028.2703124997947, 849.8398437497772 - 0.25, 30000.0, 41.0, 3109.074999999684, 815.4562499997024 - 0.25, 30000.0, 41.5, 3190.467187499545, 765.9695312496133 - 0.25, 30000.0, 42.0, 3271.299999999375, 707.9999999995066 - 0.25, 30000.0, 42.5, 3347.0359374996406, 607.7031250000475 - 0.25, 30000.0, 43.0, 3421.2749999995344, 528.350000000073 - 0.25, 30000.0, 43.5, 3494.226562499426, 492.7468750000999 - 0.25, 30000.0, 44.0, 3566.099999999319, 523.7000000001269 - 0.25, 30000.0, 44.5, 3636.7335937496123, 803.4453124999188 - 0.25, 30000.0, 45.0, 3706.8562499995664, 1131.58749999994 - 0.25, 30000.0, 45.5, 3776.825781249521, 1467.1609374999794 - 0.25, 30000.0, 46.0, 3846.9999999994748, 1769.2000000000398 - 0.25, 30000.0, 46.5, 3918.3499999995734, 1881.9929687499603 - 0.25, 30000.0, 47.0, 3990.374999999455, 1925.2187499999172 - 0.25, 30000.0, 47.5, 4063.1874999993115, 1903.8101562498628 - 0.25, 30000.0, 48.0, 4136.899999999141, 1822.6999999997956 - 0.25, 30000.0, 48.5, 4211.624999998949, 1686.8210937497151 - 0.25, 30000.0, 49.0, 4287.474999998733, 1501.1062499996235 - 0.25, 30000.0, 49.5, 4364.562499998496, 1270.4882812495198 - 0.25, 30000.0, 50.0, 4442.999999998237, 999.8999999993982 - 0.25, 35000.0, 0.0, 144.72485146938686, 144.72485146938686 - 0.25, 35000.0, 22.0, 568.2999999999995, 212.60000000000454 - 0.25, 35000.0, 22.5, 687.8335937500094, 197.3449218750159 - 0.25, 35000.0, 23.0, 803.2562500000118, 218.64062500002356 - 0.25, 35000.0, 23.5, 915.3007812500073, 269.6910156250279 - 0.25, 35000.0, 24.0, 1024.6999999999966, 343.70000000002915 - 0.25, 35000.0, 24.5, 1132.1867187499806, 433.87148437502753 - 0.25, 35000.0, 25.0, 1238.4937499999598, 533.4093750000236 - 0.25, 35000.0, 25.5, 1344.3539062499356, 635.5175781250173 - 0.25, 35000.0, 26.0, 1450.4999999999088, 733.4000000000092 - 0.25, 35000.0, 26.5, 1563.2662109373919, 750.085546875041 - 0.25, 35000.0, 27.0, 1678.1040624998777, 744.9431250000422 - 0.25, 35000.0, 27.5, 1794.7861328123645, 723.206640625044 - 0.25, 35000.0, 28.0, 1913.0849999998525, 690.1100000000466 - 0.25, 35000.0, 28.5, 2032.773242187341, 650.8871093750502 - 0.25, 35000.0, 29.0, 2153.6234374998303, 610.7718750000554 - 0.25, 35000.0, 29.5, 2275.40816406232, 574.9982031250614 - 0.25, 35000.0, 30.0, 2397.89999999981, 548.8000000000707 - 0.25, 35000.0, 30.5, 2519.6689453126733, 638.6963867185495 - 0.25, 35000.0, 31.0, 2641.8046875002024, 738.9898437497765 - 0.25, 35000.0, 31.5, 2764.194335937733, 845.2680664060047 - 0.25, 35000.0, 32.0, 2886.725000000264, 953.118749999734 - 0.25, 35000.0, 32.5, 3009.283789062797, 1058.1295898434655 - 0.25, 35000.0, 33.0, 3131.7578125003306, 1155.8882812496997 - 0.25, 35000.0, 33.5, 3254.0341796878647, 1241.9825195309352 - 0.25, 35000.0, 34.0, 3376.000000000401, 1311.9999999996742 - 0.25, 35000.0, 34.5, 3492.047929688324, 1245.9262890625364 - 0.25, 35000.0, 35.0, 3608.082812500907, 1165.960937500049 - 0.25, 35000.0, 35.5, 3724.515039063488, 1078.7013671875607 - 0.25, 35000.0, 36.0, 3841.755000001065, 990.7450000000714 - 0.25, 35000.0, 36.5, 3960.2130859386366, 908.689257812583 - 0.25, 35000.0, 37.0, 4080.299687501202, 839.1315625000948 - 0.25, 35000.0, 37.5, 4202.425195313764, 788.6693359376065 - 0.25, 35000.0, 38.0, 4327.000000001318, 763.9000000001133 - 0.25, 35000.0, 38.5, 4462.213867187758, 713.5808593746757 - 0.25, 35000.0, 39.0, 4596.664062500321, 732.140624999565 - 0.25, 35000.0, 39.5, 4729.032226562896, 839.0300781244346 - 0.25, 35000.0, 40.0, 4858.000000000489, 1053.6999999992845 - 0.25, 35000.0, 40.5, 4974.441406250708, 1598.88437499983 - 0.25, 35000.0, 41.0, 5087.968750000985, 2209.4374999997426 - 0.25, 35000.0, 41.5, 5200.386718751309, 2823.4968749996374 - 0.25, 35000.0, 42.0, 5313.500000001674, 3379.1999999995132 - 0.25, 35000.0, 42.5, 5436.687499999998, 3689.512499999643 - 0.25, 35000.0, 43.0, 5561.149999999788, 3867.8124999994957 - 0.25, 35000.0, 43.5, 5685.662499999487, 3902.3062499993184 - 0.25, 35000.0, 44.0, 5808.999999999085, 3781.1999999991103 - 0.25, 35000.0, 44.5, 5923.453125000096, 3256.9382812502336 - 0.25, 35000.0, 45.0, 6036.875000000197, 2647.793750000327 - 0.25, 35000.0, 45.5, 6150.634375000336, 2036.277343750444 - 0.25, 35000.0, 46.0, 6266.100000000518, 1504.9000000005885 - 0.25, 35000.0, 46.5, 6391.06640624997, 1431.1960937497465 - 0.25, 35000.0, 47.0, 6517.906250000048, 1484.643749999674 - 0.25, 35000.0, 47.5, 6645.417968750166, 1629.74453124958 - 0.25, 35000.0, 48.0, 6772.400000000324, 1830.9999999994618 - 0.25, 35000.0, 48.5, 6897.6507812505215, 2052.911718749313 - 0.25, 35000.0, 49.0, 7019.9687500007685, 2259.981249999127 - 0.25, 35000.0, 49.5, 7138.152343751062, 2416.7101562488997 - 0.25, 35000.0, 50.0, 7251.000000001406, 2487.5999999986343 - 0.25, 39000.0, 0.0, 120.03634058220472, 120.03634058220472 - 0.25, 39000.0, 22.0, 417.20000000000425, 76.30000000000973 - 0.25, 39000.0, 22.5, 508.28691406249226, 21.09804687500382 - 0.25, 39000.0, 23.0, 594.6546874999799, 24.67812499999824 - 0.25, 39000.0, 23.5, 677.2201171874673, 76.69414062499267 - 0.25, 39000.0, 24.0, 756.8999999999536, 166.79999999998648 - 0.25, 39000.0, 24.5, 834.6111328124383, 284.6496093749795 - 0.25, 39000.0, 25.0, 911.2703124999211, 419.8968749999715 - 0.25, 39000.0, 25.5, 987.7943359374016, 562.1957031249613 - 0.25, 39000.0, 26.0, 1065.099999999879, 701.1999999999489 - 0.25, 39000.0, 26.5, 1152.822656249976, 736.6533203125047 - 0.25, 39000.0, 27.0, 1243.65874999997, 742.9821875000072 - 0.25, 39000.0, 27.5, 1337.0304687499638, 725.2537109375126 - 0.25, 39000.0, 28.0, 1432.3599999999574, 688.5350000000203 - 0.25, 39000.0, 28.5, 1529.0695312499527, 637.8931640625292 - 0.25, 39000.0, 29.0, 1626.5812499999495, 578.3953125000417 - 0.25, 39000.0, 29.5, 1724.3173437499472, 515.1085546875554 - 0.25, 39000.0, 30.0, 1821.6999999999477, 453.1000000000713 - 0.25, 39000.0, 30.5, 1909.885937500048, 460.42158203114076 - 0.25, 39000.0, 31.0, 1997.3500000000686, 473.15703124986726 - 0.25, 39000.0, 31.5, 2084.301562500092, 490.37490234359143 - 0.25, 39000.0, 32.0, 2170.950000000119, 511.14374999981317 - 0.25, 39000.0, 32.5, 2257.504687500148, 534.5321289060312 - 0.25, 39000.0, 33.0, 2344.1750000001816, 559.6085937497464 - 0.25, 39000.0, 33.5, 2431.170312500218, 585.441699218459 - 0.25, 39000.0, 34.0, 2518.7000000002568, 611.0999999996681 - 0.25, 39000.0, 34.5, 2613.00765624996, 657.2635937498768 - 0.25, 39000.0, 35.0, 2707.6937499999362, 699.3312499998488 - 0.25, 39000.0, 35.5, 2802.3929687499035, 734.3132812498177 - 0.25, 39000.0, 36.0, 2896.739999999861, 759.2199999997835 - 0.25, 39000.0, 36.5, 2990.3695312498085, 771.0617187497462 - 0.25, 39000.0, 37.0, 3082.9162499997424, 766.8487499997045 - 0.25, 39000.0, 37.5, 3174.0148437496637, 743.5914062496611 - 0.25, 39000.0, 38.0, 3263.299999999571, 698.299999999613 - 0.25, 39000.0, 38.5, 3344.529687500336, 526.074609375268 - 0.25, 39000.0, 39.0, 3426.2625000004036, 378.6781250003187 - 0.25, 39000.0, 39.5, 3509.4390625004844, 275.76757812538017 - 0.25, 39000.0, 40.0, 3595.000000000579, 237.00000000045293 - 0.25, 39000.0, 40.5, 3688.8351562500297, 343.897656249981 - 0.25, 39000.0, 41.0, 3784.9562499999497, 529.5062500000015 - 0.25, 39000.0, 41.5, 3882.3242187498595, 788.7367187500329 - 0.25, 39000.0, 42.0, 3979.8999999997645, 1116.5000000000766 - 0.25, 39000.0, 42.5, 4070.4414062502183, 1591.8125000001678 - 0.25, 39000.0, 43.0, 4161.593750000399, 2091.8375000001965 - 0.25, 39000.0, 43.5, 4254.799218750581, 2577.843750000221 - 0.25, 39000.0, 44.0, 4351.500000000751, 3011.1000000002414 - 0.25, 39000.0, 44.5, 4467.802343750138, 3299.355468749777 - 0.25, 39000.0, 45.0, 4584.618750000299, 3478.8062499997404 - 0.25, 39000.0, 45.5, 4697.525781250538, 3532.1289062497135 - 0.25, 39000.0, 46.0, 4802.1000000008735, 3441.9999999996962 - 0.25, 39000.0, 46.5, 4868.578125000174, 2993.467187499842 - 0.25, 39000.0, 47.0, 4928.012500000142, 2445.8874999997006 - 0.25, 39000.0, 47.5, 4986.11562500008, 1860.9890624995207 - 0.25, 39000.0, 48.0, 5048.599999999991, 1300.4999999993047 - 0.25, 39000.0, 48.5, 5121.178124999858, 826.1484374990478 - 0.25, 39000.0, 49.0, 5209.562499999679, 499.662499998748 - 0.25, 39000.0, 49.5, 5319.465624999444, 382.77031249840184 - 0.25, 39000.0, 50.0, 5456.599999999145, 537.1999999980126 - 0.25, 43000.0, 0.0, 99.04181027683381, 99.04181027683381 - 0.25, 43000.0, 22.0, -139.5000000000078, 598.4999999999966 - 0.25, 43000.0, 22.5, -140.06367187504128, 326.71035156247746 - 0.25, 43000.0, 23.0, -143.09062500007795, 104.76718749996947 - 0.25, 43000.0, 23.5, -148.4472656251197, -73.78457031253026 - 0.25, 43000.0, 24.0, -156.0000000001686, -215.40000000002405 - 0.25, 43000.0, 24.5, -165.6152343752266, -326.53417968751455 - 0.25, 43000.0, 25.0, -177.15937500029588, -413.642187500005 - 0.25, 43000.0, 25.5, -190.49882812537822, -483.17910156249684 - 0.25, 43000.0, 26.0, -205.50000000047575, -541.5999999999938 - 0.25, 43000.0, 26.5, -222.43125000004986, -663.6947265625995 - 0.25, 43000.0, 27.0, -240.78000000005187, -791.4884375001178 - 0.25, 43000.0, 27.5, -260.34375000004906, -919.7216796876365 - 0.25, 43000.0, 28.0, -280.92000000004066, -1043.1350000001544 - 0.25, 43000.0, 28.5, -302.30625000002533, -1156.4689453126707 - 0.25, 43000.0, 29.0, -324.30000000000246, -1254.4640625001844 - 0.25, 43000.0, 29.5, -346.69874999997074, -1331.8608984376938 - 0.25, 43000.0, 30.0, -369.29999999992975, -1383.4000000001977 - 0.25, 43000.0, 30.5, -390.6547851561404, -1340.6652343752535 - 0.25, 43000.0, 31.0, -411.9257812498858, -1267.5687500002973 - 0.25, 43000.0, 31.5, -433.02919921862997, -1164.8660156253445 - 0.25, 43000.0, 32.0, -453.8812499998723, -1033.3125000003945 - 0.25, 43000.0, 32.5, -474.39814453111234, -873.663671875445 - 0.25, 43000.0, 33.0, -494.49609374984914, -686.6750000004977 - 0.25, 43000.0, 33.5, -514.0913085935829, -473.1019531255524 - 0.25, 43000.0, 34.0, -533.099999999812, -233.70000000061003 - 0.25, 43000.0, 34.5, -544.3742578131681, 419.18269531222177 - 0.25, 43000.0, 35.0, -555.5671875008146, 1059.3921874996659 - 0.25, 43000.0, 35.5, -567.2677734384886, 1649.1818359371027 - 0.25, 43000.0, 36.0, -580.0650000011935, 2150.8049999995364 - 0.25, 43000.0, 36.5, -594.5478515639326, 2526.51503906196 - 0.25, 43000.0, 37.0, -611.3053125017094, 2738.565312499384 - 0.25, 43000.0, 37.5, -630.9263671895276, 2749.2091796867953 - 0.25, 43000.0, 38.0, -654.0000000023904, 2520.6999999992004 - 0.25, 43000.0, 38.5, -695.6255859368721, 1541.4738281255932 - 0.25, 43000.0, 39.0, -734.3578124991915, 493.2843750007987 - 0.25, 43000.0, 39.5, -767.561132811484, -556.3222656239632 - 0.25, 43000.0, 40.0, -792.5999999987481, -1539.7999999986878 - 0.25, 43000.0, 40.5, -786.1054687497547, -2262.6632812504313 - 0.25, 43000.0, 41.0, -774.4687499997378, -2835.081250000525 - 0.25, 43000.0, 41.5, -763.347656249716, -3240.283593750635 - 0.25, 43000.0, 42.0, -758.3999999996843, -3461.5000000007676 - 0.25, 43000.0, 42.5, -792.5843750005658, -3297.4171875006887 - 0.25, 43000.0, 43.0, -833.3375000006921, -2989.6250000010014 - 0.25, 43000.0, 43.5, -875.3968750008745, -2595.1703125013564 - 0.25, 43000.0, 44.0, -913.5000000011341, -2171.100000001745 - 0.25, 43000.0, 44.5, -917.6617187505873, -1876.449218749943 - 0.25, 43000.0, 45.0, -917.2312500008236, -1625.4812499999016 - 0.25, 43000.0, 45.5, -916.8351562510475, -1434.4476562498598 - 0.25, 43000.0, 46.0, -921.1000000012325, -1319.599999999822 - 0.25, 43000.0, 46.5, -954.8203125013785, -1427.9593750007962 - 0.25, 43000.0, 47.0, -994.3875000018595, -1592.7000000009411 - 0.25, 43000.0, 47.5, -1036.3609375024419, -1777.7656250010966 - 0.25, 43000.0, 48.0, -1077.3000000031445, -1947.1000000012637 - 0.25, 43000.0, 48.5, -1113.7640625039862, -2064.6468750014433 - 0.25, 43000.0, 49.0, -1142.3125000049858, -2094.3500000016384 - 0.25, 43000.0, 49.5, -1159.5046875061628, -2000.153125001846 - 0.25, 43000.0, 50.0, -1161.9000000075348, -1746.0000000020655 - 0.25, 48000.0, 0.0, 77.88450885141765, 77.88450885141765 - 0.25, 48000.0, 22.0, -149.10000000001247, 495.9999999999602 - 0.25, 48000.0, 22.5, -128.74101562500474, 275.2146484374589 - 0.25, 48000.0, 23.0, -117.94687499999027, 97.8078124999563 - 0.25, 48000.0, 23.5, -115.45429687496917, -42.10292968754784 - 0.25, 48000.0, 24.0, -119.99999999994134, -150.40000000005352 - 0.25, 48000.0, 24.5, -130.32070312490674, -232.965820312561 - 0.25, 48000.0, 25.0, -145.15312499986524, -295.6828125000709 - 0.25, 48000.0, 25.5, -163.23398437481697, -344.43339843758247 - 0.25, 48000.0, 26.0, -183.29999999976178, -385.1000000000971 - 0.25, 48000.0, 26.5, -194.76367187505812, -485.81992187504903 - 0.25, 48000.0, 27.0, -205.15312500005797, -593.7781250000587 - 0.25, 48000.0, 27.5, -214.80351562505595, -704.1847656250684 - 0.25, 48000.0, 28.0, -224.0500000000523, -812.2500000000778 - 0.25, 48000.0, 28.5, -233.22773437504708, -913.1839843750863 - 0.25, 48000.0, 29.0, -242.67187500004067, -1002.1968750000946 - 0.25, 48000.0, 29.5, -252.71757812503296, -1074.4988281251012 - 0.25, 48000.0, 30.0, -263.7000000000245, -1125.3000000001061 - 0.25, 48000.0, 30.5, -282.36093750018307, -1089.6262695314642 - 0.25, 48000.0, 31.0, -302.0187500002263, -1028.603906250258 - 0.25, 48000.0, 31.5, -322.3984375002743, -943.1749023440597 - 0.25, 48000.0, 32.0, -343.22500000032744, -834.2812500003666 - 0.25, 48000.0, 32.5, -364.22343750038544, -702.8649414066798 - 0.25, 48000.0, 33.0, -385.1187500004483, -549.8679687504997 - 0.25, 48000.0, 33.5, -405.6359375005164, -376.23232421932596 - 0.25, 48000.0, 34.0, -425.5000000005892, -182.9000000006592 - 0.25, 48000.0, 34.5, -434.59382812524626, 325.8411328122038 - 0.25, 48000.0, 35.0, -443.42187500026773, 824.1421874996481 - 0.25, 48000.0, 35.5, -452.6464843752916, 1282.8083984370796 - 0.25, 48000.0, 36.0, -462.9300000003189, 1672.6449999994975 - 0.25, 48000.0, 36.5, -474.9347656253509, 1964.4572265619045 - 0.25, 48000.0, 37.0, -489.3231250003887, 2129.050312499294 - 0.25, 48000.0, 37.5, -506.7574218754336, 2137.229492186667 - 0.25, 48000.0, 38.0, -527.9000000004867, 1959.799999999028 - 0.25, 48000.0, 38.5, -571.2964843736987, 1202.127343749622 - 0.25, 48000.0, 39.0, -610.45312499844, 389.9437499995911 - 0.25, 48000.0, 39.5, -642.0582031231426, -424.73671875043146 - 0.25, 48000.0, 40.0, -662.7999999978016, -1189.9000000004326 - 0.25, 48000.0, 40.5, -641.9078125002964, -1758.5398437503225 - 0.25, 48000.0, 41.0, -614.5125000003671, -2211.6312500004 - 0.25, 48000.0, 41.5, -588.2859375004421, -2535.1570312504787 - 0.25, 48000.0, 42.0, -570.900000000521, -2715.1000000005624 - 0.25, 48000.0, 42.5, -605.2375000002218, -2591.899999999673 - 0.25, 48000.0, 43.0, -649.6750000002789, -2355.2999999996036 - 0.25, 48000.0, 43.5, -697.8000000003433, -2049.4999999995507 - 0.25, 48000.0, 44.0, -743.2000000004155, -1718.6999999995166 - 0.25, 48000.0, 44.5, -755.7593749998123, -1483.0726562504458 - 0.25, 48000.0, 45.0, -762.2499999997301, -1280.4562500005666 - 0.25, 48000.0, 45.5, -765.7406249996413, -1124.6617187506934 - 0.25, 48000.0, 46.0, -769.2999999995482, -1029.5000000008258 - 0.25, 48000.0, 46.5, -785.4499999999665, -1116.9031249997115 - 0.25, 48000.0, 47.0, -804.0250000000473, -1249.3124999996423 - 0.25, 48000.0, 47.5, -824.3125000001146, -1397.2906249995572 - 0.25, 48000.0, 48.0, -845.6000000001553, -1531.3999999994523 - 0.25, 48000.0, 48.5, -867.1750000001565, -1622.2031249993238 - 0.25, 48000.0, 49.0, -888.3250000001057, -1640.2624999991694 - 0.25, 48000.0, 49.5, -908.3374999999895, -1556.140624998984 - 0.25, 48000.0, 50.0, -926.4999999997955, -1340.3999999987655 - 0.30000000000000004, 0.0, 0.0, 544.7419838034795, 544.7419838034795 - 0.30000000000000004, 0.0, 22.0, 1428.8999999999996, 952.7 - 0.30000000000000004, 0.0, 22.5, 1700.1201171874948, 1041.6490234374992 - 0.30000000000000004, 0.0, 23.0, 1968.53906249999, 1128.832812499998 - 0.30000000000000004, 0.0, 23.5, 2235.0884765624837, 1214.7501953124965 - 0.30000000000000004, 0.0, 24.0, 2500.6999999999784, 1299.899999999996 - 0.30000000000000004, 0.0, 24.5, 2766.305273437474, 1384.7810546874953 - 0.30000000000000004, 0.0, 25.0, 3032.8359374999663, 1469.8921874999942 - 0.30000000000000004, 0.0, 25.5, 3301.223632812458, 1555.7322265624923 - 0.30000000000000004, 0.0, 26.0, 3572.3999999999482, 1642.7999999999909 - 0.30000000000000004, 0.0, 26.5, 3857.0734375000015, 1735.8654296874988 - 0.30000000000000004, 0.0, 27.0, 4146.957500000002, 1831.4003124999992 - 0.30000000000000004, 0.0, 27.5, 4441.307812500005, 1929.1712890625 - 0.30000000000000004, 0.0, 28.0, 4739.380000000003, 2028.945000000001 - 0.30000000000000004, 0.0, 28.5, 5040.429687500007, 2130.488085937501 - 0.30000000000000004, 0.0, 29.0, 5343.7125000000115, 2233.567187500003 - 0.30000000000000004, 0.0, 29.5, 5648.484062500015, 2337.948945312506 - 0.30000000000000004, 0.0, 30.0, 5954.000000000018, 2443.4000000000087 - 0.30000000000000004, 0.0, 30.5, 6251.700000000011, 2547.8129882812254 - 0.30000000000000004, 0.0, 31.0, 6549.4000000000115, 2653.007031249972 - 0.30000000000000004, 0.0, 31.5, 6847.100000000011, 2758.927246093717 - 0.30000000000000004, 0.0, 32.0, 7144.80000000001, 2865.5187499999624 - 0.30000000000000004, 0.0, 32.5, 7442.500000000008, 2972.7266601562064 - 0.30000000000000004, 0.0, 33.0, 7740.200000000004, 3080.4960937499527 - 0.30000000000000004, 0.0, 33.5, 8037.899999999999, 3188.772167968697 - 0.30000000000000004, 0.0, 34.0, 8335.599999999995, 3297.4999999999422 - 0.30000000000000004, 0.0, 34.5, 8633.299999999888, 3406.1780468749785 - 0.30000000000000004, 0.0, 35.0, 8930.999999999864, 3515.240624999976 - 0.30000000000000004, 0.0, 35.5, 9228.699999999837, 3624.675390624972 - 0.30000000000000004, 0.0, 36.0, 9526.399999999805, 3734.4699999999693 - 0.30000000000000004, 0.0, 36.5, 9824.099999999773, 3844.612109374966 - 0.30000000000000004, 0.0, 37.0, 10121.79999999974, 3955.0893749999636 - 0.30000000000000004, 0.0, 37.5, 10419.499999999694, 4065.88945312496 - 0.30000000000000004, 0.0, 38.0, 10717.199999999657, 4176.999999999957 - 0.30000000000000004, 0.0, 38.5, 11014.900000000154, 4288.6871093749805 - 0.30000000000000004, 0.0, 39.0, 11312.600000000199, 4400.515624999979 - 0.30000000000000004, 0.0, 39.5, 11610.300000000243, 4512.411328124979 - 0.30000000000000004, 0.0, 40.0, 11908.000000000302, 4624.299999999979 - 0.30000000000000004, 0.0, 40.5, 12205.69609374993, 4735.812499999983 - 0.30000000000000004, 0.0, 41.0, 12503.393749999905, 4847.287499999976 - 0.30000000000000004, 0.0, 41.5, 12801.094531249866, 4958.7687499999665 - 0.30000000000000004, 0.0, 42.0, 13098.799999999821, 5070.299999999955 - 0.30000000000000004, 0.0, 42.5, 13396.29296875009, 5182.354687499936 - 0.30000000000000004, 0.0, 43.0, 13693.88125000011, 5294.374999999919 - 0.30000000000000004, 0.0, 43.5, 13991.653906250127, 5406.2328124999 - 0.30000000000000004, 0.0, 44.0, 14289.700000000146, 5517.799999999883 - 0.30000000000000004, 0.0, 44.5, 14589.01874999986, 5628.624218750006 - 0.30000000000000004, 0.0, 45.0, 14888.424999999816, 5739.031250000003 - 0.30000000000000004, 0.0, 45.5, 15187.643749999757, 5849.02265625 - 0.30000000000000004, 0.0, 46.0, 15486.399999999689, 5958.599999999997 - 0.30000000000000004, 0.0, 46.5, 15783.039843749943, 6067.174999999951 - 0.30000000000000004, 0.0, 47.0, 16079.218749999924, 6175.5749999999325 - 0.30000000000000004, 0.0, 47.5, 16375.213281249899, 6284.037499999913 - 0.30000000000000004, 0.0, 48.0, 16671.299999999876, 6392.799999999891 - 0.30000000000000004, 0.0, 48.5, 16967.755468749852, 6502.099999999866 - 0.30000000000000004, 0.0, 49.0, 17264.85624999983, 6612.174999999841 - 0.30000000000000004, 0.0, 49.5, 17562.878906249793, 6723.262499999815 - 0.30000000000000004, 0.0, 50.0, 17862.099999999755, 6835.5999999997875 - 0.30000000000000004, 2000.0, 0.0, 510.0254416592407, 510.0254416592407 - 0.30000000000000004, 2000.0, 22.0, 1380.6000000000001, 902.8000000000001 - 0.30000000000000004, 2000.0, 22.5, 1642.5824218749995, 988.4382812499999 - 0.30000000000000004, 2000.0, 23.0, 1901.8781249999984, 1072.2437499999999 - 0.30000000000000004, 2000.0, 23.5, 2159.3847656249973, 1154.72734375 - 0.30000000000000004, 2000.0, 24.0, 2415.999999999995, 1236.3999999999996 - 0.30000000000000004, 2000.0, 24.5, 2672.621484374993, 1317.7726562499993 - 0.30000000000000004, 2000.0, 25.0, 2930.1468749999904, 1399.356249999999 - 0.30000000000000004, 2000.0, 25.5, 3189.473828124989, 1481.6617187499987 - 0.30000000000000004, 2000.0, 26.0, 3451.499999999984, 1565.1999999999985 - 0.30000000000000004, 2000.0, 26.5, 3726.5552734375, 1654.9144531249992 - 0.30000000000000004, 2000.0, 27.0, 4006.6440624999996, 1747.136874999999 - 0.30000000000000004, 2000.0, 27.5, 4291.0470703125, 1841.618359374999 - 0.30000000000000004, 2000.0, 28.0, 4579.045000000001, 1938.1099999999992 - 0.30000000000000004, 2000.0, 28.5, 4869.918554687499, 2036.362890624999 - 0.30000000000000004, 2000.0, 29.0, 5162.948437499998, 2136.128124999999 - 0.30000000000000004, 2000.0, 29.5, 5457.415351562501, 2237.156796875 - 0.30000000000000004, 2000.0, 30.0, 5752.6, 2339.2000000000003 - 0.30000000000000004, 2000.0, 30.5, 6040.228417968748, 2439.8936523437505 - 0.30000000000000004, 2000.0, 31.0, 6327.855468749996, 2541.3054687500003 - 0.30000000000000004, 2000.0, 31.5, 6615.481347656247, 2643.387988281251 - 0.30000000000000004, 2000.0, 32.0, 6903.106249999999, 2746.093750000001 - 0.30000000000000004, 2000.0, 32.5, 7190.730371093748, 2849.3752929687525 - 0.30000000000000004, 2000.0, 33.0, 7478.35390625, 2953.1851562500024 - 0.30000000000000004, 2000.0, 33.5, 7765.977050781249, 3057.475878906253 - 0.30000000000000004, 2000.0, 34.0, 8053.600000000002, 3162.2000000000044 - 0.30000000000000004, 2000.0, 34.5, 8341.218437499992, 3266.924101562483 - 0.30000000000000004, 2000.0, 35.0, 8628.837499999992, 3372.0234374999786 - 0.30000000000000004, 2000.0, 35.5, 8916.457812499986, 3477.4873046874754 - 0.30000000000000004, 2000.0, 36.0, 9204.079999999984, 3583.304999999971 - 0.30000000000000004, 2000.0, 36.5, 9491.704687499978, 3689.465820312466 - 0.30000000000000004, 2000.0, 37.0, 9779.332499999968, 3795.959062499962 - 0.30000000000000004, 2000.0, 37.5, 10066.964062499963, 3902.774023437455 - 0.30000000000000004, 2000.0, 38.0, 10354.599999999955, 4009.89999999995 - 0.30000000000000004, 2000.0, 38.5, 10642.252539062594, 4117.717578125001 - 0.30000000000000004, 2000.0, 39.0, 10929.904687500115, 4225.621874999998 - 0.30000000000000004, 2000.0, 39.5, 11217.554492187634, 4333.515234374995 - 0.30000000000000004, 2000.0, 40.0, 11505.20000000016, 4441.299999999994 - 0.30000000000000004, 2000.0, 40.5, 11792.830468750017, 4548.614843750002 - 0.30000000000000004, 2000.0, 41.0, 12080.456250000025, 4655.731250000006 - 0.30000000000000004, 2000.0, 41.5, 12368.07890625003, 4762.657031250011 - 0.30000000000000004, 2000.0, 42.0, 12655.700000000039, 4869.400000000016 - 0.30000000000000004, 2000.0, 42.5, 12943.098437499984, 4976.167187500001 - 0.30000000000000004, 2000.0, 43.0, 13230.587499999983, 5082.687500000004 - 0.30000000000000004, 2000.0, 43.5, 13518.257812499984, 5188.889062500003 - 0.30000000000000004, 2000.0, 44.0, 13806.199999999983, 5294.7000000000035 - 0.30000000000000004, 2000.0, 44.5, 14095.407031250068, 5399.470312500011 - 0.30000000000000004, 2000.0, 45.0, 14384.706250000087, 5503.937500000015 - 0.30000000000000004, 2000.0, 45.5, 14673.827343750105, 5608.260937500019 - 0.30000000000000004, 2000.0, 46.0, 14962.500000000131, 5712.600000000023 - 0.30000000000000004, 2000.0, 46.5, 15249.106249999948, 5817.332812500006 - 0.30000000000000004, 2000.0, 47.0, 15535.262499999937, 5922.312500000012 - 0.30000000000000004, 2000.0, 47.5, 15821.237499999927, 6027.610937500015 - 0.30000000000000004, 2000.0, 48.0, 16107.299999999923, 6133.300000000019 - 0.30000000000000004, 2000.0, 48.5, 16393.71874999992, 6239.451562500023 - 0.30000000000000004, 2000.0, 49.0, 16680.762499999924, 6346.137500000029 - 0.30000000000000004, 2000.0, 49.5, 16968.699999999924, 6453.429687500037 - 0.30000000000000004, 2000.0, 50.0, 17257.79999999993, 6561.400000000043 - 0.30000000000000004, 5000.0, 0.0, 461.2495225436869, 461.2495225436869 - 0.30000000000000004, 5000.0, 22.0, 1307.4000000000005, 831.8000000000001 - 0.30000000000000004, 5000.0, 22.5, 1555.5041015624997, 912.6541015625 - 0.30000000000000004, 5000.0, 23.0, 1801.0546875, 991.5546874999993 - 0.30000000000000004, 5000.0, 23.5, 2044.9029296874994, 1069.0279296874985 - 0.30000000000000004, 5000.0, 24.0, 2287.899999999999, 1145.5999999999983 - 0.30000000000000004, 5000.0, 24.5, 2530.897070312499, 1221.797070312497 - 0.30000000000000004, 5000.0, 25.0, 2774.745312499998, 1298.1453124999966 - 0.30000000000000004, 5000.0, 25.5, 3020.2958984374986, 1375.1708984374957 - 0.30000000000000004, 5000.0, 26.0, 3268.3999999999987, 1453.399999999994 - 0.30000000000000004, 5000.0, 26.5, 3528.8460937500026, 1537.941601562499 - 0.30000000000000004, 5000.0, 27.0, 3794.0587500000033, 1625.0009374999988 - 0.30000000000000004, 5000.0, 27.5, 4063.3570312500046, 1714.3185546874981 - 0.30000000000000004, 5000.0, 28.0, 4336.060000000007, 1805.6349999999989 - 0.30000000000000004, 5000.0, 28.5, 4611.486718750009, 1898.6908203124985 - 0.30000000000000004, 5000.0, 29.0, 4888.956250000009, 1993.2265624999984 - 0.30000000000000004, 5000.0, 29.5, 5167.787656250013, 2088.982773437498 - 0.30000000000000004, 5000.0, 30.0, 5447.300000000013, 2185.699999999999 - 0.30000000000000004, 5000.0, 30.5, 5719.66250000001, 2280.8375000000055 - 0.30000000000000004, 5000.0, 31.0, 5992.025000000017, 2376.634375000007 - 0.30000000000000004, 5000.0, 31.5, 6264.387500000019, 2473.048437500008 - 0.30000000000000004, 5000.0, 32.0, 6536.750000000024, 2570.0375000000085 - 0.30000000000000004, 5000.0, 32.5, 6809.112500000027, 2667.5593750000103 - 0.30000000000000004, 5000.0, 33.0, 7081.475000000031, 2765.5718750000124 - 0.30000000000000004, 5000.0, 33.5, 7353.837500000037, 2864.0328125000137 - 0.30000000000000004, 5000.0, 34.0, 7626.200000000042, 2962.9000000000156 - 0.30000000000000004, 5000.0, 34.5, 7898.559218750007, 3062.2780859374925 - 0.30000000000000004, 5000.0, 35.0, 8170.918750000009, 3161.9640624999893 - 0.30000000000000004, 5000.0, 35.5, 8443.278906250009, 3261.901757812486 - 0.30000000000000004, 5000.0, 36.0, 8715.640000000009, 3362.034999999983 - 0.30000000000000004, 5000.0, 36.5, 8988.002343750008, 3462.307617187479 - 0.30000000000000004, 5000.0, 37.0, 9260.366250000008, 3562.6634374999744 - 0.30000000000000004, 5000.0, 37.5, 9532.732031250003, 3663.046289062469 - 0.30000000000000004, 5000.0, 38.0, 9805.100000000006, 3763.3999999999637 - 0.30000000000000004, 5000.0, 38.5, 10077.47363281257, 3863.3119140624935 - 0.30000000000000004, 5000.0, 39.0, 10349.84843750007, 3963.267187499991 - 0.30000000000000004, 5000.0, 39.5, 10622.224023437582, 4063.2888671874903 - 0.30000000000000004, 5000.0, 40.0, 10894.60000000009, 4163.399999999987 - 0.30000000000000004, 5000.0, 40.5, 11166.975000000013, 4264.185156250002 - 0.30000000000000004, 5000.0, 41.0, 11439.350000000019, 4364.881250000005 - 0.30000000000000004, 5000.0, 41.5, 11711.725000000031, 4465.286718750008 - 0.30000000000000004, 5000.0, 42.0, 11984.100000000046, 4565.200000000011 - 0.30000000000000004, 5000.0, 42.5, 12256.26406250001, 4663.310156250002 - 0.30000000000000004, 5000.0, 43.0, 12528.512500000012, 4760.9687500000055 - 0.30000000000000004, 5000.0, 43.5, 12800.929687500018, 4858.417968750006 - 0.30000000000000004, 5000.0, 44.0, 13073.600000000031, 4955.900000000005 - 0.30000000000000004, 5000.0, 44.5, 13347.45546875, 5054.313281250007 - 0.30000000000000004, 5000.0, 45.0, 13621.393750000003, 5152.981250000012 - 0.30000000000000004, 5000.0, 45.5, 13895.16015625001, 5251.883593750012 - 0.30000000000000004, 5000.0, 46.0, 14168.500000000015, 5351.000000000016 - 0.30000000000000004, 5000.0, 46.5, 14439.881250000071, 5449.94296875002 - 0.30000000000000004, 5000.0, 47.0, 14710.837500000105, 5549.20625000003 - 0.30000000000000004, 5000.0, 47.5, 14981.625000000131, 5648.916406250037 - 0.30000000000000004, 5000.0, 48.0, 15252.50000000017, 5749.200000000048 - 0.30000000000000004, 5000.0, 48.5, 15523.718750000211, 5850.183593750059 - 0.30000000000000004, 5000.0, 49.0, 15795.537500000255, 5951.993750000074 - 0.30000000000000004, 5000.0, 49.5, 16068.2125000003, 6054.757031250089 - 0.30000000000000004, 5000.0, 50.0, 16342.000000000355, 6158.600000000107 - 0.30000000000000004, 10000.0, 0.0, 388.20742966126085, 388.20742966126085 - 0.30000000000000004, 10000.0, 22.0, 1192.6999999999998, 731.4000000000001 - 0.30000000000000004, 10000.0, 22.5, 1419.0457031249996, 804.3707031250002 - 0.30000000000000004, 10000.0, 23.0, 1643.0593749999991, 875.509375 - 0.30000000000000004, 10000.0, 23.5, 1865.5183593749985, 945.3183593749999 - 0.30000000000000004, 10000.0, 24.0, 2087.199999999997, 1014.2999999999995 - 0.30000000000000004, 10000.0, 24.5, 2308.8816406249953, 1082.956640624999 - 0.30000000000000004, 10000.0, 25.0, 2531.3406249999935, 1151.790624999999 - 0.30000000000000004, 10000.0, 25.5, 2755.3542968749907, 1221.3042968749978 - 0.30000000000000004, 10000.0, 26.0, 2981.6999999999894, 1291.999999999997 - 0.30000000000000004, 10000.0, 26.5, 3219.3185546875006, 1368.787890625 - 0.30000000000000004, 10000.0, 27.0, 3461.290312500001, 1448.014375 - 0.30000000000000004, 10000.0, 27.5, 3706.9931640625014, 1529.426171875 - 0.30000000000000004, 10000.0, 28.0, 3955.805000000002, 1612.7700000000004 - 0.30000000000000004, 10000.0, 28.5, 4207.103710937502, 1697.7925781249996 - 0.30000000000000004, 10000.0, 29.0, 4460.267187500002, 1784.2406249999997 - 0.30000000000000004, 10000.0, 29.5, 4714.673320312502, 1871.8608593750005 - 0.30000000000000004, 10000.0, 30.0, 4969.700000000003, 1960.4000000000008 - 0.30000000000000004, 10000.0, 30.5, 5218.192968750008, 2047.6159179687477 - 0.30000000000000004, 10000.0, 31.0, 5466.684375000008, 2135.433593749998 - 0.30000000000000004, 10000.0, 31.5, 5715.1742187500095, 2223.7891601562487 - 0.30000000000000004, 10000.0, 32.0, 5963.66250000001, 2312.6187499999987 - 0.30000000000000004, 10000.0, 32.5, 6212.1492187500135, 2401.858496093749 - 0.30000000000000004, 10000.0, 33.0, 6460.634375000015, 2491.4445312499993 - 0.30000000000000004, 10000.0, 33.5, 6709.117968750018, 2581.3129882812495 - 0.30000000000000004, 10000.0, 34.0, 6957.600000000019, 2671.4000000000005 - 0.30000000000000004, 10000.0, 34.5, 7206.078007812473, 2761.1458203124907 - 0.30000000000000004, 10000.0, 35.0, 7454.554687499964, 2851.029687499987 - 0.30000000000000004, 10000.0, 35.5, 7703.030273437457, 2941.0349609374844 - 0.30000000000000004, 10000.0, 36.0, 7951.50499999995, 3031.1449999999822 - 0.30000000000000004, 10000.0, 36.5, 8199.97910156244, 3121.3431640624785 - 0.30000000000000004, 10000.0, 37.0, 8448.452812499934, 3211.6128124999746 - 0.30000000000000004, 10000.0, 37.5, 8696.92636718742, 3301.93730468747 - 0.30000000000000004, 10000.0, 38.0, 8945.39999999991, 3392.2999999999656 - 0.30000000000000004, 10000.0, 38.5, 9193.869726562494, 3483.2632812500156 - 0.30000000000000004, 10000.0, 39.0, 9442.34218749999, 3573.9312500000183 - 0.30000000000000004, 10000.0, 39.5, 9690.818554687487, 3664.1585937500226 - 0.30000000000000004, 10000.0, 40.0, 9939.299999999981, 3753.800000000025 - 0.30000000000000004, 10000.0, 40.5, 10187.798437500016, 3841.729687500002 - 0.30000000000000004, 10000.0, 41.0, 10436.300000000021, 3929.175000000003 - 0.30000000000000004, 10000.0, 41.5, 10684.801562500028, 4016.382812500004 - 0.30000000000000004, 10000.0, 42.0, 10933.300000000034, 4103.600000000006 - 0.30000000000000004, 10000.0, 42.5, 11181.585156250014, 4191.479687500021 - 0.30000000000000004, 10000.0, 43.0, 11429.943750000026, 4279.700000000029 - 0.30000000000000004, 10000.0, 43.5, 11678.455468750037, 4368.345312500036 - 0.30000000000000004, 10000.0, 44.0, 11927.200000000052, 4457.500000000044 - 0.30000000000000004, 10000.0, 44.5, 12177.042187500007, 4547.631249999988 - 0.30000000000000004, 10000.0, 45.0, 12426.96250000001, 4638.287499999985 - 0.30000000000000004, 10000.0, 45.5, 12676.726562500011, 4729.399999999984 - 0.30000000000000004, 10000.0, 46.0, 12926.100000000015, 4820.899999999983 - 0.30000000000000004, 10000.0, 46.5, 13173.672656250015, 4912.058593750004 - 0.30000000000000004, 10000.0, 47.0, 13420.856250000023, 5003.731250000006 - 0.30000000000000004, 10000.0, 47.5, 13667.886718750027, 5096.113281250008 - 0.30000000000000004, 10000.0, 48.0, 13915.000000000035, 5189.40000000001 - 0.30000000000000004, 10000.0, 48.5, 14162.432031250044, 5283.786718750012 - 0.30000000000000004, 10000.0, 49.0, 14410.41875000005, 5379.468750000014 - 0.30000000000000004, 10000.0, 49.5, 14659.196093750059, 5476.641406250014 - 0.30000000000000004, 10000.0, 50.0, 14909.000000000071, 5575.5000000000155 - 0.30000000000000004, 15000.0, 0.0, 324.6164952378176, 324.6164952378176 - 0.30000000000000004, 15000.0, 22.0, 1063.3000000000002, 632.7000000000002 - 0.30000000000000004, 15000.0, 22.5, 1265.0740234375003, 696.0740234375 - 0.30000000000000004, 15000.0, 23.0, 1464.7703125000005, 757.9203124999999 - 0.30000000000000004, 15000.0, 23.5, 1663.0814453125004, 818.6814453124999 - 0.30000000000000004, 15000.0, 24.0, 1860.7000000000005, 878.7999999999998 - 0.30000000000000004, 15000.0, 24.5, 2058.3185546875006, 938.7185546874998 - 0.30000000000000004, 15000.0, 25.0, 2256.6296875000007, 998.8796874999997 - 0.30000000000000004, 15000.0, 25.5, 2456.3259765625003, 1059.7259765624995 - 0.30000000000000004, 15000.0, 26.0, 2658.1000000000004, 1121.6999999999994 - 0.30000000000000004, 15000.0, 26.5, 2869.916406250001, 1189.2884765625006 - 0.30000000000000004, 15000.0, 27.0, 3085.6112500000013, 1259.1209375000003 - 0.30000000000000004, 15000.0, 27.5, 3304.6304687500015, 1330.9466796875004 - 0.30000000000000004, 15000.0, 28.0, 3526.4200000000014, 1404.5150000000006 - 0.30000000000000004, 15000.0, 28.5, 3750.425781250002, 1479.5751953125002 - 0.30000000000000004, 15000.0, 29.0, 3976.0937500000023, 1555.8765625000005 - 0.30000000000000004, 15000.0, 29.5, 4202.8698437500025, 1633.1683984375004 - 0.30000000000000004, 15000.0, 30.0, 4430.2000000000035, 1711.2000000000007 - 0.30000000000000004, 15000.0, 30.5, 4651.712499999998, 1787.5025390625008 - 0.30000000000000004, 15000.0, 31.0, 4873.2249999999985, 1864.254687500001 - 0.30000000000000004, 15000.0, 31.5, 5094.7374999999965, 1941.4169921875011 - 0.30000000000000004, 15000.0, 32.0, 5316.249999999996, 2018.9500000000012 - 0.30000000000000004, 15000.0, 32.5, 5537.762499999997, 2096.814257812501 - 0.30000000000000004, 15000.0, 33.0, 5759.274999999996, 2174.9703125000015 - 0.30000000000000004, 15000.0, 33.5, 5980.787499999996, 2253.378710937502 - 0.30000000000000004, 15000.0, 34.0, 6202.2999999999965, 2332.000000000002 - 0.30000000000000004, 15000.0, 34.5, 6423.815781249995, 2411.103164062499 - 0.30000000000000004, 15000.0, 35.0, 6645.331249999994, 2490.310937499998 - 0.30000000000000004, 15000.0, 35.5, 6866.846093749993, 2569.554492187497 - 0.30000000000000004, 15000.0, 36.0, 7088.3599999999915, 2648.764999999997 - 0.30000000000000004, 15000.0, 36.5, 7309.8726562499905, 2727.8736328124965 - 0.30000000000000004, 15000.0, 37.0, 7531.38374999999, 2806.8115624999955 - 0.30000000000000004, 15000.0, 37.5, 7752.8929687499885, 2885.5099609374947 - 0.30000000000000004, 15000.0, 38.0, 7974.399999999988, 2963.899999999994 - 0.30000000000000004, 15000.0, 38.5, 8195.896093750012, 3041.2779296875037 - 0.30000000000000004, 15000.0, 39.0, 8417.393750000016, 3118.5390625000036 - 0.30000000000000004, 15000.0, 39.5, 8638.894531250018, 3195.7556640625044 - 0.30000000000000004, 15000.0, 40.0, 8860.400000000023, 3273.000000000005 - 0.30000000000000004, 15000.0, 40.5, 9081.923437499998, 3350.3179687500005 - 0.30000000000000004, 15000.0, 41.0, 9303.449999999997, 3427.8187500000004 - 0.30000000000000004, 15000.0, 41.5, 9524.976562499996, 3505.58515625 - 0.30000000000000004, 15000.0, 42.0, 9746.499999999995, 3583.7 - 0.30000000000000004, 15000.0, 42.5, 9967.829687500003, 3662.316406249998 - 0.30000000000000004, 15000.0, 43.0, 10189.225000000004, 3741.4187499999975 - 0.30000000000000004, 15000.0, 43.5, 10410.757812500004, 3821.061718749996 - 0.30000000000000004, 15000.0, 44.0, 10632.500000000004, 3901.2999999999956 - 0.30000000000000004, 15000.0, 44.5, 10855.226562500004, 3982.2625000000025 - 0.30000000000000004, 15000.0, 45.0, 11078.025000000003, 4063.9000000000033 - 0.30000000000000004, 15000.0, 45.5, 11300.685937500006, 4146.237500000004 - 0.30000000000000004, 15000.0, 46.0, 11523.000000000005, 4229.300000000004 - 0.30000000000000004, 15000.0, 46.5, 11743.710937500004, 4312.550000000003 - 0.30000000000000004, 15000.0, 47.0, 11964.075000000004, 4396.800000000003 - 0.30000000000000004, 15000.0, 47.5, 12184.301562500008, 4482.300000000004 - 0.30000000000000004, 15000.0, 48.0, 12404.600000000008, 4569.300000000004 - 0.30000000000000004, 15000.0, 48.5, 12625.17968750001, 4658.050000000006 - 0.30000000000000004, 15000.0, 49.0, 12846.250000000011, 4748.800000000006 - 0.30000000000000004, 15000.0, 49.5, 13068.020312500013, 4841.800000000006 - 0.30000000000000004, 15000.0, 50.0, 13290.700000000015, 4937.3000000000075 - 0.30000000000000004, 20000.0, 0.0, 269.55187838978003, 269.55187838978003 - 0.30000000000000004, 20000.0, 22.0, 854.3999999999976, 514.2999999999996 - 0.30000000000000004, 20000.0, 22.5, 1017.5244140624945, 579.0673828124986 - 0.30000000000000004, 20000.0, 23.0, 1178.7546874999914, 636.0109374999977 - 0.30000000000000004, 20000.0, 23.5, 1338.6826171874873, 686.4240234374962 - 0.30000000000000004, 20000.0, 24.0, 1497.8999999999828, 731.5999999999941 - 0.30000000000000004, 20000.0, 24.5, 1656.9986328124785, 772.8322265624917 - 0.30000000000000004, 20000.0, 25.0, 1816.5703124999732, 811.4140624999887 - 0.30000000000000004, 20000.0, 25.5, 1977.2068359374662, 848.6388671874857 - 0.30000000000000004, 20000.0, 26.0, 2139.4999999999577, 885.7999999999819 - 0.30000000000000004, 20000.0, 26.5, 2310.2253906250016, 934.0072265624927 - 0.30000000000000004, 20000.0, 27.0, 2484.1443750000035, 985.2984374999921 - 0.30000000000000004, 20000.0, 27.5, 2660.7886718750055, 1039.2841796874918 - 0.30000000000000004, 20000.0, 28.0, 2839.6900000000073, 1095.5749999999916 - 0.30000000000000004, 20000.0, 28.5, 3020.3800781250097, 1153.7814453124913 - 0.30000000000000004, 20000.0, 29.0, 3202.3906250000123, 1213.5140624999915 - 0.30000000000000004, 20000.0, 29.5, 3385.2533593750154, 1274.3833984374921 - 0.30000000000000004, 20000.0, 30.0, 3568.5000000000196, 1335.9999999999925 - 0.30000000000000004, 20000.0, 30.5, 3746.5033203124763, 1392.3491210937375 - 0.30000000000000004, 20000.0, 31.0, 3924.4453124999727, 1449.2023437499854 - 0.30000000000000004, 20000.0, 31.5, 4102.3490234374685, 1506.7059570312324 - 0.30000000000000004, 20000.0, 32.0, 4280.2374999999665, 1565.0062499999783 - 0.30000000000000004, 20000.0, 32.5, 4458.133789062464, 1624.249511718725 - 0.30000000000000004, 20000.0, 33.0, 4636.060937499961, 1684.582031249971 - 0.30000000000000004, 20000.0, 33.5, 4814.041992187461, 1746.150097656217 - 0.30000000000000004, 20000.0, 34.0, 4992.099999999959, 1809.0999999999628 - 0.30000000000000004, 20000.0, 34.5, 5170.919999999833, 1885.353203124937 - 0.30000000000000004, 20000.0, 35.0, 5349.799999999807, 1962.159374999925 - 0.30000000000000004, 20000.0, 35.5, 5528.699999999776, 2038.5433593749115 - 0.30000000000000004, 20000.0, 36.0, 5707.579999999744, 2113.529999999896 - 0.30000000000000004, 20000.0, 36.5, 5886.399999999712, 2186.144140624878 - 0.30000000000000004, 20000.0, 37.0, 6065.119999999677, 2255.4106249998595 - 0.30000000000000004, 20000.0, 37.5, 6243.699999999637, 2320.354296874837 - 0.30000000000000004, 20000.0, 38.0, 6422.099999999596, 2379.9999999998145 - 0.30000000000000004, 20000.0, 38.5, 6599.853906250045, 2420.675195312539 - 0.30000000000000004, 20000.0, 39.0, 6777.568750000075, 2460.6859375000536 - 0.30000000000000004, 20000.0, 39.5, 6955.299218750108, 2501.878710937572 - 0.30000000000000004, 20000.0, 40.0, 7133.100000000147, 2546.100000000091 - 0.30000000000000004, 20000.0, 40.5, 7311.260156249939, 2601.0234375000127 - 0.30000000000000004, 20000.0, 41.0, 7489.506249999921, 2660.337500000017 - 0.30000000000000004, 20000.0, 41.5, 7667.799218749898, 2723.5578125000247 - 0.30000000000000004, 20000.0, 42.0, 7846.099999999864, 2790.200000000033 - 0.30000000000000004, 20000.0, 42.5, 8024.142968749933, 2858.935937499941 - 0.30000000000000004, 20000.0, 43.0, 8202.206249999917, 2930.4624999999223 - 0.30000000000000004, 20000.0, 43.5, 8380.341406249901, 3004.6328124999022 - 0.30000000000000004, 20000.0, 44.0, 8558.599999999882, 3081.29999999988 - 0.30000000000000004, 20000.0, 44.5, 8737.408593749904, 3162.133593749966 - 0.30000000000000004, 20000.0, 45.0, 8916.29374999989, 3244.443749999961 - 0.30000000000000004, 20000.0, 45.5, 9095.157031249872, 3327.3570312499555 - 0.30000000000000004, 20000.0, 46.0, 9273.899999999858, 3409.9999999999472 - 0.30000000000000004, 20000.0, 46.5, 9451.97499999994, 3488.4406249999624 - 0.30000000000000004, 20000.0, 47.0, 9629.912499999922, 3566.0874999999523 - 0.30000000000000004, 20000.0, 47.5, 9807.793749999899, 3643.29062499994 - 0.30000000000000004, 20000.0, 48.0, 9985.699999999873, 3720.3999999999273 - 0.30000000000000004, 20000.0, 48.5, 10163.712499999849, 3797.7656249999154 - 0.30000000000000004, 20000.0, 49.0, 10341.912499999815, 3875.7374999999 - 0.30000000000000004, 20000.0, 49.5, 10520.381249999777, 3954.6656249998873 - 0.30000000000000004, 20000.0, 50.0, 10699.199999999733, 4034.8999999998737 - 0.30000000000000004, 25000.0, 0.0, 222.1415769283496, 222.1415769283496 - 0.30000000000000004, 25000.0, 22.0, 662.7000000000021, 460.70000000000215 - 0.30000000000000004, 25000.0, 22.5, 790.6117187500018, 438.3636718749995 - 0.30000000000000004, 25000.0, 23.0, 916.7062500000008, 442.3906249999978 - 0.30000000000000004, 25000.0, 23.5, 1041.4976562499983, 468.72226562499736 - 0.30000000000000004, 25000.0, 24.0, 1165.499999999995, 513.2999999999976 - 0.30000000000000004, 25000.0, 24.5, 1289.2273437499903, 572.0652343749988 - 0.30000000000000004, 25000.0, 25.0, 1413.1937499999856, 640.9593750000008 - 0.30000000000000004, 25000.0, 25.5, 1537.9132812499802, 715.923828125003 - 0.30000000000000004, 25000.0, 26.0, 1663.8999999999744, 792.9000000000059 - 0.30000000000000004, 25000.0, 26.5, 1796.9480468750035, 834.6421875000162 - 0.30000000000000004, 25000.0, 27.0, 1932.593125000003, 868.3825000000204 - 0.30000000000000004, 25000.0, 27.5, 2070.4441406250016, 895.7515625000243 - 0.30000000000000004, 25000.0, 28.0, 2210.1099999999997, 918.3800000000289 - 0.30000000000000004, 25000.0, 28.5, 2351.1996093749985, 937.8984375000332 - 0.30000000000000004, 25000.0, 29.0, 2493.3218749999965, 955.9375000000387 - 0.30000000000000004, 25000.0, 29.5, 2636.0857031249957, 974.1278125000433 - 0.30000000000000004, 25000.0, 30.0, 2779.099999999992, 994.1000000000486 - 0.30000000000000004, 25000.0, 30.5, 2917.5882812500186, 1040.3504882812688 - 0.30000000000000004, 25000.0, 31.0, 3055.962500000028, 1089.4664062500262 - 0.30000000000000004, 25000.0, 31.5, 3194.2492187500397, 1140.9006835937848 - 0.30000000000000004, 25000.0, 32.0, 3332.475000000053, 1194.106250000044 - 0.30000000000000004, 25000.0, 32.5, 3470.6664062500668, 1248.5360351563033 - 0.30000000000000004, 25000.0, 33.0, 3608.850000000082, 1303.6429687500638 - 0.30000000000000004, 25000.0, 33.5, 3747.0523437500988, 1358.8799804688254 - 0.30000000000000004, 25000.0, 34.0, 3885.3000000001152, 1413.7000000000864 - 0.30000000000000004, 25000.0, 34.5, 4024.162578125211, 1445.5703515625148 - 0.30000000000000004, 25000.0, 35.0, 4163.071875000254, 1478.0234375000143 - 0.30000000000000004, 25000.0, 35.5, 4302.002734375301, 1512.6060546875124 - 0.30000000000000004, 25000.0, 36.0, 4440.930000000351, 1550.8650000000114 - 0.30000000000000004, 25000.0, 36.5, 4579.828515625398, 1594.347070312509 - 0.30000000000000004, 25000.0, 37.0, 4718.673125000452, 1644.5990625000059 - 0.30000000000000004, 25000.0, 37.5, 4857.438671875507, 1703.167773437503 - 0.30000000000000004, 25000.0, 38.0, 4996.100000000565, 1771.6000000000004 - 0.30000000000000004, 25000.0, 38.5, 5134.063476562405, 1888.517968750095 - 0.30000000000000004, 25000.0, 39.0, 5272.167187499872, 1999.1687500001096 - 0.30000000000000004, 25000.0, 39.5, 5410.512304687341, 2096.8601562501276 - 0.30000000000000004, 25000.0, 40.0, 5549.1999999998125, 2174.9000000001474 - 0.30000000000000004, 25000.0, 40.5, 5689.2015625000895, 2190.221093750063 - 0.30000000000000004, 25000.0, 41.0, 5829.400000000129, 2187.0562500000897 - 0.30000000000000004, 25000.0, 41.5, 5969.54843750018, 2173.2632812501215 - 0.30000000000000004, 25000.0, 42.0, 6109.400000000239, 2156.7000000001594 - 0.30000000000000004, 25000.0, 42.5, 6247.227343750161, 2161.7632812499796 - 0.30000000000000004, 25000.0, 43.0, 6384.85625000024, 2173.156249999979 - 0.30000000000000004, 25000.0, 43.5, 6522.632031250333, 2192.1210937499786 - 0.30000000000000004, 25000.0, 44.0, 6660.900000000437, 2219.899999999977 - 0.30000000000000004, 25000.0, 44.5, 6802.173437499999, 2266.524218750079 - 0.30000000000000004, 25000.0, 45.0, 6943.762500000029, 2320.931250000113 - 0.30000000000000004, 25000.0, 45.5, 7085.145312500065, 2380.847656250152 - 0.30000000000000004, 25000.0, 46.0, 7225.800000000115, 2444.000000000194 - 0.30000000000000004, 25000.0, 46.5, 7362.661718750073, 2495.5914062500624 - 0.30000000000000004, 25000.0, 47.0, 7498.768750000075, 2550.8812500000868 - 0.30000000000000004, 25000.0, 47.5, 7634.616406250071, 2612.605468750117 - 0.30000000000000004, 25000.0, 48.0, 7770.700000000063, 2683.500000000152 - 0.30000000000000004, 25000.0, 48.5, 7907.514843750049, 2766.300781250194 - 0.30000000000000004, 25000.0, 49.0, 8045.556250000029, 2863.7437500002407 - 0.30000000000000004, 25000.0, 49.5, 8185.3195312500075, 2978.564843750297 - 0.30000000000000004, 25000.0, 50.0, 8327.299999999977, 3113.5000000003593 - 0.30000000000000004, 30000.0, 0.0, 181.5747194188527, 181.5747194188527 - 0.30000000000000004, 30000.0, 22.0, 412.90000000000134, 303.89999999998895 - 0.30000000000000004, 30000.0, 22.5, 489.49628906250945, 362.40976562499554 - 0.30000000000000004, 30000.0, 23.0, 566.0046875000197, 395.6343750000034 - 0.30000000000000004, 30000.0, 23.5, 642.6107421875329, 408.21679687501256 - 0.30000000000000004, 30000.0, 24.0, 719.5000000000496, 404.8000000000238 - 0.30000000000000004, 30000.0, 24.5, 796.8580078125703, 390.0269531250371 - 0.30000000000000004, 30000.0, 25.0, 874.8703125000962, 368.54062500005307 - 0.30000000000000004, 30000.0, 25.5, 953.7224609376276, 344.9839843750723 - 0.30000000000000004, 30000.0, 26.0, 1033.600000000165, 324.00000000009504 - 0.30000000000000004, 30000.0, 26.5, 1117.171289062463, 356.7037109374738 - 0.30000000000000004, 30000.0, 27.0, 1202.2809374999497, 403.9215624999708 - 0.30000000000000004, 30000.0, 27.5, 1288.6888671874322, 462.32988281246753 - 0.30000000000000004, 30000.0, 28.0, 1376.1549999999106, 528.604999999964 - 0.30000000000000004, 30000.0, 28.5, 1464.4392578123834, 599.4232421874603 - 0.30000000000000004, 30000.0, 29.0, 1553.3015624998507, 671.460937499957 - 0.30000000000000004, 30000.0, 29.5, 1642.5018359373112, 741.3944140624529 - 0.30000000000000004, 30000.0, 30.0, 1731.799999999765, 805.8999999999493 - 0.30000000000000004, 30000.0, 30.5, 1818.176757812583, 809.971874999971 - 0.30000000000000004, 30000.0, 31.0, 1904.435937500088, 806.8906249999711 - 0.30000000000000004, 30000.0, 31.5, 1990.6021484375924, 798.2546874999705 - 0.30000000000000004, 30000.0, 32.0, 2076.700000000096, 785.6624999999694 - 0.30000000000000004, 30000.0, 32.5, 2162.7541015625998, 770.7124999999673 - 0.30000000000000004, 30000.0, 33.0, 2248.789062500104, 755.003124999964 - 0.30000000000000004, 30000.0, 33.5, 2334.829492187608, 740.1328124999598 - 0.30000000000000004, 30000.0, 34.0, 2420.900000000112, 727.6999999999534 - 0.30000000000000004, 30000.0, 34.5, 2508.2687890624416, 732.0844140625005 - 0.30000000000000004, 30000.0, 35.0, 2595.5984374999316, 740.8859375000087 - 0.30000000000000004, 30000.0, 35.5, 2682.795117187418, 754.485742187518 - 0.30000000000000004, 30000.0, 36.0, 2769.764999999901, 773.2650000000289 - 0.30000000000000004, 30000.0, 36.5, 2856.4142578123797, 797.6048828125411 - 0.30000000000000004, 30000.0, 37.0, 2942.649062499854, 827.8865625000551 - 0.30000000000000004, 30000.0, 37.5, 3028.375585937324, 864.491210937571 - 0.30000000000000004, 30000.0, 38.0, 3113.4999999997885, 907.8000000000886 - 0.30000000000000004, 30000.0, 38.5, 3195.4689453106434, 980.793945312211 - 0.30000000000000004, 30000.0, 39.0, 3277.9234374978005, 1049.5359374996494 - 0.30000000000000004, 30000.0, 39.5, 3361.3162109349155, 1109.3849609370805 - 0.30000000000000004, 30000.0, 40.0, 3446.0999999969827, 1155.699999999505 - 0.30000000000000004, 30000.0, 40.5, 3535.6992187498977, 1161.3546874998615 - 0.30000000000000004, 30000.0, 41.0, 3626.4062499998336, 1153.1874999998145 - 0.30000000000000004, 30000.0, 41.5, 3717.485156249752, 1135.5515624997577 - 0.30000000000000004, 30000.0, 42.0, 3808.1999999996497, 1112.7999999996896 - 0.30000000000000004, 30000.0, 42.5, 3895.6156249997666, 1064.160937500035 - 0.30000000000000004, 30000.0, 43.0, 3982.074999999699, 1029.162500000052 - 0.30000000000000004, 30000.0, 43.5, 4067.721874999629, 1022.2078125000696 - 0.30000000000000004, 30000.0, 44.0, 4152.699999999563, 1057.7000000000876 - 0.30000000000000004, 30000.0, 44.5, 4236.992968749723, 1251.358593749937 - 0.30000000000000004, 30000.0, 45.0, 4320.968749999687, 1475.7437499999448 - 0.30000000000000004, 30000.0, 45.5, 4404.835156249653, 1704.7320312499646 - 0.30000000000000004, 30000.0, 46.0, 4488.799999999617, 1912.1999999999962 - 0.30000000000000004, 30000.0, 46.5, 4573.367968749674, 1998.5593749999668 - 0.30000000000000004, 30000.0, 47.0, 4658.331249999576, 2040.5374999999397 - 0.30000000000000004, 30000.0, 47.5, 4743.778906249455, 2041.3968749999042 - 0.30000000000000004, 30000.0, 48.0, 4829.7999999993135, 2004.3999999998628 - 0.30000000000000004, 30000.0, 48.5, 4916.483593749152, 1932.8093749998131 - 0.30000000000000004, 30000.0, 49.0, 5003.918749998972, 1829.8874999997554 - 0.30000000000000004, 30000.0, 49.5, 5092.194531248771, 1698.8968749996884 - 0.30000000000000004, 30000.0, 50.0, 5181.3999999985535, 1543.0999999996134 - 0.30000000000000004, 35000.0, 0.0, 147.0961652193268, 147.0961652193268 - 0.30000000000000004, 35000.0, 22.0, 514.4999999999994, 254.00000000000296 - 0.30000000000000004, 35000.0, 22.5, 620.0857421875062, 248.5054687500107 - 0.30000000000000004, 35000.0, 23.0, 722.626562500008, 268.89375000001587 - 0.30000000000000004, 35000.0, 23.5, 822.7041015625057, 310.4101562500191 - 0.30000000000000004, 35000.0, 24.0, 920.8999999999992, 368.30000000002025 - 0.30000000000000004, 35000.0, 24.5, 1017.7958984374895, 437.80859375001967 - 0.30000000000000004, 35000.0, 25.0, 1113.9734374999775, 514.1812500000175 - 0.30000000000000004, 35000.0, 25.5, 1210.0142578124626, 592.6632812500142 - 0.30000000000000004, 35000.0, 26.0, 1306.4999999999472, 668.5000000000095 - 0.30000000000000004, 35000.0, 26.5, 1408.6962890624245, 688.1623046875254 - 0.30000000000000004, 35000.0, 27.0, 1512.768437499914, 692.8828125000258 - 0.30000000000000004, 35000.0, 27.5, 1618.495117187405, 686.268164062527 - 0.30000000000000004, 35000.0, 28.0, 1725.654999999896, 671.9250000000287 - 0.30000000000000004, 35000.0, 28.5, 1834.026757812389, 653.4599609375312 - 0.30000000000000004, 35000.0, 29.0, 1943.3890624998814, 634.479687500035 - 0.30000000000000004, 35000.0, 29.5, 2053.520585937374, 618.5908203125398 - 0.30000000000000004, 35000.0, 30.0, 2164.1999999998675, 609.4000000000459 - 0.30000000000000004, 35000.0, 30.5, 2273.6818359376207, 680.0763671873653 - 0.30000000000000004, 35000.0, 31.0, 2383.414062500141, 758.0390624998499 - 0.30000000000000004, 35000.0, 31.5, 2493.3205078126616, 840.2697265623357 - 0.30000000000000004, 35000.0, 32.0, 2603.3250000001835, 923.7499999998224 - 0.30000000000000004, 35000.0, 32.5, 2713.3513671877063, 1005.4615234373109 - 0.30000000000000004, 35000.0, 33.0, 2823.3234375002307, 1082.3859374998005 - 0.30000000000000004, 35000.0, 33.5, 2933.165039062755, 1151.5048828122913 - 0.30000000000000004, 35000.0, 34.0, 3042.8000000002803, 1209.7999999997846 - 0.30000000000000004, 35000.0, 34.5, 3148.455820313054, 1176.1329296875276 - 0.30000000000000004, 35000.0, 35.0, 3254.104687500609, 1133.0453125000372 - 0.30000000000000004, 35000.0, 35.5, 3360.022460938163, 1084.9587890625457 - 0.30000000000000004, 35000.0, 36.0, 3466.4850000007145, 1036.2950000000546 - 0.30000000000000004, 35000.0, 36.5, 3573.7681640632613, 991.475585937564 - 0.30000000000000004, 35000.0, 37.0, 3682.147812500806, 954.9221875000719 - 0.30000000000000004, 35000.0, 37.5, 3791.8998046883466, 931.0564453125804 - 0.30000000000000004, 35000.0, 38.0, 3903.300000000883, 924.3000000000868 - 0.30000000000000004, 35000.0, 38.5, 4021.8681640626405, 899.5912109372615 - 0.30000000000000004, 35000.0, 39.0, 4139.9171875001775, 921.307812499681 - 0.30000000000000004, 35000.0, 39.5, 4256.557617187725, 1002.6455078120866 - 0.30000000000000004, 35000.0, 40.0, 4370.900000000286, 1156.7999999994795 - 0.30000000000000004, 35000.0, 40.5, 4476.772656250471, 1534.3039062498965 - 0.30000000000000004, 35000.0, 41.0, 4580.681250000656, 1956.081249999842 - 0.30000000000000004, 35000.0, 41.5, 4683.849218750871, 2380.3929687497757 - 0.30000000000000004, 35000.0, 42.0, 4787.5000000011105, 2765.499999999697 - 0.30000000000000004, 35000.0, 42.5, 4897.9859374999805, 2986.3859374997523 - 0.30000000000000004, 35000.0, 43.0, 5009.349999999833, 3117.899999999652 - 0.30000000000000004, 35000.0, 43.5, 5120.764062499626, 3151.61406249953 - 0.30000000000000004, 35000.0, 44.0, 5231.3999999993475, 3079.0999999993874 - 0.30000000000000004, 35000.0, 44.5, 5336.113281250064, 2729.1640625001673 - 0.30000000000000004, 35000.0, 45.0, 5440.118750000136, 2321.250000000235 - 0.30000000000000004, 35000.0, 45.5, 5544.314843750233, 1912.035937500318 - 0.30000000000000004, 35000.0, 46.0, 5649.600000000364, 1558.20000000042 - 0.30000000000000004, 35000.0, 46.5, 5761.0406249999805, 1519.1195312498355 - 0.30000000000000004, 35000.0, 47.0, 5873.700000000033, 1567.6937499997882 - 0.30000000000000004, 35000.0, 47.5, 5986.809375000115, 1679.5210937497259 - 0.30000000000000004, 35000.0, 48.0, 6099.600000000222, 1830.199999999647 - 0.30000000000000004, 35000.0, 48.5, 6211.3031250003605, 1995.3289062495448 - 0.30000000000000004, 35000.0, 49.0, 6321.15000000053, 2150.5062499994183 - 0.30000000000000004, 35000.0, 49.5, 6428.371875000736, 2271.3304687492637 - 0.30000000000000004, 35000.0, 50.0, 6532.200000000976, 2333.399999999077 - 0.30000000000000004, 39000.0, 0.0, 122.00313358302716, 122.00313358302716 - 0.30000000000000004, 39000.0, 22.0, 386.2000000000029, 144.20000000000687 - 0.30000000000000004, 39000.0, 22.5, 467.67539062499435, 112.76484375000283 - 0.30000000000000004, 39000.0, 23.0, 545.7218749999859, 121.31874999999896 - 0.30000000000000004, 39000.0, 23.5, 621.0324218749774, 162.83828124999502 - 0.30000000000000004, 39000.0, 24.0, 694.2999999999681, 230.29999999999083 - 0.30000000000000004, 39000.0, 24.5, 766.2175781249582, 316.68046874998606 - 0.30000000000000004, 39000.0, 25.0, 837.4781249999471, 414.9562499999805 - 0.30000000000000004, 39000.0, 25.5, 908.7746093749344, 518.1039062499735 - 0.30000000000000004, 39000.0, 26.0, 980.7999999999195, 619.0999999999653 - 0.30000000000000004, 39000.0, 26.5, 1060.8972656249834, 649.9281250000005 - 0.30000000000000004, 39000.0, 27.0, 1143.4893749999785, 661.0725000000022 - 0.30000000000000004, 39000.0, 27.5, 1228.1292968749747, 655.9656250000053 - 0.30000000000000004, 39000.0, 28.0, 1314.3699999999699, 638.0400000000097 - 0.30000000000000004, 39000.0, 28.5, 1401.7644531249668, 610.7281250000156 - 0.30000000000000004, 39000.0, 29.0, 1489.8656249999638, 577.4625000000237 - 0.30000000000000004, 39000.0, 29.5, 1578.226484374962, 541.6756250000324 - 0.30000000000000004, 39000.0, 30.0, 1666.3999999999621, 506.80000000004367 - 0.30000000000000004, 39000.0, 30.5, 1747.7523437500354, 518.837011718678 - 0.30000000000000004, 39000.0, 31.0, 1828.6125000000488, 534.596093749913 - 0.30000000000000004, 39000.0, 31.5, 1909.1226562500656, 553.4555664061463 - 0.30000000000000004, 39000.0, 32.0, 1989.425000000083, 574.7937499998777 - 0.30000000000000004, 39000.0, 32.5, 2069.661718750103, 597.9889648436073 - 0.30000000000000004, 39000.0, 33.0, 2149.975000000126, 622.4195312498352 - 0.30000000000000004, 39000.0, 33.5, 2230.5070312501493, 647.4637695310605 - 0.30000000000000004, 39000.0, 34.0, 2311.4000000001756, 672.4999999997842 - 0.30000000000000004, 39000.0, 34.5, 2396.873046874969, 711.6012109374176 - 0.30000000000000004, 39000.0, 35.0, 2482.603124999953, 748.0515624998983 - 0.30000000000000004, 39000.0, 35.5, 2568.34414062493, 779.8298828123766 - 0.30000000000000004, 39000.0, 36.0, 2653.8499999999, 804.9149999998531 - 0.30000000000000004, 39000.0, 36.5, 2738.8746093748623, 821.2857421873268 - 0.30000000000000004, 39000.0, 37.0, 2823.1718749998167, 826.9209374997979 - 0.30000000000000004, 39000.0, 37.5, 2906.495703124761, 819.7994140622658 - 0.30000000000000004, 39000.0, 38.0, 2988.599999999696, 797.8999999997317 - 0.30000000000000004, 39000.0, 38.5, 3065.288867187714, 690.539257812658 - 0.30000000000000004, 39000.0, 39.0, 3142.314062500259, 599.960937500187 - 0.30000000000000004, 39000.0, 39.5, 3220.3072265628093, 539.4021484377238 - 0.30000000000000004, 39000.0, 40.0, 3299.90000000037, 522.100000000268 - 0.30000000000000004, 39000.0, 40.5, 3385.029687500009, 603.1031249999861 - 0.30000000000000004, 39000.0, 41.0, 3471.699999999953, 737.1124999999985 - 0.30000000000000004, 39000.0, 41.5, 3559.220312499888, 920.6406250000181 - 0.30000000000000004, 39000.0, 42.0, 3646.8999999998214, 1150.2000000000457 - 0.30000000000000004, 39000.0, 42.5, 3729.939062500144, 1478.8031250001081 - 0.30000000000000004, 39000.0, 43.0, 3813.4000000002666, 1823.862500000127 - 0.30000000000000004, 39000.0, 43.5, 3898.2359375003916, 2159.2906250001424 - 0.30000000000000004, 39000.0, 44.0, 3985.400000000507, 2459.0000000001537 - 0.30000000000000004, 39000.0, 44.5, 4085.626562500091, 2661.5437499998493 - 0.30000000000000004, 39000.0, 45.0, 4186.1750000001975, 2790.337499999825 - 0.30000000000000004, 39000.0, 45.5, 4284.085937500357, 2833.4374999998063 - 0.30000000000000004, 39000.0, 46.0, 4376.400000000583, 2778.899999999794 - 0.30000000000000004, 39000.0, 46.5, 4443.157812500142, 2478.9804687498945 - 0.30000000000000004, 39000.0, 47.0, 4505.200000000127, 2111.8562499998015 - 0.30000000000000004, 39000.0, 47.5, 4566.3671875000955, 1719.9039062496827 - 0.30000000000000004, 39000.0, 48.0, 4630.500000000041, 1345.4999999995393 - 0.30000000000000004, 39000.0, 48.5, 4701.439062499961, 1031.021093749367 - 0.30000000000000004, 39000.0, 49.0, 4783.024999999849, 818.8437499991701 - 0.30000000000000004, 39000.0, 49.5, 4879.098437499697, 751.3445312489434 - 0.30000000000000004, 39000.0, 50.0, 4993.499999999508, 870.8999999986836 - 0.30000000000000004, 43000.0, 0.0, 100.66460832529529, 100.66460832529529 - 0.30000000000000004, 43000.0, 22.0, -34.400000000005605, 513.7999999999971 - 0.30000000000000004, 43000.0, 22.5, -21.991015625028783, 315.3367187499841 - 0.30000000000000004, 43000.0, 23.0, -11.496875000054438, 154.40624999997925 - 0.30000000000000004, 43000.0, 23.5, -2.7792968750839657, 26.17265624998069 - 0.30000000000000004, 43000.0, 24.0, 4.299999999881273, -74.20000000001332 - 0.30000000000000004, 43000.0, 24.5, 9.879296874839916, -151.54765625000488 - 0.30000000000000004, 43000.0, 25.0, 14.096874999790506, -210.70624999999586 - 0.30000000000000004, 43000.0, 25.5, 17.091015624731757, -256.51171874998806 - 0.30000000000000004, 43000.0, 26.0, 18.99999999966225, -293.799999999983 - 0.30000000000000004, 43000.0, 26.5, 20.10156249996083, -378.0162109375712 - 0.30000000000000004, 43000.0, 27.0, 20.40249999995833, -466.2790625000845 - 0.30000000000000004, 43000.0, 27.5, 20.017187499959086, -554.7486328125983 - 0.30000000000000004, 43000.0, 28.0, 19.059999999963708, -639.5850000001117 - 0.30000000000000004, 43000.0, 28.5, 17.645312499972942, -716.9482421876243 - 0.30000000000000004, 43000.0, 29.0, 15.887499999987236, -782.9984375001343 - 0.30000000000000004, 43000.0, 29.5, 13.90093750000758, -833.8956640626419 - 0.30000000000000004, 43000.0, 30.0, 11.800000000034252, -865.8000000001459 - 0.30000000000000004, 43000.0, 30.5, 10.243750000097386, -828.3138671876759 - 0.30000000000000004, 43000.0, 31.0, 8.75000000010391, -768.5890625002069 - 0.30000000000000004, 43000.0, 31.5, 7.381250000111505, -687.2197265627383 - 0.30000000000000004, 43000.0, 32.0, 6.200000000120605, -584.8000000002719 - 0.30000000000000004, 43000.0, 32.5, 5.26875000013178, -461.9240234378064 - 0.30000000000000004, 43000.0, 33.0, 4.650000000145351, -319.1859375003416 - 0.30000000000000004, 43000.0, 33.5, 4.406250000162059, -157.1798828128778 - 0.30000000000000004, 43000.0, 34.0, 4.60000000018189, 23.499999999584645 - 0.30000000000000004, 43000.0, 34.5, 10.530624999533778, 507.2000390623002 - 0.30000000000000004, 43000.0, 35.0, 16.524999999431415, 981.2484374997621 - 0.30000000000000004, 43000.0, 35.5, 22.146874999309603, 1417.9138671872165 - 0.30000000000000004, 43000.0, 36.0, 26.959999999165845, 1789.464999999669 - 0.30000000000000004, 43000.0, 36.5, 30.528124998998166, 2068.170507812116 - 0.30000000000000004, 43000.0, 37.0, 32.414999998803594, 2226.299062499561 - 0.30000000000000004, 43000.0, 37.5, 32.18437499858007, 2236.119335937001 - 0.30000000000000004, 43000.0, 38.0, 29.399999998324716, 2069.8999999994376 - 0.30000000000000004, 43000.0, 38.5, 12.901562500443475, 1350.7955078129094 - 0.30000000000000004, 43000.0, 39.0, -1.4624999994306052, 581.2109375005512 - 0.30000000000000004, 43000.0, 39.5, -11.745312499286342, -189.00410156179078 - 0.30000000000000004, 43000.0, 40.0, -15.99999999912285, -909.9999999991069 - 0.30000000000000004, 43000.0, 40.5, 3.0250000002074486, -1438.7210937503107 - 0.30000000000000004, 43000.0, 41.0, 25.850000000230196, -1855.806250000377 - 0.30000000000000004, 43000.0, 41.5, 48.300000000257484, -2148.688281250456 - 0.30000000000000004, 43000.0, 42.0, 66.20000000029282, -2304.800000000547 - 0.30000000000000004, 43000.0, 42.5, 55.23828124961612, -2174.0937500004843 - 0.30000000000000004, 43000.0, 43.0, 39.43124999953298, -1936.475000000709 - 0.30000000000000004, 43000.0, 43.5, 22.658593749410898, -1634.3687500009653 - 0.30000000000000004, 43000.0, 44.0, 8.799999999234757, -1310.2000000012445 - 0.30000000000000004, 43000.0, 44.5, 19.96953124958108, -1082.4679687499715 - 0.30000000000000004, 43000.0, 45.0, 34.51874999940914, -887.0937499999429 - 0.30000000000000004, 43000.0, 45.5, 49.03359374924598, -736.0726562499144 - 0.30000000000000004, 43000.0, 46.0, 60.09999999911116, -641.3999999998894 - 0.30000000000000004, 43000.0, 46.5, 49.421093749003475, -710.9343750005635 - 0.30000000000000004, 43000.0, 47.0, 34.41874999865697, -822.4625000006656 - 0.30000000000000004, 43000.0, 47.5, 17.632031248236004, -949.634375000775 - 0.30000000000000004, 43000.0, 48.0, 1.5999999977265418, -1066.1000000008928 - 0.30000000000000004, 43000.0, 48.5, -11.138281252885577, -1145.5093750010178 - 0.30000000000000004, 43000.0, 49.0, -18.043750003614605, -1161.5125000011549 - 0.30000000000000004, 43000.0, 49.5, -16.577343754474555, -1087.7593750013025 - 0.30000000000000004, 43000.0, 50.0, -4.2000000054795805, -897.9000000014585 - 0.30000000000000004, 48000.0, 0.0, 79.16064494602439, 79.16064494602439 - 0.30000000000000004, 48000.0, 22.0, -56.00000000000932, 422.999999999971 - 0.30000000000000004, 48000.0, 22.5, -30.86621093750275, 261.6292968749701 - 0.30000000000000004, 48000.0, 23.0, -12.882812499991136, 132.8906249999685 - 0.30000000000000004, 48000.0, 23.5, -1.083007812474368, 32.3816406249659 - 0.30000000000000004, 48000.0, 24.0, 5.500000000047624, -44.3000000000377 - 0.30000000000000004, 48000.0, 24.5, 7.833007812574975, -101.55664062504249 - 0.30000000000000004, 48000.0, 25.0, 6.882812500107752, -143.7906250000487 - 0.30000000000000004, 48000.0, 25.5, 3.6162109376460876, -175.4042968750562 - 0.30000000000000004, 48000.0, 26.0, -0.9999999998100222, -200.80000000006535 - 0.30000000000000004, 48000.0, 26.5, 1.260742187457294, -270.50214843753685 - 0.30000000000000004, 48000.0, 27.0, 4.520312499956608, -345.4265625000446 - 0.30000000000000004, 48000.0, 27.5, 8.500976562457044, -422.0689453125526 - 0.30000000000000004, 48000.0, 28.0, 12.924999999958445, -496.9250000000605 - 0.30000000000000004, 48000.0, 28.5, 17.514648437460778, -566.4904296875682 - 0.30000000000000004, 48000.0, 29.0, 21.9921874999636, -627.2609375000759 - 0.30000000000000004, 48000.0, 29.5, 26.079882812467005, -675.7322265625821 - 0.30000000000000004, 48000.0, 30.0, 29.499999999970758, -708.4000000000879 - 0.30000000000000004, 48000.0, 30.5, 26.91552734361389, -677.3379882814003 - 0.30000000000000004, 48000.0, 31.0, 23.589843749831587, -627.6945312501817 - 0.30000000000000004, 48000.0, 31.5, 19.72705078104555, -560.1959960939677 - 0.30000000000000004, 48000.0, 32.0, 15.531249999755705, -475.56875000025786 - 0.30000000000000004, 48000.0, 32.5, 11.206542968462074, -374.5391601565529 - 0.30000000000000004, 48000.0, 33.0, 6.957031249664823, -257.83359375035144 - 0.30000000000000004, 48000.0, 33.5, 2.9868164058638627, -126.17841796915567 - 0.30000000000000004, 48000.0, 34.0, -0.500000000441176, 19.69999999953575 - 0.30000000000000004, 48000.0, 34.5, 3.9690624998247017, 396.61929687479187 - 0.30000000000000004, 48000.0, 35.0, 8.637499999810352, 765.5906249997547 - 0.30000000000000004, 48000.0, 35.5, 13.017187499794474, 1105.1691406247073 - 0.30000000000000004, 48000.0, 36.0, 16.619999999775928, 1393.9099999996506 - 0.30000000000000004, 48000.0, 36.5, 18.957812499754084, 1610.3683593745827 - 0.30000000000000004, 48000.0, 37.0, 19.54249999972822, 1733.0993749995096 - 0.30000000000000004, 48000.0, 37.5, 17.88593749969698, 1740.6582031244252 - 0.30000000000000004, 48000.0, 38.0, 13.499999999659792, 1611.5999999993237 - 0.30000000000000004, 48000.0, 38.5, -7.282812499121718, 1055.2466796872147 - 0.30000000000000004, 48000.0, 39.0, -24.93749999894709, 458.9890624996892 - 0.30000000000000004, 48000.0, 39.5, -37.023437498745466, -138.78808593782924 - 0.30000000000000004, 48000.0, 40.0, -41.099999998514136, -699.7000000003418 - 0.30000000000000004, 48000.0, 40.5, -14.488281250203208, -1115.6539062502259 - 0.30000000000000004, 48000.0, 41.0, 16.91874999974877, -1445.856250000279 - 0.30000000000000004, 48000.0, 41.5, 47.46640624969814, -1679.8054687503327 - 0.30000000000000004, 48000.0, 42.0, 71.4999999996457, -1807.00000000039 - 0.30000000000000004, 48000.0, 42.5, 57.42343749984627, -1708.4695312497583 - 0.30000000000000004, 48000.0, 43.0, 35.899999999803754, -1525.568749999708 - 0.30000000000000004, 48000.0, 43.5, 11.651562499755698, -1291.1835937496662 - 0.30000000000000004, 48000.0, 44.0, -10.600000000298508, -1038.199999999637 - 0.30000000000000004, 48000.0, 44.5, -8.691406249855483, -856.2578125002924 - 0.30000000000000004, 48000.0, 45.0, -2.3187499997919616, -698.787500000371 - 0.30000000000000004, 48000.0, 45.5, 6.263281250276492, -575.9734375004532 - 0.30000000000000004, 48000.0, 46.0, 14.800000000347879, -498.00000000053865 - 0.30000000000000004, 48000.0, 46.5, 14.103125000019539, -554.309374999778 - 0.30000000000000004, 48000.0, 47.0, 11.6249999999571, -644.1249999997214 - 0.30000000000000004, 48000.0, 47.5, 7.884374999905127, -745.9281249996511 - 0.30000000000000004, 48000.0, 48.0, 3.3999999998736143, -838.199999999566 - 0.30000000000000004, 48000.0, 48.5, -1.3093750001275453, -899.4218749994623 - 0.30000000000000004, 48000.0, 49.0, -5.725000000088301, -908.0749999993373 - 0.30000000000000004, 48000.0, 49.5, -9.328124999998735, -842.6406249991892 - 0.30000000000000004, 48000.0, 50.0, -11.59999999984882, -681.5999999990136 - 0.35000000000000003, 0.0, 0.0, 555.2433966063429, 555.2433966063429 - 0.35000000000000003, 0.0, 22.0, 1375.4999999999993, 1009.8999999999996 - 0.35000000000000003, 0.0, 22.5, 1636.5349609374878, 1099.9556640624974 - 0.35000000000000003, 0.0, 23.0, 1894.8828124999764, 1188.017187499996 - 0.35000000000000003, 0.0, 23.5, 2151.4392578124643, 1274.6201171874955 - 0.35000000000000003, 0.0, 24.0, 2407.0999999999485, 1360.2999999999945 - 0.35000000000000003, 0.0, 24.5, 2662.760742187433, 1445.5923828124933 - 0.35000000000000003, 0.0, 25.0, 2919.3171874999125, 1531.0328124999926 - 0.35000000000000003, 0.0, 25.5, 3177.6650390623877, 1617.1568359374921 - 0.35000000000000003, 0.0, 26.0, 3438.6999999998593, 1704.4999999999905 - 0.35000000000000003, 0.0, 26.5, 3712.724023437509, 1798.470507812499 - 0.35000000000000003, 0.0, 27.0, 3991.7640625000117, 1895.0096875000006 - 0.35000000000000003, 0.0, 27.5, 4275.103320312516, 1993.8177734375033 - 0.35000000000000003, 0.0, 28.0, 4562.025000000021, 2094.5950000000066 - 0.35000000000000003, 0.0, 28.5, 4851.812304687531, 2197.041601562513 - 0.35000000000000003, 0.0, 29.0, 5143.748437500037, 2300.857812500018 - 0.35000000000000003, 0.0, 29.5, 5437.1166015625495, 2405.743867187525 - 0.35000000000000003, 0.0, 30.0, 5731.200000000062, 2511.4000000000337 - 0.35000000000000003, 0.0, 30.5, 6017.751367187509, 2613.993359374947 - 0.35000000000000003, 0.0, 31.0, 6304.301562500009, 2717.093749999937 - 0.35000000000000003, 0.0, 31.5, 6590.850976562506, 2820.737890624926 - 0.35000000000000003, 0.0, 32.0, 6877.400000000003, 2924.9624999999146 - 0.35000000000000003, 0.0, 32.5, 7163.949023437495, 3029.8042968749032 - 0.35000000000000003, 0.0, 33.0, 7450.498437499989, 3135.2999999998924 - 0.35000000000000003, 0.0, 33.5, 7737.048632812479, 3241.4863281248813 - 0.35000000000000003, 0.0, 34.0, 8023.599999999971, 3348.39999999987 - 0.35000000000000003, 0.0, 34.5, 8310.162773437258, 3457.9127734374283 - 0.35000000000000003, 0.0, 35.0, 8596.726562499698, 3568.0515624999202 - 0.35000000000000003, 0.0, 35.5, 8883.29082031213, 3678.6783203124114 - 0.35000000000000003, 0.0, 36.0, 9169.854999999556, 3789.6549999999024 - 0.35000000000000003, 0.0, 36.5, 9456.418554686968, 3900.843554687394 - 0.35000000000000003, 0.0, 37.0, 9742.980937499378, 4012.105937499884 - 0.35000000000000003, 0.0, 37.5, 10029.54160156177, 4123.304101562374 - 0.35000000000000003, 0.0, 38.0, 10316.099999999162, 4234.299999999864 - 0.35000000000000003, 0.0, 38.5, 10602.64609375039, 4344.191992187512 - 0.35000000000000003, 0.0, 39.0, 10889.1937500005, 4454.00156250002 - 0.35000000000000003, 0.0, 39.5, 11175.744531250633, 4563.760351562533 - 0.35000000000000003, 0.0, 40.0, 11462.300000000792, 4673.500000000047 - 0.35000000000000003, 0.0, 40.5, 11748.877343749913, 4783.089062499961 - 0.35000000000000003, 0.0, 41.0, 12035.45624999987, 4892.787499999946 - 0.35000000000000003, 0.0, 41.5, 12322.03203124981, 5002.692187499928 - 0.35000000000000003, 0.0, 42.0, 12608.599999999728, 5112.899999999905 - 0.35000000000000003, 0.0, 42.5, 12894.9054687501, 5223.718749999858 - 0.35000000000000003, 0.0, 43.0, 13181.293750000115, 5334.949999999821 - 0.35000000000000003, 0.0, 43.5, 13467.86015625013, 5446.606249999777 - 0.35000000000000003, 0.0, 44.0, 13754.700000000137, 5558.699999999732 - 0.35000000000000003, 0.0, 44.5, 14042.826562499708, 5671.618750000022 - 0.35000000000000003, 0.0, 45.0, 14331.049999999597, 5784.850000000023 - 0.35000000000000003, 0.0, 45.5, 14619.098437499453, 5898.256250000028 - 0.35000000000000003, 0.0, 46.0, 14906.699999999284, 6011.700000000039 - 0.35000000000000003, 0.0, 46.5, 15192.227343749768, 6124.30546874986 - 0.35000000000000003, 0.0, 47.0, 15477.306249999696, 6236.968749999806 - 0.35000000000000003, 0.0, 47.5, 15762.207031249616, 6349.847656249745 - 0.35000000000000003, 0.0, 48.0, 16047.199999999533, 6463.099999999679 - 0.35000000000000003, 0.0, 48.5, 16332.55546874944, 6576.883593749607 - 0.35000000000000003, 0.0, 49.0, 16618.543749999346, 6691.356249999528 - 0.35000000000000003, 0.0, 49.5, 16905.435156249245, 6806.675781249444 - 0.35000000000000003, 0.0, 50.0, 17193.499999999145, 6922.999999999356 - 0.35000000000000003, 2000.0, 0.0, 519.8575968117224, 519.8575968117224 - 0.35000000000000003, 2000.0, 22.0, 1328.1000000000004, 956.0999999999997 - 0.35000000000000003, 2000.0, 22.5, 1580.088476562498, 1042.2501953125 - 0.35000000000000003, 2000.0, 23.0, 1829.4921874999952, 1126.5609374999997 - 0.35000000000000003, 2000.0, 23.5, 2077.174804687491, 1209.5412109374997 - 0.35000000000000003, 2000.0, 24.0, 2323.999999999985, 1291.6999999999996 - 0.35000000000000003, 2000.0, 24.5, 2570.831445312479, 1373.5462890624997 - 0.35000000000000003, 2000.0, 25.0, 2818.5328124999696, 1455.5890624999995 - 0.35000000000000003, 2000.0, 25.5, 3067.967773437461, 1538.3373046875 - 0.35000000000000003, 2000.0, 26.0, 3319.9999999999486, 1622.3000000000004 - 0.35000000000000003, 2000.0, 26.5, 3584.5671875000003, 1712.6072265624975 - 0.35000000000000003, 2000.0, 27.0, 3853.9774999999995, 1805.4109374999985 - 0.35000000000000003, 2000.0, 27.5, 4127.539062500002, 1900.4279296874995 - 0.35000000000000003, 2000.0, 28.0, 4404.56, 1997.3750000000005 - 0.35000000000000003, 2000.0, 28.5, 4684.3484375, 2095.9689453125025 - 0.35000000000000003, 2000.0, 29.0, 4966.212500000001, 2195.9265625000035 - 0.35000000000000003, 2000.0, 29.5, 5249.460312500004, 2296.964648437506 - 0.35000000000000003, 2000.0, 30.0, 5533.400000000005, 2398.8000000000084 - 0.35000000000000003, 2000.0, 30.5, 5810.072949218727, 2498.0137695312465 - 0.35000000000000003, 2000.0, 31.0, 6086.7460937499745, 2597.757031249997 - 0.35000000000000003, 2000.0, 31.5, 6363.419628906224, 2698.045214843748 - 0.35000000000000003, 2000.0, 32.0, 6640.093749999973, 2798.893749999998 - 0.35000000000000003, 2000.0, 32.5, 6916.7686523437205, 2900.31806640625 - 0.35000000000000003, 2000.0, 33.0, 7193.444531249971, 3002.3335937500005 - 0.35000000000000003, 2000.0, 33.5, 7470.121582031219, 3104.9557617187525 - 0.35000000000000003, 2000.0, 34.0, 7746.799999999972, 3208.2000000000035 - 0.35000000000000003, 2000.0, 34.5, 8023.49433593751, 3313.41843749996 - 0.35000000000000003, 2000.0, 35.0, 8300.189062500009, 3419.1624999999513 - 0.35000000000000003, 2000.0, 35.5, 8576.8830078125, 3525.32031249994 - 0.35000000000000003, 2000.0, 36.0, 8853.574999999993, 3631.7799999999284 - 0.35000000000000003, 2000.0, 36.5, 9130.26386718748, 3738.4296874999154 - 0.35000000000000003, 2000.0, 37.0, 9406.948437499968, 3845.1574999999016 - 0.35000000000000003, 2000.0, 37.5, 9683.627539062452, 3951.851562499887 - 0.35000000000000003, 2000.0, 38.0, 9960.29999999994, 4058.399999999869 - 0.35000000000000003, 2000.0, 38.5, 10236.94355468773, 4164.14355468751 - 0.35000000000000003, 2000.0, 39.0, 10513.589062500287, 4269.801562500006 - 0.35000000000000003, 2000.0, 39.5, 10790.24003906285, 4375.3837890625 - 0.35000000000000003, 2000.0, 40.0, 11066.900000000425, 4480.899999999996 - 0.35000000000000003, 2000.0, 40.5, 11343.592968750045, 4586.0171875 - 0.35000000000000003, 2000.0, 41.0, 11620.293750000068, 4691.2250000000095 - 0.35000000000000003, 2000.0, 41.5, 11896.997656250092, 4796.670312500025 - 0.35000000000000003, 2000.0, 42.0, 12173.700000000117, 4902.500000000045 - 0.35000000000000003, 2000.0, 42.5, 12450.16562499993, 5009.396093750002 - 0.35000000000000003, 2000.0, 43.0, 12726.71249999993, 5116.756250000002 - 0.35000000000000003, 2000.0, 43.5, 13003.428124999939, 5224.513281250006 - 0.35000000000000003, 2000.0, 44.0, 13280.399999999949, 5332.600000000009 - 0.35000000000000003, 2000.0, 44.5, 13558.582812500172, 5440.875000000019 - 0.35000000000000003, 2000.0, 45.0, 13836.850000000224, 5549.375000000026 - 0.35000000000000003, 2000.0, 45.5, 14114.94218750027, 5658.062500000033 - 0.35000000000000003, 2000.0, 46.0, 14392.600000000324, 5766.900000000039 - 0.35000000000000003, 2000.0, 46.5, 14668.263281249821, 5875.537499999998 - 0.35000000000000003, 2000.0, 47.0, 14943.493749999781, 5984.375000000004 - 0.35000000000000003, 2000.0, 47.5, 15218.552343749745, 6093.500000000009 - 0.35000000000000003, 2000.0, 48.0, 15493.699999999713, 6203.000000000017 - 0.35000000000000003, 2000.0, 48.5, 15769.197656249687, 6312.962500000024 - 0.35000000000000003, 2000.0, 49.0, 16045.306249999674, 6423.475000000031 - 0.35000000000000003, 2000.0, 49.5, 16322.286718749672, 6534.625000000044 - 0.35000000000000003, 2000.0, 50.0, 16600.399999999685, 6646.500000000054 - 0.35000000000000003, 5000.0, 0.0, 470.14138655522305, 470.14138655522305 - 0.35000000000000003, 5000.0, 22.0, 1255.2999999999995, 879.1999999999999 - 0.35000000000000003, 5000.0, 22.5, 1493.5527343749993, 959.7740234374995 - 0.35000000000000003, 5000.0, 23.0, 1729.3406249999987, 1038.645312499999 - 0.35000000000000003, 5000.0, 23.5, 1963.4832031249985, 1116.2939453124989 - 0.35000000000000003, 5000.0, 24.0, 2196.7999999999975, 1193.1999999999987 - 0.35000000000000003, 5000.0, 24.5, 2430.110546874997, 1269.8435546874982 - 0.35000000000000003, 5000.0, 25.0, 2664.234374999996, 1346.7046874999983 - 0.35000000000000003, 5000.0, 25.5, 2899.991015624996, 1424.2634765624978 - 0.35000000000000003, 5000.0, 26.0, 3138.199999999995, 1502.999999999998 - 0.35000000000000003, 5000.0, 26.5, 3388.2832031249927, 1587.6859374999972 - 0.35000000000000003, 5000.0, 27.0, 3642.9493749999906, 1674.754999999997 - 0.35000000000000003, 5000.0, 27.5, 3901.54335937499, 1763.9515624999963 - 0.35000000000000003, 5000.0, 28.0, 4163.409999999989, 1855.0199999999957 - 0.35000000000000003, 5000.0, 28.5, 4427.894140624987, 1947.7046874999946 - 0.35000000000000003, 5000.0, 29.0, 4694.340624999984, 2041.7499999999943 - 0.35000000000000003, 5000.0, 29.5, 4962.094296874982, 2136.9003124999917 - 0.35000000000000003, 5000.0, 30.0, 5230.499999999981, 2232.8999999999905 - 0.35000000000000003, 5000.0, 30.5, 5492.01728515627, 2327.041113281249 - 0.35000000000000003, 5000.0, 31.0, 5753.532031250023, 2421.7539062499986 - 0.35000000000000003, 5000.0, 31.5, 6015.044824218777, 2517.016308593749 - 0.35000000000000003, 5000.0, 32.0, 6276.556250000028, 2612.8062499999987 - 0.35000000000000003, 5000.0, 32.5, 6538.066894531283, 2709.1016601562474 - 0.35000000000000003, 5000.0, 33.0, 6799.577343750037, 2805.8804687499983 - 0.35000000000000003, 5000.0, 33.5, 7061.088183593789, 2903.1206054687473 - 0.35000000000000003, 5000.0, 34.0, 7322.600000000043, 3000.7999999999965 - 0.35000000000000003, 5000.0, 34.5, 7584.121992187526, 3099.577851562486 - 0.35000000000000003, 5000.0, 35.0, 7845.645312500033, 3198.685937499984 - 0.35000000000000003, 5000.0, 35.5, 8107.16972656254, 3298.037304687481 - 0.35000000000000003, 5000.0, 36.0, 8368.69500000005, 3397.544999999978 - 0.35000000000000003, 5000.0, 36.5, 8630.220898437563, 3497.122070312473 - 0.35000000000000003, 5000.0, 37.0, 8891.747187500065, 3596.6815624999704 - 0.35000000000000003, 5000.0, 37.5, 9153.27363281258, 3696.136523437467 - 0.35000000000000003, 5000.0, 38.0, 9414.800000000094, 3795.3999999999623 - 0.35000000000000003, 5000.0, 38.5, 9676.330273437474, 3893.5244140625027 - 0.35000000000000003, 5000.0, 39.0, 9937.857812499964, 3991.7296875000015 - 0.35000000000000003, 5000.0, 39.5, 10199.381445312463, 4090.1201171875005 - 0.35000000000000003, 5000.0, 40.0, 10460.899999999956, 4188.800000000001 - 0.35000000000000003, 5000.0, 40.5, 10722.397656250034, 4288.298437499993 - 0.35000000000000003, 5000.0, 41.0, 10983.893750000037, 4388.124999999991 - 0.35000000000000003, 5000.0, 41.5, 11245.39296875004, 4488.214062499989 - 0.35000000000000003, 5000.0, 42.0, 11506.900000000041, 4588.499999999986 - 0.35000000000000003, 5000.0, 42.5, 11768.239843750023, 4688.530468750015 - 0.35000000000000003, 5000.0, 43.0, 12029.668750000039, 4788.781250000017 - 0.35000000000000003, 5000.0, 43.5, 12291.263281250061, 4889.341406250019 - 0.35000000000000003, 5000.0, 44.0, 12553.100000000082, 4990.300000000023 - 0.35000000000000003, 5000.0, 44.5, 12816.056250000018, 5092.136718750009 - 0.35000000000000003, 5000.0, 45.0, 13079.087500000027, 5194.393750000012 - 0.35000000000000003, 5000.0, 45.5, 13341.950000000039, 5297.003906250018 - 0.35000000000000003, 5000.0, 46.0, 13604.400000000054, 5399.9000000000215 - 0.35000000000000003, 5000.0, 46.5, 13864.967187499995, 5502.835156250009 - 0.35000000000000003, 5000.0, 47.0, 14125.124999999993, 5605.993750000018 - 0.35000000000000003, 5000.0, 47.5, 14385.120312499988, 5709.380468750025 - 0.35000000000000003, 5000.0, 48.0, 14645.199999999986, 5813.000000000035 - 0.35000000000000003, 5000.0, 48.5, 14905.61093749998, 5916.857031250046 - 0.35000000000000003, 5000.0, 49.0, 15166.59999999997, 6020.956250000058 - 0.35000000000000003, 5000.0, 49.5, 15428.414062499956, 6125.302343750073 - 0.35000000000000003, 5000.0, 50.0, 15691.299999999941, 6229.900000000089 - 0.35000000000000003, 10000.0, 0.0, 395.6912047203211, 395.6912047203211 - 0.35000000000000003, 10000.0, 22.0, 1143.3999999999994, 771.5999999999999 - 0.35000000000000003, 10000.0, 22.5, 1360.4044921874988, 843.6662109374996 - 0.35000000000000003, 10000.0, 23.0, 1575.1765624999978, 914.3453124999992 - 0.35000000000000003, 10000.0, 23.5, 1788.4603515624965, 984.0517578124989 - 0.35000000000000003, 10000.0, 24.0, 2000.999999999996, 1053.199999999998 - 0.35000000000000003, 10000.0, 24.5, 2213.539648437495, 1122.2044921874979 - 0.35000000000000003, 10000.0, 25.0, 2426.8234374999934, 1191.4796874999975 - 0.35000000000000003, 10000.0, 25.5, 2641.5955078124916, 1261.4400390624962 - 0.35000000000000003, 10000.0, 26.0, 2858.59999999999, 1332.4999999999952 - 0.35000000000000003, 10000.0, 26.5, 3086.3945312499964, 1408.60546875 - 0.35000000000000003, 10000.0, 27.0, 3318.356249999995, 1486.8412499999995 - 0.35000000000000003, 10000.0, 27.5, 3553.889843749993, 1567.01640625 - 0.35000000000000003, 10000.0, 28.0, 3792.399999999992, 1648.9399999999996 - 0.35000000000000003, 10000.0, 28.5, 4033.291406249989, 1732.4210937499995 - 0.35000000000000003, 10000.0, 29.0, 4275.968749999987, 1817.2687499999995 - 0.35000000000000003, 10000.0, 29.5, 4519.836718749983, 1903.2920312499998 - 0.35000000000000003, 10000.0, 30.0, 4764.299999999982, 1990.2999999999995 - 0.35000000000000003, 10000.0, 30.5, 5002.512499999992, 2077.191992187505 - 0.35000000000000003, 10000.0, 31.0, 5240.724999999992, 2164.773437500006 - 0.35000000000000003, 10000.0, 31.5, 5478.937499999988, 2252.940039062508 - 0.35000000000000003, 10000.0, 32.0, 5717.149999999988, 2341.5875000000083 - 0.35000000000000003, 10000.0, 32.5, 5955.362499999987, 2430.61152343751 - 0.35000000000000003, 10000.0, 33.0, 6193.574999999986, 2519.9078125000124 - 0.35000000000000003, 10000.0, 33.5, 6431.787499999984, 2609.372070312514 - 0.35000000000000003, 10000.0, 34.0, 6669.9999999999845, 2698.900000000015 - 0.35000000000000003, 10000.0, 34.5, 6908.215781249962, 2786.821328124995 - 0.35000000000000003, 10000.0, 35.0, 7146.431249999954, 2874.746874999994 - 0.35000000000000003, 10000.0, 35.5, 7384.646093749946, 2962.7214843749944 - 0.35000000000000003, 10000.0, 36.0, 7622.859999999936, 3050.7899999999936 - 0.35000000000000003, 10000.0, 36.5, 7861.072656249926, 3138.9972656249934 - 0.35000000000000003, 10000.0, 37.0, 8099.283749999915, 3227.388124999993 - 0.35000000000000003, 10000.0, 37.5, 8337.492968749906, 3316.007421874994 - 0.35000000000000003, 10000.0, 38.0, 8575.699999999892, 3404.899999999994 - 0.35000000000000003, 10000.0, 38.5, 8813.890820312556, 3494.4724609374857 - 0.35000000000000003, 10000.0, 39.0, 9052.08593750007, 3584.220312499981 - 0.35000000000000003, 10000.0, 39.5, 9290.288085937585, 3674.1080078124746 - 0.35000000000000003, 10000.0, 40.0, 9528.500000000096, 3764.0999999999685 - 0.35000000000000003, 10000.0, 40.5, 9766.74687500004, 3853.857031250011 - 0.35000000000000003, 10000.0, 41.0, 10005.000000000055, 3943.7687500000156 - 0.35000000000000003, 10000.0, 41.5, 10243.25312500008, 4033.921093750018 - 0.35000000000000003, 10000.0, 42.0, 10481.500000000106, 4124.400000000022 - 0.35000000000000003, 10000.0, 42.5, 10719.523437500035, 4215.459374999987 - 0.35000000000000003, 10000.0, 43.0, 10957.612500000048, 4306.949999999984 - 0.35000000000000003, 10000.0, 43.5, 11195.845312500063, 4398.890624999981 - 0.35000000000000003, 10000.0, 44.0, 11434.300000000076, 4491.299999999976 - 0.35000000000000003, 10000.0, 44.5, 11673.808593749987, 4584.638281250003 - 0.35000000000000003, 10000.0, 45.0, 11913.393749999988, 4678.306250000003 - 0.35000000000000003, 10000.0, 45.5, 12152.832031249989, 4772.1460937500015 - 0.35000000000000003, 10000.0, 46.0, 12391.899999999998, 4866.000000000002 - 0.35000000000000003, 10000.0, 46.5, 12629.257031250056, 4958.62812500001 - 0.35000000000000003, 10000.0, 47.0, 12866.243750000074, 5051.3875000000135 - 0.35000000000000003, 10000.0, 47.5, 13103.083593750087, 5144.553125000016 - 0.35000000000000003, 10000.0, 48.0, 13340.000000000104, 5238.400000000018 - 0.35000000000000003, 10000.0, 48.5, 13577.216406250118, 5333.20312500002 - 0.35000000000000003, 10000.0, 49.0, 13814.956250000127, 5429.237500000021 - 0.35000000000000003, 10000.0, 49.5, 14053.442968750142, 5526.778125000023 - 0.35000000000000003, 10000.0, 50.0, 14292.90000000015, 5626.10000000002 - 0.35000000000000003, 15000.0, 0.0, 330.8743786403586, 330.8743786403586 - 0.35000000000000003, 15000.0, 22.0, 1021.4999999999997, 665.9999999999995 - 0.35000000000000003, 15000.0, 22.5, 1215.3917968750002, 729.3626953124995 - 0.35000000000000003, 15000.0, 23.0, 1407.2781249999998, 791.3359374999993 - 0.35000000000000003, 15000.0, 23.5, 1597.8253906250002, 852.3162109374996 - 0.35000000000000003, 15000.0, 24.0, 1787.7, 912.6999999999998 - 0.35000000000000003, 15000.0, 24.5, 1977.5683593749998, 972.8837890625 - 0.35000000000000003, 15000.0, 25.0, 2168.0968749999997, 1033.2640625000006 - 0.35000000000000003, 15000.0, 25.5, 2359.9519531249985, 1094.2373046875014 - 0.35000000000000003, 15000.0, 26.0, 2553.799999999999, 1156.2000000000016 - 0.35000000000000003, 15000.0, 26.5, 2757.297851562499, 1222.9365234374989 - 0.35000000000000003, 15000.0, 27.0, 2964.5209374999977, 1291.6490624999985 - 0.35000000000000003, 15000.0, 27.5, 3174.937304687498, 1362.1533203124977 - 0.35000000000000003, 15000.0, 28.0, 3388.0149999999967, 1434.264999999998 - 0.35000000000000003, 15000.0, 28.5, 3603.2220703124967, 1507.799804687498 - 0.35000000000000003, 15000.0, 29.0, 3820.026562499996, 1582.5734374999977 - 0.35000000000000003, 15000.0, 29.5, 4037.896523437496, 1658.4016015624968 - 0.35000000000000003, 15000.0, 30.0, 4256.299999999995, 1735.0999999999972 - 0.35000000000000003, 15000.0, 30.5, 4469.123632812497, 1811.4987304687486 - 0.35000000000000003, 15000.0, 31.0, 4681.948437499999, 1888.4929687499985 - 0.35000000000000003, 15000.0, 31.5, 4894.774023437499, 1965.992285156249 - 0.35000000000000003, 15000.0, 32.0, 5107.599999999997, 2043.906249999999 - 0.35000000000000003, 15000.0, 32.5, 5320.425976562499, 2122.1444335937495 - 0.35000000000000003, 15000.0, 33.0, 5533.2515625, 2200.6164062499993 - 0.35000000000000003, 15000.0, 33.5, 5746.0763671875, 2279.2317382812503 - 0.35000000000000003, 15000.0, 34.0, 5958.900000000002, 2357.8999999999996 - 0.35000000000000003, 15000.0, 34.5, 6171.712226562469, 2435.0234374999945 - 0.35000000000000003, 15000.0, 35.0, 6384.523437499963, 2512.162499999994 - 0.35000000000000003, 15000.0, 35.5, 6597.334179687455, 2589.3703124999943 - 0.35000000000000003, 15000.0, 36.0, 6810.144999999946, 2666.699999999994 - 0.35000000000000003, 15000.0, 36.5, 7022.956445312436, 2744.204687499994 - 0.35000000000000003, 15000.0, 37.0, 7235.769062499926, 2821.9374999999955 - 0.35000000000000003, 15000.0, 37.5, 7448.583398437416, 2899.951562499996 - 0.35000000000000003, 15000.0, 38.0, 7661.399999999905, 2978.2999999999965 - 0.35000000000000003, 15000.0, 38.5, 7874.223632812599, 3057.3259765625085 - 0.35000000000000003, 15000.0, 39.0, 8087.048437500122, 3136.64218750001 - 0.35000000000000003, 15000.0, 39.5, 8299.874023437653, 3216.2373046875127 - 0.35000000000000003, 15000.0, 40.0, 8512.700000000188, 3296.1000000000145 - 0.35000000000000003, 15000.0, 40.5, 8725.528906250043, 3376.073437500004 - 0.35000000000000003, 15000.0, 41.0, 8938.356250000055, 3456.350000000005 - 0.35000000000000003, 15000.0, 41.5, 9151.180468750073, 3536.976562500006 - 0.35000000000000003, 15000.0, 42.0, 9364.000000000095, 3618.0000000000064 - 0.35000000000000003, 15000.0, 42.5, 9576.637500000037, 3699.814843749999 - 0.35000000000000003, 15000.0, 43.0, 9789.337500000049, 3781.98125 - 0.35000000000000003, 15000.0, 43.5, 10002.168750000068, 3864.40703125 - 0.35000000000000003, 15000.0, 44.0, 10215.200000000093, 3947.0000000000027 - 0.35000000000000003, 15000.0, 44.5, 10429.171875000038, 4028.9179687499986 - 0.35000000000000003, 15000.0, 45.0, 10643.212500000054, 4111.118750000001 - 0.35000000000000003, 15000.0, 45.5, 10857.121875000075, 4193.8101562500015 - 0.35000000000000003, 15000.0, 46.0, 11070.700000000093, 4277.200000000004 - 0.35000000000000003, 15000.0, 46.5, 11282.746875000046, 4361.476562500018 - 0.35000000000000003, 15000.0, 47.0, 11494.462500000063, 4446.875000000025 - 0.35000000000000003, 15000.0, 47.5, 11706.046875000084, 4533.610937500028 - 0.35000000000000003, 15000.0, 48.0, 11917.700000000099, 4621.900000000035 - 0.35000000000000003, 15000.0, 48.5, 12129.62187500012, 4711.957812500042 - 0.35000000000000003, 15000.0, 49.0, 12342.012500000148, 4804.000000000047 - 0.35000000000000003, 15000.0, 49.5, 12555.071875000176, 4898.242187500054 - 0.35000000000000003, 15000.0, 50.0, 12769.000000000204, 4994.90000000006 - 0.35000000000000003, 20000.0, 0.0, 274.7482385583025, 274.7482385583025 - 0.35000000000000003, 20000.0, 22.0, 839.8999999999993, 552.0999999999998 - 0.35000000000000003, 20000.0, 22.5, 999.5673828124983, 606.5255859374994 - 0.35000000000000003, 20000.0, 23.0, 1157.5359374999975, 658.5078124999991 - 0.35000000000000003, 20000.0, 23.5, 1314.3615234374963, 708.5361328124986 - 0.35000000000000003, 20000.0, 24.0, 1470.5999999999954, 757.0999999999979 - 0.35000000000000003, 20000.0, 24.5, 1626.8072265624942, 804.6888671874972 - 0.35000000000000003, 20000.0, 25.0, 1783.5390624999923, 851.7921874999964 - 0.35000000000000003, 20000.0, 25.5, 1941.3513671874905, 898.8994140624953 - 0.35000000000000003, 20000.0, 26.0, 2100.7999999999884, 946.4999999999944 - 0.35000000000000003, 20000.0, 26.5, 2268.2705078125023, 998.9867187499981 - 0.35000000000000003, 20000.0, 27.0, 2438.822187500003, 1053.168749999998 - 0.35000000000000003, 20000.0, 27.5, 2612.011523437504, 1108.866406249998 - 0.35000000000000003, 20000.0, 28.0, 2787.395000000006, 1165.899999999998 - 0.35000000000000003, 20000.0, 28.5, 2964.5291015625075, 1224.089843749998 - 0.35000000000000003, 20000.0, 29.0, 3142.9703125000074, 1283.2562499999976 - 0.35000000000000003, 20000.0, 29.5, 3322.2751171875093, 1343.219531249998 - 0.35000000000000003, 20000.0, 30.0, 3502.0000000000105, 1403.799999999998 - 0.35000000000000003, 20000.0, 30.5, 3676.9748046874893, 1462.5313476562462 - 0.35000000000000003, 20000.0, 31.0, 3851.932812499988, 1521.7382812499952 - 0.35000000000000003, 20000.0, 31.5, 4026.8806640624857, 1581.4588867187438 - 0.35000000000000003, 20000.0, 32.0, 4201.824999999984, 1641.731249999993 - 0.35000000000000003, 20000.0, 32.5, 4376.772460937482, 1702.5934570312418 - 0.35000000000000003, 20000.0, 33.0, 4551.729687499984, 1764.0835937499903 - 0.35000000000000003, 20000.0, 33.5, 4726.703320312479, 1826.2397460937386 - 0.35000000000000003, 20000.0, 34.0, 4901.699999999976, 1889.099999999987 - 0.35000000000000003, 20000.0, 34.5, 5076.921601562446, 1956.6469140624856 - 0.35000000000000003, 20000.0, 35.0, 5252.160937499938, 2024.5984374999828 - 0.35000000000000003, 20000.0, 35.5, 5427.406054687429, 2092.6169921874803 - 0.35000000000000003, 20000.0, 36.0, 5602.64499999992, 2160.3649999999766 - 0.35000000000000003, 20000.0, 36.5, 5777.865820312409, 2227.5048828124736 - 0.35000000000000003, 20000.0, 37.0, 5953.056562499897, 2293.6990624999703 - 0.35000000000000003, 20000.0, 37.5, 6128.205273437386, 2358.6099609374655 - 0.35000000000000003, 20000.0, 38.0, 6303.299999999872, 2421.899999999959 - 0.35000000000000003, 20000.0, 38.5, 6478.201171875025, 2479.0951171875095 - 0.35000000000000003, 20000.0, 39.0, 6653.090625000037, 2536.1390625000136 - 0.35000000000000003, 20000.0, 39.5, 6827.984765625047, 2593.6134765625166 - 0.35000000000000003, 20000.0, 40.0, 7002.900000000061, 2652.100000000022 - 0.35000000000000003, 20000.0, 40.5, 7177.924999999978, 2713.837499999998 - 0.35000000000000003, 20000.0, 41.0, 7352.974999999973, 2777.0874999999983 - 0.35000000000000003, 20000.0, 41.5, 7528.037499999966, 2841.768749999999 - 0.35000000000000003, 20000.0, 42.0, 7703.099999999954, 2907.7999999999993 - 0.35000000000000003, 20000.0, 42.5, 7877.982031249984, 2974.8578124999835 - 0.35000000000000003, 20000.0, 43.0, 8052.906249999979, 3043.1999999999794 - 0.35000000000000003, 20000.0, 43.5, 8227.927343749974, 3112.842187499974 - 0.35000000000000003, 20000.0, 44.0, 8403.099999999968, 3183.7999999999683 - 0.35000000000000003, 20000.0, 44.5, 8578.97499999996, 3256.764843749987 - 0.35000000000000003, 20000.0, 45.0, 8754.912499999953, 3330.8062499999855 - 0.35000000000000003, 20000.0, 45.5, 8930.768749999948, 3405.669531249984 - 0.35000000000000003, 20000.0, 46.0, 9106.39999999994, 3481.099999999981 - 0.35000000000000003, 20000.0, 46.5, 9280.95546874998, 3555.7453124999906 - 0.35000000000000003, 20000.0, 47.0, 9455.281249999976, 3630.8874999999866 - 0.35000000000000003, 20000.0, 47.5, 9629.516406249966, 3706.710937499983 - 0.35000000000000003, 20000.0, 48.0, 9803.799999999957, 3783.3999999999787 - 0.35000000000000003, 20000.0, 48.5, 9978.271093749945, 3861.139062499975 - 0.35000000000000003, 20000.0, 49.0, 10153.06874999993, 3940.1124999999693 - 0.35000000000000003, 20000.0, 49.5, 10328.332031249916, 4020.504687499966 - 0.35000000000000003, 20000.0, 50.0, 10504.199999999895, 4102.499999999962 - 0.35000000000000003, 25000.0, 0.0, 226.42397202430985, 226.42397202430985 - 0.35000000000000003, 25000.0, 22.0, 666.5000000000007, 469.90000000000066 - 0.35000000000000003, 25000.0, 22.5, 793.8978515625005, 482.75253906249935 - 0.35000000000000003, 25000.0, 23.0, 919.7671875, 507.0546874999986 - 0.35000000000000003, 25000.0, 23.5, 1044.5779296874991, 541.1044921874983 - 0.35000000000000003, 25000.0, 24.0, 1168.799999999997, 583.1999999999983 - 0.35000000000000003, 25000.0, 24.5, 1292.903320312495, 631.639257812499 - 0.35000000000000003, 25000.0, 25.0, 1417.3578124999924, 684.7203124999992 - 0.35000000000000003, 25000.0, 25.5, 1542.6333984374892, 740.7412109375003 - 0.35000000000000003, 25000.0, 26.0, 1669.1999999999869, 798.0000000000015 - 0.35000000000000003, 25000.0, 26.5, 1802.4125000000015, 841.0708984375076 - 0.35000000000000003, 25000.0, 27.0, 1938.1350000000016, 881.1915625000097 - 0.35000000000000003, 25000.0, 27.5, 2076.0000000000023, 919.0126953125117 - 0.35000000000000003, 25000.0, 28.0, 2215.640000000002, 955.1850000000143 - 0.35000000000000003, 25000.0, 28.5, 2356.6875000000023, 990.359179687516 - 0.35000000000000003, 25000.0, 29.0, 2498.7750000000015, 1025.1859375000188 - 0.35000000000000003, 25000.0, 29.5, 2641.5350000000017, 1060.3159765625217 - 0.35000000000000003, 25000.0, 30.0, 2784.6000000000017, 1096.4000000000246 - 0.35000000000000003, 25000.0, 30.5, 2923.618652343752, 1143.394335937505 - 0.35000000000000003, 25000.0, 31.0, 3062.5867187500057, 1191.757812500008 - 0.35000000000000003, 25000.0, 31.5, 3201.5161132812605, 1241.254882812511 - 0.35000000000000003, 25000.0, 32.0, 3340.4187500000157, 1291.6500000000142 - 0.35000000000000003, 25000.0, 32.5, 3479.3065429687713, 1342.7076171875178 - 0.35000000000000003, 25000.0, 33.0, 3618.1914062500264, 1394.1921875000212 - 0.35000000000000003, 25000.0, 33.5, 3757.0852539062835, 1445.8681640625252 - 0.35000000000000003, 25000.0, 34.0, 3896.0000000000405, 1497.5000000000289 - 0.35000000000000003, 25000.0, 34.5, 4035.193242187592, 1539.3824609375092 - 0.35000000000000003, 25000.0, 35.0, 4174.407812500112, 1581.65156250001 - 0.35000000000000003, 25000.0, 35.5, 4313.632226562631, 1624.9736328125102 - 0.35000000000000003, 25000.0, 36.0, 4452.855000000153, 1670.0150000000108 - 0.35000000000000003, 25000.0, 36.5, 4592.064648437674, 1717.4419921875112 - 0.35000000000000003, 25000.0, 37.0, 4731.2496875002, 1767.9209375000114 - 0.35000000000000003, 25000.0, 37.5, 4870.398632812722, 1822.1181640625114 - 0.35000000000000003, 25000.0, 38.0, 5009.500000000247, 1880.7000000000116 - 0.35000000000000003, 25000.0, 38.5, 5148.290234374963, 1960.4146484375328 - 0.35000000000000003, 25000.0, 39.0, 5287.140624999955, 2037.5078125000382 - 0.35000000000000003, 25000.0, 39.5, 5426.095703124945, 2109.0720703125453 - 0.35000000000000003, 25000.0, 40.0, 5565.199999999941, 2172.200000000053 - 0.35000000000000003, 25000.0, 40.5, 5704.871093750024, 2207.9460937500185 - 0.35000000000000003, 25000.0, 41.0, 5844.631250000039, 2235.8562500000294 - 0.35000000000000003, 25000.0, 41.5, 5984.375781250057, 2259.4382812500417 - 0.35000000000000003, 25000.0, 42.0, 6124.000000000076, 2282.2000000000558 - 0.35000000000000003, 25000.0, 42.5, 6262.719531250057, 2315.1257812499925 - 0.35000000000000003, 25000.0, 43.0, 6401.3812500000895, 2351.2562499999926 - 0.35000000000000003, 25000.0, 43.5, 6540.152343750127, 2391.1085937499925 - 0.35000000000000003, 25000.0, 44.0, 6679.200000000174, 2435.1999999999916 - 0.35000000000000003, 25000.0, 44.5, 6819.843749999981, 2488.032031250021 - 0.35000000000000003, 25000.0, 45.0, 6960.637499999986, 2544.543750000033 - 0.35000000000000003, 25000.0, 45.5, 7101.287499999993, 2603.6585937500445 - 0.35000000000000003, 25000.0, 46.0, 7241.5, 2664.3000000000593 - 0.35000000000000003, 25000.0, 46.5, 7379.52812500002, 2719.5828125000126 - 0.35000000000000003, 25000.0, 47.0, 7517.112500000018, 2776.5625000000196 - 0.35000000000000003, 25000.0, 47.5, 7654.540625000014, 2836.485937500027 - 0.35000000000000003, 25000.0, 48.0, 7792.100000000008, 2900.600000000036 - 0.35000000000000003, 25000.0, 48.5, 7930.078124999998, 2970.1515625000475 - 0.35000000000000003, 25000.0, 49.0, 8068.762499999985, 3046.3875000000617 - 0.35000000000000003, 25000.0, 49.5, 8208.440624999974, 3130.554687500077 - 0.35000000000000003, 25000.0, 50.0, 8349.399999999956, 3223.900000000096 - 0.35000000000000003, 30000.0, 0.0, 185.07507580751943, 185.07507580751943 - 0.35000000000000003, 30000.0, 22.0, 454.80000000000075, 345.19999999999345 - 0.35000000000000003, 30000.0, 22.5, 539.994921875006, 391.0945312499974 - 0.35000000000000003, 30000.0, 23.0, 624.7656250000125, 422.556250000002 - 0.35000000000000003, 30000.0, 23.5, 709.3535156250209, 442.28984375000755 - 0.35000000000000003, 30000.0, 24.0, 794.0000000000322, 453.00000000001427 - 0.35000000000000003, 30000.0, 24.5, 878.9464843750458, 457.39140625002244 - 0.35000000000000003, 30000.0, 25.0, 964.4343750000628, 458.1687500000321 - 0.35000000000000003, 30000.0, 25.5, 1050.7050781250834, 458.0367187500438 - 0.35000000000000003, 30000.0, 26.0, 1138.0000000001075, 459.700000000058 - 0.35000000000000003, 30000.0, 26.5, 1229.4330078124767, 493.1003906249834 - 0.35000000000000003, 30000.0, 27.0, 1322.5371874999685, 535.2618749999815 - 0.35000000000000003, 30000.0, 27.5, 1417.0615234374577, 584.2199218749794 - 0.35000000000000003, 30000.0, 28.0, 1512.7549999999442, 638.0099999999771 - 0.35000000000000003, 30000.0, 28.5, 1609.3666015624278, 694.6675781249749 - 0.35000000000000003, 30000.0, 29.0, 1706.6453124999077, 752.2281249999728 - 0.35000000000000003, 30000.0, 29.5, 1804.3401171873836, 808.7271093749705 - 0.35000000000000003, 30000.0, 30.0, 1902.1999999998554, 862.199999999968 - 0.35000000000000003, 30000.0, 30.5, 1997.1844726563106, 880.5370117187312 - 0.35000000000000003, 30000.0, 31.0, 2092.097656250064, 894.7898437499808 - 0.35000000000000003, 30000.0, 31.5, 2186.9541992188188, 905.86494140623 - 0.35000000000000003, 30000.0, 32.0, 2281.768750000073, 914.668749999978 - 0.35000000000000003, 30000.0, 32.5, 2376.555957031326, 922.1077148437261 - 0.35000000000000003, 30000.0, 33.0, 2471.330468750082, 929.0882812499732 - 0.35000000000000003, 30000.0, 33.5, 2566.1069335938373, 936.5168945312191 - 0.35000000000000003, 30000.0, 34.0, 2660.900000000091, 945.2999999999645 - 0.35000000000000003, 30000.0, 34.5, 2756.44906249995, 963.0111328124964 - 0.35000000000000003, 30000.0, 35.0, 2851.9749999999417, 983.2546875000004 - 0.35000000000000003, 30000.0, 35.5, 2947.4234374999314, 1006.3021484375046 - 0.35000000000000003, 30000.0, 36.0, 3042.7399999999193, 1032.4250000000095 - 0.35000000000000003, 30000.0, 36.5, 3137.870312499904, 1061.8947265625154 - 0.35000000000000003, 30000.0, 37.0, 3232.7599999998874, 1094.9828125000217 - 0.35000000000000003, 30000.0, 37.5, 3327.354687499867, 1131.9607421875291 - 0.35000000000000003, 30000.0, 38.0, 3421.5999999998426, 1173.1000000000374 - 0.35000000000000003, 30000.0, 38.5, 3513.9998046863802, 1232.383007812315 - 0.35000000000000003, 30000.0, 39.0, 3606.689062498674, 1289.2609374997778 - 0.35000000000000003, 30000.0, 39.5, 3699.933789060943, 1340.958398437236 - 0.35000000000000003, 30000.0, 40.0, 3793.9999999981833, 1384.6999999996906 - 0.35000000000000003, 30000.0, 40.5, 3890.9085937499576, 1404.1039062499212 - 0.35000000000000003, 30000.0, 41.0, 3988.4687499999245, 1415.4437499998944 - 0.35000000000000003, 30000.0, 41.5, 4086.244531249882, 1421.3867187498608 - 0.35000000000000003, 30000.0, 42.0, 4183.7999999998265, 1424.5999999998212 - 0.35000000000000003, 30000.0, 42.5, 4279.36718749986, 1413.567187500023 - 0.35000000000000003, 30000.0, 43.0, 4374.374999999819, 1410.8125000000327 - 0.35000000000000003, 30000.0, 43.5, 4468.92031249978, 1424.676562500043 - 0.35000000000000003, 30000.0, 44.0, 4563.099999999742, 1463.500000000054 - 0.35000000000000003, 30000.0, 44.5, 4657.018749999816, 1594.8031249999533 - 0.35000000000000003, 30000.0, 45.0, 4750.762499999789, 1744.0749999999546 - 0.35000000000000003, 30000.0, 45.5, 4844.424999999764, 1895.9843749999611 - 0.35000000000000003, 30000.0, 46.0, 4938.0999999997375, 2035.1999999999744 - 0.35000000000000003, 30000.0, 46.5, 5031.92031249977, 2102.9726562499745 - 0.35000000000000003, 30000.0, 47.0, 5125.9249999996955, 2144.7562499999585 - 0.35000000000000003, 30000.0, 47.5, 5220.192187499605, 2162.5867187499384 - 0.35000000000000003, 30000.0, 48.0, 5314.799999999498, 2158.4999999999136 - 0.35000000000000003, 30000.0, 48.5, 5409.826562499375, 2134.5320312498848 - 0.35000000000000003, 30000.0, 49.0, 5505.349999999236, 2092.718749999852 - 0.35000000000000003, 30000.0, 49.5, 5601.448437499084, 2035.096093749814 - 0.35000000000000003, 30000.0, 50.0, 5698.199999998917, 1963.6999999997693 - 0.35000000000000003, 35000.0, 0.0, 149.93185183540302, 149.93185183540302 - 0.35000000000000003, 35000.0, 22.0, 471.79999999999967, 288.70000000000175 - 0.35000000000000003, 35000.0, 22.5, 566.4238281250039, 291.48144531250665 - 0.35000000000000003, 35000.0, 23.0, 658.8218750000051, 311.74843750001014 - 0.35000000000000003, 35000.0, 23.5, 749.4589843750041, 346.3412109375123 - 0.35000000000000003, 35000.0, 24.0, 838.8000000000008, 392.10000000001315 - 0.35000000000000003, 35000.0, 24.5, 927.3097656249955, 445.86503906251323 - 0.35000000000000003, 35000.0, 25.0, 1015.453124999989, 504.4765625000124 - 0.35000000000000003, 35000.0, 25.5, 1103.6949218749814, 564.7748046875108 - 0.35000000000000003, 35000.0, 26.0, 1192.499999999973, 623.6000000000087 - 0.35000000000000003, 35000.0, 26.5, 1286.3035156249498, 645.6525390625148 - 0.35000000000000003, 35000.0, 27.0, 1381.8268749999434, 658.0759375000148 - 0.35000000000000003, 35000.0, 27.5, 1478.8542968749366, 663.2201171875154 - 0.35000000000000003, 35000.0, 28.0, 1577.1699999999314, 663.4350000000163 - 0.35000000000000003, 35000.0, 28.5, 1676.5582031249264, 661.0705078125183 - 0.35000000000000003, 35000.0, 29.0, 1776.8031249999217, 658.4765625000205 - 0.35000000000000003, 35000.0, 29.5, 1877.688984374917, 658.003085937524 - 0.35000000000000003, 35000.0, 30.0, 1978.9999999999134, 662.0000000000279 - 0.35000000000000003, 35000.0, 30.5, 2078.761230468828, 717.9848632811647 - 0.35000000000000003, 35000.0, 31.0, 2178.6835937500928, 778.8382812499051 - 0.35000000000000003, 35000.0, 31.5, 2278.718847656356, 842.6084960936466 - 0.35000000000000003, 35000.0, 32.0, 2378.818750000122, 907.3437499998884 - 0.35000000000000003, 35000.0, 32.5, 2478.9350585938855, 971.0922851561314 - 0.35000000000000003, 35000.0, 33.0, 2579.019531250153, 1031.9023437498754 - 0.35000000000000003, 35000.0, 33.5, 2679.023925781418, 1087.8221679686199 - 0.35000000000000003, 35000.0, 34.0, 2778.900000000185, 1136.8999999998662 - 0.35000000000000003, 35000.0, 34.5, 2876.266132812849, 1127.4678125000203 - 0.35000000000000003, 35000.0, 35.0, 2973.6296875003836, 1112.0250000000267 - 0.35000000000000003, 35000.0, 35.5, 3071.1646484379175, 1093.3546875000332 - 0.35000000000000003, 35000.0, 36.0, 3169.045000000449, 1074.2400000000398 - 0.35000000000000003, 35000.0, 36.5, 3267.4447265629788, 1057.4640625000457 - 0.35000000000000003, 35000.0, 37.0, 3366.5378125005063, 1045.8100000000527 - 0.35000000000000003, 35000.0, 37.5, 3466.4982421880304, 1042.0609375000581 - 0.35000000000000003, 35000.0, 38.0, 3567.5000000005525, 1049.0000000000646 - 0.35000000000000003, 35000.0, 38.5, 3673.038281250059, 1043.9902343748317 - 0.35000000000000003, 35000.0, 39.0, 3778.24375000008, 1068.4156249997757 - 0.35000000000000003, 35000.0, 39.5, 3882.5523437501074, 1130.708203124711 - 0.35000000000000003, 35000.0, 40.0, 3985.4000000001433, 1239.2999999996375 - 0.35000000000000003, 35000.0, 40.5, 4082.859375000297, 1489.910156249943 - 0.35000000000000003, 35000.0, 41.0, 4179.075000000409, 1768.7687499999115 - 0.35000000000000003, 35000.0, 41.5, 4274.828125000542, 2049.392968749871 - 0.35000000000000003, 35000.0, 42.0, 4370.900000000687, 2305.2999999998246 - 0.35000000000000003, 35000.0, 42.5, 4471.337499999971, 2458.16328124984 - 0.35000000000000003, 35000.0, 43.0, 4572.349999999873, 2554.0812499997755 - 0.35000000000000003, 35000.0, 43.5, 4673.412499999738, 2587.3085937496962 - 0.35000000000000003, 35000.0, 44.0, 4773.999999999557, 2552.0999999996034 - 0.35000000000000003, 35000.0, 44.5, 4870.919531250041, 2336.2843750001134 - 0.35000000000000003, 35000.0, 45.0, 4967.381250000088, 2083.1125000001593 - 0.35000000000000003, 35000.0, 45.5, 5063.9273437501515, 1829.4093750002157 - 0.35000000000000003, 35000.0, 46.0, 5161.10000000024, 1612.000000000284 - 0.35000000000000003, 35000.0, 46.5, 5261.910156249988, 1599.4320312498999 - 0.35000000000000003, 35000.0, 47.0, 5363.443750000023, 1644.1187499998714 - 0.35000000000000003, 35000.0, 47.5, 5465.255468750074, 1730.196093749833 - 0.35000000000000003, 35000.0, 48.0, 5566.9000000001415, 1841.7999999997824 - 0.35000000000000003, 35000.0, 48.5, 5667.9320312502305, 1963.066406249718 - 0.35000000000000003, 35000.0, 49.0, 5767.906250000343, 2078.1312499996357 - 0.35000000000000003, 35000.0, 49.5, 5866.377343750476, 2171.130468749536 - 0.35000000000000003, 35000.0, 50.0, 5962.900000000635, 2226.1999999994127 - 0.35000000000000003, 39000.0, 0.0, 124.35508240851087, 124.35508240851087 - 0.35000000000000003, 39000.0, 22.0, 361.30000000000183, 199.6000000000045 - 0.35000000000000003, 39000.0, 22.5, 435.18496093749616, 186.38339843750182 - 0.35000000000000003, 39000.0, 23.0, 506.6328124999906, 198.82031249999932 - 0.35000000000000003, 39000.0, 23.5, 576.1642578124852, 232.42207031249671 - 0.35000000000000003, 39000.0, 24.0, 644.2999999999796, 282.69999999999396 - 0.35000000000000003, 39000.0, 24.5, 711.5607421874735, 345.16542968749087 - 0.35000000000000003, 39000.0, 25.0, 778.4671874999669, 415.3296874999873 - 0.35000000000000003, 39000.0, 25.5, 845.5400390624594, 488.70410156248295 - 0.35000000000000003, 39000.0, 26.0, 913.2999999999511, 560.7999999999779 - 0.35000000000000003, 39000.0, 26.5, 987.326367187489, 588.1980468749982 - 0.35000000000000003, 39000.0, 27.0, 1063.370312499986, 603.115624999999 - 0.35000000000000003, 39000.0, 27.5, 1141.085351562483, 607.7378906250008 - 0.35000000000000003, 39000.0, 28.0, 1220.1249999999802, 604.2500000000034 - 0.35000000000000003, 39000.0, 28.5, 1300.1427734374777, 594.8371093750068 - 0.35000000000000003, 39000.0, 29.0, 1380.7921874999759, 581.6843750000113 - 0.35000000000000003, 39000.0, 29.5, 1461.7267578124745, 566.9769531250166 - 0.35000000000000003, 39000.0, 30.0, 1542.5999999999744, 552.9000000000226 - 0.35000000000000003, 39000.0, 30.5, 1618.4716796875246, 568.6679687499558 - 0.35000000000000003, 39000.0, 31.0, 1694.0265625000334, 586.8624999999466 - 0.35000000000000003, 39000.0, 31.5, 1769.3556640625443, 607.0945312499365 - 0.35000000000000003, 39000.0, 32.0, 1844.5500000000545, 628.9749999999256 - 0.35000000000000003, 39000.0, 32.5, 1919.700585937568, 652.1148437499132 - 0.35000000000000003, 39000.0, 33.0, 1994.8984375000812, 676.1249999998998 - 0.35000000000000003, 39000.0, 33.5, 2070.234570312596, 700.616406249885 - 0.35000000000000003, 39000.0, 34.0, 2145.800000000112, 725.1999999998692 - 0.35000000000000003, 39000.0, 34.5, 2224.2779296874774, 758.8957031249473 - 0.35000000000000003, 39000.0, 35.0, 2302.9203124999663, 791.0093749999347 - 0.35000000000000003, 39000.0, 35.5, 2381.571289062451, 820.2558593749204 - 0.35000000000000003, 39000.0, 36.0, 2460.074999999931, 845.3499999999048 - 0.35000000000000003, 39000.0, 36.5, 2538.275585937407, 865.0066406248873 - 0.35000000000000003, 39000.0, 37.0, 2616.017187499875, 877.9406249998679 - 0.35000000000000003, 39000.0, 37.5, 2693.1439453123385, 882.8667968748463 - 0.35000000000000003, 39000.0, 38.0, 2769.499999999795, 878.4999999998231 - 0.35000000000000003, 39000.0, 38.5, 2842.4351562501283, 820.0650390625813 - 0.35000000000000003, 39000.0, 39.0, 2915.581250000154, 772.317187500096 - 0.35000000000000003, 39000.0, 39.5, 2989.3367187501844, 743.6357421876148 - 0.35000000000000003, 39000.0, 40.0, 3064.1000000002196, 742.4000000001382 - 0.35000000000000003, 39000.0, 40.5, 3142.339843749998, 803.5703124999893 - 0.35000000000000003, 39000.0, 41.0, 3221.5562499999614, 898.3124999999964 - 0.35000000000000003, 39000.0, 41.5, 3301.3195312499183, 1024.373437500007 - 0.35000000000000003, 39000.0, 42.0, 3381.1999999998743, 1179.5000000000232 - 0.35000000000000003, 39000.0, 42.5, 3458.217187500088, 1397.1070312500647 - 0.35000000000000003, 39000.0, 43.0, 3535.5125000001653, 1625.0062500000754 - 0.35000000000000003, 39000.0, 43.5, 3613.6765625002467, 1846.6773437500847 - 0.35000000000000003, 39000.0, 44.0, 3693.3000000003217, 2045.60000000009 - 0.35000000000000003, 39000.0, 44.5, 3781.110156250054, 2183.4257812499054 - 0.35000000000000003, 39000.0, 45.0, 3869.10625000012, 2274.1937499998894 - 0.35000000000000003, 39000.0, 45.5, 3955.424218750219, 2310.1148437498778 - 0.35000000000000003, 39000.0, 46.0, 4038.200000000359, 2283.399999999869 - 0.35000000000000003, 39000.0, 46.5, 4104.827343750108, 2098.017968749933 - 0.35000000000000003, 39000.0, 47.0, 4168.481250000107, 1869.718749999875 - 0.35000000000000003, 39000.0, 47.5, 4231.594531250093, 1626.0101562498023 - 0.35000000000000003, 39000.0, 48.0, 4296.600000000064, 1394.3999999997138 - 0.35000000000000003, 39000.0, 48.5, 4365.93046875002, 1202.3960937496074 - 0.35000000000000003, 39000.0, 49.0, 4442.0187499999565, 1077.5062499994845 - 0.35000000000000003, 39000.0, 49.5, 4527.297656249867, 1047.2382812493406 - 0.35000000000000003, 39000.0, 50.0, 4624.199999999753, 1139.0999999991827 - 0.35000000000000003, 43000.0, 0.0, 102.60519788529486, 102.60519788529486 - 0.35000000000000003, 43000.0, 22.0, 49.59999999999607, 447.2999999999978 - 0.35000000000000003, 43000.0, 22.5, 72.34902343748085, 308.71757812498936 - 0.35000000000000003, 43000.0, 23.0, 93.62031249996372, 197.54687499998673 - 0.35000000000000003, 43000.0, 23.5, 113.55644531244373, 110.27773437498873 - 0.35000000000000003, 43000.0, 24.0, 132.2999999999201, 43.39999999999399 - 0.35000000000000003, 43000.0, 24.5, 149.99355468739188, -6.596484374998813 - 0.35000000000000003, 43000.0, 25.0, 166.77968749985806, -43.22187499999094 - 0.35000000000000003, 43000.0, 25.5, 182.80097656231808, -69.98632812498379 - 0.35000000000000003, 43000.0, 26.0, 198.19999999977048, -90.39999999997858 - 0.35000000000000003, 43000.0, 26.5, 213.6976562499701, -144.2021484375489 - 0.35000000000000003, 43000.0, 27.0, 228.8912499999676, -200.74406250005833 - 0.35000000000000003, 43000.0, 27.5, 243.82421874996712, -257.32519531256804 - 0.35000000000000003, 43000.0, 28.0, 258.5399999999692, -311.24500000007765 - 0.35000000000000003, 43000.0, 28.5, 273.08203124997397, -359.8029296875866 - 0.35000000000000003, 43000.0, 29.0, 287.4937499999821, -400.29843750009456 - 0.35000000000000003, 43000.0, 29.5, 301.81859374999436, -430.0309765626004 - 0.35000000000000003, 43000.0, 30.0, 316.1000000000106, -446.30000000010403 - 0.35000000000000003, 43000.0, 30.5, 330.36376953133265, -413.2647460938665 - 0.35000000000000003, 43000.0, 31.0, 344.67265625008963, -364.52109375013623 - 0.35000000000000003, 43000.0, 31.5, 359.0717773438478, -300.52470703140654 - 0.35000000000000003, 43000.0, 32.0, 373.6062500001071, -221.73125000017774 - 0.35000000000000003, 43000.0, 32.5, 388.32119140636803, -128.59638671894962 - 0.35000000000000003, 43000.0, 33.0, 403.261718750131, -21.57578125022151 - 0.35000000000000003, 43000.0, 33.5, 418.4729492188963, 98.87490234350551 - 0.35000000000000003, 43000.0, 34.0, 434.0000000001642, 232.29999999973273 - 0.35000000000000003, 43000.0, 34.5, 453.6405078121891, 579.807343749862 - 0.35000000000000003, 43000.0, 35.0, 473.3296874996205, 920.1812499998348 - 0.35000000000000003, 43000.0, 35.5, 492.7552734370392, 1233.769531249805 - 0.35000000000000003, 43000.0, 36.0, 511.60499999944284, 1500.9199999997736 - 0.35000000000000003, 43000.0, 36.5, 529.5666015618299, 1701.980468749738 - 0.35000000000000003, 43000.0, 37.0, 546.3278124991991, 1817.2987499997034 - 0.35000000000000003, 43000.0, 37.5, 561.5763671865485, 1827.2226562496662 - 0.35000000000000003, 43000.0, 38.0, 574.9999999988768, 1712.0999999996247 - 0.35000000000000003, 43000.0, 38.5, 578.6304687503023, 1203.9724609377674 - 0.35000000000000003, 43000.0, 39.0, 583.7812500003864, 660.2453125003622 - 0.35000000000000003, 43000.0, 39.5, 591.841406250482, 116.44550781296857 - 0.35000000000000003, 43000.0, 40.0, 604.2000000005901, -391.89999999941756 - 0.35000000000000003, 43000.0, 40.5, 633.1562500001692, -763.2710937502159 - 0.35000000000000003, 43000.0, 41.0, 664.825000000194, -1054.53125000026 - 0.35000000000000003, 43000.0, 41.5, 696.2312500002228, -1256.5507812503122 - 0.35000000000000003, 43000.0, 42.0, 724.4000000002579, -1360.200000000374 - 0.35000000000000003, 43000.0, 42.5, 732.0124999997553, -1257.2007812503252 - 0.35000000000000003, 43000.0, 43.0, 736.1749999997047, -1077.2312500004787 - 0.35000000000000003, 43000.0, 43.5, 739.6499999996282, -850.8210937506553 - 0.35000000000000003, 43000.0, 44.0, 745.1999999995157, -608.5000000008476 - 0.35000000000000003, 43000.0, 44.5, 768.5835937497127, -435.7312499999912 - 0.35000000000000003, 43000.0, 45.0, 794.3687499995922, -286.1374999999731 - 0.35000000000000003, 43000.0, 45.5, 820.1195312494774, -168.27499999995476 - 0.35000000000000003, 43000.0, 46.0, 843.3999999993828, -90.69999999993809 - 0.35000000000000003, 43000.0, 46.5, 851.153124999308, -129.76953125038108 - 0.35000000000000003, 43000.0, 47.0, 855.8124999990685, -199.11875000044938 - 0.35000000000000003, 43000.0, 47.5, 859.1906249987762, -280.1835937505226 - 0.35000000000000003, 43000.0, 48.0, 863.099999998421, -354.4000000006015 - 0.35000000000000003, 43000.0, 48.5, 869.3531249979926, -403.2039062506865 - 0.35000000000000003, 43000.0, 49.0, 879.7624999974814, -408.03125000077716 - 0.35000000000000003, 43000.0, 49.5, 896.1406249968755, -350.3179687508764 - 0.35000000000000003, 43000.0, 50.0, 920.2999999961662, -211.50000000098316 - 0.35000000000000003, 48000.0, 0.0, 80.68668596183677, 80.68668596183677 - 0.35000000000000003, 48000.0, 22.0, 18.49999999999325, 365.49999999997976 - 0.35000000000000003, 48000.0, 22.5, 47.37109374999862, 252.65820312497914 - 0.35000000000000003, 48000.0, 23.0, 71.04375000000772, 163.6218749999782 - 0.35000000000000003, 48000.0, 23.5, 90.24453125002063, 95.19960937497669 - 0.35000000000000003, 48000.0, 24.0, 105.70000000003746, 44.199999999974594 - 0.35000000000000003, 48000.0, 24.5, 118.13671875005838, 7.431640624971756 - 0.35000000000000003, 48000.0, 25.0, 128.28125000008356, -18.296875000031662 - 0.35000000000000003, 48000.0, 25.5, 136.8601562501131, -36.17695312503605 - 0.35000000000000003, 48000.0, 26.0, 144.60000000014708, -49.4000000000414 - 0.35000000000000003, 48000.0, 26.5, 157.80957031246956, -94.18730468752688 - 0.35000000000000003, 48000.0, 27.0, 171.9521874999685, -142.58781250003295 - 0.35000000000000003, 48000.0, 27.5, 186.79746093746795, -192.1306640625392 - 0.35000000000000003, 48000.0, 28.0, 202.11499999996775, -240.3450000000459 - 0.35000000000000003, 48000.0, 28.5, 217.67441406246803, -284.75996093755253 - 0.35000000000000003, 48000.0, 29.0, 233.24531249996846, -322.904687500059 - 0.35000000000000003, 48000.0, 29.5, 248.5973046874691, -352.308320312565 - 0.35000000000000003, 48000.0, 30.0, 263.49999999996965, -370.50000000007094 - 0.35000000000000003, 48000.0, 30.5, 273.76582031240224, -343.34111328135117 - 0.35000000000000003, 48000.0, 31.0, 283.4984374998788, -303.04453125012236 - 0.35000000000000003, 48000.0, 31.5, 292.84433593735264, -250.1553710938963 - 0.35000000000000003, 48000.0, 32.0, 301.9499999998239, -185.21875000017317 - 0.35000000000000003, 48000.0, 32.5, 310.961914062292, -108.77978515645341 - 0.35000000000000003, 48000.0, 33.0, 320.02656249975774, -21.38359375023616 - 0.35000000000000003, 48000.0, 33.5, 329.2904296872206, 76.4247070309774 - 0.35000000000000003, 48000.0, 34.0, 338.8999999996806, 184.09999999968812 - 0.35000000000000003, 48000.0, 34.5, 354.18613281238044, 454.9094531248609 - 0.35000000000000003, 48000.0, 35.0, 369.61718749987136, 719.8468749998349 - 0.35000000000000003, 48000.0, 35.5, 384.8458984373614, 963.7183593748061 - 0.35000000000000003, 48000.0, 36.0, 399.5249999998495, 1171.329999999768 - 0.35000000000000003, 48000.0, 36.5, 413.30722656233525, 1327.4878906247245 - 0.35000000000000003, 48000.0, 37.0, 425.8453124998185, 1416.9981249996754 - 0.35000000000000003, 48000.0, 37.5, 436.79199218729747, 1424.6667968746215 - 0.35000000000000003, 48000.0, 38.0, 445.79999999977247, 1335.2999999995545 - 0.35000000000000003, 48000.0, 38.5, 443.1458984380589, 942.2369140622941 - 0.35000000000000003, 48000.0, 39.0, 442.7203125006703, 521.0296874997712 - 0.35000000000000003, 48000.0, 39.5, 446.25957031329915, 99.03261718725298 - 0.35000000000000003, 48000.0, 40.0, 455.5000000009478, -296.4000000002643 - 0.35000000000000003, 48000.0, 40.5, 486.5773437498682, -588.594531250151 - 0.35000000000000003, 48000.0, 41.0, 521.0687499998376, -819.2437500001848 - 0.35000000000000003, 48000.0, 41.5, 554.9507812498059, -980.7210937502198 - 0.35000000000000003, 48000.0, 42.0, 584.199999999773, -1065.4000000002557 - 0.35000000000000003, 48000.0, 42.5, 586.3437499998986, -987.3921874998289 - 0.35000000000000003, 48000.0, 43.0, 583.187499999868, -848.637499999791 - 0.35000000000000003, 48000.0, 43.5, 578.0874999998331, -672.8140624997594 - 0.35000000000000003, 48000.0, 44.0, 574.3999999997936, -483.5999999997367 - 0.35000000000000003, 48000.0, 44.5, 587.8718750001074, -345.7281250001777 - 0.35000000000000003, 48000.0, 45.0, 604.5125000001553, -225.40000000022468 - 0.35000000000000003, 48000.0, 45.5, 622.7218750002066, -129.87187500027352 - 0.35000000000000003, 48000.0, 46.0, 640.9000000002594, -66.40000000032404 - 0.35000000000000003, 48000.0, 46.5, 652.5328125000101, -98.29531249983467 - 0.35000000000000003, 48000.0, 47.0, 662.8999999999633, -154.33749999978977 - 0.35000000000000003, 48000.0, 47.5, 672.3671874999243, -219.3609374997344 - 0.35000000000000003, 48000.0, 48.0, 681.2999999999003, -278.19999999966694 - 0.35000000000000003, 48000.0, 48.5, 690.0640624998995, -315.6890624995847 - 0.35000000000000003, 48000.0, 49.0, 699.0249999999286, -316.6624999994874 - 0.35000000000000003, 48000.0, 49.5, 708.5484374999954, -265.9546874993707 - 0.35000000000000003, 48000.0, 50.0, 719.0000000001078, -148.39999999923475 - 0.4, 0.0, 0.0, 567.5271020559065, 567.5271020559065 - 0.4, 0.0, 22.0, 1337.7999999999986, 1076.6999999999985 - 0.4, 0.0, 22.5, 1591.6097656249792, 1171.9378906249951 - 0.4, 0.0, 23.0, 1842.759374999957, 1261.9843749999932 - 0.4, 0.0, 23.5, 2092.129296874931, 1348.0136718749934 - 0.4, 0.0, 24.0, 2340.5999999999, 1431.1999999999935 - 0.4, 0.0, 24.5, 2589.0519531248633, 1512.7175781249948 - 0.4, 0.0, 25.0, 2838.3656249998203, 1593.7406249999963 - 0.4, 0.0, 25.5, 3089.4214843747673, 1675.4433593749984 - 0.4, 0.0, 26.0, 3343.0999999997066, 1758.9999999999995 - 0.4, 0.0, 26.5, 3609.5265625000225, 1856.920117187501 - 0.4, 0.0, 27.0, 3880.8650000000316, 1959.6903125000063 - 0.4, 0.0, 27.5, 4156.410937500041, 2066.5416015625133 - 0.4, 0.0, 28.0, 4435.460000000054, 2176.705000000022 - 0.4, 0.0, 28.5, 4717.307812500069, 2289.411523437534 - 0.4, 0.0, 29.0, 5001.25000000009, 2403.8921875000487 - 0.4, 0.0, 29.5, 5286.582187500114, 2519.3780078125665 - 0.4, 0.0, 30.0, 5572.600000000141, 2635.100000000086 - 0.4, 0.0, 30.5, 5851.162109375002, 2739.9425781249024 - 0.4, 0.0, 31.0, 6129.709375, 2844.4687499998836 - 0.4, 0.0, 31.5, 6408.245703124995, 2948.894921874864 - 0.4, 0.0, 32.0, 6686.77499999999, 3053.437499999844 - 0.4, 0.0, 32.5, 6965.301171874983, 3158.312890624823 - 0.4, 0.0, 33.0, 7243.828124999974, 3263.737499999803 - 0.4, 0.0, 33.5, 7522.359765624963, 3369.9277343747813 - 0.4, 0.0, 34.0, 7800.899999999949, 3477.09999999976 - 0.4, 0.0, 34.5, 8079.523281249539, 3596.084726562344 - 0.4, 0.0, 35.0, 8358.156249999412, 3715.473437499826 - 0.4, 0.0, 35.5, 8636.79609374927, 3834.471679687306 - 0.4, 0.0, 36.0, 8915.439999999111, 3952.284999999788 - 0.4, 0.0, 36.5, 9194.085156248933, 4068.118945312267 - 0.4, 0.0, 37.0, 9472.728749998736, 4181.179062499748 - 0.4, 0.0, 37.5, 9751.36796874852, 4290.670898437227 - 0.4, 0.0, 38.0, 10029.999999998287, 4395.799999999703 - 0.4, 0.0, 38.5, 10308.604101563298, 4489.2349609375915 - 0.4, 0.0, 39.0, 10587.20468750104, 4580.107812500122 - 0.4, 0.0, 39.5, 10865.802929688829, 4669.076757812661 - 0.4, 0.0, 40.0, 11144.400000001671, 4756.800000000209 - 0.4, 0.0, 40.5, 11423.042968749938, 4843.010937499928 - 0.4, 0.0, 41.0, 11701.668749999895, 4929.662499999902 - 0.4, 0.0, 41.5, 11980.260156249826, 5017.78281249987 - 0.4, 0.0, 42.0, 12258.799999999734, 5108.399999999826 - 0.4, 0.0, 42.5, 12536.907812500061, 5203.901562499752 - 0.4, 0.0, 43.0, 12815.075000000063, 5303.41249999968 - 0.4, 0.0, 43.5, 13093.429687500058, 5407.417187499604 - 0.4, 0.0, 44.0, 13372.100000000062, 5516.399999999516 - 0.4, 0.0, 44.5, 13652.268749999506, 5634.911718750054 - 0.4, 0.0, 45.0, 13932.587499999292, 5757.743750000066 - 0.4, 0.0, 45.5, 14212.762499999018, 5883.753906250088 - 0.4, 0.0, 46.0, 14492.499999998683, 6011.800000000125 - 0.4, 0.0, 46.5, 14770.076562499466, 6138.4390624997 - 0.4, 0.0, 47.0, 15047.199999999313, 6265.749999999584 - 0.4, 0.0, 47.5, 15324.148437499141, 6393.510937499456 - 0.4, 0.0, 48.0, 15601.19999999896, 6521.499999999311 - 0.4, 0.0, 48.5, 15878.632812498774, 6649.495312499152 - 0.4, 0.0, 49.0, 16156.724999998585, 6777.274999998981 - 0.4, 0.0, 49.5, 16435.754687498393, 6904.617187498795 - 0.4, 0.0, 50.0, 16715.999999998203, 7031.299999998599 - 0.4, 2000.0, 0.0, 531.3584586571458, 531.3584586571458 - 0.4, 2000.0, 22.0, 1073.9000000000012, 941.3999999999993 - 0.4, 2000.0, 22.5, 1277.7357421874956, 1013.9261718749993 - 0.4, 2000.0, 23.0, 1479.4640624999881, 1085.3156249999997 - 0.4, 2000.0, 23.5, 1679.7853515624784, 1155.8972656249996 - 0.4, 2000.0, 24.0, 1879.399999999966, 1225.9999999999993 - 0.4, 2000.0, 24.5, 2079.0083984374496, 1295.9527343749996 - 0.4, 2000.0, 25.0, 2279.3109374999312, 1366.0843750000004 - 0.4, 2000.0, 25.5, 2481.00800781241, 1436.7238281250009 - 0.4, 2000.0, 26.0, 2684.799999999884, 1508.2000000000019 - 0.4, 2000.0, 26.5, 2898.7359375000065, 1583.9466796874995 - 0.4, 2000.0, 27.0, 3116.5875000000083, 1661.3653125000026 - 0.4, 2000.0, 27.5, 3337.795312500011, 1740.2525390625053 - 0.4, 2000.0, 28.0, 3561.800000000013, 1820.4050000000095 - 0.4, 2000.0, 28.5, 3788.042187500016, 1901.6193359375147 - 0.4, 2000.0, 29.0, 4015.962500000021, 1983.6921875000203 - 0.4, 2000.0, 29.5, 4245.001562500027, 2066.4201953125275 - 0.4, 2000.0, 30.0, 4474.600000000035, 2149.6000000000354 - 0.4, 2000.0, 30.5, 4698.322949218718, 2230.6161132812417 - 0.4, 2000.0, 31.0, 4922.0460937499665, 2311.907031249991 - 0.4, 2000.0, 31.5, 5145.769628906216, 2393.499121093743 - 0.4, 2000.0, 32.0, 5369.493749999965, 2475.418749999994 - 0.4, 2000.0, 32.5, 5593.218652343715, 2557.6922851562463 - 0.4, 2000.0, 33.0, 5816.944531249967, 2640.3460937499985 - 0.4, 2000.0, 33.5, 6040.671582031218, 2723.4065429687516 - 0.4, 2000.0, 34.0, 6264.399999999972, 2806.900000000004 - 0.4, 2000.0, 34.5, 6488.137773437584, 2891.41023437494 - 0.4, 2000.0, 35.0, 6711.876562500084, 2976.353124999923 - 0.4, 2000.0, 35.5, 6935.615820312581, 3061.7019531249066 - 0.4, 2000.0, 36.0, 7159.355000000077, 3147.4299999998866 - 0.4, 2000.0, 36.5, 7383.093554687567, 3233.510546874864 - 0.4, 2000.0, 37.0, 7606.830937500056, 3319.91687499984 - 0.4, 2000.0, 37.5, 7830.566601562539, 3406.6222656248133 - 0.4, 2000.0, 38.0, 8054.30000000002, 3493.599999999785 - 0.4, 2000.0, 38.5, 8278.021093750509, 3580.8244140625306 - 0.4, 2000.0, 39.0, 8501.743750000634, 3668.2671875000256 - 0.4, 2000.0, 39.5, 8725.469531250776, 3755.9013671875173 - 0.4, 2000.0, 40.0, 8949.200000000941, 3843.70000000001 - 0.4, 2000.0, 40.5, 9172.948437500112, 3931.439843750011 - 0.4, 2000.0, 41.0, 9396.700000000159, 4019.368750000038 - 0.4, 2000.0, 41.5, 9620.451562500213, 4107.538281250073 - 0.4, 2000.0, 42.0, 9844.200000000283, 4196.000000000124 - 0.4, 2000.0, 42.5, 10067.754687499912, 4285.035937500016 - 0.4, 2000.0, 43.0, 10291.374999999942, 4374.375000000024 - 0.4, 2000.0, 43.5, 10515.132812499989, 4463.976562500033 - 0.4, 2000.0, 44.0, 10739.100000000057, 4553.800000000045 - 0.4, 2000.0, 44.5, 10964.05546875038, 4643.921875000039 - 0.4, 2000.0, 45.0, 11189.081250000489, 4734.13750000005 - 0.4, 2000.0, 45.5, 11413.966406250596, 4824.359375000059 - 0.4, 2000.0, 46.0, 11638.500000000717, 4914.500000000067 - 0.4, 2000.0, 46.5, 11861.412499999591, 5003.999218749981 - 0.4, 2000.0, 47.0, 12083.974999999498, 5093.4312499999905 - 0.4, 2000.0, 47.5, 12306.39999999941, 5182.897656250003 - 0.4, 2000.0, 48.0, 12528.89999999933, 5272.500000000016 - 0.4, 2000.0, 48.5, 12751.687499999263, 5362.339843750032 - 0.4, 2000.0, 49.0, 12974.974999999222, 5452.518750000049 - 0.4, 2000.0, 49.5, 13198.974999999204, 5543.138281250066 - 0.4, 2000.0, 50.0, 13423.899999999216, 5634.300000000086 - 0.4, 5000.0, 0.0, 480.5423716860524, 480.5423716860524 - 0.4, 5000.0, 22.0, 1019.0999999999992, 864.7000000000003 - 0.4, 5000.0, 22.5, 1212.4978515624982, 933.2904296874988 - 0.4, 5000.0, 23.0, 1403.9046874999965, 1000.5890624999978 - 0.4, 5000.0, 23.5, 1593.9841796874953, 1066.9431640624978 - 0.4, 5000.0, 24.0, 1783.3999999999935, 1132.699999999997 - 0.4, 5000.0, 24.5, 1972.8158203124904, 1198.2068359374978 - 0.4, 5000.0, 25.0, 2162.895312499987, 1263.810937499998 - 0.4, 5000.0, 25.5, 2354.3021484374835, 1329.8595703124986 - 0.4, 5000.0, 26.0, 2547.6999999999784, 1396.6999999999998 - 0.4, 5000.0, 26.5, 2750.7224609374766, 1467.8554687499932 - 0.4, 5000.0, 27.0, 2957.4615624999724, 1540.6787499999914 - 0.4, 5000.0, 27.5, 3167.386132812466, 1614.9726562499895 - 0.4, 5000.0, 28.0, 3379.964999999961, 1690.5399999999877 - 0.4, 5000.0, 28.5, 3594.6669921874545, 1767.1835937499861 - 0.4, 5000.0, 29.0, 3810.9609374999477, 1844.7062499999845 - 0.4, 5000.0, 29.5, 4028.31566406244, 1922.9107812499824 - 0.4, 5000.0, 30.0, 4246.199999999933, 2001.5999999999801 - 0.4, 5000.0, 30.5, 4458.49931640631, 2078.3524414062485 - 0.4, 5000.0, 31.0, 4670.797656250067, 2155.4070312499975 - 0.4, 5000.0, 31.5, 4883.095605468827, 2232.7784179687483 - 0.4, 5000.0, 32.0, 5095.393750000086, 2310.4812499999975 - 0.4, 5000.0, 32.5, 5307.692675781342, 2388.530175781247 - 0.4, 5000.0, 33.0, 5519.9929687501, 2466.9398437499976 - 0.4, 5000.0, 33.5, 5732.295214843856, 2545.724902343747 - 0.4, 5000.0, 34.0, 5944.600000000112, 2624.899999999997 - 0.4, 5000.0, 34.5, 6156.925546875071, 2705.0084765624583 - 0.4, 5000.0, 35.0, 6369.2531250000875, 2785.485937499952 - 0.4, 5000.0, 35.5, 6581.581640625104, 2866.2966796874457 - 0.4, 5000.0, 36.0, 6793.9100000001245, 2947.4049999999384 - 0.4, 5000.0, 36.5, 7006.237109375146, 3028.775195312432 - 0.4, 5000.0, 37.0, 7218.561875000174, 3110.3715624999245 - 0.4, 5000.0, 37.5, 7430.8832031252, 3192.158398437417 - 0.4, 5000.0, 38.0, 7643.200000000234, 3274.0999999999085 - 0.4, 5000.0, 38.5, 7855.502734374783, 3355.755664062476 - 0.4, 5000.0, 39.0, 8067.80312499975, 3437.7046874999664 - 0.4, 5000.0, 39.5, 8280.101953124718, 3520.0013671874526 - 0.4, 5000.0, 40.0, 8492.399999999678, 3602.699999999938 - 0.4, 5000.0, 40.5, 8704.70000000008, 3686.2328124999613 - 0.4, 5000.0, 41.0, 8917.00000000008, 3770.1249999999527 - 0.4, 5000.0, 41.5, 9129.300000000081, 3854.2796874999426 - 0.4, 5000.0, 42.0, 9341.600000000075, 3938.599999999934 - 0.4, 5000.0, 42.5, 9553.732031250025, 4022.715625000026 - 0.4, 5000.0, 43.0, 9765.931250000058, 4106.9125000000295 - 0.4, 5000.0, 43.5, 9978.2648437501, 4191.20312500003 - 0.4, 5000.0, 44.0, 10190.800000000147, 4275.6000000000295 - 0.4, 5000.0, 44.5, 10404.27187500005, 4360.314843750031 - 0.4, 5000.0, 45.0, 10617.812500000071, 4445.081250000039 - 0.4, 5000.0, 45.5, 10831.221875000101, 4529.83203125005 - 0.4, 5000.0, 46.0, 11044.300000000138, 4614.500000000059 - 0.4, 5000.0, 46.5, 11255.84687499994, 4698.69765625003 - 0.4, 5000.0, 47.0, 11467.062499999907, 4782.806250000047 - 0.4, 5000.0, 47.5, 11678.146874999873, 4866.886718750067 - 0.4, 5000.0, 48.0, 11889.299999999834, 4951.0000000000955 - 0.4, 5000.0, 48.5, 12100.72187499978, 5035.207031250127 - 0.4, 5000.0, 49.0, 12312.61249999972, 5119.568750000161 - 0.4, 5000.0, 49.5, 12525.171874999645, 5204.146093750203 - 0.4, 5000.0, 50.0, 12738.599999999564, 5289.000000000249 - 0.4, 10000.0, 0.0, 404.44512099825465, 404.44512099825465 - 0.4, 10000.0, 22.0, 936.1999999999996, 757.9999999999999 - 0.4, 10000.0, 22.5, 1113.8828124999973, 820.3126953124988 - 0.4, 10000.0, 23.0, 1289.7374999999945, 881.2859374999979 - 0.4, 10000.0, 23.5, 1464.3734374999917, 941.2662109374962 - 0.4, 10000.0, 24.0, 1638.399999999988, 1000.5999999999945 - 0.4, 10000.0, 24.5, 1812.4265624999841, 1059.6337890624923 - 0.4, 10000.0, 25.0, 1987.0624999999793, 1118.7140624999902 - 0.4, 10000.0, 25.5, 2162.917187499974, 1178.187304687487 - 0.4, 10000.0, 26.0, 2340.599999999966, 1238.3999999999835 - 0.4, 10000.0, 26.5, 2527.1187499999924, 1302.7638671874997 - 0.4, 10000.0, 27.0, 2717.0499999999874, 1368.7353124999995 - 0.4, 10000.0, 27.5, 2909.9062499999827, 1436.135351562499 - 0.4, 10000.0, 28.0, 3105.199999999976, 1504.784999999999 - 0.4, 10000.0, 28.5, 3302.443749999969, 1574.5052734374985 - 0.4, 10000.0, 29.0, 3501.1499999999614, 1645.1171874999986 - 0.4, 10000.0, 29.5, 3700.8312499999524, 1716.4417578124983 - 0.4, 10000.0, 30.0, 3900.9999999999422, 1788.2999999999986 - 0.4, 10000.0, 30.5, 4096.0479492187305, 1858.676660156268 - 0.4, 10000.0, 31.0, 4291.096093749978, 1929.4039062500228 - 0.4, 10000.0, 31.5, 4486.14462890622, 2000.4776367187765 - 0.4, 10000.0, 32.0, 4681.193749999968, 2071.893750000031 - 0.4, 10000.0, 32.5, 4876.24365234371, 2143.648144531286 - 0.4, 10000.0, 33.0, 5071.294531249956, 2215.7367187500417 - 0.4, 10000.0, 33.5, 5266.346582031199, 2288.155371093797 - 0.4, 10000.0, 34.0, 5461.399999999944, 2360.9000000000533 - 0.4, 10000.0, 34.5, 5656.462773437412, 2433.8988281250004 - 0.4, 10000.0, 35.0, 5851.526562499895, 2507.221875000003 - 0.4, 10000.0, 35.5, 6046.590820312375, 2580.8714843750045 - 0.4, 10000.0, 36.0, 6241.654999999857, 2654.8500000000076 - 0.4, 10000.0, 36.5, 6436.7185546873325, 2729.1597656250124 - 0.4, 10000.0, 37.0, 6631.78093749981, 2803.803125000016 - 0.4, 10000.0, 37.5, 6826.841601562281, 2878.7824218750216 - 0.4, 10000.0, 38.0, 7021.899999999753, 2954.100000000029 - 0.4, 10000.0, 38.5, 7216.951367187628, 3030.0957031249636 - 0.4, 10000.0, 39.0, 7412.00156250016, 3106.25937499995 - 0.4, 10000.0, 39.5, 7607.050976562693, 3182.5183593749357 - 0.4, 10000.0, 40.0, 7802.100000000234, 3258.79999999992 - 0.4, 10000.0, 40.5, 7997.150000000112, 3334.7250000000404 - 0.4, 10000.0, 41.0, 8192.200000000152, 3410.6500000000515 - 0.4, 10000.0, 41.5, 8387.250000000202, 3486.625000000062 - 0.4, 10000.0, 42.0, 8582.300000000258, 3562.7000000000717 - 0.4, 10000.0, 42.5, 8777.19765625017, 3639.1749999999797 - 0.4, 10000.0, 43.0, 8972.156250000224, 3715.749999999972 - 0.4, 10000.0, 43.5, 9167.236718750284, 3792.374999999963 - 0.4, 10000.0, 44.0, 9362.500000000344, 3868.999999999954 - 0.4, 10000.0, 44.5, 9558.616406249932, 3945.371875000002 - 0.4, 10000.0, 45.0, 9754.793749999935, 4021.725 - 0.4, 10000.0, 45.5, 9950.849218749943, 4098.090624999993 - 0.4, 10000.0, 46.0, 10146.599999999964, 4174.499999999987 - 0.4, 10000.0, 46.5, 10340.949218750206, 4250.917968750033 - 0.4, 10000.0, 47.0, 10534.993750000254, 4327.468750000044 - 0.4, 10000.0, 47.5, 10728.916406250311, 4404.210156250052 - 0.4, 10000.0, 48.0, 10922.900000000362, 4481.200000000062 - 0.4, 10000.0, 48.5, 11117.127343750411, 4558.496093750069 - 0.4, 10000.0, 49.0, 11311.78125000045, 4636.156250000077 - 0.4, 10000.0, 49.5, 11507.044531250485, 4714.238281250084 - 0.4, 10000.0, 50.0, 11703.100000000511, 4792.800000000088 - 0.4, 15000.0, 0.0, 338.194345762646, 338.194345762646 - 0.4, 15000.0, 22.0, 839.1000000000004, 652.9999999999989 - 0.4, 15000.0, 22.5, 998.3613281250018, 707.3699218749987 - 0.4, 15000.0, 23.0, 1155.9843750000034, 760.7406249999988 - 0.4, 15000.0, 23.5, 1312.5152343750053, 813.3910156249995 - 0.4, 15000.0, 24.0, 1468.5000000000073, 865.6000000000001 - 0.4, 15000.0, 24.5, 1624.4847656250095, 917.6464843750013 - 0.4, 15000.0, 25.0, 1781.0156250000111, 969.8093750000029 - 0.4, 15000.0, 25.5, 1938.6386718750132, 1022.3675781250049 - 0.4, 15000.0, 26.0, 2097.900000000016, 1075.6000000000079 - 0.4, 15000.0, 26.5, 2265.0796874999996, 1132.2751953124955 - 0.4, 15000.0, 27.0, 2435.3175, 1190.3246874999938 - 0.4, 15000.0, 27.5, 2608.1765624999994, 1249.6005859374932 - 0.4, 15000.0, 28.0, 2783.2199999999984, 1309.9549999999917 - 0.4, 15000.0, 28.5, 2960.0109374999975, 1371.2400390624905 - 0.4, 15000.0, 29.0, 3138.1124999999965, 1433.3078124999902 - 0.4, 15000.0, 29.5, 3317.087812499995, 1496.0104296874886 - 0.4, 15000.0, 30.0, 3496.4999999999955, 1559.1999999999869 - 0.4, 15000.0, 30.5, 3671.325000000001, 1621.179882812493 - 0.4, 15000.0, 31.0, 3846.1500000000024, 1683.4984374999924 - 0.4, 15000.0, 31.5, 4020.9750000000035, 1746.1552734374914 - 0.4, 15000.0, 32.0, 4195.800000000007, 1809.1499999999903 - 0.4, 15000.0, 32.5, 4370.625000000009, 1872.4822265624896 - 0.4, 15000.0, 33.0, 4545.450000000011, 1936.1515624999895 - 0.4, 15000.0, 33.5, 4720.275000000012, 2000.1576171874888 - 0.4, 15000.0, 34.0, 4895.100000000015, 2064.499999999989 - 0.4, 15000.0, 34.5, 5069.931562499948, 2129.572070312501 - 0.4, 15000.0, 35.0, 5244.762499999933, 2194.942187500003 - 0.4, 15000.0, 35.5, 5419.592187499917, 2260.5724609375065 - 0.4, 15000.0, 36.0, 5594.419999999899, 2326.4250000000116 - 0.4, 15000.0, 36.5, 5769.24531249988, 2392.4619140625173 - 0.4, 15000.0, 37.0, 5944.067499999857, 2458.645312500022 - 0.4, 15000.0, 37.5, 6118.8859374998365, 2524.9373046875303 - 0.4, 15000.0, 38.0, 6293.69999999981, 2591.300000000038 - 0.4, 15000.0, 38.5, 6468.497460937773, 2657.3949218750463 - 0.4, 15000.0, 39.0, 6643.295312500344, 2723.6406250000555 - 0.4, 15000.0, 39.5, 6818.095507812928, 2790.066015625067 - 0.4, 15000.0, 40.0, 6992.900000000522, 2856.700000000081 - 0.4, 15000.0, 40.5, 7167.719531250133, 2923.7726562500034 - 0.4, 15000.0, 41.0, 7342.543750000182, 2991.031250000003 - 0.4, 15000.0, 41.5, 7517.371093750237, 3058.4242187500004 - 0.4, 15000.0, 42.0, 7692.2000000003, 3125.899999999999 - 0.4, 15000.0, 42.5, 7866.888281250107, 3193.153124999995 - 0.4, 15000.0, 43.0, 8041.6312500001495, 3260.4874999999965 - 0.4, 15000.0, 43.5, 8216.4835937502, 3327.9531249999973 - 0.4, 15000.0, 44.0, 8391.500000000256, 3395.6000000000013 - 0.4, 15000.0, 44.5, 8567.278125000099, 3463.6968749999874 - 0.4, 15000.0, 45.0, 8743.11250000013, 3531.987499999986 - 0.4, 15000.0, 45.5, 8918.840625000175, 3600.4343749999844 - 0.4, 15000.0, 46.0, 9094.300000000228, 3668.9999999999827 - 0.4, 15000.0, 46.5, 9268.519531250136, 3737.0453125000677 - 0.4, 15000.0, 47.0, 9442.468750000182, 3805.3750000000864 - 0.4, 15000.0, 47.5, 9616.308593750235, 3874.192187500107 - 0.4, 15000.0, 48.0, 9790.200000000295, 3943.700000000128 - 0.4, 15000.0, 48.5, 9964.303906250363, 4014.101562500151 - 0.4, 15000.0, 49.0, 10138.781250000438, 4085.600000000177 - 0.4, 15000.0, 49.5, 10313.792968750515, 4158.398437500203 - 0.4, 15000.0, 50.0, 10489.500000000606, 4232.700000000231 - 0.4, 20000.0, 0.0, 280.8265214444462, 280.8265214444462 - 0.4, 20000.0, 22.0, 824.9, 588.3 - 0.4, 20000.0, 22.5, 981.4535156249998, 639.5314453125 - 0.4, 20000.0, 23.0, 1136.3968749999997, 690.3859374999998 - 0.4, 20000.0, 23.5, 1290.2667968749995, 741.0474609374997 - 0.4, 20000.0, 24.0, 1443.5999999999992, 791.6999999999996 - 0.4, 20000.0, 24.5, 1596.9332031249992, 842.5275390624995 - 0.4, 20000.0, 25.0, 1750.8031249999988, 893.7140624999992 - 0.4, 20000.0, 25.5, 1905.7464843749985, 945.4435546874989 - 0.4, 20000.0, 26.0, 2062.2999999999984, 997.8999999999987 - 0.4, 20000.0, 26.5, 2226.635937500001, 1052.9681640625001 - 0.4, 20000.0, 27.0, 2393.9775000000004, 1109.2284375000002 - 0.4, 20000.0, 27.5, 2563.895312500001, 1166.5732421875002 - 0.4, 20000.0, 28.0, 2735.960000000001, 1224.895 - 0.4, 20000.0, 28.5, 2909.7421875000014, 1284.0861328125002 - 0.4, 20000.0, 29.0, 3084.8125000000014, 1344.0390625 - 0.4, 20000.0, 29.5, 3260.7415625000012, 1404.6462109375002 - 0.4, 20000.0, 30.0, 3437.1000000000017, 1465.8000000000002 - 0.4, 20000.0, 30.5, 3608.947949218749, 1526.4047851562498 - 0.4, 20000.0, 31.0, 3780.796093749999, 1587.4351562499999 - 0.4, 20000.0, 31.5, 3952.6446289062487, 1648.8776367187497 - 0.4, 20000.0, 32.0, 4124.493749999998, 1710.7187499999995 - 0.4, 20000.0, 32.5, 4296.343652343748, 1772.9450195312495 - 0.4, 20000.0, 33.0, 4468.194531249998, 1835.5429687499993 - 0.4, 20000.0, 33.5, 4640.046582031247, 1898.4991210937492 - 0.4, 20000.0, 34.0, 4811.899999999997, 1961.7999999999993 - 0.4, 20000.0, 34.5, 4983.762773437493, 2025.68109375 - 0.4, 20000.0, 35.0, 5155.626562499991, 2089.85625 - 0.4, 20000.0, 35.5, 5327.490820312489, 2154.28828125 - 0.4, 20000.0, 36.0, 5499.354999999988, 2218.94 - 0.4, 20000.0, 36.5, 5671.218554687485, 2283.7742187500003 - 0.4, 20000.0, 37.0, 5843.080937499984, 2348.7537500000003 - 0.4, 20000.0, 37.5, 6014.941601562482, 2413.8414062499996 - 0.4, 20000.0, 38.0, 6186.799999999979, 2479.0 - 0.4, 20000.0, 38.5, 6358.651367187514, 2543.847460937504 - 0.4, 20000.0, 39.0, 6530.501562500017, 2608.8703125000043 - 0.4, 20000.0, 39.5, 6702.3509765625195, 2674.108007812505 - 0.4, 20000.0, 40.0, 6874.200000000023, 2739.600000000006 - 0.4, 20000.0, 40.5, 7046.049999999996, 2805.2890624999986 - 0.4, 20000.0, 41.0, 7217.899999999994, 2871.3499999999985 - 0.4, 20000.0, 41.5, 7389.749999999994, 2937.8609374999987 - 0.4, 20000.0, 42.0, 7561.599999999991, 3004.8999999999983 - 0.4, 20000.0, 42.5, 7733.317187500007, 3072.6351562500017 - 0.4, 20000.0, 43.0, 7905.087500000009, 3141.018750000002 - 0.4, 20000.0, 43.5, 8076.96406250001, 3210.092968750003 - 0.4, 20000.0, 44.0, 8249.000000000013, 3279.9000000000037 - 0.4, 20000.0, 44.5, 8421.779687499999, 3350.58359375 - 0.4, 20000.0, 45.0, 8594.6125, 3422.04375 - 0.4, 20000.0, 45.5, 8767.3390625, 3494.28203125 - 0.4, 20000.0, 46.0, 8939.800000000001, 3567.2999999999997 - 0.4, 20000.0, 46.5, 9111.035156249998, 3640.7906250000024 - 0.4, 20000.0, 47.0, 9282.006249999997, 3715.1875000000023 - 0.4, 20000.0, 47.5, 9452.874218749996, 3790.6156250000026 - 0.4, 20000.0, 48.0, 9623.799999999994, 3867.200000000003 - 0.4, 20000.0, 48.5, 9794.944531249994, 3945.0656250000034 - 0.4, 20000.0, 49.0, 9966.46874999999, 4024.3375000000033 - 0.4, 20000.0, 49.5, 10138.53359374999, 4105.140625000004 - 0.4, 20000.0, 50.0, 10311.299999999988, 4187.600000000004 - 0.4, 25000.0, 0.0, 231.43317230668393, 231.43317230668393 - 0.4, 25000.0, 22.0, 662.5000000000001, 487.80000000000007 - 0.4, 25000.0, 22.5, 788.4654296874997, 520.3791015624997 - 0.4, 25000.0, 23.0, 913.0765624999996, 556.2296874999993 - 0.4, 25000.0, 23.5, 1036.7744140624989, 594.9404296874991 - 0.4, 25000.0, 24.0, 1159.9999999999984, 636.099999999999 - 0.4, 25000.0, 24.5, 1283.1943359374975, 679.2970703124989 - 0.4, 25000.0, 25.0, 1406.7984374999965, 724.1203124999994 - 0.4, 25000.0, 25.5, 1531.2533203124954, 770.1583984374992 - 0.4, 25000.0, 26.0, 1656.999999999994, 816.9999999999993 - 0.4, 25000.0, 26.5, 1789.099218750001, 861.1439453125026 - 0.4, 25000.0, 27.0, 1923.6362500000016, 905.0921875000032 - 0.4, 25000.0, 27.5, 2060.2601562500017, 948.9630859375039 - 0.4, 25000.0, 28.0, 2198.6200000000017, 992.8750000000045 - 0.4, 25000.0, 28.5, 2338.364843750002, 1036.9462890625055 - 0.4, 25000.0, 29.0, 2479.143750000002, 1081.2953125000067 - 0.4, 25000.0, 29.5, 2620.6057812500035, 1126.040429687507 - 0.4, 25000.0, 30.0, 2762.4000000000046, 1171.300000000008 - 0.4, 25000.0, 30.5, 2900.4516601562486, 1219.2062500000006 - 0.4, 25000.0, 31.0, 3038.488281249999, 1267.6718750000005 - 0.4, 25000.0, 31.5, 3176.5135742187504, 1316.6234375000013 - 0.4, 25000.0, 32.0, 3314.5312500000014, 1365.9875000000018 - 0.4, 25000.0, 32.5, 3452.545019531253, 1415.6906250000025 - 0.4, 25000.0, 33.0, 3590.558593750005, 1465.6593750000031 - 0.4, 25000.0, 33.5, 3728.5756835937564, 1515.820312500004 - 0.4, 25000.0, 34.0, 3866.600000000007, 1566.1000000000047 - 0.4, 25000.0, 34.5, 4004.7144140625237, 1613.4776171875033 - 0.4, 25000.0, 35.0, 4142.835937500027, 1661.1078125000035 - 0.4, 25000.0, 35.5, 4280.9607421875335, 1709.197851562504 - 0.4, 25000.0, 36.0, 4419.08500000004, 1757.9550000000045 - 0.4, 25000.0, 36.5, 4557.2048828125435, 1807.5865234375055 - 0.4, 25000.0, 37.0, 4695.31656250005, 1858.2996875000063 - 0.4, 25000.0, 37.5, 4833.416210937557, 1910.3017578125068 - 0.4, 25000.0, 38.0, 4971.500000000064, 1963.800000000008 - 0.4, 25000.0, 38.5, 5109.487109375, 2023.791015625006 - 0.4, 25000.0, 39.0, 5247.490625000001, 2083.209375000007 - 0.4, 25000.0, 39.5, 5385.523828125002, 2141.198046875009 - 0.4, 25000.0, 40.0, 5523.600000000007, 2196.900000000011 - 0.4, 25000.0, 40.5, 5661.835937499998, 2244.5578125000006 - 0.4, 25000.0, 41.0, 5800.100000000001, 2290.175000000003 - 0.4, 25000.0, 41.5, 5938.364062500004, 2334.8546875000043 - 0.4, 25000.0, 42.0, 6076.6000000000095, 2379.700000000007 - 0.4, 25000.0, 42.5, 6214.525781250005, 2428.232031249998 - 0.4, 25000.0, 43.0, 6352.468750000015, 2478.1687499999985 - 0.4, 25000.0, 43.5, 6490.502343750026, 2529.646093749998 - 0.4, 25000.0, 44.0, 6628.700000000036, 2582.7999999999975 - 0.4, 25000.0, 44.5, 6767.748437499984, 2639.07109375 - 0.4, 25000.0, 45.0, 6906.862499999981, 2696.768750000001 - 0.4, 25000.0, 45.5, 7045.870312499977, 2755.5070312500015 - 0.4, 25000.0, 46.0, 7184.599999999974, 2814.9000000000033 - 0.4, 25000.0, 46.5, 7322.016406250004, 2872.4718749999975 - 0.4, 25000.0, 47.0, 7459.1562500000055, 2930.762499999997 - 0.4, 25000.0, 47.5, 7596.192968750005, 2990.221874999997 - 0.4, 25000.0, 48.0, 7733.300000000001, 3051.299999999997 - 0.4, 25000.0, 48.5, 7870.650781249999, 3114.4468749999974 - 0.4, 25000.0, 49.0, 8008.418749999996, 3180.112499999997 - 0.4, 25000.0, 49.5, 8146.777343749993, 3248.7468749999985 - 0.4, 25000.0, 50.0, 8285.899999999989, 3320.7999999999997 - 0.4, 30000.0, 0.0, 189.1695103044812, 189.1695103044812 - 0.4, 30000.0, 22.0, 481.80000000000035, 380.9999999999966 - 0.4, 30000.0, 22.5, 572.5955078125032, 418.98281249999866 - 0.4, 30000.0, 23.0, 662.7234375000071, 449.85000000000105 - 0.4, 30000.0, 23.5, 752.4646484375116, 474.992187500004 - 0.4, 30000.0, 24.0, 842.1000000000181, 495.80000000000746 - 0.4, 30000.0, 24.5, 931.910351562526, 513.6640625000118 - 0.4, 30000.0, 25.0, 1022.1765625000356, 529.9750000000172 - 0.4, 30000.0, 25.5, 1113.179492187547, 546.1234375000233 - 0.4, 30000.0, 26.0, 1205.200000000061, 563.500000000031 - 0.4, 30000.0, 26.5, 1301.6621093749868, 597.6511718749911 - 0.4, 30000.0, 27.0, 1399.8831249999832, 636.62062499999 - 0.4, 30000.0, 27.5, 1499.6050781249771, 679.3722656249888 - 0.4, 30000.0, 28.0, 1600.56999999997, 724.8699999999877 - 0.4, 30000.0, 28.5, 1702.5199218749613, 772.0777343749864 - 0.4, 30000.0, 29.0, 1805.1968749999503, 819.9593749999854 - 0.4, 30000.0, 29.5, 1908.3428906249378, 867.478828124984 - 0.4, 30000.0, 30.0, 2011.699999999923, 913.599999999983 - 0.4, 30000.0, 30.5, 2112.219531250038, 941.7668945312388 - 0.4, 30000.0, 31.0, 2212.700000000042, 967.9414062499881 - 0.4, 30000.0, 31.5, 2313.1492187500453, 992.565527343737 - 0.4, 30000.0, 32.0, 2413.575000000049, 1016.0812499999855 - 0.4, 30000.0, 32.5, 2513.9851562500517, 1038.930566406234 - 0.4, 30000.0, 33.0, 2614.3875000000567, 1061.555468749982 - 0.4, 30000.0, 33.5, 2714.78984375006, 1084.3979492187289 - 0.4, 30000.0, 34.0, 2815.2000000000644, 1107.899999999976 - 0.4, 30000.0, 34.5, 2915.998203124965, 1135.2373046874955 - 0.4, 30000.0, 35.0, 3016.7843749999597, 1163.857812499997 - 0.4, 30000.0, 35.5, 3117.530859374953, 1193.9431640624985 - 0.4, 30000.0, 36.0, 3218.209999999946, 1225.6750000000004 - 0.4, 30000.0, 36.5, 3318.7941406249374, 1259.2349609375028 - 0.4, 30000.0, 37.0, 3419.2556249999266, 1294.8046875000048 - 0.4, 30000.0, 37.5, 3519.5667968749153, 1332.5658203125076 - 0.4, 30000.0, 38.0, 3619.699999999901, 1372.7000000000105 - 0.4, 30000.0, 38.5, 3718.880859374411, 1422.8771484373938 - 0.4, 30000.0, 39.0, 3818.215624999303, 1471.9078124998732 - 0.4, 30000.0, 39.5, 3917.842578124182, 1518.3095703123506 - 0.4, 30000.0, 40.0, 4017.899999999045, 1560.599999999826 - 0.4, 30000.0, 40.5, 4119.446093749988, 1589.8953124999618 - 0.4, 30000.0, 41.0, 4221.331249999974, 1615.0749999999477 - 0.4, 30000.0, 41.5, 4323.325781249953, 1637.6171874999309 - 0.4, 30000.0, 42.0, 4425.199999999926, 1658.9999999999102 - 0.4, 30000.0, 42.5, 4525.985937499926, 1673.7875000000126 - 0.4, 30000.0, 43.0, 4626.487499999905, 1693.1375000000169 - 0.4, 30000.0, 43.5, 4726.770312499885, 1721.2937500000216 - 0.4, 30000.0, 44.0, 4826.899999999865, 1762.5000000000268 - 0.4, 30000.0, 44.5, 4927.078906249888, 1851.496093749968 - 0.4, 30000.0, 45.0, 5027.181249999872, 1949.831249999966 - 0.4, 30000.0, 45.5, 5127.217968749851, 2049.550781249966 - 0.4, 30000.0, 46.0, 5227.199999999834, 2142.6999999999684 - 0.4, 30000.0, 46.5, 5326.97421874986, 2198.476562499982 - 0.4, 30000.0, 47.0, 5426.781249999809, 2240.9124999999735 - 0.4, 30000.0, 47.5, 5526.697656249748, 2271.1921874999634 - 0.4, 30000.0, 48.0, 5626.7999999996755, 2290.499999999951 - 0.4, 30000.0, 48.5, 5727.164843749594, 2300.020312499936 - 0.4, 30000.0, 49.0, 5827.8687499995, 2300.9374999999195 - 0.4, 30000.0, 49.5, 5928.988281249398, 2294.435937499899 - 0.4, 30000.0, 50.0, 6030.599999999283, 2281.699999999877 - 0.4, 35000.0, 0.0, 153.24880925751793, 153.24880925751793 - 0.4, 35000.0, 22.0, 438.9999999999997, 318.30000000000086 - 0.4, 35000.0, 22.5, 525.304687500002, 328.00000000000387 - 0.4, 35000.0, 23.0, 609.9875000000029, 348.7875000000059 - 0.4, 35000.0, 23.5, 693.4265625000024, 378.70625000000723 - 0.4, 35000.0, 24.0, 776.000000000001, 415.80000000000797 - 0.4, 35000.0, 24.5, 858.0859374999985, 458.11250000000814 - 0.4, 35000.0, 25.0, 940.0624999999958, 503.6875000000079 - 0.4, 35000.0, 25.5, 1022.3078124999925, 550.5687500000075 - 0.4, 35000.0, 26.0, 1105.1999999999887, 596.8000000000065 - 0.4, 35000.0, 26.5, 1192.5529296874695, 620.7525390625075 - 0.4, 35000.0, 27.0, 1281.5053124999654, 639.0184375000074 - 0.4, 35000.0, 27.5, 1371.846289062461, 653.0138671875076 - 0.4, 35000.0, 28.0, 1463.3649999999577, 664.1550000000083 - 0.4, 35000.0, 28.5, 1555.8505859374552, 673.8580078125093 - 0.4, 35000.0, 29.0, 1649.0921874999517, 683.5390625000107 - 0.4, 35000.0, 29.5, 1742.8789453124498, 694.6143359375128 - 0.4, 35000.0, 30.0, 1836.9999999999472, 708.5000000000158 - 0.4, 35000.0, 30.5, 1929.3237304687975, 753.7559570312003 - 0.4, 35000.0, 31.0, 2021.7429687500553, 802.0695312499449 - 0.4, 35000.0, 31.5, 2114.2297851563135, 852.2717773436901 - 0.4, 35000.0, 32.0, 2206.756250000073, 903.1937499999353 - 0.4, 35000.0, 32.5, 2299.2944335938323, 953.6665039061813 - 0.4, 35000.0, 33.0, 2391.8164062500914, 1002.521093749928 - 0.4, 35000.0, 33.5, 2484.294238281351, 1048.5885742186758 - 0.4, 35000.0, 34.0, 2576.7000000001117, 1090.6999999999236 - 0.4, 35000.0, 34.5, 2667.659218750199, 1098.546875000014 - 0.4, 35000.0, 35.0, 2758.618750000219, 1102.8750000000182 - 0.4, 35000.0, 35.5, 2849.678906250237, 1105.2906250000228 - 0.4, 35000.0, 36.0, 2940.9400000002556, 1107.4000000000276 - 0.4, 35000.0, 36.5, 3032.5023437502714, 1110.8093750000319 - 0.4, 35000.0, 37.0, 3124.4662500002873, 1117.1250000000366 - 0.4, 35000.0, 37.5, 3216.932031250301, 1127.9531250000416 - 0.4, 35000.0, 38.0, 3310.0000000003124, 1144.9000000000453 - 0.4, 35000.0, 38.5, 3405.6984375000093, 1154.4792968748875 - 0.4, 35000.0, 39.0, 3501.2000000000176, 1181.2156249998511 - 0.4, 35000.0, 39.5, 3596.176562500032, 1230.0691406248102 - 0.4, 35000.0, 40.0, 3690.3000000000497, 1305.999999999763 - 0.4, 35000.0, 40.5, 3781.27343750017, 1464.9429687499714 - 0.4, 35000.0, 41.0, 3871.5250000002334, 1640.4937499999553 - 0.4, 35000.0, 41.5, 3961.5140625003055, 1817.2226562499334 - 0.4, 35000.0, 42.0, 4051.700000000386, 1979.699999999908 - 0.4, 35000.0, 42.5, 4144.448437499971, 2083.101562499905 - 0.4, 35000.0, 43.0, 4237.54999999991, 2153.1499999998664 - 0.4, 35000.0, 43.5, 4330.701562499827, 2186.1734374998196 - 0.4, 35000.0, 44.0, 4423.599999999718, 2178.4999999997644 - 0.4, 35000.0, 44.5, 4514.473437500021, 2061.8406250000708 - 0.4, 35000.0, 45.0, 4605.075000000049, 1922.9875000000989 - 0.4, 35000.0, 45.5, 4695.689062500091, 1784.1156250001343 - 0.4, 35000.0, 46.0, 4786.600000000141, 1667.4000000001765 - 0.4, 35000.0, 46.5, 4879.342187499992, 1674.3398437499445 - 0.4, 35000.0, 47.0, 4972.450000000009, 1716.0562499999287 - 0.4, 35000.0, 47.5, 5065.707812500039, 1782.994531249907 - 0.4, 35000.0, 48.0, 5158.90000000008, 1865.5999999998774 - 0.4, 35000.0, 48.5, 5251.810937500132, 1954.3179687498396 - 0.4, 35000.0, 49.0, 5344.225000000198, 2039.5937499997904 - 0.4, 35000.0, 49.5, 5435.92656250028, 2111.8726562497295 - 0.4, 35000.0, 50.0, 5526.700000000376, 2161.5999999996557 - 0.4, 39000.0, 0.0, 127.1062023908442, 127.1062023908442 - 0.4, 39000.0, 22.0, 341.90000000000106, 244.60000000000275 - 0.4, 39000.0, 22.5, 409.98925781249767, 244.8197265625011 - 0.4, 39000.0, 23.0, 476.3734374999943, 260.2171874999996 - 0.4, 39000.0, 23.5, 541.4458984374912, 288.156054687498 - 0.4, 39000.0, 24.0, 605.5999999999883, 325.9999999999963 - 0.4, 39000.0, 24.5, 669.2291015624853, 371.11269531249434 - 0.4, 39000.0, 25.0, 732.7265624999817, 420.8578124999923 - 0.4, 39000.0, 25.5, 796.4857421874781, 472.59902343748956 - 0.4, 39000.0, 26.0, 860.899999999974, 523.6999999999866 - 0.4, 39000.0, 26.5, 930.2455078124933, 548.7169921874976 - 0.4, 39000.0, 27.0, 1001.2546874999913, 566.5178124999977 - 0.4, 39000.0, 27.5, 1073.6552734374893, 578.3759765624983 - 0.4, 39000.0, 28.0, 1147.1749999999884, 585.5649999999993 - 0.4, 39000.0, 28.5, 1221.541601562486, 589.3583984375011 - 0.4, 39000.0, 29.0, 1296.4828124999854, 591.0296875000035 - 0.4, 39000.0, 29.5, 1371.7263671874841, 591.8523828125063 - 0.4, 39000.0, 30.0, 1446.9999999999839, 593.1000000000097 - 0.4, 39000.0, 30.5, 1518.608691406265, 611.7558593749753 - 0.4, 39000.0, 31.0, 1590.0289062500203, 631.8874999999704 - 0.4, 39000.0, 31.5, 1661.3143554687763, 653.272265624965 - 0.4, 39000.0, 32.0, 1732.518750000033, 675.6874999999586 - 0.4, 39000.0, 32.5, 1803.6958007812898, 698.9105468749522 - 0.4, 39000.0, 33.0, 1874.8992187500478, 722.7187499999449 - 0.4, 39000.0, 33.5, 1946.1827148438063, 746.8894531249367 - 0.4, 39000.0, 34.0, 2017.6000000000654, 771.1999999999282 - 0.4, 39000.0, 34.5, 2090.7203124999833, 800.9656640624682 - 0.4, 39000.0, 35.0, 2163.937499999977, 829.8984374999606 - 0.4, 39000.0, 35.5, 2237.160937499968, 857.2482421874519 - 0.4, 39000.0, 36.0, 2310.2999999999543, 882.2649999999419 - 0.4, 39000.0, 36.5, 2383.264062499939, 904.1986328124308 - 0.4, 39000.0, 37.0, 2455.9624999999196, 922.2990624999183 - 0.4, 39000.0, 37.5, 2528.304687499897, 935.8162109374051 - 0.4, 39000.0, 38.0, 2600.1999999998693, 943.9999999998902 - 0.4, 39000.0, 38.5, 2670.1128906250706, 920.8173828125321 - 0.4, 39000.0, 39.0, 2740.146875000083, 903.9109375000373 - 0.4, 39000.0, 39.5, 2810.5324218751, 898.1490234375456 - 0.4, 39000.0, 40.0, 2881.5000000001182, 908.4000000000565 - 0.4, 39000.0, 40.5, 2954.465624999994, 955.0507812499922 - 0.4, 39000.0, 41.0, 3027.9999999999714, 1021.2437499999945 - 0.4, 39000.0, 41.5, 3101.8593749999454, 1105.63984375 - 0.4, 39000.0, 42.0, 3175.799999999919, 1206.900000000008 - 0.4, 39000.0, 42.5, 3248.1289062500473, 1344.3531250000337 - 0.4, 39000.0, 43.0, 3320.6312500000927, 1487.7250000000395 - 0.4, 39000.0, 43.5, 3393.6429687501404, 1627.4093750000443 - 0.4, 39000.0, 44.0, 3467.5000000001855, 1753.8000000000468 - 0.4, 39000.0, 44.5, 3546.0890625000256, 1845.0367187499453 - 0.4, 39000.0, 45.0, 3624.775000000061, 1908.6687499999366 - 0.4, 39000.0, 45.5, 3702.4734375001162, 1939.9914062499292 - 0.4, 39000.0, 46.0, 3778.1000000001945, 1934.299999999924 - 0.4, 39000.0, 46.5, 3844.3007812500773, 1833.776562499962 - 0.4, 39000.0, 47.0, 3908.7687500000793, 1708.0749999999289 - 0.4, 39000.0, 47.5, 3972.9273437500747, 1573.7359374998873 - 0.4, 39000.0, 48.0, 4038.2000000000644, 1447.299999999837 - 0.4, 39000.0, 48.5, 4106.010156250043, 1345.307812499777 - 0.4, 39000.0, 49.0, 4177.781250000011, 1284.2999999997069 - 0.4, 39000.0, 49.5, 4254.936718749965, 1280.8171874996265 - 0.4, 39000.0, 50.0, 4338.899999999905, 1351.3999999995347 - 0.4, 43000.0, 0.0, 104.87514298706566, 104.87514298706566 - 0.4, 43000.0, 22.0, 114.89999999999743, 397.4999999999983 - 0.4, 43000.0, 22.5, 145.66269531248807, 306.71796874999313 - 0.4, 43000.0, 23.0, 175.28593749997728, 235.20624999999202 - 0.4, 43000.0, 23.5, 203.9162109374646, 180.51640624999413 - 0.4, 43000.0, 24.0, 231.6999999999494, 140.19999999999848 - 0.4, 43000.0, 24.5, 258.78378906243125, 111.80859375000426 - 0.4, 43000.0, 25.0, 285.3140624999095, 92.89375000001064 - 0.4, 43000.0, 25.5, 311.43730468738346, 81.00703125001678 - 0.4, 43000.0, 26.0, 337.29999999985296, 73.70000000002153 - 0.4, 43000.0, 26.5, 363.97421874997826, 43.67968749996831 - 0.4, 43000.0, 27.0, 390.733749999976, 11.92249999996201 - 0.4, 43000.0, 27.5, 417.56640624997493, -19.76093750004464 - 0.4, 43000.0, 28.0, 444.4599999999753, -49.56000000005126 - 0.4, 43000.0, 28.5, 471.4023437499776, -75.66406250005761 - 0.4, 43000.0, 29.0, 498.38124999998143, -96.26250000006311 - 0.4, 43000.0, 29.5, 525.3845312499878, -109.54468750006771 - 0.4, 43000.0, 30.0, 552.3999999999969, -113.70000000007082 - 0.4, 43000.0, 30.5, 578.9593750000661, -84.350195312572 - 0.4, 43000.0, 31.0, 605.5500000000729, -44.401562500084005 - 0.4, 43000.0, 31.5, 632.2031250000801, 5.807226562403889 - 0.4, 43000.0, 32.0, 658.9500000000888, 65.9374999998916 - 0.4, 43000.0, 32.5, 685.821875000099, 135.65058593737905 - 0.4, 43000.0, 33.0, 712.8500000001103, 214.60781249986638 - 0.4, 43000.0, 33.5, 740.0656250001234, 302.47050781235356 - 0.4, 43000.0, 34.0, 767.5000000001386, 398.8999999998406 - 0.4, 43000.0, 34.5, 797.7601562498044, 639.6827343749096 - 0.4, 43000.0, 35.0, 828.0562499997612, 875.3906249998927 - 0.4, 43000.0, 35.5, 858.1742187497096, 1092.7207031248743 - 0.4, 43000.0, 36.0, 887.8999999996481, 1278.3699999998544 - 0.4, 43000.0, 36.5, 917.0195312495766, 1419.0355468748335 - 0.4, 43000.0, 37.0, 945.3187499994935, 1501.4143749998107 - 0.4, 43000.0, 37.5, 972.5835937493976, 1512.2035156247903 - 0.4, 43000.0, 38.0, 998.5999999992879, 1438.0999999997648 - 0.4, 43000.0, 38.5, 1017.922656250199, 1096.9285156251663 - 0.4, 43000.0, 39.0, 1038.2812500002522, 731.8218750002263 - 0.4, 43000.0, 39.5, 1060.6242187503128, 367.00429687528776 - 0.4, 43000.0, 40.0, 1085.9000000003803, 26.700000000360887 - 0.4, 43000.0, 40.5, 1122.498437500133, -220.25937500014226 - 0.4, 43000.0, 41.0, 1160.9500000001565, -412.10000000016964 - 0.4, 43000.0, 41.5, 1199.2265625001842, -542.4406250002027 - 0.4, 43000.0, 42.0, 1235.3000000002166, -604.9000000002408 - 0.4, 43000.0, 42.5, 1257.364843749857, -524.4406250002044 - 0.4, 43000.0, 43.0, 1277.0812499998299, -390.80000000030424 - 0.4, 43000.0, 43.5, 1296.3320312497867, -225.0593750004183 - 0.4, 43000.0, 44.0, 1316.9999999997206, -48.30000000054429 - 0.4, 43000.0, 44.5, 1349.8429687498135, 80.31093749999707 - 0.4, 43000.0, 45.0, 1384.318749999733, 193.01250000000783 - 0.4, 43000.0, 45.5, 1418.760156249656, 283.9578125000188 - 0.4, 43000.0, 46.0, 1451.499999999592, 347.300000000029 - 0.4, 43000.0, 46.5, 1473.597656249544, 331.35624999975767 - 0.4, 43000.0, 47.0, 1493.5687499993867, 294.4499999997149 - 0.4, 43000.0, 47.5, 1512.655468749194, 249.06874999966925 - 0.4, 43000.0, 48.0, 1532.099999998959, 207.6999999996197 - 0.4, 43000.0, 48.5, 1553.1445312486733, 182.8312499995659 - 0.4, 43000.0, 49.0, 1577.0312499983313, 186.94999999950824 - 0.4, 43000.0, 49.5, 1605.002343747925, 232.54374999944548 - 0.4, 43000.0, 50.0, 1638.2999999974475, 332.0999999993787 - 0.4, 48000.0, 0.0, 82.4717256221271, 82.4717256221271 - 0.4, 48000.0, 22.0, 76.49999999999527, 322.1999999999866 - 0.4, 48000.0, 22.5, 108.20351562499948, 248.10507812498616 - 0.4, 48000.0, 23.0, 136.24687500000633, 190.72187499998566 - 0.4, 48000.0, 23.5, 161.16679687501585, 147.82773437498489 - 0.4, 48000.0, 24.0, 183.50000000002825, 117.1999999999838 - 0.4, 48000.0, 24.5, 203.78320312504374, 96.61601562498245 - 0.4, 48000.0, 25.0, 222.5531250000623, 83.85312499998076 - 0.4, 48000.0, 25.5, 240.3464843750842, 76.68867187497867 - 0.4, 48000.0, 26.0, 257.7000000001094, 72.89999999997607 - 0.4, 48000.0, 26.5, 279.40234374997925, 47.603320312481316 - 0.4, 48000.0, 27.0, 301.981249999978, 19.942187499976825 - 0.4, 48000.0, 27.5, 325.24453124997694, -8.42128906252806 - 0.4, 48000.0, 28.0, 348.999999999976, -35.8250000000333 - 0.4, 48000.0, 28.5, 373.05546874997515, -60.606835937538605 - 0.4, 48000.0, 29.0, 397.21874999997425, -81.10468750004404 - 0.4, 48000.0, 29.5, 421.29765624997293, -95.65644531254941 - 0.4, 48000.0, 30.0, 445.0999999999717, -102.6000000000547 - 0.4, 48000.0, 30.5, 465.35742187493287, -78.66826171881404 - 0.4, 48000.0, 31.0, 485.24687499991654, -45.86171875007747 - 0.4, 48000.0, 31.5, 504.8691406248983, -4.575878906342584 - 0.4, 48000.0, 32.0, 524.3249999998783, 44.79374999989044 - 0.4, 48000.0, 32.5, 543.7152343748561, 101.85166015612162 - 0.4, 48000.0, 33.0, 563.1406249998322, 166.20234374985068 - 0.4, 48000.0, 33.5, 582.7019531248062, 237.45029296857763 - 0.4, 48000.0, 34.0, 602.4999999997783, 315.1999999998028 - 0.4, 48000.0, 34.5, 626.1743749999231, 502.86609374991224 - 0.4, 48000.0, 35.0, 649.9499999999177, 686.3562499998962 - 0.4, 48000.0, 35.5, 673.590624999912, 855.3882812498773 - 0.4, 48000.0, 36.0, 696.8599999999049, 999.679999999855 - 0.4, 48000.0, 36.5, 719.5218749998962, 1108.9492187498286 - 0.4, 48000.0, 37.0, 741.3399999998854, 1172.9137499998005 - 0.4, 48000.0, 37.5, 762.0781249998723, 1181.291406249764 - 0.4, 48000.0, 38.0, 781.4999999998557, 1123.799999999725 - 0.4, 48000.0, 38.5, 792.9906250003297, 859.9624999998558 - 0.4, 48000.0, 39.0, 806.0000000003955, 577.1999999998388 - 0.4, 48000.0, 39.5, 821.7093750004722, 294.1624999998219 - 0.4, 48000.0, 40.0, 841.3000000005607, 29.499999999809916 - 0.4, 48000.0, 40.5, 875.7499999999212, -164.83281250009392 - 0.4, 48000.0, 41.0, 912.5249999999033, -316.8125000001144 - 0.4, 48000.0, 41.5, 948.8874999998852, -421.1109375001354 - 0.4, 48000.0, 42.0, 982.0999999998669, -472.40000000015624 - 0.4, 48000.0, 42.5, 996.878124999937, -411.1289062498846 - 0.4, 48000.0, 43.0, 1008.0499999999156, -307.88124999985763 - 0.4, 48000.0, 43.5, 1017.8968749998915, -179.0179687498342 - 0.4, 48000.0, 44.0, 1028.6999999998643, -40.899999999817055 - 0.4, 48000.0, 44.5, 1051.1625000000768, 61.588281249904185 - 0.4, 48000.0, 45.0, 1075.7750000001117, 152.01874999987956 - 0.4, 48000.0, 45.5, 1101.4500000001487, 225.43984374985422 - 0.4, 48000.0, 46.0, 1127.1000000001864, 276.8999999998284 - 0.4, 48000.0, 46.5, 1148.2976562500041, 263.55312500011837 - 0.4, 48000.0, 47.0, 1168.6312499999706, 233.50000000015274 - 0.4, 48000.0, 47.5, 1188.3492187499426, 196.94687500019506 - 0.4, 48000.0, 48.0, 1207.699999999925, 164.10000000024633 - 0.4, 48000.0, 48.5, 1226.9320312499244, 145.16562500030852 - 0.4, 48000.0, 49.0, 1246.293749999945, 150.3500000003828 - 0.4, 48000.0, 49.5, 1266.0335937499929, 189.85937500047066 - 0.4, 48000.0, 50.0, 1286.400000000073, 273.9000000005731 - 0.45, 0.0, 0.0, 581.6661190568789, 581.6661190568789 - 0.45, 0.0, 22.0, 1319.0999999999983, 1155.0999999999963 - 0.45, 0.0, 22.5, 1569.2966796874682, 1262.6556640624908 - 0.45, 0.0, 23.0, 1816.714062499931, 1356.492187499989 - 0.45, 0.0, 23.5, 2062.249414062386, 1439.4826171874909 - 0.45, 0.0, 24.0, 2306.79999999983, 1514.499999999995 - 0.45, 0.0, 24.5, 2551.263085937262, 1584.4173828125008 - 0.45, 0.0, 25.0, 2796.5359374996815, 1652.1078125000083 - 0.45, 0.0, 25.5, 3043.515820312084, 1720.4443359375164 - 0.45, 0.0, 26.0, 3293.0999999994715, 1792.3000000000259 - 0.45, 0.0, 26.5, 3555.5851562500443, 1898.2990234375068 - 0.45, 0.0, 27.0, 3823.006250000061, 2015.149062500017 - 0.45, 0.0, 27.5, 4094.64921875008, 2140.965820312532 - 0.45, 0.0, 28.0, 4369.800000000107, 2273.8650000000503 - 0.45, 0.0, 28.5, 4647.744531250136, 2411.962304687573 - 0.45, 0.0, 29.0, 4927.768750000173, 2553.3734375001004 - 0.45, 0.0, 29.5, 5209.158593750219, 2696.214101562632 - 0.45, 0.0, 30.0, 5491.200000000271, 2838.6000000001695 - 0.45, 0.0, 30.5, 5765.547949218737, 2953.749121093587 - 0.45, 0.0, 31.0, 6039.846093749986, 3067.046093749807 - 0.45, 0.0, 31.5, 6314.107128906232, 3178.9778320310256 - 0.45, 0.0, 32.0, 6588.343749999979, 3290.0312499997426 - 0.45, 0.0, 32.5, 6862.568652343722, 3400.6932617184593 - 0.45, 0.0, 33.0, 7136.794531249964, 3511.4507812496745 - 0.45, 0.0, 33.5, 7411.034082031205, 3622.790722655889 - 0.45, 0.0, 34.0, 7685.299999999941, 3735.199999999605 - 0.45, 0.0, 34.5, 7959.819492186707, 3878.4642187497175 - 0.45, 0.0, 35.0, 8234.370312498977, 4020.9812499996838 - 0.45, 0.0, 35.5, 8508.944726561218, 4160.44765624965 - 0.45, 0.0, 36.0, 8783.534999998425, 4294.559999999613 - 0.45, 0.0, 36.5, 9058.133398435595, 4421.014843749578 - 0.45, 0.0, 37.0, 9332.732187497737, 4537.508749999541 - 0.45, 0.0, 37.5, 9607.323632809841, 4641.738281249502 - 0.45, 0.0, 38.0, 9881.899999996913, 4731.399999999463 - 0.45, 0.0, 38.5, 10156.43457031394, 4784.148242187735 - 0.45, 0.0, 39.0, 10430.948437501898, 4828.114062500302 - 0.45, 0.0, 39.5, 10705.438085939939, 4865.447851562889 - 0.45, 0.0, 40.0, 10979.90000000307, 4898.300000000488 - 0.45, 0.0, 40.5, 11254.41562500004, 4925.661718749883 - 0.45, 0.0, 41.0, 11528.862500000027, 4954.106249999839 - 0.45, 0.0, 41.5, 11803.203124999973, 4987.047656249782 - 0.45, 0.0, 42.0, 12077.399999999885, 5027.899999999713 - 0.45, 0.0, 42.5, 12350.817968749961, 5084.932812499611 - 0.45, 0.0, 43.0, 12624.256249999931, 5154.762499999498 - 0.45, 0.0, 43.5, 12897.916406249906, 5238.860937499373 - 0.45, 0.0, 44.0, 13171.999999999894, 5338.699999999231 - 0.45, 0.0, 44.5, 13448.095312499261, 5468.400000000102 - 0.45, 0.0, 45.0, 13724.462499998906, 5611.725000000137 - 0.45, 0.0, 45.5, 14000.748437498456, 5765.087500000189 - 0.45, 0.0, 46.0, 14276.599999997883, 5924.90000000027 - 0.45, 0.0, 46.5, 14550.015624999023, 6081.352343749461 - 0.45, 0.0, 47.0, 14822.949999998746, 6239.568749999251 - 0.45, 0.0, 47.5, 15095.709374998447, 6398.450781249013 - 0.45, 0.0, 48.0, 15368.599999998143, 6556.899999998746 - 0.45, 0.0, 48.5, 15641.92812499783, 6713.817968748453 - 0.45, 0.0, 49.0, 15915.999999997519, 6868.106249998136 - 0.45, 0.0, 49.5, 16191.121874997212, 7018.666406247793 - 0.45, 0.0, 50.0, 16467.599999996914, 7164.399999997429 - 0.45, 2000.0, 0.0, 544.5963925872576, 544.5963925872576 - 0.45, 2000.0, 22.0, 405.90000000000373, 783.3999999999988 - 0.45, 2000.0, 22.5, 483.3023437499924, 813.9291015624991 - 0.45, 2000.0, 23.0, 559.8562499999774, 845.6796874999992 - 0.45, 2000.0, 23.5, 635.8320312499585, 878.3654296874988 - 0.45, 2000.0, 24.0, 711.4999999999347, 911.6999999999985 - 0.45, 2000.0, 24.5, 787.1304687499049, 945.3970703124984 - 0.45, 2000.0, 25.0, 862.9937499998707, 979.1703124999985 - 0.45, 2000.0, 25.5, 939.3601562498292, 1012.7333984374989 - 0.45, 2000.0, 26.0, 1016.4999999997815, 1045.8000000000004 - 0.45, 2000.0, 26.5, 1097.494531250026, 1075.1894531250073 - 0.45, 2000.0, 27.0, 1179.963750000031, 1103.344375000014 - 0.45, 2000.0, 27.5, 1263.6960937500382, 1130.4746093750218 - 0.45, 2000.0, 28.0, 1348.480000000046, 1156.790000000031 - 0.45, 2000.0, 28.5, 1434.1039062500558, 1182.5003906250424 - 0.45, 2000.0, 29.0, 1520.3562500000676, 1207.8156250000557 - 0.45, 2000.0, 29.5, 1607.025468750079, 1232.9455468750702 - 0.45, 2000.0, 30.0, 1693.9000000000951, 1258.1000000000877 - 0.45, 2000.0, 30.5, 1778.542773437499, 1286.6622070312349 - 0.45, 2000.0, 31.0, 1863.1796875000032, 1315.3664062499874 - 0.45, 2000.0, 31.5, 1947.8111328125087, 1344.12021484374 - 0.45, 2000.0, 32.0, 2032.4375000000157, 1372.831249999993 - 0.45, 2000.0, 32.5, 2117.0591796875274, 1401.4071289062472 - 0.45, 2000.0, 33.0, 2201.676562500037, 1429.7554687499999 - 0.45, 2000.0, 33.5, 2286.2900390625537, 1457.7838867187565 - 0.45, 2000.0, 34.0, 2370.9000000000683, 1485.4000000000121 - 0.45, 2000.0, 34.5, 2455.4338281252476, 1505.4833984374372 - 0.45, 2000.0, 35.0, 2539.9718750002644, 1525.6390624999153 - 0.45, 2000.0, 35.5, 2624.5214843752774, 1546.44394531239 - 0.45, 2000.0, 36.0, 2709.090000000287, 1568.4749999998621 - 0.45, 2000.0, 36.5, 2793.6847656252953, 1592.3091796873323 - 0.45, 2000.0, 37.0, 2878.3131250002994, 1618.5234374997995 - 0.45, 2000.0, 37.5, 2962.9824218752988, 1647.6947265622625 - 0.45, 2000.0, 38.0, 3047.700000000296, 1680.399999999724 - 0.45, 2000.0, 38.5, 3132.6082031259975, 1722.257617187569 - 0.45, 2000.0, 39.0, 3217.5093750012475, 1766.1890625000624 - 0.45, 2000.0, 39.5, 3302.3808593765307, 1811.6509765625506 - 0.45, 2000.0, 40.0, 3387.200000001854, 1858.100000000039 - 0.45, 2000.0, 40.5, 3471.8328125002463, 1906.0914062500474 - 0.45, 2000.0, 41.0, 3556.412500000339, 1953.5437500001024 - 0.45, 2000.0, 41.5, 3640.960937500444, 1999.4742187501781 - 0.45, 2000.0, 42.0, 3725.5000000005634, 2042.900000000278 - 0.45, 2000.0, 42.5, 3810.0320312500044, 2079.666406250061 - 0.45, 2000.0, 43.0, 3894.606250000112, 2113.2312500000826 - 0.45, 2000.0, 43.5, 3979.252343750266, 2143.8804687501092 - 0.45, 2000.0, 44.0, 4064.000000000473, 2171.900000000141 - 0.45, 2000.0, 44.5, 4149.1640625007585, 2197.403906250079 - 0.45, 2000.0, 45.0, 4234.375000000971, 2220.9187500001003 - 0.45, 2000.0, 45.5, 4319.548437501195, 2242.7992187501177 - 0.45, 2000.0, 46.0, 4404.600000001426, 2263.4000000001333 - 0.45, 2000.0, 46.5, 4489.042968749247, 2283.689062499966 - 0.45, 2000.0, 47.0, 4573.356249999067, 2303.1624999999844 - 0.45, 2000.0, 47.5, 4657.616406248896, 2321.929687500009 - 0.45, 2000.0, 48.0, 4741.899999998745, 2340.1000000000367 - 0.45, 2000.0, 48.5, 4826.283593748622, 2357.7828125000688 - 0.45, 2000.0, 49.0, 4910.843749998533, 2375.0875000001047 - 0.45, 2000.0, 49.5, 4995.65703124849, 2392.123437500143 - 0.45, 2000.0, 50.0, 5080.7999999985, 2409.0000000001833 - 0.45, 5000.0, 0.0, 492.5143052524732, 492.5143052524732 - 0.45, 5000.0, 22.0, 992.6999999999987, 926.2000000000013 - 0.45, 5000.0, 22.5, 1181.1275390624967, 995.7749999999979 - 0.45, 5000.0, 23.0, 1367.6046874999936, 1063.9249999999956 - 0.45, 5000.0, 23.5, 1552.779492187489, 1131.0374999999951 - 0.45, 5000.0, 24.0, 1737.2999999999836, 1197.4999999999955 - 0.45, 5000.0, 24.5, 1921.8142578124764, 1263.699999999996 - 0.45, 5000.0, 25.0, 2106.9703124999673, 1330.024999999998 - 0.45, 5000.0, 25.5, 2293.416210937458, 1396.8625000000009 - 0.45, 5000.0, 26.0, 2481.7999999999456, 1464.6000000000038 - 0.45, 5000.0, 26.5, 2679.568749999953, 1537.4175781249849 - 0.45, 5000.0, 27.0, 2880.95999999994, 1612.1268749999826 - 0.45, 5000.0, 27.5, 3085.456249999927, 1688.4652343749797 - 0.45, 5000.0, 28.0, 3292.5399999999136, 1766.1699999999764 - 0.45, 5000.0, 28.5, 3501.693749999898, 1844.978515624974 - 0.45, 5000.0, 29.0, 3712.3999999998823, 1924.6281249999722 - 0.45, 5000.0, 29.5, 3924.1412499998637, 2004.8561718749693 - 0.45, 5000.0, 30.0, 4136.399999999843, 2085.399999999966 - 0.45, 5000.0, 30.5, 4343.2250000001195, 2162.9109374999985 - 0.45, 5000.0, 31.0, 4550.050000000137, 2240.506249999998 - 0.45, 5000.0, 31.5, 4756.875000000151, 2318.217187499999 - 0.45, 5000.0, 32.0, 4963.700000000165, 2396.0749999999985 - 0.45, 5000.0, 32.5, 5170.525000000178, 2474.110937499999 - 0.45, 5000.0, 33.0, 5377.350000000193, 2552.3562500000007 - 0.45, 5000.0, 33.5, 5584.175000000204, 2630.8421875000004 - 0.45, 5000.0, 34.0, 5791.0000000002165, 2709.600000000002 - 0.45, 5000.0, 34.5, 5997.831562500106, 2788.980859374915 - 0.45, 5000.0, 35.0, 6204.662500000129, 2868.6656249999046 - 0.45, 5000.0, 35.5, 6411.4921875001555, 2948.655078124893 - 0.45, 5000.0, 36.0, 6618.320000000188, 3028.949999999882 - 0.45, 5000.0, 36.5, 6825.145312500222, 3109.5511718748717 - 0.45, 5000.0, 37.0, 7031.967500000263, 3190.4593749998617 - 0.45, 5000.0, 37.5, 7238.7859375003045, 3271.6753906248523 - 0.45, 5000.0, 38.0, 7445.600000000354, 3353.1999999998416 - 0.45, 5000.0, 38.5, 7652.397460936895, 3435.271289062436 - 0.45, 5000.0, 39.0, 7859.1953124993, 3517.5296874999094 - 0.45, 5000.0, 39.5, 8065.995507811695, 3599.923242187375 - 0.45, 5000.0, 40.0, 8272.79999999908, 3682.3999999998327 - 0.45, 5000.0, 40.5, 8479.619531250148, 3764.629687499893 - 0.45, 5000.0, 41.0, 8686.443750000151, 3846.9499999998666 - 0.45, 5000.0, 41.5, 8893.271093750142, 3929.42031249984 - 0.45, 5000.0, 42.0, 9100.100000000111, 4012.0999999998144 - 0.45, 5000.0, 42.5, 9306.764843749965, 4095.0328125000237 - 0.45, 5000.0, 43.0, 9513.493750000012, 4178.300000000021 - 0.45, 5000.0, 43.5, 9720.350781250074, 4261.967187500013 - 0.45, 5000.0, 44.0, 9927.400000000149, 4346.099999999999 - 0.45, 5000.0, 44.5, 10135.350000000099, 4431.205468750065 - 0.45, 5000.0, 45.0, 10343.362500000147, 4516.731250000081 - 0.45, 5000.0, 45.5, 10551.243750000202, 4602.566406250094 - 0.45, 5000.0, 46.0, 10758.800000000267, 4688.600000000103 - 0.45, 5000.0, 46.5, 10964.864843749774, 4774.396875000049 - 0.45, 5000.0, 47.0, 11170.606249999682, 4860.300000000085 - 0.45, 5000.0, 47.5, 11376.219531249573, 4946.328125000126 - 0.45, 5000.0, 48.0, 11581.899999999443, 5032.50000000018 - 0.45, 5000.0, 48.5, 11787.842968749288, 5118.834375000242 - 0.45, 5000.0, 49.0, 11994.243749999103, 5205.350000000314 - 0.45, 5000.0, 49.5, 12201.297656248898, 5292.065625000395 - 0.45, 5000.0, 50.0, 12409.199999998647, 5379.000000000485 - 0.45, 10000.0, 0.0, 414.5212150227323, 414.5212150227323 - 0.45, 10000.0, 22.0, 909.3999999999995, 807.8999999999987 - 0.45, 10000.0, 22.5, 1081.9564453124992, 870.6277343749995 - 0.45, 10000.0, 23.0, 1252.7484374999979, 932.1281249999996 - 0.45, 10000.0, 23.5, 1422.3662109374973, 992.7394531249992 - 0.45, 10000.0, 24.0, 1591.3999999999944, 1052.7999999999984 - 0.45, 10000.0, 24.5, 1760.4400390624928, 1112.6480468749974 - 0.45, 10000.0, 25.0, 1930.07656249999, 1172.6218749999955 - 0.45, 10000.0, 25.5, 2100.899804687487, 1233.0597656249938 - 0.45, 10000.0, 26.0, 2273.499999999983, 1294.2999999999915 - 0.45, 10000.0, 26.5, 2454.668945312482, 1359.9156249999949 - 0.45, 10000.0, 27.0, 2639.149687499978, 1427.1949999999938 - 0.45, 10000.0, 27.5, 2826.4693359374737, 1495.9218749999927 - 0.45, 10000.0, 28.0, 3016.1549999999697, 1565.8799999999926 - 0.45, 10000.0, 28.5, 3207.7337890624644, 1636.8531249999917 - 0.45, 10000.0, 29.0, 3400.7328124999594, 1708.6249999999914 - 0.45, 10000.0, 29.5, 3594.6791796874545, 1780.9793749999908 - 0.45, 10000.0, 30.0, 3789.0999999999494, 1853.6999999999905 - 0.45, 10000.0, 30.5, 3978.5590820312714, 1924.1236328125033 - 0.45, 10000.0, 31.0, 4168.0195312500255, 1994.7140625000054 - 0.45, 10000.0, 31.5, 4357.481152343781, 2065.488085937507 - 0.45, 10000.0, 32.0, 4546.943750000033, 2136.4625000000096 - 0.45, 10000.0, 32.5, 4736.4071289062895, 2207.654101562511 - 0.45, 10000.0, 33.0, 4925.871093750046, 2279.0796875000156 - 0.45, 10000.0, 33.5, 5115.335449218801, 2350.7560546875184 - 0.45, 10000.0, 34.0, 5304.800000000057, 2422.7000000000216 - 0.45, 10000.0, 34.5, 5494.265781249947, 2495.283515624988 - 0.45, 10000.0, 35.0, 5683.731249999939, 2568.1343749999883 - 0.45, 10000.0, 35.5, 5873.196093749928, 2641.2355468749865 - 0.45, 10000.0, 36.0, 6062.659999999916, 2714.569999999984 - 0.45, 10000.0, 36.5, 6252.122656249901, 2788.1207031249814 - 0.45, 10000.0, 37.0, 6441.583749999885, 2861.8706249999777 - 0.45, 10000.0, 37.5, 6631.042968749869, 2935.8027343749745 - 0.45, 10000.0, 38.0, 6820.499999999852, 3009.89999999997 - 0.45, 10000.0, 38.5, 7009.946093750053, 3084.0757812500697 - 0.45, 10000.0, 39.0, 7199.393750000055, 3158.4187500000744 - 0.45, 10000.0, 39.5, 7388.844531250058, 3232.927343750077 - 0.45, 10000.0, 40.0, 7578.300000000059, 3307.600000000082 - 0.45, 10000.0, 40.5, 7767.77343750004, 3382.1656249999983 - 0.45, 10000.0, 41.0, 7957.250000000058, 3457.000000000002 - 0.45, 10000.0, 41.5, 8146.726562500086, 3532.209375000004 - 0.45, 10000.0, 42.0, 8336.200000000117, 3607.9000000000074 - 0.45, 10000.0, 42.5, 8525.507031250041, 3684.6898437500354 - 0.45, 10000.0, 43.0, 8714.868750000045, 3761.968750000054 - 0.45, 10000.0, 43.5, 8904.346093750046, 3839.6382812500738 - 0.45, 10000.0, 44.0, 9094.000000000035, 3917.6000000000977 - 0.45, 10000.0, 44.5, 9284.485156250044, 3995.5679687499946 - 0.45, 10000.0, 45.0, 9475.03125000007, 4073.7062499999934 - 0.45, 10000.0, 45.5, 9665.461718750095, 4151.991406249991 - 0.45, 10000.0, 46.0, 9855.600000000128, 4230.399999999992 - 0.45, 10000.0, 46.5, 10044.390625000138, 4308.693750000056 - 0.45, 10000.0, 47.0, 10232.887500000192, 4387.1500000000715 - 0.45, 10000.0, 47.5, 10421.265625000247, 4465.831250000091 - 0.45, 10000.0, 48.0, 10609.700000000306, 4544.8000000001075 - 0.45, 10000.0, 48.5, 10798.36562500037, 4624.118750000126 - 0.45, 10000.0, 49.0, 10987.437500000446, 4703.850000000143 - 0.45, 10000.0, 49.5, 11177.090625000521, 4784.056250000159 - 0.45, 10000.0, 50.0, 11367.500000000593, 4864.800000000174 - 0.45, 15000.0, 0.0, 346.61990920630984, 346.61990920630984 - 0.45, 15000.0, 22.0, 815.4999999999993, 695.4999999999989 - 0.45, 15000.0, 22.5, 970.2033203124979, 751.1539062499996 - 0.45, 15000.0, 23.0, 1123.3359374999968, 805.4812500000011 - 0.45, 15000.0, 23.5, 1275.4255859374966, 858.8179687500018 - 0.45, 15000.0, 24.0, 1426.999999999996, 911.500000000003 - 0.45, 15000.0, 24.5, 1578.5869140624952, 963.863281250004 - 0.45, 15000.0, 25.0, 1730.7140624999947, 1016.2437500000055 - 0.45, 15000.0, 25.5, 1883.9091796874945, 1068.9773437500069 - 0.45, 15000.0, 26.0, 2038.6999999999941, 1122.4000000000092 - 0.45, 15000.0, 26.5, 2201.165039062482, 1179.9238281249995 - 0.45, 15000.0, 27.0, 2366.5984374999784, 1238.984374999999 - 0.45, 15000.0, 27.5, 2534.5763671874756, 1299.3902343749992 - 0.45, 15000.0, 28.0, 2704.6749999999724, 1360.9499999999985 - 0.45, 15000.0, 28.5, 2876.4705078124684, 1423.4722656249976 - 0.45, 15000.0, 29.0, 3049.539062499966, 1486.7656249999975 - 0.45, 15000.0, 29.5, 3223.4568359374625, 1550.6386718749964 - 0.45, 15000.0, 30.0, 3397.7999999999593, 1614.899999999996 - 0.45, 15000.0, 30.5, 3567.6986328125317, 1677.299218749994 - 0.45, 15000.0, 31.0, 3737.598437500038, 1739.8999999999928 - 0.45, 15000.0, 31.5, 3907.4990234375455, 1802.707031249993 - 0.45, 15000.0, 32.0, 4077.400000000053, 1865.7249999999924 - 0.45, 15000.0, 32.5, 4247.300976562562, 1928.9585937499915 - 0.45, 15000.0, 33.0, 4417.20156250007, 1992.412499999991 - 0.45, 15000.0, 33.5, 4587.101367187581, 2056.09140624999 - 0.45, 15000.0, 34.0, 4757.000000000091, 2119.9999999999895 - 0.45, 15000.0, 34.5, 4926.893789062442, 2184.4333593749734 - 0.45, 15000.0, 35.0, 5096.785937499926, 2249.0781249999686 - 0.45, 15000.0, 35.5, 5266.676367187412, 2313.9113281249624 - 0.45, 15000.0, 36.0, 5436.564999999893, 2378.9099999999557 - 0.45, 15000.0, 36.5, 5606.4517578123705, 2444.05117187495 - 0.45, 15000.0, 37.0, 5776.336562499847, 2509.3118749999417 - 0.45, 15000.0, 37.5, 5946.21933593732, 2574.669140624934 - 0.45, 15000.0, 38.0, 6116.099999999789, 2640.099999999924 - 0.45, 15000.0, 38.5, 6285.976367187688, 2704.998242187599 - 0.45, 15000.0, 39.0, 6455.85156250021, 2770.226562500118 - 0.45, 15000.0, 39.5, 6625.725976562736, 2835.8916015626373 - 0.45, 15000.0, 40.0, 6795.600000000261, 2902.1000000001604 - 0.45, 15000.0, 40.5, 6965.471093750074, 2969.4671875000367 - 0.45, 15000.0, 41.0, 7135.343750000096, 3037.387500000049 - 0.45, 15000.0, 41.5, 7305.219531250123, 3105.7640625000645 - 0.45, 15000.0, 42.0, 7475.100000000149, 3174.5000000000814 - 0.45, 15000.0, 42.5, 7644.86171875008, 3243.2796874999963 - 0.45, 15000.0, 43.0, 7814.681250000103, 3312.312499999998 - 0.45, 15000.0, 43.5, 7984.610156250125, 3381.589062500002 - 0.45, 15000.0, 44.0, 8154.70000000015, 3451.100000000007 - 0.45, 15000.0, 44.5, 8325.53359375006, 3520.875000000029 - 0.45, 15000.0, 45.0, 8496.418750000086, 3590.8500000000417 - 0.45, 15000.0, 45.5, 8667.194531250118, 3661.0000000000587 - 0.45, 15000.0, 46.0, 8837.700000000152, 3731.3000000000784 - 0.45, 15000.0, 46.5, 9006.965624999963, 3801.377343750027 - 0.45, 15000.0, 47.0, 9175.962499999963, 3871.6937500000327 - 0.45, 15000.0, 47.5, 9344.853124999976, 3942.363281250037 - 0.45, 15000.0, 48.0, 9513.79999999999, 4013.5000000000396 - 0.45, 15000.0, 48.5, 9682.965625000013, 4085.217968750044 - 0.45, 15000.0, 49.0, 9852.51250000004, 4157.631250000045 - 0.45, 15000.0, 49.5, 10022.603125000078, 4230.853906250046 - 0.45, 15000.0, 50.0, 10193.400000000118, 4305.000000000043 - 0.45, 20000.0, 0.0, 287.8228586178484, 287.8228586178484 - 0.45, 20000.0, 22.0, 810.2000000000002, 625.1 - 0.45, 20000.0, 22.5, 963.9457031249998, 677.3021484375 - 0.45, 20000.0, 23.0, 1116.1093749999989, 729.2953124999999 - 0.45, 20000.0, 23.5, 1267.2183593749983, 781.2408203124996 - 0.45, 20000.0, 24.0, 1417.7999999999965, 833.2999999999993 - 0.45, 20000.0, 24.5, 1568.3816406249957, 885.6341796874988 - 0.45, 20000.0, 25.0, 1719.4906249999933, 938.404687499998 - 0.45, 20000.0, 25.5, 1871.6542968749916, 991.7728515624973 - 0.45, 20000.0, 26.0, 2025.3999999999894, 1045.8999999999962 - 0.45, 20000.0, 26.5, 2186.7908203124994, 1102.5251953125005 - 0.45, 20000.0, 27.0, 2351.1346874999986, 1160.322187500001 - 0.45, 20000.0, 27.5, 2518.0099609374997, 1219.1818359375013 - 0.45, 20000.0, 28.0, 2686.995, 1278.995000000001 - 0.45, 20000.0, 28.5, 2857.6681640624997, 1339.6525390625015 - 0.45, 20000.0, 29.0, 3029.607812500001, 1401.0453125000015 - 0.45, 20000.0, 29.5, 3202.392304687501, 1463.0641796875016 - 0.45, 20000.0, 30.0, 3375.600000000001, 1525.6000000000024 - 0.45, 20000.0, 30.5, 3544.3861328125067, 1587.6929687500021 - 0.45, 20000.0, 31.0, 3713.173437500009, 1650.1656250000024 - 0.45, 20000.0, 31.5, 3881.96152343751, 1712.9898437500028 - 0.45, 20000.0, 32.0, 4050.750000000011, 1776.137500000003 - 0.45, 20000.0, 32.5, 4219.538476562511, 1839.5804687500045 - 0.45, 20000.0, 33.0, 4388.326562500014, 1903.2906250000046 - 0.45, 20000.0, 33.5, 4557.113867187516, 1967.239843750005 - 0.45, 20000.0, 34.0, 4725.900000000017, 2031.400000000006 - 0.45, 20000.0, 34.5, 4894.671445312496, 2094.990742187495 - 0.45, 20000.0, 35.0, 5063.442187499997, 2158.807812499992 - 0.45, 20000.0, 35.5, 5232.213085937496, 2222.8947265624915 - 0.45, 20000.0, 36.0, 5400.984999999996, 2287.2949999999887 - 0.45, 20000.0, 36.5, 5569.758789062495, 2352.052148437486 - 0.45, 20000.0, 37.0, 5738.5353124999965, 2417.209687499983 - 0.45, 20000.0, 37.5, 5907.3154296874945, 2482.811132812479 - 0.45, 20000.0, 38.0, 6076.099999999994, 2548.8999999999764 - 0.45, 20000.0, 38.5, 6244.902539062524, 2615.966992187512 - 0.45, 20000.0, 39.0, 6413.704687500027, 2683.376562500013 - 0.45, 20000.0, 39.5, 6582.5044921875315, 2751.072851562516 - 0.45, 20000.0, 40.0, 6751.300000000035, 2819.000000000018 - 0.45, 20000.0, 40.5, 6920.076562499992, 2886.7359375000087 - 0.45, 20000.0, 41.0, 7088.849999999989, 2954.7375000000125 - 0.45, 20000.0, 41.5, 7257.623437499989, 3023.0953125000174 - 0.45, 20000.0, 42.0, 7426.399999999986, 3091.9000000000224 - 0.45, 20000.0, 42.5, 7595.065625000018, 3161.4570312500014 - 0.45, 20000.0, 43.0, 7763.787500000023, 3231.556250000001 - 0.45, 20000.0, 43.5, 7932.6156250000295, 3302.202343750001 - 0.45, 20000.0, 44.0, 8101.600000000039, 3373.3999999999996 - 0.45, 20000.0, 44.5, 8271.310156250009, 3445.06796875001 - 0.45, 20000.0, 45.0, 8441.068750000019, 3517.331250000015 - 0.45, 20000.0, 45.5, 8610.717968750025, 3590.2289062500195 - 0.45, 20000.0, 46.0, 8780.100000000037, 3663.800000000025 - 0.45, 20000.0, 46.5, 8948.26015625, 3737.833593749999 - 0.45, 20000.0, 47.0, 9116.156250000004, 3812.7187499999995 - 0.45, 20000.0, 47.5, 9283.94921875, 3888.5945312499994 - 0.45, 20000.0, 48.0, 9451.8, 3965.5999999999995 - 0.45, 20000.0, 48.5, 9619.869531250006, 4043.8742187499984 - 0.45, 20000.0, 49.0, 9788.318750000004, 4123.556249999999 - 0.45, 20000.0, 49.5, 9957.308593750005, 4204.785156249996 - 0.45, 20000.0, 50.0, 10127.000000000015, 4287.699999999994 - 0.45, 25000.0, 0.0, 237.19895432128598, 237.19895432128598 - 0.45, 25000.0, 22.0, 653.7, 513.1 - 0.45, 25000.0, 22.5, 777.7240234375, 554.37109375 - 0.45, 25000.0, 23.0, 900.4828125, 595.5687499999999 - 0.45, 25000.0, 23.5, 1022.4001953125, 636.8070312499999 - 0.45, 25000.0, 24.0, 1143.8999999999999, 678.1999999999999 - 0.45, 25000.0, 24.5, 1265.4060546874998, 719.8617187499999 - 0.45, 25000.0, 25.0, 1387.3421874999995, 761.9062499999999 - 0.45, 25000.0, 25.5, 1510.1322265624997, 804.4476562499998 - 0.45, 25000.0, 26.0, 1634.1999999999994, 847.5999999999998 - 0.45, 25000.0, 26.5, 1764.4250000000004, 892.6886718750001 - 0.45, 25000.0, 27.0, 1897.03, 938.6856250000001 - 0.45, 25000.0, 27.5, 2031.6750000000002, 985.497265625 - 0.45, 25000.0, 28.0, 2168.0199999999995, 1033.03 - 0.45, 25000.0, 28.5, 2305.725, 1081.1902343749998 - 0.45, 25000.0, 29.0, 2444.45, 1129.884375 - 0.45, 25000.0, 29.5, 2583.8549999999996, 1179.018828125 - 0.45, 25000.0, 30.0, 2723.6, 1228.5 - 0.45, 25000.0, 30.5, 2859.772949218749, 1277.3971679687502 - 0.45, 25000.0, 31.0, 2995.946093749999, 1326.5335937500001 - 0.45, 25000.0, 31.5, 3132.119628906249, 1375.89541015625 - 0.45, 25000.0, 32.0, 3268.2937499999994, 1425.46875 - 0.45, 25000.0, 32.5, 3404.468652343749, 1475.2397460937502 - 0.45, 25000.0, 33.0, 3540.644531249999, 1525.1945312500002 - 0.45, 25000.0, 33.5, 3676.821582031249, 1575.3192382812501 - 0.45, 25000.0, 34.0, 3812.999999999998, 1625.6 - 0.45, 25000.0, 34.5, 3949.1877734374953, 1675.4712890625 - 0.45, 25000.0, 35.0, 4085.376562499994, 1725.5234375000002 - 0.45, 25000.0, 35.5, 4221.565820312493, 1775.7951171875 - 0.45, 25000.0, 36.0, 4357.754999999993, 1826.325 - 0.45, 25000.0, 36.5, 4493.94355468749, 1877.1517578125001 - 0.45, 25000.0, 37.0, 4630.130937499989, 1928.3140625 - 0.45, 25000.0, 37.5, 4766.316601562488, 1979.8505859375 - 0.45, 25000.0, 38.0, 4902.499999999987, 2031.8000000000002 - 0.45, 25000.0, 38.5, 5038.6763671875015, 2084.554296874999 - 0.45, 25000.0, 39.0, 5174.851562500004, 2137.6156249999995 - 0.45, 25000.0, 39.5, 5311.025976562503, 2190.9441406249994 - 0.45, 25000.0, 40.0, 5447.200000000004, 2244.499999999999 - 0.45, 25000.0, 40.5, 5583.371093749999, 2297.8976562500006 - 0.45, 25000.0, 41.0, 5719.543749999999, 2351.581250000001 - 0.45, 25000.0, 41.5, 5855.719531249999, 2405.649218750001 - 0.45, 25000.0, 42.0, 5991.899999999998, 2460.2000000000016 - 0.45, 25000.0, 42.5, 6127.992968749998, 2515.5859374999995 - 0.45, 25000.0, 43.0, 6264.131249999997, 2571.5499999999997 - 0.45, 25000.0, 43.5, 6400.353906249997, 2628.0890624999997 - 0.45, 25000.0, 44.0, 6536.699999999996, 2685.1999999999994 - 0.45, 25000.0, 44.5, 6673.618749999996, 2743.035937499999 - 0.45, 25000.0, 45.0, 6810.574999999995, 2801.3749999999986 - 0.45, 25000.0, 45.5, 6947.443749999993, 2860.1515624999984 - 0.45, 25000.0, 46.0, 7084.099999999992, 2919.299999999998 - 0.45, 25000.0, 46.5, 7219.789843750004, 2978.2234375000016 - 0.45, 25000.0, 47.0, 7355.268750000007, 3037.600000000002 - 0.45, 25000.0, 47.5, 7490.663281250009, 3097.5765625000026 - 0.45, 25000.0, 48.0, 7626.100000000011, 3158.300000000003 - 0.45, 25000.0, 48.5, 7761.705468750014, 3219.9171875000034 - 0.45, 25000.0, 49.0, 7897.606250000016, 3282.5750000000035 - 0.45, 25000.0, 49.5, 8033.92890625002, 3346.420312500004 - 0.45, 25000.0, 50.0, 8170.800000000024, 3411.600000000004 - 0.45, 30000.0, 0.0, 193.88236174817698, 193.88236174817698 - 0.45, 30000.0, 22.0, 496.9000000000001, 413.0999999999985 - 0.45, 30000.0, 22.5, 590.8919921875012, 446.9775390624992 - 0.45, 30000.0, 23.0, 684.0515625000029, 478.17968750000017 - 0.45, 30000.0, 23.5, 776.685351562505, 507.29199218750136 - 0.45, 30000.0, 24.0, 869.1000000000076, 534.9000000000029 - 0.45, 30000.0, 24.5, 961.6021484375115, 561.5892578125048 - 0.45, 30000.0, 25.0, 1054.4984375000158, 587.9453125000069 - 0.45, 30000.0, 25.5, 1148.0955078125205, 614.5537109375097 - 0.45, 30000.0, 26.0, 1242.7000000000269, 642.0000000000127 - 0.45, 30000.0, 26.5, 1341.9339843749945, 676.9660156249963 - 0.45, 30000.0, 27.0, 1442.9781249999928, 714.2893749999961 - 0.45, 30000.0, 27.5, 1545.5707031249904, 753.5105468749956 - 0.45, 30000.0, 28.0, 1649.4499999999873, 794.1699999999952 - 0.45, 30000.0, 28.5, 1754.354296874984, 835.8082031249946 - 0.45, 30000.0, 29.0, 1860.0218749999797, 877.9656249999942 - 0.45, 30000.0, 29.5, 1966.1910156249746, 920.1827343749937 - 0.45, 30000.0, 30.0, 2072.5999999999685, 961.9999999999933 - 0.45, 30000.0, 30.5, 2176.202148437519, 996.4327148437444 - 0.45, 30000.0, 31.0, 2279.785937500022, 1030.167968749994 - 0.45, 30000.0, 31.5, 2383.354882812525, 1063.3676757812432 - 0.45, 30000.0, 32.0, 2486.912500000026, 1096.1937499999922 - 0.45, 30000.0, 32.5, 2590.462304687528, 1128.8081054687411 - 0.45, 30000.0, 33.0, 2694.007812500031, 1161.3726562499896 - 0.45, 30000.0, 33.5, 2797.5525390625326, 1194.049316406238 - 0.45, 30000.0, 34.0, 2901.100000000036, 1226.999999999986 - 0.45, 30000.0, 34.5, 3004.8087499999815, 1260.9259765624968 - 0.45, 30000.0, 35.0, 3108.512499999979, 1295.3984374999975 - 0.45, 30000.0, 35.5, 3212.199999999976, 1330.527929687498 - 0.45, 30000.0, 36.0, 3315.859999999972, 1366.4249999999984 - 0.45, 30000.0, 36.5, 3419.481249999968, 1403.2001953124986 - 0.45, 30000.0, 37.0, 3523.0524999999634, 1440.9640624999997 - 0.45, 30000.0, 37.5, 3626.5624999999577, 1479.8271484374998 - 0.45, 30000.0, 38.0, 3729.999999999951, 1519.900000000001 - 0.45, 30000.0, 38.5, 3833.0394531247584, 1564.7578124999495 - 0.45, 30000.0, 39.0, 3936.1468749997143, 1609.2499999999404 - 0.45, 30000.0, 39.5, 4039.380859374665, 1652.7171874999297 - 0.45, 30000.0, 40.0, 4142.79999999961, 1694.4999999999186 - 0.45, 30000.0, 40.5, 4246.859374999999, 1730.5367187499855 - 0.45, 30000.0, 41.0, 4351.062499999993, 1764.9312499999805 - 0.45, 30000.0, 41.5, 4455.309374999986, 1798.3851562499735 - 0.45, 30000.0, 42.0, 4559.499999999975, 1831.5999999999647 - 0.45, 30000.0, 42.5, 4663.167187499968, 1862.6875000000048 - 0.45, 30000.0, 43.0, 4766.7249999999585, 1895.9750000000058 - 0.45, 30000.0, 43.5, 4870.220312499949, 1933.2000000000075 - 0.45, 30000.0, 44.0, 4973.699999999942, 1976.1000000000088 - 0.45, 30000.0, 44.5, 5077.441406249942, 2039.1546874999815 - 0.45, 30000.0, 45.0, 5181.168749999934, 2106.2624999999784 - 0.45, 30000.0, 45.5, 5284.83671874992, 2174.064062499976 - 0.45, 30000.0, 46.0, 5388.399999999909, 2239.199999999974 - 0.45, 30000.0, 46.5, 5491.49687499993, 2288.3148437499913 - 0.45, 30000.0, 47.0, 5594.524999999903, 2332.043749999986 - 0.45, 30000.0, 47.5, 5697.56562499987, 2371.025781249982 - 0.45, 30000.0, 48.0, 5800.69999999983, 2405.8999999999764 - 0.45, 30000.0, 48.5, 5904.009374999787, 2437.3054687499703 - 0.45, 30000.0, 49.0, 6007.574999999736, 2465.881249999963 - 0.45, 30000.0, 49.5, 6111.478124999676, 2492.2664062499543 - 0.45, 30000.0, 50.0, 6215.799999999613, 2517.099999999945 - 0.45, 35000.0, 0.0, 157.06675471179048, 157.06675471179048 - 0.45, 35000.0, 22.0, 414.8999999999998, 344.4000000000003 - 0.45, 35000.0, 22.5, 495.1851562500009, 359.7882812500018 - 0.45, 35000.0, 23.0, 574.2687500000013, 381.5937500000029 - 0.45, 35000.0, 23.5, 652.4679687500012, 408.7273437500037 - 0.45, 35000.0, 24.0, 730.1000000000006, 440.1000000000042 - 0.45, 35000.0, 24.5, 807.4820312499999, 474.62265625000435 - 0.45, 35000.0, 25.0, 884.9312499999991, 511.20625000000433 - 0.45, 35000.0, 25.5, 962.7648437499978, 548.7617187500042 - 0.45, 35000.0, 26.0, 1041.2999999999968, 586.2000000000043 - 0.45, 35000.0, 26.5, 1123.9095703124833, 611.6585937500037 - 0.45, 35000.0, 27.0, 1208.0296874999813, 634.2062500000031 - 0.45, 35000.0, 27.5, 1293.4537109374787, 654.6007812500033 - 0.45, 35000.0, 28.0, 1379.9749999999774, 673.6000000000035 - 0.45, 35000.0, 28.5, 1467.3869140624756, 691.9617187500041 - 0.45, 35000.0, 29.0, 1555.482812499974, 710.4437500000048 - 0.45, 35000.0, 29.5, 1644.0560546874724, 729.8039062500061 - 0.45, 35000.0, 30.0, 1732.8999999999724, 750.8000000000077 - 0.45, 35000.0, 30.5, 1819.7859375000248, 788.7237304687243 - 0.45, 35000.0, 31.0, 1906.7218750000288, 828.4148437499716 - 0.45, 35000.0, 31.5, 1993.6937500000333, 869.246972656219 - 0.45, 35000.0, 32.0, 2080.6875000000377, 910.5937499999668 - 0.45, 35000.0, 32.5, 2167.6890625000424, 951.8288085937146 - 0.45, 35000.0, 33.0, 2254.6843750000476, 992.3257812499633 - 0.45, 35000.0, 33.5, 2341.659375000053, 1031.458300781212 - 0.45, 35000.0, 34.0, 2428.600000000059, 1068.599999999961 - 0.45, 35000.0, 34.5, 2514.815429687598, 1087.9860546875088 - 0.45, 35000.0, 35.0, 2601.0328125001074, 1105.5703125000116 - 0.45, 35000.0, 35.5, 2687.3025390626167, 1122.1681640625145 - 0.45, 35000.0, 36.0, 2773.6750000001257, 1138.5950000000173 - 0.45, 35000.0, 36.5, 2860.2005859376322, 1155.6662109375202 - 0.45, 35000.0, 37.0, 2946.9296875001396, 1174.1971875000233 - 0.45, 35000.0, 37.5, 3033.912695312646, 1195.0033203125265 - 0.45, 35000.0, 38.0, 3121.20000000015, 1218.9000000000299 - 0.45, 35000.0, 38.5, 3209.8228515624833, 1238.7597656249313 - 0.45, 35000.0, 39.0, 3298.3421874999863, 1267.4593749999103 - 0.45, 35000.0, 39.5, 3386.590429687491, 1307.579296874886 - 0.45, 35000.0, 40.0, 3474.3999999999983, 1361.699999999859 - 0.45, 35000.0, 40.5, 3560.5867187500835, 1458.6421874999878 - 0.45, 35000.0, 41.0, 3646.406250000114, 1564.2499999999795 - 0.45, 35000.0, 41.5, 3732.0976562501487, 1670.6078124999694 - 0.45, 35000.0, 42.0, 3817.9000000001856, 1769.799999999957 - 0.45, 35000.0, 42.5, 3905.024999999975, 1839.457812499951 - 0.45, 35000.0, 43.0, 3992.3499999999412, 1891.8999999999307 - 0.45, 35000.0, 43.5, 4079.724999999895, 1924.992187499906 - 0.45, 35000.0, 44.0, 4166.999999999834, 1936.5999999998785 - 0.45, 35000.0, 44.5, 4253.376562500007, 1889.374218750037 - 0.45, 35000.0, 45.0, 4339.612500000021, 1830.481250000053 - 0.45, 35000.0, 45.5, 4425.817187500042, 1771.8726562500717 - 0.45, 35000.0, 46.0, 4512.100000000071, 1725.5000000000941 - 0.45, 35000.0, 46.5, 4599.003906249994, 1746.0492187499729 - 0.45, 35000.0, 47.0, 4686.031250000003, 1785.6437499999656 - 0.45, 35000.0, 47.5, 4773.117968750017, 1839.1414062499543 - 0.45, 35000.0, 48.0, 4860.200000000034, 1901.399999999939 - 0.45, 35000.0, 48.5, 4947.213281250064, 1967.2773437499193 - 0.45, 35000.0, 49.0, 5034.093750000099, 2031.6312499998926 - 0.45, 35000.0, 49.5, 5120.777343750141, 2089.31953124986 - 0.45, 35000.0, 50.0, 5207.200000000192, 2135.1999999998193 - 0.45, 39000.0, 0.0, 130.27284720837426, 130.27284720837426 - 0.45, 39000.0, 22.0, 327.40000000000055, 281.3000000000016 - 0.45, 39000.0, 22.5, 391.2619140624987, 290.9398437500007 - 0.45, 39000.0, 23.0, 453.92968749999704, 308.54374999999976 - 0.45, 39000.0, 23.5, 515.7076171874958, 332.750781249999 - 0.45, 39000.0, 24.0, 576.8999999999943, 362.19999999999794 - 0.45, 39000.0, 24.5, 637.8111328124932, 395.5304687499969 - 0.45, 39000.0, 25.0, 698.7453124999919, 431.3812499999956 - 0.45, 39000.0, 25.5, 760.0068359374907, 468.3914062499942 - 0.45, 39000.0, 26.0, 821.8999999999893, 505.19999999999254 - 0.45, 39000.0, 26.5, 887.7902343749964, 528.7388671874975 - 0.45, 39000.0, 27.0, 955.0956249999952, 548.6853124999975 - 0.45, 39000.0, 27.5, 1023.5957031249942, 565.6853515624977 - 0.45, 39000.0, 28.0, 1093.0699999999936, 580.3849999999981 - 0.45, 39000.0, 28.5, 1163.2980468749922, 593.4302734374986 - 0.45, 39000.0, 29.0, 1234.0593749999919, 605.4671874999995 - 0.45, 39000.0, 29.5, 1305.133515624991, 617.1417578125006 - 0.45, 39000.0, 30.0, 1376.2999999999909, 629.1000000000024 - 0.45, 39000.0, 30.5, 1444.7281250000078, 649.942089843738 - 0.45, 39000.0, 31.0, 1513.0562500000103, 671.6023437499857 - 0.45, 39000.0, 31.5, 1581.3125000000136, 693.9692382812333 - 0.45, 39000.0, 32.0, 1649.5250000000167, 716.9312499999803 - 0.45, 39000.0, 32.5, 1717.7218750000204, 740.3768554687271 - 0.45, 39000.0, 33.0, 1785.9312500000246, 764.1945312499738 - 0.45, 39000.0, 33.5, 1854.1812500000287, 788.2727539062199 - 0.45, 39000.0, 34.0, 1922.500000000033, 812.4999999999658 - 0.45, 39000.0, 34.5, 1991.6982031249888, 839.6296874999822 - 0.45, 39000.0, 35.0, 2060.9468749999846, 866.4124999999779 - 0.45, 39000.0, 35.5, 2130.199609374979, 892.4640624999727 - 0.45, 39000.0, 36.0, 2199.409999999972, 917.3999999999671 - 0.45, 39000.0, 36.5, 2268.531640624963, 940.8359374999608 - 0.45, 39000.0, 37.0, 2337.5181249999523, 962.3874999999537 - 0.45, 39000.0, 37.5, 2406.3230468749402, 981.6703124999458 - 0.45, 39000.0, 38.0, 2474.8999999999246, 998.2999999999371 - 0.45, 39000.0, 38.5, 2542.466406250032, 998.9617187500055 - 0.45, 39000.0, 39.0, 2610.093750000039, 1002.9062500000058 - 0.45, 39000.0, 39.5, 2677.899218750047, 1012.6226562500075 - 0.45, 39000.0, 40.0, 2746.0000000000564, 1030.6000000000101 - 0.45, 39000.0, 40.5, 2815.107031249994, 1067.2960937499943 - 0.45, 39000.0, 41.0, 2884.5062499999826, 1114.0437499999948 - 0.45, 39000.0, 41.5, 2954.0773437499693, 1170.1445312499964 - 0.45, 39000.0, 42.0, 3023.6999999999557, 1234.8999999999996 - 0.45, 39000.0, 42.5, 3092.52734375002, 1318.1703125000142 - 0.45, 39000.0, 43.0, 3161.456250000044, 1404.4750000000167 - 0.45, 39000.0, 43.5, 3230.657031250069, 1488.8921875000183 - 0.45, 39000.0, 44.0, 3300.3000000000925, 1566.5000000000186 - 0.45, 39000.0, 44.5, 3372.3992187500066, 1626.4117187499724 - 0.45, 39000.0, 45.0, 3444.5437500000216, 1672.0562499999678 - 0.45, 39000.0, 45.5, 3516.1664062500467, 1700.8976562499645 - 0.45, 39000.0, 46.0, 3586.700000000083, 1710.3999999999612 - 0.45, 39000.0, 46.5, 3652.2921875000475, 1669.45312499998 - 0.45, 39000.0, 47.0, 3716.9750000000504, 1615.524999999964 - 0.45, 39000.0, 47.5, 3781.495312500052, 1557.5093749999442 - 0.45, 39000.0, 48.0, 3846.6000000000495, 1504.2999999999186 - 0.45, 39000.0, 48.5, 3913.0359375000417, 1464.7906249998887 - 0.45, 39000.0, 49.0, 3981.550000000029, 1447.8749999998543 - 0.45, 39000.0, 49.5, 4052.889062500008, 1462.4468749998136 - 0.45, 39000.0, 50.0, 4127.799999999982, 1517.3999999997677 - 0.45, 43000.0, 0.0, 107.48793702686017, 107.48793702686017 - 0.45, 43000.0, 22.0, 163.89999999999839, 362.89999999999884 - 0.45, 43000.0, 22.5, 200.65624999999315, 309.2029296874959 - 0.45, 43000.0, 23.0, 236.5249999999869, 268.4015624999958 - 0.45, 43000.0, 23.5, 271.6562499999794, 238.8744140624976 - 0.45, 43000.0, 24.0, 306.1999999999704, 219.00000000000094 - 0.45, 43000.0, 24.5, 340.3062499999595, 207.15683593750524 - 0.45, 43000.0, 25.0, 374.12499999994657, 201.72343750000994 - 0.45, 43000.0, 25.5, 407.80624999993097, 201.0783203125146 - 0.45, 43000.0, 26.0, 441.49999999991286, 203.6000000000186 - 0.45, 43000.0, 26.5, 476.5484374999852, 191.56152343748096 - 0.45, 43000.0, 27.0, 511.9774999999834, 178.52656249997705 - 0.45, 43000.0, 27.5, 547.7328124999823, 165.63457031247282 - 0.45, 43000.0, 28.0, 583.7599999999817, 154.02499999996846 - 0.45, 43000.0, 28.5, 620.0046874999822, 144.83730468746438 - 0.45, 43000.0, 29.0, 656.4124999999838, 139.21093749996058 - 0.45, 43000.0, 29.5, 692.9290624999866, 138.2853515624572 - 0.45, 43000.0, 30.0, 729.4999999999908, 143.19999999995468 - 0.45, 43000.0, 30.5, 765.2846679687997, 169.5974609374592 - 0.45, 43000.0, 31.0, 801.0898437500551, 202.7328124999529 - 0.45, 43000.0, 31.5, 836.9360351563116, 242.36425781244645 - 0.45, 43000.0, 32.0, 872.8437500000684, 288.2499999999401 - 0.45, 43000.0, 32.5, 908.8334960938266, 340.14824218743365 - 0.45, 43000.0, 33.0, 944.9257812500858, 397.81718749992746 - 0.45, 43000.0, 33.5, 981.1411132813464, 461.01503906242147 - 0.45, 43000.0, 34.0, 1017.5000000001078, 529.4999999999153 - 0.45, 43000.0, 34.5, 1055.6943359373856, 689.504335937446 - 0.45, 43000.0, 35.0, 1093.9140624998602, 846.0765624999358 - 0.45, 43000.0, 35.5, 1132.0205078123295, 990.7392578124254 - 0.45, 43000.0, 36.0, 1169.8749999997933, 1115.0149999999144 - 0.45, 43000.0, 36.5, 1207.338867187251, 1210.426367187403 - 0.45, 43000.0, 37.0, 1244.2734374997017, 1268.4959374998905 - 0.45, 43000.0, 37.5, 1280.5400390621448, 1280.7462890623797 - 0.45, 43000.0, 38.0, 1315.9999999995794, 1238.6999999998643 - 0.45, 43000.0, 38.5, 1347.1396484376266, 1025.5875000000972 - 0.45, 43000.0, 39.0, 1378.9453125001583, 797.3750000001294 - 0.45, 43000.0, 39.5, 1412.0283203126937, 569.6500000001636 - 0.45, 43000.0, 40.0, 1447.0000000002333, 358.00000000020304 - 0.45, 43000.0, 40.5, 1489.2617187500982, 206.3679687499126 - 0.45, 43000.0, 41.0, 1532.7187500001191, 90.6437499998967 - 0.45, 43000.0, 41.5, 1576.0664062501428, 15.072656249878605 - 0.45, 43000.0, 42.0, 1618.0000000001698, -16.100000000143154 - 0.45, 43000.0, 42.5, 1650.9218749999275, 46.48437499988273 - 0.45, 43000.0, 43.0, 1682.3374999999157, 143.9124999998227 - 0.45, 43000.0, 43.5, 1713.4593749998944, 262.3843749997544 - 0.45, 43000.0, 44.0, 1745.4999999998606, 388.0999999996783 - 0.45, 43000.0, 44.5, 1785.410156249887, 482.20859374999145 - 0.45, 43000.0, 45.0, 1826.3687499998364, 565.9812499999972 - 0.45, 43000.0, 45.5, 1867.2929687497879, 635.6382812500034 - 0.45, 43000.0, 46.0, 1907.0999999997473, 687.4000000000086 - 0.45, 43000.0, 46.5, 1939.9765624997196, 688.264062499858 - 0.45, 43000.0, 47.0, 1971.4624999996233, 675.3624999998337 - 0.45, 43000.0, 47.5, 2002.3671874995046, 656.6046874998076 - 0.45, 43000.0, 48.0, 2033.4999999993593, 639.8999999997787 - 0.45, 43000.0, 48.5, 2065.6703124991814, 633.1578124997482 - 0.45, 43000.0, 49.0, 2099.6874999989673, 644.2874999997143 - 0.45, 43000.0, 49.5, 2136.3609374987113, 681.198437499678 - 0.45, 43000.0, 50.0, 2176.499999998409, 751.7999999996379 - 0.45, 48000.0, 0.0, 84.52637486521456, 84.52637486521456 - 0.45, 48000.0, 22.0, 120.0999999999969, 291.79999999999166 - 0.45, 48000.0, 22.5, 153.86367187499997, 247.77363281249134 - 0.45, 48000.0, 23.0, 185.14062500000483, 214.91093749999115 - 0.45, 48000.0, 23.5, 214.3222656250116, 191.7427734374908 - 0.45, 48000.0, 24.0, 241.8000000000203, 176.7999999999904 - 0.45, 48000.0, 24.5, 267.9652343750312, 168.61347656248992 - 0.45, 48000.0, 25.0, 293.20937500004413, 165.71406249998947 - 0.45, 48000.0, 25.5, 317.9238281250595, 166.63261718748876 - 0.45, 48000.0, 26.0, 342.50000000007736, 169.89999999998793 - 0.45, 48000.0, 26.5, 370.55859374998664, 159.3484374999878 - 0.45, 48000.0, 27.0, 399.4462499999855, 147.3674999999846 - 0.45, 48000.0, 27.5, 429.0007812499842, 135.00781249998107 - 0.45, 48000.0, 28.0, 459.05999999998295, 123.31999999997723 - 0.45, 48000.0, 28.5, 489.4617187499816, 113.35468749997317 - 0.45, 48000.0, 29.0, 520.0437499999799, 106.16249999996879 - 0.45, 48000.0, 29.5, 550.6439062499782, 102.79406249996444 - 0.45, 48000.0, 30.0, 581.0999999999759, 104.29999999996001 - 0.45, 48000.0, 30.5, 608.8578124999564, 125.64794921871244 - 0.45, 48000.0, 31.0, 636.3749999999454, 152.6460937499548 - 0.45, 48000.0, 31.5, 663.7171874999337, 185.01962890619603 - 0.45, 48000.0, 32.0, 690.9499999999202, 222.4937499999362 - 0.45, 48000.0, 32.5, 718.1390624999058, 264.7936523436753 - 0.45, 48000.0, 33.0, 745.3499999998901, 311.6445312499132 - 0.45, 48000.0, 33.5, 772.6484374998731, 362.7715820311498 - 0.45, 48000.0, 34.0, 800.0999999998544, 417.8999999998854 - 0.45, 48000.0, 34.5, 830.0507812499542, 542.6437109374478 - 0.45, 48000.0, 35.0, 860.0687499999514, 664.564062499939 - 0.45, 48000.0, 35.5, 890.0023437499484, 777.1111328124291 - 0.45, 48000.0, 36.0, 919.6999999999443, 873.7349999999162 - 0.45, 48000.0, 36.5, 949.0101562499393, 947.885742187402 - 0.45, 48000.0, 37.0, 977.7812499999332, 993.013437499885 - 0.45, 48000.0, 37.5, 1005.8617187499245, 1002.5681640623648 - 0.45, 48000.0, 38.0, 1033.0999999999149, 969.9999999998422 - 0.45, 48000.0, 38.5, 1055.252343750175, 805.287890624906 - 0.45, 48000.0, 39.0, 1078.3812500002098, 628.6343749998916 - 0.45, 48000.0, 39.5, 1103.2445312502507, 452.0386718748789 - 0.45, 48000.0, 40.0, 1130.6000000002985, 287.4999999998663 - 0.45, 48000.0, 40.5, 1167.4906249999583, 168.16015624994685 - 0.45, 48000.0, 41.0, 1205.8749999999493, 76.41874999993586 - 0.45, 48000.0, 41.5, 1243.9968749999402, 15.817968749925313 - 0.45, 48000.0, 42.0, 1280.0999999999317, -10.100000000085473 - 0.45, 48000.0, 42.5, 1304.3812499999642, 37.85937500007357 - 0.45, 48000.0, 43.0, 1326.3499999999503, 113.32500000009185 - 0.45, 48000.0, 43.5, 1347.468749999934, 205.5781250001076 - 0.45, 48000.0, 44.0, 1369.1999999999157, 303.90000000012014 - 0.45, 48000.0, 44.5, 1398.4125000000524, 378.7632812499584 - 0.45, 48000.0, 45.0, 1429.0000000000762, 445.7812499999484 - 0.45, 48000.0, 45.5, 1460.262500000102, 501.7585937499385 - 0.45, 48000.0, 46.0, 1491.5000000001273, 543.499999999929 - 0.45, 48000.0, 46.5, 1519.856250000001, 543.6500000000809 - 0.45, 48000.0, 47.0, 1547.6499999999785, 532.8375000001056 - 0.45, 48000.0, 47.5, 1575.0437499999591, 517.5312500001363 - 0.45, 48000.0, 48.0, 1602.199999999947, 504.20000000017365 - 0.45, 48000.0, 48.5, 1629.281249999946, 499.3125000002192 - 0.45, 48000.0, 49.0, 1656.4499999999598, 509.33750000027254 - 0.45, 48000.0, 49.5, 1683.8687499999924, 540.7437500003352 - 0.45, 48000.0, 50.0, 1711.7000000000467, 600.0000000004079 - 0.5, 0.0, 0.0, 597.7442557300132, 597.7442557300132 - 0.5, 0.0, 22.0, 1322.6999999999982, 1247.0999999999929 - 0.5, 0.0, 22.5, 1573.5478515624554, 1377.168945312485 - 0.5, 0.0, 23.0, 1821.2921874998988, 1477.2984374999846 - 0.5, 0.0, 23.5, 2066.890429687325, 1553.5787109374892 - 0.5, 0.0, 24.0, 2311.299999999733, 1612.099999999999 - 0.5, 0.0, 24.5, 2555.478320312122, 1658.952539062514 - 0.5, 0.0, 25.0, 2800.3828124994857, 1700.226562500031 - 0.5, 0.0, 25.5, 3046.970898436824, 1742.0123046875524 - 0.5, 0.0, 26.0, 3296.1999999991367, 1790.400000000074 - 0.5, 0.0, 26.5, 3559.0039062500755, 1909.6919921875174 - 0.5, 0.0, 27.0, 3826.9337500001047, 2051.092812500038 - 0.5, 0.0, 27.5, 4099.2367187501395, 2210.713476562562 - 0.5, 0.0, 28.0, 4375.160000000182, 2384.6650000000946 - 0.5, 0.0, 28.5, 4653.9507812502325, 2569.0583984376317 - 0.5, 0.0, 29.0, 4934.856250000299, 2760.004687500178 - 0.5, 0.0, 29.5, 5217.123593750372, 2953.6148828127316 - 0.5, 0.0, 30.0, 5500.000000000459, 3146.0000000002947 - 0.5, 0.0, 30.5, 5774.524609374965, 3283.501464843499 - 0.5, 0.0, 31.0, 6048.934374999966, 3416.739843749704 - 0.5, 0.0, 31.5, 6323.258203124968, 3546.5661132809064 - 0.5, 0.0, 32.0, 6597.524999999969, 3673.831249999606 - 0.5, 0.0, 32.5, 6871.763671874969, 3799.3862304683053 - 0.5, 0.0, 33.0, 7146.003124999966, 3924.0820312495043 - 0.5, 0.0, 33.5, 7420.272265624962, 4048.7696289057008 - 0.5, 0.0, 34.0, 7694.5999999999585, 4174.299999999398 - 0.5, 0.0, 34.5, 7969.489374998741, 4362.821562499541 - 0.5, 0.0, 35.0, 8244.449999998356, 4548.049999999486 - 0.5, 0.0, 35.5, 8519.465624997923, 4724.998437499431 - 0.5, 0.0, 36.0, 8794.519999997437, 4888.679999999373 - 0.5, 0.0, 36.5, 9069.596874996896, 5034.107812499312 - 0.5, 0.0, 37.0, 9344.679999996293, 5156.2949999992525 - 0.5, 0.0, 37.5, 9619.753124995636, 5250.2546874991895 - 0.5, 0.0, 38.0, 9894.799999994919, 5310.999999999126 - 0.5, 0.0, 38.5, 10169.798046877377, 5289.264062500462 - 0.5, 0.0, 39.0, 10444.74062500314, 5247.300000000583 - 0.5, 0.0, 39.5, 10719.612890629047, 5189.960937500731 - 0.5, 0.0, 40.0, 10994.400000005102, 5122.100000000914 - 0.5, 0.0, 40.5, 11269.217968750243, 5041.124999999824 - 0.5, 0.0, 41.0, 11543.868750000298, 4962.312499999755 - 0.5, 0.0, 41.5, 11818.28515625031, 4893.493749999669 - 0.5, 0.0, 42.0, 12092.400000000265, 4842.499999999561 - 0.5, 0.0, 42.5, 12365.153906249783, 4828.842187499438 - 0.5, 0.0, 43.0, 12637.868749999701, 4843.999999999273 - 0.5, 0.0, 43.5, 12910.874218749645, 4891.132812499085 - 0.5, 0.0, 44.0, 13184.499999999622, 4973.399999998876 - 0.5, 0.0, 44.5, 13461.056249998983, 5121.980468750169 - 0.5, 0.0, 45.0, 13738.099999998452, 5300.806250000234 - 0.5, 0.0, 45.5, 14015.168749997762, 5501.828906250338 - 0.5, 0.0, 46.0, 14291.799999996874, 5717.000000000489 - 0.5, 0.0, 46.5, 14565.472656248412, 5924.821874999121 - 0.5, 0.0, 47.0, 14838.60624999798, 6136.0749999987775 - 0.5, 0.0, 47.5, 15111.56171874752, 6348.0906249983855 - 0.5, 0.0, 48.0, 15384.699999997049, 6558.199999997947 - 0.5, 0.0, 48.5, 15658.382031246576, 6763.734374997463 - 0.5, 0.0, 49.0, 15932.96874999612, 6962.024999996937 - 0.5, 0.0, 49.5, 16208.82109374568, 7150.40312499637 - 0.5, 0.0, 50.0, 16486.299999995284, 7326.199999995764 - 0.5, 2000.0, 0.0, 559.6498656104261, 559.6498656104261 - 0.5, 2000.0, 22.0, -887.9999999999909, 406.79999999999905 - 0.5, 2000.0, 22.5, -1055.4335937500118, 352.7218749999996 - 0.5, 2000.0, 23.0, -1221.268750000038, 304.82499999999936 - 0.5, 2000.0, 23.5, -1386.0695312500707, 261.51562499999847 - 0.5, 2000.0, 24.0, -1550.400000000111, 221.19999999999732 - 0.5, 2000.0, 24.5, -1714.8242187501608, 182.2843749999958 - 0.5, 2000.0, 25.0, -1879.9062500002187, 143.17499999999472 - 0.5, 2000.0, 25.5, -2046.2101562502878, 102.27812499999374 - 0.5, 2000.0, 26.0, -2214.30000000037, 57.99999999999352 - 0.5, 2000.0, 26.5, -2390.7240234374367, -7.407812499974995 - 0.5, 2000.0, 27.0, -2570.404062499923, -80.30749999996272 - 0.5, 2000.0, 27.5, -2752.8783203124067, -159.5234374999473 - 0.5, 2000.0, 28.0, -2937.68499999989, -243.8799999999295 - 0.5, 2000.0, 28.5, -3124.3623046873704, -332.2015624999084 - 0.5, 2000.0, 29.0, -3312.4484374998488, -423.31249999988427 - 0.5, 2000.0, 29.5, -3501.481601562325, -516.0371874998565 - 0.5, 2000.0, 30.0, -3690.9999999997963, -609.1999999998261 - 0.5, 2000.0, 30.5, -3875.7032226561546, -684.8864257812686 - 0.5, 2000.0, 31.0, -4060.4289062498847, -760.2539062500139 - 0.5, 2000.0, 31.5, -4245.17607421861, -835.7209960937578 - 0.5, 2000.0, 32.0, -4429.943749999832, -911.7062500000015 - 0.5, 2000.0, 32.5, -4614.730957031052, -988.6282226562439 - 0.5, 2000.0, 33.0, -4799.536718749762, -1066.9054687499854 - 0.5, 2000.0, 33.5, -4984.360058593473, -1146.956542968726 - 0.5, 2000.0, 34.0, -5169.199999999675, -1229.1999999999662 - 0.5, 2000.0, 34.5, -5354.3324218744565, -1339.7781640625337 - 0.5, 2000.0, 35.0, -5539.453124999406, -1450.935937500059 - 0.5, 2000.0, 35.5, -5724.5347656243575, -1560.641992187588 - 0.5, 2000.0, 36.0, -5909.54999999931, -1666.8650000001198 - 0.5, 2000.0, 36.5, -6094.471484374264, -1767.573632812655 - 0.5, 2000.0, 37.0, -6279.271874999222, -1860.736562500193 - 0.5, 2000.0, 37.5, -6463.923828124182, -1944.322460937734 - 0.5, 2000.0, 38.0, -6648.399999999143, -2016.3000000002785 - 0.5, 2000.0, 38.5, -6832.172070310713, -2057.0593749998698 - 0.5, 2000.0, 39.0, -7015.973437497777, -2091.262499999878 - 0.5, 2000.0, 39.5, -7199.888085934781, -2120.784374999893 - 0.5, 2000.0, 40.0, -7383.99999999672, -2147.4999999999127 - 0.5, 2000.0, 40.5, -7568.817968749525, -2168.81953124987 - 0.5, 2000.0, 41.0, -7753.831249999365, -2192.8687499997704 - 0.5, 2000.0, 41.5, -7938.953906249182, -2223.3085937496326 - 0.5, 2000.0, 42.0, -8124.09999999898, -2263.7999999994536 - 0.5, 2000.0, 42.5, -8308.835937499733, -2330.132812499842 - 0.5, 2000.0, 43.0, -8493.562499999467, -2408.9874999997924 - 0.5, 2000.0, 43.5, -8678.332812499111, -2499.1734374997322 - 0.5, 2000.0, 44.0, -8863.199999998655, -2599.499999999662 - 0.5, 2000.0, 44.5, -9048.75234374862, -2709.8859374998488 - 0.5, 2000.0, 45.0, -9234.29374999824, -2827.5874999998086 - 0.5, 2000.0, 45.5, -9419.663281247835, -2950.970312499772 - 0.5, 2000.0, 46.0, -9604.699999997412, -3078.39999999974 - 0.5, 2000.0, 46.5, -9788.356250001218, -3204.42187500004 - 0.5, 2000.0, 47.0, -9971.712500001513, -3332.7500000000036 - 0.5, 2000.0, 47.5, -10154.962500001797, -3463.2781249999575 - 0.5, 2000.0, 48.0, -10338.30000000205, -3595.8999999999023 - 0.5, 2000.0, 48.5, -10521.91875000226, -3730.5093749998387 - 0.5, 2000.0, 49.0, -10706.012500002407, -3866.999999999768 - 0.5, 2000.0, 49.5, -10890.775000002484, -4005.2656249996908 - 0.5, 2000.0, 50.0, -11076.400000002464, -4145.199999999609 - 0.5, 5000.0, 0.0, 506.12815012650947, 506.12815012650947 - 0.5, 5000.0, 22.0, 1569.9999999999973, 1201.600000000003 - 0.5, 5000.0, 22.5, 1868.2298828124929, 1309.7994140624967 - 0.5, 5000.0, 23.0, 2163.298437499987, 1415.1921874999928 - 0.5, 5000.0, 23.5, 2456.242773437479, 1518.6388671874918 - 0.5, 5000.0, 24.0, 2748.0999999999667, 1620.9999999999925 - 0.5, 5000.0, 24.5, 3039.9072265624523, 1723.1361328124954 - 0.5, 5000.0, 25.0, 3332.7015624999353, 1825.9078124999999 - 0.5, 5000.0, 25.5, 3627.520117187415, 1930.1755859375055 - 0.5, 5000.0, 26.0, 3925.3999999998873, 2036.8000000000116 - 0.5, 5000.0, 26.5, 4238.226953124912, 2155.3396484374703 - 0.5, 5000.0, 27.0, 4556.809374999892, 2278.454062499966 - 0.5, 5000.0, 27.5, 4880.324609374866, 2405.5126953124636 - 0.5, 5000.0, 28.0, 5207.949999999838, 2535.8849999999593 - 0.5, 5000.0, 28.5, 5538.862890624809, 2668.9404296874563 - 0.5, 5000.0, 29.0, 5872.240624999776, 2804.0484374999537 - 0.5, 5000.0, 29.5, 6207.26054687474, 2940.578476562451 - 0.5, 5000.0, 30.0, 6543.099999999703, 3077.899999999949 - 0.5, 5000.0, 30.5, 6870.310742187691, 3208.856054687499 - 0.5, 5000.0, 31.0, 7197.5171875002125, 3339.9640624999993 - 0.5, 5000.0, 31.5, 7524.7181640627405, 3471.2150390625006 - 0.5, 5000.0, 32.0, 7851.912500000262, 3602.6000000000013 - 0.5, 5000.0, 32.5, 8179.099023437784, 3734.109960937502 - 0.5, 5000.0, 33.0, 8506.276562500305, 3865.7359375000065 - 0.5, 5000.0, 33.5, 8833.443945312822, 3997.4689453125084 - 0.5, 5000.0, 34.0, 9160.600000000339, 4129.300000000012 - 0.5, 5000.0, 34.5, 9487.701718750117, 4261.905898437352 - 0.5, 5000.0, 35.0, 9814.793750000139, 4394.526562499836 - 0.5, 5000.0, 35.5, 10141.87890625017, 4527.0876953123225 - 0.5, 5000.0, 36.0, 10468.96000000021, 4659.5149999998075 - 0.5, 5000.0, 36.5, 10796.039843750254, 4791.734179687297 - 0.5, 5000.0, 37.0, 11123.121250000297, 4923.6709374997845 - 0.5, 5000.0, 37.5, 11450.207031250353, 5055.2509765622735 - 0.5, 5000.0, 38.0, 11777.300000000412, 5186.399999999764 - 0.5, 5000.0, 38.5, 12104.420898436225, 5317.336914062391 - 0.5, 5000.0, 39.0, 12431.545312498522, 5447.542187499837 - 0.5, 5000.0, 39.5, 12758.672070310808, 5576.876367187271 - 0.5, 5000.0, 40.0, 13085.799999998075, 5705.199999999689 - 0.5, 5000.0, 40.5, 13412.893750000243, 5830.130468749776 - 0.5, 5000.0, 41.0, 13740.000000000251, 5954.668749999721 - 0.5, 5000.0, 41.5, 14067.131250000226, 6079.572656249662 - 0.5, 5000.0, 42.0, 14394.300000000167, 6205.599999999604 - 0.5, 5000.0, 42.5, 14721.362499999816, 6334.649218749993 - 0.5, 5000.0, 43.0, 15048.549999999874, 6465.881249999976 - 0.5, 5000.0, 43.5, 15375.93749999995, 6599.597656249947 - 0.5, 5000.0, 44.0, 15703.600000000051, 6736.099999999907 - 0.5, 5000.0, 44.5, 16032.53828125018, 6877.166406250116 - 0.5, 5000.0, 45.0, 16361.531250000256, 7021.031250000137 - 0.5, 5000.0, 45.5, 16690.28359375036, 7167.405468750156 - 0.5, 5000.0, 46.0, 17018.50000000048, 7316.000000000164 - 0.5, 5000.0, 46.5, 17344.36562499947, 7466.799218750068 - 0.5, 5000.0, 47.0, 17669.71249999926, 7619.131250000129 - 0.5, 5000.0, 47.5, 17994.853124999023, 7772.597656250201 - 0.5, 5000.0, 48.0, 18320.099999998736, 7926.80000000029 - 0.5, 5000.0, 48.5, 18645.765624998396, 8081.339843750394 - 0.5, 5000.0, 49.0, 18972.16249999799, 8235.81875000052 - 0.5, 5000.0, 49.5, 19299.60312499753, 8389.838281250655 - 0.5, 5000.0, 50.0, 19628.39999999701, 8543.00000000081 - 0.5, 10000.0, 0.0, 425.9792121979082, 425.9792121979082 - 0.5, 10000.0, 22.0, 883.2000000000015, 863.999999999999 - 0.5, 10000.0, 22.5, 1050.8273437500025, 925.9853515624997 - 0.5, 10000.0, 23.0, 1216.718750000004, 987.4671875000004 - 0.5, 10000.0, 23.5, 1381.4507812500058, 1048.6654296875015 - 0.5, 10000.0, 24.0, 1545.6000000000079, 1109.8000000000025 - 0.5, 10000.0, 24.5, 1709.7429687500107, 1171.090820312504 - 0.5, 10000.0, 25.0, 1874.4562500000134, 1232.7578125000048 - 0.5, 10000.0, 25.5, 2040.316406250017, 1295.0208984375065 - 0.5, 10000.0, 26.0, 2207.90000000002, 1358.1000000000079 - 0.5, 10000.0, 26.5, 2383.83203125, 1424.4162109374952 - 0.5, 10000.0, 27.0, 2562.9862500000017, 1492.1140624999944 - 0.5, 10000.0, 27.5, 2744.902343750005, 1561.0361328124945 - 0.5, 10000.0, 28.0, 2929.1200000000067, 1631.0249999999949 - 0.5, 10000.0, 28.5, 3115.1789062500093, 1701.9232421874945 - 0.5, 10000.0, 29.0, 3302.6187500000137, 1773.5734374999952 - 0.5, 10000.0, 29.5, 3490.9792187500175, 1845.8181640624957 - 0.5, 10000.0, 30.0, 3679.800000000022, 1918.4999999999975 - 0.5, 10000.0, 30.5, 3863.7854492187566, 1989.9870117187625 - 0.5, 10000.0, 31.0, 4047.771093750008, 2061.736718750015 - 0.5, 10000.0, 31.5, 4231.75712890626, 2133.7321289062675 - 0.5, 10000.0, 32.0, 4415.743750000011, 2205.95625000002 - 0.5, 10000.0, 32.5, 4599.731152343762, 2278.392089843774 - 0.5, 10000.0, 33.0, 4783.7195312500135, 2351.022656250027 - 0.5, 10000.0, 33.5, 4967.709082031266, 2423.8309570312804 - 0.5, 10000.0, 34.0, 5151.700000000015, 2496.8000000000347 - 0.5, 10000.0, 34.5, 5335.696992187426, 2569.734374999996 - 0.5, 10000.0, 35.0, 5519.695312499909, 2642.8124999999936 - 0.5, 10000.0, 35.5, 5703.694726562392, 2716.0343749999925 - 0.5, 10000.0, 36.0, 5887.694999999873, 2789.3999999999933 - 0.5, 10000.0, 36.5, 6071.695898437352, 2862.909374999992 - 0.5, 10000.0, 37.0, 6255.6971874998335, 2936.56249999999 - 0.5, 10000.0, 37.5, 6439.6986328123085, 3010.359374999989 - 0.5, 10000.0, 38.0, 6623.699999999783, 3084.299999999987 - 0.5, 10000.0, 38.5, 6807.700000000214, 3158.1048828125877 - 0.5, 10000.0, 39.0, 6991.7000000002545, 3232.1984375001075 - 0.5, 10000.0, 39.5, 7175.700000000299, 3306.6427734376307 - 0.5, 10000.0, 40.0, 7359.700000000345, 3381.5000000001555 - 0.5, 10000.0, 40.5, 7543.703906249999, 3457.182812499996 - 0.5, 10000.0, 41.0, 7727.706250000012, 3533.2624999999985 - 0.5, 10000.0, 41.5, 7911.7054687500295, 3609.6609375000016 - 0.5, 10000.0, 42.0, 8095.700000000051, 3686.300000000008 - 0.5, 10000.0, 42.5, 8279.535937500114, 3762.8281250000105 - 0.5, 10000.0, 43.0, 8463.425000000158, 3839.5500000000156 - 0.5, 10000.0, 43.5, 8647.42656250021, 3916.496875000021 - 0.5, 10000.0, 44.0, 8831.600000000277, 3993.700000000027 - 0.5, 10000.0, 44.5, 9016.582812499973, 4071.4289062499993 - 0.5, 10000.0, 45.0, 9201.624999999975, 4149.381250000005 - 0.5, 10000.0, 45.5, 9386.554687499975, 4227.492968750009 - 0.5, 10000.0, 46.0, 9571.199999999979, 4305.700000000019 - 0.5, 10000.0, 46.5, 9754.529687500097, 4383.395312500003 - 0.5, 10000.0, 47.0, 9937.575000000128, 4461.275000000003 - 0.5, 10000.0, 47.5, 10120.507812500171, 4539.492187500004 - 0.5, 10000.0, 48.0, 10303.500000000218, 4618.200000000003 - 0.5, 10000.0, 48.5, 10486.723437500274, 4697.551562500002 - 0.5, 10000.0, 49.0, 10670.350000000331, 4777.700000000001 - 0.5, 10000.0, 49.5, 10854.551562500395, 4858.798437500001 - 0.5, 10000.0, 50.0, 11039.500000000471, 4941.0 - 0.5, 15000.0, 0.0, 356.2010109608432, 356.2010109608432 - 0.5, 15000.0, 22.0, 793.1000000000004, 742.8000000000008 - 0.5, 15000.0, 22.5, 943.6236328124993, 797.8292968750003 - 0.5, 15000.0, 23.0, 1092.5859374999984, 852.2656249999999 - 0.5, 15000.0, 23.5, 1240.505273437497, 906.3191406249996 - 0.5, 15000.0, 24.0, 1387.8999999999953, 960.1999999999992 - 0.5, 15000.0, 24.5, 1535.288476562493, 1014.118359374999 - 0.5, 15000.0, 25.0, 1683.1890624999899, 1068.2843749999986 - 0.5, 15000.0, 25.5, 1832.1201171874873, 1122.9082031249984 - 0.5, 15000.0, 26.0, 1982.5999999999829, 1178.199999999998 - 0.5, 15000.0, 26.5, 2140.5843750000004, 1236.3085937499989 - 0.5, 15000.0, 27.0, 2301.4650000000015, 1295.6162499999984 - 0.5, 15000.0, 27.5, 2464.828125000002, 1356.0007812499973 - 0.5, 15000.0, 28.0, 2630.260000000003, 1417.3399999999965 - 0.5, 15000.0, 28.5, 2797.346875000004, 1479.5117187499952 - 0.5, 15000.0, 29.0, 2965.6750000000065, 1542.3937499999947 - 0.5, 15000.0, 29.5, 3134.8306250000064, 1605.8639062499938 - 0.5, 15000.0, 30.0, 3304.400000000009, 1669.7999999999927 - 0.5, 15000.0, 30.5, 3469.6270507812515, 1733.08603515625 - 0.5, 15000.0, 31.0, 3634.853906250003, 1796.6882812499996 - 0.5, 15000.0, 31.5, 3800.0803710937557, 1860.579199218749 - 0.5, 15000.0, 32.0, 3965.306250000008, 1924.7312499999978 - 0.5, 15000.0, 32.5, 4130.53134765626, 1989.1168945312475 - 0.5, 15000.0, 33.0, 4295.755468750015, 2053.7085937499965 - 0.5, 15000.0, 33.5, 4460.9784179687695, 2118.4788085937457 - 0.5, 15000.0, 34.0, 4626.200000000023, 2183.3999999999937 - 0.5, 15000.0, 34.5, 4791.412226562442, 2247.998789062483 - 0.5, 15000.0, 35.0, 4956.623437499926, 2312.735937499979 - 0.5, 15000.0, 35.5, 5121.834179687405, 2377.626367187475 - 0.5, 15000.0, 36.0, 5287.044999999882, 2442.6849999999713 - 0.5, 15000.0, 36.5, 5452.256445312355, 2507.9267578124663 - 0.5, 15000.0, 37.0, 5617.469062499827, 2573.3665624999617 - 0.5, 15000.0, 37.5, 5782.683398437293, 2639.0193359374543 - 0.5, 15000.0, 38.0, 5947.899999999757, 2704.89999999995 - 0.5, 15000.0, 38.5, 6113.123632812621, 2771.020312500074 - 0.5, 15000.0, 39.0, 6278.34843750015, 2837.4000000000874 - 0.5, 15000.0, 39.5, 6443.574023437683, 2904.0546875001014 - 0.5, 15000.0, 40.0, 6608.80000000022, 2971.0000000001173 - 0.5, 15000.0, 40.5, 6774.028906249976, 3038.364843750021 - 0.5, 15000.0, 41.0, 6939.256249999969, 3106.0062500000327 - 0.5, 15000.0, 41.5, 7104.4804687499645, 3173.8945312500455 - 0.5, 15000.0, 42.0, 7269.699999999958, 3242.0000000000596 - 0.5, 15000.0, 42.5, 7434.772656250076, 3310.1054687499905 - 0.5, 15000.0, 43.0, 7599.893750000113, 3378.4437499999894 - 0.5, 15000.0, 43.5, 7765.117968750155, 3447.0601562499874 - 0.5, 15000.0, 44.0, 7930.500000000208, 3515.999999999987 - 0.5, 15000.0, 44.5, 8096.621875000074, 3585.4101562500205 - 0.5, 15000.0, 45.0, 8262.800000000105, 3655.1937500000267 - 0.5, 15000.0, 45.5, 8428.878125000141, 3725.355468750032 - 0.5, 15000.0, 46.0, 8594.700000000175, 3795.9000000000356 - 0.5, 15000.0, 46.5, 8759.332031250071, 3866.753906250015 - 0.5, 15000.0, 47.0, 8923.706250000096, 3938.031250000027 - 0.5, 15000.0, 47.5, 9087.977343750124, 4009.7679687500417 - 0.5, 15000.0, 48.0, 9252.300000000156, 4082.000000000059 - 0.5, 15000.0, 48.5, 9416.828906250186, 4154.763281250081 - 0.5, 15000.0, 49.0, 9581.718750000224, 4228.0937500001055 - 0.5, 15000.0, 49.5, 9747.12421875026, 4302.027343750132 - 0.5, 15000.0, 50.0, 9913.2000000003, 4376.600000000166 - 0.5, 20000.0, 0.0, 295.77872042051507, 295.77872042051507 - 0.5, 20000.0, 22.0, 796.6000000000001, 664.6999999999997 - 0.5, 20000.0, 22.5, 947.8068359374986, 719.0548828124995 - 0.5, 20000.0, 23.0, 1097.4453124999957, 772.885937499999 - 0.5, 20000.0, 23.5, 1246.0361328124927, 826.3990234374982 - 0.5, 20000.0, 24.0, 1394.099999999989, 879.7999999999967 - 0.5, 20000.0, 24.5, 1542.1576171874842, 933.2947265624952 - 0.5, 20000.0, 25.0, 1690.729687499978, 987.0890624999935 - 0.5, 20000.0, 25.5, 1840.3369140624714, 1041.388867187491 - 0.5, 20000.0, 26.0, 1991.499999999963, 1096.3999999999885 - 0.5, 20000.0, 26.5, 2150.2042968749997, 1154.2314453125018 - 0.5, 20000.0, 27.0, 2311.8181250000002, 1213.2946875000023 - 0.5, 20000.0, 27.5, 2475.9253906250024, 1273.4693359375028 - 0.5, 20000.0, 28.0, 2642.1100000000038, 1334.6350000000039 - 0.5, 20000.0, 28.5, 2809.955859375007, 1396.6712890625042 - 0.5, 20000.0, 29.0, 2979.04687500001, 1459.4578125000055 - 0.5, 20000.0, 29.5, 3148.9669531250142, 1522.8741796875063 - 0.5, 20000.0, 30.0, 3319.300000000017, 1586.8000000000068 - 0.5, 20000.0, 30.5, 3485.252734375016, 1650.1194335937548 - 0.5, 20000.0, 31.0, 3651.2031250000186, 1713.8023437500055 - 0.5, 20000.0, 31.5, 3817.1519531250224, 1777.8231445312567 - 0.5, 20000.0, 32.0, 3983.100000000025, 1842.1562500000084 - 0.5, 20000.0, 32.5, 4149.048046875028, 1906.7760742187597 - 0.5, 20000.0, 33.0, 4314.996875000033, 1971.6570312500116 - 0.5, 20000.0, 33.5, 4480.9472656250355, 2036.7735351562626 - 0.5, 20000.0, 34.0, 4646.900000000039, 2102.100000000015 - 0.5, 20000.0, 34.5, 4812.875546874994, 2167.110859374982 - 0.5, 20000.0, 35.0, 4978.853124999992, 2232.328124999978 - 0.5, 20000.0, 35.5, 5144.831640624992, 2297.7738281249726 - 0.5, 20000.0, 36.0, 5310.809999999994, 2363.4699999999657 - 0.5, 20000.0, 36.5, 5476.787109374992, 2429.438671874959 - 0.5, 20000.0, 37.0, 5642.761874999997, 2495.7018749999497 - 0.5, 20000.0, 37.5, 5808.733203124998, 2562.2816406249403 - 0.5, 20000.0, 38.0, 5974.699999999999, 2629.19999999993 - 0.5, 20000.0, 38.5, 6140.652734375065, 2696.4884765625256 - 0.5, 20000.0, 39.0, 6306.603125000076, 2764.1546875000304 - 0.5, 20000.0, 39.5, 6472.551953125087, 2832.2185546875353 - 0.5, 20000.0, 40.0, 6638.500000000099, 2900.7000000000407 - 0.5, 20000.0, 40.5, 6804.446093749971, 2969.5359375000235 - 0.5, 20000.0, 41.0, 6970.393749999964, 3038.862500000034 - 0.5, 20000.0, 41.5, 7136.344531249958, 3108.732812500046 - 0.5, 20000.0, 42.0, 7302.299999999952, 3179.200000000063 - 0.5, 20000.0, 42.5, 7468.144531250029, 3250.5124999999894 - 0.5, 20000.0, 43.0, 7634.043750000039, 3322.4499999999844 - 0.5, 20000.0, 43.5, 7800.046093750051, 3394.987499999979 - 0.5, 20000.0, 44.0, 7966.200000000065, 3468.0999999999704 - 0.5, 20000.0, 44.5, 8133.053906249999, 3541.69609375003 - 0.5, 20000.0, 45.0, 8299.956250000012, 3615.843750000043 - 0.5, 20000.0, 45.5, 8466.755468750021, 3690.5445312500583 - 0.5, 20000.0, 46.0, 8633.300000000037, 3765.8000000000775 - 0.5, 20000.0, 46.5, 8798.676562499995, 3841.131249999981 - 0.5, 20000.0, 47.0, 8963.799999999994, 3917.212499999976 - 0.5, 20000.0, 47.5, 9128.823437499987, 3994.2374999999697 - 0.5, 20000.0, 48.0, 9293.899999999981, 4072.3999999999646 - 0.5, 20000.0, 48.5, 9459.18281249998, 4151.8937499999565 - 0.5, 20000.0, 49.0, 9624.824999999975, 4232.91249999995 - 0.5, 20000.0, 49.5, 9790.979687499972, 4315.64999999994 - 0.5, 20000.0, 50.0, 9957.799999999968, 4400.299999999932 - 0.5, 25000.0, 0.0, 243.75549437296687, 243.75549437296687 - 0.5, 25000.0, 22.0, 643.1000000000003, 544.5000000000002 - 0.5, 25000.0, 22.5, 765.083203125001, 587.8562500000004 - 0.5, 25000.0, 23.0, 885.8343750000012, 630.7250000000005 - 0.5, 25000.0, 23.5, 1005.7683593750019, 673.2812500000006 - 0.5, 25000.0, 24.0, 1125.300000000002, 715.7000000000008 - 0.5, 25000.0, 24.5, 1244.844140625003, 758.1562500000013 - 0.5, 25000.0, 25.0, 1364.8156250000036, 800.8250000000014 - 0.5, 25000.0, 25.5, 1485.6292968750047, 843.881250000002 - 0.5, 25000.0, 26.0, 1607.7000000000055, 887.5000000000026 - 0.5, 25000.0, 26.5, 1735.806640624999, 933.5324218749997 - 0.5, 25000.0, 27.0, 1866.2493749999974, 980.5731249999998 - 0.5, 25000.0, 27.5, 1998.6949218749971, 1028.5097656249998 - 0.5, 25000.0, 28.0, 2132.8099999999968, 1077.2299999999996 - 0.5, 25000.0, 28.5, 2268.261328124995, 1126.6214843749997 - 0.5, 25000.0, 29.0, 2404.715624999995, 1176.5718749999996 - 0.5, 25000.0, 29.5, 2541.839609374992, 1226.9688281249998 - 0.5, 25000.0, 30.0, 2679.2999999999906, 1277.6999999999994 - 0.5, 25000.0, 30.5, 2813.2681640624996, 1327.5780273437517 - 0.5, 25000.0, 31.0, 2947.2390625000007, 1377.6679687500018 - 0.5, 25000.0, 31.5, 3081.2123046874995, 1427.9598632812522 - 0.5, 25000.0, 32.0, 3215.1874999999995, 1478.4437500000024 - 0.5, 25000.0, 32.5, 3349.164257812499, 1529.109667968752 - 0.5, 25000.0, 33.0, 3483.142187499999, 1579.9476562500024 - 0.5, 25000.0, 33.5, 3617.1208984374985, 1630.9477539062527 - 0.5, 25000.0, 34.0, 3751.099999999998, 1682.1000000000029 - 0.5, 25000.0, 34.5, 3885.0749999999994, 1732.9789453125018 - 0.5, 25000.0, 35.0, 4019.0499999999984, 1784.0296875000017 - 0.5, 25000.0, 35.5, 4153.024999999998, 1835.2818359375017 - 0.5, 25000.0, 36.0, 4286.999999999997, 1886.7650000000017 - 0.5, 25000.0, 36.5, 4420.974999999996, 1938.5087890625018 - 0.5, 25000.0, 37.0, 4554.949999999994, 1990.5428125000021 - 0.5, 25000.0, 37.5, 4688.924999999995, 2042.896679687501 - 0.5, 25000.0, 38.0, 4822.899999999992, 2095.6000000000013 - 0.5, 25000.0, 38.5, 4956.880273437458, 2148.611718749997 - 0.5, 25000.0, 39.0, 5090.8578124999485, 2202.068749999996 - 0.5, 25000.0, 39.5, 5224.831445312437, 2256.0164062499953 - 0.5, 25000.0, 40.0, 5358.799999999924, 2310.499999999994 - 0.5, 25000.0, 40.5, 5492.751562500009, 2365.8070312500117 - 0.5, 25000.0, 41.0, 5626.700000000011, 2421.6437500000166 - 0.5, 25000.0, 41.5, 5760.648437500009, 2477.9585937500196 - 0.5, 25000.0, 42.0, 5894.600000000008, 2534.700000000025 - 0.5, 25000.0, 42.5, 6028.467968750017, 2591.69140625 - 0.5, 25000.0, 43.0, 6162.381250000017, 2649.05625 - 0.5, 25000.0, 43.5, 6296.37890625002, 2706.79296875 - 0.5, 25000.0, 44.0, 6430.500000000017, 2764.9000000000005 - 0.5, 25000.0, 44.5, 6565.185937500011, 2823.3210937500053 - 0.5, 25000.0, 45.0, 6699.912500000017, 2882.1312500000076 - 0.5, 25000.0, 45.5, 6834.557812500019, 2941.3507812500097 - 0.5, 25000.0, 46.0, 6969.000000000025, 3001.000000000012 - 0.5, 25000.0, 46.5, 7102.511718749998, 3060.802343750014 - 0.5, 25000.0, 47.0, 7235.8187499999985, 3121.1937500000186 - 0.5, 25000.0, 47.5, 7369.041406249997, 3182.313281250022 - 0.5, 25000.0, 48.0, 7502.299999999999, 3244.300000000026 - 0.5, 25000.0, 48.5, 7635.714843749999, 3307.2929687500323 - 0.5, 25000.0, 49.0, 7769.406250000001, 3371.4312500000374 - 0.5, 25000.0, 49.5, 7903.494531250004, 3436.8539062500427 - 0.5, 25000.0, 50.0, 8038.100000000007, 3503.7000000000485 - 0.5, 30000.0, 0.0, 199.2415652647092, 199.2415652647092 - 0.5, 30000.0, 22.0, 503.09999999999997, 443.2999999999995 - 0.5, 30000.0, 22.5, 598.4783203125, 475.9816406249995 - 0.5, 30000.0, 23.0, 692.9234375000007, 508.20937499999974 - 0.5, 30000.0, 23.5, 786.7568359375011, 540.157421875 - 0.5, 30000.0, 24.0, 880.3000000000018, 572.0000000000001 - 0.5, 30000.0, 24.5, 973.8744140625023, 603.9113281250009 - 0.5, 30000.0, 25.0, 1067.8015625000037, 636.065625000001 - 0.5, 30000.0, 25.5, 1162.4029296875044, 668.6371093750021 - 0.5, 30000.0, 26.0, 1258.0000000000057, 701.8000000000028 - 0.5, 30000.0, 26.5, 1358.3240234374991, 737.6548828124993 - 0.5, 30000.0, 27.0, 1460.481562499999, 774.5596874999994 - 0.5, 30000.0, 27.5, 1564.2095703124985, 812.3583984374992 - 0.5, 30000.0, 28.0, 1669.2449999999978, 850.8949999999993 - 0.5, 30000.0, 28.5, 1775.3248046874974, 890.0134765624992 - 0.5, 30000.0, 29.0, 1882.1859374999963, 929.5578124999992 - 0.5, 30000.0, 29.5, 1989.5653515624954, 969.3719921874992 - 0.5, 30000.0, 30.0, 2097.1999999999944, 1009.2999999999995 - 0.5, 30000.0, 30.5, 2202.0525390625066, 1047.3056640624982 - 0.5, 30000.0, 31.0, 2306.8984375000073, 1085.2921874999984 - 0.5, 30000.0, 31.5, 2411.7388671875087, 1123.2826171874979 - 0.5, 30000.0, 32.0, 2516.57500000001, 1161.2999999999975 - 0.5, 30000.0, 32.5, 2621.40800781251, 1199.3673828124968 - 0.5, 30000.0, 33.0, 2726.239062500011, 1237.5078124999964 - 0.5, 30000.0, 33.5, 2831.069335937512, 1275.7443359374956 - 0.5, 30000.0, 34.0, 2935.900000000013, 1314.0999999999947 - 0.5, 30000.0, 34.5, 3040.7732421874944, 1352.2401953124988 - 0.5, 30000.0, 35.0, 3145.645312499994, 1390.579687499999 - 0.5, 30000.0, 35.5, 3250.513476562492, 1429.175585937499 - 0.5, 30000.0, 36.0, 3355.3749999999914, 1468.0849999999987 - 0.5, 30000.0, 36.5, 3460.227148437491, 1507.3650390624987 - 0.5, 30000.0, 37.0, 3565.0671874999884, 1547.072812499999 - 0.5, 30000.0, 37.5, 3669.8923828124875, 1587.2654296874994 - 0.5, 30000.0, 38.0, 3774.6999999999866, 1627.9999999999989 - 0.5, 30000.0, 38.5, 3879.402929687447, 1670.5064453124846 - 0.5, 30000.0, 39.0, 3984.126562499938, 1713.0609374999817 - 0.5, 30000.0, 39.5, 4088.8869140624274, 1755.459960937479 - 0.5, 30000.0, 40.0, 4193.699999999914, 1797.499999999976 - 0.5, 30000.0, 40.5, 4298.696093749999, 1837.8359374999977 - 0.5, 30000.0, 41.0, 4403.731249999997, 1877.8624999999968 - 0.5, 30000.0, 41.5, 4508.775781249995, 1917.832812499995 - 0.5, 30000.0, 42.0, 4613.799999999993, 1957.9999999999932 - 0.5, 30000.0, 42.5, 4718.606249999991, 1998.1328125000005 - 0.5, 30000.0, 43.0, 4823.399999999989, 2039.1625000000001 - 0.5, 30000.0, 43.5, 4928.218749999985, 2081.5359375 - 0.5, 30000.0, 44.0, 5033.099999999982, 2125.6999999999994 - 0.5, 30000.0, 44.5, 5138.374218749978, 2175.4960937499923 - 0.5, 30000.0, 45.0, 5243.668749999975, 2226.61874999999 - 0.5, 30000.0, 45.5, 5348.9039062499705, 2278.157031249987 - 0.5, 30000.0, 46.0, 5453.999999999965, 2329.1999999999857 - 0.5, 30000.0, 46.5, 5558.45546874998, 2375.731249999996 - 0.5, 30000.0, 47.0, 5662.781249999972, 2421.1874999999945 - 0.5, 30000.0, 47.5, 5767.066406249961, 2465.899999999993 - 0.5, 30000.0, 48.0, 5871.399999999946, 2510.1999999999916 - 0.5, 30000.0, 48.5, 5975.871093749931, 2554.418749999989 - 0.5, 30000.0, 49.0, 6080.568749999913, 2598.8874999999875 - 0.5, 30000.0, 49.5, 6185.582031249894, 2643.937499999985 - 0.5, 30000.0, 50.0, 6290.999999999869, 2689.899999999982 - 0.5, 35000.0, 0.0, 161.40831882619423, 161.40831882619423 - 0.5, 35000.0, 22.0, 398.2999999999999, 368.6 - 0.5, 35000.0, 22.5, 474.5220703125002, 388.57343750000064 - 0.5, 35000.0, 23.0, 549.8109375000004, 411.7500000000011 - 0.5, 35000.0, 23.5, 624.4443359375005, 437.6265625000014 - 0.5, 35000.0, 24.0, 698.6999999999999, 465.70000000000164 - 0.5, 35000.0, 24.5, 772.8556640625, 495.4671875000019 - 0.5, 35000.0, 25.0, 847.1890624999997, 526.4250000000017 - 0.5, 35000.0, 25.5, 921.9779296874998, 558.0703125000017 - 0.5, 35000.0, 26.0, 997.4999999999995, 589.9000000000017 - 0.5, 35000.0, 26.5, 1076.8384765624928, 616.5669921875015 - 0.5, 35000.0, 27.0, 1157.6259374999918, 642.1353125000011 - 0.5, 35000.0, 27.5, 1239.659179687491, 666.9322265625013 - 0.5, 35000.0, 28.0, 1322.73499999999, 691.2850000000012 - 0.5, 35000.0, 28.5, 1406.6501953124898, 715.5208984375015 - 0.5, 35000.0, 29.0, 1491.2015624999888, 739.9671875000018 - 0.5, 35000.0, 29.5, 1576.1858984374883, 764.9511328125027 - 0.5, 35000.0, 30.0, 1661.3999999999878, 790.8000000000035 - 0.5, 35000.0, 30.5, 1744.5644531250098, 824.222265624989 - 0.5, 35000.0, 31.0, 1827.7500000000111, 858.5562499999878 - 0.5, 35000.0, 31.5, 1910.951171875013, 893.5214843749868 - 0.5, 35000.0, 32.0, 1994.1625000000151, 928.8374999999859 - 0.5, 35000.0, 32.5, 2077.378515625018, 964.2238281249848 - 0.5, 35000.0, 33.0, 2160.593750000019, 999.3999999999844 - 0.5, 35000.0, 33.5, 2243.802734375021, 1034.0855468749837 - 0.5, 35000.0, 34.0, 2327.000000000023, 1067.9999999999832 - 0.5, 35000.0, 34.5, 2409.9151171875365, 1094.4012890625047 - 0.5, 35000.0, 35.0, 2492.832812500039, 1120.085937500006 - 0.5, 35000.0, 35.5, 2575.7728515625427, 1145.388867187508 - 0.5, 35000.0, 36.0, 2658.755000000045, 1170.6450000000098 - 0.5, 35000.0, 36.5, 2741.799023437547, 1196.1892578125112 - 0.5, 35000.0, 37.0, 2824.9246875000495, 1222.3565625000133 - 0.5, 35000.0, 37.5, 2908.151757812551, 1249.481835937515 - 0.5, 35000.0, 38.0, 2991.5000000000514, 1277.9000000000171 - 0.5, 35000.0, 38.5, 3075.3857421874777, 1304.5330078124632 - 0.5, 35000.0, 39.0, 3159.2265624999773, 1334.8984374999527 - 0.5, 35000.0, 39.5, 3242.9541015624773, 1370.0896484374412 - 0.5, 35000.0, 40.0, 3326.499999999978, 1411.1999999999282 - 0.5, 35000.0, 40.5, 3409.371093750031, 1470.247656249995 - 0.5, 35000.0, 41.0, 3492.0937500000437, 1533.0312499999916 - 0.5, 35000.0, 41.5, 3574.769531250055, 1596.2742187499869 - 0.5, 35000.0, 42.0, 3657.500000000069, 1656.6999999999814 - 0.5, 35000.0, 42.5, 3740.7734374999845, 1705.4890624999798 - 0.5, 35000.0, 43.0, 3824.1499999999673, 1747.1249999999714 - 0.5, 35000.0, 43.5, 3907.5765624999444, 1780.5484374999612 - 0.5, 35000.0, 44.0, 3990.9999999999186, 1804.6999999999505 - 0.5, 35000.0, 44.5, 4074.230468749998, 1802.4265625000146 - 0.5, 35000.0, 45.0, 4157.406250000005, 1795.2000000000214 - 0.5, 35000.0, 45.5, 4240.528906250012, 1788.3984375000293 - 0.5, 35000.0, 46.0, 4323.600000000023, 1787.4000000000397 - 0.5, 35000.0, 46.5, 4406.562499999995, 1816.766406249989 - 0.5, 35000.0, 47.0, 4489.499999999997, 1855.018749999986 - 0.5, 35000.0, 47.5, 4572.437500000004, 1899.8617187499813 - 0.5, 35000.0, 48.0, 4655.400000000011, 1948.9999999999745 - 0.5, 35000.0, 48.5, 4738.41250000002, 2000.1382812499653 - 0.5, 35000.0, 49.0, 4821.500000000033, 2050.981249999954 - 0.5, 35000.0, 49.5, 4904.687500000051, 2099.2335937499392 - 0.5, 35000.0, 50.0, 4988.000000000072, 2142.59999999992 - 0.5, 39000.0, 0.0, 133.87378694612403, 133.87378694612403 - 0.5, 39000.0, 22.0, 317.2000000000003, 311.80000000000075 - 0.5, 39000.0, 22.5, 378.1765624999995, 327.6097656250003 - 0.5, 39000.0, 23.0, 438.28749999999883, 346.83437499999985 - 0.5, 39000.0, 23.5, 497.77968749999854, 368.91679687499953 - 0.5, 39000.0, 24.0, 556.8999999999984, 393.29999999999905 - 0.5, 39000.0, 24.5, 615.8953124999981, 419.4269531249984 - 0.5, 39000.0, 25.0, 675.0124999999983, 446.7406249999978 - 0.5, 39000.0, 25.5, 734.4984374999983, 474.6839843749971 - 0.5, 39000.0, 26.0, 794.5999999999983, 502.69999999999646 - 0.5, 39000.0, 26.5, 858.0960937499984, 525.5175781249983 - 0.5, 39000.0, 27.0, 922.8462499999979, 547.0243749999983 - 0.5, 39000.0, 27.5, 988.6632812499976, 567.4714843749981 - 0.5, 39000.0, 28.0, 1055.3599999999974, 587.109999999998 - 0.5, 39000.0, 28.5, 1122.749218749997, 606.1910156249982 - 0.5, 39000.0, 29.0, 1190.6437499999968, 624.9656249999983 - 0.5, 39000.0, 29.5, 1258.856406249996, 643.6849218749988 - 0.5, 39000.0, 30.0, 1327.1999999999964, 662.599999999999 - 0.5, 39000.0, 30.5, 1393.3947265625034, 685.0680664062451 - 0.5, 39000.0, 31.0, 1459.5453125000035, 707.9382812499946 - 0.5, 39000.0, 31.5, 1525.6638671875053, 731.1659179687434 - 0.5, 39000.0, 32.0, 1591.7625000000064, 754.7062499999925 - 0.5, 39000.0, 32.5, 1657.853320312508, 778.5145507812413 - 0.5, 39000.0, 33.0, 1723.9484375000097, 802.54609374999 - 0.5, 39000.0, 33.5, 1790.059960937511, 826.7561523437384 - 0.5, 39000.0, 34.0, 1856.2000000000132, 851.0999999999872 - 0.5, 39000.0, 34.5, 1922.709609374993, 876.7063671874904 - 0.5, 39000.0, 35.0, 1989.240624999991, 902.2453124999881 - 0.5, 39000.0, 35.5, 2055.773828124988, 927.5603515624856 - 0.5, 39000.0, 36.0, 2122.2899999999854, 952.4949999999826 - 0.5, 39000.0, 36.5, 2188.7699218749804, 976.8927734374796 - 0.5, 39000.0, 37.0, 2255.194374999975, 1000.5971874999765 - 0.5, 39000.0, 37.5, 2321.5441406249697, 1023.4517578124724 - 0.5, 39000.0, 38.0, 2387.799999999963, 1045.299999999968 - 0.5, 39000.0, 38.5, 2453.640039062512, 1060.663476562495 - 0.5, 39000.0, 39.0, 2519.5046875000153, 1077.467187499994 - 0.5, 39000.0, 39.5, 2585.441992187519, 1096.737304687493 - 0.5, 39000.0, 40.0, 2651.5000000000223, 1119.4999999999923 - 0.5, 39000.0, 40.5, 2717.9640624999965, 1150.0578124999956 - 0.5, 39000.0, 41.0, 2784.549999999992, 1184.8499999999951 - 0.5, 39000.0, 41.5, 2851.210937499987, 1223.5921874999951 - 0.5, 39000.0, 42.0, 2917.8999999999824, 1265.9999999999952 - 0.5, 39000.0, 42.5, 2984.2656250000045, 1316.1875000000039 - 0.5, 39000.0, 43.0, 3050.6875000000146, 1367.7125000000044 - 0.5, 39000.0, 43.5, 3117.2406250000254, 1418.5312500000045 - 0.5, 39000.0, 44.0, 3184.0000000000355, 1466.600000000005 - 0.5, 39000.0, 44.5, 3251.876562499997, 1507.5859374999884 - 0.5, 39000.0, 45.0, 3319.7750000000005, 1542.6499999999867 - 0.5, 39000.0, 45.5, 3387.435937500007, 1570.6640624999857 - 0.5, 39000.0, 46.0, 3454.600000000019, 1590.499999999984 - 0.5, 39000.0, 46.5, 3519.515625000022, 1588.244531249991 - 0.5, 39000.0, 47.0, 3584.0125000000253, 1580.668749999985 - 0.5, 39000.0, 47.5, 3648.4281250000286, 1571.7585937499764 - 0.5, 39000.0, 48.0, 3713.1000000000286, 1565.4999999999673 - 0.5, 39000.0, 48.5, 3778.3656250000276, 1565.8789062499548 - 0.5, 39000.0, 49.0, 3844.5625000000236, 1576.8812499999415 - 0.5, 39000.0, 49.5, 3912.028125000017, 1602.492968749925 - 0.5, 39000.0, 50.0, 3981.1000000000085, 1646.6999999999073 - 0.5, 43000.0, 0.0, 110.45906717456974, 110.45906717456974 - 0.5, 43000.0, 22.0, 198.99999999999912, 341.9999999999992 - 0.5, 43000.0, 22.5, 240.03593749999658, 316.0374999999978 - 0.5, 43000.0, 23.0, 280.36249999999336, 298.149999999998 - 0.5, 43000.0, 23.5, 320.1328124999895, 287.3374999999993 - 0.5, 43000.0, 24.0, 359.4999999999846, 282.6000000000017 - 0.5, 43000.0, 24.5, 398.6171874999788, 282.9375000000046 - 0.5, 43000.0, 25.0, 437.6374999999719, 287.3500000000077 - 0.5, 43000.0, 25.5, 476.7140624999636, 294.8375000000108 - 0.5, 43000.0, 26.0, 515.9999999999538, 304.40000000001373 - 0.5, 43000.0, 26.5, 557.0374999999909, 305.37558593749 - 0.5, 43000.0, 27.0, 598.6699999999896, 305.8740624999877 - 0.5, 43000.0, 27.5, 640.8124999999886, 306.5517578124853 - 0.5, 43000.0, 28.0, 683.3799999999882, 308.0649999999827 - 0.5, 43000.0, 28.5, 726.287499999988, 311.07011718748015 - 0.5, 43000.0, 29.0, 769.4499999999884, 316.2234374999776 - 0.5, 43000.0, 29.5, 812.7824999999891, 324.18128906247546 - 0.5, 43000.0, 30.0, 856.1999999999906, 335.59999999997376 - 0.5, 43000.0, 30.5, 898.5937500000337, 359.7458984374801 - 0.5, 43000.0, 31.0, 941.0000000000379, 387.8453124999773 - 0.5, 43000.0, 31.5, 983.4312500000424, 419.7345703124745 - 0.5, 43000.0, 32.0, 1025.9000000000478, 455.2499999999717 - 0.5, 43000.0, 32.5, 1068.4187500000537, 494.2279296874692 - 0.5, 43000.0, 33.0, 1111.0000000000605, 536.5046874999668 - 0.5, 43000.0, 33.5, 1153.6562500000675, 581.9166015624647 - 0.5, 43000.0, 34.0, 1196.4000000000758, 630.2999999999627 - 0.5, 43000.0, 34.5, 1240.2478124999398, 731.9502734374707 - 0.5, 43000.0, 35.0, 1284.1124999999258, 831.439062499966 - 0.5, 43000.0, 35.5, 1327.9109374999086, 923.7970703124608 - 0.5, 43000.0, 36.0, 1371.5599999998897, 1004.0549999999555 - 0.5, 43000.0, 36.5, 1414.9765624998663, 1067.2435546874497 - 0.5, 43000.0, 37.0, 1458.0774999998393, 1108.3934374999444 - 0.5, 43000.0, 37.5, 1500.7796874998087, 1122.5353515624388 - 0.5, 43000.0, 38.0, 1542.999999999773, 1104.6999999999334 - 0.5, 43000.0, 38.5, 1582.642968750079, 985.8732421875525 - 0.5, 43000.0, 39.0, 1622.6812500000965, 858.3390625000691 - 0.5, 43000.0, 39.5, 1663.478906250116, 731.3603515625869 - 0.5, 43000.0, 40.0, 1705.400000000137, 614.2000000001058 - 0.5, 43000.0, 40.5, 1751.6562500000678, 532.6648437499516 - 0.5, 43000.0, 41.0, 1798.6250000000844, 472.8562499999438 - 0.5, 43000.0, 41.5, 1845.5312500001028, 437.41953124993506 - 0.5, 43000.0, 42.0, 1891.6000000001234, 428.9999999999249 - 0.5, 43000.0, 42.5, 1932.3101562499724, 477.87187499994224 - 0.5, 43000.0, 43.0, 1972.1312499999697, 547.9999999999101 - 0.5, 43000.0, 43.5, 2011.7867187499623, 630.9781249998732 - 0.5, 43000.0, 44.0, 2051.999999999949, 718.3999999998327 - 0.5, 43000.0, 44.5, 2096.947656249938, 786.5117187499901 - 0.5, 43000.0, 45.0, 2142.5187499999092, 848.3937499999929 - 0.5, 43000.0, 45.5, 2188.05546874988, 901.7789062499957 - 0.5, 43000.0, 46.0, 2232.8999999998573, 944.3999999999982 - 0.5, 43000.0, 46.5, 2273.5117187498454, 956.7749999999268 - 0.5, 43000.0, 47.0, 2313.268749999792, 960.7374999999147 - 0.5, 43000.0, 47.5, 2352.6664062497257, 960.9062499999018 - 0.5, 43000.0, 48.0, 2392.1999999996433, 961.8999999998874 - 0.5, 43000.0, 48.5, 2432.364843749542, 968.3374999998719 - 0.5, 43000.0, 49.0, 2473.6562499994197, 984.8374999998543 - 0.5, 43000.0, 49.5, 2516.5695312492726, 1016.0187499998358 - 0.5, 43000.0, 50.0, 2561.5999999990963, 1066.4999999998156 - 0.5, 48000.0, 0.0, 86.86281249333541, 86.86281249333541 - 0.5, 48000.0, 22.0, 151.39999999999813, 272.99999999999534 - 0.5, 48000.0, 22.5, 186.58417968750027, 251.46757812499516 - 0.5, 48000.0, 23.0, 220.1390625000035, 236.909374999995 - 0.5, 48000.0, 23.5, 252.34941406250792, 228.42148437499492 - 0.5, 48000.0, 24.0, 283.50000000001353, 225.099999999995 - 0.5, 48000.0, 24.5, 313.87558593752067, 226.04101562499503 - 0.5, 48000.0, 25.0, 343.7609375000292, 230.34062499999513 - 0.5, 48000.0, 25.5, 373.4408203125392, 237.0949218749952 - 0.5, 48000.0, 26.0, 403.20000000005086, 245.39999999999526 - 0.5, 48000.0, 26.5, 435.79785156249216, 245.5267578124928 - 0.5, 48000.0, 27.0, 469.1859374999912, 244.8921874999907 - 0.5, 48000.0, 27.5, 503.2248046874901, 244.10527343748836 - 0.5, 48000.0, 28.0, 537.7749999999886, 243.7749999999857 - 0.5, 48000.0, 28.5, 572.6970703124872, 244.51035156248275 - 0.5, 48000.0, 29.0, 607.8515624999856, 246.92031249997976 - 0.5, 48000.0, 29.5, 643.0990234374834, 251.61386718747653 - 0.5, 48000.0, 30.0, 678.2999999999815, 259.1999999999731 - 0.5, 48000.0, 30.5, 711.4344726562235, 278.57490234373057 - 0.5, 48000.0, 31.0, 744.4226562499673, 301.2710937499766 - 0.5, 48000.0, 31.5, 777.3041992187104, 327.10830078122234 - 0.5, 48000.0, 32.0, 810.1187499999521, 355.90624999996714 - 0.5, 48000.0, 32.5, 842.9059570311933, 387.48466796871145 - 0.5, 48000.0, 33.0, 875.7054687499336, 421.66328124995533 - 0.5, 48000.0, 33.5, 908.5569335936732, 458.26181640619836 - 0.5, 48000.0, 34.0, 941.4999999999121, 497.09999999994096 - 0.5, 48000.0, 34.5, 975.9323437499758, 576.3967968749719 - 0.5, 48000.0, 35.0, 1010.4062499999745, 653.9156249999678 - 0.5, 48000.0, 35.5, 1044.8320312499732, 725.8191406249626 - 0.5, 48000.0, 36.0, 1079.119999999971, 788.2699999999566 - 0.5, 48000.0, 36.5, 1113.1804687499682, 837.430859374949 - 0.5, 48000.0, 37.0, 1146.923749999965, 869.4643749999412 - 0.5, 48000.0, 37.5, 1180.2601562499601, 880.5332031249316 - 0.5, 48000.0, 38.0, 1213.0999999999544, 866.7999999999197 - 0.5, 48000.0, 38.5, 1242.9320312500802, 775.0775390624426 - 0.5, 48000.0, 39.0, 1273.343750000096, 676.4671874999328 - 0.5, 48000.0, 39.5, 1304.7835937501143, 578.0982421874231 - 0.5, 48000.0, 40.0, 1337.7000000001372, 487.0999999999144 - 0.5, 48000.0, 40.5, 1376.2601562499824, 422.91328124997455 - 0.5, 48000.0, 41.0, 1415.7062499999788, 375.43124999996974 - 0.5, 48000.0, 41.5, 1454.9992187499756, 346.85859374996545 - 0.5, 48000.0, 42.0, 1493.099999999973, 339.3999999999612 - 0.5, 48000.0, 42.5, 1524.207812499982, 377.11171875004356 - 0.5, 48000.0, 43.0, 1553.9499999999734, 431.60625000005473 - 0.5, 48000.0, 43.5, 1583.1921874999632, 496.3476562500646 - 0.5, 48000.0, 44.0, 1612.7999999999518, 564.8000000000732 - 0.5, 48000.0, 44.5, 1646.853906250033, 618.8687499999903 - 0.5, 48000.0, 45.0, 1681.7187500000484, 668.199999999989 - 0.5, 48000.0, 45.5, 1716.974218750065, 710.8812499999877 - 0.5, 48000.0, 46.0, 1752.200000000081, 744.9999999999876 - 0.5, 48000.0, 46.5, 1785.6671875000002, 754.4093750000516 - 0.5, 48000.0, 47.0, 1818.787499999986, 757.1250000000682 - 0.5, 48000.0, 47.5, 1851.6640624999734, 756.928125000089 - 0.5, 48000.0, 48.0, 1884.399999999966, 757.6000000001143 - 0.5, 48000.0, 48.5, 1917.0984374999648, 762.9218750001448 - 0.5, 48000.0, 49.0, 1949.8624999999734, 776.6750000001808 - 0.5, 48000.0, 49.5, 1982.795312499994, 802.6406250002227 - 0.5, 48000.0, 50.0, 2016.0000000000273, 844.6000000002715 - 0.55, 0.0, 0.0, 615.8565044228885, 615.8565044228885 - 0.55, 0.0, 22.0, 1351.8999999999987, 1354.6999999999878 - 0.55, 0.0, 22.5, 1608.315429687442, 1520.5376953124764 - 0.55, 0.0, 23.0, 1861.0390624998602, 1630.1609374999769 - 0.55, 0.0, 23.5, 2111.143164062249, 1694.8537109374881 - 0.55, 0.0, 24.0, 2359.6999999996096, 1725.9000000000071 - 0.55, 0.0, 24.5, 2607.7818359369357, 1734.5837890625348 - 0.55, 0.0, 25.0, 2856.4609374992247, 1732.1890625000688 - 0.55, 0.0, 25.5, 3106.809570311475, 1729.9998046876062 - 0.55, 0.0, 26.0, 3359.8999999986863, 1739.3000000001507 - 0.55, 0.0, 26.5, 3627.8869140626202, 1878.1837890625366 - 0.55, 0.0, 27.0, 3901.3934375001636, 2057.228437500066 - 0.55, 0.0, 27.5, 4179.591992187718, 2269.4076171876086 - 0.55, 0.0, 28.0, 4461.655000000287, 2507.695000000159 - 0.55, 0.0, 28.5, 4746.754882812869, 2765.064257812718 - 0.55, 0.0, 29.0, 5034.064062500467, 3034.489062500291 - 0.55, 0.0, 29.5, 5322.75496093808, 3308.943085937871 - 0.55, 0.0, 30.0, 5612.000000000714, 3581.400000000466 - 0.55, 0.0, 30.5, 5891.707812499936, 3757.2880859371357 - 0.55, 0.0, 31.0, 6171.196874999946, 3925.464062499572 - 0.55, 0.0, 31.5, 6450.521874999954, 4087.2392578120034 - 0.55, 0.0, 32.0, 6729.737499999966, 4243.924999999433 - 0.55, 0.0, 32.5, 7008.898437499977, 4396.832617186861 - 0.55, 0.0, 33.0, 7288.059374999987, 4547.273437499286 - 0.55, 0.0, 33.5, 7567.274999999998, 4696.55878906171 - 0.55, 0.0, 34.0, 7846.600000000009, 4845.999999999136 - 0.55, 0.0, 34.5, 8126.9708984356175, 5106.927070311813 - 0.55, 0.0, 35.0, 8407.476562497523, 5360.15468749923 - 0.55, 0.0, 35.5, 8688.087695309348, 5596.516210936641 - 0.55, 0.0, 36.0, 8968.774999996092, 5806.8449999990535 - 0.55, 0.0, 36.5, 9249.50917968275, 5981.97441406147 - 0.55, 0.0, 37.0, 9530.260937494322, 6112.737812498879 - 0.55, 0.0, 37.5, 9811.0009765558, 6189.968554686284 - 0.55, 0.0, 38.0, 10091.699999992192, 6204.499999998687 - 0.55, 0.0, 38.5, 10372.355078128654, 6064.914648438282 - 0.55, 0.0, 39.0, 10652.896875004844, 5886.945312500981 - 0.55, 0.0, 39.5, 10933.290234381253, 5679.703320313725 - 0.55, 0.0, 40.0, 11213.500000007893, 5452.300000001519 - 0.55, 0.0, 40.5, 11493.672656250577, 5199.484374999745 - 0.55, 0.0, 41.0, 11773.518750000747, 4950.474999999647 - 0.55, 0.0, 41.5, 12052.930468750881, 4720.128124999519 - 0.55, 0.0, 42.0, 12331.80000000094, 4523.299999999359 - 0.55, 0.0, 42.5, 12608.433593749503, 4397.659374999233 - 0.55, 0.0, 43.0, 12884.943749999358, 4326.124999999003 - 0.55, 0.0, 43.5, 13161.857031249252, 4314.428124998743 - 0.55, 0.0, 44.0, 13439.699999999219, 4368.299999998449 - 0.55, 0.0, 44.5, 13721.901562498677, 4545.550000000255 - 0.55, 0.0, 45.0, 14004.92499999793, 4779.000000000369 - 0.55, 0.0, 45.5, 14288.135937496934, 5053.550000000548 - 0.55, 0.0, 46.0, 14570.899999995649, 5354.100000000798 - 0.55, 0.0, 46.5, 14849.87578124761, 5640.624218748667 - 0.55, 0.0, 47.0, 15128.218749996982, 5932.9187499981435 - 0.55, 0.0, 47.5, 15406.377343746322, 6225.853906247544 - 0.55, 0.0, 48.0, 15684.799999995657, 6514.299999996872 - 0.55, 0.0, 48.5, 15963.935156244996, 6793.127343746134 - 0.55, 0.0, 49.0, 16244.231249994367, 7057.206249995325 - 0.55, 0.0, 49.5, 16526.13671874378, 7301.407031244451 - 0.55, 0.0, 50.0, 16810.099999993265, 7520.5999999935175 - 0.55, 2000.0, 0.0, 576.6078161882878, 576.6078161882878 - 0.55, 2000.0, 22.0, -3019.8999999999833, -263.7000000000012 - 0.55, 2000.0, 22.5, -3590.693945312518, -459.2326171875 - 0.55, 2000.0, 23.0, -4155.848437500062, -640.0765625000007 - 0.55, 2000.0, 23.5, -4717.303710937613, -810.0822265625031 - 0.55, 2000.0, 24.0, -5277.000000000177, -973.1000000000064 - 0.55, 2000.0, 24.5, -5836.877539062757, -1132.9802734375112 - 0.55, 2000.0, 25.0, -6398.876562500346, -1293.5734375000154 - 0.55, 2000.0, 25.5, -6964.937304687957, -1458.72988281252 - 0.55, 2000.0, 26.0, -7537.000000000586, -1632.3000000000234 - 0.55, 2000.0, 26.5, -8137.48671874988, -1857.5884765624473 - 0.55, 2000.0, 27.0, -8749.026249999853, -2101.2459374999257 - 0.55, 2000.0, 27.5, -9370.047656249824, -2360.3591796874 - 0.55, 2000.0, 28.0, -9998.979999999796, -2632.01499999987 - 0.55, 2000.0, 28.5, -10634.252343749758, -2913.3001953123357 - 0.55, 2000.0, 29.0, -11274.293749999724, -3201.301562499797 - 0.55, 2000.0, 29.5, -11917.533281249685, -3493.105898437253 - 0.55, 2000.0, 30.0, -12562.39999999964, -3785.799999999701 - 0.55, 2000.0, 30.5, -13190.850683593477, -4035.0682617187717 - 0.55, 2000.0, 31.0, -13819.35546874968, -4283.342968750012 - 0.55, 2000.0, 31.5, -14447.912207030862, -4531.654003906251 - 0.55, 2000.0, 32.0, -15076.518749999548, -4781.031249999989 - 0.55, 2000.0, 32.5, -15705.172949218228, -5032.504589843727 - 0.55, 2000.0, 33.0, -16333.872656249405, -5287.10390624996 - 0.55, 2000.0, 33.5, -16962.615722655562, -5545.8590820311965 - 0.55, 2000.0, 34.0, -17591.39999999921, -5809.799999999927 - 0.55, 2000.0, 34.5, -18220.8758984365, -6139.790546874963 - 0.55, 2000.0, 35.0, -18850.32656249889, -6471.32812499999 - 0.55, 2000.0, 35.5, -19479.687695311284, -6799.744140625016 - 0.55, 2000.0, 36.0, -20108.89499999868, -7120.370000000048 - 0.55, 2000.0, 36.5, -20737.88417968606, -7428.537109375084 - 0.55, 2000.0, 37.0, -21366.590937498448, -7719.576875000119 - 0.55, 2000.0, 37.5, -21994.950976560835, -7988.820703125155 - 0.55, 2000.0, 38.0, -22622.89999999822, -8231.600000000197 - 0.55, 2000.0, 38.5, -23249.196679684563, -8402.629101562294 - 0.55, 2000.0, 39.0, -23875.56406249636, -8558.917187499806 - 0.55, 2000.0, 39.5, -24502.199414058065, -8704.82167968732 - 0.55, 2000.0, 40.0, -25129.29999999466, -8844.699999999852 - 0.55, 2000.0, 40.5, -25758.067968749197, -8972.08437499974 - 0.55, 2000.0, 41.0, -26387.29374999895, -9106.48749999957 - 0.55, 2000.0, 41.5, -27016.772656248653, -9256.596874999348 - 0.55, 2000.0, 42.0, -27646.299999998333, -9431.099999999053 - 0.55, 2000.0, 42.5, -28274.682812499246, -9667.782031249684 - 0.55, 2000.0, 43.0, -28903.099999998725, -9934.593749999593 - 0.55, 2000.0, 43.5, -29531.74218749804, -10228.583593749476 - 0.55, 2000.0, 44.0, -30160.799999997187, -10546.799999999346 - 0.55, 2000.0, 44.5, -30792.35468749771, -10889.15468749975 - 0.55, 2000.0, 45.0, -31423.949999997087, -11248.687499999676 - 0.55, 2000.0, 45.5, -32055.020312496403, -11621.301562499608 - 0.55, 2000.0, 46.0, -32684.999999995693, -12002.899999999547 - 0.55, 2000.0, 46.5, -33310.296093751866, -12379.362500000037 - 0.55, 2000.0, 47.0, -33934.58125000231, -12760.62499999997 - 0.55, 2000.0, 47.5, -34558.50078125275, -13146.59999999989 - 0.55, 2000.0, 48.0, -35182.70000000314, -13537.199999999793 - 0.55, 2000.0, 48.5, -35807.824218753456, -13932.337499999678 - 0.55, 2000.0, 49.0, -36434.51875000367, -14331.924999999552 - 0.55, 2000.0, 49.5, -37063.428906253794, -14735.874999999412 - 0.55, 2000.0, 50.0, -37695.20000000376, -15144.099999999258 - 0.55, 5000.0, 0.0, 521.464339203493, 521.464339203493 - 0.55, 5000.0, 22.0, 3144.899999999995, 1828.800000000007 - 0.55, 5000.0, 22.5, 3742.5929687499884, 2037.9353515624955 - 0.55, 5000.0, 23.0, 4333.84374999998, 2240.9296874999905 - 0.55, 5000.0, 23.5, 4920.747656249964, 2439.8091796874887 - 0.55, 5000.0, 24.0, 5505.399999999943, 2636.59999999999 - 0.55, 5000.0, 24.5, 6089.8960937499205, 2833.3283203124965 - 0.55, 5000.0, 25.0, 6676.33124999989, 3032.0203125000025 - 0.55, 5000.0, 25.5, 7266.800781249849, 3234.7021484375136 - 0.55, 5000.0, 26.0, 7863.399999999806, 3443.400000000024 - 0.55, 5000.0, 26.5, 8490.101953124866, 3680.5890624999506 - 0.55, 5000.0, 27.0, 9128.374374999821, 3929.0149999999444 - 0.55, 5000.0, 27.5, 9776.562109374783, 4187.19843749994 - 0.55, 5000.0, 28.0, 10433.009999999742, 4453.659999999937 - 0.55, 5000.0, 28.5, 11096.062890624687, 4726.920312499935 - 0.55, 5000.0, 29.0, 11764.065624999634, 5005.4999999999345 - 0.55, 5000.0, 29.5, 12435.36304687457, 5287.9196874999325 - 0.55, 5000.0, 30.0, 13108.299999999503, 5572.699999999933 - 0.55, 5000.0, 30.5, 13763.87294921903, 5844.327246093756 - 0.55, 5000.0, 31.0, 14419.42734375032, 6116.692968750006 - 0.55, 5000.0, 31.5, 15074.960253906602, 6389.654394531257 - 0.55, 5000.0, 32.0, 15730.468750000387, 6663.06875000001 - 0.55, 5000.0, 32.5, 16385.949902344164, 6936.793261718766 - 0.55, 5000.0, 33.0, 17041.400781250442, 7210.685156250021 - 0.55, 5000.0, 33.5, 17696.81845703172, 7484.601660156276 - 0.55, 5000.0, 34.0, 18352.20000000049, 7758.400000000038 - 0.55, 5000.0, 34.5, 19007.397695312575, 8034.194492187276 - 0.55, 5000.0, 35.0, 19662.567187500095, 8309.370312499757 - 0.55, 5000.0, 35.5, 20317.719335937632, 8583.56972656224 - 0.55, 5000.0, 36.0, 20972.865000000158, 8856.434999999725 - 0.55, 5000.0, 36.5, 21628.01503906271, 9127.608398437213 - 0.55, 5000.0, 37.0, 22283.180312500244, 9396.732187499703 - 0.55, 5000.0, 37.5, 22938.371679687803, 9663.448632812202 - 0.55, 5000.0, 38.0, 23593.600000000362, 9927.399999999696 - 0.55, 5000.0, 38.5, 24248.97949218521, 10187.21816406235 - 0.55, 5000.0, 39.0, 24904.36406249736, 10444.079687499763 - 0.55, 5000.0, 39.5, 25559.741601559464, 10697.851367187148 - 0.55, 5000.0, 40.0, 26215.09999999655, 10948.399999999503 - 0.55, 5000.0, 40.5, 26870.26015625041, 11189.376562499601 - 0.55, 5000.0, 41.0, 27525.443750000413, 11429.349999999493 - 0.55, 5000.0, 41.5, 28180.705468750373, 11670.673437499387 - 0.55, 5000.0, 42.0, 28836.100000000282, 11915.699999999284 - 0.55, 5000.0, 42.5, 29491.54921874956, 12170.73203124993 - 0.55, 5000.0, 43.0, 30147.29374999962, 12432.593749999878 - 0.55, 5000.0, 43.5, 30803.44140624971, 12702.05859374982 - 0.55, 5000.0, 44.0, 31460.099999999835, 12979.899999999734 - 0.55, 5000.0, 44.5, 32119.084375000315, 13270.55546875019 - 0.55, 5000.0, 45.0, 32778.11250000045, 13569.668750000219 - 0.55, 5000.0, 45.5, 33436.60937500061, 13876.547656250239 - 0.55, 5000.0, 46.0, 34094.000000000815, 14190.50000000024 - 0.55, 5000.0, 46.5, 34746.69374999901, 14512.7710937501 - 0.55, 5000.0, 47.0, 35398.33749999863, 14839.956250000192 - 0.55, 5000.0, 47.5, 36049.56249999819, 15170.588281250302 - 0.55, 5000.0, 48.0, 36700.99999999764, 15503.200000000441 - 0.55, 5000.0, 48.5, 37353.28124999702, 15836.324218750602 - 0.55, 5000.0, 49.0, 38007.03749999628, 16168.493750000795 - 0.55, 5000.0, 49.5, 38662.89999999545, 16498.24140625101 - 0.55, 5000.0, 50.0, 39321.49999999447, 16824.100000001243 - 0.55, 10000.0, 0.0, 438.88680830671694, 438.88680830671694 - 0.55, 10000.0, 22.0, 856.3000000000034, 921.999999999998 - 0.55, 10000.0, 22.5, 1018.8009765625064, 983.7931640624996 - 0.55, 10000.0, 23.0, 1179.6296875000107, 1045.6671875000013 - 0.55, 10000.0, 23.5, 1339.3435546875153, 1107.7326171875043 - 0.55, 10000.0, 24.0, 1498.5000000000211, 1170.1000000000067 - 0.55, 10000.0, 24.5, 1657.6564453125275, 1232.8798828125105 - 0.55, 10000.0, 25.0, 1817.3703125000354, 1296.1828125000134 - 0.55, 10000.0, 25.5, 1978.1990234375435, 1360.119335937518 - 0.55, 10000.0, 26.0, 2140.7000000000544, 1424.8000000000222 - 0.55, 10000.0, 26.5, 2311.282226562502, 1491.5001953124913 - 0.55, 10000.0, 27.0, 2484.985937500005, 1559.2321874999907 - 0.55, 10000.0, 27.5, 2661.36542968751, 1627.90683593749 - 0.55, 10000.0, 28.0, 2839.9750000000145, 1697.4349999999909 - 0.55, 10000.0, 28.5, 3020.3689453125216, 1767.7275390624916 - 0.55, 10000.0, 29.0, 3202.101562500028, 1838.6953124999934 - 0.55, 10000.0, 29.5, 3384.7271484375374, 1910.2491796874956 - 0.55, 10000.0, 30.0, 3567.800000000045, 1982.299999999999 - 0.55, 10000.0, 30.5, 3746.1965820312685, 2054.255371093775 - 0.55, 10000.0, 31.0, 3924.594531250022, 2126.5773437500297 - 0.55, 10000.0, 31.5, 4102.993652343776, 2199.2247070312837 - 0.55, 10000.0, 32.0, 4281.393750000032, 2272.156250000039 - 0.55, 10000.0, 32.5, 4459.794628906286, 2345.330761718794 - 0.55, 10000.0, 33.0, 4638.196093750041, 2418.70703125005 - 0.55, 10000.0, 33.5, 4816.597949218797, 2492.2438476563057 - 0.55, 10000.0, 34.0, 4995.000000000052, 2565.9000000000624 - 0.55, 10000.0, 34.5, 5173.406562499857, 2638.950546875008 - 0.55, 10000.0, 35.0, 5351.812499999823, 2712.10312500001 - 0.55, 10000.0, 35.5, 5530.217187499783, 2785.381640625013 - 0.55, 10000.0, 36.0, 5708.619999999744, 2858.8100000000154 - 0.55, 10000.0, 36.5, 5887.020312499697, 2932.412109375019 - 0.55, 10000.0, 37.0, 6065.417499999649, 3006.2118750000227 - 0.55, 10000.0, 37.5, 6243.810937499599, 3080.233203125026 - 0.55, 10000.0, 38.0, 6422.199999999543, 3154.500000000029 - 0.55, 10000.0, 38.5, 6600.572460937999, 3229.048828125188 - 0.55, 10000.0, 39.0, 6778.945312500592, 3303.8843750002284 - 0.55, 10000.0, 39.5, 6957.320507813196, 3379.0277343752764 - 0.55, 10000.0, 40.0, 7135.700000000811, 3454.50000000033 - 0.55, 10000.0, 40.5, 7314.094531249997, 3530.468749999987 - 0.55, 10000.0, 41.0, 7492.493750000029, 3606.7499999999914 - 0.55, 10000.0, 41.5, 7670.896093750069, 3683.306249999998 - 0.55, 10000.0, 42.0, 7849.300000000118, 3760.100000000007 - 0.55, 10000.0, 42.5, 8027.563281250222, 3836.9179687500077 - 0.55, 10000.0, 43.0, 8205.881250000322, 3913.968750000014 - 0.55, 10000.0, 43.5, 8384.30859375043, 3991.2851562500223 - 0.55, 10000.0, 44.0, 8562.90000000056, 4068.900000000031 - 0.55, 10000.0, 44.5, 8742.260937499947, 4147.146874999995 - 0.55, 10000.0, 45.0, 8921.674999999952, 4225.6375000000035 - 0.55, 10000.0, 45.5, 9100.976562499962, 4304.284375000016 - 0.55, 10000.0, 46.0, 9279.999999999976, 4383.000000000036 - 0.55, 10000.0, 46.5, 9457.747656250194, 4461.239843749996 - 0.55, 10000.0, 47.0, 9635.218750000275, 4539.556249999993 - 0.55, 10000.0, 47.5, 9812.580468750366, 4618.044531249991 - 0.55, 10000.0, 48.0, 9990.000000000473, 4696.799999999988 - 0.55, 10000.0, 48.5, 10167.644531250593, 4775.9179687499845 - 0.55, 10000.0, 49.0, 10345.681250000727, 4855.493749999981 - 0.55, 10000.0, 49.5, 10524.277343750875, 4935.622656249976 - 0.55, 10000.0, 50.0, 10703.600000001037, 5016.3999999999705 - 0.55, 15000.0, 0.0, 366.99425779396773, 366.99425779396773 - 0.55, 15000.0, 22.0, 772.6, 792.0999999999992 - 0.55, 15000.0, 22.5, 919.2095703125002, 846.8390624999992 - 0.55, 15000.0, 23.0, 1064.3109375000008, 901.5999999999983 - 0.55, 15000.0, 23.5, 1208.406835937501, 956.4859374999976 - 0.55, 15000.0, 24.0, 1352.000000000002, 1011.5999999999963 - 0.55, 15000.0, 24.5, 1495.5931640625029, 1067.0453124999945 - 0.55, 15000.0, 25.0, 1639.689062500004, 1122.9249999999922 - 0.55, 15000.0, 25.5, 1784.7904296875047, 1179.3421874999897 - 0.55, 15000.0, 26.0, 1931.4000000000058, 1236.3999999999862 - 0.55, 15000.0, 26.5, 2085.2978515625023, 1295.2050781250016 - 0.55, 15000.0, 27.0, 2242.0109375000025, 1354.914375000001 - 0.55, 15000.0, 27.5, 2401.1373046875024, 1415.458984375001 - 0.55, 15000.0, 28.0, 2562.275000000002, 1476.7700000000007 - 0.55, 15000.0, 28.5, 2725.0220703125015, 1538.7785156250004 - 0.55, 15000.0, 29.0, 2888.976562500001, 1601.4156249999999 - 0.55, 15000.0, 29.5, 3053.736523437499, 1664.6124218749987 - 0.55, 15000.0, 30.0, 3218.899999999996, 1728.2999999999981 - 0.55, 15000.0, 30.5, 3379.846582031261, 1792.083789062495 - 0.55, 15000.0, 31.0, 3540.7945312500115, 1856.2515624999935 - 0.55, 15000.0, 31.5, 3701.743652343765, 1920.7654296874923 - 0.55, 15000.0, 32.0, 3862.6937500000167, 1985.5874999999912 - 0.55, 15000.0, 32.5, 4023.6446289062687, 2050.6798828124893 - 0.55, 15000.0, 33.0, 4184.596093750021, 2116.0046874999884 - 0.55, 15000.0, 33.5, 4345.547949218778, 2181.524023437488 - 0.55, 15000.0, 34.0, 4506.500000000028, 2247.1999999999857 - 0.55, 15000.0, 34.5, 4667.4500000000635, 2312.340937499987 - 0.55, 15000.0, 35.0, 4828.400000000079, 2377.6249999999836 - 0.55, 15000.0, 35.5, 4989.350000000098, 2443.07656249998 - 0.55, 15000.0, 36.0, 5150.3000000001175, 2508.7199999999757 - 0.55, 15000.0, 36.5, 5311.250000000143, 2574.5796874999714 - 0.55, 15000.0, 37.0, 5472.200000000171, 2640.679999999966 - 0.55, 15000.0, 37.5, 5633.150000000198, 2707.0453124999626 - 0.55, 15000.0, 38.0, 5794.100000000231, 2773.699999999957 - 0.55, 15000.0, 38.5, 5955.0499999998965, 2840.830859375058 - 0.55, 15000.0, 39.0, 6115.999999999875, 2908.2156250000703 - 0.55, 15000.0, 39.5, 6276.94999999985, 2975.842578125083 - 0.55, 15000.0, 40.0, 6437.8999999998205, 3043.700000000096 - 0.55, 15000.0, 40.5, 6598.850000000011, 3111.739062500023 - 0.55, 15000.0, 41.0, 6759.800000000011, 3180.0000000000305 - 0.55, 15000.0, 41.5, 6920.75000000001, 3248.4859375000374 - 0.55, 15000.0, 42.0, 7081.700000000009, 3317.2000000000453 - 0.55, 15000.0, 42.5, 7242.525000000025, 3386.1296875000216 - 0.55, 15000.0, 43.0, 7403.40000000004, 3455.300000000029 - 0.55, 15000.0, 43.5, 7564.375000000053, 3524.7203125000397 - 0.55, 15000.0, 44.0, 7725.500000000073, 3594.40000000005 - 0.55, 15000.0, 44.5, 7887.3250000000735, 3664.4617187500035 - 0.55, 15000.0, 45.0, 8049.200000000095, 3734.7562500000035 - 0.55, 15000.0, 45.5, 8210.975000000124, 3805.247656250003 - 0.55, 15000.0, 46.0, 8372.500000000153, 3875.900000000002 - 0.55, 15000.0, 46.5, 8532.875000000051, 3946.32578125 - 0.55, 15000.0, 47.0, 8693.000000000067, 4016.9812500000003 - 0.55, 15000.0, 47.5, 8853.025000000089, 4087.97109375 - 0.55, 15000.0, 48.0, 9013.100000000115, 4159.399999999995 - 0.55, 15000.0, 48.5, 9173.375000000142, 4231.372656249995 - 0.55, 15000.0, 49.0, 9334.000000000178, 4303.993749999991 - 0.55, 15000.0, 49.5, 9495.12500000022, 4377.367968749984 - 0.55, 15000.0, 50.0, 9656.900000000265, 4451.59999999998 - 0.55, 20000.0, 0.0, 304.74111142797705, 304.74111142797705 - 0.55, 20000.0, 22.0, 784.9000000000013, 709.3000000000005 - 0.55, 20000.0, 22.5, 933.7998046875027, 764.0068359375001 - 0.55, 20000.0, 23.0, 1081.1765625000041, 818.8078124999996 - 0.55, 20000.0, 23.5, 1227.5400390625055, 873.8048828124986 - 0.55, 20000.0, 24.0, 1373.400000000007, 929.0999999999975 - 0.55, 20000.0, 24.5, 1519.266210937509, 984.7951171874963 - 0.55, 20000.0, 25.0, 1665.6484375000111, 1040.9921874999948 - 0.55, 20000.0, 25.5, 1813.056445312514, 1097.7931640624922 - 0.55, 20000.0, 26.0, 1962.000000000017, 1155.2999999999895 - 0.55, 20000.0, 26.5, 2118.3455078124953, 1214.660546875 - 0.55, 20000.0, 27.0, 2277.5521874999936, 1274.9906249999985 - 0.55, 20000.0, 27.5, 2439.2115234374905, 1336.2128906249975 - 0.55, 20000.0, 28.0, 2602.914999999988, 1398.249999999996 - 0.55, 20000.0, 28.5, 2768.2541015624847, 1461.0246093749945 - 0.55, 20000.0, 29.0, 2934.82031249998, 1524.4593749999922 - 0.55, 20000.0, 29.5, 3102.205117187475, 1588.4769531249904 - 0.55, 20000.0, 30.0, 3269.999999999969, 1652.9999999999882 - 0.55, 20000.0, 30.5, 3433.5111328125267, 1717.4077148437548 - 0.55, 20000.0, 31.0, 3597.02343750003, 1782.2179687500056 - 0.55, 20000.0, 31.5, 3760.536523437534, 1847.4051757812565 - 0.55, 20000.0, 32.0, 3924.050000000037, 1912.9437500000074 - 0.55, 20000.0, 32.5, 4087.5634765625414, 1978.808105468759 - 0.55, 20000.0, 33.0, 4251.076562500046, 2044.972656250011 - 0.55, 20000.0, 33.5, 4414.588867187549, 2111.411816406263 - 0.55, 20000.0, 34.0, 4578.100000000054, 2178.100000000014 - 0.55, 20000.0, 34.5, 4741.60300781259, 2244.576445312513 - 0.55, 20000.0, 35.0, 4905.10468750011, 2311.292187500016 - 0.55, 20000.0, 35.5, 5068.605273437633, 2378.263085937519 - 0.55, 20000.0, 36.0, 5232.105000000159, 2445.505000000023 - 0.55, 20000.0, 36.5, 5395.604101562688, 2513.033789062527 - 0.55, 20000.0, 37.0, 5559.102812500218, 2580.8653125000305 - 0.55, 20000.0, 37.5, 5722.601367187753, 2649.015429687535 - 0.55, 20000.0, 38.0, 5886.1000000002905, 2717.5000000000405 - 0.55, 20000.0, 38.5, 6049.599999999858, 2786.446679687519 - 0.55, 20000.0, 39.0, 6213.0999999998285, 2855.7015625000236 - 0.55, 20000.0, 39.5, 6376.5999999997985, 2925.25566406253 - 0.55, 20000.0, 40.0, 6540.0999999997675, 2995.100000000038 - 0.55, 20000.0, 40.5, 6703.600000000013, 3065.0468750000236 - 0.55, 20000.0, 41.0, 6867.100000000026, 3135.3375000000315 - 0.55, 20000.0, 41.5, 7030.600000000042, 3206.0343750000416 - 0.55, 20000.0, 42.0, 7194.100000000061, 3277.200000000052 - 0.55, 20000.0, 42.5, 7357.471093750006, 3348.9906250000236 - 0.55, 20000.0, 43.0, 7520.893750000015, 3421.3375000000296 - 0.55, 20000.0, 43.5, 7684.419531250025, 3494.2656250000364 - 0.55, 20000.0, 44.0, 7848.10000000004, 3567.800000000044 - 0.55, 20000.0, 44.5, 8012.498437500019, 3641.946093749994 - 0.55, 20000.0, 45.0, 8176.950000000023, 3716.7562499999867 - 0.55, 20000.0, 45.5, 8341.301562500024, 3792.263281249977 - 0.55, 20000.0, 46.0, 8505.40000000002, 3868.4999999999636 - 0.55, 20000.0, 46.5, 8668.330468750073, 3944.940624999998 - 0.55, 20000.0, 47.0, 8831.006250000088, 4022.4000000000024 - 0.55, 20000.0, 47.5, 8993.578906250104, 4101.134375000007 - 0.55, 20000.0, 48.0, 9156.200000000124, 4181.400000000012 - 0.55, 20000.0, 48.5, 9319.021093750143, 4263.453125000022 - 0.55, 20000.0, 49.0, 9482.193750000155, 4347.55000000003 - 0.55, 20000.0, 49.5, 9645.86953125017, 4433.9468750000415 - 0.55, 20000.0, 50.0, 9810.200000000186, 4522.900000000054 - 0.55, 25000.0, 0.0, 251.14152960796204, 251.14152960796204 - 0.55, 25000.0, 22.0, 633.7000000000003, 580.7000000000004 - 0.55, 25000.0, 22.5, 753.9525390625018, 623.9623046875007 - 0.55, 25000.0, 23.0, 872.9796875000034, 667.3515625000008 - 0.55, 25000.0, 23.5, 991.1919921875049, 710.9400390625012 - 0.55, 25000.0, 24.0, 1109.0000000000066, 754.8000000000021 - 0.55, 25000.0, 24.5, 1226.814257812508, 799.0037109375029 - 0.55, 25000.0, 25.0, 1345.0453125000101, 843.6234375000041 - 0.55, 25000.0, 25.5, 1464.103710937513, 888.7314453125055 - 0.55, 25000.0, 26.0, 1584.4000000000162, 934.4000000000074 - 0.55, 25000.0, 26.5, 1710.660937499996, 981.5025390625012 - 0.55, 25000.0, 27.0, 1839.227499999995, 1029.3559375000016 - 0.55, 25000.0, 27.5, 1969.7703124999935, 1077.8951171875024 - 0.55, 25000.0, 28.0, 2101.959999999991, 1127.055000000003 - 0.55, 25000.0, 28.5, 2235.467187499989, 1176.7705078125039 - 0.55, 25000.0, 29.0, 2369.9624999999864, 1226.9765625000048 - 0.55, 25000.0, 29.5, 2505.116562499983, 1277.608085937506 - 0.55, 25000.0, 30.0, 2640.59999999998, 1328.600000000007 - 0.55, 25000.0, 30.5, 2772.6229492187467, 1379.359765625002 - 0.55, 25000.0, 31.0, 2904.646093749996, 1430.4000000000015 - 0.55, 25000.0, 31.5, 3036.669628906245, 1481.7058593750016 - 0.55, 25000.0, 32.0, 3168.6937499999954, 1533.2625000000014 - 0.55, 25000.0, 32.5, 3300.718652343743, 1585.0550781250013 - 0.55, 25000.0, 33.0, 3432.744531249992, 1637.0687500000013 - 0.55, 25000.0, 33.5, 3564.7715820312405, 1689.2886718750012 - 0.55, 25000.0, 34.0, 3696.7999999999884, 1741.700000000001 - 0.55, 25000.0, 34.5, 3828.837773437526, 1793.6160546875099 - 0.55, 25000.0, 35.0, 3960.8765625000296, 1845.7578125000114 - 0.55, 25000.0, 35.5, 4092.9158203125335, 1898.174414062513 - 0.55, 25000.0, 36.0, 4224.955000000038, 1950.915000000015 - 0.55, 25000.0, 36.5, 4356.993554687542, 2004.0287109375163 - 0.55, 25000.0, 37.0, 4489.030937500046, 2057.5646875000193 - 0.55, 25000.0, 37.5, 4621.06660156255, 2111.5720703125203 - 0.55, 25000.0, 38.0, 4753.100000000052, 2166.100000000024 - 0.55, 25000.0, 38.5, 4885.121093749858, 2221.8705078124844 - 0.55, 25000.0, 39.0, 5017.143749999828, 2277.9109374999803 - 0.55, 25000.0, 39.5, 5149.169531249794, 2334.120898437476 - 0.55, 25000.0, 40.0, 5281.199999999757, 2390.399999999972 - 0.55, 25000.0, 40.5, 5413.252343750017, 2446.127343750028 - 0.55, 25000.0, 41.0, 5545.306250000014, 2501.9312500000383 - 0.55, 25000.0, 41.5, 5677.357031250011, 2557.9195312500497 - 0.55, 25000.0, 42.0, 5809.400000000005, 2614.2000000000644 - 0.55, 25000.0, 42.5, 5941.297656250052, 2671.052343750003 - 0.55, 25000.0, 43.0, 6073.231250000058, 2728.343750000005 - 0.55, 25000.0, 43.5, 6205.249218750067, 2786.1132812500064 - 0.55, 25000.0, 44.0, 6337.400000000071, 2844.4000000000083 - 0.55, 25000.0, 44.5, 6470.181250000025, 2903.321093750007 - 0.55, 25000.0, 45.0, 6603.012500000028, 2962.8062500000087 - 0.55, 25000.0, 45.5, 6735.7625000000335, 3022.8632812500114 - 0.55, 25000.0, 46.0, 6868.300000000041, 3083.500000000014 - 0.55, 25000.0, 46.5, 6999.845312499962, 3144.173437500021 - 0.55, 25000.0, 47.0, 7131.174999999949, 3205.662500000027 - 0.55, 25000.0, 47.5, 7262.41718749994, 3268.1953125000327 - 0.55, 25000.0, 48.0, 7393.699999999926, 3332.0000000000396 - 0.55, 25000.0, 48.5, 7525.1515624999165, 3397.3046875000464 - 0.55, 25000.0, 49.0, 7656.899999999904, 3464.337500000053 - 0.55, 25000.0, 49.5, 7789.073437499896, 3533.326562500061 - 0.55, 25000.0, 50.0, 7921.799999999886, 3604.500000000069 - 0.55, 30000.0, 0.0, 205.2787839337951, 205.2787839337951 - 0.55, 30000.0, 22.0, 503.4, 473.4 - 0.55, 30000.0, 22.5, 598.9484375, 506.8980468749999 - 0.55, 30000.0, 23.0, 693.5124999999999, 540.6031249999999 - 0.55, 30000.0, 23.5, 787.4203124999998, 574.5566406249999 - 0.55, 30000.0, 24.0, 880.9999999999999, 608.7999999999997 - 0.55, 30000.0, 24.5, 974.5796874999996, 643.3746093749999 - 0.55, 30000.0, 25.0, 1068.4874999999997, 678.3218749999997 - 0.55, 30000.0, 25.5, 1163.0515624999991, 713.6832031249997 - 0.55, 30000.0, 26.0, 1258.5999999999992, 749.4999999999997 - 0.55, 30000.0, 26.5, 1358.9076171875004, 786.3277343750002 - 0.55, 30000.0, 27.0, 1461.0528125000008, 823.7231250000002 - 0.55, 30000.0, 27.5, 1564.7728515625008, 861.6394531250002 - 0.55, 30000.0, 28.0, 1669.805000000001, 900.0300000000002 - 0.55, 30000.0, 28.5, 1775.8865234375012, 938.8480468750001 - 0.55, 30000.0, 29.0, 1882.7546875000014, 978.0468750000002 - 0.55, 30000.0, 29.5, 1990.1467578125014, 1017.5797656250003 - 0.55, 30000.0, 30.0, 2097.800000000002, 1057.4000000000005 - 0.55, 30000.0, 30.5, 2202.69091796875, 1097.1569335937502 - 0.55, 30000.0, 31.0, 2307.580468750001, 1137.1367187500005 - 0.55, 30000.0, 31.5, 2412.468847656251, 1177.3215820312503 - 0.55, 30000.0, 32.0, 2517.3562500000007, 1217.6937500000004 - 0.55, 30000.0, 32.5, 2622.2428710937506, 1258.2354492187505 - 0.55, 30000.0, 33.0, 2727.128906250001, 1298.9289062500006 - 0.55, 30000.0, 33.5, 2832.0145507812513, 1339.7563476562505 - 0.55, 30000.0, 34.0, 2936.900000000001, 1380.7000000000007 - 0.55, 30000.0, 34.5, 3041.784218749998, 1421.3430078124989 - 0.55, 30000.0, 35.0, 3146.6687499999975, 1462.104687499999 - 0.55, 30000.0, 35.5, 3251.553906249997, 1503.0052734374988 - 0.55, 30000.0, 36.0, 3356.439999999997, 1544.0649999999985 - 0.55, 30000.0, 36.5, 3461.327343749996, 1585.3041015624983 - 0.55, 30000.0, 37.0, 3566.2162499999963, 1626.7428124999983 - 0.55, 30000.0, 37.5, 3671.107031249996, 1668.4013671874982 - 0.55, 30000.0, 38.0, 3775.9999999999955, 1710.299999999998 - 0.55, 30000.0, 38.5, 3880.8986328125015, 1752.6044921875023 - 0.55, 30000.0, 39.0, 3985.798437500002, 1795.114062500003 - 0.55, 30000.0, 39.5, 4090.699023437502, 1837.8166015625036 - 0.55, 30000.0, 40.0, 4195.600000000002, 1880.7000000000044 - 0.55, 30000.0, 40.5, 4300.503906250003, 1923.600781250001 - 0.55, 30000.0, 41.0, 4405.406250000004, 1966.7187500000016 - 0.55, 30000.0, 41.5, 4510.305468750004, 2010.1023437500019 - 0.55, 30000.0, 42.0, 4615.200000000005, 2053.8000000000025 - 0.55, 30000.0, 42.5, 4719.998437499999, 2097.9890625000003 - 0.55, 30000.0, 43.0, 4824.824999999999, 2142.537500000001 - 0.55, 30000.0, 43.5, 4929.714062499998, 2187.442187500001 - 0.55, 30000.0, 44.0, 5034.699999999998, 2232.7000000000007 - 0.55, 30000.0, 44.5, 5140.145312499998, 2278.2374999999993 - 0.55, 30000.0, 45.0, 5245.624999999998, 2324.149999999999 - 0.55, 30000.0, 45.5, 5351.042187499998, 2370.4624999999987 - 0.55, 30000.0, 46.0, 5456.299999999998, 2417.1999999999985 - 0.55, 30000.0, 46.5, 5560.8171875000035, 2463.9695312499994 - 0.55, 30000.0, 47.0, 5665.175000000005, 2511.381249999999 - 0.55, 30000.0, 47.5, 5769.470312500006, 2559.627343749999 - 0.55, 30000.0, 48.0, 5873.800000000007, 2608.8999999999987 - 0.55, 30000.0, 48.5, 5978.260937500008, 2659.3914062499985 - 0.55, 30000.0, 49.0, 6082.95000000001, 2711.2937499999985 - 0.55, 30000.0, 49.5, 6187.964062500011, 2764.7992187499976 - 0.55, 30000.0, 50.0, 6293.400000000012, 2820.0999999999976 - 0.55, 35000.0, 0.0, 166.29915229494674, 166.29915229494674 - 0.55, 35000.0, 22.0, 387.99999999999994, 392.5 - 0.55, 35000.0, 22.5, 461.772265625, 416.08261718750003 - 0.55, 35000.0, 23.0, 534.7593749999997, 440.83906250000035 - 0.55, 35000.0, 23.5, 607.2167968749998, 466.6259765625003 - 0.55, 35000.0, 24.0, 679.3999999999996, 493.3000000000003 - 0.55, 35000.0, 24.5, 751.5644531249997, 520.7177734375003 - 0.55, 35000.0, 25.0, 823.9656249999997, 548.7359375000001 - 0.55, 35000.0, 25.5, 896.8589843749997, 577.2111328125001 - 0.55, 35000.0, 26.0, 970.5, 606.0000000000001 - 0.55, 35000.0, 26.5, 1047.804687499998, 633.6740234375004 - 0.55, 35000.0, 27.0, 1126.5199999999977, 661.3015625000005 - 0.55, 35000.0, 27.5, 1206.4453124999975, 688.9595703125003 - 0.55, 35000.0, 28.0, 1287.3799999999976, 716.7250000000004 - 0.55, 35000.0, 28.5, 1369.1234374999972, 744.6748046875006 - 0.55, 35000.0, 29.0, 1451.4749999999972, 772.8859375000006 - 0.55, 35000.0, 29.5, 1534.2340624999965, 801.4353515625008 - 0.55, 35000.0, 30.0, 1617.1999999999966, 830.4000000000015 - 0.55, 35000.0, 30.5, 1698.0758789062518, 861.585644531247 - 0.55, 35000.0, 31.0, 1778.957031250002, 893.1757812499965 - 0.55, 35000.0, 31.5, 1859.842480468753, 925.0827148437461 - 0.55, 35000.0, 32.0, 1940.7312500000028, 957.2187499999959 - 0.55, 35000.0, 32.5, 2021.6223632812532, 989.4961914062452 - 0.55, 35000.0, 33.0, 2102.5148437500043, 1021.827343749995 - 0.55, 35000.0, 33.5, 2183.407714843754, 1054.1245117187448 - 0.55, 35000.0, 34.0, 2264.3000000000043, 1086.2999999999945 - 0.55, 35000.0, 34.5, 2345.1386328125063, 1116.4085156250017 - 0.55, 35000.0, 35.0, 2425.9796875000065, 1146.3968750000022 - 0.55, 35000.0, 35.5, 2506.827148437507, 1176.3542968750028 - 0.55, 35000.0, 36.0, 2587.6850000000068, 1206.370000000004 - 0.55, 35000.0, 36.5, 2668.5572265625055, 1236.5332031250048 - 0.55, 35000.0, 37.0, 2749.4478125000064, 1266.933125000005 - 0.55, 35000.0, 37.5, 2830.3607421875054, 1297.658984375006 - 0.55, 35000.0, 38.0, 2911.3000000000047, 1328.8000000000068 - 0.55, 35000.0, 38.5, 2992.3613281249845, 1359.5003906249863 - 0.55, 35000.0, 39.0, 3073.4093749999834, 1391.2843749999827 - 0.55, 35000.0, 39.5, 3154.4277343749823, 1424.4511718749789 - 0.55, 35000.0, 40.0, 3235.399999999982, 1459.2999999999745 - 0.55, 35000.0, 40.5, 3316.1984375000065, 1498.9992187499972 - 0.55, 35000.0, 41.0, 3396.962500000009, 1539.8312499999956 - 0.55, 35000.0, 41.5, 3477.7203125000115, 1580.947656249994 - 0.55, 35000.0, 42.0, 3558.500000000014, 1621.499999999992 - 0.55, 35000.0, 42.5, 3639.399999999993, 1659.4523437499954 - 0.55, 35000.0, 43.0, 3720.349999999987, 1695.6187499999933 - 0.55, 35000.0, 43.5, 3801.3499999999804, 1729.6257812499912 - 0.55, 35000.0, 44.0, 3882.399999999971, 1761.099999999989 - 0.55, 35000.0, 44.5, 3963.636718749995, 1784.5390625000025 - 0.55, 35000.0, 45.0, 4044.868749999996, 1806.7500000000036 - 0.55, 35000.0, 45.5, 4126.041406249998, 1829.4109375000055 - 0.55, 35000.0, 46.0, 4207.1, 1854.200000000008 - 0.55, 35000.0, 46.5, 4287.685156249998, 1888.697656249997 - 0.55, 35000.0, 47.0, 4368.168749999997, 1926.318749999996 - 0.55, 35000.0, 47.5, 4448.617968749998, 1966.3804687499949 - 0.55, 35000.0, 48.0, 4529.1, 2008.1999999999928 - 0.55, 35000.0, 48.5, 4609.682031250003, 2051.094531249991 - 0.55, 35000.0, 49.0, 4690.431250000005, 2094.3812499999876 - 0.55, 35000.0, 49.5, 4771.41484375001, 2137.3773437499826 - 0.55, 35000.0, 50.0, 4852.700000000015, 2179.3999999999764 - 0.55, 39000.0, 0.0, 137.9302965643785, 137.9302965643785 - 0.55, 39000.0, 22.0, 310.7000000000001, 338.20000000000033 - 0.55, 39000.0, 22.5, 369.90683593749986, 357.6955078125002 - 0.55, 39000.0, 23.0, 428.43281249999984, 378.1234375 - 0.55, 39000.0, 23.5, 486.4923828124999, 399.36464843749985 - 0.55, 39000.0, 24.0, 544.3, 421.2999999999996 - 0.55, 39000.0, 24.5, 602.0701171875003, 443.8103515624995 - 0.55, 39000.0, 25.0, 660.0171875000008, 466.776562499999 - 0.55, 39000.0, 25.5, 718.3556640625013, 490.0794921874988 - 0.55, 39000.0, 26.0, 777.3000000000018, 513.5999999999985 - 0.55, 39000.0, 26.5, 839.2986328124996, 536.3070312499993 - 0.55, 39000.0, 27.0, 902.4596874999995, 558.9412499999992 - 0.55, 39000.0, 27.5, 966.6146484374993, 581.539843749999 - 0.55, 39000.0, 28.0, 1031.5949999999998, 604.1399999999987 - 0.55, 39000.0, 28.5, 1097.2322265624996, 626.7789062499988 - 0.55, 39000.0, 29.0, 1163.3578124999992, 649.4937499999987 - 0.55, 39000.0, 29.5, 1229.8032421874993, 672.3217187499989 - 0.55, 39000.0, 30.0, 1296.3999999999992, 695.2999999999987 - 0.55, 39000.0, 30.5, 1361.1732421875001, 718.9751953124987 - 0.55, 39000.0, 31.0, 1425.9328125000004, 742.8265624999984 - 0.55, 39000.0, 31.5, 1490.6822265625008, 766.8427734374983 - 0.55, 39000.0, 32.0, 1555.4250000000006, 791.012499999998 - 0.55, 39000.0, 32.5, 1620.1646484375017, 815.3244140624976 - 0.55, 39000.0, 33.0, 1684.9046875000017, 839.7671874999975 - 0.55, 39000.0, 33.5, 1749.6486328125025, 864.3294921874968 - 0.55, 39000.0, 34.0, 1814.4000000000021, 888.9999999999966 - 0.55, 39000.0, 34.5, 1879.2525390624958, 914.0142968749955 - 0.55, 39000.0, 35.0, 1944.1109374999953, 939.0906249999947 - 0.55, 39000.0, 35.5, 2008.970117187494, 964.1941406249935 - 0.55, 39000.0, 36.0, 2073.8249999999925, 989.2899999999926 - 0.55, 39000.0, 36.5, 2138.6705078124915, 1014.3433593749911 - 0.55, 39000.0, 37.0, 2203.5015624999896, 1039.3193749999898 - 0.55, 39000.0, 37.5, 2268.3130859374874, 1064.183203124988 - 0.55, 39000.0, 38.0, 2333.0999999999844, 1088.899999999987 - 0.55, 39000.0, 38.5, 2397.778125000003, 1112.0880859374954 - 0.55, 39000.0, 39.0, 2462.462500000004, 1135.7578124999945 - 0.55, 39000.0, 39.5, 2527.165625000006, 1160.1736328124935 - 0.55, 39000.0, 40.0, 2591.900000000008, 1185.5999999999926 - 0.55, 39000.0, 40.5, 2656.736718749999, 1213.087499999998 - 0.55, 39000.0, 41.0, 2721.6062499999985, 1241.7999999999972 - 0.55, 39000.0, 41.5, 2786.497656249998, 1271.687499999997 - 0.55, 39000.0, 42.0, 2851.399999999998, 1302.6999999999964 - 0.55, 39000.0, 42.5, 2916.196874999998, 1336.0335937499995 - 0.55, 39000.0, 43.0, 2981.0250000000005, 1369.8937499999995 - 0.55, 39000.0, 43.5, 3045.9156250000033, 1403.7320312499996 - 0.55, 39000.0, 44.0, 3110.900000000005, 1436.999999999999 - 0.55, 39000.0, 44.5, 3176.3570312499946, 1468.594531249997 - 0.55, 39000.0, 45.0, 3241.8312499999947, 1498.7437499999962 - 0.55, 39000.0, 45.5, 3307.214843749994, 1527.1210937499957 - 0.55, 39000.0, 46.0, 3372.3999999999946, 1553.3999999999955 - 0.55, 39000.0, 46.5, 3436.6851562500065, 1573.3476562499975 - 0.55, 39000.0, 47.0, 3500.793750000006, 1592.1062499999964 - 0.55, 39000.0, 47.5, 3564.8554687500073, 1610.9117187499944 - 0.55, 39000.0, 48.0, 3629.000000000008, 1630.999999999992 - 0.55, 39000.0, 48.5, 3693.3570312500087, 1653.607031249989 - 0.55, 39000.0, 49.0, 3758.056250000008, 1679.968749999986 - 0.55, 39000.0, 49.5, 3823.2273437500066, 1711.3210937499816 - 0.55, 39000.0, 50.0, 3889.000000000005, 1748.8999999999776 - 0.55, 43000.0, 0.0, 113.80608736902636, 113.80608736902636 - 0.55, 43000.0, 22.0, 222.5999999999996, 333.2999999999995 - 0.55, 43000.0, 22.5, 266.5080078124986, 327.086718749999 - 0.55, 43000.0, 23.0, 309.8234374999972, 325.4687499999992 - 0.55, 43000.0, 23.5, 352.70214843749557, 327.89140625000016 - 0.55, 43000.0, 24.0, 395.2999999999934, 333.8000000000015 - 0.55, 43000.0, 24.5, 437.77285156249076, 342.63984375000314 - 0.55, 43000.0, 25.0, 480.27656249998773, 353.8562500000047 - 0.55, 43000.0, 25.5, 522.9669921874842, 366.8945312500065 - 0.55, 43000.0, 26.0, 565.9999999999797, 381.20000000000806 - 0.55, 43000.0, 26.5, 611.0585937499952, 391.0541015624957 - 0.55, 43000.0, 27.0, 656.8587499999946, 400.77093749999466 - 0.55, 43000.0, 27.5, 703.2945312499942, 410.6810546874935 - 0.55, 43000.0, 28.0, 750.259999999994, 421.1149999999921 - 0.55, 43000.0, 28.5, 797.6492187499935, 432.4033203124908 - 0.55, 43000.0, 29.0, 845.3562499999933, 444.87656249998935 - 0.55, 43000.0, 29.5, 893.2751562499935, 458.865273437488 - 0.55, 43000.0, 30.0, 941.2999999999938, 474.69999999998674 - 0.55, 43000.0, 30.5, 988.14072265627, 497.2627929687424 - 0.55, 43000.0, 31.0, 1034.9882812500227, 521.8992187499916 - 0.55, 43000.0, 31.5, 1081.8495117187754, 548.5063476562406 - 0.55, 43000.0, 32.0, 1128.731250000029, 576.9812499999898 - 0.55, 43000.0, 32.5, 1175.6403320312822, 607.2209960937394 - 0.55, 43000.0, 33.0, 1222.5835937500367, 639.1226562499888 - 0.55, 43000.0, 33.5, 1269.5678710937914, 672.5833007812388 - 0.55, 43000.0, 34.0, 1316.6000000000463, 707.4999999999883 - 0.55, 43000.0, 34.5, 1364.2253515624714, 769.698671874987 - 0.55, 43000.0, 35.0, 1411.8609374999648, 830.6781249999849 - 0.55, 43000.0, 35.5, 1459.462304687457, 887.8660156249828 - 0.55, 43000.0, 36.0, 1506.984999999947, 938.6899999999811 - 0.55, 43000.0, 36.5, 1554.384570312436, 980.577734374979 - 0.55, 43000.0, 37.0, 1601.616562499923, 1010.9568749999778 - 0.55, 43000.0, 37.5, 1648.6365234374077, 1027.2550781249763 - 0.55, 43000.0, 38.0, 1695.3999999998907, 1026.8999999999755 - 0.55, 43000.0, 38.5, 1740.7941406250488, 973.7095703125276 - 0.55, 43000.0, 39.0, 1786.3968750000583, 916.1484375000352 - 0.55, 43000.0, 39.5, 1832.4011718750683, 859.1130859375428 - 0.55, 43000.0, 40.0, 1879.0000000000787, 807.5000000000521 - 0.55, 43000.0, 40.5, 1927.8921875000424, 774.6851562499772 - 0.55, 43000.0, 41.0, 1977.1625000000533, 753.6937499999747 - 0.55, 43000.0, 41.5, 2026.4015625000657, 746.0304687499716 - 0.55, 43000.0, 42.0, 2075.20000000008, 753.1999999999681 - 0.55, 43000.0, 42.5, 2121.1562499999964, 792.0195312499789 - 0.55, 43000.0, 43.0, 2166.649999999998, 842.5562499999645 - 0.55, 43000.0, 43.5, 2212.068749999997, 900.189843749948 - 0.55, 43000.0, 44.0, 2257.7999999999943, 960.29999999993 - 0.55, 43000.0, 44.5, 2306.1179687499707, 1009.7703124999923 - 0.55, 43000.0, 45.0, 2354.7687499999556, 1055.8749999999932 - 0.55, 43000.0, 45.5, 2403.385156249941, 1097.392187499994 - 0.55, 43000.0, 46.0, 2451.5999999999285, 1133.0999999999951 - 0.55, 43000.0, 46.5, 2497.4249999999265, 1152.7101562499695 - 0.55, 43000.0, 47.0, 2542.762499999901, 1167.6937499999647 - 0.55, 43000.0, 47.5, 2587.8937499998697, 1180.4554687499594 - 0.55, 43000.0, 48.0, 2633.0999999998303, 1193.3999999999542 - 0.55, 43000.0, 48.5, 2678.6624999997803, 1208.9320312499478 - 0.55, 43000.0, 49.0, 2724.8624999997182, 1229.4562499999404 - 0.55, 43000.0, 49.5, 2771.9812499996438, 1257.3773437499324 - 0.55, 43000.0, 50.0, 2820.2999999995554, 1295.0999999999237 - 0.55, 48000.0, 0.0, 89.49484257469594, 89.49484257469594 - 0.55, 48000.0, 22.0, 172.49999999999903, 264.4999999999978 - 0.55, 48000.0, 22.5, 208.59765625000028, 258.9906249999976 - 0.55, 48000.0, 23.0, 243.65625000000222, 257.43749999999756 - 0.55, 48000.0, 23.5, 277.8867187500048, 259.3406249999977 - 0.55, 48000.0, 24.0, 311.5000000000081, 264.19999999999783 - 0.55, 48000.0, 24.5, 344.7070312500122, 271.51562499999807 - 0.55, 48000.0, 25.0, 377.71875000001717, 280.78749999999843 - 0.55, 48000.0, 25.5, 410.746093750023, 291.51562499999886 - 0.55, 48000.0, 26.0, 444.0000000000298, 303.1999999999994 - 0.55, 48000.0, 26.5, 479.6396484374959, 310.61699218749646 - 0.55, 48000.0, 27.0, 516.0390624999952, 317.72031249999526 - 0.55, 48000.0, 27.5, 553.0751953124942, 324.81972656249377 - 0.55, 48000.0, 28.0, 590.6249999999933, 332.2249999999922 - 0.55, 48000.0, 28.5, 628.5654296874924, 340.24589843749044 - 0.55, 48000.0, 29.0, 666.7734374999907, 349.1921874999885 - 0.55, 48000.0, 29.5, 705.1259765624895, 359.3736328124863 - 0.55, 48000.0, 30.0, 743.4999999999876, 371.0999999999841 - 0.55, 48000.0, 30.5, 780.2548828124861, 389.07998046874184 - 0.55, 48000.0, 31.0, 816.9296874999828, 408.80546874999004 - 0.55, 48000.0, 31.5, 853.545898437479, 430.1672851562383 - 0.55, 48000.0, 32.0, 890.1249999999743, 453.0562499999861 - 0.55, 48000.0, 32.5, 926.6884765624698, 477.3631835937337 - 0.55, 48000.0, 33.0, 963.2578124999649, 502.978906249981 - 0.55, 48000.0, 33.5, 999.8544921874592, 529.7942382812281 - 0.55, 48000.0, 34.0, 1036.4999999999527, 557.6999999999748 - 0.55, 48000.0, 34.5, 1073.9360546874889, 606.2798437499869 - 0.55, 48000.0, 35.0, 1111.395312499989, 653.856249999985 - 0.55, 48000.0, 35.5, 1148.8306640624885, 698.4445312499829 - 0.55, 48000.0, 36.0, 1186.1949999999867, 738.0599999999802 - 0.55, 48000.0, 36.5, 1223.4412109374857, 770.7179687499772 - 0.55, 48000.0, 37.0, 1260.5221874999838, 794.4337499999738 - 0.55, 48000.0, 37.5, 1297.3908203124813, 807.2226562499695 - 0.55, 48000.0, 38.0, 1333.9999999999777, 807.0999999999651 - 0.55, 48000.0, 38.5, 1369.0306640625301, 766.1958984374697 - 0.55, 48000.0, 39.0, 1404.367187500036, 721.8328124999638 - 0.55, 48000.0, 39.5, 1440.2451171875432, 677.7783203124568 - 0.55, 48000.0, 40.0, 1476.9000000000522, 637.7999999999504 - 0.55, 48000.0, 40.5, 1516.5195312499955, 611.9554687499909 - 0.55, 48000.0, 41.0, 1556.6062499999953, 595.20624999999 - 0.55, 48000.0, 41.5, 1596.614843749995, 588.803906249989 - 0.55, 48000.0, 42.0, 1635.9999999999955, 593.9999999999885 - 0.55, 48000.0, 42.5, 1671.7124999999926, 624.1671875000229 - 0.55, 48000.0, 43.0, 1706.7124999999878, 663.5875000000291 - 0.55, 48000.0, 43.5, 1741.456249999982, 708.6640625000347 - 0.55, 48000.0, 44.0, 1776.3999999999753, 755.8000000000397 - 0.55, 48000.0, 44.5, 1813.7187500000193, 794.9765625000055 - 0.55, 48000.0, 45.0, 1851.462500000028, 831.5875000000079 - 0.55, 48000.0, 45.5, 1889.4000000000376, 864.6046875000105 - 0.55, 48000.0, 46.0, 1927.3000000000468, 893.000000000014 - 0.55, 48000.0, 46.5, 1964.1890625000015, 908.2453125000294 - 0.55, 48000.0, 47.0, 2000.8749999999932, 919.8125000000396 - 0.55, 48000.0, 47.5, 2037.423437499986, 929.6734375000525 - 0.55, 48000.0, 48.0, 2073.899999999982, 939.8000000000678 - 0.55, 48000.0, 48.5, 2110.3703124999815, 952.1640625000863 - 0.55, 48000.0, 49.0, 2146.899999999985, 968.7375000001083 - 0.55, 48000.0, 49.5, 2183.554687499995, 991.4921875001332 - 0.55, 48000.0, 50.0, 2220.4000000000137, 1022.4000000001625 - 0.6000000000000001, 0.0, 0.0, 636.1094831925469, 636.1094831925469 - 0.6000000000000001, 0.0, 22.0, 1409.9999999999995, 1479.8999999999808 - 0.6000000000000001, 0.0, 22.5, 1677.5515624999268, 1697.8218749999655 - 0.6000000000000001, 0.0, 23.0, 1940.4999999998133, 1820.8374999999683 - 0.6000000000000001, 0.0, 23.5, 2200.0984374996556, 1867.8593749999868 - 0.6000000000000001, 0.0, 24.0, 2457.5999999994515, 1857.8000000000209 - 0.6000000000000001, 0.0, 24.5, 2714.257812499196, 1809.5718750000674 - 0.6000000000000001, 0.0, 25.0, 2971.324999998889, 1742.0875000001215 - 0.6000000000000001, 0.0, 25.5, 3230.0546874985234, 1674.259375000188 - 0.6000000000000001, 0.0, 26.0, 3491.6999999981003, 1625.000000000262 - 0.6000000000000001, 0.0, 26.5, 3770.338281250178, 1790.8591796875605 - 0.6000000000000001, 0.0, 27.0, 4055.1312500002427, 2023.2628125001088 - 0.6000000000000001, 0.0, 27.5, 4345.133593750325, 2310.671289062671 - 0.6000000000000001, 0.0, 28.0, 4639.400000000427, 2641.545000000243 - 0.6000000000000001, 0.0, 28.5, 4936.985156250548, 3004.3443359378325 - 0.6000000000000001, 0.0, 29.0, 5236.943750000692, 3387.5296875004356 - 0.6000000000000001, 0.0, 29.5, 5538.330468750859, 3779.5614453130584 - 0.6000000000000001, 0.0, 30.0, 5840.20000000105, 4168.900000000695 - 0.6000000000000001, 0.0, 30.5, 6130.713281249901, 4403.197460936993 - 0.6000000000000001, 0.0, 31.0, 6420.856249999923, 4625.132812499403 - 0.6000000000000001, 0.0, 31.5, 6710.721093749946, 4836.57675781181 - 0.6000000000000001, 0.0, 32.0, 7000.399999999974, 5039.399999999211 - 0.6000000000000001, 0.0, 32.5, 7289.985156250005, 5235.473242186614 - 0.6000000000000001, 0.0, 33.0, 7579.568750000039, 5426.667187499013 - 0.6000000000000001, 0.0, 33.5, 7869.2429687500735, 5614.852539061411 - 0.6000000000000001, 0.0, 34.0, 8159.1000000001095, 5801.899999998809 - 0.6000000000000001, 0.0, 34.5, 8450.70203124731, 6168.551054686519 - 0.6000000000000001, 0.0, 35.0, 8742.53124999644, 6520.770312498897 - 0.6000000000000001, 0.0, 35.5, 9034.539843745448, 6843.393164061274 - 0.6000000000000001, 0.0, 36.0, 9326.679999994336, 7121.254999998653 - 0.6000000000000001, 0.0, 36.5, 9618.903906243097, 7339.191210936024 - 0.6000000000000001, 0.0, 37.0, 9911.163749991732, 7482.037187498399 - 0.6000000000000001, 0.0, 37.5, 10203.411718740233, 7534.628320310765 - 0.6000000000000001, 0.0, 38.0, 10495.599999988604, 7481.799999998126 - 0.6000000000000001, 0.0, 38.5, 10787.766210942827, 7171.4322265637165 - 0.6000000000000001, 0.0, 39.0, 11079.732812507084, 6796.329687501524 - 0.6000000000000001, 0.0, 39.5, 11371.433007821654, 6371.76230468939 - 0.6000000000000001, 0.0, 40.0, 11662.800000011555, 5913.000000002319 - 0.6000000000000001, 0.0, 40.5, 11954.002343751074, 5410.82343749965 - 0.6000000000000001, 0.0, 41.0, 12244.643750001427, 4914.78749999951 - 0.6000000000000001, 0.0, 41.5, 12534.563281251738, 4449.957812499331 - 0.6000000000000001, 0.0, 42.0, 12823.600000001972, 4041.399999999107 - 0.6000000000000001, 0.0, 42.5, 13109.174999999108, 3753.414062498992 - 0.6000000000000001, 0.0, 43.0, 13394.512499998878, 3556.1374999986892 - 0.6000000000000001, 0.0, 43.5, 13680.418749998715, 3458.9421874983404 - 0.6000000000000001, 0.0, 44.0, 13967.69999999867, 3471.1999999979453 - 0.6000000000000001, 0.0, 44.5, 14261.381249998356, 3689.005468750363 - 0.6000000000000001, 0.0, 45.0, 14556.362499997342, 4000.318750000547 - 0.6000000000000001, 0.0, 45.5, 14851.762499995977, 4379.822656250823 - 0.6000000000000001, 0.0, 46.0, 15146.69999999419, 4802.200000001204 - 0.6000000000000001, 0.0, 46.5, 15436.653124996606, 5200.5359374980835 - 0.6000000000000001, 0.0, 47.0, 15725.837499995734, 5607.749999997325 - 0.6000000000000001, 0.0, 47.5, 16014.828124994838, 6015.164062496457 - 0.6000000000000001, 0.0, 48.0, 16304.199999993934, 6414.0999999954865 - 0.6000000000000001, 0.0, 48.5, 16594.52812499306, 6795.879687494411 - 0.6000000000000001, 0.0, 49.0, 16886.38749999224, 7151.824999993236 - 0.6000000000000001, 0.0, 49.5, 17180.353124991507, 7473.2578124919655 - 0.6000000000000001, 0.0, 50.0, 17476.999999990876, 7751.499999990606 - 0.6000000000000001, 2000.0, 0.0, 595.5700675825859, 595.5700675825859 - 0.6000000000000001, 2000.0, 22.0, -6201.899999999975, -1303.4000000000015 - 0.6000000000000001, 2000.0, 22.5, -7374.700585937529, -1711.471484375 - 0.6000000000000001, 2000.0, 23.0, -8535.820312500095, -2091.8531250000024 - 0.6000000000000001, 2000.0, 23.5, -9689.254882812673, -2451.8582031250066 - 0.6000000000000001, 2000.0, 24.0, -10839.000000000271, -2798.8000000000134 - 0.6000000000000001, 2000.0, 24.5, -11989.051367187887, -3139.9917968750224 - 0.6000000000000001, 2000.0, 25.0, -13143.404687500524, -3482.7468750000317 - 0.6000000000000001, 2000.0, 25.5, -14306.055664063182, -3834.3785156250433 - 0.6000000000000001, 2000.0, 26.0, -15481.000000000873, -4202.2000000000535 - 0.6000000000000001, 2000.0, 26.5, -16714.3605468748, -4669.095898437408 - 0.6000000000000001, 2000.0, 27.0, -17970.41312499976, -5171.126562499875 - 0.6000000000000001, 2000.0, 27.5, -19245.931640624716, -5702.650195312335 - 0.6000000000000001, 2000.0, 28.0, -20537.689999999657, -6258.02499999979 - 0.6000000000000001, 2000.0, 28.5, -21842.462109374603, -6831.609179687239 - 0.6000000000000001, 2000.0, 29.0, -23157.021874999547, -7417.760937499679 - 0.6000000000000001, 2000.0, 29.5, -24478.14320312448, -8010.838476562109 - 0.6000000000000001, 2000.0, 30.0, -25802.599999999427, -8605.199999999535 - 0.6000000000000001, 2000.0, 30.5, -27093.335253905683, -9114.921777343776 - 0.6000000000000001, 2000.0, 31.0, -28384.17578124933, -9622.28984375001 - 0.6000000000000001, 2000.0, 31.5, -29675.117480467983, -10129.308300781246 - 0.6000000000000001, 2000.0, 32.0, -30966.15624999911, -10637.981249999972 - 0.6000000000000001, 2000.0, 32.5, -32257.28798828022, -11150.312792968698 - 0.6000000000000001, 2000.0, 33.0, -33548.50859374882, -11668.30703124992 - 0.6000000000000001, 2000.0, 33.5, -34839.81396484241, -12193.968066406145 - 0.6000000000000001, 2000.0, 34.0, -36131.19999999848, -12729.299999999865 - 0.6000000000000001, 2000.0, 34.5, -37423.911523435854, -13389.969843749845 - 0.6000000000000001, 2000.0, 35.0, -38716.576562498165, -14053.49374999986 - 0.6000000000000001, 2000.0, 35.5, -40009.07207031047, -14711.050781249882 - 0.6000000000000001, 2000.0, 36.0, -41301.27499999776, -15353.819999999909 - 0.6000000000000001, 2000.0, 36.5, -42593.06230468504, -15972.980468749929 - 0.6000000000000001, 2000.0, 37.0, -43884.31093749732, -16559.711249999953 - 0.6000000000000001, 2000.0, 37.5, -45174.8978515596, -17105.191406249978 - 0.6000000000000001, 2000.0, 38.0, -46464.69999999685, -17600.600000000006 - 0.6000000000000001, 2000.0, 38.5, -47751.34257812048, -17959.95410156219 - 0.6000000000000001, 2000.0, 39.0, -49038.12187499441, -18291.6046874997 - 0.6000000000000001, 2000.0, 39.5, -50325.41523436819, -18603.877929687238 - 0.6000000000000001, 2000.0, 40.0, -51613.599999991835, -18905.099999999773 - 0.6000000000000001, 2000.0, 40.5, -52904.98124999875, -19182.494531249547 - 0.6000000000000001, 2000.0, 41.0, -54197.237499998366, -19473.931249999296 - 0.6000000000000001, 2000.0, 41.5, -55489.974999997925, -19796.17734374894 - 0.6000000000000001, 2000.0, 42.0, -56782.79999999744, -20165.999999998487 - 0.6000000000000001, 2000.0, 42.5, -58073.342187498456, -20656.701562499446 - 0.6000000000000001, 2000.0, 43.0, -59363.97499999755, -21205.89999999928 - 0.6000000000000001, 2000.0, 43.5, -60655.0953124964, -21807.748437499085 - 0.6000000000000001, 2000.0, 44.0, -61947.099999994934, -22456.399999998866 - 0.6000000000000001, 2000.0, 44.5, -63244.303906246445, -23151.609374999607 - 0.6000000000000001, 2000.0, 45.0, -64541.61874999546, -23879.687499999487 - 0.6000000000000001, 2000.0, 45.5, -65837.87421874439, -24632.546874999378 - 0.6000000000000001, 2000.0, 46.0, -67131.8999999933, -25402.099999999267 - 0.6000000000000001, 2000.0, 46.5, -68416.28750000268, -26160.16171875002 - 0.6000000000000001, 2000.0, 47.0, -69698.60000000332, -26926.781249999916 - 0.6000000000000001, 2000.0, 47.5, -70980.16250000393, -27701.91015624978 - 0.6000000000000001, 2000.0, 48.0, -72262.3000000045, -28485.499999999618 - 0.6000000000000001, 2000.0, 48.5, -73546.33750000497, -29277.50234374943 - 0.6000000000000001, 2000.0, 49.0, -74833.60000000526, -30077.86874999922 - 0.6000000000000001, 2000.0, 49.5, -76125.41250000543, -30886.550781248985 - 0.6000000000000001, 2000.0, 50.0, -77423.10000000538, -31703.49999999873 - 0.6000000000000001, 5000.0, 0.0, 538.6131492187725, 538.6131492187725 - 0.6000000000000001, 5000.0, 22.0, 6111.299999999994, 2945.7000000000126 - 0.6000000000000001, 5000.0, 22.5, 7273.0048828124845, 3342.754492187496 - 0.6000000000000001, 5000.0, 23.0, 8422.09843749997, 3727.6765624999875 - 0.6000000000000001, 5000.0, 23.5, 9562.667773437446, 4104.6103515624845 - 0.6000000000000001, 5000.0, 24.0, 10698.799999999917, 4477.699999999989 - 0.6000000000000001, 5000.0, 24.5, 11834.582226562376, 4851.089648437497 - 0.6000000000000001, 5000.0, 25.0, 12974.101562499825, 5228.923437500012 - 0.6000000000000001, 5000.0, 25.5, 14121.445117187268, 5615.345507812525 - 0.6000000000000001, 5000.0, 26.0, 15280.699999999699, 6014.500000000045 - 0.6000000000000001, 5000.0, 26.5, 16498.598632812304, 6472.133203124922 - 0.6000000000000001, 5000.0, 27.0, 17739.019687499745, 6953.1643749999175 - 0.6000000000000001, 5000.0, 27.5, 18998.739648437175, 7454.60585937491 - 0.6000000000000001, 5000.0, 28.0, 20274.534999999603, 7973.469999999908 - 0.6000000000000001, 5000.0, 28.5, 21563.182226562036, 8506.769140624907 - 0.6000000000000001, 5000.0, 29.0, 22861.457812499444, 9051.515624999905 - 0.6000000000000001, 5000.0, 29.5, 24166.138242186855, 9604.72179687491 - 0.6000000000000001, 5000.0, 30.0, 25473.99999999925, 10163.399999999918 - 0.6000000000000001, 5000.0, 30.5, 26748.02802734414, 10697.463964843771 - 0.6000000000000001, 5000.0, 31.0, 28022.008593750445, 11233.605468750022 - 0.6000000000000001, 5000.0, 31.5, 29295.936425781736, 11771.417675781271 - 0.6000000000000001, 5000.0, 32.0, 30569.806250000536, 12310.493750000029 - 0.6000000000000001, 5000.0, 32.5, 31843.61279296933, 12850.426855468786 - 0.6000000000000001, 5000.0, 33.0, 33117.350781250614, 13390.810156250045 - 0.6000000000000001, 5000.0, 33.5, 34391.0149414069, 13931.23681640631 - 0.6000000000000001, 5000.0, 34.0, 35664.60000000066, 14471.30000000008 - 0.6000000000000001, 5000.0, 34.5, 36937.78117187501, 15016.257539062184 - 0.6000000000000001, 5000.0, 35.0, 38210.90312500001, 15559.498437499666 - 0.6000000000000001, 5000.0, 35.5, 39483.991015625026, 16100.07636718715 - 0.6000000000000001, 5000.0, 36.0, 40757.07000000004, 16637.044999999634 - 0.6000000000000001, 5000.0, 36.5, 42030.16523437507, 17169.45800781213 - 0.6000000000000001, 5000.0, 37.0, 43303.30187500009, 17696.369062499627 - 0.6000000000000001, 5000.0, 37.5, 44576.505078125134, 18216.831835937133 - 0.6000000000000001, 5000.0, 38.0, 45849.800000000185, 18729.89999999965 - 0.6000000000000001, 5000.0, 38.5, 47123.47968749631, 19230.180664062314 - 0.6000000000000001, 5000.0, 39.0, 48397.16249999573, 19723.4796874997 - 0.6000000000000001, 5000.0, 39.5, 49670.81406249508, 20209.838867187023 - 0.6000000000000001, 5000.0, 40.0, 50944.39999999442, 20689.299999999304 - 0.6000000000000001, 5000.0, 40.5, 52217.456250000614, 21149.009374999365 - 0.6000000000000001, 5000.0, 41.0, 53490.550000000636, 21607.062499999185 - 0.6000000000000001, 5000.0, 41.5, 54763.818750000595, 22068.659374999002 - 0.6000000000000001, 5000.0, 42.0, 56037.400000000445, 22538.999999998836 - 0.6000000000000001, 5000.0, 42.5, 57311.349218749194, 23032.44843749982 - 0.6000000000000001, 5000.0, 43.0, 58585.91874999923, 23541.374999999734 - 0.6000000000000001, 5000.0, 43.5, 59861.27890624934, 24067.314062499616 - 0.6000000000000001, 5000.0, 44.0, 61137.599999999504, 24611.79999999946 - 0.6000000000000001, 5000.0, 44.5, 62418.23593750053, 25183.730468750306 - 0.6000000000000001, 5000.0, 45.0, 63698.90000000074, 25774.331250000338 - 0.6000000000000001, 5000.0, 45.5, 64978.489062500994, 26382.191406250357 - 0.6000000000000001, 5000.0, 46.0, 66255.90000000133, 27005.900000000347 - 0.6000000000000001, 5000.0, 46.5, 67524.19374999836, 27649.178906250127 - 0.6000000000000001, 5000.0, 47.0, 68790.43749999772, 28303.431250000252 - 0.6000000000000001, 5000.0, 47.5, 70055.86249999699, 28965.192968750413 - 0.6000000000000001, 5000.0, 48.0, 71321.69999999611, 29631.00000000061 - 0.6000000000000001, 5000.0, 48.5, 72589.18124999506, 30297.38828125085 - 0.6000000000000001, 5000.0, 49.0, 73859.53749999386, 30960.893750001123 - 0.6000000000000001, 5000.0, 49.5, 75133.99999999248, 31618.052343751428 - 0.6000000000000001, 5000.0, 50.0, 76413.79999999091, 32265.400000001773 - 0.6000000000000001, 10000.0, 0.0, 453.31998413108965, 453.31998413108965 - 0.6000000000000001, 10000.0, 22.0, 827.4000000000067, 977.5999999999967 - 0.6000000000000001, 10000.0, 22.5, 984.1828125000136, 1041.4587890624998 - 0.6000000000000001, 10000.0, 23.0, 1139.4625000000215, 1105.0921875000035 - 0.6000000000000001, 10000.0, 23.5, 1293.7609375000313, 1168.6294921875085 - 0.6000000000000001, 10000.0, 24.0, 1447.6000000000427, 1232.2000000000148 - 0.6000000000000001, 10000.0, 24.5, 1601.5015625000558, 1295.9330078125222 - 0.6000000000000001, 10000.0, 25.0, 1755.9875000000707, 1359.9578125000296 - 0.6000000000000001, 10000.0, 25.5, 1911.5796875000879, 1424.4037109375386 - 0.6000000000000001, 10000.0, 26.0, 2068.8000000001066, 1489.4000000000478 - 0.6000000000000001, 10000.0, 26.5, 2233.6937500000076, 1556.402148437486 - 0.6000000000000001, 10000.0, 27.0, 2401.5750000000135, 1624.2890624999861 - 0.6000000000000001, 10000.0, 27.5, 2572.018750000022, 1692.9626953124862 - 0.6000000000000001, 10000.0, 28.0, 2744.6000000000317, 1762.3249999999873 - 0.6000000000000001, 10000.0, 28.5, 2918.8937500000425, 1832.2779296874894 - 0.6000000000000001, 10000.0, 29.0, 3094.475000000054, 1902.7234374999928 - 0.6000000000000001, 10000.0, 29.5, 3270.9187500000694, 1973.5634765624977 - 0.6000000000000001, 10000.0, 30.0, 3447.800000000084, 2044.7000000000037 - 0.6000000000000001, 10000.0, 30.5, 3620.262011718791, 2114.9172851562935 - 0.6000000000000001, 10000.0, 31.0, 3792.733593750052, 2185.3414062500497 - 0.6000000000000001, 10000.0, 31.5, 3965.211816406313, 2255.9807617188067 - 0.6000000000000001, 10000.0, 32.0, 4137.693750000077, 2326.843750000064 - 0.6000000000000001, 10000.0, 32.5, 4310.176464843838, 2397.9387695313217 - 0.6000000000000001, 10000.0, 33.0, 4482.657031250102, 2469.2742187500794 - 0.6000000000000001, 10000.0, 33.5, 4655.132519531365, 2540.858496093839 - 0.6000000000000001, 10000.0, 34.0, 4827.600000000131, 2612.7000000000976 - 0.6000000000000001, 10000.0, 34.5, 5000.044648437297, 2684.631171875052 - 0.6000000000000001, 10000.0, 35.0, 5172.47656249974, 2756.853125000065 - 0.6000000000000001, 10000.0, 35.5, 5344.8939453121775, 2829.39101562508 - 0.6000000000000001, 10000.0, 36.0, 5517.294999999606, 2902.2700000000964 - 0.6000000000000001, 10000.0, 36.5, 5689.677929687027, 2975.515234375113 - 0.6000000000000001, 10000.0, 37.0, 5862.040937499443, 3049.151875000132 - 0.6000000000000001, 10000.0, 37.5, 6034.382226561852, 3123.205078125151 - 0.6000000000000001, 10000.0, 38.0, 6206.699999999253, 3197.70000000017 - 0.6000000000000001, 10000.0, 38.5, 6378.92285156346, 3273.7734375003106 - 0.6000000000000001, 10000.0, 39.0, 6551.154687501145, 3349.7625000003777 - 0.6000000000000001, 10000.0, 39.5, 6723.409179688847, 3425.445312500452 - 0.6000000000000001, 10000.0, 40.0, 6895.700000001568, 3500.600000000539 - 0.6000000000000001, 10000.0, 40.5, 7068.09843750002, 3572.715624999973 - 0.6000000000000001, 10000.0, 41.0, 7240.53750000008, 3644.774999999978 - 0.6000000000000001, 10000.0, 41.5, 7413.007812500162, 3717.4718749999906 - 0.6000000000000001, 10000.0, 42.0, 7585.500000000263, 3791.5000000000105 - 0.6000000000000001, 10000.0, 42.5, 7757.867968750406, 3870.287499999993 - 0.6000000000000001, 10000.0, 43.0, 7930.293750000572, 3950.7 - 0.6000000000000001, 10000.0, 43.5, 8102.822656250768, 4032.3375000000083 - 0.6000000000000001, 10000.0, 44.0, 8275.500000000995, 4114.800000000017 - 0.6000000000000001, 10000.0, 44.5, 8448.8710937499, 4196.914062499992 - 0.6000000000000001, 10000.0, 45.0, 8622.281249999916, 4279.362500000003 - 0.6000000000000001, 10000.0, 45.5, 8795.575781249938, 4362.054687500028 - 0.6000000000000001, 10000.0, 46.0, 8968.59999999997, 4444.900000000062 - 0.6000000000000001, 10000.0, 46.5, 9140.425781250377, 4528.444531249976 - 0.6000000000000001, 10000.0, 47.0, 9311.981250000532, 4611.7062499999665 - 0.6000000000000001, 10000.0, 47.5, 9483.421093750716, 4694.339843749959 - 0.6000000000000001, 10000.0, 48.0, 9654.900000000926, 4775.999999999952 - 0.6000000000000001, 10000.0, 48.5, 9826.572656251163, 4856.341406249941 - 0.6000000000000001, 10000.0, 49.0, 9998.593750001426, 4935.018749999932 - 0.6000000000000001, 10000.0, 49.5, 10171.117968751714, 5011.686718749919 - 0.6000000000000001, 10000.0, 50.0, 10344.300000002031, 5085.999999999906 - 0.6000000000000001, 15000.0, 0.0, 379.06318433498546, 379.06318433498546 - 0.6000000000000001, 15000.0, 22.0, 751.1999999999999, 841.2000000000003 - 0.6000000000000001, 15000.0, 22.5, 893.7603515625003, 899.6800781250008 - 0.6000000000000001, 15000.0, 23.0, 1034.8546875000006, 957.0968750000006 - 0.6000000000000001, 15000.0, 23.5, 1174.9716796875014, 1013.715234375001 - 0.6000000000000001, 15000.0, 24.0, 1314.6000000000017, 1069.8000000000009 - 0.6000000000000001, 15000.0, 24.5, 1454.228320312503, 1125.6160156250014 - 0.6000000000000001, 15000.0, 25.0, 1594.3453125000033, 1181.4281250000022 - 0.6000000000000001, 15000.0, 25.5, 1735.439648437505, 1237.5011718750022 - 0.6000000000000001, 15000.0, 26.0, 1878.0000000000061, 1294.100000000003 - 0.6000000000000001, 15000.0, 26.5, 2027.6460937499994, 1353.9244140624996 - 0.6000000000000001, 15000.0, 27.0, 2180.028749999999, 1414.9434375 - 0.6000000000000001, 15000.0, 27.5, 2334.7570312499993, 1477.0044921875 - 0.6000000000000001, 15000.0, 28.0, 2491.4399999999982, 1539.9549999999997 - 0.6000000000000001, 15000.0, 28.5, 2649.6867187499984, 1603.6423828124996 - 0.6000000000000001, 15000.0, 29.0, 2809.106249999999, 1667.9140624999995 - 0.6000000000000001, 15000.0, 29.5, 2969.307656249998, 1732.6174609374991 - 0.6000000000000001, 15000.0, 30.0, 3129.8999999999987, 1797.5999999999992 - 0.6000000000000001, 15000.0, 30.5, 3286.3854492187465, 1860.8958007812523 - 0.6000000000000001, 15000.0, 31.0, 3442.8710937499955, 1924.3382812500029 - 0.6000000000000001, 15000.0, 31.5, 3599.3571289062443, 1987.947558593754 - 0.6000000000000001, 15000.0, 32.0, 3755.8437499999945, 2051.743750000004 - 0.6000000000000001, 15000.0, 32.5, 3912.331152343744, 2115.7469726562563 - 0.6000000000000001, 15000.0, 33.0, 4068.8195312499925, 2179.9773437500066 - 0.6000000000000001, 15000.0, 33.5, 4225.309082031242, 2244.454980468759 - 0.6000000000000001, 15000.0, 34.0, 4381.799999999993, 2309.20000000001 - 0.6000000000000001, 15000.0, 34.5, 4538.296992187475, 2374.3584374999914 - 0.6000000000000001, 15000.0, 35.0, 4694.795312499968, 2439.812499999991 - 0.6000000000000001, 15000.0, 35.5, 4851.2947265624625, 2505.5703124999905 - 0.6000000000000001, 15000.0, 36.0, 5007.794999999961, 2571.639999999989 - 0.6000000000000001, 15000.0, 36.5, 5164.295898437456, 2638.0296874999876 - 0.6000000000000001, 15000.0, 37.0, 5320.797187499952, 2704.747499999986 - 0.6000000000000001, 15000.0, 37.5, 5477.298632812445, 2771.8015624999853 - 0.6000000000000001, 15000.0, 38.0, 5633.799999999942, 2839.1999999999834 - 0.6000000000000001, 15000.0, 38.5, 5790.299999999916, 2907.1861328124824 - 0.6000000000000001, 15000.0, 39.0, 5946.7999999999, 2975.4109374999803 - 0.6000000000000001, 15000.0, 39.5, 6103.299999999878, 3043.830273437477 - 0.6000000000000001, 15000.0, 40.0, 6259.799999999858, 3112.3999999999733 - 0.6000000000000001, 15000.0, 40.5, 6416.303906249987, 3180.9070312500003 - 0.6000000000000001, 15000.0, 41.0, 6572.806249999982, 3249.5437499999994 - 0.6000000000000001, 15000.0, 41.5, 6729.305468749977, 3318.33359375 - 0.6000000000000001, 15000.0, 42.0, 6885.799999999971, 3387.2999999999975 - 0.6000000000000001, 15000.0, 42.5, 7042.151562499976, 3456.4820312499915 - 0.6000000000000001, 15000.0, 43.0, 7198.5499999999665, 3525.8812499999885 - 0.6000000000000001, 15000.0, 43.5, 7355.048437499955, 3595.514843749985 - 0.6000000000000001, 15000.0, 44.0, 7511.699999999941, 3665.3999999999833 - 0.6000000000000001, 15000.0, 44.5, 7669.065625000001, 3735.6945312500006 - 0.6000000000000001, 15000.0, 45.0, 7826.487500000004, 3806.218750000002 - 0.6000000000000001, 15000.0, 45.5, 7983.815625000006, 3876.933593749999 - 0.6000000000000001, 15000.0, 46.0, 8140.900000000009, 3947.7999999999993 - 0.6000000000000001, 15000.0, 46.5, 8296.84843749999, 4018.4351562500074 - 0.6000000000000001, 15000.0, 47.0, 8452.549999999985, 4089.281250000011 - 0.6000000000000001, 15000.0, 47.5, 8608.151562499983, 4160.436718750014 - 0.6000000000000001, 15000.0, 48.0, 8763.799999999981, 4232.000000000017 - 0.6000000000000001, 15000.0, 48.5, 8919.642187499981, 4304.069531250021 - 0.6000000000000001, 15000.0, 49.0, 9075.824999999979, 4376.743750000026 - 0.6000000000000001, 15000.0, 49.5, 9232.495312499981, 4450.121093750032 - 0.6000000000000001, 15000.0, 50.0, 9389.799999999983, 4524.300000000036 - 0.6000000000000001, 20000.0, 0.0, 314.7627889058769, 314.7627889058769 - 0.6000000000000001, 20000.0, 22.0, 776.5999999999996, 758.5999999999998 - 0.6000000000000001, 20000.0, 22.5, 923.9941406249995, 816.3884765625004 - 0.6000000000000001, 20000.0, 23.0, 1069.8718749999996, 873.8296875000011 - 0.6000000000000001, 20000.0, 23.5, 1214.7386718750006, 931.0810546875018 - 0.6000000000000001, 20000.0, 24.0, 1359.1000000000004, 988.3000000000023 - 0.6000000000000001, 20000.0, 24.5, 1503.4613281250015, 1045.643945312503 - 0.6000000000000001, 20000.0, 25.0, 1648.3281250000016, 1103.2703125000037 - 0.6000000000000001, 20000.0, 25.5, 1794.2058593750025, 1161.3365234375046 - 0.6000000000000001, 20000.0, 26.0, 1941.6000000000035, 1220.0000000000061 - 0.6000000000000001, 20000.0, 26.5, 2096.3248046874983, 1280.8810546875002 - 0.6000000000000001, 20000.0, 27.0, 2253.8803124999977, 1342.7578125000005 - 0.6000000000000001, 20000.0, 27.5, 2413.8619140624974, 1405.5369140625 - 0.6000000000000001, 20000.0, 28.0, 2575.864999999996, 1469.125 - 0.6000000000000001, 20000.0, 28.5, 2739.4849609374946, 1533.4287109374995 - 0.6000000000000001, 20000.0, 29.0, 2904.317187499993, 1598.3546874999993 - 0.6000000000000001, 20000.0, 29.5, 3069.957070312491, 1663.8095703124993 - 0.6000000000000001, 20000.0, 30.0, 3235.9999999999895, 1729.699999999999 - 0.6000000000000001, 20000.0, 30.5, 3397.7888671874994, 1794.882617187501 - 0.6000000000000001, 20000.0, 31.0, 3559.5765624999985, 1860.4140625000016 - 0.6000000000000001, 20000.0, 31.5, 3721.3634765624975, 1926.3009765625015 - 0.6000000000000001, 20000.0, 32.0, 3883.1499999999965, 1992.5500000000018 - 0.6000000000000001, 20000.0, 32.5, 4044.936523437496, 2059.167773437503 - 0.6000000000000001, 20000.0, 33.0, 4206.723437499994, 2126.160937500003 - 0.6000000000000001, 20000.0, 33.5, 4368.511132812495, 2193.5361328125027 - 0.6000000000000001, 20000.0, 34.0, 4530.299999999992, 2261.300000000004 - 0.6000000000000001, 20000.0, 34.5, 4692.096992187498, 2329.793867187501 - 0.6000000000000001, 20000.0, 35.0, 4853.895312499998, 2398.657812500001 - 0.6000000000000001, 20000.0, 35.5, 5015.694726562498, 2467.866601562501 - 0.6000000000000001, 20000.0, 36.0, 5177.494999999997, 2537.3950000000013 - 0.6000000000000001, 20000.0, 36.5, 5339.2958984375, 2607.2177734375005 - 0.6000000000000001, 20000.0, 37.0, 5501.097187499998, 2677.3096875000006 - 0.6000000000000001, 20000.0, 37.5, 5662.898632812497, 2747.6455078125014 - 0.6000000000000001, 20000.0, 38.0, 5824.699999999996, 2818.2 - 0.6000000000000001, 20000.0, 38.5, 5986.500000000001, 2888.7781249999875 - 0.6000000000000001, 20000.0, 39.0, 6148.300000000002, 2959.6124999999847 - 0.6000000000000001, 20000.0, 39.5, 6310.100000000002, 3030.7156249999825 - 0.6000000000000001, 20000.0, 40.0, 6471.900000000004, 3102.09999999998 - 0.6000000000000001, 20000.0, 40.5, 6633.700000000027, 3173.6101562500016 - 0.6000000000000001, 20000.0, 41.0, 6795.500000000039, 3245.4937500000033 - 0.6000000000000001, 20000.0, 41.5, 6957.300000000049, 3317.8304687500045 - 0.6000000000000001, 20000.0, 42.0, 7119.100000000061, 3390.700000000006 - 0.6000000000000001, 20000.0, 42.5, 7280.771093750016, 3464.475 - 0.6000000000000001, 20000.0, 43.0, 7442.493750000027, 3538.8249999999985 - 0.6000000000000001, 20000.0, 43.5, 7604.319531250037, 3613.712499999998 - 0.6000000000000001, 20000.0, 44.0, 7766.3000000000475, 3689.0999999999963 - 0.6000000000000001, 20000.0, 44.5, 7928.998437500003, 3764.754687499994 - 0.6000000000000001, 20000.0, 45.0, 8091.750000000002, 3840.9124999999935 - 0.6000000000000001, 20000.0, 45.5, 8254.401562500005, 3917.614062499992 - 0.6000000000000001, 20000.0, 46.0, 8416.800000000008, 3994.899999999992 - 0.6000000000000001, 20000.0, 46.5, 8578.03437500001, 4071.8460937500035 - 0.6000000000000001, 20000.0, 47.0, 8739.012500000017, 4149.843750000006 - 0.6000000000000001, 20000.0, 47.5, 8899.884375000018, 4229.319531250008 - 0.6000000000000001, 20000.0, 48.0, 9060.800000000025, 4310.70000000001 - 0.6000000000000001, 20000.0, 48.5, 9221.909375000028, 4394.4117187500115 - 0.6000000000000001, 20000.0, 49.0, 9383.362500000036, 4480.881250000015 - 0.6000000000000001, 20000.0, 49.5, 9545.309375000039, 4570.535156250017 - 0.6000000000000001, 20000.0, 50.0, 9707.900000000047, 4663.800000000019 - 0.6000000000000001, 25000.0, 0.0, 259.4005380471049, 259.4005380471049 - 0.6000000000000001, 25000.0, 22.0, 628.4999999999998, 620.3999999999997 - 0.6000000000000001, 25000.0, 22.5, 747.7416015625003, 665.8169921875001 - 0.6000000000000001, 25000.0, 23.0, 865.7671875000008, 711.1015625000001 - 0.6000000000000001, 25000.0, 23.5, 982.9841796875012, 756.3603515625005 - 0.6000000000000001, 25000.0, 24.0, 1099.8000000000018, 801.7000000000007 - 0.6000000000000001, 25000.0, 24.5, 1216.6220703125025, 847.2271484375011 - 0.6000000000000001, 25000.0, 25.0, 1333.8578125000033, 893.0484375000016 - 0.6000000000000001, 25000.0, 25.5, 1451.914648437504, 939.270507812502 - 0.6000000000000001, 25000.0, 26.0, 1571.2000000000053, 986.0000000000027 - 0.6000000000000001, 25000.0, 26.5, 1696.4046874999967, 1034.4263671874994 - 0.6000000000000001, 25000.0, 27.0, 1823.897499999996, 1083.6353124999987 - 0.6000000000000001, 25000.0, 27.5, 1953.351562499995, 1133.5478515624982 - 0.6000000000000001, 25000.0, 28.0, 2084.4399999999937, 1184.0849999999982 - 0.6000000000000001, 25000.0, 28.5, 2216.8359374999927, 1235.1677734374975 - 0.6000000000000001, 25000.0, 29.0, 2350.212499999992, 1286.7171874999976 - 0.6000000000000001, 25000.0, 29.5, 2484.2428124999906, 1338.6542578124968 - 0.6000000000000001, 25000.0, 30.0, 2618.59999999999, 1390.899999999996 - 0.6000000000000001, 25000.0, 30.5, 2749.522949218758, 1442.3533203124996 - 0.6000000000000001, 25000.0, 31.0, 2880.44609375001, 1494.0546874999993 - 0.6000000000000001, 25000.0, 31.5, 3011.3696289062627, 1546.0224609374989 - 0.6000000000000001, 25000.0, 32.0, 3142.2937500000157, 1598.274999999999 - 0.6000000000000001, 25000.0, 32.5, 3273.218652343768, 1650.8306640624987 - 0.6000000000000001, 25000.0, 33.0, 3404.14453125002, 1703.707812499998 - 0.6000000000000001, 25000.0, 33.5, 3535.071582031274, 1756.9248046874975 - 0.6000000000000001, 25000.0, 34.0, 3666.0000000000273, 1810.4999999999977 - 0.6000000000000001, 25000.0, 34.5, 3796.937773437493, 1864.998085937496 - 0.6000000000000001, 25000.0, 35.0, 3927.8765624999933, 1919.8390624999947 - 0.6000000000000001, 25000.0, 35.5, 4058.8158203124926, 1974.9892578124932 - 0.6000000000000001, 25000.0, 36.0, 4189.754999999994, 2030.4149999999916 - 0.6000000000000001, 25000.0, 36.5, 4320.693554687495, 2086.0826171874887 - 0.6000000000000001, 25000.0, 37.0, 4451.630937499996, 2141.958437499987 - 0.6000000000000001, 25000.0, 37.5, 4582.566601562499, 2198.0087890624845 - 0.6000000000000001, 25000.0, 38.0, 4713.5, 2254.1999999999816 - 0.6000000000000001, 25000.0, 38.5, 4844.421093749978, 2310.2378906249796 - 0.6000000000000001, 25000.0, 39.0, 4975.343749999973, 2366.484374999977 - 0.6000000000000001, 25000.0, 39.5, 5106.269531249965, 2422.963671874974 - 0.6000000000000001, 25000.0, 40.0, 5237.199999999959, 2479.699999999971 - 0.6000000000000001, 25000.0, 40.5, 5368.148437499983, 2536.7000000000103 - 0.6000000000000001, 25000.0, 41.0, 5499.0999999999785, 2594.0125000000135 - 0.6000000000000001, 25000.0, 41.5, 5630.051562499971, 2651.6687500000176 - 0.6000000000000001, 25000.0, 42.0, 5760.999999999964, 2709.700000000022 - 0.6000000000000001, 25000.0, 42.5, 5891.828906249997, 2768.172656249987 - 0.6000000000000001, 25000.0, 43.0, 6022.693749999989, 2827.068749999984 - 0.6000000000000001, 25000.0, 43.5, 6153.63671874998, 2886.4054687499797 - 0.6000000000000001, 25000.0, 44.0, 6284.699999999972, 2946.1999999999753 - 0.6000000000000001, 25000.0, 44.5, 6416.335937500015, 3006.430468750007 - 0.6000000000000001, 25000.0, 45.0, 6548.012500000019, 3067.1687500000094 - 0.6000000000000001, 25000.0, 45.5, 6679.607812500025, 3128.4476562500113 - 0.6000000000000001, 25000.0, 46.0, 6811.00000000003, 3190.3000000000143 - 0.6000000000000001, 25000.0, 46.5, 6941.453906250013, 3252.3015625 - 0.6000000000000001, 25000.0, 47.0, 7071.706250000015, 3315.124999999998 - 0.6000000000000001, 25000.0, 47.5, 7201.880468750021, 3378.985937499997 - 0.6000000000000001, 25000.0, 48.0, 7332.100000000026, 3444.0999999999967 - 0.6000000000000001, 25000.0, 48.5, 7462.488281250033, 3510.682812499995 - 0.6000000000000001, 25000.0, 49.0, 7593.168750000039, 3578.949999999994 - 0.6000000000000001, 25000.0, 49.5, 7724.264843750045, 3649.117187499993 - 0.6000000000000001, 25000.0, 50.0, 7855.900000000052, 3721.399999999992 - 0.6000000000000001, 30000.0, 0.0, 212.0295559448311, 212.0295559448311 - 0.6000000000000001, 30000.0, 22.0, 500.8000000000001, 505.20000000000005 - 0.6000000000000001, 30000.0, 22.5, 595.8962890625006, 540.6296875000004 - 0.6000000000000001, 30000.0, 23.0, 689.9921875000011, 576.0250000000005 - 0.6000000000000001, 30000.0, 23.5, 783.4169921875017, 611.457812500001 - 0.6000000000000001, 30000.0, 24.0, 876.5000000000026, 647.0000000000013 - 0.6000000000000001, 30000.0, 24.5, 969.5705078125038, 682.7234375000016 - 0.6000000000000001, 30000.0, 25.0, 1062.9578125000048, 718.700000000002 - 0.6000000000000001, 30000.0, 25.5, 1156.9912109375061, 755.0015625000023 - 0.6000000000000001, 30000.0, 26.0, 1252.0000000000082, 791.7000000000027 - 0.6000000000000001, 30000.0, 26.5, 1351.7601562499992, 829.5945312499983 - 0.6000000000000001, 30000.0, 27.0, 1453.3512499999986, 868.0712499999984 - 0.6000000000000001, 30000.0, 27.5, 1556.5117187499984, 907.077343749998 - 0.6000000000000001, 30000.0, 28.0, 1660.9799999999975, 946.5599999999977 - 0.6000000000000001, 30000.0, 28.5, 1766.4945312499967, 986.4664062499972 - 0.6000000000000001, 30000.0, 29.0, 1872.7937499999953, 1026.743749999997 - 0.6000000000000001, 30000.0, 29.5, 1979.6160937499944, 1067.3392187499965 - 0.6000000000000001, 30000.0, 30.0, 2086.6999999999935, 1108.1999999999955 - 0.6000000000000001, 30000.0, 30.5, 2191.0375000000035, 1148.7577148437513 - 0.6000000000000001, 30000.0, 31.0, 2295.3750000000036, 1189.5242187500012 - 0.6000000000000001, 30000.0, 31.5, 2399.712500000005, 1230.4958007812513 - 0.6000000000000001, 30000.0, 32.0, 2504.0500000000047, 1271.6687500000016 - 0.6000000000000001, 30000.0, 32.5, 2608.3875000000053, 1313.0393554687519 - 0.6000000000000001, 30000.0, 33.0, 2712.7250000000054, 1354.6039062500022 - 0.6000000000000001, 30000.0, 33.5, 2817.0625000000064, 1396.3586914062525 - 0.6000000000000001, 30000.0, 34.0, 2921.4000000000055, 1438.3000000000031 - 0.6000000000000001, 30000.0, 34.5, 3025.734218749986, 1480.3974609374961 - 0.6000000000000001, 30000.0, 35.0, 3130.0687499999844, 1522.676562499996 - 0.6000000000000001, 30000.0, 35.5, 3234.403906249982, 1565.1361328124945 - 0.6000000000000001, 30000.0, 36.0, 3338.7399999999793, 1607.7749999999933 - 0.6000000000000001, 30000.0, 36.5, 3443.077343749977, 1650.5919921874927 - 0.6000000000000001, 30000.0, 37.0, 3547.4162499999743, 1693.5859374999916 - 0.6000000000000001, 30000.0, 37.5, 3651.7570312499724, 1736.7556640624903 - 0.6000000000000001, 30000.0, 38.0, 3756.099999999969, 1780.0999999999892 - 0.6000000000000001, 30000.0, 38.5, 3860.4539062499452, 1823.5333984375043 - 0.6000000000000001, 30000.0, 39.0, 3964.806249999935, 1867.182812500006 - 0.6000000000000001, 30000.0, 39.5, 4069.155468749924, 1911.065820312509 - 0.6000000000000001, 30000.0, 40.0, 4173.499999999912, 1955.2000000000112 - 0.6000000000000001, 30000.0, 40.5, 4277.8304687500195, 1999.6390625 - 0.6000000000000001, 30000.0, 41.0, 4382.156250000024, 2044.3500000000006 - 0.6000000000000001, 30000.0, 41.5, 4486.478906250029, 2089.335937500002 - 0.6000000000000001, 30000.0, 42.0, 4590.800000000032, 2134.6000000000013 - 0.6000000000000001, 30000.0, 42.5, 4695.039062499995, 2180.121875000006 - 0.6000000000000001, 30000.0, 43.0, 4799.312499999996, 2225.937500000009 - 0.6000000000000001, 30000.0, 43.5, 4903.654687499997, 2272.059375000011 - 0.6000000000000001, 30000.0, 44.0, 5008.0999999999985, 2318.500000000014 - 0.6000000000000001, 30000.0, 44.5, 5113.022656250002, 2365.0960937500026 - 0.6000000000000001, 30000.0, 45.0, 5217.981250000004, 2412.1062500000035 - 0.6000000000000001, 30000.0, 45.5, 5322.874218750007, 2459.6132812500055 - 0.6000000000000001, 30000.0, 46.0, 5427.600000000011, 2507.700000000007 - 0.6000000000000001, 30000.0, 46.5, 5531.549218749995, 2556.273437499999 - 0.6000000000000001, 30000.0, 47.0, 5635.331249999993, 2605.6624999999995 - 0.6000000000000001, 30000.0, 47.5, 5739.0476562499925, 2656.0203124999994 - 0.6000000000000001, 30000.0, 48.0, 5842.799999999995, 2707.499999999999 - 0.6000000000000001, 30000.0, 48.5, 5946.689843749995, 2760.254687499999 - 0.6000000000000001, 30000.0, 49.0, 6050.818749999995, 2814.4374999999986 - 0.6000000000000001, 30000.0, 49.5, 6155.288281249998, 2870.2015625 - 0.6000000000000001, 30000.0, 50.0, 6260.200000000001, 2927.7000000000003 - 0.6000000000000001, 35000.0, 0.0, 171.7680450916509, 171.7680450916509 - 0.6000000000000001, 35000.0, 22.0, 382.8, 417.70000000000005 - 0.6000000000000001, 35000.0, 22.5, 455.392578125, 444.04296875000006 - 0.6000000000000001, 35000.0, 23.0, 527.2593749999999, 470.44374999999997 - 0.6000000000000001, 35000.0, 23.5, 598.6464843749999, 496.94765624999997 - 0.6000000000000001, 35000.0, 24.0, 669.8, 523.5999999999999 - 0.6000000000000001, 35000.0, 24.5, 740.966015625, 550.4460937499998 - 0.6000000000000001, 35000.0, 25.0, 812.390625, 577.5312499999997 - 0.6000000000000001, 35000.0, 25.5, 884.3199218749999, 604.9007812499996 - 0.6000000000000001, 35000.0, 26.0, 956.9999999999999, 632.5999999999993 - 0.6000000000000001, 35000.0, 26.5, 1033.2732421875003, 661.1759765625002 - 0.6000000000000001, 35000.0, 27.0, 1110.9378125000003, 690.2009375000002 - 0.6000000000000001, 35000.0, 27.5, 1189.7947265625, 719.6341796875001 - 0.6000000000000001, 35000.0, 28.0, 1269.6450000000004, 749.4350000000003 - 0.6000000000000001, 35000.0, 28.5, 1350.2896484375003, 779.5626953125003 - 0.6000000000000001, 35000.0, 29.0, 1431.5296875000001, 809.9765625000005 - 0.6000000000000001, 35000.0, 29.5, 1513.1661328125, 840.6358984375005 - 0.6000000000000001, 35000.0, 30.0, 1595.0000000000002, 871.5000000000006 - 0.6000000000000001, 35000.0, 30.5, 1674.7368164062498, 902.1479492187502 - 0.6000000000000001, 35000.0, 31.0, 1754.4726562499998, 932.95546875 - 0.6000000000000001, 35000.0, 31.5, 1834.2081054687496, 963.91806640625 - 0.6000000000000001, 35000.0, 32.0, 1913.9437499999997, 995.03125 - 0.6000000000000001, 35000.0, 32.5, 1993.6801757812495, 1026.29052734375 - 0.6000000000000001, 35000.0, 33.0, 2073.41796875, 1057.6914062499998 - 0.6000000000000001, 35000.0, 33.5, 2153.157714843749, 1089.2293945312497 - 0.6000000000000001, 35000.0, 34.0, 2232.8999999999996, 1120.8999999999996 - 0.6000000000000001, 35000.0, 34.5, 2312.666328124999, 1152.623671875 - 0.6000000000000001, 35000.0, 35.0, 2392.434374999998, 1184.4781249999999 - 0.6000000000000001, 35000.0, 35.5, 2472.202734374998, 1216.4660156249997 - 0.6000000000000001, 35000.0, 36.0, 2551.969999999998, 1248.59 - 0.6000000000000001, 35000.0, 36.5, 2631.7347656249967, 1280.8527343749995 - 0.6000000000000001, 35000.0, 37.0, 2711.495624999997, 1313.2568749999994 - 0.6000000000000001, 35000.0, 37.5, 2791.251171874996, 1345.8050781249995 - 0.6000000000000001, 35000.0, 38.0, 2870.9999999999955, 1378.4999999999993 - 0.6000000000000001, 35000.0, 38.5, 2950.723828125, 1411.363281250001 - 0.6000000000000001, 35000.0, 39.0, 3030.446875, 1444.368750000001 - 0.6000000000000001, 35000.0, 39.5, 3110.1714843749996, 1477.5148437500013 - 0.6000000000000001, 35000.0, 40.0, 3189.9, 1510.8000000000018 - 0.6000000000000001, 35000.0, 40.5, 3269.640625000001, 1544.13671875 - 0.6000000000000001, 35000.0, 41.0, 3349.3875000000007, 1577.6437499999997 - 0.6000000000000001, 35000.0, 41.5, 3429.1406250000014, 1611.3539062499995 - 0.6000000000000001, 35000.0, 42.0, 3508.9000000000015, 1645.299999999999 - 0.6000000000000001, 35000.0, 42.5, 3588.610937500001, 1679.6046875000006 - 0.6000000000000001, 35000.0, 43.0, 3668.3500000000017, 1714.1750000000004 - 0.6000000000000001, 35000.0, 43.5, 3748.1390625000017, 1749.0078125000007 - 0.6000000000000001, 35000.0, 44.0, 3828.0000000000023, 1784.1000000000008 - 0.6000000000000001, 35000.0, 44.5, 3908.196874999999, 1819.2531249999997 - 0.6000000000000001, 35000.0, 45.0, 3988.4124999999995, 1854.7374999999995 - 0.6000000000000001, 35000.0, 45.5, 4068.5718749999996, 1890.6281249999993 - 0.6000000000000001, 35000.0, 46.0, 4148.5999999999985, 1926.9999999999989 - 0.6000000000000001, 35000.0, 46.5, 4228.039062500001, 1964.0492187500004 - 0.6000000000000001, 35000.0, 47.0, 4307.350000000001, 2001.6812500000003 - 0.6000000000000001, 35000.0, 47.5, 4386.610937500003, 2039.9226562500005 - 0.6000000000000001, 35000.0, 48.0, 4465.900000000002, 2078.8000000000006 - 0.6000000000000001, 35000.0, 48.5, 4545.295312500004, 2118.339843750001 - 0.6000000000000001, 35000.0, 49.0, 4624.875000000005, 2158.5687500000013 - 0.6000000000000001, 35000.0, 49.5, 4704.717187500006, 2199.5132812500015 - 0.6000000000000001, 35000.0, 50.0, 4784.900000000007, 2241.200000000002 - 0.6000000000000001, 39000.0, 0.0, 142.46625477534002, 142.46625477534002 - 0.6000000000000001, 39000.0, 22.0, 307.3, 362.6000000000001 - 0.6000000000000001, 39000.0, 22.5, 365.6263671875, 384.06308593750003 - 0.6000000000000001, 39000.0, 23.0, 423.3515625, 405.4453125 - 0.6000000000000001, 39000.0, 23.5, 480.67597656250007, 426.80488281249995 - 0.6000000000000001, 39000.0, 24.0, 537.8000000000002, 448.1999999999999 - 0.6000000000000001, 39000.0, 24.5, 594.9240234375002, 469.6888671874998 - 0.6000000000000001, 39000.0, 25.0, 652.2484375000001, 491.32968749999964 - 0.6000000000000001, 39000.0, 25.5, 709.9736328125003, 513.1806640624995 - 0.6000000000000001, 39000.0, 26.0, 768.3000000000004, 535.2999999999995 - 0.6000000000000001, 39000.0, 26.5, 829.5333984375001, 558.3611328125 - 0.6000000000000001, 39000.0, 27.0, 891.8890625, 581.8421875 - 0.6000000000000001, 39000.0, 27.5, 955.2064453125001, 605.6958984375002 - 0.6000000000000001, 39000.0, 28.0, 1019.3250000000002, 629.875 - 0.6000000000000001, 39000.0, 28.5, 1084.0841796875002, 654.3322265625001 - 0.6000000000000001, 39000.0, 29.0, 1149.3234375000004, 679.0203125000002 - 0.6000000000000001, 39000.0, 29.5, 1214.8822265625004, 703.8919921875001 - 0.6000000000000001, 39000.0, 30.0, 1280.6000000000004, 728.9000000000002 - 0.6000000000000001, 39000.0, 30.5, 1344.6284179687502, 753.5048828124997 - 0.6000000000000001, 39000.0, 31.0, 1408.6554687500002, 778.1984374999997 - 0.6000000000000001, 39000.0, 31.5, 1472.6813476562504, 802.9802734374997 - 0.6000000000000001, 39000.0, 32.0, 1536.70625, 827.8499999999996 - 0.6000000000000001, 39000.0, 32.5, 1600.7303710937504, 852.8072265624996 - 0.6000000000000001, 39000.0, 33.0, 1664.7539062500005, 877.8515624999997 - 0.6000000000000001, 39000.0, 33.5, 1728.7770507812504, 902.9826171874994 - 0.6000000000000001, 39000.0, 34.0, 1792.8000000000004, 928.1999999999995 - 0.6000000000000001, 39000.0, 34.5, 1856.8249999999985, 953.3720703124992 - 0.6000000000000001, 39000.0, 35.0, 1920.849999999998, 978.6421874999991 - 0.6000000000000001, 39000.0, 35.5, 1984.8749999999977, 1004.0224609374987 - 0.6000000000000001, 39000.0, 36.0, 2048.8999999999974, 1029.5249999999985 - 0.6000000000000001, 39000.0, 36.5, 2112.9249999999975, 1055.1619140624985 - 0.6000000000000001, 39000.0, 37.0, 2176.9499999999966, 1080.9453124999977 - 0.6000000000000001, 39000.0, 37.5, 2240.9749999999963, 1106.8873046874976 - 0.6000000000000001, 39000.0, 38.0, 2304.999999999996, 1132.9999999999973 - 0.6000000000000001, 39000.0, 38.5, 2369.025000000001, 1159.400976562501 - 0.6000000000000001, 39000.0, 39.0, 2433.050000000002, 1185.9421875000012 - 0.6000000000000001, 39000.0, 39.5, 2497.075000000002, 1212.6123046875016 - 0.6000000000000001, 39000.0, 40.0, 2561.1000000000026, 1239.4000000000021 - 0.6000000000000001, 39000.0, 40.5, 2625.1249999999995, 1266.1367187500005 - 0.6000000000000001, 39000.0, 41.0, 2689.15, 1293.0312500000007 - 0.6000000000000001, 39000.0, 41.5, 2753.1749999999997, 1320.135156250001 - 0.6000000000000001, 39000.0, 42.0, 2817.2, 1347.5000000000011 - 0.6000000000000001, 39000.0, 42.5, 2881.1742187499985, 1375.3375000000003 - 0.6000000000000001, 39000.0, 43.0, 2945.168749999998, 1403.4750000000001 - 0.6000000000000001, 39000.0, 43.5, 3009.203906249998, 1431.9000000000003 - 0.6000000000000001, 39000.0, 44.0, 3073.299999999998, 1460.6000000000004 - 0.6000000000000001, 39000.0, 44.5, 3137.6765625000025, 1489.472656249999 - 0.6000000000000001, 39000.0, 45.0, 3202.0750000000035, 1518.6312499999988 - 0.6000000000000001, 39000.0, 45.5, 3266.435937500004, 1548.0992187499985 - 0.6000000000000001, 39000.0, 46.0, 3330.7000000000044, 1577.8999999999983 - 0.6000000000000001, 39000.0, 46.5, 3394.5148437499984, 1607.9593750000008 - 0.6000000000000001, 39000.0, 47.0, 3458.2312499999985, 1638.4375000000014 - 0.6000000000000001, 39000.0, 47.5, 3521.9070312499985, 1669.3968750000015 - 0.6000000000000001, 39000.0, 48.0, 3585.5999999999976, 1700.900000000002 - 0.6000000000000001, 39000.0, 48.5, 3649.367968749997, 1733.009375000002 - 0.6000000000000001, 39000.0, 49.0, 3713.2687499999965, 1765.7875000000026 - 0.6000000000000001, 39000.0, 49.5, 3777.3601562499957, 1799.2968750000027 - 0.6000000000000001, 39000.0, 50.0, 3841.6999999999953, 1833.6000000000033 - 0.6000000000000001, 43000.0, 0.0, 117.5486999009874, 117.5486999009874 - 0.6000000000000001, 43000.0, 22.0, 237.0999999999999, 335.2999999999998 - 0.6000000000000001, 43000.0, 22.5, 282.77871093749957, 342.2156249999996 - 0.6000000000000001, 43000.0, 23.0, 327.9328124999991, 351.37499999999983 - 0.6000000000000001, 43000.0, 23.5, 372.7205078124986, 362.52187500000025 - 0.6000000000000001, 43000.0, 24.0, 417.29999999999785, 375.40000000000083 - 0.6000000000000001, 43000.0, 24.5, 461.8294921874971, 389.7531250000013 - 0.6000000000000001, 43000.0, 25.0, 506.46718749999616, 405.3250000000021 - 0.6000000000000001, 43000.0, 25.5, 551.3712890624948, 421.85937500000273 - 0.6000000000000001, 43000.0, 26.0, 596.6999999999936, 439.1000000000032 - 0.6000000000000001, 43000.0, 26.5, 644.2289062499983, 454.529296874999 - 0.6000000000000001, 43000.0, 27.0, 692.591249999998, 470.02312499999846 - 0.6000000000000001, 43000.0, 27.5, 741.6679687499981, 485.7128906249981 - 0.6000000000000001, 43000.0, 28.0, 791.3399999999978, 501.7299999999977 - 0.6000000000000001, 43000.0, 28.5, 841.488281249998, 518.2058593749971 - 0.6000000000000001, 43000.0, 29.0, 891.9937499999979, 535.2718749999964 - 0.6000000000000001, 43000.0, 29.5, 942.7373437499979, 553.0594531249957 - 0.6000000000000001, 43000.0, 30.0, 993.5999999999982, 571.699999999995 - 0.6000000000000001, 43000.0, 30.5, 1043.179687500009, 593.3158203124988 - 0.6000000000000001, 43000.0, 31.0, 1092.7625000000103, 615.8578124999982 - 0.6000000000000001, 43000.0, 31.5, 1142.3515625000116, 639.2677734374984 - 0.6000000000000001, 43000.0, 32.0, 1191.950000000013, 663.4874999999985 - 0.6000000000000001, 43000.0, 32.5, 1241.5609375000151, 688.4587890624985 - 0.6000000000000001, 43000.0, 33.0, 1291.1875000000166, 714.123437499999 - 0.6000000000000001, 43000.0, 33.5, 1340.832812500019, 740.4232421874992 - 0.6000000000000001, 43000.0, 34.0, 1390.5000000000216, 767.2999999999995 - 0.6000000000000001, 43000.0, 34.5, 1440.4317187499882, 805.4276562499963 - 0.6000000000000001, 43000.0, 35.0, 1490.368749999985, 842.993749999996 - 0.6000000000000001, 43000.0, 35.5, 1540.291406249982, 878.9179687499951 - 0.6000000000000001, 43000.0, 36.0, 1590.1799999999773, 912.1199999999949 - 0.6000000000000001, 43000.0, 36.5, 1640.0148437499727, 941.519531249995 - 0.6000000000000001, 43000.0, 37.0, 1689.7762499999671, 966.0362499999951 - 0.6000000000000001, 43000.0, 37.5, 1739.4445312499606, 984.5898437499952 - 0.6000000000000001, 43000.0, 38.0, 1788.9999999999532, 996.0999999999956 - 0.6000000000000001, 43000.0, 38.5, 1837.9546875000299, 985.0203125000154 - 0.6000000000000001, 43000.0, 39.0, 1887.0000000000348, 972.237500000018 - 0.6000000000000001, 43000.0, 39.5, 1936.2203125000399, 959.885937500022 - 0.6000000000000001, 43000.0, 40.0, 1985.700000000045, 950.1000000000249 - 0.6000000000000001, 43000.0, 40.5, 2036.1796875000218, 948.4828124999924 - 0.6000000000000001, 43000.0, 41.0, 2086.825000000028, 952.3124999999918 - 0.6000000000000001, 43000.0, 41.5, 2137.4578125000353, 962.3359374999917 - 0.6000000000000001, 43000.0, 42.0, 2187.9000000000433, 979.2999999999915 - 0.6000000000000001, 43000.0, 42.5, 2237.0867187500053, 1011.2249999999976 - 0.6000000000000001, 43000.0, 43.0, 2286.081250000008, 1048.674999999993 - 0.6000000000000001, 43000.0, 43.5, 2335.0601562500096, 1089.4874999999881 - 0.6000000000000001, 43000.0, 44.0, 2384.200000000011, 1131.499999999983 - 0.6000000000000001, 43000.0, 44.5, 2434.5835937499896, 1168.5343749999963 - 0.6000000000000001, 43000.0, 45.0, 2485.118749999984, 1204.049999999996 - 0.6000000000000001, 43000.0, 45.5, 2535.619531249977, 1237.490624999996 - 0.6000000000000001, 43000.0, 46.0, 2585.8999999999714, 1268.299999999996 - 0.6000000000000001, 43000.0, 46.5, 2634.938281249975, 1291.890624999992 - 0.6000000000000001, 43000.0, 47.0, 2683.7187499999654, 1313.3499999999915 - 0.6000000000000001, 43000.0, 47.5, 2732.389843749954, 1333.7343749999907 - 0.6000000000000001, 43000.0, 48.0, 2781.0999999999385, 1354.0999999999892 - 0.6000000000000001, 43000.0, 48.5, 2829.9976562499187, 1375.5031249999881 - 0.6000000000000001, 43000.0, 49.0, 2879.2312499998943, 1398.9999999999857 - 0.6000000000000001, 43000.0, 49.5, 2928.9492187498645, 1425.646874999984 - 0.6000000000000001, 43000.0, 50.0, 2979.2999999998283, 1456.4999999999804 - 0.6000000000000001, 48000.0, 0.0, 92.43795859870832, 92.43795859870832 - 0.6000000000000001, 48000.0, 22.0, 185.49999999999963, 264.9999999999992 - 0.6000000000000001, 48000.0, 22.5, 222.13671875000028, 270.146484374999 - 0.6000000000000001, 48000.0, 23.0, 258.1062500000011, 277.2156249999991 - 0.6000000000000001, 48000.0, 23.5, 293.57265625000235, 285.9769531249991 - 0.6000000000000001, 48000.0, 24.0, 328.7000000000039, 296.19999999999925 - 0.6000000000000001, 48000.0, 24.5, 363.65234375000585, 307.6542968749995 - 0.6000000000000001, 48000.0, 25.0, 398.5937500000082, 320.10937499999983 - 0.6000000000000001, 48000.0, 25.5, 433.68828125001096, 333.3347656250004 - 0.6000000000000001, 48000.0, 26.0, 469.10000000001435, 347.10000000000076 - 0.6000000000000001, 48000.0, 26.5, 506.60351562499835, 359.0978515624988 - 0.6000000000000001, 48000.0, 27.0, 544.8443749999981, 371.05593749999827 - 0.6000000000000001, 48000.0, 27.5, 583.7105468749974, 383.09980468749757 - 0.6000000000000001, 48000.0, 28.0, 623.0899999999968, 395.3549999999967 - 0.6000000000000001, 48000.0, 28.5, 662.8707031249962, 407.9470703124959 - 0.6000000000000001, 48000.0, 29.0, 702.9406249999953, 421.0015624999949 - 0.6000000000000001, 48000.0, 29.5, 743.1877343749945, 434.6440234374939 - 0.6000000000000001, 48000.0, 30.0, 783.4999999999934, 448.9999999999926 - 0.6000000000000001, 48000.0, 30.5, 822.4865234374942, 466.1305664062477 - 0.6000000000000001, 48000.0, 31.0, 861.4359374999929, 484.0414062499972 - 0.6000000000000001, 48000.0, 31.5, 900.3580078124911, 502.67373046874667 - 0.6000000000000001, 48000.0, 32.0, 939.2624999999891, 521.9687499999961 - 0.6000000000000001, 48000.0, 32.5, 978.159179687487, 541.8676757812453 - 0.6000000000000001, 48000.0, 33.0, 1017.0578124999855, 562.3117187499946 - 0.6000000000000001, 48000.0, 33.5, 1055.9681640624824, 583.2420898437434 - 0.6000000000000001, 48000.0, 34.0, 1094.8999999999794, 604.5999999999926 - 0.6000000000000001, 48000.0, 34.5, 1134.1789062499965, 634.4473437499947 - 0.6000000000000001, 48000.0, 35.0, 1173.4687499999964, 663.831249999994 - 0.6000000000000001, 48000.0, 35.5, 1212.7492187499956, 691.9195312499932 - 0.6000000000000001, 48000.0, 36.0, 1251.9999999999952, 717.8799999999924 - 0.6000000000000001, 48000.0, 36.5, 1291.2007812499946, 740.880468749991 - 0.6000000000000001, 48000.0, 37.0, 1330.3312499999931, 760.0887499999901 - 0.6000000000000001, 48000.0, 37.5, 1369.3710937499923, 774.6726562499884 - 0.6000000000000001, 48000.0, 38.0, 1408.2999999999902, 783.7999999999871 - 0.6000000000000001, 48000.0, 38.5, 1446.5492187500106, 775.5074218749876 - 0.6000000000000001, 48000.0, 39.0, 1484.9312500000124, 765.8656249999844 - 0.6000000000000001, 48000.0, 39.5, 1523.5476562500146, 756.5160156249816 - 0.6000000000000001, 48000.0, 40.0, 1562.5000000000177, 749.0999999999775 - 0.6000000000000001, 48000.0, 40.5, 1602.7296875000013, 747.8156249999995 - 0.6000000000000001, 48000.0, 41.0, 1643.1625000000022, 750.7249999999996 - 0.6000000000000001, 48000.0, 41.5, 1683.564062500003, 758.4468750000002 - 0.6000000000000001, 48000.0, 42.0, 1723.7000000000041, 771.6000000000009 - 0.6000000000000001, 48000.0, 42.5, 1762.2499999999973, 796.5648437500099 - 0.6000000000000001, 48000.0, 43.0, 1800.4999999999955, 825.8937500000129 - 0.6000000000000001, 48000.0, 43.5, 1838.6499999999924, 857.9007812500151 - 0.6000000000000001, 48000.0, 44.0, 1876.8999999999896, 890.9000000000176 - 0.6000000000000001, 48000.0, 44.5, 1916.2390625000094, 920.1585937500087 - 0.6000000000000001, 48000.0, 45.0, 1955.7625000000137, 948.2562500000115 - 0.6000000000000001, 48000.0, 45.5, 1995.3546875000181, 974.7257812500147 - 0.6000000000000001, 48000.0, 46.0, 2034.900000000023, 999.1000000000186 - 0.6000000000000001, 48000.0, 46.5, 2073.8804687500015, 1017.5718750000143 - 0.6000000000000001, 48000.0, 47.0, 2112.743749999998, 1034.3500000000197 - 0.6000000000000001, 48000.0, 47.5, 2151.5351562499955, 1050.3031250000258 - 0.6000000000000001, 48000.0, 48.0, 2190.299999999994, 1066.300000000034 - 0.6000000000000001, 48000.0, 48.5, 2229.083593749993, 1083.209375000043 - 0.6000000000000001, 48000.0, 49.0, 2267.9312499999937, 1101.900000000054 - 0.6000000000000001, 48000.0, 49.5, 2306.888281249997, 1123.2406250000665 - 0.6000000000000001, 48000.0, 50.0, 2346.000000000006, 1148.1000000000818 - 0.65, 0.0, 0.0, 658.621923759989, 658.621923759989 - 0.65, 0.0, 22.0, 1500.3000000000015, 1624.6999999999716 - 0.65, 0.0, 22.5, 1785.2083984374112, 1914.081445312451 - 0.65, 0.0, 23.0, 2064.22031249976, 2055.0859374999573 - 0.65, 0.0, 23.5, 2338.847070312043, 2077.1474609374877 - 0.65, 0.0, 24.0, 2610.5999999992573, 2009.7000000000398 - 0.65, 0.0, 24.5, 2880.9904296864, 1882.1775390626099 - 0.65, 0.0, 25.0, 3151.529687498468, 1724.0140625001986 - 0.65, 0.0, 25.5, 3423.729101560457, 1564.6435546878 - 0.65, 0.0, 26.0, 3699.099999997366, 1433.5000000004138 - 0.65, 0.0, 26.5, 3994.462109375251, 1634.8029296875975 - 0.65, 0.0, 27.0, 4296.893125000345, 1938.902812500165 - 0.65, 0.0, 27.5, 4605.28007812546, 2328.127539062753 - 0.65, 0.0, 28.0, 4918.510000000603, 2784.805000000357 - 0.65, 0.0, 28.5, 5235.469921875775, 3291.2630859379833 - 0.65, 0.0, 29.0, 5555.046875000978, 3829.829687500627 - 0.65, 0.0, 29.5, 5876.1278906262105, 4382.832695313298 - 0.65, 0.0, 30.0, 6197.600000001476, 4932.60000000099 - 0.65, 0.0, 30.5, 6505.156738281109, 5249.318066405564 - 0.65, 0.0, 31.0, 6812.1351562498985, 5547.660156249195 - 0.65, 0.0, 31.5, 7118.678808593693, 5830.158105467822 - 0.65, 0.0, 32.0, 7424.931249999995, 6099.343749998945 - 0.65, 0.0, 32.5, 7731.036035156303, 6357.7489257800635 - 0.65, 0.0, 33.0, 8037.136718750119, 6607.905468748679 - 0.65, 0.0, 33.5, 8343.376855468943, 6852.345214842296 - 0.65, 0.0, 34.0, 8649.900000000269, 7093.59999999841 - 0.65, 0.0, 34.5, 8959.120742183795, 7605.463828123654 - 0.65, 0.0, 35.0, 9268.69531249507, 8093.37187499849 - 0.65, 0.0, 35.5, 9578.550976556173, 8534.021484373323 - 0.65, 0.0, 36.0, 9888.614999992105, 8904.109999998156 - 0.65, 0.0, 36.5, 10198.814648427862, 9180.33476562298 - 0.65, 0.0, 37.0, 10509.07718748844, 9339.393124997805 - 0.65, 0.0, 37.5, 10819.329882798835, 9357.982421872617 - 0.65, 0.0, 38.0, 11129.499999984046, 9212.799999997434 - 0.65, 0.0, 38.5, 11439.691992194956, 8669.14902343927 - 0.65, 0.0, 39.0, 11749.564062509933, 8024.732812502218 - 0.65, 0.0, 39.5, 12059.004101575343, 7303.225195315235 - 0.65, 0.0, 40.0, 12367.900000016221, 6528.3000000033535 - 0.65, 0.0, 40.5, 12676.429687501755, 5685.225781249539 - 0.65, 0.0, 41.0, 12984.075000002365, 4851.4437499993455 - 0.65, 0.0, 41.5, 13290.607812502942, 4065.989843749104 - 0.65, 0.0, 42.0, 13595.800000003432, 3367.8999999987996 - 0.65, 0.0, 42.5, 13895.896093748586, 2858.13593749872 - 0.65, 0.0, 43.0, 14195.606249998244, 2489.0374999983287 - 0.65, 0.0, 43.5, 14496.113281248012, 2274.870312497875 - 0.65, 0.0, 44.0, 14798.599999997963, 2229.8999999973635 - 0.65, 0.0, 44.5, 15110.245312498022, 2502.243750000499 - 0.65, 0.0, 45.0, 15423.837499996693, 2918.7750000007695 - 0.65, 0.0, 45.5, 15738.16093749488, 3440.2187500011723 - 0.65, 0.0, 46.0, 16051.999999992488, 4027.3000000017355 - 0.65, 0.0, 46.5, 16359.232812495371, 4576.333593747355 - 0.65, 0.0, 47.0, 16665.512499994205, 5138.218749996301 - 0.65, 0.0, 47.5, 16971.58593749303, 5699.4445312451 - 0.65, 0.0, 48.0, 17278.19999999185, 6246.499999993745 - 0.65, 0.0, 48.5, 17586.101562490734, 6765.8742187422495 - 0.65, 0.0, 49.0, 17896.037499989714, 7244.0562499906155 - 0.65, 0.0, 49.5, 18208.75468748881, 7667.535156238845 - 0.65, 0.0, 50.0, 18524.999999988093, 8022.799999986944 - 0.65, 2000.0, 0.0, 616.6477847122045, 616.6477847122045 - 0.65, 2000.0, 22.0, -10646.099999999955, -2787.5999999999985 - 0.65, 2000.0, 22.5, -12659.675390625034, -3493.5318359374955 - 0.65, 2000.0, 23.0, -14653.121875000126, -4153.332812499998 - 0.65, 2000.0, 23.5, -16633.307421875244, -4779.2423828125075 - 0.65, 2000.0, 24.0, -18607.100000000373, -5383.500000000018 - 0.65, 2000.0, 24.5, -20581.367578125537, -5978.345117187532 - 0.65, 2000.0, 25.0, -22562.978125000733, -6576.017187500052 - 0.65, 2000.0, 25.5, -24558.79960937596, -7188.75566406257 - 0.65, 2000.0, 26.0, -26575.700000001223, -7828.800000000091 - 0.65, 2000.0, 26.5, -28692.91249999966, -8635.673437499841 - 0.65, 2000.0, 27.0, -30849.074999999608, -9501.604999999794 - 0.65, 2000.0, 27.5, -33038.64999999953, -10417.014062499733 - 0.65, 2000.0, 28.0, -35256.09999999945, -11372.319999999667 - 0.65, 2000.0, 28.5, -37495.88749999937, -12357.942187499591 - 0.65, 2000.0, 29.0, -39752.474999999286, -13364.299999999505 - 0.65, 2000.0, 29.5, -42020.32499999919, -14381.812812499404 - 0.65, 2000.0, 30.0, -44293.89999999911, -15400.899999999296 - 0.65, 2000.0, 30.5, -46509.592578123964, -16275.485449218764 - 0.65, 2000.0, 31.0, -48725.465624998804, -17145.48359374998 - 0.65, 2000.0, 31.5, -50941.5121093736, -18014.31337890621 - 0.65, 2000.0, 32.0, -53157.724999998405, -18885.393749999923 - 0.65, 2000.0, 32.5, -55374.09726562317, -19762.14365234364 - 0.65, 2000.0, 33.0, -57590.62187499793, -20647.982031249856 - 0.65, 2000.0, 33.5, -59807.29179687264, -21546.327832031056 - 0.65, 2000.0, 34.0, -62024.09999999736, -22460.59999999976 - 0.65, 2000.0, 34.5, -64243.15421874741, -23585.732148437142 - 0.65, 2000.0, 35.0, -66462.1312499971, -24715.389062499635 - 0.65, 2000.0, 35.5, -68680.82265624679, -25834.750195312143 - 0.65, 2000.0, 36.0, -70899.01999999645, -26928.99499999965 - 0.65, 2000.0, 36.5, -73116.51484374606, -27983.30292968714 - 0.65, 2000.0, 37.0, -75333.0987499957, -28982.853437499645 - 0.65, 2000.0, 37.5, -77548.56328124528, -29912.82597656215 - 0.65, 2000.0, 38.0, -79762.69999999485, -30758.399999999638 - 0.65, 2000.0, 38.5, -81971.48671874327, -31374.53691406204 - 0.65, 2000.0, 39.0, -84180.50624999174, -31944.15468749954 - 0.65, 2000.0, 39.5, -86390.39765624, -32481.370117187096 - 0.65, 2000.0, 40.0, -88601.79999998808, -33000.299999999654 - 0.65, 2000.0, 40.5, -90818.62187499806, -33478.841406249245 - 0.65, 2000.0, 41.0, -93036.92499999749, -33981.81874999885 - 0.65, 2000.0, 41.5, -95256.04062499685, -34537.836718748345 - 0.65, 2000.0, 42.0, -97475.29999999619, -35175.4999999977 - 0.65, 2000.0, 42.5, -99690.64765624724, -36020.31171874908 - 0.65, 2000.0, 43.0, -101906.1562499958, -36965.21874999882 - 0.65, 2000.0, 43.5, -104122.51171874398, -38000.06640624851 - 0.65, 2000.0, 44.0, -106340.39999999171, -39114.69999999817 - 0.65, 2000.0, 44.5, -108567.2609374947, -40308.457031249396 - 0.65, 2000.0, 45.0, -110794.32499999327, -41557.89374999919 - 0.65, 2000.0, 45.5, -113019.57656249167, -42849.05859374901 - 0.65, 2000.0, 46.0, -115240.99999998997, -44167.99999999882 - 0.65, 2000.0, 46.5, -117445.84140625357, -45465.84843749995 - 0.65, 2000.0, 47.0, -119647.11875000449, -46777.5374999998 - 0.65, 2000.0, 47.5, -121847.11171875532, -48103.08281249957 - 0.65, 2000.0, 48.0, -124048.10000000609, -49442.49999999933 - 0.65, 2000.0, 48.5, -126252.3632812567, -50795.80468749904 - 0.65, 2000.0, 49.0, -128462.18125000712, -52163.0124999987 - 0.65, 2000.0, 49.5, -130679.8335937573, -53544.13906249833 - 0.65, 2000.0, 50.0, -132907.60000000728, -54939.19999999793 - 0.65, 5000.0, 0.0, 557.6751139135515, 557.6751139135515 - 0.65, 5000.0, 22.0, 10863.099999999979, 4690.200000000016 - 0.65, 5000.0, 22.5, 12928.25371093747, 5386.828515624992 - 0.65, 5000.0, 23.0, 14970.920312499939, 6061.971874999978 - 0.65, 5000.0, 23.5, 16998.376757812403, 6723.104296874975 - 0.65, 5000.0, 24.0, 19017.899999999856, 7377.6999999999825 - 0.65, 5000.0, 24.5, 21036.766992187288, 8033.23320312499 - 0.65, 5000.0, 25.0, 23062.254687499724, 8697.178125000017 - 0.65, 5000.0, 25.5, 25101.64003906213, 9377.008984375036 - 0.65, 5000.0, 26.0, 27162.199999999524, 10080.200000000057 - 0.65, 5000.0, 26.5, 29327.121874999695, 10888.93945312487 - 0.65, 5000.0, 27.0, 31532.10999999961, 11740.256874999868 - 0.65, 5000.0, 27.5, 33771.42812499952, 12628.81835937486 - 0.65, 5000.0, 28.0, 36039.33999999941, 13549.289999999852 - 0.65, 5000.0, 28.5, 38330.10937499929, 14496.337890624854 - 0.65, 5000.0, 29.0, 40637.999999999156, 15464.628124999854 - 0.65, 5000.0, 29.5, 42957.27562499903, 16448.826796874866 - 0.65, 5000.0, 30.0, 45282.19999999886, 17443.59999999988 - 0.65, 5000.0, 30.5, 47546.89238281294, 18396.405664062524 - 0.65, 5000.0, 31.0, 49811.489062500514, 19353.614062500023 - 0.65, 5000.0, 31.5, 52075.98183593807, 20314.387304687527 - 0.65, 5000.0, 32.0, 54340.36250000064, 21277.887500000037 - 0.65, 5000.0, 32.5, 56604.62285156319, 22243.27675781255 - 0.65, 5000.0, 33.0, 58868.75468750072, 23209.717187500064 - 0.65, 5000.0, 33.5, 61132.74980468827, 24176.370898437577 - 0.65, 5000.0, 34.0, 63396.600000000784, 25142.400000000107 - 0.65, 5000.0, 34.5, 65659.71382812473, 26118.505937499554 - 0.65, 5000.0, 35.0, 67922.72187499973, 27091.21249999953 - 0.65, 5000.0, 35.5, 70185.6714843747, 28058.582812499513 - 0.65, 5000.0, 36.0, 72448.60999999972, 29018.679999999513 - 0.65, 5000.0, 36.5, 74711.5847656247, 29969.56718749951 - 0.65, 5000.0, 37.0, 76974.6431249997, 30909.307499999522 - 0.65, 5000.0, 37.5, 79237.83242187469, 31835.964062499545 - 0.65, 5000.0, 38.0, 81501.19999999969, 32747.59999999958 - 0.65, 5000.0, 38.5, 83765.32792968182, 33631.49003906228 - 0.65, 5000.0, 39.0, 86029.45156249344, 34502.0796874996 - 0.65, 5000.0, 39.5, 88293.49941405497, 35359.829492186844 - 0.65, 5000.0, 40.0, 90557.39999999148, 36205.199999999044 - 0.65, 5000.0, 40.5, 92820.21953125083, 37015.670312499 - 0.65, 5000.0, 41.0, 95083.09375000086, 37823.874999998734 - 0.65, 5000.0, 41.5, 97346.29609375082, 38639.467187498485 - 0.65, 5000.0, 42.0, 99610.10000000062, 39472.099999998194 - 0.65, 5000.0, 42.5, 101874.78671874855, 40348.965624999604 - 0.65, 5000.0, 43.0, 104140.61874999858, 41255.16249999946 - 0.65, 5000.0, 43.5, 106407.86640624868, 42193.32812499926 - 0.65, 5000.0, 44.0, 108676.79999999884, 43166.09999999901 - 0.65, 5000.0, 44.5, 110953.24062500072, 44189.04921875039 - 0.65, 5000.0, 45.0, 113229.687500001, 45246.70625000045 - 0.65, 5000.0, 45.5, 115504.19062500139, 46336.535156250466 - 0.65, 5000.0, 46.0, 117774.80000000187, 47456.000000000415 - 0.65, 5000.0, 46.5, 120029.2101562473, 48612.8890625001 - 0.65, 5000.0, 47.0, 122279.96874999636, 49790.21250000027 - 0.65, 5000.0, 47.5, 124529.26796874519, 50981.30468750051 - 0.65, 5000.0, 48.0, 126779.29999999386, 52179.500000000786 - 0.65, 5000.0, 48.5, 129032.25703124223, 53378.13281250111 - 0.65, 5000.0, 49.0, 131290.3312499904, 54570.537500001476 - 0.65, 5000.0, 49.5, 133555.7148437383, 55750.04843750189 - 0.65, 5000.0, 50.0, 135830.5999999859, 56910.0000000024 - 0.65, 10000.0, 0.0, 469.3633531900852, 469.3633531900852 - 0.65, 10000.0, 22.0, 795.2000000000119, 1026.4999999999952 - 0.65, 10000.0, 22.5, 945.2783203125246, 1096.3898437500009 - 0.65, 10000.0, 23.0, 1094.198437500039, 1164.1062500000078 - 0.65, 10000.0, 23.5, 1242.419335937556, 1230.044531250017 - 0.65, 10000.0, 24.0, 1390.4000000000751, 1294.6000000000274 - 0.65, 10000.0, 24.5, 1538.5994140625974, 1358.16796875004 - 0.65, 10000.0, 25.0, 1687.4765625001228, 1421.1437500000545 - 0.65, 10000.0, 25.5, 1837.4904296876518, 1483.9226562500708 - 0.65, 10000.0, 26.0, 1989.1000000001848, 1546.900000000088 - 0.65, 10000.0, 26.5, 2147.7408203125183, 1614.3566406249815 - 0.65, 10000.0, 27.0, 2309.17968750003, 1683.024374999982 - 0.65, 10000.0, 27.5, 2473.022460937544, 1752.6324218749835 - 0.65, 10000.0, 28.0, 2638.875000000059, 1822.9099999999867 - 0.65, 10000.0, 28.5, 2806.3431640625768, 1893.5863281249908 - 0.65, 10000.0, 29.0, 2975.032812500095, 1964.3906249999964 - 0.65, 10000.0, 29.5, 3144.5498046876173, 2035.0521093750044 - 0.65, 10000.0, 30.0, 3314.500000000139, 2105.300000000014 - 0.65, 10000.0, 30.5, 3480.4512695313306, 2169.9613281250704 - 0.65, 10000.0, 31.0, 3646.4320312501018, 2234.1343750000788 - 0.65, 10000.0, 31.5, 3812.432714843875, 2298.0152343750888 - 0.65, 10000.0, 32.0, 3978.443750000151, 2361.8000000000975 - 0.65, 10000.0, 32.5, 4144.455566406429, 2425.6847656251075 - 0.65, 10000.0, 33.0, 4310.458593750208, 2489.865625000117 - 0.65, 10000.0, 33.5, 4476.443261718991, 2554.5386718751283 - 0.65, 10000.0, 34.0, 4642.400000000274, 2619.90000000014 - 0.65, 10000.0, 34.5, 4808.261406249771, 2688.475390625148 - 0.65, 10000.0, 35.0, 4974.08124999969, 2757.909375000183 - 0.65, 10000.0, 35.5, 5139.855468749597, 2828.176171875222 - 0.65, 10000.0, 36.0, 5305.579999999491, 2899.2500000002647 - 0.65, 10000.0, 36.5, 5471.25078124937, 2971.1050781253107 - 0.65, 10000.0, 37.0, 5636.863749999244, 3043.7156250003586 - 0.65, 10000.0, 37.5, 5802.414843749102, 3117.0558593754113 - 0.65, 10000.0, 38.0, 5967.899999998949, 3191.100000000466 - 0.65, 10000.0, 38.5, 6133.110546876656, 3269.14453125045 - 0.65, 10000.0, 39.0, 6298.353125001971, 3346.1187500005403 - 0.65, 10000.0, 39.5, 6463.669140627316, 3421.2585937506437 - 0.65, 10000.0, 40.0, 6629.100000002695, 3493.8000000007614 - 0.65, 10000.0, 40.5, 6794.86875000008, 3554.6156249999544 - 0.65, 10000.0, 41.0, 6960.762500000193, 3614.649999999963 - 0.65, 10000.0, 41.5, 7126.750000000339, 3676.484374999983 - 0.65, 10000.0, 42.0, 7292.8000000005195, 3742.700000000017 - 0.65, 10000.0, 42.5, 7458.728906250682, 3826.264843749964 - 0.65, 10000.0, 43.0, 7624.718750000945, 3915.218749999967 - 0.65, 10000.0, 43.5, 7790.799218751257, 4007.988281249973 - 0.65, 10000.0, 44.0, 7957.000000001619, 4102.999999999977 - 0.65, 10000.0, 44.5, 8123.764843749839, 4194.922656249986 - 0.65, 10000.0, 45.0, 8290.543749999866, 4287.4437500000095 - 0.65, 10000.0, 45.5, 8457.200781249905, 4380.492968750047 - 0.65, 10000.0, 46.0, 8623.599999999968, 4474.00000000011 - 0.65, 10000.0, 46.5, 8788.94531250067, 4571.226562499931 - 0.65, 10000.0, 47.0, 8954.025000000951, 4667.437499999914 - 0.65, 10000.0, 47.5, 9118.967187501281, 4761.229687499897 - 0.65, 10000.0, 48.0, 9283.900000001659, 4851.199999999881 - 0.65, 10000.0, 48.5, 9448.951562502078, 4935.945312499864 - 0.65, 10000.0, 49.0, 9614.250000002543, 5014.062499999845 - 0.65, 10000.0, 49.5, 9779.923437503045, 5084.148437499824 - 0.65, 10000.0, 50.0, 9946.100000003591, 5144.799999999801 - 0.65, 15000.0, 0.0, 392.478543851114, 392.478543851114 - 0.65, 15000.0, 22.0, 731.0999999999993, 904.0999999999998 - 0.65, 15000.0, 22.5, 869.8976562500008, 962.2480468750017 - 0.65, 15000.0, 23.0, 1007.2437500000025, 1019.6281250000039 - 0.65, 15000.0, 23.5, 1143.6179687500048, 1076.469140625006 - 0.65, 15000.0, 24.0, 1279.5000000000066, 1133.0000000000082 - 0.65, 15000.0, 24.5, 1415.3695312500097, 1189.4496093750115 - 0.65, 15000.0, 25.0, 1551.7062500000134, 1246.0468750000146 - 0.65, 15000.0, 25.5, 1688.989843750017, 1303.020703125019 - 0.65, 15000.0, 26.0, 1827.7000000000212, 1360.6000000000233 - 0.65, 15000.0, 26.5, 1973.3435546874975, 1421.3337890625005 - 0.65, 15000.0, 27.0, 2121.6603124999974, 1483.2634375000007 - 0.65, 15000.0, 27.5, 2272.268164062497, 1546.2201171875006 - 0.65, 15000.0, 28.0, 2424.784999999997, 1610.0350000000005 - 0.65, 15000.0, 28.5, 2578.828710937497, 1674.5392578125006 - 0.65, 15000.0, 29.0, 2734.0171874999955, 1739.5640625000005 - 0.65, 15000.0, 29.5, 2889.968320312495, 1804.9405859375 - 0.65, 15000.0, 30.0, 3046.2999999999956, 1870.4999999999998 - 0.65, 15000.0, 30.5, 3198.615917968728, 1934.0157226562533 - 0.65, 15000.0, 31.0, 3350.930468749975, 1997.5726562500045 - 0.65, 15000.0, 31.5, 3503.2438476562215, 2061.1979492187565 - 0.65, 15000.0, 32.0, 3655.5562499999683, 2124.918750000009 - 0.65, 15000.0, 32.5, 3807.8678710937143, 2188.762207031262 - 0.65, 15000.0, 33.0, 3960.1789062499597, 2252.7554687500156 - 0.65, 15000.0, 33.5, 4112.489550781206, 2316.9256835937695 - 0.65, 15000.0, 34.0, 4264.799999999951, 2381.300000000024 - 0.65, 15000.0, 34.5, 4417.115781249914, 2445.7279687499736 - 0.65, 15000.0, 35.0, 4569.431249999899, 2510.4312499999696 - 0.65, 15000.0, 35.5, 4721.746093749888, 2575.453906249966 - 0.65, 15000.0, 36.0, 4874.059999999871, 2640.839999999962 - 0.65, 15000.0, 36.5, 5026.372656249859, 2706.6335937499575 - 0.65, 15000.0, 37.0, 5178.683749999844, 2772.878749999952 - 0.65, 15000.0, 37.5, 5330.992968749829, 2839.6195312499476 - 0.65, 15000.0, 38.0, 5483.299999999816, 2906.899999999941 - 0.65, 15000.0, 38.5, 5635.5960937496875, 2975.326367187463 - 0.65, 15000.0, 39.0, 5787.8937499996255, 3044.0890624999574 - 0.65, 15000.0, 39.5, 5940.194531249555, 3113.1072265624516 - 0.65, 15000.0, 40.0, 6092.499999999477, 3182.299999999944 - 0.65, 15000.0, 40.5, 6244.82343749995, 3251.345312499994 - 0.65, 15000.0, 41.0, 6397.149999999937, 3320.4999999999927 - 0.65, 15000.0, 41.5, 6549.476562499922, 3389.77968749999 - 0.65, 15000.0, 42.0, 6701.799999999903, 3459.1999999999866 - 0.65, 15000.0, 42.5, 6853.984374999965, 3528.7179687499756 - 0.65, 15000.0, 43.0, 7006.21249999995, 3598.431249999965 - 0.65, 15000.0, 43.5, 7158.534374999931, 3668.3789062499563 - 0.65, 15000.0, 44.0, 7310.999999999905, 3738.599999999945 - 0.65, 15000.0, 44.5, 7464.139843749986, 3809.434375000001 - 0.65, 15000.0, 45.0, 7617.33124999998, 3880.5000000000027 - 0.65, 15000.0, 45.5, 7770.43203124997, 3951.7156250000035 - 0.65, 15000.0, 46.0, 7923.299999999959, 4023.000000000006 - 0.65, 15000.0, 46.5, 8075.085937499936, 4093.7093750000295 - 0.65, 15000.0, 47.0, 8226.637499999915, 4164.550000000039 - 0.65, 15000.0, 47.5, 8378.095312499894, 4235.665625000051 - 0.65, 15000.0, 48.0, 8529.59999999988, 4307.2000000000635 - 0.65, 15000.0, 48.5, 8681.29218749986, 4379.29687500008 - 0.65, 15000.0, 49.0, 8833.312499999838, 4452.100000000098 - 0.65, 15000.0, 49.5, 8985.80156249982, 4525.753125000117 - 0.65, 15000.0, 50.0, 9138.8999999998, 4600.40000000014 - 0.65, 20000.0, 0.0, 325.90250426198475, 325.90250426198475 - 0.65, 20000.0, 22.0, 768.9999999999983, 815.7999999999988 - 0.65, 20000.0, 22.5, 914.9675781249997, 877.0232421875014 - 0.65, 20000.0, 23.0, 1059.4218750000011, 936.9015625000039 - 0.65, 20000.0, 23.5, 1202.8652343750032, 995.7541015625065 - 0.65, 20000.0, 24.0, 1345.8000000000056, 1053.9000000000096 - 0.65, 20000.0, 24.5, 1488.728515625009, 1111.658398437512 - 0.65, 20000.0, 25.0, 1632.1531250000132, 1169.348437500016 - 0.65, 20000.0, 25.5, 1776.5761718750182, 1227.2892578125202 - 0.65, 20000.0, 26.0, 1922.5000000000232, 1285.8000000000254 - 0.65, 20000.0, 26.5, 2075.6974609374925, 1348.0955078124966 - 0.65, 20000.0, 27.0, 2231.7015624999904, 1411.7646874999953 - 0.65, 20000.0, 27.5, 2390.111132812486, 1476.630273437494 - 0.65, 20000.0, 28.0, 2550.5249999999814, 1542.5149999999921 - 0.65, 20000.0, 28.5, 2712.541992187476, 1609.2416015624904 - 0.65, 20000.0, 29.0, 2875.7609374999693, 1676.6328124999877 - 0.65, 20000.0, 29.5, 3039.7806640624626, 1744.5113671874856 - 0.65, 20000.0, 30.0, 3204.1999999999553, 1812.6999999999825 - 0.65, 20000.0, 30.5, 3364.399316406246, 1878.575683593751 - 0.65, 20000.0, 31.0, 3524.5976562499945, 1944.6398437500018 - 0.65, 20000.0, 31.5, 3684.795605468743, 2010.9481445312529 - 0.65, 20000.0, 32.0, 3844.993749999991, 2077.5562500000037 - 0.65, 20000.0, 32.5, 4005.1926757812407, 2144.519824218755 - 0.65, 20000.0, 33.0, 4165.392968749987, 2211.894531250005 - 0.65, 20000.0, 33.5, 4325.595214843736, 2279.736035156255 - 0.65, 20000.0, 34.0, 4485.799999999985, 2348.100000000005 - 0.65, 20000.0, 34.5, 4646.025546874982, 2418.208984374993 - 0.65, 20000.0, 35.0, 4806.253124999982, 2488.840624999992 - 0.65, 20000.0, 35.5, 4966.481640624981, 2559.9394531249905 - 0.65, 20000.0, 36.0, 5126.709999999978, 2631.4499999999894 - 0.65, 20000.0, 36.5, 5286.937109374977, 2703.316796874987 - 0.65, 20000.0, 37.0, 5447.161874999974, 2775.484374999985 - 0.65, 20000.0, 37.5, 5607.383203124974, 2847.8972656249834 - 0.65, 20000.0, 38.0, 5767.599999999971, 2920.49999999998 - 0.65, 20000.0, 38.5, 5927.802734374926, 2992.9312499999232 - 0.65, 20000.0, 39.0, 6088.003124999911, 3065.599999999912 - 0.65, 20000.0, 39.5, 6248.201953124895, 3138.5187499998992 - 0.65, 20000.0, 40.0, 6408.399999999878, 3211.6999999998848 - 0.65, 20000.0, 40.5, 6568.600000000065, 3285.0312500000023 - 0.65, 20000.0, 41.0, 6728.800000000085, 3358.700000000003 - 0.65, 20000.0, 41.5, 6889.000000000111, 3432.7687500000034 - 0.65, 20000.0, 42.0, 7049.200000000138, 3507.3000000000047 - 0.65, 20000.0, 42.5, 7209.271093750045, 3582.563281249995 - 0.65, 20000.0, 43.0, 7369.393750000064, 3658.33124999999 - 0.65, 20000.0, 43.5, 7529.619531250084, 3734.5835937499855 - 0.65, 20000.0, 44.0, 7690.000000000103, 3811.2999999999797 - 0.65, 20000.0, 44.5, 7851.094531249977, 3887.897656249963 - 0.65, 20000.0, 45.0, 8012.2437499999705, 3965.1437499999543 - 0.65, 20000.0, 45.5, 8173.296093749967, 4043.2429687499475 - 0.65, 20000.0, 46.0, 8334.099999999966, 4122.3999999999405 - 0.65, 20000.0, 46.5, 8493.753906250031, 4202.948437500017 - 0.65, 20000.0, 47.0, 8653.156250000036, 4284.91250000002 - 0.65, 20000.0, 47.5, 8812.455468750042, 4368.445312500027 - 0.65, 20000.0, 48.0, 8971.800000000047, 4453.700000000031 - 0.65, 20000.0, 48.5, 9131.338281250053, 4540.829687500035 - 0.65, 20000.0, 49.0, 9291.21875000006, 4629.9875000000375 - 0.65, 20000.0, 49.5, 9451.589843750067, 4721.326562500042 - 0.65, 20000.0, 50.0, 9612.600000000079, 4815.000000000045 - 0.65, 25000.0, 0.0, 268.5809375699026, 268.5809375699026 - 0.65, 25000.0, 22.0, 623.8999999999995, 664.9999999999985 - 0.65, 25000.0, 22.5, 742.3380859375014, 712.879101562499 - 0.65, 25000.0, 23.0, 859.5453125000031, 760.0546874999997 - 0.65, 25000.0, 23.5, 975.929882812505, 806.7279296875006 - 0.65, 25000.0, 24.0, 1091.900000000007, 853.1000000000014 - 0.65, 25000.0, 24.5, 1207.8638671875087, 899.3720703125027 - 0.65, 25000.0, 25.0, 1324.229687500011, 945.7453125000045 - 0.65, 25000.0, 25.5, 1441.4056640625138, 992.4208984375066 - 0.65, 25000.0, 26.0, 1559.8000000000175, 1039.6000000000092 - 0.65, 25000.0, 26.5, 1684.1029296874901, 1089.3623046874955 - 0.65, 25000.0, 27.0, 1810.685312499988, 1140.1378124999947 - 0.65, 25000.0, 27.5, 1939.2212890624849, 1191.8056640624939 - 0.65, 25000.0, 28.0, 2069.3849999999816, 1244.2449999999924 - 0.65, 25000.0, 28.5, 2200.8505859374786, 1297.3349609374907 - 0.65, 25000.0, 29.0, 2333.292187499974, 1350.9546874999892 - 0.65, 25000.0, 29.5, 2466.3839453124697, 1404.9833203124867 - 0.65, 25000.0, 30.0, 2599.7999999999656, 1459.2999999999854 - 0.65, 25000.0, 30.5, 2729.790917968771, 1512.3056640624943 - 0.65, 25000.0, 31.0, 2859.780468750027, 1565.4984374999935 - 0.65, 25000.0, 31.5, 2989.7688476562817, 1618.8982421874923 - 0.65, 25000.0, 32.0, 3119.7562500000386, 1672.5249999999908 - 0.65, 25000.0, 32.5, 3249.7428710937947, 1726.3986328124902 - 0.65, 25000.0, 33.0, 3379.728906250052, 1780.5390624999884 - 0.65, 25000.0, 33.5, 3509.71455078131, 1834.966210937487 - 0.65, 25000.0, 34.0, 3639.700000000069, 1889.699999999986 - 0.65, 25000.0, 34.5, 3769.69078124998, 1945.0605859374948 - 0.65, 25000.0, 35.0, 3899.6812499999814, 2000.7390624999919 - 0.65, 25000.0, 35.5, 4029.6710937499834, 2056.7267578124893 - 0.65, 25000.0, 36.0, 4159.659999999988, 2113.014999999986 - 0.65, 25000.0, 36.5, 4289.647656249993, 2169.595117187481 - 0.65, 25000.0, 37.0, 4419.633749999997, 2226.458437499977 - 0.65, 25000.0, 37.5, 4549.617968750007, 2283.5962890624724 - 0.65, 25000.0, 38.0, 4679.600000000018, 2340.9999999999654 - 0.65, 25000.0, 38.5, 4809.576367187426, 2398.6693359373908 - 0.65, 25000.0, 39.0, 4939.551562499908, 2456.582812499874 - 0.65, 25000.0, 39.5, 5069.525976562386, 2514.729882812356 - 0.65, 25000.0, 40.0, 5199.499999999859, 2573.0999999998376 - 0.65, 25000.0, 40.5, 5329.471093749947, 2631.5429687500337 - 0.65, 25000.0, 41.0, 5459.443749999929, 2690.243750000043 - 0.65, 25000.0, 41.5, 5589.4195312499105, 2749.2476562500538 - 0.65, 25000.0, 42.0, 5719.399999999889, 2808.6000000000645 - 0.65, 25000.0, 42.5, 5849.296874999987, 2868.428124999944 - 0.65, 25000.0, 43.0, 5979.237499999968, 2928.662499999929 - 0.65, 25000.0, 43.5, 6109.259374999944, 2989.3156249999124 - 0.65, 25000.0, 44.0, 6239.399999999914, 3050.399999999893 - 0.65, 25000.0, 44.5, 6370.087500000035, 3111.6585937500213 - 0.65, 25000.0, 45.0, 6500.812500000043, 3173.481250000025 - 0.65, 25000.0, 45.5, 6631.456250000049, 3235.9882812500314 - 0.65, 25000.0, 46.0, 6761.900000000054, 3299.300000000035 - 0.65, 25000.0, 46.5, 6891.427343750004, 3363.5835937499755 - 0.65, 25000.0, 47.0, 7020.756250000006, 3428.8937499999665 - 0.65, 25000.0, 47.5, 7150.00703125001, 3495.3320312499577 - 0.65, 25000.0, 48.0, 7279.30000000001, 3562.9999999999463 - 0.65, 25000.0, 48.5, 7408.755468750012, 3631.9992187499342 - 0.65, 25000.0, 49.0, 7538.493750000012, 3702.4312499999205 - 0.65, 25000.0, 49.5, 7668.63515625001, 3774.397656249905 - 0.65, 25000.0, 50.0, 7799.300000000009, 3847.999999999889 - 0.65, 30000.0, 0.0, 219.53345724306766, 219.53345724306766 - 0.65, 30000.0, 22.0, 498.3000000000004, 540.5 - 0.65, 30000.0, 22.5, 592.9158203125018, 578.0794921875012 - 0.65, 30000.0, 23.0, 686.535937500004, 615.1390625000021 - 0.65, 30000.0, 23.5, 779.4880859375069, 651.829101562503 - 0.65, 30000.0, 24.0, 872.1000000000104, 688.3000000000042 - 0.65, 30000.0, 24.5, 964.6994140625151, 724.7021484375056 - 0.65, 30000.0, 25.0, 1057.6140625000203, 761.1859375000071 - 0.65, 30000.0, 25.5, 1151.1716796875266, 797.9017578125088 - 0.65, 30000.0, 26.0, 1245.7000000000342, 835.0000000000109 - 0.65, 30000.0, 26.5, 1344.957031249994, 874.0652343749946 - 0.65, 30000.0, 27.0, 1446.0362499999928, 913.8956249999934 - 0.65, 30000.0, 27.5, 1548.6773437499903, 954.3957031249925 - 0.65, 30000.0, 28.0, 1652.6199999999872, 995.469999999991 - 0.65, 30000.0, 28.5, 1757.6039062499838, 1037.0230468749896 - 0.65, 30000.0, 29.0, 1863.3687499999799, 1078.9593749999888 - 0.65, 30000.0, 29.5, 1969.6542187499751, 1121.183515624988 - 0.65, 30000.0, 30.0, 2076.19999999997, 1163.599999999986 - 0.65, 30000.0, 30.5, 2180.0125000000185, 1204.87919921875 - 0.65, 30000.0, 31.0, 2283.8250000000203, 1246.2773437500005 - 0.65, 30000.0, 31.5, 2387.6375000000226, 1287.8165039062505 - 0.65, 30000.0, 32.0, 2491.4500000000253, 1329.5187500000004 - 0.65, 30000.0, 32.5, 2595.2625000000266, 1371.4061523437513 - 0.65, 30000.0, 33.0, 2699.0750000000307, 1413.5007812500012 - 0.65, 30000.0, 33.5, 2802.8875000000326, 1455.8247070312505 - 0.65, 30000.0, 34.0, 2906.7000000000353, 1498.400000000001 - 0.65, 30000.0, 34.5, 3010.5157812499533, 1541.5666015624893 - 0.65, 30000.0, 35.0, 3114.3312499999465, 1584.9984374999865 - 0.65, 30000.0, 35.5, 3218.1460937499396, 1628.6873046874832 - 0.65, 30000.0, 36.0, 3321.959999999931, 1672.62499999998 - 0.65, 30000.0, 36.5, 3425.772656249923, 1716.8033203124764 - 0.65, 30000.0, 37.0, 3529.583749999915, 1761.214062499973 - 0.65, 30000.0, 37.5, 3633.392968749907, 1805.8490234374685 - 0.65, 30000.0, 38.0, 3737.199999999897, 1850.6999999999641 - 0.65, 30000.0, 38.5, 3840.9960937498045, 1895.7746093749938 - 0.65, 30000.0, 39.0, 3944.7937499997693, 1941.040624999997 - 0.65, 30000.0, 39.5, 4048.5945312497283, 1986.4863281249995 - 0.65, 30000.0, 40.0, 4152.399999999683, 2032.1000000000035 - 0.65, 30000.0, 40.5, 4256.22343750006, 2077.758593749998 - 0.65, 30000.0, 41.0, 4360.050000000074, 2123.606249999998 - 0.65, 30000.0, 41.5, 4463.876562500086, 2169.675781249998 - 0.65, 30000.0, 42.0, 4567.700000000098, 2215.9999999999977 - 0.65, 30000.0, 42.5, 4671.423437499988, 2262.3968750000186 - 0.65, 30000.0, 43.0, 4775.1749999999865, 2309.200000000024 - 0.65, 30000.0, 43.5, 4878.989062499987, 2356.528125000031 - 0.65, 30000.0, 44.0, 4982.899999999991, 2404.500000000038 - 0.65, 30000.0, 44.5, 5087.274218749989, 2453.789062500001 - 0.65, 30000.0, 45.0, 5191.681249999992, 2503.737500000003 - 0.65, 30000.0, 45.5, 5296.022656249995, 2554.242187500004 - 0.65, 30000.0, 46.0, 5400.200000000003, 2605.2000000000066 - 0.65, 30000.0, 46.5, 5503.61874999995, 2655.8867187499936 - 0.65, 30000.0, 47.0, 5606.874999999931, 2707.068749999994 - 0.65, 30000.0, 47.5, 5710.06874999991, 2758.8914062499935 - 0.65, 30000.0, 48.0, 5813.29999999989, 2811.4999999999955 - 0.65, 30000.0, 48.5, 5916.668749999869, 2865.039843749996 - 0.65, 30000.0, 49.0, 6020.274999999845, 2919.6562499999973 - 0.65, 30000.0, 49.5, 6124.218749999823, 2975.4945312499985 - 0.65, 30000.0, 50.0, 6228.599999999798, 3032.7000000000007 - 0.65, 35000.0, 0.0, 177.84705823118784, 177.84705823118784 - 0.65, 35000.0, 22.0, 381.50000000000006, 445.8000000000001 - 0.65, 35000.0, 22.5, 453.8398437500003, 474.18164062500017 - 0.65, 35000.0, 23.0, 525.4562500000005, 502.14687499999997 - 0.65, 35000.0, 23.5, 596.5945312500008, 529.8136718750004 - 0.65, 35000.0, 24.0, 667.5000000000011, 557.3000000000001 - 0.65, 35000.0, 24.5, 738.4179687500015, 584.7238281250003 - 0.65, 35000.0, 25.0, 809.5937500000019, 612.2031250000002 - 0.65, 35000.0, 25.5, 881.2726562500021, 639.8558593750003 - 0.65, 35000.0, 26.0, 953.7000000000024, 667.8000000000003 - 0.65, 35000.0, 26.5, 1029.7091796874997, 697.2691406249995 - 0.65, 35000.0, 27.0, 1107.1053124999999, 727.3293749999995 - 0.65, 35000.0, 27.5, 1185.690039062499, 757.9074218749994 - 0.65, 35000.0, 28.0, 1265.2649999999992, 788.9299999999995 - 0.65, 35000.0, 28.5, 1345.6318359374998, 820.3238281249995 - 0.65, 35000.0, 29.0, 1426.5921874999992, 852.0156249999995 - 0.65, 35000.0, 29.5, 1507.9476953124995, 883.9321093749998 - 0.65, 35000.0, 30.0, 1589.4999999999989, 915.9999999999998 - 0.65, 35000.0, 30.5, 1668.963867187503, 947.243261718751 - 0.65, 35000.0, 31.0, 1748.4265625000032, 978.5773437500013 - 0.65, 35000.0, 31.5, 1827.8884765625035, 1010.0149414062514 - 0.65, 35000.0, 32.0, 1907.3500000000038, 1041.5687500000015 - 0.65, 35000.0, 32.5, 1986.8115234375048, 1073.2514648437523 - 0.65, 35000.0, 33.0, 2066.2734375000055, 1105.0757812500028 - 0.65, 35000.0, 33.5, 2145.7361328125057, 1137.0543945312531 - 0.65, 35000.0, 34.0, 2225.200000000006, 1169.2000000000035 - 0.65, 35000.0, 34.5, 2304.678554687506, 1201.6626953124994 - 0.65, 35000.0, 35.0, 2384.1578125000065, 1234.3046874999989 - 0.65, 35000.0, 35.5, 2463.636914062506, 1267.125585937498 - 0.65, 35000.0, 36.0, 2543.115000000008, 1300.1249999999973 - 0.65, 35000.0, 36.5, 2622.591210937508, 1333.3025390624962 - 0.65, 35000.0, 37.0, 2702.0646875000098, 1366.6578124999955 - 0.65, 35000.0, 37.5, 2781.5345703125095, 1400.190429687494 - 0.65, 35000.0, 38.0, 2861.00000000001, 1433.8999999999933 - 0.65, 35000.0, 38.5, 2940.447460937516, 1467.8230468750091 - 0.65, 35000.0, 39.0, 3019.895312500019, 1501.9031250000103 - 0.65, 35000.0, 39.5, 3099.3455078125216, 1536.1316406250112 - 0.65, 35000.0, 40.0, 3178.8000000000247, 1570.5000000000123 - 0.65, 35000.0, 40.5, 3258.269531250007, 1604.900000000006 - 0.65, 35000.0, 41.0, 3337.7437500000083, 1639.462500000008 - 0.65, 35000.0, 41.5, 3417.2210937500095, 1674.2187500000098 - 0.65, 35000.0, 42.0, 3496.700000000011, 1709.2000000000128 - 0.65, 35000.0, 42.5, 3576.112500000005, 1744.2031249999973 - 0.65, 35000.0, 43.0, 3655.550000000009, 1779.587499999996 - 0.65, 35000.0, 43.5, 3735.037500000013, 1815.4781249999949 - 0.65, 35000.0, 44.0, 3814.600000000017, 1851.9999999999932 - 0.65, 35000.0, 44.5, 3894.512500000008, 1890.110156250006 - 0.65, 35000.0, 45.0, 3974.450000000012, 1928.7687500000077 - 0.65, 35000.0, 45.5, 4054.337500000016, 1967.7679687500097 - 0.65, 35000.0, 46.0, 4134.100000000017, 2006.9000000000115 - 0.65, 35000.0, 46.5, 4213.291406250009, 2045.0273437500025 - 0.65, 35000.0, 47.0, 4292.356250000012, 2083.2437500000033 - 0.65, 35000.0, 47.5, 4371.367968750016, 2121.7132812500045 - 0.65, 35000.0, 48.0, 4450.40000000002, 2160.6000000000054 - 0.65, 35000.0, 48.5, 4529.525781250025, 2200.067968750008 - 0.65, 35000.0, 49.0, 4608.818750000029, 2240.281250000009 - 0.65, 35000.0, 49.5, 4688.352343750035, 2281.4039062500106 - 0.65, 35000.0, 50.0, 4768.200000000043, 2323.6000000000126 - 0.65, 39000.0, 0.0, 147.50825332785192, 147.50825332785192 - 0.65, 39000.0, 22.0, 306.40000000000003, 387.0999999999999 - 0.65, 39000.0, 22.5, 364.5087890624999, 409.57851562499985 - 0.65, 39000.0, 23.0, 422.0296874999995, 431.8343749999998 - 0.65, 39000.0, 23.5, 479.16074218749924, 453.9480468749999 - 0.65, 39000.0, 24.0, 536.0999999999988, 475.99999999999983 - 0.65, 39000.0, 24.5, 593.0455078124979, 498.0707031249999 - 0.65, 39000.0, 25.0, 650.1953124999973, 520.240625 - 0.65, 39000.0, 25.5, 707.7474609374963, 542.5902343749999 - 0.65, 39000.0, 26.0, 765.8999999999951, 565.1999999999999 - 0.65, 39000.0, 26.5, 826.9359375000001, 588.9337890625002 - 0.65, 39000.0, 27.0, 889.0875000000003, 613.1334375000001 - 0.65, 39000.0, 27.5, 952.1953125, 637.7451171875006 - 0.65, 39000.0, 28.0, 1016.0999999999998, 662.7150000000005 - 0.65, 39000.0, 28.5, 1080.6421874999999, 687.9892578125008 - 0.65, 39000.0, 29.0, 1145.6625000000004, 713.5140625000012 - 0.65, 39000.0, 29.5, 1211.0015624999994, 739.2355859375012 - 0.65, 39000.0, 30.0, 1276.4999999999995, 765.1000000000016 - 0.65, 39000.0, 30.5, 1340.3250000000032, 790.4985351562498 - 0.65, 39000.0, 31.0, 1404.1500000000028, 815.9851562499997 - 0.65, 39000.0, 31.5, 1467.9750000000035, 841.5588867187498 - 0.65, 39000.0, 32.0, 1531.8000000000034, 867.2187499999999 - 0.65, 39000.0, 32.5, 1595.6250000000039, 892.9637695312501 - 0.65, 39000.0, 33.0, 1659.450000000004, 918.7929687500001 - 0.65, 39000.0, 33.5, 1723.275000000004, 944.7053710937502 - 0.65, 39000.0, 34.0, 1787.1000000000042, 970.7 - 0.65, 39000.0, 34.5, 1850.9250000000002, 996.5982812500032 - 0.65, 39000.0, 35.0, 1914.75, 1022.5937500000036 - 0.65, 39000.0, 35.5, 1978.5749999999996, 1048.7023437500036 - 0.65, 39000.0, 36.0, 2042.3999999999996, 1074.940000000004 - 0.65, 39000.0, 36.5, 2106.2249999999995, 1101.3226562500038 - 0.65, 39000.0, 37.0, 2170.0499999999993, 1127.8662500000034 - 0.65, 39000.0, 37.5, 2233.8749999999995, 1154.5867187500037 - 0.65, 39000.0, 38.0, 2297.6999999999985, 1181.5000000000036 - 0.65, 39000.0, 38.5, 2361.5250000000005, 1208.7675781250064 - 0.65, 39000.0, 39.0, 2425.3499999999995, 1236.1843750000073 - 0.65, 39000.0, 39.5, 2489.174999999998, 1263.7339843750087 - 0.65, 39000.0, 40.0, 2552.9999999999964, 1291.4000000000103 - 0.65, 39000.0, 40.5, 2616.8289062499957, 1318.9570312500045 - 0.65, 39000.0, 41.0, 2680.656249999994, 1346.6812500000058 - 0.65, 39000.0, 41.5, 2744.480468749991, 1374.6398437500072 - 0.65, 39000.0, 42.0, 2808.2999999999874, 1402.9000000000087 - 0.65, 39000.0, 42.5, 2872.0507812500036, 1431.7281250000033 - 0.65, 39000.0, 43.0, 2935.818750000004, 1460.912500000004 - 0.65, 39000.0, 43.5, 2999.627343750004, 1490.4406250000045 - 0.65, 39000.0, 44.0, 3063.5000000000045, 1520.3000000000045 - 0.65, 39000.0, 44.5, 3127.6710937500193, 1550.2554687499983 - 0.65, 39000.0, 45.0, 3191.868750000026, 1580.6062499999975 - 0.65, 39000.0, 45.5, 3256.032031250034, 1611.428906249997 - 0.65, 39000.0, 46.0, 3320.1000000000427, 1642.7999999999965 - 0.65, 39000.0, 46.5, 3383.7187500000045, 1675.2765625000031 - 0.65, 39000.0, 47.0, 3447.2375000000047, 1708.262500000004 - 0.65, 39000.0, 47.5, 3510.712500000004, 1741.6421875000049 - 0.65, 39000.0, 48.0, 3574.2000000000044, 1775.3000000000059 - 0.65, 39000.0, 48.5, 3637.7562500000035, 1809.1203125000068 - 0.65, 39000.0, 49.0, 3701.4375000000023, 1842.9875000000081 - 0.65, 39000.0, 49.5, 3765.300000000001, 1876.7859375000091 - 0.65, 39000.0, 50.0, 3829.400000000001, 1910.4000000000103 - 0.65, 43000.0, 0.0, 121.70884558380226, 121.70884558380226 - 0.65, 43000.0, 22.0, 244.9, 346.49999999999994 - 0.65, 43000.0, 22.5, 291.5542968749999, 361.2892578124999 - 0.65, 43000.0, 23.0, 337.7156249999998, 376.88593749999984 - 0.65, 43000.0, 23.5, 383.54414062499984, 393.21464843750005 - 0.65, 43000.0, 24.0, 429.1999999999995, 410.2 - 0.65, 43000.0, 24.5, 474.8433593749994, 427.7666015625 - 0.65, 43000.0, 25.0, 520.6343749999994, 445.8390625000001 - 0.65, 43000.0, 25.5, 566.733203124999, 464.34199218750007 - 0.65, 43000.0, 26.0, 613.299999999999, 483.2 - 0.65, 43000.0, 26.5, 662.165625, 501.73339843750017 - 0.65, 43000.0, 27.0, 711.9150000000001, 520.4365625 - 0.65, 43000.0, 27.5, 762.4218750000002, 539.3376953125002 - 0.65, 43000.0, 28.0, 813.5600000000003, 558.465 - 0.65, 43000.0, 28.5, 865.2031250000005, 577.8466796874997 - 0.65, 43000.0, 29.0, 917.2250000000006, 597.5109374999994 - 0.65, 43000.0, 29.5, 969.4993750000006, 617.4859765624993 - 0.65, 43000.0, 30.0, 1021.9000000000007, 637.7999999999989 - 0.65, 43000.0, 30.5, 1072.9647460937517, 659.0726562500004 - 0.65, 43000.0, 31.0, 1124.0304687500025, 680.6843750000005 - 0.65, 43000.0, 31.5, 1175.0981445312525, 702.6070312500004 - 0.65, 43000.0, 32.0, 1226.168750000003, 724.8125000000006 - 0.65, 43000.0, 32.5, 1277.243261718753, 747.2726562500008 - 0.65, 43000.0, 33.0, 1328.322656250004, 769.9593750000008 - 0.65, 43000.0, 33.5, 1379.4079101562547, 792.8445312500014 - 0.65, 43000.0, 34.0, 1430.500000000005, 815.9000000000012 - 0.65, 43000.0, 34.5, 1481.671679687496, 841.8153515624999 - 0.65, 43000.0, 35.0, 1532.8453124999946, 867.5859375 - 0.65, 43000.0, 35.5, 1584.015039062493, 892.9248046875001 - 0.65, 43000.0, 36.0, 1635.1749999999913, 917.5450000000004 - 0.65, 43000.0, 36.5, 1686.3193359374893, 941.1595703125004 - 0.65, 43000.0, 37.0, 1737.4421874999875, 963.481562500001 - 0.65, 43000.0, 37.5, 1788.537695312485, 984.2240234375013 - 0.65, 43000.0, 38.0, 1839.5999999999826, 1003.1000000000017 - 0.65, 43000.0, 38.5, 1890.4861328125157, 1015.7292968750085 - 0.65, 43000.0, 39.0, 1941.3984375000182, 1028.0406250000099 - 0.65, 43000.0, 39.5, 1992.3615234375206, 1040.6566406250113 - 0.65, 43000.0, 40.0, 2043.4000000000226, 1054.2000000000132 - 0.65, 43000.0, 40.5, 2094.728906250007, 1070.1117187499988 - 0.65, 43000.0, 41.0, 2146.1062500000103, 1087.8687499999992 - 0.65, 43000.0, 41.5, 2197.4804687500123, 1107.7664062499998 - 0.65, 43000.0, 42.0, 2248.8000000000156, 1130.1000000000001 - 0.65, 43000.0, 42.5, 2299.728125000004, 1157.7859375000023 - 0.65, 43000.0, 43.0, 2350.612500000005, 1187.4500000000028 - 0.65, 43000.0, 43.5, 2401.5156250000073, 1218.3390625000022 - 0.65, 43000.0, 44.0, 2452.500000000008, 1249.7000000000023 - 0.65, 43000.0, 44.5, 2504.007031249997, 1279.3539062499983 - 0.65, 43000.0, 45.0, 2555.5687499999945, 1308.5437499999982 - 0.65, 43000.0, 45.5, 2607.0960937499935, 1337.0867187499982 - 0.65, 43000.0, 46.0, 2658.4999999999914, 1364.7999999999981 - 0.65, 43000.0, 46.5, 2709.273437499995, 1390.1375000000003 - 0.65, 43000.0, 47.0, 2759.9124999999935, 1414.8250000000005 - 0.65, 43000.0, 47.5, 2810.4953124999906, 1439.225000000001 - 0.65, 43000.0, 48.0, 2861.0999999999876, 1463.7000000000012 - 0.65, 43000.0, 48.5, 2911.804687499983, 1488.6125000000015 - 0.65, 43000.0, 49.0, 2962.6874999999773, 1514.3250000000012 - 0.65, 43000.0, 49.5, 3013.8265624999694, 1541.2000000000014 - 0.65, 43000.0, 50.0, 3065.29999999996, 1569.6000000000008 - 0.65, 48000.0, 0.0, 95.70941438440863, 95.70941438440863 - 0.65, 48000.0, 22.0, 192.49999999999991, 273.1999999999999 - 0.65, 48000.0, 22.5, 229.4339843750001, 284.73886718749986 - 0.65, 48000.0, 23.0, 265.90312500000044, 296.9640624999997 - 0.65, 48000.0, 23.5, 302.04570312500067, 309.8072265624998 - 0.65, 48000.0, 24.0, 338.00000000000125, 323.1999999999999 - 0.65, 48000.0, 24.5, 373.9042968750018, 337.0740234375 - 0.65, 48000.0, 25.0, 409.8968750000025, 351.3609375000001 - 0.65, 48000.0, 25.5, 446.11601562500334, 365.9923828125004 - 0.65, 48000.0, 26.0, 482.7000000000042, 380.9000000000007 - 0.65, 48000.0, 26.5, 521.2089843749995, 395.44804687499993 - 0.65, 48000.0, 27.0, 560.4406249999994, 410.1031249999998 - 0.65, 48000.0, 27.5, 600.2894531249993, 424.8941406249997 - 0.65, 48000.0, 28.0, 640.649999999999, 439.84999999999934 - 0.65, 48000.0, 28.5, 681.4167968749989, 454.9996093749991 - 0.65, 48000.0, 29.0, 722.4843749999985, 470.37187499999874 - 0.65, 48000.0, 29.5, 763.7472656249982, 485.99570312499844 - 0.65, 48000.0, 30.0, 805.0999999999979, 501.8999999999982 - 0.65, 48000.0, 30.5, 845.2968749999986, 518.6940429687495 - 0.65, 48000.0, 31.0, 885.481249999998, 535.7710937499995 - 0.65, 48000.0, 31.5, 925.6562499999978, 553.1047851562495 - 0.65, 48000.0, 32.0, 965.8249999999972, 570.6687499999995 - 0.65, 48000.0, 32.5, 1005.9906249999965, 588.4366210937492 - 0.65, 48000.0, 33.0, 1046.1562499999964, 606.3820312499994 - 0.65, 48000.0, 33.5, 1086.3249999999955, 624.4786132812491 - 0.65, 48000.0, 34.0, 1126.4999999999945, 642.6999999999989 - 0.65, 48000.0, 34.5, 1166.7778906249994, 663.0537890624979 - 0.65, 48000.0, 35.0, 1207.0593749999994, 683.2859374999975 - 0.65, 48000.0, 35.5, 1247.338671874999, 703.1763671874975 - 0.65, 48000.0, 36.0, 1287.6099999999988, 722.5049999999968 - 0.65, 48000.0, 36.5, 1327.867578124998, 741.0517578124966 - 0.65, 48000.0, 37.0, 1368.1056249999979, 758.5965624999963 - 0.65, 48000.0, 37.5, 1408.3183593749966, 774.9193359374958 - 0.65, 48000.0, 38.0, 1448.4999999999952, 789.7999999999952 - 0.65, 48000.0, 38.5, 1488.4886718750054, 799.8765624999976 - 0.65, 48000.0, 39.0, 1528.5156250000064, 809.6999999999966 - 0.65, 48000.0, 39.5, 1568.6097656250076, 819.7484374999955 - 0.65, 48000.0, 40.0, 1608.8000000000093, 830.4999999999944 - 0.65, 48000.0, 40.5, 1649.3515625000011, 843.0226562500013 - 0.65, 48000.0, 41.0, 1689.962500000002, 856.9687500000019 - 0.65, 48000.0, 41.5, 1730.567187500003, 872.5804687500026 - 0.65, 48000.0, 42.0, 1771.1000000000033, 890.1000000000033 - 0.65, 48000.0, 42.5, 1811.174999999999, 911.8437500000031 - 0.65, 48000.0, 43.0, 1851.1749999999981, 935.1500000000038 - 0.65, 48000.0, 43.5, 1891.1624999999967, 959.4312500000044 - 0.65, 48000.0, 44.0, 1931.1999999999957, 984.100000000005 - 0.65, 48000.0, 44.5, 1971.6468750000035, 1007.4867187500053 - 0.65, 48000.0, 45.0, 2012.1500000000049, 1030.5187500000068 - 0.65, 48000.0, 45.5, 2052.653125000006, 1053.0414062500085 - 0.65, 48000.0, 46.0, 2093.100000000008, 1074.9000000000106 - 0.65, 48000.0, 46.5, 2133.200000000001, 1094.8031250000047 - 0.65, 48000.0, 47.0, 2173.2250000000013, 1114.1875000000064 - 0.65, 48000.0, 47.5, 2213.2124999999996, 1133.353125000009 - 0.65, 48000.0, 48.0, 2253.1999999999985, 1152.6000000000113 - 0.65, 48000.0, 48.5, 2293.224999999998, 1172.2281250000142 - 0.65, 48000.0, 49.0, 2333.3249999999985, 1192.5375000000183 - 0.65, 48000.0, 49.5, 2373.537499999999, 1213.8281250000225 - 0.65, 48000.0, 50.0, 2413.9000000000015, 1236.4000000000274 - 0.7000000000000001, 0.0, 0.0, 683.5252059365248, 683.5252059365248 - 0.7000000000000001, 0.0, 22.0, 1626.1000000000042, 1791.09999999996 - 0.7000000000000001, 0.0, 22.5, 1935.2380859373957, 2174.376367187433 - 0.7000000000000001, 0.0, 23.0, 2236.7453124996987, 2338.6640624999436 - 0.7000000000000001, 0.0, 23.5, 2532.479882811908, 2327.2697265624893 - 0.7000000000000001, 0.0, 24.0, 2824.2999999990234, 2183.500000000066 - 0.7000000000000001, 0.0, 24.5, 3114.0638671860397, 1950.6615234376684 - 0.7000000000000001, 0.0, 25.0, 3403.6296874979544, 1672.0609375002969 - 0.7000000000000001, 0.0, 25.5, 3694.8556640597626, 1391.0048828129434 - 0.7000000000000001, 0.0, 26.0, 3989.599999996463, 1150.8000000006114 - 0.7000000000000001, 0.0, 26.5, 4308.362500000341, 1397.0998046876452 - 0.7000000000000001, 0.0, 27.0, 4635.425000000469, 1793.8553125002393 - 0.7000000000000001, 0.0, 27.5, 4969.450000000629, 2315.3994140628597 - 0.7000000000000001, 0.0, 28.0, 5309.100000000825, 2936.0650000005016 - 0.7000000000000001, 0.0, 28.5, 5653.037500001057, 3630.1849609381707 - 0.7000000000000001, 0.0, 29.0, 5999.925000001329, 4372.092187500871 - 0.7000000000000001, 0.0, 29.5, 6348.425000001643, 5136.119570313593 - 0.7000000000000001, 0.0, 30.0, 6697.200000002001, 5896.600000001357 - 0.7000000000000001, 0.0, 30.5, 7028.65390624981, 6323.738378905349 - 0.7000000000000001, 0.0, 31.0, 7359.256249999873, 6724.960156248944 - 0.7000000000000001, 0.0, 31.5, 7689.217968749948, 7103.562792967536 - 0.7000000000000001, 0.0, 32.0, 8018.750000000035, 7462.843749998622 - 0.7000000000000001, 0.0, 32.5, 8348.063281250132, 7806.100488279702 - 0.7000000000000001, 0.0, 33.0, 8677.368750000243, 8136.630468748278 - 0.7000000000000001, 0.0, 33.5, 9006.877343750366, 8457.731152341856 - 0.7000000000000001, 0.0, 34.0, 9336.800000000498, 8772.69999999793 - 0.7000000000000001, 0.0, 34.5, 9670.664999995053, 9475.435703123214 - 0.7000000000000001, 0.0, 35.0, 10005.049999993385, 10141.434374997996 - 0.7000000000000001, 0.0, 35.5, 10339.849999991484, 10736.793359372774 - 0.7000000000000001, 0.0, 36.0, 10674.95999998935, 11227.609999997549 - 0.7000000000000001, 0.0, 36.5, 11010.274999986981, 11579.981640622318 - 0.7000000000000001, 0.0, 37.0, 11345.68999998437, 11760.005624997077 - 0.7000000000000001, 0.0, 37.5, 11681.099999981505, 11733.779296871839 - 0.7000000000000001, 0.0, 38.0, 12016.399999978397, 11467.399999996589 - 0.7000000000000001, 0.0, 38.5, 12351.792968760092, 10618.397265627476 - 0.7000000000000001, 0.0, 39.0, 12686.70625001346, 9621.434375003088 - 0.7000000000000001, 0.0, 39.5, 13020.966406267416, 8511.179296878809 - 0.7000000000000001, 0.0, 40.0, 13354.400000021997, 7322.300000004652 - 0.7000000000000001, 0.0, 40.5, 13687.17734375265, 6032.774999999405 - 0.7000000000000001, 0.0, 41.0, 14018.643750003606, 4756.637499999151 - 0.7000000000000001, 0.0, 41.5, 14348.488281254538, 3551.23124999883 - 0.7000000000000001, 0.0, 42.0, 14676.400000005387, 2473.8999999984244 - 0.7000000000000001, 0.0, 42.5, 14997.114843747913, 1673.85468749841 - 0.7000000000000001, 0.0, 43.0, 15317.256249997432, 1079.8249999979162 - 0.7000000000000001, 0.0, 43.5, 15638.494531247125, 712.4078124973475 - 0.7000000000000001, 0.0, 44.0, 15962.499999997079, 592.1999999967011 - 0.7000000000000001, 0.0, 44.5, 16299.24374999768, 935.1617187506613 - 0.7000000000000001, 0.0, 45.0, 16638.774999995985, 1488.3812500010445 - 0.7000000000000001, 0.0, 45.5, 16979.443749993654, 2194.3101562516094 - 0.7000000000000001, 0.0, 46.0, 17319.599999990536, 2995.40000000239 - 0.7000000000000001, 0.0, 46.5, 17651.04296874389, 3739.7937499964596 - 0.7000000000000001, 0.0, 47.0, 17981.29374999239, 4501.974999995049 - 0.7000000000000001, 0.0, 47.5, 18311.322656240874, 5262.118749993433 - 0.7000000000000001, 0.0, 48.0, 18642.099999989394, 6000.399999991614 - 0.7000000000000001, 0.0, 48.5, 18974.596093738, 6696.993749989599 - 0.7000000000000001, 0.0, 49.0, 19309.781249986754, 7332.074999987399 - 0.7000000000000001, 0.0, 49.5, 19648.6257812357, 7885.818749985014 - 0.7000000000000001, 0.0, 50.0, 19992.099999984905, 8338.399999982452 - 0.7000000000000001, 2000.0, 0.0, 639.9639745203954, 639.9639745203954 - 0.7000000000000001, 2000.0, 22.0, -16564.599999999933, -4791.599999999998 - 0.7000000000000001, 2000.0, 22.5, -19697.840234375046, -5894.950781249993 - 0.7000000000000001, 2000.0, 23.0, -22799.69062500017, -6927.343749999996 - 0.7000000000000001, 2000.0, 23.5, -25880.845703125335, -7907.664843750012 - 0.7000000000000001, 2000.0, 24.0, -28952.000000000517, -8854.800000000032 - 0.7000000000000001, 2000.0, 24.5, -32023.848046875733, -9787.635156250051 - 0.7000000000000001, 2000.0, 25.0, -35107.08437500101, -10725.056250000083 - 0.7000000000000001, 2000.0, 25.5, -38212.40351562632, -11685.949218750118 - 0.7000000000000001, 2000.0, 26.0, -41350.500000001695, -12689.200000000152 - 0.7000000000000001, 2000.0, 26.5, -44644.709570312014, -13951.06445312476 - 0.7000000000000001, 2000.0, 27.0, -47999.52218749941, -15304.336874999695 - 0.7000000000000001, 2000.0, 27.5, -51406.32246093682, -16734.06835937461 - 0.7000000000000001, 2000.0, 28.0, -54856.49499999919, -18225.30999999952 - 0.7000000000000001, 2000.0, 28.5, -58341.42441406158, -19763.112890624412 - 0.7000000000000001, 2000.0, 29.0, -61852.49531249896, -21332.528124999295 - 0.7000000000000001, 2000.0, 29.5, -65381.09230468634, -22918.60679687416 - 0.7000000000000001, 2000.0, 30.0, -68918.59999999871, -24506.39999999901 - 0.7000000000000001, 2000.0, 30.5, -72366.05830077958, -25867.79775390624 - 0.7000000000000001, 2000.0, 31.0, -75813.80078124805, -27221.313281249953 - 0.7000000000000001, 2000.0, 31.5, -79261.81630859154, -28572.298730468665 - 0.7000000000000001, 2000.0, 32.0, -82710.0937499975, -29926.106249999873 - 0.7000000000000001, 2000.0, 32.5, -86158.62197265336, -31288.087988281066 - 0.7000000000000001, 2000.0, 33.0, -89607.38984374671, -32663.596093749766 - 0.7000000000000001, 2000.0, 33.5, -93056.38623046505, -34057.98271484344 - 0.7000000000000001, 2000.0, 34.0, -96505.59999999586, -35476.59999999963 - 0.7000000000000001, 2000.0, 34.5, -99958.31890624623, -37222.49355468686 - 0.7000000000000001, 2000.0, 35.0, -103410.91874999576, -38974.97031249934 - 0.7000000000000001, 2000.0, 35.5, -106863.07421874529, -40711.03066406181 - 0.7000000000000001, 2000.0, 36.0, -110314.45999999478, -42407.67499999929 - 0.7000000000000001, 2000.0, 36.5, -113764.75078124422, -44041.90371093675 - 0.7000000000000001, 2000.0, 37.0, -117213.6212499936, -45590.717187499235 - 0.7000000000000001, 2000.0, 37.5, -120660.74609374296, -47031.11582031167 - 0.7000000000000001, 2000.0, 38.0, -124105.7999999923, -48340.0999999991 - 0.7000000000000001, 2000.0, 38.5, -127542.50605467803, -49291.88007812436 - 0.7000000000000001, 2000.0, 39.0, -130979.57656248838, -50171.39687499938 - 0.7000000000000001, 2000.0, 39.5, -134418.00878904844, -51000.71523437445 - 0.7000000000000001, 2000.0, 40.0, -137858.7999999833, -51801.899999999536 - 0.7000000000000001, 2000.0, 40.5, -141308.05390624725, -52539.916406248856 - 0.7000000000000001, 2000.0, 41.0, -144759.61874999647, -53316.76874999833 - 0.7000000000000001, 2000.0, 41.5, -148212.4492187456, -54177.361718747605 - 0.7000000000000001, 2000.0, 42.0, -151665.49999999464, -55166.59999999669 - 0.7000000000000001, 2000.0, 42.5, -155112.43281249562, -56482.03281249864 - 0.7000000000000001, 2000.0, 43.0, -158559.61249999347, -57954.86249999826 - 0.7000000000000001, 2000.0, 43.5, -162008.1109374908, -59568.935937497794 - 0.7000000000000001, 2000.0, 44.0, -165458.99999998746, -61308.09999999728 - 0.7000000000000001, 2000.0, 44.5, -168923.88671874255, -63170.90468749914 - 0.7000000000000001, 2000.0, 45.0, -172389.09374999045, -65120.612499998846 - 0.7000000000000001, 2000.0, 45.5, -175851.47890623813, -67135.18906249854 - 0.7000000000000001, 2000.0, 46.0, -179307.89999998576, -69192.59999999829 - 0.7000000000000001, 2000.0, 46.5, -182738.4687500047, -71215.45156249989 - 0.7000000000000001, 2000.0, 47.0, -186163.48750000598, -73259.21249999966 - 0.7000000000000001, 2000.0, 47.5, -189586.5125000071, -75323.99218749935 - 0.7000000000000001, 2000.0, 48.0, -193011.10000000804, -77409.89999999896 - 0.7000000000000001, 2000.0, 48.5, -196440.80625000887, -79517.04531249854 - 0.7000000000000001, 2000.0, 49.0, -199879.1875000095, -81645.53749999804 - 0.7000000000000001, 2000.0, 49.5, -203329.80000000965, -83795.4859374975 - 0.7000000000000001, 2000.0, 50.0, -206796.2000000096, -85966.99999999689 - 0.7000000000000001, 5000.0, 0.0, 578.761476549852, 578.761476549852 - 0.7000000000000001, 5000.0, 22.0, 17794.199999999964, 7200.200000000027 - 0.7000000000000001, 5000.0, 22.5, 21177.12753906244, 8332.729101562496 - 0.7000000000000001, 5000.0, 23.0, 24523.16718749991, 9430.354687499977 - 0.7000000000000001, 5000.0, 23.5, 27844.248242187357, 10505.352929687473 - 0.7000000000000001, 5000.0, 24.0, 31152.299999999796, 11569.999999999976 - 0.7000000000000001, 5000.0, 24.5, 34459.25175781223, 12636.572070312497 - 0.7000000000000001, 5000.0, 25.0, 37777.032812499594, 13717.345312500023 - 0.7000000000000001, 5000.0, 25.5, 41117.572460936964, 14824.595898437554 - 0.7000000000000001, 5000.0, 26.0, 44492.79999999932, 15970.60000000009 - 0.7000000000000001, 5000.0, 26.5, 48039.07656249959, 17289.97519531232 - 0.7000000000000001, 5000.0, 27.0, 51651.00999999947, 18679.647187499806 - 0.7000000000000001, 5000.0, 27.5, 55319.19843749933, 20130.919335937302 - 0.7000000000000001, 5000.0, 28.0, 59034.2399999992, 21635.094999999797 - 0.7000000000000001, 5000.0, 28.5, 62786.732812499016, 23183.477539062296 - 0.7000000000000001, 5000.0, 29.0, 66567.27499999886, 24767.37031249981 - 0.7000000000000001, 5000.0, 29.5, 70366.46468749865, 26378.07667968733 - 0.7000000000000001, 5000.0, 30.0, 74174.89999999844, 28006.899999999856 - 0.7000000000000001, 5000.0, 30.5, 77884.58242187554, 29569.291796875048 - 0.7000000000000001, 5000.0, 31.0, 81594.09687500066, 31139.631250000046 - 0.7000000000000001, 5000.0, 31.5, 85303.4316406257, 32716.44570312505 - 0.7000000000000001, 5000.0, 32.0, 89012.57500000081, 34298.262500000055 - 0.7000000000000001, 5000.0, 32.5, 92721.51523437584, 35883.608984375074 - 0.7000000000000001, 5000.0, 33.0, 96430.24062500091, 37471.0125000001 - 0.7000000000000001, 5000.0, 33.5, 100138.73945312593, 39059.00039062514 - 0.7000000000000001, 5000.0, 34.0, 103847.00000000099, 40646.10000000018 - 0.7000000000000001, 5000.0, 34.5, 107554.05734374946, 42251.35058593693 - 0.7000000000000001, 5000.0, 35.0, 111260.94374999941, 43850.814062499405 - 0.7000000000000001, 5000.0, 35.5, 114967.73828124936, 45441.0642578119 - 0.7000000000000001, 5000.0, 36.0, 118674.51999999928, 47018.67499999939 - 0.7000000000000001, 5000.0, 36.5, 122381.36796874923, 48580.22011718693 - 0.7000000000000001, 5000.0, 37.0, 126088.36124999916, 50122.27343749945 - 0.7000000000000001, 5000.0, 37.5, 129795.5789062491, 51641.40878906202 - 0.7000000000000001, 5000.0, 38.0, 133503.09999999905, 53134.19999999959 - 0.7000000000000001, 5000.0, 38.5, 137211.9306640544, 54576.411914062286 - 0.7000000000000001, 5000.0, 39.0, 140920.7421874906, 55996.21718749954 - 0.7000000000000001, 5000.0, 39.5, 144629.40761717668, 57394.81386718669 - 0.7000000000000001, 5000.0, 40.0, 148337.79999998774, 58773.399999998765 - 0.7000000000000001, 5000.0, 40.5, 152044.2875000011, 60096.00078124857 - 0.7000000000000001, 5000.0, 41.0, 155750.8500000012, 61415.85624999818 - 0.7000000000000001, 5000.0, 41.5, 159457.96250000116, 62749.033593747794 - 0.7000000000000001, 5000.0, 42.0, 163166.1000000009, 64111.5999999974 - 0.7000000000000001, 5000.0, 42.5, 166875.88593749775, 65549.45078124938 - 0.7000000000000001, 5000.0, 43.0, 170587.58749999778, 67036.89374999913 - 0.7000000000000001, 5000.0, 43.5, 174301.6203124979, 68578.06484374883 - 0.7000000000000001, 5000.0, 44.0, 178018.39999999802, 70177.09999999846 - 0.7000000000000001, 5000.0, 44.5, 181747.34609375102, 71858.86953125057 - 0.7000000000000001, 5000.0, 45.0, 185476.26875000136, 73598.48125000064 - 0.7000000000000001, 5000.0, 45.5, 189201.98203125197, 75391.77734375064 - 0.7000000000000001, 5000.0, 46.0, 192921.3000000026, 77234.60000000056 - 0.7000000000000001, 5000.0, 46.5, 196614.08749999607, 79140.76796875011 - 0.7000000000000001, 5000.0, 47.0, 200300.8874999947, 81080.95625000032 - 0.7000000000000001, 5000.0, 47.5, 203985.29374999297, 83043.81640625063 - 0.7000000000000001, 5000.0, 48.0, 207670.89999999106, 85018.00000000099 - 0.7000000000000001, 5000.0, 48.5, 211361.2999999888, 86992.15859375142 - 0.7000000000000001, 5000.0, 49.0, 215060.08749998605, 88954.94375000194 - 0.7000000000000001, 5000.0, 49.5, 218770.85624998296, 90895.00703125249 - 0.7000000000000001, 5000.0, 50.0, 222497.1999999795, 92801.0000000031 - 0.7000000000000001, 10000.0, 0.0, 487.1105425959411, 487.1105425959411 - 0.7000000000000001, 10000.0, 22.0, 758.4000000000192, 1064.3999999999937 - 0.7000000000000001, 10000.0, 22.5, 900.3929687500407, 1145.9939453125023 - 0.7000000000000001, 10000.0, 23.0, 1041.8187500000645, 1221.073437500014 - 0.7000000000000001, 10000.0, 23.5, 1183.0351562500905, 1290.6662109375284 - 0.7000000000000001, 10000.0, 24.0, 1324.4000000001206, 1355.8000000000463 - 0.7000000000000001, 10000.0, 24.5, 1466.271093750155, 1417.502539062567 - 0.7000000000000001, 10000.0, 25.0, 1609.0062500001939, 1476.8015625000905 - 0.7000000000000001, 10000.0, 25.5, 1752.9632812502382, 1534.724804687618 - 0.7000000000000001, 10000.0, 26.0, 1898.5000000002885, 1592.3000000001477 - 0.7000000000000001, 10000.0, 26.5, 2050.0976562500373, 1660.5982421874787 - 0.7000000000000001, 10000.0, 27.0, 2204.2262500000556, 1731.17781249998 - 0.7000000000000001, 10000.0, 27.5, 2360.536718750078, 1803.344726562484 - 0.7000000000000001, 10000.0, 28.0, 2518.6800000001012, 1876.4049999999888 - 0.7000000000000001, 10000.0, 28.5, 2678.307031250128, 1949.6646484374965 - 0.7000000000000001, 10000.0, 29.0, 2839.068750000155, 2022.4296875000055 - 0.7000000000000001, 10000.0, 29.5, 3000.6160937501854, 2094.0061328125166 - 0.7000000000000001, 10000.0, 30.0, 3162.600000000216, 2163.70000000003 - 0.7000000000000001, 10000.0, 30.5, 3321.23388671889, 2217.376074218858 - 0.7000000000000001, 10000.0, 31.0, 3479.933593750179, 2269.061718750119 - 0.7000000000000001, 10000.0, 31.5, 3638.677441406471, 2319.3430664063803 - 0.7000000000000001, 10000.0, 32.0, 3797.443750000268, 2368.8062500001415 - 0.7000000000000001, 10000.0, 32.5, 3956.210839844069, 2418.037402343902 - 0.7000000000000001, 10000.0, 33.0, 4114.957031250376, 2467.6226562501643 - 0.7000000000000001, 10000.0, 33.5, 4273.660644531687, 2518.148144531427 - 0.7000000000000001, 10000.0, 34.0, 4432.3000000004995, 2570.2000000001904 - 0.7000000000000001, 10000.0, 34.5, 4590.706992187304, 2632.1823437503126 - 0.7000000000000001, 10000.0, 35.0, 4749.020312499696, 2696.118750000385 - 0.7000000000000001, 10000.0, 35.5, 4907.2322265620705, 2761.8507812504636 - 0.7000000000000001, 10000.0, 36.0, 5065.334999999423, 2829.2200000005505 - 0.7000000000000001, 10000.0, 36.5, 5223.320898436762, 2898.067968750646 - 0.7000000000000001, 10000.0, 37.0, 5381.18218749908, 2968.2362500007457 - 0.7000000000000001, 10000.0, 37.5, 5538.91113281138, 3039.566406250853 - 0.7000000000000001, 10000.0, 38.0, 5696.499999998661, 3111.9000000009673 - 0.7000000000000001, 10000.0, 38.5, 5853.494921877637, 3192.0279296880963 - 0.7000000000000001, 10000.0, 39.0, 6010.565625003129, 3269.2390625007047 - 0.7000000000000001, 10000.0, 39.5, 6167.80351562867, 3341.830664063329 - 0.7000000000000001, 10000.0, 40.0, 6325.300000004264, 3408.100000000972 - 0.7000000000000001, 10000.0, 40.5, 6483.55859375019, 3446.86093749993 - 0.7000000000000001, 10000.0, 41.0, 6642.09375000038, 3483.6874999999463 - 0.7000000000000001, 10000.0, 41.5, 6800.832031250624, 3524.6703124999776 - 0.7000000000000001, 10000.0, 42.0, 6959.70000000092, 3575.9000000000287 - 0.7000000000000001, 10000.0, 42.5, 7118.425000001069, 3668.178124999914 - 0.7000000000000001, 10000.0, 43.0, 7277.212500001464, 3772.9999999999136 - 0.7000000000000001, 10000.0, 43.5, 7436.06875000193, 3886.571874999911 - 0.7000000000000001, 10000.0, 44.0, 7595.00000000247, 4005.0999999999062 - 0.7000000000000001, 10000.0, 44.5, 7754.293749999754, 4115.364843749986 - 0.7000000000000001, 10000.0, 45.0, 7913.562499999796, 4226.76875000002 - 0.7000000000000001, 10000.0, 45.5, 8072.699999999868, 4339.288281250084 - 0.7000000000000001, 10000.0, 46.0, 8231.599999999973, 4452.90000000018 - 0.7000000000000001, 10000.0, 46.5, 8389.687500001108, 4575.803124999855 - 0.7000000000000001, 10000.0, 47.0, 8547.512500001578, 4696.462499999825 - 0.7000000000000001, 10000.0, 47.5, 8705.156250002121, 4811.5656249997965 - 0.7000000000000001, 10000.0, 48.0, 8862.700000002742, 4917.799999999768 - 0.7000000000000001, 10000.0, 48.5, 9020.22500000343, 5011.853124999741 - 0.7000000000000001, 10000.0, 49.0, 9177.81250000418, 5090.412499999711 - 0.7000000000000001, 10000.0, 49.5, 9335.543750004994, 5150.165624999679 - 0.7000000000000001, 10000.0, 50.0, 9493.50000000586, 5187.799999999641 - 0.7000000000000001, 15000.0, 0.0, 407.3186267168067, 407.3186267168067 - 0.7000000000000001, 15000.0, 22.0, 709.4999999999986, 971.5999999999999 - 0.7000000000000001, 15000.0, 22.5, 844.1011718750018, 1027.8458984375052 - 0.7000000000000001, 15000.0, 23.0, 977.3281250000049, 1084.2328125000106 - 0.7000000000000001, 15000.0, 23.5, 1109.6410156250092, 1140.8533203125164 - 0.7000000000000001, 15000.0, 24.0, 1241.5000000000136, 1197.800000000023 - 0.7000000000000001, 15000.0, 24.5, 1373.3652343750193, 1255.1654296875315 - 0.7000000000000001, 15000.0, 25.0, 1505.6968750000256, 1313.042187500041 - 0.7000000000000001, 15000.0, 25.5, 1638.9550781250339, 1371.522851562551 - 0.7000000000000001, 15000.0, 26.0, 1773.6000000000429, 1430.7000000000646 - 0.7000000000000001, 15000.0, 26.5, 1914.9261718749929, 1491.9582031250027 - 0.7000000000000001, 15000.0, 27.0, 2058.835624999993, 1554.1718750000039 - 0.7000000000000001, 15000.0, 27.5, 2204.9597656249916, 1617.212109375005 - 0.7000000000000001, 15000.0, 28.0, 2352.9299999999907, 1680.950000000006 - 0.7000000000000001, 15000.0, 28.5, 2502.3777343749894, 1745.2566406250069 - 0.7000000000000001, 15000.0, 29.0, 2652.93437499999, 1810.003125000008 - 0.7000000000000001, 15000.0, 29.5, 2804.2313281249876, 1875.0605468750082 - 0.7000000000000001, 15000.0, 30.0, 2955.8999999999864, 1940.3000000000081 - 0.7000000000000001, 15000.0, 30.5, 3103.709765624943, 2004.136523437498 - 0.7000000000000001, 15000.0, 31.0, 3251.521874999934, 2068.0359375000003 - 0.7000000000000001, 15000.0, 31.5, 3399.3355468749246, 2132.0080078125043 - 0.7000000000000001, 15000.0, 32.0, 3547.1499999999146, 2196.0625000000095 - 0.7000000000000001, 15000.0, 32.5, 3694.964453124904, 2260.209179687514 - 0.7000000000000001, 15000.0, 33.0, 3842.7781249998934, 2324.4578125000216 - 0.7000000000000001, 15000.0, 33.5, 3990.5902343748826, 2388.8181640625276 - 0.7000000000000001, 15000.0, 34.0, 4138.39999999987, 2453.3000000000375 - 0.7000000000000001, 15000.0, 34.5, 4286.190234374809, 2517.6907812499353 - 0.7000000000000001, 15000.0, 35.0, 4433.978124999778, 2582.2437499999255 - 0.7000000000000001, 15000.0, 35.5, 4581.764453124748, 2646.989843749914 - 0.7000000000000001, 15000.0, 36.0, 4729.549999999718, 2711.959999999901 - 0.7000000000000001, 15000.0, 36.5, 4877.335546874686, 2777.1851562498878 - 0.7000000000000001, 15000.0, 37.0, 5025.121874999652, 2842.6962499998735 - 0.7000000000000001, 15000.0, 37.5, 5172.9097656246195, 2908.524218749859 - 0.7000000000000001, 15000.0, 38.0, 5320.699999999587, 2974.699999999843 - 0.7000000000000001, 15000.0, 38.5, 5468.498632811862, 3041.261914062454 - 0.7000000000000001, 15000.0, 39.0, 5616.298437499237, 3108.2296874999515 - 0.7000000000000001, 15000.0, 39.5, 5764.099023436596, 3175.632617187449 - 0.7000000000000001, 15000.0, 40.0, 5911.899999998937, 3243.499999999944 - 0.7000000000000001, 15000.0, 40.5, 6059.69999999988, 3312.1062499999807 - 0.7000000000000001, 15000.0, 41.0, 6207.499999999851, 3381.137499999977 - 0.7000000000000001, 15000.0, 41.5, 6355.29999999982, 3450.5249999999724 - 0.7000000000000001, 15000.0, 42.0, 6503.0999999997875, 3520.199999999966 - 0.7000000000000001, 15000.0, 42.5, 6650.7828124999905, 3589.8906249999536 - 0.7000000000000001, 15000.0, 43.0, 6798.512499999982, 3659.812499999934 - 0.7000000000000001, 15000.0, 43.5, 6946.335937499968, 3729.9781249999123 - 0.7000000000000001, 15000.0, 44.0, 7094.299999999948, 3800.399999999886 - 0.7000000000000001, 15000.0, 44.5, 7242.924218749945, 3871.235156250003 - 0.7000000000000001, 15000.0, 45.0, 7391.593749999923, 3942.2937500000066 - 0.7000000000000001, 15000.0, 45.5, 7540.166406249891, 4013.5304687500125 - 0.7000000000000001, 15000.0, 46.0, 7688.499999999854, 4084.9000000000215 - 0.7000000000000001, 15000.0, 46.5, 7835.733593749832, 4156.032812500077 - 0.7000000000000001, 15000.0, 47.0, 7982.731249999786, 4227.337500000101 - 0.7000000000000001, 15000.0, 47.5, 8129.638281249734, 4298.898437500131 - 0.7000000000000001, 15000.0, 48.0, 8276.599999999682, 4370.8000000001675 - 0.7000000000000001, 15000.0, 48.5, 8423.761718749627, 4443.126562500206 - 0.7000000000000001, 15000.0, 49.0, 8571.268749999568, 4515.9625000002525 - 0.7000000000000001, 15000.0, 49.5, 8719.266406249515, 4589.392187500303 - 0.7000000000000001, 15000.0, 50.0, 8867.899999999461, 4663.500000000362 - 0.7000000000000001, 20000.0, 0.0, 338.22526749364647, 338.22526749364647 - 0.7000000000000001, 20000.0, 22.0, 765.6999999999998, 882.1 - 0.7000000000000001, 20000.0, 22.5, 911.0357421875002, 942.8396484374998 - 0.7000000000000001, 20000.0, 23.0, 1054.8640625000005, 1002.9328124999998 - 0.7000000000000001, 20000.0, 23.5, 1197.685351562501, 1062.6095703125002 - 0.7000000000000001, 20000.0, 24.0, 1340.0000000000016, 1122.1 - 0.7000000000000001, 20000.0, 24.5, 1482.3083984375028, 1181.6341796875004 - 0.7000000000000001, 20000.0, 25.0, 1625.1109375000033, 1241.4421875000005 - 0.7000000000000001, 20000.0, 25.5, 1768.9080078125053, 1301.7541015625013 - 0.7000000000000001, 20000.0, 26.0, 1914.2000000000064, 1362.8000000000015 - 0.7000000000000001, 20000.0, 26.5, 2066.7359375000015, 1427.1369140625022 - 0.7000000000000001, 20000.0, 27.0, 2222.0675000000015, 1492.8009375000026 - 0.7000000000000001, 20000.0, 27.5, 2379.7953125000017, 1559.6232421875027 - 0.7000000000000001, 20000.0, 28.0, 2539.520000000001, 1627.435000000003 - 0.7000000000000001, 20000.0, 28.5, 2700.842187500001, 1696.0673828125025 - 0.7000000000000001, 20000.0, 29.0, 2863.362500000001, 1765.3515625000034 - 0.7000000000000001, 20000.0, 29.5, 3026.6815625000004, 1835.1187109375032 - 0.7000000000000001, 20000.0, 30.0, 3190.4000000000005, 1905.2000000000035 - 0.7000000000000001, 20000.0, 30.5, 3349.927050781246, 1973.2437500000003 - 0.7000000000000001, 20000.0, 31.0, 3509.453906249996, 2041.4718749999995 - 0.7000000000000001, 20000.0, 31.5, 3668.980371093745, 2109.923437499999 - 0.7000000000000001, 20000.0, 32.0, 3828.5062499999945, 2178.6374999999985 - 0.7000000000000001, 20000.0, 32.5, 3988.031347656243, 2247.6531249999975 - 0.7000000000000001, 20000.0, 33.0, 4147.5554687499925, 2317.009374999997 - 0.7000000000000001, 20000.0, 33.5, 4307.078417968742, 2386.7453124999965 - 0.7000000000000001, 20000.0, 34.0, 4466.5999999999885, 2456.8999999999955 - 0.7000000000000001, 20000.0, 34.5, 4626.112226562481, 2528.0333984375006 - 0.7000000000000001, 20000.0, 35.0, 4785.623437499979, 2599.6140625000007 - 0.7000000000000001, 20000.0, 35.5, 4945.134179687478, 2671.6314453125005 - 0.7000000000000001, 20000.0, 36.0, 5104.644999999975, 2744.0750000000016 - 0.7000000000000001, 20000.0, 36.5, 5264.156445312473, 2816.934179687502 - 0.7000000000000001, 20000.0, 37.0, 5423.669062499969, 2890.1984375000034 - 0.7000000000000001, 20000.0, 37.5, 5583.183398437467, 2963.8572265625035 - 0.7000000000000001, 20000.0, 38.0, 5742.699999999963, 3037.9000000000046 - 0.7000000000000001, 20000.0, 38.5, 5902.2236328125055, 3112.4111328124854 - 0.7000000000000001, 20000.0, 39.0, 6061.748437500005, 3187.2359374999805 - 0.7000000000000001, 20000.0, 39.5, 6221.274023437509, 3262.3427734374754 - 0.7000000000000001, 20000.0, 40.0, 6380.80000000001, 3337.6999999999703 - 0.7000000000000001, 20000.0, 40.5, 6540.324999999996, 3413.0054687499883 - 0.7000000000000001, 20000.0, 41.0, 6699.849999999993, 3488.606249999984 - 0.7000000000000001, 20000.0, 41.5, 6859.374999999991, 3564.578906249978 - 0.7000000000000001, 20000.0, 42.0, 7018.899999999989, 3640.9999999999714 - 0.7000000000000001, 20000.0, 42.5, 7178.299999999997, 3717.957812500005 - 0.7000000000000001, 20000.0, 43.0, 7337.749999999998, 3795.5125000000057 - 0.7000000000000001, 20000.0, 43.5, 7497.299999999996, 3873.735937500006 - 0.7000000000000001, 20000.0, 44.0, 7656.999999999995, 3952.7000000000075 - 0.7000000000000001, 20000.0, 44.5, 7817.403906250007, 4032.351562499998 - 0.7000000000000001, 20000.0, 45.0, 7977.85625000001, 4112.937499999997 - 0.7000000000000001, 20000.0, 45.5, 8138.205468750013, 4194.579687499996 - 0.7000000000000001, 20000.0, 46.0, 8298.300000000014, 4277.399999999995 - 0.7000000000000001, 20000.0, 46.5, 8457.222656249978, 4361.723437499985 - 0.7000000000000001, 20000.0, 47.0, 8615.893749999961, 4447.387499999982 - 0.7000000000000001, 20000.0, 47.5, 8774.46796874995, 4534.432812499974 - 0.7000000000000001, 20000.0, 48.0, 8933.09999999993, 4622.899999999965 - 0.7000000000000001, 20000.0, 48.5, 9091.944531249914, 4712.829687499955 - 0.7000000000000001, 20000.0, 49.0, 9251.156249999889, 4804.262499999947 - 0.7000000000000001, 20000.0, 49.5, 9410.889843749863, 4897.239062499933 - 0.7000000000000001, 20000.0, 50.0, 9571.299999999834, 4991.799999999919 - 0.7000000000000001, 25000.0, 0.0, 278.7363038494789, 278.7363038494789 - 0.7000000000000001, 25000.0, 22.0, 623.2000000000002, 716.6000000000001 - 0.7000000000000001, 25000.0, 22.5, 741.4320312500008, 765.6296875000002 - 0.7000000000000001, 25000.0, 23.0, 858.4562500000017, 814.1374999999998 - 0.7000000000000001, 25000.0, 23.5, 974.6773437500024, 862.3015624999997 - 0.7000000000000001, 25000.0, 24.0, 1090.5000000000032, 910.2999999999996 - 0.7000000000000001, 25000.0, 24.5, 1206.3289062500041, 958.3109374999995 - 0.7000000000000001, 25000.0, 25.0, 1322.568750000005, 1006.5124999999994 - 0.7000000000000001, 25000.0, 25.5, 1439.624218750006, 1055.0828124999998 - 0.7000000000000001, 25000.0, 26.0, 1557.900000000007, 1104.199999999999 - 0.7000000000000001, 25000.0, 26.5, 1682.0568359375, 1155.8113281250019 - 0.7000000000000001, 25000.0, 27.0, 1808.4865625000004, 1208.4268750000024 - 0.7000000000000001, 25000.0, 27.5, 1936.8642578124998, 1261.9214843750033 - 0.7000000000000001, 25000.0, 28.0, 2066.865000000001, 1316.1700000000035 - 0.7000000000000001, 25000.0, 28.5, 2198.163867187501, 1371.0472656250035 - 0.7000000000000001, 25000.0, 29.0, 2330.435937500001, 1426.428125000004 - 0.7000000000000001, 25000.0, 29.5, 2463.3562890625, 1482.1874218750045 - 0.7000000000000001, 25000.0, 30.0, 2596.6000000000004, 1538.200000000005 - 0.7000000000000001, 25000.0, 30.5, 2726.428417968753, 1592.7845703124985 - 0.7000000000000001, 25000.0, 31.0, 2856.2554687500046, 1647.520312499998 - 0.7000000000000001, 25000.0, 31.5, 2986.0813476562544, 1702.4302734374976 - 0.7000000000000001, 25000.0, 32.0, 3115.9062500000045, 1757.537499999997 - 0.7000000000000001, 25000.0, 32.5, 3245.730371093756, 1812.8650390624969 - 0.7000000000000001, 25000.0, 33.0, 3375.5539062500065, 1868.435937499996 - 0.7000000000000001, 25000.0, 33.5, 3505.3770507812574, 1924.2732421874957 - 0.7000000000000001, 25000.0, 34.0, 3635.2000000000085, 1980.3999999999949 - 0.7000000000000001, 25000.0, 34.5, 3765.024999999996, 2037.1140624999973 - 0.7000000000000001, 25000.0, 35.0, 3894.8499999999967, 2094.1374999999975 - 0.7000000000000001, 25000.0, 35.5, 4024.674999999995, 2151.4671874999976 - 0.7000000000000001, 25000.0, 36.0, 4154.499999999996, 2209.0999999999985 - 0.7000000000000001, 25000.0, 36.5, 4284.324999999996, 2267.0328124999983 - 0.7000000000000001, 25000.0, 37.0, 4414.149999999995, 2325.2625 - 0.7000000000000001, 25000.0, 37.5, 4543.974999999997, 2383.7859375000007 - 0.7000000000000001, 25000.0, 38.0, 4673.799999999995, 2442.6000000000017 - 0.7000000000000001, 25000.0, 38.5, 4803.62499999999, 2501.8070312499835 - 0.7000000000000001, 25000.0, 39.0, 4933.449999999992, 2561.24374999998 - 0.7000000000000001, 25000.0, 39.5, 5063.274999999991, 2620.8835937499757 - 0.7000000000000001, 25000.0, 40.0, 5193.099999999992, 2680.6999999999703 - 0.7000000000000001, 25000.0, 40.5, 5322.925000000009, 2740.2562499999945 - 0.7000000000000001, 25000.0, 41.0, 5452.750000000012, 2800.0999999999913 - 0.7000000000000001, 25000.0, 41.5, 5582.575000000012, 2860.368749999987 - 0.7000000000000001, 25000.0, 42.0, 5712.400000000012, 2921.1999999999844 - 0.7000000000000001, 25000.0, 42.5, 5842.119531249983, 2983.235156249999 - 0.7000000000000001, 25000.0, 43.0, 5971.881249999979, 3045.906249999996 - 0.7000000000000001, 25000.0, 43.5, 6101.727343749975, 3109.149218749995 - 0.7000000000000001, 25000.0, 44.0, 6231.699999999968, 3172.899999999993 - 0.7000000000000001, 25000.0, 44.5, 6362.259374999995, 3236.7078125000075 - 0.7000000000000001, 25000.0, 45.0, 6492.862499999993, 3301.050000000009 - 0.7000000000000001, 25000.0, 45.5, 6623.384374999985, 3366.0171875000106 - 0.7000000000000001, 25000.0, 46.0, 6753.699999999978, 3431.700000000013 - 0.7000000000000001, 25000.0, 46.5, 6883.063281249994, 3498.067968750007 - 0.7000000000000001, 25000.0, 47.0, 7012.218749999988, 3565.3812500000085 - 0.7000000000000001, 25000.0, 47.5, 7141.289843749983, 3633.77890625001 - 0.7000000000000001, 25000.0, 48.0, 7270.399999999979, 3703.4000000000106 - 0.7000000000000001, 25000.0, 48.5, 7399.672656249973, 3774.3835937500107 - 0.7000000000000001, 25000.0, 49.0, 7529.231249999965, 3846.868750000011 - 0.7000000000000001, 25000.0, 49.5, 7659.199218749956, 3920.994531250011 - 0.7000000000000001, 25000.0, 50.0, 7789.699999999951, 3996.900000000009 - 0.7000000000000001, 30000.0, 0.0, 227.834279665898, 227.834279665898 - 0.7000000000000001, 30000.0, 22.0, 498.9, 581.1000000000005 - 0.7000000000000001, 30000.0, 22.5, 593.6009765625001, 620.1503906250003 - 0.7000000000000001, 30000.0, 23.0, 687.3171875000004, 658.6093750000006 - 0.7000000000000001, 30000.0, 23.5, 780.3748046875004, 696.6386718749999 - 0.7000000000000001, 30000.0, 24.0, 873.1000000000007, 734.3999999999996 - 0.7000000000000001, 30000.0, 24.5, 965.8189453125011, 772.0550781249991 - 0.7000000000000001, 30000.0, 25.0, 1058.8578125000015, 809.7656249999985 - 0.7000000000000001, 30000.0, 25.5, 1152.542773437502, 847.6933593749977 - 0.7000000000000001, 30000.0, 26.0, 1247.2000000000028, 885.9999999999967 - 0.7000000000000001, 30000.0, 26.5, 1346.5736328125015, 926.3498046875013 - 0.7000000000000001, 30000.0, 27.0, 1447.7671875000021, 967.4878125000016 - 0.7000000000000001, 30000.0, 27.5, 1550.5208984375017, 1009.3181640625018 - 0.7000000000000001, 30000.0, 28.0, 1654.5750000000023, 1051.7450000000024 - 0.7000000000000001, 30000.0, 28.5, 1759.6697265625023, 1094.672460937502 - 0.7000000000000001, 30000.0, 29.0, 1865.5453125000024, 1138.0046875000019 - 0.7000000000000001, 30000.0, 29.5, 1971.9419921875026, 1181.645820312502 - 0.7000000000000001, 30000.0, 30.0, 2078.600000000002, 1225.5000000000023 - 0.7000000000000001, 30000.0, 30.5, 2182.536132812501, 1268.2925781249971 - 0.7000000000000001, 30000.0, 31.0, 2286.4734374999994, 1311.218749999996 - 0.7000000000000001, 30000.0, 31.5, 2390.411523437499, 1354.2949218749957 - 0.7000000000000001, 30000.0, 32.0, 2494.349999999998, 1397.537499999995 - 0.7000000000000001, 30000.0, 32.5, 2598.2884765624963, 1440.962890624994 - 0.7000000000000001, 30000.0, 33.0, 2702.2265624999964, 1484.5874999999928 - 0.7000000000000001, 30000.0, 33.5, 2806.163867187493, 1528.4277343749918 - 0.7000000000000001, 30000.0, 34.0, 2910.099999999992, 1572.4999999999905 - 0.7000000000000001, 30000.0, 34.5, 3014.0214453124995, 1617.0134765624953 - 0.7000000000000001, 30000.0, 35.0, 3117.9421875000016, 1661.773437499994 - 0.7000000000000001, 30000.0, 35.5, 3221.863085937504, 1706.7779296874935 - 0.7000000000000001, 30000.0, 36.0, 3325.785000000005, 1752.0249999999917 - 0.7000000000000001, 30000.0, 36.5, 3429.7087890625066, 1797.5126953124902 - 0.7000000000000001, 30000.0, 37.0, 3533.635312500009, 1843.239062499989 - 0.7000000000000001, 30000.0, 37.5, 3637.5654296875123, 1889.202148437488 - 0.7000000000000001, 30000.0, 38.0, 3741.500000000015, 1935.3999999999864 - 0.7000000000000001, 30000.0, 38.5, 3845.4525390624763, 1981.809570312496 - 0.7000000000000001, 30000.0, 39.0, 3949.40468749997, 2028.4609374999955 - 0.7000000000000001, 30000.0, 39.5, 4053.354492187463, 2075.356835937495 - 0.7000000000000001, 30000.0, 40.0, 4157.299999999957, 2122.499999999994 - 0.7000000000000001, 30000.0, 40.5, 4261.230468749995, 2169.767187500001 - 0.7000000000000001, 30000.0, 41.0, 4365.156249999994, 2217.3375000000015 - 0.7000000000000001, 30000.0, 41.5, 4469.078906249991, 2265.2640625000004 - 0.7000000000000001, 30000.0, 42.0, 4572.999999999987, 2313.600000000001 - 0.7000000000000001, 30000.0, 42.5, 4676.846874999993, 2362.6796874999955 - 0.7000000000000001, 30000.0, 43.0, 4780.724999999988, 2412.162499999993 - 0.7000000000000001, 30000.0, 43.5, 4884.665624999982, 2461.989062499989 - 0.7000000000000001, 30000.0, 44.0, 4988.699999999974, 2512.0999999999854 - 0.7000000000000001, 30000.0, 44.5, 5093.167968749987, 2562.0335937499985 - 0.7000000000000001, 30000.0, 45.0, 5197.6687499999825, 2612.293749999997 - 0.7000000000000001, 30000.0, 45.5, 5302.110156249976, 2662.9820312499965 - 0.7000000000000001, 30000.0, 46.0, 5406.399999999971, 2714.1999999999957 - 0.7000000000000001, 30000.0, 46.5, 5509.992968749999, 2766.0531250000004 - 0.7000000000000001, 30000.0, 47.0, 5613.431249999998, 2818.6374999999994 - 0.7000000000000001, 30000.0, 47.5, 5716.803906249994, 2872.0531249999976 - 0.7000000000000001, 30000.0, 48.0, 5820.199999999993, 2926.3999999999955 - 0.7000000000000001, 30000.0, 48.5, 5923.708593749991, 2981.778124999992 - 0.7000000000000001, 30000.0, 49.0, 6027.418749999988, 3038.2874999999876 - 0.7000000000000001, 30000.0, 49.5, 6131.419531249984, 3096.028124999982 - 0.7000000000000001, 30000.0, 50.0, 6235.799999999977, 3155.0999999999754 - 0.7000000000000001, 35000.0, 0.0, 184.57166808036143, 184.57166808036143 - 0.7000000000000001, 35000.0, 22.0, 382.9, 478.40000000000015 - 0.7000000000000001, 35000.0, 22.5, 455.5708984375, 508.22578125 - 0.7000000000000001, 35000.0, 23.0, 527.4953125000001, 537.5312499999998 - 0.7000000000000001, 35000.0, 23.5, 598.9220703125003, 566.44609375 - 0.7000000000000001, 35000.0, 24.0, 670.1000000000003, 595.0999999999999 - 0.7000000000000001, 35000.0, 24.5, 741.2779296875004, 623.6226562499999 - 0.7000000000000001, 35000.0, 25.0, 812.7046875000004, 652.1437500000003 - 0.7000000000000001, 35000.0, 25.5, 884.6291015625006, 680.79296875 - 0.7000000000000001, 35000.0, 26.0, 957.3000000000005, 709.7000000000003 - 0.7000000000000001, 35000.0, 26.5, 1033.5775390625015, 740.1498046875008 - 0.7000000000000001, 35000.0, 27.0, 1111.2484375000013, 771.1828125000005 - 0.7000000000000001, 35000.0, 27.5, 1190.1138671875017, 802.7306640625004 - 0.7000000000000001, 35000.0, 28.0, 1269.9750000000017, 834.7250000000006 - 0.7000000000000001, 35000.0, 28.5, 1350.6330078125018, 867.0974609375002 - 0.7000000000000001, 35000.0, 29.0, 1431.889062500002, 899.7796874999999 - 0.7000000000000001, 35000.0, 29.5, 1513.544335937502, 932.7033203124994 - 0.7000000000000001, 35000.0, 30.0, 1595.400000000002, 965.7999999999992 - 0.7000000000000001, 35000.0, 30.5, 1675.1736328124987, 998.2056640624992 - 0.7000000000000001, 35000.0, 31.0, 1754.9484374999981, 1030.723437499999 - 0.7000000000000001, 35000.0, 31.5, 1834.7240234374972, 1063.3607421874988 - 0.7000000000000001, 35000.0, 32.0, 1914.4999999999961, 1096.1249999999989 - 0.7000000000000001, 35000.0, 32.5, 1994.2759765624946, 1129.0236328124981 - 0.7000000000000001, 35000.0, 33.0, 2074.051562499994, 1162.0640624999978 - 0.7000000000000001, 35000.0, 33.5, 2153.8263671874925, 1195.2537109374975 - 0.7000000000000001, 35000.0, 34.0, 2233.5999999999904, 1228.5999999999972 - 0.7000000000000001, 35000.0, 34.5, 2313.3556640624993, 1262.141523437502 - 0.7000000000000001, 35000.0, 35.0, 2393.1109375, 1295.8515625000027 - 0.7000000000000001, 35000.0, 35.5, 2472.8669921875007, 1329.734570312503 - 0.7000000000000001, 35000.0, 36.0, 2552.625, 1363.7950000000044 - 0.7000000000000001, 35000.0, 36.5, 2632.3861328125017, 1398.0373046875052 - 0.7000000000000001, 35000.0, 37.0, 2712.151562500003, 1432.4659375000065 - 0.7000000000000001, 35000.0, 37.5, 2791.9224609375046, 1467.085351562508 - 0.7000000000000001, 35000.0, 38.0, 2871.700000000007, 1501.9000000000096 - 0.7000000000000001, 35000.0, 38.5, 2951.5064453125024, 1536.5810546874948 - 0.7000000000000001, 35000.0, 39.0, 3031.3109375000045, 1571.6390624999929 - 0.7000000000000001, 35000.0, 39.5, 3111.109960937506, 1607.1525390624909 - 0.7000000000000001, 35000.0, 40.0, 3190.9000000000087, 1643.1999999999884 - 0.7000000000000001, 35000.0, 40.5, 3270.6570312499957, 1680.5289062500012 - 0.7000000000000001, 35000.0, 41.0, 3350.4062499999945, 1718.2812500000016 - 0.7000000000000001, 35000.0, 41.5, 3430.1523437499905, 1756.267968750001 - 0.7000000000000001, 35000.0, 42.0, 3509.899999999988, 1794.3000000000006 - 0.7000000000000001, 35000.0, 42.5, 3589.6109375000015, 1831.5046874999994 - 0.7000000000000001, 35000.0, 43.0, 3669.3500000000026, 1868.6499999999987 - 0.7000000000000001, 35000.0, 43.5, 3749.139062500003, 1905.8203124999975 - 0.7000000000000001, 35000.0, 44.0, 3829.0000000000036, 1943.0999999999965 - 0.7000000000000001, 35000.0, 44.5, 3909.1851562499864, 1980.6515624999975 - 0.7000000000000001, 35000.0, 45.0, 3989.3937499999806, 2018.4499999999955 - 0.7000000000000001, 35000.0, 45.5, 4069.5554687499734, 2056.5484374999937 - 0.7000000000000001, 35000.0, 46.0, 4149.599999999966, 2094.99999999999 - 0.7000000000000001, 35000.0, 46.5, 4229.1093750000055, 2133.838281250001 - 0.7000000000000001, 35000.0, 47.0, 4308.500000000006, 2173.14375 - 0.7000000000000001, 35000.0, 47.5, 4387.840625000008, 2212.9773437499994 - 0.7000000000000001, 35000.0, 48.0, 4467.200000000006, 2253.3999999999983 - 0.7000000000000001, 35000.0, 48.5, 4546.646875000004, 2294.472656249996 - 0.7000000000000001, 35000.0, 49.0, 4626.250000000005, 2336.256249999995 - 0.7000000000000001, 35000.0, 49.5, 4706.078125000001, 2378.8117187499925 - 0.7000000000000001, 35000.0, 50.0, 4786.199999999997, 2422.19999999999 - 0.7000000000000001, 39000.0, 0.0, 153.08571670019185, 153.08571670019185 - 0.7000000000000001, 39000.0, 22.0, 307.40000000000003, 413.8000000000001 - 0.7000000000000001, 39000.0, 22.5, 365.72773437500024, 437.1078125000001 - 0.7000000000000001, 39000.0, 23.0, 423.45312500000045, 460.3249999999999 - 0.7000000000000001, 39000.0, 23.5, 480.7769531250006, 483.5046874999999 - 0.7000000000000001, 39000.0, 24.0, 537.9000000000009, 506.69999999999976 - 0.7000000000000001, 39000.0, 24.5, 595.0230468750011, 529.9640624999998 - 0.7000000000000001, 39000.0, 25.0, 652.3468750000011, 553.3499999999995 - 0.7000000000000001, 39000.0, 25.5, 710.0722656250013, 576.9109374999996 - 0.7000000000000001, 39000.0, 26.0, 768.4000000000016, 600.6999999999995 - 0.7000000000000001, 39000.0, 26.5, 829.6417968750001, 625.2789062500003 - 0.7000000000000001, 39000.0, 27.0, 892.0081250000001, 650.2212500000002 - 0.7000000000000001, 39000.0, 27.5, 955.337890625, 675.4929687500003 - 0.7000000000000001, 39000.0, 28.0, 1019.4699999999998, 701.0600000000001 - 0.7000000000000001, 39000.0, 28.5, 1084.2433593749995, 726.88828125 - 0.7000000000000001, 39000.0, 29.0, 1149.4968749999996, 752.9437499999999 - 0.7000000000000001, 39000.0, 29.5, 1215.0694531249994, 779.1923437499998 - 0.7000000000000001, 39000.0, 30.0, 1280.7999999999986, 805.5999999999996 - 0.7000000000000001, 39000.0, 30.5, 1344.827734375003, 831.7975585937518 - 0.7000000000000001, 39000.0, 31.0, 1408.8531250000035, 858.1179687500019 - 0.7000000000000001, 39000.0, 31.5, 1472.8769531250034, 884.5590820312519 - 0.7000000000000001, 39000.0, 32.0, 1536.900000000004, 911.118750000002 - 0.7000000000000001, 39000.0, 32.5, 1600.9230468750038, 937.7948242187523 - 0.7000000000000001, 39000.0, 33.0, 1664.9468750000044, 964.5851562500027 - 0.7000000000000001, 39000.0, 33.5, 1728.9722656250044, 991.4875976562529 - 0.7000000000000001, 39000.0, 34.0, 1793.000000000005, 1018.500000000003 - 0.7000000000000001, 39000.0, 34.5, 1857.0505468749964, 1045.5115234375025 - 0.7000000000000001, 39000.0, 35.0, 1921.1031249999971, 1072.6390625000035 - 0.7000000000000001, 39000.0, 35.5, 1985.1566406249976, 1099.8908203125036 - 0.7000000000000001, 39000.0, 36.0, 2049.2099999999978, 1127.275000000005 - 0.7000000000000001, 39000.0, 36.5, 2113.2621093749995, 1154.799804687506 - 0.7000000000000001, 39000.0, 37.0, 2177.311875000001, 1182.4734375000073 - 0.7000000000000001, 39000.0, 37.5, 2241.3582031250007, 1210.3041015625079 - 0.7000000000000001, 39000.0, 38.0, 2305.4000000000037, 1238.3000000000093 - 0.7000000000000001, 39000.0, 38.5, 2369.4224609374783, 1266.3533203124985 - 0.7000000000000001, 39000.0, 39.0, 2433.4453124999736, 1294.6484374999982 - 0.7000000000000001, 39000.0, 39.5, 2497.470507812469, 1323.2193359374978 - 0.7000000000000001, 39000.0, 40.0, 2561.499999999963, 1352.099999999997 - 0.7000000000000001, 39000.0, 40.5, 2625.548437499999, 1381.3 - 0.7000000000000001, 39000.0, 41.0, 2689.5999999999985, 1410.8874999999994 - 0.7000000000000001, 39000.0, 41.5, 2753.651562499997, 1440.9062499999995 - 0.7000000000000001, 39000.0, 42.0, 2817.6999999999957, 1471.399999999999 - 0.7000000000000001, 39000.0, 42.5, 2881.679687499996, 1502.8343750000042 - 0.7000000000000001, 39000.0, 43.0, 2945.6749999999956, 1534.6625000000045 - 0.7000000000000001, 39000.0, 43.5, 3009.7078124999925, 1566.759375000004 - 0.7000000000000001, 39000.0, 44.0, 3073.799999999991, 1599.0000000000036 - 0.7000000000000001, 39000.0, 44.5, 3138.176562499998, 1630.9781249999978 - 0.7000000000000001, 39000.0, 45.0, 3202.574999999996, 1662.962499999997 - 0.7000000000000001, 39000.0, 45.5, 3266.935937499993, 1694.9406249999952 - 0.7000000000000001, 39000.0, 46.0, 3331.19999999999, 1726.8999999999937 - 0.7000000000000001, 39000.0, 46.5, 3395.010937499989, 1758.4960937500023 - 0.7000000000000001, 39000.0, 47.0, 3458.7249999999826, 1790.1812500000028 - 0.7000000000000001, 39000.0, 47.5, 3522.4015624999765, 1822.0757812500033 - 0.7000000000000001, 39000.0, 48.0, 3586.099999999968, 1854.3000000000038 - 0.7000000000000001, 39000.0, 48.5, 3649.8796874999593, 1886.974218750004 - 0.7000000000000001, 39000.0, 49.0, 3713.7999999999483, 1920.2187500000045 - 0.7000000000000001, 39000.0, 49.5, 3777.9203124999362, 1954.153906250005 - 0.7000000000000001, 39000.0, 50.0, 3842.299999999923, 1988.900000000006 - 0.7000000000000001, 43000.0, 0.0, 126.31080251176257, 126.31080251176257 - 0.7000000000000001, 43000.0, 22.0, 248.4, 365.40000000000003 - 0.7000000000000001, 43000.0, 22.5, 295.54101562499994, 384.17265625000005 - 0.7000000000000001, 43000.0, 23.0, 342.19687499999986, 403.01875 - 0.7000000000000001, 43000.0, 23.5, 388.5292968749999, 421.95546875 - 0.7000000000000001, 43000.0, 24.0, 434.69999999999976, 440.99999999999994 - 0.7000000000000001, 43000.0, 24.5, 480.87070312499975, 460.16953125 - 0.7000000000000001, 43000.0, 25.0, 527.2031249999997, 479.48124999999993 - 0.7000000000000001, 43000.0, 25.5, 573.8589843749997, 498.9523437499999 - 0.7000000000000001, 43000.0, 26.0, 620.9999999999995, 518.5999999999997 - 0.7000000000000001, 43000.0, 26.5, 670.4859375000001, 538.5986328125 - 0.7000000000000001, 43000.0, 27.0, 720.8775, 558.8171875 - 0.7000000000000001, 43000.0, 27.5, 772.0453125000001, 579.2458984375002 - 0.7000000000000001, 43000.0, 28.0, 823.8600000000001, 599.8750000000002 - 0.7000000000000001, 43000.0, 28.5, 876.1921875000002, 620.6947265625003 - 0.7000000000000001, 43000.0, 29.0, 928.9125000000001, 641.6953125000001 - 0.7000000000000001, 43000.0, 29.5, 981.8915625, 662.8669921875002 - 0.7000000000000001, 43000.0, 30.0, 1035.0000000000002, 684.2000000000002 - 0.7000000000000001, 43000.0, 30.5, 1086.75, 705.7009765625006 - 0.7000000000000001, 43000.0, 31.0, 1138.5, 727.3421875000005 - 0.7000000000000001, 43000.0, 31.5, 1190.25, 749.1123046875005 - 0.7000000000000001, 43000.0, 32.0, 1242.0, 771.0000000000006 - 0.7000000000000001, 43000.0, 32.5, 1293.75, 792.9939453125006 - 0.7000000000000001, 43000.0, 33.0, 1345.5, 815.0828125000006 - 0.7000000000000001, 43000.0, 33.5, 1397.25, 837.2552734375006 - 0.7000000000000001, 43000.0, 34.0, 1449.0, 859.5000000000007 - 0.7000000000000001, 43000.0, 34.5, 1500.75, 881.5398828124997 - 0.7000000000000001, 43000.0, 35.0, 1552.5, 903.6546874999998 - 0.7000000000000001, 43000.0, 35.5, 1604.25, 925.8583984374999 - 0.7000000000000001, 43000.0, 36.0, 1656.0, 948.1649999999998 - 0.7000000000000001, 43000.0, 36.5, 1707.75, 970.5884765624996 - 0.7000000000000001, 43000.0, 37.0, 1759.5, 993.1428124999996 - 0.7000000000000001, 43000.0, 37.5, 1811.25, 1015.8419921874997 - 0.7000000000000001, 43000.0, 38.0, 1863.0, 1038.6999999999998 - 0.7000000000000001, 43000.0, 38.5, 1914.75, 1061.7603515625012 - 0.7000000000000001, 43000.0, 39.0, 1966.5, 1084.9921875000014 - 0.7000000000000001, 43000.0, 39.5, 2018.25, 1108.4029296875017 - 0.7000000000000001, 43000.0, 40.0, 2070.0, 1132.0000000000018 - 0.7000000000000001, 43000.0, 40.5, 2121.75, 1155.62578125 - 0.7000000000000001, 43000.0, 41.0, 2173.5, 1179.5187500000002 - 0.7000000000000001, 43000.0, 41.5, 2225.25, 1203.7523437500001 - 0.7000000000000001, 43000.0, 42.0, 2277.0, 1228.4 - 0.7000000000000001, 43000.0, 42.5, 2328.7070312499995, 1254.000000000001 - 0.7000000000000001, 43000.0, 43.0, 2380.4312499999996, 1279.9750000000013 - 0.7000000000000001, 43000.0, 43.5, 2432.1898437499995, 1306.2125000000012 - 0.7000000000000001, 43000.0, 44.0, 2483.9999999999995, 1332.6000000000017 - 0.7000000000000001, 43000.0, 44.5, 2536.05078125, 1358.7789062499999 - 0.7000000000000001, 43000.0, 45.0, 2588.1187500000005, 1384.9812499999996 - 0.7000000000000001, 43000.0, 45.5, 2640.15234375, 1411.1929687499996 - 0.7000000000000001, 43000.0, 46.0, 2692.1000000000004, 1437.3999999999994 - 0.7000000000000001, 43000.0, 46.5, 2743.652343749999, 1463.2718750000008 - 0.7000000000000001, 43000.0, 47.0, 2795.1187499999987, 1489.2375000000009 - 0.7000000000000001, 43000.0, 47.5, 2846.5507812499986, 1515.409375000001 - 0.7000000000000001, 43000.0, 48.0, 2897.999999999998, 1541.9000000000012 - 0.7000000000000001, 43000.0, 48.5, 2949.5179687499976, 1568.8218750000015 - 0.7000000000000001, 43000.0, 49.0, 3001.1562499999973, 1596.2875000000015 - 0.7000000000000001, 43000.0, 49.5, 3052.966406249997, 1624.409375000002 - 0.7000000000000001, 43000.0, 50.0, 3104.9999999999964, 1653.3000000000022 - 0.7000000000000001, 48000.0, 0.0, 99.32830174205827, 99.32830174205827 - 0.7000000000000001, 48000.0, 22.0, 195.6, 287.80000000000007 - 0.7000000000000001, 48000.0, 22.5, 232.7220703125, 302.57148437500007 - 0.7000000000000001, 48000.0, 23.0, 269.4609375, 317.4031250000001 - 0.7000000000000001, 48000.0, 23.5, 305.94433593749994, 332.30820312500003 - 0.7000000000000001, 48000.0, 24.0, 342.29999999999995, 347.30000000000007 - 0.7000000000000001, 48000.0, 24.5, 378.65566406249997, 362.39179687500007 - 0.7000000000000001, 48000.0, 25.0, 415.1390624999999, 377.5968750000001 - 0.7000000000000001, 48000.0, 25.5, 451.87792968749983, 392.92851562500016 - 0.7000000000000001, 48000.0, 26.0, 488.9999999999998, 408.40000000000003 - 0.7000000000000001, 48000.0, 26.5, 527.9755859375, 424.14628906250016 - 0.7000000000000001, 48000.0, 27.0, 567.6665625, 440.0659375000002 - 0.7000000000000001, 48000.0, 27.5, 607.9705078125, 456.15136718750017 - 0.7000000000000001, 48000.0, 28.0, 648.7850000000001, 472.3950000000002 - 0.7000000000000001, 48000.0, 28.5, 690.0076171875002, 488.78925781250024 - 0.7000000000000001, 48000.0, 29.0, 731.5359375, 505.32656250000025 - 0.7000000000000001, 48000.0, 29.5, 773.2675390625001, 521.9993359375003 - 0.7000000000000001, 48000.0, 30.0, 815.1000000000001, 538.8000000000004 - 0.7000000000000001, 48000.0, 30.5, 855.8534179687501, 555.7377929687499 - 0.7000000000000001, 48000.0, 31.0, 896.6054687500001, 572.7867187499999 - 0.7000000000000001, 48000.0, 31.5, 937.3563476562504, 589.9375976562499 - 0.7000000000000001, 48000.0, 32.0, 978.1062500000003, 607.1812499999997 - 0.7000000000000001, 48000.0, 32.5, 1018.8553710937503, 624.5084960937497 - 0.7000000000000001, 48000.0, 33.0, 1059.6039062500004, 641.9101562499998 - 0.7000000000000001, 48000.0, 33.5, 1100.3520507812502, 659.3770507812496 - 0.7000000000000001, 48000.0, 34.0, 1141.1000000000004, 676.8999999999996 - 0.7000000000000001, 48000.0, 34.5, 1181.8499999999992, 694.2536718749994 - 0.7000000000000001, 48000.0, 35.0, 1222.5999999999992, 711.6656249999993 - 0.7000000000000001, 48000.0, 35.5, 1263.349999999999, 729.1472656249992 - 0.7000000000000001, 48000.0, 36.0, 1304.099999999999, 746.7099999999992 - 0.7000000000000001, 48000.0, 36.5, 1344.849999999999, 764.3652343749993 - 0.7000000000000001, 48000.0, 37.0, 1385.599999999999, 782.1243749999992 - 0.7000000000000001, 48000.0, 37.5, 1426.3499999999988, 799.9988281249989 - 0.7000000000000001, 48000.0, 38.0, 1467.0999999999985, 817.9999999999987 - 0.7000000000000001, 48000.0, 38.5, 1507.8500000000006, 836.1677734375016 - 0.7000000000000001, 48000.0, 39.0, 1548.6000000000008, 854.4703125000019 - 0.7000000000000001, 48000.0, 39.5, 1589.350000000001, 872.9126953125023 - 0.7000000000000001, 48000.0, 40.0, 1630.1000000000015, 891.500000000003 - 0.7000000000000001, 48000.0, 40.5, 1670.8460937499992, 910.1054687500003 - 0.7000000000000001, 48000.0, 41.0, 1711.593749999999, 928.9187500000005 - 0.7000000000000001, 48000.0, 41.5, 1752.344531249999, 947.9976562500005 - 0.7000000000000001, 48000.0, 42.0, 1793.0999999999985, 967.4000000000007 - 0.7000000000000001, 48000.0, 42.5, 1833.842187499999, 987.5429687500002 - 0.7000000000000001, 48000.0, 43.0, 1874.5999999999988, 1007.9812500000002 - 0.7000000000000001, 48000.0, 43.5, 1915.3828124999986, 1028.6289062500002 - 0.7000000000000001, 48000.0, 44.0, 1956.1999999999982, 1049.3999999999999 - 0.7000000000000001, 48000.0, 44.5, 1997.1742187500004, 1070.0328125000005 - 0.7000000000000001, 48000.0, 45.0, 2038.1562500000002, 1090.6875000000011 - 0.7000000000000001, 48000.0, 45.5, 2079.1101562500007, 1111.3484375000012 - 0.7000000000000001, 48000.0, 46.0, 2120.0000000000005, 1132.0000000000014 - 0.7000000000000001, 48000.0, 46.5, 2160.6062499999994, 1152.3531250000003 - 0.7000000000000001, 48000.0, 47.0, 2201.1499999999996, 1172.7750000000003 - 0.7000000000000001, 48000.0, 47.5, 2241.6687499999994, 1193.3593750000002 - 0.7000000000000001, 48000.0, 48.0, 2282.199999999999, 1214.2000000000005 - 0.7000000000000001, 48000.0, 48.5, 2322.781249999999, 1235.3906250000007 - 0.7000000000000001, 48000.0, 49.0, 2363.449999999999, 1257.0250000000008 - 0.7000000000000001, 48000.0, 49.5, 2404.2437499999983, 1279.1968750000008 - 0.7000000000000001, 48000.0, 50.0, 2445.199999999999, 1302.0000000000014 - 0.75, 0.0, 0.0, 710.9639385219803, 710.9639385219803 - 0.75, 0.0, 22.0, 1790.7000000000085, 1981.0999999999456 - 0.75, 0.0, 22.5, 2131.5927734373804, 2483.7666015624113 - 0.75, 0.0, 23.0, 2462.62031249963, 2677.329687499928 - 0.75, 0.0, 23.5, 2786.0876953117527, 2622.7779296874933 - 0.75, 0.0, 24.0, 3104.299999998748, 2381.1000000000977 - 0.75, 0.0, 24.5, 3419.56230468561, 2013.2845703127416 - 0.75, 0.0, 25.0, 3734.179687497338, 1580.3203125004225 - 0.75, 0.0, 25.5, 4050.4572265589277, 1143.195898438129 - 0.75, 0.0, 26.0, 4370.699999995373, 762.9000000008609 - 0.75, 0.0, 26.5, 4720.143554687953, 1064.8345703127027 - 0.75, 0.0, 27.0, 5079.47281250062, 1577.8271875003306 - 0.75, 0.0, 27.5, 5447.061914063334, 2266.109960937988 - 0.75, 0.0, 28.0, 5821.285000001095, 3093.9150000006775 - 0.75, 0.0, 28.5, 6200.516210938901, 4025.4744140634075 - 0.75, 0.0, 29.0, 6583.12968750176, 5025.020312501165 - 0.75, 0.0, 29.5, 6967.4995703146715, 6056.784804688954 - 0.75, 0.0, 30.0, 7352.000000002639, 7085.000000001801 - 0.75, 0.0, 30.5, 7714.8205078122555, 7654.54687499884 - 0.75, 0.0, 31.0, 8076.442187499849, 8188.946874998651 - 0.75, 0.0, 31.5, 8437.161523437464, 8692.37031249845 - 0.75, 0.0, 32.0, 8797.275000000096, 9168.987499998244 - 0.75, 0.0, 32.5, 9157.079101562746, 9622.96874999803 - 0.75, 0.0, 33.0, 9516.870312500416, 10058.484374997812 - 0.75, 0.0, 33.5, 9876.945117188105, 10479.704687497597 - 0.75, 0.0, 34.0, 10237.600000000813, 10890.799999997369 - 0.75, 0.0, 34.5, 10603.772773431054, 11836.236992185195 - 0.75, 0.0, 35.0, 10970.676562491346, 12728.432812497414 - 0.75, 0.0, 35.5, 11338.165820301336, 13520.100976559623 - 0.75, 0.0, 36.0, 11706.094999986013, 14163.954999996826 - 0.75, 0.0, 36.5, 12074.318554670375, 14612.708398434028 - 0.75, 0.0, 37.0, 12442.69093747942, 14819.074687496239 - 0.75, 0.0, 37.5, 12811.066601538143, 14735.767382808415 - 0.75, 0.0, 38.0, 13179.299999971538, 14315.499999995583 - 0.75, 0.0, 38.5, 13547.729687513292, 13079.509179690838 - 0.75, 0.0, 39.0, 13915.475000017746, 11635.714062504154 - 0.75, 0.0, 39.5, 14282.282812522975, 10032.711914067622 - 0.75, 0.0, 40.0, 14647.900000029014, 8319.100000006241 - 0.75, 0.0, 40.5, 15012.467968753792, 6463.554687499246 - 0.75, 0.0, 41.0, 15375.18125000519, 4626.562499998923 - 0.75, 0.0, 41.5, 15735.628906256588, 2888.689062498499 - 0.75, 0.0, 42.0, 16093.400000007905, 1330.4999999979736 - 0.75, 0.0, 42.5, 16441.34921874708, 162.599999998062 - 0.75, 0.0, 43.0, 16788.493749996436, -716.500000002548 - 0.75, 0.0, 43.5, 17137.116406246038, -1278.2500000032496 - 0.75, 0.0, 44.0, 17489.499999995995, -1494.1000000040517 - 0.75, 0.0, 44.5, 17859.12656249735, -1062.34374999915 - 0.75, 0.0, 45.0, 18232.599999995236, -336.8499999986334 - 0.75, 0.0, 45.5, 18607.72343749229, 601.6687500021362 - 0.75, 0.0, 46.0, 18982.29999998832, 1672.500000003185 - 0.75, 0.0, 46.5, 19345.511718742127, 2662.692968745388 - 0.75, 0.0, 47.0, 19707.231249990244, 3676.668749993545 - 0.75, 0.0, 47.5, 20068.710156238354, 4686.6101562414315 - 0.75, 0.0, 48.0, 20431.19999998653, 5664.699999989052 - 0.75, 0.0, 48.5, 20795.95234373483, 6583.121093736418 - 0.75, 0.0, 49.0, 21164.218749983345, 7414.056249983535 - 0.75, 0.0, 49.5, 21537.250781232142, 8129.688281230403 - 0.75, 0.0, 50.0, 21916.299999981304, 8702.199999977032 - 0.75, 2000.0, 0.0, 665.6540298521967, 665.6540298521967 - 0.75, 2000.0, 22.0, -24169.499999999894, -7390.699999999991 - 0.75, 2000.0, 22.5, -28741.416992187547, -9005.265429687483 - 0.75, 2000.0, 23.0, -33267.464062500214, -10516.71406249999 - 0.75, 2000.0, 23.5, -37763.254101562925, -11952.555664062507 - 0.75, 2000.0, 24.0, -42244.40000000067, -13340.300000000034 - 0.75, 2000.0, 24.5, -46726.51464843846, -14707.45683593757 - 0.75, 2000.0, 25.0, -51225.21093750131, -16081.535937500117 - 0.75, 2000.0, 25.5, -55756.10175781422, -17490.04707031267 - 0.75, 2000.0, 26.0, -60334.800000002215, -18960.500000000222 - 0.75, 2000.0, 26.5, -65141.31874999927, -20809.01230468715 - 0.75, 2000.0, 27.0, -70036.26499999913, -22790.977812499554 - 0.75, 2000.0, 27.5, -75007.06874999899, -24884.430664061943 - 0.75, 2000.0, 28.0, -80041.15999999884, -27067.404999999322 - 0.75, 2000.0, 28.5, -85125.96874999866, -29317.934960936676 - 0.75, 2000.0, 29.0, -90248.9249999985, -31614.054687499018 - 0.75, 2000.0, 29.5, -95397.45874999835, -33933.798320311325 - 0.75, 2000.0, 30.0, -100558.99999999817, -36255.19999999863 - 0.75, 2000.0, 30.5, -105589.16806640374, -38242.8971679687 - 0.75, 2000.0, 31.0, -110619.7570312471, -40218.167968749905 - 0.75, 2000.0, 31.5, -115650.75029296543, -42188.89384765609 - 0.75, 2000.0, 32.0, -120682.13124999621, -44162.95624999976 - 0.75, 2000.0, 32.5, -125713.88330077693, -46148.23662109344 - 0.75, 2000.0, 33.0, -130745.9898437451, -48152.61640624962 - 0.75, 2000.0, 33.5, -135778.43427733827, -50183.97705078077 - 0.75, 2000.0, 34.0, -140811.19999999384, -52250.19999999943 - 0.75, 2000.0, 34.5, -145849.12050780718, -54795.67015624897 - 0.75, 2000.0, 35.0, -150886.86718749403, -57350.193749998914 - 0.75, 2000.0, 35.5, -155923.96152343083, -59880.08046874884 - 0.75, 2000.0, 36.0, -160959.92499999248, -62351.63999999878 - 0.75, 2000.0, 36.5, -165994.27910155425, -64731.18203124867 - 0.75, 2000.0, 37.0, -171026.5453124908, -66985.01624999859 - 0.75, 2000.0, 37.5, -176056.2451171774, -69079.45234374847 - 0.75, 2000.0, 38.0, -181082.89999998885, -70980.79999999833 - 0.75, 2000.0, 38.5, -186097.27753904945, -72357.48613281162 - 0.75, 2000.0, 39.0, -191112.19218748412, -73628.16093749915 - 0.75, 2000.0, 39.5, -196129.11074216833, -74825.3302734367 - 0.75, 2000.0, 40.0, -201149.49999997727, -75981.49999999933 - 0.75, 2000.0, 40.5, -206182.34140624612, -77044.51093749836 - 0.75, 2000.0, 41.0, -211218.58124999507, -78165.3999999976 - 0.75, 2000.0, 41.5, -216256.68046874387, -79410.53906249664 - 0.75, 2000.0, 42.0, -221295.09999999258, -80846.29999999539 - 0.75, 2000.0, 42.5, -226324.5312499934, -82765.285156248 - 0.75, 2000.0, 43.0, -231354.31249999034, -84917.14374999743 - 0.75, 2000.0, 43.5, -236386.01249998648, -87277.75546874681 - 0.75, 2000.0, 44.0, -241421.19999998182, -89822.99999999604 - 0.75, 2000.0, 44.5, -246476.8421874896, -92550.15937499874 - 0.75, 2000.0, 45.0, -251532.9499999868, -95405.14999999832 - 0.75, 2000.0, 45.5, -256584.9328124836, -98355.2906249979 - 0.75, 2000.0, 46.0, -261628.19999998034, -101367.89999999752 - 0.75, 2000.0, 46.5, -266633.68046875595, -104327.9999999997 - 0.75, 2000.0, 47.0, -271631.0562500075, -107318.1249999994 - 0.75, 2000.0, 47.5, -276625.5289062591, -110338.51249999893 - 0.75, 2000.0, 48.0, -281622.30000001023, -113389.39999999844 - 0.75, 2000.0, 48.5, -286626.57109376125, -116471.02499999783 - 0.75, 2000.0, 49.0, -291643.54375001194, -119583.62499999716 - 0.75, 2000.0, 49.5, -296678.4195312622, -122727.43749999635 - 0.75, 2000.0, 50.0, -301736.400000012, -125902.69999999547 - 0.75, 5000.0, 0.0, 601.9946817746047, 601.9946817746047 - 0.75, 5000.0, 22.0, 27298.499999999938, 10613.600000000035 - 0.75, 5000.0, 22.5, 32488.41445312491, 12343.027929687496 - 0.75, 5000.0, 23.0, 37621.69687499987, 14019.364062499964 - 0.75, 5000.0, 23.5, 42716.65585937479, 15661.41816406246 - 0.75, 5000.0, 24.0, 47791.59999999971, 17287.99999999997 - 0.75, 5000.0, 24.5, 52864.83789062459, 18917.91933593749 - 0.75, 5000.0, 25.0, 57954.67812499943, 20569.985937500027 - 0.75, 5000.0, 25.5, 63079.42929687425, 22263.009570312566 - 0.75, 5000.0, 26.0, 68257.39999999906, 24015.800000000123 - 0.75, 5000.0, 26.5, 73697.86757812441, 26034.20781249975 - 0.75, 5000.0, 27.0, 79239.08437499928, 28160.68999999973 - 0.75, 5000.0, 27.5, 84866.62148437409, 30381.99218749972 - 0.75, 5000.0, 28.0, 90566.0499999989, 32684.85999999972 - 0.75, 5000.0, 28.5, 96322.94101562366, 35056.03906249974 - 0.75, 5000.0, 29.0, 102122.86562499845, 37482.27499999974 - 0.75, 5000.0, 29.5, 107951.39492187316, 39950.313437499775 - 0.75, 5000.0, 30.0, 113794.09999999785, 42446.89999999982 - 0.75, 5000.0, 30.5, 119485.21455078186, 44844.261816406324 - 0.75, 5000.0, 31.0, 125176.06015625069, 47254.56953125007 - 0.75, 5000.0, 31.5, 130866.62099609456, 49675.47529296882 - 0.75, 5000.0, 32.0, 136556.88125000085, 52104.63125000008 - 0.75, 5000.0, 32.5, 142246.82509765725, 54539.68955078136 - 0.75, 5000.0, 33.0, 147936.436718751, 56978.30234375014 - 0.75, 5000.0, 33.5, 153625.70029296985, 59418.12177734395 - 0.75, 5000.0, 34.0, 159314.6000000011, 61856.80000000024 - 0.75, 5000.0, 34.5, 165001.67339843648, 64325.20238281177 - 0.75, 5000.0, 35.0, 170688.4890624989, 66784.60468749923 - 0.75, 5000.0, 35.5, 176375.16894531128, 69229.49589843674 - 0.75, 5000.0, 36.0, 182061.83499999862, 71654.36499999928 - 0.75, 5000.0, 36.5, 187748.609179686, 74053.7009765618 - 0.75, 5000.0, 37.0, 193435.61343749834, 76421.99281249939 - 0.75, 5000.0, 37.5, 199122.96972656067, 78753.72949218698 - 0.75, 5000.0, 38.0, 204810.799999998, 81043.39999999957 - 0.75, 5000.0, 38.5, 210500.69433592618, 83250.21191406228 - 0.75, 5000.0, 39.0, 216190.54531248688, 85422.22968749945 - 0.75, 5000.0, 39.5, 221880.14863279753, 87561.78261718649 - 0.75, 5000.0, 40.0, 227569.299999983, 89671.19999999845 - 0.75, 5000.0, 40.5, 233255.39765625144, 91696.642187498 - 0.75, 5000.0, 41.0, 238941.59375000154, 93719.07499999745 - 0.75, 5000.0, 41.5, 244628.64296875155, 95763.29531249692 - 0.75, 5000.0, 42.0, 250317.30000000127, 97854.09999999634 - 0.75, 5000.0, 42.5, 256008.67109374667, 100063.07109374901 - 0.75, 5000.0, 43.0, 261703.01874999664, 102349.50624999864 - 0.75, 5000.0, 43.5, 267400.95703124674, 104719.4882812482 - 0.75, 5000.0, 44.0, 273103.09999999695, 107179.0999999977 - 0.75, 5000.0, 44.5, 278823.80000000144, 109765.5492187507 - 0.75, 5000.0, 45.0, 284544.437500002, 112441.34375000079 - 0.75, 5000.0, 45.5, 290260.1312500027, 115200.11640625077 - 0.75, 5000.0, 46.0, 295966.0000000036, 118035.50000000065 - 0.75, 5000.0, 46.5, 301631.17031249433, 120969.68203125006 - 0.75, 5000.0, 47.0, 307287.1499999924, 123956.31875000038 - 0.75, 5000.0, 47.5, 312939.45468749024, 126977.62109375074 - 0.75, 5000.0, 48.0, 318593.59999998746, 130015.80000000124 - 0.75, 5000.0, 48.5, 324255.1015624843, 133053.06640625178 - 0.75, 5000.0, 49.0, 329929.4749999805, 136071.63125000245 - 0.75, 5000.0, 49.5, 335622.2359374762, 139053.70546875315 - 0.75, 5000.0, 50.0, 341338.8999999714, 141981.500000004 - 0.75, 10000.0, 0.0, 506.6646070280395, 506.6646070280395 - 0.75, 10000.0, 22.0, 715.7000000000291, 1086.999999999992 - 0.75, 10000.0, 22.5, 847.832226562563, 1187.6787109375052 - 0.75, 10000.0, 23.0, 980.3046875000987, 1274.3578125000226 - 0.75, 10000.0, 23.5, 1113.3248046876379, 1349.1830078125447 - 0.75, 10000.0, 24.0, 1247.1000000001814, 1414.3000000000718 - 0.75, 10000.0, 24.5, 1381.8376953127308, 1471.8544921876037 - 0.75, 10000.0, 25.0, 1517.7453125002862, 1523.9921875001405 - 0.75, 10000.0, 25.5, 1655.0302734378502, 1572.8587890626823 - 0.75, 10000.0, 26.0, 1793.9000000004237, 1620.6000000002286 - 0.75, 10000.0, 26.5, 1937.4384765625668, 1690.3615234374772 - 0.75, 10000.0, 27.0, 2083.1409375000953, 1764.4890624999812 - 0.75, 10000.0, 27.5, 2230.7216796876264, 1841.5283203124875 - 0.75, 10000.0, 28.0, 2379.895000000161, 1920.0249999999958 - 0.75, 10000.0, 28.5, 2530.375195312699, 1998.5248046875067 - 0.75, 10000.0, 29.0, 2681.876562500237, 2075.5734375000197 - 0.75, 10000.0, 29.5, 2834.1133984377784, 2149.716601562537 - 0.75, 10000.0, 30.0, 2986.800000000318, 2219.500000000057 - 0.75, 10000.0, 30.5, 3137.0793945314767, 2255.150097656408 - 0.75, 10000.0, 31.0, 3287.4820312502884, 2286.2289062501704 - 0.75, 10000.0, 31.5, 3437.9670898441095, 2313.979199218932 - 0.75, 10000.0, 32.0, 3588.4937500004376, 2339.643750000195 - 0.75, 10000.0, 32.5, 3739.0211914067736, 2364.4653320314583 - 0.75, 10000.0, 33.0, 3889.5085937506183, 2389.686718750221 - 0.75, 10000.0, 33.5, 4039.9151367194704, 2416.5506835939836 - 0.75, 10000.0, 34.0, 4190.20000000083, 2446.300000000248 - 0.75, 10000.0, 34.5, 4340.031562499922, 2497.451171875562 - 0.75, 10000.0, 35.0, 4489.687499999785, 2552.3281250006903 - 0.75, 10000.0, 35.5, 4639.154687499626, 2610.5285156258324 - 0.75, 10000.0, 36.0, 4788.419999999439, 2671.6500000009855 - 0.75, 10000.0, 36.5, 4937.470312499225, 2735.2902343761534 - 0.75, 10000.0, 37.0, 5086.292499998986, 2801.046875001333 - 0.75, 10000.0, 37.5, 5234.87343749872, 2868.517578126525 - 0.75, 10000.0, 38.0, 5383.199999998424, 2937.300000001729 - 0.75, 10000.0, 38.5, 5530.435351566445, 3019.289453125739 - 0.75, 10000.0, 39.0, 5677.817187504675, 3095.4093750008565 - 0.75, 10000.0, 39.5, 5825.515429692975, 3162.5246093759934 - 0.75, 10000.0, 40.0, 5973.700000006348, 3217.5000000011514 - 0.75, 10000.0, 40.5, 6123.321093750369, 3220.1437499999006 - 0.75, 10000.0, 41.0, 6273.456250000669, 3219.1999999999225 - 0.75, 10000.0, 41.5, 6423.9632812510445, 3226.356249999974 - 0.75, 10000.0, 42.0, 6574.700000001502, 3253.3000000000516 - 0.75, 10000.0, 42.5, 6725.235156251599, 3359.3554687498427 - 0.75, 10000.0, 43.0, 6875.831250002163, 3489.518749999832 - 0.75, 10000.0, 43.5, 7026.461718752826, 3636.4226562498184 - 0.75, 10000.0, 44.0, 7177.100000003594, 3792.6999999997947 - 0.75, 10000.0, 44.5, 7327.809374999648, 3932.43281249999 - 0.75, 10000.0, 45.0, 7478.437499999709, 4074.2250000000417 - 0.75, 10000.0, 45.5, 7628.92187499982, 4218.129687500134 - 0.75, 10000.0, 46.0, 7779.1999999999825, 4364.200000000278 - 0.75, 10000.0, 46.5, 7929.03359375172, 4528.391406249742 - 0.75, 10000.0, 47.0, 8078.6062500024545, 4688.493749999691 - 0.75, 10000.0, 47.5, 8227.925781253305, 4838.199218749647 - 0.75, 10000.0, 48.0, 8377.000000004256, 4971.199999999606 - 0.75, 10000.0, 48.5, 8525.83671875531, 5081.188281249563 - 0.75, 10000.0, 49.0, 8674.443750006454, 5161.8562499995205 - 0.75, 10000.0, 49.5, 8822.828906257684, 5206.896093749474 - 0.75, 10000.0, 50.0, 8971.000000008993, 5209.999999999421 - 0.75, 15000.0, 0.0, 423.669606576056, 423.669606576056 - 0.75, 15000.0, 22.0, 683.5999999999981, 1034.5000000000007 - 0.75, 15000.0, 22.5, 812.8505859375025, 1089.776562500011 - 0.75, 15000.0, 23.0, 940.9578125000075, 1145.9500000000214 - 0.75, 15000.0, 23.5, 1068.336132812514, 1202.9734375000335 - 0.75, 15000.0, 24.0, 1195.4000000000215, 1260.800000000047 - 0.75, 15000.0, 24.5, 1322.5638671875306, 1319.382812500062 - 0.75, 15000.0, 25.0, 1450.242187500041, 1378.6750000000804 - 0.75, 15000.0, 25.5, 1578.8494140625533, 1438.629687500102 - 0.75, 15000.0, 26.0, 1708.8000000000673, 1499.200000000127 - 0.75, 15000.0, 26.5, 1844.9298828124834, 1560.322656250009 - 0.75, 15000.0, 27.0, 1983.4846874999819, 1621.9662500000113 - 0.75, 15000.0, 27.5, 2124.12089843748, 1684.0867187500148 - 0.75, 15000.0, 28.0, 2266.4949999999767, 1746.6400000000178 - 0.75, 15000.0, 28.5, 2410.2634765624744, 1809.5820312500216 - 0.75, 15000.0, 29.0, 2555.082812499972, 1872.868750000024 - 0.75, 15000.0, 29.5, 2700.6094921874683, 1936.4560937500264 - 0.75, 15000.0, 30.0, 2846.499999999965, 2000.3000000000272 - 0.75, 15000.0, 30.5, 2988.838769531136, 2063.951171874984 - 0.75, 15000.0, 31.0, 3131.194531249869, 2127.8093749999884 - 0.75, 15000.0, 31.5, 3273.563964843601, 2191.8691406249936 - 0.75, 15000.0, 32.0, 3415.943749999832, 2256.125 - 0.75, 15000.0, 32.5, 3558.33056640606, 2320.5714843750084 - 0.75, 15000.0, 33.0, 3700.72109374979, 2385.2031250000196 - 0.75, 15000.0, 33.5, 3843.1120117185174, 2450.014453125032 - 0.75, 15000.0, 34.0, 3985.4999999997435, 2515.0000000000473 - 0.75, 15000.0, 34.5, 4127.80421874965, 2581.48812499987 - 0.75, 15000.0, 35.0, 4270.106249999595, 2648.012499999846 - 0.75, 15000.0, 35.5, 4412.410156249538, 2714.4406249998206 - 0.75, 15000.0, 36.0, 4554.71999999948, 2780.6399999997925 - 0.75, 15000.0, 36.5, 4697.039843749419, 2846.478124999762 - 0.75, 15000.0, 37.0, 4839.373749999355, 2911.8224999997287 - 0.75, 15000.0, 37.5, 4981.72578124929, 2976.540624999693 - 0.75, 15000.0, 38.0, 5124.099999999226, 3040.4999999996535 - 0.75, 15000.0, 38.5, 5266.567968748965, 3101.003124999973 - 0.75, 15000.0, 39.0, 5409.031249998771, 3161.812499999983 - 0.75, 15000.0, 39.5, 5551.478906248548, 3223.365624999995 - 0.75, 15000.0, 40.0, 5693.899999998296, 3286.1000000000067 - 0.75, 15000.0, 40.5, 5836.224999999762, 3352.2421874999595 - 0.75, 15000.0, 41.0, 5978.524999999713, 3419.724999999953 - 0.75, 15000.0, 41.5, 6120.812499999667, 3488.270312499945 - 0.75, 15000.0, 42.0, 6263.099999999625, 3557.5999999999385 - 0.75, 15000.0, 42.5, 6405.306250000076, 3627.0531249999312 - 0.75, 15000.0, 43.0, 6547.575000000095, 3696.887499999897 - 0.75, 15000.0, 43.5, 6689.956250000112, 3766.978124999857 - 0.75, 15000.0, 44.0, 6832.50000000012, 3837.199999999809 - 0.75, 15000.0, 44.5, 6975.795312499879, 3906.650781250007 - 0.75, 15000.0, 45.0, 7119.137499999829, 3976.293750000015 - 0.75, 15000.0, 45.5, 7262.36093749976, 4046.3148437500286 - 0.75, 15000.0, 46.0, 7405.299999999678, 4116.90000000005 - 0.75, 15000.0, 46.5, 7546.937499999668, 4189.289843750158 - 0.75, 15000.0, 47.0, 7688.299999999577, 4262.193750000211 - 0.75, 15000.0, 47.5, 7829.562499999482, 4335.375781250273 - 0.75, 15000.0, 48.0, 7970.8999999993775, 4408.600000000346 - 0.75, 15000.0, 48.5, 8112.487499999272, 4481.63046875043 - 0.75, 15000.0, 49.0, 8254.499999999163, 4554.2312500005255 - 0.75, 15000.0, 49.5, 8397.112499999055, 4626.166406250635 - 0.75, 15000.0, 50.0, 8540.499999998949, 4697.200000000759 - 0.75, 20000.0, 0.0, 351.802634630659, 351.802634630659 - 0.75, 20000.0, 22.0, 763.4999999999994, 950.3999999999994 - 0.75, 20000.0, 22.5, 908.4302734374994, 1013.2091796874992 - 0.75, 20000.0, 23.0, 1051.8578125, 1075.4140624999993 - 0.75, 20000.0, 23.5, 1194.2814453125004, 1137.2369140624985 - 0.75, 20000.0, 24.0, 1336.2000000000014, 1198.8999999999987 - 0.75, 20000.0, 24.5, 1478.112304687502, 1260.625585937499 - 0.75, 20000.0, 25.0, 1620.5171875000035, 1322.6359374999997 - 0.75, 20000.0, 25.5, 1763.9134765625054, 1385.1533203125002 - 0.75, 20000.0, 26.0, 1908.8000000000075, 1448.4000000000008 - 0.75, 20000.0, 26.5, 2060.9078125000083, 1514.8117187500063 - 0.75, 20000.0, 27.0, 2215.8025000000093, 1582.5237500000076 - 0.75, 20000.0, 27.5, 2373.0859375000105, 1651.3789062500086 - 0.75, 20000.0, 28.0, 2532.360000000012, 1721.22000000001 - 0.75, 20000.0, 28.5, 2693.226562500013, 1791.8898437500109 - 0.75, 20000.0, 29.0, 2855.287500000014, 1863.2312500000126 - 0.75, 20000.0, 29.5, 3018.144687500015, 1935.0870312500138 - 0.75, 20000.0, 30.0, 3181.400000000016, 2007.3000000000145 - 0.75, 20000.0, 30.5, 3340.477050781249, 2077.9127929687497 - 0.75, 20000.0, 31.0, 3499.5539062499993, 2148.7398437499987 - 0.75, 20000.0, 31.5, 3658.6303710937477, 2219.795410156248 - 0.75, 20000.0, 32.0, 3817.7062499999975, 2291.0937499999977 - 0.75, 20000.0, 32.5, 3976.781347656248, 2362.649121093746 - 0.75, 20000.0, 33.0, 4135.855468749998, 2434.4757812499943 - 0.75, 20000.0, 33.5, 4294.928417968748, 2506.587988281242 - 0.75, 20000.0, 34.0, 4453.999999999998, 2578.99999999999 - 0.75, 20000.0, 34.5, 4613.0687890624495, 2651.8060546875117 - 0.75, 20000.0, 35.0, 4772.135937499946, 2724.9328125000143 - 0.75, 20000.0, 35.5, 4931.201367187437, 2798.386914062518 - 0.75, 20000.0, 36.0, 5090.264999999927, 2872.175000000021 - 0.75, 20000.0, 36.5, 5249.326757812419, 2946.303710937524 - 0.75, 20000.0, 37.0, 5408.386562499911, 3020.779687500028 - 0.75, 20000.0, 37.5, 5567.4443359374, 3095.609570312533 - 0.75, 20000.0, 38.0, 5726.499999999888, 3170.8000000000375 - 0.75, 20000.0, 38.5, 5885.540820312513, 3246.2996093749175 - 0.75, 20000.0, 39.0, 6044.585937500018, 3322.2031249998968 - 0.75, 20000.0, 39.5, 6203.6380859375295, 3398.530078124875 - 0.75, 20000.0, 40.0, 6362.700000000039, 3475.2999999998488 - 0.75, 20000.0, 40.5, 6521.796875000005, 3552.335156249968 - 0.75, 20000.0, 41.0, 6680.900000000008, 3629.9312499999564 - 0.75, 20000.0, 41.5, 6840.003125000011, 3708.1867187499415 - 0.75, 20000.0, 42.0, 6999.100000000013, 3787.199999999925 - 0.75, 20000.0, 42.5, 7158.032031249992, 3867.526562500009 - 0.75, 20000.0, 43.0, 7317.006249999993, 3948.625000000009 - 0.75, 20000.0, 43.5, 7476.0773437499965, 4030.4109375000085 - 0.75, 20000.0, 44.0, 7635.300000000002, 4112.8000000000075 - 0.75, 20000.0, 44.5, 7795.244531250056, 4194.99296874999 - 0.75, 20000.0, 45.0, 7955.2437500000715, 4277.906249999986 - 0.75, 20000.0, 45.5, 8115.146093750093, 4361.74140624998 - 0.75, 20000.0, 46.0, 8274.800000000112, 4446.699999999973 - 0.75, 20000.0, 46.5, 8433.303906249932, 4533.397656249978 - 0.75, 20000.0, 47.0, 8591.5562499999, 4621.456249999972 - 0.75, 20000.0, 47.5, 8749.705468749858, 4710.911718749962 - 0.75, 20000.0, 48.0, 8907.899999999814, 4801.799999999952 - 0.75, 20000.0, 48.5, 9066.288281249763, 4894.157031249939 - 0.75, 20000.0, 49.0, 9225.018749999701, 4988.018749999926 - 0.75, 20000.0, 49.5, 9384.239843749634, 5083.421093749908 - 0.75, 20000.0, 50.0, 9544.099999999557, 5180.399999999891 - 0.75, 25000.0, 0.0, 289.9256072383788, 289.9256072383788 - 0.75, 25000.0, 22.0, 623.9000000000007, 776.2 - 0.75, 25000.0, 22.5, 742.3205078125027, 826.0728515624994 - 0.75, 25000.0, 23.0, 859.5234375000049, 875.7421874999987 - 0.75, 25000.0, 23.5, 975.914648437507, 925.3404296874979 - 0.75, 25000.0, 24.0, 1091.9000000000094, 974.9999999999969 - 0.75, 25000.0, 24.5, 1207.885351562512, 1024.853320312496 - 0.75, 25000.0, 25.0, 1324.2765625000138, 1075.0328124999944 - 0.75, 25000.0, 25.5, 1441.4794921875164, 1125.6708984374936 - 0.75, 25000.0, 26.0, 1559.9000000000196, 1176.899999999992 - 0.75, 25000.0, 26.5, 1684.2054687500008, 1230.2470703125048 - 0.75, 25000.0, 27.0, 1810.783750000001, 1284.529687500006 - 0.75, 25000.0, 27.5, 1939.3101562500012, 1339.6412109375067 - 0.75, 25000.0, 28.0, 2069.460000000002, 1395.4750000000079 - 0.75, 25000.0, 28.5, 2200.908593750002, 1451.9244140625092 - 0.75, 25000.0, 29.0, 2333.331250000003, 1508.882812500011 - 0.75, 25000.0, 29.5, 2466.4032812500036, 1566.243554687511 - 0.75, 25000.0, 30.0, 2599.8000000000034, 1623.9000000000124 - 0.75, 25000.0, 30.5, 2729.7875000000045, 1680.5560546874967 - 0.75, 25000.0, 31.0, 2859.775000000006, 1737.407812499996 - 0.75, 25000.0, 31.5, 2989.7625000000066, 1794.461914062495 - 0.75, 25000.0, 32.0, 3119.750000000008, 1851.7249999999942 - 0.75, 25000.0, 32.5, 3249.7375000000097, 1909.203710937493 - 0.75, 25000.0, 33.0, 3379.7250000000113, 1966.904687499992 - 0.75, 25000.0, 33.5, 3509.7125000000133, 2024.8345703124915 - 0.75, 25000.0, 34.0, 3639.7000000000166, 2082.9999999999905 - 0.75, 25000.0, 34.5, 3769.6842187500065, 2141.4191015624997 - 0.75, 25000.0, 35.0, 3899.66875000001, 2200.0859375000014 - 0.75, 25000.0, 35.5, 4029.653906250013, 2259.0060546875047 - 0.75, 25000.0, 36.0, 4159.640000000016, 2318.185000000008 - 0.75, 25000.0, 36.5, 4289.6273437500195, 2377.628320312512 - 0.75, 25000.0, 37.0, 4419.616250000023, 2437.3415625000166 - 0.75, 25000.0, 37.5, 4549.607031250028, 2497.330273437524 - 0.75, 25000.0, 38.0, 4679.600000000033, 2557.600000000029 - 0.75, 25000.0, 38.5, 4809.603906249959, 2618.2005859374485 - 0.75, 25000.0, 39.0, 4939.606249999954, 2679.070312499936 - 0.75, 25000.0, 39.5, 5069.605468749951, 2740.204882812424 - 0.75, 25000.0, 40.0, 5199.599999999946, 2801.599999999907 - 0.75, 25000.0, 40.5, 5329.576562500045, 2862.9593749999854 - 0.75, 25000.0, 41.0, 5459.550000000053, 2924.68749999998 - 0.75, 25000.0, 41.5, 5589.52343750006, 2986.8968749999735 - 0.75, 25000.0, 42.0, 5719.500000000069, 3049.6999999999666 - 0.75, 25000.0, 42.5, 5849.3968749999685, 3113.6351562499963 - 0.75, 25000.0, 43.0, 5979.337499999961, 3178.218749999993 - 0.75, 25000.0, 43.5, 6109.359374999957, 3243.3929687499904 - 0.75, 25000.0, 44.0, 6239.499999999952, 3309.099999999986 - 0.75, 25000.0, 44.5, 6370.1874999999845, 3374.9109375000166 - 0.75, 25000.0, 45.0, 6500.912499999974, 3441.287500000023 - 0.75, 25000.0, 45.5, 6631.556249999955, 3508.3203125000323 - 0.75, 25000.0, 46.0, 6761.999999999936, 3576.100000000043 - 0.75, 25000.0, 46.5, 6891.527343750003, 3644.5570312500163 - 0.75, 25000.0, 47.0, 7020.856249999999, 3714.006250000019 - 0.75, 25000.0, 47.5, 7150.107031249994, 3784.602343750024 - 0.75, 25000.0, 48.0, 7279.39999999999, 3856.5000000000277 - 0.75, 25000.0, 48.5, 7408.855468749983, 3929.8539062500313 - 0.75, 25000.0, 49.0, 7538.5937499999745, 4004.818750000035 - 0.75, 25000.0, 49.5, 7668.7351562499625, 4081.549218750038 - 0.75, 25000.0, 50.0, 7799.3999999999505, 4160.200000000042 - 0.75, 30000.0, 0.0, 236.9802245692568, 236.9802245692568 - 0.75, 30000.0, 22.0, 500.8999999999998, 628.5000000000008 - 0.75, 30000.0, 22.5, 595.9828125, 668.5476562500007 - 0.75, 30000.0, 23.0, 690.0750000000003, 708.0937500000007 - 0.75, 30000.0, 23.5, 783.5046875000004, 747.2929687499998 - 0.75, 30000.0, 24.0, 876.6000000000006, 786.2999999999988 - 0.75, 30000.0, 24.5, 969.6890625000007, 825.2695312499975 - 0.75, 30000.0, 25.0, 1063.100000000001, 864.3562499999957 - 0.75, 30000.0, 25.5, 1157.1609375000012, 903.7148437499932 - 0.75, 30000.0, 26.0, 1252.2000000000012, 943.4999999999907 - 0.75, 30000.0, 26.5, 1351.9865234375043, 985.3429687500031 - 0.75, 30000.0, 27.0, 1453.6040625000053, 1028.0062500000038 - 0.75, 30000.0, 27.5, 1556.7908203125062, 1071.391406250004 - 0.75, 30000.0, 28.0, 1661.2850000000067, 1115.4000000000042 - 0.75, 30000.0, 28.5, 1766.8248046875067, 1159.9335937500045 - 0.75, 30000.0, 29.0, 1873.148437500007, 1204.8937500000052 - 0.75, 30000.0, 29.5, 1979.9941015625075, 1250.1820312500054 - 0.75, 30000.0, 30.0, 2087.1000000000076, 1295.7000000000057 - 0.75, 30000.0, 30.5, 2191.453417968759, 1340.1392578124955 - 0.75, 30000.0, 31.0, 2295.805468750009, 1384.726562499994 - 0.75, 30000.0, 31.5, 2400.1563476562583, 1429.4787109374931 - 0.75, 30000.0, 32.0, 2504.5062500000085, 1474.4124999999913 - 0.75, 30000.0, 32.5, 2608.8553710937563, 1519.5447265624896 - 0.75, 30000.0, 33.0, 2713.203906250006, 1564.8921874999874 - 0.75, 30000.0, 33.5, 2817.552050781255, 1610.471679687485 - 0.75, 30000.0, 34.0, 2921.9000000000033, 1656.2999999999831 - 0.75, 30000.0, 34.5, 3026.2500000000223, 1702.8049218749916 - 0.75, 30000.0, 35.0, 3130.6000000000286, 1749.5531249999904 - 0.75, 30000.0, 35.5, 3234.9500000000376, 1796.522265624988 - 0.75, 30000.0, 36.0, 3339.300000000047, 1843.6899999999866 - 0.75, 30000.0, 36.5, 3443.650000000058, 1891.0339843749844 - 0.75, 30000.0, 37.0, 3548.00000000007, 1938.5318749999822 - 0.75, 30000.0, 37.5, 3652.350000000083, 1986.161328124981 - 0.75, 30000.0, 38.0, 3756.7000000000976, 2033.8999999999796 - 0.75, 30000.0, 38.5, 3861.049999999905, 2081.5652343749844 - 0.75, 30000.0, 39.0, 3965.3999999998837, 2129.3781249999815 - 0.75, 30000.0, 39.5, 4069.74999999986, 2177.351953124979 - 0.75, 30000.0, 40.0, 4174.099999999836, 2225.4999999999773 - 0.75, 30000.0, 40.5, 4278.449999999992, 2273.614843750003 - 0.75, 30000.0, 41.0, 4382.799999999989, 2322.0187500000034 - 0.75, 30000.0, 41.5, 4487.149999999981, 2370.8132812500053 - 0.75, 30000.0, 42.0, 4591.499999999973, 2420.1000000000095 - 0.75, 30000.0, 42.5, 4695.767968749986, 2470.429687499994 - 0.75, 30000.0, 43.0, 4800.068749999975, 2521.2749999999887 - 0.75, 30000.0, 43.5, 4904.4351562499605, 2572.5578124999824 - 0.75, 30000.0, 44.0, 5008.899999999944, 2624.199999999974 - 0.75, 30000.0, 44.5, 5113.8203124999845, 2675.697656249981 - 0.75, 30000.0, 45.0, 5218.774999999982, 2727.568749999976 - 0.75, 30000.0, 45.5, 5323.667187499979, 2779.9054687499706 - 0.75, 30000.0, 46.0, 5428.399999999976, 2832.7999999999643 - 0.75, 30000.0, 46.5, 5532.400000000013, 2886.2429687500075 - 0.75, 30000.0, 47.0, 5636.237500000017, 2940.4687500000064 - 0.75, 30000.0, 47.5, 5740.006250000022, 2995.610156250004 - 0.75, 30000.0, 48.0, 5843.800000000027, 3051.8 - 0.75, 30000.0, 48.5, 5947.7125000000315, 3109.1710937499943 - 0.75, 30000.0, 49.0, 6051.837500000036, 3167.8562499999844 - 0.75, 30000.0, 49.5, 6156.268750000039, 3227.988281249974 - 0.75, 30000.0, 50.0, 6261.100000000041, 3289.6999999999584 - 0.75, 35000.0, 0.0, 191.98092321729453, 191.98092321729453 - 0.75, 35000.0, 22.0, 385.7999999999998, 517.1000000000001 - 0.75, 35000.0, 22.5, 459.04257812499986, 547.9025390624996 - 0.75, 35000.0, 23.0, 531.5218749999997, 578.1796874999993 - 0.75, 35000.0, 23.5, 603.4902343749997, 608.0669921874993 - 0.75, 35000.0, 24.0, 675.1999999999995, 637.6999999999991 - 0.75, 35000.0, 24.5, 746.9035156249987, 667.2142578124993 - 0.75, 35000.0, 25.0, 818.8531249999985, 696.7453124999995 - 0.75, 35000.0, 25.5, 891.3011718749979, 726.4287109374998 - 0.75, 35000.0, 26.0, 964.4999999999968, 756.4 - 0.75, 35000.0, 26.5, 1041.3433593750037, 788.0142578125015 - 0.75, 35000.0, 27.0, 1119.5931250000042, 820.2571875000017 - 0.75, 35000.0, 27.5, 1199.0488281250045, 853.0552734375013 - 0.75, 35000.0, 28.0, 1279.510000000005, 886.3350000000012 - 0.75, 35000.0, 28.5, 1360.776171875005, 920.0228515625005 - 0.75, 35000.0, 29.0, 1442.6468750000054, 954.0453124999999 - 0.75, 35000.0, 29.5, 1524.9216406250055, 988.3288671874992 - 0.75, 35000.0, 30.0, 1607.400000000005, 1022.7999999999977 - 0.75, 35000.0, 30.5, 1687.782714843745, 1056.3692382812505 - 0.75, 35000.0, 31.0, 1768.1679687499925, 1090.0757812500005 - 0.75, 35000.0, 31.5, 1848.5551757812402, 1123.9428710937507 - 0.75, 35000.0, 32.0, 1928.9437499999879, 1157.9937500000008 - 0.75, 35000.0, 32.5, 2009.3331054687344, 1192.2516601562502 - 0.75, 35000.0, 33.0, 2089.722656249982, 1226.73984375 - 0.75, 35000.0, 33.5, 2170.1118164062277, 1261.48154296875 - 0.75, 35000.0, 34.0, 2250.499999999974, 1296.4999999999995 - 0.75, 35000.0, 34.5, 2330.878007812501, 1332.6760937500133 - 0.75, 35000.0, 35.0, 2411.254687500003, 1369.0937500000164 - 0.75, 35000.0, 35.5, 2491.6302734375054, 1405.69453125002 - 0.75, 35000.0, 36.0, 2572.0050000000074, 1442.4200000000255 - 0.75, 35000.0, 36.5, 2652.37910156251, 1479.211718750031 - 0.75, 35000.0, 37.0, 2732.7528125000135, 1516.0112500000373 - 0.75, 35000.0, 37.5, 2813.126367187517, 1552.7601562500433 - 0.75, 35000.0, 38.0, 2893.500000000021, 1589.400000000051 - 0.75, 35000.0, 38.5, 2973.874999999986, 1625.3386718749725 - 0.75, 35000.0, 39.0, 3054.2499999999873, 1661.3281249999666 - 0.75, 35000.0, 39.5, 3134.624999999988, 1697.4285156249598 - 0.75, 35000.0, 40.0, 3214.99999999999, 1733.6999999999514 - 0.75, 35000.0, 40.5, 3295.374999999996, 1770.2632812499983 - 0.75, 35000.0, 41.0, 3375.749999999993, 1807.0937499999977 - 0.75, 35000.0, 41.5, 3456.1249999999895, 1844.2273437499964 - 0.75, 35000.0, 42.0, 3536.499999999986, 1881.699999999994 - 0.75, 35000.0, 42.5, 3616.812500000001, 1919.7664062500073 - 0.75, 35000.0, 43.0, 3697.1500000000005, 1958.1562500000086 - 0.75, 35000.0, 43.5, 3777.537500000001, 1996.8179687500096 - 0.75, 35000.0, 44.0, 3858.000000000002, 2035.700000000011 - 0.75, 35000.0, 44.5, 3938.816406249968, 2074.4187499999925 - 0.75, 35000.0, 45.0, 4019.656249999957, 2113.3874999999903 - 0.75, 35000.0, 45.5, 4100.442968749943, 2152.6874999999845 - 0.75, 35000.0, 46.0, 4181.099999999928, 2192.3999999999787 - 0.75, 35000.0, 46.5, 4261.160156249988, 2232.688281249996 - 0.75, 35000.0, 47.0, 4341.093749999982, 2273.5187499999915 - 0.75, 35000.0, 47.5, 4420.980468749975, 2314.9398437499867 - 0.75, 35000.0, 48.0, 4500.899999999963, 2356.999999999981 - 0.75, 35000.0, 48.5, 4580.932031249949, 2399.7476562499733 - 0.75, 35000.0, 49.0, 4661.156249999937, 2443.231249999966 - 0.75, 35000.0, 49.5, 4741.652343749921, 2487.4992187499583 - 0.75, 35000.0, 50.0, 4822.4999999999, 2532.599999999948 - 0.75, 39000.0, 0.0, 159.23103220093358, 159.23103220093358 - 0.75, 39000.0, 22.0, 309.70000000000016, 444.8000000000001 - 0.75, 39000.0, 22.5, 368.4568359375008, 469.51699218749974 - 0.75, 39000.0, 23.0, 426.6078125000012, 493.95156249999945 - 0.75, 39000.0, 23.5, 484.35488281250144, 518.1853515624991 - 0.75, 39000.0, 24.0, 541.9000000000015, 542.2999999999988 - 0.75, 39000.0, 24.5, 599.4451171875014, 566.3771484374981 - 0.75, 39000.0, 25.0, 657.1921875000013, 590.4984374999976 - 0.75, 39000.0, 25.5, 715.3431640625013, 614.7455078124973 - 0.75, 39000.0, 26.0, 774.100000000001, 639.1999999999964 - 0.75, 39000.0, 26.5, 835.7865234375007, 664.650390625001 - 0.75, 39000.0, 27.0, 898.604062500001, 690.5118750000009 - 0.75, 39000.0, 27.5, 962.3908203125011, 716.744921875001 - 0.75, 39000.0, 28.0, 1026.9850000000013, 743.310000000001 - 0.75, 39000.0, 28.5, 1092.224804687501, 770.1675781250003 - 0.75, 39000.0, 29.0, 1157.9484375000009, 797.2781250000003 - 0.75, 39000.0, 29.5, 1223.994101562501, 824.6021093749997 - 0.75, 39000.0, 30.0, 1290.2000000000003, 852.0999999999991 - 0.75, 39000.0, 30.5, 1354.7013671875081, 879.2433593750056 - 0.75, 39000.0, 31.0, 1419.2015625000101, 906.5281250000065 - 0.75, 39000.0, 31.5, 1483.700976562512, 933.9613281250073 - 0.75, 39000.0, 32.0, 1548.2000000000135, 961.5500000000085 - 0.75, 39000.0, 32.5, 1612.6990234375155, 989.3011718750092 - 0.75, 39000.0, 33.0, 1677.1984375000175, 1017.2218750000102 - 0.75, 39000.0, 33.5, 1741.6986328125197, 1045.3191406250114 - 0.75, 39000.0, 34.0, 1806.2000000000219, 1073.6000000000124 - 0.75, 39000.0, 34.5, 1870.699648437496, 1101.9303906250111 - 0.75, 39000.0, 35.0, 1935.2015624999972, 1130.4718750000138 - 0.75, 39000.0, 35.5, 1999.7064453124988, 1159.2449218750164 - 0.75, 39000.0, 36.0, 2064.2150000000006, 1188.2700000000202 - 0.75, 39000.0, 36.5, 2128.727929687503, 1217.5675781250236 - 0.75, 39000.0, 37.0, 2193.2459375000058, 1247.1581250000272 - 0.75, 39000.0, 37.5, 2257.769726562508, 1277.0621093750315 - 0.75, 39000.0, 38.0, 2322.300000000012, 1307.3000000000359 - 0.75, 39000.0, 38.5, 2386.8617187499444, 1338.323632812491 - 0.75, 39000.0, 39.0, 2451.418749999935, 1369.498437499989 - 0.75, 39000.0, 39.5, 2515.9664062499246, 1400.7490234374866 - 0.75, 39000.0, 40.0, 2580.499999999913, 1431.999999999984 - 0.75, 39000.0, 40.5, 2644.983593750008, 1462.9171874999965 - 0.75, 39000.0, 41.0, 2709.456250000009, 1493.7874999999954 - 0.75, 39000.0, 41.5, 2773.925781250012, 1524.6390624999942 - 0.75, 39000.0, 42.0, 2838.4000000000133, 1555.499999999993 - 0.75, 39000.0, 42.5, 2902.9140625000005, 1586.2851562500095 - 0.75, 39000.0, 43.0, 2967.437500000001, 1617.1812500000092 - 0.75, 39000.0, 43.5, 3031.9671875000013, 1648.2617187500073 - 0.75, 39000.0, 44.0, 3096.5000000000027, 1679.6000000000042 - 0.75, 39000.0, 44.5, 3161.0289062499883, 1711.675781249989 - 0.75, 39000.0, 45.0, 3225.556249999981, 1743.993749999986 - 0.75, 39000.0, 45.5, 3290.080468749971, 1776.4648437499818 - 0.75, 39000.0, 46.0, 3354.5999999999594, 1808.9999999999766 - 0.75, 39000.0, 46.5, 3419.105468749967, 1840.814843750005 - 0.75, 39000.0, 47.0, 3483.606249999953, 1872.7937500000064 - 0.75, 39000.0, 47.5, 3548.1039062499353, 1905.1257812500087 - 0.75, 39000.0, 48.0, 3612.5999999999162, 1938.0000000000111 - 0.75, 39000.0, 48.5, 3677.0960937498926, 1971.6054687500143 - 0.75, 39000.0, 49.0, 3741.5937499998654, 2006.1312500000172 - 0.75, 39000.0, 49.5, 3806.0945312498357, 2041.7664062500207 - 0.75, 39000.0, 50.0, 3870.5999999998016, 2078.7000000000244 - 0.75, 43000.0, 0.0, 131.38129340613406, 131.38129340613406 - 0.75, 43000.0, 22.0, 249.99999999999994, 390.5 - 0.75, 43000.0, 22.5, 297.4451171875, 410.73085937500014 - 0.75, 43000.0, 23.0, 344.40156250000007, 430.7906250000003 - 0.75, 43000.0, 23.5, 391.0322265625, 450.7300781250007 - 0.75, 43000.0, 24.0, 437.49999999999994, 470.600000000001 - 0.75, 43000.0, 24.5, 483.96777343749966, 490.45117187500153 - 0.75, 43000.0, 25.0, 530.5984374999994, 510.33437500000224 - 0.75, 43000.0, 25.5, 577.5548828124994, 530.3003906250027 - 0.75, 43000.0, 26.0, 624.999999999999, 550.4000000000037 - 0.75, 43000.0, 26.5, 674.8070312499988, 571.0572265624994 - 0.75, 43000.0, 27.0, 725.5262499999982, 591.9709374999993 - 0.75, 43000.0, 27.5, 777.0273437499977, 613.1279296874994 - 0.75, 43000.0, 28.0, 829.1799999999974, 634.5149999999992 - 0.75, 43000.0, 28.5, 881.8539062499964, 656.1189453124996 - 0.75, 43000.0, 29.0, 934.9187499999955, 677.9265624999992 - 0.75, 43000.0, 29.5, 988.2442187499945, 699.9246484374991 - 0.75, 43000.0, 30.0, 1041.699999999994, 722.0999999999991 - 0.75, 43000.0, 30.5, 1093.7895507812543, 744.3684570312512 - 0.75, 43000.0, 31.0, 1145.878906250005, 766.794531250001 - 0.75, 43000.0, 31.5, 1197.967871093756, 789.3717773437514 - 0.75, 43000.0, 32.0, 1250.0562500000062, 812.0937500000018 - 0.75, 43000.0, 32.5, 1302.1438476562575, 834.9540039062521 - 0.75, 43000.0, 33.0, 1354.2304687500082, 857.9460937500024 - 0.75, 43000.0, 33.5, 1406.3159179687589, 881.0635742187529 - 0.75, 43000.0, 34.0, 1458.4000000000099, 904.3000000000034 - 0.75, 43000.0, 34.5, 1510.4714453125073, 927.2793749999972 - 0.75, 43000.0, 35.0, 1562.5421875000095, 950.3999999999971 - 0.75, 43000.0, 35.5, 1614.6130859375119, 973.6906249999967 - 0.75, 43000.0, 36.0, 1666.6850000000143, 997.1799999999963 - 0.75, 43000.0, 36.5, 1718.7587890625168, 1020.8968749999959 - 0.75, 43000.0, 37.0, 1770.83531250002, 1044.8699999999958 - 0.75, 43000.0, 37.5, 1822.9154296875236, 1069.1281249999956 - 0.75, 43000.0, 38.0, 1875.0000000000273, 1093.6999999999957 - 0.75, 43000.0, 38.5, 1927.1078124999758, 1119.0373046874865 - 0.75, 43000.0, 39.0, 1979.212499999972, 1144.5265624999834 - 0.75, 43000.0, 39.5, 2031.3109374999676, 1170.1025390624802 - 0.75, 43000.0, 40.0, 2083.3999999999633, 1195.6999999999764 - 0.75, 43000.0, 40.5, 2135.4531250000014, 1221.078906249999 - 0.75, 43000.0, 41.0, 2187.500000000002, 1246.4187499999985 - 0.75, 43000.0, 41.5, 2239.5468750000014, 1271.7242187499971 - 0.75, 43000.0, 42.0, 2291.6000000000013, 1296.9999999999961 - 0.75, 43000.0, 42.5, 2343.6499999999955, 1322.1648437499964 - 0.75, 43000.0, 43.0, 2395.724999999996, 1347.3437499999957 - 0.75, 43000.0, 43.5, 2447.8374999999955, 1372.5757812499942 - 0.75, 43000.0, 44.0, 2499.999999999996, 1397.8999999999924 - 0.75, 43000.0, 44.5, 2552.3773437500017, 1423.3593749999973 - 0.75, 43000.0, 45.0, 2604.7687500000025, 1448.9874999999963 - 0.75, 43000.0, 45.5, 2657.125781250002, 1474.8218749999965 - 0.75, 43000.0, 46.0, 2709.4000000000037, 1500.899999999996 - 0.75, 43000.0, 46.5, 2761.296874999994, 1527.1148437499985 - 0.75, 43000.0, 47.0, 2813.1124999999925, 1553.706249999998 - 0.75, 43000.0, 47.5, 2864.896874999991, 1580.7695312499977 - 0.75, 43000.0, 48.0, 2916.69999999999, 1608.3999999999974 - 0.75, 43000.0, 48.5, 2968.5718749999874, 1636.6929687499974 - 0.75, 43000.0, 49.0, 3020.562499999986, 1665.7437499999971 - 0.75, 43000.0, 49.5, 3072.721874999984, 1695.6476562499977 - 0.75, 43000.0, 50.0, 3125.0999999999826, 1726.499999999998 - 0.75, 48000.0, 0.0, 103.3156348879275, 103.3156348879275 - 0.75, 48000.0, 22.0, 196.8999999999999, 307.49999999999983 - 0.75, 48000.0, 22.5, 234.23359374999993, 323.448046875 - 0.75, 48000.0, 23.0, 271.19374999999997, 339.2531250000002 - 0.75, 48000.0, 23.5, 307.9070312500002, 354.9566406250002 - 0.75, 48000.0, 24.0, 344.50000000000045, 370.6 - 0.75, 48000.0, 24.5, 381.09921875000026, 386.2246093750001 - 0.75, 48000.0, 25.0, 417.8312500000005, 401.871875 - 0.75, 48000.0, 25.5, 454.8226562500008, 417.583203125 - 0.75, 48000.0, 26.0, 492.20000000000084, 433.3999999999999 - 0.75, 48000.0, 26.5, 531.4228515624998, 449.6712890624995 - 0.75, 48000.0, 27.0, 571.3609375, 466.14843749999943 - 0.75, 48000.0, 27.5, 611.9123046874996, 482.8201171874993 - 0.75, 48000.0, 28.0, 652.9749999999997, 499.6749999999992 - 0.75, 48000.0, 28.5, 694.4470703124998, 516.7017578124992 - 0.75, 48000.0, 29.0, 736.2265624999995, 533.889062499999 - 0.75, 48000.0, 29.5, 778.2115234374995, 551.2255859374991 - 0.75, 48000.0, 30.0, 820.2999999999993, 568.699999999999 - 0.75, 48000.0, 30.5, 861.3236328124999, 586.2291992187498 - 0.75, 48000.0, 31.0, 902.3484374999998, 603.8804687499999 - 0.75, 48000.0, 31.5, 943.3740234374999, 621.6493164062499 - 0.75, 48000.0, 32.0, 984.3999999999996, 639.5312499999998 - 0.75, 48000.0, 32.5, 1025.4259765624995, 657.5217773437498 - 0.75, 48000.0, 33.0, 1066.4515624999997, 675.6164062499997 - 0.75, 48000.0, 33.5, 1107.4763671874996, 693.8106445312496 - 0.75, 48000.0, 34.0, 1148.4999999999993, 712.0999999999995 - 0.75, 48000.0, 34.5, 1189.5122265624977, 730.201484375002 - 0.75, 48000.0, 35.0, 1230.5234374999982, 748.4156250000025 - 0.75, 48000.0, 35.5, 1271.5341796874986, 766.764453125003 - 0.75, 48000.0, 36.0, 1312.5449999999994, 785.2700000000033 - 0.75, 48000.0, 36.5, 1353.5564453125003, 803.954296875004 - 0.75, 48000.0, 37.0, 1394.5690625000016, 822.8393750000046 - 0.75, 48000.0, 37.5, 1435.5833984375026, 841.9472656250057 - 0.75, 48000.0, 38.0, 1476.6000000000042, 861.3000000000063 - 0.75, 48000.0, 38.5, 1517.6341796874815, 881.2455078125008 - 0.75, 48000.0, 39.0, 1558.664062499978, 901.3109375000012 - 0.75, 48000.0, 39.5, 1599.6869140624744, 921.4458984375017 - 0.75, 48000.0, 40.0, 1640.6999999999703, 941.6000000000023 - 0.75, 48000.0, 40.5, 1681.6742187499976, 961.5929687499985 - 0.75, 48000.0, 41.0, 1722.6437499999965, 981.5562499999979 - 0.75, 48000.0, 41.5, 1763.6164062499956, 1001.4914062499978 - 0.75, 48000.0, 42.0, 1804.5999999999947, 1021.3999999999975 - 0.75, 48000.0, 42.5, 1845.6062499999994, 1041.201562499999 - 0.75, 48000.0, 43.0, 1886.6374999999998, 1061.0124999999996 - 0.75, 48000.0, 43.5, 1927.6999999999994, 1080.8671874999998 - 0.75, 48000.0, 44.0, 1968.7999999999997, 1100.8 - 0.75, 48000.0, 44.5, 2010.0531250000001, 1120.86875 - 0.75, 48000.0, 45.0, 2051.3125, 1141.0750000000003 - 0.75, 48000.0, 45.5, 2092.540625, 1161.44375 - 0.75, 48000.0, 46.0, 2133.7, 1182.0000000000002 - 0.75, 48000.0, 46.5, 2174.5578124999947, 1202.6359374999993 - 0.75, 48000.0, 47.0, 2215.3499999999935, 1223.5625 - 0.75, 48000.0, 47.5, 2256.117187499993, 1244.8578125 - 0.75, 48000.0, 48.0, 2296.8999999999937, 1266.6000000000001 - 0.75, 48000.0, 48.5, 2337.7390624999935, 1288.8671875000005 - 0.75, 48000.0, 49.0, 2378.6749999999943, 1311.7375000000009 - 0.75, 48000.0, 49.5, 2419.748437499995, 1335.2890625000014 - 0.75, 48000.0, 50.0, 2460.9999999999977, 1359.6000000000017 - 0.8, 0.0, 0.0, 741.0965866747633, 741.0965866747633 - 0.8, 0.0, 22.0, 1997.4000000000137, 2196.6999999999284 - 0.8, 0.0, 22.5, 2378.224609374864, 2847.3121093748846 - 0.8, 0.0, 23.0, 2746.3906249995516, 3076.84062499991 - 0.8, 0.0, 23.5, 3104.7613281240715, 2968.223828124998 - 0.8, 0.0, 24.0, 3456.1999999984237, 2604.4000000001397 - 0.8, 0.0, 24.5, 3803.569921872603, 2068.307421875337 - 0.8, 0.0, 25.0, 4149.734374996609, 1442.884375000578 - 0.8, 0.0, 25.5, 4497.556640620438, 811.0691406258593 - 0.8, 0.0, 26.0, 4849.899999994088, 255.80000000116888 - 0.8, 0.0, 26.5, 5237.909375000581, 625.0919921877758 - 0.8, 0.0, 27.0, 5637.782500000802, 1280.5253125004438 - 0.8, 0.0, 27.5, 6047.534375001078, 2173.8822265631497 - 0.8, 0.0, 28.0, 6465.180000001414, 3256.9450000008956 - 0.8, 0.0, 28.5, 6888.734375001813, 4481.495898438683 - 0.8, 0.0, 29.0, 7316.2125000022725, 5799.317187501514 - 0.8, 0.0, 29.5, 7745.629375002801, 7162.1911328144015 - 0.8, 0.0, 30.0, 8175.0000000034, 8521.900000002337 - 0.8, 0.0, 30.5, 8577.272265624691, 9269.832031248545 - 0.8, 0.0, 31.0, 8977.915624999827, 9971.534374998308 - 0.8, 0.0, 31.5, 9377.332421874993, 10632.160156248057 - 0.8, 0.0, 32.0, 9775.925000000183, 11256.862499997802 - 0.8, 0.0, 32.5, 10174.0957031254, 11850.794531247535 - 0.8, 0.0, 33.0, 10572.246875000646, 12419.109374997268 - 0.8, 0.0, 33.5, 10970.780859375918, 12966.960156246994 - 0.8, 0.0, 34.0, 11370.10000000122, 13499.499999996722 - 0.8, 0.0, 34.5, 11776.88203124178, 14745.638007809583 - 0.8, 0.0, 35.0, 12184.656249988928, 15917.842187496726 - 0.8, 0.0, 35.5, 12593.22734373568, 16952.336523433867 - 0.8, 0.0, 36.0, 13002.399999982035, 17785.344999996 - 0.8, 0.0, 36.5, 13411.978906227983, 18353.091601558117 - 0.8, 0.0, 37.0, 13821.768749973526, 18591.800312495237 - 0.8, 0.0, 37.5, 14231.574218718642, 18437.695117182346 - 0.8, 0.0, 38.0, 14641.19999996335, 17826.99999999442 - 0.8, 0.0, 38.5, 15051.16269532961, 16112.81699219187 - 0.8, 0.0, 39.0, 15460.185937522869, 14116.851562505444 - 0.8, 0.0, 39.5, 15867.916210967107, 11904.910351569182 - 0.8, 0.0, 40.0, 16274.000000037388, 9542.800000008108 - 0.8, 0.0, 40.5, 16678.524218755207, 6987.648437499063 - 0.8, 0.0, 41.0, 17080.51875000716, 4457.412499998653 - 0.8, 0.0, 41.5, 17479.453906259147, 2061.3703124981166 - 0.8, 0.0, 42.0, 17874.800000011055, -91.20000000254731 - 0.8, 0.0, 42.5, 18257.117187496056, -1713.59843750233 - 0.8, 0.0, 43.0, 18638.34999999522, -2944.9375000030595 - 0.8, 0.0, 43.5, 19021.532812494715, -3746.9078125039127 - 0.8, 0.0, 44.0, 19409.699999994704, -4081.2000000048856 - 0.8, 0.0, 44.5, 19820.643749997023, -3540.3757812489257 - 0.8, 0.0, 45.0, 20236.737499994437, -2602.9062499982415 - 0.8, 0.0, 45.5, 20655.112499990784, -1378.1335937472259 - 0.8, 0.0, 46.0, 21072.89999998583, 24.60000000414948 - 0.8, 0.0, 46.5, 21476.067187490076, 1316.8078124941194 - 0.8, 0.0, 47.0, 21877.374999987762, 2639.949999991765 - 0.8, 0.0, 47.5, 22278.420312485436, 3956.3421874890632 - 0.8, 0.0, 48.0, 22680.799999983214, 5228.2999999860185 - 0.8, 0.0, 48.5, 23086.11093748119, 6418.139062482642 - 0.8, 0.0, 49.0, 23495.949999979464, 7488.17499997895 - 0.8, 0.0, 49.5, 23911.91406247812, 8400.72343747494 - 0.8, 0.0, 50.0, 24335.59999997726, 9118.099999970622 - 0.8, 2000.0, 0.0, 693.86631684205, 693.86631684205 - 0.8, 2000.0, 22.0, -33672.89999999987, -10660.19999999999 - 0.8, 2000.0, 22.5, -40042.62753906258, -12914.012890624981 - 0.8, 2000.0, 23.0, -46348.379687500295, -15024.27187499999 - 0.8, 2000.0, 23.5, -52611.916992188075, -17029.344921875014 - 0.8, 2000.0, 24.0, -58855.00000000089, -18967.600000000053 - 0.8, 2000.0, 24.5, -65099.38925781376, -20877.40507812511 - 0.8, 2000.0, 25.0, -71366.84531250173, -22797.12812500018 - 0.8, 2000.0, 25.5, -77679.12871093978, -24765.13710937525 - 0.8, 2000.0, 26.0, -84058.00000000291, -26819.800000000338 - 0.8, 2000.0, 26.5, -90754.30703124905, -29403.26035156202 - 0.8, 2000.0, 27.0, -97573.81374999887, -32173.183437499403 - 0.8, 2000.0, 27.5, -104499.00859374867, -35098.718554686755 - 0.8, 2000.0, 28.0, -111512.37999999845, -38149.0149999991 - 0.8, 2000.0, 28.5, -118596.41640624823, -41293.222070311414 - 0.8, 2000.0, 29.0, -125733.60624999805, -44500.4890624987 - 0.8, 2000.0, 29.5, -132906.43796874778, -47739.96527343596 - 0.8, 2000.0, 30.0, -140097.3999999976, -50980.7999999982 - 0.8, 2000.0, 30.5, -147105.35751952772, -53751.822167968676 - 0.8, 2000.0, 31.0, -154113.91015624593, -56504.43671874985 - 0.8, 2000.0, 31.5, -161123.03427733906, -59249.72822265602 - 0.8, 2000.0, 32.0, -168132.70624999466, -61998.78124999968 - 0.8, 2000.0, 32.5, -175142.90244140016, -64762.680371093316 - 0.8, 2000.0, 33.0, -182153.59921874318, -67552.51015624947 - 0.8, 2000.0, 33.5, -189164.77294921107, -70379.3551757806 - 0.8, 2000.0, 34.0, -196176.39999999138, -73254.2999999992 - 0.8, 2000.0, 34.5, -203195.2739453053, -76800.6780468735 - 0.8, 2000.0, 35.0, -210213.90468749191, -80359.01562499837 - 0.8, 2000.0, 35.5, -217231.6193359284, -83882.08789062327 - 0.8, 2000.0, 36.0, -224247.74499998993, -87322.66999999812 - 0.8, 2000.0, 36.5, -231261.6087890512, -90633.53710937298 - 0.8, 2000.0, 37.0, -238272.53781248754, -93767.4643749978 - 0.8, 2000.0, 37.5, -245279.8591796737, -96677.2269531226 - 0.8, 2000.0, 38.0, -252282.89999998474, -99315.59999999736 - 0.8, 2000.0, 38.5, -259268.67812498278, -101216.85761718643 - 0.8, 2000.0, 39.0, -266255.21249997895, -102969.27656249891 - 0.8, 2000.0, 39.5, -273244.56562497484, -104618.6322265615 - 0.8, 2000.0, 40.0, -280238.79999997007, -106210.69999999911 - 0.8, 2000.0, 40.5, -287250.54843749496, -107671.41640624774 - 0.8, 2000.0, 41.0, -294267.0749999935, -109214.33124999676 - 0.8, 2000.0, 41.5, -301286.2140624921, -110933.15546874545 - 0.8, 2000.0, 42.0, -308305.7999999903, -112921.59999999384 - 0.8, 2000.0, 42.5, -315312.7765624907, -115593.48906249728 - 0.8, 2000.0, 43.0, -322320.2249999864, -118594.37499999652 - 0.8, 2000.0, 43.5, -329330.3359374813, -121889.92343749563 - 0.8, 2000.0, 44.0, -336345.2999999749, -125445.79999999462 - 0.8, 2000.0, 44.5, -343388.78828123625, -129257.42812499835 - 0.8, 2000.0, 45.0, -350432.91874998243, -133248.8124999978 - 0.8, 2000.0, 45.5, -357471.2898437284, -137373.71562499722 - 0.8, 2000.0, 46.0, -364497.499999974, -141585.89999999668 - 0.8, 2000.0, 46.5, -371470.9875000076, -145722.52265624964 - 0.8, 2000.0, 47.0, -378433.17500000953, -149900.59374999913 - 0.8, 2000.0, 47.5, -385391.3250000115, -154120.51796874855 - 0.8, 2000.0, 48.0, -392352.700000013, -158382.69999999777 - 0.8, 2000.0, 48.5, -399324.56250001426, -162687.54453124697 - 0.8, 2000.0, 49.0, -406314.1750000151, -167035.4562499961 - 0.8, 2000.0, 49.5, -413328.8000000155, -171426.839843745 - 0.8, 2000.0, 50.0, -420375.70000001503, -175862.0999999938 - 0.8, 5000.0, 0.0, 627.5089068328704, 627.5089068328704 - 0.8, 5000.0, 22.0, 39769.89999999991, 15068.300000000045 - 0.8, 5000.0, 22.5, 47330.902539062365, 17580.296679687483 - 0.8, 5000.0, 23.0, 54809.3671874998, 20015.53906249995 - 0.8, 5000.0, 23.5, 62231.97324218722, 22401.361914062447 - 0.8, 5000.0, 24.0, 69625.3999999996, 24765.09999999996 - 0.8, 5000.0, 24.5, 77016.32675781191, 27134.08808593749 - 0.8, 5000.0, 25.0, 84431.43281249922, 29535.66093750003 - 0.8, 5000.0, 25.5, 91897.39746093648, 31997.153320312576 - 0.8, 5000.0, 26.0, 99440.8999999987, 34545.900000000154 - 0.8, 5000.0, 26.5, 107366.89980468673, 37480.60468749965 - 0.8, 5000.0, 27.0, 115439.69781249904, 40572.73999999963 - 0.8, 5000.0, 27.5, 123638.26816406132, 43803.12031249961 - 0.8, 5000.0, 28.0, 131941.58499999857, 47152.55999999962 - 0.8, 5000.0, 28.5, 140328.62246093576, 50601.873437499635 - 0.8, 5000.0, 29.0, 148778.3546874979, 54131.87499999966 - 0.8, 5000.0, 29.5, 157269.75582031006, 57723.379062499705 - 0.8, 5000.0, 30.0, 165781.7999999972, 61357.19999999975 - 0.8, 5000.0, 30.5, 174072.9051757819, 64849.45517578133 - 0.8, 5000.0, 31.0, 182363.60703125078, 68361.34140625007 - 0.8, 5000.0, 31.5, 190653.88505859463, 71889.35849609385 - 0.8, 5000.0, 32.0, 198943.71875000096, 75430.00625000012 - 0.8, 5000.0, 32.5, 207233.0875976573, 78979.7844726564 - 0.8, 5000.0, 33.0, 215521.9710937511, 82535.19296875018 - 0.8, 5000.0, 33.5, 223810.34873046994, 86092.731542969 - 0.8, 5000.0, 34.0, 232098.2000000012, 89648.90000000033 - 0.8, 5000.0, 34.5, 240383.42367187337, 93250.47222656154 - 0.8, 5000.0, 35.0, 248668.27812499815, 96838.88593749906 - 0.8, 5000.0, 35.5, 256952.94101562296, 100405.85292968655 - 0.8, 5000.0, 36.0, 265237.58999999776, 103943.08499999909 - 0.8, 5000.0, 36.5, 273522.4027343725, 107442.2939453117 - 0.8, 5000.0, 37.0, 281807.5568749972, 110895.1915624993 - 0.8, 5000.0, 37.5, 290093.23007812194, 114293.48964843694 - 0.8, 5000.0, 38.0, 298379.5999999966, 117628.89999999962 - 0.8, 5000.0, 38.5, 306669.02539060987, 120838.1556640623 - 0.8, 5000.0, 39.0, 314958.3718749824, 123996.45468749938 - 0.8, 5000.0, 39.5, 323247.33242185495, 127107.72636718632 - 0.8, 5000.0, 40.0, 331535.59999997716, 130175.8999999981 - 0.8, 5000.0, 40.5, 339819.28750000184, 133124.23593749726 - 0.8, 5000.0, 41.0, 348103.1000000021, 136069.59999999657 - 0.8, 5000.0, 41.5, 356388.162500002, 139048.18906249586 - 0.8, 5000.0, 42.0, 364675.60000000166, 142096.19999999506 - 0.8, 5000.0, 42.5, 372967.1664062453, 145318.9937499985 - 0.8, 5000.0, 43.0, 381263.1062499952, 148655.93749999805 - 0.8, 5000.0, 43.5, 389564.2929687453, 152115.5624999974 - 0.8, 5000.0, 44.0, 397871.5999999954, 155706.39999999668 - 0.8, 5000.0, 44.5, 406205.8500000018, 159481.44609375088 - 0.8, 5000.0, 45.0, 414539.9875000024, 163386.98125000094 - 0.8, 5000.0, 45.5, 422866.90625000355, 167413.75078125097 - 0.8, 5000.0, 46.0, 431179.5000000048, 171552.5000000008 - 0.8, 5000.0, 46.5, 439432.8031249923, 175836.49765624997 - 0.8, 5000.0, 47.0, 447672.7124999896, 180196.95625000037 - 0.8, 5000.0, 47.5, 455907.26562498655, 184607.61171875082 - 0.8, 5000.0, 48.0, 464144.4999999829, 189042.20000000144 - 0.8, 5000.0, 48.5, 472392.45312497864, 193474.45703125215 - 0.8, 5000.0, 49.0, 480659.16249997355, 197878.11875000296 - 0.8, 5000.0, 49.5, 488952.66562496783, 202226.92109375392 - 0.8, 5000.0, 50.0, 497280.9999999612, 206494.60000000495 - 0.8, 10000.0, 0.0, 528.1384758247927, 528.1384758247927 - 0.8, 10000.0, 22.0, 665.8000000000418, 1089.9999999999902 - 0.8, 10000.0, 22.5, 785.9015625000923, 1218.8517578125093 - 0.8, 10000.0, 23.0, 907.6375000001436, 1322.3234375000343 - 0.8, 10000.0, 23.5, 1031.0046875001988, 1404.2833984375668 - 0.8, 10000.0, 24.0, 1156.000000000259, 1468.6000000001063 - 0.8, 10000.0, 24.5, 1282.6203125003267, 1519.1416015626519 - 0.8, 10000.0, 25.0, 1410.8625000004029, 1559.7765625002055 - 0.8, 10000.0, 25.5, 1540.7234375004907, 1594.373242187767 - 0.8, 10000.0, 26.0, 1672.2000000005912, 1626.8000000003349 - 0.8, 10000.0, 26.5, 1806.4375000001085, 1698.8810546874788 - 0.8, 10000.0, 27.0, 1942.350000000149, 1778.6978124999864 - 0.8, 10000.0, 27.5, 2079.737500000193, 1863.6119140624965 - 0.8, 10000.0, 28.0, 2218.4000000002416, 1950.9850000000092 - 0.8, 10000.0, 28.5, 2358.1375000002918, 2038.1787109375248 - 0.8, 10000.0, 29.0, 2498.7500000003442, 2122.5546875000437 - 0.8, 10000.0, 29.5, 2640.037500000397, 2201.474570312565 - 0.8, 10000.0, 30.0, 2781.8000000004495, 2272.3000000000916 - 0.8, 10000.0, 30.5, 2922.4573242190913, 2281.2719726564696 - 0.8, 10000.0, 31.0, 3063.3210937504373, 2281.741406250235 - 0.8, 10000.0, 31.5, 3204.322753906796, 2275.938574218999 - 0.8, 10000.0, 32.0, 3345.393750000666, 2266.093750000261 - 0.8, 10000.0, 32.5, 3486.4655273445496, 2254.437207031525 - 0.8, 10000.0, 33.0, 3627.4695312509466, 2243.1992187502883 - 0.8, 10000.0, 33.5, 3768.337207032357, 2234.61005859405 - 0.8, 10000.0, 34.0, 3909.0000000012797, 2230.9000000003116 - 0.8, 10000.0, 34.5, 4048.885273437643, 2265.9810156259173 - 0.8, 10000.0, 35.0, 4188.4765624999845, 2307.384375001124 - 0.8, 10000.0, 35.5, 4327.7533203122875, 2354.3230468763522 - 0.8, 10000.0, 36.0, 4466.694999999558, 2406.0100000016005 - 0.8, 10000.0, 36.5, 4605.281054686793, 2461.6582031268713 - 0.8, 10000.0, 37.0, 4743.4909374989875, 2520.48062500216 - 0.8, 10000.0, 37.5, 4881.304101561151, 2581.6902343774723 - 0.8, 10000.0, 38.0, 5018.69999999827, 2644.500000002802 - 0.8, 10000.0, 38.5, 5154.291210943138, 2727.7949218758704 - 0.8, 10000.0, 39.0, 5290.132812506664, 2800.9156250009846 - 0.8, 10000.0, 39.5, 5426.508007820292, 2858.703515626116 - 0.8, 10000.0, 40.0, 5563.700000009024, 2896.000000001269 - 0.8, 10000.0, 40.5, 5703.309375000629, 2845.1562499998636 - 0.8, 10000.0, 41.0, 5843.775000001076, 2788.499999999897 - 0.8, 10000.0, 41.5, 5984.853125001632, 2745.86874999997 - 0.8, 10000.0, 42.0, 6126.300000002297, 2737.1000000000813 - 0.8, 10000.0, 42.5, 6267.438281252289, 2863.124999999747 - 0.8, 10000.0, 43.0, 6408.6312500030635, 3030.249999999721 - 0.8, 10000.0, 43.5, 6549.808593753973, 3225.874999999686 - 0.8, 10000.0, 44.0, 6690.900000005026, 3437.39999999964 - 0.8, 10000.0, 44.5, 6831.663281249515, 3620.318750000001 - 0.8, 10000.0, 45.0, 6972.268749999598, 3806.700000000075 - 0.8, 10000.0, 45.5, 7112.714843749763, 3996.706250000206 - 0.8, 10000.0, 46.0, 7253.000000000006, 4190.500000000411 - 0.8, 10000.0, 46.5, 7393.364843752539, 4415.208593749584 - 0.8, 10000.0, 47.0, 7533.468750003625, 4633.243749999507 - 0.8, 10000.0, 47.5, 7673.213281254874, 4833.982031249441 - 0.8, 10000.0, 48.0, 7812.500000006275, 5006.79999999938 - 0.8, 10000.0, 48.5, 7951.230468757812, 5141.0742187493215 - 0.8, 10000.0, 49.0, 8089.306250009474, 5226.181249999264 - 0.8, 10000.0, 49.5, 8226.628906261243, 5251.497656249197 - 0.8, 10000.0, 50.0, 8363.100000013115, 5206.399999999126 - 0.8, 15000.0, 0.0, 441.6259141976832, 441.6259141976832 - 0.8, 15000.0, 22.0, 650.599999999998, 1083.600000000003 - 0.8, 15000.0, 22.5, 772.6255859375035, 1141.3429687500206 - 0.8, 15000.0, 23.0, 893.9828125000101, 1199.8187500000386 - 0.8, 15000.0, 23.5, 1014.998632812519, 1258.9351562500585 - 0.8, 15000.0, 24.0, 1136.000000000029, 1318.6000000000809 - 0.8, 15000.0, 24.5, 1257.3138671875415, 1378.7210937501068 - 0.8, 15000.0, 25.0, 1379.2671875000565, 1439.2062500001375 - 0.8, 15000.0, 25.5, 1502.1869140625738, 1499.9632812501725 - 0.8, 15000.0, 26.0, 1626.4000000000938, 1560.9000000002143 - 0.8, 15000.0, 26.5, 1755.8906249999666, 1620.9521484375184 - 0.8, 15000.0, 27.0, 1887.5374999999633, 1680.944062500025 - 0.8, 15000.0, 27.5, 2021.040624999959, 1740.9501953125318 - 0.8, 15000.0, 28.0, 2156.099999999953, 1801.0450000000392 - 0.8, 15000.0, 28.5, 2292.4156249999482, 1861.302929687546 - 0.8, 15000.0, 29.0, 2429.6874999999413, 1921.7984375000526 - 0.8, 15000.0, 29.5, 2567.615624999933, 1982.6059765625585 - 0.8, 15000.0, 30.0, 2705.8999999999255, 2043.8000000000632 - 0.8, 15000.0, 30.5, 2841.1747070310535, 2106.1526367187075 - 0.8, 15000.0, 31.0, 2976.4976562497736, 2168.9742187499623 - 0.8, 15000.0, 31.5, 3111.8608398434926, 2232.27275390622 - 0.8, 15000.0, 32.0, 3247.25624999971, 2296.0562499999805 - 0.8, 15000.0, 32.5, 3382.675878905924, 2360.332714843741 - 0.8, 15000.0, 33.0, 3518.1117187496384, 2425.110156250008 - 0.8, 15000.0, 33.5, 3653.5557617183504, 2490.3965820312774 - 0.8, 15000.0, 34.0, 3788.9999999995607, 2556.20000000005 - 0.8, 15000.0, 34.5, 3924.241601561928, 2628.3612499997685 - 0.8, 15000.0, 35.0, 4059.485937499335, 2700.4999999997235 - 0.8, 15000.0, 35.5, 4194.743554686737, 2772.0687499996743 - 0.8, 15000.0, 36.0, 4330.024999999137, 2842.5199999996203 - 0.8, 15000.0, 36.5, 4465.340820311533, 2911.3062499995604 - 0.8, 15000.0, 37.0, 4600.7015624989235, 2977.8799999994953 - 0.8, 15000.0, 37.5, 4736.117773436312, 3041.6937499994247 - 0.8, 15000.0, 38.0, 4871.5999999987, 3102.199999999347 - 0.8, 15000.0, 38.5, 5007.364453123526, 3150.560351562537 - 0.8, 15000.0, 39.0, 5143.10937499826, 3198.8171875000753 - 0.8, 15000.0, 39.5, 5278.7996093729535, 3248.2654296876185 - 0.8, 15000.0, 40.0, 5414.399999997608, 3300.200000000166 - 0.8, 15000.0, 40.5, 5549.689843749593, 3360.805468749928 - 0.8, 15000.0, 41.0, 5684.893749999523, 3424.5312499999186 - 0.8, 15000.0, 41.5, 5820.050781249459, 3490.7164062499114 - 0.8, 15000.0, 42.0, 5955.19999999941, 3558.6999999999052 - 0.8, 15000.0, 42.5, 6090.31406250025, 3627.2585937499102 - 0.8, 15000.0, 43.0, 6225.525000000327, 3696.5187499998565 - 0.8, 15000.0, 43.5, 6360.898437500403, 3766.044531249793 - 0.8, 15000.0, 44.0, 6496.500000000473, 3835.399999999717 - 0.8, 15000.0, 44.5, 6633.1296874997815, 3901.2351562500135 - 0.8, 15000.0, 45.0, 6769.824999999688, 3967.1937500000286 - 0.8, 15000.0, 45.5, 6906.357812499567, 4034.0054687500524 - 0.8, 15000.0, 46.0, 7042.499999999421, 4102.400000000086 - 0.8, 15000.0, 46.5, 7176.843749999441, 4177.364843750285 - 0.8, 15000.0, 47.0, 7310.812499999291, 4253.66875000038 - 0.8, 15000.0, 47.5, 7444.649999999131, 4330.338281250493 - 0.8, 15000.0, 48.0, 7578.599999998962, 4406.400000000626 - 0.8, 15000.0, 48.5, 7712.906249998788, 4480.880468750779 - 0.8, 15000.0, 49.0, 7847.812499998612, 4552.806250000956 - 0.8, 15000.0, 49.5, 7983.56249999844, 4621.203906251158 - 0.8, 15000.0, 50.0, 8120.39999999827, 4685.100000001384 - 0.8, 20000.0, 0.0, 366.71301817357903, 366.71301817357903 - 0.8, 20000.0, 22.0, 750.9999999999989, 1018.9999999999994 - 0.8, 20000.0, 22.5, 893.4732421874993, 1081.284375000001 - 0.8, 20000.0, 23.0, 1034.4890624999998, 1143.7250000000029 - 0.8, 20000.0, 23.5, 1174.5353515625006, 1206.4281250000051 - 0.8, 20000.0, 24.0, 1314.1000000000022, 1269.5000000000075 - 0.8, 20000.0, 24.5, 1453.6708984375034, 1333.0468750000114 - 0.8, 20000.0, 25.0, 1593.7359375000053, 1397.175000000015 - 0.8, 20000.0, 25.5, 1734.783007812507, 1461.9906250000201 - 0.8, 20000.0, 26.0, 1877.3000000000097, 1527.6000000000254 - 0.8, 20000.0, 26.5, 2026.9031249999935, 1595.4150390624982 - 0.8, 20000.0, 27.0, 2179.2449999999913, 1664.310937499998 - 0.8, 20000.0, 27.5, 2333.9343749999875, 1734.1701171874977 - 0.8, 20000.0, 28.0, 2490.579999999984, 1804.8749999999973 - 0.8, 20000.0, 28.5, 2648.7906249999783, 1876.3080078124972 - 0.8, 20000.0, 29.0, 2808.1749999999715, 1948.351562499996 - 0.8, 20000.0, 29.5, 2968.3418749999646, 2020.8880859374951 - 0.8, 20000.0, 30.0, 3128.8999999999583, 2093.799999999995 - 0.8, 20000.0, 30.5, 3285.3499999999904, 2165.796679687495 - 0.8, 20000.0, 31.0, 3441.7999999999884, 2238.0453124999935 - 0.8, 20000.0, 31.5, 3598.249999999987, 2310.5400390624923 - 0.8, 20000.0, 32.0, 3754.699999999985, 2383.2749999999915 - 0.8, 20000.0, 32.5, 3911.149999999982, 2456.244335937492 - 0.8, 20000.0, 33.0, 4067.5999999999804, 2529.4421874999903 - 0.8, 20000.0, 33.5, 4224.049999999977, 2602.8626953124904 - 0.8, 20000.0, 34.0, 4380.499999999978, 2676.4999999999905 - 0.8, 20000.0, 34.5, 4536.949999999971, 2749.9298828125084 - 0.8, 20000.0, 35.0, 4693.399999999965, 2823.604687500016 - 0.8, 20000.0, 35.5, 4849.84999999996, 2897.558398437524 - 0.8, 20000.0, 36.0, 5006.299999999952, 2971.8250000000353 - 0.8, 20000.0, 36.5, 5162.749999999949, 3046.4384765625455 - 0.8, 20000.0, 37.0, 5319.1999999999425, 3121.4328125000598 - 0.8, 20000.0, 37.5, 5475.649999999936, 3196.841992187575 - 0.8, 20000.0, 38.0, 5632.099999999929, 3272.700000000092 - 0.8, 20000.0, 38.5, 5788.5552734373305, 3349.288671874848 - 0.8, 20000.0, 39.0, 5945.00781249979, 3426.2656249998145 - 0.8, 20000.0, 39.5, 6101.4564453122475, 3503.6097656247753 - 0.8, 20000.0, 40.0, 6257.899999999696, 3581.2999999997314 - 0.8, 20000.0, 40.5, 6414.322656249955, 3658.797656249946 - 0.8, 20000.0, 41.0, 6570.743749999938, 3736.8062499999246 - 0.8, 20000.0, 41.5, 6727.167968749916, 3815.5117187498995 - 0.8, 20000.0, 42.0, 6883.599999999894, 3895.0999999998694 - 0.8, 20000.0, 42.5, 7039.950781250035, 3976.6281250000006 - 0.8, 20000.0, 43.0, 7196.356250000035, 4059.0624999999964 - 0.8, 20000.0, 43.5, 7352.858593750027, 4142.240624999992 - 0.8, 20000.0, 44.0, 7509.500000000017, 4225.999999999989 - 0.8, 20000.0, 44.5, 7666.779687500012, 4309.412500000017 - 0.8, 20000.0, 45.0, 7824.100000000026, 4393.387500000026 - 0.8, 20000.0, 45.5, 7981.320312500037, 4478.0687500000395 - 0.8, 20000.0, 46.0, 8138.300000000059, 4563.600000000052 - 0.8, 20000.0, 46.5, 8294.187499999893, 4650.179687499969 - 0.8, 20000.0, 47.0, 8449.837499999854, 4737.874999999959 - 0.8, 20000.0, 47.5, 8605.393749999812, 4826.807812499951 - 0.8, 20000.0, 48.0, 8760.999999999764, 4917.099999999942 - 0.8, 20000.0, 48.5, 8916.799999999708, 5008.873437499933 - 0.8, 20000.0, 49.0, 9072.937499999654, 5102.249999999925 - 0.8, 20000.0, 49.5, 9229.556249999587, 5197.351562499915 - 0.8, 20000.0, 50.0, 9386.799999999526, 5294.299999999909 - 0.8, 25000.0, 0.0, 302.21346860524045, 302.21346860524045 - 0.8, 25000.0, 22.0, 626.4999999999995, 839.0999999999995 - 0.8, 25000.0, 22.5, 745.4023437500001, 891.1683593750007 - 0.8, 25000.0, 23.0, 863.0812500000009, 943.0031250000013 - 0.8, 25000.0, 23.5, 979.9445312500015, 994.7363281250017 - 0.8, 25000.0, 24.0, 1096.4000000000028, 1046.5000000000016 - 0.8, 25000.0, 24.5, 1212.8554687500043, 1098.4261718750013 - 0.8, 25000.0, 25.0, 1329.7187500000057, 1150.6468750000013 - 0.8, 25000.0, 25.5, 1447.3976562500084, 1203.2941406250009 - 0.8, 25000.0, 26.0, 1566.300000000011, 1256.5000000000002 - 0.8, 25000.0, 26.5, 1691.1156249999933, 1311.7554687499978 - 0.8, 25000.0, 27.0, 1818.2149999999908, 1367.911249999996 - 0.8, 25000.0, 27.5, 1947.2718749999897, 1424.866406249994 - 0.8, 25000.0, 28.0, 2077.9599999999864, 1482.5199999999925 - 0.8, 25000.0, 28.5, 2209.9531249999836, 1540.7710937499896 - 0.8, 25000.0, 29.0, 2342.9249999999815, 1599.5187499999865 - 0.8, 25000.0, 29.5, 2476.549374999977, 1658.6620312499838 - 0.8, 25000.0, 30.0, 2610.499999999972, 1718.09999999998 - 0.8, 25000.0, 30.5, 2741.0250000000206, 1776.5898437499968 - 0.8, 25000.0, 31.0, 2871.5500000000256, 1835.281249999997 - 0.8, 25000.0, 31.5, 3002.0750000000307, 1894.182031249997 - 0.8, 25000.0, 32.0, 3132.600000000035, 1953.2999999999975 - 0.8, 25000.0, 32.5, 3263.1250000000414, 2012.6429687499979 - 0.8, 25000.0, 33.0, 3393.6500000000487, 2072.218749999999 - 0.8, 25000.0, 33.5, 3524.1750000000566, 2132.035156249999 - 0.8, 25000.0, 34.0, 3654.700000000065, 2192.1 - 0.8, 25000.0, 34.5, 3785.2249999999913, 2252.4670312499948 - 0.8, 25000.0, 35.0, 3915.749999999989, 2313.0937499999973 - 0.8, 25000.0, 35.5, 4046.274999999988, 2373.9835937500025 - 0.8, 25000.0, 36.0, 4176.799999999983, 2435.140000000008 - 0.8, 25000.0, 36.5, 4307.324999999983, 2496.5664062500136 - 0.8, 25000.0, 37.0, 4437.849999999981, 2558.266250000022 - 0.8, 25000.0, 37.5, 4568.374999999981, 2620.24296875003 - 0.8, 25000.0, 38.0, 4698.899999999977, 2682.500000000041 - 0.8, 25000.0, 38.5, 4829.424999999993, 2744.9701171874044 - 0.8, 25000.0, 39.0, 4959.949999999993, 2807.7640624998835 - 0.8, 25000.0, 39.5, 5090.474999999996, 2870.9009765623587 - 0.8, 25000.0, 40.0, 5220.9999999999945, 2934.3999999998323 - 0.8, 25000.0, 40.5, 5351.521093750047, 2998.117187500018 - 0.8, 25000.0, 41.0, 5482.043750000066, 3062.300000000023 - 0.8, 25000.0, 41.5, 5612.569531250088, 3127.0328125000287 - 0.8, 25000.0, 42.0, 5743.100000000115, 3192.4000000000347 - 0.8, 25000.0, 42.5, 5873.550781250024, 3258.8648437499896 - 0.8, 25000.0, 43.0, 6004.043750000033, 3325.9812499999857 - 0.8, 25000.0, 43.5, 6134.614843750046, 3393.6820312499826 - 0.8, 25000.0, 44.0, 6265.300000000059, 3461.8999999999796 - 0.8, 25000.0, 44.5, 6396.517968750024, 3529.978125000012 - 0.8, 25000.0, 45.0, 6527.768750000039, 3598.67500000001 - 0.8, 25000.0, 45.5, 6658.935156250059, 3668.1593750000065 - 0.8, 25000.0, 46.0, 6789.900000000082, 3738.6000000000017 - 0.8, 25000.0, 46.5, 6919.952343750061, 3810.6734374999774 - 0.8, 25000.0, 47.0, 7049.806250000077, 3883.8374999999683 - 0.8, 25000.0, 47.5, 7179.58203125009, 3958.05781249996 - 0.8, 25000.0, 48.0, 7309.400000000104, 4033.299999999949 - 0.8, 25000.0, 48.5, 7439.380468750119, 4109.5296874999385 - 0.8, 25000.0, 49.0, 7569.643750000137, 4186.712499999926 - 0.8, 25000.0, 49.5, 7700.310156250155, 4264.8140624999105 - 0.8, 25000.0, 50.0, 7831.500000000174, 4343.799999999897 - 0.8, 30000.0, 0.0, 247.02411194413267, 247.02411194413267 - 0.8, 30000.0, 22.0, 504.7999999999998, 678.1999999999995 - 0.8, 30000.0, 22.5, 600.6025390625008, 718.9031250000002 - 0.8, 30000.0, 23.0, 695.4171875000015, 759.5250000000012 - 0.8, 30000.0, 23.5, 789.5732421875028, 800.1593750000029 - 0.8, 30000.0, 24.0, 883.4000000000041, 840.9000000000052 - 0.8, 30000.0, 24.5, 977.226757812505, 881.8406250000079 - 0.8, 30000.0, 25.0, 1071.3828125000066, 923.0750000000116 - 0.8, 30000.0, 25.5, 1166.1974609375084, 964.696875000016 - 0.8, 30000.0, 26.0, 1262.0000000000102, 1006.800000000021 - 0.8, 30000.0, 26.5, 1362.5800781249939, 1050.4638671874982 - 0.8, 30000.0, 27.0, 1465.0043749999916, 1094.8528124999975 - 0.8, 30000.0, 27.5, 1569.0089843749902, 1139.8916015624966 - 0.8, 30000.0, 28.0, 1674.3299999999879, 1185.5049999999956 - 0.8, 30000.0, 28.5, 1780.703515624986, 1231.6177734374949 - 0.8, 30000.0, 29.0, 1887.865624999983, 1278.1546874999933 - 0.8, 30000.0, 29.5, 1995.5524218749804, 1325.0405078124923 - 0.8, 30000.0, 30.0, 2103.499999999977, 1372.1999999999898 - 0.8, 30000.0, 30.5, 2208.665234375008, 1418.8520507812434 - 0.8, 30000.0, 31.0, 2313.8281250000095, 1465.694531249992 - 0.8, 30000.0, 31.5, 2418.989453125011, 1512.7194335937406 - 0.8, 30000.0, 32.0, 2524.150000000014, 1559.9187499999894 - 0.8, 30000.0, 32.5, 2629.310546875016, 1607.284472656237 - 0.8, 30000.0, 33.0, 2734.4718750000193, 1654.808593749985 - 0.8, 30000.0, 33.5, 2839.6347656250214, 1702.4831054687322 - 0.8, 30000.0, 34.0, 2944.8000000000243, 1750.2999999999797 - 0.8, 30000.0, 34.5, 3049.9847656250145, 1798.014609374985 - 0.8, 30000.0, 35.0, 3155.1718750000223, 1845.8781249999836 - 0.8, 30000.0, 35.5, 3260.3605468750293, 1893.9050781249816 - 0.8, 30000.0, 36.0, 3365.5500000000397, 1942.10999999998 - 0.8, 30000.0, 36.5, 3470.73945312505, 1990.5074218749778 - 0.8, 30000.0, 37.0, 3575.928125000062, 2039.1118749999757 - 0.8, 30000.0, 37.5, 3681.115234375076, 2087.937890624975 - 0.8, 30000.0, 38.0, 3786.3000000000907, 2136.999999999972 - 0.8, 30000.0, 38.5, 3891.4763671875003, 2186.3464843749193 - 0.8, 30000.0, 39.0, 3996.6515624999993, 2235.9406249999 - 0.8, 30000.0, 39.5, 4101.825976562497, 2285.7894531248785 - 0.8, 30000.0, 40.0, 4206.999999999995, 2335.8999999998546 - 0.8, 30000.0, 40.5, 4312.178906249995, 2386.117187499984 - 0.8, 30000.0, 41.0, 4417.356249999995, 2436.6749999999743 - 0.8, 30000.0, 41.5, 4522.530468749996, 2487.6453124999625 - 0.8, 30000.0, 42.0, 4627.7, 2539.099999999948 - 0.8, 30000.0, 42.5, 4732.7695312500155, 2591.4273437500033 - 0.8, 30000.0, 43.0, 4837.868750000018, 2644.2562500000026 - 0.8, 30000.0, 43.5, 4943.033593750015, 2697.53203125 - 0.8, 30000.0, 44.0, 5048.30000000001, 2751.199999999996 - 0.8, 30000.0, 44.5, 5154.043750000015, 2804.7953125000095 - 0.8, 30000.0, 45.0, 5259.825000000024, 2858.8375000000106 - 0.8, 30000.0, 45.5, 5365.543750000035, 2913.4359375000113 - 0.8, 30000.0, 46.0, 5471.100000000049, 2968.7000000000107 - 0.8, 30000.0, 46.5, 5575.897656250008, 3024.965624999983 - 0.8, 30000.0, 47.0, 5680.53125000001, 3082.0249999999805 - 0.8, 30000.0, 47.5, 5785.099218750011, 3139.8968749999785 - 0.8, 30000.0, 48.0, 5889.700000000008, 3198.599999999976 - 0.8, 30000.0, 48.5, 5994.432031250002, 3258.1531249999753 - 0.8, 30000.0, 49.0, 6099.393749999994, 3318.5749999999744 - 0.8, 30000.0, 49.5, 6204.683593749982, 3379.8843749999764 - 0.8, 30000.0, 50.0, 6310.399999999969, 3442.099999999978 - 0.8, 35000.0, 0.0, 200.11761383957753, 200.11761383957753 - 0.8, 35000.0, 22.0, 389.9999999999995, 557.7999999999997 - 0.8, 35000.0, 22.5, 463.99746093750025, 589.1033203125004 - 0.8, 35000.0, 23.0, 537.2453125000011, 620.1734375000005 - 0.8, 35000.0, 23.5, 609.9955078125028, 651.1068359375013 - 0.8, 35000.0, 24.0, 682.5000000000049, 682.0000000000015 - 0.8, 35000.0, 24.5, 755.010742187508, 712.9494140625018 - 0.8, 35000.0, 25.0, 827.7796875000113, 744.0515625000019 - 0.8, 35000.0, 25.5, 901.0587890625159, 775.4029296875024 - 0.8, 35000.0, 26.0, 975.1000000000213, 807.100000000003 - 0.8, 35000.0, 26.5, 1052.8062499999965, 840.0650390624978 - 0.8, 35000.0, 27.0, 1131.9299999999957, 873.6159374999971 - 0.8, 35000.0, 27.5, 1212.2687499999947, 907.7076171874962 - 0.8, 35000.0, 28.0, 1293.6199999999938, 942.2949999999952 - 0.8, 35000.0, 28.5, 1375.7812499999927, 977.3330078124937 - 0.8, 35000.0, 29.0, 1458.5499999999918, 1012.776562499992 - 0.8, 35000.0, 29.5, 1541.72374999999, 1048.5805859374902 - 0.8, 35000.0, 30.0, 1625.0999999999885, 1084.699999999988 - 0.8, 35000.0, 30.5, 1706.3499999999817, 1121.0040039062396 - 0.8, 35000.0, 31.0, 1787.599999999979, 1157.5414062499879 - 0.8, 35000.0, 31.5, 1868.8499999999763, 1194.2752929687363 - 0.8, 35000.0, 32.0, 1950.099999999974, 1231.1687499999837 - 0.8, 35000.0, 32.5, 2031.3499999999706, 1268.184863281232 - 0.8, 35000.0, 33.0, 2112.5999999999685, 1305.2867187499792 - 0.8, 35000.0, 33.5, 2193.8499999999644, 1342.4374023437263 - 0.8, 35000.0, 34.0, 2275.0999999999617, 1379.5999999999738 - 0.8, 35000.0, 34.5, 2356.3434374999742, 1416.0251562500005 - 0.8, 35000.0, 35.0, 2437.5874999999714, 1452.4562500000018 - 0.8, 35000.0, 35.5, 2518.832812499968, 1488.9242187500038 - 0.8, 35000.0, 36.0, 2600.0799999999645, 1525.4600000000066 - 0.8, 35000.0, 36.5, 2681.329687499962, 1562.0945312500094 - 0.8, 35000.0, 37.0, 2762.5824999999586, 1598.8587500000128 - 0.8, 35000.0, 37.5, 2843.839062499956, 1635.783593750017 - 0.8, 35000.0, 38.0, 2925.099999999954, 1672.9000000000215 - 0.8, 35000.0, 38.5, 3006.3775390624296, 1710.3675781249342 - 0.8, 35000.0, 39.0, 3087.654687499921, 1748.0218749999206 - 0.8, 35000.0, 39.5, 3168.92949218741, 1785.8652343749038 - 0.8, 35000.0, 40.0, 3250.1999999998975, 1823.8999999998857 - 0.8, 35000.0, 40.5, 3331.4554687499935, 1862.0015625 - 0.8, 35000.0, 41.0, 3412.7062499999943, 1900.3499999999983 - 0.8, 35000.0, 41.5, 3493.9539062499925, 1938.998437499996 - 0.8, 35000.0, 42.0, 3575.1999999999916, 1977.9999999999925 - 0.8, 35000.0, 42.5, 3656.3835937500285, 2017.6617187499864 - 0.8, 35000.0, 43.0, 3737.5937500000414, 2057.681249999984 - 0.8, 35000.0, 43.5, 3818.857031250058, 2098.010156249982 - 0.8, 35000.0, 44.0, 3900.200000000076, 2138.599999999981 - 0.8, 35000.0, 44.5, 3981.914843750007, 2178.9570312500023 - 0.8, 35000.0, 45.0, 4063.656250000004, 2219.656250000004 - 0.8, 35000.0, 45.5, 4145.344531250001, 2260.827343750008 - 0.8, 35000.0, 46.0, 4226.899999999996, 2302.6000000000117 - 0.8, 35000.0, 46.5, 4307.844531249976, 2345.322656250006 - 0.8, 35000.0, 47.0, 4388.656249999971, 2388.8187500000076 - 0.8, 35000.0, 47.5, 4469.4148437499625, 2433.1304687500115 - 0.8, 35000.0, 48.0, 4550.199999999955, 2478.300000000015 - 0.8, 35000.0, 48.5, 4631.091406249946, 2524.3695312500204 - 0.8, 35000.0, 49.0, 4712.168749999936, 2571.3812500000263 - 0.8, 35000.0, 49.5, 4793.5117187499245, 2619.377343750033 - 0.8, 35000.0, 50.0, 4875.199999999909, 2668.400000000041 - 0.8, 39000.0, 0.0, 165.97969047787768, 165.97969047787768 - 0.8, 39000.0, 22.0, 312.29999999999984, 479.19999999999953 - 0.8, 39000.0, 22.5, 371.56093750000093, 503.89843750000006 - 0.8, 39000.0, 23.0, 430.2125000000026, 528.6000000000009 - 0.8, 39000.0, 23.5, 488.4578125000049, 553.3515625000018 - 0.8, 39000.0, 24.0, 546.5000000000078, 578.2000000000029 - 0.8, 39000.0, 24.5, 604.5421875000117, 603.1921875000045 - 0.8, 39000.0, 25.0, 662.7875000000162, 628.3750000000065 - 0.8, 39000.0, 25.5, 721.4390625000217, 653.7953125000087 - 0.8, 39000.0, 26.0, 780.7000000000277, 679.5000000000116 - 0.8, 39000.0, 26.5, 842.9062499999995, 705.9447265625001 - 0.8, 39000.0, 27.0, 906.2499999999994, 732.7909374999999 - 0.8, 39000.0, 27.5, 970.5687499999993, 760.0154296874997 - 0.8, 39000.0, 28.0, 1035.699999999999, 787.5949999999995 - 0.8, 39000.0, 28.5, 1101.481249999999, 815.506445312499 - 0.8, 39000.0, 29.0, 1167.7499999999982, 843.7265624999983 - 0.8, 39000.0, 29.5, 1234.3437499999977, 872.2321484374977 - 0.8, 39000.0, 30.0, 1301.0999999999972, 900.9999999999965 - 0.8, 39000.0, 30.5, 1366.147949218751, 929.8555664062493 - 0.8, 39000.0, 31.0, 1431.1960937500019, 958.9414062499989 - 0.8, 39000.0, 31.5, 1496.2446289062523, 988.248730468748 - 0.8, 39000.0, 32.0, 1561.293750000003, 1017.7687499999978 - 0.8, 39000.0, 32.5, 1626.343652343754, 1047.4926757812468 - 0.8, 39000.0, 33.0, 1691.3945312500039, 1077.411718749996 - 0.8, 39000.0, 33.5, 1756.4465820312548, 1107.5170898437452 - 0.8, 39000.0, 34.0, 1821.5000000000052, 1137.7999999999943 - 0.8, 39000.0, 34.5, 1886.5627734375282, 1168.6023437499846 - 0.8, 39000.0, 35.0, 1951.626562500035, 1199.5312499999825 - 0.8, 39000.0, 35.5, 2016.690820312543, 1230.5445312499796 - 0.8, 39000.0, 36.0, 2081.7550000000515, 1261.5999999999767 - 0.8, 39000.0, 36.5, 2146.818554687561, 1292.6554687499727 - 0.8, 39000.0, 37.0, 2211.8809375000724, 1323.668749999969 - 0.8, 39000.0, 37.5, 2276.9416015625848, 1354.5976562499654 - 0.8, 39000.0, 38.0, 2342.0000000000964, 1385.3999999999603 - 0.8, 39000.0, 38.5, 2407.046093749882, 1415.5958984375106 - 0.8, 39000.0, 39.0, 2472.0937499998586, 1445.8078125000134 - 0.8, 39000.0, 39.5, 2537.144531249833, 1476.0908203125161 - 0.8, 39000.0, 40.0, 2602.1999999998047, 1506.5000000000193 - 0.8, 39000.0, 40.5, 2667.273437499986, 1537.1617187500094 - 0.8, 39000.0, 41.0, 2732.3499999999794, 1568.0312500000111 - 0.8, 39000.0, 41.5, 2797.426562499973, 1599.1351562500129 - 0.8, 39000.0, 42.0, 2862.499999999963, 1630.5000000000148 - 0.8, 39000.0, 42.5, 2927.50468750001, 1662.2968749999939 - 0.8, 39000.0, 43.0, 2992.525000000014, 1694.3499999999929 - 0.8, 39000.0, 43.5, 3057.582812500018, 1726.6281249999918 - 0.8, 39000.0, 44.0, 3122.700000000023, 1759.0999999999904 - 0.8, 39000.0, 44.5, 3188.1054687499964, 1791.5156250000048 - 0.8, 39000.0, 45.0, 3253.5312499999995, 1824.1500000000067 - 0.8, 39000.0, 45.5, 3318.9164062500045, 1857.0593750000073 - 0.8, 39000.0, 46.0, 3384.2000000000116, 1890.300000000008 - 0.8, 39000.0, 46.5, 3449.016406250033, 1923.7523437500038 - 0.8, 39000.0, 47.0, 3513.7312500000394, 1957.7187500000084 - 0.8, 39000.0, 47.5, 3578.4054687500434, 1992.3257812500149 - 0.8, 39000.0, 48.0, 3643.100000000048, 2027.7000000000228 - 0.8, 39000.0, 48.5, 3707.875781250051, 2063.967968750033 - 0.8, 39000.0, 49.0, 3772.7937500000553, 2101.256250000045 - 0.8, 39000.0, 49.5, 3837.9148437500594, 2139.6914062500605 - 0.8, 39000.0, 50.0, 3903.3000000000625, 2179.4000000000774 - 0.8, 43000.0, 0.0, 136.94960154887144, 136.94960154887144 - 0.8, 43000.0, 22.0, 252.09999999999985, 420.29999999999995 - 0.8, 43000.0, 22.5, 299.9728515625006, 440.8289062500005 - 0.8, 43000.0, 23.0, 347.354687500001, 461.2187500000013 - 0.8, 43000.0, 23.5, 394.40917968750125, 481.52421875000243 - 0.8, 43000.0, 24.0, 441.3000000000012, 501.80000000000393 - 0.8, 43000.0, 24.5, 488.1908203125011, 522.1007812500058 - 0.8, 43000.0, 25.0, 535.245312500001, 542.4812500000078 - 0.8, 43000.0, 25.5, 582.6271484375008, 562.9960937500103 - 0.8, 43000.0, 26.0, 630.5000000000003, 583.7000000000133 - 0.8, 43000.0, 26.5, 680.7460937499959, 605.0414062499985 - 0.8, 43000.0, 27.0, 731.9087499999946, 626.7037499999985 - 0.8, 43000.0, 27.5, 783.8570312499927, 648.6742187499984 - 0.8, 43000.0, 28.0, 836.4599999999906, 670.9399999999979 - 0.8, 43000.0, 28.5, 889.5867187499881, 693.4882812499981 - 0.8, 43000.0, 29.0, 943.1062499999856, 716.3062499999977 - 0.8, 43000.0, 29.5, 996.8876562499826, 739.3810937499973 - 0.8, 43000.0, 30.0, 1050.7999999999793, 762.6999999999972 - 0.8, 43000.0, 30.5, 1103.3375000000153, 786.2427734375041 - 0.8, 43000.0, 31.0, 1155.8750000000182, 810.004687500005 - 0.8, 43000.0, 31.5, 1208.4125000000213, 833.9736328125061 - 0.8, 43000.0, 32.0, 1260.9500000000241, 858.1375000000078 - 0.8, 43000.0, 32.5, 1313.4875000000275, 882.4841796875089 - 0.8, 43000.0, 33.0, 1366.0250000000306, 907.001562500011 - 0.8, 43000.0, 33.5, 1418.5625000000346, 931.6775390625133 - 0.8, 43000.0, 34.0, 1471.1000000000379, 956.5000000000156 - 0.8, 43000.0, 34.5, 1523.6407812500238, 981.711953124994 - 0.8, 43000.0, 35.0, 1576.1812500000299, 1007.0218749999937 - 0.8, 43000.0, 35.5, 1628.721093750037, 1032.393359374994 - 0.8, 43000.0, 36.0, 1681.2600000000448, 1057.789999999994 - 0.8, 43000.0, 36.5, 1733.7976562500537, 1083.175390624994 - 0.8, 43000.0, 37.0, 1786.3337500000632, 1108.5131249999943 - 0.8, 43000.0, 37.5, 1838.867968750074, 1133.7667968749947 - 0.8, 43000.0, 38.0, 1891.400000000086, 1158.8999999999953 - 0.8, 43000.0, 38.5, 1943.921093749937, 1183.4839843749578 - 0.8, 43000.0, 39.0, 1996.4437499999258, 1208.078124999948 - 0.8, 43000.0, 39.5, 2048.9695312499134, 1232.733203124937 - 0.8, 43000.0, 40.0, 2101.4999999999004, 1257.4999999999238 - 0.8, 43000.0, 40.5, 2154.0484375000115, 1282.5249999999974 - 0.8, 43000.0, 41.0, 2206.6000000000154, 1307.7249999999958 - 0.8, 43000.0, 41.5, 2259.1515625000197, 1333.1124999999947 - 0.8, 43000.0, 42.0, 2311.7000000000226, 1358.6999999999935 - 0.8, 43000.0, 42.5, 2364.1835937499995, 1384.5781249999948 - 0.8, 43000.0, 43.0, 2416.681250000001, 1410.649999999993 - 0.8, 43000.0, 43.5, 2469.213281250004, 1436.89687499999 - 0.8, 43000.0, 44.0, 2521.8000000000075, 1463.2999999999865 - 0.8, 43000.0, 44.5, 2574.6492187500057, 1489.6453124999896 - 0.8, 43000.0, 45.0, 2627.5187500000065, 1516.1874999999882 - 0.8, 43000.0, 45.5, 2680.3539062500085, 1542.985937499986 - 0.8, 43000.0, 46.0, 2733.1000000000113, 1570.0999999999851 - 0.8, 43000.0, 46.5, 2785.4289062499874, 1597.4875000000004 - 0.8, 43000.0, 47.0, 2837.6687499999857, 1625.3500000000001 - 0.8, 43000.0, 47.5, 2889.8742187499834, 1653.7875000000008 - 0.8, 43000.0, 48.0, 2942.09999999998, 1682.9000000000012 - 0.8, 43000.0, 48.5, 2994.4007812499763, 1712.7875000000017 - 0.8, 43000.0, 49.0, 3046.8312499999734, 1743.5500000000031 - 0.8, 43000.0, 49.5, 3099.4460937499666, 1775.287500000005 - 0.8, 43000.0, 50.0, 3152.299999999961, 1808.1000000000076 - 0.8, 48000.0, 0.0, 107.69444161226188, 107.69444161226188 - 0.8, 48000.0, 22.0, 198.4999999999997, 330.9999999999997 - 0.8, 48000.0, 22.5, 236.20117187500023, 347.1722656250002 - 0.8, 48000.0, 23.0, 273.5156250000009, 363.2343750000005 - 0.8, 48000.0, 23.5, 310.57226562500153, 379.2292968750007 - 0.8, 48000.0, 24.0, 347.5000000000024, 395.2000000000009 - 0.8, 48000.0, 24.5, 384.42773437500324, 411.189453125001 - 0.8, 48000.0, 25.0, 421.48437500000455, 427.2406250000011 - 0.8, 48000.0, 25.5, 458.798828125006, 443.3964843750012 - 0.8, 48000.0, 26.0, 496.5000000000077, 459.7000000000013 - 0.8, 48000.0, 26.5, 536.0703124999997, 476.5017578124981 - 0.8, 48000.0, 27.0, 576.3624999999994, 493.5546874999976 - 0.8, 48000.0, 27.5, 617.2734374999987, 510.84902343749707 - 0.8, 48000.0, 28.0, 658.6999999999983, 528.3749999999966 - 0.8, 48000.0, 28.5, 700.5390624999976, 546.122851562496 - 0.8, 48000.0, 29.0, 742.6874999999968, 564.0828124999952 - 0.8, 48000.0, 29.5, 785.0421874999956, 582.2451171874942 - 0.8, 48000.0, 30.0, 827.4999999999949, 600.5999999999934 - 0.8, 48000.0, 30.5, 868.8749999999987, 619.1356445312512 - 0.8, 48000.0, 31.0, 910.2499999999982, 637.8445312500014 - 0.8, 48000.0, 31.5, 951.6249999999977, 656.7170898437521 - 0.8, 48000.0, 32.0, 992.9999999999968, 675.7437500000024 - 0.8, 48000.0, 32.5, 1034.3749999999964, 694.9149414062529 - 0.8, 48000.0, 33.0, 1075.7499999999955, 714.2210937500035 - 0.8, 48000.0, 33.5, 1117.1249999999945, 733.6526367187537 - 0.8, 48000.0, 34.0, 1158.4999999999936, 753.2000000000044 - 0.8, 48000.0, 34.5, 1199.8815624999972, 773.051718750008 - 0.8, 48000.0, 35.0, 1241.2624999999987, 792.9812500000097 - 0.8, 48000.0, 35.5, 1282.6421875000008, 812.960156250012 - 0.8, 48000.0, 36.0, 1324.0200000000027, 832.9600000000141 - 0.8, 48000.0, 36.5, 1365.3953125000053, 852.9523437500173 - 0.8, 48000.0, 37.0, 1406.7675000000086, 872.9087500000203 - 0.8, 48000.0, 37.5, 1448.1359375000116, 892.8007812500236 - 0.8, 48000.0, 38.0, 1489.5000000000155, 912.6000000000272 - 0.8, 48000.0, 38.5, 1530.8421874999324, 931.9742187499963 - 0.8, 48000.0, 39.0, 1572.1874999999202, 951.3562499999958 - 0.8, 48000.0, 39.5, 1613.5390624999063, 970.7851562499951 - 0.8, 48000.0, 40.0, 1654.899999999891, 990.2999999999944 - 0.8, 48000.0, 40.5, 1696.2968749999975, 1010.0140624999979 - 0.8, 48000.0, 41.0, 1737.699999999997, 1029.8624999999977 - 0.8, 48000.0, 41.5, 1779.1031249999967, 1049.8546874999984 - 0.8, 48000.0, 42.0, 1820.4999999999966, 1069.9999999999986 - 0.8, 48000.0, 42.5, 1861.8218750000028, 1090.358593749999 - 0.8, 48000.0, 43.0, 1903.1500000000024, 1110.8687500000003 - 0.8, 48000.0, 43.5, 1944.5031250000025, 1131.5195312500018 - 0.8, 48000.0, 44.0, 1985.9000000000021, 1152.300000000004 - 0.8, 48000.0, 44.5, 2027.5156250000025, 1173.0664062500086 - 0.8, 48000.0, 45.0, 2069.150000000003, 1193.993750000011 - 0.8, 48000.0, 45.5, 2110.7593750000037, 1215.1242187500138 - 0.8, 48000.0, 46.0, 2152.300000000003, 1236.5000000000164 - 0.8, 48000.0, 46.5, 2193.5132812499864, 1258.0656250000027 - 0.8, 48000.0, 47.0, 2234.656249999984, 1280.0000000000048 - 0.8, 48000.0, 47.5, 2275.771093749983, 1302.3843750000071 - 0.8, 48000.0, 48.0, 2316.8999999999805, 1325.3000000000104 - 0.8, 48000.0, 48.5, 2358.085156249982, 1348.8281250000148 - 0.8, 48000.0, 49.0, 2399.368749999985, 1373.0500000000184 - 0.8, 48000.0, 49.5, 2440.7929687499895, 1398.0468750000234 - 0.8, 48000.0, 50.0, 2482.399999999998, 1423.9000000000292 - 0.8500000000000001, 0.0, 0.0, 774.0961457537835, 774.0961457537835 - 0.8500000000000001, 0.0, 22.0, 2249.500000000021, 2439.899999999908 - 0.8500000000000001, 0.0, 22.5, 2679.08574218735, 3270.072851562354 - 0.8500000000000001, 0.0, 23.0, 3092.6015624994657, 3542.954687499889 - 0.8500000000000001, 0.0, 23.5, 3493.591601561366, 3368.1591796875045 - 0.8500000000000001, 0.0, 24.0, 3885.599999998049, 2855.3000000001907 - 0.8500000000000001, 0.0, 24.5, 4272.170898434515, 2113.990820312947 - 0.8500000000000001, 0.0, 25.0, 4656.84843749576, 1253.8453125007645 - 0.8500000000000001, 0.0, 25.5, 5043.176757806783, 384.47714843863287 - 0.8500000000000001, 0.0, 26.0, 5434.699999992579, -384.49999999846113 - 0.8500000000000001, 0.0, 26.5, 5869.76406250074, 64.95683593786498 - 0.8500000000000001, 0.0, 27.0, 6319.100000001018, 891.656562500576 - 0.8500000000000001, 0.0, 27.5, 6780.285937501368, 2032.339257813338 - 0.8500000000000001, 0.0, 28.0, 7250.900000001792, 3423.7450000011504 - 0.8500000000000001, 0.0, 28.5, 7728.520312502295, 5002.613867189011 - 0.8500000000000001, 0.0, 29.0, 8210.725000002876, 6705.685937501938 - 0.8500000000000001, 0.0, 29.5, 8695.092187503542, 8469.701289064924 - 0.8500000000000001, 0.0, 30.0, 9179.200000004294, 10231.400000002977 - 0.8500000000000001, 0.0, 30.5, 9629.624902343374, 11197.68232421695 - 0.8500000000000001, 0.0, 31.0, 10077.899218749806, 12104.636718747906 - 0.8500000000000001, 0.0, 31.5, 10524.553613281287, 12958.511816403854 - 0.8500000000000001, 0.0, 32.0, 10970.118750000302, 13765.556249997293 - 0.8500000000000001, 0.0, 32.5, 11415.125292969351, 14532.018652340717 - 0.8500000000000001, 0.0, 33.0, 11860.10390625094, 15264.147656246643 - 0.8500000000000001, 0.0, 33.5, 12305.585253907568, 15968.191894527561 - 0.8500000000000001, 0.0, 34.0, 12752.100000001734, 16650.399999995974 - 0.8500000000000001, 0.0, 34.5, 13208.430742177203, 18261.409062496372 - 0.8500000000000001, 0.0, 35.0, 13666.070312486094, 19773.137499995937 - 0.8500000000000001, 0.0, 35.5, 14124.76347654448, 21101.892187495476 - 0.8500000000000001, 0.0, 36.0, 14584.254999977364, 22163.979999995026 - 0.8500000000000001, 0.0, 36.5, 15044.289648409736, 22875.707812494555 - 0.8500000000000001, 0.0, 37.0, 15504.612187466588, 23153.382499994063 - 0.8500000000000001, 0.0, 37.5, 15964.967382772913, 22913.31093749359 - 0.8500000000000001, 0.0, 38.0, 16425.09999995371, 22071.79999999309 - 0.8500000000000001, 0.0, 38.5, 16885.752539084107, 19778.65292969311 - 0.8500000000000001, 0.0, 39.0, 17345.154687528888, 17114.126562506946 - 0.8500000000000001, 0.0, 39.5, 17802.82949222491, 14164.861914071034 - 0.8500000000000001, 0.0, 40.0, 18258.300000047253, 11017.500000010376 - 0.8500000000000001, 0.0, 40.5, 18711.568750006925, 7615.139843748865 - 0.8500000000000001, 0.0, 41.0, 19161.48750000955, 4245.381249998341 - 0.8500000000000001, 0.0, 41.5, 19607.38750001226, 1052.2820312476797 - 0.8500000000000001, 0.0, 42.0, 20048.600000014907, -1820.1000000031563 - 0.8500000000000001, 0.0, 42.5, 20472.93671874484, -3992.710937502751 - 0.8500000000000001, 0.0, 43.0, 20895.856249993776, -5650.4875000036245 - 0.8500000000000001, 0.0, 43.5, 21321.297656243143, -6743.370312504649 - 0.8500000000000001, 0.0, 44.0, 21753.19999999317, -7221.300000005824 - 0.8500000000000001, 0.0, 44.5, 22214.545312496724, -6549.037499998676 - 0.8500000000000001, 0.0, 45.0, 22682.6124999936, -5355.774999997783 - 0.8500000000000001, 0.0, 45.5, 23153.72343748914, -3785.5249999964944 - 0.8500000000000001, 0.0, 46.0, 23624.19999998306, -1982.2999999947133 - 0.8500000000000001, 0.0, 46.5, 24076.13749998772, -326.08515625736004 - 0.8500000000000001, 0.0, 47.0, 24525.774999984904, 1369.4687499896881 - 0.8500000000000001, 0.0, 47.5, 24975.1249999821, 3054.7382812362966 - 0.8500000000000001, 0.0, 48.0, 25426.199999979446, 4680.099999982475 - 0.8500000000000001, 0.0, 48.5, 25881.012499977063, 6195.9304687282365 - 0.8500000000000001, 0.0, 49.0, 26341.574999975077, 7552.606249973587 - 0.8500000000000001, 0.0, 49.5, 26809.89999997361, 8700.503906218557 - 0.8500000000000001, 0.0, 50.0, 27287.999999972777, 9589.999999963122 - 0.8500000000000001, 2000.0, 0.0, 724.7628058116046, 724.7628058116046 - 0.8500000000000001, 2000.0, 22.0, -45286.89999999982, -14675.399999999987 - 0.8500000000000001, 2000.0, 22.5, -53853.69375000008, -17710.73027343747 - 0.8500000000000001, 2000.0, 23.0, -62334.37500000038, -20552.845312499987 - 0.8500000000000001, 2000.0, 23.5, -70758.21875000071, -23253.462695312523 - 0.8500000000000001, 2000.0, 24.0, -79154.50000000115, -25864.300000000076 - 0.8500000000000001, 2000.0, 24.5, -87552.49375000161, -28437.074804687658 - 0.8500000000000001, 2000.0, 25.0, -95981.47500000217, -31023.504687500237 - 0.8500000000000001, 2000.0, 25.5, -104470.7187500029, -33675.30722656285 - 0.8500000000000001, 2000.0, 26.0, -113049.50000000368, -36444.20000000048 - 0.8500000000000001, 2000.0, 26.5, -122055.24140624875, -39927.55195312436 - 0.8500000000000001, 2000.0, 27.0, -131226.67874999848, -43662.6093749992 - 0.8500000000000001, 2000.0, 27.5, -140540.26171874822, -47607.549609374015 - 0.8500000000000001, 2000.0, 28.0, -149972.43999999797, -51720.54999999881 - 0.8500000000000001, 2000.0, 28.5, -159499.66328124766, -55959.787890623586 - 0.8500000000000001, 2000.0, 29.0, -169098.38124999742, -60283.44062499832 - 0.8500000000000001, 2000.0, 29.5, -178745.0435937471, -64649.685546873014 - 0.8500000000000001, 2000.0, 30.0, -188416.09999999686, -69016.69999999768 - 0.8500000000000001, 2000.0, 30.5, -197841.0623046827, -72745.61123046864 - 0.8500000000000001, 2000.0, 31.0, -207266.83593749444, -76448.50859374978 - 0.8500000000000001, 2000.0, 31.5, -216693.3884765561, -80140.43134765592 - 0.8500000000000001, 2000.0, 32.0, -226120.68749999275, -83836.41874999953 - 0.8500000000000001, 2000.0, 32.5, -235548.70058592924, -87551.51005859318 - 0.8500000000000001, 2000.0, 33.0, -244977.39531249067, -91300.74453124925 - 0.8500000000000001, 2000.0, 33.5, -254406.73925780202, -95099.16142578034 - 0.8500000000000001, 2000.0, 34.0, -263836.6999999883, -98961.79999999894 - 0.8500000000000001, 2000.0, 34.5, -273276.4941406155, -103732.9333203104 - 0.8500000000000001, 2000.0, 35.0, -282715.95937498927, -108519.39218749771 - 0.8500000000000001, 2000.0, 35.5, -292154.18242186296, -113257.24121093504 - 0.8500000000000001, 2000.0, 36.0, -301590.2499999866, -117882.54499999726 - 0.8500000000000001, 2000.0, 36.5, -311023.24882811005, -122331.36816405956 - 0.8500000000000001, 2000.0, 37.0, -320452.26562498335, -126539.7753124968 - 0.8500000000000001, 2000.0, 37.5, -329876.3871093565, -130443.83105468395 - 0.8500000000000001, 2000.0, 38.0, -339294.69999997964, -133979.59999999608 - 0.8500000000000001, 2000.0, 38.5, -348689.5847656028, -136515.4970703111 - 0.8500000000000001, 2000.0, 39.0, -358085.4968749729, -138849.57343749865 - 0.8500000000000001, 2000.0, 39.5, -367485.23554684233, -141044.03808593622 - 0.8500000000000001, 2000.0, 40.0, -376891.59999996144, -143161.09999999887 - 0.8500000000000001, 2000.0, 40.5, -386321.73906249326, -145099.42421874698 - 0.8500000000000001, 2000.0, 41.0, -395758.3624999916, -147150.18124999575 - 0.8500000000000001, 2000.0, 41.5, -405198.52968748956, -149440.99765624406 - 0.8500000000000001, 2000.0, 42.0, -414639.29999998753, -152099.499999992 - 0.8500000000000001, 2000.0, 42.5, -424063.00234373746, -155690.06484374643 - 0.8500000000000001, 2000.0, 43.0, -433487.3187499818, -159728.86874999537 - 0.8500000000000001, 2000.0, 43.5, -442915.2007812249, -164168.8382812442 - 0.8500000000000001, 2000.0, 44.0, -452349.59999996645, -168962.89999999283 - 0.8500000000000001, 2000.0, 44.5, -461822.38593748224, -174103.91796874782 - 0.8500000000000001, 2000.0, 45.0, -471296.0249999773, -179488.90624999703 - 0.8500000000000001, 2000.0, 45.5, -480761.9015624719, -185054.8164062463 - 0.8500000000000001, 2000.0, 46.0, -490211.3999999661, -190738.5999999956 - 0.8500000000000001, 2000.0, 46.5, -499589.90078125976, -196318.04843749938 - 0.8500000000000001, 2000.0, 47.0, -508953.193750012, -201952.93749999872 - 0.8500000000000001, 2000.0, 47.5, -518311.0648437643, -207643.882812498 - 0.8500000000000001, 2000.0, 48.0, -527673.3000000162, -213391.49999999703 - 0.8500000000000001, 2000.0, 48.5, -537049.685156268, -219196.40468749593 - 0.8500000000000001, 2000.0, 49.0, -546450.0062500192, -225059.21249999464 - 0.8500000000000001, 2000.0, 49.5, -555884.0492187692, -230980.53906249322 - 0.8500000000000001, 2000.0, 50.0, -565361.6000000187, -236960.99999999168 - 0.8500000000000001, 5000.0, 0.0, 655.4506321301836, 655.4506321301836 - 0.8500000000000001, 5000.0, 22.0, 55602.299999999894, 20702.200000000066 - 0.8500000000000001, 5000.0, 22.5, 66173.37988281234, 24207.107031249998 - 0.8500000000000001, 5000.0, 23.0, 76629.03593749976, 27605.41874999995 - 0.8500000000000001, 5000.0, 23.5, 87006.57402343715, 30935.246093749953 - 0.8500000000000001, 5000.0, 24.0, 97343.2999999995, 34234.69999999997 - 0.8500000000000001, 5000.0, 24.5, 107676.51972656179, 37541.891406250004 - 0.8500000000000001, 5000.0, 25.0, 118043.53906249903, 40894.93125000005 - 0.8500000000000001, 5000.0, 25.5, 128481.66386718626, 44331.93046875013 - 0.8500000000000001, 5000.0, 26.0, 139028.19999999835, 47891.00000000022 - 0.8500000000000001, 5000.0, 26.5, 150109.5781249991, 51988.13320312455 - 0.8500000000000001, 5000.0, 27.0, 161396.21499999883, 56305.15187499953 - 0.8500000000000001, 5000.0, 27.5, 172858.70937499855, 60815.38710937453 - 0.8500000000000001, 5000.0, 28.0, 184467.65999999823, 65492.169999999525 - 0.8500000000000001, 5000.0, 28.5, 196193.66562499778, 70308.83164062451 - 0.8500000000000001, 5000.0, 29.0, 208007.32499999742, 75238.70312499958 - 0.8500000000000001, 5000.0, 29.5, 219879.23687499695, 80255.11554687466 - 0.8500000000000001, 5000.0, 30.0, 231779.99999999648, 85331.39999999972 - 0.8500000000000001, 5000.0, 30.5, 243371.77070312577, 90213.01132812513 - 0.8500000000000001, 5000.0, 31.0, 254962.96562500094, 95122.85937500016 - 0.8500000000000001, 5000.0, 31.5, 266553.55898437614, 100055.97773437518 - 0.8500000000000001, 5000.0, 32.0, 278143.52500000125, 105007.40000000018 - 0.8500000000000001, 5000.0, 32.5, 289732.83789062616, 109972.15976562524 - 0.8500000000000001, 5000.0, 33.0, 301321.4718750014, 114945.29062500033 - 0.8500000000000001, 5000.0, 33.5, 312909.40117187647, 119921.82617187541 - 0.8500000000000001, 5000.0, 34.0, 324496.6000000015, 124896.80000000048 - 0.8500000000000001, 5000.0, 34.5, 336080.1698437477, 129937.57101562388 - 0.8500000000000001, 5000.0, 35.0, 347663.23124999733, 134959.9593749989 - 0.8500000000000001, 5000.0, 35.5, 359246.0320312471, 139952.11054687397 - 0.8500000000000001, 5000.0, 36.0, 370828.8199999968, 144902.16999999902 - 0.8500000000000001, 5000.0, 36.5, 382411.8429687463, 149798.28320312416 - 0.8500000000000001, 5000.0, 37.0, 393995.348749996, 154628.59562499938 - 0.8500000000000001, 5000.0, 37.5, 405579.58515624545, 159381.25273437455 - 0.8500000000000001, 5000.0, 38.0, 417164.7999999949, 164044.39999999985 - 0.8500000000000001, 5000.0, 38.5, 428754.33027341776, 168525.50878906247 - 0.8500000000000001, 5000.0, 39.0, 440343.73281247716, 172935.22968749944 - 0.8500000000000001, 5000.0, 39.5, 451932.5689452864, 177279.63574218625 - 0.8500000000000001, 5000.0, 40.0, 463520.3999999703, 181564.7999999978 - 0.8500000000000001, 5000.0, 40.5, 475101.6945312525, 185685.4234374965 - 0.8500000000000001, 5000.0, 41.0, 486683.1437500028, 189803.49999999558 - 0.8500000000000001, 5000.0, 41.5, 498266.3460937529, 193969.6515624946 - 0.8500000000000001, 5000.0, 42.0, 509852.90000000247, 198234.49999999366 - 0.8500000000000001, 5000.0, 42.5, 521445.39609374385, 202746.38593749807 - 0.8500000000000001, 5000.0, 43.0, 533044.0437499938, 207419.1249999974 - 0.8500000000000001, 5000.0, 43.5, 544650.0445312436, 212264.25156249662 - 0.8500000000000001, 5000.0, 44.0, 556264.5999999936, 217293.29999999562 - 0.8500000000000001, 5000.0, 44.5, 567916.7437500024, 222578.91796875125 - 0.8500000000000001, 5000.0, 45.0, 579568.7125000035, 228047.08125000133 - 0.8500000000000001, 5000.0, 45.5, 591210.5750000047, 233684.87890625128 - 0.8500000000000001, 5000.0, 46.0, 602832.4000000064, 239479.40000000104 - 0.8500000000000001, 5000.0, 46.5, 614371.3304687401, 245478.08125000002 - 0.8500000000000001, 5000.0, 47.0, 625891.5312499866, 251583.5250000005 - 0.8500000000000001, 5000.0, 47.5, 637404.2414062326, 257758.68125000107 - 0.8500000000000001, 5000.0, 48.0, 648920.6999999777, 263966.5000000018 - 0.8500000000000001, 5000.0, 48.5, 660452.1460937222, 270169.9312500027 - 0.8500000000000001, 5000.0, 49.0, 672009.8187499655, 276331.9250000037 - 0.8500000000000001, 5000.0, 49.5, 683604.9570312079, 282415.43125000485 - 0.8500000000000001, 5000.0, 50.0, 695248.7999999495, 288383.40000000614 - 0.8500000000000001, 10000.0, 0.0, 551.6554331934453, 551.6554331934453 - 0.8500000000000001, 10000.0, 22.0, 607.4000000000581, 1069.0999999999885 - 0.8500000000000001, 10000.0, 22.5, 712.9064453126297, 1236.9207031250153 - 0.8500000000000001, 10000.0, 23.0, 821.7984375002012, 1363.3343750000508 - 0.8500000000000001, 10000.0, 23.5, 933.7912109377754, 1454.655859375096 - 0.8500000000000001, 10000.0, 24.0, 1048.6000000003564, 1517.2000000001499 - 0.8500000000000001, 10000.0, 24.5, 1165.9400390629455, 1557.2816406252143 - 0.8500000000000001, 10000.0, 25.0, 1285.5265625005468, 1581.21562500029 - 0.8500000000000001, 10000.0, 25.5, 1407.0748046881633, 1595.3167968753742 - 0.8500000000000001, 10000.0, 26.0, 1530.3000000007974, 1605.9000000004717 - 0.8500000000000001, 10000.0, 26.5, 1653.768945312665, 1681.3914062499834 - 0.8500000000000001, 10000.0, 27.0, 1778.2796875002205, 1769.5437499999953 - 0.8500000000000001, 10000.0, 27.5, 1903.7443359377814, 1866.0242187500116 - 0.8500000000000001, 10000.0, 28.0, 2030.0750000003463, 1966.5000000000296 - 0.8500000000000001, 10000.0, 28.5, 2157.183789062912, 2066.6382812500515 - 0.8500000000000001, 10000.0, 29.0, 2284.98281250048, 2162.106250000078 - 0.8500000000000001, 10000.0, 29.5, 2413.3841796880483, 2248.5710937501053 - 0.8500000000000001, 10000.0, 30.0, 2542.300000000613, 2321.7000000001367 - 0.8500000000000001, 10000.0, 30.5, 2671.8372070317396, 2293.7302734377963 - 0.8500000000000001, 10000.0, 31.0, 2801.69453125063, 2251.704687500313 - 0.8500000000000001, 10000.0, 31.5, 2931.765527344538, 2199.2361328128277 - 0.8500000000000001, 10000.0, 32.0, 3061.943750000965, 2139.937500000342 - 0.8500000000000001, 10000.0, 32.5, 3192.122753907411, 2077.4216796878536 - 0.8500000000000001, 10000.0, 33.0, 3322.196093751377, 2015.301562500364 - 0.8500000000000001, 10000.0, 33.5, 3452.057324220363, 1957.1900390628753 - 0.8500000000000001, 10000.0, 34.0, 3581.6000000018685, 1906.700000000386 - 0.8500000000000001, 10000.0, 34.5, 3709.9182812504937, 1919.4710156263939 - 0.8500000000000001, 10000.0, 35.0, 3837.7812500003142, 1942.1343750017065 - 0.8500000000000001, 10000.0, 35.5, 3965.15859375009, 1973.3480468770501 - 0.8500000000000001, 10000.0, 36.0, 4092.019999999817, 2011.7700000024263 - 0.8500000000000001, 10000.0, 36.5, 4218.3351562494945, 2056.0582031278336 - 0.8500000000000001, 10000.0, 37.0, 4344.073749999124, 2104.8706250032733 - 0.8500000000000001, 10000.0, 37.5, 4469.205468748705, 2156.8652343787426 - 0.8500000000000001, 10000.0, 38.0, 4593.699999998232, 2210.700000004244 - 0.8500000000000001, 10000.0, 38.5, 4715.421875007761, 2294.4101562509773 - 0.8500000000000001, 10000.0, 39.0, 4837.537500009156, 2362.0437500010707 - 0.8500000000000001, 10000.0, 39.5, 4960.484375010689, 2405.7304687511796 - 0.8500000000000001, 10000.0, 40.0, 5084.700000012363, 2417.600000001308 - 0.8500000000000001, 10000.0, 40.5, 5212.6765625009875, 2292.590624999818 - 0.8500000000000001, 10000.0, 41.0, 5341.975000001625, 2158.8999999998696 - 0.8500000000000001, 10000.0, 41.5, 5472.210937502411, 2047.5343749999688 - 0.8500000000000001, 10000.0, 42.0, 5603.0000000033415, 1989.500000000126 - 0.8500000000000001, 10000.0, 42.5, 5733.313281253166, 2142.81484374962 - 0.8500000000000001, 10000.0, 43.0, 5863.668750004196, 2360.6687499995714 - 0.8500000000000001, 10000.0, 43.5, 5993.939843755406, 2623.263281249513 - 0.8500000000000001, 10000.0, 44.0, 6124.000000006807, 2910.7999999994277 - 0.8500000000000001, 10000.0, 44.5, 6253.207031249352, 3153.2148437500196 - 0.8500000000000001, 10000.0, 45.0, 6382.156249999466, 3401.081250000121 - 0.8500000000000001, 10000.0, 45.5, 6510.927343749691, 3654.707031250303 - 0.8500000000000001, 10000.0, 46.0, 6639.600000000039, 3914.4000000005844 - 0.8500000000000001, 10000.0, 46.5, 6769.062500003599, 4222.471874999372 - 0.8500000000000001, 10000.0, 47.0, 6898.262500005137, 4520.424999999264 - 0.8500000000000001, 10000.0, 47.5, 7026.956250006901, 4791.765624999171 - 0.8500000000000001, 10000.0, 48.0, 7154.900000008871, 5019.999999999088 - 0.8500000000000001, 10000.0, 48.5, 7281.850000011024, 5188.6343749990065 - 0.8500000000000001, 10000.0, 49.0, 7407.562500013345, 5281.174999998928 - 0.8500000000000001, 10000.0, 49.5, 7531.793750015803, 5281.128124998843 - 0.8500000000000001, 10000.0, 50.0, 7654.300000018385, 5171.999999998754 - 0.8500000000000001, 15000.0, 0.0, 461.2906390236099, 461.2906390236099 - 0.8500000000000001, 15000.0, 22.0, 607.6999999999983, 1109.700000000008 - 0.8500000000000001, 15000.0, 22.5, 719.9058593750041, 1175.8480468750352 - 0.8500000000000001, 15000.0, 23.0, 832.2531250000119, 1240.8781250000627 - 0.8500000000000001, 15000.0, 23.5, 944.9238281250224, 1304.8441406250934 - 0.8500000000000001, 15000.0, 24.0, 1058.1000000000354, 1367.8000000001275 - 0.8500000000000001, 15000.0, 24.5, 1171.9636718750514, 1429.7996093751672 - 0.8500000000000001, 15000.0, 25.0, 1286.6968750000706, 1490.8968750002125 - 0.8500000000000001, 15000.0, 25.5, 1402.4816406250932, 1551.145703125266 - 0.8500000000000001, 15000.0, 26.0, 1519.500000000119, 1610.6000000003282 - 0.8500000000000001, 15000.0, 26.5, 1640.3443359374426, 1668.3716796875349 - 0.8500000000000001, 15000.0, 27.0, 1762.9240624999354, 1725.402812500046 - 0.8500000000000001, 15000.0, 27.5, 1887.0080078124274, 1781.9087890625583 - 0.8500000000000001, 15000.0, 28.0, 2012.364999999917, 1838.105000000072 - 0.8500000000000001, 15000.0, 28.5, 2138.7638671874065, 1894.2068359375849 - 0.8500000000000001, 15000.0, 29.0, 2265.9734374998934, 1950.4296875000973 - 0.8500000000000001, 15000.0, 29.5, 2393.7625390623775, 2006.988945312609 - 0.8500000000000001, 15000.0, 30.0, 2521.8999999998623, 2064.100000000119 - 0.8500000000000001, 15000.0, 30.5, 2647.8893554684405, 2123.433886718666 - 0.8500000000000001, 15000.0, 31.0, 2773.980468749644, 2183.6117187499217 - 0.8500000000000001, 15000.0, 31.5, 2900.1579101558455, 2244.71025390618 - 0.8500000000000001, 15000.0, 32.0, 3026.406249999544, 2306.806249999943 - 0.8500000000000001, 15000.0, 32.5, 3152.71005859324, 2369.97646484371 - 0.8500000000000001, 15000.0, 33.0, 3279.0539062494345, 2434.2976562499816 - 0.8500000000000001, 15000.0, 33.5, 3405.4223632806265, 2499.84658203126 - 0.8500000000000001, 15000.0, 34.0, 3531.7999999993153, 2566.7000000000417 - 0.8500000000000001, 15000.0, 34.5, 3657.7862499991274, 2649.551406249624 - 0.8500000000000001, 15000.0, 35.0, 3783.7874999989845, 2732.468749999548 - 0.8500000000000001, 15000.0, 35.5, 3909.824999998831, 2814.136718749463 - 0.8500000000000001, 15000.0, 36.0, 4035.9199999986727, 2893.2399999993686 - 0.8500000000000001, 15000.0, 36.5, 4162.093749998506, 2968.4632812492646 - 0.8500000000000001, 15000.0, 37.0, 4288.367499998333, 3038.4912499991524 - 0.8500000000000001, 15000.0, 37.5, 4414.762499998154, 3102.0085937490267 - 0.8500000000000001, 15000.0, 38.0, 4541.299999997971, 3157.699999998893 - 0.8500000000000001, 15000.0, 38.5, 4668.448437498078, 3185.9439453126624 - 0.8500000000000001, 15000.0, 39.0, 4795.549999997748, 3213.223437500249 - 0.8500000000000001, 15000.0, 39.5, 4922.5265624973645, 3242.2912109378467 - 0.8500000000000001, 15000.0, 40.0, 5049.299999996932, 3275.9000000004576 - 0.8500000000000001, 15000.0, 40.5, 5175.385937499362, 3326.848437499887 - 0.8500000000000001, 15000.0, 41.0, 5301.2749999992675, 3383.8249999998757 - 0.8500000000000001, 15000.0, 41.5, 5427.051562499191, 3445.564062499869 - 0.8500000000000001, 15000.0, 42.0, 5552.799999999142, 3510.7999999998674 - 0.8500000000000001, 15000.0, 42.5, 5678.56562500053, 3577.5601562498937 - 0.8500000000000001, 15000.0, 43.0, 5804.487500000702, 3645.5687499998176 - 0.8500000000000001, 15000.0, 43.5, 5930.665625000883, 3713.8429687497237 - 0.8500000000000001, 15000.0, 44.0, 6057.200000001061, 3781.3999999996113 - 0.8500000000000001, 15000.0, 44.5, 6185.303906249645, 3840.5421875000216 - 0.8500000000000001, 15000.0, 45.0, 6313.518749999495, 3899.687500000045 - 0.8500000000000001, 15000.0, 45.5, 6441.499218749304, 3960.539062500083 - 0.8500000000000001, 15000.0, 46.0, 6568.899999999074, 4024.8000000001375 - 0.8500000000000001, 15000.0, 46.5, 6693.59843749914, 4104.14218750047 - 0.8500000000000001, 15000.0, 47.0, 6817.737499998916, 4186.312500000626 - 0.8500000000000001, 15000.0, 47.5, 6941.682812498673, 4269.026562500812 - 0.8500000000000001, 15000.0, 48.0, 7065.799999998424, 4350.000000001034 - 0.8500000000000001, 15000.0, 48.5, 7190.454687498166, 4426.94843750129 - 0.8500000000000001, 15000.0, 49.0, 7316.012499997908, 4497.587500001582 - 0.8500000000000001, 15000.0, 49.5, 7442.839062497657, 4559.632812501916 - 0.8500000000000001, 15000.0, 50.0, 7571.299999997418, 4610.800000002292 - 0.8500000000000001, 20000.0, 0.0, 383.0420205274593, 383.0420205274593 - 0.8500000000000001, 20000.0, 22.0, 733.0999999999982, 1093.6999999999991 - 0.8500000000000001, 20000.0, 22.5, 872.2058593749994, 1156.9136718750035 - 0.8500000000000001, 20000.0, 23.0, 1009.890625000001, 1220.2531250000084 - 0.8500000000000001, 20000.0, 23.5, 1146.630078125003, 1283.8160156250146 - 0.8500000000000001, 20000.0, 24.0, 1282.9000000000049, 1347.7000000000219 - 0.8500000000000001, 20000.0, 24.5, 1419.176171875007, 1412.0027343750312 - 0.8500000000000001, 20000.0, 25.0, 1555.9343750000098, 1476.8218750000422 - 0.8500000000000001, 20000.0, 25.5, 1693.6503906250132, 1542.2550781250548 - 0.8500000000000001, 20000.0, 26.0, 1832.800000000017, 1608.4000000000701 - 0.8500000000000001, 20000.0, 26.5, 1978.8615234374868, 1676.457617187498 - 0.8500000000000001, 20000.0, 27.0, 2127.5940624999803, 1745.485312499999 - 0.8500000000000001, 20000.0, 27.5, 2278.6158203124724, 1815.3916015624989 - 0.8500000000000001, 20000.0, 28.0, 2431.5449999999623, 1886.0849999999987 - 0.8500000000000001, 20000.0, 28.5, 2585.99980468745, 1957.4740234374983 - 0.8500000000000001, 20000.0, 29.0, 2741.598437499936, 2029.4671874999972 - 0.8500000000000001, 20000.0, 29.5, 2897.9591015624205, 2101.9730078124967 - 0.8500000000000001, 20000.0, 30.0, 3054.699999999902, 2174.899999999994 - 0.8500000000000001, 20000.0, 30.5, 3207.4263671874915, 2247.4360351562314 - 0.8500000000000001, 20000.0, 31.0, 3360.1515624999893, 2320.2789062499764 - 0.8500000000000001, 20000.0, 31.5, 3512.875976562489, 2393.4057617187236 - 0.8500000000000001, 20000.0, 32.0, 3665.599999999988, 2466.7937499999703 - 0.8500000000000001, 20000.0, 32.5, 3818.3240234374866, 2540.4200195312155 - 0.8500000000000001, 20000.0, 33.0, 3971.0484374999883, 2614.2617187499623 - 0.8500000000000001, 20000.0, 33.5, 4123.7736328124865, 2688.295996093708 - 0.8500000000000001, 20000.0, 34.0, 4276.499999999989, 2762.499999999956 - 0.8500000000000001, 20000.0, 34.5, 4429.237773437447, 2835.936640625027 - 0.8500000000000001, 20000.0, 35.0, 4581.976562499937, 2909.584375000045 - 0.8500000000000001, 20000.0, 35.5, 4734.715820312427, 2983.507421875068 - 0.8500000000000001, 20000.0, 36.0, 4887.454999999915, 3057.7700000000928 - 0.8500000000000001, 20000.0, 36.5, 5040.1935546874065, 3132.436328125122 - 0.8500000000000001, 20000.0, 37.0, 5192.9309374998975, 3207.5706250001567 - 0.8500000000000001, 20000.0, 37.5, 5345.666601562386, 3283.237109375195 - 0.8500000000000001, 20000.0, 38.0, 5498.399999999874, 3359.5000000002374 - 0.8500000000000001, 20000.0, 38.5, 5651.121093749652, 3436.923437499676 - 0.8500000000000001, 20000.0, 39.0, 5803.843749999561, 3514.8124999995975 - 0.8500000000000001, 20000.0, 39.5, 5956.569531249457, 3593.120312499509 - 0.8500000000000001, 20000.0, 40.0, 6109.299999999334, 3671.799999999408 - 0.8500000000000001, 20000.0, 40.5, 6262.0484374999, 3750.449218749902 - 0.8500000000000001, 20000.0, 41.0, 6414.79999999986, 3829.518749999862 - 0.8500000000000001, 20000.0, 41.5, 6567.551562499809, 3909.1039062498157 - 0.8500000000000001, 20000.0, 42.0, 6720.299999999752, 3989.2999999997605 - 0.8500000000000001, 20000.0, 42.5, 6872.909375000118, 4070.5187500000184 - 0.8500000000000001, 20000.0, 43.0, 7025.562500000128, 4152.412500000021 - 0.8500000000000001, 20000.0, 43.5, 7178.309375000133, 4234.950000000022 - 0.8500000000000001, 20000.0, 44.0, 7331.200000000127, 4318.100000000021 - 0.8500000000000001, 20000.0, 44.5, 7484.772656250042, 4401.960156250047 - 0.8500000000000001, 20000.0, 45.0, 7638.393750000066, 4486.3187500000695 - 0.8500000000000001, 20000.0, 45.5, 7791.917968750101, 4571.092968750099 - 0.8500000000000001, 20000.0, 46.0, 7945.20000000014, 4656.200000000135 - 0.8500000000000001, 20000.0, 46.5, 8097.367968749816, 4740.271874999948 - 0.8500000000000001, 20000.0, 47.0, 8249.293749999755, 4825.024999999936 - 0.8500000000000001, 20000.0, 47.5, 8401.122656249681, 4910.890624999922 - 0.8500000000000001, 20000.0, 48.0, 8552.999999999602, 4998.299999999909 - 0.8500000000000001, 20000.0, 48.5, 8705.071093749513, 5087.684374999896 - 0.8500000000000001, 20000.0, 49.0, 8857.481249999426, 5179.474999999883 - 0.8500000000000001, 20000.0, 49.5, 9010.375781249331, 5274.103124999872 - 0.8500000000000001, 20000.0, 50.0, 9163.899999999236, 5371.999999999864 - 0.8500000000000001, 25000.0, 0.0, 315.6704341223289, 315.6704341223289 - 0.8500000000000001, 25000.0, 22.0, 631.5999999999987, 911.3999999999984 - 0.8500000000000001, 25000.0, 22.5, 751.4085937500001, 963.5716796875021 - 0.8500000000000001, 25000.0, 23.0, 870.0062500000018, 1016.0515625000048 - 0.8500000000000001, 25000.0, 23.5, 987.8007812500034, 1068.9056640625072 - 0.8500000000000001, 25000.0, 24.0, 1105.2000000000055, 1122.200000000008 - 0.8500000000000001, 25000.0, 24.5, 1222.6117187500085, 1176.000585937509 - 0.8500000000000001, 25000.0, 25.0, 1340.443750000012, 1230.3734375000097 - 0.8500000000000001, 25000.0, 25.5, 1459.1039062500165, 1285.384570312511 - 0.8500000000000001, 25000.0, 26.0, 1579.0000000000218, 1341.100000000012 - 0.8500000000000001, 25000.0, 26.5, 1704.8328124999882, 1398.5318359375005 - 0.8500000000000001, 25000.0, 27.0, 1832.9624999999849, 1456.8540624999985 - 0.8500000000000001, 25000.0, 27.5, 1963.0609374999815, 1515.9705078124964 - 0.8500000000000001, 25000.0, 28.0, 2094.799999999976, 1575.7849999999937 - 0.8500000000000001, 25000.0, 28.5, 2227.851562499972, 1636.2013671874895 - 0.8500000000000001, 25000.0, 29.0, 2361.8874999999643, 1697.123437499985 - 0.8500000000000001, 25000.0, 29.5, 2496.579687499958, 1758.4550390624797 - 0.8500000000000001, 25000.0, 30.0, 2631.599999999948, 1820.0999999999735 - 0.8500000000000001, 25000.0, 30.5, 2763.1750000000575, 1880.884667968747 - 0.8500000000000001, 25000.0, 31.0, 2894.750000000071, 1941.8929687499979 - 0.8500000000000001, 25000.0, 31.5, 3026.325000000085, 2003.1313476562495 - 0.8500000000000001, 25000.0, 32.0, 3157.9000000001006, 2064.606250000001 - 0.8500000000000001, 25000.0, 32.5, 3289.475000000118, 2126.3241210937545 - 0.8500000000000001, 25000.0, 33.0, 3421.050000000137, 2188.2914062500067 - 0.8500000000000001, 25000.0, 33.5, 3552.6250000001573, 2250.5145507812595 - 0.8500000000000001, 25000.0, 34.0, 3684.2000000001804, 2313.000000000013 - 0.8500000000000001, 25000.0, 34.5, 3815.775000000004, 2375.6840624999836 - 0.8500000000000001, 25000.0, 35.0, 3947.350000000006, 2438.64999999999 - 0.8500000000000001, 25000.0, 35.5, 4078.9250000000065, 2501.9109374999975 - 0.8500000000000001, 25000.0, 36.0, 4210.500000000008, 2565.4800000000087 - 0.8500000000000001, 25000.0, 36.5, 4342.0750000000135, 2629.3703125000206 - 0.8500000000000001, 25000.0, 37.0, 4473.650000000015, 2693.595000000036 - 0.8500000000000001, 25000.0, 37.5, 4605.22500000002, 2758.1671875000543 - 0.8500000000000001, 25000.0, 38.0, 4736.800000000026, 2823.1000000000754 - 0.8500000000000001, 25000.0, 38.5, 4868.369726562491, 2888.3970703122827 - 0.8500000000000001, 25000.0, 39.0, 4999.942187499993, 2954.0859374997344 - 0.8500000000000001, 25000.0, 39.5, 5131.518554687493, 3020.1818359371778 - 0.8500000000000001, 25000.0, 40.0, 5263.099999999988, 3086.699999999614 - 0.8500000000000001, 25000.0, 40.5, 5394.698437500129, 3153.564843750065 - 0.8500000000000001, 25000.0, 41.0, 5526.300000000184, 3220.9187500000844 - 0.8500000000000001, 25000.0, 41.5, 5657.901562500247, 3288.8132812501062 - 0.8500000000000001, 25000.0, 42.0, 5789.50000000032, 3357.30000000013 - 0.8500000000000001, 25000.0, 42.5, 5920.975000000114, 3426.7039062499853 - 0.8500000000000001, 25000.0, 43.0, 6052.487500000153, 3496.6937499999844 - 0.8500000000000001, 25000.0, 43.5, 6184.081250000195, 3567.2117187499844 - 0.8500000000000001, 25000.0, 44.0, 6315.800000000245, 3638.1999999999857 - 0.8500000000000001, 25000.0, 44.5, 6448.109375000061, 3708.87812500004 - 0.8500000000000001, 25000.0, 45.0, 6580.462500000105, 3780.2000000000417 - 0.8500000000000001, 25000.0, 45.5, 6712.734375000158, 3852.396875000039 - 0.8500000000000001, 25000.0, 46.0, 6844.800000000222, 3925.700000000032 - 0.8500000000000001, 25000.0, 46.5, 6975.913281250154, 4001.192187499971 - 0.8500000000000001, 25000.0, 47.0, 7106.818750000188, 4077.9124999999603 - 0.8500000000000001, 25000.0, 47.5, 7237.639843750223, 4155.75156249995 - 0.8500000000000001, 25000.0, 48.0, 7368.500000000258, 4234.599999999935 - 0.8500000000000001, 25000.0, 48.5, 7499.522656250297, 4314.348437499921 - 0.8500000000000001, 25000.0, 49.0, 7630.8312500003385, 4394.887499999903 - 0.8500000000000001, 25000.0, 49.5, 7762.5492187503805, 4476.107812499887 - 0.8500000000000001, 25000.0, 50.0, 7894.8000000004295, 4557.899999999869 - 0.8500000000000001, 30000.0, 0.0, 258.0236050231911, 258.0236050231911 - 0.8500000000000001, 30000.0, 22.0, 510.79999999999967, 734.5999999999984 - 0.8500000000000001, 30000.0, 22.5, 607.7013671875017, 776.2416015625006 - 0.8500000000000001, 30000.0, 23.0, 703.6140625000036, 818.1796875000035 - 0.8500000000000001, 30000.0, 23.5, 798.8697265625053, 860.4529296875074 - 0.8500000000000001, 30000.0, 24.0, 893.8000000000072, 903.1000000000128 - 0.8500000000000001, 30000.0, 24.5, 988.736523437509, 946.1595703125196 - 0.8500000000000001, 30000.0, 25.0, 1084.0109375000109, 989.670312500028 - 0.8500000000000001, 30000.0, 25.5, 1179.9548828125132, 1033.6708984375382 - 0.8500000000000001, 30000.0, 26.0, 1276.9000000000158, 1078.2000000000498 - 0.8500000000000001, 30000.0, 26.5, 1378.6669921874884, 1123.925195312499 - 0.8500000000000001, 30000.0, 27.0, 1482.2978124999854, 1170.2921874999984 - 0.8500000000000001, 30000.0, 27.5, 1587.5259765624817, 1217.2318359374972 - 0.8500000000000001, 30000.0, 28.0, 1694.084999999977, 1264.6749999999945 - 0.8500000000000001, 30000.0, 28.5, 1801.708398437473, 1312.5525390624923 - 0.8500000000000001, 30000.0, 29.0, 1910.129687499967, 1360.7953124999894 - 0.8500000000000001, 30000.0, 29.5, 2019.0823828124608, 1409.334179687486 - 0.8500000000000001, 30000.0, 30.0, 2128.299999999953, 1458.0999999999824 - 0.8500000000000001, 30000.0, 30.5, 2234.71796875002, 1506.2033203124909 - 0.8500000000000001, 30000.0, 31.0, 2341.1343750000256, 1554.4734374999891 - 0.8500000000000001, 30000.0, 31.5, 2447.5492187500313, 1602.919335937486 - 0.8500000000000001, 30000.0, 32.0, 2553.962500000037, 1651.5499999999838 - 0.8500000000000001, 30000.0, 32.5, 2660.3742187500434, 1700.37441406248 - 0.8500000000000001, 30000.0, 33.0, 2766.7843750000516, 1749.401562499976 - 0.8500000000000001, 30000.0, 33.5, 2873.1929687500588, 1798.6404296874719 - 0.8500000000000001, 30000.0, 34.0, 2979.6000000000686, 1848.0999999999665 - 0.8500000000000001, 30000.0, 34.5, 3085.9964453125144, 1897.8220703124728 - 0.8500000000000001, 30000.0, 35.0, 3192.392187500026, 1947.7796874999697 - 0.8500000000000001, 30000.0, 35.5, 3298.7880859375396, 1997.978710937465 - 0.8500000000000001, 30000.0, 36.0, 3405.1850000000572, 2048.424999999961 - 0.8500000000000001, 30000.0, 36.5, 3511.5837890625767, 2099.1244140624563 - 0.8500000000000001, 30000.0, 37.0, 3617.9853125000996, 2150.0828124999507 - 0.8500000000000001, 30000.0, 37.5, 3724.390429687625, 2201.3060546874462 - 0.8500000000000001, 30000.0, 38.0, 3830.8000000001534, 2252.7999999999397 - 0.8500000000000001, 30000.0, 38.5, 3937.2275390624873, 2304.559960937324 - 0.8500000000000001, 30000.0, 39.0, 4043.6546874999785, 2356.6078124997803 - 0.8500000000000001, 30000.0, 39.5, 4150.079492187467, 2408.951757812231 - 0.8500000000000001, 30000.0, 40.0, 4256.49999999995, 2461.5999999996766 - 0.8500000000000001, 30000.0, 40.5, 4362.901562499999, 2514.4835937499793 - 0.8500000000000001, 30000.0, 41.0, 4469.300000000008, 2567.718749999965 - 0.8500000000000001, 30000.0, 41.5, 4575.698437500017, 2621.3445312499452 - 0.8500000000000001, 30000.0, 42.0, 4682.10000000003, 2675.3999999999196 - 0.8500000000000001, 30000.0, 42.5, 4788.437500000055, 2730.0921875000276 - 0.8500000000000001, 30000.0, 43.0, 4894.812500000058, 2785.2250000000317 - 0.8500000000000001, 30000.0, 43.5, 5001.256250000057, 2840.7703125000326 - 0.8500000000000001, 30000.0, 44.0, 5107.800000000054, 2896.700000000031 - 0.8500000000000001, 30000.0, 44.5, 5214.8031250000395, 2952.599218750056 - 0.8500000000000001, 30000.0, 45.0, 5321.837500000057, 3008.981250000068 - 0.8500000000000001, 30000.0, 45.5, 5428.803125000085, 3065.9726562500796 - 0.8500000000000001, 30000.0, 46.0, 5535.600000000122, 3123.7000000000903 - 0.8500000000000001, 30000.0, 46.5, 5641.6242187500475, 3182.5085937499725 - 0.8500000000000001, 30000.0, 47.0, 5747.481250000057, 3242.2187499999686 - 0.8500000000000001, 30000.0, 47.5, 5853.272656250066, 3302.869531249967 - 0.8500000000000001, 30000.0, 48.0, 5959.100000000068, 3364.499999999965 - 0.8500000000000001, 30000.0, 48.5, 6065.06484375007, 3427.149218749966 - 0.8500000000000001, 30000.0, 49.0, 6171.268750000069, 3490.8562499999694 - 0.8500000000000001, 30000.0, 49.5, 6277.813281250063, 3555.6601562499754 - 0.8500000000000001, 30000.0, 50.0, 6384.800000000049, 3621.599999999985 - 0.8500000000000001, 35000.0, 0.0, 209.0284537211675, 209.0284537211675 - 0.8500000000000001, 35000.0, 22.0, 395.9999999999994, 604.6999999999999 - 0.8500000000000001, 35000.0, 22.5, 471.17460937499874, 636.4693359374993 - 0.8500000000000001, 35000.0, 23.0, 545.578124999998, 668.2703124999986 - 0.8500000000000001, 35000.0, 23.5, 619.4675781249972, 700.1861328124977 - 0.8500000000000001, 35000.0, 24.0, 693.099999999996, 732.2999999999968 - 0.8500000000000001, 35000.0, 24.5, 766.7324218749951, 764.6951171874955 - 0.8500000000000001, 35000.0, 25.0, 840.621874999994, 797.4546874999942 - 0.8500000000000001, 35000.0, 25.5, 915.025390624993, 830.6619140624928 - 0.8500000000000001, 35000.0, 26.0, 990.1999999999916, 864.3999999999911 - 0.8500000000000001, 35000.0, 26.5, 1069.098828124997, 899.9197265625018 - 0.8500000000000001, 35000.0, 27.0, 1149.4368749999978, 936.2034375000029 - 0.8500000000000001, 35000.0, 27.5, 1231.008984374997, 973.1341796875046 - 0.8500000000000001, 35000.0, 28.0, 1313.6099999999967, 1010.5950000000065 - 0.8500000000000001, 35000.0, 28.5, 1397.034765624997, 1048.4689453125086 - 0.8500000000000001, 35000.0, 29.0, 1481.0781249999966, 1086.639062500011 - 0.8500000000000001, 35000.0, 29.5, 1565.5349218749964, 1124.9883984375135 - 0.8500000000000001, 35000.0, 30.0, 1650.1999999999962, 1163.400000000017 - 0.8500000000000001, 35000.0, 30.5, 1732.720214843765, 1200.1843749999964 - 0.8500000000000001, 35000.0, 31.0, 1815.2429687500178, 1236.946874999996 - 0.8500000000000001, 35000.0, 31.5, 1897.7676757812708, 1273.7203124999955 - 0.8500000000000001, 35000.0, 32.0, 1980.2937500000235, 1310.5374999999951 - 0.8500000000000001, 35000.0, 32.5, 2062.8206054687776, 1347.4312499999946 - 0.8500000000000001, 35000.0, 33.0, 2145.3476562500305, 1384.4343749999946 - 0.8500000000000001, 35000.0, 33.5, 2227.874316406284, 1421.5796874999944 - 0.8500000000000001, 35000.0, 34.0, 2310.4000000000374, 1458.8999999999937 - 0.8500000000000001, 35000.0, 34.5, 2392.91878906251, 1496.8243359375035 - 0.8500000000000001, 35000.0, 35.0, 2475.435937500011, 1534.9515625000038 - 0.8500000000000001, 35000.0, 35.5, 2557.951367187514, 1573.2767578125038 - 0.8500000000000001, 35000.0, 36.0, 2640.4650000000165, 1611.7950000000037 - 0.8500000000000001, 35000.0, 36.5, 2722.9767578125193, 1650.5013671875035 - 0.8500000000000001, 35000.0, 37.0, 2805.486562500022, 1689.390937500004 - 0.8500000000000001, 35000.0, 37.5, 2887.9943359375256, 1728.458789062504 - 0.8500000000000001, 35000.0, 38.0, 2970.50000000003, 1767.7000000000053 - 0.8500000000000001, 35000.0, 38.5, 3052.9908203125415, 1806.9978515625035 - 0.8500000000000001, 35000.0, 39.0, 3135.485937500047, 1846.5171875000026 - 0.8500000000000001, 35000.0, 39.5, 3217.9880859375535, 1886.2779296875015 - 0.8500000000000001, 35000.0, 40.0, 3300.500000000059, 1926.3000000000002 - 0.8500000000000001, 35000.0, 40.5, 3383.0468749999995, 1966.4578124999925 - 0.8500000000000001, 35000.0, 41.0, 3465.6000000000017, 2006.9749999999883 - 0.8500000000000001, 35000.0, 41.5, 3548.1531250000075, 2047.9296874999843 - 0.8500000000000001, 35000.0, 42.0, 3630.7000000000135, 2089.3999999999787 - 0.8500000000000001, 35000.0, 42.5, 3713.144531250004, 2132.0460937499943 - 0.8500000000000001, 35000.0, 43.0, 3795.606250000007, 2175.131249999992 - 0.8500000000000001, 35000.0, 43.5, 3878.11484375001, 2218.5007812499875 - 0.8500000000000001, 35000.0, 44.0, 3960.7000000000153, 2261.9999999999827 - 0.8500000000000001, 35000.0, 44.5, 4043.660937500035, 2304.7164062500096 - 0.8500000000000001, 35000.0, 45.0, 4126.650000000043, 2347.5562500000115 - 0.8500000000000001, 35000.0, 45.5, 4209.589062500055, 2390.667968750014 - 0.8500000000000001, 35000.0, 46.0, 4292.400000000068, 2434.2000000000157 - 0.8500000000000001, 35000.0, 46.5, 4374.614062499999, 2478.3789062500055 - 0.8500000000000001, 35000.0, 47.0, 4456.700000000003, 2523.243750000007 - 0.8500000000000001, 35000.0, 47.5, 4538.735937500008, 2568.911718750009 - 0.8500000000000001, 35000.0, 48.0, 4620.800000000013, 2615.5000000000114 - 0.8500000000000001, 35000.0, 48.5, 4702.97031250002, 2663.125781250015 - 0.8500000000000001, 35000.0, 49.0, 4785.325000000028, 2711.9062500000186 - 0.8500000000000001, 35000.0, 49.5, 4867.942187500039, 2761.9585937500237 - 0.8500000000000001, 35000.0, 50.0, 4950.90000000005, 2813.4000000000296 - 0.8500000000000001, 39000.0, 0.0, 173.37043643505206, 173.37043643505206 - 0.8500000000000001, 39000.0, 22.0, 318.29999999999984, 518.6999999999999 - 0.8500000000000001, 39000.0, 22.5, 378.73945312499956, 543.7580078125 - 0.8500000000000001, 39000.0, 23.0, 438.54687499999903, 569.0734375000002 - 0.8500000000000001, 39000.0, 23.5, 497.93085937499853, 594.6771484375005 - 0.8500000000000001, 39000.0, 24.0, 557.099999999998, 620.6000000000008 - 0.8500000000000001, 39000.0, 24.5, 616.2628906249972, 646.872851562502 - 0.8500000000000001, 39000.0, 25.0, 675.6281249999965, 673.5265625000028 - 0.8500000000000001, 39000.0, 25.5, 735.4042968749957, 700.591992187504 - 0.8500000000000001, 39000.0, 26.0, 795.7999999999946, 728.1000000000057 - 0.8500000000000001, 39000.0, 26.5, 859.2085937500015, 756.5736328124981 - 0.8500000000000001, 39000.0, 27.0, 923.7787500000017, 785.5796874999978 - 0.8500000000000001, 39000.0, 27.5, 989.3445312500023, 815.064648437498 - 0.8500000000000001, 39000.0, 28.0, 1055.740000000003, 844.9749999999981 - 0.8500000000000001, 39000.0, 28.5, 1122.7992187500038, 875.2572265624983 - 0.8500000000000001, 39000.0, 29.0, 1190.3562500000046, 905.8578124999985 - 0.8500000000000001, 39000.0, 29.5, 1258.245156250006, 936.7232421874991 - 0.8500000000000001, 39000.0, 30.0, 1326.3000000000068, 967.7999999999997 - 0.8500000000000001, 39000.0, 30.5, 1392.612500000011, 998.6982421875052 - 0.8500000000000001, 39000.0, 31.0, 1458.925000000013, 1029.732812500006 - 0.8500000000000001, 39000.0, 31.5, 1525.2375000000156, 1060.8822265625067 - 0.8500000000000001, 39000.0, 32.0, 1591.5500000000177, 1092.125000000008 - 0.8500000000000001, 39000.0, 32.5, 1657.8625000000202, 1123.439648437509 - 0.8500000000000001, 39000.0, 33.0, 1724.1750000000231, 1154.804687500009 - 0.8500000000000001, 39000.0, 33.5, 1790.4875000000263, 1186.1986328125101 - 0.8500000000000001, 39000.0, 34.0, 1856.8000000000293, 1217.600000000011 - 0.8500000000000001, 39000.0, 34.5, 1923.1157812500076, 1248.493476562486 - 0.8500000000000001, 39000.0, 35.0, 1989.4312500000078, 1279.3984374999825 - 0.8500000000000001, 39000.0, 35.5, 2055.746093750008, 1310.3404296874783 - 0.8500000000000001, 39000.0, 36.0, 2122.0600000000077, 1341.3449999999725 - 0.8500000000000001, 39000.0, 36.5, 2188.372656250008, 1372.4376953124665 - 0.8500000000000001, 39000.0, 37.0, 2254.6837500000074, 1403.644062499961 - 0.8500000000000001, 39000.0, 37.5, 2320.992968750006, 1434.9896484374542 - 0.8500000000000001, 39000.0, 38.0, 2387.3000000000056, 1466.499999999946 - 0.8500000000000001, 39000.0, 38.5, 2453.5960937501036, 1498.2998046875523 - 0.8500000000000001, 39000.0, 39.0, 2519.8937500001252, 1530.2640625000615 - 0.8500000000000001, 39000.0, 39.5, 2586.194531250148, 1562.3962890625717 - 0.8500000000000001, 39000.0, 40.0, 2652.5000000001733, 1594.7000000000826 - 0.8500000000000001, 39000.0, 40.5, 2718.823437500025, 1627.1210937500123 - 0.8500000000000001, 39000.0, 41.0, 2785.150000000035, 1659.7437500000178 - 0.8500000000000001, 39000.0, 41.5, 2851.47656250005, 1692.5945312500262 - 0.8500000000000001, 39000.0, 42.0, 2917.8000000000675, 1725.700000000036 - 0.8500000000000001, 39000.0, 42.5, 2984.0468750000337, 1759.1804687500157 - 0.8500000000000001, 39000.0, 43.0, 3050.3125000000427, 1792.9312500000199 - 0.8500000000000001, 39000.0, 43.5, 3116.621875000053, 1826.9414062500246 - 0.8500000000000001, 39000.0, 44.0, 3183.000000000064, 1861.2000000000296 - 0.8500000000000001, 39000.0, 44.5, 3249.702343750004, 1895.4226562500244 - 0.8500000000000001, 39000.0, 45.0, 3316.431250000007, 1929.981250000031 - 0.8500000000000001, 39000.0, 45.5, 3383.1195312500085, 1964.9742187500383 - 0.8500000000000001, 39000.0, 46.0, 3449.7000000000103, 2000.500000000046 - 0.8500000000000001, 39000.0, 46.5, 3515.7773437500073, 2036.81328125001 - 0.8500000000000001, 39000.0, 47.0, 3581.7437500000106, 2073.7937500000126 - 0.8500000000000001, 39000.0, 47.5, 3647.663281250014, 2111.4773437500157 - 0.8500000000000001, 39000.0, 48.0, 3713.600000000019, 2149.900000000018 - 0.8500000000000001, 39000.0, 48.5, 3779.6179687500253, 2189.0976562500205 - 0.8500000000000001, 39000.0, 49.0, 3845.781250000033, 2229.1062500000226 - 0.8500000000000001, 39000.0, 49.5, 3912.1539062500433, 2269.9617187500244 - 0.8500000000000001, 39000.0, 50.0, 3978.8000000000543, 2311.7000000000266 - 0.8500000000000001, 43000.0, 0.0, 143.0476953040159, 143.0476953040159 - 0.8500000000000001, 43000.0, 22.0, 257.10000000000025, 453.2999999999995 - 0.8500000000000001, 43000.0, 22.5, 305.8304687500003, 474.33183593749993 - 0.8500000000000001, 43000.0, 23.0, 354.0812500000006, 495.32031249999994 - 0.8500000000000001, 43000.0, 23.5, 402.0164062500005, 516.3236328125001 - 0.8500000000000001, 43000.0, 24.0, 449.8000000000006, 537.4000000000002 - 0.8500000000000001, 43000.0, 24.5, 497.5960937500004, 558.6076171875004 - 0.8500000000000001, 43000.0, 25.0, 545.5687500000005, 580.0046875000003 - 0.8500000000000001, 43000.0, 25.5, 593.8820312500003, 601.6494140625005 - 0.8500000000000001, 43000.0, 26.0, 642.6999999999999, 623.6000000000006 - 0.8500000000000001, 43000.0, 26.5, 693.9203124999981, 646.4833984374998 - 0.8500000000000001, 43000.0, 27.0, 746.0724999999978, 669.8215625000001 - 0.8500000000000001, 43000.0, 27.5, 799.0234374999977, 693.5751953125008 - 0.8500000000000001, 43000.0, 28.0, 852.6399999999976, 717.7050000000012 - 0.8500000000000001, 43000.0, 28.5, 906.7890624999974, 742.1716796875021 - 0.8500000000000001, 43000.0, 29.0, 961.3374999999974, 766.935937500003 - 0.8500000000000001, 43000.0, 29.5, 1016.1521874999972, 791.9584765625042 - 0.8500000000000001, 43000.0, 30.0, 1071.0999999999976, 817.2000000000057 - 0.8500000000000001, 43000.0, 30.5, 1124.647949218755, 842.4916015624991 - 0.8500000000000001, 43000.0, 31.0, 1178.1960937500062, 867.9359374999985 - 0.8500000000000001, 43000.0, 31.5, 1231.7446289062568, 893.5060546874979 - 0.8500000000000001, 43000.0, 32.0, 1285.2937500000078, 919.1749999999973 - 0.8500000000000001, 43000.0, 32.5, 1338.8436523437585, 944.9158203124966 - 0.8500000000000001, 43000.0, 33.0, 1392.3945312500089, 970.7015624999959 - 0.8500000000000001, 43000.0, 33.5, 1445.9465820312596, 996.5052734374948 - 0.8500000000000001, 43000.0, 34.0, 1499.5000000000093, 1022.2999999999938 - 0.8500000000000001, 43000.0, 34.5, 1553.0627734375141, 1047.5157421874949 - 0.8500000000000001, 43000.0, 35.0, 1606.6265625000153, 1072.7203124999924 - 0.8500000000000001, 43000.0, 35.5, 1660.1908203125163, 1097.9384765624898 - 0.8500000000000001, 43000.0, 36.0, 1713.7550000000167, 1123.1949999999867 - 0.8500000000000001, 43000.0, 36.5, 1767.3185546875168, 1148.5146484374832 - 0.8500000000000001, 43000.0, 37.0, 1820.8809375000178, 1173.9221874999785 - 0.8500000000000001, 43000.0, 37.5, 1874.4416015625177, 1199.4423828124736 - 0.8500000000000001, 43000.0, 38.0, 1928.0000000000177, 1225.099999999968 - 0.8500000000000001, 43000.0, 38.5, 1981.551367187554, 1251.0242187500007 - 0.8500000000000001, 43000.0, 39.0, 2035.1015625000625, 1277.0812499999988 - 0.8500000000000001, 43000.0, 39.5, 2088.650976562572, 1303.2726562499965 - 0.8500000000000001, 43000.0, 40.0, 2142.2000000000808, 1329.5999999999945 - 0.8500000000000001, 43000.0, 40.5, 2195.7460937500105, 1356.017968750021 - 0.8500000000000001, 43000.0, 41.0, 2249.2937500000157, 1382.593750000028 - 0.8500000000000001, 43000.0, 41.5, 2302.8445312500203, 1409.3476562500337 - 0.8500000000000001, 43000.0, 42.0, 2356.400000000027, 1436.3000000000407 - 0.8500000000000001, 43000.0, 42.5, 2409.934375000014, 1463.5375000000051 - 0.8500000000000001, 43000.0, 43.0, 2463.487500000018, 1490.9875000000075 - 0.8500000000000001, 43000.0, 43.5, 2517.071875000021, 1518.64375000001 - 0.8500000000000001, 43000.0, 44.0, 2570.7000000000244, 1546.5000000000143 - 0.8500000000000001, 43000.0, 44.5, 2624.528906250024, 1574.186718750004 - 0.8500000000000001, 43000.0, 45.0, 2678.3687500000324, 1602.2062500000036 - 0.8500000000000001, 43000.0, 45.5, 2732.1742187500413, 1630.6976562500024 - 0.8500000000000001, 43000.0, 46.0, 2785.900000000051, 1659.8000000000004 - 0.8500000000000001, 43000.0, 46.5, 2839.270312500014, 1690.2109374999973 - 0.8500000000000001, 43000.0, 47.0, 2892.562500000017, 1721.2874999999967 - 0.8500000000000001, 43000.0, 47.5, 2945.823437500021, 1752.945312499997 - 0.8500000000000001, 43000.0, 48.0, 2999.1000000000267, 1785.0999999999974 - 0.8500000000000001, 43000.0, 48.5, 3052.439062500033, 1817.6671874999981 - 0.8500000000000001, 43000.0, 49.0, 3105.8875000000394, 1850.5624999999993 - 0.8500000000000001, 43000.0, 49.5, 3159.4921875000464, 1883.7015625000008 - 0.8500000000000001, 43000.0, 50.0, 3213.3000000000557, 1917.0000000000023 - 0.8500000000000001, 48000.0, 0.0, 112.48986120043169, 112.48986120043169 - 0.8500000000000001, 48000.0, 22.0, 202.49999999999997, 356.99999999999994 - 0.8500000000000001, 48000.0, 22.5, 240.85742187499997, 373.54785156249983 - 0.8500000000000001, 48000.0, 23.0, 278.8406249999999, 390.0671874999997 - 0.8500000000000001, 48000.0, 23.5, 316.5785156249997, 406.6029296874995 - 0.8500000000000001, 48000.0, 24.0, 354.19999999999953, 423.19999999999914 - 0.8500000000000001, 48000.0, 24.5, 391.83398437499915, 439.903320312499 - 0.8500000000000001, 48000.0, 25.0, 429.60937499999864, 456.75781249999864 - 0.8500000000000001, 48000.0, 25.5, 467.65507812499834, 473.80839843749845 - 0.8500000000000001, 48000.0, 26.0, 506.09999999999764, 491.09999999999843 - 0.8500000000000001, 48000.0, 26.5, 546.4374999999995, 509.11640625000007 - 0.8500000000000001, 48000.0, 27.0, 587.5099999999993, 527.48875 - 0.8500000000000001, 48000.0, 27.5, 629.2124999999993, 546.18671875 - 0.8500000000000001, 48000.0, 28.0, 671.4399999999994, 565.1799999999997 - 0.8500000000000001, 48000.0, 28.5, 714.0874999999992, 584.4382812499996 - 0.8500000000000001, 48000.0, 29.0, 757.0499999999992, 603.9312499999992 - 0.8500000000000001, 48000.0, 29.5, 800.2224999999994, 623.628593749999 - 0.8500000000000001, 48000.0, 30.0, 843.4999999999993, 643.4999999999989 - 0.8500000000000001, 48000.0, 30.5, 885.675000000003, 663.424511718752 - 0.8500000000000001, 48000.0, 31.0, 927.8500000000034, 683.4710937500024 - 0.8500000000000001, 48000.0, 31.5, 970.0250000000037, 703.6180664062525 - 0.8500000000000001, 48000.0, 32.0, 1012.2000000000038, 723.8437500000031 - 0.8500000000000001, 48000.0, 32.5, 1054.3750000000039, 744.1264648437532 - 0.8500000000000001, 48000.0, 33.0, 1096.5500000000034, 764.4445312500036 - 0.8500000000000001, 48000.0, 33.5, 1138.7250000000038, 784.7762695312533 - 0.8500000000000001, 48000.0, 34.0, 1180.9000000000042, 805.100000000004 - 0.8500000000000001, 48000.0, 34.5, 1223.0749999999923, 824.9588671874923 - 0.8500000000000001, 48000.0, 35.0, 1265.2499999999889, 844.8078124999904 - 0.8500000000000001, 48000.0, 35.5, 1307.4249999999852, 864.6666015624882 - 0.8500000000000001, 48000.0, 36.0, 1349.5999999999806, 884.5549999999857 - 0.8500000000000001, 48000.0, 36.5, 1391.7749999999762, 904.4927734374834 - 0.8500000000000001, 48000.0, 37.0, 1433.9499999999705, 924.4996874999805 - 0.8500000000000001, 48000.0, 37.5, 1476.1249999999645, 944.5955078124775 - 0.8500000000000001, 48000.0, 38.0, 1518.299999999958, 964.7999999999747 - 0.8500000000000001, 48000.0, 38.5, 1560.4750000000674, 985.2183593750203 - 0.8500000000000001, 48000.0, 39.0, 1602.6500000000806, 1005.7406250000239 - 0.8500000000000001, 48000.0, 39.5, 1644.8250000000944, 1026.3675781250276 - 0.8500000000000001, 48000.0, 40.0, 1687.00000000011, 1047.100000000032 - 0.8500000000000001, 48000.0, 40.5, 1729.1750000000184, 1067.897656250005 - 0.8500000000000001, 48000.0, 41.0, 1771.350000000025, 1088.8187500000067 - 0.8500000000000001, 48000.0, 41.5, 1813.5250000000324, 1109.8804687500092 - 0.8500000000000001, 48000.0, 42.0, 1855.7000000000412, 1131.1000000000122 - 0.8500000000000001, 48000.0, 42.5, 1897.843750000009, 1152.553125000006 - 0.8500000000000001, 48000.0, 43.0, 1940.0000000000114, 1174.1750000000097 - 0.8500000000000001, 48000.0, 43.5, 1982.1812500000128, 1195.9593750000142 - 0.8500000000000001, 48000.0, 44.0, 2024.4000000000149, 1217.9000000000192 - 0.8500000000000001, 48000.0, 44.5, 2066.7937499999844, 1239.6976562500051 - 0.8500000000000001, 48000.0, 45.0, 2109.19999999998, 1261.7562500000067 - 0.8500000000000001, 48000.0, 45.5, 2151.581249999976, 1284.1867187500084 - 0.8500000000000001, 48000.0, 46.0, 2193.8999999999687, 1307.1000000000106 - 0.8500000000000001, 48000.0, 46.5, 2235.931250000027, 1331.0562500000117 - 0.8500000000000001, 48000.0, 47.0, 2277.9000000000347, 1355.5375000000151 - 0.8500000000000001, 48000.0, 47.5, 2319.8437500000437, 1380.4750000000186 - 0.8500000000000001, 48000.0, 48.0, 2361.800000000053, 1405.8000000000222 - 0.8500000000000001, 48000.0, 48.5, 2403.8062500000624, 1431.4437500000267 - 0.8500000000000001, 48000.0, 49.0, 2445.900000000073, 1457.337500000031 - 0.8500000000000001, 48000.0, 49.5, 2488.1187500000824, 1483.4125000000352 - 0.8500000000000001, 48000.0, 50.0, 2530.5000000000923, 1509.60000000004 - 0.9, 0.0, 0.0, 810.15086163223, 810.15086163223 - 0.9, 0.0, 22.0, 2550.3000000000284, 2712.6999999998825 - 0.9, 0.0, 22.5, 3038.128320312335, 3757.108789062316 - 0.9, 0.0, 23.0, 3505.7984374993694, 4081.4296874998613 - 0.9, 0.0, 23.5, 3957.6693359361298, 3827.1357421875114 - 0.9, 0.0, 24.0, 4398.099999997621, 3135.7000000002554 - 0.9, 0.0, 24.5, 4831.449414058836, 2148.595507813084 - 0.9, 0.0, 25.0, 5262.076562494776, 1007.2953125009908 - 0.9, 0.0, 25.5, 5694.340429680441, -146.7275390610339 - 0.9, 0.0, 26.0, 6132.599999990832, -1171.9999999980064 - 0.9, 0.0, 26.5, 6623.811718750915, -628.4861328120294 - 0.9, 0.0, 27.0, 7132.171250001261, 400.92781250074177 - 0.9, 0.0, 27.5, 7654.7351562517, 1835.1041015635647 - 0.9, 0.0, 28.0, 8188.560000002228, 3592.905000001454 - 0.9, 0.0, 28.5, 8730.702343752855, 5593.192773439405 - 0.9, 0.0, 29.0, 9278.218750003576, 7754.829687502421 - 0.9, 0.0, 29.5, 9828.165781254396, 9996.678007815524 - 0.9, 0.0, 30.0, 10377.60000000532, 12237.600000003706 - 0.9, 0.0, 30.5, 10885.494140624542, 13466.186230466541 - 0.9, 0.0, 31.0, 11390.61562499979, 14620.167968747443 - 0.9, 0.0, 31.5, 11893.64804687509, 15707.004785153322 - 0.9, 0.0, 32.0, 12395.275000000442, 16734.156249996693 - 0.9, 0.0, 32.5, 12896.180078125843, 17709.08193359005 - 0.9, 0.0, 33.0, 13397.046875001297, 18639.241406245907 - 0.9, 0.0, 33.5, 13898.5589843768, 19532.094238276753 - 0.9, 0.0, 34.0, 14401.400000002359, 20395.099999995105 - 0.9, 0.0, 34.5, 14916.856874987292, 22441.320468745555 - 0.9, 0.0, 35.0, 15433.999999982794, 24357.793749995006 - 0.9, 0.0, 35.5, 15952.503124977673, 26037.16015624446 - 0.9, 0.0, 36.0, 16472.039999971923, 27372.059999993893 - 0.9, 0.0, 36.5, 16992.28437496554, 28255.133593743332 - 0.9, 0.0, 37.0, 17512.90999995852, 28579.0212499927 - 0.9, 0.0, 37.5, 18033.590624950837, 28236.363281242127 - 0.9, 0.0, 38.0, 18553.999999942505, 27119.799999991505 - 0.9, 0.0, 38.5, 19075.159765651813, 24137.349218757037 - 0.9, 0.0, 39.0, 19594.696875035876, 20676.81875000873 - 0.9, 0.0, 39.5, 20111.98554692148, 16849.653906260683 - 0.9, 0.0, 40.0, 20626.400000058693, 12767.30000001295 - 0.9, 0.0, 40.5, 21137.82421875896, 8356.112499998628 - 0.9, 0.0, 41.0, 21644.918750012388, 3986.6624999980004 - 0.9, 0.0, 41.5, 22146.853906265966, -155.56875000280888 - 0.9, 0.0, 42.0, 22642.800000019513, -3885.1000000038366 - 0.9, 0.0, 42.5, 23117.325781243388, -6712.707812503199 - 0.9, 0.0, 43.0, 23590.043749992066, -8878.150000004229 - 0.9, 0.0, 43.5, 24065.964843741313, -10317.442187505425 - 0.9, 0.0, 44.0, 24550.099999991387, -10966.600000006823 - 0.9, 0.0, 44.5, 25071.581249996438, -10138.432031248369 - 0.9, 0.0, 45.0, 25601.649999992707, -8641.443749997241 - 0.9, 0.0, 45.5, 26135.668749987348, -6660.933593745613 - 0.9, 0.0, 46.0, 26668.999999979977, -4382.199999993394 - 0.9, 0.0, 46.5, 27179.15078123501, -2294.209375009057 - 0.9, 0.0, 47.0, 27686.481249981633, -157.12500001269882 - 0.9, 0.0, 47.5, 28193.496093728307, 1965.221874983109 - 0.9, 0.0, 48.0, 28702.69999997518, 4008.9999999783895 - 0.9, 0.0, 48.5, 29216.597656222406, 5910.378124973151 - 0.9, 0.0, 49.0, 29737.693749970167, 7605.524999967403 - 0.9, 0.0, 49.5, 30268.492968718587, 9030.609374961168 - 0.9, 0.0, 50.0, 30811.499999967822, 10121.799999954452 - 0.9, 2000.0, 0.0, 758.519745677721, 758.519745677721 - 0.9, 2000.0, 22.0, -59223.59999999976, -19511.599999999977 - 0.9, 2000.0, 22.5, -70426.83750000008, -23484.954687499958 - 0.9, 2000.0, 23.0, -81517.38750000045, -27205.262499999983 - 0.9, 2000.0, 23.5, -92533.5437500009, -30740.339062500017 - 0.9, 2000.0, 24.0, -103513.60000000142, -34158.000000000095 - 0.9, 2000.0, 24.5, -114495.85000000201, -37526.060937500195 - 0.9, 2000.0, 25.0, -125518.58750000272, -40912.33750000033 - 0.9, 2000.0, 25.5, -136620.10625000356, -44384.64531250045 - 0.9, 2000.0, 26.0, -147838.70000000455, -48010.800000000614 - 0.9, 2000.0, 26.5, -159615.68886718588, -52575.63046874916 - 0.9, 2000.0, 27.0, -171609.37031249804, -57470.91124999897 - 0.9, 2000.0, 27.5, -183788.94785156017, -62641.541406248725 - 0.9, 2000.0, 28.0, -196123.62499999735, -68032.41999999848 - 0.9, 2000.0, 28.5, -208582.60527343446, -73588.44609374815 - 0.9, 2000.0, 29.0, -221135.0921874967, -79254.51874999782 - 0.9, 2000.0, 29.5, -233750.2892578088, -84975.53703124748 - 0.9, 2000.0, 30.0, -246397.39999999598, -90696.39999999705 - 0.9, 2000.0, 30.5, -258722.71806639983, -95575.30283203104 - 0.9, 2000.0, 31.0, -271049.1101562426, -100418.7726562497 - 0.9, 2000.0, 31.5, -283376.53310546017, -105246.63271484328 - 0.9, 2000.0, 32.0, -295704.9437499903, -110078.70624999938 - 0.9, 2000.0, 32.5, -308034.2989257703, -114934.81650390541 - 0.9, 2000.0, 33.0, -320364.5554687377, -119834.78671874893 - 0.9, 2000.0, 33.5, -332695.6702148299, -124798.44013671756 - 0.9, 2000.0, 34.0, -345027.59999998444, -129845.59999999858 - 0.9, 2000.0, 34.5, -357372.49601561285, -136087.85207030963 - 0.9, 2000.0, 35.0, -369716.95937498624, -142349.2796874969 - 0.9, 2000.0, 35.5, -382059.78554685955, -148545.72871093405 - 0.9, 2000.0, 36.0, -394399.7699999827, -154593.04499999626 - 0.9, 2000.0, 36.5, -406735.70820310566, -160407.07441405838 - 0.9, 2000.0, 37.0, -419066.3956249784, -165903.6628124955 - 0.9, 2000.0, 37.5, -431390.6277343511, -170998.6560546825 - 0.9, 2000.0, 38.0, -443707.1999999736, -175607.8999999945 - 0.9, 2000.0, 38.5, -455992.8744140341, -178898.90703124824 - 0.9, 2000.0, 39.0, -468279.90468746546, -181923.88124999826 - 0.9, 2000.0, 39.5, -480571.9826171461, -184764.9648437483 - 0.9, 2000.0, 40.0, -492872.79999995115, -187504.2999999986 - 0.9, 2000.0, 40.5, -505204.9773437415, -190007.325781246 - 0.9, 2000.0, 41.0, -517545.70624998934, -192659.5687499944 - 0.9, 2000.0, 41.5, -529891.1070312368, -195629.8523437423 - 0.9, 2000.0, 42.0, -542237.2999999841, -199086.9999999897 - 0.9, 2000.0, 42.5, -554561.0421874832, -203778.43281249524 - 0.9, 2000.0, 43.0, -566885.562499976, -209062.9374999939 - 0.9, 2000.0, 43.5, -579214.7265624669, -214877.89843749237 - 0.9, 2000.0, 44.0, -591552.3999999561, -221160.6999999906 - 0.9, 2000.0, 44.5, -603940.2960937271, -227900.83593749718 - 0.9, 2000.0, 45.0, -616329.2937499708, -234962.73749999618 - 0.9, 2000.0, 45.5, -628708.1195312141, -242262.94531249517 - 0.9, 2000.0, 46.0, -641065.4999999566, -249717.99999999424 - 0.9, 2000.0, 46.5, -653329.9312500113, -257033.60624999914 - 0.9, 2000.0, 47.0, -665574.4625000145, -264421.4749999983 - 0.9, 2000.0, 47.5, -677811.912500017, -271882.4812499972 - 0.9, 2000.0, 48.0, -690055.1000000197, -279417.4999999961 - 0.9, 2000.0, 48.5, -702316.8437500215, -287027.4062499947 - 0.9, 2000.0, 49.0, -714609.9625000226, -294713.0749999931 - 0.9, 2000.0, 49.5, -726947.2750000232, -302475.38124999113 - 0.9, 2000.0, 50.0, -739341.6000000224, -310315.1999999891 - 0.9, 5000.0, 0.0, 685.979251144027, 685.979251144027 - 0.9, 5000.0, 22.0, 75189.59999999986, 27653.20000000009 - 0.9, 5000.0, 22.5, 89484.63457031232, 32386.030664062495 - 0.9, 5000.0, 23.0, 103623.56093749973, 36975.54218749996 - 0.9, 5000.0, 23.5, 117656.83183593706, 41473.132617187446 - 0.9, 5000.0, 24.0, 131634.89999999932, 45930.19999999996 - 0.9, 5000.0, 24.5, 145608.21816406163, 50398.14238281252 - 0.9, 5000.0, 25.0, 159627.2390624988, 54928.357812500086 - 0.9, 5000.0, 25.5, 173742.41542968585, 59572.24433593768 - 0.9, 5000.0, 26.0, 188004.19999999792, 64381.20000000029 - 0.9, 5000.0, 26.5, 202989.30742187385, 69915.76074218695 - 0.9, 5000.0, 27.0, 218252.00062499847, 75747.28031249938 - 0.9, 5000.0, 27.5, 233752.51601562314, 81839.8759765619 - 0.9, 5000.0, 28.0, 249451.08999999778, 88157.66499999938 - 0.9, 5000.0, 28.5, 265307.9589843723, 94664.76464843692 - 0.9, 5000.0, 29.0, 281283.35937499686, 101325.2921874995 - 0.9, 5000.0, 29.5, 297337.52757812117, 108103.3648828121 - 0.9, 5000.0, 30.0, 313430.69999999565, 114963.09999999971 - 0.9, 5000.0, 30.5, 329105.92753906344, 121563.06972656272 - 0.9, 5000.0, 31.0, 344780.3640625011, 128202.03593750024 - 0.9, 5000.0, 31.5, 360453.97792968876, 134873.21542968779 - 0.9, 5000.0, 32.0, 376126.73750000127, 141569.82500000033 - 0.9, 5000.0, 32.5, 391798.61113281385, 148285.08144531288 - 0.9, 5000.0, 33.0, 407469.56718750147, 155012.2015625004 - 0.9, 5000.0, 33.5, 423139.5740234391, 161744.40214843804 - 0.9, 5000.0, 34.0, 438808.60000000166, 168474.9000000007 - 0.9, 5000.0, 34.5, 454472.7735937469, 175296.90964843615 - 0.9, 5000.0, 35.0, 470136.26874999644, 182094.12656249874 - 0.9, 5000.0, 35.5, 485799.41953124595, 188850.24394531132 - 0.9, 5000.0, 36.0, 501462.5599999954, 195548.9549999989 - 0.9, 5000.0, 36.5, 517126.0242187449, 202173.95292968658 - 0.9, 5000.0, 37.0, 532790.1462499943, 208708.93093749936 - 0.9, 5000.0, 37.5, 548455.2601562437, 215137.5822265621 - 0.9, 5000.0, 38.0, 564121.6999999929, 221443.60000000003 - 0.9, 5000.0, 38.5, 579794.0154296625, 227497.53691406266 - 0.9, 5000.0, 39.0, 595466.1390624711, 233454.89218749953 - 0.9, 5000.0, 39.5, 611137.4681640293, 239324.50136718608 - 0.9, 5000.0, 40.0, 626807.3999999621, 245115.19999999745 - 0.9, 5000.0, 40.5, 642468.3562500031, 250686.84609374555 - 0.9, 5000.0, 41.0, 658129.5000000034, 256256.84374999432 - 0.9, 5000.0, 41.5, 673793.0187500035, 261893.61953124314 - 0.9, 5000.0, 42.0, 689461.1000000031, 267665.59999999194 - 0.9, 5000.0, 42.5, 705137.3843749918, 273774.41484374745 - 0.9, 5000.0, 43.0, 720822.0249999915, 280102.0062499965 - 0.9, 5000.0, 43.5, 736516.6281249915, 286663.5195312454 - 0.9, 5000.0, 44.0, 752222.7999999914, 293474.0999999942 - 0.9, 5000.0, 44.5, 767979.7289062534, 300630.3226562515 - 0.9, 5000.0, 45.0, 783736.4062500045, 308033.3312500016 - 0.9, 5000.0, 45.5, 799479.4054687562, 315665.6992187515 - 0.9, 5000.0, 46.0, 815195.3000000083, 323510.0000000013 - 0.9, 5000.0, 46.5, 830799.0968749872, 331631.29921874986 - 0.9, 5000.0, 47.0, 846377.5624999829, 339896.68125000055 - 0.9, 5000.0, 47.5, 861945.8968749776, 348255.7226562512 - 0.9, 5000.0, 48.0, 877519.2999999714, 356658.00000000204 - 0.9, 5000.0, 48.5, 893112.9718749643, 365053.08984375314 - 0.9, 5000.0, 49.0, 908742.1124999559, 373390.5687500044 - 0.9, 5000.0, 49.5, 924421.9218749463, 381620.01328125584 - 0.9, 5000.0, 50.0, 940167.5999999352, 389691.00000000745 - 0.9, 10000.0, 0.0, 577.3496315377902, 577.3496315377902 - 0.9, 10000.0, 22.0, 539.2000000000783, 1019.9999999999868 - 0.9, 10000.0, 22.5, 627.1523437501764, 1239.293164062523 - 0.9, 10000.0, 23.0, 720.7687500002722, 1395.754687500071 - 0.9, 10000.0, 23.5, 819.4007812503703, 1498.988867187631 - 0.9, 10000.0, 24.0, 922.4000000004751, 1558.6000000002045 - 0.9, 10000.0, 24.5, 1029.1179687505905, 1584.1923828127913 - 0.9, 10000.0, 25.0, 1138.9062500007208, 1585.3703125003926 - 0.9, 10000.0, 25.5, 1251.116406250871, 1571.7380859380082 - 0.9, 10000.0, 26.0, 1365.1000000010445, 1552.90000000064 - 0.9, 10000.0, 26.5, 1476.1070312502377, 1633.127148437492 - 0.9, 10000.0, 27.0, 1587.3562500003122, 1732.7665625000097 - 0.9, 10000.0, 27.5, 1698.9023437503931, 1845.193945312532 - 0.9, 10000.0, 28.0, 1810.800000000478, 1963.785000000058 - 0.9, 10000.0, 28.5, 1923.1039062505645, 2081.915429687589 - 0.9, 10000.0, 29.0, 2035.8687500006508, 2192.960937500121 - 0.9, 10000.0, 29.5, 2149.1492187507347, 2290.297226562659 - 0.9, 10000.0, 30.0, 2263.0000000008135, 2367.3000000001985 - 0.9, 10000.0, 30.5, 2379.6885742194277, 2290.5135742191414 - 0.9, 10000.0, 31.0, 2496.8460937508735, 2192.224218750408 - 0.9, 10000.0, 31.5, 2614.316503907344, 2077.886816406675 - 0.9, 10000.0, 32.0, 2731.943750001343, 1952.9562500004376 - 0.9, 10000.0, 32.5, 2849.5717773453684, 1822.8874023441963 - 0.9, 10000.0, 33.0, 2967.0445312519223, 1693.1351562504556 - 0.9, 10000.0, 33.5, 3084.2059570335045, 1569.1543945317135 - 0.9, 10000.0, 34.0, 3200.900000002617, 1456.400000000469 - 0.9, 10000.0, 34.5, 3315.7807421884995, 1439.620312502011 - 0.9, 10000.0, 35.0, 3429.995312500807, 1437.425000002459 - 0.9, 10000.0, 35.5, 3543.500976563054, 1447.7171875029535 - 0.9, 10000.0, 36.0, 3656.2550000002398, 1468.400000003493 - 0.9, 10000.0, 36.5, 3768.214648437363, 1497.3765625040787 - 0.9, 10000.0, 37.0, 3879.3371874994227, 1532.5500000047086 - 0.9, 10000.0, 37.5, 3989.5798828114166, 1571.8234375053844 - 0.9, 10000.0, 38.0, 4098.899999998344, 1613.100000006104 - 0.9, 10000.0, 38.5, 4204.18671876036, 1696.000976563554 - 0.9, 10000.0, 39.0, 4310.056250012207, 1755.0796875011065 - 0.9, 10000.0, 39.5, 4417.147656264231, 1778.968554688669 - 0.9, 10000.0, 40.0, 4526.10000001644, 1756.3000000012453 - 0.9, 10000.0, 40.5, 4640.575781251462, 1533.1390624997682 - 0.9, 10000.0, 41.0, 4756.981250002337, 1297.7124999998387 - 0.9, 10000.0, 41.5, 4874.74609375341, 1095.6796874999768 - 0.9, 10000.0, 42.0, 4993.30000000467, 972.7000000001881 - 0.9, 10000.0, 42.5, 5111.139062504248, 1161.7531249994613 - 0.9, 10000.0, 43.0, 5229.00000000559, 1446.2499999993875 - 0.9, 10000.0, 43.5, 5346.685937507161, 1796.9218749992883 - 0.9, 10000.0, 44.0, 5464.0000000089785, 2184.499999999156 - 0.9, 10000.0, 44.5, 5579.792187499157, 2505.3132812500507 - 0.9, 10000.0, 45.0, 5695.199999999307, 2834.256250000184 - 0.9, 10000.0, 45.5, 5810.407812499614, 3171.821093750427 - 0.9, 10000.0, 46.0, 5925.600000000084, 3518.500000000802 - 0.9, 10000.0, 46.5, 6042.50781250493, 3936.3984374991014 - 0.9, 10000.0, 47.0, 6159.1500000070355, 4339.749999998951 - 0.9, 10000.0, 47.5, 6275.092187509444, 4704.401562498826 - 0.9, 10000.0, 48.0, 6389.900000012126, 5006.199999998713 - 0.9, 10000.0, 48.5, 6503.139062515048, 5220.9921874986085 - 0.9, 10000.0, 49.0, 6614.375000018181, 5324.624999998505 - 0.9, 10000.0, 49.5, 6723.173437521488, 5292.9453124983975 - 0.9, 10000.0, 50.0, 6829.100000024942, 5101.799999998282 - 0.9, 15000.0, 0.0, 482.77595841011583, 482.77595841011583 - 0.9, 15000.0, 22.0, 552.0999999999997, 1103.6000000000154 - 0.9, 15000.0, 22.5, 651.171093750005, 1186.5947265625546 - 0.9, 15000.0, 23.0, 751.6187500000133, 1264.1671875000943 - 0.9, 15000.0, 23.5, 853.4070312500248, 1336.806054687638 - 0.9, 15000.0, 24.0, 956.50000000004, 1405.0000000001867 - 0.9, 15000.0, 24.5, 1060.8617187500593, 1469.237695312743 - 0.9, 15000.0, 25.0, 1166.4562500000823, 1530.0078125003076 - 0.9, 15000.0, 25.5, 1273.2476562501092, 1587.7990234378835 - 0.9, 15000.0, 26.0, 1381.2000000001408, 1643.1000000004726 - 0.9, 15000.0, 26.5, 1490.8269531249086, 1697.1062500000571 - 0.9, 15000.0, 27.0, 1601.5743749998967, 1749.6400000000754 - 0.9, 15000.0, 27.5, 1713.3121093748823, 1801.068750000096 - 0.9, 15000.0, 28.0, 1825.9099999998655, 1851.7600000001173 - 0.9, 15000.0, 28.5, 1939.2378906248464, 1902.0812500001396 - 0.9, 15000.0, 29.0, 2053.1656249998236, 1952.4000000001606 - 0.9, 15000.0, 29.5, 2167.5630468747986, 2003.083750000181 - 0.9, 15000.0, 30.0, 2282.2999999997705, 2054.5000000001987 - 0.9, 15000.0, 30.5, 2396.154492187043, 2108.4878906248555 - 0.9, 15000.0, 31.0, 2510.192187499476, 2163.8031249998608 - 0.9, 15000.0, 31.5, 2624.3869140619045, 2220.673046874871 - 0.9, 15000.0, 32.0, 2738.7124999993302, 2279.324999999887 - 0.9, 15000.0, 32.5, 2853.142773436752, 2339.9863281249095 - 0.9, 15000.0, 33.0, 2967.651562499172, 2402.8843749999387 - 0.9, 15000.0, 33.5, 3082.212695311587, 2468.246484374976 - 0.9, 15000.0, 34.0, 3196.799999998999, 2536.3000000000193 - 0.9, 15000.0, 34.5, 3310.722031248743, 2636.2998437494316 - 0.9, 15000.0, 35.0, 3424.68124999853, 2736.68124999931 - 0.9, 15000.0, 35.5, 3538.7148437483047, 2834.907031249176 - 0.9, 15000.0, 36.0, 3652.8599999980684, 2928.4399999990255 - 0.9, 15000.0, 36.5, 3767.153906247819, 3014.7429687488607 - 0.9, 15000.0, 37.0, 3881.6337499975593, 3091.2787499986775 - 0.9, 15000.0, 37.5, 3996.336718747292, 3155.5101562484765 - 0.9, 15000.0, 38.0, 4111.299999997014, 3204.89999999826 - 0.9, 15000.0, 38.5, 4227.380273435151, 3203.164257812866 - 0.9, 15000.0, 39.0, 4343.37031249727, 3199.010937500525 - 0.9, 15000.0, 39.5, 4459.125195309328, 3197.4021484382074 - 0.9, 15000.0, 40.0, 4574.499999996321, 3203.300000000914 - 0.9, 15000.0, 40.5, 4688.60468749906, 3239.4234374998346 - 0.9, 15000.0, 41.0, 4802.33749999894, 3285.8749999998236 - 0.9, 15000.0, 41.5, 4915.851562498855, 3340.5140624998216 - 0.9, 15000.0, 42.0, 5029.299999998817, 3401.1999999998307 - 0.9, 15000.0, 42.5, 5142.820312500948, 3465.010937499887 - 0.9, 15000.0, 43.0, 5256.587500001261, 3530.899999999784 - 0.9, 15000.0, 43.5, 5370.7609375015945, 3597.0390624996535 - 0.9, 15000.0, 44.0, 5485.500000001937, 3661.5999999994965 - 0.9, 15000.0, 44.5, 5602.694531249466, 3710.1257812500335 - 0.9, 15000.0, 45.0, 5720.081249999247, 3758.4687500000678 - 0.9, 15000.0, 45.5, 5837.127343748968, 3809.8523437501235 - 0.9, 15000.0, 46.0, 5953.299999998624, 3867.5000000002046 - 0.9, 15000.0, 46.5, 6065.347656248763, 3953.5062500007184 - 0.9, 15000.0, 47.0, 6176.543749998444, 4044.6750000009592 - 0.9, 15000.0, 47.5, 6287.442968748105, 4136.6812500012475 - 0.9, 15000.0, 48.0, 6398.599999997755, 4225.200000001587 - 0.9, 15000.0, 48.5, 6510.569531247398, 4305.906250001984 - 0.9, 15000.0, 49.0, 6623.906249997048, 4374.475000002438 - 0.9, 15000.0, 49.5, 6739.164843746708, 4426.581250002955 - 0.9, 15000.0, 50.0, 6856.899999996391, 4457.900000003536 - 0.9, 20000.0, 0.0, 400.88279043101625, 400.88279043101625 - 0.9, 20000.0, 22.0, 714.6999999999975, 1180.2999999999986 - 0.9, 20000.0, 22.5, 850.6693359375004, 1249.9455078125077 - 0.9, 20000.0, 23.0, 985.1953125000027, 1317.3859375000175 - 0.9, 20000.0, 23.5, 1118.7486328125049, 1383.0333984375304 - 0.9, 20000.0, 24.0, 1251.8000000000072, 1447.300000000046 - 0.9, 20000.0, 24.5, 1384.820117187509, 1510.5978515625645 - 0.9, 20000.0, 25.0, 1518.2796875000115, 1573.3390625000868 - 0.9, 20000.0, 25.5, 1652.6494140625136, 1635.9357421876125 - 0.9, 20000.0, 26.0, 1788.4000000000158, 1698.8000000001437 - 0.9, 20000.0, 26.5, 1930.9226562499773, 1765.4501953125018 - 0.9, 20000.0, 27.0, 2076.0487499999645, 1833.3696875000037 - 0.9, 20000.0, 27.5, 2223.4054687499483, 1902.4380859375055 - 0.9, 20000.0, 28.0, 2372.6199999999285, 1972.5350000000055 - 0.9, 20000.0, 28.5, 2523.319531249906, 2043.540039062505 - 0.9, 20000.0, 29.0, 2675.131249999879, 2115.3328125000044 - 0.9, 20000.0, 29.5, 2827.6823437498483, 2187.792929687502 - 0.9, 20000.0, 30.0, 2980.5999999998135, 2260.8 - 0.9, 20000.0, 30.5, 3129.5866210937434, 2333.371484374951 - 0.9, 20000.0, 31.0, 3278.567968749992, 2406.3312499999415 - 0.9, 20000.0, 31.5, 3427.5450195312433, 2479.6410156249326 - 0.9, 20000.0, 32.0, 3576.518749999996, 2553.262499999923 - 0.9, 20000.0, 32.5, 3725.490136718747, 2627.1574218749124 - 0.9, 20000.0, 33.0, 3874.460156250002, 2701.2874999999017 - 0.9, 20000.0, 33.5, 4023.4297851562574, 2775.6144531248924 - 0.9, 20000.0, 34.0, 4172.400000000014, 2850.0999999998826 - 0.9, 20000.0, 34.5, 4321.414023437443, 2923.3580859375616 - 0.9, 20000.0, 35.0, 4470.426562499929, 2996.8265625000977 - 0.9, 20000.0, 35.5, 4619.434570312418, 3070.595507812641 - 0.9, 20000.0, 36.0, 4768.434999999908, 3144.7550000001925 - 0.9, 20000.0, 36.5, 4917.424804687395, 3219.395117187751 - 0.9, 20000.0, 37.0, 5066.400937499888, 3294.605937500318 - 0.9, 20000.0, 37.5, 5215.360351562379, 3370.4775390628943 - 0.9, 20000.0, 38.0, 5364.299999999874, 3447.1000000004783 - 0.9, 20000.0, 38.5, 5513.092382811877, 3524.7490234369398 - 0.9, 20000.0, 39.0, 5661.923437499206, 3603.2328124993 - 0.9, 20000.0, 39.5, 5810.817773436501, 3682.6001953116397 - 0.9, 20000.0, 40.0, 5959.799999998761, 3762.8999999989564 - 0.9, 20000.0, 40.5, 6109.120312499824, 3845.3460937498558 - 0.9, 20000.0, 41.0, 6258.487499999741, 3928.3562499997943 - 0.9, 20000.0, 41.5, 6407.835937499646, 4011.5132812497227 - 0.9, 20000.0, 42.0, 6557.0999999995365, 4094.3999999996386 - 0.9, 20000.0, 42.5, 6705.760937500255, 4174.454687500056 - 0.9, 20000.0, 43.0, 6854.38750000029, 4254.262500000072 - 0.9, 20000.0, 43.5, 7003.095312500308, 4334.264062500087 - 0.9, 20000.0, 44.0, 7152.000000000315, 4414.900000000104 - 0.9, 20000.0, 44.5, 7301.986718750084, 4498.985937500091 - 0.9, 20000.0, 45.0, 7452.093750000128, 4583.637500000136 - 0.9, 20000.0, 45.5, 7602.128906250187, 4668.345312500189 - 0.9, 20000.0, 46.0, 7751.900000000259, 4752.600000000254 - 0.9, 20000.0, 46.5, 7900.339843749717, 4831.876562499924 - 0.9, 20000.0, 47.0, 8048.481249999626, 4911.287499999908 - 0.9, 20000.0, 47.5, 8196.482031249529, 4991.929687499889 - 0.9, 20000.0, 48.0, 8344.49999999942, 5074.899999999871 - 0.9, 20000.0, 48.5, 8492.692968749305, 5161.295312499853 - 0.9, 20000.0, 49.0, 8641.21874999919, 5252.212499999832 - 0.9, 20000.0, 49.5, 8790.235156249073, 5348.748437499811 - 0.9, 20000.0, 50.0, 8939.899999998957, 5451.999999999793 - 0.9, 25000.0, 0.0, 330.3732690039361, 330.3732690039361 - 0.9, 25000.0, 22.0, 639.7999999999972, 999.1999999999966 - 0.9, 25000.0, 22.5, 761.0703125000003, 1045.938281250005 - 0.9, 25000.0, 23.0, 881.1750000000031, 1095.018750000011 - 0.9, 25000.0, 23.5, 1000.5171875000061, 1146.2648437500166 - 0.9, 25000.0, 24.0, 1119.5000000000089, 1199.5000000000202 - 0.9, 25000.0, 24.5, 1238.526562500013, 1254.547656250024 - 0.9, 25000.0, 25.0, 1358.000000000018, 1311.2312500000273 - 0.9, 25000.0, 25.5, 1478.3234375000238, 1369.3742187500313 - 0.9, 25000.0, 26.0, 1599.9000000000322, 1428.800000000036 - 0.9, 25000.0, 26.5, 1727.4025390624843, 1488.771484375009 - 0.9, 25000.0, 27.0, 1857.2084374999806, 1549.6406250000077 - 0.9, 25000.0, 27.5, 1988.9888671874755, 1611.326953125006 - 0.9, 25000.0, 28.0, 2122.4149999999686, 1673.750000000002 - 0.9, 25000.0, 28.5, 2257.1580078124603, 1736.8292968749975 - 0.9, 25000.0, 29.0, 2392.889062499951, 1800.484374999991 - 0.9, 25000.0, 29.5, 2529.279335937439, 1864.6347656249832 - 0.9, 25000.0, 30.0, 2665.9999999999245, 1929.1999999999732 - 0.9, 25000.0, 30.5, 2799.271582031368, 1993.4392578124973 - 0.9, 25000.0, 31.0, 2932.5445312501424, 2057.9953125000006 - 0.9, 25000.0, 31.5, 3065.818652343921, 2122.8505859375036 - 0.9, 25000.0, 32.0, 3199.0937500002033, 2187.9875000000084 - 0.9, 25000.0, 32.5, 3332.3696289064883, 2253.388476562514 - 0.9, 25000.0, 33.0, 3465.6460937502775, 2319.035937500021 - 0.9, 25000.0, 33.5, 3598.9229492190716, 2384.912304687528 - 0.9, 25000.0, 34.0, 3732.2000000003695, 2451.0000000000377 - 0.9, 25000.0, 34.5, 3865.4618750000454, 2516.496406249963 - 0.9, 25000.0, 35.0, 3998.725000000055, 2582.2437499999714 - 0.9, 25000.0, 35.5, 4131.990625000069, 2648.2992187499844 - 0.9, 25000.0, 36.0, 4265.260000000082, 2714.7200000000003 - 0.9, 25000.0, 36.5, 4398.534375000098, 2781.5632812500203 - 0.9, 25000.0, 37.0, 4531.815000000118, 2848.886250000046 - 0.9, 25000.0, 37.5, 4665.1031250001415, 2916.7460937500746 - 0.9, 25000.0, 38.0, 4798.400000000167, 2985.20000000011 - 0.9, 25000.0, 38.5, 4931.71953125001, 3054.762890624597 - 0.9, 25000.0, 39.0, 5065.0437500000135, 3124.7968749995066 - 0.9, 25000.0, 39.5, 5198.371093750007, 3195.2574218744016 - 0.9, 25000.0, 40.0, 5331.69999999999, 3266.0999999992837 - 0.9, 25000.0, 40.5, 5465.0484375002725, 3337.1375000001462 - 0.9, 25000.0, 41.0, 5598.387500000386, 3408.525000000193 - 0.9, 25000.0, 41.5, 5731.707812500517, 3480.275000000244 - 0.9, 25000.0, 42.0, 5865.000000000676, 3552.400000000299 - 0.9, 25000.0, 42.5, 5998.063281250294, 3624.9320312499835 - 0.9, 25000.0, 43.0, 6131.1562500003865, 3697.856249999988 - 0.9, 25000.0, 43.5, 6264.346093750487, 3771.177343749997 - 0.9, 25000.0, 44.0, 6397.700000000602, 3844.9000000000106 - 0.9, 25000.0, 44.5, 6531.820312500127, 3918.579687500089 - 0.9, 25000.0, 45.0, 6666.025000000213, 3992.8500000000968 - 0.9, 25000.0, 45.5, 6800.167187500326, 4067.895312500098 - 0.9, 25000.0, 46.0, 6934.100000000456, 4143.90000000009 - 0.9, 25000.0, 46.5, 7066.985156250298, 4220.888281249977 - 0.9, 25000.0, 47.0, 7199.643750000362, 4299.268749999968 - 0.9, 25000.0, 47.5, 7332.205468750429, 4379.2898437499625 - 0.9, 25000.0, 48.0, 7464.800000000496, 4461.199999999955 - 0.9, 25000.0, 48.5, 7597.55703125057, 4545.247656249948 - 0.9, 25000.0, 49.0, 7730.606250000646, 4631.68124999994 - 0.9, 25000.0, 49.5, 7864.077343750727, 4720.749218749933 - 0.9, 25000.0, 50.0, 7998.100000000815, 4812.699999999929 - 0.9, 30000.0, 0.0, 270.0414503775105, 270.0414503775105 - 0.9, 30000.0, 22.0, 519.0999999999998, 802.0999999999966 - 0.9, 30000.0, 22.5, 617.5205078125032, 845.587890625001 - 0.9, 30000.0, 23.0, 714.9359375000063, 889.3343750000066 - 0.9, 30000.0, 23.5, 811.6833984375091, 933.3886718750146 - 0.9, 30000.0, 24.0, 908.1000000000114, 977.8000000000247 - 0.9, 30000.0, 24.5, 1004.5228515625133, 1022.6175781250375 - 0.9, 30000.0, 25.0, 1101.2890625000152, 1067.8906250000532 - 0.9, 30000.0, 25.5, 1198.7357421875174, 1113.6683593750718 - 0.9, 30000.0, 26.0, 1297.2000000000194, 1160.0000000000941 - 0.9, 30000.0, 26.5, 1400.5599609374829, 1207.9396484375043 - 0.9, 30000.0, 27.0, 1505.8140624999771, 1256.589062500003 - 0.9, 30000.0, 27.5, 1612.692382812471, 1305.825195312501 - 0.9, 30000.0, 28.0, 1720.9249999999636, 1355.5249999999978 - 0.9, 30000.0, 28.5, 1830.2419921874546, 1405.5654296874936 - 0.9, 30000.0, 29.0, 1940.3734374999447, 1455.8234374999888 - 0.9, 30000.0, 29.5, 2051.0494140624323, 1506.1759765624824 - 0.9, 30000.0, 30.0, 2161.9999999999195, 1556.4999999999757 - 0.9, 30000.0, 30.5, 2270.158007812542, 1603.9654296874908 - 0.9, 30000.0, 31.0, 2378.317187500051, 1651.4140624999882 - 0.9, 30000.0, 31.5, 2486.4740234375627, 1698.9806640624843 - 0.9, 30000.0, 32.0, 2594.6250000000737, 1746.7999999999806 - 0.9, 30000.0, 32.5, 2702.7666015625873, 1795.006835937476 - 0.9, 30000.0, 33.0, 2810.895312500102, 1843.7359374999692 - 0.9, 30000.0, 33.5, 2919.0076171876185, 1893.1220703124625 - 0.9, 30000.0, 34.0, 3027.100000000135, 1943.2999999999552 - 0.9, 30000.0, 34.5, 3135.055742187502, 1997.4068359374605 - 0.9, 30000.0, 35.0, 3242.9953125000197, 2052.289062499955 - 0.9, 30000.0, 35.5, 3350.9259765625416, 2107.795507812448 - 0.9, 30000.0, 36.0, 3458.8550000000687, 2163.7749999999405 - 0.9, 30000.0, 36.5, 3566.789648437601, 2220.0763671874306 - 0.9, 30000.0, 37.0, 3674.7371875001386, 2276.5484374999214 - 0.9, 30000.0, 37.5, 3782.7048828126817, 2333.040039062411 - 0.9, 30000.0, 38.0, 3890.7000000002304, 2389.3999999998987 - 0.9, 30000.0, 38.5, 3998.799414062467, 2444.6123046871767 - 0.9, 30000.0, 39.0, 4106.904687499944, 2499.8390624995945 - 0.9, 30000.0, 39.5, 4215.007617187413, 2555.121289062001 - 0.9, 30000.0, 40.0, 4323.099999999875, 2610.4999999993966 - 0.9, 30000.0, 40.5, 4431.102343750014, 2665.923437499985 - 0.9, 30000.0, 41.0, 4539.106250000036, 2721.562499999968 - 0.9, 30000.0, 41.5, 4647.132031250064, 2777.4953124999433 - 0.9, 30000.0, 42.0, 4755.2000000001, 2833.7999999999106 - 0.9, 30000.0, 42.5, 4863.357812500117, 2890.843750000075 - 0.9, 30000.0, 43.0, 4971.587500000126, 2948.3000000000866 - 0.9, 30000.0, 43.5, 5079.898437500128, 3006.1312500000977 - 0.9, 30000.0, 44.0, 5188.3000000001275, 3064.3000000001057 - 0.9, 30000.0, 44.5, 5297.063281250063, 3122.3820312501475 - 0.9, 30000.0, 45.0, 5405.831250000099, 3180.881250000182 - 0.9, 30000.0, 45.5, 5514.508593750149, 3239.914843750218 - 0.9, 30000.0, 46.0, 5623.000000000216, 3299.600000000254 - 0.9, 30000.0, 46.5, 5730.717968750112, 3359.159374999961 - 0.9, 30000.0, 47.0, 5838.256250000138, 3419.9624999999573 - 0.9, 30000.0, 47.5, 5945.7164062501615, 3482.4843749999563 - 0.9, 30000.0, 48.0, 6053.200000000181, 3547.1999999999584 - 0.9, 30000.0, 48.5, 6160.808593750195, 3614.584374999964 - 0.9, 30000.0, 49.0, 6268.643750000207, 3685.1124999999756 - 0.9, 30000.0, 49.5, 6376.80703125021, 3759.2593749999905 - 0.9, 30000.0, 50.0, 6485.400000000203, 3837.5000000000114 - 0.9, 35000.0, 0.0, 218.7642747180399, 218.7642747180399 - 0.9, 35000.0, 22.0, 402.89999999999856, 669.1999999999999 - 0.9, 35000.0, 22.5, 479.36601562499686, 701.5150390624987 - 0.9, 35000.0, 23.0, 555.0468749999949, 734.6296874999972 - 0.9, 35000.0, 23.5, 630.2042968749928, 768.4794921874956 - 0.9, 35000.0, 24.0, 705.09999999999, 802.9999999999934 - 0.9, 35000.0, 24.5, 779.9957031249874, 838.1267578124912 - 0.9, 35000.0, 25.0, 855.1531249999844, 873.7953124999887 - 0.9, 35000.0, 25.5, 930.8339843749811, 909.9412109374861 - 0.9, 35000.0, 26.0, 1007.2999999999772, 946.4999999999832 - 0.9, 35000.0, 26.5, 1087.5582031249924, 983.1255859375021 - 0.9, 35000.0, 27.0, 1169.281874999991, 1020.0190625000047 - 0.9, 35000.0, 27.5, 1252.2621093749894, 1057.1642578125075 - 0.9, 35000.0, 28.0, 1336.2899999999886, 1094.545000000011 - 0.9, 35000.0, 28.5, 1421.156640624987, 1132.145117187515 - 0.9, 35000.0, 29.0, 1506.6531249999848, 1169.9484375000195 - 0.9, 35000.0, 29.5, 1592.5705468749834, 1207.9387890625248 - 0.9, 35000.0, 30.0, 1678.699999999981, 1246.1000000000313 - 0.9, 35000.0, 30.5, 1762.6472656250223, 1284.1066406249913 - 0.9, 35000.0, 31.0, 1846.5968750000259, 1322.2812499999902 - 0.9, 35000.0, 31.5, 1930.5480468750297, 1360.637109374989 - 0.9, 35000.0, 32.0, 2014.500000000034, 1399.187499999988 - 0.9, 35000.0, 32.5, 2098.451953125039, 1437.9457031249858 - 0.9, 35000.0, 33.0, 2182.4031250000435, 1476.9249999999852 - 0.9, 35000.0, 33.5, 2266.352734375048, 1516.1386718749845 - 0.9, 35000.0, 34.0, 2350.3000000000543, 1555.5999999999835 - 0.9, 35000.0, 34.5, 2434.217890625001, 1595.7086328125122 - 0.9, 35000.0, 35.0, 2518.1343750000005, 1636.0546875000132 - 0.9, 35000.0, 35.5, 2602.0511718750013, 1676.614648437513 - 0.9, 35000.0, 36.0, 2685.9700000000003, 1717.365000000014 - 0.9, 35000.0, 36.5, 2769.8925781250005, 1758.2822265625148 - 0.9, 35000.0, 37.0, 2853.8206250000007, 1799.3428125000162 - 0.9, 35000.0, 37.5, 2937.7558593750036, 1840.5232421875187 - 0.9, 35000.0, 38.0, 3021.7000000000035, 1881.8000000000206 - 0.9, 35000.0, 38.5, 3105.6800781250276, 1922.878515624971 - 0.9, 35000.0, 39.0, 3189.6593750000284, 1964.1468749999635 - 0.9, 35000.0, 39.5, 3273.6339843750293, 2005.6417968749547 - 0.9, 35000.0, 40.0, 3357.6000000000313, 2047.3999999999446 - 0.9, 35000.0, 40.5, 3441.532031249982, 2089.52656249998 - 0.9, 35000.0, 41.0, 3525.4562499999815, 2131.9624999999714 - 0.9, 35000.0, 41.5, 3609.3773437499826, 2174.717187499962 - 0.9, 35000.0, 42.0, 3693.299999999986, 2217.7999999999497 - 0.9, 35000.0, 42.5, 3777.1820312500035, 2261.282812499979 - 0.9, 35000.0, 43.0, 3861.0937500000064, 2305.0874999999687 - 0.9, 35000.0, 43.5, 3945.0585937500105, 2349.1984374999583 - 0.9, 35000.0, 44.0, 4029.1000000000167, 2393.599999999945 - 0.9, 35000.0, 44.5, 4113.491406250078, 2438.0460937500143 - 0.9, 35000.0, 45.0, 4197.906250000102, 2482.843750000017 - 0.9, 35000.0, 45.5, 4282.267968750132, 2528.06953125002 - 0.9, 35000.0, 46.0, 4366.500000000165, 2573.8000000000234 - 0.9, 35000.0, 46.5, 4450.142968749979, 2619.943750000012 - 0.9, 35000.0, 47.0, 4533.656249999983, 2666.8125000000155 - 0.9, 35000.0, 47.5, 4617.116406249989, 2714.55000000002 - 0.9, 35000.0, 48.0, 4700.5999999999985, 2763.3000000000275 - 0.9, 35000.0, 48.5, 4784.183593750013, 2813.206250000035 - 0.9, 35000.0, 49.0, 4867.943750000031, 2864.4125000000454 - 0.9, 35000.0, 49.5, 4951.957031250057, 2917.0625000000564 - 0.9, 35000.0, 50.0, 5036.300000000085, 2971.3000000000707 - 0.9, 39000.0, 0.0, 181.44543055777993, 181.44543055777993 - 0.9, 39000.0, 22.0, 324.0999999999995, 572.5999999999996 - 0.9, 39000.0, 22.5, 385.5748046874989, 597.2865234374989 - 0.9, 39000.0, 23.0, 446.4265624999982, 623.232812499999 - 0.9, 39000.0, 23.5, 506.86503906249743, 650.3126953124993 - 0.9, 39000.0, 24.0, 567.0999999999966, 678.4000000000001 - 0.9, 39000.0, 24.5, 627.3412109374958, 707.3685546875014 - 0.9, 39000.0, 25.0, 687.7984374999947, 737.092187500003 - 0.9, 39000.0, 25.5, 748.6814453124936, 767.4447265625053 - 0.9, 39000.0, 26.0, 810.1999999999927, 798.3000000000078 - 0.9, 39000.0, 26.5, 874.774609375003, 828.9863281249951 - 0.9, 39000.0, 27.0, 940.530625000004, 859.8918749999948 - 0.9, 39000.0, 27.5, 1007.298828125005, 890.9839843749947 - 0.9, 39000.0, 28.0, 1074.9100000000064, 922.2299999999947 - 0.9, 39000.0, 28.5, 1143.1949218750085, 953.597265624995 - 0.9, 39000.0, 29.0, 1211.98437500001, 985.0531249999956 - 0.9, 39000.0, 29.5, 1281.109140625012, 1016.564921874996 - 0.9, 39000.0, 30.0, 1350.400000000014, 1048.099999999997 - 0.9, 39000.0, 30.5, 1417.902734375022, 1079.0223632812608 - 0.9, 39000.0, 31.0, 1485.4031250000262, 1109.9601562500125 - 0.9, 39000.0, 31.5, 1552.9019531250308, 1140.9381835937645 - 0.9, 39000.0, 32.0, 1620.4000000000353, 1171.9812500000166 - 0.9, 39000.0, 32.5, 1687.89804687504, 1203.1141601562688 - 0.9, 39000.0, 33.0, 1755.3968750000458, 1234.3617187500201 - 0.9, 39000.0, 33.5, 1822.897265625052, 1265.7487304687722 - 0.9, 39000.0, 34.0, 1890.4000000000578, 1297.3000000000243 - 0.9, 39000.0, 34.5, 1957.918984375, 1329.4377734374661 - 0.9, 39000.0, 35.0, 2025.440624999999, 1361.7515624999576 - 0.9, 39000.0, 35.5, 2092.9644531249965, 1394.2283203124473 - 0.9, 39000.0, 36.0, 2160.489999999994, 1426.854999999936 - 0.9, 39000.0, 36.5, 2228.016796874991, 1459.6185546874235 - 0.9, 39000.0, 37.0, 2295.5443749999877, 1492.5059374999098 - 0.9, 39000.0, 37.5, 2363.072265624983, 1525.5041015623942 - 0.9, 39000.0, 38.0, 2430.5999999999785, 1558.5999999998776 - 0.9, 39000.0, 38.5, 2498.130273437669, 1591.375585937589 - 0.9, 39000.0, 39.0, 2565.6578125002025, 1624.4328125001043 - 0.9, 39000.0, 39.5, 2633.1814453127395, 1657.848632812621 - 0.9, 39000.0, 40.0, 2700.7000000002795, 1691.7000000001394 - 0.9, 39000.0, 40.5, 2768.197656250035, 1726.5648437500286 - 0.9, 39000.0, 41.0, 2835.6937500000527, 1761.8187500000429 - 0.9, 39000.0, 41.5, 2903.192968750075, 1797.3382812500615 - 0.9, 39000.0, 42.0, 2970.7000000001053, 1833.0000000000848 - 0.9, 39000.0, 42.5, 3038.1960937500507, 1868.2625000000246 - 0.9, 39000.0, 43.0, 3105.7187500000623, 1903.5875000000308 - 0.9, 39000.0, 43.5, 3173.2820312500758, 1939.0187500000386 - 0.9, 39000.0, 44.0, 3240.900000000091, 1974.6000000000465 - 0.9, 39000.0, 44.5, 3308.7624999999834, 2010.2929687500487 - 0.9, 39000.0, 45.0, 3376.6374999999803, 2046.256250000063 - 0.9, 39000.0, 45.5, 3444.468749999975, 2082.5664062500778 - 0.9, 39000.0, 46.0, 3512.1999999999675, 2119.300000000094 - 0.9, 39000.0, 46.5, 3579.4898437500046, 2156.3695312500104 - 0.9, 39000.0, 47.0, 3646.681250000006, 2194.081250000014 - 0.9, 39000.0, 47.5, 3713.832031250008, 2232.577343750016 - 0.9, 39000.0, 48.0, 3781.0000000000105, 2272.0000000000196 - 0.9, 39000.0, 48.5, 3848.2429687500144, 2312.491406250021 - 0.9, 39000.0, 49.0, 3915.6187500000215, 2354.1937500000217 - 0.9, 39000.0, 49.5, 3983.1851562500306, 2397.24921875002 - 0.9, 39000.0, 50.0, 4051.0000000000427, 2441.8000000000184 - 0.9, 43000.0, 0.0, 149.71036122677498, 149.71036122677498 - 0.9, 43000.0, 22.0, 261.9000000000003, 498.2999999999985 - 0.9, 43000.0, 22.5, 311.59746093750044, 518.0042968749992 - 0.9, 43000.0, 23.0, 360.7828125000003, 538.8906249999997 - 0.9, 43000.0, 23.5, 409.62675781250005, 560.8316406249999 - 0.9, 43000.0, 24.0, 458.2999999999995, 583.6999999999998 - 0.9, 43000.0, 24.5, 506.9732421874987, 607.3683593750003 - 0.9, 43000.0, 25.0, 555.8171874999978, 631.7093750000004 - 0.9, 43000.0, 25.5, 605.0025390624965, 656.5957031250007 - 0.9, 43000.0, 26.0, 654.699999999995, 681.9000000000015 - 0.9, 43000.0, 26.5, 706.8726562499969, 706.8414062499982 - 0.9, 43000.0, 27.0, 760.0012499999964, 731.9087499999986 - 0.9, 43000.0, 27.5, 813.9492187499961, 757.0867187499994 - 0.9, 43000.0, 28.0, 868.5799999999962, 782.3600000000002 - 0.9, 43000.0, 28.5, 923.7570312499961, 807.7132812500016 - 0.9, 43000.0, 29.0, 979.3437499999961, 833.131250000003 - 0.9, 43000.0, 29.5, 1035.203593749996, 858.598593750005 - 0.9, 43000.0, 30.0, 1091.1999999999962, 884.100000000007 - 0.9, 43000.0, 30.5, 1145.7645507812647, 909.2686523437465 - 0.9, 43000.0, 31.0, 1200.3289062500166, 934.4742187499953 - 0.9, 43000.0, 31.5, 1254.892871093769, 959.7348632812436 - 0.9, 43000.0, 32.0, 1309.4562500000213, 985.0687499999922 - 0.9, 43000.0, 32.5, 1364.0188476562732, 1010.4940429687404 - 0.9, 43000.0, 33.0, 1418.5804687500245, 1036.028906249988 - 0.9, 43000.0, 33.5, 1473.1409179687764, 1061.691503906236 - 0.9, 43000.0, 34.0, 1527.700000000028, 1087.4999999999836 - 0.9, 43000.0, 34.5, 1582.2464453125283, 1113.8133984374915 - 0.9, 43000.0, 35.0, 1636.7921875000309, 1140.2765624999874 - 0.9, 43000.0, 35.5, 1691.3380859375327, 1166.8751953124815 - 0.9, 43000.0, 36.0, 1745.885000000034, 1193.5949999999752 - 0.9, 43000.0, 36.5, 1800.4337890625347, 1220.4216796874666 - 0.9, 43000.0, 37.0, 1854.985312500036, 1247.3409374999583 - 0.9, 43000.0, 37.5, 1909.5404296875363, 1274.338476562447 - 0.9, 43000.0, 38.0, 1964.1000000000358, 1301.3999999999355 - 0.9, 43000.0, 38.5, 2018.6775390625942, 1328.1832031249805 - 0.9, 43000.0, 39.0, 2073.2546875001094, 1355.1718749999739 - 0.9, 43000.0, 39.5, 2127.829492187626, 1382.4246093749657 - 0.9, 43000.0, 40.0, 2182.4000000001424, 1409.999999999957 - 0.9, 43000.0, 40.5, 2236.9515625000195, 1438.286718750047 - 0.9, 43000.0, 41.0, 2291.5000000000264, 1466.8812500000608 - 0.9, 43000.0, 41.5, 2346.0484375000356, 1495.7101562500761 - 0.9, 43000.0, 42.0, 2400.600000000047, 1524.7000000000914 - 0.9, 43000.0, 42.5, 2455.1265625000246, 1553.5781250000018 - 0.9, 43000.0, 43.0, 2509.675000000033, 1582.550000000004 - 0.9, 43000.0, 43.5, 2564.2609375000384, 1611.6218750000073 - 0.9, 43000.0, 44.0, 2618.900000000044, 1640.8000000000125 - 0.9, 43000.0, 44.5, 2673.779687500065, 1669.735156250005 - 0.9, 43000.0, 45.0, 2728.6750000000848, 1698.931250000003 - 0.9, 43000.0, 45.5, 2783.532812500108, 1728.536718749999 - 0.9, 43000.0, 46.0, 2838.300000000133, 1758.6999999999935 - 0.9, 43000.0, 46.5, 2892.6578125000306, 1790.1007812499886 - 0.9, 43000.0, 47.0, 2946.9250000000407, 1822.1437499999865 - 0.9, 43000.0, 47.5, 3001.154687500052, 1854.7648437499854 - 0.9, 43000.0, 48.0, 3055.400000000066, 1887.8999999999846 - 0.9, 43000.0, 48.5, 3109.714062500083, 1921.4851562499832 - 0.9, 43000.0, 49.0, 3164.150000000101, 1955.4562499999824 - 0.9, 43000.0, 49.5, 3218.7609375001207, 1989.749218749983 - 0.9, 43000.0, 50.0, 3273.600000000144, 2024.2999999999838 - 0.9, 48000.0, 0.0, 117.72924910726343, 117.72924910726343 - 0.9, 48000.0, 22.0, 206.19999999999985, 392.39999999999975 - 0.9, 48000.0, 22.5, 245.3439453125, 407.9402343749997 - 0.9, 48000.0, 23.0, 284.08593749999983, 424.40312499999953 - 0.9, 48000.0, 23.5, 322.5599609374997, 441.6894531249993 - 0.9, 48000.0, 24.0, 360.8999999999991, 459.6999999999992 - 0.9, 48000.0, 24.5, 399.24003906249857, 478.33554687499907 - 0.9, 48000.0, 25.0, 437.7140624999978, 497.4968749999991 - 0.9, 48000.0, 25.5, 476.4560546874969, 517.084765624999 - 0.9, 48000.0, 26.0, 515.5999999999956, 536.9999999999994 - 0.9, 48000.0, 26.5, 556.6853515624989, 556.6347656249994 - 0.9, 48000.0, 27.0, 598.520937499999, 576.3693749999993 - 0.9, 48000.0, 27.5, 640.9998046874988, 596.1917968749984 - 0.9, 48000.0, 28.0, 684.0149999999987, 616.0899999999982 - 0.9, 48000.0, 28.5, 727.4595703124988, 636.0519531249979 - 0.9, 48000.0, 29.0, 771.2265624999989, 656.0656249999975 - 0.9, 48000.0, 29.5, 815.2090234374991, 676.1189843749969 - 0.9, 48000.0, 30.0, 859.2999999999993, 696.1999999999966 - 0.9, 48000.0, 30.5, 902.2756835937563, 716.0206054687526 - 0.9, 48000.0, 31.0, 945.2523437500064, 735.8710937500033 - 0.9, 48000.0, 31.5, 988.2293945312565, 755.7657226562537 - 0.9, 48000.0, 32.0, 1031.2062500000065, 775.7187500000042 - 0.9, 48000.0, 32.5, 1074.1823242187565, 795.7444335937548 - 0.9, 48000.0, 33.0, 1117.1570312500064, 815.8570312500051 - 0.9, 48000.0, 33.5, 1160.129785156256, 836.0708007812555 - 0.9, 48000.0, 34.0, 1203.1000000000056, 856.4000000000061 - 0.9, 48000.0, 34.5, 1246.0494531249813, 877.130820312484 - 0.9, 48000.0, 35.0, 1288.9968749999748, 897.9796874999801 - 0.9, 48000.0, 35.5, 1331.9433593749675, 918.9349609374751 - 0.9, 48000.0, 36.0, 1374.8899999999592, 939.9849999999697 - 0.9, 48000.0, 36.5, 1417.8378906249504, 961.1181640624638 - 0.9, 48000.0, 37.0, 1460.78812499994, 982.322812499958 - 0.9, 48000.0, 37.5, 1503.7417968749287, 1003.5873046874509 - 0.9, 48000.0, 38.0, 1546.6999999999168, 1024.899999999944 - 0.9, 48000.0, 38.5, 1589.6722656251402, 1045.9876953125515 - 0.9, 48000.0, 39.0, 1632.646875000167, 1067.2359375000615 - 0.9, 48000.0, 39.5, 1675.6230468751965, 1088.6912109375724 - 0.9, 48000.0, 40.0, 1718.6000000002289, 1110.4000000000851 - 0.9, 48000.0, 40.5, 1761.5750000000312, 1132.6695312500074 - 0.9, 48000.0, 41.0, 1804.550000000042, 1155.1812500000115 - 0.9, 48000.0, 41.5, 1847.5250000000544, 1177.8773437500165 - 0.9, 48000.0, 42.0, 1890.5000000000693, 1200.7000000000226 - 0.9, 48000.0, 42.5, 1933.4398437500122, 1223.4312500000126 - 0.9, 48000.0, 43.0, 1976.393750000015, 1246.2375000000197 - 0.9, 48000.0, 43.5, 2019.3757812500164, 1269.125000000028 - 0.9, 48000.0, 44.0, 2062.4000000000165, 1292.1000000000383 - 0.9, 48000.0, 44.5, 2105.624999999964, 1314.899218750009 - 0.9, 48000.0, 45.0, 2148.8624999999543, 1337.9062500000114 - 0.9, 48000.0, 45.5, 2192.0687499999417, 1361.2351562500144 - 0.9, 48000.0, 46.0, 2235.1999999999275, 1385.0000000000184 - 0.9, 48000.0, 46.5, 2277.9898437500565, 1409.721093750027 - 0.9, 48000.0, 47.0, 2320.7062500000743, 1434.9437500000358 - 0.9, 48000.0, 47.5, 2363.3945312500946, 1460.6195312500447 - 0.9, 48000.0, 48.0, 2406.100000000117, 1486.7000000000555 - 0.9, 48000.0, 48.5, 2448.867968750141, 1513.136718750067 - 0.9, 48000.0, 49.0, 2491.7437500001647, 1539.8812500000788 - 0.9, 48000.0, 49.5, 2534.772656250191, 1566.8851562500918 - 0.9, 48000.0, 50.0, 2578.0000000002183, 1594.1000000001059 diff --git a/aviary/models/engines/turbofan_28k.csv b/aviary/models/engines/turbofan_28k.csv new file mode 100644 index 0000000000..7a712695fc --- /dev/null +++ b/aviary/models/engines/turbofan_28k.csv @@ -0,0 +1,1115 @@ +# created 04/22/25 +# FLOPS-derived engine deck converted from turbofan_28_ENGDEK + +Mach Number (input), Altitude (ft, input), Throttle (input), Gross Thrust (lbf, output), Ram Drag (lbf, output), Fuel Flow (lb/h, output), NOx Rate (lb/h, output) + 0.0, 0.0, 21.0, 1446.4, 0.0, 842.2, 4.7876 + 0.0, 0.0, 22.0, 2314.3, 0.0, 976.0, 5.1926 + 0.0, 0.0, 24.0, 4049.9, 0.0, 1281.0, 6.6532 + 0.0, 0.0, 26.0, 5785.6, 0.0, 1659.9, 8.2234 + 0.0, 0.0, 30.0, 9642.7, 0.0, 2621.6, 12.095 + 0.0, 0.0, 34.0, 13499.8, 0.0, 3673.3, 15.032 + 0.0, 0.0, 38.0, 17356.9, 0.0, 4795.2, 17.588 + 0.0, 0.0, 42.0, 21214.0, 0.0, 5979.1, 19.855 + 0.0, 0.0, 46.0, 25071.1, 0.0, 7258.1, 33.398 + 0.0, 0.0, 48.0, 26999.7, 0.0, 7932.6, 49.218 + 0.0, 0.0, 50.0, 28928.1, 0.0, 8662.3, 61.989 + 0.0, 2000.0, 21.0, 1446.4, 0.0, 781.8, 5.2521 + 0.0, 2000.0, 22.0, 2314.2, 0.0, 914.2, 5.1431 + 0.0, 2000.0, 24.0, 4049.9, 0.0, 1220.2, 6.7284 + 0.0, 2000.0, 26.0, 5785.6, 0.0, 1608.2, 8.4472 + 0.0, 2000.0, 30.0, 9642.7, 0.0, 2572.5, 12.52 + 0.0, 2000.0, 34.0, 13499.7, 0.0, 3624.6, 15.601 + 0.0, 2000.0, 38.0, 17356.8, 0.0, 4748.2, 18.241 + 0.0, 2000.0, 42.0, 21213.8, 0.0, 5953.1, 20.617 + 0.0, 2000.0, 46.0, 25070.8, 0.0, 7274.3, 46.519 + 0.0, 2000.0, 48.0, 26999.7, 0.0, 8005.4, 61.6 + 0.0, 2000.0, 50.0, 28928.0, 0.0, 8769.0, 72.51 + 0.0, 5000.0, 21.0, 1338.1, 0.0, 706.8, 6.8008 + 0.0, 5000.0, 22.0, 2140.9, 0.0, 828.3, 5.03 + 0.0, 5000.0, 24.0, 3746.7, 0.0, 1111.0, 6.2319 + 0.0, 5000.0, 26.0, 5352.3, 0.0, 1469.9, 7.9885 + 0.0, 5000.0, 30.0, 8920.6, 0.0, 2355.4, 12.028 + 0.0, 5000.0, 34.0, 12488.9, 0.0, 3323.4, 15.131 + 0.0, 5000.0, 38.0, 16057.1, 0.0, 4353.1, 17.774 + 0.0, 5000.0, 42.0, 19625.3, 0.0, 5473.5, 20.181 + 0.0, 5000.0, 46.0, 23193.5, 0.0, 6708.4, 39.131 + 0.0, 5000.0, 48.0, 24977.9, 0.0, 7391.9, 57.314 + 0.0, 5000.0, 50.0, 26761.8, 0.0, 8104.6, 69.258 + 0.1, 0.0, 21.0, 2503.9, 1057.5, 905.8, 4.7726 + 0.1, 0.0, 22.0, 3575.1, 1260.9, 1088.1, 5.7209 + 0.1, 0.0, 24.0, 5626.3, 1576.4, 1525.4, 7.6905 + 0.1, 0.0, 26.0, 7615.0, 1829.5, 2001.1, 9.4545 + 0.1, 0.0, 30.0, 11922.9, 2280.3, 3129.8, 13.596 + 0.1, 0.0, 34.0, 16145.2, 2645.4, 4326.3, 16.588 + 0.1, 0.0, 38.0, 20316.5, 2959.7, 5587.6, 19.158 + 0.1, 0.0, 42.0, 24452.2, 3238.4, 6932.0, 26.87 + 0.1, 0.0, 46.0, 28560.1, 3489.2, 8389.7, 57.658 + 0.1, 0.0, 48.0, 30603.9, 3604.5, 9194.3, 69.248 + 0.1, 0.0, 50.0, 32642.3, 3714.3, 10032.8, 77.44 + 0.1, 2000.0, 21.0, 2330.3, 984.5, 824.4, 4.924 + 0.1, 2000.0, 22.0, 3327.1, 1173.8, 991.2, 5.5336 + 0.1, 2000.0, 24.0, 5235.7, 1467.4, 1391.5, 7.5234 + 0.1, 2000.0, 26.0, 7086.3, 1702.9, 1826.8, 9.2983 + 0.1, 2000.0, 30.0, 11094.9, 2122.6, 2859.5, 13.428 + 0.1, 2000.0, 34.0, 15023.5, 2462.3, 3960.7, 16.447 + 0.1, 2000.0, 38.0, 18904.9, 2754.8, 5117.1, 19.021 + 0.1, 2000.0, 42.0, 22752.9, 3013.8, 6361.1, 24.784 + 0.1, 2000.0, 46.0, 26574.2, 3246.4, 7721.3, 56.641 + 0.1, 2000.0, 48.0, 28476.4, 3353.7, 8462.9, 68.509 + 0.1, 2000.0, 50.0, 30372.6, 3455.8, 9235.9, 77.04 + 0.1, 5000.0, 21.0, 2084.6, 880.6, 738.0, 6.5816 + 0.1, 5000.0, 22.0, 2976.4, 1050.0, 884.8, 4.9156 + 0.1, 5000.0, 24.0, 4684.1, 1312.8, 1237.6, 6.8861 + 0.1, 5000.0, 26.0, 6339.8, 1523.6, 1621.7, 8.6447 + 0.1, 5000.0, 30.0, 9926.1, 1899.3, 2532.7, 12.65 + 0.1, 5000.0, 34.0, 13440.9, 2203.3, 3503.2, 15.631 + 0.1, 5000.0, 38.0, 16913.5, 2465.1, 4524.4, 18.179 + 0.1, 5000.0, 42.0, 20356.6, 2696.9, 5621.1, 20.48 + 0.1, 5000.0, 46.0, 23775.6, 2905.2, 6820.1, 42.076 + 0.1, 5000.0, 48.0, 25476.8, 3001.2, 7474.2, 58.535 + 0.1, 5000.0, 50.0, 27173.2, 3092.6, 8156.2, 69.812 + 0.1, 10000.0, 21.0, 1721.9, 727.2, 612.6, 9.402 + 0.1, 10000.0, 22.0, 2458.8, 867.2, 730.7, 7.2271 + 0.1, 10000.0, 24.0, 3869.8, 1084.5, 1014.8, 5.7309 + 0.1, 10000.0, 26.0, 5237.7, 1258.8, 1324.4, 7.4445 + 0.1, 10000.0, 30.0, 8200.9, 1569.4, 2059.1, 10.942 + 0.1, 10000.0, 34.0, 11104.9, 1820.8, 2841.8, 14.099 + 0.1, 10000.0, 38.0, 13974.0, 2037.3, 3665.3, 16.569 + 0.1, 10000.0, 42.0, 16818.6, 2229.1, 4548.6, 18.8 + 0.1, 10000.0, 46.0, 19643.6, 2401.3, 5515.6, 21.945 + 0.1, 10000.0, 48.0, 21049.0, 2480.6, 6042.3, 33.273 + 0.1, 10000.0, 50.0, 22450.7, 2556.3, 6592.6, 50.98 + 0.2, 0.0, 21.0, 3984.0, 2660.5, 927.8, 4.88 + 0.2, 0.0, 22.0, 5132.8, 3015.2, 1158.3, 6.0773 + 0.2, 0.0, 24.0, 7290.5, 3584.8, 1655.7, 8.2264 + 0.2, 0.0, 26.0, 9344.4, 4050.6, 2168.2, 10.048 + 0.2, 0.0, 30.0, 13714.4, 4891.5, 3335.6, 14.183 + 0.2, 0.0, 34.0, 17928.1, 5575.9, 4564.4, 17.136 + 0.2, 0.0, 38.0, 22048.5, 6167.1, 5839.6, 19.652 + 0.2, 0.0, 42.0, 26104.0, 6693.4, 7176.2, 31.254 + 0.2, 0.0, 46.0, 30105.5, 7165.7, 8625.1, 60.801 + 0.2, 0.0, 48.0, 32088.4, 7383.6, 9408.5, 71.454 + 0.2, 0.0, 50.0, 34059.1, 7590.1, 10231.7, 78.754 + 0.2, 2000.0, 21.0, 3705.8, 2475.9, 844.5, 4.8026 + 0.2, 2000.0, 22.0, 4773.5, 2805.8, 1055.1, 5.8928 + 0.2, 2000.0, 24.0, 6779.2, 3335.6, 1509.9, 8.0591 + 0.2, 2000.0, 26.0, 8688.2, 3768.8, 1978.1, 9.8731 + 0.2, 2000.0, 30.0, 12750.0, 4551.0, 3045.6, 14.013 + 0.2, 2000.0, 34.0, 16665.9, 5187.3, 4175.2, 16.989 + 0.2, 2000.0, 38.0, 20495.5, 5737.3, 5341.9, 19.504 + 0.2, 2000.0, 42.0, 24264.1, 6226.1, 6575.1, 28.173 + 0.2, 2000.0, 46.0, 27981.8, 6663.9, 7924.2, 59.521 + 0.2, 2000.0, 48.0, 29823.9, 6866.3, 8646.0, 70.578 + 0.2, 2000.0, 50.0, 31655.3, 7058.3, 9403.9, 78.279 + 0.2, 5000.0, 21.0, 3315.0, 2214.7, 755.5, 6.435 + 0.2, 5000.0, 22.0, 4270.4, 2510.0, 941.0, 5.268 + 0.2, 5000.0, 24.0, 6064.9, 2984.3, 1342.0, 7.4149 + 0.2, 5000.0, 26.0, 7773.0, 3372.1, 1755.4, 9.2124 + 0.2, 5000.0, 30.0, 11407.0, 4072.2, 2696.9, 13.226 + 0.2, 5000.0, 34.0, 14910.5, 4641.7, 3693.1, 16.168 + 0.2, 5000.0, 38.0, 18336.7, 5134.0, 4722.6, 18.655 + 0.2, 5000.0, 42.0, 21708.3, 5571.5, 5810.0, 20.901 + 0.2, 5000.0, 46.0, 25034.4, 5963.4, 6999.7, 46.548 + 0.2, 5000.0, 48.0, 26682.2, 6144.6, 7635.7, 60.797 + 0.2, 5000.0, 50.0, 28321.1, 6316.5, 8304.7, 71.484 + 0.2, 10000.0, 21.0, 2738.0, 1829.0, 626.4, 9.2804 + 0.2, 10000.0, 22.0, 3527.6, 2073.3, 775.5, 6.4797 + 0.2, 10000.0, 24.0, 5010.5, 2465.5, 1098.5, 6.2413 + 0.2, 10000.0, 26.0, 6421.8, 2786.1, 1431.7, 7.9908 + 0.2, 10000.0, 30.0, 9424.6, 3365.1, 2191.4, 11.756 + 0.2, 10000.0, 34.0, 12319.4, 3836.1, 2994.6, 14.615 + 0.2, 10000.0, 38.0, 15150.2, 4243.1, 3825.2, 17.028 + 0.2, 10000.0, 42.0, 17936.1, 4604.8, 4701.2, 19.18 + 0.2, 10000.0, 46.0, 20683.4, 4929.0, 5659.9, 23.631 + 0.2, 10000.0, 48.0, 22045.5, 5078.8, 6173.0, 36.496 + 0.2, 10000.0, 50.0, 23399.5, 5221.0, 6712.2, 53.492 + 0.25, 0.0, 21.0, 4982.9, 3711.0, 967.7, 5.1347 + 0.25, 0.0, 22.0, 6155.9, 4120.9, 1221.5, 6.4157 + 0.25, 0.0, 24.0, 8353.0, 4791.8, 1741.2, 8.5818 + 0.25, 0.0, 26.0, 10434.6, 5347.2, 2267.6, 10.748 + 0.25, 0.0, 30.0, 14837.1, 6358.1, 3458.3, 14.538 + 0.25, 0.0, 34.0, 19055.8, 7185.2, 4700.4, 17.453 + 0.25, 0.0, 38.0, 23164.2, 7901.7, 5979.8, 19.93 + 0.25, 0.0, 42.0, 27194.4, 8540.4, 7318.7, 34.279 + 0.25, 0.0, 46.0, 31158.1, 9112.7, 8772.0, 62.953 + 0.25, 0.0, 48.0, 33119.2, 9377.6, 9547.4, 72.817 + 0.25, 0.0, 50.0, 35064.8, 9627.7, 10368.8, 79.61 + 0.25, 2000.0, 21.0, 4635.4, 3453.6, 881.2, 4.9403 + 0.25, 2000.0, 22.0, 5725.7, 3834.8, 1113.2, 6.2358 + 0.25, 2000.0, 24.0, 7767.9, 4458.7, 1587.7, 8.4148 + 0.25, 2000.0, 26.0, 9702.8, 4975.4, 2068.9, 10.313 + 0.25, 2000.0, 30.0, 13794.8, 5915.8, 3157.8, 14.369 + 0.25, 2000.0, 34.0, 17715.3, 6684.5, 4299.7, 17.308 + 0.25, 2000.0, 38.0, 21533.5, 7351.2, 5470.6, 19.785 + 0.25, 2000.0, 42.0, 25278.1, 7944.4, 6705.3, 30.749 + 0.25, 2000.0, 46.0, 28960.8, 8474.8, 8057.1, 61.504 + 0.25, 2000.0, 48.0, 30782.4, 8720.7, 8773.3, 71.978 + 0.25, 2000.0, 50.0, 32590.3, 8953.2, 9529.4, 79.171 + 0.25, 5000.0, 21.0, 4146.8, 3089.4, 787.7, 5.8398 + 0.25, 5000.0, 22.0, 5122.4, 3430.7, 992.0, 5.6074 + 0.25, 5000.0, 24.0, 6949.9, 3989.3, 1411.0, 7.7697 + 0.25, 5000.0, 26.0, 8681.0, 4451.7, 1835.5, 9.5548 + 0.25, 5000.0, 30.0, 12342.2, 5293.4, 2795.6, 13.576 + 0.25, 5000.0, 34.0, 15850.1, 5981.6, 3803.0, 16.482 + 0.25, 5000.0, 38.0, 19266.4, 6578.4, 4836.6, 18.932 + 0.25, 5000.0, 42.0, 22617.1, 7109.4, 5925.2, 21.995 + 0.25, 5000.0, 46.0, 25911.5, 7584.2, 7117.3, 49.402 + 0.25, 5000.0, 48.0, 27541.0, 7804.3, 7748.5, 62.576 + 0.25, 5000.0, 50.0, 29158.9, 8012.2, 8415.7, 72.732 + 0.25, 10000.0, 21.0, 3424.9, 2551.5, 652.1, 8.6939 + 0.25, 10000.0, 22.0, 4231.3, 2833.9, 816.4, 5.6904 + 0.25, 10000.0, 24.0, 5741.3, 3295.8, 1153.9, 6.5846 + 0.25, 10000.0, 26.0, 7171.8, 3678.2, 1496.8, 8.3269 + 0.25, 10000.0, 30.0, 10196.9, 4374.2, 2270.9, 12.094 + 0.25, 10000.0, 34.0, 13095.1, 4943.3, 3083.3, 14.918 + 0.25, 10000.0, 38.0, 15917.5, 5436.7, 3916.9, 17.295 + 0.25, 10000.0, 42.0, 18685.9, 5875.8, 4794.1, 19.414 + 0.25, 10000.0, 46.0, 21407.5, 6268.5, 5754.5, 25.017 + 0.25, 10000.0, 48.0, 22754.0, 6450.6, 6263.1, 38.869 + 0.25, 10000.0, 50.0, 24090.7, 6622.7, 6801.4, 55.311 + 0.3, 0.0, 21.0, 6173.4, 4945.6, 1022.8, 5.4835 + 0.3, 0.0, 22.0, 7364.1, 5399.7, 1289.1, 6.7761 + 0.3, 0.0, 24.0, 9594.3, 6156.5, 1828.9, 8.945 + 0.3, 0.0, 26.0, 11702.0, 6790.9, 2370.2, 11.37 + 0.3, 0.0, 30.0, 16141.2, 7956.0, 3586.7, 14.908 + 0.3, 0.0, 34.0, 20374.2, 8914.9, 4845.9, 17.791 + 0.3, 0.0, 38.0, 24482.0, 9748.6, 6136.4, 20.242 + 0.3, 0.0, 42.0, 28498.9, 10491.9, 7487.2, 38.185 + 0.3, 0.0, 46.0, 32440.2, 11158.6, 8946.6, 65.354 + 0.3, 0.0, 48.0, 34385.6, 11467.0, 9722.6, 74.456 + 0.3, 0.0, 50.0, 36314.3, 11758.7, 10541.1, 80.608 + 0.3, 2000.0, 21.0, 5743.4, 4602.6, 931.5, 5.2941 + 0.3, 2000.0, 22.0, 6850.3, 5024.9, 1175.0, 6.6001 + 0.3, 2000.0, 24.0, 8923.2, 5728.8, 1668.1, 8.7823 + 0.3, 2000.0, 26.0, 10882.3, 6318.8, 2161.9, 11.024 + 0.3, 2000.0, 30.0, 15008.5, 7402.8, 3275.4, 14.742 + 0.3, 2000.0, 34.0, 18942.1, 8294.0, 4433.1, 17.647 + 0.3, 2000.0, 38.0, 22759.9, 9069.6, 5614.1, 20.098 + 0.3, 2000.0, 42.0, 26492.4, 9759.9, 6860.5, 34.305 + 0.3, 2000.0, 46.0, 30152.8, 10377.9, 8215.0, 63.856 + 0.3, 2000.0, 48.0, 31959.4, 10663.8, 8934.3, 73.679 + 0.3, 2000.0, 50.0, 33752.0, 10934.9, 9687.3, 80.217 + 0.3, 5000.0, 21.0, 5137.9, 4117.3, 832.0, 5.0092 + 0.3, 5000.0, 22.0, 6128.4, 4495.5, 1046.5, 5.9682 + 0.3, 5000.0, 24.0, 7983.1, 5125.5, 1481.4, 8.1293 + 0.3, 5000.0, 26.0, 9735.9, 5653.8, 1917.6, 9.9046 + 0.3, 5000.0, 30.0, 13427.5, 6623.9, 2899.2, 13.942 + 0.3, 5000.0, 34.0, 16946.8, 7421.7, 3920.4, 16.816 + 0.3, 5000.0, 38.0, 20362.5, 8115.9, 4962.2, 19.238 + 0.3, 5000.0, 42.0, 23701.7, 8733.8, 6061.4, 23.521 + 0.3, 5000.0, 46.0, 26976.2, 9286.8, 7256.0, 52.53 + 0.3, 5000.0, 48.0, 28592.9, 9543.0, 7890.1, 64.754 + 0.3, 5000.0, 50.0, 30196.6, 9785.7, 8554.4, 74.212 + 0.3, 10000.0, 21.0, 4243.8, 3400.8, 687.6, 7.8677 + 0.3, 10000.0, 22.0, 5062.5, 3713.6, 860.4, 4.908 + 0.3, 10000.0, 24.0, 6595.3, 4234.8, 1211.0, 6.9375 + 0.3, 10000.0, 26.0, 8043.8, 4671.6, 1563.1, 8.6667 + 0.3, 10000.0, 30.0, 11094.2, 5473.9, 2354.8, 12.45 + 0.3, 10000.0, 34.0, 14002.0, 6133.6, 3177.8, 15.24 + 0.3, 10000.0, 38.0, 16824.1, 6707.5, 4018.5, 17.59 + 0.3, 10000.0, 42.0, 19583.3, 7218.6, 4904.6, 19.693 + 0.3, 10000.0, 46.0, 22288.8, 7676.1, 5867.0, 26.947 + 0.3, 10000.0, 48.0, 23624.2, 7887.9, 6378.4, 42.083 + 0.3, 10000.0, 50.0, 24949.6, 8088.6, 6913.7, 57.381 + 0.3, 15000.0, 21.0, 3479.6, 2788.1, 567.1, 10.753 + 0.3, 15000.0, 22.0, 4151.5, 3045.2, 705.0, 7.7596 + 0.3, 15000.0, 24.0, 5409.3, 3473.3, 985.3, 5.6485 + 0.3, 15000.0, 26.0, 6597.7, 3831.9, 1267.2, 7.317 + 0.3, 15000.0, 30.0, 9100.3, 4490.8, 1900.3, 10.236 + 0.3, 15000.0, 34.0, 11486.0, 5032.6, 2558.6, 13.48 + 0.3, 15000.0, 38.0, 13801.0, 5503.8, 3231.5, 15.733 + 0.3, 15000.0, 42.0, 16064.5, 5923.6, 3939.7, 17.744 + 0.3, 15000.0, 46.0, 18284.0, 6299.3, 4708.7, 19.683 + 0.3, 15000.0, 48.0, 19379.7, 6473.2, 5117.8, 21.325 + 0.3, 15000.0, 50.0, 20466.5, 6637.9, 5546.1, 30.41 + 0.35, 0.0, 21.0, 7566.3, 6374.0, 1096.3, 5.9318 + 0.35, 0.0, 22.0, 8770.7, 6863.1, 1379.4, 7.2407 + 0.35, 0.0, 24.0, 11031.6, 7693.3, 1932.5, 9.3656 + 0.35, 0.0, 26.0, 13168.6, 8399.6, 2472.9, 11.765 + 0.35, 0.0, 30.0, 17653.6, 9705.4, 3720.3, 15.291 + 0.35, 0.0, 34.0, 21914.4, 10786.9, 5002.2, 18.152 + 0.35, 0.0, 38.0, 26037.3, 11730.5, 6310.8, 20.585 + 0.35, 0.0, 42.0, 30057.1, 12571.0, 7691.3, 43.121 + 0.35, 0.0, 46.0, 33993.9, 13328.4, 9155.7, 67.99 + 0.35, 0.0, 48.0, 35932.2, 13677.3, 9939.7, 76.316 + 0.35, 0.0, 50.0, 37853.7, 14009.0, 10755.8, 81.718 + 0.35, 2000.0, 21.0, 7039.8, 5932.0, 999.1, 5.7509 + 0.35, 2000.0, 22.0, 8159.4, 6386.9, 1257.8, 7.0693 + 0.35, 2000.0, 24.0, 10260.8, 7159.0, 1763.3, 9.2076 + 0.35, 2000.0, 26.0, 12247.3, 7816.1, 2255.9, 11.585 + 0.35, 2000.0, 30.0, 16416.2, 9030.9, 3397.3, 15.126 + 0.35, 2000.0, 34.0, 20375.6, 10036.0, 4575.8, 18.008 + 0.35, 2000.0, 38.0, 24207.3, 10913.7, 5773.4, 20.441 + 0.35, 2000.0, 42.0, 27941.9, 11694.1, 7047.4, 39.005 + 0.35, 2000.0, 46.0, 31598.2, 12396.5, 8403.2, 66.444 + 0.35, 2000.0, 48.0, 33398.3, 12719.4, 9133.8, 75.613 + 0.35, 2000.0, 50.0, 35183.5, 13027.6, 9884.0, 81.388 + 0.35, 5000.0, 21.0, 6297.7, 5306.8, 891.4, 5.1268 + 0.35, 5000.0, 22.0, 7299.6, 5714.1, 1119.5, 6.4339 + 0.35, 5000.0, 24.0, 9179.9, 6405.3, 1565.3, 8.5499 + 0.35, 5000.0, 26.0, 10957.1, 6993.4, 2000.3, 10.262 + 0.35, 5000.0, 30.0, 14686.9, 8080.8, 3006.9, 14.321 + 0.35, 5000.0, 34.0, 18229.2, 8980.4, 4046.1, 17.171 + 0.35, 5000.0, 38.0, 21657.4, 9766.2, 5102.9, 19.576 + 0.35, 5000.0, 42.0, 24998.3, 10464.7, 6226.3, 25.926 + 0.35, 5000.0, 46.0, 28269.4, 11093.1, 7421.8, 55.81 + 0.35, 5000.0, 48.0, 29879.7, 11382.5, 8065.8, 67.275 + 0.35, 5000.0, 50.0, 31477.1, 11658.5, 8727.8, 75.918 + 0.35, 10000.0, 21.0, 5202.0, 4383.5, 735.2, 6.795 + 0.35, 10000.0, 22.0, 6030.2, 4720.6, 919.0, 5.282 + 0.35, 10000.0, 24.0, 7584.1, 5292.2, 1278.6, 7.346 + 0.35, 10000.0, 26.0, 9052.7, 5778.6, 1629.9, 9.0072 + 0.35, 10000.0, 30.0, 12134.6, 6677.8, 2441.6, 12.816 + 0.35, 10000.0, 34.0, 15061.4, 7421.8, 3279.3, 15.582 + 0.35, 10000.0, 38.0, 17893.8, 8071.6, 4132.1, 17.916 + 0.35, 10000.0, 42.0, 20654.1, 8649.1, 5037.3, 20.024 + 0.35, 10000.0, 46.0, 23357.0, 9169.2, 6000.8, 29.598 + 0.35, 10000.0, 48.0, 24688.2, 9408.4, 6520.4, 45.942 + 0.35, 10000.0, 50.0, 26007.2, 9636.6, 7053.3, 59.554 + 0.35, 15000.0, 21.0, 4265.5, 3594.1, 604.8, 9.6899 + 0.35, 15000.0, 22.0, 4945.3, 3871.2, 751.6, 6.6744 + 0.35, 15000.0, 24.0, 6220.4, 4340.7, 1039.2, 6.0427 + 0.35, 15000.0, 26.0, 7425.3, 4740.1, 1320.6, 7.6429 + 0.35, 15000.0, 30.0, 9953.9, 5478.5, 1969.8, 10.871 + 0.35, 15000.0, 34.0, 12355.2, 6089.6, 2639.9, 13.806 + 0.35, 15000.0, 38.0, 14678.8, 6623.1, 3322.2, 16.041 + 0.35, 15000.0, 42.0, 16943.3, 7097.5, 4045.6, 18.057 + 0.35, 15000.0, 46.0, 19160.5, 7524.6, 4816.5, 19.961 + 0.35, 15000.0, 48.0, 20251.7, 7720.9, 5231.4, 22.662 + 0.35, 15000.0, 50.0, 21334.5, 7908.4, 5657.5, 33.192 + 0.4, 2000.0, 21.0, 8528.1, 7446.9, 1080.6, 6.2764 + 0.4, 2000.0, 22.0, 9658.0, 7928.2, 1353.5, 7.5936 + 0.4, 2000.0, 24.0, 11784.7, 8757.4, 1878.4, 9.7055 + 0.4, 2000.0, 26.0, 13797.7, 9473.0, 2382.4, 12.101 + 0.4, 2000.0, 30.0, 18018.9, 10811.1, 3529.2, 15.538 + 0.4, 2000.0, 34.0, 22012.9, 11922.0, 4732.9, 18.404 + 0.4, 2000.0, 38.0, 25869.2, 12895.0, 5956.0, 20.83 + 0.4, 2000.0, 42.0, 29617.1, 13759.9, 7260.5, 44.558 + 0.4, 2000.0, 46.0, 33282.9, 14542.5, 8623.9, 69.274 + 0.4, 2000.0, 48.0, 35081.9, 14900.1, 9368.5, 77.682 + 0.4, 2000.0, 50.0, 36867.3, 15243.9, 10120.0, 82.629 + 0.4, 5000.0, 21.0, 7629.4, 6662.3, 963.1, 5.6477 + 0.4, 5000.0, 22.0, 8640.5, 7093.1, 1203.9, 6.9524 + 0.4, 5000.0, 24.0, 10543.4, 7835.5, 1666.8, 9.0427 + 0.4, 5000.0, 26.0, 12344.4, 8476.0, 2111.2, 11.188 + 0.4, 5000.0, 30.0, 16121.1, 9673.7, 3123.3, 14.728 + 0.4, 5000.0, 34.0, 19694.5, 10668.0, 4184.8, 17.56 + 0.4, 5000.0, 38.0, 23144.4, 11539.2, 5263.3, 19.957 + 0.4, 5000.0, 42.0, 26497.4, 12313.3, 6414.0, 29.514 + 0.4, 5000.0, 46.0, 29777.0, 13014.0, 7616.7, 59.083 + 0.4, 5000.0, 48.0, 31386.7, 13333.9, 8272.8, 70.033 + 0.4, 5000.0, 50.0, 32983.8, 13641.9, 8936.1, 77.81 + 0.4, 10000.0, 21.0, 6302.4, 5503.6, 792.8, 5.5515 + 0.4, 10000.0, 22.0, 7138.3, 5860.2, 987.2, 5.7899 + 0.4, 10000.0, 24.0, 8710.6, 6473.9, 1360.1, 7.8236 + 0.4, 10000.0, 26.0, 10198.9, 7003.7, 1718.7, 9.4457 + 0.4, 10000.0, 30.0, 13319.7, 7994.3, 2535.4, 13.209 + 0.4, 10000.0, 34.0, 16272.3, 8816.6, 3391.4, 15.957 + 0.4, 10000.0, 38.0, 19122.7, 9537.0, 4262.0, 18.284 + 0.4, 10000.0, 42.0, 21893.2, 10177.2, 5188.5, 20.395 + 0.4, 10000.0, 46.0, 24602.9, 10756.8, 6158.4, 33.244 + 0.4, 10000.0, 48.0, 25932.9, 11021.4, 6687.2, 50.261 + 0.4, 10000.0, 50.0, 27252.3, 11276.0, 7221.2, 62.314 + 0.4, 15000.0, 21.0, 5168.0, 4512.9, 650.8, 8.4556 + 0.4, 15000.0, 22.0, 5854.1, 4806.0, 806.0, 5.4657 + 0.4, 15000.0, 24.0, 7144.6, 5310.3, 1104.8, 6.507 + 0.4, 15000.0, 26.0, 8365.6, 5745.3, 1391.4, 8.064 + 0.4, 15000.0, 30.0, 10925.8, 6558.6, 2044.8, 11.526 + 0.4, 15000.0, 34.0, 13348.1, 7234.0, 2729.6, 14.163 + 0.4, 15000.0, 38.0, 15686.6, 7825.6, 3426.3, 16.392 + 0.4, 15000.0, 42.0, 17959.2, 8351.4, 4166.5, 18.41 + 0.4, 15000.0, 46.0, 20182.2, 8827.3, 4942.1, 20.28 + 0.4, 15000.0, 48.0, 21272.7, 9044.6, 5364.6, 24.607 + 0.4, 15000.0, 50.0, 22355.5, 9253.8, 5792.4, 36.891 + 0.4, 20000.0, 21.0, 4204.2, 3671.1, 533.0, 11.344 + 0.4, 20000.0, 22.0, 4763.2, 3910.2, 655.9, 8.3987 + 0.4, 20000.0, 24.0, 5814.2, 4321.4, 892.7, 5.1322 + 0.4, 20000.0, 26.0, 6808.5, 4676.0, 1119.9, 6.6187 + 0.4, 20000.0, 30.0, 8893.2, 5339.0, 1638.7, 9.2928 + 0.4, 20000.0, 34.0, 10865.4, 5889.5, 2181.2, 12.258 + 0.4, 20000.0, 38.0, 12769.1, 6371.6, 2734.1, 14.37 + 0.4, 20000.0, 42.0, 14619.4, 6800.2, 3321.2, 16.28 + 0.4, 20000.0, 46.0, 16429.0, 7188.1, 3935.2, 18.048 + 0.4, 20000.0, 48.0, 17317.4, 7365.4, 4270.7, 18.955 + 0.4, 20000.0, 50.0, 18198.2, 7535.7, 4608.9, 19.817 + 0.45, 5000.0, 21.0, 9134.3, 8186.4, 1052.9, 6.2594 + 0.45, 5000.0, 22.0, 10153.5, 8637.0, 1297.4, 7.5048 + 0.45, 5000.0, 24.0, 12077.2, 9423.1, 1777.2, 9.5637 + 0.45, 5000.0, 26.0, 13900.8, 10109.4, 2237.9, 11.895 + 0.45, 5000.0, 30.0, 17726.1, 11407.1, 3263.8, 15.21 + 0.45, 5000.0, 34.0, 21336.8, 12490.1, 4347.5, 18.009 + 0.45, 5000.0, 38.0, 24813.0, 13438.6, 5462.2, 20.42 + 0.45, 5000.0, 42.0, 28188.8, 14287.0, 6626.4, 34.59 + 0.45, 5000.0, 46.0, 31486.0, 15056.3, 7841.9, 62.504 + 0.45, 5000.0, 48.0, 33098.2, 15405.0, 8512.7, 72.975 + 0.45, 5000.0, 50.0, 34700.2, 15743.1, 9179.8, 79.815 + 0.45, 10000.0, 21.0, 7545.9, 6763.0, 865.0, 5.1128 + 0.45, 10000.0, 22.0, 8388.6, 7135.9, 1062.6, 6.3291 + 0.45, 10000.0, 24.0, 9978.2, 7786.1, 1449.5, 8.3334 + 0.45, 10000.0, 26.0, 11485.1, 8353.6, 1820.8, 9.9346 + 0.45, 10000.0, 30.0, 14645.9, 9426.7, 2648.1, 13.672 + 0.45, 10000.0, 34.0, 17629.4, 10322.5, 3522.4, 16.391 + 0.45, 10000.0, 38.0, 20501.5, 11106.9, 4421.5, 18.73 + 0.45, 10000.0, 42.0, 23290.9, 11808.7, 5360.6, 20.812 + 0.45, 10000.0, 46.0, 26014.7, 12444.7, 6339.6, 38.018 + 0.45, 10000.0, 48.0, 27346.9, 12733.1, 6880.0, 54.809 + 0.45, 10000.0, 50.0, 28670.6, 13012.9, 7417.8, 65.545 + 0.45, 15000.0, 21.0, 6188.1, 5546.1, 708.2, 7.0161 + 0.45, 15000.0, 22.0, 6879.8, 5852.6, 866.3, 5.0623 + 0.45, 15000.0, 24.0, 8184.3, 6386.7, 1176.1, 6.9948 + 0.45, 15000.0, 26.0, 9420.7, 6852.7, 1473.1, 8.533 + 0.45, 15000.0, 30.0, 12014.0, 7734.1, 2135.7, 11.974 + 0.45, 15000.0, 34.0, 14461.5, 8469.7, 2834.4, 14.576 + 0.45, 15000.0, 38.0, 16817.6, 9113.8, 3553.9, 16.816 + 0.45, 15000.0, 42.0, 19105.8, 9690.3, 4304.2, 18.806 + 0.45, 15000.0, 46.0, 21340.5, 10212.6, 5087.2, 20.647 + 0.45, 15000.0, 48.0, 22433.2, 10449.4, 5519.7, 27.602 + 0.45, 15000.0, 50.0, 23518.8, 10679.1, 5949.6, 41.472 + 0.45, 20000.0, 21.0, 5034.5, 4512.0, 578.2, 9.9201 + 0.45, 20000.0, 22.0, 5598.0, 4762.1, 703.5, 7.1405 + 0.45, 20000.0, 24.0, 6660.5, 5197.7, 949.2, 5.5997 + 0.45, 20000.0, 26.0, 7667.4, 5577.6, 1184.8, 7.0642 + 0.45, 20000.0, 30.0, 9779.0, 6296.0, 1710.7, 9.6704 + 0.45, 20000.0, 34.0, 11771.9, 6895.7, 2264.6, 12.648 + 0.45, 20000.0, 38.0, 13690.0, 7420.5, 2835.3, 14.769 + 0.45, 20000.0, 42.0, 15553.0, 7890.4, 3430.4, 16.652 + 0.45, 20000.0, 46.0, 17372.0, 8316.2, 4051.2, 18.392 + 0.45, 20000.0, 48.0, 18261.9, 8509.5, 4393.4, 19.298 + 0.45, 20000.0, 50.0, 19145.4, 8696.4, 4733.9, 20.481 + 0.45, 25000.0, 21.0, 4060.5, 3638.9, 471.3, 12.824 + 0.45, 25000.0, 22.0, 4515.9, 3841.4, 569.7, 10.068 + 0.45, 25000.0, 24.0, 5374.3, 4193.9, 762.8, 5.6593 + 0.45, 25000.0, 26.0, 6187.3, 4501.0, 947.5, 5.5964 + 0.45, 25000.0, 30.0, 7892.2, 5081.8, 1360.8, 8.0513 + 0.45, 25000.0, 34.0, 9501.3, 5566.7, 1795.6, 10.502 + 0.45, 25000.0, 38.0, 11049.7, 5991.0, 2244.5, 12.709 + 0.45, 25000.0, 42.0, 12553.9, 6370.9, 2711.4, 14.474 + 0.45, 25000.0, 46.0, 14022.2, 6715.2, 3198.7, 16.109 + 0.45, 25000.0, 48.0, 14740.5, 6871.3, 3466.7, 16.96 + 0.45, 25000.0, 50.0, 15453.9, 7022.7, 3734.8, 17.763 + 0.5, 10000.0, 21.0, 8935.3, 8163.6, 961.2, 5.8415 + 0.5, 10000.0, 22.0, 9784.6, 8549.9, 1163.5, 6.9976 + 0.5, 10000.0, 24.0, 11396.5, 9235.8, 1543.3, 8.8511 + 0.5, 10000.0, 26.0, 12924.7, 9838.0, 1929.2, 10.579 + 0.5, 10000.0, 30.0, 16130.8, 10986.4, 2783.0, 14.206 + 0.5, 10000.0, 34.0, 19153.1, 11950.9, 3679.1, 16.896 + 0.5, 10000.0, 38.0, 22058.2, 12798.3, 4602.1, 19.219 + 0.5, 10000.0, 42.0, 24877.3, 13559.7, 5557.3, 21.879 + 0.5, 10000.0, 46.0, 27624.5, 14249.1, 6554.3, 44.221 + 0.5, 10000.0, 48.0, 28965.7, 14561.4, 7104.9, 59.126 + 0.5, 10000.0, 50.0, 30298.2, 14865.0, 7650.4, 69.048 + 0.5, 15000.0, 21.0, 7328.1, 6695.3, 785.0, 5.2669 + 0.5, 15000.0, 22.0, 8025.5, 7012.9, 947.3, 5.7106 + 0.5, 15000.0, 24.0, 9348.0, 7576.1, 1250.9, 7.4914 + 0.5, 15000.0, 26.0, 10602.1, 8070.9, 1560.0, 9.017 + 0.5, 15000.0, 30.0, 13232.8, 9014.0, 2243.0, 12.483 + 0.5, 15000.0, 34.0, 15712.4, 9806.1, 2959.9, 15.058 + 0.5, 15000.0, 38.0, 18095.8, 10502.0, 3698.5, 17.284 + 0.5, 15000.0, 42.0, 20408.6, 11127.3, 4462.3, 19.251 + 0.5, 15000.0, 46.0, 22662.5, 11693.7, 5260.4, 22.186 + 0.5, 15000.0, 48.0, 23762.9, 11950.1, 5699.8, 31.922 + 0.5, 15000.0, 50.0, 24855.4, 12199.1, 6135.5, 46.874 + 0.5, 20000.0, 21.0, 5962.3, 5447.4, 638.9, 8.1949 + 0.5, 20000.0, 22.0, 6530.4, 5706.6, 767.5, 5.5864 + 0.5, 20000.0, 24.0, 7607.5, 6165.9, 1008.8, 6.0754 + 0.5, 20000.0, 26.0, 8628.5, 6569.1, 1253.7, 7.5239 + 0.5, 20000.0, 30.0, 10770.3, 7337.8, 1795.3, 10.124 + 0.5, 20000.0, 34.0, 12788.9, 7983.4, 2363.9, 13.102 + 0.5, 20000.0, 38.0, 14729.0, 8550.6, 2949.4, 15.208 + 0.5, 20000.0, 42.0, 16611.6, 9060.2, 3555.1, 17.068 + 0.5, 20000.0, 46.0, 18446.0, 9521.6, 4187.2, 18.792 + 0.5, 20000.0, 48.0, 19341.8, 9731.0, 4535.0, 19.685 + 0.5, 20000.0, 50.0, 20231.5, 9934.1, 4880.0, 22.256 + 0.5, 25000.0, 21.0, 4809.4, 4393.9, 518.7, 11.107 + 0.5, 25000.0, 22.0, 5268.5, 4603.8, 619.7, 8.5392 + 0.5, 25000.0, 24.0, 6138.4, 4975.2, 809.4, 4.6585 + 0.5, 25000.0, 26.0, 6963.0, 5301.2, 1001.5, 6.0297 + 0.5, 25000.0, 30.0, 8692.6, 5923.0, 1426.9, 8.4555 + 0.5, 25000.0, 34.0, 10322.4, 6444.9, 1873.7, 11.135 + 0.5, 25000.0, 38.0, 11888.8, 6903.5, 2334.1, 13.12 + 0.5, 25000.0, 42.0, 13408.7, 7315.6, 2809.6, 14.863 + 0.5, 25000.0, 46.0, 14889.7, 7688.8, 3305.8, 16.482 + 0.5, 25000.0, 48.0, 15612.7, 7857.9, 3578.7, 17.322 + 0.5, 25000.0, 50.0, 16331.0, 8022.2, 3850.1, 18.114 + 0.55, 10000.0, 21.0, 10473.2, 9708.0, 1063.1, 6.5663 + 0.55, 10000.0, 22.0, 11331.3, 10107.0, 1273.2, 7.684 + 0.55, 10000.0, 24.0, 12968.8, 10826.2, 1651.6, 9.4227 + 0.55, 10000.0, 26.0, 14524.0, 11463.2, 2046.0, 11.615 + 0.55, 10000.0, 30.0, 17784.6, 12683.1, 2929.7, 14.772 + 0.55, 10000.0, 34.0, 20855.7, 13713.6, 3852.5, 17.44 + 0.55, 10000.0, 38.0, 23804.1, 14621.6, 4806.1, 19.759 + 0.55, 10000.0, 42.0, 26664.3, 15441.0, 5782.5, 24.834 + 0.55, 10000.0, 46.0, 29445.2, 16181.5, 6806.8, 51.322 + 0.55, 10000.0, 48.0, 30801.6, 16517.7, 7366.0, 63.487 + 0.55, 10000.0, 50.0, 32151.3, 16847.1, 7921.7, 72.72 + 0.55, 15000.0, 21.0, 8589.7, 7962.3, 866.4, 5.2947 + 0.55, 15000.0, 22.0, 9294.1, 8290.2, 1034.6, 6.3704 + 0.55, 15000.0, 24.0, 10637.7, 8880.9, 1337.3, 8.0399 + 0.55, 15000.0, 26.0, 11913.6, 9404.0, 1653.0, 9.52 + 0.55, 15000.0, 30.0, 14588.5, 10405.8, 2359.7, 13.02 + 0.55, 15000.0, 34.0, 17108.0, 11252.3, 3098.8, 15.578 + 0.55, 15000.0, 38.0, 19526.7, 11997.8, 3861.4, 17.796 + 0.55, 15000.0, 42.0, 21872.4, 12670.6, 4642.0, 19.745 + 0.55, 15000.0, 46.0, 24153.7, 13278.7, 5460.9, 25.174 + 0.55, 15000.0, 48.0, 25266.4, 13555.1, 5907.7, 37.782 + 0.55, 15000.0, 50.0, 26373.7, 13825.7, 6352.0, 52.652 + 0.55, 20000.0, 21.0, 6989.4, 6479.0, 703.3, 6.503 + 0.55, 20000.0, 22.0, 7563.3, 6746.5, 837.0, 5.0064 + 0.55, 20000.0, 24.0, 8657.4, 7228.1, 1077.2, 6.5972 + 0.55, 20000.0, 26.0, 9696.4, 7654.5, 1327.5, 8.0013 + 0.55, 20000.0, 30.0, 11874.4, 8471.2, 1888.0, 11.051 + 0.55, 20000.0, 34.0, 13925.6, 9161.1, 2474.4, 13.594 + 0.55, 20000.0, 38.0, 15894.5, 9768.8, 3078.5, 15.69 + 0.55, 20000.0, 42.0, 17804.3, 10317.3, 3698.0, 17.532 + 0.55, 20000.0, 46.0, 19661.3, 10813.0, 4347.4, 19.251 + 0.55, 20000.0, 48.0, 20567.3, 11038.3, 4701.1, 20.129 + 0.55, 20000.0, 50.0, 21468.4, 11258.8, 5053.1, 25.154 + 0.55, 25000.0, 21.0, 5638.5, 5226.6, 569.1, 9.4348 + 0.55, 25000.0, 22.0, 6102.2, 5443.2, 674.2, 6.9986 + 0.55, 25000.0, 24.0, 6985.9, 5832.7, 863.0, 5.1538 + 0.55, 25000.0, 26.0, 7825.0, 6177.5, 1059.5, 6.4814 + 0.55, 25000.0, 30.0, 9583.8, 6838.0, 1499.7, 8.8813 + 0.55, 25000.0, 34.0, 11240.1, 7395.8, 1960.8, 11.598 + 0.55, 25000.0, 38.0, 12829.7, 7887.1, 2435.5, 13.57 + 0.55, 25000.0, 42.0, 14371.4, 8330.6, 2922.0, 15.297 + 0.55, 25000.0, 46.0, 15870.7, 8731.4, 3431.6, 16.909 + 0.55, 25000.0, 48.0, 16601.9, 8913.6, 3708.9, 17.733 + 0.55, 25000.0, 50.0, 17329.5, 9092.0, 3985.6, 18.518 + 0.55, 30000.0, 21.0, 4506.0, 4176.6, 459.6, 12.365 + 0.55, 30000.0, 22.0, 4877.6, 4350.6, 541.3, 9.9465 + 0.55, 30000.0, 24.0, 5585.4, 4663.2, 688.6, 6.3459 + 0.55, 30000.0, 26.0, 6257.1, 4939.6, 841.1, 4.9951 + 0.55, 30000.0, 30.0, 7665.1, 5469.3, 1183.3, 7.2442 + 0.55, 30000.0, 34.0, 8990.5, 5916.4, 1541.7, 9.1534 + 0.55, 30000.0, 38.0, 10262.7, 6310.2, 1910.9, 11.49 + 0.55, 30000.0, 42.0, 11496.3, 6665.6, 2289.2, 13.1 + 0.55, 30000.0, 46.0, 12696.1, 6986.9, 2685.7, 14.605 + 0.55, 30000.0, 48.0, 13281.5, 7133.2, 2900.4, 15.372 + 0.55, 30000.0, 50.0, 13863.3, 7275.8, 3114.4, 16.106 + 0.6, 15000.0, 21.0, 9973.8, 9348.2, 950.5, 5.9783 + 0.6, 15000.0, 22.0, 10687.7, 9686.8, 1124.3, 7.0163 + 0.6, 15000.0, 24.0, 12054.5, 10302.9, 1438.6, 8.6443 + 0.6, 15000.0, 26.0, 13357.4, 10855.1, 1754.7, 10.048 + 0.6, 15000.0, 30.0, 16084.8, 11914.4, 2488.5, 13.592 + 0.6, 15000.0, 34.0, 18652.7, 12814.1, 3252.5, 16.138 + 0.6, 15000.0, 38.0, 21114.4, 13607.6, 4042.6, 18.351 + 0.6, 15000.0, 42.0, 23501.9, 14327.1, 4845.2, 20.289 + 0.6, 15000.0, 46.0, 25820.8, 14977.7, 5688.9, 30.203 + 0.6, 15000.0, 48.0, 26957.4, 15280.2, 6143.4, 44.833 + 0.6, 15000.0, 50.0, 28089.5, 15578.2, 6600.6, 58.064 + 0.6, 20000.0, 21.0, 8116.3, 7607.3, 769.9, 4.8739 + 0.6, 20000.0, 22.0, 8697.8, 7883.4, 907.9, 5.6219 + 0.6, 20000.0, 24.0, 9810.9, 8385.7, 1157.0, 7.1692 + 0.6, 20000.0, 26.0, 10872.0, 8836.1, 1408.5, 8.504 + 0.6, 20000.0, 30.0, 13092.7, 9699.5, 1989.8, 11.708 + 0.6, 20000.0, 34.0, 15183.5, 10432.9, 2596.5, 14.121 + 0.6, 20000.0, 38.0, 17187.7, 11079.9, 3223.0, 16.215 + 0.6, 20000.0, 42.0, 19131.3, 11666.4, 3858.8, 18.043 + 0.6, 20000.0, 46.0, 21019.2, 12196.8, 4528.3, 19.756 + 0.6, 20000.0, 48.0, 21944.6, 12443.4, 4888.4, 21.651 + 0.6, 20000.0, 50.0, 22865.7, 12685.9, 5250.5, 29.739 + 0.6, 25000.0, 21.0, 6548.0, 6137.4, 621.3, 7.8343 + 0.6, 25000.0, 22.0, 7018.0, 6361.0, 730.0, 5.5192 + 0.6, 25000.0, 24.0, 7917.0, 6767.3, 925.6, 5.6982 + 0.6, 25000.0, 26.0, 8773.7, 7131.3, 1123.2, 6.9559 + 0.6, 25000.0, 30.0, 10567.1, 7829.7, 1580.2, 9.3365 + 0.6, 25000.0, 34.0, 12254.9, 8422.5, 2056.4, 12.09 + 0.6, 25000.0, 38.0, 13872.9, 8945.6, 2548.6, 14.059 + 0.6, 25000.0, 42.0, 15441.9, 9419.5, 3048.5, 15.774 + 0.6, 25000.0, 46.0, 16965.8, 9848.6, 3573.0, 17.377 + 0.6, 25000.0, 48.0, 17712.8, 10048.1, 3855.9, 18.185 + 0.6, 25000.0, 50.0, 18456.6, 10244.4, 4140.2, 18.967 + 0.6, 30000.0, 21.0, 5233.4, 4905.1, 500.0, 10.771 + 0.6, 30000.0, 22.0, 5610.0, 5084.7, 584.6, 8.4942 + 0.6, 30000.0, 24.0, 6329.9, 5410.6, 736.4, 5.0619 + 0.6, 30000.0, 26.0, 7015.7, 5702.4, 890.5, 5.441 + 0.6, 30000.0, 30.0, 8451.2, 6262.4, 1245.5, 7.6673 + 0.6, 30000.0, 34.0, 9802.1, 6737.8, 1616.1, 9.6371 + 0.6, 30000.0, 38.0, 11096.9, 7157.0, 1998.7, 11.943 + 0.6, 30000.0, 42.0, 12352.3, 7536.9, 2387.5, 13.542 + 0.6, 30000.0, 46.0, 13571.6, 7880.7, 2795.9, 15.04 + 0.6, 30000.0, 48.0, 14169.7, 8041.0, 3014.6, 15.79 + 0.6, 30000.0, 50.0, 14764.6, 8198.1, 3235.5, 16.524 + 0.6, 35000.0, 21.0, 4139.6, 3879.7, 401.9, 13.765 + 0.6, 35000.0, 22.0, 4438.7, 4022.7, 467.0, 11.472 + 0.6, 35000.0, 24.0, 5009.8, 4281.9, 583.8, 8.0866 + 0.6, 35000.0, 26.0, 5553.5, 4513.7, 702.3, 5.2844 + 0.6, 35000.0, 30.0, 6691.7, 4958.7, 975.1, 6.0676 + 0.6, 35000.0, 34.0, 7762.5, 5336.2, 1259.8, 7.8379 + 0.6, 35000.0, 38.0, 8788.5, 5669.1, 1553.9, 9.6313 + 0.6, 35000.0, 42.0, 9783.3, 5970.6, 1853.8, 11.406 + 0.6, 35000.0, 46.0, 10749.7, 6243.7, 2167.6, 12.793 + 0.6, 35000.0, 48.0, 11223.1, 6370.7, 2335.6, 13.49 + 0.6, 35000.0, 50.0, 11695.0, 6496.0, 2504.7, 14.172 + 0.6, 37000.0, 21.0, 3758.1, 3522.0, 370.0, 14.208 + 0.6, 37000.0, 22.0, 4030.2, 3652.4, 428.7, 11.931 + 0.6, 37000.0, 24.0, 4549.5, 3888.3, 534.1, 8.6067 + 0.6, 37000.0, 26.0, 5043.7, 4099.0, 640.8, 5.8649 + 0.6, 37000.0, 30.0, 6078.5, 4504.0, 886.9, 5.62 + 0.6, 37000.0, 34.0, 7051.8, 4847.5, 1143.9, 7.3337 + 0.6, 37000.0, 38.0, 7984.2, 5150.1, 1409.1, 8.8243 + 0.6, 37000.0, 42.0, 8888.2, 5424.2, 1680.1, 10.753 + 0.6, 37000.0, 46.0, 9766.3, 5672.7, 1963.0, 12.091 + 0.6, 37000.0, 48.0, 10197.0, 5788.4, 2114.5, 12.764 + 0.6, 37000.0, 50.0, 10625.8, 5902.3, 2266.3, 13.418 + 0.6, 39000.0, 21.0, 3410.5, 3195.9, 342.8, 13.736 + 0.6, 39000.0, 22.0, 3658.1, 3314.8, 396.0, 11.525 + 0.6, 39000.0, 24.0, 4130.3, 3529.5, 491.6, 8.3235 + 0.6, 39000.0, 26.0, 4579.5, 3721.3, 588.5, 5.6738 + 0.6, 39000.0, 30.0, 5520.0, 4089.6, 811.7, 5.3948 + 0.6, 39000.0, 34.0, 6404.7, 4402.1, 1044.8, 7.0416 + 0.6, 39000.0, 38.0, 7251.9, 4677.1, 1285.7, 8.4753 + 0.6, 39000.0, 42.0, 8073.2, 4926.2, 1532.0, 10.334 + 0.6, 39000.0, 46.0, 8871.3, 5152.2, 1788.5, 11.619 + 0.6, 39000.0, 48.0, 9262.7, 5257.5, 1925.9, 12.265 + 0.6, 39000.0, 50.0, 9652.5, 5361.2, 2063.4, 12.888 + 0.6, 41000.0, 21.0, 3094.4, 2899.4, 318.6, 13.295 + 0.6, 41000.0, 22.0, 3320.0, 3008.0, 366.6, 11.145 + 0.6, 41000.0, 24.0, 3749.4, 3203.6, 453.0, 8.0632 + 0.6, 41000.0, 26.0, 4157.8, 3378.0, 541.0, 5.5011 + 0.6, 41000.0, 30.0, 5012.8, 3713.2, 743.4, 5.178 + 0.6, 41000.0, 34.0, 5816.8, 3997.3, 954.9, 6.7566 + 0.6, 41000.0, 38.0, 6586.8, 4247.5, 1173.9, 8.1404 + 0.6, 41000.0, 42.0, 7333.1, 4473.9, 1397.5, 9.9298 + 0.6, 41000.0, 46.0, 8058.4, 4679.4, 1630.2, 11.165 + 0.6, 41000.0, 48.0, 8414.1, 4775.2, 1754.8, 11.784 + 0.6, 41000.0, 50.0, 8768.5, 4869.7, 1878.9, 12.376 + 0.65, 15000.0, 21.0, 11481.3, 10854.1, 1035.9, 6.6394 + 0.65, 15000.0, 22.0, 12207.7, 11204.2, 1215.3, 7.6447 + 0.65, 15000.0, 24.0, 13603.0, 11846.9, 1542.7, 9.2444 + 0.65, 15000.0, 26.0, 14935.6, 12427.0, 1867.4, 11.011 + 0.65, 15000.0, 30.0, 17724.6, 13543.7, 2628.1, 14.192 + 0.65, 15000.0, 34.0, 20349.9, 14496.6, 3420.7, 16.73 + 0.65, 15000.0, 38.0, 22863.3, 15337.4, 4243.8, 18.949 + 0.65, 15000.0, 42.0, 25300.6, 16102.7, 5073.7, 20.882 + 0.65, 15000.0, 46.0, 27684.0, 16813.4, 5945.8, 37.645 + 0.65, 15000.0, 48.0, 28853.2, 17146.3, 6412.4, 52.445 + 0.65, 15000.0, 50.0, 30016.4, 17473.3, 6885.5, 63.165 + 0.65, 20000.0, 21.0, 9343.5, 8833.4, 837.7, 5.2653 + 0.65, 20000.0, 22.0, 9935.0, 9118.7, 979.9, 6.2209 + 0.65, 20000.0, 24.0, 11071.1, 9642.6, 1239.6, 7.74 + 0.65, 20000.0, 26.0, 12156.3, 10115.6, 1497.6, 9.0357 + 0.65, 20000.0, 30.0, 14427.2, 11026.1, 2101.3, 12.279 + 0.65, 20000.0, 34.0, 16564.3, 11802.7, 2729.9, 14.679 + 0.65, 20000.0, 38.0, 18610.2, 12488.0, 3382.1, 16.776 + 0.65, 20000.0, 42.0, 20594.6, 13112.0, 4040.1, 18.601 + 0.65, 20000.0, 46.0, 22534.2, 13691.1, 4731.2, 20.306 + 0.65, 20000.0, 48.0, 23485.7, 13962.4, 5100.5, 24.941 + 0.65, 20000.0, 50.0, 24432.6, 14229.1, 5474.5, 36.266 + 0.65, 25000.0, 21.0, 7538.7, 7127.2, 674.5, 6.3118 + 0.65, 25000.0, 22.0, 8016.8, 7358.3, 786.7, 4.8016 + 0.65, 25000.0, 24.0, 8934.3, 7781.9, 990.5, 6.2373 + 0.65, 25000.0, 26.0, 9810.5, 8164.3, 1193.3, 7.4577 + 0.65, 25000.0, 30.0, 11644.1, 8900.5, 1667.2, 9.8122 + 0.65, 25000.0, 34.0, 13369.6, 9528.5, 2161.3, 12.612 + 0.65, 25000.0, 38.0, 15021.2, 10082.6, 2673.6, 14.582 + 0.65, 25000.0, 42.0, 16623.1, 10587.1, 3190.9, 16.294 + 0.65, 25000.0, 46.0, 18188.8, 11055.3, 3733.0, 17.892 + 0.65, 25000.0, 48.0, 18957.1, 11274.9, 4023.5, 18.687 + 0.65, 25000.0, 50.0, 19721.6, 11490.7, 4316.5, 19.465 + 0.65, 30000.0, 21.0, 6025.8, 5696.8, 541.2, 9.2686 + 0.65, 30000.0, 22.0, 6408.8, 5882.4, 628.6, 7.1132 + 0.65, 30000.0, 24.0, 7143.4, 6222.1, 786.8, 4.7609 + 0.65, 30000.0, 26.0, 7844.8, 6528.7, 944.9, 5.9115 + 0.65, 30000.0, 30.0, 9312.7, 7119.2, 1313.5, 8.114 + 0.65, 30000.0, 34.0, 10693.4, 7622.5, 1697.7, 10.518 + 0.65, 30000.0, 38.0, 12015.1, 8066.7, 2096.0, 12.429 + 0.65, 30000.0, 42.0, 13296.7, 8470.9, 2498.2, 14.024 + 0.65, 30000.0, 46.0, 14549.5, 8846.3, 2919.9, 15.514 + 0.65, 30000.0, 48.0, 15164.4, 9022.5, 3145.2, 16.258 + 0.65, 30000.0, 50.0, 15776.0, 9195.4, 3372.5, 16.984 + 0.65, 35000.0, 21.0, 4767.0, 4506.6, 433.5, 12.248 + 0.65, 35000.0, 22.0, 5071.1, 4654.4, 500.8, 10.098 + 0.65, 35000.0, 24.0, 5653.7, 4924.4, 622.1, 6.8639 + 0.65, 35000.0, 26.0, 6210.0, 5168.0, 743.9, 4.422 + 0.65, 35000.0, 30.0, 7373.7, 5637.1, 1027.3, 6.4841 + 0.65, 35000.0, 34.0, 8468.2, 6037.1, 1322.7, 8.2441 + 0.65, 35000.0, 38.0, 9515.4, 6389.7, 1628.5, 10.363 + 0.65, 35000.0, 42.0, 10530.9, 6710.5, 1938.8, 11.854 + 0.65, 35000.0, 46.0, 11523.6, 7008.6, 2262.9, 13.234 + 0.65, 35000.0, 48.0, 12010.7, 7148.5, 2436.1, 13.925 + 0.65, 35000.0, 50.0, 12495.8, 7286.2, 2609.9, 14.597 + 0.65, 37000.0, 21.0, 4328.0, 4091.4, 398.3, 12.711 + 0.65, 37000.0, 22.0, 4604.7, 4226.1, 459.1, 10.58 + 0.65, 37000.0, 24.0, 5134.7, 4472.0, 568.6, 7.4067 + 0.65, 37000.0, 26.0, 5640.3, 4693.6, 678.3, 4.7981 + 0.65, 37000.0, 30.0, 6698.2, 5120.4, 934.1, 6.0241 + 0.65, 37000.0, 34.0, 7693.1, 5484.2, 1200.6, 7.7263 + 0.65, 37000.0, 38.0, 8645.0, 5805.0, 1476.6, 9.5229 + 0.65, 37000.0, 42.0, 9567.7, 6096.5, 1757.2, 11.188 + 0.65, 37000.0, 46.0, 10470.1, 6367.8, 2049.0, 12.517 + 0.65, 37000.0, 48.0, 10912.6, 6494.8, 2205.3, 13.184 + 0.65, 37000.0, 50.0, 11353.7, 6620.3, 2361.7, 13.83 + 0.65, 39000.0, 21.0, 3928.0, 3713.0, 368.4, 12.291 + 0.65, 39000.0, 22.0, 4179.8, 3835.7, 423.5, 10.222 + 0.65, 39000.0, 24.0, 4661.5, 4059.5, 522.5, 7.1754 + 0.65, 39000.0, 26.0, 5121.2, 4261.1, 622.3, 4.6517 + 0.65, 39000.0, 30.0, 6082.8, 4649.3, 854.5, 5.7838 + 0.65, 39000.0, 34.0, 6987.2, 4980.3, 1096.2, 7.4195 + 0.65, 39000.0, 38.0, 7852.3, 5272.0, 1347.0, 9.1325 + 0.65, 39000.0, 42.0, 8690.6, 5536.9, 1601.9, 10.752 + 0.65, 39000.0, 46.0, 9510.4, 5783.5, 1866.9, 12.031 + 0.65, 39000.0, 48.0, 9912.8, 5899.1, 2008.5, 12.671 + 0.65, 39000.0, 50.0, 10313.9, 6013.4, 2149.9, 13.285 + 0.65, 41000.0, 21.0, 3564.4, 3369.0, 341.4, 11.899 + 0.65, 41000.0, 22.0, 3793.7, 3481.1, 391.2, 9.8837 + 0.65, 41000.0, 24.0, 4231.9, 3684.9, 480.9, 6.9499 + 0.65, 41000.0, 26.0, 4649.7, 3868.3, 571.5, 4.5148 + 0.65, 41000.0, 30.0, 5523.7, 4221.4, 782.2, 5.5521 + 0.65, 41000.0, 34.0, 6345.8, 4522.5, 1001.6, 7.1247 + 0.65, 41000.0, 38.0, 7131.8, 4787.6, 1229.2, 8.7518 + 0.65, 41000.0, 42.0, 7893.5, 5028.4, 1460.7, 10.331 + 0.65, 41000.0, 46.0, 8638.7, 5252.7, 1701.3, 11.562 + 0.65, 41000.0, 48.0, 9004.5, 5357.9, 1829.8, 12.177 + 0.65, 41000.0, 50.0, 9369.0, 5462.0, 1957.7, 12.762 + 0.7, 15000.0, 21.0, 13112.0, 12479.9, 1130.1, 7.3244 + 0.7, 15000.0, 22.0, 13855.4, 12844.0, 1307.0, 8.2542 + 0.7, 15000.0, 24.0, 15285.0, 13515.0, 1648.6, 9.8351 + 0.7, 15000.0, 26.0, 16649.3, 14120.8, 1994.3, 11.901 + 0.7, 15000.0, 30.0, 19512.9, 15298.6, 2780.9, 14.827 + 0.7, 15000.0, 34.0, 22204.6, 16304.7, 3606.0, 17.362 + 0.7, 15000.0, 38.0, 24778.2, 17192.6, 4465.4, 19.588 + 0.7, 15000.0, 42.0, 27296.1, 18024.8, 5329.0, 23.483 + 0.7, 15000.0, 46.0, 29762.1, 18805.2, 6235.3, 46.81 + 0.7, 15000.0, 48.0, 30970.5, 19170.8, 6719.8, 59.383 + 0.7, 15000.0, 50.0, 32171.1, 19528.5, 7209.9, 68.703 + 0.7, 20000.0, 21.0, 10671.0, 10156.9, 912.4, 5.9185 + 0.7, 20000.0, 22.0, 11276.8, 10454.1, 1053.1, 6.8056 + 0.7, 20000.0, 24.0, 12440.5, 11000.8, 1323.8, 8.3011 + 0.7, 20000.0, 26.0, 13551.0, 11494.4, 1598.0, 9.6082 + 0.7, 20000.0, 30.0, 15882.3, 12454.6, 2221.7, 12.874 + 0.7, 20000.0, 34.0, 18073.4, 13274.7, 2876.5, 15.272 + 0.7, 20000.0, 38.0, 20168.3, 13998.5, 3557.9, 17.375 + 0.7, 20000.0, 42.0, 22217.1, 14676.3, 4242.1, 19.201 + 0.7, 20000.0, 46.0, 24224.9, 15312.9, 4960.5, 22.398 + 0.7, 20000.0, 48.0, 25208.3, 15610.7, 5344.4, 30.86 + 0.7, 20000.0, 50.0, 26185.8, 15902.7, 5731.7, 44.479 + 0.7, 25000.0, 21.0, 8610.5, 8195.8, 733.3, 4.7574 + 0.7, 25000.0, 22.0, 9099.7, 8436.2, 843.9, 5.3542 + 0.7, 25000.0, 24.0, 10039.4, 8878.3, 1056.5, 6.7662 + 0.7, 25000.0, 26.0, 10936.2, 9277.4, 1272.2, 7.9972 + 0.7, 25000.0, 30.0, 12818.5, 10053.9, 1762.2, 10.809 + 0.7, 25000.0, 34.0, 14587.3, 10716.9, 2276.5, 13.166 + 0.7, 25000.0, 38.0, 16278.4, 11302.1, 2811.5, 15.14 + 0.7, 25000.0, 42.0, 17932.2, 11850.1, 3349.2, 16.853 + 0.7, 25000.0, 46.0, 19552.5, 12364.7, 3912.9, 18.449 + 0.7, 25000.0, 48.0, 20346.0, 12605.2, 4213.9, 19.242 + 0.7, 25000.0, 50.0, 21135.9, 12842.2, 4516.7, 20.805 + 0.7, 30000.0, 21.0, 6883.1, 6551.6, 586.9, 7.7444 + 0.7, 30000.0, 22.0, 7275.0, 6744.6, 673.2, 5.7924 + 0.7, 30000.0, 24.0, 8027.3, 7099.1, 838.4, 5.2616 + 0.7, 30000.0, 26.0, 8744.9, 7418.9, 1005.9, 6.4147 + 0.7, 30000.0, 30.0, 10251.7, 8041.7, 1387.1, 8.5806 + 0.7, 30000.0, 34.0, 11667.2, 8573.2, 1787.1, 11.099 + 0.7, 30000.0, 38.0, 13020.3, 9042.3, 2203.0, 12.944 + 0.7, 30000.0, 42.0, 14343.5, 9481.5, 2621.7, 14.545 + 0.7, 30000.0, 46.0, 15639.9, 9894.0, 3059.8, 16.032 + 0.7, 30000.0, 48.0, 16274.9, 10087.0, 3293.1, 16.77 + 0.7, 30000.0, 50.0, 16906.9, 10277.0, 3528.3, 17.488 + 0.7, 35000.0, 21.0, 5445.9, 5183.5, 468.4, 10.726 + 0.7, 35000.0, 22.0, 5757.0, 5337.1, 535.0, 8.7976 + 0.7, 35000.0, 24.0, 6353.6, 5618.9, 661.7, 5.6702 + 0.7, 35000.0, 26.0, 6922.8, 5873.2, 791.0, 4.8981 + 0.7, 35000.0, 30.0, 8117.1, 6367.8, 1083.9, 6.9194 + 0.7, 35000.0, 34.0, 9239.1, 6790.1, 1391.6, 8.6731 + 0.7, 35000.0, 38.0, 10311.5, 7162.7, 1711.2, 10.844 + 0.7, 35000.0, 42.0, 11359.5, 7511.0, 2033.2, 12.334 + 0.7, 35000.0, 46.0, 12386.9, 7838.7, 2370.3, 13.714 + 0.7, 35000.0, 48.0, 12890.1, 7992.0, 2549.7, 14.401 + 0.7, 35000.0, 50.0, 13391.1, 8143.2, 2729.2, 15.063 + 0.7, 37000.0, 21.0, 4944.6, 4706.2, 429.8, 11.211 + 0.7, 37000.0, 22.0, 5227.7, 4846.2, 489.9, 9.3025 + 0.7, 37000.0, 24.0, 5770.2, 5102.7, 604.1, 6.2444 + 0.7, 37000.0, 26.0, 6287.7, 5334.1, 720.9, 4.4868 + 0.7, 37000.0, 30.0, 7373.4, 5784.0, 985.0, 6.4444 + 0.7, 37000.0, 34.0, 8393.3, 6168.3, 1262.6, 8.1407 + 0.7, 37000.0, 38.0, 9368.0, 6507.2, 1551.0, 10.209 + 0.7, 37000.0, 42.0, 10320.4, 6823.9, 1842.1, 11.651 + 0.7, 37000.0, 46.0, 11254.0, 7121.8, 2146.1, 12.982 + 0.7, 37000.0, 48.0, 11711.4, 7261.3, 2308.0, 13.645 + 0.7, 37000.0, 50.0, 12167.0, 7399.1, 2469.7, 14.282 + 0.7, 39000.0, 21.0, 4487.8, 4271.2, 396.9, 10.846 + 0.7, 39000.0, 22.0, 4745.4, 4398.8, 451.5, 8.9937 + 0.7, 39000.0, 24.0, 5238.7, 4632.3, 555.0, 6.0497 + 0.7, 39000.0, 26.0, 5709.1, 4842.7, 660.9, 4.3014 + 0.7, 39000.0, 30.0, 6696.0, 5252.1, 900.8, 6.1896 + 0.7, 39000.0, 34.0, 7623.1, 5601.6, 1152.7, 7.8201 + 0.7, 39000.0, 38.0, 8508.9, 5909.8, 1414.4, 9.8095 + 0.7, 39000.0, 42.0, 9374.1, 6197.4, 1678.7, 11.196 + 0.7, 39000.0, 46.0, 10222.7, 6468.4, 1955.0, 12.479 + 0.7, 39000.0, 48.0, 10638.4, 6595.3, 2101.9, 13.116 + 0.7, 39000.0, 50.0, 11052.6, 6720.7, 2248.2, 13.723 + 0.7, 41000.0, 21.0, 4072.9, 3876.1, 367.0, 10.5 + 0.7, 41000.0, 22.0, 4307.3, 3992.4, 416.6, 8.698 + 0.7, 41000.0, 24.0, 4756.0, 4204.9, 510.3, 5.8669 + 0.7, 41000.0, 26.0, 5183.6, 4396.4, 606.4, 4.1214 + 0.7, 41000.0, 30.0, 6080.8, 4768.8, 824.2, 5.9412 + 0.7, 41000.0, 34.0, 6923.7, 5086.9, 1052.9, 7.5111 + 0.7, 41000.0, 38.0, 7728.7, 5367.1, 1290.6, 9.4241 + 0.7, 41000.0, 42.0, 8515.0, 5628.6, 1531.1, 10.763 + 0.7, 41000.0, 46.0, 9286.2, 5874.9, 1781.7, 11.996 + 0.7, 41000.0, 48.0, 9664.1, 5990.4, 1914.9, 12.607 + 0.7, 41000.0, 50.0, 10040.5, 6104.4, 2047.5, 13.189 + 0.7, 43000.0, 21.0, 3695.7, 3516.9, 340.2, 10.182 + 0.7, 43000.0, 22.0, 3909.2, 3623.1, 385.1, 8.4342 + 0.7, 43000.0, 24.0, 4317.5, 3816.8, 469.8, 5.6921 + 0.7, 43000.0, 26.0, 4706.4, 3991.1, 557.2, 3.9488 + 0.7, 43000.0, 30.0, 5522.1, 4329.9, 754.8, 5.704 + 0.7, 43000.0, 34.0, 6288.3, 4619.3, 962.3, 7.2124 + 0.7, 43000.0, 38.0, 7019.9, 4874.0, 1178.2, 9.0518 + 0.7, 43000.0, 42.0, 7734.6, 5111.8, 1396.8, 10.344 + 0.7, 43000.0, 46.0, 8435.5, 5335.9, 1624.2, 11.53 + 0.7, 43000.0, 48.0, 8778.7, 5440.7, 1745.0, 12.116 + 0.7, 43000.0, 50.0, 9121.2, 5544.6, 1865.4, 12.676 + 0.75, 20000.0, 21.0, 12099.2, 11578.4, 993.4, 6.5843 + 0.75, 20000.0, 22.0, 12724.0, 11890.6, 1129.3, 7.3857 + 0.75, 20000.0, 24.0, 13920.6, 12462.1, 1410.5, 8.8599 + 0.75, 20000.0, 26.0, 15061.0, 12977.4, 1701.9, 10.327 + 0.75, 20000.0, 30.0, 17460.5, 13988.0, 2352.5, 13.498 + 0.75, 20000.0, 34.0, 19714.1, 14852.5, 3037.5, 15.9 + 0.75, 20000.0, 38.0, 21884.6, 15634.1, 3751.2, 18.01 + 0.75, 20000.0, 42.0, 24018.9, 16379.3, 4468.2, 19.85 + 0.75, 20000.0, 46.0, 26105.5, 17076.8, 5219.0, 27.25 + 0.75, 20000.0, 48.0, 27126.2, 17402.8, 5619.3, 39.528 + 0.75, 20000.0, 50.0, 28140.0, 17722.3, 6024.0, 53.01 + 0.75, 25000.0, 21.0, 9763.6, 9343.5, 797.1, 5.1492 + 0.75, 25000.0, 22.0, 10267.9, 9595.8, 903.1, 5.8999 + 0.75, 25000.0, 24.0, 11234.1, 10058.0, 1124.6, 7.2923 + 0.75, 25000.0, 26.0, 12154.7, 10474.5, 1353.8, 8.5338 + 0.75, 25000.0, 30.0, 14092.2, 11291.8, 1864.8, 11.499 + 0.75, 25000.0, 34.0, 15911.3, 11990.8, 2403.1, 13.753 + 0.75, 25000.0, 38.0, 17663.3, 12622.6, 2963.2, 15.732 + 0.75, 25000.0, 42.0, 19385.8, 13225.0, 3526.7, 17.457 + 0.75, 25000.0, 46.0, 21070.1, 13789.1, 4116.3, 19.057 + 0.75, 25000.0, 48.0, 21894.0, 14052.8, 4429.6, 19.847 + 0.75, 25000.0, 50.0, 22712.7, 14311.6, 4746.3, 24.56 + 0.75, 30000.0, 21.0, 7805.4, 7469.7, 636.6, 6.2175 + 0.75, 30000.0, 22.0, 8209.2, 7672.0, 718.6, 4.557 + 0.75, 30000.0, 24.0, 8982.7, 8042.7, 891.3, 5.7565 + 0.75, 30000.0, 26.0, 9719.7, 8376.8, 1069.8, 6.9217 + 0.75, 30000.0, 30.0, 11270.2, 9032.1, 1467.1, 9.0687 + 0.75, 30000.0, 34.0, 12725.6, 9592.3, 1885.5, 11.645 + 0.75, 30000.0, 38.0, 14127.3, 10098.7, 2320.9, 13.494 + 0.75, 30000.0, 42.0, 15505.2, 10581.3, 2759.3, 15.102 + 0.75, 30000.0, 46.0, 16852.7, 11033.5, 3217.1, 16.592 + 0.75, 30000.0, 48.0, 17511.6, 11244.9, 3461.0, 17.331 + 0.75, 30000.0, 50.0, 18167.3, 11452.9, 3705.8, 18.044 + 0.75, 35000.0, 21.0, 6176.3, 5910.6, 506.6, 9.2124 + 0.75, 35000.0, 22.0, 6496.8, 6071.7, 569.8, 7.5518 + 0.75, 35000.0, 24.0, 7110.0, 6366.1, 702.3, 4.5131 + 0.75, 35000.0, 26.0, 7694.4, 6631.6, 839.8, 5.3704 + 0.75, 35000.0, 30.0, 8923.6, 7152.1, 1145.3, 7.3736 + 0.75, 35000.0, 34.0, 10077.2, 7597.2, 1467.2, 9.1266 + 0.75, 35000.0, 38.0, 11187.9, 7999.4, 1801.8, 11.352 + 0.75, 35000.0, 42.0, 12279.4, 8382.4, 2139.1, 12.849 + 0.75, 35000.0, 46.0, 13347.0, 8741.4, 2491.2, 14.234 + 0.75, 35000.0, 48.0, 13869.4, 8909.5, 2678.5, 14.92 + 0.75, 35000.0, 50.0, 14389.1, 9075.0, 2865.5, 15.578 + 0.75, 37000.0, 21.0, 5608.1, 5366.7, 464.3, 9.7221 + 0.75, 37000.0, 22.0, 5899.7, 5513.5, 521.3, 8.0824 + 0.75, 37000.0, 24.0, 6457.4, 5781.4, 640.8, 5.1113 + 0.75, 37000.0, 26.0, 6988.6, 6023.0, 764.9, 4.9447 + 0.75, 37000.0, 30.0, 8106.0, 6496.6, 1040.5, 6.8848 + 0.75, 37000.0, 34.0, 9154.7, 6901.6, 1331.0, 8.58 + 0.75, 37000.0, 38.0, 10164.2, 7267.4, 1632.9, 10.7 + 0.75, 37000.0, 42.0, 11156.1, 7615.6, 1937.4, 12.149 + 0.75, 37000.0, 46.0, 12126.5, 7942.2, 2255.5, 13.485 + 0.75, 37000.0, 48.0, 12601.0, 8094.8, 2424.1, 14.146 + 0.75, 37000.0, 50.0, 13073.6, 8245.6, 2592.2, 14.778 + 0.75, 39000.0, 21.0, 5090.3, 4871.0, 428.1, 9.413 + 0.75, 39000.0, 22.0, 5355.6, 5004.7, 479.9, 7.8205 + 0.75, 39000.0, 24.0, 5862.7, 5248.6, 588.2, 4.959 + 0.75, 39000.0, 26.0, 6345.7, 5468.4, 700.9, 4.7432 + 0.75, 39000.0, 30.0, 7361.5, 5899.2, 951.1, 6.612 + 0.75, 39000.0, 34.0, 8314.7, 6267.5, 1214.7, 8.2426 + 0.75, 39000.0, 38.0, 9232.3, 6600.2, 1488.9, 10.284 + 0.75, 39000.0, 42.0, 10133.6, 6916.7, 1765.7, 11.679 + 0.75, 39000.0, 46.0, 11015.2, 7213.4, 2054.3, 12.964 + 0.75, 39000.0, 48.0, 11446.7, 7352.4, 2207.5, 13.6 + 0.75, 39000.0, 50.0, 11876.3, 7489.5, 2360.1, 14.206 + 0.75, 41000.0, 21.0, 4620.0, 4420.7, 395.3, 9.1163 + 0.75, 41000.0, 22.0, 4861.4, 4542.5, 442.3, 7.5735 + 0.75, 41000.0, 24.0, 5322.7, 4764.6, 540.6, 4.8099 + 0.75, 41000.0, 26.0, 5761.8, 4964.6, 642.9, 4.5487 + 0.75, 41000.0, 30.0, 6685.2, 5356.6, 869.9, 6.3495 + 0.75, 41000.0, 34.0, 7551.8, 5691.7, 1109.2, 7.9189 + 0.75, 41000.0, 38.0, 8385.8, 5994.3, 1358.1, 9.8824 + 0.75, 41000.0, 42.0, 9204.8, 6281.8, 1609.8, 11.227 + 0.75, 41000.0, 46.0, 10006.1, 6551.7, 1872.0, 12.464 + 0.75, 41000.0, 48.0, 10398.3, 6678.1, 2010.9, 13.074 + 0.75, 41000.0, 50.0, 10788.7, 6802.8, 2149.4, 13.657 + 0.75, 43000.0, 21.0, 4192.7, 4011.6, 365.5, 8.8388 + 0.75, 43000.0, 22.0, 4412.3, 4122.6, 408.2, 7.3458 + 0.75, 43000.0, 24.0, 4832.0, 4324.9, 497.1, 4.6778 + 0.75, 43000.0, 26.0, 5231.3, 4506.9, 590.1, 4.3594 + 0.75, 43000.0, 30.0, 6071.0, 4863.7, 796.3, 6.0969 + 0.75, 43000.0, 34.0, 6858.8, 5168.6, 1013.4, 7.606 + 0.75, 43000.0, 38.0, 7616.8, 5443.7, 1239.5, 9.4944 + 0.75, 43000.0, 42.0, 8361.0, 5705.0, 1468.3, 10.791 + 0.75, 43000.0, 46.0, 9089.4, 5950.4, 1706.1, 11.98 + 0.75, 43000.0, 48.0, 9445.7, 6065.4, 1832.3, 12.567 + 0.75, 43000.0, 50.0, 9800.8, 6179.0, 1958.1, 13.127 + 0.79, 20000.0, 21.0, 13316.7, 12788.5, 1056.2, 7.085 + 0.79, 20000.0, 22.0, 13958.5, 13113.3, 1191.3, 7.8437 + 0.79, 20000.0, 24.0, 15183.9, 13704.9, 1486.2, 9.3251 + 0.79, 20000.0, 26.0, 16353.4, 14240.4, 1788.3, 11.26 + 0.79, 20000.0, 30.0, 18814.0, 15292.3, 2465.9, 14.02 + 0.79, 20000.0, 34.0, 21136.0, 16205.7, 3176.5, 16.425 + 0.79, 20000.0, 38.0, 23387.7, 17048.6, 3921.0, 18.548 + 0.79, 20000.0, 42.0, 25599.2, 17851.6, 4668.4, 20.401 + 0.79, 20000.0, 46.0, 27757.9, 18601.6, 5449.7, 33.71 + 0.79, 20000.0, 48.0, 28812.4, 18951.7, 5865.5, 47.623 + 0.79, 20000.0, 50.0, 29859.3, 19294.4, 6286.5, 58.771 + 0.79, 25000.0, 21.0, 10746.2, 10320.3, 846.3, 5.6217 + 0.79, 25000.0, 22.0, 11264.8, 10583.2, 952.1, 6.3348 + 0.79, 25000.0, 24.0, 12254.3, 11061.5, 1184.1, 7.73 + 0.79, 25000.0, 26.0, 13198.3, 11494.4, 1421.7, 8.9669 + 0.79, 25000.0, 30.0, 15184.9, 12345.0, 1954.0, 11.988 + 0.79, 25000.0, 34.0, 17059.4, 13083.5, 2512.5, 14.244 + 0.79, 25000.0, 38.0, 18877.2, 13765.2, 3097.0, 16.235 + 0.79, 25000.0, 42.0, 20662.0, 14414.1, 3683.6, 17.97 + 0.79, 25000.0, 46.0, 22404.6, 15020.7, 4297.5, 19.578 + 0.79, 25000.0, 48.0, 23255.8, 15303.8, 4623.5, 21.98 + 0.79, 25000.0, 50.0, 24101.0, 15581.1, 4952.6, 29.779 + 0.79, 30000.0, 21.0, 8591.6, 8251.2, 675.0, 5.0944 + 0.79, 30000.0, 22.0, 9006.5, 8461.9, 756.7, 4.8532 + 0.79, 30000.0, 24.0, 9798.6, 8845.4, 937.1, 6.1642 + 0.79, 30000.0, 26.0, 10554.1, 9192.5, 1122.5, 7.3259 + 0.79, 30000.0, 30.0, 12143.7, 9874.3, 1536.0, 9.4741 + 0.79, 30000.0, 34.0, 13643.5, 10466.3, 1970.6, 12.102 + 0.79, 30000.0, 38.0, 15097.6, 11012.7, 2424.8, 13.96 + 0.79, 30000.0, 42.0, 16525.2, 11532.5, 2881.4, 15.578 + 0.79, 30000.0, 46.0, 17919.4, 12018.9, 3357.8, 17.075 + 0.79, 30000.0, 48.0, 18600.1, 12245.8, 3611.2, 17.815 + 0.79, 30000.0, 50.0, 19277.1, 12468.8, 3865.8, 18.526 + 0.79, 35000.0, 21.0, 6798.9, 6529.5, 536.1, 8.112 + 0.79, 35000.0, 22.0, 7128.1, 6697.1, 598.7, 6.5792 + 0.79, 35000.0, 24.0, 7756.4, 7002.1, 737.5, 4.6585 + 0.79, 35000.0, 26.0, 8355.2, 7277.7, 880.4, 5.7496 + 0.79, 35000.0, 30.0, 9615.4, 7819.4, 1198.4, 7.7528 + 0.79, 35000.0, 34.0, 10803.8, 8289.5, 1532.7, 9.805 + 0.79, 35000.0, 38.0, 11956.1, 8723.4, 1881.7, 11.784 + 0.79, 35000.0, 42.0, 13087.1, 9135.9, 2232.9, 13.288 + 0.79, 35000.0, 46.0, 14191.7, 9522.2, 2599.6, 14.681 + 0.79, 35000.0, 48.0, 14731.2, 9702.5, 2793.6, 15.367 + 0.79, 35000.0, 50.0, 15267.9, 9880.0, 2987.8, 16.024 + 0.79, 37000.0, 21.0, 6173.6, 5928.9, 490.9, 8.6418 + 0.79, 37000.0, 22.0, 6473.1, 6081.5, 547.1, 7.1362 + 0.79, 37000.0, 24.0, 7044.4, 6359.1, 672.3, 4.2757 + 0.79, 37000.0, 26.0, 7588.8, 6609.9, 801.5, 5.3123 + 0.79, 37000.0, 30.0, 8734.3, 7102.7, 1088.2, 7.2492 + 0.79, 37000.0, 34.0, 9814.5, 7530.3, 1389.7, 8.9444 + 0.79, 37000.0, 38.0, 10862.0, 7925.1, 1704.9, 11.117 + 0.79, 37000.0, 42.0, 11889.7, 8300.2, 2022.2, 12.573 + 0.79, 37000.0, 46.0, 12893.6, 8651.4, 2352.9, 13.917 + 0.79, 37000.0, 48.0, 13383.9, 8815.5, 2528.3, 14.579 + 0.79, 37000.0, 50.0, 13871.8, 8977.0, 2703.4, 15.214 + 0.79, 39000.0, 21.0, 5603.8, 5381.5, 452.2, 8.3724 + 0.79, 39000.0, 22.0, 5876.3, 5520.5, 503.1, 6.9121 + 0.79, 39000.0, 24.0, 6395.9, 5773.3, 616.7, 4.1333 + 0.79, 39000.0, 26.0, 6890.8, 6001.3, 734.2, 5.0969 + 0.79, 39000.0, 30.0, 7932.0, 6449.6, 994.3, 6.962 + 0.79, 39000.0, 34.0, 8914.2, 6838.7, 1268.4, 8.5965 + 0.79, 39000.0, 38.0, 9866.0, 7197.6, 1554.3, 10.685 + 0.79, 39000.0, 42.0, 10799.9, 7538.5, 1842.4, 12.088 + 0.79, 39000.0, 46.0, 11712.2, 7857.8, 2143.1, 13.382 + 0.79, 39000.0, 48.0, 12157.8, 8007.0, 2302.2, 14.017 + 0.79, 39000.0, 50.0, 12601.3, 8153.9, 2461.0, 14.625 + 0.79, 41000.0, 21.0, 5086.2, 4884.2, 417.1, 8.114 + 0.79, 41000.0, 22.0, 5334.1, 5010.8, 463.4, 6.7051 + 0.79, 41000.0, 24.0, 5806.8, 5241.1, 566.2, 3.9985 + 0.79, 41000.0, 26.0, 6256.7, 5448.5, 672.9, 4.8879 + 0.79, 41000.0, 30.0, 7203.5, 5856.5, 909.4, 6.6888 + 0.79, 41000.0, 34.0, 8096.2, 6210.4, 1158.0, 8.2594 + 0.79, 41000.0, 38.0, 8961.4, 6536.8, 1417.5, 10.269 + 0.79, 41000.0, 42.0, 9810.0, 6846.6, 1679.3, 11.621 + 0.79, 41000.0, 46.0, 10639.2, 7136.9, 1952.5, 12.865 + 0.79, 41000.0, 48.0, 11044.2, 7272.6, 2096.9, 13.476 + 0.79, 41000.0, 50.0, 11447.3, 7406.3, 2241.1, 14.062 + 0.8, 20000.0, 21.0, 13631.6, 13101.2, 1071.7, 7.2066 + 0.8, 20000.0, 22.0, 14277.9, 13429.2, 1206.9, 7.9564 + 0.8, 20000.0, 24.0, 15511.1, 14025.9, 1505.6, 9.4413 + 0.8, 20000.0, 26.0, 16688.8, 14567.1, 1810.3, 11.398 + 0.8, 20000.0, 30.0, 19165.5, 15629.4, 2495.5, 14.154 + 0.8, 20000.0, 34.0, 21509.9, 16559.4, 3213.1, 16.56 + 0.8, 20000.0, 38.0, 23783.7, 17418.7, 3966.3, 18.689 + 0.8, 20000.0, 42.0, 26016.0, 18236.5, 4721.8, 20.545 + 0.8, 20000.0, 46.0, 28194.2, 19000.4, 5512.1, 35.72 + 0.8, 20000.0, 48.0, 29257.3, 19356.5, 5932.0, 49.678 + 0.8, 20000.0, 50.0, 30313.1, 19704.9, 6356.8, 59.957 + 0.8, 25000.0, 21.0, 11000.5, 10572.8, 858.4, 5.7369 + 0.8, 25000.0, 22.0, 11522.8, 10838.4, 964.5, 6.4424 + 0.8, 25000.0, 24.0, 12518.5, 11320.9, 1199.4, 7.8407 + 0.8, 25000.0, 26.0, 13468.9, 11757.9, 1438.7, 9.0737 + 0.8, 25000.0, 30.0, 15468.6, 12617.0, 1976.9, 12.111 + 0.8, 25000.0, 34.0, 17361.2, 13369.0, 2541.0, 14.37 + 0.8, 25000.0, 38.0, 19196.7, 14063.9, 3132.5, 16.366 + 0.8, 25000.0, 42.0, 20998.4, 14725.0, 3725.7, 18.104 + 0.8, 25000.0, 46.0, 22756.7, 15342.6, 4346.4, 19.716 + 0.8, 25000.0, 48.0, 23614.9, 15630.5, 4675.4, 22.812 + 0.8, 25000.0, 50.0, 24467.2, 15912.5, 5007.9, 31.446 + 0.8, 30000.0, 21.0, 8794.9, 8453.1, 684.4, 4.8251 + 0.8, 30000.0, 22.0, 9212.8, 8666.0, 766.2, 4.9546 + 0.8, 30000.0, 24.0, 10009.9, 9052.9, 949.1, 6.2683 + 0.8, 30000.0, 26.0, 10770.5, 9403.4, 1135.9, 7.4268 + 0.8, 30000.0, 30.0, 12370.4, 10092.0, 1554.2, 9.6026 + 0.8, 30000.0, 34.0, 13884.6, 10694.7, 1993.0, 12.219 + 0.8, 30000.0, 38.0, 15352.8, 11251.5, 2452.3, 14.081 + 0.8, 30000.0, 42.0, 16793.7, 11781.1, 2913.8, 15.701 + 0.8, 30000.0, 46.0, 18200.3, 12276.3, 3395.6, 17.201 + 0.8, 30000.0, 48.0, 18886.8, 12507.0, 3651.1, 17.94 + 0.8, 30000.0, 50.0, 19569.5, 12734.0, 3908.4, 18.652 + 0.8, 35000.0, 21.0, 6959.9, 6689.4, 543.4, 7.8502 + 0.8, 35000.0, 22.0, 7291.5, 6858.8, 606.0, 6.339 + 0.8, 35000.0, 24.0, 7923.7, 7166.4, 746.6, 4.7559 + 0.8, 35000.0, 26.0, 8526.5, 7444.7, 890.7, 5.8442 + 0.8, 35000.0, 30.0, 9794.9, 7991.8, 1212.3, 7.8493 + 0.8, 35000.0, 34.0, 10994.6, 8470.3, 1549.7, 9.9967 + 0.8, 35000.0, 38.0, 12158.1, 8912.6, 1902.7, 11.895 + 0.8, 35000.0, 42.0, 13299.6, 9332.9, 2257.9, 13.403 + 0.8, 35000.0, 46.0, 14413.9, 9725.9, 2628.2, 14.796 + 0.8, 35000.0, 48.0, 14958.1, 9909.5, 2824.3, 15.483 + 0.8, 35000.0, 50.0, 15499.3, 10090.1, 3020.9, 16.142 + 0.8, 37000.0, 21.0, 6319.9, 6074.2, 497.4, 8.3849 + 0.8, 37000.0, 22.0, 6621.5, 6228.4, 553.7, 6.9012 + 0.8, 37000.0, 24.0, 7196.4, 6508.4, 680.6, 4.3469 + 0.8, 37000.0, 26.0, 7744.3, 6761.5, 810.7, 5.4024 + 0.8, 37000.0, 30.0, 8897.5, 7259.4, 1100.8, 7.3437 + 0.8, 37000.0, 34.0, 9988.0, 7694.8, 1405.5, 9.0829 + 0.8, 37000.0, 38.0, 11045.4, 8096.9, 1723.9, 11.224 + 0.8, 37000.0, 42.0, 12082.7, 8479.1, 2044.4, 12.682 + 0.8, 37000.0, 46.0, 13095.6, 8836.7, 2378.8, 14.03 + 0.8, 37000.0, 48.0, 13590.1, 9003.6, 2555.9, 14.692 + 0.8, 37000.0, 50.0, 14082.1, 9167.9, 2733.1, 15.327 + 0.8, 39000.0, 21.0, 5736.6, 5513.4, 458.1, 8.1251 + 0.8, 39000.0, 22.0, 6011.0, 5653.8, 509.0, 6.6908 + 0.8, 39000.0, 24.0, 6533.9, 5908.8, 624.2, 4.1644 + 0.8, 39000.0, 26.0, 7032.1, 6139.1, 742.6, 5.1849 + 0.8, 39000.0, 30.0, 8080.3, 6592.0, 1005.9, 7.0545 + 0.8, 39000.0, 34.0, 9071.6, 6988.0, 1282.5, 8.7133 + 0.8, 39000.0, 38.0, 10032.7, 7353.7, 1571.6, 10.789 + 0.8, 39000.0, 42.0, 10975.1, 7701.0, 1862.9, 12.194 + 0.8, 39000.0, 46.0, 11895.7, 8026.0, 2166.6, 13.49 + 0.8, 39000.0, 48.0, 12345.1, 8177.9, 2327.3, 14.126 + 0.8, 39000.0, 50.0, 12792.3, 8327.3, 2488.0, 14.736 + 0.8, 41000.0, 21.0, 5206.8, 5004.0, 422.5, 7.8759 + 0.8, 41000.0, 22.0, 5456.4, 5131.9, 468.7, 6.4921 + 0.8, 41000.0, 24.0, 5932.1, 5364.1, 573.0, 3.9876 + 0.8, 41000.0, 26.0, 6385.0, 5573.6, 680.6, 4.9727 + 0.8, 41000.0, 30.0, 7338.1, 5985.7, 919.7, 6.7752 + 0.8, 41000.0, 34.0, 8239.2, 6346.0, 1170.8, 8.3569 + 0.8, 41000.0, 38.0, 9112.8, 6678.6, 1433.3, 10.37 + 0.8, 41000.0, 42.0, 9969.4, 6994.3, 1697.9, 11.724 + 0.8, 41000.0, 46.0, 10805.8, 7289.8, 1973.9, 12.969 + 0.8, 41000.0, 48.0, 11214.3, 7427.8, 2119.8, 13.581 + 0.8, 41000.0, 50.0, 11620.8, 7563.8, 2265.5, 14.167 + 0.8, 43000.0, 21.0, 4725.6, 4541.3, 390.2, 7.6384 + 0.8, 43000.0, 22.0, 4952.6, 4657.7, 432.1, 6.3043 + 0.8, 43000.0, 24.0, 5385.5, 4869.4, 526.6, 3.8166 + 0.8, 43000.0, 26.0, 5797.4, 5060.1, 624.5, 4.7702 + 0.8, 43000.0, 30.0, 6664.0, 5435.0, 841.4, 6.5063 + 0.8, 43000.0, 34.0, 7483.3, 5762.9, 1069.3, 8.0181 + 0.8, 43000.0, 38.0, 8277.5, 6065.4, 1307.7, 9.9658 + 0.8, 43000.0, 42.0, 9055.9, 6352.3, 1548.6, 11.272 + 0.8, 43000.0, 46.0, 9816.3, 6621.1, 1799.0, 12.468 + 0.8, 43000.0, 48.0, 10187.6, 6746.6, 1931.5, 13.058 + 0.8, 43000.0, 50.0, 10556.9, 6870.2, 2063.5, 13.619 + 0.85, 20000.0, 21.0, 15269.7, 14726.9, 1148.4, 7.7963 + 0.85, 20000.0, 22.0, 15940.5, 15071.8, 1286.4, 8.5229 + 0.85, 20000.0, 24.0, 17216.3, 15696.2, 1605.0, 10.037 + 0.85, 20000.0, 26.0, 18437.2, 16265.7, 1923.0, 12.046 + 0.85, 20000.0, 30.0, 21018.2, 17399.0, 2650.6, 14.837 + 0.85, 20000.0, 34.0, 23493.4, 18426.4, 3408.9, 17.264 + 0.85, 20000.0, 38.0, 25884.8, 19370.2, 4206.9, 19.414 + 0.85, 20000.0, 42.0, 28229.3, 20267.0, 5007.6, 23.798 + 0.85, 20000.0, 46.0, 30511.4, 21101.3, 5843.9, 46.826 + 0.85, 20000.0, 48.0, 31623.3, 21489.2, 6287.4, 58.579 + 0.85, 20000.0, 50.0, 32726.4, 21868.7, 6737.1, 67.29 + 0.85, 25000.0, 21.0, 12322.9, 11885.2, 918.3, 6.2921 + 0.85, 25000.0, 22.0, 12864.9, 12164.6, 1027.0, 6.9769 + 0.85, 25000.0, 24.0, 13894.8, 12669.2, 1277.4, 8.3905 + 0.85, 25000.0, 26.0, 14880.2, 13129.4, 1527.5, 9.6187 + 0.85, 25000.0, 30.0, 16963.6, 14045.5, 2098.8, 12.751 + 0.85, 25000.0, 34.0, 18961.6, 14876.3, 2695.0, 15.027 + 0.85, 25000.0, 38.0, 20891.7, 15639.3, 3321.4, 17.042 + 0.85, 25000.0, 42.0, 22783.5, 16363.9, 3949.4, 18.8 + 0.85, 25000.0, 46.0, 24625.9, 17039.0, 4606.3, 21.726 + 0.85, 25000.0, 48.0, 25523.3, 17352.8, 4953.5, 29.253 + 0.85, 25000.0, 50.0, 26413.9, 17659.8, 5304.8, 41.448 + 0.85, 30000.0, 21.0, 9852.7, 9503.0, 730.5, 4.817 + 0.85, 30000.0, 22.0, 10286.3, 9726.8, 814.8, 5.4569 + 0.85, 30000.0, 24.0, 11110.8, 10131.7, 1009.8, 6.7844 + 0.85, 30000.0, 26.0, 11899.3, 10500.5, 1204.7, 7.9341 + 0.85, 30000.0, 30.0, 13566.3, 11234.9, 1649.0, 10.684 + 0.85, 30000.0, 34.0, 15164.4, 11900.5, 2112.4, 12.829 + 0.85, 30000.0, 38.0, 16708.5, 12512.1, 2599.3, 14.708 + 0.85, 30000.0, 42.0, 18221.3, 13092.4, 3087.7, 16.346 + 0.85, 30000.0, 46.0, 19695.1, 13633.6, 3597.6, 17.86 + 0.85, 30000.0, 48.0, 20413.3, 13885.5, 3867.4, 18.603 + 0.85, 30000.0, 50.0, 21126.4, 14132.3, 4139.7, 19.317 + 0.85, 35000.0, 21.0, 7797.5, 7520.8, 578.7, 6.6087 + 0.85, 35000.0, 22.0, 8141.8, 7699.1, 643.4, 5.1541 + 0.85, 35000.0, 24.0, 8795.7, 8020.9, 793.4, 5.2408 + 0.85, 35000.0, 26.0, 9420.6, 8313.7, 943.8, 6.3186 + 0.85, 35000.0, 30.0, 10741.8, 8897.0, 1284.8, 8.3419 + 0.85, 35000.0, 34.0, 12008.4, 9425.6, 1641.7, 10.725 + 0.85, 35000.0, 38.0, 13232.1, 9911.4, 2016.1, 12.477 + 0.85, 35000.0, 42.0, 14430.9, 10372.2, 2391.9, 13.999 + 0.85, 35000.0, 46.0, 15598.6, 10802.0, 2783.9, 15.406 + 0.85, 35000.0, 48.0, 16167.5, 11002.0, 2990.7, 16.095 + 0.85, 35000.0, 50.0, 16732.6, 11198.0, 3199.2, 16.758 + 0.85, 37000.0, 21.0, 7080.7, 6829.3, 529.2, 7.1696 + 0.85, 37000.0, 22.0, 7393.9, 6991.7, 587.4, 5.7449 + 0.85, 37000.0, 24.0, 7988.5, 7284.6, 722.8, 4.8169 + 0.85, 37000.0, 26.0, 8556.5, 7551.0, 858.6, 5.8624 + 0.85, 37000.0, 30.0, 9757.7, 8081.8, 1166.5, 7.8217 + 0.85, 37000.0, 34.0, 10908.7, 8562.5, 1488.5, 10.073 + 0.85, 37000.0, 38.0, 12020.9, 9004.3, 1826.1, 11.786 + 0.85, 37000.0, 42.0, 13110.2, 9423.3, 2165.5, 13.259 + 0.85, 37000.0, 46.0, 14171.0, 9813.8, 2518.9, 14.617 + 0.85, 37000.0, 48.0, 14688.6, 9996.1, 2705.6, 15.283 + 0.85, 37000.0, 50.0, 15202.3, 10174.6, 2893.4, 15.924 + 0.85, 39000.0, 21.0, 6427.5, 6199.1, 487.0, 6.9546 + 0.85, 39000.0, 22.0, 6712.2, 6346.7, 539.4, 5.589 + 0.85, 39000.0, 24.0, 7253.1, 6613.6, 662.4, 4.6165 + 0.85, 39000.0, 26.0, 7769.4, 6855.8, 785.8, 5.6258 + 0.85, 39000.0, 30.0, 8861.3, 7338.7, 1065.5, 7.514 + 0.85, 39000.0, 34.0, 9907.4, 7775.8, 1357.5, 9.6651 + 0.85, 39000.0, 38.0, 10918.3, 8177.7, 1664.3, 11.33 + 0.85, 39000.0, 42.0, 11908.0, 8558.4, 1972.4, 12.748 + 0.85, 39000.0, 46.0, 12872.3, 8913.7, 2293.5, 14.056 + 0.85, 39000.0, 48.0, 13342.3, 9079.2, 2463.0, 14.695 + 0.85, 39000.0, 50.0, 13809.4, 9241.8, 2633.5, 15.311 + 0.9, 35000.0, 21.0, 8689.9, 8405.4, 612.6, 5.4642 + 0.9, 35000.0, 22.0, 9048.1, 8592.9, 681.7, 4.4604 + 0.9, 35000.0, 24.0, 9727.3, 8930.8, 841.5, 5.7208 + 0.9, 35000.0, 26.0, 10383.2, 9245.3, 999.3, 6.7969 + 0.9, 35000.0, 30.0, 11785.1, 9888.5, 1365.6, 8.8636 + 0.9, 35000.0, 34.0, 13126.8, 10471.6, 1745.1, 11.33 + 0.9, 35000.0, 38.0, 14418.8, 11005.1, 2142.8, 13.096 + 0.9, 35000.0, 42.0, 15682.3, 11509.9, 2543.0, 14.64 + 0.9, 35000.0, 46.0, 16909.5, 11978.5, 2959.3, 16.059 + 0.9, 35000.0, 48.0, 17506.0, 12195.7, 3179.8, 16.757 + 0.9, 35000.0, 50.0, 18098.7, 12409.1, 3401.9, 17.426 + 0.9, 37000.0, 21.0, 7891.3, 7632.9, 559.6, 6.0554 + 0.9, 37000.0, 22.0, 8217.1, 7803.6, 621.9, 4.6273 + 0.9, 37000.0, 24.0, 8834.9, 8111.3, 766.2, 5.2826 + 0.9, 37000.0, 26.0, 9431.0, 8397.2, 908.7, 6.3254 + 0.9, 37000.0, 30.0, 10705.5, 8982.6, 1239.4, 8.326 + 0.9, 37000.0, 34.0, 11924.9, 9512.8, 1581.3, 10.673 + 0.9, 37000.0, 38.0, 13099.4, 9998.1, 1940.8, 12.386 + 0.9, 37000.0, 42.0, 14247.6, 10457.1, 2302.0, 13.878 + 0.9, 37000.0, 46.0, 15363.1, 10883.5, 2678.2, 15.252 + 0.9, 37000.0, 48.0, 15905.5, 11081.3, 2876.5, 15.923 + 0.9, 37000.0, 50.0, 16443.8, 11275.0, 3076.2, 16.569 + 0.9, 39000.0, 21.0, 7163.6, 6928.7, 514.4, 5.8837 + 0.9, 39000.0, 22.0, 7459.9, 7084.2, 570.9, 4.5067 + 0.9, 39000.0, 24.0, 8021.6, 7364.1, 701.6, 5.0624 + 0.9, 39000.0, 26.0, 8563.7, 7624.5, 831.4, 6.0727 + 0.9, 39000.0, 30.0, 9722.3, 8156.9, 1131.6, 7.9996 + 0.9, 39000.0, 34.0, 10830.8, 8639.2, 1442.2, 10.258 + 0.9, 39000.0, 38.0, 11898.0, 9080.3, 1768.2, 11.906 + 0.9, 39000.0, 42.0, 12941.4, 9497.6, 2096.6, 13.345 + 0.9, 39000.0, 46.0, 13955.2, 9885.2, 2438.2, 14.667 + 0.9, 39000.0, 48.0, 14447.9, 10064.9, 2618.2, 15.313 + 0.9, 39000.0, 50.0, 14937.5, 10241.3, 2799.5, 15.933 diff --git a/aviary/models/engines/turbofan_28k.deck b/aviary/models/engines/turbofan_28k.deck deleted file mode 100644 index 4af2acf7cb..0000000000 --- a/aviary/models/engines/turbofan_28k.deck +++ /dev/null @@ -1,1114 +0,0 @@ -# FLOPS-derived engine deck converted from turbofan_28_ENGDEK - -Mach_Number (unitless), Altitude (ft), Throttle (unitless), Gross_Thrust (lbf), Ram_Drag (lbf), Fuel_Flow (lb/h), NOx_Rate (lb/h) - 0.0, 0.0, 21.0, 1446.4, 0.0, 842.2, 4.7876 - 0.0, 0.0, 22.0, 2314.3, 0.0, 976.0, 5.1926 - 0.0, 0.0, 24.0, 4049.9, 0.0, 1281.0, 6.6532 - 0.0, 0.0, 26.0, 5785.6, 0.0, 1659.9, 8.2234 - 0.0, 0.0, 30.0, 9642.7, 0.0, 2621.6, 12.0946 - 0.0, 0.0, 34.0, 13499.8, 0.0, 3673.3, 15.0321 - 0.0, 0.0, 38.0, 17356.9, 0.0, 4795.2, 17.5877 - 0.0, 0.0, 42.0, 21214.0, 0.0, 5979.1, 19.8547 - 0.0, 0.0, 46.0, 25071.1, 0.0, 7258.1, 33.3976 - 0.0, 0.0, 48.0, 26999.7, 0.0, 7932.6, 49.2185 - 0.0, 0.0, 50.0, 28928.1, 0.0, 8662.3, 61.9894 - 0.0, 2000.0, 21.0, 1446.4, 0.0, 781.8, 5.2521 - 0.0, 2000.0, 22.0, 2314.2, 0.0, 914.2, 5.1431 - 0.0, 2000.0, 24.0, 4049.9, 0.0, 1220.2, 6.7284 - 0.0, 2000.0, 26.0, 5785.6, 0.0, 1608.2, 8.4472 - 0.0, 2000.0, 30.0, 9642.7, 0.0, 2572.5, 12.5205 - 0.0, 2000.0, 34.0, 13499.7, 0.0, 3624.6, 15.6007 - 0.0, 2000.0, 38.0, 17356.8, 0.0, 4748.2, 18.2407 - 0.0, 2000.0, 42.0, 21213.8, 0.0, 5953.1, 20.6168 - 0.0, 2000.0, 46.0, 25070.8, 0.0, 7274.3, 46.5192 - 0.0, 2000.0, 48.0, 26999.7, 0.0, 8005.4, 61.6004 - 0.0, 2000.0, 50.0, 28928.0, 0.0, 8769.0, 72.5104 - 0.0, 5000.0, 21.0, 1338.1, 0.0, 706.8, 6.8008 - 0.0, 5000.0, 22.0, 2140.9, 0.0, 828.3, 5.03 - 0.0, 5000.0, 24.0, 3746.7, 0.0, 1111.0, 6.2319 - 0.0, 5000.0, 26.0, 5352.3, 0.0, 1469.9, 7.9885 - 0.0, 5000.0, 30.0, 8920.6, 0.0, 2355.4, 12.0275 - 0.0, 5000.0, 34.0, 12488.9, 0.0, 3323.4, 15.1312 - 0.0, 5000.0, 38.0, 16057.1, 0.0, 4353.1, 17.7742 - 0.0, 5000.0, 42.0, 19625.3, 0.0, 5473.5, 20.1814 - 0.0, 5000.0, 46.0, 23193.5, 0.0, 6708.4, 39.1314 - 0.0, 5000.0, 48.0, 24977.9, 0.0, 7391.9, 57.3145 - 0.0, 5000.0, 50.0, 26761.8, 0.0, 8104.6, 69.2582 - 0.1, 0.0, 21.0, 2503.9, 1057.5, 905.8, 4.7726 - 0.1, 0.0, 22.0, 3575.1, 1260.9, 1088.1, 5.7209 - 0.1, 0.0, 24.0, 5626.3, 1576.4, 1525.4, 7.6905 - 0.1, 0.0, 26.0, 7615.0, 1829.5, 2001.1, 9.4545 - 0.1, 0.0, 30.0, 11922.9, 2280.3, 3129.8, 13.5965 - 0.1, 0.0, 34.0, 16145.2, 2645.4, 4326.3, 16.5878 - 0.1, 0.0, 38.0, 20316.5, 2959.7, 5587.6, 19.1578 - 0.1, 0.0, 42.0, 24452.2, 3238.4, 6932.0, 26.8701 - 0.1, 0.0, 46.0, 28560.1, 3489.2, 8389.7, 57.6579 - 0.1, 0.0, 48.0, 30603.9, 3604.5, 9194.3, 69.2477 - 0.1, 0.0, 50.0, 32642.3, 3714.3, 10032.8, 77.4403 - 0.1, 2000.0, 21.0, 2330.3, 984.5, 824.4, 4.924 - 0.1, 2000.0, 22.0, 3327.1, 1173.8, 991.2, 5.5336 - 0.1, 2000.0, 24.0, 5235.7, 1467.4, 1391.5, 7.5234 - 0.1, 2000.0, 26.0, 7086.3, 1702.9, 1826.8, 9.2983 - 0.1, 2000.0, 30.0, 11094.9, 2122.6, 2859.5, 13.4284 - 0.1, 2000.0, 34.0, 15023.5, 2462.3, 3960.7, 16.4467 - 0.1, 2000.0, 38.0, 18904.9, 2754.8, 5117.1, 19.0209 - 0.1, 2000.0, 42.0, 22752.9, 3013.8, 6361.1, 24.7835 - 0.1, 2000.0, 46.0, 26574.2, 3246.4, 7721.3, 56.6411 - 0.1, 2000.0, 48.0, 28476.4, 3353.7, 8462.9, 68.5093 - 0.1, 2000.0, 50.0, 30372.6, 3455.8, 9235.9, 77.0405 - 0.1, 5000.0, 21.0, 2084.6, 880.6, 738.0, 6.5816 - 0.1, 5000.0, 22.0, 2976.4, 1050.0, 884.8, 4.9156 - 0.1, 5000.0, 24.0, 4684.1, 1312.8, 1237.6, 6.8861 - 0.1, 5000.0, 26.0, 6339.8, 1523.6, 1621.7, 8.6447 - 0.1, 5000.0, 30.0, 9926.1, 1899.3, 2532.7, 12.6499 - 0.1, 5000.0, 34.0, 13440.9, 2203.3, 3503.2, 15.6314 - 0.1, 5000.0, 38.0, 16913.5, 2465.1, 4524.4, 18.1789 - 0.1, 5000.0, 42.0, 20356.6, 2696.9, 5621.1, 20.4797 - 0.1, 5000.0, 46.0, 23775.6, 2905.2, 6820.1, 42.0756 - 0.1, 5000.0, 48.0, 25476.8, 3001.2, 7474.2, 58.5348 - 0.1, 5000.0, 50.0, 27173.2, 3092.6, 8156.2, 69.8119 - 0.1, 10000.0, 21.0, 1721.9, 727.2, 612.6, 9.402 - 0.1, 10000.0, 22.0, 2458.8, 867.2, 730.7, 7.2271 - 0.1, 10000.0, 24.0, 3869.8, 1084.5, 1014.8, 5.7309 - 0.1, 10000.0, 26.0, 5237.7, 1258.8, 1324.4, 7.4445 - 0.1, 10000.0, 30.0, 8200.9, 1569.4, 2059.1, 10.9423 - 0.1, 10000.0, 34.0, 11104.9, 1820.8, 2841.8, 14.0989 - 0.1, 10000.0, 38.0, 13974.0, 2037.3, 3665.3, 16.5692 - 0.1, 10000.0, 42.0, 16818.6, 2229.1, 4548.6, 18.7998 - 0.1, 10000.0, 46.0, 19643.6, 2401.3, 5515.6, 21.9454 - 0.1, 10000.0, 48.0, 21049.0, 2480.6, 6042.3, 33.2727 - 0.1, 10000.0, 50.0, 22450.7, 2556.3, 6592.6, 50.9804 - 0.2, 0.0, 21.0, 3984.0, 2660.5, 927.8, 4.88 - 0.2, 0.0, 22.0, 5132.8, 3015.2, 1158.3, 6.0773 - 0.2, 0.0, 24.0, 7290.5, 3584.8, 1655.7, 8.2264 - 0.2, 0.0, 26.0, 9344.4, 4050.6, 2168.2, 10.048 - 0.2, 0.0, 30.0, 13714.4, 4891.5, 3335.6, 14.1832 - 0.2, 0.0, 34.0, 17928.1, 5575.9, 4564.4, 17.1365 - 0.2, 0.0, 38.0, 22048.5, 6167.1, 5839.6, 19.6518 - 0.2, 0.0, 42.0, 26104.0, 6693.4, 7176.2, 31.254 - 0.2, 0.0, 46.0, 30105.5, 7165.7, 8625.1, 60.8012 - 0.2, 0.0, 48.0, 32088.4, 7383.6, 9408.5, 71.4541 - 0.2, 0.0, 50.0, 34059.1, 7590.1, 10231.7, 78.754 - 0.2, 2000.0, 21.0, 3705.8, 2475.9, 844.5, 4.8026 - 0.2, 2000.0, 22.0, 4773.5, 2805.8, 1055.1, 5.8928 - 0.2, 2000.0, 24.0, 6779.2, 3335.6, 1509.9, 8.0591 - 0.2, 2000.0, 26.0, 8688.2, 3768.8, 1978.1, 9.8731 - 0.2, 2000.0, 30.0, 12750.0, 4551.0, 3045.6, 14.0129 - 0.2, 2000.0, 34.0, 16665.9, 5187.3, 4175.2, 16.9893 - 0.2, 2000.0, 38.0, 20495.5, 5737.3, 5341.9, 19.5044 - 0.2, 2000.0, 42.0, 24264.1, 6226.1, 6575.1, 28.1727 - 0.2, 2000.0, 46.0, 27981.8, 6663.9, 7924.2, 59.5213 - 0.2, 2000.0, 48.0, 29823.9, 6866.3, 8646.0, 70.5775 - 0.2, 2000.0, 50.0, 31655.3, 7058.3, 9403.9, 78.2786 - 0.2, 5000.0, 21.0, 3315.0, 2214.7, 755.5, 6.435 - 0.2, 5000.0, 22.0, 4270.4, 2510.0, 941.0, 5.268 - 0.2, 5000.0, 24.0, 6064.9, 2984.3, 1342.0, 7.4149 - 0.2, 5000.0, 26.0, 7773.0, 3372.1, 1755.4, 9.2124 - 0.2, 5000.0, 30.0, 11407.0, 4072.2, 2696.9, 13.2256 - 0.2, 5000.0, 34.0, 14910.5, 4641.7, 3693.1, 16.1681 - 0.2, 5000.0, 38.0, 18336.7, 5134.0, 4722.6, 18.6548 - 0.2, 5000.0, 42.0, 21708.3, 5571.5, 5810.0, 20.9007 - 0.2, 5000.0, 46.0, 25034.4, 5963.4, 6999.7, 46.548 - 0.2, 5000.0, 48.0, 26682.2, 6144.6, 7635.7, 60.7973 - 0.2, 5000.0, 50.0, 28321.1, 6316.5, 8304.7, 71.4843 - 0.2, 10000.0, 21.0, 2738.0, 1829.0, 626.4, 9.2804 - 0.2, 10000.0, 22.0, 3527.6, 2073.3, 775.5, 6.4797 - 0.2, 10000.0, 24.0, 5010.5, 2465.5, 1098.5, 6.2413 - 0.2, 10000.0, 26.0, 6421.8, 2786.1, 1431.7, 7.9908 - 0.2, 10000.0, 30.0, 9424.6, 3365.1, 2191.4, 11.7561 - 0.2, 10000.0, 34.0, 12319.4, 3836.1, 2994.6, 14.6148 - 0.2, 10000.0, 38.0, 15150.2, 4243.1, 3825.2, 17.0282 - 0.2, 10000.0, 42.0, 17936.1, 4604.8, 4701.2, 19.1798 - 0.2, 10000.0, 46.0, 20683.4, 4929.0, 5659.9, 23.6308 - 0.2, 10000.0, 48.0, 22045.5, 5078.8, 6173.0, 36.4956 - 0.2, 10000.0, 50.0, 23399.5, 5221.0, 6712.2, 53.4919 - 0.25, 0.0, 21.0, 4982.9, 3711.0, 967.7, 5.1347 - 0.25, 0.0, 22.0, 6155.9, 4120.9, 1221.5, 6.4157 - 0.25, 0.0, 24.0, 8353.0, 4791.8, 1741.2, 8.5818 - 0.25, 0.0, 26.0, 10434.6, 5347.2, 2267.6, 10.7481 - 0.25, 0.0, 30.0, 14837.1, 6358.1, 3458.3, 14.5379 - 0.25, 0.0, 34.0, 19055.8, 7185.2, 4700.4, 17.4532 - 0.25, 0.0, 38.0, 23164.2, 7901.7, 5979.8, 19.9304 - 0.25, 0.0, 42.0, 27194.4, 8540.4, 7318.7, 34.2788 - 0.25, 0.0, 46.0, 31158.1, 9112.7, 8772.0, 62.9527 - 0.25, 0.0, 48.0, 33119.2, 9377.6, 9547.4, 72.8167 - 0.25, 0.0, 50.0, 35064.8, 9627.7, 10368.8, 79.61 - 0.25, 2000.0, 21.0, 4635.4, 3453.6, 881.2, 4.9403 - 0.25, 2000.0, 22.0, 5725.7, 3834.8, 1113.2, 6.2358 - 0.25, 2000.0, 24.0, 7767.9, 4458.7, 1587.7, 8.4148 - 0.25, 2000.0, 26.0, 9702.8, 4975.4, 2068.9, 10.3133 - 0.25, 2000.0, 30.0, 13794.8, 5915.8, 3157.8, 14.3694 - 0.25, 2000.0, 34.0, 17715.3, 6684.5, 4299.7, 17.3076 - 0.25, 2000.0, 38.0, 21533.5, 7351.2, 5470.6, 19.7854 - 0.25, 2000.0, 42.0, 25278.1, 7944.4, 6705.3, 30.7493 - 0.25, 2000.0, 46.0, 28960.8, 8474.8, 8057.1, 61.504 - 0.25, 2000.0, 48.0, 30782.4, 8720.7, 8773.3, 71.9783 - 0.25, 2000.0, 50.0, 32590.3, 8953.2, 9529.4, 79.1712 - 0.25, 5000.0, 21.0, 4146.8, 3089.4, 787.7, 5.8398 - 0.25, 5000.0, 22.0, 5122.4, 3430.7, 992.0, 5.6074 - 0.25, 5000.0, 24.0, 6949.9, 3989.3, 1411.0, 7.7697 - 0.25, 5000.0, 26.0, 8681.0, 4451.7, 1835.5, 9.5548 - 0.25, 5000.0, 30.0, 12342.2, 5293.4, 2795.6, 13.5758 - 0.25, 5000.0, 34.0, 15850.1, 5981.6, 3803.0, 16.4816 - 0.25, 5000.0, 38.0, 19266.4, 6578.4, 4836.6, 18.9321 - 0.25, 5000.0, 42.0, 22617.1, 7109.4, 5925.2, 21.9946 - 0.25, 5000.0, 46.0, 25911.5, 7584.2, 7117.3, 49.402 - 0.25, 5000.0, 48.0, 27541.0, 7804.3, 7748.5, 62.5764 - 0.25, 5000.0, 50.0, 29158.9, 8012.2, 8415.7, 72.7322 - 0.25, 10000.0, 21.0, 3424.9, 2551.5, 652.1, 8.6939 - 0.25, 10000.0, 22.0, 4231.3, 2833.9, 816.4, 5.6904 - 0.25, 10000.0, 24.0, 5741.3, 3295.8, 1153.9, 6.5846 - 0.25, 10000.0, 26.0, 7171.8, 3678.2, 1496.8, 8.3269 - 0.25, 10000.0, 30.0, 10196.9, 4374.2, 2270.9, 12.0944 - 0.25, 10000.0, 34.0, 13095.1, 4943.3, 3083.3, 14.918 - 0.25, 10000.0, 38.0, 15917.5, 5436.7, 3916.9, 17.295 - 0.25, 10000.0, 42.0, 18685.9, 5875.8, 4794.1, 19.4143 - 0.25, 10000.0, 46.0, 21407.5, 6268.5, 5754.5, 25.0166 - 0.25, 10000.0, 48.0, 22754.0, 6450.6, 6263.1, 38.8691 - 0.25, 10000.0, 50.0, 24090.7, 6622.7, 6801.4, 55.311 - 0.3, 0.0, 21.0, 6173.4, 4945.6, 1022.8, 5.4835 - 0.3, 0.0, 22.0, 7364.1, 5399.7, 1289.1, 6.7761 - 0.3, 0.0, 24.0, 9594.3, 6156.5, 1828.9, 8.945 - 0.3, 0.0, 26.0, 11702.0, 6790.9, 2370.2, 11.3695 - 0.3, 0.0, 30.0, 16141.2, 7956.0, 3586.7, 14.9079 - 0.3, 0.0, 34.0, 20374.2, 8914.9, 4845.9, 17.7911 - 0.3, 0.0, 38.0, 24482.0, 9748.6, 6136.4, 20.2415 - 0.3, 0.0, 42.0, 28498.9, 10491.9, 7487.2, 38.1853 - 0.3, 0.0, 46.0, 32440.2, 11158.6, 8946.6, 65.3539 - 0.3, 0.0, 48.0, 34385.6, 11467.0, 9722.6, 74.4559 - 0.3, 0.0, 50.0, 36314.3, 11758.7, 10541.1, 80.6075 - 0.3, 2000.0, 21.0, 5743.4, 4602.6, 931.5, 5.2941 - 0.3, 2000.0, 22.0, 6850.3, 5024.9, 1175.0, 6.6001 - 0.3, 2000.0, 24.0, 8923.2, 5728.8, 1668.1, 8.7823 - 0.3, 2000.0, 26.0, 10882.3, 6318.8, 2161.9, 11.0244 - 0.3, 2000.0, 30.0, 15008.5, 7402.8, 3275.4, 14.742 - 0.3, 2000.0, 34.0, 18942.1, 8294.0, 4433.1, 17.6473 - 0.3, 2000.0, 38.0, 22759.9, 9069.6, 5614.1, 20.0977 - 0.3, 2000.0, 42.0, 26492.4, 9759.9, 6860.5, 34.3047 - 0.3, 2000.0, 46.0, 30152.8, 10377.9, 8215.0, 63.8559 - 0.3, 2000.0, 48.0, 31959.4, 10663.8, 8934.3, 73.6791 - 0.3, 2000.0, 50.0, 33752.0, 10934.9, 9687.3, 80.2171 - 0.3, 5000.0, 21.0, 5137.9, 4117.3, 832.0, 5.0092 - 0.3, 5000.0, 22.0, 6128.4, 4495.5, 1046.5, 5.9682 - 0.3, 5000.0, 24.0, 7983.1, 5125.5, 1481.4, 8.1293 - 0.3, 5000.0, 26.0, 9735.9, 5653.8, 1917.6, 9.9046 - 0.3, 5000.0, 30.0, 13427.5, 6623.9, 2899.2, 13.9423 - 0.3, 5000.0, 34.0, 16946.8, 7421.7, 3920.4, 16.8161 - 0.3, 5000.0, 38.0, 20362.5, 8115.9, 4962.2, 19.2379 - 0.3, 5000.0, 42.0, 23701.7, 8733.8, 6061.4, 23.5209 - 0.3, 5000.0, 46.0, 26976.2, 9286.8, 7256.0, 52.5299 - 0.3, 5000.0, 48.0, 28592.9, 9543.0, 7890.1, 64.7543 - 0.3, 5000.0, 50.0, 30196.6, 9785.7, 8554.4, 74.2115 - 0.3, 10000.0, 21.0, 4243.8, 3400.8, 687.6, 7.8677 - 0.3, 10000.0, 22.0, 5062.5, 3713.6, 860.4, 4.908 - 0.3, 10000.0, 24.0, 6595.3, 4234.8, 1211.0, 6.9375 - 0.3, 10000.0, 26.0, 8043.8, 4671.6, 1563.1, 8.6667 - 0.3, 10000.0, 30.0, 11094.2, 5473.9, 2354.8, 12.4504 - 0.3, 10000.0, 34.0, 14002.0, 6133.6, 3177.8, 15.2398 - 0.3, 10000.0, 38.0, 16824.1, 6707.5, 4018.5, 17.5905 - 0.3, 10000.0, 42.0, 19583.3, 7218.6, 4904.6, 19.6927 - 0.3, 10000.0, 46.0, 22288.8, 7676.1, 5867.0, 26.9467 - 0.3, 10000.0, 48.0, 23624.2, 7887.9, 6378.4, 42.0826 - 0.3, 10000.0, 50.0, 24949.6, 8088.6, 6913.7, 57.381 - 0.3, 15000.0, 21.0, 3479.6, 2788.1, 567.1, 10.753 - 0.3, 15000.0, 22.0, 4151.5, 3045.2, 705.0, 7.7596 - 0.3, 15000.0, 24.0, 5409.3, 3473.3, 985.3, 5.6485 - 0.3, 15000.0, 26.0, 6597.7, 3831.9, 1267.2, 7.317 - 0.3, 15000.0, 30.0, 9100.3, 4490.8, 1900.3, 10.2364 - 0.3, 15000.0, 34.0, 11486.0, 5032.6, 2558.6, 13.4803 - 0.3, 15000.0, 38.0, 13801.0, 5503.8, 3231.5, 15.7326 - 0.3, 15000.0, 42.0, 16064.5, 5923.6, 3939.7, 17.7439 - 0.3, 15000.0, 46.0, 18284.0, 6299.3, 4708.7, 19.6831 - 0.3, 15000.0, 48.0, 19379.7, 6473.2, 5117.8, 21.3254 - 0.3, 15000.0, 50.0, 20466.5, 6637.9, 5546.1, 30.4095 - 0.35, 0.0, 21.0, 7566.3, 6374.0, 1096.3, 5.9318 - 0.35, 0.0, 22.0, 8770.7, 6863.1, 1379.4, 7.2407 - 0.35, 0.0, 24.0, 11031.6, 7693.3, 1932.5, 9.3656 - 0.35, 0.0, 26.0, 13168.6, 8399.6, 2472.9, 11.7648 - 0.35, 0.0, 30.0, 17653.6, 9705.4, 3720.3, 15.2909 - 0.35, 0.0, 34.0, 21914.4, 10786.9, 5002.2, 18.1525 - 0.35, 0.0, 38.0, 26037.3, 11730.5, 6310.8, 20.5849 - 0.35, 0.0, 42.0, 30057.1, 12571.0, 7691.3, 43.1208 - 0.35, 0.0, 46.0, 33993.9, 13328.4, 9155.7, 67.9905 - 0.35, 0.0, 48.0, 35932.2, 13677.3, 9939.7, 76.3155 - 0.35, 0.0, 50.0, 37853.7, 14009.0, 10755.8, 81.718 - 0.35, 2000.0, 21.0, 7039.8, 5932.0, 999.1, 5.7509 - 0.35, 2000.0, 22.0, 8159.4, 6386.9, 1257.8, 7.0693 - 0.35, 2000.0, 24.0, 10260.8, 7159.0, 1763.3, 9.2076 - 0.35, 2000.0, 26.0, 12247.3, 7816.1, 2255.9, 11.5847 - 0.35, 2000.0, 30.0, 16416.2, 9030.9, 3397.3, 15.1257 - 0.35, 2000.0, 34.0, 20375.6, 10036.0, 4575.8, 18.0083 - 0.35, 2000.0, 38.0, 24207.3, 10913.7, 5773.4, 20.4408 - 0.35, 2000.0, 42.0, 27941.9, 11694.1, 7047.4, 39.005 - 0.35, 2000.0, 46.0, 31598.2, 12396.5, 8403.2, 66.4441 - 0.35, 2000.0, 48.0, 33398.3, 12719.4, 9133.8, 75.6132 - 0.35, 2000.0, 50.0, 35183.5, 13027.6, 9884.0, 81.3882 - 0.35, 5000.0, 21.0, 6297.7, 5306.8, 891.4, 5.1268 - 0.35, 5000.0, 22.0, 7299.6, 5714.1, 1119.5, 6.4339 - 0.35, 5000.0, 24.0, 9179.9, 6405.3, 1565.3, 8.5499 - 0.35, 5000.0, 26.0, 10957.1, 6993.4, 2000.3, 10.2625 - 0.35, 5000.0, 30.0, 14686.9, 8080.8, 3006.9, 14.3212 - 0.35, 5000.0, 34.0, 18229.2, 8980.4, 4046.1, 17.1706 - 0.35, 5000.0, 38.0, 21657.4, 9766.2, 5102.9, 19.5757 - 0.35, 5000.0, 42.0, 24998.3, 10464.7, 6226.3, 25.9255 - 0.35, 5000.0, 46.0, 28269.4, 11093.1, 7421.8, 55.8105 - 0.35, 5000.0, 48.0, 29879.7, 11382.5, 8065.8, 67.2746 - 0.35, 5000.0, 50.0, 31477.1, 11658.5, 8727.8, 75.9179 - 0.35, 10000.0, 21.0, 5202.0, 4383.5, 735.2, 6.795 - 0.35, 10000.0, 22.0, 6030.2, 4720.6, 919.0, 5.282 - 0.35, 10000.0, 24.0, 7584.1, 5292.2, 1278.6, 7.346 - 0.35, 10000.0, 26.0, 9052.7, 5778.6, 1629.9, 9.0072 - 0.35, 10000.0, 30.0, 12134.6, 6677.8, 2441.6, 12.816 - 0.35, 10000.0, 34.0, 15061.4, 7421.8, 3279.3, 15.5823 - 0.35, 10000.0, 38.0, 17893.8, 8071.6, 4132.1, 17.9157 - 0.35, 10000.0, 42.0, 20654.1, 8649.1, 5037.3, 20.0235 - 0.35, 10000.0, 46.0, 23357.0, 9169.2, 6000.8, 29.5981 - 0.35, 10000.0, 48.0, 24688.2, 9408.4, 6520.4, 45.9418 - 0.35, 10000.0, 50.0, 26007.2, 9636.6, 7053.3, 59.5544 - 0.35, 15000.0, 21.0, 4265.5, 3594.1, 604.8, 9.6899 - 0.35, 15000.0, 22.0, 4945.3, 3871.2, 751.6, 6.6744 - 0.35, 15000.0, 24.0, 6220.4, 4340.7, 1039.2, 6.0427 - 0.35, 15000.0, 26.0, 7425.3, 4740.1, 1320.6, 7.6429 - 0.35, 15000.0, 30.0, 9953.9, 5478.5, 1969.8, 10.8708 - 0.35, 15000.0, 34.0, 12355.2, 6089.6, 2639.9, 13.8065 - 0.35, 15000.0, 38.0, 14678.8, 6623.1, 3322.2, 16.0412 - 0.35, 15000.0, 42.0, 16943.3, 7097.5, 4045.6, 18.0572 - 0.35, 15000.0, 46.0, 19160.5, 7524.6, 4816.5, 19.9608 - 0.35, 15000.0, 48.0, 20251.7, 7720.9, 5231.4, 22.6619 - 0.35, 15000.0, 50.0, 21334.5, 7908.4, 5657.5, 33.1924 - 0.4, 2000.0, 21.0, 8528.1, 7446.9, 1080.6, 6.2764 - 0.4, 2000.0, 22.0, 9658.0, 7928.2, 1353.5, 7.5936 - 0.4, 2000.0, 24.0, 11784.7, 8757.4, 1878.4, 9.7055 - 0.4, 2000.0, 26.0, 13797.7, 9473.0, 2382.4, 12.1006 - 0.4, 2000.0, 30.0, 18018.9, 10811.1, 3529.2, 15.5376 - 0.4, 2000.0, 34.0, 22012.9, 11922.0, 4732.9, 18.4036 - 0.4, 2000.0, 38.0, 25869.2, 12895.0, 5956.0, 20.8298 - 0.4, 2000.0, 42.0, 29617.1, 13759.9, 7260.5, 44.5575 - 0.4, 2000.0, 46.0, 33282.9, 14542.5, 8623.9, 69.2745 - 0.4, 2000.0, 48.0, 35081.9, 14900.1, 9368.5, 77.6817 - 0.4, 2000.0, 50.0, 36867.3, 15243.9, 10120.0, 82.6292 - 0.4, 5000.0, 21.0, 7629.4, 6662.3, 963.1, 5.6477 - 0.4, 5000.0, 22.0, 8640.5, 7093.1, 1203.9, 6.9524 - 0.4, 5000.0, 24.0, 10543.4, 7835.5, 1666.8, 9.0427 - 0.4, 5000.0, 26.0, 12344.4, 8476.0, 2111.2, 11.1881 - 0.4, 5000.0, 30.0, 16121.1, 9673.7, 3123.3, 14.7282 - 0.4, 5000.0, 34.0, 19694.5, 10668.0, 4184.8, 17.5597 - 0.4, 5000.0, 38.0, 23144.4, 11539.2, 5263.3, 19.9572 - 0.4, 5000.0, 42.0, 26497.4, 12313.3, 6414.0, 29.514 - 0.4, 5000.0, 46.0, 29777.0, 13014.0, 7616.7, 59.0834 - 0.4, 5000.0, 48.0, 31386.7, 13333.9, 8272.8, 70.033 - 0.4, 5000.0, 50.0, 32983.8, 13641.9, 8936.1, 77.8099 - 0.4, 10000.0, 21.0, 6302.4, 5503.6, 792.8, 5.5515 - 0.4, 10000.0, 22.0, 7138.3, 5860.2, 987.2, 5.7899 - 0.4, 10000.0, 24.0, 8710.6, 6473.9, 1360.1, 7.8236 - 0.4, 10000.0, 26.0, 10198.9, 7003.7, 1718.7, 9.4457 - 0.4, 10000.0, 30.0, 13319.7, 7994.3, 2535.4, 13.2086 - 0.4, 10000.0, 34.0, 16272.3, 8816.6, 3391.4, 15.9573 - 0.4, 10000.0, 38.0, 19122.7, 9537.0, 4262.0, 18.2845 - 0.4, 10000.0, 42.0, 21893.2, 10177.2, 5188.5, 20.3954 - 0.4, 10000.0, 46.0, 24602.9, 10756.8, 6158.4, 33.2437 - 0.4, 10000.0, 48.0, 25932.9, 11021.4, 6687.2, 50.2607 - 0.4, 10000.0, 50.0, 27252.3, 11276.0, 7221.2, 62.3136 - 0.4, 15000.0, 21.0, 5168.0, 4512.9, 650.8, 8.4556 - 0.4, 15000.0, 22.0, 5854.1, 4806.0, 806.0, 5.4657 - 0.4, 15000.0, 24.0, 7144.6, 5310.3, 1104.8, 6.507 - 0.4, 15000.0, 26.0, 8365.6, 5745.3, 1391.4, 8.064 - 0.4, 15000.0, 30.0, 10925.8, 6558.6, 2044.8, 11.5264 - 0.4, 15000.0, 34.0, 13348.1, 7234.0, 2729.6, 14.1632 - 0.4, 15000.0, 38.0, 15686.6, 7825.6, 3426.3, 16.3919 - 0.4, 15000.0, 42.0, 17959.2, 8351.4, 4166.5, 18.4104 - 0.4, 15000.0, 46.0, 20182.2, 8827.3, 4942.1, 20.2805 - 0.4, 15000.0, 48.0, 21272.7, 9044.6, 5364.6, 24.6069 - 0.4, 15000.0, 50.0, 22355.5, 9253.8, 5792.4, 36.8914 - 0.4, 20000.0, 21.0, 4204.2, 3671.1, 533.0, 11.3443 - 0.4, 20000.0, 22.0, 4763.2, 3910.2, 655.9, 8.3987 - 0.4, 20000.0, 24.0, 5814.2, 4321.4, 892.7, 5.1322 - 0.4, 20000.0, 26.0, 6808.5, 4676.0, 1119.9, 6.6187 - 0.4, 20000.0, 30.0, 8893.2, 5339.0, 1638.7, 9.2928 - 0.4, 20000.0, 34.0, 10865.4, 5889.5, 2181.2, 12.2577 - 0.4, 20000.0, 38.0, 12769.1, 6371.6, 2734.1, 14.3697 - 0.4, 20000.0, 42.0, 14619.4, 6800.2, 3321.2, 16.2797 - 0.4, 20000.0, 46.0, 16429.0, 7188.1, 3935.2, 18.0475 - 0.4, 20000.0, 48.0, 17317.4, 7365.4, 4270.7, 18.9554 - 0.4, 20000.0, 50.0, 18198.2, 7535.7, 4608.9, 19.8172 - 0.45, 5000.0, 21.0, 9134.3, 8186.4, 1052.9, 6.2594 - 0.45, 5000.0, 22.0, 10153.5, 8637.0, 1297.4, 7.5048 - 0.45, 5000.0, 24.0, 12077.2, 9423.1, 1777.2, 9.5637 - 0.45, 5000.0, 26.0, 13900.8, 10109.4, 2237.9, 11.8951 - 0.45, 5000.0, 30.0, 17726.1, 11407.1, 3263.8, 15.2102 - 0.45, 5000.0, 34.0, 21336.8, 12490.1, 4347.5, 18.0093 - 0.45, 5000.0, 38.0, 24813.0, 13438.6, 5462.2, 20.4201 - 0.45, 5000.0, 42.0, 28188.8, 14287.0, 6626.4, 34.5899 - 0.45, 5000.0, 46.0, 31486.0, 15056.3, 7841.9, 62.5039 - 0.45, 5000.0, 48.0, 33098.2, 15405.0, 8512.7, 72.9747 - 0.45, 5000.0, 50.0, 34700.2, 15743.1, 9179.8, 79.8154 - 0.45, 10000.0, 21.0, 7545.9, 6763.0, 865.0, 5.1128 - 0.45, 10000.0, 22.0, 8388.6, 7135.9, 1062.6, 6.3291 - 0.45, 10000.0, 24.0, 9978.2, 7786.1, 1449.5, 8.3334 - 0.45, 10000.0, 26.0, 11485.1, 8353.6, 1820.8, 9.9346 - 0.45, 10000.0, 30.0, 14645.9, 9426.7, 2648.1, 13.6721 - 0.45, 10000.0, 34.0, 17629.4, 10322.5, 3522.4, 16.3907 - 0.45, 10000.0, 38.0, 20501.5, 11106.9, 4421.5, 18.7295 - 0.45, 10000.0, 42.0, 23290.9, 11808.7, 5360.6, 20.8118 - 0.45, 10000.0, 46.0, 26014.7, 12444.7, 6339.6, 38.0177 - 0.45, 10000.0, 48.0, 27346.9, 12733.1, 6880.0, 54.809 - 0.45, 10000.0, 50.0, 28670.6, 13012.9, 7417.8, 65.5452 - 0.45, 15000.0, 21.0, 6188.1, 5546.1, 708.2, 7.0161 - 0.45, 15000.0, 22.0, 6879.8, 5852.6, 866.3, 5.0623 - 0.45, 15000.0, 24.0, 8184.3, 6386.7, 1176.1, 6.9948 - 0.45, 15000.0, 26.0, 9420.7, 6852.7, 1473.1, 8.533 - 0.45, 15000.0, 30.0, 12014.0, 7734.1, 2135.7, 11.9737 - 0.45, 15000.0, 34.0, 14461.5, 8469.7, 2834.4, 14.5758 - 0.45, 15000.0, 38.0, 16817.6, 9113.8, 3553.9, 16.8157 - 0.45, 15000.0, 42.0, 19105.8, 9690.3, 4304.2, 18.8064 - 0.45, 15000.0, 46.0, 21340.5, 10212.6, 5087.2, 20.6468 - 0.45, 15000.0, 48.0, 22433.2, 10449.4, 5519.7, 27.6021 - 0.45, 15000.0, 50.0, 23518.8, 10679.1, 5949.6, 41.4721 - 0.45, 20000.0, 21.0, 5034.5, 4512.0, 578.2, 9.9201 - 0.45, 20000.0, 22.0, 5598.0, 4762.1, 703.5, 7.1405 - 0.45, 20000.0, 24.0, 6660.5, 5197.7, 949.2, 5.5997 - 0.45, 20000.0, 26.0, 7667.4, 5577.6, 1184.8, 7.0642 - 0.45, 20000.0, 30.0, 9779.0, 6296.0, 1710.7, 9.6704 - 0.45, 20000.0, 34.0, 11771.9, 6895.7, 2264.6, 12.6477 - 0.45, 20000.0, 38.0, 13690.0, 7420.5, 2835.3, 14.7686 - 0.45, 20000.0, 42.0, 15553.0, 7890.4, 3430.4, 16.6516 - 0.45, 20000.0, 46.0, 17372.0, 8316.2, 4051.2, 18.3923 - 0.45, 20000.0, 48.0, 18261.9, 8509.5, 4393.4, 19.298 - 0.45, 20000.0, 50.0, 19145.4, 8696.4, 4733.9, 20.4806 - 0.45, 25000.0, 21.0, 4060.5, 3638.9, 471.3, 12.8242 - 0.45, 25000.0, 22.0, 4515.9, 3841.4, 569.7, 10.0682 - 0.45, 25000.0, 24.0, 5374.3, 4193.9, 762.8, 5.6593 - 0.45, 25000.0, 26.0, 6187.3, 4501.0, 947.5, 5.5964 - 0.45, 25000.0, 30.0, 7892.2, 5081.8, 1360.8, 8.0513 - 0.45, 25000.0, 34.0, 9501.3, 5566.7, 1795.6, 10.5022 - 0.45, 25000.0, 38.0, 11049.7, 5991.0, 2244.5, 12.7089 - 0.45, 25000.0, 42.0, 12553.9, 6370.9, 2711.4, 14.4744 - 0.45, 25000.0, 46.0, 14022.2, 6715.2, 3198.7, 16.1089 - 0.45, 25000.0, 48.0, 14740.5, 6871.3, 3466.7, 16.9602 - 0.45, 25000.0, 50.0, 15453.9, 7022.7, 3734.8, 17.7627 - 0.5, 10000.0, 21.0, 8935.3, 8163.6, 961.2, 5.8415 - 0.5, 10000.0, 22.0, 9784.6, 8549.9, 1163.5, 6.9976 - 0.5, 10000.0, 24.0, 11396.5, 9235.8, 1543.3, 8.8511 - 0.5, 10000.0, 26.0, 12924.7, 9838.0, 1929.2, 10.5792 - 0.5, 10000.0, 30.0, 16130.8, 10986.4, 2783.0, 14.2064 - 0.5, 10000.0, 34.0, 19153.1, 11950.9, 3679.1, 16.8955 - 0.5, 10000.0, 38.0, 22058.2, 12798.3, 4602.1, 19.2194 - 0.5, 10000.0, 42.0, 24877.3, 13559.7, 5557.3, 21.8787 - 0.5, 10000.0, 46.0, 27624.5, 14249.1, 6554.3, 44.2213 - 0.5, 10000.0, 48.0, 28965.7, 14561.4, 7104.9, 59.1261 - 0.5, 10000.0, 50.0, 30298.2, 14865.0, 7650.4, 69.0476 - 0.5, 15000.0, 21.0, 7328.1, 6695.3, 785.0, 5.2669 - 0.5, 15000.0, 22.0, 8025.5, 7012.9, 947.3, 5.7106 - 0.5, 15000.0, 24.0, 9348.0, 7576.1, 1250.9, 7.4914 - 0.5, 15000.0, 26.0, 10602.1, 8070.9, 1560.0, 9.017 - 0.5, 15000.0, 30.0, 13232.8, 9014.0, 2243.0, 12.4829 - 0.5, 15000.0, 34.0, 15712.4, 9806.1, 2959.9, 15.0577 - 0.5, 15000.0, 38.0, 18095.8, 10502.0, 3698.5, 17.2835 - 0.5, 15000.0, 42.0, 20408.6, 11127.3, 4462.3, 19.2512 - 0.5, 15000.0, 46.0, 22662.5, 11693.7, 5260.4, 22.1856 - 0.5, 15000.0, 48.0, 23762.9, 11950.1, 5699.8, 31.922 - 0.5, 15000.0, 50.0, 24855.4, 12199.1, 6135.5, 46.874 - 0.5, 20000.0, 21.0, 5962.3, 5447.4, 638.9, 8.1949 - 0.5, 20000.0, 22.0, 6530.4, 5706.6, 767.5, 5.5864 - 0.5, 20000.0, 24.0, 7607.5, 6165.9, 1008.8, 6.0754 - 0.5, 20000.0, 26.0, 8628.5, 6569.1, 1253.7, 7.5239 - 0.5, 20000.0, 30.0, 10770.3, 7337.8, 1795.3, 10.1237 - 0.5, 20000.0, 34.0, 12788.9, 7983.4, 2363.9, 13.1017 - 0.5, 20000.0, 38.0, 14729.0, 8550.6, 2949.4, 15.2078 - 0.5, 20000.0, 42.0, 16611.6, 9060.2, 3555.1, 17.0676 - 0.5, 20000.0, 46.0, 18446.0, 9521.6, 4187.2, 18.7919 - 0.5, 20000.0, 48.0, 19341.8, 9731.0, 4535.0, 19.685 - 0.5, 20000.0, 50.0, 20231.5, 9934.1, 4880.0, 22.2565 - 0.5, 25000.0, 21.0, 4809.4, 4393.9, 518.7, 11.1067 - 0.5, 25000.0, 22.0, 5268.5, 4603.8, 619.7, 8.5392 - 0.5, 25000.0, 24.0, 6138.4, 4975.2, 809.4, 4.6585 - 0.5, 25000.0, 26.0, 6963.0, 5301.2, 1001.5, 6.0297 - 0.5, 25000.0, 30.0, 8692.6, 5923.0, 1426.9, 8.4555 - 0.5, 25000.0, 34.0, 10322.4, 6444.9, 1873.7, 11.1348 - 0.5, 25000.0, 38.0, 11888.8, 6903.5, 2334.1, 13.1197 - 0.5, 25000.0, 42.0, 13408.7, 7315.6, 2809.6, 14.8632 - 0.5, 25000.0, 46.0, 14889.7, 7688.8, 3305.8, 16.4821 - 0.5, 25000.0, 48.0, 15612.7, 7857.9, 3578.7, 17.3225 - 0.5, 25000.0, 50.0, 16331.0, 8022.2, 3850.1, 18.1143 - 0.55, 10000.0, 21.0, 10473.2, 9708.0, 1063.1, 6.5663 - 0.55, 10000.0, 22.0, 11331.3, 10107.0, 1273.2, 7.684 - 0.55, 10000.0, 24.0, 12968.8, 10826.2, 1651.6, 9.4227 - 0.55, 10000.0, 26.0, 14524.0, 11463.2, 2046.0, 11.6154 - 0.55, 10000.0, 30.0, 17784.6, 12683.1, 2929.7, 14.7724 - 0.55, 10000.0, 34.0, 20855.7, 13713.6, 3852.5, 17.4405 - 0.55, 10000.0, 38.0, 23804.1, 14621.6, 4806.1, 19.7586 - 0.55, 10000.0, 42.0, 26664.3, 15441.0, 5782.5, 24.8341 - 0.55, 10000.0, 46.0, 29445.2, 16181.5, 6806.8, 51.3216 - 0.55, 10000.0, 48.0, 30801.6, 16517.7, 7366.0, 63.4873 - 0.55, 10000.0, 50.0, 32151.3, 16847.1, 7921.7, 72.7201 - 0.55, 15000.0, 21.0, 8589.7, 7962.3, 866.4, 5.2947 - 0.55, 15000.0, 22.0, 9294.1, 8290.2, 1034.6, 6.3704 - 0.55, 15000.0, 24.0, 10637.7, 8880.9, 1337.3, 8.0399 - 0.55, 15000.0, 26.0, 11913.6, 9404.0, 1653.0, 9.52 - 0.55, 15000.0, 30.0, 14588.5, 10405.8, 2359.7, 13.0203 - 0.55, 15000.0, 34.0, 17108.0, 11252.3, 3098.8, 15.5778 - 0.55, 15000.0, 38.0, 19526.7, 11997.8, 3861.4, 17.7957 - 0.55, 15000.0, 42.0, 21872.4, 12670.6, 4642.0, 19.7451 - 0.55, 15000.0, 46.0, 24153.7, 13278.7, 5460.9, 25.1739 - 0.55, 15000.0, 48.0, 25266.4, 13555.1, 5907.7, 37.7816 - 0.55, 15000.0, 50.0, 26373.7, 13825.7, 6352.0, 52.6518 - 0.55, 20000.0, 21.0, 6989.4, 6479.0, 703.3, 6.503 - 0.55, 20000.0, 22.0, 7563.3, 6746.5, 837.0, 5.0064 - 0.55, 20000.0, 24.0, 8657.4, 7228.1, 1077.2, 6.5972 - 0.55, 20000.0, 26.0, 9696.4, 7654.5, 1327.5, 8.0013 - 0.55, 20000.0, 30.0, 11874.4, 8471.2, 1888.0, 11.0514 - 0.55, 20000.0, 34.0, 13925.6, 9161.1, 2474.4, 13.5941 - 0.55, 20000.0, 38.0, 15894.5, 9768.8, 3078.5, 15.69 - 0.55, 20000.0, 42.0, 17804.3, 10317.3, 3698.0, 17.5325 - 0.55, 20000.0, 46.0, 19661.3, 10813.0, 4347.4, 19.2513 - 0.55, 20000.0, 48.0, 20567.3, 11038.3, 4701.1, 20.1286 - 0.55, 20000.0, 50.0, 21468.4, 11258.8, 5053.1, 25.1535 - 0.55, 25000.0, 21.0, 5638.5, 5226.6, 569.1, 9.4348 - 0.55, 25000.0, 22.0, 6102.2, 5443.2, 674.2, 6.9986 - 0.55, 25000.0, 24.0, 6985.9, 5832.7, 863.0, 5.1538 - 0.55, 25000.0, 26.0, 7825.0, 6177.5, 1059.5, 6.4814 - 0.55, 25000.0, 30.0, 9583.8, 6838.0, 1499.7, 8.8813 - 0.55, 25000.0, 34.0, 11240.1, 7395.8, 1960.8, 11.5975 - 0.55, 25000.0, 38.0, 12829.7, 7887.1, 2435.5, 13.5701 - 0.55, 25000.0, 42.0, 14371.4, 8330.6, 2922.0, 15.2974 - 0.55, 25000.0, 46.0, 15870.7, 8731.4, 3431.6, 16.9093 - 0.55, 25000.0, 48.0, 16601.9, 8913.6, 3708.9, 17.7331 - 0.55, 25000.0, 50.0, 17329.5, 9092.0, 3985.6, 18.5183 - 0.55, 30000.0, 21.0, 4506.0, 4176.6, 459.6, 12.3646 - 0.55, 30000.0, 22.0, 4877.6, 4350.6, 541.3, 9.9465 - 0.55, 30000.0, 24.0, 5585.4, 4663.2, 688.6, 6.3459 - 0.55, 30000.0, 26.0, 6257.1, 4939.6, 841.1, 4.9951 - 0.55, 30000.0, 30.0, 7665.1, 5469.3, 1183.3, 7.2442 - 0.55, 30000.0, 34.0, 8990.5, 5916.4, 1541.7, 9.1534 - 0.55, 30000.0, 38.0, 10262.7, 6310.2, 1910.9, 11.4896 - 0.55, 30000.0, 42.0, 11496.3, 6665.6, 2289.2, 13.1001 - 0.55, 30000.0, 46.0, 12696.1, 6986.9, 2685.7, 14.6049 - 0.55, 30000.0, 48.0, 13281.5, 7133.2, 2900.4, 15.3716 - 0.55, 30000.0, 50.0, 13863.3, 7275.8, 3114.4, 16.1055 - 0.6, 15000.0, 21.0, 9973.8, 9348.2, 950.5, 5.9783 - 0.6, 15000.0, 22.0, 10687.7, 9686.8, 1124.3, 7.0163 - 0.6, 15000.0, 24.0, 12054.5, 10302.9, 1438.6, 8.6443 - 0.6, 15000.0, 26.0, 13357.4, 10855.1, 1754.7, 10.0484 - 0.6, 15000.0, 30.0, 16084.8, 11914.4, 2488.5, 13.592 - 0.6, 15000.0, 34.0, 18652.7, 12814.1, 3252.5, 16.1377 - 0.6, 15000.0, 38.0, 21114.4, 13607.6, 4042.6, 18.3508 - 0.6, 15000.0, 42.0, 23501.9, 14327.1, 4845.2, 20.2894 - 0.6, 15000.0, 46.0, 25820.8, 14977.7, 5688.9, 30.203 - 0.6, 15000.0, 48.0, 26957.4, 15280.2, 6143.4, 44.8334 - 0.6, 15000.0, 50.0, 28089.5, 15578.2, 6600.6, 58.0636 - 0.6, 20000.0, 21.0, 8116.3, 7607.3, 769.9, 4.8739 - 0.6, 20000.0, 22.0, 8697.8, 7883.4, 907.9, 5.6219 - 0.6, 20000.0, 24.0, 9810.9, 8385.7, 1157.0, 7.1692 - 0.6, 20000.0, 26.0, 10872.0, 8836.1, 1408.5, 8.504 - 0.6, 20000.0, 30.0, 13092.7, 9699.5, 1989.8, 11.7084 - 0.6, 20000.0, 34.0, 15183.5, 10432.9, 2596.5, 14.1211 - 0.6, 20000.0, 38.0, 17187.7, 11079.9, 3223.0, 16.2145 - 0.6, 20000.0, 42.0, 19131.3, 11666.4, 3858.8, 18.0426 - 0.6, 20000.0, 46.0, 21019.2, 12196.8, 4528.3, 19.7561 - 0.6, 20000.0, 48.0, 21944.6, 12443.4, 4888.4, 21.6513 - 0.6, 20000.0, 50.0, 22865.7, 12685.9, 5250.5, 29.7394 - 0.6, 25000.0, 21.0, 6548.0, 6137.4, 621.3, 7.8343 - 0.6, 25000.0, 22.0, 7018.0, 6361.0, 730.0, 5.5192 - 0.6, 25000.0, 24.0, 7917.0, 6767.3, 925.6, 5.6982 - 0.6, 25000.0, 26.0, 8773.7, 7131.3, 1123.2, 6.9559 - 0.6, 25000.0, 30.0, 10567.1, 7829.7, 1580.2, 9.3365 - 0.6, 25000.0, 34.0, 12254.9, 8422.5, 2056.4, 12.09 - 0.6, 25000.0, 38.0, 13872.9, 8945.6, 2548.6, 14.0586 - 0.6, 25000.0, 42.0, 15441.9, 9419.5, 3048.5, 15.7736 - 0.6, 25000.0, 46.0, 16965.8, 9848.6, 3573.0, 17.3772 - 0.6, 25000.0, 48.0, 17712.8, 10048.1, 3855.9, 18.1848 - 0.6, 25000.0, 50.0, 18456.6, 10244.4, 4140.2, 18.9671 - 0.6, 30000.0, 21.0, 5233.4, 4905.1, 500.0, 10.771 - 0.6, 30000.0, 22.0, 5610.0, 5084.7, 584.6, 8.4942 - 0.6, 30000.0, 24.0, 6329.9, 5410.6, 736.4, 5.0619 - 0.6, 30000.0, 26.0, 7015.7, 5702.4, 890.5, 5.441 - 0.6, 30000.0, 30.0, 8451.2, 6262.4, 1245.5, 7.6673 - 0.6, 30000.0, 34.0, 9802.1, 6737.8, 1616.1, 9.6371 - 0.6, 30000.0, 38.0, 11096.9, 7157.0, 1998.7, 11.9431 - 0.6, 30000.0, 42.0, 12352.3, 7536.9, 2387.5, 13.542 - 0.6, 30000.0, 46.0, 13571.6, 7880.7, 2795.9, 15.0403 - 0.6, 30000.0, 48.0, 14169.7, 8041.0, 3014.6, 15.7897 - 0.6, 30000.0, 50.0, 14764.6, 8198.1, 3235.5, 16.5238 - 0.6, 35000.0, 21.0, 4139.6, 3879.7, 401.9, 13.7651 - 0.6, 35000.0, 22.0, 4438.7, 4022.7, 467.0, 11.4717 - 0.6, 35000.0, 24.0, 5009.8, 4281.9, 583.8, 8.0866 - 0.6, 35000.0, 26.0, 5553.5, 4513.7, 702.3, 5.2844 - 0.6, 35000.0, 30.0, 6691.7, 4958.7, 975.1, 6.0676 - 0.6, 35000.0, 34.0, 7762.5, 5336.2, 1259.8, 7.8379 - 0.6, 35000.0, 38.0, 8788.5, 5669.1, 1553.9, 9.6313 - 0.6, 35000.0, 42.0, 9783.3, 5970.6, 1853.8, 11.4063 - 0.6, 35000.0, 46.0, 10749.7, 6243.7, 2167.6, 12.7926 - 0.6, 35000.0, 48.0, 11223.1, 6370.7, 2335.6, 13.4895 - 0.6, 35000.0, 50.0, 11695.0, 6496.0, 2504.7, 14.1725 - 0.6, 37000.0, 21.0, 3758.1, 3522.0, 370.0, 14.2083 - 0.6, 37000.0, 22.0, 4030.2, 3652.4, 428.7, 11.9308 - 0.6, 37000.0, 24.0, 4549.5, 3888.3, 534.1, 8.6067 - 0.6, 37000.0, 26.0, 5043.7, 4099.0, 640.8, 5.8649 - 0.6, 37000.0, 30.0, 6078.5, 4504.0, 886.9, 5.62 - 0.6, 37000.0, 34.0, 7051.8, 4847.5, 1143.9, 7.3337 - 0.6, 37000.0, 38.0, 7984.2, 5150.1, 1409.1, 8.8243 - 0.6, 37000.0, 42.0, 8888.2, 5424.2, 1680.1, 10.7527 - 0.6, 37000.0, 46.0, 9766.3, 5672.7, 1963.0, 12.0908 - 0.6, 37000.0, 48.0, 10197.0, 5788.4, 2114.5, 12.7641 - 0.6, 37000.0, 50.0, 10625.8, 5902.3, 2266.3, 13.4179 - 0.6, 39000.0, 21.0, 3410.5, 3195.9, 342.8, 13.7365 - 0.6, 39000.0, 22.0, 3658.1, 3314.8, 396.0, 11.5252 - 0.6, 39000.0, 24.0, 4130.3, 3529.5, 491.6, 8.3235 - 0.6, 39000.0, 26.0, 4579.5, 3721.3, 588.5, 5.6738 - 0.6, 39000.0, 30.0, 5520.0, 4089.6, 811.7, 5.3948 - 0.6, 39000.0, 34.0, 6404.7, 4402.1, 1044.8, 7.0416 - 0.6, 39000.0, 38.0, 7251.9, 4677.1, 1285.7, 8.4753 - 0.6, 39000.0, 42.0, 8073.2, 4926.2, 1532.0, 10.3344 - 0.6, 39000.0, 46.0, 8871.3, 5152.2, 1788.5, 11.6188 - 0.6, 39000.0, 48.0, 9262.7, 5257.5, 1925.9, 12.2647 - 0.6, 39000.0, 50.0, 9652.5, 5361.2, 2063.4, 12.8882 - 0.6, 41000.0, 21.0, 3094.4, 2899.4, 318.6, 13.295 - 0.6, 41000.0, 22.0, 3320.0, 3008.0, 366.6, 11.1448 - 0.6, 41000.0, 24.0, 3749.4, 3203.6, 453.0, 8.0632 - 0.6, 41000.0, 26.0, 4157.8, 3378.0, 541.0, 5.5011 - 0.6, 41000.0, 30.0, 5012.8, 3713.2, 743.4, 5.178 - 0.6, 41000.0, 34.0, 5816.8, 3997.3, 954.9, 6.7566 - 0.6, 41000.0, 38.0, 6586.8, 4247.5, 1173.9, 8.1404 - 0.6, 41000.0, 42.0, 7333.1, 4473.9, 1397.5, 9.9298 - 0.6, 41000.0, 46.0, 8058.4, 4679.4, 1630.2, 11.1649 - 0.6, 41000.0, 48.0, 8414.1, 4775.2, 1754.8, 11.7844 - 0.6, 41000.0, 50.0, 8768.5, 4869.7, 1878.9, 12.376 - 0.65, 15000.0, 21.0, 11481.3, 10854.1, 1035.9, 6.6394 - 0.65, 15000.0, 22.0, 12207.7, 11204.2, 1215.3, 7.6447 - 0.65, 15000.0, 24.0, 13603.0, 11846.9, 1542.7, 9.2444 - 0.65, 15000.0, 26.0, 14935.6, 12427.0, 1867.4, 11.011 - 0.65, 15000.0, 30.0, 17724.6, 13543.7, 2628.1, 14.1919 - 0.65, 15000.0, 34.0, 20349.9, 14496.6, 3420.7, 16.7302 - 0.65, 15000.0, 38.0, 22863.3, 15337.4, 4243.8, 18.9494 - 0.65, 15000.0, 42.0, 25300.6, 16102.7, 5073.7, 20.8824 - 0.65, 15000.0, 46.0, 27684.0, 16813.4, 5945.8, 37.6447 - 0.65, 15000.0, 48.0, 28853.2, 17146.3, 6412.4, 52.4446 - 0.65, 15000.0, 50.0, 30016.4, 17473.3, 6885.5, 63.165 - 0.65, 20000.0, 21.0, 9343.5, 8833.4, 837.7, 5.2653 - 0.65, 20000.0, 22.0, 9935.0, 9118.7, 979.9, 6.2209 - 0.65, 20000.0, 24.0, 11071.1, 9642.6, 1239.6, 7.74 - 0.65, 20000.0, 26.0, 12156.3, 10115.6, 1497.6, 9.0357 - 0.65, 20000.0, 30.0, 14427.2, 11026.1, 2101.3, 12.2787 - 0.65, 20000.0, 34.0, 16564.3, 11802.7, 2729.9, 14.6793 - 0.65, 20000.0, 38.0, 18610.2, 12488.0, 3382.1, 16.7756 - 0.65, 20000.0, 42.0, 20594.6, 13112.0, 4040.1, 18.6009 - 0.65, 20000.0, 46.0, 22534.2, 13691.1, 4731.2, 20.3058 - 0.65, 20000.0, 48.0, 23485.7, 13962.4, 5100.5, 24.9412 - 0.65, 20000.0, 50.0, 24432.6, 14229.1, 5474.5, 36.2661 - 0.65, 25000.0, 21.0, 7538.7, 7127.2, 674.5, 6.3118 - 0.65, 25000.0, 22.0, 8016.8, 7358.3, 786.7, 4.8016 - 0.65, 25000.0, 24.0, 8934.3, 7781.9, 990.5, 6.2373 - 0.65, 25000.0, 26.0, 9810.5, 8164.3, 1193.3, 7.4577 - 0.65, 25000.0, 30.0, 11644.1, 8900.5, 1667.2, 9.8122 - 0.65, 25000.0, 34.0, 13369.6, 9528.5, 2161.3, 12.6125 - 0.65, 25000.0, 38.0, 15021.2, 10082.6, 2673.6, 14.582 - 0.65, 25000.0, 42.0, 16623.1, 10587.1, 3190.9, 16.2937 - 0.65, 25000.0, 46.0, 18188.8, 11055.3, 3733.0, 17.8916 - 0.65, 25000.0, 48.0, 18957.1, 11274.9, 4023.5, 18.6867 - 0.65, 25000.0, 50.0, 19721.6, 11490.7, 4316.5, 19.4646 - 0.65, 30000.0, 21.0, 6025.8, 5696.8, 541.2, 9.2686 - 0.65, 30000.0, 22.0, 6408.8, 5882.4, 628.6, 7.1132 - 0.65, 30000.0, 24.0, 7143.4, 6222.1, 786.8, 4.7609 - 0.65, 30000.0, 26.0, 7844.8, 6528.7, 944.9, 5.9115 - 0.65, 30000.0, 30.0, 9312.7, 7119.2, 1313.5, 8.114 - 0.65, 30000.0, 34.0, 10693.4, 7622.5, 1697.7, 10.5176 - 0.65, 30000.0, 38.0, 12015.1, 8066.7, 2096.0, 12.429 - 0.65, 30000.0, 42.0, 13296.7, 8470.9, 2498.2, 14.0245 - 0.65, 30000.0, 46.0, 14549.5, 8846.3, 2919.9, 15.5145 - 0.65, 30000.0, 48.0, 15164.4, 9022.5, 3145.2, 16.2578 - 0.65, 30000.0, 50.0, 15776.0, 9195.4, 3372.5, 16.9835 - 0.65, 35000.0, 21.0, 4767.0, 4506.6, 433.5, 12.2477 - 0.65, 35000.0, 22.0, 5071.1, 4654.4, 500.8, 10.0982 - 0.65, 35000.0, 24.0, 5653.7, 4924.4, 622.1, 6.8639 - 0.65, 35000.0, 26.0, 6210.0, 5168.0, 743.9, 4.422 - 0.65, 35000.0, 30.0, 7373.7, 5637.1, 1027.3, 6.4841 - 0.65, 35000.0, 34.0, 8468.2, 6037.1, 1322.7, 8.2441 - 0.65, 35000.0, 38.0, 9515.4, 6389.7, 1628.5, 10.3632 - 0.65, 35000.0, 42.0, 10530.9, 6710.5, 1938.8, 11.8544 - 0.65, 35000.0, 46.0, 11523.6, 7008.6, 2262.9, 13.2342 - 0.65, 35000.0, 48.0, 12010.7, 7148.5, 2436.1, 13.9247 - 0.65, 35000.0, 50.0, 12495.8, 7286.2, 2609.9, 14.5969 - 0.65, 37000.0, 21.0, 4328.0, 4091.4, 398.3, 12.7114 - 0.65, 37000.0, 22.0, 4604.7, 4226.1, 459.1, 10.5799 - 0.65, 37000.0, 24.0, 5134.7, 4472.0, 568.6, 7.4067 - 0.65, 37000.0, 26.0, 5640.3, 4693.6, 678.3, 4.7981 - 0.65, 37000.0, 30.0, 6698.2, 5120.4, 934.1, 6.0241 - 0.65, 37000.0, 34.0, 7693.1, 5484.2, 1200.6, 7.7263 - 0.65, 37000.0, 38.0, 8645.0, 5805.0, 1476.6, 9.5229 - 0.65, 37000.0, 42.0, 9567.7, 6096.5, 1757.2, 11.1876 - 0.65, 37000.0, 46.0, 10470.1, 6367.8, 2049.0, 12.5173 - 0.65, 37000.0, 48.0, 10912.6, 6494.8, 2205.3, 13.1845 - 0.65, 37000.0, 50.0, 11353.7, 6620.3, 2361.7, 13.8301 - 0.65, 39000.0, 21.0, 3928.0, 3713.0, 368.4, 12.2906 - 0.65, 39000.0, 22.0, 4179.8, 3835.7, 423.5, 10.2222 - 0.65, 39000.0, 24.0, 4661.5, 4059.5, 522.5, 7.1754 - 0.65, 39000.0, 26.0, 5121.2, 4261.1, 622.3, 4.6517 - 0.65, 39000.0, 30.0, 6082.8, 4649.3, 854.5, 5.7838 - 0.65, 39000.0, 34.0, 6987.2, 4980.3, 1096.2, 7.4195 - 0.65, 39000.0, 38.0, 7852.3, 5272.0, 1347.0, 9.1325 - 0.65, 39000.0, 42.0, 8690.6, 5536.9, 1601.9, 10.7517 - 0.65, 39000.0, 46.0, 9510.4, 5783.5, 1866.9, 12.0307 - 0.65, 39000.0, 48.0, 9912.8, 5899.1, 2008.5, 12.6712 - 0.65, 39000.0, 50.0, 10313.9, 6013.4, 2149.9, 13.285 - 0.65, 41000.0, 21.0, 3564.4, 3369.0, 341.4, 11.8988 - 0.65, 41000.0, 22.0, 3793.7, 3481.1, 391.2, 9.8837 - 0.65, 41000.0, 24.0, 4231.9, 3684.9, 480.9, 6.9499 - 0.65, 41000.0, 26.0, 4649.7, 3868.3, 571.5, 4.5148 - 0.65, 41000.0, 30.0, 5523.7, 4221.4, 782.2, 5.5521 - 0.65, 41000.0, 34.0, 6345.8, 4522.5, 1001.6, 7.1247 - 0.65, 41000.0, 38.0, 7131.8, 4787.6, 1229.2, 8.7518 - 0.65, 41000.0, 42.0, 7893.5, 5028.4, 1460.7, 10.3306 - 0.65, 41000.0, 46.0, 8638.7, 5252.7, 1701.3, 11.5623 - 0.65, 41000.0, 48.0, 9004.5, 5357.9, 1829.8, 12.177 - 0.65, 41000.0, 50.0, 9369.0, 5462.0, 1957.7, 12.7624 - 0.7, 15000.0, 21.0, 13112.0, 12479.9, 1130.1, 7.3244 - 0.7, 15000.0, 22.0, 13855.4, 12844.0, 1307.0, 8.2542 - 0.7, 15000.0, 24.0, 15285.0, 13515.0, 1648.6, 9.8351 - 0.7, 15000.0, 26.0, 16649.3, 14120.8, 1994.3, 11.9014 - 0.7, 15000.0, 30.0, 19512.9, 15298.6, 2780.9, 14.827 - 0.7, 15000.0, 34.0, 22204.6, 16304.7, 3606.0, 17.3622 - 0.7, 15000.0, 38.0, 24778.2, 17192.6, 4465.4, 19.5875 - 0.7, 15000.0, 42.0, 27296.1, 18024.8, 5329.0, 23.4826 - 0.7, 15000.0, 46.0, 29762.1, 18805.2, 6235.3, 46.8096 - 0.7, 15000.0, 48.0, 30970.5, 19170.8, 6719.8, 59.383 - 0.7, 15000.0, 50.0, 32171.1, 19528.5, 7209.9, 68.7032 - 0.7, 20000.0, 21.0, 10671.0, 10156.9, 912.4, 5.9185 - 0.7, 20000.0, 22.0, 11276.8, 10454.1, 1053.1, 6.8056 - 0.7, 20000.0, 24.0, 12440.5, 11000.8, 1323.8, 8.3011 - 0.7, 20000.0, 26.0, 13551.0, 11494.4, 1598.0, 9.6082 - 0.7, 20000.0, 30.0, 15882.3, 12454.6, 2221.7, 12.8741 - 0.7, 20000.0, 34.0, 18073.4, 13274.7, 2876.5, 15.2715 - 0.7, 20000.0, 38.0, 20168.3, 13998.5, 3557.9, 17.3754 - 0.7, 20000.0, 42.0, 22217.1, 14676.3, 4242.1, 19.2013 - 0.7, 20000.0, 46.0, 24224.9, 15312.9, 4960.5, 22.3983 - 0.7, 20000.0, 48.0, 25208.3, 15610.7, 5344.4, 30.8596 - 0.7, 20000.0, 50.0, 26185.8, 15902.7, 5731.7, 44.4788 - 0.7, 25000.0, 21.0, 8610.5, 8195.8, 733.3, 4.7574 - 0.7, 25000.0, 22.0, 9099.7, 8436.2, 843.9, 5.3542 - 0.7, 25000.0, 24.0, 10039.4, 8878.3, 1056.5, 6.7662 - 0.7, 25000.0, 26.0, 10936.2, 9277.4, 1272.2, 7.9972 - 0.7, 25000.0, 30.0, 12818.5, 10053.9, 1762.2, 10.8094 - 0.7, 25000.0, 34.0, 14587.3, 10716.9, 2276.5, 13.1665 - 0.7, 25000.0, 38.0, 16278.4, 11302.1, 2811.5, 15.1405 - 0.7, 25000.0, 42.0, 17932.2, 11850.1, 3349.2, 16.8532 - 0.7, 25000.0, 46.0, 19552.5, 12364.7, 3912.9, 18.4489 - 0.7, 25000.0, 48.0, 20346.0, 12605.2, 4213.9, 19.2419 - 0.7, 25000.0, 50.0, 21135.9, 12842.2, 4516.7, 20.8046 - 0.7, 30000.0, 21.0, 6883.1, 6551.6, 586.9, 7.7444 - 0.7, 30000.0, 22.0, 7275.0, 6744.6, 673.2, 5.7924 - 0.7, 30000.0, 24.0, 8027.3, 7099.1, 838.4, 5.2616 - 0.7, 30000.0, 26.0, 8744.9, 7418.9, 1005.9, 6.4147 - 0.7, 30000.0, 30.0, 10251.7, 8041.7, 1387.1, 8.5806 - 0.7, 30000.0, 34.0, 11667.2, 8573.2, 1787.1, 11.0992 - 0.7, 30000.0, 38.0, 13020.3, 9042.3, 2203.0, 12.9445 - 0.7, 30000.0, 42.0, 14343.5, 9481.5, 2621.7, 14.5449 - 0.7, 30000.0, 46.0, 15639.9, 9894.0, 3059.8, 16.0318 - 0.7, 30000.0, 48.0, 16274.9, 10087.0, 3293.1, 16.7705 - 0.7, 30000.0, 50.0, 16906.9, 10277.0, 3528.3, 17.4883 - 0.7, 35000.0, 21.0, 5445.9, 5183.5, 468.4, 10.7259 - 0.7, 35000.0, 22.0, 5757.0, 5337.1, 535.0, 8.7976 - 0.7, 35000.0, 24.0, 6353.6, 5618.9, 661.7, 5.6702 - 0.7, 35000.0, 26.0, 6922.8, 5873.2, 791.0, 4.8981 - 0.7, 35000.0, 30.0, 8117.1, 6367.8, 1083.9, 6.9194 - 0.7, 35000.0, 34.0, 9239.1, 6790.1, 1391.6, 8.6731 - 0.7, 35000.0, 38.0, 10311.5, 7162.7, 1711.2, 10.8441 - 0.7, 35000.0, 42.0, 11359.5, 7511.0, 2033.2, 12.3341 - 0.7, 35000.0, 46.0, 12386.9, 7838.7, 2370.3, 13.7136 - 0.7, 35000.0, 48.0, 12890.1, 7992.0, 2549.7, 14.4009 - 0.7, 35000.0, 50.0, 13391.1, 8143.2, 2729.2, 15.0634 - 0.7, 37000.0, 21.0, 4944.6, 4706.2, 429.8, 11.2106 - 0.7, 37000.0, 22.0, 5227.7, 4846.2, 489.9, 9.3025 - 0.7, 37000.0, 24.0, 5770.2, 5102.7, 604.1, 6.2444 - 0.7, 37000.0, 26.0, 6287.7, 5334.1, 720.9, 4.4868 - 0.7, 37000.0, 30.0, 7373.4, 5784.0, 985.0, 6.4444 - 0.7, 37000.0, 34.0, 8393.3, 6168.3, 1262.6, 8.1407 - 0.7, 37000.0, 38.0, 9368.0, 6507.2, 1551.0, 10.2088 - 0.7, 37000.0, 42.0, 10320.4, 6823.9, 1842.1, 11.6506 - 0.7, 37000.0, 46.0, 11254.0, 7121.8, 2146.1, 12.9821 - 0.7, 37000.0, 48.0, 11711.4, 7261.3, 2308.0, 13.645 - 0.7, 37000.0, 50.0, 12167.0, 7399.1, 2469.7, 14.282 - 0.7, 39000.0, 21.0, 4487.8, 4271.2, 396.9, 10.8462 - 0.7, 39000.0, 22.0, 4745.4, 4398.8, 451.5, 8.9937 - 0.7, 39000.0, 24.0, 5238.7, 4632.3, 555.0, 6.0497 - 0.7, 39000.0, 26.0, 5709.1, 4842.7, 660.9, 4.3014 - 0.7, 39000.0, 30.0, 6696.0, 5252.1, 900.8, 6.1896 - 0.7, 39000.0, 34.0, 7623.1, 5601.6, 1152.7, 7.8201 - 0.7, 39000.0, 38.0, 8508.9, 5909.8, 1414.4, 9.8095 - 0.7, 39000.0, 42.0, 9374.1, 6197.4, 1678.7, 11.196 - 0.7, 39000.0, 46.0, 10222.7, 6468.4, 1955.0, 12.4794 - 0.7, 39000.0, 48.0, 10638.4, 6595.3, 2101.9, 13.1156 - 0.7, 39000.0, 50.0, 11052.6, 6720.7, 2248.2, 13.7233 - 0.7, 41000.0, 21.0, 4072.9, 3876.1, 367.0, 10.4999 - 0.7, 41000.0, 22.0, 4307.3, 3992.4, 416.6, 8.698 - 0.7, 41000.0, 24.0, 4756.0, 4204.9, 510.3, 5.8669 - 0.7, 41000.0, 26.0, 5183.6, 4396.4, 606.4, 4.1214 - 0.7, 41000.0, 30.0, 6080.8, 4768.8, 824.2, 5.9412 - 0.7, 41000.0, 34.0, 6923.7, 5086.9, 1052.9, 7.5111 - 0.7, 41000.0, 38.0, 7728.7, 5367.1, 1290.6, 9.4241 - 0.7, 41000.0, 42.0, 8515.0, 5628.6, 1531.1, 10.7626 - 0.7, 41000.0, 46.0, 9286.2, 5874.9, 1781.7, 11.9963 - 0.7, 41000.0, 48.0, 9664.1, 5990.4, 1914.9, 12.6068 - 0.7, 41000.0, 50.0, 10040.5, 6104.4, 2047.5, 13.1893 - 0.7, 43000.0, 21.0, 3695.7, 3516.9, 340.2, 10.182 - 0.7, 43000.0, 22.0, 3909.2, 3623.1, 385.1, 8.4342 - 0.7, 43000.0, 24.0, 4317.5, 3816.8, 469.8, 5.6921 - 0.7, 43000.0, 26.0, 4706.4, 3991.1, 557.2, 3.9488 - 0.7, 43000.0, 30.0, 5522.1, 4329.9, 754.8, 5.704 - 0.7, 43000.0, 34.0, 6288.3, 4619.3, 962.3, 7.2124 - 0.7, 43000.0, 38.0, 7019.9, 4874.0, 1178.2, 9.0518 - 0.7, 43000.0, 42.0, 7734.6, 5111.8, 1396.8, 10.3435 - 0.7, 43000.0, 46.0, 8435.5, 5335.9, 1624.2, 11.5304 - 0.7, 43000.0, 48.0, 8778.7, 5440.7, 1745.0, 12.1165 - 0.7, 43000.0, 50.0, 9121.2, 5544.6, 1865.4, 12.6763 - 0.75, 20000.0, 21.0, 12099.2, 11578.4, 993.4, 6.5843 - 0.75, 20000.0, 22.0, 12724.0, 11890.6, 1129.3, 7.3857 - 0.75, 20000.0, 24.0, 13920.6, 12462.1, 1410.5, 8.8599 - 0.75, 20000.0, 26.0, 15061.0, 12977.4, 1701.9, 10.3273 - 0.75, 20000.0, 30.0, 17460.5, 13988.0, 2352.5, 13.4976 - 0.75, 20000.0, 34.0, 19714.1, 14852.5, 3037.5, 15.8999 - 0.75, 20000.0, 38.0, 21884.6, 15634.1, 3751.2, 18.0102 - 0.75, 20000.0, 42.0, 24018.9, 16379.3, 4468.2, 19.8495 - 0.75, 20000.0, 46.0, 26105.5, 17076.8, 5219.0, 27.2502 - 0.75, 20000.0, 48.0, 27126.2, 17402.8, 5619.3, 39.5279 - 0.75, 20000.0, 50.0, 28140.0, 17722.3, 6024.0, 53.0099 - 0.75, 25000.0, 21.0, 9763.6, 9343.5, 797.1, 5.1492 - 0.75, 25000.0, 22.0, 10267.9, 9595.8, 903.1, 5.8999 - 0.75, 25000.0, 24.0, 11234.1, 10058.0, 1124.6, 7.2923 - 0.75, 25000.0, 26.0, 12154.7, 10474.5, 1353.8, 8.5338 - 0.75, 25000.0, 30.0, 14092.2, 11291.8, 1864.8, 11.4987 - 0.75, 25000.0, 34.0, 15911.3, 11990.8, 2403.1, 13.7532 - 0.75, 25000.0, 38.0, 17663.3, 12622.6, 2963.2, 15.732 - 0.75, 25000.0, 42.0, 19385.8, 13225.0, 3526.7, 17.4568 - 0.75, 25000.0, 46.0, 21070.1, 13789.1, 4116.3, 19.0568 - 0.75, 25000.0, 48.0, 21894.0, 14052.8, 4429.6, 19.8471 - 0.75, 25000.0, 50.0, 22712.7, 14311.6, 4746.3, 24.5603 - 0.75, 30000.0, 21.0, 7805.4, 7469.7, 636.6, 6.2175 - 0.75, 30000.0, 22.0, 8209.2, 7672.0, 718.6, 4.557 - 0.75, 30000.0, 24.0, 8982.7, 8042.7, 891.3, 5.7565 - 0.75, 30000.0, 26.0, 9719.7, 8376.8, 1069.8, 6.9217 - 0.75, 30000.0, 30.0, 11270.2, 9032.1, 1467.1, 9.0687 - 0.75, 30000.0, 34.0, 12725.6, 9592.3, 1885.5, 11.6454 - 0.75, 30000.0, 38.0, 14127.3, 10098.7, 2320.9, 13.4935 - 0.75, 30000.0, 42.0, 15505.2, 10581.3, 2759.3, 15.1024 - 0.75, 30000.0, 46.0, 16852.7, 11033.5, 3217.1, 16.5918 - 0.75, 30000.0, 48.0, 17511.6, 11244.9, 3461.0, 17.331 - 0.75, 30000.0, 50.0, 18167.3, 11452.9, 3705.8, 18.0435 - 0.75, 35000.0, 21.0, 6176.3, 5910.6, 506.6, 9.2124 - 0.75, 35000.0, 22.0, 6496.8, 6071.7, 569.8, 7.5518 - 0.75, 35000.0, 24.0, 7110.0, 6366.1, 702.3, 4.5131 - 0.75, 35000.0, 26.0, 7694.4, 6631.6, 839.8, 5.3704 - 0.75, 35000.0, 30.0, 8923.6, 7152.1, 1145.3, 7.3736 - 0.75, 35000.0, 34.0, 10077.2, 7597.2, 1467.2, 9.1266 - 0.75, 35000.0, 38.0, 11187.9, 7999.4, 1801.8, 11.3524 - 0.75, 35000.0, 42.0, 12279.4, 8382.4, 2139.1, 12.8488 - 0.75, 35000.0, 46.0, 13347.0, 8741.4, 2491.2, 14.2339 - 0.75, 35000.0, 48.0, 13869.4, 8909.5, 2678.5, 14.9197 - 0.75, 35000.0, 50.0, 14389.1, 9075.0, 2865.5, 15.5782 - 0.75, 37000.0, 21.0, 5608.1, 5366.7, 464.3, 9.7221 - 0.75, 37000.0, 22.0, 5899.7, 5513.5, 521.3, 8.0824 - 0.75, 37000.0, 24.0, 6457.4, 5781.4, 640.8, 5.1113 - 0.75, 37000.0, 26.0, 6988.6, 6023.0, 764.9, 4.9447 - 0.75, 37000.0, 30.0, 8106.0, 6496.6, 1040.5, 6.8848 - 0.75, 37000.0, 34.0, 9154.7, 6901.6, 1331.0, 8.58 - 0.75, 37000.0, 38.0, 10164.2, 7267.4, 1632.9, 10.6998 - 0.75, 37000.0, 42.0, 11156.1, 7615.6, 1937.4, 12.1486 - 0.75, 37000.0, 46.0, 12126.5, 7942.2, 2255.5, 13.4852 - 0.75, 37000.0, 48.0, 12601.0, 8094.8, 2424.1, 14.1465 - 0.75, 37000.0, 50.0, 13073.6, 8245.6, 2592.2, 14.7777 - 0.75, 39000.0, 21.0, 5090.3, 4871.0, 428.1, 9.413 - 0.75, 39000.0, 22.0, 5355.6, 5004.7, 479.9, 7.8205 - 0.75, 39000.0, 24.0, 5862.7, 5248.6, 588.2, 4.959 - 0.75, 39000.0, 26.0, 6345.7, 5468.4, 700.9, 4.7432 - 0.75, 39000.0, 30.0, 7361.5, 5899.2, 951.1, 6.612 - 0.75, 39000.0, 34.0, 8314.7, 6267.5, 1214.7, 8.2426 - 0.75, 39000.0, 38.0, 9232.3, 6600.2, 1488.9, 10.2835 - 0.75, 39000.0, 42.0, 10133.6, 6916.7, 1765.7, 11.6794 - 0.75, 39000.0, 46.0, 11015.2, 7213.4, 2054.3, 12.9644 - 0.75, 39000.0, 48.0, 11446.7, 7352.4, 2207.5, 13.5999 - 0.75, 39000.0, 50.0, 11876.3, 7489.5, 2360.1, 14.2058 - 0.75, 41000.0, 21.0, 4620.0, 4420.7, 395.3, 9.1163 - 0.75, 41000.0, 22.0, 4861.4, 4542.5, 442.3, 7.5735 - 0.75, 41000.0, 24.0, 5322.7, 4764.6, 540.6, 4.8099 - 0.75, 41000.0, 26.0, 5761.8, 4964.6, 642.9, 4.5487 - 0.75, 41000.0, 30.0, 6685.2, 5356.6, 869.9, 6.3495 - 0.75, 41000.0, 34.0, 7551.8, 5691.7, 1109.2, 7.9189 - 0.75, 41000.0, 38.0, 8385.8, 5994.3, 1358.1, 9.8824 - 0.75, 41000.0, 42.0, 9204.8, 6281.8, 1609.8, 11.2269 - 0.75, 41000.0, 46.0, 10006.1, 6551.7, 1872.0, 12.4638 - 0.75, 41000.0, 48.0, 10398.3, 6678.1, 2010.9, 13.0741 - 0.75, 41000.0, 50.0, 10788.7, 6802.8, 2149.4, 13.6567 - 0.75, 43000.0, 21.0, 4192.7, 4011.6, 365.5, 8.8388 - 0.75, 43000.0, 22.0, 4412.3, 4122.6, 408.2, 7.3458 - 0.75, 43000.0, 24.0, 4832.0, 4324.9, 497.1, 4.6778 - 0.75, 43000.0, 26.0, 5231.3, 4506.9, 590.1, 4.3594 - 0.75, 43000.0, 30.0, 6071.0, 4863.7, 796.3, 6.0969 - 0.75, 43000.0, 34.0, 6858.8, 5168.6, 1013.4, 7.606 - 0.75, 43000.0, 38.0, 7616.8, 5443.7, 1239.5, 9.4944 - 0.75, 43000.0, 42.0, 8361.0, 5705.0, 1468.3, 10.7912 - 0.75, 43000.0, 46.0, 9089.4, 5950.4, 1706.1, 11.9799 - 0.75, 43000.0, 48.0, 9445.7, 6065.4, 1832.3, 12.5674 - 0.75, 43000.0, 50.0, 9800.8, 6179.0, 1958.1, 13.1272 - 0.79, 20000.0, 21.0, 13316.7, 12788.5, 1056.2, 7.085 - 0.79, 20000.0, 22.0, 13958.5, 13113.3, 1191.3, 7.8437 - 0.79, 20000.0, 24.0, 15183.9, 13704.9, 1486.2, 9.3251 - 0.79, 20000.0, 26.0, 16353.4, 14240.4, 1788.3, 11.2602 - 0.79, 20000.0, 30.0, 18814.0, 15292.3, 2465.9, 14.0199 - 0.79, 20000.0, 34.0, 21136.0, 16205.7, 3176.5, 16.4247 - 0.79, 20000.0, 38.0, 23387.7, 17048.6, 3921.0, 18.5484 - 0.79, 20000.0, 42.0, 25599.2, 17851.6, 4668.4, 20.4014 - 0.79, 20000.0, 46.0, 27757.9, 18601.6, 5449.7, 33.7104 - 0.79, 20000.0, 48.0, 28812.4, 18951.7, 5865.5, 47.6231 - 0.79, 20000.0, 50.0, 29859.3, 19294.4, 6286.5, 58.7708 - 0.79, 25000.0, 21.0, 10746.2, 10320.3, 846.3, 5.6217 - 0.79, 25000.0, 22.0, 11264.8, 10583.2, 952.1, 6.3348 - 0.79, 25000.0, 24.0, 12254.3, 11061.5, 1184.1, 7.73 - 0.79, 25000.0, 26.0, 13198.3, 11494.4, 1421.7, 8.9669 - 0.79, 25000.0, 30.0, 15184.9, 12345.0, 1954.0, 11.9882 - 0.79, 25000.0, 34.0, 17059.4, 13083.5, 2512.5, 14.2443 - 0.79, 25000.0, 38.0, 18877.2, 13765.2, 3097.0, 16.2353 - 0.79, 25000.0, 42.0, 20662.0, 14414.1, 3683.6, 17.9702 - 0.79, 25000.0, 46.0, 22404.6, 15020.7, 4297.5, 19.5778 - 0.79, 25000.0, 48.0, 23255.8, 15303.8, 4623.5, 21.9802 - 0.79, 25000.0, 50.0, 24101.0, 15581.1, 4952.6, 29.7794 - 0.79, 30000.0, 21.0, 8591.6, 8251.2, 675.0, 5.0944 - 0.79, 30000.0, 22.0, 9006.5, 8461.9, 756.7, 4.8532 - 0.79, 30000.0, 24.0, 9798.6, 8845.4, 937.1, 6.1642 - 0.79, 30000.0, 26.0, 10554.1, 9192.5, 1122.5, 7.3259 - 0.79, 30000.0, 30.0, 12143.7, 9874.3, 1536.0, 9.4741 - 0.79, 30000.0, 34.0, 13643.5, 10466.3, 1970.6, 12.1021 - 0.79, 30000.0, 38.0, 15097.6, 11012.7, 2424.8, 13.9599 - 0.79, 30000.0, 42.0, 16525.2, 11532.5, 2881.4, 15.5783 - 0.79, 30000.0, 46.0, 17919.4, 12018.9, 3357.8, 17.0748 - 0.79, 30000.0, 48.0, 18600.1, 12245.8, 3611.2, 17.8146 - 0.79, 30000.0, 50.0, 19277.1, 12468.8, 3865.8, 18.5261 - 0.79, 35000.0, 21.0, 6798.9, 6529.5, 536.1, 8.112 - 0.79, 35000.0, 22.0, 7128.1, 6697.1, 598.7, 6.5792 - 0.79, 35000.0, 24.0, 7756.4, 7002.1, 737.5, 4.6585 - 0.79, 35000.0, 26.0, 8355.2, 7277.7, 880.4, 5.7496 - 0.79, 35000.0, 30.0, 9615.4, 7819.4, 1198.4, 7.7528 - 0.79, 35000.0, 34.0, 10803.8, 8289.5, 1532.7, 9.805 - 0.79, 35000.0, 38.0, 11956.1, 8723.4, 1881.7, 11.7838 - 0.79, 35000.0, 42.0, 13087.1, 9135.9, 2232.9, 13.2881 - 0.79, 35000.0, 46.0, 14191.7, 9522.2, 2599.6, 14.681 - 0.79, 35000.0, 48.0, 14731.2, 9702.5, 2793.6, 15.3669 - 0.79, 35000.0, 50.0, 15267.9, 9880.0, 2987.8, 16.0243 - 0.79, 37000.0, 21.0, 6173.6, 5928.9, 490.9, 8.6418 - 0.79, 37000.0, 22.0, 6473.1, 6081.5, 547.1, 7.1362 - 0.79, 37000.0, 24.0, 7044.4, 6359.1, 672.3, 4.2757 - 0.79, 37000.0, 26.0, 7588.8, 6609.9, 801.5, 5.3123 - 0.79, 37000.0, 30.0, 8734.3, 7102.7, 1088.2, 7.2492 - 0.79, 37000.0, 34.0, 9814.5, 7530.3, 1389.7, 8.9444 - 0.79, 37000.0, 38.0, 10862.0, 7925.1, 1704.9, 11.1167 - 0.79, 37000.0, 42.0, 11889.7, 8300.2, 2022.2, 12.5731 - 0.79, 37000.0, 46.0, 12893.6, 8651.4, 2352.9, 13.9174 - 0.79, 37000.0, 48.0, 13383.9, 8815.5, 2528.3, 14.5794 - 0.79, 37000.0, 50.0, 13871.8, 8977.0, 2703.4, 15.2136 - 0.79, 39000.0, 21.0, 5603.8, 5381.5, 452.2, 8.3724 - 0.79, 39000.0, 22.0, 5876.3, 5520.5, 503.1, 6.9121 - 0.79, 39000.0, 24.0, 6395.9, 5773.3, 616.7, 4.1333 - 0.79, 39000.0, 26.0, 6890.8, 6001.3, 734.2, 5.0969 - 0.79, 39000.0, 30.0, 7932.0, 6449.6, 994.3, 6.962 - 0.79, 39000.0, 34.0, 8914.2, 6838.7, 1268.4, 8.5965 - 0.79, 39000.0, 38.0, 9866.0, 7197.6, 1554.3, 10.685 - 0.79, 39000.0, 42.0, 10799.9, 7538.5, 1842.4, 12.0879 - 0.79, 39000.0, 46.0, 11712.2, 7857.8, 2143.1, 13.3818 - 0.79, 39000.0, 48.0, 12157.8, 8007.0, 2302.2, 14.0174 - 0.79, 39000.0, 50.0, 12601.3, 8153.9, 2461.0, 14.6254 - 0.79, 41000.0, 21.0, 5086.2, 4884.2, 417.1, 8.114 - 0.79, 41000.0, 22.0, 5334.1, 5010.8, 463.4, 6.7051 - 0.79, 41000.0, 24.0, 5806.8, 5241.1, 566.2, 3.9985 - 0.79, 41000.0, 26.0, 6256.7, 5448.5, 672.9, 4.8879 - 0.79, 41000.0, 30.0, 7203.5, 5856.5, 909.4, 6.6888 - 0.79, 41000.0, 34.0, 8096.2, 6210.4, 1158.0, 8.2594 - 0.79, 41000.0, 38.0, 8961.4, 6536.8, 1417.5, 10.2694 - 0.79, 41000.0, 42.0, 9810.0, 6846.6, 1679.3, 11.621 - 0.79, 41000.0, 46.0, 10639.2, 7136.9, 1952.5, 12.8649 - 0.79, 41000.0, 48.0, 11044.2, 7272.6, 2096.9, 13.4762 - 0.79, 41000.0, 50.0, 11447.3, 7406.3, 2241.1, 14.0615 - 0.8, 20000.0, 21.0, 13631.6, 13101.2, 1071.7, 7.2066 - 0.8, 20000.0, 22.0, 14277.9, 13429.2, 1206.9, 7.9564 - 0.8, 20000.0, 24.0, 15511.1, 14025.9, 1505.6, 9.4413 - 0.8, 20000.0, 26.0, 16688.8, 14567.1, 1810.3, 11.3981 - 0.8, 20000.0, 30.0, 19165.5, 15629.4, 2495.5, 14.1535 - 0.8, 20000.0, 34.0, 21509.9, 16559.4, 3213.1, 16.5599 - 0.8, 20000.0, 38.0, 23783.7, 17418.7, 3966.3, 18.6886 - 0.8, 20000.0, 42.0, 26016.0, 18236.5, 4721.8, 20.5452 - 0.8, 20000.0, 46.0, 28194.2, 19000.4, 5512.1, 35.7201 - 0.8, 20000.0, 48.0, 29257.3, 19356.5, 5932.0, 49.6781 - 0.8, 20000.0, 50.0, 30313.1, 19704.9, 6356.8, 59.9573 - 0.8, 25000.0, 21.0, 11000.5, 10572.8, 858.4, 5.7369 - 0.8, 25000.0, 22.0, 11522.8, 10838.4, 964.5, 6.4424 - 0.8, 25000.0, 24.0, 12518.5, 11320.9, 1199.4, 7.8407 - 0.8, 25000.0, 26.0, 13468.9, 11757.9, 1438.7, 9.0737 - 0.8, 25000.0, 30.0, 15468.6, 12617.0, 1976.9, 12.1112 - 0.8, 25000.0, 34.0, 17361.2, 13369.0, 2541.0, 14.3696 - 0.8, 25000.0, 38.0, 19196.7, 14063.9, 3132.5, 16.3657 - 0.8, 25000.0, 42.0, 20998.4, 14725.0, 3725.7, 18.1043 - 0.8, 25000.0, 46.0, 22756.7, 15342.6, 4346.4, 19.7156 - 0.8, 25000.0, 48.0, 23614.9, 15630.5, 4675.4, 22.8123 - 0.8, 25000.0, 50.0, 24467.2, 15912.5, 5007.9, 31.4463 - 0.8, 30000.0, 21.0, 8794.9, 8453.1, 684.4, 4.8251 - 0.8, 30000.0, 22.0, 9212.8, 8666.0, 766.2, 4.9546 - 0.8, 30000.0, 24.0, 10009.9, 9052.9, 949.1, 6.2683 - 0.8, 30000.0, 26.0, 10770.5, 9403.4, 1135.9, 7.4268 - 0.8, 30000.0, 30.0, 12370.4, 10092.0, 1554.2, 9.6026 - 0.8, 30000.0, 34.0, 13884.6, 10694.7, 1993.0, 12.2194 - 0.8, 30000.0, 38.0, 15352.8, 11251.5, 2452.3, 14.0807 - 0.8, 30000.0, 42.0, 16793.7, 11781.1, 2913.8, 15.7013 - 0.8, 30000.0, 46.0, 18200.3, 12276.3, 3395.6, 17.2013 - 0.8, 30000.0, 48.0, 18886.8, 12507.0, 3651.1, 17.9402 - 0.8, 30000.0, 50.0, 19569.5, 12734.0, 3908.4, 18.6521 - 0.8, 35000.0, 21.0, 6959.9, 6689.4, 543.4, 7.8502 - 0.8, 35000.0, 22.0, 7291.5, 6858.8, 606.0, 6.339 - 0.8, 35000.0, 24.0, 7923.7, 7166.4, 746.6, 4.7559 - 0.8, 35000.0, 26.0, 8526.5, 7444.7, 890.7, 5.8442 - 0.8, 35000.0, 30.0, 9794.9, 7991.8, 1212.3, 7.8493 - 0.8, 35000.0, 34.0, 10994.6, 8470.3, 1549.7, 9.9967 - 0.8, 35000.0, 38.0, 12158.1, 8912.6, 1902.7, 11.8951 - 0.8, 35000.0, 42.0, 13299.6, 9332.9, 2257.9, 13.4031 - 0.8, 35000.0, 46.0, 14413.9, 9725.9, 2628.2, 14.7963 - 0.8, 35000.0, 48.0, 14958.1, 9909.5, 2824.3, 15.483 - 0.8, 35000.0, 50.0, 15499.3, 10090.1, 3020.9, 16.1418 - 0.8, 37000.0, 21.0, 6319.9, 6074.2, 497.4, 8.3849 - 0.8, 37000.0, 22.0, 6621.5, 6228.4, 553.7, 6.9012 - 0.8, 37000.0, 24.0, 7196.4, 6508.4, 680.6, 4.3469 - 0.8, 37000.0, 26.0, 7744.3, 6761.5, 810.7, 5.4024 - 0.8, 37000.0, 30.0, 8897.5, 7259.4, 1100.8, 7.3437 - 0.8, 37000.0, 34.0, 9988.0, 7694.8, 1405.5, 9.0829 - 0.8, 37000.0, 38.0, 11045.4, 8096.9, 1723.9, 11.2241 - 0.8, 37000.0, 42.0, 12082.7, 8479.1, 2044.4, 12.6821 - 0.8, 37000.0, 46.0, 13095.6, 8836.7, 2378.8, 14.0299 - 0.8, 37000.0, 48.0, 13590.1, 9003.6, 2555.9, 14.6924 - 0.8, 37000.0, 50.0, 14082.1, 9167.9, 2733.1, 15.3273 - 0.8, 39000.0, 21.0, 5736.6, 5513.4, 458.1, 8.1251 - 0.8, 39000.0, 22.0, 6011.0, 5653.8, 509.0, 6.6908 - 0.8, 39000.0, 24.0, 6533.9, 5908.8, 624.2, 4.1644 - 0.8, 39000.0, 26.0, 7032.1, 6139.1, 742.6, 5.1849 - 0.8, 39000.0, 30.0, 8080.3, 6592.0, 1005.9, 7.0545 - 0.8, 39000.0, 34.0, 9071.6, 6988.0, 1282.5, 8.7133 - 0.8, 39000.0, 38.0, 10032.7, 7353.7, 1571.6, 10.789 - 0.8, 39000.0, 42.0, 10975.1, 7701.0, 1862.9, 12.1943 - 0.8, 39000.0, 46.0, 11895.7, 8026.0, 2166.6, 13.4902 - 0.8, 39000.0, 48.0, 12345.1, 8177.9, 2327.3, 14.1257 - 0.8, 39000.0, 50.0, 12792.3, 8327.3, 2488.0, 14.7358 - 0.8, 41000.0, 21.0, 5206.8, 5004.0, 422.5, 7.8759 - 0.8, 41000.0, 22.0, 5456.4, 5131.9, 468.7, 6.4921 - 0.8, 41000.0, 24.0, 5932.1, 5364.1, 573.0, 3.9876 - 0.8, 41000.0, 26.0, 6385.0, 5573.6, 680.6, 4.9727 - 0.8, 41000.0, 30.0, 7338.1, 5985.7, 919.7, 6.7752 - 0.8, 41000.0, 34.0, 8239.2, 6346.0, 1170.8, 8.3569 - 0.8, 41000.0, 38.0, 9112.8, 6678.6, 1433.3, 10.3696 - 0.8, 41000.0, 42.0, 9969.4, 6994.3, 1697.9, 11.7243 - 0.8, 41000.0, 46.0, 10805.8, 7289.8, 1973.9, 12.9692 - 0.8, 41000.0, 48.0, 11214.3, 7427.8, 2119.8, 13.581 - 0.8, 41000.0, 50.0, 11620.8, 7563.8, 2265.5, 14.1666 - 0.8, 43000.0, 21.0, 4725.6, 4541.3, 390.2, 7.6384 - 0.8, 43000.0, 22.0, 4952.6, 4657.7, 432.1, 6.3043 - 0.8, 43000.0, 24.0, 5385.5, 4869.4, 526.6, 3.8166 - 0.8, 43000.0, 26.0, 5797.4, 5060.1, 624.5, 4.7702 - 0.8, 43000.0, 30.0, 6664.0, 5435.0, 841.4, 6.5063 - 0.8, 43000.0, 34.0, 7483.3, 5762.9, 1069.3, 8.0181 - 0.8, 43000.0, 38.0, 8277.5, 6065.4, 1307.7, 9.9658 - 0.8, 43000.0, 42.0, 9055.9, 6352.3, 1548.6, 11.2718 - 0.8, 43000.0, 46.0, 9816.3, 6621.1, 1799.0, 12.4684 - 0.8, 43000.0, 48.0, 10187.6, 6746.6, 1931.5, 13.0575 - 0.8, 43000.0, 50.0, 10556.9, 6870.2, 2063.5, 13.6188 - 0.85, 20000.0, 21.0, 15269.7, 14726.9, 1148.4, 7.7963 - 0.85, 20000.0, 22.0, 15940.5, 15071.8, 1286.4, 8.5229 - 0.85, 20000.0, 24.0, 17216.3, 15696.2, 1605.0, 10.037 - 0.85, 20000.0, 26.0, 18437.2, 16265.7, 1923.0, 12.0458 - 0.85, 20000.0, 30.0, 21018.2, 17399.0, 2650.6, 14.837 - 0.85, 20000.0, 34.0, 23493.4, 18426.4, 3408.9, 17.2645 - 0.85, 20000.0, 38.0, 25884.8, 19370.2, 4206.9, 19.4142 - 0.85, 20000.0, 42.0, 28229.3, 20267.0, 5007.6, 23.7977 - 0.85, 20000.0, 46.0, 30511.4, 21101.3, 5843.9, 46.826 - 0.85, 20000.0, 48.0, 31623.3, 21489.2, 6287.4, 58.5793 - 0.85, 20000.0, 50.0, 32726.4, 21868.7, 6737.1, 67.2902 - 0.85, 25000.0, 21.0, 12322.9, 11885.2, 918.3, 6.2921 - 0.85, 25000.0, 22.0, 12864.9, 12164.6, 1027.0, 6.9769 - 0.85, 25000.0, 24.0, 13894.8, 12669.2, 1277.4, 8.3905 - 0.85, 25000.0, 26.0, 14880.2, 13129.4, 1527.5, 9.6187 - 0.85, 25000.0, 30.0, 16963.6, 14045.5, 2098.8, 12.7509 - 0.85, 25000.0, 34.0, 18961.6, 14876.3, 2695.0, 15.0269 - 0.85, 25000.0, 38.0, 20891.7, 15639.3, 3321.4, 17.0425 - 0.85, 25000.0, 42.0, 22783.5, 16363.9, 3949.4, 18.7996 - 0.85, 25000.0, 46.0, 24625.9, 17039.0, 4606.3, 21.7264 - 0.85, 25000.0, 48.0, 25523.3, 17352.8, 4953.5, 29.2527 - 0.85, 25000.0, 50.0, 26413.9, 17659.8, 5304.8, 41.448 - 0.85, 30000.0, 21.0, 9852.7, 9503.0, 730.5, 4.817 - 0.85, 30000.0, 22.0, 10286.3, 9726.8, 814.8, 5.4569 - 0.85, 30000.0, 24.0, 11110.8, 10131.7, 1009.8, 6.7844 - 0.85, 30000.0, 26.0, 11899.3, 10500.5, 1204.7, 7.9341 - 0.85, 30000.0, 30.0, 13566.3, 11234.9, 1649.0, 10.6836 - 0.85, 30000.0, 34.0, 15164.4, 11900.5, 2112.4, 12.8292 - 0.85, 30000.0, 38.0, 16708.5, 12512.1, 2599.3, 14.7084 - 0.85, 30000.0, 42.0, 18221.3, 13092.4, 3087.7, 16.346 - 0.85, 30000.0, 46.0, 19695.1, 13633.6, 3597.6, 17.8596 - 0.85, 30000.0, 48.0, 20413.3, 13885.5, 3867.4, 18.6028 - 0.85, 30000.0, 50.0, 21126.4, 14132.3, 4139.7, 19.3169 - 0.85, 35000.0, 21.0, 7797.5, 7520.8, 578.7, 6.6087 - 0.85, 35000.0, 22.0, 8141.8, 7699.1, 643.4, 5.1541 - 0.85, 35000.0, 24.0, 8795.7, 8020.9, 793.4, 5.2408 - 0.85, 35000.0, 26.0, 9420.6, 8313.7, 943.8, 6.3186 - 0.85, 35000.0, 30.0, 10741.8, 8897.0, 1284.8, 8.3419 - 0.85, 35000.0, 34.0, 12008.4, 9425.6, 1641.7, 10.725 - 0.85, 35000.0, 38.0, 13232.1, 9911.4, 2016.1, 12.4766 - 0.85, 35000.0, 42.0, 14430.9, 10372.2, 2391.9, 13.999 - 0.85, 35000.0, 46.0, 15598.6, 10802.0, 2783.9, 15.4058 - 0.85, 35000.0, 48.0, 16167.5, 11002.0, 2990.7, 16.095 - 0.85, 35000.0, 50.0, 16732.6, 11198.0, 3199.2, 16.7582 - 0.85, 37000.0, 21.0, 7080.7, 6829.3, 529.2, 7.1696 - 0.85, 37000.0, 22.0, 7393.9, 6991.7, 587.4, 5.7449 - 0.85, 37000.0, 24.0, 7988.5, 7284.6, 722.8, 4.8169 - 0.85, 37000.0, 26.0, 8556.5, 7551.0, 858.6, 5.8624 - 0.85, 37000.0, 30.0, 9757.7, 8081.8, 1166.5, 7.8217 - 0.85, 37000.0, 34.0, 10908.7, 8562.5, 1488.5, 10.0732 - 0.85, 37000.0, 38.0, 12020.9, 9004.3, 1826.1, 11.7857 - 0.85, 37000.0, 42.0, 13110.2, 9423.3, 2165.5, 13.2592 - 0.85, 37000.0, 46.0, 14171.0, 9813.8, 2518.9, 14.6171 - 0.85, 37000.0, 48.0, 14688.6, 9996.1, 2705.6, 15.2834 - 0.85, 37000.0, 50.0, 15202.3, 10174.6, 2893.4, 15.9241 - 0.85, 39000.0, 21.0, 6427.5, 6199.1, 487.0, 6.9546 - 0.85, 39000.0, 22.0, 6712.2, 6346.7, 539.4, 5.589 - 0.85, 39000.0, 24.0, 7253.1, 6613.6, 662.4, 4.6165 - 0.85, 39000.0, 26.0, 7769.4, 6855.8, 785.8, 5.6258 - 0.85, 39000.0, 30.0, 8861.3, 7338.7, 1065.5, 7.514 - 0.85, 39000.0, 34.0, 9907.4, 7775.8, 1357.5, 9.6651 - 0.85, 39000.0, 38.0, 10918.3, 8177.7, 1664.3, 11.3296 - 0.85, 39000.0, 42.0, 11908.0, 8558.4, 1972.4, 12.7479 - 0.85, 39000.0, 46.0, 12872.3, 8913.7, 2293.5, 14.056 - 0.85, 39000.0, 48.0, 13342.3, 9079.2, 2463.0, 14.6952 - 0.85, 39000.0, 50.0, 13809.4, 9241.8, 2633.5, 15.3107 - 0.9, 35000.0, 21.0, 8689.9, 8405.4, 612.6, 5.4642 - 0.9, 35000.0, 22.0, 9048.1, 8592.9, 681.7, 4.4604 - 0.9, 35000.0, 24.0, 9727.3, 8930.8, 841.5, 5.7208 - 0.9, 35000.0, 26.0, 10383.2, 9245.3, 999.3, 6.7969 - 0.9, 35000.0, 30.0, 11785.1, 9888.5, 1365.6, 8.8636 - 0.9, 35000.0, 34.0, 13126.8, 10471.6, 1745.1, 11.3302 - 0.9, 35000.0, 38.0, 14418.8, 11005.1, 2142.8, 13.0965 - 0.9, 35000.0, 42.0, 15682.3, 11509.9, 2543.0, 14.6396 - 0.9, 35000.0, 46.0, 16909.5, 11978.5, 2959.3, 16.0593 - 0.9, 35000.0, 48.0, 17506.0, 12195.7, 3179.8, 16.7568 - 0.9, 35000.0, 50.0, 18098.7, 12409.1, 3401.9, 17.4262 - 0.9, 37000.0, 21.0, 7891.3, 7632.9, 559.6, 6.0554 - 0.9, 37000.0, 22.0, 8217.1, 7803.6, 621.9, 4.6273 - 0.9, 37000.0, 24.0, 8834.9, 8111.3, 766.2, 5.2826 - 0.9, 37000.0, 26.0, 9431.0, 8397.2, 908.7, 6.3254 - 0.9, 37000.0, 30.0, 10705.5, 8982.6, 1239.4, 8.326 - 0.9, 37000.0, 34.0, 11924.9, 9512.8, 1581.3, 10.6732 - 0.9, 37000.0, 38.0, 13099.4, 9998.1, 1940.8, 12.3857 - 0.9, 37000.0, 42.0, 14247.6, 10457.1, 2302.0, 13.878 - 0.9, 37000.0, 46.0, 15363.1, 10883.5, 2678.2, 15.2518 - 0.9, 37000.0, 48.0, 15905.5, 11081.3, 2876.5, 15.9229 - 0.9, 37000.0, 50.0, 16443.8, 11275.0, 3076.2, 16.5691 - 0.9, 39000.0, 21.0, 7163.6, 6928.7, 514.4, 5.8837 - 0.9, 39000.0, 22.0, 7459.9, 7084.2, 570.9, 4.5067 - 0.9, 39000.0, 24.0, 8021.6, 7364.1, 701.6, 5.0624 - 0.9, 39000.0, 26.0, 8563.7, 7624.5, 831.4, 6.0727 - 0.9, 39000.0, 30.0, 9722.3, 8156.9, 1131.6, 7.9996 - 0.9, 39000.0, 34.0, 10830.8, 8639.2, 1442.2, 10.2576 - 0.9, 39000.0, 38.0, 11898.0, 9080.3, 1768.2, 11.9058 - 0.9, 39000.0, 42.0, 12941.4, 9497.6, 2096.6, 13.3448 - 0.9, 39000.0, 46.0, 13955.2, 9885.2, 2438.2, 14.6669 - 0.9, 39000.0, 48.0, 14447.9, 10064.9, 2618.2, 15.3126 - 0.9, 39000.0, 50.0, 14937.5, 10241.3, 2799.5, 15.9332 diff --git a/aviary/models/engines/turbofan_28k_with_electric.deck b/aviary/models/engines/turbofan_28k_with_electric.deck deleted file mode 100644 index 3ccbebe773..0000000000 --- a/aviary/models/engines/turbofan_28k_with_electric.deck +++ /dev/null @@ -1,1112 +0,0 @@ -Mach_Number (unitless), Altitude (ft), Throttle (unitless), Gross_Thrust (lbf), Ram_Drag (lbf), Fuel_Flow (lb/h), NOx_Rate (lb/h),electric_power_in (kW) - 0.0, 0.0, 21.0, 1446.4, 0.0, 842.2, 4.7876, 14.464 - 0.0, 0.0, 22.0, 2314.3, 0.0, 976.0, 5.1926, 23.143 - 0.0, 0.0, 24.0, 4049.9, 0.0, 1281.0, 6.6532, 40.499 - 0.0, 0.0, 26.0, 5785.6, 0.0, 1659.9, 8.2234, 57.856 - 0.0, 0.0, 30.0, 9642.7, 0.0, 2621.6, 12.0946, 96.427 - 0.0, 0.0, 34.0, 13499.8, 0.0, 3673.3, 15.0321, 134.998 - 0.0, 0.0, 38.0, 17356.9, 0.0, 4795.2, 17.5877, 173.56900000000002 - 0.0, 0.0, 42.0, 21214.0, 0.0, 5979.1, 19.8547, 212.14000000000001 - 0.0, 0.0, 46.0, 25071.1, 0.0, 7258.1, 33.3976, 250.71099999999998 - 0.0, 0.0, 48.0, 26999.7, 0.0, 7932.6, 49.2185, 269.997 - 0.0, 0.0, 50.0, 28928.1, 0.0, 8662.3, 61.9894, 289.281 - 0.0, 2000.0, 21.0, 1446.4, 0.0, 781.8, 5.2521, 14.464 - 0.0, 2000.0, 22.0, 2314.2, 0.0, 914.2, 5.1431, 23.142 - 0.0, 2000.0, 24.0, 4049.9, 0.0, 1220.2, 6.7284, 40.499 - 0.0, 2000.0, 26.0, 5785.6, 0.0, 1608.2, 8.4472, 57.856 - 0.0, 2000.0, 30.0, 9642.7, 0.0, 2572.5, 12.5205, 96.427 - 0.0, 2000.0, 34.0, 13499.7, 0.0, 3624.6, 15.6007, 134.997 - 0.0, 2000.0, 38.0, 17356.8, 0.0, 4748.2, 18.2407, 173.56799999999998 - 0.0, 2000.0, 42.0, 21213.8, 0.0, 5953.1, 20.6168, 212.138 - 0.0, 2000.0, 46.0, 25070.8, 0.0, 7274.3, 46.5192, 250.708 - 0.0, 2000.0, 48.0, 26999.7, 0.0, 8005.4, 61.6004, 269.997 - 0.0, 2000.0, 50.0, 28928.0, 0.0, 8769.0, 72.5104, 289.28000000000003 - 0.0, 5000.0, 21.0, 1338.1, 0.0, 706.8, 6.8008, 13.381 - 0.0, 5000.0, 22.0, 2140.9, 0.0, 828.3, 5.03, 21.409000000000002 - 0.0, 5000.0, 24.0, 3746.7, 0.0, 1111.0, 6.2319, 37.467 - 0.0, 5000.0, 26.0, 5352.3, 0.0, 1469.9, 7.9885, 53.523 - 0.0, 5000.0, 30.0, 8920.6, 0.0, 2355.4, 12.0275, 89.206 - 0.0, 5000.0, 34.0, 12488.9, 0.0, 3323.4, 15.1312, 124.889 - 0.0, 5000.0, 38.0, 16057.1, 0.0, 4353.1, 17.7742, 160.571 - 0.0, 5000.0, 42.0, 19625.3, 0.0, 5473.5, 20.1814, 196.253 - 0.0, 5000.0, 46.0, 23193.5, 0.0, 6708.4, 39.1314, 231.935 - 0.0, 5000.0, 48.0, 24977.9, 0.0, 7391.9, 57.3145, 249.77900000000002 - 0.0, 5000.0, 50.0, 26761.8, 0.0, 8104.6, 69.2582, 267.618 - 0.1, 0.0, 21.0, 2503.9, 1057.5, 905.8, 4.7726, 25.039 - 0.1, 0.0, 22.0, 3575.1, 1260.9, 1088.1, 5.7209, 35.751 - 0.1, 0.0, 24.0, 5626.3, 1576.4, 1525.4, 7.6905, 56.263000000000005 - 0.1, 0.0, 26.0, 7615.0, 1829.5, 2001.1, 9.4545, 76.15 - 0.1, 0.0, 30.0, 11922.9, 2280.3, 3129.8, 13.5965, 119.229 - 0.1, 0.0, 34.0, 16145.2, 2645.4, 4326.3, 16.5878, 161.452 - 0.1, 0.0, 38.0, 20316.5, 2959.7, 5587.6, 19.1578, 203.165 - 0.1, 0.0, 42.0, 24452.2, 3238.4, 6932.0, 26.8701, 244.52200000000002 - 0.1, 0.0, 46.0, 28560.1, 3489.2, 8389.7, 57.6579, 285.601 - 0.1, 0.0, 48.0, 30603.9, 3604.5, 9194.3, 69.2477, 306.03900000000004 - 0.1, 0.0, 50.0, 32642.3, 3714.3, 10032.8, 77.4403, 326.423 - 0.1, 2000.0, 21.0, 2330.3, 984.5, 824.4, 4.924, 23.303 - 0.1, 2000.0, 22.0, 3327.1, 1173.8, 991.2, 5.5336, 33.271 - 0.1, 2000.0, 24.0, 5235.7, 1467.4, 1391.5, 7.5234, 52.357 - 0.1, 2000.0, 26.0, 7086.3, 1702.9, 1826.8, 9.2983, 70.863 - 0.1, 2000.0, 30.0, 11094.9, 2122.6, 2859.5, 13.4284, 110.949 - 0.1, 2000.0, 34.0, 15023.5, 2462.3, 3960.7, 16.4467, 150.235 - 0.1, 2000.0, 38.0, 18904.9, 2754.8, 5117.1, 19.0209, 189.049 - 0.1, 2000.0, 42.0, 22752.9, 3013.8, 6361.1, 24.7835, 227.52900000000002 - 0.1, 2000.0, 46.0, 26574.2, 3246.4, 7721.3, 56.6411, 265.742 - 0.1, 2000.0, 48.0, 28476.4, 3353.7, 8462.9, 68.5093, 284.764 - 0.1, 2000.0, 50.0, 30372.6, 3455.8, 9235.9, 77.0405, 303.726 - 0.1, 5000.0, 21.0, 2084.6, 880.6, 738.0, 6.5816, 20.846 - 0.1, 5000.0, 22.0, 2976.4, 1050.0, 884.8, 4.9156, 29.764000000000003 - 0.1, 5000.0, 24.0, 4684.1, 1312.8, 1237.6, 6.8861, 46.841 - 0.1, 5000.0, 26.0, 6339.8, 1523.6, 1621.7, 8.6447, 63.398 - 0.1, 5000.0, 30.0, 9926.1, 1899.3, 2532.7, 12.6499, 99.26100000000001 - 0.1, 5000.0, 34.0, 13440.9, 2203.3, 3503.2, 15.6314, 134.409 - 0.1, 5000.0, 38.0, 16913.5, 2465.1, 4524.4, 18.1789, 169.135 - 0.1, 5000.0, 42.0, 20356.6, 2696.9, 5621.1, 20.4797, 203.566 - 0.1, 5000.0, 46.0, 23775.6, 2905.2, 6820.1, 42.0756, 237.756 - 0.1, 5000.0, 48.0, 25476.8, 3001.2, 7474.2, 58.5348, 254.768 - 0.1, 5000.0, 50.0, 27173.2, 3092.6, 8156.2, 69.8119, 271.732 - 0.1, 10000.0, 21.0, 1721.9, 727.2, 612.6, 9.402, 17.219 - 0.1, 10000.0, 22.0, 2458.8, 867.2, 730.7, 7.2271, 24.588 - 0.1, 10000.0, 24.0, 3869.8, 1084.5, 1014.8, 5.7309, 38.698 - 0.1, 10000.0, 26.0, 5237.7, 1258.8, 1324.4, 7.4445, 52.377 - 0.1, 10000.0, 30.0, 8200.9, 1569.4, 2059.1, 10.9423, 82.009 - 0.1, 10000.0, 34.0, 11104.9, 1820.8, 2841.8, 14.0989, 111.04899999999999 - 0.1, 10000.0, 38.0, 13974.0, 2037.3, 3665.3, 16.5692, 139.74 - 0.1, 10000.0, 42.0, 16818.6, 2229.1, 4548.6, 18.7998, 168.18599999999998 - 0.1, 10000.0, 46.0, 19643.6, 2401.3, 5515.6, 21.9454, 196.43599999999998 - 0.1, 10000.0, 48.0, 21049.0, 2480.6, 6042.3, 33.2727, 210.49 - 0.1, 10000.0, 50.0, 22450.7, 2556.3, 6592.6, 50.9804, 224.507 - 0.2, 0.0, 21.0, 3984.0, 2660.5, 927.8, 4.88, 39.84 - 0.2, 0.0, 22.0, 5132.8, 3015.2, 1158.3, 6.0773, 51.328 - 0.2, 0.0, 24.0, 7290.5, 3584.8, 1655.7, 8.2264, 72.905 - 0.2, 0.0, 26.0, 9344.4, 4050.6, 2168.2, 10.048, 93.444 - 0.2, 0.0, 30.0, 13714.4, 4891.5, 3335.6, 14.1832, 137.144 - 0.2, 0.0, 34.0, 17928.1, 5575.9, 4564.4, 17.1365, 179.28099999999998 - 0.2, 0.0, 38.0, 22048.5, 6167.1, 5839.6, 19.6518, 220.485 - 0.2, 0.0, 42.0, 26104.0, 6693.4, 7176.2, 31.254, 261.04 - 0.2, 0.0, 46.0, 30105.5, 7165.7, 8625.1, 60.8012, 301.055 - 0.2, 0.0, 48.0, 32088.4, 7383.6, 9408.5, 71.4541, 320.884 - 0.2, 0.0, 50.0, 34059.1, 7590.1, 10231.7, 78.754, 340.591 - 0.2, 2000.0, 21.0, 3705.8, 2475.9, 844.5, 4.8026, 37.058 - 0.2, 2000.0, 22.0, 4773.5, 2805.8, 1055.1, 5.8928, 47.735 - 0.2, 2000.0, 24.0, 6779.2, 3335.6, 1509.9, 8.0591, 67.792 - 0.2, 2000.0, 26.0, 8688.2, 3768.8, 1978.1, 9.8731, 86.882 - 0.2, 2000.0, 30.0, 12750.0, 4551.0, 3045.6, 14.0129, 127.5 - 0.2, 2000.0, 34.0, 16665.9, 5187.3, 4175.2, 16.9893, 166.65900000000002 - 0.2, 2000.0, 38.0, 20495.5, 5737.3, 5341.9, 19.5044, 204.955 - 0.2, 2000.0, 42.0, 24264.1, 6226.1, 6575.1, 28.1727, 242.641 - 0.2, 2000.0, 46.0, 27981.8, 6663.9, 7924.2, 59.5213, 279.818 - 0.2, 2000.0, 48.0, 29823.9, 6866.3, 8646.0, 70.5775, 298.23900000000003 - 0.2, 2000.0, 50.0, 31655.3, 7058.3, 9403.9, 78.2786, 316.553 - 0.2, 5000.0, 21.0, 3315.0, 2214.7, 755.5, 6.435, 33.15 - 0.2, 5000.0, 22.0, 4270.4, 2510.0, 941.0, 5.268, 42.704 - 0.2, 5000.0, 24.0, 6064.9, 2984.3, 1342.0, 7.4149, 60.649 - 0.2, 5000.0, 26.0, 7773.0, 3372.1, 1755.4, 9.2124, 77.73 - 0.2, 5000.0, 30.0, 11407.0, 4072.2, 2696.9, 13.2256, 114.07000000000001 - 0.2, 5000.0, 34.0, 14910.5, 4641.7, 3693.1, 16.1681, 149.105 - 0.2, 5000.0, 38.0, 18336.7, 5134.0, 4722.6, 18.6548, 183.36700000000002 - 0.2, 5000.0, 42.0, 21708.3, 5571.5, 5810.0, 20.9007, 217.083 - 0.2, 5000.0, 46.0, 25034.4, 5963.4, 6999.7, 46.548, 250.34400000000002 - 0.2, 5000.0, 48.0, 26682.2, 6144.6, 7635.7, 60.7973, 266.822 - 0.2, 5000.0, 50.0, 28321.1, 6316.5, 8304.7, 71.4843, 283.211 - 0.2, 10000.0, 21.0, 2738.0, 1829.0, 626.4, 9.2804, 27.38 - 0.2, 10000.0, 22.0, 3527.6, 2073.3, 775.5, 6.4797, 35.276 - 0.2, 10000.0, 24.0, 5010.5, 2465.5, 1098.5, 6.2413, 50.105000000000004 - 0.2, 10000.0, 26.0, 6421.8, 2786.1, 1431.7, 7.9908, 64.218 - 0.2, 10000.0, 30.0, 9424.6, 3365.1, 2191.4, 11.7561, 94.24600000000001 - 0.2, 10000.0, 34.0, 12319.4, 3836.1, 2994.6, 14.6148, 123.194 - 0.2, 10000.0, 38.0, 15150.2, 4243.1, 3825.2, 17.0282, 151.502 - 0.2, 10000.0, 42.0, 17936.1, 4604.8, 4701.2, 19.1798, 179.361 - 0.2, 10000.0, 46.0, 20683.4, 4929.0, 5659.9, 23.6308, 206.83400000000003 - 0.2, 10000.0, 48.0, 22045.5, 5078.8, 6173.0, 36.4956, 220.455 - 0.2, 10000.0, 50.0, 23399.5, 5221.0, 6712.2, 53.4919, 233.995 - 0.25, 0.0, 21.0, 4982.9, 3711.0, 967.7, 5.1347, 49.829 - 0.25, 0.0, 22.0, 6155.9, 4120.9, 1221.5, 6.4157, 61.559 - 0.25, 0.0, 24.0, 8353.0, 4791.8, 1741.2, 8.5818, 83.53 - 0.25, 0.0, 26.0, 10434.6, 5347.2, 2267.6, 10.7481, 104.346 - 0.25, 0.0, 30.0, 14837.1, 6358.1, 3458.3, 14.5379, 148.371 - 0.25, 0.0, 34.0, 19055.8, 7185.2, 4700.4, 17.4532, 190.558 - 0.25, 0.0, 38.0, 23164.2, 7901.7, 5979.8, 19.9304, 231.64200000000002 - 0.25, 0.0, 42.0, 27194.4, 8540.4, 7318.7, 34.2788, 271.944 - 0.25, 0.0, 46.0, 31158.1, 9112.7, 8772.0, 62.9527, 311.581 - 0.25, 0.0, 48.0, 33119.2, 9377.6, 9547.4, 72.8167, 331.19199999999995 - 0.25, 0.0, 50.0, 35064.8, 9627.7, 10368.8, 79.61, 350.648 - 0.25, 2000.0, 21.0, 4635.4, 3453.6, 881.2, 4.9403, 46.354 - 0.25, 2000.0, 22.0, 5725.7, 3834.8, 1113.2, 6.2358, 57.257 - 0.25, 2000.0, 24.0, 7767.9, 4458.7, 1587.7, 8.4148, 77.679 - 0.25, 2000.0, 26.0, 9702.8, 4975.4, 2068.9, 10.3133, 97.02799999999999 - 0.25, 2000.0, 30.0, 13794.8, 5915.8, 3157.8, 14.3694, 137.948 - 0.25, 2000.0, 34.0, 17715.3, 6684.5, 4299.7, 17.3076, 177.153 - 0.25, 2000.0, 38.0, 21533.5, 7351.2, 5470.6, 19.7854, 215.335 - 0.25, 2000.0, 42.0, 25278.1, 7944.4, 6705.3, 30.7493, 252.78099999999998 - 0.25, 2000.0, 46.0, 28960.8, 8474.8, 8057.1, 61.504, 289.608 - 0.25, 2000.0, 48.0, 30782.4, 8720.7, 8773.3, 71.9783, 307.824 - 0.25, 2000.0, 50.0, 32590.3, 8953.2, 9529.4, 79.1712, 325.903 - 0.25, 5000.0, 21.0, 4146.8, 3089.4, 787.7, 5.8398, 41.468 - 0.25, 5000.0, 22.0, 5122.4, 3430.7, 992.0, 5.6074, 51.224 - 0.25, 5000.0, 24.0, 6949.9, 3989.3, 1411.0, 7.7697, 69.499 - 0.25, 5000.0, 26.0, 8681.0, 4451.7, 1835.5, 9.5548, 86.81 - 0.25, 5000.0, 30.0, 12342.2, 5293.4, 2795.6, 13.5758, 123.42200000000001 - 0.25, 5000.0, 34.0, 15850.1, 5981.6, 3803.0, 16.4816, 158.501 - 0.25, 5000.0, 38.0, 19266.4, 6578.4, 4836.6, 18.9321, 192.66400000000002 - 0.25, 5000.0, 42.0, 22617.1, 7109.4, 5925.2, 21.9946, 226.171 - 0.25, 5000.0, 46.0, 25911.5, 7584.2, 7117.3, 49.402, 259.115 - 0.25, 5000.0, 48.0, 27541.0, 7804.3, 7748.5, 62.5764, 275.41 - 0.25, 5000.0, 50.0, 29158.9, 8012.2, 8415.7, 72.7322, 291.589 - 0.25, 10000.0, 21.0, 3424.9, 2551.5, 652.1, 8.6939, 34.249 - 0.25, 10000.0, 22.0, 4231.3, 2833.9, 816.4, 5.6904, 42.313 - 0.25, 10000.0, 24.0, 5741.3, 3295.8, 1153.9, 6.5846, 57.413000000000004 - 0.25, 10000.0, 26.0, 7171.8, 3678.2, 1496.8, 8.3269, 71.718 - 0.25, 10000.0, 30.0, 10196.9, 4374.2, 2270.9, 12.0944, 101.969 - 0.25, 10000.0, 34.0, 13095.1, 4943.3, 3083.3, 14.918, 130.951 - 0.25, 10000.0, 38.0, 15917.5, 5436.7, 3916.9, 17.295, 159.175 - 0.25, 10000.0, 42.0, 18685.9, 5875.8, 4794.1, 19.4143, 186.859 - 0.25, 10000.0, 46.0, 21407.5, 6268.5, 5754.5, 25.0166, 214.07500000000002 - 0.25, 10000.0, 48.0, 22754.0, 6450.6, 6263.1, 38.8691, 227.54 - 0.25, 10000.0, 50.0, 24090.7, 6622.7, 6801.4, 55.311, 240.907 - 0.3, 0.0, 21.0, 6173.4, 4945.6, 1022.8, 5.4835, 61.733999999999995 - 0.3, 0.0, 22.0, 7364.1, 5399.7, 1289.1, 6.7761, 73.641 - 0.3, 0.0, 24.0, 9594.3, 6156.5, 1828.9, 8.945, 95.943 - 0.3, 0.0, 26.0, 11702.0, 6790.9, 2370.2, 11.3695, 117.02 - 0.3, 0.0, 30.0, 16141.2, 7956.0, 3586.7, 14.9079, 161.412 - 0.3, 0.0, 34.0, 20374.2, 8914.9, 4845.9, 17.7911, 203.74200000000002 - 0.3, 0.0, 38.0, 24482.0, 9748.6, 6136.4, 20.2415, 244.82 - 0.3, 0.0, 42.0, 28498.9, 10491.9, 7487.2, 38.1853, 284.98900000000003 - 0.3, 0.0, 46.0, 32440.2, 11158.6, 8946.6, 65.3539, 324.402 - 0.3, 0.0, 48.0, 34385.6, 11467.0, 9722.6, 74.4559, 343.856 - 0.3, 0.0, 50.0, 36314.3, 11758.7, 10541.1, 80.6075, 363.14300000000003 - 0.3, 2000.0, 21.0, 5743.4, 4602.6, 931.5, 5.2941, 57.434 - 0.3, 2000.0, 22.0, 6850.3, 5024.9, 1175.0, 6.6001, 68.503 - 0.3, 2000.0, 24.0, 8923.2, 5728.8, 1668.1, 8.7823, 89.23200000000001 - 0.3, 2000.0, 26.0, 10882.3, 6318.8, 2161.9, 11.0244, 108.823 - 0.3, 2000.0, 30.0, 15008.5, 7402.8, 3275.4, 14.742, 150.085 - 0.3, 2000.0, 34.0, 18942.1, 8294.0, 4433.1, 17.6473, 189.421 - 0.3, 2000.0, 38.0, 22759.9, 9069.6, 5614.1, 20.0977, 227.59900000000002 - 0.3, 2000.0, 42.0, 26492.4, 9759.9, 6860.5, 34.3047, 264.92400000000004 - 0.3, 2000.0, 46.0, 30152.8, 10377.9, 8215.0, 63.8559, 301.528 - 0.3, 2000.0, 48.0, 31959.4, 10663.8, 8934.3, 73.6791, 319.594 - 0.3, 2000.0, 50.0, 33752.0, 10934.9, 9687.3, 80.2171, 337.52 - 0.3, 5000.0, 21.0, 5137.9, 4117.3, 832.0, 5.0092, 51.379 - 0.3, 5000.0, 22.0, 6128.4, 4495.5, 1046.5, 5.9682, 61.284 - 0.3, 5000.0, 24.0, 7983.1, 5125.5, 1481.4, 8.1293, 79.831 - 0.3, 5000.0, 26.0, 9735.9, 5653.8, 1917.6, 9.9046, 97.359 - 0.3, 5000.0, 30.0, 13427.5, 6623.9, 2899.2, 13.9423, 134.275 - 0.3, 5000.0, 34.0, 16946.8, 7421.7, 3920.4, 16.8161, 169.468 - 0.3, 5000.0, 38.0, 20362.5, 8115.9, 4962.2, 19.2379, 203.625 - 0.3, 5000.0, 42.0, 23701.7, 8733.8, 6061.4, 23.5209, 237.01700000000002 - 0.3, 5000.0, 46.0, 26976.2, 9286.8, 7256.0, 52.5299, 269.762 - 0.3, 5000.0, 48.0, 28592.9, 9543.0, 7890.1, 64.7543, 285.92900000000003 - 0.3, 5000.0, 50.0, 30196.6, 9785.7, 8554.4, 74.2115, 301.966 - 0.3, 10000.0, 21.0, 4243.8, 3400.8, 687.6, 7.8677, 42.438 - 0.3, 10000.0, 22.0, 5062.5, 3713.6, 860.4, 4.908, 50.625 - 0.3, 10000.0, 24.0, 6595.3, 4234.8, 1211.0, 6.9375, 65.953 - 0.3, 10000.0, 26.0, 8043.8, 4671.6, 1563.1, 8.6667, 80.438 - 0.3, 10000.0, 30.0, 11094.2, 5473.9, 2354.8, 12.4504, 110.94200000000001 - 0.3, 10000.0, 34.0, 14002.0, 6133.6, 3177.8, 15.2398, 140.02 - 0.3, 10000.0, 38.0, 16824.1, 6707.5, 4018.5, 17.5905, 168.24099999999999 - 0.3, 10000.0, 42.0, 19583.3, 7218.6, 4904.6, 19.6927, 195.833 - 0.3, 10000.0, 46.0, 22288.8, 7676.1, 5867.0, 26.9467, 222.888 - 0.3, 10000.0, 48.0, 23624.2, 7887.9, 6378.4, 42.0826, 236.24200000000002 - 0.3, 10000.0, 50.0, 24949.6, 8088.6, 6913.7, 57.381, 249.49599999999998 - 0.3, 15000.0, 21.0, 3479.6, 2788.1, 567.1, 10.753, 34.796 - 0.3, 15000.0, 22.0, 4151.5, 3045.2, 705.0, 7.7596, 41.515 - 0.3, 15000.0, 24.0, 5409.3, 3473.3, 985.3, 5.6485, 54.093 - 0.3, 15000.0, 26.0, 6597.7, 3831.9, 1267.2, 7.317, 65.977 - 0.3, 15000.0, 30.0, 9100.3, 4490.8, 1900.3, 10.2364, 91.003 - 0.3, 15000.0, 34.0, 11486.0, 5032.6, 2558.6, 13.4803, 114.86 - 0.3, 15000.0, 38.0, 13801.0, 5503.8, 3231.5, 15.7326, 138.01 - 0.3, 15000.0, 42.0, 16064.5, 5923.6, 3939.7, 17.7439, 160.645 - 0.3, 15000.0, 46.0, 18284.0, 6299.3, 4708.7, 19.6831, 182.84 - 0.3, 15000.0, 48.0, 19379.7, 6473.2, 5117.8, 21.3254, 193.79700000000003 - 0.3, 15000.0, 50.0, 20466.5, 6637.9, 5546.1, 30.4095, 204.665 - 0.35, 0.0, 21.0, 7566.3, 6374.0, 1096.3, 5.9318, 75.663 - 0.35, 0.0, 22.0, 8770.7, 6863.1, 1379.4, 7.2407, 87.70700000000001 - 0.35, 0.0, 24.0, 11031.6, 7693.3, 1932.5, 9.3656, 110.316 - 0.35, 0.0, 26.0, 13168.6, 8399.6, 2472.9, 11.7648, 131.686 - 0.35, 0.0, 30.0, 17653.6, 9705.4, 3720.3, 15.2909, 176.536 - 0.35, 0.0, 34.0, 21914.4, 10786.9, 5002.2, 18.1525, 219.144 - 0.35, 0.0, 38.0, 26037.3, 11730.5, 6310.8, 20.5849, 260.373 - 0.35, 0.0, 42.0, 30057.1, 12571.0, 7691.3, 43.1208, 300.57099999999997 - 0.35, 0.0, 46.0, 33993.9, 13328.4, 9155.7, 67.9905, 339.939 - 0.35, 0.0, 48.0, 35932.2, 13677.3, 9939.7, 76.3155, 359.322 - 0.35, 0.0, 50.0, 37853.7, 14009.0, 10755.8, 81.718, 378.537 - 0.35, 2000.0, 21.0, 7039.8, 5932.0, 999.1, 5.7509, 70.39800000000001 - 0.35, 2000.0, 22.0, 8159.4, 6386.9, 1257.8, 7.0693, 81.594 - 0.35, 2000.0, 24.0, 10260.8, 7159.0, 1763.3, 9.2076, 102.60799999999999 - 0.35, 2000.0, 26.0, 12247.3, 7816.1, 2255.9, 11.5847, 122.473 - 0.35, 2000.0, 30.0, 16416.2, 9030.9, 3397.3, 15.1257, 164.162 - 0.35, 2000.0, 34.0, 20375.6, 10036.0, 4575.8, 18.0083, 203.756 - 0.35, 2000.0, 38.0, 24207.3, 10913.7, 5773.4, 20.4408, 242.073 - 0.35, 2000.0, 42.0, 27941.9, 11694.1, 7047.4, 39.005, 279.41900000000004 - 0.35, 2000.0, 46.0, 31598.2, 12396.5, 8403.2, 66.4441, 315.982 - 0.35, 2000.0, 48.0, 33398.3, 12719.4, 9133.8, 75.6132, 333.98300000000006 - 0.35, 2000.0, 50.0, 35183.5, 13027.6, 9884.0, 81.3882, 351.835 - 0.35, 5000.0, 21.0, 6297.7, 5306.8, 891.4, 5.1268, 62.977 - 0.35, 5000.0, 22.0, 7299.6, 5714.1, 1119.5, 6.4339, 72.99600000000001 - 0.35, 5000.0, 24.0, 9179.9, 6405.3, 1565.3, 8.5499, 91.79899999999999 - 0.35, 5000.0, 26.0, 10957.1, 6993.4, 2000.3, 10.2625, 109.57100000000001 - 0.35, 5000.0, 30.0, 14686.9, 8080.8, 3006.9, 14.3212, 146.869 - 0.35, 5000.0, 34.0, 18229.2, 8980.4, 4046.1, 17.1706, 182.292 - 0.35, 5000.0, 38.0, 21657.4, 9766.2, 5102.9, 19.5757, 216.574 - 0.35, 5000.0, 42.0, 24998.3, 10464.7, 6226.3, 25.9255, 249.983 - 0.35, 5000.0, 46.0, 28269.4, 11093.1, 7421.8, 55.8105, 282.694 - 0.35, 5000.0, 48.0, 29879.7, 11382.5, 8065.8, 67.2746, 298.797 - 0.35, 5000.0, 50.0, 31477.1, 11658.5, 8727.8, 75.9179, 314.771 - 0.35, 10000.0, 21.0, 5202.0, 4383.5, 735.2, 6.795, 52.02 - 0.35, 10000.0, 22.0, 6030.2, 4720.6, 919.0, 5.282, 60.302 - 0.35, 10000.0, 24.0, 7584.1, 5292.2, 1278.6, 7.346, 75.84100000000001 - 0.35, 10000.0, 26.0, 9052.7, 5778.6, 1629.9, 9.0072, 90.52700000000002 - 0.35, 10000.0, 30.0, 12134.6, 6677.8, 2441.6, 12.816, 121.346 - 0.35, 10000.0, 34.0, 15061.4, 7421.8, 3279.3, 15.5823, 150.614 - 0.35, 10000.0, 38.0, 17893.8, 8071.6, 4132.1, 17.9157, 178.938 - 0.35, 10000.0, 42.0, 20654.1, 8649.1, 5037.3, 20.0235, 206.541 - 0.35, 10000.0, 46.0, 23357.0, 9169.2, 6000.8, 29.5981, 233.57 - 0.35, 10000.0, 48.0, 24688.2, 9408.4, 6520.4, 45.9418, 246.882 - 0.35, 10000.0, 50.0, 26007.2, 9636.6, 7053.3, 59.5544, 260.072 - 0.35, 15000.0, 21.0, 4265.5, 3594.1, 604.8, 9.6899, 42.655 - 0.35, 15000.0, 22.0, 4945.3, 3871.2, 751.6, 6.6744, 49.453 - 0.35, 15000.0, 24.0, 6220.4, 4340.7, 1039.2, 6.0427, 62.204 - 0.35, 15000.0, 26.0, 7425.3, 4740.1, 1320.6, 7.6429, 74.253 - 0.35, 15000.0, 30.0, 9953.9, 5478.5, 1969.8, 10.8708, 99.539 - 0.35, 15000.0, 34.0, 12355.2, 6089.6, 2639.9, 13.8065, 123.552 - 0.35, 15000.0, 38.0, 14678.8, 6623.1, 3322.2, 16.0412, 146.78799999999998 - 0.35, 15000.0, 42.0, 16943.3, 7097.5, 4045.6, 18.0572, 169.433 - 0.35, 15000.0, 46.0, 19160.5, 7524.6, 4816.5, 19.9608, 191.60500000000002 - 0.35, 15000.0, 48.0, 20251.7, 7720.9, 5231.4, 22.6619, 202.51700000000002 - 0.35, 15000.0, 50.0, 21334.5, 7908.4, 5657.5, 33.1924, 213.345 - 0.4, 2000.0, 21.0, 8528.1, 7446.9, 1080.6, 6.2764, 85.281 - 0.4, 2000.0, 22.0, 9658.0, 7928.2, 1353.5, 7.5936, 96.58 - 0.4, 2000.0, 24.0, 11784.7, 8757.4, 1878.4, 9.7055, 117.84700000000001 - 0.4, 2000.0, 26.0, 13797.7, 9473.0, 2382.4, 12.1006, 137.977 - 0.4, 2000.0, 30.0, 18018.9, 10811.1, 3529.2, 15.5376, 180.18900000000002 - 0.4, 2000.0, 34.0, 22012.9, 11922.0, 4732.9, 18.4036, 220.12900000000002 - 0.4, 2000.0, 38.0, 25869.2, 12895.0, 5956.0, 20.8298, 258.692 - 0.4, 2000.0, 42.0, 29617.1, 13759.9, 7260.5, 44.5575, 296.171 - 0.4, 2000.0, 46.0, 33282.9, 14542.5, 8623.9, 69.2745, 332.829 - 0.4, 2000.0, 48.0, 35081.9, 14900.1, 9368.5, 77.6817, 350.819 - 0.4, 2000.0, 50.0, 36867.3, 15243.9, 10120.0, 82.6292, 368.67300000000006 - 0.4, 5000.0, 21.0, 7629.4, 6662.3, 963.1, 5.6477, 76.294 - 0.4, 5000.0, 22.0, 8640.5, 7093.1, 1203.9, 6.9524, 86.405 - 0.4, 5000.0, 24.0, 10543.4, 7835.5, 1666.8, 9.0427, 105.434 - 0.4, 5000.0, 26.0, 12344.4, 8476.0, 2111.2, 11.1881, 123.444 - 0.4, 5000.0, 30.0, 16121.1, 9673.7, 3123.3, 14.7282, 161.211 - 0.4, 5000.0, 34.0, 19694.5, 10668.0, 4184.8, 17.5597, 196.945 - 0.4, 5000.0, 38.0, 23144.4, 11539.2, 5263.3, 19.9572, 231.44400000000002 - 0.4, 5000.0, 42.0, 26497.4, 12313.3, 6414.0, 29.514, 264.97400000000005 - 0.4, 5000.0, 46.0, 29777.0, 13014.0, 7616.7, 59.0834, 297.77 - 0.4, 5000.0, 48.0, 31386.7, 13333.9, 8272.8, 70.033, 313.867 - 0.4, 5000.0, 50.0, 32983.8, 13641.9, 8936.1, 77.8099, 329.838 - 0.4, 10000.0, 21.0, 6302.4, 5503.6, 792.8, 5.5515, 63.024 - 0.4, 10000.0, 22.0, 7138.3, 5860.2, 987.2, 5.7899, 71.38300000000001 - 0.4, 10000.0, 24.0, 8710.6, 6473.9, 1360.1, 7.8236, 87.10600000000001 - 0.4, 10000.0, 26.0, 10198.9, 7003.7, 1718.7, 9.4457, 101.989 - 0.4, 10000.0, 30.0, 13319.7, 7994.3, 2535.4, 13.2086, 133.197 - 0.4, 10000.0, 34.0, 16272.3, 8816.6, 3391.4, 15.9573, 162.72299999999998 - 0.4, 10000.0, 38.0, 19122.7, 9537.0, 4262.0, 18.2845, 191.227 - 0.4, 10000.0, 42.0, 21893.2, 10177.2, 5188.5, 20.3954, 218.93200000000002 - 0.4, 10000.0, 46.0, 24602.9, 10756.8, 6158.4, 33.2437, 246.02900000000002 - 0.4, 10000.0, 48.0, 25932.9, 11021.4, 6687.2, 50.2607, 259.329 - 0.4, 10000.0, 50.0, 27252.3, 11276.0, 7221.2, 62.3136, 272.523 - 0.4, 15000.0, 21.0, 5168.0, 4512.9, 650.8, 8.4556, 51.68 - 0.4, 15000.0, 22.0, 5854.1, 4806.0, 806.0, 5.4657, 58.541000000000004 - 0.4, 15000.0, 24.0, 7144.6, 5310.3, 1104.8, 6.507, 71.44600000000001 - 0.4, 15000.0, 26.0, 8365.6, 5745.3, 1391.4, 8.064, 83.656 - 0.4, 15000.0, 30.0, 10925.8, 6558.6, 2044.8, 11.5264, 109.258 - 0.4, 15000.0, 34.0, 13348.1, 7234.0, 2729.6, 14.1632, 133.481 - 0.4, 15000.0, 38.0, 15686.6, 7825.6, 3426.3, 16.3919, 156.866 - 0.4, 15000.0, 42.0, 17959.2, 8351.4, 4166.5, 18.4104, 179.592 - 0.4, 15000.0, 46.0, 20182.2, 8827.3, 4942.1, 20.2805, 201.822 - 0.4, 15000.0, 48.0, 21272.7, 9044.6, 5364.6, 24.6069, 212.727 - 0.4, 15000.0, 50.0, 22355.5, 9253.8, 5792.4, 36.8914, 223.555 - 0.4, 20000.0, 21.0, 4204.2, 3671.1, 533.0, 11.3443, 42.042 - 0.4, 20000.0, 22.0, 4763.2, 3910.2, 655.9, 8.3987, 47.632 - 0.4, 20000.0, 24.0, 5814.2, 4321.4, 892.7, 5.1322, 58.141999999999996 - 0.4, 20000.0, 26.0, 6808.5, 4676.0, 1119.9, 6.6187, 68.08500000000001 - 0.4, 20000.0, 30.0, 8893.2, 5339.0, 1638.7, 9.2928, 88.932 - 0.4, 20000.0, 34.0, 10865.4, 5889.5, 2181.2, 12.2577, 108.654 - 0.4, 20000.0, 38.0, 12769.1, 6371.6, 2734.1, 14.3697, 127.691 - 0.4, 20000.0, 42.0, 14619.4, 6800.2, 3321.2, 16.2797, 146.194 - 0.4, 20000.0, 46.0, 16429.0, 7188.1, 3935.2, 18.0475, 164.29 - 0.4, 20000.0, 48.0, 17317.4, 7365.4, 4270.7, 18.9554, 173.174 - 0.4, 20000.0, 50.0, 18198.2, 7535.7, 4608.9, 19.8172, 181.982 - 0.45, 5000.0, 21.0, 9134.3, 8186.4, 1052.9, 6.2594, 91.34299999999999 - 0.45, 5000.0, 22.0, 10153.5, 8637.0, 1297.4, 7.5048, 101.535 - 0.45, 5000.0, 24.0, 12077.2, 9423.1, 1777.2, 9.5637, 120.772 - 0.45, 5000.0, 26.0, 13900.8, 10109.4, 2237.9, 11.8951, 139.008 - 0.45, 5000.0, 30.0, 17726.1, 11407.1, 3263.8, 15.2102, 177.261 - 0.45, 5000.0, 34.0, 21336.8, 12490.1, 4347.5, 18.0093, 213.368 - 0.45, 5000.0, 38.0, 24813.0, 13438.6, 5462.2, 20.4201, 248.13 - 0.45, 5000.0, 42.0, 28188.8, 14287.0, 6626.4, 34.5899, 281.888 - 0.45, 5000.0, 46.0, 31486.0, 15056.3, 7841.9, 62.5039, 314.86 - 0.45, 5000.0, 48.0, 33098.2, 15405.0, 8512.7, 72.9747, 330.98199999999997 - 0.45, 5000.0, 50.0, 34700.2, 15743.1, 9179.8, 79.8154, 347.00199999999995 - 0.45, 10000.0, 21.0, 7545.9, 6763.0, 865.0, 5.1128, 75.459 - 0.45, 10000.0, 22.0, 8388.6, 7135.9, 1062.6, 6.3291, 83.88600000000001 - 0.45, 10000.0, 24.0, 9978.2, 7786.1, 1449.5, 8.3334, 99.78200000000001 - 0.45, 10000.0, 26.0, 11485.1, 8353.6, 1820.8, 9.9346, 114.851 - 0.45, 10000.0, 30.0, 14645.9, 9426.7, 2648.1, 13.6721, 146.459 - 0.45, 10000.0, 34.0, 17629.4, 10322.5, 3522.4, 16.3907, 176.294 - 0.45, 10000.0, 38.0, 20501.5, 11106.9, 4421.5, 18.7295, 205.01500000000001 - 0.45, 10000.0, 42.0, 23290.9, 11808.7, 5360.6, 20.8118, 232.90900000000002 - 0.45, 10000.0, 46.0, 26014.7, 12444.7, 6339.6, 38.0177, 260.147 - 0.45, 10000.0, 48.0, 27346.9, 12733.1, 6880.0, 54.809, 273.469 - 0.45, 10000.0, 50.0, 28670.6, 13012.9, 7417.8, 65.5452, 286.706 - 0.45, 15000.0, 21.0, 6188.1, 5546.1, 708.2, 7.0161, 61.88100000000001 - 0.45, 15000.0, 22.0, 6879.8, 5852.6, 866.3, 5.0623, 68.798 - 0.45, 15000.0, 24.0, 8184.3, 6386.7, 1176.1, 6.9948, 81.843 - 0.45, 15000.0, 26.0, 9420.7, 6852.7, 1473.1, 8.533, 94.20700000000001 - 0.45, 15000.0, 30.0, 12014.0, 7734.1, 2135.7, 11.9737, 120.14 - 0.45, 15000.0, 34.0, 14461.5, 8469.7, 2834.4, 14.5758, 144.615 - 0.45, 15000.0, 38.0, 16817.6, 9113.8, 3553.9, 16.8157, 168.176 - 0.45, 15000.0, 42.0, 19105.8, 9690.3, 4304.2, 18.8064, 191.058 - 0.45, 15000.0, 46.0, 21340.5, 10212.6, 5087.2, 20.6468, 213.405 - 0.45, 15000.0, 48.0, 22433.2, 10449.4, 5519.7, 27.6021, 224.33200000000002 - 0.45, 15000.0, 50.0, 23518.8, 10679.1, 5949.6, 41.4721, 235.188 - 0.45, 20000.0, 21.0, 5034.5, 4512.0, 578.2, 9.9201, 50.345 - 0.45, 20000.0, 22.0, 5598.0, 4762.1, 703.5, 7.1405, 55.980000000000004 - 0.45, 20000.0, 24.0, 6660.5, 5197.7, 949.2, 5.5997, 66.605 - 0.45, 20000.0, 26.0, 7667.4, 5577.6, 1184.8, 7.0642, 76.67399999999999 - 0.45, 20000.0, 30.0, 9779.0, 6296.0, 1710.7, 9.6704, 97.79 - 0.45, 20000.0, 34.0, 11771.9, 6895.7, 2264.6, 12.6477, 117.719 - 0.45, 20000.0, 38.0, 13690.0, 7420.5, 2835.3, 14.7686, 136.9 - 0.45, 20000.0, 42.0, 15553.0, 7890.4, 3430.4, 16.6516, 155.53 - 0.45, 20000.0, 46.0, 17372.0, 8316.2, 4051.2, 18.3923, 173.72 - 0.45, 20000.0, 48.0, 18261.9, 8509.5, 4393.4, 19.298, 182.61900000000003 - 0.45, 20000.0, 50.0, 19145.4, 8696.4, 4733.9, 20.4806, 191.454 - 0.45, 25000.0, 21.0, 4060.5, 3638.9, 471.3, 12.8242, 40.605000000000004 - 0.45, 25000.0, 22.0, 4515.9, 3841.4, 569.7, 10.0682, 45.159 - 0.45, 25000.0, 24.0, 5374.3, 4193.9, 762.8, 5.6593, 53.743 - 0.45, 25000.0, 26.0, 6187.3, 4501.0, 947.5, 5.5964, 61.873000000000005 - 0.45, 25000.0, 30.0, 7892.2, 5081.8, 1360.8, 8.0513, 78.922 - 0.45, 25000.0, 34.0, 9501.3, 5566.7, 1795.6, 10.5022, 95.01299999999999 - 0.45, 25000.0, 38.0, 11049.7, 5991.0, 2244.5, 12.7089, 110.49700000000001 - 0.45, 25000.0, 42.0, 12553.9, 6370.9, 2711.4, 14.4744, 125.539 - 0.45, 25000.0, 46.0, 14022.2, 6715.2, 3198.7, 16.1089, 140.222 - 0.45, 25000.0, 48.0, 14740.5, 6871.3, 3466.7, 16.9602, 147.405 - 0.45, 25000.0, 50.0, 15453.9, 7022.7, 3734.8, 17.7627, 154.539 - 0.5, 10000.0, 21.0, 8935.3, 8163.6, 961.2, 5.8415, 89.353 - 0.5, 10000.0, 22.0, 9784.6, 8549.9, 1163.5, 6.9976, 97.846 - 0.5, 10000.0, 24.0, 11396.5, 9235.8, 1543.3, 8.8511, 113.965 - 0.5, 10000.0, 26.0, 12924.7, 9838.0, 1929.2, 10.5792, 129.247 - 0.5, 10000.0, 30.0, 16130.8, 10986.4, 2783.0, 14.2064, 161.308 - 0.5, 10000.0, 34.0, 19153.1, 11950.9, 3679.1, 16.8955, 191.53099999999998 - 0.5, 10000.0, 38.0, 22058.2, 12798.3, 4602.1, 19.2194, 220.58200000000002 - 0.5, 10000.0, 42.0, 24877.3, 13559.7, 5557.3, 21.8787, 248.773 - 0.5, 10000.0, 46.0, 27624.5, 14249.1, 6554.3, 44.2213, 276.245 - 0.5, 10000.0, 48.0, 28965.7, 14561.4, 7104.9, 59.1261, 289.65700000000004 - 0.5, 10000.0, 50.0, 30298.2, 14865.0, 7650.4, 69.0476, 302.982 - 0.5, 15000.0, 21.0, 7328.1, 6695.3, 785.0, 5.2669, 73.281 - 0.5, 15000.0, 22.0, 8025.5, 7012.9, 947.3, 5.7106, 80.255 - 0.5, 15000.0, 24.0, 9348.0, 7576.1, 1250.9, 7.4914, 93.48 - 0.5, 15000.0, 26.0, 10602.1, 8070.9, 1560.0, 9.017, 106.021 - 0.5, 15000.0, 30.0, 13232.8, 9014.0, 2243.0, 12.4829, 132.328 - 0.5, 15000.0, 34.0, 15712.4, 9806.1, 2959.9, 15.0577, 157.124 - 0.5, 15000.0, 38.0, 18095.8, 10502.0, 3698.5, 17.2835, 180.958 - 0.5, 15000.0, 42.0, 20408.6, 11127.3, 4462.3, 19.2512, 204.08599999999998 - 0.5, 15000.0, 46.0, 22662.5, 11693.7, 5260.4, 22.1856, 226.625 - 0.5, 15000.0, 48.0, 23762.9, 11950.1, 5699.8, 31.922, 237.62900000000002 - 0.5, 15000.0, 50.0, 24855.4, 12199.1, 6135.5, 46.874, 248.55400000000003 - 0.5, 20000.0, 21.0, 5962.3, 5447.4, 638.9, 8.1949, 59.623000000000005 - 0.5, 20000.0, 22.0, 6530.4, 5706.6, 767.5, 5.5864, 65.304 - 0.5, 20000.0, 24.0, 7607.5, 6165.9, 1008.8, 6.0754, 76.075 - 0.5, 20000.0, 26.0, 8628.5, 6569.1, 1253.7, 7.5239, 86.285 - 0.5, 20000.0, 30.0, 10770.3, 7337.8, 1795.3, 10.1237, 107.70299999999999 - 0.5, 20000.0, 34.0, 12788.9, 7983.4, 2363.9, 13.1017, 127.889 - 0.5, 20000.0, 38.0, 14729.0, 8550.6, 2949.4, 15.2078, 147.29 - 0.5, 20000.0, 42.0, 16611.6, 9060.2, 3555.1, 17.0676, 166.11599999999999 - 0.5, 20000.0, 46.0, 18446.0, 9521.6, 4187.2, 18.7919, 184.46 - 0.5, 20000.0, 48.0, 19341.8, 9731.0, 4535.0, 19.685, 193.418 - 0.5, 20000.0, 50.0, 20231.5, 9934.1, 4880.0, 22.2565, 202.315 - 0.5, 25000.0, 21.0, 4809.4, 4393.9, 518.7, 11.1067, 48.093999999999994 - 0.5, 25000.0, 22.0, 5268.5, 4603.8, 619.7, 8.5392, 52.685 - 0.5, 25000.0, 24.0, 6138.4, 4975.2, 809.4, 4.6585, 61.384 - 0.5, 25000.0, 26.0, 6963.0, 5301.2, 1001.5, 6.0297, 69.63 - 0.5, 25000.0, 30.0, 8692.6, 5923.0, 1426.9, 8.4555, 86.926 - 0.5, 25000.0, 34.0, 10322.4, 6444.9, 1873.7, 11.1348, 103.224 - 0.5, 25000.0, 38.0, 11888.8, 6903.5, 2334.1, 13.1197, 118.88799999999999 - 0.5, 25000.0, 42.0, 13408.7, 7315.6, 2809.6, 14.8632, 134.08700000000002 - 0.5, 25000.0, 46.0, 14889.7, 7688.8, 3305.8, 16.4821, 148.89700000000002 - 0.5, 25000.0, 48.0, 15612.7, 7857.9, 3578.7, 17.3225, 156.127 - 0.5, 25000.0, 50.0, 16331.0, 8022.2, 3850.1, 18.1143, 163.31 - 0.55, 10000.0, 21.0, 10473.2, 9708.0, 1063.1, 6.5663, 104.73200000000001 - 0.55, 10000.0, 22.0, 11331.3, 10107.0, 1273.2, 7.684, 113.31299999999999 - 0.55, 10000.0, 24.0, 12968.8, 10826.2, 1651.6, 9.4227, 129.688 - 0.55, 10000.0, 26.0, 14524.0, 11463.2, 2046.0, 11.6154, 145.24 - 0.55, 10000.0, 30.0, 17784.6, 12683.1, 2929.7, 14.7724, 177.84599999999998 - 0.55, 10000.0, 34.0, 20855.7, 13713.6, 3852.5, 17.4405, 208.55700000000002 - 0.55, 10000.0, 38.0, 23804.1, 14621.6, 4806.1, 19.7586, 238.041 - 0.55, 10000.0, 42.0, 26664.3, 15441.0, 5782.5, 24.8341, 266.643 - 0.55, 10000.0, 46.0, 29445.2, 16181.5, 6806.8, 51.3216, 294.452 - 0.55, 10000.0, 48.0, 30801.6, 16517.7, 7366.0, 63.4873, 308.016 - 0.55, 10000.0, 50.0, 32151.3, 16847.1, 7921.7, 72.7201, 321.513 - 0.55, 15000.0, 21.0, 8589.7, 7962.3, 866.4, 5.2947, 85.897 - 0.55, 15000.0, 22.0, 9294.1, 8290.2, 1034.6, 6.3704, 92.941 - 0.55, 15000.0, 24.0, 10637.7, 8880.9, 1337.3, 8.0399, 106.37700000000001 - 0.55, 15000.0, 26.0, 11913.6, 9404.0, 1653.0, 9.52, 119.13600000000001 - 0.55, 15000.0, 30.0, 14588.5, 10405.8, 2359.7, 13.0203, 145.885 - 0.55, 15000.0, 34.0, 17108.0, 11252.3, 3098.8, 15.5778, 171.08 - 0.55, 15000.0, 38.0, 19526.7, 11997.8, 3861.4, 17.7957, 195.26700000000002 - 0.55, 15000.0, 42.0, 21872.4, 12670.6, 4642.0, 19.7451, 218.72400000000002 - 0.55, 15000.0, 46.0, 24153.7, 13278.7, 5460.9, 25.1739, 241.537 - 0.55, 15000.0, 48.0, 25266.4, 13555.1, 5907.7, 37.7816, 252.66400000000002 - 0.55, 15000.0, 50.0, 26373.7, 13825.7, 6352.0, 52.6518, 263.737 - 0.55, 20000.0, 21.0, 6989.4, 6479.0, 703.3, 6.503, 69.89399999999999 - 0.55, 20000.0, 22.0, 7563.3, 6746.5, 837.0, 5.0064, 75.63300000000001 - 0.55, 20000.0, 24.0, 8657.4, 7228.1, 1077.2, 6.5972, 86.574 - 0.55, 20000.0, 26.0, 9696.4, 7654.5, 1327.5, 8.0013, 96.964 - 0.55, 20000.0, 30.0, 11874.4, 8471.2, 1888.0, 11.0514, 118.744 - 0.55, 20000.0, 34.0, 13925.6, 9161.1, 2474.4, 13.5941, 139.256 - 0.55, 20000.0, 38.0, 15894.5, 9768.8, 3078.5, 15.69, 158.945 - 0.55, 20000.0, 42.0, 17804.3, 10317.3, 3698.0, 17.5325, 178.043 - 0.55, 20000.0, 46.0, 19661.3, 10813.0, 4347.4, 19.2513, 196.613 - 0.55, 20000.0, 48.0, 20567.3, 11038.3, 4701.1, 20.1286, 205.673 - 0.55, 20000.0, 50.0, 21468.4, 11258.8, 5053.1, 25.1535, 214.68400000000003 - 0.55, 25000.0, 21.0, 5638.5, 5226.6, 569.1, 9.4348, 56.385 - 0.55, 25000.0, 22.0, 6102.2, 5443.2, 674.2, 6.9986, 61.022 - 0.55, 25000.0, 24.0, 6985.9, 5832.7, 863.0, 5.1538, 69.859 - 0.55, 25000.0, 26.0, 7825.0, 6177.5, 1059.5, 6.4814, 78.25 - 0.55, 25000.0, 30.0, 9583.8, 6838.0, 1499.7, 8.8813, 95.838 - 0.55, 25000.0, 34.0, 11240.1, 7395.8, 1960.8, 11.5975, 112.40100000000001 - 0.55, 25000.0, 38.0, 12829.7, 7887.1, 2435.5, 13.5701, 128.297 - 0.55, 25000.0, 42.0, 14371.4, 8330.6, 2922.0, 15.2974, 143.714 - 0.55, 25000.0, 46.0, 15870.7, 8731.4, 3431.6, 16.9093, 158.70700000000002 - 0.55, 25000.0, 48.0, 16601.9, 8913.6, 3708.9, 17.7331, 166.019 - 0.55, 25000.0, 50.0, 17329.5, 9092.0, 3985.6, 18.5183, 173.29500000000002 - 0.55, 30000.0, 21.0, 4506.0, 4176.6, 459.6, 12.3646, 45.06 - 0.55, 30000.0, 22.0, 4877.6, 4350.6, 541.3, 9.9465, 48.776 - 0.55, 30000.0, 24.0, 5585.4, 4663.2, 688.6, 6.3459, 55.854 - 0.55, 30000.0, 26.0, 6257.1, 4939.6, 841.1, 4.9951, 62.571000000000005 - 0.55, 30000.0, 30.0, 7665.1, 5469.3, 1183.3, 7.2442, 76.65100000000001 - 0.55, 30000.0, 34.0, 8990.5, 5916.4, 1541.7, 9.1534, 89.905 - 0.55, 30000.0, 38.0, 10262.7, 6310.2, 1910.9, 11.4896, 102.62700000000001 - 0.55, 30000.0, 42.0, 11496.3, 6665.6, 2289.2, 13.1001, 114.963 - 0.55, 30000.0, 46.0, 12696.1, 6986.9, 2685.7, 14.6049, 126.96100000000001 - 0.55, 30000.0, 48.0, 13281.5, 7133.2, 2900.4, 15.3716, 132.815 - 0.55, 30000.0, 50.0, 13863.3, 7275.8, 3114.4, 16.1055, 138.633 - 0.6, 15000.0, 21.0, 9973.8, 9348.2, 950.5, 5.9783, 99.738 - 0.6, 15000.0, 22.0, 10687.7, 9686.8, 1124.3, 7.0163, 106.87700000000001 - 0.6, 15000.0, 24.0, 12054.5, 10302.9, 1438.6, 8.6443, 120.545 - 0.6, 15000.0, 26.0, 13357.4, 10855.1, 1754.7, 10.0484, 133.574 - 0.6, 15000.0, 30.0, 16084.8, 11914.4, 2488.5, 13.592, 160.84799999999998 - 0.6, 15000.0, 34.0, 18652.7, 12814.1, 3252.5, 16.1377, 186.52700000000002 - 0.6, 15000.0, 38.0, 21114.4, 13607.6, 4042.6, 18.3508, 211.144 - 0.6, 15000.0, 42.0, 23501.9, 14327.1, 4845.2, 20.2894, 235.019 - 0.6, 15000.0, 46.0, 25820.8, 14977.7, 5688.9, 30.203, 258.20799999999997 - 0.6, 15000.0, 48.0, 26957.4, 15280.2, 6143.4, 44.8334, 269.574 - 0.6, 15000.0, 50.0, 28089.5, 15578.2, 6600.6, 58.0636, 280.895 - 0.6, 20000.0, 21.0, 8116.3, 7607.3, 769.9, 4.8739, 81.163 - 0.6, 20000.0, 22.0, 8697.8, 7883.4, 907.9, 5.6219, 86.978 - 0.6, 20000.0, 24.0, 9810.9, 8385.7, 1157.0, 7.1692, 98.109 - 0.6, 20000.0, 26.0, 10872.0, 8836.1, 1408.5, 8.504, 108.72 - 0.6, 20000.0, 30.0, 13092.7, 9699.5, 1989.8, 11.7084, 130.92700000000002 - 0.6, 20000.0, 34.0, 15183.5, 10432.9, 2596.5, 14.1211, 151.835 - 0.6, 20000.0, 38.0, 17187.7, 11079.9, 3223.0, 16.2145, 171.877 - 0.6, 20000.0, 42.0, 19131.3, 11666.4, 3858.8, 18.0426, 191.313 - 0.6, 20000.0, 46.0, 21019.2, 12196.8, 4528.3, 19.7561, 210.192 - 0.6, 20000.0, 48.0, 21944.6, 12443.4, 4888.4, 21.6513, 219.446 - 0.6, 20000.0, 50.0, 22865.7, 12685.9, 5250.5, 29.7394, 228.657 - 0.6, 25000.0, 21.0, 6548.0, 6137.4, 621.3, 7.8343, 65.48 - 0.6, 25000.0, 22.0, 7018.0, 6361.0, 730.0, 5.5192, 70.18 - 0.6, 25000.0, 24.0, 7917.0, 6767.3, 925.6, 5.6982, 79.17 - 0.6, 25000.0, 26.0, 8773.7, 7131.3, 1123.2, 6.9559, 87.73700000000001 - 0.6, 25000.0, 30.0, 10567.1, 7829.7, 1580.2, 9.3365, 105.671 - 0.6, 25000.0, 34.0, 12254.9, 8422.5, 2056.4, 12.09, 122.54899999999999 - 0.6, 25000.0, 38.0, 13872.9, 8945.6, 2548.6, 14.0586, 138.729 - 0.6, 25000.0, 42.0, 15441.9, 9419.5, 3048.5, 15.7736, 154.419 - 0.6, 25000.0, 46.0, 16965.8, 9848.6, 3573.0, 17.3772, 169.658 - 0.6, 25000.0, 48.0, 17712.8, 10048.1, 3855.9, 18.1848, 177.128 - 0.6, 25000.0, 50.0, 18456.6, 10244.4, 4140.2, 18.9671, 184.566 - 0.6, 30000.0, 21.0, 5233.4, 4905.1, 500.0, 10.771, 52.333999999999996 - 0.6, 30000.0, 22.0, 5610.0, 5084.7, 584.6, 8.4942, 56.1 - 0.6, 30000.0, 24.0, 6329.9, 5410.6, 736.4, 5.0619, 63.299 - 0.6, 30000.0, 26.0, 7015.7, 5702.4, 890.5, 5.441, 70.157 - 0.6, 30000.0, 30.0, 8451.2, 6262.4, 1245.5, 7.6673, 84.51200000000001 - 0.6, 30000.0, 34.0, 9802.1, 6737.8, 1616.1, 9.6371, 98.021 - 0.6, 30000.0, 38.0, 11096.9, 7157.0, 1998.7, 11.9431, 110.969 - 0.6, 30000.0, 42.0, 12352.3, 7536.9, 2387.5, 13.542, 123.523 - 0.6, 30000.0, 46.0, 13571.6, 7880.7, 2795.9, 15.0403, 135.716 - 0.6, 30000.0, 48.0, 14169.7, 8041.0, 3014.6, 15.7897, 141.697 - 0.6, 30000.0, 50.0, 14764.6, 8198.1, 3235.5, 16.5238, 147.64600000000002 - 0.6, 35000.0, 21.0, 4139.6, 3879.7, 401.9, 13.7651, 41.39600000000001 - 0.6, 35000.0, 22.0, 4438.7, 4022.7, 467.0, 11.4717, 44.387 - 0.6, 35000.0, 24.0, 5009.8, 4281.9, 583.8, 8.0866, 50.098000000000006 - 0.6, 35000.0, 26.0, 5553.5, 4513.7, 702.3, 5.2844, 55.535000000000004 - 0.6, 35000.0, 30.0, 6691.7, 4958.7, 975.1, 6.0676, 66.917 - 0.6, 35000.0, 34.0, 7762.5, 5336.2, 1259.8, 7.8379, 77.625 - 0.6, 35000.0, 38.0, 8788.5, 5669.1, 1553.9, 9.6313, 87.885 - 0.6, 35000.0, 42.0, 9783.3, 5970.6, 1853.8, 11.4063, 97.833 - 0.6, 35000.0, 46.0, 10749.7, 6243.7, 2167.6, 12.7926, 107.49700000000001 - 0.6, 35000.0, 48.0, 11223.1, 6370.7, 2335.6, 13.4895, 112.23100000000001 - 0.6, 35000.0, 50.0, 11695.0, 6496.0, 2504.7, 14.1725, 116.95 - 0.6, 37000.0, 21.0, 3758.1, 3522.0, 370.0, 14.2083, 37.581 - 0.6, 37000.0, 22.0, 4030.2, 3652.4, 428.7, 11.9308, 40.302 - 0.6, 37000.0, 24.0, 4549.5, 3888.3, 534.1, 8.6067, 45.495 - 0.6, 37000.0, 26.0, 5043.7, 4099.0, 640.8, 5.8649, 50.437 - 0.6, 37000.0, 30.0, 6078.5, 4504.0, 886.9, 5.62, 60.785000000000004 - 0.6, 37000.0, 34.0, 7051.8, 4847.5, 1143.9, 7.3337, 70.518 - 0.6, 37000.0, 38.0, 7984.2, 5150.1, 1409.1, 8.8243, 79.842 - 0.6, 37000.0, 42.0, 8888.2, 5424.2, 1680.1, 10.7527, 88.882 - 0.6, 37000.0, 46.0, 9766.3, 5672.7, 1963.0, 12.0908, 97.663 - 0.6, 37000.0, 48.0, 10197.0, 5788.4, 2114.5, 12.7641, 101.97 - 0.6, 37000.0, 50.0, 10625.8, 5902.3, 2266.3, 13.4179, 106.258 - 0.6, 39000.0, 21.0, 3410.5, 3195.9, 342.8, 13.7365, 34.105000000000004 - 0.6, 39000.0, 22.0, 3658.1, 3314.8, 396.0, 11.5252, 36.581 - 0.6, 39000.0, 24.0, 4130.3, 3529.5, 491.6, 8.3235, 41.303000000000004 - 0.6, 39000.0, 26.0, 4579.5, 3721.3, 588.5, 5.6738, 45.795 - 0.6, 39000.0, 30.0, 5520.0, 4089.6, 811.7, 5.3948, 55.2 - 0.6, 39000.0, 34.0, 6404.7, 4402.1, 1044.8, 7.0416, 64.047 - 0.6, 39000.0, 38.0, 7251.9, 4677.1, 1285.7, 8.4753, 72.51899999999999 - 0.6, 39000.0, 42.0, 8073.2, 4926.2, 1532.0, 10.3344, 80.732 - 0.6, 39000.0, 46.0, 8871.3, 5152.2, 1788.5, 11.6188, 88.713 - 0.6, 39000.0, 48.0, 9262.7, 5257.5, 1925.9, 12.2647, 92.62700000000001 - 0.6, 39000.0, 50.0, 9652.5, 5361.2, 2063.4, 12.8882, 96.525 - 0.6, 41000.0, 21.0, 3094.4, 2899.4, 318.6, 13.295, 30.944000000000003 - 0.6, 41000.0, 22.0, 3320.0, 3008.0, 366.6, 11.1448, 33.2 - 0.6, 41000.0, 24.0, 3749.4, 3203.6, 453.0, 8.0632, 37.494 - 0.6, 41000.0, 26.0, 4157.8, 3378.0, 541.0, 5.5011, 41.578 - 0.6, 41000.0, 30.0, 5012.8, 3713.2, 743.4, 5.178, 50.128 - 0.6, 41000.0, 34.0, 5816.8, 3997.3, 954.9, 6.7566, 58.168000000000006 - 0.6, 41000.0, 38.0, 6586.8, 4247.5, 1173.9, 8.1404, 65.86800000000001 - 0.6, 41000.0, 42.0, 7333.1, 4473.9, 1397.5, 9.9298, 73.331 - 0.6, 41000.0, 46.0, 8058.4, 4679.4, 1630.2, 11.1649, 80.584 - 0.6, 41000.0, 48.0, 8414.1, 4775.2, 1754.8, 11.7844, 84.141 - 0.6, 41000.0, 50.0, 8768.5, 4869.7, 1878.9, 12.376, 87.685 - 0.65, 15000.0, 21.0, 11481.3, 10854.1, 1035.9, 6.6394, 114.81299999999999 - 0.65, 15000.0, 22.0, 12207.7, 11204.2, 1215.3, 7.6447, 122.07700000000001 - 0.65, 15000.0, 24.0, 13603.0, 11846.9, 1542.7, 9.2444, 136.03 - 0.65, 15000.0, 26.0, 14935.6, 12427.0, 1867.4, 11.011, 149.356 - 0.65, 15000.0, 30.0, 17724.6, 13543.7, 2628.1, 14.1919, 177.24599999999998 - 0.65, 15000.0, 34.0, 20349.9, 14496.6, 3420.7, 16.7302, 203.49900000000002 - 0.65, 15000.0, 38.0, 22863.3, 15337.4, 4243.8, 18.9494, 228.633 - 0.65, 15000.0, 42.0, 25300.6, 16102.7, 5073.7, 20.8824, 253.006 - 0.65, 15000.0, 46.0, 27684.0, 16813.4, 5945.8, 37.6447, 276.84000000000003 - 0.65, 15000.0, 48.0, 28853.2, 17146.3, 6412.4, 52.4446, 288.53200000000004 - 0.65, 15000.0, 50.0, 30016.4, 17473.3, 6885.5, 63.165, 300.16400000000004 - 0.65, 20000.0, 21.0, 9343.5, 8833.4, 837.7, 5.2653, 93.435 - 0.65, 20000.0, 22.0, 9935.0, 9118.7, 979.9, 6.2209, 99.35000000000001 - 0.65, 20000.0, 24.0, 11071.1, 9642.6, 1239.6, 7.74, 110.71100000000001 - 0.65, 20000.0, 26.0, 12156.3, 10115.6, 1497.6, 9.0357, 121.56299999999999 - 0.65, 20000.0, 30.0, 14427.2, 11026.1, 2101.3, 12.2787, 144.27200000000002 - 0.65, 20000.0, 34.0, 16564.3, 11802.7, 2729.9, 14.6793, 165.643 - 0.65, 20000.0, 38.0, 18610.2, 12488.0, 3382.1, 16.7756, 186.102 - 0.65, 20000.0, 42.0, 20594.6, 13112.0, 4040.1, 18.6009, 205.946 - 0.65, 20000.0, 46.0, 22534.2, 13691.1, 4731.2, 20.3058, 225.342 - 0.65, 20000.0, 48.0, 23485.7, 13962.4, 5100.5, 24.9412, 234.857 - 0.65, 20000.0, 50.0, 24432.6, 14229.1, 5474.5, 36.2661, 244.326 - 0.65, 25000.0, 21.0, 7538.7, 7127.2, 674.5, 6.3118, 75.387 - 0.65, 25000.0, 22.0, 8016.8, 7358.3, 786.7, 4.8016, 80.168 - 0.65, 25000.0, 24.0, 8934.3, 7781.9, 990.5, 6.2373, 89.34299999999999 - 0.65, 25000.0, 26.0, 9810.5, 8164.3, 1193.3, 7.4577, 98.105 - 0.65, 25000.0, 30.0, 11644.1, 8900.5, 1667.2, 9.8122, 116.441 - 0.65, 25000.0, 34.0, 13369.6, 9528.5, 2161.3, 12.6125, 133.696 - 0.65, 25000.0, 38.0, 15021.2, 10082.6, 2673.6, 14.582, 150.21200000000002 - 0.65, 25000.0, 42.0, 16623.1, 10587.1, 3190.9, 16.2937, 166.231 - 0.65, 25000.0, 46.0, 18188.8, 11055.3, 3733.0, 17.8916, 181.888 - 0.65, 25000.0, 48.0, 18957.1, 11274.9, 4023.5, 18.6867, 189.571 - 0.65, 25000.0, 50.0, 19721.6, 11490.7, 4316.5, 19.4646, 197.21599999999998 - 0.65, 30000.0, 21.0, 6025.8, 5696.8, 541.2, 9.2686, 60.258 - 0.65, 30000.0, 22.0, 6408.8, 5882.4, 628.6, 7.1132, 64.08800000000001 - 0.65, 30000.0, 24.0, 7143.4, 6222.1, 786.8, 4.7609, 71.434 - 0.65, 30000.0, 26.0, 7844.8, 6528.7, 944.9, 5.9115, 78.44800000000001 - 0.65, 30000.0, 30.0, 9312.7, 7119.2, 1313.5, 8.114, 93.12700000000001 - 0.65, 30000.0, 34.0, 10693.4, 7622.5, 1697.7, 10.5176, 106.934 - 0.65, 30000.0, 38.0, 12015.1, 8066.7, 2096.0, 12.429, 120.15100000000001 - 0.65, 30000.0, 42.0, 13296.7, 8470.9, 2498.2, 14.0245, 132.967 - 0.65, 30000.0, 46.0, 14549.5, 8846.3, 2919.9, 15.5145, 145.495 - 0.65, 30000.0, 48.0, 15164.4, 9022.5, 3145.2, 16.2578, 151.644 - 0.65, 30000.0, 50.0, 15776.0, 9195.4, 3372.5, 16.9835, 157.76 - 0.65, 35000.0, 21.0, 4767.0, 4506.6, 433.5, 12.2477, 47.67 - 0.65, 35000.0, 22.0, 5071.1, 4654.4, 500.8, 10.0982, 50.711000000000006 - 0.65, 35000.0, 24.0, 5653.7, 4924.4, 622.1, 6.8639, 56.537 - 0.65, 35000.0, 26.0, 6210.0, 5168.0, 743.9, 4.422, 62.1 - 0.65, 35000.0, 30.0, 7373.7, 5637.1, 1027.3, 6.4841, 73.737 - 0.65, 35000.0, 34.0, 8468.2, 6037.1, 1322.7, 8.2441, 84.682 - 0.65, 35000.0, 38.0, 9515.4, 6389.7, 1628.5, 10.3632, 95.154 - 0.65, 35000.0, 42.0, 10530.9, 6710.5, 1938.8, 11.8544, 105.309 - 0.65, 35000.0, 46.0, 11523.6, 7008.6, 2262.9, 13.2342, 115.236 - 0.65, 35000.0, 48.0, 12010.7, 7148.5, 2436.1, 13.9247, 120.10700000000001 - 0.65, 35000.0, 50.0, 12495.8, 7286.2, 2609.9, 14.5969, 124.958 - 0.65, 37000.0, 21.0, 4328.0, 4091.4, 398.3, 12.7114, 43.28 - 0.65, 37000.0, 22.0, 4604.7, 4226.1, 459.1, 10.5799, 46.047 - 0.65, 37000.0, 24.0, 5134.7, 4472.0, 568.6, 7.4067, 51.347 - 0.65, 37000.0, 26.0, 5640.3, 4693.6, 678.3, 4.7981, 56.403000000000006 - 0.65, 37000.0, 30.0, 6698.2, 5120.4, 934.1, 6.0241, 66.982 - 0.65, 37000.0, 34.0, 7693.1, 5484.2, 1200.6, 7.7263, 76.93100000000001 - 0.65, 37000.0, 38.0, 8645.0, 5805.0, 1476.6, 9.5229, 86.45 - 0.65, 37000.0, 42.0, 9567.7, 6096.5, 1757.2, 11.1876, 95.677 - 0.65, 37000.0, 46.0, 10470.1, 6367.8, 2049.0, 12.5173, 104.70100000000001 - 0.65, 37000.0, 48.0, 10912.6, 6494.8, 2205.3, 13.1845, 109.126 - 0.65, 37000.0, 50.0, 11353.7, 6620.3, 2361.7, 13.8301, 113.537 - 0.65, 39000.0, 21.0, 3928.0, 3713.0, 368.4, 12.2906, 39.28 - 0.65, 39000.0, 22.0, 4179.8, 3835.7, 423.5, 10.2222, 41.798 - 0.65, 39000.0, 24.0, 4661.5, 4059.5, 522.5, 7.1754, 46.615 - 0.65, 39000.0, 26.0, 5121.2, 4261.1, 622.3, 4.6517, 51.211999999999996 - 0.65, 39000.0, 30.0, 6082.8, 4649.3, 854.5, 5.7838, 60.828 - 0.65, 39000.0, 34.0, 6987.2, 4980.3, 1096.2, 7.4195, 69.872 - 0.65, 39000.0, 38.0, 7852.3, 5272.0, 1347.0, 9.1325, 78.52300000000001 - 0.65, 39000.0, 42.0, 8690.6, 5536.9, 1601.9, 10.7517, 86.906 - 0.65, 39000.0, 46.0, 9510.4, 5783.5, 1866.9, 12.0307, 95.104 - 0.65, 39000.0, 48.0, 9912.8, 5899.1, 2008.5, 12.6712, 99.128 - 0.65, 39000.0, 50.0, 10313.9, 6013.4, 2149.9, 13.285, 103.139 - 0.65, 41000.0, 21.0, 3564.4, 3369.0, 341.4, 11.8988, 35.644 - 0.65, 41000.0, 22.0, 3793.7, 3481.1, 391.2, 9.8837, 37.937 - 0.65, 41000.0, 24.0, 4231.9, 3684.9, 480.9, 6.9499, 42.318999999999996 - 0.65, 41000.0, 26.0, 4649.7, 3868.3, 571.5, 4.5148, 46.497 - 0.65, 41000.0, 30.0, 5523.7, 4221.4, 782.2, 5.5521, 55.237 - 0.65, 41000.0, 34.0, 6345.8, 4522.5, 1001.6, 7.1247, 63.458000000000006 - 0.65, 41000.0, 38.0, 7131.8, 4787.6, 1229.2, 8.7518, 71.318 - 0.65, 41000.0, 42.0, 7893.5, 5028.4, 1460.7, 10.3306, 78.935 - 0.65, 41000.0, 46.0, 8638.7, 5252.7, 1701.3, 11.5623, 86.38700000000001 - 0.65, 41000.0, 48.0, 9004.5, 5357.9, 1829.8, 12.177, 90.045 - 0.65, 41000.0, 50.0, 9369.0, 5462.0, 1957.7, 12.7624, 93.69 - 0.7, 15000.0, 21.0, 13112.0, 12479.9, 1130.1, 7.3244, 131.12 - 0.7, 15000.0, 22.0, 13855.4, 12844.0, 1307.0, 8.2542, 138.554 - 0.7, 15000.0, 24.0, 15285.0, 13515.0, 1648.6, 9.8351, 152.85 - 0.7, 15000.0, 26.0, 16649.3, 14120.8, 1994.3, 11.9014, 166.493 - 0.7, 15000.0, 30.0, 19512.9, 15298.6, 2780.9, 14.827, 195.12900000000002 - 0.7, 15000.0, 34.0, 22204.6, 16304.7, 3606.0, 17.3622, 222.046 - 0.7, 15000.0, 38.0, 24778.2, 17192.6, 4465.4, 19.5875, 247.782 - 0.7, 15000.0, 42.0, 27296.1, 18024.8, 5329.0, 23.4826, 272.961 - 0.7, 15000.0, 46.0, 29762.1, 18805.2, 6235.3, 46.8096, 297.621 - 0.7, 15000.0, 48.0, 30970.5, 19170.8, 6719.8, 59.383, 309.705 - 0.7, 15000.0, 50.0, 32171.1, 19528.5, 7209.9, 68.7032, 321.711 - 0.7, 20000.0, 21.0, 10671.0, 10156.9, 912.4, 5.9185, 106.71000000000001 - 0.7, 20000.0, 22.0, 11276.8, 10454.1, 1053.1, 6.8056, 112.768 - 0.7, 20000.0, 24.0, 12440.5, 11000.8, 1323.8, 8.3011, 124.405 - 0.7, 20000.0, 26.0, 13551.0, 11494.4, 1598.0, 9.6082, 135.51 - 0.7, 20000.0, 30.0, 15882.3, 12454.6, 2221.7, 12.8741, 158.823 - 0.7, 20000.0, 34.0, 18073.4, 13274.7, 2876.5, 15.2715, 180.734 - 0.7, 20000.0, 38.0, 20168.3, 13998.5, 3557.9, 17.3754, 201.683 - 0.7, 20000.0, 42.0, 22217.1, 14676.3, 4242.1, 19.2013, 222.171 - 0.7, 20000.0, 46.0, 24224.9, 15312.9, 4960.5, 22.3983, 242.24900000000002 - 0.7, 20000.0, 48.0, 25208.3, 15610.7, 5344.4, 30.8596, 252.083 - 0.7, 20000.0, 50.0, 26185.8, 15902.7, 5731.7, 44.4788, 261.858 - 0.7, 25000.0, 21.0, 8610.5, 8195.8, 733.3, 4.7574, 86.105 - 0.7, 25000.0, 22.0, 9099.7, 8436.2, 843.9, 5.3542, 90.99700000000001 - 0.7, 25000.0, 24.0, 10039.4, 8878.3, 1056.5, 6.7662, 100.394 - 0.7, 25000.0, 26.0, 10936.2, 9277.4, 1272.2, 7.9972, 109.36200000000001 - 0.7, 25000.0, 30.0, 12818.5, 10053.9, 1762.2, 10.8094, 128.185 - 0.7, 25000.0, 34.0, 14587.3, 10716.9, 2276.5, 13.1665, 145.873 - 0.7, 25000.0, 38.0, 16278.4, 11302.1, 2811.5, 15.1405, 162.784 - 0.7, 25000.0, 42.0, 17932.2, 11850.1, 3349.2, 16.8532, 179.322 - 0.7, 25000.0, 46.0, 19552.5, 12364.7, 3912.9, 18.4489, 195.525 - 0.7, 25000.0, 48.0, 20346.0, 12605.2, 4213.9, 19.2419, 203.46 - 0.7, 25000.0, 50.0, 21135.9, 12842.2, 4516.7, 20.8046, 211.359 - 0.7, 30000.0, 21.0, 6883.1, 6551.6, 586.9, 7.7444, 68.831 - 0.7, 30000.0, 22.0, 7275.0, 6744.6, 673.2, 5.7924, 72.75 - 0.7, 30000.0, 24.0, 8027.3, 7099.1, 838.4, 5.2616, 80.27300000000001 - 0.7, 30000.0, 26.0, 8744.9, 7418.9, 1005.9, 6.4147, 87.449 - 0.7, 30000.0, 30.0, 10251.7, 8041.7, 1387.1, 8.5806, 102.51700000000001 - 0.7, 30000.0, 34.0, 11667.2, 8573.2, 1787.1, 11.0992, 116.67200000000001 - 0.7, 30000.0, 38.0, 13020.3, 9042.3, 2203.0, 12.9445, 130.203 - 0.7, 30000.0, 42.0, 14343.5, 9481.5, 2621.7, 14.5449, 143.435 - 0.7, 30000.0, 46.0, 15639.9, 9894.0, 3059.8, 16.0318, 156.399 - 0.7, 30000.0, 48.0, 16274.9, 10087.0, 3293.1, 16.7705, 162.749 - 0.7, 30000.0, 50.0, 16906.9, 10277.0, 3528.3, 17.4883, 169.06900000000002 - 0.7, 35000.0, 21.0, 5445.9, 5183.5, 468.4, 10.7259, 54.458999999999996 - 0.7, 35000.0, 22.0, 5757.0, 5337.1, 535.0, 8.7976, 57.57 - 0.7, 35000.0, 24.0, 6353.6, 5618.9, 661.7, 5.6702, 63.53600000000001 - 0.7, 35000.0, 26.0, 6922.8, 5873.2, 791.0, 4.8981, 69.22800000000001 - 0.7, 35000.0, 30.0, 8117.1, 6367.8, 1083.9, 6.9194, 81.171 - 0.7, 35000.0, 34.0, 9239.1, 6790.1, 1391.6, 8.6731, 92.391 - 0.7, 35000.0, 38.0, 10311.5, 7162.7, 1711.2, 10.8441, 103.11500000000001 - 0.7, 35000.0, 42.0, 11359.5, 7511.0, 2033.2, 12.3341, 113.595 - 0.7, 35000.0, 46.0, 12386.9, 7838.7, 2370.3, 13.7136, 123.869 - 0.7, 35000.0, 48.0, 12890.1, 7992.0, 2549.7, 14.4009, 128.901 - 0.7, 35000.0, 50.0, 13391.1, 8143.2, 2729.2, 15.0634, 133.911 - 0.7, 37000.0, 21.0, 4944.6, 4706.2, 429.8, 11.2106, 49.446000000000005 - 0.7, 37000.0, 22.0, 5227.7, 4846.2, 489.9, 9.3025, 52.277 - 0.7, 37000.0, 24.0, 5770.2, 5102.7, 604.1, 6.2444, 57.702 - 0.7, 37000.0, 26.0, 6287.7, 5334.1, 720.9, 4.4868, 62.877 - 0.7, 37000.0, 30.0, 7373.4, 5784.0, 985.0, 6.4444, 73.734 - 0.7, 37000.0, 34.0, 8393.3, 6168.3, 1262.6, 8.1407, 83.93299999999999 - 0.7, 37000.0, 38.0, 9368.0, 6507.2, 1551.0, 10.2088, 93.68 - 0.7, 37000.0, 42.0, 10320.4, 6823.9, 1842.1, 11.6506, 103.204 - 0.7, 37000.0, 46.0, 11254.0, 7121.8, 2146.1, 12.9821, 112.54 - 0.7, 37000.0, 48.0, 11711.4, 7261.3, 2308.0, 13.645, 117.114 - 0.7, 37000.0, 50.0, 12167.0, 7399.1, 2469.7, 14.282, 121.67 - 0.7, 39000.0, 21.0, 4487.8, 4271.2, 396.9, 10.8462, 44.878 - 0.7, 39000.0, 22.0, 4745.4, 4398.8, 451.5, 8.9937, 47.454 - 0.7, 39000.0, 24.0, 5238.7, 4632.3, 555.0, 6.0497, 52.387 - 0.7, 39000.0, 26.0, 5709.1, 4842.7, 660.9, 4.3014, 57.09100000000001 - 0.7, 39000.0, 30.0, 6696.0, 5252.1, 900.8, 6.1896, 66.96000000000001 - 0.7, 39000.0, 34.0, 7623.1, 5601.6, 1152.7, 7.8201, 76.23100000000001 - 0.7, 39000.0, 38.0, 8508.9, 5909.8, 1414.4, 9.8095, 85.089 - 0.7, 39000.0, 42.0, 9374.1, 6197.4, 1678.7, 11.196, 93.741 - 0.7, 39000.0, 46.0, 10222.7, 6468.4, 1955.0, 12.4794, 102.227 - 0.7, 39000.0, 48.0, 10638.4, 6595.3, 2101.9, 13.1156, 106.384 - 0.7, 39000.0, 50.0, 11052.6, 6720.7, 2248.2, 13.7233, 110.52600000000001 - 0.7, 41000.0, 21.0, 4072.9, 3876.1, 367.0, 10.4999, 40.729 - 0.7, 41000.0, 22.0, 4307.3, 3992.4, 416.6, 8.698, 43.073 - 0.7, 41000.0, 24.0, 4756.0, 4204.9, 510.3, 5.8669, 47.56 - 0.7, 41000.0, 26.0, 5183.6, 4396.4, 606.4, 4.1214, 51.836000000000006 - 0.7, 41000.0, 30.0, 6080.8, 4768.8, 824.2, 5.9412, 60.808 - 0.7, 41000.0, 34.0, 6923.7, 5086.9, 1052.9, 7.5111, 69.237 - 0.7, 41000.0, 38.0, 7728.7, 5367.1, 1290.6, 9.4241, 77.287 - 0.7, 41000.0, 42.0, 8515.0, 5628.6, 1531.1, 10.7626, 85.15 - 0.7, 41000.0, 46.0, 9286.2, 5874.9, 1781.7, 11.9963, 92.86200000000001 - 0.7, 41000.0, 48.0, 9664.1, 5990.4, 1914.9, 12.6068, 96.641 - 0.7, 41000.0, 50.0, 10040.5, 6104.4, 2047.5, 13.1893, 100.405 - 0.7, 43000.0, 21.0, 3695.7, 3516.9, 340.2, 10.182, 36.957 - 0.7, 43000.0, 22.0, 3909.2, 3623.1, 385.1, 8.4342, 39.092 - 0.7, 43000.0, 24.0, 4317.5, 3816.8, 469.8, 5.6921, 43.175000000000004 - 0.7, 43000.0, 26.0, 4706.4, 3991.1, 557.2, 3.9488, 47.064 - 0.7, 43000.0, 30.0, 5522.1, 4329.9, 754.8, 5.704, 55.221000000000004 - 0.7, 43000.0, 34.0, 6288.3, 4619.3, 962.3, 7.2124, 62.883 - 0.7, 43000.0, 38.0, 7019.9, 4874.0, 1178.2, 9.0518, 70.199 - 0.7, 43000.0, 42.0, 7734.6, 5111.8, 1396.8, 10.3435, 77.346 - 0.7, 43000.0, 46.0, 8435.5, 5335.9, 1624.2, 11.5304, 84.355 - 0.7, 43000.0, 48.0, 8778.7, 5440.7, 1745.0, 12.1165, 87.787 - 0.7, 43000.0, 50.0, 9121.2, 5544.6, 1865.4, 12.6763, 91.212 - 0.75, 20000.0, 21.0, 12099.2, 11578.4, 993.4, 6.5843, 120.992 - 0.75, 20000.0, 22.0, 12724.0, 11890.6, 1129.3, 7.3857, 127.24000000000001 - 0.75, 20000.0, 24.0, 13920.6, 12462.1, 1410.5, 8.8599, 139.20600000000002 - 0.75, 20000.0, 26.0, 15061.0, 12977.4, 1701.9, 10.3273, 150.61 - 0.75, 20000.0, 30.0, 17460.5, 13988.0, 2352.5, 13.4976, 174.605 - 0.75, 20000.0, 34.0, 19714.1, 14852.5, 3037.5, 15.8999, 197.141 - 0.75, 20000.0, 38.0, 21884.6, 15634.1, 3751.2, 18.0102, 218.846 - 0.75, 20000.0, 42.0, 24018.9, 16379.3, 4468.2, 19.8495, 240.18900000000002 - 0.75, 20000.0, 46.0, 26105.5, 17076.8, 5219.0, 27.2502, 261.055 - 0.75, 20000.0, 48.0, 27126.2, 17402.8, 5619.3, 39.5279, 271.262 - 0.75, 20000.0, 50.0, 28140.0, 17722.3, 6024.0, 53.0099, 281.40000000000003 - 0.75, 25000.0, 21.0, 9763.6, 9343.5, 797.1, 5.1492, 97.63600000000001 - 0.75, 25000.0, 22.0, 10267.9, 9595.8, 903.1, 5.8999, 102.679 - 0.75, 25000.0, 24.0, 11234.1, 10058.0, 1124.6, 7.2923, 112.34100000000001 - 0.75, 25000.0, 26.0, 12154.7, 10474.5, 1353.8, 8.5338, 121.54700000000001 - 0.75, 25000.0, 30.0, 14092.2, 11291.8, 1864.8, 11.4987, 140.922 - 0.75, 25000.0, 34.0, 15911.3, 11990.8, 2403.1, 13.7532, 159.113 - 0.75, 25000.0, 38.0, 17663.3, 12622.6, 2963.2, 15.732, 176.633 - 0.75, 25000.0, 42.0, 19385.8, 13225.0, 3526.7, 17.4568, 193.858 - 0.75, 25000.0, 46.0, 21070.1, 13789.1, 4116.3, 19.0568, 210.701 - 0.75, 25000.0, 48.0, 21894.0, 14052.8, 4429.6, 19.8471, 218.94 - 0.75, 25000.0, 50.0, 22712.7, 14311.6, 4746.3, 24.5603, 227.127 - 0.75, 30000.0, 21.0, 7805.4, 7469.7, 636.6, 6.2175, 78.054 - 0.75, 30000.0, 22.0, 8209.2, 7672.0, 718.6, 4.557, 82.09200000000001 - 0.75, 30000.0, 24.0, 8982.7, 8042.7, 891.3, 5.7565, 89.82700000000001 - 0.75, 30000.0, 26.0, 9719.7, 8376.8, 1069.8, 6.9217, 97.197 - 0.75, 30000.0, 30.0, 11270.2, 9032.1, 1467.1, 9.0687, 112.70200000000001 - 0.75, 30000.0, 34.0, 12725.6, 9592.3, 1885.5, 11.6454, 127.256 - 0.75, 30000.0, 38.0, 14127.3, 10098.7, 2320.9, 13.4935, 141.273 - 0.75, 30000.0, 42.0, 15505.2, 10581.3, 2759.3, 15.1024, 155.05200000000002 - 0.75, 30000.0, 46.0, 16852.7, 11033.5, 3217.1, 16.5918, 168.52700000000002 - 0.75, 30000.0, 48.0, 17511.6, 11244.9, 3461.0, 17.331, 175.11599999999999 - 0.75, 30000.0, 50.0, 18167.3, 11452.9, 3705.8, 18.0435, 181.673 - 0.75, 35000.0, 21.0, 6176.3, 5910.6, 506.6, 9.2124, 61.763000000000005 - 0.75, 35000.0, 22.0, 6496.8, 6071.7, 569.8, 7.5518, 64.968 - 0.75, 35000.0, 24.0, 7110.0, 6366.1, 702.3, 4.5131, 71.10000000000001 - 0.75, 35000.0, 26.0, 7694.4, 6631.6, 839.8, 5.3704, 76.944 - 0.75, 35000.0, 30.0, 8923.6, 7152.1, 1145.3, 7.3736, 89.236 - 0.75, 35000.0, 34.0, 10077.2, 7597.2, 1467.2, 9.1266, 100.772 - 0.75, 35000.0, 38.0, 11187.9, 7999.4, 1801.8, 11.3524, 111.879 - 0.75, 35000.0, 42.0, 12279.4, 8382.4, 2139.1, 12.8488, 122.794 - 0.75, 35000.0, 46.0, 13347.0, 8741.4, 2491.2, 14.2339, 133.47 - 0.75, 35000.0, 48.0, 13869.4, 8909.5, 2678.5, 14.9197, 138.694 - 0.75, 35000.0, 50.0, 14389.1, 9075.0, 2865.5, 15.5782, 143.89100000000002 - 0.75, 37000.0, 21.0, 5608.1, 5366.7, 464.3, 9.7221, 56.081 - 0.75, 37000.0, 22.0, 5899.7, 5513.5, 521.3, 8.0824, 58.997 - 0.75, 37000.0, 24.0, 6457.4, 5781.4, 640.8, 5.1113, 64.574 - 0.75, 37000.0, 26.0, 6988.6, 6023.0, 764.9, 4.9447, 69.88600000000001 - 0.75, 37000.0, 30.0, 8106.0, 6496.6, 1040.5, 6.8848, 81.06 - 0.75, 37000.0, 34.0, 9154.7, 6901.6, 1331.0, 8.58, 91.54700000000001 - 0.75, 37000.0, 38.0, 10164.2, 7267.4, 1632.9, 10.6998, 101.64200000000001 - 0.75, 37000.0, 42.0, 11156.1, 7615.6, 1937.4, 12.1486, 111.561 - 0.75, 37000.0, 46.0, 12126.5, 7942.2, 2255.5, 13.4852, 121.265 - 0.75, 37000.0, 48.0, 12601.0, 8094.8, 2424.1, 14.1465, 126.01 - 0.75, 37000.0, 50.0, 13073.6, 8245.6, 2592.2, 14.7777, 130.73600000000002 - 0.75, 39000.0, 21.0, 5090.3, 4871.0, 428.1, 9.413, 50.903000000000006 - 0.75, 39000.0, 22.0, 5355.6, 5004.7, 479.9, 7.8205, 53.556000000000004 - 0.75, 39000.0, 24.0, 5862.7, 5248.6, 588.2, 4.959, 58.627 - 0.75, 39000.0, 26.0, 6345.7, 5468.4, 700.9, 4.7432, 63.457 - 0.75, 39000.0, 30.0, 7361.5, 5899.2, 951.1, 6.612, 73.615 - 0.75, 39000.0, 34.0, 8314.7, 6267.5, 1214.7, 8.2426, 83.147 - 0.75, 39000.0, 38.0, 9232.3, 6600.2, 1488.9, 10.2835, 92.323 - 0.75, 39000.0, 42.0, 10133.6, 6916.7, 1765.7, 11.6794, 101.33600000000001 - 0.75, 39000.0, 46.0, 11015.2, 7213.4, 2054.3, 12.9644, 110.15200000000002 - 0.75, 39000.0, 48.0, 11446.7, 7352.4, 2207.5, 13.5999, 114.46700000000001 - 0.75, 39000.0, 50.0, 11876.3, 7489.5, 2360.1, 14.2058, 118.76299999999999 - 0.75, 41000.0, 21.0, 4620.0, 4420.7, 395.3, 9.1163, 46.2 - 0.75, 41000.0, 22.0, 4861.4, 4542.5, 442.3, 7.5735, 48.614 - 0.75, 41000.0, 24.0, 5322.7, 4764.6, 540.6, 4.8099, 53.227 - 0.75, 41000.0, 26.0, 5761.8, 4964.6, 642.9, 4.5487, 57.618 - 0.75, 41000.0, 30.0, 6685.2, 5356.6, 869.9, 6.3495, 66.852 - 0.75, 41000.0, 34.0, 7551.8, 5691.7, 1109.2, 7.9189, 75.518 - 0.75, 41000.0, 38.0, 8385.8, 5994.3, 1358.1, 9.8824, 83.85799999999999 - 0.75, 41000.0, 42.0, 9204.8, 6281.8, 1609.8, 11.2269, 92.04799999999999 - 0.75, 41000.0, 46.0, 10006.1, 6551.7, 1872.0, 12.4638, 100.061 - 0.75, 41000.0, 48.0, 10398.3, 6678.1, 2010.9, 13.0741, 103.98299999999999 - 0.75, 41000.0, 50.0, 10788.7, 6802.8, 2149.4, 13.6567, 107.88700000000001 - 0.75, 43000.0, 21.0, 4192.7, 4011.6, 365.5, 8.8388, 41.927 - 0.75, 43000.0, 22.0, 4412.3, 4122.6, 408.2, 7.3458, 44.123000000000005 - 0.75, 43000.0, 24.0, 4832.0, 4324.9, 497.1, 4.6778, 48.32 - 0.75, 43000.0, 26.0, 5231.3, 4506.9, 590.1, 4.3594, 52.313 - 0.75, 43000.0, 30.0, 6071.0, 4863.7, 796.3, 6.0969, 60.71 - 0.75, 43000.0, 34.0, 6858.8, 5168.6, 1013.4, 7.606, 68.58800000000001 - 0.75, 43000.0, 38.0, 7616.8, 5443.7, 1239.5, 9.4944, 76.168 - 0.75, 43000.0, 42.0, 8361.0, 5705.0, 1468.3, 10.7912, 83.61 - 0.75, 43000.0, 46.0, 9089.4, 5950.4, 1706.1, 11.9799, 90.89399999999999 - 0.75, 43000.0, 48.0, 9445.7, 6065.4, 1832.3, 12.5674, 94.45700000000001 - 0.75, 43000.0, 50.0, 9800.8, 6179.0, 1958.1, 13.1272, 98.008 - 0.79, 20000.0, 21.0, 13316.7, 12788.5, 1056.2, 7.085, 133.167 - 0.79, 20000.0, 22.0, 13958.5, 13113.3, 1191.3, 7.8437, 139.585 - 0.79, 20000.0, 24.0, 15183.9, 13704.9, 1486.2, 9.3251, 151.839 - 0.79, 20000.0, 26.0, 16353.4, 14240.4, 1788.3, 11.2602, 163.534 - 0.79, 20000.0, 30.0, 18814.0, 15292.3, 2465.9, 14.0199, 188.14000000000001 - 0.79, 20000.0, 34.0, 21136.0, 16205.7, 3176.5, 16.4247, 211.36 - 0.79, 20000.0, 38.0, 23387.7, 17048.6, 3921.0, 18.5484, 233.877 - 0.79, 20000.0, 42.0, 25599.2, 17851.6, 4668.4, 20.4014, 255.99200000000002 - 0.79, 20000.0, 46.0, 27757.9, 18601.6, 5449.7, 33.7104, 277.579 - 0.79, 20000.0, 48.0, 28812.4, 18951.7, 5865.5, 47.6231, 288.124 - 0.79, 20000.0, 50.0, 29859.3, 19294.4, 6286.5, 58.7708, 298.593 - 0.79, 25000.0, 21.0, 10746.2, 10320.3, 846.3, 5.6217, 107.462 - 0.79, 25000.0, 22.0, 11264.8, 10583.2, 952.1, 6.3348, 112.648 - 0.79, 25000.0, 24.0, 12254.3, 11061.5, 1184.1, 7.73, 122.54299999999999 - 0.79, 25000.0, 26.0, 13198.3, 11494.4, 1421.7, 8.9669, 131.983 - 0.79, 25000.0, 30.0, 15184.9, 12345.0, 1954.0, 11.9882, 151.849 - 0.79, 25000.0, 34.0, 17059.4, 13083.5, 2512.5, 14.2443, 170.59400000000002 - 0.79, 25000.0, 38.0, 18877.2, 13765.2, 3097.0, 16.2353, 188.77200000000002 - 0.79, 25000.0, 42.0, 20662.0, 14414.1, 3683.6, 17.9702, 206.62 - 0.79, 25000.0, 46.0, 22404.6, 15020.7, 4297.5, 19.5778, 224.046 - 0.79, 25000.0, 48.0, 23255.8, 15303.8, 4623.5, 21.9802, 232.558 - 0.79, 25000.0, 50.0, 24101.0, 15581.1, 4952.6, 29.7794, 241.01 - 0.79, 30000.0, 21.0, 8591.6, 8251.2, 675.0, 5.0944, 85.91600000000001 - 0.79, 30000.0, 22.0, 9006.5, 8461.9, 756.7, 4.8532, 90.065 - 0.79, 30000.0, 24.0, 9798.6, 8845.4, 937.1, 6.1642, 97.986 - 0.79, 30000.0, 26.0, 10554.1, 9192.5, 1122.5, 7.3259, 105.54100000000001 - 0.79, 30000.0, 30.0, 12143.7, 9874.3, 1536.0, 9.4741, 121.43700000000001 - 0.79, 30000.0, 34.0, 13643.5, 10466.3, 1970.6, 12.1021, 136.435 - 0.79, 30000.0, 38.0, 15097.6, 11012.7, 2424.8, 13.9599, 150.976 - 0.79, 30000.0, 42.0, 16525.2, 11532.5, 2881.4, 15.5783, 165.252 - 0.79, 30000.0, 46.0, 17919.4, 12018.9, 3357.8, 17.0748, 179.19400000000002 - 0.79, 30000.0, 48.0, 18600.1, 12245.8, 3611.2, 17.8146, 186.00099999999998 - 0.79, 30000.0, 50.0, 19277.1, 12468.8, 3865.8, 18.5261, 192.771 - 0.79, 35000.0, 21.0, 6798.9, 6529.5, 536.1, 8.112, 67.989 - 0.79, 35000.0, 22.0, 7128.1, 6697.1, 598.7, 6.5792, 71.281 - 0.79, 35000.0, 24.0, 7756.4, 7002.1, 737.5, 4.6585, 77.564 - 0.79, 35000.0, 26.0, 8355.2, 7277.7, 880.4, 5.7496, 83.552 - 0.79, 35000.0, 30.0, 9615.4, 7819.4, 1198.4, 7.7528, 96.154 - 0.79, 35000.0, 34.0, 10803.8, 8289.5, 1532.7, 9.805, 108.038 - 0.79, 35000.0, 38.0, 11956.1, 8723.4, 1881.7, 11.7838, 119.561 - 0.79, 35000.0, 42.0, 13087.1, 9135.9, 2232.9, 13.2881, 130.871 - 0.79, 35000.0, 46.0, 14191.7, 9522.2, 2599.6, 14.681, 141.917 - 0.79, 35000.0, 48.0, 14731.2, 9702.5, 2793.6, 15.3669, 147.312 - 0.79, 35000.0, 50.0, 15267.9, 9880.0, 2987.8, 16.0243, 152.679 - 0.79, 37000.0, 21.0, 6173.6, 5928.9, 490.9, 8.6418, 61.736000000000004 - 0.79, 37000.0, 22.0, 6473.1, 6081.5, 547.1, 7.1362, 64.73100000000001 - 0.79, 37000.0, 24.0, 7044.4, 6359.1, 672.3, 4.2757, 70.444 - 0.79, 37000.0, 26.0, 7588.8, 6609.9, 801.5, 5.3123, 75.888 - 0.79, 37000.0, 30.0, 8734.3, 7102.7, 1088.2, 7.2492, 87.34299999999999 - 0.79, 37000.0, 34.0, 9814.5, 7530.3, 1389.7, 8.9444, 98.145 - 0.79, 37000.0, 38.0, 10862.0, 7925.1, 1704.9, 11.1167, 108.62 - 0.79, 37000.0, 42.0, 11889.7, 8300.2, 2022.2, 12.5731, 118.897 - 0.79, 37000.0, 46.0, 12893.6, 8651.4, 2352.9, 13.9174, 128.936 - 0.79, 37000.0, 48.0, 13383.9, 8815.5, 2528.3, 14.5794, 133.839 - 0.79, 37000.0, 50.0, 13871.8, 8977.0, 2703.4, 15.2136, 138.718 - 0.79, 39000.0, 21.0, 5603.8, 5381.5, 452.2, 8.3724, 56.038000000000004 - 0.79, 39000.0, 22.0, 5876.3, 5520.5, 503.1, 6.9121, 58.763000000000005 - 0.79, 39000.0, 24.0, 6395.9, 5773.3, 616.7, 4.1333, 63.958999999999996 - 0.79, 39000.0, 26.0, 6890.8, 6001.3, 734.2, 5.0969, 68.908 - 0.79, 39000.0, 30.0, 7932.0, 6449.6, 994.3, 6.962, 79.32000000000001 - 0.79, 39000.0, 34.0, 8914.2, 6838.7, 1268.4, 8.5965, 89.14200000000001 - 0.79, 39000.0, 38.0, 9866.0, 7197.6, 1554.3, 10.685, 98.66 - 0.79, 39000.0, 42.0, 10799.9, 7538.5, 1842.4, 12.0879, 107.999 - 0.79, 39000.0, 46.0, 11712.2, 7857.8, 2143.1, 13.3818, 117.12200000000001 - 0.79, 39000.0, 48.0, 12157.8, 8007.0, 2302.2, 14.0174, 121.57799999999999 - 0.79, 39000.0, 50.0, 12601.3, 8153.9, 2461.0, 14.6254, 126.01299999999999 - 0.79, 41000.0, 21.0, 5086.2, 4884.2, 417.1, 8.114, 50.862 - 0.79, 41000.0, 22.0, 5334.1, 5010.8, 463.4, 6.7051, 53.34100000000001 - 0.79, 41000.0, 24.0, 5806.8, 5241.1, 566.2, 3.9985, 58.068000000000005 - 0.79, 41000.0, 26.0, 6256.7, 5448.5, 672.9, 4.8879, 62.567 - 0.79, 41000.0, 30.0, 7203.5, 5856.5, 909.4, 6.6888, 72.035 - 0.79, 41000.0, 34.0, 8096.2, 6210.4, 1158.0, 8.2594, 80.962 - 0.79, 41000.0, 38.0, 8961.4, 6536.8, 1417.5, 10.2694, 89.614 - 0.79, 41000.0, 42.0, 9810.0, 6846.6, 1679.3, 11.621, 98.10000000000001 - 0.79, 41000.0, 46.0, 10639.2, 7136.9, 1952.5, 12.8649, 106.39200000000001 - 0.79, 41000.0, 48.0, 11044.2, 7272.6, 2096.9, 13.4762, 110.44200000000001 - 0.79, 41000.0, 50.0, 11447.3, 7406.3, 2241.1, 14.0615, 114.473 - 0.8, 20000.0, 21.0, 13631.6, 13101.2, 1071.7, 7.2066, 136.316 - 0.8, 20000.0, 22.0, 14277.9, 13429.2, 1206.9, 7.9564, 142.779 - 0.8, 20000.0, 24.0, 15511.1, 14025.9, 1505.6, 9.4413, 155.11100000000002 - 0.8, 20000.0, 26.0, 16688.8, 14567.1, 1810.3, 11.3981, 166.888 - 0.8, 20000.0, 30.0, 19165.5, 15629.4, 2495.5, 14.1535, 191.655 - 0.8, 20000.0, 34.0, 21509.9, 16559.4, 3213.1, 16.5599, 215.09900000000002 - 0.8, 20000.0, 38.0, 23783.7, 17418.7, 3966.3, 18.6886, 237.83700000000002 - 0.8, 20000.0, 42.0, 26016.0, 18236.5, 4721.8, 20.5452, 260.16 - 0.8, 20000.0, 46.0, 28194.2, 19000.4, 5512.1, 35.7201, 281.942 - 0.8, 20000.0, 48.0, 29257.3, 19356.5, 5932.0, 49.6781, 292.573 - 0.8, 20000.0, 50.0, 30313.1, 19704.9, 6356.8, 59.9573, 303.131 - 0.8, 25000.0, 21.0, 11000.5, 10572.8, 858.4, 5.7369, 110.005 - 0.8, 25000.0, 22.0, 11522.8, 10838.4, 964.5, 6.4424, 115.228 - 0.8, 25000.0, 24.0, 12518.5, 11320.9, 1199.4, 7.8407, 125.185 - 0.8, 25000.0, 26.0, 13468.9, 11757.9, 1438.7, 9.0737, 134.689 - 0.8, 25000.0, 30.0, 15468.6, 12617.0, 1976.9, 12.1112, 154.686 - 0.8, 25000.0, 34.0, 17361.2, 13369.0, 2541.0, 14.3696, 173.61200000000002 - 0.8, 25000.0, 38.0, 19196.7, 14063.9, 3132.5, 16.3657, 191.967 - 0.8, 25000.0, 42.0, 20998.4, 14725.0, 3725.7, 18.1043, 209.984 - 0.8, 25000.0, 46.0, 22756.7, 15342.6, 4346.4, 19.7156, 227.567 - 0.8, 25000.0, 48.0, 23614.9, 15630.5, 4675.4, 22.8123, 236.14900000000003 - 0.8, 25000.0, 50.0, 24467.2, 15912.5, 5007.9, 31.4463, 244.67200000000003 - 0.8, 30000.0, 21.0, 8794.9, 8453.1, 684.4, 4.8251, 87.949 - 0.8, 30000.0, 22.0, 9212.8, 8666.0, 766.2, 4.9546, 92.128 - 0.8, 30000.0, 24.0, 10009.9, 9052.9, 949.1, 6.2683, 100.099 - 0.8, 30000.0, 26.0, 10770.5, 9403.4, 1135.9, 7.4268, 107.705 - 0.8, 30000.0, 30.0, 12370.4, 10092.0, 1554.2, 9.6026, 123.704 - 0.8, 30000.0, 34.0, 13884.6, 10694.7, 1993.0, 12.2194, 138.846 - 0.8, 30000.0, 38.0, 15352.8, 11251.5, 2452.3, 14.0807, 153.528 - 0.8, 30000.0, 42.0, 16793.7, 11781.1, 2913.8, 15.7013, 167.937 - 0.8, 30000.0, 46.0, 18200.3, 12276.3, 3395.6, 17.2013, 182.003 - 0.8, 30000.0, 48.0, 18886.8, 12507.0, 3651.1, 17.9402, 188.868 - 0.8, 30000.0, 50.0, 19569.5, 12734.0, 3908.4, 18.6521, 195.695 - 0.8, 35000.0, 21.0, 6959.9, 6689.4, 543.4, 7.8502, 69.599 - 0.8, 35000.0, 22.0, 7291.5, 6858.8, 606.0, 6.339, 72.915 - 0.8, 35000.0, 24.0, 7923.7, 7166.4, 746.6, 4.7559, 79.237 - 0.8, 35000.0, 26.0, 8526.5, 7444.7, 890.7, 5.8442, 85.265 - 0.8, 35000.0, 30.0, 9794.9, 7991.8, 1212.3, 7.8493, 97.949 - 0.8, 35000.0, 34.0, 10994.6, 8470.3, 1549.7, 9.9967, 109.94600000000001 - 0.8, 35000.0, 38.0, 12158.1, 8912.6, 1902.7, 11.8951, 121.581 - 0.8, 35000.0, 42.0, 13299.6, 9332.9, 2257.9, 13.4031, 132.996 - 0.8, 35000.0, 46.0, 14413.9, 9725.9, 2628.2, 14.7963, 144.139 - 0.8, 35000.0, 48.0, 14958.1, 9909.5, 2824.3, 15.483, 149.58100000000002 - 0.8, 35000.0, 50.0, 15499.3, 10090.1, 3020.9, 16.1418, 154.993 - 0.8, 37000.0, 21.0, 6319.9, 6074.2, 497.4, 8.3849, 63.199 - 0.8, 37000.0, 22.0, 6621.5, 6228.4, 553.7, 6.9012, 66.215 - 0.8, 37000.0, 24.0, 7196.4, 6508.4, 680.6, 4.3469, 71.964 - 0.8, 37000.0, 26.0, 7744.3, 6761.5, 810.7, 5.4024, 77.443 - 0.8, 37000.0, 30.0, 8897.5, 7259.4, 1100.8, 7.3437, 88.97500000000001 - 0.8, 37000.0, 34.0, 9988.0, 7694.8, 1405.5, 9.0829, 99.88 - 0.8, 37000.0, 38.0, 11045.4, 8096.9, 1723.9, 11.2241, 110.454 - 0.8, 37000.0, 42.0, 12082.7, 8479.1, 2044.4, 12.6821, 120.82700000000001 - 0.8, 37000.0, 46.0, 13095.6, 8836.7, 2378.8, 14.0299, 130.95600000000002 - 0.8, 37000.0, 48.0, 13590.1, 9003.6, 2555.9, 14.6924, 135.901 - 0.8, 37000.0, 50.0, 14082.1, 9167.9, 2733.1, 15.3273, 140.821 - 0.8, 39000.0, 21.0, 5736.6, 5513.4, 458.1, 8.1251, 57.36600000000001 - 0.8, 39000.0, 22.0, 6011.0, 5653.8, 509.0, 6.6908, 60.11 - 0.8, 39000.0, 24.0, 6533.9, 5908.8, 624.2, 4.1644, 65.339 - 0.8, 39000.0, 26.0, 7032.1, 6139.1, 742.6, 5.1849, 70.32100000000001 - 0.8, 39000.0, 30.0, 8080.3, 6592.0, 1005.9, 7.0545, 80.803 - 0.8, 39000.0, 34.0, 9071.6, 6988.0, 1282.5, 8.7133, 90.71600000000001 - 0.8, 39000.0, 38.0, 10032.7, 7353.7, 1571.6, 10.789, 100.32700000000001 - 0.8, 39000.0, 42.0, 10975.1, 7701.0, 1862.9, 12.1943, 109.751 - 0.8, 39000.0, 46.0, 11895.7, 8026.0, 2166.6, 13.4902, 118.95700000000001 - 0.8, 39000.0, 48.0, 12345.1, 8177.9, 2327.3, 14.1257, 123.45100000000001 - 0.8, 39000.0, 50.0, 12792.3, 8327.3, 2488.0, 14.7358, 127.923 - 0.8, 41000.0, 21.0, 5206.8, 5004.0, 422.5, 7.8759, 52.068000000000005 - 0.8, 41000.0, 22.0, 5456.4, 5131.9, 468.7, 6.4921, 54.564 - 0.8, 41000.0, 24.0, 5932.1, 5364.1, 573.0, 3.9876, 59.321000000000005 - 0.8, 41000.0, 26.0, 6385.0, 5573.6, 680.6, 4.9727, 63.85 - 0.8, 41000.0, 30.0, 7338.1, 5985.7, 919.7, 6.7752, 73.381 - 0.8, 41000.0, 34.0, 8239.2, 6346.0, 1170.8, 8.3569, 82.39200000000001 - 0.8, 41000.0, 38.0, 9112.8, 6678.6, 1433.3, 10.3696, 91.128 - 0.8, 41000.0, 42.0, 9969.4, 6994.3, 1697.9, 11.7243, 99.694 - 0.8, 41000.0, 46.0, 10805.8, 7289.8, 1973.9, 12.9692, 108.05799999999999 - 0.8, 41000.0, 48.0, 11214.3, 7427.8, 2119.8, 13.581, 112.143 - 0.8, 41000.0, 50.0, 11620.8, 7563.8, 2265.5, 14.1666, 116.208 - 0.8, 43000.0, 21.0, 4725.6, 4541.3, 390.2, 7.6384, 47.25600000000001 - 0.8, 43000.0, 22.0, 4952.6, 4657.7, 432.1, 6.3043, 49.526 - 0.8, 43000.0, 24.0, 5385.5, 4869.4, 526.6, 3.8166, 53.855000000000004 - 0.8, 43000.0, 26.0, 5797.4, 5060.1, 624.5, 4.7702, 57.974 - 0.8, 43000.0, 30.0, 6664.0, 5435.0, 841.4, 6.5063, 66.64 - 0.8, 43000.0, 34.0, 7483.3, 5762.9, 1069.3, 8.0181, 74.833 - 0.8, 43000.0, 38.0, 8277.5, 6065.4, 1307.7, 9.9658, 82.775 - 0.8, 43000.0, 42.0, 9055.9, 6352.3, 1548.6, 11.2718, 90.559 - 0.8, 43000.0, 46.0, 9816.3, 6621.1, 1799.0, 12.4684, 98.163 - 0.8, 43000.0, 48.0, 10187.6, 6746.6, 1931.5, 13.0575, 101.876 - 0.8, 43000.0, 50.0, 10556.9, 6870.2, 2063.5, 13.6188, 105.569 - 0.85, 20000.0, 21.0, 15269.7, 14726.9, 1148.4, 7.7963, 152.697 - 0.85, 20000.0, 22.0, 15940.5, 15071.8, 1286.4, 8.5229, 159.405 - 0.85, 20000.0, 24.0, 17216.3, 15696.2, 1605.0, 10.037, 172.16299999999998 - 0.85, 20000.0, 26.0, 18437.2, 16265.7, 1923.0, 12.0458, 184.372 - 0.85, 20000.0, 30.0, 21018.2, 17399.0, 2650.6, 14.837, 210.18200000000002 - 0.85, 20000.0, 34.0, 23493.4, 18426.4, 3408.9, 17.2645, 234.93400000000003 - 0.85, 20000.0, 38.0, 25884.8, 19370.2, 4206.9, 19.4142, 258.848 - 0.85, 20000.0, 42.0, 28229.3, 20267.0, 5007.6, 23.7977, 282.293 - 0.85, 20000.0, 46.0, 30511.4, 21101.3, 5843.9, 46.826, 305.11400000000003 - 0.85, 20000.0, 48.0, 31623.3, 21489.2, 6287.4, 58.5793, 316.233 - 0.85, 20000.0, 50.0, 32726.4, 21868.7, 6737.1, 67.2902, 327.264 - 0.85, 25000.0, 21.0, 12322.9, 11885.2, 918.3, 6.2921, 123.229 - 0.85, 25000.0, 22.0, 12864.9, 12164.6, 1027.0, 6.9769, 128.649 - 0.85, 25000.0, 24.0, 13894.8, 12669.2, 1277.4, 8.3905, 138.948 - 0.85, 25000.0, 26.0, 14880.2, 13129.4, 1527.5, 9.6187, 148.80200000000002 - 0.85, 25000.0, 30.0, 16963.6, 14045.5, 2098.8, 12.7509, 169.636 - 0.85, 25000.0, 34.0, 18961.6, 14876.3, 2695.0, 15.0269, 189.61599999999999 - 0.85, 25000.0, 38.0, 20891.7, 15639.3, 3321.4, 17.0425, 208.917 - 0.85, 25000.0, 42.0, 22783.5, 16363.9, 3949.4, 18.7996, 227.835 - 0.85, 25000.0, 46.0, 24625.9, 17039.0, 4606.3, 21.7264, 246.25900000000001 - 0.85, 25000.0, 48.0, 25523.3, 17352.8, 4953.5, 29.2527, 255.233 - 0.85, 25000.0, 50.0, 26413.9, 17659.8, 5304.8, 41.448, 264.139 - 0.85, 30000.0, 21.0, 9852.7, 9503.0, 730.5, 4.817, 98.52700000000002 - 0.85, 30000.0, 22.0, 10286.3, 9726.8, 814.8, 5.4569, 102.863 - 0.85, 30000.0, 24.0, 11110.8, 10131.7, 1009.8, 6.7844, 111.10799999999999 - 0.85, 30000.0, 26.0, 11899.3, 10500.5, 1204.7, 7.9341, 118.993 - 0.85, 30000.0, 30.0, 13566.3, 11234.9, 1649.0, 10.6836, 135.66299999999998 - 0.85, 30000.0, 34.0, 15164.4, 11900.5, 2112.4, 12.8292, 151.644 - 0.85, 30000.0, 38.0, 16708.5, 12512.1, 2599.3, 14.7084, 167.085 - 0.85, 30000.0, 42.0, 18221.3, 13092.4, 3087.7, 16.346, 182.213 - 0.85, 30000.0, 46.0, 19695.1, 13633.6, 3597.6, 17.8596, 196.951 - 0.85, 30000.0, 48.0, 20413.3, 13885.5, 3867.4, 18.6028, 204.133 - 0.85, 30000.0, 50.0, 21126.4, 14132.3, 4139.7, 19.3169, 211.264 - 0.85, 35000.0, 21.0, 7797.5, 7520.8, 578.7, 6.6087, 77.97500000000001 - 0.85, 35000.0, 22.0, 8141.8, 7699.1, 643.4, 5.1541, 81.418 - 0.85, 35000.0, 24.0, 8795.7, 8020.9, 793.4, 5.2408, 87.95700000000001 - 0.85, 35000.0, 26.0, 9420.6, 8313.7, 943.8, 6.3186, 94.206 - 0.85, 35000.0, 30.0, 10741.8, 8897.0, 1284.8, 8.3419, 107.41799999999999 - 0.85, 35000.0, 34.0, 12008.4, 9425.6, 1641.7, 10.725, 120.084 - 0.85, 35000.0, 38.0, 13232.1, 9911.4, 2016.1, 12.4766, 132.321 - 0.85, 35000.0, 42.0, 14430.9, 10372.2, 2391.9, 13.999, 144.309 - 0.85, 35000.0, 46.0, 15598.6, 10802.0, 2783.9, 15.4058, 155.98600000000002 - 0.85, 35000.0, 48.0, 16167.5, 11002.0, 2990.7, 16.095, 161.675 - 0.85, 35000.0, 50.0, 16732.6, 11198.0, 3199.2, 16.7582, 167.326 - 0.85, 37000.0, 21.0, 7080.7, 6829.3, 529.2, 7.1696, 70.807 - 0.85, 37000.0, 22.0, 7393.9, 6991.7, 587.4, 5.7449, 73.939 - 0.85, 37000.0, 24.0, 7988.5, 7284.6, 722.8, 4.8169, 79.885 - 0.85, 37000.0, 26.0, 8556.5, 7551.0, 858.6, 5.8624, 85.565 - 0.85, 37000.0, 30.0, 9757.7, 8081.8, 1166.5, 7.8217, 97.57700000000001 - 0.85, 37000.0, 34.0, 10908.7, 8562.5, 1488.5, 10.0732, 109.087 - 0.85, 37000.0, 38.0, 12020.9, 9004.3, 1826.1, 11.7857, 120.209 - 0.85, 37000.0, 42.0, 13110.2, 9423.3, 2165.5, 13.2592, 131.102 - 0.85, 37000.0, 46.0, 14171.0, 9813.8, 2518.9, 14.6171, 141.71 - 0.85, 37000.0, 48.0, 14688.6, 9996.1, 2705.6, 15.2834, 146.886 - 0.85, 37000.0, 50.0, 15202.3, 10174.6, 2893.4, 15.9241, 152.023 - 0.85, 39000.0, 21.0, 6427.5, 6199.1, 487.0, 6.9546, 64.275 - 0.85, 39000.0, 22.0, 6712.2, 6346.7, 539.4, 5.589, 67.122 - 0.85, 39000.0, 24.0, 7253.1, 6613.6, 662.4, 4.6165, 72.531 - 0.85, 39000.0, 26.0, 7769.4, 6855.8, 785.8, 5.6258, 77.694 - 0.85, 39000.0, 30.0, 8861.3, 7338.7, 1065.5, 7.514, 88.613 - 0.85, 39000.0, 34.0, 9907.4, 7775.8, 1357.5, 9.6651, 99.074 - 0.85, 39000.0, 38.0, 10918.3, 8177.7, 1664.3, 11.3296, 109.18299999999999 - 0.85, 39000.0, 42.0, 11908.0, 8558.4, 1972.4, 12.7479, 119.08 - 0.85, 39000.0, 46.0, 12872.3, 8913.7, 2293.5, 14.056, 128.72299999999998 - 0.85, 39000.0, 48.0, 13342.3, 9079.2, 2463.0, 14.6952, 133.423 - 0.85, 39000.0, 50.0, 13809.4, 9241.8, 2633.5, 15.3107, 138.094 - 0.9, 35000.0, 21.0, 8689.9, 8405.4, 612.6, 5.4642, 86.899 - 0.9, 35000.0, 22.0, 9048.1, 8592.9, 681.7, 4.4604, 90.48100000000001 - 0.9, 35000.0, 24.0, 9727.3, 8930.8, 841.5, 5.7208, 97.273 - 0.9, 35000.0, 26.0, 10383.2, 9245.3, 999.3, 6.7969, 103.83200000000001 - 0.9, 35000.0, 30.0, 11785.1, 9888.5, 1365.6, 8.8636, 117.851 - 0.9, 35000.0, 34.0, 13126.8, 10471.6, 1745.1, 11.3302, 131.268 - 0.9, 35000.0, 38.0, 14418.8, 11005.1, 2142.8, 13.0965, 144.188 - 0.9, 35000.0, 42.0, 15682.3, 11509.9, 2543.0, 14.6396, 156.823 - 0.9, 35000.0, 46.0, 16909.5, 11978.5, 2959.3, 16.0593, 169.095 - 0.9, 35000.0, 48.0, 17506.0, 12195.7, 3179.8, 16.7568, 175.06 - 0.9, 35000.0, 50.0, 18098.7, 12409.1, 3401.9, 17.4262, 180.98700000000002 - 0.9, 37000.0, 21.0, 7891.3, 7632.9, 559.6, 6.0554, 78.913 - 0.9, 37000.0, 22.0, 8217.1, 7803.6, 621.9, 4.6273, 82.171 - 0.9, 37000.0, 24.0, 8834.9, 8111.3, 766.2, 5.2826, 88.349 - 0.9, 37000.0, 26.0, 9431.0, 8397.2, 908.7, 6.3254, 94.31 - 0.9, 37000.0, 30.0, 10705.5, 8982.6, 1239.4, 8.326, 107.055 - 0.9, 37000.0, 34.0, 11924.9, 9512.8, 1581.3, 10.6732, 119.249 - 0.9, 37000.0, 38.0, 13099.4, 9998.1, 1940.8, 12.3857, 130.994 - 0.9, 37000.0, 42.0, 14247.6, 10457.1, 2302.0, 13.878, 142.476 - 0.9, 37000.0, 46.0, 15363.1, 10883.5, 2678.2, 15.2518, 153.631 - 0.9, 37000.0, 48.0, 15905.5, 11081.3, 2876.5, 15.9229, 159.055 - 0.9, 37000.0, 50.0, 16443.8, 11275.0, 3076.2, 16.5691, 164.438 - 0.9, 39000.0, 21.0, 7163.6, 6928.7, 514.4, 5.8837, 71.63600000000001 - 0.9, 39000.0, 22.0, 7459.9, 7084.2, 570.9, 4.5067, 74.599 - 0.9, 39000.0, 24.0, 8021.6, 7364.1, 701.6, 5.0624, 80.21600000000001 - 0.9, 39000.0, 26.0, 8563.7, 7624.5, 831.4, 6.0727, 85.63700000000001 - 0.9, 39000.0, 30.0, 9722.3, 8156.9, 1131.6, 7.9996, 97.223 - 0.9, 39000.0, 34.0, 10830.8, 8639.2, 1442.2, 10.2576, 108.30799999999999 - 0.9, 39000.0, 38.0, 11898.0, 9080.3, 1768.2, 11.9058, 118.98 - 0.9, 39000.0, 42.0, 12941.4, 9497.6, 2096.6, 13.3448, 129.414 - 0.9, 39000.0, 46.0, 13955.2, 9885.2, 2438.2, 14.6669, 139.55200000000002 - 0.9, 39000.0, 48.0, 14447.9, 10064.9, 2618.2, 15.3126, 144.479 - 0.9, 39000.0, 50.0, 14937.5, 10241.3, 2799.5, 15.9332, 149.375 diff --git a/aviary/models/engines/turbofan_gasp_bwb.csv b/aviary/models/engines/turbofan_gasp_bwb.csv new file mode 100644 index 0000000000..a1b7fb83f8 --- /dev/null +++ b/aviary/models/engines/turbofan_gasp_bwb.csv @@ -0,0 +1,11181 @@ +# created 07/18/25 at 16:35 by xjiang +# GASP-derived engine deck converted from MAPS.eng +# t4max: 100.0 +# t4cruise: 87.65 +# t4climb: 100.0 +# sls_airflow: 1087.97 +# sfn_idle: 1.307 + +Mach Number (input), Altitude (ft, input), Throttle (input), Thrust (lbf, output), Fuel Flow (lb/h, output) + 0.0, 0.0, 0.0, 710.9849, 710.985 + 0.0, 0.0, 0.05, 1207.844, 446.163 + 0.0, 0.0, 0.07, 1691.356, 524.093 + 0.0, 0.0, 0.09, 2174.855, 603.633 + 0.0, 0.0, 0.11, 2658.342, 684.762 + 0.0, 0.0, 0.13, 3141.817, 767.462 + 0.0, 0.0, 0.15, 3625.281, 851.712 + 0.0, 0.0, 0.17, 4108.736, 937.495 + 0.0, 0.0, 0.19, 4592.181, 1024.79 + 0.0, 0.0, 0.21, 5075.617, 1113.58 + 0.0, 0.0, 0.23, 5559.046, 1203.84 + 0.0, 0.0, 0.25, 6042.469, 1295.56 + 0.0, 0.0, 0.27, 6525.885, 1388.72 + 0.0, 0.0, 0.29, 7009.296, 1483.29 + 0.0, 0.0, 0.31, 7492.703, 1579.26 + 0.0, 0.0, 0.33, 7976.106, 1676.61 + 0.0, 0.0, 0.35, 8459.506, 1775.31 + 0.0, 0.0, 0.37, 8942.905, 1875.36 + 0.0, 0.0, 0.39, 9426.302, 1976.73 + 0.0, 0.0, 0.41, 9909.7, 2079.33 + 0.0, 0.0, 0.43, 10393.1, 2183.17 + 0.0, 0.0, 0.45, 10876.5, 2288.31 + 0.0, 0.0, 0.47, 11359.9, 2394.78 + 0.0, 0.0, 0.49, 11843.3, 2502.59 + 0.0, 0.0, 0.51, 12326.7, 2611.5 + 0.0, 0.0, 0.53, 12810.1, 2721.59 + 0.0, 0.0, 0.55, 13293.5, 2833.22 + 0.0, 0.0, 0.57, 13776.9, 2946.55 + 0.0, 0.0, 0.59, 14260.3, 3061.7 + 0.0, 0.0, 0.61, 14743.68, 3179.12 + 0.0, 0.0, 0.63, 15227.05, 3298.85 + 0.0, 0.0, 0.65, 15710.44, 3420.58 + 0.0, 0.0, 0.67, 16193.84, 3544.28 + 0.0, 0.0, 0.69, 16677.27, 3669.94 + 0.0, 0.0, 0.71, 17160.8, 3797.55 + 0.0, 0.0, 0.73, 17644.43, 3927.08 + 0.0, 0.0, 0.75, 18128.06, 4058.51 + 0.0, 0.0, 0.77, 18611.67, 4191.8 + 0.0, 0.0, 0.79, 19095.24, 4326.94 + 0.0, 0.0, 0.81, 19578.64, 4463.75 + 0.0, 0.0, 0.83, 20061.87, 4602.23 + 0.0, 0.0, 0.85, 20545.06, 4742.6 + 0.0, 0.0, 0.87, 21028.23, 4884.93 + 0.0, 0.0, 0.89, 21511.4, 5029.26 + 0.0, 0.0, 0.91, 21994.61, 5175.66 + 0.0, 0.0, 0.93, 22477.86, 5324.18 + 0.0, 0.0, 0.95, 22961.19, 5474.88 + 0.0, 0.0, 0.97, 23444.62, 5627.8 + 0.0, 0.0, 0.99, 23928.17, 5783.02 + 0.0, 2000.0, 0.0, 665.6779, 665.678 + 0.0, 2000.0, 0.05, 1156.3, 422.369 + 0.0, 2000.0, 0.07, 1618.82, 496.778 + 0.0, 2000.0, 0.09, 2081.34, 572.687 + 0.0, 2000.0, 0.11, 2543.86, 650.083 + 0.0, 2000.0, 0.13, 3006.38, 728.952 + 0.0, 2000.0, 0.15, 3468.9, 809.281 + 0.0, 2000.0, 0.17, 3931.42, 891.056 + 0.0, 2000.0, 0.19, 4393.94, 974.263 + 0.0, 2000.0, 0.21, 4856.46, 1058.89 + 0.0, 2000.0, 0.23, 5318.98, 1144.92 + 0.0, 2000.0, 0.25, 5781.5, 1232.34 + 0.0, 2000.0, 0.27, 6244.02, 1321.14 + 0.0, 2000.0, 0.29, 6706.54, 1411.31 + 0.0, 2000.0, 0.31, 7169.06, 1502.83 + 0.0, 2000.0, 0.33, 7631.58, 1595.68 + 0.0, 2000.0, 0.35, 8094.1, 1689.86 + 0.0, 2000.0, 0.37, 8556.62, 1785.34 + 0.0, 2000.0, 0.39, 9019.14, 1882.13 + 0.0, 2000.0, 0.41, 9481.657, 1980.14 + 0.0, 2000.0, 0.43, 9944.171, 2079.39 + 0.0, 2000.0, 0.45, 10406.69, 2179.92 + 0.0, 2000.0, 0.47, 10869.21, 2281.77 + 0.0, 2000.0, 0.49, 11331.73, 2384.92 + 0.0, 2000.0, 0.51, 11794.28, 2489.12 + 0.0, 2000.0, 0.53, 12256.84, 2594.42 + 0.0, 2000.0, 0.55, 12719.41, 2701.29 + 0.0, 2000.0, 0.57, 13181.97, 2809.88 + 0.0, 2000.0, 0.59, 13644.53, 2920.33 + 0.0, 2000.0, 0.61, 14107.06, 3033.25 + 0.0, 2000.0, 0.63, 14569.57, 3148.69 + 0.0, 2000.0, 0.65, 15032.08, 3266.12 + 0.0, 2000.0, 0.67, 15494.57, 3385.49 + 0.0, 2000.0, 0.69, 15957.06, 3506.71 + 0.0, 2000.0, 0.71, 16419.54, 3629.56 + 0.0, 2000.0, 0.73, 16882.01, 3754.0 + 0.0, 2000.0, 0.75, 17344.49, 3880.23 + 0.0, 2000.0, 0.77, 17806.97, 4008.26 + 0.0, 2000.0, 0.79, 18269.45, 4138.1 + 0.0, 2000.0, 0.81, 18731.96, 4269.65 + 0.0, 2000.0, 0.83, 19194.5, 4402.97 + 0.0, 2000.0, 0.85, 19657.04, 4538.23 + 0.0, 2000.0, 0.87, 20119.58, 4675.49 + 0.0, 2000.0, 0.89, 20582.13, 4814.83 + 0.0, 2000.0, 0.91, 21044.67, 4956.31 + 0.0, 2000.0, 0.93, 21507.21, 5100.0 + 0.0, 2000.0, 0.95, 21969.74, 5245.97 + 0.0, 2000.0, 0.97, 22432.25, 5394.28 + 0.0, 2000.0, 0.99, 22894.76, 5545.01 + 0.0, 5000.0, 0.0, 602.0369, 602.037 + 0.0, 5000.0, 0.05, 1079.606, 390.937 + 0.0, 5000.0, 0.07, 1511.114, 459.611 + 0.0, 5000.0, 0.09, 1942.635, 529.715 + 0.0, 5000.0, 0.11, 2374.168, 601.238 + 0.0, 5000.0, 0.13, 2805.713, 674.166 + 0.0, 5000.0, 0.15, 3237.269, 748.487 + 0.0, 5000.0, 0.17, 3668.834, 824.189 + 0.0, 5000.0, 0.19, 4100.409, 901.257 + 0.0, 5000.0, 0.21, 4531.993, 979.68 + 0.0, 5000.0, 0.23, 4963.584, 1059.44 + 0.0, 5000.0, 0.25, 5395.181, 1140.54 + 0.0, 5000.0, 0.27, 5826.785, 1222.95 + 0.0, 5000.0, 0.29, 6258.394, 1306.66 + 0.0, 5000.0, 0.31, 6690.007, 1391.66 + 0.0, 5000.0, 0.33, 7121.624, 1477.94 + 0.0, 5000.0, 0.35, 7553.244, 1565.49 + 0.0, 5000.0, 0.37, 7984.865, 1654.28 + 0.0, 5000.0, 0.39, 8416.488, 1744.32 + 0.0, 5000.0, 0.41, 8848.11, 1835.48 + 0.0, 5000.0, 0.43, 9279.73, 1927.77 + 0.0, 5000.0, 0.45, 9711.35, 2021.34 + 0.0, 5000.0, 0.47, 10142.97, 2116.22 + 0.0, 5000.0, 0.49, 10574.59, 2212.46 + 0.0, 5000.0, 0.51, 11006.21, 2309.94 + 0.0, 5000.0, 0.53, 11437.83, 2408.75 + 0.0, 5000.0, 0.55, 11869.46, 2509.12 + 0.0, 5000.0, 0.57, 12301.08, 2611.19 + 0.0, 5000.0, 0.59, 12732.69, 2715.06 + 0.0, 5000.0, 0.61, 13164.3, 2821.17 + 0.0, 5000.0, 0.63, 13595.9, 2929.55 + 0.0, 5000.0, 0.65, 14027.49, 3039.82 + 0.0, 5000.0, 0.67, 14459.09, 3151.92 + 0.0, 5000.0, 0.69, 14890.7, 3265.81 + 0.0, 5000.0, 0.71, 15322.32, 3381.28 + 0.0, 5000.0, 0.73, 15753.95, 3498.33 + 0.0, 5000.0, 0.75, 16185.59, 3617.1 + 0.0, 5000.0, 0.77, 16617.24, 3737.62 + 0.0, 5000.0, 0.79, 17048.88, 3859.9 + 0.0, 5000.0, 0.81, 17480.51, 3983.78 + 0.0, 5000.0, 0.83, 17912.14, 4109.32 + 0.0, 5000.0, 0.85, 18343.76, 4236.79 + 0.0, 5000.0, 0.87, 18775.38, 4366.3 + 0.0, 5000.0, 0.89, 19206.99, 4497.95 + 0.0, 5000.0, 0.91, 19638.6, 4631.82 + 0.0, 5000.0, 0.93, 20070.21, 4768.04 + 0.0, 5000.0, 0.95, 20501.81, 4906.68 + 0.0, 5000.0, 0.97, 20933.41, 5047.86 + 0.0, 5000.0, 0.99, 21365.0, 5191.67 + 0.0, 10000.0, 0.0, 506.7648, 506.765 + 0.0, 10000.0, 0.05, 946.4875, 339.775 + 0.0, 10000.0, 0.07, 1325.672, 399.534 + 0.0, 10000.0, 0.09, 1704.83, 460.481 + 0.0, 10000.0, 0.11, 2083.964, 522.615 + 0.0, 10000.0, 0.13, 2463.074, 585.93 + 0.0, 10000.0, 0.15, 2842.163, 650.425 + 0.0, 10000.0, 0.17, 3221.231, 716.096 + 0.0, 10000.0, 0.19, 3600.281, 782.939 + 0.0, 10000.0, 0.21, 3979.315, 850.953 + 0.0, 10000.0, 0.23, 4358.333, 920.132 + 0.0, 10000.0, 0.25, 4737.338, 990.475 + 0.0, 10000.0, 0.27, 5116.33, 1061.98 + 0.0, 10000.0, 0.29, 5495.312, 1134.64 + 0.0, 10000.0, 0.31, 5874.286, 1208.45 + 0.0, 10000.0, 0.33, 6253.252, 1283.41 + 0.0, 10000.0, 0.35, 6632.213, 1359.53 + 0.0, 10000.0, 0.37, 7011.169, 1436.78 + 0.0, 10000.0, 0.39, 7390.123, 1515.18 + 0.0, 10000.0, 0.41, 7769.077, 1594.57 + 0.0, 10000.0, 0.43, 8148.031, 1675.0 + 0.0, 10000.0, 0.45, 8526.988, 1756.66 + 0.0, 10000.0, 0.47, 8905.948, 1839.61 + 0.0, 10000.0, 0.49, 9284.914, 1923.92 + 0.0, 10000.0, 0.51, 9663.896, 2009.66 + 0.0, 10000.0, 0.53, 10042.89, 2096.9 + 0.0, 10000.0, 0.55, 10421.89, 2185.67 + 0.0, 10000.0, 0.57, 10800.9, 2276.01 + 0.0, 10000.0, 0.59, 11179.9, 2367.99 + 0.0, 10000.0, 0.61, 11558.89, 2461.8 + 0.0, 10000.0, 0.63, 11937.88, 2557.48 + 0.0, 10000.0, 0.65, 12316.86, 2654.82 + 0.0, 10000.0, 0.67, 12695.83, 2753.8 + 0.0, 10000.0, 0.69, 13074.81, 2854.4 + 0.0, 10000.0, 0.71, 13453.79, 2956.44 + 0.0, 10000.0, 0.73, 13832.76, 3059.92 + 0.0, 10000.0, 0.75, 14211.74, 3165.05 + 0.0, 10000.0, 0.77, 14590.72, 3271.88 + 0.0, 10000.0, 0.79, 14969.7, 3380.45 + 0.0, 10000.0, 0.81, 15348.71, 3490.92 + 0.0, 10000.0, 0.83, 15727.74, 3603.32 + 0.0, 10000.0, 0.85, 16106.76, 3717.52 + 0.0, 10000.0, 0.87, 16485.78, 3833.53 + 0.0, 10000.0, 0.89, 16864.8, 3951.33 + 0.0, 10000.0, 0.91, 17243.8, 4070.92 + 0.0, 10000.0, 0.93, 17622.78, 4192.28 + 0.0, 10000.0, 0.95, 18001.74, 4315.42 + 0.0, 10000.0, 0.97, 18380.67, 4440.33 + 0.0, 10000.0, 0.99, 18759.57, 4567.01 + 0.0, 15000.0, 0.0, 423.8486, 423.849 + 0.0, 15000.0, 0.05, 741.2, 418.4 + 0.0, 15000.0, 0.07, 1038.436, 453.699 + 0.0, 15000.0, 0.09, 1335.59, 492.572 + 0.0, 15000.0, 0.11, 1632.664, 534.661 + 0.0, 15000.0, 0.13, 1929.656, 579.604 + 0.0, 15000.0, 0.15, 2226.568, 627.043 + 0.0, 15000.0, 0.17, 2523.4, 676.618 + 0.0, 15000.0, 0.19, 2820.153, 727.97 + 0.0, 15000.0, 0.21, 3116.827, 780.739 + 0.0, 15000.0, 0.23, 3413.423, 834.566 + 0.0, 15000.0, 0.25, 3709.941, 889.091 + 0.0, 15000.0, 0.27, 4006.382, 943.955 + 0.0, 15000.0, 0.29, 4302.747, 998.799 + 0.0, 15000.0, 0.31, 4598.973, 1051.09 + 0.0, 15000.0, 0.33, 4895.077, 1101.01 + 0.0, 15000.0, 0.35, 5191.15, 1151.4 + 0.0, 15000.0, 0.37, 5487.223, 1202.96 + 0.0, 15000.0, 0.39, 5783.327, 1256.38 + 0.0, 15000.0, 0.41, 6079.418, 1315.32 + 0.0, 15000.0, 0.43, 6375.543, 1379.77 + 0.0, 15000.0, 0.45, 6671.844, 1445.98 + 0.0, 15000.0, 0.47, 6968.387, 1513.21 + 0.0, 15000.0, 0.49, 7265.238, 1580.69 + 0.0, 15000.0, 0.51, 7562.479, 1644.15 + 0.0, 15000.0, 0.53, 7860.172, 1703.68 + 0.0, 15000.0, 0.55, 8158.362, 1763.79 + 0.0, 15000.0, 0.57, 8457.109, 1825.44 + 0.0, 15000.0, 0.59, 8756.47, 1889.59 + 0.0, 15000.0, 0.61, 9057.832, 1962.21 + 0.0, 15000.0, 0.63, 9360.933, 2043.06 + 0.0, 15000.0, 0.65, 9663.862, 2125.65 + 0.0, 15000.0, 0.67, 9966.035, 2208.51 + 0.0, 15000.0, 0.69, 10266.87, 2290.18 + 0.0, 15000.0, 0.71, 10563.11, 2362.34 + 0.0, 15000.0, 0.73, 10854.83, 2425.18 + 0.0, 15000.0, 0.75, 11145.39, 2487.4 + 0.0, 15000.0, 0.77, 11435.51, 2550.83 + 0.0, 15000.0, 0.79, 11725.89, 2617.33 + 0.0, 15000.0, 0.81, 12019.34, 2694.71 + 0.0, 15000.0, 0.83, 12316.07, 2783.37 + 0.0, 15000.0, 0.85, 12613.65, 2876.29 + 0.0, 15000.0, 0.87, 12911.78, 2972.42 + 0.0, 15000.0, 0.89, 13210.13, 3070.69 + 0.0, 15000.0, 0.91, 13508.41, 3170.06 + 0.0, 15000.0, 0.93, 13806.29, 3269.47 + 0.0, 15000.0, 0.95, 14103.47, 3367.88 + 0.0, 15000.0, 0.97, 14399.64, 3464.23 + 0.0, 15000.0, 0.99, 14694.48, 3557.47 + 0.0, 20000.0, 0.0, 352.0686, 352.069 + 0.0, 20000.0, 0.05, 607.3, 275.8 + 0.0, 20000.0, 0.07, 851.5355, 311.583 + 0.0, 20000.0, 0.09, 1095.769, 347.27 + 0.0, 20000.0, 0.11, 1339.995, 383.026 + 0.0, 20000.0, 0.13, 1584.209, 419.021 + 0.0, 20000.0, 0.15, 1828.407, 455.421 + 0.0, 20000.0, 0.17, 2072.584, 492.396 + 0.0, 20000.0, 0.19, 2316.735, 530.112 + 0.0, 20000.0, 0.21, 2560.856, 568.737 + 0.0, 20000.0, 0.23, 2804.942, 608.439 + 0.0, 20000.0, 0.25, 3048.989, 649.386 + 0.0, 20000.0, 0.27, 3292.99, 691.745 + 0.0, 20000.0, 0.29, 3536.943, 735.685 + 0.0, 20000.0, 0.31, 3780.878, 782.778 + 0.0, 20000.0, 0.33, 4024.78, 832.852 + 0.0, 20000.0, 0.35, 4268.594, 883.987 + 0.0, 20000.0, 0.37, 4512.298, 935.671 + 0.0, 20000.0, 0.39, 4755.87, 987.389 + 0.0, 20000.0, 0.41, 4999.192, 1036.74 + 0.0, 20000.0, 0.43, 5242.265, 1083.66 + 0.0, 20000.0, 0.45, 5485.212, 1130.46 + 0.0, 20000.0, 0.47, 5728.06, 1177.52 + 0.0, 20000.0, 0.49, 5970.833, 1225.25 + 0.0, 20000.0, 0.51, 6213.282, 1275.46 + 0.0, 20000.0, 0.53, 6455.499, 1328.19 + 0.0, 20000.0, 0.55, 6697.919, 1381.79 + 0.0, 20000.0, 0.57, 6940.7, 1435.99 + 0.0, 20000.0, 0.59, 7184.003, 1490.51 + 0.0, 20000.0, 0.61, 7428.729, 1543.17 + 0.0, 20000.0, 0.63, 7674.857, 1594.17 + 0.0, 20000.0, 0.65, 7921.444, 1646.06 + 0.0, 20000.0, 0.67, 8168.288, 1699.48 + 0.0, 20000.0, 0.69, 8415.19, 1755.08 + 0.0, 20000.0, 0.71, 8661.992, 1815.85 + 0.0, 20000.0, 0.73, 8908.481, 1881.87 + 0.0, 20000.0, 0.75, 9154.394, 1950.32 + 0.0, 20000.0, 0.77, 9399.509, 2020.72 + 0.0, 20000.0, 0.79, 9643.604, 2092.58 + 0.0, 20000.0, 0.81, 9884.821, 2165.01 + 0.0, 20000.0, 0.83, 10123.34, 2237.63 + 0.0, 20000.0, 0.85, 10361.36, 2310.54 + 0.0, 20000.0, 0.87, 10599.45, 2383.46 + 0.0, 20000.0, 0.89, 10838.2, 2456.09 + 0.0, 20000.0, 0.91, 11078.17, 2528.13 + 0.0, 20000.0, 0.93, 11319.94, 2599.3 + 0.0, 20000.0, 0.95, 11564.07, 2669.31 + 0.0, 20000.0, 0.97, 11811.14, 2737.85 + 0.0, 20000.0, 0.99, 12061.72, 2804.65 + 0.0, 25000.0, 0.0, 290.2769, 290.277 + 0.0, 25000.0, 0.05, 490.6, 210.9 + 0.0, 25000.0, 0.07, 678.0227, 281.925 + 0.0, 25000.0, 0.09, 867.0613, 337.889 + 0.0, 25000.0, 0.11, 1057.558, 380.832 + 0.0, 25000.0, 0.13, 1249.354, 412.796 + 0.0, 25000.0, 0.15, 1442.293, 435.825 + 0.0, 25000.0, 0.17, 1636.216, 451.959 + 0.0, 25000.0, 0.19, 1830.965, 463.241 + 0.0, 25000.0, 0.21, 2026.382, 471.712 + 0.0, 25000.0, 0.23, 2222.311, 479.414 + 0.0, 25000.0, 0.25, 2418.591, 488.39 + 0.0, 25000.0, 0.27, 2615.067, 500.681 + 0.0, 25000.0, 0.29, 2811.579, 518.329 + 0.0, 25000.0, 0.31, 3007.851, 552.369 + 0.0, 25000.0, 0.33, 3203.754, 602.663 + 0.0, 25000.0, 0.35, 3399.306, 657.9 + 0.0, 25000.0, 0.37, 3594.409, 715.761 + 0.0, 25000.0, 0.39, 3788.961, 773.927 + 0.0, 25000.0, 0.41, 3982.451, 825.836 + 0.0, 25000.0, 0.43, 4174.879, 870.2 + 0.0, 25000.0, 0.45, 4366.756, 911.0 + 0.0, 25000.0, 0.47, 4558.184, 947.976 + 0.0, 25000.0, 0.49, 4749.261, 980.868 + 0.0, 25000.0, 0.51, 4939.878, 1002.82 + 0.0, 25000.0, 0.53, 5130.184, 1015.17 + 0.0, 25000.0, 0.55, 5320.594, 1027.44 + 0.0, 25000.0, 0.57, 5511.31, 1042.59 + 0.0, 25000.0, 0.59, 5702.534, 1063.53 + 0.0, 25000.0, 0.61, 5894.961, 1104.51 + 0.0, 25000.0, 0.63, 6088.673, 1165.73 + 0.0, 25000.0, 0.65, 6283.144, 1233.34 + 0.0, 25000.0, 0.67, 6478.336, 1304.82 + 0.0, 25000.0, 0.69, 6674.215, 1377.6 + 0.0, 25000.0, 0.71, 6871.197, 1443.53 + 0.0, 25000.0, 0.73, 7069.137, 1501.43 + 0.0, 25000.0, 0.75, 7267.325, 1557.13 + 0.0, 25000.0, 0.77, 7465.505, 1610.81 + 0.0, 25000.0, 0.79, 7663.421, 1662.68 + 0.0, 25000.0, 0.81, 7860.64, 1712.78 + 0.0, 25000.0, 0.83, 8056.95, 1761.33 + 0.0, 25000.0, 0.85, 8252.356, 1808.76 + 0.0, 25000.0, 0.87, 8446.688, 1855.34 + 0.0, 25000.0, 0.89, 8639.776, 1901.33 + 0.0, 25000.0, 0.91, 8831.449, 1947.02 + 0.0, 25000.0, 0.93, 9021.537, 1992.67 + 0.0, 25000.0, 0.95, 9209.869, 2038.54 + 0.0, 25000.0, 0.97, 9396.275, 2084.92 + 0.0, 25000.0, 0.99, 9580.585, 2132.06 + 0.0, 30000.0, 0.0, 237.4081, 237.408 + 0.0, 30000.0, 0.05, 320.4, 156.0 + 0.0, 30000.0, 0.07, 454.4467, 167.957 + 0.0, 30000.0, 0.09, 586.778, 180.013 + 0.0, 30000.0, 0.11, 717.6213, 192.183 + 0.0, 30000.0, 0.13, 847.204, 204.484 + 0.0, 30000.0, 0.15, 975.7536, 216.932 + 0.0, 30000.0, 0.17, 1103.497, 229.543 + 0.0, 30000.0, 0.19, 1230.663, 242.333 + 0.0, 30000.0, 0.21, 1357.478, 255.318 + 0.0, 30000.0, 0.23, 1484.169, 268.515 + 0.0, 30000.0, 0.25, 1610.964, 281.939 + 0.0, 30000.0, 0.27, 1738.091, 295.606 + 0.0, 30000.0, 0.29, 1865.777, 309.534 + 0.0, 30000.0, 0.31, 1995.356, 323.277 + 0.0, 30000.0, 0.33, 2126.788, 336.964 + 0.0, 30000.0, 0.35, 2258.656, 351.294 + 0.0, 30000.0, 0.37, 2390.65, 366.505 + 0.0, 30000.0, 0.39, 2522.46, 382.838 + 0.0, 30000.0, 0.41, 2652.997, 402.503 + 0.0, 30000.0, 0.43, 2782.14, 425.262 + 0.0, 30000.0, 0.45, 2910.737, 448.425 + 0.0, 30000.0, 0.47, 3038.859, 471.276 + 0.0, 30000.0, 0.49, 3166.574, 493.099 + 0.0, 30000.0, 0.51, 3293.65, 510.473 + 0.0, 30000.0, 0.53, 3420.229, 523.337 + 0.0, 30000.0, 0.55, 3546.825, 534.988 + 0.0, 30000.0, 0.57, 3673.653, 546.018 + 0.0, 30000.0, 0.59, 3800.928, 557.022 + 0.0, 30000.0, 0.61, 3929.799, 569.521 + 0.0, 30000.0, 0.63, 4060.254, 583.883 + 0.0, 30000.0, 0.65, 4191.119, 599.325 + 0.0, 30000.0, 0.67, 4322.153, 615.991 + 0.0, 30000.0, 0.69, 4453.118, 634.025 + 0.0, 30000.0, 0.71, 4582.853, 655.533 + 0.0, 30000.0, 0.73, 4711.341, 680.183 + 0.0, 30000.0, 0.75, 4839.713, 705.206 + 0.0, 30000.0, 0.77, 4968.177, 729.796 + 0.0, 30000.0, 0.79, 5096.941, 753.144 + 0.0, 30000.0, 0.81, 5227.183, 769.818 + 0.0, 30000.0, 0.83, 5358.876, 780.134 + 0.0, 30000.0, 0.85, 5490.788, 790.15 + 0.0, 30000.0, 0.87, 5622.655, 801.302 + 0.0, 30000.0, 0.89, 5754.216, 815.026 + 0.0, 30000.0, 0.91, 5885.209, 832.755 + 0.0, 30000.0, 0.93, 6015.37, 855.927 + 0.0, 30000.0, 0.95, 6144.438, 885.975 + 0.0, 30000.0, 0.97, 6272.149, 924.335 + 0.0, 30000.0, 0.99, 6398.242, 972.443 + 0.0, 35000.0, 0.0, 192.4721, 192.472 + 0.0, 35000.0, 0.05, 333.5, 296.4 + 0.0, 35000.0, 0.07, 480.3002, 292.22 + 0.0, 35000.0, 0.09, 629.7493, 292.1 + 0.0, 35000.0, 0.11, 781.5683, 295.804 + 0.0, 35000.0, 0.13, 935.4782, 303.098 + 0.0, 35000.0, 0.15, 1091.2, 313.746 + 0.0, 35000.0, 0.17, 1248.455, 327.514 + 0.0, 35000.0, 0.19, 1406.963, 344.166 + 0.0, 35000.0, 0.21, 1566.446, 363.467 + 0.0, 35000.0, 0.23, 1726.625, 385.182 + 0.0, 35000.0, 0.25, 1887.22, 409.076 + 0.0, 35000.0, 0.27, 2047.953, 434.913 + 0.0, 35000.0, 0.29, 2208.544, 462.46 + 0.0, 35000.0, 0.31, 2368.429, 493.908 + 0.0, 35000.0, 0.33, 2527.396, 528.436 + 0.0, 35000.0, 0.35, 2685.594, 562.2 + 0.0, 35000.0, 0.37, 2842.881, 593.788 + 0.0, 35000.0, 0.39, 2999.119, 621.788 + 0.0, 35000.0, 0.41, 3154.026, 634.082 + 0.0, 35000.0, 0.43, 3307.497, 631.853 + 0.0, 35000.0, 0.45, 3459.6, 629.581 + 0.0, 35000.0, 0.47, 3610.263, 631.044 + 0.0, 35000.0, 0.49, 3759.414, 640.017 + 0.0, 35000.0, 0.51, 3905.531, 676.649 + 0.0, 35000.0, 0.53, 4048.893, 740.748 + 0.0, 35000.0, 0.55, 4191.581, 811.781 + 0.0, 35000.0, 0.57, 4334.228, 885.589 + 0.0, 35000.0, 0.59, 4477.464, 958.01 + 0.0, 35000.0, 0.61, 4624.512, 1016.4 + 0.0, 35000.0, 0.63, 4775.376, 1058.66 + 0.0, 35000.0, 0.65, 4926.838, 1093.21 + 0.0, 35000.0, 0.67, 5078.271, 1120.02 + 0.0, 35000.0, 0.69, 5229.051, 1139.03 + 0.0, 35000.0, 0.71, 5375.164, 1141.48 + 0.0, 35000.0, 0.73, 5516.806, 1129.43 + 0.0, 35000.0, 0.75, 5658.381, 1115.78 + 0.0, 35000.0, 0.77, 5800.907, 1104.71 + 0.0, 35000.0, 0.79, 5945.399, 1100.41 + 0.0, 35000.0, 0.81, 6096.872, 1123.48 + 0.0, 35000.0, 0.83, 6255.375, 1174.13 + 0.0, 35000.0, 0.85, 6415.987, 1232.12 + 0.0, 35000.0, 0.87, 6577.788, 1293.67 + 0.0, 35000.0, 0.89, 6739.855, 1355.0 + 0.0, 35000.0, 0.91, 6901.266, 1412.32 + 0.0, 35000.0, 0.93, 7061.101, 1461.83 + 0.0, 35000.0, 0.95, 7218.437, 1499.76 + 0.0, 35000.0, 0.97, 7372.354, 1522.3 + 0.0, 35000.0, 0.99, 7521.929, 1525.68 + 0.0, 40000.0, 0.0, 152.3229, 152.323 + 0.0, 40000.0, 0.05, 327.9, 175.7 + 0.0, 40000.0, 0.07, 444.307, 227.09 + 0.0, 40000.0, 0.09, 559.8792, 265.23 + 0.0, 40000.0, 0.11, 674.9522, 292.004 + 0.0, 40000.0, 0.13, 789.8616, 309.299 + 0.0, 40000.0, 0.15, 904.9429, 319.0 + 0.0, 40000.0, 0.17, 1020.532, 322.992 + 0.0, 40000.0, 0.19, 1136.963, 323.16 + 0.0, 40000.0, 0.21, 1254.573, 321.391 + 0.0, 40000.0, 0.23, 1373.698, 319.569 + 0.0, 40000.0, 0.25, 1494.671, 319.58 + 0.0, 40000.0, 0.27, 1617.83, 323.309 + 0.0, 40000.0, 0.29, 1743.51, 332.643 + 0.0, 40000.0, 0.31, 1875.464, 360.315 + 0.0, 40000.0, 0.33, 2013.199, 405.582 + 0.0, 40000.0, 0.35, 2151.975, 454.219 + 0.0, 40000.0, 0.37, 2290.471, 502.849 + 0.0, 40000.0, 0.39, 2427.366, 548.098 + 0.0, 40000.0, 0.41, 2557.134, 572.175 + 0.0, 40000.0, 0.43, 2679.471, 575.199 + 0.0, 40000.0, 0.45, 2799.3, 575.2 + 0.0, 40000.0, 0.47, 2917.337, 575.793 + 0.0, 40000.0, 0.49, 3034.298, 580.593 + 0.0, 40000.0, 0.51, 3150.672, 609.146 + 0.0, 40000.0, 0.53, 3267.231, 661.204 + 0.0, 40000.0, 0.55, 3385.031, 716.725 + 0.0, 40000.0, 0.57, 3504.902, 771.598 + 0.0, 40000.0, 0.59, 3627.67, 821.712 + 0.0, 40000.0, 0.61, 3759.055, 849.795 + 0.0, 40000.0, 0.63, 3898.699, 854.928 + 0.0, 40000.0, 0.65, 4040.169, 852.544 + 0.0, 40000.0, 0.67, 4181.92, 844.913 + 0.0, 40000.0, 0.69, 4322.41, 834.308 + 0.0, 40000.0, 0.71, 4456.19, 820.931 + 0.0, 40000.0, 0.73, 4582.664, 807.553 + 0.0, 40000.0, 0.75, 4706.088, 799.519 + 0.0, 40000.0, 0.77, 4826.811, 800.103 + 0.0, 40000.0, 0.79, 4945.185, 812.579 + 0.0, 40000.0, 0.81, 5059.533, 860.839 + 0.0, 40000.0, 0.83, 5170.698, 943.159 + 0.0, 40000.0, 0.85, 5282.037, 1032.2 + 0.0, 40000.0, 0.87, 5394.885, 1121.24 + 0.0, 40000.0, 0.89, 5510.574, 1203.56 + 0.0, 40000.0, 0.91, 5630.436, 1272.44 + 0.0, 40000.0, 0.93, 5755.805, 1321.15 + 0.0, 40000.0, 0.95, 5888.012, 1342.97 + 0.0, 40000.0, 0.97, 6028.392, 1331.19 + 0.0, 40000.0, 0.99, 6178.277, 1279.08 + 0.0, 43000.0, 0.0, 131.9447, 131.945 + 0.0, 43000.0, 0.05, 172.3, 261.2 + 0.0, 43000.0, 0.07, 363.6572, 326.802 + 0.0, 43000.0, 0.09, 529.2374, 379.844 + 0.0, 43000.0, 0.11, 672.3286, 421.34 + 0.0, 43000.0, 0.13, 796.2189, 452.305 + 0.0, 43000.0, 0.15, 904.1964, 473.754 + 0.0, 43000.0, 0.17, 999.5493, 486.701 + 0.0, 43000.0, 0.19, 1085.566, 492.161 + 0.0, 43000.0, 0.21, 1165.533, 491.148 + 0.0, 43000.0, 0.23, 1242.741, 484.678 + 0.0, 43000.0, 0.25, 1320.476, 473.764 + 0.0, 43000.0, 0.27, 1402.027, 459.422 + 0.0, 43000.0, 0.29, 1490.681, 442.666 + 0.0, 43000.0, 0.31, 1606.439, 417.527 + 0.0, 43000.0, 0.33, 1748.537, 386.712 + 0.0, 43000.0, 0.35, 1895.45, 361.606 + 0.0, 43000.0, 0.37, 2042.363, 346.611 + 0.0, 43000.0, 0.39, 2184.461, 346.126 + 0.0, 43000.0, 0.41, 2299.09, 397.396 + 0.0, 43000.0, 0.43, 2385.762, 496.859 + 0.0, 43000.0, 0.45, 2466.15, 600.15 + 0.0, 43000.0, 0.47, 2544.09, 695.745 + 0.0, 43000.0, 0.49, 2623.418, 772.12 + 0.0, 43000.0, 0.51, 2720.672, 768.255 + 0.0, 43000.0, 0.53, 2836.61, 684.626 + 0.0, 43000.0, 0.55, 2956.2, 583.206 + 0.0, 43000.0, 0.57, 3077.118, 476.473 + 0.0, 43000.0, 0.59, 3197.04, 376.901 + 0.0, 43000.0, 0.61, 3305.145, 329.76 + 0.0, 43000.0, 0.63, 3401.169, 339.575 + 0.0, 43000.0, 0.65, 3495.4, 370.131 + 0.0, 43000.0, 0.67, 3589.631, 418.006 + 0.0, 43000.0, 0.69, 3685.655, 479.775 + 0.0, 43000.0, 0.71, 3793.76, 555.683 + 0.0, 43000.0, 0.73, 3913.682, 641.419 + 0.0, 43000.0, 0.75, 4034.6, 728.113 + 0.0, 43000.0, 0.77, 4154.19, 810.562 + 0.0, 43000.0, 0.79, 4270.128, 883.566 + 0.0, 43000.0, 0.81, 4370.328, 921.127 + 0.0, 43000.0, 0.83, 4454.832, 923.086 + 0.0, 43000.0, 0.85, 4535.806, 915.119 + 0.0, 43000.0, 0.87, 4615.659, 902.105 + 0.0, 43000.0, 0.89, 4696.797, 888.926 + 0.0, 43000.0, 0.91, 4781.627, 880.463 + 0.0, 43000.0, 0.93, 4872.557, 881.596 + 0.0, 43000.0, 0.95, 4971.994, 897.206 + 0.0, 43000.0, 0.97, 5082.344, 932.175 + 0.0, 43000.0, 0.99, 5206.016, 991.382 + 0.0, 48000.0, 0.0, 103.8672, 103.867 + 0.0, 48000.0, 0.05, 187.5, 325.7 + 0.0, 48000.0, 0.07, 329.0812, 365.265 + 0.0, 48000.0, 0.09, 454.147, 394.115 + 0.0, 48000.0, 0.11, 564.5595, 413.341 + 0.0, 48000.0, 0.13, 662.1803, 424.033 + 0.0, 48000.0, 0.15, 748.8714, 427.282 + 0.0, 48000.0, 0.17, 826.4947, 424.179 + 0.0, 48000.0, 0.19, 896.9118, 415.815 + 0.0, 48000.0, 0.21, 961.9848, 403.279 + 0.0, 48000.0, 0.23, 1023.576, 387.664 + 0.0, 48000.0, 0.25, 1083.546, 370.059 + 0.0, 48000.0, 0.27, 1143.757, 351.555 + 0.0, 48000.0, 0.29, 1206.072, 333.243 + 0.0, 48000.0, 0.31, 1277.09, 313.703 + 0.0, 48000.0, 0.33, 1357.523, 294.635 + 0.0, 48000.0, 0.35, 1442.2, 280.856 + 0.0, 48000.0, 0.37, 1530.685, 274.676 + 0.0, 48000.0, 0.39, 1622.542, 278.401 + 0.0, 48000.0, 0.41, 1717.758, 315.585 + 0.0, 48000.0, 0.43, 1815.795, 383.384 + 0.0, 48000.0, 0.45, 1915.594, 452.563 + 0.0, 48000.0, 0.47, 2016.514, 515.13 + 0.0, 48000.0, 0.49, 2117.917, 563.093 + 0.0, 48000.0, 0.51, 2222.444, 550.528 + 0.0, 48000.0, 0.53, 2328.66, 478.639 + 0.0, 48000.0, 0.55, 2431.056, 395.756 + 0.0, 48000.0, 0.57, 2527.402, 312.28 + 0.0, 48000.0, 0.59, 2615.468, 238.609 + 0.0, 48000.0, 0.61, 2675.696, 218.593 + 0.0, 48000.0, 0.63, 2710.055, 254.521 + 0.0, 48000.0, 0.65, 2742.05, 307.125 + 0.0, 48000.0, 0.67, 2777.853, 370.585 + 0.0, 48000.0, 0.69, 2823.636, 439.081 + 0.0, 48000.0, 0.71, 2913.45, 495.241 + 0.0, 48000.0, 0.73, 3046.709, 536.045 + 0.0, 48000.0, 0.75, 3188.194, 572.831 + 0.0, 48000.0, 0.77, 3330.56, 605.384 + 0.0, 48000.0, 0.79, 3466.465, 633.486 + 0.0, 48000.0, 0.81, 3566.015, 651.592 + 0.0, 48000.0, 0.83, 3627.334, 660.778 + 0.0, 48000.0, 0.85, 3676.563, 668.738 + 0.0, 48000.0, 0.87, 3717.291, 677.837 + 0.0, 48000.0, 0.89, 3753.11, 690.443 + 0.0, 48000.0, 0.91, 3787.609, 708.921 + 0.0, 48000.0, 0.93, 3824.38, 735.639 + 0.0, 48000.0, 0.95, 3867.013, 772.963 + 0.0, 48000.0, 0.97, 3919.097, 823.258 + 0.0, 48000.0, 0.99, 3984.224, 888.892 + 0.05, 0.0, 0.0, 712.0519, 712.052 + 0.05, 0.0, 0.05, 1141.559, 513.531 + 0.05, 0.0, 0.07, 1597.674, 598.985 + 0.05, 0.0, 0.09, 2053.818, 685.55 + 0.05, 0.0, 0.11, 2509.989, 773.228 + 0.05, 0.0, 0.13, 2966.185, 862.021 + 0.05, 0.0, 0.15, 3422.403, 951.931 + 0.05, 0.0, 0.17, 3878.641, 1042.96 + 0.05, 0.0, 0.19, 4334.897, 1135.11 + 0.05, 0.0, 0.21, 4791.167, 1228.39 + 0.05, 0.0, 0.23, 5247.449, 1322.79 + 0.05, 0.0, 0.25, 5703.742, 1418.32 + 0.05, 0.0, 0.27, 6160.042, 1514.98 + 0.05, 0.0, 0.29, 6616.347, 1612.78 + 0.05, 0.0, 0.31, 7072.654, 1711.71 + 0.05, 0.0, 0.33, 7528.961, 1811.77 + 0.05, 0.0, 0.35, 7985.266, 1912.98 + 0.05, 0.0, 0.37, 8441.565, 2015.33 + 0.05, 0.0, 0.39, 8897.857, 2118.82 + 0.05, 0.0, 0.41, 9354.12, 2223.4 + 0.05, 0.0, 0.43, 9810.356, 2329.08 + 0.05, 0.0, 0.45, 10266.59, 2435.96 + 0.05, 0.0, 0.47, 10722.83, 2544.06 + 0.05, 0.0, 0.49, 11179.09, 2653.42 + 0.05, 0.0, 0.51, 11635.39, 2763.93 + 0.05, 0.0, 0.53, 12091.73, 2875.64 + 0.05, 0.0, 0.55, 12548.1, 2988.82 + 0.05, 0.0, 0.57, 13004.47, 3103.58 + 0.05, 0.0, 0.59, 13460.84, 3220.04 + 0.05, 0.0, 0.61, 13917.18, 3338.58 + 0.05, 0.0, 0.63, 14373.51, 3459.25 + 0.05, 0.0, 0.65, 14829.83, 3581.73 + 0.05, 0.0, 0.67, 15286.15, 3705.97 + 0.05, 0.0, 0.69, 15742.46, 3831.94 + 0.05, 0.0, 0.71, 16198.79, 3959.58 + 0.05, 0.0, 0.73, 16655.13, 4088.87 + 0.05, 0.0, 0.75, 17111.47, 4219.81 + 0.05, 0.0, 0.77, 17567.8, 4352.39 + 0.05, 0.0, 0.79, 18024.12, 4486.6 + 0.05, 0.0, 0.81, 18480.4, 4622.22 + 0.05, 0.0, 0.83, 18936.65, 4759.28 + 0.05, 0.0, 0.85, 19392.89, 4898.06 + 0.05, 0.0, 0.87, 19849.13, 5038.63 + 0.05, 0.0, 0.89, 20305.37, 5181.07 + 0.05, 0.0, 0.91, 20761.63, 5325.46 + 0.05, 0.0, 0.93, 21217.9, 5471.88 + 0.05, 0.0, 0.95, 21674.19, 5620.41 + 0.05, 0.0, 0.97, 22130.52, 5771.11 + 0.05, 0.0, 0.99, 22586.88, 5924.08 + 0.05, 2000.0, 0.0, 666.6769, 666.677 + 0.05, 2000.0, 0.05, 1091.659, 485.081 + 0.05, 2000.0, 0.07, 1528.786, 566.643 + 0.05, 2000.0, 0.09, 1965.888, 649.23 + 0.05, 2000.0, 0.11, 2402.967, 732.849 + 0.05, 2000.0, 0.13, 2840.024, 817.506 + 0.05, 2000.0, 0.15, 3277.061, 903.209 + 0.05, 2000.0, 0.17, 3714.081, 989.966 + 0.05, 2000.0, 0.19, 4151.084, 1077.78 + 0.05, 2000.0, 0.21, 4588.073, 1166.67 + 0.05, 2000.0, 0.23, 5025.049, 1256.62 + 0.05, 2000.0, 0.25, 5462.014, 1347.66 + 0.05, 2000.0, 0.27, 5898.97, 1439.79 + 0.05, 2000.0, 0.29, 6335.918, 1533.01 + 0.05, 2000.0, 0.31, 6772.861, 1627.34 + 0.05, 2000.0, 0.33, 7209.8, 1722.78 + 0.05, 2000.0, 0.35, 7646.736, 1819.33 + 0.05, 2000.0, 0.37, 8083.673, 1917.01 + 0.05, 2000.0, 0.39, 8520.61, 2015.82 + 0.05, 2000.0, 0.41, 8957.558, 2115.71 + 0.05, 2000.0, 0.43, 9394.517, 2216.69 + 0.05, 2000.0, 0.45, 9831.476, 2318.88 + 0.05, 2000.0, 0.47, 10268.44, 2422.29 + 0.05, 2000.0, 0.49, 10705.39, 2526.98 + 0.05, 2000.0, 0.51, 11142.34, 2632.82 + 0.05, 2000.0, 0.53, 11579.27, 2739.89 + 0.05, 2000.0, 0.55, 12016.21, 2848.44 + 0.05, 2000.0, 0.57, 12453.14, 2958.59 + 0.05, 2000.0, 0.59, 12890.07, 3070.45 + 0.05, 2000.0, 0.61, 13327.01, 3184.46 + 0.05, 2000.0, 0.63, 13763.97, 3300.66 + 0.05, 2000.0, 0.65, 14200.92, 3418.65 + 0.05, 2000.0, 0.67, 14637.88, 3538.35 + 0.05, 2000.0, 0.69, 15074.85, 3659.72 + 0.05, 2000.0, 0.71, 15511.82, 3782.58 + 0.05, 2000.0, 0.73, 15948.8, 3906.9 + 0.05, 2000.0, 0.75, 16385.77, 4032.79 + 0.05, 2000.0, 0.77, 16822.75, 4160.26 + 0.05, 2000.0, 0.79, 17259.73, 4289.29 + 0.05, 2000.0, 0.81, 17696.7, 4419.64 + 0.05, 2000.0, 0.83, 18133.67, 4551.37 + 0.05, 2000.0, 0.85, 18570.63, 4684.84 + 0.05, 2000.0, 0.87, 19007.58, 4820.16 + 0.05, 2000.0, 0.89, 19444.54, 4957.44 + 0.05, 2000.0, 0.91, 19881.5, 5096.8 + 0.05, 2000.0, 0.93, 20318.45, 5238.35 + 0.05, 2000.0, 0.95, 20755.41, 5382.21 + 0.05, 2000.0, 0.97, 21192.37, 5528.49 + 0.05, 2000.0, 0.99, 21629.33, 5677.31 + 0.05, 5000.0, 0.0, 602.9404, 602.94 + 0.05, 5000.0, 0.05, 1020.668, 449.578 + 0.05, 5000.0, 0.07, 1428.763, 524.262 + 0.05, 5000.0, 0.09, 1836.866, 600.019 + 0.05, 5000.0, 0.11, 2244.976, 676.849 + 0.05, 5000.0, 0.13, 2653.093, 754.752 + 0.05, 5000.0, 0.15, 3061.217, 833.73 + 0.05, 5000.0, 0.17, 3469.346, 913.783 + 0.05, 5000.0, 0.19, 3877.481, 994.912 + 0.05, 5000.0, 0.21, 4285.62, 1077.12 + 0.05, 5000.0, 0.23, 4693.764, 1160.4 + 0.05, 5000.0, 0.25, 5101.911, 1244.76 + 0.05, 5000.0, 0.27, 5510.061, 1330.2 + 0.05, 5000.0, 0.29, 5918.213, 1416.72 + 0.05, 5000.0, 0.31, 6326.367, 1504.33 + 0.05, 5000.0, 0.33, 6734.523, 1593.01 + 0.05, 5000.0, 0.35, 7142.679, 1682.78 + 0.05, 5000.0, 0.37, 7550.836, 1773.62 + 0.05, 5000.0, 0.39, 7958.992, 1865.56 + 0.05, 5000.0, 0.41, 8367.145, 1958.44 + 0.05, 5000.0, 0.43, 8775.293, 2052.3 + 0.05, 5000.0, 0.45, 9183.442, 2147.35 + 0.05, 5000.0, 0.47, 9591.592, 2243.65 + 0.05, 5000.0, 0.49, 9999.743, 2341.27 + 0.05, 5000.0, 0.51, 10407.89, 2440.31 + 0.05, 5000.0, 0.53, 10816.03, 2540.81 + 0.05, 5000.0, 0.55, 11224.18, 2642.82 + 0.05, 5000.0, 0.57, 11632.35, 2746.39 + 0.05, 5000.0, 0.59, 12040.54, 2851.56 + 0.05, 5000.0, 0.61, 12448.82, 2958.57 + 0.05, 5000.0, 0.63, 12857.16, 3067.42 + 0.05, 5000.0, 0.65, 13265.51, 3177.93 + 0.05, 5000.0, 0.67, 13673.84, 3290.07 + 0.05, 5000.0, 0.69, 14082.13, 3403.81 + 0.05, 5000.0, 0.71, 14490.29, 3519.04 + 0.05, 5000.0, 0.73, 14898.3, 3635.76 + 0.05, 5000.0, 0.75, 15306.27, 3754.07 + 0.05, 5000.0, 0.77, 15714.22, 3873.97 + 0.05, 5000.0, 0.79, 16122.18, 3995.47 + 0.05, 5000.0, 0.81, 16530.2, 4118.38 + 0.05, 5000.0, 0.83, 16938.31, 4242.77 + 0.05, 5000.0, 0.85, 17346.45, 4368.95 + 0.05, 5000.0, 0.87, 17754.6, 4497.05 + 0.05, 5000.0, 0.89, 18162.76, 4627.18 + 0.05, 5000.0, 0.91, 18570.94, 4759.45 + 0.05, 5000.0, 0.93, 18979.11, 4893.98 + 0.05, 5000.0, 0.95, 19387.29, 5030.89 + 0.05, 5000.0, 0.97, 19795.45, 5170.28 + 0.05, 5000.0, 0.99, 20203.61, 5312.28 + 0.05, 10000.0, 0.0, 507.5253, 507.525 + 0.05, 10000.0, 0.05, 885.3113, 388.063 + 0.05, 10000.0, 0.07, 1239.776, 451.724 + 0.05, 10000.0, 0.09, 1594.228, 516.293 + 0.05, 10000.0, 0.11, 1948.669, 581.776 + 0.05, 10000.0, 0.13, 2303.098, 648.176 + 0.05, 10000.0, 0.15, 2657.516, 715.499 + 0.05, 10000.0, 0.17, 3011.925, 783.751 + 0.05, 10000.0, 0.19, 3366.324, 852.936 + 0.05, 10000.0, 0.21, 3720.714, 923.059 + 0.05, 10000.0, 0.23, 4075.096, 994.126 + 0.05, 10000.0, 0.25, 4429.471, 1066.14 + 0.05, 10000.0, 0.27, 4783.839, 1139.11 + 0.05, 10000.0, 0.29, 5138.201, 1213.04 + 0.05, 10000.0, 0.31, 5492.558, 1287.93 + 0.05, 10000.0, 0.33, 5846.909, 1363.78 + 0.05, 10000.0, 0.35, 6201.256, 1440.62 + 0.05, 10000.0, 0.37, 6555.6, 1518.43 + 0.05, 10000.0, 0.39, 6909.941, 1597.22 + 0.05, 10000.0, 0.41, 7264.278, 1676.86 + 0.05, 10000.0, 0.43, 7618.614, 1757.39 + 0.05, 10000.0, 0.45, 7972.949, 1839.02 + 0.05, 10000.0, 0.47, 8327.285, 1921.82 + 0.05, 10000.0, 0.49, 8681.621, 2005.88 + 0.05, 10000.0, 0.51, 9035.963, 2091.37 + 0.05, 10000.0, 0.53, 9390.311, 2178.34 + 0.05, 10000.0, 0.55, 9744.66, 2266.7 + 0.05, 10000.0, 0.57, 10099.01, 2356.48 + 0.05, 10000.0, 0.59, 10453.36, 2447.69 + 0.05, 10000.0, 0.61, 10807.7, 2540.44 + 0.05, 10000.0, 0.63, 11162.03, 2634.72 + 0.05, 10000.0, 0.65, 11516.36, 2730.45 + 0.05, 10000.0, 0.67, 11870.69, 2827.6 + 0.05, 10000.0, 0.69, 12225.04, 2926.16 + 0.05, 10000.0, 0.71, 12579.4, 3025.97 + 0.05, 10000.0, 0.73, 12933.78, 3127.04 + 0.05, 10000.0, 0.75, 13288.17, 3229.57 + 0.05, 10000.0, 0.77, 13642.56, 3333.61 + 0.05, 10000.0, 0.79, 13996.95, 3439.21 + 0.05, 10000.0, 0.81, 14351.33, 3546.52 + 0.05, 10000.0, 0.83, 14705.7, 3655.58 + 0.05, 10000.0, 0.85, 15060.07, 3766.27 + 0.05, 10000.0, 0.87, 15414.43, 3878.61 + 0.05, 10000.0, 0.89, 15768.79, 3992.58 + 0.05, 10000.0, 0.91, 16123.13, 4108.19 + 0.05, 10000.0, 0.93, 16477.47, 4225.44 + 0.05, 10000.0, 0.95, 16831.79, 4344.34 + 0.05, 10000.0, 0.97, 17186.1, 4464.87 + 0.05, 10000.0, 0.99, 17540.4, 4587.05 + 0.05, 15000.0, 0.0, 424.4847, 424.485 + 0.05, 15000.0, 0.05, 705.1313, 411.488 + 0.05, 15000.0, 0.07, 987.6923, 453.983 + 0.05, 15000.0, 0.09, 1270.192, 498.89 + 0.05, 15000.0, 0.11, 1552.632, 545.98 + 0.05, 15000.0, 0.13, 1835.014, 595.024 + 0.05, 15000.0, 0.15, 2117.337, 645.793 + 0.05, 15000.0, 0.17, 2399.604, 698.057 + 0.05, 15000.0, 0.19, 2681.815, 751.588 + 0.05, 15000.0, 0.21, 2963.972, 806.156 + 0.05, 15000.0, 0.23, 3246.075, 861.532 + 0.05, 15000.0, 0.25, 3528.126, 917.487 + 0.05, 15000.0, 0.27, 3810.125, 973.793 + 0.05, 15000.0, 0.29, 4092.075, 1030.22 + 0.05, 15000.0, 0.31, 4373.938, 1085.09 + 0.05, 15000.0, 0.33, 4655.724, 1138.52 + 0.05, 15000.0, 0.35, 4937.491, 1192.45 + 0.05, 15000.0, 0.37, 5219.257, 1247.33 + 0.05, 15000.0, 0.39, 5501.044, 1303.64 + 0.05, 15000.0, 0.41, 5782.812, 1363.87 + 0.05, 15000.0, 0.43, 6064.597, 1427.99 + 0.05, 15000.0, 0.45, 6346.5, 1493.51 + 0.05, 15000.0, 0.47, 6628.568, 1559.92 + 0.05, 15000.0, 0.49, 6910.847, 1626.74 + 0.05, 15000.0, 0.51, 7193.405, 1691.04 + 0.05, 15000.0, 0.53, 7476.283, 1752.93 + 0.05, 15000.0, 0.55, 7759.498, 1815.47 + 0.05, 15000.0, 0.57, 8043.088, 1879.33 + 0.05, 15000.0, 0.59, 8327.09, 1945.18 + 0.05, 15000.0, 0.61, 8612.419, 2017.17 + 0.05, 15000.0, 0.63, 8898.9, 2095.12 + 0.05, 15000.0, 0.65, 9185.265, 2174.54 + 0.05, 15000.0, 0.67, 9471.124, 2254.39 + 0.05, 15000.0, 0.69, 9756.088, 2333.65 + 0.05, 15000.0, 0.71, 10037.99, 2406.52 + 0.05, 15000.0, 0.73, 10316.87, 2473.14 + 0.05, 15000.0, 0.75, 10594.99, 2539.59 + 0.05, 15000.0, 0.77, 10872.8, 2607.18 + 0.05, 15000.0, 0.79, 11150.79, 2677.22 + 0.05, 15000.0, 0.81, 11430.84, 2755.28 + 0.05, 15000.0, 0.83, 11713.08, 2841.63 + 0.05, 15000.0, 0.85, 11995.89, 2931.22 + 0.05, 15000.0, 0.87, 12279.05, 3023.27 + 0.05, 15000.0, 0.89, 12562.35, 3117.02 + 0.05, 15000.0, 0.91, 12845.59, 3211.69 + 0.05, 15000.0, 0.93, 13128.55, 3306.51 + 0.05, 15000.0, 0.95, 13411.01, 3400.7 + 0.05, 15000.0, 0.97, 13692.78, 3493.5 + 0.05, 15000.0, 0.99, 13973.63, 3584.13 + 0.05, 20000.0, 0.0, 352.5969, 352.597 + 0.05, 20000.0, 0.05, 578.3562, 292.031 + 0.05, 20000.0, 0.07, 810.6562, 331.227 + 0.05, 20000.0, 0.09, 1042.961, 370.255 + 0.05, 20000.0, 0.11, 1275.268, 409.257 + 0.05, 20000.0, 0.13, 1507.57, 448.375 + 0.05, 20000.0, 0.15, 1739.865, 487.751 + 0.05, 20000.0, 0.17, 1972.147, 527.527 + 0.05, 20000.0, 0.19, 2204.412, 567.844 + 0.05, 20000.0, 0.21, 2436.657, 608.845 + 0.05, 20000.0, 0.23, 2668.875, 650.671 + 0.05, 20000.0, 0.25, 2901.064, 693.465 + 0.05, 20000.0, 0.27, 3133.218, 737.368 + 0.05, 20000.0, 0.29, 3365.333, 782.522 + 0.05, 20000.0, 0.31, 3597.427, 830.165 + 0.05, 20000.0, 0.33, 3829.489, 880.174 + 0.05, 20000.0, 0.35, 4061.483, 931.062 + 0.05, 20000.0, 0.37, 4293.395, 982.44 + 0.05, 20000.0, 0.39, 4525.209, 1033.92 + 0.05, 20000.0, 0.41, 4756.843, 1083.62 + 0.05, 20000.0, 0.43, 4988.298, 1131.52 + 0.05, 20000.0, 0.45, 5219.661, 1179.44 + 0.05, 20000.0, 0.47, 5450.951, 1227.69 + 0.05, 20000.0, 0.49, 5682.185, 1276.63 + 0.05, 20000.0, 0.51, 5913.178, 1327.73 + 0.05, 20000.0, 0.53, 6143.997, 1381.06 + 0.05, 20000.0, 0.55, 6374.965, 1435.21 + 0.05, 20000.0, 0.57, 6606.201, 1489.94 + 0.05, 20000.0, 0.59, 6837.821, 1545.04 + 0.05, 20000.0, 0.61, 7070.497, 1598.72 + 0.05, 20000.0, 0.63, 7304.211, 1651.13 + 0.05, 20000.0, 0.65, 7538.262, 1704.3 + 0.05, 20000.0, 0.67, 7772.501, 1758.76 + 0.05, 20000.0, 0.69, 8006.776, 1815.01 + 0.05, 20000.0, 0.71, 8240.963, 1875.38 + 0.05, 20000.0, 0.73, 8474.904, 1939.96 + 0.05, 20000.0, 0.75, 8708.415, 2006.52 + 0.05, 20000.0, 0.77, 8941.336, 2074.7 + 0.05, 20000.0, 0.79, 9173.504, 2144.11 + 0.05, 20000.0, 0.81, 9403.551, 2214.01 + 0.05, 20000.0, 0.83, 9631.607, 2284.09 + 0.05, 20000.0, 0.85, 9859.306, 2354.57 + 0.05, 20000.0, 0.87, 10087.07, 2425.24 + 0.05, 20000.0, 0.89, 10315.33, 2495.93 + 0.05, 20000.0, 0.91, 10544.51, 2566.44 + 0.05, 20000.0, 0.93, 10775.03, 2636.58 + 0.05, 20000.0, 0.95, 11007.32, 2706.16 + 0.05, 20000.0, 0.97, 11241.8, 2775.0 + 0.05, 20000.0, 0.99, 11478.9, 2842.9 + 0.05, 25000.0, 0.0, 290.7125, 290.713 + 0.05, 25000.0, 0.05, 471.06, 231.19 + 0.05, 25000.0, 0.07, 652.677, 295.272 + 0.05, 25000.0, 0.09, 835.5386, 347.713 + 0.05, 25000.0, 0.11, 1019.523, 390.092 + 0.05, 25000.0, 0.13, 1204.51, 423.991 + 0.05, 25000.0, 0.15, 1390.378, 450.989 + 0.05, 25000.0, 0.17, 1577.005, 472.668 + 0.05, 25000.0, 0.19, 1764.271, 490.608 + 0.05, 25000.0, 0.21, 1952.053, 506.39 + 0.05, 25000.0, 0.23, 2140.232, 521.593 + 0.05, 25000.0, 0.25, 2328.685, 537.798 + 0.05, 25000.0, 0.27, 2517.292, 556.587 + 0.05, 25000.0, 0.29, 2705.931, 579.539 + 0.05, 25000.0, 0.31, 2894.395, 615.175 + 0.05, 25000.0, 0.33, 3082.583, 663.393 + 0.05, 25000.0, 0.35, 3270.502, 715.468 + 0.05, 25000.0, 0.37, 3458.073, 769.617 + 0.05, 25000.0, 0.39, 3645.218, 824.055 + 0.05, 25000.0, 0.41, 3831.527, 873.685 + 0.05, 25000.0, 0.43, 4017.0, 917.525 + 0.05, 25000.0, 0.45, 4202.049, 958.711 + 0.05, 25000.0, 0.47, 4386.752, 997.065 + 0.05, 25000.0, 0.49, 4571.19, 1032.41 + 0.05, 25000.0, 0.51, 4755.302, 1059.57 + 0.05, 25000.0, 0.53, 4939.203, 1079.59 + 0.05, 25000.0, 0.55, 5123.183, 1099.69 + 0.05, 25000.0, 0.57, 5307.391, 1122.12 + 0.05, 25000.0, 0.59, 5491.975, 1149.12 + 0.05, 25000.0, 0.61, 5677.42, 1191.56 + 0.05, 25000.0, 0.63, 5863.793, 1249.59 + 0.05, 25000.0, 0.65, 6050.746, 1312.63 + 0.05, 25000.0, 0.67, 6238.265, 1378.75 + 0.05, 25000.0, 0.69, 6426.336, 1446.0 + 0.05, 25000.0, 0.71, 6615.364, 1508.13 + 0.05, 25000.0, 0.73, 6805.233, 1564.26 + 0.05, 25000.0, 0.75, 6995.31, 1618.81 + 0.05, 25000.0, 0.77, 7185.379, 1671.92 + 0.05, 25000.0, 0.79, 7375.224, 1723.73 + 0.05, 25000.0, 0.81, 7564.425, 1774.16 + 0.05, 25000.0, 0.83, 7752.816, 1823.41 + 0.05, 25000.0, 0.85, 7940.483, 1871.92 + 0.05, 25000.0, 0.87, 8127.309, 1919.94 + 0.05, 25000.0, 0.89, 8313.177, 1967.71 + 0.05, 25000.0, 0.91, 8497.969, 2015.46 + 0.05, 25000.0, 0.93, 8681.569, 2063.45 + 0.05, 25000.0, 0.95, 8863.859, 2111.91 + 0.05, 25000.0, 0.97, 9044.722, 2161.07 + 0.05, 25000.0, 0.99, 9224.041, 2211.2 + 0.05, 30000.0, 0.0, 237.7644, 237.764 + 0.05, 30000.0, 0.05, 324.23, 179.44 + 0.05, 30000.0, 0.07, 458.4904, 196.072 + 0.05, 30000.0, 0.09, 591.4277, 212.772 + 0.05, 30000.0, 0.11, 723.217, 229.555 + 0.05, 30000.0, 0.13, 854.0338, 246.438 + 0.05, 30000.0, 0.15, 984.0534, 263.439 + 0.05, 30000.0, 0.17, 1113.451, 280.574 + 0.05, 30000.0, 0.19, 1242.402, 297.86 + 0.05, 30000.0, 0.21, 1371.082, 315.314 + 0.05, 30000.0, 0.23, 1499.666, 332.952 + 0.05, 30000.0, 0.25, 1628.329, 350.791 + 0.05, 30000.0, 0.27, 1757.247, 368.848 + 0.05, 30000.0, 0.29, 1886.595, 387.141 + 0.05, 30000.0, 0.31, 2017.398, 405.342 + 0.05, 30000.0, 0.33, 2149.625, 423.552 + 0.05, 30000.0, 0.35, 2282.191, 442.297 + 0.05, 30000.0, 0.37, 2414.857, 461.758 + 0.05, 30000.0, 0.39, 2547.389, 482.12 + 0.05, 30000.0, 0.41, 2678.964, 505.021 + 0.05, 30000.0, 0.43, 2809.487, 530.293 + 0.05, 30000.0, 0.45, 2939.591, 555.952 + 0.05, 30000.0, 0.47, 3069.321, 581.476 + 0.05, 30000.0, 0.49, 3198.726, 606.339 + 0.05, 30000.0, 0.51, 3327.588, 628.062 + 0.05, 30000.0, 0.53, 3456.018, 646.594 + 0.05, 30000.0, 0.55, 3584.454, 664.318 + 0.05, 30000.0, 0.57, 3713.069, 681.659 + 0.05, 30000.0, 0.59, 3842.038, 699.041 + 0.05, 30000.0, 0.61, 3972.283, 717.485 + 0.05, 30000.0, 0.63, 4103.795, 737.272 + 0.05, 30000.0, 0.65, 4235.641, 757.942 + 0.05, 30000.0, 0.67, 4367.632, 779.631 + 0.05, 30000.0, 0.69, 4499.581, 802.473 + 0.05, 30000.0, 0.71, 4630.589, 828.184 + 0.05, 30000.0, 0.73, 4760.641, 856.516 + 0.05, 30000.0, 0.75, 4890.603, 885.263 + 0.05, 30000.0, 0.77, 5020.63, 913.795 + 0.05, 30000.0, 0.79, 5150.879, 941.483 + 0.05, 30000.0, 0.81, 5282.24, 964.092 + 0.05, 30000.0, 0.83, 5414.692, 981.866 + 0.05, 30000.0, 0.85, 5547.299, 999.533 + 0.05, 30000.0, 0.87, 5679.86, 1018.21 + 0.05, 30000.0, 0.89, 5812.177, 1039.03 + 0.05, 30000.0, 0.91, 5944.047, 1063.1 + 0.05, 30000.0, 0.93, 6075.271, 1091.54 + 0.05, 30000.0, 0.95, 6205.649, 1125.48 + 0.05, 30000.0, 0.97, 6334.98, 1166.03 + 0.05, 30000.0, 0.99, 6463.063, 1214.32 + 0.05, 35000.0, 0.0, 192.7609, 192.761 + 0.05, 35000.0, 0.05, 323.75, 285.425 + 0.05, 35000.0, 0.07, 463.8546, 287.31 + 0.05, 35000.0, 0.09, 606.0962, 292.548 + 0.05, 35000.0, 0.11, 750.2492, 300.942 + 0.05, 35000.0, 0.13, 896.0884, 312.297 + 0.05, 35000.0, 0.15, 1043.388, 326.413 + 0.05, 35000.0, 0.17, 1191.924, 343.096 + 0.05, 35000.0, 0.19, 1341.469, 362.147 + 0.05, 35000.0, 0.21, 1491.799, 383.371 + 0.05, 35000.0, 0.23, 1642.688, 406.569 + 0.05, 35000.0, 0.25, 1793.911, 431.546 + 0.05, 35000.0, 0.27, 1945.243, 458.104 + 0.05, 35000.0, 0.29, 2096.457, 486.046 + 0.05, 35000.0, 0.31, 2247.09, 517.077 + 0.05, 35000.0, 0.33, 2396.973, 550.537 + 0.05, 35000.0, 0.35, 2546.238, 583.409 + 0.05, 35000.0, 0.37, 2694.774, 614.574 + 0.05, 35000.0, 0.39, 2842.473, 642.914 + 0.05, 35000.0, 0.41, 2989.128, 658.764 + 0.05, 35000.0, 0.43, 3134.653, 663.078 + 0.05, 35000.0, 0.45, 3279.084, 667.427 + 0.05, 35000.0, 0.47, 3422.361, 674.834 + 0.05, 35000.0, 0.49, 3564.421, 688.327 + 0.05, 35000.0, 0.51, 3704.011, 724.028 + 0.05, 35000.0, 0.53, 3841.36, 781.789 + 0.05, 35000.0, 0.55, 3978.173, 845.181 + 0.05, 35000.0, 0.57, 4114.967, 910.88 + 0.05, 35000.0, 0.59, 4252.258, 975.558 + 0.05, 35000.0, 0.61, 4392.693, 1029.1 + 0.05, 35000.0, 0.63, 4536.272, 1069.82 + 0.05, 35000.0, 0.65, 4680.344, 1104.49 + 0.05, 35000.0, 0.67, 4824.389, 1133.05 + 0.05, 35000.0, 0.69, 4967.891, 1155.49 + 0.05, 35000.0, 0.71, 5107.554, 1164.8 + 0.05, 35000.0, 0.73, 5243.534, 1162.63 + 0.05, 35000.0, 0.75, 5379.433, 1159.3 + 0.05, 35000.0, 0.77, 5516.077, 1158.14 + 0.05, 35000.0, 0.79, 5654.294, 1162.5 + 0.05, 35000.0, 0.81, 5798.149, 1188.9 + 0.05, 35000.0, 0.83, 5947.686, 1237.48 + 0.05, 35000.0, 0.85, 6098.92, 1292.04 + 0.05, 35000.0, 0.87, 6251.108, 1349.51 + 0.05, 35000.0, 0.89, 6403.505, 1406.87 + 0.05, 35000.0, 0.91, 6555.368, 1461.06 + 0.05, 35000.0, 0.93, 6705.954, 1509.05 + 0.05, 35000.0, 0.95, 6854.517, 1547.78 + 0.05, 35000.0, 0.97, 7000.315, 1574.22 + 0.05, 35000.0, 0.99, 7142.604, 1585.33 + 0.05, 40000.0, 0.0, 152.5515, 152.551 + 0.05, 40000.0, 0.05, 306.5, 184.775 + 0.05, 40000.0, 0.07, 417.2452, 229.295 + 0.05, 40000.0, 0.09, 527.3469, 263.421 + 0.05, 40000.0, 0.11, 637.0702, 288.643 + 0.05, 40000.0, 0.13, 746.6802, 306.447 + 0.05, 40000.0, 0.15, 856.442, 318.324 + 0.05, 40000.0, 0.17, 966.6206, 325.761 + 0.05, 40000.0, 0.19, 1077.481, 330.248 + 0.05, 40000.0, 0.21, 1189.289, 333.272 + 0.05, 40000.0, 0.23, 1302.308, 336.323 + 0.05, 40000.0, 0.25, 1416.805, 340.889 + 0.05, 40000.0, 0.27, 1533.045, 348.458 + 0.05, 40000.0, 0.29, 1651.291, 360.52 + 0.05, 40000.0, 0.31, 1774.529, 387.156 + 0.05, 40000.0, 0.33, 1902.363, 427.774 + 0.05, 40000.0, 0.35, 2031.023, 471.098 + 0.05, 40000.0, 0.37, 2159.456, 514.451 + 0.05, 40000.0, 0.39, 2286.608, 555.154 + 0.05, 40000.0, 0.41, 2408.075, 579.069 + 0.05, 40000.0, 0.43, 2523.617, 586.295 + 0.05, 40000.0, 0.45, 2637.156, 591.169 + 0.05, 40000.0, 0.47, 2749.266, 596.569 + 0.05, 40000.0, 0.49, 2860.517, 605.373 + 0.05, 40000.0, 0.51, 2971.297, 633.14 + 0.05, 40000.0, 0.53, 3082.221, 679.675 + 0.05, 40000.0, 0.55, 3194.139, 729.022 + 0.05, 40000.0, 0.57, 3307.712, 777.91 + 0.05, 40000.0, 0.59, 3423.603, 823.068 + 0.05, 40000.0, 0.61, 3546.382, 850.735 + 0.05, 40000.0, 0.63, 3675.764, 860.184 + 0.05, 40000.0, 0.65, 3806.608, 863.714 + 0.05, 40000.0, 0.67, 3937.681, 863.14 + 0.05, 40000.0, 0.69, 4067.751, 860.275 + 0.05, 40000.0, 0.71, 4192.469, 855.277 + 0.05, 40000.0, 0.73, 4311.358, 850.362 + 0.05, 40000.0, 0.75, 4427.813, 849.798 + 0.05, 40000.0, 0.77, 4542.111, 856.204 + 0.05, 40000.0, 0.79, 4654.532, 872.194 + 0.05, 40000.0, 0.81, 4763.734, 916.887 + 0.05, 40000.0, 0.83, 4870.389, 988.898 + 0.05, 40000.0, 0.85, 4977.18, 1066.34 + 0.05, 40000.0, 0.87, 5085.168, 1143.82 + 0.05, 40000.0, 0.89, 5195.419, 1215.97 + 0.05, 40000.0, 0.91, 5308.995, 1277.38 + 0.05, 40000.0, 0.93, 5426.96, 1322.68 + 0.05, 40000.0, 0.95, 5550.377, 1346.48 + 0.05, 40000.0, 0.97, 5680.309, 1343.39 + 0.05, 40000.0, 0.99, 5817.82, 1308.04 + 0.05, 43000.0, 0.0, 132.1427, 132.143 + 0.05, 43000.0, 0.05, 174.3, 252.4 + 0.05, 43000.0, 0.07, 344.1166, 308.354 + 0.05, 43000.0, 0.09, 492.883, 354.291 + 0.05, 43000.0, 0.11, 623.284, 391.015 + 0.05, 43000.0, 0.13, 738.0043, 419.328 + 0.05, 43000.0, 0.15, 839.7286, 440.036 + 0.05, 43000.0, 0.17, 931.1415, 453.94 + 0.05, 43000.0, 0.19, 1014.928, 461.846 + 0.05, 43000.0, 0.21, 1093.772, 464.556 + 0.05, 43000.0, 0.23, 1170.36, 462.874 + 0.05, 43000.0, 0.25, 1247.374, 457.603 + 0.05, 43000.0, 0.27, 1327.501, 449.547 + 0.05, 43000.0, 0.29, 1413.425, 439.51 + 0.05, 43000.0, 0.31, 1521.473, 422.467 + 0.05, 43000.0, 0.33, 1651.022, 400.634 + 0.05, 43000.0, 0.35, 1784.5, 383.469 + 0.05, 43000.0, 0.37, 1917.978, 374.602 + 0.05, 43000.0, 0.39, 2047.527, 377.663 + 0.05, 43000.0, 0.41, 2154.657, 423.241 + 0.05, 43000.0, 0.43, 2238.968, 508.432 + 0.05, 43000.0, 0.45, 2318.15, 596.831 + 0.05, 43000.0, 0.47, 2395.332, 678.996 + 0.05, 43000.0, 0.49, 2473.643, 745.485 + 0.05, 43000.0, 0.51, 2566.574, 746.311 + 0.05, 43000.0, 0.53, 2674.742, 681.861 + 0.05, 43000.0, 0.55, 2785.894, 602.894 + 0.05, 43000.0, 0.57, 2898.136, 519.624 + 0.05, 43000.0, 0.59, 3009.574, 442.268 + 0.05, 43000.0, 0.61, 3111.403, 407.875 + 0.05, 43000.0, 0.63, 3203.405, 420.153 + 0.05, 43000.0, 0.65, 3293.95, 449.475 + 0.05, 43000.0, 0.67, 3384.495, 493.045 + 0.05, 43000.0, 0.69, 3476.497, 548.067 + 0.05, 43000.0, 0.71, 3578.326, 614.83 + 0.05, 43000.0, 0.73, 3689.764, 689.79 + 0.05, 43000.0, 0.75, 3802.006, 765.575 + 0.05, 43000.0, 0.77, 3913.158, 837.896 + 0.05, 43000.0, 0.79, 4021.326, 902.464 + 0.05, 43000.0, 0.81, 4116.66, 937.802 + 0.05, 43000.0, 0.83, 4199.193, 943.788 + 0.05, 43000.0, 0.85, 4278.85, 941.65 + 0.05, 43000.0, 0.87, 4357.595, 935.432 + 0.05, 43000.0, 0.89, 4437.392, 929.178 + 0.05, 43000.0, 0.91, 4520.208, 926.929 + 0.05, 43000.0, 0.93, 4608.005, 932.731 + 0.05, 43000.0, 0.95, 4702.75, 950.625 + 0.05, 43000.0, 0.97, 4806.407, 984.655 + 0.05, 43000.0, 0.99, 4920.94, 1038.86 + 0.05, 48000.0, 0.0, 104.023, 104.023 + 0.05, 48000.0, 0.05, 179.8, 296.7 + 0.05, 48000.0, 0.07, 306.1451, 330.881 + 0.05, 48000.0, 0.09, 418.984, 356.494 + 0.05, 48000.0, 0.11, 519.8389, 374.411 + 0.05, 48000.0, 0.13, 610.232, 385.506 + 0.05, 48000.0, 0.15, 691.6857, 390.65 + 0.05, 48000.0, 0.17, 765.7223, 390.716 + 0.05, 48000.0, 0.19, 833.864, 386.575 + 0.05, 48000.0, 0.21, 897.6331, 379.101 + 0.05, 48000.0, 0.23, 958.552, 369.165 + 0.05, 48000.0, 0.25, 1018.143, 357.64 + 0.05, 48000.0, 0.27, 1077.928, 345.398 + 0.05, 48000.0, 0.29, 1139.43, 333.312 + 0.05, 48000.0, 0.31, 1208.036, 320.114 + 0.05, 48000.0, 0.33, 1284.332, 307.196 + 0.05, 48000.0, 0.35, 1364.1, 298.606 + 0.05, 48000.0, 0.37, 1446.988, 296.254 + 0.05, 48000.0, 0.39, 1532.644, 302.05 + 0.05, 48000.0, 0.41, 1621.086, 335.347 + 0.05, 48000.0, 0.43, 1711.871, 393.825 + 0.05, 48000.0, 0.45, 1804.1, 453.494 + 0.05, 48000.0, 0.47, 1897.241, 507.804 + 0.05, 48000.0, 0.49, 1990.762, 550.209 + 0.05, 48000.0, 0.51, 2086.772, 543.103 + 0.05, 48000.0, 0.53, 2184.099, 487.468 + 0.05, 48000.0, 0.55, 2278.294, 422.869 + 0.05, 48000.0, 0.57, 2367.547, 357.816 + 0.05, 48000.0, 0.59, 2450.048, 300.819 + 0.05, 48000.0, 0.61, 2509.866, 287.735 + 0.05, 48000.0, 0.63, 2548.616, 320.445 + 0.05, 48000.0, 0.65, 2585.45, 366.85 + 0.05, 48000.0, 0.67, 2625.404, 422.199 + 0.05, 48000.0, 0.69, 2673.514, 481.741 + 0.05, 48000.0, 0.71, 2757.578, 531.366 + 0.05, 48000.0, 0.73, 2877.115, 568.592 + 0.05, 48000.0, 0.75, 3003.356, 602.569 + 0.05, 48000.0, 0.77, 3130.299, 633.083 + 0.05, 48000.0, 0.79, 3251.942, 659.924 + 0.05, 48000.0, 0.81, 3343.83, 678.349 + 0.05, 48000.0, 0.83, 3404.434, 689.245 + 0.05, 48000.0, 0.85, 3455.15, 699.125 + 0.05, 48000.0, 0.87, 3498.922, 709.973 + 0.05, 48000.0, 0.89, 3538.694, 723.773 + 0.05, 48000.0, 0.91, 3577.41, 742.509 + 0.05, 48000.0, 0.93, 3618.014, 768.165 + 0.05, 48000.0, 0.95, 3663.45, 802.725 + 0.05, 48000.0, 0.97, 3716.662, 848.173 + 0.05, 48000.0, 0.99, 3780.594, 906.493 + 0.1, 0.0, 0.0, 715.2593, 715.259 + 0.1, 0.0, 0.05, 1083.006, 574.425 + 0.1, 0.0, 0.07, 1515.783, 666.998 + 0.1, 0.0, 0.09, 1948.588, 760.284 + 0.1, 0.0, 0.11, 2381.418, 854.301 + 0.1, 0.0, 0.13, 2814.271, 949.067 + 0.1, 0.0, 0.15, 3247.144, 1044.6 + 0.1, 0.0, 0.17, 3680.035, 1140.92 + 0.1, 0.0, 0.19, 4112.942, 1238.03 + 0.1, 0.0, 0.21, 4545.861, 1335.97 + 0.1, 0.0, 0.23, 4978.792, 1434.75 + 0.1, 0.0, 0.25, 5411.731, 1534.38 + 0.1, 0.0, 0.27, 5844.676, 1634.88 + 0.1, 0.0, 0.29, 6277.625, 1736.27 + 0.1, 0.0, 0.31, 6710.575, 1838.56 + 0.1, 0.0, 0.33, 7143.524, 1941.79 + 0.1, 0.0, 0.35, 7576.469, 2045.95 + 0.1, 0.0, 0.37, 8009.408, 2151.07 + 0.1, 0.0, 0.39, 8442.339, 2257.18 + 0.1, 0.0, 0.41, 8875.239, 2364.2 + 0.1, 0.0, 0.43, 9308.111, 2472.19 + 0.1, 0.0, 0.45, 9740.981, 2581.26 + 0.1, 0.0, 0.47, 10173.86, 2691.46 + 0.1, 0.0, 0.49, 10606.75, 2802.85 + 0.1, 0.0, 0.51, 11039.69, 2915.41 + 0.1, 0.0, 0.53, 11472.67, 3029.23 + 0.1, 0.0, 0.55, 11905.67, 3144.43 + 0.1, 0.0, 0.57, 12338.68, 3261.09 + 0.1, 0.0, 0.59, 12771.7, 3379.3 + 0.1, 0.0, 0.61, 13204.69, 3499.35 + 0.1, 0.0, 0.63, 13637.66, 3621.27 + 0.1, 0.0, 0.65, 14070.63, 3744.8 + 0.1, 0.0, 0.67, 14503.58, 3869.92 + 0.1, 0.0, 0.69, 14936.53, 3996.59 + 0.1, 0.0, 0.71, 15369.46, 4124.77 + 0.1, 0.0, 0.73, 15802.38, 4254.43 + 0.1, 0.0, 0.75, 16235.3, 4385.56 + 0.1, 0.0, 0.77, 16668.22, 4518.15 + 0.1, 0.0, 0.79, 17101.14, 4652.16 + 0.1, 0.0, 0.81, 17534.08, 4787.32 + 0.1, 0.0, 0.83, 17967.03, 4923.65 + 0.1, 0.0, 0.85, 18399.99, 5061.54 + 0.1, 0.0, 0.87, 18832.96, 5201.1 + 0.1, 0.0, 0.89, 19265.92, 5342.43 + 0.1, 0.0, 0.91, 19698.88, 5485.65 + 0.1, 0.0, 0.93, 20131.83, 5630.87 + 0.1, 0.0, 0.95, 20564.78, 5778.19 + 0.1, 0.0, 0.97, 20997.72, 5927.72 + 0.1, 0.0, 0.99, 21430.64, 6079.57 + 0.1, 2000.0, 0.0, 669.6799, 669.68 + 0.1, 2000.0, 0.05, 1036.525, 542.419 + 0.1, 2000.0, 0.07, 1451.532, 630.637 + 0.1, 2000.0, 0.09, 1866.516, 719.511 + 0.1, 2000.0, 0.11, 2281.479, 809.061 + 0.1, 2000.0, 0.13, 2696.423, 899.311 + 0.1, 2000.0, 0.15, 3111.35, 990.281 + 0.1, 2000.0, 0.17, 3526.261, 1081.99 + 0.1, 2000.0, 0.19, 3941.157, 1174.47 + 0.1, 2000.0, 0.21, 4356.04, 1267.73 + 0.1, 2000.0, 0.23, 4770.912, 1361.8 + 0.1, 2000.0, 0.25, 5185.775, 1456.69 + 0.1, 2000.0, 0.27, 5600.63, 1552.44 + 0.1, 2000.0, 0.29, 6015.478, 1649.06 + 0.1, 2000.0, 0.31, 6430.321, 1746.57 + 0.1, 2000.0, 0.33, 6845.161, 1844.99 + 0.1, 2000.0, 0.35, 7260.0, 1944.36 + 0.1, 2000.0, 0.37, 7674.839, 2044.68 + 0.1, 2000.0, 0.39, 8089.679, 2145.98 + 0.1, 2000.0, 0.41, 8504.526, 2248.21 + 0.1, 2000.0, 0.43, 8919.38, 2351.41 + 0.1, 2000.0, 0.45, 9334.238, 2455.71 + 0.1, 2000.0, 0.47, 9749.1, 2561.16 + 0.1, 2000.0, 0.49, 10163.97, 2667.81 + 0.1, 2000.0, 0.51, 10578.84, 2775.68 + 0.1, 2000.0, 0.53, 10993.73, 2884.83 + 0.1, 2000.0, 0.55, 11408.61, 2995.37 + 0.1, 2000.0, 0.57, 11823.49, 3107.38 + 0.1, 2000.0, 0.59, 12238.37, 3220.93 + 0.1, 2000.0, 0.61, 12653.21, 3336.33 + 0.1, 2000.0, 0.63, 13068.03, 3453.61 + 0.1, 2000.0, 0.65, 13482.85, 3572.46 + 0.1, 2000.0, 0.67, 13897.67, 3692.85 + 0.1, 2000.0, 0.69, 14312.49, 3814.72 + 0.1, 2000.0, 0.71, 14727.33, 3937.94 + 0.1, 2000.0, 0.73, 15142.21, 4062.48 + 0.1, 2000.0, 0.75, 15557.09, 4188.44 + 0.1, 2000.0, 0.77, 15971.97, 4315.8 + 0.1, 2000.0, 0.79, 16386.86, 4444.58 + 0.1, 2000.0, 0.81, 16801.73, 4574.49 + 0.1, 2000.0, 0.83, 17216.6, 4705.6 + 0.1, 2000.0, 0.85, 17631.46, 4838.32 + 0.1, 2000.0, 0.87, 18046.31, 4972.77 + 0.1, 2000.0, 0.89, 18461.17, 5109.1 + 0.1, 2000.0, 0.91, 18876.03, 5247.42 + 0.1, 2000.0, 0.93, 19290.89, 5387.88 + 0.1, 2000.0, 0.95, 19705.74, 5530.61 + 0.1, 2000.0, 0.97, 20120.6, 5675.73 + 0.1, 2000.0, 0.99, 20535.47, 5823.38 + 0.1, 5000.0, 0.0, 605.6563, 605.656 + 0.1, 5000.0, 0.05, 969.75, 500.556 + 0.1, 5000.0, 0.07, 1357.65, 581.525 + 0.1, 5000.0, 0.09, 1745.55, 663.196 + 0.1, 5000.0, 0.11, 2133.45, 745.586 + 0.1, 5000.0, 0.13, 2521.35, 828.713 + 0.1, 5000.0, 0.15, 2909.25, 912.594 + 0.1, 5000.0, 0.17, 3297.15, 997.244 + 0.1, 5000.0, 0.19, 3685.05, 1082.68 + 0.1, 5000.0, 0.21, 4072.95, 1168.92 + 0.1, 5000.0, 0.23, 4460.85, 1255.98 + 0.1, 5000.0, 0.25, 4848.75, 1343.88 + 0.1, 5000.0, 0.27, 5236.65, 1432.63 + 0.1, 5000.0, 0.29, 5624.55, 1522.26 + 0.1, 5000.0, 0.31, 6012.45, 1612.77 + 0.1, 5000.0, 0.33, 6400.35, 1704.18 + 0.1, 5000.0, 0.35, 6788.25, 1796.52 + 0.1, 5000.0, 0.37, 7176.15, 1889.79 + 0.1, 5000.0, 0.39, 7564.05, 1984.02 + 0.1, 5000.0, 0.41, 7951.95, 2079.1 + 0.1, 5000.0, 0.43, 8339.85, 2175.08 + 0.1, 5000.0, 0.45, 8727.75, 2272.15 + 0.1, 5000.0, 0.47, 9115.65, 2370.39 + 0.1, 5000.0, 0.49, 9503.55, 2469.87 + 0.1, 5000.0, 0.51, 9891.435, 2570.76 + 0.1, 5000.0, 0.53, 10279.31, 2673.11 + 0.1, 5000.0, 0.55, 10667.19, 2776.87 + 0.1, 5000.0, 0.57, 11055.1, 2882.06 + 0.1, 5000.0, 0.59, 11443.02, 2988.71 + 0.1, 5000.0, 0.61, 11831.04, 3096.99 + 0.1, 5000.0, 0.63, 12219.15, 3206.88 + 0.1, 5000.0, 0.65, 12607.26, 3318.25 + 0.1, 5000.0, 0.67, 12995.35, 3431.06 + 0.1, 5000.0, 0.69, 13383.4, 3545.27 + 0.1, 5000.0, 0.71, 13771.3, 3660.73 + 0.1, 5000.0, 0.73, 14159.05, 3777.44 + 0.1, 5000.0, 0.75, 14546.76, 3895.58 + 0.1, 5000.0, 0.77, 14934.45, 4015.17 + 0.1, 5000.0, 0.79, 15322.14, 4136.27 + 0.1, 5000.0, 0.81, 15709.92, 4258.79 + 0.1, 5000.0, 0.83, 16097.8, 4382.8 + 0.1, 5000.0, 0.85, 16485.69, 4508.51 + 0.1, 5000.0, 0.87, 16873.61, 4636.03 + 0.1, 5000.0, 0.89, 17261.54, 4765.45 + 0.1, 5000.0, 0.91, 17649.46, 4896.86 + 0.1, 5000.0, 0.93, 18037.39, 5030.38 + 0.1, 5000.0, 0.95, 18425.31, 5166.09 + 0.1, 5000.0, 0.97, 18813.2, 5304.09 + 0.1, 5000.0, 0.99, 19201.08, 5444.48 + 0.1, 10000.0, 0.0, 509.8115, 509.811 + 0.1, 10000.0, 0.05, 834.2438, 429.475 + 0.1, 10000.0, 0.07, 1168.236, 497.541 + 0.1, 10000.0, 0.09, 1502.215, 566.223 + 0.1, 10000.0, 0.11, 1836.182, 635.537 + 0.1, 10000.0, 0.13, 2170.137, 705.499 + 0.1, 10000.0, 0.15, 2504.081, 776.125 + 0.1, 10000.0, 0.17, 2838.016, 847.431 + 0.1, 10000.0, 0.19, 3171.941, 919.433 + 0.1, 10000.0, 0.21, 3505.857, 992.147 + 0.1, 10000.0, 0.23, 3839.766, 1065.59 + 0.1, 10000.0, 0.25, 4173.669, 1139.78 + 0.1, 10000.0, 0.27, 4507.565, 1214.72 + 0.1, 10000.0, 0.29, 4841.456, 1290.44 + 0.1, 10000.0, 0.31, 5175.343, 1366.96 + 0.1, 10000.0, 0.33, 5509.226, 1444.28 + 0.1, 10000.0, 0.35, 5843.106, 1522.42 + 0.1, 10000.0, 0.37, 6176.985, 1601.41 + 0.1, 10000.0, 0.39, 6510.862, 1681.25 + 0.1, 10000.0, 0.41, 6844.738, 1761.85 + 0.1, 10000.0, 0.43, 7178.615, 1843.24 + 0.1, 10000.0, 0.45, 7512.494, 1925.63 + 0.1, 10000.0, 0.47, 7846.374, 2009.07 + 0.1, 10000.0, 0.49, 8180.257, 2093.66 + 0.1, 10000.0, 0.51, 8514.15, 2179.59 + 0.1, 10000.0, 0.53, 8848.053, 2266.91 + 0.1, 10000.0, 0.55, 9181.956, 2355.49 + 0.1, 10000.0, 0.57, 9515.857, 2445.34 + 0.1, 10000.0, 0.59, 9849.754, 2536.46 + 0.1, 10000.0, 0.61, 10183.63, 2628.91 + 0.1, 10000.0, 0.63, 10517.49, 2722.69 + 0.1, 10000.0, 0.65, 10851.34, 2817.73 + 0.1, 10000.0, 0.67, 11185.2, 2914.0 + 0.1, 10000.0, 0.69, 11519.06, 3011.5 + 0.1, 10000.0, 0.71, 11852.95, 3110.02 + 0.1, 10000.0, 0.73, 12186.87, 3209.6 + 0.1, 10000.0, 0.75, 12520.79, 3310.48 + 0.1, 10000.0, 0.77, 12854.71, 3412.72 + 0.1, 10000.0, 0.79, 13188.64, 3516.4 + 0.1, 10000.0, 0.81, 13522.56, 3621.75 + 0.1, 10000.0, 0.83, 13856.47, 3728.79 + 0.1, 10000.0, 0.85, 14190.37, 3837.36 + 0.1, 10000.0, 0.87, 14524.27, 3947.45 + 0.1, 10000.0, 0.89, 14858.16, 4059.04 + 0.1, 10000.0, 0.91, 15192.04, 4172.13 + 0.1, 10000.0, 0.93, 15525.92, 4286.71 + 0.1, 10000.0, 0.95, 15859.78, 4402.76 + 0.1, 10000.0, 0.97, 16193.64, 4520.28 + 0.1, 10000.0, 0.99, 16527.48, 4639.27 + 0.1, 15000.0, 0.0, 426.3968, 426.397 + 0.1, 15000.0, 0.05, 673.4, 410.4 + 0.1, 15000.0, 0.07, 943.0822, 459.506 + 0.1, 15000.0, 0.09, 1212.72, 510.069 + 0.1, 15000.0, 0.11, 1482.315, 561.963 + 0.1, 15000.0, 0.13, 1751.869, 615.062 + 0.1, 15000.0, 0.15, 2021.382, 669.243 + 0.1, 15000.0, 0.17, 2290.857, 724.379 + 0.1, 15000.0, 0.19, 2560.295, 780.345 + 0.1, 15000.0, 0.21, 2829.697, 837.016 + 0.1, 15000.0, 0.23, 3099.064, 894.266 + 0.1, 15000.0, 0.25, 3368.399, 951.971 + 0.1, 15000.0, 0.27, 3637.702, 1010.01 + 0.1, 15000.0, 0.29, 3906.974, 1068.24 + 0.1, 15000.0, 0.31, 4176.198, 1125.67 + 0.1, 15000.0, 0.33, 4445.38, 1182.37 + 0.1, 15000.0, 0.35, 4714.55, 1239.55 + 0.1, 15000.0, 0.37, 4983.72, 1297.51 + 0.1, 15000.0, 0.39, 5252.902, 1356.57 + 0.1, 15000.0, 0.41, 5522.064, 1418.27 + 0.1, 15000.0, 0.43, 5791.229, 1482.64 + 0.1, 15000.0, 0.45, 6060.469, 1548.1 + 0.1, 15000.0, 0.47, 6329.814, 1614.36 + 0.1, 15000.0, 0.49, 6599.297, 1681.13 + 0.1, 15000.0, 0.51, 6868.97, 1746.57 + 0.1, 15000.0, 0.53, 7138.859, 1810.77 + 0.1, 15000.0, 0.55, 7408.962, 1875.66 + 0.1, 15000.0, 0.57, 7679.302, 1941.69 + 0.1, 15000.0, 0.59, 7949.899, 2009.28 + 0.1, 15000.0, 0.61, 8221.314, 2081.14 + 0.1, 15000.0, 0.63, 8493.438, 2157.15 + 0.1, 15000.0, 0.65, 8765.487, 2234.38 + 0.1, 15000.0, 0.67, 9037.221, 2312.15 + 0.1, 15000.0, 0.69, 9308.397, 2389.82 + 0.1, 15000.0, 0.71, 9577.668, 2463.53 + 0.1, 15000.0, 0.73, 9845.061, 2533.39 + 0.1, 15000.0, 0.75, 10111.97, 2603.44 + 0.1, 15000.0, 0.77, 10378.71, 2674.58 + 0.1, 15000.0, 0.79, 10645.55, 2747.66 + 0.1, 15000.0, 0.81, 10913.68, 2826.48 + 0.1, 15000.0, 0.83, 11183.18, 2911.22 + 0.1, 15000.0, 0.85, 11453.03, 2998.4 + 0.1, 15000.0, 0.87, 11723.1, 3087.49 + 0.1, 15000.0, 0.89, 11993.24, 3177.93 + 0.1, 15000.0, 0.91, 12263.33, 3269.2 + 0.1, 15000.0, 0.93, 12533.22, 3360.75 + 0.1, 15000.0, 0.95, 12802.79, 3452.02 + 0.1, 15000.0, 0.97, 13071.9, 3542.5 + 0.1, 15000.0, 0.99, 13340.41, 3631.62 + 0.1, 20000.0, 0.0, 354.1852, 354.185 + 0.1, 20000.0, 0.05, 553.2, 308.6 + 0.1, 20000.0, 0.07, 775.1521, 351.291 + 0.1, 20000.0, 0.09, 997.1138, 393.73 + 0.1, 20000.0, 0.11, 1219.081, 436.041 + 0.1, 20000.0, 0.13, 1441.051, 478.344 + 0.1, 20000.0, 0.15, 1663.018, 520.761 + 0.1, 20000.0, 0.17, 1884.979, 563.413 + 0.1, 20000.0, 0.19, 2106.93, 606.423 + 0.1, 20000.0, 0.21, 2328.866, 649.912 + 0.1, 20000.0, 0.23, 2550.785, 694.001 + 0.1, 20000.0, 0.25, 2772.681, 738.813 + 0.1, 20000.0, 0.27, 2994.552, 784.468 + 0.1, 20000.0, 0.29, 3216.392, 831.089 + 0.1, 20000.0, 0.31, 3438.21, 879.634 + 0.1, 20000.0, 0.33, 3659.999, 930.022 + 0.1, 20000.0, 0.35, 3881.737, 981.131 + 0.1, 20000.0, 0.37, 4103.416, 1032.68 + 0.1, 20000.0, 0.39, 4325.025, 1084.38 + 0.1, 20000.0, 0.41, 4546.508, 1134.81 + 0.1, 20000.0, 0.43, 4767.868, 1183.97 + 0.1, 20000.0, 0.45, 4989.162, 1233.26 + 0.1, 20000.0, 0.47, 5210.405, 1282.94 + 0.1, 20000.0, 0.49, 5431.609, 1333.29 + 0.1, 20000.0, 0.51, 5652.639, 1385.54 + 0.1, 20000.0, 0.53, 5873.545, 1439.71 + 0.1, 20000.0, 0.55, 6094.556, 1494.66 + 0.1, 20000.0, 0.57, 6315.758, 1550.18 + 0.1, 20000.0, 0.59, 6537.233, 1606.07 + 0.1, 20000.0, 0.61, 6759.463, 1660.92 + 0.1, 20000.0, 0.63, 6982.434, 1714.82 + 0.1, 20000.0, 0.65, 7205.644, 1769.4 + 0.1, 20000.0, 0.67, 7428.983, 1825.05 + 0.1, 20000.0, 0.69, 7652.345, 1882.17 + 0.1, 20000.0, 0.71, 7875.63, 1942.56 + 0.1, 20000.0, 0.73, 8098.729, 2006.28 + 0.1, 20000.0, 0.75, 8321.519, 2071.63 + 0.1, 20000.0, 0.77, 8543.886, 2138.34 + 0.1, 20000.0, 0.79, 8765.719, 2206.11 + 0.1, 20000.0, 0.81, 8986.043, 2274.29 + 0.1, 20000.0, 0.83, 9204.954, 2342.69 + 0.1, 20000.0, 0.85, 9423.619, 2411.56 + 0.1, 20000.0, 0.87, 9642.341, 2480.8 + 0.1, 20000.0, 0.89, 9861.426, 2550.29 + 0.1, 20000.0, 0.91, 10081.18, 2619.93 + 0.1, 20000.0, 0.93, 10301.9, 2689.61 + 0.1, 20000.0, 0.95, 10523.91, 2759.21 + 0.1, 20000.0, 0.97, 10747.49, 2828.64 + 0.1, 20000.0, 0.99, 10972.96, 2897.77 + 0.1, 25000.0, 0.0, 292.022, 292.022 + 0.1, 25000.0, 0.05, 453.7, 250.4 + 0.1, 25000.0, 0.07, 630.0592, 309.19 + 0.1, 25000.0, 0.09, 807.3519, 359.172 + 0.1, 25000.0, 0.11, 985.4875, 401.543 + 0.1, 25000.0, 0.13, 1164.375, 437.499 + 0.1, 25000.0, 0.15, 1343.925, 468.236 + 0.1, 25000.0, 0.17, 1524.046, 494.951 + 0.1, 25000.0, 0.19, 1704.647, 518.841 + 0.1, 25000.0, 0.21, 1885.639, 541.102 + 0.1, 25000.0, 0.23, 2066.93, 562.93 + 0.1, 25000.0, 0.25, 2248.43, 585.523 + 0.1, 25000.0, 0.27, 2430.048, 610.076 + 0.1, 25000.0, 0.29, 2611.695, 637.787 + 0.1, 25000.0, 0.31, 2793.219, 675.074 + 0.1, 25000.0, 0.33, 2974.544, 721.869 + 0.1, 25000.0, 0.35, 3155.669, 771.612 + 0.1, 25000.0, 0.37, 3336.532, 822.967 + 0.1, 25000.0, 0.39, 3517.071, 874.598 + 0.1, 25000.0, 0.41, 3696.968, 922.648 + 0.1, 25000.0, 0.43, 3876.223, 966.392 + 0.1, 25000.0, 0.45, 4055.156, 1008.24 + 0.1, 25000.0, 0.47, 4233.832, 1048.07 + 0.1, 25000.0, 0.49, 4412.313, 1085.78 + 0.1, 25000.0, 0.51, 4590.575, 1117.58 + 0.1, 25000.0, 0.53, 4768.702, 1144.25 + 0.1, 25000.0, 0.55, 4946.887, 1171.12 + 0.1, 25000.0, 0.57, 5125.237, 1199.86 + 0.1, 25000.0, 0.59, 5303.856, 1232.12 + 0.1, 25000.0, 0.61, 5483.064, 1276.0 + 0.1, 25000.0, 0.63, 5662.913, 1331.59 + 0.1, 25000.0, 0.65, 5843.194, 1391.04 + 0.1, 25000.0, 0.67, 6023.909, 1452.92 + 0.1, 25000.0, 0.69, 6205.06, 1515.76 + 0.1, 25000.0, 0.71, 6387.025, 1574.97 + 0.1, 25000.0, 0.73, 6569.714, 1629.86 + 0.1, 25000.0, 0.75, 6752.575, 1683.69 + 0.1, 25000.0, 0.77, 6935.428, 1736.57 + 0.1, 25000.0, 0.79, 7118.093, 1788.59 + 0.1, 25000.0, 0.81, 7300.178, 1839.59 + 0.1, 25000.0, 0.83, 7481.555, 1889.73 + 0.1, 25000.0, 0.85, 7662.362, 1939.46 + 0.1, 25000.0, 0.87, 7842.526, 1989.0 + 0.1, 25000.0, 0.89, 8021.971, 2038.55 + 0.1, 25000.0, 0.91, 8200.621, 2088.33 + 0.1, 25000.0, 0.93, 8378.402, 2138.55 + 0.1, 25000.0, 0.95, 8555.238, 2189.41 + 0.1, 25000.0, 0.97, 8731.053, 2241.14 + 0.1, 25000.0, 0.99, 8905.774, 2293.93 + 0.1, 30000.0, 0.0, 238.8354, 238.835 + 0.1, 30000.0, 0.05, 326.6, 200.8 + 0.1, 30000.0, 0.07, 460.7024, 221.759 + 0.1, 30000.0, 0.09, 593.8098, 242.738 + 0.1, 30000.0, 0.11, 726.0537, 263.754 + 0.1, 30000.0, 0.13, 857.5661, 284.827 + 0.1, 30000.0, 0.15, 988.4786, 305.975 + 0.1, 30000.0, 0.17, 1118.923, 327.218 + 0.1, 30000.0, 0.19, 1249.031, 348.574 + 0.1, 30000.0, 0.21, 1378.934, 370.062 + 0.1, 30000.0, 0.23, 1508.765, 391.701 + 0.1, 30000.0, 0.25, 1638.654, 413.51 + 0.1, 30000.0, 0.27, 1768.734, 435.508 + 0.1, 30000.0, 0.29, 1899.137, 457.713 + 0.1, 30000.0, 0.31, 2030.628, 479.901 + 0.1, 30000.0, 0.33, 2163.186, 502.148 + 0.1, 30000.0, 0.35, 2296.0, 524.837 + 0.1, 30000.0, 0.37, 2428.894, 548.107 + 0.1, 30000.0, 0.39, 2561.692, 572.094 + 0.1, 30000.0, 0.41, 2693.794, 597.981 + 0.1, 30000.0, 0.43, 2825.127, 625.652 + 0.1, 30000.0, 0.45, 2956.144, 653.694 + 0.1, 30000.0, 0.47, 3086.875, 681.737 + 0.1, 30000.0, 0.49, 3217.35, 709.414 + 0.1, 30000.0, 0.51, 3347.371, 734.994 + 0.1, 30000.0, 0.53, 3477.025, 758.439 + 0.1, 30000.0, 0.55, 3606.675, 781.4 + 0.1, 30000.0, 0.57, 3736.461, 804.169 + 0.1, 30000.0, 0.59, 3866.523, 827.038 + 0.1, 30000.0, 0.61, 3997.584, 850.636 + 0.1, 30000.0, 0.63, 4129.643, 875.174 + 0.1, 30000.0, 0.65, 4261.969, 900.438 + 0.1, 30000.0, 0.67, 4394.416, 926.553 + 0.1, 30000.0, 0.69, 4526.841, 953.647 + 0.1, 30000.0, 0.71, 4658.566, 983.093 + 0.1, 30000.0, 0.73, 4789.574, 1014.71 + 0.1, 30000.0, 0.75, 4920.513, 1046.79 + 0.1, 30000.0, 0.77, 5051.495, 1078.83 + 0.1, 30000.0, 0.79, 5182.635, 1110.37 + 0.1, 30000.0, 0.81, 5314.588, 1138.18 + 0.1, 30000.0, 0.83, 5447.335, 1162.44 + 0.1, 30000.0, 0.85, 5580.188, 1186.76 + 0.1, 30000.0, 0.87, 5712.996, 1211.99 + 0.1, 30000.0, 0.89, 5845.611, 1238.98 + 0.1, 30000.0, 0.91, 5977.885, 1268.58 + 0.1, 30000.0, 0.93, 6109.668, 1301.65 + 0.1, 30000.0, 0.95, 6240.813, 1339.04 + 0.1, 30000.0, 0.97, 6371.169, 1381.6 + 0.1, 30000.0, 0.99, 6500.588, 1430.18 + 0.1, 35000.0, 0.0, 193.6292, 193.629 + 0.1, 35000.0, 0.05, 314.5, 276.8 + 0.1, 35000.0, 0.07, 448.5241, 284.181 + 0.1, 35000.0, 0.09, 584.2434, 294.281 + 0.1, 35000.0, 0.11, 721.4789, 306.938 + 0.1, 35000.0, 0.13, 860.0515, 321.99 + 0.1, 35000.0, 0.15, 999.7821, 339.275 + 0.1, 35000.0, 0.17, 1140.492, 358.632 + 0.1, 35000.0, 0.19, 1282.001, 379.9 + 0.1, 35000.0, 0.21, 1424.132, 402.917 + 0.1, 35000.0, 0.23, 1566.704, 427.521 + 0.1, 35000.0, 0.25, 1709.539, 453.55 + 0.1, 35000.0, 0.27, 1852.457, 480.843 + 0.1, 35000.0, 0.29, 1995.28, 509.239 + 0.1, 35000.0, 0.31, 2137.631, 540.029 + 0.1, 35000.0, 0.33, 2279.379, 572.7 + 0.1, 35000.0, 0.35, 2420.638, 604.931 + 0.1, 35000.0, 0.37, 2561.324, 635.856 + 0.1, 35000.0, 0.39, 2701.356, 664.609 + 0.1, 35000.0, 0.41, 2840.585, 683.631 + 0.1, 35000.0, 0.43, 2978.943, 693.677 + 0.1, 35000.0, 0.45, 3116.444, 703.819 + 0.1, 35000.0, 0.47, 3253.034, 716.435 + 0.1, 35000.0, 0.49, 3388.663, 733.903 + 0.1, 35000.0, 0.51, 3522.314, 768.888 + 0.1, 35000.0, 0.53, 3654.169, 821.275 + 0.1, 35000.0, 0.55, 3785.606, 878.169 + 0.1, 35000.0, 0.57, 3917.042, 936.96 + 0.1, 35000.0, 0.59, 4048.891, 995.041 + 0.1, 35000.0, 0.61, 4183.299, 1044.47 + 0.1, 35000.0, 0.63, 4320.262, 1083.93 + 0.1, 35000.0, 0.65, 4457.625, 1118.72 + 0.1, 35000.0, 0.67, 4594.964, 1148.84 + 0.1, 35000.0, 0.69, 4731.855, 1174.26 + 0.1, 35000.0, 0.71, 4865.633, 1189.49 + 0.1, 35000.0, 0.73, 4996.418, 1195.84 + 0.1, 35000.0, 0.75, 5127.113, 1201.39 + 0.1, 35000.0, 0.77, 5258.379, 1208.77 + 0.1, 35000.0, 0.79, 5390.88, 1220.6 + 0.1, 35000.0, 0.81, 5527.861, 1249.87 + 0.1, 35000.0, 0.83, 5669.359, 1296.7 + 0.1, 35000.0, 0.85, 5812.2, 1348.31 + 0.1, 35000.0, 0.87, 5955.793, 1402.3 + 0.1, 35000.0, 0.89, 6099.547, 1456.27 + 0.1, 35000.0, 0.91, 6242.872, 1507.82 + 0.1, 35000.0, 0.93, 6385.178, 1554.55 + 0.1, 35000.0, 0.95, 6525.875, 1594.04 + 0.1, 35000.0, 0.97, 6664.372, 1623.91 + 0.1, 35000.0, 0.99, 6800.078, 1641.75 + 0.1, 40000.0, 0.0, 153.2386, 153.239 + 0.1, 40000.0, 0.05, 287.5, 192.9 + 0.1, 40000.0, 0.07, 393.1405, 231.807 + 0.1, 40000.0, 0.09, 498.2982, 262.736 + 0.1, 40000.0, 0.11, 603.178, 286.839 + 0.1, 40000.0, 0.13, 707.9853, 305.267 + 0.1, 40000.0, 0.15, 812.925, 319.171 + 0.1, 40000.0, 0.17, 918.2023, 329.704 + 0.1, 40000.0, 0.19, 1024.022, 338.017 + 0.1, 40000.0, 0.21, 1130.59, 345.26 + 0.1, 40000.0, 0.23, 1238.111, 352.586 + 0.1, 40000.0, 0.25, 1346.79, 361.146 + 0.1, 40000.0, 0.27, 1456.832, 372.091 + 0.1, 40000.0, 0.29, 1568.443, 386.573 + 0.1, 40000.0, 0.31, 1683.947, 412.415 + 0.1, 40000.0, 0.33, 1803.037, 449.15 + 0.1, 40000.0, 0.35, 1922.769, 488.025 + 0.1, 40000.0, 0.37, 2042.318, 526.956 + 0.1, 40000.0, 0.39, 2160.862, 563.859 + 0.1, 40000.0, 0.41, 2274.956, 587.723 + 0.1, 40000.0, 0.43, 2384.412, 598.628 + 0.1, 40000.0, 0.45, 2492.3, 607.75 + 0.1, 40000.0, 0.47, 2599.068, 617.336 + 0.1, 40000.0, 0.49, 2705.164, 629.633 + 0.1, 40000.0, 0.51, 2810.888, 656.785 + 0.1, 40000.0, 0.53, 2916.723, 698.639 + 0.1, 40000.0, 0.55, 3023.338, 742.744 + 0.1, 40000.0, 0.57, 3131.253, 786.546 + 0.1, 40000.0, 0.59, 3240.988, 827.494 + 0.1, 40000.0, 0.61, 3356.128, 854.837 + 0.1, 40000.0, 0.63, 3476.451, 868.01 + 0.1, 40000.0, 0.65, 3597.925, 876.631 + 0.1, 40000.0, 0.67, 3719.583, 882.122 + 0.1, 40000.0, 0.69, 3840.458, 885.905 + 0.1, 40000.0, 0.71, 3957.144, 888.101 + 0.1, 40000.0, 0.73, 4069.266, 890.446 + 0.1, 40000.0, 0.75, 4179.481, 896.294 + 0.1, 40000.0, 0.77, 4288.007, 907.695 + 0.1, 40000.0, 0.79, 4395.059, 926.703 + 0.1, 40000.0, 0.81, 4499.584, 968.342 + 0.1, 40000.0, 0.83, 4602.107, 1031.52 + 0.1, 40000.0, 0.85, 4704.731, 1099.02 + 0.1, 40000.0, 0.87, 4808.29, 1166.62 + 0.1, 40000.0, 0.89, 4913.615, 1230.06 + 0.1, 40000.0, 0.91, 5021.539, 1285.11 + 0.1, 40000.0, 0.93, 5132.896, 1327.54 + 0.1, 40000.0, 0.95, 5248.519, 1353.1 + 0.1, 40000.0, 0.97, 5369.239, 1357.56 + 0.1, 40000.0, 0.99, 5495.89, 1336.67 + 0.1, 43000.0, 0.0, 132.738, 132.738 + 0.1, 43000.0, 0.05, 175.7, 244.9 + 0.1, 43000.0, 0.07, 326.6245, 292.718 + 0.1, 43000.0, 0.09, 460.6116, 332.696 + 0.1, 43000.0, 0.11, 579.8211, 365.458 + 0.1, 43000.0, 0.13, 686.4128, 391.626 + 0.1, 43000.0, 0.15, 782.5464, 411.825 + 0.1, 43000.0, 0.17, 870.3818, 426.678 + 0.1, 43000.0, 0.19, 952.0786, 436.81 + 0.1, 43000.0, 0.21, 1029.797, 442.843 + 0.1, 43000.0, 0.23, 1105.696, 445.402 + 0.1, 43000.0, 0.25, 1181.936, 445.11 + 0.1, 43000.0, 0.27, 1260.676, 442.591 + 0.1, 43000.0, 0.29, 1344.077, 438.468 + 0.1, 43000.0, 0.31, 1445.27, 428.558 + 0.1, 43000.0, 0.33, 1563.755, 414.65 + 0.1, 43000.0, 0.35, 1685.4, 404.506 + 0.1, 43000.0, 0.37, 1807.045, 401.08 + 0.1, 43000.0, 0.39, 1925.53, 407.326 + 0.1, 43000.0, 0.41, 2025.988, 448.027 + 0.1, 43000.0, 0.43, 2108.098, 520.846 + 0.1, 43000.0, 0.45, 2186.081, 596.325 + 0.1, 43000.0, 0.47, 2262.455, 666.836 + 0.1, 43000.0, 0.49, 2339.734, 724.751 + 0.1, 43000.0, 0.51, 2428.758, 729.698 + 0.1, 43000.0, 0.53, 2530.025, 681.988 + 0.1, 43000.0, 0.55, 2633.694, 622.606 + 0.1, 43000.0, 0.57, 2738.244, 559.798 + 0.1, 43000.0, 0.59, 2842.157, 501.81 + 0.1, 43000.0, 0.61, 2938.375, 478.53 + 0.1, 43000.0, 0.63, 3026.721, 492.957 + 0.1, 43000.0, 0.65, 3113.9, 521.2 + 0.1, 43000.0, 0.67, 3201.079, 561.011 + 0.1, 43000.0, 0.69, 3289.425, 610.142 + 0.1, 43000.0, 0.71, 3385.643, 668.906 + 0.1, 43000.0, 0.73, 3489.556, 734.434 + 0.1, 43000.0, 0.75, 3594.106, 800.675 + 0.1, 43000.0, 0.77, 3697.775, 864.14 + 0.1, 43000.0, 0.79, 3799.042, 921.34 + 0.1, 43000.0, 0.81, 3889.996, 954.768 + 0.1, 43000.0, 0.83, 3970.669, 964.332 + 0.1, 43000.0, 0.85, 4049.031, 967.356 + 0.1, 43000.0, 0.87, 4126.664, 967.146 + 0.1, 43000.0, 0.89, 4205.146, 967.008 + 0.1, 43000.0, 0.91, 4286.059, 970.25 + 0.1, 43000.0, 0.93, 4370.981, 980.176 + 0.1, 43000.0, 0.95, 4461.494, 1000.09 + 0.1, 43000.0, 0.97, 4559.176, 1033.31 + 0.1, 43000.0, 0.99, 4665.609, 1083.13 + 0.1, 48000.0, 0.0, 104.4916, 104.492 + 0.1, 48000.0, 0.05, 172.8, 271.6 + 0.1, 48000.0, 0.07, 285.7628, 301.302 + 0.1, 48000.0, 0.09, 387.8401, 324.276 + 0.1, 48000.0, 0.11, 480.2585, 341.208 + 0.1, 48000.0, 0.13, 564.2446, 352.783 + 0.1, 48000.0, 0.15, 641.025, 359.686 + 0.1, 48000.0, 0.17, 711.8262, 362.602 + 0.1, 48000.0, 0.19, 777.8747, 362.217 + 0.1, 48000.0, 0.21, 840.3971, 359.215 + 0.1, 48000.0, 0.23, 900.62, 354.282 + 0.1, 48000.0, 0.25, 959.77, 348.103 + 0.1, 48000.0, 0.27, 1019.074, 341.363 + 0.1, 48000.0, 0.29, 1079.757, 334.747 + 0.1, 48000.0, 0.31, 1146.155, 327.137 + 0.1, 48000.0, 0.33, 1218.74, 319.654 + 0.1, 48000.0, 0.35, 1294.125, 315.663 + 0.1, 48000.0, 0.37, 1372.03, 316.724 + 0.1, 48000.0, 0.39, 1452.175, 324.397 + 0.1, 48000.0, 0.41, 1534.602, 354.369 + 0.1, 48000.0, 0.43, 1618.952, 404.776 + 0.1, 48000.0, 0.45, 1704.469, 456.2 + 0.1, 48000.0, 0.47, 1790.715, 503.352 + 0.1, 48000.0, 0.49, 1877.256, 540.943 + 0.1, 48000.0, 0.51, 1965.74, 538.616 + 0.1, 48000.0, 0.53, 2055.226, 497.158 + 0.1, 48000.0, 0.55, 2142.181, 448.5 + 0.1, 48000.0, 0.57, 2225.159, 399.506 + 0.1, 48000.0, 0.59, 2302.711, 357.04 + 0.1, 48000.0, 0.61, 2362.06, 350.002 + 0.1, 48000.0, 0.63, 2404.506, 379.913 + 0.1, 48000.0, 0.65, 2445.425, 420.919 + 0.1, 48000.0, 0.67, 2488.864, 469.198 + 0.1, 48000.0, 0.69, 2538.87, 520.932 + 0.1, 48000.0, 0.71, 2617.807, 564.838 + 0.1, 48000.0, 0.73, 2725.281, 598.906 + 0.1, 48000.0, 0.75, 2838.137, 630.394 + 0.1, 48000.0, 0.77, 2951.542, 659.1 + 0.1, 48000.0, 0.79, 3060.66, 684.822 + 0.1, 48000.0, 0.81, 3145.774, 703.548 + 0.1, 48000.0, 0.83, 3205.656, 716.001 + 0.1, 48000.0, 0.85, 3257.569, 727.631 + 0.1, 48000.0, 0.87, 3303.891, 740.084 + 0.1, 48000.0, 0.89, 3347.004, 755.002 + 0.1, 48000.0, 0.91, 3389.286, 774.031 + 0.1, 48000.0, 0.93, 3433.119, 798.813 + 0.1, 48000.0, 0.95, 3480.881, 830.994 + 0.1, 48000.0, 0.97, 3534.954, 872.216 + 0.1, 48000.0, 0.99, 3597.716, 924.125 + 0.15, 0.0, 0.0, 720.6265, 720.626 + 0.15, 0.0, 0.05, 1031.936, 630.366 + 0.15, 0.0, 0.07, 1444.675, 729.93 + 0.15, 0.0, 0.09, 1857.423, 829.862 + 0.15, 0.0, 0.11, 2270.179, 930.191 + 0.15, 0.0, 0.13, 2682.94, 1030.95 + 0.15, 0.0, 0.15, 3095.708, 1132.17 + 0.15, 0.0, 0.17, 3508.48, 1233.87 + 0.15, 0.0, 0.19, 3921.256, 1336.1 + 0.15, 0.0, 0.21, 4334.035, 1438.87 + 0.15, 0.0, 0.23, 4746.815, 1542.23 + 0.15, 0.0, 0.25, 5159.597, 1646.2 + 0.15, 0.0, 0.27, 5572.379, 1750.81 + 0.15, 0.0, 0.29, 5985.16, 1856.1 + 0.15, 0.0, 0.31, 6397.939, 1962.08 + 0.15, 0.0, 0.33, 6810.716, 2068.8 + 0.15, 0.0, 0.35, 7223.489, 2176.29 + 0.15, 0.0, 0.37, 7636.258, 2284.57 + 0.15, 0.0, 0.39, 8049.021, 2393.68 + 0.15, 0.0, 0.41, 8461.768, 2503.57 + 0.15, 0.0, 0.43, 8874.5, 2614.29 + 0.15, 0.0, 0.45, 9287.231, 2725.98 + 0.15, 0.0, 0.47, 9699.965, 2838.71 + 0.15, 0.0, 0.49, 10112.71, 2952.54 + 0.15, 0.0, 0.51, 10525.47, 3067.55 + 0.15, 0.0, 0.53, 10938.27, 3183.81 + 0.15, 0.0, 0.55, 11351.07, 3301.36 + 0.15, 0.0, 0.57, 11763.87, 3420.24 + 0.15, 0.0, 0.59, 12176.68, 3540.52 + 0.15, 0.0, 0.61, 12589.47, 3662.41 + 0.15, 0.0, 0.63, 13002.26, 3785.93 + 0.15, 0.0, 0.65, 13415.04, 3910.9 + 0.15, 0.0, 0.67, 13827.82, 4037.28 + 0.15, 0.0, 0.69, 14240.59, 4165.05 + 0.15, 0.0, 0.71, 14653.36, 4294.19 + 0.15, 0.0, 0.73, 15066.12, 4424.67 + 0.15, 0.0, 0.75, 15478.88, 4556.46 + 0.15, 0.0, 0.77, 15891.64, 4689.55 + 0.15, 0.0, 0.79, 16304.42, 4823.91 + 0.15, 0.0, 0.81, 16717.21, 4959.2 + 0.15, 0.0, 0.83, 17130.04, 5095.46 + 0.15, 0.0, 0.85, 17542.86, 5233.17 + 0.15, 0.0, 0.87, 17955.68, 5372.45 + 0.15, 0.0, 0.89, 18368.5, 5513.45 + 0.15, 0.0, 0.91, 18781.3, 5656.29 + 0.15, 0.0, 0.93, 19194.08, 5801.12 + 0.15, 0.0, 0.95, 19606.84, 5948.07 + 0.15, 0.0, 0.97, 20019.57, 6097.28 + 0.15, 0.0, 0.99, 20432.27, 6248.87 + 0.15, 2000.0, 0.0, 674.705, 674.705 + 0.15, 2000.0, 0.05, 989.1663, 595.674 + 0.15, 2000.0, 0.07, 1384.964, 690.324 + 0.15, 2000.0, 0.09, 1780.753, 785.324 + 0.15, 2000.0, 0.11, 2176.535, 880.706 + 0.15, 2000.0, 0.13, 2572.309, 976.503 + 0.15, 2000.0, 0.15, 2968.076, 1072.75 + 0.15, 2000.0, 0.17, 3363.838, 1169.47 + 0.15, 2000.0, 0.19, 3759.594, 1266.71 + 0.15, 2000.0, 0.21, 4155.345, 1364.5 + 0.15, 2000.0, 0.23, 4551.092, 1462.86 + 0.15, 2000.0, 0.25, 4946.836, 1561.84 + 0.15, 2000.0, 0.27, 5342.577, 1661.45 + 0.15, 2000.0, 0.29, 5738.316, 1761.75 + 0.15, 2000.0, 0.31, 6134.054, 1862.75 + 0.15, 2000.0, 0.33, 6529.79, 1964.5 + 0.15, 2000.0, 0.35, 6925.526, 2067.02 + 0.15, 2000.0, 0.37, 7321.263, 2170.35 + 0.15, 2000.0, 0.39, 7717.001, 2274.52 + 0.15, 2000.0, 0.41, 8112.734, 2379.49 + 0.15, 2000.0, 0.43, 8508.466, 2485.32 + 0.15, 2000.0, 0.45, 8904.205, 2592.13 + 0.15, 2000.0, 0.47, 9299.954, 2700.0 + 0.15, 2000.0, 0.49, 9695.717, 2808.98 + 0.15, 2000.0, 0.51, 10091.53, 2919.19 + 0.15, 2000.0, 0.53, 10487.38, 3030.67 + 0.15, 2000.0, 0.55, 10883.24, 3143.45 + 0.15, 2000.0, 0.57, 11279.08, 3257.56 + 0.15, 2000.0, 0.59, 11674.91, 3373.05 + 0.15, 2000.0, 0.61, 12070.66, 3490.15 + 0.15, 2000.0, 0.63, 12466.33, 3608.86 + 0.15, 2000.0, 0.65, 12861.98, 3728.96 + 0.15, 2000.0, 0.67, 13257.62, 3850.42 + 0.15, 2000.0, 0.69, 13653.27, 3973.2 + 0.15, 2000.0, 0.71, 14048.96, 4097.13 + 0.15, 2000.0, 0.73, 14444.69, 4222.22 + 0.15, 2000.0, 0.75, 14840.43, 4348.59 + 0.15, 2000.0, 0.77, 15236.19, 4476.26 + 0.15, 2000.0, 0.79, 15631.95, 4605.24 + 0.15, 2000.0, 0.81, 16027.7, 4735.33 + 0.15, 2000.0, 0.83, 16423.45, 4866.6 + 0.15, 2000.0, 0.85, 16819.21, 4999.41 + 0.15, 2000.0, 0.87, 17214.96, 5133.87 + 0.15, 2000.0, 0.89, 17610.71, 5270.13 + 0.15, 2000.0, 0.91, 18006.45, 5408.31 + 0.15, 2000.0, 0.93, 18402.2, 5548.54 + 0.15, 2000.0, 0.95, 18797.95, 5690.94 + 0.15, 2000.0, 0.97, 19193.7, 5835.65 + 0.15, 2000.0, 0.99, 19589.44, 5982.79 + 0.15, 5000.0, 0.0, 610.201, 610.201 + 0.15, 5000.0, 0.05, 925.6772, 546.979 + 0.15, 5000.0, 0.07, 1296.146, 634.277 + 0.15, 5000.0, 0.09, 1666.604, 721.93 + 0.15, 5000.0, 0.11, 2037.053, 809.971 + 0.15, 5000.0, 0.13, 2407.493, 898.432 + 0.15, 5000.0, 0.15, 2777.925, 987.345 + 0.15, 5000.0, 0.17, 3148.35, 1076.74 + 0.15, 5000.0, 0.19, 3518.768, 1166.66 + 0.15, 5000.0, 0.21, 3889.181, 1257.12 + 0.15, 5000.0, 0.23, 4259.588, 1348.17 + 0.15, 5000.0, 0.25, 4629.991, 1439.83 + 0.15, 5000.0, 0.27, 5000.391, 1532.14 + 0.15, 5000.0, 0.29, 5370.787, 1625.13 + 0.15, 5000.0, 0.31, 5741.182, 1718.83 + 0.15, 5000.0, 0.33, 6111.576, 1813.27 + 0.15, 5000.0, 0.35, 6481.969, 1908.49 + 0.15, 5000.0, 0.37, 6852.363, 2004.52 + 0.15, 5000.0, 0.39, 7222.757, 2101.38 + 0.15, 5000.0, 0.41, 7593.157, 2199.05 + 0.15, 5000.0, 0.43, 7963.563, 2297.55 + 0.15, 5000.0, 0.45, 8333.969, 2397.05 + 0.15, 5000.0, 0.47, 8704.375, 2497.62 + 0.15, 5000.0, 0.49, 9074.779, 2599.34 + 0.15, 5000.0, 0.51, 9445.168, 2702.37 + 0.15, 5000.0, 0.53, 9815.545, 2806.76 + 0.15, 5000.0, 0.55, 10185.92, 2912.44 + 0.15, 5000.0, 0.57, 10556.31, 3019.44 + 0.15, 5000.0, 0.59, 10926.72, 3127.77 + 0.15, 5000.0, 0.61, 11297.17, 3237.62 + 0.15, 5000.0, 0.63, 11667.68, 3348.97 + 0.15, 5000.0, 0.65, 12038.18, 3461.63 + 0.15, 5000.0, 0.67, 12408.68, 3575.57 + 0.15, 5000.0, 0.69, 12779.16, 3690.73 + 0.15, 5000.0, 0.71, 13149.56, 3806.82 + 0.15, 5000.0, 0.73, 13519.88, 3923.86 + 0.15, 5000.0, 0.75, 13890.19, 4042.18 + 0.15, 5000.0, 0.77, 14260.48, 4161.86 + 0.15, 5000.0, 0.79, 14630.78, 4282.97 + 0.15, 5000.0, 0.81, 15001.14, 4405.65 + 0.15, 5000.0, 0.83, 15371.56, 4529.95 + 0.15, 5000.0, 0.85, 15741.99, 4655.9 + 0.15, 5000.0, 0.87, 16112.43, 4783.55 + 0.15, 5000.0, 0.89, 16482.86, 4912.97 + 0.15, 5000.0, 0.91, 16853.29, 5044.21 + 0.15, 5000.0, 0.93, 17223.7, 5177.33 + 0.15, 5000.0, 0.95, 17594.09, 5312.4 + 0.15, 5000.0, 0.97, 17964.45, 5449.46 + 0.15, 5000.0, 0.99, 18334.77, 5588.58 + 0.15, 10000.0, 0.0, 513.637, 513.637 + 0.15, 10000.0, 0.05, 791.97, 466.888 + 0.15, 10000.0, 0.07, 1109.106, 539.67 + 0.15, 10000.0, 0.09, 1426.223, 612.787 + 0.15, 10000.0, 0.11, 1743.322, 686.268 + 0.15, 10000.0, 0.13, 2060.404, 760.14 + 0.15, 10000.0, 0.15, 2377.471, 834.43 + 0.15, 10000.0, 0.17, 2694.524, 909.167 + 0.15, 10000.0, 0.19, 3011.564, 984.378 + 0.15, 10000.0, 0.21, 3328.593, 1060.09 + 0.15, 10000.0, 0.23, 3645.612, 1136.33 + 0.15, 10000.0, 0.25, 3962.622, 1213.13 + 0.15, 10000.0, 0.27, 4279.626, 1290.51 + 0.15, 10000.0, 0.29, 4596.623, 1368.51 + 0.15, 10000.0, 0.31, 4913.616, 1447.14 + 0.15, 10000.0, 0.33, 5230.606, 1526.44 + 0.15, 10000.0, 0.35, 5547.594, 1606.43 + 0.15, 10000.0, 0.37, 5864.581, 1687.15 + 0.15, 10000.0, 0.39, 6181.57, 1768.61 + 0.15, 10000.0, 0.41, 6498.562, 1850.77 + 0.15, 10000.0, 0.43, 6815.558, 1933.68 + 0.15, 10000.0, 0.45, 7132.558, 2017.48 + 0.15, 10000.0, 0.47, 7449.564, 2102.23 + 0.15, 10000.0, 0.49, 7766.576, 2188.01 + 0.15, 10000.0, 0.51, 8083.606, 2275.0 + 0.15, 10000.0, 0.53, 8400.652, 2363.26 + 0.15, 10000.0, 0.55, 8717.699, 2452.64 + 0.15, 10000.0, 0.57, 9034.744, 2543.16 + 0.15, 10000.0, 0.59, 9351.781, 2634.81 + 0.15, 10000.0, 0.61, 9668.788, 2727.65 + 0.15, 10000.0, 0.63, 9985.766, 2821.67 + 0.15, 10000.0, 0.65, 10302.74, 2916.8 + 0.15, 10000.0, 0.67, 10619.71, 3013.01 + 0.15, 10000.0, 0.69, 10936.68, 3110.3 + 0.15, 10000.0, 0.71, 11253.67, 3208.41 + 0.15, 10000.0, 0.73, 11570.68, 3307.36 + 0.15, 10000.0, 0.75, 11887.7, 3407.49 + 0.15, 10000.0, 0.77, 12204.72, 3508.89 + 0.15, 10000.0, 0.79, 12521.75, 3611.65 + 0.15, 10000.0, 0.81, 12838.78, 3716.11 + 0.15, 10000.0, 0.83, 13155.81, 3822.3 + 0.15, 10000.0, 0.85, 13472.84, 3929.95 + 0.15, 10000.0, 0.87, 13789.86, 4039.01 + 0.15, 10000.0, 0.89, 14106.88, 4149.48 + 0.15, 10000.0, 0.91, 14423.9, 4261.3 + 0.15, 10000.0, 0.93, 14740.9, 4374.46 + 0.15, 10000.0, 0.95, 15057.89, 4488.92 + 0.15, 10000.0, 0.97, 15374.87, 4604.66 + 0.15, 10000.0, 0.99, 15691.83, 4721.64 + 0.15, 15000.0, 0.0, 429.5964, 429.596 + 0.15, 15000.0, 0.05, 645.8438, 414.738 + 0.15, 15000.0, 0.07, 904.3701, 469.965 + 0.15, 15000.0, 0.09, 1162.865, 525.877 + 0.15, 15000.0, 0.11, 1421.331, 582.428 + 0.15, 15000.0, 0.13, 1679.768, 639.574 + 0.15, 15000.0, 0.15, 1938.179, 697.269 + 0.15, 15000.0, 0.17, 2196.565, 755.469 + 0.15, 15000.0, 0.19, 2454.927, 814.13 + 0.15, 15000.0, 0.21, 2713.268, 873.206 + 0.15, 15000.0, 0.23, 2971.587, 932.653 + 0.15, 15000.0, 0.25, 3229.889, 992.427 + 0.15, 15000.0, 0.27, 3488.172, 1052.48 + 0.15, 15000.0, 0.29, 3746.44, 1112.77 + 0.15, 15000.0, 0.31, 4004.686, 1172.78 + 0.15, 15000.0, 0.33, 4262.913, 1232.57 + 0.15, 15000.0, 0.35, 4521.134, 1292.81 + 0.15, 15000.0, 0.37, 4779.356, 1353.69 + 0.15, 15000.0, 0.39, 5037.583, 1415.39 + 0.15, 15000.0, 0.41, 5295.791, 1478.81 + 0.15, 15000.0, 0.43, 5553.994, 1543.95 + 0.15, 15000.0, 0.45, 5812.239, 1609.97 + 0.15, 15000.0, 0.47, 6070.547, 1676.71 + 0.15, 15000.0, 0.49, 6328.937, 1744.02 + 0.15, 15000.0, 0.51, 6587.449, 1810.9 + 0.15, 15000.0, 0.53, 6846.098, 1877.4 + 0.15, 15000.0, 0.55, 7104.872, 1944.62 + 0.15, 15000.0, 0.57, 7363.781, 2012.81 + 0.15, 15000.0, 0.59, 7622.835, 2082.23 + 0.15, 15000.0, 0.61, 7882.34, 2154.44 + 0.15, 15000.0, 0.63, 8142.235, 2229.39 + 0.15, 15000.0, 0.65, 8402.087, 2305.36 + 0.15, 15000.0, 0.67, 8661.759, 2381.95 + 0.15, 15000.0, 0.69, 8921.118, 2458.77 + 0.15, 15000.0, 0.71, 9179.408, 2533.5 + 0.15, 15000.0, 0.73, 9436.643, 2606.21 + 0.15, 15000.0, 0.75, 9693.612, 2679.38 + 0.15, 15000.0, 0.77, 9950.478, 2753.57 + 0.15, 15000.0, 0.79, 10207.41, 2829.33 + 0.15, 15000.0, 0.81, 10465.08, 2909.07 + 0.15, 15000.0, 0.83, 10723.52, 2992.89 + 0.15, 15000.0, 0.85, 10982.16, 3078.57 + 0.15, 15000.0, 0.87, 11240.91, 3165.74 + 0.15, 15000.0, 0.89, 11499.7, 3254.04 + 0.15, 15000.0, 0.91, 11758.44, 3343.13 + 0.15, 15000.0, 0.93, 12017.06, 3432.64 + 0.15, 15000.0, 0.95, 12275.47, 3522.21 + 0.15, 15000.0, 0.97, 12533.6, 3611.49 + 0.15, 15000.0, 0.99, 12791.36, 3700.12 + 0.15, 20000.0, 0.0, 356.8429, 356.843 + 0.15, 20000.0, 0.05, 531.6187, 325.644 + 0.15, 20000.0, 0.07, 744.7175, 371.919 + 0.15, 20000.0, 0.09, 957.8277, 417.849 + 0.15, 20000.0, 0.11, 1170.946, 463.54 + 0.15, 20000.0, 0.13, 1384.069, 509.098 + 0.15, 20000.0, 0.15, 1597.193, 554.631 + 0.15, 20000.0, 0.17, 1810.316, 600.245 + 0.15, 20000.0, 0.19, 2023.432, 646.046 + 0.15, 20000.0, 0.21, 2236.54, 692.141 + 0.15, 20000.0, 0.23, 2449.636, 738.636 + 0.15, 20000.0, 0.25, 2662.716, 785.639 + 0.15, 20000.0, 0.27, 2875.777, 833.255 + 0.15, 20000.0, 0.29, 3088.815, 881.591 + 0.15, 20000.0, 0.31, 3301.833, 931.377 + 0.15, 20000.0, 0.33, 3514.825, 982.569 + 0.15, 20000.0, 0.35, 3727.781, 1034.35 + 0.15, 20000.0, 0.37, 3940.695, 1086.52 + 0.15, 20000.0, 0.39, 4153.562, 1138.88 + 0.15, 20000.0, 0.41, 4366.345, 1190.4 + 0.15, 20000.0, 0.43, 4579.046, 1241.09 + 0.15, 20000.0, 0.45, 4791.703, 1292.0 + 0.15, 20000.0, 0.47, 5004.326, 1343.34 + 0.15, 20000.0, 0.49, 5216.922, 1395.33 + 0.15, 20000.0, 0.51, 5429.4, 1448.94 + 0.15, 20000.0, 0.53, 5641.794, 1504.22 + 0.15, 20000.0, 0.55, 5854.26, 1560.21 + 0.15, 20000.0, 0.57, 6066.854, 1616.75 + 0.15, 20000.0, 0.59, 6279.635, 1673.67 + 0.15, 20000.0, 0.61, 6492.929, 1729.85 + 0.15, 20000.0, 0.63, 6706.727, 1785.35 + 0.15, 20000.0, 0.65, 6920.686, 1841.45 + 0.15, 20000.0, 0.67, 7134.73, 1898.46 + 0.15, 20000.0, 0.69, 7348.785, 1956.68 + 0.15, 20000.0, 0.71, 7562.779, 2017.48 + 0.15, 20000.0, 0.73, 7776.636, 2080.92 + 0.15, 20000.0, 0.75, 7990.28, 2145.71 + 0.15, 20000.0, 0.77, 8203.637, 2211.64 + 0.15, 20000.0, 0.79, 8416.631, 2278.51 + 0.15, 20000.0, 0.81, 8628.602, 2345.77 + 0.15, 20000.0, 0.83, 8839.616, 2413.28 + 0.15, 20000.0, 0.85, 9050.469, 2481.34 + 0.15, 20000.0, 0.87, 9261.37, 2549.9 + 0.15, 20000.0, 0.89, 9472.528, 2618.9 + 0.15, 20000.0, 0.91, 9684.152, 2688.31 + 0.15, 20000.0, 0.93, 9896.452, 2758.07 + 0.15, 20000.0, 0.95, 10109.64, 2828.13 + 0.15, 20000.0, 0.97, 10323.91, 2898.45 + 0.15, 20000.0, 0.99, 10539.49, 2968.98 + 0.15, 25000.0, 0.0, 294.2133, 294.213 + 0.15, 25000.0, 0.05, 438.44, 268.76 + 0.15, 25000.0, 0.07, 610.0851, 323.774 + 0.15, 25000.0, 0.09, 782.4077, 372.279 + 0.15, 25000.0, 0.11, 955.3423, 415.158 + 0.15, 25000.0, 0.13, 1128.824, 453.296 + 0.15, 25000.0, 0.15, 1302.786, 487.574 + 0.15, 25000.0, 0.17, 1477.165, 518.876 + 0.15, 25000.0, 0.19, 1651.894, 548.085 + 0.15, 25000.0, 0.21, 1826.909, 576.083 + 0.15, 25000.0, 0.23, 2002.143, 603.755 + 0.15, 25000.0, 0.25, 2177.532, 631.983 + 0.15, 25000.0, 0.27, 2353.009, 661.65 + 0.15, 25000.0, 0.29, 2528.511, 693.639 + 0.15, 25000.0, 0.31, 2703.932, 732.647 + 0.15, 25000.0, 0.33, 2879.217, 778.633 + 0.15, 25000.0, 0.35, 3054.357, 826.816 + 0.15, 25000.0, 0.37, 3229.307, 876.231 + 0.15, 25000.0, 0.39, 3404.018, 925.912 + 0.15, 25000.0, 0.41, 3578.249, 973.035 + 0.15, 25000.0, 0.43, 3751.999, 1017.08 + 0.15, 25000.0, 0.45, 3925.514, 1059.85 + 0.15, 25000.0, 0.47, 4098.842, 1101.27 + 0.15, 25000.0, 0.49, 4272.032, 1141.28 + 0.15, 25000.0, 0.51, 4445.084, 1177.2 + 0.15, 25000.0, 0.53, 4618.059, 1209.61 + 0.15, 25000.0, 0.55, 4791.076, 1242.31 + 0.15, 25000.0, 0.57, 4964.206, 1276.48 + 0.15, 25000.0, 0.59, 5137.521, 1313.32 + 0.15, 25000.0, 0.61, 5311.213, 1358.63 + 0.15, 25000.0, 0.63, 5485.325, 1412.49 + 0.15, 25000.0, 0.65, 5659.747, 1469.27 + 0.15, 25000.0, 0.67, 5834.494, 1527.93 + 0.15, 25000.0, 0.69, 6009.578, 1587.44 + 0.15, 25000.0, 0.71, 6185.338, 1644.51 + 0.15, 25000.0, 0.73, 6361.708, 1698.66 + 0.15, 25000.0, 0.75, 6538.215, 1752.2 + 0.15, 25000.0, 0.77, 6714.714, 1805.19 + 0.15, 25000.0, 0.79, 6891.06, 1857.68 + 0.15, 25000.0, 0.81, 7066.896, 1909.49 + 0.15, 25000.0, 0.83, 7242.126, 1960.72 + 0.15, 25000.0, 0.85, 7416.92, 2011.83 + 0.15, 25000.0, 0.87, 7591.234, 2062.97 + 0.15, 25000.0, 0.89, 7765.024, 2114.35 + 0.15, 25000.0, 0.91, 7938.249, 2166.13 + 0.15, 25000.0, 0.93, 8110.863, 2218.51 + 0.15, 25000.0, 0.95, 8282.825, 2271.65 + 0.15, 25000.0, 0.97, 8454.091, 2325.74 + 0.15, 25000.0, 0.99, 8624.617, 2380.97 + 0.15, 30000.0, 0.0, 240.6275, 240.628 + 0.15, 30000.0, 0.05, 327.72, 220.36 + 0.15, 30000.0, 0.07, 461.3582, 245.335 + 0.15, 30000.0, 0.09, 594.2709, 270.267 + 0.15, 30000.0, 0.11, 726.554, 295.178 + 0.15, 30000.0, 0.13, 858.3035, 320.09 + 0.15, 30000.0, 0.15, 989.6154, 345.025 + 0.15, 30000.0, 0.17, 1120.586, 370.005 + 0.15, 30000.0, 0.19, 1251.31, 395.054 + 0.15, 30000.0, 0.21, 1381.885, 420.192 + 0.15, 30000.0, 0.23, 1512.405, 445.442 + 0.15, 30000.0, 0.25, 1642.968, 470.826 + 0.15, 30000.0, 0.27, 1773.67, 496.367 + 0.15, 30000.0, 0.29, 1904.605, 522.086 + 0.15, 30000.0, 0.31, 2036.329, 547.841 + 0.15, 30000.0, 0.33, 2168.827, 573.694 + 0.15, 30000.0, 0.35, 2301.513, 599.912 + 0.15, 30000.0, 0.37, 2434.26, 626.599 + 0.15, 30000.0, 0.39, 2566.943, 653.856 + 0.15, 30000.0, 0.41, 2699.138, 682.507 + 0.15, 30000.0, 0.43, 2830.793, 712.48 + 0.15, 30000.0, 0.45, 2962.217, 742.806 + 0.15, 30000.0, 0.47, 3093.428, 773.237 + 0.15, 30000.0, 0.49, 3224.442, 803.526 + 0.15, 30000.0, 0.51, 3355.085, 832.526 + 0.15, 30000.0, 0.53, 3485.42, 860.207 + 0.15, 30000.0, 0.55, 3615.746, 887.658 + 0.15, 30000.0, 0.57, 3746.173, 915.068 + 0.15, 30000.0, 0.59, 3876.809, 942.626 + 0.15, 30000.0, 0.61, 4008.213, 970.672 + 0.15, 30000.0, 0.63, 4140.386, 999.357 + 0.15, 30000.0, 0.65, 4272.767, 1028.65 + 0.15, 30000.0, 0.67, 4405.248, 1058.66 + 0.15, 30000.0, 0.69, 4537.721, 1089.51 + 0.15, 30000.0, 0.71, 4669.686, 1122.27 + 0.15, 30000.0, 0.73, 4801.13, 1156.84 + 0.15, 30000.0, 0.75, 4932.521, 1191.89 + 0.15, 30000.0, 0.77, 5063.938, 1227.07 + 0.15, 30000.0, 0.79, 5195.463, 1262.03 + 0.15, 30000.0, 0.81, 5327.559, 1294.38 + 0.15, 30000.0, 0.83, 5460.213, 1324.27 + 0.15, 30000.0, 0.85, 5592.933, 1354.34 + 0.15, 30000.0, 0.87, 5725.612, 1385.24 + 0.15, 30000.0, 0.89, 5858.143, 1417.58 + 0.15, 30000.0, 0.91, 5990.42, 1452.0 + 0.15, 30000.0, 0.93, 6122.335, 1489.12 + 0.15, 30000.0, 0.95, 6253.783, 1529.58 + 0.15, 30000.0, 0.97, 6384.654, 1574.0 + 0.15, 30000.0, 0.99, 6514.844, 1623.01 + 0.15, 35000.0, 0.0, 195.0822, 195.082 + 0.15, 35000.0, 0.05, 305.8, 270.45 + 0.15, 35000.0, 0.07, 434.3455, 282.809 + 0.15, 35000.0, 0.09, 564.2098, 297.319 + 0.15, 35000.0, 0.11, 695.2533, 313.85 + 0.15, 35000.0, 0.13, 827.3364, 332.275 + 0.15, 35000.0, 0.15, 960.3196, 352.463 + 0.15, 35000.0, 0.17, 1094.063, 374.285 + 0.15, 35000.0, 0.19, 1228.428, 397.612 + 0.15, 35000.0, 0.21, 1363.275, 422.316 + 0.15, 35000.0, 0.23, 1498.463, 448.266 + 0.15, 35000.0, 0.25, 1633.854, 475.335 + 0.15, 35000.0, 0.27, 1769.307, 503.392 + 0.15, 35000.0, 0.29, 1904.684, 532.309 + 0.15, 35000.0, 0.31, 2039.684, 563.039 + 0.15, 35000.0, 0.33, 2174.206, 595.189 + 0.15, 35000.0, 0.35, 2308.35, 627.025 + 0.15, 35000.0, 0.37, 2442.054, 657.893 + 0.15, 35000.0, 0.39, 2575.256, 687.139 + 0.15, 35000.0, 0.41, 2707.857, 708.99 + 0.15, 35000.0, 0.43, 2839.805, 724.032 + 0.15, 35000.0, 0.45, 2971.094, 739.216 + 0.15, 35000.0, 0.47, 3101.681, 756.371 + 0.15, 35000.0, 0.49, 3231.522, 777.326 + 0.15, 35000.0, 0.51, 3359.809, 811.806 + 0.15, 35000.0, 0.53, 3486.683, 859.727 + 0.15, 35000.0, 0.55, 3613.241, 911.194 + 0.15, 35000.0, 0.57, 3739.809, 964.206 + 0.15, 35000.0, 0.59, 3866.716, 1016.77 + 0.15, 35000.0, 0.61, 3995.674, 1062.77 + 0.15, 35000.0, 0.63, 4126.674, 1101.23 + 0.15, 35000.0, 0.65, 4257.994, 1136.21 + 0.15, 35000.0, 0.67, 4389.292, 1167.71 + 0.15, 35000.0, 0.69, 4520.226, 1195.71 + 0.15, 35000.0, 0.71, 4648.676, 1216.02 + 0.15, 35000.0, 0.73, 4774.73, 1229.65 + 0.15, 35000.0, 0.75, 4900.691, 1242.78 + 0.15, 35000.0, 0.77, 5027.078, 1257.44 + 0.15, 35000.0, 0.79, 5154.414, 1275.64 + 0.15, 35000.0, 0.81, 5285.242, 1307.39 + 0.15, 35000.0, 0.83, 5419.593, 1352.77 + 0.15, 35000.0, 0.85, 5554.984, 1401.93 + 0.15, 35000.0, 0.87, 5690.957, 1453.02 + 0.15, 35000.0, 0.89, 5827.051, 1504.17 + 0.15, 35000.0, 0.91, 5962.807, 1553.55 + 0.15, 35000.0, 0.93, 6097.765, 1599.28 + 0.15, 35000.0, 0.95, 6231.466, 1639.51 + 0.15, 35000.0, 0.97, 6363.449, 1672.39 + 0.15, 35000.0, 0.99, 6493.256, 1696.05 + 0.15, 40000.0, 0.0, 154.3885, 154.388 + 0.15, 40000.0, 0.05, 270.8, 200.25 + 0.15, 40000.0, 0.07, 371.8828, 234.71 + 0.15, 40000.0, 0.09, 472.6153, 263.204 + 0.15, 40000.0, 0.11, 573.1523, 286.599 + 0.15, 40000.0, 0.13, 673.6486, 305.766 + 0.15, 40000.0, 0.15, 774.2589, 321.573 + 0.15, 40000.0, 0.17, 875.1382, 334.891 + 0.15, 40000.0, 0.19, 976.4412, 346.588 + 0.15, 40000.0, 0.21, 1078.323, 357.533 + 0.15, 40000.0, 0.23, 1180.938, 368.597 + 0.15, 40000.0, 0.25, 1284.441, 380.648 + 0.15, 40000.0, 0.27, 1388.987, 394.556 + 0.15, 40000.0, 0.29, 1494.731, 411.189 + 0.15, 40000.0, 0.31, 1603.444, 436.472 + 0.15, 40000.0, 0.33, 1714.89, 470.049 + 0.15, 40000.0, 0.35, 1826.822, 505.284 + 0.15, 40000.0, 0.37, 1938.611, 540.596 + 0.15, 40000.0, 0.39, 2049.628, 574.404 + 0.15, 40000.0, 0.41, 2157.238, 598.333 + 0.15, 40000.0, 0.43, 2261.298, 612.448 + 0.15, 40000.0, 0.45, 2364.156, 625.256 + 0.15, 40000.0, 0.47, 2466.157, 638.471 + 0.15, 40000.0, 0.49, 2567.643, 653.804 + 0.15, 40000.0, 0.51, 2668.841, 680.512 + 0.15, 40000.0, 0.53, 2770.122, 718.48 + 0.15, 40000.0, 0.55, 2872.003, 758.219 + 0.15, 40000.0, 0.57, 2974.883, 797.783 + 0.15, 40000.0, 0.59, 3079.161, 835.229 + 0.15, 40000.0, 0.61, 3187.591, 862.351 + 0.15, 40000.0, 0.63, 3300.001, 878.721 + 0.15, 40000.0, 0.65, 3413.297, 891.691 + 0.15, 40000.0, 0.67, 3526.738, 902.352 + 0.15, 40000.0, 0.69, 3639.583, 911.795 + 0.15, 40000.0, 0.71, 3749.222, 920.11 + 0.15, 40000.0, 0.73, 3855.366, 928.632 + 0.15, 40000.0, 0.75, 3960.05, 939.934 + 0.15, 40000.0, 0.77, 4063.438, 955.594 + 0.15, 40000.0, 0.79, 4165.694, 977.187 + 0.15, 40000.0, 0.81, 4266.009, 1016.27 + 0.15, 40000.0, 0.83, 4364.782, 1072.0 + 0.15, 40000.0, 0.85, 4463.628, 1131.13 + 0.15, 40000.0, 0.87, 4563.185, 1190.4 + 0.15, 40000.0, 0.89, 4664.092, 1246.53 + 0.15, 40000.0, 0.91, 4766.985, 1296.26 + 0.15, 40000.0, 0.93, 4872.503, 1336.33 + 0.15, 40000.0, 0.95, 4981.284, 1363.48 + 0.15, 40000.0, 0.97, 5093.967, 1374.43 + 0.15, 40000.0, 0.99, 5211.188, 1365.92 + 0.15, 43000.0, 0.0, 133.734, 133.734 + 0.15, 43000.0, 0.05, 176.6, 238.7 + 0.15, 43000.0, 0.07, 311.1216, 279.793 + 0.15, 43000.0, 0.09, 432.2471, 314.884 + 0.15, 43000.0, 0.11, 541.6843, 344.444 + 0.15, 43000.0, 0.13, 641.141, 368.947 + 0.15, 43000.0, 0.15, 732.325, 388.864 + 0.15, 43000.0, 0.17, 816.9442, 404.669 + 0.15, 43000.0, 0.19, 896.7065, 416.835 + 0.15, 43000.0, 0.21, 973.3197, 425.833 + 0.15, 43000.0, 0.23, 1048.492, 432.136 + 0.15, 43000.0, 0.25, 1123.93, 436.217 + 0.15, 43000.0, 0.27, 1201.343, 438.549 + 0.15, 43000.0, 0.29, 1282.438, 439.604 + 0.15, 43000.0, 0.31, 1377.597, 435.943 + 0.15, 43000.0, 0.33, 1486.425, 428.988 + 0.15, 43000.0, 0.35, 1597.75, 425.019 + 0.15, 43000.0, 0.37, 1709.075, 426.403 + 0.15, 43000.0, 0.39, 1817.903, 435.51 + 0.15, 43000.0, 0.41, 1912.484, 472.101 + 0.15, 43000.0, 0.43, 1992.564, 534.329 + 0.15, 43000.0, 0.45, 2069.381, 598.737 + 0.15, 43000.0, 0.47, 2144.925, 659.261 + 0.15, 43000.0, 0.49, 2221.182, 709.837 + 0.15, 43000.0, 0.51, 2306.712, 718.391 + 0.15, 43000.0, 0.53, 2401.909, 685.163 + 0.15, 43000.0, 0.55, 2499.006, 642.712 + 0.15, 43000.0, 0.57, 2596.805, 597.586 + 0.15, 43000.0, 0.59, 2694.108, 556.33 + 0.15, 43000.0, 0.61, 2785.358, 542.659 + 0.15, 43000.0, 0.63, 2870.412, 558.959 + 0.15, 43000.0, 0.65, 2954.55, 586.288 + 0.15, 43000.0, 0.67, 3038.688, 622.868 + 0.15, 43000.0, 0.69, 3123.742, 666.924 + 0.15, 43000.0, 0.71, 3214.992, 718.78 + 0.15, 43000.0, 0.73, 3312.295, 776.152 + 0.15, 43000.0, 0.75, 3410.094, 834.144 + 0.15, 43000.0, 0.77, 3507.191, 889.962 + 0.15, 43000.0, 0.79, 3602.388, 940.812 + 0.15, 43000.0, 0.81, 3689.442, 972.64 + 0.15, 43000.0, 0.83, 3768.379, 985.383 + 0.15, 43000.0, 0.85, 3845.494, 992.962 + 0.15, 43000.0, 0.87, 3922.034, 998.041 + 0.15, 43000.0, 0.89, 3999.249, 1003.28 + 0.15, 43000.0, 0.91, 4078.388, 1011.36 + 0.15, 43000.0, 0.93, 4160.699, 1024.92 + 0.15, 43000.0, 0.95, 4247.431, 1046.64 + 0.15, 43000.0, 0.97, 4339.834, 1079.18 + 0.15, 43000.0, 0.99, 4439.155, 1125.2 + 0.15, 48000.0, 0.0, 105.2757, 105.276 + 0.15, 48000.0, 0.05, 166.5, 250.2 + 0.15, 48000.0, 0.07, 267.8252, 276.268 + 0.15, 48000.0, 0.09, 360.5244, 297.164 + 0.15, 48000.0, 0.11, 445.5692, 313.415 + 0.15, 48000.0, 0.13, 523.9312, 325.549 + 0.15, 48000.0, 0.15, 596.5821, 334.093 + 0.15, 48000.0, 0.17, 664.4937, 339.573 + 0.15, 48000.0, 0.19, 728.6374, 342.515 + 0.15, 48000.0, 0.21, 789.985, 343.448 + 0.15, 48000.0, 0.23, 849.5082, 342.898 + 0.15, 48000.0, 0.25, 908.1786, 341.391 + 0.15, 48000.0, 0.27, 966.9678, 339.456 + 0.15, 48000.0, 0.29, 1026.848, 337.618 + 0.15, 48000.0, 0.31, 1091.244, 334.901 + 0.15, 48000.0, 0.33, 1160.534, 332.196 + 0.15, 48000.0, 0.35, 1232.044, 332.263 + 0.15, 48000.0, 0.37, 1305.556, 336.358 + 0.15, 48000.0, 0.39, 1380.852, 345.737 + 0.15, 48000.0, 0.41, 1457.99, 372.917 + 0.15, 48000.0, 0.43, 1536.685, 416.424 + 0.15, 48000.0, 0.45, 1616.306, 460.794 + 0.15, 48000.0, 0.47, 1696.502, 501.821 + 0.15, 48000.0, 0.49, 1776.919, 535.303 + 0.15, 48000.0, 0.51, 1858.819, 537.132 + 0.15, 48000.0, 0.53, 1941.459, 507.93 + 0.15, 48000.0, 0.55, 2022.087, 473.044 + 0.15, 48000.0, 0.57, 2099.567, 437.92 + 0.15, 48000.0, 0.59, 2172.763, 408.004 + 0.15, 48000.0, 0.61, 2231.605, 406.197 + 0.15, 48000.0, 0.63, 2277.121, 433.715 + 0.15, 48000.0, 0.65, 2321.444, 470.081 + 0.15, 48000.0, 0.67, 2367.768, 512.277 + 0.15, 48000.0, 0.69, 2419.291, 557.285 + 0.15, 48000.0, 0.71, 2493.698, 596.25 + 0.15, 48000.0, 0.73, 2590.672, 627.568 + 0.15, 48000.0, 0.75, 2691.894, 656.887 + 0.15, 48000.0, 0.77, 2793.534, 684.019 + 0.15, 48000.0, 0.79, 2891.762, 708.773 + 0.15, 48000.0, 0.81, 2970.947, 727.801 + 0.15, 48000.0, 0.83, 3030.119, 741.679 + 0.15, 48000.0, 0.85, 3082.975, 754.913 + 0.15, 48000.0, 0.87, 3131.407, 768.847 + 0.15, 48000.0, 0.89, 3177.307, 784.825 + 0.15, 48000.0, 0.91, 3222.57, 804.191 + 0.15, 48000.0, 0.93, 3269.086, 828.289 + 0.15, 48000.0, 0.95, 3318.75, 858.463 + 0.15, 48000.0, 0.97, 3373.454, 896.057 + 0.15, 48000.0, 0.99, 3435.09, 942.415 + 0.2, 0.0, 0.0, 728.1854, 728.185 + 0.2, 0.0, 0.05, 988.1, 682.875 + 0.2, 0.0, 0.07, 1383.34, 789.584 + 0.2, 0.0, 0.09, 1778.58, 896.313 + 0.2, 0.0, 0.11, 2173.82, 1003.11 + 0.2, 0.0, 0.13, 2569.06, 1110.01 + 0.2, 0.0, 0.15, 2964.3, 1217.08 + 0.2, 0.0, 0.17, 3359.54, 1324.34 + 0.2, 0.0, 0.19, 3754.78, 1431.84 + 0.2, 0.0, 0.21, 4150.02, 1539.64 + 0.2, 0.0, 0.23, 4545.26, 1647.77 + 0.2, 0.0, 0.25, 4940.5, 1756.27 + 0.2, 0.0, 0.27, 5335.74, 1865.21 + 0.2, 0.0, 0.29, 5730.98, 1974.61 + 0.2, 0.0, 0.31, 6126.22, 2084.52 + 0.2, 0.0, 0.33, 6521.46, 2195.0 + 0.2, 0.0, 0.35, 6916.7, 2306.08 + 0.2, 0.0, 0.37, 7311.94, 2417.8 + 0.2, 0.0, 0.39, 7707.18, 2530.22 + 0.2, 0.0, 0.41, 8102.42, 2643.33 + 0.2, 0.0, 0.43, 8497.66, 2757.18 + 0.2, 0.0, 0.45, 8892.9, 2871.9 + 0.2, 0.0, 0.47, 9288.14, 2987.55 + 0.2, 0.0, 0.49, 9683.38, 3104.19 + 0.2, 0.0, 0.51, 10078.62, 3221.93 + 0.2, 0.0, 0.53, 10473.86, 3340.83 + 0.2, 0.0, 0.55, 10869.1, 3460.89 + 0.2, 0.0, 0.57, 11264.34, 3582.18 + 0.2, 0.0, 0.59, 11659.58, 3704.73 + 0.2, 0.0, 0.61, 12054.82, 3828.77 + 0.2, 0.0, 0.63, 12450.06, 3954.3 + 0.2, 0.0, 0.65, 12845.29, 4081.12 + 0.2, 0.0, 0.67, 13240.53, 4209.2 + 0.2, 0.0, 0.69, 13635.78, 4338.5 + 0.2, 0.0, 0.71, 14031.02, 4468.93 + 0.2, 0.0, 0.73, 14426.27, 4600.48 + 0.2, 0.0, 0.75, 14821.53, 4733.2 + 0.2, 0.0, 0.77, 15216.79, 4867.09 + 0.2, 0.0, 0.79, 15612.06, 5002.14 + 0.2, 0.0, 0.81, 16007.35, 5138.04 + 0.2, 0.0, 0.83, 16402.67, 5274.88 + 0.2, 0.0, 0.85, 16797.97, 5413.09 + 0.2, 0.0, 0.87, 17193.28, 5552.82 + 0.2, 0.0, 0.89, 17588.56, 5694.23 + 0.2, 0.0, 0.91, 17983.83, 5837.45 + 0.2, 0.0, 0.93, 18379.07, 5982.63 + 0.2, 0.0, 0.95, 18774.27, 6129.91 + 0.2, 0.0, 0.97, 19169.44, 6279.45 + 0.2, 0.0, 0.99, 19564.56, 6431.39 + 0.2, 2000.0, 0.0, 681.7823, 681.782 + 0.2, 2000.0, 0.05, 947.85, 646.137 + 0.2, 2000.0, 0.07, 1326.99, 747.27 + 0.2, 2000.0, 0.09, 1706.13, 848.465 + 0.2, 2000.0, 0.11, 2085.27, 949.767 + 0.2, 2000.0, 0.13, 2464.41, 1051.22 + 0.2, 2000.0, 0.15, 2843.55, 1152.86 + 0.2, 2000.0, 0.17, 3222.69, 1254.74 + 0.2, 2000.0, 0.19, 3601.83, 1356.9 + 0.2, 2000.0, 0.21, 3980.97, 1459.38 + 0.2, 2000.0, 0.23, 4360.11, 1562.23 + 0.2, 2000.0, 0.25, 4739.25, 1665.49 + 0.2, 2000.0, 0.27, 5118.39, 1769.2 + 0.2, 2000.0, 0.29, 5497.53, 1873.4 + 0.2, 2000.0, 0.31, 5876.67, 1978.14 + 0.2, 2000.0, 0.33, 6255.81, 2083.46 + 0.2, 2000.0, 0.35, 6634.95, 2189.41 + 0.2, 2000.0, 0.37, 7014.09, 2296.03 + 0.2, 2000.0, 0.39, 7393.23, 2403.36 + 0.2, 2000.0, 0.41, 7772.36, 2511.38 + 0.2, 2000.0, 0.43, 8151.483, 2620.17 + 0.2, 2000.0, 0.45, 8530.613, 2729.83 + 0.2, 2000.0, 0.47, 8909.754, 2840.45 + 0.2, 2000.0, 0.49, 9288.913, 2952.08 + 0.2, 2000.0, 0.51, 9668.131, 3064.87 + 0.2, 2000.0, 0.53, 10047.4, 3178.87 + 0.2, 2000.0, 0.55, 10426.68, 3294.06 + 0.2, 2000.0, 0.57, 10805.95, 3410.45 + 0.2, 2000.0, 0.59, 11185.19, 3528.1 + 0.2, 2000.0, 0.61, 11564.34, 3647.2 + 0.2, 2000.0, 0.63, 11943.4, 3767.74 + 0.2, 2000.0, 0.65, 12322.44, 3889.53 + 0.2, 2000.0, 0.67, 12701.46, 4012.5 + 0.2, 2000.0, 0.69, 13080.48, 4136.62 + 0.2, 2000.0, 0.71, 13459.56, 4261.65 + 0.2, 2000.0, 0.73, 13838.68, 4387.58 + 0.2, 2000.0, 0.75, 14217.82, 4514.67 + 0.2, 2000.0, 0.77, 14596.97, 4642.97 + 0.2, 2000.0, 0.79, 14976.12, 4772.53 + 0.2, 2000.0, 0.81, 15355.27, 4903.28 + 0.2, 2000.0, 0.83, 15734.41, 5035.31 + 0.2, 2000.0, 0.85, 16113.55, 5168.84 + 0.2, 2000.0, 0.87, 16492.69, 5304.0 + 0.2, 2000.0, 0.89, 16871.83, 5440.88 + 0.2, 2000.0, 0.91, 17250.97, 5579.6 + 0.2, 2000.0, 0.93, 17630.11, 5720.27 + 0.2, 2000.0, 0.95, 18009.25, 5863.01 + 0.2, 2000.0, 0.97, 18388.39, 6007.92 + 0.2, 2000.0, 0.99, 18767.53, 6155.11 + 0.2, 5000.0, 0.0, 616.6016, 616.602 + 0.2, 5000.0, 0.05, 887.275, 591.95 + 0.2, 5000.0, 0.07, 1242.622, 685.399 + 0.2, 5000.0, 0.09, 1597.946, 778.908 + 0.2, 5000.0, 0.11, 1953.249, 872.524 + 0.2, 5000.0, 0.13, 2308.533, 966.289 + 0.2, 5000.0, 0.15, 2663.8, 1060.25 + 0.2, 5000.0, 0.17, 3019.051, 1154.45 + 0.2, 5000.0, 0.19, 3374.287, 1248.94 + 0.2, 5000.0, 0.21, 3729.51, 1343.75 + 0.2, 5000.0, 0.23, 4084.722, 1438.94 + 0.2, 5000.0, 0.25, 4439.925, 1534.55 + 0.2, 5000.0, 0.27, 4795.12, 1630.62 + 0.2, 5000.0, 0.29, 5150.308, 1727.2 + 0.2, 5000.0, 0.31, 5505.491, 1824.34 + 0.2, 5000.0, 0.33, 5860.671, 1922.07 + 0.2, 5000.0, 0.35, 6215.85, 2020.45 + 0.2, 5000.0, 0.37, 6571.029, 2119.51 + 0.2, 5000.0, 0.39, 6926.209, 2219.31 + 0.2, 5000.0, 0.41, 7281.397, 2319.84 + 0.2, 5000.0, 0.43, 7636.594, 2421.15 + 0.2, 5000.0, 0.45, 7991.794, 2523.37 + 0.2, 5000.0, 0.47, 8346.995, 2626.55 + 0.2, 5000.0, 0.49, 8702.198, 2730.78 + 0.2, 5000.0, 0.51, 9057.402, 2836.2 + 0.2, 5000.0, 0.53, 9412.605, 2942.87 + 0.2, 5000.0, 0.55, 9767.806, 3050.71 + 0.2, 5000.0, 0.57, 10123.01, 3159.74 + 0.2, 5000.0, 0.59, 10478.2, 3270.0 + 0.2, 5000.0, 0.61, 10833.39, 3381.67 + 0.2, 5000.0, 0.63, 11188.57, 3494.72 + 0.2, 5000.0, 0.65, 11543.75, 3608.95 + 0.2, 5000.0, 0.67, 11898.93, 3724.3 + 0.2, 5000.0, 0.69, 12254.11, 3840.71 + 0.2, 5000.0, 0.71, 12609.29, 3957.77 + 0.2, 5000.0, 0.73, 12964.48, 4075.52 + 0.2, 5000.0, 0.75, 13319.68, 4194.43 + 0.2, 5000.0, 0.77, 13674.88, 4314.63 + 0.2, 5000.0, 0.79, 14030.09, 4436.23 + 0.2, 5000.0, 0.81, 14385.32, 4559.59 + 0.2, 5000.0, 0.83, 14740.57, 4684.77 + 0.2, 5000.0, 0.85, 15095.82, 4811.55 + 0.2, 5000.0, 0.87, 15451.06, 4939.95 + 0.2, 5000.0, 0.89, 15806.29, 5069.97 + 0.2, 5000.0, 0.91, 16161.5, 5201.64 + 0.2, 5000.0, 0.93, 16516.69, 5334.95 + 0.2, 5000.0, 0.95, 16871.86, 5469.93 + 0.2, 5000.0, 0.97, 17226.98, 5606.57 + 0.2, 5000.0, 0.99, 17582.07, 5744.9 + 0.2, 10000.0, 0.0, 519.0247, 519.025 + 0.2, 10000.0, 0.05, 757.175, 503.181 + 0.2, 10000.0, 0.07, 1060.442, 580.795 + 0.2, 10000.0, 0.09, 1363.686, 658.501 + 0.2, 10000.0, 0.11, 1666.909, 736.336 + 0.2, 10000.0, 0.13, 1970.113, 814.338 + 0.2, 10000.0, 0.15, 2273.3, 892.544 + 0.2, 10000.0, 0.17, 2576.471, 970.992 + 0.2, 10000.0, 0.19, 2879.627, 1049.72 + 0.2, 10000.0, 0.21, 3182.77, 1128.76 + 0.2, 10000.0, 0.23, 3485.902, 1208.16 + 0.2, 10000.0, 0.25, 3789.025, 1287.96 + 0.2, 10000.0, 0.27, 4092.14, 1368.18 + 0.2, 10000.0, 0.29, 4395.248, 1448.87 + 0.2, 10000.0, 0.31, 4698.351, 1530.06 + 0.2, 10000.0, 0.33, 5001.451, 1611.8 + 0.2, 10000.0, 0.35, 5304.55, 1694.12 + 0.2, 10000.0, 0.37, 5607.649, 1777.05 + 0.2, 10000.0, 0.39, 5910.749, 1860.65 + 0.2, 10000.0, 0.41, 6213.854, 1944.89 + 0.2, 10000.0, 0.43, 6516.965, 2029.83 + 0.2, 10000.0, 0.45, 6820.081, 2115.57 + 0.2, 10000.0, 0.47, 7123.204, 2202.17 + 0.2, 10000.0, 0.49, 7426.333, 2289.68 + 0.2, 10000.0, 0.51, 7729.479, 2378.28 + 0.2, 10000.0, 0.53, 8032.642, 2468.01 + 0.2, 10000.0, 0.55, 8335.806, 2558.74 + 0.2, 10000.0, 0.57, 8638.969, 2650.48 + 0.2, 10000.0, 0.59, 8942.125, 2743.24 + 0.2, 10000.0, 0.61, 9245.257, 2837.06 + 0.2, 10000.0, 0.63, 9548.363, 2931.94 + 0.2, 10000.0, 0.65, 9851.463, 3027.81 + 0.2, 10000.0, 0.67, 10154.56, 3124.66 + 0.2, 10000.0, 0.69, 10457.65, 3222.45 + 0.2, 10000.0, 0.71, 10760.76, 3320.91 + 0.2, 10000.0, 0.73, 11063.87, 3420.08 + 0.2, 10000.0, 0.75, 11366.99, 3520.34 + 0.2, 10000.0, 0.77, 11670.11, 3621.81 + 0.2, 10000.0, 0.79, 11973.24, 3724.58 + 0.2, 10000.0, 0.81, 12276.37, 3829.12 + 0.2, 10000.0, 0.83, 12579.51, 3935.45 + 0.2, 10000.0, 0.85, 12882.66, 4043.18 + 0.2, 10000.0, 0.87, 13185.8, 4152.26 + 0.2, 10000.0, 0.89, 13488.93, 4262.64 + 0.2, 10000.0, 0.91, 13792.06, 4374.26 + 0.2, 10000.0, 0.93, 14095.18, 4487.08 + 0.2, 10000.0, 0.95, 14398.29, 4601.04 + 0.2, 10000.0, 0.97, 14701.39, 4716.09 + 0.2, 10000.0, 0.99, 15004.47, 4832.18 + 0.2, 15000.0, 0.0, 434.1026, 434.103 + 0.2, 15000.0, 0.05, 622.3, 424.1 + 0.2, 15000.0, 0.07, 871.3204, 485.056 + 0.2, 15000.0, 0.09, 1120.319, 546.084 + 0.2, 15000.0, 0.11, 1369.299, 607.197 + 0.2, 15000.0, 0.13, 1618.26, 668.413 + 0.2, 15000.0, 0.15, 1867.204, 729.746 + 0.2, 15000.0, 0.17, 2116.132, 791.214 + 0.2, 15000.0, 0.19, 2365.047, 852.831 + 0.2, 15000.0, 0.21, 2613.95, 914.613 + 0.2, 15000.0, 0.23, 2862.842, 976.576 + 0.2, 15000.0, 0.25, 3111.724, 1038.74 + 0.2, 15000.0, 0.27, 3360.599, 1101.11 + 0.2, 15000.0, 0.29, 3609.468, 1163.71 + 0.2, 15000.0, 0.31, 3858.331, 1226.37 + 0.2, 15000.0, 0.33, 4107.191, 1289.15 + 0.2, 15000.0, 0.35, 4356.05, 1352.34 + 0.2, 15000.0, 0.37, 4604.909, 1416.04 + 0.2, 15000.0, 0.39, 4853.769, 1480.37 + 0.2, 15000.0, 0.41, 5102.612, 1545.75 + 0.2, 15000.0, 0.43, 5351.446, 1612.2 + 0.2, 15000.0, 0.45, 5600.3, 1679.36 + 0.2, 15000.0, 0.47, 5849.186, 1747.17 + 0.2, 15000.0, 0.49, 6098.116, 1815.58 + 0.2, 15000.0, 0.51, 6347.118, 1884.2 + 0.2, 15000.0, 0.53, 6596.199, 1953.05 + 0.2, 15000.0, 0.55, 6845.344, 2022.61 + 0.2, 15000.0, 0.57, 7094.555, 2093.0 + 0.2, 15000.0, 0.59, 7343.834, 2164.34 + 0.2, 15000.0, 0.61, 7593.319, 2237.38 + 0.2, 15000.0, 0.63, 7842.98, 2312.11 + 0.2, 15000.0, 0.65, 8092.619, 2387.68 + 0.2, 15000.0, 0.67, 8342.171, 2463.92 + 0.2, 15000.0, 0.69, 8591.574, 2540.63 + 0.2, 15000.0, 0.71, 8840.471, 2616.59 + 0.2, 15000.0, 0.73, 9088.87, 2691.87 + 0.2, 15000.0, 0.75, 9337.144, 2767.81 + 0.2, 15000.0, 0.77, 9585.371, 2844.73 + 0.2, 15000.0, 0.79, 9833.632, 2922.92 + 0.2, 15000.0, 0.81, 10082.25, 3003.8 + 0.2, 15000.0, 0.83, 10331.26, 3087.41 + 0.2, 15000.0, 0.85, 10580.35, 3172.44 + 0.2, 15000.0, 0.87, 10829.49, 3258.7 + 0.2, 15000.0, 0.89, 11078.64, 3345.96 + 0.2, 15000.0, 0.91, 11327.75, 3434.01 + 0.2, 15000.0, 0.93, 11576.78, 3522.64 + 0.2, 15000.0, 0.95, 11825.7, 3611.63 + 0.2, 15000.0, 0.97, 12074.46, 3700.77 + 0.2, 15000.0, 0.99, 12323.01, 3789.85 + 0.2, 20000.0, 0.0, 360.586, 360.586 + 0.2, 20000.0, 0.05, 513.4, 343.3 + 0.2, 20000.0, 0.07, 719.0469, 393.256 + 0.2, 20000.0, 0.09, 924.7049, 442.763 + 0.2, 20000.0, 0.11, 1130.371, 491.915 + 0.2, 20000.0, 0.13, 1336.043, 540.81 + 0.2, 20000.0, 0.15, 1541.718, 589.543 + 0.2, 20000.0, 0.17, 1747.393, 638.211 + 0.2, 20000.0, 0.19, 1953.065, 686.909 + 0.2, 20000.0, 0.21, 2158.733, 735.735 + 0.2, 20000.0, 0.23, 2364.392, 784.783 + 0.2, 20000.0, 0.25, 2570.041, 834.151 + 0.2, 20000.0, 0.27, 2775.677, 883.935 + 0.2, 20000.0, 0.29, 2981.297, 934.23 + 0.2, 20000.0, 0.31, 3186.899, 985.586 + 0.2, 20000.0, 0.33, 3392.481, 1037.99 + 0.2, 20000.0, 0.35, 3598.037, 1090.86 + 0.2, 20000.0, 0.37, 3803.566, 1144.08 + 0.2, 20000.0, 0.39, 4009.064, 1197.53 + 0.2, 20000.0, 0.41, 4214.509, 1250.49 + 0.2, 20000.0, 0.43, 4419.903, 1302.98 + 0.2, 20000.0, 0.45, 4625.269, 1355.75 + 0.2, 20000.0, 0.47, 4830.613, 1408.97 + 0.2, 20000.0, 0.49, 5035.941, 1462.8 + 0.2, 20000.0, 0.51, 5241.195, 1518.02 + 0.2, 20000.0, 0.53, 5446.396, 1574.64 + 0.2, 20000.0, 0.55, 5651.644, 1631.92 + 0.2, 20000.0, 0.57, 5856.973, 1689.72 + 0.2, 20000.0, 0.59, 6062.421, 1747.9 + 0.2, 20000.0, 0.61, 6268.195, 1805.58 + 0.2, 20000.0, 0.63, 6474.291, 1862.8 + 0.2, 20000.0, 0.65, 6680.487, 1920.57 + 0.2, 20000.0, 0.67, 6886.735, 1979.11 + 0.2, 20000.0, 0.69, 7092.987, 2038.67 + 0.2, 20000.0, 0.71, 7299.192, 2100.27 + 0.2, 20000.0, 0.73, 7505.302, 2163.96 + 0.2, 20000.0, 0.75, 7711.275, 2228.8 + 0.2, 20000.0, 0.77, 7917.064, 2294.63 + 0.2, 20000.0, 0.79, 8122.622, 2361.3 + 0.2, 20000.0, 0.81, 8327.529, 2428.36 + 0.2, 20000.0, 0.83, 8531.829, 2495.73 + 0.2, 20000.0, 0.85, 8736.031, 2563.71 + 0.2, 20000.0, 0.87, 8940.272, 2632.3 + 0.2, 20000.0, 0.89, 9144.686, 2701.48 + 0.2, 20000.0, 0.91, 9349.408, 2771.26 + 0.2, 20000.0, 0.93, 9554.574, 2841.63 + 0.2, 20000.0, 0.95, 9760.319, 2912.59 + 0.2, 20000.0, 0.97, 9966.777, 2984.12 + 0.2, 20000.0, 0.99, 10174.09, 3056.23 + 0.2, 25000.0, 0.0, 297.2994, 297.299 + 0.2, 25000.0, 0.05, 425.2, 286.5 + 0.2, 25000.0, 0.07, 592.6704, 339.117 + 0.2, 25000.0, 0.09, 760.6122, 387.043 + 0.2, 25000.0, 0.11, 928.9802, 430.913 + 0.2, 25000.0, 0.13, 1097.729, 471.359 + 0.2, 25000.0, 0.15, 1266.814, 509.014 + 0.2, 25000.0, 0.17, 1436.19, 544.512 + 0.2, 25000.0, 0.19, 1605.811, 578.487 + 0.2, 25000.0, 0.21, 1775.633, 611.57 + 0.2, 25000.0, 0.23, 1945.61, 644.396 + 0.2, 25000.0, 0.25, 2115.697, 677.597 + 0.2, 25000.0, 0.27, 2285.849, 711.808 + 0.2, 25000.0, 0.29, 2456.021, 747.66 + 0.2, 25000.0, 0.31, 2626.145, 788.47 + 0.2, 25000.0, 0.33, 2796.182, 834.221 + 0.2, 25000.0, 0.35, 2966.119, 881.562 + 0.2, 25000.0, 0.37, 3135.922, 929.828 + 0.2, 25000.0, 0.39, 3305.557, 978.351 + 0.2, 25000.0, 0.41, 3474.843, 1025.15 + 0.2, 25000.0, 0.43, 3643.783, 1069.89 + 0.2, 25000.0, 0.45, 3812.556, 1113.83 + 0.2, 25000.0, 0.47, 3981.2, 1156.94 + 0.2, 25000.0, 0.49, 4149.749, 1199.2 + 0.2, 25000.0, 0.51, 4318.221, 1238.81 + 0.2, 25000.0, 0.53, 4486.656, 1276.16 + 0.2, 25000.0, 0.55, 4655.119, 1313.84 + 0.2, 25000.0, 0.57, 4823.656, 1352.67 + 0.2, 25000.0, 0.59, 4992.313, 1393.49 + 0.2, 25000.0, 0.61, 5161.191, 1440.26 + 0.2, 25000.0, 0.63, 5330.322, 1493.05 + 0.2, 25000.0, 0.65, 5499.669, 1547.99 + 0.2, 25000.0, 0.67, 5669.25, 1604.4 + 0.2, 25000.0, 0.69, 5839.083, 1661.56 + 0.2, 25000.0, 0.71, 6009.463, 1717.25 + 0.2, 25000.0, 0.73, 6180.34, 1771.14 + 0.2, 25000.0, 0.75, 6351.325, 1824.78 + 0.2, 25000.0, 0.77, 6522.302, 1878.2 + 0.2, 25000.0, 0.79, 6693.155, 1931.44 + 0.2, 25000.0, 0.81, 6863.574, 1984.28 + 0.2, 25000.0, 0.83, 7033.491, 2036.82 + 0.2, 25000.0, 0.85, 7203.081, 2089.45 + 0.2, 25000.0, 0.87, 7372.326, 2142.32 + 0.2, 25000.0, 0.89, 7541.204, 2195.58 + 0.2, 25000.0, 0.91, 7709.697, 2249.38 + 0.2, 25000.0, 0.93, 7877.783, 2303.87 + 0.2, 25000.0, 0.95, 8045.444, 2359.2 + 0.2, 25000.0, 0.97, 8212.658, 2415.52 + 0.2, 25000.0, 0.99, 8379.407, 2472.99 + 0.2, 30000.0, 0.0, 243.1516, 243.152 + 0.2, 30000.0, 0.05, 327.8, 238.4 + 0.2, 30000.0, 0.07, 460.7332, 267.117 + 0.2, 30000.0, 0.09, 593.1576, 295.716 + 0.2, 30000.0, 0.11, 725.1404, 324.225 + 0.2, 30000.0, 0.13, 856.7488, 352.669 + 0.2, 30000.0, 0.15, 988.05, 381.075 + 0.2, 30000.0, 0.17, 1119.111, 409.47 + 0.2, 30000.0, 0.19, 1250.0, 437.881 + 0.2, 30000.0, 0.21, 1380.782, 466.333 + 0.2, 30000.0, 0.23, 1511.527, 494.854 + 0.2, 30000.0, 0.25, 1642.3, 523.47 + 0.2, 30000.0, 0.27, 1773.169, 552.208 + 0.2, 30000.0, 0.29, 1904.202, 581.093 + 0.2, 30000.0, 0.31, 2035.783, 610.052 + 0.2, 30000.0, 0.33, 2167.903, 639.134 + 0.2, 30000.0, 0.35, 2300.156, 668.519 + 0.2, 30000.0, 0.37, 2432.456, 698.281 + 0.2, 30000.0, 0.39, 2564.714, 728.498 + 0.2, 30000.0, 0.41, 2696.649, 759.723 + 0.2, 30000.0, 0.43, 2828.221, 791.916 + 0.2, 30000.0, 0.45, 2959.631, 824.444 + 0.2, 30000.0, 0.47, 3090.888, 857.149 + 0.2, 30000.0, 0.49, 3221.998, 889.877 + 0.2, 30000.0, 0.51, 3352.811, 921.913 + 0.2, 30000.0, 0.53, 3483.374, 953.236 + 0.2, 30000.0, 0.55, 3613.925, 984.519 + 0.2, 30000.0, 0.57, 3744.548, 1015.88 + 0.2, 30000.0, 0.59, 3875.327, 1047.42 + 0.2, 30000.0, 0.61, 4006.68, 1079.29 + 0.2, 30000.0, 0.63, 4138.61, 1111.59 + 0.2, 30000.0, 0.65, 4270.7, 1144.41 + 0.2, 30000.0, 0.67, 4402.87, 1177.85 + 0.2, 30000.0, 0.69, 4535.04, 1212.01 + 0.2, 30000.0, 0.71, 4666.854, 1247.74 + 0.2, 30000.0, 0.73, 4798.3, 1284.96 + 0.2, 30000.0, 0.75, 4929.706, 1322.69 + 0.2, 30000.0, 0.77, 5061.126, 1360.68 + 0.2, 30000.0, 0.79, 5192.614, 1398.68 + 0.2, 30000.0, 0.81, 5324.485, 1435.0 + 0.2, 30000.0, 0.83, 5456.73, 1469.74 + 0.2, 30000.0, 0.85, 5589.013, 1504.78 + 0.2, 30000.0, 0.87, 5721.259, 1540.56 + 0.2, 30000.0, 0.89, 5853.396, 1577.53 + 0.2, 30000.0, 0.91, 5985.349, 1616.13 + 0.2, 30000.0, 0.93, 6117.046, 1656.82 + 0.2, 30000.0, 0.95, 6248.413, 1700.03 + 0.2, 30000.0, 0.97, 6379.375, 1746.2 + 0.2, 30000.0, 0.99, 6509.86, 1795.79 + 0.2, 35000.0, 0.0, 197.1285, 197.128 + 0.2, 35000.0, 0.05, 297.7, 266.3 + 0.2, 35000.0, 0.07, 421.3559, 283.166 + 0.2, 35000.0, 0.09, 546.014, 301.68 + 0.2, 35000.0, 0.11, 671.5681, 321.74 + 0.2, 35000.0, 0.13, 797.912, 343.249 + 0.2, 35000.0, 0.15, 924.9393, 366.107 + 0.2, 35000.0, 0.17, 1052.544, 390.214 + 0.2, 35000.0, 0.19, 1180.619, 415.471 + 0.2, 35000.0, 0.21, 1309.059, 441.779 + 0.2, 35000.0, 0.23, 1437.757, 469.038 + 0.2, 35000.0, 0.25, 1566.607, 497.149 + 0.2, 35000.0, 0.27, 1695.503, 526.012 + 0.2, 35000.0, 0.29, 1824.338, 555.528 + 0.2, 35000.0, 0.31, 1952.878, 586.376 + 0.2, 35000.0, 0.33, 2081.048, 618.269 + 0.2, 35000.0, 0.35, 2208.931, 649.95 + 0.2, 35000.0, 0.37, 2336.485, 680.943 + 0.2, 35000.0, 0.39, 2463.664, 710.772 + 0.2, 35000.0, 0.41, 2590.408, 735.15 + 0.2, 35000.0, 0.43, 2716.675, 754.525 + 0.2, 35000.0, 0.45, 2842.45, 774.075 + 0.2, 35000.0, 0.47, 2967.697, 795.169 + 0.2, 35000.0, 0.49, 3092.38, 819.176 + 0.2, 35000.0, 0.51, 3215.868, 853.362 + 0.2, 35000.0, 0.53, 3338.27, 897.667 + 0.2, 35000.0, 0.55, 3460.438, 944.706 + 0.2, 35000.0, 0.57, 3582.625, 992.992 + 0.2, 35000.0, 0.59, 3705.087, 1041.03 + 0.2, 35000.0, 0.61, 3829.16, 1084.28 + 0.2, 35000.0, 0.63, 3954.836, 1121.99 + 0.2, 35000.0, 0.65, 4080.763, 1157.22 + 0.2, 35000.0, 0.67, 4206.669, 1189.96 + 0.2, 35000.0, 0.69, 4332.285, 1220.21 + 0.2, 35000.0, 0.71, 4455.955, 1244.85 + 0.2, 35000.0, 0.73, 4577.743, 1264.62 + 0.2, 35000.0, 0.75, 4699.438, 1284.16 + 0.2, 35000.0, 0.77, 4821.44, 1304.98 + 0.2, 35000.0, 0.79, 4944.152, 1328.58 + 0.2, 35000.0, 0.81, 5069.525, 1362.48 + 0.2, 35000.0, 0.83, 5197.584, 1406.71 + 0.2, 35000.0, 0.85, 5326.431, 1453.9 + 0.2, 35000.0, 0.87, 5455.716, 1502.64 + 0.2, 35000.0, 0.89, 5585.089, 1551.53 + 0.2, 35000.0, 0.91, 5714.202, 1599.18 + 0.2, 35000.0, 0.93, 5842.703, 1644.19 + 0.2, 35000.0, 0.95, 5970.244, 1685.15 + 0.2, 35000.0, 0.97, 6096.475, 1720.67 + 0.2, 35000.0, 0.99, 6221.046, 1749.36 + 0.2, 40000.0, 0.0, 156.0079, 156.008 + 0.2, 40000.0, 0.05, 256.3, 207.0 + 0.2, 40000.0, 0.07, 353.362, 238.091 + 0.2, 40000.0, 0.09, 450.1807, 264.856 + 0.2, 40000.0, 0.11, 546.8695, 287.93 + 0.2, 40000.0, 0.13, 643.5418, 307.953 + 0.2, 40000.0, 0.15, 740.3107, 325.561 + 0.2, 40000.0, 0.17, 837.2897, 341.391 + 0.2, 40000.0, 0.19, 934.5921, 356.083 + 0.2, 40000.0, 0.21, 1032.331, 370.272 + 0.2, 40000.0, 0.23, 1130.62, 384.596 + 0.2, 40000.0, 0.25, 1229.573, 399.693 + 0.2, 40000.0, 0.27, 1329.302, 416.2 + 0.2, 40000.0, 0.29, 1429.921, 434.755 + 0.2, 40000.0, 0.31, 1532.743, 459.713 + 0.2, 40000.0, 0.33, 1637.589, 490.809 + 0.2, 40000.0, 0.35, 1742.794, 523.162 + 0.2, 40000.0, 0.37, 1847.888, 555.608 + 0.2, 40000.0, 0.39, 1952.405, 586.98 + 0.2, 40000.0, 0.41, 2054.382, 611.096 + 0.2, 40000.0, 0.43, 2153.714, 628.006 + 0.2, 40000.0, 0.45, 2252.15, 644.0 + 0.2, 40000.0, 0.47, 2349.946, 660.346 + 0.2, 40000.0, 0.49, 2447.358, 678.312 + 0.2, 40000.0, 0.51, 2544.553, 704.752 + 0.2, 40000.0, 0.53, 2641.808, 739.58 + 0.2, 40000.0, 0.55, 2739.513, 775.775 + 0.2, 40000.0, 0.57, 2837.965, 811.898 + 0.2, 40000.0, 0.59, 2937.464, 846.51 + 0.2, 40000.0, 0.61, 3040.069, 873.523 + 0.2, 40000.0, 0.63, 3145.652, 892.627 + 0.2, 40000.0, 0.65, 3251.9, 909.287 + 0.2, 40000.0, 0.67, 3358.26, 924.319 + 0.2, 40000.0, 0.69, 3464.179, 938.539 + 0.2, 40000.0, 0.71, 3567.71, 952.014 + 0.2, 40000.0, 0.73, 3668.637, 965.742 + 0.2, 40000.0, 0.75, 3768.475, 981.65 + 0.2, 40000.0, 0.77, 3867.345, 1000.92 + 0.2, 40000.0, 0.79, 3965.368, 1024.73 + 0.2, 40000.0, 0.81, 4061.935, 1061.74 + 0.2, 40000.0, 0.83, 4157.346, 1111.33 + 0.2, 40000.0, 0.85, 4252.806, 1163.54 + 0.2, 40000.0, 0.87, 4348.793, 1215.94 + 0.2, 40000.0, 0.89, 4445.781, 1266.06 + 0.2, 40000.0, 0.91, 4544.248, 1311.45 + 0.2, 40000.0, 0.93, 4644.668, 1349.67 + 0.2, 40000.0, 0.95, 4747.519, 1378.26 + 0.2, 40000.0, 0.97, 4853.275, 1394.76 + 0.2, 40000.0, 0.99, 4962.414, 1396.73 + 0.2, 43000.0, 0.0, 135.1368, 135.137 + 0.2, 43000.0, 0.05, 177.1, 233.8 + 0.2, 43000.0, 0.07, 297.5488, 269.478 + 0.2, 43000.0, 0.09, 407.6137, 300.678 + 0.2, 43000.0, 0.11, 508.6181, 327.75 + 0.2, 43000.0, 0.13, 601.8854, 351.04 + 0.2, 43000.0, 0.15, 688.7393, 370.896 + 0.2, 43000.0, 0.17, 770.5031, 387.668 + 0.2, 43000.0, 0.19, 848.5003, 401.701 + 0.2, 43000.0, 0.21, 924.0544, 413.345 + 0.2, 43000.0, 0.23, 998.4888, 422.947 + 0.2, 43000.0, 0.25, 1073.127, 430.856 + 0.2, 43000.0, 0.27, 1149.293, 437.418 + 0.2, 43000.0, 0.29, 1228.309, 442.983 + 0.2, 43000.0, 0.31, 1318.219, 444.766 + 0.2, 43000.0, 0.33, 1418.717, 443.874 + 0.2, 43000.0, 0.35, 1521.15, 445.306 + 0.2, 43000.0, 0.37, 1623.583, 450.928 + 0.2, 43000.0, 0.39, 1724.081, 462.606 + 0.2, 43000.0, 0.41, 1813.546, 495.812 + 0.2, 43000.0, 0.43, 1891.78, 549.113 + 0.2, 43000.0, 0.45, 1967.488, 604.175 + 0.2, 43000.0, 0.47, 2042.207, 656.269 + 0.2, 43000.0, 0.49, 2117.477, 700.666 + 0.2, 43000.0, 0.51, 2199.92, 712.362 + 0.2, 43000.0, 0.53, 2289.842, 691.543 + 0.2, 43000.0, 0.55, 2381.237, 663.581 + 0.2, 43000.0, 0.57, 2473.181, 633.578 + 0.2, 43000.0, 0.59, 2564.747, 606.632 + 0.2, 43000.0, 0.61, 2651.649, 601.197 + 0.2, 43000.0, 0.63, 2733.777, 619.134 + 0.2, 43000.0, 0.65, 2815.2, 645.719 + 0.2, 43000.0, 0.67, 2896.623, 679.578 + 0.2, 43000.0, 0.69, 2978.751, 719.337 + 0.2, 43000.0, 0.71, 3065.653, 765.321 + 0.2, 43000.0, 0.73, 3157.219, 815.744 + 0.2, 43000.0, 0.75, 3249.162, 866.713 + 0.2, 43000.0, 0.77, 3340.558, 916.029 + 0.2, 43000.0, 0.79, 3430.48, 961.496 + 0.2, 43000.0, 0.81, 3514.103, 992.036 + 0.2, 43000.0, 0.83, 3591.447, 1007.6 + 0.2, 43000.0, 0.85, 3667.381, 1019.19 + 0.2, 43000.0, 0.87, 3742.874, 1028.91 + 0.2, 43000.0, 0.89, 3818.892, 1038.87 + 0.2, 43000.0, 0.91, 3896.402, 1051.18 + 0.2, 43000.0, 0.93, 3976.372, 1067.95 + 0.2, 43000.0, 0.95, 4059.769, 1091.28 + 0.2, 43000.0, 0.97, 4147.559, 1123.29 + 0.2, 43000.0, 0.99, 4240.711, 1166.1 + 0.2, 48000.0, 0.0, 106.38, 106.38 + 0.2, 48000.0, 0.05, 160.9, 232.3 + 0.2, 48000.0, 0.07, 252.2238, 255.518 + 0.2, 48000.0, 0.09, 336.8461, 274.86 + 0.2, 48000.0, 0.11, 415.5215, 290.719 + 0.2, 48000.0, 0.13, 489.0046, 303.493 + 0.2, 48000.0, 0.15, 558.05, 313.575 + 0.2, 48000.0, 0.17, 623.4122, 321.361 + 0.2, 48000.0, 0.19, 685.8457, 327.247 + 0.2, 48000.0, 0.21, 746.1051, 331.626 + 0.2, 48000.0, 0.23, 804.945, 334.896 + 0.2, 48000.0, 0.25, 863.12, 337.45 + 0.2, 48000.0, 0.27, 921.3846, 339.684 + 0.2, 48000.0, 0.29, 980.4933, 341.994 + 0.2, 48000.0, 0.31, 1043.1, 343.538 + 0.2, 48000.0, 0.33, 1109.499, 345.011 + 0.2, 48000.0, 0.35, 1177.625, 348.644 + 0.2, 48000.0, 0.37, 1247.311, 355.431 + 0.2, 48000.0, 0.39, 1318.39, 366.366 + 0.2, 48000.0, 0.41, 1390.932, 391.257 + 0.2, 48000.0, 0.43, 1464.714, 428.961 + 0.2, 48000.0, 0.45, 1539.219, 467.388 + 0.2, 48000.0, 0.47, 1614.165, 503.258 + 0.2, 48000.0, 0.49, 1689.273, 533.294 + 0.2, 48000.0, 0.51, 1765.483, 538.716 + 0.2, 48000.0, 0.53, 1842.217, 520.003 + 0.2, 48000.0, 0.55, 1917.381, 496.894 + 0.2, 48000.0, 0.57, 1990.104, 473.627 + 0.2, 48000.0, 0.59, 2059.512, 454.44 + 0.2, 48000.0, 0.61, 2117.83, 457.127 + 0.2, 48000.0, 0.63, 2165.859, 482.641 + 0.2, 48000.0, 0.65, 2212.975, 515.087 + 0.2, 48000.0, 0.67, 2261.651, 552.129 + 0.2, 48000.0, 0.69, 2314.36, 591.431 + 0.2, 48000.0, 0.71, 2384.811, 626.194 + 0.2, 48000.0, 0.73, 2472.754, 655.164 + 0.2, 48000.0, 0.75, 2563.981, 682.631 + 0.2, 48000.0, 0.77, 2655.518, 708.425 + 0.2, 48000.0, 0.79, 2744.391, 732.372 + 0.2, 48000.0, 0.81, 2818.449, 751.716 + 0.2, 48000.0, 0.83, 2876.941, 766.911 + 0.2, 48000.0, 0.85, 2930.525, 781.625 + 0.2, 48000.0, 0.87, 2980.677, 796.939 + 0.2, 48000.0, 0.89, 3028.873, 813.934 + 0.2, 48000.0, 0.91, 3076.592, 833.692 + 0.2, 48000.0, 0.93, 3125.308, 857.295 + 0.2, 48000.0, 0.95, 3176.5, 885.825 + 0.2, 48000.0, 0.97, 3231.644, 920.363 + 0.2, 48000.0, 0.99, 3292.216, 961.99 + 0.25, 0.0, 0.0, 737.9815, 737.981 + 0.25, 0.0, 0.05, 951.25, 733.475 + 0.25, 0.0, 0.07, 1330.767, 847.759 + 0.25, 0.0, 0.09, 1710.315, 961.667 + 0.25, 0.0, 0.11, 2089.892, 1075.26 + 0.25, 0.0, 0.13, 2469.496, 1188.61 + 0.25, 0.0, 0.15, 2849.125, 1301.77 + 0.25, 0.0, 0.17, 3228.778, 1414.82 + 0.25, 0.0, 0.19, 3608.454, 1527.81 + 0.25, 0.0, 0.21, 3988.151, 1640.8 + 0.25, 0.0, 0.23, 4367.867, 1753.87 + 0.25, 0.0, 0.25, 4747.6, 1867.08 + 0.25, 0.0, 0.27, 5127.349, 1980.48 + 0.25, 0.0, 0.29, 5507.113, 2094.15 + 0.25, 0.0, 0.31, 5886.89, 2208.14 + 0.25, 0.0, 0.33, 6266.678, 2322.53 + 0.25, 0.0, 0.35, 6646.475, 2437.38 + 0.25, 0.0, 0.37, 7026.28, 2552.74 + 0.25, 0.0, 0.39, 7406.092, 2668.69 + 0.25, 0.0, 0.41, 7785.909, 2785.31 + 0.25, 0.0, 0.43, 8165.729, 2902.66 + 0.25, 0.0, 0.45, 8545.55, 3020.77 + 0.25, 0.0, 0.47, 8925.371, 3139.69 + 0.25, 0.0, 0.49, 9305.191, 3259.47 + 0.25, 0.0, 0.51, 9685.003, 3380.13 + 0.25, 0.0, 0.53, 10064.81, 3501.71 + 0.25, 0.0, 0.55, 10444.61, 3624.34 + 0.25, 0.0, 0.57, 10824.4, 3748.07 + 0.25, 0.0, 0.59, 11204.2, 3872.98 + 0.25, 0.0, 0.61, 11584.0, 3999.43 + 0.25, 0.0, 0.63, 11963.8, 4127.4 + 0.25, 0.0, 0.65, 12343.6, 4256.55 + 0.25, 0.0, 0.67, 12723.4, 4386.8 + 0.25, 0.0, 0.69, 13103.2, 4518.09 + 0.25, 0.0, 0.71, 13482.99, 4650.09 + 0.25, 0.0, 0.73, 13862.78, 4782.78 + 0.25, 0.0, 0.75, 14242.57, 4916.48 + 0.25, 0.0, 0.77, 14622.38, 5051.25 + 0.25, 0.0, 0.79, 15002.19, 5187.13 + 0.25, 0.0, 0.81, 15382.04, 5324.03 + 0.25, 0.0, 0.83, 15761.93, 5462.04 + 0.25, 0.0, 0.85, 16141.82, 5601.43 + 0.25, 0.0, 0.87, 16521.71, 5742.34 + 0.25, 0.0, 0.89, 16901.58, 5884.88 + 0.25, 0.0, 0.91, 17281.42, 6029.18 + 0.25, 0.0, 0.93, 17661.22, 6175.37 + 0.25, 0.0, 0.95, 18040.97, 6323.57 + 0.25, 0.0, 0.97, 18420.68, 6473.91 + 0.25, 0.0, 0.99, 18800.31, 6626.51 + 0.25, 2000.0, 0.0, 690.9541, 690.954 + 0.25, 2000.0, 0.05, 910.8437, 695.1 + 0.25, 2000.0, 0.07, 1275.516, 803.039 + 0.25, 2000.0, 0.09, 1640.175, 910.73 + 0.25, 2000.0, 0.11, 2004.822, 1018.23 + 0.25, 2000.0, 0.13, 2369.457, 1125.59 + 0.25, 2000.0, 0.15, 2734.081, 1232.87 + 0.25, 2000.0, 0.17, 3098.696, 1340.13 + 0.25, 2000.0, 0.19, 3463.301, 1447.43 + 0.25, 2000.0, 0.21, 3827.897, 1554.8 + 0.25, 2000.0, 0.23, 4192.486, 1662.33 + 0.25, 2000.0, 0.25, 4557.069, 1770.05 + 0.25, 2000.0, 0.27, 4921.645, 1878.03 + 0.25, 2000.0, 0.29, 5286.216, 1986.32 + 0.25, 2000.0, 0.31, 5650.783, 2094.98 + 0.25, 2000.0, 0.33, 6015.346, 2204.06 + 0.25, 2000.0, 0.35, 6379.906, 2313.62 + 0.25, 2000.0, 0.37, 6744.465, 2423.72 + 0.25, 2000.0, 0.39, 7109.022, 2534.41 + 0.25, 2000.0, 0.41, 7473.578, 2645.73 + 0.25, 2000.0, 0.43, 7838.135, 2757.74 + 0.25, 2000.0, 0.45, 8202.694, 2870.52 + 0.25, 2000.0, 0.47, 8567.254, 2984.14 + 0.25, 2000.0, 0.49, 8931.817, 3098.67 + 0.25, 2000.0, 0.51, 9296.39, 3214.23 + 0.25, 2000.0, 0.53, 9660.973, 3330.86 + 0.25, 2000.0, 0.55, 10025.56, 3448.57 + 0.25, 2000.0, 0.57, 10390.14, 3567.39 + 0.25, 2000.0, 0.59, 10754.71, 3687.36 + 0.25, 2000.0, 0.61, 11119.27, 3808.77 + 0.25, 2000.0, 0.63, 11483.8, 3931.6 + 0.25, 2000.0, 0.65, 11848.34, 4055.54 + 0.25, 2000.0, 0.67, 12212.88, 4180.53 + 0.25, 2000.0, 0.69, 12577.42, 4306.48 + 0.25, 2000.0, 0.71, 12942.01, 4432.98 + 0.25, 2000.0, 0.73, 13306.62, 4560.03 + 0.25, 2000.0, 0.75, 13671.25, 4688.11 + 0.25, 2000.0, 0.77, 14035.88, 4817.3 + 0.25, 2000.0, 0.79, 14400.49, 4947.71 + 0.25, 2000.0, 0.81, 14765.08, 5079.46 + 0.25, 2000.0, 0.83, 15129.63, 5212.66 + 0.25, 2000.0, 0.85, 15494.17, 5347.37 + 0.25, 2000.0, 0.87, 15858.7, 5483.67 + 0.25, 2000.0, 0.89, 16223.23, 5621.65 + 0.25, 2000.0, 0.91, 16587.77, 5761.4 + 0.25, 2000.0, 0.93, 16952.31, 5903.02 + 0.25, 2000.0, 0.95, 17316.86, 6046.58 + 0.25, 2000.0, 0.97, 17681.42, 6192.18 + 0.25, 2000.0, 0.99, 18046.0, 6339.91 + 0.25, 5000.0, 0.0, 624.8966, 624.897 + 0.25, 5000.0, 0.05, 853.3687, 638.575 + 0.25, 5000.0, 0.07, 1195.448, 737.77 + 0.25, 5000.0, 0.09, 1537.491, 836.817 + 0.25, 5000.0, 0.11, 1879.501, 935.765 + 0.25, 5000.0, 0.13, 2221.48, 1034.67 + 0.25, 5000.0, 0.15, 2563.431, 1133.58 + 0.25, 5000.0, 0.17, 2905.356, 1232.54 + 0.25, 5000.0, 0.19, 3247.257, 1331.61 + 0.25, 5000.0, 0.21, 3589.138, 1430.84 + 0.25, 5000.0, 0.23, 3930.999, 1530.28 + 0.25, 5000.0, 0.25, 4272.844, 1629.98 + 0.25, 5000.0, 0.27, 4614.675, 1729.99 + 0.25, 5000.0, 0.29, 4956.494, 1830.36 + 0.25, 5000.0, 0.31, 5298.304, 1931.15 + 0.25, 5000.0, 0.33, 5640.107, 2032.4 + 0.25, 5000.0, 0.35, 5981.906, 2134.18 + 0.25, 5000.0, 0.37, 6323.703, 2236.51 + 0.25, 5000.0, 0.39, 6665.5, 2339.47 + 0.25, 5000.0, 0.41, 7007.301, 2443.06 + 0.25, 5000.0, 0.43, 7349.106, 2547.34 + 0.25, 5000.0, 0.45, 7690.919, 2652.42 + 0.25, 5000.0, 0.47, 8032.742, 2758.37 + 0.25, 5000.0, 0.49, 8374.577, 2865.27 + 0.25, 5000.0, 0.51, 8716.45, 2973.32 + 0.25, 5000.0, 0.53, 9058.358, 3082.54 + 0.25, 5000.0, 0.55, 9400.269, 3192.84 + 0.25, 5000.0, 0.57, 9742.173, 3304.21 + 0.25, 5000.0, 0.59, 10084.06, 3416.66 + 0.25, 5000.0, 0.61, 10425.89, 3530.32 + 0.25, 5000.0, 0.63, 10767.66, 3645.18 + 0.25, 5000.0, 0.65, 11109.42, 3761.06 + 0.25, 5000.0, 0.67, 11451.17, 3877.94 + 0.25, 5000.0, 0.69, 11792.92, 3995.75 + 0.25, 5000.0, 0.71, 12134.71, 4114.07 + 0.25, 5000.0, 0.73, 12476.53, 4232.93 + 0.25, 5000.0, 0.75, 12818.37, 4352.89 + 0.25, 5000.0, 0.77, 13160.22, 4474.11 + 0.25, 5000.0, 0.79, 13502.07, 4596.72 + 0.25, 5000.0, 0.81, 13843.93, 4721.26 + 0.25, 5000.0, 0.83, 14185.8, 4847.79 + 0.25, 5000.0, 0.85, 14527.67, 4975.89 + 0.25, 5000.0, 0.87, 14869.53, 5105.53 + 0.25, 5000.0, 0.89, 15211.38, 5236.68 + 0.25, 5000.0, 0.91, 15553.22, 5369.29 + 0.25, 5000.0, 0.93, 15895.03, 5503.33 + 0.25, 5000.0, 0.95, 16236.83, 5638.78 + 0.25, 5000.0, 0.97, 16578.6, 5775.59 + 0.25, 5000.0, 0.99, 16920.34, 5913.74 + 0.25, 10000.0, 0.0, 526.007, 526.007 + 0.25, 10000.0, 0.05, 728.5437, 541.231 + 0.25, 10000.0, 0.07, 1020.296, 623.604 + 0.25, 10000.0, 0.09, 1312.035, 705.882 + 0.25, 10000.0, 0.11, 1603.762, 788.111 + 0.25, 10000.0, 0.13, 1895.477, 870.333 + 0.25, 10000.0, 0.15, 2187.181, 952.594 + 0.25, 10000.0, 0.17, 2478.876, 1034.94 + 0.25, 10000.0, 0.19, 2770.561, 1117.4 + 0.25, 10000.0, 0.21, 3062.237, 1200.04 + 0.25, 10000.0, 0.23, 3353.906, 1282.9 + 0.25, 10000.0, 0.25, 3645.569, 1366.01 + 0.25, 10000.0, 0.27, 3937.225, 1449.42 + 0.25, 10000.0, 0.29, 4228.876, 1533.18 + 0.25, 10000.0, 0.31, 4520.523, 1617.33 + 0.25, 10000.0, 0.33, 4812.166, 1701.91 + 0.25, 10000.0, 0.35, 5103.806, 1786.97 + 0.25, 10000.0, 0.37, 5395.445, 1872.55 + 0.25, 10000.0, 0.39, 5687.082, 1958.7 + 0.25, 10000.0, 0.41, 5978.72, 2045.44 + 0.25, 10000.0, 0.43, 6270.36, 2132.81 + 0.25, 10000.0, 0.45, 6562.0, 2220.9 + 0.25, 10000.0, 0.47, 6853.64, 2309.76 + 0.25, 10000.0, 0.49, 7145.28, 2399.44 + 0.25, 10000.0, 0.51, 7436.918, 2490.1 + 0.25, 10000.0, 0.53, 7728.555, 2581.79 + 0.25, 10000.0, 0.55, 8020.194, 2674.37 + 0.25, 10000.0, 0.57, 8311.834, 2767.87 + 0.25, 10000.0, 0.59, 8603.477, 2862.26 + 0.25, 10000.0, 0.61, 8895.127, 2957.58 + 0.25, 10000.0, 0.63, 9186.784, 3053.8 + 0.25, 10000.0, 0.65, 9478.444, 3150.92 + 0.25, 10000.0, 0.67, 9770.105, 3248.93 + 0.25, 10000.0, 0.69, 10061.77, 3347.83 + 0.25, 10000.0, 0.71, 10353.43, 3447.34 + 0.25, 10000.0, 0.73, 10645.09, 3547.52 + 0.25, 10000.0, 0.75, 10936.76, 3648.76 + 0.25, 10000.0, 0.77, 11228.42, 3751.16 + 0.25, 10000.0, 0.79, 11520.07, 3854.84 + 0.25, 10000.0, 0.81, 11811.72, 3960.31 + 0.25, 10000.0, 0.83, 12103.37, 4067.59 + 0.25, 10000.0, 0.85, 12395.01, 4176.22 + 0.25, 10000.0, 0.87, 12686.65, 4286.15 + 0.25, 10000.0, 0.89, 12978.28, 4397.29 + 0.25, 10000.0, 0.91, 13269.91, 4509.59 + 0.25, 10000.0, 0.93, 13561.54, 4622.96 + 0.25, 10000.0, 0.95, 13853.16, 4737.35 + 0.25, 10000.0, 0.97, 14144.78, 4852.68 + 0.25, 10000.0, 0.99, 14436.39, 4968.89 + 0.25, 15000.0, 0.0, 439.9424, 439.942 + 0.25, 15000.0, 0.05, 602.6063, 438.088 + 0.25, 15000.0, 0.07, 843.6975, 504.475 + 0.25, 15000.0, 0.09, 1084.774, 570.456 + 0.25, 15000.0, 0.11, 1325.838, 636.089 + 0.25, 15000.0, 0.13, 1566.89, 701.434 + 0.25, 15000.0, 0.15, 1807.932, 766.551 + 0.25, 15000.0, 0.17, 2048.964, 831.498 + 0.25, 15000.0, 0.19, 2289.99, 896.335 + 0.25, 15000.0, 0.21, 2531.009, 961.122 + 0.25, 15000.0, 0.23, 2772.023, 1025.92 + 0.25, 15000.0, 0.25, 3013.034, 1090.78 + 0.25, 15000.0, 0.27, 3254.043, 1155.77 + 0.25, 15000.0, 0.29, 3495.052, 1220.95 + 0.25, 15000.0, 0.31, 3736.065, 1286.38 + 0.25, 15000.0, 0.33, 3977.084, 1352.13 + 0.25, 15000.0, 0.35, 4218.103, 1418.23 + 0.25, 15000.0, 0.37, 4459.122, 1484.75 + 0.25, 15000.0, 0.39, 4700.141, 1551.74 + 0.25, 15000.0, 0.41, 4941.146, 1619.36 + 0.25, 15000.0, 0.43, 5182.139, 1687.62 + 0.25, 15000.0, 0.45, 5423.139, 1756.47 + 0.25, 15000.0, 0.47, 5664.151, 1825.92 + 0.25, 15000.0, 0.49, 5905.182, 1895.97 + 0.25, 15000.0, 0.51, 6146.251, 1966.63 + 0.25, 15000.0, 0.53, 6387.361, 2037.9 + 0.25, 15000.0, 0.55, 6628.495, 2109.86 + 0.25, 15000.0, 0.57, 6869.653, 2182.53 + 0.25, 15000.0, 0.59, 7110.833, 2255.94 + 0.25, 15000.0, 0.61, 7352.073, 2330.28 + 0.25, 15000.0, 0.63, 7593.361, 2405.54 + 0.25, 15000.0, 0.65, 7834.64, 2481.53 + 0.25, 15000.0, 0.67, 8075.889, 2558.19 + 0.25, 15000.0, 0.69, 8317.088, 2635.48 + 0.25, 15000.0, 0.71, 8558.12, 2712.95 + 0.25, 15000.0, 0.73, 8798.99, 2790.66 + 0.25, 15000.0, 0.75, 9039.82, 2869.15 + 0.25, 15000.0, 0.77, 9280.637, 2948.59 + 0.25, 15000.0, 0.79, 9521.47, 3029.11 + 0.25, 15000.0, 0.81, 9762.437, 3111.41 + 0.25, 15000.0, 0.83, 10003.54, 3195.5 + 0.25, 15000.0, 0.85, 10244.68, 3280.75 + 0.25, 15000.0, 0.87, 10485.82, 3367.05 + 0.25, 15000.0, 0.89, 10726.96, 3454.29 + 0.25, 15000.0, 0.91, 10968.07, 3542.38 + 0.25, 15000.0, 0.93, 11209.14, 3631.2 + 0.25, 15000.0, 0.95, 11450.14, 3720.65 + 0.25, 15000.0, 0.97, 11691.07, 3810.62 + 0.25, 15000.0, 0.99, 11931.9, 3901.0 + 0.25, 20000.0, 0.0, 365.4369, 365.437 + 0.25, 20000.0, 0.05, 498.3312, 361.706 + 0.25, 20000.0, 0.07, 697.8347, 415.447 + 0.25, 20000.0, 0.09, 897.3471, 468.625 + 0.25, 20000.0, 0.11, 1096.866, 521.329 + 0.25, 20000.0, 0.13, 1296.391, 573.649 + 0.25, 20000.0, 0.15, 1495.918, 625.676 + 0.25, 20000.0, 0.17, 1695.447, 677.499 + 0.25, 20000.0, 0.19, 1894.975, 729.209 + 0.25, 20000.0, 0.21, 2094.499, 780.896 + 0.25, 20000.0, 0.23, 2294.02, 832.65 + 0.25, 20000.0, 0.25, 2493.533, 884.56 + 0.25, 20000.0, 0.27, 2693.038, 936.717 + 0.25, 20000.0, 0.29, 2892.532, 989.211 + 0.25, 20000.0, 0.31, 3092.013, 1042.45 + 0.25, 20000.0, 0.33, 3291.48, 1096.45 + 0.25, 20000.0, 0.35, 3490.93, 1150.83 + 0.25, 20000.0, 0.37, 3690.362, 1205.51 + 0.25, 20000.0, 0.39, 3889.776, 1260.44 + 0.25, 20000.0, 0.41, 4089.158, 1315.16 + 0.25, 20000.0, 0.43, 4288.51, 1369.71 + 0.25, 20000.0, 0.45, 4487.845, 1424.59 + 0.25, 20000.0, 0.47, 4687.168, 1479.91 + 0.25, 20000.0, 0.49, 4886.483, 1535.8 + 0.25, 20000.0, 0.51, 5085.757, 1592.85 + 0.25, 20000.0, 0.53, 5285.003, 1651.06 + 0.25, 20000.0, 0.55, 5484.276, 1709.86 + 0.25, 20000.0, 0.57, 5683.597, 1769.15 + 0.25, 20000.0, 0.59, 5882.986, 1828.82 + 0.25, 20000.0, 0.61, 6082.564, 1888.18 + 0.25, 20000.0, 0.63, 6282.327, 1947.26 + 0.25, 20000.0, 0.65, 6482.147, 2006.85 + 0.25, 20000.0, 0.67, 6681.994, 2067.12 + 0.25, 20000.0, 0.69, 6881.842, 2128.26 + 0.25, 20000.0, 0.71, 7081.655, 2191.04 + 0.25, 20000.0, 0.73, 7281.408, 2255.5 + 0.25, 20000.0, 0.75, 7481.079, 2320.96 + 0.25, 20000.0, 0.77, 7680.643, 2387.3 + 0.25, 20000.0, 0.79, 7880.074, 2454.42 + 0.25, 20000.0, 0.81, 8079.127, 2521.97 + 0.25, 20000.0, 0.83, 8277.829, 2589.9 + 0.25, 20000.0, 0.85, 8476.479, 2658.49 + 0.25, 20000.0, 0.87, 8675.158, 2727.78 + 0.25, 20000.0, 0.89, 8873.946, 2797.77 + 0.25, 20000.0, 0.91, 9072.923, 2868.5 + 0.25, 20000.0, 0.93, 9272.17, 2939.99 + 0.25, 20000.0, 0.95, 9471.766, 3012.26 + 0.25, 20000.0, 0.97, 9671.792, 3085.33 + 0.25, 20000.0, 0.99, 9872.328, 3159.22 + 0.25, 25000.0, 0.0, 301.2989, 301.299 + 0.25, 25000.0, 0.05, 413.9, 303.85 + 0.25, 25000.0, 0.07, 577.7309, 355.314 + 0.25, 25000.0, 0.09, 741.8718, 403.478 + 0.25, 25000.0, 0.11, 906.2933, 448.781 + 0.25, 25000.0, 0.13, 1070.966, 491.664 + 0.25, 25000.0, 0.15, 1235.861, 532.567 + 0.25, 25000.0, 0.17, 1400.948, 571.93 + 0.25, 25000.0, 0.19, 1566.198, 610.193 + 0.25, 25000.0, 0.21, 1731.582, 647.797 + 0.25, 25000.0, 0.23, 1897.07, 685.181 + 0.25, 25000.0, 0.25, 2062.633, 722.785 + 0.25, 25000.0, 0.27, 2228.241, 761.051 + 0.25, 25000.0, 0.29, 2393.866, 800.417 + 0.25, 25000.0, 0.31, 2559.467, 843.122 + 0.25, 25000.0, 0.33, 2725.017, 889.172 + 0.25, 25000.0, 0.35, 2890.503, 936.334 + 0.25, 25000.0, 0.37, 3055.9, 984.178 + 0.25, 25000.0, 0.39, 3221.183, 1032.27 + 0.25, 25000.0, 0.41, 3386.226, 1079.31 + 0.25, 25000.0, 0.43, 3551.028, 1125.08 + 0.25, 25000.0, 0.45, 3715.719, 1170.43 + 0.25, 25000.0, 0.47, 3880.323, 1215.36 + 0.25, 25000.0, 0.49, 4044.868, 1259.85 + 0.25, 25000.0, 0.51, 4209.374, 1302.76 + 0.25, 25000.0, 0.53, 4373.87, 1344.35 + 0.25, 25000.0, 0.55, 4538.384, 1386.29 + 0.25, 25000.0, 0.57, 4702.943, 1429.13 + 0.25, 25000.0, 0.59, 4867.574, 1473.41 + 0.25, 25000.0, 0.61, 5032.318, 1521.68 + 0.25, 25000.0, 0.63, 5197.197, 1574.01 + 0.25, 25000.0, 0.65, 5362.219, 1627.91 + 0.25, 25000.0, 0.67, 5527.402, 1682.94 + 0.25, 25000.0, 0.69, 5692.768, 1738.65 + 0.25, 25000.0, 0.71, 5858.558, 1793.66 + 0.25, 25000.0, 0.73, 6024.739, 1847.74 + 0.25, 25000.0, 0.75, 6191.0, 1901.87 + 0.25, 25000.0, 0.77, 6357.253, 1956.05 + 0.25, 25000.0, 0.79, 6523.41, 2010.3 + 0.25, 25000.0, 0.81, 6689.211, 2064.41 + 0.25, 25000.0, 0.83, 6854.609, 2118.46 + 0.25, 25000.0, 0.85, 7019.772, 2172.78 + 0.25, 25000.0, 0.87, 7184.696, 2227.49 + 0.25, 25000.0, 0.89, 7349.377, 2282.71 + 0.25, 25000.0, 0.91, 7513.81, 2338.56 + 0.25, 25000.0, 0.93, 7677.991, 2395.17 + 0.25, 25000.0, 0.95, 7841.916, 2452.65 + 0.25, 25000.0, 0.97, 8005.579, 2511.12 + 0.25, 25000.0, 0.99, 8168.977, 2570.7 + 0.25, 30000.0, 0.0, 246.4226, 246.423 + 0.25, 30000.0, 0.05, 327.05, 255.2 + 0.25, 30000.0, 0.07, 459.1029, 287.42 + 0.25, 30000.0, 0.09, 590.8165, 319.44 + 0.25, 30000.0, 0.11, 722.2355, 351.29 + 0.25, 30000.0, 0.13, 853.4047, 383.003 + 0.25, 30000.0, 0.15, 984.3687, 414.611 + 0.25, 30000.0, 0.17, 1115.172, 446.144 + 0.25, 30000.0, 0.19, 1245.86, 477.635 + 0.25, 30000.0, 0.21, 1376.477, 509.116 + 0.25, 30000.0, 0.23, 1507.068, 540.618 + 0.25, 30000.0, 0.25, 1637.678, 572.173 + 0.25, 30000.0, 0.27, 1768.35, 603.812 + 0.25, 30000.0, 0.29, 1899.13, 635.568 + 0.25, 30000.0, 0.31, 2030.273, 667.42 + 0.25, 30000.0, 0.33, 2161.771, 699.412 + 0.25, 30000.0, 0.35, 2293.359, 731.653 + 0.25, 30000.0, 0.37, 2424.981, 764.202 + 0.25, 30000.0, 0.39, 2556.578, 797.114 + 0.25, 30000.0, 0.41, 2687.976, 830.753 + 0.25, 30000.0, 0.43, 2819.145, 865.102 + 0.25, 30000.0, 0.45, 2950.208, 899.764 + 0.25, 30000.0, 0.47, 3081.164, 934.65 + 0.25, 30000.0, 0.49, 3212.014, 969.669 + 0.25, 30000.0, 0.51, 3342.635, 1004.41 + 0.25, 30000.0, 0.53, 3473.058, 1038.86 + 0.25, 30000.0, 0.55, 3603.469, 1073.41 + 0.25, 30000.0, 0.57, 3733.93, 1108.11 + 0.25, 30000.0, 0.59, 3864.503, 1143.03 + 0.25, 30000.0, 0.61, 3995.493, 1178.18 + 0.25, 30000.0, 0.63, 4126.904, 1213.64 + 0.25, 30000.0, 0.65, 4258.433, 1249.55 + 0.25, 30000.0, 0.67, 4390.023, 1286.02 + 0.25, 30000.0, 0.69, 4521.619, 1323.12 + 0.25, 30000.0, 0.71, 4652.973, 1361.51 + 0.25, 30000.0, 0.73, 4784.076, 1401.14 + 0.25, 30000.0, 0.75, 4915.148, 1441.3 + 0.25, 30000.0, 0.77, 5046.226, 1481.82 + 0.25, 30000.0, 0.79, 5177.342, 1522.54 + 0.25, 30000.0, 0.81, 5308.7, 1562.33 + 0.25, 30000.0, 0.83, 5440.294, 1601.25 + 0.25, 30000.0, 0.85, 5571.906, 1640.56 + 0.25, 30000.0, 0.87, 5703.488, 1680.56 + 0.25, 30000.0, 0.89, 5834.992, 1721.53 + 0.25, 30000.0, 0.91, 5966.37, 1763.78 + 0.25, 30000.0, 0.93, 6097.574, 1807.6 + 0.25, 30000.0, 0.95, 6228.556, 1853.29 + 0.25, 30000.0, 0.97, 6359.268, 1901.15 + 0.25, 30000.0, 0.99, 6489.662, 1951.47 + 0.25, 35000.0, 0.0, 199.7804, 199.78 + 0.25, 35000.0, 0.05, 290.25, 264.275 + 0.25, 35000.0, 0.07, 409.5921, 285.228 + 0.25, 35000.0, 0.09, 529.6748, 307.383 + 0.25, 35000.0, 0.11, 650.4194, 330.668 + 0.25, 35000.0, 0.13, 771.7472, 355.011 + 0.25, 35000.0, 0.15, 893.5795, 380.34 + 0.25, 35000.0, 0.17, 1015.837, 406.582 + 0.25, 35000.0, 0.19, 1138.442, 433.666 + 0.25, 35000.0, 0.21, 1261.315, 461.518 + 0.25, 35000.0, 0.23, 1384.377, 490.066 + 0.25, 35000.0, 0.25, 1507.55, 519.238 + 0.25, 35000.0, 0.27, 1630.755, 548.962 + 0.25, 35000.0, 0.29, 1753.913, 579.166 + 0.25, 35000.0, 0.31, 1876.845, 610.314 + 0.25, 35000.0, 0.33, 1999.496, 642.204 + 0.25, 35000.0, 0.35, 2121.938, 673.966 + 0.25, 35000.0, 0.37, 2244.139, 705.266 + 0.25, 35000.0, 0.39, 2366.07, 735.773 + 0.25, 35000.0, 0.41, 2487.697, 762.422 + 0.25, 35000.0, 0.43, 2608.991, 785.541 + 0.25, 35000.0, 0.45, 2729.928, 808.855 + 0.25, 35000.0, 0.47, 2850.48, 833.355 + 0.25, 35000.0, 0.49, 2970.619, 860.034 + 0.25, 35000.0, 0.51, 3089.863, 894.133 + 0.25, 35000.0, 0.53, 3208.294, 935.613 + 0.25, 35000.0, 0.55, 3326.558, 979.156 + 0.25, 35000.0, 0.57, 3444.847, 1023.69 + 0.25, 35000.0, 0.59, 3563.355, 1068.16 + 0.25, 35000.0, 0.61, 3683.101, 1109.26 + 0.25, 35000.0, 0.63, 3804.076, 1146.49 + 0.25, 35000.0, 0.65, 3925.244, 1182.03 + 0.25, 35000.0, 0.67, 4046.393, 1215.91 + 0.25, 35000.0, 0.69, 4167.315, 1248.12 + 0.25, 35000.0, 0.71, 4286.745, 1276.42 + 0.25, 35000.0, 0.73, 4404.729, 1301.35 + 0.25, 35000.0, 0.75, 4522.623, 1326.26 + 0.25, 35000.0, 0.77, 4640.731, 1352.24 + 0.25, 35000.0, 0.79, 4759.352, 1380.38 + 0.25, 35000.0, 0.81, 4879.945, 1416.13 + 0.25, 35000.0, 0.83, 5002.532, 1459.54 + 0.25, 35000.0, 0.85, 5125.698, 1505.22 + 0.25, 35000.0, 0.87, 5249.185, 1552.15 + 0.25, 35000.0, 0.89, 5372.733, 1599.31 + 0.25, 35000.0, 0.91, 5496.085, 1645.67 + 0.25, 35000.0, 0.93, 5618.982, 1690.22 + 0.25, 35000.0, 0.95, 5741.164, 1731.94 + 0.25, 35000.0, 0.97, 5862.374, 1769.8 + 0.25, 35000.0, 0.99, 5982.353, 1802.78 + 0.25, 40000.0, 0.0, 158.1067, 158.107 + 0.25, 40000.0, 0.05, 243.9, 213.325 + 0.25, 40000.0, 0.07, 337.4679, 242.034 + 0.25, 40000.0, 0.09, 430.8767, 267.722 + 0.25, 40000.0, 0.11, 524.2063, 290.839 + 0.25, 40000.0, 0.13, 617.5366, 311.836 + 0.25, 40000.0, 0.15, 710.9473, 331.165 + 0.25, 40000.0, 0.17, 804.5183, 349.277 + 0.25, 40000.0, 0.19, 898.3294, 366.623 + 0.25, 40000.0, 0.21, 992.4605, 383.655 + 0.25, 40000.0, 0.23, 1086.991, 400.823 + 0.25, 40000.0, 0.25, 1182.002, 418.578 + 0.25, 40000.0, 0.27, 1277.572, 437.373 + 0.25, 40000.0, 0.29, 1373.781, 457.658 + 0.25, 40000.0, 0.31, 1471.568, 482.519 + 0.25, 40000.0, 0.33, 1570.805, 511.768 + 0.25, 40000.0, 0.35, 1670.295, 541.945 + 0.25, 40000.0, 0.37, 1769.704, 572.224 + 0.25, 40000.0, 0.39, 1868.693, 601.778 + 0.25, 40000.0, 0.41, 1965.851, 626.208 + 0.25, 40000.0, 0.43, 2061.102, 645.553 + 0.25, 40000.0, 0.45, 2155.706, 664.294 + 0.25, 40000.0, 0.47, 2249.849, 683.337 + 0.25, 40000.0, 0.49, 2343.714, 703.588 + 0.25, 40000.0, 0.51, 2437.42, 729.936 + 0.25, 40000.0, 0.53, 2531.168, 762.323 + 0.25, 40000.0, 0.55, 2625.242, 795.741 + 0.25, 40000.0, 0.57, 2719.859, 829.165 + 0.25, 40000.0, 0.59, 2815.234, 861.573 + 0.25, 40000.0, 0.61, 2912.86, 888.604 + 0.25, 40000.0, 0.63, 3012.643, 910.044 + 0.25, 40000.0, 0.65, 3112.911, 929.817 + 0.25, 40000.0, 0.67, 3213.263, 948.517 + 0.25, 40000.0, 0.69, 3313.3, 966.736 + 0.25, 40000.0, 0.71, 3411.617, 984.523 + 0.25, 40000.0, 0.73, 3508.058, 1002.6 + 0.25, 40000.0, 0.75, 3603.713, 1022.37 + 0.25, 40000.0, 0.77, 3698.667, 1044.68 + 0.25, 40000.0, 0.79, 3793.008, 1070.4 + 0.25, 40000.0, 0.81, 3886.29, 1105.82 + 0.25, 40000.0, 0.83, 3978.73, 1150.47 + 0.25, 40000.0, 0.85, 4071.202, 1197.13 + 0.25, 40000.0, 0.87, 4164.048, 1244.01 + 0.25, 40000.0, 0.89, 4257.615, 1289.33 + 0.25, 40000.0, 0.91, 4352.244, 1331.31 + 0.25, 40000.0, 0.93, 4448.28, 1368.15 + 0.25, 40000.0, 0.95, 4546.067, 1398.08 + 0.25, 40000.0, 0.97, 4645.949, 1419.3 + 0.25, 40000.0, 0.99, 4748.268, 1430.04 + 0.25, 43000.0, 0.0, 136.9547, 136.955 + 0.25, 43000.0, 0.05, 177.3, 230.2 + 0.25, 43000.0, 0.07, 285.8468, 261.67 + 0.25, 43000.0, 0.09, 386.5354, 289.905 + 0.25, 43000.0, 0.11, 480.367, 315.15 + 0.25, 43000.0, 0.13, 568.3429, 337.654 + 0.25, 43000.0, 0.15, 651.4643, 357.664 + 0.25, 43000.0, 0.17, 730.7324, 375.427 + 0.25, 43000.0, 0.19, 807.1486, 391.191 + 0.25, 43000.0, 0.21, 881.7139, 405.202 + 0.25, 43000.0, 0.23, 955.4297, 417.708 + 0.25, 43000.0, 0.25, 1029.297, 428.957 + 0.25, 43000.0, 0.27, 1104.318, 439.196 + 0.25, 43000.0, 0.29, 1181.492, 448.671 + 0.25, 43000.0, 0.31, 1266.903, 455.169 + 0.25, 43000.0, 0.33, 1360.32, 459.534 + 0.25, 43000.0, 0.35, 1455.2, 465.669 + 0.25, 43000.0, 0.37, 1550.08, 475.013 + 0.25, 43000.0, 0.39, 1643.497, 489.008 + 0.25, 43000.0, 0.41, 1728.574, 519.506 + 0.25, 43000.0, 0.43, 1805.161, 565.424 + 0.25, 43000.0, 0.45, 1879.838, 612.744 + 0.25, 43000.0, 0.47, 1953.766, 657.857 + 0.25, 43000.0, 0.49, 2028.109, 697.157 + 0.25, 43000.0, 0.51, 2107.867, 711.586 + 0.25, 43000.0, 0.53, 2193.273, 701.283 + 0.25, 43000.0, 0.55, 2279.794, 685.581 + 0.25, 43000.0, 0.57, 2366.732, 668.366 + 0.25, 43000.0, 0.59, 2453.392, 653.52 + 0.25, 43000.0, 0.61, 2536.547, 655.075 + 0.25, 43000.0, 0.63, 2616.113, 674.453 + 0.25, 43000.0, 0.65, 2695.15, 700.475 + 0.25, 43000.0, 0.67, 2774.187, 732.105 + 0.25, 43000.0, 0.69, 2853.753, 768.307 + 0.25, 43000.0, 0.71, 2936.908, 809.397 + 0.25, 43000.0, 0.73, 3023.568, 854.012 + 0.25, 43000.0, 0.75, 3110.506, 899.113 + 0.25, 43000.0, 0.77, 3197.027, 943.009 + 0.25, 43000.0, 0.79, 3282.433, 984.012 + 0.25, 43000.0, 0.81, 3363.082, 1013.57 + 0.25, 43000.0, 0.83, 3438.991, 1031.66 + 0.25, 43000.0, 0.85, 3513.837, 1046.77 + 0.25, 43000.0, 0.87, 3588.352, 1060.55 + 0.25, 43000.0, 0.89, 3663.265, 1074.64 + 0.25, 43000.0, 0.91, 3739.309, 1090.65 + 0.25, 43000.0, 0.93, 3817.214, 1110.25 + 0.25, 43000.0, 0.95, 3897.712, 1135.05 + 0.25, 43000.0, 0.97, 3981.535, 1166.7 + 0.25, 43000.0, 0.99, 4069.412, 1206.84 + 0.25, 48000.0, 0.0, 107.8111, 107.811 + 0.25, 48000.0, 0.05, 156.0, 217.7 + 0.25, 48000.0, 0.07, 238.8496, 238.793 + 0.25, 48000.0, 0.09, 316.6142, 257.066 + 0.25, 48000.0, 0.11, 389.8663, 272.805 + 0.25, 48000.0, 0.13, 459.1779, 286.299 + 0.25, 48000.0, 0.15, 525.1214, 297.836 + 0.25, 48000.0, 0.17, 588.2691, 307.702 + 0.25, 48000.0, 0.19, 649.193, 316.186 + 0.25, 48000.0, 0.21, 708.4656, 323.576 + 0.25, 48000.0, 0.23, 766.6591, 330.159 + 0.25, 48000.0, 0.25, 824.3457, 336.223 + 0.25, 48000.0, 0.27, 882.0977, 342.055 + 0.25, 48000.0, 0.29, 940.4873, 347.944 + 0.25, 48000.0, 0.31, 1001.521, 353.179 + 0.25, 48000.0, 0.33, 1065.424, 358.288 + 0.25, 48000.0, 0.35, 1130.637, 365.044 + 0.25, 48000.0, 0.37, 1197.039, 374.217 + 0.25, 48000.0, 0.39, 1264.506, 386.581 + 0.25, 48000.0, 0.41, 1333.112, 409.655 + 0.25, 48000.0, 0.43, 1402.687, 442.575 + 0.25, 48000.0, 0.45, 1472.813, 476.094 + 0.25, 48000.0, 0.47, 1543.27, 507.71 + 0.25, 48000.0, 0.49, 1613.841, 534.925 + 0.25, 48000.0, 0.51, 1685.201, 543.433 + 0.25, 48000.0, 0.53, 1756.914, 533.597 + 0.25, 48000.0, 0.55, 1827.431, 520.444 + 0.25, 48000.0, 0.57, 1896.098, 507.196 + 0.25, 48000.0, 0.59, 1962.261, 497.078 + 0.25, 48000.0, 0.61, 2020.065, 503.597 + 0.25, 48000.0, 0.63, 2070.117, 527.483 + 0.25, 48000.0, 0.65, 2119.487, 556.687 + 0.25, 48000.0, 0.67, 2170.046, 589.448 + 0.25, 48000.0, 0.69, 2223.662, 624.002 + 0.25, 48000.0, 0.71, 2290.709, 655.264 + 0.25, 48000.0, 0.73, 2370.994, 682.276 + 0.25, 48000.0, 0.75, 2453.756, 708.206 + 0.25, 48000.0, 0.77, 2536.741, 732.903 + 0.25, 48000.0, 0.79, 2617.692, 756.213 + 0.25, 48000.0, 0.81, 2687.38, 775.906 + 0.25, 48000.0, 0.83, 2745.241, 792.333 + 0.25, 48000.0, 0.85, 2799.375, 808.425 + 0.25, 48000.0, 0.87, 2850.909, 825.037 + 0.25, 48000.0, 0.89, 2900.97, 843.024 + 0.25, 48000.0, 0.91, 2950.684, 863.24 + 0.25, 48000.0, 0.93, 3001.177, 886.539 + 0.25, 48000.0, 0.95, 3053.575, 913.775 + 0.25, 48000.0, 0.97, 3109.005, 945.803 + 0.25, 48000.0, 0.99, 3168.594, 983.478 + 0.3, 0.0, 0.0, 750.0733, 750.073 + 0.3, 0.0, 0.05, 900.2438, 781.631 + 0.3, 0.0, 0.07, 1260.567, 900.276 + 0.3, 0.0, 0.09, 1620.862, 1018.35 + 0.3, 0.0, 0.11, 1981.132, 1135.93 + 0.3, 0.0, 0.13, 2341.379, 1253.07 + 0.3, 0.0, 0.15, 2701.606, 1369.84 + 0.3, 0.0, 0.17, 3061.815, 1486.31 + 0.3, 0.0, 0.19, 3422.008, 1602.55 + 0.3, 0.0, 0.21, 3782.189, 1718.62 + 0.3, 0.0, 0.23, 4142.358, 1834.58 + 0.3, 0.0, 0.25, 4502.519, 1950.51 + 0.3, 0.0, 0.27, 4862.674, 2066.46 + 0.3, 0.0, 0.29, 5222.825, 2182.52 + 0.3, 0.0, 0.31, 5582.975, 2298.73 + 0.3, 0.0, 0.33, 5943.126, 2415.18 + 0.3, 0.0, 0.35, 6303.281, 2531.92 + 0.3, 0.0, 0.37, 6663.442, 2649.02 + 0.3, 0.0, 0.39, 7023.611, 2766.55 + 0.3, 0.0, 0.41, 7383.801, 2884.61 + 0.3, 0.0, 0.43, 7744.012, 3003.26 + 0.3, 0.0, 0.45, 8104.231, 3122.51 + 0.3, 0.0, 0.47, 8464.456, 3242.42 + 0.3, 0.0, 0.49, 8824.685, 3363.02 + 0.3, 0.0, 0.51, 9184.915, 3484.33 + 0.3, 0.0, 0.53, 9545.144, 3606.4 + 0.3, 0.0, 0.55, 9905.369, 3729.36 + 0.3, 0.0, 0.57, 10265.59, 3853.27 + 0.3, 0.0, 0.59, 10625.8, 3978.22 + 0.3, 0.0, 0.61, 10985.99, 4104.58 + 0.3, 0.0, 0.63, 11346.15, 4232.35 + 0.3, 0.0, 0.65, 11706.31, 4361.15 + 0.3, 0.0, 0.67, 12066.47, 4490.89 + 0.3, 0.0, 0.69, 12426.62, 4621.5 + 0.3, 0.0, 0.71, 12786.78, 4752.6 + 0.3, 0.0, 0.73, 13146.94, 4884.2 + 0.3, 0.0, 0.75, 13507.11, 5016.63 + 0.3, 0.0, 0.77, 13867.3, 5149.97 + 0.3, 0.0, 0.79, 14227.49, 5284.27 + 0.3, 0.0, 0.81, 14587.74, 5419.46 + 0.3, 0.0, 0.83, 14948.03, 5555.63 + 0.3, 0.0, 0.85, 15308.33, 5693.04 + 0.3, 0.0, 0.87, 15668.61, 5831.84 + 0.3, 0.0, 0.89, 16028.88, 5972.14 + 0.3, 0.0, 0.91, 16389.11, 6114.08 + 0.3, 0.0, 0.93, 16749.31, 6257.78 + 0.3, 0.0, 0.95, 17109.45, 6403.38 + 0.3, 0.0, 0.97, 17469.53, 6551.0 + 0.3, 0.0, 0.99, 17829.53, 6700.77 + 0.3, 2000.0, 0.0, 702.2754, 702.275 + 0.3, 2000.0, 0.05, 865.2125, 739.319 + 0.3, 2000.0, 0.07, 1211.461, 851.738 + 0.3, 2000.0, 0.09, 1557.691, 963.685 + 0.3, 2000.0, 0.11, 1903.905, 1075.22 + 0.3, 2000.0, 0.13, 2250.103, 1186.41 + 0.3, 2000.0, 0.15, 2596.288, 1297.31 + 0.3, 2000.0, 0.17, 2942.46, 1407.98 + 0.3, 2000.0, 0.19, 3288.622, 1518.49 + 0.3, 2000.0, 0.21, 3634.776, 1628.89 + 0.3, 2000.0, 0.23, 3980.922, 1739.26 + 0.3, 2000.0, 0.25, 4327.063, 1849.64 + 0.3, 2000.0, 0.27, 4673.199, 1960.11 + 0.3, 2000.0, 0.29, 5019.333, 2070.72 + 0.3, 2000.0, 0.31, 5365.467, 2181.54 + 0.3, 2000.0, 0.33, 5711.601, 2292.62 + 0.3, 2000.0, 0.35, 6057.738, 2404.03 + 0.3, 2000.0, 0.37, 6403.878, 2515.83 + 0.3, 2000.0, 0.39, 6750.024, 2628.09 + 0.3, 2000.0, 0.41, 7096.184, 2740.85 + 0.3, 2000.0, 0.43, 7442.358, 2854.2 + 0.3, 2000.0, 0.45, 7788.538, 2968.18 + 0.3, 2000.0, 0.47, 8134.721, 3082.86 + 0.3, 2000.0, 0.49, 8480.907, 3198.28 + 0.3, 2000.0, 0.51, 8827.095, 3314.56 + 0.3, 2000.0, 0.53, 9173.284, 3431.73 + 0.3, 2000.0, 0.55, 9519.469, 3549.82 + 0.3, 2000.0, 0.57, 9865.648, 3668.86 + 0.3, 2000.0, 0.59, 10211.82, 3788.89 + 0.3, 2000.0, 0.61, 10557.96, 3910.21 + 0.3, 2000.0, 0.63, 10904.08, 4032.79 + 0.3, 2000.0, 0.65, 11250.19, 4156.33 + 0.3, 2000.0, 0.67, 11596.31, 4280.76 + 0.3, 2000.0, 0.69, 11942.43, 4406.0 + 0.3, 2000.0, 0.71, 12288.59, 4531.6 + 0.3, 2000.0, 0.73, 12634.79, 4657.59 + 0.3, 2000.0, 0.75, 12980.99, 4784.46 + 0.3, 2000.0, 0.77, 13327.2, 4912.31 + 0.3, 2000.0, 0.79, 13673.4, 5041.27 + 0.3, 2000.0, 0.81, 14019.58, 5171.53 + 0.3, 2000.0, 0.83, 14365.72, 5303.17 + 0.3, 2000.0, 0.85, 14711.86, 5436.2 + 0.3, 2000.0, 0.87, 15058.0, 5570.68 + 0.3, 2000.0, 0.89, 15404.13, 5706.7 + 0.3, 2000.0, 0.91, 15750.27, 5844.31 + 0.3, 2000.0, 0.93, 16096.41, 5983.61 + 0.3, 2000.0, 0.95, 16442.56, 6124.65 + 0.3, 2000.0, 0.97, 16788.73, 6267.52 + 0.3, 2000.0, 0.99, 17134.9, 6412.28 + 0.3, 5000.0, 0.0, 635.1355, 635.136 + 0.3, 5000.0, 0.05, 812.6, 678.838 + 0.3, 5000.0, 0.07, 1137.64, 782.243 + 0.3, 5000.0, 0.09, 1462.68, 885.292 + 0.3, 5000.0, 0.11, 1787.72, 988.041 + 0.3, 5000.0, 0.13, 2112.76, 1090.55 + 0.3, 5000.0, 0.15, 2437.8, 1192.86 + 0.3, 5000.0, 0.17, 2762.84, 1295.05 + 0.3, 5000.0, 0.19, 3087.88, 1397.16 + 0.3, 5000.0, 0.21, 3412.92, 1499.25 + 0.3, 5000.0, 0.23, 3737.96, 1601.37 + 0.3, 5000.0, 0.25, 4063.0, 1703.59 + 0.3, 5000.0, 0.27, 4388.04, 1805.95 + 0.3, 5000.0, 0.29, 4713.08, 1908.52 + 0.3, 5000.0, 0.31, 5038.12, 2011.35 + 0.3, 5000.0, 0.33, 5363.16, 2114.5 + 0.3, 5000.0, 0.35, 5688.2, 2218.01 + 0.3, 5000.0, 0.37, 6013.24, 2321.96 + 0.3, 5000.0, 0.39, 6338.28, 2426.39 + 0.3, 5000.0, 0.41, 6663.318, 2531.34 + 0.3, 5000.0, 0.43, 6988.355, 2636.87 + 0.3, 5000.0, 0.45, 7313.394, 2743.07 + 0.3, 5000.0, 0.47, 7638.434, 2850.0 + 0.3, 5000.0, 0.49, 7963.477, 2957.72 + 0.3, 5000.0, 0.51, 8288.529, 3066.4 + 0.3, 5000.0, 0.53, 8613.589, 3176.08 + 0.3, 5000.0, 0.55, 8938.65, 3286.68 + 0.3, 5000.0, 0.57, 9263.711, 3398.21 + 0.3, 5000.0, 0.59, 9588.771, 3510.7 + 0.3, 5000.0, 0.61, 9913.823, 3624.28 + 0.3, 5000.0, 0.63, 10238.87, 3738.96 + 0.3, 5000.0, 0.65, 10563.91, 3854.54 + 0.3, 5000.0, 0.67, 10888.94, 3970.97 + 0.3, 5000.0, 0.69, 11213.98, 4088.2 + 0.3, 5000.0, 0.71, 11539.02, 4205.75 + 0.3, 5000.0, 0.73, 11864.05, 4323.67 + 0.3, 5000.0, 0.75, 12189.09, 4442.57 + 0.3, 5000.0, 0.77, 12514.13, 4562.59 + 0.3, 5000.0, 0.79, 12839.17, 4683.91 + 0.3, 5000.0, 0.81, 13164.24, 4807.09 + 0.3, 5000.0, 0.83, 13489.32, 4932.2 + 0.3, 5000.0, 0.85, 13814.41, 5058.78 + 0.3, 5000.0, 0.87, 14139.49, 5186.79 + 0.3, 5000.0, 0.89, 14464.57, 5316.19 + 0.3, 5000.0, 0.91, 14789.63, 5446.94 + 0.3, 5000.0, 0.93, 15114.68, 5579.01 + 0.3, 5000.0, 0.95, 15439.72, 5712.35 + 0.3, 5000.0, 0.97, 15764.73, 5846.92 + 0.3, 5000.0, 0.99, 16089.72, 5982.68 + 0.3, 10000.0, 0.0, 534.6256, 534.626 + 0.3, 10000.0, 0.05, 706.7, 579.706 + 0.3, 10000.0, 0.07, 989.34, 666.817 + 0.3, 10000.0, 0.09, 1271.98, 753.716 + 0.3, 10000.0, 0.11, 1554.62, 840.448 + 0.3, 10000.0, 0.13, 1837.26, 927.059 + 0.3, 10000.0, 0.15, 2119.9, 1013.59 + 0.3, 10000.0, 0.17, 2402.54, 1100.1 + 0.3, 10000.0, 0.19, 2685.18, 1186.62 + 0.3, 10000.0, 0.21, 2967.82, 1273.2 + 0.3, 10000.0, 0.23, 3250.46, 1359.89 + 0.3, 10000.0, 0.25, 3533.1, 1446.73 + 0.3, 10000.0, 0.27, 3815.74, 1533.77 + 0.3, 10000.0, 0.29, 4098.38, 1621.05 + 0.3, 10000.0, 0.31, 4381.02, 1708.62 + 0.3, 10000.0, 0.33, 4663.66, 1796.53 + 0.3, 10000.0, 0.35, 4946.3, 1884.82 + 0.3, 10000.0, 0.37, 5228.94, 1973.53 + 0.3, 10000.0, 0.39, 5511.58, 2062.72 + 0.3, 10000.0, 0.41, 5794.217, 2152.38 + 0.3, 10000.0, 0.43, 6076.851, 2242.57 + 0.3, 10000.0, 0.45, 6359.488, 2333.4 + 0.3, 10000.0, 0.47, 6642.128, 2424.93 + 0.3, 10000.0, 0.49, 6924.774, 2517.24 + 0.3, 10000.0, 0.51, 7207.439, 2610.58 + 0.3, 10000.0, 0.53, 7490.122, 2704.96 + 0.3, 10000.0, 0.55, 7772.806, 2800.17 + 0.3, 10000.0, 0.57, 8055.489, 2896.18 + 0.3, 10000.0, 0.59, 8338.165, 2992.94 + 0.3, 10000.0, 0.61, 8620.815, 3090.29 + 0.3, 10000.0, 0.63, 8903.439, 3188.22 + 0.3, 10000.0, 0.65, 9186.056, 3286.94 + 0.3, 10000.0, 0.67, 9468.672, 3386.47 + 0.3, 10000.0, 0.69, 9751.289, 3486.87 + 0.3, 10000.0, 0.71, 10033.91, 3588.05 + 0.3, 10000.0, 0.73, 10316.55, 3690.09 + 0.3, 10000.0, 0.75, 10599.2, 3793.21 + 0.3, 10000.0, 0.77, 10881.87, 3897.48 + 0.3, 10000.0, 0.79, 11164.55, 4003.03 + 0.3, 10000.0, 0.81, 11447.3, 4110.24 + 0.3, 10000.0, 0.83, 11730.1, 4219.14 + 0.3, 10000.0, 0.85, 12012.9, 4329.38 + 0.3, 10000.0, 0.87, 12295.69, 4440.88 + 0.3, 10000.0, 0.89, 12578.44, 4553.6 + 0.3, 10000.0, 0.91, 12861.15, 4667.48 + 0.3, 10000.0, 0.93, 13143.79, 4782.48 + 0.3, 10000.0, 0.95, 13426.35, 4898.53 + 0.3, 10000.0, 0.97, 13708.82, 5015.57 + 0.3, 10000.0, 0.99, 13991.17, 5133.57 + 0.3, 15000.0, 0.0, 447.1509, 447.151 + 0.3, 15000.0, 0.05, 586.6, 456.3 + 0.3, 15000.0, 0.07, 821.2658, 527.917 + 0.3, 15000.0, 0.09, 1055.921, 598.762 + 0.3, 15000.0, 0.11, 1290.568, 668.924 + 0.3, 15000.0, 0.13, 1525.207, 738.493 + 0.3, 15000.0, 0.15, 1759.839, 807.557 + 0.3, 15000.0, 0.17, 1994.466, 876.207 + 0.3, 15000.0, 0.19, 2229.09, 944.532 + 0.3, 15000.0, 0.21, 2463.71, 1012.62 + 0.3, 15000.0, 0.23, 2698.329, 1080.56 + 0.3, 15000.0, 0.25, 2932.947, 1148.45 + 0.3, 15000.0, 0.27, 3167.567, 1216.37 + 0.3, 15000.0, 0.29, 3402.188, 1284.41 + 0.3, 15000.0, 0.31, 3636.819, 1352.77 + 0.3, 15000.0, 0.33, 3871.459, 1421.53 + 0.3, 15000.0, 0.35, 4106.1, 1490.59 + 0.3, 15000.0, 0.37, 4340.741, 1559.99 + 0.3, 15000.0, 0.39, 4575.381, 1629.76 + 0.3, 15000.0, 0.41, 4810.01, 1699.91 + 0.3, 15000.0, 0.43, 5044.627, 1770.47 + 0.3, 15000.0, 0.45, 5279.244, 1841.54 + 0.3, 15000.0, 0.47, 5513.863, 1913.15 + 0.3, 15000.0, 0.49, 5748.486, 1985.36 + 0.3, 15000.0, 0.51, 5983.126, 2058.36 + 0.3, 15000.0, 0.53, 6217.783, 2132.18 + 0.3, 15000.0, 0.55, 6452.444, 2206.63 + 0.3, 15000.0, 0.57, 6687.107, 2281.7 + 0.3, 15000.0, 0.59, 6921.77, 2357.36 + 0.3, 15000.0, 0.61, 7156.423, 2433.44 + 0.3, 15000.0, 0.63, 7391.066, 2509.95 + 0.3, 15000.0, 0.65, 7625.706, 2587.09 + 0.3, 15000.0, 0.67, 7860.345, 2664.91 + 0.3, 15000.0, 0.69, 8094.982, 2743.45 + 0.3, 15000.0, 0.71, 8329.617, 2822.74 + 0.3, 15000.0, 0.73, 8564.251, 2902.85 + 0.3, 15000.0, 0.75, 8798.887, 2983.82 + 0.3, 15000.0, 0.77, 9033.528, 3065.71 + 0.3, 15000.0, 0.79, 9268.174, 3148.58 + 0.3, 15000.0, 0.81, 9502.843, 3232.65 + 0.3, 15000.0, 0.83, 9737.531, 3317.92 + 0.3, 15000.0, 0.85, 9972.219, 3404.2 + 0.3, 15000.0, 0.87, 10206.9, 3491.45 + 0.3, 15000.0, 0.89, 10441.57, 3579.65 + 0.3, 15000.0, 0.91, 10676.22, 3668.77 + 0.3, 15000.0, 0.93, 10910.85, 3758.77 + 0.3, 15000.0, 0.95, 11145.46, 3849.62 + 0.3, 15000.0, 0.97, 11380.02, 3941.3 + 0.3, 15000.0, 0.99, 11614.55, 4033.78 + 0.3, 20000.0, 0.0, 371.4245, 371.425 + 0.3, 20000.0, 0.05, 486.2, 381.0 + 0.3, 20000.0, 0.07, 680.7753, 438.636 + 0.3, 20000.0, 0.09, 875.3563, 495.588 + 0.3, 20000.0, 0.11, 1069.942, 551.942 + 0.3, 20000.0, 0.13, 1264.531, 607.787 + 0.3, 20000.0, 0.15, 1459.121, 663.211 + 0.3, 20000.0, 0.17, 1653.713, 718.3 + 0.3, 20000.0, 0.19, 1848.305, 773.143 + 0.3, 20000.0, 0.21, 2042.895, 827.828 + 0.3, 20000.0, 0.23, 2237.482, 882.442 + 0.3, 20000.0, 0.25, 2432.066, 937.073 + 0.3, 20000.0, 0.27, 2626.644, 991.808 + 0.3, 20000.0, 0.29, 2821.217, 1046.74 + 0.3, 20000.0, 0.31, 3015.781, 1102.17 + 0.3, 20000.0, 0.33, 3210.336, 1158.13 + 0.3, 20000.0, 0.35, 3404.881, 1214.39 + 0.3, 20000.0, 0.37, 3599.417, 1270.93 + 0.3, 20000.0, 0.39, 3793.942, 1327.72 + 0.3, 20000.0, 0.41, 3988.449, 1384.52 + 0.3, 20000.0, 0.43, 4182.938, 1441.38 + 0.3, 20000.0, 0.45, 4377.419, 1498.59 + 0.3, 20000.0, 0.47, 4571.894, 1556.24 + 0.3, 20000.0, 0.49, 4766.365, 1614.4 + 0.3, 20000.0, 0.51, 4960.82, 1673.49 + 0.3, 20000.0, 0.53, 5155.265, 1733.53 + 0.3, 20000.0, 0.55, 5349.725, 1794.09 + 0.3, 20000.0, 0.57, 5544.209, 1855.1 + 0.3, 20000.0, 0.59, 5738.726, 1916.49 + 0.3, 20000.0, 0.61, 5933.336, 1977.72 + 0.3, 20000.0, 0.63, 6128.036, 2038.82 + 0.3, 20000.0, 0.65, 6322.762, 2100.4 + 0.3, 20000.0, 0.67, 6517.501, 2162.6 + 0.3, 20000.0, 0.69, 6712.237, 2225.58 + 0.3, 20000.0, 0.71, 6906.952, 2289.9 + 0.3, 20000.0, 0.73, 7101.631, 2355.62 + 0.3, 20000.0, 0.75, 7296.269, 2422.22 + 0.3, 20000.0, 0.77, 7490.852, 2489.65 + 0.3, 20000.0, 0.79, 7685.37, 2557.84 + 0.3, 20000.0, 0.81, 7879.699, 2626.51 + 0.3, 20000.0, 0.83, 8073.854, 2695.64 + 0.3, 20000.0, 0.85, 8267.987, 2765.49 + 0.3, 20000.0, 0.87, 8462.141, 2836.1 + 0.3, 20000.0, 0.89, 8656.356, 2907.49 + 0.3, 20000.0, 0.91, 8850.675, 2979.72 + 0.3, 20000.0, 0.93, 9045.138, 3052.81 + 0.3, 20000.0, 0.95, 9239.787, 3126.81 + 0.3, 20000.0, 0.97, 9434.665, 3201.74 + 0.3, 20000.0, 0.99, 9629.812, 3277.66 + 0.3, 25000.0, 0.0, 306.2357, 306.236 + 0.3, 25000.0, 0.05, 404.46, 321.04 + 0.3, 25000.0, 0.07, 565.1823, 372.46 + 0.3, 25000.0, 0.09, 726.0928, 421.593 + 0.3, 25000.0, 0.11, 887.1739, 468.736 + 0.3, 25000.0, 0.13, 1048.408, 514.187 + 0.3, 25000.0, 0.15, 1209.778, 558.242 + 0.3, 25000.0, 0.17, 1371.266, 601.198 + 0.3, 25000.0, 0.19, 1532.854, 643.351 + 0.3, 25000.0, 0.21, 1694.525, 684.999 + 0.3, 25000.0, 0.23, 1856.261, 726.439 + 0.3, 25000.0, 0.25, 2018.045, 767.967 + 0.3, 25000.0, 0.27, 2179.86, 809.879 + 0.3, 25000.0, 0.29, 2341.687, 852.474 + 0.3, 25000.0, 0.31, 2503.507, 897.182 + 0.3, 25000.0, 0.33, 2665.303, 944.025 + 0.3, 25000.0, 0.35, 2827.061, 991.615 + 0.3, 25000.0, 0.37, 2988.764, 1039.7 + 0.3, 25000.0, 0.39, 3150.396, 1088.03 + 0.3, 25000.0, 0.41, 3311.871, 1135.82 + 0.3, 25000.0, 0.43, 3473.189, 1182.95 + 0.3, 25000.0, 0.45, 3634.436, 1229.94 + 0.3, 25000.0, 0.47, 3795.631, 1276.8 + 0.3, 25000.0, 0.49, 3956.789, 1323.51 + 0.3, 25000.0, 0.51, 4117.935, 1369.41 + 0.3, 25000.0, 0.53, 4279.083, 1414.65 + 0.3, 25000.0, 0.55, 4440.242, 1460.25 + 0.3, 25000.0, 0.57, 4601.427, 1506.54 + 0.3, 25000.0, 0.59, 4762.65, 1553.84 + 0.3, 25000.0, 0.61, 4923.917, 1603.69 + 0.3, 25000.0, 0.63, 5085.244, 1656.12 + 0.3, 25000.0, 0.65, 5246.659, 1709.69 + 0.3, 25000.0, 0.67, 5408.18, 1764.15 + 0.3, 25000.0, 0.69, 5569.825, 1819.25 + 0.3, 25000.0, 0.71, 5731.783, 1874.21 + 0.3, 25000.0, 0.73, 5894.031, 1928.92 + 0.3, 25000.0, 0.75, 6056.335, 1983.9 + 0.3, 25000.0, 0.77, 6218.631, 2039.15 + 0.3, 25000.0, 0.79, 6380.855, 2094.67 + 0.3, 25000.0, 0.81, 6542.801, 2150.3 + 0.3, 25000.0, 0.83, 6704.44, 2206.06 + 0.3, 25000.0, 0.85, 6865.918, 2262.25 + 0.3, 25000.0, 0.87, 7027.239, 2318.94 + 0.3, 25000.0, 0.89, 7188.41, 2376.22 + 0.3, 25000.0, 0.91, 7349.434, 2434.2 + 0.3, 25000.0, 0.93, 7510.317, 2492.95 + 0.3, 25000.0, 0.95, 7671.063, 2552.58 + 0.3, 25000.0, 0.97, 7831.676, 2613.16 + 0.3, 25000.0, 0.99, 7992.163, 2674.8 + 0.3, 30000.0, 0.0, 250.4603, 250.46 + 0.3, 30000.0, 0.05, 325.68, 271.04 + 0.3, 30000.0, 0.07, 456.7427, 306.563 + 0.3, 30000.0, 0.09, 587.594, 341.795 + 0.3, 30000.0, 0.11, 718.2618, 376.773 + 0.3, 30000.0, 0.13, 848.7739, 411.535 + 0.3, 30000.0, 0.15, 979.1579, 446.118 + 0.3, 30000.0, 0.17, 1109.442, 480.56 + 0.3, 30000.0, 0.19, 1239.653, 514.898 + 0.3, 30000.0, 0.21, 1369.819, 549.17 + 0.3, 30000.0, 0.23, 1499.969, 583.413 + 0.3, 30000.0, 0.25, 1630.129, 617.665 + 0.3, 30000.0, 0.27, 1760.328, 651.964 + 0.3, 30000.0, 0.29, 1890.594, 686.346 + 0.3, 30000.0, 0.31, 2021.081, 720.834 + 0.3, 30000.0, 0.33, 2151.787, 755.47 + 0.3, 30000.0, 0.35, 2282.55, 790.313 + 0.3, 30000.0, 0.37, 2413.335, 825.407 + 0.3, 30000.0, 0.39, 2544.108, 860.799 + 0.3, 30000.0, 0.41, 2674.77, 896.722 + 0.3, 30000.0, 0.43, 2805.302, 933.176 + 0.3, 30000.0, 0.45, 2935.767, 969.922 + 0.3, 30000.0, 0.47, 3066.163, 1006.91 + 0.3, 30000.0, 0.49, 3196.486, 1044.11 + 0.3, 30000.0, 0.51, 3326.639, 1081.28 + 0.3, 30000.0, 0.53, 3456.642, 1118.42 + 0.3, 30000.0, 0.55, 3586.635, 1155.75 + 0.3, 30000.0, 0.57, 3716.661, 1193.29 + 0.3, 30000.0, 0.59, 3846.765, 1231.08 + 0.3, 30000.0, 0.61, 3977.162, 1269.06 + 0.3, 30000.0, 0.63, 4107.854, 1307.28 + 0.3, 30000.0, 0.65, 4238.63, 1345.92 + 0.3, 30000.0, 0.67, 4369.451, 1385.07 + 0.3, 30000.0, 0.69, 4500.277, 1424.81 + 0.3, 30000.0, 0.71, 4630.946, 1465.6 + 0.3, 30000.0, 0.73, 4761.447, 1507.43 + 0.3, 30000.0, 0.75, 4891.926, 1549.82 + 0.3, 30000.0, 0.77, 5022.403, 1592.67 + 0.3, 30000.0, 0.79, 5152.899, 1635.85 + 0.3, 30000.0, 0.81, 5283.536, 1678.69 + 0.3, 30000.0, 0.83, 5414.311, 1721.22 + 0.3, 30000.0, 0.85, 5545.093, 1764.21 + 0.3, 30000.0, 0.87, 5675.85, 1807.83 + 0.3, 30000.0, 0.89, 5806.556, 1852.28 + 0.3, 30000.0, 0.91, 5937.18, 1897.72 + 0.3, 30000.0, 0.93, 6067.694, 1944.33 + 0.3, 30000.0, 0.95, 6198.068, 1992.31 + 0.3, 30000.0, 0.97, 6328.273, 2041.82 + 0.3, 30000.0, 0.99, 6458.28, 2093.05 + 0.3, 35000.0, 0.0, 203.0538, 203.054 + 0.3, 35000.0, 0.05, 283.5, 264.3 + 0.3, 35000.0, 0.07, 399.0911, 288.966 + 0.3, 35000.0, 0.09, 515.2109, 314.447 + 0.3, 35000.0, 0.11, 631.803, 340.693 + 0.3, 35000.0, 0.13, 748.811, 367.658 + 0.3, 35000.0, 0.15, 866.1786, 395.293 + 0.3, 35000.0, 0.17, 983.8492, 423.551 + 0.3, 35000.0, 0.19, 1101.766, 452.383 + 0.3, 35000.0, 0.21, 1219.874, 481.743 + 0.3, 35000.0, 0.23, 1338.115, 511.581 + 0.3, 35000.0, 0.25, 1456.434, 541.851 + 0.3, 35000.0, 0.27, 1574.774, 572.505 + 0.3, 35000.0, 0.29, 1693.079, 603.494 + 0.3, 35000.0, 0.31, 1811.215, 635.123 + 0.3, 35000.0, 0.33, 1929.144, 667.259 + 0.3, 35000.0, 0.35, 2046.925, 699.331 + 0.3, 35000.0, 0.37, 2164.538, 731.121 + 0.3, 35000.0, 0.39, 2281.963, 762.411 + 0.3, 35000.0, 0.41, 2399.188, 791.113 + 0.3, 35000.0, 0.43, 2516.19, 817.46 + 0.3, 35000.0, 0.45, 2632.944, 844.012 + 0.3, 35000.0, 0.47, 2749.428, 871.456 + 0.3, 35000.0, 0.49, 2865.62, 900.48 + 0.3, 35000.0, 0.51, 2981.164, 934.698 + 0.3, 35000.0, 0.53, 3096.12, 974.088 + 0.3, 35000.0, 0.55, 3210.963, 1014.99 + 0.3, 35000.0, 0.57, 3325.833, 1056.69 + 0.3, 35000.0, 0.59, 3440.873, 1098.43 + 0.3, 35000.0, 0.61, 3556.839, 1137.98 + 0.3, 35000.0, 0.63, 3673.723, 1174.97 + 0.3, 35000.0, 0.65, 3790.75, 1210.93 + 0.3, 35000.0, 0.67, 3907.761, 1245.87 + 0.3, 35000.0, 0.69, 4024.597, 1279.81 + 0.3, 35000.0, 0.71, 4140.32, 1311.19 + 0.3, 35000.0, 0.73, 4254.96, 1340.41 + 0.3, 35000.0, 0.75, 4369.519, 1369.77 + 0.3, 35000.0, 0.77, 4484.215, 1400.04 + 0.3, 35000.0, 0.79, 4599.27, 1431.97 + 0.3, 35000.0, 0.81, 4715.737, 1469.37 + 0.3, 35000.0, 0.83, 4833.635, 1512.27 + 0.3, 35000.0, 0.85, 4951.944, 1556.89 + 0.3, 35000.0, 0.87, 5070.478, 1602.52 + 0.3, 35000.0, 0.89, 5189.054, 1648.45 + 0.3, 35000.0, 0.91, 5307.487, 1693.96 + 0.3, 35000.0, 0.93, 5425.591, 1738.32 + 0.3, 35000.0, 0.95, 5543.181, 1780.84 + 0.3, 35000.0, 0.97, 5660.074, 1820.78 + 0.3, 35000.0, 0.99, 5776.084, 1857.43 + 0.3, 40000.0, 0.0, 160.6973, 160.697 + 0.3, 40000.0, 0.05, 233.5, 219.4 + 0.3, 40000.0, 0.07, 324.0903, 246.625 + 0.3, 40000.0, 0.09, 414.5856, 271.834 + 0.3, 40000.0, 0.11, 505.0393, 295.331 + 0.3, 40000.0, 0.13, 595.5048, 317.424 + 0.3, 40000.0, 0.15, 686.0357, 338.418 + 0.3, 40000.0, 0.17, 776.6855, 358.618 + 0.3, 40000.0, 0.19, 867.5076, 378.331 + 0.3, 40000.0, 0.21, 958.5555, 397.862 + 0.3, 40000.0, 0.23, 1049.883, 417.517 + 0.3, 40000.0, 0.25, 1141.543, 437.601 + 0.3, 40000.0, 0.27, 1233.589, 458.422 + 0.3, 40000.0, 0.29, 1326.075, 480.283 + 0.3, 40000.0, 0.31, 1419.644, 505.273 + 0.3, 40000.0, 0.33, 1514.205, 533.264 + 0.3, 40000.0, 0.35, 1608.938, 561.919 + 0.3, 40000.0, 0.37, 1703.611, 590.68 + 0.3, 40000.0, 0.39, 1797.992, 618.989 + 0.3, 40000.0, 0.41, 1891.106, 643.865 + 0.3, 40000.0, 0.43, 1982.902, 665.338 + 0.3, 40000.0, 0.45, 2074.25, 686.45 + 0.3, 40000.0, 0.47, 2165.278, 707.818 + 0.3, 40000.0, 0.49, 2256.114, 730.059 + 0.3, 40000.0, 0.51, 2346.838, 756.496 + 0.3, 40000.0, 0.53, 2437.59, 787.09 + 0.3, 40000.0, 0.55, 2528.569, 818.444 + 0.3, 40000.0, 0.57, 2619.925, 849.864 + 0.3, 40000.0, 0.59, 2711.811, 880.656 + 0.3, 40000.0, 0.61, 2805.262, 907.842 + 0.3, 40000.0, 0.63, 2900.214, 931.282 + 0.3, 40000.0, 0.65, 2995.506, 953.675 + 0.3, 40000.0, 0.67, 3090.86, 975.436 + 0.3, 40000.0, 0.69, 3185.998, 996.98 + 0.3, 40000.0, 0.71, 3279.951, 1018.34 + 0.3, 40000.0, 0.73, 3372.607, 1040.04 + 0.3, 40000.0, 0.75, 3464.719, 1063.02 + 0.3, 40000.0, 0.77, 3556.345, 1087.91 + 0.3, 40000.0, 0.79, 3647.543, 1115.29 + 0.3, 40000.0, 0.81, 3738.001, 1149.56 + 0.3, 40000.0, 0.83, 3827.867, 1190.41 + 0.3, 40000.0, 0.85, 3917.75, 1232.77 + 0.3, 40000.0, 0.87, 4007.889, 1275.39 + 0.3, 40000.0, 0.89, 4098.523, 1317.04 + 0.3, 40000.0, 0.91, 4189.89, 1356.45 + 0.3, 40000.0, 0.93, 4282.228, 1392.38 + 0.3, 40000.0, 0.95, 4375.775, 1423.58 + 0.3, 40000.0, 0.97, 4470.77, 1448.8 + 0.3, 40000.0, 0.99, 4567.452, 1466.8 + 0.3, 43000.0, 0.0, 139.1987, 139.199 + 0.3, 43000.0, 0.05, 177.3, 227.9 + 0.3, 43000.0, 0.07, 275.9563, 256.27 + 0.3, 43000.0, 0.09, 368.8362, 282.387 + 0.3, 43000.0, 0.11, 456.6756, 306.421 + 0.3, 43000.0, 0.13, 540.2099, 328.54 + 0.3, 43000.0, 0.15, 620.175, 348.911 + 0.3, 43000.0, 0.17, 697.3065, 367.703 + 0.3, 43000.0, 0.19, 772.34, 385.085 + 0.3, 43000.0, 0.21, 846.0114, 401.225 + 0.3, 43000.0, 0.23, 919.0561, 416.292 + 0.3, 43000.0, 0.25, 992.21, 430.453 + 0.3, 43000.0, 0.27, 1066.209, 443.877 + 0.3, 43000.0, 0.29, 1141.788, 456.733 + 0.3, 43000.0, 0.31, 1223.415, 467.296 + 0.3, 43000.0, 0.33, 1310.921, 476.195 + 0.3, 43000.0, 0.35, 1399.5, 486.406 + 0.3, 43000.0, 0.37, 1488.079, 499.015 + 0.3, 43000.0, 0.39, 1575.585, 515.108 + 0.3, 43000.0, 0.41, 1656.969, 543.533 + 0.3, 43000.0, 0.43, 1732.121, 583.494 + 0.3, 43000.0, 0.45, 1805.869, 624.55 + 0.3, 43000.0, 0.47, 1879.067, 664.022 + 0.3, 43000.0, 0.49, 1952.569, 699.231 + 0.3, 43000.0, 0.51, 2030.039, 716.037 + 0.3, 43000.0, 0.53, 2111.65, 714.54 + 0.3, 43000.0, 0.55, 2194.081, 709.081 + 0.3, 43000.0, 0.57, 2276.822, 702.541 + 0.3, 43000.0, 0.59, 2359.363, 697.798 + 0.3, 43000.0, 0.61, 2439.349, 705.227 + 0.3, 43000.0, 0.63, 2516.717, 725.891 + 0.3, 43000.0, 0.65, 2593.7, 751.537 + 0.3, 43000.0, 0.67, 2670.683, 781.412 + 0.3, 43000.0, 0.69, 2748.051, 814.76 + 0.3, 43000.0, 0.71, 2828.037, 851.878 + 0.3, 43000.0, 0.73, 2910.578, 891.756 + 0.3, 43000.0, 0.75, 2993.319, 932.075 + 0.3, 43000.0, 0.77, 3075.75, 971.57 + 0.3, 43000.0, 0.79, 3157.361, 1008.98 + 0.3, 43000.0, 0.81, 3235.485, 1037.86 + 0.3, 43000.0, 0.83, 3310.135, 1058.21 + 0.3, 43000.0, 0.85, 3384.006, 1076.43 + 0.3, 43000.0, 0.87, 3457.636, 1093.76 + 0.3, 43000.0, 0.89, 3531.56, 1111.44 + 0.3, 43000.0, 0.91, 3606.315, 1130.71 + 0.3, 43000.0, 0.93, 3682.439, 1152.81 + 0.3, 43000.0, 0.95, 3760.469, 1178.97 + 0.3, 43000.0, 0.97, 3840.94, 1210.44 + 0.3, 43000.0, 0.99, 3924.39, 1248.45 + 0.3, 48000.0, 0.0, 109.5775, 109.578 + 0.3, 48000.0, 0.05, 151.8, 206.2 + 0.3, 48000.0, 0.07, 227.5939, 225.833 + 0.3, 48000.0, 0.09, 299.638, 243.485 + 0.3, 48000.0, 0.11, 368.3541, 259.359 + 0.3, 48000.0, 0.13, 434.164, 273.656 + 0.3, 48000.0, 0.15, 497.4893, 286.579 + 0.3, 48000.0, 0.17, 558.7517, 298.329 + 0.3, 48000.0, 0.19, 618.373, 309.11 + 0.3, 48000.0, 0.21, 676.7749, 319.123 + 0.3, 48000.0, 0.23, 734.379, 328.57 + 0.3, 48000.0, 0.25, 791.6071, 337.654 + 0.3, 48000.0, 0.27, 848.881, 346.577 + 0.3, 48000.0, 0.29, 906.6223, 355.54 + 0.3, 48000.0, 0.31, 966.304, 363.955 + 0.3, 48000.0, 0.33, 1028.093, 372.216 + 0.3, 48000.0, 0.35, 1090.85, 381.7 + 0.3, 48000.0, 0.37, 1154.487, 392.992 + 0.3, 48000.0, 0.39, 1218.916, 406.677 + 0.3, 48000.0, 0.41, 1284.212, 428.377 + 0.3, 48000.0, 0.43, 1350.248, 457.457 + 0.3, 48000.0, 0.45, 1416.694, 487.025 + 0.3, 48000.0, 0.47, 1483.381, 515.225 + 0.3, 48000.0, 0.49, 1550.143, 540.201 + 0.3, 48000.0, 0.51, 1617.446, 551.349 + 0.3, 48000.0, 0.53, 1684.97, 548.933 + 0.3, 48000.0, 0.55, 1751.606, 544.088 + 0.3, 48000.0, 0.57, 1816.88, 539.198 + 0.3, 48000.0, 0.59, 1880.318, 536.65 + 0.3, 48000.0, 0.61, 1937.638, 546.411 + 0.3, 48000.0, 0.63, 1989.29, 569.029 + 0.3, 48000.0, 0.65, 2040.45, 595.631 + 0.3, 48000.0, 0.67, 2092.49, 624.927 + 0.3, 48000.0, 0.69, 2146.782, 655.627 + 0.3, 48000.0, 0.71, 2210.952, 684.051 + 0.3, 48000.0, 0.73, 2284.856, 709.487 + 0.3, 48000.0, 0.75, 2360.575, 734.194 + 0.3, 48000.0, 0.77, 2436.446, 758.038 + 0.3, 48000.0, 0.79, 2510.806, 780.889 + 0.3, 48000.0, 0.81, 2576.84, 800.98 + 0.3, 48000.0, 0.83, 2634.136, 818.575 + 0.3, 48000.0, 0.85, 2688.681, 835.969 + 0.3, 48000.0, 0.87, 2741.313, 853.82 + 0.3, 48000.0, 0.89, 2792.866, 872.79 + 0.3, 48000.0, 0.91, 2844.178, 893.537 + 0.3, 48000.0, 0.93, 2896.083, 916.723 + 0.3, 48000.0, 0.95, 2949.419, 943.006 + 0.3, 48000.0, 0.97, 3005.02, 973.048 + 0.3, 48000.0, 0.99, 3063.724, 1007.51 + 0.35, 0.0, 0.0, 764.5331, 764.533 + 0.35, 0.0, 0.05, 858.4097, 821.464 + 0.35, 0.0, 0.07, 1202.17, 944.899 + 0.35, 0.0, 0.09, 1545.9, 1067.54 + 0.35, 0.0, 0.11, 1889.603, 1189.45 + 0.35, 0.0, 0.13, 2233.28, 1310.71 + 0.35, 0.0, 0.15, 2576.934, 1431.4 + 0.35, 0.0, 0.17, 2920.568, 1551.58 + 0.35, 0.0, 0.19, 3264.183, 1671.33 + 0.35, 0.0, 0.21, 3607.783, 1790.71 + 0.35, 0.0, 0.23, 3951.37, 1909.81 + 0.35, 0.0, 0.25, 4294.946, 2028.7 + 0.35, 0.0, 0.27, 4638.514, 2147.44 + 0.35, 0.0, 0.29, 4982.076, 2266.11 + 0.35, 0.0, 0.31, 5325.634, 2384.79 + 0.35, 0.0, 0.33, 5669.191, 2503.54 + 0.35, 0.0, 0.35, 6012.75, 2622.44 + 0.35, 0.0, 0.37, 6356.313, 2741.57 + 0.35, 0.0, 0.39, 6699.882, 2860.98 + 0.35, 0.0, 0.41, 7043.47, 2980.82 + 0.35, 0.0, 0.43, 7387.076, 3101.14 + 0.35, 0.0, 0.45, 7730.688, 3221.94 + 0.35, 0.0, 0.47, 8074.306, 3343.25 + 0.35, 0.0, 0.49, 8417.925, 3465.13 + 0.35, 0.0, 0.51, 8761.544, 3587.55 + 0.35, 0.0, 0.53, 9105.159, 3710.59 + 0.35, 0.0, 0.55, 9448.771, 3834.38 + 0.35, 0.0, 0.57, 9792.378, 3958.99 + 0.35, 0.0, 0.59, 10135.98, 4084.49 + 0.35, 0.0, 0.61, 10479.56, 4211.29 + 0.35, 0.0, 0.63, 10823.12, 4339.37 + 0.35, 0.0, 0.65, 11166.67, 4468.34 + 0.35, 0.0, 0.67, 11510.23, 4598.12 + 0.35, 0.0, 0.69, 11853.79, 4728.63 + 0.35, 0.0, 0.71, 12197.38, 4859.48 + 0.35, 0.0, 0.73, 12540.99, 4990.68 + 0.35, 0.0, 0.75, 12884.61, 5122.58 + 0.35, 0.0, 0.77, 13228.24, 5255.24 + 0.35, 0.0, 0.79, 13571.87, 5388.74 + 0.35, 0.0, 0.81, 13915.51, 5523.0 + 0.35, 0.0, 0.83, 14259.16, 5658.12 + 0.35, 0.0, 0.85, 14602.8, 5794.37 + 0.35, 0.0, 0.87, 14946.43, 5931.87 + 0.35, 0.0, 0.89, 15290.05, 6070.76 + 0.35, 0.0, 0.91, 15633.64, 6211.17 + 0.35, 0.0, 0.93, 15977.21, 6353.22 + 0.35, 0.0, 0.95, 16320.74, 6497.06 + 0.35, 0.0, 0.97, 16664.24, 6642.81 + 0.35, 0.0, 0.99, 17007.7, 6790.6 + 0.35, 2000.0, 0.0, 715.8137, 715.814 + 0.35, 2000.0, 0.05, 826.43, 778.608 + 0.35, 2000.0, 0.07, 1157.087, 895.278 + 0.35, 2000.0, 0.09, 1487.729, 1011.31 + 0.35, 2000.0, 0.11, 1818.358, 1126.78 + 0.35, 2000.0, 0.13, 2148.975, 1241.74 + 0.35, 2000.0, 0.15, 2479.581, 1356.26 + 0.35, 2000.0, 0.17, 2810.178, 1470.4 + 0.35, 2000.0, 0.19, 3140.768, 1584.22 + 0.35, 2000.0, 0.21, 3471.351, 1697.79 + 0.35, 2000.0, 0.23, 3801.928, 1811.17 + 0.35, 2000.0, 0.25, 4132.503, 1924.43 + 0.35, 2000.0, 0.27, 4463.074, 2037.62 + 0.35, 2000.0, 0.29, 4793.645, 2150.81 + 0.35, 2000.0, 0.31, 5124.216, 2264.07 + 0.35, 2000.0, 0.33, 5454.788, 2377.46 + 0.35, 2000.0, 0.35, 5785.364, 2491.03 + 0.35, 2000.0, 0.37, 6115.944, 2604.86 + 0.35, 2000.0, 0.39, 6446.53, 2719.01 + 0.35, 2000.0, 0.41, 6777.129, 2833.54 + 0.35, 2000.0, 0.43, 7107.741, 2948.53 + 0.35, 2000.0, 0.45, 7438.359, 3064.01 + 0.35, 2000.0, 0.47, 7768.98, 3180.06 + 0.35, 2000.0, 0.49, 8099.603, 3296.74 + 0.35, 2000.0, 0.51, 8430.228, 3414.12 + 0.35, 2000.0, 0.53, 8760.851, 3532.27 + 0.35, 2000.0, 0.55, 9091.471, 3651.21 + 0.35, 2000.0, 0.57, 9422.085, 3770.96 + 0.35, 2000.0, 0.59, 9752.691, 3891.59 + 0.35, 2000.0, 0.61, 10083.27, 4013.4 + 0.35, 2000.0, 0.63, 10413.83, 4136.36 + 0.35, 2000.0, 0.65, 10744.39, 4260.14 + 0.35, 2000.0, 0.67, 11074.94, 4384.66 + 0.35, 2000.0, 0.69, 11405.5, 4509.85 + 0.35, 2000.0, 0.71, 11736.07, 4635.19 + 0.35, 2000.0, 0.73, 12066.67, 4760.7 + 0.35, 2000.0, 0.75, 12397.27, 4886.96 + 0.35, 2000.0, 0.77, 12727.88, 5014.1 + 0.35, 2000.0, 0.79, 13058.5, 5142.25 + 0.35, 2000.0, 0.81, 13389.14, 5271.74 + 0.35, 2000.0, 0.83, 13719.79, 5402.66 + 0.35, 2000.0, 0.85, 14050.44, 5534.86 + 0.35, 2000.0, 0.87, 14381.08, 5668.39 + 0.35, 2000.0, 0.89, 14711.72, 5803.3 + 0.35, 2000.0, 0.91, 15042.34, 5939.62 + 0.35, 2000.0, 0.93, 15372.94, 6077.42 + 0.35, 2000.0, 0.95, 15703.51, 6216.73 + 0.35, 2000.0, 0.97, 16034.06, 6357.6 + 0.35, 2000.0, 0.99, 16364.57, 6500.06 + 0.35, 5000.0, 0.0, 647.3795, 647.38 + 0.35, 5000.0, 0.05, 776.6853, 715.614 + 0.35, 5000.0, 0.07, 1087.604, 822.764 + 0.35, 5000.0, 0.09, 1398.505, 929.449 + 0.35, 5000.0, 0.11, 1709.391, 1035.72 + 0.35, 5000.0, 0.13, 2020.262, 1141.64 + 0.35, 5000.0, 0.15, 2331.121, 1247.26 + 0.35, 5000.0, 0.17, 2641.968, 1352.63 + 0.35, 5000.0, 0.19, 2952.805, 1457.81 + 0.35, 5000.0, 0.21, 3263.633, 1562.85 + 0.35, 5000.0, 0.23, 3574.454, 1667.81 + 0.35, 5000.0, 0.25, 3885.269, 1772.73 + 0.35, 5000.0, 0.27, 4196.08, 1877.68 + 0.35, 5000.0, 0.29, 4506.887, 1982.71 + 0.35, 5000.0, 0.31, 4817.693, 2087.87 + 0.35, 5000.0, 0.33, 5128.498, 2193.22 + 0.35, 5000.0, 0.35, 5439.305, 2298.81 + 0.35, 5000.0, 0.37, 5750.114, 2404.7 + 0.35, 5000.0, 0.39, 6060.927, 2510.93 + 0.35, 5000.0, 0.41, 6371.751, 2617.54 + 0.35, 5000.0, 0.43, 6682.587, 2724.58 + 0.35, 5000.0, 0.45, 6993.427, 2832.16 + 0.35, 5000.0, 0.47, 7304.268, 2940.34 + 0.35, 5000.0, 0.49, 7615.11, 3049.21 + 0.35, 5000.0, 0.51, 7925.941, 3158.97 + 0.35, 5000.0, 0.53, 8236.762, 3269.64 + 0.35, 5000.0, 0.55, 8547.585, 3381.12 + 0.35, 5000.0, 0.57, 8858.411, 3493.4 + 0.35, 5000.0, 0.59, 9169.245, 3606.5 + 0.35, 5000.0, 0.61, 9480.107, 3720.53 + 0.35, 5000.0, 0.63, 9790.995, 3835.47 + 0.35, 5000.0, 0.65, 10101.88, 3951.17 + 0.35, 5000.0, 0.67, 10412.77, 4067.59 + 0.35, 5000.0, 0.69, 10723.64, 4184.66 + 0.35, 5000.0, 0.71, 11034.46, 4301.91 + 0.35, 5000.0, 0.73, 11345.23, 4419.38 + 0.35, 5000.0, 0.75, 11655.99, 4537.72 + 0.35, 5000.0, 0.77, 11966.75, 4657.09 + 0.35, 5000.0, 0.79, 12277.52, 4777.68 + 0.35, 5000.0, 0.81, 12588.33, 4900.12 + 0.35, 5000.0, 0.83, 12899.19, 5024.48 + 0.35, 5000.0, 0.85, 13210.05, 5150.24 + 0.35, 5000.0, 0.87, 13520.92, 5277.35 + 0.35, 5000.0, 0.89, 13831.79, 5405.78 + 0.35, 5000.0, 0.91, 14142.64, 5535.46 + 0.35, 5000.0, 0.93, 14453.48, 5666.35 + 0.35, 5000.0, 0.95, 14764.29, 5798.41 + 0.35, 5000.0, 0.97, 15075.07, 5931.58 + 0.35, 5000.0, 0.99, 15385.81, 6065.81 + 0.35, 10000.0, 0.0, 544.932, 544.932 + 0.35, 10000.0, 0.05, 689.1016, 613.36 + 0.35, 10000.0, 0.07, 963.5973, 705.289 + 0.35, 10000.0, 0.09, 1238.157, 796.878 + 0.35, 10000.0, 0.11, 1512.777, 888.175 + 0.35, 10000.0, 0.13, 1787.451, 979.229 + 0.35, 10000.0, 0.15, 2062.175, 1070.09 + 0.35, 10000.0, 0.17, 2336.943, 1160.8 + 0.35, 10000.0, 0.19, 2611.752, 1251.42 + 0.35, 10000.0, 0.21, 2886.596, 1341.99 + 0.35, 10000.0, 0.23, 3161.47, 1432.55 + 0.35, 10000.0, 0.25, 3436.37, 1523.17 + 0.35, 10000.0, 0.27, 3711.291, 1613.88 + 0.35, 10000.0, 0.29, 3986.227, 1704.74 + 0.35, 10000.0, 0.31, 4261.175, 1795.79 + 0.35, 10000.0, 0.33, 4536.128, 1887.08 + 0.35, 10000.0, 0.35, 4811.083, 1978.67 + 0.35, 10000.0, 0.37, 5086.035, 2070.59 + 0.35, 10000.0, 0.39, 5360.978, 2162.9 + 0.35, 10000.0, 0.41, 5635.886, 2255.61 + 0.35, 10000.0, 0.43, 5910.759, 2348.77 + 0.35, 10000.0, 0.45, 6185.625, 2442.5 + 0.35, 10000.0, 0.47, 6460.49, 2536.86 + 0.35, 10000.0, 0.49, 6735.361, 2631.92 + 0.35, 10000.0, 0.51, 7010.262, 2727.98 + 0.35, 10000.0, 0.53, 7285.193, 2825.06 + 0.35, 10000.0, 0.55, 7560.134, 2922.88 + 0.35, 10000.0, 0.57, 7835.081, 3021.4 + 0.35, 10000.0, 0.59, 8110.03, 3120.55 + 0.35, 10000.0, 0.61, 8384.976, 3220.06 + 0.35, 10000.0, 0.63, 8659.916, 3319.92 + 0.35, 10000.0, 0.65, 8934.85, 3420.48 + 0.35, 10000.0, 0.67, 9209.777, 3521.81 + 0.35, 10000.0, 0.69, 9484.695, 3624.0 + 0.35, 10000.0, 0.71, 9759.579, 3727.14 + 0.35, 10000.0, 0.73, 10034.43, 3831.31 + 0.35, 10000.0, 0.75, 10309.29, 3936.56 + 0.35, 10000.0, 0.77, 10584.15, 4042.94 + 0.35, 10000.0, 0.79, 10859.04, 4150.53 + 0.35, 10000.0, 0.81, 11134.0, 4259.57 + 0.35, 10000.0, 0.83, 11409.04, 4370.09 + 0.35, 10000.0, 0.85, 11684.08, 4481.89 + 0.35, 10000.0, 0.87, 11959.12, 4594.96 + 0.35, 10000.0, 0.89, 12234.14, 4709.28 + 0.35, 10000.0, 0.91, 12509.13, 4824.84 + 0.35, 10000.0, 0.93, 12784.05, 4941.62 + 0.35, 10000.0, 0.95, 13058.92, 5059.61 + 0.35, 10000.0, 0.97, 13333.69, 5178.78 + 0.35, 10000.0, 0.99, 13608.37, 5299.12 + 0.35, 15000.0, 0.0, 455.771, 455.771 + 0.35, 15000.0, 0.05, 574.1187, 478.337 + 0.35, 15000.0, 0.07, 803.7896, 555.079 + 0.35, 15000.0, 0.09, 1033.452, 630.771 + 0.35, 15000.0, 0.11, 1263.108, 705.522 + 0.35, 15000.0, 0.13, 1492.757, 779.443 + 0.35, 15000.0, 0.15, 1722.402, 852.641 + 0.35, 15000.0, 0.17, 1952.043, 925.227 + 0.35, 15000.0, 0.19, 2181.682, 997.308 + 0.35, 15000.0, 0.21, 2411.318, 1068.99 + 0.35, 15000.0, 0.23, 2640.955, 1140.39 + 0.35, 15000.0, 0.25, 2870.591, 1211.62 + 0.35, 15000.0, 0.27, 3100.23, 1282.77 + 0.35, 15000.0, 0.29, 3329.872, 1353.97 + 0.35, 15000.0, 0.31, 3559.523, 1425.48 + 0.35, 15000.0, 0.33, 3789.184, 1497.38 + 0.35, 15000.0, 0.35, 4018.847, 1569.52 + 0.35, 15000.0, 0.37, 4248.51, 1641.94 + 0.35, 15000.0, 0.39, 4478.171, 1714.67 + 0.35, 15000.0, 0.41, 4707.822, 1787.68 + 0.35, 15000.0, 0.43, 4937.465, 1861.01 + 0.35, 15000.0, 0.45, 5167.104, 1934.78 + 0.35, 15000.0, 0.47, 5396.74, 2009.06 + 0.35, 15000.0, 0.49, 5626.376, 2083.89 + 0.35, 15000.0, 0.51, 5856.017, 2159.56 + 0.35, 15000.0, 0.53, 6085.663, 2236.08 + 0.35, 15000.0, 0.55, 6315.306, 2313.18 + 0.35, 15000.0, 0.57, 6544.946, 2390.8 + 0.35, 15000.0, 0.59, 6774.58, 2468.92 + 0.35, 15000.0, 0.61, 7004.191, 2547.17 + 0.35, 15000.0, 0.63, 7233.783, 2625.59 + 0.35, 15000.0, 0.65, 7463.374, 2704.57 + 0.35, 15000.0, 0.67, 7692.971, 2784.21 + 0.35, 15000.0, 0.69, 7922.578, 2864.63 + 0.35, 15000.0, 0.71, 8152.222, 2946.11 + 0.35, 15000.0, 0.73, 8381.903, 3028.7 + 0.35, 15000.0, 0.75, 8611.596, 3112.22 + 0.35, 15000.0, 0.77, 8841.296, 3196.66 + 0.35, 15000.0, 0.79, 9070.999, 3282.02 + 0.35, 15000.0, 0.81, 9300.693, 3368.27 + 0.35, 15000.0, 0.83, 9530.375, 3455.42 + 0.35, 15000.0, 0.85, 9760.051, 3543.52 + 0.35, 15000.0, 0.87, 9989.719, 3632.6 + 0.35, 15000.0, 0.89, 10219.38, 3722.66 + 0.35, 15000.0, 0.91, 10449.03, 3813.72 + 0.35, 15000.0, 0.93, 10678.67, 3905.81 + 0.35, 15000.0, 0.95, 10908.3, 3998.93 + 0.35, 15000.0, 0.97, 11137.91, 4093.11 + 0.35, 15000.0, 0.99, 11367.51, 4188.37 + 0.35, 20000.0, 0.0, 378.5848, 378.585 + 0.35, 20000.0, 0.05, 476.7937, 401.319 + 0.35, 20000.0, 0.07, 667.5631, 462.968 + 0.35, 20000.0, 0.09, 858.3342, 523.805 + 0.35, 20000.0, 0.11, 1049.107, 583.918 + 0.35, 20000.0, 0.13, 1239.88, 643.396 + 0.35, 20000.0, 0.15, 1430.654, 702.328 + 0.35, 20000.0, 0.17, 1621.428, 760.802 + 0.35, 20000.0, 0.19, 1812.201, 818.908 + 0.35, 20000.0, 0.21, 2002.974, 876.733 + 0.35, 20000.0, 0.23, 2193.744, 934.368 + 0.35, 20000.0, 0.25, 2384.514, 991.899 + 0.35, 20000.0, 0.27, 2575.28, 1049.42 + 0.35, 20000.0, 0.29, 2766.044, 1107.01 + 0.35, 20000.0, 0.31, 2956.805, 1164.92 + 0.35, 20000.0, 0.33, 3147.563, 1223.2 + 0.35, 20000.0, 0.35, 3338.316, 1281.71 + 0.35, 20000.0, 0.37, 3529.064, 1340.46 + 0.35, 20000.0, 0.39, 3719.806, 1399.47 + 0.35, 20000.0, 0.41, 3910.537, 1458.67 + 0.35, 20000.0, 0.43, 4101.258, 1518.08 + 0.35, 20000.0, 0.45, 4291.975, 1577.85 + 0.35, 20000.0, 0.47, 4482.69, 1638.03 + 0.35, 20000.0, 0.49, 4673.405, 1698.67 + 0.35, 20000.0, 0.51, 4864.119, 1760.03 + 0.35, 20000.0, 0.53, 5054.835, 1822.12 + 0.35, 20000.0, 0.55, 5245.558, 1884.67 + 0.35, 20000.0, 0.57, 5436.29, 1947.64 + 0.35, 20000.0, 0.59, 5627.035, 2010.97 + 0.35, 20000.0, 0.61, 5817.811, 2074.27 + 0.35, 20000.0, 0.63, 6008.618, 2137.56 + 0.35, 20000.0, 0.65, 6199.433, 2201.33 + 0.35, 20000.0, 0.67, 6390.25, 2265.68 + 0.35, 20000.0, 0.69, 6581.064, 2330.75 + 0.35, 20000.0, 0.71, 6771.866, 2396.97 + 0.35, 20000.0, 0.73, 6962.651, 2464.4 + 0.35, 20000.0, 0.75, 7153.419, 2532.66 + 0.35, 20000.0, 0.77, 7344.167, 2601.71 + 0.35, 20000.0, 0.79, 7534.892, 2671.53 + 0.35, 20000.0, 0.81, 7725.547, 2741.9 + 0.35, 20000.0, 0.83, 7916.141, 2812.83 + 0.35, 20000.0, 0.85, 8106.73, 2884.53 + 0.35, 20000.0, 0.87, 8297.332, 2957.03 + 0.35, 20000.0, 0.89, 8487.962, 3030.38 + 0.35, 20000.0, 0.91, 8678.639, 3104.61 + 0.35, 20000.0, 0.93, 8869.377, 3179.78 + 0.35, 20000.0, 0.95, 9060.193, 3255.91 + 0.35, 20000.0, 0.97, 9251.105, 3333.06 + 0.35, 20000.0, 0.99, 9442.129, 3411.26 + 0.35, 25000.0, 0.0, 312.1392, 312.139 + 0.35, 25000.0, 0.05, 396.8, 338.3 + 0.35, 25000.0, 0.07, 554.9405, 390.648 + 0.35, 25000.0, 0.09, 713.1817, 441.401 + 0.35, 25000.0, 0.11, 871.5143, 490.754 + 0.35, 25000.0, 0.13, 1029.929, 538.905 + 0.35, 25000.0, 0.15, 1188.418, 586.05 + 0.35, 25000.0, 0.17, 1346.971, 632.385 + 0.35, 25000.0, 0.19, 1505.578, 678.107 + 0.35, 25000.0, 0.21, 1664.232, 723.413 + 0.35, 25000.0, 0.23, 1822.923, 768.498 + 0.35, 25000.0, 0.25, 1981.641, 813.56 + 0.35, 25000.0, 0.27, 2140.379, 858.794 + 0.35, 25000.0, 0.29, 2299.126, 904.398 + 0.35, 25000.0, 0.31, 2457.876, 951.227 + 0.35, 25000.0, 0.33, 2616.62, 999.318 + 0.35, 25000.0, 0.35, 2775.344, 1047.89 + 0.35, 25000.0, 0.37, 2934.038, 1096.81 + 0.35, 25000.0, 0.39, 3092.692, 1145.97 + 0.35, 25000.0, 0.41, 3251.252, 1194.98 + 0.35, 25000.0, 0.43, 3409.718, 1243.78 + 0.35, 25000.0, 0.45, 3568.144, 1292.63 + 0.35, 25000.0, 0.47, 3726.54, 1341.54 + 0.35, 25000.0, 0.49, 3884.916, 1390.5 + 0.35, 25000.0, 0.51, 4043.291, 1439.14 + 0.35, 25000.0, 0.53, 4201.674, 1487.55 + 0.35, 25000.0, 0.55, 4360.062, 1536.3 + 0.35, 25000.0, 0.57, 4518.463, 1585.58 + 0.35, 25000.0, 0.59, 4676.882, 1635.58 + 0.35, 25000.0, 0.61, 4835.309, 1687.09 + 0.35, 25000.0, 0.63, 4993.755, 1740.15 + 0.35, 25000.0, 0.65, 5152.25, 1794.04 + 0.35, 25000.0, 0.67, 5310.809, 1848.66 + 0.35, 25000.0, 0.69, 5469.447, 1903.89 + 0.35, 25000.0, 0.71, 5628.297, 1959.4 + 0.35, 25000.0, 0.73, 5787.343, 2015.14 + 0.35, 25000.0, 0.75, 5946.425, 2071.32 + 0.35, 25000.0, 0.77, 6105.499, 2127.94 + 0.35, 25000.0, 0.79, 6264.521, 2185.0 + 0.35, 25000.0, 0.81, 6423.342, 2242.37 + 0.35, 25000.0, 0.83, 6581.944, 2300.07 + 0.35, 25000.0, 0.85, 6740.444, 2358.3 + 0.35, 25000.0, 0.87, 6898.849, 2417.12 + 0.35, 25000.0, 0.89, 7057.169, 2476.6 + 0.35, 25000.0, 0.91, 7215.413, 2536.79 + 0.35, 25000.0, 0.93, 7373.589, 2597.76 + 0.35, 25000.0, 0.95, 7531.706, 2659.58 + 0.35, 25000.0, 0.97, 7689.774, 2722.29 + 0.35, 25000.0, 0.99, 7847.8, 2785.98 + 0.35, 30000.0, 0.0, 255.2886, 255.289 + 0.35, 30000.0, 0.05, 323.9, 286.2 + 0.35, 30000.0, 0.07, 453.9281, 324.861 + 0.35, 30000.0, 0.09, 583.8369, 363.136 + 0.35, 30000.0, 0.11, 713.642, 401.069 + 0.35, 30000.0, 0.13, 843.359, 438.703 + 0.35, 30000.0, 0.15, 973.0036, 476.082 + 0.35, 30000.0, 0.17, 1102.591, 513.25 + 0.35, 30000.0, 0.19, 1232.137, 550.249 + 0.35, 30000.0, 0.21, 1361.658, 587.125 + 0.35, 30000.0, 0.23, 1491.168, 623.92 + 0.35, 30000.0, 0.25, 1620.684, 660.679 + 0.35, 30000.0, 0.27, 1750.221, 697.444 + 0.35, 30000.0, 0.29, 1879.795, 734.26 + 0.35, 30000.0, 0.31, 2009.49, 771.182 + 0.35, 30000.0, 0.33, 2139.307, 808.252 + 0.35, 30000.0, 0.35, 2269.156, 845.494 + 0.35, 30000.0, 0.37, 2399.019, 882.946 + 0.35, 30000.0, 0.39, 2528.878, 920.646 + 0.35, 30000.0, 0.41, 2658.684, 958.754 + 0.35, 30000.0, 0.43, 2788.427, 997.279 + 0.35, 30000.0, 0.45, 2918.131, 1036.07 + 0.35, 30000.0, 0.47, 3047.794, 1075.12 + 0.35, 30000.0, 0.49, 3177.41, 1114.39 + 0.35, 30000.0, 0.51, 3306.907, 1153.77 + 0.35, 30000.0, 0.53, 3436.298, 1193.26 + 0.35, 30000.0, 0.55, 3565.681, 1232.98 + 0.35, 30000.0, 0.57, 3695.086, 1272.94 + 0.35, 30000.0, 0.59, 3824.543, 1313.17 + 0.35, 30000.0, 0.61, 3954.196, 1353.6 + 0.35, 30000.0, 0.63, 4084.048, 1394.27 + 0.35, 30000.0, 0.65, 4213.956, 1435.34 + 0.35, 30000.0, 0.67, 4343.894, 1476.9 + 0.35, 30000.0, 0.69, 4473.836, 1519.01 + 0.35, 30000.0, 0.71, 4603.676, 1562.01 + 0.35, 30000.0, 0.73, 4733.406, 1605.91 + 0.35, 30000.0, 0.75, 4863.119, 1650.38 + 0.35, 30000.0, 0.77, 4992.825, 1695.37 + 0.35, 30000.0, 0.79, 5122.538, 1740.82 + 0.35, 30000.0, 0.81, 5252.326, 1786.37 + 0.35, 30000.0, 0.83, 5382.188, 1832.03 + 0.35, 30000.0, 0.85, 5512.05, 1878.21 + 0.35, 30000.0, 0.87, 5641.896, 1924.99 + 0.35, 30000.0, 0.89, 5771.71, 1972.47 + 0.35, 30000.0, 0.91, 5901.476, 2020.74 + 0.35, 30000.0, 0.93, 6031.178, 2069.88 + 0.35, 30000.0, 0.95, 6160.8, 2119.99 + 0.35, 30000.0, 0.97, 6290.326, 2171.16 + 0.35, 30000.0, 0.99, 6419.74, 2223.48 + 0.35, 35000.0, 0.0, 206.9682, 206.968 + 0.35, 35000.0, 0.05, 277.5, 266.3 + 0.35, 35000.0, 0.07, 389.8899, 294.357 + 0.35, 35000.0, 0.09, 502.641, 322.891 + 0.35, 35000.0, 0.11, 615.7148, 351.876 + 0.35, 35000.0, 0.13, 729.0723, 381.286 + 0.35, 35000.0, 0.15, 842.675, 411.096 + 0.35, 35000.0, 0.17, 956.4841, 441.28 + 0.35, 35000.0, 0.19, 1070.461, 471.812 + 0.35, 35000.0, 0.21, 1184.567, 502.665 + 0.35, 35000.0, 0.23, 1298.763, 533.815 + 0.35, 35000.0, 0.25, 1413.01, 565.236 + 0.35, 35000.0, 0.27, 1527.27, 596.901 + 0.35, 35000.0, 0.29, 1641.505, 628.784 + 0.35, 35000.0, 0.31, 1755.618, 661.076 + 0.35, 35000.0, 0.33, 1869.584, 693.699 + 0.35, 35000.0, 0.35, 1983.45, 726.306 + 0.35, 35000.0, 0.37, 2097.204, 758.767 + 0.35, 35000.0, 0.39, 2210.834, 790.952 + 0.35, 35000.0, 0.41, 2324.34, 821.532 + 0.35, 35000.0, 0.43, 2437.708, 850.667 + 0.35, 35000.0, 0.45, 2550.912, 880.006 + 0.35, 35000.0, 0.47, 2663.936, 909.999 + 0.35, 35000.0, 0.49, 2776.764, 941.096 + 0.35, 35000.0, 0.51, 2889.143, 975.636 + 0.35, 35000.0, 0.53, 3001.113, 1013.61 + 0.35, 35000.0, 0.55, 3113.013, 1052.67 + 0.35, 35000.0, 0.57, 3224.94, 1092.34 + 0.35, 35000.0, 0.59, 3336.994, 1132.17 + 0.35, 35000.0, 0.61, 3449.719, 1170.7 + 0.35, 35000.0, 0.63, 3563.105, 1207.71 + 0.35, 35000.0, 0.65, 3676.594, 1244.19 + 0.35, 35000.0, 0.67, 3790.068, 1280.17 + 0.35, 35000.0, 0.69, 3903.413, 1315.64 + 0.35, 35000.0, 0.71, 4015.954, 1349.63 + 0.35, 35000.0, 0.73, 4127.71, 1382.39 + 0.35, 35000.0, 0.75, 4239.394, 1415.42 + 0.35, 35000.0, 0.77, 4351.16, 1449.23 + 0.35, 35000.0, 0.79, 4463.162, 1484.32 + 0.35, 35000.0, 0.81, 4576.134, 1523.21 + 0.35, 35000.0, 0.83, 4690.09, 1565.9 + 0.35, 35000.0, 0.85, 4804.325, 1609.9 + 0.35, 35000.0, 0.87, 4918.712, 1654.73 + 0.35, 35000.0, 0.89, 5033.124, 1699.92 + 0.35, 35000.0, 0.91, 5147.435, 1744.99 + 0.35, 35000.0, 0.93, 5261.519, 1789.45 + 0.35, 35000.0, 0.95, 5375.25, 1832.82 + 0.35, 35000.0, 0.97, 5488.501, 1874.64 + 0.35, 35000.0, 0.99, 5601.145, 1914.42 + 0.35, 40000.0, 0.0, 163.7951, 163.795 + 0.35, 40000.0, 0.05, 225.0, 225.4 + 0.35, 40000.0, 0.07, 313.1193, 251.948 + 0.35, 40000.0, 0.09, 401.1898, 277.221 + 0.35, 40000.0, 0.11, 489.2449, 301.414 + 0.35, 40000.0, 0.13, 577.3181, 324.725 + 0.35, 40000.0, 0.15, 665.4429, 347.35 + 0.35, 40000.0, 0.17, 753.6527, 369.485 + 0.35, 40000.0, 0.19, 841.981, 391.327 + 0.35, 40000.0, 0.21, 930.4612, 413.073 + 0.35, 40000.0, 0.23, 1019.127, 434.918 + 0.35, 40000.0, 0.25, 1108.011, 457.06 + 0.35, 40000.0, 0.27, 1197.148, 479.694 + 0.35, 40000.0, 0.29, 1286.571, 503.018 + 0.35, 40000.0, 0.31, 1376.694, 528.357 + 0.35, 40000.0, 0.33, 1467.458, 555.634 + 0.35, 40000.0, 0.35, 1558.331, 583.369 + 0.35, 40000.0, 0.37, 1649.163, 611.209 + 0.35, 40000.0, 0.39, 1739.801, 638.804 + 0.35, 40000.0, 0.41, 1829.609, 664.265 + 0.35, 40000.0, 0.43, 1918.555, 687.613 + 0.35, 40000.0, 0.45, 2007.206, 710.781 + 0.35, 40000.0, 0.47, 2095.648, 734.163 + 0.35, 40000.0, 0.49, 2183.963, 758.153 + 0.35, 40000.0, 0.51, 2272.204, 784.861 + 0.35, 40000.0, 0.53, 2360.461, 814.264 + 0.35, 40000.0, 0.55, 2448.869, 844.213 + 0.35, 40000.0, 0.57, 2537.526, 874.269 + 0.35, 40000.0, 0.59, 2626.534, 903.996 + 0.35, 40000.0, 0.61, 2716.574, 931.484 + 0.35, 40000.0, 0.63, 2807.605, 956.654 + 0.35, 40000.0, 0.65, 2898.862, 981.256 + 0.35, 40000.0, 0.67, 2990.164, 1005.57 + 0.35, 40000.0, 0.69, 3081.327, 1029.87 + 0.35, 40000.0, 0.71, 3171.718, 1054.19 + 0.35, 40000.0, 0.73, 3261.262, 1078.87 + 0.35, 40000.0, 0.75, 3350.45, 1104.54 + 0.35, 40000.0, 0.77, 3439.318, 1131.61 + 0.35, 40000.0, 0.79, 3527.902, 1160.47 + 0.35, 40000.0, 0.81, 3615.993, 1194.05 + 0.35, 40000.0, 0.83, 3703.687, 1232.12 + 0.35, 40000.0, 0.85, 3791.387, 1271.34 + 0.35, 40000.0, 0.87, 3879.252, 1310.86 + 0.35, 40000.0, 0.89, 3967.438, 1349.86 + 0.35, 40000.0, 0.91, 4056.101, 1387.5 + 0.35, 40000.0, 0.93, 4145.399, 1422.96 + 0.35, 40000.0, 0.95, 4235.487, 1455.41 + 0.35, 40000.0, 0.97, 4326.524, 1484.02 + 0.35, 40000.0, 0.99, 4418.666, 1507.95 + 0.35, 43000.0, 0.0, 141.8822, 141.882 + 0.35, 43000.0, 0.05, 177.2, 226.9 + 0.35, 43000.0, 0.07, 267.8181, 253.175 + 0.35, 43000.0, 0.09, 354.3404, 277.951 + 0.35, 43000.0, 0.11, 437.2883, 301.338 + 0.35, 43000.0, 0.13, 517.1832, 323.444 + 0.35, 43000.0, 0.15, 594.5464, 344.379 + 0.35, 43000.0, 0.17, 669.8994, 364.25 + 0.35, 43000.0, 0.19, 743.7634, 383.166 + 0.35, 43000.0, 0.21, 816.6599, 401.236 + 0.35, 43000.0, 0.23, 889.1102, 418.57 + 0.35, 43000.0, 0.25, 961.6357, 435.274 + 0.35, 43000.0, 0.27, 1034.758, 451.459 + 0.35, 43000.0, 0.29, 1108.998, 467.233 + 0.35, 43000.0, 0.31, 1187.52, 481.291 + 0.35, 43000.0, 0.33, 1270.205, 494.083 + 0.35, 43000.0, 0.35, 1353.65, 507.819 + 0.35, 43000.0, 0.37, 1437.095, 523.293 + 0.35, 43000.0, 0.39, 1519.78, 541.299 + 0.35, 43000.0, 0.41, 1598.132, 568.24 + 0.35, 43000.0, 0.43, 1672.072, 603.552 + 0.35, 43000.0, 0.45, 1745.019, 639.7 + 0.35, 43000.0, 0.47, 1817.575, 674.76 + 0.35, 43000.0, 0.49, 1890.346, 706.808 + 0.35, 43000.0, 0.51, 1965.921, 725.687 + 0.35, 43000.0, 0.53, 2044.423, 731.469 + 0.35, 43000.0, 0.55, 2123.506, 734.45 + 0.35, 43000.0, 0.57, 2202.812, 736.695 + 0.35, 43000.0, 0.59, 2281.98, 740.269 + 0.35, 43000.0, 0.61, 2359.353, 752.587 + 0.35, 43000.0, 0.63, 2434.887, 774.419 + 0.35, 43000.0, 0.65, 2510.15, 799.887 + 0.35, 43000.0, 0.67, 2585.413, 828.463 + 0.35, 43000.0, 0.69, 2660.947, 859.619 + 0.35, 43000.0, 0.71, 2738.32, 893.631 + 0.35, 43000.0, 0.73, 2817.488, 929.775 + 0.35, 43000.0, 0.75, 2896.794, 966.331 + 0.35, 43000.0, 0.77, 2975.877, 1002.38 + 0.35, 43000.0, 0.79, 3054.379, 1037.01 + 0.35, 43000.0, 0.81, 3130.416, 1065.52 + 0.35, 43000.0, 0.83, 3203.999, 1087.92 + 0.35, 43000.0, 0.85, 3277.031, 1108.89 + 0.35, 43000.0, 0.87, 3349.894, 1129.33 + 0.35, 43000.0, 0.89, 3422.966, 1150.16 + 0.35, 43000.0, 0.91, 3496.629, 1172.28 + 0.35, 43000.0, 0.93, 3571.261, 1196.61 + 0.35, 43000.0, 0.95, 3647.244, 1224.06 + 0.35, 43000.0, 0.97, 3724.956, 1255.54 + 0.35, 43000.0, 0.99, 3804.779, 1291.96 + 0.35, 48000.0, 0.0, 111.69, 111.69 + 0.35, 48000.0, 0.05, 148.3, 197.6 + 0.35, 48000.0, 0.07, 218.3478, 216.376 + 0.35, 48000.0, 0.09, 285.7265, 233.819 + 0.35, 48000.0, 0.11, 350.7358, 250.064 + 0.35, 48000.0, 0.13, 413.6758, 265.248 + 0.35, 48000.0, 0.15, 474.8464, 279.507 + 0.35, 48000.0, 0.17, 534.5475, 292.977 + 0.35, 48000.0, 0.19, 593.0791, 305.794 + 0.35, 48000.0, 0.21, 650.741, 318.094 + 0.35, 48000.0, 0.23, 707.8332, 330.014 + 0.35, 48000.0, 0.25, 764.6557, 341.689 + 0.35, 48000.0, 0.27, 821.5084, 353.255 + 0.35, 48000.0, 0.29, 878.6911, 364.85 + 0.35, 48000.0, 0.31, 937.2462, 375.998 + 0.35, 48000.0, 0.33, 997.2937, 386.984 + 0.35, 48000.0, 0.35, 1058.031, 398.85 + 0.35, 48000.0, 0.37, 1119.399, 412.028 + 0.35, 48000.0, 0.39, 1181.336, 426.95 + 0.35, 48000.0, 0.41, 1243.916, 447.69 + 0.35, 48000.0, 0.43, 1307.045, 473.796 + 0.35, 48000.0, 0.45, 1370.469, 500.294 + 0.35, 48000.0, 0.47, 1434.062, 525.85 + 0.35, 48000.0, 0.49, 1497.702, 549.13 + 0.35, 48000.0, 0.51, 1561.691, 562.528 + 0.35, 48000.0, 0.53, 1625.801, 566.23 + 0.35, 48000.0, 0.55, 1689.275, 568.219 + 0.35, 48000.0, 0.57, 1751.781, 570.201 + 0.35, 48000.0, 0.59, 1812.987, 573.886 + 0.35, 48000.0, 0.61, 1869.879, 586.376 + 0.35, 48000.0, 0.63, 1922.775, 608.071 + 0.35, 48000.0, 0.65, 1975.331, 632.669 + 0.35, 48000.0, 0.67, 2028.517, 659.26 + 0.35, 48000.0, 0.69, 2083.303, 686.938 + 0.35, 48000.0, 0.71, 2145.102, 713.148 + 0.35, 48000.0, 0.73, 2213.807, 737.382 + 0.35, 48000.0, 0.75, 2283.794, 761.175 + 0.35, 48000.0, 0.77, 2353.878, 784.416 + 0.35, 48000.0, 0.79, 2422.877, 806.994 + 0.35, 48000.0, 0.81, 2485.93, 827.549 + 0.35, 48000.0, 0.83, 2542.745, 846.273 + 0.35, 48000.0, 0.85, 2597.6, 864.913 + 0.35, 48000.0, 0.87, 2651.095, 883.965 + 0.35, 48000.0, 0.89, 2703.83, 903.925 + 0.35, 48000.0, 0.91, 2756.405, 925.289 + 0.35, 48000.0, 0.93, 2809.42, 948.553 + 0.35, 48000.0, 0.95, 2863.475, 974.213 + 0.35, 48000.0, 0.97, 2919.17, 1002.76 + 0.35, 48000.0, 0.99, 2977.105, 1034.7 + 0.4, 0.0, 0.0, 781.4469, 781.447 + 0.4, 0.0, 0.05, 823.0312, 859.425 + 0.4, 0.0, 0.07, 1152.346, 987.556 + 0.4, 0.0, 0.09, 1481.651, 1114.69 + 0.4, 0.0, 0.11, 1810.947, 1240.89 + 0.4, 0.0, 0.13, 2140.236, 1366.25 + 0.4, 0.0, 0.15, 2469.519, 1490.85 + 0.4, 0.0, 0.17, 2798.795, 1614.76 + 0.4, 0.0, 0.19, 3128.066, 1738.06 + 0.4, 0.0, 0.21, 3457.333, 1860.82 + 0.4, 0.0, 0.23, 3786.596, 1983.14 + 0.4, 0.0, 0.25, 4115.856, 2105.07 + 0.4, 0.0, 0.27, 4445.115, 2226.72 + 0.4, 0.0, 0.29, 4774.372, 2348.14 + 0.4, 0.0, 0.31, 5103.628, 2469.43 + 0.4, 0.0, 0.33, 5432.885, 2590.66 + 0.4, 0.0, 0.35, 5762.144, 2711.9 + 0.4, 0.0, 0.37, 6091.404, 2833.24 + 0.4, 0.0, 0.39, 6420.667, 2954.75 + 0.4, 0.0, 0.41, 6749.939, 3076.59 + 0.4, 0.0, 0.43, 7079.219, 3198.81 + 0.4, 0.0, 0.45, 7408.5, 3321.39 + 0.4, 0.0, 0.47, 7737.781, 3444.37 + 0.4, 0.0, 0.49, 8067.061, 3567.8 + 0.4, 0.0, 0.51, 8396.333, 3691.67 + 0.4, 0.0, 0.53, 8725.596, 3816.04 + 0.4, 0.0, 0.55, 9054.856, 3941.03 + 0.4, 0.0, 0.57, 9384.115, 4066.71 + 0.4, 0.0, 0.59, 9713.372, 4193.16 + 0.4, 0.0, 0.61, 10042.62, 4320.76 + 0.4, 0.0, 0.63, 10371.87, 4449.51 + 0.4, 0.0, 0.65, 10701.12, 4579.02 + 0.4, 0.0, 0.67, 11030.38, 4709.21 + 0.4, 0.0, 0.69, 11359.66, 4840.0 + 0.4, 0.0, 0.71, 11688.98, 4971.03 + 0.4, 0.0, 0.73, 12018.34, 5102.28 + 0.4, 0.0, 0.75, 12347.71, 5234.11 + 0.4, 0.0, 0.77, 12677.07, 5366.6 + 0.4, 0.0, 0.79, 13006.43, 5499.81 + 0.4, 0.0, 0.81, 13335.74, 5633.66 + 0.4, 0.0, 0.83, 13665.0, 5768.26 + 0.4, 0.0, 0.85, 13994.24, 5903.87 + 0.4, 0.0, 0.87, 14323.47, 6040.63 + 0.4, 0.0, 0.89, 14652.69, 6178.66 + 0.4, 0.0, 0.91, 14981.91, 6318.1 + 0.4, 0.0, 0.93, 15311.12, 6459.08 + 0.4, 0.0, 0.95, 15640.33, 6601.73 + 0.4, 0.0, 0.97, 15969.55, 6746.17 + 0.4, 0.0, 0.99, 16298.78, 6892.55 + 0.4, 2000.0, 0.0, 731.6497, 731.65 + 0.4, 2000.0, 0.05, 792.7813, 816.556 + 0.4, 2000.0, 0.07, 1109.996, 937.292 + 0.4, 2000.0, 0.09, 1427.201, 1057.27 + 0.4, 2000.0, 0.11, 1744.397, 1176.56 + 0.4, 2000.0, 0.13, 2061.586, 1295.22 + 0.4, 2000.0, 0.15, 2378.769, 1413.32 + 0.4, 2000.0, 0.17, 2695.945, 1530.91 + 0.4, 2000.0, 0.19, 3013.116, 1648.07 + 0.4, 2000.0, 0.21, 3330.283, 1764.85 + 0.4, 2000.0, 0.23, 3647.446, 1881.31 + 0.4, 2000.0, 0.25, 3964.606, 1997.53 + 0.4, 2000.0, 0.27, 4281.765, 2113.56 + 0.4, 2000.0, 0.29, 4598.922, 2229.47 + 0.4, 2000.0, 0.31, 4916.078, 2345.32 + 0.4, 2000.0, 0.33, 5233.235, 2461.17 + 0.4, 2000.0, 0.35, 5550.394, 2577.09 + 0.4, 2000.0, 0.37, 5867.554, 2693.14 + 0.4, 2000.0, 0.39, 6184.717, 2809.39 + 0.4, 2000.0, 0.41, 6501.887, 2925.88 + 0.4, 2000.0, 0.43, 6819.064, 3042.7 + 0.4, 2000.0, 0.45, 7136.244, 3159.9 + 0.4, 2000.0, 0.47, 7453.425, 3277.55 + 0.4, 2000.0, 0.49, 7770.608, 3395.71 + 0.4, 2000.0, 0.51, 8087.793, 3514.49 + 0.4, 2000.0, 0.53, 8404.979, 3633.94 + 0.4, 2000.0, 0.55, 8722.163, 3754.06 + 0.4, 2000.0, 0.57, 9039.342, 3874.9 + 0.4, 2000.0, 0.59, 9356.516, 3996.5 + 0.4, 2000.0, 0.61, 9673.674, 4119.17 + 0.4, 2000.0, 0.63, 9990.817, 4242.88 + 0.4, 2000.0, 0.65, 10307.96, 4367.29 + 0.4, 2000.0, 0.67, 10625.09, 4492.31 + 0.4, 2000.0, 0.69, 10942.23, 4617.86 + 0.4, 2000.0, 0.71, 11259.37, 4743.35 + 0.4, 2000.0, 0.73, 11576.51, 4868.81 + 0.4, 2000.0, 0.75, 11893.66, 4994.91 + 0.4, 2000.0, 0.77, 12210.82, 5121.78 + 0.4, 2000.0, 0.79, 12528.0, 5249.59 + 0.4, 2000.0, 0.81, 12845.24, 5378.77 + 0.4, 2000.0, 0.83, 13162.53, 5509.4 + 0.4, 2000.0, 0.85, 13479.83, 5641.23 + 0.4, 2000.0, 0.87, 13797.11, 5774.28 + 0.4, 2000.0, 0.89, 14114.38, 5908.58 + 0.4, 2000.0, 0.91, 14431.61, 6044.14 + 0.4, 2000.0, 0.93, 14748.8, 6180.99 + 0.4, 2000.0, 0.95, 15065.93, 6319.14 + 0.4, 2000.0, 0.97, 15382.98, 6458.63 + 0.4, 2000.0, 0.99, 15699.95, 6599.47 + 0.4, 5000.0, 0.0, 661.7016, 661.702 + 0.4, 5000.0, 0.05, 745.4375, 751.1 + 0.4, 5000.0, 0.07, 1044.253, 861.859 + 0.4, 5000.0, 0.09, 1343.027, 972.078 + 0.4, 5000.0, 0.11, 1641.764, 1081.81 + 0.4, 5000.0, 0.13, 1940.466, 1191.1 + 0.4, 5000.0, 0.15, 2239.138, 1300.0 + 0.4, 5000.0, 0.17, 2537.781, 1408.57 + 0.4, 5000.0, 0.19, 2836.399, 1516.85 + 0.4, 5000.0, 0.21, 3134.996, 1624.9 + 0.4, 5000.0, 0.23, 3433.574, 1732.76 + 0.4, 5000.0, 0.25, 3732.138, 1840.5 + 0.4, 5000.0, 0.27, 4030.689, 1948.16 + 0.4, 5000.0, 0.29, 4329.231, 2055.78 + 0.4, 5000.0, 0.31, 4627.768, 2163.43 + 0.4, 5000.0, 0.33, 4926.302, 2271.15 + 0.4, 5000.0, 0.35, 5224.838, 2379.0 + 0.4, 5000.0, 0.37, 5523.377, 2487.02 + 0.4, 5000.0, 0.39, 5821.923, 2595.27 + 0.4, 5000.0, 0.41, 6120.493, 2703.74 + 0.4, 5000.0, 0.43, 6419.087, 2812.49 + 0.4, 5000.0, 0.45, 6717.688, 2921.66 + 0.4, 5000.0, 0.47, 7016.292, 3031.35 + 0.4, 5000.0, 0.49, 7314.898, 3141.62 + 0.4, 5000.0, 0.51, 7613.485, 3252.75 + 0.4, 5000.0, 0.53, 7912.053, 3364.77 + 0.4, 5000.0, 0.55, 8210.625, 3477.49 + 0.4, 5000.0, 0.57, 8509.205, 3590.91 + 0.4, 5000.0, 0.59, 8807.797, 3705.0 + 0.4, 5000.0, 0.61, 9106.444, 3819.82 + 0.4, 5000.0, 0.63, 9405.14, 3935.35 + 0.4, 5000.0, 0.65, 9703.838, 4051.49 + 0.4, 5000.0, 0.67, 10002.52, 4168.21 + 0.4, 5000.0, 0.69, 10301.18, 4285.48 + 0.4, 5000.0, 0.71, 10599.75, 4402.79 + 0.4, 5000.0, 0.73, 10898.22, 4520.22 + 0.4, 5000.0, 0.75, 11196.68, 4638.42 + 0.4, 5000.0, 0.77, 11495.12, 4757.57 + 0.4, 5000.0, 0.79, 11793.57, 4877.87 + 0.4, 5000.0, 0.81, 12092.09, 4999.97 + 0.4, 5000.0, 0.83, 12390.68, 5123.96 + 0.4, 5000.0, 0.85, 12689.28, 5249.29 + 0.4, 5000.0, 0.87, 12987.89, 5375.93 + 0.4, 5000.0, 0.89, 13286.5, 5503.81 + 0.4, 5000.0, 0.91, 13585.1, 5632.89 + 0.4, 5000.0, 0.93, 13883.67, 5763.12 + 0.4, 5000.0, 0.95, 14182.22, 5894.46 + 0.4, 5000.0, 0.97, 14480.73, 6026.85 + 0.4, 5000.0, 0.99, 14779.19, 6160.24 + 0.4, 10000.0, 0.0, 556.9876, 556.988 + 0.4, 10000.0, 0.05, 672.075, 644.631 + 0.4, 10000.0, 0.07, 938.7514, 741.125 + 0.4, 10000.0, 0.09, 1205.554, 837.148 + 0.4, 10000.0, 0.11, 1472.474, 932.754 + 0.4, 10000.0, 0.13, 1739.501, 1027.99 + 0.4, 10000.0, 0.15, 2006.625, 1122.92 + 0.4, 10000.0, 0.17, 2273.837, 1217.58 + 0.4, 10000.0, 0.19, 2541.128, 1312.04 + 0.4, 10000.0, 0.21, 2808.488, 1406.33 + 0.4, 10000.0, 0.23, 3075.907, 1500.52 + 0.4, 10000.0, 0.25, 3343.375, 1594.66 + 0.4, 10000.0, 0.27, 3610.883, 1688.79 + 0.4, 10000.0, 0.29, 3878.422, 1782.97 + 0.4, 10000.0, 0.31, 4145.982, 1877.26 + 0.4, 10000.0, 0.33, 4413.553, 1971.7 + 0.4, 10000.0, 0.35, 4681.125, 2066.34 + 0.4, 10000.0, 0.37, 4948.689, 2161.25 + 0.4, 10000.0, 0.39, 5216.236, 2256.46 + 0.4, 10000.0, 0.41, 5483.716, 2352.01 + 0.4, 10000.0, 0.43, 5751.129, 2447.94 + 0.4, 10000.0, 0.45, 6018.525, 2544.37 + 0.4, 10000.0, 0.47, 6285.913, 2641.35 + 0.4, 10000.0, 0.49, 6553.302, 2738.95 + 0.4, 10000.0, 0.51, 6820.722, 2837.48 + 0.4, 10000.0, 0.53, 7088.178, 2936.94 + 0.4, 10000.0, 0.55, 7355.65, 3037.05 + 0.4, 10000.0, 0.57, 7623.138, 3137.75 + 0.4, 10000.0, 0.59, 7890.642, 3238.99 + 0.4, 10000.0, 0.61, 8158.183, 3340.4 + 0.4, 10000.0, 0.63, 8425.757, 3442.0 + 0.4, 10000.0, 0.65, 8693.331, 3544.23 + 0.4, 10000.0, 0.67, 8960.895, 3647.18 + 0.4, 10000.0, 0.69, 9228.439, 3750.96 + 0.4, 10000.0, 0.71, 9495.904, 3855.81 + 0.4, 10000.0, 0.73, 9763.292, 3961.81 + 0.4, 10000.0, 0.75, 10030.66, 4068.86 + 0.4, 10000.0, 0.77, 10298.03, 4177.01 + 0.4, 10000.0, 0.79, 10565.4, 4286.31 + 0.4, 10000.0, 0.81, 10832.85, 4396.83 + 0.4, 10000.0, 0.83, 11100.35, 4508.62 + 0.4, 10000.0, 0.85, 11367.88, 4621.65 + 0.4, 10000.0, 0.87, 11635.41, 4735.94 + 0.4, 10000.0, 0.89, 11902.94, 4851.52 + 0.4, 10000.0, 0.91, 12170.46, 4968.41 + 0.4, 10000.0, 0.93, 12437.97, 5086.63 + 0.4, 10000.0, 0.95, 12705.45, 5206.2 + 0.4, 10000.0, 0.97, 12972.9, 5327.15 + 0.4, 10000.0, 0.99, 13240.31, 5449.5 + 0.4, 15000.0, 0.0, 465.854, 465.854 + 0.4, 15000.0, 0.05, 565.0, 503.8 + 0.4, 15000.0, 0.07, 791.0334, 585.655 + 0.4, 15000.0, 0.09, 1017.059, 666.249 + 0.4, 15000.0, 0.11, 1243.077, 745.704 + 0.4, 15000.0, 0.13, 1469.089, 824.14 + 0.4, 15000.0, 0.15, 1695.096, 901.679 + 0.4, 15000.0, 0.17, 1921.1, 978.442 + 0.4, 15000.0, 0.19, 2147.1, 1054.55 + 0.4, 15000.0, 0.21, 2373.099, 1130.13 + 0.4, 15000.0, 0.23, 2599.097, 1205.3 + 0.4, 15000.0, 0.25, 2825.096, 1280.17 + 0.4, 15000.0, 0.27, 3051.095, 1354.88 + 0.4, 15000.0, 0.29, 3277.098, 1429.55 + 0.4, 15000.0, 0.31, 3503.109, 1504.46 + 0.4, 15000.0, 0.33, 3729.129, 1579.69 + 0.4, 15000.0, 0.35, 3955.15, 1655.12 + 0.4, 15000.0, 0.37, 4181.171, 1730.79 + 0.4, 15000.0, 0.39, 4407.191, 1806.72 + 0.4, 15000.0, 0.41, 4633.203, 1882.94 + 0.4, 15000.0, 0.43, 4859.206, 1959.48 + 0.4, 15000.0, 0.45, 5085.206, 2036.43 + 0.4, 15000.0, 0.47, 5311.205, 2113.83 + 0.4, 15000.0, 0.49, 5537.202, 2191.74 + 0.4, 15000.0, 0.51, 5763.2, 2270.4 + 0.4, 15000.0, 0.53, 5989.2, 2349.82 + 0.4, 15000.0, 0.55, 6215.2, 2429.74 + 0.4, 15000.0, 0.57, 6441.2, 2510.14 + 0.4, 15000.0, 0.59, 6667.2, 2590.95 + 0.4, 15000.0, 0.61, 6893.2, 2671.79 + 0.4, 15000.0, 0.63, 7119.2, 2752.7 + 0.4, 15000.0, 0.65, 7345.2, 2834.14 + 0.4, 15000.0, 0.67, 7571.2, 2916.24 + 0.4, 15000.0, 0.69, 7797.2, 2999.13 + 0.4, 15000.0, 0.71, 8023.198, 3083.2 + 0.4, 15000.0, 0.73, 8249.195, 3168.51 + 0.4, 15000.0, 0.75, 8475.194, 3254.77 + 0.4, 15000.0, 0.77, 8701.194, 3341.97 + 0.4, 15000.0, 0.79, 8927.197, 3430.1 + 0.4, 15000.0, 0.81, 9153.209, 3519.02 + 0.4, 15000.0, 0.83, 9379.229, 3608.75 + 0.4, 15000.0, 0.85, 9605.25, 3699.44 + 0.4, 15000.0, 0.87, 9831.271, 3791.15 + 0.4, 15000.0, 0.89, 10057.29, 3883.91 + 0.4, 15000.0, 0.91, 10283.31, 3977.77 + 0.4, 15000.0, 0.93, 10509.32, 4072.76 + 0.4, 15000.0, 0.95, 10735.32, 4168.93 + 0.4, 15000.0, 0.97, 10961.32, 4266.33 + 0.4, 15000.0, 0.99, 11187.31, 4364.98 + 0.4, 20000.0, 0.0, 386.9602, 386.96 + 0.4, 20000.0, 0.05, 469.9, 422.8 + 0.4, 20000.0, 0.07, 657.8924, 488.586 + 0.4, 20000.0, 0.09, 845.8827, 553.428 + 0.4, 20000.0, 0.11, 1033.871, 617.416 + 0.4, 20000.0, 0.13, 1221.858, 680.645 + 0.4, 20000.0, 0.15, 1409.843, 743.207 + 0.4, 20000.0, 0.17, 1597.827, 805.194 + 0.4, 20000.0, 0.19, 1785.809, 866.699 + 0.4, 20000.0, 0.21, 1973.791, 927.815 + 0.4, 20000.0, 0.23, 2161.771, 988.634 + 0.4, 20000.0, 0.25, 2349.751, 1049.25 + 0.4, 20000.0, 0.27, 2537.731, 1109.75 + 0.4, 20000.0, 0.29, 2725.71, 1170.24 + 0.4, 20000.0, 0.31, 2913.692, 1230.91 + 0.4, 20000.0, 0.33, 3101.675, 1291.84 + 0.4, 20000.0, 0.35, 3289.656, 1352.94 + 0.4, 20000.0, 0.37, 3477.636, 1414.25 + 0.4, 20000.0, 0.39, 3665.613, 1475.81 + 0.4, 20000.0, 0.41, 3853.581, 1537.68 + 0.4, 20000.0, 0.43, 4041.541, 1599.89 + 0.4, 20000.0, 0.45, 4229.5, 1662.44 + 0.4, 20000.0, 0.47, 4417.459, 1725.37 + 0.4, 20000.0, 0.49, 4605.419, 1788.68 + 0.4, 20000.0, 0.51, 4793.387, 1852.53 + 0.4, 20000.0, 0.53, 4981.364, 1916.9 + 0.4, 20000.0, 0.55, 5169.344, 1981.67 + 0.4, 20000.0, 0.57, 5357.325, 2046.82 + 0.4, 20000.0, 0.59, 5545.308, 2112.32 + 0.4, 20000.0, 0.61, 5733.292, 2177.89 + 0.4, 20000.0, 0.63, 5921.275, 2243.57 + 0.4, 20000.0, 0.65, 6109.256, 2309.73 + 0.4, 20000.0, 0.67, 6297.236, 2376.47 + 0.4, 20000.0, 0.69, 6485.213, 2443.9 + 0.4, 20000.0, 0.71, 6673.183, 2512.37 + 0.4, 20000.0, 0.73, 6861.146, 2581.92 + 0.4, 20000.0, 0.75, 7049.106, 2652.3 + 0.4, 20000.0, 0.77, 7237.065, 2723.48 + 0.4, 20000.0, 0.79, 7425.022, 2795.43 + 0.4, 20000.0, 0.81, 7612.975, 2868.05 + 0.4, 20000.0, 0.83, 7800.926, 2941.32 + 0.4, 20000.0, 0.85, 7988.881, 3015.41 + 0.4, 20000.0, 0.87, 8176.842, 3090.34 + 0.4, 20000.0, 0.89, 8364.811, 3166.15 + 0.4, 20000.0, 0.91, 8552.792, 3242.88 + 0.4, 20000.0, 0.93, 8740.785, 3320.57 + 0.4, 20000.0, 0.95, 8928.794, 3399.24 + 0.4, 20000.0, 0.97, 9116.821, 3478.95 + 0.4, 20000.0, 0.99, 9304.868, 3559.71 + 0.4, 25000.0, 0.0, 319.0447, 319.045 + 0.4, 25000.0, 0.05, 390.84, 355.86 + 0.4, 25000.0, 0.07, 546.9213, 409.974 + 0.4, 25000.0, 0.09, 703.0447, 462.912 + 0.4, 25000.0, 0.11, 859.2068, 514.808 + 0.4, 25000.0, 0.13, 1015.404, 565.794 + 0.4, 25000.0, 0.15, 1171.633, 616.001 + 0.4, 25000.0, 0.17, 1327.89, 665.562 + 0.4, 25000.0, 0.19, 1484.171, 714.608 + 0.4, 25000.0, 0.21, 1640.474, 763.273 + 0.4, 25000.0, 0.23, 1796.794, 811.688 + 0.4, 25000.0, 0.25, 1953.127, 859.985 + 0.4, 25000.0, 0.27, 2109.472, 908.296 + 0.4, 25000.0, 0.29, 2265.823, 956.755 + 0.4, 25000.0, 0.31, 2422.182, 1005.84 + 0.4, 25000.0, 0.33, 2578.545, 1055.59 + 0.4, 25000.0, 0.35, 2734.901, 1105.64 + 0.4, 25000.0, 0.37, 2891.244, 1155.94 + 0.4, 25000.0, 0.39, 3047.567, 1206.46 + 0.4, 25000.0, 0.41, 3203.843, 1257.11 + 0.4, 25000.0, 0.43, 3360.069, 1307.86 + 0.4, 25000.0, 0.45, 3516.276, 1358.77 + 0.4, 25000.0, 0.47, 3672.468, 1409.85 + 0.4, 25000.0, 0.49, 3828.651, 1461.1 + 0.4, 25000.0, 0.51, 3984.834, 1512.3 + 0.4, 25000.0, 0.53, 4141.023, 1563.5 + 0.4, 25000.0, 0.55, 4297.214, 1615.02 + 0.4, 25000.0, 0.57, 4453.41, 1666.94 + 0.4, 25000.0, 0.59, 4609.614, 1719.38 + 0.4, 25000.0, 0.61, 4765.816, 1772.66 + 0.4, 25000.0, 0.63, 4922.022, 1826.84 + 0.4, 25000.0, 0.65, 5078.254, 1881.64 + 0.4, 25000.0, 0.67, 5234.519, 1937.07 + 0.4, 25000.0, 0.69, 5390.827, 1993.1 + 0.4, 25000.0, 0.71, 5547.258, 2049.7 + 0.4, 25000.0, 0.73, 5703.803, 2106.84 + 0.4, 25000.0, 0.75, 5860.365, 2164.56 + 0.4, 25000.0, 0.77, 6016.919, 2222.86 + 0.4, 25000.0, 0.79, 6173.44, 2281.72 + 0.4, 25000.0, 0.81, 6329.831, 2341.06 + 0.4, 25000.0, 0.83, 6486.083, 2400.91 + 0.4, 25000.0, 0.85, 6642.276, 2461.38 + 0.4, 25000.0, 0.87, 6798.42, 2522.5 + 0.4, 25000.0, 0.89, 6954.522, 2584.31 + 0.4, 25000.0, 0.91, 7110.591, 2646.84 + 0.4, 25000.0, 0.93, 7266.637, 2710.13 + 0.4, 25000.0, 0.95, 7422.669, 2774.22 + 0.4, 25000.0, 0.97, 7578.694, 2839.14 + 0.4, 25000.0, 0.99, 7734.722, 2904.93 + 0.4, 30000.0, 0.0, 260.9363, 260.936 + 0.4, 30000.0, 0.05, 321.92, 300.96 + 0.4, 30000.0, 0.07, 450.9345, 342.632 + 0.4, 30000.0, 0.09, 579.8916, 383.821 + 0.4, 30000.0, 0.11, 708.7986, 424.577 + 0.4, 30000.0, 0.13, 837.6629, 464.949 + 0.4, 30000.0, 0.15, 966.4921, 504.989 + 0.4, 30000.0, 0.17, 1095.294, 544.746 + 0.4, 30000.0, 0.19, 1224.075, 584.27 + 0.4, 30000.0, 0.21, 1352.843, 623.611 + 0.4, 30000.0, 0.23, 1481.606, 662.818 + 0.4, 30000.0, 0.25, 1610.371, 701.943 + 0.4, 30000.0, 0.27, 1739.145, 741.035 + 0.4, 30000.0, 0.29, 1867.936, 780.144 + 0.4, 30000.0, 0.31, 1996.783, 819.352 + 0.4, 30000.0, 0.33, 2125.687, 858.701 + 0.4, 30000.0, 0.35, 2254.606, 898.194 + 0.4, 30000.0, 0.37, 2383.533, 937.865 + 0.4, 30000.0, 0.39, 2512.46, 977.748 + 0.4, 30000.0, 0.41, 2641.368, 1017.97 + 0.4, 30000.0, 0.43, 2770.253, 1058.55 + 0.4, 30000.0, 0.45, 2899.12, 1099.38 + 0.4, 30000.0, 0.47, 3027.964, 1140.44 + 0.4, 30000.0, 0.49, 3156.782, 1181.72 + 0.4, 30000.0, 0.51, 3285.524, 1223.14 + 0.4, 30000.0, 0.53, 3414.196, 1264.7 + 0.4, 30000.0, 0.55, 3542.865, 1306.51 + 0.4, 30000.0, 0.57, 3671.548, 1348.57 + 0.4, 30000.0, 0.59, 3800.264, 1390.93 + 0.4, 30000.0, 0.61, 3929.106, 1433.52 + 0.4, 30000.0, 0.63, 4058.074, 1476.38 + 0.4, 30000.0, 0.65, 4187.076, 1519.66 + 0.4, 30000.0, 0.67, 4316.096, 1563.42 + 0.4, 30000.0, 0.69, 4445.116, 1607.71 + 0.4, 30000.0, 0.71, 4574.067, 1652.78 + 0.4, 30000.0, 0.73, 4702.943, 1698.63 + 0.4, 30000.0, 0.75, 4831.805, 1745.08 + 0.4, 30000.0, 0.77, 4960.659, 1792.1 + 0.4, 30000.0, 0.79, 5089.511, 1839.67 + 0.4, 30000.0, 0.81, 5218.402, 1887.67 + 0.4, 30000.0, 0.83, 5347.33, 1936.1 + 0.4, 30000.0, 0.85, 5476.258, 1985.08 + 0.4, 30000.0, 0.87, 5605.176, 2034.64 + 0.4, 30000.0, 0.89, 5734.078, 2084.82 + 0.4, 30000.0, 0.91, 5862.955, 2135.63 + 0.4, 30000.0, 0.93, 5991.801, 2187.1 + 0.4, 30000.0, 0.95, 6120.608, 2239.26 + 0.4, 30000.0, 0.97, 6249.367, 2292.13 + 0.4, 30000.0, 0.99, 6378.071, 2345.75 + 0.4, 35000.0, 0.0, 211.547, 211.547 + 0.4, 35000.0, 0.05, 272.3, 270.2 + 0.4, 35000.0, 0.07, 382.0254, 301.373 + 0.4, 35000.0, 0.09, 491.984, 332.734 + 0.4, 35000.0, 0.11, 602.1506, 364.277 + 0.4, 35000.0, 0.13, 712.5, 395.995 + 0.4, 35000.0, 0.15, 823.0071, 427.882 + 0.4, 35000.0, 0.17, 933.6469, 459.933 + 0.4, 35000.0, 0.19, 1044.394, 492.14 + 0.4, 35000.0, 0.21, 1155.223, 524.497 + 0.4, 35000.0, 0.23, 1266.11, 556.999 + 0.4, 35000.0, 0.25, 1377.029, 589.639 + 0.4, 35000.0, 0.27, 1487.954, 622.41 + 0.4, 35000.0, 0.29, 1598.861, 655.307 + 0.4, 35000.0, 0.31, 1709.685, 688.445 + 0.4, 35000.0, 0.33, 1820.409, 721.789 + 0.4, 35000.0, 0.35, 1931.069, 755.15 + 0.4, 35000.0, 0.37, 2041.659, 788.463 + 0.4, 35000.0, 0.39, 2152.173, 821.663 + 0.4, 35000.0, 0.41, 2262.618, 853.989 + 0.4, 35000.0, 0.43, 2372.984, 885.544 + 0.4, 35000.0, 0.45, 2483.25, 917.294 + 0.4, 35000.0, 0.47, 2593.404, 949.509 + 0.4, 35000.0, 0.49, 2703.434, 982.462 + 0.4, 35000.0, 0.51, 2813.171, 1017.53 + 0.4, 35000.0, 0.53, 2922.64, 1054.7 + 0.4, 35000.0, 0.55, 3032.069, 1092.63 + 0.4, 35000.0, 0.57, 3141.524, 1131.04 + 0.4, 35000.0, 0.59, 3251.071, 1169.68 + 0.4, 35000.0, 0.61, 3361.082, 1207.7 + 0.4, 35000.0, 0.63, 3471.55, 1244.97 + 0.4, 35000.0, 0.65, 3582.088, 1282.1 + 0.4, 35000.0, 0.67, 3692.613, 1319.1 + 0.4, 35000.0, 0.69, 3803.045, 1355.99 + 0.4, 35000.0, 0.71, 3912.92, 1392.19 + 0.4, 35000.0, 0.73, 4022.25, 1427.87 + 0.4, 35000.0, 0.75, 4131.519, 1463.92 + 0.4, 35000.0, 0.77, 4240.829, 1500.65 + 0.4, 35000.0, 0.79, 4350.285, 1538.37 + 0.4, 35000.0, 0.81, 4460.371, 1578.64 + 0.4, 35000.0, 0.83, 4571.097, 1621.45 + 0.4, 35000.0, 0.85, 4682.0, 1665.26 + 0.4, 35000.0, 0.87, 4792.999, 1709.77 + 0.4, 35000.0, 0.89, 4904.013, 1754.68 + 0.4, 35000.0, 0.91, 5014.96, 1799.7 + 0.4, 35000.0, 0.93, 5125.758, 1844.53 + 0.4, 35000.0, 0.95, 5236.325, 1888.87 + 0.4, 35000.0, 0.97, 5346.58, 1932.41 + 0.4, 35000.0, 0.99, 5456.442, 1974.87 + 0.4, 40000.0, 0.0, 167.4188, 167.419 + 0.4, 40000.0, 0.05, 218.3, 231.5 + 0.4, 40000.0, 0.07, 304.4446, 258.089 + 0.4, 40000.0, 0.09, 390.5715, 283.914 + 0.4, 40000.0, 0.11, 476.6997, 309.094 + 0.4, 40000.0, 0.13, 562.8482, 333.747 + 0.4, 40000.0, 0.15, 649.0357, 357.993 + 0.4, 40000.0, 0.17, 735.2813, 381.949 + 0.4, 40000.0, 0.19, 821.6039, 405.734 + 0.4, 40000.0, 0.21, 908.0224, 429.467 + 0.4, 40000.0, 0.23, 994.5558, 453.267 + 0.4, 40000.0, 0.25, 1081.223, 477.251 + 0.4, 40000.0, 0.27, 1168.043, 501.539 + 0.4, 40000.0, 0.29, 1255.034, 526.25 + 0.4, 40000.0, 0.31, 1342.443, 552.156 + 0.4, 40000.0, 0.33, 1430.234, 579.218 + 0.4, 40000.0, 0.35, 1518.088, 606.581 + 0.4, 40000.0, 0.37, 1605.913, 634.047 + 0.4, 40000.0, 0.39, 1693.62, 661.415 + 0.4, 40000.0, 0.41, 1780.822, 687.604 + 0.4, 40000.0, 0.43, 1867.501, 712.628 + 0.4, 40000.0, 0.45, 1954.0, 737.6 + 0.4, 40000.0, 0.47, 2040.371, 762.748 + 0.4, 40000.0, 0.49, 2126.666, 788.3 + 0.4, 40000.0, 0.51, 2212.913, 815.463 + 0.4, 40000.0, 0.53, 2299.17, 844.229 + 0.4, 40000.0, 0.55, 2385.519, 873.375 + 0.4, 40000.0, 0.57, 2472.022, 902.657 + 0.4, 40000.0, 0.59, 2558.741, 931.831 + 0.4, 40000.0, 0.61, 2646.093, 959.781 + 0.4, 40000.0, 0.63, 2734.054, 986.474 + 0.4, 40000.0, 0.65, 2822.156, 1012.96 + 0.4, 40000.0, 0.67, 2910.289, 1039.4 + 0.4, 40000.0, 0.69, 2998.34, 1066.0 + 0.4, 40000.0, 0.71, 3085.926, 1092.76 + 0.4, 40000.0, 0.73, 3173.003, 1119.92 + 0.4, 40000.0, 0.75, 3259.863, 1147.86 + 0.4, 40000.0, 0.77, 3346.526, 1176.81 + 0.4, 40000.0, 0.79, 3433.015, 1207.04 + 0.4, 40000.0, 0.81, 3519.194, 1240.34 + 0.4, 40000.0, 0.83, 3605.122, 1276.6 + 0.4, 40000.0, 0.85, 3691.05, 1313.71 + 0.4, 40000.0, 0.87, 3777.074, 1351.18 + 0.4, 40000.0, 0.89, 3863.29, 1388.47 + 0.4, 40000.0, 0.91, 3949.794, 1425.09 + 0.4, 40000.0, 0.93, 4036.682, 1460.51 + 0.4, 40000.0, 0.95, 4124.05, 1494.21 + 0.4, 40000.0, 0.97, 4211.994, 1525.69 + 0.4, 40000.0, 0.99, 4300.61, 1554.42 + 0.4, 43000.0, 0.0, 145.0211, 145.021 + 0.4, 43000.0, 0.05, 177.1, 227.2 + 0.4, 43000.0, 0.07, 261.373, 252.283 + 0.4, 43000.0, 0.09, 342.8719, 276.42 + 0.4, 43000.0, 0.11, 421.9498, 299.676 + 0.4, 43000.0, 0.13, 498.9594, 322.118 + 0.4, 43000.0, 0.15, 574.2536, 343.811 + 0.4, 43000.0, 0.17, 648.1853, 364.821 + 0.4, 43000.0, 0.19, 721.1073, 385.214 + 0.4, 43000.0, 0.21, 793.3726, 405.057 + 0.4, 43000.0, 0.23, 865.334, 424.414 + 0.4, 43000.0, 0.25, 937.3443, 443.353 + 0.4, 43000.0, 0.27, 1009.756, 461.939 + 0.4, 43000.0, 0.29, 1082.923, 480.238 + 0.4, 43000.0, 0.31, 1158.985, 497.295 + 0.4, 43000.0, 0.33, 1237.861, 513.424 + 0.4, 43000.0, 0.35, 1317.25, 530.206 + 0.4, 43000.0, 0.37, 1396.639, 548.203 + 0.4, 43000.0, 0.39, 1475.515, 567.974 + 0.4, 43000.0, 0.41, 1551.463, 593.976 + 0.4, 43000.0, 0.43, 1624.43, 625.826 + 0.4, 43000.0, 0.45, 1696.725, 658.3 + 0.4, 43000.0, 0.47, 1768.756, 690.07 + 0.4, 43000.0, 0.49, 1840.931, 719.808 + 0.4, 43000.0, 0.51, 1914.998, 740.512 + 0.4, 43000.0, 0.53, 1991.04, 752.229 + 0.4, 43000.0, 0.55, 2067.475, 762.056 + 0.4, 43000.0, 0.57, 2144.062, 771.418 + 0.4, 43000.0, 0.59, 2220.56, 781.737 + 0.4, 43000.0, 0.61, 2295.856, 798.089 + 0.4, 43000.0, 0.63, 2369.918, 821.013 + 0.4, 43000.0, 0.65, 2443.8, 846.506 + 0.4, 43000.0, 0.67, 2517.682, 874.222 + 0.4, 43000.0, 0.69, 2591.744, 903.811 + 0.4, 43000.0, 0.71, 2667.04, 935.526 + 0.4, 43000.0, 0.73, 2743.538, 968.872 + 0.4, 43000.0, 0.75, 2820.125, 1002.61 + 0.4, 43000.0, 0.77, 2896.56, 1036.11 + 0.4, 43000.0, 0.79, 2972.602, 1068.72 + 0.4, 43000.0, 0.81, 3046.981, 1097.17 + 0.4, 43000.0, 0.83, 3119.704, 1121.46 + 0.4, 43000.0, 0.85, 3192.056, 1144.87 + 0.4, 43000.0, 0.87, 3264.295, 1168.05 + 0.4, 43000.0, 0.89, 3336.676, 1191.65 + 0.4, 43000.0, 0.91, 3409.456, 1216.3 + 0.4, 43000.0, 0.93, 3482.893, 1242.65 + 0.4, 43000.0, 0.95, 3557.244, 1271.36 + 0.4, 43000.0, 0.97, 3632.764, 1303.05 + 0.4, 43000.0, 0.99, 3709.711, 1338.37 + 0.4, 48000.0, 0.0, 114.1609, 114.161 + 0.4, 48000.0, 0.05, 145.5, 191.7 + 0.4, 48000.0, 0.07, 211.0027, 210.164 + 0.4, 48000.0, 0.09, 274.6888, 227.77 + 0.4, 48000.0, 0.11, 336.7621, 244.608 + 0.4, 48000.0, 0.13, 397.4264, 260.764 + 0.4, 48000.0, 0.15, 456.8857, 276.325 + 0.4, 48000.0, 0.17, 515.3439, 291.379 + 0.4, 48000.0, 0.19, 573.0048, 306.013 + 0.4, 48000.0, 0.21, 630.0723, 320.315 + 0.4, 48000.0, 0.23, 686.7504, 334.371 + 0.4, 48000.0, 0.25, 743.2429, 348.27 + 0.4, 48000.0, 0.27, 799.7536, 362.098 + 0.4, 48000.0, 0.29, 856.4865, 375.944 + 0.4, 48000.0, 0.31, 914.1452, 389.438 + 0.4, 48000.0, 0.33, 972.8124, 402.78 + 0.4, 48000.0, 0.35, 1031.95, 416.731 + 0.4, 48000.0, 0.37, 1091.52, 431.601 + 0.4, 48000.0, 0.39, 1151.483, 447.696 + 0.4, 48000.0, 0.41, 1211.905, 467.859 + 0.4, 48000.0, 0.43, 1272.723, 491.782 + 0.4, 48000.0, 0.45, 1333.744, 516.013 + 0.4, 48000.0, 0.47, 1394.878, 539.632 + 0.4, 48000.0, 0.49, 1456.038, 561.719 + 0.4, 48000.0, 0.51, 1517.405, 577.035 + 0.4, 48000.0, 0.53, 1578.825, 585.709 + 0.4, 48000.0, 0.55, 1639.806, 593.231 + 0.4, 48000.0, 0.57, 1700.13, 600.775 + 0.4, 48000.0, 0.59, 1759.575, 609.515 + 0.4, 48000.0, 0.61, 1816.116, 624.295 + 0.4, 48000.0, 0.63, 1869.97, 645.399 + 0.4, 48000.0, 0.65, 1923.6, 668.55 + 0.4, 48000.0, 0.67, 1977.662, 693.141 + 0.4, 48000.0, 0.69, 2032.812, 718.565 + 0.4, 48000.0, 0.71, 2092.721, 743.149 + 0.4, 48000.0, 0.73, 2157.313, 766.545 + 0.4, 48000.0, 0.75, 2222.769, 789.731 + 0.4, 48000.0, 0.77, 2288.283, 812.62 + 0.4, 48000.0, 0.79, 2353.049, 835.122 + 0.4, 48000.0, 0.81, 2413.749, 856.223 + 0.4, 48000.0, 0.83, 2470.187, 876.058 + 0.4, 48000.0, 0.85, 2525.287, 895.913 + 0.4, 48000.0, 0.87, 2579.464, 916.148 + 0.4, 48000.0, 0.89, 2633.13, 937.123 + 0.4, 48000.0, 0.91, 2686.697, 959.198 + 0.4, 48000.0, 0.93, 2740.579, 982.733 + 0.4, 48000.0, 0.95, 2795.187, 1008.09 + 0.4, 48000.0, 0.97, 2850.936, 1035.62 + 0.4, 48000.0, 0.99, 2908.238, 1065.7 + 0.45, 0.0, 0.0, 800.9154, 800.915 + 0.45, 0.0, 0.05, 791.3919, 901.968 + 0.45, 0.0, 0.07, 1107.86, 1034.18 + 0.45, 0.0, 0.09, 1424.332, 1165.27 + 0.45, 0.0, 0.11, 1740.808, 1295.32 + 0.45, 0.0, 0.13, 2057.288, 1424.4 + 0.45, 0.0, 0.15, 2373.771, 1552.6 + 0.45, 0.0, 0.17, 2690.256, 1679.99 + 0.45, 0.0, 0.19, 3006.745, 1806.66 + 0.45, 0.0, 0.21, 3323.236, 1932.67 + 0.45, 0.0, 0.23, 3639.729, 2058.12 + 0.45, 0.0, 0.25, 3956.224, 2183.07 + 0.45, 0.0, 0.27, 4272.721, 2307.62 + 0.45, 0.0, 0.29, 4589.22, 2431.83 + 0.45, 0.0, 0.31, 4905.72, 2555.78 + 0.45, 0.0, 0.33, 5222.221, 2679.56 + 0.45, 0.0, 0.35, 5538.723, 2803.25 + 0.45, 0.0, 0.37, 5855.226, 2926.91 + 0.45, 0.0, 0.39, 6171.729, 3050.64 + 0.45, 0.0, 0.41, 6488.233, 3174.57 + 0.45, 0.0, 0.43, 6804.74, 3298.76 + 0.45, 0.0, 0.45, 7121.244, 3423.21 + 0.45, 0.0, 0.47, 7437.746, 3547.96 + 0.45, 0.0, 0.49, 7754.243, 3673.06 + 0.45, 0.0, 0.51, 8070.727, 3798.54 + 0.45, 0.0, 0.53, 8387.197, 3924.46 + 0.45, 0.0, 0.55, 8703.666, 4050.9 + 0.45, 0.0, 0.57, 9020.136, 4177.92 + 0.45, 0.0, 0.59, 9336.61, 4305.58 + 0.45, 0.0, 0.61, 9653.092, 4434.22 + 0.45, 0.0, 0.63, 9969.583, 4563.83 + 0.45, 0.0, 0.65, 10286.09, 4694.06 + 0.45, 0.0, 0.67, 10602.61, 4824.85 + 0.45, 0.0, 0.69, 10919.14, 4956.13 + 0.45, 0.0, 0.71, 11235.74, 5087.52 + 0.45, 0.0, 0.73, 11552.38, 5219.04 + 0.45, 0.0, 0.75, 11869.02, 5351.03 + 0.45, 0.0, 0.77, 12185.66, 5483.57 + 0.45, 0.0, 0.79, 12502.27, 5616.72 + 0.45, 0.0, 0.81, 12818.79, 5750.43 + 0.45, 0.0, 0.83, 13135.23, 5884.78 + 0.45, 0.0, 0.85, 13451.64, 6020.04 + 0.45, 0.0, 0.87, 13768.04, 6156.34 + 0.45, 0.0, 0.89, 14084.43, 6293.8 + 0.45, 0.0, 0.91, 14400.83, 6432.56 + 0.45, 0.0, 0.93, 14717.25, 6572.74 + 0.45, 0.0, 0.95, 15033.7, 6714.48 + 0.45, 0.0, 0.97, 15350.2, 6857.9 + 0.45, 0.0, 0.99, 15666.74, 7003.13 + 0.45, 2000.0, 0.0, 749.8776, 749.878 + 0.45, 2000.0, 0.05, 762.5512, 856.751 + 0.45, 2000.0, 0.07, 1067.79, 981.415 + 0.45, 2000.0, 0.09, 1373.019, 1105.21 + 0.45, 2000.0, 0.11, 1678.239, 1228.21 + 0.45, 2000.0, 0.13, 1983.451, 1350.47 + 0.45, 2000.0, 0.15, 2288.656, 1472.06 + 0.45, 2000.0, 0.17, 2593.854, 1593.04 + 0.45, 2000.0, 0.19, 2899.046, 1713.46 + 0.45, 2000.0, 0.21, 3204.233, 1833.4 + 0.45, 2000.0, 0.23, 3509.414, 1952.92 + 0.45, 2000.0, 0.25, 3814.591, 2072.08 + 0.45, 2000.0, 0.27, 4119.765, 2190.94 + 0.45, 2000.0, 0.29, 4424.936, 2309.57 + 0.45, 2000.0, 0.31, 4730.104, 2428.03 + 0.45, 2000.0, 0.33, 5035.271, 2546.38 + 0.45, 2000.0, 0.35, 5340.436, 2664.69 + 0.45, 2000.0, 0.37, 5645.601, 2783.02 + 0.45, 2000.0, 0.39, 5950.767, 2901.43 + 0.45, 2000.0, 0.41, 6255.935, 3019.97 + 0.45, 2000.0, 0.43, 6561.107, 3138.7 + 0.45, 2000.0, 0.45, 6866.279, 3257.72 + 0.45, 2000.0, 0.47, 7171.451, 3377.09 + 0.45, 2000.0, 0.49, 7476.624, 3496.88 + 0.45, 2000.0, 0.51, 7781.797, 3617.23 + 0.45, 2000.0, 0.53, 8086.97, 3738.19 + 0.45, 2000.0, 0.55, 8392.141, 3859.72 + 0.45, 2000.0, 0.57, 8697.311, 3981.87 + 0.45, 2000.0, 0.59, 9002.478, 4104.66 + 0.45, 2000.0, 0.61, 9307.636, 4228.36 + 0.45, 2000.0, 0.63, 9612.787, 4352.96 + 0.45, 2000.0, 0.65, 9917.938, 4478.13 + 0.45, 2000.0, 0.67, 10223.09, 4603.78 + 0.45, 2000.0, 0.69, 10528.24, 4729.83 + 0.45, 2000.0, 0.71, 10833.4, 4855.69 + 0.45, 2000.0, 0.73, 11138.56, 4981.39 + 0.45, 2000.0, 0.75, 11443.72, 5107.61 + 0.45, 2000.0, 0.77, 11748.91, 5234.5 + 0.45, 2000.0, 0.79, 12054.1, 5362.24 + 0.45, 2000.0, 0.81, 12359.35, 5491.27 + 0.45, 2000.0, 0.83, 12664.65, 5621.68 + 0.45, 2000.0, 0.85, 12969.95, 5753.21 + 0.45, 2000.0, 0.87, 13275.24, 5885.87 + 0.45, 2000.0, 0.89, 13580.5, 6019.68 + 0.45, 2000.0, 0.91, 13885.73, 6154.66 + 0.45, 2000.0, 0.93, 14190.9, 6290.83 + 0.45, 2000.0, 0.95, 14496.02, 6428.22 + 0.45, 2000.0, 0.97, 14801.05, 6566.83 + 0.45, 2000.0, 0.99, 15106.0, 6706.7 + 0.45, 5000.0, 0.0, 678.1868, 678.187 + 0.45, 5000.0, 0.05, 718.6694, 787.493 + 0.45, 5000.0, 0.07, 1006.5, 902.054 + 0.45, 5000.0, 0.09, 1294.306, 1015.96 + 0.45, 5000.0, 0.11, 1582.089, 1129.27 + 0.45, 5000.0, 0.13, 1869.85, 1242.03 + 0.45, 5000.0, 0.15, 2157.593, 1354.3 + 0.45, 5000.0, 0.17, 2445.319, 1466.12 + 0.45, 5000.0, 0.19, 2733.03, 1577.55 + 0.45, 5000.0, 0.21, 3020.727, 1688.63 + 0.45, 5000.0, 0.23, 3308.414, 1799.43 + 0.45, 5000.0, 0.25, 3596.092, 1909.99 + 0.45, 5000.0, 0.27, 3883.763, 2020.36 + 0.45, 5000.0, 0.29, 4171.428, 2130.6 + 0.45, 5000.0, 0.31, 4459.091, 2240.75 + 0.45, 5000.0, 0.33, 4746.753, 2350.87 + 0.45, 5000.0, 0.35, 5034.416, 2461.02 + 0.45, 5000.0, 0.37, 5322.081, 2571.23 + 0.45, 5000.0, 0.39, 5609.752, 2681.57 + 0.45, 5000.0, 0.41, 5897.438, 2792.01 + 0.45, 5000.0, 0.43, 6185.139, 2902.62 + 0.45, 5000.0, 0.45, 6472.845, 3013.57 + 0.45, 5000.0, 0.47, 6760.554, 3124.93 + 0.45, 5000.0, 0.49, 7048.265, 3236.8 + 0.45, 5000.0, 0.51, 7335.958, 3349.48 + 0.45, 5000.0, 0.53, 7623.637, 3463.01 + 0.45, 5000.0, 0.55, 7911.323, 3577.14 + 0.45, 5000.0, 0.57, 8199.023, 3691.85 + 0.45, 5000.0, 0.59, 8486.741, 3807.11 + 0.45, 5000.0, 0.61, 8774.534, 3922.91 + 0.45, 5000.0, 0.63, 9062.393, 4039.22 + 0.45, 5000.0, 0.65, 9350.256, 4156.02 + 0.45, 5000.0, 0.67, 9638.103, 4273.27 + 0.45, 5000.0, 0.69, 9925.919, 4390.96 + 0.45, 5000.0, 0.71, 10213.62, 4508.63 + 0.45, 5000.0, 0.73, 10501.19, 4626.35 + 0.45, 5000.0, 0.75, 10788.74, 4744.74 + 0.45, 5000.0, 0.77, 11076.27, 4864.0 + 0.45, 5000.0, 0.79, 11363.8, 4984.29 + 0.45, 5000.0, 0.81, 11651.4, 5106.26 + 0.45, 5000.0, 0.83, 11939.07, 5229.97 + 0.45, 5000.0, 0.85, 12226.76, 5354.96 + 0.45, 5000.0, 0.87, 12514.46, 5481.19 + 0.45, 5000.0, 0.89, 12802.16, 5608.64 + 0.45, 5000.0, 0.91, 13089.85, 5737.27 + 0.45, 5000.0, 0.93, 13377.53, 5867.07 + 0.45, 5000.0, 0.95, 13665.19, 5997.99 + 0.45, 5000.0, 0.97, 13952.81, 6130.01 + 0.45, 5000.0, 0.99, 14240.4, 6263.1 + 0.45, 10000.0, 0.0, 570.8641, 570.864 + 0.45, 10000.0, 0.05, 651.9469, 675.959 + 0.45, 10000.0, 0.07, 910.4855, 776.43 + 0.45, 10000.0, 0.09, 1169.157, 876.307 + 0.45, 10000.0, 0.11, 1427.952, 975.645 + 0.45, 10000.0, 0.13, 1686.86, 1074.5 + 0.45, 10000.0, 0.15, 1945.871, 1172.92 + 0.45, 10000.0, 0.17, 2204.974, 1270.97 + 0.45, 10000.0, 0.19, 2464.159, 1368.71 + 0.45, 10000.0, 0.21, 2723.417, 1466.17 + 0.45, 10000.0, 0.23, 2982.737, 1563.43 + 0.45, 10000.0, 0.25, 3242.109, 1660.54 + 0.45, 10000.0, 0.27, 3501.523, 1757.55 + 0.45, 10000.0, 0.29, 3760.969, 1854.51 + 0.45, 10000.0, 0.31, 4020.436, 1951.48 + 0.45, 10000.0, 0.33, 4279.914, 2048.52 + 0.45, 10000.0, 0.35, 4539.393, 2145.68 + 0.45, 10000.0, 0.37, 4798.864, 2243.02 + 0.45, 10000.0, 0.39, 5058.315, 2340.59 + 0.45, 10000.0, 0.41, 5317.697, 2438.43 + 0.45, 10000.0, 0.43, 5577.009, 2536.61 + 0.45, 10000.0, 0.45, 5836.3, 2635.19 + 0.45, 10000.0, 0.47, 6095.58, 2734.24 + 0.45, 10000.0, 0.49, 6354.859, 2833.82 + 0.45, 10000.0, 0.51, 6614.158, 2934.22 + 0.45, 10000.0, 0.53, 6873.483, 3035.45 + 0.45, 10000.0, 0.55, 7132.825, 3137.22 + 0.45, 10000.0, 0.57, 7392.186, 3239.47 + 0.45, 10000.0, 0.59, 7651.569, 3342.15 + 0.45, 10000.0, 0.61, 7911.01, 3444.85 + 0.45, 10000.0, 0.63, 8170.504, 3547.58 + 0.45, 10000.0, 0.65, 8430.004, 3650.85 + 0.45, 10000.0, 0.67, 8689.499, 3754.77 + 0.45, 10000.0, 0.69, 8948.974, 3859.48 + 0.45, 10000.0, 0.71, 9208.366, 3965.26 + 0.45, 10000.0, 0.73, 9467.676, 4072.22 + 0.45, 10000.0, 0.75, 9726.963, 4180.19 + 0.45, 10000.0, 0.77, 9986.24, 4289.21 + 0.45, 10000.0, 0.79, 10245.52, 4399.32 + 0.45, 10000.0, 0.81, 10504.84, 4510.56 + 0.45, 10000.0, 0.83, 10764.2, 4622.95 + 0.45, 10000.0, 0.85, 11023.58, 4736.54 + 0.45, 10000.0, 0.87, 11282.97, 4851.38 + 0.45, 10000.0, 0.89, 11542.36, 4967.49 + 0.45, 10000.0, 0.91, 11801.76, 5084.92 + 0.45, 10000.0, 0.93, 12061.15, 5203.72 + 0.45, 10000.0, 0.95, 12320.54, 5323.91 + 0.45, 10000.0, 0.97, 12579.93, 5445.53 + 0.45, 10000.0, 0.99, 12839.3, 5568.63 + 0.45, 15000.0, 0.0, 477.46, 477.46 + 0.45, 15000.0, 0.05, 559.0813, 532.287 + 0.45, 15000.0, 0.07, 782.7614, 619.343 + 0.45, 15000.0, 0.09, 1006.432, 704.967 + 0.45, 15000.0, 0.11, 1230.094, 789.288 + 0.45, 15000.0, 0.13, 1453.749, 872.437 + 0.45, 15000.0, 0.15, 1677.398, 954.544 + 0.45, 15000.0, 0.17, 1901.041, 1035.74 + 0.45, 15000.0, 0.19, 2124.681, 1116.15 + 0.45, 15000.0, 0.21, 2348.318, 1195.91 + 0.45, 15000.0, 0.23, 2571.954, 1275.15 + 0.45, 15000.0, 0.25, 2795.589, 1354.0 + 0.45, 15000.0, 0.27, 3019.224, 1432.58 + 0.45, 15000.0, 0.29, 3242.862, 1511.04 + 0.45, 15000.0, 0.31, 3466.507, 1589.65 + 0.45, 15000.0, 0.33, 3690.161, 1668.51 + 0.45, 15000.0, 0.35, 3913.816, 1747.51 + 0.45, 15000.0, 0.37, 4137.471, 1826.71 + 0.45, 15000.0, 0.39, 4361.124, 1906.15 + 0.45, 15000.0, 0.41, 4584.769, 1985.95 + 0.45, 15000.0, 0.43, 4808.405, 2066.14 + 0.45, 15000.0, 0.45, 5032.04, 2146.7 + 0.45, 15000.0, 0.47, 5255.675, 2227.67 + 0.45, 15000.0, 0.49, 5479.312, 2309.07 + 0.45, 15000.0, 0.51, 5702.951, 2391.04 + 0.45, 15000.0, 0.53, 5926.593, 2473.59 + 0.45, 15000.0, 0.55, 6150.242, 2556.58 + 0.45, 15000.0, 0.57, 6373.9, 2639.99 + 0.45, 15000.0, 0.59, 6597.568, 2723.78 + 0.45, 15000.0, 0.61, 6821.271, 2807.61 + 0.45, 15000.0, 0.63, 7045.006, 2891.53 + 0.45, 15000.0, 0.65, 7268.74, 2976.0 + 0.45, 15000.0, 0.67, 7492.464, 3061.13 + 0.45, 15000.0, 0.69, 7716.17, 3147.05 + 0.45, 15000.0, 0.71, 7939.807, 3234.17 + 0.45, 15000.0, 0.73, 8163.377, 3322.54 + 0.45, 15000.0, 0.75, 8386.929, 3411.89 + 0.45, 15000.0, 0.77, 8610.474, 3502.22 + 0.45, 15000.0, 0.79, 8834.022, 3593.5 + 0.45, 15000.0, 0.81, 9057.611, 3685.64 + 0.45, 15000.0, 0.83, 9281.246, 3778.64 + 0.45, 15000.0, 0.85, 9504.893, 3872.68 + 0.45, 15000.0, 0.87, 9728.549, 3967.79 + 0.45, 15000.0, 0.89, 9952.212, 4064.03 + 0.45, 15000.0, 0.91, 10175.88, 4161.44 + 0.45, 15000.0, 0.93, 10399.54, 4260.08 + 0.45, 15000.0, 0.95, 10623.2, 4359.99 + 0.45, 15000.0, 0.97, 10846.84, 4461.22 + 0.45, 15000.0, 0.99, 11070.48, 4563.82 + 0.45, 20000.0, 0.0, 396.6007, 396.601 + 0.45, 20000.0, 0.05, 465.3062, 445.581 + 0.45, 20000.0, 0.07, 651.4577, 515.636 + 0.45, 20000.0, 0.09, 837.6036, 584.61 + 0.45, 20000.0, 0.11, 1023.745, 652.6 + 0.45, 20000.0, 0.13, 1209.881, 719.707 + 0.45, 20000.0, 0.15, 1396.015, 786.029 + 0.45, 20000.0, 0.17, 1582.145, 851.666 + 0.45, 20000.0, 0.19, 1768.274, 916.715 + 0.45, 20000.0, 0.21, 1954.401, 981.276 + 0.45, 20000.0, 0.23, 2140.527, 1045.45 + 0.45, 20000.0, 0.25, 2326.654, 1109.33 + 0.45, 20000.0, 0.27, 2512.781, 1173.02 + 0.45, 20000.0, 0.29, 2698.91, 1236.62 + 0.45, 20000.0, 0.31, 2885.045, 1300.32 + 0.45, 20000.0, 0.33, 3071.185, 1364.2 + 0.45, 20000.0, 0.35, 3257.327, 1428.22 + 0.45, 20000.0, 0.37, 3443.467, 1492.42 + 0.45, 20000.0, 0.39, 3629.606, 1556.85 + 0.45, 20000.0, 0.41, 3815.737, 1621.67 + 0.45, 20000.0, 0.43, 4001.859, 1686.9 + 0.45, 20000.0, 0.45, 4187.98, 1752.45 + 0.45, 20000.0, 0.47, 4374.101, 1818.32 + 0.45, 20000.0, 0.49, 4560.224, 1884.53 + 0.45, 20000.0, 0.51, 4746.359, 1951.06 + 0.45, 20000.0, 0.53, 4932.503, 2017.93 + 0.45, 20000.0, 0.55, 5118.65, 2085.15 + 0.45, 20000.0, 0.57, 5304.796, 2152.7 + 0.45, 20000.0, 0.59, 5490.941, 2220.61 + 0.45, 20000.0, 0.61, 5677.078, 2288.67 + 0.45, 20000.0, 0.63, 5863.206, 2356.95 + 0.45, 20000.0, 0.65, 6049.331, 2425.72 + 0.45, 20000.0, 0.67, 6235.453, 2495.09 + 0.45, 20000.0, 0.69, 6421.572, 2565.14 + 0.45, 20000.0, 0.71, 6607.686, 2636.19 + 0.45, 20000.0, 0.73, 6793.795, 2708.28 + 0.45, 20000.0, 0.75, 6979.906, 2781.2 + 0.45, 20000.0, 0.77, 7166.021, 2854.95 + 0.45, 20000.0, 0.79, 7352.142, 2929.52 + 0.45, 20000.0, 0.81, 7538.285, 3004.86 + 0.45, 20000.0, 0.83, 7724.448, 3080.97 + 0.45, 20000.0, 0.85, 7910.615, 3157.94 + 0.45, 20000.0, 0.87, 8096.784, 3235.79 + 0.45, 20000.0, 0.89, 8282.95, 3314.55 + 0.45, 20000.0, 0.91, 8469.11, 3394.23 + 0.45, 20000.0, 0.93, 8655.261, 3474.86 + 0.45, 20000.0, 0.95, 8841.399, 3556.47 + 0.45, 20000.0, 0.97, 9027.52, 3639.09 + 0.45, 20000.0, 0.99, 9213.621, 3722.73 + 0.45, 25000.0, 0.0, 326.9932, 326.993 + 0.45, 25000.0, 0.05, 386.5, 373.95 + 0.45, 25000.0, 0.07, 541.0403, 430.53 + 0.45, 25000.0, 0.09, 695.5882, 486.139 + 0.45, 25000.0, 0.11, 850.1436, 540.873 + 0.45, 25000.0, 0.13, 1004.706, 594.829 + 0.45, 25000.0, 0.15, 1159.275, 648.104 + 0.45, 25000.0, 0.17, 1313.85, 700.796 + 0.45, 25000.0, 0.19, 1468.432, 753.0 + 0.45, 25000.0, 0.21, 1623.019, 804.814 + 0.45, 25000.0, 0.23, 1777.612, 856.336 + 0.45, 25000.0, 0.25, 1932.21, 907.66 + 0.45, 25000.0, 0.27, 2086.813, 958.886 + 0.45, 25000.0, 0.29, 2241.42, 1010.11 + 0.45, 25000.0, 0.31, 2396.036, 1061.59 + 0.45, 25000.0, 0.33, 2550.66, 1113.38 + 0.45, 25000.0, 0.35, 2705.284, 1165.34 + 0.45, 25000.0, 0.37, 2859.905, 1217.49 + 0.45, 25000.0, 0.39, 3014.52, 1269.86 + 0.45, 25000.0, 0.41, 3169.118, 1322.51 + 0.45, 25000.0, 0.43, 3323.697, 1375.46 + 0.45, 25000.0, 0.45, 3478.269, 1428.63 + 0.45, 25000.0, 0.47, 3632.834, 1482.02 + 0.45, 25000.0, 0.49, 3787.396, 1535.61 + 0.45, 25000.0, 0.51, 3941.953, 1589.25 + 0.45, 25000.0, 0.53, 4096.509, 1642.98 + 0.45, 25000.0, 0.55, 4251.066, 1696.98 + 0.45, 25000.0, 0.57, 4405.625, 1751.31 + 0.45, 25000.0, 0.59, 4560.19, 1806.03 + 0.45, 25000.0, 0.61, 4714.761, 1861.22 + 0.45, 25000.0, 0.63, 4869.34, 1916.94 + 0.45, 25000.0, 0.65, 5023.931, 1973.18 + 0.45, 25000.0, 0.67, 5178.536, 2030.0 + 0.45, 25000.0, 0.69, 5333.157, 2087.42 + 0.45, 25000.0, 0.71, 5487.826, 2145.58 + 0.45, 25000.0, 0.73, 5642.536, 2204.49 + 0.45, 25000.0, 0.75, 5797.25, 2264.07 + 0.45, 25000.0, 0.77, 5951.956, 2324.32 + 0.45, 25000.0, 0.79, 6106.642, 2385.24 + 0.45, 25000.0, 0.81, 6261.263, 2446.8 + 0.45, 25000.0, 0.83, 6415.815, 2509.02 + 0.45, 25000.0, 0.85, 6570.341, 2571.92 + 0.45, 25000.0, 0.87, 6724.845, 2635.52 + 0.45, 25000.0, 0.89, 6879.334, 2699.83 + 0.45, 25000.0, 0.91, 7033.814, 2764.85 + 0.45, 25000.0, 0.93, 7188.292, 2830.61 + 0.45, 25000.0, 0.95, 7342.772, 2897.1 + 0.45, 25000.0, 0.97, 7497.261, 2964.35 + 0.45, 25000.0, 0.99, 7651.765, 3032.36 + 0.45, 30000.0, 0.0, 267.4372, 267.437 + 0.45, 30000.0, 0.05, 319.95, 315.6 + 0.45, 30000.0, 0.07, 448.0375, 360.192 + 0.45, 30000.0, 0.09, 576.1047, 404.204 + 0.45, 30000.0, 0.11, 704.1541, 447.692 + 0.45, 30000.0, 0.13, 832.1883, 490.714 + 0.45, 30000.0, 0.15, 960.2098, 533.325 + 0.45, 30000.0, 0.17, 1088.221, 575.582 + 0.45, 30000.0, 0.19, 1216.225, 617.54 + 0.45, 30000.0, 0.21, 1344.224, 659.257 + 0.45, 30000.0, 0.23, 1472.22, 700.788 + 0.45, 30000.0, 0.25, 1600.217, 742.19 + 0.45, 30000.0, 0.27, 1728.216, 783.519 + 0.45, 30000.0, 0.29, 1856.22, 824.832 + 0.45, 30000.0, 0.31, 1984.242, 866.231 + 0.45, 30000.0, 0.33, 2112.283, 907.761 + 0.45, 30000.0, 0.35, 2240.328, 949.409 + 0.45, 30000.0, 0.37, 2368.377, 991.211 + 0.45, 30000.0, 0.39, 2496.426, 1033.2 + 0.45, 30000.0, 0.41, 2624.474, 1075.5 + 0.45, 30000.0, 0.43, 2752.518, 1118.13 + 0.45, 30000.0, 0.45, 2880.555, 1160.99 + 0.45, 30000.0, 0.47, 3008.582, 1204.05 + 0.45, 30000.0, 0.49, 3136.598, 1247.3 + 0.45, 30000.0, 0.51, 3264.572, 1290.65 + 0.45, 30000.0, 0.53, 3392.508, 1334.09 + 0.45, 30000.0, 0.55, 3520.444, 1377.77 + 0.45, 30000.0, 0.57, 3648.39, 1421.71 + 0.45, 30000.0, 0.59, 3776.356, 1465.95 + 0.45, 30000.0, 0.61, 3904.399, 1510.5 + 0.45, 30000.0, 0.63, 4032.518, 1555.39 + 0.45, 30000.0, 0.65, 4160.655, 1600.71 + 0.45, 30000.0, 0.67, 4288.798, 1646.52 + 0.45, 30000.0, 0.69, 4416.937, 1692.86 + 0.45, 30000.0, 0.71, 4545.021, 1739.9 + 0.45, 30000.0, 0.73, 4673.05, 1787.66 + 0.45, 30000.0, 0.75, 4801.064, 1836.04 + 0.45, 30000.0, 0.77, 4929.07, 1885.03 + 0.45, 30000.0, 0.79, 5057.073, 1934.64 + 0.45, 30000.0, 0.81, 5185.097, 1984.9 + 0.45, 30000.0, 0.83, 5313.145, 2035.81 + 0.45, 30000.0, 0.85, 5441.194, 2087.31 + 0.45, 30000.0, 0.87, 5569.241, 2139.38 + 0.45, 30000.0, 0.89, 5697.282, 2192.01 + 0.45, 30000.0, 0.91, 5825.315, 2245.17 + 0.45, 30000.0, 0.93, 5953.337, 2298.85 + 0.45, 30000.0, 0.95, 6081.344, 2353.03 + 0.45, 30000.0, 0.97, 6209.333, 2407.69 + 0.45, 30000.0, 0.99, 6337.3, 2462.82 + 0.45, 35000.0, 0.0, 216.8173, 216.817 + 0.45, 35000.0, 0.05, 267.95, 275.925 + 0.45, 35000.0, 0.07, 375.5347, 309.988 + 0.45, 35000.0, 0.09, 483.2585, 343.995 + 0.45, 35000.0, 0.11, 591.1063, 377.955 + 0.45, 35000.0, 0.13, 699.063, 411.88 + 0.45, 35000.0, 0.15, 807.1134, 445.781 + 0.45, 35000.0, 0.17, 915.2424, 479.669 + 0.45, 35000.0, 0.19, 1023.435, 513.555 + 0.45, 35000.0, 0.21, 1131.675, 547.449 + 0.45, 35000.0, 0.23, 1239.949, 581.363 + 0.45, 35000.0, 0.25, 1348.241, 615.308 + 0.45, 35000.0, 0.27, 1456.536, 649.294 + 0.45, 35000.0, 0.29, 1564.818, 683.332 + 0.45, 35000.0, 0.31, 1673.046, 717.5 + 0.45, 35000.0, 0.33, 1781.211, 751.792 + 0.45, 35000.0, 0.35, 1889.338, 786.122 + 0.45, 35000.0, 0.37, 1997.424, 820.469 + 0.45, 35000.0, 0.39, 2105.469, 854.811 + 0.45, 35000.0, 0.41, 2213.48, 888.793 + 0.45, 35000.0, 0.43, 2321.454, 922.473 + 0.45, 35000.0, 0.45, 2429.372, 956.333 + 0.45, 35000.0, 0.47, 2537.227, 990.514 + 0.45, 35000.0, 0.49, 2645.011, 1025.16 + 0.45, 35000.0, 0.51, 2752.618, 1060.95 + 0.45, 35000.0, 0.53, 2860.065, 1097.89 + 0.45, 35000.0, 0.55, 2967.492, 1135.33 + 0.45, 35000.0, 0.57, 3074.942, 1173.16 + 0.45, 35000.0, 0.59, 3182.456, 1211.26 + 0.45, 35000.0, 0.61, 3290.273, 1249.23 + 0.45, 35000.0, 0.63, 3398.386, 1287.02 + 0.45, 35000.0, 0.65, 3506.544, 1324.93 + 0.45, 35000.0, 0.67, 3614.691, 1362.99 + 0.45, 35000.0, 0.69, 3722.775, 1401.22 + 0.45, 35000.0, 0.71, 3830.494, 1439.33 + 0.45, 35000.0, 0.73, 3937.853, 1477.42 + 0.45, 35000.0, 0.75, 4045.164, 1515.97 + 0.45, 35000.0, 0.77, 4152.49, 1555.13 + 0.45, 35000.0, 0.79, 4259.897, 1595.08 + 0.45, 35000.0, 0.81, 4367.681, 1636.68 + 0.45, 35000.0, 0.83, 4475.852, 1679.92 + 0.45, 35000.0, 0.85, 4584.127, 1723.95 + 0.45, 35000.0, 0.87, 4692.457, 1768.6 + 0.45, 35000.0, 0.89, 4800.794, 1813.69 + 0.45, 35000.0, 0.91, 4909.089, 1859.06 + 0.45, 35000.0, 0.93, 5017.295, 1904.53 + 0.45, 35000.0, 0.95, 5125.361, 1949.94 + 0.45, 35000.0, 0.97, 5233.24, 1995.12 + 0.45, 35000.0, 0.99, 5340.882, 2039.89 + 0.45, 40000.0, 0.0, 171.5898, 171.59 + 0.45, 40000.0, 0.05, 213.3, 237.875 + 0.45, 40000.0, 0.07, 297.9561, 265.132 + 0.45, 40000.0, 0.09, 382.6132, 291.944 + 0.45, 40000.0, 0.11, 467.2804, 318.377 + 0.45, 40000.0, 0.13, 551.9668, 344.499 + 0.45, 40000.0, 0.15, 636.6812, 370.378 + 0.45, 40000.0, 0.17, 721.4329, 396.08 + 0.45, 40000.0, 0.19, 806.2309, 421.673 + 0.45, 40000.0, 0.21, 891.0841, 447.225 + 0.45, 40000.0, 0.23, 976.0016, 472.802 + 0.45, 40000.0, 0.25, 1060.992, 498.473 + 0.45, 40000.0, 0.27, 1146.066, 524.305 + 0.45, 40000.0, 0.29, 1231.231, 550.364 + 0.45, 40000.0, 0.31, 1316.615, 577.051 + 0.45, 40000.0, 0.33, 1402.201, 604.352 + 0.45, 40000.0, 0.35, 1487.817, 631.842 + 0.45, 40000.0, 0.37, 1573.416, 659.427 + 0.45, 40000.0, 0.39, 1658.949, 687.012 + 0.45, 40000.0, 0.41, 1744.207, 714.077 + 0.45, 40000.0, 0.43, 1829.181, 740.633 + 0.45, 40000.0, 0.45, 1914.056, 767.219 + 0.45, 40000.0, 0.47, 1998.862, 793.946 + 0.45, 40000.0, 0.49, 2083.625, 820.928 + 0.45, 40000.0, 0.51, 2168.362, 848.734 + 0.45, 40000.0, 0.53, 2253.103, 877.366 + 0.45, 40000.0, 0.55, 2337.895, 906.259 + 0.45, 40000.0, 0.57, 2422.773, 935.306 + 0.45, 40000.0, 0.59, 2507.771, 964.397 + 0.45, 40000.0, 0.61, 2593.118, 992.98 + 0.45, 40000.0, 0.63, 2678.801, 1021.05 + 0.45, 40000.0, 0.65, 2764.564, 1049.17 + 0.45, 40000.0, 0.67, 2850.347, 1077.44 + 0.45, 40000.0, 0.69, 2936.089, 1105.96 + 0.45, 40000.0, 0.71, 3021.584, 1134.78 + 0.45, 40000.0, 0.73, 3106.807, 1164.02 + 0.45, 40000.0, 0.75, 3191.913, 1193.89 + 0.45, 40000.0, 0.77, 3276.91, 1224.52 + 0.45, 40000.0, 0.79, 3361.809, 1256.05 + 0.45, 40000.0, 0.81, 3446.53, 1289.5 + 0.45, 40000.0, 0.83, 3531.104, 1324.8 + 0.45, 40000.0, 0.85, 3615.673, 1360.77 + 0.45, 40000.0, 0.87, 3700.291, 1397.13 + 0.45, 40000.0, 0.89, 3785.011, 1433.58 + 0.45, 40000.0, 0.91, 3869.885, 1469.84 + 0.45, 40000.0, 0.93, 3954.966, 1505.62 + 0.45, 40000.0, 0.95, 4040.308, 1540.62 + 0.45, 40000.0, 0.97, 4125.963, 1574.57 + 0.45, 40000.0, 0.99, 4211.985, 1607.17 + 0.45, 43000.0, 0.0, 148.634, 148.634 + 0.45, 43000.0, 0.05, 177.1, 228.8 + 0.45, 43000.0, 0.07, 256.5616, 253.495 + 0.45, 43000.0, 0.09, 334.2549, 277.62 + 0.45, 43000.0, 0.11, 410.4044, 301.212 + 0.45, 43000.0, 0.13, 485.235, 324.309 + 0.45, 43000.0, 0.15, 558.9714, 346.95 + 0.45, 43000.0, 0.17, 631.8383, 369.171 + 0.45, 43000.0, 0.19, 704.0605, 391.011 + 0.45, 43000.0, 0.21, 775.8626, 412.508 + 0.45, 43000.0, 0.23, 847.4694, 433.698 + 0.45, 43000.0, 0.25, 919.1057, 454.62 + 0.45, 43000.0, 0.27, 990.9962, 475.312 + 0.45, 43000.0, 0.29, 1063.366, 495.811 + 0.45, 43000.0, 0.31, 1137.575, 515.453 + 0.45, 43000.0, 0.33, 1213.574, 534.445 + 0.45, 43000.0, 0.35, 1289.9, 553.869 + 0.45, 43000.0, 0.37, 1366.226, 574.103 + 0.45, 43000.0, 0.39, 1442.225, 595.525 + 0.45, 43000.0, 0.41, 1516.363, 621.088 + 0.45, 43000.0, 0.43, 1588.608, 650.546 + 0.45, 43000.0, 0.45, 1660.425, 680.456 + 0.45, 43000.0, 0.47, 1732.074, 709.948 + 0.45, 43000.0, 0.49, 1803.815, 738.152 + 0.45, 43000.0, 0.51, 1876.755, 760.484 + 0.45, 43000.0, 0.53, 1950.949, 776.973 + 0.45, 43000.0, 0.55, 2025.394, 792.269 + 0.45, 43000.0, 0.57, 2099.936, 807.302 + 0.45, 43000.0, 0.59, 2174.424, 823.006 + 0.45, 43000.0, 0.61, 2248.155, 842.666 + 0.45, 43000.0, 0.63, 2321.109, 866.644 + 0.45, 43000.0, 0.65, 2393.95, 892.375 + 0.45, 43000.0, 0.67, 2466.791, 919.65 + 0.45, 43000.0, 0.69, 2539.745, 948.26 + 0.45, 43000.0, 0.71, 2613.476, 978.43 + 0.45, 43000.0, 0.73, 2687.964, 1009.85 + 0.45, 43000.0, 0.75, 2762.506, 1041.65 + 0.45, 43000.0, 0.77, 2836.951, 1073.42 + 0.45, 43000.0, 0.79, 2911.145, 1104.74 + 0.45, 43000.0, 0.81, 2984.283, 1133.43 + 0.45, 43000.0, 0.83, 3056.372, 1159.48 + 0.45, 43000.0, 0.85, 3128.225, 1185.1 + 0.45, 43000.0, 0.87, 3200.006, 1210.72 + 0.45, 43000.0, 0.89, 3271.879, 1236.77 + 0.45, 43000.0, 0.91, 3344.005, 1263.7 + 0.45, 43000.0, 0.93, 3416.55, 1291.92 + 0.45, 43000.0, 0.95, 3489.675, 1321.87 + 0.45, 43000.0, 0.97, 3563.544, 1354.0 + 0.45, 43000.0, 0.99, 3638.321, 1388.73 + 0.45, 48000.0, 0.0, 117.005, 117.005 + 0.45, 48000.0, 0.05, 143.4, 188.3 + 0.45, 48000.0, 0.07, 205.4498, 206.934 + 0.45, 48000.0, 0.09, 266.3341, 225.042 + 0.45, 48000.0, 0.11, 326.1835, 242.675 + 0.45, 48000.0, 0.13, 385.1286, 259.889 + 0.45, 48000.0, 0.15, 443.3, 276.736 + 0.45, 48000.0, 0.17, 500.8282, 293.269 + 0.45, 48000.0, 0.19, 557.8437, 309.544 + 0.45, 48000.0, 0.21, 614.4771, 325.612 + 0.45, 48000.0, 0.23, 670.859, 341.527 + 0.45, 48000.0, 0.25, 727.12, 357.343 + 0.45, 48000.0, 0.27, 783.3906, 373.113 + 0.45, 48000.0, 0.29, 839.8013, 388.891 + 0.45, 48000.0, 0.31, 896.7982, 404.407 + 0.45, 48000.0, 0.33, 954.4354, 419.792 + 0.45, 48000.0, 0.35, 1012.375, 435.581 + 0.45, 48000.0, 0.37, 1070.595, 451.984 + 0.45, 48000.0, 0.39, 1129.072, 469.211 + 0.45, 48000.0, 0.41, 1187.863, 489.15 + 0.45, 48000.0, 0.43, 1246.928, 511.604 + 0.45, 48000.0, 0.45, 1306.125, 534.294 + 0.45, 48000.0, 0.47, 1365.394, 556.618 + 0.45, 48000.0, 0.49, 1424.675, 577.974 + 0.45, 48000.0, 0.51, 1484.062, 594.937 + 0.45, 48000.0, 0.53, 1543.458, 607.59 + 0.45, 48000.0, 0.55, 1602.569, 619.519 + 0.45, 48000.0, 0.57, 1661.257, 631.49 + 0.45, 48000.0, 0.59, 1719.387, 644.269 + 0.45, 48000.0, 0.61, 1775.678, 660.975 + 0.45, 48000.0, 0.63, 1830.27, 681.804 + 0.45, 48000.0, 0.65, 1884.725, 704.025 + 0.45, 48000.0, 0.67, 1939.46, 727.262 + 0.45, 48000.0, 0.69, 1994.892, 751.139 + 0.45, 48000.0, 0.71, 2053.368, 774.645 + 0.45, 48000.0, 0.73, 2114.838, 797.557 + 0.45, 48000.0, 0.75, 2176.856, 820.444 + 0.45, 48000.0, 0.77, 2238.904, 843.236 + 0.45, 48000.0, 0.79, 2300.464, 865.867 + 0.45, 48000.0, 0.81, 2359.398, 887.612 + 0.45, 48000.0, 0.83, 2415.579, 908.563 + 0.45, 48000.0, 0.85, 2470.9, 929.625 + 0.45, 48000.0, 0.87, 2525.629, 951.047 + 0.45, 48000.0, 0.89, 2580.034, 973.078 + 0.45, 48000.0, 0.91, 2634.386, 995.968 + 0.45, 48000.0, 0.93, 2688.951, 1019.97 + 0.45, 48000.0, 0.95, 2744.0, 1045.33 + 0.45, 48000.0, 0.97, 2799.801, 1072.29 + 0.45, 48000.0, 0.99, 2856.622, 1101.11 + 0.5, 0.0, 0.0, 823.0539, 823.054 + 0.5, 0.0, 0.05, 760.775, 955.544 + 0.5, 0.0, 0.07, 1065.482, 1090.7 + 0.5, 0.0, 0.09, 1370.166, 1224.76 + 0.5, 0.0, 0.11, 1674.829, 1357.79 + 0.5, 0.0, 0.13, 1979.473, 1489.87 + 0.5, 0.0, 0.15, 2284.1, 1621.06 + 0.5, 0.0, 0.17, 2588.711, 1751.43 + 0.5, 0.0, 0.19, 2893.307, 1881.05 + 0.5, 0.0, 0.21, 3197.89, 2009.99 + 0.5, 0.0, 0.23, 3502.462, 2138.32 + 0.5, 0.0, 0.25, 3807.025, 2266.12 + 0.5, 0.0, 0.27, 4111.58, 2393.44 + 0.5, 0.0, 0.29, 4416.128, 2520.37 + 0.5, 0.0, 0.31, 4720.671, 2646.96 + 0.5, 0.0, 0.33, 5025.211, 2773.29 + 0.5, 0.0, 0.35, 5329.75, 2899.43 + 0.5, 0.0, 0.37, 5634.289, 3025.45 + 0.5, 0.0, 0.39, 5938.829, 3151.42 + 0.5, 0.0, 0.41, 6243.379, 3277.41 + 0.5, 0.0, 0.43, 6547.939, 3403.49 + 0.5, 0.0, 0.45, 6852.5, 3529.73 + 0.5, 0.0, 0.47, 7157.061, 3656.18 + 0.5, 0.0, 0.49, 7461.621, 3782.91 + 0.5, 0.0, 0.51, 7766.17, 3910.04 + 0.5, 0.0, 0.53, 8070.707, 4037.61 + 0.5, 0.0, 0.55, 8375.244, 4165.62 + 0.5, 0.0, 0.57, 8679.783, 4294.1 + 0.5, 0.0, 0.59, 8984.326, 4423.1 + 0.5, 0.0, 0.61, 9288.878, 4552.86 + 0.5, 0.0, 0.63, 9593.44, 4683.37 + 0.5, 0.0, 0.65, 9898.013, 4814.36 + 0.5, 0.0, 0.67, 10202.6, 4945.76 + 0.5, 0.0, 0.69, 10507.2, 5077.51 + 0.5, 0.0, 0.71, 10811.84, 5209.26 + 0.5, 0.0, 0.73, 11116.51, 5341.02 + 0.5, 0.0, 0.75, 11421.19, 5473.14 + 0.5, 0.0, 0.77, 11725.85, 5605.69 + 0.5, 0.0, 0.79, 12030.49, 5738.75 + 0.5, 0.0, 0.81, 12335.05, 5872.3 + 0.5, 0.0, 0.83, 12639.53, 6006.41 + 0.5, 0.0, 0.85, 12943.98, 6141.34 + 0.5, 0.0, 0.87, 13248.43, 6277.19 + 0.5, 0.0, 0.89, 13552.87, 6414.11 + 0.5, 0.0, 0.91, 13857.33, 6552.2 + 0.5, 0.0, 0.93, 14161.82, 6691.6 + 0.5, 0.0, 0.95, 14466.34, 6832.44 + 0.5, 0.0, 0.97, 14770.92, 6974.83 + 0.5, 0.0, 0.99, 15075.55, 7118.9 + 0.5, 2000.0, 0.0, 770.6054, 770.605 + 0.5, 2000.0, 0.05, 734.025, 902.781 + 0.5, 2000.0, 0.07, 1028.072, 1031.28 + 0.5, 2000.0, 0.09, 1322.096, 1158.79 + 0.5, 2000.0, 0.11, 1616.099, 1285.39 + 0.5, 2000.0, 0.13, 1910.083, 1411.12 + 0.5, 2000.0, 0.15, 2204.05, 1536.07 + 0.5, 2000.0, 0.17, 2498.001, 1660.29 + 0.5, 2000.0, 0.19, 2791.937, 1783.85 + 0.5, 2000.0, 0.21, 3085.86, 1906.81 + 0.5, 2000.0, 0.23, 3379.772, 2029.24 + 0.5, 2000.0, 0.25, 3673.675, 2151.21 + 0.5, 2000.0, 0.27, 3967.57, 2272.77 + 0.5, 2000.0, 0.29, 4261.458, 2393.99 + 0.5, 2000.0, 0.31, 4555.341, 2514.95 + 0.5, 2000.0, 0.33, 4849.221, 2635.69 + 0.5, 2000.0, 0.35, 5143.1, 2756.29 + 0.5, 2000.0, 0.37, 5436.979, 2876.82 + 0.5, 2000.0, 0.39, 5730.859, 2997.33 + 0.5, 2000.0, 0.41, 6024.749, 3117.87 + 0.5, 2000.0, 0.43, 6318.649, 3238.52 + 0.5, 2000.0, 0.45, 6612.55, 3359.36 + 0.5, 2000.0, 0.47, 6906.451, 3480.47 + 0.5, 2000.0, 0.49, 7200.351, 3601.92 + 0.5, 2000.0, 0.51, 7494.243, 3723.91 + 0.5, 2000.0, 0.53, 7788.126, 3846.48 + 0.5, 2000.0, 0.55, 8082.006, 3969.53 + 0.5, 2000.0, 0.57, 8375.885, 4093.06 + 0.5, 2000.0, 0.59, 8669.762, 4217.09 + 0.5, 2000.0, 0.61, 8963.632, 4341.81 + 0.5, 2000.0, 0.63, 9257.497, 4467.18 + 0.5, 2000.0, 0.65, 9551.369, 4592.98 + 0.5, 2000.0, 0.67, 9845.25, 4719.14 + 0.5, 2000.0, 0.69, 10139.15, 4845.59 + 0.5, 2000.0, 0.71, 10433.08, 4971.82 + 0.5, 2000.0, 0.73, 10727.06, 5097.89 + 0.5, 2000.0, 0.75, 11021.05, 5224.36 + 0.5, 2000.0, 0.77, 11315.04, 5351.39 + 0.5, 2000.0, 0.79, 11609.02, 5479.13 + 0.5, 2000.0, 0.81, 11902.96, 5607.89 + 0.5, 2000.0, 0.83, 12196.86, 5737.78 + 0.5, 2000.0, 0.85, 12490.74, 5868.68 + 0.5, 2000.0, 0.87, 12784.61, 6000.64 + 0.5, 2000.0, 0.89, 13078.47, 6133.72 + 0.5, 2000.0, 0.91, 13372.32, 6267.98 + 0.5, 2000.0, 0.93, 13666.17, 6403.48 + 0.5, 2000.0, 0.95, 13960.01, 6540.28 + 0.5, 2000.0, 0.97, 14253.84, 6678.42 + 0.5, 2000.0, 0.99, 14547.68, 6817.98 + 0.5, 5000.0, 0.0, 696.9329, 696.933 + 0.5, 5000.0, 0.05, 696.1938, 826.988 + 0.5, 5000.0, 0.07, 973.2597, 945.872 + 0.5, 5000.0, 0.09, 1250.402, 1063.89 + 0.5, 5000.0, 0.11, 1527.615, 1181.11 + 0.5, 5000.0, 0.13, 1804.893, 1297.59 + 0.5, 5000.0, 0.15, 2082.231, 1413.39 + 0.5, 5000.0, 0.17, 2359.623, 1528.56 + 0.5, 5000.0, 0.19, 2637.063, 1643.18 + 0.5, 5000.0, 0.21, 2914.547, 1757.3 + 0.5, 5000.0, 0.23, 3192.067, 1870.98 + 0.5, 5000.0, 0.25, 3469.619, 1984.29 + 0.5, 5000.0, 0.27, 3747.197, 2097.28 + 0.5, 5000.0, 0.29, 4024.795, 2210.01 + 0.5, 5000.0, 0.31, 4302.408, 2322.55 + 0.5, 5000.0, 0.33, 4580.03, 2434.95 + 0.5, 5000.0, 0.35, 4857.656, 2547.29 + 0.5, 5000.0, 0.37, 5135.28, 2659.61 + 0.5, 5000.0, 0.39, 5412.896, 2771.98 + 0.5, 5000.0, 0.41, 5690.48, 2884.42 + 0.5, 5000.0, 0.43, 5968.029, 2997.02 + 0.5, 5000.0, 0.45, 6245.569, 3109.86 + 0.5, 5000.0, 0.47, 6523.102, 3223.04 + 0.5, 5000.0, 0.49, 6800.634, 3336.63 + 0.5, 5000.0, 0.51, 7078.161, 3450.91 + 0.5, 5000.0, 0.53, 7355.689, 3565.91 + 0.5, 5000.0, 0.55, 7633.231, 3681.4 + 0.5, 5000.0, 0.57, 7910.796, 3797.35 + 0.5, 5000.0, 0.59, 8188.39, 3913.75 + 0.5, 5000.0, 0.61, 8466.075, 4030.54 + 0.5, 5000.0, 0.63, 8743.844, 4147.71 + 0.5, 5000.0, 0.65, 9021.625, 4265.26 + 0.5, 5000.0, 0.67, 9299.398, 4383.18 + 0.5, 5000.0, 0.69, 9577.143, 4501.44 + 0.5, 5000.0, 0.71, 9854.777, 4619.67 + 0.5, 5000.0, 0.73, 10132.29, 4737.94 + 0.5, 5000.0, 0.75, 10409.78, 4856.77 + 0.5, 5000.0, 0.77, 10687.23, 4976.33 + 0.5, 5000.0, 0.79, 10964.68, 5096.79 + 0.5, 5000.0, 0.81, 11242.15, 5218.59 + 0.5, 5000.0, 0.83, 11519.66, 5341.83 + 0.5, 5000.0, 0.85, 11797.17, 5466.24 + 0.5, 5000.0, 0.87, 12074.7, 5591.83 + 0.5, 5000.0, 0.89, 12352.23, 5718.64 + 0.5, 5000.0, 0.91, 12629.77, 5846.67 + 0.5, 5000.0, 0.93, 12907.32, 5975.96 + 0.5, 5000.0, 0.95, 13184.87, 6106.51 + 0.5, 5000.0, 0.97, 13462.44, 6238.36 + 0.5, 5000.0, 0.99, 13740.01, 6371.52 + 0.5, 10000.0, 0.0, 586.6436, 586.644 + 0.5, 10000.0, 0.05, 625.0438, 709.781 + 0.5, 10000.0, 0.07, 874.4829, 813.311 + 0.5, 10000.0, 0.09, 1123.954, 916.135 + 0.5, 10000.0, 0.11, 1373.453, 1018.31 + 0.5, 10000.0, 0.13, 1622.98, 1119.89 + 0.5, 10000.0, 0.15, 1872.531, 1220.94 + 0.5, 10000.0, 0.17, 2122.104, 1321.52 + 0.5, 10000.0, 0.19, 2371.697, 1421.67 + 0.5, 10000.0, 0.21, 2621.307, 1521.45 + 0.5, 10000.0, 0.23, 2870.932, 1620.93 + 0.5, 10000.0, 0.25, 3120.569, 1720.16 + 0.5, 10000.0, 0.27, 3370.216, 1819.19 + 0.5, 10000.0, 0.29, 3619.871, 1918.09 + 0.5, 10000.0, 0.31, 3869.53, 2016.9 + 0.5, 10000.0, 0.33, 4119.193, 2115.69 + 0.5, 10000.0, 0.35, 4368.856, 2214.52 + 0.5, 10000.0, 0.37, 4618.517, 2313.43 + 0.5, 10000.0, 0.39, 4868.174, 2412.5 + 0.5, 10000.0, 0.41, 5117.816, 2511.77 + 0.5, 10000.0, 0.43, 5367.442, 2611.3 + 0.5, 10000.0, 0.45, 5617.063, 2711.14 + 0.5, 10000.0, 0.47, 5866.679, 2811.36 + 0.5, 10000.0, 0.49, 6116.293, 2912.0 + 0.5, 10000.0, 0.51, 6365.905, 3013.36 + 0.5, 10000.0, 0.53, 6615.516, 3115.44 + 0.5, 10000.0, 0.55, 6865.131, 3217.94 + 0.5, 10000.0, 0.57, 7114.752, 3320.79 + 0.5, 10000.0, 0.59, 7364.381, 3423.94 + 0.5, 10000.0, 0.61, 7614.03, 3526.92 + 0.5, 10000.0, 0.63, 7863.698, 3629.77 + 0.5, 10000.0, 0.65, 8113.375, 3733.03 + 0.5, 10000.0, 0.67, 8363.06, 3836.82 + 0.5, 10000.0, 0.69, 8612.752, 3941.28 + 0.5, 10000.0, 0.71, 8862.444, 4046.69 + 0.5, 10000.0, 0.73, 9112.135, 4153.16 + 0.5, 10000.0, 0.75, 9361.831, 4260.58 + 0.5, 10000.0, 0.77, 9611.534, 4369.02 + 0.5, 10000.0, 0.79, 9861.243, 4478.53 + 0.5, 10000.0, 0.81, 10110.98, 4589.26 + 0.5, 10000.0, 0.83, 10360.75, 4701.27 + 0.5, 10000.0, 0.85, 10610.51, 4814.44 + 0.5, 10000.0, 0.87, 10860.25, 4928.81 + 0.5, 10000.0, 0.89, 11109.96, 5044.37 + 0.5, 10000.0, 0.91, 11359.63, 5161.14 + 0.5, 10000.0, 0.93, 11609.24, 5279.12 + 0.5, 10000.0, 0.95, 11858.79, 5398.33 + 0.5, 10000.0, 0.97, 12108.26, 5518.78 + 0.5, 10000.0, 0.99, 12357.64, 5640.48 + 0.5, 15000.0, 0.0, 490.6577, 490.658 + 0.5, 15000.0, 0.05, 556.2, 563.4 + 0.5, 15000.0, 0.07, 778.7382, 655.838 + 0.5, 15000.0, 0.09, 1001.264, 746.691 + 0.5, 15000.0, 0.11, 1223.779, 836.096 + 0.5, 15000.0, 0.13, 1446.285, 924.191 + 0.5, 15000.0, 0.15, 1668.782, 1011.11 + 0.5, 15000.0, 0.17, 1891.273, 1097.0 + 0.5, 15000.0, 0.19, 2113.759, 1182.0 + 0.5, 15000.0, 0.21, 2336.241, 1266.23 + 0.5, 15000.0, 0.23, 2558.72, 1349.85 + 0.5, 15000.0, 0.25, 2781.199, 1432.98 + 0.5, 15000.0, 0.27, 3003.678, 1515.76 + 0.5, 15000.0, 0.29, 3226.158, 1598.34 + 0.5, 15000.0, 0.31, 3448.649, 1681.0 + 0.5, 15000.0, 0.33, 3671.149, 1763.84 + 0.5, 15000.0, 0.35, 3893.65, 1846.77 + 0.5, 15000.0, 0.37, 4116.151, 1929.88 + 0.5, 15000.0, 0.39, 4338.651, 2013.22 + 0.5, 15000.0, 0.41, 4561.14, 2097.0 + 0.5, 15000.0, 0.43, 4783.617, 2181.24 + 0.5, 15000.0, 0.45, 5006.094, 2265.83 + 0.5, 15000.0, 0.47, 5228.573, 2350.75 + 0.5, 15000.0, 0.49, 5451.056, 2436.03 + 0.5, 15000.0, 0.51, 5673.544, 2521.65 + 0.5, 15000.0, 0.53, 5896.041, 2607.62 + 0.5, 15000.0, 0.55, 6118.55, 2693.95 + 0.5, 15000.0, 0.57, 6341.075, 2780.65 + 0.5, 15000.0, 0.59, 6563.62, 2867.72 + 0.5, 15000.0, 0.61, 6786.226, 2954.93 + 0.5, 15000.0, 0.63, 7008.888, 3042.35 + 0.5, 15000.0, 0.65, 7231.55, 3130.34 + 0.5, 15000.0, 0.67, 7454.196, 3219.02 + 0.5, 15000.0, 0.69, 7676.81, 3308.51 + 0.5, 15000.0, 0.71, 7899.31, 3399.17 + 0.5, 15000.0, 0.73, 8121.696, 3491.08 + 0.5, 15000.0, 0.75, 8344.05, 3583.99 + 0.5, 15000.0, 0.77, 8566.388, 3677.94 + 0.5, 15000.0, 0.79, 8788.726, 3772.92 + 0.5, 15000.0, 0.81, 9011.121, 3868.88 + 0.5, 15000.0, 0.83, 9233.58, 3965.86 + 0.5, 15000.0, 0.85, 9456.056, 4063.95 + 0.5, 15000.0, 0.87, 9678.547, 4163.19 + 0.5, 15000.0, 0.89, 9901.047, 4263.62 + 0.5, 15000.0, 0.91, 10123.55, 4365.29 + 0.5, 15000.0, 0.93, 10346.06, 4468.23 + 0.5, 15000.0, 0.95, 10568.57, 4572.47 + 0.5, 15000.0, 0.97, 10791.07, 4678.08 + 0.5, 15000.0, 0.99, 11013.56, 4785.07 + 0.5, 20000.0, 0.0, 407.5634, 407.563 + 0.5, 20000.0, 0.05, 462.8, 469.8 + 0.5, 20000.0, 0.07, 647.9534, 544.262 + 0.5, 20000.0, 0.09, 833.0986, 617.504 + 0.5, 20000.0, 0.11, 1018.237, 689.631 + 0.5, 20000.0, 0.13, 1203.369, 760.753 + 0.5, 20000.0, 0.15, 1388.496, 830.975 + 0.5, 20000.0, 0.17, 1573.62, 900.405 + 0.5, 20000.0, 0.19, 1758.74, 969.151 + 0.5, 20000.0, 0.21, 1943.859, 1037.32 + 0.5, 20000.0, 0.23, 2128.977, 1105.02 + 0.5, 20000.0, 0.25, 2314.096, 1172.35 + 0.5, 20000.0, 0.27, 2499.215, 1239.43 + 0.5, 20000.0, 0.29, 2684.338, 1306.36 + 0.5, 20000.0, 0.31, 2869.469, 1373.35 + 0.5, 20000.0, 0.33, 3054.609, 1440.48 + 0.5, 20000.0, 0.35, 3239.75, 1507.71 + 0.5, 20000.0, 0.37, 3424.891, 1575.09 + 0.5, 20000.0, 0.39, 3610.031, 1642.7 + 0.5, 20000.0, 0.41, 3795.161, 1710.73 + 0.5, 20000.0, 0.43, 3980.281, 1779.2 + 0.5, 20000.0, 0.45, 4165.4, 1847.96 + 0.5, 20000.0, 0.47, 4350.519, 1916.98 + 0.5, 20000.0, 0.49, 4535.639, 1986.27 + 0.5, 20000.0, 0.51, 4720.767, 2055.7 + 0.5, 20000.0, 0.53, 4905.904, 2125.29 + 0.5, 20000.0, 0.55, 5091.044, 2195.17 + 0.5, 20000.0, 0.57, 5276.185, 2265.36 + 0.5, 20000.0, 0.59, 5461.328, 2335.89 + 0.5, 20000.0, 0.61, 5646.472, 2406.68 + 0.5, 20000.0, 0.63, 5831.615, 2477.77 + 0.5, 20000.0, 0.65, 6016.756, 2549.4 + 0.5, 20000.0, 0.67, 6201.896, 2621.65 + 0.5, 20000.0, 0.69, 6387.033, 2694.62 + 0.5, 20000.0, 0.71, 6572.16, 2768.57 + 0.5, 20000.0, 0.73, 6757.277, 2843.56 + 0.5, 20000.0, 0.75, 6942.394, 2919.42 + 0.5, 20000.0, 0.77, 7127.513, 2996.15 + 0.5, 20000.0, 0.79, 7312.636, 3073.76 + 0.5, 20000.0, 0.81, 7497.779, 3152.26 + 0.5, 20000.0, 0.83, 7682.942, 3231.65 + 0.5, 20000.0, 0.85, 7868.106, 3311.95 + 0.5, 20000.0, 0.87, 8053.269, 3393.16 + 0.5, 20000.0, 0.89, 8238.425, 3475.29 + 0.5, 20000.0, 0.91, 8423.572, 3558.34 + 0.5, 20000.0, 0.93, 8608.704, 3642.34 + 0.5, 20000.0, 0.95, 8793.819, 3727.27 + 0.5, 20000.0, 0.97, 8978.911, 3813.16 + 0.5, 20000.0, 0.99, 9163.978, 3900.01 + 0.5, 25000.0, 0.0, 336.0318, 336.032 + 0.5, 25000.0, 0.05, 383.7, 392.8 + 0.5, 25000.0, 0.07, 537.2134, 452.413 + 0.5, 25000.0, 0.09, 690.7186, 511.092 + 0.5, 25000.0, 0.11, 844.2169, 568.923 + 0.5, 25000.0, 0.13, 997.7091, 625.988 + 0.5, 25000.0, 0.15, 1151.196, 682.371 + 0.5, 25000.0, 0.17, 1304.68, 738.158 + 0.5, 25000.0, 0.19, 1458.16, 793.43 + 0.5, 25000.0, 0.21, 1611.639, 848.273 + 0.5, 25000.0, 0.23, 1765.117, 902.77 + 0.5, 25000.0, 0.25, 1918.596, 957.006 + 0.5, 25000.0, 0.27, 2072.075, 1011.06 + 0.5, 25000.0, 0.29, 2225.558, 1065.03 + 0.5, 25000.0, 0.31, 2379.047, 1119.06 + 0.5, 25000.0, 0.33, 2532.544, 1173.22 + 0.5, 25000.0, 0.35, 2686.044, 1227.49 + 0.5, 25000.0, 0.37, 2839.545, 1281.9 + 0.5, 25000.0, 0.39, 2993.048, 1336.51 + 0.5, 25000.0, 0.41, 3146.552, 1391.5 + 0.5, 25000.0, 0.43, 3300.055, 1446.88 + 0.5, 25000.0, 0.45, 3453.556, 1502.49 + 0.5, 25000.0, 0.47, 3607.056, 1558.31 + 0.5, 25000.0, 0.49, 3760.553, 1614.33 + 0.5, 25000.0, 0.51, 3914.038, 1670.37 + 0.5, 25000.0, 0.53, 4067.512, 1726.46 + 0.5, 25000.0, 0.55, 4220.988, 1782.78 + 0.5, 25000.0, 0.57, 4374.467, 1839.38 + 0.5, 25000.0, 0.59, 4527.953, 1896.3 + 0.5, 25000.0, 0.61, 4681.465, 1953.56 + 0.5, 25000.0, 0.63, 4835.001, 2011.2 + 0.5, 25000.0, 0.65, 4988.544, 2069.34 + 0.5, 25000.0, 0.67, 5142.088, 2128.05 + 0.5, 25000.0, 0.69, 5295.631, 2187.38 + 0.5, 25000.0, 0.71, 5449.159, 2247.53 + 0.5, 25000.0, 0.73, 5602.671, 2308.54 + 0.5, 25000.0, 0.75, 5756.175, 2370.28 + 0.5, 25000.0, 0.77, 5909.671, 2432.77 + 0.5, 25000.0, 0.79, 6063.159, 2496.0 + 0.5, 25000.0, 0.81, 6216.636, 2560.02 + 0.5, 25000.0, 0.83, 6370.102, 2624.83 + 0.5, 25000.0, 0.85, 6523.562, 2690.38 + 0.5, 25000.0, 0.87, 6677.019, 2756.65 + 0.5, 25000.0, 0.89, 6830.473, 2823.64 + 0.5, 25000.0, 0.91, 6983.927, 2891.34 + 0.5, 25000.0, 0.93, 7137.381, 2959.73 + 0.5, 25000.0, 0.95, 7290.837, 3028.8 + 0.5, 25000.0, 0.97, 7444.298, 3098.55 + 0.5, 25000.0, 0.99, 7597.764, 3168.95 + 0.5, 30000.0, 0.0, 274.8295, 274.83 + 0.5, 30000.0, 0.05, 318.2, 330.4 + 0.5, 30000.0, 0.07, 445.5124, 377.857 + 0.5, 30000.0, 0.09, 572.8227, 424.641 + 0.5, 30000.0, 0.11, 700.1311, 470.814 + 0.5, 30000.0, 0.13, 827.4378, 516.438 + 0.5, 30000.0, 0.15, 954.7429, 561.575 + 0.5, 30000.0, 0.17, 1082.047, 606.288 + 0.5, 30000.0, 0.19, 1209.349, 650.64 + 0.5, 30000.0, 0.21, 1336.651, 694.693 + 0.5, 30000.0, 0.23, 1463.951, 738.509 + 0.5, 30000.0, 0.25, 1591.251, 782.15 + 0.5, 30000.0, 0.27, 1718.551, 825.679 + 0.5, 30000.0, 0.29, 1845.85, 869.159 + 0.5, 30000.0, 0.31, 1973.15, 912.708 + 0.5, 30000.0, 0.33, 2100.45, 956.374 + 0.5, 30000.0, 0.35, 2227.75, 1000.14 + 0.5, 30000.0, 0.37, 2355.05, 1044.03 + 0.5, 30000.0, 0.39, 2482.35, 1088.1 + 0.5, 30000.0, 0.41, 2609.652, 1132.47 + 0.5, 30000.0, 0.43, 2736.955, 1177.17 + 0.5, 30000.0, 0.45, 2864.256, 1222.06 + 0.5, 30000.0, 0.47, 2991.556, 1267.12 + 0.5, 30000.0, 0.49, 3118.853, 1312.34 + 0.5, 30000.0, 0.51, 3246.135, 1357.55 + 0.5, 30000.0, 0.53, 3373.403, 1402.76 + 0.5, 30000.0, 0.55, 3500.675, 1448.19 + 0.5, 30000.0, 0.57, 3627.955, 1493.87 + 0.5, 30000.0, 0.59, 3755.247, 1539.87 + 0.5, 30000.0, 0.61, 3882.586, 1586.25 + 0.5, 30000.0, 0.63, 4009.968, 1633.06 + 0.5, 30000.0, 0.65, 4137.356, 1680.32 + 0.5, 30000.0, 0.67, 4264.743, 1728.1 + 0.5, 30000.0, 0.69, 4392.119, 1776.42 + 0.5, 30000.0, 0.71, 4519.444, 1825.4 + 0.5, 30000.0, 0.73, 4646.717, 1875.06 + 0.5, 30000.0, 0.75, 4773.975, 1925.36 + 0.5, 30000.0, 0.77, 4901.225, 1976.32 + 0.5, 30000.0, 0.79, 5028.474, 2027.94 + 0.5, 30000.0, 0.81, 5155.744, 2080.36 + 0.5, 30000.0, 0.83, 5283.038, 2133.58 + 0.5, 30000.0, 0.85, 5410.337, 2187.41 + 0.5, 30000.0, 0.87, 5537.641, 2241.82 + 0.5, 30000.0, 0.89, 5664.947, 2296.75 + 0.5, 30000.0, 0.91, 5792.253, 2352.16 + 0.5, 30000.0, 0.93, 5919.559, 2408.01 + 0.5, 30000.0, 0.95, 6046.862, 2464.24 + 0.5, 30000.0, 0.97, 6174.162, 2520.81 + 0.5, 30000.0, 0.99, 6301.456, 2577.67 + 0.5, 35000.0, 0.0, 222.8105, 222.81 + 0.5, 35000.0, 0.05, 264.5, 283.4 + 0.5, 35000.0, 0.07, 370.4546, 320.177 + 0.5, 35000.0, 0.09, 476.4833, 356.693 + 0.5, 35000.0, 0.11, 582.5779, 392.972 + 0.5, 35000.0, 0.13, 688.7302, 429.04 + 0.5, 35000.0, 0.15, 794.9321, 464.925 + 0.5, 35000.0, 0.17, 901.1754, 500.651 + 0.5, 35000.0, 0.19, 1007.452, 536.245 + 0.5, 35000.0, 0.21, 1113.753, 571.732 + 0.5, 35000.0, 0.23, 1220.072, 607.138 + 0.5, 35000.0, 0.25, 1326.399, 642.49 + 0.5, 35000.0, 0.27, 1432.726, 677.813 + 0.5, 35000.0, 0.29, 1539.046, 713.133 + 0.5, 35000.0, 0.31, 1645.333, 748.515 + 0.5, 35000.0, 0.33, 1751.583, 783.975 + 0.5, 35000.0, 0.35, 1857.813, 819.481 + 0.5, 35000.0, 0.37, 1964.023, 855.042 + 0.5, 35000.0, 0.39, 2070.213, 890.664 + 0.5, 35000.0, 0.41, 2176.391, 926.252 + 0.5, 35000.0, 0.43, 2282.555, 961.838 + 0.5, 35000.0, 0.45, 2388.694, 997.581 + 0.5, 35000.0, 0.47, 2494.802, 1033.54 + 0.5, 35000.0, 0.49, 2600.877, 1069.77 + 0.5, 35000.0, 0.51, 2706.857, 1106.47 + 0.5, 35000.0, 0.53, 2812.753, 1143.68 + 0.5, 35000.0, 0.55, 2918.644, 1181.22 + 0.5, 35000.0, 0.57, 3024.552, 1219.07 + 0.5, 35000.0, 0.59, 3130.502, 1257.22 + 0.5, 35000.0, 0.61, 3236.634, 1295.56 + 0.5, 35000.0, 0.63, 3342.942, 1334.11 + 0.5, 35000.0, 0.65, 3449.275, 1372.96 + 0.5, 35000.0, 0.67, 3555.6, 1412.15 + 0.5, 35000.0, 0.69, 3661.884, 1451.69 + 0.5, 35000.0, 0.71, 3767.948, 1491.5 + 0.5, 35000.0, 0.73, 3873.792, 1531.64 + 0.5, 35000.0, 0.75, 3979.6, 1572.28 + 0.5, 35000.0, 0.77, 4085.408, 1613.51 + 0.5, 35000.0, 0.79, 4191.252, 1655.39 + 0.5, 35000.0, 0.81, 4297.299, 1698.33 + 0.5, 35000.0, 0.83, 4403.554, 1742.34 + 0.5, 35000.0, 0.85, 4509.862, 1786.99 + 0.5, 35000.0, 0.87, 4616.199, 1832.21 + 0.5, 35000.0, 0.89, 4722.538, 1877.9 + 0.5, 35000.0, 0.91, 4828.853, 1923.99 + 0.5, 35000.0, 0.93, 4935.12, 1970.38 + 0.5, 35000.0, 0.95, 5041.312, 2017.01 + 0.5, 35000.0, 0.97, 5147.405, 2063.77 + 0.5, 35000.0, 0.99, 5253.372, 2110.59 + 0.5, 40000.0, 0.0, 176.3328, 176.333 + 0.5, 40000.0, 0.05, 209.9, 244.7 + 0.5, 40000.0, 0.07, 293.5437, 273.164 + 0.5, 40000.0, 0.09, 377.1972, 301.341 + 0.5, 40000.0, 0.11, 460.8635, 329.27 + 0.5, 40000.0, 0.13, 544.5456, 356.989 + 0.5, 40000.0, 0.15, 628.2464, 384.536 + 0.5, 40000.0, 0.17, 711.969, 411.949 + 0.5, 40000.0, 0.19, 795.7162, 439.266 + 0.5, 40000.0, 0.21, 879.4911, 466.525 + 0.5, 40000.0, 0.23, 963.2966, 493.765 + 0.5, 40000.0, 0.25, 1047.136, 521.023 + 0.5, 40000.0, 0.27, 1131.011, 548.338 + 0.5, 40000.0, 0.29, 1214.927, 575.748 + 0.5, 40000.0, 0.31, 1298.935, 603.425 + 0.5, 40000.0, 0.33, 1383.027, 631.376 + 0.5, 40000.0, 0.35, 1467.131, 659.437 + 0.5, 40000.0, 0.37, 1551.225, 687.583 + 0.5, 40000.0, 0.39, 1635.287, 715.786 + 0.5, 40000.0, 0.41, 1719.226, 743.883 + 0.5, 40000.0, 0.43, 1803.035, 771.88 + 0.5, 40000.0, 0.45, 1886.8, 799.95 + 0.5, 40000.0, 0.47, 1970.533, 828.132 + 0.5, 40000.0, 0.49, 2054.246, 856.465 + 0.5, 40000.0, 0.51, 2137.947, 885.104 + 0.5, 40000.0, 0.53, 2221.649, 914.059 + 0.5, 40000.0, 0.55, 2305.375, 943.194 + 0.5, 40000.0, 0.57, 2389.141, 972.491 + 0.5, 40000.0, 0.59, 2472.963, 1001.93 + 0.5, 40000.0, 0.61, 2556.946, 1031.33 + 0.5, 40000.0, 0.63, 2641.085, 1060.71 + 0.5, 40000.0, 0.65, 2725.262, 1090.29 + 0.5, 40000.0, 0.67, 2809.452, 1120.16 + 0.5, 40000.0, 0.69, 2893.627, 1150.35 + 0.5, 40000.0, 0.71, 2977.698, 1180.95 + 0.5, 40000.0, 0.73, 3061.653, 1212.0 + 0.5, 40000.0, 0.75, 3145.556, 1243.58 + 0.5, 40000.0, 0.77, 3229.409, 1275.76 + 0.5, 40000.0, 0.79, 3313.214, 1308.61 + 0.5, 40000.0, 0.81, 3396.928, 1342.6 + 0.5, 40000.0, 0.83, 3480.564, 1377.72 + 0.5, 40000.0, 0.85, 3564.194, 1413.39 + 0.5, 40000.0, 0.87, 3647.841, 1449.48 + 0.5, 40000.0, 0.89, 3731.531, 1485.85 + 0.5, 40000.0, 0.91, 3815.289, 1522.37 + 0.5, 40000.0, 0.93, 3899.139, 1558.89 + 0.5, 40000.0, 0.95, 3983.106, 1595.29 + 0.5, 40000.0, 0.97, 4067.216, 1631.41 + 0.5, 40000.0, 0.99, 4151.492, 1667.13 + 0.5, 43000.0, 0.0, 152.7425, 152.742 + 0.5, 43000.0, 0.05, 177.3, 231.7 + 0.5, 43000.0, 0.07, 253.3249, 256.708 + 0.5, 43000.0, 0.09, 328.3134, 281.374 + 0.5, 43000.0, 0.11, 402.3968, 305.72 + 0.5, 43000.0, 0.13, 475.7069, 329.768 + 0.5, 43000.0, 0.15, 548.375, 353.539 + 0.5, 43000.0, 0.17, 620.5327, 377.056 + 0.5, 43000.0, 0.19, 692.3116, 400.339 + 0.5, 43000.0, 0.21, 763.843, 423.411 + 0.5, 43000.0, 0.23, 835.2587, 446.293 + 0.5, 43000.0, 0.25, 906.69, 469.007 + 0.5, 43000.0, 0.27, 978.2685, 491.575 + 0.5, 43000.0, 0.29, 1050.126, 514.018 + 0.5, 43000.0, 0.31, 1123.057, 535.907 + 0.5, 43000.0, 0.33, 1197.033, 557.372 + 0.5, 43000.0, 0.35, 1271.2, 579.106 + 0.5, 43000.0, 0.37, 1345.367, 601.351 + 0.5, 43000.0, 0.39, 1419.343, 624.346 + 0.5, 43000.0, 0.41, 1492.234, 649.925 + 0.5, 43000.0, 0.43, 1564.02, 677.942 + 0.5, 43000.0, 0.45, 1635.556, 706.275 + 0.5, 43000.0, 0.47, 1706.995, 734.392 + 0.5, 43000.0, 0.49, 1778.487, 761.761 + 0.5, 43000.0, 0.51, 1850.678, 785.577 + 0.5, 43000.0, 0.53, 1923.6, 805.86 + 0.5, 43000.0, 0.55, 1996.669, 825.456 + 0.5, 43000.0, 0.57, 2069.795, 844.939 + 0.5, 43000.0, 0.59, 2142.891, 864.879 + 0.5, 43000.0, 0.61, 2215.549, 887.251 + 0.5, 43000.0, 0.63, 2287.757, 912.285 + 0.5, 43000.0, 0.65, 2359.9, 938.475 + 0.5, 43000.0, 0.67, 2432.043, 965.713 + 0.5, 43000.0, 0.69, 2504.251, 993.891 + 0.5, 43000.0, 0.71, 2576.909, 1023.21 + 0.5, 43000.0, 0.73, 2650.005, 1053.5 + 0.5, 43000.0, 0.75, 2723.131, 1084.18 + 0.5, 43000.0, 0.77, 2796.2, 1114.99 + 0.5, 43000.0, 0.79, 2869.122, 1145.68 + 0.5, 43000.0, 0.81, 2941.429, 1174.9 + 0.5, 43000.0, 0.83, 3013.124, 1202.65 + 0.5, 43000.0, 0.85, 3084.681, 1230.31 + 0.5, 43000.0, 0.87, 3156.197, 1258.13 + 0.5, 43000.0, 0.89, 3227.766, 1286.41 + 0.5, 43000.0, 0.91, 3299.483, 1315.4 + 0.5, 43000.0, 0.93, 3371.444, 1345.39 + 0.5, 43000.0, 0.95, 3443.744, 1376.64 + 0.5, 43000.0, 0.97, 3516.477, 1409.43 + 0.5, 43000.0, 0.99, 3589.74, 1444.04 + 0.5, 48000.0, 0.0, 120.2392, 120.239 + 0.5, 48000.0, 0.05, 142.0, 187.2 + 0.5, 48000.0, 0.07, 201.5801, 206.428 + 0.5, 48000.0, 0.09, 260.4714, 225.335 + 0.5, 48000.0, 0.11, 318.7509, 243.951 + 0.5, 48000.0, 0.13, 376.4955, 262.31 + 0.5, 48000.0, 0.15, 433.7821, 280.443 + 0.5, 48000.0, 0.17, 490.6877, 298.383 + 0.5, 48000.0, 0.19, 547.2892, 316.161 + 0.5, 48000.0, 0.21, 603.6636, 333.811 + 0.5, 48000.0, 0.23, 659.8877, 351.363 + 0.5, 48000.0, 0.25, 716.0386, 368.851 + 0.5, 48000.0, 0.27, 772.1931, 386.307 + 0.5, 48000.0, 0.29, 828.4282, 403.762 + 0.5, 48000.0, 0.31, 885.0026, 421.035 + 0.5, 48000.0, 0.33, 941.9492, 438.21 + 0.5, 48000.0, 0.35, 999.075, 455.637 + 0.5, 48000.0, 0.37, 1056.369, 473.452 + 0.5, 48000.0, 0.39, 1113.819, 491.791 + 0.5, 48000.0, 0.41, 1171.473, 511.83 + 0.5, 48000.0, 0.43, 1229.305, 533.452 + 0.5, 48000.0, 0.45, 1287.219, 555.25 + 0.5, 48000.0, 0.47, 1345.174, 576.856 + 0.5, 48000.0, 0.49, 1403.132, 597.902 + 0.5, 48000.0, 0.51, 1461.133, 616.297 + 0.5, 48000.0, 0.53, 1519.118, 632.092 + 0.5, 48000.0, 0.55, 1576.931, 647.475 + 0.5, 48000.0, 0.57, 1634.494, 662.914 + 0.5, 48000.0, 0.59, 1691.729, 678.877 + 0.5, 48000.0, 0.61, 1747.895, 697.22 + 0.5, 48000.0, 0.63, 1803.073, 718.075 + 0.5, 48000.0, 0.65, 1858.175, 739.844 + 0.5, 48000.0, 0.67, 1913.445, 762.318 + 0.5, 48000.0, 0.69, 1969.127, 785.291 + 0.5, 48000.0, 0.71, 2026.606, 808.229 + 0.5, 48000.0, 0.73, 2085.85, 831.004 + 0.5, 48000.0, 0.75, 2145.412, 853.894 + 0.5, 48000.0, 0.77, 2204.987, 876.849 + 0.5, 48000.0, 0.79, 2264.267, 899.822 + 0.5, 48000.0, 0.81, 2321.976, 922.328 + 0.5, 48000.0, 0.83, 2378.041, 944.423 + 0.5, 48000.0, 0.85, 2433.594, 966.706 + 0.5, 48000.0, 0.87, 2488.797, 989.339 + 0.5, 48000.0, 0.89, 2543.812, 1012.48 + 0.5, 48000.0, 0.91, 2598.802, 1036.3 + 0.5, 48000.0, 0.93, 2653.929, 1060.96 + 0.5, 48000.0, 0.95, 2709.356, 1086.62 + 0.5, 48000.0, 0.97, 2765.245, 1113.44 + 0.5, 48000.0, 0.99, 2821.758, 1141.58 + 0.55, 0.0, 0.0, 847.9933, 847.993 + 0.55, 0.0, 0.05, 728.4641, 1026.61 + 0.55, 0.0, 0.07, 1021.977, 1163.05 + 0.55, 0.0, 0.09, 1315.371, 1298.62 + 0.55, 0.0, 0.11, 1608.653, 1433.38 + 0.55, 0.0, 0.13, 1901.832, 1567.37 + 0.55, 0.0, 0.15, 2194.917, 1700.63 + 0.55, 0.0, 0.17, 2487.917, 1833.2 + 0.55, 0.0, 0.19, 2780.84, 1965.15 + 0.55, 0.0, 0.21, 3073.694, 2096.51 + 0.55, 0.0, 0.23, 3366.489, 2227.32 + 0.55, 0.0, 0.25, 3659.233, 2357.64 + 0.55, 0.0, 0.27, 3951.934, 2487.51 + 0.55, 0.0, 0.29, 4244.601, 2616.98 + 0.55, 0.0, 0.31, 4537.243, 2746.09 + 0.55, 0.0, 0.33, 4829.869, 2874.88 + 0.55, 0.0, 0.35, 5122.486, 3003.41 + 0.55, 0.0, 0.37, 5415.104, 3131.72 + 0.55, 0.0, 0.39, 5707.73, 3259.86 + 0.55, 0.0, 0.41, 6000.4, 3387.77 + 0.55, 0.0, 0.43, 6293.114, 3515.52 + 0.55, 0.0, 0.45, 6585.845, 3643.3 + 0.55, 0.0, 0.47, 6878.59, 3771.22 + 0.55, 0.0, 0.49, 7171.345, 3899.37 + 0.55, 0.0, 0.51, 7464.105, 4028.01 + 0.55, 0.0, 0.53, 7756.868, 4157.22 + 0.55, 0.0, 0.55, 8049.631, 4286.79 + 0.55, 0.0, 0.57, 8342.393, 4416.74 + 0.55, 0.0, 0.59, 8635.149, 4547.07 + 0.55, 0.0, 0.61, 8927.891, 4677.9 + 0.55, 0.0, 0.63, 9220.617, 4809.2 + 0.55, 0.0, 0.65, 9513.334, 4940.81 + 0.55, 0.0, 0.67, 9806.045, 5072.65 + 0.55, 0.0, 0.69, 10098.75, 5204.68 + 0.55, 0.0, 0.71, 10391.45, 5336.55 + 0.55, 0.0, 0.73, 10684.14, 5468.27 + 0.55, 0.0, 0.75, 10976.83, 5600.22 + 0.55, 0.0, 0.77, 11269.52, 5732.49 + 0.55, 0.0, 0.79, 11562.21, 5865.16 + 0.55, 0.0, 0.81, 11854.89, 5998.26 + 0.55, 0.0, 0.83, 12147.57, 6131.9 + 0.55, 0.0, 0.85, 12440.25, 6266.24 + 0.55, 0.0, 0.87, 12732.94, 6401.41 + 0.55, 0.0, 0.89, 13025.63, 6537.53 + 0.55, 0.0, 0.91, 13318.32, 6674.7 + 0.55, 0.0, 0.93, 13611.02, 6813.06 + 0.55, 0.0, 0.95, 13903.73, 6952.71 + 0.55, 0.0, 0.97, 14196.45, 7093.77 + 0.55, 0.0, 0.99, 14489.18, 7236.37 + 0.55, 2000.0, 0.0, 793.9555, 793.955 + 0.55, 2000.0, 0.05, 705.4875, 958.234 + 0.55, 2000.0, 0.07, 988.4436, 1090.52 + 0.55, 2000.0, 0.09, 1271.344, 1221.66 + 0.55, 2000.0, 0.11, 1554.194, 1351.73 + 0.55, 2000.0, 0.13, 1836.996, 1480.79 + 0.55, 2000.0, 0.15, 2119.756, 1608.92 + 0.55, 2000.0, 0.17, 2402.478, 1736.19 + 0.55, 2000.0, 0.19, 2685.167, 1862.66 + 0.55, 2000.0, 0.21, 2967.826, 1988.42 + 0.55, 2000.0, 0.23, 3250.461, 2113.52 + 0.55, 2000.0, 0.25, 3533.075, 2238.03 + 0.55, 2000.0, 0.27, 3815.673, 2362.04 + 0.55, 2000.0, 0.29, 4098.26, 2485.61 + 0.55, 2000.0, 0.31, 4380.839, 2608.81 + 0.55, 2000.0, 0.33, 4663.416, 2731.7 + 0.55, 2000.0, 0.35, 4945.994, 2854.37 + 0.55, 2000.0, 0.37, 5228.578, 2976.88 + 0.55, 2000.0, 0.39, 5511.172, 3099.3 + 0.55, 2000.0, 0.41, 5793.803, 3221.7 + 0.55, 2000.0, 0.43, 6076.47, 3344.14 + 0.55, 2000.0, 0.45, 6359.144, 3466.7 + 0.55, 2000.0, 0.47, 6641.82, 3589.48 + 0.55, 2000.0, 0.49, 6924.492, 3712.52 + 0.55, 2000.0, 0.51, 7207.136, 3836.12 + 0.55, 2000.0, 0.53, 7489.751, 3960.28 + 0.55, 2000.0, 0.55, 7772.356, 4084.8 + 0.55, 2000.0, 0.57, 8054.956, 4209.66 + 0.55, 2000.0, 0.59, 8337.552, 4334.84 + 0.55, 2000.0, 0.61, 8620.132, 4460.34 + 0.55, 2000.0, 0.63, 8902.701, 4586.13 + 0.55, 2000.0, 0.65, 9185.288, 4712.18 + 0.55, 2000.0, 0.67, 9467.902, 4838.45 + 0.55, 2000.0, 0.69, 9750.555, 4964.94 + 0.55, 2000.0, 0.71, 10033.35, 5091.36 + 0.55, 2000.0, 0.73, 10316.28, 5217.76 + 0.55, 2000.0, 0.75, 10599.21, 5344.47 + 0.55, 2000.0, 0.77, 10882.11, 5471.59 + 0.55, 2000.0, 0.79, 11164.94, 5599.2 + 0.55, 2000.0, 0.81, 11447.52, 5727.29 + 0.55, 2000.0, 0.83, 11729.86, 5855.97 + 0.55, 2000.0, 0.85, 12012.13, 5985.52 + 0.55, 2000.0, 0.87, 12294.4, 6116.09 + 0.55, 2000.0, 0.89, 12576.68, 6247.84 + 0.55, 2000.0, 0.91, 12859.04, 6380.91 + 0.55, 2000.0, 0.93, 13141.5, 6515.46 + 0.55, 2000.0, 0.95, 13424.11, 6651.64 + 0.55, 2000.0, 0.97, 13706.91, 6789.6 + 0.55, 2000.0, 0.99, 13989.94, 6929.5 + 0.55, 5000.0, 0.0, 718.0507, 718.051 + 0.55, 5000.0, 0.05, 677.8234, 871.781 + 0.55, 5000.0, 0.07, 943.4448, 995.84 + 0.55, 5000.0, 0.09, 1209.376, 1118.66 + 0.55, 5000.0, 0.11, 1475.593, 1240.31 + 0.55, 5000.0, 0.13, 1742.074, 1360.9 + 0.55, 5000.0, 0.15, 2008.795, 1480.49 + 0.55, 5000.0, 0.17, 2275.734, 1599.17 + 0.55, 5000.0, 0.19, 2542.868, 1717.03 + 0.55, 5000.0, 0.21, 2810.172, 1834.15 + 0.55, 5000.0, 0.23, 3077.626, 1950.61 + 0.55, 5000.0, 0.25, 3345.205, 2066.49 + 0.55, 5000.0, 0.27, 3612.886, 2181.89 + 0.55, 5000.0, 0.29, 3880.647, 2296.88 + 0.55, 5000.0, 0.31, 4148.464, 2411.55 + 0.55, 5000.0, 0.33, 4416.315, 2525.98 + 0.55, 5000.0, 0.35, 4684.177, 2640.25 + 0.55, 5000.0, 0.37, 4952.025, 2754.45 + 0.55, 5000.0, 0.39, 5219.839, 2868.66 + 0.55, 5000.0, 0.41, 5487.512, 2983.05 + 0.55, 5000.0, 0.43, 5755.043, 3097.69 + 0.55, 5000.0, 0.45, 6022.528, 3212.52 + 0.55, 5000.0, 0.47, 6289.984, 3327.6 + 0.55, 5000.0, 0.49, 6557.428, 3442.97 + 0.55, 5000.0, 0.51, 6824.89, 3558.77 + 0.55, 5000.0, 0.53, 7092.383, 3675.01 + 0.55, 5000.0, 0.55, 7359.902, 3791.61 + 0.55, 5000.0, 0.57, 7627.456, 3908.55 + 0.55, 5000.0, 0.59, 7895.056, 4025.83 + 0.55, 5000.0, 0.61, 8162.766, 4143.47 + 0.55, 5000.0, 0.63, 8430.584, 4261.45 + 0.55, 5000.0, 0.65, 8698.433, 4379.75 + 0.55, 5000.0, 0.67, 8966.295, 4498.36 + 0.55, 5000.0, 0.69, 9234.153, 4617.25 + 0.55, 5000.0, 0.71, 9501.953, 4736.16 + 0.55, 5000.0, 0.73, 9769.686, 4855.15 + 0.55, 5000.0, 0.75, 10037.38, 4974.57 + 0.55, 5000.0, 0.77, 10305.05, 5094.54 + 0.55, 5000.0, 0.79, 10572.68, 5215.18 + 0.55, 5000.0, 0.81, 10840.23, 5336.58 + 0.55, 5000.0, 0.83, 11107.71, 5458.87 + 0.55, 5000.0, 0.85, 11375.19, 5582.15 + 0.55, 5000.0, 0.87, 11642.66, 5706.55 + 0.55, 5000.0, 0.89, 11910.16, 5832.17 + 0.55, 5000.0, 0.91, 12177.7, 5959.13 + 0.55, 5000.0, 0.93, 12445.29, 6087.54 + 0.55, 5000.0, 0.95, 12712.96, 6217.52 + 0.55, 5000.0, 0.97, 12980.71, 6349.17 + 0.55, 5000.0, 0.99, 13248.57, 6482.62 + 0.55, 10000.0, 0.0, 604.4195, 604.419 + 0.55, 10000.0, 0.05, 587.6922, 748.538 + 0.55, 10000.0, 0.07, 826.4269, 853.872 + 0.55, 10000.0, 0.09, 1064.93, 958.411 + 0.55, 10000.0, 0.11, 1303.219, 1062.21 + 0.55, 10000.0, 0.13, 1541.312, 1165.33 + 0.55, 10000.0, 0.15, 1779.227, 1267.82 + 0.55, 10000.0, 0.17, 2016.981, 1369.74 + 0.55, 10000.0, 0.19, 2254.592, 1471.15 + 0.55, 10000.0, 0.21, 2492.079, 1572.1 + 0.55, 10000.0, 0.23, 2729.458, 1672.65 + 0.55, 10000.0, 0.25, 2966.748, 1772.85 + 0.55, 10000.0, 0.27, 3203.967, 1872.77 + 0.55, 10000.0, 0.29, 3441.132, 1972.45 + 0.55, 10000.0, 0.31, 3678.261, 2071.96 + 0.55, 10000.0, 0.33, 3915.372, 2171.35 + 0.55, 10000.0, 0.35, 4152.483, 2270.68 + 0.55, 10000.0, 0.37, 4389.611, 2370.0 + 0.55, 10000.0, 0.39, 4626.774, 2469.38 + 0.55, 10000.0, 0.41, 4864.062, 2568.87 + 0.55, 10000.0, 0.43, 5101.475, 2668.53 + 0.55, 10000.0, 0.45, 5338.925, 2768.4 + 0.55, 10000.0, 0.47, 5576.395, 2868.54 + 0.55, 10000.0, 0.49, 5813.868, 2968.99 + 0.55, 10000.0, 0.51, 6051.301, 3070.07 + 0.55, 10000.0, 0.53, 6288.685, 3171.78 + 0.55, 10000.0, 0.55, 6526.041, 3273.75 + 0.55, 10000.0, 0.57, 6763.363, 3375.93 + 0.55, 10000.0, 0.59, 7000.648, 3478.23 + 0.55, 10000.0, 0.61, 7237.816, 3580.14 + 0.55, 10000.0, 0.63, 7474.88, 3681.68 + 0.55, 10000.0, 0.65, 7711.948, 3783.43 + 0.55, 10000.0, 0.67, 7949.054, 3885.52 + 0.55, 10000.0, 0.69, 8186.227, 3988.09 + 0.55, 10000.0, 0.71, 8423.614, 4091.3 + 0.55, 10000.0, 0.73, 8661.219, 4195.27 + 0.55, 10000.0, 0.75, 8898.908, 4300.11 + 0.55, 10000.0, 0.77, 9136.658, 4405.94 + 0.55, 10000.0, 0.79, 9374.447, 4512.87 + 0.55, 10000.0, 0.81, 9612.293, 4621.48 + 0.55, 10000.0, 0.83, 9850.164, 4731.78 + 0.55, 10000.0, 0.85, 10087.98, 4843.24 + 0.55, 10000.0, 0.87, 10325.7, 4955.79 + 0.55, 10000.0, 0.89, 10563.28, 5069.33 + 0.55, 10000.0, 0.91, 10800.67, 5183.78 + 0.55, 10000.0, 0.93, 11037.85, 5299.06 + 0.55, 10000.0, 0.95, 11274.77, 5415.08 + 0.55, 10000.0, 0.97, 11511.39, 5531.74 + 0.55, 10000.0, 0.99, 11747.66, 5648.97 + 0.55, 15000.0, 0.0, 505.5252, 505.525 + 0.55, 15000.0, 0.05, 556.45, 596.544 + 0.55, 15000.0, 0.07, 779.0825, 694.718 + 0.55, 15000.0, 0.09, 1001.697, 791.131 + 0.55, 15000.0, 0.11, 1224.296, 885.935 + 0.55, 15000.0, 0.13, 1446.882, 979.28 + 0.55, 15000.0, 0.15, 1669.457, 1071.32 + 0.55, 15000.0, 0.17, 1892.024, 1162.19 + 0.55, 15000.0, 0.19, 2114.584, 1252.06 + 0.55, 15000.0, 0.21, 2337.14, 1341.08 + 0.55, 15000.0, 0.23, 2559.695, 1429.38 + 0.55, 15000.0, 0.25, 2782.25, 1517.14 + 0.55, 15000.0, 0.27, 3004.808, 1604.48 + 0.55, 15000.0, 0.29, 3227.372, 1691.57 + 0.55, 15000.0, 0.31, 3449.955, 1778.72 + 0.55, 15000.0, 0.33, 3672.557, 1866.05 + 0.55, 15000.0, 0.35, 3895.162, 1953.45 + 0.55, 15000.0, 0.37, 4117.768, 2041.0 + 0.55, 15000.0, 0.39, 4340.37, 2128.76 + 0.55, 15000.0, 0.41, 4562.951, 2216.99 + 0.55, 15000.0, 0.43, 4785.512, 2305.72 + 0.55, 15000.0, 0.45, 5008.068, 2394.74 + 0.55, 15000.0, 0.47, 5230.624, 2484.02 + 0.55, 15000.0, 0.49, 5453.182, 2573.56 + 0.55, 15000.0, 0.51, 5675.747, 2663.2 + 0.55, 15000.0, 0.53, 5898.324, 2752.95 + 0.55, 15000.0, 0.55, 6120.91, 2842.98 + 0.55, 15000.0, 0.57, 6343.508, 2933.34 + 0.55, 15000.0, 0.59, 6566.12, 3024.08 + 0.55, 15000.0, 0.61, 6788.766, 3115.05 + 0.55, 15000.0, 0.63, 7011.445, 3206.35 + 0.55, 15000.0, 0.65, 7234.13, 3298.29 + 0.55, 15000.0, 0.67, 7456.813, 3390.97 + 0.55, 15000.0, 0.69, 7679.487, 3484.55 + 0.55, 15000.0, 0.71, 7902.127, 3579.38 + 0.55, 15000.0, 0.73, 8124.728, 3675.54 + 0.55, 15000.0, 0.75, 8347.312, 3772.8 + 0.55, 15000.0, 0.77, 8569.881, 3871.17 + 0.55, 15000.0, 0.79, 8792.434, 3970.66 + 0.55, 15000.0, 0.81, 9014.969, 4071.26 + 0.55, 15000.0, 0.83, 9237.488, 4172.99 + 0.55, 15000.0, 0.85, 9460.002, 4275.9 + 0.55, 15000.0, 0.87, 9682.515, 4380.0 + 0.55, 15000.0, 0.89, 9905.032, 4485.31 + 0.55, 15000.0, 0.91, 10127.56, 4591.85 + 0.55, 15000.0, 0.93, 10350.1, 4699.66 + 0.55, 15000.0, 0.95, 10572.65, 4808.74 + 0.55, 15000.0, 0.97, 10795.23, 4919.12 + 0.55, 15000.0, 0.99, 11017.84, 5030.83 + 0.55, 20000.0, 0.0, 419.913, 419.913 + 0.55, 20000.0, 0.05, 462.1688, 495.594 + 0.55, 20000.0, 0.07, 647.0738, 574.608 + 0.55, 20000.0, 0.09, 831.9697, 652.262 + 0.55, 20000.0, 0.11, 1016.858, 728.671 + 0.55, 20000.0, 0.13, 1201.739, 803.953 + 0.55, 20000.0, 0.15, 1386.615, 878.224 + 0.55, 20000.0, 0.17, 1571.486, 951.602 + 0.55, 20000.0, 0.19, 1756.354, 1024.2 + 0.55, 20000.0, 0.21, 1941.22, 1096.15 + 0.55, 20000.0, 0.23, 2126.086, 1167.55 + 0.55, 20000.0, 0.25, 2310.951, 1238.52 + 0.55, 20000.0, 0.27, 2495.819, 1309.19 + 0.55, 20000.0, 0.29, 2680.689, 1379.66 + 0.55, 20000.0, 0.31, 2865.569, 1450.18 + 0.55, 20000.0, 0.33, 3050.458, 1520.83 + 0.55, 20000.0, 0.35, 3235.35, 1591.55 + 0.55, 20000.0, 0.37, 3420.242, 1662.41 + 0.55, 20000.0, 0.39, 3605.131, 1733.46 + 0.55, 20000.0, 0.41, 3790.011, 1804.94 + 0.55, 20000.0, 0.43, 3974.88, 1876.87 + 0.55, 20000.0, 0.45, 4159.747, 1949.04 + 0.55, 20000.0, 0.47, 4344.613, 2021.42 + 0.55, 20000.0, 0.49, 4529.479, 2093.98 + 0.55, 20000.0, 0.51, 4714.347, 2166.52 + 0.55, 20000.0, 0.53, 4899.218, 2239.04 + 0.55, 20000.0, 0.55, 5084.094, 2311.8 + 0.55, 20000.0, 0.57, 5268.976, 2384.84 + 0.55, 20000.0, 0.59, 5453.865, 2458.23 + 0.55, 20000.0, 0.61, 5638.773, 2531.97 + 0.55, 20000.0, 0.63, 5823.7, 2606.13 + 0.55, 20000.0, 0.65, 6008.63, 2680.87 + 0.55, 20000.0, 0.67, 6193.559, 2756.28 + 0.55, 20000.0, 0.69, 6378.484, 2832.44 + 0.55, 20000.0, 0.71, 6563.388, 2909.61 + 0.55, 20000.0, 0.73, 6748.27, 2987.84 + 0.55, 20000.0, 0.75, 6933.146, 3066.99 + 0.55, 20000.0, 0.77, 7118.016, 3147.07 + 0.55, 20000.0, 0.79, 7302.885, 3228.11 + 0.55, 20000.0, 0.81, 7487.761, 3310.15 + 0.55, 20000.0, 0.83, 7672.646, 3393.22 + 0.55, 20000.0, 0.85, 7857.529, 3477.24 + 0.55, 20000.0, 0.87, 8042.408, 3562.21 + 0.55, 20000.0, 0.89, 8227.284, 3648.11 + 0.55, 20000.0, 0.91, 8412.152, 3734.93 + 0.55, 20000.0, 0.93, 8597.013, 3822.67 + 0.55, 20000.0, 0.95, 8781.864, 3911.32 + 0.55, 20000.0, 0.97, 8966.703, 4000.85 + 0.55, 20000.0, 0.99, 9151.53, 4091.27 + 0.55, 25000.0, 0.0, 346.2139, 346.214 + 0.55, 25000.0, 0.05, 382.36, 412.64 + 0.55, 25000.0, 0.07, 535.3563, 475.715 + 0.55, 25000.0, 0.09, 688.3423, 537.784 + 0.55, 25000.0, 0.11, 841.319, 598.932 + 0.55, 25000.0, 0.13, 994.2876, 659.246 + 0.55, 25000.0, 0.15, 1147.249, 718.812 + 0.55, 25000.0, 0.17, 1300.205, 777.716 + 0.55, 25000.0, 0.19, 1453.156, 836.045 + 0.55, 25000.0, 0.21, 1606.103, 893.884 + 0.55, 25000.0, 0.23, 1759.048, 951.32 + 0.55, 25000.0, 0.25, 1911.991, 1008.44 + 0.55, 25000.0, 0.27, 2064.934, 1065.33 + 0.55, 25000.0, 0.29, 2217.878, 1122.07 + 0.55, 25000.0, 0.31, 2370.825, 1178.83 + 0.55, 25000.0, 0.33, 2523.776, 1235.66 + 0.55, 25000.0, 0.35, 2676.73, 1292.56 + 0.55, 25000.0, 0.37, 2829.687, 1349.58 + 0.55, 25000.0, 0.39, 2982.648, 1406.77 + 0.55, 25000.0, 0.41, 3135.618, 1464.37 + 0.55, 25000.0, 0.43, 3288.595, 1522.39 + 0.55, 25000.0, 0.45, 3441.574, 1580.61 + 0.55, 25000.0, 0.47, 3594.551, 1639.01 + 0.55, 25000.0, 0.49, 3747.525, 1697.55 + 0.55, 25000.0, 0.51, 3900.478, 1756.02 + 0.55, 25000.0, 0.53, 4053.413, 1814.41 + 0.55, 25000.0, 0.55, 4206.349, 1872.99 + 0.55, 25000.0, 0.57, 4359.292, 1931.83 + 0.55, 25000.0, 0.59, 4512.246, 1990.97 + 0.55, 25000.0, 0.61, 4665.249, 2050.47 + 0.55, 25000.0, 0.63, 4818.298, 2110.39 + 0.55, 25000.0, 0.65, 4971.352, 2170.82 + 0.55, 25000.0, 0.67, 5124.403, 2231.83 + 0.55, 25000.0, 0.69, 5277.44, 2293.51 + 0.55, 25000.0, 0.71, 5430.417, 2356.03 + 0.55, 25000.0, 0.73, 5583.334, 2419.44 + 0.55, 25000.0, 0.75, 5736.235, 2483.63 + 0.55, 25000.0, 0.77, 5889.128, 2548.63 + 0.55, 25000.0, 0.79, 6042.021, 2614.43 + 0.55, 25000.0, 0.81, 6194.945, 2681.15 + 0.55, 25000.0, 0.83, 6347.903, 2748.77 + 0.55, 25000.0, 0.85, 6500.867, 2817.17 + 0.55, 25000.0, 0.87, 6653.836, 2886.33 + 0.55, 25000.0, 0.89, 6806.806, 2956.22 + 0.55, 25000.0, 0.91, 6959.773, 3026.79 + 0.55, 25000.0, 0.93, 7112.735, 3098.03 + 0.55, 25000.0, 0.95, 7265.687, 3169.9 + 0.55, 25000.0, 0.97, 7418.628, 3242.37 + 0.55, 25000.0, 0.99, 7571.554, 3315.41 + 0.55, 30000.0, 0.0, 283.1571, 283.157 + 0.55, 30000.0, 0.05, 316.88, 345.64 + 0.55, 30000.0, 0.07, 443.6348, 395.946 + 0.55, 30000.0, 0.09, 570.3923, 445.489 + 0.55, 30000.0, 0.11, 697.1522, 494.338 + 0.55, 30000.0, 0.13, 823.9141, 542.561 + 0.55, 30000.0, 0.15, 950.6775, 590.225 + 0.55, 30000.0, 0.17, 1077.442, 637.399 + 0.55, 30000.0, 0.19, 1204.207, 684.151 + 0.55, 30000.0, 0.21, 1330.973, 730.549 + 0.55, 30000.0, 0.23, 1457.738, 776.66 + 0.55, 30000.0, 0.25, 1584.503, 822.554 + 0.55, 30000.0, 0.27, 1711.267, 868.297 + 0.55, 30000.0, 0.29, 1838.029, 913.959 + 0.55, 30000.0, 0.31, 1964.789, 959.671 + 0.55, 30000.0, 0.33, 2091.545, 1005.49 + 0.55, 30000.0, 0.35, 2218.3, 1051.37 + 0.55, 30000.0, 0.37, 2345.053, 1097.38 + 0.55, 30000.0, 0.39, 2471.805, 1143.53 + 0.55, 30000.0, 0.41, 2598.553, 1190.0 + 0.55, 30000.0, 0.43, 2725.299, 1236.79 + 0.55, 30000.0, 0.45, 2852.046, 1283.74 + 0.55, 30000.0, 0.47, 2978.793, 1330.83 + 0.55, 30000.0, 0.49, 3105.544, 1378.03 + 0.55, 30000.0, 0.51, 3232.297, 1425.1 + 0.55, 30000.0, 0.53, 3359.053, 1472.06 + 0.55, 30000.0, 0.55, 3485.816, 1519.19 + 0.55, 30000.0, 0.57, 3612.587, 1566.58 + 0.55, 30000.0, 0.59, 3739.366, 1614.28 + 0.55, 30000.0, 0.61, 3866.175, 1662.46 + 0.55, 30000.0, 0.63, 3993.011, 1711.15 + 0.55, 30000.0, 0.65, 4119.846, 1760.34 + 0.55, 30000.0, 0.67, 4246.672, 1810.06 + 0.55, 30000.0, 0.69, 4373.483, 1860.35 + 0.55, 30000.0, 0.71, 4500.237, 1911.28 + 0.55, 30000.0, 0.73, 4626.935, 1962.9 + 0.55, 30000.0, 0.75, 4753.617, 2015.17 + 0.55, 30000.0, 0.77, 4880.292, 2068.13 + 0.55, 30000.0, 0.79, 5006.969, 2121.79 + 0.55, 30000.0, 0.81, 5133.676, 2176.35 + 0.55, 30000.0, 0.83, 5260.416, 2231.79 + 0.55, 30000.0, 0.85, 5387.167, 2287.88 + 0.55, 30000.0, 0.87, 5513.928, 2344.55 + 0.55, 30000.0, 0.89, 5640.695, 2401.74 + 0.55, 30000.0, 0.91, 5767.466, 2459.39 + 0.55, 30000.0, 0.93, 5894.241, 2517.42 + 0.55, 30000.0, 0.95, 6021.017, 2575.79 + 0.55, 30000.0, 0.97, 6147.793, 2634.43 + 0.55, 30000.0, 0.99, 6274.565, 2693.28 + 0.55, 35000.0, 0.0, 229.5619, 229.562 + 0.55, 35000.0, 0.05, 262.0, 292.55 + 0.55, 35000.0, 0.07, 366.8221, 331.914 + 0.55, 35000.0, 0.09, 471.6771, 370.846 + 0.55, 35000.0, 0.11, 576.5612, 409.386 + 0.55, 35000.0, 0.13, 681.4706, 447.573 + 0.55, 35000.0, 0.15, 786.4018, 485.445 + 0.55, 35000.0, 0.17, 891.3509, 523.04 + 0.55, 35000.0, 0.19, 996.3142, 560.398 + 0.55, 35000.0, 0.21, 1101.288, 597.557 + 0.55, 35000.0, 0.23, 1206.269, 634.556 + 0.55, 35000.0, 0.25, 1311.252, 671.434 + 0.55, 35000.0, 0.27, 1416.235, 708.228 + 0.55, 35000.0, 0.29, 1521.214, 744.979 + 0.55, 35000.0, 0.31, 1626.175, 781.76 + 0.55, 35000.0, 0.33, 1731.117, 818.6 + 0.55, 35000.0, 0.35, 1836.05, 855.487 + 0.55, 35000.0, 0.37, 1940.975, 892.443 + 0.55, 35000.0, 0.39, 2045.893, 929.487 + 0.55, 35000.0, 0.41, 2150.81, 966.675 + 0.55, 35000.0, 0.43, 2255.725, 1004.02 + 0.55, 35000.0, 0.45, 2360.631, 1041.5 + 0.55, 35000.0, 0.47, 2465.528, 1079.11 + 0.55, 35000.0, 0.49, 2570.412, 1116.87 + 0.55, 35000.0, 0.51, 2675.258, 1154.69 + 0.55, 35000.0, 0.53, 2780.07, 1192.61 + 0.55, 35000.0, 0.55, 2884.884, 1230.74 + 0.55, 35000.0, 0.57, 2989.711, 1269.15 + 0.55, 35000.0, 0.59, 3094.562, 1307.86 + 0.55, 35000.0, 0.61, 3199.508, 1346.97 + 0.55, 35000.0, 0.63, 3304.545, 1386.52 + 0.55, 35000.0, 0.65, 3409.594, 1426.48 + 0.55, 35000.0, 0.67, 3514.637, 1466.89 + 0.55, 35000.0, 0.69, 3619.656, 1507.77 + 0.55, 35000.0, 0.71, 3724.556, 1549.17 + 0.55, 35000.0, 0.73, 3829.339, 1591.1 + 0.55, 35000.0, 0.75, 3934.097, 1633.57 + 0.55, 35000.0, 0.77, 4038.848, 1676.62 + 0.55, 35000.0, 0.79, 4143.609, 1720.25 + 0.55, 35000.0, 0.81, 4248.46, 1764.62 + 0.55, 35000.0, 0.83, 4353.402, 1809.71 + 0.55, 35000.0, 0.85, 4458.366, 1855.37 + 0.55, 35000.0, 0.87, 4563.341, 1901.57 + 0.55, 35000.0, 0.89, 4668.316, 1948.27 + 0.55, 35000.0, 0.91, 4773.28, 1995.44 + 0.55, 35000.0, 0.93, 4878.223, 2043.04 + 0.55, 35000.0, 0.95, 4983.134, 2091.04 + 0.55, 35000.0, 0.97, 5088.002, 2139.4 + 0.55, 35000.0, 0.99, 5192.816, 2188.09 + 0.55, 40000.0, 0.0, 181.6758, 181.676 + 0.55, 40000.0, 0.05, 208.0, 252.15 + 0.55, 40000.0, 0.07, 291.0972, 282.268 + 0.55, 40000.0, 0.09, 374.2058, 312.136 + 0.55, 40000.0, 0.11, 457.3256, 341.78 + 0.55, 40000.0, 0.13, 540.4564, 371.225 + 0.55, 40000.0, 0.15, 623.5982, 400.498 + 0.55, 40000.0, 0.17, 706.7509, 429.626 + 0.55, 40000.0, 0.19, 789.9143, 458.633 + 0.55, 40000.0, 0.21, 873.0883, 487.547 + 0.55, 40000.0, 0.23, 956.2729, 516.393 + 0.55, 40000.0, 0.25, 1039.468, 545.198 + 0.55, 40000.0, 0.27, 1122.673, 573.987 + 0.55, 40000.0, 0.29, 1205.889, 602.788 + 0.55, 40000.0, 0.31, 1289.126, 631.661 + 0.55, 40000.0, 0.33, 1372.383, 660.626 + 0.55, 40000.0, 0.35, 1455.641, 689.653 + 0.55, 40000.0, 0.37, 1538.893, 718.751 + 0.55, 40000.0, 0.39, 1622.135, 747.929 + 0.55, 40000.0, 0.41, 1705.339, 777.216 + 0.55, 40000.0, 0.43, 1788.505, 806.617 + 0.55, 40000.0, 0.45, 1871.656, 836.106 + 0.55, 40000.0, 0.47, 1954.798, 865.681 + 0.55, 40000.0, 0.49, 2037.933, 895.34 + 0.55, 40000.0, 0.51, 2121.064, 925.004 + 0.55, 40000.0, 0.53, 2204.195, 954.689 + 0.55, 40000.0, 0.55, 2287.334, 984.506 + 0.55, 40000.0, 0.57, 2370.486, 1014.49 + 0.55, 40000.0, 0.59, 2453.656, 1044.67 + 0.55, 40000.0, 0.61, 2536.876, 1075.08 + 0.55, 40000.0, 0.63, 2620.145, 1105.74 + 0.55, 40000.0, 0.65, 2703.428, 1136.72 + 0.55, 40000.0, 0.67, 2786.718, 1168.05 + 0.55, 40000.0, 0.69, 2870.008, 1199.78 + 0.55, 40000.0, 0.71, 2953.277, 1231.97 + 0.55, 40000.0, 0.73, 3036.521, 1264.67 + 0.55, 40000.0, 0.75, 3119.75, 1297.85 + 0.55, 40000.0, 0.77, 3202.963, 1331.55 + 0.55, 40000.0, 0.79, 3286.159, 1365.78 + 0.55, 40000.0, 0.81, 3369.315, 1400.71 + 0.55, 40000.0, 0.83, 3452.435, 1436.33 + 0.55, 40000.0, 0.85, 3535.547, 1472.44 + 0.55, 40000.0, 0.87, 3618.66, 1509.01 + 0.55, 40000.0, 0.89, 3701.783, 1545.98 + 0.55, 40000.0, 0.91, 3784.923, 1583.31 + 0.55, 40000.0, 0.93, 3868.089, 1620.94 + 0.55, 40000.0, 0.95, 3951.291, 1658.85 + 0.55, 40000.0, 0.97, 4034.535, 1696.97 + 0.55, 40000.0, 0.99, 4117.83, 1735.26 + 0.55, 43000.0, 0.0, 157.3707, 157.371 + 0.55, 43000.0, 0.05, 177.8, 235.9 + 0.55, 43000.0, 0.07, 251.6035, 261.821 + 0.55, 43000.0, 0.09, 324.8714, 287.508 + 0.55, 43000.0, 0.11, 397.6715, 312.977 + 0.55, 43000.0, 0.13, 470.0715, 338.243 + 0.55, 43000.0, 0.15, 542.1393, 363.321 + 0.55, 43000.0, 0.17, 613.9426, 388.228 + 0.55, 43000.0, 0.19, 685.5492, 412.979 + 0.55, 43000.0, 0.21, 757.027, 437.588 + 0.55, 43000.0, 0.23, 828.4437, 462.072 + 0.55, 43000.0, 0.25, 899.8671, 486.446 + 0.55, 43000.0, 0.27, 971.3651, 510.725 + 0.55, 43000.0, 0.29, 1043.005, 534.925 + 0.55, 43000.0, 0.31, 1115.197, 558.801 + 0.55, 43000.0, 0.33, 1187.925, 582.432 + 0.55, 43000.0, 0.35, 1260.75, 606.219 + 0.55, 43000.0, 0.37, 1333.575, 630.304 + 0.55, 43000.0, 0.39, 1406.303, 654.829 + 0.55, 43000.0, 0.41, 1478.474, 680.834 + 0.55, 43000.0, 0.43, 1550.079, 708.243 + 0.55, 43000.0, 0.45, 1621.556, 735.862 + 0.55, 43000.0, 0.47, 1692.983, 763.398 + 0.55, 43000.0, 0.49, 1764.438, 790.555 + 0.55, 43000.0, 0.51, 1836.252, 815.766 + 0.55, 43000.0, 0.53, 1908.441, 839.044 + 0.55, 43000.0, 0.55, 1980.706, 861.987 + 0.55, 43000.0, 0.57, 2053.001, 884.919 + 0.55, 43000.0, 0.59, 2125.28, 908.161 + 0.55, 43000.0, 0.61, 2197.335, 932.777 + 0.55, 43000.0, 0.63, 2269.159, 958.911 + 0.55, 43000.0, 0.65, 2340.95, 985.787 + 0.55, 43000.0, 0.67, 2412.741, 1013.37 + 0.55, 43000.0, 0.69, 2484.565, 1041.63 + 0.55, 43000.0, 0.71, 2556.62, 1070.74 + 0.55, 43000.0, 0.73, 2628.899, 1100.63 + 0.55, 43000.0, 0.75, 2701.194, 1130.92 + 0.55, 43000.0, 0.77, 2773.459, 1161.48 + 0.55, 43000.0, 0.79, 2845.648, 1192.16 + 0.55, 43000.0, 0.81, 2917.521, 1222.21 + 0.55, 43000.0, 0.83, 2989.08, 1251.64 + 0.55, 43000.0, 0.85, 3060.569, 1281.21 + 0.55, 43000.0, 0.87, 3132.035, 1311.09 + 0.55, 43000.0, 0.89, 3203.528, 1341.42 + 0.55, 43000.0, 0.91, 3275.097, 1372.36 + 0.55, 43000.0, 0.93, 3346.79, 1404.06 + 0.55, 43000.0, 0.95, 3418.656, 1436.69 + 0.55, 43000.0, 0.97, 3490.745, 1470.39 + 0.55, 43000.0, 0.99, 3563.104, 1505.32 + 0.55, 48000.0, 0.0, 123.8826, 123.883 + 0.55, 48000.0, 0.05, 141.3, 188.2 + 0.55, 48000.0, 0.07, 199.285, 208.386 + 0.55, 48000.0, 0.09, 256.91, 228.352 + 0.55, 48000.0, 0.11, 314.215, 248.121 + 0.55, 48000.0, 0.13, 371.24, 267.713 + 0.55, 48000.0, 0.15, 428.025, 287.15 + 0.55, 48000.0, 0.17, 484.61, 306.452 + 0.55, 48000.0, 0.19, 541.035, 325.641 + 0.55, 48000.0, 0.21, 597.34, 344.738 + 0.55, 48000.0, 0.23, 653.565, 363.764 + 0.55, 48000.0, 0.25, 709.75, 382.74 + 0.55, 48000.0, 0.27, 765.935, 401.687 + 0.55, 48000.0, 0.29, 822.16, 420.627 + 0.55, 48000.0, 0.31, 878.5557, 439.455 + 0.55, 48000.0, 0.33, 935.1402, 458.223 + 0.55, 48000.0, 0.35, 991.8187, 477.137 + 0.55, 48000.0, 0.37, 1048.587, 496.28 + 0.55, 48000.0, 0.39, 1105.442, 515.732 + 0.55, 48000.0, 0.41, 1162.418, 536.165 + 0.55, 48000.0, 0.43, 1219.502, 557.516 + 0.55, 48000.0, 0.45, 1276.631, 578.994 + 0.55, 48000.0, 0.47, 1333.783, 600.393 + 0.55, 48000.0, 0.49, 1390.933, 621.511 + 0.55, 48000.0, 0.51, 1448.09, 641.182 + 0.55, 48000.0, 0.53, 1505.223, 659.436 + 0.55, 48000.0, 0.55, 1562.262, 677.494 + 0.55, 48000.0, 0.57, 1619.17, 695.618 + 0.55, 48000.0, 0.59, 1675.907, 714.07 + 0.55, 48000.0, 0.61, 1732.094, 733.836 + 0.55, 48000.0, 0.63, 1787.775, 755.004 + 0.55, 48000.0, 0.65, 1843.419, 776.756 + 0.55, 48000.0, 0.67, 1899.152, 799.002 + 0.55, 48000.0, 0.69, 1955.103, 821.652 + 0.55, 48000.0, 0.71, 2011.996, 844.494 + 0.55, 48000.0, 0.73, 2069.813, 867.468 + 0.55, 48000.0, 0.75, 2127.794, 890.662 + 0.55, 48000.0, 0.77, 2185.777, 914.044 + 0.55, 48000.0, 0.79, 2243.6, 937.582 + 0.55, 48000.0, 0.81, 2300.583, 960.981 + 0.55, 48000.0, 0.83, 2356.69, 984.271 + 0.55, 48000.0, 0.85, 2412.525, 1007.81 + 0.55, 48000.0, 0.87, 2468.176, 1031.7 + 0.55, 48000.0, 0.89, 2523.731, 1056.04 + 0.55, 48000.0, 0.91, 2579.278, 1080.91 + 0.55, 48000.0, 0.93, 2634.905, 1106.42 + 0.55, 48000.0, 0.95, 2690.7, 1132.66 + 0.55, 48000.0, 0.97, 2746.751, 1159.73 + 0.55, 48000.0, 0.99, 2803.146, 1187.73 + 0.6, 0.0, 0.0, 875.8803, 875.88 + 0.6, 0.0, 0.05, 691.7425, 1121.61 + 0.6, 0.0, 0.07, 974.1147, 1257.15 + 0.6, 0.0, 0.09, 1256.167, 1392.33 + 0.6, 0.0, 0.11, 1537.922, 1527.14 + 0.6, 0.0, 0.13, 1819.403, 1661.6 + 0.6, 0.0, 0.15, 2100.632, 1795.71 + 0.6, 0.0, 0.17, 2381.634, 1929.47 + 0.6, 0.0, 0.19, 2662.431, 2062.88 + 0.6, 0.0, 0.21, 2943.046, 2195.95 + 0.6, 0.0, 0.23, 3223.502, 2328.68 + 0.6, 0.0, 0.25, 3503.823, 2461.08 + 0.6, 0.0, 0.27, 3784.03, 2593.14 + 0.6, 0.0, 0.29, 4064.148, 2724.87 + 0.6, 0.0, 0.31, 4344.199, 2856.28 + 0.6, 0.0, 0.33, 4624.206, 2987.37 + 0.6, 0.0, 0.35, 4904.193, 3118.14 + 0.6, 0.0, 0.37, 5184.182, 3248.6 + 0.6, 0.0, 0.39, 5464.196, 3378.74 + 0.6, 0.0, 0.41, 5744.321, 3508.3 + 0.6, 0.0, 0.43, 6024.565, 3637.33 + 0.6, 0.0, 0.45, 6304.859, 3766.27 + 0.6, 0.0, 0.47, 6585.194, 3895.25 + 0.6, 0.0, 0.49, 6865.564, 4024.43 + 0.6, 0.0, 0.51, 7145.978, 4154.34 + 0.6, 0.0, 0.53, 7426.424, 4285.03 + 0.6, 0.0, 0.55, 7706.871, 4416.04 + 0.6, 0.0, 0.57, 7987.306, 4547.33 + 0.6, 0.0, 0.59, 8267.712, 4678.85 + 0.6, 0.0, 0.61, 8548.042, 4810.55 + 0.6, 0.0, 0.63, 8828.29, 4942.37 + 0.6, 0.0, 0.65, 9108.489, 5074.28 + 0.6, 0.0, 0.67, 9388.64, 5206.22 + 0.6, 0.0, 0.69, 9668.745, 5338.14 + 0.6, 0.0, 0.71, 9948.751, 5469.67 + 0.6, 0.0, 0.73, 10228.67, 5600.83 + 0.6, 0.0, 0.75, 10508.59, 5732.07 + 0.6, 0.0, 0.77, 10788.53, 5863.49 + 0.6, 0.0, 0.79, 11068.52, 5995.2 + 0.6, 0.0, 0.81, 11348.69, 6127.32 + 0.6, 0.0, 0.83, 11629.04, 6259.96 + 0.6, 0.0, 0.85, 11909.45, 6393.22 + 0.6, 0.0, 0.87, 12189.88, 6527.19 + 0.6, 0.0, 0.89, 12470.31, 6662.0 + 0.6, 0.0, 0.91, 12750.72, 6797.73 + 0.6, 0.0, 0.93, 13031.07, 6934.5 + 0.6, 0.0, 0.95, 13311.36, 7072.41 + 0.6, 0.0, 0.97, 13591.53, 7211.57 + 0.6, 0.0, 0.99, 13871.59, 7352.08 + 0.6, 2000.0, 0.0, 820.0654, 820.065 + 0.6, 2000.0, 0.05, 675.2237, 1026.7 + 0.6, 2000.0, 0.07, 946.5082, 1162.77 + 0.6, 2000.0, 0.09, 1217.676, 1297.48 + 0.6, 2000.0, 0.11, 1488.738, 1430.89 + 0.6, 2000.0, 0.13, 1759.703, 1563.11 + 0.6, 2000.0, 0.15, 2030.581, 1694.2 + 0.6, 2000.0, 0.17, 2301.382, 1824.25 + 0.6, 2000.0, 0.19, 2572.116, 1953.35 + 0.6, 2000.0, 0.21, 2842.791, 2081.56 + 0.6, 2000.0, 0.23, 3113.419, 2208.99 + 0.6, 2000.0, 0.25, 3384.009, 2335.69 + 0.6, 2000.0, 0.27, 3654.57, 2461.77 + 0.6, 2000.0, 0.29, 3925.113, 2587.3 + 0.6, 2000.0, 0.31, 4195.646, 2712.36 + 0.6, 2000.0, 0.33, 4466.181, 2837.03 + 0.6, 2000.0, 0.35, 4736.726, 2961.4 + 0.6, 2000.0, 0.37, 5007.292, 3085.54 + 0.6, 2000.0, 0.39, 5277.888, 3209.55 + 0.6, 2000.0, 0.41, 5548.574, 3333.52 + 0.6, 2000.0, 0.43, 5819.349, 3457.53 + 0.6, 2000.0, 0.45, 6090.146, 3581.63 + 0.6, 2000.0, 0.47, 6360.951, 3705.88 + 0.6, 2000.0, 0.49, 6631.749, 3830.36 + 0.6, 2000.0, 0.51, 6902.482, 3955.41 + 0.6, 2000.0, 0.53, 7173.147, 4081.03 + 0.6, 2000.0, 0.55, 7443.79, 4206.88 + 0.6, 2000.0, 0.57, 7714.417, 4332.88 + 0.6, 2000.0, 0.59, 7985.034, 4458.95 + 0.6, 2000.0, 0.61, 8255.608, 4584.8 + 0.6, 2000.0, 0.63, 8526.153, 4710.39 + 0.6, 2000.0, 0.65, 8796.731, 4836.04 + 0.6, 2000.0, 0.67, 9067.367, 4961.79 + 0.6, 2000.0, 0.69, 9338.084, 5087.7 + 0.6, 2000.0, 0.71, 9609.12, 5213.91 + 0.6, 2000.0, 0.73, 9880.448, 5340.46 + 0.6, 2000.0, 0.75, 10151.77, 5467.23 + 0.6, 2000.0, 0.77, 10423.01, 5594.22 + 0.6, 2000.0, 0.79, 10694.09, 5721.41 + 0.6, 2000.0, 0.81, 10964.53, 5848.13 + 0.6, 2000.0, 0.83, 11234.35, 5974.54 + 0.6, 2000.0, 0.85, 11504.05, 6101.64 + 0.6, 2000.0, 0.87, 11773.73, 6229.74 + 0.6, 2000.0, 0.89, 12043.52, 6359.17 + 0.6, 2000.0, 0.91, 12313.51, 6490.25 + 0.6, 2000.0, 0.93, 12583.82, 6623.3 + 0.6, 2000.0, 0.95, 12854.55, 6758.64 + 0.6, 2000.0, 0.97, 13125.82, 6896.6 + 0.6, 2000.0, 0.99, 13397.73, 7037.49 + 0.6, 5000.0, 0.0, 741.6644, 741.664 + 0.6, 5000.0, 0.05, 663.3713, 924.07 + 0.6, 5000.0, 0.07, 915.9692, 1054.48 + 0.6, 5000.0, 0.09, 1169.287, 1183.04 + 0.6, 5000.0, 0.11, 1423.273, 1309.86 + 0.6, 5000.0, 0.13, 1677.871, 1435.08 + 0.6, 5000.0, 0.15, 1933.029, 1558.83 + 0.6, 5000.0, 0.17, 2188.693, 1681.21 + 0.6, 5000.0, 0.19, 2444.809, 1802.36 + 0.6, 5000.0, 0.21, 2701.324, 1922.41 + 0.6, 5000.0, 0.23, 2958.184, 2041.48 + 0.6, 5000.0, 0.25, 3215.336, 2159.7 + 0.6, 5000.0, 0.27, 3472.726, 2277.19 + 0.6, 5000.0, 0.29, 3730.3, 2394.07 + 0.6, 5000.0, 0.31, 3988.006, 2510.47 + 0.6, 5000.0, 0.33, 4245.788, 2626.52 + 0.6, 5000.0, 0.35, 4503.594, 2742.34 + 0.6, 5000.0, 0.37, 4761.37, 2858.05 + 0.6, 5000.0, 0.39, 5019.062, 2973.79 + 0.6, 5000.0, 0.41, 5276.43, 3089.97 + 0.6, 5000.0, 0.43, 5533.465, 3206.66 + 0.6, 5000.0, 0.45, 5790.393, 3323.53 + 0.6, 5000.0, 0.47, 6047.248, 3440.54 + 0.6, 5000.0, 0.49, 6304.07, 3557.69 + 0.6, 5000.0, 0.51, 6560.944, 3674.79 + 0.6, 5000.0, 0.53, 6817.894, 3791.87 + 0.6, 5000.0, 0.55, 7074.886, 3909.11 + 0.6, 5000.0, 0.57, 7331.934, 4026.57 + 0.6, 5000.0, 0.59, 7589.051, 4144.29 + 0.6, 5000.0, 0.61, 7846.307, 4262.45 + 0.6, 5000.0, 0.63, 8103.702, 4381.08 + 0.6, 5000.0, 0.65, 8361.166, 4500.01 + 0.6, 5000.0, 0.67, 8618.686, 4619.22 + 0.6, 5000.0, 0.69, 8876.248, 4738.71 + 0.6, 5000.0, 0.71, 9133.868, 4858.34 + 0.6, 5000.0, 0.73, 9391.525, 4978.14 + 0.6, 5000.0, 0.75, 9649.163, 5098.22 + 0.6, 5000.0, 0.77, 9906.751, 5218.59 + 0.6, 5000.0, 0.79, 10164.26, 5339.28 + 0.6, 5000.0, 0.81, 10421.51, 5459.84 + 0.6, 5000.0, 0.83, 10678.52, 5580.4 + 0.6, 5000.0, 0.85, 10935.47, 5701.71 + 0.6, 5000.0, 0.87, 11192.42, 5824.02 + 0.6, 5000.0, 0.89, 11449.41, 5947.6 + 0.6, 5000.0, 0.91, 11706.5, 6072.7 + 0.6, 5000.0, 0.93, 11963.71, 6199.58 + 0.6, 5000.0, 0.95, 12221.11, 6328.51 + 0.6, 5000.0, 0.97, 12478.74, 6459.74 + 0.6, 5000.0, 0.99, 12736.65, 6593.52 + 0.6, 10000.0, 0.0, 624.2964, 624.296 + 0.6, 10000.0, 0.05, 536.2188, 794.666 + 0.6, 10000.0, 0.07, 762.0008, 900.221 + 0.6, 10000.0, 0.09, 987.073, 1004.92 + 0.6, 10000.0, 0.11, 1211.49, 1108.81 + 0.6, 10000.0, 0.13, 1435.306, 1211.95 + 0.6, 10000.0, 0.15, 1658.576, 1314.39 + 0.6, 10000.0, 0.17, 1881.355, 1416.18 + 0.6, 10000.0, 0.19, 2103.696, 1517.39 + 0.6, 10000.0, 0.21, 2325.655, 1618.05 + 0.6, 10000.0, 0.23, 2547.286, 1718.22 + 0.6, 10000.0, 0.25, 2768.644, 1817.96 + 0.6, 10000.0, 0.27, 2989.783, 1917.32 + 0.6, 10000.0, 0.29, 3210.757, 2016.35 + 0.6, 10000.0, 0.31, 3431.622, 2115.11 + 0.6, 10000.0, 0.33, 3652.432, 2213.64 + 0.6, 10000.0, 0.35, 3873.241, 2312.0 + 0.6, 10000.0, 0.37, 4094.105, 2410.25 + 0.6, 10000.0, 0.39, 4315.076, 2508.44 + 0.6, 10000.0, 0.41, 4536.425, 2606.61 + 0.6, 10000.0, 0.43, 4758.154, 2704.83 + 0.6, 10000.0, 0.45, 4980.0, 2803.14 + 0.6, 10000.0, 0.47, 5201.913, 2901.6 + 0.6, 10000.0, 0.49, 5423.843, 3000.26 + 0.6, 10000.0, 0.51, 5645.683, 3099.5 + 0.6, 10000.0, 0.53, 5867.397, 3199.3 + 0.6, 10000.0, 0.55, 6089.025, 3299.21 + 0.6, 10000.0, 0.57, 6310.545, 3399.13 + 0.6, 10000.0, 0.59, 6531.938, 3498.93 + 0.6, 10000.0, 0.61, 6752.941, 3598.03 + 0.6, 10000.0, 0.63, 6973.592, 3696.42 + 0.6, 10000.0, 0.65, 7194.23, 3794.73 + 0.6, 10000.0, 0.67, 7414.951, 3893.1 + 0.6, 10000.0, 0.69, 7635.852, 3991.65 + 0.6, 10000.0, 0.71, 7857.355, 4090.29 + 0.6, 10000.0, 0.73, 8079.478, 4189.18 + 0.6, 10000.0, 0.75, 8301.834, 4288.83 + 0.6, 10000.0, 0.77, 8524.361, 4389.46 + 0.6, 10000.0, 0.79, 8746.999, 4491.33 + 0.6, 10000.0, 0.81, 8969.772, 4595.74 + 0.6, 10000.0, 0.83, 9192.598, 4702.69 + 0.6, 10000.0, 0.85, 9415.288, 4810.82 + 0.6, 10000.0, 0.87, 9637.738, 4919.87 + 0.6, 10000.0, 0.89, 9859.846, 5029.56 + 0.6, 10000.0, 0.91, 10081.51, 5139.62 + 0.6, 10000.0, 0.93, 10302.62, 5249.77 + 0.6, 10000.0, 0.95, 10523.09, 5359.75 + 0.6, 10000.0, 0.97, 10742.8, 5469.27 + 0.6, 10000.0, 0.99, 10961.65, 5578.06 + 0.6, 15000.0, 0.0, 522.1498, 522.15 + 0.6, 15000.0, 0.05, 558.9, 631.9 + 0.6, 15000.0, 0.07, 782.4953, 736.033 + 0.6, 15000.0, 0.09, 1006.07, 838.232 + 0.6, 15000.0, 0.11, 1229.628, 938.661 + 0.6, 15000.0, 0.13, 1453.172, 1037.48 + 0.6, 15000.0, 0.15, 1676.704, 1134.87 + 0.6, 15000.0, 0.17, 1900.226, 1230.97 + 0.6, 15000.0, 0.19, 2123.743, 1325.97 + 0.6, 15000.0, 0.21, 2347.256, 1420.01 + 0.6, 15000.0, 0.23, 2570.769, 1513.28 + 0.6, 15000.0, 0.25, 2794.284, 1605.92 + 0.6, 15000.0, 0.27, 3017.804, 1698.11 + 0.6, 15000.0, 0.29, 3241.332, 1790.01 + 0.6, 15000.0, 0.31, 3464.886, 1881.98 + 0.6, 15000.0, 0.33, 3688.466, 1974.14 + 0.6, 15000.0, 0.35, 3912.05, 2066.36 + 0.6, 15000.0, 0.37, 4135.634, 2158.71 + 0.6, 15000.0, 0.39, 4359.214, 2251.24 + 0.6, 15000.0, 0.41, 4582.767, 2344.26 + 0.6, 15000.0, 0.43, 4806.293, 2437.77 + 0.6, 15000.0, 0.45, 5029.813, 2531.51 + 0.6, 15000.0, 0.47, 5253.328, 2625.44 + 0.6, 15000.0, 0.49, 5476.842, 2719.52 + 0.6, 15000.0, 0.51, 5700.364, 2813.44 + 0.6, 15000.0, 0.53, 5923.895, 2907.24 + 0.6, 15000.0, 0.55, 6147.431, 3001.26 + 0.6, 15000.0, 0.57, 6370.974, 3095.57 + 0.6, 15000.0, 0.59, 6594.523, 3190.28 + 0.6, 15000.0, 0.61, 6818.076, 3285.36 + 0.6, 15000.0, 0.63, 7041.635, 3380.93 + 0.6, 15000.0, 0.65, 7265.206, 3477.22 + 0.6, 15000.0, 0.67, 7488.791, 3574.35 + 0.6, 15000.0, 0.69, 7712.392, 3672.44 + 0.6, 15000.0, 0.71, 7936.046, 3771.89 + 0.6, 15000.0, 0.73, 8159.745, 3872.74 + 0.6, 15000.0, 0.75, 8383.444, 3974.79 + 0.6, 15000.0, 0.77, 8607.129, 4078.04 + 0.6, 15000.0, 0.79, 8830.786, 4182.5 + 0.6, 15000.0, 0.81, 9054.348, 4288.24 + 0.6, 15000.0, 0.83, 9277.813, 4395.25 + 0.6, 15000.0, 0.85, 9501.25, 4503.49 + 0.6, 15000.0, 0.87, 9724.671, 4612.97 + 0.6, 15000.0, 0.89, 9948.088, 4723.68 + 0.6, 15000.0, 0.91, 10171.52, 4835.62 + 0.6, 15000.0, 0.93, 10394.97, 4948.79 + 0.6, 15000.0, 0.95, 10618.45, 5063.18 + 0.6, 15000.0, 0.97, 10841.98, 5178.79 + 0.6, 15000.0, 0.99, 11065.58, 5295.63 + 0.6, 20000.0, 0.0, 433.7222, 433.722 + 0.6, 20000.0, 0.05, 463.2, 523.1 + 0.6, 20000.0, 0.07, 648.5134, 606.82 + 0.6, 20000.0, 0.09, 833.8186, 689.037 + 0.6, 20000.0, 0.11, 1019.117, 769.881 + 0.6, 20000.0, 0.13, 1204.409, 849.478 + 0.6, 20000.0, 0.15, 1389.696, 927.957 + 0.6, 20000.0, 0.17, 1574.98, 1005.45 + 0.6, 20000.0, 0.19, 1760.26, 1082.07 + 0.6, 20000.0, 0.21, 1945.539, 1157.96 + 0.6, 20000.0, 0.23, 2130.817, 1233.24 + 0.6, 20000.0, 0.25, 2316.096, 1308.05 + 0.6, 20000.0, 0.27, 2501.375, 1382.5 + 0.6, 20000.0, 0.29, 2686.658, 1456.73 + 0.6, 20000.0, 0.31, 2871.949, 1531.01 + 0.6, 20000.0, 0.33, 3057.249, 1605.44 + 0.6, 20000.0, 0.35, 3242.55, 1679.91 + 0.6, 20000.0, 0.37, 3427.851, 1754.5 + 0.6, 20000.0, 0.39, 3613.151, 1829.25 + 0.6, 20000.0, 0.41, 3798.443, 1904.41 + 0.6, 20000.0, 0.43, 3983.726, 1980.01 + 0.6, 20000.0, 0.45, 4169.006, 2055.79 + 0.6, 20000.0, 0.47, 4354.285, 2131.72 + 0.6, 20000.0, 0.49, 4539.562, 2207.75 + 0.6, 20000.0, 0.51, 4724.832, 2283.59 + 0.6, 20000.0, 0.53, 4910.097, 2359.25 + 0.6, 20000.0, 0.55, 5095.369, 2435.09 + 0.6, 20000.0, 0.57, 5280.65, 2511.21 + 0.6, 20000.0, 0.59, 5465.946, 2587.69 + 0.6, 20000.0, 0.61, 5651.284, 2664.63 + 0.6, 20000.0, 0.63, 5836.663, 2742.12 + 0.6, 20000.0, 0.65, 6022.05, 2820.24 + 0.6, 20000.0, 0.67, 6207.437, 2899.09 + 0.6, 20000.0, 0.69, 6392.816, 2978.74 + 0.6, 20000.0, 0.71, 6578.156, 3059.43 + 0.6, 20000.0, 0.73, 6763.454, 3141.21 + 0.6, 20000.0, 0.75, 6948.737, 3223.97 + 0.6, 20000.0, 0.77, 7134.009, 3307.74 + 0.6, 20000.0, 0.79, 7319.271, 3392.52 + 0.6, 20000.0, 0.81, 7504.533, 3478.45 + 0.6, 20000.0, 0.83, 7689.796, 3565.53 + 0.6, 20000.0, 0.85, 7875.056, 3653.63 + 0.6, 20000.0, 0.87, 8060.315, 3742.7 + 0.6, 20000.0, 0.89, 8245.572, 3832.73 + 0.6, 20000.0, 0.91, 8430.828, 3923.69 + 0.6, 20000.0, 0.93, 8616.085, 4015.55 + 0.6, 20000.0, 0.95, 8801.344, 4108.28 + 0.6, 20000.0, 0.97, 8986.604, 4201.84 + 0.6, 20000.0, 0.99, 9171.867, 4296.22 + 0.6, 25000.0, 0.0, 357.5994, 357.599 + 0.6, 25000.0, 0.05, 382.4, 433.7 + 0.6, 25000.0, 0.07, 535.3848, 500.532 + 0.6, 25000.0, 0.09, 688.3654, 566.225 + 0.6, 25000.0, 0.11, 841.3422, 630.875 + 0.6, 25000.0, 0.13, 994.3155, 694.58 + 0.6, 25000.0, 0.15, 1147.286, 757.436 + 0.6, 25000.0, 0.17, 1300.253, 819.54 + 0.6, 25000.0, 0.19, 1453.218, 880.99 + 0.6, 25000.0, 0.21, 1606.181, 941.883 + 0.6, 25000.0, 0.23, 1759.143, 1002.31 + 0.6, 25000.0, 0.25, 1912.103, 1062.38 + 0.6, 25000.0, 0.27, 2065.062, 1122.18 + 0.6, 25000.0, 0.29, 2218.021, 1181.82 + 0.6, 25000.0, 0.31, 2370.978, 1241.47 + 0.6, 25000.0, 0.33, 2523.935, 1301.23 + 0.6, 25000.0, 0.35, 2676.894, 1361.04 + 0.6, 25000.0, 0.37, 2829.854, 1420.94 + 0.6, 25000.0, 0.39, 2982.817, 1481.0 + 0.6, 25000.0, 0.41, 3135.79, 1541.44 + 0.6, 25000.0, 0.43, 3288.773, 1602.28 + 0.6, 25000.0, 0.45, 3441.756, 1663.27 + 0.6, 25000.0, 0.47, 3594.737, 1724.39 + 0.6, 25000.0, 0.49, 3747.714, 1785.59 + 0.6, 25000.0, 0.51, 3900.664, 1846.55 + 0.6, 25000.0, 0.53, 4053.59, 1907.3 + 0.6, 25000.0, 0.55, 4206.519, 1968.2 + 0.6, 25000.0, 0.57, 4359.457, 2029.34 + 0.6, 25000.0, 0.59, 4512.413, 2090.81 + 0.6, 25000.0, 0.61, 4665.437, 2152.75 + 0.6, 25000.0, 0.63, 4818.524, 2215.24 + 0.6, 25000.0, 0.65, 4971.619, 2278.29 + 0.6, 25000.0, 0.67, 5124.708, 2341.97 + 0.6, 25000.0, 0.69, 5277.777, 2406.34 + 0.6, 25000.0, 0.71, 5430.759, 2471.55 + 0.6, 25000.0, 0.73, 5583.652, 2537.65 + 0.6, 25000.0, 0.75, 5736.525, 2604.57 + 0.6, 25000.0, 0.77, 5889.39, 2672.33 + 0.6, 25000.0, 0.79, 6042.259, 2740.96 + 0.6, 25000.0, 0.81, 6195.188, 2810.61 + 0.6, 25000.0, 0.83, 6348.178, 2881.27 + 0.6, 25000.0, 0.85, 6501.181, 2952.76 + 0.6, 25000.0, 0.87, 6654.191, 3025.03 + 0.6, 25000.0, 0.89, 6807.199, 3098.04 + 0.6, 25000.0, 0.91, 6960.198, 3171.73 + 0.6, 25000.0, 0.93, 7113.182, 3246.06 + 0.6, 25000.0, 0.95, 7266.144, 3320.99 + 0.6, 25000.0, 0.97, 7419.075, 3396.46 + 0.6, 25000.0, 0.99, 7571.969, 3472.44 + 0.6, 30000.0, 0.0, 292.469, 292.469 + 0.6, 30000.0, 0.05, 316.2, 361.6 + 0.6, 30000.0, 0.07, 442.68, 414.773 + 0.6, 30000.0, 0.09, 569.16, 467.103 + 0.6, 30000.0, 0.11, 695.64, 518.662 + 0.6, 30000.0, 0.13, 822.12, 569.524 + 0.6, 30000.0, 0.15, 948.6, 619.761 + 0.6, 30000.0, 0.17, 1075.08, 669.446 + 0.6, 30000.0, 0.19, 1201.56, 718.653 + 0.6, 30000.0, 0.21, 1328.04, 767.455 + 0.6, 30000.0, 0.23, 1454.52, 815.923 + 0.6, 30000.0, 0.25, 1581.0, 864.133 + 0.6, 30000.0, 0.27, 1707.48, 912.156 + 0.6, 30000.0, 0.29, 1833.96, 960.065 + 0.6, 30000.0, 0.31, 1960.442, 1008.01 + 0.6, 30000.0, 0.33, 2086.925, 1056.04 + 0.6, 30000.0, 0.35, 2213.406, 1104.12 + 0.6, 30000.0, 0.37, 2339.886, 1152.29 + 0.6, 30000.0, 0.39, 2466.363, 1200.59 + 0.6, 30000.0, 0.41, 2592.83, 1249.21 + 0.6, 30000.0, 0.43, 2719.287, 1298.14 + 0.6, 30000.0, 0.45, 2845.744, 1347.21 + 0.6, 30000.0, 0.47, 2972.203, 1396.36 + 0.6, 30000.0, 0.49, 3098.666, 1445.58 + 0.6, 30000.0, 0.51, 3225.141, 1494.55 + 0.6, 30000.0, 0.53, 3351.629, 1543.31 + 0.6, 30000.0, 0.55, 3478.125, 1592.21 + 0.6, 30000.0, 0.57, 3604.629, 1641.34 + 0.6, 30000.0, 0.59, 3731.141, 1690.81 + 0.6, 30000.0, 0.61, 3857.677, 1740.82 + 0.6, 30000.0, 0.63, 3984.234, 1791.45 + 0.6, 30000.0, 0.65, 4110.787, 1842.59 + 0.6, 30000.0, 0.67, 4237.328, 1894.3 + 0.6, 30000.0, 0.69, 4363.849, 1946.61 + 0.6, 30000.0, 0.71, 4490.305, 1999.58 + 0.6, 30000.0, 0.73, 4616.695, 2053.23 + 0.6, 30000.0, 0.75, 4743.069, 2107.57 + 0.6, 30000.0, 0.77, 4869.437, 2162.62 + 0.6, 30000.0, 0.79, 4995.809, 2218.42 + 0.6, 30000.0, 0.81, 5122.224, 2275.17 + 0.6, 30000.0, 0.83, 5248.686, 2332.86 + 0.6, 30000.0, 0.85, 5375.162, 2391.22 + 0.6, 30000.0, 0.87, 5501.651, 2450.19 + 0.6, 30000.0, 0.89, 5628.149, 2509.68 + 0.6, 30000.0, 0.91, 5754.652, 2569.63 + 0.6, 30000.0, 0.93, 5881.158, 2629.97 + 0.6, 30000.0, 0.95, 6007.662, 2690.62 + 0.6, 30000.0, 0.97, 6134.163, 2751.53 + 0.6, 30000.0, 0.99, 6260.657, 2812.61 + 0.6, 35000.0, 0.0, 237.1112, 237.111 + 0.6, 35000.0, 0.05, 260.5, 303.3 + 0.6, 35000.0, 0.07, 364.6742, 345.171 + 0.6, 35000.0, 0.09, 468.8586, 386.474 + 0.6, 35000.0, 0.11, 573.052, 427.259 + 0.6, 35000.0, 0.13, 677.2531, 467.575 + 0.6, 35000.0, 0.15, 781.4607, 507.471 + 0.6, 35000.0, 0.17, 885.6736, 546.997 + 0.6, 35000.0, 0.19, 989.8904, 586.202 + 0.6, 35000.0, 0.21, 1094.11, 625.136 + 0.6, 35000.0, 0.23, 1198.331, 663.847 + 0.6, 35000.0, 0.25, 1302.553, 702.386 + 0.6, 35000.0, 0.27, 1406.773, 740.801 + 0.6, 35000.0, 0.29, 1510.992, 779.142 + 0.6, 35000.0, 0.31, 1615.203, 817.507 + 0.6, 35000.0, 0.33, 1719.406, 855.934 + 0.6, 35000.0, 0.35, 1823.606, 894.4 + 0.6, 35000.0, 0.37, 1927.805, 932.93 + 0.6, 35000.0, 0.39, 2032.002, 971.549 + 0.6, 35000.0, 0.41, 2136.2, 1010.37 + 0.6, 35000.0, 0.43, 2240.4, 1049.4 + 0.6, 35000.0, 0.45, 2344.6, 1088.54 + 0.6, 35000.0, 0.47, 2448.8, 1127.75 + 0.6, 35000.0, 0.49, 2553.0, 1167.04 + 0.6, 35000.0, 0.51, 2657.193, 1206.17 + 0.6, 35000.0, 0.53, 2761.382, 1245.18 + 0.6, 35000.0, 0.55, 2865.575, 1284.36 + 0.6, 35000.0, 0.57, 2969.776, 1323.77 + 0.6, 35000.0, 0.59, 3073.989, 1363.49 + 0.6, 35000.0, 0.61, 3178.238, 1403.72 + 0.6, 35000.0, 0.63, 3282.524, 1444.5 + 0.6, 35000.0, 0.65, 3386.812, 1485.76 + 0.6, 35000.0, 0.67, 3491.098, 1527.53 + 0.6, 35000.0, 0.69, 3595.37, 1569.83 + 0.6, 35000.0, 0.71, 3699.594, 1612.78 + 0.6, 35000.0, 0.73, 3803.767, 1656.38 + 0.6, 35000.0, 0.75, 3907.925, 1700.55 + 0.6, 35000.0, 0.77, 4012.075, 1745.3 + 0.6, 35000.0, 0.79, 4116.224, 1790.62 + 0.6, 35000.0, 0.81, 4220.396, 1836.54 + 0.6, 35000.0, 0.83, 4324.593, 1883.04 + 0.6, 35000.0, 0.85, 4428.794, 1930.09 + 0.6, 35000.0, 0.87, 4532.997, 1977.67 + 0.6, 35000.0, 0.89, 4637.2, 2025.76 + 0.6, 35000.0, 0.91, 4741.399, 2074.36 + 0.6, 35000.0, 0.93, 4845.594, 2123.45 + 0.6, 35000.0, 0.95, 4949.781, 2173.01 + 0.6, 35000.0, 0.97, 5053.958, 2223.04 + 0.6, 35000.0, 0.99, 5158.123, 2273.5 + 0.6, 40000.0, 0.0, 187.6504, 187.65 + 0.6, 40000.0, 0.05, 207.5, 260.4 + 0.6, 40000.0, 0.07, 290.5066, 292.531 + 0.6, 40000.0, 0.09, 373.5214, 324.359 + 0.6, 40000.0, 0.11, 456.5431, 355.912 + 0.6, 40000.0, 0.13, 539.5709, 387.216 + 0.6, 40000.0, 0.15, 622.6036, 418.296 + 0.6, 40000.0, 0.17, 705.6401, 449.181 + 0.6, 40000.0, 0.19, 788.6796, 479.897 + 0.6, 40000.0, 0.21, 871.7208, 510.47 + 0.6, 40000.0, 0.23, 954.7627, 540.928 + 0.6, 40000.0, 0.25, 1037.804, 571.296 + 0.6, 40000.0, 0.27, 1120.845, 601.601 + 0.6, 40000.0, 0.29, 1203.882, 631.87 + 0.6, 40000.0, 0.31, 1286.913, 662.143 + 0.6, 40000.0, 0.33, 1369.936, 692.441 + 0.6, 40000.0, 0.35, 1452.956, 722.775 + 0.6, 40000.0, 0.37, 1535.975, 753.165 + 0.6, 40000.0, 0.39, 1618.992, 783.631 + 0.6, 40000.0, 0.41, 1702.01, 814.275 + 0.6, 40000.0, 0.43, 1785.03, 845.097 + 0.6, 40000.0, 0.45, 1868.05, 876.0 + 0.6, 40000.0, 0.47, 1951.07, 906.967 + 0.6, 40000.0, 0.49, 2034.09, 937.981 + 0.6, 40000.0, 0.51, 2117.11, 968.865 + 0.6, 40000.0, 0.53, 2200.13, 999.641 + 0.6, 40000.0, 0.55, 2283.15, 1030.52 + 0.6, 40000.0, 0.57, 2366.17, 1061.58 + 0.6, 40000.0, 0.59, 2449.19, 1092.86 + 0.6, 40000.0, 0.61, 2532.207, 1124.48 + 0.6, 40000.0, 0.63, 2615.221, 1156.48 + 0.6, 40000.0, 0.65, 2698.238, 1188.85 + 0.6, 40000.0, 0.67, 2781.258, 1221.62 + 0.6, 40000.0, 0.69, 2864.284, 1254.82 + 0.6, 40000.0, 0.71, 2947.328, 1288.57 + 0.6, 40000.0, 0.73, 3030.387, 1322.86 + 0.6, 40000.0, 0.75, 3113.45, 1357.64 + 0.6, 40000.0, 0.77, 3196.513, 1392.9 + 0.6, 40000.0, 0.79, 3279.572, 1428.65 + 0.6, 40000.0, 0.81, 3362.617, 1464.88 + 0.6, 40000.0, 0.83, 3445.646, 1501.6 + 0.6, 40000.0, 0.85, 3528.669, 1538.81 + 0.6, 40000.0, 0.87, 3611.685, 1576.49 + 0.6, 40000.0, 0.89, 3694.696, 1614.64 + 0.6, 40000.0, 0.91, 3777.703, 1653.27 + 0.6, 40000.0, 0.93, 3860.706, 1692.37 + 0.6, 40000.0, 0.95, 3943.706, 1731.94 + 0.6, 40000.0, 0.97, 4026.705, 1771.98 + 0.6, 40000.0, 0.99, 4109.702, 1812.48 + 0.6, 43000.0, 0.0, 162.546, 162.546 + 0.6, 43000.0, 0.05, 178.7, 241.4 + 0.6, 43000.0, 0.07, 251.3383, 268.732 + 0.6, 43000.0, 0.09, 323.7532, 295.846 + 0.6, 43000.0, 0.11, 395.9729, 322.757 + 0.6, 43000.0, 0.13, 468.0256, 349.483 + 0.6, 43000.0, 0.15, 539.9393, 376.039 + 0.6, 43000.0, 0.17, 611.7421, 402.443 + 0.6, 43000.0, 0.19, 683.4622, 428.712 + 0.6, 43000.0, 0.21, 755.1277, 454.861 + 0.6, 43000.0, 0.23, 826.7666, 480.907 + 0.6, 43000.0, 0.25, 898.4071, 506.867 + 0.6, 43000.0, 0.27, 970.0774, 532.758 + 0.6, 43000.0, 0.29, 1041.805, 558.596 + 0.6, 43000.0, 0.31, 1113.76, 584.278 + 0.6, 43000.0, 0.33, 1185.935, 609.85 + 0.6, 43000.0, 0.35, 1258.15, 635.506 + 0.6, 43000.0, 0.37, 1330.365, 661.32 + 0.6, 43000.0, 0.39, 1402.54, 687.366 + 0.6, 43000.0, 0.41, 1474.486, 714.163 + 0.6, 43000.0, 0.43, 1546.2, 741.678 + 0.6, 43000.0, 0.45, 1617.862, 769.325 + 0.6, 43000.0, 0.47, 1689.504, 796.964 + 0.6, 43000.0, 0.49, 1761.158, 824.455 + 0.6, 43000.0, 0.51, 1832.962, 851.023 + 0.6, 43000.0, 0.53, 1904.922, 876.683 + 0.6, 43000.0, 0.55, 1976.912, 902.231 + 0.6, 43000.0, 0.57, 2048.915, 927.833 + 0.6, 43000.0, 0.59, 2120.911, 953.655 + 0.6, 43000.0, 0.61, 2192.811, 980.179 + 0.6, 43000.0, 0.63, 2264.613, 1007.49 + 0.6, 43000.0, 0.65, 2336.4, 1035.29 + 0.6, 43000.0, 0.67, 2408.187, 1063.59 + 0.6, 43000.0, 0.69, 2479.989, 1092.4 + 0.6, 43000.0, 0.71, 2551.889, 1121.89 + 0.6, 43000.0, 0.73, 2623.885, 1152.04 + 0.6, 43000.0, 0.75, 2695.887, 1182.61 + 0.6, 43000.0, 0.77, 2767.878, 1213.55 + 0.6, 43000.0, 0.79, 2839.838, 1244.79 + 0.6, 43000.0, 0.81, 2911.666, 1275.97 + 0.6, 43000.0, 0.83, 2983.364, 1307.1 + 0.6, 43000.0, 0.85, 3055.031, 1338.54 + 0.6, 43000.0, 0.87, 3126.689, 1370.37 + 0.6, 43000.0, 0.89, 3198.356, 1402.66 + 0.6, 43000.0, 0.91, 3270.054, 1435.48 + 0.6, 43000.0, 0.93, 3341.801, 1468.92 + 0.6, 43000.0, 0.95, 3413.619, 1503.03 + 0.6, 43000.0, 0.97, 3485.526, 1537.91 + 0.6, 43000.0, 0.99, 3557.544, 1573.61 + 0.6, 48000.0, 0.0, 127.9566, 127.957 + 0.6, 48000.0, 0.05, 141.3, 191.1 + 0.6, 48000.0, 0.07, 198.4556, 212.545 + 0.6, 48000.0, 0.09, 255.4589, 233.796 + 0.6, 48000.0, 0.11, 312.3264, 254.87 + 0.6, 48000.0, 0.13, 369.075, 275.786 + 0.6, 48000.0, 0.15, 425.7214, 296.561 + 0.6, 48000.0, 0.17, 482.2823, 317.213 + 0.6, 48000.0, 0.19, 538.7745, 337.76 + 0.6, 48000.0, 0.21, 595.2146, 358.221 + 0.6, 48000.0, 0.23, 651.6194, 378.612 + 0.6, 48000.0, 0.25, 708.0057, 398.953 + 0.6, 48000.0, 0.27, 764.3902, 419.261 + 0.6, 48000.0, 0.29, 820.7895, 439.554 + 0.6, 48000.0, 0.31, 877.255, 459.796 + 0.6, 48000.0, 0.33, 933.795, 480.018 + 0.6, 48000.0, 0.35, 990.375, 500.319 + 0.6, 48000.0, 0.37, 1046.995, 520.741 + 0.6, 48000.0, 0.39, 1103.655, 541.33 + 0.6, 48000.0, 0.41, 1160.38, 562.42 + 0.6, 48000.0, 0.43, 1217.163, 583.986 + 0.6, 48000.0, 0.45, 1273.969, 605.638 + 0.6, 48000.0, 0.47, 1330.784, 627.277 + 0.6, 48000.0, 0.49, 1387.598, 648.807 + 0.6, 48000.0, 0.51, 1444.404, 669.656 + 0.6, 48000.0, 0.53, 1501.189, 689.841 + 0.6, 48000.0, 0.55, 1557.931, 709.969 + 0.6, 48000.0, 0.57, 1614.616, 730.17 + 0.6, 48000.0, 0.59, 1671.227, 750.578 + 0.6, 48000.0, 0.61, 1727.606, 771.628 + 0.6, 48000.0, 0.63, 1783.773, 793.38 + 0.6, 48000.0, 0.65, 1839.925, 815.512 + 0.6, 48000.0, 0.67, 1896.117, 838.008 + 0.6, 48000.0, 0.69, 1952.404, 860.852 + 0.6, 48000.0, 0.71, 2009.099, 884.033 + 0.6, 48000.0, 0.73, 2066.193, 907.534 + 0.6, 48000.0, 0.75, 2123.356, 931.331 + 0.6, 48000.0, 0.77, 2180.518, 955.406 + 0.6, 48000.0, 0.79, 2237.606, 979.741 + 0.6, 48000.0, 0.81, 2294.32, 1004.18 + 0.6, 48000.0, 0.83, 2350.645, 1028.74 + 0.6, 48000.0, 0.85, 2406.85, 1053.6 + 0.6, 48000.0, 0.87, 2462.975, 1078.81 + 0.6, 48000.0, 0.89, 2519.06, 1104.43 + 0.6, 48000.0, 0.91, 2575.145, 1130.49 + 0.6, 48000.0, 0.93, 2631.27, 1157.05 + 0.6, 48000.0, 0.95, 2687.475, 1184.15 + 0.6, 48000.0, 0.97, 2743.8, 1211.84 + 0.6, 48000.0, 0.99, 2800.285, 1240.18 + 0.65, 0.0, 0.0, 906.8784, 906.878 + 0.65, 0.0, 0.05, 647.8938, 1247.0 + 0.65, 0.0, 0.07, 918.6615, 1378.94 + 0.65, 0.0, 0.09, 1188.774, 1511.34 + 0.65, 0.0, 0.11, 1458.28, 1644.15 + 0.65, 0.0, 0.13, 1727.225, 1777.3 + 0.65, 0.0, 0.15, 1995.656, 1910.73 + 0.65, 0.0, 0.17, 2263.622, 2044.37 + 0.65, 0.0, 0.19, 2531.169, 2178.16 + 0.65, 0.0, 0.21, 2798.344, 2312.05 + 0.65, 0.0, 0.23, 3065.195, 2445.97 + 0.65, 0.0, 0.25, 3331.769, 2579.85 + 0.65, 0.0, 0.27, 3598.112, 2713.64 + 0.65, 0.0, 0.29, 3864.273, 2847.26 + 0.65, 0.0, 0.31, 4130.299, 2980.67 + 0.65, 0.0, 0.33, 4396.236, 3113.8 + 0.65, 0.0, 0.35, 4662.131, 3246.58 + 0.65, 0.0, 0.37, 4928.033, 3378.95 + 0.65, 0.0, 0.39, 5193.988, 3510.85 + 0.65, 0.0, 0.41, 5460.169, 3641.65 + 0.65, 0.0, 0.43, 5726.592, 3771.42 + 0.65, 0.0, 0.45, 5993.119, 3900.96 + 0.65, 0.0, 0.47, 6259.736, 4030.45 + 0.65, 0.0, 0.49, 6526.429, 4160.13 + 0.65, 0.0, 0.51, 6793.231, 4290.89 + 0.65, 0.0, 0.53, 7060.118, 4422.77 + 0.65, 0.0, 0.55, 7327.006, 4554.96 + 0.65, 0.0, 0.57, 7593.861, 4687.34 + 0.65, 0.0, 0.59, 7860.645, 4819.79 + 0.65, 0.0, 0.61, 8127.243, 4952.02 + 0.65, 0.0, 0.63, 8393.637, 5083.94 + 0.65, 0.0, 0.65, 8659.913, 5215.67 + 0.65, 0.0, 0.67, 8926.072, 5347.18 + 0.65, 0.0, 0.69, 9192.118, 5478.4 + 0.65, 0.0, 0.71, 9457.916, 5608.92 + 0.65, 0.0, 0.73, 9723.503, 5738.76 + 0.65, 0.0, 0.75, 9989.088, 5868.49 + 0.65, 0.0, 0.77, 10254.74, 5998.23 + 0.65, 0.0, 0.79, 10520.53, 6128.14 + 0.65, 0.0, 0.81, 10786.83, 6258.47 + 0.65, 0.0, 0.83, 11053.62, 6389.35 + 0.65, 0.0, 0.85, 11320.56, 6520.75 + 0.65, 0.0, 0.87, 11587.55, 6652.76 + 0.65, 0.0, 0.89, 11854.53, 6785.46 + 0.65, 0.0, 0.91, 12121.44, 6918.95 + 0.65, 0.0, 0.93, 12388.18, 7053.32 + 0.65, 0.0, 0.95, 12654.69, 7188.65 + 0.65, 0.0, 0.97, 12920.91, 7325.04 + 0.65, 0.0, 0.99, 13186.74, 7462.57 + 0.65, 2000.0, 0.0, 849.0882, 849.088 + 0.65, 2000.0, 0.05, 641.5187, 1111.76 + 0.65, 2000.0, 0.07, 899.8677, 1251.66 + 0.65, 2000.0, 0.09, 1158.005, 1389.89 + 0.65, 2000.0, 0.11, 1415.949, 1526.53 + 0.65, 2000.0, 0.13, 1673.718, 1661.7 + 0.65, 2000.0, 0.15, 1931.331, 1795.49 + 0.65, 2000.0, 0.17, 2188.806, 1928.0 + 0.65, 2000.0, 0.19, 2446.161, 2059.34 + 0.65, 2000.0, 0.21, 2703.416, 2189.6 + 0.65, 2000.0, 0.23, 2960.587, 2318.89 + 0.65, 2000.0, 0.25, 3217.694, 2447.31 + 0.65, 2000.0, 0.27, 3474.755, 2574.96 + 0.65, 2000.0, 0.29, 3731.788, 2701.93 + 0.65, 2000.0, 0.31, 3988.812, 2828.34 + 0.65, 2000.0, 0.33, 4245.845, 2954.27 + 0.65, 2000.0, 0.35, 4502.906, 3079.84 + 0.65, 2000.0, 0.37, 4760.013, 3205.14 + 0.65, 2000.0, 0.39, 5017.184, 3330.27 + 0.65, 2000.0, 0.41, 5274.538, 3455.43 + 0.65, 2000.0, 0.43, 5532.067, 3580.69 + 0.65, 2000.0, 0.45, 5789.644, 3706.03 + 0.65, 2000.0, 0.47, 6047.239, 3831.48 + 0.65, 2000.0, 0.49, 6304.822, 3957.1 + 0.65, 2000.0, 0.51, 6562.285, 4083.36 + 0.65, 2000.0, 0.53, 6819.617, 4210.21 + 0.65, 2000.0, 0.55, 7076.906, 4337.1 + 0.65, 2000.0, 0.57, 7334.162, 4463.9 + 0.65, 2000.0, 0.59, 7591.392, 4590.45 + 0.65, 2000.0, 0.61, 7848.531, 4716.01 + 0.65, 2000.0, 0.63, 8105.607, 4840.56 + 0.65, 2000.0, 0.65, 8362.738, 4964.92 + 0.65, 2000.0, 0.67, 8619.968, 5089.24 + 0.65, 2000.0, 0.69, 8877.344, 5213.68 + 0.65, 2000.0, 0.71, 9135.313, 5339.08 + 0.65, 2000.0, 0.73, 9393.823, 5465.45 + 0.65, 2000.0, 0.75, 9652.319, 5591.95 + 0.65, 2000.0, 0.77, 9910.648, 5718.42 + 0.65, 2000.0, 0.79, 10168.66, 5844.69 + 0.65, 2000.0, 0.81, 10425.45, 5969.07 + 0.65, 2000.0, 0.83, 10681.04, 6091.77 + 0.65, 2000.0, 0.85, 10936.41, 6214.91 + 0.65, 2000.0, 0.87, 11191.78, 6339.07 + 0.65, 2000.0, 0.89, 11447.36, 6464.83 + 0.65, 2000.0, 0.91, 11703.37, 6592.79 + 0.65, 2000.0, 0.93, 11960.02, 6723.51 + 0.65, 2000.0, 0.95, 12217.54, 6857.59 + 0.65, 2000.0, 0.97, 12476.13, 6995.61 + 0.65, 2000.0, 0.99, 12736.01, 7138.15 + 0.65, 5000.0, 0.0, 767.9125, 767.913 + 0.65, 5000.0, 0.05, 652.65, 986.05 + 0.65, 5000.0, 0.07, 889.7462, 1124.32 + 0.65, 5000.0, 0.09, 1128.198, 1259.83 + 0.65, 5000.0, 0.11, 1367.903, 1392.75 + 0.65, 5000.0, 0.13, 1608.763, 1523.29 + 0.65, 5000.0, 0.15, 1850.675, 1651.63 + 0.65, 5000.0, 0.17, 2093.539, 1777.95 + 0.65, 5000.0, 0.19, 2337.255, 1902.47 + 0.65, 5000.0, 0.21, 2581.72, 2025.35 + 0.65, 5000.0, 0.23, 2826.836, 2146.8 + 0.65, 5000.0, 0.25, 3072.5, 2267.0 + 0.65, 5000.0, 0.27, 3318.612, 2386.15 + 0.65, 5000.0, 0.29, 3565.072, 2504.43 + 0.65, 5000.0, 0.31, 3811.777, 2622.03 + 0.65, 5000.0, 0.33, 4058.629, 2739.15 + 0.65, 5000.0, 0.35, 4305.525, 2855.98 + 0.65, 5000.0, 0.37, 4552.365, 2972.7 + 0.65, 5000.0, 0.39, 4799.049, 3089.5 + 0.65, 5000.0, 0.41, 5045.126, 3207.25 + 0.65, 5000.0, 0.43, 5290.582, 3325.97 + 0.65, 5000.0, 0.45, 5535.831, 3444.86 + 0.65, 5000.0, 0.47, 5780.943, 3563.8 + 0.65, 5000.0, 0.49, 6025.984, 3682.65 + 0.65, 5000.0, 0.51, 6271.121, 3800.72 + 0.65, 5000.0, 0.53, 6516.398, 3918.02 + 0.65, 5000.0, 0.55, 6761.738, 4035.24 + 0.65, 5000.0, 0.57, 7007.161, 4152.53 + 0.65, 5000.0, 0.59, 7252.69, 4270.03 + 0.65, 5000.0, 0.61, 7498.397, 4388.24 + 0.65, 5000.0, 0.63, 7744.29, 4507.22 + 0.65, 5000.0, 0.65, 7990.313, 4626.55 + 0.65, 5000.0, 0.67, 8236.459, 4746.2 + 0.65, 5000.0, 0.69, 8482.724, 4866.14 + 0.65, 5000.0, 0.71, 8729.241, 4986.46 + 0.65, 5000.0, 0.73, 8975.971, 5107.1 + 0.65, 5000.0, 0.75, 9222.706, 5227.79 + 0.65, 5000.0, 0.77, 9469.376, 5348.45 + 0.65, 5000.0, 0.79, 9715.908, 5468.94 + 0.65, 5000.0, 0.81, 9961.896, 5587.99 + 0.65, 5000.0, 0.83, 10207.35, 5705.76 + 0.65, 5000.0, 0.85, 10452.7, 5823.92 + 0.65, 5000.0, 0.87, 10698.03, 5942.94 + 0.65, 5000.0, 0.89, 10943.44, 6063.28 + 0.65, 5000.0, 0.91, 11189.01, 6185.43 + 0.65, 5000.0, 0.93, 11434.84, 6309.84 + 0.65, 5000.0, 0.95, 11681.02, 6436.98 + 0.65, 5000.0, 0.97, 11927.65, 6567.33 + 0.65, 5000.0, 0.99, 12174.8, 6701.36 + 0.65, 10000.0, 0.0, 646.3907, 646.391 + 0.65, 10000.0, 0.05, 466.95, 850.606 + 0.65, 10000.0, 0.07, 676.888, 954.461 + 0.65, 10000.0, 0.09, 885.37, 1057.43 + 0.65, 10000.0, 0.11, 1092.508, 1159.56 + 0.65, 10000.0, 0.13, 1298.414, 1260.9 + 0.65, 10000.0, 0.15, 1503.2, 1361.49 + 0.65, 10000.0, 0.17, 1706.978, 1461.38 + 0.65, 10000.0, 0.19, 1909.86, 1560.62 + 0.65, 10000.0, 0.21, 2111.958, 1659.24 + 0.65, 10000.0, 0.23, 2313.384, 1757.29 + 0.65, 10000.0, 0.25, 2514.25, 1854.83 + 0.65, 10000.0, 0.27, 2714.668, 1951.89 + 0.65, 10000.0, 0.29, 2914.75, 2048.53 + 0.65, 10000.0, 0.31, 3114.608, 2144.78 + 0.65, 10000.0, 0.33, 3314.354, 2240.7 + 0.65, 10000.0, 0.35, 3514.1, 2336.32 + 0.65, 10000.0, 0.37, 3713.958, 2431.7 + 0.65, 10000.0, 0.39, 3914.04, 2526.87 + 0.65, 10000.0, 0.41, 4114.894, 2621.86 + 0.65, 10000.0, 0.43, 4316.525, 2716.73 + 0.65, 10000.0, 0.45, 4518.4, 2811.54 + 0.65, 10000.0, 0.47, 4720.419, 2906.38 + 0.65, 10000.0, 0.49, 4922.482, 3001.29 + 0.65, 10000.0, 0.51, 5124.388, 3096.81 + 0.65, 10000.0, 0.53, 5326.061, 3192.88 + 0.65, 10000.0, 0.55, 5527.556, 3288.86 + 0.65, 10000.0, 0.57, 5728.826, 3384.6 + 0.65, 10000.0, 0.59, 5929.821, 3479.94 + 0.65, 10000.0, 0.61, 6129.979, 3574.11 + 0.65, 10000.0, 0.63, 6329.376, 3667.1 + 0.65, 10000.0, 0.65, 6528.725, 3759.61 + 0.65, 10000.0, 0.67, 6728.226, 3851.77 + 0.65, 10000.0, 0.69, 6928.079, 3943.69 + 0.65, 10000.0, 0.71, 7129.144, 4034.85 + 0.65, 10000.0, 0.73, 7331.461, 4125.53 + 0.65, 10000.0, 0.75, 7534.25, 4216.79 + 0.65, 10000.0, 0.77, 7737.391, 4309.09 + 0.65, 10000.0, 0.79, 7940.764, 4402.84 + 0.65, 10000.0, 0.81, 8144.427, 4500.56 + 0.65, 10000.0, 0.83, 8348.217, 4602.19 + 0.65, 10000.0, 0.85, 8551.75, 4705.06 + 0.65, 10000.0, 0.87, 8754.819, 4808.59 + 0.65, 10000.0, 0.89, 8957.217, 4912.23 + 0.65, 10000.0, 0.91, 9158.738, 5015.38 + 0.65, 10000.0, 0.93, 9359.176, 5117.48 + 0.65, 10000.0, 0.95, 9558.325, 5217.94 + 0.65, 10000.0, 0.97, 9755.978, 5316.2 + 0.65, 10000.0, 0.99, 9951.928, 5411.68 + 0.65, 15000.0, 0.0, 540.6291, 540.629 + 0.65, 15000.0, 0.05, 562.875, 669.456 + 0.65, 15000.0, 0.07, 788.0318, 779.716 + 0.65, 15000.0, 0.09, 1013.174, 887.876 + 0.65, 15000.0, 0.11, 1238.303, 994.115 + 0.65, 15000.0, 0.13, 1463.422, 1098.61 + 0.65, 15000.0, 0.15, 1688.533, 1201.54 + 0.65, 15000.0, 0.17, 1913.637, 1303.08 + 0.65, 15000.0, 0.19, 2138.738, 1403.41 + 0.65, 15000.0, 0.21, 2363.837, 1502.71 + 0.65, 15000.0, 0.23, 2588.936, 1601.16 + 0.65, 15000.0, 0.25, 2814.038, 1698.93 + 0.65, 15000.0, 0.27, 3039.145, 1796.2 + 0.65, 15000.0, 0.29, 3264.259, 1893.15 + 0.65, 15000.0, 0.31, 3489.394, 1990.19 + 0.65, 15000.0, 0.33, 3714.551, 2087.46 + 0.65, 15000.0, 0.35, 3939.712, 2184.76 + 0.65, 15000.0, 0.37, 4164.874, 2282.16 + 0.65, 15000.0, 0.39, 4390.031, 2379.72 + 0.65, 15000.0, 0.41, 4615.167, 2477.75 + 0.65, 15000.0, 0.43, 4840.281, 2576.25 + 0.65, 15000.0, 0.45, 5065.388, 2674.92 + 0.65, 15000.0, 0.47, 5290.49, 2773.69 + 0.65, 15000.0, 0.49, 5515.589, 2872.52 + 0.65, 15000.0, 0.51, 5740.688, 2970.95 + 0.65, 15000.0, 0.53, 5965.79, 3069.01 + 0.65, 15000.0, 0.55, 6190.893, 3167.24 + 0.65, 15000.0, 0.57, 6416.0, 3265.76 + 0.65, 15000.0, 0.59, 6641.111, 3364.7 + 0.65, 15000.0, 0.61, 6866.219, 3464.22 + 0.65, 15000.0, 0.63, 7091.326, 3564.43 + 0.65, 15000.0, 0.65, 7316.448, 3665.45 + 0.65, 15000.0, 0.67, 7541.591, 3767.4 + 0.65, 15000.0, 0.69, 7766.76, 3870.4 + 0.65, 15000.0, 0.71, 7992.013, 3974.79 + 0.65, 15000.0, 0.73, 8217.342, 4080.63 + 0.65, 15000.0, 0.75, 8442.678, 4187.74 + 0.65, 15000.0, 0.77, 8668.001, 4296.15 + 0.65, 15000.0, 0.79, 8893.292, 4405.88 + 0.65, 15000.0, 0.81, 9118.459, 4517.06 + 0.65, 15000.0, 0.83, 9343.501, 4629.69 + 0.65, 15000.0, 0.85, 9568.506, 4743.63 + 0.65, 15000.0, 0.87, 9793.489, 4858.86 + 0.65, 15000.0, 0.89, 10018.47, 4975.36 + 0.65, 15000.0, 0.91, 10243.45, 5093.1 + 0.65, 15000.0, 0.93, 10468.46, 5212.04 + 0.65, 15000.0, 0.95, 10693.51, 5332.18 + 0.65, 15000.0, 0.97, 10918.62, 5453.47 + 0.65, 15000.0, 0.99, 11143.8, 5575.89 + 0.65, 20000.0, 0.0, 449.072, 449.072 + 0.65, 20000.0, 0.05, 465.6813, 552.456 + 0.65, 20000.0, 0.07, 651.9665, 641.04 + 0.65, 20000.0, 0.09, 838.2472, 727.983 + 0.65, 20000.0, 0.11, 1024.524, 813.423 + 0.65, 20000.0, 0.13, 1210.798, 897.5 + 0.65, 20000.0, 0.15, 1397.068, 980.354 + 0.65, 20000.0, 0.17, 1583.337, 1062.12 + 0.65, 20000.0, 0.19, 1769.604, 1142.95 + 0.65, 20000.0, 0.21, 1955.871, 1222.97 + 0.65, 20000.0, 0.23, 2142.137, 1302.32 + 0.65, 20000.0, 0.25, 2328.403, 1381.14 + 0.65, 20000.0, 0.27, 2514.671, 1459.58 + 0.65, 20000.0, 0.29, 2700.94, 1537.77 + 0.65, 20000.0, 0.31, 2887.214, 1616.03 + 0.65, 20000.0, 0.33, 3073.493, 1694.47 + 0.65, 20000.0, 0.35, 3259.773, 1772.93 + 0.65, 20000.0, 0.37, 3446.054, 1851.48 + 0.65, 20000.0, 0.39, 3632.335, 1930.17 + 0.65, 20000.0, 0.41, 3818.614, 2009.24 + 0.65, 20000.0, 0.43, 4004.89, 2088.69 + 0.65, 20000.0, 0.45, 4191.164, 2168.28 + 0.65, 20000.0, 0.47, 4377.436, 2247.95 + 0.65, 20000.0, 0.49, 4563.704, 2327.65 + 0.65, 20000.0, 0.51, 4749.956, 2406.98 + 0.65, 20000.0, 0.53, 4936.193, 2485.98 + 0.65, 20000.0, 0.55, 5122.436, 2565.12 + 0.65, 20000.0, 0.57, 5308.691, 2644.53 + 0.65, 20000.0, 0.59, 5494.966, 2724.33 + 0.65, 20000.0, 0.61, 5681.305, 2804.73 + 0.65, 20000.0, 0.63, 5867.705, 2885.82 + 0.65, 20000.0, 0.65, 6054.116, 2967.62 + 0.65, 20000.0, 0.67, 6240.524, 3050.2 + 0.65, 20000.0, 0.69, 6426.918, 3133.64 + 0.65, 20000.0, 0.71, 6613.247, 3218.14 + 0.65, 20000.0, 0.73, 6799.507, 3303.76 + 0.65, 20000.0, 0.75, 6985.745, 3390.42 + 0.65, 20000.0, 0.77, 7171.966, 3478.14 + 0.65, 20000.0, 0.79, 7358.177, 3566.96 + 0.65, 20000.0, 0.81, 7544.397, 3657.07 + 0.65, 20000.0, 0.83, 7730.63, 3748.45 + 0.65, 20000.0, 0.85, 7916.864, 3840.92 + 0.65, 20000.0, 0.87, 8103.099, 3934.41 + 0.65, 20000.0, 0.89, 8289.336, 4028.9 + 0.65, 20000.0, 0.91, 8475.577, 4124.32 + 0.65, 20000.0, 0.93, 8661.821, 4220.64 + 0.65, 20000.0, 0.95, 8848.069, 4317.82 + 0.65, 20000.0, 0.97, 9034.322, 4415.8 + 0.65, 20000.0, 0.99, 9220.581, 4514.54 + 0.65, 25000.0, 0.0, 370.2552, 370.255 + 0.65, 25000.0, 0.05, 383.74, 456.21 + 0.65, 25000.0, 0.07, 537.2147, 526.958 + 0.65, 25000.0, 0.09, 690.6945, 596.427 + 0.65, 25000.0, 0.11, 844.1788, 664.726 + 0.65, 25000.0, 0.13, 997.6668, 731.965 + 0.65, 25000.0, 0.15, 1151.158, 798.253 + 0.65, 25000.0, 0.17, 1304.651, 863.7 + 0.65, 25000.0, 0.19, 1458.147, 928.414 + 0.65, 25000.0, 0.21, 1611.643, 992.504 + 0.65, 25000.0, 0.23, 1765.14, 1056.08 + 0.65, 25000.0, 0.25, 1918.637, 1119.25 + 0.65, 25000.0, 0.27, 2072.134, 1182.13 + 0.65, 25000.0, 0.29, 2225.628, 1244.82 + 0.65, 25000.0, 0.31, 2379.118, 1307.58 + 0.65, 25000.0, 0.33, 2532.602, 1370.47 + 0.65, 25000.0, 0.35, 2686.086, 1433.41 + 0.65, 25000.0, 0.37, 2839.569, 1496.42 + 0.65, 25000.0, 0.39, 2993.053, 1559.55 + 0.65, 25000.0, 0.41, 3146.544, 1623.02 + 0.65, 25000.0, 0.43, 3300.042, 1686.83 + 0.65, 25000.0, 0.45, 3453.539, 1750.75 + 0.65, 25000.0, 0.47, 3607.033, 1814.73 + 0.65, 25000.0, 0.49, 3760.523, 1878.72 + 0.65, 25000.0, 0.51, 3913.985, 1942.33 + 0.65, 25000.0, 0.53, 4067.424, 2005.6 + 0.65, 25000.0, 0.55, 4220.867, 2068.98 + 0.65, 25000.0, 0.57, 4374.322, 2132.61 + 0.65, 25000.0, 0.59, 4527.797, 2196.6 + 0.65, 25000.0, 0.61, 4681.348, 2261.21 + 0.65, 25000.0, 0.63, 4834.971, 2326.52 + 0.65, 25000.0, 0.65, 4988.604, 2392.46 + 0.65, 25000.0, 0.67, 5142.23, 2459.07 + 0.65, 25000.0, 0.69, 5295.835, 2526.41 + 0.65, 25000.0, 0.71, 5449.343, 2594.58 + 0.65, 25000.0, 0.73, 5602.753, 2663.62 + 0.65, 25000.0, 0.75, 5756.14, 2733.52 + 0.65, 25000.0, 0.77, 5909.519, 2804.31 + 0.65, 25000.0, 0.79, 6062.905, 2876.01 + 0.65, 25000.0, 0.81, 6216.36, 2948.83 + 0.65, 25000.0, 0.83, 6369.888, 3022.77 + 0.65, 25000.0, 0.85, 6523.429, 3097.58 + 0.65, 25000.0, 0.87, 6676.976, 3173.2 + 0.65, 25000.0, 0.89, 6830.518, 3249.58 + 0.65, 25000.0, 0.91, 6984.047, 3326.65 + 0.65, 25000.0, 0.93, 7137.554, 3404.36 + 0.65, 25000.0, 0.95, 7291.028, 3482.64 + 0.65, 25000.0, 0.97, 7444.462, 3561.45 + 0.65, 25000.0, 0.99, 7597.845, 3640.72 + 0.65, 30000.0, 0.0, 302.8197, 302.82 + 0.65, 30000.0, 0.05, 316.37, 378.56 + 0.65, 30000.0, 0.07, 442.9236, 434.657 + 0.65, 30000.0, 0.09, 569.4723, 489.839 + 0.65, 30000.0, 0.11, 696.017, 544.183 + 0.65, 30000.0, 0.13, 822.5582, 597.767 + 0.65, 30000.0, 0.15, 949.0966, 650.668 + 0.65, 30000.0, 0.17, 1075.633, 702.962 + 0.65, 30000.0, 0.19, 1202.168, 754.727 + 0.65, 30000.0, 0.21, 1328.702, 806.04 + 0.65, 30000.0, 0.23, 1455.236, 856.978 + 0.65, 30000.0, 0.25, 1581.771, 907.617 + 0.65, 30000.0, 0.27, 1708.307, 958.037 + 0.65, 30000.0, 0.29, 1834.845, 1008.31 + 0.65, 30000.0, 0.31, 1961.391, 1058.6 + 0.65, 30000.0, 0.33, 2087.944, 1108.97 + 0.65, 30000.0, 0.35, 2214.497, 1159.37 + 0.65, 30000.0, 0.37, 2341.049, 1209.82 + 0.65, 30000.0, 0.39, 2467.597, 1260.38 + 0.65, 30000.0, 0.41, 2594.132, 1311.23 + 0.65, 30000.0, 0.43, 2720.653, 1362.36 + 0.65, 30000.0, 0.45, 2847.172, 1413.6 + 0.65, 30000.0, 0.47, 2973.692, 1464.89 + 0.65, 30000.0, 0.49, 3100.216, 1516.19 + 0.65, 30000.0, 0.51, 3226.752, 1567.17 + 0.65, 30000.0, 0.53, 3353.301, 1617.85 + 0.65, 30000.0, 0.55, 3479.859, 1668.66 + 0.65, 30000.0, 0.57, 3606.425, 1719.69 + 0.65, 30000.0, 0.59, 3732.999, 1771.07 + 0.65, 30000.0, 0.61, 3859.601, 1823.05 + 0.65, 30000.0, 0.63, 3986.226, 1875.71 + 0.65, 30000.0, 0.65, 4112.847, 1928.92 + 0.65, 30000.0, 0.67, 4239.454, 1982.73 + 0.65, 30000.0, 0.69, 4366.039, 2037.16 + 0.65, 30000.0, 0.71, 4492.55, 2092.29 + 0.65, 30000.0, 0.73, 4618.988, 2148.12 + 0.65, 30000.0, 0.75, 4745.41, 2204.67 + 0.65, 30000.0, 0.77, 4871.825, 2261.98 + 0.65, 30000.0, 0.79, 4998.248, 2320.05 + 0.65, 30000.0, 0.81, 5124.722, 2379.13 + 0.65, 30000.0, 0.83, 5251.253, 2439.19 + 0.65, 30000.0, 0.85, 5377.801, 2499.94 + 0.65, 30000.0, 0.87, 5504.363, 2561.33 + 0.65, 30000.0, 0.89, 5630.933, 2623.26 + 0.65, 30000.0, 0.91, 5757.507, 2685.68 + 0.65, 30000.0, 0.93, 5884.082, 2748.5 + 0.65, 30000.0, 0.95, 6010.651, 2811.65 + 0.65, 30000.0, 0.97, 6137.212, 2875.06 + 0.65, 30000.0, 0.99, 6263.758, 2938.65 + 0.65, 35000.0, 0.0, 245.5028, 245.503 + 0.65, 35000.0, 0.05, 260.05, 315.575 + 0.65, 35000.0, 0.07, 364.0479, 359.924 + 0.65, 35000.0, 0.09, 468.0467, 403.596 + 0.65, 35000.0, 0.11, 572.0463, 446.651 + 0.65, 35000.0, 0.13, 676.0466, 489.145 + 0.65, 35000.0, 0.15, 780.0473, 531.137 + 0.65, 35000.0, 0.17, 884.0483, 572.684 + 0.65, 35000.0, 0.19, 988.0494, 613.846 + 0.65, 35000.0, 0.21, 1092.051, 654.679 + 0.65, 35000.0, 0.23, 1196.051, 695.243 + 0.65, 35000.0, 0.25, 1300.052, 735.594 + 0.65, 35000.0, 0.27, 1404.052, 775.791 + 0.65, 35000.0, 0.29, 1508.051, 815.892 + 0.65, 35000.0, 0.31, 1612.048, 856.029 + 0.65, 35000.0, 0.33, 1716.043, 896.241 + 0.65, 35000.0, 0.35, 1820.037, 936.478 + 0.65, 35000.0, 0.37, 1924.032, 976.762 + 0.65, 35000.0, 0.39, 2028.027, 1017.12 + 0.65, 35000.0, 0.41, 2132.022, 1057.65 + 0.65, 35000.0, 0.43, 2236.018, 1098.37 + 0.65, 35000.0, 0.45, 2340.016, 1139.16 + 0.65, 35000.0, 0.47, 2444.016, 1180.0 + 0.65, 35000.0, 0.49, 2548.021, 1220.86 + 0.65, 35000.0, 0.51, 2652.033, 1261.5 + 0.65, 35000.0, 0.53, 2756.053, 1301.94 + 0.65, 35000.0, 0.55, 2860.077, 1342.51 + 0.65, 35000.0, 0.57, 2964.104, 1383.3 + 0.65, 35000.0, 0.59, 3068.134, 1424.42 + 0.65, 35000.0, 0.61, 3172.169, 1466.07 + 0.65, 35000.0, 0.63, 3276.206, 1508.32 + 0.65, 35000.0, 0.65, 3380.244, 1551.08 + 0.65, 35000.0, 0.67, 3484.279, 1594.37 + 0.65, 35000.0, 0.69, 3588.311, 1638.24 + 0.65, 35000.0, 0.71, 3692.334, 1682.8 + 0.65, 35000.0, 0.73, 3796.347, 1728.06 + 0.65, 35000.0, 0.75, 3900.355, 1773.93 + 0.65, 35000.0, 0.77, 4004.357, 1820.39 + 0.65, 35000.0, 0.79, 4108.354, 1867.45 + 0.65, 35000.0, 0.81, 4212.343, 1915.11 + 0.65, 35000.0, 0.83, 4316.325, 1963.35 + 0.65, 35000.0, 0.85, 4420.305, 2012.14 + 0.65, 35000.0, 0.87, 4524.283, 2061.47 + 0.65, 35000.0, 0.89, 4628.261, 2111.33 + 0.65, 35000.0, 0.91, 4732.24, 2161.7 + 0.65, 35000.0, 0.93, 4836.222, 2212.55 + 0.65, 35000.0, 0.95, 4940.208, 2263.89 + 0.65, 35000.0, 0.97, 5044.199, 2315.69 + 0.65, 35000.0, 0.99, 5148.198, 2367.94 + 0.65, 40000.0, 0.0, 194.2915, 194.291 + 0.65, 40000.0, 0.05, 208.3, 269.625 + 0.65, 40000.0, 0.07, 291.6617, 304.037 + 0.65, 40000.0, 0.09, 375.0262, 338.042 + 0.65, 40000.0, 0.11, 458.3928, 371.674 + 0.65, 40000.0, 0.13, 541.7608, 404.969 + 0.65, 40000.0, 0.15, 625.1295, 437.962 + 0.65, 40000.0, 0.17, 708.4982, 470.687 + 0.65, 40000.0, 0.19, 791.8664, 503.18 + 0.65, 40000.0, 0.21, 875.2332, 535.475 + 0.65, 40000.0, 0.23, 958.5981, 567.608 + 0.65, 40000.0, 0.25, 1041.96, 599.614 + 0.65, 40000.0, 0.27, 1125.319, 631.527 + 0.65, 40000.0, 0.29, 1208.674, 663.383 + 0.65, 40000.0, 0.31, 1292.019, 695.251 + 0.65, 40000.0, 0.33, 1375.355, 727.159 + 0.65, 40000.0, 0.35, 1458.689, 759.089 + 0.65, 40000.0, 0.37, 1542.022, 791.058 + 0.65, 40000.0, 0.39, 1625.357, 823.085 + 0.65, 40000.0, 0.41, 1708.7, 855.254 + 0.65, 40000.0, 0.43, 1792.052, 887.568 + 0.65, 40000.0, 0.45, 1875.406, 919.944 + 0.65, 40000.0, 0.47, 1958.763, 952.365 + 0.65, 40000.0, 0.49, 2042.121, 984.817 + 0.65, 40000.0, 0.51, 2125.48, 1017.12 + 0.65, 40000.0, 0.53, 2208.84, 1049.3 + 0.65, 40000.0, 0.55, 2292.198, 1081.58 + 0.65, 40000.0, 0.57, 2375.553, 1114.03 + 0.65, 40000.0, 0.59, 2458.902, 1146.72 + 0.65, 40000.0, 0.61, 2542.235, 1179.77 + 0.65, 40000.0, 0.63, 2625.552, 1213.23 + 0.65, 40000.0, 0.65, 2708.867, 1247.07 + 0.65, 40000.0, 0.67, 2792.185, 1281.35 + 0.65, 40000.0, 0.69, 2875.509, 1316.09 + 0.65, 40000.0, 0.71, 2958.858, 1351.44 + 0.65, 40000.0, 0.73, 3042.232, 1387.4 + 0.65, 40000.0, 0.75, 3125.613, 1423.86 + 0.65, 40000.0, 0.77, 3208.997, 1460.83 + 0.65, 40000.0, 0.79, 3292.383, 1498.29 + 0.65, 40000.0, 0.81, 3375.762, 1536.19 + 0.65, 40000.0, 0.83, 3459.131, 1574.53 + 0.65, 40000.0, 0.85, 3542.495, 1613.36 + 0.65, 40000.0, 0.87, 3625.853, 1652.69 + 0.65, 40000.0, 0.89, 3709.203, 1692.53 + 0.65, 40000.0, 0.91, 3792.545, 1732.9 + 0.65, 40000.0, 0.93, 3875.877, 1773.79 + 0.65, 40000.0, 0.95, 3959.198, 1815.22 + 0.65, 40000.0, 0.97, 4042.509, 1857.2 + 0.65, 40000.0, 0.99, 4125.806, 1899.74 + 0.65, 43000.0, 0.0, 168.2987, 168.299 + 0.65, 43000.0, 0.05, 180.1, 248.2 + 0.65, 43000.0, 0.07, 252.4698, 277.341 + 0.65, 43000.0, 0.09, 324.7827, 306.213 + 0.65, 43000.0, 0.11, 397.0457, 334.837 + 0.65, 43000.0, 0.13, 469.2658, 363.237 + 0.65, 43000.0, 0.15, 541.45, 391.436 + 0.65, 43000.0, 0.17, 613.6054, 419.456 + 0.65, 43000.0, 0.19, 685.7391, 447.319 + 0.65, 43000.0, 0.21, 757.8581, 475.05 + 0.65, 43000.0, 0.23, 829.9694, 502.67 + 0.65, 43000.0, 0.25, 902.08, 530.203 + 0.65, 43000.0, 0.27, 974.197, 557.67 + 0.65, 43000.0, 0.29, 1046.328, 585.096 + 0.65, 43000.0, 0.31, 1118.513, 612.481 + 0.65, 43000.0, 0.33, 1190.752, 639.854 + 0.65, 43000.0, 0.35, 1263.0, 667.269 + 0.65, 43000.0, 0.37, 1335.248, 694.757 + 0.65, 43000.0, 0.39, 1407.487, 722.352 + 0.65, 43000.0, 0.41, 1479.67, 750.262 + 0.65, 43000.0, 0.43, 1551.797, 778.476 + 0.65, 43000.0, 0.45, 1623.912, 806.769 + 0.65, 43000.0, 0.47, 1696.023, 835.087 + 0.65, 43000.0, 0.49, 1768.138, 863.38 + 0.65, 43000.0, 0.51, 1840.294, 891.324 + 0.65, 43000.0, 0.53, 1912.49, 918.933 + 0.65, 43000.0, 0.55, 1984.694, 946.556 + 0.65, 43000.0, 0.57, 2056.9, 974.274 + 0.65, 43000.0, 0.59, 2129.102, 1002.16 + 0.65, 43000.0, 0.61, 2201.274, 1030.39 + 0.65, 43000.0, 0.63, 2273.414, 1059.01 + 0.65, 43000.0, 0.65, 2345.55, 1087.97 + 0.65, 43000.0, 0.67, 2417.686, 1117.34 + 0.65, 43000.0, 0.69, 2489.826, 1147.13 + 0.65, 43000.0, 0.71, 2561.998, 1177.52 + 0.65, 43000.0, 0.73, 2634.2, 1208.53 + 0.65, 43000.0, 0.75, 2706.406, 1239.99 + 0.65, 43000.0, 0.77, 2778.61, 1271.89 + 0.65, 43000.0, 0.79, 2850.806, 1304.2 + 0.65, 43000.0, 0.81, 2922.968, 1336.8 + 0.65, 43000.0, 0.83, 2995.095, 1369.71 + 0.65, 43000.0, 0.85, 3067.212, 1403.02 + 0.65, 43000.0, 0.87, 3139.326, 1436.78 + 0.65, 43000.0, 0.89, 3211.441, 1471.01 + 0.65, 43000.0, 0.91, 3283.561, 1505.72 + 0.65, 43000.0, 0.93, 3355.692, 1540.94 + 0.65, 43000.0, 0.95, 3427.837, 1576.7 + 0.65, 43000.0, 0.97, 3500.003, 1613.02 + 0.65, 43000.0, 0.99, 3572.194, 1649.92 + 0.65, 48000.0, 0.0, 132.4851, 132.485 + 0.65, 48000.0, 0.05, 142.0, 195.7 + 0.65, 48000.0, 0.07, 198.9833, 218.648 + 0.65, 48000.0, 0.09, 255.9272, 241.369 + 0.65, 48000.0, 0.11, 312.8359, 263.885 + 0.65, 48000.0, 0.13, 369.7136, 286.214 + 0.65, 48000.0, 0.15, 426.5643, 308.379 + 0.65, 48000.0, 0.17, 483.3921, 330.398 + 0.65, 48000.0, 0.19, 540.2012, 352.293 + 0.65, 48000.0, 0.21, 596.9957, 374.084 + 0.65, 48000.0, 0.23, 653.7796, 395.791 + 0.65, 48000.0, 0.25, 710.5571, 417.434 + 0.65, 48000.0, 0.27, 767.3324, 439.035 + 0.65, 48000.0, 0.29, 824.1095, 460.613 + 0.65, 48000.0, 0.31, 880.8977, 482.19 + 0.65, 48000.0, 0.33, 937.6999, 503.785 + 0.65, 48000.0, 0.35, 994.5125, 525.419 + 0.65, 48000.0, 0.37, 1051.337, 547.11 + 0.65, 48000.0, 0.39, 1108.175, 568.88 + 0.65, 48000.0, 0.41, 1165.042, 590.863 + 0.65, 48000.0, 0.43, 1221.935, 613.051 + 0.65, 48000.0, 0.45, 1278.837, 635.294 + 0.65, 48000.0, 0.47, 1335.744, 657.554 + 0.65, 48000.0, 0.49, 1392.649, 679.797 + 0.65, 48000.0, 0.51, 1449.547, 701.784 + 0.65, 48000.0, 0.53, 1506.434, 723.529 + 0.65, 48000.0, 0.55, 1563.306, 745.294 + 0.65, 48000.0, 0.57, 1620.161, 767.141 + 0.65, 48000.0, 0.59, 1676.993, 789.132 + 0.65, 48000.0, 0.61, 1733.759, 811.402 + 0.65, 48000.0, 0.63, 1790.463, 833.995 + 0.65, 48000.0, 0.65, 1847.162, 856.862 + 0.65, 48000.0, 0.67, 1903.874, 880.03 + 0.65, 48000.0, 0.69, 1960.614, 903.523 + 0.65, 48000.0, 0.71, 2017.476, 927.439 + 0.65, 48000.0, 0.73, 2074.456, 951.785 + 0.65, 48000.0, 0.75, 2131.456, 976.481 + 0.65, 48000.0, 0.77, 2188.454, 1001.52 + 0.65, 48000.0, 0.79, 2245.428, 1026.89 + 0.65, 48000.0, 0.81, 2302.287, 1052.54 + 0.65, 48000.0, 0.83, 2359.024, 1078.46 + 0.65, 48000.0, 0.85, 2415.725, 1104.73 + 0.65, 48000.0, 0.87, 2472.402, 1131.35 + 0.65, 48000.0, 0.89, 2529.067, 1158.35 + 0.65, 48000.0, 0.91, 2585.735, 1185.75 + 0.65, 48000.0, 0.93, 2642.416, 1213.55 + 0.65, 48000.0, 0.95, 2699.125, 1241.78 + 0.65, 48000.0, 0.97, 2755.874, 1270.44 + 0.65, 48000.0, 0.99, 2812.675, 1299.56 + 0.7, 0.0, 0.0, 941.1685, 941.169 + 0.7, 0.0, 0.05, 594.2013, 1409.24 + 0.7, 0.0, 0.07, 852.3849, 1534.35 + 0.7, 0.0, 0.09, 1109.413, 1661.14 + 0.7, 0.0, 0.11, 1365.369, 1789.46 + 0.7, 0.0, 0.13, 1620.337, 1919.16 + 0.7, 0.0, 0.15, 1874.399, 2050.07 + 0.7, 0.0, 0.17, 2127.639, 2182.04 + 0.7, 0.0, 0.19, 2380.14, 2314.91 + 0.7, 0.0, 0.21, 2631.986, 2448.53 + 0.7, 0.0, 0.23, 2883.261, 2582.75 + 0.7, 0.0, 0.25, 3134.046, 2717.39 + 0.7, 0.0, 0.27, 3384.427, 2852.32 + 0.7, 0.0, 0.29, 3634.485, 2987.36 + 0.7, 0.0, 0.31, 3884.305, 3122.37 + 0.7, 0.0, 0.33, 4133.97, 3257.19 + 0.7, 0.0, 0.35, 4383.564, 3391.66 + 0.7, 0.0, 0.37, 4633.169, 3525.63 + 0.7, 0.0, 0.39, 4882.868, 3658.94 + 0.7, 0.0, 0.41, 5132.966, 3790.48 + 0.7, 0.0, 0.43, 5383.492, 3920.31 + 0.7, 0.0, 0.45, 5634.204, 4049.72 + 0.7, 0.0, 0.47, 5885.077, 4179.0 + 0.7, 0.0, 0.49, 6136.089, 4308.46 + 0.7, 0.0, 0.51, 6387.31, 4439.51 + 0.7, 0.0, 0.53, 6638.694, 4572.19 + 0.7, 0.0, 0.55, 6890.079, 4705.18 + 0.7, 0.0, 0.57, 7141.397, 4838.27 + 0.7, 0.0, 0.59, 7392.58, 4971.25 + 0.7, 0.0, 0.61, 7643.403, 5103.52 + 0.7, 0.0, 0.63, 7893.836, 5234.96 + 0.7, 0.0, 0.65, 8144.043, 5365.87 + 0.7, 0.0, 0.67, 8394.031, 5496.23 + 0.7, 0.0, 0.69, 8643.808, 5625.99 + 0.7, 0.0, 0.71, 8893.118, 5754.59 + 0.7, 0.0, 0.73, 9142.033, 5882.12 + 0.7, 0.0, 0.75, 9390.953, 6009.27 + 0.7, 0.0, 0.77, 9640.012, 6136.24 + 0.7, 0.0, 0.79, 9889.347, 6263.23 + 0.7, 0.0, 0.81, 10139.67, 6390.71 + 0.7, 0.0, 0.83, 10390.99, 6518.8 + 0.7, 0.0, 0.85, 10642.56, 6647.31 + 0.7, 0.0, 0.87, 10894.25, 6776.3 + 0.7, 0.0, 0.89, 11145.91, 6905.85 + 0.7, 0.0, 0.91, 11397.39, 7036.03 + 0.7, 0.0, 0.93, 11648.55, 7166.9 + 0.7, 0.0, 0.95, 11899.23, 7298.54 + 0.7, 0.0, 0.97, 12149.3, 7431.01 + 0.7, 0.0, 0.99, 12398.62, 7564.38 + 0.7, 2000.0, 0.0, 881.1932, 881.193 + 0.7, 2000.0, 0.05, 602.6575, 1217.01 + 0.7, 2000.0, 0.07, 846.1243, 1360.84 + 0.7, 2000.0, 0.09, 1089.242, 1502.55 + 0.7, 2000.0, 0.11, 1332.042, 1642.29 + 0.7, 2000.0, 0.13, 1574.555, 1780.18 + 0.7, 2000.0, 0.15, 1816.813, 1916.36 + 0.7, 2000.0, 0.17, 2058.845, 2050.95 + 0.7, 2000.0, 0.19, 2300.684, 2184.08 + 0.7, 2000.0, 0.21, 2542.36, 2315.88 + 0.7, 2000.0, 0.23, 2783.904, 2446.49 + 0.7, 2000.0, 0.25, 3025.348, 2576.02 + 0.7, 2000.0, 0.27, 3266.722, 2704.61 + 0.7, 2000.0, 0.29, 3508.057, 2832.39 + 0.7, 2000.0, 0.31, 3749.385, 2959.49 + 0.7, 2000.0, 0.33, 3990.736, 3086.04 + 0.7, 2000.0, 0.35, 4232.143, 3212.17 + 0.7, 2000.0, 0.37, 4473.634, 3338.0 + 0.7, 2000.0, 0.39, 4715.242, 3463.67 + 0.7, 2000.0, 0.41, 4957.169, 3589.51 + 0.7, 2000.0, 0.43, 5199.403, 3715.6 + 0.7, 2000.0, 0.45, 5441.723, 3841.77 + 0.7, 2000.0, 0.47, 5684.077, 3968.04 + 0.7, 2000.0, 0.49, 5926.414, 4094.44 + 0.7, 2000.0, 0.51, 6168.549, 4221.55 + 0.7, 2000.0, 0.53, 6410.464, 4349.26 + 0.7, 2000.0, 0.55, 6652.304, 4476.8 + 0.7, 2000.0, 0.57, 6894.081, 4603.92 + 0.7, 2000.0, 0.59, 7135.81, 4730.38 + 0.7, 2000.0, 0.61, 7377.374, 4854.81 + 0.7, 2000.0, 0.63, 7618.817, 4977.23 + 0.7, 2000.0, 0.65, 7860.344, 5099.13 + 0.7, 2000.0, 0.67, 8102.029, 5220.85 + 0.7, 2000.0, 0.69, 8343.949, 5342.7 + 0.7, 2000.0, 0.71, 8586.852, 5466.49 + 0.7, 2000.0, 0.73, 8830.652, 5592.18 + 0.7, 2000.0, 0.75, 9074.421, 5717.92 + 0.7, 2000.0, 0.77, 9317.908, 5843.32 + 0.7, 2000.0, 0.79, 9560.862, 5967.98 + 0.7, 2000.0, 0.81, 9801.751, 6088.76 + 0.7, 2000.0, 0.83, 10040.64, 6205.93 + 0.7, 2000.0, 0.85, 10279.16, 6323.22 + 0.7, 2000.0, 0.87, 10517.69, 6441.58 + 0.7, 2000.0, 0.89, 10756.61, 6561.97 + 0.7, 2000.0, 0.91, 10996.27, 6685.34 + 0.7, 2000.0, 0.93, 11237.04, 6812.64 + 0.7, 2000.0, 0.95, 11479.3, 6944.83 + 0.7, 2000.0, 0.97, 11723.4, 7082.86 + 0.7, 2000.0, 0.99, 11969.73, 7227.7 + 0.7, 5000.0, 0.0, 796.9482, 796.948 + 0.7, 5000.0, 0.05, 645.4725, 1059.92 + 0.7, 5000.0, 0.07, 863.6895, 1207.89 + 0.7, 5000.0, 0.09, 1084.167, 1351.81 + 0.7, 5000.0, 0.11, 1306.736, 1491.96 + 0.7, 5000.0, 0.13, 1531.229, 1628.64 + 0.7, 5000.0, 0.15, 1757.478, 1762.11 + 0.7, 5000.0, 0.17, 1985.315, 1892.68 + 0.7, 5000.0, 0.19, 2214.572, 2020.61 + 0.7, 5000.0, 0.21, 2445.081, 2146.2 + 0.7, 5000.0, 0.23, 2676.674, 2269.73 + 0.7, 5000.0, 0.25, 2909.183, 2391.49 + 0.7, 5000.0, 0.27, 3142.44, 2511.75 + 0.7, 5000.0, 0.29, 3376.277, 2630.81 + 0.7, 5000.0, 0.31, 3610.526, 2748.95 + 0.7, 5000.0, 0.33, 3845.019, 2866.45 + 0.7, 5000.0, 0.35, 4079.588, 2983.6 + 0.7, 5000.0, 0.37, 4314.065, 3100.68 + 0.7, 5000.0, 0.39, 4548.282, 3217.98 + 0.7, 5000.0, 0.41, 4781.495, 3336.97 + 0.7, 5000.0, 0.43, 5013.677, 3457.64 + 0.7, 5000.0, 0.45, 5245.514, 3578.51 + 0.7, 5000.0, 0.47, 5477.115, 3699.3 + 0.7, 5000.0, 0.49, 5708.593, 3819.72 + 0.7, 5000.0, 0.51, 5940.22, 3938.29 + 0.7, 5000.0, 0.53, 6172.069, 4055.01 + 0.7, 5000.0, 0.55, 6404.008, 4171.34 + 0.7, 5000.0, 0.57, 6636.069, 4287.57 + 0.7, 5000.0, 0.59, 6868.284, 4403.98 + 0.7, 5000.0, 0.61, 7100.734, 4521.59 + 0.7, 5000.0, 0.63, 7333.439, 4640.5 + 0.7, 5000.0, 0.65, 7566.359, 4759.9 + 0.7, 5000.0, 0.67, 7799.503, 4879.72 + 0.7, 5000.0, 0.69, 8032.881, 4999.88 + 0.7, 5000.0, 0.71, 8266.794, 5120.75 + 0.7, 5000.0, 0.73, 8501.18, 5242.17 + 0.7, 5000.0, 0.75, 8735.613, 5363.37 + 0.7, 5000.0, 0.77, 8969.958, 5484.07 + 0.7, 5000.0, 0.79, 9204.082, 5603.98 + 0.7, 5000.0, 0.81, 9437.259, 5720.63 + 0.7, 5000.0, 0.83, 9669.498, 5834.27 + 0.7, 5000.0, 0.85, 9901.549, 5947.8 + 0.7, 5000.0, 0.87, 10133.56, 6061.99 + 0.7, 5000.0, 0.89, 10365.7, 6177.59 + 0.7, 5000.0, 0.91, 10598.11, 6295.36 + 0.7, 5000.0, 0.93, 10830.95, 6416.06 + 0.7, 5000.0, 0.95, 11064.37, 6540.44 + 0.7, 5000.0, 0.97, 11298.52, 6669.25 + 0.7, 5000.0, 0.99, 11533.57, 6803.25 + 0.7, 10000.0, 0.0, 670.8315, 670.832 + 0.7, 10000.0, 0.05, 376.2125, 918.796 + 0.7, 10000.0, 0.07, 566.7717, 1018.7 + 0.7, 10000.0, 0.09, 754.8076, 1117.74 + 0.7, 10000.0, 0.11, 940.5144, 1215.94 + 0.7, 10000.0, 0.13, 1124.086, 1313.34 + 0.7, 10000.0, 0.15, 1305.718, 1409.97 + 0.7, 10000.0, 0.17, 1485.602, 1505.87 + 0.7, 10000.0, 0.19, 1663.935, 1601.07 + 0.7, 10000.0, 0.21, 1840.91, 1695.6 + 0.7, 10000.0, 0.23, 2016.721, 1789.5 + 0.7, 10000.0, 0.25, 2191.563, 1882.8 + 0.7, 10000.0, 0.27, 2365.629, 1975.53 + 0.7, 10000.0, 0.29, 2539.114, 2067.73 + 0.7, 10000.0, 0.31, 2712.213, 2159.43 + 0.7, 10000.0, 0.33, 2885.119, 2250.66 + 0.7, 10000.0, 0.35, 3058.028, 2341.46 + 0.7, 10000.0, 0.37, 3231.132, 2431.86 + 0.7, 10000.0, 0.39, 3404.626, 2521.89 + 0.7, 10000.0, 0.41, 3579.456, 2611.5 + 0.7, 10000.0, 0.43, 3755.633, 2700.74 + 0.7, 10000.0, 0.45, 3932.238, 2789.78 + 0.7, 10000.0, 0.47, 4109.099, 2878.7 + 0.7, 10000.0, 0.49, 4286.047, 2967.58 + 0.7, 10000.0, 0.51, 4462.751, 3057.15 + 0.7, 10000.0, 0.53, 4639.082, 3147.35 + 0.7, 10000.0, 0.55, 4815.106, 3237.25 + 0.7, 10000.0, 0.57, 4990.732, 3326.6 + 0.7, 10000.0, 0.59, 5165.866, 3415.14 + 0.7, 10000.0, 0.61, 5339.503, 3501.91 + 0.7, 10000.0, 0.63, 5511.773, 3586.84 + 0.7, 10000.0, 0.65, 5683.939, 3670.74 + 0.7, 10000.0, 0.67, 5856.351, 3753.74 + 0.7, 10000.0, 0.69, 6029.361, 3835.93 + 0.7, 10000.0, 0.71, 6204.459, 3916.19 + 0.7, 10000.0, 0.73, 6381.718, 3994.93 + 0.7, 10000.0, 0.75, 6559.798, 4074.07 + 0.7, 10000.0, 0.77, 6738.495, 4154.31 + 0.7, 10000.0, 0.79, 6917.61, 4236.37 + 0.7, 10000.0, 0.81, 7097.267, 4324.48 + 0.7, 10000.0, 0.83, 7277.185, 4418.49 + 0.7, 10000.0, 0.85, 7456.675, 4513.84 + 0.7, 10000.0, 0.87, 7635.376, 4609.52 + 0.7, 10000.0, 0.89, 7812.928, 4704.51 + 0.7, 10000.0, 0.91, 7988.969, 4797.81 + 0.7, 10000.0, 0.93, 8163.138, 4888.41 + 0.7, 10000.0, 0.95, 8335.075, 4975.27 + 0.7, 10000.0, 0.97, 8504.418, 5057.4 + 0.7, 10000.0, 0.99, 8670.807, 5133.78 + 0.7, 15000.0, 0.0, 561.071, 561.071 + 0.7, 15000.0, 0.05, 567.7, 709.2 + 0.7, 15000.0, 0.07, 794.7476, 825.7 + 0.7, 15000.0, 0.09, 1021.797, 939.95 + 0.7, 15000.0, 0.11, 1248.849, 1052.14 + 0.7, 15000.0, 0.13, 1475.902, 1162.46 + 0.7, 15000.0, 0.15, 1702.957, 1271.1 + 0.7, 15000.0, 0.17, 1930.013, 1378.25 + 0.7, 15000.0, 0.19, 2157.071, 1484.1 + 0.7, 15000.0, 0.21, 2384.129, 1588.84 + 0.7, 15000.0, 0.23, 2611.189, 1692.66 + 0.7, 15000.0, 0.25, 2838.249, 1795.74 + 0.7, 15000.0, 0.27, 3065.309, 1898.29 + 0.7, 15000.0, 0.29, 3292.37, 2000.48 + 0.7, 15000.0, 0.31, 3519.43, 2102.78 + 0.7, 15000.0, 0.33, 3746.49, 2205.33 + 0.7, 15000.0, 0.35, 3973.55, 2307.89 + 0.7, 15000.0, 0.37, 4200.61, 2410.51 + 0.7, 15000.0, 0.39, 4427.67, 2513.26 + 0.7, 15000.0, 0.41, 4654.732, 2616.44 + 0.7, 15000.0, 0.43, 4881.795, 2720.05 + 0.7, 15000.0, 0.45, 5108.856, 2823.76 + 0.7, 15000.0, 0.47, 5335.916, 2927.49 + 0.7, 15000.0, 0.49, 5562.973, 3031.19 + 0.7, 15000.0, 0.51, 5790.015, 3134.26 + 0.7, 15000.0, 0.53, 6017.043, 3236.77 + 0.7, 15000.0, 0.55, 6244.075, 3339.4 + 0.7, 15000.0, 0.57, 6471.115, 3442.34 + 0.7, 15000.0, 0.59, 6698.167, 3545.75 + 0.7, 15000.0, 0.61, 6925.257, 3649.99 + 0.7, 15000.0, 0.63, 7152.385, 3755.19 + 0.7, 15000.0, 0.65, 7379.525, 3861.3 + 0.7, 15000.0, 0.67, 7606.673, 3968.41 + 0.7, 15000.0, 0.69, 7833.825, 4076.64 + 0.7, 15000.0, 0.71, 8060.974, 4186.19 + 0.7, 15000.0, 0.73, 8288.118, 4297.15 + 0.7, 15000.0, 0.75, 8515.25, 4409.44 + 0.7, 15000.0, 0.77, 8742.366, 4523.11 + 0.7, 15000.0, 0.79, 8969.462, 4638.21 + 0.7, 15000.0, 0.81, 9196.505, 4754.96 + 0.7, 15000.0, 0.83, 9423.498, 4873.36 + 0.7, 15000.0, 0.85, 9650.475, 4993.19 + 0.7, 15000.0, 0.87, 9877.444, 5114.4 + 0.7, 15000.0, 0.89, 10104.41, 5236.94 + 0.7, 15000.0, 0.91, 10331.39, 5360.77 + 0.7, 15000.0, 0.93, 10558.38, 5485.84 + 0.7, 15000.0, 0.95, 10785.4, 5612.11 + 0.7, 15000.0, 0.97, 11012.45, 5739.52 + 0.7, 15000.0, 0.99, 11239.54, 5868.04 + 0.7, 20000.0, 0.0, 466.0519, 466.052 + 0.7, 20000.0, 0.05, 469.4, 583.8 + 0.7, 20000.0, 0.07, 657.1276, 677.414 + 0.7, 20000.0, 0.09, 844.8573, 769.25 + 0.7, 20000.0, 0.11, 1032.589, 859.459 + 0.7, 20000.0, 0.13, 1220.322, 948.191 + 0.7, 20000.0, 0.15, 1408.057, 1035.6 + 0.7, 20000.0, 0.17, 1595.793, 1121.83 + 0.7, 20000.0, 0.19, 1783.531, 1207.03 + 0.7, 20000.0, 0.21, 1971.269, 1291.37 + 0.7, 20000.0, 0.23, 2159.009, 1374.98 + 0.7, 20000.0, 0.25, 2346.749, 1458.02 + 0.7, 20000.0, 0.27, 2534.489, 1540.63 + 0.7, 20000.0, 0.29, 2722.23, 1622.98 + 0.7, 20000.0, 0.31, 2909.968, 1705.44 + 0.7, 20000.0, 0.33, 3097.705, 1788.09 + 0.7, 20000.0, 0.35, 3285.444, 1870.77 + 0.7, 20000.0, 0.37, 3473.184, 1953.5 + 0.7, 20000.0, 0.39, 3660.927, 2036.33 + 0.7, 20000.0, 0.41, 3848.68, 2119.51 + 0.7, 20000.0, 0.43, 4036.443, 2203.01 + 0.7, 20000.0, 0.45, 4224.206, 2286.59 + 0.7, 20000.0, 0.47, 4411.967, 2370.19 + 0.7, 20000.0, 0.49, 4599.724, 2453.75 + 0.7, 20000.0, 0.51, 4787.453, 2536.77 + 0.7, 20000.0, 0.53, 4975.156, 2619.3 + 0.7, 20000.0, 0.55, 5162.863, 2701.95 + 0.7, 20000.0, 0.57, 5350.582, 2784.87 + 0.7, 20000.0, 0.59, 5538.321, 2868.22 + 0.7, 20000.0, 0.61, 5726.137, 2952.33 + 0.7, 20000.0, 0.63, 5914.027, 3037.33 + 0.7, 20000.0, 0.65, 6101.925, 3123.1 + 0.7, 20000.0, 0.67, 6289.815, 3209.72 + 0.7, 20000.0, 0.69, 6477.681, 3297.26 + 0.7, 20000.0, 0.71, 6665.446, 3385.86 + 0.7, 20000.0, 0.73, 6853.109, 3475.56 + 0.7, 20000.0, 0.75, 7040.744, 3566.36 + 0.7, 20000.0, 0.77, 7228.365, 3658.29 + 0.7, 20000.0, 0.79, 7415.986, 3751.4 + 0.7, 20000.0, 0.81, 7603.657, 3845.92 + 0.7, 20000.0, 0.83, 7791.385, 3941.85 + 0.7, 20000.0, 0.85, 7979.125, 4038.93 + 0.7, 20000.0, 0.87, 8166.873, 4137.11 + 0.7, 20000.0, 0.89, 8354.625, 4236.32 + 0.7, 20000.0, 0.91, 8542.374, 4336.52 + 0.7, 20000.0, 0.93, 8730.118, 4437.63 + 0.7, 20000.0, 0.95, 8917.85, 4539.62 + 0.7, 20000.0, 0.97, 9105.566, 4642.41 + 0.7, 20000.0, 0.99, 9293.262, 4745.96 + 0.7, 25000.0, 0.0, 384.255, 384.255 + 0.7, 25000.0, 0.05, 386.3, 480.4 + 0.7, 25000.0, 0.07, 540.7618, 555.086 + 0.7, 25000.0, 0.09, 695.2359, 628.401 + 0.7, 25000.0, 0.11, 849.7209, 700.46 + 0.7, 25000.0, 0.13, 1004.215, 771.379 + 0.7, 25000.0, 0.15, 1158.718, 841.275 + 0.7, 25000.0, 0.17, 1313.227, 910.264 + 0.7, 25000.0, 0.19, 1467.741, 978.461 + 0.7, 25000.0, 0.21, 1622.259, 1045.98 + 0.7, 25000.0, 0.23, 1776.78, 1112.95 + 0.7, 25000.0, 0.25, 1931.301, 1179.47 + 0.7, 25000.0, 0.27, 2085.822, 1245.67 + 0.7, 25000.0, 0.29, 2240.342, 1311.65 + 0.7, 25000.0, 0.31, 2394.853, 1377.71 + 0.7, 25000.0, 0.33, 2549.356, 1443.92 + 0.7, 25000.0, 0.35, 2703.856, 1510.15 + 0.7, 25000.0, 0.37, 2858.355, 1576.42 + 0.7, 25000.0, 0.39, 3012.852, 1642.78 + 0.7, 25000.0, 0.41, 3167.352, 1709.42 + 0.7, 25000.0, 0.43, 3321.855, 1776.34 + 0.7, 25000.0, 0.45, 3476.356, 1843.31 + 0.7, 25000.0, 0.47, 3630.856, 1910.3 + 0.7, 25000.0, 0.49, 3785.353, 1977.25 + 0.7, 25000.0, 0.51, 3939.831, 2043.73 + 0.7, 25000.0, 0.53, 4094.294, 2109.77 + 0.7, 25000.0, 0.55, 4248.763, 2175.92 + 0.7, 25000.0, 0.57, 4403.243, 2242.32 + 0.7, 25000.0, 0.59, 4557.742, 2309.11 + 0.7, 25000.0, 0.61, 4712.307, 2376.63 + 0.7, 25000.0, 0.63, 4866.934, 2444.98 + 0.7, 25000.0, 0.65, 5021.569, 2513.99 + 0.7, 25000.0, 0.67, 5176.198, 2583.73 + 0.7, 25000.0, 0.69, 5330.807, 2654.24 + 0.7, 25000.0, 0.71, 5485.329, 2725.59 + 0.7, 25000.0, 0.73, 5639.762, 2797.82 + 0.7, 25000.0, 0.75, 5794.175, 2870.94 + 0.7, 25000.0, 0.77, 5948.58, 2944.99 + 0.7, 25000.0, 0.79, 6102.989, 3020.01 + 0.7, 25000.0, 0.81, 6257.46, 3096.25 + 0.7, 25000.0, 0.83, 6411.993, 3173.7 + 0.7, 25000.0, 0.85, 6566.538, 3252.07 + 0.7, 25000.0, 0.87, 6721.087, 3331.3 + 0.7, 25000.0, 0.89, 6875.632, 3411.31 + 0.7, 25000.0, 0.91, 7030.165, 3492.06 + 0.7, 25000.0, 0.93, 7184.678, 3573.46 + 0.7, 25000.0, 0.95, 7339.163, 3655.46 + 0.7, 25000.0, 0.97, 7493.612, 3737.98 + 0.7, 25000.0, 0.99, 7648.017, 3820.96 + 0.7, 30000.0, 0.0, 314.2697, 314.27 + 0.7, 30000.0, 0.05, 317.6, 396.8 + 0.7, 30000.0, 0.07, 444.641, 455.913 + 0.7, 30000.0, 0.09, 571.6759, 514.053 + 0.7, 30000.0, 0.11, 698.7058, 571.299 + 0.7, 30000.0, 0.13, 825.7314, 627.732 + 0.7, 30000.0, 0.15, 952.7536, 683.432 + 0.7, 30000.0, 0.17, 1079.773, 738.479 + 0.7, 30000.0, 0.19, 1206.791, 792.953 + 0.7, 30000.0, 0.21, 1333.809, 846.934 + 0.7, 30000.0, 0.23, 1460.826, 900.503 + 0.7, 30000.0, 0.25, 1587.844, 953.739 + 0.7, 30000.0, 0.27, 1714.864, 1006.72 + 0.7, 30000.0, 0.29, 1841.887, 1059.53 + 0.7, 30000.0, 0.31, 1968.919, 1112.35 + 0.7, 30000.0, 0.33, 2095.959, 1165.23 + 0.7, 30000.0, 0.35, 2223.0, 1218.11 + 0.7, 30000.0, 0.37, 2350.041, 1271.02 + 0.7, 30000.0, 0.39, 2477.081, 1323.98 + 0.7, 30000.0, 0.41, 2604.111, 1377.18 + 0.7, 30000.0, 0.43, 2731.131, 1430.6 + 0.7, 30000.0, 0.45, 2858.15, 1484.08 + 0.7, 30000.0, 0.47, 2985.169, 1537.58 + 0.7, 30000.0, 0.49, 3112.189, 1591.07 + 0.7, 30000.0, 0.51, 3239.212, 1644.2 + 0.7, 30000.0, 0.53, 3366.24, 1697.03 + 0.7, 30000.0, 0.55, 3493.275, 1749.97 + 0.7, 30000.0, 0.57, 3620.318, 1803.14 + 0.7, 30000.0, 0.59, 3747.37, 1856.67 + 0.7, 30000.0, 0.61, 3874.456, 1910.83 + 0.7, 30000.0, 0.63, 4001.573, 1965.7 + 0.7, 30000.0, 0.65, 4128.688, 2021.16 + 0.7, 30000.0, 0.67, 4255.79, 2077.23 + 0.7, 30000.0, 0.69, 4382.871, 2133.97 + 0.7, 30000.0, 0.71, 4509.876, 2191.43 + 0.7, 30000.0, 0.73, 4636.806, 2249.64 + 0.7, 30000.0, 0.75, 4763.719, 2308.6 + 0.7, 30000.0, 0.77, 4890.625, 2368.35 + 0.7, 30000.0, 0.79, 5017.538, 2428.91 + 0.7, 30000.0, 0.81, 5144.503, 2490.52 + 0.7, 30000.0, 0.83, 5271.524, 2553.16 + 0.7, 30000.0, 0.85, 5398.563, 2616.54 + 0.7, 30000.0, 0.87, 5525.613, 2680.57 + 0.7, 30000.0, 0.89, 5652.67, 2745.2 + 0.7, 30000.0, 0.91, 5779.73, 2810.32 + 0.7, 30000.0, 0.93, 5906.787, 2875.88 + 0.7, 30000.0, 0.95, 6033.838, 2941.79 + 0.7, 30000.0, 0.97, 6160.876, 3007.97 + 0.7, 30000.0, 0.99, 6287.897, 3074.36 + 0.7, 35000.0, 0.0, 254.7855, 254.786 + 0.7, 35000.0, 0.05, 260.7, 329.3 + 0.7, 35000.0, 0.07, 364.98, 376.146 + 0.7, 35000.0, 0.09, 469.26, 422.231 + 0.7, 35000.0, 0.11, 573.54, 467.62 + 0.7, 35000.0, 0.13, 677.82, 512.379 + 0.7, 35000.0, 0.15, 782.1, 556.571 + 0.7, 35000.0, 0.17, 886.38, 600.262 + 0.7, 35000.0, 0.19, 990.66, 643.516 + 0.7, 35000.0, 0.21, 1094.94, 686.399 + 0.7, 35000.0, 0.23, 1199.22, 728.973 + 0.7, 35000.0, 0.25, 1303.5, 771.306 + 0.7, 35000.0, 0.27, 1407.78, 813.46 + 0.7, 35000.0, 0.29, 1512.06, 855.502 + 0.7, 35000.0, 0.31, 1616.34, 897.597 + 0.7, 35000.0, 0.33, 1720.62, 939.786 + 0.7, 35000.0, 0.35, 1824.9, 981.981 + 0.7, 35000.0, 0.37, 1929.18, 1024.2 + 0.7, 35000.0, 0.39, 2033.46, 1066.45 + 0.7, 35000.0, 0.41, 2137.738, 1108.82 + 0.7, 35000.0, 0.43, 2242.015, 1151.3 + 0.7, 35000.0, 0.45, 2346.294, 1193.82 + 0.7, 35000.0, 0.47, 2450.574, 1236.37 + 0.7, 35000.0, 0.49, 2554.857, 1278.92 + 0.7, 35000.0, 0.51, 2659.149, 1321.25 + 0.7, 35000.0, 0.53, 2763.449, 1363.38 + 0.7, 35000.0, 0.55, 2867.75, 1405.64 + 0.7, 35000.0, 0.57, 2972.051, 1448.13 + 0.7, 35000.0, 0.59, 3076.351, 1490.94 + 0.7, 35000.0, 0.61, 3180.641, 1534.29 + 0.7, 35000.0, 0.63, 3284.921, 1578.25 + 0.7, 35000.0, 0.65, 3389.2, 1622.72 + 0.7, 35000.0, 0.67, 3493.479, 1667.74 + 0.7, 35000.0, 0.69, 3597.759, 1713.36 + 0.7, 35000.0, 0.71, 3702.05, 1759.68 + 0.7, 35000.0, 0.73, 3806.353, 1806.73 + 0.7, 35000.0, 0.75, 3910.656, 1854.41 + 0.7, 35000.0, 0.77, 4014.957, 1902.73 + 0.7, 35000.0, 0.79, 4119.254, 1951.69 + 0.7, 35000.0, 0.81, 4223.534, 2001.33 + 0.7, 35000.0, 0.83, 4327.797, 2051.63 + 0.7, 35000.0, 0.85, 4432.056, 2102.53 + 0.7, 35000.0, 0.87, 4536.313, 2153.97 + 0.7, 35000.0, 0.89, 4640.57, 2205.93 + 0.7, 35000.0, 0.91, 4744.831, 2258.39 + 0.7, 35000.0, 0.93, 4849.096, 2311.3 + 0.7, 35000.0, 0.95, 4953.369, 2364.65 + 0.7, 35000.0, 0.97, 5057.652, 2418.4 + 0.7, 35000.0, 0.99, 5161.947, 2472.51 + 0.7, 40000.0, 0.0, 201.6379, 201.638 + 0.7, 40000.0, 0.05, 210.3, 280.0 + 0.7, 40000.0, 0.07, 294.4524, 316.871 + 0.7, 40000.0, 0.09, 378.6027, 353.213 + 0.7, 40000.0, 0.11, 462.7511, 389.072 + 0.7, 40000.0, 0.13, 546.8978, 424.494 + 0.7, 40000.0, 0.15, 631.0429, 459.525 + 0.7, 40000.0, 0.17, 715.1866, 494.212 + 0.7, 40000.0, 0.19, 799.3291, 528.602 + 0.7, 40000.0, 0.21, 883.4707, 562.741 + 0.7, 40000.0, 0.23, 967.6114, 596.675 + 0.7, 40000.0, 0.25, 1051.751, 630.45 + 0.7, 40000.0, 0.27, 1135.891, 664.113 + 0.7, 40000.0, 0.29, 1220.03, 697.711 + 0.7, 40000.0, 0.31, 1304.17, 731.371 + 0.7, 40000.0, 0.33, 1388.31, 765.119 + 0.7, 40000.0, 0.35, 1472.45, 798.881 + 0.7, 40000.0, 0.37, 1556.59, 832.666 + 0.7, 40000.0, 0.39, 1640.73, 866.48 + 0.7, 40000.0, 0.41, 1724.87, 900.352 + 0.7, 40000.0, 0.43, 1809.01, 934.283 + 0.7, 40000.0, 0.45, 1893.15, 968.25 + 0.7, 40000.0, 0.47, 1977.29, 1002.25 + 0.7, 40000.0, 0.49, 2061.43, 1036.28 + 0.7, 40000.0, 0.51, 2145.572, 1070.2 + 0.7, 40000.0, 0.53, 2229.715, 1104.04 + 0.7, 40000.0, 0.55, 2313.856, 1137.99 + 0.7, 40000.0, 0.57, 2397.996, 1172.13 + 0.7, 40000.0, 0.59, 2482.133, 1206.5 + 0.7, 40000.0, 0.61, 2566.26, 1241.21 + 0.7, 40000.0, 0.63, 2650.377, 1276.3 + 0.7, 40000.0, 0.65, 2734.494, 1311.79 + 0.7, 40000.0, 0.67, 2818.613, 1347.73 + 0.7, 40000.0, 0.69, 2902.736, 1384.18 + 0.7, 40000.0, 0.71, 2986.876, 1421.29 + 0.7, 40000.0, 0.73, 3071.033, 1459.1 + 0.7, 40000.0, 0.75, 3155.194, 1497.46 + 0.7, 40000.0, 0.77, 3239.357, 1536.36 + 0.7, 40000.0, 0.79, 3323.52, 1575.79 + 0.7, 40000.0, 0.81, 3407.674, 1615.7 + 0.7, 40000.0, 0.83, 3491.82, 1656.08 + 0.7, 40000.0, 0.85, 3575.962, 1696.98 + 0.7, 40000.0, 0.87, 3660.1, 1738.4 + 0.7, 40000.0, 0.89, 3744.234, 1780.33 + 0.7, 40000.0, 0.91, 3828.364, 1822.8 + 0.7, 40000.0, 0.93, 3912.49, 1865.79 + 0.7, 40000.0, 0.95, 3996.612, 1909.32 + 0.7, 40000.0, 0.97, 4080.73, 1953.38 + 0.7, 40000.0, 0.99, 4164.844, 1997.99 + 0.7, 43000.0, 0.0, 174.6622, 174.662 + 0.7, 43000.0, 0.05, 182.1, 256.3 + 0.7, 43000.0, 0.07, 254.939, 287.546 + 0.7, 43000.0, 0.09, 327.7841, 318.433 + 0.7, 43000.0, 0.11, 400.6342, 348.992 + 0.7, 43000.0, 0.13, 473.4886, 379.255 + 0.7, 43000.0, 0.15, 546.3464, 409.254 + 0.7, 43000.0, 0.17, 619.2067, 439.019 + 0.7, 43000.0, 0.19, 692.0687, 468.583 + 0.7, 43000.0, 0.21, 764.9314, 497.978 + 0.7, 43000.0, 0.23, 837.794, 527.234 + 0.7, 43000.0, 0.25, 910.6557, 556.384 + 0.7, 43000.0, 0.27, 983.5156, 585.459 + 0.7, 43000.0, 0.29, 1056.373, 614.491 + 0.7, 43000.0, 0.31, 1129.221, 643.554 + 0.7, 43000.0, 0.33, 1202.061, 672.67 + 0.7, 43000.0, 0.35, 1274.9, 701.806 + 0.7, 43000.0, 0.37, 1347.739, 730.972 + 0.7, 43000.0, 0.39, 1420.579, 760.178 + 0.7, 43000.0, 0.41, 1493.427, 789.477 + 0.7, 43000.0, 0.43, 1566.284, 818.868 + 0.7, 43000.0, 0.45, 1639.144, 848.3 + 0.7, 43000.0, 0.47, 1712.005, 877.764 + 0.7, 43000.0, 0.49, 1784.868, 907.251 + 0.7, 43000.0, 0.51, 1857.732, 936.64 + 0.7, 43000.0, 0.53, 1930.595, 965.949 + 0.7, 43000.0, 0.55, 2003.456, 995.331 + 0.7, 43000.0, 0.57, 2076.316, 1024.83 + 0.7, 43000.0, 0.59, 2149.173, 1054.49 + 0.7, 43000.0, 0.61, 2222.021, 1084.34 + 0.7, 43000.0, 0.63, 2294.861, 1114.42 + 0.7, 43000.0, 0.65, 2367.7, 1144.81 + 0.7, 43000.0, 0.67, 2440.539, 1175.57 + 0.7, 43000.0, 0.69, 2513.379, 1206.74 + 0.7, 43000.0, 0.71, 2586.227, 1238.51 + 0.7, 43000.0, 0.73, 2659.084, 1270.89 + 0.7, 43000.0, 0.75, 2731.944, 1303.78 + 0.7, 43000.0, 0.77, 2804.805, 1337.14 + 0.7, 43000.0, 0.79, 2877.668, 1370.99 + 0.7, 43000.0, 0.81, 2950.532, 1405.32 + 0.7, 43000.0, 0.83, 3023.395, 1440.11 + 0.7, 43000.0, 0.85, 3096.256, 1475.38 + 0.7, 43000.0, 0.87, 3169.116, 1511.12 + 0.7, 43000.0, 0.89, 3241.973, 1547.32 + 0.7, 43000.0, 0.91, 3314.826, 1583.99 + 0.7, 43000.0, 0.93, 3387.675, 1621.13 + 0.7, 43000.0, 0.95, 3460.519, 1658.72 + 0.7, 43000.0, 0.97, 3533.356, 1696.77 + 0.7, 43000.0, 0.99, 3606.187, 1735.28 + 0.7, 48000.0, 0.0, 137.4945, 137.494 + 0.7, 48000.0, 0.05, 143.4, 201.8 + 0.7, 48000.0, 0.07, 200.759, 226.433 + 0.7, 48000.0, 0.09, 258.1241, 250.774 + 0.7, 48000.0, 0.11, 315.4942, 274.849 + 0.7, 48000.0, 0.13, 372.8686, 298.685 + 0.7, 48000.0, 0.15, 430.2464, 322.307 + 0.7, 48000.0, 0.17, 487.6267, 345.742 + 0.7, 48000.0, 0.19, 545.0087, 369.016 + 0.7, 48000.0, 0.21, 602.3914, 392.154 + 0.7, 48000.0, 0.23, 659.774, 415.183 + 0.7, 48000.0, 0.25, 717.1557, 438.129 + 0.7, 48000.0, 0.27, 774.5356, 461.017 + 0.7, 48000.0, 0.29, 831.9127, 483.875 + 0.7, 48000.0, 0.31, 889.2812, 506.768 + 0.7, 48000.0, 0.33, 946.6414, 529.713 + 0.7, 48000.0, 0.35, 1004.0, 552.675 + 0.7, 48000.0, 0.37, 1061.359, 575.661 + 0.7, 48000.0, 0.39, 1118.719, 598.678 + 0.7, 48000.0, 0.41, 1176.087, 621.758 + 0.7, 48000.0, 0.43, 1233.464, 644.901 + 0.7, 48000.0, 0.45, 1290.844, 668.075 + 0.7, 48000.0, 0.47, 1348.225, 691.273 + 0.7, 48000.0, 0.49, 1405.608, 714.488 + 0.7, 48000.0, 0.51, 1462.992, 737.632 + 0.7, 48000.0, 0.53, 1520.375, 760.718 + 0.7, 48000.0, 0.55, 1577.756, 783.863 + 0.7, 48000.0, 0.57, 1635.136, 807.099 + 0.7, 48000.0, 0.59, 1692.513, 830.461 + 0.7, 48000.0, 0.61, 1749.881, 853.961 + 0.7, 48000.0, 0.63, 1807.241, 877.638 + 0.7, 48000.0, 0.65, 1864.6, 901.556 + 0.7, 48000.0, 0.67, 1921.959, 925.761 + 0.7, 48000.0, 0.69, 1979.319, 950.295 + 0.7, 48000.0, 0.71, 2036.689, 975.303 + 0.7, 48000.0, 0.73, 2094.069, 1000.8 + 0.7, 48000.0, 0.75, 2151.45, 1026.69 + 0.7, 48000.0, 0.77, 2208.831, 1052.97 + 0.7, 48000.0, 0.79, 2266.211, 1079.63 + 0.7, 48000.0, 0.81, 2323.583, 1106.66 + 0.7, 48000.0, 0.83, 2380.946, 1134.07 + 0.7, 48000.0, 0.85, 2438.306, 1161.84 + 0.7, 48000.0, 0.87, 2495.665, 1189.99 + 0.7, 48000.0, 0.89, 2553.022, 1218.51 + 0.7, 48000.0, 0.91, 2610.378, 1247.39 + 0.7, 48000.0, 0.93, 2667.735, 1276.63 + 0.7, 48000.0, 0.95, 2725.094, 1306.23 + 0.7, 48000.0, 0.97, 2782.454, 1336.19 + 0.7, 48000.0, 0.99, 2839.817, 1366.51 + 0.75, 0.0, 0.0, 978.9498, 978.95 + 0.75, 0.0, 0.05, 527.9484, 1614.77 + 0.75, 0.0, 0.07, 772.0526, 1729.3 + 0.75, 0.0, 0.09, 1014.303, 1847.19 + 0.75, 0.0, 0.11, 1254.834, 1968.15 + 0.75, 0.0, 0.13, 1493.778, 2091.89 + 0.75, 0.0, 0.15, 1731.27, 2218.15 + 0.75, 0.0, 0.17, 1967.444, 2346.63 + 0.75, 0.0, 0.19, 2202.433, 2477.05 + 0.75, 0.0, 0.21, 2436.371, 2609.13 + 0.75, 0.0, 0.23, 2669.392, 2742.58 + 0.75, 0.0, 0.25, 2901.63, 2877.13 + 0.75, 0.0, 0.27, 3133.218, 3012.49 + 0.75, 0.0, 0.29, 3364.29, 3148.37 + 0.75, 0.0, 0.31, 3594.981, 3284.5 + 0.75, 0.0, 0.33, 3825.423, 3420.59 + 0.75, 0.0, 0.35, 4055.752, 3556.36 + 0.75, 0.0, 0.37, 4286.099, 3691.53 + 0.75, 0.0, 0.39, 4516.6, 3825.81 + 0.75, 0.0, 0.41, 4747.74, 3957.43 + 0.75, 0.0, 0.43, 4979.566, 4086.49 + 0.75, 0.0, 0.45, 5211.692, 4214.88 + 0.75, 0.0, 0.47, 5444.08, 4343.06 + 0.75, 0.0, 0.49, 5676.695, 4471.44 + 0.75, 0.0, 0.51, 5909.658, 4602.08 + 0.75, 0.0, 0.53, 6142.895, 4735.02 + 0.75, 0.0, 0.55, 6376.131, 4868.31 + 0.75, 0.0, 0.57, 6609.254, 5001.61 + 0.75, 0.0, 0.59, 6842.149, 5134.57 + 0.75, 0.0, 0.61, 7074.435, 5266.26 + 0.75, 0.0, 0.63, 7306.063, 5396.48 + 0.75, 0.0, 0.65, 7537.316, 5525.77 + 0.75, 0.0, 0.67, 7768.207, 5654.09 + 0.75, 0.0, 0.69, 7998.752, 5781.4 + 0.75, 0.0, 0.71, 8228.531, 5906.97 + 0.75, 0.0, 0.73, 8457.665, 6030.94 + 0.75, 0.0, 0.75, 8686.816, 6154.21 + 0.75, 0.0, 0.77, 8916.209, 6277.06 + 0.75, 0.0, 0.79, 9146.072, 6399.75 + 0.75, 0.0, 0.81, 9377.612, 6523.03 + 0.75, 0.0, 0.83, 9610.817, 6647.04 + 0.75, 0.0, 0.85, 9844.458, 6771.36 + 0.75, 0.0, 0.87, 10078.28, 6896.04 + 0.75, 0.0, 0.89, 10312.05, 7021.12 + 0.75, 0.0, 0.91, 10545.49, 7146.64 + 0.75, 0.0, 0.93, 10778.38, 7272.65 + 0.75, 0.0, 0.95, 11010.45, 7399.19 + 0.75, 0.0, 0.97, 11241.47, 7526.3 + 0.75, 0.0, 0.99, 11471.17, 7654.02 + 0.75, 2000.0, 0.0, 916.5669, 916.567 + 0.75, 2000.0, 0.05, 556.925, 1346.04 + 0.75, 2000.0, 0.07, 782.8807, 1493.92 + 0.75, 2000.0, 0.09, 1008.301, 1639.12 + 0.75, 2000.0, 0.11, 1233.234, 1781.82 + 0.75, 2000.0, 0.13, 1457.728, 1922.2 + 0.75, 2000.0, 0.15, 1681.831, 2060.4 + 0.75, 2000.0, 0.17, 1905.593, 2196.62 + 0.75, 2000.0, 0.19, 2129.061, 2331.01 + 0.75, 2000.0, 0.21, 2352.284, 2463.75 + 0.75, 2000.0, 0.23, 2575.31, 2595.0 + 0.75, 2000.0, 0.25, 2798.188, 2724.94 + 0.75, 2000.0, 0.27, 3020.965, 2853.73 + 0.75, 2000.0, 0.29, 3243.691, 2981.55 + 0.75, 2000.0, 0.31, 3466.414, 3108.57 + 0.75, 2000.0, 0.33, 3689.182, 3234.94 + 0.75, 2000.0, 0.35, 3912.044, 3360.85 + 0.75, 2000.0, 0.37, 4135.047, 3486.47 + 0.75, 2000.0, 0.39, 4358.241, 3611.95 + 0.75, 2000.0, 0.41, 4581.943, 3737.85 + 0.75, 2000.0, 0.43, 4806.136, 3864.24 + 0.75, 2000.0, 0.45, 5030.469, 3990.75 + 0.75, 2000.0, 0.47, 5254.86, 4117.35 + 0.75, 2000.0, 0.49, 5479.226, 4244.05 + 0.75, 2000.0, 0.51, 5703.281, 4371.54 + 0.75, 2000.0, 0.53, 5926.991, 4499.65 + 0.75, 2000.0, 0.55, 6150.581, 4627.3 + 0.75, 2000.0, 0.57, 6374.07, 4754.13 + 0.75, 2000.0, 0.59, 6597.474, 4879.78 + 0.75, 2000.0, 0.61, 6820.607, 5002.03 + 0.75, 2000.0, 0.63, 7043.538, 5120.97 + 0.75, 2000.0, 0.65, 7266.588, 5239.01 + 0.75, 2000.0, 0.67, 7489.873, 5356.7 + 0.75, 2000.0, 0.69, 7713.512, 5474.57 + 0.75, 2000.0, 0.71, 7938.66, 5595.74 + 0.75, 2000.0, 0.73, 8165.183, 5720.11 + 0.75, 2000.0, 0.75, 8391.655, 5844.45 + 0.75, 2000.0, 0.77, 8617.689, 5968.06 + 0.75, 2000.0, 0.79, 8842.9, 6090.24 + 0.75, 2000.0, 0.81, 9064.919, 6205.86 + 0.75, 2000.0, 0.83, 9283.84, 6315.31 + 0.75, 2000.0, 0.85, 9502.217, 6424.47 + 0.75, 2000.0, 0.87, 9720.625, 6534.78 + 0.75, 2000.0, 0.89, 9939.638, 6647.7 + 0.75, 2000.0, 0.91, 10159.83, 6764.69 + 0.75, 2000.0, 0.93, 10381.77, 6887.2 + 0.75, 2000.0, 0.95, 10606.04, 7016.67 + 0.75, 2000.0, 0.97, 10833.21, 7154.57 + 0.75, 2000.0, 0.99, 11063.85, 7302.33 + 0.75, 5000.0, 0.0, 828.9401, 828.94 + 0.75, 5000.0, 0.05, 641.6516, 1147.87 + 0.75, 5000.0, 0.07, 836.7126, 1307.7 + 0.75, 5000.0, 0.09, 1035.255, 1461.77 + 0.75, 5000.0, 0.11, 1237.019, 1610.49 + 0.75, 5000.0, 0.13, 1441.747, 1754.27 + 0.75, 5000.0, 0.15, 1649.18, 1893.51 + 0.75, 5000.0, 0.17, 1859.059, 2028.64 + 0.75, 5000.0, 0.19, 2071.127, 2160.07 + 0.75, 5000.0, 0.21, 2285.123, 2288.21 + 0.75, 5000.0, 0.23, 2500.791, 2413.47 + 0.75, 5000.0, 0.25, 2717.87, 2536.26 + 0.75, 5000.0, 0.27, 2936.103, 2656.99 + 0.75, 5000.0, 0.29, 3155.231, 2776.09 + 0.75, 5000.0, 0.31, 3374.995, 2893.96 + 0.75, 5000.0, 0.33, 3595.137, 3011.0 + 0.75, 5000.0, 0.35, 3815.398, 3127.65 + 0.75, 5000.0, 0.37, 4035.52, 3244.3 + 0.75, 5000.0, 0.39, 4255.243, 3361.38 + 0.75, 5000.0, 0.41, 4473.431, 3481.19 + 0.75, 5000.0, 0.43, 4690.038, 3603.68 + 0.75, 5000.0, 0.45, 4906.109, 3726.45 + 0.75, 5000.0, 0.47, 5121.814, 3848.99 + 0.75, 5000.0, 0.49, 5337.32, 3970.77 + 0.75, 5000.0, 0.51, 5553.04, 4089.24 + 0.75, 5000.0, 0.53, 5769.082, 4204.39 + 0.75, 5000.0, 0.55, 5985.248, 4318.75 + 0.75, 5000.0, 0.57, 6201.588, 4432.81 + 0.75, 5000.0, 0.59, 6418.147, 4547.06 + 0.75, 5000.0, 0.61, 6635.018, 4663.24 + 0.75, 5000.0, 0.63, 6852.238, 4781.55 + 0.75, 5000.0, 0.65, 7069.792, 4900.57 + 0.75, 5000.0, 0.67, 7287.709, 5020.18 + 0.75, 5000.0, 0.69, 7506.016, 5140.24 + 0.75, 5000.0, 0.71, 7725.249, 5261.46 + 0.75, 5000.0, 0.73, 7945.311, 5383.52 + 0.75, 5000.0, 0.75, 8165.478, 5505.02 + 0.75, 5000.0, 0.77, 8385.532, 5625.43 + 0.75, 5000.0, 0.79, 8605.256, 5744.21 + 0.75, 5000.0, 0.81, 8823.487, 5857.39 + 0.75, 5000.0, 0.83, 9040.238, 5965.25 + 0.75, 5000.0, 0.85, 9256.689, 6072.36 + 0.75, 5000.0, 0.87, 9473.08, 6179.87 + 0.75, 5000.0, 0.89, 9689.649, 6288.89 + 0.75, 5000.0, 0.91, 9906.635, 6400.56 + 0.75, 5000.0, 0.93, 10124.28, 6516.01 + 0.75, 5000.0, 0.95, 10342.82, 6636.37 + 0.75, 5000.0, 0.97, 10562.49, 6762.76 + 0.75, 5000.0, 0.99, 10783.54, 6896.33 + 0.75, 10000.0, 0.0, 697.7607, 697.761 + 0.75, 10000.0, 0.05, 260.3328, 1001.68 + 0.75, 10000.0, 0.07, 427.3353, 1095.04 + 0.75, 10000.0, 0.09, 590.3728, 1187.61 + 0.75, 10000.0, 0.11, 749.7505, 1279.39 + 0.75, 10000.0, 0.13, 905.7739, 1370.41 + 0.75, 10000.0, 0.15, 1058.748, 1460.67 + 0.75, 10000.0, 0.17, 1208.979, 1550.19 + 0.75, 10000.0, 0.19, 1356.772, 1638.99 + 0.75, 10000.0, 0.21, 1502.433, 1727.08 + 0.75, 10000.0, 0.23, 1646.266, 1814.49 + 0.75, 10000.0, 0.25, 1788.577, 1901.21 + 0.75, 10000.0, 0.27, 1929.671, 1987.28 + 0.75, 10000.0, 0.29, 2069.855, 2072.7 + 0.75, 10000.0, 0.31, 2209.432, 2157.49 + 0.75, 10000.0, 0.33, 2348.71, 2241.67 + 0.75, 10000.0, 0.35, 2487.992, 2325.26 + 0.75, 10000.0, 0.37, 2627.585, 2408.26 + 0.75, 10000.0, 0.39, 2767.794, 2490.69 + 0.75, 10000.0, 0.41, 2910.1, 2572.39 + 0.75, 10000.0, 0.43, 3054.524, 2653.4 + 0.75, 10000.0, 0.45, 3199.625, 2734.04 + 0.75, 10000.0, 0.47, 3345.138, 2814.39 + 0.75, 10000.0, 0.49, 3490.798, 2894.58 + 0.75, 10000.0, 0.51, 3636.111, 2975.69 + 0.75, 10000.0, 0.53, 3780.87, 3057.59 + 0.75, 10000.0, 0.55, 3925.147, 3138.92 + 0.75, 10000.0, 0.57, 4068.789, 3219.33 + 0.75, 10000.0, 0.59, 4211.642, 3298.44 + 0.75, 10000.0, 0.61, 4352.087, 3374.96 + 0.75, 10000.0, 0.63, 4490.324, 3448.74 + 0.75, 10000.0, 0.65, 4628.377, 3520.8 + 0.75, 10000.0, 0.67, 4766.8, 3591.23 + 0.75, 10000.0, 0.69, 4906.152, 3660.11 + 0.75, 10000.0, 0.71, 5048.777, 3725.52 + 0.75, 10000.0, 0.73, 5194.799, 3788.02 + 0.75, 10000.0, 0.75, 5342.117, 3850.7 + 0.75, 10000.0, 0.77, 5490.422, 3914.63 + 0.75, 10000.0, 0.79, 5639.403, 3980.88 + 0.75, 10000.0, 0.81, 5789.298, 4056.02 + 0.75, 10000.0, 0.83, 5939.662, 4139.79 + 0.75, 10000.0, 0.85, 6089.372, 4225.05 + 0.75, 10000.0, 0.87, 6237.851, 4310.19 + 0.75, 10000.0, 0.89, 6384.522, 4393.6 + 0.75, 10000.0, 0.91, 6528.81, 4473.67 + 0.75, 10000.0, 0.93, 6670.137, 4548.78 + 0.75, 10000.0, 0.95, 6807.928, 4617.34 + 0.75, 10000.0, 0.97, 6941.606, 4677.71 + 0.75, 10000.0, 0.99, 7070.594, 4728.3 + 0.75, 15000.0, 0.0, 583.594, 583.594 + 0.75, 15000.0, 0.05, 572.7, 751.119 + 0.75, 15000.0, 0.07, 801.6979, 873.917 + 0.75, 15000.0, 0.09, 1030.731, 994.339 + 0.75, 15000.0, 0.11, 1259.793, 1112.58 + 0.75, 15000.0, 0.13, 1488.881, 1228.85 + 0.75, 15000.0, 0.15, 1717.989, 1343.33 + 0.75, 15000.0, 0.17, 1947.111, 1456.23 + 0.75, 15000.0, 0.19, 2176.244, 1567.74 + 0.75, 15000.0, 0.21, 2405.382, 1678.07 + 0.75, 15000.0, 0.23, 2634.52, 1787.41 + 0.75, 15000.0, 0.25, 2863.653, 1895.97 + 0.75, 15000.0, 0.27, 3092.776, 2003.93 + 0.75, 15000.0, 0.29, 3321.884, 2111.49 + 0.75, 15000.0, 0.31, 3550.944, 2219.18 + 0.75, 15000.0, 0.33, 3779.958, 2327.1 + 0.75, 15000.0, 0.35, 4008.962, 2435.0 + 0.75, 15000.0, 0.37, 4237.967, 2542.93 + 0.75, 15000.0, 0.39, 4466.981, 2650.93 + 0.75, 15000.0, 0.41, 4696.043, 2759.3 + 0.75, 15000.0, 0.43, 4925.154, 2868.04 + 0.75, 15000.0, 0.45, 5154.279, 2976.81 + 0.75, 15000.0, 0.47, 5383.412, 3085.54 + 0.75, 15000.0, 0.49, 5612.546, 3194.15 + 0.75, 15000.0, 0.51, 5841.638, 3301.96 + 0.75, 15000.0, 0.53, 6070.69, 3409.02 + 0.75, 15000.0, 0.55, 6299.755, 3516.2 + 0.75, 15000.0, 0.57, 6528.845, 3623.73 + 0.75, 15000.0, 0.59, 6757.974, 3731.82 + 0.75, 15000.0, 0.61, 6987.256, 3841.05 + 0.75, 15000.0, 0.63, 7216.68, 3951.56 + 0.75, 15000.0, 0.65, 7446.107, 4063.08 + 0.75, 15000.0, 0.67, 7675.499, 4175.66 + 0.75, 15000.0, 0.69, 7904.821, 4289.37 + 0.75, 15000.0, 0.71, 8133.877, 4404.21 + 0.75, 15000.0, 0.73, 8362.668, 4520.28 + 0.75, 15000.0, 0.75, 8591.394, 4637.69 + 0.75, 15000.0, 0.77, 8820.093, 4756.53 + 0.75, 15000.0, 0.79, 9048.807, 4876.9 + 0.75, 15000.0, 0.81, 9277.688, 4999.16 + 0.75, 15000.0, 0.83, 9506.75, 5123.33 + 0.75, 15000.0, 0.85, 9735.863, 5249.08 + 0.75, 15000.0, 0.87, 9965.012, 5376.33 + 0.75, 15000.0, 0.89, 10194.18, 5505.04 + 0.75, 15000.0, 0.91, 10423.36, 5635.15 + 0.75, 15000.0, 0.93, 10652.52, 5766.61 + 0.75, 15000.0, 0.95, 10881.66, 5899.36 + 0.75, 15000.0, 0.97, 11110.76, 6033.34 + 0.75, 15000.0, 0.99, 11339.8, 6168.5 + 0.75, 20000.0, 0.0, 484.7606, 484.761 + 0.75, 20000.0, 0.05, 474.1438, 617.269 + 0.75, 20000.0, 0.07, 663.691, 716.087 + 0.75, 20000.0, 0.09, 853.2506, 812.993 + 0.75, 20000.0, 0.11, 1042.821, 908.15 + 0.75, 20000.0, 0.13, 1232.401, 1001.72 + 0.75, 20000.0, 0.15, 1421.99, 1093.86 + 0.75, 20000.0, 0.17, 1611.585, 1184.74 + 0.75, 20000.0, 0.19, 1801.186, 1274.52 + 0.75, 20000.0, 0.21, 1990.79, 1363.36 + 0.75, 20000.0, 0.23, 2180.398, 1451.43 + 0.75, 20000.0, 0.25, 2370.006, 1538.87 + 0.75, 20000.0, 0.27, 2559.615, 1625.87 + 0.75, 20000.0, 0.29, 2749.222, 1712.57 + 0.75, 20000.0, 0.31, 2938.817, 1799.41 + 0.75, 20000.0, 0.33, 3128.4, 1886.49 + 0.75, 20000.0, 0.35, 3317.984, 1973.57 + 0.75, 20000.0, 0.37, 3507.574, 2060.68 + 0.75, 20000.0, 0.39, 3697.172, 2147.85 + 0.75, 20000.0, 0.41, 3886.8, 2235.32 + 0.75, 20000.0, 0.43, 4076.457, 2323.06 + 0.75, 20000.0, 0.45, 4266.119, 2410.82 + 0.75, 20000.0, 0.47, 4455.781, 2498.53 + 0.75, 20000.0, 0.49, 4645.438, 2586.13 + 0.75, 20000.0, 0.51, 4835.056, 2673.03 + 0.75, 20000.0, 0.53, 5024.638, 2759.29 + 0.75, 20000.0, 0.55, 5214.218, 2845.64 + 0.75, 20000.0, 0.57, 5403.804, 2932.27 + 0.75, 20000.0, 0.59, 5593.404, 3019.4 + 0.75, 20000.0, 0.61, 5783.081, 3107.51 + 0.75, 20000.0, 0.63, 5972.83, 3196.72 + 0.75, 20000.0, 0.65, 6162.577, 3286.79 + 0.75, 20000.0, 0.67, 6352.304, 3377.78 + 0.75, 20000.0, 0.69, 6541.994, 3469.73 + 0.75, 20000.0, 0.71, 6731.537, 3562.69 + 0.75, 20000.0, 0.73, 6920.937, 3656.72 + 0.75, 20000.0, 0.75, 7110.31, 3751.87 + 0.75, 20000.0, 0.77, 7299.682, 3848.2 + 0.75, 20000.0, 0.79, 7489.078, 3945.78 + 0.75, 20000.0, 0.81, 7678.616, 4044.91 + 0.75, 20000.0, 0.83, 7868.297, 4145.57 + 0.75, 20000.0, 0.85, 8058.014, 4247.48 + 0.75, 20000.0, 0.87, 8247.749, 4350.55 + 0.75, 20000.0, 0.89, 8437.483, 4454.74 + 0.75, 20000.0, 0.91, 8627.198, 4559.98 + 0.75, 20000.0, 0.93, 8816.875, 4666.2 + 0.75, 20000.0, 0.95, 9006.496, 4773.35 + 0.75, 20000.0, 0.97, 9196.044, 4881.36 + 0.75, 20000.0, 0.99, 9385.5, 4990.17 + 0.75, 25000.0, 0.0, 399.6801, 399.68 + 0.75, 25000.0, 0.05, 390.0, 506.5 + 0.75, 25000.0, 0.07, 545.9418, 585.012 + 0.75, 25000.0, 0.09, 701.8959, 662.159 + 0.75, 25000.0, 0.11, 857.8609, 738.05 + 0.75, 25000.0, 0.13, 1013.835, 812.797 + 0.75, 25000.0, 0.15, 1169.818, 886.511 + 0.75, 25000.0, 0.17, 1325.807, 959.302 + 0.75, 25000.0, 0.19, 1481.801, 1031.28 + 0.75, 25000.0, 0.21, 1637.799, 1102.56 + 0.75, 25000.0, 0.23, 1793.8, 1173.25 + 0.75, 25000.0, 0.25, 1949.801, 1243.45 + 0.75, 25000.0, 0.27, 2105.802, 1313.29 + 0.75, 25000.0, 0.29, 2261.802, 1382.87 + 0.75, 25000.0, 0.31, 2417.793, 1452.46 + 0.75, 25000.0, 0.33, 2573.776, 1522.12 + 0.75, 25000.0, 0.35, 2729.756, 1591.75 + 0.75, 25000.0, 0.37, 2885.735, 1661.38 + 0.75, 25000.0, 0.39, 3041.712, 1731.04 + 0.75, 25000.0, 0.41, 3197.688, 1800.94 + 0.75, 25000.0, 0.43, 3353.665, 1871.07 + 0.75, 25000.0, 0.45, 3509.644, 1941.23 + 0.75, 25000.0, 0.47, 3665.624, 2011.38 + 0.75, 25000.0, 0.49, 3821.607, 2081.48 + 0.75, 25000.0, 0.51, 3977.592, 2151.1 + 0.75, 25000.0, 0.53, 4133.58, 2220.3 + 0.75, 25000.0, 0.55, 4289.575, 2289.61 + 0.75, 25000.0, 0.57, 4445.578, 2359.17 + 0.75, 25000.0, 0.59, 4601.59, 2429.12 + 0.75, 25000.0, 0.61, 4757.633, 2499.82 + 0.75, 25000.0, 0.63, 4913.704, 2571.36 + 0.75, 25000.0, 0.65, 5069.775, 2643.59 + 0.75, 25000.0, 0.67, 5225.838, 2716.58 + 0.75, 25000.0, 0.69, 5381.885, 2790.38 + 0.75, 25000.0, 0.71, 5537.875, 2865.07 + 0.75, 25000.0, 0.73, 5693.808, 2940.68 + 0.75, 25000.0, 0.75, 5849.725, 3017.25 + 0.75, 25000.0, 0.77, 6005.634, 3094.81 + 0.75, 25000.0, 0.79, 6161.543, 3173.4 + 0.75, 25000.0, 0.81, 6317.481, 3253.3 + 0.75, 25000.0, 0.83, 6473.452, 3334.49 + 0.75, 25000.0, 0.85, 6629.431, 3416.67 + 0.75, 25000.0, 0.87, 6785.416, 3499.77 + 0.75, 25000.0, 0.89, 6941.405, 3583.72 + 0.75, 25000.0, 0.91, 7097.395, 3668.46 + 0.75, 25000.0, 0.93, 7253.384, 3753.91 + 0.75, 25000.0, 0.95, 7409.369, 3840.01 + 0.75, 25000.0, 0.97, 7565.348, 3926.67 + 0.75, 25000.0, 0.99, 7721.319, 4013.85 + 0.75, 30000.0, 0.0, 326.8854, 326.885 + 0.75, 30000.0, 0.05, 320.1, 416.6 + 0.75, 30000.0, 0.07, 448.1076, 478.859 + 0.75, 30000.0, 0.09, 576.1173, 540.101 + 0.75, 30000.0, 0.11, 704.1289, 600.407 + 0.75, 30000.0, 0.13, 832.1422, 659.859 + 0.75, 30000.0, 0.15, 960.1571, 718.539 + 0.75, 30000.0, 0.17, 1088.173, 776.529 + 0.75, 30000.0, 0.19, 1216.191, 833.911 + 0.75, 30000.0, 0.21, 1344.209, 890.767 + 0.75, 30000.0, 0.23, 1472.229, 947.178 + 0.75, 30000.0, 0.25, 1600.249, 1003.23 + 0.75, 30000.0, 0.27, 1728.269, 1059.0 + 0.75, 30000.0, 0.29, 1856.29, 1114.56 + 0.75, 30000.0, 0.31, 1984.308, 1170.14 + 0.75, 30000.0, 0.33, 2112.325, 1225.77 + 0.75, 30000.0, 0.35, 2240.344, 1281.36 + 0.75, 30000.0, 0.37, 2368.364, 1336.93 + 0.75, 30000.0, 0.39, 2496.387, 1392.5 + 0.75, 30000.0, 0.41, 2624.419, 1448.19 + 0.75, 30000.0, 0.43, 2752.459, 1503.98 + 0.75, 30000.0, 0.45, 2880.5, 1559.79 + 0.75, 30000.0, 0.47, 3008.541, 1615.61 + 0.75, 30000.0, 0.49, 3136.581, 1671.41 + 0.75, 30000.0, 0.51, 3264.606, 1726.91 + 0.75, 30000.0, 0.53, 3392.618, 1782.17 + 0.75, 30000.0, 0.55, 3520.631, 1837.57 + 0.75, 30000.0, 0.57, 3648.651, 1893.21 + 0.75, 30000.0, 0.59, 3776.68, 1949.22 + 0.75, 30000.0, 0.61, 3904.752, 2005.86 + 0.75, 30000.0, 0.63, 4032.863, 2063.2 + 0.75, 30000.0, 0.65, 4160.975, 2121.14 + 0.75, 30000.0, 0.67, 4289.079, 2179.72 + 0.75, 30000.0, 0.69, 4417.166, 2238.99 + 0.75, 30000.0, 0.71, 4545.186, 2299.02 + 0.75, 30000.0, 0.73, 4673.139, 2359.84 + 0.75, 30000.0, 0.75, 4801.075, 2421.46 + 0.75, 30000.0, 0.77, 4929.003, 2483.9 + 0.75, 30000.0, 0.79, 5056.932, 2547.21 + 0.75, 30000.0, 0.81, 5184.899, 2611.65 + 0.75, 30000.0, 0.83, 5312.906, 2677.19 + 0.75, 30000.0, 0.85, 5440.925, 2743.51 + 0.75, 30000.0, 0.87, 5568.952, 2810.54 + 0.75, 30000.0, 0.89, 5696.983, 2878.17 + 0.75, 30000.0, 0.91, 5825.017, 2946.35 + 0.75, 30000.0, 0.93, 5953.048, 3014.97 + 0.75, 30000.0, 0.95, 6081.075, 3083.96 + 0.75, 30000.0, 0.97, 6209.094, 3153.24 + 0.75, 30000.0, 0.99, 6337.101, 3222.71 + 0.75, 35000.0, 0.0, 265.0134, 265.013 + 0.75, 35000.0, 0.05, 262.5, 344.4 + 0.75, 35000.0, 0.07, 367.5076, 393.811 + 0.75, 35000.0, 0.09, 472.5173, 442.397 + 0.75, 35000.0, 0.11, 577.5289, 490.229 + 0.75, 35000.0, 0.13, 682.5422, 537.376 + 0.75, 35000.0, 0.15, 787.5571, 583.907 + 0.75, 35000.0, 0.17, 892.5734, 629.893 + 0.75, 35000.0, 0.19, 997.5909, 675.402 + 0.75, 35000.0, 0.21, 1102.609, 720.505 + 0.75, 35000.0, 0.23, 1207.629, 765.27 + 0.75, 35000.0, 0.25, 1312.649, 809.769 + 0.75, 35000.0, 0.27, 1417.669, 854.069 + 0.75, 35000.0, 0.29, 1522.69, 898.241 + 0.75, 35000.0, 0.31, 1627.71, 942.482 + 0.75, 35000.0, 0.33, 1732.73, 986.832 + 0.75, 35000.0, 0.35, 1837.75, 1031.17 + 0.75, 35000.0, 0.37, 1942.77, 1075.5 + 0.75, 35000.0, 0.39, 2047.79, 1119.83 + 0.75, 35000.0, 0.41, 2152.81, 1164.19 + 0.75, 35000.0, 0.43, 2257.83, 1208.59 + 0.75, 35000.0, 0.45, 2362.85, 1252.99 + 0.75, 35000.0, 0.47, 2467.87, 1297.39 + 0.75, 35000.0, 0.49, 2572.89, 1341.8 + 0.75, 35000.0, 0.51, 2677.912, 1386.0 + 0.75, 35000.0, 0.53, 2782.935, 1430.04 + 0.75, 35000.0, 0.55, 2887.956, 1474.22 + 0.75, 35000.0, 0.57, 2992.976, 1518.63 + 0.75, 35000.0, 0.59, 3097.993, 1563.38 + 0.75, 35000.0, 0.61, 3203.0, 1608.66 + 0.75, 35000.0, 0.63, 3307.997, 1654.54 + 0.75, 35000.0, 0.65, 3412.994, 1700.96 + 0.75, 35000.0, 0.67, 3517.993, 1747.95 + 0.75, 35000.0, 0.69, 3622.996, 1795.56 + 0.75, 35000.0, 0.71, 3728.018, 1843.89 + 0.75, 35000.0, 0.73, 3833.057, 1892.96 + 0.75, 35000.0, 0.75, 3938.1, 1942.72 + 0.75, 35000.0, 0.77, 4043.143, 1993.16 + 0.75, 35000.0, 0.79, 4148.182, 2044.28 + 0.75, 35000.0, 0.81, 4253.204, 2096.21 + 0.75, 35000.0, 0.83, 4358.207, 2148.92 + 0.75, 35000.0, 0.85, 4463.206, 2202.24 + 0.75, 35000.0, 0.87, 4568.203, 2256.13 + 0.75, 35000.0, 0.89, 4673.2, 2310.53 + 0.75, 35000.0, 0.91, 4778.201, 2365.38 + 0.75, 35000.0, 0.93, 4883.206, 2420.64 + 0.75, 35000.0, 0.95, 4988.219, 2476.26 + 0.75, 35000.0, 0.97, 5093.242, 2532.17 + 0.75, 35000.0, 0.99, 5198.277, 2588.34 + 0.75, 40000.0, 0.0, 209.7322, 209.732 + 0.75, 40000.0, 0.05, 213.4, 291.7 + 0.75, 40000.0, 0.07, 298.7685, 331.119 + 0.75, 40000.0, 0.09, 384.1332, 369.905 + 0.75, 40000.0, 0.11, 469.4947, 408.112 + 0.75, 40000.0, 0.13, 554.8536, 445.798 + 0.75, 40000.0, 0.15, 640.2107, 483.018 + 0.75, 40000.0, 0.17, 725.5667, 519.829 + 0.75, 40000.0, 0.19, 810.9222, 556.286 + 0.75, 40000.0, 0.21, 896.2779, 592.447 + 0.75, 40000.0, 0.23, 981.6346, 628.366 + 0.75, 40000.0, 0.25, 1066.993, 664.101 + 0.75, 40000.0, 0.27, 1152.353, 699.708 + 0.75, 40000.0, 0.29, 1237.717, 735.242 + 0.75, 40000.0, 0.31, 1323.089, 770.883 + 0.75, 40000.0, 0.33, 1408.469, 806.657 + 0.75, 40000.0, 0.35, 1493.85, 842.438 + 0.75, 40000.0, 0.37, 1579.231, 878.222 + 0.75, 40000.0, 0.39, 1664.611, 914.008 + 0.75, 40000.0, 0.41, 1749.983, 949.763 + 0.75, 40000.0, 0.43, 1835.346, 985.491 + 0.75, 40000.0, 0.45, 1920.706, 1021.23 + 0.75, 40000.0, 0.47, 2006.065, 1056.99 + 0.75, 40000.0, 0.49, 2091.422, 1092.79 + 0.75, 40000.0, 0.51, 2176.78, 1128.53 + 0.75, 40000.0, 0.53, 2262.14, 1164.25 + 0.75, 40000.0, 0.55, 2347.5, 1200.1 + 0.75, 40000.0, 0.57, 2432.86, 1236.15 + 0.75, 40000.0, 0.59, 2518.22, 1272.44 + 0.75, 40000.0, 0.61, 2603.578, 1309.04 + 0.75, 40000.0, 0.63, 2688.935, 1346.0 + 0.75, 40000.0, 0.65, 2774.294, 1383.39 + 0.75, 40000.0, 0.67, 2859.654, 1421.26 + 0.75, 40000.0, 0.69, 2945.017, 1459.67 + 0.75, 40000.0, 0.71, 3030.389, 1498.85 + 0.75, 40000.0, 0.73, 3115.769, 1538.8 + 0.75, 40000.0, 0.75, 3201.15, 1579.36 + 0.75, 40000.0, 0.77, 3286.531, 1620.51 + 0.75, 40000.0, 0.79, 3371.911, 1662.23 + 0.75, 40000.0, 0.81, 3457.283, 1704.48 + 0.75, 40000.0, 0.83, 3542.646, 1747.24 + 0.75, 40000.0, 0.85, 3628.006, 1790.54 + 0.75, 40000.0, 0.87, 3713.365, 1834.37 + 0.75, 40000.0, 0.89, 3798.722, 1878.73 + 0.75, 40000.0, 0.91, 3884.078, 1923.6 + 0.75, 40000.0, 0.93, 3969.435, 1968.99 + 0.75, 40000.0, 0.95, 4054.794, 2014.88 + 0.75, 40000.0, 0.97, 4140.154, 2061.28 + 0.75, 40000.0, 0.99, 4225.517, 2108.17 + 0.75, 43000.0, 0.0, 181.6737, 181.674 + 0.75, 43000.0, 0.05, 184.8, 265.7 + 0.75, 43000.0, 0.07, 258.6866, 299.246 + 0.75, 43000.0, 0.09, 332.5814, 332.331 + 0.75, 43000.0, 0.11, 406.4831, 364.998 + 0.75, 43000.0, 0.13, 480.3909, 397.286 + 0.75, 43000.0, 0.15, 554.3036, 429.236 + 0.75, 43000.0, 0.17, 628.2201, 460.889 + 0.75, 43000.0, 0.19, 702.1396, 492.285 + 0.75, 43000.0, 0.21, 776.0608, 523.466 + 0.75, 43000.0, 0.23, 849.9827, 554.472 + 0.75, 43000.0, 0.25, 923.9043, 585.343 + 0.75, 43000.0, 0.27, 997.8245, 616.12 + 0.75, 43000.0, 0.29, 1071.742, 646.845 + 0.75, 43000.0, 0.31, 1145.651, 677.639 + 0.75, 43000.0, 0.33, 1219.551, 708.524 + 0.75, 43000.0, 0.35, 1293.45, 739.419 + 0.75, 43000.0, 0.37, 1367.349, 770.323 + 0.75, 43000.0, 0.39, 1441.249, 801.238 + 0.75, 43000.0, 0.41, 1515.157, 832.157 + 0.75, 43000.0, 0.43, 1589.074, 863.081 + 0.75, 43000.0, 0.45, 1662.994, 894.025 + 0.75, 43000.0, 0.47, 1736.915, 924.993 + 0.75, 43000.0, 0.49, 1810.838, 955.989 + 0.75, 43000.0, 0.51, 1884.762, 986.947 + 0.75, 43000.0, 0.53, 1958.685, 1017.89 + 0.75, 43000.0, 0.55, 2032.606, 1048.92 + 0.75, 43000.0, 0.57, 2106.526, 1080.1 + 0.75, 43000.0, 0.59, 2180.443, 1111.45 + 0.75, 43000.0, 0.61, 2254.351, 1142.97 + 0.75, 43000.0, 0.63, 2328.251, 1174.71 + 0.75, 43000.0, 0.65, 2402.15, 1206.79 + 0.75, 43000.0, 0.67, 2476.049, 1239.25 + 0.75, 43000.0, 0.69, 2549.949, 1272.16 + 0.75, 43000.0, 0.71, 2623.857, 1305.71 + 0.75, 43000.0, 0.73, 2697.774, 1339.94 + 0.75, 43000.0, 0.75, 2771.694, 1374.71 + 0.75, 43000.0, 0.77, 2845.615, 1409.99 + 0.75, 43000.0, 0.79, 2919.538, 1445.8 + 0.75, 43000.0, 0.81, 2993.462, 1482.14 + 0.75, 43000.0, 0.83, 3067.385, 1518.99 + 0.75, 43000.0, 0.85, 3141.306, 1556.34 + 0.75, 43000.0, 0.87, 3215.226, 1594.17 + 0.75, 43000.0, 0.89, 3289.143, 1632.47 + 0.75, 43000.0, 0.91, 3363.056, 1671.24 + 0.75, 43000.0, 0.93, 3436.965, 1710.46 + 0.75, 43000.0, 0.95, 3510.869, 1750.11 + 0.75, 43000.0, 0.97, 3584.766, 1790.2 + 0.75, 43000.0, 0.99, 3658.657, 1830.7 + 0.75, 48000.0, 0.0, 143.0139, 143.014 + 0.75, 48000.0, 0.05, 145.5, 209.2 + 0.75, 48000.0, 0.07, 203.6742, 235.639 + 0.75, 48000.0, 0.09, 261.8586, 261.712 + 0.75, 48000.0, 0.11, 320.052, 287.449 + 0.75, 48000.0, 0.13, 378.2531, 312.884 + 0.75, 48000.0, 0.15, 436.4607, 338.05 + 0.75, 48000.0, 0.17, 494.6736, 362.979 + 0.75, 48000.0, 0.19, 552.8904, 387.704 + 0.75, 48000.0, 0.21, 611.1101, 412.257 + 0.75, 48000.0, 0.23, 669.3313, 436.672 + 0.75, 48000.0, 0.25, 727.5529, 460.98 + 0.75, 48000.0, 0.27, 785.7735, 485.215 + 0.75, 48000.0, 0.29, 843.992, 509.408 + 0.75, 48000.0, 0.31, 902.2028, 533.661 + 0.75, 48000.0, 0.33, 960.4059, 557.989 + 0.75, 48000.0, 0.35, 1018.606, 582.325 + 0.75, 48000.0, 0.37, 1076.805, 606.669 + 0.75, 48000.0, 0.39, 1135.002, 631.021 + 0.75, 48000.0, 0.41, 1193.198, 655.373 + 0.75, 48000.0, 0.43, 1251.395, 679.726 + 0.75, 48000.0, 0.45, 1309.594, 704.094 + 0.75, 48000.0, 0.47, 1367.794, 728.479 + 0.75, 48000.0, 0.49, 1425.997, 752.887 + 0.75, 48000.0, 0.51, 1484.209, 777.264 + 0.75, 48000.0, 0.53, 1542.429, 801.629 + 0.75, 48000.0, 0.55, 1600.65, 826.069 + 0.75, 48000.0, 0.57, 1658.871, 850.614 + 0.75, 48000.0, 0.59, 1717.091, 875.297 + 0.75, 48000.0, 0.61, 1775.303, 900.112 + 0.75, 48000.0, 0.63, 1833.506, 925.099 + 0.75, 48000.0, 0.65, 1891.706, 950.344 + 0.75, 48000.0, 0.67, 1949.905, 975.894 + 0.75, 48000.0, 0.69, 2008.102, 1001.8 + 0.75, 48000.0, 0.71, 2066.298, 1028.22 + 0.75, 48000.0, 0.73, 2124.495, 1055.17 + 0.75, 48000.0, 0.75, 2182.694, 1082.55 + 0.75, 48000.0, 0.77, 2240.894, 1110.34 + 0.75, 48000.0, 0.79, 2299.097, 1138.55 + 0.75, 48000.0, 0.81, 2357.309, 1167.17 + 0.75, 48000.0, 0.83, 2415.529, 1196.19 + 0.75, 48000.0, 0.85, 2473.75, 1225.61 + 0.75, 48000.0, 0.87, 2531.971, 1255.41 + 0.75, 48000.0, 0.89, 2590.191, 1285.58 + 0.75, 48000.0, 0.91, 2648.408, 1316.11 + 0.75, 48000.0, 0.93, 2706.62, 1346.99 + 0.75, 48000.0, 0.95, 2764.825, 1378.21 + 0.75, 48000.0, 0.97, 2823.022, 1409.77 + 0.75, 48000.0, 0.99, 2881.21, 1441.64 + 0.8, 0.0, 0.0, 1020.44, 1020.44 + 0.8, 0.0, 0.05, 446.4188, 1870.05 + 0.8, 0.0, 0.07, 674.4321, 1969.73 + 0.8, 0.0, 0.09, 899.6642, 2074.95 + 0.8, 0.0, 0.11, 1122.316, 2185.26 + 0.8, 0.0, 0.13, 1342.588, 2300.22 + 0.8, 0.0, 0.15, 1560.681, 2419.38 + 0.8, 0.0, 0.17, 1776.797, 2542.28 + 0.8, 0.0, 0.19, 1991.135, 2668.49 + 0.8, 0.0, 0.21, 2203.896, 2797.57 + 0.8, 0.0, 0.23, 2415.282, 2929.05 + 0.8, 0.0, 0.25, 2625.494, 3062.5 + 0.8, 0.0, 0.27, 2834.731, 3197.47 + 0.8, 0.0, 0.29, 3043.195, 3333.51 + 0.8, 0.0, 0.31, 3251.087, 3470.19 + 0.8, 0.0, 0.33, 3458.607, 3607.04 + 0.8, 0.0, 0.35, 3665.956, 3743.63 + 0.8, 0.0, 0.37, 3873.336, 3879.5 + 0.8, 0.0, 0.39, 4080.946, 4014.22 + 0.8, 0.0, 0.41, 4289.514, 4145.18 + 0.8, 0.0, 0.43, 4499.113, 4272.45 + 0.8, 0.0, 0.45, 4709.163, 4398.8 + 0.8, 0.0, 0.47, 4919.608, 4524.81 + 0.8, 0.0, 0.49, 5130.395, 4651.08 + 0.8, 0.0, 0.51, 5341.719, 4780.46 + 0.8, 0.0, 0.53, 5553.464, 4913.0 + 0.8, 0.0, 0.55, 5765.206, 5045.95 + 0.8, 0.0, 0.57, 5976.771, 5178.82 + 0.8, 0.0, 0.59, 6187.982, 5311.12 + 0.8, 0.0, 0.61, 6398.249, 5441.46 + 0.8, 0.0, 0.63, 6607.497, 5569.55 + 0.8, 0.0, 0.65, 6816.169, 5696.24 + 0.8, 0.0, 0.67, 7024.291, 5821.46 + 0.8, 0.0, 0.69, 7231.889, 5945.15 + 0.8, 0.0, 0.71, 7438.33, 6066.37 + 0.8, 0.0, 0.73, 7643.8, 6185.28 + 0.8, 0.0, 0.75, 7849.306, 6303.1 + 0.8, 0.0, 0.77, 8055.194, 6420.2 + 0.8, 0.0, 0.79, 8261.81, 6536.95 + 0.8, 0.0, 0.81, 8471.016, 6654.42 + 0.8, 0.0, 0.83, 8682.791, 6772.8 + 0.8, 0.0, 0.85, 8895.231, 6891.39 + 0.8, 0.0, 0.87, 9107.95, 7010.18 + 0.8, 0.0, 0.89, 9320.558, 7129.2 + 0.8, 0.0, 0.91, 9532.669, 7248.46 + 0.8, 0.0, 0.93, 9743.893, 7367.96 + 0.8, 0.0, 0.95, 9953.844, 7487.71 + 0.8, 0.0, 0.97, 10162.13, 7607.74 + 0.8, 0.0, 0.99, 10368.37, 7728.04 + 0.8, 2000.0, 0.0, 955.4136, 955.414 + 0.8, 2000.0, 0.05, 502.6063, 1502.43 + 0.8, 2000.0, 0.07, 707.739, 1654.54 + 0.8, 2000.0, 0.09, 912.0929, 1803.25 + 0.8, 2000.0, 0.11, 1115.739, 1948.78 + 0.8, 2000.0, 0.13, 1318.749, 2091.35 + 0.8, 2000.0, 0.15, 1521.194, 2231.19 + 0.8, 2000.0, 0.17, 1723.144, 2368.52 + 0.8, 2000.0, 0.19, 1924.672, 2503.57 + 0.8, 2000.0, 0.21, 2125.849, 2636.55 + 0.8, 2000.0, 0.23, 2326.745, 2767.68 + 0.8, 2000.0, 0.25, 2527.431, 2897.21 + 0.8, 2000.0, 0.27, 2727.98, 3025.33 + 0.8, 2000.0, 0.29, 2928.462, 3152.29 + 0.8, 2000.0, 0.31, 3128.948, 3278.3 + 0.8, 2000.0, 0.33, 3329.51, 3403.59 + 0.8, 2000.0, 0.35, 3530.219, 3528.37 + 0.8, 2000.0, 0.37, 3731.145, 3652.87 + 0.8, 2000.0, 0.39, 3932.361, 3777.33 + 0.8, 2000.0, 0.41, 4134.337, 3902.54 + 0.8, 2000.0, 0.43, 4337.047, 4028.6 + 0.8, 2000.0, 0.45, 4539.969, 4154.84 + 0.8, 2000.0, 0.47, 4742.981, 4281.19 + 0.8, 2000.0, 0.49, 4945.961, 4407.6 + 0.8, 2000.0, 0.51, 5148.484, 4534.91 + 0.8, 2000.0, 0.53, 5350.501, 4662.84 + 0.8, 2000.0, 0.55, 5552.338, 4789.95 + 0.8, 2000.0, 0.57, 5754.019, 4915.73 + 0.8, 2000.0, 0.59, 5955.568, 5039.68 + 0.8, 2000.0, 0.61, 6156.703, 5158.51 + 0.8, 2000.0, 0.63, 6357.524, 5272.39 + 0.8, 2000.0, 0.65, 6558.506, 5384.89 + 0.8, 2000.0, 0.67, 6759.823, 5496.86 + 0.8, 2000.0, 0.69, 6961.645, 5609.11 + 0.8, 2000.0, 0.71, 7165.657, 5726.43 + 0.8, 2000.0, 0.73, 7371.664, 5848.7 + 0.8, 2000.0, 0.75, 7577.594, 5970.84 + 0.8, 2000.0, 0.77, 7782.885, 6091.78 + 0.8, 2000.0, 0.79, 7986.978, 6210.4 + 0.8, 2000.0, 0.81, 8186.423, 6319.03 + 0.8, 2000.0, 0.83, 8381.358, 6418.19 + 0.8, 2000.0, 0.85, 8575.513, 6516.53 + 0.8, 2000.0, 0.87, 8769.728, 6616.16 + 0.8, 2000.0, 0.89, 8964.843, 6719.17 + 0.8, 2000.0, 0.91, 9161.698, 6827.66 + 0.8, 2000.0, 0.93, 9361.133, 6943.72 + 0.8, 2000.0, 0.95, 9563.988, 7069.44 + 0.8, 2000.0, 0.97, 9771.103, 7206.93 + 0.8, 2000.0, 0.99, 9983.318, 7358.28 + 0.8, 5000.0, 0.0, 864.0729, 864.073 + 0.8, 5000.0, 0.05, 641.0, 1252.1 + 0.8, 5000.0, 0.07, 807.729, 1426.29 + 0.8, 5000.0, 0.09, 979.522, 1592.51 + 0.8, 5000.0, 0.11, 1156.003, 1751.32 + 0.8, 5000.0, 0.13, 1336.796, 1903.3 + 0.8, 5000.0, 0.15, 1521.525, 2049.05 + 0.8, 5000.0, 0.17, 1709.814, 2189.13 + 0.8, 5000.0, 0.19, 1901.287, 2324.13 + 0.8, 5000.0, 0.21, 2095.568, 2454.62 + 0.8, 5000.0, 0.23, 2292.281, 2581.18 + 0.8, 5000.0, 0.25, 2491.05, 2704.4 + 0.8, 5000.0, 0.27, 2691.499, 2824.85 + 0.8, 5000.0, 0.29, 2893.252, 2943.11 + 0.8, 5000.0, 0.31, 3095.933, 3059.76 + 0.8, 5000.0, 0.33, 3299.166, 3175.38 + 0.8, 5000.0, 0.35, 3502.575, 3290.55 + 0.8, 5000.0, 0.37, 3705.784, 3405.85 + 0.8, 5000.0, 0.39, 3908.417, 3521.85 + 0.8, 5000.0, 0.41, 4108.828, 3641.99 + 0.8, 5000.0, 0.43, 4306.948, 3766.14 + 0.8, 5000.0, 0.45, 4504.288, 3890.68 + 0.8, 5000.0, 0.47, 4701.088, 4014.78 + 0.8, 5000.0, 0.49, 4897.588, 4137.67 + 0.8, 5000.0, 0.51, 5094.377, 4255.31 + 0.8, 5000.0, 0.53, 5291.612, 4367.7 + 0.8, 5000.0, 0.55, 5489.012, 4478.81 + 0.8, 5000.0, 0.57, 5686.649, 4589.38 + 0.8, 5000.0, 0.59, 5884.592, 4700.18 + 0.8, 5000.0, 0.61, 6082.948, 4813.96 + 0.8, 5000.0, 0.63, 6281.778, 4931.01 + 0.8, 5000.0, 0.65, 6481.1, 5049.09 + 0.8, 5000.0, 0.67, 6680.966, 5168.02 + 0.8, 5000.0, 0.69, 6881.428, 5287.56 + 0.8, 5000.0, 0.71, 7083.326, 5408.84 + 0.8, 5000.0, 0.73, 7286.521, 5531.32 + 0.8, 5000.0, 0.75, 7489.9, 5652.82 + 0.8, 5000.0, 0.77, 7693.135, 5772.49 + 0.8, 5000.0, 0.79, 7895.898, 5889.48 + 0.8, 5000.0, 0.81, 8096.467, 5997.86 + 0.8, 5000.0, 0.83, 8294.851, 6098.02 + 0.8, 5000.0, 0.85, 8492.794, 6196.62 + 0.8, 5000.0, 0.87, 8690.642, 6295.26 + 0.8, 5000.0, 0.89, 8888.745, 6395.54 + 0.8, 5000.0, 0.91, 9087.449, 6499.07 + 0.8, 5000.0, 0.93, 9287.104, 6607.45 + 0.8, 5000.0, 0.95, 9488.056, 6722.28 + 0.8, 5000.0, 0.97, 9690.655, 6845.17 + 0.8, 5000.0, 0.99, 9895.247, 6977.71 + 0.8, 10000.0, 0.0, 727.3338, 727.334 + 0.8, 10000.0, 0.05, 115.6375, 1101.68 + 0.8, 10000.0, 0.07, 254.2621, 1185.6 + 0.8, 10000.0, 0.09, 387.0523, 1268.84 + 0.8, 10000.0, 0.11, 514.4577, 1351.39 + 0.8, 10000.0, 0.13, 636.9279, 1433.26 + 0.8, 10000.0, 0.15, 754.9125, 1514.42 + 0.8, 10000.0, 0.17, 868.8611, 1594.87 + 0.8, 10000.0, 0.19, 979.2233, 1674.61 + 0.8, 10000.0, 0.21, 1086.449, 1753.61 + 0.8, 10000.0, 0.23, 1190.987, 1831.88 + 0.8, 10000.0, 0.25, 1293.288, 1909.41 + 0.8, 10000.0, 0.27, 1393.8, 1986.18 + 0.8, 10000.0, 0.29, 1492.974, 2062.18 + 0.8, 10000.0, 0.31, 1591.26, 2137.42 + 0.8, 10000.0, 0.33, 1689.106, 2211.88 + 0.8, 10000.0, 0.35, 1786.963, 2285.54 + 0.8, 10000.0, 0.37, 1885.279, 2358.41 + 0.8, 10000.0, 0.39, 1984.505, 2430.47 + 0.8, 10000.0, 0.41, 2086.817, 2501.39 + 0.8, 10000.0, 0.43, 2192.244, 2571.23 + 0.8, 10000.0, 0.45, 2298.675, 2640.48 + 0.8, 10000.0, 0.47, 2405.722, 2709.29 + 0.8, 10000.0, 0.49, 2512.997, 2777.8 + 0.8, 10000.0, 0.51, 2619.804, 2847.58 + 0.8, 10000.0, 0.53, 2725.831, 2918.43 + 0.8, 10000.0, 0.55, 2831.15, 2988.42 + 0.8, 10000.0, 0.57, 2935.525, 3057.03 + 0.8, 10000.0, 0.59, 3038.72, 3123.73 + 0.8, 10000.0, 0.61, 3138.304, 3186.77 + 0.8, 10000.0, 0.63, 3234.572, 3245.91 + 0.8, 10000.0, 0.65, 3330.544, 3302.45 + 0.8, 10000.0, 0.67, 3427.046, 3356.44 + 0.8, 10000.0, 0.69, 3524.904, 3407.95 + 0.8, 10000.0, 0.71, 3627.577, 3454.02 + 0.8, 10000.0, 0.73, 3735.253, 3495.43 + 0.8, 10000.0, 0.75, 3844.85, 3536.76 + 0.8, 10000.0, 0.77, 3955.919, 3579.55 + 0.8, 10000.0, 0.79, 4068.011, 3625.32 + 0.8, 10000.0, 0.81, 4181.527, 3683.7 + 0.8, 10000.0, 0.83, 4295.811, 3754.28 + 0.8, 10000.0, 0.85, 4409.15, 3826.56 + 0.8, 10000.0, 0.87, 4520.681, 3898.15 + 0.8, 10000.0, 0.89, 4629.541, 3966.65 + 0.8, 10000.0, 0.91, 4734.868, 4029.68 + 0.8, 10000.0, 0.93, 4835.8, 4084.84 + 0.8, 10000.0, 0.95, 4931.475, 4129.74 + 0.8, 10000.0, 0.97, 5021.03, 4161.98 + 0.8, 10000.0, 0.99, 5103.602, 4179.19 + 0.8, 15000.0, 0.0, 608.3284, 608.328 + 0.8, 15000.0, 0.05, 577.2, 795.2 + 0.8, 15000.0, 0.07, 807.9381, 924.3 + 0.8, 15000.0, 0.09, 1038.764, 1050.93 + 0.8, 15000.0, 0.11, 1269.665, 1175.28 + 0.8, 15000.0, 0.13, 1500.627, 1297.57 + 0.8, 15000.0, 0.15, 1731.639, 1417.99 + 0.8, 15000.0, 0.17, 1962.688, 1536.74 + 0.8, 15000.0, 0.19, 2193.759, 1654.04 + 0.8, 15000.0, 0.21, 2424.842, 1770.07 + 0.8, 15000.0, 0.23, 2655.922, 1885.05 + 0.8, 15000.0, 0.25, 2886.987, 1999.18 + 0.8, 15000.0, 0.27, 3118.024, 2112.66 + 0.8, 15000.0, 0.29, 3349.021, 2225.69 + 0.8, 15000.0, 0.31, 3579.888, 2338.8 + 0.8, 15000.0, 0.33, 3810.631, 2452.11 + 0.8, 15000.0, 0.35, 4041.35, 2565.35 + 0.8, 15000.0, 0.37, 4272.069, 2678.55 + 0.8, 15000.0, 0.39, 4502.812, 2791.77 + 0.8, 15000.0, 0.41, 4733.681, 2905.29 + 0.8, 15000.0, 0.43, 4964.68, 3019.08 + 0.8, 15000.0, 0.45, 5195.719, 3132.86 + 0.8, 15000.0, 0.47, 5426.784, 3246.53 + 0.8, 15000.0, 0.49, 5657.861, 3360.03 + 0.8, 15000.0, 0.51, 5888.853, 3472.58 + 0.8, 15000.0, 0.53, 6119.766, 3584.28 + 0.8, 15000.0, 0.55, 6350.712, 3696.12 + 0.8, 15000.0, 0.57, 6581.719, 3808.36 + 0.8, 15000.0, 0.59, 6812.812, 3921.29 + 0.8, 15000.0, 0.61, 7044.277, 4035.75 + 0.8, 15000.0, 0.63, 7276.079, 4151.88 + 0.8, 15000.0, 0.65, 7507.862, 4269.1 + 0.8, 15000.0, 0.67, 7739.53, 4387.41 + 0.8, 15000.0, 0.69, 7970.984, 4506.8 + 0.8, 15000.0, 0.71, 8201.666, 4626.95 + 0.8, 15000.0, 0.73, 8431.591, 4747.95 + 0.8, 15000.0, 0.75, 8661.344, 4870.25 + 0.8, 15000.0, 0.77, 8891.051, 4994.01 + 0.8, 15000.0, 0.79, 9120.838, 5119.37 + 0.8, 15000.0, 0.81, 9351.211, 5246.9 + 0.8, 15000.0, 0.83, 9582.203, 5376.66 + 0.8, 15000.0, 0.85, 9813.375, 5508.17 + 0.8, 15000.0, 0.87, 10044.67, 5641.39 + 0.8, 15000.0, 0.89, 10276.02, 5776.26 + 0.8, 15000.0, 0.91, 10507.37, 5912.74 + 0.8, 15000.0, 0.93, 10738.67, 6050.77 + 0.8, 15000.0, 0.95, 10969.85, 6190.31 + 0.8, 15000.0, 0.97, 11200.85, 6331.3 + 0.8, 15000.0, 0.99, 11431.62, 6473.69 + 0.8, 20000.0, 0.0, 505.3061, 505.306 + 0.8, 20000.0, 0.05, 479.7, 653.0 + 0.8, 20000.0, 0.07, 671.3512, 757.202 + 0.8, 20000.0, 0.09, 863.0291, 859.364 + 0.8, 20000.0, 0.11, 1054.731, 959.659 + 0.8, 20000.0, 0.13, 1246.453, 1058.26 + 0.8, 20000.0, 0.15, 1438.193, 1155.34 + 0.8, 20000.0, 0.17, 1629.947, 1251.06 + 0.8, 20000.0, 0.19, 1821.714, 1345.61 + 0.8, 20000.0, 0.21, 2013.488, 1439.16 + 0.8, 20000.0, 0.23, 2205.269, 1531.87 + 0.8, 20000.0, 0.25, 2397.051, 1623.92 + 0.8, 20000.0, 0.27, 2588.834, 1715.49 + 0.8, 20000.0, 0.29, 2780.613, 1806.74 + 0.8, 20000.0, 0.31, 2972.364, 1898.15 + 0.8, 20000.0, 0.33, 3164.09, 1989.83 + 0.8, 20000.0, 0.35, 3355.819, 2081.49 + 0.8, 20000.0, 0.37, 3547.557, 2173.15 + 0.8, 20000.0, 0.39, 3739.313, 2264.84 + 0.8, 20000.0, 0.41, 3931.128, 2356.77 + 0.8, 20000.0, 0.43, 4123.001, 2448.92 + 0.8, 20000.0, 0.45, 4314.887, 2541.03 + 0.8, 20000.0, 0.47, 4506.778, 2633.04 + 0.8, 20000.0, 0.49, 4698.663, 2724.87 + 0.8, 20000.0, 0.51, 4890.501, 2815.83 + 0.8, 20000.0, 0.53, 5082.291, 2905.99 + 0.8, 20000.0, 0.55, 5274.069, 2996.24 + 0.8, 20000.0, 0.57, 5465.841, 3086.82 + 0.8, 20000.0, 0.59, 5657.613, 3177.95 + 0.8, 20000.0, 0.61, 5849.439, 3270.33 + 0.8, 20000.0, 0.63, 6041.314, 3364.09 + 0.8, 20000.0, 0.65, 6233.169, 3458.81 + 0.8, 20000.0, 0.67, 6424.986, 3554.49 + 0.8, 20000.0, 0.69, 6616.747, 3651.18 + 0.8, 20000.0, 0.71, 6808.304, 3748.76 + 0.8, 20000.0, 0.73, 6999.67, 3847.3 + 0.8, 20000.0, 0.75, 7191.019, 3946.97 + 0.8, 20000.0, 0.77, 7382.393, 4047.88 + 0.8, 20000.0, 0.79, 7573.838, 4150.08 + 0.8, 20000.0, 0.81, 7765.574, 4253.95 + 0.8, 20000.0, 0.83, 7957.604, 4359.49 + 0.8, 20000.0, 0.85, 8149.706, 4466.37 + 0.8, 20000.0, 0.87, 8341.838, 4574.52 + 0.8, 20000.0, 0.89, 8533.958, 4683.88 + 0.8, 20000.0, 0.91, 8726.023, 4794.4 + 0.8, 20000.0, 0.93, 8917.991, 4906.02 + 0.8, 20000.0, 0.95, 9109.819, 5018.68 + 0.8, 20000.0, 0.97, 9301.465, 5132.32 + 0.8, 20000.0, 0.99, 9492.887, 5246.89 + 0.8, 25000.0, 0.0, 416.6197, 416.62 + 0.8, 25000.0, 0.05, 395.5, 534.8 + 0.8, 25000.0, 0.07, 553.699, 617.611 + 0.8, 25000.0, 0.09, 711.9041, 699.009 + 0.8, 25000.0, 0.11, 870.1142, 779.109 + 0.8, 25000.0, 0.13, 1028.329, 858.022 + 0.8, 25000.0, 0.15, 1186.546, 935.861 + 0.8, 25000.0, 0.17, 1344.767, 1012.74 + 0.8, 25000.0, 0.19, 1502.989, 1088.77 + 0.8, 25000.0, 0.21, 1661.211, 1164.06 + 0.8, 25000.0, 0.23, 1819.434, 1238.73 + 0.8, 25000.0, 0.25, 1977.656, 1312.89 + 0.8, 25000.0, 0.27, 2135.876, 1386.66 + 0.8, 25000.0, 0.29, 2294.093, 1460.13 + 0.8, 25000.0, 0.31, 2452.301, 1533.62 + 0.8, 25000.0, 0.33, 2610.501, 1607.18 + 0.8, 25000.0, 0.35, 2768.7, 1680.67 + 0.8, 25000.0, 0.37, 2926.899, 1754.1 + 0.8, 25000.0, 0.39, 3085.099, 1827.5 + 0.8, 25000.0, 0.41, 3243.307, 1900.99 + 0.8, 25000.0, 0.43, 3401.524, 1974.56 + 0.8, 25000.0, 0.45, 3559.744, 2048.11 + 0.8, 25000.0, 0.47, 3717.965, 2121.63 + 0.8, 25000.0, 0.49, 3876.188, 2195.09 + 0.8, 25000.0, 0.51, 4034.405, 2268.15 + 0.8, 25000.0, 0.53, 4192.616, 2340.85 + 0.8, 25000.0, 0.55, 4350.831, 2413.7 + 0.8, 25000.0, 0.57, 4509.052, 2486.84 + 0.8, 25000.0, 0.59, 4667.281, 2560.41 + 0.8, 25000.0, 0.61, 4825.543, 2634.74 + 0.8, 25000.0, 0.63, 4983.834, 2709.93 + 0.8, 25000.0, 0.65, 5142.125, 2785.88 + 0.8, 25000.0, 0.67, 5300.408, 2862.63 + 0.8, 25000.0, 0.69, 5458.675, 2940.25 + 0.8, 25000.0, 0.71, 5616.883, 3018.82 + 0.8, 25000.0, 0.73, 5775.033, 3098.42 + 0.8, 25000.0, 0.75, 5933.169, 3179.04 + 0.8, 25000.0, 0.77, 6091.298, 3260.73 + 0.8, 25000.0, 0.79, 6249.43, 3343.55 + 0.8, 25000.0, 0.81, 6407.6, 3427.82 + 0.8, 25000.0, 0.83, 6565.811, 3513.52 + 0.8, 25000.0, 0.85, 6724.031, 3600.27 + 0.8, 25000.0, 0.87, 6882.258, 3687.99 + 0.8, 25000.0, 0.89, 7040.486, 3776.6 + 0.8, 25000.0, 0.91, 7198.713, 3865.99 + 0.8, 25000.0, 0.93, 7356.933, 3956.09 + 0.8, 25000.0, 0.95, 7515.144, 4046.81 + 0.8, 25000.0, 0.97, 7673.34, 4138.05 + 0.8, 25000.0, 0.99, 7831.519, 4229.72 + 0.8, 30000.0, 0.0, 340.7397, 340.74 + 0.8, 30000.0, 0.05, 323.9, 438.2 + 0.8, 30000.0, 0.07, 453.4676, 503.974 + 0.8, 30000.0, 0.09, 583.0373, 568.634 + 0.8, 30000.0, 0.11, 712.6089, 632.27 + 0.8, 30000.0, 0.13, 842.1822, 694.974 + 0.8, 30000.0, 0.15, 971.7571, 756.836 + 0.8, 30000.0, 0.17, 1101.333, 817.946 + 0.8, 30000.0, 0.19, 1230.911, 878.395 + 0.8, 30000.0, 0.21, 1360.489, 938.274 + 0.8, 30000.0, 0.23, 1490.069, 997.673 + 0.8, 30000.0, 0.25, 1619.649, 1056.68 + 0.8, 30000.0, 0.27, 1749.229, 1115.39 + 0.8, 30000.0, 0.29, 1878.81, 1173.9 + 0.8, 30000.0, 0.31, 2008.39, 1232.45 + 0.8, 30000.0, 0.33, 2137.97, 1291.09 + 0.8, 30000.0, 0.35, 2267.55, 1349.68 + 0.8, 30000.0, 0.37, 2397.13, 1408.23 + 0.8, 30000.0, 0.39, 2526.71, 1466.75 + 0.8, 30000.0, 0.41, 2656.292, 1525.29 + 0.8, 30000.0, 0.43, 2785.875, 1583.87 + 0.8, 30000.0, 0.45, 2915.456, 1642.42 + 0.8, 30000.0, 0.47, 3045.036, 1700.93 + 0.8, 30000.0, 0.49, 3174.613, 1759.39 + 0.8, 30000.0, 0.51, 3304.181, 1817.51 + 0.8, 30000.0, 0.53, 3433.741, 1875.34 + 0.8, 30000.0, 0.55, 3563.3, 1933.29 + 0.8, 30000.0, 0.57, 3692.859, 1991.51 + 0.8, 30000.0, 0.59, 3822.419, 2050.11 + 0.8, 30000.0, 0.61, 3951.987, 2109.4 + 0.8, 30000.0, 0.63, 4081.564, 2169.45 + 0.8, 30000.0, 0.65, 4211.144, 2230.16 + 0.8, 30000.0, 0.67, 4340.725, 2291.56 + 0.8, 30000.0, 0.69, 4470.308, 2353.72 + 0.8, 30000.0, 0.71, 4599.893, 2416.72 + 0.8, 30000.0, 0.73, 4729.479, 2480.6 + 0.8, 30000.0, 0.75, 4859.062, 2545.35 + 0.8, 30000.0, 0.77, 4988.642, 2610.99 + 0.8, 30000.0, 0.79, 5118.216, 2677.56 + 0.8, 30000.0, 0.81, 5247.771, 2745.34 + 0.8, 30000.0, 0.83, 5377.308, 2814.29 + 0.8, 30000.0, 0.85, 5506.844, 2884.07 + 0.8, 30000.0, 0.87, 5636.381, 2954.58 + 0.8, 30000.0, 0.89, 5765.925, 3025.72 + 0.8, 30000.0, 0.91, 5895.478, 3097.4 + 0.8, 30000.0, 0.93, 6025.046, 3169.51 + 0.8, 30000.0, 0.95, 6154.631, 3241.97 + 0.8, 30000.0, 0.97, 6284.239, 3314.68 + 0.8, 30000.0, 0.99, 6413.872, 3387.54 + 0.8, 35000.0, 0.0, 276.2454, 276.245 + 0.8, 35000.0, 0.05, 265.5, 360.8 + 0.8, 35000.0, 0.07, 371.6676, 412.892 + 0.8, 35000.0, 0.09, 477.8373, 464.114 + 0.8, 35000.0, 0.11, 584.0089, 514.536 + 0.8, 35000.0, 0.13, 690.1822, 564.232 + 0.8, 35000.0, 0.15, 796.3571, 613.275 + 0.8, 35000.0, 0.17, 902.5334, 661.737 + 0.8, 35000.0, 0.19, 1008.711, 709.691 + 0.8, 35000.0, 0.21, 1114.889, 757.209 + 0.8, 35000.0, 0.23, 1221.069, 804.365 + 0.8, 35000.0, 0.25, 1327.249, 851.23 + 0.8, 35000.0, 0.27, 1433.429, 897.878 + 0.8, 35000.0, 0.29, 1539.61, 944.38 + 0.8, 35000.0, 0.31, 1645.788, 990.957 + 0.8, 35000.0, 0.33, 1751.965, 1037.65 + 0.8, 35000.0, 0.35, 1858.144, 1084.3 + 0.8, 35000.0, 0.37, 1964.324, 1130.92 + 0.8, 35000.0, 0.39, 2070.507, 1177.51 + 0.8, 35000.0, 0.41, 2176.699, 1224.07 + 0.8, 35000.0, 0.43, 2282.899, 1270.6 + 0.8, 35000.0, 0.45, 2389.1, 1317.11 + 0.8, 35000.0, 0.47, 2495.301, 1363.59 + 0.8, 35000.0, 0.49, 2601.501, 1410.07 + 0.8, 35000.0, 0.51, 2707.693, 1456.33 + 0.8, 35000.0, 0.53, 2813.876, 1502.43 + 0.8, 35000.0, 0.55, 2920.056, 1548.68 + 0.8, 35000.0, 0.57, 3026.235, 1595.18 + 0.8, 35000.0, 0.59, 3132.412, 1642.02 + 0.8, 35000.0, 0.61, 3238.587, 1689.43 + 0.8, 35000.0, 0.63, 3344.761, 1737.47 + 0.8, 35000.0, 0.65, 3450.937, 1786.09 + 0.8, 35000.0, 0.67, 3557.118, 1835.31 + 0.8, 35000.0, 0.69, 3663.304, 1885.2 + 0.8, 35000.0, 0.71, 3769.509, 1935.87 + 0.8, 35000.0, 0.73, 3875.732, 1987.35 + 0.8, 35000.0, 0.75, 3981.956, 2039.56 + 0.8, 35000.0, 0.77, 4088.179, 2092.5 + 0.8, 35000.0, 0.79, 4194.395, 2146.18 + 0.8, 35000.0, 0.81, 4300.587, 2200.76 + 0.8, 35000.0, 0.83, 4406.753, 2256.21 + 0.8, 35000.0, 0.85, 4512.912, 2312.29 + 0.8, 35000.0, 0.87, 4619.068, 2368.94 + 0.8, 35000.0, 0.89, 4725.222, 2426.07 + 0.8, 35000.0, 0.91, 4831.379, 2483.62 + 0.8, 35000.0, 0.93, 4937.541, 2541.52 + 0.8, 35000.0, 0.95, 5043.712, 2599.68 + 0.8, 35000.0, 0.97, 5149.896, 2658.04 + 0.8, 35000.0, 0.99, 5256.094, 2716.53 + 0.8, 40000.0, 0.0, 218.6213, 218.621 + 0.8, 40000.0, 0.05, 217.5, 304.9 + 0.8, 40000.0, 0.07, 304.5, 346.866 + 0.8, 40000.0, 0.09, 391.5, 388.147 + 0.8, 40000.0, 0.11, 478.5, 428.801 + 0.8, 40000.0, 0.13, 565.5, 468.89 + 0.8, 40000.0, 0.15, 652.5, 508.471 + 0.8, 40000.0, 0.17, 739.5, 547.606 + 0.8, 40000.0, 0.19, 826.5, 586.353 + 0.8, 40000.0, 0.21, 913.5, 624.772 + 0.8, 40000.0, 0.23, 1000.5, 662.923 + 0.8, 40000.0, 0.25, 1087.5, 700.866 + 0.8, 40000.0, 0.27, 1174.5, 738.659 + 0.8, 40000.0, 0.29, 1261.5, 776.363 + 0.8, 40000.0, 0.31, 1348.5, 814.172 + 0.8, 40000.0, 0.33, 1435.5, 852.112 + 0.8, 40000.0, 0.35, 1522.5, 890.044 + 0.8, 40000.0, 0.37, 1609.5, 927.962 + 0.8, 40000.0, 0.39, 1696.5, 965.86 + 0.8, 40000.0, 0.41, 1783.5, 1003.69 + 0.8, 40000.0, 0.43, 1870.5, 1041.44 + 0.8, 40000.0, 0.45, 1957.5, 1079.2 + 0.8, 40000.0, 0.47, 2044.5, 1116.97 + 0.8, 40000.0, 0.49, 2131.5, 1154.78 + 0.8, 40000.0, 0.51, 2218.502, 1192.54 + 0.8, 40000.0, 0.53, 2305.505, 1230.31 + 0.8, 40000.0, 0.55, 2392.506, 1268.22 + 0.8, 40000.0, 0.57, 2479.506, 1306.36 + 0.8, 40000.0, 0.59, 2566.503, 1344.77 + 0.8, 40000.0, 0.61, 2653.49, 1383.51 + 0.8, 40000.0, 0.63, 2740.467, 1422.66 + 0.8, 40000.0, 0.65, 2827.444, 1462.27 + 0.8, 40000.0, 0.67, 2914.423, 1502.42 + 0.8, 40000.0, 0.69, 3001.406, 1543.17 + 0.8, 40000.0, 0.71, 3088.404, 1584.8 + 0.8, 40000.0, 0.73, 3175.418, 1627.32 + 0.8, 40000.0, 0.75, 3262.437, 1670.49 + 0.8, 40000.0, 0.77, 3349.461, 1714.29 + 0.8, 40000.0, 0.79, 3436.487, 1758.69 + 0.8, 40000.0, 0.81, 3523.513, 1803.59 + 0.8, 40000.0, 0.83, 3610.539, 1848.99 + 0.8, 40000.0, 0.85, 3697.562, 1894.92 + 0.8, 40000.0, 0.87, 3784.582, 1941.4 + 0.8, 40000.0, 0.89, 3871.596, 1988.4 + 0.8, 40000.0, 0.91, 3958.602, 2035.93 + 0.8, 40000.0, 0.93, 4045.6, 2083.98 + 0.8, 40000.0, 0.95, 4132.587, 2132.55 + 0.8, 40000.0, 0.97, 4219.563, 2181.63 + 0.8, 40000.0, 0.99, 4306.525, 2231.22 + 0.8, 43000.0, 0.0, 189.3735, 189.374 + 0.8, 43000.0, 0.05, 188.3, 276.4 + 0.8, 43000.0, 0.07, 263.6534, 312.338 + 0.8, 43000.0, 0.09, 338.9986, 347.732 + 0.8, 43000.0, 0.11, 414.3369, 382.63 + 0.8, 43000.0, 0.13, 489.6691, 417.078 + 0.8, 43000.0, 0.15, 564.9964, 451.125 + 0.8, 43000.0, 0.17, 640.3199, 484.818 + 0.8, 43000.0, 0.19, 715.6404, 518.206 + 0.8, 43000.0, 0.21, 790.9592, 551.335 + 0.8, 43000.0, 0.23, 866.2773, 584.254 + 0.8, 43000.0, 0.25, 941.5957, 617.01 + 0.8, 43000.0, 0.27, 1016.915, 649.651 + 0.8, 43000.0, 0.29, 1092.238, 682.224 + 0.8, 43000.0, 0.31, 1167.569, 714.88 + 0.8, 43000.0, 0.33, 1242.909, 747.643 + 0.8, 43000.0, 0.35, 1318.25, 780.406 + 0.8, 43000.0, 0.37, 1393.591, 813.167 + 0.8, 43000.0, 0.39, 1468.931, 845.924 + 0.8, 43000.0, 0.41, 1544.261, 878.649 + 0.8, 43000.0, 0.43, 1619.581, 911.346 + 0.8, 43000.0, 0.45, 1694.9, 944.05 + 0.8, 43000.0, 0.47, 1770.219, 976.77 + 0.8, 43000.0, 0.49, 1845.539, 1009.51 + 0.8, 43000.0, 0.51, 1920.869, 1042.22 + 0.8, 43000.0, 0.53, 1996.209, 1074.91 + 0.8, 43000.0, 0.55, 2071.55, 1107.71 + 0.8, 43000.0, 0.57, 2146.891, 1140.66 + 0.8, 43000.0, 0.59, 2222.231, 1173.83 + 0.8, 43000.0, 0.61, 2297.561, 1207.21 + 0.8, 43000.0, 0.63, 2372.881, 1240.86 + 0.8, 43000.0, 0.65, 2448.2, 1274.88 + 0.8, 43000.0, 0.67, 2523.519, 1309.34 + 0.8, 43000.0, 0.69, 2598.839, 1344.31 + 0.8, 43000.0, 0.71, 2674.169, 1380.01 + 0.8, 43000.0, 0.73, 2749.509, 1416.48 + 0.8, 43000.0, 0.75, 2824.85, 1453.51 + 0.8, 43000.0, 0.77, 2900.191, 1491.11 + 0.8, 43000.0, 0.79, 2975.531, 1529.24 + 0.8, 43000.0, 0.81, 3050.863, 1567.87 + 0.8, 43000.0, 0.83, 3126.186, 1607.0 + 0.8, 43000.0, 0.85, 3201.506, 1646.62 + 0.8, 43000.0, 0.87, 3276.825, 1686.73 + 0.8, 43000.0, 0.89, 3352.142, 1727.33 + 0.8, 43000.0, 0.91, 3427.458, 1768.39 + 0.8, 43000.0, 0.93, 3502.775, 1809.92 + 0.8, 43000.0, 0.95, 3578.094, 1851.91 + 0.8, 43000.0, 0.97, 3653.414, 1894.34 + 0.8, 43000.0, 0.99, 3728.737, 1937.2 + 0.8, 48000.0, 0.0, 149.0752, 149.075 + 0.8, 48000.0, 0.05, 148.3, 217.7 + 0.8, 48000.0, 0.07, 207.62, 246.008 + 0.8, 48000.0, 0.09, 266.94, 273.885 + 0.8, 48000.0, 0.11, 326.26, 301.37 + 0.8, 48000.0, 0.13, 385.58, 328.499 + 0.8, 48000.0, 0.15, 444.9, 355.311 + 0.8, 48000.0, 0.17, 504.22, 381.843 + 0.8, 48000.0, 0.19, 563.54, 408.134 + 0.8, 48000.0, 0.21, 622.86, 434.22 + 0.8, 48000.0, 0.23, 682.18, 460.141 + 0.8, 48000.0, 0.25, 741.5, 485.933 + 0.8, 48000.0, 0.27, 800.82, 511.635 + 0.8, 48000.0, 0.29, 860.14, 537.283 + 0.8, 48000.0, 0.31, 919.46, 563.0 + 0.8, 48000.0, 0.33, 978.78, 588.803 + 0.8, 48000.0, 0.35, 1038.1, 614.606 + 0.8, 48000.0, 0.37, 1097.42, 640.407 + 0.8, 48000.0, 0.39, 1156.74, 666.204 + 0.8, 48000.0, 0.41, 1216.058, 691.972 + 0.8, 48000.0, 0.43, 1275.375, 717.715 + 0.8, 48000.0, 0.45, 1334.694, 743.462 + 0.8, 48000.0, 0.47, 1394.014, 769.221 + 0.8, 48000.0, 0.49, 1453.337, 795.0 + 0.8, 48000.0, 0.51, 1512.67, 820.746 + 0.8, 48000.0, 0.53, 1572.013, 846.482 + 0.8, 48000.0, 0.55, 1631.356, 872.306 + 0.8, 48000.0, 0.57, 1690.697, 898.256 + 0.8, 48000.0, 0.59, 1750.034, 924.37 + 0.8, 48000.0, 0.61, 1809.352, 950.66 + 0.8, 48000.0, 0.63, 1868.653, 977.17 + 0.8, 48000.0, 0.65, 1927.95, 1003.97 + 0.8, 48000.0, 0.67, 1987.247, 1031.12 + 0.8, 48000.0, 0.69, 2046.548, 1058.67 + 0.8, 48000.0, 0.71, 2105.866, 1086.78 + 0.8, 48000.0, 0.73, 2165.203, 1115.48 + 0.8, 48000.0, 0.75, 2224.544, 1144.63 + 0.8, 48000.0, 0.77, 2283.887, 1174.22 + 0.8, 48000.0, 0.79, 2343.23, 1204.24 + 0.8, 48000.0, 0.81, 2402.564, 1234.66 + 0.8, 48000.0, 0.83, 2461.89, 1265.47 + 0.8, 48000.0, 0.85, 2521.212, 1296.69 + 0.8, 48000.0, 0.87, 2580.53, 1328.29 + 0.8, 48000.0, 0.89, 2639.844, 1360.27 + 0.8, 48000.0, 0.91, 2699.154, 1392.62 + 0.8, 48000.0, 0.93, 2758.46, 1425.34 + 0.8, 48000.0, 0.95, 2817.762, 1458.41 + 0.8, 48000.0, 0.97, 2877.06, 1491.83 + 0.8, 48000.0, 0.99, 2936.354, 1525.59 + 0.85, 0.0, 0.0, 1065.879, 1065.88 + 0.85, 0.0, 0.05, 346.8956, 2181.53 + 0.85, 0.0, 0.07, 556.2907, 2261.57 + 0.85, 0.0, 0.09, 761.7162, 2349.91 + 0.85, 0.0, 0.11, 963.4589, 2445.88 + 0.85, 0.0, 0.13, 1161.805, 2548.85 + 0.85, 0.0, 0.15, 1357.042, 2658.15 + 0.85, 0.0, 0.17, 1549.456, 2773.14 + 0.85, 0.0, 0.19, 1739.333, 2893.16 + 0.85, 0.0, 0.21, 1926.961, 3017.57 + 0.85, 0.0, 0.23, 2112.625, 3145.71 + 0.85, 0.0, 0.25, 2296.613, 3276.93 + 0.85, 0.0, 0.27, 2479.211, 3410.57 + 0.85, 0.0, 0.29, 2660.707, 3546.0 + 0.85, 0.0, 0.31, 2841.385, 3682.54 + 0.85, 0.0, 0.33, 3021.534, 3819.56 + 0.85, 0.0, 0.35, 3201.439, 3956.41 + 0.85, 0.0, 0.37, 3381.388, 4092.42 + 0.85, 0.0, 0.39, 3561.667, 4226.94 + 0.85, 0.0, 0.41, 3743.313, 4356.35 + 0.85, 0.0, 0.43, 3926.431, 4480.71 + 0.85, 0.0, 0.45, 4110.193, 4603.81 + 0.85, 0.0, 0.47, 4294.522, 4726.43 + 0.85, 0.0, 0.49, 4479.341, 4849.39 + 0.85, 0.0, 0.51, 4664.937, 4976.51 + 0.85, 0.0, 0.53, 4851.145, 5107.87 + 0.85, 0.0, 0.55, 5037.346, 5239.73 + 0.85, 0.0, 0.57, 5223.286, 5371.41 + 0.85, 0.0, 0.59, 5408.71, 5502.24 + 0.85, 0.0, 0.61, 5592.755, 5630.32 + 0.85, 0.0, 0.63, 5775.314, 5755.25 + 0.85, 0.0, 0.65, 5957.039, 5878.19 + 0.85, 0.0, 0.67, 6137.972, 5999.05 + 0.85, 0.0, 0.69, 6318.156, 6117.76 + 0.85, 0.0, 0.71, 6496.688, 6233.07 + 0.85, 0.0, 0.73, 6673.84, 6345.19 + 0.85, 0.0, 0.75, 6851.054, 6455.74 + 0.85, 0.0, 0.77, 7028.83, 6565.21 + 0.85, 0.0, 0.79, 7207.667, 6674.09 + 0.85, 0.0, 0.81, 7390.264, 6783.89 + 0.85, 0.0, 0.83, 7576.588, 6894.83 + 0.85, 0.0, 0.85, 7763.872, 7005.86 + 0.85, 0.0, 0.87, 7951.551, 7116.94 + 0.85, 0.0, 0.89, 8139.058, 7228.04 + 0.85, 0.0, 0.91, 8325.827, 7339.14 + 0.85, 0.0, 0.93, 8511.291, 7450.21 + 0.85, 0.0, 0.95, 8694.883, 7561.22 + 0.85, 0.0, 0.97, 8876.038, 7672.15 + 0.85, 0.0, 0.99, 9054.188, 7782.97 + 0.85, 2000.0, 0.0, 997.9563, 997.956 + 0.85, 2000.0, 0.05, 437.9863, 1689.77 + 0.85, 2000.0, 0.07, 618.3016, 1846.35 + 0.85, 2000.0, 0.09, 797.5311, 1998.6 + 0.85, 2000.0, 0.11, 975.775, 2146.81 + 0.85, 2000.0, 0.13, 1153.133, 2291.29 + 0.85, 2000.0, 0.15, 1329.706, 2432.31 + 0.85, 2000.0, 0.17, 1505.594, 2570.18 + 0.85, 2000.0, 0.19, 1680.897, 2705.19 + 0.85, 2000.0, 0.21, 1855.715, 2837.62 + 0.85, 2000.0, 0.23, 2030.148, 2967.78 + 0.85, 2000.0, 0.25, 2204.296, 3095.94 + 0.85, 2000.0, 0.27, 2378.26, 3222.41 + 0.85, 2000.0, 0.29, 2552.14, 3347.48 + 0.85, 2000.0, 0.31, 2726.036, 3471.44 + 0.85, 2000.0, 0.33, 2900.048, 3594.57 + 0.85, 2000.0, 0.35, 3074.276, 3717.18 + 0.85, 2000.0, 0.37, 3248.821, 3839.56 + 0.85, 2000.0, 0.39, 3423.782, 3961.99 + 0.85, 2000.0, 0.41, 3599.825, 4085.66 + 0.85, 2000.0, 0.43, 3776.914, 4210.65 + 0.85, 2000.0, 0.45, 3954.309, 4335.93 + 0.85, 2000.0, 0.47, 4131.835, 4461.35 + 0.85, 2000.0, 0.49, 4309.319, 4586.78 + 0.85, 2000.0, 0.51, 4486.163, 4713.23 + 0.85, 2000.0, 0.53, 4662.295, 4840.28 + 0.85, 2000.0, 0.55, 4838.171, 4966.08 + 0.85, 2000.0, 0.57, 5013.821, 5089.92 + 0.85, 2000.0, 0.59, 5189.276, 5211.12 + 0.85, 2000.0, 0.61, 5364.133, 5325.08 + 0.85, 2000.0, 0.63, 5538.528, 5432.06 + 0.85, 2000.0, 0.65, 5713.138, 5537.11 + 0.85, 2000.0, 0.67, 5888.202, 5641.4 + 0.85, 2000.0, 0.69, 6063.963, 5746.13 + 0.85, 2000.0, 0.71, 6242.767, 5858.19 + 0.85, 2000.0, 0.73, 6424.345, 5977.39 + 0.85, 2000.0, 0.75, 6605.813, 6096.39 + 0.85, 2000.0, 0.77, 6786.392, 6213.59 + 0.85, 2000.0, 0.79, 6965.303, 6327.4 + 0.85, 2000.0, 0.81, 7137.738, 6426.93 + 0.85, 2000.0, 0.83, 7303.894, 6512.84 + 0.85, 2000.0, 0.85, 7468.974, 6597.31 + 0.85, 2000.0, 0.87, 7634.154, 6683.23 + 0.85, 2000.0, 0.89, 7800.608, 6773.5 + 0.85, 2000.0, 0.91, 7969.511, 6871.03 + 0.85, 2000.0, 0.93, 8142.036, 6978.72 + 0.85, 2000.0, 0.95, 8319.358, 7099.47 + 0.85, 2000.0, 0.97, 8502.652, 7236.17 + 0.85, 2000.0, 0.99, 8693.093, 7391.73 + 0.85, 5000.0, 0.0, 902.5483, 902.548 + 0.85, 5000.0, 0.05, 643.3306, 1374.81 + 0.85, 5000.0, 0.07, 775.6523, 1566.18 + 0.85, 5000.0, 0.09, 915.0293, 1746.79 + 0.85, 5000.0, 0.11, 1060.938, 1917.43 + 0.85, 5000.0, 0.13, 1212.855, 2078.89 + 0.85, 5000.0, 0.15, 1370.257, 2231.95 + 0.85, 5000.0, 0.17, 1532.62, 2377.41 + 0.85, 5000.0, 0.19, 1699.42, 2516.06 + 0.85, 5000.0, 0.21, 1870.133, 2648.68 + 0.85, 5000.0, 0.23, 2044.237, 2776.07 + 0.85, 5000.0, 0.25, 2221.208, 2899.01 + 0.85, 5000.0, 0.27, 2400.522, 3018.3 + 0.85, 5000.0, 0.29, 2581.655, 3134.73 + 0.85, 5000.0, 0.31, 2764.084, 3249.09 + 0.85, 5000.0, 0.33, 2947.285, 3362.16 + 0.85, 5000.0, 0.35, 3130.734, 3474.74 + 0.85, 5000.0, 0.37, 3313.909, 3587.61 + 0.85, 5000.0, 0.39, 3496.285, 3701.57 + 0.85, 5000.0, 0.41, 3675.579, 3821.44 + 0.85, 5000.0, 0.43, 3851.693, 3947.04 + 0.85, 5000.0, 0.45, 4026.718, 4073.15 + 0.85, 5000.0, 0.47, 4200.983, 4198.62 + 0.85, 5000.0, 0.49, 4374.82, 4322.27 + 0.85, 5000.0, 0.51, 4549.032, 4438.24 + 0.85, 5000.0, 0.53, 4723.834, 4546.5 + 0.85, 5000.0, 0.55, 4898.852, 4652.85 + 0.85, 5000.0, 0.57, 5074.184, 4758.4 + 0.85, 5000.0, 0.59, 5249.93, 4864.26 + 0.85, 5000.0, 0.61, 5426.222, 4974.5 + 0.85, 5000.0, 0.63, 5603.151, 5089.49 + 0.85, 5000.0, 0.65, 5780.769, 5205.98 + 0.85, 5000.0, 0.67, 5959.163, 5323.65 + 0.85, 5000.0, 0.69, 6138.415, 5442.16 + 0.85, 5000.0, 0.71, 6319.747, 5563.12 + 0.85, 5000.0, 0.73, 6502.968, 5685.73 + 0.85, 5000.0, 0.75, 6686.475, 5806.84 + 0.85, 5000.0, 0.77, 6869.801, 5925.22 + 0.85, 5000.0, 0.79, 7052.479, 6039.6 + 0.85, 5000.0, 0.81, 7232.083, 6141.68 + 0.85, 5000.0, 0.83, 7408.619, 6231.92 + 0.85, 5000.0, 0.85, 7584.536, 6319.58 + 0.85, 5000.0, 0.87, 7760.316, 6406.85 + 0.85, 5000.0, 0.89, 7936.444, 6495.91 + 0.85, 5000.0, 0.91, 8113.405, 6588.94 + 0.85, 5000.0, 0.93, 8291.683, 6688.13 + 0.85, 5000.0, 0.95, 8471.762, 6795.67 + 0.85, 5000.0, 0.97, 8654.127, 6913.74 + 0.85, 5000.0, 0.99, 8839.262, 7044.52 + 0.85, 10000.0, 0.0, 759.7205, 759.72 + 0.85, 10000.0, 0.05, -61.54687, 1221.25 + 0.85, 10000.0, 0.07, 43.23534, 1292.46 + 0.85, 10000.0, 0.09, 139.8331, 1363.19 + 0.85, 10000.0, 0.11, 228.8774, 1433.39 + 0.85, 10000.0, 0.13, 310.9992, 1503.03 + 0.85, 10000.0, 0.15, 386.8294, 1572.06 + 0.85, 10000.0, 0.17, 456.999, 1640.45 + 0.85, 10000.0, 0.19, 522.139, 1708.15 + 0.85, 10000.0, 0.21, 582.8802, 1775.12 + 0.85, 10000.0, 0.23, 639.8538, 1841.33 + 0.85, 10000.0, 0.25, 693.6906, 1906.72 + 0.85, 10000.0, 0.27, 745.0216, 1971.27 + 0.85, 10000.0, 0.29, 794.4778, 2034.93 + 0.85, 10000.0, 0.31, 842.6901, 2097.65 + 0.85, 10000.0, 0.33, 890.2895, 2159.41 + 0.85, 10000.0, 0.35, 937.9069, 2220.15 + 0.85, 10000.0, 0.37, 986.1733, 2279.85 + 0.85, 10000.0, 0.39, 1035.72, 2338.44 + 0.85, 10000.0, 0.41, 1089.593, 2395.39 + 0.85, 10000.0, 0.43, 1147.839, 2450.76 + 0.85, 10000.0, 0.45, 1207.5, 2505.3 + 0.85, 10000.0, 0.47, 1268.037, 2559.21 + 0.85, 10000.0, 0.49, 1328.908, 2612.72 + 0.85, 10000.0, 0.51, 1389.167, 2667.98 + 0.85, 10000.0, 0.53, 1448.373, 2724.74 + 0.85, 10000.0, 0.55, 1506.588, 2780.31 + 0.85, 10000.0, 0.57, 1563.467, 2833.94 + 0.85, 10000.0, 0.59, 1618.667, 2884.91 + 0.85, 10000.0, 0.61, 1668.726, 2930.87 + 0.85, 10000.0, 0.63, 1714.057, 2971.48 + 0.85, 10000.0, 0.65, 1758.946, 3008.38 + 0.85, 10000.0, 0.67, 1804.561, 3041.6 + 0.85, 10000.0, 0.69, 1852.07, 3071.19 + 0.85, 10000.0, 0.71, 1906.335, 3092.9 + 0.85, 10000.0, 0.73, 1967.63, 3107.79 + 0.85, 10000.0, 0.75, 2031.637, 3122.3 + 0.85, 10000.0, 0.77, 2097.735, 3138.54 + 0.85, 10000.0, 0.79, 2165.301, 3158.64 + 0.85, 10000.0, 0.81, 2234.963, 3196.06 + 0.85, 10000.0, 0.83, 2305.795, 3250.18 + 0.85, 10000.0, 0.85, 2375.319, 3306.27 + 0.85, 10000.0, 0.87, 2442.305, 3360.96 + 0.85, 10000.0, 0.89, 2505.526, 3410.86 + 0.85, 10000.0, 0.91, 2563.752, 3452.6 + 0.85, 10000.0, 0.93, 2615.755, 3482.8 + 0.85, 10000.0, 0.95, 2660.306, 3498.08 + 0.85, 10000.0, 0.97, 2696.177, 3495.07 + 0.85, 10000.0, 0.99, 2722.139, 3470.38 + 0.85, 15000.0, 0.0, 635.416, 635.416 + 0.85, 15000.0, 0.05, 580.525, 841.431 + 0.85, 15000.0, 0.07, 812.5236, 976.781 + 0.85, 15000.0, 0.09, 1044.687, 1109.6 + 0.85, 15000.0, 0.11, 1276.991, 1240.08 + 0.85, 15000.0, 0.13, 1509.41, 1368.43 + 0.85, 15000.0, 0.15, 1741.921, 1494.85 + 0.85, 15000.0, 0.17, 1974.499, 1619.53 + 0.85, 15000.0, 0.19, 2207.119, 1742.69 + 0.85, 15000.0, 0.21, 2439.757, 1864.52 + 0.85, 15000.0, 0.23, 2672.389, 1985.22 + 0.85, 15000.0, 0.25, 2904.989, 2104.99 + 0.85, 15000.0, 0.27, 3137.534, 2224.03 + 0.85, 15000.0, 0.29, 3369.999, 2342.56 + 0.85, 15000.0, 0.31, 3602.213, 2461.07 + 0.85, 15000.0, 0.33, 3834.186, 2579.7 + 0.85, 15000.0, 0.35, 4066.112, 2698.18 + 0.85, 15000.0, 0.37, 4298.039, 2816.55 + 0.85, 15000.0, 0.39, 4530.012, 2934.86 + 0.85, 15000.0, 0.41, 4762.226, 3053.37 + 0.85, 15000.0, 0.43, 4994.691, 3172.07 + 0.85, 15000.0, 0.45, 5227.236, 3290.69 + 0.85, 15000.0, 0.47, 5459.837, 3409.17 + 0.85, 15000.0, 0.49, 5692.468, 3527.46 + 0.85, 15000.0, 0.51, 5924.954, 3644.71 + 0.85, 15000.0, 0.53, 6157.306, 3761.06 + 0.85, 15000.0, 0.55, 6389.726, 3877.61 + 0.85, 15000.0, 0.57, 6622.263, 3994.67 + 0.85, 15000.0, 0.59, 6854.965, 4112.57 + 0.85, 15000.0, 0.61, 7088.385, 4232.47 + 0.85, 15000.0, 0.63, 7322.45, 4354.5 + 0.85, 15000.0, 0.65, 7556.462, 4477.68 + 0.85, 15000.0, 0.67, 7790.226, 4601.93 + 0.85, 15000.0, 0.69, 8023.547, 4727.15 + 0.85, 15000.0, 0.71, 8255.288, 4852.52 + 0.85, 15000.0, 0.73, 8485.482, 4978.13 + 0.85, 15000.0, 0.75, 8715.334, 5104.92 + 0.85, 15000.0, 0.77, 8945.108, 5233.15 + 0.85, 15000.0, 0.79, 9175.065, 5363.05 + 0.85, 15000.0, 0.81, 9406.274, 5495.42 + 0.85, 15000.0, 0.83, 9638.804, 5630.39 + 0.85, 15000.0, 0.85, 9871.717, 5767.36 + 0.85, 15000.0, 0.87, 10104.88, 5906.31 + 0.85, 15000.0, 0.89, 10338.18, 6047.2 + 0.85, 15000.0, 0.91, 10571.47, 6190.03 + 0.85, 15000.0, 0.93, 10804.63, 6334.75 + 0.85, 15000.0, 0.95, 11037.52, 6481.34 + 0.85, 15000.0, 0.97, 11270.03, 6629.78 + 0.85, 15000.0, 0.99, 11502.02, 6780.04 + 0.85, 20000.0, 0.0, 527.8064, 527.806 + 0.85, 20000.0, 0.05, 485.8563, 691.131 + 0.85, 20000.0, 0.07, 679.8025, 800.905 + 0.85, 20000.0, 0.09, 873.7945, 908.516 + 0.85, 20000.0, 0.11, 1067.827, 1014.15 + 0.85, 20000.0, 0.13, 1261.895, 1117.98 + 0.85, 20000.0, 0.15, 1455.993, 1220.19 + 0.85, 20000.0, 0.17, 1650.117, 1320.97 + 0.85, 20000.0, 0.19, 1844.26, 1420.5 + 0.85, 20000.0, 0.21, 2038.418, 1518.95 + 0.85, 20000.0, 0.23, 2232.586, 1616.52 + 0.85, 20000.0, 0.25, 2426.758, 1713.38 + 0.85, 20000.0, 0.27, 2620.93, 1809.71 + 0.85, 20000.0, 0.29, 2815.096, 1905.69 + 0.85, 20000.0, 0.31, 3009.215, 2001.85 + 0.85, 20000.0, 0.33, 3203.29, 2098.29 + 0.85, 20000.0, 0.35, 3397.37, 2194.67 + 0.85, 20000.0, 0.37, 3591.468, 2291.04 + 0.85, 20000.0, 0.39, 3785.596, 2387.39 + 0.85, 20000.0, 0.41, 3979.823, 2483.95 + 0.85, 20000.0, 0.43, 4174.148, 2580.68 + 0.85, 20000.0, 0.45, 4368.498, 2677.32 + 0.85, 20000.0, 0.47, 4562.859, 2773.79 + 0.85, 20000.0, 0.49, 4757.216, 2870.04 + 0.85, 20000.0, 0.51, 4951.52, 2965.24 + 0.85, 20000.0, 0.53, 5145.766, 3059.49 + 0.85, 20000.0, 0.55, 5339.984, 3153.84 + 0.85, 20000.0, 0.57, 5534.175, 3248.55 + 0.85, 20000.0, 0.59, 5728.34, 3343.92 + 0.85, 20000.0, 0.61, 5922.511, 3440.87 + 0.85, 20000.0, 0.63, 6116.68, 3539.53 + 0.85, 20000.0, 0.65, 6310.8, 3639.24 + 0.85, 20000.0, 0.67, 6504.855, 3739.98 + 0.85, 20000.0, 0.69, 6698.829, 3841.72 + 0.85, 20000.0, 0.71, 6892.531, 3944.18 + 0.85, 20000.0, 0.73, 7085.988, 4047.39 + 0.85, 20000.0, 0.75, 7279.446, 4151.74 + 0.85, 20000.0, 0.77, 7472.976, 4257.33 + 0.85, 20000.0, 0.79, 7666.646, 4364.26 + 0.85, 20000.0, 0.81, 7860.837, 4472.97 + 0.85, 20000.0, 0.83, 8055.543, 4583.47 + 0.85, 20000.0, 0.85, 8250.375, 4695.42 + 0.85, 20000.0, 0.87, 8445.253, 4808.77 + 0.85, 20000.0, 0.89, 8640.097, 4923.47 + 0.85, 20000.0, 0.91, 8834.827, 5039.49 + 0.85, 20000.0, 0.93, 9029.364, 5156.78 + 0.85, 20000.0, 0.95, 9223.627, 5275.29 + 0.85, 20000.0, 0.97, 9417.536, 5394.98 + 0.85, 20000.0, 0.99, 9611.012, 5515.81 + 0.85, 25000.0, 0.0, 435.1709, 435.171 + 0.85, 25000.0, 0.05, 403.275, 565.575 + 0.85, 25000.0, 0.07, 564.7207, 653.561 + 0.85, 25000.0, 0.09, 726.1591, 739.937 + 0.85, 25000.0, 0.11, 887.5906, 824.838 + 0.85, 25000.0, 0.13, 1049.015, 908.398 + 0.85, 25000.0, 0.15, 1210.433, 990.753 + 0.85, 25000.0, 0.17, 1371.844, 1072.04 + 0.85, 25000.0, 0.19, 1533.25, 1152.38 + 0.85, 25000.0, 0.21, 1694.649, 1231.93 + 0.85, 25000.0, 0.23, 1856.042, 1310.81 + 0.85, 25000.0, 0.25, 2017.43, 1389.16 + 0.85, 25000.0, 0.27, 2178.812, 1467.12 + 0.85, 25000.0, 0.29, 2340.189, 1544.81 + 0.85, 25000.0, 0.31, 2501.553, 1622.69 + 0.85, 25000.0, 0.33, 2662.907, 1700.83 + 0.85, 25000.0, 0.35, 2824.261, 1778.87 + 0.85, 25000.0, 0.37, 2985.62, 1856.81 + 0.85, 25000.0, 0.39, 3146.987, 1934.62 + 0.85, 25000.0, 0.41, 3308.392, 2012.19 + 0.85, 25000.0, 0.43, 3469.831, 2089.52 + 0.85, 25000.0, 0.45, 3631.272, 2166.73 + 0.85, 25000.0, 0.47, 3792.706, 2243.86 + 0.85, 25000.0, 0.49, 3954.124, 2320.93 + 0.85, 25000.0, 0.51, 4115.47, 2397.71 + 0.85, 25000.0, 0.53, 4276.747, 2474.3 + 0.85, 25000.0, 0.55, 4438.019, 2551.11 + 0.85, 25000.0, 0.57, 4599.3, 2628.28 + 0.85, 25000.0, 0.59, 4760.607, 2705.98 + 0.85, 25000.0, 0.61, 4922.028, 2784.55 + 0.85, 25000.0, 0.63, 5083.561, 2864.09 + 0.85, 25000.0, 0.65, 5245.111, 2944.47 + 0.85, 25000.0, 0.67, 5406.657, 3025.77 + 0.85, 25000.0, 0.69, 5568.179, 3108.03 + 0.85, 25000.0, 0.71, 5729.569, 3191.35 + 0.85, 25000.0, 0.73, 5890.828, 3275.78 + 0.85, 25000.0, 0.75, 6052.064, 3361.34 + 0.85, 25000.0, 0.77, 6213.3, 3448.1 + 0.85, 25000.0, 0.79, 6374.557, 3536.11 + 0.85, 25000.0, 0.81, 6535.945, 3625.82 + 0.85, 25000.0, 0.83, 6697.466, 3717.17 + 0.85, 25000.0, 0.85, 6859.009, 3809.65 + 0.85, 25000.0, 0.87, 7020.553, 3903.1 + 0.85, 25000.0, 0.89, 7182.077, 3997.38 + 0.85, 25000.0, 0.91, 7343.56, 4092.37 + 0.85, 25000.0, 0.93, 7504.98, 4187.92 + 0.85, 25000.0, 0.95, 7666.316, 4283.89 + 0.85, 25000.0, 0.97, 7827.547, 4380.13 + 0.85, 25000.0, 0.99, 7988.652, 4476.52 + 0.85, 30000.0, 0.0, 355.9122, 355.912 + 0.85, 30000.0, 0.05, 329.2, 461.7 + 0.85, 30000.0, 0.07, 460.8715, 531.041 + 0.85, 30000.0, 0.09, 592.5468, 599.242 + 0.85, 30000.0, 0.11, 724.2253, 666.393 + 0.85, 30000.0, 0.13, 855.9064, 732.585 + 0.85, 30000.0, 0.15, 987.5893, 797.907 + 0.85, 30000.0, 0.17, 1119.273, 862.45 + 0.85, 30000.0, 0.19, 1250.958, 926.304 + 0.85, 30000.0, 0.21, 1382.642, 989.558 + 0.85, 30000.0, 0.23, 1514.325, 1052.3 + 0.85, 30000.0, 0.25, 1646.007, 1114.63 + 0.85, 30000.0, 0.27, 1777.687, 1176.63 + 0.85, 30000.0, 0.29, 1909.363, 1238.38 + 0.85, 30000.0, 0.31, 2041.03, 1300.15 + 0.85, 30000.0, 0.33, 2172.687, 1361.99 + 0.85, 30000.0, 0.35, 2304.344, 1423.74 + 0.85, 30000.0, 0.37, 2436.003, 1485.41 + 0.85, 30000.0, 0.39, 2567.666, 1547.02 + 0.85, 30000.0, 0.41, 2699.346, 1608.59 + 0.85, 30000.0, 0.43, 2831.043, 1670.15 + 0.85, 30000.0, 0.45, 2962.744, 1731.65 + 0.85, 30000.0, 0.47, 3094.447, 1793.11 + 0.85, 30000.0, 0.49, 3226.15, 1854.51 + 0.85, 30000.0, 0.51, 3357.844, 1915.59 + 0.85, 30000.0, 0.53, 3489.53, 1976.4 + 0.85, 30000.0, 0.55, 3621.212, 2037.37 + 0.85, 30000.0, 0.57, 3752.89, 2098.64 + 0.85, 30000.0, 0.59, 3884.564, 2160.34 + 0.85, 30000.0, 0.61, 4016.23, 2222.81 + 0.85, 30000.0, 0.63, 4147.887, 2286.14 + 0.85, 30000.0, 0.65, 4279.544, 2350.18 + 0.85, 30000.0, 0.67, 4411.203, 2414.98 + 0.85, 30000.0, 0.69, 4542.866, 2480.58 + 0.85, 30000.0, 0.71, 4674.548, 2547.07 + 0.85, 30000.0, 0.73, 4806.247, 2614.49 + 0.85, 30000.0, 0.75, 4937.95, 2682.81 + 0.85, 30000.0, 0.77, 5069.653, 2752.08 + 0.85, 30000.0, 0.79, 5201.352, 2822.31 + 0.85, 30000.0, 0.81, 5333.032, 2893.8 + 0.85, 30000.0, 0.83, 5464.693, 2966.5 + 0.85, 30000.0, 0.85, 5596.35, 3040.06 + 0.85, 30000.0, 0.87, 5728.007, 3114.39 + 0.85, 30000.0, 0.89, 5859.668, 3189.38 + 0.85, 30000.0, 0.91, 5991.334, 3264.95 + 0.85, 30000.0, 0.93, 6123.011, 3340.98 + 0.85, 30000.0, 0.95, 6254.7, 3417.39 + 0.85, 30000.0, 0.97, 6386.405, 3494.07 + 0.85, 30000.0, 0.99, 6518.13, 3570.93 + 0.85, 35000.0, 0.0, 288.546, 288.546 + 0.85, 35000.0, 0.05, 269.4, 378.7 + 0.85, 35000.0, 0.07, 377.1685, 433.54 + 0.85, 35000.0, 0.09, 484.9332, 487.5 + 0.85, 35000.0, 0.11, 592.6947, 540.65 + 0.85, 35000.0, 0.13, 700.4536, 593.061 + 0.85, 35000.0, 0.15, 808.2107, 644.804 + 0.85, 35000.0, 0.17, 915.9667, 695.949 + 0.85, 35000.0, 0.19, 1023.722, 746.567 + 0.85, 35000.0, 0.21, 1131.478, 796.728 + 0.85, 35000.0, 0.23, 1239.235, 846.504 + 0.85, 35000.0, 0.25, 1346.993, 895.964 + 0.85, 35000.0, 0.27, 1454.753, 945.18 + 0.85, 35000.0, 0.29, 1562.517, 994.222 + 0.85, 35000.0, 0.31, 1670.289, 1043.29 + 0.85, 35000.0, 0.33, 1778.069, 1092.44 + 0.85, 35000.0, 0.35, 1885.85, 1141.52 + 0.85, 35000.0, 0.37, 1993.631, 1190.55 + 0.85, 35000.0, 0.39, 2101.411, 1239.53 + 0.85, 35000.0, 0.41, 2209.183, 1288.46 + 0.85, 35000.0, 0.43, 2316.946, 1337.34 + 0.85, 35000.0, 0.45, 2424.706, 1386.2 + 0.85, 35000.0, 0.47, 2532.465, 1435.04 + 0.85, 35000.0, 0.49, 2640.222, 1483.88 + 0.85, 35000.0, 0.51, 2747.98, 1532.53 + 0.85, 35000.0, 0.53, 2855.74, 1581.05 + 0.85, 35000.0, 0.55, 2963.5, 1629.73 + 0.85, 35000.0, 0.57, 3071.26, 1678.67 + 0.85, 35000.0, 0.59, 3179.02, 1727.98 + 0.85, 35000.0, 0.61, 3286.778, 1777.85 + 0.85, 35000.0, 0.63, 3394.535, 1828.36 + 0.85, 35000.0, 0.65, 3502.294, 1879.47 + 0.85, 35000.0, 0.67, 3610.054, 1931.23 + 0.85, 35000.0, 0.69, 3717.817, 1983.69 + 0.85, 35000.0, 0.71, 3825.59, 2037.02 + 0.85, 35000.0, 0.73, 3933.373, 2091.25 + 0.85, 35000.0, 0.75, 4041.156, 2146.26 + 0.85, 35000.0, 0.77, 4148.937, 2202.05 + 0.85, 35000.0, 0.79, 4256.714, 2258.62 + 0.85, 35000.0, 0.81, 4364.474, 2316.15 + 0.85, 35000.0, 0.83, 4472.217, 2374.58 + 0.85, 35000.0, 0.85, 4579.956, 2433.68 + 0.85, 35000.0, 0.87, 4687.693, 2493.33 + 0.85, 35000.0, 0.89, 4795.43, 2553.47 + 0.85, 35000.0, 0.91, 4903.171, 2614.01 + 0.85, 35000.0, 0.93, 5010.916, 2674.87 + 0.85, 35000.0, 0.95, 5118.669, 2735.95 + 0.85, 35000.0, 0.97, 5226.432, 2797.18 + 0.85, 35000.0, 0.99, 5334.207, 2858.46 + 0.85, 40000.0, 0.0, 228.356, 228.356 + 0.85, 40000.0, 0.05, 220.6, 318.6 + 0.85, 40000.0, 0.07, 308.8476, 362.776 + 0.85, 40000.0, 0.09, 397.0973, 406.263 + 0.85, 40000.0, 0.11, 485.3489, 449.118 + 0.85, 40000.0, 0.13, 573.6022, 491.399 + 0.85, 40000.0, 0.15, 661.8571, 533.164 + 0.85, 40000.0, 0.17, 750.1134, 574.471 + 0.85, 40000.0, 0.19, 838.3709, 615.378 + 0.85, 40000.0, 0.21, 926.6293, 655.943 + 0.85, 40000.0, 0.23, 1014.889, 696.223 + 0.85, 40000.0, 0.25, 1103.149, 736.277 + 0.85, 40000.0, 0.27, 1191.409, 776.162 + 0.85, 40000.0, 0.29, 1279.67, 815.936 + 0.85, 40000.0, 0.31, 1367.932, 855.787 + 0.85, 40000.0, 0.33, 1456.195, 895.74 + 0.85, 40000.0, 0.35, 1544.456, 935.663 + 0.85, 40000.0, 0.37, 1632.716, 975.549 + 0.85, 40000.0, 0.39, 1720.973, 1015.39 + 0.85, 40000.0, 0.41, 1809.221, 1055.13 + 0.85, 40000.0, 0.43, 1897.461, 1094.77 + 0.85, 40000.0, 0.45, 1985.7, 1134.4 + 0.85, 40000.0, 0.47, 2073.939, 1174.05 + 0.85, 40000.0, 0.49, 2162.179, 1213.73 + 0.85, 40000.0, 0.51, 2250.427, 1253.41 + 0.85, 40000.0, 0.53, 2338.684, 1293.12 + 0.85, 40000.0, 0.55, 2426.944, 1333.0 + 0.85, 40000.0, 0.57, 2515.205, 1373.12 + 0.85, 40000.0, 0.59, 2603.468, 1413.55 + 0.85, 40000.0, 0.61, 2691.73, 1454.34 + 0.85, 40000.0, 0.63, 2779.99, 1495.55 + 0.85, 40000.0, 0.65, 2868.25, 1537.26 + 0.85, 40000.0, 0.67, 2956.51, 1579.55 + 0.85, 40000.0, 0.69, 3044.77, 1622.47 + 0.85, 40000.0, 0.71, 3133.03, 1666.33 + 0.85, 40000.0, 0.73, 3221.29, 1711.13 + 0.85, 40000.0, 0.75, 3309.55, 1756.61 + 0.85, 40000.0, 0.77, 3397.81, 1802.75 + 0.85, 40000.0, 0.79, 3486.07, 1849.5 + 0.85, 40000.0, 0.81, 3574.332, 1896.79 + 0.85, 40000.0, 0.83, 3662.595, 1944.59 + 0.85, 40000.0, 0.85, 3750.856, 1992.93 + 0.85, 40000.0, 0.87, 3839.116, 2041.78 + 0.85, 40000.0, 0.89, 3927.373, 2091.14 + 0.85, 40000.0, 0.91, 4015.626, 2140.98 + 0.85, 40000.0, 0.93, 4103.875, 2191.3 + 0.85, 40000.0, 0.95, 4192.119, 2242.08 + 0.85, 40000.0, 0.97, 4280.356, 2293.29 + 0.85, 40000.0, 0.99, 4368.587, 2344.93 + 0.85, 43000.0, 0.0, 197.806, 197.806 + 0.85, 43000.0, 0.05, 192.7, 288.4 + 0.85, 43000.0, 0.07, 269.78, 326.723 + 0.85, 43000.0, 0.09, 346.86, 364.461 + 0.85, 43000.0, 0.11, 423.94, 401.663 + 0.85, 43000.0, 0.13, 501.02, 438.381 + 0.85, 43000.0, 0.15, 578.1, 474.664 + 0.85, 43000.0, 0.17, 655.18, 510.563 + 0.85, 43000.0, 0.19, 732.26, 546.127 + 0.85, 43000.0, 0.21, 809.34, 581.408 + 0.85, 43000.0, 0.23, 886.42, 616.454 + 0.85, 43000.0, 0.25, 963.5, 651.317 + 0.85, 43000.0, 0.27, 1040.58, 686.046 + 0.85, 43000.0, 0.29, 1117.66, 720.693 + 0.85, 43000.0, 0.31, 1194.74, 755.421 + 0.85, 43000.0, 0.33, 1271.82, 790.253 + 0.85, 43000.0, 0.35, 1348.9, 825.069 + 0.85, 43000.0, 0.37, 1425.98, 859.863 + 0.85, 43000.0, 0.39, 1503.06, 894.629 + 0.85, 43000.0, 0.41, 1580.14, 929.303 + 0.85, 43000.0, 0.43, 1657.22, 963.893 + 0.85, 43000.0, 0.45, 1734.3, 998.481 + 0.85, 43000.0, 0.47, 1811.38, 1033.09 + 0.85, 43000.0, 0.49, 1888.46, 1067.75 + 0.85, 43000.0, 0.51, 1965.538, 1102.43 + 0.85, 43000.0, 0.53, 2042.615, 1137.16 + 0.85, 43000.0, 0.55, 2119.694, 1172.04 + 0.85, 43000.0, 0.57, 2196.774, 1207.12 + 0.85, 43000.0, 0.59, 2273.857, 1242.44 + 0.85, 43000.0, 0.61, 2350.949, 1277.99 + 0.85, 43000.0, 0.63, 2428.049, 1313.82 + 0.85, 43000.0, 0.65, 2505.15, 1350.08 + 0.85, 43000.0, 0.67, 2582.251, 1386.82 + 0.85, 43000.0, 0.69, 2659.351, 1424.12 + 0.85, 43000.0, 0.71, 2736.443, 1462.27 + 0.85, 43000.0, 0.73, 2813.526, 1501.29 + 0.85, 43000.0, 0.75, 2890.606, 1540.93 + 0.85, 43000.0, 0.77, 2967.685, 1581.15 + 0.85, 43000.0, 0.79, 3044.762, 1621.92 + 0.85, 43000.0, 0.81, 3121.84, 1663.14 + 0.85, 43000.0, 0.83, 3198.92, 1704.8 + 0.85, 43000.0, 0.85, 3276.0, 1746.95 + 0.85, 43000.0, 0.87, 3353.08, 1789.6 + 0.85, 43000.0, 0.89, 3430.16, 1832.74 + 0.85, 43000.0, 0.91, 3507.24, 1876.38 + 0.85, 43000.0, 0.93, 3584.32, 1920.51 + 0.85, 43000.0, 0.95, 3661.4, 1965.13 + 0.85, 43000.0, 0.97, 3738.48, 2010.23 + 0.85, 43000.0, 0.99, 3815.56, 2055.82 + 0.85, 48000.0, 0.0, 155.7133, 155.713 + 0.85, 48000.0, 0.05, 151.8, 227.1 + 0.85, 48000.0, 0.07, 212.4876, 257.278 + 0.85, 48000.0, 0.09, 273.1773, 286.997 + 0.85, 48000.0, 0.11, 333.8689, 316.297 + 0.85, 48000.0, 0.13, 394.5622, 345.216 + 0.85, 48000.0, 0.15, 455.2571, 373.793 + 0.85, 48000.0, 0.17, 515.9534, 402.068 + 0.85, 48000.0, 0.19, 576.6509, 430.08 + 0.85, 48000.0, 0.21, 637.3493, 457.869 + 0.85, 48000.0, 0.23, 698.0486, 485.473 + 0.85, 48000.0, 0.25, 758.7486, 512.931 + 0.85, 48000.0, 0.27, 819.449, 540.284 + 0.85, 48000.0, 0.29, 880.1496, 567.57 + 0.85, 48000.0, 0.31, 940.85, 594.917 + 0.85, 48000.0, 0.33, 1001.55, 622.344 + 0.85, 48000.0, 0.35, 1062.25, 649.756 + 0.85, 48000.0, 0.37, 1122.95, 677.151 + 0.85, 48000.0, 0.39, 1183.65, 704.523 + 0.85, 48000.0, 0.41, 1244.35, 731.824 + 0.85, 48000.0, 0.43, 1305.05, 759.059 + 0.85, 48000.0, 0.45, 1365.75, 786.294 + 0.85, 48000.0, 0.47, 1426.45, 813.547 + 0.85, 48000.0, 0.49, 1487.15, 840.836 + 0.85, 48000.0, 0.51, 1547.848, 868.144 + 0.85, 48000.0, 0.53, 1608.545, 895.497 + 0.85, 48000.0, 0.55, 1669.244, 922.969 + 0.85, 48000.0, 0.57, 1729.944, 950.594 + 0.85, 48000.0, 0.59, 1790.647, 978.41 + 0.85, 48000.0, 0.61, 1851.359, 1006.41 + 0.85, 48000.0, 0.63, 1912.079, 1034.64 + 0.85, 48000.0, 0.65, 1972.8, 1063.2 + 0.85, 48000.0, 0.67, 2033.521, 1092.14 + 0.85, 48000.0, 0.69, 2094.241, 1121.53 + 0.85, 48000.0, 0.71, 2154.953, 1151.57 + 0.85, 48000.0, 0.73, 2215.656, 1182.3 + 0.85, 48000.0, 0.75, 2276.356, 1213.52 + 0.85, 48000.0, 0.77, 2337.055, 1245.19 + 0.85, 48000.0, 0.79, 2397.752, 1277.29 + 0.85, 48000.0, 0.81, 2458.45, 1309.75 + 0.85, 48000.0, 0.83, 2519.15, 1342.54 + 0.85, 48000.0, 0.85, 2579.85, 1375.73 + 0.85, 48000.0, 0.87, 2640.55, 1409.3 + 0.85, 48000.0, 0.89, 2701.25, 1443.27 + 0.85, 48000.0, 0.91, 2761.95, 1477.63 + 0.85, 48000.0, 0.93, 2822.65, 1512.38 + 0.85, 48000.0, 0.95, 2883.35, 1547.53 + 0.85, 48000.0, 0.97, 2944.05, 1583.06 + 0.85, 48000.0, 0.99, 3004.75, 1618.99 + 0.9, 0.0, 0.0, 1115.524, 1115.52 + 0.9, 0.0, 0.05, 226.6625, 2555.67 + 0.9, 0.0, 0.07, 414.3961, 2610.75 + 0.9, 0.0, 0.09, 596.6793, 2677.52 + 0.9, 0.0, 0.11, 773.9057, 2755.06 + 0.9, 0.0, 0.13, 946.4689, 2842.49 + 0.9, 0.0, 0.15, 1114.763, 2938.88 + 0.9, 0.0, 0.17, 1279.18, 3043.35 + 0.9, 0.0, 0.19, 1440.115, 3154.98 + 0.9, 0.0, 0.21, 1597.962, 3272.87 + 0.9, 0.0, 0.23, 1753.113, 3396.13 + 0.9, 0.0, 0.25, 1905.962, 3523.84 + 0.9, 0.0, 0.27, 2056.904, 3655.11 + 0.9, 0.0, 0.29, 2206.331, 3789.03 + 0.9, 0.0, 0.31, 2354.638, 3924.69 + 0.9, 0.0, 0.33, 2502.217, 4061.2 + 0.9, 0.0, 0.35, 2649.463, 4197.66 + 0.9, 0.0, 0.37, 2796.768, 4333.15 + 0.9, 0.0, 0.39, 2944.527, 4466.77 + 0.9, 0.0, 0.41, 3094.163, 4593.62 + 0.9, 0.0, 0.43, 3245.82, 4713.76 + 0.9, 0.0, 0.45, 3398.363, 4832.24 + 0.9, 0.0, 0.47, 3551.685, 4950.1 + 0.9, 0.0, 0.49, 3705.682, 5068.38 + 0.9, 0.0, 0.51, 3860.757, 5192.11 + 0.9, 0.0, 0.53, 4016.682, 5321.36 + 0.9, 0.0, 0.55, 4172.594, 5451.24 + 0.9, 0.0, 0.57, 4328.139, 5580.85 + 0.9, 0.0, 0.59, 4482.966, 5709.3 + 0.9, 0.0, 0.61, 4635.865, 5834.05 + 0.9, 0.0, 0.63, 4786.691, 5954.61 + 0.9, 0.0, 0.65, 4936.363, 6072.49 + 0.9, 0.0, 0.67, 5084.942, 6187.57 + 0.9, 0.0, 0.69, 5232.492, 6299.74 + 0.9, 0.0, 0.71, 5377.781, 6407.37 + 0.9, 0.0, 0.73, 5521.185, 6510.72 + 0.9, 0.0, 0.75, 5664.688, 6611.93 + 0.9, 0.0, 0.77, 5808.978, 6711.62 + 0.9, 0.0, 0.79, 5954.746, 6810.43 + 0.9, 0.0, 0.81, 6105.733, 6910.42 + 0.9, 0.0, 0.83, 6261.887, 7011.86 + 0.9, 0.0, 0.85, 6419.369, 7113.25 + 0.9, 0.0, 0.87, 6577.389, 7214.51 + 0.9, 0.0, 0.89, 6735.157, 7315.57 + 0.9, 0.0, 0.91, 6891.884, 7416.35 + 0.9, 0.0, 0.93, 7046.78, 7516.8 + 0.9, 0.0, 0.95, 7199.056, 7616.82 + 0.9, 0.0, 0.97, 7347.922, 7716.36 + 0.9, 0.0, 0.99, 7492.588, 7815.34 + 0.9, 2000.0, 0.0, 1044.438, 1044.44 + 0.9, 2000.0, 0.05, 361.35, 1911.66 + 0.9, 2000.0, 0.07, 512.171, 2072.96 + 0.9, 2000.0, 0.09, 661.528, 2228.81 + 0.9, 2000.0, 0.11, 809.557, 2379.57 + 0.9, 2000.0, 0.13, 956.394, 2525.62 + 0.9, 2000.0, 0.15, 1102.175, 2667.34 + 0.9, 2000.0, 0.17, 1247.036, 2805.12 + 0.9, 2000.0, 0.19, 1391.113, 2939.32 + 0.9, 2000.0, 0.21, 1534.542, 3070.33 + 0.9, 2000.0, 0.23, 1677.459, 3198.52 + 0.9, 2000.0, 0.25, 1820.0, 3324.28 + 0.9, 2000.0, 0.27, 1962.301, 3447.98 + 0.9, 2000.0, 0.29, 2104.498, 3570.0 + 0.9, 2000.0, 0.31, 2246.727, 3690.72 + 0.9, 2000.0, 0.33, 2389.124, 3810.52 + 0.9, 2000.0, 0.35, 2531.825, 3929.77 + 0.9, 2000.0, 0.37, 2674.966, 4048.85 + 0.9, 2000.0, 0.39, 2818.683, 4168.15 + 0.9, 2000.0, 0.41, 2963.884, 4289.31 + 0.9, 2000.0, 0.43, 3110.518, 4412.39 + 0.9, 2000.0, 0.45, 3257.575, 4535.9 + 0.9, 2000.0, 0.47, 3404.816, 4659.6 + 0.9, 2000.0, 0.49, 3552.002, 4783.26 + 0.9, 2000.0, 0.51, 3698.323, 4908.06 + 0.9, 2000.0, 0.53, 3843.679, 5033.43 + 0.9, 2000.0, 0.55, 3988.681, 5157.01 + 0.9, 2000.0, 0.57, 4133.37, 5277.89 + 0.9, 2000.0, 0.59, 4277.784, 5395.13 + 0.9, 2000.0, 0.61, 4421.368, 5502.58 + 0.9, 2000.0, 0.63, 4564.306, 5600.58 + 0.9, 2000.0, 0.65, 4707.519, 5695.98 + 0.9, 2000.0, 0.67, 4851.333, 5790.4 + 0.9, 2000.0, 0.69, 4996.077, 5885.44 + 0.9, 2000.0, 0.71, 5144.911, 5990.62 + 0.9, 2000.0, 0.73, 5297.474, 6105.65 + 0.9, 2000.0, 0.75, 5449.888, 6220.4 + 0.9, 2000.0, 0.77, 5601.105, 6332.65 + 0.9, 2000.0, 0.79, 5750.08, 6440.19 + 0.9, 2000.0, 0.81, 5890.34, 6528.21 + 0.9, 2000.0, 0.83, 6022.153, 6597.55 + 0.9, 2000.0, 0.85, 6152.531, 6664.68 + 0.9, 2000.0, 0.87, 6283.06, 6733.47 + 0.9, 2000.0, 0.89, 6415.323, 6807.83 + 0.9, 2000.0, 0.91, 6550.905, 6891.62 + 0.9, 2000.0, 0.93, 6691.392, 6988.74 + 0.9, 2000.0, 0.95, 6838.369, 7103.08 + 0.9, 2000.0, 0.97, 6993.419, 7238.5 + 0.9, 2000.0, 0.99, 7158.128, 7398.91 + 0.9, 5000.0, 0.0, 944.5859, 944.586 + 0.9, 5000.0, 0.05, 648.4563, 1518.19 + 0.9, 5000.0, 0.07, 739.396, 1729.9 + 0.9, 5000.0, 0.09, 839.8369, 1927.42 + 0.9, 5000.0, 0.11, 949.0742, 2111.82 + 0.9, 5000.0, 0.13, 1066.403, 2284.15 + 0.9, 5000.0, 0.15, 1191.119, 2445.44 + 0.9, 5000.0, 0.17, 1322.516, 2596.75 + 0.9, 5000.0, 0.19, 1459.891, 2739.13 + 0.9, 5000.0, 0.21, 1602.539, 2873.63 + 0.9, 5000.0, 0.23, 1749.754, 3001.3 + 0.9, 5000.0, 0.25, 1900.831, 3123.19 + 0.9, 5000.0, 0.27, 2055.067, 3240.34 + 0.9, 5000.0, 0.29, 2211.756, 3353.82 + 0.9, 5000.0, 0.31, 2370.193, 3464.66 + 0.9, 5000.0, 0.33, 2529.674, 3573.91 + 0.9, 5000.0, 0.35, 2689.494, 3682.64 + 0.9, 5000.0, 0.37, 2848.947, 3791.88 + 0.9, 5000.0, 0.39, 3007.33, 3902.68 + 0.9, 5000.0, 0.41, 3161.578, 4021.62 + 0.9, 5000.0, 0.43, 3311.558, 4148.39 + 0.9, 5000.0, 0.45, 3460.069, 4275.88 + 0.9, 5000.0, 0.47, 3607.549, 4402.44 + 0.9, 5000.0, 0.49, 3754.439, 4526.45 + 0.9, 5000.0, 0.51, 3901.801, 4639.76 + 0.9, 5000.0, 0.53, 4049.923, 4742.31 + 0.9, 5000.0, 0.55, 4198.319, 4842.21 + 0.9, 5000.0, 0.57, 4347.124, 4941.0 + 0.9, 5000.0, 0.59, 4496.476, 5040.23 + 0.9, 5000.0, 0.61, 4646.54, 5145.6 + 0.9, 5000.0, 0.63, 4797.445, 5257.65 + 0.9, 5000.0, 0.65, 4949.288, 5371.76 + 0.9, 5000.0, 0.67, 5102.19, 5487.49 + 0.9, 5000.0, 0.69, 5256.275, 5604.37 + 0.9, 5000.0, 0.71, 5413.234, 5724.54 + 0.9, 5000.0, 0.73, 5572.811, 5846.92 + 0.9, 5000.0, 0.75, 5732.8, 5967.17 + 0.9, 5000.0, 0.77, 5892.565, 6083.57 + 0.9, 5000.0, 0.79, 6051.47, 6194.41 + 0.9, 5000.0, 0.81, 6206.22, 6288.44 + 0.9, 5000.0, 0.83, 6356.823, 6366.26 + 0.9, 5000.0, 0.85, 6506.588, 6440.26 + 0.9, 5000.0, 0.87, 6656.164, 6513.33 + 0.9, 5000.0, 0.89, 6806.203, 6588.35 + 0.9, 5000.0, 0.91, 6957.357, 6668.22 + 0.9, 5000.0, 0.93, 7110.276, 6755.82 + 0.9, 5000.0, 0.95, 7265.613, 6854.04 + 0.9, 5000.0, 0.97, 7424.017, 6965.76 + 0.9, 5000.0, 0.99, 7586.14, 7093.89 + 0.9, 10000.0, 0.0, 795.1056, 795.106 + 0.9, 10000.0, 0.05, -274.8937, 1362.83 + 0.9, 10000.0, 0.07, -210.0616, 1417.75 + 0.9, 10000.0, 0.09, -156.2979, 1472.46 + 0.9, 10000.0, 0.11, -112.749, 1526.86 + 0.9, 10000.0, 0.13, -78.56135, 1580.88 + 0.9, 10000.0, 0.15, -52.88125, 1634.44 + 0.9, 10000.0, 0.17, -34.85515, 1687.46 + 0.9, 10000.0, 0.19, -23.62945, 1739.86 + 0.9, 10000.0, 0.21, -18.35055, 1791.55 + 0.9, 10000.0, 0.23, -18.16485, 1842.46 + 0.9, 10000.0, 0.25, -22.21875, 1892.51 + 0.9, 10000.0, 0.27, -29.65865, 1941.6 + 0.9, 10000.0, 0.29, -39.63095, 1989.67 + 0.9, 10000.0, 0.31, -51.28205, 2036.64 + 0.9, 10000.0, 0.33, -63.75835, 2082.41 + 0.9, 10000.0, 0.35, -76.20625, 2126.92 + 0.9, 10000.0, 0.37, -87.77215, 2170.07 + 0.9, 10000.0, 0.39, -97.60245, 2211.8 + 0.9, 10000.0, 0.41, -101.5815, 2251.24 + 0.9, 10000.0, 0.43, -99.6465, 2288.5 + 0.9, 10000.0, 0.45, -95.7875, 2324.66 + 0.9, 10000.0, 0.47, -90.7325, 2359.99 + 0.9, 10000.0, 0.49, -85.2095, 2394.8 + 0.9, 10000.0, 0.51, -80.46295, 2432.04 + 0.9, 10000.0, 0.53, -77.09565, 2471.37 + 0.9, 10000.0, 0.55, -75.06875, 2509.11 + 0.9, 10000.0, 0.57, -74.85985, 2544.28 + 0.9, 10000.0, 0.59, -76.94655, 2575.86 + 0.9, 10000.0, 0.61, -86.0717, 2600.78 + 0.9, 10000.0, 0.63, -101.6789, 2618.54 + 0.9, 10000.0, 0.65, -117.9125, 2631.25 + 0.9, 10000.0, 0.67, -133.1821, 2638.92 + 0.9, 10000.0, 0.69, -145.8973, 2641.56 + 0.9, 10000.0, 0.71, -149.4698, 2633.36 + 0.9, 10000.0, 0.73, -143.5209, 2615.74 + 0.9, 10000.0, 0.75, -133.8812, 2597.38 + 0.9, 10000.0, 0.77, -121.3835, 2581.13 + 0.9, 10000.0, 0.79, -106.8606, 2569.81 + 0.9, 10000.0, 0.81, -89.3881, 2581.62 + 0.9, 10000.0, 0.83, -70.2247, 2615.68 + 0.9, 10000.0, 0.85, -52.8125, 2652.06 + 0.9, 10000.0, 0.87, -38.8363, 2686.16 + 0.9, 10000.0, 0.89, -29.9809, 2713.39 + 0.9, 10000.0, 0.91, -27.9311, 2729.17 + 0.9, 10000.0, 0.93, -34.3717, 2728.89 + 0.9, 10000.0, 0.95, -50.9875, 2707.97 + 0.9, 10000.0, 0.97, -79.4633, 2661.81 + 0.9, 10000.0, 0.99, -121.4839, 2585.82 + 0.9, 15000.0, 0.0, 665.0115, 665.011 + 0.9, 15000.0, 0.05, 582.0, 889.8 + 0.9, 15000.0, 0.07, 814.5098, 1031.29 + 0.9, 15000.0, 0.09, 1047.29, 1170.24 + 0.9, 15000.0, 0.11, 1280.3, 1306.82 + 0.9, 15000.0, 0.13, 1513.499, 1441.24 + 0.9, 15000.0, 0.15, 1746.846, 1573.68 + 0.9, 15000.0, 0.17, 1980.302, 1704.34 + 0.9, 15000.0, 0.19, 2213.826, 1833.4 + 0.9, 15000.0, 0.21, 2447.376, 1961.07 + 0.9, 15000.0, 0.23, 2680.913, 2087.53 + 0.9, 15000.0, 0.25, 2914.396, 2212.97 + 0.9, 15000.0, 0.27, 3147.784, 2337.59 + 0.9, 15000.0, 0.29, 3381.037, 2461.58 + 0.9, 15000.0, 0.31, 3613.869, 2585.41 + 0.9, 15000.0, 0.33, 3846.299, 2709.21 + 0.9, 15000.0, 0.35, 4078.65, 2832.75 + 0.9, 15000.0, 0.37, 4311.001, 2956.08 + 0.9, 15000.0, 0.39, 4543.431, 3079.25 + 0.9, 15000.0, 0.41, 4776.26, 3202.51 + 0.9, 15000.0, 0.43, 5009.508, 3325.86 + 0.9, 15000.0, 0.45, 5242.894, 3449.09 + 0.9, 15000.0, 0.47, 5476.377, 3572.16 + 0.9, 15000.0, 0.49, 5709.919, 3695.04 + 0.9, 15000.0, 0.51, 5943.235, 3816.89 + 0.9, 15000.0, 0.53, 6176.345, 3937.87 + 0.9, 15000.0, 0.55, 6409.575, 4059.15 + 0.9, 15000.0, 0.57, 6643.005, 4181.08 + 0.9, 15000.0, 0.59, 6876.715, 4304.03 + 0.9, 15000.0, 0.61, 7111.643, 4429.57 + 0.9, 15000.0, 0.63, 7347.661, 4557.75 + 0.9, 15000.0, 0.65, 7583.575, 4687.14 + 0.9, 15000.0, 0.67, 7819.049, 4817.51 + 0.9, 15000.0, 0.69, 8053.747, 4948.63 + 0.9, 15000.0, 0.71, 8285.69, 5079.03 + 0.9, 15000.0, 0.73, 8514.939, 5208.78 + 0.9, 15000.0, 0.75, 8743.6, 5339.49 + 0.9, 15000.0, 0.77, 8972.133, 5471.56 + 0.9, 15000.0, 0.79, 9200.998, 5605.34 + 0.9, 15000.0, 0.81, 9432.082, 5741.95 + 0.9, 15000.0, 0.83, 9665.498, 5881.59 + 0.9, 15000.0, 0.85, 9899.594, 6023.54 + 0.9, 15000.0, 0.87, 10134.14, 6167.83 + 0.9, 15000.0, 0.89, 10368.91, 6314.48 + 0.9, 15000.0, 0.91, 10603.66, 6463.52 + 0.9, 15000.0, 0.93, 10838.18, 6614.96 + 0.9, 15000.0, 0.95, 11072.23, 6768.84 + 0.9, 15000.0, 0.97, 11305.58, 6925.16 + 0.9, 15000.0, 0.99, 11538.01, 7083.96 + 0.9, 20000.0, 0.0, 552.3898, 552.39 + 0.9, 20000.0, 0.05, 492.4, 731.8 + 0.9, 20000.0, 0.07, 688.7394, 847.339 + 0.9, 20000.0, 0.09, 885.1487, 960.601 + 0.9, 20000.0, 0.11, 1081.62, 1071.78 + 0.9, 20000.0, 0.13, 1278.146, 1181.05 + 0.9, 20000.0, 0.15, 1474.718, 1288.62 + 0.9, 20000.0, 0.17, 1671.329, 1394.66 + 0.9, 20000.0, 0.19, 1867.97, 1499.38 + 0.9, 20000.0, 0.21, 2064.635, 1602.96 + 0.9, 20000.0, 0.23, 2261.314, 1705.58 + 0.9, 20000.0, 0.25, 2458.001, 1807.44 + 0.9, 20000.0, 0.27, 2654.688, 1908.73 + 0.9, 20000.0, 0.29, 2851.366, 2009.63 + 0.9, 20000.0, 0.31, 3047.973, 2110.7 + 0.9, 20000.0, 0.33, 3244.513, 2212.03 + 0.9, 20000.0, 0.35, 3441.062, 2313.28 + 0.9, 20000.0, 0.37, 3637.64, 2414.48 + 0.9, 20000.0, 0.39, 3834.264, 2515.63 + 0.9, 20000.0, 0.41, 4031.041, 2616.96 + 0.9, 20000.0, 0.43, 4227.968, 2718.42 + 0.9, 20000.0, 0.45, 4424.937, 2819.76 + 0.9, 20000.0, 0.47, 4621.927, 2920.88 + 0.9, 20000.0, 0.49, 4818.914, 3021.71 + 0.9, 20000.0, 0.51, 5015.849, 3121.33 + 0.9, 20000.0, 0.53, 5212.715, 3219.85 + 0.9, 20000.0, 0.55, 5409.531, 3318.48 + 0.9, 20000.0, 0.57, 5606.29, 3417.55 + 0.9, 20000.0, 0.59, 5802.982, 3517.38 + 0.9, 20000.0, 0.61, 5999.598, 3619.2 + 0.9, 20000.0, 0.63, 6196.13, 3723.12 + 0.9, 20000.0, 0.65, 6392.569, 3828.2 + 0.9, 20000.0, 0.67, 6588.905, 3934.35 + 0.9, 20000.0, 0.69, 6785.131, 4041.49 + 0.9, 20000.0, 0.71, 6981.003, 4149.06 + 0.9, 20000.0, 0.73, 7176.569, 4257.09 + 0.9, 20000.0, 0.75, 7372.169, 4366.21 + 0.9, 20000.0, 0.77, 7567.906, 4476.55 + 0.9, 20000.0, 0.79, 7763.886, 4588.28 + 0.9, 20000.0, 0.81, 7960.706, 4701.86 + 0.9, 20000.0, 0.83, 8158.35, 4817.36 + 0.9, 20000.0, 0.85, 8356.194, 4934.44 + 0.9, 20000.0, 0.87, 8554.104, 5053.07 + 0.9, 20000.0, 0.89, 8751.946, 5173.24 + 0.9, 20000.0, 0.91, 8949.587, 5294.94 + 0.9, 20000.0, 0.93, 9146.893, 5418.14 + 0.9, 20000.0, 0.95, 9343.731, 5542.84 + 0.9, 20000.0, 0.97, 9539.967, 5669.01 + 0.9, 20000.0, 0.99, 9735.467, 5796.64 + 0.9, 25000.0, 0.0, 455.4397, 455.44 + 0.9, 25000.0, 0.05, 413.8, 599.1 + 0.9, 25000.0, 0.07, 579.6939, 693.544 + 0.9, 25000.0, 0.09, 745.5598, 785.928 + 0.9, 25000.0, 0.11, 911.3995, 876.44 + 0.9, 25000.0, 0.13, 1077.215, 965.272 + 0.9, 25000.0, 0.15, 1243.007, 1052.61 + 0.9, 25000.0, 0.17, 1408.779, 1138.66 + 0.9, 25000.0, 0.19, 1574.531, 1223.59 + 0.9, 25000.0, 0.21, 1740.265, 1307.6 + 0.9, 25000.0, 0.23, 1905.984, 1390.89 + 0.9, 25000.0, 0.25, 2071.689, 1473.64 + 0.9, 25000.0, 0.27, 2237.381, 1556.04 + 0.9, 25000.0, 0.29, 2403.063, 1638.28 + 0.9, 25000.0, 0.31, 2568.723, 1721.18 + 0.9, 25000.0, 0.33, 2734.366, 1804.78 + 0.9, 25000.0, 0.35, 2900.013, 1888.33 + 0.9, 25000.0, 0.37, 3065.672, 1971.73 + 0.9, 25000.0, 0.39, 3231.351, 2054.87 + 0.9, 25000.0, 0.41, 3397.125, 2137.18 + 0.9, 25000.0, 0.43, 3562.987, 2218.65 + 0.9, 25000.0, 0.45, 3728.844, 2299.85 + 0.9, 25000.0, 0.47, 3894.67, 2380.87 + 0.9, 25000.0, 0.49, 4060.442, 2461.82 + 0.9, 25000.0, 0.51, 4225.988, 2542.66 + 0.9, 25000.0, 0.53, 4391.318, 2623.52 + 0.9, 25000.0, 0.55, 4556.625, 2704.72 + 0.9, 25000.0, 0.57, 4721.956, 2786.45 + 0.9, 25000.0, 0.59, 4887.358, 2868.87 + 0.9, 25000.0, 0.61, 5053.081, 2952.42 + 0.9, 25000.0, 0.63, 5219.123, 3037.21 + 0.9, 25000.0, 0.65, 5385.225, 3123.03 + 0.9, 25000.0, 0.67, 5551.335, 3209.92 + 0.9, 25000.0, 0.69, 5717.401, 3297.95 + 0.9, 25000.0, 0.71, 5883.149, 3387.13 + 0.9, 25000.0, 0.73, 6048.581, 3477.52 + 0.9, 25000.0, 0.75, 6213.969, 3569.21 + 0.9, 25000.0, 0.77, 6379.367, 3662.25 + 0.9, 25000.0, 0.79, 6544.829, 3756.72 + 0.9, 25000.0, 0.81, 6710.647, 3853.28 + 0.9, 25000.0, 0.83, 6876.817, 3951.85 + 0.9, 25000.0, 0.85, 7043.038, 4051.58 + 0.9, 25000.0, 0.87, 7209.246, 4152.22 + 0.9, 25000.0, 0.89, 7375.38, 4253.55 + 0.9, 25000.0, 0.91, 7541.378, 4355.33 + 0.9, 25000.0, 0.93, 7707.176, 4457.32 + 0.9, 25000.0, 0.95, 7872.713, 4559.28 + 0.9, 25000.0, 0.97, 8037.925, 4660.97 + 0.9, 25000.0, 0.99, 8202.751, 4762.16 + 0.9, 30000.0, 0.0, 372.4894, 372.489 + 0.9, 30000.0, 0.05, 336.2, 487.2 + 0.9, 30000.0, 0.07, 470.4697, 559.843 + 0.9, 30000.0, 0.09, 604.7567, 631.514 + 0.9, 30000.0, 0.11, 739.0578, 702.278 + 0.9, 30000.0, 0.13, 873.3698, 772.199 + 0.9, 30000.0, 0.15, 1007.689, 841.339 + 0.9, 30000.0, 0.17, 1142.013, 909.764 + 0.9, 30000.0, 0.19, 1276.338, 977.538 + 0.9, 30000.0, 0.21, 1410.661, 1044.72 + 0.9, 30000.0, 0.23, 1544.978, 1111.39 + 0.9, 30000.0, 0.25, 1679.287, 1177.59 + 0.9, 30000.0, 0.27, 1813.584, 1243.39 + 0.9, 30000.0, 0.29, 1947.866, 1308.87 + 0.9, 30000.0, 0.31, 2082.093, 1374.14 + 0.9, 30000.0, 0.33, 2216.271, 1439.25 + 0.9, 30000.0, 0.35, 2350.45, 1504.17 + 0.9, 30000.0, 0.37, 2484.645, 1568.95 + 0.9, 30000.0, 0.39, 2618.871, 1633.61 + 0.9, 30000.0, 0.41, 2753.198, 1698.17 + 0.9, 30000.0, 0.43, 2887.626, 1762.69 + 0.9, 30000.0, 0.45, 3022.087, 1827.19 + 0.9, 30000.0, 0.47, 3156.569, 1891.71 + 0.9, 30000.0, 0.49, 3291.057, 1956.28 + 0.9, 30000.0, 0.51, 3425.504, 2020.77 + 0.9, 30000.0, 0.53, 3559.904, 2085.25 + 0.9, 30000.0, 0.55, 3694.3, 2150.02 + 0.9, 30000.0, 0.57, 3828.696, 2215.2 + 0.9, 30000.0, 0.59, 3963.096, 2280.91 + 0.9, 30000.0, 0.61, 4097.546, 2347.47 + 0.9, 30000.0, 0.63, 4232.04, 2414.95 + 0.9, 30000.0, 0.65, 4366.525, 2483.18 + 0.9, 30000.0, 0.67, 4500.986, 2552.19 + 0.9, 30000.0, 0.69, 4635.408, 2621.99 + 0.9, 30000.0, 0.71, 4769.7, 2692.6 + 0.9, 30000.0, 0.73, 4903.866, 2764.04 + 0.9, 30000.0, 0.75, 5038.006, 2836.37 + 0.9, 30000.0, 0.77, 5172.145, 2909.63 + 0.9, 30000.0, 0.79, 5306.305, 2983.83 + 0.9, 30000.0, 0.81, 5440.597, 3059.24 + 0.9, 30000.0, 0.83, 5575.022, 3135.82 + 0.9, 30000.0, 0.85, 5709.475, 3213.31 + 0.9, 30000.0, 0.87, 5843.936, 3291.63 + 0.9, 30000.0, 0.89, 5978.385, 3370.7 + 0.9, 30000.0, 0.91, 6112.805, 3450.46 + 0.9, 30000.0, 0.93, 6247.174, 3530.84 + 0.9, 30000.0, 0.95, 6381.475, 3611.76 + 0.9, 30000.0, 0.97, 6515.688, 3693.16 + 0.9, 30000.0, 0.99, 6649.793, 3774.97 + 0.9, 35000.0, 0.0, 301.9855, 301.986 + 0.9, 35000.0, 0.05, 274.4, 398.1 + 0.9, 35000.0, 0.07, 384.1266, 455.966 + 0.9, 35000.0, 0.09, 493.8614, 512.898 + 0.9, 35000.0, 0.11, 603.6031, 568.971 + 0.9, 35000.0, 0.13, 713.3509, 624.261 + 0.9, 35000.0, 0.15, 823.1036, 678.843 + 0.9, 35000.0, 0.17, 932.8601, 732.793 + 0.9, 35000.0, 0.19, 1042.62, 786.188 + 0.9, 35000.0, 0.21, 1152.381, 839.102 + 0.9, 35000.0, 0.23, 1262.143, 891.611 + 0.9, 35000.0, 0.25, 1371.904, 943.791 + 0.9, 35000.0, 0.27, 1481.665, 995.719 + 0.9, 35000.0, 0.29, 1591.422, 1047.47 + 0.9, 35000.0, 0.31, 1701.171, 1099.27 + 0.9, 35000.0, 0.33, 1810.911, 1151.16 + 0.9, 35000.0, 0.35, 1920.65, 1202.99 + 0.9, 35000.0, 0.37, 2030.389, 1254.76 + 0.9, 35000.0, 0.39, 2140.129, 1306.47 + 0.9, 35000.0, 0.41, 2249.877, 1358.09 + 0.9, 35000.0, 0.43, 2359.634, 1409.63 + 0.9, 35000.0, 0.45, 2469.394, 1461.14 + 0.9, 35000.0, 0.47, 2579.155, 1512.64 + 0.9, 35000.0, 0.49, 2688.918, 1564.14 + 0.9, 35000.0, 0.51, 2798.68, 1615.49 + 0.9, 35000.0, 0.53, 2908.44, 1666.75 + 0.9, 35000.0, 0.55, 3018.2, 1718.19 + 0.9, 35000.0, 0.57, 3127.96, 1769.93 + 0.9, 35000.0, 0.59, 3237.72, 1822.06 + 0.9, 35000.0, 0.61, 3347.482, 1874.78 + 0.9, 35000.0, 0.63, 3457.245, 1928.17 + 0.9, 35000.0, 0.65, 3567.006, 1982.2 + 0.9, 35000.0, 0.67, 3676.766, 2036.92 + 0.9, 35000.0, 0.69, 3786.523, 2092.37 + 0.9, 35000.0, 0.71, 3896.273, 2148.75 + 0.9, 35000.0, 0.73, 4006.016, 2206.08 + 0.9, 35000.0, 0.75, 4115.756, 2264.23 + 0.9, 35000.0, 0.77, 4225.495, 2323.2 + 0.9, 35000.0, 0.79, 4335.232, 2383.0 + 0.9, 35000.0, 0.81, 4444.968, 2443.79 + 0.9, 35000.0, 0.83, 4554.705, 2505.55 + 0.9, 35000.0, 0.85, 4664.444, 2567.98 + 0.9, 35000.0, 0.87, 4774.184, 2630.99 + 0.9, 35000.0, 0.89, 4883.927, 2694.49 + 0.9, 35000.0, 0.91, 4993.674, 2758.4 + 0.9, 35000.0, 0.93, 5103.425, 2822.6 + 0.9, 35000.0, 0.95, 5213.181, 2887.03 + 0.9, 35000.0, 0.97, 5322.944, 2951.57 + 0.9, 35000.0, 0.99, 5432.713, 3016.13 + 0.9, 40000.0, 0.0, 238.9921, 238.992 + 0.9, 40000.0, 0.05, 224.5, 333.5 + 0.9, 40000.0, 0.07, 314.2742, 380.167 + 0.9, 40000.0, 0.09, 404.0586, 426.087 + 0.9, 40000.0, 0.11, 493.852, 471.321 + 0.9, 40000.0, 0.13, 583.6531, 515.934 + 0.9, 40000.0, 0.15, 673.4607, 559.989 + 0.9, 40000.0, 0.17, 763.2736, 603.549 + 0.9, 40000.0, 0.19, 853.0904, 646.678 + 0.9, 40000.0, 0.21, 942.9101, 689.438 + 0.9, 40000.0, 0.23, 1032.731, 731.893 + 0.9, 40000.0, 0.25, 1122.553, 774.107 + 0.9, 40000.0, 0.27, 1212.373, 816.143 + 0.9, 40000.0, 0.29, 1302.192, 858.063 + 0.9, 40000.0, 0.31, 1392.003, 900.076 + 0.9, 40000.0, 0.33, 1481.806, 942.209 + 0.9, 40000.0, 0.35, 1571.606, 984.313 + 0.9, 40000.0, 0.37, 1661.405, 1026.38 + 0.9, 40000.0, 0.39, 1751.202, 1068.41 + 0.9, 40000.0, 0.41, 1841.0, 1110.3 + 0.9, 40000.0, 0.43, 1930.8, 1152.09 + 0.9, 40000.0, 0.45, 2020.6, 1193.87 + 0.9, 40000.0, 0.47, 2110.4, 1235.67 + 0.9, 40000.0, 0.49, 2200.2, 1277.54 + 0.9, 40000.0, 0.51, 2290.0, 1319.42 + 0.9, 40000.0, 0.53, 2379.8, 1361.38 + 0.9, 40000.0, 0.55, 2469.6, 1403.53 + 0.9, 40000.0, 0.57, 2559.4, 1445.95 + 0.9, 40000.0, 0.59, 2649.2, 1488.69 + 0.9, 40000.0, 0.61, 2738.998, 1531.8 + 0.9, 40000.0, 0.63, 2828.795, 1575.36 + 0.9, 40000.0, 0.65, 2918.594, 1619.44 + 0.9, 40000.0, 0.67, 3008.394, 1664.11 + 0.9, 40000.0, 0.69, 3098.197, 1709.46 + 0.9, 40000.0, 0.71, 3188.009, 1755.76 + 0.9, 40000.0, 0.73, 3277.829, 1803.03 + 0.9, 40000.0, 0.75, 3367.65, 1851.02 + 0.9, 40000.0, 0.77, 3457.471, 1899.69 + 0.9, 40000.0, 0.79, 3547.291, 1949.01 + 0.9, 40000.0, 0.81, 3637.103, 1998.93 + 0.9, 40000.0, 0.83, 3726.906, 2049.4 + 0.9, 40000.0, 0.85, 3816.706, 2100.43 + 0.9, 40000.0, 0.87, 3906.505, 2151.98 + 0.9, 40000.0, 0.89, 3996.302, 2204.01 + 0.9, 40000.0, 0.91, 4086.098, 2256.5 + 0.9, 40000.0, 0.93, 4175.895, 2309.42 + 0.9, 40000.0, 0.95, 4265.694, 2362.74 + 0.9, 40000.0, 0.97, 4355.494, 2416.43 + 0.9, 40000.0, 0.99, 4445.297, 2470.47 + 0.9, 43000.0, 0.0, 207.0191, 207.019 + 0.9, 43000.0, 0.05, 197.9, 301.7 + 0.9, 43000.0, 0.07, 277.0266, 342.594 + 0.9, 43000.0, 0.09, 356.1614, 382.845 + 0.9, 43000.0, 0.11, 435.3031, 422.507 + 0.9, 43000.0, 0.13, 514.4509, 461.636 + 0.9, 43000.0, 0.15, 593.6036, 500.289 + 0.9, 43000.0, 0.17, 672.7601, 538.521 + 0.9, 43000.0, 0.19, 751.9196, 576.387 + 0.9, 43000.0, 0.21, 831.0808, 613.943 + 0.9, 43000.0, 0.23, 910.2427, 651.244 + 0.9, 43000.0, 0.25, 989.4043, 688.347 + 0.9, 43000.0, 0.27, 1068.565, 725.307 + 0.9, 43000.0, 0.29, 1147.722, 762.179 + 0.9, 43000.0, 0.31, 1226.871, 799.154 + 0.9, 43000.0, 0.33, 1306.011, 836.255 + 0.9, 43000.0, 0.35, 1385.15, 873.338 + 0.9, 43000.0, 0.37, 1464.289, 910.392 + 0.9, 43000.0, 0.39, 1543.429, 947.409 + 0.9, 43000.0, 0.41, 1622.579, 984.284 + 0.9, 43000.0, 0.43, 1701.739, 1021.03 + 0.9, 43000.0, 0.45, 1780.9, 1057.78 + 0.9, 43000.0, 0.47, 1860.061, 1094.57 + 0.9, 43000.0, 0.49, 1939.221, 1131.43 + 0.9, 43000.0, 0.51, 2018.371, 1168.39 + 0.9, 43000.0, 0.53, 2097.511, 1205.48 + 0.9, 43000.0, 0.55, 2176.65, 1242.76 + 0.9, 43000.0, 0.57, 2255.789, 1280.28 + 0.9, 43000.0, 0.59, 2334.929, 1318.08 + 0.9, 43000.0, 0.61, 2414.077, 1356.14 + 0.9, 43000.0, 0.63, 2493.234, 1394.51 + 0.9, 43000.0, 0.65, 2572.394, 1433.34 + 0.9, 43000.0, 0.67, 2651.555, 1472.7 + 0.9, 43000.0, 0.69, 2730.718, 1512.67 + 0.9, 43000.0, 0.71, 2809.882, 1553.55 + 0.9, 43000.0, 0.73, 2889.045, 1595.36 + 0.9, 43000.0, 0.75, 2968.206, 1637.83 + 0.9, 43000.0, 0.77, 3047.366, 1680.91 + 0.9, 43000.0, 0.79, 3126.523, 1724.57 + 0.9, 43000.0, 0.81, 3205.673, 1768.67 + 0.9, 43000.0, 0.83, 3284.816, 1813.2 + 0.9, 43000.0, 0.85, 3363.956, 1858.24 + 0.9, 43000.0, 0.87, 3443.095, 1903.8 + 0.9, 43000.0, 0.89, 3522.232, 1949.87 + 0.9, 43000.0, 0.91, 3601.368, 1996.46 + 0.9, 43000.0, 0.93, 3680.505, 2043.56 + 0.9, 43000.0, 0.95, 3759.644, 2091.18 + 0.9, 43000.0, 0.97, 3838.784, 2139.32 + 0.9, 43000.0, 0.99, 3917.927, 2187.98 + 0.9, 48000.0, 0.0, 162.9659, 162.966 + 0.9, 48000.0, 0.05, 155.8, 237.6 + 0.9, 48000.0, 0.07, 218.119, 269.795 + 0.9, 48000.0, 0.09, 280.4441, 301.485 + 0.9, 48000.0, 0.11, 342.7742, 332.714 + 0.9, 48000.0, 0.13, 405.1086, 363.524 + 0.9, 48000.0, 0.15, 467.4464, 393.961 + 0.9, 48000.0, 0.17, 529.7867, 424.066 + 0.9, 48000.0, 0.19, 592.1287, 453.885 + 0.9, 48000.0, 0.21, 654.4714, 483.46 + 0.9, 48000.0, 0.23, 716.814, 512.835 + 0.9, 48000.0, 0.25, 779.1557, 542.053 + 0.9, 48000.0, 0.27, 841.4956, 571.158 + 0.9, 48000.0, 0.29, 903.8327, 600.194 + 0.9, 48000.0, 0.31, 966.1612, 629.309 + 0.9, 48000.0, 0.33, 1028.481, 658.521 + 0.9, 48000.0, 0.35, 1090.8, 687.719 + 0.9, 48000.0, 0.37, 1153.119, 716.894 + 0.9, 48000.0, 0.39, 1215.439, 746.04 + 0.9, 48000.0, 0.41, 1277.769, 775.076 + 0.9, 48000.0, 0.43, 1340.109, 804.011 + 0.9, 48000.0, 0.45, 1402.45, 832.95 + 0.9, 48000.0, 0.47, 1464.791, 861.921 + 0.9, 48000.0, 0.49, 1527.131, 890.952 + 0.9, 48000.0, 0.51, 1589.461, 920.065 + 0.9, 48000.0, 0.53, 1651.781, 949.29 + 0.9, 48000.0, 0.55, 1714.1, 978.669 + 0.9, 48000.0, 0.57, 1776.419, 1008.23 + 0.9, 48000.0, 0.59, 1838.739, 1038.02 + 0.9, 48000.0, 0.61, 1901.067, 1068.0 + 0.9, 48000.0, 0.63, 1963.404, 1098.22 + 0.9, 48000.0, 0.65, 2025.744, 1128.81 + 0.9, 48000.0, 0.67, 2088.085, 1159.8 + 0.9, 48000.0, 0.69, 2150.428, 1191.27 + 0.9, 48000.0, 0.71, 2212.772, 1223.45 + 0.9, 48000.0, 0.73, 2275.115, 1256.36 + 0.9, 48000.0, 0.75, 2337.456, 1289.79 + 0.9, 48000.0, 0.77, 2399.796, 1323.7 + 0.9, 48000.0, 0.79, 2462.133, 1358.06 + 0.9, 48000.0, 0.81, 2524.463, 1392.78 + 0.9, 48000.0, 0.83, 2586.786, 1427.85 + 0.9, 48000.0, 0.85, 2649.106, 1463.33 + 0.9, 48000.0, 0.87, 2711.425, 1499.21 + 0.9, 48000.0, 0.89, 2773.742, 1535.5 + 0.9, 48000.0, 0.91, 2836.058, 1572.2 + 0.9, 48000.0, 0.93, 2898.375, 1609.29 + 0.9, 48000.0, 0.95, 2960.694, 1646.79 + 0.9, 48000.0, 0.97, 3023.014, 1684.7 + 0.9, 48000.0, 0.99, 3085.337, 1723.0 diff --git a/aviary/models/engines/turboshaft_1120hp.csv b/aviary/models/engines/turboshaft_1120hp.csv new file mode 100644 index 0000000000..fd24a3f989 --- /dev/null +++ b/aviary/models/engines/turboshaft_1120hp.csv @@ -0,0 +1,2096 @@ +# created 04/22/25 +# GASP_TS-derived engine deck converted from MAPS_1120hp.eng +# t4max: 50.0 +# t4cruise: 46.67 +# t4climb: 48.33 +# t4flight_idle: 20.0 +# xsfc: 0.0 +# cexp: 0.0 +# sls_horsepower: 1120.0 +# freeturbine_rpm: 24539.0 +# propeller_rpm: 1210.0 +# gearbox_ratio: 0.049308 +# torque_limit: 4861.4 +# sls_corrected_airflow: 7.9568 + +Mach Number (input), Altitude (ft, input), Throttle (input), Shaft Power Corrected (hp, output), Tailpipe Thrust (lbf, output), Fuel Flow (lb/h, output) + 0.0, 0.0, 20.0, 112.0, 37.7, 195.8 + 0.05, 0.0, 20.0, 111.769, 28.0688, 195.181 + 0.1, 0.0, 20.0, 111.1, 18.4, 193.3 + 0.15, 0.0, 20.0, 110.006, 8.75625, 190.219 + 0.2, 0.0, 20.0, 108.5, -0.8, 186.0 + 0.25, 0.0, 20.0, 106.588, -10.2125, 180.7 + 0.3, 0.0, 20.0, 104.3, -19.4, 174.4 + 0.35, 0.0, 20.0, 101.65, -28.2812, 167.138 + 0.4, 0.0, 20.0, 98.7, -36.8, 159.1 + 0.45, 0.0, 20.0, 95.5, -44.8937, 150.438 + 0.5, 0.0, 20.0, 92.1, -52.5, 141.3 + 0.55, 0.0, 20.0, 88.55, -59.5562, 131.838 + 0.6, 0.0, 20.0, 84.9, -66.0, 122.2 + 0.0, 0.0, 22.0, 179.345, 44.715, 230.177 + 0.05, 0.0, 22.0, 178.975, 34.4628, 229.45 + 0.1, 0.0, 22.0, 177.904, 24.1222, 227.282 + 0.15, 0.0, 22.0, 176.152, 13.7785, 223.756 + 0.2, 0.0, 22.0, 173.74, 3.51741, 218.956 + 0.25, 0.0, 22.0, 170.673, -6.57889, 212.952 + 0.3, 0.0, 22.0, 167.015, -16.4153, 205.872 + 0.35, 0.0, 22.0, 162.813, -25.8656, 197.838 + 0.4, 0.0, 22.0, 158.131, -34.941, 188.935 + 0.45, 0.0, 22.0, 153.028, -43.6181, 179.258 + 0.5, 0.0, 22.0, 147.562, -51.8737, 168.903 + 0.55, 0.0, 22.0, 141.795, -59.6846, 157.964 + 0.6, 0.0, 22.0, 135.783, -67.0275, 146.536 + 0.0, 0.0, 24.0, 246.472, 51.4137, 262.388 + 0.05, 0.0, 24.0, 245.964, 40.5599, 261.584 + 0.1, 0.0, 24.0, 244.492, 29.6252, 259.198 + 0.15, 0.0, 24.0, 242.085, 18.6954, 255.317 + 0.2, 0.0, 24.0, 238.77, 7.85667, 250.029 + 0.25, 0.0, 24.0, 234.555, -2.80339, 243.401 + 0.3, 0.0, 24.0, 229.527, -13.2038, 235.581 + 0.35, 0.0, 24.0, 223.747, -23.2362, 226.718 + 0.4, 0.0, 24.0, 217.305, -32.8947, 216.883 + 0.45, 0.0, 24.0, 210.289, -42.1475, 206.165 + 0.5, 0.0, 24.0, 202.781, -50.9631, 194.655 + 0.55, 0.0, 24.0, 194.867, -59.31, 182.442 + 0.6, 0.0, 24.0, 186.632, -67.1563, 169.619 + 0.0, 0.0, 26.0, 313.528, 57.8749, 293.06 + 0.05, 0.0, 26.0, 312.88, 46.4687, 292.204 + 0.1, 0.0, 26.0, 311.008, 35.0071, 289.634 + 0.15, 0.0, 26.0, 307.946, 23.5674, 285.435 + 0.2, 0.0, 26.0, 303.73, 12.2272, 279.694 + 0.25, 0.0, 26.0, 298.37, 1.06967, 272.474 + 0.3, 0.0, 26.0, 291.973, -9.84456, 263.934 + 0.35, 0.0, 26.0, 284.603, -20.4477, 254.219 + 0.4, 0.0, 26.0, 276.395, -30.6778, 243.433 + 0.45, 0.0, 26.0, 267.461, -40.4716, 231.69 + 0.5, 0.0, 26.0, 257.919, -49.7657, 219.105 + 0.55, 0.0, 26.0, 247.883, -58.4968, 205.791 + 0.6, 0.0, 26.0, 237.468, -66.6014, 191.863 + 0.0, 0.0, 28.0, 380.711, 64.1604, 322.897 + 0.05, 0.0, 28.0, 379.919, 52.3018, 322.02 + 0.1, 0.0, 28.0, 377.646, 40.3761, 319.249 + 0.15, 0.0, 28.0, 373.934, 28.4601, 314.689 + 0.2, 0.0, 28.0, 368.82, 16.631, 308.446 + 0.25, 0.0, 28.0, 362.311, 4.96879, 300.601 + 0.3, 0.0, 28.0, 354.543, -6.45888, 291.328 + 0.35, 0.0, 28.0, 345.602, -17.591, 280.784 + 0.4, 0.0, 28.0, 335.641, -28.3279, 269.103 + 0.45, 0.0, 28.0, 324.797, -38.5794, 256.427 + 0.5, 0.0, 28.0, 313.206, -48.2555, 242.896 + 0.55, 0.0, 28.0, 301.005, -57.2661, 228.651 + 0.6, 0.0, 28.0, 288.331, -65.5212, 213.833 + 0.0, 0.0, 30.0, 448.0, 70.4, 352.3 + 0.05, 0.0, 30.0, 447.075, 58.1563, 351.388 + 0.1, 0.0, 30.0, 444.4, 45.8, 348.4 + 0.15, 0.0, 30.0, 440.025, 33.4188, 343.462 + 0.2, 0.0, 30.0, 434.0, 21.1, 336.7 + 0.25, 0.0, 30.0, 426.337, 8.93125, 328.212 + 0.3, 0.0, 30.0, 417.2, -3.0, 318.2 + 0.35, 0.0, 30.0, 406.7, -14.6125, 306.844 + 0.4, 0.0, 30.0, 395.0, -25.8, 294.3 + 0.45, 0.0, 30.0, 382.25, -36.4625, 280.731 + 0.5, 0.0, 30.0, 368.6, -46.5, 266.3 + 0.55, 0.0, 30.0, 354.2, -55.8125, 251.169 + 0.6, 0.0, 30.0, 339.2, -64.3, 235.5 + 0.0, 0.0, 32.0, 515.289, 76.8117, 381.673 + 0.05, 0.0, 32.0, 514.297, 64.1718, 380.608 + 0.1, 0.0, 32.0, 511.209, 51.3642, 377.411 + 0.15, 0.0, 32.0, 506.12, 38.5, 372.174 + 0.2, 0.0, 32.0, 499.125, 25.6902, 364.992 + 0.25, 0.0, 32.0, 490.302, 13.0577, 355.906 + 0.3, 0.0, 32.0, 479.802, 0.67781, 345.165 + 0.35, 0.0, 32.0, 467.74, -11.3576, 332.975 + 0.4, 0.0, 32.0, 454.297, -22.9745, 319.509 + 0.45, 0.0, 32.0, 439.64, -34.0942, 304.949 + 0.5, 0.0, 32.0, 423.932, -44.6381, 289.476 + 0.55, 0.0, 32.0, 407.339, -54.5276, 273.272 + 0.6, 0.0, 32.0, 390.026, -63.6842, 256.517 + 0.0, 0.0, 34.0, 582.446, 83.2393, 410.785 + 0.05, 0.0, 34.0, 581.374, 70.2159, 409.615 + 0.1, 0.0, 34.0, 577.875, 56.9797, 406.207 + 0.15, 0.0, 34.0, 572.085, 43.6586, 400.646 + 0.2, 0.0, 34.0, 564.136, 30.3804, 393.014 + 0.25, 0.0, 34.0, 554.155, 17.2893, 383.325 + 0.3, 0.0, 34.0, 542.294, 4.46426, 371.873 + 0.35, 0.0, 34.0, 528.681, -7.97947, 358.904 + 0.4, 0.0, 34.0, 513.507, -20.006, 344.57 + 0.45, 0.0, 34.0, 496.95, -31.5595, 329.051 + 0.5, 0.0, 34.0, 479.184, -42.5842, 312.521 + 0.55, 0.0, 34.0, 460.387, -53.0245, 295.158 + 0.6, 0.0, 34.0, 440.735, -62.8245, 277.139 + 0.0, 0.0, 36.0, 649.488, 89.6416, 439.68 + 0.05, 0.0, 36.0, 648.278, 76.2396, 438.495 + 0.1, 0.0, 36.0, 644.379, 62.6084, 434.871 + 0.15, 0.0, 36.0, 637.934, 48.8759, 428.925 + 0.2, 0.0, 36.0, 629.082, 35.1697, 420.772 + 0.25, 0.0, 36.0, 617.952, 21.6254, 410.464 + 0.3, 0.0, 36.0, 604.726, 8.34796, 398.314 + 0.35, 0.0, 36.0, 589.56, -4.52037, 384.614 + 0.4, 0.0, 36.0, 572.655, -16.9551, 369.476 + 0.45, 0.0, 36.0, 554.199, -28.9024, 353.058 + 0.5, 0.0, 36.0, 534.381, -40.3084, 335.515 + 0.55, 0.0, 36.0, 513.392, -51.119, 317.006 + 0.6, 0.0, 36.0, 491.419, -61.2806, 297.686 + 0.0, 0.0, 38.0, 716.881, 96.127, 468.889 + 0.05, 0.0, 38.0, 715.466, 82.291, 467.608 + 0.1, 0.0, 38.0, 711.175, 68.2613, 463.745 + 0.15, 0.0, 38.0, 704.123, 54.1524, 457.426 + 0.2, 0.0, 38.0, 694.423, 40.0788, 448.778 + 0.25, 0.0, 38.0, 682.155, 26.1661, 437.869 + 0.3, 0.0, 38.0, 667.54, 12.4956, 424.996 + 0.35, 0.0, 38.0, 650.734, -0.846162, 410.408 + 0.4, 0.0, 38.0, 632.007, -13.7495, 394.307 + 0.45, 0.0, 38.0, 611.603, -26.1106, 376.91 + 0.5, 0.0, 38.0, 589.762, -37.8256, 358.431 + 0.55, 0.0, 38.0, 566.729, -48.7907, 339.084 + 0.6, 0.0, 38.0, 542.744, -58.9019, 319.085 + 0.0, 0.0, 40.0, 784.0, 102.6, 497.7 + 0.05, 0.0, 40.0, 782.5, 88.3938, 496.344 + 0.1, 0.0, 40.0, 777.8, 74.0, 492.3 + 0.15, 0.0, 40.0, 770.05, 59.5313, 485.681 + 0.2, 0.0, 40.0, 759.4, 45.1, 476.6 + 0.25, 0.0, 40.0, 745.975, 30.8375, 465.094 + 0.3, 0.0, 40.0, 730.0, 16.8, 451.5 + 0.35, 0.0, 40.0, 711.65, 3.0375, 436.1 + 0.4, 0.0, 40.0, 691.2, -10.3, 419.1 + 0.45, 0.0, 40.0, 668.9, -23.0875, 400.725 + 0.5, 0.0, 40.0, 645.0, -35.2, 381.2 + 0.55, 0.0, 40.0, 619.75, -46.5125, 360.75 + 0.6, 0.0, 40.0, 593.4, -56.9, 339.6 + 0.0, 0.0, 42.0, 851.127, 109.088, 526.592 + 0.05, 0.0, 42.0, 849.439, 94.6039, 525.133 + 0.1, 0.0, 42.0, 844.346, 79.8705, 520.851 + 0.15, 0.0, 42.0, 835.98, 65.0158, 513.868 + 0.2, 0.0, 42.0, 824.471, 50.168, 504.308 + 0.25, 0.0, 42.0, 809.905, 35.4682, 492.233 + 0.3, 0.0, 42.0, 792.554, 21.0043, 477.955 + 0.35, 0.0, 42.0, 772.614, 6.88126, 461.722 + 0.4, 0.0, 42.0, 750.397, -6.81179, 443.79 + 0.45, 0.0, 42.0, 726.186, -19.9818, 424.413 + 0.5, 0.0, 42.0, 700.263, -32.5357, 403.846 + 0.55, 0.0, 42.0, 672.911, -44.3805, 382.341 + 0.6, 0.0, 42.0, 644.412, -55.4231, 360.154 + 0.0, 0.0, 44.0, 918.489, 115.698, 555.522 + 0.05, 0.0, 44.0, 916.688, 100.858, 553.979 + 0.1, 0.0, 44.0, 911.189, 85.7959, 549.503 + 0.15, 0.0, 44.0, 902.143, 70.6157, 542.197 + 0.2, 0.0, 44.0, 889.705, 55.4221, 532.166 + 0.25, 0.0, 44.0, 873.986, 40.3058, 519.407 + 0.3, 0.0, 44.0, 855.262, 25.4131, 504.345 + 0.35, 0.0, 44.0, 833.723, 10.8968, 487.345 + 0.4, 0.0, 44.0, 809.732, -3.17275, 468.584 + 0.45, 0.0, 44.0, 783.609, -16.7047, 448.286 + 0.5, 0.0, 44.0, 755.674, -29.6081, 426.674 + 0.55, 0.0, 44.0, 726.246, -41.7921, 403.974 + 0.6, 0.0, 44.0, 695.646, -53.1657, 380.408 + 0.0, 0.0, 46.0, 985.511, 122.4, 584.447 + 0.05, 0.0, 46.0, 983.565, 107.263, 582.834 + 0.1, 0.0, 46.0, 977.666, 91.8398, 578.128 + 0.15, 0.0, 46.0, 967.972, 76.2635, 570.457 + 0.2, 0.0, 46.0, 954.64, 60.6687, 559.954 + 0.25, 0.0, 46.0, 937.774, 45.1982, 546.661 + 0.3, 0.0, 46.0, 917.683, 29.961, 530.968 + 0.35, 0.0, 46.0, 894.593, 15.0907, 513.202 + 0.4, 0.0, 46.0, 868.862, 0.657101, 493.591 + 0.45, 0.0, 46.0, 840.816, -13.2538, 472.388 + 0.5, 0.0, 46.0, 810.781, -26.5562, 449.846 + 0.55, 0.0, 46.0, 779.083, -39.1642, 426.217 + 0.6, 0.0, 46.0, 746.048, -50.992, 401.755 + 0.0, 0.0, 48.0, 1052.87, 129.258, 614.241 + 0.05, 0.0, 48.0, 1050.87, 113.782, 612.542 + 0.1, 0.0, 48.0, 1044.56, 98.0541, 607.595 + 0.15, 0.0, 48.0, 1034.14, 82.1772, 599.542 + 0.2, 0.0, 48.0, 1019.83, 66.2551, 588.526 + 0.25, 0.0, 48.0, 1001.79, 50.3581, 574.597 + 0.3, 0.0, 48.0, 980.343, 34.6894, 558.175 + 0.35, 0.0, 48.0, 955.726, 19.4842, 539.631 + 0.4, 0.0, 48.0, 928.289, 4.71653, 519.161 + 0.45, 0.0, 48.0, 898.354, -9.57436, 497.005 + 0.5, 0.0, 48.0, 866.245, -23.3491, 473.402 + 0.55, 0.0, 48.0, 832.283, -36.5684, 448.593 + 0.6, 0.0, 48.0, 796.791, -49.193, 422.816 + 0.0, 0.0, 50.0, 1120.0, 136.3, 644.0 + 0.05, 0.0, 50.0, 1117.81, 120.544, 642.281 + 0.1, 0.0, 50.0, 1111.1, 104.5, 637.2 + 0.15, 0.0, 50.0, 1100.07, 88.2813, 628.869 + 0.2, 0.0, 50.0, 1084.9, 72.0, 617.4 + 0.25, 0.0, 50.0, 1065.73, 55.7438, 602.762 + 0.3, 0.0, 50.0, 1042.9, 39.7, 585.5 + 0.35, 0.0, 50.0, 1016.65, 24.0812, 566.094 + 0.4, 0.0, 50.0, 987.4, 8.9, 544.7 + 0.45, 0.0, 50.0, 955.525, -5.78125, 521.556 + 0.5, 0.0, 50.0, 921.4, -19.9, 496.9 + 0.55, 0.0, 50.0, 885.4, -33.3938, 470.969 + 0.6, 0.0, 50.0, 847.9, -46.2, 444.0 + 0.0, 1500.0, 20.0, 95.7, 35.6, 187.4 + 0.05, 1500.0, 20.0, 95.4674, 26.1135, 186.781 + 0.1, 1500.0, 20.0, 94.9, 16.6, 184.9 + 0.15, 1500.0, 20.0, 93.989, 7.12979, 181.838 + 0.2, 1500.0, 20.0, 92.7253, -2.22695, 177.677 + 0.25, 1500.0, 20.0, 91.1, -11.4, 172.5 + 0.3, 1500.0, 20.0, 89.0799, -20.3089, 166.387 + 0.35, 1500.0, 20.0, 86.8431, -28.962, 159.419 + 0.4, 1500.0, 20.0, 84.4, -37.3, 151.7 + 0.45, 1500.0, 20.0, 81.6979, -45.2387, 143.354 + 0.5, 1500.0, 20.0, 78.7, -52.7, 134.5 + 0.55, 1500.0, 20.0, 75.3693, -59.6061, 125.257 + 0.6, 1500.0, 20.0, 71.6689, -65.8789, 115.744 + 0.0, 1500.0, 22.0, 153.244, 41.5221, 216.562 + 0.05, 1500.0, 22.0, 152.965, 31.4738, 215.965 + 0.1, 1500.0, 22.0, 152.04, 21.4104, 213.922 + 0.15, 1500.0, 22.0, 150.511, 11.3897, 210.539 + 0.2, 1500.0, 22.0, 148.416, 1.46973, 205.924 + 0.25, 1500.0, 22.0, 145.795, -8.29149, 200.182 + 0.3, 1500.0, 22.0, 142.693, -17.8421, 193.43 + 0.35, 1500.0, 22.0, 139.099, -27.0749, 185.693 + 0.4, 1500.0, 22.0, 135.072, -35.9339, 177.096 + 0.45, 1500.0, 22.0, 130.709, -44.3857, 167.813 + 0.5, 1500.0, 22.0, 126.099, -52.3911, 158.003 + 0.55, 1500.0, 22.0, 121.331, -59.911, 147.829 + 0.6, 1500.0, 22.0, 116.491, -66.9061, 137.45 + 0.0, 1500.0, 24.0, 210.602, 47.3391, 244.57 + 0.05, 1500.0, 24.0, 210.212, 36.7927, 243.902 + 0.1, 1500.0, 24.0, 208.946, 26.2052, 241.676 + 0.15, 1500.0, 24.0, 206.853, 15.6433, 237.992 + 0.2, 1500.0, 24.0, 203.98, 5.17398, 232.95 + 0.25, 1500.0, 24.0, 200.377, -5.13584, 226.65 + 0.3, 1500.0, 24.0, 196.095, -15.2246, 219.184 + 0.35, 1500.0, 24.0, 191.153, -24.9799, 210.687 + 0.4, 1500.0, 24.0, 185.63, -34.3432, 201.293 + 0.45, 1500.0, 24.0, 179.642, -43.281, 191.147 + 0.5, 1500.0, 24.0, 173.296, -51.7538, 180.392 + 0.55, 1500.0, 24.0, 166.697, -59.7219, 169.173 + 0.6, 1500.0, 24.0, 159.953, -67.1456, 157.631 + 0.0, 1500.0, 26.0, 267.898, 53.0851, 271.677 + 0.05, 1500.0, 26.0, 267.367, 42.0812, 270.898 + 0.1, 1500.0, 26.0, 265.762, 30.9948, 268.479 + 0.15, 1500.0, 26.0, 263.125, 19.9114, 264.5 + 0.2, 1500.0, 26.0, 259.498, 8.91641, 259.045 + 0.25, 1500.0, 26.0, 254.923, -1.90443, 252.197 + 0.3, 1500.0, 26.0, 249.426, -12.4612, 244.01 + 0.35, 1500.0, 26.0, 243.144, -22.6961, 234.774 + 0.4, 1500.0, 26.0, 236.162, -32.5454, 224.621 + 0.45, 1500.0, 26.0, 228.558, -41.9504, 213.64 + 0.5, 1500.0, 26.0, 220.412, -50.8509, 201.93 + 0.55, 1500.0, 26.0, 211.804, -59.1871, 189.589 + 0.6, 1500.0, 26.0, 202.812, -66.8989, 176.717 + 0.0, 1500.0, 28.0, 325.304, 58.7932, 298.13 + 0.05, 1500.0, 28.0, 324.641, 47.3391, 297.278 + 0.1, 1500.0, 28.0, 322.679, 35.7769, 294.664 + 0.15, 1500.0, 28.0, 319.472, 24.2058, 290.377 + 0.2, 1500.0, 28.0, 315.071, 12.7251, 284.504 + 0.25, 1500.0, 28.0, 309.529, 1.43399, 277.132 + 0.3, 1500.0, 28.0, 302.883, -9.55444, 268.316 + 0.35, 1500.0, 28.0, 295.275, -20.2397, 258.389 + 0.4, 1500.0, 28.0, 286.799, -30.557, 247.472 + 0.45, 1500.0, 28.0, 277.549, -40.4267, 235.613 + 0.5, 1500.0, 28.0, 267.618, -49.7726, 222.879 + 0.55, 1500.0, 28.0, 257.099, -58.5188, 209.336 + 0.6, 1500.0, 28.0, 246.087, -66.5893, 195.05 + 0.0, 1500.0, 30.0, 382.8, 64.5, 324.2 + 0.05, 1500.0, 30.0, 382.023, 52.6109, 323.306 + 0.1, 1500.0, 30.0, 379.7, 40.6, 320.5 + 0.15, 1500.0, 30.0, 375.906, 28.5737, 315.891 + 0.2, 1500.0, 30.0, 370.714, 16.6383, 309.588 + 0.25, 1500.0, 30.0, 364.2, 4.9, 301.7 + 0.3, 1500.0, 30.0, 356.436, -6.51645, 292.313 + 0.35, 1500.0, 30.0, 347.497, -17.6379, 281.708 + 0.4, 1500.0, 30.0, 337.5, -28.4, 270.0 + 0.45, 1500.0, 30.0, 326.588, -38.7148, 257.241 + 0.5, 1500.0, 30.0, 314.9, -48.5, 243.5 + 0.55, 1500.0, 30.0, 302.572, -57.6736, 228.844 + 0.6, 1500.0, 30.0, 289.743, -66.1533, 213.34 + 0.0, 1500.0, 32.0, 440.296, 70.262, 350.244 + 0.05, 1500.0, 32.0, 439.429, 57.9853, 349.31 + 0.1, 1500.0, 32.0, 436.776, 45.5634, 346.31 + 0.15, 1500.0, 32.0, 432.42, 33.106, 341.371 + 0.2, 1500.0, 32.0, 426.444, 20.7228, 334.622 + 0.25, 1500.0, 32.0, 418.933, 8.52333, 326.187 + 0.3, 1500.0, 32.0, 409.962, -3.36956, 316.183 + 0.35, 1500.0, 32.0, 399.654, -14.9386, 304.83 + 0.4, 1500.0, 32.0, 388.146, -26.1111, 292.281 + 0.45, 1500.0, 32.0, 375.601, -36.8039, 278.673 + 0.5, 1500.0, 32.0, 362.176, -46.9362, 264.144 + 0.55, 1500.0, 32.0, 348.026, -56.4273, 248.834 + 0.6, 1500.0, 32.0, 333.308, -65.1968, 232.884 + 0.0, 1500.0, 34.0, 497.685, 76.024, 376.172 + 0.05, 1500.0, 34.0, 496.712, 63.3885, 375.175 + 0.1, 1500.0, 34.0, 493.718, 50.5793, 371.971 + 0.15, 1500.0, 34.0, 488.796, 37.7103, 366.701 + 0.2, 1500.0, 34.0, 482.037, 24.8956, 359.508 + 0.25, 1500.0, 34.0, 473.532, 12.2494, 350.53 + 0.3, 1500.0, 34.0, 463.358, -0.108171, 339.907 + 0.35, 1500.0, 34.0, 451.7, -12.0977, 327.788 + 0.4, 1500.0, 34.0, 438.711, -23.6495, 314.373 + 0.45, 1500.0, 34.0, 424.556, -34.7127, 299.908 + 0.5, 1500.0, 34.0, 409.399, -45.232, 284.626 + 0.55, 1500.0, 34.0, 393.401, -55.1518, 268.761 + 0.6, 1500.0, 34.0, 376.725, -64.4165, 252.546 + 0.0, 1500.0, 36.0, 554.972, 81.7704, 401.98 + 0.05, 1500.0, 36.0, 553.871, 68.7873, 400.888 + 0.1, 1500.0, 36.0, 550.52, 55.6094, 397.475 + 0.15, 1500.0, 36.0, 545.021, 42.3536, 391.889 + 0.2, 1500.0, 36.0, 537.479, 29.1368, 384.273 + 0.25, 1500.0, 36.0, 527.996, 16.0758, 374.772 + 0.3, 1500.0, 36.0, 516.659, 3.2878, 363.533 + 0.35, 1500.0, 36.0, 503.684, -9.0929, 350.661 + 0.4, 1500.0, 36.0, 489.234, -21.0112, 336.392 + 0.45, 1500.0, 36.0, 473.476, -32.4655, 321.045 + 0.5, 1500.0, 36.0, 456.575, -43.4408, 304.919 + 0.55, 1500.0, 36.0, 438.697, -53.9222, 288.31 + 0.6, 1500.0, 36.0, 420.008, -63.8949, 271.519 + 0.0, 1500.0, 38.0, 612.504, 87.5469, 427.669 + 0.05, 1500.0, 38.0, 611.34, 74.1775, 426.483 + 0.1, 1500.0, 38.0, 607.673, 60.6605, 422.908 + 0.15, 1500.0, 38.0, 601.624, 47.0864, 417.069 + 0.2, 1500.0, 38.0, 593.309, 33.5452, 409.09 + 0.25, 1500.0, 38.0, 582.85, 20.1273, 399.095 + 0.3, 1500.0, 38.0, 570.35, 6.91055, 387.19 + 0.35, 1500.0, 38.0, 556.012, -5.91186, 373.633 + 0.4, 1500.0, 38.0, 540.021, -18.2638, 358.631 + 0.45, 1500.0, 38.0, 522.582, -30.1225, 342.4 + 0.5, 1500.0, 38.0, 503.893, -41.4518, 325.156 + 0.55, 1500.0, 38.0, 484.154, -52.2156, 307.11 + 0.6, 1500.0, 38.0, 463.564, -62.3778, 288.478 + 0.0, 1500.0, 40.0, 669.9, 93.3, 453.3 + 0.05, 1500.0, 40.0, 668.543, 79.6556, 452.059 + 0.1, 1500.0, 40.0, 664.5, 65.8, 448.3 + 0.15, 1500.0, 40.0, 657.886, 51.8466, 442.152 + 0.2, 1500.0, 40.0, 648.815, 37.9089, 433.743 + 0.25, 1500.0, 40.0, 637.4, 24.1, 423.2 + 0.3, 1500.0, 40.0, 623.736, 10.5323, 410.616 + 0.35, 1500.0, 40.0, 608.069, -2.665, 396.385 + 0.4, 1500.0, 40.0, 590.6, -15.4, 380.7 + 0.45, 1500.0, 40.0, 571.541, -27.6033, 363.69 + 0.5, 1500.0, 40.0, 551.1, -39.2, 345.5 + 0.55, 1500.0, 40.0, 529.487, -50.115, 326.276 + 0.6, 1500.0, 40.0, 506.91, -60.2733, 306.162 + 0.0, 1500.0, 42.0, 727.216, 99.1736, 479.057 + 0.05, 1500.0, 42.0, 725.815, 85.1583, 477.737 + 0.1, 1500.0, 42.0, 721.441, 70.9513, 473.734 + 0.15, 1500.0, 42.0, 714.241, 56.6536, 467.206 + 0.2, 1500.0, 42.0, 704.358, 42.3663, 458.311 + 0.25, 1500.0, 42.0, 691.938, 28.1907, 447.207 + 0.3, 1500.0, 42.0, 677.115, 14.2141, 434.032 + 0.35, 1500.0, 42.0, 660.083, 0.655568, 419.098 + 0.4, 1500.0, 42.0, 641.08, -12.4096, 402.615 + 0.45, 1500.0, 42.0, 620.397, -24.9745, 384.766 + 0.5, 1500.0, 42.0, 598.31, -37.0152, 365.743 + 0.55, 1500.0, 42.0, 575.098, -48.5079, 345.734 + 0.6, 1500.0, 42.0, 551.036, -59.4285, 324.931 + 0.0, 1500.0, 44.0, 784.802, 105.068, 504.794 + 0.05, 1500.0, 44.0, 783.261, 90.711, 503.448 + 0.1, 1500.0, 44.0, 778.536, 76.1549, 499.281 + 0.15, 1500.0, 44.0, 770.773, 61.5104, 492.455 + 0.2, 1500.0, 44.0, 760.116, 46.8885, 483.133 + 0.25, 1500.0, 44.0, 746.711, 32.4, 471.478 + 0.3, 1500.0, 44.0, 730.682, 18.1654, 457.628 + 0.35, 1500.0, 44.0, 712.314, 4.21555, 441.917 + 0.4, 1500.0, 44.0, 691.847, -9.32866, 424.582 + 0.45, 1500.0, 44.0, 669.533, -22.3054, 405.849 + 0.5, 1500.0, 44.0, 645.622, -34.5631, 385.947 + 0.55, 1500.0, 44.0, 620.362, -45.9502, 365.103 + 0.6, 1500.0, 44.0, 594.003, -56.3151, 343.547 + 0.0, 1500.0, 46.0, 841.998, 110.926, 530.406 + 0.05, 1500.0, 46.0, 840.365, 96.3398, 528.958 + 0.1, 1500.0, 46.0, 835.319, 81.4937, 524.581 + 0.15, 1500.0, 46.0, 827.013, 66.5123, 517.44 + 0.2, 1500.0, 46.0, 815.6, 51.5202, 507.701 + 0.25, 1500.0, 46.0, 801.233, 36.6422, 495.528 + 0.3, 1500.0, 46.0, 784.045, 22.0047, 481.058 + 0.35, 1500.0, 46.0, 764.331, 7.72846, 464.657 + 0.4, 1500.0, 46.0, 742.353, -6.09075, 446.557 + 0.45, 1500.0, 46.0, 718.39, -19.3771, 426.952 + 0.5, 1500.0, 46.0, 692.717, -32.0498, 406.047 + 0.55, 1500.0, 46.0, 665.608, -44.028, 384.046 + 0.6, 1500.0, 46.0, 637.338, -55.231, 361.152 + 0.0, 1500.0, 48.0, 899.584, 116.903, 556.148 + 0.05, 1500.0, 48.0, 897.873, 101.973, 554.658 + 0.1, 1500.0, 48.0, 892.466, 86.8194, 550.088 + 0.15, 1500.0, 48.0, 883.553, 71.5461, 542.618 + 0.2, 1500.0, 48.0, 871.319, 56.2586, 532.429 + 0.25, 1500.0, 48.0, 855.954, 41.0617, 519.701 + 0.3, 1500.0, 48.0, 837.637, 26.0507, 504.591 + 0.35, 1500.0, 48.0, 816.599, 11.4089, 487.461 + 0.4, 1500.0, 48.0, 793.115, -2.76425, 468.559 + 0.45, 1500.0, 48.0, 767.502, -16.4062, 448.111 + 0.5, 1500.0, 48.0, 740.068, -29.445, 426.348 + 0.55, 1500.0, 48.0, 711.12, -41.8089, 403.501 + 0.6, 1500.0, 48.0, 680.965, -53.4259, 379.802 + 0.0, 1500.0, 50.0, 956.9, 122.9, 581.8 + 0.05, 1500.0, 50.0, 955.029, 107.742, 580.243 + 0.1, 1500.0, 50.0, 949.3, 92.3, 575.5 + 0.15, 1500.0, 50.0, 939.877, 76.6968, 567.746 + 0.2, 1500.0, 50.0, 926.923, 61.0557, 557.155 + 0.25, 1500.0, 50.0, 910.6, 45.5, 543.9 + 0.3, 1500.0, 50.0, 891.036, 30.146, 528.117 + 0.35, 1500.0, 50.0, 868.64, 15.184, 510.273 + 0.4, 1500.0, 50.0, 843.7, 0.7, 490.6 + 0.45, 1500.0, 50.0, 816.493, -13.276, 469.252 + 0.5, 1500.0, 50.0, 787.3, -26.7, 446.4 + 0.55, 1500.0, 50.0, 756.401, -39.5279, 422.218 + 0.6, 1500.0, 50.0, 724.077, -51.7156, 396.878 + 0.0, 3000.0, 20.0, 101.8, 36.2, 192.7 + 0.05, 3000.0, 20.0, 101.538, 26.6682, 192.092 + 0.1, 3000.0, 20.0, 100.9, 17.1, 190.2 + 0.15, 3000.0, 20.0, 99.8935, 7.56768, 187.102 + 0.2, 3000.0, 20.0, 98.5247, -1.85643, 182.876 + 0.25, 3000.0, 20.0, 96.8, -11.1, 177.6 + 0.3, 3000.0, 20.0, 94.718, -20.081, 171.351 + 0.35, 3000.0, 20.0, 92.342, -28.8014, 164.206 + 0.4, 3000.0, 20.0, 89.7, -37.2, 156.3 + 0.45, 3000.0, 20.0, 86.812, -45.1924, 147.809 + 0.5, 3000.0, 20.0, 83.7, -52.7, 138.9 + 0.55, 3000.0, 20.0, 80.3861, -59.6443, 129.738 + 0.6, 3000.0, 20.0, 76.8922, -65.9467, 120.49 + 0.0, 3000.0, 22.0, 162.929, 42.5836, 223.314 + 0.05, 3000.0, 22.0, 162.645, 32.4126, 222.592 + 0.1, 3000.0, 22.0, 161.654, 22.211, 220.49 + 0.15, 3000.0, 22.0, 160.009, 12.0513, 217.078 + 0.2, 3000.0, 22.0, 157.767, 2.00618, 212.422 + 0.25, 3000.0, 22.0, 154.982, -7.85169, 206.591 + 0.3, 3000.0, 22.0, 151.728, -17.4423, 199.637 + 0.35, 3000.0, 22.0, 147.926, -26.7464, 191.723 + 0.4, 3000.0, 22.0, 143.636, -35.7081, 182.962 + 0.45, 3000.0, 22.0, 138.97, -44.2614, 173.467 + 0.5, 3000.0, 22.0, 134.028, -52.3429, 163.348 + 0.55, 3000.0, 22.0, 128.91, -59.8893, 152.718 + 0.6, 3000.0, 22.0, 123.715, -66.8372, 141.688 + 0.0, 3000.0, 24.0, 223.924, 48.7459, 252.576 + 0.05, 3000.0, 24.0, 223.503, 38.0462, 251.789 + 0.1, 3000.0, 24.0, 222.147, 27.3055, 249.494 + 0.15, 3000.0, 24.0, 219.913, 16.5958, 245.758 + 0.2, 3000.0, 24.0, 216.858, 5.98932, 240.649 + 0.25, 3000.0, 24.0, 213.041, -4.44196, 234.234 + 0.3, 3000.0, 24.0, 208.53, -14.6235, 226.557 + 0.35, 3000.0, 24.0, 203.289, -24.5006, 217.851 + 0.4, 3000.0, 24.0, 197.398, -34.0063, 208.242 + 0.45, 3000.0, 24.0, 190.993, -43.0698, 197.832 + 0.5, 3000.0, 24.0, 184.194, -51.6217, 186.729 + 0.55, 3000.0, 24.0, 177.123, -59.5922, 175.04 + 0.6, 3000.0, 24.0, 169.901, -66.9118, 162.872 + 0.0, 3000.0, 26.0, 284.876, 54.7864, 280.87 + 0.05, 3000.0, 26.0, 284.277, 43.619, 280.038 + 0.1, 3000.0, 26.0, 282.553, 32.3945, 277.552 + 0.15, 3000.0, 26.0, 279.748, 21.1843, 273.487 + 0.2, 3000.0, 26.0, 275.902, 10.0602, 267.915 + 0.25, 3000.0, 26.0, 271.059, -0.906369, 260.912 + 0.3, 3000.0, 26.0, 265.253, -11.6467, 252.522 + 0.35, 3000.0, 26.0, 258.568, -22.069, 243.029 + 0.4, 3000.0, 26.0, 251.102, -32.0904, 232.58 + 0.45, 3000.0, 26.0, 242.976, -41.628, 221.291 + 0.5, 3000.0, 26.0, 234.306, -50.5991, 209.285 + 0.55, 3000.0, 26.0, 225.206, -58.9207, 196.686 + 0.6, 3000.0, 26.0, 215.791, -66.5099, 183.617 + 0.0, 3000.0, 28.0, 345.9, 60.832, 308.624 + 0.05, 3000.0, 28.0, 345.197, 49.1844, 307.719 + 0.1, 3000.0, 28.0, 343.119, 37.4765, 305.025 + 0.15, 3000.0, 28.0, 339.718, 25.7791, 300.626 + 0.2, 3000.0, 28.0, 335.044, 14.1634, 294.605 + 0.25, 3000.0, 28.0, 329.15, 2.70004, 287.046 + 0.3, 3000.0, 28.0, 322.073, -8.54637, 278.004 + 0.35, 3000.0, 28.0, 313.955, -19.4582, 267.777 + 0.4, 3000.0, 28.0, 304.909, -29.9492, 256.507 + 0.45, 3000.0, 28.0, 295.054, -39.9411, 244.293 + 0.5, 3000.0, 28.0, 284.508, -49.3536, 231.247 + 0.55, 3000.0, 28.0, 273.389, -58.1065, 217.477 + 0.6, 3000.0, 28.0, 261.816, -66.1194, 203.096 + 0.0, 3000.0, 30.0, 407.0, 66.9, 336.1 + 0.05, 3000.0, 30.0, 406.231, 54.7831, 335.111 + 0.1, 3000.0, 30.0, 403.8, 42.6, 332.2 + 0.15, 3000.0, 30.0, 399.783, 30.4253, 327.464 + 0.2, 3000.0, 30.0, 394.258, 18.3338, 320.999 + 0.25, 3000.0, 30.0, 387.3, 6.4, 312.9 + 0.3, 3000.0, 30.0, 378.976, -5.30729, 303.239 + 0.35, 3000.0, 30.0, 369.434, -16.668, 292.295 + 0.4, 3000.0, 30.0, 358.8, -27.6, 280.2 + 0.45, 3000.0, 30.0, 347.211, -38.0347, 267.037 + 0.5, 3000.0, 30.0, 334.8, -47.9, 252.9 + 0.55, 3000.0, 30.0, 321.702, -57.1239, 237.886 + 0.6, 3000.0, 30.0, 308.05, -65.6344, 222.089 + 0.0, 3000.0, 32.0, 468.161, 72.9553, 363.58 + 0.05, 3000.0, 32.0, 467.238, 60.4663, 362.551 + 0.1, 3000.0, 32.0, 464.425, 47.8574, 359.441 + 0.15, 3000.0, 32.0, 459.804, 35.2233, 354.363 + 0.2, 3000.0, 32.0, 453.454, 22.6584, 347.431 + 0.25, 3000.0, 32.0, 445.457, 10.2573, 338.758 + 0.3, 3000.0, 32.0, 435.877, -1.88225, 328.442 + 0.35, 3000.0, 32.0, 424.905, -13.6893, 316.711 + 0.4, 3000.0, 32.0, 412.691, -25.0764, 303.732 + 0.45, 3000.0, 32.0, 399.387, -35.9514, 289.665 + 0.5, 3000.0, 32.0, 385.147, -46.2231, 274.674 + 0.55, 3000.0, 32.0, 370.123, -55.8007, 258.92 + 0.6, 3000.0, 32.0, 354.467, -64.5932, 242.565 + 0.0, 3000.0, 34.0, 529.181, 79.0714, 390.953 + 0.05, 3000.0, 34.0, 528.109, 66.2159, 389.854 + 0.1, 3000.0, 34.0, 524.917, 53.1954, 386.542 + 0.15, 3000.0, 34.0, 519.692, 40.1205, 381.133 + 0.2, 3000.0, 34.0, 512.523, 27.102, 373.745 + 0.25, 3000.0, 34.0, 503.5, 14.2506, 364.496 + 0.3, 3000.0, 34.0, 492.695, 1.68676, 353.485 + 0.35, 3000.0, 34.0, 480.293, -10.5493, 340.947 + 0.4, 3000.0, 34.0, 466.472, -22.3693, 327.089 + 0.45, 3000.0, 34.0, 451.437, -33.6722, 312.134 + 0.5, 3000.0, 34.0, 435.384, -44.3602, 296.302 + 0.55, 3000.0, 34.0, 418.512, -54.3355, 279.812 + 0.6, 3000.0, 34.0, 401.017, -63.5003, 262.882 + 0.0, 3000.0, 36.0, 590.053, 85.2485, 418.198 + 0.05, 3000.0, 36.0, 588.871, 72.0079, 416.995 + 0.1, 3000.0, 36.0, 585.312, 58.5865, 413.477 + 0.15, 3000.0, 36.0, 579.482, 45.0987, 407.754 + 0.2, 3000.0, 36.0, 571.49, 31.6587, 399.931 + 0.25, 3000.0, 36.0, 561.444, 18.3808, 390.117 + 0.3, 3000.0, 36.0, 549.444, 5.38798, 378.389 + 0.35, 3000.0, 36.0, 535.615, -7.26429, 365.063 + 0.4, 3000.0, 36.0, 520.163, -19.4916, 350.362 + 0.45, 3000.0, 36.0, 503.367, -31.2074, 334.51 + 0.5, 3000.0, 36.0, 485.487, -42.3257, 317.729 + 0.55, 3000.0, 36.0, 466.783, -52.7606, 300.242 + 0.6, 3000.0, 36.0, 447.515, -62.4261, 282.273 + 0.0, 3000.0, 38.0, 651.293, 91.2985, 445.325 + 0.05, 3000.0, 38.0, 650.003, 77.7535, 444.142 + 0.1, 3000.0, 38.0, 646.072, 64.0065, 440.459 + 0.15, 3000.0, 38.0, 639.625, 50.1704, 434.413 + 0.2, 3000.0, 38.0, 630.789, 36.3582, 426.14 + 0.25, 3000.0, 38.0, 619.69, 22.6828, 415.778 + 0.3, 3000.0, 38.0, 606.447, 9.26359, 403.44 + 0.35, 3000.0, 38.0, 591.211, -3.83605, 389.423 + 0.4, 3000.0, 38.0, 574.19, -16.509, 373.922 + 0.45, 3000.0, 38.0, 555.637, -28.6321, 357.109 + 0.5, 3000.0, 38.0, 535.796, -40.0859, 339.162 + 0.55, 3000.0, 38.0, 514.909, -50.7514, 320.257 + 0.6, 3000.0, 38.0, 493.221, -60.5094, 300.572 + 0.0, 3000.0, 40.0, 712.3, 97.5, 472.5 + 0.05, 3000.0, 40.0, 710.902, 83.5265, 471.139 + 0.1, 3000.0, 40.0, 706.6, 69.4, 467.2 + 0.15, 3000.0, 40.0, 699.536, 55.2103, 460.811 + 0.2, 3000.0, 40.0, 689.855, 41.0471, 452.102 + 0.25, 3000.0, 40.0, 677.7, 27.0, 441.2 + 0.3, 3000.0, 40.0, 663.21, 13.145, 428.209 + 0.35, 3000.0, 40.0, 646.531, -0.315952, 413.435 + 0.4, 3000.0, 40.0, 627.9, -13.3, 397.1 + 0.45, 3000.0, 40.0, 607.626, -25.776, 379.416 + 0.5, 3000.0, 40.0, 586.0, -37.7, 360.6 + 0.55, 3000.0, 40.0, 563.313, -49.0279, 340.866 + 0.6, 3000.0, 40.0, 539.857, -59.7156, 320.431 + 0.0, 3000.0, 42.0, 773.209, 103.733, 499.609 + 0.05, 3000.0, 42.0, 771.753, 89.4977, 498.285 + 0.1, 3000.0, 42.0, 767.116, 75.0156, 494.156 + 0.15, 3000.0, 42.0, 759.46, 60.4125, 487.39 + 0.2, 3000.0, 42.0, 748.946, 45.8139, 478.157 + 0.25, 3000.0, 42.0, 735.735, 31.3456, 466.628 + 0.3, 3000.0, 42.0, 719.982, 17.1345, 452.954 + 0.35, 3000.0, 42.0, 701.892, 3.31019, 437.416 + 0.4, 3000.0, 42.0, 681.703, -10.0484, 420.253 + 0.45, 3000.0, 42.0, 659.692, -22.8987, 401.713 + 0.5, 3000.0, 42.0, 636.124, -35.189, 382.042 + 0.55, 3000.0, 42.0, 611.265, -46.8679, 361.484 + 0.6, 3000.0, 42.0, 585.382, -57.8835, 340.285 + 0.0, 3000.0, 44.0, 834.441, 109.983, 526.877 + 0.05, 3000.0, 44.0, 832.778, 95.3864, 525.434 + 0.1, 3000.0, 44.0, 827.774, 80.5754, 521.096 + 0.15, 3000.0, 44.0, 819.561, 65.6563, 514.016 + 0.2, 3000.0, 44.0, 808.273, 50.7357, 504.351 + 0.25, 3000.0, 44.0, 794.043, 35.9204, 492.254 + 0.3, 3000.0, 44.0, 776.973, 21.3092, 477.844 + 0.35, 3000.0, 44.0, 757.411, 7.07646, 461.528 + 0.4, 3000.0, 44.0, 735.625, -6.68676, 443.551 + 0.45, 3000.0, 44.0, 711.892, -19.9291, 424.12 + 0.5, 3000.0, 44.0, 686.487, -32.5893, 403.448 + 0.55, 3000.0, 44.0, 659.687, -44.6061, 381.753 + 0.6, 3000.0, 44.0, 631.766, -55.9182, 359.249 + 0.0, 3000.0, 46.0, 895.366, 116.266, 553.978 + 0.05, 3000.0, 46.0, 893.603, 101.391, 552.445 + 0.1, 3000.0, 46.0, 888.226, 86.2668, 547.898 + 0.15, 3000.0, 46.0, 879.391, 71.0063, 540.495 + 0.2, 3000.0, 46.0, 867.251, 55.7225, 530.392 + 0.25, 3000.0, 46.0, 851.963, 40.5282, 517.746 + 0.3, 3000.0, 46.0, 833.647, 25.5268, 502.681 + 0.35, 3000.0, 46.0, 812.698, 10.914, 485.575 + 0.4, 3000.0, 46.0, 789.375, -3.21595, 466.704 + 0.45, 3000.0, 46.0, 763.917, -16.8167, 446.34 + 0.5, 3000.0, 46.0, 736.568, -29.8301, 424.758 + 0.55, 3000.0, 46.0, 707.571, -42.1979, 402.231 + 0.6, 3000.0, 46.0, 677.171, -53.8618, 379.033 + 0.0, 3000.0, 48.0, 956.504, 122.647, 581.294 + 0.05, 3000.0, 48.0, 954.619, 107.499, 579.692 + 0.1, 3000.0, 48.0, 948.884, 92.0462, 574.926 + 0.15, 3000.0, 48.0, 939.459, 76.4239, 567.168 + 0.2, 3000.0, 48.0, 926.506, 60.7683, 556.59 + 0.25, 3000.0, 48.0, 910.183, 45.2156, 543.363 + 0.3, 3000.0, 48.0, 890.613, 29.9096, 527.629 + 0.35, 3000.0, 48.0, 868.22, 14.9352, 509.762 + 0.4, 3000.0, 48.0, 843.297, 0.394429, 490.036 + 0.45, 3000.0, 48.0, 816.122, -13.615, 468.715 + 0.5, 3000.0, 48.0, 786.979, -26.9942, 446.067 + 0.55, 3000.0, 48.0, 756.151, -39.6445, 422.36 + 0.6, 3000.0, 48.0, 723.92, -51.4669, 397.862 + 0.0, 3000.0, 50.0, 1017.5, 129.0, 608.4 + 0.05, 3000.0, 50.0, 1015.51, 113.544, 606.821 + 0.1, 3000.0, 50.0, 1009.4, 97.8, 601.9 + 0.15, 3000.0, 50.0, 999.349, 81.8937, 593.828 + 0.2, 3000.0, 50.0, 985.552, 65.9517, 582.798 + 0.25, 3000.0, 50.0, 968.2, 50.1, 569.0 + 0.3, 3000.0, 50.0, 947.464, 34.4734, 552.595 + 0.35, 3000.0, 50.0, 923.66, 19.1306, 534.005 + 0.4, 3000.0, 50.0, 897.1, 4.2, 513.5 + 0.45, 3000.0, 50.0, 868.133, -10.1604, 491.317 + 0.5, 3000.0, 50.0, 837.1, -23.8, 467.7 + 0.55, 3000.0, 50.0, 804.341, -36.5682, 442.894 + 0.6, 3000.0, 50.0, 770.198, -48.3144, 417.143 + 0.0, 5000.0, 20.0, 110.4, 37.1, 200.5 + 0.05, 5000.0, 20.0, 110.238, 27.4563, 199.844 + 0.1, 5000.0, 20.0, 109.6, 17.8, 197.9 + 0.15, 5000.0, 20.0, 108.513, 8.19375, 194.731 + 0.2, 5000.0, 20.0, 107.0, -1.3, 190.4 + 0.25, 5000.0, 20.0, 105.075, -10.6125, 184.944 + 0.3, 5000.0, 20.0, 102.8, -19.7, 178.5 + 0.35, 5000.0, 20.0, 100.244, -28.5188, 171.181 + 0.4, 5000.0, 20.0, 97.4, -37.0, 163.1 + 0.45, 5000.0, 20.0, 94.2813, -45.0813, 154.369 + 0.5, 5000.0, 20.0, 90.9, -52.7, 145.1 + 0.55, 5000.0, 20.0, 87.2687, -59.7938, 135.406 + 0.6, 5000.0, 20.0, 83.4, -66.3, 125.4 + 0.0, 5000.0, 22.0, 176.866, 43.9646, 232.745 + 0.05, 5000.0, 22.0, 176.5, 33.7396, 232.065 + 0.1, 5000.0, 22.0, 175.419, 23.4382, 229.922 + 0.15, 5000.0, 22.0, 173.66, 13.1466, 226.401 + 0.2, 5000.0, 22.0, 171.261, 2.95097, 221.586 + 0.25, 5000.0, 22.0, 168.266, -7.05052, 215.555 + 0.3, 5000.0, 22.0, 164.691, -16.8076, 208.415 + 0.35, 5000.0, 22.0, 160.53, -26.2585, 200.246 + 0.4, 5000.0, 22.0, 155.888, -35.3396, 191.205 + 0.45, 5000.0, 22.0, 150.844, -43.9876, 181.428 + 0.5, 5000.0, 22.0, 145.474, -52.1394, 171.054 + 0.55, 5000.0, 22.0, 139.857, -59.7318, 160.219 + 0.6, 5000.0, 22.0, 134.069, -66.7015, 149.061 + 0.0, 5000.0, 24.0, 243.053, 50.6064, 263.783 + 0.05, 5000.0, 24.0, 242.57, 39.8113, 263.04 + 0.1, 5000.0, 24.0, 241.089, 28.9291, 260.688 + 0.15, 5000.0, 24.0, 238.669, 18.0453, 256.814 + 0.2, 5000.0, 24.0, 235.364, 7.24539, 251.504 + 0.25, 5000.0, 24.0, 231.246, -3.38291, 244.826 + 0.3, 5000.0, 24.0, 226.331, -13.76, 236.922 + 0.35, 5000.0, 24.0, 220.614, -23.7945, 227.9 + 0.4, 5000.0, 24.0, 214.238, -33.434, 217.929 + 0.45, 5000.0, 24.0, 207.31, -42.6166, 207.165 + 0.5, 5000.0, 24.0, 199.937, -51.28, 195.764 + 0.55, 5000.0, 24.0, 192.225, -59.3622, 183.879 + 0.6, 5000.0, 24.0, 184.281, -66.801, 171.666 + 0.0, 5000.0, 26.0, 309.147, 57.1258, 293.939 + 0.05, 5000.0, 26.0, 308.571, 45.787, 293.108 + 0.1, 5000.0, 26.0, 306.711, 34.3709, 290.542 + 0.15, 5000.0, 26.0, 303.639, 22.9544, 286.32 + 0.2, 5000.0, 26.0, 299.428, 11.6143, 280.518 + 0.25, 5000.0, 26.0, 294.155, 0.417467, 273.174 + 0.3, 5000.0, 26.0, 287.877, -10.5286, 264.492 + 0.35, 5000.0, 26.0, 280.63, -21.1087, 254.633 + 0.4, 5000.0, 26.0, 272.554, -31.2787, 243.761 + 0.45, 5000.0, 26.0, 263.76, -40.9767, 232.038 + 0.5, 5000.0, 26.0, 254.363, -50.1408, 219.626 + 0.55, 5000.0, 26.0, 244.474, -58.7092, 206.689 + 0.6, 5000.0, 26.0, 234.208, -66.6198, 193.389 + 0.0, 5000.0, 28.0, 375.412, 63.6458, 323.539 + 0.05, 5000.0, 28.0, 374.67, 51.8092, 322.615 + 0.1, 5000.0, 28.0, 372.414, 39.8831, 319.839 + 0.15, 5000.0, 28.0, 368.707, 27.95, 315.286 + 0.2, 5000.0, 28.0, 363.615, 16.0925, 309.025 + 0.25, 5000.0, 28.0, 357.183, 4.38892, 301.072 + 0.3, 5000.0, 28.0, 349.533, -7.06534, 291.674 + 0.35, 5000.0, 28.0, 340.764, -18.1673, 281.037 + 0.4, 5000.0, 28.0, 330.988, -28.8616, 269.294 + 0.45, 5000.0, 28.0, 320.314, -39.0806, 256.598 + 0.5, 5000.0, 28.0, 308.849, -48.757, 243.098 + 0.55, 5000.0, 28.0, 296.702, -57.8235, 228.948 + 0.6, 5000.0, 28.0, 283.981, -66.2126, 214.298 + 0.0, 5000.0, 30.0, 441.8, 70.2, 352.9 + 0.05, 5000.0, 30.0, 440.862, 57.9125, 351.887 + 0.1, 5000.0, 30.0, 438.2, 45.5, 348.9 + 0.15, 5000.0, 30.0, 433.862, 33.0625, 344.012 + 0.2, 5000.0, 30.0, 427.9, 20.7, 337.3 + 0.25, 5000.0, 30.0, 420.319, 8.525, 328.775 + 0.3, 5000.0, 30.0, 411.3, -3.4, 318.7 + 0.35, 5000.0, 30.0, 400.994, -15.0, 307.306 + 0.4, 5000.0, 30.0, 389.5, -26.2, 294.7 + 0.45, 5000.0, 30.0, 376.931, -36.925, 281.019 + 0.5, 5000.0, 30.0, 363.4, -47.1, 266.4 + 0.55, 5000.0, 30.0, 349.019, -56.65, 250.981 + 0.6, 5000.0, 30.0, 333.9, -65.5, 234.9 + 0.0, 5000.0, 32.0, 508.133, 76.7967, 382.467 + 0.05, 5000.0, 32.0, 507.091, 64.1077, 381.392 + 0.1, 5000.0, 32.0, 504.041, 51.2444, 378.166 + 0.15, 5000.0, 32.0, 499.052, 38.3243, 372.891 + 0.2, 5000.0, 32.0, 492.191, 25.4648, 365.664 + 0.25, 5000.0, 32.0, 483.489, 12.8018, 356.535 + 0.3, 5000.0, 32.0, 473.122, 0.397206, 345.754 + 0.35, 5000.0, 32.0, 461.219, -11.6662, 333.541 + 0.4, 5000.0, 32.0, 447.956, -23.3152, 320.029 + 0.45, 5000.0, 32.0, 433.499, -34.4739, 305.376 + 0.5, 5000.0, 32.0, 418.013, -45.0667, 289.735 + 0.55, 5000.0, 32.0, 401.662, -55.0179, 273.264 + 0.6, 5000.0, 32.0, 384.611, -64.2518, 256.118 + 0.0, 5000.0, 34.0, 574.315, 83.4152, 411.939 + 0.05, 5000.0, 34.0, 573.213, 70.3278, 410.784 + 0.1, 5000.0, 34.0, 569.776, 57.0347, 407.333 + 0.15, 5000.0, 34.0, 564.111, 43.6618, 401.693 + 0.2, 5000.0, 34.0, 556.323, 30.3354, 393.97 + 0.25, 5000.0, 34.0, 546.505, 17.1989, 384.218 + 0.3, 5000.0, 34.0, 534.807, 4.32537, 372.697 + 0.35, 5000.0, 34.0, 521.331, -8.18473, 359.624 + 0.4, 5000.0, 34.0, 506.316, -20.2701, 345.18 + 0.45, 5000.0, 34.0, 489.968, -31.8595, 329.553 + 0.5, 5000.0, 34.0, 472.491, -42.882, 312.934 + 0.55, 5000.0, 34.0, 454.091, -53.2664, 295.512 + 0.6, 5000.0, 34.0, 434.973, -62.9416, 277.477 + 0.0, 5000.0, 36.0, 640.395, 90.0589, 441.217 + 0.05, 5000.0, 36.0, 639.223, 76.549, 439.961 + 0.1, 5000.0, 36.0, 635.386, 62.8403, 436.31 + 0.15, 5000.0, 36.0, 629.032, 49.0516, 430.351 + 0.2, 5000.0, 36.0, 620.308, 35.3017, 422.174 + 0.25, 5000.0, 36.0, 609.364, 21.7194, 411.794 + 0.3, 5000.0, 36.0, 596.34, 8.39317, 399.515 + 0.35, 5000.0, 36.0, 581.344, -4.56402, 385.575 + 0.4, 5000.0, 36.0, 564.621, -17.0976, 370.19 + 0.45, 5000.0, 36.0, 546.381, -29.1383, 353.583 + 0.5, 5000.0, 36.0, 526.836, -40.6171, 335.976 + 0.55, 5000.0, 36.0, 506.196, -51.4647, 317.593 + 0.6, 5000.0, 36.0, 484.672, -61.612, 298.655 + 0.0, 5000.0, 38.0, 706.924, 96.7873, 470.388 + 0.05, 5000.0, 38.0, 705.497, 82.8257, 469.09 + 0.1, 5000.0, 38.0, 701.235, 68.7208, 465.232 + 0.15, 5000.0, 38.0, 694.255, 54.5633, 458.923 + 0.2, 5000.0, 38.0, 684.676, 40.4438, 450.272 + 0.25, 5000.0, 38.0, 672.586, 26.4488, 439.324 + 0.3, 5000.0, 38.0, 658.194, 12.682, 426.379 + 0.35, 5000.0, 38.0, 641.661, -0.761423, 411.688 + 0.4, 5000.0, 38.0, 623.23, -13.7694, 395.44 + 0.45, 5000.0, 38.0, 603.125, -26.2339, 377.838 + 0.5, 5000.0, 38.0, 581.57, -38.0471, 359.088 + 0.55, 5000.0, 38.0, 558.786, -49.101, 339.394 + 0.6, 5000.0, 38.0, 534.997, -59.2877, 318.96 + 0.0, 5000.0, 40.0, 773.1, 103.5, 499.6 + 0.05, 5000.0, 40.0, 771.55, 89.1875, 498.188 + 0.1, 5000.0, 40.0, 766.9, 74.7, 494.1 + 0.15, 5000.0, 40.0, 759.275, 60.1375, 487.437 + 0.2, 5000.0, 40.0, 748.8, 45.6, 478.3 + 0.25, 5000.0, 40.0, 735.556, 31.1812, 466.7 + 0.3, 5000.0, 40.0, 719.8, 17.0, 453.0 + 0.35, 5000.0, 40.0, 701.737, 3.18125, 437.513 + 0.4, 5000.0, 40.0, 681.6, -10.2, 420.4 + 0.45, 5000.0, 40.0, 659.612, -23.0563, 401.863 + 0.5, 5000.0, 40.0, 636.0, -35.3, 382.1 + 0.55, 5000.0, 40.0, 610.987, -46.8438, 361.313 + 0.6, 5000.0, 40.0, 584.8, -57.6, 339.7 + 0.0, 5000.0, 42.0, 839.268, 110.228, 528.932 + 0.05, 5000.0, 42.0, 837.622, 95.6462, 527.449 + 0.1, 5000.0, 42.0, 832.589, 80.8134, 523.109 + 0.15, 5000.0, 42.0, 824.311, 65.8531, 516.037 + 0.2, 5000.0, 42.0, 812.93, 50.8894, 506.365 + 0.25, 5000.0, 42.0, 798.55, 36.0505, 494.143 + 0.3, 5000.0, 42.0, 781.431, 21.4472, 479.728 + 0.35, 5000.0, 42.0, 761.773, 7.20753, 463.431 + 0.4, 5000.0, 42.0, 739.872, -6.59192, 445.435 + 0.45, 5000.0, 42.0, 716.003, -19.8618, 425.953 + 0.5, 5000.0, 42.0, 690.439, -32.5127, 405.201 + 0.55, 5000.0, 42.0, 663.454, -44.4553, 383.394 + 0.6, 5000.0, 42.0, 635.321, -55.6001, 360.745 + 0.0, 5000.0, 44.0, 905.668, 117.083, 558.231 + 0.05, 5000.0, 44.0, 903.934, 102.126, 556.744 + 0.1, 5000.0, 44.0, 898.512, 86.9369, 552.224 + 0.15, 5000.0, 44.0, 889.572, 71.6252, 544.811 + 0.2, 5000.0, 44.0, 877.285, 56.3015, 534.643 + 0.25, 5000.0, 44.0, 861.795, 41.0717, 521.777 + 0.3, 5000.0, 44.0, 843.348, 26.0597, 506.595 + 0.35, 5000.0, 44.0, 822.114, 11.3906, 489.43 + 0.4, 5000.0, 44.0, 798.457, -2.83259, 470.487 + 0.45, 5000.0, 44.0, 772.693, -16.5014, 449.999 + 0.5, 5000.0, 44.0, 745.138, -29.5072, 428.204 + 0.55, 5000.0, 44.0, 716.108, -41.7416, 405.336 + 0.6, 5000.0, 44.0, 685.918, -53.0961, 381.632 + 0.0, 5000.0, 46.0, 971.726, 123.965, 587.488 + 0.05, 5000.0, 46.0, 969.837, 108.705, 585.869 + 0.1, 5000.0, 46.0, 964.032, 93.1604, 581.102 + 0.15, 5000.0, 46.0, 954.471, 77.4603, 573.325 + 0.2, 5000.0, 46.0, 941.315, 61.7342, 562.676 + 0.25, 5000.0, 46.0, 924.674, 46.1132, 549.211 + 0.3, 5000.0, 46.0, 904.859, 30.7209, 533.318 + 0.35, 5000.0, 46.0, 882.102, 15.7041, 515.331 + 0.4, 5000.0, 46.0, 856.743, 1.12342, 495.475 + 0.45, 5000.0, 46.0, 829.092, -12.9393, 473.999 + 0.5, 5000.0, 46.0, 799.462, -26.4019, 451.157 + 0.55, 5000.0, 46.0, 768.163, -39.1825, 427.199 + 0.6, 5000.0, 46.0, 735.508, -51.199, 402.377 + 0.0, 5000.0, 48.0, 1038.21, 130.938, 617.068 + 0.05, 5000.0, 48.0, 1036.13, 115.387, 615.365 + 0.1, 5000.0, 48.0, 1029.91, 99.5422, 610.405 + 0.15, 5000.0, 48.0, 1019.71, 83.521, 602.317 + 0.2, 5000.0, 48.0, 1005.67, 67.4399, 591.226 + 0.25, 5000.0, 48.0, 987.876, 51.3928, 577.157 + 0.3, 5000.0, 48.0, 966.687, 35.5648, 560.544 + 0.35, 5000.0, 48.0, 942.394, 20.1654, 541.764 + 0.4, 5000.0, 48.0, 915.328, 5.21495, 521.023 + 0.45, 5000.0, 48.0, 885.81, -9.21905, 498.572 + 0.5, 5000.0, 48.0, 854.161, -23.069, 474.66 + 0.55, 5000.0, 48.0, 820.7, -36.2673, 449.539 + 0.6, 5000.0, 48.0, 785.748, -48.7463, 423.458 + 0.0, 5000.0, 50.0, 1104.4, 138.1, 647.0 + 0.05, 5000.0, 50.0, 1102.24, 122.206, 645.256 + 0.1, 5000.0, 50.0, 1095.6, 106.0, 640.1 + 0.15, 5000.0, 50.0, 1084.69, 89.6187, 631.669 + 0.2, 5000.0, 50.0, 1069.7, 73.2, 620.1 + 0.25, 5000.0, 50.0, 1050.8, 56.9063, 605.425 + 0.3, 5000.0, 50.0, 1028.3, 40.8, 588.1 + 0.35, 5000.0, 50.0, 1002.42, 24.9375, 568.525 + 0.4, 5000.0, 50.0, 973.6, 9.5, 546.9 + 0.45, 5000.0, 50.0, 942.2, -5.3625, 523.475 + 0.5, 5000.0, 50.0, 908.6, -19.5, 498.5 + 0.55, 5000.0, 50.0, 873.175, -32.7625, 472.225 + 0.6, 5000.0, 50.0, 836.3, -45.0, 444.9 + 0.0, 10000.0, 20.0, 135.6, 39.5, 224.4 + 0.05, 10000.0, 20.0, 135.331, 29.725, 223.669 + 0.1, 10000.0, 20.0, 134.5, 19.9, 221.6 + 0.15, 10000.0, 20.0, 133.144, 10.1, 218.231 + 0.2, 10000.0, 20.0, 131.3, 0.4, 213.6 + 0.25, 10000.0, 20.0, 129.025, -9.11875, 207.694 + 0.3, 10000.0, 20.0, 126.3, -18.4, 200.7 + 0.35, 10000.0, 20.0, 123.081, -27.375, 192.775 + 0.4, 10000.0, 20.0, 119.5, -36.0, 184.0 + 0.45, 10000.0, 20.0, 115.681, -44.2187, 174.462 + 0.5, 10000.0, 20.0, 111.6, -52.0, 164.3 + 0.55, 10000.0, 20.0, 107.269, -59.3062, 153.638 + 0.6, 10000.0, 20.0, 102.7, -66.1, 142.6 + 0.0, 10000.0, 22.0, 217.135, 47.7301, 261.128 + 0.05, 10000.0, 22.0, 216.652, 37.1845, 260.343 + 0.1, 10000.0, 22.0, 215.351, 26.6282, 258.045 + 0.15, 10000.0, 22.0, 213.241, 16.1128, 254.282 + 0.2, 10000.0, 22.0, 210.333, 5.68995, 249.101 + 0.25, 10000.0, 22.0, 206.603, -4.60659, 242.5 + 0.3, 10000.0, 22.0, 202.16, -14.6721, 234.671 + 0.35, 10000.0, 22.0, 197.089, -24.4056, 225.769 + 0.4, 10000.0, 22.0, 191.438, -33.7621, 215.91 + 0.45, 10000.0, 22.0, 185.243, -42.6689, 205.198 + 0.5, 10000.0, 22.0, 178.621, -51.1088, 193.825 + 0.55, 10000.0, 22.0, 171.667, -59.0508, 181.958 + 0.6, 10000.0, 22.0, 164.476, -66.4639, 169.766 + 0.0, 10000.0, 24.0, 298.408, 55.7831, 296.735 + 0.05, 10000.0, 24.0, 297.796, 44.6001, 295.867 + 0.1, 10000.0, 24.0, 296.005, 33.356, 293.319 + 0.15, 10000.0, 24.0, 293.076, 22.1239, 289.14 + 0.2, 10000.0, 24.0, 289.047, 10.9768, 283.383 + 0.25, 10000.0, 24.0, 283.931, -0.0179954, 276.036 + 0.3, 10000.0, 24.0, 277.84, -10.7703, 267.336 + 0.35, 10000.0, 24.0, 270.858, -21.1855, 257.472 + 0.4, 10000.0, 24.0, 263.079, -31.2094, 246.569 + 0.45, 10000.0, 24.0, 254.581, -40.767, 234.753 + 0.5, 10000.0, 24.0, 245.491, -49.8268, 222.215 + 0.55, 10000.0, 24.0, 235.922, -58.3461, 209.129 + 0.6, 10000.0, 24.0, 225.988, -66.2824, 195.67 + 0.0, 10000.0, 26.0, 379.592, 63.7411, 331.727 + 0.05, 10000.0, 26.0, 378.879, 52.0041, 330.765 + 0.1, 10000.0, 26.0, 376.595, 40.1198, 327.95 + 0.15, 10000.0, 26.0, 372.824, 28.2005, 323.341 + 0.2, 10000.0, 26.0, 367.653, 16.3587, 316.995 + 0.25, 10000.0, 26.0, 361.175, 4.7289, 308.896 + 0.3, 10000.0, 26.0, 353.46, -6.64245, 299.325 + 0.35, 10000.0, 26.0, 344.548, -17.6882, 288.514 + 0.4, 10000.0, 26.0, 334.621, -28.3356, 276.584 + 0.45, 10000.0, 26.0, 323.844, -38.507, 263.672 + 0.5, 10000.0, 26.0, 312.309, -48.1504, 249.962 + 0.55, 10000.0, 26.0, 300.128, -57.2072, 235.628 + 0.6, 10000.0, 26.0, 287.412, -65.619, 220.84 + 0.0, 10000.0, 28.0, 460.933, 71.6983, 366.742 + 0.05, 10000.0, 28.0, 460.067, 59.4315, 365.694 + 0.1, 10000.0, 28.0, 457.3, 46.9614, 362.603 + 0.15, 10000.0, 28.0, 452.73, 34.4253, 357.552 + 0.2, 10000.0, 28.0, 446.455, 21.9606, 350.624 + 0.25, 10000.0, 28.0, 438.568, 9.74785, 341.843 + 0.3, 10000.0, 28.0, 429.181, -2.20501, 331.47 + 0.35, 10000.0, 28.0, 418.379, -13.8676, 319.731 + 0.4, 10000.0, 28.0, 406.345, -25.1266, 306.752 + 0.45, 10000.0, 28.0, 393.24, -35.8727, 292.655 + 0.5, 10000.0, 28.0, 379.212, -46.0635, 277.679 + 0.55, 10000.0, 28.0, 364.413, -55.6397, 262.035 + 0.6, 10000.0, 28.0, 348.992, -64.5422, 245.934 + 0.0, 10000.0, 30.0, 542.4, 79.7, 401.9 + 0.05, 10000.0, 30.0, 541.344, 66.9063, 400.769 + 0.1, 10000.0, 30.0, 538.1, 53.9, 397.4 + 0.15, 10000.0, 30.0, 532.756, 40.8187, 391.906 + 0.2, 10000.0, 30.0, 525.4, 27.8, 384.4 + 0.25, 10000.0, 30.0, 516.081, 15.025, 374.956 + 0.3, 10000.0, 30.0, 505.0, 2.5, 363.8 + 0.35, 10000.0, 30.0, 492.325, -9.75625, 351.137 + 0.4, 10000.0, 30.0, 478.2, -21.6, 337.1 + 0.45, 10000.0, 30.0, 462.744, -32.8875, 321.781 + 0.5, 10000.0, 30.0, 446.2, -43.6, 305.5 + 0.55, 10000.0, 30.0, 428.781, -53.6875, 288.519 + 0.6, 10000.0, 30.0, 410.7, -63.1, 271.1 + 0.0, 10000.0, 32.0, 623.867, 87.7931, 437.162 + 0.05, 10000.0, 32.0, 622.65, 74.4468, 435.93 + 0.1, 10000.0, 32.0, 618.906, 60.9471, 432.295 + 0.15, 10000.0, 32.0, 612.748, 47.3909, 426.369 + 0.2, 10000.0, 32.0, 604.283, 33.8754, 418.267 + 0.25, 10000.0, 32.0, 593.595, 20.4938, 408.042 + 0.3, 10000.0, 32.0, 580.874, 7.35394, 395.988 + 0.35, 10000.0, 32.0, 566.268, -5.43394, 382.381 + 0.4, 10000.0, 32.0, 549.994, -17.7842, 367.325 + 0.45, 10000.0, 32.0, 532.241, -29.5819, 350.913 + 0.5, 10000.0, 32.0, 513.243, -40.8048, 333.445 + 0.55, 10000.0, 32.0, 493.222, -51.4077, 315.167 + 0.6, 10000.0, 32.0, 472.401, -61.3452, 296.328 + 0.0, 10000.0, 34.0, 705.176, 95.9111, 472.338 + 0.05, 10000.0, 34.0, 703.788, 82.0961, 471.027 + 0.1, 10000.0, 34.0, 699.551, 68.1283, 467.139 + 0.15, 10000.0, 34.0, 692.59, 54.0932, 460.795 + 0.2, 10000.0, 34.0, 683.03, 40.0763, 452.114 + 0.25, 10000.0, 34.0, 670.976, 26.1378, 441.151 + 0.3, 10000.0, 34.0, 656.617, 12.4389, 428.226 + 0.35, 10000.0, 34.0, 640.084, -0.851417, 413.639 + 0.4, 10000.0, 34.0, 621.665, -13.6967, 397.507 + 0.45, 10000.0, 34.0, 601.623, -26.0267, 379.947 + 0.5, 10000.0, 34.0, 580.177, -37.7739, 361.261 + 0.55, 10000.0, 34.0, 557.555, -48.8699, 341.706 + 0.6, 10000.0, 34.0, 533.988, -59.2464, 321.538 + 0.0, 10000.0, 36.0, 786.345, 104.049, 507.408 + 0.05, 10000.0, 36.0, 784.774, 89.8625, 506.041 + 0.1, 10000.0, 36.0, 780.058, 75.4388, 501.914 + 0.15, 10000.0, 36.0, 772.321, 60.8978, 495.166 + 0.2, 10000.0, 36.0, 761.687, 46.3595, 485.934 + 0.25, 10000.0, 36.0, 748.241, 31.9452, 474.308 + 0.3, 10000.0, 36.0, 732.222, 17.7721, 460.568 + 0.35, 10000.0, 36.0, 713.791, 3.98303, 444.964 + 0.4, 10000.0, 36.0, 693.259, -9.37847, 427.683 + 0.45, 10000.0, 36.0, 670.906, -22.2655, 408.877 + 0.5, 10000.0, 36.0, 646.984, -34.5455, 388.905 + 0.55, 10000.0, 36.0, 621.751, -46.1073, 368.074 + 0.6, 10000.0, 36.0, 595.465, -56.8398, 346.689 + 0.0, 10000.0, 38.0, 867.938, 112.328, 542.761 + 0.05, 10000.0, 38.0, 866.225, 97.6558, 541.286 + 0.1, 10000.0, 38.0, 861.036, 82.7777, 536.921 + 0.15, 10000.0, 38.0, 852.504, 67.7979, 529.783 + 0.2, 10000.0, 38.0, 840.76, 52.8199, 519.986 + 0.25, 10000.0, 38.0, 825.883, 37.9445, 507.558 + 0.3, 10000.0, 38.0, 808.172, 23.2843, 492.876 + 0.35, 10000.0, 38.0, 787.865, 8.94807, 476.27 + 0.4, 10000.0, 38.0, 765.232, -4.95282, 457.912 + 0.45, 10000.0, 38.0, 740.502, -18.2865, 437.982 + 0.5, 10000.0, 38.0, 714.036, -31.0059, 416.792 + 0.55, 10000.0, 38.0, 686.163, -43.043, 394.624 + 0.6, 10000.0, 38.0, 657.209, -54.3296, 371.757 + 0.0, 10000.0, 40.0, 949.2, 120.6, 578.0 + 0.05, 10000.0, 40.0, 947.394, 105.581, 576.444 + 0.1, 10000.0, 40.0, 941.7, 90.3, 571.8 + 0.15, 10000.0, 40.0, 932.306, 74.8687, 564.206 + 0.2, 10000.0, 40.0, 919.4, 59.4, 553.8 + 0.25, 10000.0, 40.0, 903.144, 43.9813, 540.637 + 0.3, 10000.0, 40.0, 883.8, 28.8, 525.1 + 0.35, 10000.0, 40.0, 861.569, 14.0813, 507.525 + 0.4, 10000.0, 40.0, 836.8, -0.2, 488.1 + 0.45, 10000.0, 40.0, 809.794, -14.0437, 467.012 + 0.5, 10000.0, 40.0, 780.9, -27.3, 444.6 + 0.55, 10000.0, 40.0, 750.456, -39.8562, 421.162 + 0.6, 10000.0, 40.0, 718.8, -51.6, 397.0 + 0.0, 10000.0, 42.0, 1030.47, 129.033, 613.671 + 0.05, 10000.0, 42.0, 1028.45, 113.607, 611.964 + 0.1, 10000.0, 42.0, 1022.27, 97.9123, 607.025 + 0.15, 10000.0, 42.0, 1012.11, 82.0588, 598.985 + 0.2, 10000.0, 42.0, 998.155, 66.155, 587.979 + 0.25, 10000.0, 42.0, 980.533, 50.2839, 574.034 + 0.3, 10000.0, 42.0, 959.543, 34.6326, 557.598 + 0.35, 10000.0, 42.0, 935.393, 19.4033, 539.078 + 0.4, 10000.0, 42.0, 908.482, 4.63389, 518.631 + 0.45, 10000.0, 42.0, 879.162, -9.58334, 496.443 + 0.5, 10000.0, 42.0, 847.787, -23.2093, 472.845 + 0.55, 10000.0, 42.0, 814.712, -36.1915, 448.135 + 0.6, 10000.0, 42.0, 780.29, -48.4777, 422.608 + 0.0, 10000.0, 44.0, 1112.03, 137.86, 650.078 + 0.05, 10000.0, 44.0, 1109.84, 122.095, 648.304 + 0.1, 10000.0, 44.0, 1103.19, 105.979, 643.17 + 0.15, 10000.0, 44.0, 1092.25, 89.6624, 634.785 + 0.2, 10000.0, 44.0, 1077.19, 73.2918, 623.261 + 0.25, 10000.0, 44.0, 1058.13, 57.0381, 608.58 + 0.3, 10000.0, 44.0, 1035.43, 40.9835, 591.232 + 0.35, 10000.0, 44.0, 1009.41, 25.2234, 571.626 + 0.4, 10000.0, 44.0, 980.42, 9.88859, 549.992 + 0.45, 10000.0, 44.0, 948.783, -4.87644, 526.59 + 0.5, 10000.0, 44.0, 914.914, -19.0168, 501.732 + 0.55, 10000.0, 44.0, 879.203, -32.4553, 475.719 + 0.6, 10000.0, 44.0, 842.041, -45.1147, 448.849 + 0.0, 10000.0, 46.0, 1193.17, 146.776, 686.642 + 0.05, 10000.0, 46.0, 1190.82, 130.623, 684.729 + 0.1, 10000.0, 46.0, 1183.67, 114.118, 679.301 + 0.15, 10000.0, 46.0, 1171.91, 97.3976, 670.477 + 0.2, 10000.0, 46.0, 1155.76, 80.599, 658.375 + 0.25, 10000.0, 46.0, 1135.34, 63.8602, 642.988 + 0.3, 10000.0, 46.0, 1111.02, 47.3138, 624.81 + 0.35, 10000.0, 46.0, 1083.07, 31.1142, 604.272 + 0.4, 10000.0, 46.0, 1051.92, 15.3342, 581.548 + 0.45, 10000.0, 46.0, 1017.97, 0.0535011, 556.787 + 0.5, 10000.0, 46.0, 981.631, -14.595, 530.497 + 0.55, 10000.0, 46.0, 943.334, -28.492, 503.095 + 0.6, 10000.0, 46.0, 903.498, -41.5177, 475.0 + 0.0, 10000.0, 48.0, 1274.73, 155.887, 723.744 + 0.05, 10000.0, 48.0, 1272.27, 139.337, 721.739 + 0.1, 10000.0, 48.0, 1264.63, 122.424, 716.001 + 0.15, 10000.0, 48.0, 1252.04, 105.285, 706.674 + 0.2, 10000.0, 48.0, 1234.74, 88.0586, 693.903 + 0.25, 10000.0, 48.0, 1212.93, 70.8821, 677.702 + 0.3, 10000.0, 48.0, 1186.97, 53.8945, 658.607 + 0.35, 10000.0, 48.0, 1157.1, 37.2596, 637.128 + 0.4, 10000.0, 48.0, 1123.81, 21.0399, 613.357 + 0.45, 10000.0, 48.0, 1087.53, 5.31172, 587.369 + 0.5, 10000.0, 48.0, 1048.71, -9.80269, 559.738 + 0.55, 10000.0, 48.0, 1007.81, -24.1925, 530.913 + 0.6, 10000.0, 48.0, 965.288, -37.7469, 501.344 + 0.0, 10000.0, 50.0, 1356.0, 165.0, 761.0 + 0.05, 10000.0, 50.0, 1353.32, 148.075, 758.938 + 0.1, 10000.0, 50.0, 1345.2, 130.8, 752.9 + 0.15, 10000.0, 50.0, 1331.86, 113.3, 743.062 + 0.2, 10000.0, 50.0, 1313.5, 95.7, 729.6 + 0.25, 10000.0, 50.0, 1290.26, 78.125, 712.563 + 0.3, 10000.0, 50.0, 1262.6, 60.7, 692.5 + 0.35, 10000.0, 50.0, 1230.86, 43.5437, 669.925 + 0.4, 10000.0, 50.0, 1195.5, 26.8, 645.0 + 0.45, 10000.0, 50.0, 1156.91, 10.6375, 617.919 + 0.5, 10000.0, 50.0, 1115.6, -4.9, 589.1 + 0.55, 10000.0, 50.0, 1072.07, -19.7375, 558.906 + 0.6, 10000.0, 50.0, 1026.8, -33.8, 527.7 + 0.0, 15000.0, 20.0, 180.0, 43.4, 262.4 + 0.05, 15000.0, 20.0, 166.675, 32.55, 257.275 + 0.1, 15000.0, 20.0, 158.0, 22.0, 252.4 + 0.15, 15000.0, 20.0, 153.0, 11.75, 247.525 + 0.2, 15000.0, 20.0, 150.7, 1.8, 242.4 + 0.25, 15000.0, 20.0, 150.125, -7.85, 236.775 + 0.3, 15000.0, 20.0, 150.3, -17.2, 230.4 + 0.35, 15000.0, 20.0, 150.25, -26.25, 223.025 + 0.4, 15000.0, 20.0, 149.0, -35.0, 214.4 + 0.45, 15000.0, 20.0, 144.612, -43.5, 203.925 + 0.5, 15000.0, 20.0, 139.0, -51.6, 192.4 + 0.55, 15000.0, 20.0, 133.112, -59.2, 180.275 + 0.6, 15000.0, 20.0, 127.9, -66.2, 168.0 + 0.0, 15000.0, 22.0, 284.656, 51.0064, 305.376 + 0.05, 15000.0, 22.0, 264.767, 39.947, 297.085 + 0.1, 15000.0, 22.0, 251.895, 29.0398, 290.141 + 0.15, 15000.0, 22.0, 244.549, 18.3055, 284.06 + 0.2, 15000.0, 22.0, 241.237, 7.76459, 278.356 + 0.25, 15000.0, 22.0, 240.469, -2.56214, 272.542 + 0.3, 15000.0, 22.0, 240.752, -12.6541, 266.133 + 0.35, 15000.0, 22.0, 240.596, -22.4907, 258.643 + 0.4, 15000.0, 22.0, 238.51, -32.0511, 249.586 + 0.45, 15000.0, 22.0, 231.511, -41.3696, 237.85 + 0.5, 15000.0, 22.0, 222.58, -50.2614, 224.829 + 0.55, 15000.0, 22.0, 213.207, -58.5966, 211.292 + 0.6, 15000.0, 22.0, 204.883, -66.2451, 198.007 + 0.0, 15000.0, 24.0, 391.447, 60.2227, 348.477 + 0.05, 15000.0, 24.0, 364.009, 48.277, 337.036 + 0.1, 15000.0, 24.0, 346.247, 36.5657, 328.018 + 0.15, 15000.0, 24.0, 336.107, 25.0921, 320.709 + 0.2, 15000.0, 24.0, 331.533, 13.8601, 314.396 + 0.25, 15000.0, 24.0, 330.469, 2.87305, 308.364 + 0.3, 15000.0, 24.0, 330.862, -7.86538, 301.9 + 0.35, 15000.0, 24.0, 330.656, -18.3516, 294.291 + 0.4, 15000.0, 24.0, 327.795, -28.582, 284.823 + 0.45, 15000.0, 24.0, 318.171, -38.6317, 271.928 + 0.5, 15000.0, 24.0, 305.89, -48.2613, 257.454 + 0.55, 15000.0, 24.0, 293.005, -57.31, 242.397 + 0.6, 15000.0, 24.0, 281.568, -65.6172, 227.751 + 0.0, 15000.0, 26.0, 499.311, 70.3357, 392.1 + 0.05, 15000.0, 26.0, 463.855, 57.1566, 377.423 + 0.1, 15000.0, 26.0, 440.872, 44.4216, 366.264 + 0.15, 15000.0, 26.0, 427.72, 32.0955, 357.681 + 0.2, 15000.0, 26.0, 421.759, 20.1433, 350.727 + 0.25, 15000.0, 26.0, 420.348, 8.52993, 344.459 + 0.3, 15000.0, 26.0, 420.846, -2.7796, 337.931 + 0.35, 15000.0, 26.0, 420.612, -13.8203, 330.198 + 0.4, 15000.0, 26.0, 417.005, -24.6274, 320.316 + 0.45, 15000.0, 26.0, 404.753, -35.3521, 306.272 + 0.5, 15000.0, 26.0, 389.11, -45.6804, 290.325 + 0.55, 15000.0, 26.0, 372.698, -55.4145, 273.668 + 0.6, 15000.0, 26.0, 358.14, -64.3567, 257.492 + 0.0, 15000.0, 28.0, 606.826, 80.4284, 437.065 + 0.05, 15000.0, 28.0, 563.588, 66.0998, 418.812 + 0.1, 15000.0, 28.0, 535.541, 52.4191, 405.297 + 0.15, 15000.0, 28.0, 519.471, 39.312, 395.318 + 0.2, 15000.0, 28.0, 512.166, 26.7042, 387.674 + 0.25, 15000.0, 28.0, 510.414, 14.5215, 381.162 + 0.3, 15000.0, 28.0, 511.001, 2.68963, 374.58 + 0.35, 15000.0, 28.0, 510.715, -8.86563, 366.726 + 0.4, 15000.0, 28.0, 506.343, -20.2186, 356.398 + 0.45, 15000.0, 28.0, 491.478, -31.6062, 341.064 + 0.5, 15000.0, 28.0, 472.49, -42.6144, 323.512 + 0.55, 15000.0, 28.0, 452.556, -52.9916, 305.2 + 0.6, 15000.0, 28.0, 434.853, -62.4864, 287.587 + 0.0, 15000.0, 30.0, 714.0, 90.4, 482.5 + 0.05, 15000.0, 30.0, 663.175, 75.0312, 460.669 + 0.1, 15000.0, 30.0, 630.2, 60.5, 444.8 + 0.15, 15000.0, 30.0, 611.3, 46.6937, 433.431 + 0.2, 15000.0, 30.0, 602.7, 33.5, 425.1 + 0.25, 15000.0, 30.0, 600.625, 20.8062, 418.344 + 0.3, 15000.0, 30.0, 601.3, 8.5, 411.7 + 0.35, 15000.0, 30.0, 600.95, -3.53125, 403.706 + 0.4, 15000.0, 30.0, 595.8, -15.4, 392.9 + 0.45, 15000.0, 30.0, 578.325, -27.4312, 376.213 + 0.5, 15000.0, 30.0, 556.0, -39.1, 357.0 + 0.55, 15000.0, 30.0, 532.55, -50.0937, 337.013 + 0.6, 15000.0, 30.0, 511.7, -60.1, 318.0 + 0.0, 15000.0, 32.0, 821.673, 100.482, 526.019 + 0.05, 15000.0, 32.0, 762.994, 84.0181, 501.528 + 0.1, 15000.0, 32.0, 724.923, 68.6214, 483.908 + 0.15, 15000.0, 32.0, 703.103, 54.1334, 471.497 + 0.2, 15000.0, 32.0, 693.178, 40.3959, 462.631 + 0.25, 15000.0, 32.0, 690.794, 27.2502, 455.647 + 0.3, 15000.0, 32.0, 691.593, 14.538, 448.882 + 0.35, 15000.0, 32.0, 691.22, 2.10072, 440.674 + 0.4, 15000.0, 32.0, 685.319, -10.22, 429.36 + 0.45, 15000.0, 32.0, 665.204, -22.8424, 411.48 + 0.5, 15000.0, 32.0, 639.51, -35.1455, 390.76 + 0.55, 15000.0, 32.0, 612.541, -46.7677, 369.128 + 0.6, 15000.0, 32.0, 588.602, -57.3478, 348.513 + 0.0, 15000.0, 34.0, 928.245, 110.277, 570.779 + 0.05, 15000.0, 34.0, 862.117, 92.9528, 543.211 + 0.1, 15000.0, 34.0, 819.228, 76.8483, 523.541 + 0.15, 15000.0, 34.0, 794.662, 61.7743, 509.886 + 0.2, 15000.0, 34.0, 783.503, 47.5413, 500.362 + 0.25, 15000.0, 34.0, 780.837, 33.9597, 493.088 + 0.3, 15000.0, 34.0, 781.748, 20.84, 486.18 + 0.35, 15000.0, 34.0, 781.321, 7.99275, 477.755 + 0.4, 15000.0, 34.0, 774.641, -4.77161, 465.93 + 0.45, 15000.0, 34.0, 751.9, -17.9295, 446.811 + 0.5, 15000.0, 34.0, 722.858, -30.8097, 424.548 + 0.55, 15000.0, 34.0, 692.379, -43.0279, 401.279 + 0.6, 15000.0, 34.0, 665.332, -54.1998, 379.14 + 0.0, 15000.0, 36.0, 1033.73, 120.189, 617.979 + 0.05, 15000.0, 36.0, 960.583, 102.084, 586.365 + 0.1, 15000.0, 36.0, 913.164, 85.3237, 563.991 + 0.15, 15000.0, 36.0, 886.025, 69.6917, 548.697 + 0.2, 15000.0, 36.0, 873.715, 54.9741, 538.323 + 0.25, 15000.0, 36.0, 870.785, 40.9565, 530.71 + 0.3, 15000.0, 36.0, 871.783, 27.4244, 523.696 + 0.35, 15000.0, 36.0, 871.261, 14.1635, 515.123 + 0.4, 15000.0, 36.0, 863.766, 0.959268, 502.831 + 0.45, 15000.0, 36.0, 838.424, -12.7099, 482.362 + 0.5, 15000.0, 36.0, 806.062, -26.1369, 458.447 + 0.55, 15000.0, 36.0, 772.082, -38.9219, 433.517 + 0.6, 15000.0, 36.0, 741.887, -50.665, 410.004 + 0.0, 15000.0, 38.0, 1142.05, 133.07, 666.067 + 0.05, 15000.0, 38.0, 1060.85, 112.838, 629.925 + 0.1, 15000.0, 38.0, 1008.2, 94.5568, 604.615 + 0.15, 15000.0, 38.0, 978.039, 77.8964, 587.647 + 0.2, 15000.0, 38.0, 964.344, 62.5254, 576.535 + 0.25, 15000.0, 38.0, 961.072, 48.1127, 568.788 + 0.3, 15000.0, 38.0, 962.184, 34.3271, 561.919 + 0.35, 15000.0, 38.0, 961.642, 20.8375, 553.439 + 0.4, 15000.0, 38.0, 953.407, 7.31281, 540.86 + 0.45, 15000.0, 38.0, 925.43, -7.0141, 519.072 + 0.5, 15000.0, 38.0, 889.7, -21.1663, 493.451 + 0.55, 15000.0, 38.0, 852.196, -34.6029, 466.749 + 0.6, 15000.0, 38.0, 818.897, -46.7829, 441.722 + 0.0, 15000.0, 40.0, 1249.5, 143.9, 710.4 + 0.05, 15000.0, 40.0, 1160.52, 122.662, 671.775 + 0.1, 15000.0, 40.0, 1102.8, 103.6, 644.9 + 0.15, 15000.0, 40.0, 1069.73, 86.3375, 627.075 + 0.2, 15000.0, 40.0, 1054.7, 70.5, 615.6 + 0.25, 15000.0, 40.0, 1051.09, 55.7125, 607.775 + 0.3, 15000.0, 40.0, 1052.3, 41.6, 600.9 + 0.35, 15000.0, 40.0, 1051.71, 27.7875, 592.275 + 0.4, 15000.0, 40.0, 1042.7, 13.9, 579.2 + 0.45, 15000.0, 40.0, 1012.09, -0.90625, 556.15 + 0.5, 15000.0, 40.0, 973.0, -15.6, 528.9 + 0.55, 15000.0, 40.0, 931.956, -29.6188, 500.4 + 0.6, 15000.0, 40.0, 895.5, -42.4, 473.6 + 0.0, 15000.0, 42.0, 1356.11, 154.577, 760.079 + 0.05, 15000.0, 42.0, 1259.67, 132.422, 717.09 + 0.1, 15000.0, 42.0, 1197.11, 112.672, 687.295 + 0.15, 15000.0, 42.0, 1161.26, 94.8978, 667.698 + 0.2, 15000.0, 42.0, 1144.96, 78.6751, 655.304 + 0.25, 15000.0, 42.0, 1141.04, 63.5775, 647.116 + 0.3, 15000.0, 42.0, 1142.34, 49.1789, 640.137 + 0.35, 15000.0, 42.0, 1141.68, 35.0534, 631.371 + 0.4, 15000.0, 42.0, 1131.9, 20.7748, 617.822 + 0.45, 15000.0, 42.0, 1098.71, 5.37633, 593.364 + 0.5, 15000.0, 42.0, 1056.31, -9.94531, 564.39 + 0.55, 15000.0, 42.0, 1011.79, -24.5342, 534.163 + 0.6, 15000.0, 42.0, 972.22, -37.7345, 505.947 + 0.0, 15000.0, 44.0, 1462.37, 167.3, 808.001 + 0.05, 15000.0, 44.0, 1358.69, 143.504, 761.495 + 0.1, 15000.0, 44.0, 1291.47, 122.559, 729.4 + 0.15, 15000.0, 44.0, 1252.99, 103.954, 708.456 + 0.2, 15000.0, 44.0, 1235.53, 87.1729, 695.401 + 0.25, 15000.0, 44.0, 1231.38, 71.7037, 686.976 + 0.3, 15000.0, 44.0, 1232.8, 57.0328, 679.92 + 0.35, 15000.0, 44.0, 1232.09, 42.6467, 670.972 + 0.4, 15000.0, 44.0, 1221.52, 28.032, 656.873 + 0.45, 15000.0, 44.0, 1185.68, 12.048, 630.95 + 0.5, 15000.0, 44.0, 1139.91, -3.93677, 600.178 + 0.55, 15000.0, 44.0, 1091.85, -19.1812, 568.117 + 0.6, 15000.0, 44.0, 1049.16, -32.944, 538.331 + 0.0, 15000.0, 46.0, 1570.28, 179.834, 855.818 + 0.05, 15000.0, 46.0, 1458.55, 154.577, 805.807 + 0.1, 15000.0, 46.0, 1386.08, 132.553, 771.417 + 0.15, 15000.0, 46.0, 1344.58, 113.175, 749.127 + 0.2, 15000.0, 46.0, 1325.72, 95.8564, 735.415 + 0.25, 15000.0, 46.0, 1321.21, 80.0108, 726.763 + 0.3, 15000.0, 46.0, 1322.74, 65.0516, 719.648 + 0.35, 15000.0, 46.0, 1322.0, 50.3921, 710.55 + 0.4, 15000.0, 46.0, 1310.68, 35.4459, 695.95 + 0.45, 15000.0, 46.0, 1272.22, 18.9295, 668.663 + 0.5, 15000.0, 46.0, 1223.09, 2.34658, 636.155 + 0.55, 15000.0, 46.0, 1171.51, -13.4959, 602.229 + 0.6, 15000.0, 46.0, 1125.69, -27.7911, 570.686 + 0.0, 15000.0, 48.0, 1678.08, 192.888, 905.569 + 0.05, 15000.0, 48.0, 1558.51, 165.997, 851.551 + 0.1, 15000.0, 48.0, 1480.95, 142.786, 814.49 + 0.15, 15000.0, 48.0, 1436.53, 122.586, 790.587 + 0.2, 15000.0, 48.0, 1416.34, 104.722, 776.042 + 0.25, 15000.0, 48.0, 1411.51, 88.5227, 767.054 + 0.3, 15000.0, 48.0, 1413.15, 73.3163, 759.825 + 0.35, 15000.0, 48.0, 1412.38, 58.4304, 750.552 + 0.4, 15000.0, 48.0, 1400.3, 43.1927, 735.438 + 0.45, 15000.0, 48.0, 1359.19, 26.1566, 706.739 + 0.5, 15000.0, 48.0, 1306.69, 8.97307, 672.48 + 0.55, 15000.0, 48.0, 1251.59, -7.48124, 636.743 + 0.6, 15000.0, 48.0, 1202.69, -22.3298, 603.609 + 0.0, 15000.0, 50.0, 1782.5, 205.8, 958.1 + 0.05, 15000.0, 50.0, 1656.36, 177.331, 898.981 + 0.1, 15000.0, 50.0, 1574.6, 153.0, 858.5 + 0.15, 15000.0, 50.0, 1527.81, 132.044, 832.519 + 0.2, 15000.0, 50.0, 1506.6, 113.7, 816.9 + 0.25, 15000.0, 50.0, 1501.56, 97.2062, 807.506 + 0.3, 15000.0, 50.0, 1503.3, 81.8, 800.2 + 0.35, 15000.0, 50.0, 1502.41, 66.7187, 790.844 + 0.4, 15000.0, 50.0, 1489.5, 51.2, 775.3 + 0.45, 15000.0, 50.0, 1445.81, 33.6125, 745.156 + 0.5, 15000.0, 50.0, 1390.0, 15.8, 709.1 + 0.55, 15000.0, 50.0, 1331.39, -1.2625, 671.544 + 0.6, 15000.0, 50.0, 1279.3, -16.6, 636.9 + 0.0, 17500.0, 20.0, 128.9, 39.8, 262.4 + 0.05, 17500.0, 20.0, 138.125, 30.4563, 264.481 + 0.1, 17500.0, 20.0, 145.2, 21.0, 264.5 + 0.15, 17500.0, 20.0, 150.375, 11.4938, 262.619 + 0.2, 17500.0, 20.0, 153.9, 2.0, 259.0 + 0.25, 17500.0, 20.0, 156.025, -7.41875, 253.806 + 0.3, 17500.0, 20.0, 157.0, -16.7, 247.2 + 0.35, 17500.0, 20.0, 157.075, -25.7812, 239.344 + 0.4, 17500.0, 20.0, 156.5, -34.6, 230.4 + 0.45, 17500.0, 20.0, 156.144, -43.0875, 220.706 + 0.5, 17500.0, 20.0, 154.4, -51.2, 209.9 + 0.55, 17500.0, 20.0, 150.281, -58.8875, 197.794 + 0.6, 17500.0, 20.0, 142.8, -66.1, 184.2 + 0.0, 17500.0, 22.0, 204.798, 49.164, 288.244 + 0.05, 17500.0, 22.0, 220.159, 39.0309, 292.893 + 0.1, 17500.0, 22.0, 231.925, 28.7793, 294.846 + 0.15, 17500.0, 22.0, 240.519, 18.4754, 294.348 + 0.2, 17500.0, 22.0, 246.362, 8.18557, 291.645 + 0.25, 17500.0, 22.0, 249.877, -2.02378, 286.984 + 0.3, 17500.0, 22.0, 251.486, -12.0863, 280.61 + 0.35, 17500.0, 22.0, 251.613, -21.9358, 272.769 + 0.4, 17500.0, 22.0, 250.68, -31.5058, 263.708 + 0.45, 17500.0, 22.0, 250.112, -40.7154, 254.009 + 0.5, 17500.0, 22.0, 247.323, -49.542, 242.907 + 0.55, 17500.0, 22.0, 240.729, -57.9482, 229.971 + 0.6, 17500.0, 22.0, 228.748, -65.897, 214.773 + 0.0, 17500.0, 24.0, 281.749, 56.9925, 315.478 + 0.05, 17500.0, 24.0, 302.738, 46.5841, 322.783 + 0.1, 17500.0, 24.0, 318.823, 35.9597, 326.748 + 0.15, 17500.0, 24.0, 330.577, 25.2002, 327.698 + 0.2, 17500.0, 24.0, 338.575, 14.3866, 325.961 + 0.25, 17500.0, 24.0, 343.392, 3.59969, 321.864 + 0.3, 17500.0, 24.0, 345.603, -7.07955, 315.732 + 0.35, 17500.0, 24.0, 345.783, -17.5702, 307.892 + 0.4, 17500.0, 24.0, 344.506, -27.7914, 298.671 + 0.45, 17500.0, 24.0, 343.721, -37.6304, 288.902 + 0.5, 17500.0, 24.0, 339.882, -47.1016, 277.391 + 0.55, 17500.0, 24.0, 330.817, -56.1877, 263.45 + 0.6, 17500.0, 24.0, 314.354, -64.8712, 246.394 + 0.0, 17500.0, 26.0, 358.991, 63.9491, 344.101 + 0.05, 17500.0, 26.0, 385.477, 53.6025, 354.034 + 0.1, 17500.0, 26.0, 405.777, 42.8805, 359.997 + 0.15, 17500.0, 26.0, 420.616, 31.8868, 362.39 + 0.2, 17500.0, 26.0, 430.717, 20.7248, 361.615 + 0.25, 17500.0, 26.0, 436.803, 9.49817, 358.074 + 0.3, 17500.0, 26.0, 439.597, -1.68959, 352.169 + 0.35, 17500.0, 26.0, 439.822, -12.7349, 344.3 + 0.4, 17500.0, 26.0, 438.202, -23.5341, 334.87 + 0.45, 17500.0, 26.0, 437.203, -33.9258, 324.952 + 0.5, 17500.0, 26.0, 432.318, -43.9803, 312.931 + 0.55, 17500.0, 26.0, 420.787, -53.7098, 297.864 + 0.6, 17500.0, 26.0, 399.846, -63.1268, 278.808 + 0.0, 17500.0, 28.0, 435.374, 70.7419, 374.234 + 0.05, 17500.0, 28.0, 467.792, 60.6351, 386.612 + 0.1, 17500.0, 28.0, 492.613, 49.9482, 394.434 + 0.15, 17500.0, 28.0, 510.733, 38.8157, 398.168 + 0.2, 17500.0, 28.0, 523.044, 27.3721, 398.28 + 0.25, 17500.0, 28.0, 530.44, 15.7517, 395.236 + 0.3, 17500.0, 28.0, 533.815, 4.08923, 389.504 + 0.35, 17500.0, 28.0, 534.062, -7.48102, 381.549 + 0.4, 17500.0, 28.0, 532.076, -18.8246, 371.838 + 0.45, 17500.0, 28.0, 530.882, -29.7105, 361.653 + 0.5, 17500.0, 28.0, 524.977, -40.2936, 349.014 + 0.55, 17500.0, 28.0, 510.989, -50.6319, 332.757 + 0.6, 17500.0, 28.0, 485.546, -60.7838, 311.716 + 0.0, 17500.0, 30.0, 511.3, 77.9, 405.5 + 0.05, 17500.0, 30.0, 549.888, 67.9812, 420.15 + 0.1, 17500.0, 30.0, 579.4, 57.3, 429.7 + 0.15, 17500.0, 30.0, 600.913, 46.0187, 434.675 + 0.2, 17500.0, 30.0, 615.5, 34.3, 435.6 + 0.25, 17500.0, 30.0, 624.237, 22.3062, 433.0 + 0.3, 17500.0, 30.0, 628.2, 10.2, 427.4 + 0.35, 17500.0, 30.0, 628.462, -1.85625, 419.325 + 0.4, 17500.0, 30.0, 626.1, -13.7, 409.3 + 0.45, 17500.0, 30.0, 624.719, -25.0312, 398.8 + 0.5, 17500.0, 30.0, 617.8, -36.1, 385.5 + 0.55, 17500.0, 30.0, 601.356, -47.0187, 368.025 + 0.6, 17500.0, 30.0, 571.4, -57.9, 345.0 + 0.0, 17500.0, 32.0, 588.056, 86.2904, 437.185 + 0.05, 17500.0, 32.0, 632.43, 76.068, 454.037 + 0.1, 17500.0, 32.0, 666.371, 65.0662, 465.249 + 0.15, 17500.0, 32.0, 691.117, 53.4482, 471.408 + 0.2, 17500.0, 32.0, 707.901, 41.3769, 473.101 + 0.25, 17500.0, 32.0, 717.958, 29.015, 470.914 + 0.3, 17500.0, 32.0, 722.524, 16.5256, 465.435 + 0.35, 17500.0, 32.0, 722.832, 4.07159, 457.249 + 0.4, 17500.0, 32.0, 720.118, -8.18418, 446.943 + 0.45, 17500.0, 32.0, 718.525, -19.9186, 436.213 + 0.5, 17500.0, 32.0, 710.561, -31.4492, 422.32 + 0.55, 17500.0, 32.0, 691.645, -42.9336, 403.632 + 0.6, 17500.0, 32.0, 657.192, -54.5292, 378.52 + 0.0, 17500.0, 34.0, 664.932, 94.4414, 470.268 + 0.05, 17500.0, 34.0, 714.972, 84.079, 488.859 + 0.1, 17500.0, 34.0, 753.262, 72.8844, 501.402 + 0.15, 17500.0, 34.0, 781.19, 61.0267, 508.526 + 0.2, 17500.0, 34.0, 800.145, 48.6752, 510.863 + 0.25, 17500.0, 34.0, 811.514, 35.9989, 509.043 + 0.3, 17500.0, 34.0, 816.686, 23.1668, 503.698 + 0.35, 17500.0, 34.0, 817.049, 10.348, 495.457 + 0.4, 17500.0, 34.0, 813.991, -2.28828, 484.951 + 0.45, 17500.0, 34.0, 812.18, -14.3859, 474.078 + 0.5, 17500.0, 34.0, 803.165, -26.3371, 459.669 + 0.55, 17500.0, 34.0, 781.775, -38.3472, 439.826 + 0.6, 17500.0, 34.0, 742.84, -50.6211, 412.645 + 0.0, 17500.0, 36.0, 741.594, 101.774, 503.643 + 0.05, 17500.0, 36.0, 797.345, 91.6851, 523.937 + 0.1, 17500.0, 36.0, 840.012, 80.6016, 537.803 + 0.15, 17500.0, 36.0, 871.14, 68.7159, 545.911 + 0.2, 17500.0, 36.0, 892.272, 56.2206, 548.932 + 0.25, 17500.0, 36.0, 904.954, 43.3083, 547.535 + 0.3, 17500.0, 36.0, 910.729, 30.1715, 542.39 + 0.35, 17500.0, 36.0, 911.142, 17.0028, 534.167 + 0.4, 17500.0, 36.0, 907.737, 3.9949, 523.537 + 0.45, 17500.0, 36.0, 905.712, -8.43436, 512.595 + 0.5, 17500.0, 36.0, 895.652, -20.7684, 497.732 + 0.55, 17500.0, 36.0, 871.796, -33.2653, 476.764 + 0.6, 17500.0, 36.0, 828.383, -46.1833, 447.508 + 0.0, 17500.0, 38.0, 817.726, 109.018, 529.934 + 0.05, 17500.0, 38.0, 879.598, 99.2665, 554.854 + 0.1, 17500.0, 38.0, 926.924, 88.3699, 572.219 + 0.15, 17500.0, 38.0, 961.426, 76.5389, 582.842 + 0.2, 17500.0, 38.0, 984.826, 63.9841, 587.539 + 0.25, 17500.0, 38.0, 998.848, 50.9165, 587.125 + 0.3, 17500.0, 38.0, 1005.21, 37.5469, 582.414 + 0.35, 17500.0, 38.0, 1005.65, 24.0859, 574.221 + 0.4, 17500.0, 38.0, 1001.87, 10.7446, 563.36 + 0.45, 17500.0, 38.0, 999.652, -2.00814, 552.318 + 0.5, 17500.0, 38.0, 988.572, -14.7363, 536.899 + 0.55, 17500.0, 38.0, 962.254, -27.7458, 514.579 + 0.6, 17500.0, 38.0, 914.324, -41.3425, 482.836 + 0.0, 17500.0, 40.0, 896.1, 117.7, 563.5 + 0.05, 17500.0, 40.0, 963.05, 107.894, 590.681 + 0.1, 17500.0, 40.0, 1014.3, 96.9, 609.8 + 0.15, 17500.0, 40.0, 1051.7, 84.9312, 621.719 + 0.2, 17500.0, 40.0, 1077.1, 72.2, 627.3 + 0.25, 17500.0, 40.0, 1092.35, 58.9188, 627.406 + 0.3, 17500.0, 40.0, 1099.3, 45.3, 622.9 + 0.35, 17500.0, 40.0, 1099.8, 31.5562, 614.644 + 0.4, 17500.0, 40.0, 1095.7, 17.9, 603.5 + 0.45, 17500.0, 40.0, 1093.25, 4.81875, 592.131 + 0.5, 17500.0, 40.0, 1081.1, -8.3, 576.0 + 0.55, 17500.0, 40.0, 1052.3, -21.7937, 552.369 + 0.6, 17500.0, 40.0, 999.9, -36.0, 518.5 + 0.0, 17500.0, 42.0, 973.34, 123.569, 596.68 + 0.05, 17500.0, 42.0, 1045.77, 114.936, 626.483 + 0.1, 17500.0, 42.0, 1101.24, 104.696, 647.571 + 0.15, 17500.0, 42.0, 1141.75, 93.1287, 660.883 + 0.2, 17500.0, 42.0, 1169.28, 80.5133, 667.357 + 0.25, 17500.0, 42.0, 1185.83, 67.1286, 667.935 + 0.3, 17500.0, 42.0, 1193.39, 53.2537, 663.554 + 0.35, 17500.0, 42.0, 1193.97, 39.1677, 655.154 + 0.4, 17500.0, 42.0, 1189.54, 25.1496, 643.674 + 0.45, 17500.0, 42.0, 1186.87, 11.8489, 632.019 + 0.5, 17500.0, 42.0, 1173.66, -1.56648, 615.233 + 0.55, 17500.0, 42.0, 1142.37, -15.5583, 590.327 + 0.6, 17500.0, 42.0, 1085.48, -30.5882, 554.31 + 0.0, 17500.0, 44.0, 1049.07, 131.5, 629.682 + 0.05, 17500.0, 44.0, 1127.8, 123.305, 662.369 + 0.1, 17500.0, 44.0, 1188.04, 113.324, 685.613 + 0.15, 17500.0, 44.0, 1231.99, 101.859, 700.441 + 0.2, 17500.0, 44.0, 1261.82, 89.2139, 707.883 + 0.25, 17500.0, 44.0, 1279.72, 75.6909, 708.968 + 0.3, 17500.0, 44.0, 1287.86, 61.5934, 704.723 + 0.35, 17500.0, 44.0, 1288.44, 47.2245, 696.179 + 0.4, 17500.0, 44.0, 1283.64, 32.887, 684.363 + 0.45, 17500.0, 44.0, 1280.81, 19.3039, 672.469 + 0.5, 17500.0, 44.0, 1266.61, 5.51906, 655.031 + 0.55, 17500.0, 44.0, 1232.87, -9.00356, 628.745 + 0.6, 17500.0, 44.0, 1171.41, -24.8002, 590.308 + 0.0, 17500.0, 46.0, 1126.06, 139.818, 662.121 + 0.05, 17500.0, 46.0, 1210.34, 131.971, 698.015 + 0.1, 17500.0, 46.0, 1274.86, 122.181, 723.633 + 0.15, 17500.0, 46.0, 1321.94, 110.772, 740.111 + 0.2, 17500.0, 46.0, 1353.92, 98.0704, 748.588 + 0.25, 17500.0, 46.0, 1373.13, 84.4016, 750.201 + 0.3, 17500.0, 46.0, 1381.88, 70.0909, 746.087 + 0.35, 17500.0, 46.0, 1382.52, 55.4639, 737.383 + 0.4, 17500.0, 46.0, 1377.36, 40.846, 725.228 + 0.45, 17500.0, 46.0, 1374.28, 27.0255, 713.13 + 0.5, 17500.0, 46.0, 1359.0, 12.9394, 695.112 + 0.55, 17500.0, 46.0, 1322.79, -2.01271, 667.565 + 0.6, 17500.0, 46.0, 1256.93, -18.4311, 626.884 + 0.0, 17500.0, 48.0, 1202.57, 148.607, 696.872 + 0.05, 17500.0, 48.0, 1292.78, 141.027, 735.157 + 0.1, 17500.0, 48.0, 1361.83, 131.365, 762.581 + 0.15, 17500.0, 48.0, 1412.21, 119.967, 780.355 + 0.2, 17500.0, 48.0, 1446.42, 107.182, 789.687 + 0.25, 17500.0, 48.0, 1466.95, 93.3561, 791.786 + 0.3, 17500.0, 48.0, 1476.3, 78.8369, 787.86 + 0.35, 17500.0, 48.0, 1476.97, 63.9714, 779.119 + 0.4, 17500.0, 48.0, 1471.46, 49.1069, 766.77 + 0.45, 17500.0, 48.0, 1468.17, 35.1165, 754.604 + 0.5, 17500.0, 48.0, 1451.86, 20.7696, 736.089 + 0.55, 17500.0, 48.0, 1413.19, 5.36176, 707.273 + 0.6, 17500.0, 48.0, 1342.81, -11.8118, 664.206 + 0.0, 17500.0, 50.0, 1280.9, 159.4, 733.6 + 0.05, 17500.0, 50.0, 1376.21, 151.206, 773.406 + 0.1, 17500.0, 50.0, 1449.2, 141.1, 802.1 + 0.15, 17500.0, 50.0, 1502.49, 129.394, 820.894 + 0.2, 17500.0, 50.0, 1538.7, 116.4, 831.0 + 0.25, 17500.0, 50.0, 1560.46, 102.431, 833.631 + 0.3, 17500.0, 50.0, 1570.4, 87.8, 830.0 + 0.35, 17500.0, 50.0, 1571.14, 72.8188, 821.319 + 0.4, 17500.0, 50.0, 1565.3, 57.8, 808.8 + 0.45, 17500.0, 50.0, 1561.78, 43.5812, 796.344 + 0.5, 17500.0, 50.0, 1544.4, 28.9, 777.1 + 0.55, 17500.0, 50.0, 1503.24, 13.0188, 746.906 + 0.6, 17500.0, 50.0, 1428.4, -4.8, 701.6 + 0.0, 20000.0, 20.0, 162.5, 41.8, 294.8 + 0.05, 20000.0, 20.0, 157.781, 31.6875, 293.4 + 0.1, 20000.0, 20.0, 155.2, 21.7, 290.7 + 0.15, 20000.0, 20.0, 154.344, 11.8625, 286.75 + 0.2, 20000.0, 20.0, 154.8, 2.2, 281.6 + 0.25, 20000.0, 20.0, 156.156, -7.2625, 275.3 + 0.3, 20000.0, 20.0, 158.0, -16.5, 267.9 + 0.35, 20000.0, 20.0, 159.919, -25.4875, 259.45 + 0.4, 20000.0, 20.0, 161.5, -34.2, 250.0 + 0.45, 20000.0, 20.0, 162.156, -42.6188, 239.581 + 0.5, 20000.0, 20.0, 162.0, -50.7, 228.3 + 0.55, 20000.0, 20.0, 160.969, -58.4063, 216.244 + 0.6, 20000.0, 20.0, 159.0, -65.7, 203.5 + 0.0, 20000.0, 22.0, 258.199, 49.4351, 321.673 + 0.05, 20000.0, 22.0, 251.476, 39.1425, 319.349 + 0.1, 20000.0, 22.0, 247.929, 28.8209, 316.277 + 0.15, 20000.0, 22.0, 246.937, 18.5189, 312.403 + 0.2, 20000.0, 22.0, 247.88, 8.28485, 307.676 + 0.25, 20000.0, 22.0, 250.137, -1.8328, 302.042 + 0.3, 20000.0, 22.0, 253.088, -11.7856, 295.448 + 0.35, 20000.0, 22.0, 256.111, -21.5252, 287.841 + 0.4, 20000.0, 22.0, 258.586, -31.003, 279.169 + 0.45, 20000.0, 22.0, 259.636, -40.1704, 269.31 + 0.5, 20000.0, 22.0, 259.41, -48.9798, 258.415 + 0.55, 20000.0, 22.0, 257.797, -57.3832, 246.567 + 0.6, 20000.0, 22.0, 254.689, -65.3328, 233.849 + 0.0, 20000.0, 24.0, 355.85, 59.0754, 353.581 + 0.05, 20000.0, 24.0, 346.176, 47.7505, 350.188 + 0.1, 20000.0, 24.0, 341.005, 36.5283, 346.613 + 0.15, 20000.0, 24.0, 339.458, 25.4359, 342.694 + 0.2, 20000.0, 24.0, 340.66, 14.5002, 338.267 + 0.25, 20000.0, 24.0, 343.734, 3.74819, 333.171 + 0.3, 20000.0, 24.0, 347.804, -6.79317, 327.242 + 0.35, 20000.0, 24.0, 351.992, -17.0969, 320.317 + 0.4, 20000.0, 24.0, 355.423, -27.136, 312.234 + 0.45, 20000.0, 24.0, 356.846, -36.8952, 302.714 + 0.5, 20000.0, 24.0, 356.505, -46.3126, 291.944 + 0.55, 20000.0, 24.0, 354.268, -55.338, 279.994 + 0.6, 20000.0, 24.0, 350.004, -63.9212, 266.937 + 0.0, 20000.0, 26.0, 454.15, 69.4682, 389.413 + 0.05, 20000.0, 26.0, 441.211, 56.8179, 384.703 + 0.1, 20000.0, 26.0, 434.195, 44.5153, 380.422 + 0.15, 20000.0, 26.0, 431.954, 32.5478, 376.289 + 0.2, 20000.0, 26.0, 433.34, 20.9031, 372.021 + 0.25, 20000.0, 26.0, 437.203, 9.56871, 367.336 + 0.3, 20000.0, 26.0, 442.396, -1.46791, 361.952 + 0.35, 20000.0, 26.0, 447.77, -12.2192, 355.586 + 0.4, 20000.0, 26.0, 452.177, -22.6975, 347.956 + 0.45, 20000.0, 26.0, 453.966, -32.9466, 338.607 + 0.5, 20000.0, 26.0, 453.495, -42.8854, 327.775 + 0.55, 20000.0, 26.0, 450.62, -52.4642, 315.522 + 0.6, 20000.0, 26.0, 445.196, -61.6332, 301.911 + 0.0, 20000.0, 28.0, 551.161, 78.8939, 428.355 + 0.05, 20000.0, 28.0, 535.573, 65.3909, 421.758 + 0.1, 20000.0, 28.0, 527.142, 52.3584, 416.341 + 0.15, 20000.0, 28.0, 524.48, 39.7635, 411.68 + 0.2, 20000.0, 28.0, 526.197, 27.5728, 407.348 + 0.25, 20000.0, 28.0, 530.905, 15.7533, 402.923 + 0.3, 20000.0, 28.0, 537.214, 4.27167, 397.98 + 0.35, 20000.0, 28.0, 543.735, -6.90516, 392.094 + 0.4, 20000.0, 28.0, 549.079, -17.8104, 384.841 + 0.45, 20000.0, 28.0, 551.248, -28.5209, 375.546 + 0.5, 20000.0, 28.0, 550.677, -38.9387, 364.537 + 0.55, 20000.0, 28.0, 547.191, -49.0098, 351.891 + 0.6, 20000.0, 28.0, 540.613, -58.6798, 337.688 + 0.0, 20000.0, 30.0, 647.5, 87.5, 468.4 + 0.05, 20000.0, 30.0, 629.606, 73.5562, 459.894 + 0.1, 20000.0, 30.0, 620.0, 60.1, 453.3 + 0.15, 20000.0, 30.0, 617.069, 47.0937, 448.056 + 0.2, 20000.0, 30.0, 619.2, 34.5, 443.6 + 0.25, 20000.0, 30.0, 624.781, 22.2812, 439.369 + 0.3, 20000.0, 30.0, 632.2, 10.4, 434.8 + 0.35, 20000.0, 30.0, 639.844, -1.18125, 429.331 + 0.4, 20000.0, 30.0, 646.1, -12.5, 422.4 + 0.45, 20000.0, 30.0, 648.656, -23.6438, 413.112 + 0.5, 20000.0, 30.0, 648.0, -34.5, 401.9 + 0.55, 20000.0, 30.0, 643.919, -45.0063, 388.862 + 0.6, 20000.0, 30.0, 636.2, -55.1, 374.1 + 0.0, 20000.0, 32.0, 745.387, 96.0806, 505.599 + 0.05, 20000.0, 32.0, 724.542, 81.7619, 496.624 + 0.1, 20000.0, 32.0, 713.308, 67.9436, 489.847 + 0.15, 20000.0, 32.0, 709.818, 54.5847, 484.644 + 0.2, 20000.0, 32.0, 712.203, 41.6441, 480.39 + 0.25, 20000.0, 32.0, 718.594, 29.0807, 476.461 + 0.3, 20000.0, 32.0, 727.124, 16.8537, 472.232 + 0.35, 20000.0, 32.0, 735.925, 4.92183, 467.08 + 0.4, 20000.0, 32.0, 743.128, -6.75582, 460.38 + 0.45, 20000.0, 32.0, 746.044, -18.2762, 451.15 + 0.5, 20000.0, 32.0, 745.267, -29.5127, 439.838 + 0.55, 20000.0, 32.0, 740.57, -40.3943, 426.533 + 0.6, 20000.0, 32.0, 731.725, -50.8504, 411.326 + 0.0, 20000.0, 34.0, 842.382, 105.74, 545.689 + 0.05, 20000.0, 34.0, 818.877, 90.6249, 535.14 + 0.1, 20000.0, 34.0, 806.22, 76.1664, 527.418 + 0.15, 20000.0, 34.0, 802.302, 62.2967, 521.783 + 0.2, 20000.0, 34.0, 805.014, 48.948, 517.496 + 0.25, 20000.0, 34.0, 812.245, 36.0529, 513.816 + 0.3, 20000.0, 34.0, 821.886, 23.5438, 510.002 + 0.35, 20000.0, 34.0, 831.829, 11.353, 505.314 + 0.4, 20000.0, 34.0, 839.962, -0.58708, 499.013 + 0.45, 20000.0, 34.0, 843.247, -12.4161, 489.954 + 0.5, 20000.0, 34.0, 842.363, -23.9852, 478.607 + 0.55, 20000.0, 34.0, 837.06, -35.2174, 465.038 + 0.6, 20000.0, 34.0, 827.087, -46.036, 449.313 + 0.0, 20000.0, 36.0, 938.267, 116.452, 589.458 + 0.05, 20000.0, 36.0, 912.503, 100.137, 575.834 + 0.1, 20000.0, 36.0, 898.702, 84.7708, 566.155 + 0.15, 20000.0, 36.0, 894.535, 70.238, 559.484 + 0.2, 20000.0, 36.0, 897.67, 56.4219, 554.883 + 0.25, 20000.0, 36.0, 905.778, 43.2064, 551.417 + 0.3, 20000.0, 36.0, 916.528, 30.4751, 548.148 + 0.35, 20000.0, 36.0, 927.589, 18.1117, 544.139 + 0.4, 20000.0, 36.0, 936.631, 5.99991, 538.455 + 0.45, 20000.0, 36.0, 940.303, -6.0732, 529.672 + 0.5, 20000.0, 36.0, 939.336, -17.9337, 518.312 + 0.55, 20000.0, 36.0, 933.441, -29.5044, 504.411 + 0.6, 20000.0, 36.0, 922.327, -40.708, 488.004 + 0.0, 20000.0, 38.0, 1037.43, 124.758, 627.355 + 0.05, 20000.0, 38.0, 1008.31, 108.377, 613.383 + 0.1, 20000.0, 38.0, 992.581, 92.9104, 603.726 + 0.15, 20000.0, 38.0, 987.651, 78.2446, 597.362 + 0.2, 20000.0, 38.0, 990.916, 64.2674, 593.263 + 0.25, 20000.0, 38.0, 999.771, 50.8667, 590.406 + 0.3, 20000.0, 38.0, 1011.61, 37.9302, 587.765 + 0.35, 20000.0, 38.0, 1023.84, 25.3454, 584.316 + 0.4, 20000.0, 38.0, 1033.86, 13.0001, 579.032 + 0.45, 20000.0, 38.0, 1037.9, 0.693247, 570.375 + 0.5, 20000.0, 38.0, 1036.82, -11.4213, 558.862 + 0.55, 20000.0, 38.0, 1030.29, -23.2782, 544.496 + 0.6, 20000.0, 38.0, 1018.02, -34.8125, 527.279 + 0.0, 20000.0, 40.0, 1135.9, 136.1, 669.7 + 0.05, 20000.0, 40.0, 1103.49, 118.544, 654.094 + 0.1, 20000.0, 40.0, 1085.9, 102.2, 643.5 + 0.15, 20000.0, 40.0, 1080.26, 86.9063, 636.756 + 0.2, 20000.0, 40.0, 1083.7, 72.5, 632.7 + 0.25, 20000.0, 40.0, 1093.34, 58.8188, 630.169 + 0.3, 20000.0, 40.0, 1106.3, 45.7, 628.0 + 0.35, 20000.0, 40.0, 1119.71, 32.9813, 625.031 + 0.4, 20000.0, 40.0, 1130.7, 20.5, 620.1 + 0.45, 20000.0, 40.0, 1135.11, 7.9875, 611.456 + 0.5, 20000.0, 40.0, 1133.9, -4.4, 599.7 + 0.55, 20000.0, 40.0, 1126.74, -16.6125, 584.844 + 0.6, 20000.0, 40.0, 1113.3, -28.6, 566.9 + 0.0, 20000.0, 42.0, 1232.69, 145.814, 710.136 + 0.05, 20000.0, 42.0, 1197.71, 127.83, 693.827 + 0.1, 20000.0, 42.0, 1178.76, 111.137, 682.935 + 0.15, 20000.0, 42.0, 1172.72, 95.5591, 676.208 + 0.2, 20000.0, 42.0, 1176.48, 80.918, 672.395 + 0.25, 20000.0, 42.0, 1186.94, 67.0365, 670.243 + 0.3, 20000.0, 42.0, 1200.99, 53.737, 668.5 + 0.35, 20000.0, 42.0, 1215.53, 40.842, 665.915 + 0.4, 20000.0, 42.0, 1227.45, 28.1742, 661.236 + 0.45, 20000.0, 42.0, 1232.27, 15.4422, 652.576 + 0.5, 20000.0, 42.0, 1230.99, 2.80984, 640.587 + 0.55, 20000.0, 42.0, 1223.23, -9.67292, 625.286 + 0.6, 20000.0, 42.0, 1208.61, -21.9561, 606.692 + 0.0, 20000.0, 44.0, 1330.63, 155.941, 753.564 + 0.05, 20000.0, 44.0, 1292.7, 137.488, 735.557 + 0.1, 20000.0, 44.0, 1272.13, 120.409, 723.646 + 0.15, 20000.0, 44.0, 1265.55, 104.515, 716.449 + 0.2, 20000.0, 44.0, 1269.58, 89.6139, 712.585 + 0.25, 20000.0, 44.0, 1280.88, 75.5165, 710.673 + 0.3, 20000.0, 44.0, 1296.06, 62.0318, 709.331 + 0.35, 20000.0, 44.0, 1311.78, 48.9696, 707.178 + 0.4, 20000.0, 44.0, 1324.65, 36.1395, 702.833 + 0.45, 20000.0, 44.0, 1329.83, 23.2303, 694.187 + 0.5, 20000.0, 44.0, 1328.43, 10.4134, 682.043 + 0.55, 20000.0, 44.0, 1320.06, -2.26054, 666.477 + 0.6, 20000.0, 44.0, 1304.33, -14.7408, 647.564 + 0.0, 20000.0, 46.0, 1426.45, 167.225, 795.168 + 0.05, 20000.0, 46.0, 1386.28, 147.86, 776.486 + 0.1, 20000.0, 46.0, 1364.58, 130.097, 764.222 + 0.15, 20000.0, 46.0, 1357.75, 113.709, 756.935 + 0.2, 20000.0, 46.0, 1362.22, 98.4704, 753.184 + 0.25, 20000.0, 46.0, 1374.39, 84.1527, 751.526 + 0.3, 20000.0, 46.0, 1390.68, 70.5293, 750.521 + 0.35, 20000.0, 46.0, 1407.51, 57.3732, 748.727 + 0.4, 20000.0, 46.0, 1421.29, 44.4574, 744.703 + 0.45, 20000.0, 46.0, 1426.86, 31.421, 736.315 + 0.5, 20000.0, 46.0, 1425.37, 18.4386, 724.197 + 0.55, 20000.0, 46.0, 1416.39, 5.5511, 708.292 + 0.6, 20000.0, 46.0, 1399.47, -7.20076, 688.543 + 0.0, 20000.0, 48.0, 1524.63, 180.309, 843.66 + 0.05, 20000.0, 48.0, 1481.44, 159.349, 821.483 + 0.1, 20000.0, 48.0, 1458.05, 140.443, 806.955 + 0.15, 20000.0, 48.0, 1450.62, 123.288, 798.419 + 0.2, 20000.0, 48.0, 1455.32, 107.582, 794.215 + 0.25, 20000.0, 48.0, 1468.29, 93.0237, 792.685 + 0.3, 20000.0, 48.0, 1485.7, 79.3107, 792.17 + 0.35, 20000.0, 48.0, 1503.7, 66.1409, 791.013 + 0.4, 20000.0, 48.0, 1518.45, 53.2123, 787.553 + 0.45, 20000.0, 48.0, 1524.4, 40.0427, 779.338 + 0.5, 20000.0, 48.0, 1522.81, 26.8703, 767.095 + 0.55, 20000.0, 48.0, 1513.19, 13.7533, 750.761 + 0.6, 20000.0, 48.0, 1495.1, 0.749768, 730.268 + 0.0, 20000.0, 50.0, 1621.4, 190.6, 887.0 + 0.05, 20000.0, 50.0, 1575.65, 169.213, 863.306 + 0.1, 20000.0, 50.0, 1550.9, 150.0, 848.0 + 0.15, 20000.0, 50.0, 1543.08, 132.638, 839.269 + 0.2, 20000.0, 50.0, 1548.1, 116.8, 835.3 + 0.25, 20000.0, 50.0, 1561.9, 102.162, 834.281 + 0.3, 20000.0, 50.0, 1580.4, 88.4, 834.4 + 0.35, 20000.0, 50.0, 1599.53, 75.1875, 833.844 + 0.4, 20000.0, 50.0, 1615.2, 62.2, 830.8 + 0.45, 20000.0, 50.0, 1621.57, 48.925, 822.544 + 0.5, 20000.0, 50.0, 1619.9, 35.6, 810.0 + 0.55, 20000.0, 50.0, 1609.68, 22.275, 793.181 + 0.6, 20000.0, 50.0, 1590.4, 9.0, 772.1 + 0.0, 23000.0, 20.0, 150.2, 40.9, 342.1 + 0.05, 23000.0, 20.0, 152.056, 31.2625, 341.856 + 0.1, 23000.0, 20.0, 153.8, 21.6, 339.3 + 0.15, 23000.0, 20.0, 155.469, 11.9625, 334.644 + 0.2, 23000.0, 20.0, 157.1, 2.4, 328.1 + 0.25, 23000.0, 20.0, 158.731, -7.0375, 319.881 + 0.3, 23000.0, 20.0, 160.4, -16.3, 310.2 + 0.35, 23000.0, 20.0, 162.144, -25.3375, 299.269 + 0.4, 23000.0, 20.0, 164.0, -34.1, 287.3 + 0.45, 23000.0, 20.0, 166.238, -42.5188, 274.55 + 0.5, 23000.0, 20.0, 168.2, -50.6, 261.1 + 0.55, 23000.0, 20.0, 169.463, -58.3313, 247.075 + 0.6, 23000.0, 20.0, 169.6, -65.7, 232.6 + 0.0, 23000.0, 22.0, 240.861, 50.9589, 351.257 + 0.05, 23000.0, 22.0, 243.682, 40.17, 351.114 + 0.1, 23000.0, 22.0, 246.371, 29.4855, 349.037 + 0.15, 23000.0, 22.0, 248.981, 18.9342, 345.193 + 0.2, 23000.0, 22.0, 251.563, 8.54498, 339.75 + 0.25, 23000.0, 22.0, 254.168, -1.65329, 332.876 + 0.3, 23000.0, 22.0, 256.848, -11.6318, 324.736 + 0.35, 23000.0, 22.0, 259.653, -21.3617, 315.498 + 0.4, 23000.0, 22.0, 262.635, -30.8142, 305.33 + 0.45, 23000.0, 22.0, 266.203, -39.9664, 294.48 + 0.5, 23000.0, 22.0, 269.338, -48.7714, 282.871 + 0.55, 23000.0, 22.0, 271.376, -57.1883, 270.51 + 0.6, 23000.0, 22.0, 271.657, -65.1762, 257.4 + 0.0, 23000.0, 24.0, 330.26, 59.1052, 370.678 + 0.05, 23000.0, 24.0, 334.466, 47.956, 371.234 + 0.1, 23000.0, 24.0, 338.386, 36.8286, 369.926 + 0.15, 23000.0, 24.0, 342.108, 25.7682, 366.921 + 0.2, 23000.0, 24.0, 345.722, 14.8203, 362.384 + 0.25, 23000.0, 24.0, 349.317, 4.03032, 356.478 + 0.3, 23000.0, 24.0, 352.984, -6.55626, 349.371 + 0.35, 23000.0, 24.0, 356.811, -16.8941, 341.226 + 0.4, 23000.0, 24.0, 360.888, -26.9376, 332.209 + 0.45, 23000.0, 24.0, 365.813, -36.6243, 322.635 + 0.5, 23000.0, 24.0, 370.149, -45.9604, 312.218 + 0.55, 23000.0, 24.0, 372.966, -54.935, 300.822 + 0.6, 23000.0, 24.0, 373.335, -63.537, 288.311 + 0.0, 23000.0, 26.0, 419.24, 66.7821, 397.591 + 0.05, 23000.0, 26.0, 424.971, 55.4921, 399.017 + 0.1, 23000.0, 26.0, 430.214, 44.0989, 398.508 + 0.15, 23000.0, 26.0, 435.105, 32.6726, 396.245 + 0.2, 23000.0, 26.0, 439.778, 21.2831, 392.412 + 0.25, 23000.0, 26.0, 444.37, 10.0006, 387.188 + 0.3, 23000.0, 26.0, 449.016, -1.10482, 380.758 + 0.35, 23000.0, 26.0, 453.852, -11.963, 373.302 + 0.4, 23000.0, 26.0, 459.012, -22.504, 365.002 + 0.45, 23000.0, 26.0, 465.305, -32.604, 356.271 + 0.5, 23000.0, 26.0, 470.851, -42.3537, 346.599 + 0.55, 23000.0, 26.0, 474.443, -51.7899, 335.706 + 0.6, 23000.0, 26.0, 474.873, -60.9496, 323.312 + 0.0, 23000.0, 28.0, 508.999, 76.312, 429.156 + 0.05, 23000.0, 28.0, 515.998, 64.1691, 430.924 + 0.1, 23000.0, 28.0, 522.39, 52.0353, 430.795 + 0.15, 23000.0, 28.0, 528.342, 39.9651, 428.948 + 0.2, 23000.0, 28.0, 534.021, 28.0127, 425.561 + 0.25, 23000.0, 28.0, 539.596, 16.2325, 420.813 + 0.3, 23000.0, 28.0, 545.233, 4.67879, 414.883 + 0.35, 23000.0, 28.0, 551.1, -6.59418, 407.948 + 0.4, 23000.0, 28.0, 557.364, -17.5321, 400.189 + 0.45, 23000.0, 28.0, 565.013, -28.032, 392.071 + 0.5, 23000.0, 28.0, 571.752, -38.1854, 382.909 + 0.55, 23000.0, 28.0, 576.108, -48.0352, 372.305 + 0.6, 23000.0, 28.0, 576.606, -57.6243, 359.863 + 0.0, 23000.0, 30.0, 599.3, 86.5, 462.8 + 0.05, 23000.0, 30.0, 607.381, 73.3, 464.775 + 0.1, 23000.0, 30.0, 614.8, 60.3, 464.9 + 0.15, 23000.0, 30.0, 621.744, 47.525, 463.35 + 0.2, 23000.0, 30.0, 628.4, 35.0, 460.3 + 0.25, 23000.0, 30.0, 634.956, 22.75, 455.925 + 0.3, 23000.0, 30.0, 641.6, 10.8, 450.4 + 0.35, 23000.0, 30.0, 648.519, -0.825, 443.9 + 0.4, 23000.0, 30.0, 655.9, -12.1, 436.6 + 0.45, 23000.0, 30.0, 664.887, -22.975, 429.013 + 0.5, 23000.0, 30.0, 672.8, -33.5, 420.3 + 0.55, 23000.0, 30.0, 677.913, -43.7, 409.963 + 0.6, 23000.0, 30.0, 678.5, -53.6, 397.5 + 0.0, 23000.0, 32.0, 688.767, 93.7732, 494.468 + 0.05, 23000.0, 32.0, 698.246, 80.807, 497.905 + 0.1, 23000.0, 32.0, 706.917, 67.8489, 499.126 + 0.15, 23000.0, 32.0, 715.002, 54.9591, 498.376 + 0.2, 23000.0, 32.0, 722.724, 42.1978, 495.903 + 0.25, 23000.0, 32.0, 730.304, 29.6253, 491.952 + 0.3, 23000.0, 32.0, 737.967, 17.3018, 486.771 + 0.35, 23000.0, 32.0, 745.935, 5.2875, 480.604 + 0.4, 23000.0, 32.0, 754.43, -6.35735, 473.698 + 0.45, 23000.0, 32.0, 764.785, -17.5232, 466.738 + 0.5, 23000.0, 32.0, 773.894, -28.2978, 458.657 + 0.55, 23000.0, 32.0, 779.761, -38.7197, 448.827 + 0.6, 23000.0, 32.0, 780.388, -48.8273, 436.619 + 0.0, 23000.0, 34.0, 780.934, 101.413, 530.156 + 0.05, 23000.0, 34.0, 790.52, 88.5888, 533.546 + 0.1, 23000.0, 34.0, 799.593, 75.6158, 534.845 + 0.15, 23000.0, 34.0, 808.321, 62.5867, 534.285 + 0.2, 23000.0, 34.0, 816.876, 49.5943, 532.099 + 0.25, 23000.0, 34.0, 825.427, 36.7311, 528.522 + 0.3, 23000.0, 34.0, 834.146, 24.09, 523.787 + 0.35, 23000.0, 34.0, 843.203, 11.7636, 518.126 + 0.4, 23000.0, 34.0, 852.768, -0.15537, 511.773 + 0.45, 23000.0, 34.0, 864.099, -11.4788, 505.427 + 0.5, 23000.0, 34.0, 874.103, -22.4002, 497.926 + 0.55, 23000.0, 34.0, 880.776, -33.0177, 488.576 + 0.6, 23000.0, 34.0, 882.111, -43.4295, 476.68 + 0.0, 23000.0, 36.0, 875.279, 110.681, 570.318 + 0.05, 23000.0, 36.0, 883.965, 97.3678, 571.861 + 0.1, 23000.0, 36.0, 892.764, 83.9536, 572.04 + 0.15, 23000.0, 36.0, 901.729, 70.5317, 570.97 + 0.2, 23000.0, 36.0, 910.913, 57.195, 568.764 + 0.25, 23000.0, 36.0, 920.373, 44.0362, 565.538 + 0.3, 23000.0, 36.0, 930.16, 31.1481, 561.405 + 0.35, 23000.0, 36.0, 940.33, 18.6235, 556.479 + 0.4, 23000.0, 36.0, 950.937, 6.55521, 550.875 + 0.45, 23000.0, 36.0, 962.978, -4.82677, 545.121 + 0.5, 23000.0, 36.0, 973.675, -15.8414, 538.089 + 0.55, 23000.0, 36.0, 981.193, -26.6705, 529.069 + 0.6, 23000.0, 36.0, 983.696, -37.4958, 517.348 + 0.0, 23000.0, 38.0, 960.805, 120.434, 603.507 + 0.05, 23000.0, 38.0, 972.867, 106.44, 606.692 + 0.1, 23000.0, 38.0, 984.177, 92.5045, 608.174 + 0.15, 23000.0, 38.0, 994.975, 78.6911, 608.127 + 0.2, 23000.0, 38.0, 1005.5, 65.0635, 606.724 + 0.25, 23000.0, 38.0, 1015.99, 51.6855, 604.136 + 0.3, 23000.0, 38.0, 1026.68, 38.6207, 600.538 + 0.35, 23000.0, 38.0, 1037.81, 25.9329, 596.103 + 0.4, 23000.0, 38.0, 1049.62, 13.6858, 591.002 + 0.45, 23000.0, 38.0, 1063.76, 2.0359, 585.962 + 0.5, 23000.0, 38.0, 1076.23, -9.23153, 579.497 + 0.55, 23000.0, 38.0, 1084.43, -20.2385, 570.671 + 0.6, 23000.0, 38.0, 1085.76, -31.1069, 558.551 + 0.0, 23000.0, 40.0, 1049.3, 127.6, 640.8 + 0.05, 23000.0, 40.0, 1063.11, 114.256, 644.4 + 0.1, 23000.0, 40.0, 1075.9, 100.7, 646.3 + 0.15, 23000.0, 40.0, 1087.96, 87.0438, 646.675 + 0.2, 23000.0, 40.0, 1099.6, 73.4, 645.7 + 0.25, 23000.0, 40.0, 1111.11, 59.8812, 643.55 + 0.3, 23000.0, 40.0, 1122.8, 46.6, 640.4 + 0.35, 23000.0, 40.0, 1134.96, 33.6687, 636.425 + 0.4, 23000.0, 40.0, 1147.9, 21.2, 631.8 + 0.45, 23000.0, 40.0, 1163.54, 9.45, 627.325 + 0.5, 23000.0, 40.0, 1177.3, -1.9, 621.3 + 0.55, 23000.0, 40.0, 1186.24, -13.025, 612.65 + 0.6, 23000.0, 40.0, 1187.4, -24.1, 600.3 + 0.0, 23000.0, 42.0, 1139.46, 139.702, 678.57 + 0.05, 23000.0, 42.0, 1154.37, 125.002, 682.658 + 0.1, 23000.0, 42.0, 1168.17, 110.437, 685.019 + 0.15, 23000.0, 42.0, 1181.21, 96.0638, 685.833 + 0.2, 23000.0, 42.0, 1193.8, 81.941, 685.281 + 0.25, 23000.0, 42.0, 1206.27, 68.1261, 683.544 + 0.3, 23000.0, 42.0, 1218.94, 54.6767, 680.802 + 0.35, 23000.0, 42.0, 1232.13, 41.6505, 677.236 + 0.4, 23000.0, 42.0, 1246.18, 29.1051, 673.026 + 0.45, 23000.0, 42.0, 1263.16, 17.1932, 668.999 + 0.5, 23000.0, 42.0, 1278.11, 5.68774, 663.398 + 0.55, 23000.0, 42.0, 1287.81, -5.54333, 655.112 + 0.6, 23000.0, 42.0, 1289.05, -16.6321, 643.031 + 0.0, 23000.0, 44.0, 1228.25, 146.559, 713.657 + 0.05, 23000.0, 44.0, 1244.93, 132.849, 719.635 + 0.1, 23000.0, 44.0, 1260.23, 118.884, 723.378 + 0.15, 23000.0, 44.0, 1274.55, 104.796, 725.164 + 0.2, 23000.0, 44.0, 1288.26, 90.7148, 725.272 + 0.25, 23000.0, 44.0, 1301.76, 76.7724, 723.979 + 0.3, 23000.0, 44.0, 1315.41, 63.0999, 721.563 + 0.35, 23000.0, 44.0, 1329.6, 49.8286, 718.303 + 0.4, 23000.0, 44.0, 1344.72, 37.0898, 714.476 + 0.45, 23000.0, 44.0, 1363.09, 25.1892, 711.155 + 0.5, 23000.0, 44.0, 1379.27, 13.7347, 706.235 + 0.55, 23000.0, 44.0, 1389.76, 2.50903, 698.408 + 0.6, 23000.0, 44.0, 1391.05, -8.70543, 686.363 + 0.0, 23000.0, 46.0, 1318.23, 159.104, 753.665 + 0.05, 23000.0, 46.0, 1335.98, 144.018, 759.596 + 0.1, 23000.0, 46.0, 1352.29, 129.02, 763.363 + 0.15, 23000.0, 46.0, 1367.59, 114.195, 765.25 + 0.2, 23000.0, 46.0, 1382.27, 99.6247, 765.539 + 0.25, 23000.0, 46.0, 1396.74, 85.3915, 764.515 + 0.3, 23000.0, 46.0, 1411.39, 71.578, 762.463 + 0.35, 23000.0, 46.0, 1426.64, 58.2668, 759.665 + 0.4, 23000.0, 46.0, 1442.87, 45.5404, 756.406 + 0.45, 23000.0, 46.0, 1462.58, 33.6386, 753.881 + 0.5, 23000.0, 46.0, 1479.93, 22.1724, 749.64 + 0.55, 23000.0, 46.0, 1491.16, 10.9098, 742.142 + 0.6, 23000.0, 46.0, 1492.54, -0.380992, 729.848 + 0.0, 23000.0, 48.0, 1408.79, 169.4, 795.745 + 0.05, 23000.0, 48.0, 1427.58, 154.013, 800.919 + 0.1, 23000.0, 48.0, 1444.89, 138.735, 804.3 + 0.15, 23000.0, 48.0, 1461.15, 123.655, 806.112 + 0.2, 23000.0, 48.0, 1476.78, 108.862, 806.581 + 0.25, 23000.0, 48.0, 1492.21, 94.4444, 805.931 + 0.3, 23000.0, 48.0, 1507.86, 80.4908, 804.386 + 0.35, 23000.0, 48.0, 1524.15, 67.09, 802.172 + 0.4, 23000.0, 48.0, 1541.51, 54.3305, 799.514 + 0.45, 23000.0, 48.0, 1562.55, 42.4986, 797.554 + 0.5, 23000.0, 48.0, 1581.09, 31.0908, 793.761 + 0.55, 23000.0, 48.0, 1593.11, 19.8013, 786.521 + 0.6, 23000.0, 48.0, 1594.63, 8.32423, 774.221 + 0.0, 23000.0, 50.0, 1498.4, 179.3, 835.2 + 0.05, 23000.0, 50.0, 1518.44, 163.731, 840.769 + 0.1, 23000.0, 50.0, 1536.9, 148.3, 844.6 + 0.15, 23000.0, 50.0, 1554.24, 133.094, 846.906 + 0.2, 23000.0, 50.0, 1570.9, 118.2, 847.9 + 0.25, 23000.0, 50.0, 1587.34, 103.706, 847.794 + 0.3, 23000.0, 50.0, 1604.0, 89.7, 846.8 + 0.35, 23000.0, 50.0, 1621.34, 76.2687, 845.131 + 0.4, 23000.0, 50.0, 1639.8, 63.5, 843.0 + 0.45, 23000.0, 50.0, 1662.19, 51.6875, 841.569 + 0.5, 23000.0, 50.0, 1681.9, 40.3, 838.2 + 0.55, 23000.0, 50.0, 1694.69, 29.0125, 831.206 + 0.6, 23000.0, 50.0, 1696.3, 17.5, 818.9 + 0.0, 25000.0, 20.0, 151.6, 42.1, 398.9 + 0.05, 25000.0, 20.0, 153.325, 31.9875, 398.087 + 0.1, 25000.0, 20.0, 155.0, 22.0, 394.4 + 0.15, 25000.0, 20.0, 156.65, 12.1625, 388.112 + 0.2, 25000.0, 20.0, 158.3, 2.5, 379.5 + 0.25, 25000.0, 20.0, 159.975, -6.9625, 368.838 + 0.3, 25000.0, 20.0, 161.7, -16.2, 356.4 + 0.35, 25000.0, 20.0, 163.5, -25.1875, 342.463 + 0.4, 25000.0, 20.0, 165.4, -33.9, 327.3 + 0.45, 25000.0, 20.0, 167.438, -42.3125, 311.188 + 0.5, 25000.0, 20.0, 169.6, -50.4, 294.4 + 0.55, 25000.0, 20.0, 171.888, -58.1375, 277.213 + 0.6, 25000.0, 20.0, 174.3, -65.5, 259.9 + 0.0, 25000.0, 22.0, 241.951, 50.9027, 385.858 + 0.05, 25000.0, 22.0, 245.144, 40.1948, 385.52 + 0.1, 25000.0, 22.0, 248.095, 29.57, 382.883 + 0.15, 25000.0, 22.0, 250.877, 19.0607, 378.156 + 0.2, 25000.0, 22.0, 253.562, 8.69952, 371.549 + 0.25, 25000.0, 22.0, 256.222, -1.48109, 363.271 + 0.3, 25000.0, 22.0, 258.929, -11.4486, 353.535 + 0.35, 25000.0, 22.0, 261.755, -21.1705, 342.548 + 0.4, 25000.0, 22.0, 264.771, -30.6142, 330.521 + 0.45, 25000.0, 22.0, 268.122, -39.7428, 317.654 + 0.5, 25000.0, 22.0, 271.663, -48.5372, 304.186 + 0.55, 25000.0, 22.0, 275.32, -56.9737, 290.347 + 0.6, 25000.0, 22.0, 279.022, -65.0287, 276.365 + 0.0, 25000.0, 24.0, 332.736, 59.6054, 394.756 + 0.05, 25000.0, 24.0, 337.023, 48.3443, 394.921 + 0.1, 25000.0, 24.0, 341.012, 37.1369, 393.065 + 0.15, 25000.0, 24.0, 344.796, 26.0234, 389.37 + 0.2, 25000.0, 24.0, 348.467, 15.0436, 384.016 + 0.25, 25000.0, 24.0, 352.119, 4.23755, 377.186 + 0.3, 25000.0, 24.0, 355.845, -6.35465, 369.058 + 0.35, 25000.0, 24.0, 359.736, -16.6931, 359.816 + 0.4, 25000.0, 24.0, 363.885, -26.7376, 349.639 + 0.45, 25000.0, 24.0, 368.477, -36.4413, 338.705 + 0.5, 25000.0, 24.0, 373.331, -45.7853, 327.205 + 0.55, 25000.0, 24.0, 378.359, -54.7439, 315.323 + 0.6, 25000.0, 24.0, 383.471, -63.2913, 303.245 + 0.0, 25000.0, 26.0, 423.545, 68.2268, 418.016 + 0.05, 25000.0, 26.0, 428.843, 56.467, 418.701 + 0.1, 25000.0, 26.0, 433.821, 44.7389, 417.456 + 0.15, 25000.0, 26.0, 438.585, 33.09, 414.454 + 0.2, 25000.0, 26.0, 443.241, 21.5678, 409.87 + 0.25, 25000.0, 26.0, 447.896, 10.2199, 403.879 + 0.3, 25000.0, 26.0, 452.655, -0.906429, 396.655 + 0.35, 25000.0, 26.0, 457.626, -11.7635, 388.373 + 0.4, 25000.0, 26.0, 462.915, -22.304, 379.206 + 0.45, 25000.0, 26.0, 468.723, -32.4696, 369.344 + 0.5, 25000.0, 26.0, 474.869, -42.2449, 358.92 + 0.55, 25000.0, 26.0, 481.266, -51.6036, 348.084 + 0.6, 25000.0, 26.0, 487.829, -60.5195, 336.984 + 0.0, 25000.0, 28.0, 513.62, 76.8431, 446.566 + 0.05, 25000.0, 28.0, 520.325, 64.6309, 447.743 + 0.1, 25000.0, 28.0, 526.559, 52.4371, 447.035 + 0.15, 25000.0, 28.0, 532.466, 40.3153, 444.609 + 0.2, 25000.0, 28.0, 538.189, 28.3191, 440.637 + 0.25, 25000.0, 28.0, 543.87, 16.5021, 435.288 + 0.3, 25000.0, 28.0, 549.652, 4.91795, 428.733 + 0.35, 25000.0, 28.0, 555.678, -6.37985, 421.14 + 0.4, 25000.0, 28.0, 562.09, -17.3377, 412.682 + 0.45, 25000.0, 28.0, 569.164, -27.8828, 403.552 + 0.5, 25000.0, 28.0, 576.645, -38.0191, 393.844 + 0.55, 25000.0, 28.0, 584.412, -47.7314, 383.678 + 0.6, 25000.0, 28.0, 592.343, -57.0045, 373.171 + 0.0, 25000.0, 30.0, 603.6, 85.3, 477.3 + 0.05, 25000.0, 30.0, 611.831, 72.7562, 479.05 + 0.1, 25000.0, 30.0, 619.4, 60.2, 478.9 + 0.15, 25000.0, 30.0, 626.494, 47.6937, 477.025 + 0.2, 25000.0, 30.0, 633.3, 35.3, 473.6 + 0.25, 25000.0, 30.0, 640.006, 23.0812, 468.8 + 0.3, 25000.0, 30.0, 646.8, 11.1, 462.8 + 0.35, 25000.0, 30.0, 653.869, -0.58125, 455.775 + 0.4, 25000.0, 30.0, 661.4, -11.9, 447.9 + 0.45, 25000.0, 30.0, 669.763, -22.7625, 439.387 + 0.5, 25000.0, 30.0, 678.6, -33.2, 430.3 + 0.55, 25000.0, 30.0, 687.738, -43.2125, 420.737 + 0.6, 25000.0, 30.0, 697.0, -52.8, 410.8 + 0.0, 25000.0, 32.0, 695.182, 93.0283, 508.442 + 0.05, 25000.0, 32.0, 704.287, 80.5186, 511.256 + 0.1, 25000.0, 32.0, 712.738, 67.8675, 511.936 + 0.15, 25000.0, 32.0, 720.732, 55.1625, 510.708 + 0.2, 25000.0, 32.0, 728.466, 42.4914, 507.799 + 0.25, 25000.0, 32.0, 736.139, 29.9417, 503.435 + 0.3, 25000.0, 32.0, 743.948, 17.601, 497.842 + 0.35, 25000.0, 32.0, 752.091, 5.55696, 491.246 + 0.4, 25000.0, 32.0, 760.765, -6.10287, 483.874 + 0.45, 25000.0, 32.0, 770.358, -17.2464, 476.014 + 0.5, 25000.0, 32.0, 780.5, -27.9194, 467.705 + 0.55, 25000.0, 32.0, 791.013, -38.1234, 459.049 + 0.6, 25000.0, 32.0, 801.719, -47.8598, 450.149 + 0.0, 25000.0, 34.0, 786.511, 101.662, 542.501 + 0.05, 25000.0, 34.0, 796.496, 88.8823, 545.54 + 0.1, 25000.0, 34.0, 805.84, 75.9329, 546.486 + 0.15, 25000.0, 34.0, 814.747, 62.9113, 545.569 + 0.2, 25000.0, 34.0, 823.425, 49.9153, 543.022 + 0.25, 25000.0, 34.0, 832.078, 37.0424, 539.077 + 0.3, 25000.0, 34.0, 840.912, 24.3903, 533.966 + 0.35, 25000.0, 34.0, 850.134, 12.0566, 527.922 + 0.4, 25000.0, 34.0, 859.949, 0.138797, 521.176 + 0.45, 25000.0, 34.0, 870.752, -11.2147, 514.034 + 0.5, 25000.0, 34.0, 882.18, -22.0584, 506.509 + 0.55, 25000.0, 34.0, 894.059, -32.3964, 498.685 + 0.6, 25000.0, 34.0, 906.216, -42.2324, 490.649 + 0.0, 25000.0, 36.0, 877.181, 111.546, 579.325 + 0.05, 25000.0, 36.0, 888.226, 98.0318, 581.63 + 0.1, 25000.0, 36.0, 898.593, 84.4787, 582.235 + 0.15, 25000.0, 36.0, 908.502, 70.9677, 581.314 + 0.2, 25000.0, 36.0, 918.177, 57.5804, 579.04 + 0.25, 25000.0, 36.0, 927.838, 44.3982, 575.585 + 0.3, 25000.0, 36.0, 937.707, 31.5025, 571.123 + 0.35, 25000.0, 36.0, 948.005, 18.9747, 565.827 + 0.4, 25000.0, 36.0, 958.955, 6.8963, 559.87 + 0.45, 25000.0, 36.0, 970.979, -4.60768, 553.49 + 0.5, 25000.0, 36.0, 983.696, -15.5867, 546.666 + 0.55, 25000.0, 36.0, 996.925, -26.0465, 539.443 + 0.6, 25000.0, 36.0, 1010.49, -35.993, 531.866 + 0.0, 25000.0, 38.0, 969.53, 120.194, 613.149 + 0.05, 25000.0, 38.0, 981.199, 106.388, 616.51 + 0.1, 25000.0, 38.0, 992.265, 92.6207, 618.067 + 0.15, 25000.0, 38.0, 1002.95, 78.9547, 618.003 + 0.2, 25000.0, 38.0, 1013.48, 65.4532, 616.501 + 0.25, 25000.0, 38.0, 1024.07, 52.1791, 613.743 + 0.3, 25000.0, 38.0, 1034.96, 39.1952, 609.913 + 0.35, 25000.0, 38.0, 1046.35, 26.5645, 605.193 + 0.4, 25000.0, 38.0, 1058.48, 14.3499, 599.767 + 0.45, 25000.0, 38.0, 1071.8, 2.63034, 593.885 + 0.5, 25000.0, 38.0, 1085.85, -8.57937, 587.525 + 0.55, 25000.0, 38.0, 1100.42, -19.2484, 580.733 + 0.6, 25000.0, 38.0, 1115.3, -29.3459, 573.556 + 0.0, 25000.0, 40.0, 1059.5, 129.5, 650.6 + 0.05, 25000.0, 40.0, 1072.58, 115.631, 654.194 + 0.1, 25000.0, 40.0, 1084.9, 101.7, 656.0 + 0.15, 25000.0, 40.0, 1096.72, 87.7938, 656.206 + 0.2, 25000.0, 40.0, 1108.3, 74.0, 655.0 + 0.25, 25000.0, 40.0, 1119.91, 60.4062, 652.569 + 0.3, 25000.0, 40.0, 1131.8, 47.1, 649.1 + 0.35, 25000.0, 40.0, 1144.24, 34.1687, 644.781 + 0.4, 25000.0, 40.0, 1157.5, 21.7, 639.8 + 0.45, 25000.0, 40.0, 1172.09, 9.8, 634.4 + 0.5, 25000.0, 40.0, 1187.5, -1.5, 628.6 + 0.55, 25000.0, 40.0, 1203.49, -12.15, 622.475 + 0.6, 25000.0, 40.0, 1219.8, -22.1, 616.1 + 0.0, 25000.0, 42.0, 1150.16, 141.444, 687.298 + 0.05, 25000.0, 42.0, 1164.4, 126.296, 691.605 + 0.1, 25000.0, 42.0, 1177.8, 111.403, 694.044 + 0.15, 25000.0, 42.0, 1190.65, 96.8031, 694.817 + 0.2, 25000.0, 42.0, 1203.24, 82.5379, 694.129 + 0.25, 25000.0, 42.0, 1215.85, 68.647, 692.182 + 0.3, 25000.0, 42.0, 1228.76, 55.1704, 689.179 + 0.35, 25000.0, 42.0, 1242.26, 42.1481, 685.324 + 0.4, 25000.0, 42.0, 1256.63, 29.6202, 680.819 + 0.45, 25000.0, 42.0, 1272.44, 17.5969, 675.901 + 0.5, 25000.0, 42.0, 1289.15, 6.20761, 670.676 + 0.55, 25000.0, 42.0, 1306.49, -4.44771, 665.287 + 0.6, 25000.0, 42.0, 1324.21, -14.2694, 659.873 + 0.0, 25000.0, 44.0, 1241.99, 148.623, 724.296 + 0.05, 25000.0, 44.0, 1257.01, 134.33, 729.598 + 0.1, 25000.0, 44.0, 1271.24, 119.952, 732.803 + 0.15, 25000.0, 44.0, 1284.96, 105.594, 734.167 + 0.2, 25000.0, 44.0, 1298.47, 91.3597, 733.942 + 0.25, 25000.0, 44.0, 1312.05, 77.3531, 732.383 + 0.3, 25000.0, 44.0, 1325.99, 63.6785, 729.745 + 0.35, 25000.0, 44.0, 1340.58, 50.4398, 726.28 + 0.4, 25000.0, 44.0, 1356.11, 37.7412, 722.243 + 0.45, 25000.0, 44.0, 1373.15, 25.7151, 717.971 + 0.5, 25000.0, 44.0, 1391.15, 14.3805, 713.468 + 0.55, 25000.0, 44.0, 1409.85, 3.78491, 708.823 + 0.6, 25000.0, 44.0, 1428.97, -6.02424, 704.122 + 0.0, 25000.0, 46.0, 1332.47, 158.012, 763.729 + 0.05, 25000.0, 46.0, 1348.63, 143.651, 769.097 + 0.1, 25000.0, 46.0, 1363.92, 129.161, 772.405 + 0.15, 25000.0, 46.0, 1378.67, 114.661, 773.922 + 0.2, 25000.0, 46.0, 1393.19, 100.27, 773.916 + 0.25, 25000.0, 46.0, 1407.78, 86.1059, 772.656 + 0.3, 25000.0, 46.0, 1422.75, 72.2892, 770.411 + 0.35, 25000.0, 46.0, 1438.42, 58.9383, 767.449 + 0.4, 25000.0, 46.0, 1455.1, 46.1724, 764.04 + 0.45, 25000.0, 46.0, 1473.39, 34.1575, 760.622 + 0.5, 25000.0, 46.0, 1492.71, 22.8715, 756.952 + 0.55, 25000.0, 46.0, 1512.77, 12.3395, 752.957 + 0.6, 25000.0, 46.0, 1533.28, 2.58646, 748.565 + 0.0, 25000.0, 48.0, 1422.42, 169.693, 808.309 + 0.05, 25000.0, 48.0, 1440.2, 154.39, 811.554 + 0.1, 25000.0, 48.0, 1456.9, 139.191, 813.571 + 0.15, 25000.0, 48.0, 1472.87, 124.183, 814.491 + 0.2, 25000.0, 48.0, 1488.47, 109.454, 814.441 + 0.25, 25000.0, 48.0, 1504.07, 95.0925, 813.55 + 0.3, 25000.0, 48.0, 1520.03, 81.1861, 811.947 + 0.35, 25000.0, 48.0, 1536.71, 67.8228, 809.759 + 0.4, 25000.0, 48.0, 1554.49, 55.0908, 807.115 + 0.45, 25000.0, 48.0, 1574.06, 43.1086, 804.183 + 0.5, 25000.0, 48.0, 1594.75, 31.8725, 800.975 + 0.55, 25000.0, 48.0, 1616.21, 21.4095, 797.542 + 0.6, 25000.0, 48.0, 1638.1, 11.7463, 793.936 + 0.0, 25000.0, 50.0, 1513.4, 179.1, 842.5 + 0.05, 25000.0, 50.0, 1532.15, 163.875, 848.313 + 0.1, 25000.0, 50.0, 1549.8, 148.7, 852.3 + 0.15, 25000.0, 50.0, 1566.72, 133.675, 854.688 + 0.2, 25000.0, 50.0, 1583.3, 118.9, 855.7 + 0.25, 25000.0, 50.0, 1599.9, 104.475, 855.562 + 0.3, 25000.0, 50.0, 1616.9, 90.5, 854.5 + 0.35, 25000.0, 50.0, 1634.67, 77.075, 852.737 + 0.4, 25000.0, 50.0, 1653.6, 64.3, 850.5 + 0.45, 25000.0, 50.0, 1674.41, 52.3, 848.113 + 0.5, 25000.0, 50.0, 1696.4, 41.1, 845.5 + 0.55, 25000.0, 50.0, 1719.21, 30.75, 842.688 + 0.6, 25000.0, 50.0, 1742.5, 21.3, 839.7 diff --git a/aviary/models/engines/turboshaft_1120hp.deck b/aviary/models/engines/turboshaft_1120hp.deck deleted file mode 100644 index c83f813b49..0000000000 --- a/aviary/models/engines/turboshaft_1120hp.deck +++ /dev/null @@ -1,2095 +0,0 @@ -# GASP_TS-derived engine deck converted from MAPS_1120hp.eng -# t4max: 50.0 -# t4cruise: 46.67 -# t4climb: 48.33 -# t4flight_idle: 20.0 -# xsfc: 0.0 -# cexp: 0.0 -# sls_horsepower: 1120.0 -# freeturbine_rpm: 24539.0 -# propeller_rpm: 1210.0 -# gearbox_ratio: 0.049308 -# torque_limit: 4861.4 -# sls_corrected_airflow: 7.9568 - - Mach_Number, Altitude (ft), Throttle, Shaft_Power_Corrected (hp), Tailpipe_Thrust (lbf), Fuel_Flow (lb/h) - 0.0, 0.0, 20.0, 111.99999999999997, 37.699999999999996, 195.79999999999995 - 0.05, 0.0, 20.0, 111.76875, 28.06875, 195.18125000000003 - 0.1, 0.0, 20.0, 111.10000000000001, 18.400000000000013, 193.30000000000007 -0.15000000000000002, 0.0, 20.0, 110.00625, 8.756250000000017, 190.2187500000001 - 0.2, 0.0, 20.0, 108.49999999999996, -0.7999999999999651, 186.0000000000001 - 0.25, 0.0, 20.0, 106.5875, -10.212499999999979, 180.69999999999982 -0.30000000000000004, 0.0, 20.0, 104.30000000000004, -19.400000000000006, 174.40000000000003 -0.35000000000000003, 0.0, 20.0, 101.65000000000005, -28.281249999999993, 167.13750000000002 - 0.4, 0.0, 20.0, 98.70000000000009, -36.799999999999976, 159.10000000000002 - 0.45, 0.0, 20.0, 95.5000000000001, -44.89374999999997, 150.43750000000006 - 0.5, 0.0, 20.0, 92.10000000000011, -52.499999999999964, 141.30000000000007 - 0.55, 0.0, 20.0, 88.55000000000007, -59.55624999999999, 131.83750000000006 - 0.6000000000000001, 0.0, 20.0, 84.9, -66.00000000000001, 122.2000000000001 - 0.0, 0.0, 22.0, 179.34493481532428, 44.715006603080305, 230.17749238074498 - 0.05, 0.0, 22.0, 178.97463556375254, 34.46281901171256, 229.4503543632648 - 0.1, 0.0, 22.0, 177.90377016055834, 24.122161920604178, 227.28171706993288 -0.15000000000000002, 0.0, 22.0, 176.1523547815024, 13.778528167505797, 223.7555850075051 - 0.2, 0.0, 22.0, 173.74040560234536, 3.517410590168061, 218.95596268273675 - 0.25, 0.0, 22.0, 170.6727293589416, -6.578888984426928, 212.95234426112413 -0.30000000000000004, 0.0, 22.0, 167.01497054677077, -16.415304686222992, 205.8722652732005 -0.35000000000000003, 0.0, 22.0, 162.81315210172886, -25.86564486024505, 197.83780366084835 - 0.4, 0.0, 22.0, 158.13094543843175, -34.94098503426709, 188.93482635550112 - 0.45, 0.0, 22.0, 153.02760985181504, -43.61808394037586, 179.25825304120474 - 0.5, 0.0, 22.0, 147.5624046368148, -51.87370031065807, 168.90300340200494 - 0.55, 0.0, 22.0, 141.7945890883666, -59.68459287720051, 157.96399712194759 - 0.6000000000000001, 0.0, 22.0, 135.78342250140645, -67.02752037208982, 146.53615388507868 - 0.0, 0.0, 24.0, 246.47246740766226, 51.41370159878795, 262.3879720279042 - 0.05, 0.0, 24.0, 245.9635677818766, 40.55991858183634, 261.58413161207505 - 0.1, 0.0, 24.0, 244.4918850802795, 29.62515306839222, 259.1980483184538 -0.15000000000000002, 0.0, 24.0, 242.08492739075146, 18.695403730708698, 255.3172221470399 - 0.2, 0.0, 24.0, 238.77020280117262, 7.856669241038933, 250.0291530978337 - 0.25, 0.0, 24.0, 234.5551146794723, -2.8033949803702383, 243.40083374682519 -0.30000000000000004, 0.0, 24.0, 229.52748527338522, -13.203760505246626, 235.58128636604152 -0.35000000000000003, 0.0, 24.0, 223.74657605086406, -23.236204252724693, 226.71818731999855 - 0.4, 0.0, 24.0, 217.30547271921554, -32.89465476033619, 216.88256690719103 - 0.45, 0.0, 24.0, 210.28880492590724, -42.14750266101357, 206.1646169426193 - 0.5, 0.0, 24.0, 202.7812023184073, -50.963138587689265, 194.6545292412836 - 0.55, 0.0, 24.0, 194.86729454418366, -59.30995317329574, 182.44249561818435 - 0.6000000000000001, 0.0, 24.0, 186.63171125070429, -67.15633705076537, 169.61870788832204 - 0.0, 0.0, 26.0, 313.5275325923382, 57.87489329295546, 293.0597054846908 - 0.05, 0.0, 26.0, 312.8801822181247, 46.46873364610386, 292.2039816792531 - 0.1, 0.0, 26.0, 311.0081149197217, 35.00706325587816, 289.6335210320082 -0.15000000000000002, 0.0, 26.0, 307.9463226092493, 23.56739021015867, 285.4348167828225 - 0.2, 0.0, 26.0, 303.7297971988269, 12.227222596825728, 279.69436217156255 - 0.25, 0.0, 26.0, 298.369885320533, 1.0696685158999362, 272.4744011019638 -0.30000000000000004, 0.0, 26.0, 291.9725147266139, -9.844563981158725, 263.93417482228193 -0.35000000000000003, 0.0, 26.0, 284.6034239491347, -20.44769121508176, 254.21904414872373 - 0.4, 0.0, 26.0, 276.394527280783, -30.67783196927166, 243.432894281129 - 0.45, 0.0, 26.0, 267.4611950740913, -40.47162941146322, 231.68997932342936 - 0.5, 0.0, 26.0, 257.91879768159185, -49.7657267093912, 219.1045533795568 - 0.55, 0.0, 26.0, 247.88270545581688, -58.496767030790444, 205.7908705534433 - 0.6000000000000001, 0.0, 26.0, 237.46828874929847, -66.60139354339569, 191.86318494902068 - 0.0, 0.0, 28.0, 380.71132797414174, 64.16041898231998, 322.8970983543237 - 0.05, 0.0, 28.0, 379.9186096488317, 52.30183805955042, 322.01965114868847 - 0.1, 0.0, 28.0, 377.64643933043425, 40.37607100903362, 319.2486174136746 -0.15000000000000002, 0.0, 28.0, 373.9338063807854, 28.460116614294428, 314.6889819633879 - 0.2, 0.0, 28.0, 368.8197001617208, 16.63097365885769, 308.4457296119337 - 0.25, 0.0, 28.0, 362.3110671681346, 4.968791089446317, 300.6008979367994 -0.30000000000000004, 0.0, 28.0, 354.5430253626924, -6.458882800008785, 291.32831346195445 -0.35000000000000003, 0.0, 28.0, 345.6019017737347, -17.591036309924323, 280.7839598889099 - 0.4, 0.0, 28.0, 335.64101569913254, -28.327910710534162, 269.10340326256636 - 0.45, 0.0, 28.0, 324.79693836937355, -38.57943402961784, 256.42731404197605 - 0.5, 0.0, 28.0, 313.20624101494565, -48.25553429495496, 242.8963626861914 - 0.55, 0.0, 28.0, 301.0054948663367, -57.266139534325134, 228.65121965426457 - 0.6000000000000001, 0.0, 28.0, 288.3312711540347, -65.5211777755079, 213.83255540524783 - 0.0, 0.0, 30.0, 447.9999999999994, 70.39999999999996, 352.29999999999995 - 0.05, 0.0, 30.0, 447.07499999999993, 58.156250000000014, 351.38750000000016 - 0.1, 0.0, 30.0, 444.4000000000002, 45.80000000000004, 348.3999999999991 -0.15000000000000002, 0.0, 30.0, 440.0250000000003, 33.41875000000004, 343.462499999997 - 0.2, 0.0, 30.0, 434.00000000000045, 21.099999999999998, 336.6999999999938 - 0.25, 0.0, 30.0, 426.3374999999992, 8.93124999999989, 328.2124999999999 -0.30000000000000004, 0.0, 30.0, 417.2000000000005, -3.000000000000066, 318.1999999999976 -0.35000000000000003, 0.0, 30.0, 406.7000000000011, -14.612500000000082, 306.843749999996 - 0.4, 0.0, 30.0, 395.0000000000021, -25.800000000000086, 294.2999999999942 - 0.45, 0.0, 30.0, 382.25000000000415, -36.46250000000002, 280.7312499999927 - 0.5, 0.0, 30.0, 368.6000000000072, -46.499999999999886, 266.2999999999914 - 0.55, 0.0, 30.0, 354.20000000001204, -55.81249999999966, 251.16874999999047 - 0.6000000000000001, 0.0, 30.0, 339.200000000019, -64.29999999999933, 235.49999999999037 - 0.0, 0.0, 32.0, 515.2886720258577, 76.81166778501041, 381.67286088251075 - 0.05, 0.0, 32.0, 514.2969889095979, 64.17175480649937, 380.6081917031196 - 0.1, 0.0, 32.0, 511.20880156087435, 51.36419529128468, 377.410860040541 -0.15000000000000002, 0.0, 32.0, 506.1196461749198, 38.50000516699353, 372.1743632540723 - 0.2, 0.0, 32.0, 499.12505894696716, 25.6902003612531, 364.99219870301124 - 0.25, 0.0, 32.0, 490.30218458498234, 13.057650128833368, 355.90584758165846 -0.30000000000000004, 0.0, 32.0, 479.8017337459986, 0.6778104159339521, 345.1648557443028 -0.35000000000000003, 0.0, 32.0, 467.73967528825636, -11.357647126137639, 332.97481673093483 - 0.4, 0.0, 32.0, 454.29737931615955, -22.974500357933863, 319.50906867877245 - 0.45, 0.0, 32.0, 439.6398656225713, -34.0941647620423, 304.94901357572604 - 0.5, 0.0, 32.0, 423.9321540003543, -44.63805582105045, 289.47605340970676 - 0.55, 0.0, 32.0, 407.33926424237154, -54.527589017545914, 273.2715901686252 - 0.6000000000000001, 0.0, 32.0, 390.0262161414862, -63.68417983411625, 256.5170258403923 - 0.0, 0.0, 34.0, 582.4463994858675, 83.2392580152162, 410.7854182756185 - 0.05, 0.0, 34.0, 581.3736703078126, 70.21588372096733, 409.6149153061913 - 0.1, 0.0, 34.0, 577.8753880008202, 56.97970766741133, 406.2072289984825 -0.15000000000000002, 0.0, 34.0, 572.0849085983792, 43.65859351843262, 400.64578088779973 - 0.2, 0.0, 34.0, 564.1355881339807, 30.380404937915685, 393.0139925094505 - 0.25, 0.0, 34.0, 554.1551527874216, 17.289265017763103, 383.32537127586374 -0.30000000000000004, 0.0, 34.0, 542.293848153251, 4.4642591378030305, 371.873081090972 -0.35000000000000003, 0.0, 34.0, 528.6805332115401, -7.9794731109489465, 358.9035862556719 - 0.4, 0.0, 34.0, 513.5070939854921, -20.005971270152955, 344.57049299144296 - 0.45, 0.0, 34.0, 496.9496597375274, -31.559480098299986, 329.0506220396207 - 0.5, 0.0, 34.0, 479.18435973006837, -42.584244353881026, 312.52079414154025 - 0.55, 0.0, 34.0, 460.38732322553614, -53.02450879538708, 295.15783003853716 - 0.6000000000000001, 0.0, 34.0, 440.73467948635243, -62.82451818130906, 277.13855047194653 - 0.0, 0.0, 36.0, 649.488430709646, 89.64157895894078, 439.67986328687346 - 0.05, 0.0, 36.0, 648.2780538963945, 76.23955379240824, 438.4952269529693 - 0.1, 0.0, 36.0, 644.3793422599991, 62.60838332665023, 434.87128048266237 -0.15000000000000002, 0.0, 36.0, 637.9335427306597, 48.875852917293244, 428.9246023406449 - 0.2, 0.0, 36.0, 629.0819022385771, 35.169747919963825, 420.7717709916086 - 0.25, 0.0, 36.0, 617.9523563228726, 21.625379601849787, 410.4639971263444 -0.30000000000000004, 0.0, 36.0, 604.726086086946, 8.3479555838907, 398.31396253123074 -0.35000000000000003, 0.0, 36.0, 589.560319372145, -4.520370336391797, 384.614134209393 - 0.4, 0.0, 36.0, 572.6548515036563, -16.955125421553774, 369.47636720130316 - 0.45, 0.0, 36.0, 554.1988359357103, -28.90241666913154, 353.0576695380992 - 0.5, 0.0, 36.0, 534.381426122538, -40.3083510766614, 335.5150492509188 - 0.55, 0.0, 36.0, 513.3917755183699, -51.11903564167971, 317.0055143709001 - 0.6000000000000001, 0.0, 36.0, 491.4190375774369, -61.28057736172268, 297.68607292918057 - 0.0, 0.0, 38.0, 716.8807942074749, 96.12700282091733, 468.88927219679954 - 0.05, 0.0, 38.0, 715.4661656348787, 82.29095986042296, 467.60799095946135 - 0.1, 0.0, 38.0, 711.1753350700383, 68.26125513273314, 463.7448896591786 -0.15000000000000002, 0.0, 38.0, 704.1228053437417, 54.15237688948877, 457.426053046706 - 0.2, 0.0, 38.0, 694.4230792867777, 40.078813382330885, 448.77756587279873 - 0.25, 0.0, 38.0, 682.1553528750366, 26.166114867840438, 437.86935410480663 -0.30000000000000004, 0.0, 38.0, 667.5400495039844, 12.495583582841462, 424.99597884374793 -0.35000000000000003, 0.0, 38.0, 650.7337219815935, -0.8461622436320876, 410.40761270131986 - 0.4, 0.0, 38.0, 632.0071780461461, -13.74952033162338, 394.3073471129951 - 0.45, 0.0, 38.0, 611.6026617033502, -26.11063441390652, 376.9100438082958 - 0.5, 0.0, 38.0, 589.7624169589133, -37.82564822325564, 358.43056451674414 - 0.55, 0.0, 38.0, 566.7286878185436, -48.790705492444864, 339.0837709678625 - 0.6000000000000001, 0.0, 38.0, 542.7437182879488, -58.90194995424832, 319.0845248911728 - 0.0, 0.0, 40.0, 783.9999999999998, 102.60000000000011, 497.70000000000056 - 0.05, 0.0, 40.0, 782.5000000000005, 88.39375000000007, 496.3437500000003 - 0.1, 0.0, 40.0, 777.8000000000002, 74.00000000000006, 492.29999999999995 -0.15000000000000002, 0.0, 40.0, 770.0499999999998, 59.53125000000012, 485.6812499999994 - 0.2, 0.0, 40.0, 759.3999999999984, 45.10000000000034, 476.5999999999994 - 0.25, 0.0, 40.0, 745.9750000000032, 30.837499999999835, 465.0937500000021 -0.30000000000000004, 0.0, 40.0, 729.999999999999, 16.800000000000068, 451.4999999999963 -0.35000000000000003, 0.0, 40.0, 711.6499999999944, 3.037500000000169, 436.09999999999184 - 0.4, 0.0, 40.0, 691.1999999999863, -10.299999999999683, 419.0999999999855 - 0.45, 0.0, 40.0, 668.8999999999733, -23.087499999999462, 400.7249999999774 - 0.5, 0.0, 40.0, 644.9999999999544, -35.19999999999917, 381.1999999999671 - 0.55, 0.0, 40.0, 619.7499999999297, -46.5124999999988, 360.7499999999548 - 0.6000000000000001, 0.0, 40.0, 593.3999999998975, -56.89999999999833, 339.59999999994005 - 0.0, 0.0, 42.0, 851.1272051793511, 109.08811511460955, 526.5918291583557 - 0.05, 0.0, 42.0, 849.4391538723271, 94.6038822980871, 525.1331360293098 - 0.1, 0.0, 42.0, 844.3461466776646, 79.87047352380908, 520.8505106751662 -0.15000000000000002, 0.0, 42.0, 835.9796483083996, 65.01584840332417, 513.8676531932886 - 0.2, 0.0, 42.0, 824.4711234775679, 50.16796654818095, 504.30826368104005 - 0.25, 0.0, 42.0, 809.9050719466364, 35.46821607355167, 492.23287487951933 -0.30000000000000004, 0.0, 42.0, 792.553853283339, 21.004271080112563, 477.95468895488074 -0.35000000000000003, 0.0, 42.0, 772.6142351311705, 6.881255765902125, 461.7217850459937 - 0.4, 0.0, 42.0, 750.397493024372, -6.811792045996124, 443.7900649758768 - 0.45, 0.0, 42.0, 726.1862755244988, -19.98181293875968, 424.41347489651105 - 0.5, 0.0, 42.0, 700.2632311931053, -32.535747495566035, 403.8459609598779 - 0.55, 0.0, 42.0, 672.9110085917468, -44.38053629959277, 382.34146931795834 - 0.6000000000000001, 0.0, 42.0, 644.4122562819791, -55.423119934017315, 360.15394612273417 - 0.0, 0.0, 44.0, 918.4887696440404, 115.69752335234227, 555.5221263194699 - 0.05, 0.0, 44.0, 916.6882810978317, 100.85800419504623, 553.9788952747008 - 0.1, 0.0, 44.0, 911.1888518865055, 85.79585593766424, 549.5025255963754 -0.15000000000000002, 0.0, 44.0, 902.1434891486128, 70.61568392995419, 542.1969990027033 - 0.2, 0.0, 44.0, 889.7052000227047, 55.42209352167404, 532.1662972118945 - 0.25, 0.0, 44.0, 873.9864346022429, 40.30584058226862, 519.4073658135544 -0.30000000000000004, 0.0, 44.0, 855.2618711610495, 25.41307890243609, 504.3452949117091 -0.35000000000000003, 0.0, 44.0, 833.7227727411915, 10.896808916277863, 487.34516787186084 - 0.4, 0.0, 44.0, 809.7318351314167, -3.172753436964112, 468.58395049917436 - 0.45, 0.0, 44.0, 783.6088959338025, -16.704696094333208, 448.28563798889866 - 0.5, 0.0, 44.0, 755.6737927504271, -29.608106992872766, 426.6742255362824 - 0.55, 0.0, 44.0, 726.2463631833677, -41.79207406962617, 403.9737083365744 - 0.6000000000000001, 0.0, 44.0, 695.6464448347017, -53.16568526163671, 380.4080815850236 - 0.0, 0.0, 46.0, 985.5112303559608, 122.39976942353425, 584.4465697283215 - 0.05, 0.0, 46.0, 983.5646724343355, 107.26337061216333, 582.8342995402508 - 0.1, 0.0, 46.0, 977.666266877422, 91.83984569829309, 578.1277615913351 -0.15000000000000002, 0.0, 46.0, 967.9724557741258, 76.26352201071265, 570.457423390821 - 0.2, 0.0, 46.0, 954.639681213351, 60.66872687821103, 559.9537524479524 - 0.25, 0.0, 46.0, 937.7735163890865, 45.1981799429485, 546.6612083665597 -0.30000000000000004, 0.0, 46.0, 917.6830100750233, 29.96103159360235, 530.9682823721554 -0.35000000000000003, 0.0, 46.0, 894.5925822426052, 15.090666373945188, 513.2022453812107 - 0.4, 0.0, 46.0, 868.8616924925927, 0.6571014608605947, 493.591217924612 - 0.45, 0.0, 46.0, 840.8160405184137, -13.253804127045694, 472.3881081296407 - 0.5, 0.0, 46.0, 810.7813260134958, -26.55619137116792, 449.84582412357827 - 0.55, 0.0, 46.0, 779.0832486712653, -39.16420125290037, 426.2172740337063 - 0.6000000000000001, 0.0, 46.0, 746.0475081851504, -50.991974753637244, 401.7553659873061 - 0.0, 0.0, 48.0, 1052.872794820649, 129.2579386846625, 614.241318444193 - 0.05, 0.0, 48.0, 1050.8708449813194, 113.78223649168622, 612.542003210286 - 0.1, 0.0, 48.0, 1044.557010251727, 98.0541318015227, 607.5946146131755 -0.15000000000000002, 0.0, 48.0, 1034.1392989997025, 82.17721095987847, 599.5417014091418 - 0.2, 0.0, 48.0, 1019.825719593077, 66.25506031246, 588.5258123544663 - 0.25, 0.0, 48.0, 1001.7920264591361, 50.35810115604068, 574.5971273668869 -0.30000000000000004, 0.0, 48.0, 980.3429897872818, 34.68941498312371, 558.1753017182828 -0.35000000000000003, 0.0, 48.0, 955.7260677992863, 19.484221172600712, 539.631371837081 - 0.4, 0.0, 48.0, 928.2889508251654, 4.716527362077724, 519.1613741712276 - 0.45, 0.0, 48.0, 898.3542711678815, -9.574355875517519, 497.00509516379253 - 0.5, 0.0, 48.0, 866.2446611303952, -23.349117967257275, 473.40232125784524 - 0.55, 0.0, 48.0, 832.2827530156684, -36.56844834021384, 448.5928388964555 - 0.6000000000000001, 0.0, 48.0, 796.7911791266629, -49.19303642145945, 422.81643452269327 - 0.0, 0.0, 50.0, 1120.0000000000007, 136.29999999999967, 643.9999999999998 - 0.05, 0.0, 50.0, 1117.8062500000026, 120.5437500000002, 642.2812500000045 - 0.1, 0.0, 50.0, 1111.1000000000088, 104.50000000000072, 637.2000000000123 -0.15000000000000002, 0.0, 50.0, 1100.0687500000217, 88.2812500000014, 628.868750000023 - 0.2, 0.0, 50.0, 1084.900000000042, 72.00000000000213, 617.4000000000376 - 0.25, 0.0, 50.0, 1065.7312500000105, 55.74375000000072, 602.7624999999906 -0.30000000000000004, 0.0, 50.0, 1042.9000000000146, 39.69999999999945, 585.5000000000023 -0.35000000000000003, 0.0, 50.0, 1016.6500000000314, 24.081249999999166, 566.0937500000043 - 0.4, 0.0, 50.0, 987.4000000000532, 8.899999999998938, 544.7000000000081 - 0.45, 0.0, 50.0, 955.5250000000808, -5.781250000001215, 521.556250000014 - 0.5, 0.0, 50.0, 921.4000000001128, -19.90000000000128, 496.9000000000223 - 0.55, 0.0, 50.0, 885.4000000001491, -33.393750000001276, 470.9687500000334 - 0.6000000000000001, 0.0, 50.0, 847.90000000019, -46.20000000000118, 444.00000000004803 - 0.0, 1500.0, 20.0, 95.69999999999999, 35.599999999999994, 187.39999999999998 - 0.05, 1500.0, 20.0, 95.46735389610389, 26.11347402597402, 186.78134740259745 - 0.1, 1500.0, 20.0, 94.89999999999996, 16.599999999999987, 184.90000000000003 -0.15000000000000002, 1500.0, 20.0, 93.9889691558441, 7.129788961038928, 181.8379788961039 - 0.2, 1500.0, 20.0, 92.7252922077921, -2.226948051948111, 177.67730519480511 - 0.25, 1500.0, 20.0, 91.09999999999984, -11.400000000000091, 172.49999999999983 -0.30000000000000004, 1500.0, 20.0, 89.07994227994244, -20.308874458874495, 166.38744588744626 -0.35000000000000003, 1500.0, 20.0, 86.84309523809516, -28.962023809523792, 159.4190476190475 - 0.4, 1500.0, 20.0, 84.39999999999985, -37.299999999999955, 151.69999999999976 - 0.45, 1500.0, 20.0, 81.6979365079362, -45.23865079365073, 143.35396825396796 - 0.5, 1500.0, 20.0, 78.69999999999953, -52.699999999999896, 134.4999999999996 - 0.55, 1500.0, 20.0, 75.36928571428501, -59.606071428571305, 125.25714285714238 - 0.6000000000000001, 1500.0, 20.0, 71.66888888888792, -65.87888888888874, 115.74444444444387 - 0.0, 1500.0, 22.0, 153.2438416234512, 41.52208788145173, 216.5618934644455 - 0.05, 1500.0, 22.0, 152.96466490873289, 31.47381318631449, 215.96515839901164 - 0.1, 1500.0, 22.0, 152.0404352180063, 21.41035248680888, 213.92209690968318 -0.15000000000000002, 1500.0, 22.0, 150.51087645340473, 11.389671207696404, 210.5393886604932 - 0.2, 1500.0, 22.0, 148.4157125170614, 1.4697347737385635, 205.92371331547457 - 0.25, 1500.0, 22.0, 145.79466731110938, -8.29149139030314, 200.18175053866054 -0.30000000000000004, 1500.0, 22.0, 142.6931254712557, -17.842115586578803, 193.4295590063016 -0.35000000000000003, 1500.0, 22.0, 139.09868832660743, -27.074855305820954, 185.6926396128084 - 0.4, 1500.0, 22.0, 135.0715898925971, -35.93392693090799, 177.0961120378473 - 0.45, 1500.0, 22.0, 130.70916450838988, -44.38573198565869, 167.81275046014844 - 0.5, 1500.0, 22.0, 126.09947143221805, -52.39112570865675, 158.0034154336762 - 0.55, 1500.0, 22.0, 121.33056992231371, -59.910963338485914, 147.828967512395 - 0.6000000000000001, 1500.0, 22.0, 116.49051923690911, -66.90610011372983, 137.45026725026906 - 0.0, 1500.0, 24.0, 210.60192081172568, 47.33909802179344, 244.56972189419133 - 0.05, 1500.0, 24.0, 210.2121588920601, 36.7927468214943, 243.9015375306978 - 0.1, 1500.0, 24.0, 208.94623563602548, 26.205176243404456, 241.67584164383305 -0.15000000000000002, 1500.0, 24.0, 206.8527346242065, 15.643287880258438, 237.992230792426 - 0.2, 1500.0, 24.0, 203.98023943718792, 5.173983324790743, 232.95030153530564 - 0.25, 1500.0, 24.0, 200.37733365555442, -5.135835830264115, 226.64965043130076 -0.30000000000000004, 1500.0, 24.0, 196.09494595042113, -15.224612614555486, 219.18423918109764 -0.35000000000000003, 1500.0, 24.0, 191.15250584988783, -24.97991195537535, 210.6872381427101 - 0.4, 1500.0, 24.0, 185.6297769192752, -34.343161762701875, 201.29275907280189 - 0.45, 1500.0, 24.0, 179.64205523431372, -43.28100935686897, 191.14681104341287 - 0.5, 1500.0, 24.0, 173.29575374313148, -51.75379720562152, 180.39242879773892 - 0.55, 1500.0, 24.0, 166.6972853938567, -59.72186777670451, 169.1726470789764 - 0.6000000000000001, 1500.0, 24.0, 159.95306313461748, -67.14556353786284, 157.6305006303215 - 0.0, 1500.0, 26.0, 267.8980791882746, 53.0850642214093, 271.6766035917145 - 0.05, 1500.0, 26.0, 267.36655743400786, 42.0812495128675, 270.89846083950147 - 0.1, 1500.0, 26.0, 265.7618184450414, 30.99482375659559, 268.4785379231415 -0.15000000000000002, 1500.0, 26.0, 263.12529904882524, 19.91135547494629, 264.4996935291776 - 0.2, 1500.0, 26.0, 259.4984360728094, 8.916413190272365, 259.0447863441533 - 0.25, 1500.0, 26.0, 254.92266634444417, -1.90443457507347, 252.19667505461177 -0.30000000000000004, 1500.0, 26.0, 249.42576646452184, -12.461246654437662, 244.01046019906377 -0.35000000000000003, 1500.0, 26.0, 243.14396730510208, -22.696136190114515, 234.7739216281122 - 0.4, 1500.0, 26.0, 236.16216899965386, -32.54543312904181, 224.6213500888324 - 0.45, 1500.0, 26.0, 228.55837164254936, -41.95035724318645, 213.64022655533222 - 0.5, 1500.0, 26.0, 220.41230033793477, -50.85090584825802, 201.92973444496204 - 0.55, 1500.0, 26.0, 211.80368018995608, -59.18707625996607, 189.58905717507258 - 0.6000000000000001, 1500.0, 26.0, 202.81223630275946, -66.89886579402015, 176.71737816301447 - 0.0, 1500.0, 28.0, 325.3042329207624, 58.793241618722455, 298.1304743952346 - 0.05, 1500.0, 28.0, 324.6405583224275, 47.33910046350418, 297.2779931248496 - 0.1, 1500.0, 28.0, 322.6792651056029, 35.77686272355022, 294.66442698763916 -0.15000000000000002, 1500.0, 28.0, 319.47225758443136, 24.20577041932904, 290.3772231235876 - 0.2, 1500.0, 28.0, 315.07144007305607, 12.725065571309074, 284.50382867267905 - 0.25, 1500.0, 28.0, 309.52871688561976, 1.433990199958765, 277.1316907748978 -0.30000000000000004, 1500.0, 28.0, 302.8831798877539, -9.554438265057815, 268.3163228988775 -0.35000000000000003, 1500.0, 28.0, 295.27450392441716, -20.239650095825663, 258.38889714217936 - 0.4, 1500.0, 28.0, 286.79878048156985, -30.556996214909592, 247.47209388435974 - 0.45, 1500.0, 28.0, 277.5486703695332, -40.42665879691902, 235.61346636901987 - 0.5, 1500.0, 28.0, 267.6176920675382, -49.77261220345216, 222.87934962375036 - 0.55, 1500.0, 28.0, 257.09936405481557, -58.51883079610729, 209.33607867614177 - 0.6000000000000001, 1500.0, 28.0, 246.0872048105959, -66.58928893648272, 195.04998855378452 - 0.0, 1500.0, 30.0, 382.79999999999995, 64.50000000000003, 324.20000000000005 - 0.05, 1500.0, 30.0, 382.0229545454542, 52.610860389610394, 323.30584415584457 - 0.1, 1500.0, 30.0, 379.69999999999925, 40.59999999999998, 320.50000000000097 -0.15000000000000002, 1500.0, 30.0, 375.9055681818176, 28.573709415584393, 315.89123376623564 - 0.2, 1500.0, 30.0, 370.7140909090905, 16.63827922077919, 309.58831168831523 - 0.25, 1500.0, 30.0, 364.20000000000044, 4.89999999999998, 301.7000000000057 -0.30000000000000004, 1500.0, 30.0, 356.43585858585584, -6.516450216450109, 292.3134199134164 -0.35000000000000003, 1500.0, 30.0, 347.49749999999807, -17.637857142857197, 281.7078571428554 - 0.4, 1500.0, 30.0, 337.49999999999545, -28.40000000000016, 269.9999999999961 - 0.45, 1500.0, 30.0, 326.588333333325, -38.7147619047623, 257.241428571421 - 0.5, 1500.0, 30.0, 314.8999999999869, -48.500000000000774, 243.49999999998724 - 0.55, 1500.0, 30.0, 302.5724999999812, -57.67357142857276, 228.8435714285516 - 0.6000000000000001, 1500.0, 30.0, 289.7433333333077, -66.15333333333552, 213.339999999971 - 0.0, 1500.0, 32.0, 440.2957670792371, 70.26199927258685, 350.24381298569006 - 0.05, 1500.0, 32.0, 439.4291017813626, 57.98528467413509, 349.3096863568782 - 0.1, 1500.0, 32.0, 436.77597578570686, 45.563403576767975, 346.30986039328604 -0.15000000000000002, 1500.0, 32.0, 432.41989454097376, 33.106013094493406, 341.3714520170025 - 0.2, 1500.0, 32.0, 426.44436349586783, 20.722770341319325, 334.62157815011636 - 0.25, 1500.0, 32.0, 418.9328880990927, 8.523332431253634, 326.18735571471666 -0.30000000000000004, 1500.0, 32.0, 409.9618555581633, -3.3695570535124237, 316.1830425377271 -0.35000000000000003, 1500.0, 32.0, 399.6536105968732, -14.938588147872242, 304.8296748100429 - 0.4, 1500.0, 32.0, 388.14597862711656, -26.111137527486573, 292.28122993131745 - 0.45, 1500.0, 32.0, 375.6013420019245, -36.803879231561936, 278.6726976307221 - 0.5, 1500.0, 32.0, 362.1759438390445, -46.936162958418656, 264.1438145550484 - 0.55, 1500.0, 32.0, 348.02602725622404, -56.42733840637697, 248.83431735108738 - 0.6000000000000001, 1500.0, 32.0, 333.3078353712103, -65.19675527375725, 232.88394266563049 - 0.0, 1500.0, 34.0, 497.68482149635736, 76.02397709878858, 376.17210263078516 - 0.05, 1500.0, 34.0, 496.7117738806082, 63.38854612178574, 375.17482742385357 - 0.1, 1500.0, 34.0, 493.7183270609965, 50.57929338628754, 371.9709072725672 -0.15000000000000002, 1500.0, 34.0, 488.79607555680525, 37.71029767966195, 366.701447094531 - 0.2, 1500.0, 34.0, 482.0366138873173, 24.89563778927699, 359.5075518073497 - 0.25, 1500.0, 34.0, 473.5315365718155, 12.249392502500637, 350.53032632862823 -0.30000000000000004, 1500.0, 34.0, 463.3584257512548, -0.10817096208226076, 339.9073449542679 -0.35000000000000003, 1500.0, 34.0, 451.69979380403777, -12.097672397018105, 327.78768960915704 - 0.4, 1500.0, 34.0, 438.7107787517037, -23.649459624436382, 314.37326911004646 - 0.45, 1500.0, 34.0, 424.5562938011786, -34.7127426819555, 299.90827144497115 - 0.5, 1500.0, 34.0, 409.3988083630447, -45.23201605332128, 284.62631480914513 - 0.55, 1500.0, 34.0, 393.40079184788453, -55.15177422227958, 268.761017397782 - 0.6000000000000001, 1500.0, 34.0, 376.72471366628054, -64.4165116725762, 252.54599740609578 - 0.0, 1500.0, 36.0, 554.9724302152221, 81.7704369179696, 401.9803823367566 - 0.05, 1500.0, 36.0, 553.8714049721384, 68.78725919542927, 400.8875966725919 - 0.1, 1500.0, 36.0, 550.5199555825, 55.60937948102862, 397.47537104692776 -0.15000000000000002, 1500.0, 36.0, 545.0213836324202, 42.353626674955585, 391.8886923777993 - 0.2, 1500.0, 36.0, 537.4789907080112, 29.13682967739815, 384.27254758324057 - 0.25, 1500.0, 36.0, 527.9960783953869, 16.075817388544312, 374.7719235812864 -0.30000000000000004, 1500.0, 36.0, 516.6594799051213, 3.2878047832859747, 363.53295855256994 -0.35000000000000003, 1500.0, 36.0, 503.6835470489076, -9.09289900765284, 350.6613355838367 - 0.4, 1500.0, 36.0, 489.2336717483017, -21.01117156866688, 336.3923227848512 - 0.45, 1500.0, 36.0, 473.4755427491625, -32.46545377697055, 321.04527575546877 - 0.5, 1500.0, 36.0, 456.57477459128125, -43.440795686572585, 304.91852822302167 - 0.55, 1500.0, 36.0, 438.6969818144485, -53.922247351481765, 288.31041391484166 - 0.6000000000000001, 1500.0, 36.0, 420.0077789584553, -63.89485882570683, 271.5192665582616 - 0.0, 1500.0, 38.0, 612.504225866503, 87.54692521778345, 427.6691450896797 - 0.05, 1500.0, 38.0, 611.3397559654801, 74.17746471232472, 426.4830430612535 - 0.1, 1500.0, 38.0, 607.6732685615771, 60.66053375588027, 422.90806848984545 -0.15000000000000002, 1500.0, 38.0, 601.6235674495817, 47.08636842797866, 417.0687761720428 - 0.2, 1500.0, 38.0, 593.309456424282, 33.545204808148355, 409.0897209044322 - 0.25, 1500.0, 38.0, 582.8497392804663, 20.127278975917854, 399.0954574836011 -0.30000000000000004, 1500.0, 38.0, 570.3501145283909, 6.910553264954771, 387.19033657352054 -0.35000000000000003, 1500.0, 38.0, 556.011577289683, -5.911859538156467, 373.63256610294553 - 0.4, 1500.0, 38.0, 540.0208842063372, -18.2637835743366, 358.63064065503335 - 0.45, 1500.0, 38.0, 522.5815101697791, -30.122453444461193, 342.4003208476877 - 0.5, 1500.0, 38.0, 503.8927505090825, -41.451751134417506, 325.1555507901243 - 0.55, 1500.0, 38.0, 484.15390055332074, -52.215558630092744, 307.1102745915592 - 0.6000000000000001, 1500.0, 38.0, 463.5642556315679, -62.377757917374254, 288.4784363612077 - 0.0, 1500.0, 40.0, 669.9000000000007, 93.30000000000013, 453.30000000000035 - 0.05, 1500.0, 40.0, 668.5426948051972, 79.65556818181814, 452.0586688311697 - 0.1, 1500.0, 40.0, 664.5000000000034, 65.79999999999976, 448.30000000000007 -0.15000000000000002, 1500.0, 40.0, 657.8859577922105, 51.84664772727225, 442.15199675324465 - 0.2, 1500.0, 40.0, 648.8146103896111, 37.90886363636284, 433.74266233765655 - 0.25, 1500.0, 40.0, 637.3999999999966, 24.099999999998772, 423.1999999999889 -0.30000000000000004, 1500.0, 40.0, 623.7360028860138, 10.532323232322236, 410.61601731600314 -0.35000000000000003, 1500.0, 40.0, 608.0689285714402, -2.6649999999998353, 396.38523809523775 - 0.4, 1500.0, 40.0, 590.6000000000222, -15.399999999999686, 380.6999999999973 - 0.45, 1500.0, 40.0, 571.5407142857515, -27.603333333332817, 363.68984126983406 - 0.5, 1500.0, 40.0, 551.1000000000569, -39.19999999999921, 345.4999999999857 - 0.55, 1500.0, 40.0, 529.4867857143676, -50.11499999999886, 326.27571428568984 - 0.6000000000000001, 1500.0, 40.0, 506.91000000011303, -60.27333333333175, 306.16222222218414 - 0.0, 1500.0, 42.0, 727.2161559655029, 99.1736304531933, 479.05691737332893 - 0.05, 1500.0, 42.0, 725.8148474233182, 85.15831122498543, 477.7369845980461 - 0.1, 1500.0, 42.0, 721.4414113225844, 70.95125346831578, 473.73389043469604 -0.15000000000000002, 1500.0, 42.0, 714.2407836242762, 56.65356377339392, 467.2058137226046 - 0.2, 1500.0, 42.0, 704.3579002893679, 42.366348730429614, 458.3109333010971 - 0.25, 1500.0, 42.0, 691.9376972788335, 28.190714929632534, 447.20742800949927 -0.30000000000000004, 1500.0, 42.0, 677.1152284033615, 14.214098433984896, 434.03193158096065 -0.35000000000000003, 1500.0, 42.0, 660.083085710312, 0.6555675657724076, 419.09781733764476 - 0.4, 1500.0, 42.0, 641.0804085089301, -12.409563627547975, 402.6147632185942 - 0.45, 1500.0, 42.0, 620.3971319168153, -24.97447622728636, 384.76640711976216 - 0.5, 1500.0, 42.0, 598.3104920994771, -37.01522753256117, 365.74289694787547 - 0.55, 1500.0, 42.0, 575.0977252224255, -48.50787484249083, 345.73438060966015 - 0.6000000000000001, 1500.0, 42.0, 551.0360674511705, -59.42847545619369, 324.93100601184295 - 0.0, 1500.0, 44.0, 784.8022436078677, 105.06776734385357, 504.79392268540096 - 0.05, 1500.0, 44.0, 783.2609067931114, 90.71099082783063, 503.4480121826384 - 0.1, 1500.0, 44.0, 778.5360119915617, 76.15490483433547, 499.28079433829834 -0.15000000000000002, 1500.0, 44.0, 770.7727021390465, 61.51042541999961, 492.4549729105506 - 0.2, 1500.0, 44.0, 760.116120171392, 46.88846864145455, 483.1332516575647 - 0.25, 1500.0, 44.0, 746.7114090244262, 32.39995055533181, 471.47833433751026 -0.30000000000000004, 1500.0, 44.0, 730.6822136116793, 18.16539020741929, 457.6284593525641 -0.35000000000000003, 1500.0, 44.0, 712.3140938330312, 4.215546043658498, 441.9166612608471 - 0.4, 1500.0, 44.0, 691.846894267475, -9.328664787000175, 424.58181996419773 - 0.45, 1500.0, 44.0, 669.53297865803, -22.305425311907342, 405.8489763057251 - 0.5, 1500.0, 44.0, 645.6215809567065, -34.56314351433851, 385.9466308932199 - 0.55, 1500.0, 44.0, 620.3619351155155, -45.9502273775692, 365.10328433447324 - 0.6000000000000001, 1500.0, 44.0, 594.0032750864681, -56.31508488487492, 343.54743723727574 - 0.0, 1500.0, 46.0, 841.9977563921332, 110.92576028015617, 530.4060773145992 - 0.05, 1500.0, 46.0, 840.3651899471043, 96.33980022015739, 528.9575822271147 - 0.1, 1500.0, 46.0, 835.3191067723676, 81.49374155360279, 524.5807968016229 -0.15000000000000002, 1500.0, 46.0, 827.0128784020941, 66.51230923469338, 517.4404649922614 - 0.2, 1500.0, 46.0, 815.5998763704561, 51.5202282176303, 507.70133075316886 - 0.25, 1500.0, 46.0, 801.2334722116252, 36.64222345661457, 495.52813803848346 -0.30000000000000004, 1500.0, 46.0, 784.0445072698627, 22.004723716562488, 481.0575785626849 -0.35000000000000003, 1500.0, 46.0, 764.3310756078923, 7.728459068115913, 464.6569202496698 - 0.4, 1500.0, 46.0, 742.353105732526, -6.090752340970528, 446.5565888958911 - 0.45, 1500.0, 46.0, 718.3901428264527, -19.377107932967828, 426.9518866921911 - 0.5, 1500.0, 46.0, 692.7168279033891, -32.0498012376408, 406.046896730816 - 0.55, 1500.0, 46.0, 665.6078019770513, -44.02802578475425, 384.0457021040122 - 0.6000000000000001, 1500.0, 46.0, 637.3377060611564, -55.23097510407297, 361.1523859040256 - 0.0, 1500.0, 48.0, 899.583844034498, 116.90334260817346, 556.1478180207478 - 0.05, 1500.0, 48.0, 897.8728720298483, 101.97344661670267, 554.6579210496367 - 0.1, 1500.0, 48.0, 892.4664810008874, 86.81940573428257, 550.0875580392459 -0.15000000000000002, 1500.0, 48.0, 883.552632610575, 71.54614385962161, 542.6175009870261 - 0.2, 1500.0, 48.0, 871.3192885218712, 56.258584891428164, 532.4285218904272 - 0.25, 1500.0, 48.0, 855.954410397735, 41.06165272841078, 519.7013927468995 -0.30000000000000004, 1500.0, 48.0, 837.6368116980575, 26.050721749270195, 504.5913173370263 -0.35000000000000003, 1500.0, 48.0, 816.5992359995436, 11.408949105185352, 487.4607655709342 - 0.4, 1500.0, 48.0, 793.1148560969625, -2.764252582428869, 468.55905291338354 - 0.45, 1500.0, 48.0, 767.5020940031645, -16.40620133865105, 448.1111949658707 - 0.5, 1500.0, 48.0, 740.0680594264886, -29.44503252693581, 426.34828229570564 - 0.55, 1500.0, 48.0, 711.1198620752743, -41.80888151073776, 403.50140547019913 - 0.6000000000000001, 1500.0, 48.0, 680.9646116578604, -53.42588365351152, 379.80165505666145 - 0.0, 1500.0, 50.0, 956.9000000000019, 122.89999999999998, 581.7999999999995 - 0.05, 1500.0, 50.0, 955.028685064947, 107.74214285714356, 580.2426298701308 - 0.1, 1500.0, 50.0, 949.3000000000266, 92.30000000000179, 575.5000000000007 -0.15000000000000002, 1500.0, 50.0, 939.876972402643, 76.69678571428899, 567.7460551948027 - 0.2, 1500.0, 50.0, 926.9226298701986, 61.055714285719404, 557.15474025973 - 0.25, 1500.0, 50.0, 910.6000000000953, 45.50000000000747, 543.8999999999779 -0.30000000000000004, 1500.0, 50.0, 891.0361471861409, 30.14603174603084, 528.11659451662 -0.35000000000000003, 1500.0, 50.0, 868.6403571428258, 15.18404761904751, 510.27261904761957 - 0.4, 1500.0, 50.0, 843.699999999931, 0.7000000000000473, 490.5999999999976 - 0.45, 1500.0, 50.0, 816.493095237967, -13.276031746031432, 469.25158730157807 - 0.5, 1500.0, 50.0, 787.2999999997882, -26.6999999999993, 446.3999999999796 - 0.55, 1500.0, 50.0, 756.4010714282468, -39.527857142855986, 422.2178571428199 - 0.6000000000000001, 1500.0, 50.0, 724.0766666661958, -51.71555555555385, 396.87777777771726 - 0.0, 3000.0, 20.0, 101.79999999999998, 36.199999999999996, 192.69999999999996 - 0.05, 3000.0, 20.0, 101.53766233766234, 26.668214285714278, 192.09219155844156 - 0.1, 3000.0, 20.0, 100.9, 17.099999999999984, 190.2 -0.15000000000000002, 3000.0, 20.0, 99.89350649350644, 7.567678571428529, 187.10171266233758 - 0.2, 3000.0, 20.0, 98.52467532467521, -1.8564285714286357, 182.8756168831167 - 0.25, 3000.0, 20.0, 96.79999999999983, -11.100000000000101, 177.59999999999968 -0.30000000000000004, 3000.0, 20.0, 94.71796536796592, -20.080952380952443, 171.3508658008664 -0.35000000000000003, 3000.0, 20.0, 92.34202380952372, -28.80142857142855, 164.2060714285714 - 0.4, 3000.0, 20.0, 89.69999999999985, -37.199999999999946, 156.29999999999995 - 0.45, 3000.0, 20.0, 86.81198412698387, -45.19238095238085, 147.80928571428558 - 0.5, 3000.0, 20.0, 83.69999999999959, -52.69999999999985, 138.8999999999998 - 0.55, 3000.0, 20.0, 80.38607142857084, -59.644285714285516, 129.73821428571392 - 0.6000000000000001, 3000.0, 20.0, 76.8922222222214, -65.94666666666639, 120.48999999999944 - 0.0, 3000.0, 22.0, 162.9285137622159, 42.583585387540374, 223.31414648342877 - 0.05, 3000.0, 22.0, 162.6454730837386, 32.41264747887439, 222.59163039649508 - 0.1, 3000.0, 22.0, 161.65379237230414, 22.21099951723447, 220.49040722666155 -0.15000000000000002, 3000.0, 22.0, 160.0089979102913, 12.051292487619424, 217.07809270386517 - 0.2, 3000.0, 22.0, 157.76661598007905, 2.006177375028133, 212.42230255804304 - 0.25, 3000.0, 22.0, 154.9821728640463, -7.851694835540597, 206.59065251913228 -0.30000000000000004, 3000.0, 22.0, 151.72762050937632, -17.442299207731242, 199.63710922228216 -0.35000000000000003, 3000.0, 22.0, 147.92647318282798, -26.74643828002576, 191.72280267100155 - 0.4, 3000.0, 22.0, 143.63607725834478, -35.70807532954679, 182.96238404938512 - 0.45, 3000.0, 22.0, 138.9701491850412, -44.261362028556356, 173.46681685149156 - 0.5, 3000.0, 22.0, 134.02831289323896, -52.34290295053166, 163.347986493889 - 0.55, 3000.0, 22.0, 128.91019231326007, -59.88930266894989, 152.7177783931454 - 0.6000000000000001, 3000.0, 22.0, 123.71541137542634, -66.83716575728818, 141.68807796582885 - 0.0, 3000.0, 24.0, 223.92425688110797, 48.74586480186032, 252.5758484036831 - 0.05, 3000.0, 24.0, 223.50328869558518, 38.04620683027163, 251.78890001382382 - 0.1, 3000.0, 24.0, 222.14689618615245, 27.305499758617348, 249.49397877529998 -0.15000000000000002, 3000.0, 24.0, 219.91267072457273, 16.595839634580862, 245.75835703349102 - 0.2, 3000.0, 24.0, 216.8582036826093, 5.98932250584557, 240.64930713377703 - 0.25, 3000.0, 24.0, 213.04108643202508, -4.441955579905142, 234.23410142153762 -0.30000000000000004, 3000.0, 24.0, 208.52956081775062, -14.62351752573158, 226.5568100064719 -0.35000000000000003, 3000.0, 24.0, 203.28861905199653, -24.500638408017306, 217.85064608046102 - 0.4, 3000.0, 24.0, 197.39803862917333, -34.006253989043856, 208.24191310559584 - 0.45, 3000.0, 24.0, 190.99281961880087, -43.06983592020175, 197.83204586214396 - 0.5, 3000.0, 24.0, 184.19415644662254, -51.62172188060422, 186.72869630082957 - 0.55, 3000.0, 24.0, 177.12324353838156, -59.59224954936447, 175.0395163723769 - 0.6000000000000001, 3000.0, 24.0, 169.90127531982105, -66.91175660559564, 162.8721580275104 - 0.0, 3000.0, 26.0, 284.8757431188921, 54.7863515224101, 280.87047708222315 - 0.05, 3000.0, 26.0, 284.27655445387416, 43.61903984482912, 280.03829112121684 - 0.1, 3000.0, 26.0, 282.5531038138488, 32.394500241383064, 277.5523467106077 -0.15000000000000002, 3000.0, 26.0, 279.7475645512412, 21.184344433836575, 273.4866699787174 - 0.2, 3000.0, 26.0, 275.902110018477, 10.060184143954276, 267.91528705386696 - 0.25, 3000.0, 26.0, 271.05891356798116, -0.9063689064991916, 260.912224064378 -0.30000000000000004, 3000.0, 26.0, 265.252517711265, -11.646695907976186, 252.52222746379041 -0.35000000000000003, 3000.0, 26.0, 258.5677307107037, -22.06898844361505, 243.0290405353729 - 0.4, 3000.0, 26.0, 251.10196137082968, -32.090394983767595, 232.58025013711563 - 0.45, 3000.0, 26.0, 242.9762805394057, -41.62804943248975, 221.2912315264184 - 0.5, 3000.0, 26.0, 234.3058435533879, -50.59908933541119, 209.28541286083018 - 0.55, 3000.0, 26.0, 225.20580574973212, -58.920652238161615, 196.6862222978997 - 0.6000000000000001, 3000.0, 26.0, 215.7913224653946, -66.50987568637072, 183.61708799517584 - 0.0, 3000.0, 28.0, 345.90024554029276, 60.832003683382425, 308.6239599848667 - 0.05, 3000.0, 28.0, 345.1973491267419, 49.18439627328946, 307.7191382382659 - 0.1, 3000.0, 28.0, 343.1192739271945, 37.47646686629199, 305.02511874875546 -0.15000000000000002, 3000.0, 28.0, 339.71759499321337, 25.779144556758258, 300.62572389546517 - 0.2, 3000.0, 28.0, 335.04388737636083, 14.163358439056505, 294.6047760575245 - 0.25, 3000.0, 28.0, 329.14972612819946, 2.700037607554953, 287.04609761406374 -0.30000000000000004, 3000.0, 28.0, 322.07286896159536, -8.54636902207996, 278.0043577983992 -0.35000000000000003, 3000.0, 28.0, 313.9552469774767, -19.458199157460694, 267.776746436243 - 0.4, 3000.0, 28.0, 304.9089832078583, -29.949199009439116, 256.5066590664273 - 0.45, 3000.0, 28.0, 295.05396331622086, -39.9410934336244, 244.2932679948188 - 0.5, 3000.0, 28.0, 284.5081323081797, -49.353612624436316, 231.24680133552596 - 0.55, 3000.0, 28.0, 273.3894351893498, -58.106486776294595, 217.47748720265747 - 0.6000000000000001, 3000.0, 28.0, 261.8158169653465, -66.11944608361905, 203.09555371032198 - 0.0, 3000.0, 30.0, 406.9999999999997, 66.89999999999996, 336.0999999999996 - 0.05, 3000.0, 30.0, 406.2312175324673, 54.78311688311691, 335.11060064935043 - 0.1, 3000.0, 30.0, 403.8000000000001, 42.60000000000015, 332.20000000000033 -0.15000000000000002, 3000.0, 30.0, 399.7831737012998, 30.425324675324976, 327.4640990259751 - 0.2, 3000.0, 30.0, 394.25756493506793, 18.333766233766752, 320.998798701301 - 0.25, 3000.0, 30.0, 387.3000000000057, 6.400000000000796, 312.9000000000038 -0.30000000000000004, 3000.0, 30.0, 378.9764069263993, -5.307287157286828, 303.2392496392509 -0.35000000000000003, 3000.0, 30.0, 369.4339285714241, -16.66797619047607, 292.29523809523397 - 0.4, 3000.0, 30.0, 358.7999999999914, -27.59999999999973, 280.19999999999254 - 0.45, 3000.0, 30.0, 347.21071428570036, -38.03468253968203, 267.03650793649604 - 0.5, 3000.0, 30.0, 334.79999999997904, -47.89999999999915, 252.89999999998224 - 0.55, 3000.0, 30.0, 321.7017857142567, -57.12392857142727, 237.88571428568912 - 0.6000000000000001, 3000.0, 30.0, 308.0499999999615, -65.63444444444256, 222.08888888885463 - 0.0, 3000.0, 32.0, 468.16135944441925, 72.95526812981271, 363.5801119137578 - 0.05, 3000.0, 32.0, 467.2383983389552, 60.46627348338173, 362.55093423923574 - 0.1, 3000.0, 32.0, 464.42548518149687, 47.857435340624015, 359.4405581345822 -0.15000000000000002, 3000.0, 32.0, 459.8035804288493, 35.223296210466316, 354.3625571042707 - 0.2, 3000.0, 32.0, 453.45364453781724, 22.658398601835486, 347.43050465277423 - 0.25, 3000.0, 32.0, 445.4566379652055, 10.25728502365829, 338.757974284566 -0.30000000000000004, 3000.0, 32.0, 435.87695349748367, -1.8822522601610963, 328.4419595355635 -0.35000000000000003, 3000.0, 32.0, 424.90548812007006, -13.689335951130206, 316.71065893394257 - 0.4, 3000.0, 32.0, 412.6910167921354, -25.076422028452296, 303.7316901582577 - 0.45, 3000.0, 32.0, 399.3873684626442, -35.95135483308508, 289.6654435911088 - 0.5, 3000.0, 32.0, 385.1471085831127, -46.2231316155478, 274.6741164390853 - 0.55, 3000.0, 32.0, 370.1228026050569, -55.800749626359725, 258.91990590877634 - 0.6000000000000001, 3000.0, 32.0, 354.4670159799929, -64.59320611604002, 242.56500920677146 - 0.0, 3000.0, 34.0, 529.1811441726364, 79.07141832369578, 390.9530969054826 - 0.05, 3000.0, 34.0, 528.1092797373989, 66.21590862419971, 389.8541046586254 - 0.1, 3000.0, 34.0, 524.9166261725863, 53.19535537980903, 386.54155196164936 -0.15000000000000002, 3000.0, 34.0, 519.6918006494087, 40.120473938868656, 381.1328310943569 - 0.2, 3000.0, 34.0, 512.5234203390754, 27.101979649723535, 373.7453343365501 - 0.25, 3000.0, 34.0, 503.50010241279705, 14.250587860718532, 364.49645396803123 -0.30000000000000004, 3000.0, 34.0, 492.6946145098953, 1.6867625251954657, 353.4850528068425 -0.35000000000000003, 3000.0, 34.0, 480.2926738318875, -10.54931567053409, 340.9471220717348 - 0.4, 3000.0, 34.0, 466.4719862240049, -22.369293911986745, 327.08896430759967 - 0.45, 3000.0, 34.0, 451.43661569108025, -33.67220184255903, 312.13414853363764 - 0.5, 3000.0, 34.0, 435.3840366980484, -44.36022349117716, 296.3019271504743 - 0.55, 3000.0, 34.0, 418.5117237098448, -54.33554288676736, 279.8115525587351 - 0.6000000000000001, 3000.0, 34.0, 401.01715119140437, -63.50034405825578, 262.8822771590456 - 0.0, 3000.0, 36.0, 590.0531817327238, 85.24852053315321, 418.1979915662497 - 0.05, 3000.0, 36.0, 588.8713516422665, 72.00790390779754, 416.99477809725045 - 0.1, 3000.0, 36.0, 585.3117258340349, 58.5865289662062, 413.4774558979989 -0.15000000000000002, 3000.0, 36.0, 579.4820541233814, 45.09869315181467, 407.753680738167 - 0.2, 3000.0, 36.0, 571.4900863256589, 31.658693908058343, 399.9311083874262 - 0.25, 3000.0, 36.0, 561.4435722562196, 18.380828678372716, 390.1173946154483 -0.30000000000000004, 3000.0, 36.0, 549.4442266085982, 5.387982769440118, 378.38927818061455 -0.35000000000000003, 3000.0, 36.0, 535.614555451576, -7.264290606857807, 365.0632151469426 - 0.4, 3000.0, 36.0, 520.1628827630818, -19.491570030417773, 350.36246867145144 - 0.45, 3000.0, 36.0, 503.3668147041404, -31.207364335484183, 334.51000732913667 - 0.5, 3000.0, 36.0, 485.48663689000944, -42.3256997927139, 317.7288733405041 - 0.55, 3000.0, 36.0, 466.7826349359464, -52.76060267276371, 300.24210892605987 - 0.6000000000000001, 3000.0, 36.0, 447.5150944572089, -62.42609924629045, 282.27275630631 - 0.0, 3000.0, 38.0, 651.2926481144905, 91.29852629643278, 445.3253505844458 - 0.05, 3000.0, 38.0, 650.0032056827623, 77.7535021457984, 444.1424159107887 - 0.1, 3000.0, 38.0, 646.0720710130134, 64.00649239167225, 440.4594195908498 -0.15000000000000002, 3000.0, 38.0, 639.6253756756145, 50.170425059826975, 434.4131388054742 - 0.2, 3000.0, 38.0, 630.789251240935, 36.35822817603514, 426.1403507355071 - 0.25, 3000.0, 38.0, 619.6898292793452, 22.6828297660693, 415.77783256179356 -0.30000000000000004, 3000.0, 38.0, 606.4467733909419, 9.26358710404535, 403.4399824636183 -0.35000000000000003, 3000.0, 38.0, 591.2113542625235, -3.836049205602457, 389.4232648922947 - 0.4, 3000.0, 38.0, 574.1895174019484, -16.50902083327567, 373.9224912543841 - 0.45, 3000.0, 38.0, 555.636594138016, -28.632056129293908, 357.10946226295175 - 0.5, 3000.0, 38.0, 535.7955693442967, -40.0859367739974, 339.1617313044422 - 0.55, 3000.0, 38.0, 514.9094278943622, -50.75144444772643, 320.25685176530055 - 0.6000000000000001, 3000.0, 38.0, 493.2211546617837, -60.50936083082122, 300.57237703197114 - 0.0, 3000.0, 40.0, 712.3000000000004, 97.49999999999993, 472.5000000000003 - 0.05, 3000.0, 40.0, 710.9024188311713, 83.52646103896112, 471.1391558441565 - 0.1, 3000.0, 40.0, 706.6000000000031, 69.40000000000008, 467.20000000000147 -0.15000000000000002, 3000.0, 40.0, 699.5363717532485, 55.21030844155838, 460.81126623376855 - 0.2, 3000.0, 40.0, 689.8551623376608, 41.04707792207748, 452.10168831169193 - 0.25, 3000.0, 40.0, 677.6999999999922, 26.999999999998906, 441.20000000000476 -0.30000000000000004, 3000.0, 40.0, 663.2104617604363, 13.145021645021583, 428.2088023087926 -0.35000000000000003, 3000.0, 40.0, 646.5310714285761, -0.3159523809522433, 413.4354761904771 - 0.4, 3000.0, 40.0, 627.9000000000092, -13.29999999999976, 397.10000000000247 - 0.45, 3000.0, 40.0, 607.6259523809681, -25.776031746031375, 379.41634920635494 - 0.5, 3000.0, 40.0, 586.0000000000252, -37.69999999999948, 360.6000000000109 - 0.55, 3000.0, 40.0, 563.313214285752, -49.02785714285647, 340.8664285714471 - 0.6000000000000001, 3000.0, 40.0, 539.8566666667207, -59.71555555555476, 320.4311111111397 - 0.0, 3000.0, 42.0, 773.2090993135843, 103.73324048093983, 499.60891363479493 - 0.05, 3000.0, 42.0, 771.7530416351206, 89.49772690527556, 498.28524598645373 - 0.1, 3000.0, 42.0, 767.1160631261091, 75.01559889013906, 494.1556174658179 -0.15000000000000002, 3000.0, 42.0, 759.4597411270707, 60.412462571070975, 487.38968906346554 - 0.2, 3000.0, 42.0, 748.945652978525, 45.81392408361202, 478.15712176997494 - 0.25, 3000.0, 42.0, 735.7353760209924, 31.345589563302845, 466.62757657592437 -0.30000000000000004, 3000.0, 42.0, 719.9815899889911, 17.13452327322803, 452.954074481161 -0.35000000000000003, 3000.0, 42.0, 701.8917042352772, 3.3101891012906273, 437.41590704355235 - 0.4, 3000.0, 42.0, 681.7033426081716, -10.048375135109218, 420.2532033295842 - 0.45, 3000.0, 42.0, 659.6920671649281, -22.89866525399745, 401.7132640595716 - 0.5, 3000.0, 42.0, 636.123955410567, -35.189043664543426, 382.0415970403727 - 0.55, 3000.0, 42.0, 611.2650848501079, -46.86787277591651, 361.48371007884487 - 0.6000000000000001, 3000.0, 42.0, 585.381532988571, -57.88351499728604, 340.2851109818454 - 0.0, 3000.0, 44.0, 834.4406852657435, 109.98264534809792, 526.8766997206293 - 0.05, 3000.0, 44.0, 832.7780952699143, 95.38639693613887, 525.4337371206481 - 0.1, 3000.0, 44.0, 827.7735788208684, 80.57538038599995, 521.0955078576171 -0.15000000000000002, 3000.0, 44.0, 819.5606083142824, 65.6562661177304, 514.016466339332 - 0.2, 3000.0, 44.0, 808.272656145833, 50.73572455137944, 504.3510669735878 - 0.25, 3000.0, 44.0, 794.0431947111972, 35.92042610699626, 492.2537641681799 -0.30000000000000004, 3000.0, 44.0, 776.9732395677332, 21.30923288900729, 477.84365180531546 -0.35000000000000003, 3000.0, 44.0, 757.4113055302087, 7.076457870527309, 461.5281623089908 - 0.4, 3000.0, 44.0, 735.6247018564743, -6.686756612637959, 443.55146865232314 - 0.45, 3000.0, 44.0, 711.8915144431575, -19.929098684971823, 424.1196252257649 - 0.5, 3000.0, 44.0, 686.4871350271924, -32.58929885588548, 403.4482160654347 - 0.55, 3000.0, 44.0, 659.686955345513, -44.606087634790136, 381.7528252074512 - 0.6000000000000001, 3000.0, 44.0, 631.7663671350534, -55.918195531096956, 359.2490366879331 - 0.0, 3000.0, 46.0, 895.3657871102474, 116.26600103984045, 553.9784190432997 - 0.05, 3000.0, 46.0, 893.6031391174436, 101.39098963484581, 552.44469240861 - 0.1, 3000.0, 46.0, 888.2264211791327, 86.26679362594808, 547.898019766395 -0.15000000000000002, 3000.0, 46.0, 879.3907762926765, 71.00632524365773, 540.4949921203769 - 0.2, 3000.0, 46.0, 867.2513474554372, 55.72249671848533, 530.3922004742792 - 0.25, 3000.0, 46.0, 851.9632776647774, 40.528220280941426, 517.7462358318252 -0.30000000000000004, 3000.0, 46.0, 833.6474518293328, 25.526840184351748, 502.68099829961346 -0.35000000000000003, 3000.0, 46.0, 812.6982071644899, 10.913961961699929, 485.5748566780531 - 0.4, 3000.0, 46.0, 789.3752981435488, -3.2159506114849346, 466.70365011160806 - 0.45, 3000.0, 46.0, 763.9172735892064, -16.81672564360619, 446.34024643504796 - 0.5, 3000.0, 46.0, 736.5679837368073, -29.830118272084036, 424.75825631056676 - 0.55, 3000.0, 46.0, 707.5712788216955, -42.197883634338744, 402.23129040035843 - 0.6000000000000001, 3000.0, 46.0, 677.1710090792135, -53.861776867790496, 379.03295936661743 - 0.0, 3000.0, 48.0, 956.5044568368961, 122.64688950981146, 581.2942432945891 - 0.05, 3000.0, 48.0, 954.6190281390627, 107.49925991592278, 579.6919657249306 - 0.1, 3000.0, 48.0, 948.8839368738882, 92.04623955605622, 574.9260909896286 -0.15000000000000002, 3000.0, 48.0, 939.4594058262957, 76.42390492726732, 567.1682259732897 - 0.2, 3000.0, 48.0, 926.5056577812085, 60.7683325266113, 556.5899775605194 - 0.25, 3000.0, 48.0, 910.1829155235505, 45.215598851143625, 543.3629526359244 -0.30000000000000004, 3000.0, 48.0, 890.6128626122843, 29.9096007430317, 527.6292880963127 -0.35000000000000003, 3000.0, 48.0, 868.2202421855098, 14.935214070548646, 509.76242979332505 - 0.4, 3000.0, 48.0, 843.2966573918071, 0.3944289343812468, 490.0357474175675 - 0.45, 3000.0, 48.0, 816.1220298386442, -13.614995766737904, 468.7148331945392 - 0.5, 3000.0, 48.0, 786.9792015187647, -26.994243333587196, 446.06722371601705 - 0.55, 3000.0, 48.0, 756.1510144249129, -39.644497066945085, 422.36045557377804 - 0.6000000000000001, 3000.0, 48.0, 723.9203105498327, -51.46694026758988, 397.86206535959866 - 0.0, 3000.0, 50.0, 1017.4999999999991, 129.00000000000026, 608.3999999999992 - 0.05, 3000.0, 50.0, 1015.5141558441528, 113.5441720779232, 606.8212012987059 - 0.1, 3000.0, 50.0, 1009.3999999999941, 97.80000000000207, 601.9000000000086 -0.15000000000000002, 3000.0, 50.0, 999.3487662337574, 81.89374188312006, 593.8281980519606 - 0.2, 3000.0, 50.0, 985.5516883116773, 65.95165584416029, 582.7975974026133 - 0.25, 3000.0, 50.0, 968.1999999999881, 50.10000000000578, 569.0000000000199 -0.30000000000000004, 3000.0, 50.0, 947.4643578643132, 34.47337662337861, 552.5951659451465 -0.35000000000000003, 3000.0, 50.0, 923.6604761904573, 19.13059523809533, 534.0046428571416 - 0.4, 3000.0, 50.0, 897.0999999999711, 4.199999999999961, 513.4999999999936 - 0.45, 3000.0, 50.0, 868.1330158729744, -10.160396825397099, 491.3169047618895 - 0.5, 3000.0, 50.0, 837.0999999999422, -23.800000000000647, 467.69999999997066 - 0.55, 3000.0, 50.0, 804.3414285713503, -36.56821428571548, 442.89392857137875 - 0.6000000000000001, 3000.0, 50.0, 770.197777777674, -48.31444444444632, 417.1433333332556 - 0.0, 5000.0, 20.0, 110.39999999999998, 37.099999999999994, 200.49999999999994 - 0.05, 5000.0, 20.0, 110.2375, 27.456250000000008, 199.84374999999997 - 0.1, 5000.0, 20.0, 109.60000000000004, 17.800000000000015, 197.9 -0.15000000000000002, 5000.0, 20.0, 108.51250000000006, 8.193750000000021, 194.73125 - 0.2, 5000.0, 20.0, 107.00000000000013, -1.2999999999999683, 190.39999999999995 - 0.25, 5000.0, 20.0, 105.07499999999999, -10.61249999999999, 184.94375 -0.30000000000000004, 5000.0, 20.0, 102.80000000000001, -19.700000000000006, 178.49999999999997 -0.35000000000000003, 5000.0, 20.0, 100.24375000000002, -28.518750000000008, 171.18125 - 0.4, 5000.0, 20.0, 97.40000000000002, -37.0, 163.10000000000002 - 0.45, 5000.0, 20.0, 94.28125000000003, -45.08125000000001, 154.3687500000001 - 0.5, 5000.0, 20.0, 90.90000000000002, -52.70000000000003, 145.10000000000014 - 0.55, 5000.0, 20.0, 87.26874999999998, -59.793750000000074, 135.40625000000023 - 0.6000000000000001, 5000.0, 20.0, 83.3999999999999, -66.30000000000013, 125.40000000000035 - 0.0, 5000.0, 22.0, 176.8660859503895, 43.964620636221255, 232.74527154235903 - 0.05, 5000.0, 22.0, 176.49975132902094, 33.739622205067874, 232.06530940691673 - 0.1, 5000.0, 22.0, 175.4186074368549, 23.438219218599233, 229.92225335516997 -0.15000000000000002, 5000.0, 22.0, 173.65989023081698, 13.14660361321481, 226.40089712622049 - 0.2, 5000.0, 22.0, 171.26083566783322, 2.950967325314122, 221.58603445917 - 0.25, 5000.0, 22.0, 168.2660265986593, -7.050519718966634, 215.55512318475266 -0.30000000000000004, 5000.0, 22.0, 164.6906582987302, -16.807599552438248, 208.41496476717143 -0.35000000000000003, 5000.0, 22.0, 160.52977466717252, -26.258517789036592, 200.24609449486434 - 0.4, 5000.0, 22.0, 155.88841268366235, -35.33959375925123, 191.20476872584902 - 0.45, 5000.0, 22.0, 150.84411105773842, -43.98762836443332, 181.42831355074856 - 0.5, 5000.0, 22.0, 145.4744084989396, -52.139422505933965, 171.0540550601859 - 0.55, 5000.0, 22.0, 139.85684371680466, -59.731777085104326, 160.21931934478414 - 0.6000000000000001, 5000.0, 22.0, 134.06895542087236, -66.70149300329547, 149.06143249516626 - 0.0, 5000.0, 24.0, 243.05304297519478, 50.60638242620074, 263.7833568520805 - 0.05, 5000.0, 24.0, 242.56963242464428, 39.81134940995689, 263.0398915580044 - 0.1, 5000.0, 24.0, 241.089303718428, 28.929109609299744, 260.6878657855094 -0.15000000000000002, 5000.0, 24.0, 238.6686838485203, 18.045258992429105, 256.81368091090184 - 0.2, 5000.0, 24.0, 235.36439980689522, 7.2453935275446995, 251.50373831048836 - 0.25, 5000.0, 24.0, 231.24588942601835, -3.382906329041314, 244.82602591314344 -0.30000000000000004, 5000.0, 24.0, 226.33134717638768, -13.759998073466848, 236.92218543746407 -0.35000000000000003, 5000.0, 24.0, 220.61401346027517, -23.794489865744257, 227.89959713408754 - 0.4, 5000.0, 24.0, 214.2381883148086, -33.43404925794071, 217.9290333357344 - 0.45, 5000.0, 24.0, 207.31040686840225, -42.61657895410955, 207.16541835460538 - 0.5, 5000.0, 24.0, 199.9372042494701, -51.27998165830417, 195.76367650290095 - 0.55, 5000.0, 24.0, 192.2251155864263, -59.36216007457792, 183.87873209282165 - 0.6000000000000001, 5000.0, 24.0, 184.28067600768497, -66.80101690698423, 171.66550943656804 - 0.0, 5000.0, 26.0, 309.1469570248053, 57.12583389806961, 293.93880639062246 - 0.05, 5000.0, 26.0, 308.57088785575723, 45.78701551231198, 293.1080690056341 - 0.1, 5000.0, 26.0, 306.71069628157403, 34.37089039070072, 290.54235153826437 -0.15000000000000002, 5000.0, 26.0, 303.6387823508156, 22.9543625650361, 286.3197661324741 - 0.2, 5000.0, 26.0, 299.4275461120415, 11.61433606711837, 280.51842493222347 - 0.25, 5000.0, 26.0, 294.15461395404753, 0.41746692036734745, 273.17436704915787 -0.30000000000000004, 5000.0, 26.0, 287.8767069046798, -10.528596818276291, 264.4919237241708 -0.35000000000000003, 5000.0, 26.0, 280.6302399197912, -21.108703047933577, 254.63317752587793 - 0.4, 5000.0, 26.0, 272.55375760412335, -31.27870787700441, 243.7609135826943 - 0.45, 5000.0, 26.0, 263.76027215019633, -40.976715361568885, 232.03774138308637 - 0.5, 5000.0, 26.0, 254.36279575053013, -50.14082955770701, 219.62627041552065 - 0.55, 5000.0, 26.0, 244.4743405976449, -58.70915452149888, 206.68911016846363 - 0.6000000000000001, 5000.0, 26.0, 234.20791888406063, -66.61979430902448, 193.38887013038186 - 0.0, 5000.0, 28.0, 375.4117526392866, 63.64576912499682, 323.53910092277596 - 0.05, 5000.0, 28.0, 374.67039959560486, 51.80922849603761, 322.61466691657773 - 0.1, 5000.0, 28.0, 372.41407016706233, 39.88310530787375, 319.83949678003273 -0.15000000000000002, 5000.0, 28.0, 368.7074654514902, 27.949993232616432, 315.2856945564261 - 0.2, 5000.0, 28.0, 363.6152865467198, 16.092485942376854, 309.02536428904295 - 0.25, 5000.0, 28.0, 357.1832572255554, 4.388923248060169, 301.0722785233895 -0.30000000000000004, 5000.0, 28.0, 349.53301056092124, -7.065339594603404, 291.6735357960966 -0.35000000000000003, 5000.0, 28.0, 340.7643329380461, -18.167347863946738, 281.03658387237437 - 0.4, 5000.0, 28.0, 330.9884881928546, -28.861560146872353, 269.29414761202895 - 0.45, 5000.0, 28.0, 320.3138707985959, -39.08058170314045, 256.59763260121645 - 0.5, 5000.0, 28.0, 308.8488752285195, -48.757017792511235, 243.09844442609275 - 0.55, 5000.0, 28.0, 296.7018959558748, -57.82347367474492, 228.94798867281392 - 0.6000000000000001, 5000.0, 28.0, 283.9813274539109, -66.21255460960168, 214.29767092753605 - 0.0, 5000.0, 30.0, 441.7999999999995, 70.2, 352.8999999999999 - 0.05, 5000.0, 30.0, 440.8624999999994, 57.912500000000016, 351.8874999999996 - 0.1, 5000.0, 30.0, 438.19999999999874, 45.49999999999991, 348.89999999999833 -0.15000000000000002, 5000.0, 30.0, 433.86249999999694, 33.06249999999974, 344.0124999999965 - 0.2, 5000.0, 30.0, 427.89999999999384, 20.699999999999456, 337.29999999999416 - 0.25, 5000.0, 30.0, 420.31874999999883, 8.52499999999994, 328.7749999999986 -0.30000000000000004, 5000.0, 30.0, 411.2999999999987, -3.400000000000083, 318.6999999999971 -0.35000000000000003, 5000.0, 30.0, 400.9937499999985, -15.00000000000016, 307.30624999999515 - 0.4, 5000.0, 30.0, 389.4999999999981, -26.200000000000255, 294.6999999999926 - 0.45, 5000.0, 30.0, 376.9312499999972, -36.92500000000036, 281.0187499999892 - 0.5, 5000.0, 30.0, 363.3999999999956, -47.10000000000044, 266.39999999998486 - 0.55, 5000.0, 30.0, 349.01874999999274, -56.6500000000005, 250.98124999997953 - 0.6000000000000001, 5000.0, 30.0, 333.89999999998867, -65.50000000000054, 234.89999999997312 - 0.0, 5000.0, 32.0, 508.1330064694041, 76.79674357950772, 382.46684226087865 - 0.05, 5000.0, 32.0, 507.0905897379821, 64.107702024385, 381.39163742453707 - 0.1, 5000.0, 32.0, 504.04117072424685, 51.24443280563956, 378.16644640361994 -0.15000000000000002, 5000.0, 32.0, 499.05218735240896, 38.32434225116018, 372.89067600075833 - 0.2, 5000.0, 32.0, 492.19107754668005, 25.464836688835703, 365.6637330185837 - 0.25, 5000.0, 32.0, 483.48889557834934, 12.801820884803796, 356.5352207802171 -0.30000000000000004, 5000.0, 32.0, 473.1222303303872, 0.39720585220720367, 345.7539565268227 -0.35000000000000003, 5000.0, 32.0, 461.2189189945701, -11.666244306039424, 333.5405941829762 - 0.4, 5000.0, 32.0, 447.9562709158338, -23.31518409311211, 320.0292270216681 - 0.45, 5000.0, 32.0, 433.499227400824, -34.47391336066432, 305.3755884787846 - 0.5, 5000.0, 32.0, 418.0127297561873, -45.066731960349465, 289.7354119902124 - 0.55, 5000.0, 32.0, 401.6617192885698, -55.01793974382107, 273.26443099183734 - 0.6000000000000001, 5000.0, 32.0, 384.61113730461796, -64.25183656273248, 256.1183789195464 - 0.0, 5000.0, 34.0, 574.3153870504522, 83.4152371525129, 411.9386920364563 - 0.05, 5000.0, 34.0, 573.212721231648, 70.32779016495245, 410.78390802238744 - 0.1, 5000.0, 34.0, 569.77575479679, 57.03465715893981, 407.3333101030861 -0.15000000000000002, 5000.0, 34.0, 564.1105823347724, 43.661843468946465, 401.6931234363885 - 0.2, 5000.0, 34.0, 556.323298434489, 30.335354429443907, 393.9695731801305 - 0.25, 5000.0, 34.0, 546.5049211737129, 17.19887202833136, 384.21805401248156 -0.30000000000000004, 5000.0, 34.0, 534.8067746746815, 4.325371639796075, 372.69728253026904 -0.35000000000000003, 5000.0, 34.0, 521.3307312236767, -8.184728147435491, 359.6242518167558 - 0.4, 5000.0, 34.0, 506.31616440630495, -20.27007498908106, 345.17952709081464 - 0.45, 5000.0, 34.0, 489.9680724833437, -31.859549979747165, 329.5527805374166 - 0.5, 5000.0, 34.0, 472.49145371557046, -42.88203421404033, 312.9336843415325 - 0.55, 5000.0, 34.0, 454.0913063637625, -53.26640878656708, 295.5119106881333 - 0.6000000000000001, 5000.0, 34.0, 434.9726286886978, -62.94155479193397, 277.4771317621897 - 0.0, 5000.0, 36.0, 640.3945001782255, 90.05892767499401, 441.21685746355894 - 0.05, 5000.0, 36.0, 639.2229705170112, 76.549012776515, 439.96080408826566 - 0.1, 5000.0, 36.0, 635.3863458585846, 62.84032229112389, 436.30959335153557 -0.15000000000000002, 5000.0, 36.0, 629.0321737479167, 49.05162430002865, 430.3513365291907 - 0.2, 5000.0, 36.0, 620.3080017299782, 35.30168688443711, 422.17414489705345 - 0.25, 5000.0, 36.0, 609.3639738336773, 21.71943325529943, 411.7941710404302 -0.30000000000000004, 5000.0, 36.0, 596.3398481521195, 8.3931661045948, 399.51540230667297 -0.35000000000000003, 5000.0, 36.0, 581.3438031053238, -4.564017014137981, 385.5746662916942 - 0.4, 5000.0, 36.0, 564.620721741363, -17.097577474625233, 370.18959483514817 - 0.45, 5000.0, 36.0, 546.3813109513029, -29.138336918776748, 353.5826187157551 - 0.5, 5000.0, 36.0, 526.8362776262086, -40.61711698850233, 335.9761687122347 - 0.55, 5000.0, 36.0, 506.19632865714414, -51.464739325711726, 317.59267560330704 - 0.6000000000000001, 5000.0, 36.0, 484.6721709351755, -61.61202557231478, 298.65457016769227 - 0.0, 5000.0, 38.0, 706.9237339913813, 96.78729137165801, 470.3878032657437 - 0.05, 5000.0, 38.0, 705.4972103043149, 82.82566466392034, 469.09012036203876 - 0.1, 5000.0, 38.0, 701.2349689161515, 68.72075563438453, 465.2322524755884 -0.15000000000000002, 5000.0, 38.0, 694.2552763862855, 54.563251553986525, 458.92321681704766 - 0.2, 5000.0, 38.0, 684.676399274111, 40.443839693662106, 450.2720305970718 - 0.25, 5000.0, 38.0, 672.585611269333, 26.448847069852963, 439.32435796177816 -0.30000000000000004, 5000.0, 38.0, 658.1941575404257, 12.682041716980715, 426.37927531547246 -0.35000000000000003, 5000.0, 38.0, 641.6608614083372, -0.7614230438156351, 411.68818240391994 - 0.4, 5000.0, 38.0, 623.2302621054156, -13.76937605625296, 395.4397733489735 - 0.45, 5000.0, 38.0, 603.1254698861563, -26.23390062283444, 377.8384186784595 - 0.5, 5000.0, 38.0, 581.5695950050549, -38.04708004606324, 359.0884889202045 - 0.55, 5000.0, 38.0, 558.7857477166065, -49.10099762844258, 339.3943546020351 - 0.6000000000000001, 5000.0, 38.0, 534.9970382753064, -59.28773667247557, 318.9603862517775 - 0.0, 5000.0, 40.0, 773.1000000000006, 103.50000000000007, 499.60000000000065 - 0.05, 5000.0, 40.0, 771.5499999999996, 89.18749999999993, 498.1875000000005 - 0.1, 5000.0, 40.0, 766.8999999999972, 74.69999999999962, 494.0999999999991 -0.15000000000000002, 5000.0, 40.0, 759.2749999999936, 60.137499999999264, 487.43749999999693 - 0.2, 5000.0, 40.0, 748.7999999999895, 45.599999999998836, 478.2999999999939 - 0.25, 5000.0, 40.0, 735.5562499999966, 31.1812499999996, 466.69999999999925 -0.30000000000000004, 5000.0, 40.0, 719.7999999999985, 16.99999999999986, 453.0000000000025 -0.35000000000000003, 5000.0, 40.0, 701.7374999999968, 3.181249999999815, 437.51250000000465 - 0.4, 5000.0, 40.0, 681.599999999995, -10.200000000000209, 420.4000000000071 - 0.45, 5000.0, 40.0, 659.6124999999942, -23.056250000000208, 401.86250000000905 - 0.5, 5000.0, 40.0, 635.9999999999935, -35.30000000000019, 382.10000000001054 - 0.55, 5000.0, 40.0, 610.9874999999937, -46.84375000000014, 361.3125000000111 - 0.6000000000000001, 5000.0, 40.0, 584.7999999999954, -57.60000000000009, 339.7000000000105 - 0.0, 5000.0, 42.0, 839.2682451053608, 110.22785513310733, 528.9315691768529 - 0.05, 5000.0, 42.0, 837.621993944381, 95.64624535364325, 527.449390668354 - 0.1, 5000.0, 42.0, 832.5887650683652, 80.81337047169139, 523.1085422382207 -0.15000000000000002, 5000.0, 42.0, 824.3108286715395, 65.85312789270117, 516.0374941780406 - 0.2, 5000.0, 42.0, 812.9304549481292, 50.88941502212229, 506.36471677940284 - 0.25, 5000.0, 42.0, 798.5497910650553, 36.05048743850654, 494.1431290366219 -0.30000000000000004, 5000.0, 42.0, 781.4314762984617, 21.447168027994813, 479.727855133107 -0.35000000000000003, 5000.0, 42.0, 761.7725742490925, 7.207532466002556, 463.43095983058254 - 0.4, 5000.0, 42.0, 739.871959110109, -6.591922036747067, 445.43454038845044 - 0.45, 5000.0, 42.0, 716.0030524265688, -19.861803653357548, 425.95318594169333 - 0.5, 5000.0, 42.0, 690.439275743529, -32.51272055693239, 405.2014856252941 - 0.55, 5000.0, 42.0, 663.454050606046, -44.455280920575056, 383.3940285742357 - 0.6000000000000001, 5000.0, 42.0, 635.3207985591773, -55.60009291738906, 360.74540392350065 - 0.0, 5000.0, 44.0, 905.6675015062683, 117.0834379342054, 558.2314895147067 - 0.05, 5000.0, 44.0, 903.9342749352323, 102.12641000504907, 556.7435759909733 - 0.1, 5000.0, 44.0, 898.5124649848032, 86.93688928345655, 552.2239587150234 -0.15000000000000002, 5000.0, 44.0, 889.5724995969141, 71.6251673355741, 544.8109467338563 - 0.2, 5000.0, 44.0, 877.2848067134998, 56.301535727547765, 534.6428490944706 - 0.25, 5000.0, 44.0, 861.7953218500221, 41.07168220906506, 521.7766701670845 -0.30000000000000004, 5000.0, 44.0, 843.3479502278394, 26.059709795647922, 506.59463302904356 -0.35000000000000003, 5000.0, 44.0, 822.1139429452683, 11.39060814499378, 489.4303002966288 - 0.4, 5000.0, 44.0, 798.4571978868637, -2.832594919742964, 470.4866577232953 - 0.45, 5000.0, 44.0, 772.6934512406215, -16.501381116772055, 449.9993352782047 - 0.5, 5000.0, 44.0, 745.1384391945361, -29.507232164303215, 428.2039629305181 - 0.55, 5000.0, 44.0, 716.1078979366031, -41.74162978054618, 405.33617064939665 - 0.6000000000000001, 5000.0, 44.0, 685.9175636548173, -53.0960556837107, 381.6315884040017 - 0.0, 5000.0, 46.0, 971.7260261177418, 123.965208453733, 587.487502217403 - 0.05, 5000.0, 46.0, 969.8374331295893, 108.7051336368313, 585.8685790701288 - 0.1, 5000.0, 46.0, 964.032416251269, 93.16040349242013, 581.101505393077 -0.15000000000000002, 5000.0, 46.0, 954.4714960983722, 77.46031519233436, 573.3245902332451 - 0.2, 5000.0, 46.0, 941.3151932864887, 61.73416590840874, 562.6761426376324 - 0.25, 5000.0, 46.0, 924.6742637842198, 46.113220753191484, 549.2106404542878 -0.30000000000000004, 5000.0, 46.0, 904.8585221481485, 30.720873076380848, 533.3178863270786 -0.35000000000000003, 5000.0, 46.0, 882.1021977662236, 15.704148568218255, 515.3311377299667 - 0.4, 5000.0, 46.0, 856.7428021131337, 1.123415319629425, 495.4745080207731 - 0.45, 5000.0, 46.0, 829.0920261418809, -12.939294178631325, 473.9993965863531 - 0.5, 5000.0, 46.0, 799.4615608054663, -26.401947435809692, 451.1572028135613 - 0.55, 5000.0, 46.0, 768.1630970568922, -39.182511961151356, 427.1993260892527 - 0.6000000000000001, 5000.0, 46.0, 735.5083258491594, -51.198955263902015, 402.3771658002824 - 0.0, 5000.0, 48.0, 1038.213463350083, 130.93806867541375, 617.0684307451519 - 0.05, 5000.0, 48.0, 1036.125243737535, 115.3867397629034, 615.3645426202315 - 0.1, 5000.0, 48.0, 1029.908078002252, 99.54215411573483, 610.4050138342697 -0.15000000000000002, 5000.0, 48.0, 1019.7088092148518, 83.52099000387406, 602.316538906077 - 0.2, 5000.0, 48.0, 1005.674280445948, 67.43992569728724, 591.2258123544639 - 0.25, 5000.0, 48.0, 987.8758588960145, 51.39284465504036, 577.1565110547441 -0.30000000000000004, 5000.0, 48.0, 966.6868152460911, 35.56480957979829, 560.5443824561894 -0.35000000000000003, 5000.0, 48.0, 942.3936687825826, 20.165430535867316, 541.7635212674652 - 0.4, 5000.0, 48.0, 915.3280408898758, 5.214948897385982, 521.0225625856787 - 0.45, 5000.0, 48.0, 885.8102774278624, -9.219051788965054, 498.5715064108294 - 0.5, 5000.0, 48.0, 854.160724256434, -23.068987976505138, 474.660352742918 - 0.55, 5000.0, 48.0, 820.6997272354829, -36.26727611855363, 449.53910158194395 - 0.6000000000000001, 5000.0, 48.0, 785.7476322249001, -48.746332668429865, 423.4577529279072 - 0.0, 5000.0, 50.0, 1104.4000000000015, 138.10000000000008, 646.9999999999985 - 0.05, 5000.0, 50.0, 1102.237500000005, 122.20624999999998, 645.2562500000034 - 0.1, 5000.0, 50.0, 1095.6000000000079, 105.99999999999991, 640.1000000000092 -0.15000000000000002, 5000.0, 50.0, 1084.6875000000073, 89.6187499999998, 631.6687500000173 - 0.2, 5000.0, 50.0, 1069.7000000000025, 73.19999999999975, 620.1000000000288 - 0.25, 5000.0, 50.0, 1050.799999999988, 56.90625000000015, 605.4250000000095 -0.30000000000000004, 5000.0, 50.0, 1028.299999999993, 40.79999999999978, 588.100000000003 -0.35000000000000003, 5000.0, 50.0, 1002.4249999999838, 24.9375, 568.5250000000096 - 0.4, 5000.0, 50.0, 973.5999999999713, 9.50000000000042, 546.9000000000195 - 0.45, 5000.0, 50.0, 942.1999999999534, -5.3624999999989775, 523.4750000000327 - 0.5, 5000.0, 50.0, 908.5999999999301, -19.499999999998195, 498.5000000000487 - 0.55, 5000.0, 50.0, 873.1749999999004, -32.76249999999719, 472.2250000000672 - 0.6000000000000001, 5000.0, 50.0, 836.2999999998633, -44.99999999999602, 444.90000000008797 - 0.0, 10000.0, 20.0, 135.59999999999997, 39.49999999999999, 224.39999999999995 - 0.05, 10000.0, 20.0, 135.33125, 29.725000000000005, 223.66875 - 0.1, 10000.0, 20.0, 134.5000000000001, 19.90000000000002, 221.60000000000002 -0.15000000000000002, 10000.0, 20.0, 133.14375000000015, 10.100000000000033, 218.23125000000002 - 0.2, 10000.0, 20.0, 131.3000000000003, 0.4000000000000542, 213.60000000000005 - 0.25, 10000.0, 20.0, 129.02500000000003, -9.118749999999986, 207.69374999999985 -0.30000000000000004, 10000.0, 20.0, 126.30000000000004, -18.400000000000016, 200.70000000000002 -0.35000000000000003, 10000.0, 20.0, 123.0812500000001, -27.37500000000001, 192.77500000000006 - 0.4, 10000.0, 20.0, 119.50000000000014, -36.000000000000014, 184.00000000000014 - 0.45, 10000.0, 20.0, 115.68124999999998, -44.218749999999986, 174.4625 - 0.5, 10000.0, 20.0, 111.6, -51.99999999999999, 164.3 - 0.55, 10000.0, 20.0, 107.26875000000003, -59.306250000000006, 153.63750000000007 - 0.6000000000000001, 10000.0, 20.0, 102.70000000000005, -66.10000000000004, 142.60000000000008 - 0.0, 10000.0, 22.0, 217.13547465141042, 47.73009753902789, 261.12827942451077 - 0.05, 10000.0, 22.0, 216.65226979820125, 37.18445952055672, 260.34294029709423 - 0.1, 10000.0, 22.0, 215.35095895813294, 26.628179622763557, 258.0451318312362 -0.15000000000000002, 10000.0, 22.0, 213.24132025739533, 16.112820697429083, 254.2819674986441 - 0.2, 10000.0, 22.0, 210.3331318221789, 5.689945596333982, 249.1005607710253 - 0.25, 10000.0, 22.0, 206.6032081134341, -4.606591987223712, 242.4996004057702 -0.30000000000000004, 10000.0, 22.0, 202.16021825306805, -14.672101726015704, 234.67147401753633 -0.35000000000000003, 10000.0, 22.0, 197.08927462713044, -24.405569053452766, 225.76901381287306 - 0.4, 10000.0, 22.0, 191.43786190413417, -33.762112994320184, 215.9095747734917 - 0.45, 10000.0, 22.0, 185.24345666471316, -42.66887591141315, 205.1981392751936 - 0.5, 10000.0, 22.0, 178.62119555855728, -51.10877322411249, 193.82465734225792 - 0.55, 10000.0, 22.0, 171.6668002180942, -59.0507770876525, 181.9578370868452 - 0.6000000000000001, 10000.0, 22.0, 164.47599227575105, -66.46385965726756, 169.7663866211153 - 0.0, 10000.0, 24.0, 298.4077373257053, 55.78310285058157, 296.73450025270614 - 0.05, 10000.0, 24.0, 297.7955098991011, 44.60010025352282, 295.86746132244224 - 0.1, 10000.0, 24.0, 296.0054794790672, 33.35603573031435, 293.31894448309095 -0.15000000000000002, 10000.0, 24.0, 293.07628512869843, 22.12393620009085, 289.14024971037253 - 0.2, 10000.0, 24.0, 289.04656591109006, 10.976828581987025, 283.38267698000755 - 0.25, 10000.0, 24.0, 283.93097905671675, -0.01799541754855845, 276.03630602373545 -0.30000000000000004, 10000.0, 24.0, 277.84010912653343, -10.770303241323269, 267.3360975492184 -0.35000000000000003, 10000.0, 24.0, 270.858387313564, -21.18545021246471, 257.4718527999307 - 0.4, 10000.0, 24.0, 263.07893095206504, -31.209380983565694, 246.56912990017275 - 0.45, 10000.0, 24.0, 254.58110333235723, -40.76704962284608, 234.75305855811436 - 0.5, 10000.0, 24.0, 245.49059777927917, -49.82678320655194, 222.2147252656247 - 0.55, 10000.0, 24.0, 235.92152510904742, -58.34606555892252, 209.12872731865198 - 0.6000000000000001, 10000.0, 24.0, 225.98799613787543, -66.28238050419723, 195.66966201314276 - 0.0, 10000.0, 26.0, 379.592262674295, 63.74105939262133, 331.7265813686462 - 0.05, 10000.0, 26.0, 378.8794901009004, 52.004136226210626, 330.764887199243 - 0.1, 10000.0, 26.0, 376.5945205209351, 40.119802026483455, 327.95019121932717 -0.15000000000000002, 10000.0, 26.0, 372.8237148713034, 28.200516354038207, 323.34067317277834 - 0.2, 10000.0, 26.0, 367.6534340889106, 16.358738769473256, 316.9945128034764 - 0.25, 10000.0, 26.0, 361.1752709432818, 4.728897145738416, 308.8963364388153 -0.30000000000000004, 10000.0, 26.0, 353.4598908734643, -6.642453893623031, 299.3249840721318 -0.35000000000000003, 10000.0, 26.0, 344.5478626864316, -17.68817184475034, 288.5139348805509 - 0.4, 10000.0, 26.0, 334.6210690479276, -28.335592475651243, 276.5838976401067 - 0.45, 10000.0, 26.0, 323.84389666764486, -38.50703537857247, 263.67203320343805 - 0.5, 10000.0, 26.0, 312.30940222072275, -48.150406576935225, 249.96246451786175 - 0.55, 10000.0, 26.0, 300.12847489095356, -57.20721548636641, 235.62757400703498 - 0.6000000000000001, 10000.0, 26.0, 287.41200386212415, -65.61897152249328, 220.8397440946109 - 0.0, 10000.0, 28.0, 460.9326435115505, 71.69826782338465, 366.7424823272348 - 0.05, 10000.0, 28.0, 460.06663840167175, 59.43148362344777, 365.6940482171602 - 0.1, 10000.0, 28.0, 457.29987849091935, 46.9613635359373, 362.6029573559425 -0.15000000000000002, 10000.0, 28.0, 452.73014166406546, 34.42528060120226, 357.5520842162164 - 0.2, 10000.0, 28.0, 446.455205805883, 21.960607859591672, 350.6243032706161 - 0.25, 10000.0, 28.0, 438.5675039085393, 9.747848272637842, 341.8430803900315 -0.30000000000000004, 10000.0, 28.0, 429.180848534636, -2.2050148828587135, 331.4695158523436 -0.35000000000000003, 10000.0, 28.0, 418.37880478765385, -13.867601898639531, 319.7307494159347 - 0.4, 10000.0, 28.0, 406.3445480371842, -25.126599107544834, 306.75212851024713 - 0.45, 10000.0, 28.0, 393.24000860103206, -35.872734384979154, 292.6545146636078 - 0.5, 10000.0, 28.0, 379.2124867380253, -46.06350339499271, 277.6785053377349 - 0.55, 10000.0, 28.0, 364.41294022173537, -55.63970985447494, 262.0347640110011 - 0.6000000000000001, 10000.0, 28.0, 348.9923268257337, -64.54215748031504, 245.933954161778 - 0.0, 10000.0, 30.0, 542.3999999999999, 79.69999999999999, 401.8999999999999 - 0.05, 10000.0, 30.0, 541.3437499999989, 66.90625000000007, 400.76874999999876 - 0.1, 10000.0, 30.0, 538.0999999999964, 53.89999999999998, 397.3999999999963 -0.15000000000000002, 10000.0, 30.0, 532.7562499999925, 40.81874999999972, 391.906249999993 - 0.2, 10000.0, 30.0, 525.3999999999874, 27.79999999999931, 384.39999999998895 - 0.25, 10000.0, 30.0, 516.0812500000014, 15.024999999999606, 374.95624999999984 -0.30000000000000004, 10000.0, 30.0, 504.9999999999992, 2.500000000000044, 363.799999999997 -0.35000000000000003, 10000.0, 30.0, 492.3249999999981, -9.75624999999986, 351.13749999999555 - 0.4, 10000.0, 30.0, 478.1999999999971, -21.59999999999965, 337.0999999999943 - 0.45, 10000.0, 30.0, 462.7437499999946, -32.88750000000039, 321.78124999999517 - 0.5, 10000.0, 30.0, 446.1999999999915, -43.600000000000705, 305.4999999999922 - 0.55, 10000.0, 30.0, 428.781249999988, -53.68750000000114, 288.5187499999884 - 0.6000000000000001, 10000.0, 30.0, 410.69999999998345, -63.100000000001714, 271.099999999984 - 0.0, 10000.0, 32.0, 623.8673564884492, 87.79312167902685, 437.1616353619812 - 0.05, 10000.0, 32.0, 622.6495320493204, 74.44680624318065, 435.9301794466893 - 0.1, 10000.0, 32.0, 618.9064856024784, 60.947082297369235, 432.2947962398703 -0.15000000000000002, 10000.0, 32.0, 612.7478327788577, 47.39094164443689, 426.3691953115599 - 0.2, 10000.0, 32.0, 604.2831892093919, 33.87537608722789, 418.2670862317937 - 0.25, 10000.0, 32.0, 593.5948688446334, 20.493809483346332, 408.04237221301 -0.30000000000000004, 10000.0, 32.0, 580.8743923566734, 7.353937471357487, 395.9881818980231 -0.35000000000000003, 10000.0, 32.0, 566.2680131656444, -5.433940741629, 382.3814874938531 - 0.4, 10000.0, 32.0, 549.9938469781023, -17.784212003637695, 367.32466152032333 - 0.45, 10000.0, 32.0, 532.240856796559, -29.58186046266897, 350.9130289154483 - 0.5, 10000.0, 32.0, 513.2427541532833, -40.804795011686274, 333.44470463168744 - 0.55, 10000.0, 32.0, 493.22206344810786, -51.40769335741293, 315.167106117898 - 0.6000000000000001, 10000.0, 32.0, 472.4013090808645, -61.34523320657194, 296.32765082293344 - 0.0, 10000.0, 34.0, 705.1761765203894, 95.91109806251372, 472.33811386339136 - 0.05, 10000.0, 34.0, 703.7878325970806, 82.09610229418696, 471.02688061861676 - 0.1, 10000.0, 34.0, 699.5505460183465, 68.12830792909999, 467.1388949404843 -0.15000000000000002, 10000.0, 34.0, 692.5895930516666, 54.093200577070704, 460.7945016368411 - 0.2, 10000.0, 34.0, 683.0302499645214, 40.07626584791721, 452.11404551553386 - 0.25, 10000.0, 34.0, 670.9758642939889, 26.137779235456136, 441.15108677387605 -0.30000000000000004, 10000.0, 34.0, 656.6174984987471, 12.438856697506449, 428.22632405130975 -0.35000000000000003, 10000.0, 34.0, 640.0836816369039, -0.8514174730634849, 413.6390566269018 - 0.4, 10000.0, 34.0, 621.6653614472524, -13.696672787595393, 397.50704277910387 - 0.45, 10000.0, 34.0, 601.6232677058563, -26.026744997229336, 379.9469444582552 - 0.5, 10000.0, 34.0, 580.1765833590431, -37.77393108970019, 361.2613499277654 - 0.55, 10000.0, 34.0, 557.5548780605836, -48.86991274359404, 341.70636587278085 - 0.6000000000000001, 10000.0, 34.0, 533.9877214642464, -59.246371637497006, 321.5380989784461 - 0.0, 10000.0, 36.0, 786.3449214663212, 104.04867509983553, 507.40835379720977 - 0.05, 10000.0, 36.0, 784.7741324040106, 89.86253194345399, 506.04105758798715 - 0.1, 10000.0, 36.0, 780.0582550469284, 75.43883562780573, 501.9143612414136 -0.15000000000000002, 10000.0, 36.0, 772.3211936560936, 60.89776410941515, 495.16599828999114 - 0.2, 10000.0, 36.0, 761.6868524925258, 46.35949534480658, 485.9337022662221 - 0.25, 10000.0, 36.0, 748.2413963308037, 31.945236878000067, 474.3075062477438 -0.30000000000000004, 10000.0, 36.0, 732.2219478912507, 17.772077903027597, 460.56824513164906 -0.35000000000000003, 10000.0, 36.0, 713.7908618129027, 3.983029817293019, 444.9639300339278 - 0.4, 10000.0, 36.0, 693.2586071141652, -9.378466445316517, 427.68306537556805 - 0.45, 10000.0, 36.0, 670.9062025593903, -22.265482202125767, 408.8773149236623 - 0.5, 10000.0, 36.0, 646.984353549835, -34.54546930209254, 388.9052117558984 - 0.55, 10000.0, 36.0, 621.7513438275604, -46.10728446126643, 368.073571622327 - 0.6000000000000001, 10000.0, 36.0, 595.4654571346147, -56.83978439569696, 346.689210272994 - 0.0, 10000.0, 38.0, 867.9378187011903, 112.32837890238524, 542.760840860747 - 0.05, 10000.0, 38.0, 866.2252490501229, 97.65580625875053, 541.2856624558318 - 0.1, 10000.0, 38.0, 861.0363092752301, 82.77774917823987, 536.9211960837143 -0.15000000000000002, 10000.0, 38.0, 852.5037482200312, 67.79788746247006, 529.7827338075305 - 0.2, 10000.0, 38.0, 840.7603147280462, 52.81990091305788, 519.9855676904135 - 0.25, 10000.0, 38.0, 825.8825720666854, 37.94453919098525, 507.5577049623406 -0.30000000000000004, 10000.0, 38.0, 808.1718258078564, 23.284272519775083, 492.87629218596516 -0.35000000000000003, 10000.0, 38.0, 787.8647455127319, 8.94807122258982, 476.2699710533671 - 0.4, 10000.0, 38.0, 765.231802481217, -4.9528153385087546, 457.91226340648876 - 0.45, 10000.0, 38.0, 740.5020516279681, -18.28645907621894, 437.9815347823834 - 0.5, 10000.0, 38.0, 714.0364116698603, -31.0059258431, 416.79189578778414 - 0.55, 10000.0, 38.0, 686.1628353732483, -43.04303300674769, 394.62352076201654 - 0.6000000000000001, 10000.0, 38.0, 657.2092755044714, -54.32959793475694, 371.7565840444006 - 0.0, 10000.0, 40.0, 949.2000000000012, 120.6000000000001, 578.0000000000005 - 0.05, 10000.0, 40.0, 947.393750000001, 105.58125000000003, 576.4437500000001 - 0.1, 10000.0, 40.0, 941.6999999999977, 90.2999999999997, 571.8000000000003 -0.15000000000000002, 10000.0, 40.0, 932.306249999991, 74.86874999999922, 564.2062500000003 - 0.2, 10000.0, 40.0, 919.3999999999812, 59.39999999999863, 553.8000000000008 - 0.25, 10000.0, 40.0, 903.1437500000003, 43.98125000000033, 540.6374999999936 -0.30000000000000004, 10000.0, 40.0, 883.7999999999946, 28.800000000000107, 525.0999999999999 -0.35000000000000003, 10000.0, 40.0, 861.5687499999889, 14.08125000000018, 507.5249999999989 - 0.4, 10000.0, 40.0, 836.7999999999811, -0.19999999999971196, 488.0999999999974 - 0.45, 10000.0, 40.0, 809.793750000005, -14.043749999999896, 467.01249999999885 - 0.5, 10000.0, 40.0, 780.9000000000079, -27.29999999999983, 444.59999999999735 - 0.55, 10000.0, 40.0, 750.4562500000121, -39.85624999999984, 421.1624999999962 - 0.6000000000000001, 10000.0, 40.0, 718.8000000000187, -51.59999999999985, 396.9999999999953 - 0.0, 10000.0, 42.0, 1030.4718662707141, 129.03314756355084, 613.6707519639976 - 0.05, 10000.0, 42.0, 1028.4495705373695, 113.60679542169338, 611.9641073380755 - 0.1, 10000.0, 42.0, 1022.2709377597806, 97.91234904336592, 607.024698086731 -0.15000000000000002, 10000.0, 42.0, 1012.1134516891038, 82.05875689276029, 598.9854513238251 - 0.2, 10000.0, 42.0, 998.1545960764956, 66.15496743406821, 587.9792941632184 - 0.25, 10000.0, 42.0, 980.5326601542996, 50.28386134682823, 574.0336929462507 -0.30000000000000004, 10000.0, 42.0, 959.5427112300989, 34.63259044918947, 557.5979571043495 -0.35000000000000003, 10000.0, 42.0, 935.3926706006805, 19.40329030558224, 539.077530009985 - 0.4, 10000.0, 42.0, 908.4822655308183, 4.6338903567011736, 518.6314761814623 - 0.45, 10000.0, 42.0, 879.1621691987244, -9.583339183729564, 496.4427169204421 - 0.5, 10000.0, 42.0, 847.7874651608543, -23.20928507036719, 472.84512524934024 - 0.55, 10000.0, 42.0, 814.7121343790773, -36.19154481577377, 448.13483626040255 - 0.6000000000000001, 10000.0, 42.0, 780.2901578152726, -48.47771593251124, 422.60798504586734 - 0.0, 10000.0, 44.0, 1112.0274746761775, 137.8596603509804, 650.078451841095 - 0.05, 10000.0, 44.0, 1109.8396287132352, 122.09462421901726, 648.3044392065182 - 0.1, 10000.0, 44.0, 1103.187398401414, 105.97942555900008, 643.1700462128388 -0.15000000000000002, 10000.0, 44.0, 1092.2457733984113, 89.66239009784267, 634.7854550726312 - 0.2, 10000.0, 44.0, 1077.189743361927, 73.29184356245894, 623.2608479984702 - 0.25, 10000.0, 44.0, 1058.1256088990217, 57.0381410698487, 608.5797891089506 -0.30000000000000004, 10000.0, 44.0, 1035.4344268193452, 40.98352017666805, 591.2323148986086 -0.35000000000000003, 10000.0, 44.0, 1009.4118478417497, 25.223374930911103, 571.6264804102105 - 0.4, 10000.0, 44.0, 980.4203908458715, 9.888590975566252, 549.9917941177898 - 0.45, 10000.0, 44.0, 948.7834336989706, -4.876444910474831, 526.5898057641426 - 0.5, 10000.0, 44.0, 914.9140501570279, -19.01684208692818, 501.73244658573776 - 0.55, 10000.0, 44.0, 879.2028900038675, -32.45533587885753, 475.71905244562714 - 0.6000000000000001, 10000.0, 44.0, 842.0406030233034, -45.114661611326724, 448.8489592068627 - 0.0, 10000.0, 46.0, 1193.172525323824, 146.7760412849769, 686.6415978187591 - 0.05, 10000.0, 46.0, 1190.8202146644212, 130.62294394313165, 684.728995994116 - 0.1, 10000.0, 46.0, 1183.6677203625075, 114.11786721687652, 679.3013570590716 -0.15000000000000002, 10000.0, 46.0, 1171.9132816788226, 97.3976114127839, 670.4771524585472 - 0.2, 10000.0, 46.0, 1155.7551378741064, 80.59897683742638, 658.3748536374643 - 0.25, 10000.0, 46.0, 1135.336891100991, 63.86016948777727, 642.9883365642697 -0.30000000000000004, 10000.0, 46.0, 1111.0206919445866, 47.313772599208455, 624.809859113339 -0.35000000000000003, 10000.0, 46.0, 1083.0700420037438, 31.114219654278195, 604.2716343586657 - 0.4, 10000.0, 46.0, 1051.9244903902015, 15.334165908410354, 581.5476726700344 - 0.45, 10000.0, 46.0, 1017.9674622151184, 0.053501138082605704, 556.7869094877462 - 0.5, 10000.0, 46.0, 981.6308310790541, -14.595044737309557, 530.4967826742275 - 0.55, 10000.0, 46.0, 943.3343584602096, -28.491951834101027, 503.09510448637053 - 0.6000000000000001, 10000.0, 46.0, 903.4978058367905, -41.51770026862626, 474.9996871810691 - 0.0, 10000.0, 48.0, 1274.7281337292843, 155.88672236770347, 723.7443824951858 - 0.05, 10000.0, 48.0, 1272.2736188945821, 139.3374187460312, 721.7392524946854 - 0.1, 10000.0, 48.0, 1264.632219169615, 122.42423396775328, 716.0008355935481 -0.15000000000000002, 10000.0, 48.0, 1252.0423050406976, 105.2852599571292, 706.6737696732877 - 0.2, 10000.0, 48.0, 1234.7422469941423, 88.05858863841858, 693.9026926154198 - 0.25, 10000.0, 48.0, 1212.9325035048755, 70.88211462779427, 677.7018395608699 -0.30000000000000004, 10000.0, 48.0, 1186.9651810933585, 53.89452177377538, 658.6070566129199 -0.35000000000000003, 10000.0, 48.0, 1157.0978876746556, 37.259633205909346, 637.1275359830613 - 0.4, 10000.0, 48.0, 1123.8145775397916, 21.039925697286005, 613.357474487685 - 0.45, 10000.0, 48.0, 1087.528876515135, 5.311716550617147, 587.3690053278294 - 0.5, 10000.0, 48.0, 1048.7093779097813, -9.802692693415192, 559.7375115610462 - 0.55, 10000.0, 48.0, 1007.8109331621979, -24.192496553620604, 530.9125637807656 - 0.6000000000000001, 10000.0, 48.0, 965.2883937108297, -37.746889548809044, 501.34373258041546 - 0.0, 10000.0, 50.0, 1355.9999999999957, 164.9999999999996, 761.0000000000003 - 0.05, 10000.0, 50.0, 1353.3187500000085, 148.07500000000005, 758.9375000000003 - 0.1, 10000.0, 50.0, 1345.200000000021, 130.80000000000038, 752.8999999999995 -0.15000000000000002, 10000.0, 50.0, 1331.85625000003, 113.30000000000051, 743.0624999999977 - 0.2, 10000.0, 50.0, 1313.5000000000327, 95.70000000000043, 729.5999999999939 - 0.25, 10000.0, 50.0, 1290.2624999999953, 78.1249999999998, 712.5625000000014 -0.30000000000000004, 10000.0, 50.0, 1262.5999999999826, 60.699999999998745, 692.4999999999974 -0.35000000000000003, 10000.0, 50.0, 1230.862499999974, 43.5437499999984, 669.9249999999976 - 0.4, 10000.0, 50.0, 1195.4999999999668, 26.799999999998217, 644.9999999999976 - 0.45, 10000.0, 50.0, 1156.9062500000261, 10.637499999999298, 617.9187499999853 - 0.5, 10000.0, 50.0, 1115.6000000000454, -4.9000000000008095, 589.0999999999757 - 0.55, 10000.0, 50.0, 1072.0687500000713, -19.737500000000864, 558.9062499999645 - 0.6000000000000001, 10000.0, 50.0, 1026.800000000102, -33.80000000000084, 527.6999999999517 - 0.0, 15000.0, 20.0, 179.99999999999937, 43.40000000000012, 262.40000000000026 - 0.05, 15000.0, 20.0, 166.6749999999996, 32.550000000000075, 257.27500000000015 - 0.1, 15000.0, 20.0, 157.99999999999977, 22.000000000000032, 252.40000000000003 -0.15000000000000002, 15000.0, 20.0, 152.9999999999999, 11.750000000000009, 247.52499999999998 - 0.2, 15000.0, 20.0, 150.69999999999996, 1.7999999999999998, 242.39999999999998 - 0.25, 15000.0, 20.0, 150.125, -7.850000000000001, 236.77499999999998 -0.30000000000000004, 15000.0, 20.0, 150.30000000000007, -17.20000000000001, 230.40000000000003 -0.35000000000000003, 15000.0, 20.0, 150.2500000000001, -26.250000000000007, 223.02500000000006 - 0.4, 15000.0, 20.0, 149.00000000000017, -35.000000000000014, 214.40000000000015 - 0.45, 15000.0, 20.0, 144.61249999999993, -43.500000000000036, 203.92499999999993 - 0.5, 15000.0, 20.0, 138.99999999999994, -51.60000000000007, 192.39999999999995 - 0.55, 15000.0, 20.0, 133.1124999999999, -59.20000000000012, 180.27499999999998 - 0.6000000000000001, 15000.0, 20.0, 127.89999999999986, -66.20000000000014, 167.99999999999994 - 0.0, 15000.0, 22.0, 284.65574116971146, 51.00643166036347, 305.37616738213507 - 0.05, 15000.0, 22.0, 264.76707507429256, 39.94701809790612, 297.0847962263615 - 0.1, 15000.0, 22.0, 251.89528665240638, 29.03981328912609, 290.1414794722727 -0.15000000000000002, 15000.0, 22.0, 244.5491367285015, 18.30545798764724, 284.0604192766932 - 0.2, 15000.0, 22.0, 241.23738612702624, 7.76459294709338, 278.35581779644804 - 0.25, 15000.0, 22.0, 240.46879567242885, -2.56214107891164, 272.5418771883617 -0.30000000000000004, 15000.0, 22.0, 240.75212618915796, -12.654103336744011, 266.1327996092587 -0.35000000000000003, 15000.0, 22.0, 240.59613850166153, -22.490653072779864, 258.642787215964 - 0.4, 15000.0, 22.0, 238.5095934343882, -32.051149533395396, 249.58604216530227 - 0.45, 15000.0, 22.0, 231.51062160118704, -41.369618872827495, 237.84983489812356 - 0.5, 15000.0, 22.0, 222.5798744583053, -50.26141961387011, 224.82916271917583 - 0.55, 15000.0, 22.0, 213.20737325139166, -58.59657718717795, 211.2920912172323 - 0.6000000000000001, 15000.0, 22.0, 204.88313922609464, -66.24511702340561, 198.006685981066 - 0.0, 15000.0, 24.0, 391.4473297741786, 60.222675019505985, 348.477362610168 - 0.05, 15000.0, 24.0, 364.00920629060687, 48.277025761880395, 337.0364417417052 - 0.1, 15000.0, 24.0, 346.2474630559779, 36.56565426624772, 328.0182530065287 -0.15000000000000002, 15000.0, 24.0, 336.1069894960276, 25.092144429686773, 320.7091564965619 - 0.2, 15000.0, 24.0, 331.5326750364909, 13.86008014927639, 314.39551230372865 - 0.25, 15000.0, 24.0, 330.46940910310366, 2.873045322095377, 308.3636805199522 -0.30000000000000004, 15000.0, 24.0, 330.8620811216015, -7.865376154777471, 301.9000212371565 -0.35000000000000003, 15000.0, 24.0, 330.65558051771944, -18.35160038426331, 294.29089454726477 - 0.4, 15000.0, 24.0, 327.7947967171934, -28.582043469283356, 284.82266054220094 - 0.45, 15000.0, 24.0, 318.1708085472173, -38.6316936998001, 271.9275940893467 - 0.5, 15000.0, 24.0, 305.88993722915484, -48.26125061761084, 257.454310954252 - 0.55, 15000.0, 24.0, 293.0046933858324, -57.309985951554154, 242.39734167792622 - 0.6000000000000001, 15000.0, 24.0, 281.56758764007395, -65.61717143046864, 227.75121680137804 - 0.0, 15000.0, 26.0, 499.3110477937902, 70.3357025484668, 392.1004741471343 - 0.05, 15000.0, 26.0, 463.8552999697752, 57.156649376901626, 377.42256414386895 - 0.1, 15000.0, 26.0, 440.8719961333468, 44.4215885988063, 366.26428680464903 -0.15000000000000002, 15000.0, 26.0, 427.720273899303, 32.095476877902705, 357.6808090780843 - 0.2, 15000.0, 26.0, 421.75927088244265, 20.143270877912713, 350.7272979127853 - 0.25, 15000.0, 26.0, 420.34812469756406, 8.529927262558209, 344.4589202573619 -0.30000000000000004, 15000.0, 26.0, 420.84597295946594, -2.7795973044389353, 337.93084306042454 -0.35000000000000003, 15000.0, 26.0, 420.61195328294656, -13.820346159356822, 330.19823327058316 - 0.4, 15000.0, 26.0, 417.0052032828045, -24.627362638473585, 320.31625783644796 - 0.45, 15000.0, 26.0, 404.7531846926543, -35.352084090359014, 306.27168583150865 - 0.5, 15000.0, 26.0, 389.1100627708528, -45.68037181441654, 290.32487782974096 - 0.55, 15000.0, 26.0, 372.6983268945787, -55.41448112234143, 273.667796530005 - 0.6000000000000001, 15000.0, 26.0, 358.14046644100813, -64.35666732582887, 257.4924046311585 - 0.0, 15000.0, 28.0, 606.8261344259578, 80.42838335228451, 437.065149090311 - 0.05, 15000.0, 28.0, 563.588153804952, 66.09981842658942, 418.81168624064566 - 0.1, 15000.0, 28.0, 535.5406821657929, 52.419096371725736, 405.2966775001897 -0.15000000000000002, 15000.0, 28.0, 519.4709755025074, 39.3119668181973, 395.3180501039725 - 0.2, 15000.0, 28.0, 512.1662898091223, 26.70417939650796, 387.6737312870242 - 0.25, 15000.0, 28.0, 510.4138810796641, 14.521483737161528, 381.16164828437456 -0.30000000000000004, 15000.0, 28.0, 511.0010053081593, 2.689629470661824, 374.57972833105333 -0.35000000000000003, 15000.0, 28.0, 510.71491848863496, -8.86563377248728, 366.7258986620905 - 0.4, 15000.0, 28.0, 506.3428766151172, -20.21855636178199, 356.39808651251553 - 0.45, 15000.0, 28.0, 491.4775819275594, -31.606231146573773, 341.06414767274504 - 0.5, 15000.0, 28.0, 472.48995168218664, -42.614381056792055, 323.51222371165596 - 0.55, 15000.0, 28.0, 452.5563493811324, -52.99157150222103, 305.20038475352055 - 0.6000000000000001, 15000.0, 28.0, 434.85313852654014, -62.486367892645156, 287.58670092260644 - 0.0, 15000.0, 30.0, 713.9999999999905, 90.39999999999948, 482.5000000000072 - 0.05, 15000.0, 30.0, 663.1749999999932, 75.0312499999997, 460.66875000000465 - 0.1, 15000.0, 30.0, 630.1999999999954, 60.49999999999986, 444.80000000000257 -0.15000000000000002, 15000.0, 30.0, 611.2999999999973, 46.693749999999945, 433.43125000000094 - 0.2, 15000.0, 30.0, 602.6999999999998, 33.49999999999998, 425.09999999999957 - 0.25, 15000.0, 30.0, 600.6250000000024, 20.80624999999996, 418.34374999999835 -0.30000000000000004, 15000.0, 30.0, 601.3000000000058, 8.499999999999867, 411.69999999999715 -0.35000000000000003, 15000.0, 30.0, 600.9500000000097, -3.5312500000002545, 403.7062499999959 - 0.4, 15000.0, 30.0, 595.800000000015, -15.400000000000421, 392.89999999999446 - 0.45, 15000.0, 30.0, 578.3249999999931, -27.431249999999604, 376.2125000000038 - 0.5, 15000.0, 30.0, 555.9999999999884, -39.09999999999937, 357.0000000000055 - 0.55, 15000.0, 30.0, 532.5499999999821, -50.09374999999913, 337.0125000000077 - 0.6000000000000001, 15000.0, 30.0, 511.69999999997395, -60.099999999998914, 318.00000000001023 - 0.0, 15000.0, 32.0, 821.6728132996476, 100.48209843033415, 526.0189885356938 - 0.05, 15000.0, 32.0, 762.9942957576367, 84.01811377291833, 501.528203080642 - 0.1, 15000.0, 32.0, 724.9229587682233, 68.62138038346656, 483.9084924633979 -0.15000000000000002, 15000.0, 32.0, 703.1029630445021, 54.13344800838597, 471.4969434102928 - 0.2, 15000.0, 32.0, 693.1784692995677, 40.39586639408382, 462.6306426476578 - 0.25, 15000.0, 32.0, 690.793638246515, 27.25018528696728, 455.64667690182404 -0.30000000000000004, 15000.0, 32.0, 691.5926305984387, 14.537954433443538, 448.8821328991228 -0.35000000000000003, 15000.0, 32.0, 691.2196070684338, 2.1007235799198285, 440.67409736588536 - 0.4, 15000.0, 32.0, 685.3187283695942, -10.219957527196675, 429.35965702844265 - 0.45, 15000.0, 32.0, 665.2040160764675, -22.842437373449187, 411.480038444082 - 0.5, 15000.0, 32.0, 639.5100483178073, -35.14547151657943, 390.7599088462709 - 0.55, 15000.0, 32.0, 612.5412640838349, -46.7677137462798, 369.1280752994334 - 0.6000000000000001, 15000.0, 32.0, 588.6021023647625, -57.34781785224255, 348.513344867993 - 0.0, 15000.0, 34.0, 928.2449193207835, 110.27717152559309, 570.7790228551557 - 0.05, 15000.0, 34.0, 862.1173079178186, 92.95275890578564, 543.2111410314259 - 0.1, 15000.0, 34.0, 819.2280640736507, 76.84831624171979, 523.541034115306 -0.15000000000000002, 15000.0, 34.0, 794.6618731186074, 61.77433206296619, 509.88577166442485 - 0.2, 15000.0, 34.0, 783.5034203830149, 47.54129489909576, 500.36242323641073 - 0.25, 15000.0, 34.0, 780.8373911972001, 33.9596932796793, 493.0880583888925 -0.30000000000000004, 15000.0, 34.0, 781.7484708914898, 20.84001573428763, 486.1797466794986 -0.35000000000000003, 15000.0, 34.0, 781.3213447962103, 7.992750792491573, 477.7545576658578 - 0.4, 15000.0, 34.0, 774.6406982416886, -4.771613016138047, 465.9295609055989 - 0.45, 15000.0, 34.0, 751.9002550394698, -17.929490581396443, 446.81140494200383 - 0.5, 15000.0, 34.0, 722.8575850762174, -30.809683115614018, 424.5484223757501 - 0.55, 15000.0, 34.0, 692.3792967198003, -43.02789525048672, 401.2785247931729 - 0.6000000000000001, 15000.0, 34.0, 665.3319983380933, -54.19983161771073, 379.1396237806055 - 0.0, 15000.0, 36.0, 1033.731200792566, 120.1885820105158, 617.9788264380061 - 0.05, 15000.0, 36.0, 960.5826328605089, 102.0844911486309, 586.3649018998445 - 0.1, 15000.0, 36.0, 913.1639744252461, 85.32366702567505, 563.9909596803922 -0.15000000000000002, 15000.0, 36.0, 886.0249762010593, 69.69168007494102, 548.6970684443547 - 0.2, 15000.0, 36.0, 873.7153889022288, 54.97410072972176, 538.3232968564364 - 0.25, 15000.0, 36.0, 870.784963243036, 40.956499423310134, 530.7097135813431 -0.30000000000000004, 15000.0, 36.0, 871.783449937762, 27.424446588998993, 523.6963872837795 -0.35000000000000003, 15000.0, 36.0, 871.2605997006877, 14.163512660081263, 515.1233866284509 - 0.4, 15000.0, 36.0, 863.7661632460944, 0.9592680698497875, 502.83078028006275 - 0.45, 15000.0, 36.0, 838.4236717288717, -12.709867658331651, 482.36248147959486 - 0.5, 15000.0, 36.0, 806.0615345414502, -26.136871361381356, 458.4470251629399 - 0.55, 15000.0, 36.0, 772.0819415168344, -38.92187078614559, 433.5167908422698 - 0.6000000000000001, 15000.0, 36.0, 741.8870824880456, -50.664993679471216, 410.0041580297535 - 0.0, 15000.0, 38.0, 1142.050365098131, 133.07017333449144, 666.0671550654004 - 0.05, 15000.0, 38.0, 1060.8532794588098, 112.83767826084205, 629.9253508705766 - 0.1, 15000.0, 38.0, 1008.1957168483676, 94.55679822068791, 604.6149346586252 -0.15000000000000002, 15000.0, 38.0, 978.0388624866216, 77.89641490667347, 587.6474826793412 - 0.2, 15000.0, 38.0, 964.3439015933882, 62.52541001144331, 576.5345711825198 - 0.25, 15000.0, 38.0, 961.0720193884843, 48.11266522764203, 568.7877764179559 -0.30000000000000004, 15000.0, 38.0, 962.1844010917267, 34.32706224791418, 561.9186746354447 -0.35000000000000003, 15000.0, 38.0, 961.6422319229317, 20.837482764904347, 553.4388420847811 - 0.4, 15000.0, 38.0, 953.4066971019166, 7.312808471257115, 540.8598550157601 - 0.45, 15000.0, 38.0, 925.4300775794188, -7.014100469240751, 519.0721779329155 - 0.5, 15000.0, 38.0, 889.7002713825287, -21.166297777373185, 493.4507223218307 - 0.55, 15000.0, 38.0, 852.196272269304, -34.60285870278419, 466.7492879228398 - 0.6000000000000001, 15000.0, 38.0, 818.8970739977786, -46.78285849511661, 441.7216744762719 - 0.0, 15000.0, 40.0, 1249.5000000000048, 143.8999999999997, 710.3999999999871 - 0.05, 15000.0, 40.0, 1160.5187500000027, 122.6624999999998, 671.7749999999934 - 0.1, 15000.0, 40.0, 1102.8000000000009, 103.59999999999988, 644.8999999999976 -0.15000000000000002, 15000.0, 40.0, 1069.7312500000003, 86.33749999999999, 627.0750000000005 - 0.2, 15000.0, 40.0, 1054.6999999999996, 70.50000000000007, 615.6000000000014 - 0.25, 15000.0, 40.0, 1051.0937499999982, 55.71250000000017, 607.775000000001 -0.30000000000000004, 15000.0, 40.0, 1052.2999999999963, 41.60000000000022, 600.8999999999988 -0.35000000000000003, 15000.0, 40.0, 1051.706249999993, 27.78750000000025, 592.2749999999954 - 0.4, 15000.0, 40.0, 1042.699999999987, 13.900000000000242, 579.1999999999907 - 0.45, 15000.0, 40.0, 1012.0937500000001, -0.9062500000002491, 556.1500000000025 - 0.5, 15000.0, 40.0, 973.0000000000025, -15.600000000000474, 528.9000000000053 - 0.55, 15000.0, 40.0, 931.9562500000073, -29.618750000000798, 500.4000000000101 - 0.6000000000000001, 15000.0, 40.0, 895.5000000000148, -42.4000000000012, 473.6000000000177 - 0.0, 15000.0, 42.0, 1356.108635155606, 154.57650847442238, 760.0792946701766 - 0.05, 15000.0, 42.0, 1259.6675952027867, 132.4224812000879, 717.0897518037798 - 0.1, 15000.0, 42.0, 1197.1074280484934, 112.67158759654274, 687.2948932873404 -0.15000000000000002, 15000.0, 42.0, 1161.2612348999485, 94.89780631345592, 667.6984331353565 - 0.2, 15000.0, 42.0, 1144.9621169643779, 78.67511600049656, 655.3040853623262 - 0.25, 15000.0, 42.0, 1141.043175449004, 63.57749530733375, 647.115563982748 -0.30000000000000004, 15000.0, 42.0, 1142.3375115610527, 49.178922883636496, 640.1365830111193 -0.35000000000000003, 15000.0, 42.0, 1141.6782265077463, 35.05337737907395, 631.3708564619387 - 0.4, 15000.0, 42.0, 1131.8984214963102, 20.774837443315153, 617.8220983497048 - 0.45, 15000.0, 42.0, 1098.7072016817867, 5.376334651602156, 593.3642989143816 - 0.5, 15000.0, 42.0, 1056.3096564279433, -9.945311123113388, 564.3903434940604 - 0.55, 15000.0, 42.0, 1011.7868790463643, -24.534227082305303, 534.163393652293 - 0.6000000000000001, 15000.0, 42.0, 972.2199628486371, -37.734540427448195, 505.9466109526338 - 0.0, 15000.0, 44.0, 1462.372361318423, 167.29993440440933, 808.001466676733 - 0.05, 15000.0, 44.0, 1358.6890429786483, 143.50378437349505, 761.4954271927585 - 0.1, 15000.0, 44.0, 1291.4684605446746, 122.55949586605477, 729.4002795251845 -0.15000000000000002, 15000.0, 44.0, 1252.9901796480615, 103.95366076182614, 708.4555774713446 - 0.2, 15000.0, 44.0, 1235.5337659203694, 87.17287094054703, 695.4008748285707 - 0.25, 15000.0, 44.0, 1231.378784993159, 71.70371828195513, 686.9757253941967 -0.30000000000000004, 15000.0, 44.0, 1232.804802497989, 57.032794665788224, 679.919682965555 -0.35000000000000003, 15000.0, 44.0, 1232.0913840664214, 42.646691971784115, 670.972301339979 - 0.4, 15000.0, 44.0, 1221.518095330015, 28.03200207968054, 656.8731343148014 - 0.45, 15000.0, 44.0, 1185.6804633349752, 12.048014533248903, 630.9504205897645 - 0.5, 15000.0, 44.0, 1139.910169468947, -3.9367717798738697, 600.1776592549899 - 0.55, 15000.0, 44.0, 1091.8548565342292, -19.18116030801693, 568.1170343030221 - 0.6000000000000001, 15000.0, 44.0, 1049.1621673331163, -32.94395449950951, 538.3307297264 - 0.0, 15000.0, 46.0, 1570.2812015994375, 179.83428390794188, 855.8179916144857 - 0.05, 15000.0, 46.0, 1458.5487643085344, 154.57728335322992, 805.8073005305024 - 0.1, 15000.0, 46.0, 1386.0827270946043, 132.55302349006405, 771.4170629105467 -0.15000000000000002, 15000.0, 46.0, 1344.5759649441209, 113.17491243870668, 749.1266441587933 - 0.2, 15000.0, 46.0, 1325.7213528435593, 95.85635831942002, 735.4154096794163 - 0.25, 15000.0, 46.0, 1321.211765779393, 80.01076925246633, 726.7627248765904 -0.30000000000000004, 15000.0, 46.0, 1322.7400787380966, 65.05155335810784, 719.6479551544905 -0.35000000000000003, 15000.0, 46.0, 1321.9991667061436, 50.39211875660686, 710.5504659172915 - 0.4, 15000.0, 46.0, 1310.6819046700086, 35.44587356822566, 695.9496225691671 - 0.45, 15000.0, 46.0, 1272.219536665032, 18.92947991045611, 668.6631943498842 - 0.5, 15000.0, 46.0, 1223.0898305310584, 2.3465839118687164, 636.1553351568548 - 0.55, 15000.0, 46.0, 1171.5089231567563, -13.495914301738923, 602.2286027230924 - 0.6000000000000001, 15000.0, 46.0, 1125.692951430813, -27.791114604567827, 570.6855547816059 - 0.0, 15000.0, 48.0, 1678.0807806074781, 192.88811511461017, 905.5689873915544 - 0.05, 15000.0, 48.0, 1558.5088502171918, 165.99655871341054, 851.5505799756775 - 0.1, 15000.0, 48.0, 1480.9525536098154, 142.78644381052325, 814.4899719414996 -0.15000000000000002, 15000.0, 48.0, 1436.5254353406524, 122.58556752905803, 790.5871168741983 - 0.2, 15000.0, 48.0, 1416.3410399650074, 104.72172699212457, 776.0419683589513 - 0.25, 15000.0, 48.0, 1411.5129120381855, 88.52271932283257, 767.0544799809354 -0.30000000000000004, 15000.0, 48.0, 1413.1545961154916, 73.3163416442917, 759.8246053253279 -0.35000000000000003, 15000.0, 48.0, 1412.3796367522302, 58.430391079611724, 750.5522979773064 - 0.4, 15000.0, 48.0, 1400.301578503705, 43.19266475190229, 735.4375115220475 - 0.45, 15000.0, 48.0, 1359.1927983182168, 26.15656911835743, 706.7391828432089 - 0.5, 15000.0, 48.0, 1306.6903435720626, 8.973073299835136, 672.4803156305544 - 0.55, 15000.0, 48.0, 1251.5900940345084, -7.481244248720962, 636.7428968723442 - 0.6000000000000001, 15000.0, 48.0, 1202.687929474832, -22.329805072367915, 603.608913556829 - 0.0, 15000.0, 50.0, 1782.5000000000434, 205.8000000000012, 958.1000000000355 - 0.05, 15000.0, 50.0, 1656.3625000000236, 177.33125000000123, 898.9812500000226 - 0.1, 15000.0, 50.0, 1574.600000000011, 153.000000000001, 858.5000000000128 -0.15000000000000002, 15000.0, 50.0, 1527.812500000004, 132.0437500000006, 832.5187500000055 - 0.2, 15000.0, 50.0, 1506.6000000000033, 113.70000000000017, 816.9000000000001 - 0.25, 15000.0, 50.0, 1501.5625000000073, 97.20624999999961, 807.5062499999957 -0.30000000000000004, 15000.0, 50.0, 1503.3000000000156, 81.79999999999899, 800.1999999999913 -0.35000000000000003, 15000.0, 50.0, 1502.412500000027, 66.71874999999838, 790.8437499999861 - 0.4, 15000.0, 50.0, 1489.5000000000416, 51.19999999999774, 775.2999999999796 - 0.45, 15000.0, 50.0, 1445.806250000001, 33.61250000000031, 745.1562500000122 - 0.5, 15000.0, 50.0, 1390.0000000000027, 15.800000000000775, 709.1000000000264 - 0.55, 15000.0, 50.0, 1331.3937500000022, -1.2624999999984663, 671.5437500000455 - 0.6000000000000001, 15000.0, 50.0, 1279.3000000000002, -16.599999999997365, 636.9000000000688 - 0.0, 17500.0, 20.0, 128.89999999999986, 39.80000000000008, 262.3999999999998 - 0.05, 17500.0, 20.0, 138.12499999999991, 30.456250000000054, 264.4812499999999 - 0.1, 17500.0, 20.0, 145.19999999999996, 21.000000000000025, 264.4999999999999 -0.15000000000000002, 17500.0, 20.0, 150.37499999999997, 11.493750000000006, 262.6187499999999 - 0.2, 17500.0, 20.0, 153.89999999999998, 1.9999999999999998, 258.99999999999994 - 0.25, 17500.0, 20.0, 156.02499999999995, -7.418749999999999, 253.80624999999998 -0.30000000000000004, 17500.0, 20.0, 156.99999999999997, -16.700000000000003, 247.19999999999996 -0.35000000000000003, 17500.0, 20.0, 157.07499999999996, -25.781249999999993, 239.34374999999994 - 0.4, 17500.0, 20.0, 156.49999999999994, -34.59999999999998, 230.39999999999992 - 0.45, 17500.0, 20.0, 156.14375000000004, -43.08750000000005, 220.70625000000015 - 0.5, 17500.0, 20.0, 154.4000000000001, -51.200000000000074, 209.90000000000026 - 0.55, 17500.0, 20.0, 150.28125000000017, -58.887500000000124, 197.79375000000036 - 0.6000000000000001, 17500.0, 20.0, 142.80000000000024, -66.10000000000016, 184.2000000000004 - 0.0, 17500.0, 22.0, 204.79762948163938, 49.16400580903924, 288.2436355793072 - 0.05, 17500.0, 22.0, 220.15919338214866, 39.0309233954866, 292.8929214320115 - 0.1, 17500.0, 22.0, 231.92534620859192, 28.779263484188245, 294.8456359019062 -0.15000000000000002, 17500.0, 22.0, 240.51861508158652, 18.475366490265973, 294.34774615470485 - 0.2, 17500.0, 22.0, 246.3615271217497, 8.185572828841565, 291.64521935612004 - 0.25, 17500.0, 22.0, 249.87660944969872, -2.0237770849632124, 286.98402267186526 -0.30000000000000004, 17500.0, 22.0, 251.48638918605099, -12.08634283602659, 280.6101232676535 -0.35000000000000003, 17500.0, 22.0, 251.61339345142375, -21.93578400922676, 272.7694883091979 - 0.4, 17500.0, 22.0, 250.68014936643428, -31.50576018944198, 263.7080849622118 - 0.45, 17500.0, 22.0, 250.11213520252844, -40.71538335989939, 254.00943986454809 - 0.5, 17500.0, 22.0, 247.32302462783963, -49.541955910430275, 242.90684176550218 - 0.55, 17500.0, 22.0, 240.7294424613317, -57.94823262921477, 229.97113888651072 - 0.6000000000000001, 17500.0, 22.0, 228.74801352196755, -65.896968304433, 214.77317944900997 - 0.0, 17500.0, 24.0, 281.7489048759334, 56.9925437151953, 315.4784297089172 - 0.05, 17500.0, 24.0, 302.73838049174265, 46.58412851017039, 322.7831571369383 - 0.1, 17500.0, 24.0, 318.8226731042968, 35.959721877206746, 326.74757408639834 -0.15000000000000002, 17500.0, 24.0, 330.576541767149, 25.2002372637318, 327.69817090028744 - 0.2, 17500.0, 24.0, 338.5747455338525, 14.386588117173016, 325.9614379215958 - 0.25, 17500.0, 24.0, 343.39204345795997, 3.5996878849578104, 321.86386549331314 -0.30000000000000004, 17500.0, 24.0, 345.6031945930244, -7.079549985486383, 315.7319439584295 -0.35000000000000003, 17500.0, 24.0, 345.78295799259934, -17.570212046732106, 307.8921636599351 - 0.4, 17500.0, 24.0, 344.5060927102373, -27.791384851351925, 298.6710149408196 - 0.45, 17500.0, 24.0, 343.720702741466, -37.630390164603824, 288.9017768936596 - 0.5, 17500.0, 24.0, 339.8815123139222, -47.101608901003594, 277.3905736126942 - 0.55, 17500.0, 24.0, 330.81659059722443, -56.18765718775205, 263.450317941756 - 0.6000000000000001, 17500.0, 24.0, 314.3540067609878, -64.87115115205016, 246.39392272467398 - 0.0, 17500.0, 26.0, 358.991365529409, 63.94907871683165, 344.1014060488733 - 0.05, 17500.0, 26.0, 385.4767209102632, 53.60249692711085, 354.03443212585915 - 0.1, 17500.0, 26.0, 405.77732689570644, 42.8805485281311, 359.99669431993703 -0.15000000000000002, 17500.0, 26.0, 420.6164109119187, 31.886799792064647, 362.3897225685178 - 0.2, 17500.0, 26.0, 430.71720038508033, 20.72481699108369, 361.6150468090114 - 0.25, 17500.0, 26.0, 436.8029227413713, 9.498166397360428, 358.0741969788281 -0.30000000000000004, 17500.0, 26.0, 439.5968054069716, -1.6895857169329291, 352.1687030153783 -0.35000000000000003, 17500.0, 26.0, 439.8220758080615, -12.73487307962415, 344.300094856072 - 0.4, 17500.0, 26.0, 438.20196137082115, -23.534129418541024, 334.86990243831974 - 0.45, 17500.0, 26.0, 437.20257767914006, -33.92583028935858, 324.95189399049787 - 0.5, 17500.0, 26.0, 432.3184876860855, -43.9802839363618, 312.93088457713645 - 0.55, 17500.0, 26.0, 420.78714250245207, -53.709840431682025, 297.8639275537475 - 0.6000000000000001, 17500.0, 26.0, 399.84599323902506, -63.12684984745095, 278.8080762758349 - 0.0, 17500.0, 28.0, 435.3741697405005, 70.7419096443912, 374.23413625814686 - 0.05, 17500.0, 28.0, 467.79169131373624, 60.635083722749926, 386.61159750313914 - 0.1, 17500.0, 28.0, 492.6133423458541, 49.948189106385904, 394.43403537391964 -0.15000000000000002, 17500.0, 28.0, 510.7328037208373, 38.8156912912842, 398.167961722387 - 0.2, 17500.0, 28.0, 523.0437563226692, 27.372055773429874, 398.2798884004409 - 0.25, 17500.0, 28.0, 530.4398810353334, 15.75174804880797, 395.2363272599799 -0.30000000000000004, 17500.0, 28.0, 533.814858742813, 4.089233613403555, 389.5037901529032 -0.35000000000000003, 17500.0, 28.0, 534.0623703290916, -7.481022036798296, 381.5487889311099 - 0.4, 17500.0, 28.0, 532.0760966781517, -18.82455340581254, 371.837835446499 - 0.45, 17500.0, 28.0, 530.882260317287, -29.710540080510988, 361.6529949426892 - 0.5, 17500.0, 28.0, 524.976917200553, -40.29358131633742, 349.0141190964165 - 0.55, 17500.0, 28.0, 510.9886649253162, -50.631921451592106, 332.75661297613436 - 0.6000000000000001, 17500.0, 28.0, 485.54610108894246, -60.783804824575405, 311.7158816502978 - 0.0, 17500.0, 30.0, 511.30000000000683, 77.89999999999905, 405.49999999999625 - 0.05, 17500.0, 30.0, 549.8875000000043, 67.98124999999945, 420.1499999999986 - 0.1, 17500.0, 30.0, 579.4000000000024, 57.29999999999971, 429.7 -0.15000000000000002, 17500.0, 30.0, 600.9125000000009, 46.018749999999876, 434.6750000000004 - 0.2, 17500.0, 30.0, 615.5, 34.29999999999996, 435.6000000000004 - 0.25, 17500.0, 30.0, 624.2374999999992, 22.306249999999984, 433.0000000000001 -0.30000000000000004, 17500.0, 30.0, 628.1999999999985, 10.199999999999948, 427.3999999999998 -0.35000000000000003, 17500.0, 30.0, 628.4624999999975, -1.8562500000000928, 419.3249999999996 - 0.4, 17500.0, 30.0, 626.0999999999958, -13.700000000000145, 409.29999999999984 - 0.45, 17500.0, 30.0, 624.7187499999944, -25.03124999999957, 398.7999999999936 - 0.5, 17500.0, 30.0, 617.7999999999918, -36.099999999999305, 385.49999999999085 - 0.55, 17500.0, 30.0, 601.3562499999883, -47.01874999999901, 368.0249999999874 - 0.6000000000000001, 17500.0, 30.0, 571.3999999999847, -57.89999999999864, 344.9999999999833 - 0.0, 17500.0, 32.0, 588.0564795784485, 86.29044629530864, 437.18513918441107 - 0.05, 17500.0, 32.0, 632.4295630849244, 76.06795031391238, 454.0369076792064 - 0.1, 17500.0, 32.0, 666.3714726082785, 65.06624570116678, 465.24904566695733 -0.15000000000000002, 17500.0, 32.0, 691.1170164186107, 53.448246515432174, 471.4082233424663 - 0.2, 17500.0, 32.0, 707.901002786021, 41.37686681506885, 473.10111090053556 - 0.25, 17500.0, 32.0, 717.9582399806094, 29.015020658437084, 470.91437853596756 -0.30000000000000004, 17500.0, 32.0, 722.5235362724763, 16.52562210389714, 465.43469644356486 -0.35000000000000003, 17500.0, 32.0, 722.831699931721, 4.071585209809335, 457.2487348181299 - 0.4, 17500.0, 32.0, 720.1175392284441, -8.184175965466059, 446.94316385446456 - 0.45, 17500.0, 32.0, 718.5247076993674, -19.918558326759015, 436.21326824561714 - 0.5, 17500.0, 32.0, 710.5614778147418, -31.449214926139017, 422.3198746916819 - 0.55, 17500.0, 32.0, 691.6449673114466, -42.933609778866355, 403.6324243910222 - 0.6000000000000001, 17500.0, 32.0, 657.1922939263569, -54.529206900201, 378.52035854198886 - 0.0, 17500.0, 34.0, 664.9316380936322, 94.44144222822871, 470.26804200164565 - 0.05, 17500.0, 34.0, 714.971642668329, 84.07895220859022, 488.8593879770205 - 0.1, 17500.0, 34.0, 753.2617167237303, 72.8843560088413, 501.40185824661404 -0.15000000000000002, 17500.0, 34.0, 781.1900284613273, 61.026746047942865, 508.52618093968135 - 0.2, 17500.0, 34.0, 800.1447460826115, 48.67521474485591, 510.8630841854776 - 0.25, 17500.0, 34.0, 811.5140377890748, 35.99885451854132, 509.04329611325807 -0.30000000000000004, 17500.0, 34.0, 816.6860717822086, 23.166757787960037, 503.6975448522781 -0.35000000000000003, 17500.0, 34.0, 817.0490162635047, 10.348016972073012, 495.45655853179295 - 0.4, 17500.0, 34.0, 813.9910394344543, -2.288275510158826, 484.9510652810575 - 0.45, 17500.0, 34.0, 812.1798778749574, -14.385901141891077, 474.07763330647566 - 0.5, 17500.0, 34.0, 803.1649946512979, -26.337145797812695, 459.6694705058561 - 0.55, 17500.0, 34.0, 781.7754212081722, -38.3471692547288, 439.8256248541559 - 0.6000000000000001, 17500.0, 34.0, 742.8401889902743, -50.62113128944468, 412.64514432633183 - 0.0, 17500.0, 36.0, 741.5944344448129, 101.77380746768267, 503.64347537201525 - 0.05, 17500.0, 36.0, 797.3452131258944, 91.68512329345164, 523.937098026681 - 0.1, 17500.0, 36.0, 840.0122153544754, 80.60164024150396, 537.8030867468526 -0.15000000000000002, 17500.0, 36.0, 871.1397688190772, 68.71594642137882, 545.9114056480743 - 0.2, 17500.0, 36.0, 892.2722012082197, 56.22062994261541, 548.9320188458912 - 0.25, 17500.0, 36.0, 904.9538402104234, 43.30827891475289, 547.5348904558479 -0.30000000000000004, 17500.0, 36.0, 910.729013514209, 30.171481447330432, 542.3899845934889 -0.35000000000000003, 17500.0, 36.0, 911.1420488080962, 17.00282564988724, 534.1672653743597 - 0.4, 17500.0, 36.0, 907.7372737806057, 3.994899631962493, 523.5366969140041 - 0.45, 17500.0, 36.0, 905.7117327028392, -8.434363688449777, 512.5949353003064 - 0.5, 17500.0, 36.0, 895.6516035156129, -20.768410627173928, 497.7318687317928 - 0.55, 17500.0, 36.0, 871.79578074234, -33.2653426915786, 476.7640773793292 - 0.6000000000000001, 17500.0, 36.0, 828.383158906424, -46.18326138903293, 447.50814141378174 - 0.0, 17500.0, 38.0, 817.7256455775745, 109.01775332085363, 529.9336597138301 - 0.05, 17500.0, 38.0, 879.5981081805471, 99.26647770737908, 554.8543321705711 - 0.1, 17500.0, 38.0, 926.9239005855035, 88.36990918223465, 572.2189485546334 -0.15000000000000002, 17500.0, 38.0, 961.4257065919309, 76.53885501218782, 582.8423476823629 - 0.2, 17500.0, 38.0, 984.8262099993171, 63.98412246400587, 587.5393683701056 - 0.25, 17500.0, 38.0, 998.8480946071503, 50.91651880445629, 587.1248494342078 -0.30000000000000004, 17500.0, 38.0, 1005.2140442149171, 37.54685130030643, 582.413629691015 -0.35000000000000003, 17500.0, 38.0, 1005.6467426221063, 24.085927218323743, 574.2205479568735 - 0.4, 17500.0, 38.0, 1001.8688736282048, 10.744553825275613, 563.3604430481295 - 0.45, 17500.0, 38.0, 999.6519709682169, -2.0081363108815222, 552.3175901916551 - 0.5, 17500.0, 38.0, 988.5721686351105, -14.736311826946828, 536.8985189722155 - 0.55, 17500.0, 38.0, 962.2544505574124, -27.745816058530256, 514.5791953851167 - 0.6000000000000001, 17500.0, 38.0, 914.323800663629, -41.34249234124186, 482.83558542565805 - 0.0, 17500.0, 40.0, 896.0999999999761, 117.69999999999938, 563.499999999994 - 0.05, 17500.0, 40.0, 963.0499999999889, 107.8937499999996, 590.6812499999967 - 0.1, 17500.0, 40.0, 1014.2999999999965, 96.89999999999979, 609.7999999999986 -0.15000000000000002, 17500.0, 40.0, 1051.7000000000003, 84.93124999999995, 621.71875 - 0.2, 17500.0, 40.0, 1077.1000000000004, 72.20000000000007, 627.3000000000001 - 0.25, 17500.0, 40.0, 1092.3499999999985, 58.9187500000001, 627.4062499999989 -0.30000000000000004, 17500.0, 40.0, 1099.2999999999952, 45.30000000000007, 622.8999999999967 -0.35000000000000003, 17500.0, 40.0, 1099.7999999999922, 31.55624999999994, 614.6437499999927 - 0.4, 17500.0, 40.0, 1095.6999999999898, 17.899999999999707, 603.4999999999876 - 0.45, 17500.0, 40.0, 1093.2500000000107, 4.818750000000107, 592.1312499999997 - 0.5, 17500.0, 40.0, 1081.1000000000188, -8.299999999999848, 576.0000000000008 - 0.55, 17500.0, 40.0, 1052.3000000000297, -21.793749999999807, 552.3687500000032 - 0.6000000000000001, 17500.0, 40.0, 999.9000000000455, -35.999999999999766, 518.5000000000066 - 0.0, 17500.0, 42.0, 973.3399259312724, 123.56908046492518, 596.6800371903564 - 0.05, 17500.0, 42.0, 1045.7698294895074, 114.93571241999898, 626.4832694956889 - 0.1, 17500.0, 42.0, 1101.2404828506442, 104.6959144426875, 647.5710305991735 -0.15000000000000002, 17500.0, 42.0, 1141.7450963150216, 93.12874874883906, 660.882631083486 - 0.2, 17500.0, 42.0, 1169.276880182975, 80.51327755430202, 667.3573815313043 - 0.25, 17500.0, 42.0, 1185.8290447548422, 67.1285630749247, 667.9345925253045 -0.30000000000000004, 17500.0, 42.0, 1193.3948003309602, 53.25366752655548, 663.5535746481643 -0.35000000000000003, 17500.0, 42.0, 1193.9673572116646, 39.16765312504264, 655.15363848256 - 0.4, 17500.0, 42.0, 1189.5399256972944, 25.149582086234577, 643.6740946111681 - 0.45, 17500.0, 42.0, 1186.8688718395174, 11.848903122605458, 632.0189936302914 - 0.5, 17500.0, 42.0, 1173.6579386846627, -1.5664810398737639, 615.2334260817368 - 0.55, 17500.0, 42.0, 1142.3740250303717, -15.558281178606261, 590.3272225209348 - 0.6000000000000001, 17500.0, 42.0, 1085.4840296742957, -30.588208070995233, 554.3102135033173 - 0.0, 17500.0, 44.0, 1049.0667486119662, 131.4998178763026, 629.6818175008689 - 0.05, 17500.0, 44.0, 1127.7971162056704, 123.30532024358976, 662.3690875402351 - 0.1, 17500.0, 44.0, 1188.0441542455528, 113.32414181419625, 685.6125824883844 -0.15000000000000002, 17500.0, 44.0, 1231.9910981736466, 101.85932301836496, 700.4410218463782 - 0.2, 17500.0, 44.0, 1261.8211834319845, 89.21390428633886, 707.8831251152769 - 0.25, 17500.0, 44.0, 1279.7176454625992, 75.69092604836098, 708.9676117961418 -0.30000000000000004, 17500.0, 44.0, 1287.8637197075245, 61.593428734674234, 704.7232013900335 -0.35000000000000003, 17500.0, 44.0, 1288.4426416087915, 47.224452775521684, 696.1786133980129 - 0.4, 17500.0, 44.0, 1283.6376466084348, 32.88703860114625, 684.3625673211411 - 0.45, 17500.0, 44.0, 1280.8088914889022, 19.303851871267963, 672.4694396033293 - 0.5, 17500.0, 44.0, 1266.6088476709751, 5.519057327699561, 655.0309789171117 - 0.55, 17500.0, 44.0, 1232.8669079158644, -9.003555058268647, 628.7445908778936 - 0.6000000000000001, 17500.0, 44.0, 1171.412464984775, -24.800195315346635, 590.3076811010691 - 0.0, 17500.0, 46.0, 1126.0585495233531, 139.8177839825152, 662.1206714634152 - 0.05, 17500.0, 46.0, 1210.3405989824741, 131.97111496845204, 698.0151591543361 - 0.1, 17500.0, 46.0, 1274.8596109063144, 122.18068126541465, 723.6329312795687 -0.15000000000000002, 17500.0, 46.0, 1321.9443792088578, 110.77196385968797, 740.1114751700303 - 0.2, 17500.0, 46.0, 1353.923697804088, 98.07044373755694, 748.5882781566381 - 0.25, 17500.0, 46.0, 1373.1263606059902, 84.40160188530645, 750.2008275703096 -0.30000000000000004, 17500.0, 46.0, 1381.8811615285476, 70.09091928922135, 746.0866107419621 -0.35000000000000003, 17500.0, 46.0, 1382.5168944857446, 55.46387693558666, 737.3831150025128 - 0.4, 17500.0, 46.0, 1377.3623533915656, 40.84595581068723, 725.227827682879 - 0.45, 17500.0, 46.0, 1374.2766390680872, 27.025525148370775, 713.1304072008535 - 0.5, 17500.0, 46.0, 1358.9976247050126, 12.939401192233868, 695.1118276267152 - 0.55, 17500.0, 46.0, 1322.7934904001404, -2.0127115665639734, 667.5652341176105 - 0.6000000000000001, 17500.0, 46.0, 1256.932416251269, -18.43110863686329, 626.8837718306892 - 0.0, 17500.0, 48.0, 1202.571123243588, 148.6071491793373, 696.8723300777192 - 0.05, 17500.0, 48.0, 1292.7819056124172, 141.02700191037744, 735.156638540733 - 0.1, 17500.0, 48.0, 1361.8285978872602, 131.36462386201268, 762.5813369028807 -0.15000000000000002, 17500.0, 48.0, 1412.2075789027604, 119.96721792088266, 780.3552227643385 - 0.2, 17500.0, 48.0, 1446.4152274935645, 107.18198697362693, 789.6870937252814 - 0.25, 17500.0, 48.0, 1466.947922494318, 93.35613390688516, 791.7857473858857 -0.30000000000000004, 17500.0, 48.0, 1476.3020427396657, 78.83686160729705, 787.8599813463273 -0.35000000000000003, 17500.0, 48.0, 1476.9739670642539, 63.97137296150207, 779.1185932067813 - 0.4, 17500.0, 48.0, 1471.4600743027274, 49.106870856139906, 766.7703805674239 - 0.45, 17500.0, 48.0, 1468.1730617704795, 35.116469281397976, 754.604079533061 - 0.5, 17500.0, 48.0, 1451.8603528599178, 20.76963781326949, 736.0886721899852 - 0.55, 17500.0, 48.0, 1413.1856894441742, 5.361757131292585, 707.2730791291239 - 0.6000000000000001, 17500.0, 48.0, 1342.8128133963894, -11.811792084993094, 664.2062209414019 - 0.0, 17500.0, 50.0, 1280.9000000000333, 159.40000000000506, 733.6000000000076 - 0.05, 17500.0, 50.0, 1376.212500000014, 151.2062500000031, 773.4062500000043 - 0.1, 17500.0, 50.0, 1449.2000000000037, 141.1000000000017, 802.1000000000023 -0.15000000000000002, 17500.0, 50.0, 1502.4874999999995, 129.39375000000075, 820.8937500000009 - 0.2, 17500.0, 50.0, 1538.7000000000012, 116.40000000000025, 830.9999999999999 - 0.25, 17500.0, 50.0, 1560.462500000008, 102.43125000000026, 833.6312499999997 -0.30000000000000004, 17500.0, 50.0, 1570.4000000000176, 87.80000000000082, 829.9999999999999 -0.35000000000000003, 17500.0, 50.0, 1571.1375000000305, 72.8187500000019, 821.3187500000008 - 0.4, 17500.0, 50.0, 1565.3000000000452, 57.80000000000349, 808.8000000000015 - 0.45, 17500.0, 50.0, 1561.7812500000111, 43.581249999999805, 796.3437500000196 - 0.5, 17500.0, 50.0, 1544.4000000000292, 28.90000000000004, 777.1000000000284 - 0.55, 17500.0, 50.0, 1503.2437500000563, 13.018750000000345, 746.9062500000368 - 0.6000000000000001, 17500.0, 50.0, 1428.4000000000945, -4.799999999999322, 701.6000000000441 - 0.0, 20000.0, 20.0, 162.49999999999991, 41.80000000000008, 294.80000000000047 - 0.05, 20000.0, 20.0, 157.78124999999994, 31.687500000000046, 293.4000000000002 - 0.1, 20000.0, 20.0, 155.19999999999996, 21.70000000000002, 290.7000000000001 -0.15000000000000002, 20000.0, 20.0, 154.34374999999997, 11.862500000000004, 286.75 - 0.2, 20000.0, 20.0, 154.79999999999998, 2.1999999999999997, 281.59999999999997 - 0.25, 20000.0, 20.0, 156.15624999999997, -7.262499999999999, 275.29999999999995 -0.30000000000000004, 20000.0, 20.0, 157.99999999999997, -16.500000000000004, 267.8999999999999 -0.35000000000000003, 20000.0, 20.0, 159.91875, -25.487499999999986, 259.44999999999993 - 0.4, 20000.0, 20.0, 161.49999999999997, -34.19999999999996, 249.99999999999991 - 0.45, 20000.0, 20.0, 162.15625000000006, -42.61875000000003, 239.58125000000007 - 0.5, 20000.0, 20.0, 162.0000000000001, -50.70000000000005, 228.30000000000018 - 0.55, 20000.0, 20.0, 160.9687500000002, -58.406250000000085, 216.24375000000026 - 0.6000000000000001, 20000.0, 20.0, 159.00000000000026, -65.70000000000012, 203.50000000000028 - 0.0, 20000.0, 22.0, 258.19946884463434, 49.43509350088409, 321.67328948785655 - 0.05, 20000.0, 22.0, 251.47628234585903, 39.14246409975277, 319.3489265031609 - 0.1, 20000.0, 22.0, 247.92913954416193, 28.820922576959376, 316.27654396193 -0.15000000000000002, 20000.0, 22.0, 246.93737433648042, 18.518906080723212, 312.4031929668564 - 0.2, 20000.0, 22.0, 247.88032061975187, 8.284851759263606, 307.6759246206321 - 0.25, 20000.0, 22.0, 250.1373122909134, -1.8328032392001077, 302.0417900259491 -0.30000000000000004, 20000.0, 22.0, 253.08768324690234, -11.785621766448616, 295.44784028549986 -0.35000000000000003, 20000.0, 22.0, 256.1107673846561, -21.525166674262568, 287.8411265019763 - 0.4, 20000.0, 22.0, 258.58589860111175, -31.003000814422627, 279.1686997780706 - 0.45, 20000.0, 22.0, 259.63644797351833, -40.17041981662654, 269.3097466584053 - 0.5, 20000.0, 22.0, 259.40963785788165, -48.979788198903876, 258.41491191988393 - 0.55, 20000.0, 22.0, 257.7967277905217, -57.38320325720128, 246.5669757813426 - 0.6000000000000001, 20000.0, 22.0, 254.68897730775672, -65.33276228746533, 233.84871846161587 - 0.0, 20000.0, 24.0, 355.84973442231393, 59.075420561284304, 353.5812736907168 - 0.05, 20000.0, 24.0, 346.1762661729276, 47.75049438098557, 350.1882680243074 - 0.1, 20000.0, 24.0, 341.0045697720801, 36.528335099322, 346.6134417384294 -0.15000000000000002, 20000.0, 24.0, 339.45806216824013, 25.43591579715889, 342.6940816513178 - 0.2, 20000.0, 24.0, 340.66016030987623, 14.500209555361518, 338.26747458120786 - 0.25, 20000.0, 24.0, 343.73428114545703, 3.7481894547951793, 333.17090734633496 -0.30000000000000004, 20000.0, 24.0, 347.80384162345115, -6.793171423674847, 327.2416667649337 -0.35000000000000003, 20000.0, 24.0, 351.99225869232714, -17.09689999918324, 320.31703965524014 - 0.4, 20000.0, 24.0, 355.42294930055385, -27.13602319086472, 312.2343128354888 - 0.45, 20000.0, 24.0, 356.84634898676165, -36.89518205343458, 302.7139759850826 - 0.5, 20000.0, 24.0, 356.5048189289442, -46.3125610992857, 291.9437073387579 - 0.55, 20000.0, 24.0, 354.26773889526555, -55.33795897639124, 279.9943879924233 - 0.6000000000000001, 20000.0, 24.0, 350.00448865388444, -63.92117433272455, 266.93689904198465 - 0.0, 20000.0, 26.0, 454.15026557767476, 69.46820087124235, 389.41261314964873 - 0.05, 20000.0, 26.0, 441.2112338270657, 56.81791761234193, 384.7025212938741 - 0.1, 20000.0, 26.0, 434.1954302279171, 44.51528633320494, 380.42206753396414 -0.15000000000000002, 20000.0, 26.0, 431.95443783175955, 32.54784747323297, 376.28899885235137 - 0.2, 20000.0, 26.0, 433.3398396901248, 20.903141471827634, 372.0210622314678 - 0.25, 20000.0, 26.0, 437.2032188545439, 9.568708768390513, 367.3360046537457 -0.30000000000000004, 20000.0, 26.0, 442.3961583765483, -1.4679101976768076, 361.9515731016175 -0.35000000000000003, 20000.0, 26.0, 447.7702413076694, -12.219174986972716, 355.58551455751495 - 0.4, 20000.0, 26.0, 452.17705069943827, -22.697545160095626, 347.9555760038706 - 0.45, 20000.0, 26.0, 453.9661510132465, -32.94660938192949, 338.60708198255696 - 0.5, 20000.0, 26.0, 453.4951810710676, -42.88543990021578, 327.7750467976897 - 0.55, 20000.0, 26.0, 450.6197611047506, -52.464238066980954, 315.5220623128324 - 0.6000000000000001, 20000.0, 26.0, 445.1955113461363, -61.63320523425165, 301.9107203915452 - 0.0, 20000.0, 28.0, 551.1612446066326, 78.89390739652005, 428.3547230735671 - 0.05, 20000.0, 28.0, 535.5727237832863, 65.39085663557401, 421.75830969095284 - 0.1, 20000.0, 28.0, 527.1420335623523, 52.358439696028476, 416.34139065103017 -0.15000000000000002, 20000.0, 28.0, 524.479998360108, 39.763484427613704, 411.67953903755694 - 0.2, 20000.0, 28.0, 526.1974425928319, 27.572818680059935, 407.34832793429166 - 0.25, 20000.0, 28.0, 530.9051906768018, 15.753270303097413, 402.9233304249921 -0.30000000000000004, 20000.0, 28.0, 537.2140670282959, 4.2716671464563865, 397.98011959341653 -0.35000000000000003, 20000.0, 28.0, 543.7348960635926, -6.905162940132877, 392.0942685233231 - 0.4, 20000.0, 28.0, 549.0785021989695, -17.81039210694013, 384.8413502984699 - 0.45, 20000.0, 28.0, 551.2484542727727, -28.52087587531614, 375.54583004162583 - 0.5, 20000.0, 28.0, 550.6773434350768, -38.93873628228696, 364.5366047195175 - 0.55, 20000.0, 28.0, 547.1905052580261, -49.00977873595903, 351.89146333788267 - 0.6000000000000001, 20000.0, 28.0, 540.6132753137647, -58.67980864443911, 337.6881949024585 - 0.0, 20000.0, 30.0, 647.4999999999955, 87.49999999999949, 468.3999999999937 - 0.05, 20000.0, 30.0, 629.6062499999967, 73.5562499999997, 459.8937499999962 - 0.1, 20000.0, 30.0, 619.9999999999982, 60.09999999999983, 453.29999999999814 -0.15000000000000002, 20000.0, 30.0, 617.0687499999992, 47.093749999999936, 448.0562499999995 - 0.2, 20000.0, 30.0, 619.1999999999996, 34.49999999999999, 443.6000000000003 - 0.25, 20000.0, 30.0, 624.7812499999992, 22.281249999999968, 439.36875000000055 -0.30000000000000004, 20000.0, 30.0, 632.1999999999982, 10.399999999999842, 434.80000000000007 -0.35000000000000003, 20000.0, 30.0, 639.8437499999962, -1.1812500000003616, 429.33124999999905 - 0.4, 20000.0, 30.0, 646.0999999999931, -12.500000000000671, 422.3999999999975 - 0.45, 20000.0, 30.0, 648.6562499999927, -23.64375000000019, 413.1124999999943 - 0.5, 20000.0, 30.0, 647.9999999999883, -34.500000000000384, 401.89999999999236 - 0.55, 20000.0, 30.0, 643.9187499999829, -45.00625000000067, 388.8624999999909 - 0.6000000000000001, 20000.0, 30.0, 636.1999999999766, -55.10000000000103, 374.0999999999906 - 0.0, 20000.0, 32.0, 745.3872800538642, 96.08063622986988, 505.59948817927034 - 0.05, 20000.0, 32.0, 724.5420215864343, 81.76194482676117, 496.6243248226929 - 0.1, 20000.0, 32.0, 713.3082936108315, 67.9436420438754, 489.8472354725873 -0.15000000000000002, 20000.0, 32.0, 709.8178781950705, 54.584695543157636, 484.6438577644094 - 0.2, 20000.0, 32.0, 712.2025574071678, 41.64407298655294, 480.38982933361586 - 0.25, 20000.0, 32.0, 718.5941133151384, 29.080742036006352, 476.46078781566257 -0.30000000000000004, 20000.0, 32.0, 727.1243279869982, 16.853670353462906, 472.23237084600595 -0.35000000000000003, 20000.0, 32.0, 735.9249834907629, 4.921825600867669, 467.08021606010203 - 0.4, 20000.0, 32.0, 743.1278618944482, -6.7558245598343225, 460.37996109340696 - 0.45, 20000.0, 32.0, 746.0442531514959, -18.276231339779446, 451.15002641300407 - 0.5, 20000.0, 32.0, 745.2674156736163, -29.512670457779148, 439.8377011594824 - 0.55, 20000.0, 32.0, 740.5701157579182, -40.39433650572708, 426.5330573050682 - 0.6000000000000001, 20000.0, 32.0, 731.7251197015249, -50.850424075516436, 411.3261668219822 - 0.0, 20000.0, 34.0, 842.3823563195513, 105.73973456239553, 545.6893054940492 - 0.05, 20000.0, 34.0, 818.8770297661332, 90.62493684411032, 535.1398067485119 - 0.1, 20000.0, 34.0, 806.2202076172529, 76.16644502866816, 527.4179339726612 -0.15000000000000002, 20000.0, 34.0, 802.3023160227212, 62.29666986164657, 521.7834344192329 - 0.2, 20000.0, 34.0, 805.0137811323493, 48.94802208862299, 517.4960553409629 - 0.25, 20000.0, 34.0, 812.2450290959482, 36.05291245517493, 513.8155439905871 -0.30000000000000004, 20000.0, 34.0, 821.886486063329, 23.543751706879895, 510.0016476208414 -0.35000000000000003, 20000.0, 34.0, 831.8285781843027, 11.352950589315356, 505.3141134844613 - 0.4, 20000.0, 34.0, 839.9617316086803, -0.5870801519411691, 499.01268883418294 - 0.45, 20000.0, 34.0, 843.2467837982929, -12.416132908571091, 489.95398158424626 - 0.5, 20000.0, 34.0, 842.3629269669211, -23.985187523219434, 478.60715700287955 - 0.55, 20000.0, 34.0, 837.0597646403843, -35.21742697578967, 465.0382410198149 - 0.6000000000000001, 20000.0, 34.0, 827.0869003444906, -46.03603424618552, 449.3132595647842 - 0.0, 20000.0, 36.0, 938.2672645482608, 116.45194372088264, 589.4576304234296 - 0.05, 20000.0, 36.0, 912.5027286701218, 100.13672082246939, 575.8344604203294 - 0.1, 20000.0, 36.0, 898.7020448826661, 84.77083365116039, 566.155459640485 -0.15000000000000002, 20000.0, 36.0, 894.5347225219009, 70.23800274319309, 559.483950374453 - 0.2, 20000.0, 36.0, 897.6702709238343, 56.42194863480484, 554.8832549127897 - 0.25, 20000.0, 36.0, 905.7781994244731, 43.206391862233076, 551.4166955460508 -0.30000000000000004, 20000.0, 36.0, 916.5280173598248, 30.475052961715164, 548.1475945647927 -0.35000000000000003, 20000.0, 36.0, 927.589234065897, 18.111652469488554, 544.1392742595717 - 0.4, 20000.0, 36.0, 936.6313588786966, 5.999910921790638, 538.455056920944 - 0.45, 20000.0, 36.0, 940.3034076787667, -6.073201952060133, 529.6721194781118 - 0.5, 20000.0, 36.0, 939.3363701685723, -17.933713195067636, 518.3122203056993 - 0.55, 20000.0, 36.0, 933.4407425951523, -29.5044006571535, 504.4109724169728 - 0.6000000000000001, 20000.0, 36.0, 922.3270212055232, -40.708042188240064, 488.0039888251999 - 0.0, 20000.0, 38.0, 1037.4316639544586, 124.75775062807473, 627.3554202192579 - 0.05, 20000.0, 38.0, 1008.3065871980464, 108.3774066250971, 613.3825444933825 - 0.1, 20000.0, 38.0, 992.5807416948553, 92.91044917546891, 603.7262813500893 -0.15000000000000002, 20000.0, 38.0, 987.6513821137587, 78.24456189557202, 597.3615284046386 - 0.2, 20000.0, 38.0, 990.9157631236301, 64.2674284017884, 593.263183272291 - 0.25, 20000.0, 38.0, 999.7711393933428, 50.866732310499934, 590.4061435683071 -0.30000000000000004, 20000.0, 38.0, 1011.61476559177, 37.930157238088505, 587.7653069079469 -0.35000000000000003, 20000.0, 38.0, 1023.8438963877862, 25.345386800936044, 584.315570906471 - 0.4, 20000.0, 38.0, 1033.8557864502634, 13.000104615424476, 579.03183317914 - 0.45, 20000.0, 38.0, 1037.901474558922, 0.6932466172038554, 570.3749942726455 - 0.5, 20000.0, 38.0, 1036.8168630500868, -11.421260535144587, 558.8619430080415 - 0.55, 20000.0, 38.0, 1030.2916383709269, -23.27823786376808, 544.4955711379014 - 0.6000000000000001, 20000.0, 38.0, 1018.0154869686146, -34.8125063908156, 527.278770414753 - 0.0, 20000.0, 40.0, 1135.9000000000162, 136.1000000000012, 669.7000000000098 - 0.05, 20000.0, 40.0, 1103.487500000008, 118.54375000000066, 654.0937500000047 - 0.1, 20000.0, 40.0, 1085.9000000000035, 102.2000000000003, 643.5000000000018 -0.15000000000000002, 20000.0, 40.0, 1080.262500000002, 86.90625000000009, 636.7562500000009 - 0.2, 20000.0, 40.0, 1083.7000000000016, 72.5, 632.7000000000008 - 0.25, 20000.0, 40.0, 1093.3375000000012, 58.818749999999994, 630.1687500000013 -0.30000000000000004, 20000.0, 40.0, 1106.2999999999995, 45.700000000000024, 628.0000000000014 -0.35000000000000003, 20000.0, 40.0, 1119.7124999999949, 32.981250000000124, 625.0312500000001 - 0.4, 20000.0, 40.0, 1130.6999999999875, 20.500000000000224, 620.0999999999974 - 0.45, 20000.0, 40.0, 1135.1125000000097, 7.987500000000116, 611.4562500000029 - 0.5, 20000.0, 40.0, 1133.9000000000126, -4.3999999999998956, 599.7000000000077 - 0.55, 20000.0, 40.0, 1126.7375000000156, -16.612499999999994, 584.8437500000151 - 0.6000000000000001, 20000.0, 40.0, 1113.3000000000181, -28.60000000000015, 566.9000000000268 - 0.0, 20000.0, 42.0, 1232.6855152605738, 145.81448462241931, 710.1357471445999 - 0.05, 20000.0, 42.0, 1197.7129874263112, 127.82986299218575, 693.8265898380761 - 0.1, 20000.0, 42.0, 1178.7588671955957, 111.13723300387188, 682.9346330718597 -0.15000000000000002, 20000.0, 42.0, 1172.7165389718764, 95.55911090632159, 676.2079501994072 - 0.2, 20000.0, 42.0, 1176.479387158603, 80.91801294837872, 672.3946145741734 - 0.25, 20000.0, 42.0, 1186.9407961592267, 67.03645537888727, 670.242699549615 -0.30000000000000004, 20000.0, 42.0, 1200.9941503771981, 53.736954446691044, 668.5002784791877 -0.35000000000000003, 20000.0, 42.0, 1215.5328342159657, 40.842026400634, 665.9154247163473 - 0.4, 20000.0, 42.0, 1227.450232078981, 28.174187489560044, 661.2362116145498 - 0.45, 20000.0, 42.0, 1232.2747098037714, 15.442212086735037, 652.5760560749206 - 0.5, 20000.0, 42.0, 1230.9947074915624, 2.8098420677369065, 640.5870008078894 - 0.55, 20000.0, 42.0, 1223.2336466776662, -9.672922567434302, 625.2864320715415 - 0.6000000000000001, 20000.0, 42.0, 1208.6149488973906, -21.956081818778582, 606.6917361239697 - 0.0, 20000.0, 44.0, 1330.6282735599284, 155.94054037054028, 753.5638557084849 - 0.05, 20000.0, 44.0, 1292.7026647054781, 137.4875166759353, 735.557336475413 - 0.1, 20000.0, 44.0, 1272.1300144561046, 120.40901658661342, 723.6461995788017 -0.15000000000000002, 20000.0, 44.0, 1265.545098451021, 104.51461936820466, 716.4492119724108 - 0.2, 20000.0, 44.0, 1269.5826923294405, 89.61390428633882, 712.5851406100027 - 0.25, 20000.0, 44.0, 1280.8775717305755, 75.51645060664573, 710.6727524453382 -0.30000000000000004, 20000.0, 44.0, 1296.064512293639, 62.03183759475527, 709.330814432178 -0.35000000000000003, 20000.0, 44.0, 1311.7782896578433, 48.96964451629729, 707.1780935242846 - 0.4, 20000.0, 44.0, 1324.6536794624012, 36.13945063690163, 702.8333566754181 - 0.45, 20000.0, 44.0, 1329.8338562403428, 23.230275008299355, 694.1869503373115 - 0.5, 20000.0, 44.0, 1328.428398949411, 10.413377537816869, 682.0429029698415 - 0.55, 20000.0, 44.0, 1320.0552854411415, -2.2605420811183636, 666.4768225308813 - 0.6000000000000001, 20000.0, 44.0, 1304.3324935670837, -14.740784155078806, 647.564316978291 - 0.0, 20000.0, 46.0, 1426.4473202597576, 167.2246911117159, 795.16799712932 - 0.05, 20000.0, 46.0, 1386.2833611228045, 147.85959570820015, 776.4857472921694 - 0.1, 20000.0, 46.0, 1364.5802230717632, 130.0968644207403, 764.2219051003523 -0.15000000000000002, 20000.0, 46.0, 1357.7531304674194, 113.70948463522852, 756.9349985001364 - 0.2, 20000.0, 46.0, 1362.21730767056, 98.47044373755695, 753.1835554377882 - 0.25, 20000.0, 46.0, 1374.3879790419714, 84.15272911361767, 751.5261038595751 -0.30000000000000004, 20000.0, 46.0, 1390.680368942441, 70.52932814930269, 750.5211717117642 -0.35000000000000003, 20000.0, 46.0, 1407.5097017327537, 57.37322823050424, 748.7272869406224 - 0.4, 20000.0, 46.0, 1421.2912017736965, 44.4574167431143, 744.7029774924166 - 0.45, 20000.0, 46.0, 1426.863179854193, 31.420978582427793, 736.3148503086932 - 0.5, 20000.0, 46.0, 1425.3716010505873, 18.438608606126646, 724.1971963498588 - 0.55, 20000.0, 46.0, 1416.3855168673329, 5.551099181293619, 708.2923855715877 - 0.6000000000000001, 20000.0, 46.0, 1399.4739788089, -7.20075732498751, 688.5427879295606 - 0.0, 20000.0, 48.0, 1524.6302693863502, 180.30900694215697, 843.6603534058597 - 0.05, 20000.0, 48.0, 1481.4351672103603, 159.34906594983332, 821.4829971163201 - 0.1, 20000.0, 48.0, 1458.047446663172, 140.4426185076935, 806.9553391036242 -0.15000000000000002, 20000.0, 48.0, 1450.6237233413342, 123.28761029065294, 798.4188139050793 - 0.2, 20000.0, 48.0, 1455.3206128413974, 107.58198697362681, 794.2148560579925 - 0.25, 20000.0, 48.0, 1468.2947307599104, 93.02369423153036, 792.6849000996713 -0.30000000000000004, 20000.0, 48.0, 1485.702692693423, 79.31067773927889, 792.1703805674227 -0.35000000000000003, 20000.0, 48.0, 1503.701114238485, 66.14088317178755, 791.012731998554 - 0.4, 20000.0, 48.0, 1518.4466109916445, 53.21225620397164, 787.5533889303724 - 0.45, 20000.0, 48.0, 1524.403818510022, 40.04265313722909, 779.3375289465046 - 0.5, 20000.0, 48.0, 1522.805292508476, 26.87028776702518, 767.0953574453243 - 0.55, 20000.0, 48.0, 1513.1916086624149, 13.753284515306543, 750.7608228715294 - 0.6000000000000001, 20000.0, 48.0, 1495.1033426472532, 0.7497678040205771, 730.2678736698138 - 0.0, 20000.0, 50.0, 1621.400000000094, 190.60000000000213, 887.0000000000128 - 0.05, 20000.0, 50.0, 1575.6500000000444, 169.21250000000137, 863.3062500000073 - 0.1, 20000.0, 50.0, 1550.9000000000153, 150.00000000000077, 848.0000000000042 -0.15000000000000002, 20000.0, 50.0, 1543.0750000000023, 132.63750000000033, 839.268750000003 - 0.2, 20000.0, 50.0, 1548.100000000002, 116.80000000000004, 835.3000000000025 - 0.25, 20000.0, 50.0, 1561.9000000000108, 102.1625, 834.2812500000017 -0.30000000000000004, 20000.0, 50.0, 1580.4000000000256, 88.40000000000028, 834.4000000000001 -0.35000000000000003, 20000.0, 50.0, 1599.5250000000422, 75.18750000000091, 833.8437499999965 - 0.4, 20000.0, 50.0, 1615.2000000000564, 62.200000000001964, 830.7999999999898 - 0.45, 20000.0, 50.0, 1621.568750000054, 48.924999999998846, 822.5437499999989 - 0.5, 20000.0, 50.0, 1619.900000000097, 35.599999999998474, 810.0000000000076 - 0.55, 20000.0, 50.0, 1609.6812500001483, 22.274999999998034, 793.1812500000225 - 0.6000000000000001, 20000.0, 50.0, 1590.4000000002065, 8.999999999997554, 772.1000000000441 - 0.0, 23000.0, 20.0, 150.1999999999998, 40.90000000000008, 342.10000000000014 - 0.05, 23000.0, 20.0, 152.05624999999986, 31.26250000000005, 341.85625000000005 - 0.1, 23000.0, 20.0, 153.7999999999999, 21.600000000000023, 339.29999999999995 -0.15000000000000002, 23000.0, 20.0, 155.46874999999994, 11.962500000000006, 334.64374999999995 - 0.2, 23000.0, 20.0, 157.09999999999997, 2.3999999999999995, 328.09999999999997 - 0.25, 23000.0, 20.0, 158.73125, -7.037499999999999, 319.88125 -0.30000000000000004, 23000.0, 20.0, 160.40000000000003, -16.3, 310.20000000000005 -0.35000000000000003, 23000.0, 20.0, 162.14375000000007, -25.337499999999988, 299.26875000000007 - 0.4, 23000.0, 20.0, 164.00000000000014, -34.099999999999966, 287.30000000000007 - 0.45, 23000.0, 20.0, 166.23750000000007, -42.51875000000002, 274.55 - 0.5, 23000.0, 20.0, 168.2000000000001, -50.600000000000044, 261.1000000000002 - 0.55, 23000.0, 20.0, 169.46250000000018, -58.33125000000008, 247.07500000000027 - 0.6000000000000001, 23000.0, 20.0, 169.6000000000002, -65.70000000000012, 232.60000000000036 - 0.0, 23000.0, 22.0, 240.8607513349636, 50.958884282841126, 351.2565870293523 - 0.05, 23000.0, 22.0, 243.68161070005044, 40.169968497706215, 351.11352610580343 - 0.1, 23000.0, 22.0, 246.37139546426786, 29.485452439664652, 349.0366790909985 -0.15000000000000002, 23000.0, 22.0, 248.9814945700196, 18.934176523838225, 345.1932594080852 - 0.2, 23000.0, 22.0, 251.56329695970936, 8.544981165348718, 339.75048048021097 - 0.25, 23000.0, 22.0, 254.16819157574088, -1.6532932206820823, 332.87555573052344 -0.30000000000000004, 23000.0, 22.0, 256.84756736051787, -11.631806219132407, 324.7356985821703 -0.35000000000000003, 23000.0, 22.0, 259.6528132564438, -21.36171741488046, 315.498122458299 - 0.4, 23000.0, 22.0, 262.6353182059227, -30.81418639280445, 305.3300407820574 - 0.45, 23000.0, 22.0, 266.20325901535244, -39.96641301645136, 294.4797260058681 - 0.5, 23000.0, 22.0, 269.337661035158, -48.77143603469362, 282.8712144650562 - 0.55, 23000.0, 22.0, 271.3763374797623, -57.188334475072715, 270.50960152422385 - 0.6000000000000001, 23000.0, 22.0, 271.6571015635862, -65.17618736512993, 257.39998254797246 - 0.0, 23000.0, 24.0, 330.260375667479, 59.105189763105265, 370.6781823540402 - 0.05, 23000.0, 24.0, 334.46643035002387, 47.95604834518336, 371.23369357975537 - 0.1, 23000.0, 24.0, 338.38569773213374, 36.828563976629646, 369.9263726010437 -0.15000000000000002, 23000.0, 24.0, 342.1076222850101, 25.768163625138424, 366.9213193693453 - 0.2, 23000.0, 24.0, 345.72164847985505, 14.820274258404076, 362.38363383610056 - 0.25, 23000.0, 24.0, 349.31722078787044, 4.030322844120934, 356.4784159527497 -0.30000000000000004, 23000.0, 24.0, 352.98378368025817, -6.556263650016668, 349.370765670733 -0.35000000000000003, 23000.0, 24.0, 356.8107816282202, -16.89405825631437, 341.2257829414908 - 0.4, 23000.0, 24.0, 360.8876591029582, -26.937634007077822, 332.20856771646316 - 0.45, 23000.0, 24.0, 365.8131283809891, -36.624329567191886, 322.63474946173244 - 0.5, 23000.0, 24.0, 370.14883051758136, -45.96042107122559, 312.2178395848214 - 0.55, 23000.0, 24.0, 372.9656743733285, -54.934950286327755, 300.8218790078994 - 0.6000000000000001, 23000.0, 24.0, 373.3345688088191, -63.53695897964685, 288.310908653134 - 0.0, 23000.0, 26.0, 419.2396243325111, 66.78205310194889, 397.59148416405276 - 0.05, 23000.0, 26.0, 424.9710696499718, 55.49214394380748, 399.017098000806 - 0.1, 23000.0, 26.0, 430.21430226786566, 44.09894929376234, 398.5077265655896 -0.15000000000000002, 23000.0, 26.0, 435.10487771499106, 32.67256246451954, 396.2452496265629 - 0.2, 23000.0, 26.0, 439.7783515201463, 21.283076768785087, 392.4115469518848 - 0.25, 23000.0, 26.0, 444.3702792121296, 10.000585519265, 387.1884983097144 -0.30000000000000004, 23000.0, 26.0, 449.01621631973927, -1.1048179713347195, 380.75798346821074 -0.35000000000000003, 23000.0, 26.0, 453.8517183717735, -11.963040390308029, 373.30188219553287 - 0.4, 23000.0, 26.0, 459.01234089703064, -22.503988424948922, 365.0020742598397 - 0.45, 23000.0, 26.0, 465.30511823895034, -32.60403960970687, 356.2711599146632 - 0.5, 23000.0, 26.0, 470.85116948242666, -42.35368809041098, 346.59885747205834 - 0.55, 23000.0, 26.0, 474.4430925270151, -51.789898860046826, 335.70560572946255 - 0.6000000000000001, 23000.0, 26.0, 474.8734852722604, -60.949636911599335, 323.31184348430855 - 0.0, 23000.0, 28.0, 508.99923019921573, 76.31203645573979, 429.1562030422335 - 0.05, 23000.0, 28.0, 515.9979230135891, 64.16905352193041, 430.92395182328283 - 0.1, 23000.0, 28.0, 522.3895814940595, 52.03530516458266, 430.7948951069495 -0.15000000000000002, 23000.0, 28.0, 528.3415624863584, 39.9650982160306, 428.94762798957197 - 0.2, 23000.0, 28.0, 534.0212228362163, 28.01273950860826, 425.5607455674887 - 0.25, 23000.0, 28.0, 539.5959193893656, 16.232535874649656, 420.81284293703834 -0.30000000000000004, 23000.0, 28.0, 545.2330089915379, 4.678794146488824, 414.88251519455923 -0.35000000000000003, 23000.0, 28.0, 551.0998484884637, -6.5941788435402, 407.9483574363897 - 0.4, 23000.0, 28.0, 557.3637947258757, -17.532076263103388, 400.18896475886845 - 0.45, 23000.0, 28.0, 565.0129582230677, -28.03199629143302, 392.0709491623259 - 0.5, 23000.0, 28.0, 571.7524348050806, -38.18541706149572, 382.9088550311265 - 0.55, 23000.0, 28.0, 576.108073970518, -48.03522171782375, 372.305243653628 - 0.6000000000000001, 23000.0, 28.0, 576.6057252179851, -57.62429340494979, 359.862676318187 - 0.0, 23000.0, 30.0, 599.3000000000137, 86.49999999999987, 462.7999999999999 - 0.05, 23000.0, 30.0, 607.3812500000088, 73.29999999999997, 464.7750000000001 - 0.1, 23000.0, 30.0, 614.8000000000048, 60.30000000000001, 464.90000000000003 -0.15000000000000002, 23000.0, 30.0, 621.7437500000023, 47.52500000000002, 463.34999999999985 - 0.2, 23000.0, 30.0, 628.4, 34.99999999999998, 460.29999999999956 - 0.25, 23000.0, 30.0, 634.9562499999985, 22.749999999999904, 455.92499999999933 -0.30000000000000004, 23000.0, 30.0, 641.5999999999975, 10.799999999999807, 450.399999999999 -0.35000000000000003, 23000.0, 30.0, 648.5187499999972, -0.8250000000002893, 443.89999999999895 - 0.4, 23000.0, 30.0, 655.899999999997, -12.100000000000382, 436.59999999999906 - 0.45, 23000.0, 30.0, 664.8874999999989, -22.974999999999888, 429.01250000000107 - 0.5, 23000.0, 30.0, 672.7999999999996, -33.49999999999994, 420.3000000000025 - 0.55, 23000.0, 30.0, 677.9125000000008, -43.700000000000124, 409.9625000000044 - 0.6000000000000001, 23000.0, 30.0, 678.5000000000033, -53.60000000000039, 397.50000000000654 - 0.0, 23000.0, 32.0, 688.7665610741473, 93.7731807371353, 494.467867071847 - 0.05, 23000.0, 32.0, 698.2464577797718, 80.8069737034382, 497.9048571611944 - 0.1, 23000.0, 32.0, 706.9174139639682, 67.8488554431737, 499.12552419117674 -0.15000000000000002, 23000.0, 32.0, 715.0021875028359, 54.95905166175678, 498.3761472549833 - 0.2, 23000.0, 32.0, 722.723536272474, 42.197788064602214, 495.9030054458035 - 0.25, 23000.0, 32.0, 730.3042181489817, 29.625290357124914, 491.95237785682656 -0.30000000000000004, 23000.0, 32.0, 737.9669910084581, 17.30178424473975, 486.7705435812418 -0.35000000000000003, 23000.0, 32.0, 745.9346127270028, 5.287495432861632, 480.6037817122385 - 0.4, 23000.0, 32.0, 754.4298411807148, -6.357350373094575, 473.69837134300604 - 0.45, 23000.0, 32.0, 764.7850635694888, -17.52318443208937, 466.73788320648225 - 0.5, 23000.0, 32.0, 773.8941497980451, -28.297810145581796, 458.65672147660655 - 0.55, 23000.0, 32.0, 779.7605990949107, -38.71968787940648, 448.8265819670628 - 0.6000000000000001, 23000.0, 32.0, 780.3879106886069, -48.82727799939796, 436.61916049153706 - 0.0, 23000.0, 34.0, 780.9336284544793, 101.4129876172607, 530.1559180140465 - 0.05, 23000.0, 34.0, 790.5202412885309, 88.58879535415288, 533.5461910380512 - 0.1, 23000.0, 34.0, 799.5925252423191, 75.61580865220904, 534.8446415045908 -0.15000000000000002, 23000.0, 34.0, 808.320884237715, 62.58673151730393, 534.284598221308 - 0.2, 23000.0, 34.0, 816.8757221965899, 49.59426795531238, 532.0993899958454 - 0.25, 23000.0, 34.0, 825.4274430408146, 36.73112197210922, 528.5223456358459 -0.30000000000000004, 23000.0, 34.0, 834.1464506922601, 24.08999757356926, 523.7867939489525 -0.35000000000000003, 23000.0, 34.0, 843.203149072798, 11.763598765567314, 518.1260637428082 - 0.4, 23000.0, 34.0, 852.7679421042992, -0.15537044602180464, 511.773483825055 - 0.45, 23000.0, 34.0, 864.099036674467, -11.478794446332573, 505.4268481099386 - 0.5, 23000.0, 34.0, 874.1034278077036, -22.40020405646158, 497.92609008530644 - 0.55, 23000.0, 34.0, 880.7759134942564, -33.01771848851426, 488.5756083456089 - 0.6000000000000001, 23000.0, 34.0, 882.1112917243643, -43.429456954596304, 476.67980148529523 - 0.0, 23000.0, 36.0, 875.2790231074816, 110.68149013265615, 570.3182541883718 - 0.05, 23000.0, 36.0, 883.9654275872275, 97.36776088243897, 571.8608990359577 - 0.1, 23000.0, 36.0, 892.7639303132937, 83.95358019796483, 572.0399970414845 -0.15000000000000002, 23000.0, 36.0, 901.7285959435291, 70.53173718771227, 570.9697501307603 - 0.2, 23000.0, 36.0, 910.9134891357825, 57.19502096015995, 568.7643602295922 - 0.25, 23000.0, 36.0, 920.3726745479036, 44.03622062378644, 565.5380292637874 -0.30000000000000004, 23000.0, 36.0, 930.1602168377412, 31.148125287070336, 561.404959159153 -0.35000000000000003, 23000.0, 36.0, 940.3301806631449, 18.623524058490272, 556.4793518414969 - 0.4, 23000.0, 36.0, 950.9366306819636, 6.555206046524815, 550.8754092366255 - 0.45, 23000.0, 36.0, 962.978139294552, -4.8267699452986506, 545.1205745676223 - 0.5, 23000.0, 36.0, 973.6752479313067, -15.841423893646763, 538.0893258684906 - 0.55, 23000.0, 36.0, 981.1930057651642, -26.670506080136818, 529.0693824705112 - 0.6000000000000001, 23000.0, 36.0, 983.6964619690405, -37.49576678638638, 517.3484637049607 - 0.0, 23000.0, 38.0, 960.8048697679887, 120.43390735773674, 603.5066977336838 - 0.05, 23000.0, 38.0, 972.8667969941099, 106.43997984689355, 606.6915342694939 - 0.1, 23000.0, 38.0, 984.1772923485102, 92.5044568330761, 608.1740255668266 -0.15000000000000002, 23000.0, 38.0, 994.9748935211019, 78.69105191472654, 608.127065504498 - 0.2, 23000.0, 38.0, 1005.4981382017955, 65.06347869028727, 606.7235479613252 - 0.25, 23000.0, 38.0, 1015.9855640805022, 51.685450758200346, 604.1363668161243 -0.30000000000000004, 23000.0, 38.0, 1026.6757088471325, 38.62068171690803, 600.5384159477128 -0.35000000000000003, 23000.0, 38.0, 1037.8071101915975, 25.932885164852536, 596.1025892349065 - 0.4, 23000.0, 38.0, 1049.6183058038089, 13.685774700476077, 591.0017805565222 - 0.45, 23000.0, 38.0, 1063.7646240714666, 2.0359011915216416, 585.9623705734406 - 0.5, 23000.0, 38.0, 1076.234230591073, -9.231533571469908, 579.4967928182757 - 0.55, 23000.0, 38.0, 1084.432081656891, -20.238490528656023, 570.6709676056967 - 0.6000000000000001, 23000.0, 38.0, 1085.7631335632007, -31.106930620194568, 558.5508152503771 - 0.0, 23000.0, 40.0, 1049.29999999997, 127.60000000000127, 640.799999999983 - 0.05, 23000.0, 40.0, 1063.1124999999845, 114.2562500000009, 644.399999999992 - 0.1, 23000.0, 40.0, 1075.899999999994, 100.70000000000053, 646.2999999999976 -0.15000000000000002, 23000.0, 40.0, 1087.9624999999996, 87.04375000000022, 646.6750000000008 - 0.2, 23000.0, 40.0, 1099.6000000000017, 73.39999999999996, 645.7000000000012 - 0.25, 23000.0, 40.0, 1111.1125000000004, 59.88124999999975, 643.5499999999998 -0.30000000000000004, 23000.0, 40.0, 1122.7999999999968, 46.59999999999954, 640.3999999999966 -0.35000000000000003, 23000.0, 40.0, 1134.9624999999896, 33.66874999999935, 636.4249999999926 - 0.4, 23000.0, 40.0, 1147.8999999999808, 21.199999999999157, 631.7999999999873 - 0.45, 23000.0, 40.0, 1163.5375000000113, 9.449999999999942, 627.3250000000024 - 0.5, 23000.0, 40.0, 1177.3000000000216, -1.9000000000001727, 621.3000000000051 - 0.55, 23000.0, 40.0, 1186.2375000000368, -13.025000000000363, 612.6500000000095 - 0.6000000000000001, 23000.0, 40.0, 1187.400000000059, -24.10000000000063, 600.300000000016 - 0.0, 23000.0, 42.0, 1139.4644383782172, 139.7021362810039, 678.5699169164062 - 0.05, 23000.0, 42.0, 1154.3663707687244, 125.00201989297233, 682.6578809183944 - 0.1, 23000.0, 42.0, 1168.1734447744057, 110.436676123494, 685.0186630191247 -0.15000000000000002, 23000.0, 42.0, 1181.209789918698, 96.06378833427262, 685.8328574453171 - 0.2, 23000.0, 42.0, 1193.799535725033, 81.94103988701212, 685.2810584236931 - 0.25, 23000.0, 42.0, 1206.2668117168466, 68.12611414341625, 683.5438601809733 -0.30000000000000004, 23000.0, 42.0, 1218.935747417573, 54.67669446518881, 680.801856943878 -0.35000000000000003, 23000.0, 42.0, 1232.130472350647, 41.650464214033654, 677.2356429391285 - 0.4, 23000.0, 42.0, 1246.1751160395017, 29.105106751654567, 673.0258123934453 - 0.45, 23000.0, 42.0, 1263.1616643187158, 17.193192839329754, 668.9986535655495 - 0.5, 23000.0, 42.0, 1278.1106777782902, 5.6877436400404475, 663.3976785861705 - 0.55, 23000.0, 42.0, 1287.810573319357, -5.543332283657403, 655.1120936180422 - 0.6000000000000001, 23000.0, 42.0, 1289.0497678430536, -16.63212636920802, 643.0311048238965 - 0.0, 23000.0, 44.0, 1228.2540050938853, 146.5585574932954, 713.6568606027433 - 0.05, 23000.0, 44.0, 1244.9281860710244, 132.84902013033525, 719.6347547164662 - 0.1, 23000.0, 44.0, 1260.232827959531, 118.88436860551788, 723.3778927743012 -0.15000000000000002, 23000.0, 44.0, 1274.5504870686264, 104.7958669299927, 725.1643026613965 - 0.2, 23000.0, 44.0, 1288.2637197075292, 90.71477911490913, 725.2720122628992 - 0.25, 23000.0, 44.0, 1301.7550821854607, 76.77236917141663, 723.9790494639572 -0.30000000000000004, 23000.0, 44.0, 1315.407130811641, 63.09990111066465, 721.5634421497175 -0.35000000000000003, 23000.0, 44.0, 1329.6024218952912, 49.82863894380262, 718.3032182053282 - 0.4, 23000.0, 44.0, 1344.7235117456296, 37.089846681979964, 714.4764055159367 - 0.45, 23000.0, 44.0, 1363.094366821554, 25.18916880554984, 711.1548482421821 - 0.5, 23000.0, 44.0, 1379.2733129832893, 13.734727918051995, 706.2351254427743 - 0.55, 23000.0, 44.0, 1389.7600862407544, 2.509027092230956, 698.4076324519381 - 0.6000000000000001, 23000.0, 44.0, 1391.0544226038567, -8.7054305991693, 686.3627646038852 - 0.0, 23000.0, 46.0, 1318.2329978670407, 159.10448561101234, 753.6650350581559 - 0.05, 23000.0, 46.0, 1335.9755114008221, 144.0175807342185, 759.5964943530503 - 0.1, 23000.0, 46.0, 1352.2949179768239, 129.02028850131796, 763.363357923464 -0.15000000000000002, 23000.0, 46.0, 1367.5937873193118, 114.19514533874039, 765.2495157458948 - 0.2, 23000.0, 46.0, 1382.274689152554, 99.62468767291534, 765.53885779684 - 0.25, 23000.0, 46.0, 1396.7401932008158, 85.39145193027238, 764.5152740527976 -0.30000000000000004, 23000.0, 46.0, 1411.3928691883643, 71.57797453724106, 762.4626544902651 -0.35000000000000003, 23000.0, 46.0, 1426.6352868394656, 58.266791920250995, 759.6648890857405 - 0.4, 23000.0, 46.0, 1442.870015878386, 45.54044050573174, 756.4058678157204 - 0.45, 23000.0, 46.0, 1462.5773969904628, 33.63864843998006, 753.881163041357 - 0.5, 23000.0, 46.0, 1479.9266870167266, 22.172376989820354, 749.639617585162 - 0.55, 23000.0, 46.0, 1491.1649137592651, 10.90977914194098, 742.1417566542851 - 0.6000000000000001, 23000.0, 46.0, 1492.5391050201754, -0.3809921169679624, 729.8481054558844 - 0.0, 23000.0, 48.0, 1408.7940576547987, 169.4000003509754, 795.7452188296787 - 0.05, 23000.0, 48.0, 1427.5758647374741, 154.01283098651314, 800.9190114958927 - 0.1, 23000.0, 48.0, 1444.8865367279122, 138.73500474141292, 804.2997215988066 -0.15000000000000002, 23000.0, 48.0, 1461.1483925668688, 123.65520545444457, 806.112070576365 - 0.2, 23000.0, 48.0, 1476.7837511951016, 108.86211696437798, 806.5807798665122 - 0.25, 23000.0, 48.0, 1492.2149315533668, 94.444423109983, 805.9305709071931 -0.30000000000000004, 23000.0, 48.0, 1507.8642525824212, 80.4908077300296, 804.3861651363522 -0.35000000000000003, 23000.0, 48.0, 1524.154033223022, 67.08995466328756, 802.1722839919347 - 0.4, 23000.0, 48.0, 1541.506592415925, 54.3305477485269, 799.5136489118844 - 0.45, 23000.0, 48.0, 1562.5541899090113, 42.49857235545161, 797.5540272914018 - 0.5, 23000.0, 48.0, 1581.0893222217271, 31.090807730029766, 793.7610026966684 - 0.55, 23000.0, 48.0, 1593.114426680678, 19.801334649164556, 786.5212046511166 - 0.6000000000000001, 23000.0, 48.0, 1594.6319406124483, 8.324233889758702, 774.221262678181 - 0.0, 23000.0, 50.0, 1498.4000000000156, 179.30000000000257, 835.2000000000154 - 0.05, 23000.0, 50.0, 1518.4375000000089, 163.7312500000017, 840.7687500000052 - 0.1, 23000.0, 50.0, 1536.9000000000044, 148.30000000000098, 844.5999999999996 -0.15000000000000002, 23000.0, 50.0, 1554.2375000000006, 133.09375000000034, 846.9062499999977 - 0.2, 23000.0, 50.0, 1570.8999999999962, 118.19999999999992, 847.8999999999988 - 0.25, 23000.0, 50.0, 1587.3374999999896, 103.70624999999956, 847.7937500000023 -0.30000000000000004, 23000.0, 50.0, 1603.9999999999795, 89.69999999999938, 846.8000000000071 -0.35000000000000003, 23000.0, 50.0, 1621.3374999999648, 76.26874999999927, 845.1312500000129 - 0.4, 23000.0, 50.0, 1639.7999999999433, 63.499999999999346, 843.0000000000188 - 0.45, 23000.0, 50.0, 1662.1874999999948, 51.687499999999076, 841.5687500000182 - 0.5, 23000.0, 50.0, 1681.9000000000074, 40.29999999999917, 838.2000000000317 - 0.55, 23000.0, 50.0, 1694.6875000000268, 29.01249999999929, 831.2062500000482 - 0.6000000000000001, 23000.0, 50.0, 1696.3000000000534, 17.499999999999446, 818.9000000000676 - 0.0, 25000.0, 20.0, 151.59999999999982, 42.10000000000013, 398.89999999999964 - 0.05, 25000.0, 20.0, 153.3249999999999, 31.987500000000075, 398.0874999999998 - 0.1, 25000.0, 20.0, 154.99999999999994, 22.000000000000036, 394.3999999999998 -0.15000000000000002, 25000.0, 20.0, 156.64999999999998, 12.162500000000009, 388.1124999999999 - 0.2, 25000.0, 20.0, 158.29999999999998, 2.4999999999999996, 379.49999999999994 - 0.25, 25000.0, 20.0, 159.97499999999997, -6.962500000000002, 368.83750000000003 -0.30000000000000004, 25000.0, 20.0, 161.7, -16.200000000000014, 356.4 -0.35000000000000003, 25000.0, 20.0, 163.49999999999997, -25.187500000000014, 342.46250000000003 - 0.4, 25000.0, 20.0, 165.4, -33.90000000000001, 327.30000000000007 - 0.45, 25000.0, 20.0, 167.4375, -42.31250000000002, 311.1875000000001 - 0.5, 25000.0, 20.0, 169.60000000000008, -50.40000000000005, 294.40000000000026 - 0.55, 25000.0, 20.0, 171.8875000000001, -58.137500000000095, 277.2125000000005 - 0.6000000000000001, 25000.0, 20.0, 174.30000000000018, -65.50000000000014, 259.9000000000007 - 0.0, 25000.0, 22.0, 241.95125704127386, 50.90270658434611, 385.8578449206611 - 0.05, 25000.0, 22.0, 245.14362131919492, 40.19482681519602, 385.52024975697776 - 0.1, 25000.0, 22.0, 248.09498664273056, 29.56999130795504, 382.88285506326974 -0.15000000000000002, 25000.0, 22.0, 250.8772925742111, 19.06071623838375, 378.1556221299986 - 0.2, 25000.0, 22.0, 253.56247867596676, 8.699517782242834, 371.54851224762547 - 0.25, 25000.0, 22.0, 256.2224845103278, -1.4810878847070943, 363.27148670661177 -0.30000000000000004, 25000.0, 22.0, 258.9292496396246, -11.448584586705408, 353.53450679741826 -0.35000000000000003, 25000.0, 22.0, 261.7547136261871, -21.170456147991448, 342.54753381050676 - 0.4, 25000.0, 22.0, 264.7708160323461, -30.61418639280456, 330.5205290363385 - 0.45, 25000.0, 22.0, 268.1218756657849, -39.74280195885499, 317.6538775540623 - 0.5, 25000.0, 22.0, 271.6626943527759, -48.537158229969606, 304.186269288079 - 0.55, 25000.0, 22.0, 275.320453164946, -56.97365340344617, 290.34681795148015 - 0.6000000000000001, 25000.0, 22.0, 279.0223331739218, -65.02868567658243, 276.3646372573555 - 0.0, 25000.0, 24.0, 332.7358087908592, 59.60542540026304, 394.7563405981032 - 0.05, 25000.0, 24.0, 337.02255396193095, 48.34429967448703, 394.9207783693084 - 0.1, 25000.0, 24.0, 341.0115654294547, 37.136941572909905, 393.064953831547 -0.15000000000000002, 25000.0, 24.0, 344.7955607212173, 26.023359183412012, 389.3698318564053 - 0.2, 25000.0, 24.0, 348.46725736500616, 15.043560593873645, 384.0163773154692 - 0.25, 25000.0, 24.0, 352.1193728886085, 4.237553892175132, 377.1855550803249 -0.30000000000000004, 25000.0, 24.0, 355.8446248198115, -6.3546528338032156, 369.05833002255827 -0.35000000000000003, 25000.0, 24.0, 359.7357306864027, -16.693051496181045, 359.8156670137558 - 0.4, 25000.0, 24.0, 363.8854080161693, -26.737634007078043, 349.638530925503 - 0.45, 25000.0, 24.0, 368.4771878328935, -36.441290938727164, 338.7053440169799 - 0.5, 25000.0, 24.0, 373.3313471763893, -45.78531822290834, 327.20469899699947 - 0.55, 25000.0, 24.0, 378.35897658247416, -54.7439104515149, 315.32264596197814 - 0.6000000000000001, 25000.0, 24.0, 383.4711665869615, -63.29126221644001, 303.24523500832737 - 0.0, 25000.0, 26.0, 423.5447320198051, 68.22679092400682, 418.0159138152125 - 0.05, 25000.0, 26.0, 428.84280094506863, 56.46698412617999, 418.7011821031492 - 0.1, 25000.0, 26.0, 433.820650894813, 44.73889618388727, 417.4556250681892 -0.15000000000000002, 25000.0, 26.0, 438.584557581118, 33.09001900924839, 414.45373051781286 - 0.2, 25000.0, 26.0, 443.24079671606216, 21.567844514383037, 409.8699862595003 - 0.25, 25000.0, 26.0, 447.8956440117248, 10.2198646114109, 403.87888010073203 -0.30000000000000004, 25000.0, 26.0, 452.65537518018533, -0.906428787548338, 396.65489984898835 -0.35000000000000003, 25000.0, 26.0, 457.62626593352246, -11.763543770374959, 388.3725333117494 - 0.4, 25000.0, 26.0, 462.9145919838156, -22.303988424949267, 379.2062682964957 - 0.45, 25000.0, 26.0, 468.7228121671103, -32.46962893917181, 369.3436217028667 - 0.5, 25000.0, 26.0, 474.86865282361526, -42.2448991008623, 358.91999406188114 - 0.55, 25000.0, 26.0, 481.2660234175299, -51.60359079786056, 348.0838149967373 - 0.6000000000000001, 25000.0, 26.0, 487.82883341304097, -60.51949591800643, 336.9835141306233 - 0.0, 25000.0, 28.0, 513.6199636951204, 76.84309889516511, 446.5656916816458 - 0.05, 25000.0, 28.0, 520.3245496631727, 64.63086306082172, 447.7434877567819 - 0.1, 25000.0, 28.0, 526.5590898932503, 52.43705869593119, 447.0346188211878 -0.15000000000000002, 25000.0, 28.0, 532.4663437017956, 40.315275607369024, 444.6090884731088 - 0.2, 25000.0, 28.0, 538.1890704052515, 28.31910360201067, 440.6369003107903 - 0.25, 25000.0, 28.0, 543.8700293200608, 16.502132486731586, 435.28805793247767 -0.30000000000000004, 25000.0, 28.0, 549.6519797626655, 4.917952068407205, 428.73256493641634 -0.35000000000000003, 25000.0, 28.0, 555.6776810495091, -6.379847846086974, 421.14042492085144 - 0.4, 25000.0, 28.0, 562.0898924970343, -17.337677449875503, 412.6816414840287 - 0.45, 25000.0, 28.0, 569.1636346707489, -27.882757292405415, 403.5518009128527 - 0.5, 25000.0, 28.0, 576.6448831399063, -38.01906649783386, 393.8441587395746 - 0.55, 25000.0, 28.0, 584.411874722831, -47.731394546640395, 383.677553185092 - 0.6000000000000001, 25000.0, 28.0, 592.3428462378449, -57.00453091930461, 373.1708224703091 - 0.0, 25000.0, 30.0, 603.6000000000109, 85.29999999999968, 477.3000000000175 - 0.05, 25000.0, 30.0, 611.8312500000076, 72.75624999999981, 479.0500000000102 - 0.1, 25000.0, 30.0, 619.4000000000045, 60.19999999999992, 478.9000000000048 -0.15000000000000002, 25000.0, 30.0, 626.4937500000018, 47.693749999999966, 477.0250000000015 - 0.2, 25000.0, 30.0, 633.2999999999995, 35.29999999999999, 473.59999999999997 - 0.25, 25000.0, 30.0, 640.0062499999977, 23.081249999999994, 468.80000000000035 -0.30000000000000004, 25000.0, 30.0, 646.7999999999962, 11.09999999999999, 462.8000000000023 -0.35000000000000003, 25000.0, 30.0, 653.8687499999953, -0.5812499999999836, 455.77500000000566 - 0.4, 25000.0, 30.0, 661.3999999999944, -11.899999999999919, 447.9000000000106 - 0.45, 25000.0, 30.0, 669.7625000000022, -22.76249999999985, 439.38749999999516 - 0.5, 25000.0, 30.0, 678.6000000000051, -33.19999999999982, 430.2999999999943 - 0.55, 25000.0, 30.0, 687.7375000000093, -43.212499999999835, 420.7374999999944 - 0.6000000000000001, 25000.0, 30.0, 697.0000000000143, -52.799999999999905, 410.79999999999575 - 0.0, 25000.0, 32.0, 695.1820221528478, 93.02833352578631, 508.44239304693116 - 0.05, 25000.0, 32.0, 704.2874031562056, 80.51861047853336, 511.25600422774704 - 0.1, 25000.0, 32.0, 712.7380781285342, 67.86747990303272, 511.93588990275197 -0.15000000000000002, 25000.0, 32.0, 720.7317621963222, 55.162548750262275, 510.70825021223425 - 0.2, 25000.0, 32.0, 728.4661704860584, 42.49142397119977, 507.79928529648197 - 0.25, 25000.0, 32.0, 736.1390181242319, 29.941712516822964, 503.43519529578356 -0.30000000000000004, 25000.0, 32.0, 743.9480202373309, 17.601021338109632, 497.84218035042727 -0.35000000000000003, 25000.0, 32.0, 752.0908919518446, 5.556957386037579, 491.2464406007012 - 0.4, 25000.0, 32.0, 760.765348394262, -6.102872388415417, 483.87417618689364 - 0.45, 25000.0, 32.0, 770.357515017709, -17.246357410436026, 476.0137487627696 - 0.5, 25000.0, 32.0, 780.4998759687913, -27.91940160055295, 467.7048739281892 - 0.55, 25000.0, 32.0, 791.0133257207673, -38.123405255459275, 459.0494287964895 - 0.6000000000000001, 25000.0, 32.0, 801.7187587468868, -47.85976867184798, 450.1492904810076 - 0.0, 25000.0, 34.0, 786.5108253280989, 101.66215219764653, 542.500832704856 - 0.05, 25000.0, 34.0, 796.496046953423, 88.88233974328466, 545.5403960165772 - 0.1, 25000.0, 34.0, 805.8395615323308, 75.9328556574415, 546.4856012991752 -0.15000000000000002, 25000.0, 34.0, 814.7471497981593, 62.9113061925594, 545.568600147564 - 0.2, 25000.0, 34.0, 823.4245924842445, 49.91529760108072, 543.0215441566559 - 0.25, 25000.0, 34.0, 832.0776703239227, 37.042436135447836, 539.0765849213642 -0.30000000000000004, 25000.0, 34.0, 840.9121640505306, 24.390328048103118, 533.9658740366024 -0.35000000000000003, 25000.0, 34.0, 850.1338543974036, 12.056579591488962, 527.9215630972831 - 0.4, 25000.0, 34.0, 859.948522097879, 0.13879701804774058, 521.1758036983193 - 0.45, 25000.0, 34.0, 870.7517120575288, -11.214669746254042, 514.0340418454816 - 0.5, 25000.0, 34.0, 882.1799124929983, -22.05844546954662, 506.5085459011072 - 0.55, 25000.0, 34.0, 894.0593757931775, -32.39641124643689, 498.68487863838607 - 0.6000000000000001, 25000.0, 34.0, 906.2163543469519, -42.232448171531345, 490.64860283051075 - 0.0, 25000.0, 36.0, 877.1807430555197, 111.54572710370968, 579.3247401600911 - 0.05, 25000.0, 36.0, 888.2258781266335, 98.03180935853514, 581.6296263702412 - 0.1, 25000.0, 36.0, 898.5925098464586, 84.4786654329943, 582.2350219556401 -0.15000000000000002, 25000.0, 36.0, 908.502272255664, 70.96772824481873, 581.3140019056958 - 0.2, 25000.0, 36.0, 918.1767993949203, 57.58043071173989, 579.0396412098165 - 0.25, 25000.0, 36.0, 927.8377253048972, 44.398205751489364, 575.5850148574101 -0.30000000000000004, 25000.0, 36.0, 937.7066840262646, 31.502486281798657, 571.1231978378848 -0.35000000000000003, 25000.0, 36.0, 948.005309599693, 18.974705220399347, 565.8272651406484 - 0.4, 25000.0, 36.0, 958.9552360658516, 6.896295485022957, 559.8702917551093 - 0.45, 25000.0, 36.0, 970.9788417742836, -4.607682726779066, 553.4895509863871 - 0.5, 25000.0, 36.0, 983.6955278390687, -15.586678336735556, 546.6655228767355 - 0.55, 25000.0, 36.0, 996.9254396831798, -26.046512986757104, 539.4428857841051 - 0.6000000000000001, 25000.0, 36.0, 1010.4887227295783, -35.99300831875344, 531.8663180664545 - 0.0, 25000.0, 38.0, 969.5296526832667, 120.19439813099795, 613.1493488560158 - 0.05, 25000.0, 38.0, 981.1988817828051, 106.38823686190113, 616.5100610016673 - 0.1, 25000.0, 38.0, 992.2647667886813, 92.6207127457395, 618.0669520571341 -0.15000000000000002, 25000.0, 38.0, 1002.9504325345387, 78.95473556946183, 618.0028559761815 - 0.2, 25000.0, 38.0, 1013.4790038540203, 65.45321512001692, 616.5006067125747 - 0.25, 25000.0, 38.0, 1024.0736055807704, 52.17906118435353, 613.7430382200785 -0.30000000000000004, 25000.0, 38.0, 1034.957362548432, 39.19518354942046, 609.9129844524584 -0.35000000000000003, 25000.0, 38.0, 1046.353399590649, 26.564492002166542, 605.1932793634794 - 0.4, 25000.0, 38.0, 1058.4848415410652, 14.349896329540512, 599.7667569069067 - 0.45, 25000.0, 38.0, 1071.7952517995625, 2.630338952531406, 593.8845991307642 - 0.5, 25000.0, 38.0, 1085.8464395010785, -8.579368244033816, 587.5245957060481 - 0.55, 25000.0, 38.0, 1100.4206523468429, -19.248380741288596, 580.7328843980207 - 0.6000000000000001, 25000.0, 38.0, 1115.3001380380633, -29.34585402036595, 573.5556029719411 - 0.0, 25000.0, 40.0, 1059.49999999999, 129.49999999999943, 650.5999999999792 - 0.05, 25000.0, 40.0, 1072.5812499999954, 115.6312499999999, 654.1937499999875 - 0.1, 25000.0, 40.0, 1084.8999999999987, 101.70000000000009, 655.9999999999937 -0.15000000000000002, 25000.0, 40.0, 1096.7187500000007, 87.79375000000012, 656.206249999998 - 0.2, 25000.0, 40.0, 1108.3000000000018, 74.00000000000001, 655.0000000000009 - 0.25, 25000.0, 40.0, 1119.9062500000011, 60.406249999999794, 652.5687500000025 -0.30000000000000004, 25000.0, 40.0, 1131.7999999999993, 47.099999999999504, 649.100000000003 -0.35000000000000003, 25000.0, 40.0, 1144.2437499999958, 34.1687499999992, 644.7812500000031 - 0.4, 25000.0, 40.0, 1157.499999999991, 21.699999999998827, 639.8000000000025 - 0.45, 25000.0, 40.0, 1172.0875000000092, 9.800000000000143, 634.3999999999983 - 0.5, 25000.0, 40.0, 1187.500000000017, -1.4999999999997695, 628.6000000000013 - 0.55, 25000.0, 40.0, 1203.4875000000288, -12.149999999999688, 622.4750000000071 - 0.6000000000000001, 25000.0, 40.0, 1219.8000000000438, -22.099999999999582, 616.1000000000158 - 0.0, 25000.0, 42.0, 1150.1595171493389, 141.44438335312452, 687.2978643429593 - 0.05, 25000.0, 42.0, 1164.3987232852676, 126.29636767087781, 691.6048687166581 - 0.1, 25000.0, 42.0, 1177.8017641434783, 111.40260001000937, 694.043546745652 -0.15000000000000002, 25000.0, 42.0, 1190.6538532809004, 96.80309892182427, 694.817090159474 - 0.2, 25000.0, 42.0, 1203.2402042544677, 82.5378829576276, 694.1286906876581 - 0.25, 25000.0, 42.0, 1215.8460306211095, 68.64697066872448, 692.1815400597375 -0.30000000000000004, 25000.0, 42.0, 1228.7565459377572, 55.17038060641985, 689.178830005246 -0.35000000000000003, 25000.0, 42.0, 1242.2569637613421, 42.148131322018884, 685.3237522537161 - 0.4, 25000.0, 42.0, 1256.6324976487952, 29.620241366826612, 680.8194985346819 - 0.45, 25000.0, 42.0, 1272.4423165895464, 17.5968546219187, 675.900585999929 - 0.5, 25000.0, 42.0, 1289.1497678430135, 6.207613649288966, 670.6762301122243 - 0.55, 25000.0, 42.0, 1306.4921541011058, -4.447713659297967, 665.2869717565802 - 0.6000000000000001, 25000.0, 42.0, 1324.2067780557359, -14.269359412077575, 659.8733518180126 - 0.0, 25000.0, 44.0, 1241.9864133423584, 148.62330223032168, 724.296458614609 - 0.05, 25000.0, 44.0, 1257.0083864979183, 134.32993080803695, 729.5978892605846 - 0.1, 25000.0, 44.0, 1271.2364040936777, 119.95214766959454, 732.8033392600573 -0.15000000000000002, 25000.0, 44.0, 1284.9593884658823, 105.5940313416804, 734.1667777861402 - 0.2, 25000.0, 44.0, 1298.4662619507776, 91.35966035098043, 733.9421740119484 - 0.25, 25000.0, 44.0, 1312.0459468846086, 77.35311322418063, 732.3834971105961 -0.30000000000000004, 25000.0, 44.0, 1325.9873656036211, 63.67846848796691, 729.7447162551969 -0.35000000000000003, 25000.0, 44.0, 1340.5794404440603, 50.43980466902523, 726.2798006188658 - 0.4, 25000.0, 44.0, 1356.1110937421709, 37.74120029404157, 722.2427193747169 - 0.45, 25000.0, 44.0, 1373.1487145394524, 25.715058046175336, 717.970546707151 - 0.5, 25000.0, 44.0, 1391.1488250564187, 14.38048398269299, 713.4679367554318 - 0.55, 25000.0, 44.0, 1409.845414218853, 3.784908317335386, 708.8226486701092 - 0.6000000000000001, 25000.0, 44.0, 1428.9724709525308, -6.024238736157091, 704.1224416017326 - 0.0, 25000.0, 46.0, 1332.4732076794496, 158.01194265055568, 763.7287035873644 - 0.05, 25000.0, 46.0, 1348.6274141069825, 143.6512495601452, 769.0971857530686 - 0.1, 25000.0, 46.0, 1363.9243885415851, 129.1612636414931, 772.4054561074395 -0.15000000000000002, 25000.0, 46.0, 1378.6746848285457, 114.66102379197999, 773.9222454319282 - 0.2, 25000.0, 46.0, 1393.1888568131533, 100.2695689089865, 773.9162845079862 - 0.25, 25000.0, 46.0, 1407.7774583406963, 86.10593788989318, 772.6563041170642 -0.30000000000000004, 25000.0, 46.0, 1422.7510432564625, 72.28916963208056, 770.411035040614 -0.35000000000000003, 25000.0, 46.0, 1438.4201654057415, 58.93830303292938, 767.4492080600861 - 0.4, 25000.0, 46.0, 1455.0953786338225, 46.172376989820194, 764.0395539569327 - 0.45, 25000.0, 46.0, 1473.386335000265, 34.15745501997476, 760.6215557481668 - 0.5, 25000.0, 46.0, 1492.7062937075318, 22.871502161250003, 756.9516875085569 - 0.55, 25000.0, 46.0, 1512.767612172347, 12.339508071344541, 752.9571755484434 - 0.6000000000000001, 25000.0, 46.0, 1533.2826478114403, 2.5864624079568066, 748.5652461781613 - 0.0, 25000.0, 48.0, 1422.4154131333469, 169.6928508986594, 808.3092865912829 - 0.05, 25000.0, 48.0, 1440.2041724674991, 154.39043080397389, 811.55359879396 - 0.1, 25000.0, 48.0, 1456.90009287839, 139.19117928259436, 813.5714023857277 -0.15000000000000002, 25000.0, 48.0, 1472.8667421506711, 124.18310700481167, 814.4911560142524 - 0.2, 25000.0, 48.0, 1488.4676880689935, 109.45422464091669, 814.4413183272009 - 0.25, 25000.0, 48.0, 1504.0664984180103, 95.09254286120022, 813.5503479722398 -0.30000000000000004, 25000.0, 48.0, 1520.026740982374, 81.18607233595301, 811.9467035970358 -0.35000000000000003, 25000.0, 48.0, 1536.7119835467356, 67.822823735466, 809.758843849256 - 0.4, 25000.0, 48.0, 1554.4857938957473, 55.09080773002993, 807.1152273765667 - 0.45, 25000.0, 48.0, 1574.0643454364542, 43.108594411632566, 804.1828283550147 - 0.5, 25000.0, 48.0, 1594.7533890863838, 31.872516185473394, 800.9745588471451 - 0.55, 25000.0, 48.0, 1616.2112813854876, 21.409464878448972, 797.5418464438903 - 0.6000000000000001, 25000.0, 48.0, 1638.0963788736972, 11.746332317455812, 793.9361187361783 - 0.0, 25000.0, 50.0, 1513.3999999999928, 179.1000000000028, 842.5000000000693 - 0.05, 25000.0, 50.0, 1532.1499999999935, 163.8750000000018, 848.3125000000408 - 0.1, 25000.0, 50.0, 1549.7999999999959, 148.70000000000095, 852.3000000000205 -0.15000000000000002, 25000.0, 50.0, 1566.7249999999979, 133.6750000000003, 854.6875000000069 - 0.2, 25000.0, 50.0, 1583.2999999999977, 118.89999999999976, 855.6999999999992 - 0.25, 25000.0, 50.0, 1599.8999999999953, 104.47499999999943, 855.5624999999956 -0.30000000000000004, 25000.0, 50.0, 1616.8999999999894, 90.49999999999928, 854.4999999999947 -0.35000000000000003, 25000.0, 50.0, 1634.6749999999786, 77.07499999999935, 852.7374999999953 - 0.4, 25000.0, 50.0, 1653.5999999999626, 64.29999999999964, 850.4999999999959 - 0.45, 25000.0, 50.0, 1674.4125000000208, 52.299999999999685, 848.1125000000059 - 0.5, 25000.0, 50.0, 1696.4000000000487, 41.09999999999972, 845.5000000000186 - 0.55, 25000.0, 50.0, 1719.2125000000883, 30.749999999999822, 842.6875000000389 - 0.6000000000000001, 25000.0, 50.0, 1742.50000000014, 21.29999999999999, 839.7000000000685 diff --git a/aviary/models/engines/turboshaft_1120hp_no_tailpipe.csv b/aviary/models/engines/turboshaft_1120hp_no_tailpipe.csv new file mode 100644 index 0000000000..3a68560fea --- /dev/null +++ b/aviary/models/engines/turboshaft_1120hp_no_tailpipe.csv @@ -0,0 +1,2096 @@ +# created 04/22/25 +# GASP_TS-derived engine deck converted from MAPS_1120hp.eng +# t4max: 50.0 +# t4cruise: 46.67 +# t4climb: 48.33 +# t4flight_idle: 20.0 +# xsfc: 0.0 +# cexp: 0.0 +# sls_horsepower: 1120.0 +# freeturbine_rpm: 24539.0 +# propeller_rpm: 1210.0 +# gearbox_ratio: 0.049308 +# torque_limit: 4861.4 +# sls_corrected_airflow: 7.9568 + +Mach Number (input), Altitude (ft, input), Throttle (input), Shaft Power Corrected (hp, output), Fuel Flow (lb/h, output) + 0.0, 0.0, 20.0, 112.0, 195.8 + 0.05, 0.0, 20.0, 111.769, 195.181 + 0.1, 0.0, 20.0, 111.1, 193.3 + 0.15, 0.0, 20.0, 110.006, 190.219 + 0.2, 0.0, 20.0, 108.5, 186.0 + 0.25, 0.0, 20.0, 106.588, 180.7 + 0.3, 0.0, 20.0, 104.3, 174.4 + 0.35, 0.0, 20.0, 101.65, 167.138 + 0.4, 0.0, 20.0, 98.7, 159.1 + 0.45, 0.0, 20.0, 95.5, 150.438 + 0.5, 0.0, 20.0, 92.1, 141.3 + 0.55, 0.0, 20.0, 88.55, 131.838 + 0.6, 0.0, 20.0, 84.9, 122.2 + 0.0, 0.0, 22.0, 179.345, 230.177 + 0.05, 0.0, 22.0, 178.975, 229.45 + 0.1, 0.0, 22.0, 177.904, 227.282 + 0.15, 0.0, 22.0, 176.152, 223.756 + 0.2, 0.0, 22.0, 173.74, 218.956 + 0.25, 0.0, 22.0, 170.673, 212.952 + 0.3, 0.0, 22.0, 167.015, 205.872 + 0.35, 0.0, 22.0, 162.813, 197.838 + 0.4, 0.0, 22.0, 158.131, 188.935 + 0.45, 0.0, 22.0, 153.028, 179.258 + 0.5, 0.0, 22.0, 147.562, 168.903 + 0.55, 0.0, 22.0, 141.795, 157.964 + 0.6, 0.0, 22.0, 135.783, 146.536 + 0.0, 0.0, 24.0, 246.472, 262.388 + 0.05, 0.0, 24.0, 245.964, 261.584 + 0.1, 0.0, 24.0, 244.492, 259.198 + 0.15, 0.0, 24.0, 242.085, 255.317 + 0.2, 0.0, 24.0, 238.77, 250.029 + 0.25, 0.0, 24.0, 234.555, 243.401 + 0.3, 0.0, 24.0, 229.527, 235.581 + 0.35, 0.0, 24.0, 223.747, 226.718 + 0.4, 0.0, 24.0, 217.305, 216.883 + 0.45, 0.0, 24.0, 210.289, 206.165 + 0.5, 0.0, 24.0, 202.781, 194.655 + 0.55, 0.0, 24.0, 194.867, 182.442 + 0.6, 0.0, 24.0, 186.632, 169.619 + 0.0, 0.0, 26.0, 313.528, 293.06 + 0.05, 0.0, 26.0, 312.88, 292.204 + 0.1, 0.0, 26.0, 311.008, 289.634 + 0.15, 0.0, 26.0, 307.946, 285.435 + 0.2, 0.0, 26.0, 303.73, 279.694 + 0.25, 0.0, 26.0, 298.37, 272.474 + 0.3, 0.0, 26.0, 291.973, 263.934 + 0.35, 0.0, 26.0, 284.603, 254.219 + 0.4, 0.0, 26.0, 276.395, 243.433 + 0.45, 0.0, 26.0, 267.461, 231.69 + 0.5, 0.0, 26.0, 257.919, 219.105 + 0.55, 0.0, 26.0, 247.883, 205.791 + 0.6, 0.0, 26.0, 237.468, 191.863 + 0.0, 0.0, 28.0, 380.711, 322.897 + 0.05, 0.0, 28.0, 379.919, 322.02 + 0.1, 0.0, 28.0, 377.646, 319.249 + 0.15, 0.0, 28.0, 373.934, 314.689 + 0.2, 0.0, 28.0, 368.82, 308.446 + 0.25, 0.0, 28.0, 362.311, 300.601 + 0.3, 0.0, 28.0, 354.543, 291.328 + 0.35, 0.0, 28.0, 345.602, 280.784 + 0.4, 0.0, 28.0, 335.641, 269.103 + 0.45, 0.0, 28.0, 324.797, 256.427 + 0.5, 0.0, 28.0, 313.206, 242.896 + 0.55, 0.0, 28.0, 301.005, 228.651 + 0.6, 0.0, 28.0, 288.331, 213.833 + 0.0, 0.0, 30.0, 448.0, 352.3 + 0.05, 0.0, 30.0, 447.075, 351.388 + 0.1, 0.0, 30.0, 444.4, 348.4 + 0.15, 0.0, 30.0, 440.025, 343.462 + 0.2, 0.0, 30.0, 434.0, 336.7 + 0.25, 0.0, 30.0, 426.337, 328.212 + 0.3, 0.0, 30.0, 417.2, 318.2 + 0.35, 0.0, 30.0, 406.7, 306.844 + 0.4, 0.0, 30.0, 395.0, 294.3 + 0.45, 0.0, 30.0, 382.25, 280.731 + 0.5, 0.0, 30.0, 368.6, 266.3 + 0.55, 0.0, 30.0, 354.2, 251.169 + 0.6, 0.0, 30.0, 339.2, 235.5 + 0.0, 0.0, 32.0, 515.289, 381.673 + 0.05, 0.0, 32.0, 514.297, 380.608 + 0.1, 0.0, 32.0, 511.209, 377.411 + 0.15, 0.0, 32.0, 506.12, 372.174 + 0.2, 0.0, 32.0, 499.125, 364.992 + 0.25, 0.0, 32.0, 490.302, 355.906 + 0.3, 0.0, 32.0, 479.802, 345.165 + 0.35, 0.0, 32.0, 467.74, 332.975 + 0.4, 0.0, 32.0, 454.297, 319.509 + 0.45, 0.0, 32.0, 439.64, 304.949 + 0.5, 0.0, 32.0, 423.932, 289.476 + 0.55, 0.0, 32.0, 407.339, 273.272 + 0.6, 0.0, 32.0, 390.026, 256.517 + 0.0, 0.0, 34.0, 582.446, 410.785 + 0.05, 0.0, 34.0, 581.374, 409.615 + 0.1, 0.0, 34.0, 577.875, 406.207 + 0.15, 0.0, 34.0, 572.085, 400.646 + 0.2, 0.0, 34.0, 564.136, 393.014 + 0.25, 0.0, 34.0, 554.155, 383.325 + 0.3, 0.0, 34.0, 542.294, 371.873 + 0.35, 0.0, 34.0, 528.681, 358.904 + 0.4, 0.0, 34.0, 513.507, 344.57 + 0.45, 0.0, 34.0, 496.95, 329.051 + 0.5, 0.0, 34.0, 479.184, 312.521 + 0.55, 0.0, 34.0, 460.387, 295.158 + 0.6, 0.0, 34.0, 440.735, 277.139 + 0.0, 0.0, 36.0, 649.488, 439.68 + 0.05, 0.0, 36.0, 648.278, 438.495 + 0.1, 0.0, 36.0, 644.379, 434.871 + 0.15, 0.0, 36.0, 637.934, 428.925 + 0.2, 0.0, 36.0, 629.082, 420.772 + 0.25, 0.0, 36.0, 617.952, 410.464 + 0.3, 0.0, 36.0, 604.726, 398.314 + 0.35, 0.0, 36.0, 589.56, 384.614 + 0.4, 0.0, 36.0, 572.655, 369.476 + 0.45, 0.0, 36.0, 554.199, 353.058 + 0.5, 0.0, 36.0, 534.381, 335.515 + 0.55, 0.0, 36.0, 513.392, 317.006 + 0.6, 0.0, 36.0, 491.419, 297.686 + 0.0, 0.0, 38.0, 716.881, 468.889 + 0.05, 0.0, 38.0, 715.466, 467.608 + 0.1, 0.0, 38.0, 711.175, 463.745 + 0.15, 0.0, 38.0, 704.123, 457.426 + 0.2, 0.0, 38.0, 694.423, 448.778 + 0.25, 0.0, 38.0, 682.155, 437.869 + 0.3, 0.0, 38.0, 667.54, 424.996 + 0.35, 0.0, 38.0, 650.734, 410.408 + 0.4, 0.0, 38.0, 632.007, 394.307 + 0.45, 0.0, 38.0, 611.603, 376.91 + 0.5, 0.0, 38.0, 589.762, 358.431 + 0.55, 0.0, 38.0, 566.729, 339.084 + 0.6, 0.0, 38.0, 542.744, 319.085 + 0.0, 0.0, 40.0, 784.0, 497.7 + 0.05, 0.0, 40.0, 782.5, 496.344 + 0.1, 0.0, 40.0, 777.8, 492.3 + 0.15, 0.0, 40.0, 770.05, 485.681 + 0.2, 0.0, 40.0, 759.4, 476.6 + 0.25, 0.0, 40.0, 745.975, 465.094 + 0.3, 0.0, 40.0, 730.0, 451.5 + 0.35, 0.0, 40.0, 711.65, 436.1 + 0.4, 0.0, 40.0, 691.2, 419.1 + 0.45, 0.0, 40.0, 668.9, 400.725 + 0.5, 0.0, 40.0, 645.0, 381.2 + 0.55, 0.0, 40.0, 619.75, 360.75 + 0.6, 0.0, 40.0, 593.4, 339.6 + 0.0, 0.0, 42.0, 851.127, 526.592 + 0.05, 0.0, 42.0, 849.439, 525.133 + 0.1, 0.0, 42.0, 844.346, 520.851 + 0.15, 0.0, 42.0, 835.98, 513.868 + 0.2, 0.0, 42.0, 824.471, 504.308 + 0.25, 0.0, 42.0, 809.905, 492.233 + 0.3, 0.0, 42.0, 792.554, 477.955 + 0.35, 0.0, 42.0, 772.614, 461.722 + 0.4, 0.0, 42.0, 750.397, 443.79 + 0.45, 0.0, 42.0, 726.186, 424.413 + 0.5, 0.0, 42.0, 700.263, 403.846 + 0.55, 0.0, 42.0, 672.911, 382.341 + 0.6, 0.0, 42.0, 644.412, 360.154 + 0.0, 0.0, 44.0, 918.489, 555.522 + 0.05, 0.0, 44.0, 916.688, 553.979 + 0.1, 0.0, 44.0, 911.189, 549.503 + 0.15, 0.0, 44.0, 902.143, 542.197 + 0.2, 0.0, 44.0, 889.705, 532.166 + 0.25, 0.0, 44.0, 873.986, 519.407 + 0.3, 0.0, 44.0, 855.262, 504.345 + 0.35, 0.0, 44.0, 833.723, 487.345 + 0.4, 0.0, 44.0, 809.732, 468.584 + 0.45, 0.0, 44.0, 783.609, 448.286 + 0.5, 0.0, 44.0, 755.674, 426.674 + 0.55, 0.0, 44.0, 726.246, 403.974 + 0.6, 0.0, 44.0, 695.646, 380.408 + 0.0, 0.0, 46.0, 985.511, 584.447 + 0.05, 0.0, 46.0, 983.565, 582.834 + 0.1, 0.0, 46.0, 977.666, 578.128 + 0.15, 0.0, 46.0, 967.972, 570.457 + 0.2, 0.0, 46.0, 954.64, 559.954 + 0.25, 0.0, 46.0, 937.774, 546.661 + 0.3, 0.0, 46.0, 917.683, 530.968 + 0.35, 0.0, 46.0, 894.593, 513.202 + 0.4, 0.0, 46.0, 868.862, 493.591 + 0.45, 0.0, 46.0, 840.816, 472.388 + 0.5, 0.0, 46.0, 810.781, 449.846 + 0.55, 0.0, 46.0, 779.083, 426.217 + 0.6, 0.0, 46.0, 746.048, 401.755 + 0.0, 0.0, 48.0, 1052.87, 614.241 + 0.05, 0.0, 48.0, 1050.87, 612.542 + 0.1, 0.0, 48.0, 1044.56, 607.595 + 0.15, 0.0, 48.0, 1034.14, 599.542 + 0.2, 0.0, 48.0, 1019.83, 588.526 + 0.25, 0.0, 48.0, 1001.79, 574.597 + 0.3, 0.0, 48.0, 980.343, 558.175 + 0.35, 0.0, 48.0, 955.726, 539.631 + 0.4, 0.0, 48.0, 928.289, 519.161 + 0.45, 0.0, 48.0, 898.354, 497.005 + 0.5, 0.0, 48.0, 866.245, 473.402 + 0.55, 0.0, 48.0, 832.283, 448.593 + 0.6, 0.0, 48.0, 796.791, 422.816 + 0.0, 0.0, 50.0, 1120.0, 644.0 + 0.05, 0.0, 50.0, 1117.81, 642.281 + 0.1, 0.0, 50.0, 1111.1, 637.2 + 0.15, 0.0, 50.0, 1100.07, 628.869 + 0.2, 0.0, 50.0, 1084.9, 617.4 + 0.25, 0.0, 50.0, 1065.73, 602.762 + 0.3, 0.0, 50.0, 1042.9, 585.5 + 0.35, 0.0, 50.0, 1016.65, 566.094 + 0.4, 0.0, 50.0, 987.4, 544.7 + 0.45, 0.0, 50.0, 955.525, 521.556 + 0.5, 0.0, 50.0, 921.4, 496.9 + 0.55, 0.0, 50.0, 885.4, 470.969 + 0.6, 0.0, 50.0, 847.9, 444.0 + 0.0, 1500.0, 20.0, 95.7, 187.4 + 0.05, 1500.0, 20.0, 95.4674, 186.781 + 0.1, 1500.0, 20.0, 94.9, 184.9 + 0.15, 1500.0, 20.0, 93.989, 181.838 + 0.2, 1500.0, 20.0, 92.7253, 177.677 + 0.25, 1500.0, 20.0, 91.1, 172.5 + 0.3, 1500.0, 20.0, 89.0799, 166.387 + 0.35, 1500.0, 20.0, 86.8431, 159.419 + 0.4, 1500.0, 20.0, 84.4, 151.7 + 0.45, 1500.0, 20.0, 81.6979, 143.354 + 0.5, 1500.0, 20.0, 78.7, 134.5 + 0.55, 1500.0, 20.0, 75.3693, 125.257 + 0.6, 1500.0, 20.0, 71.6689, 115.744 + 0.0, 1500.0, 22.0, 153.244, 216.562 + 0.05, 1500.0, 22.0, 152.965, 215.965 + 0.1, 1500.0, 22.0, 152.04, 213.922 + 0.15, 1500.0, 22.0, 150.511, 210.539 + 0.2, 1500.0, 22.0, 148.416, 205.924 + 0.25, 1500.0, 22.0, 145.795, 200.182 + 0.3, 1500.0, 22.0, 142.693, 193.43 + 0.35, 1500.0, 22.0, 139.099, 185.693 + 0.4, 1500.0, 22.0, 135.072, 177.096 + 0.45, 1500.0, 22.0, 130.709, 167.813 + 0.5, 1500.0, 22.0, 126.099, 158.003 + 0.55, 1500.0, 22.0, 121.331, 147.829 + 0.6, 1500.0, 22.0, 116.491, 137.45 + 0.0, 1500.0, 24.0, 210.602, 244.57 + 0.05, 1500.0, 24.0, 210.212, 243.902 + 0.1, 1500.0, 24.0, 208.946, 241.676 + 0.15, 1500.0, 24.0, 206.853, 237.992 + 0.2, 1500.0, 24.0, 203.98, 232.95 + 0.25, 1500.0, 24.0, 200.377, 226.65 + 0.3, 1500.0, 24.0, 196.095, 219.184 + 0.35, 1500.0, 24.0, 191.153, 210.687 + 0.4, 1500.0, 24.0, 185.63, 201.293 + 0.45, 1500.0, 24.0, 179.642, 191.147 + 0.5, 1500.0, 24.0, 173.296, 180.392 + 0.55, 1500.0, 24.0, 166.697, 169.173 + 0.6, 1500.0, 24.0, 159.953, 157.631 + 0.0, 1500.0, 26.0, 267.898, 271.677 + 0.05, 1500.0, 26.0, 267.367, 270.898 + 0.1, 1500.0, 26.0, 265.762, 268.479 + 0.15, 1500.0, 26.0, 263.125, 264.5 + 0.2, 1500.0, 26.0, 259.498, 259.045 + 0.25, 1500.0, 26.0, 254.923, 252.197 + 0.3, 1500.0, 26.0, 249.426, 244.01 + 0.35, 1500.0, 26.0, 243.144, 234.774 + 0.4, 1500.0, 26.0, 236.162, 224.621 + 0.45, 1500.0, 26.0, 228.558, 213.64 + 0.5, 1500.0, 26.0, 220.412, 201.93 + 0.55, 1500.0, 26.0, 211.804, 189.589 + 0.6, 1500.0, 26.0, 202.812, 176.717 + 0.0, 1500.0, 28.0, 325.304, 298.13 + 0.05, 1500.0, 28.0, 324.641, 297.278 + 0.1, 1500.0, 28.0, 322.679, 294.664 + 0.15, 1500.0, 28.0, 319.472, 290.377 + 0.2, 1500.0, 28.0, 315.071, 284.504 + 0.25, 1500.0, 28.0, 309.529, 277.132 + 0.3, 1500.0, 28.0, 302.883, 268.316 + 0.35, 1500.0, 28.0, 295.275, 258.389 + 0.4, 1500.0, 28.0, 286.799, 247.472 + 0.45, 1500.0, 28.0, 277.549, 235.613 + 0.5, 1500.0, 28.0, 267.618, 222.879 + 0.55, 1500.0, 28.0, 257.099, 209.336 + 0.6, 1500.0, 28.0, 246.087, 195.05 + 0.0, 1500.0, 30.0, 382.8, 324.2 + 0.05, 1500.0, 30.0, 382.023, 323.306 + 0.1, 1500.0, 30.0, 379.7, 320.5 + 0.15, 1500.0, 30.0, 375.906, 315.891 + 0.2, 1500.0, 30.0, 370.714, 309.588 + 0.25, 1500.0, 30.0, 364.2, 301.7 + 0.3, 1500.0, 30.0, 356.436, 292.313 + 0.35, 1500.0, 30.0, 347.497, 281.708 + 0.4, 1500.0, 30.0, 337.5, 270.0 + 0.45, 1500.0, 30.0, 326.588, 257.241 + 0.5, 1500.0, 30.0, 314.9, 243.5 + 0.55, 1500.0, 30.0, 302.572, 228.844 + 0.6, 1500.0, 30.0, 289.743, 213.34 + 0.0, 1500.0, 32.0, 440.296, 350.244 + 0.05, 1500.0, 32.0, 439.429, 349.31 + 0.1, 1500.0, 32.0, 436.776, 346.31 + 0.15, 1500.0, 32.0, 432.42, 341.371 + 0.2, 1500.0, 32.0, 426.444, 334.622 + 0.25, 1500.0, 32.0, 418.933, 326.187 + 0.3, 1500.0, 32.0, 409.962, 316.183 + 0.35, 1500.0, 32.0, 399.654, 304.83 + 0.4, 1500.0, 32.0, 388.146, 292.281 + 0.45, 1500.0, 32.0, 375.601, 278.673 + 0.5, 1500.0, 32.0, 362.176, 264.144 + 0.55, 1500.0, 32.0, 348.026, 248.834 + 0.6, 1500.0, 32.0, 333.308, 232.884 + 0.0, 1500.0, 34.0, 497.685, 376.172 + 0.05, 1500.0, 34.0, 496.712, 375.175 + 0.1, 1500.0, 34.0, 493.718, 371.971 + 0.15, 1500.0, 34.0, 488.796, 366.701 + 0.2, 1500.0, 34.0, 482.037, 359.508 + 0.25, 1500.0, 34.0, 473.532, 350.53 + 0.3, 1500.0, 34.0, 463.358, 339.907 + 0.35, 1500.0, 34.0, 451.7, 327.788 + 0.4, 1500.0, 34.0, 438.711, 314.373 + 0.45, 1500.0, 34.0, 424.556, 299.908 + 0.5, 1500.0, 34.0, 409.399, 284.626 + 0.55, 1500.0, 34.0, 393.401, 268.761 + 0.6, 1500.0, 34.0, 376.725, 252.546 + 0.0, 1500.0, 36.0, 554.972, 401.98 + 0.05, 1500.0, 36.0, 553.871, 400.888 + 0.1, 1500.0, 36.0, 550.52, 397.475 + 0.15, 1500.0, 36.0, 545.021, 391.889 + 0.2, 1500.0, 36.0, 537.479, 384.273 + 0.25, 1500.0, 36.0, 527.996, 374.772 + 0.3, 1500.0, 36.0, 516.659, 363.533 + 0.35, 1500.0, 36.0, 503.684, 350.661 + 0.4, 1500.0, 36.0, 489.234, 336.392 + 0.45, 1500.0, 36.0, 473.476, 321.045 + 0.5, 1500.0, 36.0, 456.575, 304.919 + 0.55, 1500.0, 36.0, 438.697, 288.31 + 0.6, 1500.0, 36.0, 420.008, 271.519 + 0.0, 1500.0, 38.0, 612.504, 427.669 + 0.05, 1500.0, 38.0, 611.34, 426.483 + 0.1, 1500.0, 38.0, 607.673, 422.908 + 0.15, 1500.0, 38.0, 601.624, 417.069 + 0.2, 1500.0, 38.0, 593.309, 409.09 + 0.25, 1500.0, 38.0, 582.85, 399.095 + 0.3, 1500.0, 38.0, 570.35, 387.19 + 0.35, 1500.0, 38.0, 556.012, 373.633 + 0.4, 1500.0, 38.0, 540.021, 358.631 + 0.45, 1500.0, 38.0, 522.582, 342.4 + 0.5, 1500.0, 38.0, 503.893, 325.156 + 0.55, 1500.0, 38.0, 484.154, 307.11 + 0.6, 1500.0, 38.0, 463.564, 288.478 + 0.0, 1500.0, 40.0, 669.9, 453.3 + 0.05, 1500.0, 40.0, 668.543, 452.059 + 0.1, 1500.0, 40.0, 664.5, 448.3 + 0.15, 1500.0, 40.0, 657.886, 442.152 + 0.2, 1500.0, 40.0, 648.815, 433.743 + 0.25, 1500.0, 40.0, 637.4, 423.2 + 0.3, 1500.0, 40.0, 623.736, 410.616 + 0.35, 1500.0, 40.0, 608.069, 396.385 + 0.4, 1500.0, 40.0, 590.6, 380.7 + 0.45, 1500.0, 40.0, 571.541, 363.69 + 0.5, 1500.0, 40.0, 551.1, 345.5 + 0.55, 1500.0, 40.0, 529.487, 326.276 + 0.6, 1500.0, 40.0, 506.91, 306.162 + 0.0, 1500.0, 42.0, 727.216, 479.057 + 0.05, 1500.0, 42.0, 725.815, 477.737 + 0.1, 1500.0, 42.0, 721.441, 473.734 + 0.15, 1500.0, 42.0, 714.241, 467.206 + 0.2, 1500.0, 42.0, 704.358, 458.311 + 0.25, 1500.0, 42.0, 691.938, 447.207 + 0.3, 1500.0, 42.0, 677.115, 434.032 + 0.35, 1500.0, 42.0, 660.083, 419.098 + 0.4, 1500.0, 42.0, 641.08, 402.615 + 0.45, 1500.0, 42.0, 620.397, 384.766 + 0.5, 1500.0, 42.0, 598.31, 365.743 + 0.55, 1500.0, 42.0, 575.098, 345.734 + 0.6, 1500.0, 42.0, 551.036, 324.931 + 0.0, 1500.0, 44.0, 784.802, 504.794 + 0.05, 1500.0, 44.0, 783.261, 503.448 + 0.1, 1500.0, 44.0, 778.536, 499.281 + 0.15, 1500.0, 44.0, 770.773, 492.455 + 0.2, 1500.0, 44.0, 760.116, 483.133 + 0.25, 1500.0, 44.0, 746.711, 471.478 + 0.3, 1500.0, 44.0, 730.682, 457.628 + 0.35, 1500.0, 44.0, 712.314, 441.917 + 0.4, 1500.0, 44.0, 691.847, 424.582 + 0.45, 1500.0, 44.0, 669.533, 405.849 + 0.5, 1500.0, 44.0, 645.622, 385.947 + 0.55, 1500.0, 44.0, 620.362, 365.103 + 0.6, 1500.0, 44.0, 594.003, 343.547 + 0.0, 1500.0, 46.0, 841.998, 530.406 + 0.05, 1500.0, 46.0, 840.365, 528.958 + 0.1, 1500.0, 46.0, 835.319, 524.581 + 0.15, 1500.0, 46.0, 827.013, 517.44 + 0.2, 1500.0, 46.0, 815.6, 507.701 + 0.25, 1500.0, 46.0, 801.233, 495.528 + 0.3, 1500.0, 46.0, 784.045, 481.058 + 0.35, 1500.0, 46.0, 764.331, 464.657 + 0.4, 1500.0, 46.0, 742.353, 446.557 + 0.45, 1500.0, 46.0, 718.39, 426.952 + 0.5, 1500.0, 46.0, 692.717, 406.047 + 0.55, 1500.0, 46.0, 665.608, 384.046 + 0.6, 1500.0, 46.0, 637.338, 361.152 + 0.0, 1500.0, 48.0, 899.584, 556.148 + 0.05, 1500.0, 48.0, 897.873, 554.658 + 0.1, 1500.0, 48.0, 892.466, 550.088 + 0.15, 1500.0, 48.0, 883.553, 542.618 + 0.2, 1500.0, 48.0, 871.319, 532.429 + 0.25, 1500.0, 48.0, 855.954, 519.701 + 0.3, 1500.0, 48.0, 837.637, 504.591 + 0.35, 1500.0, 48.0, 816.599, 487.461 + 0.4, 1500.0, 48.0, 793.115, 468.559 + 0.45, 1500.0, 48.0, 767.502, 448.111 + 0.5, 1500.0, 48.0, 740.068, 426.348 + 0.55, 1500.0, 48.0, 711.12, 403.501 + 0.6, 1500.0, 48.0, 680.965, 379.802 + 0.0, 1500.0, 50.0, 956.9, 581.8 + 0.05, 1500.0, 50.0, 955.029, 580.243 + 0.1, 1500.0, 50.0, 949.3, 575.5 + 0.15, 1500.0, 50.0, 939.877, 567.746 + 0.2, 1500.0, 50.0, 926.923, 557.155 + 0.25, 1500.0, 50.0, 910.6, 543.9 + 0.3, 1500.0, 50.0, 891.036, 528.117 + 0.35, 1500.0, 50.0, 868.64, 510.273 + 0.4, 1500.0, 50.0, 843.7, 490.6 + 0.45, 1500.0, 50.0, 816.493, 469.252 + 0.5, 1500.0, 50.0, 787.3, 446.4 + 0.55, 1500.0, 50.0, 756.401, 422.218 + 0.6, 1500.0, 50.0, 724.077, 396.878 + 0.0, 3000.0, 20.0, 101.8, 192.7 + 0.05, 3000.0, 20.0, 101.538, 192.092 + 0.1, 3000.0, 20.0, 100.9, 190.2 + 0.15, 3000.0, 20.0, 99.8935, 187.102 + 0.2, 3000.0, 20.0, 98.5247, 182.876 + 0.25, 3000.0, 20.0, 96.8, 177.6 + 0.3, 3000.0, 20.0, 94.718, 171.351 + 0.35, 3000.0, 20.0, 92.342, 164.206 + 0.4, 3000.0, 20.0, 89.7, 156.3 + 0.45, 3000.0, 20.0, 86.812, 147.809 + 0.5, 3000.0, 20.0, 83.7, 138.9 + 0.55, 3000.0, 20.0, 80.3861, 129.738 + 0.6, 3000.0, 20.0, 76.8922, 120.49 + 0.0, 3000.0, 22.0, 162.929, 223.314 + 0.05, 3000.0, 22.0, 162.645, 222.592 + 0.1, 3000.0, 22.0, 161.654, 220.49 + 0.15, 3000.0, 22.0, 160.009, 217.078 + 0.2, 3000.0, 22.0, 157.767, 212.422 + 0.25, 3000.0, 22.0, 154.982, 206.591 + 0.3, 3000.0, 22.0, 151.728, 199.637 + 0.35, 3000.0, 22.0, 147.926, 191.723 + 0.4, 3000.0, 22.0, 143.636, 182.962 + 0.45, 3000.0, 22.0, 138.97, 173.467 + 0.5, 3000.0, 22.0, 134.028, 163.348 + 0.55, 3000.0, 22.0, 128.91, 152.718 + 0.6, 3000.0, 22.0, 123.715, 141.688 + 0.0, 3000.0, 24.0, 223.924, 252.576 + 0.05, 3000.0, 24.0, 223.503, 251.789 + 0.1, 3000.0, 24.0, 222.147, 249.494 + 0.15, 3000.0, 24.0, 219.913, 245.758 + 0.2, 3000.0, 24.0, 216.858, 240.649 + 0.25, 3000.0, 24.0, 213.041, 234.234 + 0.3, 3000.0, 24.0, 208.53, 226.557 + 0.35, 3000.0, 24.0, 203.289, 217.851 + 0.4, 3000.0, 24.0, 197.398, 208.242 + 0.45, 3000.0, 24.0, 190.993, 197.832 + 0.5, 3000.0, 24.0, 184.194, 186.729 + 0.55, 3000.0, 24.0, 177.123, 175.04 + 0.6, 3000.0, 24.0, 169.901, 162.872 + 0.0, 3000.0, 26.0, 284.876, 280.87 + 0.05, 3000.0, 26.0, 284.277, 280.038 + 0.1, 3000.0, 26.0, 282.553, 277.552 + 0.15, 3000.0, 26.0, 279.748, 273.487 + 0.2, 3000.0, 26.0, 275.902, 267.915 + 0.25, 3000.0, 26.0, 271.059, 260.912 + 0.3, 3000.0, 26.0, 265.253, 252.522 + 0.35, 3000.0, 26.0, 258.568, 243.029 + 0.4, 3000.0, 26.0, 251.102, 232.58 + 0.45, 3000.0, 26.0, 242.976, 221.291 + 0.5, 3000.0, 26.0, 234.306, 209.285 + 0.55, 3000.0, 26.0, 225.206, 196.686 + 0.6, 3000.0, 26.0, 215.791, 183.617 + 0.0, 3000.0, 28.0, 345.9, 308.624 + 0.05, 3000.0, 28.0, 345.197, 307.719 + 0.1, 3000.0, 28.0, 343.119, 305.025 + 0.15, 3000.0, 28.0, 339.718, 300.626 + 0.2, 3000.0, 28.0, 335.044, 294.605 + 0.25, 3000.0, 28.0, 329.15, 287.046 + 0.3, 3000.0, 28.0, 322.073, 278.004 + 0.35, 3000.0, 28.0, 313.955, 267.777 + 0.4, 3000.0, 28.0, 304.909, 256.507 + 0.45, 3000.0, 28.0, 295.054, 244.293 + 0.5, 3000.0, 28.0, 284.508, 231.247 + 0.55, 3000.0, 28.0, 273.389, 217.477 + 0.6, 3000.0, 28.0, 261.816, 203.096 + 0.0, 3000.0, 30.0, 407.0, 336.1 + 0.05, 3000.0, 30.0, 406.231, 335.111 + 0.1, 3000.0, 30.0, 403.8, 332.2 + 0.15, 3000.0, 30.0, 399.783, 327.464 + 0.2, 3000.0, 30.0, 394.258, 320.999 + 0.25, 3000.0, 30.0, 387.3, 312.9 + 0.3, 3000.0, 30.0, 378.976, 303.239 + 0.35, 3000.0, 30.0, 369.434, 292.295 + 0.4, 3000.0, 30.0, 358.8, 280.2 + 0.45, 3000.0, 30.0, 347.211, 267.037 + 0.5, 3000.0, 30.0, 334.8, 252.9 + 0.55, 3000.0, 30.0, 321.702, 237.886 + 0.6, 3000.0, 30.0, 308.05, 222.089 + 0.0, 3000.0, 32.0, 468.161, 363.58 + 0.05, 3000.0, 32.0, 467.238, 362.551 + 0.1, 3000.0, 32.0, 464.425, 359.441 + 0.15, 3000.0, 32.0, 459.804, 354.363 + 0.2, 3000.0, 32.0, 453.454, 347.431 + 0.25, 3000.0, 32.0, 445.457, 338.758 + 0.3, 3000.0, 32.0, 435.877, 328.442 + 0.35, 3000.0, 32.0, 424.905, 316.711 + 0.4, 3000.0, 32.0, 412.691, 303.732 + 0.45, 3000.0, 32.0, 399.387, 289.665 + 0.5, 3000.0, 32.0, 385.147, 274.674 + 0.55, 3000.0, 32.0, 370.123, 258.92 + 0.6, 3000.0, 32.0, 354.467, 242.565 + 0.0, 3000.0, 34.0, 529.181, 390.953 + 0.05, 3000.0, 34.0, 528.109, 389.854 + 0.1, 3000.0, 34.0, 524.917, 386.542 + 0.15, 3000.0, 34.0, 519.692, 381.133 + 0.2, 3000.0, 34.0, 512.523, 373.745 + 0.25, 3000.0, 34.0, 503.5, 364.496 + 0.3, 3000.0, 34.0, 492.695, 353.485 + 0.35, 3000.0, 34.0, 480.293, 340.947 + 0.4, 3000.0, 34.0, 466.472, 327.089 + 0.45, 3000.0, 34.0, 451.437, 312.134 + 0.5, 3000.0, 34.0, 435.384, 296.302 + 0.55, 3000.0, 34.0, 418.512, 279.812 + 0.6, 3000.0, 34.0, 401.017, 262.882 + 0.0, 3000.0, 36.0, 590.053, 418.198 + 0.05, 3000.0, 36.0, 588.871, 416.995 + 0.1, 3000.0, 36.0, 585.312, 413.477 + 0.15, 3000.0, 36.0, 579.482, 407.754 + 0.2, 3000.0, 36.0, 571.49, 399.931 + 0.25, 3000.0, 36.0, 561.444, 390.117 + 0.3, 3000.0, 36.0, 549.444, 378.389 + 0.35, 3000.0, 36.0, 535.615, 365.063 + 0.4, 3000.0, 36.0, 520.163, 350.362 + 0.45, 3000.0, 36.0, 503.367, 334.51 + 0.5, 3000.0, 36.0, 485.487, 317.729 + 0.55, 3000.0, 36.0, 466.783, 300.242 + 0.6, 3000.0, 36.0, 447.515, 282.273 + 0.0, 3000.0, 38.0, 651.293, 445.325 + 0.05, 3000.0, 38.0, 650.003, 444.142 + 0.1, 3000.0, 38.0, 646.072, 440.459 + 0.15, 3000.0, 38.0, 639.625, 434.413 + 0.2, 3000.0, 38.0, 630.789, 426.14 + 0.25, 3000.0, 38.0, 619.69, 415.778 + 0.3, 3000.0, 38.0, 606.447, 403.44 + 0.35, 3000.0, 38.0, 591.211, 389.423 + 0.4, 3000.0, 38.0, 574.19, 373.922 + 0.45, 3000.0, 38.0, 555.637, 357.109 + 0.5, 3000.0, 38.0, 535.796, 339.162 + 0.55, 3000.0, 38.0, 514.909, 320.257 + 0.6, 3000.0, 38.0, 493.221, 300.572 + 0.0, 3000.0, 40.0, 712.3, 472.5 + 0.05, 3000.0, 40.0, 710.902, 471.139 + 0.1, 3000.0, 40.0, 706.6, 467.2 + 0.15, 3000.0, 40.0, 699.536, 460.811 + 0.2, 3000.0, 40.0, 689.855, 452.102 + 0.25, 3000.0, 40.0, 677.7, 441.2 + 0.3, 3000.0, 40.0, 663.21, 428.209 + 0.35, 3000.0, 40.0, 646.531, 413.435 + 0.4, 3000.0, 40.0, 627.9, 397.1 + 0.45, 3000.0, 40.0, 607.626, 379.416 + 0.5, 3000.0, 40.0, 586.0, 360.6 + 0.55, 3000.0, 40.0, 563.313, 340.866 + 0.6, 3000.0, 40.0, 539.857, 320.431 + 0.0, 3000.0, 42.0, 773.209, 499.609 + 0.05, 3000.0, 42.0, 771.753, 498.285 + 0.1, 3000.0, 42.0, 767.116, 494.156 + 0.15, 3000.0, 42.0, 759.46, 487.39 + 0.2, 3000.0, 42.0, 748.946, 478.157 + 0.25, 3000.0, 42.0, 735.735, 466.628 + 0.3, 3000.0, 42.0, 719.982, 452.954 + 0.35, 3000.0, 42.0, 701.892, 437.416 + 0.4, 3000.0, 42.0, 681.703, 420.253 + 0.45, 3000.0, 42.0, 659.692, 401.713 + 0.5, 3000.0, 42.0, 636.124, 382.042 + 0.55, 3000.0, 42.0, 611.265, 361.484 + 0.6, 3000.0, 42.0, 585.382, 340.285 + 0.0, 3000.0, 44.0, 834.441, 526.877 + 0.05, 3000.0, 44.0, 832.778, 525.434 + 0.1, 3000.0, 44.0, 827.774, 521.096 + 0.15, 3000.0, 44.0, 819.561, 514.016 + 0.2, 3000.0, 44.0, 808.273, 504.351 + 0.25, 3000.0, 44.0, 794.043, 492.254 + 0.3, 3000.0, 44.0, 776.973, 477.844 + 0.35, 3000.0, 44.0, 757.411, 461.528 + 0.4, 3000.0, 44.0, 735.625, 443.551 + 0.45, 3000.0, 44.0, 711.892, 424.12 + 0.5, 3000.0, 44.0, 686.487, 403.448 + 0.55, 3000.0, 44.0, 659.687, 381.753 + 0.6, 3000.0, 44.0, 631.766, 359.249 + 0.0, 3000.0, 46.0, 895.366, 553.978 + 0.05, 3000.0, 46.0, 893.603, 552.445 + 0.1, 3000.0, 46.0, 888.226, 547.898 + 0.15, 3000.0, 46.0, 879.391, 540.495 + 0.2, 3000.0, 46.0, 867.251, 530.392 + 0.25, 3000.0, 46.0, 851.963, 517.746 + 0.3, 3000.0, 46.0, 833.647, 502.681 + 0.35, 3000.0, 46.0, 812.698, 485.575 + 0.4, 3000.0, 46.0, 789.375, 466.704 + 0.45, 3000.0, 46.0, 763.917, 446.34 + 0.5, 3000.0, 46.0, 736.568, 424.758 + 0.55, 3000.0, 46.0, 707.571, 402.231 + 0.6, 3000.0, 46.0, 677.171, 379.033 + 0.0, 3000.0, 48.0, 956.504, 581.294 + 0.05, 3000.0, 48.0, 954.619, 579.692 + 0.1, 3000.0, 48.0, 948.884, 574.926 + 0.15, 3000.0, 48.0, 939.459, 567.168 + 0.2, 3000.0, 48.0, 926.506, 556.59 + 0.25, 3000.0, 48.0, 910.183, 543.363 + 0.3, 3000.0, 48.0, 890.613, 527.629 + 0.35, 3000.0, 48.0, 868.22, 509.762 + 0.4, 3000.0, 48.0, 843.297, 490.036 + 0.45, 3000.0, 48.0, 816.122, 468.715 + 0.5, 3000.0, 48.0, 786.979, 446.067 + 0.55, 3000.0, 48.0, 756.151, 422.36 + 0.6, 3000.0, 48.0, 723.92, 397.862 + 0.0, 3000.0, 50.0, 1017.5, 608.4 + 0.05, 3000.0, 50.0, 1015.51, 606.821 + 0.1, 3000.0, 50.0, 1009.4, 601.9 + 0.15, 3000.0, 50.0, 999.349, 593.828 + 0.2, 3000.0, 50.0, 985.552, 582.798 + 0.25, 3000.0, 50.0, 968.2, 569.0 + 0.3, 3000.0, 50.0, 947.464, 552.595 + 0.35, 3000.0, 50.0, 923.66, 534.005 + 0.4, 3000.0, 50.0, 897.1, 513.5 + 0.45, 3000.0, 50.0, 868.133, 491.317 + 0.5, 3000.0, 50.0, 837.1, 467.7 + 0.55, 3000.0, 50.0, 804.341, 442.894 + 0.6, 3000.0, 50.0, 770.198, 417.143 + 0.0, 5000.0, 20.0, 110.4, 200.5 + 0.05, 5000.0, 20.0, 110.238, 199.844 + 0.1, 5000.0, 20.0, 109.6, 197.9 + 0.15, 5000.0, 20.0, 108.513, 194.731 + 0.2, 5000.0, 20.0, 107.0, 190.4 + 0.25, 5000.0, 20.0, 105.075, 184.944 + 0.3, 5000.0, 20.0, 102.8, 178.5 + 0.35, 5000.0, 20.0, 100.244, 171.181 + 0.4, 5000.0, 20.0, 97.4, 163.1 + 0.45, 5000.0, 20.0, 94.2813, 154.369 + 0.5, 5000.0, 20.0, 90.9, 145.1 + 0.55, 5000.0, 20.0, 87.2687, 135.406 + 0.6, 5000.0, 20.0, 83.4, 125.4 + 0.0, 5000.0, 22.0, 176.866, 232.745 + 0.05, 5000.0, 22.0, 176.5, 232.065 + 0.1, 5000.0, 22.0, 175.419, 229.922 + 0.15, 5000.0, 22.0, 173.66, 226.401 + 0.2, 5000.0, 22.0, 171.261, 221.586 + 0.25, 5000.0, 22.0, 168.266, 215.555 + 0.3, 5000.0, 22.0, 164.691, 208.415 + 0.35, 5000.0, 22.0, 160.53, 200.246 + 0.4, 5000.0, 22.0, 155.888, 191.205 + 0.45, 5000.0, 22.0, 150.844, 181.428 + 0.5, 5000.0, 22.0, 145.474, 171.054 + 0.55, 5000.0, 22.0, 139.857, 160.219 + 0.6, 5000.0, 22.0, 134.069, 149.061 + 0.0, 5000.0, 24.0, 243.053, 263.783 + 0.05, 5000.0, 24.0, 242.57, 263.04 + 0.1, 5000.0, 24.0, 241.089, 260.688 + 0.15, 5000.0, 24.0, 238.669, 256.814 + 0.2, 5000.0, 24.0, 235.364, 251.504 + 0.25, 5000.0, 24.0, 231.246, 244.826 + 0.3, 5000.0, 24.0, 226.331, 236.922 + 0.35, 5000.0, 24.0, 220.614, 227.9 + 0.4, 5000.0, 24.0, 214.238, 217.929 + 0.45, 5000.0, 24.0, 207.31, 207.165 + 0.5, 5000.0, 24.0, 199.937, 195.764 + 0.55, 5000.0, 24.0, 192.225, 183.879 + 0.6, 5000.0, 24.0, 184.281, 171.666 + 0.0, 5000.0, 26.0, 309.147, 293.939 + 0.05, 5000.0, 26.0, 308.571, 293.108 + 0.1, 5000.0, 26.0, 306.711, 290.542 + 0.15, 5000.0, 26.0, 303.639, 286.32 + 0.2, 5000.0, 26.0, 299.428, 280.518 + 0.25, 5000.0, 26.0, 294.155, 273.174 + 0.3, 5000.0, 26.0, 287.877, 264.492 + 0.35, 5000.0, 26.0, 280.63, 254.633 + 0.4, 5000.0, 26.0, 272.554, 243.761 + 0.45, 5000.0, 26.0, 263.76, 232.038 + 0.5, 5000.0, 26.0, 254.363, 219.626 + 0.55, 5000.0, 26.0, 244.474, 206.689 + 0.6, 5000.0, 26.0, 234.208, 193.389 + 0.0, 5000.0, 28.0, 375.412, 323.539 + 0.05, 5000.0, 28.0, 374.67, 322.615 + 0.1, 5000.0, 28.0, 372.414, 319.839 + 0.15, 5000.0, 28.0, 368.707, 315.286 + 0.2, 5000.0, 28.0, 363.615, 309.025 + 0.25, 5000.0, 28.0, 357.183, 301.072 + 0.3, 5000.0, 28.0, 349.533, 291.674 + 0.35, 5000.0, 28.0, 340.764, 281.037 + 0.4, 5000.0, 28.0, 330.988, 269.294 + 0.45, 5000.0, 28.0, 320.314, 256.598 + 0.5, 5000.0, 28.0, 308.849, 243.098 + 0.55, 5000.0, 28.0, 296.702, 228.948 + 0.6, 5000.0, 28.0, 283.981, 214.298 + 0.0, 5000.0, 30.0, 441.8, 352.9 + 0.05, 5000.0, 30.0, 440.862, 351.887 + 0.1, 5000.0, 30.0, 438.2, 348.9 + 0.15, 5000.0, 30.0, 433.862, 344.012 + 0.2, 5000.0, 30.0, 427.9, 337.3 + 0.25, 5000.0, 30.0, 420.319, 328.775 + 0.3, 5000.0, 30.0, 411.3, 318.7 + 0.35, 5000.0, 30.0, 400.994, 307.306 + 0.4, 5000.0, 30.0, 389.5, 294.7 + 0.45, 5000.0, 30.0, 376.931, 281.019 + 0.5, 5000.0, 30.0, 363.4, 266.4 + 0.55, 5000.0, 30.0, 349.019, 250.981 + 0.6, 5000.0, 30.0, 333.9, 234.9 + 0.0, 5000.0, 32.0, 508.133, 382.467 + 0.05, 5000.0, 32.0, 507.091, 381.392 + 0.1, 5000.0, 32.0, 504.041, 378.166 + 0.15, 5000.0, 32.0, 499.052, 372.891 + 0.2, 5000.0, 32.0, 492.191, 365.664 + 0.25, 5000.0, 32.0, 483.489, 356.535 + 0.3, 5000.0, 32.0, 473.122, 345.754 + 0.35, 5000.0, 32.0, 461.219, 333.541 + 0.4, 5000.0, 32.0, 447.956, 320.029 + 0.45, 5000.0, 32.0, 433.499, 305.376 + 0.5, 5000.0, 32.0, 418.013, 289.735 + 0.55, 5000.0, 32.0, 401.662, 273.264 + 0.6, 5000.0, 32.0, 384.611, 256.118 + 0.0, 5000.0, 34.0, 574.315, 411.939 + 0.05, 5000.0, 34.0, 573.213, 410.784 + 0.1, 5000.0, 34.0, 569.776, 407.333 + 0.15, 5000.0, 34.0, 564.111, 401.693 + 0.2, 5000.0, 34.0, 556.323, 393.97 + 0.25, 5000.0, 34.0, 546.505, 384.218 + 0.3, 5000.0, 34.0, 534.807, 372.697 + 0.35, 5000.0, 34.0, 521.331, 359.624 + 0.4, 5000.0, 34.0, 506.316, 345.18 + 0.45, 5000.0, 34.0, 489.968, 329.553 + 0.5, 5000.0, 34.0, 472.491, 312.934 + 0.55, 5000.0, 34.0, 454.091, 295.512 + 0.6, 5000.0, 34.0, 434.973, 277.477 + 0.0, 5000.0, 36.0, 640.395, 441.217 + 0.05, 5000.0, 36.0, 639.223, 439.961 + 0.1, 5000.0, 36.0, 635.386, 436.31 + 0.15, 5000.0, 36.0, 629.032, 430.351 + 0.2, 5000.0, 36.0, 620.308, 422.174 + 0.25, 5000.0, 36.0, 609.364, 411.794 + 0.3, 5000.0, 36.0, 596.34, 399.515 + 0.35, 5000.0, 36.0, 581.344, 385.575 + 0.4, 5000.0, 36.0, 564.621, 370.19 + 0.45, 5000.0, 36.0, 546.381, 353.583 + 0.5, 5000.0, 36.0, 526.836, 335.976 + 0.55, 5000.0, 36.0, 506.196, 317.593 + 0.6, 5000.0, 36.0, 484.672, 298.655 + 0.0, 5000.0, 38.0, 706.924, 470.388 + 0.05, 5000.0, 38.0, 705.497, 469.09 + 0.1, 5000.0, 38.0, 701.235, 465.232 + 0.15, 5000.0, 38.0, 694.255, 458.923 + 0.2, 5000.0, 38.0, 684.676, 450.272 + 0.25, 5000.0, 38.0, 672.586, 439.324 + 0.3, 5000.0, 38.0, 658.194, 426.379 + 0.35, 5000.0, 38.0, 641.661, 411.688 + 0.4, 5000.0, 38.0, 623.23, 395.44 + 0.45, 5000.0, 38.0, 603.125, 377.838 + 0.5, 5000.0, 38.0, 581.57, 359.088 + 0.55, 5000.0, 38.0, 558.786, 339.394 + 0.6, 5000.0, 38.0, 534.997, 318.96 + 0.0, 5000.0, 40.0, 773.1, 499.6 + 0.05, 5000.0, 40.0, 771.55, 498.188 + 0.1, 5000.0, 40.0, 766.9, 494.1 + 0.15, 5000.0, 40.0, 759.275, 487.437 + 0.2, 5000.0, 40.0, 748.8, 478.3 + 0.25, 5000.0, 40.0, 735.556, 466.7 + 0.3, 5000.0, 40.0, 719.8, 453.0 + 0.35, 5000.0, 40.0, 701.737, 437.513 + 0.4, 5000.0, 40.0, 681.6, 420.4 + 0.45, 5000.0, 40.0, 659.612, 401.863 + 0.5, 5000.0, 40.0, 636.0, 382.1 + 0.55, 5000.0, 40.0, 610.987, 361.313 + 0.6, 5000.0, 40.0, 584.8, 339.7 + 0.0, 5000.0, 42.0, 839.268, 528.932 + 0.05, 5000.0, 42.0, 837.622, 527.449 + 0.1, 5000.0, 42.0, 832.589, 523.109 + 0.15, 5000.0, 42.0, 824.311, 516.037 + 0.2, 5000.0, 42.0, 812.93, 506.365 + 0.25, 5000.0, 42.0, 798.55, 494.143 + 0.3, 5000.0, 42.0, 781.431, 479.728 + 0.35, 5000.0, 42.0, 761.773, 463.431 + 0.4, 5000.0, 42.0, 739.872, 445.435 + 0.45, 5000.0, 42.0, 716.003, 425.953 + 0.5, 5000.0, 42.0, 690.439, 405.201 + 0.55, 5000.0, 42.0, 663.454, 383.394 + 0.6, 5000.0, 42.0, 635.321, 360.745 + 0.0, 5000.0, 44.0, 905.668, 558.231 + 0.05, 5000.0, 44.0, 903.934, 556.744 + 0.1, 5000.0, 44.0, 898.512, 552.224 + 0.15, 5000.0, 44.0, 889.572, 544.811 + 0.2, 5000.0, 44.0, 877.285, 534.643 + 0.25, 5000.0, 44.0, 861.795, 521.777 + 0.3, 5000.0, 44.0, 843.348, 506.595 + 0.35, 5000.0, 44.0, 822.114, 489.43 + 0.4, 5000.0, 44.0, 798.457, 470.487 + 0.45, 5000.0, 44.0, 772.693, 449.999 + 0.5, 5000.0, 44.0, 745.138, 428.204 + 0.55, 5000.0, 44.0, 716.108, 405.336 + 0.6, 5000.0, 44.0, 685.918, 381.632 + 0.0, 5000.0, 46.0, 971.726, 587.488 + 0.05, 5000.0, 46.0, 969.837, 585.869 + 0.1, 5000.0, 46.0, 964.032, 581.102 + 0.15, 5000.0, 46.0, 954.471, 573.325 + 0.2, 5000.0, 46.0, 941.315, 562.676 + 0.25, 5000.0, 46.0, 924.674, 549.211 + 0.3, 5000.0, 46.0, 904.859, 533.318 + 0.35, 5000.0, 46.0, 882.102, 515.331 + 0.4, 5000.0, 46.0, 856.743, 495.475 + 0.45, 5000.0, 46.0, 829.092, 473.999 + 0.5, 5000.0, 46.0, 799.462, 451.157 + 0.55, 5000.0, 46.0, 768.163, 427.199 + 0.6, 5000.0, 46.0, 735.508, 402.377 + 0.0, 5000.0, 48.0, 1038.21, 617.068 + 0.05, 5000.0, 48.0, 1036.13, 615.365 + 0.1, 5000.0, 48.0, 1029.91, 610.405 + 0.15, 5000.0, 48.0, 1019.71, 602.317 + 0.2, 5000.0, 48.0, 1005.67, 591.226 + 0.25, 5000.0, 48.0, 987.876, 577.157 + 0.3, 5000.0, 48.0, 966.687, 560.544 + 0.35, 5000.0, 48.0, 942.394, 541.764 + 0.4, 5000.0, 48.0, 915.328, 521.023 + 0.45, 5000.0, 48.0, 885.81, 498.572 + 0.5, 5000.0, 48.0, 854.161, 474.66 + 0.55, 5000.0, 48.0, 820.7, 449.539 + 0.6, 5000.0, 48.0, 785.748, 423.458 + 0.0, 5000.0, 50.0, 1104.4, 647.0 + 0.05, 5000.0, 50.0, 1102.24, 645.256 + 0.1, 5000.0, 50.0, 1095.6, 640.1 + 0.15, 5000.0, 50.0, 1084.69, 631.669 + 0.2, 5000.0, 50.0, 1069.7, 620.1 + 0.25, 5000.0, 50.0, 1050.8, 605.425 + 0.3, 5000.0, 50.0, 1028.3, 588.1 + 0.35, 5000.0, 50.0, 1002.42, 568.525 + 0.4, 5000.0, 50.0, 973.6, 546.9 + 0.45, 5000.0, 50.0, 942.2, 523.475 + 0.5, 5000.0, 50.0, 908.6, 498.5 + 0.55, 5000.0, 50.0, 873.175, 472.225 + 0.6, 5000.0, 50.0, 836.3, 444.9 + 0.0, 10000.0, 20.0, 135.6, 224.4 + 0.05, 10000.0, 20.0, 135.331, 223.669 + 0.1, 10000.0, 20.0, 134.5, 221.6 + 0.15, 10000.0, 20.0, 133.144, 218.231 + 0.2, 10000.0, 20.0, 131.3, 213.6 + 0.25, 10000.0, 20.0, 129.025, 207.694 + 0.3, 10000.0, 20.0, 126.3, 200.7 + 0.35, 10000.0, 20.0, 123.081, 192.775 + 0.4, 10000.0, 20.0, 119.5, 184.0 + 0.45, 10000.0, 20.0, 115.681, 174.462 + 0.5, 10000.0, 20.0, 111.6, 164.3 + 0.55, 10000.0, 20.0, 107.269, 153.638 + 0.6, 10000.0, 20.0, 102.7, 142.6 + 0.0, 10000.0, 22.0, 217.135, 261.128 + 0.05, 10000.0, 22.0, 216.652, 260.343 + 0.1, 10000.0, 22.0, 215.351, 258.045 + 0.15, 10000.0, 22.0, 213.241, 254.282 + 0.2, 10000.0, 22.0, 210.333, 249.101 + 0.25, 10000.0, 22.0, 206.603, 242.5 + 0.3, 10000.0, 22.0, 202.16, 234.671 + 0.35, 10000.0, 22.0, 197.089, 225.769 + 0.4, 10000.0, 22.0, 191.438, 215.91 + 0.45, 10000.0, 22.0, 185.243, 205.198 + 0.5, 10000.0, 22.0, 178.621, 193.825 + 0.55, 10000.0, 22.0, 171.667, 181.958 + 0.6, 10000.0, 22.0, 164.476, 169.766 + 0.0, 10000.0, 24.0, 298.408, 296.735 + 0.05, 10000.0, 24.0, 297.796, 295.867 + 0.1, 10000.0, 24.0, 296.005, 293.319 + 0.15, 10000.0, 24.0, 293.076, 289.14 + 0.2, 10000.0, 24.0, 289.047, 283.383 + 0.25, 10000.0, 24.0, 283.931, 276.036 + 0.3, 10000.0, 24.0, 277.84, 267.336 + 0.35, 10000.0, 24.0, 270.858, 257.472 + 0.4, 10000.0, 24.0, 263.079, 246.569 + 0.45, 10000.0, 24.0, 254.581, 234.753 + 0.5, 10000.0, 24.0, 245.491, 222.215 + 0.55, 10000.0, 24.0, 235.922, 209.129 + 0.6, 10000.0, 24.0, 225.988, 195.67 + 0.0, 10000.0, 26.0, 379.592, 331.727 + 0.05, 10000.0, 26.0, 378.879, 330.765 + 0.1, 10000.0, 26.0, 376.595, 327.95 + 0.15, 10000.0, 26.0, 372.824, 323.341 + 0.2, 10000.0, 26.0, 367.653, 316.995 + 0.25, 10000.0, 26.0, 361.175, 308.896 + 0.3, 10000.0, 26.0, 353.46, 299.325 + 0.35, 10000.0, 26.0, 344.548, 288.514 + 0.4, 10000.0, 26.0, 334.621, 276.584 + 0.45, 10000.0, 26.0, 323.844, 263.672 + 0.5, 10000.0, 26.0, 312.309, 249.962 + 0.55, 10000.0, 26.0, 300.128, 235.628 + 0.6, 10000.0, 26.0, 287.412, 220.84 + 0.0, 10000.0, 28.0, 460.933, 366.742 + 0.05, 10000.0, 28.0, 460.067, 365.694 + 0.1, 10000.0, 28.0, 457.3, 362.603 + 0.15, 10000.0, 28.0, 452.73, 357.552 + 0.2, 10000.0, 28.0, 446.455, 350.624 + 0.25, 10000.0, 28.0, 438.568, 341.843 + 0.3, 10000.0, 28.0, 429.181, 331.47 + 0.35, 10000.0, 28.0, 418.379, 319.731 + 0.4, 10000.0, 28.0, 406.345, 306.752 + 0.45, 10000.0, 28.0, 393.24, 292.655 + 0.5, 10000.0, 28.0, 379.212, 277.679 + 0.55, 10000.0, 28.0, 364.413, 262.035 + 0.6, 10000.0, 28.0, 348.992, 245.934 + 0.0, 10000.0, 30.0, 542.4, 401.9 + 0.05, 10000.0, 30.0, 541.344, 400.769 + 0.1, 10000.0, 30.0, 538.1, 397.4 + 0.15, 10000.0, 30.0, 532.756, 391.906 + 0.2, 10000.0, 30.0, 525.4, 384.4 + 0.25, 10000.0, 30.0, 516.081, 374.956 + 0.3, 10000.0, 30.0, 505.0, 363.8 + 0.35, 10000.0, 30.0, 492.325, 351.137 + 0.4, 10000.0, 30.0, 478.2, 337.1 + 0.45, 10000.0, 30.0, 462.744, 321.781 + 0.5, 10000.0, 30.0, 446.2, 305.5 + 0.55, 10000.0, 30.0, 428.781, 288.519 + 0.6, 10000.0, 30.0, 410.7, 271.1 + 0.0, 10000.0, 32.0, 623.867, 437.162 + 0.05, 10000.0, 32.0, 622.65, 435.93 + 0.1, 10000.0, 32.0, 618.906, 432.295 + 0.15, 10000.0, 32.0, 612.748, 426.369 + 0.2, 10000.0, 32.0, 604.283, 418.267 + 0.25, 10000.0, 32.0, 593.595, 408.042 + 0.3, 10000.0, 32.0, 580.874, 395.988 + 0.35, 10000.0, 32.0, 566.268, 382.381 + 0.4, 10000.0, 32.0, 549.994, 367.325 + 0.45, 10000.0, 32.0, 532.241, 350.913 + 0.5, 10000.0, 32.0, 513.243, 333.445 + 0.55, 10000.0, 32.0, 493.222, 315.167 + 0.6, 10000.0, 32.0, 472.401, 296.328 + 0.0, 10000.0, 34.0, 705.176, 472.338 + 0.05, 10000.0, 34.0, 703.788, 471.027 + 0.1, 10000.0, 34.0, 699.551, 467.139 + 0.15, 10000.0, 34.0, 692.59, 460.795 + 0.2, 10000.0, 34.0, 683.03, 452.114 + 0.25, 10000.0, 34.0, 670.976, 441.151 + 0.3, 10000.0, 34.0, 656.617, 428.226 + 0.35, 10000.0, 34.0, 640.084, 413.639 + 0.4, 10000.0, 34.0, 621.665, 397.507 + 0.45, 10000.0, 34.0, 601.623, 379.947 + 0.5, 10000.0, 34.0, 580.177, 361.261 + 0.55, 10000.0, 34.0, 557.555, 341.706 + 0.6, 10000.0, 34.0, 533.988, 321.538 + 0.0, 10000.0, 36.0, 786.345, 507.408 + 0.05, 10000.0, 36.0, 784.774, 506.041 + 0.1, 10000.0, 36.0, 780.058, 501.914 + 0.15, 10000.0, 36.0, 772.321, 495.166 + 0.2, 10000.0, 36.0, 761.687, 485.934 + 0.25, 10000.0, 36.0, 748.241, 474.308 + 0.3, 10000.0, 36.0, 732.222, 460.568 + 0.35, 10000.0, 36.0, 713.791, 444.964 + 0.4, 10000.0, 36.0, 693.259, 427.683 + 0.45, 10000.0, 36.0, 670.906, 408.877 + 0.5, 10000.0, 36.0, 646.984, 388.905 + 0.55, 10000.0, 36.0, 621.751, 368.074 + 0.6, 10000.0, 36.0, 595.465, 346.689 + 0.0, 10000.0, 38.0, 867.938, 542.761 + 0.05, 10000.0, 38.0, 866.225, 541.286 + 0.1, 10000.0, 38.0, 861.036, 536.921 + 0.15, 10000.0, 38.0, 852.504, 529.783 + 0.2, 10000.0, 38.0, 840.76, 519.986 + 0.25, 10000.0, 38.0, 825.883, 507.558 + 0.3, 10000.0, 38.0, 808.172, 492.876 + 0.35, 10000.0, 38.0, 787.865, 476.27 + 0.4, 10000.0, 38.0, 765.232, 457.912 + 0.45, 10000.0, 38.0, 740.502, 437.982 + 0.5, 10000.0, 38.0, 714.036, 416.792 + 0.55, 10000.0, 38.0, 686.163, 394.624 + 0.6, 10000.0, 38.0, 657.209, 371.757 + 0.0, 10000.0, 40.0, 949.2, 578.0 + 0.05, 10000.0, 40.0, 947.394, 576.444 + 0.1, 10000.0, 40.0, 941.7, 571.8 + 0.15, 10000.0, 40.0, 932.306, 564.206 + 0.2, 10000.0, 40.0, 919.4, 553.8 + 0.25, 10000.0, 40.0, 903.144, 540.637 + 0.3, 10000.0, 40.0, 883.8, 525.1 + 0.35, 10000.0, 40.0, 861.569, 507.525 + 0.4, 10000.0, 40.0, 836.8, 488.1 + 0.45, 10000.0, 40.0, 809.794, 467.012 + 0.5, 10000.0, 40.0, 780.9, 444.6 + 0.55, 10000.0, 40.0, 750.456, 421.162 + 0.6, 10000.0, 40.0, 718.8, 397.0 + 0.0, 10000.0, 42.0, 1030.47, 613.671 + 0.05, 10000.0, 42.0, 1028.45, 611.964 + 0.1, 10000.0, 42.0, 1022.27, 607.025 + 0.15, 10000.0, 42.0, 1012.11, 598.985 + 0.2, 10000.0, 42.0, 998.155, 587.979 + 0.25, 10000.0, 42.0, 980.533, 574.034 + 0.3, 10000.0, 42.0, 959.543, 557.598 + 0.35, 10000.0, 42.0, 935.393, 539.078 + 0.4, 10000.0, 42.0, 908.482, 518.631 + 0.45, 10000.0, 42.0, 879.162, 496.443 + 0.5, 10000.0, 42.0, 847.787, 472.845 + 0.55, 10000.0, 42.0, 814.712, 448.135 + 0.6, 10000.0, 42.0, 780.29, 422.608 + 0.0, 10000.0, 44.0, 1112.03, 650.078 + 0.05, 10000.0, 44.0, 1109.84, 648.304 + 0.1, 10000.0, 44.0, 1103.19, 643.17 + 0.15, 10000.0, 44.0, 1092.25, 634.785 + 0.2, 10000.0, 44.0, 1077.19, 623.261 + 0.25, 10000.0, 44.0, 1058.13, 608.58 + 0.3, 10000.0, 44.0, 1035.43, 591.232 + 0.35, 10000.0, 44.0, 1009.41, 571.626 + 0.4, 10000.0, 44.0, 980.42, 549.992 + 0.45, 10000.0, 44.0, 948.783, 526.59 + 0.5, 10000.0, 44.0, 914.914, 501.732 + 0.55, 10000.0, 44.0, 879.203, 475.719 + 0.6, 10000.0, 44.0, 842.041, 448.849 + 0.0, 10000.0, 46.0, 1193.17, 686.642 + 0.05, 10000.0, 46.0, 1190.82, 684.729 + 0.1, 10000.0, 46.0, 1183.67, 679.301 + 0.15, 10000.0, 46.0, 1171.91, 670.477 + 0.2, 10000.0, 46.0, 1155.76, 658.375 + 0.25, 10000.0, 46.0, 1135.34, 642.988 + 0.3, 10000.0, 46.0, 1111.02, 624.81 + 0.35, 10000.0, 46.0, 1083.07, 604.272 + 0.4, 10000.0, 46.0, 1051.92, 581.548 + 0.45, 10000.0, 46.0, 1017.97, 556.787 + 0.5, 10000.0, 46.0, 981.631, 530.497 + 0.55, 10000.0, 46.0, 943.334, 503.095 + 0.6, 10000.0, 46.0, 903.498, 475.0 + 0.0, 10000.0, 48.0, 1274.73, 723.744 + 0.05, 10000.0, 48.0, 1272.27, 721.739 + 0.1, 10000.0, 48.0, 1264.63, 716.001 + 0.15, 10000.0, 48.0, 1252.04, 706.674 + 0.2, 10000.0, 48.0, 1234.74, 693.903 + 0.25, 10000.0, 48.0, 1212.93, 677.702 + 0.3, 10000.0, 48.0, 1186.97, 658.607 + 0.35, 10000.0, 48.0, 1157.1, 637.128 + 0.4, 10000.0, 48.0, 1123.81, 613.357 + 0.45, 10000.0, 48.0, 1087.53, 587.369 + 0.5, 10000.0, 48.0, 1048.71, 559.738 + 0.55, 10000.0, 48.0, 1007.81, 530.913 + 0.6, 10000.0, 48.0, 965.288, 501.344 + 0.0, 10000.0, 50.0, 1356.0, 761.0 + 0.05, 10000.0, 50.0, 1353.32, 758.938 + 0.1, 10000.0, 50.0, 1345.2, 752.9 + 0.15, 10000.0, 50.0, 1331.86, 743.062 + 0.2, 10000.0, 50.0, 1313.5, 729.6 + 0.25, 10000.0, 50.0, 1290.26, 712.563 + 0.3, 10000.0, 50.0, 1262.6, 692.5 + 0.35, 10000.0, 50.0, 1230.86, 669.925 + 0.4, 10000.0, 50.0, 1195.5, 645.0 + 0.45, 10000.0, 50.0, 1156.91, 617.919 + 0.5, 10000.0, 50.0, 1115.6, 589.1 + 0.55, 10000.0, 50.0, 1072.07, 558.906 + 0.6, 10000.0, 50.0, 1026.8, 527.7 + 0.0, 15000.0, 20.0, 180.0, 262.4 + 0.05, 15000.0, 20.0, 166.675, 257.275 + 0.1, 15000.0, 20.0, 158.0, 252.4 + 0.15, 15000.0, 20.0, 153.0, 247.525 + 0.2, 15000.0, 20.0, 150.7, 242.4 + 0.25, 15000.0, 20.0, 150.125, 236.775 + 0.3, 15000.0, 20.0, 150.3, 230.4 + 0.35, 15000.0, 20.0, 150.25, 223.025 + 0.4, 15000.0, 20.0, 149.0, 214.4 + 0.45, 15000.0, 20.0, 144.612, 203.925 + 0.5, 15000.0, 20.0, 139.0, 192.4 + 0.55, 15000.0, 20.0, 133.112, 180.275 + 0.6, 15000.0, 20.0, 127.9, 168.0 + 0.0, 15000.0, 22.0, 284.656, 305.376 + 0.05, 15000.0, 22.0, 264.767, 297.085 + 0.1, 15000.0, 22.0, 251.895, 290.141 + 0.15, 15000.0, 22.0, 244.549, 284.06 + 0.2, 15000.0, 22.0, 241.237, 278.356 + 0.25, 15000.0, 22.0, 240.469, 272.542 + 0.3, 15000.0, 22.0, 240.752, 266.133 + 0.35, 15000.0, 22.0, 240.596, 258.643 + 0.4, 15000.0, 22.0, 238.51, 249.586 + 0.45, 15000.0, 22.0, 231.511, 237.85 + 0.5, 15000.0, 22.0, 222.58, 224.829 + 0.55, 15000.0, 22.0, 213.207, 211.292 + 0.6, 15000.0, 22.0, 204.883, 198.007 + 0.0, 15000.0, 24.0, 391.447, 348.477 + 0.05, 15000.0, 24.0, 364.009, 337.036 + 0.1, 15000.0, 24.0, 346.247, 328.018 + 0.15, 15000.0, 24.0, 336.107, 320.709 + 0.2, 15000.0, 24.0, 331.533, 314.396 + 0.25, 15000.0, 24.0, 330.469, 308.364 + 0.3, 15000.0, 24.0, 330.862, 301.9 + 0.35, 15000.0, 24.0, 330.656, 294.291 + 0.4, 15000.0, 24.0, 327.795, 284.823 + 0.45, 15000.0, 24.0, 318.171, 271.928 + 0.5, 15000.0, 24.0, 305.89, 257.454 + 0.55, 15000.0, 24.0, 293.005, 242.397 + 0.6, 15000.0, 24.0, 281.568, 227.751 + 0.0, 15000.0, 26.0, 499.311, 392.1 + 0.05, 15000.0, 26.0, 463.855, 377.423 + 0.1, 15000.0, 26.0, 440.872, 366.264 + 0.15, 15000.0, 26.0, 427.72, 357.681 + 0.2, 15000.0, 26.0, 421.759, 350.727 + 0.25, 15000.0, 26.0, 420.348, 344.459 + 0.3, 15000.0, 26.0, 420.846, 337.931 + 0.35, 15000.0, 26.0, 420.612, 330.198 + 0.4, 15000.0, 26.0, 417.005, 320.316 + 0.45, 15000.0, 26.0, 404.753, 306.272 + 0.5, 15000.0, 26.0, 389.11, 290.325 + 0.55, 15000.0, 26.0, 372.698, 273.668 + 0.6, 15000.0, 26.0, 358.14, 257.492 + 0.0, 15000.0, 28.0, 606.826, 437.065 + 0.05, 15000.0, 28.0, 563.588, 418.812 + 0.1, 15000.0, 28.0, 535.541, 405.297 + 0.15, 15000.0, 28.0, 519.471, 395.318 + 0.2, 15000.0, 28.0, 512.166, 387.674 + 0.25, 15000.0, 28.0, 510.414, 381.162 + 0.3, 15000.0, 28.0, 511.001, 374.58 + 0.35, 15000.0, 28.0, 510.715, 366.726 + 0.4, 15000.0, 28.0, 506.343, 356.398 + 0.45, 15000.0, 28.0, 491.478, 341.064 + 0.5, 15000.0, 28.0, 472.49, 323.512 + 0.55, 15000.0, 28.0, 452.556, 305.2 + 0.6, 15000.0, 28.0, 434.853, 287.587 + 0.0, 15000.0, 30.0, 714.0, 482.5 + 0.05, 15000.0, 30.0, 663.175, 460.669 + 0.1, 15000.0, 30.0, 630.2, 444.8 + 0.15, 15000.0, 30.0, 611.3, 433.431 + 0.2, 15000.0, 30.0, 602.7, 425.1 + 0.25, 15000.0, 30.0, 600.625, 418.344 + 0.3, 15000.0, 30.0, 601.3, 411.7 + 0.35, 15000.0, 30.0, 600.95, 403.706 + 0.4, 15000.0, 30.0, 595.8, 392.9 + 0.45, 15000.0, 30.0, 578.325, 376.213 + 0.5, 15000.0, 30.0, 556.0, 357.0 + 0.55, 15000.0, 30.0, 532.55, 337.013 + 0.6, 15000.0, 30.0, 511.7, 318.0 + 0.0, 15000.0, 32.0, 821.673, 526.019 + 0.05, 15000.0, 32.0, 762.994, 501.528 + 0.1, 15000.0, 32.0, 724.923, 483.908 + 0.15, 15000.0, 32.0, 703.103, 471.497 + 0.2, 15000.0, 32.0, 693.178, 462.631 + 0.25, 15000.0, 32.0, 690.794, 455.647 + 0.3, 15000.0, 32.0, 691.593, 448.882 + 0.35, 15000.0, 32.0, 691.22, 440.674 + 0.4, 15000.0, 32.0, 685.319, 429.36 + 0.45, 15000.0, 32.0, 665.204, 411.48 + 0.5, 15000.0, 32.0, 639.51, 390.76 + 0.55, 15000.0, 32.0, 612.541, 369.128 + 0.6, 15000.0, 32.0, 588.602, 348.513 + 0.0, 15000.0, 34.0, 928.245, 570.779 + 0.05, 15000.0, 34.0, 862.117, 543.211 + 0.1, 15000.0, 34.0, 819.228, 523.541 + 0.15, 15000.0, 34.0, 794.662, 509.886 + 0.2, 15000.0, 34.0, 783.503, 500.362 + 0.25, 15000.0, 34.0, 780.837, 493.088 + 0.3, 15000.0, 34.0, 781.748, 486.18 + 0.35, 15000.0, 34.0, 781.321, 477.755 + 0.4, 15000.0, 34.0, 774.641, 465.93 + 0.45, 15000.0, 34.0, 751.9, 446.811 + 0.5, 15000.0, 34.0, 722.858, 424.548 + 0.55, 15000.0, 34.0, 692.379, 401.279 + 0.6, 15000.0, 34.0, 665.332, 379.14 + 0.0, 15000.0, 36.0, 1033.73, 617.979 + 0.05, 15000.0, 36.0, 960.583, 586.365 + 0.1, 15000.0, 36.0, 913.164, 563.991 + 0.15, 15000.0, 36.0, 886.025, 548.697 + 0.2, 15000.0, 36.0, 873.715, 538.323 + 0.25, 15000.0, 36.0, 870.785, 530.71 + 0.3, 15000.0, 36.0, 871.783, 523.696 + 0.35, 15000.0, 36.0, 871.261, 515.123 + 0.4, 15000.0, 36.0, 863.766, 502.831 + 0.45, 15000.0, 36.0, 838.424, 482.362 + 0.5, 15000.0, 36.0, 806.062, 458.447 + 0.55, 15000.0, 36.0, 772.082, 433.517 + 0.6, 15000.0, 36.0, 741.887, 410.004 + 0.0, 15000.0, 38.0, 1142.05, 666.067 + 0.05, 15000.0, 38.0, 1060.85, 629.925 + 0.1, 15000.0, 38.0, 1008.2, 604.615 + 0.15, 15000.0, 38.0, 978.039, 587.647 + 0.2, 15000.0, 38.0, 964.344, 576.535 + 0.25, 15000.0, 38.0, 961.072, 568.788 + 0.3, 15000.0, 38.0, 962.184, 561.919 + 0.35, 15000.0, 38.0, 961.642, 553.439 + 0.4, 15000.0, 38.0, 953.407, 540.86 + 0.45, 15000.0, 38.0, 925.43, 519.072 + 0.5, 15000.0, 38.0, 889.7, 493.451 + 0.55, 15000.0, 38.0, 852.196, 466.749 + 0.6, 15000.0, 38.0, 818.897, 441.722 + 0.0, 15000.0, 40.0, 1249.5, 710.4 + 0.05, 15000.0, 40.0, 1160.52, 671.775 + 0.1, 15000.0, 40.0, 1102.8, 644.9 + 0.15, 15000.0, 40.0, 1069.73, 627.075 + 0.2, 15000.0, 40.0, 1054.7, 615.6 + 0.25, 15000.0, 40.0, 1051.09, 607.775 + 0.3, 15000.0, 40.0, 1052.3, 600.9 + 0.35, 15000.0, 40.0, 1051.71, 592.275 + 0.4, 15000.0, 40.0, 1042.7, 579.2 + 0.45, 15000.0, 40.0, 1012.09, 556.15 + 0.5, 15000.0, 40.0, 973.0, 528.9 + 0.55, 15000.0, 40.0, 931.956, 500.4 + 0.6, 15000.0, 40.0, 895.5, 473.6 + 0.0, 15000.0, 42.0, 1356.11, 760.079 + 0.05, 15000.0, 42.0, 1259.67, 717.09 + 0.1, 15000.0, 42.0, 1197.11, 687.295 + 0.15, 15000.0, 42.0, 1161.26, 667.698 + 0.2, 15000.0, 42.0, 1144.96, 655.304 + 0.25, 15000.0, 42.0, 1141.04, 647.116 + 0.3, 15000.0, 42.0, 1142.34, 640.137 + 0.35, 15000.0, 42.0, 1141.68, 631.371 + 0.4, 15000.0, 42.0, 1131.9, 617.822 + 0.45, 15000.0, 42.0, 1098.71, 593.364 + 0.5, 15000.0, 42.0, 1056.31, 564.39 + 0.55, 15000.0, 42.0, 1011.79, 534.163 + 0.6, 15000.0, 42.0, 972.22, 505.947 + 0.0, 15000.0, 44.0, 1462.37, 808.001 + 0.05, 15000.0, 44.0, 1358.69, 761.495 + 0.1, 15000.0, 44.0, 1291.47, 729.4 + 0.15, 15000.0, 44.0, 1252.99, 708.456 + 0.2, 15000.0, 44.0, 1235.53, 695.401 + 0.25, 15000.0, 44.0, 1231.38, 686.976 + 0.3, 15000.0, 44.0, 1232.8, 679.92 + 0.35, 15000.0, 44.0, 1232.09, 670.972 + 0.4, 15000.0, 44.0, 1221.52, 656.873 + 0.45, 15000.0, 44.0, 1185.68, 630.95 + 0.5, 15000.0, 44.0, 1139.91, 600.178 + 0.55, 15000.0, 44.0, 1091.85, 568.117 + 0.6, 15000.0, 44.0, 1049.16, 538.331 + 0.0, 15000.0, 46.0, 1570.28, 855.818 + 0.05, 15000.0, 46.0, 1458.55, 805.807 + 0.1, 15000.0, 46.0, 1386.08, 771.417 + 0.15, 15000.0, 46.0, 1344.58, 749.127 + 0.2, 15000.0, 46.0, 1325.72, 735.415 + 0.25, 15000.0, 46.0, 1321.21, 726.763 + 0.3, 15000.0, 46.0, 1322.74, 719.648 + 0.35, 15000.0, 46.0, 1322.0, 710.55 + 0.4, 15000.0, 46.0, 1310.68, 695.95 + 0.45, 15000.0, 46.0, 1272.22, 668.663 + 0.5, 15000.0, 46.0, 1223.09, 636.155 + 0.55, 15000.0, 46.0, 1171.51, 602.229 + 0.6, 15000.0, 46.0, 1125.69, 570.686 + 0.0, 15000.0, 48.0, 1678.08, 905.569 + 0.05, 15000.0, 48.0, 1558.51, 851.551 + 0.1, 15000.0, 48.0, 1480.95, 814.49 + 0.15, 15000.0, 48.0, 1436.53, 790.587 + 0.2, 15000.0, 48.0, 1416.34, 776.042 + 0.25, 15000.0, 48.0, 1411.51, 767.054 + 0.3, 15000.0, 48.0, 1413.15, 759.825 + 0.35, 15000.0, 48.0, 1412.38, 750.552 + 0.4, 15000.0, 48.0, 1400.3, 735.438 + 0.45, 15000.0, 48.0, 1359.19, 706.739 + 0.5, 15000.0, 48.0, 1306.69, 672.48 + 0.55, 15000.0, 48.0, 1251.59, 636.743 + 0.6, 15000.0, 48.0, 1202.69, 603.609 + 0.0, 15000.0, 50.0, 1782.5, 958.1 + 0.05, 15000.0, 50.0, 1656.36, 898.981 + 0.1, 15000.0, 50.0, 1574.6, 858.5 + 0.15, 15000.0, 50.0, 1527.81, 832.519 + 0.2, 15000.0, 50.0, 1506.6, 816.9 + 0.25, 15000.0, 50.0, 1501.56, 807.506 + 0.3, 15000.0, 50.0, 1503.3, 800.2 + 0.35, 15000.0, 50.0, 1502.41, 790.844 + 0.4, 15000.0, 50.0, 1489.5, 775.3 + 0.45, 15000.0, 50.0, 1445.81, 745.156 + 0.5, 15000.0, 50.0, 1390.0, 709.1 + 0.55, 15000.0, 50.0, 1331.39, 671.544 + 0.6, 15000.0, 50.0, 1279.3, 636.9 + 0.0, 17500.0, 20.0, 128.9, 262.4 + 0.05, 17500.0, 20.0, 138.125, 264.481 + 0.1, 17500.0, 20.0, 145.2, 264.5 + 0.15, 17500.0, 20.0, 150.375, 262.619 + 0.2, 17500.0, 20.0, 153.9, 259.0 + 0.25, 17500.0, 20.0, 156.025, 253.806 + 0.3, 17500.0, 20.0, 157.0, 247.2 + 0.35, 17500.0, 20.0, 157.075, 239.344 + 0.4, 17500.0, 20.0, 156.5, 230.4 + 0.45, 17500.0, 20.0, 156.144, 220.706 + 0.5, 17500.0, 20.0, 154.4, 209.9 + 0.55, 17500.0, 20.0, 150.281, 197.794 + 0.6, 17500.0, 20.0, 142.8, 184.2 + 0.0, 17500.0, 22.0, 204.798, 288.244 + 0.05, 17500.0, 22.0, 220.159, 292.893 + 0.1, 17500.0, 22.0, 231.925, 294.846 + 0.15, 17500.0, 22.0, 240.519, 294.348 + 0.2, 17500.0, 22.0, 246.362, 291.645 + 0.25, 17500.0, 22.0, 249.877, 286.984 + 0.3, 17500.0, 22.0, 251.486, 280.61 + 0.35, 17500.0, 22.0, 251.613, 272.769 + 0.4, 17500.0, 22.0, 250.68, 263.708 + 0.45, 17500.0, 22.0, 250.112, 254.009 + 0.5, 17500.0, 22.0, 247.323, 242.907 + 0.55, 17500.0, 22.0, 240.729, 229.971 + 0.6, 17500.0, 22.0, 228.748, 214.773 + 0.0, 17500.0, 24.0, 281.749, 315.478 + 0.05, 17500.0, 24.0, 302.738, 322.783 + 0.1, 17500.0, 24.0, 318.823, 326.748 + 0.15, 17500.0, 24.0, 330.577, 327.698 + 0.2, 17500.0, 24.0, 338.575, 325.961 + 0.25, 17500.0, 24.0, 343.392, 321.864 + 0.3, 17500.0, 24.0, 345.603, 315.732 + 0.35, 17500.0, 24.0, 345.783, 307.892 + 0.4, 17500.0, 24.0, 344.506, 298.671 + 0.45, 17500.0, 24.0, 343.721, 288.902 + 0.5, 17500.0, 24.0, 339.882, 277.391 + 0.55, 17500.0, 24.0, 330.817, 263.45 + 0.6, 17500.0, 24.0, 314.354, 246.394 + 0.0, 17500.0, 26.0, 358.991, 344.101 + 0.05, 17500.0, 26.0, 385.477, 354.034 + 0.1, 17500.0, 26.0, 405.777, 359.997 + 0.15, 17500.0, 26.0, 420.616, 362.39 + 0.2, 17500.0, 26.0, 430.717, 361.615 + 0.25, 17500.0, 26.0, 436.803, 358.074 + 0.3, 17500.0, 26.0, 439.597, 352.169 + 0.35, 17500.0, 26.0, 439.822, 344.3 + 0.4, 17500.0, 26.0, 438.202, 334.87 + 0.45, 17500.0, 26.0, 437.203, 324.952 + 0.5, 17500.0, 26.0, 432.318, 312.931 + 0.55, 17500.0, 26.0, 420.787, 297.864 + 0.6, 17500.0, 26.0, 399.846, 278.808 + 0.0, 17500.0, 28.0, 435.374, 374.234 + 0.05, 17500.0, 28.0, 467.792, 386.612 + 0.1, 17500.0, 28.0, 492.613, 394.434 + 0.15, 17500.0, 28.0, 510.733, 398.168 + 0.2, 17500.0, 28.0, 523.044, 398.28 + 0.25, 17500.0, 28.0, 530.44, 395.236 + 0.3, 17500.0, 28.0, 533.815, 389.504 + 0.35, 17500.0, 28.0, 534.062, 381.549 + 0.4, 17500.0, 28.0, 532.076, 371.838 + 0.45, 17500.0, 28.0, 530.882, 361.653 + 0.5, 17500.0, 28.0, 524.977, 349.014 + 0.55, 17500.0, 28.0, 510.989, 332.757 + 0.6, 17500.0, 28.0, 485.546, 311.716 + 0.0, 17500.0, 30.0, 511.3, 405.5 + 0.05, 17500.0, 30.0, 549.888, 420.15 + 0.1, 17500.0, 30.0, 579.4, 429.7 + 0.15, 17500.0, 30.0, 600.913, 434.675 + 0.2, 17500.0, 30.0, 615.5, 435.6 + 0.25, 17500.0, 30.0, 624.237, 433.0 + 0.3, 17500.0, 30.0, 628.2, 427.4 + 0.35, 17500.0, 30.0, 628.462, 419.325 + 0.4, 17500.0, 30.0, 626.1, 409.3 + 0.45, 17500.0, 30.0, 624.719, 398.8 + 0.5, 17500.0, 30.0, 617.8, 385.5 + 0.55, 17500.0, 30.0, 601.356, 368.025 + 0.6, 17500.0, 30.0, 571.4, 345.0 + 0.0, 17500.0, 32.0, 588.056, 437.185 + 0.05, 17500.0, 32.0, 632.43, 454.037 + 0.1, 17500.0, 32.0, 666.371, 465.249 + 0.15, 17500.0, 32.0, 691.117, 471.408 + 0.2, 17500.0, 32.0, 707.901, 473.101 + 0.25, 17500.0, 32.0, 717.958, 470.914 + 0.3, 17500.0, 32.0, 722.524, 465.435 + 0.35, 17500.0, 32.0, 722.832, 457.249 + 0.4, 17500.0, 32.0, 720.118, 446.943 + 0.45, 17500.0, 32.0, 718.525, 436.213 + 0.5, 17500.0, 32.0, 710.561, 422.32 + 0.55, 17500.0, 32.0, 691.645, 403.632 + 0.6, 17500.0, 32.0, 657.192, 378.52 + 0.0, 17500.0, 34.0, 664.932, 470.268 + 0.05, 17500.0, 34.0, 714.972, 488.859 + 0.1, 17500.0, 34.0, 753.262, 501.402 + 0.15, 17500.0, 34.0, 781.19, 508.526 + 0.2, 17500.0, 34.0, 800.145, 510.863 + 0.25, 17500.0, 34.0, 811.514, 509.043 + 0.3, 17500.0, 34.0, 816.686, 503.698 + 0.35, 17500.0, 34.0, 817.049, 495.457 + 0.4, 17500.0, 34.0, 813.991, 484.951 + 0.45, 17500.0, 34.0, 812.18, 474.078 + 0.5, 17500.0, 34.0, 803.165, 459.669 + 0.55, 17500.0, 34.0, 781.775, 439.826 + 0.6, 17500.0, 34.0, 742.84, 412.645 + 0.0, 17500.0, 36.0, 741.594, 503.643 + 0.05, 17500.0, 36.0, 797.345, 523.937 + 0.1, 17500.0, 36.0, 840.012, 537.803 + 0.15, 17500.0, 36.0, 871.14, 545.911 + 0.2, 17500.0, 36.0, 892.272, 548.932 + 0.25, 17500.0, 36.0, 904.954, 547.535 + 0.3, 17500.0, 36.0, 910.729, 542.39 + 0.35, 17500.0, 36.0, 911.142, 534.167 + 0.4, 17500.0, 36.0, 907.737, 523.537 + 0.45, 17500.0, 36.0, 905.712, 512.595 + 0.5, 17500.0, 36.0, 895.652, 497.732 + 0.55, 17500.0, 36.0, 871.796, 476.764 + 0.6, 17500.0, 36.0, 828.383, 447.508 + 0.0, 17500.0, 38.0, 817.726, 529.934 + 0.05, 17500.0, 38.0, 879.598, 554.854 + 0.1, 17500.0, 38.0, 926.924, 572.219 + 0.15, 17500.0, 38.0, 961.426, 582.842 + 0.2, 17500.0, 38.0, 984.826, 587.539 + 0.25, 17500.0, 38.0, 998.848, 587.125 + 0.3, 17500.0, 38.0, 1005.21, 582.414 + 0.35, 17500.0, 38.0, 1005.65, 574.221 + 0.4, 17500.0, 38.0, 1001.87, 563.36 + 0.45, 17500.0, 38.0, 999.652, 552.318 + 0.5, 17500.0, 38.0, 988.572, 536.899 + 0.55, 17500.0, 38.0, 962.254, 514.579 + 0.6, 17500.0, 38.0, 914.324, 482.836 + 0.0, 17500.0, 40.0, 896.1, 563.5 + 0.05, 17500.0, 40.0, 963.05, 590.681 + 0.1, 17500.0, 40.0, 1014.3, 609.8 + 0.15, 17500.0, 40.0, 1051.7, 621.719 + 0.2, 17500.0, 40.0, 1077.1, 627.3 + 0.25, 17500.0, 40.0, 1092.35, 627.406 + 0.3, 17500.0, 40.0, 1099.3, 622.9 + 0.35, 17500.0, 40.0, 1099.8, 614.644 + 0.4, 17500.0, 40.0, 1095.7, 603.5 + 0.45, 17500.0, 40.0, 1093.25, 592.131 + 0.5, 17500.0, 40.0, 1081.1, 576.0 + 0.55, 17500.0, 40.0, 1052.3, 552.369 + 0.6, 17500.0, 40.0, 999.9, 518.5 + 0.0, 17500.0, 42.0, 973.34, 596.68 + 0.05, 17500.0, 42.0, 1045.77, 626.483 + 0.1, 17500.0, 42.0, 1101.24, 647.571 + 0.15, 17500.0, 42.0, 1141.75, 660.883 + 0.2, 17500.0, 42.0, 1169.28, 667.357 + 0.25, 17500.0, 42.0, 1185.83, 667.935 + 0.3, 17500.0, 42.0, 1193.39, 663.554 + 0.35, 17500.0, 42.0, 1193.97, 655.154 + 0.4, 17500.0, 42.0, 1189.54, 643.674 + 0.45, 17500.0, 42.0, 1186.87, 632.019 + 0.5, 17500.0, 42.0, 1173.66, 615.233 + 0.55, 17500.0, 42.0, 1142.37, 590.327 + 0.6, 17500.0, 42.0, 1085.48, 554.31 + 0.0, 17500.0, 44.0, 1049.07, 629.682 + 0.05, 17500.0, 44.0, 1127.8, 662.369 + 0.1, 17500.0, 44.0, 1188.04, 685.613 + 0.15, 17500.0, 44.0, 1231.99, 700.441 + 0.2, 17500.0, 44.0, 1261.82, 707.883 + 0.25, 17500.0, 44.0, 1279.72, 708.968 + 0.3, 17500.0, 44.0, 1287.86, 704.723 + 0.35, 17500.0, 44.0, 1288.44, 696.179 + 0.4, 17500.0, 44.0, 1283.64, 684.363 + 0.45, 17500.0, 44.0, 1280.81, 672.469 + 0.5, 17500.0, 44.0, 1266.61, 655.031 + 0.55, 17500.0, 44.0, 1232.87, 628.745 + 0.6, 17500.0, 44.0, 1171.41, 590.308 + 0.0, 17500.0, 46.0, 1126.06, 662.121 + 0.05, 17500.0, 46.0, 1210.34, 698.015 + 0.1, 17500.0, 46.0, 1274.86, 723.633 + 0.15, 17500.0, 46.0, 1321.94, 740.111 + 0.2, 17500.0, 46.0, 1353.92, 748.588 + 0.25, 17500.0, 46.0, 1373.13, 750.201 + 0.3, 17500.0, 46.0, 1381.88, 746.087 + 0.35, 17500.0, 46.0, 1382.52, 737.383 + 0.4, 17500.0, 46.0, 1377.36, 725.228 + 0.45, 17500.0, 46.0, 1374.28, 713.13 + 0.5, 17500.0, 46.0, 1359.0, 695.112 + 0.55, 17500.0, 46.0, 1322.79, 667.565 + 0.6, 17500.0, 46.0, 1256.93, 626.884 + 0.0, 17500.0, 48.0, 1202.57, 696.872 + 0.05, 17500.0, 48.0, 1292.78, 735.157 + 0.1, 17500.0, 48.0, 1361.83, 762.581 + 0.15, 17500.0, 48.0, 1412.21, 780.355 + 0.2, 17500.0, 48.0, 1446.42, 789.687 + 0.25, 17500.0, 48.0, 1466.95, 791.786 + 0.3, 17500.0, 48.0, 1476.3, 787.86 + 0.35, 17500.0, 48.0, 1476.97, 779.119 + 0.4, 17500.0, 48.0, 1471.46, 766.77 + 0.45, 17500.0, 48.0, 1468.17, 754.604 + 0.5, 17500.0, 48.0, 1451.86, 736.089 + 0.55, 17500.0, 48.0, 1413.19, 707.273 + 0.6, 17500.0, 48.0, 1342.81, 664.206 + 0.0, 17500.0, 50.0, 1280.9, 733.6 + 0.05, 17500.0, 50.0, 1376.21, 773.406 + 0.1, 17500.0, 50.0, 1449.2, 802.1 + 0.15, 17500.0, 50.0, 1502.49, 820.894 + 0.2, 17500.0, 50.0, 1538.7, 831.0 + 0.25, 17500.0, 50.0, 1560.46, 833.631 + 0.3, 17500.0, 50.0, 1570.4, 830.0 + 0.35, 17500.0, 50.0, 1571.14, 821.319 + 0.4, 17500.0, 50.0, 1565.3, 808.8 + 0.45, 17500.0, 50.0, 1561.78, 796.344 + 0.5, 17500.0, 50.0, 1544.4, 777.1 + 0.55, 17500.0, 50.0, 1503.24, 746.906 + 0.6, 17500.0, 50.0, 1428.4, 701.6 + 0.0, 20000.0, 20.0, 162.5, 294.8 + 0.05, 20000.0, 20.0, 157.781, 293.4 + 0.1, 20000.0, 20.0, 155.2, 290.7 + 0.15, 20000.0, 20.0, 154.344, 286.75 + 0.2, 20000.0, 20.0, 154.8, 281.6 + 0.25, 20000.0, 20.0, 156.156, 275.3 + 0.3, 20000.0, 20.0, 158.0, 267.9 + 0.35, 20000.0, 20.0, 159.919, 259.45 + 0.4, 20000.0, 20.0, 161.5, 250.0 + 0.45, 20000.0, 20.0, 162.156, 239.581 + 0.5, 20000.0, 20.0, 162.0, 228.3 + 0.55, 20000.0, 20.0, 160.969, 216.244 + 0.6, 20000.0, 20.0, 159.0, 203.5 + 0.0, 20000.0, 22.0, 258.199, 321.673 + 0.05, 20000.0, 22.0, 251.476, 319.349 + 0.1, 20000.0, 22.0, 247.929, 316.277 + 0.15, 20000.0, 22.0, 246.937, 312.403 + 0.2, 20000.0, 22.0, 247.88, 307.676 + 0.25, 20000.0, 22.0, 250.137, 302.042 + 0.3, 20000.0, 22.0, 253.088, 295.448 + 0.35, 20000.0, 22.0, 256.111, 287.841 + 0.4, 20000.0, 22.0, 258.586, 279.169 + 0.45, 20000.0, 22.0, 259.636, 269.31 + 0.5, 20000.0, 22.0, 259.41, 258.415 + 0.55, 20000.0, 22.0, 257.797, 246.567 + 0.6, 20000.0, 22.0, 254.689, 233.849 + 0.0, 20000.0, 24.0, 355.85, 353.581 + 0.05, 20000.0, 24.0, 346.176, 350.188 + 0.1, 20000.0, 24.0, 341.005, 346.613 + 0.15, 20000.0, 24.0, 339.458, 342.694 + 0.2, 20000.0, 24.0, 340.66, 338.267 + 0.25, 20000.0, 24.0, 343.734, 333.171 + 0.3, 20000.0, 24.0, 347.804, 327.242 + 0.35, 20000.0, 24.0, 351.992, 320.317 + 0.4, 20000.0, 24.0, 355.423, 312.234 + 0.45, 20000.0, 24.0, 356.846, 302.714 + 0.5, 20000.0, 24.0, 356.505, 291.944 + 0.55, 20000.0, 24.0, 354.268, 279.994 + 0.6, 20000.0, 24.0, 350.004, 266.937 + 0.0, 20000.0, 26.0, 454.15, 389.413 + 0.05, 20000.0, 26.0, 441.211, 384.703 + 0.1, 20000.0, 26.0, 434.195, 380.422 + 0.15, 20000.0, 26.0, 431.954, 376.289 + 0.2, 20000.0, 26.0, 433.34, 372.021 + 0.25, 20000.0, 26.0, 437.203, 367.336 + 0.3, 20000.0, 26.0, 442.396, 361.952 + 0.35, 20000.0, 26.0, 447.77, 355.586 + 0.4, 20000.0, 26.0, 452.177, 347.956 + 0.45, 20000.0, 26.0, 453.966, 338.607 + 0.5, 20000.0, 26.0, 453.495, 327.775 + 0.55, 20000.0, 26.0, 450.62, 315.522 + 0.6, 20000.0, 26.0, 445.196, 301.911 + 0.0, 20000.0, 28.0, 551.161, 428.355 + 0.05, 20000.0, 28.0, 535.573, 421.758 + 0.1, 20000.0, 28.0, 527.142, 416.341 + 0.15, 20000.0, 28.0, 524.48, 411.68 + 0.2, 20000.0, 28.0, 526.197, 407.348 + 0.25, 20000.0, 28.0, 530.905, 402.923 + 0.3, 20000.0, 28.0, 537.214, 397.98 + 0.35, 20000.0, 28.0, 543.735, 392.094 + 0.4, 20000.0, 28.0, 549.079, 384.841 + 0.45, 20000.0, 28.0, 551.248, 375.546 + 0.5, 20000.0, 28.0, 550.677, 364.537 + 0.55, 20000.0, 28.0, 547.191, 351.891 + 0.6, 20000.0, 28.0, 540.613, 337.688 + 0.0, 20000.0, 30.0, 647.5, 468.4 + 0.05, 20000.0, 30.0, 629.606, 459.894 + 0.1, 20000.0, 30.0, 620.0, 453.3 + 0.15, 20000.0, 30.0, 617.069, 448.056 + 0.2, 20000.0, 30.0, 619.2, 443.6 + 0.25, 20000.0, 30.0, 624.781, 439.369 + 0.3, 20000.0, 30.0, 632.2, 434.8 + 0.35, 20000.0, 30.0, 639.844, 429.331 + 0.4, 20000.0, 30.0, 646.1, 422.4 + 0.45, 20000.0, 30.0, 648.656, 413.112 + 0.5, 20000.0, 30.0, 648.0, 401.9 + 0.55, 20000.0, 30.0, 643.919, 388.862 + 0.6, 20000.0, 30.0, 636.2, 374.1 + 0.0, 20000.0, 32.0, 745.387, 505.599 + 0.05, 20000.0, 32.0, 724.542, 496.624 + 0.1, 20000.0, 32.0, 713.308, 489.847 + 0.15, 20000.0, 32.0, 709.818, 484.644 + 0.2, 20000.0, 32.0, 712.203, 480.39 + 0.25, 20000.0, 32.0, 718.594, 476.461 + 0.3, 20000.0, 32.0, 727.124, 472.232 + 0.35, 20000.0, 32.0, 735.925, 467.08 + 0.4, 20000.0, 32.0, 743.128, 460.38 + 0.45, 20000.0, 32.0, 746.044, 451.15 + 0.5, 20000.0, 32.0, 745.267, 439.838 + 0.55, 20000.0, 32.0, 740.57, 426.533 + 0.6, 20000.0, 32.0, 731.725, 411.326 + 0.0, 20000.0, 34.0, 842.382, 545.689 + 0.05, 20000.0, 34.0, 818.877, 535.14 + 0.1, 20000.0, 34.0, 806.22, 527.418 + 0.15, 20000.0, 34.0, 802.302, 521.783 + 0.2, 20000.0, 34.0, 805.014, 517.496 + 0.25, 20000.0, 34.0, 812.245, 513.816 + 0.3, 20000.0, 34.0, 821.886, 510.002 + 0.35, 20000.0, 34.0, 831.829, 505.314 + 0.4, 20000.0, 34.0, 839.962, 499.013 + 0.45, 20000.0, 34.0, 843.247, 489.954 + 0.5, 20000.0, 34.0, 842.363, 478.607 + 0.55, 20000.0, 34.0, 837.06, 465.038 + 0.6, 20000.0, 34.0, 827.087, 449.313 + 0.0, 20000.0, 36.0, 938.267, 589.458 + 0.05, 20000.0, 36.0, 912.503, 575.834 + 0.1, 20000.0, 36.0, 898.702, 566.155 + 0.15, 20000.0, 36.0, 894.535, 559.484 + 0.2, 20000.0, 36.0, 897.67, 554.883 + 0.25, 20000.0, 36.0, 905.778, 551.417 + 0.3, 20000.0, 36.0, 916.528, 548.148 + 0.35, 20000.0, 36.0, 927.589, 544.139 + 0.4, 20000.0, 36.0, 936.631, 538.455 + 0.45, 20000.0, 36.0, 940.303, 529.672 + 0.5, 20000.0, 36.0, 939.336, 518.312 + 0.55, 20000.0, 36.0, 933.441, 504.411 + 0.6, 20000.0, 36.0, 922.327, 488.004 + 0.0, 20000.0, 38.0, 1037.43, 627.355 + 0.05, 20000.0, 38.0, 1008.31, 613.383 + 0.1, 20000.0, 38.0, 992.581, 603.726 + 0.15, 20000.0, 38.0, 987.651, 597.362 + 0.2, 20000.0, 38.0, 990.916, 593.263 + 0.25, 20000.0, 38.0, 999.771, 590.406 + 0.3, 20000.0, 38.0, 1011.61, 587.765 + 0.35, 20000.0, 38.0, 1023.84, 584.316 + 0.4, 20000.0, 38.0, 1033.86, 579.032 + 0.45, 20000.0, 38.0, 1037.9, 570.375 + 0.5, 20000.0, 38.0, 1036.82, 558.862 + 0.55, 20000.0, 38.0, 1030.29, 544.496 + 0.6, 20000.0, 38.0, 1018.02, 527.279 + 0.0, 20000.0, 40.0, 1135.9, 669.7 + 0.05, 20000.0, 40.0, 1103.49, 654.094 + 0.1, 20000.0, 40.0, 1085.9, 643.5 + 0.15, 20000.0, 40.0, 1080.26, 636.756 + 0.2, 20000.0, 40.0, 1083.7, 632.7 + 0.25, 20000.0, 40.0, 1093.34, 630.169 + 0.3, 20000.0, 40.0, 1106.3, 628.0 + 0.35, 20000.0, 40.0, 1119.71, 625.031 + 0.4, 20000.0, 40.0, 1130.7, 620.1 + 0.45, 20000.0, 40.0, 1135.11, 611.456 + 0.5, 20000.0, 40.0, 1133.9, 599.7 + 0.55, 20000.0, 40.0, 1126.74, 584.844 + 0.6, 20000.0, 40.0, 1113.3, 566.9 + 0.0, 20000.0, 42.0, 1232.69, 710.136 + 0.05, 20000.0, 42.0, 1197.71, 693.827 + 0.1, 20000.0, 42.0, 1178.76, 682.935 + 0.15, 20000.0, 42.0, 1172.72, 676.208 + 0.2, 20000.0, 42.0, 1176.48, 672.395 + 0.25, 20000.0, 42.0, 1186.94, 670.243 + 0.3, 20000.0, 42.0, 1200.99, 668.5 + 0.35, 20000.0, 42.0, 1215.53, 665.915 + 0.4, 20000.0, 42.0, 1227.45, 661.236 + 0.45, 20000.0, 42.0, 1232.27, 652.576 + 0.5, 20000.0, 42.0, 1230.99, 640.587 + 0.55, 20000.0, 42.0, 1223.23, 625.286 + 0.6, 20000.0, 42.0, 1208.61, 606.692 + 0.0, 20000.0, 44.0, 1330.63, 753.564 + 0.05, 20000.0, 44.0, 1292.7, 735.557 + 0.1, 20000.0, 44.0, 1272.13, 723.646 + 0.15, 20000.0, 44.0, 1265.55, 716.449 + 0.2, 20000.0, 44.0, 1269.58, 712.585 + 0.25, 20000.0, 44.0, 1280.88, 710.673 + 0.3, 20000.0, 44.0, 1296.06, 709.331 + 0.35, 20000.0, 44.0, 1311.78, 707.178 + 0.4, 20000.0, 44.0, 1324.65, 702.833 + 0.45, 20000.0, 44.0, 1329.83, 694.187 + 0.5, 20000.0, 44.0, 1328.43, 682.043 + 0.55, 20000.0, 44.0, 1320.06, 666.477 + 0.6, 20000.0, 44.0, 1304.33, 647.564 + 0.0, 20000.0, 46.0, 1426.45, 795.168 + 0.05, 20000.0, 46.0, 1386.28, 776.486 + 0.1, 20000.0, 46.0, 1364.58, 764.222 + 0.15, 20000.0, 46.0, 1357.75, 756.935 + 0.2, 20000.0, 46.0, 1362.22, 753.184 + 0.25, 20000.0, 46.0, 1374.39, 751.526 + 0.3, 20000.0, 46.0, 1390.68, 750.521 + 0.35, 20000.0, 46.0, 1407.51, 748.727 + 0.4, 20000.0, 46.0, 1421.29, 744.703 + 0.45, 20000.0, 46.0, 1426.86, 736.315 + 0.5, 20000.0, 46.0, 1425.37, 724.197 + 0.55, 20000.0, 46.0, 1416.39, 708.292 + 0.6, 20000.0, 46.0, 1399.47, 688.543 + 0.0, 20000.0, 48.0, 1524.63, 843.66 + 0.05, 20000.0, 48.0, 1481.44, 821.483 + 0.1, 20000.0, 48.0, 1458.05, 806.955 + 0.15, 20000.0, 48.0, 1450.62, 798.419 + 0.2, 20000.0, 48.0, 1455.32, 794.215 + 0.25, 20000.0, 48.0, 1468.29, 792.685 + 0.3, 20000.0, 48.0, 1485.7, 792.17 + 0.35, 20000.0, 48.0, 1503.7, 791.013 + 0.4, 20000.0, 48.0, 1518.45, 787.553 + 0.45, 20000.0, 48.0, 1524.4, 779.338 + 0.5, 20000.0, 48.0, 1522.81, 767.095 + 0.55, 20000.0, 48.0, 1513.19, 750.761 + 0.6, 20000.0, 48.0, 1495.1, 730.268 + 0.0, 20000.0, 50.0, 1621.4, 887.0 + 0.05, 20000.0, 50.0, 1575.65, 863.306 + 0.1, 20000.0, 50.0, 1550.9, 848.0 + 0.15, 20000.0, 50.0, 1543.08, 839.269 + 0.2, 20000.0, 50.0, 1548.1, 835.3 + 0.25, 20000.0, 50.0, 1561.9, 834.281 + 0.3, 20000.0, 50.0, 1580.4, 834.4 + 0.35, 20000.0, 50.0, 1599.53, 833.844 + 0.4, 20000.0, 50.0, 1615.2, 830.8 + 0.45, 20000.0, 50.0, 1621.57, 822.544 + 0.5, 20000.0, 50.0, 1619.9, 810.0 + 0.55, 20000.0, 50.0, 1609.68, 793.181 + 0.6, 20000.0, 50.0, 1590.4, 772.1 + 0.0, 23000.0, 20.0, 150.2, 342.1 + 0.05, 23000.0, 20.0, 152.056, 341.856 + 0.1, 23000.0, 20.0, 153.8, 339.3 + 0.15, 23000.0, 20.0, 155.469, 334.644 + 0.2, 23000.0, 20.0, 157.1, 328.1 + 0.25, 23000.0, 20.0, 158.731, 319.881 + 0.3, 23000.0, 20.0, 160.4, 310.2 + 0.35, 23000.0, 20.0, 162.144, 299.269 + 0.4, 23000.0, 20.0, 164.0, 287.3 + 0.45, 23000.0, 20.0, 166.238, 274.55 + 0.5, 23000.0, 20.0, 168.2, 261.1 + 0.55, 23000.0, 20.0, 169.463, 247.075 + 0.6, 23000.0, 20.0, 169.6, 232.6 + 0.0, 23000.0, 22.0, 240.861, 351.257 + 0.05, 23000.0, 22.0, 243.682, 351.114 + 0.1, 23000.0, 22.0, 246.371, 349.037 + 0.15, 23000.0, 22.0, 248.981, 345.193 + 0.2, 23000.0, 22.0, 251.563, 339.75 + 0.25, 23000.0, 22.0, 254.168, 332.876 + 0.3, 23000.0, 22.0, 256.848, 324.736 + 0.35, 23000.0, 22.0, 259.653, 315.498 + 0.4, 23000.0, 22.0, 262.635, 305.33 + 0.45, 23000.0, 22.0, 266.203, 294.48 + 0.5, 23000.0, 22.0, 269.338, 282.871 + 0.55, 23000.0, 22.0, 271.376, 270.51 + 0.6, 23000.0, 22.0, 271.657, 257.4 + 0.0, 23000.0, 24.0, 330.26, 370.678 + 0.05, 23000.0, 24.0, 334.466, 371.234 + 0.1, 23000.0, 24.0, 338.386, 369.926 + 0.15, 23000.0, 24.0, 342.108, 366.921 + 0.2, 23000.0, 24.0, 345.722, 362.384 + 0.25, 23000.0, 24.0, 349.317, 356.478 + 0.3, 23000.0, 24.0, 352.984, 349.371 + 0.35, 23000.0, 24.0, 356.811, 341.226 + 0.4, 23000.0, 24.0, 360.888, 332.209 + 0.45, 23000.0, 24.0, 365.813, 322.635 + 0.5, 23000.0, 24.0, 370.149, 312.218 + 0.55, 23000.0, 24.0, 372.966, 300.822 + 0.6, 23000.0, 24.0, 373.335, 288.311 + 0.0, 23000.0, 26.0, 419.24, 397.591 + 0.05, 23000.0, 26.0, 424.971, 399.017 + 0.1, 23000.0, 26.0, 430.214, 398.508 + 0.15, 23000.0, 26.0, 435.105, 396.245 + 0.2, 23000.0, 26.0, 439.778, 392.412 + 0.25, 23000.0, 26.0, 444.37, 387.188 + 0.3, 23000.0, 26.0, 449.016, 380.758 + 0.35, 23000.0, 26.0, 453.852, 373.302 + 0.4, 23000.0, 26.0, 459.012, 365.002 + 0.45, 23000.0, 26.0, 465.305, 356.271 + 0.5, 23000.0, 26.0, 470.851, 346.599 + 0.55, 23000.0, 26.0, 474.443, 335.706 + 0.6, 23000.0, 26.0, 474.873, 323.312 + 0.0, 23000.0, 28.0, 508.999, 429.156 + 0.05, 23000.0, 28.0, 515.998, 430.924 + 0.1, 23000.0, 28.0, 522.39, 430.795 + 0.15, 23000.0, 28.0, 528.342, 428.948 + 0.2, 23000.0, 28.0, 534.021, 425.561 + 0.25, 23000.0, 28.0, 539.596, 420.813 + 0.3, 23000.0, 28.0, 545.233, 414.883 + 0.35, 23000.0, 28.0, 551.1, 407.948 + 0.4, 23000.0, 28.0, 557.364, 400.189 + 0.45, 23000.0, 28.0, 565.013, 392.071 + 0.5, 23000.0, 28.0, 571.752, 382.909 + 0.55, 23000.0, 28.0, 576.108, 372.305 + 0.6, 23000.0, 28.0, 576.606, 359.863 + 0.0, 23000.0, 30.0, 599.3, 462.8 + 0.05, 23000.0, 30.0, 607.381, 464.775 + 0.1, 23000.0, 30.0, 614.8, 464.9 + 0.15, 23000.0, 30.0, 621.744, 463.35 + 0.2, 23000.0, 30.0, 628.4, 460.3 + 0.25, 23000.0, 30.0, 634.956, 455.925 + 0.3, 23000.0, 30.0, 641.6, 450.4 + 0.35, 23000.0, 30.0, 648.519, 443.9 + 0.4, 23000.0, 30.0, 655.9, 436.6 + 0.45, 23000.0, 30.0, 664.887, 429.013 + 0.5, 23000.0, 30.0, 672.8, 420.3 + 0.55, 23000.0, 30.0, 677.913, 409.963 + 0.6, 23000.0, 30.0, 678.5, 397.5 + 0.0, 23000.0, 32.0, 688.767, 494.468 + 0.05, 23000.0, 32.0, 698.246, 497.905 + 0.1, 23000.0, 32.0, 706.917, 499.126 + 0.15, 23000.0, 32.0, 715.002, 498.376 + 0.2, 23000.0, 32.0, 722.724, 495.903 + 0.25, 23000.0, 32.0, 730.304, 491.952 + 0.3, 23000.0, 32.0, 737.967, 486.771 + 0.35, 23000.0, 32.0, 745.935, 480.604 + 0.4, 23000.0, 32.0, 754.43, 473.698 + 0.45, 23000.0, 32.0, 764.785, 466.738 + 0.5, 23000.0, 32.0, 773.894, 458.657 + 0.55, 23000.0, 32.0, 779.761, 448.827 + 0.6, 23000.0, 32.0, 780.388, 436.619 + 0.0, 23000.0, 34.0, 780.934, 530.156 + 0.05, 23000.0, 34.0, 790.52, 533.546 + 0.1, 23000.0, 34.0, 799.593, 534.845 + 0.15, 23000.0, 34.0, 808.321, 534.285 + 0.2, 23000.0, 34.0, 816.876, 532.099 + 0.25, 23000.0, 34.0, 825.427, 528.522 + 0.3, 23000.0, 34.0, 834.146, 523.787 + 0.35, 23000.0, 34.0, 843.203, 518.126 + 0.4, 23000.0, 34.0, 852.768, 511.773 + 0.45, 23000.0, 34.0, 864.099, 505.427 + 0.5, 23000.0, 34.0, 874.103, 497.926 + 0.55, 23000.0, 34.0, 880.776, 488.576 + 0.6, 23000.0, 34.0, 882.111, 476.68 + 0.0, 23000.0, 36.0, 875.279, 570.318 + 0.05, 23000.0, 36.0, 883.965, 571.861 + 0.1, 23000.0, 36.0, 892.764, 572.04 + 0.15, 23000.0, 36.0, 901.729, 570.97 + 0.2, 23000.0, 36.0, 910.913, 568.764 + 0.25, 23000.0, 36.0, 920.373, 565.538 + 0.3, 23000.0, 36.0, 930.16, 561.405 + 0.35, 23000.0, 36.0, 940.33, 556.479 + 0.4, 23000.0, 36.0, 950.937, 550.875 + 0.45, 23000.0, 36.0, 962.978, 545.121 + 0.5, 23000.0, 36.0, 973.675, 538.089 + 0.55, 23000.0, 36.0, 981.193, 529.069 + 0.6, 23000.0, 36.0, 983.696, 517.348 + 0.0, 23000.0, 38.0, 960.805, 603.507 + 0.05, 23000.0, 38.0, 972.867, 606.692 + 0.1, 23000.0, 38.0, 984.177, 608.174 + 0.15, 23000.0, 38.0, 994.975, 608.127 + 0.2, 23000.0, 38.0, 1005.5, 606.724 + 0.25, 23000.0, 38.0, 1015.99, 604.136 + 0.3, 23000.0, 38.0, 1026.68, 600.538 + 0.35, 23000.0, 38.0, 1037.81, 596.103 + 0.4, 23000.0, 38.0, 1049.62, 591.002 + 0.45, 23000.0, 38.0, 1063.76, 585.962 + 0.5, 23000.0, 38.0, 1076.23, 579.497 + 0.55, 23000.0, 38.0, 1084.43, 570.671 + 0.6, 23000.0, 38.0, 1085.76, 558.551 + 0.0, 23000.0, 40.0, 1049.3, 640.8 + 0.05, 23000.0, 40.0, 1063.11, 644.4 + 0.1, 23000.0, 40.0, 1075.9, 646.3 + 0.15, 23000.0, 40.0, 1087.96, 646.675 + 0.2, 23000.0, 40.0, 1099.6, 645.7 + 0.25, 23000.0, 40.0, 1111.11, 643.55 + 0.3, 23000.0, 40.0, 1122.8, 640.4 + 0.35, 23000.0, 40.0, 1134.96, 636.425 + 0.4, 23000.0, 40.0, 1147.9, 631.8 + 0.45, 23000.0, 40.0, 1163.54, 627.325 + 0.5, 23000.0, 40.0, 1177.3, 621.3 + 0.55, 23000.0, 40.0, 1186.24, 612.65 + 0.6, 23000.0, 40.0, 1187.4, 600.3 + 0.0, 23000.0, 42.0, 1139.46, 678.57 + 0.05, 23000.0, 42.0, 1154.37, 682.658 + 0.1, 23000.0, 42.0, 1168.17, 685.019 + 0.15, 23000.0, 42.0, 1181.21, 685.833 + 0.2, 23000.0, 42.0, 1193.8, 685.281 + 0.25, 23000.0, 42.0, 1206.27, 683.544 + 0.3, 23000.0, 42.0, 1218.94, 680.802 + 0.35, 23000.0, 42.0, 1232.13, 677.236 + 0.4, 23000.0, 42.0, 1246.18, 673.026 + 0.45, 23000.0, 42.0, 1263.16, 668.999 + 0.5, 23000.0, 42.0, 1278.11, 663.398 + 0.55, 23000.0, 42.0, 1287.81, 655.112 + 0.6, 23000.0, 42.0, 1289.05, 643.031 + 0.0, 23000.0, 44.0, 1228.25, 713.657 + 0.05, 23000.0, 44.0, 1244.93, 719.635 + 0.1, 23000.0, 44.0, 1260.23, 723.378 + 0.15, 23000.0, 44.0, 1274.55, 725.164 + 0.2, 23000.0, 44.0, 1288.26, 725.272 + 0.25, 23000.0, 44.0, 1301.76, 723.979 + 0.3, 23000.0, 44.0, 1315.41, 721.563 + 0.35, 23000.0, 44.0, 1329.6, 718.303 + 0.4, 23000.0, 44.0, 1344.72, 714.476 + 0.45, 23000.0, 44.0, 1363.09, 711.155 + 0.5, 23000.0, 44.0, 1379.27, 706.235 + 0.55, 23000.0, 44.0, 1389.76, 698.408 + 0.6, 23000.0, 44.0, 1391.05, 686.363 + 0.0, 23000.0, 46.0, 1318.23, 753.665 + 0.05, 23000.0, 46.0, 1335.98, 759.596 + 0.1, 23000.0, 46.0, 1352.29, 763.363 + 0.15, 23000.0, 46.0, 1367.59, 765.25 + 0.2, 23000.0, 46.0, 1382.27, 765.539 + 0.25, 23000.0, 46.0, 1396.74, 764.515 + 0.3, 23000.0, 46.0, 1411.39, 762.463 + 0.35, 23000.0, 46.0, 1426.64, 759.665 + 0.4, 23000.0, 46.0, 1442.87, 756.406 + 0.45, 23000.0, 46.0, 1462.58, 753.881 + 0.5, 23000.0, 46.0, 1479.93, 749.64 + 0.55, 23000.0, 46.0, 1491.16, 742.142 + 0.6, 23000.0, 46.0, 1492.54, 729.848 + 0.0, 23000.0, 48.0, 1408.79, 795.745 + 0.05, 23000.0, 48.0, 1427.58, 800.919 + 0.1, 23000.0, 48.0, 1444.89, 804.3 + 0.15, 23000.0, 48.0, 1461.15, 806.112 + 0.2, 23000.0, 48.0, 1476.78, 806.581 + 0.25, 23000.0, 48.0, 1492.21, 805.931 + 0.3, 23000.0, 48.0, 1507.86, 804.386 + 0.35, 23000.0, 48.0, 1524.15, 802.172 + 0.4, 23000.0, 48.0, 1541.51, 799.514 + 0.45, 23000.0, 48.0, 1562.55, 797.554 + 0.5, 23000.0, 48.0, 1581.09, 793.761 + 0.55, 23000.0, 48.0, 1593.11, 786.521 + 0.6, 23000.0, 48.0, 1594.63, 774.221 + 0.0, 23000.0, 50.0, 1498.4, 835.2 + 0.05, 23000.0, 50.0, 1518.44, 840.769 + 0.1, 23000.0, 50.0, 1536.9, 844.6 + 0.15, 23000.0, 50.0, 1554.24, 846.906 + 0.2, 23000.0, 50.0, 1570.9, 847.9 + 0.25, 23000.0, 50.0, 1587.34, 847.794 + 0.3, 23000.0, 50.0, 1604.0, 846.8 + 0.35, 23000.0, 50.0, 1621.34, 845.131 + 0.4, 23000.0, 50.0, 1639.8, 843.0 + 0.45, 23000.0, 50.0, 1662.19, 841.569 + 0.5, 23000.0, 50.0, 1681.9, 838.2 + 0.55, 23000.0, 50.0, 1694.69, 831.206 + 0.6, 23000.0, 50.0, 1696.3, 818.9 + 0.0, 25000.0, 20.0, 151.6, 398.9 + 0.05, 25000.0, 20.0, 153.325, 398.087 + 0.1, 25000.0, 20.0, 155.0, 394.4 + 0.15, 25000.0, 20.0, 156.65, 388.112 + 0.2, 25000.0, 20.0, 158.3, 379.5 + 0.25, 25000.0, 20.0, 159.975, 368.838 + 0.3, 25000.0, 20.0, 161.7, 356.4 + 0.35, 25000.0, 20.0, 163.5, 342.463 + 0.4, 25000.0, 20.0, 165.4, 327.3 + 0.45, 25000.0, 20.0, 167.438, 311.188 + 0.5, 25000.0, 20.0, 169.6, 294.4 + 0.55, 25000.0, 20.0, 171.888, 277.213 + 0.6, 25000.0, 20.0, 174.3, 259.9 + 0.0, 25000.0, 22.0, 241.951, 385.858 + 0.05, 25000.0, 22.0, 245.144, 385.52 + 0.1, 25000.0, 22.0, 248.095, 382.883 + 0.15, 25000.0, 22.0, 250.877, 378.156 + 0.2, 25000.0, 22.0, 253.562, 371.549 + 0.25, 25000.0, 22.0, 256.222, 363.271 + 0.3, 25000.0, 22.0, 258.929, 353.535 + 0.35, 25000.0, 22.0, 261.755, 342.548 + 0.4, 25000.0, 22.0, 264.771, 330.521 + 0.45, 25000.0, 22.0, 268.122, 317.654 + 0.5, 25000.0, 22.0, 271.663, 304.186 + 0.55, 25000.0, 22.0, 275.32, 290.347 + 0.6, 25000.0, 22.0, 279.022, 276.365 + 0.0, 25000.0, 24.0, 332.736, 394.756 + 0.05, 25000.0, 24.0, 337.023, 394.921 + 0.1, 25000.0, 24.0, 341.012, 393.065 + 0.15, 25000.0, 24.0, 344.796, 389.37 + 0.2, 25000.0, 24.0, 348.467, 384.016 + 0.25, 25000.0, 24.0, 352.119, 377.186 + 0.3, 25000.0, 24.0, 355.845, 369.058 + 0.35, 25000.0, 24.0, 359.736, 359.816 + 0.4, 25000.0, 24.0, 363.885, 349.639 + 0.45, 25000.0, 24.0, 368.477, 338.705 + 0.5, 25000.0, 24.0, 373.331, 327.205 + 0.55, 25000.0, 24.0, 378.359, 315.323 + 0.6, 25000.0, 24.0, 383.471, 303.245 + 0.0, 25000.0, 26.0, 423.545, 418.016 + 0.05, 25000.0, 26.0, 428.843, 418.701 + 0.1, 25000.0, 26.0, 433.821, 417.456 + 0.15, 25000.0, 26.0, 438.585, 414.454 + 0.2, 25000.0, 26.0, 443.241, 409.87 + 0.25, 25000.0, 26.0, 447.896, 403.879 + 0.3, 25000.0, 26.0, 452.655, 396.655 + 0.35, 25000.0, 26.0, 457.626, 388.373 + 0.4, 25000.0, 26.0, 462.915, 379.206 + 0.45, 25000.0, 26.0, 468.723, 369.344 + 0.5, 25000.0, 26.0, 474.869, 358.92 + 0.55, 25000.0, 26.0, 481.266, 348.084 + 0.6, 25000.0, 26.0, 487.829, 336.984 + 0.0, 25000.0, 28.0, 513.62, 446.566 + 0.05, 25000.0, 28.0, 520.325, 447.743 + 0.1, 25000.0, 28.0, 526.559, 447.035 + 0.15, 25000.0, 28.0, 532.466, 444.609 + 0.2, 25000.0, 28.0, 538.189, 440.637 + 0.25, 25000.0, 28.0, 543.87, 435.288 + 0.3, 25000.0, 28.0, 549.652, 428.733 + 0.35, 25000.0, 28.0, 555.678, 421.14 + 0.4, 25000.0, 28.0, 562.09, 412.682 + 0.45, 25000.0, 28.0, 569.164, 403.552 + 0.5, 25000.0, 28.0, 576.645, 393.844 + 0.55, 25000.0, 28.0, 584.412, 383.678 + 0.6, 25000.0, 28.0, 592.343, 373.171 + 0.0, 25000.0, 30.0, 603.6, 477.3 + 0.05, 25000.0, 30.0, 611.831, 479.05 + 0.1, 25000.0, 30.0, 619.4, 478.9 + 0.15, 25000.0, 30.0, 626.494, 477.025 + 0.2, 25000.0, 30.0, 633.3, 473.6 + 0.25, 25000.0, 30.0, 640.006, 468.8 + 0.3, 25000.0, 30.0, 646.8, 462.8 + 0.35, 25000.0, 30.0, 653.869, 455.775 + 0.4, 25000.0, 30.0, 661.4, 447.9 + 0.45, 25000.0, 30.0, 669.763, 439.387 + 0.5, 25000.0, 30.0, 678.6, 430.3 + 0.55, 25000.0, 30.0, 687.738, 420.737 + 0.6, 25000.0, 30.0, 697.0, 410.8 + 0.0, 25000.0, 32.0, 695.182, 508.442 + 0.05, 25000.0, 32.0, 704.287, 511.256 + 0.1, 25000.0, 32.0, 712.738, 511.936 + 0.15, 25000.0, 32.0, 720.732, 510.708 + 0.2, 25000.0, 32.0, 728.466, 507.799 + 0.25, 25000.0, 32.0, 736.139, 503.435 + 0.3, 25000.0, 32.0, 743.948, 497.842 + 0.35, 25000.0, 32.0, 752.091, 491.246 + 0.4, 25000.0, 32.0, 760.765, 483.874 + 0.45, 25000.0, 32.0, 770.358, 476.014 + 0.5, 25000.0, 32.0, 780.5, 467.705 + 0.55, 25000.0, 32.0, 791.013, 459.049 + 0.6, 25000.0, 32.0, 801.719, 450.149 + 0.0, 25000.0, 34.0, 786.511, 542.501 + 0.05, 25000.0, 34.0, 796.496, 545.54 + 0.1, 25000.0, 34.0, 805.84, 546.486 + 0.15, 25000.0, 34.0, 814.747, 545.569 + 0.2, 25000.0, 34.0, 823.425, 543.022 + 0.25, 25000.0, 34.0, 832.078, 539.077 + 0.3, 25000.0, 34.0, 840.912, 533.966 + 0.35, 25000.0, 34.0, 850.134, 527.922 + 0.4, 25000.0, 34.0, 859.949, 521.176 + 0.45, 25000.0, 34.0, 870.752, 514.034 + 0.5, 25000.0, 34.0, 882.18, 506.509 + 0.55, 25000.0, 34.0, 894.059, 498.685 + 0.6, 25000.0, 34.0, 906.216, 490.649 + 0.0, 25000.0, 36.0, 877.181, 579.325 + 0.05, 25000.0, 36.0, 888.226, 581.63 + 0.1, 25000.0, 36.0, 898.593, 582.235 + 0.15, 25000.0, 36.0, 908.502, 581.314 + 0.2, 25000.0, 36.0, 918.177, 579.04 + 0.25, 25000.0, 36.0, 927.838, 575.585 + 0.3, 25000.0, 36.0, 937.707, 571.123 + 0.35, 25000.0, 36.0, 948.005, 565.827 + 0.4, 25000.0, 36.0, 958.955, 559.87 + 0.45, 25000.0, 36.0, 970.979, 553.49 + 0.5, 25000.0, 36.0, 983.696, 546.666 + 0.55, 25000.0, 36.0, 996.925, 539.443 + 0.6, 25000.0, 36.0, 1010.49, 531.866 + 0.0, 25000.0, 38.0, 969.53, 613.149 + 0.05, 25000.0, 38.0, 981.199, 616.51 + 0.1, 25000.0, 38.0, 992.265, 618.067 + 0.15, 25000.0, 38.0, 1002.95, 618.003 + 0.2, 25000.0, 38.0, 1013.48, 616.501 + 0.25, 25000.0, 38.0, 1024.07, 613.743 + 0.3, 25000.0, 38.0, 1034.96, 609.913 + 0.35, 25000.0, 38.0, 1046.35, 605.193 + 0.4, 25000.0, 38.0, 1058.48, 599.767 + 0.45, 25000.0, 38.0, 1071.8, 593.885 + 0.5, 25000.0, 38.0, 1085.85, 587.525 + 0.55, 25000.0, 38.0, 1100.42, 580.733 + 0.6, 25000.0, 38.0, 1115.3, 573.556 + 0.0, 25000.0, 40.0, 1059.5, 650.6 + 0.05, 25000.0, 40.0, 1072.58, 654.194 + 0.1, 25000.0, 40.0, 1084.9, 656.0 + 0.15, 25000.0, 40.0, 1096.72, 656.206 + 0.2, 25000.0, 40.0, 1108.3, 655.0 + 0.25, 25000.0, 40.0, 1119.91, 652.569 + 0.3, 25000.0, 40.0, 1131.8, 649.1 + 0.35, 25000.0, 40.0, 1144.24, 644.781 + 0.4, 25000.0, 40.0, 1157.5, 639.8 + 0.45, 25000.0, 40.0, 1172.09, 634.4 + 0.5, 25000.0, 40.0, 1187.5, 628.6 + 0.55, 25000.0, 40.0, 1203.49, 622.475 + 0.6, 25000.0, 40.0, 1219.8, 616.1 + 0.0, 25000.0, 42.0, 1150.16, 687.298 + 0.05, 25000.0, 42.0, 1164.4, 691.605 + 0.1, 25000.0, 42.0, 1177.8, 694.044 + 0.15, 25000.0, 42.0, 1190.65, 694.817 + 0.2, 25000.0, 42.0, 1203.24, 694.129 + 0.25, 25000.0, 42.0, 1215.85, 692.182 + 0.3, 25000.0, 42.0, 1228.76, 689.179 + 0.35, 25000.0, 42.0, 1242.26, 685.324 + 0.4, 25000.0, 42.0, 1256.63, 680.819 + 0.45, 25000.0, 42.0, 1272.44, 675.901 + 0.5, 25000.0, 42.0, 1289.15, 670.676 + 0.55, 25000.0, 42.0, 1306.49, 665.287 + 0.6, 25000.0, 42.0, 1324.21, 659.873 + 0.0, 25000.0, 44.0, 1241.99, 724.296 + 0.05, 25000.0, 44.0, 1257.01, 729.598 + 0.1, 25000.0, 44.0, 1271.24, 732.803 + 0.15, 25000.0, 44.0, 1284.96, 734.167 + 0.2, 25000.0, 44.0, 1298.47, 733.942 + 0.25, 25000.0, 44.0, 1312.05, 732.383 + 0.3, 25000.0, 44.0, 1325.99, 729.745 + 0.35, 25000.0, 44.0, 1340.58, 726.28 + 0.4, 25000.0, 44.0, 1356.11, 722.243 + 0.45, 25000.0, 44.0, 1373.15, 717.971 + 0.5, 25000.0, 44.0, 1391.15, 713.468 + 0.55, 25000.0, 44.0, 1409.85, 708.823 + 0.6, 25000.0, 44.0, 1428.97, 704.122 + 0.0, 25000.0, 46.0, 1332.47, 763.729 + 0.05, 25000.0, 46.0, 1348.63, 769.097 + 0.1, 25000.0, 46.0, 1363.92, 772.405 + 0.15, 25000.0, 46.0, 1378.67, 773.922 + 0.2, 25000.0, 46.0, 1393.19, 773.916 + 0.25, 25000.0, 46.0, 1407.78, 772.656 + 0.3, 25000.0, 46.0, 1422.75, 770.411 + 0.35, 25000.0, 46.0, 1438.42, 767.449 + 0.4, 25000.0, 46.0, 1455.1, 764.04 + 0.45, 25000.0, 46.0, 1473.39, 760.622 + 0.5, 25000.0, 46.0, 1492.71, 756.952 + 0.55, 25000.0, 46.0, 1512.77, 752.957 + 0.6, 25000.0, 46.0, 1533.28, 748.565 + 0.0, 25000.0, 48.0, 1422.42, 808.309 + 0.05, 25000.0, 48.0, 1440.2, 811.554 + 0.1, 25000.0, 48.0, 1456.9, 813.571 + 0.15, 25000.0, 48.0, 1472.87, 814.491 + 0.2, 25000.0, 48.0, 1488.47, 814.441 + 0.25, 25000.0, 48.0, 1504.07, 813.55 + 0.3, 25000.0, 48.0, 1520.03, 811.947 + 0.35, 25000.0, 48.0, 1536.71, 809.759 + 0.4, 25000.0, 48.0, 1554.49, 807.115 + 0.45, 25000.0, 48.0, 1574.06, 804.183 + 0.5, 25000.0, 48.0, 1594.75, 800.975 + 0.55, 25000.0, 48.0, 1616.21, 797.542 + 0.6, 25000.0, 48.0, 1638.1, 793.936 + 0.0, 25000.0, 50.0, 1513.4, 842.5 + 0.05, 25000.0, 50.0, 1532.15, 848.313 + 0.1, 25000.0, 50.0, 1549.8, 852.3 + 0.15, 25000.0, 50.0, 1566.72, 854.688 + 0.2, 25000.0, 50.0, 1583.3, 855.7 + 0.25, 25000.0, 50.0, 1599.9, 855.562 + 0.3, 25000.0, 50.0, 1616.9, 854.5 + 0.35, 25000.0, 50.0, 1634.67, 852.737 + 0.4, 25000.0, 50.0, 1653.6, 850.5 + 0.45, 25000.0, 50.0, 1674.41, 848.113 + 0.5, 25000.0, 50.0, 1696.4, 845.5 + 0.55, 25000.0, 50.0, 1719.21, 842.688 + 0.6, 25000.0, 50.0, 1742.5, 839.7 diff --git a/aviary/models/engines/turboshaft_1120hp_no_tailpipe.deck b/aviary/models/engines/turboshaft_1120hp_no_tailpipe.deck deleted file mode 100644 index 937c6726f4..0000000000 --- a/aviary/models/engines/turboshaft_1120hp_no_tailpipe.deck +++ /dev/null @@ -1,2095 +0,0 @@ -# GASP_TS-derived engine deck converted from MAPS_1120hp.eng -# t4max: 50.0 -# t4cruise: 46.67 -# t4climb: 48.33 -# t4flight_idle: 20.0 -# xsfc: 0.0 -# cexp: 0.0 -# sls_horsepower: 1120.0 -# freeturbine_rpm: 24539.0 -# propeller_rpm: 1210.0 -# gearbox_ratio: 0.049308 -# torque_limit: 4861.4 -# sls_corrected_airflow: 7.9568 - - Mach_Number, Altitude (ft), Throttle, Shaft_Power_Corrected (hp), Fuel_Flow (lb/h) - 0.0, 0.0, 20.0, 111.99999999999997, 195.79999999999995 - 0.05, 0.0, 20.0, 111.76875, 195.18125000000003 - 0.1, 0.0, 20.0, 111.10000000000001, 193.30000000000007 -0.15000000000000002, 0.0, 20.0, 110.00625, 190.2187500000001 - 0.2, 0.0, 20.0, 108.49999999999996, 186.0000000000001 - 0.25, 0.0, 20.0, 106.5875, 180.69999999999982 -0.30000000000000004, 0.0, 20.0, 104.30000000000004, 174.40000000000003 -0.35000000000000003, 0.0, 20.0, 101.65000000000005, 167.13750000000002 - 0.4, 0.0, 20.0, 98.70000000000009, 159.10000000000002 - 0.45, 0.0, 20.0, 95.5000000000001, 150.43750000000006 - 0.5, 0.0, 20.0, 92.10000000000011, 141.30000000000007 - 0.55, 0.0, 20.0, 88.55000000000007, 131.83750000000006 - 0.6000000000000001, 0.0, 20.0, 84.9, 122.2000000000001 - 0.0, 0.0, 22.0, 179.34493481532428, 230.17749238074498 - 0.05, 0.0, 22.0, 178.97463556375254, 229.4503543632648 - 0.1, 0.0, 22.0, 177.90377016055834, 227.28171706993288 -0.15000000000000002, 0.0, 22.0, 176.1523547815024, 223.7555850075051 - 0.2, 0.0, 22.0, 173.74040560234536, 218.95596268273675 - 0.25, 0.0, 22.0, 170.6727293589416, 212.95234426112413 -0.30000000000000004, 0.0, 22.0, 167.01497054677077, 205.8722652732005 -0.35000000000000003, 0.0, 22.0, 162.81315210172886, 197.83780366084835 - 0.4, 0.0, 22.0, 158.13094543843175, 188.93482635550112 - 0.45, 0.0, 22.0, 153.02760985181504, 179.25825304120474 - 0.5, 0.0, 22.0, 147.5624046368148, 168.90300340200494 - 0.55, 0.0, 22.0, 141.7945890883666, 157.96399712194759 - 0.6000000000000001, 0.0, 22.0, 135.78342250140645, 146.53615388507868 - 0.0, 0.0, 24.0, 246.47246740766226, 262.3879720279042 - 0.05, 0.0, 24.0, 245.9635677818766, 261.58413161207505 - 0.1, 0.0, 24.0, 244.4918850802795, 259.1980483184538 -0.15000000000000002, 0.0, 24.0, 242.08492739075146, 255.3172221470399 - 0.2, 0.0, 24.0, 238.77020280117262, 250.0291530978337 - 0.25, 0.0, 24.0, 234.5551146794723, 243.40083374682519 -0.30000000000000004, 0.0, 24.0, 229.52748527338522, 235.58128636604152 -0.35000000000000003, 0.0, 24.0, 223.74657605086406, 226.71818731999855 - 0.4, 0.0, 24.0, 217.30547271921554, 216.88256690719103 - 0.45, 0.0, 24.0, 210.28880492590724, 206.1646169426193 - 0.5, 0.0, 24.0, 202.7812023184073, 194.6545292412836 - 0.55, 0.0, 24.0, 194.86729454418366, 182.44249561818435 - 0.6000000000000001, 0.0, 24.0, 186.63171125070429, 169.61870788832204 - 0.0, 0.0, 26.0, 313.5275325923382, 293.0597054846908 - 0.05, 0.0, 26.0, 312.8801822181247, 292.2039816792531 - 0.1, 0.0, 26.0, 311.0081149197217, 289.6335210320082 -0.15000000000000002, 0.0, 26.0, 307.9463226092493, 285.4348167828225 - 0.2, 0.0, 26.0, 303.7297971988269, 279.69436217156255 - 0.25, 0.0, 26.0, 298.369885320533, 272.4744011019638 -0.30000000000000004, 0.0, 26.0, 291.9725147266139, 263.93417482228193 -0.35000000000000003, 0.0, 26.0, 284.6034239491347, 254.21904414872373 - 0.4, 0.0, 26.0, 276.394527280783, 243.432894281129 - 0.45, 0.0, 26.0, 267.4611950740913, 231.68997932342936 - 0.5, 0.0, 26.0, 257.91879768159185, 219.1045533795568 - 0.55, 0.0, 26.0, 247.88270545581688, 205.7908705534433 - 0.6000000000000001, 0.0, 26.0, 237.46828874929847, 191.86318494902068 - 0.0, 0.0, 28.0, 380.71132797414174, 322.8970983543237 - 0.05, 0.0, 28.0, 379.9186096488317, 322.01965114868847 - 0.1, 0.0, 28.0, 377.64643933043425, 319.2486174136746 -0.15000000000000002, 0.0, 28.0, 373.9338063807854, 314.6889819633879 - 0.2, 0.0, 28.0, 368.8197001617208, 308.4457296119337 - 0.25, 0.0, 28.0, 362.3110671681346, 300.6008979367994 -0.30000000000000004, 0.0, 28.0, 354.5430253626924, 291.32831346195445 -0.35000000000000003, 0.0, 28.0, 345.6019017737347, 280.7839598889099 - 0.4, 0.0, 28.0, 335.64101569913254, 269.10340326256636 - 0.45, 0.0, 28.0, 324.79693836937355, 256.42731404197605 - 0.5, 0.0, 28.0, 313.20624101494565, 242.8963626861914 - 0.55, 0.0, 28.0, 301.0054948663367, 228.65121965426457 - 0.6000000000000001, 0.0, 28.0, 288.3312711540347, 213.83255540524783 - 0.0, 0.0, 30.0, 447.9999999999994, 352.29999999999995 - 0.05, 0.0, 30.0, 447.07499999999993, 351.38750000000016 - 0.1, 0.0, 30.0, 444.4000000000002, 348.3999999999991 -0.15000000000000002, 0.0, 30.0, 440.0250000000003, 343.462499999997 - 0.2, 0.0, 30.0, 434.00000000000045, 336.6999999999938 - 0.25, 0.0, 30.0, 426.3374999999992, 328.2124999999999 -0.30000000000000004, 0.0, 30.0, 417.2000000000005, 318.1999999999976 -0.35000000000000003, 0.0, 30.0, 406.7000000000011, 306.843749999996 - 0.4, 0.0, 30.0, 395.0000000000021, 294.2999999999942 - 0.45, 0.0, 30.0, 382.25000000000415, 280.7312499999927 - 0.5, 0.0, 30.0, 368.6000000000072, 266.2999999999914 - 0.55, 0.0, 30.0, 354.20000000001204, 251.16874999999047 - 0.6000000000000001, 0.0, 30.0, 339.200000000019, 235.49999999999037 - 0.0, 0.0, 32.0, 515.2886720258577, 381.67286088251075 - 0.05, 0.0, 32.0, 514.2969889095979, 380.6081917031196 - 0.1, 0.0, 32.0, 511.20880156087435, 377.410860040541 -0.15000000000000002, 0.0, 32.0, 506.1196461749198, 372.1743632540723 - 0.2, 0.0, 32.0, 499.12505894696716, 364.99219870301124 - 0.25, 0.0, 32.0, 490.30218458498234, 355.90584758165846 -0.30000000000000004, 0.0, 32.0, 479.8017337459986, 345.1648557443028 -0.35000000000000003, 0.0, 32.0, 467.73967528825636, 332.97481673093483 - 0.4, 0.0, 32.0, 454.29737931615955, 319.50906867877245 - 0.45, 0.0, 32.0, 439.6398656225713, 304.94901357572604 - 0.5, 0.0, 32.0, 423.9321540003543, 289.47605340970676 - 0.55, 0.0, 32.0, 407.33926424237154, 273.2715901686252 - 0.6000000000000001, 0.0, 32.0, 390.0262161414862, 256.5170258403923 - 0.0, 0.0, 34.0, 582.4463994858675, 410.7854182756185 - 0.05, 0.0, 34.0, 581.3736703078126, 409.6149153061913 - 0.1, 0.0, 34.0, 577.8753880008202, 406.2072289984825 -0.15000000000000002, 0.0, 34.0, 572.0849085983792, 400.64578088779973 - 0.2, 0.0, 34.0, 564.1355881339807, 393.0139925094505 - 0.25, 0.0, 34.0, 554.1551527874216, 383.32537127586374 -0.30000000000000004, 0.0, 34.0, 542.293848153251, 371.873081090972 -0.35000000000000003, 0.0, 34.0, 528.6805332115401, 358.9035862556719 - 0.4, 0.0, 34.0, 513.5070939854921, 344.57049299144296 - 0.45, 0.0, 34.0, 496.9496597375274, 329.0506220396207 - 0.5, 0.0, 34.0, 479.18435973006837, 312.52079414154025 - 0.55, 0.0, 34.0, 460.38732322553614, 295.15783003853716 - 0.6000000000000001, 0.0, 34.0, 440.73467948635243, 277.13855047194653 - 0.0, 0.0, 36.0, 649.488430709646, 439.67986328687346 - 0.05, 0.0, 36.0, 648.2780538963945, 438.4952269529693 - 0.1, 0.0, 36.0, 644.3793422599991, 434.87128048266237 -0.15000000000000002, 0.0, 36.0, 637.9335427306597, 428.9246023406449 - 0.2, 0.0, 36.0, 629.0819022385771, 420.7717709916086 - 0.25, 0.0, 36.0, 617.9523563228726, 410.4639971263444 -0.30000000000000004, 0.0, 36.0, 604.726086086946, 398.31396253123074 -0.35000000000000003, 0.0, 36.0, 589.560319372145, 384.614134209393 - 0.4, 0.0, 36.0, 572.6548515036563, 369.47636720130316 - 0.45, 0.0, 36.0, 554.1988359357103, 353.0576695380992 - 0.5, 0.0, 36.0, 534.381426122538, 335.5150492509188 - 0.55, 0.0, 36.0, 513.3917755183699, 317.0055143709001 - 0.6000000000000001, 0.0, 36.0, 491.4190375774369, 297.68607292918057 - 0.0, 0.0, 38.0, 716.8807942074749, 468.88927219679954 - 0.05, 0.0, 38.0, 715.4661656348787, 467.60799095946135 - 0.1, 0.0, 38.0, 711.1753350700383, 463.7448896591786 -0.15000000000000002, 0.0, 38.0, 704.1228053437417, 457.426053046706 - 0.2, 0.0, 38.0, 694.4230792867777, 448.77756587279873 - 0.25, 0.0, 38.0, 682.1553528750366, 437.86935410480663 -0.30000000000000004, 0.0, 38.0, 667.5400495039844, 424.99597884374793 -0.35000000000000003, 0.0, 38.0, 650.7337219815935, 410.40761270131986 - 0.4, 0.0, 38.0, 632.0071780461461, 394.3073471129951 - 0.45, 0.0, 38.0, 611.6026617033502, 376.9100438082958 - 0.5, 0.0, 38.0, 589.7624169589133, 358.43056451674414 - 0.55, 0.0, 38.0, 566.7286878185436, 339.0837709678625 - 0.6000000000000001, 0.0, 38.0, 542.7437182879488, 319.0845248911728 - 0.0, 0.0, 40.0, 783.9999999999998, 497.70000000000056 - 0.05, 0.0, 40.0, 782.5000000000005, 496.3437500000003 - 0.1, 0.0, 40.0, 777.8000000000002, 492.29999999999995 -0.15000000000000002, 0.0, 40.0, 770.0499999999998, 485.6812499999994 - 0.2, 0.0, 40.0, 759.3999999999984, 476.5999999999994 - 0.25, 0.0, 40.0, 745.9750000000032, 465.0937500000021 -0.30000000000000004, 0.0, 40.0, 729.999999999999, 451.4999999999963 -0.35000000000000003, 0.0, 40.0, 711.6499999999944, 436.09999999999184 - 0.4, 0.0, 40.0, 691.1999999999863, 419.0999999999855 - 0.45, 0.0, 40.0, 668.8999999999733, 400.7249999999774 - 0.5, 0.0, 40.0, 644.9999999999544, 381.1999999999671 - 0.55, 0.0, 40.0, 619.7499999999297, 360.7499999999548 - 0.6000000000000001, 0.0, 40.0, 593.3999999998975, 339.59999999994005 - 0.0, 0.0, 42.0, 851.1272051793511, 526.5918291583557 - 0.05, 0.0, 42.0, 849.4391538723271, 525.1331360293098 - 0.1, 0.0, 42.0, 844.3461466776646, 520.8505106751662 -0.15000000000000002, 0.0, 42.0, 835.9796483083996, 513.8676531932886 - 0.2, 0.0, 42.0, 824.4711234775679, 504.30826368104005 - 0.25, 0.0, 42.0, 809.9050719466364, 492.23287487951933 -0.30000000000000004, 0.0, 42.0, 792.553853283339, 477.95468895488074 -0.35000000000000003, 0.0, 42.0, 772.6142351311705, 461.7217850459937 - 0.4, 0.0, 42.0, 750.397493024372, 443.7900649758768 - 0.45, 0.0, 42.0, 726.1862755244988, 424.41347489651105 - 0.5, 0.0, 42.0, 700.2632311931053, 403.8459609598779 - 0.55, 0.0, 42.0, 672.9110085917468, 382.34146931795834 - 0.6000000000000001, 0.0, 42.0, 644.4122562819791, 360.15394612273417 - 0.0, 0.0, 44.0, 918.4887696440404, 555.5221263194699 - 0.05, 0.0, 44.0, 916.6882810978317, 553.9788952747008 - 0.1, 0.0, 44.0, 911.1888518865055, 549.5025255963754 -0.15000000000000002, 0.0, 44.0, 902.1434891486128, 542.1969990027033 - 0.2, 0.0, 44.0, 889.7052000227047, 532.1662972118945 - 0.25, 0.0, 44.0, 873.9864346022429, 519.4073658135544 -0.30000000000000004, 0.0, 44.0, 855.2618711610495, 504.3452949117091 -0.35000000000000003, 0.0, 44.0, 833.7227727411915, 487.34516787186084 - 0.4, 0.0, 44.0, 809.7318351314167, 468.58395049917436 - 0.45, 0.0, 44.0, 783.6088959338025, 448.28563798889866 - 0.5, 0.0, 44.0, 755.6737927504271, 426.6742255362824 - 0.55, 0.0, 44.0, 726.2463631833677, 403.9737083365744 - 0.6000000000000001, 0.0, 44.0, 695.6464448347017, 380.4080815850236 - 0.0, 0.0, 46.0, 985.5112303559608, 584.4465697283215 - 0.05, 0.0, 46.0, 983.5646724343355, 582.8342995402508 - 0.1, 0.0, 46.0, 977.666266877422, 578.1277615913351 -0.15000000000000002, 0.0, 46.0, 967.9724557741258, 570.457423390821 - 0.2, 0.0, 46.0, 954.639681213351, 559.9537524479524 - 0.25, 0.0, 46.0, 937.7735163890865, 546.6612083665597 -0.30000000000000004, 0.0, 46.0, 917.6830100750233, 530.9682823721554 -0.35000000000000003, 0.0, 46.0, 894.5925822426052, 513.2022453812107 - 0.4, 0.0, 46.0, 868.8616924925927, 493.591217924612 - 0.45, 0.0, 46.0, 840.8160405184137, 472.3881081296407 - 0.5, 0.0, 46.0, 810.7813260134958, 449.84582412357827 - 0.55, 0.0, 46.0, 779.0832486712653, 426.2172740337063 - 0.6000000000000001, 0.0, 46.0, 746.0475081851504, 401.7553659873061 - 0.0, 0.0, 48.0, 1052.872794820649, 614.241318444193 - 0.05, 0.0, 48.0, 1050.8708449813194, 612.542003210286 - 0.1, 0.0, 48.0, 1044.557010251727, 607.5946146131755 -0.15000000000000002, 0.0, 48.0, 1034.1392989997025, 599.5417014091418 - 0.2, 0.0, 48.0, 1019.825719593077, 588.5258123544663 - 0.25, 0.0, 48.0, 1001.7920264591361, 574.5971273668869 -0.30000000000000004, 0.0, 48.0, 980.3429897872818, 558.1753017182828 -0.35000000000000003, 0.0, 48.0, 955.7260677992863, 539.631371837081 - 0.4, 0.0, 48.0, 928.2889508251654, 519.1613741712276 - 0.45, 0.0, 48.0, 898.3542711678815, 497.00509516379253 - 0.5, 0.0, 48.0, 866.2446611303952, 473.40232125784524 - 0.55, 0.0, 48.0, 832.2827530156684, 448.5928388964555 - 0.6000000000000001, 0.0, 48.0, 796.7911791266629, 422.81643452269327 - 0.0, 0.0, 50.0, 1120.0000000000007, 643.9999999999998 - 0.05, 0.0, 50.0, 1117.8062500000026, 642.2812500000045 - 0.1, 0.0, 50.0, 1111.1000000000088, 637.2000000000123 -0.15000000000000002, 0.0, 50.0, 1100.0687500000217, 628.868750000023 - 0.2, 0.0, 50.0, 1084.900000000042, 617.4000000000376 - 0.25, 0.0, 50.0, 1065.7312500000105, 602.7624999999906 -0.30000000000000004, 0.0, 50.0, 1042.9000000000146, 585.5000000000023 -0.35000000000000003, 0.0, 50.0, 1016.6500000000314, 566.0937500000043 - 0.4, 0.0, 50.0, 987.4000000000532, 544.7000000000081 - 0.45, 0.0, 50.0, 955.5250000000808, 521.556250000014 - 0.5, 0.0, 50.0, 921.4000000001128, 496.9000000000223 - 0.55, 0.0, 50.0, 885.4000000001491, 470.9687500000334 - 0.6000000000000001, 0.0, 50.0, 847.90000000019, 444.00000000004803 - 0.0, 1500.0, 20.0, 95.69999999999999, 187.39999999999998 - 0.05, 1500.0, 20.0, 95.46735389610389, 186.78134740259745 - 0.1, 1500.0, 20.0, 94.89999999999996, 184.90000000000003 -0.15000000000000002, 1500.0, 20.0, 93.9889691558441, 181.8379788961039 - 0.2, 1500.0, 20.0, 92.7252922077921, 177.67730519480511 - 0.25, 1500.0, 20.0, 91.09999999999984, 172.49999999999983 -0.30000000000000004, 1500.0, 20.0, 89.07994227994244, 166.38744588744626 -0.35000000000000003, 1500.0, 20.0, 86.84309523809516, 159.4190476190475 - 0.4, 1500.0, 20.0, 84.39999999999985, 151.69999999999976 - 0.45, 1500.0, 20.0, 81.6979365079362, 143.35396825396796 - 0.5, 1500.0, 20.0, 78.69999999999953, 134.4999999999996 - 0.55, 1500.0, 20.0, 75.36928571428501, 125.25714285714238 - 0.6000000000000001, 1500.0, 20.0, 71.66888888888792, 115.74444444444387 - 0.0, 1500.0, 22.0, 153.2438416234512, 216.5618934644455 - 0.05, 1500.0, 22.0, 152.96466490873289, 215.96515839901164 - 0.1, 1500.0, 22.0, 152.0404352180063, 213.92209690968318 -0.15000000000000002, 1500.0, 22.0, 150.51087645340473, 210.5393886604932 - 0.2, 1500.0, 22.0, 148.4157125170614, 205.92371331547457 - 0.25, 1500.0, 22.0, 145.79466731110938, 200.18175053866054 -0.30000000000000004, 1500.0, 22.0, 142.6931254712557, 193.4295590063016 -0.35000000000000003, 1500.0, 22.0, 139.09868832660743, 185.6926396128084 - 0.4, 1500.0, 22.0, 135.0715898925971, 177.0961120378473 - 0.45, 1500.0, 22.0, 130.70916450838988, 167.81275046014844 - 0.5, 1500.0, 22.0, 126.09947143221805, 158.0034154336762 - 0.55, 1500.0, 22.0, 121.33056992231371, 147.828967512395 - 0.6000000000000001, 1500.0, 22.0, 116.49051923690911, 137.45026725026906 - 0.0, 1500.0, 24.0, 210.60192081172568, 244.56972189419133 - 0.05, 1500.0, 24.0, 210.2121588920601, 243.9015375306978 - 0.1, 1500.0, 24.0, 208.94623563602548, 241.67584164383305 -0.15000000000000002, 1500.0, 24.0, 206.8527346242065, 237.992230792426 - 0.2, 1500.0, 24.0, 203.98023943718792, 232.95030153530564 - 0.25, 1500.0, 24.0, 200.37733365555442, 226.64965043130076 -0.30000000000000004, 1500.0, 24.0, 196.09494595042113, 219.18423918109764 -0.35000000000000003, 1500.0, 24.0, 191.15250584988783, 210.6872381427101 - 0.4, 1500.0, 24.0, 185.6297769192752, 201.29275907280189 - 0.45, 1500.0, 24.0, 179.64205523431372, 191.14681104341287 - 0.5, 1500.0, 24.0, 173.29575374313148, 180.39242879773892 - 0.55, 1500.0, 24.0, 166.6972853938567, 169.1726470789764 - 0.6000000000000001, 1500.0, 24.0, 159.95306313461748, 157.6305006303215 - 0.0, 1500.0, 26.0, 267.8980791882746, 271.6766035917145 - 0.05, 1500.0, 26.0, 267.36655743400786, 270.89846083950147 - 0.1, 1500.0, 26.0, 265.7618184450414, 268.4785379231415 -0.15000000000000002, 1500.0, 26.0, 263.12529904882524, 264.4996935291776 - 0.2, 1500.0, 26.0, 259.4984360728094, 259.0447863441533 - 0.25, 1500.0, 26.0, 254.92266634444417, 252.19667505461177 -0.30000000000000004, 1500.0, 26.0, 249.42576646452184, 244.01046019906377 -0.35000000000000003, 1500.0, 26.0, 243.14396730510208, 234.7739216281122 - 0.4, 1500.0, 26.0, 236.16216899965386, 224.6213500888324 - 0.45, 1500.0, 26.0, 228.55837164254936, 213.64022655533222 - 0.5, 1500.0, 26.0, 220.41230033793477, 201.92973444496204 - 0.55, 1500.0, 26.0, 211.80368018995608, 189.58905717507258 - 0.6000000000000001, 1500.0, 26.0, 202.81223630275946, 176.71737816301447 - 0.0, 1500.0, 28.0, 325.3042329207624, 298.1304743952346 - 0.05, 1500.0, 28.0, 324.6405583224275, 297.2779931248496 - 0.1, 1500.0, 28.0, 322.6792651056029, 294.66442698763916 -0.15000000000000002, 1500.0, 28.0, 319.47225758443136, 290.3772231235876 - 0.2, 1500.0, 28.0, 315.07144007305607, 284.50382867267905 - 0.25, 1500.0, 28.0, 309.52871688561976, 277.1316907748978 -0.30000000000000004, 1500.0, 28.0, 302.8831798877539, 268.3163228988775 -0.35000000000000003, 1500.0, 28.0, 295.27450392441716, 258.38889714217936 - 0.4, 1500.0, 28.0, 286.79878048156985, 247.47209388435974 - 0.45, 1500.0, 28.0, 277.5486703695332, 235.61346636901987 - 0.5, 1500.0, 28.0, 267.6176920675382, 222.87934962375036 - 0.55, 1500.0, 28.0, 257.09936405481557, 209.33607867614177 - 0.6000000000000001, 1500.0, 28.0, 246.0872048105959, 195.04998855378452 - 0.0, 1500.0, 30.0, 382.79999999999995, 324.20000000000005 - 0.05, 1500.0, 30.0, 382.0229545454542, 323.30584415584457 - 0.1, 1500.0, 30.0, 379.69999999999925, 320.50000000000097 -0.15000000000000002, 1500.0, 30.0, 375.9055681818176, 315.89123376623564 - 0.2, 1500.0, 30.0, 370.7140909090905, 309.58831168831523 - 0.25, 1500.0, 30.0, 364.20000000000044, 301.7000000000057 -0.30000000000000004, 1500.0, 30.0, 356.43585858585584, 292.3134199134164 -0.35000000000000003, 1500.0, 30.0, 347.49749999999807, 281.7078571428554 - 0.4, 1500.0, 30.0, 337.49999999999545, 269.9999999999961 - 0.45, 1500.0, 30.0, 326.588333333325, 257.241428571421 - 0.5, 1500.0, 30.0, 314.8999999999869, 243.49999999998724 - 0.55, 1500.0, 30.0, 302.5724999999812, 228.8435714285516 - 0.6000000000000001, 1500.0, 30.0, 289.7433333333077, 213.339999999971 - 0.0, 1500.0, 32.0, 440.2957670792371, 350.24381298569006 - 0.05, 1500.0, 32.0, 439.4291017813626, 349.3096863568782 - 0.1, 1500.0, 32.0, 436.77597578570686, 346.30986039328604 -0.15000000000000002, 1500.0, 32.0, 432.41989454097376, 341.3714520170025 - 0.2, 1500.0, 32.0, 426.44436349586783, 334.62157815011636 - 0.25, 1500.0, 32.0, 418.9328880990927, 326.18735571471666 -0.30000000000000004, 1500.0, 32.0, 409.9618555581633, 316.1830425377271 -0.35000000000000003, 1500.0, 32.0, 399.6536105968732, 304.8296748100429 - 0.4, 1500.0, 32.0, 388.14597862711656, 292.28122993131745 - 0.45, 1500.0, 32.0, 375.6013420019245, 278.6726976307221 - 0.5, 1500.0, 32.0, 362.1759438390445, 264.1438145550484 - 0.55, 1500.0, 32.0, 348.02602725622404, 248.83431735108738 - 0.6000000000000001, 1500.0, 32.0, 333.3078353712103, 232.88394266563049 - 0.0, 1500.0, 34.0, 497.68482149635736, 376.17210263078516 - 0.05, 1500.0, 34.0, 496.7117738806082, 375.17482742385357 - 0.1, 1500.0, 34.0, 493.7183270609965, 371.9709072725672 -0.15000000000000002, 1500.0, 34.0, 488.79607555680525, 366.701447094531 - 0.2, 1500.0, 34.0, 482.0366138873173, 359.5075518073497 - 0.25, 1500.0, 34.0, 473.5315365718155, 350.53032632862823 -0.30000000000000004, 1500.0, 34.0, 463.3584257512548, 339.9073449542679 -0.35000000000000003, 1500.0, 34.0, 451.69979380403777, 327.78768960915704 - 0.4, 1500.0, 34.0, 438.7107787517037, 314.37326911004646 - 0.45, 1500.0, 34.0, 424.5562938011786, 299.90827144497115 - 0.5, 1500.0, 34.0, 409.3988083630447, 284.62631480914513 - 0.55, 1500.0, 34.0, 393.40079184788453, 268.761017397782 - 0.6000000000000001, 1500.0, 34.0, 376.72471366628054, 252.54599740609578 - 0.0, 1500.0, 36.0, 554.9724302152221, 401.9803823367566 - 0.05, 1500.0, 36.0, 553.8714049721384, 400.8875966725919 - 0.1, 1500.0, 36.0, 550.5199555825, 397.47537104692776 -0.15000000000000002, 1500.0, 36.0, 545.0213836324202, 391.8886923777993 - 0.2, 1500.0, 36.0, 537.4789907080112, 384.27254758324057 - 0.25, 1500.0, 36.0, 527.9960783953869, 374.7719235812864 -0.30000000000000004, 1500.0, 36.0, 516.6594799051213, 363.53295855256994 -0.35000000000000003, 1500.0, 36.0, 503.6835470489076, 350.6613355838367 - 0.4, 1500.0, 36.0, 489.2336717483017, 336.3923227848512 - 0.45, 1500.0, 36.0, 473.4755427491625, 321.04527575546877 - 0.5, 1500.0, 36.0, 456.57477459128125, 304.91852822302167 - 0.55, 1500.0, 36.0, 438.6969818144485, 288.31041391484166 - 0.6000000000000001, 1500.0, 36.0, 420.0077789584553, 271.5192665582616 - 0.0, 1500.0, 38.0, 612.504225866503, 427.6691450896797 - 0.05, 1500.0, 38.0, 611.3397559654801, 426.4830430612535 - 0.1, 1500.0, 38.0, 607.6732685615771, 422.90806848984545 -0.15000000000000002, 1500.0, 38.0, 601.6235674495817, 417.0687761720428 - 0.2, 1500.0, 38.0, 593.309456424282, 409.0897209044322 - 0.25, 1500.0, 38.0, 582.8497392804663, 399.0954574836011 -0.30000000000000004, 1500.0, 38.0, 570.3501145283909, 387.19033657352054 -0.35000000000000003, 1500.0, 38.0, 556.011577289683, 373.63256610294553 - 0.4, 1500.0, 38.0, 540.0208842063372, 358.63064065503335 - 0.45, 1500.0, 38.0, 522.5815101697791, 342.4003208476877 - 0.5, 1500.0, 38.0, 503.8927505090825, 325.1555507901243 - 0.55, 1500.0, 38.0, 484.15390055332074, 307.1102745915592 - 0.6000000000000001, 1500.0, 38.0, 463.5642556315679, 288.4784363612077 - 0.0, 1500.0, 40.0, 669.9000000000007, 453.30000000000035 - 0.05, 1500.0, 40.0, 668.5426948051972, 452.0586688311697 - 0.1, 1500.0, 40.0, 664.5000000000034, 448.30000000000007 -0.15000000000000002, 1500.0, 40.0, 657.8859577922105, 442.15199675324465 - 0.2, 1500.0, 40.0, 648.8146103896111, 433.74266233765655 - 0.25, 1500.0, 40.0, 637.3999999999966, 423.1999999999889 -0.30000000000000004, 1500.0, 40.0, 623.7360028860138, 410.61601731600314 -0.35000000000000003, 1500.0, 40.0, 608.0689285714402, 396.38523809523775 - 0.4, 1500.0, 40.0, 590.6000000000222, 380.6999999999973 - 0.45, 1500.0, 40.0, 571.5407142857515, 363.68984126983406 - 0.5, 1500.0, 40.0, 551.1000000000569, 345.4999999999857 - 0.55, 1500.0, 40.0, 529.4867857143676, 326.27571428568984 - 0.6000000000000001, 1500.0, 40.0, 506.91000000011303, 306.16222222218414 - 0.0, 1500.0, 42.0, 727.2161559655029, 479.05691737332893 - 0.05, 1500.0, 42.0, 725.8148474233182, 477.7369845980461 - 0.1, 1500.0, 42.0, 721.4414113225844, 473.73389043469604 -0.15000000000000002, 1500.0, 42.0, 714.2407836242762, 467.2058137226046 - 0.2, 1500.0, 42.0, 704.3579002893679, 458.3109333010971 - 0.25, 1500.0, 42.0, 691.9376972788335, 447.20742800949927 -0.30000000000000004, 1500.0, 42.0, 677.1152284033615, 434.03193158096065 -0.35000000000000003, 1500.0, 42.0, 660.083085710312, 419.09781733764476 - 0.4, 1500.0, 42.0, 641.0804085089301, 402.6147632185942 - 0.45, 1500.0, 42.0, 620.3971319168153, 384.76640711976216 - 0.5, 1500.0, 42.0, 598.3104920994771, 365.74289694787547 - 0.55, 1500.0, 42.0, 575.0977252224255, 345.73438060966015 - 0.6000000000000001, 1500.0, 42.0, 551.0360674511705, 324.93100601184295 - 0.0, 1500.0, 44.0, 784.8022436078677, 504.79392268540096 - 0.05, 1500.0, 44.0, 783.2609067931114, 503.4480121826384 - 0.1, 1500.0, 44.0, 778.5360119915617, 499.28079433829834 -0.15000000000000002, 1500.0, 44.0, 770.7727021390465, 492.4549729105506 - 0.2, 1500.0, 44.0, 760.116120171392, 483.1332516575647 - 0.25, 1500.0, 44.0, 746.7114090244262, 471.47833433751026 -0.30000000000000004, 1500.0, 44.0, 730.6822136116793, 457.6284593525641 -0.35000000000000003, 1500.0, 44.0, 712.3140938330312, 441.9166612608471 - 0.4, 1500.0, 44.0, 691.846894267475, 424.58181996419773 - 0.45, 1500.0, 44.0, 669.53297865803, 405.8489763057251 - 0.5, 1500.0, 44.0, 645.6215809567065, 385.9466308932199 - 0.55, 1500.0, 44.0, 620.3619351155155, 365.10328433447324 - 0.6000000000000001, 1500.0, 44.0, 594.0032750864681, 343.54743723727574 - 0.0, 1500.0, 46.0, 841.9977563921332, 530.4060773145992 - 0.05, 1500.0, 46.0, 840.3651899471043, 528.9575822271147 - 0.1, 1500.0, 46.0, 835.3191067723676, 524.5807968016229 -0.15000000000000002, 1500.0, 46.0, 827.0128784020941, 517.4404649922614 - 0.2, 1500.0, 46.0, 815.5998763704561, 507.70133075316886 - 0.25, 1500.0, 46.0, 801.2334722116252, 495.52813803848346 -0.30000000000000004, 1500.0, 46.0, 784.0445072698627, 481.0575785626849 -0.35000000000000003, 1500.0, 46.0, 764.3310756078923, 464.6569202496698 - 0.4, 1500.0, 46.0, 742.353105732526, 446.5565888958911 - 0.45, 1500.0, 46.0, 718.3901428264527, 426.9518866921911 - 0.5, 1500.0, 46.0, 692.7168279033891, 406.046896730816 - 0.55, 1500.0, 46.0, 665.6078019770513, 384.0457021040122 - 0.6000000000000001, 1500.0, 46.0, 637.3377060611564, 361.1523859040256 - 0.0, 1500.0, 48.0, 899.583844034498, 556.1478180207478 - 0.05, 1500.0, 48.0, 897.8728720298483, 554.6579210496367 - 0.1, 1500.0, 48.0, 892.4664810008874, 550.0875580392459 -0.15000000000000002, 1500.0, 48.0, 883.552632610575, 542.6175009870261 - 0.2, 1500.0, 48.0, 871.3192885218712, 532.4285218904272 - 0.25, 1500.0, 48.0, 855.954410397735, 519.7013927468995 -0.30000000000000004, 1500.0, 48.0, 837.6368116980575, 504.5913173370263 -0.35000000000000003, 1500.0, 48.0, 816.5992359995436, 487.4607655709342 - 0.4, 1500.0, 48.0, 793.1148560969625, 468.55905291338354 - 0.45, 1500.0, 48.0, 767.5020940031645, 448.1111949658707 - 0.5, 1500.0, 48.0, 740.0680594264886, 426.34828229570564 - 0.55, 1500.0, 48.0, 711.1198620752743, 403.50140547019913 - 0.6000000000000001, 1500.0, 48.0, 680.9646116578604, 379.80165505666145 - 0.0, 1500.0, 50.0, 956.9000000000019, 581.7999999999995 - 0.05, 1500.0, 50.0, 955.028685064947, 580.2426298701308 - 0.1, 1500.0, 50.0, 949.3000000000266, 575.5000000000007 -0.15000000000000002, 1500.0, 50.0, 939.876972402643, 567.7460551948027 - 0.2, 1500.0, 50.0, 926.9226298701986, 557.15474025973 - 0.25, 1500.0, 50.0, 910.6000000000953, 543.8999999999779 -0.30000000000000004, 1500.0, 50.0, 891.0361471861409, 528.11659451662 -0.35000000000000003, 1500.0, 50.0, 868.6403571428258, 510.27261904761957 - 0.4, 1500.0, 50.0, 843.699999999931, 490.5999999999976 - 0.45, 1500.0, 50.0, 816.493095237967, 469.25158730157807 - 0.5, 1500.0, 50.0, 787.2999999997882, 446.3999999999796 - 0.55, 1500.0, 50.0, 756.4010714282468, 422.2178571428199 - 0.6000000000000001, 1500.0, 50.0, 724.0766666661958, 396.87777777771726 - 0.0, 3000.0, 20.0, 101.79999999999998, 192.69999999999996 - 0.05, 3000.0, 20.0, 101.53766233766234, 192.09219155844156 - 0.1, 3000.0, 20.0, 100.9, 190.2 -0.15000000000000002, 3000.0, 20.0, 99.89350649350644, 187.10171266233758 - 0.2, 3000.0, 20.0, 98.52467532467521, 182.8756168831167 - 0.25, 3000.0, 20.0, 96.79999999999983, 177.59999999999968 -0.30000000000000004, 3000.0, 20.0, 94.71796536796592, 171.3508658008664 -0.35000000000000003, 3000.0, 20.0, 92.34202380952372, 164.2060714285714 - 0.4, 3000.0, 20.0, 89.69999999999985, 156.29999999999995 - 0.45, 3000.0, 20.0, 86.81198412698387, 147.80928571428558 - 0.5, 3000.0, 20.0, 83.69999999999959, 138.8999999999998 - 0.55, 3000.0, 20.0, 80.38607142857084, 129.73821428571392 - 0.6000000000000001, 3000.0, 20.0, 76.8922222222214, 120.48999999999944 - 0.0, 3000.0, 22.0, 162.9285137622159, 223.31414648342877 - 0.05, 3000.0, 22.0, 162.6454730837386, 222.59163039649508 - 0.1, 3000.0, 22.0, 161.65379237230414, 220.49040722666155 -0.15000000000000002, 3000.0, 22.0, 160.0089979102913, 217.07809270386517 - 0.2, 3000.0, 22.0, 157.76661598007905, 212.42230255804304 - 0.25, 3000.0, 22.0, 154.9821728640463, 206.59065251913228 -0.30000000000000004, 3000.0, 22.0, 151.72762050937632, 199.63710922228216 -0.35000000000000003, 3000.0, 22.0, 147.92647318282798, 191.72280267100155 - 0.4, 3000.0, 22.0, 143.63607725834478, 182.96238404938512 - 0.45, 3000.0, 22.0, 138.9701491850412, 173.46681685149156 - 0.5, 3000.0, 22.0, 134.02831289323896, 163.347986493889 - 0.55, 3000.0, 22.0, 128.91019231326007, 152.7177783931454 - 0.6000000000000001, 3000.0, 22.0, 123.71541137542634, 141.68807796582885 - 0.0, 3000.0, 24.0, 223.92425688110797, 252.5758484036831 - 0.05, 3000.0, 24.0, 223.50328869558518, 251.78890001382382 - 0.1, 3000.0, 24.0, 222.14689618615245, 249.49397877529998 -0.15000000000000002, 3000.0, 24.0, 219.91267072457273, 245.75835703349102 - 0.2, 3000.0, 24.0, 216.8582036826093, 240.64930713377703 - 0.25, 3000.0, 24.0, 213.04108643202508, 234.23410142153762 -0.30000000000000004, 3000.0, 24.0, 208.52956081775062, 226.5568100064719 -0.35000000000000003, 3000.0, 24.0, 203.28861905199653, 217.85064608046102 - 0.4, 3000.0, 24.0, 197.39803862917333, 208.24191310559584 - 0.45, 3000.0, 24.0, 190.99281961880087, 197.83204586214396 - 0.5, 3000.0, 24.0, 184.19415644662254, 186.72869630082957 - 0.55, 3000.0, 24.0, 177.12324353838156, 175.0395163723769 - 0.6000000000000001, 3000.0, 24.0, 169.90127531982105, 162.8721580275104 - 0.0, 3000.0, 26.0, 284.8757431188921, 280.87047708222315 - 0.05, 3000.0, 26.0, 284.27655445387416, 280.03829112121684 - 0.1, 3000.0, 26.0, 282.5531038138488, 277.5523467106077 -0.15000000000000002, 3000.0, 26.0, 279.7475645512412, 273.4866699787174 - 0.2, 3000.0, 26.0, 275.902110018477, 267.91528705386696 - 0.25, 3000.0, 26.0, 271.05891356798116, 260.912224064378 -0.30000000000000004, 3000.0, 26.0, 265.252517711265, 252.52222746379041 -0.35000000000000003, 3000.0, 26.0, 258.5677307107037, 243.0290405353729 - 0.4, 3000.0, 26.0, 251.10196137082968, 232.58025013711563 - 0.45, 3000.0, 26.0, 242.9762805394057, 221.2912315264184 - 0.5, 3000.0, 26.0, 234.3058435533879, 209.28541286083018 - 0.55, 3000.0, 26.0, 225.20580574973212, 196.6862222978997 - 0.6000000000000001, 3000.0, 26.0, 215.7913224653946, 183.61708799517584 - 0.0, 3000.0, 28.0, 345.90024554029276, 308.6239599848667 - 0.05, 3000.0, 28.0, 345.1973491267419, 307.7191382382659 - 0.1, 3000.0, 28.0, 343.1192739271945, 305.02511874875546 -0.15000000000000002, 3000.0, 28.0, 339.71759499321337, 300.62572389546517 - 0.2, 3000.0, 28.0, 335.04388737636083, 294.6047760575245 - 0.25, 3000.0, 28.0, 329.14972612819946, 287.04609761406374 -0.30000000000000004, 3000.0, 28.0, 322.07286896159536, 278.0043577983992 -0.35000000000000003, 3000.0, 28.0, 313.9552469774767, 267.776746436243 - 0.4, 3000.0, 28.0, 304.9089832078583, 256.5066590664273 - 0.45, 3000.0, 28.0, 295.05396331622086, 244.2932679948188 - 0.5, 3000.0, 28.0, 284.5081323081797, 231.24680133552596 - 0.55, 3000.0, 28.0, 273.3894351893498, 217.47748720265747 - 0.6000000000000001, 3000.0, 28.0, 261.8158169653465, 203.09555371032198 - 0.0, 3000.0, 30.0, 406.9999999999997, 336.0999999999996 - 0.05, 3000.0, 30.0, 406.2312175324673, 335.11060064935043 - 0.1, 3000.0, 30.0, 403.8000000000001, 332.20000000000033 -0.15000000000000002, 3000.0, 30.0, 399.7831737012998, 327.4640990259751 - 0.2, 3000.0, 30.0, 394.25756493506793, 320.998798701301 - 0.25, 3000.0, 30.0, 387.3000000000057, 312.9000000000038 -0.30000000000000004, 3000.0, 30.0, 378.9764069263993, 303.2392496392509 -0.35000000000000003, 3000.0, 30.0, 369.4339285714241, 292.29523809523397 - 0.4, 3000.0, 30.0, 358.7999999999914, 280.19999999999254 - 0.45, 3000.0, 30.0, 347.21071428570036, 267.03650793649604 - 0.5, 3000.0, 30.0, 334.79999999997904, 252.89999999998224 - 0.55, 3000.0, 30.0, 321.7017857142567, 237.88571428568912 - 0.6000000000000001, 3000.0, 30.0, 308.0499999999615, 222.08888888885463 - 0.0, 3000.0, 32.0, 468.16135944441925, 363.5801119137578 - 0.05, 3000.0, 32.0, 467.2383983389552, 362.55093423923574 - 0.1, 3000.0, 32.0, 464.42548518149687, 359.4405581345822 -0.15000000000000002, 3000.0, 32.0, 459.8035804288493, 354.3625571042707 - 0.2, 3000.0, 32.0, 453.45364453781724, 347.43050465277423 - 0.25, 3000.0, 32.0, 445.4566379652055, 338.757974284566 -0.30000000000000004, 3000.0, 32.0, 435.87695349748367, 328.4419595355635 -0.35000000000000003, 3000.0, 32.0, 424.90548812007006, 316.71065893394257 - 0.4, 3000.0, 32.0, 412.6910167921354, 303.7316901582577 - 0.45, 3000.0, 32.0, 399.3873684626442, 289.6654435911088 - 0.5, 3000.0, 32.0, 385.1471085831127, 274.6741164390853 - 0.55, 3000.0, 32.0, 370.1228026050569, 258.91990590877634 - 0.6000000000000001, 3000.0, 32.0, 354.4670159799929, 242.56500920677146 - 0.0, 3000.0, 34.0, 529.1811441726364, 390.9530969054826 - 0.05, 3000.0, 34.0, 528.1092797373989, 389.8541046586254 - 0.1, 3000.0, 34.0, 524.9166261725863, 386.54155196164936 -0.15000000000000002, 3000.0, 34.0, 519.6918006494087, 381.1328310943569 - 0.2, 3000.0, 34.0, 512.5234203390754, 373.7453343365501 - 0.25, 3000.0, 34.0, 503.50010241279705, 364.49645396803123 -0.30000000000000004, 3000.0, 34.0, 492.6946145098953, 353.4850528068425 -0.35000000000000003, 3000.0, 34.0, 480.2926738318875, 340.9471220717348 - 0.4, 3000.0, 34.0, 466.4719862240049, 327.08896430759967 - 0.45, 3000.0, 34.0, 451.43661569108025, 312.13414853363764 - 0.5, 3000.0, 34.0, 435.3840366980484, 296.3019271504743 - 0.55, 3000.0, 34.0, 418.5117237098448, 279.8115525587351 - 0.6000000000000001, 3000.0, 34.0, 401.01715119140437, 262.8822771590456 - 0.0, 3000.0, 36.0, 590.0531817327238, 418.1979915662497 - 0.05, 3000.0, 36.0, 588.8713516422665, 416.99477809725045 - 0.1, 3000.0, 36.0, 585.3117258340349, 413.4774558979989 -0.15000000000000002, 3000.0, 36.0, 579.4820541233814, 407.753680738167 - 0.2, 3000.0, 36.0, 571.4900863256589, 399.9311083874262 - 0.25, 3000.0, 36.0, 561.4435722562196, 390.1173946154483 -0.30000000000000004, 3000.0, 36.0, 549.4442266085982, 378.38927818061455 -0.35000000000000003, 3000.0, 36.0, 535.614555451576, 365.0632151469426 - 0.4, 3000.0, 36.0, 520.1628827630818, 350.36246867145144 - 0.45, 3000.0, 36.0, 503.3668147041404, 334.51000732913667 - 0.5, 3000.0, 36.0, 485.48663689000944, 317.7288733405041 - 0.55, 3000.0, 36.0, 466.7826349359464, 300.24210892605987 - 0.6000000000000001, 3000.0, 36.0, 447.5150944572089, 282.27275630631 - 0.0, 3000.0, 38.0, 651.2926481144905, 445.3253505844458 - 0.05, 3000.0, 38.0, 650.0032056827623, 444.1424159107887 - 0.1, 3000.0, 38.0, 646.0720710130134, 440.4594195908498 -0.15000000000000002, 3000.0, 38.0, 639.6253756756145, 434.4131388054742 - 0.2, 3000.0, 38.0, 630.789251240935, 426.1403507355071 - 0.25, 3000.0, 38.0, 619.6898292793452, 415.77783256179356 -0.30000000000000004, 3000.0, 38.0, 606.4467733909419, 403.4399824636183 -0.35000000000000003, 3000.0, 38.0, 591.2113542625235, 389.4232648922947 - 0.4, 3000.0, 38.0, 574.1895174019484, 373.9224912543841 - 0.45, 3000.0, 38.0, 555.636594138016, 357.10946226295175 - 0.5, 3000.0, 38.0, 535.7955693442967, 339.1617313044422 - 0.55, 3000.0, 38.0, 514.9094278943622, 320.25685176530055 - 0.6000000000000001, 3000.0, 38.0, 493.2211546617837, 300.57237703197114 - 0.0, 3000.0, 40.0, 712.3000000000004, 472.5000000000003 - 0.05, 3000.0, 40.0, 710.9024188311713, 471.1391558441565 - 0.1, 3000.0, 40.0, 706.6000000000031, 467.20000000000147 -0.15000000000000002, 3000.0, 40.0, 699.5363717532485, 460.81126623376855 - 0.2, 3000.0, 40.0, 689.8551623376608, 452.10168831169193 - 0.25, 3000.0, 40.0, 677.6999999999922, 441.20000000000476 -0.30000000000000004, 3000.0, 40.0, 663.2104617604363, 428.2088023087926 -0.35000000000000003, 3000.0, 40.0, 646.5310714285761, 413.4354761904771 - 0.4, 3000.0, 40.0, 627.9000000000092, 397.10000000000247 - 0.45, 3000.0, 40.0, 607.6259523809681, 379.41634920635494 - 0.5, 3000.0, 40.0, 586.0000000000252, 360.6000000000109 - 0.55, 3000.0, 40.0, 563.313214285752, 340.8664285714471 - 0.6000000000000001, 3000.0, 40.0, 539.8566666667207, 320.4311111111397 - 0.0, 3000.0, 42.0, 773.2090993135843, 499.60891363479493 - 0.05, 3000.0, 42.0, 771.7530416351206, 498.28524598645373 - 0.1, 3000.0, 42.0, 767.1160631261091, 494.1556174658179 -0.15000000000000002, 3000.0, 42.0, 759.4597411270707, 487.38968906346554 - 0.2, 3000.0, 42.0, 748.945652978525, 478.15712176997494 - 0.25, 3000.0, 42.0, 735.7353760209924, 466.62757657592437 -0.30000000000000004, 3000.0, 42.0, 719.9815899889911, 452.954074481161 -0.35000000000000003, 3000.0, 42.0, 701.8917042352772, 437.41590704355235 - 0.4, 3000.0, 42.0, 681.7033426081716, 420.2532033295842 - 0.45, 3000.0, 42.0, 659.6920671649281, 401.7132640595716 - 0.5, 3000.0, 42.0, 636.123955410567, 382.0415970403727 - 0.55, 3000.0, 42.0, 611.2650848501079, 361.48371007884487 - 0.6000000000000001, 3000.0, 42.0, 585.381532988571, 340.2851109818454 - 0.0, 3000.0, 44.0, 834.4406852657435, 526.8766997206293 - 0.05, 3000.0, 44.0, 832.7780952699143, 525.4337371206481 - 0.1, 3000.0, 44.0, 827.7735788208684, 521.0955078576171 -0.15000000000000002, 3000.0, 44.0, 819.5606083142824, 514.016466339332 - 0.2, 3000.0, 44.0, 808.272656145833, 504.3510669735878 - 0.25, 3000.0, 44.0, 794.0431947111972, 492.2537641681799 -0.30000000000000004, 3000.0, 44.0, 776.9732395677332, 477.84365180531546 -0.35000000000000003, 3000.0, 44.0, 757.4113055302087, 461.5281623089908 - 0.4, 3000.0, 44.0, 735.6247018564743, 443.55146865232314 - 0.45, 3000.0, 44.0, 711.8915144431575, 424.1196252257649 - 0.5, 3000.0, 44.0, 686.4871350271924, 403.4482160654347 - 0.55, 3000.0, 44.0, 659.686955345513, 381.7528252074512 - 0.6000000000000001, 3000.0, 44.0, 631.7663671350534, 359.2490366879331 - 0.0, 3000.0, 46.0, 895.3657871102474, 553.9784190432997 - 0.05, 3000.0, 46.0, 893.6031391174436, 552.44469240861 - 0.1, 3000.0, 46.0, 888.2264211791327, 547.898019766395 -0.15000000000000002, 3000.0, 46.0, 879.3907762926765, 540.4949921203769 - 0.2, 3000.0, 46.0, 867.2513474554372, 530.3922004742792 - 0.25, 3000.0, 46.0, 851.9632776647774, 517.7462358318252 -0.30000000000000004, 3000.0, 46.0, 833.6474518293328, 502.68099829961346 -0.35000000000000003, 3000.0, 46.0, 812.6982071644899, 485.5748566780531 - 0.4, 3000.0, 46.0, 789.3752981435488, 466.70365011160806 - 0.45, 3000.0, 46.0, 763.9172735892064, 446.34024643504796 - 0.5, 3000.0, 46.0, 736.5679837368073, 424.75825631056676 - 0.55, 3000.0, 46.0, 707.5712788216955, 402.23129040035843 - 0.6000000000000001, 3000.0, 46.0, 677.1710090792135, 379.03295936661743 - 0.0, 3000.0, 48.0, 956.5044568368961, 581.2942432945891 - 0.05, 3000.0, 48.0, 954.6190281390627, 579.6919657249306 - 0.1, 3000.0, 48.0, 948.8839368738882, 574.9260909896286 -0.15000000000000002, 3000.0, 48.0, 939.4594058262957, 567.1682259732897 - 0.2, 3000.0, 48.0, 926.5056577812085, 556.5899775605194 - 0.25, 3000.0, 48.0, 910.1829155235505, 543.3629526359244 -0.30000000000000004, 3000.0, 48.0, 890.6128626122843, 527.6292880963127 -0.35000000000000003, 3000.0, 48.0, 868.2202421855098, 509.76242979332505 - 0.4, 3000.0, 48.0, 843.2966573918071, 490.0357474175675 - 0.45, 3000.0, 48.0, 816.1220298386442, 468.7148331945392 - 0.5, 3000.0, 48.0, 786.9792015187647, 446.06722371601705 - 0.55, 3000.0, 48.0, 756.1510144249129, 422.36045557377804 - 0.6000000000000001, 3000.0, 48.0, 723.9203105498327, 397.86206535959866 - 0.0, 3000.0, 50.0, 1017.4999999999991, 608.3999999999992 - 0.05, 3000.0, 50.0, 1015.5141558441528, 606.8212012987059 - 0.1, 3000.0, 50.0, 1009.3999999999941, 601.9000000000086 -0.15000000000000002, 3000.0, 50.0, 999.3487662337574, 593.8281980519606 - 0.2, 3000.0, 50.0, 985.5516883116773, 582.7975974026133 - 0.25, 3000.0, 50.0, 968.1999999999881, 569.0000000000199 -0.30000000000000004, 3000.0, 50.0, 947.4643578643132, 552.5951659451465 -0.35000000000000003, 3000.0, 50.0, 923.6604761904573, 534.0046428571416 - 0.4, 3000.0, 50.0, 897.0999999999711, 513.4999999999936 - 0.45, 3000.0, 50.0, 868.1330158729744, 491.3169047618895 - 0.5, 3000.0, 50.0, 837.0999999999422, 467.69999999997066 - 0.55, 3000.0, 50.0, 804.3414285713503, 442.89392857137875 - 0.6000000000000001, 3000.0, 50.0, 770.197777777674, 417.1433333332556 - 0.0, 5000.0, 20.0, 110.39999999999998, 200.49999999999994 - 0.05, 5000.0, 20.0, 110.2375, 199.84374999999997 - 0.1, 5000.0, 20.0, 109.60000000000004, 197.9 -0.15000000000000002, 5000.0, 20.0, 108.51250000000006, 194.73125 - 0.2, 5000.0, 20.0, 107.00000000000013, 190.39999999999995 - 0.25, 5000.0, 20.0, 105.07499999999999, 184.94375 -0.30000000000000004, 5000.0, 20.0, 102.80000000000001, 178.49999999999997 -0.35000000000000003, 5000.0, 20.0, 100.24375000000002, 171.18125 - 0.4, 5000.0, 20.0, 97.40000000000002, 163.10000000000002 - 0.45, 5000.0, 20.0, 94.28125000000003, 154.3687500000001 - 0.5, 5000.0, 20.0, 90.90000000000002, 145.10000000000014 - 0.55, 5000.0, 20.0, 87.26874999999998, 135.40625000000023 - 0.6000000000000001, 5000.0, 20.0, 83.3999999999999, 125.40000000000035 - 0.0, 5000.0, 22.0, 176.8660859503895, 232.74527154235903 - 0.05, 5000.0, 22.0, 176.49975132902094, 232.06530940691673 - 0.1, 5000.0, 22.0, 175.4186074368549, 229.92225335516997 -0.15000000000000002, 5000.0, 22.0, 173.65989023081698, 226.40089712622049 - 0.2, 5000.0, 22.0, 171.26083566783322, 221.58603445917 - 0.25, 5000.0, 22.0, 168.2660265986593, 215.55512318475266 -0.30000000000000004, 5000.0, 22.0, 164.6906582987302, 208.41496476717143 -0.35000000000000003, 5000.0, 22.0, 160.52977466717252, 200.24609449486434 - 0.4, 5000.0, 22.0, 155.88841268366235, 191.20476872584902 - 0.45, 5000.0, 22.0, 150.84411105773842, 181.42831355074856 - 0.5, 5000.0, 22.0, 145.4744084989396, 171.0540550601859 - 0.55, 5000.0, 22.0, 139.85684371680466, 160.21931934478414 - 0.6000000000000001, 5000.0, 22.0, 134.06895542087236, 149.06143249516626 - 0.0, 5000.0, 24.0, 243.05304297519478, 263.7833568520805 - 0.05, 5000.0, 24.0, 242.56963242464428, 263.0398915580044 - 0.1, 5000.0, 24.0, 241.089303718428, 260.6878657855094 -0.15000000000000002, 5000.0, 24.0, 238.6686838485203, 256.81368091090184 - 0.2, 5000.0, 24.0, 235.36439980689522, 251.50373831048836 - 0.25, 5000.0, 24.0, 231.24588942601835, 244.82602591314344 -0.30000000000000004, 5000.0, 24.0, 226.33134717638768, 236.92218543746407 -0.35000000000000003, 5000.0, 24.0, 220.61401346027517, 227.89959713408754 - 0.4, 5000.0, 24.0, 214.2381883148086, 217.9290333357344 - 0.45, 5000.0, 24.0, 207.31040686840225, 207.16541835460538 - 0.5, 5000.0, 24.0, 199.9372042494701, 195.76367650290095 - 0.55, 5000.0, 24.0, 192.2251155864263, 183.87873209282165 - 0.6000000000000001, 5000.0, 24.0, 184.28067600768497, 171.66550943656804 - 0.0, 5000.0, 26.0, 309.1469570248053, 293.93880639062246 - 0.05, 5000.0, 26.0, 308.57088785575723, 293.1080690056341 - 0.1, 5000.0, 26.0, 306.71069628157403, 290.54235153826437 -0.15000000000000002, 5000.0, 26.0, 303.6387823508156, 286.3197661324741 - 0.2, 5000.0, 26.0, 299.4275461120415, 280.51842493222347 - 0.25, 5000.0, 26.0, 294.15461395404753, 273.17436704915787 -0.30000000000000004, 5000.0, 26.0, 287.8767069046798, 264.4919237241708 -0.35000000000000003, 5000.0, 26.0, 280.6302399197912, 254.63317752587793 - 0.4, 5000.0, 26.0, 272.55375760412335, 243.7609135826943 - 0.45, 5000.0, 26.0, 263.76027215019633, 232.03774138308637 - 0.5, 5000.0, 26.0, 254.36279575053013, 219.62627041552065 - 0.55, 5000.0, 26.0, 244.4743405976449, 206.68911016846363 - 0.6000000000000001, 5000.0, 26.0, 234.20791888406063, 193.38887013038186 - 0.0, 5000.0, 28.0, 375.4117526392866, 323.53910092277596 - 0.05, 5000.0, 28.0, 374.67039959560486, 322.61466691657773 - 0.1, 5000.0, 28.0, 372.41407016706233, 319.83949678003273 -0.15000000000000002, 5000.0, 28.0, 368.7074654514902, 315.2856945564261 - 0.2, 5000.0, 28.0, 363.6152865467198, 309.02536428904295 - 0.25, 5000.0, 28.0, 357.1832572255554, 301.0722785233895 -0.30000000000000004, 5000.0, 28.0, 349.53301056092124, 291.6735357960966 -0.35000000000000003, 5000.0, 28.0, 340.7643329380461, 281.03658387237437 - 0.4, 5000.0, 28.0, 330.9884881928546, 269.29414761202895 - 0.45, 5000.0, 28.0, 320.3138707985959, 256.59763260121645 - 0.5, 5000.0, 28.0, 308.8488752285195, 243.09844442609275 - 0.55, 5000.0, 28.0, 296.7018959558748, 228.94798867281392 - 0.6000000000000001, 5000.0, 28.0, 283.9813274539109, 214.29767092753605 - 0.0, 5000.0, 30.0, 441.7999999999995, 352.8999999999999 - 0.05, 5000.0, 30.0, 440.8624999999994, 351.8874999999996 - 0.1, 5000.0, 30.0, 438.19999999999874, 348.89999999999833 -0.15000000000000002, 5000.0, 30.0, 433.86249999999694, 344.0124999999965 - 0.2, 5000.0, 30.0, 427.89999999999384, 337.29999999999416 - 0.25, 5000.0, 30.0, 420.31874999999883, 328.7749999999986 -0.30000000000000004, 5000.0, 30.0, 411.2999999999987, 318.6999999999971 -0.35000000000000003, 5000.0, 30.0, 400.9937499999985, 307.30624999999515 - 0.4, 5000.0, 30.0, 389.4999999999981, 294.6999999999926 - 0.45, 5000.0, 30.0, 376.9312499999972, 281.0187499999892 - 0.5, 5000.0, 30.0, 363.3999999999956, 266.39999999998486 - 0.55, 5000.0, 30.0, 349.01874999999274, 250.98124999997953 - 0.6000000000000001, 5000.0, 30.0, 333.89999999998867, 234.89999999997312 - 0.0, 5000.0, 32.0, 508.1330064694041, 382.46684226087865 - 0.05, 5000.0, 32.0, 507.0905897379821, 381.39163742453707 - 0.1, 5000.0, 32.0, 504.04117072424685, 378.16644640361994 -0.15000000000000002, 5000.0, 32.0, 499.05218735240896, 372.89067600075833 - 0.2, 5000.0, 32.0, 492.19107754668005, 365.6637330185837 - 0.25, 5000.0, 32.0, 483.48889557834934, 356.5352207802171 -0.30000000000000004, 5000.0, 32.0, 473.1222303303872, 345.7539565268227 -0.35000000000000003, 5000.0, 32.0, 461.2189189945701, 333.5405941829762 - 0.4, 5000.0, 32.0, 447.9562709158338, 320.0292270216681 - 0.45, 5000.0, 32.0, 433.499227400824, 305.3755884787846 - 0.5, 5000.0, 32.0, 418.0127297561873, 289.7354119902124 - 0.55, 5000.0, 32.0, 401.6617192885698, 273.26443099183734 - 0.6000000000000001, 5000.0, 32.0, 384.61113730461796, 256.1183789195464 - 0.0, 5000.0, 34.0, 574.3153870504522, 411.9386920364563 - 0.05, 5000.0, 34.0, 573.212721231648, 410.78390802238744 - 0.1, 5000.0, 34.0, 569.77575479679, 407.3333101030861 -0.15000000000000002, 5000.0, 34.0, 564.1105823347724, 401.6931234363885 - 0.2, 5000.0, 34.0, 556.323298434489, 393.9695731801305 - 0.25, 5000.0, 34.0, 546.5049211737129, 384.21805401248156 -0.30000000000000004, 5000.0, 34.0, 534.8067746746815, 372.69728253026904 -0.35000000000000003, 5000.0, 34.0, 521.3307312236767, 359.6242518167558 - 0.4, 5000.0, 34.0, 506.31616440630495, 345.17952709081464 - 0.45, 5000.0, 34.0, 489.9680724833437, 329.5527805374166 - 0.5, 5000.0, 34.0, 472.49145371557046, 312.9336843415325 - 0.55, 5000.0, 34.0, 454.0913063637625, 295.5119106881333 - 0.6000000000000001, 5000.0, 34.0, 434.9726286886978, 277.4771317621897 - 0.0, 5000.0, 36.0, 640.3945001782255, 441.21685746355894 - 0.05, 5000.0, 36.0, 639.2229705170112, 439.96080408826566 - 0.1, 5000.0, 36.0, 635.3863458585846, 436.30959335153557 -0.15000000000000002, 5000.0, 36.0, 629.0321737479167, 430.3513365291907 - 0.2, 5000.0, 36.0, 620.3080017299782, 422.17414489705345 - 0.25, 5000.0, 36.0, 609.3639738336773, 411.7941710404302 -0.30000000000000004, 5000.0, 36.0, 596.3398481521195, 399.51540230667297 -0.35000000000000003, 5000.0, 36.0, 581.3438031053238, 385.5746662916942 - 0.4, 5000.0, 36.0, 564.620721741363, 370.18959483514817 - 0.45, 5000.0, 36.0, 546.3813109513029, 353.5826187157551 - 0.5, 5000.0, 36.0, 526.8362776262086, 335.9761687122347 - 0.55, 5000.0, 36.0, 506.19632865714414, 317.59267560330704 - 0.6000000000000001, 5000.0, 36.0, 484.6721709351755, 298.65457016769227 - 0.0, 5000.0, 38.0, 706.9237339913813, 470.3878032657437 - 0.05, 5000.0, 38.0, 705.4972103043149, 469.09012036203876 - 0.1, 5000.0, 38.0, 701.2349689161515, 465.2322524755884 -0.15000000000000002, 5000.0, 38.0, 694.2552763862855, 458.92321681704766 - 0.2, 5000.0, 38.0, 684.676399274111, 450.2720305970718 - 0.25, 5000.0, 38.0, 672.585611269333, 439.32435796177816 -0.30000000000000004, 5000.0, 38.0, 658.1941575404257, 426.37927531547246 -0.35000000000000003, 5000.0, 38.0, 641.6608614083372, 411.68818240391994 - 0.4, 5000.0, 38.0, 623.2302621054156, 395.4397733489735 - 0.45, 5000.0, 38.0, 603.1254698861563, 377.8384186784595 - 0.5, 5000.0, 38.0, 581.5695950050549, 359.0884889202045 - 0.55, 5000.0, 38.0, 558.7857477166065, 339.3943546020351 - 0.6000000000000001, 5000.0, 38.0, 534.9970382753064, 318.9603862517775 - 0.0, 5000.0, 40.0, 773.1000000000006, 499.60000000000065 - 0.05, 5000.0, 40.0, 771.5499999999996, 498.1875000000005 - 0.1, 5000.0, 40.0, 766.8999999999972, 494.0999999999991 -0.15000000000000002, 5000.0, 40.0, 759.2749999999936, 487.43749999999693 - 0.2, 5000.0, 40.0, 748.7999999999895, 478.2999999999939 - 0.25, 5000.0, 40.0, 735.5562499999966, 466.69999999999925 -0.30000000000000004, 5000.0, 40.0, 719.7999999999985, 453.0000000000025 -0.35000000000000003, 5000.0, 40.0, 701.7374999999968, 437.51250000000465 - 0.4, 5000.0, 40.0, 681.599999999995, 420.4000000000071 - 0.45, 5000.0, 40.0, 659.6124999999942, 401.86250000000905 - 0.5, 5000.0, 40.0, 635.9999999999935, 382.10000000001054 - 0.55, 5000.0, 40.0, 610.9874999999937, 361.3125000000111 - 0.6000000000000001, 5000.0, 40.0, 584.7999999999954, 339.7000000000105 - 0.0, 5000.0, 42.0, 839.2682451053608, 528.9315691768529 - 0.05, 5000.0, 42.0, 837.621993944381, 527.449390668354 - 0.1, 5000.0, 42.0, 832.5887650683652, 523.1085422382207 -0.15000000000000002, 5000.0, 42.0, 824.3108286715395, 516.0374941780406 - 0.2, 5000.0, 42.0, 812.9304549481292, 506.36471677940284 - 0.25, 5000.0, 42.0, 798.5497910650553, 494.1431290366219 -0.30000000000000004, 5000.0, 42.0, 781.4314762984617, 479.727855133107 -0.35000000000000003, 5000.0, 42.0, 761.7725742490925, 463.43095983058254 - 0.4, 5000.0, 42.0, 739.871959110109, 445.43454038845044 - 0.45, 5000.0, 42.0, 716.0030524265688, 425.95318594169333 - 0.5, 5000.0, 42.0, 690.439275743529, 405.2014856252941 - 0.55, 5000.0, 42.0, 663.454050606046, 383.3940285742357 - 0.6000000000000001, 5000.0, 42.0, 635.3207985591773, 360.74540392350065 - 0.0, 5000.0, 44.0, 905.6675015062683, 558.2314895147067 - 0.05, 5000.0, 44.0, 903.9342749352323, 556.7435759909733 - 0.1, 5000.0, 44.0, 898.5124649848032, 552.2239587150234 -0.15000000000000002, 5000.0, 44.0, 889.5724995969141, 544.8109467338563 - 0.2, 5000.0, 44.0, 877.2848067134998, 534.6428490944706 - 0.25, 5000.0, 44.0, 861.7953218500221, 521.7766701670845 -0.30000000000000004, 5000.0, 44.0, 843.3479502278394, 506.59463302904356 -0.35000000000000003, 5000.0, 44.0, 822.1139429452683, 489.4303002966288 - 0.4, 5000.0, 44.0, 798.4571978868637, 470.4866577232953 - 0.45, 5000.0, 44.0, 772.6934512406215, 449.9993352782047 - 0.5, 5000.0, 44.0, 745.1384391945361, 428.2039629305181 - 0.55, 5000.0, 44.0, 716.1078979366031, 405.33617064939665 - 0.6000000000000001, 5000.0, 44.0, 685.9175636548173, 381.6315884040017 - 0.0, 5000.0, 46.0, 971.7260261177418, 587.487502217403 - 0.05, 5000.0, 46.0, 969.8374331295893, 585.8685790701288 - 0.1, 5000.0, 46.0, 964.032416251269, 581.101505393077 -0.15000000000000002, 5000.0, 46.0, 954.4714960983722, 573.3245902332451 - 0.2, 5000.0, 46.0, 941.3151932864887, 562.6761426376324 - 0.25, 5000.0, 46.0, 924.6742637842198, 549.2106404542878 -0.30000000000000004, 5000.0, 46.0, 904.8585221481485, 533.3178863270786 -0.35000000000000003, 5000.0, 46.0, 882.1021977662236, 515.3311377299667 - 0.4, 5000.0, 46.0, 856.7428021131337, 495.4745080207731 - 0.45, 5000.0, 46.0, 829.0920261418809, 473.9993965863531 - 0.5, 5000.0, 46.0, 799.4615608054663, 451.1572028135613 - 0.55, 5000.0, 46.0, 768.1630970568922, 427.1993260892527 - 0.6000000000000001, 5000.0, 46.0, 735.5083258491594, 402.3771658002824 - 0.0, 5000.0, 48.0, 1038.213463350083, 617.0684307451519 - 0.05, 5000.0, 48.0, 1036.125243737535, 615.3645426202315 - 0.1, 5000.0, 48.0, 1029.908078002252, 610.4050138342697 -0.15000000000000002, 5000.0, 48.0, 1019.7088092148518, 602.316538906077 - 0.2, 5000.0, 48.0, 1005.674280445948, 591.2258123544639 - 0.25, 5000.0, 48.0, 987.8758588960145, 577.1565110547441 -0.30000000000000004, 5000.0, 48.0, 966.6868152460911, 560.5443824561894 -0.35000000000000003, 5000.0, 48.0, 942.3936687825826, 541.7635212674652 - 0.4, 5000.0, 48.0, 915.3280408898758, 521.0225625856787 - 0.45, 5000.0, 48.0, 885.8102774278624, 498.5715064108294 - 0.5, 5000.0, 48.0, 854.160724256434, 474.660352742918 - 0.55, 5000.0, 48.0, 820.6997272354829, 449.53910158194395 - 0.6000000000000001, 5000.0, 48.0, 785.7476322249001, 423.4577529279072 - 0.0, 5000.0, 50.0, 1104.4000000000015, 646.9999999999985 - 0.05, 5000.0, 50.0, 1102.237500000005, 645.2562500000034 - 0.1, 5000.0, 50.0, 1095.6000000000079, 640.1000000000092 -0.15000000000000002, 5000.0, 50.0, 1084.6875000000073, 631.6687500000173 - 0.2, 5000.0, 50.0, 1069.7000000000025, 620.1000000000288 - 0.25, 5000.0, 50.0, 1050.799999999988, 605.4250000000095 -0.30000000000000004, 5000.0, 50.0, 1028.299999999993, 588.100000000003 -0.35000000000000003, 5000.0, 50.0, 1002.4249999999838, 568.5250000000096 - 0.4, 5000.0, 50.0, 973.5999999999713, 546.9000000000195 - 0.45, 5000.0, 50.0, 942.1999999999534, 523.4750000000327 - 0.5, 5000.0, 50.0, 908.5999999999301, 498.5000000000487 - 0.55, 5000.0, 50.0, 873.1749999999004, 472.2250000000672 - 0.6000000000000001, 5000.0, 50.0, 836.2999999998633, 444.90000000008797 - 0.0, 10000.0, 20.0, 135.59999999999997, 224.39999999999995 - 0.05, 10000.0, 20.0, 135.33125, 223.66875 - 0.1, 10000.0, 20.0, 134.5000000000001, 221.60000000000002 -0.15000000000000002, 10000.0, 20.0, 133.14375000000015, 218.23125000000002 - 0.2, 10000.0, 20.0, 131.3000000000003, 213.60000000000005 - 0.25, 10000.0, 20.0, 129.02500000000003, 207.69374999999985 -0.30000000000000004, 10000.0, 20.0, 126.30000000000004, 200.70000000000002 -0.35000000000000003, 10000.0, 20.0, 123.0812500000001, 192.77500000000006 - 0.4, 10000.0, 20.0, 119.50000000000014, 184.00000000000014 - 0.45, 10000.0, 20.0, 115.68124999999998, 174.4625 - 0.5, 10000.0, 20.0, 111.6, 164.3 - 0.55, 10000.0, 20.0, 107.26875000000003, 153.63750000000007 - 0.6000000000000001, 10000.0, 20.0, 102.70000000000005, 142.60000000000008 - 0.0, 10000.0, 22.0, 217.13547465141042, 261.12827942451077 - 0.05, 10000.0, 22.0, 216.65226979820125, 260.34294029709423 - 0.1, 10000.0, 22.0, 215.35095895813294, 258.0451318312362 -0.15000000000000002, 10000.0, 22.0, 213.24132025739533, 254.2819674986441 - 0.2, 10000.0, 22.0, 210.3331318221789, 249.1005607710253 - 0.25, 10000.0, 22.0, 206.6032081134341, 242.4996004057702 -0.30000000000000004, 10000.0, 22.0, 202.16021825306805, 234.67147401753633 -0.35000000000000003, 10000.0, 22.0, 197.08927462713044, 225.76901381287306 - 0.4, 10000.0, 22.0, 191.43786190413417, 215.9095747734917 - 0.45, 10000.0, 22.0, 185.24345666471316, 205.1981392751936 - 0.5, 10000.0, 22.0, 178.62119555855728, 193.82465734225792 - 0.55, 10000.0, 22.0, 171.6668002180942, 181.9578370868452 - 0.6000000000000001, 10000.0, 22.0, 164.47599227575105, 169.7663866211153 - 0.0, 10000.0, 24.0, 298.4077373257053, 296.73450025270614 - 0.05, 10000.0, 24.0, 297.7955098991011, 295.86746132244224 - 0.1, 10000.0, 24.0, 296.0054794790672, 293.31894448309095 -0.15000000000000002, 10000.0, 24.0, 293.07628512869843, 289.14024971037253 - 0.2, 10000.0, 24.0, 289.04656591109006, 283.38267698000755 - 0.25, 10000.0, 24.0, 283.93097905671675, 276.03630602373545 -0.30000000000000004, 10000.0, 24.0, 277.84010912653343, 267.3360975492184 -0.35000000000000003, 10000.0, 24.0, 270.858387313564, 257.4718527999307 - 0.4, 10000.0, 24.0, 263.07893095206504, 246.56912990017275 - 0.45, 10000.0, 24.0, 254.58110333235723, 234.75305855811436 - 0.5, 10000.0, 24.0, 245.49059777927917, 222.2147252656247 - 0.55, 10000.0, 24.0, 235.92152510904742, 209.12872731865198 - 0.6000000000000001, 10000.0, 24.0, 225.98799613787543, 195.66966201314276 - 0.0, 10000.0, 26.0, 379.592262674295, 331.7265813686462 - 0.05, 10000.0, 26.0, 378.8794901009004, 330.764887199243 - 0.1, 10000.0, 26.0, 376.5945205209351, 327.95019121932717 -0.15000000000000002, 10000.0, 26.0, 372.8237148713034, 323.34067317277834 - 0.2, 10000.0, 26.0, 367.6534340889106, 316.9945128034764 - 0.25, 10000.0, 26.0, 361.1752709432818, 308.8963364388153 -0.30000000000000004, 10000.0, 26.0, 353.4598908734643, 299.3249840721318 -0.35000000000000003, 10000.0, 26.0, 344.5478626864316, 288.5139348805509 - 0.4, 10000.0, 26.0, 334.6210690479276, 276.5838976401067 - 0.45, 10000.0, 26.0, 323.84389666764486, 263.67203320343805 - 0.5, 10000.0, 26.0, 312.30940222072275, 249.96246451786175 - 0.55, 10000.0, 26.0, 300.12847489095356, 235.62757400703498 - 0.6000000000000001, 10000.0, 26.0, 287.41200386212415, 220.8397440946109 - 0.0, 10000.0, 28.0, 460.9326435115505, 366.7424823272348 - 0.05, 10000.0, 28.0, 460.06663840167175, 365.6940482171602 - 0.1, 10000.0, 28.0, 457.29987849091935, 362.6029573559425 -0.15000000000000002, 10000.0, 28.0, 452.73014166406546, 357.5520842162164 - 0.2, 10000.0, 28.0, 446.455205805883, 350.6243032706161 - 0.25, 10000.0, 28.0, 438.5675039085393, 341.8430803900315 -0.30000000000000004, 10000.0, 28.0, 429.180848534636, 331.4695158523436 -0.35000000000000003, 10000.0, 28.0, 418.37880478765385, 319.7307494159347 - 0.4, 10000.0, 28.0, 406.3445480371842, 306.75212851024713 - 0.45, 10000.0, 28.0, 393.24000860103206, 292.6545146636078 - 0.5, 10000.0, 28.0, 379.2124867380253, 277.6785053377349 - 0.55, 10000.0, 28.0, 364.41294022173537, 262.0347640110011 - 0.6000000000000001, 10000.0, 28.0, 348.9923268257337, 245.933954161778 - 0.0, 10000.0, 30.0, 542.3999999999999, 401.8999999999999 - 0.05, 10000.0, 30.0, 541.3437499999989, 400.76874999999876 - 0.1, 10000.0, 30.0, 538.0999999999964, 397.3999999999963 -0.15000000000000002, 10000.0, 30.0, 532.7562499999925, 391.906249999993 - 0.2, 10000.0, 30.0, 525.3999999999874, 384.39999999998895 - 0.25, 10000.0, 30.0, 516.0812500000014, 374.95624999999984 -0.30000000000000004, 10000.0, 30.0, 504.9999999999992, 363.799999999997 -0.35000000000000003, 10000.0, 30.0, 492.3249999999981, 351.13749999999555 - 0.4, 10000.0, 30.0, 478.1999999999971, 337.0999999999943 - 0.45, 10000.0, 30.0, 462.7437499999946, 321.78124999999517 - 0.5, 10000.0, 30.0, 446.1999999999915, 305.4999999999922 - 0.55, 10000.0, 30.0, 428.781249999988, 288.5187499999884 - 0.6000000000000001, 10000.0, 30.0, 410.69999999998345, 271.099999999984 - 0.0, 10000.0, 32.0, 623.8673564884492, 437.1616353619812 - 0.05, 10000.0, 32.0, 622.6495320493204, 435.9301794466893 - 0.1, 10000.0, 32.0, 618.9064856024784, 432.2947962398703 -0.15000000000000002, 10000.0, 32.0, 612.7478327788577, 426.3691953115599 - 0.2, 10000.0, 32.0, 604.2831892093919, 418.2670862317937 - 0.25, 10000.0, 32.0, 593.5948688446334, 408.04237221301 -0.30000000000000004, 10000.0, 32.0, 580.8743923566734, 395.9881818980231 -0.35000000000000003, 10000.0, 32.0, 566.2680131656444, 382.3814874938531 - 0.4, 10000.0, 32.0, 549.9938469781023, 367.32466152032333 - 0.45, 10000.0, 32.0, 532.240856796559, 350.9130289154483 - 0.5, 10000.0, 32.0, 513.2427541532833, 333.44470463168744 - 0.55, 10000.0, 32.0, 493.22206344810786, 315.167106117898 - 0.6000000000000001, 10000.0, 32.0, 472.4013090808645, 296.32765082293344 - 0.0, 10000.0, 34.0, 705.1761765203894, 472.33811386339136 - 0.05, 10000.0, 34.0, 703.7878325970806, 471.02688061861676 - 0.1, 10000.0, 34.0, 699.5505460183465, 467.1388949404843 -0.15000000000000002, 10000.0, 34.0, 692.5895930516666, 460.7945016368411 - 0.2, 10000.0, 34.0, 683.0302499645214, 452.11404551553386 - 0.25, 10000.0, 34.0, 670.9758642939889, 441.15108677387605 -0.30000000000000004, 10000.0, 34.0, 656.6174984987471, 428.22632405130975 -0.35000000000000003, 10000.0, 34.0, 640.0836816369039, 413.6390566269018 - 0.4, 10000.0, 34.0, 621.6653614472524, 397.50704277910387 - 0.45, 10000.0, 34.0, 601.6232677058563, 379.9469444582552 - 0.5, 10000.0, 34.0, 580.1765833590431, 361.2613499277654 - 0.55, 10000.0, 34.0, 557.5548780605836, 341.70636587278085 - 0.6000000000000001, 10000.0, 34.0, 533.9877214642464, 321.5380989784461 - 0.0, 10000.0, 36.0, 786.3449214663212, 507.40835379720977 - 0.05, 10000.0, 36.0, 784.7741324040106, 506.04105758798715 - 0.1, 10000.0, 36.0, 780.0582550469284, 501.9143612414136 -0.15000000000000002, 10000.0, 36.0, 772.3211936560936, 495.16599828999114 - 0.2, 10000.0, 36.0, 761.6868524925258, 485.9337022662221 - 0.25, 10000.0, 36.0, 748.2413963308037, 474.3075062477438 -0.30000000000000004, 10000.0, 36.0, 732.2219478912507, 460.56824513164906 -0.35000000000000003, 10000.0, 36.0, 713.7908618129027, 444.9639300339278 - 0.4, 10000.0, 36.0, 693.2586071141652, 427.68306537556805 - 0.45, 10000.0, 36.0, 670.9062025593903, 408.8773149236623 - 0.5, 10000.0, 36.0, 646.984353549835, 388.9052117558984 - 0.55, 10000.0, 36.0, 621.7513438275604, 368.073571622327 - 0.6000000000000001, 10000.0, 36.0, 595.4654571346147, 346.689210272994 - 0.0, 10000.0, 38.0, 867.9378187011903, 542.760840860747 - 0.05, 10000.0, 38.0, 866.2252490501229, 541.2856624558318 - 0.1, 10000.0, 38.0, 861.0363092752301, 536.9211960837143 -0.15000000000000002, 10000.0, 38.0, 852.5037482200312, 529.7827338075305 - 0.2, 10000.0, 38.0, 840.7603147280462, 519.9855676904135 - 0.25, 10000.0, 38.0, 825.8825720666854, 507.5577049623406 -0.30000000000000004, 10000.0, 38.0, 808.1718258078564, 492.87629218596516 -0.35000000000000003, 10000.0, 38.0, 787.8647455127319, 476.2699710533671 - 0.4, 10000.0, 38.0, 765.231802481217, 457.91226340648876 - 0.45, 10000.0, 38.0, 740.5020516279681, 437.9815347823834 - 0.5, 10000.0, 38.0, 714.0364116698603, 416.79189578778414 - 0.55, 10000.0, 38.0, 686.1628353732483, 394.62352076201654 - 0.6000000000000001, 10000.0, 38.0, 657.2092755044714, 371.7565840444006 - 0.0, 10000.0, 40.0, 949.2000000000012, 578.0000000000005 - 0.05, 10000.0, 40.0, 947.393750000001, 576.4437500000001 - 0.1, 10000.0, 40.0, 941.6999999999977, 571.8000000000003 -0.15000000000000002, 10000.0, 40.0, 932.306249999991, 564.2062500000003 - 0.2, 10000.0, 40.0, 919.3999999999812, 553.8000000000008 - 0.25, 10000.0, 40.0, 903.1437500000003, 540.6374999999936 -0.30000000000000004, 10000.0, 40.0, 883.7999999999946, 525.0999999999999 -0.35000000000000003, 10000.0, 40.0, 861.5687499999889, 507.5249999999989 - 0.4, 10000.0, 40.0, 836.7999999999811, 488.0999999999974 - 0.45, 10000.0, 40.0, 809.793750000005, 467.01249999999885 - 0.5, 10000.0, 40.0, 780.9000000000079, 444.59999999999735 - 0.55, 10000.0, 40.0, 750.4562500000121, 421.1624999999962 - 0.6000000000000001, 10000.0, 40.0, 718.8000000000187, 396.9999999999953 - 0.0, 10000.0, 42.0, 1030.4718662707141, 613.6707519639976 - 0.05, 10000.0, 42.0, 1028.4495705373695, 611.9641073380755 - 0.1, 10000.0, 42.0, 1022.2709377597806, 607.024698086731 -0.15000000000000002, 10000.0, 42.0, 1012.1134516891038, 598.9854513238251 - 0.2, 10000.0, 42.0, 998.1545960764956, 587.9792941632184 - 0.25, 10000.0, 42.0, 980.5326601542996, 574.0336929462507 -0.30000000000000004, 10000.0, 42.0, 959.5427112300989, 557.5979571043495 -0.35000000000000003, 10000.0, 42.0, 935.3926706006805, 539.077530009985 - 0.4, 10000.0, 42.0, 908.4822655308183, 518.6314761814623 - 0.45, 10000.0, 42.0, 879.1621691987244, 496.4427169204421 - 0.5, 10000.0, 42.0, 847.7874651608543, 472.84512524934024 - 0.55, 10000.0, 42.0, 814.7121343790773, 448.13483626040255 - 0.6000000000000001, 10000.0, 42.0, 780.2901578152726, 422.60798504586734 - 0.0, 10000.0, 44.0, 1112.0274746761775, 650.078451841095 - 0.05, 10000.0, 44.0, 1109.8396287132352, 648.3044392065182 - 0.1, 10000.0, 44.0, 1103.187398401414, 643.1700462128388 -0.15000000000000002, 10000.0, 44.0, 1092.2457733984113, 634.7854550726312 - 0.2, 10000.0, 44.0, 1077.189743361927, 623.2608479984702 - 0.25, 10000.0, 44.0, 1058.1256088990217, 608.5797891089506 -0.30000000000000004, 10000.0, 44.0, 1035.4344268193452, 591.2323148986086 -0.35000000000000003, 10000.0, 44.0, 1009.4118478417497, 571.6264804102105 - 0.4, 10000.0, 44.0, 980.4203908458715, 549.9917941177898 - 0.45, 10000.0, 44.0, 948.7834336989706, 526.5898057641426 - 0.5, 10000.0, 44.0, 914.9140501570279, 501.73244658573776 - 0.55, 10000.0, 44.0, 879.2028900038675, 475.71905244562714 - 0.6000000000000001, 10000.0, 44.0, 842.0406030233034, 448.8489592068627 - 0.0, 10000.0, 46.0, 1193.172525323824, 686.6415978187591 - 0.05, 10000.0, 46.0, 1190.8202146644212, 684.728995994116 - 0.1, 10000.0, 46.0, 1183.6677203625075, 679.3013570590716 -0.15000000000000002, 10000.0, 46.0, 1171.9132816788226, 670.4771524585472 - 0.2, 10000.0, 46.0, 1155.7551378741064, 658.3748536374643 - 0.25, 10000.0, 46.0, 1135.336891100991, 642.9883365642697 -0.30000000000000004, 10000.0, 46.0, 1111.0206919445866, 624.809859113339 -0.35000000000000003, 10000.0, 46.0, 1083.0700420037438, 604.2716343586657 - 0.4, 10000.0, 46.0, 1051.9244903902015, 581.5476726700344 - 0.45, 10000.0, 46.0, 1017.9674622151184, 556.7869094877462 - 0.5, 10000.0, 46.0, 981.6308310790541, 530.4967826742275 - 0.55, 10000.0, 46.0, 943.3343584602096, 503.09510448637053 - 0.6000000000000001, 10000.0, 46.0, 903.4978058367905, 474.9996871810691 - 0.0, 10000.0, 48.0, 1274.7281337292843, 723.7443824951858 - 0.05, 10000.0, 48.0, 1272.2736188945821, 721.7392524946854 - 0.1, 10000.0, 48.0, 1264.632219169615, 716.0008355935481 -0.15000000000000002, 10000.0, 48.0, 1252.0423050406976, 706.6737696732877 - 0.2, 10000.0, 48.0, 1234.7422469941423, 693.9026926154198 - 0.25, 10000.0, 48.0, 1212.9325035048755, 677.7018395608699 -0.30000000000000004, 10000.0, 48.0, 1186.9651810933585, 658.6070566129199 -0.35000000000000003, 10000.0, 48.0, 1157.0978876746556, 637.1275359830613 - 0.4, 10000.0, 48.0, 1123.8145775397916, 613.357474487685 - 0.45, 10000.0, 48.0, 1087.528876515135, 587.3690053278294 - 0.5, 10000.0, 48.0, 1048.7093779097813, 559.7375115610462 - 0.55, 10000.0, 48.0, 1007.8109331621979, 530.9125637807656 - 0.6000000000000001, 10000.0, 48.0, 965.2883937108297, 501.34373258041546 - 0.0, 10000.0, 50.0, 1355.9999999999957, 761.0000000000003 - 0.05, 10000.0, 50.0, 1353.3187500000085, 758.9375000000003 - 0.1, 10000.0, 50.0, 1345.200000000021, 752.8999999999995 -0.15000000000000002, 10000.0, 50.0, 1331.85625000003, 743.0624999999977 - 0.2, 10000.0, 50.0, 1313.5000000000327, 729.5999999999939 - 0.25, 10000.0, 50.0, 1290.2624999999953, 712.5625000000014 -0.30000000000000004, 10000.0, 50.0, 1262.5999999999826, 692.4999999999974 -0.35000000000000003, 10000.0, 50.0, 1230.862499999974, 669.9249999999976 - 0.4, 10000.0, 50.0, 1195.4999999999668, 644.9999999999976 - 0.45, 10000.0, 50.0, 1156.9062500000261, 617.9187499999853 - 0.5, 10000.0, 50.0, 1115.6000000000454, 589.0999999999757 - 0.55, 10000.0, 50.0, 1072.0687500000713, 558.9062499999645 - 0.6000000000000001, 10000.0, 50.0, 1026.800000000102, 527.6999999999517 - 0.0, 15000.0, 20.0, 179.99999999999937, 262.40000000000026 - 0.05, 15000.0, 20.0, 166.6749999999996, 257.27500000000015 - 0.1, 15000.0, 20.0, 157.99999999999977, 252.40000000000003 -0.15000000000000002, 15000.0, 20.0, 152.9999999999999, 247.52499999999998 - 0.2, 15000.0, 20.0, 150.69999999999996, 242.39999999999998 - 0.25, 15000.0, 20.0, 150.125, 236.77499999999998 -0.30000000000000004, 15000.0, 20.0, 150.30000000000007, 230.40000000000003 -0.35000000000000003, 15000.0, 20.0, 150.2500000000001, 223.02500000000006 - 0.4, 15000.0, 20.0, 149.00000000000017, 214.40000000000015 - 0.45, 15000.0, 20.0, 144.61249999999993, 203.92499999999993 - 0.5, 15000.0, 20.0, 138.99999999999994, 192.39999999999995 - 0.55, 15000.0, 20.0, 133.1124999999999, 180.27499999999998 - 0.6000000000000001, 15000.0, 20.0, 127.89999999999986, 167.99999999999994 - 0.0, 15000.0, 22.0, 284.65574116971146, 305.37616738213507 - 0.05, 15000.0, 22.0, 264.76707507429256, 297.0847962263615 - 0.1, 15000.0, 22.0, 251.89528665240638, 290.1414794722727 -0.15000000000000002, 15000.0, 22.0, 244.5491367285015, 284.0604192766932 - 0.2, 15000.0, 22.0, 241.23738612702624, 278.35581779644804 - 0.25, 15000.0, 22.0, 240.46879567242885, 272.5418771883617 -0.30000000000000004, 15000.0, 22.0, 240.75212618915796, 266.1327996092587 -0.35000000000000003, 15000.0, 22.0, 240.59613850166153, 258.642787215964 - 0.4, 15000.0, 22.0, 238.5095934343882, 249.58604216530227 - 0.45, 15000.0, 22.0, 231.51062160118704, 237.84983489812356 - 0.5, 15000.0, 22.0, 222.5798744583053, 224.82916271917583 - 0.55, 15000.0, 22.0, 213.20737325139166, 211.2920912172323 - 0.6000000000000001, 15000.0, 22.0, 204.88313922609464, 198.006685981066 - 0.0, 15000.0, 24.0, 391.4473297741786, 348.477362610168 - 0.05, 15000.0, 24.0, 364.00920629060687, 337.0364417417052 - 0.1, 15000.0, 24.0, 346.2474630559779, 328.0182530065287 -0.15000000000000002, 15000.0, 24.0, 336.1069894960276, 320.7091564965619 - 0.2, 15000.0, 24.0, 331.5326750364909, 314.39551230372865 - 0.25, 15000.0, 24.0, 330.46940910310366, 308.3636805199522 -0.30000000000000004, 15000.0, 24.0, 330.8620811216015, 301.9000212371565 -0.35000000000000003, 15000.0, 24.0, 330.65558051771944, 294.29089454726477 - 0.4, 15000.0, 24.0, 327.7947967171934, 284.82266054220094 - 0.45, 15000.0, 24.0, 318.1708085472173, 271.9275940893467 - 0.5, 15000.0, 24.0, 305.88993722915484, 257.454310954252 - 0.55, 15000.0, 24.0, 293.0046933858324, 242.39734167792622 - 0.6000000000000001, 15000.0, 24.0, 281.56758764007395, 227.75121680137804 - 0.0, 15000.0, 26.0, 499.3110477937902, 392.1004741471343 - 0.05, 15000.0, 26.0, 463.8552999697752, 377.42256414386895 - 0.1, 15000.0, 26.0, 440.8719961333468, 366.26428680464903 -0.15000000000000002, 15000.0, 26.0, 427.720273899303, 357.6808090780843 - 0.2, 15000.0, 26.0, 421.75927088244265, 350.7272979127853 - 0.25, 15000.0, 26.0, 420.34812469756406, 344.4589202573619 -0.30000000000000004, 15000.0, 26.0, 420.84597295946594, 337.93084306042454 -0.35000000000000003, 15000.0, 26.0, 420.61195328294656, 330.19823327058316 - 0.4, 15000.0, 26.0, 417.0052032828045, 320.31625783644796 - 0.45, 15000.0, 26.0, 404.7531846926543, 306.27168583150865 - 0.5, 15000.0, 26.0, 389.1100627708528, 290.32487782974096 - 0.55, 15000.0, 26.0, 372.6983268945787, 273.667796530005 - 0.6000000000000001, 15000.0, 26.0, 358.14046644100813, 257.4924046311585 - 0.0, 15000.0, 28.0, 606.8261344259578, 437.065149090311 - 0.05, 15000.0, 28.0, 563.588153804952, 418.81168624064566 - 0.1, 15000.0, 28.0, 535.5406821657929, 405.2966775001897 -0.15000000000000002, 15000.0, 28.0, 519.4709755025074, 395.3180501039725 - 0.2, 15000.0, 28.0, 512.1662898091223, 387.6737312870242 - 0.25, 15000.0, 28.0, 510.4138810796641, 381.16164828437456 -0.30000000000000004, 15000.0, 28.0, 511.0010053081593, 374.57972833105333 -0.35000000000000003, 15000.0, 28.0, 510.71491848863496, 366.7258986620905 - 0.4, 15000.0, 28.0, 506.3428766151172, 356.39808651251553 - 0.45, 15000.0, 28.0, 491.4775819275594, 341.06414767274504 - 0.5, 15000.0, 28.0, 472.48995168218664, 323.51222371165596 - 0.55, 15000.0, 28.0, 452.5563493811324, 305.20038475352055 - 0.6000000000000001, 15000.0, 28.0, 434.85313852654014, 287.58670092260644 - 0.0, 15000.0, 30.0, 713.9999999999905, 482.5000000000072 - 0.05, 15000.0, 30.0, 663.1749999999932, 460.66875000000465 - 0.1, 15000.0, 30.0, 630.1999999999954, 444.80000000000257 -0.15000000000000002, 15000.0, 30.0, 611.2999999999973, 433.43125000000094 - 0.2, 15000.0, 30.0, 602.6999999999998, 425.09999999999957 - 0.25, 15000.0, 30.0, 600.6250000000024, 418.34374999999835 -0.30000000000000004, 15000.0, 30.0, 601.3000000000058, 411.69999999999715 -0.35000000000000003, 15000.0, 30.0, 600.9500000000097, 403.7062499999959 - 0.4, 15000.0, 30.0, 595.800000000015, 392.89999999999446 - 0.45, 15000.0, 30.0, 578.3249999999931, 376.2125000000038 - 0.5, 15000.0, 30.0, 555.9999999999884, 357.0000000000055 - 0.55, 15000.0, 30.0, 532.5499999999821, 337.0125000000077 - 0.6000000000000001, 15000.0, 30.0, 511.69999999997395, 318.00000000001023 - 0.0, 15000.0, 32.0, 821.6728132996476, 526.0189885356938 - 0.05, 15000.0, 32.0, 762.9942957576367, 501.528203080642 - 0.1, 15000.0, 32.0, 724.9229587682233, 483.9084924633979 -0.15000000000000002, 15000.0, 32.0, 703.1029630445021, 471.4969434102928 - 0.2, 15000.0, 32.0, 693.1784692995677, 462.6306426476578 - 0.25, 15000.0, 32.0, 690.793638246515, 455.64667690182404 -0.30000000000000004, 15000.0, 32.0, 691.5926305984387, 448.8821328991228 -0.35000000000000003, 15000.0, 32.0, 691.2196070684338, 440.67409736588536 - 0.4, 15000.0, 32.0, 685.3187283695942, 429.35965702844265 - 0.45, 15000.0, 32.0, 665.2040160764675, 411.480038444082 - 0.5, 15000.0, 32.0, 639.5100483178073, 390.7599088462709 - 0.55, 15000.0, 32.0, 612.5412640838349, 369.1280752994334 - 0.6000000000000001, 15000.0, 32.0, 588.6021023647625, 348.513344867993 - 0.0, 15000.0, 34.0, 928.2449193207835, 570.7790228551557 - 0.05, 15000.0, 34.0, 862.1173079178186, 543.2111410314259 - 0.1, 15000.0, 34.0, 819.2280640736507, 523.541034115306 -0.15000000000000002, 15000.0, 34.0, 794.6618731186074, 509.88577166442485 - 0.2, 15000.0, 34.0, 783.5034203830149, 500.36242323641073 - 0.25, 15000.0, 34.0, 780.8373911972001, 493.0880583888925 -0.30000000000000004, 15000.0, 34.0, 781.7484708914898, 486.1797466794986 -0.35000000000000003, 15000.0, 34.0, 781.3213447962103, 477.7545576658578 - 0.4, 15000.0, 34.0, 774.6406982416886, 465.9295609055989 - 0.45, 15000.0, 34.0, 751.9002550394698, 446.81140494200383 - 0.5, 15000.0, 34.0, 722.8575850762174, 424.5484223757501 - 0.55, 15000.0, 34.0, 692.3792967198003, 401.2785247931729 - 0.6000000000000001, 15000.0, 34.0, 665.3319983380933, 379.1396237806055 - 0.0, 15000.0, 36.0, 1033.731200792566, 617.9788264380061 - 0.05, 15000.0, 36.0, 960.5826328605089, 586.3649018998445 - 0.1, 15000.0, 36.0, 913.1639744252461, 563.9909596803922 -0.15000000000000002, 15000.0, 36.0, 886.0249762010593, 548.6970684443547 - 0.2, 15000.0, 36.0, 873.7153889022288, 538.3232968564364 - 0.25, 15000.0, 36.0, 870.784963243036, 530.7097135813431 -0.30000000000000004, 15000.0, 36.0, 871.783449937762, 523.6963872837795 -0.35000000000000003, 15000.0, 36.0, 871.2605997006877, 515.1233866284509 - 0.4, 15000.0, 36.0, 863.7661632460944, 502.83078028006275 - 0.45, 15000.0, 36.0, 838.4236717288717, 482.36248147959486 - 0.5, 15000.0, 36.0, 806.0615345414502, 458.4470251629399 - 0.55, 15000.0, 36.0, 772.0819415168344, 433.5167908422698 - 0.6000000000000001, 15000.0, 36.0, 741.8870824880456, 410.0041580297535 - 0.0, 15000.0, 38.0, 1142.050365098131, 666.0671550654004 - 0.05, 15000.0, 38.0, 1060.8532794588098, 629.9253508705766 - 0.1, 15000.0, 38.0, 1008.1957168483676, 604.6149346586252 -0.15000000000000002, 15000.0, 38.0, 978.0388624866216, 587.6474826793412 - 0.2, 15000.0, 38.0, 964.3439015933882, 576.5345711825198 - 0.25, 15000.0, 38.0, 961.0720193884843, 568.7877764179559 -0.30000000000000004, 15000.0, 38.0, 962.1844010917267, 561.9186746354447 -0.35000000000000003, 15000.0, 38.0, 961.6422319229317, 553.4388420847811 - 0.4, 15000.0, 38.0, 953.4066971019166, 540.8598550157601 - 0.45, 15000.0, 38.0, 925.4300775794188, 519.0721779329155 - 0.5, 15000.0, 38.0, 889.7002713825287, 493.4507223218307 - 0.55, 15000.0, 38.0, 852.196272269304, 466.7492879228398 - 0.6000000000000001, 15000.0, 38.0, 818.8970739977786, 441.7216744762719 - 0.0, 15000.0, 40.0, 1249.5000000000048, 710.3999999999871 - 0.05, 15000.0, 40.0, 1160.5187500000027, 671.7749999999934 - 0.1, 15000.0, 40.0, 1102.8000000000009, 644.8999999999976 -0.15000000000000002, 15000.0, 40.0, 1069.7312500000003, 627.0750000000005 - 0.2, 15000.0, 40.0, 1054.6999999999996, 615.6000000000014 - 0.25, 15000.0, 40.0, 1051.0937499999982, 607.775000000001 -0.30000000000000004, 15000.0, 40.0, 1052.2999999999963, 600.8999999999988 -0.35000000000000003, 15000.0, 40.0, 1051.706249999993, 592.2749999999954 - 0.4, 15000.0, 40.0, 1042.699999999987, 579.1999999999907 - 0.45, 15000.0, 40.0, 1012.0937500000001, 556.1500000000025 - 0.5, 15000.0, 40.0, 973.0000000000025, 528.9000000000053 - 0.55, 15000.0, 40.0, 931.9562500000073, 500.4000000000101 - 0.6000000000000001, 15000.0, 40.0, 895.5000000000148, 473.6000000000177 - 0.0, 15000.0, 42.0, 1356.108635155606, 760.0792946701766 - 0.05, 15000.0, 42.0, 1259.6675952027867, 717.0897518037798 - 0.1, 15000.0, 42.0, 1197.1074280484934, 687.2948932873404 -0.15000000000000002, 15000.0, 42.0, 1161.2612348999485, 667.6984331353565 - 0.2, 15000.0, 42.0, 1144.9621169643779, 655.3040853623262 - 0.25, 15000.0, 42.0, 1141.043175449004, 647.115563982748 -0.30000000000000004, 15000.0, 42.0, 1142.3375115610527, 640.1365830111193 -0.35000000000000003, 15000.0, 42.0, 1141.6782265077463, 631.3708564619387 - 0.4, 15000.0, 42.0, 1131.8984214963102, 617.8220983497048 - 0.45, 15000.0, 42.0, 1098.7072016817867, 593.3642989143816 - 0.5, 15000.0, 42.0, 1056.3096564279433, 564.3903434940604 - 0.55, 15000.0, 42.0, 1011.7868790463643, 534.163393652293 - 0.6000000000000001, 15000.0, 42.0, 972.2199628486371, 505.9466109526338 - 0.0, 15000.0, 44.0, 1462.372361318423, 808.001466676733 - 0.05, 15000.0, 44.0, 1358.6890429786483, 761.4954271927585 - 0.1, 15000.0, 44.0, 1291.4684605446746, 729.4002795251845 -0.15000000000000002, 15000.0, 44.0, 1252.9901796480615, 708.4555774713446 - 0.2, 15000.0, 44.0, 1235.5337659203694, 695.4008748285707 - 0.25, 15000.0, 44.0, 1231.378784993159, 686.9757253941967 -0.30000000000000004, 15000.0, 44.0, 1232.804802497989, 679.919682965555 -0.35000000000000003, 15000.0, 44.0, 1232.0913840664214, 670.972301339979 - 0.4, 15000.0, 44.0, 1221.518095330015, 656.8731343148014 - 0.45, 15000.0, 44.0, 1185.6804633349752, 630.9504205897645 - 0.5, 15000.0, 44.0, 1139.910169468947, 600.1776592549899 - 0.55, 15000.0, 44.0, 1091.8548565342292, 568.1170343030221 - 0.6000000000000001, 15000.0, 44.0, 1049.1621673331163, 538.3307297264 - 0.0, 15000.0, 46.0, 1570.2812015994375, 855.8179916144857 - 0.05, 15000.0, 46.0, 1458.5487643085344, 805.8073005305024 - 0.1, 15000.0, 46.0, 1386.0827270946043, 771.4170629105467 -0.15000000000000002, 15000.0, 46.0, 1344.5759649441209, 749.1266441587933 - 0.2, 15000.0, 46.0, 1325.7213528435593, 735.4154096794163 - 0.25, 15000.0, 46.0, 1321.211765779393, 726.7627248765904 -0.30000000000000004, 15000.0, 46.0, 1322.7400787380966, 719.6479551544905 -0.35000000000000003, 15000.0, 46.0, 1321.9991667061436, 710.5504659172915 - 0.4, 15000.0, 46.0, 1310.6819046700086, 695.9496225691671 - 0.45, 15000.0, 46.0, 1272.219536665032, 668.6631943498842 - 0.5, 15000.0, 46.0, 1223.0898305310584, 636.1553351568548 - 0.55, 15000.0, 46.0, 1171.5089231567563, 602.2286027230924 - 0.6000000000000001, 15000.0, 46.0, 1125.692951430813, 570.6855547816059 - 0.0, 15000.0, 48.0, 1678.0807806074781, 905.5689873915544 - 0.05, 15000.0, 48.0, 1558.5088502171918, 851.5505799756775 - 0.1, 15000.0, 48.0, 1480.9525536098154, 814.4899719414996 -0.15000000000000002, 15000.0, 48.0, 1436.5254353406524, 790.5871168741983 - 0.2, 15000.0, 48.0, 1416.3410399650074, 776.0419683589513 - 0.25, 15000.0, 48.0, 1411.5129120381855, 767.0544799809354 -0.30000000000000004, 15000.0, 48.0, 1413.1545961154916, 759.8246053253279 -0.35000000000000003, 15000.0, 48.0, 1412.3796367522302, 750.5522979773064 - 0.4, 15000.0, 48.0, 1400.301578503705, 735.4375115220475 - 0.45, 15000.0, 48.0, 1359.1927983182168, 706.7391828432089 - 0.5, 15000.0, 48.0, 1306.6903435720626, 672.4803156305544 - 0.55, 15000.0, 48.0, 1251.5900940345084, 636.7428968723442 - 0.6000000000000001, 15000.0, 48.0, 1202.687929474832, 603.608913556829 - 0.0, 15000.0, 50.0, 1782.5000000000434, 958.1000000000355 - 0.05, 15000.0, 50.0, 1656.3625000000236, 898.9812500000226 - 0.1, 15000.0, 50.0, 1574.600000000011, 858.5000000000128 -0.15000000000000002, 15000.0, 50.0, 1527.812500000004, 832.5187500000055 - 0.2, 15000.0, 50.0, 1506.6000000000033, 816.9000000000001 - 0.25, 15000.0, 50.0, 1501.5625000000073, 807.5062499999957 -0.30000000000000004, 15000.0, 50.0, 1503.3000000000156, 800.1999999999913 -0.35000000000000003, 15000.0, 50.0, 1502.412500000027, 790.8437499999861 - 0.4, 15000.0, 50.0, 1489.5000000000416, 775.2999999999796 - 0.45, 15000.0, 50.0, 1445.806250000001, 745.1562500000122 - 0.5, 15000.0, 50.0, 1390.0000000000027, 709.1000000000264 - 0.55, 15000.0, 50.0, 1331.3937500000022, 671.5437500000455 - 0.6000000000000001, 15000.0, 50.0, 1279.3000000000002, 636.9000000000688 - 0.0, 17500.0, 20.0, 128.89999999999986, 262.3999999999998 - 0.05, 17500.0, 20.0, 138.12499999999991, 264.4812499999999 - 0.1, 17500.0, 20.0, 145.19999999999996, 264.4999999999999 -0.15000000000000002, 17500.0, 20.0, 150.37499999999997, 262.6187499999999 - 0.2, 17500.0, 20.0, 153.89999999999998, 258.99999999999994 - 0.25, 17500.0, 20.0, 156.02499999999995, 253.80624999999998 -0.30000000000000004, 17500.0, 20.0, 156.99999999999997, 247.19999999999996 -0.35000000000000003, 17500.0, 20.0, 157.07499999999996, 239.34374999999994 - 0.4, 17500.0, 20.0, 156.49999999999994, 230.39999999999992 - 0.45, 17500.0, 20.0, 156.14375000000004, 220.70625000000015 - 0.5, 17500.0, 20.0, 154.4000000000001, 209.90000000000026 - 0.55, 17500.0, 20.0, 150.28125000000017, 197.79375000000036 - 0.6000000000000001, 17500.0, 20.0, 142.80000000000024, 184.2000000000004 - 0.0, 17500.0, 22.0, 204.79762948163938, 288.2436355793072 - 0.05, 17500.0, 22.0, 220.15919338214866, 292.8929214320115 - 0.1, 17500.0, 22.0, 231.92534620859192, 294.8456359019062 -0.15000000000000002, 17500.0, 22.0, 240.51861508158652, 294.34774615470485 - 0.2, 17500.0, 22.0, 246.3615271217497, 291.64521935612004 - 0.25, 17500.0, 22.0, 249.87660944969872, 286.98402267186526 -0.30000000000000004, 17500.0, 22.0, 251.48638918605099, 280.6101232676535 -0.35000000000000003, 17500.0, 22.0, 251.61339345142375, 272.7694883091979 - 0.4, 17500.0, 22.0, 250.68014936643428, 263.7080849622118 - 0.45, 17500.0, 22.0, 250.11213520252844, 254.00943986454809 - 0.5, 17500.0, 22.0, 247.32302462783963, 242.90684176550218 - 0.55, 17500.0, 22.0, 240.7294424613317, 229.97113888651072 - 0.6000000000000001, 17500.0, 22.0, 228.74801352196755, 214.77317944900997 - 0.0, 17500.0, 24.0, 281.7489048759334, 315.4784297089172 - 0.05, 17500.0, 24.0, 302.73838049174265, 322.7831571369383 - 0.1, 17500.0, 24.0, 318.8226731042968, 326.74757408639834 -0.15000000000000002, 17500.0, 24.0, 330.576541767149, 327.69817090028744 - 0.2, 17500.0, 24.0, 338.5747455338525, 325.9614379215958 - 0.25, 17500.0, 24.0, 343.39204345795997, 321.86386549331314 -0.30000000000000004, 17500.0, 24.0, 345.6031945930244, 315.7319439584295 -0.35000000000000003, 17500.0, 24.0, 345.78295799259934, 307.8921636599351 - 0.4, 17500.0, 24.0, 344.5060927102373, 298.6710149408196 - 0.45, 17500.0, 24.0, 343.720702741466, 288.9017768936596 - 0.5, 17500.0, 24.0, 339.8815123139222, 277.3905736126942 - 0.55, 17500.0, 24.0, 330.81659059722443, 263.450317941756 - 0.6000000000000001, 17500.0, 24.0, 314.3540067609878, 246.39392272467398 - 0.0, 17500.0, 26.0, 358.991365529409, 344.1014060488733 - 0.05, 17500.0, 26.0, 385.4767209102632, 354.03443212585915 - 0.1, 17500.0, 26.0, 405.77732689570644, 359.99669431993703 -0.15000000000000002, 17500.0, 26.0, 420.6164109119187, 362.3897225685178 - 0.2, 17500.0, 26.0, 430.71720038508033, 361.6150468090114 - 0.25, 17500.0, 26.0, 436.8029227413713, 358.0741969788281 -0.30000000000000004, 17500.0, 26.0, 439.5968054069716, 352.1687030153783 -0.35000000000000003, 17500.0, 26.0, 439.8220758080615, 344.300094856072 - 0.4, 17500.0, 26.0, 438.20196137082115, 334.86990243831974 - 0.45, 17500.0, 26.0, 437.20257767914006, 324.95189399049787 - 0.5, 17500.0, 26.0, 432.3184876860855, 312.93088457713645 - 0.55, 17500.0, 26.0, 420.78714250245207, 297.8639275537475 - 0.6000000000000001, 17500.0, 26.0, 399.84599323902506, 278.8080762758349 - 0.0, 17500.0, 28.0, 435.3741697405005, 374.23413625814686 - 0.05, 17500.0, 28.0, 467.79169131373624, 386.61159750313914 - 0.1, 17500.0, 28.0, 492.6133423458541, 394.43403537391964 -0.15000000000000002, 17500.0, 28.0, 510.7328037208373, 398.167961722387 - 0.2, 17500.0, 28.0, 523.0437563226692, 398.2798884004409 - 0.25, 17500.0, 28.0, 530.4398810353334, 395.2363272599799 -0.30000000000000004, 17500.0, 28.0, 533.814858742813, 389.5037901529032 -0.35000000000000003, 17500.0, 28.0, 534.0623703290916, 381.5487889311099 - 0.4, 17500.0, 28.0, 532.0760966781517, 371.837835446499 - 0.45, 17500.0, 28.0, 530.882260317287, 361.6529949426892 - 0.5, 17500.0, 28.0, 524.976917200553, 349.0141190964165 - 0.55, 17500.0, 28.0, 510.9886649253162, 332.75661297613436 - 0.6000000000000001, 17500.0, 28.0, 485.54610108894246, 311.7158816502978 - 0.0, 17500.0, 30.0, 511.30000000000683, 405.49999999999625 - 0.05, 17500.0, 30.0, 549.8875000000043, 420.1499999999986 - 0.1, 17500.0, 30.0, 579.4000000000024, 429.7 -0.15000000000000002, 17500.0, 30.0, 600.9125000000009, 434.6750000000004 - 0.2, 17500.0, 30.0, 615.5, 435.6000000000004 - 0.25, 17500.0, 30.0, 624.2374999999992, 433.0000000000001 -0.30000000000000004, 17500.0, 30.0, 628.1999999999985, 427.3999999999998 -0.35000000000000003, 17500.0, 30.0, 628.4624999999975, 419.3249999999996 - 0.4, 17500.0, 30.0, 626.0999999999958, 409.29999999999984 - 0.45, 17500.0, 30.0, 624.7187499999944, 398.7999999999936 - 0.5, 17500.0, 30.0, 617.7999999999918, 385.49999999999085 - 0.55, 17500.0, 30.0, 601.3562499999883, 368.0249999999874 - 0.6000000000000001, 17500.0, 30.0, 571.3999999999847, 344.9999999999833 - 0.0, 17500.0, 32.0, 588.0564795784485, 437.18513918441107 - 0.05, 17500.0, 32.0, 632.4295630849244, 454.0369076792064 - 0.1, 17500.0, 32.0, 666.3714726082785, 465.24904566695733 -0.15000000000000002, 17500.0, 32.0, 691.1170164186107, 471.4082233424663 - 0.2, 17500.0, 32.0, 707.901002786021, 473.10111090053556 - 0.25, 17500.0, 32.0, 717.9582399806094, 470.91437853596756 -0.30000000000000004, 17500.0, 32.0, 722.5235362724763, 465.43469644356486 -0.35000000000000003, 17500.0, 32.0, 722.831699931721, 457.2487348181299 - 0.4, 17500.0, 32.0, 720.1175392284441, 446.94316385446456 - 0.45, 17500.0, 32.0, 718.5247076993674, 436.21326824561714 - 0.5, 17500.0, 32.0, 710.5614778147418, 422.3198746916819 - 0.55, 17500.0, 32.0, 691.6449673114466, 403.6324243910222 - 0.6000000000000001, 17500.0, 32.0, 657.1922939263569, 378.52035854198886 - 0.0, 17500.0, 34.0, 664.9316380936322, 470.26804200164565 - 0.05, 17500.0, 34.0, 714.971642668329, 488.8593879770205 - 0.1, 17500.0, 34.0, 753.2617167237303, 501.40185824661404 -0.15000000000000002, 17500.0, 34.0, 781.1900284613273, 508.52618093968135 - 0.2, 17500.0, 34.0, 800.1447460826115, 510.8630841854776 - 0.25, 17500.0, 34.0, 811.5140377890748, 509.04329611325807 -0.30000000000000004, 17500.0, 34.0, 816.6860717822086, 503.6975448522781 -0.35000000000000003, 17500.0, 34.0, 817.0490162635047, 495.45655853179295 - 0.4, 17500.0, 34.0, 813.9910394344543, 484.9510652810575 - 0.45, 17500.0, 34.0, 812.1798778749574, 474.07763330647566 - 0.5, 17500.0, 34.0, 803.1649946512979, 459.6694705058561 - 0.55, 17500.0, 34.0, 781.7754212081722, 439.8256248541559 - 0.6000000000000001, 17500.0, 34.0, 742.8401889902743, 412.64514432633183 - 0.0, 17500.0, 36.0, 741.5944344448129, 503.64347537201525 - 0.05, 17500.0, 36.0, 797.3452131258944, 523.937098026681 - 0.1, 17500.0, 36.0, 840.0122153544754, 537.8030867468526 -0.15000000000000002, 17500.0, 36.0, 871.1397688190772, 545.9114056480743 - 0.2, 17500.0, 36.0, 892.2722012082197, 548.9320188458912 - 0.25, 17500.0, 36.0, 904.9538402104234, 547.5348904558479 -0.30000000000000004, 17500.0, 36.0, 910.729013514209, 542.3899845934889 -0.35000000000000003, 17500.0, 36.0, 911.1420488080962, 534.1672653743597 - 0.4, 17500.0, 36.0, 907.7372737806057, 523.5366969140041 - 0.45, 17500.0, 36.0, 905.7117327028392, 512.5949353003064 - 0.5, 17500.0, 36.0, 895.6516035156129, 497.7318687317928 - 0.55, 17500.0, 36.0, 871.79578074234, 476.7640773793292 - 0.6000000000000001, 17500.0, 36.0, 828.383158906424, 447.50814141378174 - 0.0, 17500.0, 38.0, 817.7256455775745, 529.9336597138301 - 0.05, 17500.0, 38.0, 879.5981081805471, 554.8543321705711 - 0.1, 17500.0, 38.0, 926.9239005855035, 572.2189485546334 -0.15000000000000002, 17500.0, 38.0, 961.4257065919309, 582.8423476823629 - 0.2, 17500.0, 38.0, 984.8262099993171, 587.5393683701056 - 0.25, 17500.0, 38.0, 998.8480946071503, 587.1248494342078 -0.30000000000000004, 17500.0, 38.0, 1005.2140442149171, 582.413629691015 -0.35000000000000003, 17500.0, 38.0, 1005.6467426221063, 574.2205479568735 - 0.4, 17500.0, 38.0, 1001.8688736282048, 563.3604430481295 - 0.45, 17500.0, 38.0, 999.6519709682169, 552.3175901916551 - 0.5, 17500.0, 38.0, 988.5721686351105, 536.8985189722155 - 0.55, 17500.0, 38.0, 962.2544505574124, 514.5791953851167 - 0.6000000000000001, 17500.0, 38.0, 914.323800663629, 482.83558542565805 - 0.0, 17500.0, 40.0, 896.0999999999761, 563.499999999994 - 0.05, 17500.0, 40.0, 963.0499999999889, 590.6812499999967 - 0.1, 17500.0, 40.0, 1014.2999999999965, 609.7999999999986 -0.15000000000000002, 17500.0, 40.0, 1051.7000000000003, 621.71875 - 0.2, 17500.0, 40.0, 1077.1000000000004, 627.3000000000001 - 0.25, 17500.0, 40.0, 1092.3499999999985, 627.4062499999989 -0.30000000000000004, 17500.0, 40.0, 1099.2999999999952, 622.8999999999967 -0.35000000000000003, 17500.0, 40.0, 1099.7999999999922, 614.6437499999927 - 0.4, 17500.0, 40.0, 1095.6999999999898, 603.4999999999876 - 0.45, 17500.0, 40.0, 1093.2500000000107, 592.1312499999997 - 0.5, 17500.0, 40.0, 1081.1000000000188, 576.0000000000008 - 0.55, 17500.0, 40.0, 1052.3000000000297, 552.3687500000032 - 0.6000000000000001, 17500.0, 40.0, 999.9000000000455, 518.5000000000066 - 0.0, 17500.0, 42.0, 973.3399259312724, 596.6800371903564 - 0.05, 17500.0, 42.0, 1045.7698294895074, 626.4832694956889 - 0.1, 17500.0, 42.0, 1101.2404828506442, 647.5710305991735 -0.15000000000000002, 17500.0, 42.0, 1141.7450963150216, 660.882631083486 - 0.2, 17500.0, 42.0, 1169.276880182975, 667.3573815313043 - 0.25, 17500.0, 42.0, 1185.8290447548422, 667.9345925253045 -0.30000000000000004, 17500.0, 42.0, 1193.3948003309602, 663.5535746481643 -0.35000000000000003, 17500.0, 42.0, 1193.9673572116646, 655.15363848256 - 0.4, 17500.0, 42.0, 1189.5399256972944, 643.6740946111681 - 0.45, 17500.0, 42.0, 1186.8688718395174, 632.0189936302914 - 0.5, 17500.0, 42.0, 1173.6579386846627, 615.2334260817368 - 0.55, 17500.0, 42.0, 1142.3740250303717, 590.3272225209348 - 0.6000000000000001, 17500.0, 42.0, 1085.4840296742957, 554.3102135033173 - 0.0, 17500.0, 44.0, 1049.0667486119662, 629.6818175008689 - 0.05, 17500.0, 44.0, 1127.7971162056704, 662.3690875402351 - 0.1, 17500.0, 44.0, 1188.0441542455528, 685.6125824883844 -0.15000000000000002, 17500.0, 44.0, 1231.9910981736466, 700.4410218463782 - 0.2, 17500.0, 44.0, 1261.8211834319845, 707.8831251152769 - 0.25, 17500.0, 44.0, 1279.7176454625992, 708.9676117961418 -0.30000000000000004, 17500.0, 44.0, 1287.8637197075245, 704.7232013900335 -0.35000000000000003, 17500.0, 44.0, 1288.4426416087915, 696.1786133980129 - 0.4, 17500.0, 44.0, 1283.6376466084348, 684.3625673211411 - 0.45, 17500.0, 44.0, 1280.8088914889022, 672.4694396033293 - 0.5, 17500.0, 44.0, 1266.6088476709751, 655.0309789171117 - 0.55, 17500.0, 44.0, 1232.8669079158644, 628.7445908778936 - 0.6000000000000001, 17500.0, 44.0, 1171.412464984775, 590.3076811010691 - 0.0, 17500.0, 46.0, 1126.0585495233531, 662.1206714634152 - 0.05, 17500.0, 46.0, 1210.3405989824741, 698.0151591543361 - 0.1, 17500.0, 46.0, 1274.8596109063144, 723.6329312795687 -0.15000000000000002, 17500.0, 46.0, 1321.9443792088578, 740.1114751700303 - 0.2, 17500.0, 46.0, 1353.923697804088, 748.5882781566381 - 0.25, 17500.0, 46.0, 1373.1263606059902, 750.2008275703096 -0.30000000000000004, 17500.0, 46.0, 1381.8811615285476, 746.0866107419621 -0.35000000000000003, 17500.0, 46.0, 1382.5168944857446, 737.3831150025128 - 0.4, 17500.0, 46.0, 1377.3623533915656, 725.227827682879 - 0.45, 17500.0, 46.0, 1374.2766390680872, 713.1304072008535 - 0.5, 17500.0, 46.0, 1358.9976247050126, 695.1118276267152 - 0.55, 17500.0, 46.0, 1322.7934904001404, 667.5652341176105 - 0.6000000000000001, 17500.0, 46.0, 1256.932416251269, 626.8837718306892 - 0.0, 17500.0, 48.0, 1202.571123243588, 696.8723300777192 - 0.05, 17500.0, 48.0, 1292.7819056124172, 735.156638540733 - 0.1, 17500.0, 48.0, 1361.8285978872602, 762.5813369028807 -0.15000000000000002, 17500.0, 48.0, 1412.2075789027604, 780.3552227643385 - 0.2, 17500.0, 48.0, 1446.4152274935645, 789.6870937252814 - 0.25, 17500.0, 48.0, 1466.947922494318, 791.7857473858857 -0.30000000000000004, 17500.0, 48.0, 1476.3020427396657, 787.8599813463273 -0.35000000000000003, 17500.0, 48.0, 1476.9739670642539, 779.1185932067813 - 0.4, 17500.0, 48.0, 1471.4600743027274, 766.7703805674239 - 0.45, 17500.0, 48.0, 1468.1730617704795, 754.604079533061 - 0.5, 17500.0, 48.0, 1451.8603528599178, 736.0886721899852 - 0.55, 17500.0, 48.0, 1413.1856894441742, 707.2730791291239 - 0.6000000000000001, 17500.0, 48.0, 1342.8128133963894, 664.2062209414019 - 0.0, 17500.0, 50.0, 1280.9000000000333, 733.6000000000076 - 0.05, 17500.0, 50.0, 1376.212500000014, 773.4062500000043 - 0.1, 17500.0, 50.0, 1449.2000000000037, 802.1000000000023 -0.15000000000000002, 17500.0, 50.0, 1502.4874999999995, 820.8937500000009 - 0.2, 17500.0, 50.0, 1538.7000000000012, 830.9999999999999 - 0.25, 17500.0, 50.0, 1560.462500000008, 833.6312499999997 -0.30000000000000004, 17500.0, 50.0, 1570.4000000000176, 829.9999999999999 -0.35000000000000003, 17500.0, 50.0, 1571.1375000000305, 821.3187500000008 - 0.4, 17500.0, 50.0, 1565.3000000000452, 808.8000000000015 - 0.45, 17500.0, 50.0, 1561.7812500000111, 796.3437500000196 - 0.5, 17500.0, 50.0, 1544.4000000000292, 777.1000000000284 - 0.55, 17500.0, 50.0, 1503.2437500000563, 746.9062500000368 - 0.6000000000000001, 17500.0, 50.0, 1428.4000000000945, 701.6000000000441 - 0.0, 20000.0, 20.0, 162.49999999999991, 294.80000000000047 - 0.05, 20000.0, 20.0, 157.78124999999994, 293.4000000000002 - 0.1, 20000.0, 20.0, 155.19999999999996, 290.7000000000001 -0.15000000000000002, 20000.0, 20.0, 154.34374999999997, 286.75 - 0.2, 20000.0, 20.0, 154.79999999999998, 281.59999999999997 - 0.25, 20000.0, 20.0, 156.15624999999997, 275.29999999999995 -0.30000000000000004, 20000.0, 20.0, 157.99999999999997, 267.8999999999999 -0.35000000000000003, 20000.0, 20.0, 159.91875, 259.44999999999993 - 0.4, 20000.0, 20.0, 161.49999999999997, 249.99999999999991 - 0.45, 20000.0, 20.0, 162.15625000000006, 239.58125000000007 - 0.5, 20000.0, 20.0, 162.0000000000001, 228.30000000000018 - 0.55, 20000.0, 20.0, 160.9687500000002, 216.24375000000026 - 0.6000000000000001, 20000.0, 20.0, 159.00000000000026, 203.50000000000028 - 0.0, 20000.0, 22.0, 258.19946884463434, 321.67328948785655 - 0.05, 20000.0, 22.0, 251.47628234585903, 319.3489265031609 - 0.1, 20000.0, 22.0, 247.92913954416193, 316.27654396193 -0.15000000000000002, 20000.0, 22.0, 246.93737433648042, 312.4031929668564 - 0.2, 20000.0, 22.0, 247.88032061975187, 307.6759246206321 - 0.25, 20000.0, 22.0, 250.1373122909134, 302.0417900259491 -0.30000000000000004, 20000.0, 22.0, 253.08768324690234, 295.44784028549986 -0.35000000000000003, 20000.0, 22.0, 256.1107673846561, 287.8411265019763 - 0.4, 20000.0, 22.0, 258.58589860111175, 279.1686997780706 - 0.45, 20000.0, 22.0, 259.63644797351833, 269.3097466584053 - 0.5, 20000.0, 22.0, 259.40963785788165, 258.41491191988393 - 0.55, 20000.0, 22.0, 257.7967277905217, 246.5669757813426 - 0.6000000000000001, 20000.0, 22.0, 254.68897730775672, 233.84871846161587 - 0.0, 20000.0, 24.0, 355.84973442231393, 353.5812736907168 - 0.05, 20000.0, 24.0, 346.1762661729276, 350.1882680243074 - 0.1, 20000.0, 24.0, 341.0045697720801, 346.6134417384294 -0.15000000000000002, 20000.0, 24.0, 339.45806216824013, 342.6940816513178 - 0.2, 20000.0, 24.0, 340.66016030987623, 338.26747458120786 - 0.25, 20000.0, 24.0, 343.73428114545703, 333.17090734633496 -0.30000000000000004, 20000.0, 24.0, 347.80384162345115, 327.2416667649337 -0.35000000000000003, 20000.0, 24.0, 351.99225869232714, 320.31703965524014 - 0.4, 20000.0, 24.0, 355.42294930055385, 312.2343128354888 - 0.45, 20000.0, 24.0, 356.84634898676165, 302.7139759850826 - 0.5, 20000.0, 24.0, 356.5048189289442, 291.9437073387579 - 0.55, 20000.0, 24.0, 354.26773889526555, 279.9943879924233 - 0.6000000000000001, 20000.0, 24.0, 350.00448865388444, 266.93689904198465 - 0.0, 20000.0, 26.0, 454.15026557767476, 389.41261314964873 - 0.05, 20000.0, 26.0, 441.2112338270657, 384.7025212938741 - 0.1, 20000.0, 26.0, 434.1954302279171, 380.42206753396414 -0.15000000000000002, 20000.0, 26.0, 431.95443783175955, 376.28899885235137 - 0.2, 20000.0, 26.0, 433.3398396901248, 372.0210622314678 - 0.25, 20000.0, 26.0, 437.2032188545439, 367.3360046537457 -0.30000000000000004, 20000.0, 26.0, 442.3961583765483, 361.9515731016175 -0.35000000000000003, 20000.0, 26.0, 447.7702413076694, 355.58551455751495 - 0.4, 20000.0, 26.0, 452.17705069943827, 347.9555760038706 - 0.45, 20000.0, 26.0, 453.9661510132465, 338.60708198255696 - 0.5, 20000.0, 26.0, 453.4951810710676, 327.7750467976897 - 0.55, 20000.0, 26.0, 450.6197611047506, 315.5220623128324 - 0.6000000000000001, 20000.0, 26.0, 445.1955113461363, 301.9107203915452 - 0.0, 20000.0, 28.0, 551.1612446066326, 428.3547230735671 - 0.05, 20000.0, 28.0, 535.5727237832863, 421.75830969095284 - 0.1, 20000.0, 28.0, 527.1420335623523, 416.34139065103017 -0.15000000000000002, 20000.0, 28.0, 524.479998360108, 411.67953903755694 - 0.2, 20000.0, 28.0, 526.1974425928319, 407.34832793429166 - 0.25, 20000.0, 28.0, 530.9051906768018, 402.9233304249921 -0.30000000000000004, 20000.0, 28.0, 537.2140670282959, 397.98011959341653 -0.35000000000000003, 20000.0, 28.0, 543.7348960635926, 392.0942685233231 - 0.4, 20000.0, 28.0, 549.0785021989695, 384.8413502984699 - 0.45, 20000.0, 28.0, 551.2484542727727, 375.54583004162583 - 0.5, 20000.0, 28.0, 550.6773434350768, 364.5366047195175 - 0.55, 20000.0, 28.0, 547.1905052580261, 351.89146333788267 - 0.6000000000000001, 20000.0, 28.0, 540.6132753137647, 337.6881949024585 - 0.0, 20000.0, 30.0, 647.4999999999955, 468.3999999999937 - 0.05, 20000.0, 30.0, 629.6062499999967, 459.8937499999962 - 0.1, 20000.0, 30.0, 619.9999999999982, 453.29999999999814 -0.15000000000000002, 20000.0, 30.0, 617.0687499999992, 448.0562499999995 - 0.2, 20000.0, 30.0, 619.1999999999996, 443.6000000000003 - 0.25, 20000.0, 30.0, 624.7812499999992, 439.36875000000055 -0.30000000000000004, 20000.0, 30.0, 632.1999999999982, 434.80000000000007 -0.35000000000000003, 20000.0, 30.0, 639.8437499999962, 429.33124999999905 - 0.4, 20000.0, 30.0, 646.0999999999931, 422.3999999999975 - 0.45, 20000.0, 30.0, 648.6562499999927, 413.1124999999943 - 0.5, 20000.0, 30.0, 647.9999999999883, 401.89999999999236 - 0.55, 20000.0, 30.0, 643.9187499999829, 388.8624999999909 - 0.6000000000000001, 20000.0, 30.0, 636.1999999999766, 374.0999999999906 - 0.0, 20000.0, 32.0, 745.3872800538642, 505.59948817927034 - 0.05, 20000.0, 32.0, 724.5420215864343, 496.6243248226929 - 0.1, 20000.0, 32.0, 713.3082936108315, 489.8472354725873 -0.15000000000000002, 20000.0, 32.0, 709.8178781950705, 484.6438577644094 - 0.2, 20000.0, 32.0, 712.2025574071678, 480.38982933361586 - 0.25, 20000.0, 32.0, 718.5941133151384, 476.46078781566257 -0.30000000000000004, 20000.0, 32.0, 727.1243279869982, 472.23237084600595 -0.35000000000000003, 20000.0, 32.0, 735.9249834907629, 467.08021606010203 - 0.4, 20000.0, 32.0, 743.1278618944482, 460.37996109340696 - 0.45, 20000.0, 32.0, 746.0442531514959, 451.15002641300407 - 0.5, 20000.0, 32.0, 745.2674156736163, 439.8377011594824 - 0.55, 20000.0, 32.0, 740.5701157579182, 426.5330573050682 - 0.6000000000000001, 20000.0, 32.0, 731.7251197015249, 411.3261668219822 - 0.0, 20000.0, 34.0, 842.3823563195513, 545.6893054940492 - 0.05, 20000.0, 34.0, 818.8770297661332, 535.1398067485119 - 0.1, 20000.0, 34.0, 806.2202076172529, 527.4179339726612 -0.15000000000000002, 20000.0, 34.0, 802.3023160227212, 521.7834344192329 - 0.2, 20000.0, 34.0, 805.0137811323493, 517.4960553409629 - 0.25, 20000.0, 34.0, 812.2450290959482, 513.8155439905871 -0.30000000000000004, 20000.0, 34.0, 821.886486063329, 510.0016476208414 -0.35000000000000003, 20000.0, 34.0, 831.8285781843027, 505.3141134844613 - 0.4, 20000.0, 34.0, 839.9617316086803, 499.01268883418294 - 0.45, 20000.0, 34.0, 843.2467837982929, 489.95398158424626 - 0.5, 20000.0, 34.0, 842.3629269669211, 478.60715700287955 - 0.55, 20000.0, 34.0, 837.0597646403843, 465.0382410198149 - 0.6000000000000001, 20000.0, 34.0, 827.0869003444906, 449.3132595647842 - 0.0, 20000.0, 36.0, 938.2672645482608, 589.4576304234296 - 0.05, 20000.0, 36.0, 912.5027286701218, 575.8344604203294 - 0.1, 20000.0, 36.0, 898.7020448826661, 566.155459640485 -0.15000000000000002, 20000.0, 36.0, 894.5347225219009, 559.483950374453 - 0.2, 20000.0, 36.0, 897.6702709238343, 554.8832549127897 - 0.25, 20000.0, 36.0, 905.7781994244731, 551.4166955460508 -0.30000000000000004, 20000.0, 36.0, 916.5280173598248, 548.1475945647927 -0.35000000000000003, 20000.0, 36.0, 927.589234065897, 544.1392742595717 - 0.4, 20000.0, 36.0, 936.6313588786966, 538.455056920944 - 0.45, 20000.0, 36.0, 940.3034076787667, 529.6721194781118 - 0.5, 20000.0, 36.0, 939.3363701685723, 518.3122203056993 - 0.55, 20000.0, 36.0, 933.4407425951523, 504.4109724169728 - 0.6000000000000001, 20000.0, 36.0, 922.3270212055232, 488.0039888251999 - 0.0, 20000.0, 38.0, 1037.4316639544586, 627.3554202192579 - 0.05, 20000.0, 38.0, 1008.3065871980464, 613.3825444933825 - 0.1, 20000.0, 38.0, 992.5807416948553, 603.7262813500893 -0.15000000000000002, 20000.0, 38.0, 987.6513821137587, 597.3615284046386 - 0.2, 20000.0, 38.0, 990.9157631236301, 593.263183272291 - 0.25, 20000.0, 38.0, 999.7711393933428, 590.4061435683071 -0.30000000000000004, 20000.0, 38.0, 1011.61476559177, 587.7653069079469 -0.35000000000000003, 20000.0, 38.0, 1023.8438963877862, 584.315570906471 - 0.4, 20000.0, 38.0, 1033.8557864502634, 579.03183317914 - 0.45, 20000.0, 38.0, 1037.901474558922, 570.3749942726455 - 0.5, 20000.0, 38.0, 1036.8168630500868, 558.8619430080415 - 0.55, 20000.0, 38.0, 1030.2916383709269, 544.4955711379014 - 0.6000000000000001, 20000.0, 38.0, 1018.0154869686146, 527.278770414753 - 0.0, 20000.0, 40.0, 1135.9000000000162, 669.7000000000098 - 0.05, 20000.0, 40.0, 1103.487500000008, 654.0937500000047 - 0.1, 20000.0, 40.0, 1085.9000000000035, 643.5000000000018 -0.15000000000000002, 20000.0, 40.0, 1080.262500000002, 636.7562500000009 - 0.2, 20000.0, 40.0, 1083.7000000000016, 632.7000000000008 - 0.25, 20000.0, 40.0, 1093.3375000000012, 630.1687500000013 -0.30000000000000004, 20000.0, 40.0, 1106.2999999999995, 628.0000000000014 -0.35000000000000003, 20000.0, 40.0, 1119.7124999999949, 625.0312500000001 - 0.4, 20000.0, 40.0, 1130.6999999999875, 620.0999999999974 - 0.45, 20000.0, 40.0, 1135.1125000000097, 611.4562500000029 - 0.5, 20000.0, 40.0, 1133.9000000000126, 599.7000000000077 - 0.55, 20000.0, 40.0, 1126.7375000000156, 584.8437500000151 - 0.6000000000000001, 20000.0, 40.0, 1113.3000000000181, 566.9000000000268 - 0.0, 20000.0, 42.0, 1232.6855152605738, 710.1357471445999 - 0.05, 20000.0, 42.0, 1197.7129874263112, 693.8265898380761 - 0.1, 20000.0, 42.0, 1178.7588671955957, 682.9346330718597 -0.15000000000000002, 20000.0, 42.0, 1172.7165389718764, 676.2079501994072 - 0.2, 20000.0, 42.0, 1176.479387158603, 672.3946145741734 - 0.25, 20000.0, 42.0, 1186.9407961592267, 670.242699549615 -0.30000000000000004, 20000.0, 42.0, 1200.9941503771981, 668.5002784791877 -0.35000000000000003, 20000.0, 42.0, 1215.5328342159657, 665.9154247163473 - 0.4, 20000.0, 42.0, 1227.450232078981, 661.2362116145498 - 0.45, 20000.0, 42.0, 1232.2747098037714, 652.5760560749206 - 0.5, 20000.0, 42.0, 1230.9947074915624, 640.5870008078894 - 0.55, 20000.0, 42.0, 1223.2336466776662, 625.2864320715415 - 0.6000000000000001, 20000.0, 42.0, 1208.6149488973906, 606.6917361239697 - 0.0, 20000.0, 44.0, 1330.6282735599284, 753.5638557084849 - 0.05, 20000.0, 44.0, 1292.7026647054781, 735.557336475413 - 0.1, 20000.0, 44.0, 1272.1300144561046, 723.6461995788017 -0.15000000000000002, 20000.0, 44.0, 1265.545098451021, 716.4492119724108 - 0.2, 20000.0, 44.0, 1269.5826923294405, 712.5851406100027 - 0.25, 20000.0, 44.0, 1280.8775717305755, 710.6727524453382 -0.30000000000000004, 20000.0, 44.0, 1296.064512293639, 709.330814432178 -0.35000000000000003, 20000.0, 44.0, 1311.7782896578433, 707.1780935242846 - 0.4, 20000.0, 44.0, 1324.6536794624012, 702.8333566754181 - 0.45, 20000.0, 44.0, 1329.8338562403428, 694.1869503373115 - 0.5, 20000.0, 44.0, 1328.428398949411, 682.0429029698415 - 0.55, 20000.0, 44.0, 1320.0552854411415, 666.4768225308813 - 0.6000000000000001, 20000.0, 44.0, 1304.3324935670837, 647.564316978291 - 0.0, 20000.0, 46.0, 1426.4473202597576, 795.16799712932 - 0.05, 20000.0, 46.0, 1386.2833611228045, 776.4857472921694 - 0.1, 20000.0, 46.0, 1364.5802230717632, 764.2219051003523 -0.15000000000000002, 20000.0, 46.0, 1357.7531304674194, 756.9349985001364 - 0.2, 20000.0, 46.0, 1362.21730767056, 753.1835554377882 - 0.25, 20000.0, 46.0, 1374.3879790419714, 751.5261038595751 -0.30000000000000004, 20000.0, 46.0, 1390.680368942441, 750.5211717117642 -0.35000000000000003, 20000.0, 46.0, 1407.5097017327537, 748.7272869406224 - 0.4, 20000.0, 46.0, 1421.2912017736965, 744.7029774924166 - 0.45, 20000.0, 46.0, 1426.863179854193, 736.3148503086932 - 0.5, 20000.0, 46.0, 1425.3716010505873, 724.1971963498588 - 0.55, 20000.0, 46.0, 1416.3855168673329, 708.2923855715877 - 0.6000000000000001, 20000.0, 46.0, 1399.4739788089, 688.5427879295606 - 0.0, 20000.0, 48.0, 1524.6302693863502, 843.6603534058597 - 0.05, 20000.0, 48.0, 1481.4351672103603, 821.4829971163201 - 0.1, 20000.0, 48.0, 1458.047446663172, 806.9553391036242 -0.15000000000000002, 20000.0, 48.0, 1450.6237233413342, 798.4188139050793 - 0.2, 20000.0, 48.0, 1455.3206128413974, 794.2148560579925 - 0.25, 20000.0, 48.0, 1468.2947307599104, 792.6849000996713 -0.30000000000000004, 20000.0, 48.0, 1485.702692693423, 792.1703805674227 -0.35000000000000003, 20000.0, 48.0, 1503.701114238485, 791.012731998554 - 0.4, 20000.0, 48.0, 1518.4466109916445, 787.5533889303724 - 0.45, 20000.0, 48.0, 1524.403818510022, 779.3375289465046 - 0.5, 20000.0, 48.0, 1522.805292508476, 767.0953574453243 - 0.55, 20000.0, 48.0, 1513.1916086624149, 750.7608228715294 - 0.6000000000000001, 20000.0, 48.0, 1495.1033426472532, 730.2678736698138 - 0.0, 20000.0, 50.0, 1621.400000000094, 887.0000000000128 - 0.05, 20000.0, 50.0, 1575.6500000000444, 863.3062500000073 - 0.1, 20000.0, 50.0, 1550.9000000000153, 848.0000000000042 -0.15000000000000002, 20000.0, 50.0, 1543.0750000000023, 839.268750000003 - 0.2, 20000.0, 50.0, 1548.100000000002, 835.3000000000025 - 0.25, 20000.0, 50.0, 1561.9000000000108, 834.2812500000017 -0.30000000000000004, 20000.0, 50.0, 1580.4000000000256, 834.4000000000001 -0.35000000000000003, 20000.0, 50.0, 1599.5250000000422, 833.8437499999965 - 0.4, 20000.0, 50.0, 1615.2000000000564, 830.7999999999898 - 0.45, 20000.0, 50.0, 1621.568750000054, 822.5437499999989 - 0.5, 20000.0, 50.0, 1619.900000000097, 810.0000000000076 - 0.55, 20000.0, 50.0, 1609.6812500001483, 793.1812500000225 - 0.6000000000000001, 20000.0, 50.0, 1590.4000000002065, 772.1000000000441 - 0.0, 23000.0, 20.0, 150.1999999999998, 342.10000000000014 - 0.05, 23000.0, 20.0, 152.05624999999986, 341.85625000000005 - 0.1, 23000.0, 20.0, 153.7999999999999, 339.29999999999995 -0.15000000000000002, 23000.0, 20.0, 155.46874999999994, 334.64374999999995 - 0.2, 23000.0, 20.0, 157.09999999999997, 328.09999999999997 - 0.25, 23000.0, 20.0, 158.73125, 319.88125 -0.30000000000000004, 23000.0, 20.0, 160.40000000000003, 310.20000000000005 -0.35000000000000003, 23000.0, 20.0, 162.14375000000007, 299.26875000000007 - 0.4, 23000.0, 20.0, 164.00000000000014, 287.30000000000007 - 0.45, 23000.0, 20.0, 166.23750000000007, 274.55 - 0.5, 23000.0, 20.0, 168.2000000000001, 261.1000000000002 - 0.55, 23000.0, 20.0, 169.46250000000018, 247.07500000000027 - 0.6000000000000001, 23000.0, 20.0, 169.6000000000002, 232.60000000000036 - 0.0, 23000.0, 22.0, 240.8607513349636, 351.2565870293523 - 0.05, 23000.0, 22.0, 243.68161070005044, 351.11352610580343 - 0.1, 23000.0, 22.0, 246.37139546426786, 349.0366790909985 -0.15000000000000002, 23000.0, 22.0, 248.9814945700196, 345.1932594080852 - 0.2, 23000.0, 22.0, 251.56329695970936, 339.75048048021097 - 0.25, 23000.0, 22.0, 254.16819157574088, 332.87555573052344 -0.30000000000000004, 23000.0, 22.0, 256.84756736051787, 324.7356985821703 -0.35000000000000003, 23000.0, 22.0, 259.6528132564438, 315.498122458299 - 0.4, 23000.0, 22.0, 262.6353182059227, 305.3300407820574 - 0.45, 23000.0, 22.0, 266.20325901535244, 294.4797260058681 - 0.5, 23000.0, 22.0, 269.337661035158, 282.8712144650562 - 0.55, 23000.0, 22.0, 271.3763374797623, 270.50960152422385 - 0.6000000000000001, 23000.0, 22.0, 271.6571015635862, 257.39998254797246 - 0.0, 23000.0, 24.0, 330.260375667479, 370.6781823540402 - 0.05, 23000.0, 24.0, 334.46643035002387, 371.23369357975537 - 0.1, 23000.0, 24.0, 338.38569773213374, 369.9263726010437 -0.15000000000000002, 23000.0, 24.0, 342.1076222850101, 366.9213193693453 - 0.2, 23000.0, 24.0, 345.72164847985505, 362.38363383610056 - 0.25, 23000.0, 24.0, 349.31722078787044, 356.4784159527497 -0.30000000000000004, 23000.0, 24.0, 352.98378368025817, 349.370765670733 -0.35000000000000003, 23000.0, 24.0, 356.8107816282202, 341.2257829414908 - 0.4, 23000.0, 24.0, 360.8876591029582, 332.20856771646316 - 0.45, 23000.0, 24.0, 365.8131283809891, 322.63474946173244 - 0.5, 23000.0, 24.0, 370.14883051758136, 312.2178395848214 - 0.55, 23000.0, 24.0, 372.9656743733285, 300.8218790078994 - 0.6000000000000001, 23000.0, 24.0, 373.3345688088191, 288.310908653134 - 0.0, 23000.0, 26.0, 419.2396243325111, 397.59148416405276 - 0.05, 23000.0, 26.0, 424.9710696499718, 399.017098000806 - 0.1, 23000.0, 26.0, 430.21430226786566, 398.5077265655896 -0.15000000000000002, 23000.0, 26.0, 435.10487771499106, 396.2452496265629 - 0.2, 23000.0, 26.0, 439.7783515201463, 392.4115469518848 - 0.25, 23000.0, 26.0, 444.3702792121296, 387.1884983097144 -0.30000000000000004, 23000.0, 26.0, 449.01621631973927, 380.75798346821074 -0.35000000000000003, 23000.0, 26.0, 453.8517183717735, 373.30188219553287 - 0.4, 23000.0, 26.0, 459.01234089703064, 365.0020742598397 - 0.45, 23000.0, 26.0, 465.30511823895034, 356.2711599146632 - 0.5, 23000.0, 26.0, 470.85116948242666, 346.59885747205834 - 0.55, 23000.0, 26.0, 474.4430925270151, 335.70560572946255 - 0.6000000000000001, 23000.0, 26.0, 474.8734852722604, 323.31184348430855 - 0.0, 23000.0, 28.0, 508.99923019921573, 429.1562030422335 - 0.05, 23000.0, 28.0, 515.9979230135891, 430.92395182328283 - 0.1, 23000.0, 28.0, 522.3895814940595, 430.7948951069495 -0.15000000000000002, 23000.0, 28.0, 528.3415624863584, 428.94762798957197 - 0.2, 23000.0, 28.0, 534.0212228362163, 425.5607455674887 - 0.25, 23000.0, 28.0, 539.5959193893656, 420.81284293703834 -0.30000000000000004, 23000.0, 28.0, 545.2330089915379, 414.88251519455923 -0.35000000000000003, 23000.0, 28.0, 551.0998484884637, 407.9483574363897 - 0.4, 23000.0, 28.0, 557.3637947258757, 400.18896475886845 - 0.45, 23000.0, 28.0, 565.0129582230677, 392.0709491623259 - 0.5, 23000.0, 28.0, 571.7524348050806, 382.9088550311265 - 0.55, 23000.0, 28.0, 576.108073970518, 372.305243653628 - 0.6000000000000001, 23000.0, 28.0, 576.6057252179851, 359.862676318187 - 0.0, 23000.0, 30.0, 599.3000000000137, 462.7999999999999 - 0.05, 23000.0, 30.0, 607.3812500000088, 464.7750000000001 - 0.1, 23000.0, 30.0, 614.8000000000048, 464.90000000000003 -0.15000000000000002, 23000.0, 30.0, 621.7437500000023, 463.34999999999985 - 0.2, 23000.0, 30.0, 628.4, 460.29999999999956 - 0.25, 23000.0, 30.0, 634.9562499999985, 455.92499999999933 -0.30000000000000004, 23000.0, 30.0, 641.5999999999975, 450.399999999999 -0.35000000000000003, 23000.0, 30.0, 648.5187499999972, 443.89999999999895 - 0.4, 23000.0, 30.0, 655.899999999997, 436.59999999999906 - 0.45, 23000.0, 30.0, 664.8874999999989, 429.01250000000107 - 0.5, 23000.0, 30.0, 672.7999999999996, 420.3000000000025 - 0.55, 23000.0, 30.0, 677.9125000000008, 409.9625000000044 - 0.6000000000000001, 23000.0, 30.0, 678.5000000000033, 397.50000000000654 - 0.0, 23000.0, 32.0, 688.7665610741473, 494.467867071847 - 0.05, 23000.0, 32.0, 698.2464577797718, 497.9048571611944 - 0.1, 23000.0, 32.0, 706.9174139639682, 499.12552419117674 -0.15000000000000002, 23000.0, 32.0, 715.0021875028359, 498.3761472549833 - 0.2, 23000.0, 32.0, 722.723536272474, 495.9030054458035 - 0.25, 23000.0, 32.0, 730.3042181489817, 491.95237785682656 -0.30000000000000004, 23000.0, 32.0, 737.9669910084581, 486.7705435812418 -0.35000000000000003, 23000.0, 32.0, 745.9346127270028, 480.6037817122385 - 0.4, 23000.0, 32.0, 754.4298411807148, 473.69837134300604 - 0.45, 23000.0, 32.0, 764.7850635694888, 466.73788320648225 - 0.5, 23000.0, 32.0, 773.8941497980451, 458.65672147660655 - 0.55, 23000.0, 32.0, 779.7605990949107, 448.8265819670628 - 0.6000000000000001, 23000.0, 32.0, 780.3879106886069, 436.61916049153706 - 0.0, 23000.0, 34.0, 780.9336284544793, 530.1559180140465 - 0.05, 23000.0, 34.0, 790.5202412885309, 533.5461910380512 - 0.1, 23000.0, 34.0, 799.5925252423191, 534.8446415045908 -0.15000000000000002, 23000.0, 34.0, 808.320884237715, 534.284598221308 - 0.2, 23000.0, 34.0, 816.8757221965899, 532.0993899958454 - 0.25, 23000.0, 34.0, 825.4274430408146, 528.5223456358459 -0.30000000000000004, 23000.0, 34.0, 834.1464506922601, 523.7867939489525 -0.35000000000000003, 23000.0, 34.0, 843.203149072798, 518.1260637428082 - 0.4, 23000.0, 34.0, 852.7679421042992, 511.773483825055 - 0.45, 23000.0, 34.0, 864.099036674467, 505.4268481099386 - 0.5, 23000.0, 34.0, 874.1034278077036, 497.92609008530644 - 0.55, 23000.0, 34.0, 880.7759134942564, 488.5756083456089 - 0.6000000000000001, 23000.0, 34.0, 882.1112917243643, 476.67980148529523 - 0.0, 23000.0, 36.0, 875.2790231074816, 570.3182541883718 - 0.05, 23000.0, 36.0, 883.9654275872275, 571.8608990359577 - 0.1, 23000.0, 36.0, 892.7639303132937, 572.0399970414845 -0.15000000000000002, 23000.0, 36.0, 901.7285959435291, 570.9697501307603 - 0.2, 23000.0, 36.0, 910.9134891357825, 568.7643602295922 - 0.25, 23000.0, 36.0, 920.3726745479036, 565.5380292637874 -0.30000000000000004, 23000.0, 36.0, 930.1602168377412, 561.404959159153 -0.35000000000000003, 23000.0, 36.0, 940.3301806631449, 556.4793518414969 - 0.4, 23000.0, 36.0, 950.9366306819636, 550.8754092366255 - 0.45, 23000.0, 36.0, 962.978139294552, 545.1205745676223 - 0.5, 23000.0, 36.0, 973.6752479313067, 538.0893258684906 - 0.55, 23000.0, 36.0, 981.1930057651642, 529.0693824705112 - 0.6000000000000001, 23000.0, 36.0, 983.6964619690405, 517.3484637049607 - 0.0, 23000.0, 38.0, 960.8048697679887, 603.5066977336838 - 0.05, 23000.0, 38.0, 972.8667969941099, 606.6915342694939 - 0.1, 23000.0, 38.0, 984.1772923485102, 608.1740255668266 -0.15000000000000002, 23000.0, 38.0, 994.9748935211019, 608.127065504498 - 0.2, 23000.0, 38.0, 1005.4981382017955, 606.7235479613252 - 0.25, 23000.0, 38.0, 1015.9855640805022, 604.1363668161243 -0.30000000000000004, 23000.0, 38.0, 1026.6757088471325, 600.5384159477128 -0.35000000000000003, 23000.0, 38.0, 1037.8071101915975, 596.1025892349065 - 0.4, 23000.0, 38.0, 1049.6183058038089, 591.0017805565222 - 0.45, 23000.0, 38.0, 1063.7646240714666, 585.9623705734406 - 0.5, 23000.0, 38.0, 1076.234230591073, 579.4967928182757 - 0.55, 23000.0, 38.0, 1084.432081656891, 570.6709676056967 - 0.6000000000000001, 23000.0, 38.0, 1085.7631335632007, 558.5508152503771 - 0.0, 23000.0, 40.0, 1049.29999999997, 640.799999999983 - 0.05, 23000.0, 40.0, 1063.1124999999845, 644.399999999992 - 0.1, 23000.0, 40.0, 1075.899999999994, 646.2999999999976 -0.15000000000000002, 23000.0, 40.0, 1087.9624999999996, 646.6750000000008 - 0.2, 23000.0, 40.0, 1099.6000000000017, 645.7000000000012 - 0.25, 23000.0, 40.0, 1111.1125000000004, 643.5499999999998 -0.30000000000000004, 23000.0, 40.0, 1122.7999999999968, 640.3999999999966 -0.35000000000000003, 23000.0, 40.0, 1134.9624999999896, 636.4249999999926 - 0.4, 23000.0, 40.0, 1147.8999999999808, 631.7999999999873 - 0.45, 23000.0, 40.0, 1163.5375000000113, 627.3250000000024 - 0.5, 23000.0, 40.0, 1177.3000000000216, 621.3000000000051 - 0.55, 23000.0, 40.0, 1186.2375000000368, 612.6500000000095 - 0.6000000000000001, 23000.0, 40.0, 1187.400000000059, 600.300000000016 - 0.0, 23000.0, 42.0, 1139.4644383782172, 678.5699169164062 - 0.05, 23000.0, 42.0, 1154.3663707687244, 682.6578809183944 - 0.1, 23000.0, 42.0, 1168.1734447744057, 685.0186630191247 -0.15000000000000002, 23000.0, 42.0, 1181.209789918698, 685.8328574453171 - 0.2, 23000.0, 42.0, 1193.799535725033, 685.2810584236931 - 0.25, 23000.0, 42.0, 1206.2668117168466, 683.5438601809733 -0.30000000000000004, 23000.0, 42.0, 1218.935747417573, 680.801856943878 -0.35000000000000003, 23000.0, 42.0, 1232.130472350647, 677.2356429391285 - 0.4, 23000.0, 42.0, 1246.1751160395017, 673.0258123934453 - 0.45, 23000.0, 42.0, 1263.1616643187158, 668.9986535655495 - 0.5, 23000.0, 42.0, 1278.1106777782902, 663.3976785861705 - 0.55, 23000.0, 42.0, 1287.810573319357, 655.1120936180422 - 0.6000000000000001, 23000.0, 42.0, 1289.0497678430536, 643.0311048238965 - 0.0, 23000.0, 44.0, 1228.2540050938853, 713.6568606027433 - 0.05, 23000.0, 44.0, 1244.9281860710244, 719.6347547164662 - 0.1, 23000.0, 44.0, 1260.232827959531, 723.3778927743012 -0.15000000000000002, 23000.0, 44.0, 1274.5504870686264, 725.1643026613965 - 0.2, 23000.0, 44.0, 1288.2637197075292, 725.2720122628992 - 0.25, 23000.0, 44.0, 1301.7550821854607, 723.9790494639572 -0.30000000000000004, 23000.0, 44.0, 1315.407130811641, 721.5634421497175 -0.35000000000000003, 23000.0, 44.0, 1329.6024218952912, 718.3032182053282 - 0.4, 23000.0, 44.0, 1344.7235117456296, 714.4764055159367 - 0.45, 23000.0, 44.0, 1363.094366821554, 711.1548482421821 - 0.5, 23000.0, 44.0, 1379.2733129832893, 706.2351254427743 - 0.55, 23000.0, 44.0, 1389.7600862407544, 698.4076324519381 - 0.6000000000000001, 23000.0, 44.0, 1391.0544226038567, 686.3627646038852 - 0.0, 23000.0, 46.0, 1318.2329978670407, 753.6650350581559 - 0.05, 23000.0, 46.0, 1335.9755114008221, 759.5964943530503 - 0.1, 23000.0, 46.0, 1352.2949179768239, 763.363357923464 -0.15000000000000002, 23000.0, 46.0, 1367.5937873193118, 765.2495157458948 - 0.2, 23000.0, 46.0, 1382.274689152554, 765.53885779684 - 0.25, 23000.0, 46.0, 1396.7401932008158, 764.5152740527976 -0.30000000000000004, 23000.0, 46.0, 1411.3928691883643, 762.4626544902651 -0.35000000000000003, 23000.0, 46.0, 1426.6352868394656, 759.6648890857405 - 0.4, 23000.0, 46.0, 1442.870015878386, 756.4058678157204 - 0.45, 23000.0, 46.0, 1462.5773969904628, 753.881163041357 - 0.5, 23000.0, 46.0, 1479.9266870167266, 749.639617585162 - 0.55, 23000.0, 46.0, 1491.1649137592651, 742.1417566542851 - 0.6000000000000001, 23000.0, 46.0, 1492.5391050201754, 729.8481054558844 - 0.0, 23000.0, 48.0, 1408.7940576547987, 795.7452188296787 - 0.05, 23000.0, 48.0, 1427.5758647374741, 800.9190114958927 - 0.1, 23000.0, 48.0, 1444.8865367279122, 804.2997215988066 -0.15000000000000002, 23000.0, 48.0, 1461.1483925668688, 806.112070576365 - 0.2, 23000.0, 48.0, 1476.7837511951016, 806.5807798665122 - 0.25, 23000.0, 48.0, 1492.2149315533668, 805.9305709071931 -0.30000000000000004, 23000.0, 48.0, 1507.8642525824212, 804.3861651363522 -0.35000000000000003, 23000.0, 48.0, 1524.154033223022, 802.1722839919347 - 0.4, 23000.0, 48.0, 1541.506592415925, 799.5136489118844 - 0.45, 23000.0, 48.0, 1562.5541899090113, 797.5540272914018 - 0.5, 23000.0, 48.0, 1581.0893222217271, 793.7610026966684 - 0.55, 23000.0, 48.0, 1593.114426680678, 786.5212046511166 - 0.6000000000000001, 23000.0, 48.0, 1594.6319406124483, 774.221262678181 - 0.0, 23000.0, 50.0, 1498.4000000000156, 835.2000000000154 - 0.05, 23000.0, 50.0, 1518.4375000000089, 840.7687500000052 - 0.1, 23000.0, 50.0, 1536.9000000000044, 844.5999999999996 -0.15000000000000002, 23000.0, 50.0, 1554.2375000000006, 846.9062499999977 - 0.2, 23000.0, 50.0, 1570.8999999999962, 847.8999999999988 - 0.25, 23000.0, 50.0, 1587.3374999999896, 847.7937500000023 -0.30000000000000004, 23000.0, 50.0, 1603.9999999999795, 846.8000000000071 -0.35000000000000003, 23000.0, 50.0, 1621.3374999999648, 845.1312500000129 - 0.4, 23000.0, 50.0, 1639.7999999999433, 843.0000000000188 - 0.45, 23000.0, 50.0, 1662.1874999999948, 841.5687500000182 - 0.5, 23000.0, 50.0, 1681.9000000000074, 838.2000000000317 - 0.55, 23000.0, 50.0, 1694.6875000000268, 831.2062500000482 - 0.6000000000000001, 23000.0, 50.0, 1696.3000000000534, 818.9000000000676 - 0.0, 25000.0, 20.0, 151.59999999999982, 398.89999999999964 - 0.05, 25000.0, 20.0, 153.3249999999999, 398.0874999999998 - 0.1, 25000.0, 20.0, 154.99999999999994, 394.3999999999998 -0.15000000000000002, 25000.0, 20.0, 156.64999999999998, 388.1124999999999 - 0.2, 25000.0, 20.0, 158.29999999999998, 379.49999999999994 - 0.25, 25000.0, 20.0, 159.97499999999997, 368.83750000000003 -0.30000000000000004, 25000.0, 20.0, 161.7, 356.4 -0.35000000000000003, 25000.0, 20.0, 163.49999999999997, 342.46250000000003 - 0.4, 25000.0, 20.0, 165.4, 327.30000000000007 - 0.45, 25000.0, 20.0, 167.4375, 311.1875000000001 - 0.5, 25000.0, 20.0, 169.60000000000008, 294.40000000000026 - 0.55, 25000.0, 20.0, 171.8875000000001, 277.2125000000005 - 0.6000000000000001, 25000.0, 20.0, 174.30000000000018, 259.9000000000007 - 0.0, 25000.0, 22.0, 241.95125704127386, 385.8578449206611 - 0.05, 25000.0, 22.0, 245.14362131919492, 385.52024975697776 - 0.1, 25000.0, 22.0, 248.09498664273056, 382.88285506326974 -0.15000000000000002, 25000.0, 22.0, 250.8772925742111, 378.1556221299986 - 0.2, 25000.0, 22.0, 253.56247867596676, 371.54851224762547 - 0.25, 25000.0, 22.0, 256.2224845103278, 363.27148670661177 -0.30000000000000004, 25000.0, 22.0, 258.9292496396246, 353.53450679741826 -0.35000000000000003, 25000.0, 22.0, 261.7547136261871, 342.54753381050676 - 0.4, 25000.0, 22.0, 264.7708160323461, 330.5205290363385 - 0.45, 25000.0, 22.0, 268.1218756657849, 317.6538775540623 - 0.5, 25000.0, 22.0, 271.6626943527759, 304.186269288079 - 0.55, 25000.0, 22.0, 275.320453164946, 290.34681795148015 - 0.6000000000000001, 25000.0, 22.0, 279.0223331739218, 276.3646372573555 - 0.0, 25000.0, 24.0, 332.7358087908592, 394.7563405981032 - 0.05, 25000.0, 24.0, 337.02255396193095, 394.9207783693084 - 0.1, 25000.0, 24.0, 341.0115654294547, 393.064953831547 -0.15000000000000002, 25000.0, 24.0, 344.7955607212173, 389.3698318564053 - 0.2, 25000.0, 24.0, 348.46725736500616, 384.0163773154692 - 0.25, 25000.0, 24.0, 352.1193728886085, 377.1855550803249 -0.30000000000000004, 25000.0, 24.0, 355.8446248198115, 369.05833002255827 -0.35000000000000003, 25000.0, 24.0, 359.7357306864027, 359.8156670137558 - 0.4, 25000.0, 24.0, 363.8854080161693, 349.638530925503 - 0.45, 25000.0, 24.0, 368.4771878328935, 338.7053440169799 - 0.5, 25000.0, 24.0, 373.3313471763893, 327.20469899699947 - 0.55, 25000.0, 24.0, 378.35897658247416, 315.32264596197814 - 0.6000000000000001, 25000.0, 24.0, 383.4711665869615, 303.24523500832737 - 0.0, 25000.0, 26.0, 423.5447320198051, 418.0159138152125 - 0.05, 25000.0, 26.0, 428.84280094506863, 418.7011821031492 - 0.1, 25000.0, 26.0, 433.820650894813, 417.4556250681892 -0.15000000000000002, 25000.0, 26.0, 438.584557581118, 414.45373051781286 - 0.2, 25000.0, 26.0, 443.24079671606216, 409.8699862595003 - 0.25, 25000.0, 26.0, 447.8956440117248, 403.87888010073203 -0.30000000000000004, 25000.0, 26.0, 452.65537518018533, 396.65489984898835 -0.35000000000000003, 25000.0, 26.0, 457.62626593352246, 388.3725333117494 - 0.4, 25000.0, 26.0, 462.9145919838156, 379.2062682964957 - 0.45, 25000.0, 26.0, 468.7228121671103, 369.3436217028667 - 0.5, 25000.0, 26.0, 474.86865282361526, 358.91999406188114 - 0.55, 25000.0, 26.0, 481.2660234175299, 348.0838149967373 - 0.6000000000000001, 25000.0, 26.0, 487.82883341304097, 336.9835141306233 - 0.0, 25000.0, 28.0, 513.6199636951204, 446.5656916816458 - 0.05, 25000.0, 28.0, 520.3245496631727, 447.7434877567819 - 0.1, 25000.0, 28.0, 526.5590898932503, 447.0346188211878 -0.15000000000000002, 25000.0, 28.0, 532.4663437017956, 444.6090884731088 - 0.2, 25000.0, 28.0, 538.1890704052515, 440.6369003107903 - 0.25, 25000.0, 28.0, 543.8700293200608, 435.28805793247767 -0.30000000000000004, 25000.0, 28.0, 549.6519797626655, 428.73256493641634 -0.35000000000000003, 25000.0, 28.0, 555.6776810495091, 421.14042492085144 - 0.4, 25000.0, 28.0, 562.0898924970343, 412.6816414840287 - 0.45, 25000.0, 28.0, 569.1636346707489, 403.5518009128527 - 0.5, 25000.0, 28.0, 576.6448831399063, 393.8441587395746 - 0.55, 25000.0, 28.0, 584.411874722831, 383.677553185092 - 0.6000000000000001, 25000.0, 28.0, 592.3428462378449, 373.1708224703091 - 0.0, 25000.0, 30.0, 603.6000000000109, 477.3000000000175 - 0.05, 25000.0, 30.0, 611.8312500000076, 479.0500000000102 - 0.1, 25000.0, 30.0, 619.4000000000045, 478.9000000000048 -0.15000000000000002, 25000.0, 30.0, 626.4937500000018, 477.0250000000015 - 0.2, 25000.0, 30.0, 633.2999999999995, 473.59999999999997 - 0.25, 25000.0, 30.0, 640.0062499999977, 468.80000000000035 -0.30000000000000004, 25000.0, 30.0, 646.7999999999962, 462.8000000000023 -0.35000000000000003, 25000.0, 30.0, 653.8687499999953, 455.77500000000566 - 0.4, 25000.0, 30.0, 661.3999999999944, 447.9000000000106 - 0.45, 25000.0, 30.0, 669.7625000000022, 439.38749999999516 - 0.5, 25000.0, 30.0, 678.6000000000051, 430.2999999999943 - 0.55, 25000.0, 30.0, 687.7375000000093, 420.7374999999944 - 0.6000000000000001, 25000.0, 30.0, 697.0000000000143, 410.79999999999575 - 0.0, 25000.0, 32.0, 695.1820221528478, 508.44239304693116 - 0.05, 25000.0, 32.0, 704.2874031562056, 511.25600422774704 - 0.1, 25000.0, 32.0, 712.7380781285342, 511.93588990275197 -0.15000000000000002, 25000.0, 32.0, 720.7317621963222, 510.70825021223425 - 0.2, 25000.0, 32.0, 728.4661704860584, 507.79928529648197 - 0.25, 25000.0, 32.0, 736.1390181242319, 503.43519529578356 -0.30000000000000004, 25000.0, 32.0, 743.9480202373309, 497.84218035042727 -0.35000000000000003, 25000.0, 32.0, 752.0908919518446, 491.2464406007012 - 0.4, 25000.0, 32.0, 760.765348394262, 483.87417618689364 - 0.45, 25000.0, 32.0, 770.357515017709, 476.0137487627696 - 0.5, 25000.0, 32.0, 780.4998759687913, 467.7048739281892 - 0.55, 25000.0, 32.0, 791.0133257207673, 459.0494287964895 - 0.6000000000000001, 25000.0, 32.0, 801.7187587468868, 450.1492904810076 - 0.0, 25000.0, 34.0, 786.5108253280989, 542.500832704856 - 0.05, 25000.0, 34.0, 796.496046953423, 545.5403960165772 - 0.1, 25000.0, 34.0, 805.8395615323308, 546.4856012991752 -0.15000000000000002, 25000.0, 34.0, 814.7471497981593, 545.568600147564 - 0.2, 25000.0, 34.0, 823.4245924842445, 543.0215441566559 - 0.25, 25000.0, 34.0, 832.0776703239227, 539.0765849213642 -0.30000000000000004, 25000.0, 34.0, 840.9121640505306, 533.9658740366024 -0.35000000000000003, 25000.0, 34.0, 850.1338543974036, 527.9215630972831 - 0.4, 25000.0, 34.0, 859.948522097879, 521.1758036983193 - 0.45, 25000.0, 34.0, 870.7517120575288, 514.0340418454816 - 0.5, 25000.0, 34.0, 882.1799124929983, 506.5085459011072 - 0.55, 25000.0, 34.0, 894.0593757931775, 498.68487863838607 - 0.6000000000000001, 25000.0, 34.0, 906.2163543469519, 490.64860283051075 - 0.0, 25000.0, 36.0, 877.1807430555197, 579.3247401600911 - 0.05, 25000.0, 36.0, 888.2258781266335, 581.6296263702412 - 0.1, 25000.0, 36.0, 898.5925098464586, 582.2350219556401 -0.15000000000000002, 25000.0, 36.0, 908.502272255664, 581.3140019056958 - 0.2, 25000.0, 36.0, 918.1767993949203, 579.0396412098165 - 0.25, 25000.0, 36.0, 927.8377253048972, 575.5850148574101 -0.30000000000000004, 25000.0, 36.0, 937.7066840262646, 571.1231978378848 -0.35000000000000003, 25000.0, 36.0, 948.005309599693, 565.8272651406484 - 0.4, 25000.0, 36.0, 958.9552360658516, 559.8702917551093 - 0.45, 25000.0, 36.0, 970.9788417742836, 553.4895509863871 - 0.5, 25000.0, 36.0, 983.6955278390687, 546.6655228767355 - 0.55, 25000.0, 36.0, 996.9254396831798, 539.4428857841051 - 0.6000000000000001, 25000.0, 36.0, 1010.4887227295783, 531.8663180664545 - 0.0, 25000.0, 38.0, 969.5296526832667, 613.1493488560158 - 0.05, 25000.0, 38.0, 981.1988817828051, 616.5100610016673 - 0.1, 25000.0, 38.0, 992.2647667886813, 618.0669520571341 -0.15000000000000002, 25000.0, 38.0, 1002.9504325345387, 618.0028559761815 - 0.2, 25000.0, 38.0, 1013.4790038540203, 616.5006067125747 - 0.25, 25000.0, 38.0, 1024.0736055807704, 613.7430382200785 -0.30000000000000004, 25000.0, 38.0, 1034.957362548432, 609.9129844524584 -0.35000000000000003, 25000.0, 38.0, 1046.353399590649, 605.1932793634794 - 0.4, 25000.0, 38.0, 1058.4848415410652, 599.7667569069067 - 0.45, 25000.0, 38.0, 1071.7952517995625, 593.8845991307642 - 0.5, 25000.0, 38.0, 1085.8464395010785, 587.5245957060481 - 0.55, 25000.0, 38.0, 1100.4206523468429, 580.7328843980207 - 0.6000000000000001, 25000.0, 38.0, 1115.3001380380633, 573.5556029719411 - 0.0, 25000.0, 40.0, 1059.49999999999, 650.5999999999792 - 0.05, 25000.0, 40.0, 1072.5812499999954, 654.1937499999875 - 0.1, 25000.0, 40.0, 1084.8999999999987, 655.9999999999937 -0.15000000000000002, 25000.0, 40.0, 1096.7187500000007, 656.206249999998 - 0.2, 25000.0, 40.0, 1108.3000000000018, 655.0000000000009 - 0.25, 25000.0, 40.0, 1119.9062500000011, 652.5687500000025 -0.30000000000000004, 25000.0, 40.0, 1131.7999999999993, 649.100000000003 -0.35000000000000003, 25000.0, 40.0, 1144.2437499999958, 644.7812500000031 - 0.4, 25000.0, 40.0, 1157.499999999991, 639.8000000000025 - 0.45, 25000.0, 40.0, 1172.0875000000092, 634.3999999999983 - 0.5, 25000.0, 40.0, 1187.500000000017, 628.6000000000013 - 0.55, 25000.0, 40.0, 1203.4875000000288, 622.4750000000071 - 0.6000000000000001, 25000.0, 40.0, 1219.8000000000438, 616.1000000000158 - 0.0, 25000.0, 42.0, 1150.1595171493389, 687.2978643429593 - 0.05, 25000.0, 42.0, 1164.3987232852676, 691.6048687166581 - 0.1, 25000.0, 42.0, 1177.8017641434783, 694.043546745652 -0.15000000000000002, 25000.0, 42.0, 1190.6538532809004, 694.817090159474 - 0.2, 25000.0, 42.0, 1203.2402042544677, 694.1286906876581 - 0.25, 25000.0, 42.0, 1215.8460306211095, 692.1815400597375 -0.30000000000000004, 25000.0, 42.0, 1228.7565459377572, 689.178830005246 -0.35000000000000003, 25000.0, 42.0, 1242.2569637613421, 685.3237522537161 - 0.4, 25000.0, 42.0, 1256.6324976487952, 680.8194985346819 - 0.45, 25000.0, 42.0, 1272.4423165895464, 675.900585999929 - 0.5, 25000.0, 42.0, 1289.1497678430135, 670.6762301122243 - 0.55, 25000.0, 42.0, 1306.4921541011058, 665.2869717565802 - 0.6000000000000001, 25000.0, 42.0, 1324.2067780557359, 659.8733518180126 - 0.0, 25000.0, 44.0, 1241.9864133423584, 724.296458614609 - 0.05, 25000.0, 44.0, 1257.0083864979183, 729.5978892605846 - 0.1, 25000.0, 44.0, 1271.2364040936777, 732.8033392600573 -0.15000000000000002, 25000.0, 44.0, 1284.9593884658823, 734.1667777861402 - 0.2, 25000.0, 44.0, 1298.4662619507776, 733.9421740119484 - 0.25, 25000.0, 44.0, 1312.0459468846086, 732.3834971105961 -0.30000000000000004, 25000.0, 44.0, 1325.9873656036211, 729.7447162551969 -0.35000000000000003, 25000.0, 44.0, 1340.5794404440603, 726.2798006188658 - 0.4, 25000.0, 44.0, 1356.1110937421709, 722.2427193747169 - 0.45, 25000.0, 44.0, 1373.1487145394524, 717.970546707151 - 0.5, 25000.0, 44.0, 1391.1488250564187, 713.4679367554318 - 0.55, 25000.0, 44.0, 1409.845414218853, 708.8226486701092 - 0.6000000000000001, 25000.0, 44.0, 1428.9724709525308, 704.1224416017326 - 0.0, 25000.0, 46.0, 1332.4732076794496, 763.7287035873644 - 0.05, 25000.0, 46.0, 1348.6274141069825, 769.0971857530686 - 0.1, 25000.0, 46.0, 1363.9243885415851, 772.4054561074395 -0.15000000000000002, 25000.0, 46.0, 1378.6746848285457, 773.9222454319282 - 0.2, 25000.0, 46.0, 1393.1888568131533, 773.9162845079862 - 0.25, 25000.0, 46.0, 1407.7774583406963, 772.6563041170642 -0.30000000000000004, 25000.0, 46.0, 1422.7510432564625, 770.411035040614 -0.35000000000000003, 25000.0, 46.0, 1438.4201654057415, 767.4492080600861 - 0.4, 25000.0, 46.0, 1455.0953786338225, 764.0395539569327 - 0.45, 25000.0, 46.0, 1473.386335000265, 760.6215557481668 - 0.5, 25000.0, 46.0, 1492.7062937075318, 756.9516875085569 - 0.55, 25000.0, 46.0, 1512.767612172347, 752.9571755484434 - 0.6000000000000001, 25000.0, 46.0, 1533.2826478114403, 748.5652461781613 - 0.0, 25000.0, 48.0, 1422.4154131333469, 808.3092865912829 - 0.05, 25000.0, 48.0, 1440.2041724674991, 811.55359879396 - 0.1, 25000.0, 48.0, 1456.90009287839, 813.5714023857277 -0.15000000000000002, 25000.0, 48.0, 1472.8667421506711, 814.4911560142524 - 0.2, 25000.0, 48.0, 1488.4676880689935, 814.4413183272009 - 0.25, 25000.0, 48.0, 1504.0664984180103, 813.5503479722398 -0.30000000000000004, 25000.0, 48.0, 1520.026740982374, 811.9467035970358 -0.35000000000000003, 25000.0, 48.0, 1536.7119835467356, 809.758843849256 - 0.4, 25000.0, 48.0, 1554.4857938957473, 807.1152273765667 - 0.45, 25000.0, 48.0, 1574.0643454364542, 804.1828283550147 - 0.5, 25000.0, 48.0, 1594.7533890863838, 800.9745588471451 - 0.55, 25000.0, 48.0, 1616.2112813854876, 797.5418464438903 - 0.6000000000000001, 25000.0, 48.0, 1638.0963788736972, 793.9361187361783 - 0.0, 25000.0, 50.0, 1513.3999999999928, 842.5000000000693 - 0.05, 25000.0, 50.0, 1532.1499999999935, 848.3125000000408 - 0.1, 25000.0, 50.0, 1549.7999999999959, 852.3000000000205 -0.15000000000000002, 25000.0, 50.0, 1566.7249999999979, 854.6875000000069 - 0.2, 25000.0, 50.0, 1583.2999999999977, 855.6999999999992 - 0.25, 25000.0, 50.0, 1599.8999999999953, 855.5624999999956 -0.30000000000000004, 25000.0, 50.0, 1616.8999999999894, 854.4999999999947 -0.35000000000000003, 25000.0, 50.0, 1634.6749999999786, 852.7374999999953 - 0.4, 25000.0, 50.0, 1653.5999999999626, 850.4999999999959 - 0.45, 25000.0, 50.0, 1674.4125000000208, 848.1125000000059 - 0.5, 25000.0, 50.0, 1696.4000000000487, 845.5000000000186 - 0.55, 25000.0, 50.0, 1719.2125000000883, 842.6875000000389 - 0.6000000000000001, 25000.0, 50.0, 1742.50000000014, 839.7000000000685 diff --git a/aviary/models/engines/turboshaft_4465hp.csv b/aviary/models/engines/turboshaft_4465hp.csv new file mode 100644 index 0000000000..9d55e8c2ab --- /dev/null +++ b/aviary/models/engines/turboshaft_4465hp.csv @@ -0,0 +1,1784 @@ +# created 06/06/25 +# GASP-derived turboshaft engine deck converted from turboshaft_4465hp.eng +# t4max: 50.0 +# t4cruise: 45.0 +# t4climb: 50.0 +# t4flight_idle: 26.0 +# xsfc: 0.0 +# cexp: 0.0 +# sls_horsepower: 4465.2 +# freeturbine_rpm: 13820.0 +# propeller_rpm: 1020.7 +# gearbox_ratio: 0.073855 +# torque_limit: 22976.2 +# sls_corrected_airflow: 30.5 + +Mach Number (input), Altitude (ft, input), Throttle (input), Shaft Power Corrected (hp, output), Tailpipe Thrust (lbf, output), Fuel Flow (lb/h, output) + 0.0, 0.0, 0.52, 794.4, 618.4, 1035.9 + 0.0, 0.0, 0.56, 1191.6, 651.7, 1194.5 + 0.0, 0.0, 0.6, 1588.9, 684.8, 1353.8 + 0.0, 0.0, 0.64, 1986.1, 717.7, 1513.6 + 0.0, 0.0, 0.68, 2383.3, 750.4, 1674.2 + 0.0, 0.0, 0.72, 2780.5, 785.0, 1842.1 + 0.0, 0.0, 0.76, 3177.7, 820.3, 2013.2 + 0.0, 0.0, 0.8, 3574.9, 855.5, 2185.8 + 0.0, 0.0, 0.84, 3798.07, 875.278, 2283.19 + 0.0, 0.0, 0.88, 3922.95, 886.341, 2338.21 + 0.0, 0.0, 0.92, 4066.41, 898.889, 2400.84 + 0.0, 0.0, 0.96, 4263.05, 916.134, 2486.79 + 0.0, 0.0, 1.0, 4465.2, 934.3, 2577.5 + 0.0, 5000.0, 0.52, 889.4, 671.4, 1101.4 + 0.0, 5000.0, 0.56, 1334.1, 709.4, 1276.9 + 0.0, 5000.0, 0.6, 1778.8, 747.2, 1453.0 + 0.0, 5000.0, 0.64, 2223.4, 784.8, 1629.8 + 0.0, 5000.0, 0.68, 2668.1, 822.3, 1807.7 + 0.0, 5000.0, 0.72, 3112.8, 862.2, 1994.6 + 0.0, 5000.0, 0.76, 3557.5, 902.9, 2185.9 + 0.0, 5000.0, 0.8, 4002.2, 943.4, 2377.8 + 0.0, 5000.0, 0.84, 4252.81, 966.313, 2486.6 + 0.0, 5000.0, 0.88, 4392.58, 979.178, 2548.1 + 0.0, 5000.0, 0.92, 4549.91, 993.468, 2616.7 + 0.0, 5000.0, 0.96, 4762.86, 1012.79, 2709.62 + 0.0, 5000.0, 1.0, 4979.1, 1032.9, 2806.9 + 0.0, 10000.0, 0.52, 1122.0, 814.9, 1262.3 + 0.0, 10000.0, 0.56, 1682.9, 866.4, 1477.7 + 0.0, 10000.0, 0.6, 2244.0, 917.4, 1693.6 + 0.0, 10000.0, 0.64, 2804.9, 968.4, 1911.2 + 0.0, 10000.0, 0.68, 3365.9, 1019.2, 2129.8 + 0.0, 10000.0, 0.72, 3926.9, 1071.8, 2355.8 + 0.0, 10000.0, 0.76, 4487.9, 1126.3, 2588.9 + 0.0, 10000.0, 0.8, 5048.9, 1181.0, 2824.4 + 0.0, 10000.0, 0.84, 5369.34, 1212.16, 2959.35 + 0.0, 10000.0, 0.88, 5545.65, 1229.44, 3035.33 + 0.0, 10000.0, 0.92, 5721.67, 1247.22, 3114.34 + 0.0, 10000.0, 0.96, 5946.43, 1270.45, 3217.53 + 0.0, 10000.0, 1.0, 6174.2, 1294.7, 3325.2 + 0.0, 15000.0, 0.52, 1231.5, 884.2, 1375.3 + 0.0, 15000.0, 0.56, 1845.3, 936.1, 1599.8 + 0.0, 15000.0, 0.6, 2465.6, 993.1, 1820.4 + 0.0, 15000.0, 0.64, 3070.4, 1051.0, 2057.9 + 0.0, 15000.0, 0.68, 3700.5, 1104.4, 2296.1 + 0.0, 15000.0, 0.72, 4312.9, 1156.1, 2537.8 + 0.0, 15000.0, 0.76, 4919.2, 1218.9, 2778.2 + 0.0, 15000.0, 0.8, 5536.0, 1286.7, 3043.0 + 0.0, 15000.0, 0.84, 5894.92, 1325.19, 3191.83 + 0.0, 15000.0, 0.88, 6096.45, 1345.5, 3272.99 + 0.0, 15000.0, 0.92, 6290.81, 1363.73, 3359.21 + 0.0, 15000.0, 0.96, 6528.77, 1386.0, 3474.38 + 0.0, 15000.0, 1.0, 6761.7, 1408.4, 3593.6 + 0.0, 20000.0, 0.52, 1005.1, -179.8, -972.1 + 0.0, 20000.0, 0.56, 1499.4, 58.3, -409.5 + 0.0, 20000.0, 0.6, 1993.7, 236.6, 148.2 + 0.0, 20000.0, 0.64, 2524.4, 414.8, 704.9 + 0.0, 20000.0, 0.68, 3035.2, 576.6, 1190.0 + 0.0, 20000.0, 0.72, 3553.5, 724.4, 1687.5 + 0.0, 20000.0, 0.76, 4047.8, 902.5, 2282.6 + 0.0, 20000.0, 0.8, 4558.6, 1013.7, 2889.7 + 0.0, 20000.0, 0.84, 4843.66, 1055.78, 3050.75 + 0.0, 20000.0, 0.88, 4996.65, 1058.91, 2962.83 + 0.0, 20000.0, 0.92, 5169.61, 1073.75, 2931.05 + 0.0, 20000.0, 0.96, 5397.87, 1109.98, 3044.48 + 0.0, 20000.0, 1.0, 5600.1, 1136.3, 3176.2 + 0.0, 25000.0, 0.52, 1455.0, 1019.4, 1480.1 + 0.0, 25000.0, 0.56, 2278.3, 1094.7, 1873.5 + 0.0, 25000.0, 0.6, 3040.8, 1180.8, 2124.3 + 0.0, 25000.0, 0.64, 3745.3, 1266.7, 2485.1 + 0.0, 25000.0, 0.68, 4545.3, 1284.6, 2619.8 + 0.0, 25000.0, 0.72, 5200.3, 1386.9, 2950.4 + 0.0, 25000.0, 0.76, 6179.6, 1476.9, 3390.9 + 0.0, 25000.0, 0.8, 6774.1, 1477.3, 3427.5 + 0.0, 25000.0, 0.84, 7201.34, 1531.88, 3623.85 + 0.0, 25000.0, 0.88, 7515.27, 1612.05, 3889.66 + 0.0, 25000.0, 0.92, 7781.25, 1670.76, 4065.15 + 0.0, 25000.0, 0.96, 8041.83, 1697.9, 4129.51 + 0.0, 25000.0, 1.0, 8316.7, 1720.3, 4200.9 + 0.0, 30000.0, 0.52, 1587.8, 1074.7, 1549.3 + 0.0, 30000.0, 0.56, 2577.7, 1142.4, 1948.0 + 0.0, 30000.0, 0.6, 3346.8, 1253.8, 2131.4 + 0.0, 30000.0, 0.64, 4046.7, 1324.4, 2579.5 + 0.0, 30000.0, 0.68, 4934.6, 1431.0, 2947.8 + 0.0, 30000.0, 0.72, 5728.0, 1447.7, 2984.2 + 0.0, 30000.0, 0.76, 6611.5, 1658.6, 3733.2 + 0.0, 30000.0, 0.8, 7535.4, 1639.5, 3802.2 + 0.0, 30000.0, 0.84, 8005.99, 1673.25, 3948.44 + 0.0, 30000.0, 0.88, 8214.07, 1737.46, 4137.53 + 0.0, 30000.0, 0.92, 8447.3, 1800.66, 4315.37 + 0.0, 30000.0, 0.96, 8799.63, 1849.57, 4467.29 + 0.0, 30000.0, 1.0, 9171.3, 1889.1, 4618.1 + 0.0, 35000.0, 0.52, 1860.5, 1134.4, 1545.5 + 0.0, 35000.0, 0.56, 2646.7, 1179.5, 1909.4 + 0.0, 35000.0, 0.6, 3462.5, 1306.5, 2427.0 + 0.0, 35000.0, 0.64, 4472.7, 1342.0, 2586.5 + 0.0, 35000.0, 0.68, 5314.9, 1525.1, 3099.4 + 0.0, 35000.0, 0.72, 6140.7, 1569.4, 3342.5 + 0.0, 35000.0, 0.76, 7175.4, 1721.9, 3713.1 + 0.0, 35000.0, 0.8, 8001.2, 1705.9, 3886.3 + 0.0, 35000.0, 0.84, 8413.31, 1739.15, 4151.49 + 0.0, 35000.0, 0.88, 8587.82, 1801.96, 4452.92 + 0.0, 35000.0, 0.92, 8776.18, 1866.0, 4697.96 + 0.0, 35000.0, 0.96, 9079.11, 1920.19, 4867.7 + 0.0, 35000.0, 1.0, 9446.6, 1970.8, 5017.0 + 0.05, 0.0, 0.52, 794.7, 563.7, 1033.8 + 0.05, 0.0, 0.56, 1192.1, 597.1, 1192.5 + 0.05, 0.0, 0.6, 1589.5, 630.4, 1351.8 + 0.05, 0.0, 0.64, 1986.9, 663.4, 1511.6 + 0.05, 0.0, 0.68, 2384.2, 696.3, 1672.3 + 0.05, 0.0, 0.72, 2781.6, 731.1, 1840.2 + 0.05, 0.0, 0.76, 3179.0, 766.4, 2011.3 + 0.05, 0.0, 0.8, 3576.3, 801.7, 2184.0 + 0.05, 0.0, 0.84, 3799.54, 821.568, 2281.46 + 0.05, 0.0, 0.88, 3924.45, 832.708, 2336.51 + 0.05, 0.0, 0.92, 4067.9, 845.31, 2399.11 + 0.05, 0.0, 0.96, 4264.51, 862.593, 2484.97 + 0.05, 0.0, 1.0, 4466.6, 880.8, 2575.6 + 0.05, 5000.0, 0.52, 889.6, 614.6, 1099.3 + 0.05, 5000.0, 0.56, 1334.3, 652.6, 1274.6 + 0.05, 5000.0, 0.6, 1779.1, 690.7, 1450.8 + 0.05, 5000.0, 0.64, 2223.9, 728.4, 1627.6 + 0.05, 5000.0, 0.68, 2668.7, 765.9, 1805.6 + 0.05, 5000.0, 0.72, 3113.5, 806.1, 1992.6 + 0.05, 5000.0, 0.76, 3558.2, 846.9, 2183.9 + 0.05, 5000.0, 0.8, 4003.0, 887.5, 2375.8 + 0.05, 5000.0, 0.84, 4253.68, 910.502, 2484.67 + 0.05, 5000.0, 0.88, 4393.48, 923.445, 2546.26 + 0.05, 5000.0, 0.92, 4550.77, 937.786, 2614.87 + 0.05, 5000.0, 0.96, 4763.63, 957.145, 2707.71 + 0.05, 5000.0, 1.0, 4979.8, 977.3, 2804.9 + 0.05, 10000.0, 0.52, 1122.2, 753.6, 1260.2 + 0.05, 10000.0, 0.56, 1683.3, 805.3, 1475.7 + 0.05, 10000.0, 0.6, 2244.3, 856.5, 1691.6 + 0.05, 10000.0, 0.64, 2805.5, 907.7, 1909.2 + 0.05, 10000.0, 0.68, 3366.5, 958.5, 2128.0 + 0.05, 10000.0, 0.72, 3927.7, 1011.4, 2353.9 + 0.05, 10000.0, 0.76, 4488.7, 1066.0, 2587.2 + 0.05, 10000.0, 0.8, 5049.8, 1120.9, 2822.6 + 0.05, 10000.0, 0.84, 5370.27, 1152.14, 2957.49 + 0.05, 10000.0, 0.88, 5546.57, 1169.44, 3033.44 + 0.05, 10000.0, 0.92, 5722.55, 1187.26, 3112.42 + 0.05, 10000.0, 0.96, 5947.27, 1210.57, 3215.57 + 0.05, 10000.0, 1.0, 6175.0, 1234.9, 3323.2 + 0.05, 15000.0, 0.52, 1239.3, 824.6, 1372.2 + 0.05, 15000.0, 0.56, 1857.5, 879.0, 1600.5 + 0.05, 15000.0, 0.6, 2479.7, 936.0, 1827.7 + 0.05, 15000.0, 0.64, 3093.3, 993.5, 2064.2 + 0.05, 15000.0, 0.68, 3720.5, 1048.4, 2302.2 + 0.05, 15000.0, 0.72, 4338.2, 1103.5, 2545.6 + 0.05, 15000.0, 0.76, 4952.8, 1165.4, 2792.2 + 0.05, 15000.0, 0.8, 5573.0, 1230.3, 3053.0 + 0.05, 15000.0, 0.84, 5930.88, 1267.77, 3203.36 + 0.05, 15000.0, 0.88, 6129.73, 1288.48, 3288.67 + 0.05, 15000.0, 0.92, 6323.63, 1308.07, 3376.67 + 0.05, 15000.0, 0.96, 6565.08, 1332.29, 3490.36 + 0.05, 15000.0, 1.0, 6805.0, 1357.0, 3608.0 + 0.05, 20000.0, 0.52, 1106.4, 68.8, -301.2 + 0.05, 20000.0, 0.56, 1653.6, 258.5, 174.7 + 0.05, 20000.0, 0.6, 2200.8, 405.3, 648.3 + 0.05, 20000.0, 0.64, 2774.6, 552.0, 1122.7 + 0.05, 20000.0, 0.68, 3333.8, 686.8, 1545.2 + 0.05, 20000.0, 0.72, 3897.8, 812.0, 1979.0 + 0.05, 20000.0, 0.76, 4445.0, 959.6, 2485.6 + 0.05, 20000.0, 0.8, 5004.2, 1059.9, 3002.4 + 0.05, 20000.0, 0.84, 5319.06, 1102.13, 3166.38 + 0.05, 20000.0, 0.88, 5489.33, 1111.25, 3131.91 + 0.05, 20000.0, 0.92, 5672.19, 1128.45, 3136.95 + 0.05, 20000.0, 0.96, 5909.94, 1162.49, 3252.27 + 0.05, 20000.0, 1.0, 6129.9, 1189.7, 3381.5 + 0.05, 25000.0, 0.52, 1470.4, 949.0, 1485.4 + 0.05, 25000.0, 0.56, 2273.7, 1024.5, 1847.6 + 0.05, 25000.0, 0.6, 3033.2, 1107.3, 2109.4 + 0.05, 25000.0, 0.64, 3752.5, 1189.9, 2449.9 + 0.05, 25000.0, 0.68, 4539.6, 1224.2, 2629.6 + 0.05, 25000.0, 0.72, 5222.9, 1318.8, 2949.8 + 0.05, 25000.0, 0.76, 6137.5, 1405.7, 3354.8 + 0.05, 25000.0, 0.8, 6777.3, 1431.2, 3478.0 + 0.05, 25000.0, 0.84, 7205.97, 1483.77, 3672.22 + 0.05, 25000.0, 0.88, 7498.12, 1547.69, 3890.33 + 0.05, 25000.0, 0.92, 7753.89, 1596.35, 4043.91 + 0.05, 25000.0, 0.96, 8022.32, 1624.94, 4127.1 + 0.05, 25000.0, 1.0, 8301.3, 1650.5, 4216.5 + 0.05, 30000.0, 0.52, 1607.4, 1006.5, 1558.2 + 0.05, 30000.0, 0.56, 2551.5, 1079.1, 1932.7 + 0.05, 30000.0, 0.6, 3338.4, 1182.9, 2153.7 + 0.05, 30000.0, 0.64, 4074.9, 1257.6, 2566.1 + 0.05, 30000.0, 0.68, 4945.8, 1357.5, 2920.2 + 0.05, 30000.0, 0.72, 5749.8, 1395.2, 3042.4 + 0.05, 30000.0, 0.76, 6617.2, 1571.1, 3674.7 + 0.05, 30000.0, 0.8, 7513.3, 1583.6, 3826.2 + 0.05, 30000.0, 0.84, 7985.15, 1622.93, 3990.05 + 0.05, 30000.0, 0.88, 8208.22, 1677.38, 4158.58 + 0.05, 30000.0, 0.92, 8445.92, 1730.66, 4317.98 + 0.05, 30000.0, 0.96, 8785.82, 1775.61, 4466.73 + 0.05, 30000.0, 1.0, 9139.6, 1814.1, 4615.6 + 0.05, 35000.0, 0.52, 1839.9, 1055.5, 1573.5 + 0.05, 35000.0, 0.56, 2656.9, 1114.7, 1930.7 + 0.05, 35000.0, 0.6, 3493.8, 1230.8, 2396.4 + 0.05, 35000.0, 0.64, 4470.4, 1282.2, 2608.3 + 0.05, 35000.0, 0.68, 5327.3, 1439.3, 3073.9 + 0.05, 35000.0, 0.72, 6172.3, 1495.2, 3344.0 + 0.05, 35000.0, 0.76, 7167.2, 1633.6, 3722.3 + 0.05, 35000.0, 0.8, 8012.2, 1651.8, 3957.4 + 0.05, 35000.0, 0.84, 8453.65, 1692.61, 4211.56 + 0.05, 35000.0, 0.88, 8659.06, 1746.78, 4463.09 + 0.05, 35000.0, 0.92, 8869.85, 1801.15, 4672.45 + 0.05, 35000.0, 0.96, 9179.6, 1850.41, 4835.8 + 0.05, 35000.0, 1.0, 9534.1, 1897.2, 4985.1 + 0.1, 0.0, 0.52, 794.3, 508.8, 1027.5 + 0.1, 0.0, 0.56, 1191.5, 542.4, 1185.9 + 0.1, 0.0, 0.6, 1588.7, 575.9, 1345.1 + 0.1, 0.0, 0.64, 1985.9, 609.1, 1504.7 + 0.1, 0.0, 0.68, 2383.1, 642.1, 1665.2 + 0.1, 0.0, 0.72, 2780.2, 677.0, 1833.0 + 0.1, 0.0, 0.76, 3177.4, 712.5, 2003.8 + 0.1, 0.0, 0.8, 3574.5, 748.1, 2176.7 + 0.1, 0.0, 0.84, 3797.65, 768.086, 2274.14 + 0.1, 0.0, 0.88, 3922.5, 779.229, 2329.03 + 0.1, 0.0, 0.92, 4065.76, 791.802, 2391.42 + 0.1, 0.0, 0.96, 4261.98, 809.073, 2477.09 + 0.1, 0.0, 1.0, 4463.6, 827.3, 2567.5 + 0.1, 5000.0, 0.52, 889.0, 557.5, 1092.8 + 0.1, 5000.0, 0.56, 1333.4, 595.8, 1267.8 + 0.1, 5000.0, 0.6, 1777.9, 634.0, 1443.8 + 0.1, 5000.0, 0.64, 2222.3, 671.9, 1620.5 + 0.1, 5000.0, 0.68, 2666.9, 709.6, 1798.1 + 0.1, 5000.0, 0.72, 3111.3, 749.9, 1985.3 + 0.1, 5000.0, 0.76, 3555.7, 791.0, 2176.3 + 0.1, 5000.0, 0.8, 4000.3, 831.8, 2368.0 + 0.1, 5000.0, 0.84, 4250.9, 854.851, 2476.67 + 0.1, 5000.0, 0.88, 4390.54, 867.766, 2538.06 + 0.1, 5000.0, 0.92, 4547.21, 882.11, 2606.47 + 0.1, 5000.0, 0.96, 4759.02, 901.541, 2699.11 + 0.1, 5000.0, 1.0, 4974.2, 921.8, 2796.1 + 0.1, 10000.0, 0.52, 1121.1, 692.4, 1253.3 + 0.1, 10000.0, 0.56, 1681.8, 744.4, 1468.6 + 0.1, 10000.0, 0.6, 2242.3, 795.8, 1684.3 + 0.1, 10000.0, 0.64, 2802.9, 847.2, 1901.8 + 0.1, 10000.0, 0.68, 3363.4, 898.3, 2120.5 + 0.1, 10000.0, 0.72, 3924.1, 951.3, 2346.3 + 0.1, 10000.0, 0.76, 4484.6, 1006.2, 2579.3 + 0.1, 10000.0, 0.8, 5045.2, 1061.3, 2814.6 + 0.1, 10000.0, 0.84, 5365.43, 1092.65, 2949.29 + 0.1, 10000.0, 0.88, 5541.57, 1110.02, 3024.98 + 0.1, 10000.0, 0.92, 5717.2, 1127.9, 3103.73 + 0.1, 10000.0, 0.96, 5941.33, 1151.29, 3206.69 + 0.1, 10000.0, 1.0, 6168.4, 1175.7, 3314.1 + 0.1, 15000.0, 0.52, 1242.1, 763.3, 1363.8 + 0.1, 15000.0, 0.56, 1862.2, 819.4, 1594.3 + 0.1, 15000.0, 0.6, 2484.5, 876.5, 1825.3 + 0.1, 15000.0, 0.64, 3102.7, 933.8, 2061.0 + 0.1, 15000.0, 0.68, 3727.0, 989.8, 2298.6 + 0.1, 15000.0, 0.72, 4347.1, 1047.1, 2542.7 + 0.1, 15000.0, 0.76, 4965.9, 1108.6, 2793.0 + 0.1, 15000.0, 0.8, 5587.2, 1171.7, 3051.0 + 0.1, 15000.0, 0.84, 5943.88, 1208.52, 3201.95 + 0.1, 15000.0, 0.88, 6140.75, 1229.5, 3289.43 + 0.1, 15000.0, 0.92, 6333.9, 1249.95, 3378.19 + 0.1, 15000.0, 0.96, 6576.85, 1275.4, 3490.65 + 0.1, 15000.0, 1.0, 6820.5, 1301.6, 3607.0 + 0.1, 20000.0, 0.52, 1185.4, 254.7, 228.7 + 0.1, 20000.0, 0.56, 1773.9, 405.9, 635.3 + 0.1, 20000.0, 0.6, 2362.4, 527.6, 1041.5 + 0.1, 20000.0, 0.64, 2969.6, 649.2, 1449.7 + 0.1, 20000.0, 0.68, 3566.5, 762.5, 1821.9 + 0.1, 20000.0, 0.72, 4166.2, 869.7, 2204.4 + 0.1, 20000.0, 0.76, 4754.7, 993.1, 2640.1 + 0.1, 20000.0, 0.8, 5351.6, 1084.6, 3084.4 + 0.1, 20000.0, 0.84, 5689.74, 1126.92, 3250.27 + 0.1, 20000.0, 0.88, 5873.49, 1140.87, 3258.02 + 0.1, 20000.0, 0.92, 6063.97, 1160.04, 3292.09 + 0.1, 20000.0, 0.96, 6308.82, 1192.41, 3408.67 + 0.1, 20000.0, 1.0, 6542.3, 1220.4, 3535.7 + 0.1, 25000.0, 0.52, 1480.6, 879.9, 1484.2 + 0.1, 25000.0, 0.56, 2267.2, 955.6, 1821.4 + 0.1, 25000.0, 0.6, 3023.5, 1035.9, 2091.3 + 0.1, 25000.0, 0.64, 3753.4, 1116.0, 2415.3 + 0.1, 25000.0, 0.68, 4529.3, 1163.3, 2630.1 + 0.1, 25000.0, 0.72, 5234.0, 1251.9, 2941.8 + 0.1, 25000.0, 0.76, 6096.6, 1336.5, 3318.0 + 0.1, 25000.0, 0.8, 6771.3, 1381.5, 3507.9 + 0.1, 25000.0, 0.84, 7200.59, 1432.57, 3700.23 + 0.1, 25000.0, 0.88, 7475.18, 1483.97, 3881.24 + 0.1, 25000.0, 0.92, 7722.37, 1524.9, 4017.82 + 0.1, 25000.0, 0.96, 7996.26, 1554.66, 4115.57 + 0.1, 25000.0, 1.0, 8277.7, 1582.7, 4218.8 + 0.1, 30000.0, 0.52, 1620.6, 938.7, 1559.4 + 0.1, 30000.0, 0.56, 2527.3, 1015.3, 1914.3 + 0.1, 30000.0, 0.6, 3326.9, 1113.2, 2164.6 + 0.1, 30000.0, 0.64, 4091.2, 1191.2, 2548.0 + 0.1, 30000.0, 0.68, 4947.5, 1286.0, 2890.6 + 0.1, 30000.0, 0.72, 5758.6, 1340.0, 3079.3 + 0.1, 30000.0, 0.76, 6612.2, 1488.5, 3619.1 + 0.1, 30000.0, 0.8, 7485.3, 1526.3, 3835.6 + 0.1, 30000.0, 0.84, 7957.53, 1570.2, 4013.24 + 0.1, 30000.0, 0.88, 8192.07, 1616.96, 4165.39 + 0.1, 30000.0, 0.92, 8432.86, 1662.44, 4309.99 + 0.1, 30000.0, 0.96, 8762.3, 1704.29, 4455.87 + 0.1, 30000.0, 1.0, 9101.3, 1742.0, 4602.8 + 0.1, 35000.0, 0.52, 1822.1, 980.3, 1590.7 + 0.1, 35000.0, 0.56, 2662.7, 1050.6, 1942.0 + 0.1, 35000.0, 0.6, 3515.8, 1158.4, 2366.5 + 0.1, 35000.0, 0.64, 4465.2, 1222.5, 2619.4 + 0.1, 35000.0, 0.68, 5333.0, 1359.1, 3047.1 + 0.1, 35000.0, 0.72, 6192.5, 1424.7, 3338.9 + 0.1, 35000.0, 0.76, 7155.1, 1551.9, 3721.5 + 0.1, 35000.0, 0.8, 8014.6, 1597.4, 4005.8 + 0.1, 35000.0, 0.84, 8478.79, 1644.3, 4251.23 + 0.1, 35000.0, 0.88, 8708.28, 1691.7, 4463.14 + 0.1, 35000.0, 0.92, 8936.32, 1738.47, 4644.05 + 0.1, 35000.0, 0.96, 9250.9, 1783.92, 4802.13 + 0.1, 35000.0, 1.0, 9594.7, 1827.8, 4951.2 + 0.15, 0.0, 0.52, 793.2, 454.1, 1016.8 + 0.15, 0.0, 0.56, 1189.8, 487.8, 1174.9 + 0.15, 0.0, 0.6, 1586.5, 521.5, 1333.7 + 0.15, 0.0, 0.64, 1983.1, 554.9, 1493.0 + 0.15, 0.0, 0.68, 2379.6, 588.1, 1653.1 + 0.15, 0.0, 0.72, 2776.2, 623.2, 1820.4 + 0.15, 0.0, 0.76, 3172.8, 658.8, 1990.9 + 0.15, 0.0, 0.8, 3569.4, 694.7, 2163.9 + 0.15, 0.0, 0.84, 3792.3, 714.866, 2261.25 + 0.15, 0.0, 0.88, 3916.95, 726.103, 2315.89 + 0.15, 0.0, 0.92, 4059.71, 738.729, 2377.93 + 0.15, 0.0, 0.96, 4255.12, 756.038, 2463.16 + 0.15, 0.0, 1.0, 4455.8, 774.3, 2553.1 + 0.15, 5000.0, 0.52, 886.9, 500.6, 1081.4 + 0.15, 5000.0, 0.56, 1330.4, 539.1, 1256.2 + 0.15, 5000.0, 0.6, 1773.9, 577.4, 1431.6 + 0.15, 5000.0, 0.64, 2217.4, 615.5, 1607.7 + 0.15, 5000.0, 0.68, 2660.8, 653.6, 1785.4 + 0.15, 5000.0, 0.72, 3104.3, 694.0, 1971.9 + 0.15, 5000.0, 0.76, 3547.7, 735.3, 2162.3 + 0.15, 5000.0, 0.8, 3991.2, 776.4, 2354.2 + 0.15, 5000.0, 0.84, 4241.23, 799.631, 2462.85 + 0.15, 5000.0, 0.88, 4380.57, 812.639, 2524.03 + 0.15, 5000.0, 0.92, 4536.74, 827.034, 2592.05 + 0.15, 5000.0, 0.96, 4747.8, 846.499, 2684.16 + 0.15, 5000.0, 1.0, 4962.3, 866.8, 2780.6 + 0.15, 10000.0, 0.52, 1118.9, 631.5, 1241.7 + 0.15, 10000.0, 0.56, 1678.3, 683.8, 1456.6 + 0.15, 10000.0, 0.6, 2237.8, 735.5, 1672.1 + 0.15, 10000.0, 0.64, 2797.2, 787.3, 1889.2 + 0.15, 10000.0, 0.68, 3356.7, 838.7, 2107.4 + 0.15, 10000.0, 0.72, 3916.1, 892.0, 2332.8 + 0.15, 10000.0, 0.76, 4475.5, 947.2, 2565.6 + 0.15, 10000.0, 0.8, 5035.0, 1002.6, 2800.4 + 0.15, 10000.0, 0.84, 5354.65, 1034.06, 2934.67 + 0.15, 10000.0, 0.88, 5530.45, 1051.43, 3009.97 + 0.15, 10000.0, 0.92, 5705.5, 1069.33, 3088.3 + 0.15, 10000.0, 0.96, 5928.67, 1092.8, 3190.78 + 0.15, 10000.0, 1.0, 6154.6, 1117.3, 3297.7 + 0.15, 15000.0, 0.52, 1240.8, 701.0, 1350.4 + 0.15, 15000.0, 0.56, 1860.7, 758.2, 1581.8 + 0.15, 15000.0, 0.6, 2481.6, 815.5, 1814.4 + 0.15, 15000.0, 0.64, 3101.0, 872.8, 2049.4 + 0.15, 15000.0, 0.68, 3722.3, 929.6, 2286.4 + 0.15, 15000.0, 0.72, 4342.4, 988.2, 2530.4 + 0.15, 15000.0, 0.76, 4962.1, 1049.7, 2782.4 + 0.15, 15000.0, 0.8, 5582.6, 1111.9, 3038.5 + 0.15, 15000.0, 0.84, 5937.89, 1148.39, 3189.27 + 0.15, 15000.0, 0.88, 6133.27, 1169.5, 3277.39 + 0.15, 15000.0, 0.92, 6325.42, 1190.41, 3366.07 + 0.15, 15000.0, 0.96, 6568.27, 1216.56, 3477.46 + 0.15, 15000.0, 1.0, 6813.0, 1243.6, 3592.7 + 0.15, 20000.0, 0.52, 1244.4, 385.1, 633.0 + 0.15, 20000.0, 0.56, 1863.8, 506.6, 985.7 + 0.15, 20000.0, 0.6, 2483.2, 608.9, 1339.3 + 0.15, 20000.0, 0.64, 3115.1, 711.1, 1695.6 + 0.15, 20000.0, 0.68, 3740.1, 807.8, 2028.4 + 0.15, 20000.0, 0.72, 4366.5, 901.1, 2370.6 + 0.15, 20000.0, 0.76, 4985.9, 1005.9, 2751.0 + 0.15, 20000.0, 0.8, 5610.9, 1090.5, 3138.6 + 0.15, 20000.0, 0.84, 5966.46, 1132.89, 3305.42 + 0.15, 20000.0, 0.88, 6160.33, 1150.61, 3345.41 + 0.15, 20000.0, 0.92, 6356.3, 1171.37, 3401.59 + 0.15, 20000.0, 0.96, 6606.09, 1202.55, 3518.84 + 0.15, 20000.0, 1.0, 6849.3, 1231.2, 3643.9 + 0.15, 25000.0, 0.52, 1486.0, 812.3, 1477.1 + 0.15, 25000.0, 0.56, 2258.7, 888.2, 1794.7 + 0.15, 25000.0, 0.6, 3011.5, 966.7, 2070.1 + 0.15, 25000.0, 0.64, 3748.2, 1045.0, 2380.9 + 0.15, 25000.0, 0.68, 4514.3, 1102.3, 2622.0 + 0.15, 25000.0, 0.72, 5234.2, 1186.4, 2926.8 + 0.15, 25000.0, 0.76, 6055.9, 1269.4, 3280.1 + 0.15, 25000.0, 0.8, 6756.2, 1329.0, 3519.2 + 0.15, 25000.0, 0.84, 7185.33, 1379.03, 3709.8 + 0.15, 25000.0, 0.88, 7446.06, 1421.17, 3862.98 + 0.15, 25000.0, 0.92, 7686.1, 1456.39, 3986.8 + 0.15, 25000.0, 0.96, 7963.3, 1487.07, 4095.34 + 0.15, 25000.0, 1.0, 8245.7, 1517.0, 4208.7 + 0.15, 30000.0, 0.52, 1627.9, 871.6, 1553.6 + 0.15, 30000.0, 0.56, 2504.5, 951.4, 1892.9 + 0.15, 30000.0, 0.6, 3312.2, 1044.9, 2165.1 + 0.15, 30000.0, 0.64, 4096.4, 1125.5, 2525.4 + 0.15, 30000.0, 0.68, 4940.1, 1216.6, 2858.8 + 0.15, 30000.0, 0.72, 5755.1, 1282.8, 3097.0 + 0.15, 30000.0, 0.76, 6596.8, 1410.6, 3565.6 + 0.15, 30000.0, 0.8, 7451.0, 1468.1, 3831.5 + 0.15, 30000.0, 0.84, 7922.78, 1515.65, 4019.49 + 0.15, 30000.0, 0.88, 8165.64, 1556.58, 4158.97 + 0.15, 30000.0, 0.92, 8408.24, 1596.11, 4291.96 + 0.15, 30000.0, 0.96, 8728.93, 1635.66, 4435.22 + 0.15, 30000.0, 1.0, 9055.8, 1672.8, 4580.2 + 0.15, 35000.0, 0.52, 1806.5, 908.7, 1598.1 + 0.15, 35000.0, 0.56, 2664.2, 987.5, 1944.2 + 0.15, 35000.0, 0.6, 3529.0, 1089.3, 2336.9 + 0.15, 35000.0, 0.64, 4456.7, 1163.3, 2620.7 + 0.15, 35000.0, 0.68, 5331.9, 1284.3, 3018.8 + 0.15, 35000.0, 0.72, 6201.6, 1357.9, 3327.5 + 0.15, 35000.0, 0.76, 7138.4, 1476.5, 3711.5 + 0.15, 35000.0, 0.8, 8008.1, 1543.2, 4033.6 + 0.15, 35000.0, 0.84, 8489.11, 1594.92, 4272.28 + 0.15, 35000.0, 0.88, 8736.61, 1637.18, 4453.65 + 0.15, 35000.0, 0.92, 8977.34, 1678.2, 4612.51 + 0.15, 35000.0, 0.96, 9294.94, 1720.83, 4766.26 + 0.15, 35000.0, 1.0, 9630.0, 1762.6, 4914.9 + 0.2, 0.0, 0.52, 791.4, 399.6, 1002.0 + 0.2, 0.0, 0.56, 1187.0, 433.6, 1159.5 + 0.2, 0.0, 0.6, 1582.6, 467.5, 1317.8 + 0.2, 0.0, 0.64, 1978.3, 501.1, 1476.6 + 0.2, 0.0, 0.68, 2374.0, 534.5, 1636.2 + 0.2, 0.0, 0.72, 2769.6, 569.8, 1802.7 + 0.2, 0.0, 0.76, 3165.3, 605.7, 1972.9 + 0.2, 0.0, 0.8, 3561.0, 642.0, 2145.6 + 0.2, 0.0, 0.84, 3783.47, 662.309, 2242.73 + 0.2, 0.0, 0.88, 3907.83, 673.534, 2297.15 + 0.2, 0.0, 0.92, 4049.93, 686.136, 2358.75 + 0.2, 0.0, 0.96, 4244.16, 703.472, 2443.33 + 0.2, 0.0, 1.0, 4443.5, 721.8, 2532.6 + 0.2, 5000.0, 0.52, 884.1, 443.9, 1066.0 + 0.2, 5000.0, 0.56, 1326.1, 482.7, 1239.9 + 0.2, 5000.0, 0.6, 1768.1, 521.2, 1414.6 + 0.2, 5000.0, 0.64, 2210.2, 559.5, 1590.0 + 0.2, 5000.0, 0.68, 2652.2, 598.1, 1767.9 + 0.2, 5000.0, 0.72, 3094.2, 638.7, 1953.3 + 0.2, 5000.0, 0.76, 3536.2, 680.1, 2142.9 + 0.2, 5000.0, 0.8, 3978.3, 721.6, 2334.1 + 0.2, 5000.0, 0.84, 4227.62, 745.039, 2442.51 + 0.2, 5000.0, 0.88, 4366.52, 758.127, 2503.66 + 0.2, 5000.0, 0.92, 4521.72, 772.554, 2571.38 + 0.2, 5000.0, 0.96, 4731.19, 792.051, 2662.86 + 0.2, 5000.0, 1.0, 4944.2, 812.4, 2758.6 + 0.2, 10000.0, 0.52, 1115.4, 571.2, 1225.6 + 0.2, 10000.0, 0.56, 1673.0, 623.9, 1440.0 + 0.2, 10000.0, 0.6, 2230.7, 676.0, 1654.8 + 0.2, 10000.0, 0.64, 2788.3, 728.1, 1871.4 + 0.2, 10000.0, 0.68, 3346.1, 779.9, 2089.0 + 0.2, 10000.0, 0.72, 3903.7, 833.6, 2313.7 + 0.2, 10000.0, 0.76, 4461.3, 889.2, 2545.9 + 0.2, 10000.0, 0.8, 5019.0, 945.0, 2780.4 + 0.2, 10000.0, 0.84, 5337.73, 976.636, 2914.1 + 0.2, 10000.0, 0.88, 5513.01, 994.036, 2988.67 + 0.2, 10000.0, 0.92, 5687.16, 1011.96, 3066.27 + 0.2, 10000.0, 0.96, 5908.88, 1035.51, 3168.08 + 0.2, 10000.0, 1.0, 6133.2, 1060.1, 3274.3 + 0.2, 15000.0, 0.52, 1236.3, 638.4, 1332.3 + 0.2, 15000.0, 0.56, 1854.3, 696.3, 1563.6 + 0.2, 15000.0, 0.6, 2472.6, 753.9, 1796.2 + 0.2, 15000.0, 0.64, 3090.6, 811.4, 2030.5 + 0.2, 15000.0, 0.68, 3708.7, 868.8, 2266.7 + 0.2, 15000.0, 0.72, 4326.9, 928.1, 2510.0 + 0.2, 15000.0, 0.76, 4945.0, 989.9, 2762.2 + 0.2, 15000.0, 0.8, 5563.2, 1051.9, 3017.0 + 0.2, 15000.0, 0.84, 5916.88, 1088.31, 3167.01 + 0.2, 15000.0, 0.88, 6111.08, 1109.44, 3254.63 + 0.2, 15000.0, 0.92, 6301.97, 1130.53, 3342.6 + 0.2, 15000.0, 0.96, 6543.49, 1156.98, 3452.97 + 0.2, 15000.0, 1.0, 6787.3, 1184.4, 3567.2 + 0.2, 20000.0, 0.52, 1285.7, 467.2, 927.1 + 0.2, 20000.0, 0.56, 1926.8, 566.7, 1239.3 + 0.2, 20000.0, 0.6, 2567.9, 654.6, 1553.2 + 0.2, 20000.0, 0.64, 3216.8, 742.4, 1870.1 + 0.2, 20000.0, 0.68, 3861.4, 826.8, 2173.0 + 0.2, 20000.0, 0.72, 4506.5, 909.8, 2484.5 + 0.2, 20000.0, 0.76, 5147.6, 1000.9, 2823.2 + 0.2, 20000.0, 0.8, 5792.2, 1080.3, 3167.9 + 0.2, 20000.0, 0.84, 6160.0, 1122.73, 3334.84 + 0.2, 20000.0, 0.88, 6360.99, 1143.29, 3398.33 + 0.2, 20000.0, 0.92, 6560.59, 1165.32, 3470.55 + 0.2, 20000.0, 0.96, 6813.34, 1195.7, 3587.94 + 0.2, 20000.0, 1.0, 7062.9, 1224.9, 3711.2 + 0.2, 25000.0, 0.52, 1487.0, 746.4, 1464.7 + 0.2, 25000.0, 0.56, 2248.1, 822.5, 1767.3 + 0.2, 25000.0, 0.6, 2997.0, 899.8, 2045.9 + 0.2, 25000.0, 0.64, 3737.1, 976.9, 2346.3 + 0.2, 25000.0, 0.68, 4494.5, 1041.6, 2606.0 + 0.2, 25000.0, 0.72, 5224.1, 1122.5, 2905.2 + 0.2, 25000.0, 0.76, 6014.4, 1204.5, 3240.7 + 0.2, 25000.0, 0.8, 6732.1, 1274.5, 3513.9 + 0.2, 25000.0, 0.84, 7160.31, 1323.87, 3702.87 + 0.2, 25000.0, 0.88, 7410.38, 1359.54, 3836.14 + 0.2, 25000.0, 0.92, 7644.46, 1390.8, 3950.8 + 0.2, 25000.0, 0.96, 7923.08, 1422.19, 4066.83 + 0.2, 25000.0, 1.0, 8205.1, 1453.5, 4187.1 + 0.2, 30000.0, 0.52, 1629.8, 805.5, 1541.5 + 0.2, 30000.0, 0.56, 2482.5, 887.8, 1868.6 + 0.2, 30000.0, 0.6, 3294.2, 978.2, 2156.2 + 0.2, 30000.0, 0.64, 4091.3, 1060.8, 2498.5 + 0.2, 30000.0, 0.68, 4924.0, 1149.4, 2824.6 + 0.2, 30000.0, 0.72, 5740.0, 1224.3, 3097.6 + 0.2, 30000.0, 0.76, 6571.3, 1337.2, 3513.4 + 0.2, 30000.0, 0.8, 7410.0, 1409.5, 3815.0 + 0.2, 30000.0, 0.84, 7880.51, 1459.91, 4010.3 + 0.2, 30000.0, 0.88, 8128.93, 1496.62, 4140.29 + 0.2, 30000.0, 0.92, 8372.18, 1531.83, 4264.45 + 0.2, 30000.0, 0.96, 8685.51, 1569.72, 4405.28 + 0.2, 30000.0, 1.0, 9002.5, 1606.5, 4548.3 + 0.2, 35000.0, 0.52, 1792.5, 840.6, 1596.7 + 0.2, 35000.0, 0.56, 2661.5, 925.7, 1938.2 + 0.2, 35000.0, 0.6, 3533.9, 1023.5, 2307.2 + 0.2, 35000.0, 0.64, 4444.5, 1105.0, 2613.1 + 0.2, 35000.0, 0.68, 5323.9, 1214.7, 2988.8 + 0.2, 35000.0, 0.72, 6199.9, 1294.8, 3310.1 + 0.2, 35000.0, 0.76, 7116.4, 1407.1, 3693.1 + 0.2, 35000.0, 0.8, 7992.4, 1489.7, 4042.9 + 0.2, 35000.0, 0.84, 8485.01, 1545.13, 4276.48 + 0.2, 35000.0, 0.88, 8745.24, 1583.7, 4435.19 + 0.2, 35000.0, 0.92, 8994.65, 1620.57, 4577.56 + 0.2, 35000.0, 0.96, 9313.66, 1661.25, 4727.81 + 0.2, 35000.0, 1.0, 9641.6, 1701.6, 4875.8 + 0.25, 0.0, 0.52, 788.1, 345.4, 983.1 + 0.25, 0.0, 0.56, 1182.2, 379.7, 1139.8 + 0.25, 0.0, 0.6, 1576.2, 413.7, 1297.2 + 0.25, 0.0, 0.64, 1970.2, 447.5, 1455.2 + 0.25, 0.0, 0.68, 2364.3, 481.2, 1614.1 + 0.25, 0.0, 0.72, 2758.4, 516.6, 1779.5 + 0.25, 0.0, 0.76, 3152.4, 553.0, 1949.6 + 0.25, 0.0, 0.8, 3546.4, 589.5, 2121.2 + 0.25, 0.0, 0.84, 3768.11, 609.894, 2217.78 + 0.25, 0.0, 0.88, 3891.98, 621.137, 2271.89 + 0.25, 0.0, 0.92, 4032.62, 633.756, 2332.96 + 0.25, 0.0, 0.96, 4224.35, 651.132, 2416.66 + 0.25, 0.0, 1.0, 4421.2, 669.5, 2505.0 + 0.25, 5000.0, 0.52, 879.5, 387.6, 1046.3 + 0.25, 5000.0, 0.56, 1319.3, 426.6, 1219.1 + 0.25, 5000.0, 0.6, 1759.0, 465.3, 1392.7 + 0.25, 5000.0, 0.64, 2198.7, 503.7, 1566.8 + 0.25, 5000.0, 0.68, 2638.5, 542.9, 1744.7 + 0.25, 5000.0, 0.72, 3078.2, 583.6, 1928.7 + 0.25, 5000.0, 0.76, 3517.9, 625.2, 2117.1 + 0.25, 5000.0, 0.8, 3957.6, 667.0, 2307.7 + 0.25, 5000.0, 0.84, 4205.76, 690.586, 2415.64 + 0.25, 5000.0, 0.88, 4344.05, 703.723, 2476.32 + 0.25, 5000.0, 0.92, 4497.92, 718.175, 2543.38 + 0.25, 5000.0, 0.96, 4705.23, 737.71, 2633.98 + 0.25, 5000.0, 1.0, 4916.2, 758.1, 2728.8 + 0.25, 10000.0, 0.52, 1108.8, 511.0, 1204.4 + 0.25, 10000.0, 0.56, 1663.3, 564.0, 1417.7 + 0.25, 10000.0, 0.6, 2217.7, 616.6, 1631.5 + 0.25, 10000.0, 0.64, 2772.0, 669.1, 1846.9 + 0.25, 10000.0, 0.68, 3326.4, 721.1, 2063.3 + 0.25, 10000.0, 0.72, 3880.8, 775.2, 2286.9 + 0.25, 10000.0, 0.76, 4435.3, 831.2, 2517.9 + 0.25, 10000.0, 0.8, 4989.7, 887.1, 2751.1 + 0.25, 10000.0, 0.84, 5306.43, 918.907, 2884.17 + 0.25, 10000.0, 0.88, 5480.67, 936.522, 2958.46 + 0.25, 10000.0, 0.92, 5654.46, 954.68, 3035.71 + 0.25, 10000.0, 0.96, 5876.12, 978.444, 3136.93 + 0.25, 10000.0, 1.0, 6100.2, 1003.2, 3242.4 + 0.25, 15000.0, 0.52, 1229.5, 576.2, 1309.8 + 0.25, 15000.0, 0.56, 1844.3, 634.6, 1540.3 + 0.25, 15000.0, 0.6, 2459.1, 692.6, 1771.9 + 0.25, 15000.0, 0.64, 3073.9, 750.5, 2005.4 + 0.25, 15000.0, 0.68, 3688.5, 808.4, 2240.6 + 0.25, 15000.0, 0.72, 4303.4, 868.1, 2482.8 + 0.25, 15000.0, 0.76, 4918.2, 930.4, 2734.2 + 0.25, 15000.0, 0.8, 5533.0, 992.7, 2988.0 + 0.25, 15000.0, 0.84, 5884.82, 1029.18, 3136.85 + 0.25, 15000.0, 0.88, 6077.95, 1050.27, 3223.25 + 0.25, 15000.0, 0.92, 6267.36, 1071.35, 3310.07 + 0.25, 15000.0, 0.96, 6506.68, 1097.89, 3419.41 + 0.25, 15000.0, 1.0, 6748.2, 1125.4, 3532.6 + 0.25, 20000.0, 0.52, 1311.6, 508.2, 1126.4 + 0.25, 20000.0, 0.56, 1966.4, 592.3, 1409.5 + 0.25, 20000.0, 0.6, 2621.2, 670.1, 1694.7 + 0.25, 20000.0, 0.64, 3280.4, 747.8, 1982.9 + 0.25, 20000.0, 0.68, 3937.2, 823.6, 2264.0 + 0.25, 20000.0, 0.72, 4594.0, 899.4, 2553.0 + 0.25, 20000.0, 0.76, 5248.8, 981.0, 2861.6 + 0.25, 20000.0, 0.8, 5905.6, 1056.7, 3175.2 + 0.25, 20000.0, 0.84, 6281.15, 1099.16, 3341.54 + 0.25, 20000.0, 0.88, 6486.66, 1121.76, 3421.03 + 0.25, 20000.0, 0.92, 6688.21, 1144.74, 3504.07 + 0.25, 20000.0, 0.96, 6942.15, 1174.64, 3621.12 + 0.25, 20000.0, 1.0, 7195.1, 1204.3, 3742.7 + 0.25, 25000.0, 0.52, 1484.0, 682.4, 1447.6 + 0.25, 25000.0, 0.56, 2235.3, 758.7, 1739.0 + 0.25, 25000.0, 0.6, 2979.8, 835.3, 2018.8 + 0.25, 25000.0, 0.64, 3720.3, 911.7, 2311.1 + 0.25, 25000.0, 0.68, 4469.8, 981.6, 2582.8 + 0.25, 25000.0, 0.72, 5204.3, 1060.4, 2877.4 + 0.25, 25000.0, 0.76, 5971.1, 1141.9, 3199.4 + 0.25, 25000.0, 0.8, 6699.1, 1218.8, 3494.0 + 0.25, 25000.0, 0.84, 7125.68, 1267.84, 3681.34 + 0.25, 25000.0, 0.88, 7367.74, 1299.37, 3801.27 + 0.25, 25000.0, 0.92, 7596.86, 1328.11, 3909.74 + 0.25, 25000.0, 0.96, 7875.25, 1360.02, 4030.46 + 0.25, 25000.0, 1.0, 8155.7, 1392.3, 4154.9 + 0.25, 30000.0, 0.52, 1626.8, 740.7, 1523.8 + 0.25, 30000.0, 0.56, 2460.7, 824.9, 1841.5 + 0.25, 30000.0, 0.6, 3272.8, 913.3, 2138.9 + 0.25, 30000.0, 0.64, 4076.7, 997.4, 2467.5 + 0.25, 30000.0, 0.68, 4899.6, 1084.5, 2787.8 + 0.25, 30000.0, 0.72, 5714.0, 1165.2, 3083.2 + 0.25, 30000.0, 0.76, 6536.0, 1268.1, 3461.7 + 0.25, 30000.0, 0.8, 7361.9, 1351.0, 3787.2 + 0.25, 30000.0, 0.84, 7830.36, 1403.57, 3987.14 + 0.25, 30000.0, 0.88, 8081.93, 1437.44, 4110.33 + 0.25, 30000.0, 0.92, 8324.8, 1469.71, 4228.01 + 0.25, 30000.0, 0.96, 8631.89, 1506.53, 4366.58 + 0.25, 30000.0, 1.0, 8940.8, 1543.1, 4507.6 + 0.25, 35000.0, 0.52, 1779.5, 775.9, 1587.5 + 0.25, 35000.0, 0.56, 2654.7, 865.5, 1924.9 + 0.25, 35000.0, 0.6, 3531.0, 961.0, 2277.0 + 0.25, 35000.0, 0.64, 4428.2, 1048.0, 2597.5 + 0.25, 35000.0, 0.68, 5308.9, 1150.1, 2956.9 + 0.25, 35000.0, 0.72, 6187.7, 1235.4, 3287.0 + 0.25, 35000.0, 0.76, 7088.4, 1343.4, 3667.1 + 0.25, 35000.0, 0.8, 7967.2, 1437.4, 4035.8 + 0.25, 35000.0, 0.84, 8466.9, 1495.6, 4265.58 + 0.25, 35000.0, 0.88, 8735.33, 1531.73, 4408.33 + 0.25, 35000.0, 0.92, 8989.97, 1565.83, 4538.95 + 0.25, 35000.0, 0.96, 9308.97, 1605.28, 4686.35 + 0.25, 35000.0, 1.0, 9631.1, 1644.8, 4833.5 + 0.3, 0.0, 0.52, 784.1, 292.0, 960.5 + 0.3, 0.0, 0.56, 1176.1, 326.6, 1116.2 + 0.3, 0.0, 0.6, 1568.2, 360.9, 1272.6 + 0.3, 0.0, 0.64, 1960.2, 394.9, 1429.5 + 0.3, 0.0, 0.68, 2352.2, 428.9, 1587.4 + 0.3, 0.0, 0.72, 2744.3, 464.4, 1751.4 + 0.3, 0.0, 0.76, 3136.3, 501.3, 1921.4 + 0.3, 0.0, 0.8, 3528.4, 538.0, 2091.9 + 0.3, 0.0, 0.84, 3749.2, 558.509, 2187.81 + 0.3, 0.0, 0.88, 3872.39, 569.814, 2241.44 + 0.3, 0.0, 0.92, 4011.03, 582.493, 2301.8 + 0.3, 0.0, 0.96, 4199.44, 599.946, 2384.51 + 0.3, 0.0, 1.0, 4393.1, 618.4, 2471.8 + 0.3, 5000.0, 0.52, 873.8, 332.1, 1022.5 + 0.3, 5000.0, 0.56, 1310.7, 371.3, 1194.1 + 0.3, 5000.0, 0.6, 1747.8, 410.2, 1366.2 + 0.3, 5000.0, 0.64, 2184.7, 449.2, 1539.9 + 0.3, 5000.0, 0.68, 2621.6, 488.7, 1716.9 + 0.3, 5000.0, 0.72, 3058.5, 529.6, 1899.3 + 0.3, 5000.0, 0.76, 3495.4, 571.6, 2086.6 + 0.3, 5000.0, 0.8, 3932.3, 613.6, 2276.0 + 0.3, 5000.0, 0.84, 4178.92, 637.304, 2383.25 + 0.3, 5000.0, 0.88, 4316.23, 650.504, 2443.46 + 0.3, 5000.0, 0.92, 4468.49, 664.994, 2509.77 + 0.3, 5000.0, 0.96, 4673.41, 684.563, 2599.24 + 0.3, 5000.0, 1.0, 4882.1, 705.0, 2692.9 + 0.3, 10000.0, 0.52, 1100.8, 451.8, 1179.1 + 0.3, 10000.0, 0.56, 1651.2, 505.3, 1391.0 + 0.3, 10000.0, 0.6, 2201.7, 558.3, 1603.4 + 0.3, 10000.0, 0.64, 2752.0, 611.2, 1817.3 + 0.3, 10000.0, 0.68, 3302.4, 663.7, 2032.5 + 0.3, 10000.0, 0.72, 3852.9, 718.1, 2254.4 + 0.3, 10000.0, 0.76, 4403.2, 774.5, 2483.9 + 0.3, 10000.0, 0.8, 4953.7, 831.0, 2716.0 + 0.3, 10000.0, 0.84, 5268.01, 863.061, 2848.37 + 0.3, 10000.0, 0.88, 5440.98, 880.726, 2922.19 + 0.3, 10000.0, 0.92, 5614.53, 898.962, 2998.9 + 0.3, 10000.0, 0.96, 5836.45, 922.891, 3099.4 + 0.3, 10000.0, 1.0, 6060.4, 947.8, 3204.0 + 0.3, 15000.0, 0.52, 1221.3, 515.1, 1283.2 + 0.3, 15000.0, 0.56, 1832.0, 574.0, 1512.5 + 0.3, 15000.0, 0.6, 2442.7, 632.5, 1742.7 + 0.3, 15000.0, 0.64, 3053.3, 691.0, 1975.2 + 0.3, 15000.0, 0.68, 3664.0, 749.4, 2209.2 + 0.3, 15000.0, 0.72, 4274.7, 809.5, 2450.1 + 0.3, 15000.0, 0.76, 4885.3, 872.4, 2700.2 + 0.3, 15000.0, 0.8, 5496.0, 935.3, 2953.0 + 0.3, 15000.0, 0.84, 5845.68, 971.954, 3100.48 + 0.3, 15000.0, 0.88, 6037.66, 992.957, 3185.32 + 0.3, 15000.0, 0.92, 6225.38, 1013.95, 3270.77 + 0.3, 15000.0, 0.96, 6462.01, 1040.49, 3378.97 + 0.3, 15000.0, 1.0, 6700.5, 1068.0, 3491.0 + 0.3, 20000.0, 0.52, 1324.4, 515.3, 1246.3 + 0.3, 20000.0, 0.56, 1986.1, 589.5, 1509.7 + 0.3, 20000.0, 0.6, 2647.8, 660.8, 1775.3 + 0.3, 20000.0, 0.64, 3311.6, 732.0, 2043.7 + 0.3, 20000.0, 0.68, 3974.3, 802.3, 2309.7 + 0.3, 20000.0, 0.72, 4636.8, 873.5, 2583.0 + 0.3, 20000.0, 0.76, 5298.5, 949.1, 2871.1 + 0.3, 20000.0, 0.8, 5961.2, 1022.4, 3163.4 + 0.3, 20000.0, 0.84, 6340.67, 1064.89, 3328.52 + 0.3, 20000.0, 0.88, 6548.49, 1088.84, 3417.78 + 0.3, 20000.0, 0.92, 6750.53, 1112.5, 3507.28 + 0.3, 20000.0, 0.96, 7004.09, 1142.17, 3623.54 + 0.3, 20000.0, 1.0, 7257.9, 1172.2, 3743.5 + 0.3, 25000.0, 0.52, 1477.4, 620.5, 1426.4 + 0.3, 25000.0, 0.56, 2220.2, 697.0, 1709.6 + 0.3, 25000.0, 0.6, 2959.7, 773.3, 1988.9 + 0.3, 25000.0, 0.64, 3698.0, 849.4, 2274.9 + 0.3, 25000.0, 0.68, 4440.1, 922.7, 2553.1 + 0.3, 25000.0, 0.72, 5175.4, 1000.3, 2843.8 + 0.3, 25000.0, 0.76, 5925.0, 1081.7, 3155.8 + 0.3, 25000.0, 0.8, 6657.3, 1162.7, 3461.5 + 0.3, 25000.0, 0.84, 7081.57, 1211.67, 3647.16 + 0.3, 25000.0, 0.88, 7317.75, 1240.92, 3758.97 + 0.3, 25000.0, 0.92, 7542.69, 1268.3, 3863.55 + 0.3, 25000.0, 0.96, 7819.44, 1300.59, 3986.63 + 0.3, 25000.0, 1.0, 8097.3, 1333.5, 4113.0 + 0.3, 30000.0, 0.52, 1619.4, 677.5, 1501.2 + 0.3, 30000.0, 0.56, 2438.5, 763.1, 1811.7 + 0.3, 30000.0, 0.6, 3247.9, 850.4, 2114.2 + 0.3, 30000.0, 0.64, 4053.4, 935.6, 2432.6 + 0.3, 30000.0, 0.68, 4867.3, 1022.0, 2748.2 + 0.3, 30000.0, 0.72, 5677.8, 1106.2, 3055.9 + 0.3, 30000.0, 0.76, 6491.2, 1203.1, 3409.7 + 0.3, 30000.0, 0.8, 7306.3, 1293.1, 3749.2 + 0.3, 30000.0, 0.84, 7771.95, 1347.26, 3951.49 + 0.3, 30000.0, 0.88, 8024.65, 1379.43, 4070.08 + 0.3, 30000.0, 0.92, 8266.24, 1409.9, 4183.2 + 0.3, 30000.0, 0.96, 8567.89, 1446.1, 4319.62 + 0.3, 30000.0, 1.0, 8870.1, 1482.6, 4458.6 + 0.3, 35000.0, 0.52, 1766.9, 714.5, 1571.5 + 0.3, 35000.0, 0.56, 2643.9, 807.2, 1905.2 + 0.3, 35000.0, 0.6, 3520.8, 901.8, 2245.9 + 0.3, 35000.0, 0.64, 4407.4, 992.7, 2574.8 + 0.3, 35000.0, 0.68, 5286.8, 1090.3, 2922.9 + 0.3, 35000.0, 0.72, 6165.3, 1179.7, 3258.5 + 0.3, 35000.0, 0.76, 7053.7, 1285.1, 3634.3 + 0.3, 35000.0, 0.8, 7932.2, 1386.8, 4014.4 + 0.3, 35000.0, 0.84, 8435.17, 1447.03, 4241.36 + 0.3, 35000.0, 0.88, 8708.02, 1481.73, 4373.66 + 0.3, 35000.0, 0.92, 8965.05, 1514.19, 4496.41 + 0.3, 35000.0, 0.96, 9282.8, 1553.03, 4641.49 + 0.3, 35000.0, 1.0, 9600.1, 1592.2, 4787.6 + 0.35, 0.0, 0.52, 779.5, 240.0, 934.3 + 0.35, 0.0, 0.56, 1169.2, 274.8, 1088.9 + 0.35, 0.0, 0.6, 1559.0, 309.4, 1244.0 + 0.35, 0.0, 0.64, 1948.7, 343.8, 1399.8 + 0.35, 0.0, 0.68, 2338.5, 378.0, 1556.5 + 0.35, 0.0, 0.72, 2728.2, 414.1, 1720.3 + 0.35, 0.0, 0.76, 3117.9, 451.2, 1888.8 + 0.35, 0.0, 0.8, 3507.7, 488.2, 2057.9 + 0.35, 0.0, 0.84, 3727.38, 508.953, 2153.39 + 0.35, 0.0, 0.88, 3849.84, 520.445, 2207.04 + 0.35, 0.0, 0.92, 3986.7, 533.229, 2266.93 + 0.35, 0.0, 0.96, 4172.16, 550.722, 2348.49 + 0.35, 0.0, 1.0, 4363.0, 569.2, 2434.5 + 0.35, 5000.0, 0.52, 867.9, 278.0, 995.3 + 0.35, 5000.0, 0.56, 1301.8, 317.6, 1165.5 + 0.35, 5000.0, 0.6, 1735.7, 356.8, 1336.2 + 0.35, 5000.0, 0.64, 2169.6, 396.5, 1509.8 + 0.35, 5000.0, 0.68, 2603.6, 436.3, 1685.3 + 0.35, 5000.0, 0.72, 3037.5, 477.4, 1865.9 + 0.35, 5000.0, 0.76, 3471.5, 519.8, 2052.2 + 0.35, 5000.0, 0.8, 3905.4, 562.2, 2240.1 + 0.35, 5000.0, 0.84, 4150.47, 586.12, 2346.62 + 0.35, 5000.0, 0.88, 4286.88, 599.4, 2406.45 + 0.35, 5000.0, 0.92, 4437.5, 613.87, 2472.03 + 0.35, 5000.0, 0.96, 4639.83, 633.381, 2560.3 + 0.35, 5000.0, 1.0, 4846.0, 653.8, 2652.7 + 0.35, 10000.0, 0.52, 1092.3, 394.4, 1150.3 + 0.35, 10000.0, 0.56, 1638.4, 448.5, 1360.5 + 0.35, 10000.0, 0.6, 2184.5, 502.0, 1571.7 + 0.35, 10000.0, 0.64, 2730.7, 555.3, 1783.9 + 0.35, 10000.0, 0.68, 3276.8, 608.4, 1997.7 + 0.35, 10000.0, 0.72, 3822.9, 663.3, 2218.0 + 0.35, 10000.0, 0.76, 4369.1, 720.2, 2446.0 + 0.35, 10000.0, 0.8, 4915.2, 777.3, 2676.6 + 0.35, 10000.0, 0.84, 5226.86, 809.707, 2808.13 + 0.35, 10000.0, 0.88, 5398.49, 827.562, 2881.48 + 0.35, 10000.0, 0.92, 5571.72, 845.973, 2957.67 + 0.35, 10000.0, 0.96, 5793.75, 870.11, 3057.43 + 0.35, 10000.0, 1.0, 6017.4, 895.2, 3161.1 + 0.35, 15000.0, 0.52, 1212.6, 455.8, 1252.8 + 0.35, 15000.0, 0.56, 1818.7, 515.4, 1480.8 + 0.35, 15000.0, 0.6, 2425.0, 574.5, 1709.8 + 0.35, 15000.0, 0.64, 3031.2, 633.8, 1941.0 + 0.35, 15000.0, 0.68, 3637.5, 692.8, 2173.6 + 0.35, 15000.0, 0.72, 4243.6, 753.6, 2413.2 + 0.35, 15000.0, 0.76, 4849.9, 817.1, 2662.0 + 0.35, 15000.0, 0.8, 5456.2, 880.7, 2913.5 + 0.35, 15000.0, 0.84, 5803.45, 917.546, 3059.57 + 0.35, 15000.0, 0.88, 5994.0, 938.449, 3142.95 + 0.35, 15000.0, 0.92, 6179.82, 959.387, 3227.0 + 0.35, 15000.0, 0.96, 6413.65, 986.002, 3333.86 + 0.35, 15000.0, 1.0, 6649.0, 1013.6, 3444.5 + 0.35, 20000.0, 0.52, 1326.4, 495.7, 1302.2 + 0.35, 20000.0, 0.56, 1989.4, 564.4, 1553.3 + 0.35, 20000.0, 0.6, 2652.4, 632.1, 1806.5 + 0.35, 20000.0, 0.64, 3316.1, 699.7, 2062.2 + 0.35, 20000.0, 0.68, 3979.5, 767.0, 2318.4 + 0.35, 20000.0, 0.72, 4642.7, 835.7, 2581.4 + 0.35, 20000.0, 0.76, 5305.7, 908.1, 2856.6 + 0.35, 20000.0, 0.8, 5969.1, 980.1, 3135.4 + 0.35, 20000.0, 0.84, 6349.34, 1022.63, 3298.81 + 0.35, 20000.0, 0.88, 6557.66, 1047.36, 3392.83 + 0.35, 20000.0, 0.92, 6758.94, 1071.46, 3485.28 + 0.35, 20000.0, 0.96, 7010.75, 1101.08, 3600.38 + 0.35, 20000.0, 1.0, 7263.3, 1131.4, 3718.7 + 0.35, 25000.0, 0.52, 1467.6, 560.9, 1401.7 + 0.35, 25000.0, 0.56, 2202.7, 637.6, 1678.9 + 0.35, 25000.0, 0.6, 2936.5, 713.9, 1956.3 + 0.35, 25000.0, 0.64, 3670.4, 790.0, 2237.3 + 0.35, 25000.0, 0.68, 4405.3, 865.3, 2517.6 + 0.35, 25000.0, 0.72, 5138.0, 942.4, 2804.8 + 0.35, 25000.0, 0.76, 5875.1, 1024.0, 3109.5 + 0.35, 25000.0, 0.8, 6606.8, 1107.0, 3418.4 + 0.35, 25000.0, 0.84, 7028.11, 1156.09, 3602.25 + 0.35, 25000.0, 0.88, 7260.04, 1184.46, 3709.8 + 0.35, 25000.0, 0.92, 7481.34, 1211.35, 3812.17 + 0.35, 25000.0, 0.96, 7755.3, 1243.91, 3935.77 + 0.35, 25000.0, 1.0, 8029.7, 1277.2, 4062.3 + 0.35, 30000.0, 0.52, 1608.1, 616.2, 1474.4 + 0.35, 30000.0, 0.56, 2415.3, 702.8, 1779.3 + 0.35, 30000.0, 0.6, 3219.4, 789.7, 2083.1 + 0.35, 30000.0, 0.64, 4022.2, 875.7, 2394.0 + 0.35, 30000.0, 0.68, 4827.5, 962.0, 2705.6 + 0.35, 30000.0, 0.72, 5632.1, 1048.0, 3017.8 + 0.35, 30000.0, 0.76, 6437.2, 1142.0, 3356.6 + 0.35, 30000.0, 0.8, 7242.8, 1236.3, 3702.1 + 0.35, 30000.0, 0.84, 7704.91, 1291.57, 3904.85 + 0.35, 30000.0, 0.88, 7957.09, 1322.95, 4020.52 + 0.35, 30000.0, 0.92, 8196.61, 1352.52, 4130.58 + 0.35, 30000.0, 0.96, 8493.34, 1388.47, 4264.91 + 0.35, 30000.0, 1.0, 8789.8, 1425.0, 4401.8 + 0.35, 35000.0, 0.52, 1754.1, 656.3, 1549.7 + 0.35, 35000.0, 0.56, 2629.2, 751.1, 1880.0 + 0.35, 35000.0, 0.6, 3503.8, 845.9, 2213.5 + 0.35, 35000.0, 0.64, 4381.7, 939.5, 2545.9 + 0.35, 35000.0, 0.68, 5257.5, 1035.1, 2886.6 + 0.35, 35000.0, 0.72, 6133.0, 1127.7, 3224.9 + 0.35, 35000.0, 0.76, 7011.6, 1231.9, 3595.5 + 0.35, 35000.0, 0.8, 7887.1, 1338.4, 3980.8 + 0.35, 35000.0, 0.84, 8390.21, 1400.07, 4205.58 + 0.35, 35000.0, 0.88, 8664.5, 1434.18, 4331.75 + 0.35, 35000.0, 0.92, 8921.61, 1465.91, 4449.68 + 0.35, 35000.0, 0.96, 9237.06, 1504.6, 4592.82 + 0.35, 35000.0, 1.0, 9550.2, 1543.8, 4737.7 + 0.4, 0.0, 0.52, 773.9, 189.1, 904.8 + 0.4, 0.0, 0.56, 1160.7, 224.3, 1058.0 + 0.4, 0.0, 0.6, 1547.7, 259.2, 1211.8 + 0.4, 0.0, 0.64, 1934.6, 293.9, 1366.1 + 0.4, 0.0, 0.68, 2321.6, 328.4, 1521.6 + 0.4, 0.0, 0.72, 2708.5, 365.2, 1684.8 + 0.4, 0.0, 0.76, 3095.5, 402.7, 1851.7 + 0.4, 0.0, 0.8, 3482.3, 439.9, 2019.3 + 0.4, 0.0, 0.84, 3700.52, 460.902, 2114.33 + 0.4, 0.0, 0.88, 3822.18, 472.639, 2167.97 + 0.4, 0.0, 0.92, 3957.29, 485.573, 2227.32 + 0.4, 0.0, 0.96, 4139.87, 503.11, 2307.61 + 0.4, 0.0, 1.0, 4327.9, 521.6, 2392.2 + 0.4, 5000.0, 0.52, 860.9, 225.2, 964.9 + 0.4, 5000.0, 0.56, 1291.4, 265.1, 1133.4 + 0.4, 5000.0, 0.6, 1721.8, 304.8, 1302.9 + 0.4, 5000.0, 0.64, 2152.3, 345.3, 1476.0 + 0.4, 5000.0, 0.68, 2582.7, 385.4, 1649.6 + 0.4, 5000.0, 0.72, 3013.2, 426.8, 1828.8 + 0.4, 5000.0, 0.76, 3443.6, 469.6, 2013.5 + 0.4, 5000.0, 0.8, 3874.1, 512.4, 2199.7 + 0.4, 5000.0, 0.84, 4117.34, 536.528, 2305.25 + 0.4, 5000.0, 0.88, 4252.59, 549.888, 2364.46 + 0.4, 5000.0, 0.92, 4401.11, 564.394, 2429.11 + 0.4, 5000.0, 0.96, 4600.22, 583.939, 2516.02 + 0.4, 5000.0, 1.0, 4803.3, 604.4, 2607.0 + 0.4, 10000.0, 0.52, 1082.3, 338.4, 1117.9 + 0.4, 10000.0, 0.56, 1623.4, 393.0, 1326.4 + 0.4, 10000.0, 0.6, 2164.6, 447.3, 1535.8 + 0.4, 10000.0, 0.64, 2705.7, 501.1, 1746.4 + 0.4, 10000.0, 0.68, 3247.0, 554.8, 1958.4 + 0.4, 10000.0, 0.72, 3788.2, 610.1, 2176.7 + 0.4, 10000.0, 0.76, 4329.3, 667.8, 2403.0 + 0.4, 10000.0, 0.8, 4870.4, 725.5, 2631.7 + 0.4, 10000.0, 0.84, 5179.05, 758.25, 2762.22 + 0.4, 10000.0, 0.88, 5349.16, 776.293, 2835.05 + 0.4, 10000.0, 0.92, 5521.96, 794.912, 2910.76 + 0.4, 10000.0, 0.96, 5744.03, 819.308, 3009.79 + 0.4, 10000.0, 1.0, 5967.2, 844.6, 3112.5 + 0.4, 15000.0, 0.52, 1202.2, 398.0, 1218.9 + 0.4, 15000.0, 0.56, 1803.3, 458.3, 1445.1 + 0.4, 15000.0, 0.6, 2404.4, 518.3, 1672.9 + 0.4, 15000.0, 0.64, 3005.5, 578.1, 1902.3 + 0.4, 15000.0, 0.68, 3606.6, 637.9, 2133.6 + 0.4, 15000.0, 0.72, 4207.5, 699.4, 2371.3 + 0.4, 15000.0, 0.76, 4808.6, 763.7, 2618.5 + 0.4, 15000.0, 0.8, 5409.7, 828.2, 2868.8 + 0.4, 15000.0, 0.84, 5754.11, 865.295, 3013.32 + 0.4, 15000.0, 0.88, 5943.02, 886.07, 3094.95 + 0.4, 15000.0, 0.92, 6126.62, 906.918, 3177.3 + 0.4, 15000.0, 0.96, 6357.15, 933.611, 3282.56 + 0.4, 15000.0, 1.0, 6588.9, 961.3, 3391.6 + 0.4, 20000.0, 0.52, 1319.9, 456.6, 1309.5 + 0.4, 20000.0, 0.56, 1979.8, 523.1, 1553.7 + 0.4, 20000.0, 0.6, 2639.7, 589.4, 1799.8 + 0.4, 20000.0, 0.64, 3299.6, 655.6, 2048.1 + 0.4, 20000.0, 0.68, 3959.6, 721.8, 2298.4 + 0.4, 20000.0, 0.72, 4619.5, 789.6, 2555.1 + 0.4, 20000.0, 0.76, 5279.4, 860.9, 2823.0 + 0.4, 20000.0, 0.8, 5939.4, 932.5, 3094.1 + 0.4, 20000.0, 0.84, 6317.95, 975.102, 3255.39 + 0.4, 20000.0, 0.88, 6525.33, 1000.17, 3350.42 + 0.4, 20000.0, 0.92, 6724.82, 1024.48, 3443.18 + 0.4, 20000.0, 0.96, 6973.71, 1054.17, 3556.77 + 0.4, 20000.0, 1.0, 7223.3, 1084.7, 3673.4 + 0.4, 25000.0, 0.52, 1455.0, 503.8, 1374.1 + 0.4, 25000.0, 0.56, 2182.7, 580.7, 1646.7 + 0.4, 25000.0, 0.6, 2910.0, 657.2, 1921.1 + 0.4, 25000.0, 0.64, 3637.7, 733.5, 2197.9 + 0.4, 25000.0, 0.68, 4365.3, 809.8, 2477.0 + 0.4, 25000.0, 0.72, 5092.7, 886.9, 2760.8 + 0.4, 25000.0, 0.76, 5820.4, 968.9, 3060.1 + 0.4, 25000.0, 0.8, 6547.7, 1052.5, 3366.7 + 0.4, 25000.0, 0.84, 6965.43, 1101.84, 3548.52 + 0.4, 25000.0, 0.88, 7194.19, 1130.26, 3654.34 + 0.4, 25000.0, 0.92, 7412.21, 1157.24, 3755.52 + 0.4, 25000.0, 0.96, 7682.46, 1190.0, 3878.28 + 0.4, 25000.0, 1.0, 7952.7, 1223.5, 4003.7 + 0.4, 30000.0, 0.52, 1593.4, 557.1, 1444.1 + 0.4, 30000.0, 0.56, 2390.5, 644.4, 1744.4 + 0.4, 30000.0, 0.6, 3187.2, 731.4, 2046.6 + 0.4, 30000.0, 0.64, 3983.9, 818.0, 2351.9 + 0.4, 30000.0, 0.68, 4780.6, 904.6, 2659.8 + 0.4, 30000.0, 0.72, 5577.6, 991.3, 2971.0 + 0.4, 30000.0, 0.76, 6374.3, 1084.6, 3301.6 + 0.4, 30000.0, 0.8, 7171.0, 1181.1, 3647.0 + 0.4, 30000.0, 0.84, 7628.86, 1237.13, 3848.69 + 0.4, 30000.0, 0.88, 7879.25, 1268.37, 3962.64 + 0.4, 30000.0, 0.92, 8116.03, 1297.72, 4070.71 + 0.4, 30000.0, 0.96, 8408.08, 1333.66, 4202.97 + 0.4, 30000.0, 1.0, 8699.3, 1370.3, 4337.7 + 0.4, 35000.0, 0.52, 1740.5, 601.2, 1523.1 + 0.4, 35000.0, 0.56, 2610.7, 697.5, 1850.2 + 0.4, 35000.0, 0.6, 3480.5, 793.3, 2179.4 + 0.4, 35000.0, 0.64, 4350.7, 888.8, 2511.7 + 0.4, 35000.0, 0.68, 5220.9, 984.3, 2847.8 + 0.4, 35000.0, 0.72, 6091.1, 1079.4, 3186.5 + 0.4, 35000.0, 0.76, 6961.4, 1183.5, 3551.5 + 0.4, 35000.0, 0.8, 7831.6, 1292.7, 3937.1 + 0.4, 35000.0, 0.84, 8332.42, 1355.41, 4160.01 + 0.4, 35000.0, 0.88, 8605.91, 1389.55, 4283.17 + 0.4, 35000.0, 0.92, 8861.41, 1421.21, 4398.5 + 0.4, 35000.0, 0.96, 9173.69, 1460.11, 4539.94 + 0.4, 35000.0, 1.0, 9483.0, 1499.6, 4683.4 + 0.45, 0.0, 0.52, 766.7, 139.4, 872.4 + 0.45, 0.0, 0.56, 1150.1, 174.9, 1023.9 + 0.45, 0.0, 0.6, 1533.6, 210.1, 1175.9 + 0.45, 0.0, 0.64, 1916.9, 245.0, 1328.4 + 0.45, 0.0, 0.68, 2300.3, 280.5, 1483.8 + 0.45, 0.0, 0.72, 2683.6, 317.4, 1644.9 + 0.45, 0.0, 0.76, 3067.0, 355.0, 1809.7 + 0.45, 0.0, 0.8, 3450.4, 392.9, 1976.5 + 0.45, 0.0, 0.84, 3666.8, 414.236, 2070.93 + 0.45, 0.0, 0.88, 3787.3, 426.056, 2123.95 + 0.45, 0.0, 0.92, 3920.29, 438.961, 2182.27 + 0.45, 0.0, 0.96, 4099.56, 456.446, 2261.1 + 0.45, 0.0, 1.0, 4284.3, 474.9, 2344.1 + 0.45, 5000.0, 0.52, 852.3, 173.7, 931.3 + 0.45, 5000.0, 0.56, 1278.4, 213.8, 1097.8 + 0.45, 5000.0, 0.6, 1704.4, 254.5, 1267.0 + 0.45, 5000.0, 0.64, 2130.6, 295.2, 1438.0 + 0.45, 5000.0, 0.68, 2556.7, 335.7, 1609.8 + 0.45, 5000.0, 0.72, 2982.8, 377.4, 1786.8 + 0.45, 5000.0, 0.76, 3409.0, 420.5, 1969.5 + 0.45, 5000.0, 0.8, 3835.1, 463.6, 2153.8 + 0.45, 5000.0, 0.84, 4076.0, 487.911, 2258.29 + 0.45, 5000.0, 0.88, 4209.87, 501.366, 2316.8 + 0.45, 5000.0, 0.92, 4356.03, 515.898, 2380.39 + 0.45, 5000.0, 0.96, 4551.52, 535.437, 2465.69 + 0.45, 5000.0, 1.0, 4751.1, 555.9, 2555.0 + 0.45, 10000.0, 0.52, 1070.4, 283.5, 1082.1 + 0.45, 10000.0, 0.56, 1605.5, 338.8, 1288.5 + 0.45, 10000.0, 0.6, 2140.7, 393.6, 1495.7 + 0.45, 10000.0, 0.64, 2675.9, 448.1, 1704.2 + 0.45, 10000.0, 0.68, 3211.0, 502.6, 1914.6 + 0.45, 10000.0, 0.72, 3746.2, 558.2, 2130.1 + 0.45, 10000.0, 0.76, 4281.3, 616.5, 2354.4 + 0.45, 10000.0, 0.8, 4816.6, 674.7, 2580.9 + 0.45, 10000.0, 0.84, 5121.68, 707.797, 2710.14 + 0.45, 10000.0, 0.88, 5289.82, 726.089, 2782.24 + 0.45, 10000.0, 0.92, 5461.78, 744.946, 2857.22 + 0.45, 10000.0, 0.96, 5683.38, 769.593, 2955.28 + 0.45, 10000.0, 1.0, 5905.6, 795.1, 3056.8 + 0.45, 15000.0, 0.52, 1189.7, 341.3, 1181.0 + 0.45, 15000.0, 0.56, 1784.3, 402.4, 1405.4 + 0.45, 15000.0, 0.6, 2379.1, 463.2, 1631.2 + 0.45, 15000.0, 0.64, 2974.0, 523.8, 1858.8 + 0.45, 15000.0, 0.68, 3568.8, 584.3, 2088.1 + 0.45, 15000.0, 0.72, 4163.5, 646.5, 2323.9 + 0.45, 15000.0, 0.76, 4758.3, 711.6, 2569.1 + 0.45, 15000.0, 0.8, 5353.1, 776.9, 2817.2 + 0.45, 15000.0, 0.84, 5694.05, 814.22, 2959.84 + 0.45, 15000.0, 0.88, 5880.99, 834.88, 3039.78 + 0.45, 15000.0, 0.92, 6061.95, 855.63, 3120.41 + 0.45, 15000.0, 0.96, 6288.55, 882.359, 3223.88 + 0.45, 15000.0, 1.0, 6516.0, 910.1, 3331.1 + 0.45, 20000.0, 0.52, 1307.2, 405.2, 1283.6 + 0.45, 20000.0, 0.56, 1960.8, 471.7, 1524.3 + 0.45, 20000.0, 0.6, 2614.4, 538.1, 1766.7 + 0.45, 20000.0, 0.64, 3267.8, 604.4, 2011.1 + 0.45, 20000.0, 0.68, 3921.4, 670.8, 2258.0 + 0.45, 20000.0, 0.72, 4575.0, 738.8, 2511.0 + 0.45, 20000.0, 0.76, 5228.6, 810.4, 2775.2 + 0.45, 20000.0, 0.8, 5882.2, 882.3, 3042.4 + 0.45, 20000.0, 0.84, 6257.27, 925.009, 3201.29 + 0.45, 20000.0, 0.88, 6462.68, 950.074, 3294.82 + 0.45, 20000.0, 0.92, 6659.56, 974.423, 3386.09 + 0.45, 20000.0, 0.96, 6904.56, 1004.23, 3497.89 + 0.45, 20000.0, 1.0, 7149.9, 1034.9, 3612.7 + 0.45, 25000.0, 0.52, 1440.0, 449.4, 1344.2 + 0.45, 25000.0, 0.56, 2160.1, 526.5, 1612.8 + 0.45, 25000.0, 0.6, 2880.0, 603.3, 1883.4 + 0.45, 25000.0, 0.64, 3600.1, 679.9, 2156.3 + 0.45, 25000.0, 0.68, 4320.0, 756.6, 2432.0 + 0.45, 25000.0, 0.72, 5040.1, 834.0, 2712.2 + 0.45, 25000.0, 0.76, 5759.9, 916.5, 3007.2 + 0.45, 25000.0, 0.8, 6480.1, 1000.0, 3308.4 + 0.45, 25000.0, 0.84, 6893.67, 1049.65, 3487.91 + 0.45, 25000.0, 0.88, 7119.84, 1078.59, 3593.18 + 0.45, 25000.0, 0.92, 7334.7, 1105.95, 3693.55 + 0.45, 25000.0, 0.96, 7600.59, 1138.87, 3814.6 + 0.45, 25000.0, 1.0, 7866.1, 1172.5, 3938.1 + 0.45, 30000.0, 0.52, 1575.8, 500.5, 1411.0 + 0.45, 30000.0, 0.56, 2363.5, 588.3, 1707.1 + 0.45, 30000.0, 0.6, 3151.2, 675.7, 2005.7 + 0.45, 30000.0, 0.64, 3939.3, 762.8, 2306.5 + 0.45, 30000.0, 0.68, 4727.0, 849.9, 2610.6 + 0.45, 30000.0, 0.72, 5515.0, 936.8, 2917.6 + 0.45, 30000.0, 0.76, 6302.8, 1030.7, 3243.9 + 0.45, 30000.0, 0.8, 7090.5, 1128.0, 3585.0 + 0.45, 30000.0, 0.84, 7543.44, 1184.53, 3784.5 + 0.45, 30000.0, 0.88, 7791.14, 1216.07, 3897.42 + 0.45, 30000.0, 0.92, 8024.64, 1245.61, 4004.14 + 0.45, 30000.0, 0.96, 8311.93, 1281.71, 4134.31 + 0.45, 30000.0, 1.0, 8598.0, 1318.5, 4266.8 + 0.45, 35000.0, 0.52, 1725.5, 549.1, 1492.7 + 0.45, 35000.0, 0.56, 2588.5, 646.7, 1816.7 + 0.45, 35000.0, 0.6, 3451.4, 744.0, 2143.2 + 0.45, 35000.0, 0.64, 4314.0, 841.0, 2473.1 + 0.45, 35000.0, 0.68, 5176.9, 937.7, 2806.3 + 0.45, 35000.0, 0.72, 6039.9, 1034.8, 3143.6 + 0.45, 35000.0, 0.76, 6902.4, 1139.6, 3503.1 + 0.45, 35000.0, 0.8, 7765.4, 1250.2, 3885.4 + 0.45, 35000.0, 0.84, 8262.19, 1313.73, 4106.42 + 0.45, 35000.0, 0.88, 8533.42, 1348.3, 4228.49 + 0.45, 35000.0, 0.92, 8786.16, 1380.33, 4342.61 + 0.45, 35000.0, 0.96, 9094.61, 1419.65, 4482.43 + 0.45, 35000.0, 1.0, 9400.1, 1459.6, 4624.3 + 0.5, 0.0, 0.52, 758.8, 91.2, 837.3 + 0.5, 0.0, 0.56, 1138.2, 127.1, 987.0 + 0.5, 0.0, 0.6, 1517.6, 162.5, 1136.9 + 0.5, 0.0, 0.64, 1897.0, 198.2, 1288.8 + 0.5, 0.0, 0.68, 2276.4, 234.2, 1442.9 + 0.5, 0.0, 0.72, 2655.8, 271.3, 1601.6 + 0.5, 0.0, 0.76, 3035.2, 309.5, 1765.0 + 0.5, 0.0, 0.8, 3414.6, 347.7, 1930.1 + 0.5, 0.0, 0.84, 3628.94, 369.256, 2023.55 + 0.5, 0.0, 0.88, 3748.23, 381.216, 2075.9 + 0.5, 0.0, 0.92, 3878.96, 394.155, 2133.16 + 0.5, 0.0, 0.96, 4054.64, 411.594, 2210.4 + 0.5, 0.0, 1.0, 4235.8, 430.0, 2291.7 + 0.5, 5000.0, 0.52, 842.5, 123.7, 895.0 + 0.5, 5000.0, 0.56, 1263.8, 164.5, 1060.1 + 0.5, 5000.0, 0.6, 1685.2, 205.9, 1228.3 + 0.5, 5000.0, 0.64, 2106.4, 247.0, 1397.0 + 0.5, 5000.0, 0.68, 2527.7, 287.8, 1566.8 + 0.5, 5000.0, 0.72, 2949.0, 329.8, 1741.4 + 0.5, 5000.0, 0.76, 3370.3, 373.3, 1921.8 + 0.5, 5000.0, 0.8, 3791.5, 416.7, 2103.8 + 0.5, 5000.0, 0.84, 4029.85, 441.231, 2207.08 + 0.5, 5000.0, 0.88, 4162.28, 454.826, 2264.92 + 0.5, 5000.0, 0.92, 4305.89, 469.386, 2327.42 + 0.5, 5000.0, 0.96, 4497.41, 488.873, 2411.01 + 0.5, 5000.0, 1.0, 4693.1, 509.3, 2498.5 + 0.5, 10000.0, 0.52, 1057.1, 230.5, 1043.6 + 0.5, 10000.0, 0.56, 1585.6, 286.4, 1247.6 + 0.5, 10000.0, 0.6, 2114.1, 341.9, 1452.5 + 0.5, 10000.0, 0.64, 2642.8, 397.0, 1658.6 + 0.5, 10000.0, 0.68, 3171.3, 452.2, 1866.8 + 0.5, 10000.0, 0.72, 3699.9, 508.3, 2079.5 + 0.5, 10000.0, 0.76, 4228.4, 567.3, 2301.3 + 0.5, 10000.0, 0.8, 4756.9, 626.2, 2525.4 + 0.5, 10000.0, 0.84, 5058.0, 659.701, 2653.35 + 0.5, 10000.0, 0.88, 5224.15, 678.213, 2724.79 + 0.5, 10000.0, 0.92, 5395.2, 697.281, 2799.06 + 0.5, 10000.0, 0.96, 5616.16, 722.178, 2896.08 + 0.5, 10000.0, 1.0, 5837.2, 747.9, 2996.3 + 0.5, 15000.0, 0.52, 1174.8, 286.4, 1140.1 + 0.5, 15000.0, 0.56, 1762.3, 348.3, 1362.2 + 0.5, 15000.0, 0.6, 2349.6, 410.0, 1585.8 + 0.5, 15000.0, 0.64, 2937.1, 471.4, 1811.0 + 0.5, 15000.0, 0.68, 3524.5, 532.7, 2038.0 + 0.5, 15000.0, 0.72, 4112.0, 595.5, 2271.0 + 0.5, 15000.0, 0.76, 4699.3, 661.4, 2514.1 + 0.5, 15000.0, 0.8, 5286.8, 727.4, 2759.8 + 0.5, 15000.0, 0.84, 5623.52, 765.038, 2900.54 + 0.5, 15000.0, 0.88, 5808.07, 785.781, 2978.91 + 0.5, 15000.0, 0.92, 5986.79, 806.601, 3058.06 + 0.5, 15000.0, 0.96, 6210.59, 833.458, 3160.0 + 0.5, 15000.0, 1.0, 6434.9, 861.3, 3265.5 + 0.5, 20000.0, 0.52, 1290.6, 348.7, 1239.9 + 0.5, 20000.0, 0.56, 1935.9, 416.3, 1478.5 + 0.5, 20000.0, 0.6, 2581.2, 483.6, 1718.7 + 0.5, 20000.0, 0.64, 3226.4, 550.8, 1960.9 + 0.5, 20000.0, 0.68, 3871.7, 618.1, 2205.5 + 0.5, 20000.0, 0.72, 4517.0, 686.9, 2456.0 + 0.5, 20000.0, 0.76, 5162.3, 759.5, 2718.1 + 0.5, 20000.0, 0.8, 5807.6, 832.2, 2983.2 + 0.5, 20000.0, 0.84, 6178.07, 875.064, 3139.51 + 0.5, 20000.0, 0.88, 6380.88, 899.924, 3230.28 + 0.5, 20000.0, 0.92, 6574.53, 924.154, 3319.12 + 0.5, 20000.0, 0.96, 6814.87, 954.043, 3428.89 + 0.5, 20000.0, 1.0, 7055.1, 984.8, 3541.7 + 0.5, 25000.0, 0.52, 1423.0, 397.9, 1312.6 + 0.5, 25000.0, 0.56, 2134.8, 475.2, 1577.0 + 0.5, 25000.0, 0.6, 2846.3, 552.3, 1843.3 + 0.5, 25000.0, 0.64, 3557.8, 629.2, 2112.1 + 0.5, 25000.0, 0.68, 4269.3, 706.1, 2383.3 + 0.5, 25000.0, 0.72, 4980.8, 783.9, 2659.4 + 0.5, 25000.0, 0.76, 5692.6, 866.9, 2950.4 + 0.5, 25000.0, 0.8, 6404.1, 950.3, 3245.5 + 0.5, 25000.0, 0.84, 6812.97, 1000.27, 3422.34 + 0.5, 25000.0, 0.88, 7036.58, 1029.72, 3526.88 + 0.5, 25000.0, 0.92, 7248.19, 1057.46, 3626.18 + 0.5, 25000.0, 0.96, 7509.3, 1090.54, 3745.13 + 0.5, 25000.0, 1.0, 7769.7, 1124.3, 3866.4 + 0.5, 30000.0, 0.52, 1555.8, 446.7, 1375.8 + 0.5, 30000.0, 0.56, 2333.7, 534.9, 1667.5 + 0.5, 30000.0, 0.6, 3111.3, 622.8, 1961.4 + 0.5, 30000.0, 0.64, 3889.2, 710.4, 2258.0 + 0.5, 30000.0, 0.68, 4667.1, 798.0, 2557.8 + 0.5, 30000.0, 0.72, 5445.0, 885.2, 2859.7 + 0.5, 30000.0, 0.76, 6223.0, 980.1, 3182.7 + 0.5, 30000.0, 0.8, 7000.9, 1077.5, 3517.2 + 0.5, 30000.0, 0.84, 7448.27, 1134.4, 3713.77 + 0.5, 30000.0, 0.88, 7692.75, 1166.43, 3825.84 + 0.5, 30000.0, 0.92, 7922.54, 1196.34, 3931.43 + 0.5, 30000.0, 0.96, 8204.73, 1232.65, 4059.43 + 0.5, 30000.0, 1.0, 8485.3, 1269.6, 4189.6 + 0.5, 35000.0, 0.52, 1708.5, 499.9, 1459.5 + 0.5, 35000.0, 0.56, 2562.7, 599.0, 1780.4 + 0.5, 35000.0, 0.6, 3417.0, 698.0, 2104.5 + 0.5, 35000.0, 0.64, 4271.2, 796.5, 2431.0 + 0.5, 35000.0, 0.68, 5125.4, 895.1, 2761.9 + 0.5, 35000.0, 0.72, 5979.7, 993.9, 3096.5 + 0.5, 35000.0, 0.76, 6833.9, 1099.9, 3451.1 + 0.5, 35000.0, 0.8, 7688.2, 1211.4, 3827.8 + 0.5, 35000.0, 0.84, 8179.94, 1275.68, 4046.57 + 0.5, 35000.0, 0.88, 8448.2, 1310.91, 4168.3 + 0.5, 35000.0, 0.92, 8697.62, 1343.5, 4281.75 + 0.5, 35000.0, 0.96, 9001.75, 1383.34, 4419.9 + 0.5, 35000.0, 1.0, 9303.1, 1423.8, 4560.0 + 0.55, 0.0, 0.52, 751.1, 44.8, 799.7 + 0.55, 0.0, 0.56, 1125.8, 81.4, 947.7 + 0.55, 0.0, 0.6, 1500.6, 116.8, 1095.4 + 0.55, 0.0, 0.64, 1876.3, 154.6, 1249.4 + 0.55, 0.0, 0.68, 2251.7, 189.4, 1398.7 + 0.55, 0.0, 0.72, 2627.4, 227.5, 1555.9 + 0.55, 0.0, 0.76, 3002.9, 267.6, 1719.8 + 0.55, 0.0, 0.8, 3377.5, 304.8, 1880.7 + 0.55, 0.0, 0.84, 3589.66, 326.262, 1972.56 + 0.55, 0.0, 0.88, 3707.99, 338.639, 2024.73 + 0.55, 0.0, 0.92, 3836.57, 351.918, 2081.34 + 0.55, 0.0, 0.96, 4008.52, 369.421, 2156.94 + 0.55, 0.0, 1.0, 4186.0, 387.8, 2236.5 + 0.55, 5000.0, 0.52, 831.9, 75.4, 856.5 + 0.55, 5000.0, 0.56, 1248.6, 118.0, 1021.7 + 0.55, 5000.0, 0.6, 1665.9, 159.0, 1186.6 + 0.55, 5000.0, 0.64, 2081.6, 201.5, 1354.2 + 0.55, 5000.0, 0.68, 2497.8, 242.3, 1521.5 + 0.55, 5000.0, 0.72, 2914.5, 284.6, 1694.1 + 0.55, 5000.0, 0.76, 3330.1, 328.8, 1872.0 + 0.55, 5000.0, 0.8, 3746.4, 372.6, 2051.1 + 0.55, 5000.0, 0.84, 3982.31, 397.449, 2153.01 + 0.55, 5000.0, 0.88, 4113.37, 411.261, 2210.26 + 0.55, 5000.0, 0.92, 4254.33, 425.859, 2271.77 + 0.55, 5000.0, 0.96, 4441.54, 445.246, 2353.68 + 0.55, 5000.0, 1.0, 4633.0, 465.6, 2439.3 + 0.55, 10000.0, 0.52, 1042.6, 179.3, 1002.6 + 0.55, 10000.0, 0.56, 1564.0, 236.0, 1204.0 + 0.55, 10000.0, 0.6, 2085.4, 292.2, 1406.4 + 0.55, 10000.0, 0.64, 2606.6, 348.0, 1610.0 + 0.55, 10000.0, 0.68, 3128.0, 403.7, 1815.2 + 0.55, 10000.0, 0.72, 3649.4, 460.6, 2025.3 + 0.55, 10000.0, 0.76, 4170.6, 520.3, 2244.7 + 0.55, 10000.0, 0.8, 4692.0, 580.1, 2466.3 + 0.55, 10000.0, 0.84, 4988.78, 614.022, 2592.79 + 0.55, 10000.0, 0.88, 5152.55, 632.679, 2663.35 + 0.55, 10000.0, 0.92, 5322.4, 651.96, 2736.72 + 0.55, 10000.0, 0.96, 5542.49, 677.204, 2832.53 + 0.55, 10000.0, 1.0, 5762.1, 703.2, 2931.3 + 0.55, 15000.0, 0.52, 1157.3, 233.3, 1096.0 + 0.55, 15000.0, 0.56, 1735.8, 296.1, 1315.5 + 0.55, 15000.0, 0.6, 2314.5, 358.6, 1536.2 + 0.55, 15000.0, 0.64, 2893.2, 420.7, 1758.5 + 0.55, 15000.0, 0.68, 3471.8, 482.8, 1982.8 + 0.55, 15000.0, 0.72, 4050.5, 546.2, 2212.7 + 0.55, 15000.0, 0.76, 4629.0, 612.8, 2452.5 + 0.55, 15000.0, 0.8, 5207.7, 679.7, 2695.3 + 0.55, 15000.0, 0.84, 5539.11, 717.795, 2834.43 + 0.55, 15000.0, 0.88, 5720.94, 738.73, 2911.93 + 0.55, 15000.0, 0.92, 5898.78, 759.76, 2990.21 + 0.55, 15000.0, 0.96, 6122.45, 786.916, 3090.91 + 0.55, 15000.0, 1.0, 6346.0, 815.0, 3194.9 + 0.55, 20000.0, 0.52, 1272.4, 294.3, 1193.8 + 0.55, 20000.0, 0.56, 1908.6, 363.0, 1429.7 + 0.55, 20000.0, 0.6, 2544.8, 431.3, 1667.3 + 0.55, 20000.0, 0.64, 3181.1, 499.5, 1907.2 + 0.55, 20000.0, 0.68, 3817.3, 567.8, 2149.2 + 0.55, 20000.0, 0.72, 4453.3, 637.5, 2397.0 + 0.55, 20000.0, 0.76, 5089.5, 711.1, 2656.6 + 0.55, 20000.0, 0.8, 5725.7, 784.9, 2919.4 + 0.55, 20000.0, 0.84, 6091.13, 827.981, 3073.07 + 0.55, 20000.0, 0.88, 6291.08, 852.546, 3161.06 + 0.55, 20000.0, 0.92, 6481.1, 876.533, 3247.38 + 0.55, 20000.0, 0.96, 6716.22, 906.414, 3354.94 + 0.55, 20000.0, 1.0, 6950.9, 937.2, 3465.5 + 0.55, 25000.0, 0.52, 1404.4, 349.5, 1279.9 + 0.55, 25000.0, 0.56, 2106.7, 427.0, 1539.1 + 0.55, 25000.0, 0.6, 2808.7, 504.3, 1800.9 + 0.55, 25000.0, 0.64, 3511.0, 581.4, 2064.9 + 0.55, 25000.0, 0.68, 4213.1, 658.7, 2331.6 + 0.55, 25000.0, 0.72, 4915.4, 736.8, 2602.8 + 0.55, 25000.0, 0.76, 5617.5, 820.2, 2889.3 + 0.55, 25000.0, 0.8, 6319.8, 904.2, 3180.0 + 0.55, 25000.0, 0.84, 6723.45, 954.415, 3353.73 + 0.55, 25000.0, 0.88, 6944.03, 983.923, 3456.02 + 0.55, 25000.0, 0.92, 7152.09, 1011.75, 3553.34 + 0.55, 25000.0, 0.96, 7408.26, 1045.03, 3670.28 + 0.55, 25000.0, 1.0, 7663.3, 1079.0, 3789.5 + 0.55, 30000.0, 0.52, 1533.9, 396.0, 1339.2 + 0.55, 30000.0, 0.56, 2300.5, 484.6, 1625.7 + 0.55, 30000.0, 0.6, 3067.4, 572.9, 1914.7 + 0.55, 30000.0, 0.64, 3834.4, 661.1, 2206.6 + 0.55, 30000.0, 0.68, 4601.3, 749.0, 2501.2 + 0.55, 30000.0, 0.72, 5368.3, 837.2, 2799.4 + 0.55, 30000.0, 0.76, 6135.2, 932.6, 3117.2 + 0.55, 30000.0, 0.8, 6901.8, 1030.1, 3444.7 + 0.55, 30000.0, 0.84, 7342.98, 1087.34, 3637.97 + 0.55, 30000.0, 0.88, 7584.09, 1119.81, 3748.9 + 0.55, 30000.0, 0.92, 7809.87, 1150.04, 3853.15 + 0.55, 30000.0, 0.96, 8086.3, 1186.49, 3978.85 + 0.55, 30000.0, 1.0, 8360.6, 1223.6, 4106.6 + 0.55, 35000.0, 0.52, 1688.9, 453.5, 1424.5 + 0.55, 35000.0, 0.56, 2533.4, 554.7, 1742.2 + 0.55, 35000.0, 0.6, 3377.8, 655.3, 2062.9 + 0.55, 35000.0, 0.64, 4221.9, 755.7, 2386.3 + 0.55, 35000.0, 0.68, 5066.3, 856.3, 2714.4 + 0.55, 35000.0, 0.72, 5910.8, 956.7, 3045.5 + 0.55, 35000.0, 0.76, 6755.2, 1064.1, 3396.3 + 0.55, 35000.0, 0.8, 7599.7, 1176.8, 3766.4 + 0.55, 35000.0, 0.84, 8086.04, 1241.97, 3982.24 + 0.55, 35000.0, 0.88, 8351.41, 1277.84, 4103.17 + 0.55, 35000.0, 0.92, 8597.51, 1310.96, 4215.65 + 0.55, 35000.0, 0.96, 8897.02, 1351.28, 4351.94 + 0.55, 35000.0, 1.0, 9193.6, 1392.2, 4490.1 + 0.6, 0.0, 0.52, 744.5, 0.5, 759.8 + 0.6, 0.0, 0.56, 1113.7, 38.3, 906.4 + 0.6, 0.0, 0.6, 1483.5, 73.4, 1052.0 + 0.6, 0.0, 0.64, 1856.2, 115.3, 1212.3 + 0.6, 0.0, 0.68, 2228.0, 146.0, 1351.0 + 0.6, 0.0, 0.72, 2600.7, 186.6, 1508.8 + 0.6, 0.0, 0.76, 2972.9, 230.7, 1676.3 + 0.6, 0.0, 0.8, 3341.7, 264.7, 1828.9 + 0.6, 0.0, 0.84, 3551.68, 285.553, 1918.32 + 0.6, 0.0, 0.88, 3669.6, 298.845, 1971.36 + 0.6, 0.0, 0.92, 3796.38, 313.013, 2028.17 + 0.6, 0.0, 0.96, 3964.61, 330.79, 2102.16 + 0.6, 0.0, 1.0, 4138.5, 349.2, 2180.0 + 0.6, 5000.0, 0.52, 820.9, 29.0, 816.3 + 0.6, 5000.0, 0.56, 1233.8, 75.1, 984.0 + 0.6, 5000.0, 0.6, 1648.2, 113.8, 1141.7 + 0.6, 5000.0, 0.64, 2058.1, 159.5, 1310.8 + 0.6, 5000.0, 0.68, 2469.1, 199.8, 1474.8 + 0.6, 5000.0, 0.72, 2882.0, 242.4, 1646.4 + 0.6, 5000.0, 0.76, 3291.0, 287.8, 1821.7 + 0.6, 5000.0, 0.8, 3702.9, 332.2, 1997.1 + 0.6, 5000.0, 0.84, 3936.76, 357.526, 2097.43 + 0.6, 5000.0, 0.88, 4066.72, 371.663, 2154.25 + 0.6, 5000.0, 0.92, 4204.96, 386.318, 2215.02 + 0.6, 5000.0, 0.96, 4387.57, 405.557, 2295.4 + 0.6, 5000.0, 1.0, 4574.5, 425.8, 2379.2 + 0.6, 10000.0, 0.52, 1027.1, 130.1, 959.5 + 0.6, 10000.0, 0.56, 1540.6, 187.7, 1158.2 + 0.6, 10000.0, 0.6, 2054.1, 244.7, 1357.9 + 0.6, 10000.0, 0.64, 2567.7, 301.3, 1558.9 + 0.6, 10000.0, 0.68, 3081.2, 357.9, 1761.7 + 0.6, 10000.0, 0.72, 3594.7, 415.3, 1968.4 + 0.6, 10000.0, 0.76, 4108.2, 475.7, 2184.9 + 0.6, 10000.0, 0.8, 4621.9, 536.2, 2403.7 + 0.6, 10000.0, 0.84, 4914.14, 570.55, 2528.58 + 0.6, 10000.0, 0.88, 5075.49, 589.473, 2598.21 + 0.6, 10000.0, 0.92, 5243.85, 609.039, 2670.64 + 0.6, 10000.0, 0.96, 5462.5, 634.622, 2765.18 + 0.6, 10000.0, 1.0, 5680.1, 660.9, 2862.4 + 0.6, 15000.0, 0.52, 1138.3, 182.4, 1050.0 + 0.6, 15000.0, 0.56, 1707.5, 246.1, 1266.4 + 0.6, 15000.0, 0.6, 2276.6, 309.5, 1484.2 + 0.6, 15000.0, 0.64, 2845.8, 372.3, 1703.2 + 0.6, 15000.0, 0.68, 3414.9, 435.2, 1924.5 + 0.6, 15000.0, 0.72, 3984.1, 499.2, 2150.7 + 0.6, 15000.0, 0.76, 4553.2, 566.8, 2387.4 + 0.6, 15000.0, 0.8, 5122.4, 634.4, 2627.2 + 0.6, 15000.0, 0.84, 5448.11, 672.997, 2764.57 + 0.6, 15000.0, 0.88, 5627.0, 694.289, 2841.04 + 0.6, 15000.0, 0.92, 5803.74, 715.618, 2918.32 + 0.6, 15000.0, 0.96, 6027.01, 743.037, 3017.71 + 0.6, 15000.0, 1.0, 6249.5, 771.3, 3120.1 + 0.6, 20000.0, 0.52, 1252.5, 242.2, 1145.5 + 0.6, 20000.0, 0.56, 1878.9, 311.9, 1378.6 + 0.6, 20000.0, 0.6, 2505.3, 381.4, 1613.6 + 0.6, 20000.0, 0.64, 3131.5, 450.6, 1850.4 + 0.6, 20000.0, 0.68, 3757.8, 519.9, 2089.6 + 0.6, 20000.0, 0.72, 4384.2, 590.4, 2334.4 + 0.6, 20000.0, 0.76, 5010.4, 665.1, 2591.1 + 0.6, 20000.0, 0.8, 5636.7, 740.1, 2851.1 + 0.6, 20000.0, 0.84, 5996.59, 783.454, 3002.02 + 0.6, 20000.0, 0.88, 6193.38, 807.757, 3087.35 + 0.6, 20000.0, 0.92, 6379.58, 831.535, 3171.15 + 0.6, 20000.0, 0.96, 6609.29, 861.45, 3276.31 + 0.6, 20000.0, 1.0, 6838.2, 892.3, 3384.5 + 0.6, 25000.0, 0.52, 1384.0, 304.7, 1246.6 + 0.6, 25000.0, 0.56, 2075.7, 382.3, 1500.7 + 0.6, 25000.0, 0.6, 2767.7, 459.8, 1757.1 + 0.6, 25000.0, 0.64, 3459.7, 537.1, 2015.9 + 0.6, 25000.0, 0.68, 4151.7, 614.5, 2277.5 + 0.6, 25000.0, 0.72, 4843.4, 692.8, 2543.5 + 0.6, 25000.0, 0.76, 5535.4, 776.9, 2825.5 + 0.6, 25000.0, 0.8, 6227.4, 861.2, 3111.1 + 0.6, 25000.0, 0.84, 6625.39, 911.513, 3281.26 + 0.6, 25000.0, 0.88, 6842.88, 941.025, 3380.99 + 0.6, 25000.0, 0.92, 7047.22, 968.93, 3476.02 + 0.6, 25000.0, 0.96, 7298.05, 1002.4, 3590.6 + 0.6, 25000.0, 1.0, 7547.3, 1036.6, 3707.5 + 0.6, 30000.0, 0.52, 1509.4, 348.5, 1301.2 + 0.6, 30000.0, 0.56, 2264.2, 437.5, 1581.9 + 0.6, 30000.0, 0.6, 3019.0, 526.3, 1866.1 + 0.6, 30000.0, 0.64, 3773.9, 614.6, 2151.7 + 0.6, 30000.0, 0.68, 4528.4, 703.4, 2441.8 + 0.6, 30000.0, 0.72, 5283.2, 792.4, 2735.7 + 0.6, 30000.0, 0.76, 6038.1, 888.2, 3047.3 + 0.6, 30000.0, 0.8, 6792.6, 985.3, 3366.6 + 0.6, 30000.0, 0.84, 7227.0, 1042.89, 3556.46 + 0.6, 30000.0, 0.88, 7464.27, 1076.1, 3666.73 + 0.6, 30000.0, 0.92, 7685.42, 1106.9, 3770.0 + 0.6, 30000.0, 0.96, 7955.37, 1143.6, 3893.39 + 0.6, 30000.0, 1.0, 8222.9, 1180.9, 4018.6 + 0.6, 35000.0, 0.52, 1663.8, 407.4, 1385.4 + 0.6, 35000.0, 0.56, 2495.5, 510.1, 1698.9 + 0.6, 35000.0, 0.6, 3327.6, 611.9, 2014.6 + 0.6, 35000.0, 0.64, 4159.3, 713.9, 2334.3 + 0.6, 35000.0, 0.68, 4991.4, 815.6, 2657.0 + 0.6, 35000.0, 0.72, 5823.1, 917.1, 2983.4 + 0.6, 35000.0, 0.76, 6655.2, 1025.9, 3329.4 + 0.6, 35000.0, 0.8, 7486.9, 1139.1, 3692.4 + 0.6, 35000.0, 0.84, 7966.03, 1204.93, 3904.81 + 0.6, 35000.0, 0.88, 8227.42, 1241.51, 4024.47 + 0.6, 35000.0, 0.92, 8469.23, 1275.17, 4135.6 + 0.6, 35000.0, 0.96, 8762.98, 1315.86, 4269.69 + 0.6, 35000.0, 1.0, 9053.5, 1357.1, 4405.5 + 0.65, 0.0, 0.52, 739.9, -41.4, 717.8 + 0.65, 0.0, 0.56, 1102.7, -1.7, 863.5 + 0.65, 0.0, 0.6, 1467.2, 32.7, 1007.3 + 0.65, 0.0, 0.64, 1838.1, 81.4, 1179.6 + 0.65, 0.0, 0.68, 2207.1, 103.9, 1299.6 + 0.65, 0.0, 0.72, 2578.0, 149.2, 1461.3 + 0.65, 0.0, 0.76, 2948.0, 200.2, 1636.7 + 0.65, 0.0, 0.8, 3309.8, 227.9, 1775.3 + 0.65, 0.0, 0.84, 3517.73, 247.43, 1861.2 + 0.65, 0.0, 0.88, 3636.1, 262.353, 1916.69 + 0.65, 0.0, 0.92, 3761.68, 278.201, 1975.0 + 0.65, 0.0, 0.96, 3926.3, 296.566, 2047.5 + 0.65, 0.0, 1.0, 4096.9, 315.1, 2123.7 + 0.65, 5000.0, 0.52, 809.9, -15.3, 774.9 + 0.65, 5000.0, 0.56, 1220.4, 36.6, 948.4 + 0.65, 5000.0, 0.6, 1633.8, 70.3, 1093.4 + 0.65, 5000.0, 0.64, 2037.8, 121.8, 1268.0 + 0.65, 5000.0, 0.68, 2443.7, 160.9, 1427.6 + 0.65, 5000.0, 0.72, 2854.2, 203.8, 1599.8 + 0.65, 5000.0, 0.76, 3255.6, 251.1, 1772.5 + 0.65, 5000.0, 0.8, 3664.1, 296.4, 1943.2 + 0.65, 5000.0, 0.84, 3896.62, 322.422, 2041.7 + 0.65, 5000.0, 0.88, 4025.87, 337.025, 2098.32 + 0.65, 5000.0, 0.92, 4161.43, 351.766, 2158.73 + 0.65, 5000.0, 0.96, 4339.18, 370.803, 2237.88 + 0.65, 5000.0, 1.0, 4521.3, 390.9, 2320.0 + 0.65, 10000.0, 0.52, 1008.8, 83.4, 916.6 + 0.65, 10000.0, 0.56, 1513.2, 141.4, 1111.8 + 0.65, 10000.0, 0.6, 2017.6, 198.9, 1307.9 + 0.65, 10000.0, 0.64, 2522.0, 255.9, 1505.0 + 0.65, 10000.0, 0.68, 3026.4, 312.8, 1703.9 + 0.65, 10000.0, 0.72, 3530.7, 370.6, 1907.0 + 0.65, 10000.0, 0.76, 4035.1, 431.5, 2119.6 + 0.65, 10000.0, 0.8, 4539.5, 492.5, 2334.6 + 0.65, 10000.0, 0.84, 4826.61, 527.156, 2457.45 + 0.65, 10000.0, 0.88, 4985.13, 546.236, 2525.98 + 0.65, 10000.0, 0.92, 5149.89, 565.844, 2596.89 + 0.65, 10000.0, 0.96, 5363.49, 591.412, 2689.17 + 0.65, 10000.0, 1.0, 5576.3, 617.7, 2784.1 + 0.65, 15000.0, 0.52, 1118.2, 133.8, 1002.5 + 0.65, 15000.0, 0.56, 1677.3, 198.5, 1215.6 + 0.65, 15000.0, 0.6, 2236.3, 262.6, 1429.9 + 0.65, 15000.0, 0.64, 2795.4, 326.4, 1645.7 + 0.65, 15000.0, 0.68, 3354.5, 390.1, 1863.5 + 0.65, 15000.0, 0.72, 3913.6, 454.8, 2085.9 + 0.65, 15000.0, 0.76, 4472.7, 523.2, 2319.5 + 0.65, 15000.0, 0.8, 5031.8, 591.8, 2555.7 + 0.65, 15000.0, 0.84, 5351.47, 630.907, 2691.05 + 0.65, 15000.0, 0.88, 5527.19, 652.422, 2766.43 + 0.65, 15000.0, 0.92, 5702.4, 674.013, 2842.67 + 0.65, 15000.0, 0.96, 5924.62, 701.81, 2940.68 + 0.65, 15000.0, 1.0, 6145.4, 730.4, 3041.4 + 0.65, 20000.0, 0.52, 1231.2, 192.4, 1095.4 + 0.65, 20000.0, 0.56, 1846.7, 263.3, 1325.6 + 0.65, 20000.0, 0.6, 2462.3, 333.9, 1557.4 + 0.65, 20000.0, 0.64, 3077.9, 404.1, 1791.1 + 0.65, 20000.0, 0.68, 3693.6, 474.5, 2027.3 + 0.65, 20000.0, 0.72, 4309.2, 545.9, 2268.4 + 0.65, 20000.0, 0.76, 4924.8, 621.8, 2522.0 + 0.65, 20000.0, 0.8, 5540.4, 697.8, 2778.7 + 0.65, 20000.0, 0.84, 5894.3, 741.505, 2926.95 + 0.65, 20000.0, 0.88, 6087.73, 765.757, 3009.96 + 0.65, 20000.0, 0.92, 6270.05, 789.448, 3091.43 + 0.65, 20000.0, 0.96, 6494.36, 819.368, 3194.1 + 0.65, 20000.0, 1.0, 6717.5, 850.2, 3299.7 + 0.65, 25000.0, 0.52, 1361.4, 263.1, 1212.0 + 0.65, 25000.0, 0.56, 2042.2, 340.8, 1460.4 + 0.65, 25000.0, 0.6, 2722.8, 418.4, 1711.4 + 0.65, 25000.0, 0.64, 3403.6, 496.0, 1964.9 + 0.65, 25000.0, 0.68, 4084.2, 573.4, 2220.8 + 0.65, 25000.0, 0.72, 4765.0, 652.6, 2482.8 + 0.65, 25000.0, 0.76, 5445.6, 736.9, 2759.1 + 0.65, 25000.0, 0.8, 6126.4, 821.3, 3038.2 + 0.65, 25000.0, 0.84, 6518.06, 871.524, 3204.24 + 0.65, 25000.0, 0.88, 6731.93, 900.884, 3301.37 + 0.65, 25000.0, 0.92, 6932.15, 928.788, 3394.17 + 0.65, 25000.0, 0.96, 7177.29, 962.452, 3506.37 + 0.65, 25000.0, 1.0, 7420.4, 996.9, 3620.9 + 0.65, 30000.0, 0.52, 1483.2, 304.7, 1262.4 + 0.65, 30000.0, 0.56, 2224.6, 394.1, 1538.0 + 0.65, 30000.0, 0.6, 2966.2, 483.2, 1815.9 + 0.65, 30000.0, 0.64, 3707.8, 572.2, 2096.4 + 0.65, 30000.0, 0.68, 4449.5, 661.5, 2381.1 + 0.65, 30000.0, 0.72, 5190.8, 750.8, 2668.7 + 0.65, 30000.0, 0.76, 5932.4, 847.3, 2974.7 + 0.65, 30000.0, 0.8, 6674.0, 943.8, 3285.2 + 0.65, 30000.0, 0.84, 7101.12, 1001.62, 3471.25 + 0.65, 30000.0, 0.88, 7334.24, 1035.51, 3580.58 + 0.65, 30000.0, 0.92, 7550.57, 1066.86, 3682.57 + 0.65, 30000.0, 0.96, 7813.85, 1103.81, 3803.33 + 0.65, 30000.0, 1.0, 8074.4, 1141.3, 3925.7 + 0.65, 35000.0, 0.52, 1632.9, 361.5, 1343.1 + 0.65, 35000.0, 0.56, 2449.5, 464.5, 1650.2 + 0.65, 35000.0, 0.6, 3265.7, 567.2, 1960.4 + 0.65, 35000.0, 0.64, 4082.3, 669.6, 2273.4 + 0.65, 35000.0, 0.68, 4898.6, 771.7, 2589.9 + 0.65, 35000.0, 0.72, 5715.2, 873.8, 2909.7 + 0.65, 35000.0, 0.76, 6531.5, 983.3, 3249.1 + 0.65, 35000.0, 0.8, 7348.1, 1096.8, 3603.8 + 0.65, 35000.0, 0.84, 7818.61, 1163.14, 3812.25 + 0.65, 35000.0, 0.88, 8075.07, 1200.32, 3930.5 + 0.65, 35000.0, 0.92, 8311.45, 1234.43, 4040.01 + 0.65, 35000.0, 0.96, 8597.88, 1275.36, 4171.39 + 0.65, 35000.0, 1.0, 8880.7, 1316.8, 4304.3 + 0.7, 0.0, 0.52, 738.2, -80.6, 673.9 + 0.7, 0.0, 0.56, 1093.6, -38.1, 819.4 + 0.7, 0.0, 0.6, 1452.6, -4.9, 961.9 + 0.7, 0.0, 0.64, 1823.4, 54.0, 1153.4 + 0.7, 0.0, 0.68, 2190.8, 63.0, 1244.3 + 0.7, 0.0, 0.72, 2561.6, 115.9, 1414.4 + 0.7, 0.0, 0.76, 2931.0, 177.5, 1603.2 + 0.7, 0.0, 0.8, 3284.4, 194.9, 1720.5 + 0.7, 0.0, 0.84, 3490.53, 212.193, 1801.55 + 0.7, 0.0, 0.88, 3610.51, 229.685, 1861.64 + 0.7, 0.0, 0.92, 3735.71, 248.245, 1923.19 + 0.7, 0.0, 0.96, 3897.0, 267.614, 1994.38 + 0.7, 0.0, 1.0, 4064.8, 286.4, 2069.1 + 0.7, 5000.0, 0.52, 799.3, -57.3, 732.8 + 0.7, 5000.0, 0.56, 1209.4, 3.3, 916.3 + 0.7, 5000.0, 0.6, 1624.4, 28.5, 1041.5 + 0.7, 5000.0, 0.64, 2022.6, 89.2, 1227.0 + 0.7, 5000.0, 0.68, 2423.7, 126.2, 1380.8 + 0.7, 5000.0, 0.72, 2833.8, 169.4, 1555.8 + 0.7, 5000.0, 0.76, 3226.5, 219.5, 1726.0 + 0.7, 5000.0, 0.8, 3633.1, 266.1, 1890.8 + 0.7, 5000.0, 0.84, 3865.27, 293.1, 1987.2 + 0.7, 5000.0, 0.88, 3994.39, 308.34, 2043.93 + 0.7, 5000.0, 0.92, 4127.36, 323.202, 2104.46 + 0.7, 5000.0, 0.96, 4300.02, 341.985, 2182.8 + 0.7, 5000.0, 1.0, 4477.1, 361.9, 2263.5 + 0.7, 10000.0, 0.52, 989.0, 39.1, 872.8 + 0.7, 10000.0, 0.56, 1483.4, 97.5, 1063.9 + 0.7, 10000.0, 0.6, 1977.9, 155.4, 1256.1 + 0.7, 10000.0, 0.64, 2472.4, 212.7, 1449.2 + 0.7, 10000.0, 0.68, 2966.9, 270.0, 1644.0 + 0.7, 10000.0, 0.72, 3461.5, 328.0, 1842.8 + 0.7, 10000.0, 0.76, 3955.9, 389.3, 2051.3 + 0.7, 10000.0, 0.8, 4450.3, 450.6, 2262.1 + 0.7, 10000.0, 0.84, 4731.92, 485.61, 2382.86 + 0.7, 10000.0, 0.88, 4887.39, 505.013, 2450.39 + 0.7, 10000.0, 0.92, 5048.11, 524.73, 2519.71 + 0.7, 10000.0, 0.96, 5255.97, 550.203, 2609.41 + 0.7, 10000.0, 1.0, 5463.4, 576.4, 2701.7 + 0.7, 15000.0, 0.52, 1096.8, 87.6, 953.7 + 0.7, 15000.0, 0.56, 1645.3, 153.2, 1163.3 + 0.7, 15000.0, 0.6, 2193.7, 218.3, 1374.1 + 0.7, 15000.0, 0.64, 2742.1, 282.9, 1586.3 + 0.7, 15000.0, 0.68, 3290.4, 347.5, 1800.5 + 0.7, 15000.0, 0.72, 3838.8, 412.9, 2019.1 + 0.7, 15000.0, 0.76, 4387.3, 482.3, 2248.8 + 0.7, 15000.0, 0.8, 4935.7, 551.7, 2481.4 + 0.7, 15000.0, 0.84, 5249.0, 591.33, 2614.74 + 0.7, 15000.0, 0.88, 5421.35, 613.187, 2689.03 + 0.7, 15000.0, 0.92, 5594.77, 635.111, 2764.23 + 0.7, 15000.0, 0.96, 5815.55, 663.258, 2860.82 + 0.7, 15000.0, 1.0, 6034.3, 692.1, 2959.8 + 0.7, 20000.0, 0.52, 1206.3, 144.7, 1043.5 + 0.7, 20000.0, 0.56, 1809.6, 216.8, 1269.8 + 0.7, 20000.0, 0.6, 2412.7, 288.4, 1498.0 + 0.7, 20000.0, 0.64, 3015.9, 359.7, 1727.9 + 0.7, 20000.0, 0.68, 3619.0, 431.1, 1960.3 + 0.7, 20000.0, 0.72, 4222.3, 503.1, 2196.9 + 0.7, 20000.0, 0.76, 4825.3, 580.3, 2447.1 + 0.7, 20000.0, 0.8, 5428.6, 657.6, 2700.8 + 0.7, 20000.0, 0.84, 5775.15, 701.787, 2846.49 + 0.7, 20000.0, 0.88, 5964.67, 726.035, 2927.27 + 0.7, 20000.0, 0.92, 6144.85, 749.756, 3006.83 + 0.7, 20000.0, 0.96, 6367.44, 779.888, 3107.7 + 0.7, 20000.0, 1.0, 6588.2, 810.9, 3211.3 + 0.7, 25000.0, 0.52, 1334.1, 213.7, 1155.9 + 0.7, 25000.0, 0.56, 2001.2, 292.8, 1401.1 + 0.7, 25000.0, 0.6, 2668.2, 371.9, 1648.8 + 0.7, 25000.0, 0.64, 3335.3, 450.4, 1898.3 + 0.7, 25000.0, 0.68, 4002.5, 529.8, 2151.8 + 0.7, 25000.0, 0.72, 4669.4, 610.0, 2410.1 + 0.7, 25000.0, 0.76, 5336.6, 695.6, 2682.3 + 0.7, 25000.0, 0.8, 6003.5, 781.2, 2957.9 + 0.7, 25000.0, 0.84, 6387.54, 831.604, 3120.26 + 0.7, 25000.0, 0.88, 6597.28, 860.564, 3213.74 + 0.7, 25000.0, 0.92, 6792.51, 888.161, 3303.27 + 0.7, 25000.0, 0.96, 7030.52, 921.818, 3412.61 + 0.7, 25000.0, 1.0, 7266.1, 956.3, 3524.3 + 0.7, 30000.0, 0.52, 1455.0, 265.0, 1224.5 + 0.7, 30000.0, 0.56, 2182.3, 354.7, 1493.6 + 0.7, 30000.0, 0.6, 2909.7, 444.1, 1765.6 + 0.7, 30000.0, 0.64, 3637.3, 533.5, 2040.4 + 0.7, 30000.0, 0.68, 4364.6, 623.1, 2318.3 + 0.7, 30000.0, 0.72, 5092.2, 712.7, 2600.1 + 0.7, 30000.0, 0.76, 5819.6, 809.3, 2899.0 + 0.7, 30000.0, 0.8, 6547.0, 906.1, 3202.4 + 0.7, 30000.0, 0.84, 6966.17, 964.209, 3384.35 + 0.7, 30000.0, 0.88, 7194.87, 998.381, 3491.41 + 0.7, 30000.0, 0.92, 7406.17, 1029.96, 3591.2 + 0.7, 30000.0, 0.96, 7662.53, 1067.11, 3709.22 + 0.7, 30000.0, 1.0, 7915.8, 1104.8, 3828.8 + 0.7, 35000.0, 0.52, 1600.0, 319.4, 1300.8 + 0.7, 35000.0, 0.56, 2399.7, 423.0, 1601.4 + 0.7, 35000.0, 0.6, 3199.8, 526.2, 1904.3 + 0.7, 35000.0, 0.64, 3999.8, 628.8, 2210.3 + 0.7, 35000.0, 0.68, 4799.8, 731.4, 2520.0 + 0.7, 35000.0, 0.72, 5599.8, 834.2, 2834.0 + 0.7, 35000.0, 0.76, 6399.8, 944.0, 3165.5 + 0.7, 35000.0, 0.8, 7199.5, 1057.6, 3511.1 + 0.7, 35000.0, 0.84, 7660.69, 1124.44, 3715.49 + 0.7, 35000.0, 0.88, 7912.16, 1162.29, 3832.56 + 0.7, 35000.0, 0.92, 8142.9, 1196.87, 3940.59 + 0.7, 35000.0, 0.96, 8421.49, 1238.0, 4069.1 + 0.7, 35000.0, 1.0, 8696.1, 1279.6, 4198.9 + 0.75, 0.0, 0.52, 740.3, -116.8, 628.3 + 0.75, 0.0, 0.56, 1087.2, -70.4, 774.5 + 0.75, 0.0, 0.6, 1440.6, -39.0, 916.4 + 0.75, 0.0, 0.64, 1813.5, 34.2, 1135.8 + 0.75, 0.0, 0.68, 2180.9, 23.2, 1184.9 + 0.75, 0.0, 0.72, 2553.8, 87.3, 1369.1 + 0.75, 0.0, 0.76, 2924.7, 164.0, 1578.0 + 0.75, 0.0, 0.8, 3268.1, 166.2, 1665.1 + 0.75, 0.0, 0.84, 3472.8, 180.142, 1739.74 + 0.75, 0.0, 0.88, 3595.85, 201.359, 1807.11 + 0.75, 0.0, 0.92, 3721.75, 223.907, 1874.11 + 0.75, 0.0, 0.96, 3880.13, 244.798, 1944.25 + 0.75, 0.0, 1.0, 4045.8, 264.0, 2017.7 + 0.75, 5000.0, 0.52, 789.5, -96.8, 690.5 + 0.75, 5000.0, 0.56, 1201.8, -24.0, 889.1 + 0.75, 5000.0, 0.6, 1621.7, -11.6, 985.8 + 0.75, 5000.0, 0.64, 2014.4, 62.5, 1189.0 + 0.75, 5000.0, 0.68, 2411.2, 96.3, 1335.3 + 0.75, 5000.0, 0.72, 2823.5, 139.8, 1515.9 + 0.75, 5000.0, 0.76, 3206.3, 193.8, 1683.8 + 0.75, 5000.0, 0.8, 3613.0, 242.2, 1841.3 + 0.75, 5000.0, 0.84, 3846.13, 270.52, 1935.27 + 0.75, 5000.0, 0.88, 3975.83, 286.6, 1992.5 + 0.75, 5000.0, 0.92, 4106.38, 301.63, 2053.78 + 0.75, 5000.0, 0.96, 4273.76, 320.101, 2131.89 + 0.75, 5000.0, 1.0, 4445.6, 339.8, 2211.5 + 0.75, 10000.0, 0.52, 969.0, -2.9, 827.0 + 0.75, 10000.0, 0.56, 1452.8, 56.4, 1013.6 + 0.75, 10000.0, 0.6, 1937.0, 114.8, 1202.2 + 0.75, 10000.0, 0.64, 2421.8, 172.6, 1392.4 + 0.75, 10000.0, 0.68, 2906.0, 231.1, 1584.2 + 0.75, 10000.0, 0.72, 3391.2, 289.0, 1777.5 + 0.75, 10000.0, 0.76, 3875.2, 350.7, 1982.5 + 0.75, 10000.0, 0.8, 4359.8, 412.1, 2189.3 + 0.75, 10000.0, 0.84, 4635.78, 447.685, 2308.3 + 0.75, 10000.0, 0.88, 4788.18, 467.85, 2375.22 + 0.75, 10000.0, 0.92, 4946.09, 488.051, 2443.34 + 0.75, 10000.0, 0.96, 5150.47, 513.626, 2530.79 + 0.75, 10000.0, 1.0, 5354.1, 539.8, 2620.5 + 0.75, 15000.0, 0.52, 1073.9, 43.9, 903.8 + 0.75, 15000.0, 0.56, 1611.6, 110.1, 1109.7 + 0.75, 15000.0, 0.6, 2148.9, 177.0, 1317.6 + 0.75, 15000.0, 0.64, 2686.0, 241.7, 1525.3 + 0.75, 15000.0, 0.68, 3222.4, 307.4, 1736.2 + 0.75, 15000.0, 0.72, 3759.5, 373.4, 1951.1 + 0.75, 15000.0, 0.76, 4296.8, 444.4, 2175.3 + 0.75, 15000.0, 0.8, 4833.9, 513.9, 2404.9 + 0.75, 15000.0, 0.84, 5140.5, 554.067, 2536.49 + 0.75, 15000.0, 0.88, 5309.35, 576.642, 2609.75 + 0.75, 15000.0, 0.92, 5480.84, 599.082, 2683.94 + 0.75, 15000.0, 0.96, 5700.07, 627.407, 2779.15 + 0.75, 15000.0, 1.0, 5916.8, 656.2, 2876.3 + 0.75, 20000.0, 0.52, 1179.5, 99.6, 990.5 + 0.75, 20000.0, 0.56, 1769.3, 172.7, 1212.7 + 0.75, 20000.0, 0.6, 2359.0, 245.4, 1436.7 + 0.75, 20000.0, 0.64, 2948.8, 317.9, 1662.8 + 0.75, 20000.0, 0.68, 3538.5, 390.0, 1890.7 + 0.75, 20000.0, 0.72, 4128.3, 463.1, 2123.4 + 0.75, 20000.0, 0.76, 4718.0, 541.4, 2369.5 + 0.75, 20000.0, 0.8, 5307.8, 619.6, 2618.5 + 0.75, 20000.0, 0.84, 5646.23, 664.273, 2761.48 + 0.75, 20000.0, 0.88, 5831.55, 688.758, 2840.79 + 0.75, 20000.0, 0.92, 6010.11, 712.745, 2919.08 + 0.75, 20000.0, 0.96, 6232.08, 743.226, 3018.38 + 0.75, 20000.0, 1.0, 6451.4, 774.5, 3120.1 + 0.75, 25000.0, 0.52, 1305.1, 166.9, 1099.1 + 0.75, 25000.0, 0.56, 1957.7, 247.7, 1341.1 + 0.75, 25000.0, 0.6, 2610.1, 328.1, 1584.6 + 0.75, 25000.0, 0.64, 3262.7, 408.4, 1831.3 + 0.75, 25000.0, 0.68, 3915.4, 489.0, 2080.8 + 0.75, 25000.0, 0.72, 4567.8, 570.3, 2334.8 + 0.75, 25000.0, 0.76, 5220.4, 657.2, 2602.7 + 0.75, 25000.0, 0.8, 5873.0, 744.1, 2874.4 + 0.75, 25000.0, 0.84, 6248.87, 794.713, 3033.04 + 0.75, 25000.0, 0.88, 6453.93, 823.258, 3123.01 + 0.75, 25000.0, 0.92, 6644.0, 850.54, 3209.36 + 0.75, 25000.0, 0.96, 6875.11, 884.196, 3315.8 + 0.75, 25000.0, 1.0, 7103.4, 918.7, 3424.6 + 0.75, 30000.0, 0.52, 1424.9, 229.9, 1187.8 + 0.75, 30000.0, 0.56, 2137.2, 319.6, 1450.3 + 0.75, 30000.0, 0.6, 2849.8, 409.3, 1715.4 + 0.75, 30000.0, 0.64, 3562.1, 498.7, 1983.3 + 0.75, 30000.0, 0.68, 4274.7, 588.3, 2254.7 + 0.75, 30000.0, 0.72, 4987.0, 678.3, 2529.7 + 0.75, 30000.0, 0.76, 5699.4, 775.0, 2821.7 + 0.75, 30000.0, 0.8, 6411.9, 872.2, 3117.9 + 0.75, 30000.0, 0.84, 6822.59, 930.403, 3295.17 + 0.75, 30000.0, 0.88, 7046.48, 964.518, 3399.18 + 0.75, 30000.0, 0.92, 7252.41, 996.133, 3496.38 + 0.75, 30000.0, 0.96, 7501.52, 1033.47, 3611.7 + 0.75, 30000.0, 1.0, 7747.2, 1071.4, 3728.6 + 0.75, 35000.0, 0.52, 1565.1, 281.5, 1258.8 + 0.75, 35000.0, 0.56, 2347.5, 385.5, 1552.0 + 0.75, 35000.0, 0.6, 3129.9, 488.7, 1847.8 + 0.75, 35000.0, 0.64, 3912.2, 591.7, 2146.4 + 0.75, 35000.0, 0.68, 4695.0, 694.6, 2448.8 + 0.75, 35000.0, 0.72, 5477.3, 797.9, 2755.4 + 0.75, 35000.0, 0.76, 6259.7, 908.2, 3079.8 + 0.75, 35000.0, 0.8, 7042.4, 1021.5, 3415.7 + 0.75, 35000.0, 0.84, 7493.83, 1088.75, 3615.61 + 0.75, 35000.0, 0.88, 7739.68, 1127.37, 3731.24 + 0.75, 35000.0, 0.92, 7964.28, 1162.56, 3837.5 + 0.75, 35000.0, 0.96, 8234.71, 1203.99, 3962.88 + 0.75, 35000.0, 1.0, 8500.8, 1245.8, 4089.4 + 0.8, 0.0, 0.52, 747.1, -149.7, 581.2 + 0.8, 0.0, 0.56, 1084.3, -98.1, 729.2 + 0.8, 0.0, 0.6, 1432.1, -69.2, 871.4 + 0.8, 0.0, 0.64, 1809.8, 23.1, 1128.9 + 0.8, 0.0, 0.68, 2179.2, -15.6, 1121.2 + 0.8, 0.0, 0.72, 2556.9, 64.0, 1326.4 + 0.8, 0.0, 0.76, 2931.9, 161.1, 1563.3 + 0.8, 0.0, 0.8, 3263.5, 142.3, 1609.7 + 0.8, 0.0, 0.84, 3467.26, 151.576, 1676.13 + 0.8, 0.0, 0.88, 3595.15, 177.896, 1754.02 + 0.8, 0.0, 0.92, 3723.07, 205.95, 1829.1 + 0.8, 0.0, 0.96, 3879.08, 228.985, 1898.54 + 0.8, 0.0, 1.0, 4043.5, 248.8, 1971.0 + 0.8, 5000.0, 0.52, 780.9, -133.6, 648.5 + 0.8, 5000.0, 0.56, 1198.6, -44.5, 868.2 + 0.8, 5000.0, 0.6, 1627.4, -50.0, 926.1 + 0.8, 5000.0, 0.64, 2015.1, 42.5, 1155.2 + 0.8, 5000.0, 0.68, 2408.3, 71.8, 1292.0 + 0.8, 5000.0, 0.72, 2826.0, 115.6, 1481.6 + 0.8, 5000.0, 0.76, 3197.6, 174.8, 1647.5 + 0.8, 5000.0, 0.8, 3606.9, 225.6, 1796.1 + 0.8, 5000.0, 0.84, 3842.6, 255.643, 1887.29 + 0.8, 5000.0, 0.88, 3973.75, 272.798, 1945.47 + 0.8, 5000.0, 0.92, 4102.12, 288.051, 2008.27 + 0.8, 5000.0, 0.96, 4264.05, 306.15, 2086.82 + 0.8, 5000.0, 1.0, 4430.5, 325.6, 2165.8 + 0.8, 10000.0, 0.52, 950.1, -42.7, 778.1 + 0.8, 10000.0, 0.56, 1423.0, 18.5, 960.0 + 0.8, 10000.0, 0.6, 1896.9, 77.7, 1145.9 + 0.8, 10000.0, 0.64, 2373.1, 136.5, 1335.5 + 0.8, 10000.0, 0.68, 2847.0, 197.7, 1526.7 + 0.8, 10000.0, 0.72, 3323.9, 255.1, 1712.8 + 0.8, 10000.0, 0.76, 3797.6, 317.3, 1915.7 + 0.8, 10000.0, 0.8, 4273.5, 378.6, 2119.3 + 0.8, 10000.0, 0.84, 4543.94, 415.15, 2237.25 + 0.8, 10000.0, 0.88, 4693.41, 436.793, 2304.21 + 0.8, 10000.0, 0.92, 4851.42, 458.164, 2372.04 + 0.8, 10000.0, 0.96, 5057.47, 484.312, 2458.22 + 0.8, 10000.0, 1.0, 5261.1, 510.7, 2545.8 + 0.8, 15000.0, 0.52, 1049.3, 2.8, 853.0 + 0.8, 15000.0, 0.56, 1576.3, 69.1, 1055.0 + 0.8, 15000.0, 0.6, 2102.0, 139.1, 1261.2 + 0.8, 15000.0, 0.64, 2627.2, 202.7, 1463.0 + 0.8, 15000.0, 0.68, 3150.3, 269.8, 1671.3 + 0.8, 15000.0, 0.72, 3675.5, 336.2, 1882.7 + 0.8, 15000.0, 0.76, 4201.0, 409.8, 2099.0 + 0.8, 15000.0, 0.8, 4726.2, 478.2, 2326.8 + 0.8, 15000.0, 0.84, 5025.78, 518.924, 2457.18 + 0.8, 15000.0, 0.88, 5191.03, 542.844, 2529.5 + 0.8, 15000.0, 0.92, 5360.63, 566.092, 2602.75 + 0.8, 15000.0, 0.96, 5578.45, 594.28, 2696.7 + 0.8, 15000.0, 1.0, 5793.5, 622.5, 2791.9 + 0.8, 20000.0, 0.52, 1151.1, 56.9, 936.9 + 0.8, 20000.0, 0.56, 1726.7, 131.2, 1154.9 + 0.8, 20000.0, 0.6, 2302.4, 205.1, 1374.8 + 0.8, 20000.0, 0.64, 2878.0, 278.5, 1596.3 + 0.8, 20000.0, 0.68, 3453.5, 351.9, 1820.2 + 0.8, 20000.0, 0.72, 4029.1, 426.0, 2048.4 + 0.8, 20000.0, 0.76, 4604.7, 505.2, 2289.7 + 0.8, 20000.0, 0.8, 5180.2, 584.2, 2533.6 + 0.8, 20000.0, 0.84, 5510.15, 629.419, 2673.93 + 0.8, 20000.0, 0.88, 5691.07, 654.294, 2752.05 + 0.8, 20000.0, 0.92, 5867.39, 678.675, 2829.22 + 0.8, 20000.0, 0.96, 6087.68, 709.582, 2926.87 + 0.8, 20000.0, 1.0, 6304.7, 741.2, 3026.6 + 0.8, 25000.0, 0.52, 1274.6, 123.2, 1042.9 + 0.8, 25000.0, 0.56, 1911.9, 205.4, 1280.5 + 0.8, 25000.0, 0.6, 2549.2, 287.5, 1520.4 + 0.8, 25000.0, 0.64, 3186.5, 369.4, 1763.1 + 0.8, 25000.0, 0.68, 3823.8, 451.1, 2008.2 + 0.8, 25000.0, 0.72, 4461.1, 533.5, 2257.5 + 0.8, 25000.0, 0.76, 5098.4, 621.6, 2521.3 + 0.8, 25000.0, 0.8, 5735.7, 709.8, 2788.6 + 0.8, 25000.0, 0.84, 6102.98, 760.686, 2943.39 + 0.8, 25000.0, 0.88, 6303.27, 788.909, 3029.91 + 0.8, 25000.0, 0.92, 6488.02, 815.935, 3113.13 + 0.8, 25000.0, 0.96, 6711.88, 849.598, 3216.59 + 0.8, 25000.0, 1.0, 6932.7, 884.1, 3322.4 + 0.8, 30000.0, 0.52, 1393.1, 199.9, 1153.4 + 0.8, 30000.0, 0.56, 2089.7, 289.5, 1408.8 + 0.8, 30000.0, 0.6, 2786.3, 378.8, 1666.4 + 0.8, 30000.0, 0.64, 3482.9, 467.9, 1926.6 + 0.8, 30000.0, 0.68, 4179.4, 557.5, 2190.6 + 0.8, 30000.0, 0.72, 4876.0, 647.6, 2458.5 + 0.8, 30000.0, 0.76, 5572.6, 744.4, 2743.0 + 0.8, 30000.0, 0.8, 6269.1, 841.5, 3031.4 + 0.8, 30000.0, 0.84, 6670.85, 899.582, 3203.67 + 0.8, 30000.0, 0.88, 6889.79, 933.619, 3304.5 + 0.8, 30000.0, 0.92, 7090.16, 965.336, 3398.95 + 0.8, 30000.0, 0.96, 7331.62, 1002.96, 3511.36 + 0.8, 30000.0, 1.0, 7569.3, 1041.2, 3625.4 + 0.8, 35000.0, 0.52, 1528.2, 248.2, 1218.2 + 0.8, 35000.0, 0.56, 2292.2, 351.9, 1503.1 + 0.8, 35000.0, 0.6, 3056.3, 455.2, 1790.8 + 0.8, 35000.0, 0.64, 3820.1, 558.4, 2081.8 + 0.8, 35000.0, 0.68, 4584.2, 661.6, 2376.7 + 0.8, 35000.0, 0.72, 5348.3, 765.2, 2675.8 + 0.8, 35000.0, 0.76, 6112.4, 875.9, 2992.1 + 0.8, 35000.0, 0.8, 6876.4, 988.5, 3317.2 + 0.8, 35000.0, 0.84, 7317.39, 1056.12, 3512.34 + 0.8, 35000.0, 0.88, 7557.55, 1095.67, 3626.72 + 0.8, 35000.0, 0.92, 7775.86, 1131.5, 3731.51 + 0.8, 35000.0, 0.96, 8037.68, 1173.09, 3853.91 + 0.8, 35000.0, 1.0, 8294.8, 1215.0, 3977.2 diff --git a/aviary/models/engines/turboshaft_4465hp.deck b/aviary/models/engines/turboshaft_4465hp.deck deleted file mode 100644 index 91a42a30ab..0000000000 --- a/aviary/models/engines/turboshaft_4465hp.deck +++ /dev/null @@ -1,1783 +0,0 @@ -# GASP-derived turboshaft engine deck converted from turboshaft_4465hp.eng -# t4max: 50.0 -# t4cruise: 45.0 -# t4climb: 50.0 -# t4flight_idle: 26.0 -# xsfc: 0.0 -# cexp: 0.0 -# sls_horsepower: 4465.2 -# freeturbine_rpm: 13820.0 -# propeller_rpm: 1020.7 -# gearbox_ratio: 0.073855 -# torque_limit: 22976.2 -# sls_corrected_airflow: 30.5 - - Mach_Number, Altitude (ft), Throttle, Shaft_Power (hp), Tailpipe_Thrust (lbf), Fuel_Flow (lb/h) - 0.0, 0.0, 0.52, 794.3999999999999, 618.3999999999999, 1035.8999999999999 - 0.0, 0.0, 0.56, 1191.5999999999997, 651.7, 1194.4999999999995 - 0.0, 0.0, 0.6, 1588.8999999999996, 684.8000000000001, 1353.7999999999993 - 0.0, 0.0, 0.64, 1986.100000000001, 717.6999999999996, 1513.600000000001 - 0.0, 0.0, 0.68, 2383.2999999999993, 750.4000000000004, 1674.2 - 0.0, 0.0, 0.72, 2780.500000000001, 785.0000000000003, 1842.099999999999 - 0.0, 0.0, 0.76, 3177.6999999999985, 820.3, 2013.2000000000007 - 0.0, 0.0, 0.8, 3574.9000000000005, 855.4999999999987, 2185.7999999999993 - 0.0, 0.0, 0.84, 3798.0720000000024, 875.2782857142853, 2283.190285714286 - 0.0, 0.0, 0.88, 3922.952000000004, 886.341142857142, 2338.2131428571433 - 0.0, 0.0, 0.92, 4066.411199999998, 898.8888, 2400.8423999999995 - 0.0, 0.0, 0.96, 4263.050399999998, 916.1335999999998, 2486.788799999999 - 0.0, 0.0, 1.0, 4465.199999999999, 934.2999999999996, 2577.499999999998 - 0.0, 5000.0, 0.52, 889.3999999999999, 671.3999999999999, 1101.3999999999999 - 0.0, 5000.0, 0.56, 1334.1, 709.4000000000001, 1276.9000000000005 - 0.0, 5000.0, 0.6, 1778.8000000000004, 747.2000000000003, 1453.0000000000018 - 0.0, 5000.0, 0.64, 2223.3999999999987, 784.8000000000002, 1629.7999999999997 - 0.0, 5000.0, 0.68, 2668.1, 822.2999999999998, 1807.6999999999998 - 0.0, 5000.0, 0.72, 3112.8, 862.1999999999997, 1994.6000000000017 - 0.0, 5000.0, 0.76, 3557.5000000000023, 902.9000000000009, 2185.9000000000015 - 0.0, 5000.0, 0.8, 4002.1999999999944, 943.3999999999988, 2377.8 - 0.0, 5000.0, 0.84, 4252.814285714287, 966.3125714285716, 2486.596 - 0.0, 5000.0, 0.88, 4392.5771428571425, 979.1782857142856, 2548.0960000000005 - 0.0, 5000.0, 0.92, 4549.907999999997, 993.4679999999992, 2616.6967999999974 - 0.0, 5000.0, 0.96, 4762.855999999996, 1012.7919999999986, 2709.617599999996 - 0.0, 5000.0, 1.0, 4979.099999999995, 1032.8999999999978, 2806.899999999994 - 0.0, 10000.0, 0.52, 1121.9999999999998, 814.8999999999999, 1262.2999999999997 - 0.0, 10000.0, 0.56, 1682.9000000000005, 866.3999999999999, 1477.6999999999996 - 0.0, 10000.0, 0.6, 2244.000000000002, 917.4, 1693.5999999999992 - 0.0, 10000.0, 0.64, 2804.8999999999987, 968.4000000000002, 1911.200000000001 - 0.0, 10000.0, 0.68, 3365.899999999997, 1019.2000000000002, 2129.8 - 0.0, 10000.0, 0.72, 3926.900000000005, 1071.8000000000018, 2355.8000000000006 - 0.0, 10000.0, 0.76, 4487.900000000003, 1126.2999999999984, 2588.8999999999996 - 0.0, 10000.0, 0.8, 5048.899999999998, 1181.0, 2824.3999999999965 - 0.0, 10000.0, 0.84, 5369.339428571428, 1212.1582857142855, 2959.351999999999 - 0.0, 10000.0, 0.88, 5545.653714285712, 1229.4411428571425, 3035.331999999998 - 0.0, 10000.0, 0.92, 5721.667199999998, 1247.2167999999995, 3114.342399999999 - 0.0, 10000.0, 0.96, 5946.4263999999985, 1270.449599999999, 3217.5327999999995 - 0.0, 10000.0, 1.0, 6174.199999999997, 1294.6999999999987, 3325.1999999999994 - 0.0, 15000.0, 0.52, 1231.4999999999934, 884.1999999999911, 1375.3000000000052 - 0.0, 15000.0, 0.56, 1845.2999999999683, 936.0999999999684, 1599.799999999946 - 0.0, 15000.0, 0.6, 2465.5999999997866, 993.0999999999193, 1820.3999999998093 - 0.0, 15000.0, 0.64, 3070.3999999999896, 1050.999999999959, 2057.8999999998896 - 0.0, 15000.0, 0.68, 3700.500000000119, 1104.3999999999803, 2296.099999999792 - 0.0, 15000.0, 0.72, 4312.89999999986, 1156.0999999999253, 2537.7999999998397 - 0.0, 15000.0, 0.76, 4919.19999999985, 1218.8999999999473, 2778.199999999837 - 0.0, 15000.0, 0.8, 5536.000000000075, 1286.6999999999873, 3042.9999999999577 - 0.0, 15000.0, 0.84, 5894.917142857293, 1325.1942857142812, 3191.828571428538 - 0.0, 15000.0, 0.88, 6096.44857142881, 1345.4971428571446, 3272.994285714213 - 0.0, 15000.0, 0.92, 6290.805599999711, 1363.729599999995, 3359.2095999999237 - 0.0, 15000.0, 0.96, 6528.771199999519, 1385.9991999999752, 3474.3791999998894 - 0.0, 15000.0, 1.0, 6761.699999999236, 1408.399999999948, 3593.5999999998494 - 0.0, 20000.0, 0.52, 1005.0999999999442, -179.8000000000082, -972.099999999996 - 0.0, 20000.0, 0.56, 1499.400000000155, 58.29999999996068, -409.499999999999 - 0.0, 20000.0, 0.6, 1993.7000000003677, 236.59999999991925, 148.1999999999089 - 0.0, 20000.0, 0.64, 2524.3999999997613, 414.79999999957806, 704.8999999990343 - 0.0, 20000.0, 0.68, 3035.199999999369, 576.599999999807, 1189.9999999984575 - 0.0, 20000.0, 0.72, 3553.4999999979827, 724.3999999991906, 1687.499999999159 - 0.0, 20000.0, 0.76, 4047.799999998764, 902.5000000000281, 2282.5999999976952 - 0.0, 20000.0, 0.8, 4558.599999998213, 1013.7000000002164, 2889.6999999998075 - 0.0, 20000.0, 0.84, 4843.655428571438, 1055.781142857111, 3050.746285714762 - 0.0, 20000.0, 0.88, 4996.649714286513, 1058.9125714285788, 2962.8291428588177 - 0.0, 20000.0, 0.92, 5169.605600002497, 1073.749600000052, 2931.046400000766 - 0.0, 20000.0, 0.96, 5397.8672000045635, 1109.9752000001365, 3044.4808000015146 - 0.0, 20000.0, 1.0, 5600.100000007005, 1136.3000000002728, 3176.2000000024345 - 0.0, 25000.0, 0.52, 1454.9999999999484, 1019.3999999999954, 1480.0999999997996 - 0.0, 25000.0, 0.56, 2278.299999999715, 1094.6999999998795, 1873.4999999997287 - 0.0, 25000.0, 0.6, 3040.799999999219, 1180.799999999564, 2124.2999999987683 - 0.0, 25000.0, 0.64, 3745.299999999083, 1266.6999999997893, 2485.0999999995415 - 0.0, 25000.0, 0.68, 4545.299999997396, 1284.5999999996125, 2619.8000000001202 - 0.0, 25000.0, 0.72, 5200.299999996687, 1386.8999999996997, 2950.400000000227 - 0.0, 25000.0, 0.76, 6179.599999998828, 1476.8999999993048, 3390.8999999997313 - 0.0, 25000.0, 0.8, 6774.100000001599, 1477.2999999995213, 3427.5000000001737 - 0.0, 25000.0, 0.84, 7201.338857143723, 1531.8771428571938, 3623.85314285827 - 0.0, 25000.0, 0.88, 7515.267428573812, 1612.0485714287408, 3889.6645714312112 - 0.0, 25000.0, 0.92, 7781.253599999968, 1670.7576000000292, 4065.1528000006115 - 0.0, 25000.0, 0.96, 8041.831200000129, 1697.8952000001418, 4129.50960000108 - 0.0, 25000.0, 1.0, 8316.700000000581, 1720.3000000002658, 4200.9000000017 - 0.0, 30000.0, 0.52, 1587.7999999999893, 1074.6999999999748, 1549.299999999925 - 0.0, 30000.0, 0.56, 2577.699999999213, 1142.3999999998246, 1948.0000000003222 - 0.0, 30000.0, 0.6, 3346.7999999986814, 1253.799999999447, 2131.4000000006454 - 0.0, 30000.0, 0.64, 4046.699999999955, 1324.400000000169, 2579.499999998938 - 0.0, 30000.0, 0.68, 4934.5999999973865, 1431.000000000178, 2947.7999999993012 - 0.0, 30000.0, 0.72, 5728.000000000285, 1447.6999999999337, 2984.199999998774 - 0.0, 30000.0, 0.76, 6611.4999999956635, 1658.5999999995806, 3733.2000000005555 - 0.0, 30000.0, 0.8, 7535.400000000952, 1639.5000000003574, 3802.2000000005596 - 0.0, 30000.0, 0.84, 8005.990285715036, 1673.2474285716232, 3948.437142857921 - 0.0, 30000.0, 0.88, 8214.073142859635, 1737.461714286159, 4137.528571430464 - 0.0, 30000.0, 0.92, 8447.301600000092, 1800.6648000001267, 4315.3656 - 0.0, 30000.0, 0.96, 8799.627200001054, 1849.573600000298, 4467.291200000452 - 0.0, 30000.0, 1.0, 9171.300000002611, 1889.1000000005297, 4618.100000001108 - 0.0, 35000.0, 0.52, 1860.4999999998781, 1134.3999999999799, 1545.4999999998604 - 0.0, 35000.0, 0.56, 2646.6999999994337, 1179.499999999923, 1909.3999999996133 - 0.0, 35000.0, 0.6, 3462.499999998352, 1306.499999999773, 2426.999999998648 - 0.0, 35000.0, 0.64, 4472.699999998527, 1341.9999999994682, 2586.4999999985885 - 0.0, 35000.0, 0.68, 5314.899999996407, 1525.0999999996734, 3099.3999999973057 - 0.0, 35000.0, 0.72, 6140.699999998994, 1569.3999999997231, 3342.499999998407 - 0.0, 35000.0, 0.76, 7175.399999999354, 1721.900000000009, 3713.0999999989745 - 0.0, 35000.0, 0.8, 8001.200000002285, 1705.9000000002864, 3886.30000000061 - 0.0, 35000.0, 0.84, 8413.310857143115, 1739.1531428573096, 4151.494857142577 - 0.0, 35000.0, 0.88, 8587.819428573372, 1801.9645714290405, 4452.923428571376 - 0.0, 35000.0, 0.92, 8776.180800000748, 1865.99520000034, 4697.955199999519 - 0.0, 35000.0, 0.96, 9079.113600001861, 1920.1944000006904, 4867.6983999995155 - 0.0, 35000.0, 1.0, 9446.60000000331, 1970.8000000011382, 5016.999999999679 - 0.05, 0.0, 0.52, 794.7000000000002, 563.7, 1033.8000000000002 - 0.05, 0.0, 0.56, 1192.0999999999997, 597.0999999999993, 1192.4999999999975 - 0.05, 0.0, 0.6, 1589.4999999999993, 630.3999999999978, 1351.7999999999934 - 0.05, 0.0, 0.64, 1986.9000000000042, 663.4000000000009, 1511.6000000000063 - 0.05, 0.0, 0.68, 2384.199999999992, 696.2999999999997, 1672.300000000002 - 0.05, 0.0, 0.72, 2781.5999999999995, 731.0999999999974, 1840.1999999999955 - 0.05, 0.0, 0.76, 3178.999999999995, 766.4000000000009, 2011.3000000000038 - 0.05, 0.0, 0.8, 3576.3000000000106, 801.6999999999987, 2184.000000000001 - 0.05, 0.0, 0.84, 3799.5371428571525, 821.5680000000007, 2281.459428571425 - 0.05, 0.0, 0.88, 3924.448571428588, 832.7080000000001, 2336.5137142857066 - 0.05, 0.0, 0.92, 4067.9040000000005, 845.3103999999973, 2399.1103999999937 - 0.05, 0.0, 0.96, 4264.508000000001, 862.5927999999951, 2484.9727999999873 - 0.05, 0.0, 1.0, 4466.5999999999985, 880.7999999999923, 2575.599999999979 - 0.05, 5000.0, 0.52, 889.6000000000004, 614.6, 1099.3000000000004 - 0.05, 5000.0, 0.56, 1334.3, 652.600000000001, 1274.6000000000006 - 0.05, 5000.0, 0.6, 1779.0999999999979, 690.7000000000019, 1450.8000000000025 - 0.05, 5000.0, 0.64, 2223.900000000005, 728.3999999999988, 1627.6000000000022 - 0.05, 5000.0, 0.68, 2668.7000000000035, 765.8999999999959, 1805.5999999999967 - 0.05, 5000.0, 0.72, 3113.499999999998, 806.0999999999967, 1992.6000000000008 - 0.05, 5000.0, 0.76, 3558.2000000000053, 846.9000000000011, 2183.9000000000165 - 0.05, 5000.0, 0.8, 4002.999999999997, 887.4999999999983, 2375.8000000000143 - 0.05, 5000.0, 0.84, 4253.683428571426, 910.5022857142882, 2484.6691428571444 - 0.05, 5000.0, 0.88, 4393.477714285705, 923.4451428571472, 2546.260571428572 - 0.05, 5000.0, 0.92, 4550.772799999993, 937.7863999999995, 2614.872799999997 - 0.05, 5000.0, 0.96, 4763.633599999985, 957.1447999999989, 2707.713599999995 - 0.05, 5000.0, 1.0, 4979.799999999974, 977.2999999999981, 2804.8999999999924 - 0.05, 10000.0, 0.52, 1122.2, 753.6000000000003, 1260.2 - 0.05, 10000.0, 0.56, 1683.3000000000013, 805.3, 1475.6999999999991 - 0.05, 10000.0, 0.6, 2244.3000000000025, 856.4999999999984, 1691.6000000000001 - 0.05, 10000.0, 0.64, 2805.499999999996, 907.6999999999973, 1909.2000000000041 - 0.05, 10000.0, 0.68, 3366.4999999999977, 958.4999999999984, 2127.9999999999945 - 0.05, 10000.0, 0.72, 3927.6999999999907, 1011.3999999999996, 2353.900000000007 - 0.05, 10000.0, 0.76, 4488.70000000002, 1065.9999999999975, 2587.2000000000025 - 0.05, 10000.0, 0.8, 5049.799999999994, 1120.9000000000042, 2822.5999999999985 - 0.05, 10000.0, 0.84, 5370.272000000004, 1152.1399999999983, 2957.494857142854 - 0.05, 10000.0, 0.88, 5546.5720000000065, 1169.4399999999982, 3033.443428571422 - 0.05, 10000.0, 0.92, 5722.548799999993, 1187.2552000000028, 3112.422399999987 - 0.05, 10000.0, 0.96, 5947.265599999985, 1210.5704000000046, 3215.5727999999776 - 0.05, 10000.0, 1.0, 6174.9999999999745, 1234.9000000000074, 3323.1999999999653 - 0.05, 15000.0, 0.52, 1239.299999999997, 824.599999999995, 1372.2000000000028 - 0.05, 15000.0, 0.56, 1857.4999999999802, 878.9999999999816, 1600.4999999999734 - 0.05, 15000.0, 0.6, 2479.699999999888, 935.9999999999544, 1827.6999999999039 - 0.05, 15000.0, 0.64, 3093.2999999999865, 993.4999999999733, 2064.1999999999266 - 0.05, 15000.0, 0.68, 3720.500000000043, 1048.3999999999883, 2302.1999999998884 - 0.05, 15000.0, 0.72, 4338.199999999933, 1103.499999999959, 2545.5999999999067 - 0.05, 15000.0, 0.76, 4952.799999999873, 1165.3999999999614, 2792.199999999927 - 0.05, 15000.0, 0.8, 5573.000000000046, 1230.2999999999934, 3052.9999999999777 - 0.05, 15000.0, 0.84, 5930.8811428572135, 1267.7657142857086, 3203.362285714262 - 0.05, 15000.0, 0.88, 6129.732571428681, 1288.482857142852, 3288.6651428570876 - 0.05, 15000.0, 0.92, 6323.630399999844, 1308.0736000000006, 3376.665599999961 - 0.05, 15000.0, 0.96, 6565.076799999741, 1332.2871999999934, 3490.363199999942 - 0.05, 15000.0, 1.0, 6804.999999999589, 1356.9999999999811, 3607.9999999999213 - 0.05, 20000.0, 0.52, 1106.39999999996, 68.79999999999444, -301.19999999999766 - 0.05, 20000.0, 0.56, 1653.6000000001154, 258.49999999997067, 174.7000000000039 - 0.05, 20000.0, 0.6, 2200.8000000002758, 405.2999999999379, 648.2999999999498 - 0.05, 20000.0, 0.64, 2774.5999999998685, 551.9999999996978, 1122.6999999993177 - 0.05, 20000.0, 0.68, 3333.7999999995004, 686.7999999998589, 1545.1999999989152 - 0.05, 20000.0, 0.72, 3897.79999999865, 811.9999999994433, 1978.999999999422 - 0.05, 20000.0, 0.76, 4444.999999999165, 959.6000000000246, 2485.5999999983915 - 0.05, 20000.0, 0.8, 5004.199999998734, 1059.9000000001495, 3002.399999999782 - 0.05, 20000.0, 0.84, 5319.062285714257, 1102.126285714259, 3166.3811428574527 - 0.05, 20000.0, 0.88, 5489.325142857627, 1111.2491428571377, 3131.912571429708 - 0.05, 20000.0, 0.92, 5672.192800001668, 1128.4488000000244, 3136.948000000519 - 0.05, 20000.0, 0.96, 5909.93760000307, 1162.4856000000757, 3252.272000001029 - 0.05, 20000.0, 1.0, 6129.900000004725, 1189.7000000001613, 3381.5000000016544 - 0.05, 25000.0, 0.52, 1470.3999999999637, 948.9999999999962, 1485.3999999998584 - 0.05, 25000.0, 0.56, 2273.6999999997906, 1024.4999999999134, 1847.5999999998128 - 0.05, 25000.0, 0.6, 3033.1999999994314, 1107.2999999996928, 2109.39999999915 - 0.05, 25000.0, 0.64, 3752.49999999933, 1189.899999999847, 2449.8999999996854 - 0.05, 25000.0, 0.68, 4539.599999998129, 1224.1999999997247, 2629.600000000122 - 0.05, 25000.0, 0.72, 5222.899999997663, 1318.7999999997667, 2949.8000000001707 - 0.05, 25000.0, 0.76, 6137.499999999119, 1405.6999999995166, 3354.799999999818 - 0.05, 25000.0, 0.8, 6777.300000001191, 1431.1999999996553, 3478.000000000095 - 0.05, 25000.0, 0.84, 7205.9742857148285, 1483.7662857143125, 3672.2222857150814 - 0.05, 25000.0, 0.88, 7498.117142858703, 1547.6891428572442, 3890.3251428590083 - 0.05, 25000.0, 0.92, 7753.888799999919, 1596.3480000000088, 4043.9128000004284 - 0.05, 25000.0, 0.96, 8022.317599999999, 1624.9440000000818, 4127.097600000756 - 0.05, 25000.0, 1.0, 8301.30000000027, 1650.500000000162, 4216.50000000119 - 0.05, 30000.0, 0.52, 1607.3999999999937, 1006.499999999982, 1558.1999999999473 - 0.05, 30000.0, 0.56, 2551.49999999945, 1079.099999999876, 1932.7000000002267 - 0.05, 30000.0, 0.6, 3338.3999999990897, 1182.8999999996108, 2153.7000000004614 - 0.05, 30000.0, 0.64, 4074.899999999916, 1257.6000000001118, 2566.0999999992223 - 0.05, 30000.0, 0.68, 4945.799999998146, 1357.5000000001237, 2920.1999999995073 - 0.05, 30000.0, 0.72, 5749.8000000002285, 1395.1999999999523, 3042.3999999991433 - 0.05, 30000.0, 0.76, 6617.199999996998, 1571.0999999997098, 3674.700000000362 - 0.05, 30000.0, 0.8, 7513.300000000715, 1583.6000000002516, 3826.2000000003773 - 0.05, 30000.0, 0.84, 7985.145142857598, 1622.9342857144159, 3990.0468571433676 - 0.05, 30000.0, 0.88, 8208.216571430181, 1677.3771428574441, 4158.575428572685 - 0.05, 30000.0, 0.92, 8445.921600000001, 1730.664800000082, 4317.977599999974 - 0.05, 30000.0, 0.96, 8785.815200000641, 1775.6096000001992, 4466.731200000284 - 0.05, 30000.0, 1.0, 9139.600000001694, 1814.1000000003587, 4615.600000000735 - 0.05, 35000.0, 0.52, 1839.8999999999116, 1055.4999999999857, 1573.4999999999002 - 0.05, 35000.0, 0.56, 2656.8999999995813, 1114.6999999999477, 1930.6999999997274 - 0.05, 35000.0, 0.6, 3493.799999998788, 1230.7999999998467, 2396.3999999990688 - 0.05, 35000.0, 0.64, 4470.399999998946, 1282.1999999996144, 2608.2999999990197 - 0.05, 35000.0, 0.68, 5327.299999997423, 1439.2999999997676, 3073.8999999980924 - 0.05, 35000.0, 0.72, 6172.299999999443, 1495.1999999998102, 3343.9999999989122 - 0.05, 35000.0, 0.76, 7167.199999999515, 1633.6000000000142, 3722.2999999992676 - 0.05, 35000.0, 0.8, 8012.20000000163, 1651.800000000201, 3957.4000000004644 - 0.05, 35000.0, 0.84, 8453.65314285734, 1692.6057142858167, 4211.559428571177 - 0.05, 35000.0, 0.88, 8659.064571429954, 1746.7828571431594, 4463.093714285574 - 0.05, 35000.0, 0.92, 8869.845600000495, 1801.1456000002263, 4672.445599999682 - 0.05, 35000.0, 0.96, 9179.595200001253, 1850.4112000004677, 4835.803199999678 - 0.05, 35000.0, 1.0, 9534.100000002234, 1897.2000000007772, 4985.099999999786 - 0.1, 0.0, 0.52, 794.3, 508.8000000000001, 1027.5000000000007 - 0.1, 0.0, 0.56, 1191.5000000000005, 542.3999999999995, 1185.899999999994 - 0.1, 0.0, 0.6, 1588.7000000000019, 575.8999999999962, 1345.0999999999865 - 0.1, 0.0, 0.64, 1985.9000000000055, 609.1000000000029, 1504.7000000000212 - 0.1, 0.0, 0.68, 2383.099999999966, 642.0999999999981, 1665.200000000004 - 0.1, 0.0, 0.72, 2780.200000000006, 676.9999999999911, 1832.999999999994 - 0.1, 0.0, 0.76, 3177.399999999991, 712.5000000000006, 2003.800000000018 - 0.1, 0.0, 0.8, 3574.5000000000277, 748.1000000000004, 2176.699999999999 - 0.1, 0.0, 0.84, 3797.654857142873, 768.0862857142888, 2274.138857142845 - 0.1, 0.0, 0.88, 3922.5034285714564, 779.229142857147, 2329.027428571406 - 0.1, 0.0, 0.92, 4065.7584000000097, 791.8023999999932, 2391.42319999998 - 0.1, 0.0, 0.96, 4261.984800000016, 809.0727999999885, 2477.090399999966 - 0.1, 0.0, 1.0, 4463.600000000023, 827.2999999999823, 2567.4999999999477 - 0.1, 5000.0, 0.52, 889.0000000000015, 557.5000000000002, 1092.8000000000009 - 0.1, 5000.0, 0.56, 1333.4000000000005, 595.8000000000034, 1267.800000000004 - 0.1, 5000.0, 0.6, 1777.899999999997, 634.0000000000047, 1443.800000000009 - 0.1, 5000.0, 0.64, 2222.300000000032, 671.8999999999932, 1620.5000000000032 - 0.1, 5000.0, 0.68, 2666.9000000000055, 709.5999999999892, 1798.099999999987 - 0.1, 5000.0, 0.72, 3111.300000000007, 749.8999999999895, 1985.2999999999984 - 0.1, 5000.0, 0.76, 3555.7000000000094, 791.0000000000016, 2176.3000000000575 - 0.1, 5000.0, 0.8, 4000.2999999999993, 831.7999999999965, 2368.0000000000427 - 0.1, 5000.0, 0.84, 4250.895999999973, 854.8514285714348, 2476.6691428571467 - 0.1, 5000.0, 0.88, 4390.535999999959, 867.7657142857265, 2538.0605714285725 - 0.1, 5000.0, 0.92, 4547.20639999999, 882.1103999999964, 2606.4727999999886 - 0.1, 5000.0, 0.96, 4759.016799999973, 901.540799999993, 2699.113599999979 - 0.1, 5000.0, 1.0, 4974.1999999999525, 921.7999999999882, 2796.0999999999653 - 0.1, 10000.0, 0.52, 1121.099999999999, 692.4000000000004, 1253.3 - 0.1, 10000.0, 0.56, 1681.8000000000025, 744.3999999999999, 1468.6 - 0.1, 10000.0, 0.6, 2242.300000000005, 795.7999999999945, 1684.3000000000056 - 0.1, 10000.0, 0.64, 2802.899999999985, 847.199999999995, 1901.800000000008 - 0.1, 10000.0, 0.68, 3363.400000000002, 898.2999999999928, 2120.4999999999827 - 0.1, 10000.0, 0.72, 3924.099999999962, 951.299999999996, 2346.3000000000293 - 0.1, 10000.0, 0.76, 4484.600000000045, 1006.1999999999955, 2579.3000000000097 - 0.1, 10000.0, 0.8, 5045.200000000003, 1061.3000000000125, 2814.6000000000017 - 0.1, 10000.0, 0.84, 5365.426285714286, 1092.6542857142804, 2949.2908571428484 - 0.1, 10000.0, 0.88, 5541.569142857143, 1110.0171428571364, 3024.9794285714142 - 0.1, 10000.0, 0.92, 5717.199999999958, 1127.8952000000081, 3103.7303999999594 - 0.1, 10000.0, 0.96, 5941.327999999926, 1151.2904000000128, 3206.692799999931 - 0.1, 10000.0, 1.0, 6168.399999999882, 1175.7000000000198, 3314.099999999893 - 0.1, 15000.0, 0.52, 1242.099999999999, 763.2999999999976, 1363.8000000000009 - 0.1, 15000.0, 0.56, 1862.1999999999907, 819.3999999999908, 1594.299999999989 - 0.1, 15000.0, 0.6, 2484.4999999999527, 876.4999999999782, 1825.2999999999615 - 0.1, 15000.0, 0.64, 3102.6999999999903, 933.7999999999855, 2060.9999999999604 - 0.1, 15000.0, 0.68, 3727.0000000000036, 989.7999999999946, 2298.599999999951 - 0.1, 15000.0, 0.72, 4347.099999999976, 1047.0999999999813, 2542.699999999954 - 0.1, 15000.0, 0.76, 4965.899999999921, 1108.5999999999776, 2792.999999999975 - 0.1, 15000.0, 0.8, 5587.200000000024, 1171.6999999999962, 3050.999999999989 - 0.1, 15000.0, 0.84, 5943.880571428597, 1208.5234285714241, 3201.948571428556 - 0.1, 15000.0, 0.88, 6140.746285714322, 1229.4977142857083, 3289.434285714251 - 0.1, 15000.0, 0.92, 6333.903199999929, 1249.9472000000028, 3378.187199999981 - 0.1, 15000.0, 0.96, 6576.854399999883, 1275.402400000001, 3490.6543999999717 - 0.1, 15000.0, 1.0, 6820.4999999998145, 1301.599999999998, 3606.999999999961 - 0.1, 20000.0, 0.52, 1185.399999999973, 254.6999999999964, 228.7000000000013 - 0.1, 20000.0, 0.56, 1773.9000000000829, 405.89999999997883, 635.3000000000055 - 0.1, 20000.0, 0.6, 2362.4000000001984, 527.5999999999539, 1041.499999999978 - 0.1, 20000.0, 0.64, 2969.599999999941, 649.1999999997931, 1449.6999999995398 - 0.1, 20000.0, 0.68, 3566.4999999996157, 762.4999999999006, 1821.8999999992723 - 0.1, 20000.0, 0.72, 4166.19999999915, 869.6999999996369, 2204.3999999996245 - 0.1, 20000.0, 0.76, 4754.699999999465, 993.1000000000199, 2640.0999999989294 - 0.1, 20000.0, 0.8, 5351.599999999146, 1084.6000000000981, 3084.399999999789 - 0.1, 20000.0, 0.84, 5689.7377142856685, 1126.9245714285498, 3250.2691428573294 - 0.1, 20000.0, 0.88, 5873.494857143123, 1140.8702857142741, 3258.020571429297 - 0.1, 20000.0, 0.92, 6063.965600001045, 1160.035200000007, 3292.092000000332 - 0.1, 20000.0, 0.96, 6308.819200001942, 1192.4144000000351, 3408.6720000006612 - 0.1, 20000.0, 1.0, 6542.300000003, 1220.4000000000844, 3535.700000001062 - 0.1, 25000.0, 0.52, 1480.599999999976, 879.8999999999971, 1484.1999999999043 - 0.1, 25000.0, 0.56, 2267.1999999998516, 955.5999999999411, 1821.3999999998762 - 0.1, 25000.0, 0.6, 3023.4999999996016, 1035.8999999997932, 2091.2999999994413 - 0.1, 25000.0, 0.64, 3753.399999999525, 1115.999999999894, 2415.2999999997933 - 0.1, 25000.0, 0.68, 4529.2999999987105, 1163.2999999998128, 2630.100000000109 - 0.1, 25000.0, 0.72, 5233.999999998426, 1251.8999999998252, 2941.800000000121 - 0.1, 25000.0, 0.76, 6096.599999999359, 1336.49999999968, 3317.999999999882 - 0.1, 25000.0, 0.8, 6771.30000000085, 1381.4999999997615, 3507.900000000041 - 0.1, 25000.0, 0.84, 7200.592571428879, 1432.57200000001, 3700.2308571433914 - 0.1, 25000.0, 0.88, 7475.1782857152275, 1483.972000000053, 3881.239428572684 - 0.1, 25000.0, 0.92, 7722.371999999904, 1524.8983999999964, 4017.819200000287 - 0.1, 25000.0, 0.96, 7996.259999999931, 1554.66480000004, 4115.570400000506 - 0.1, 25000.0, 1.0, 8277.700000000077, 1582.7000000000874, 4218.800000000796 - 0.1, 30000.0, 0.52, 1620.5999999999967, 938.6999999999878, 1559.3999999999648 - 0.1, 30000.0, 0.56, 2527.299999999633, 1015.2999999999162, 1914.3000000001516 - 0.1, 30000.0, 0.6, 3326.8999999994, 1113.1999999997383, 2164.600000000316 - 0.1, 30000.0, 0.64, 4091.199999999899, 1191.2000000000673, 2547.999999999454 - 0.1, 30000.0, 0.68, 4947.499999998739, 1286.0000000000807, 2890.5999999996675 - 0.1, 30000.0, 0.72, 5758.600000000174, 1339.9999999999666, 3079.29999999943 - 0.1, 30000.0, 0.76, 6612.199999998024, 1488.499999999809, 3619.1000000002186 - 0.1, 30000.0, 0.8, 7485.300000000515, 1526.3000000001698, 3835.600000000238 - 0.1, 30000.0, 0.84, 7957.532000000242, 1570.200000000082, 4013.237714286026 - 0.1, 30000.0, 0.88, 8192.07200000096, 1616.9600000001933, 4165.394857143638 - 0.1, 30000.0, 0.92, 8432.85839999995, 1662.436800000049, 4309.990399999962 - 0.1, 30000.0, 0.96, 8762.304800000347, 1704.293600000125, 4455.86880000016 - 0.1, 30000.0, 1.0, 9101.30000000102, 1742.0000000002287, 4602.800000000455 - 0.1, 35000.0, 0.52, 1822.0999999999385, 980.2999999999904, 1590.6999999999316 - 0.1, 35000.0, 0.56, 2662.6999999997015, 1050.5999999999663, 1941.9999999998163 - 0.1, 35000.0, 0.6, 3515.799999999142, 1158.399999999902, 2366.499999999392 - 0.1, 35000.0, 0.64, 4465.1999999992795, 1222.4999999997315, 2619.399999999354 - 0.1, 35000.0, 0.68, 5332.999999998226, 1359.099999999842, 3047.0999999987075 - 0.1, 35000.0, 0.72, 6192.4999999997435, 1424.6999999998754, 3338.8999999992966 - 0.1, 35000.0, 0.76, 7155.099999999643, 1551.9000000000142, 3721.4999999994993 - 0.1, 35000.0, 0.8, 8014.600000001109, 1597.4000000001347, 4005.8000000003403 - 0.1, 35000.0, 0.84, 8478.786857143004, 1644.3017142857702, 4251.2331428569305 - 0.1, 35000.0, 0.88, 8708.27542857236, 1691.6988571430365, 4463.144571428395 - 0.1, 35000.0, 0.92, 8936.320800000314, 1738.4688000001406, 4644.051199999805 - 0.1, 35000.0, 0.96, 9250.897600000797, 1783.9216000002984, 4802.1263999998 - 0.1, 35000.0, 1.0, 9594.700000001427, 1827.8000000005006, 4951.199999999868 -0.15000000000000002, 0.0, 0.52, 793.2000000000002, 454.1000000000001, 1016.8 -0.15000000000000002, 0.0, 0.56, 1189.7999999999984, 487.79999999999933, 1174.899999999999 -0.15000000000000002, 0.0, 0.6, 1586.4999999999966, 521.499999999999, 1333.6999999999996 -0.15000000000000002, 0.0, 0.64, 1983.0999999999956, 554.9000000000004, 1492.9999999999945 -0.15000000000000002, 0.0, 0.68, 2379.5999999999967, 588.0999999999991, 1653.1000000000013 -0.15000000000000002, 0.0, 0.72, 2776.1999999999857, 623.2000000000028, 1820.3999999999862 -0.15000000000000002, 0.0, 0.76, 3172.799999999992, 658.7999999999964, 1990.899999999992 -0.15000000000000002, 0.0, 0.8, 3569.400000000006, 694.7000000000066, 2163.9000000000137 -0.15000000000000002, 0.0, 0.84, 3792.300571428572, 714.8657142857145, 2261.2485714285663 -0.15000000000000002, 0.0, 0.88, 3916.9462857142858, 726.102857142858, 2315.8942857142756 -0.15000000000000002, 0.0, 0.92, 4059.713600000006, 738.7287999999996, 2377.928799999996 -0.15000000000000002, 0.0, 0.96, 4255.115200000006, 756.0375999999991, 2463.1575999999936 -0.15000000000000002, 0.0, 1.0, 4455.800000000005, 774.2999999999989, 2553.0999999999917 -0.15000000000000002, 5000.0, 0.52, 886.8999999999999, 500.6000000000001, 1081.4000000000005 -0.15000000000000002, 5000.0, 0.56, 1330.399999999998, 539.0999999999999, 1256.1999999999987 -0.15000000000000002, 5000.0, 0.6, 1773.8999999999965, 577.3999999999993, 1431.5999999999972 -0.15000000000000002, 5000.0, 0.64, 2217.399999999995, 615.499999999996, 1607.7000000000046 -0.15000000000000002, 5000.0, 0.68, 2660.799999999998, 653.5999999999992, 1785.4 -0.15000000000000002, 5000.0, 0.72, 3104.299999999984, 693.9999999999997, 1971.8999999999946 -0.15000000000000002, 5000.0, 0.76, 3547.700000000015, 735.2999999999942, 2162.2999999999984 -0.15000000000000002, 5000.0, 0.8, 3991.2000000000303, 776.4000000000046, 2354.1999999999966 -0.15000000000000002, 5000.0, 0.84, 4241.228000000004, 799.6308571428572, 2462.8480000000027 -0.15000000000000002, 5000.0, 0.88, 4380.568000000013, 812.6394285714288, 2524.0280000000057 -0.15000000000000002, 5000.0, 0.92, 4536.743200000002, 827.0336000000023, 2592.0464000000034 -0.15000000000000002, 5000.0, 0.96, 4747.798400000002, 846.4992000000034, 2684.164800000004 -0.15000000000000002, 5000.0, 1.0, 4962.299999999995, 866.8000000000046, 2780.6000000000063 -0.15000000000000002, 10000.0, 0.52, 1118.9, 631.5000000000003, 1241.7000000000003 -0.15000000000000002, 10000.0, 0.56, 1678.2999999999968, 683.7999999999988, 1456.5999999999979 -0.15000000000000002, 10000.0, 0.6, 2237.7999999999925, 735.4999999999965, 1672.0999999999974 -0.15000000000000002, 10000.0, 0.64, 2797.199999999987, 787.2999999999975, 1889.2000000000014 -0.15000000000000002, 10000.0, 0.68, 3356.6999999999957, 838.7, 2107.399999999981 -0.15000000000000002, 10000.0, 0.72, 3916.0999999999967, 891.9999999999985, 2332.799999999998 -0.15000000000000002, 10000.0, 0.76, 4475.499999999992, 947.1999999999925, 2565.5999999999954 -0.15000000000000002, 10000.0, 0.8, 5035.000000000034, 1002.6000000000054, 2800.4000000000156 -0.15000000000000002, 10000.0, 0.84, 5354.653714285712, 1034.0645714285697, 2934.670285714286 -0.15000000000000002, 10000.0, 0.88, 5530.450857142859, 1051.430285714282, 3009.973142857142 -0.15000000000000002, 10000.0, 0.92, 5705.499199999995, 1069.3272000000002, 3088.3000000000006 -0.15000000000000002, 10000.0, 0.96, 5928.670399999991, 1092.7984, 3190.783999999996 -0.15000000000000002, 10000.0, 1.0, 6154.599999999991, 1117.2999999999993, 3297.6999999999903 -0.15000000000000002, 15000.0, 0.52, 1240.7999999999997, 700.9999999999991, 1350.4 -0.15000000000000002, 15000.0, 0.56, 1860.6999999999973, 758.1999999999967, 1581.799999999997 -0.15000000000000002, 15000.0, 0.6, 2481.599999999988, 815.4999999999928, 1814.3999999999899 -0.15000000000000002, 15000.0, 0.64, 3100.9999999999955, 872.7999999999953, 2049.3999999999864 -0.15000000000000002, 15000.0, 0.68, 3722.299999999992, 929.5999999999987, 2286.399999999986 -0.15000000000000002, 15000.0, 0.72, 4342.399999999994, 988.1999999999946, 2530.3999999999864 -0.15000000000000002, 15000.0, 0.76, 4962.0999999999685, 1049.6999999999914, 2782.3999999999933 -0.15000000000000002, 15000.0, 0.8, 5582.600000000005, 1111.8999999999978, 3038.4999999999955 -0.15000000000000002, 15000.0, 0.84, 5937.8880000000045, 1148.3942857142836, 3189.270285714279 -0.15000000000000002, 15000.0, 0.88, 6133.2680000000055, 1169.4971428571396, 3277.393142857127 -0.15000000000000002, 15000.0, 0.92, 6325.419199999976, 1190.4112000000018, 3366.0663999999924 -0.15000000000000002, 15000.0, 0.96, 6568.270399999964, 1216.5624000000025, 3477.456799999986 -0.15000000000000002, 15000.0, 1.0, 6812.999999999942, 1243.600000000003, 3592.6999999999803 -0.15000000000000002, 20000.0, 0.52, 1244.3999999999828, 385.0999999999981, 633.0000000000009 -0.15000000000000002, 20000.0, 0.56, 1863.8000000000561, 506.5999999999858, 985.7000000000063 -0.15000000000000002, 20000.0, 0.6, 2483.2000000001344, 608.8999999999676, 1339.2999999999959 -0.15000000000000002, 20000.0, 0.64, 3115.0999999999854, 711.0999999998659, 1695.5999999997084 -0.15000000000000002, 20000.0, 0.68, 3740.099999999717, 807.7999999999333, 2028.3999999995408 -0.15000000000000002, 20000.0, 0.72, 4366.499999999508, 901.0999999997791, 2370.599999999772 -0.15000000000000002, 20000.0, 0.76, 4985.899999999675, 1005.9000000000144, 2750.99999999933 -0.15000000000000002, 20000.0, 0.8, 5610.899999999465, 1090.500000000061, 3138.599999999819 -0.15000000000000002, 20000.0, 0.84, 5966.458857142813, 1132.8879999999838, 3305.4188571429568 -0.15000000000000002, 20000.0, 0.88, 6160.327428571556, 1150.6079999999865, 3345.4074285718552 -0.15000000000000002, 20000.0, 0.92, 6356.304800000598, 1171.371199999998, 3401.5880000001966 -0.15000000000000002, 20000.0, 0.96, 6606.093600001129, 1202.5544000000114, 3518.8400000003926 -0.15000000000000002, 20000.0, 1.0, 6849.300000001754, 1231.2000000000369, 3643.900000000631 -0.15000000000000002, 25000.0, 0.52, 1485.999999999985, 812.2999999999979, 1477.099999999939 -0.15000000000000002, 25000.0, 0.56, 2258.6999999999007, 888.1999999999621, 1794.6999999999232 -0.15000000000000002, 25000.0, 0.6, 3011.4999999997362, 966.6999999998686, 2070.099999999656 -0.15000000000000002, 25000.0, 0.64, 3748.199999999674, 1044.99999999993, 2380.8999999998705 -0.15000000000000002, 25000.0, 0.68, 4514.2999999991625, 1102.29999999988, 2622.0000000000873 -0.15000000000000002, 25000.0, 0.72, 5234.199999998997, 1186.3999999998748, 2926.80000000008 -0.15000000000000002, 25000.0, 0.76, 6055.899999999557, 1269.3999999998014, 3280.0999999999267 -0.15000000000000002, 25000.0, 0.8, 6756.2000000005755, 1328.999999999844, 3519.2000000000085 -0.15000000000000002, 25000.0, 0.84, 7185.327428571578, 1379.0297142857141, 3709.804000000335 -0.15000000000000002, 25000.0, 0.88, 7446.061714286227, 1421.1668571428775, 3862.9840000007894 -0.15000000000000002, 25000.0, 0.92, 7686.098399999908, 1456.3887999999902, 3986.804000000181 -0.15000000000000002, 25000.0, 0.96, 7963.300799999905, 1487.0736000000131, 4095.3440000003193 -0.15000000000000002, 25000.0, 1.0, 8245.699999999973, 1517.0000000000382, 4208.700000000499 -0.15000000000000002, 30000.0, 0.52, 1627.8999999999987, 871.5999999999921, 1553.599999999978 -0.15000000000000002, 30000.0, 0.56, 2504.49999999977, 951.3999999999465, 1892.9000000000947 -0.15000000000000002, 30000.0, 0.6, 3312.199999999628, 1044.8999999998339, 2165.100000000203 -0.15000000000000002, 30000.0, 0.64, 4096.399999999897, 1125.5000000000352, 2525.399999999637 -0.15000000000000002, 30000.0, 0.68, 4940.099999999187, 1216.6000000000492, 2858.7999999997874 -0.15000000000000002, 30000.0, 0.72, 5755.100000000121, 1282.7999999999768, 3096.9999999996426 -0.15000000000000002, 30000.0, 0.76, 6596.799999998783, 1410.5999999998814, 3565.6000000001195 -0.15000000000000002, 30000.0, 0.8, 7451.000000000353, 1468.100000000108, 3831.5000000001364 -0.15000000000000002, 30000.0, 0.84, 7922.7782857143875, 1515.6548571429043, 4019.493714285886 -0.15000000000000002, 30000.0, 0.88, 8165.64114285765, 1556.5834285715432, 4158.970857143299 -0.15000000000000002, 30000.0, 0.92, 8408.235199999925, 1596.1136000000251, 4291.961599999959 -0.15000000000000002, 30000.0, 0.96, 8728.92640000015, 1635.6552000000713, 4435.215200000077 -0.15000000000000002, 30000.0, 1.0, 9055.80000000054, 1672.8000000001334, 4580.200000000255 -0.15000000000000002, 35000.0, 0.52, 1806.4999999999595, 908.6999999999938, 1598.0999999999558 -0.15000000000000002, 35000.0, 0.56, 2664.199999999797, 987.4999999999794, 1944.199999999884 -0.15000000000000002, 35000.0, 0.6, 3528.999999999421, 1089.2999999999413, 2336.899999999629 -0.15000000000000002, 35000.0, 0.64, 4456.699999999534, 1163.2999999998235, 2620.699999999601 -0.15000000000000002, 35000.0, 0.68, 5331.899999998844, 1284.299999999898, 3018.799999999172 -0.15000000000000002, 35000.0, 0.72, 6201.599999999921, 1357.8999999999241, 3327.4999999995766 -0.15000000000000002, 35000.0, 0.76, 7138.399999999748, 1476.5000000000111, 3711.4999999996785 -0.15000000000000002, 35000.0, 0.8, 8008.10000000072, 1543.2000000000853, 4033.6000000002405 -0.15000000000000002, 35000.0, 0.84, 8489.108571428673, 1594.9165714285964, 4272.282857142688 -0.15000000000000002, 35000.0, 0.88, 8736.614285714872, 1637.1822857143798, 4453.651428571252 -0.15000000000000002, 35000.0, 0.92, 8977.342400000181, 1678.200000000079, 4612.5111999998935 -0.15000000000000002, 35000.0, 0.96, 9294.94480000047, 1720.8320000001745, 4766.2623999998905 -0.15000000000000002, 35000.0, 1.0, 9630.000000000842, 1762.6000000002973, 4914.8999999999305 - 0.2, 0.0, 0.52, 791.4, 399.60000000000025, 1001.9999999999999 - 0.2, 0.0, 0.56, 1186.9999999999964, 433.59999999999894, 1159.5000000000023 - 0.2, 0.0, 0.6, 1582.5999999999922, 467.4999999999981, 1317.8000000000077 - 0.2, 0.0, 0.64, 1978.299999999995, 501.10000000000264, 1476.5999999999874 - 0.2, 0.0, 0.68, 2373.9999999999945, 534.4999999999957, 1636.200000000012 - 0.2, 0.0, 0.72, 2769.5999999999817, 569.8000000000047, 1802.6999999999653 - 0.2, 0.0, 0.76, 3165.2999999999884, 605.6999999999906, 1972.8999999999737 - 0.2, 0.0, 0.8, 3561.0000000000164, 642.0000000000198, 2145.600000000041 - 0.2, 0.0, 0.84, 3783.4702857142884, 662.3085714285754, 2242.7314285714187 - 0.2, 0.0, 0.88, 3907.8331428571446, 673.5342857142958, 2297.145714285699 - 0.2, 0.0, 0.92, 4049.93040000002, 686.1359999999979, 2358.7471999999843 - 0.2, 0.0, 0.96, 4244.164800000027, 703.4719999999961, 2443.3343999999784 - 0.2, 0.0, 1.0, 4443.500000000032, 721.7999999999943, 2532.5999999999704 - 0.2, 5000.0, 0.52, 884.0999999999996, 443.90000000000003, 1066.0000000000007 - 0.2, 5000.0, 0.56, 1326.0999999999967, 482.69999999999953, 1239.8999999999962 - 0.2, 5000.0, 0.6, 1768.09999999999, 521.1999999999996, 1414.5999999999974 - 0.2, 5000.0, 0.64, 2210.1999999999684, 559.4999999999877, 1590.0000000000196 - 0.2, 5000.0, 0.68, 2652.1999999999857, 598.1000000000003, 1767.8999999999944 - 0.2, 5000.0, 0.72, 3094.1999999999375, 638.6999999999967, 1953.2999999999784 - 0.2, 5000.0, 0.76, 3536.2000000000503, 680.0999999999866, 2142.9000000000024 - 0.2, 5000.0, 0.8, 3978.300000000092, 721.6000000000138, 2334.0999999999963 - 0.2, 5000.0, 0.84, 4227.624000000026, 745.0388571428615, 2442.5142857143 - 0.2, 5000.0, 0.88, 4366.524000000057, 758.1274285714361, 2503.6571428571697 - 0.2, 5000.0, 0.92, 4521.7152000000115, 772.5536000000072, 2571.379199999999 - 0.2, 5000.0, 0.96, 4731.18640000001, 792.0512000000111, 2662.8584 - 0.2, 5000.0, 1.0, 4944.200000000009, 812.4000000000163, 2758.6000000000004 - 0.2, 10000.0, 0.52, 1115.4000000000003, 571.2000000000008, 1225.6000000000006 - 0.2, 10000.0, 0.56, 1672.9999999999945, 623.8999999999962, 1439.9999999999986 - 0.2, 10000.0, 0.6, 2230.699999999989, 675.9999999999893, 1654.8000000000072 - 0.2, 10000.0, 0.64, 2788.299999999961, 728.0999999999955, 1871.4000000000187 - 0.2, 10000.0, 0.68, 3346.0999999999854, 779.9000000000004, 2088.999999999939 - 0.2, 10000.0, 0.72, 3903.6999999999935, 833.6000000000054, 2313.6999999999975 - 0.2, 10000.0, 0.76, 4461.30000000001, 889.1999999999794, 2545.8999999999796 - 0.2, 10000.0, 0.8, 5019.00000000009, 945.0000000000168, 2780.4000000000437 - 0.2, 10000.0, 0.84, 5337.733714285725, 976.6359999999968, 2914.098857142852 - 0.2, 10000.0, 0.88, 5513.010857142885, 994.0359999999911, 2988.667428571416 - 0.2, 10000.0, 0.92, 5687.161600000011, 1011.9640000000002, 3066.2663999999886 - 0.2, 10000.0, 0.96, 5908.875200000028, 1035.5120000000006, 3168.0767999999703 - 0.2, 10000.0, 1.0, 6133.200000000053, 1060.1000000000029, 3274.299999999943 - 0.2, 15000.0, 0.52, 1236.2999999999997, 638.3999999999999, 1332.2999999999997 - 0.2, 15000.0, 0.56, 1854.2999999999993, 696.2999999999997, 1563.5999999999995 - 0.2, 15000.0, 0.6, 2472.599999999999, 753.8999999999996, 1796.1999999999996 - 0.2, 15000.0, 0.64, 3090.5999999999995, 811.4000000000004, 2030.5000000000014 - 0.2, 15000.0, 0.68, 3708.6999999999975, 868.7999999999998, 2266.7 - 0.2, 15000.0, 0.72, 4326.900000000001, 928.1000000000004, 2510.0000000000036 - 0.2, 15000.0, 0.76, 4945.000000000002, 989.9000000000005, 2762.1999999999966 - 0.2, 15000.0, 0.8, 5563.1999999999925, 1051.899999999999, 3016.999999999999 - 0.2, 15000.0, 0.84, 5916.8759999999975, 1088.305142857143, 3167.010285714286 - 0.2, 15000.0, 0.88, 6111.075999999997, 1109.4365714285716, 3254.633142857144 - 0.2, 15000.0, 0.92, 6301.973599999998, 1130.5264000000002, 3342.5951999999975 - 0.2, 15000.0, 0.96, 6543.491199999997, 1156.9848000000006, 3452.974399999996 - 0.2, 15000.0, 1.0, 6787.299999999996, 1184.400000000001, 3567.199999999994 - 0.2, 20000.0, 0.52, 1285.6999999999898, 467.199999999999, 927.1000000000003 - 0.2, 20000.0, 0.56, 1926.800000000035, 566.699999999991, 1239.3000000000052 - 0.2, 20000.0, 0.6, 2567.9000000000833, 654.5999999999785, 1553.2000000000046 - 0.2, 20000.0, 0.64, 3216.8000000000075, 742.3999999999195, 1870.0999999998303 - 0.2, 20000.0, 0.68, 3861.3999999998023, 826.7999999999581, 2172.9999999997344 - 0.2, 20000.0, 0.72, 4506.499999999746, 909.7999999998779, 2484.4999999998754 - 0.2, 20000.0, 0.76, 5147.599999999816, 1000.9000000000087, 2823.1999999996133 - 0.2, 20000.0, 0.8, 5792.199999999696, 1080.3000000000352, 3167.8999999998628 - 0.2, 20000.0, 0.84, 6160.002857142823, 1122.7285714285606, 3334.8388571428995 - 0.2, 20000.0, 0.88, 6360.991428571477, 1143.2942857142732, 3398.3274285716498 - 0.2, 20000.0, 0.92, 6560.591200000301, 1165.3191999999956, 3470.5456000001022 - 0.2, 20000.0, 0.96, 6813.342400000581, 1195.6984000000002, 3587.935200000208 - 0.2, 20000.0, 1.0, 7062.900000000908, 1224.9000000000108, 3711.200000000335 - 0.2, 25000.0, 0.52, 1486.9999999999914, 746.3999999999986, 1464.6999999999641 - 0.2, 25000.0, 0.56, 2248.099999999939, 822.4999999999774, 1767.2999999999565 - 0.2, 25000.0, 0.6, 2996.9999999998377, 899.7999999999233, 2045.8999999998052 - 0.2, 25000.0, 0.64, 3737.0999999997866, 976.8999999999573, 2346.299999999923 - 0.2, 25000.0, 0.68, 4494.499999999497, 1041.5999999999285, 2606.000000000061 - 0.2, 25000.0, 0.72, 5224.099999999409, 1122.4999999999154, 2905.200000000048 - 0.2, 25000.0, 0.76, 6014.399999999714, 1204.4999999998868, 3240.699999999956 - 0.2, 25000.0, 0.8, 6732.1000000003605, 1274.4999999999059, 3513.8999999999933 - 0.2, 25000.0, 0.84, 7160.3125714286225, 1323.8748571428516, 3702.866857143047 - 0.2, 25000.0, 0.88, 7410.378285714515, 1359.5434285714298, 3836.135428571882 - 0.2, 25000.0, 0.92, 7644.463199999928, 1390.799199999989, 3950.7992000001054 - 0.2, 25000.0, 0.96, 7923.082399999916, 1422.1863999999987, 4066.8344000001857 - 0.2, 25000.0, 1.0, 8205.09999999994, 1453.5000000000089, 4187.10000000029 - 0.2, 30000.0, 0.52, 1629.7999999999997, 805.4999999999953, 1541.4999999999875 - 0.2, 30000.0, 0.56, 2482.4999999998668, 887.7999999999686, 1868.6000000000545 - 0.2, 30000.0, 0.6, 3294.1999999997865, 978.1999999999024, 2156.20000000012 - 0.2, 30000.0, 0.64, 4091.299999999907, 1060.8000000000136, 2498.4999999997767 - 0.2, 30000.0, 0.68, 4923.999999999512, 1149.4000000000262, 2824.599999999873 - 0.2, 30000.0, 0.72, 5740.000000000074, 1224.2999999999845, 3097.5999999997935 - 0.2, 30000.0, 0.76, 6571.299999999316, 1337.199999999932, 3513.400000000056 - 0.2, 30000.0, 0.8, 7410.000000000224, 1409.500000000064, 3815.0000000000664 - 0.2, 30000.0, 0.84, 7880.511428571448, 1459.9091428571674, 4010.298857142938 - 0.2, 30000.0, 0.88, 8128.925714285927, 1496.6205714286325, 4140.287428571644 - 0.2, 30000.0, 0.92, 8372.175199999921, 1531.828000000011, 4264.448799999964 - 0.2, 30000.0, 0.96, 8685.51040000003, 1569.7240000000345, 4405.281600000025 - 0.2, 30000.0, 1.0, 9002.500000000233, 1606.500000000068, 4548.300000000124 - 0.2, 35000.0, 0.52, 1792.4999999999754, 840.5999999999964, 1596.6999999999734 - 0.2, 35000.0, 0.56, 2661.4999999998713, 925.6999999999883, 1938.1999999999327 - 0.2, 35000.0, 0.6, 3533.8999999996345, 1023.4999999999671, 2307.199999999794 - 0.2, 35000.0, 0.64, 4444.49999999972, 1104.9999999998931, 2613.0999999997753 - 0.2, 35000.0, 0.68, 5323.899999999298, 1214.6999999999387, 2988.7999999995077 - 0.2, 35000.0, 0.72, 6199.900000000008, 1294.7999999999581, 3310.09999999977 - 0.2, 35000.0, 0.76, 7116.39999999983, 1407.1000000000063, 3693.0999999998103 - 0.2, 35000.0, 0.8, 7992.400000000436, 1489.7000000000505, 4042.9000000001597 - 0.2, 35000.0, 0.84, 8485.01485714292, 1545.1257142857212, 4276.475428571305 - 0.2, 35000.0, 0.88, 8745.24342857176, 1583.7028571428973, 4435.189714285565 - 0.2, 35000.0, 0.92, 8994.646400000098, 1620.5744000000377, 4577.564799999951 - 0.2, 35000.0, 0.96, 9313.660800000254, 1661.2488000000894, 4727.805599999951 - 0.2, 35000.0, 1.0, 9641.600000000451, 1701.6000000001563, 4875.799999999976 - 0.25, 0.0, 0.52, 788.1000000000004, 345.4, 983.1000000000009 - 0.25, 0.0, 0.56, 1182.2000000000012, 379.69999999999965, 1139.7999999999952 - 0.25, 0.0, 0.6, 1576.1999999999996, 413.69999999999874, 1297.1999999999828 - 0.25, 0.0, 0.64, 1970.200000000027, 447.4999999999964, 1455.2000000000214 - 0.25, 0.0, 0.68, 2364.299999999955, 481.19999999999845, 1614.1000000000063 - 0.25, 0.0, 0.72, 2758.400000000019, 516.5999999999946, 1779.5000000000075 - 0.25, 0.0, 0.76, 3152.3999999999733, 552.9999999999947, 1949.6000000000051 - 0.25, 0.0, 0.8, 3546.4000000000606, 589.4999999999928, 2121.200000000043 - 0.25, 0.0, 0.84, 3768.107428571425, 609.8942857142835, 2217.779428571414 - 0.25, 0.0, 0.88, 3891.9817142857214, 621.1371428571389, 2271.8937142856967 - 0.25, 0.0, 0.92, 4032.6207999999756, 633.7560000000003, 2332.9552000000035 - 0.25, 0.0, 0.96, 4224.345599999962, 651.1320000000009, 2416.662400000004 - 0.25, 0.0, 1.0, 4421.199999999948, 669.5000000000016, 2505.0000000000027 - 0.25, 5000.0, 0.52, 879.5000000000009, 387.6000000000001, 1046.3000000000006 - 0.25, 5000.0, 0.56, 1319.3000000000015, 426.5999999999988, 1219.1000000000035 - 0.25, 5000.0, 0.6, 1758.9999999999973, 465.29999999999666, 1392.6999999999957 - 0.25, 5000.0, 0.64, 2198.6999999999875, 503.6999999999985, 1566.7999999999743 - 0.25, 5000.0, 0.68, 2638.4999999999955, 542.8999999999983, 1744.700000000022 - 0.25, 5000.0, 0.72, 3078.200000000006, 583.6000000000073, 1928.6999999999796 - 0.25, 5000.0, 0.76, 3517.8999999999855, 625.2000000000011, 2117.100000000016 - 0.25, 5000.0, 0.8, 3957.600000000038, 667.0000000000048, 2307.6999999999857 - 0.25, 5000.0, 0.84, 4205.762285714297, 690.5857142857113, 2415.6399999999803 - 0.25, 5000.0, 0.88, 4344.045142857173, 703.7228571428527, 2476.3199999999647 - 0.25, 5000.0, 0.92, 4497.9184000000305, 718.1751999999892, 2543.3775999999866 - 0.25, 5000.0, 0.96, 4705.228800000038, 737.7103999999805, 2633.975199999982 - 0.25, 5000.0, 1.0, 4916.200000000045, 758.0999999999698, 2728.799999999976 - 0.25, 10000.0, 0.52, 1108.8000000000006, 511.0000000000005, 1204.4 - 0.25, 10000.0, 0.56, 1663.2999999999952, 563.9999999999945, 1417.69999999999 - 0.25, 10000.0, 0.6, 2217.699999999972, 616.5999999999831, 1631.4999999999766 - 0.25, 10000.0, 0.64, 2772.0000000000373, 669.1000000000006, 1846.9000000000046 - 0.25, 10000.0, 0.68, 3326.3999999999915, 721.0999999999908, 2063.3000000000034 - 0.25, 10000.0, 0.72, 3880.799999999999, 775.1999999999941, 2286.8999999999905 - 0.25, 10000.0, 0.76, 4435.299999999985, 831.1999999999887, 2517.8999999999523 - 0.25, 10000.0, 0.8, 4989.7000000000335, 887.0999999999974, 2751.099999999979 - 0.25, 10000.0, 0.84, 5306.431999999984, 918.9074285714361, 2884.1657142856957 - 0.25, 10000.0, 0.88, 5480.671999999987, 936.5217142857279, 2958.462857142824 - 0.25, 10000.0, 0.92, 5654.46399999998, 954.6799999999889, 3035.7135999999937 - 0.25, 10000.0, 0.96, 5876.115999999971, 978.4439999999819, 3136.927199999986 - 0.25, 10000.0, 1.0, 6100.199999999964, 1003.1999999999736, 3242.3999999999783 - 0.25, 15000.0, 0.52, 1229.5, 576.2, 1309.8000000000002 - 0.25, 15000.0, 0.56, 1844.2999999999954, 634.6000000000003, 1540.2999999999997 - 0.25, 15000.0, 0.6, 2459.0999999999904, 692.6000000000005, 1771.8999999999999 - 0.25, 15000.0, 0.64, 3073.8999999999983, 750.5000000000001, 2005.4000000000026 - 0.25, 15000.0, 0.68, 3688.500000000011, 808.3999999999975, 2240.5999999999995 - 0.25, 15000.0, 0.72, 4303.399999999998, 868.100000000001, 2482.8000000000084 - 0.25, 15000.0, 0.76, 4918.2000000000035, 930.4000000000007, 2734.199999999999 - 0.25, 15000.0, 0.8, 5532.999999999983, 992.700000000001, 2988.000000000002 - 0.25, 15000.0, 0.84, 5884.817142857137, 1029.1828571428587, 3136.851428571433 - 0.25, 15000.0, 0.88, 6077.948571428567, 1050.2714285714321, 3223.2457142857256 - 0.25, 15000.0, 0.92, 6267.361599999999, 1071.3535999999988, 3310.0656000000045 - 0.25, 15000.0, 0.96, 6506.683199999997, 1097.8871999999983, 3419.411200000009 - 0.25, 15000.0, 1.0, 6748.199999999997, 1125.3999999999971, 3532.6000000000163 - 0.25, 20000.0, 0.52, 1311.599999999995, 508.1999999999997, 1126.4 - 0.25, 20000.0, 0.56, 1966.400000000019, 592.2999999999951, 1409.5000000000043 - 0.25, 20000.0, 0.6, 2621.2000000000453, 670.0999999999875, 1694.700000000008 - 0.25, 20000.0, 0.64, 3280.4000000000137, 747.7999999999568, 1982.8999999999126 - 0.25, 20000.0, 0.68, 3937.1999999998734, 823.5999999999764, 2263.999999999864 - 0.25, 20000.0, 0.72, 4593.999999999889, 899.3999999999414, 2552.9999999999413 - 0.25, 20000.0, 0.76, 5248.799999999903, 981.0000000000036, 2861.5999999998025 - 0.25, 20000.0, 0.8, 5905.599999999857, 1056.7000000000187, 3175.1999999999107 - 0.25, 20000.0, 0.84, 6281.146857142841, 1099.1582857142796, 3341.5377142857255 - 0.25, 20000.0, 0.88, 6486.655428571444, 1121.7611428571342, 3421.0348571429504 - 0.25, 20000.0, 0.92, 6688.205600000124, 1144.7415999999964, 3504.074400000045 - 0.25, 20000.0, 0.96, 6942.147200000243, 1174.6391999999971, 3621.116800000093 - 0.25, 20000.0, 1.0, 7195.100000000388, 1204.300000000001, 3742.70000000015 - 0.25, 25000.0, 0.52, 1483.9999999999957, 682.3999999999992, 1447.599999999981 - 0.25, 25000.0, 0.56, 2235.2999999999656, 758.6999999999877, 1738.9999999999777 - 0.25, 25000.0, 0.6, 2979.7999999999092, 835.2999999999602, 2018.7999999999022 - 0.25, 25000.0, 0.64, 3720.2999999998688, 911.6999999999771, 2311.0999999999553 - 0.25, 25000.0, 0.68, 4469.799999999732, 981.5999999999617, 2582.8000000000343 - 0.25, 25000.0, 0.72, 5204.2999999996855, 1060.3999999999487, 2877.4000000000246 - 0.25, 25000.0, 0.76, 5971.099999999834, 1141.8999999999432, 3199.3999999999746 - 0.25, 25000.0, 0.8, 6699.100000000202, 1218.7999999999495, 3493.9999999999886 - 0.25, 25000.0, 0.84, 7125.681714285716, 1267.8428571428503, 3681.344571428665 - 0.25, 25000.0, 0.88, 7367.738857142927, 1299.3714285714204, 3801.270285714508 - 0.25, 25000.0, 0.92, 7596.861599999954, 1328.1095999999907, 3909.736800000056 - 0.25, 25000.0, 0.96, 7875.247199999942, 1360.0191999999931, 4030.457600000098 - 0.25, 25000.0, 1.0, 8155.6999999999525, 1392.2999999999956, 4154.900000000149 - 0.25, 30000.0, 0.52, 1626.8000000000002, 740.6999999999975, 1523.7999999999938 - 0.25, 30000.0, 0.56, 2460.6999999999307, 824.8999999999833, 1841.5000000000277 - 0.25, 30000.0, 0.6, 3272.799999999889, 913.2999999999483, 2138.900000000062 - 0.25, 30000.0, 0.64, 4076.699999999927, 997.4000000000016, 2467.4999999998777 - 0.25, 30000.0, 0.68, 4899.599999999736, 1084.5000000000118, 2787.79999999993 - 0.25, 30000.0, 0.72, 5714.000000000036, 1165.19999999999, 3083.1999999998925 - 0.25, 30000.0, 0.76, 6535.999999999666, 1268.0999999999651, 3461.7000000000194 - 0.25, 30000.0, 0.8, 7361.900000000124, 1351.0000000000339, 3787.200000000023 - 0.25, 30000.0, 0.84, 7830.358857142836, 1403.5731428571528, 3987.13714285717 - 0.25, 30000.0, 0.88, 8081.92742857148, 1437.444571428599, 4110.328571428653 - 0.25, 30000.0, 0.92, 8324.801599999939, 1469.7128000000018, 4228.009599999973 - 0.25, 30000.0, 0.96, 8631.887199999976, 1506.5296000000126, 4366.579199999999 - 0.25, 30000.0, 1.0, 8940.80000000006, 1543.1000000000267, 4507.600000000046 - 0.25, 35000.0, 0.52, 1779.4999999999866, 775.8999999999982, 1587.4999999999857 - 0.25, 35000.0, 0.56, 2654.699999999926, 865.4999999999941, 1924.899999999966 - 0.25, 35000.0, 0.6, 3530.9999999997904, 960.9999999999835, 2276.9999999999004 - 0.25, 35000.0, 0.64, 4428.199999999852, 1047.999999999943, 2597.4999999998895 - 0.25, 35000.0, 0.68, 5308.899999999618, 1150.0999999999672, 2956.899999999735 - 0.25, 35000.0, 0.72, 6187.700000000031, 1235.399999999979, 3286.999999999892 - 0.25, 35000.0, 0.76, 7088.399999999894, 1343.4000000000012, 3667.0999999999026 - 0.25, 35000.0, 0.8, 7967.200000000238, 1437.400000000027, 4035.800000000097 - 0.25, 35000.0, 0.84, 8466.90228571432, 1495.6045714285688, 4265.577714285634 - 0.25, 35000.0, 0.88, 8735.325142857298, 1531.7302857142959, 4408.3348571427505 - 0.25, 35000.0, 0.92, 8989.968800000042, 1565.8272000000131, 4538.951199999989 - 0.25, 35000.0, 0.96, 9308.969600000113, 1605.278400000036, 4686.350399999988 - 0.25, 35000.0, 1.0, 9631.100000000211, 1644.8000000000668, 4833.500000000004 -0.30000000000000004, 0.0, 0.52, 784.1000000000001, 292.0, 960.5 -0.30000000000000004, 0.0, 0.56, 1176.0999999999988, 326.6000000000004, 1116.1999999999994 -0.30000000000000004, 0.0, 0.6, 1568.1999999999978, 360.90000000000094, 1272.6000000000001 -0.30000000000000004, 0.0, 0.64, 1960.1999999999966, 394.9000000000022, 1429.5000000000084 -0.30000000000000004, 0.0, 0.68, 2352.200000000006, 428.9000000000019, 1587.3999999999999 -0.30000000000000004, 0.0, 0.72, 2744.3000000000065, 464.40000000000106, 1751.4000000000015 -0.30000000000000004, 0.0, 0.76, 3136.300000000012, 501.3000000000025, 1921.40000000001 -0.30000000000000004, 0.0, 0.8, 3528.3999999999974, 537.9999999999978, 2091.8999999999924 -0.30000000000000004, 0.0, 0.84, 3749.2005714285697, 558.5085714285731, 2187.8091428571415 -0.30000000000000004, 0.0, 0.88, 3872.3862857142844, 569.8142857142893, 2241.4405714285717 -0.30000000000000004, 0.0, 0.92, 4011.0344000000005, 582.4928000000006, 2301.8015999999975 -0.30000000000000004, 0.0, 0.96, 4199.4368, 599.9456000000005, 2384.5111999999954 -0.30000000000000004, 0.0, 1.0, 4393.100000000003, 618.4000000000002, 2471.7999999999906 -0.30000000000000004, 5000.0, 0.52, 873.8000000000001, 332.1, 1022.5000000000003 -0.30000000000000004, 5000.0, 0.56, 1310.7000000000012, 371.30000000000007, 1194.1000000000017 -0.30000000000000004, 5000.0, 0.6, 1747.8000000000036, 410.20000000000033, 1366.2000000000057 -0.30000000000000004, 5000.0, 0.64, 2184.700000000002, 449.2000000000004, 1539.9000000000033 -0.30000000000000004, 5000.0, 0.68, 2621.600000000003, 488.70000000000095, 1716.8999999999971 -0.30000000000000004, 5000.0, 0.72, 3058.5000000000236, 529.6000000000008, 1899.3000000000125 -0.30000000000000004, 5000.0, 0.76, 3495.40000000001, 571.6000000000023, 2086.5999999999985 -0.30000000000000004, 5000.0, 0.8, 3932.2999999999943, 613.5999999999992, 2276.0000000000014 -0.30000000000000004, 5000.0, 0.84, 4178.917142857152, 637.3039999999997, 2383.2531428571424 -0.30000000000000004, 5000.0, 0.88, 4316.228571428592, 650.5039999999999, 2443.464571428575 -0.30000000000000004, 5000.0, 0.92, 4468.493600000002, 664.9935999999988, 2509.7656000000006 -0.30000000000000004, 5000.0, 0.96, 4673.4072, 684.563199999998, 2599.235199999998 -0.30000000000000004, 5000.0, 1.0, 4882.099999999998, 704.999999999997, 2692.899999999991 -0.30000000000000004, 10000.0, 0.52, 1100.7999999999995, 451.79999999999995, 1179.0999999999997 -0.30000000000000004, 10000.0, 0.56, 1651.2000000000003, 505.3000000000004, 1391.000000000001 -0.30000000000000004, 10000.0, 0.6, 2201.7000000000035, 558.3000000000019, 1603.4000000000003 -0.30000000000000004, 10000.0, 0.64, 2752.0000000000086, 611.2000000000019, 1817.300000000006 -0.30000000000000004, 10000.0, 0.68, 3302.40000000003, 663.7000000000037, 2032.5000000000036 -0.30000000000000004, 10000.0, 0.72, 3852.9, 718.1000000000035, 2254.4000000000115 -0.30000000000000004, 10000.0, 0.76, 4403.200000000018, 774.499999999999, 2483.900000000001 -0.30000000000000004, 10000.0, 0.8, 4953.7000000000035, 831.0000000000001, 2716.0000000000036 -0.30000000000000004, 10000.0, 0.84, 5268.006857142857, 863.0605714285714, 2848.3714285714277 -0.30000000000000004, 10000.0, 0.88, 5440.9754285714325, 880.7262857142866, 2922.1857142857184 -0.30000000000000004, 10000.0, 0.92, 5614.526400000004, 898.9616000000004, 2998.899199999995 -0.30000000000000004, 10000.0, 0.96, 5836.448800000003, 922.8912000000001, 3099.3983999999896 -0.30000000000000004, 10000.0, 1.0, 6060.400000000004, 947.8, 3203.9999999999836 -0.30000000000000004, 15000.0, 0.52, 1221.3000000000004, 515.0999999999998, 1283.2 -0.30000000000000004, 15000.0, 0.56, 1832.0000000000014, 574.0000000000005, 1512.4999999999993 -0.30000000000000004, 15000.0, 0.6, 2442.700000000006, 632.5000000000022, 1742.6999999999987 -0.30000000000000004, 15000.0, 0.64, 3053.3000000000025, 690.9999999999985, 1975.20000000001 -0.30000000000000004, 15000.0, 0.68, 3664.000000000012, 749.4000000000009, 2209.200000000005 -0.30000000000000004, 15000.0, 0.72, 4274.700000000011, 809.5000000000056, 2450.100000000021 -0.30000000000000004, 15000.0, 0.76, 4885.300000000011, 872.4000000000012, 2700.200000000017 -0.30000000000000004, 15000.0, 0.8, 5495.999999999997, 935.2999999999981, 2953.000000000012 -0.30000000000000004, 15000.0, 0.84, 5845.684000000015, 971.9542857142842, 3100.4765714285804 -0.30000000000000004, 15000.0, 0.88, 6037.664000000037, 992.9571428571413, 3185.3222857143046 -0.30000000000000004, 15000.0, 0.92, 6225.378400000012, 1013.9535999999991, 3270.7696000000105 -0.30000000000000004, 15000.0, 0.96, 6462.01280000002, 1040.487199999998, 3378.971200000014 -0.30000000000000004, 15000.0, 1.0, 6700.500000000035, 1067.9999999999964, 3491.000000000017 -0.30000000000000004, 20000.0, 0.52, 1324.3999999999976, 515.3, 1246.3 -0.30000000000000004, 20000.0, 0.56, 1986.100000000008, 589.4999999999977, 1509.7000000000028 -0.30000000000000004, 20000.0, 0.6, 2647.8000000000193, 660.799999999994, 1775.3000000000065 -0.30000000000000004, 20000.0, 0.64, 3311.6000000000117, 731.9999999999808, 2043.6999999999628 -0.30000000000000004, 20000.0, 0.68, 3974.2999999999283, 802.2999999999888, 2309.699999999942 -0.30000000000000004, 20000.0, 0.72, 4636.799999999964, 873.4999999999774, 2582.99999999998 -0.30000000000000004, 20000.0, 0.76, 5298.4999999999545, 949.0999999999999, 2871.0999999999153 -0.30000000000000004, 20000.0, 0.8, 5961.199999999953, 1022.4000000000092, 3163.3999999999564 -0.30000000000000004, 20000.0, 0.84, 6340.667999999997, 1064.8891428571403, 3328.523999999998 -0.30000000000000004, 20000.0, 0.88, 6548.4880000000085, 1088.8405714285675, 3417.7840000000247 -0.30000000000000004, 20000.0, 0.92, 6750.528800000034, 1112.5007999999993, 3507.2840000000133 -0.30000000000000004, 20000.0, 0.96, 7004.089600000071, 1142.1695999999993, 3623.5440000000294 -0.30000000000000004, 20000.0, 1.0, 7257.900000000114, 1172.2000000000007, 3743.5000000000496 -0.30000000000000004, 25000.0, 0.52, 1477.399999999998, 620.4999999999995, 1426.399999999992 -0.30000000000000004, 25000.0, 0.56, 2220.199999999984, 696.9999999999942, 1709.599999999991 -0.30000000000000004, 25000.0, 0.6, 2959.699999999957, 773.299999999983, 1988.8999999999592 -0.30000000000000004, 25000.0, 0.64, 3697.999999999927, 849.3999999999895, 2274.8999999999746 -0.30000000000000004, 25000.0, 0.68, 4440.099999999881, 922.6999999999824, 2553.100000000012 -0.30000000000000004, 25000.0, 0.72, 5175.39999999986, 1000.2999999999731, 2843.800000000009 -0.30000000000000004, 25000.0, 0.76, 5924.999999999919, 1081.699999999976, 3155.7999999999856 -0.30000000000000004, 25000.0, 0.8, 6657.300000000092, 1162.6999999999775, 3461.4999999999923 -0.30000000000000004, 25000.0, 0.84, 7081.568571428556, 1211.669142857137, 3647.162285714319 -0.30000000000000004, 25000.0, 0.88, 7317.754285714288, 1240.9205714285629, 3758.965142857226 -0.30000000000000004, 25000.0, 0.92, 7542.688799999979, 1268.2999999999943, 3863.5488000000246 -0.30000000000000004, 25000.0, 0.96, 7819.437599999977, 1300.5879999999934, 3986.629600000043 -0.30000000000000004, 25000.0, 1.0, 8097.299999999982, 1333.4999999999923, 4113.000000000064 -0.30000000000000004, 30000.0, 0.52, 1619.4000000000003, 677.499999999999, 1501.1999999999973 -0.30000000000000004, 30000.0, 0.56, 2438.4999999999704, 763.0999999999925, 1811.7000000000112 -0.30000000000000004, 30000.0, 0.6, 3247.8999999999514, 850.3999999999766, 2114.2000000000253 -0.30000000000000004, 30000.0, 0.64, 4053.399999999951, 935.5999999999959, 2432.5999999999453 -0.30000000000000004, 30000.0, 0.68, 4867.299999999877, 1022.0000000000036, 2748.1999999999675 -0.30000000000000004, 30000.0, 0.72, 5677.800000000008, 1106.1999999999941, 3055.8999999999546 -0.30000000000000004, 30000.0, 0.76, 6491.199999999871, 1203.099999999985, 3409.700000000004 -0.30000000000000004, 30000.0, 0.8, 7306.300000000056, 1293.1000000000156, 3749.2000000000016 -0.30000000000000004, 30000.0, 0.84, 7771.947999999975, 1347.2571428571462, 3951.492571428575 -0.30000000000000004, 30000.0, 0.88, 8024.6479999999865, 1379.4285714285809, 4070.0782857143013 -0.30000000000000004, 30000.0, 0.92, 8266.237599999959, 1409.9007999999988, 4183.201599999981 -0.30000000000000004, 30000.0, 0.96, 8567.887199999966, 1446.1016000000016, 4319.619199999991 -0.30000000000000004, 30000.0, 1.0, 8870.099999999984, 1482.6000000000056, 4458.600000000007 -0.30000000000000004, 35000.0, 0.52, 1766.8999999999937, 714.4999999999991, 1571.4999999999936 -0.30000000000000004, 35000.0, 0.56, 2643.899999999963, 807.1999999999972, 1905.1999999999862 -0.30000000000000004, 35000.0, 0.6, 3520.7999999998983, 901.7999999999921, 2245.899999999961 -0.30000000000000004, 35000.0, 0.64, 4407.399999999934, 992.6999999999754, 2574.7999999999565 -0.30000000000000004, 35000.0, 0.68, 5286.799999999824, 1090.299999999984, 2922.8999999998778 -0.30000000000000004, 35000.0, 0.72, 6165.300000000021, 1179.6999999999916, 3258.4999999999613 -0.30000000000000004, 35000.0, 0.76, 7053.699999999942, 1285.0999999999976, 3634.2999999999606 -0.30000000000000004, 35000.0, 0.8, 7932.200000000108, 1386.8000000000127, 4014.400000000049 -0.30000000000000004, 35000.0, 0.84, 8435.167428571436, 1447.028571428567, 4241.35657142853 -0.30000000000000004, 35000.0, 0.88, 8708.021714285764, 1481.7342857142835, 4373.662285714225 -0.30000000000000004, 35000.0, 0.92, 8965.045600000014, 1514.193600000001, 4496.409600000004 -0.30000000000000004, 35000.0, 0.96, 9282.795200000042, 1553.0272000000082, 4641.491200000006 -0.30000000000000004, 35000.0, 1.0, 9600.100000000073, 1592.200000000018, 4787.600000000014 -0.35000000000000003, 0.0, 0.52, 779.4999999999995, 239.9999999999999, 934.2999999999998 -0.35000000000000003, 0.0, 0.56, 1169.1999999999994, 274.8000000000004, 1088.9000000000017 -0.35000000000000003, 0.0, 0.6, 1558.9999999999955, 309.4000000000007, 1244.0000000000045 -0.35000000000000003, 0.0, 0.64, 1948.699999999988, 343.7999999999993, 1399.8000000000038 -0.35000000000000003, 0.0, 0.68, 2338.5000000000023, 378.0000000000026, 1556.5000000000073 -0.35000000000000003, 0.0, 0.72, 2728.200000000007, 414.1000000000014, 1720.300000000005 -0.35000000000000003, 0.0, 0.76, 3117.9000000000324, 451.20000000000147, 1888.800000000004 -0.35000000000000003, 0.0, 0.8, 3507.6999999999994, 488.19999999999754, 2057.9000000000037 -0.35000000000000003, 0.0, 0.84, 3727.3782857142837, 508.95314285714204, 2153.3948571428546 -0.35000000000000003, 0.0, 0.88, 3849.8411428571385, 520.4445714285696, 2207.043428571425 -0.35000000000000003, 0.0, 0.92, 3986.7007999999896, 533.2288, 2266.931999999988 -0.35000000000000003, 0.0, 0.96, 4172.157599999983, 550.7216000000002, 2348.491999999979 -0.35000000000000003, 0.0, 1.0, 4362.9999999999745, 569.2, 2434.4999999999677 -0.35000000000000003, 5000.0, 0.52, 867.8999999999999, 277.9999999999999, 995.2999999999998 -0.35000000000000003, 5000.0, 0.56, 1301.8000000000047, 317.6000000000011, 1165.4999999999982 -0.35000000000000003, 5000.0, 0.6, 1735.700000000011, 356.8000000000029, 1336.1999999999985 -0.35000000000000003, 5000.0, 0.64, 2169.6000000000145, 396.5000000000004, 1509.8000000000006 -0.35000000000000003, 5000.0, 0.68, 2603.5999999999854, 436.300000000002, 1685.2999999999913 -0.35000000000000003, 5000.0, 0.72, 3037.5000000000073, 477.3999999999997, 1865.9000000000108 -0.35000000000000003, 5000.0, 0.76, 3471.5000000000173, 519.7999999999987, 2052.1999999999925 -0.35000000000000003, 5000.0, 0.8, 3905.4000000000137, 562.1999999999967, 2240.1000000000013 -0.35000000000000003, 5000.0, 0.84, 4150.467428571426, 586.1199999999977, 2346.621142857133 -0.35000000000000003, 5000.0, 0.88, 4286.881714285712, 599.3999999999958, 2406.4525714285533 -0.35000000000000003, 5000.0, 0.92, 4437.5039999999835, 613.8703999999998, 2472.034399999989 -0.35000000000000003, 5000.0, 0.96, 4639.831999999975, 633.3807999999995, 2560.304799999984 -0.35000000000000003, 5000.0, 1.0, 4845.99999999996, 653.799999999999, 2652.6999999999775 -0.35000000000000003, 10000.0, 0.52, 1092.2999999999995, 394.39999999999975, 1150.2999999999995 -0.35000000000000003, 10000.0, 0.56, 1638.4000000000037, 448.50000000000074, 1360.5000000000018 -0.35000000000000003, 10000.0, 0.6, 2184.500000000013, 502.00000000000455, 1571.7000000000041 -0.35000000000000003, 10000.0, 0.64, 2730.699999999993, 555.3000000000033, 1783.9000000000074 -0.35000000000000003, 10000.0, 0.68, 3276.8000000000075, 608.3999999999988, 1997.699999999999 -0.35000000000000003, 10000.0, 0.72, 3822.900000000017, 663.3000000000029, 2217.9999999999955 -0.35000000000000003, 10000.0, 0.76, 4369.100000000019, 720.2000000000031, 2446.00000000001 -0.35000000000000003, 10000.0, 0.8, 4915.2, 777.3000000000013, 2676.600000000004 -0.35000000000000003, 10000.0, 0.84, 5226.857142857138, 809.7074285714272, 2808.1342857142854 -0.35000000000000003, 10000.0, 0.88, 5398.48857142856, 827.5617142857124, 2881.477142857144 -0.35000000000000003, 10000.0, 0.92, 5571.716799999977, 845.9727999999993, 2957.6743999999926 -0.35000000000000003, 10000.0, 0.96, 5793.753599999962, 870.1095999999983, 3057.4287999999897 -0.35000000000000003, 10000.0, 1.0, 6017.399999999947, 895.1999999999973, 3161.0999999999863 -0.35000000000000003, 15000.0, 0.52, 1212.5999999999997, 455.7999999999999, 1252.8 -0.35000000000000003, 15000.0, 0.56, 1818.7000000000014, 515.4000000000009, 1480.8000000000018 -0.35000000000000003, 15000.0, 0.6, 2425.0000000000014, 574.5000000000028, 1709.8000000000043 -0.35000000000000003, 15000.0, 0.64, 3031.1999999999853, 633.799999999999, 1941.0000000000111 -0.35000000000000003, 15000.0, 0.68, 3637.500000000005, 692.7999999999969, 2173.599999999999 -0.35000000000000003, 15000.0, 0.72, 4243.600000000032, 753.6000000000024, 2413.1999999999857 -0.35000000000000003, 15000.0, 0.76, 4849.89999999999, 817.1000000000023, 2662.000000000006 -0.35000000000000003, 15000.0, 0.8, 5456.199999999981, 880.6999999999936, 2913.4999999999986 -0.35000000000000003, 15000.0, 0.84, 5803.449142857134, 917.5462857142838, 3059.568571428571 -0.35000000000000003, 15000.0, 0.88, 5994.000571428554, 938.449142857139, 3142.9542857142847 -0.35000000000000003, 15000.0, 0.92, 6179.819199999972, 959.3871999999965, 3226.999199999991 -0.35000000000000003, 15000.0, 0.96, 6413.646399999961, 986.0023999999931, 3333.8583999999814 -0.35000000000000003, 15000.0, 1.0, 6648.999999999941, 1013.5999999999881, 3444.4999999999704 -0.35000000000000003, 20000.0, 0.52, 1326.3999999999994, 495.70000000000005, 1302.2 -0.35000000000000003, 20000.0, 0.56, 1989.400000000002, 564.3999999999994, 1553.300000000002 -0.35000000000000003, 20000.0, 0.6, 2652.400000000004, 632.0999999999984, 1806.5000000000034 -0.35000000000000003, 20000.0, 0.64, 3316.1000000000045, 699.6999999999941, 2062.19999999999 -0.35000000000000003, 20000.0, 0.68, 3979.4999999999704, 766.9999999999966, 2318.3999999999833 -0.35000000000000003, 20000.0, 0.72, 4642.699999999993, 835.6999999999936, 2581.399999999997 -0.35000000000000003, 20000.0, 0.76, 5305.69999999998, 908.0999999999988, 2856.599999999974 -0.35000000000000003, 20000.0, 0.8, 5969.0999999999985, 980.1000000000039, 3135.3999999999883 -0.35000000000000003, 20000.0, 0.84, 6349.343428571432, 1022.6331428571428, 3298.8062857142804 -0.35000000000000003, 20000.0, 0.88, 6557.657714285726, 1047.3645714285706, 3392.8291428571415 -0.35000000000000003, 20000.0, 0.92, 6758.941600000002, 1071.4592000000007, 3485.284000000001 -0.35000000000000003, 20000.0, 0.96, 7010.751200000009, 1101.0824000000014, 3600.3760000000034 -0.35000000000000003, 20000.0, 1.0, 7263.300000000014, 1131.4000000000024, 3718.7000000000066 -0.35000000000000003, 25000.0, 0.52, 1467.5999999999995, 560.9, 1401.6999999999975 -0.35000000000000003, 25000.0, 0.56, 2202.699999999995, 637.5999999999984, 1678.8999999999971 -0.35000000000000003, 25000.0, 0.6, 2936.499999999985, 713.8999999999953, 1956.2999999999884 -0.35000000000000003, 25000.0, 0.64, 3670.399999999968, 789.9999999999972, 2237.299999999987 -0.35000000000000003, 25000.0, 0.68, 4405.299999999963, 865.2999999999945, 2517.6 -0.35000000000000003, 25000.0, 0.72, 5137.999999999957, 942.3999999999902, 2804.800000000001 -0.35000000000000003, 25000.0, 0.76, 5875.09999999997, 1023.9999999999931, 3109.499999999996 -0.35000000000000003, 25000.0, 0.8, 6606.800000000024, 1106.9999999999932, 3418.3999999999974 -0.35000000000000003, 25000.0, 0.84, 7028.10685714285, 1156.08914285714, 3602.2451428571476 -0.35000000000000003, 25000.0, 0.88, 7260.035428571417, 1184.4605714285656, 3709.7965714285865 -0.35000000000000003, 25000.0, 0.92, 7481.339999999995, 1211.3503999999978, 3812.167200000008 -0.35000000000000003, 25000.0, 0.96, 7755.2959999999985, 1243.908799999997, 3935.766400000014 -0.35000000000000003, 25000.0, 1.0, 8029.700000000007, 1277.1999999999953, 4062.3000000000193 -0.35000000000000003, 30000.0, 0.52, 1608.1000000000001, 616.1999999999997, 1474.3999999999992 -0.35000000000000003, 30000.0, 0.56, 2415.29999999999, 702.7999999999972, 1779.300000000003 -0.35000000000000003, 30000.0, 0.6, 3219.399999999983, 789.699999999992, 2083.100000000007 -0.35000000000000003, 30000.0, 0.64, 4022.1999999999757, 875.6999999999963, 2393.9999999999845 -0.35000000000000003, 30000.0, 0.68, 4827.499999999959, 962.0000000000003, 2705.5999999999885 -0.35000000000000003, 30000.0, 0.72, 5632.099999999996, 1047.9999999999973, 3017.7999999999856 -0.35000000000000003, 30000.0, 0.76, 6437.199999999969, 1141.9999999999939, 3356.5999999999995 -0.35000000000000003, 30000.0, 0.8, 7242.800000000016, 1236.3000000000054, 3702.0999999999963 -0.35000000000000003, 30000.0, 0.84, 7704.906285714271, 1291.5714285714287, 3904.8491428571397 -0.35000000000000003, 30000.0, 0.88, 7957.08914285712, 1322.9457142857161, 4020.520571428566 -0.35000000000000003, 30000.0, 0.92, 8196.606399999982, 1352.524799999998, 4130.582399999993 -0.35000000000000003, 30000.0, 0.96, 8493.340799999982, 1388.469599999998, 4264.912799999993 -0.35000000000000003, 30000.0, 1.0, 8789.799999999981, 1424.9999999999984, 4401.7999999999965 -0.35000000000000003, 35000.0, 0.52, 1754.099999999998, 656.2999999999998, 1549.699999999998 -0.35000000000000003, 35000.0, 0.56, 2629.199999999987, 751.0999999999989, 1879.9999999999961 -0.35000000000000003, 35000.0, 0.6, 3503.7999999999643, 845.8999999999972, 2213.49999999999 -0.35000000000000003, 35000.0, 0.64, 4381.69999999998, 939.4999999999934, 2545.8999999999896 -0.35000000000000003, 35000.0, 0.68, 5257.499999999943, 1035.0999999999945, 2886.599999999958 -0.35000000000000003, 35000.0, 0.72, 6133.0, 1127.6999999999969, 3224.8999999999924 -0.35000000000000003, 35000.0, 0.76, 7011.599999999979, 1231.899999999997, 3595.4999999999905 -0.35000000000000003, 35000.0, 0.8, 7887.100000000033, 1338.4000000000049, 3980.8000000000175 -0.35000000000000003, 35000.0, 0.84, 8390.206857142855, 1400.07314285714, 4205.578857142842 -0.35000000000000003, 35000.0, 0.88, 8664.49542857143, 1434.184571428568, 4331.747428571408 -0.35000000000000003, 35000.0, 0.92, 8921.612800000004, 1465.9087999999977, 4449.679200000006 -0.35000000000000003, 35000.0, 0.96, 9237.061600000006, 1504.6015999999981, 4592.822400000009 -0.35000000000000003, 35000.0, 1.0, 9550.200000000013, 1543.7999999999988, 4737.700000000011 - 0.4, 0.0, 0.52, 773.8999999999988, 189.10000000000008, 904.8000000000008 - 0.4, 0.0, 0.56, 1160.6999999999969, 224.30000000000058, 1058.000000000005 - 0.4, 0.0, 0.6, 1547.699999999982, 259.2000000000002, 1211.8000000000125 - 0.4, 0.0, 0.64, 1934.599999999947, 293.8999999999996, 1366.1000000000142 - 0.4, 0.0, 0.68, 2321.600000000001, 328.400000000007, 1521.6000000000197 - 0.4, 0.0, 0.72, 2708.5000000000246, 365.20000000000385, 1684.8000000000018 - 0.4, 0.0, 0.76, 3095.500000000084, 402.7000000000048, 1851.7000000000137 - 0.4, 0.0, 0.8, 3482.300000000003, 439.89999999999156, 2019.3000000000188 - 0.4, 0.0, 0.84, 3700.5217142857246, 460.9017142857136, 2114.331428571431 - 0.4, 0.0, 0.88, 3822.178857142878, 472.6388571428555, 2167.96571428572 - 0.4, 0.0, 0.92, 3957.2919999999767, 485.5728000000009, 2227.315199999967 - 0.4, 0.0, 0.96, 4139.86799999996, 503.10960000000176, 2307.610399999941 - 0.4, 0.0, 1.0, 4327.899999999938, 521.6000000000031, 2392.1999999999075 - 0.4, 5000.0, 0.52, 860.8999999999996, 225.19999999999987, 964.8999999999996 - 0.4, 5000.0, 0.56, 1291.400000000011, 265.1000000000026, 1133.3999999999946 - 0.4, 5000.0, 0.6, 1721.8000000000252, 304.80000000000706, 1302.8999999999926 - 0.4, 5000.0, 0.64, 2152.3000000000407, 345.3000000000017, 1475.9999999999952 - 0.4, 5000.0, 0.68, 2582.699999999959, 385.40000000000697, 1649.5999999999601 - 0.4, 5000.0, 0.72, 3013.2000000000353, 426.799999999999, 1828.8000000000156 - 0.4, 5000.0, 0.76, 3443.6000000000554, 469.59999999999604, 2013.499999999989 - 0.4, 5000.0, 0.8, 3874.1000000000536, 512.3999999999902, 2199.700000000006 - 0.4, 5000.0, 0.84, 4117.335428571429, 536.5279999999932, 2305.252571428543 - 0.4, 5000.0, 0.88, 4252.589714285717, 549.8879999999883, 2364.4582857142327 - 0.4, 5000.0, 0.92, 4401.111199999951, 564.3936000000014, 2429.113599999973 - 0.4, 5000.0, 0.96, 4600.218399999918, 583.9392000000015, 2516.023199999963 - 0.4, 5000.0, 1.0, 4803.299999999868, 604.4000000000012, 2606.9999999999545 - 0.4, 10000.0, 0.52, 1082.2999999999977, 338.39999999999964, 1117.8999999999992 - 0.4, 10000.0, 0.56, 1623.4000000000092, 393.0000000000019, 1326.4000000000076 - 0.4, 10000.0, 0.6, 2164.600000000028, 447.3000000000116, 1535.8000000000147 - 0.4, 10000.0, 0.64, 2705.6999999999575, 501.1000000000083, 1746.4000000000153 - 0.4, 10000.0, 0.68, 3247.0000000000114, 554.7999999999929, 1958.400000000004 - 0.4, 10000.0, 0.72, 3788.2000000000103, 610.1000000000084, 2176.69999999999 - 0.4, 10000.0, 0.76, 4329.3, 667.8000000000079, 2403.0000000000273 - 0.4, 10000.0, 0.8, 4870.400000000013, 725.500000000003, 2631.700000000023 - 0.4, 10000.0, 0.84, 5179.052571428571, 758.2502857142815, 2762.217714285721 - 0.4, 10000.0, 0.88, 5349.158285714294, 776.2931428571355, 2835.054857142874 - 0.4, 10000.0, 0.92, 5521.9647999999215, 794.9119999999962, 2910.759199999978 - 0.4, 10000.0, 0.96, 5744.025599999883, 819.3079999999936, 3009.786399999969 - 0.4, 10000.0, 1.0, 5967.199999999839, 844.5999999999902, 3112.499999999959 - 0.4, 15000.0, 0.52, 1202.1999999999996, 397.99999999999994, 1218.9 - 0.4, 15000.0, 0.56, 1803.3000000000034, 458.30000000000115, 1445.100000000005 - 0.4, 15000.0, 0.6, 2404.400000000004, 518.3000000000048, 1672.9000000000135 - 0.4, 15000.0, 0.64, 3005.4999999999573, 578.0999999999952, 1902.3000000000384 - 0.4, 15000.0, 0.68, 3606.5999999999813, 637.8999999999854, 2133.5999999999835 - 0.4, 15000.0, 0.72, 4207.50000000006, 699.4000000000054, 2371.299999999957 - 0.4, 15000.0, 0.76, 4808.599999999972, 763.7000000000013, 2618.5000000000164 - 0.4, 15000.0, 0.8, 5409.699999999943, 828.1999999999821, 2868.8000000000056 - 0.4, 15000.0, 0.84, 5754.105714285685, 865.2954285714229, 3013.3177142857153 - 0.4, 15000.0, 0.88, 5943.022857142802, 886.0697142857038, 3094.954857142859 - 0.4, 15000.0, 0.92, 6126.624799999937, 906.9175999999906, 3177.29599999997 - 0.4, 15000.0, 0.96, 6357.1495999999015, 933.6111999999812, 3282.559999999943 - 0.4, 15000.0, 1.0, 6588.899999999859, 961.2999999999682, 3391.5999999999094 - 0.4, 20000.0, 0.52, 1319.9, 456.6, 1309.5 - 0.4, 20000.0, 0.56, 1979.7999999999997, 523.1000000000001, 1553.7000000000003 - 0.4, 20000.0, 0.6, 2639.699999999999, 589.4000000000007, 1799.8000000000009 - 0.4, 20000.0, 0.64, 3299.5999999999985, 655.5999999999995, 2048.0999999999995 - 0.4, 20000.0, 0.68, 3959.599999999997, 721.8000000000011, 2298.3999999999983 - 0.4, 20000.0, 0.72, 4619.5, 789.5999999999985, 2555.1000000000035 - 0.4, 20000.0, 0.76, 5279.4, 860.9000000000002, 2822.999999999998 - 0.4, 20000.0, 0.8, 5939.400000000004, 932.5000000000005, 3094.099999999998 - 0.4, 20000.0, 0.84, 6317.950285714288, 975.1022857142859, 3255.3931428571423 - 0.4, 20000.0, 0.88, 6525.333142857148, 1000.1651428571432, 3350.4245714285703 - 0.4, 20000.0, 0.92, 6724.824800000002, 1024.4792000000004, 3443.183999999999 - 0.4, 20000.0, 0.96, 6973.713600000004, 1054.1704000000007, 3556.771999999998 - 0.4, 20000.0, 1.0, 7223.300000000006, 1084.7000000000007, 3673.3999999999974 - 0.4, 25000.0, 0.52, 1455.0, 503.8, 1374.1 - 0.4, 25000.0, 0.56, 2182.6999999999994, 580.7, 1646.7000000000007 - 0.4, 25000.0, 0.6, 2909.999999999998, 657.2000000000003, 1921.1000000000015 - 0.4, 25000.0, 0.64, 3637.699999999999, 733.5000000000002, 2197.899999999997 - 0.4, 25000.0, 0.68, 4365.299999999996, 809.8000000000004, 2477.000000000002 - 0.4, 25000.0, 0.72, 5092.700000000005, 886.8999999999991, 2760.8000000000006 - 0.4, 25000.0, 0.76, 5820.399999999995, 968.8999999999997, 3060.100000000005 - 0.4, 25000.0, 0.8, 6547.699999999996, 1052.5000000000002, 3366.7000000000003 - 0.4, 25000.0, 0.84, 6965.430285714287, 1101.838285714286, 3548.5182857142845 - 0.4, 25000.0, 0.88, 7194.193142857149, 1130.2611428571436, 3654.34114285714 - 0.4, 25000.0, 0.92, 7412.210400000001, 1157.2407999999998, 3755.5240000000003 - 0.4, 25000.0, 0.96, 7682.464800000002, 1189.9975999999997, 3878.284 - 0.4, 25000.0, 1.0, 7952.700000000003, 1223.4999999999995, 4003.6999999999994 - 0.4, 30000.0, 0.52, 1593.4, 557.1, 1444.1 - 0.4, 30000.0, 0.56, 2390.5, 644.3999999999997, 1744.400000000001 - 0.4, 30000.0, 0.6, 3187.1999999999994, 731.3999999999991, 2046.6000000000026 - 0.4, 30000.0, 0.64, 3983.899999999997, 818.0000000000001, 2351.8999999999983 - 0.4, 30000.0, 0.68, 4780.600000000001, 904.6000000000005, 2659.800000000002 - 0.4, 30000.0, 0.72, 5577.5999999999985, 991.3000000000011, 2971.0000000000005 - 0.4, 30000.0, 0.76, 6374.300000000005, 1084.5999999999985, 3301.6000000000004 - 0.4, 30000.0, 0.8, 7170.999999999996, 1181.1000000000004, 3647.0 - 0.4, 30000.0, 0.84, 7628.861142857143, 1237.1262857142856, 3848.690857142856 - 0.4, 30000.0, 0.88, 7879.252571428573, 1268.369142857143, 3962.639428571426 - 0.4, 30000.0, 0.92, 8116.031200000005, 1297.7175999999995, 4070.7096000000006 - 0.4, 30000.0, 0.96, 8408.078400000006, 1333.6631999999995, 4202.971200000001 - 0.4, 30000.0, 1.0, 8699.300000000008, 1370.2999999999988, 4337.700000000001 - 0.4, 35000.0, 0.52, 1740.5, 601.2, 1523.1 - 0.4, 35000.0, 0.56, 2610.699999999999, 697.5000000000002, 1850.1999999999998 - 0.4, 35000.0, 0.6, 3480.4999999999973, 793.3000000000004, 2179.4 - 0.4, 35000.0, 0.64, 4350.700000000001, 888.7999999999992, 2511.7000000000007 - 0.4, 35000.0, 0.68, 5220.899999999998, 984.2999999999994, 2847.799999999995 - 0.4, 35000.0, 0.72, 6091.099999999998, 1079.3999999999994, 3186.500000000004 - 0.4, 35000.0, 0.76, 6961.40000000001, 1183.500000000001, 3551.5000000000005 - 0.4, 35000.0, 0.8, 7831.599999999993, 1292.7000000000007, 3937.100000000001 - 0.4, 35000.0, 0.84, 8332.417142857144, 1355.4137142857144, 4160.011428571429 - 0.4, 35000.0, 0.88, 8605.908571428572, 1389.5508571428572, 4283.165714285715 - 0.4, 35000.0, 0.92, 8861.406399999994, 1421.2079999999994, 4398.4992 - 0.4, 35000.0, 0.96, 9173.692799999993, 1460.107999999999, 4539.938399999998 - 0.4, 35000.0, 1.0, 9482.999999999989, 1499.599999999998, 4683.399999999998 - 0.45, 0.0, 0.52, 766.7000000000006, 139.39999999999992, 872.3999999999997 - 0.45, 0.0, 0.56, 1150.100000000001, 174.8999999999994, 1023.900000000005 - 0.45, 0.0, 0.6, 1533.6000000000042, 210.0999999999986, 1175.9000000000117 - 0.45, 0.0, 0.64, 1916.9000000000524, 245.00000000000563, 1328.4000000000326 - 0.45, 0.0, 0.68, 2300.300000000006, 280.50000000000574, 1483.8000000000052 - 0.45, 0.0, 0.72, 2683.6000000000604, 317.400000000008, 1644.9000000000265 - 0.45, 0.0, 0.76, 3067.000000000039, 355.0000000000085, 1809.7000000000405 - 0.45, 0.0, 0.8, 3450.399999999949, 392.9000000000062, 1976.4999999999807 - 0.45, 0.0, 0.84, 3666.8017142857066, 414.2360000000001, 2070.9297142857076 - 0.45, 0.0, 0.88, 3787.2988571428464, 426.05600000000055, 2123.946857142843 - 0.45, 0.0, 0.92, 3920.2888000000107, 438.9608, 2182.2727999999975 - 0.45, 0.0, 0.96, 4099.56160000002, 456.4455999999999, 2261.101599999999 - 0.45, 0.0, 1.0, 4284.300000000036, 474.89999999999986, 2344.1000000000026 - 0.45, 5000.0, 0.52, 852.2999999999992, 173.69999999999973, 931.3000000000001 - 0.45, 5000.0, 0.56, 1278.3999999999967, 213.80000000000052, 1097.8000000000095 - 0.45, 5000.0, 0.6, 1704.3999999999824, 254.5000000000039, 1267.0000000000318 - 0.45, 5000.0, 0.64, 2130.6000000000295, 295.20000000000374, 1437.9999999999986 - 0.45, 5000.0, 0.68, 2556.700000000042, 335.7000000000041, 1609.8000000000136 - 0.45, 5000.0, 0.72, 2982.8000000000447, 377.40000000000566, 1786.8000000000086 - 0.45, 5000.0, 0.76, 3409.0000000000414, 420.5000000000035, 1969.5000000000175 - 0.45, 5000.0, 0.8, 3835.1000000000436, 463.60000000000286, 2153.8000000000106 - 0.45, 5000.0, 0.84, 4075.9971428571416, 487.91142857142825, 2258.285714285695 - 0.45, 5000.0, 0.88, 4209.868571428575, 501.3657142857142, 2316.8028571428276 - 0.45, 5000.0, 0.92, 4356.031199999997, 515.8983999999978, 2380.3855999999837 - 0.45, 5000.0, 0.96, 4551.522400000001, 535.436799999997, 2465.6911999999775 - 0.45, 5000.0, 1.0, 4751.1000000000095, 555.8999999999959, 2554.999999999969 - 0.45, 10000.0, 0.52, 1070.3999999999994, 283.5000000000001, 1082.0999999999983 - 0.45, 10000.0, 0.56, 1605.4999999999905, 338.80000000000246, 1288.5000000000105 - 0.45, 10000.0, 0.6, 2140.6999999999834, 393.6000000000079, 1495.700000000027 - 0.45, 10000.0, 0.64, 2675.90000000002, 448.1000000000125, 1704.2000000000453 - 0.45, 10000.0, 0.68, 3211.0, 502.6000000000112, 1914.6000000000029 - 0.45, 10000.0, 0.72, 3746.2000000000417, 558.2000000000107, 2130.1000000000467 - 0.45, 10000.0, 0.76, 4281.300000000142, 616.5000000000093, 2354.399999999996 - 0.45, 10000.0, 0.8, 4816.600000000032, 674.7000000000002, 2580.9000000000087 - 0.45, 10000.0, 0.84, 5121.676571428543, 707.7971428571328, 2710.143999999971 - 0.45, 10000.0, 0.88, 5289.822285714233, 726.0885714285541, 2782.2439999999397 - 0.45, 10000.0, 0.92, 5461.776000000007, 744.9463999999954, 2857.2207999999882 - 0.45, 10000.0, 0.96, 5683.384000000027, 769.5927999999924, 2955.27759999998 - 0.45, 10000.0, 1.0, 5905.60000000006, 795.0999999999883, 3056.799999999968 - 0.45, 15000.0, 0.52, 1189.6999999999991, 341.2999999999998, 1180.9999999999982 - 0.45, 15000.0, 0.56, 1784.3000000000145, 402.4000000000025, 1405.4000000000015 - 0.45, 15000.0, 0.6, 2379.1000000000404, 463.2000000000075, 1631.2000000000023 - 0.45, 15000.0, 0.64, 2974.000000000015, 523.8000000000079, 1858.8000000000377 - 0.45, 15000.0, 0.68, 3568.7999999999925, 584.3000000000116, 2088.1000000000154 - 0.45, 15000.0, 0.72, 4163.50000000006, 646.50000000001, 2323.9000000000137 - 0.45, 15000.0, 0.76, 4758.300000000009, 711.6000000000201, 2569.1000000000354 - 0.45, 15000.0, 0.8, 5353.100000000098, 776.899999999997, 2817.200000000044 - 0.45, 15000.0, 0.84, 5694.053714285671, 814.2199999999917, 2959.835999999987 - 0.45, 15000.0, 0.88, 5880.990857142777, 834.8799999999842, 3039.775999999976 - 0.45, 15000.0, 0.92, 6061.947199999943, 855.6296000000003, 3120.4103999999443 - 0.45, 15000.0, 0.96, 6288.546399999911, 882.3592000000009, 3223.8847999999184 - 0.45, 15000.0, 1.0, 6515.999999999878, 910.1000000000014, 3331.0999999998885 - 0.45, 20000.0, 0.52, 1307.2, 405.19999999999993, 1283.6000000000001 - 0.45, 20000.0, 0.56, 1960.800000000001, 471.7000000000001, 1524.2999999999997 - 0.45, 20000.0, 0.6, 2614.400000000004, 538.1000000000007, 1766.700000000001 - 0.45, 20000.0, 0.64, 3267.8000000000015, 604.3999999999997, 2011.1 - 0.45, 20000.0, 0.68, 3921.40000000001, 670.8000000000031, 2257.9999999999995 - 0.45, 20000.0, 0.72, 4575.000000000013, 738.7999999999998, 2511.0000000000064 - 0.45, 20000.0, 0.76, 5228.60000000003, 810.4000000000055, 2775.200000000009 - 0.45, 20000.0, 0.8, 5882.199999999979, 882.2999999999971, 3042.3999999999774 - 0.45, 20000.0, 0.84, 6257.265714285695, 925.0085714285698, 3201.2931428571464 - 0.45, 20000.0, 0.88, 6462.682857142827, 950.0742857142837, 3294.824571428578 - 0.45, 20000.0, 0.92, 6659.5592000000015, 974.4231999999953, 3386.093599999999 - 0.45, 20000.0, 0.96, 6904.558400000006, 1004.2263999999922, 3497.8911999999978 - 0.45, 20000.0, 1.0, 7149.900000000014, 1034.899999999989, 3612.699999999995 - 0.45, 25000.0, 0.52, 1440.0000000000005, 449.3999999999999, 1344.2000000000007 - 0.45, 25000.0, 0.56, 2160.0999999999976, 526.5000000000007, 1612.8000000000036 - 0.45, 25000.0, 0.6, 2880.0, 603.3000000000014, 1883.400000000012 - 0.45, 25000.0, 0.64, 3600.1000000000267, 679.9000000000007, 2156.3000000000106 - 0.45, 25000.0, 0.68, 4319.9999999999945, 756.6000000000035, 2432.0000000000227 - 0.45, 25000.0, 0.72, 5040.100000000032, 834.0000000000003, 2712.200000000007 - 0.45, 25000.0, 0.76, 5759.899999999995, 916.5000000000026, 3007.2000000000203 - 0.45, 25000.0, 0.8, 6480.099999999998, 1000.0000000000008, 3308.3999999999965 - 0.45, 25000.0, 0.84, 6893.672571428577, 1049.6520000000028, 3487.9068571428634 - 0.45, 25000.0, 0.88, 7119.838285714304, 1078.5920000000062, 3593.1754285714424 - 0.45, 25000.0, 0.92, 7334.695199999984, 1105.9511999999988, 3693.5511999999962 - 0.45, 25000.0, 0.96, 7600.586399999967, 1138.8703999999989, 3814.5983999999926 - 0.45, 25000.0, 1.0, 7866.099999999945, 1172.5, 3938.0999999999894 - 0.45, 30000.0, 0.52, 1575.8000000000004, 500.5, 1411.0 - 0.45, 30000.0, 0.56, 2363.5000000000045, 588.300000000001, 1707.1000000000022 - 0.45, 30000.0, 0.6, 3151.200000000014, 675.7000000000023, 2005.7000000000075 - 0.45, 30000.0, 0.64, 3939.3000000000116, 762.8000000000062, 2306.4999999999927 - 0.45, 30000.0, 0.68, 4727.000000000025, 849.9000000000025, 2610.6000000000136 - 0.45, 30000.0, 0.72, 5515.000000000019, 936.8000000000055, 2917.6000000000095 - 0.45, 30000.0, 0.76, 6302.800000000017, 1030.7000000000016, 3243.899999999998 - 0.45, 30000.0, 0.8, 7090.499999999998, 1127.9999999999977, 3585.0000000000086 - 0.45, 30000.0, 0.84, 7543.440000000008, 1184.5319999999995, 3784.501714285713 - 0.45, 30000.0, 0.88, 7791.14000000002, 1216.071999999999, 3897.418857142859 - 0.45, 30000.0, 0.92, 8024.635200000016, 1245.6120000000008, 4004.1408000000047 - 0.45, 30000.0, 0.96, 8311.930400000023, 1281.7120000000018, 4134.305600000006 - 0.45, 30000.0, 1.0, 8598.000000000038, 1318.500000000003, 4266.800000000006 - 0.45, 35000.0, 0.52, 1725.5, 549.1, 1492.7000000000003 - 0.45, 35000.0, 0.56, 2588.5000000000014, 646.700000000002, 1816.6999999999991 - 0.45, 35000.0, 0.6, 3451.400000000006, 744.0000000000051, 2143.2000000000035 - 0.45, 35000.0, 0.64, 4314.000000000006, 840.9999999999957, 2473.100000000003 - 0.45, 35000.0, 0.68, 5176.900000000013, 937.7000000000019, 2806.3000000000125 - 0.45, 35000.0, 0.72, 6039.900000000043, 1034.8000000000009, 3143.600000000012 - 0.45, 35000.0, 0.76, 6902.400000000037, 1139.6000000000108, 3503.0999999999963 - 0.45, 35000.0, 0.8, 7765.3999999999705, 1250.1999999999973, 3885.3999999999955 - 0.45, 35000.0, 0.84, 8262.194857142873, 1313.725714285715, 4106.421142857142 - 0.45, 35000.0, 0.88, 8533.423428571467, 1348.3028571428592, 4228.4925714285655 - 0.45, 35000.0, 0.92, 8786.16239999998, 1380.3264000000024, 4342.608799999992 - 0.45, 35000.0, 0.96, 9094.61279999997, 1419.6528000000035, 4482.433599999983 - 0.45, 35000.0, 1.0, 9400.099999999959, 1459.600000000005, 4624.299999999974 - 0.5, 0.0, 0.52, 758.8000000000015, 91.2, 837.2999999999996 - 0.5, 0.0, 0.56, 1138.2000000000016, 127.0999999999993, 987.0000000000101 - 0.5, 0.0, 0.6, 1517.600000000001, 162.4999999999988, 1136.900000000023 - 0.5, 0.0, 0.64, 1897.0000000001098, 198.20000000001303, 1288.8000000000757 - 0.5, 0.0, 0.68, 2276.4000000000196, 234.20000000001184, 1442.9000000000074 - 0.5, 0.0, 0.72, 2655.8000000000998, 271.3000000000183, 1601.6000000000483 - 0.5, 0.0, 0.76, 3035.2000000000885, 309.5000000000235, 1765.0000000000925 - 0.5, 0.0, 0.8, 3414.5999999998758, 347.70000000001437, 1930.0999999999738 - 0.5, 0.0, 0.84, 3628.9405714285504, 369.25600000000026, 2023.5525714285661 - 0.5, 0.0, 0.88, 3748.2262857142546, 381.21600000000245, 2075.898285714275 - 0.5, 0.0, 0.92, 3878.9584000000186, 394.1552000000022, 2133.162399999998 - 0.5, 0.0, 0.96, 4054.6448000000455, 411.5944000000027, 2210.400800000002 - 0.5, 0.0, 1.0, 4235.800000000087, 430.0000000000032, 2291.7000000000094 - 0.5, 5000.0, 0.52, 842.499999999998, 123.69999999999924, 895.0 - 0.5, 5000.0, 0.56, 1263.7999999999824, 164.49999999999994, 1060.1000000000172 - 0.5, 5000.0, 0.6, 1685.199999999936, 205.90000000000433, 1228.3000000000616 - 0.5, 5000.0, 0.64, 2106.4000000000447, 247.00000000000506, 1396.9999999999957 - 0.5, 5000.0, 0.68, 2527.700000000062, 287.8000000000047, 1566.8000000000197 - 0.5, 5000.0, 0.72, 2949.000000000104, 329.80000000001155, 1741.4000000000092 - 0.5, 5000.0, 0.76, 3370.300000000086, 373.30000000000666, 1921.8000000000318 - 0.5, 5000.0, 0.8, 3791.5000000001223, 416.7000000000046, 2103.8000000000447 - 0.5, 5000.0, 0.84, 4029.854285714292, 441.23142857142983, 2207.0839999999603 - 0.5, 5000.0, 0.88, 4162.277142857168, 454.8257142857177, 2264.9239999999436 - 0.5, 5000.0, 0.92, 4305.893600000012, 469.3863999999965, 2327.416799999966 - 0.5, 5000.0, 0.96, 4497.407200000029, 488.8727999999944, 2411.00959999995 - 0.5, 5000.0, 1.0, 4693.100000000058, 509.29999999999234, 2498.4999999999363 - 0.5, 10000.0, 0.52, 1057.1000000000008, 230.5, 1043.599999999999 - 0.5, 10000.0, 0.56, 1585.599999999999, 286.39999999999924, 1247.6000000000024 - 0.5, 10000.0, 0.6, 2114.0999999999926, 341.9000000000003, 1452.5000000000134 - 0.5, 10000.0, 0.64, 2642.7999999999893, 397.0000000000046, 1658.600000000018 - 0.5, 10000.0, 0.68, 3171.3000000000443, 452.2000000000056, 1866.8000000000281 - 0.5, 10000.0, 0.72, 3699.900000000006, 508.3000000000059, 2079.5000000000136 - 0.5, 10000.0, 0.76, 4228.39999999997, 567.3000000000048, 2301.3000000000306 - 0.5, 10000.0, 0.8, 4756.899999999926, 626.200000000003, 2525.399999999999 - 0.5, 10000.0, 0.84, 5058.004571428514, 659.7011428571462, 2653.353714285705 - 0.5, 10000.0, 0.88, 5224.150285714197, 678.2125714285801, 2724.790857142849 - 0.5, 10000.0, 0.92, 5395.198400000011, 697.2807999999976, 2799.0631999999982 - 0.5, 10000.0, 0.96, 5616.160800000016, 722.177599999995, 2896.0783999999976 - 0.5, 10000.0, 1.0, 5837.200000000023, 747.8999999999913, 2996.299999999997 - 0.5, 15000.0, 0.52, 1174.7999999999988, 286.4000000000001, 1140.1000000000004 - 0.5, 15000.0, 0.56, 1762.2999999999943, 348.3000000000014, 1362.1999999999985 - 0.5, 15000.0, 0.6, 2349.6000000000013, 410.0000000000053, 1585.7999999999995 - 0.5, 15000.0, 0.64, 2937.0999999999644, 471.40000000000333, 1811.0000000000111 - 0.5, 15000.0, 0.68, 3524.4999999999804, 532.7000000000016, 2038.000000000021 - 0.5, 15000.0, 0.72, 4111.999999999978, 595.5000000000041, 2271.000000000022 - 0.5, 15000.0, 0.76, 4699.300000000061, 661.400000000005, 2514.1000000000354 - 0.5, 15000.0, 0.8, 5286.799999999995, 727.3999999999978, 2759.799999999956 - 0.5, 15000.0, 0.84, 5623.517142857109, 765.038285714279, 2900.5422857142703 - 0.5, 15000.0, 0.88, 5808.068571428527, 785.7811428571315, 2978.9051428571083 - 0.5, 15000.0, 0.92, 5986.792800000008, 806.6008000000066, 3058.061599999969 - 0.5, 15000.0, 0.96, 6210.585599999995, 833.4576000000097, 3159.9951999999525 - 0.5, 15000.0, 1.0, 6434.899999999978, 861.3000000000139, 3265.4999999999345 - 0.5, 20000.0, 0.52, 1290.6000000000001, 348.7, 1239.9000000000003 - 0.5, 20000.0, 0.56, 1935.9000000000065, 416.2999999999994, 1478.5000000000002 - 0.5, 20000.0, 0.6, 2581.200000000018, 483.5999999999992, 1718.7000000000062 - 0.5, 20000.0, 0.64, 3226.400000000018, 550.7999999999982, 1960.899999999999 - 0.5, 20000.0, 0.68, 3871.70000000001, 618.1000000000041, 2205.5 - 0.5, 20000.0, 0.72, 4517.00000000005, 686.9000000000052, 2456.0000000000146 - 0.5, 20000.0, 0.76, 5162.300000000085, 759.5000000000152, 2718.100000000029 - 0.5, 20000.0, 0.8, 5807.599999999935, 832.1999999999914, 2983.1999999999166 - 0.5, 20000.0, 0.84, 6178.066857142799, 875.0639999999937, 3139.5148571428567 - 0.5, 20000.0, 0.88, 6380.875428571324, 899.923999999991, 3230.2834285714375 - 0.5, 20000.0, 0.92, 6574.525599999973, 924.1535999999832, 3319.1223999999947 - 0.5, 20000.0, 0.96, 6814.867199999965, 954.0431999999731, 3428.8927999999873 - 0.5, 20000.0, 1.0, 7055.099999999962, 984.7999999999603, 3541.6999999999757 - 0.5, 25000.0, 0.52, 1423.0000000000007, 397.89999999999964, 1312.6000000000008 - 0.5, 25000.0, 0.56, 2134.7999999999934, 475.2000000000012, 1577.000000000008 - 0.5, 25000.0, 0.6, 2846.299999999994, 552.3000000000028, 1843.3000000000306 - 0.5, 25000.0, 0.64, 3557.800000000058, 629.1999999999988, 2112.1000000000354 - 0.5, 25000.0, 0.68, 4269.29999999997, 706.1000000000066, 2383.3000000000657 - 0.5, 25000.0, 0.72, 4980.8000000000675, 783.899999999994, 2659.400000000022 - 0.5, 25000.0, 0.76, 5692.59999999997, 866.9000000000085, 2950.400000000044 - 0.5, 25000.0, 0.8, 6404.100000000028, 950.2999999999971, 3245.4999999999814 - 0.5, 25000.0, 0.84, 6812.967428571416, 1000.2657142857178, 3422.3360000000207 - 0.5, 25000.0, 0.88, 7036.581714285719, 1029.7228571428648, 3526.876000000044 - 0.5, 25000.0, 0.92, 7248.189599999935, 1057.4615999999926, 3626.180799999988 - 0.5, 25000.0, 0.96, 7509.303199999883, 1090.5431999999914, 3745.125599999981 - 0.5, 25000.0, 1.0, 7769.69999999981, 1124.2999999999925, 3866.3999999999733 - 0.5, 30000.0, 0.52, 1555.8000000000009, 446.69999999999993, 1375.8 - 0.5, 30000.0, 0.56, 2333.700000000011, 534.900000000002, 1667.5000000000027 - 0.5, 30000.0, 0.6, 3111.300000000041, 622.8000000000069, 1961.4000000000187 - 0.5, 30000.0, 0.64, 3889.200000000014, 710.4000000000132, 2257.999999999972 - 0.5, 30000.0, 0.68, 4667.100000000053, 798.0000000000057, 2557.8000000000284 - 0.5, 30000.0, 0.72, 5445.000000000064, 885.2000000000113, 2859.700000000022 - 0.5, 30000.0, 0.76, 6223.000000000046, 980.100000000007, 3182.699999999982 - 0.5, 30000.0, 0.8, 7000.9000000000215, 1077.4999999999943, 3517.200000000018 - 0.5, 30000.0, 0.84, 7448.270285714279, 1134.3988571428533, 3713.765714285701 - 0.5, 30000.0, 0.88, 7692.753142857138, 1166.4274285714228, 3825.8428571428403 - 0.5, 30000.0, 0.92, 7922.541600000007, 1196.3408000000006, 3931.4336000000017 - 0.5, 30000.0, 0.96, 8204.727200000014, 1232.6456000000023, 4059.4271999999996 - 0.5, 30000.0, 1.0, 8485.30000000003, 1269.6000000000056, 4189.599999999999 - 0.5, 35000.0, 0.52, 1708.499999999999, 499.9, 1459.5000000000005 - 0.5, 35000.0, 0.56, 2562.699999999996, 599.0000000000051, 1780.3999999999978 - 0.5, 35000.0, 0.6, 3416.9999999999986, 698.0000000000143, 2104.500000000016 - 0.5, 35000.0, 0.64, 4271.200000000004, 796.4999999999858, 2431.000000000011 - 0.5, 35000.0, 0.68, 5125.400000000017, 895.1000000000043, 2761.9000000000315 - 0.5, 35000.0, 0.72, 5979.700000000166, 993.9000000000038, 3096.5000000000323 - 0.5, 35000.0, 0.76, 6833.900000000062, 1099.9000000000285, 3451.0999999999835 - 0.5, 35000.0, 0.8, 7688.1999999999425, 1211.3999999999933, 3827.800000000001 - 0.5, 35000.0, 0.84, 8179.936571428611, 1275.6845714285678, 4046.574857142831 - 0.5, 35000.0, 0.88, 8448.202285714384, 1310.9102857142816, 4168.303428571376 - 0.5, 35000.0, 0.92, 8697.61679999995, 1343.4992000000034, 4281.7471999999825 - 0.5, 35000.0, 0.96, 9001.745599999917, 1383.342400000006, 4419.9023999999645 - 0.5, 35000.0, 1.0, 9303.099999999884, 1423.8000000000102, 4559.999999999941 - 0.55, 0.0, 0.52, 751.100000000003, 44.80000000000016, 799.6999999999994 - 0.55, 0.0, 0.56, 1125.8000000000018, 81.39999999999979, 947.7000000000164 - 0.55, 0.0, 0.6, 1500.5999999999913, 116.80000000000094, 1095.4000000000356 - 0.55, 0.0, 0.64, 1876.3000000001823, 154.60000000002424, 1249.4000000001347 - 0.55, 0.0, 0.68, 2251.700000000041, 189.40000000001965, 1398.700000000003 - 0.55, 0.0, 0.72, 2627.40000000013, 227.5000000000315, 1555.9000000000656 - 0.55, 0.0, 0.76, 3002.900000000154, 267.6000000000488, 1719.8000000001648 - 0.55, 0.0, 0.8, 3377.4999999997526, 304.8000000000261, 1880.69999999998 - 0.55, 0.0, 0.84, 3589.66057142853, 326.26171428571485, 1972.5628571428542 - 0.55, 0.0, 0.88, 3707.986285714229, 338.6388571428631, 2024.7314285714333 - 0.55, 0.0, 0.92, 3836.5680000000334, 351.9184000000067, 2081.341600000003 - 0.55, 0.0, 0.96, 4008.5240000000895, 369.42080000000914, 2156.943200000013 - 0.55, 0.0, 1.0, 4186.00000000017, 387.8000000000115, 2236.500000000026 - 0.55, 5000.0, 0.52, 831.8999999999961, 75.39999999999847, 856.5 - 0.55, 5000.0, 0.56, 1248.5999999999558, 117.99999999999854, 1021.7000000000273 - 0.55, 5000.0, 0.6, 1665.8999999998473, 159.0000000000029, 1186.600000000099 - 0.55, 5000.0, 0.64, 2081.600000000049, 201.5000000000045, 1354.1999999999891 - 0.55, 5000.0, 0.68, 2497.8000000000643, 242.3000000000015, 1521.5000000000139 - 0.55, 5000.0, 0.72, 2914.500000000179, 284.6000000000189, 1694.0999999999929 - 0.55, 5000.0, 0.76, 3330.100000000133, 328.80000000000956, 1872.0000000000455 - 0.55, 5000.0, 0.8, 3746.400000000256, 372.6000000000075, 2051.10000000011 - 0.55, 5000.0, 0.84, 3982.308571428589, 397.44914285714697, 2153.010857142785 - 0.55, 5000.0, 0.88, 4113.3742857143525, 411.26057142858264, 2210.2594285713376 - 0.55, 5000.0, 0.92, 4254.328000000051, 425.859199999996, 2271.773599999942 - 0.55, 5000.0, 0.96, 4441.536000000103, 445.2463999999928, 2353.67919999992 - 0.55, 5000.0, 1.0, 4633.0000000001755, 465.59999999998894, 2439.299999999902 - 0.55, 10000.0, 0.52, 1042.6000000000001, 179.29999999999998, 1002.6000000000007 - 0.55, 10000.0, 0.56, 1564.0000000000055, 236.00000000000037, 1204.000000000004 - 0.55, 10000.0, 0.6, 2085.4000000000074, 292.2000000000006, 1406.4000000000149 - 0.55, 10000.0, 0.64, 2606.600000000016, 348.0000000000107, 1610.0000000000307 - 0.55, 10000.0, 0.68, 3128.000000000024, 403.6999999999965, 1815.1999999999946 - 0.55, 10000.0, 0.72, 3649.4000000000683, 460.59999999999997, 2025.3 - 0.55, 10000.0, 0.76, 4170.59999999997, 520.3000000000054, 2244.7000000000517 - 0.55, 10000.0, 0.8, 4692.00000000004, 580.1000000000063, 2466.3000000000325 - 0.55, 10000.0, 0.84, 4988.7777142857085, 614.0217142857181, 2592.787999999999 - 0.55, 10000.0, 0.88, 5152.554857142842, 632.6788571428621, 2663.34799999999 - 0.55, 10000.0, 0.92, 5322.3992000000335, 651.959999999999, 2736.7175999999868 - 0.55, 10000.0, 0.96, 5542.486400000049, 677.2039999999977, 2832.5271999999754 - 0.55, 10000.0, 1.0, 5762.100000000065, 703.1999999999969, 2931.299999999959 - 0.55, 15000.0, 0.52, 1157.3000000000004, 233.30000000000015, 1096.0000000000025 - 0.55, 15000.0, 0.56, 1735.7999999999986, 296.1000000000017, 1315.5000000000102 - 0.55, 15000.0, 0.6, 2314.4999999999955, 358.6000000000043, 1536.2000000000264 - 0.55, 15000.0, 0.64, 2893.200000000062, 420.69999999999783, 1758.5000000000275 - 0.55, 15000.0, 0.68, 3471.8000000000343, 482.8000000000065, 1982.7999999999934 - 0.55, 15000.0, 0.72, 4050.5000000000045, 546.2000000000025, 2212.7000000000075 - 0.55, 15000.0, 0.76, 4628.999999999999, 612.8000000000155, 2452.4999999999995 - 0.55, 15000.0, 0.8, 5207.700000000001, 679.7000000000069, 2695.299999999985 - 0.55, 15000.0, 0.84, 5539.113142857136, 717.7954285714259, 2834.433714285703 - 0.55, 15000.0, 0.88, 5720.944571428542, 738.7297142857082, 2911.9308571428223 - 0.55, 15000.0, 0.92, 5898.782399999986, 759.7600000000025, 2990.2087999999762 - 0.55, 15000.0, 0.96, 6122.44879999998, 786.9160000000031, 3090.909599999964 - 0.55, 15000.0, 1.0, 6345.999999999977, 815.0000000000043, 3194.8999999999496 - 0.55, 20000.0, 0.52, 1272.4000000000024, 294.3000000000004, 1193.8000000000009 - 0.55, 20000.0, 0.56, 1908.6000000000147, 363.00000000000165, 1429.7000000000007 - 0.55, 20000.0, 0.6, 2544.8000000000293, 431.3000000000053, 1667.3000000000022 - 0.55, 20000.0, 0.64, 3181.1000000000245, 499.500000000012, 1907.1999999999969 - 0.55, 20000.0, 0.68, 3817.3000000000893, 567.7999999999964, 2149.2000000000053 - 0.55, 20000.0, 0.72, 4453.30000000002, 637.5000000000103, 2396.999999999963 - 0.55, 20000.0, 0.76, 5089.500000000036, 711.1000000000041, 2656.6000000000354 - 0.55, 20000.0, 0.8, 5725.700000000126, 784.9000000000196, 2919.4000000000224 - 0.55, 20000.0, 0.84, 6091.1308571428135, 827.9805714285656, 3073.0668571428637 - 0.55, 20000.0, 0.88, 6291.079428571333, 852.5462857142722, 3161.05542857143 - 0.55, 20000.0, 0.92, 6481.104799999988, 876.5328000000027, 3247.379999999995 - 0.55, 20000.0, 0.96, 6716.22159999996, 906.4136000000022, 3354.9359999999947 - 0.55, 20000.0, 1.0, 6950.899999999918, 937.2000000000022, 3465.499999999996 - 0.55, 25000.0, 0.52, 1404.4000000000003, 349.49999999999994, 1279.9000000000012 - 0.55, 25000.0, 0.56, 2106.700000000014, 427.0000000000018, 1539.1000000000079 - 0.55, 25000.0, 0.6, 2808.7000000000344, 504.30000000000587, 1800.9000000000221 - 0.55, 25000.0, 0.64, 3510.9999999999977, 581.4000000000095, 2064.9000000000065 - 0.55, 25000.0, 0.68, 4213.100000000103, 658.7000000000023, 2331.6000000000163 - 0.55, 25000.0, 0.72, 4915.400000000029, 736.8000000000192, 2602.800000000043 - 0.55, 25000.0, 0.76, 5617.500000000001, 820.2000000000104, 2889.300000000063 - 0.55, 25000.0, 0.8, 6319.80000000016, 904.2000000000176, 3179.9999999999845 - 0.55, 25000.0, 0.84, 6723.448571428582, 954.4148571428586, 3353.730857142858 - 0.55, 25000.0, 0.88, 6944.034285714296, 983.9234285714305, 3456.019428571424 - 0.55, 25000.0, 0.92, 7152.088800000006, 1011.7519999999979, 3553.3448000000185 - 0.55, 25000.0, 0.96, 7408.257600000019, 1045.0319999999956, 3670.281600000026 - 0.55, 25000.0, 1.0, 7663.300000000044, 1078.9999999999927, 3789.5000000000337 - 0.55, 30000.0, 0.52, 1533.9000000000008, 396.0000000000004, 1339.2000000000007 - 0.55, 30000.0, 0.56, 2300.500000000009, 484.6000000000037, 1625.6999999999994 - 0.55, 30000.0, 0.6, 3067.400000000038, 572.9000000000085, 1914.6999999999998 - 0.55, 30000.0, 0.64, 3834.4000000000387, 661.1000000000118, 2206.60000000001 - 0.55, 30000.0, 0.68, 4601.300000000055, 749.0000000000072, 2501.2000000000317 - 0.55, 30000.0, 0.72, 5368.300000000053, 837.2000000000046, 2799.400000000028 - 0.55, 30000.0, 0.76, 6135.2000000000735, 932.5999999999977, 3117.1999999999857 - 0.55, 30000.0, 0.8, 6901.800000000202, 1030.1000000000163, 3444.70000000003 - 0.55, 30000.0, 0.84, 7342.979428571434, 1087.3371428571372, 3637.966857142841 - 0.55, 30000.0, 0.88, 7584.093714285688, 1119.808571428556, 3748.8954285713894 - 0.55, 30000.0, 0.92, 7809.873600000028, 1150.0368000000044, 3853.145600000005 - 0.55, 30000.0, 0.96, 8086.299200000051, 1186.4936000000089, 3978.847200000004 - 0.55, 30000.0, 1.0, 8360.600000000073, 1223.6000000000151, 4106.599999999999 - 0.55, 35000.0, 0.52, 1688.8999999999992, 453.50000000000057, 1424.500000000001 - 0.55, 35000.0, 0.56, 2533.40000000001, 554.7000000000041, 1742.2000000000169 - 0.55, 35000.0, 0.6, 3377.800000000043, 655.3000000000116, 2062.9000000000547 - 0.55, 35000.0, 0.64, 4221.899999999968, 755.7000000000103, 2386.299999999966 - 0.55, 35000.0, 0.68, 5066.300000000096, 856.3000000000052, 2714.400000000019 - 0.55, 35000.0, 0.72, 5910.800000000018, 956.6999999999982, 3045.5000000000637 - 0.55, 35000.0, 0.76, 6755.200000000072, 1064.0999999999985, 3396.300000000068 - 0.55, 35000.0, 0.8, 7599.700000000093, 1176.8000000000009, 3766.4000000000597 - 0.55, 35000.0, 0.84, 8086.038857142861, 1241.9657142857097, 3982.2394285714136 - 0.55, 35000.0, 0.88, 8351.40742857143, 1277.8428571428462, 4103.173714285676 - 0.55, 35000.0, 0.92, 8597.505600000017, 1310.96160000001, 4215.653600000065 - 0.55, 35000.0, 0.96, 8897.0152, 1351.2832000000146, 4351.939200000092 - 0.55, 35000.0, 1.0, 9193.599999999971, 1392.2000000000205, 4490.100000000122 - 0.6000000000000001, 0.0, 0.52, 744.5000000000052, 0.5000000000005871, 759.7999999999993 - 0.6000000000000001, 0.0, 0.56, 1113.700000000002, 38.30000000000135, 906.4000000000234 - 0.6000000000000001, 0.0, 0.6, 1483.4999999999702, 73.40000000000593, 1052.0000000000464 - 0.6000000000000001, 0.0, 0.64, 1856.2000000002672, 115.30000000003959, 1212.30000000021 - 0.6000000000000001, 0.0, 0.68, 2228.0000000000755, 146.00000000002862, 1350.9999999999866 - 0.6000000000000001, 0.0, 0.72, 2600.700000000137, 186.60000000004715, 1508.8000000000682 - 0.6000000000000001, 0.0, 0.76, 2972.9000000002357, 230.70000000008724, 1676.3000000002592 - 0.6000000000000001, 0.0, 0.8, 3341.6999999995714, 264.7000000000414, 1828.900000000006 - 0.6000000000000001, 0.0, 0.84, 3551.683999999926, 285.5531428571436, 1918.3234285714323 - 0.6000000000000001, 0.0, 0.88, 3669.603999999906, 298.84457142858287, 1971.3577142857475 - 0.6000000000000001, 0.0, 0.92, 3796.3848000000553, 313.0128000000148, 2028.168000000018 - 0.6000000000000001, 0.0, 0.96, 3964.6056000001518, 330.7896000000209, 2102.1640000000357 - 0.6000000000000001, 0.0, 1.0, 4138.500000000296, 349.20000000002756, 2180.000000000062 - 0.6000000000000001, 5000.0, 0.52, 820.8999999999936, 28.999999999997407, 816.3000000000002 - 0.6000000000000001, 5000.0, 0.56, 1233.7999999999122, 75.099999999996, 984.0000000000391 - 0.6000000000000001, 5000.0, 0.6, 1648.1999999997042, 113.79999999999895, 1141.7000000001447 - 0.6000000000000001, 5000.0, 0.64, 2058.100000000035, 159.5000000000013, 1310.7999999999774 - 0.6000000000000001, 5000.0, 0.68, 2469.1000000000377, 199.79999999999222, 1474.7999999999881 - 0.6000000000000001, 5000.0, 0.72, 2882.000000000266, 242.40000000002726, 1646.399999999951 - 0.6000000000000001, 5000.0, 0.76, 3291.000000000171, 287.80000000001144, 1821.7000000000553 - 0.6000000000000001, 5000.0, 0.8, 3702.9000000004603, 332.20000000001266, 1997.1000000002166 - 0.6000000000000001, 5000.0, 0.84, 3936.7617142857493, 357.5257142857232, 2097.4297142855976 - 0.6000000000000001, 5000.0, 0.88, 4066.7188571429856, 371.66285714288114, 2154.2468571427253 - 0.6000000000000001, 5000.0, 0.92, 4204.964000000129, 386.31839999999715, 2215.0223999999184 - 0.6000000000000001, 5000.0, 0.96, 4387.572000000239, 405.5567999999925, 2295.400799999892 - 0.6000000000000001, 5000.0, 1.0, 4574.500000000388, 425.7999999999868, 2379.199999999875 - 0.6000000000000001, 10000.0, 0.52, 1027.0999999999997, 130.0999999999999, 959.4999999999998 - 0.6000000000000001, 10000.0, 0.56, 1540.6000000000006, 187.7, 1158.1999999999998 - 0.6000000000000001, 10000.0, 0.6, 2054.100000000003, 244.70000000000005, 1357.900000000001 - 0.6000000000000001, 10000.0, 0.64, 2567.7000000000003, 301.30000000000024, 1558.9000000000055 - 0.6000000000000001, 10000.0, 0.68, 3081.200000000004, 357.9, 1761.6999999999973 - 0.6000000000000001, 10000.0, 0.72, 3594.700000000011, 415.30000000000194, 1968.399999999987 - 0.6000000000000001, 10000.0, 0.76, 4108.200000000019, 475.69999999999686, 2184.8999999999855 - 0.6000000000000001, 10000.0, 0.8, 4621.900000000005, 536.2000000000004, 2403.6999999999925 - 0.6000000000000001, 10000.0, 0.84, 4914.137714285733, 570.5502857142865, 2528.579428571436 - 0.6000000000000001, 10000.0, 0.88, 5075.49485714289, 589.4731428571451, 2598.2137142857287 - 0.6000000000000001, 10000.0, 0.92, 5243.853599999988, 609.0391999999999, 2670.64159999999 - 0.6000000000000001, 10000.0, 0.96, 5462.49519999998, 634.6223999999991, 2765.175199999983 - 0.6000000000000001, 10000.0, 1.0, 5680.09999999997, 660.8999999999979, 2862.3999999999737 - 0.6000000000000001, 15000.0, 0.52, 1138.2999999999995, 182.39999999999986, 1050.0 - 0.6000000000000001, 15000.0, 0.56, 1707.4999999999975, 246.09999999999985, 1266.4000000000003 - 0.6000000000000001, 15000.0, 0.6, 2276.5999999999967, 309.50000000000017, 1484.2000000000005 - 0.6000000000000001, 15000.0, 0.64, 2845.799999999996, 372.29999999999956, 1703.1999999999935 - 0.6000000000000001, 15000.0, 0.68, 3414.8999999999833, 435.2000000000006, 1924.4999999999957 - 0.6000000000000001, 15000.0, 0.72, 3984.1000000000045, 499.20000000000124, 2150.6999999999907 - 0.6000000000000001, 15000.0, 0.76, 4553.200000000002, 566.8000000000013, 2387.400000000006 - 0.6000000000000001, 15000.0, 0.8, 5122.4000000000015, 634.3999999999974, 2627.2000000000094 - 0.6000000000000001, 15000.0, 0.84, 5448.109142857159, 672.9971428571438, 2764.5742857142995 - 0.6000000000000001, 15000.0, 0.88, 5627.000571428604, 694.2885714285736, 2841.03714285717 - 0.6000000000000001, 15000.0, 0.92, 5803.741599999973, 715.6183999999982, 2918.3160000000016 - 0.6000000000000001, 15000.0, 0.96, 6027.011199999953, 743.0367999999975, 3017.712000000006 - 0.6000000000000001, 15000.0, 1.0, 6249.49999999993, 771.2999999999964, 3120.1000000000104 - 0.6000000000000001, 20000.0, 0.52, 1252.4999999999995, 242.19999999999976, 1145.4999999999993 - 0.6000000000000001, 20000.0, 0.56, 1878.900000000001, 311.8999999999993, 1378.6000000000017 - 0.6000000000000001, 20000.0, 0.6, 2505.3000000000084, 381.3999999999982, 1613.600000000007 - 0.6000000000000001, 20000.0, 0.64, 3131.5000000000055, 450.6000000000005, 1850.4000000000067 - 0.6000000000000001, 20000.0, 0.68, 3757.7999999999834, 519.8999999999997, 2089.6000000000076 - 0.6000000000000001, 20000.0, 0.72, 4384.199999999981, 590.3999999999977, 2334.4000000000037 - 0.6000000000000001, 20000.0, 0.76, 5010.400000000011, 665.100000000002, 2591.100000000006 - 0.6000000000000001, 20000.0, 0.8, 5636.700000000023, 740.1000000000043, 2851.100000000011 - 0.6000000000000001, 20000.0, 0.84, 5996.593142857138, 783.454285714289, 3002.0245714285684 - 0.6000000000000001, 20000.0, 0.88, 6193.384571428569, 807.7571428571495, 3087.3502857142826 - 0.6000000000000001, 20000.0, 0.92, 6379.58399999998, 831.5351999999978, 3171.1527999999976 - 0.6000000000000001, 20000.0, 0.96, 6609.291999999968, 861.450399999996, 3276.309599999994 - 0.6000000000000001, 20000.0, 1.0, 6838.199999999953, 892.2999999999936, 3384.499999999989 - 0.6000000000000001, 25000.0, 0.52, 1384.0, 304.7, 1246.5999999999995 - 0.6000000000000001, 25000.0, 0.56, 2075.6999999999985, 382.2999999999994, 1500.6999999999962 - 0.6000000000000001, 25000.0, 0.6, 2767.6999999999966, 459.79999999999825, 1757.09999999999 - 0.6000000000000001, 25000.0, 0.64, 3459.6999999999957, 537.0999999999992, 2015.900000000005 - 0.6000000000000001, 25000.0, 0.68, 4151.700000000002, 614.4999999999986, 2277.500000000001 - 0.6000000000000001, 25000.0, 0.72, 4843.399999999994, 692.8000000000033, 2543.4999999999923 - 0.6000000000000001, 25000.0, 0.76, 5535.400000000016, 776.8999999999985, 2825.499999999998 - 0.6000000000000001, 25000.0, 0.8, 6227.400000000023, 861.2000000000024, 3111.100000000017 - 0.6000000000000001, 25000.0, 0.84, 6625.392571428571, 911.5131428571457, 3281.2645714285695 - 0.6000000000000001, 25000.0, 0.88, 6842.878285714283, 941.0245714285761, 3380.990285714283 - 0.6000000000000001, 25000.0, 0.92, 7047.215200000018, 968.9295999999969, 3476.0184000000013 - 0.6000000000000001, 25000.0, 0.96, 7298.046400000026, 1002.4031999999945, 3590.6007999999993 - 0.6000000000000001, 25000.0, 1.0, 7547.300000000036, 1036.599999999992, 3707.499999999996 - 0.6000000000000001, 30000.0, 0.52, 1509.4, 348.4999999999999, 1301.2000000000005 - 0.6000000000000001, 30000.0, 0.56, 2264.2000000000003, 437.50000000000006, 1581.900000000003 - 0.6000000000000001, 30000.0, 0.6, 3019.0000000000095, 526.3000000000012, 1866.1000000000095 - 0.6000000000000001, 30000.0, 0.64, 3773.899999999983, 614.5999999999995, 2151.699999999997 - 0.6000000000000001, 30000.0, 0.68, 4528.400000000022, 703.3999999999979, 2441.800000000004 - 0.6000000000000001, 30000.0, 0.72, 5283.200000000008, 792.3999999999996, 2735.7000000000094 - 0.6000000000000001, 30000.0, 0.76, 6038.100000000012, 888.2000000000058, 3047.3000000000125 - 0.6000000000000001, 30000.0, 0.8, 6792.599999999982, 985.2999999999995, 3366.5999999999935 - 0.6000000000000001, 30000.0, 0.84, 7227.0005714285835, 1042.8874285714319, 3556.457142857151 - 0.6000000000000001, 30000.0, 0.88, 7464.266285714311, 1076.1017142857208, 3666.72857142859 - 0.6000000000000001, 30000.0, 0.92, 7685.423199999985, 1106.8999999999967, 3769.9951999999976 - 0.6000000000000001, 30000.0, 0.96, 7955.3743999999815, 1143.6039999999957, 3893.3903999999957 - 0.6000000000000001, 30000.0, 1.0, 8222.899999999983, 1180.8999999999942, 4018.5999999999917 - 0.6000000000000001, 35000.0, 0.52, 1663.8000000000002, 407.3999999999999, 1385.3999999999999 - 0.6000000000000001, 35000.0, 0.56, 2495.5000000000014, 510.1000000000005, 1698.899999999999 - 0.6000000000000001, 35000.0, 0.6, 3327.6000000000045, 611.9000000000013, 2014.5999999999997 - 0.6000000000000001, 35000.0, 0.64, 4159.300000000017, 713.9000000000005, 2334.2999999999984 - 0.6000000000000001, 35000.0, 0.68, 4991.399999999993, 815.6000000000008, 2657.000000000009 - 0.6000000000000001, 35000.0, 0.72, 5823.100000000008, 917.099999999993, 2983.399999999981 - 0.6000000000000001, 35000.0, 0.76, 6655.200000000003, 1025.9000000000017, 3329.3999999999933 - 0.6000000000000001, 35000.0, 0.8, 7486.900000000014, 1139.1000000000047, 3692.399999999998 - 0.6000000000000001, 35000.0, 0.84, 7966.02914285714, 1204.9262857142887, 3904.806285714297 - 0.6000000000000001, 35000.0, 0.88, 8227.42057142856, 1241.5091428571486, 4024.469142857164 - 0.6000000000000001, 35000.0, 0.92, 8469.23439999998, 1275.1735999999958, 4135.600799999983 - 0.6000000000000001, 35000.0, 0.96, 8762.976799999957, 1315.8551999999916, 4269.6895999999715 - 0.6000000000000001, 35000.0, 1.0, 9053.49999999992, 1357.0999999999854, 4405.499999999956 - 0.65, 0.0, 0.52, 739.9000000000082, -41.399999999998585, 717.7999999999993 - 0.65, 0.0, 0.56, 1102.7000000000025, -1.6999999999956197, 863.5000000000305 - 0.65, 0.0, 0.6, 1467.1999999999348, 32.7000000000148, 1007.3000000000532 - 0.65, 0.0, 0.64, 1838.1000000003596, 81.40000000005975, 1179.6000000003005 - 0.65, 0.0, 0.68, 2207.100000000123, 103.90000000003882, 1299.5999999999538 - 0.65, 0.0, 0.72, 2578.0000000001087, 149.20000000006468, 1461.3000000000482 - 0.65, 0.0, 0.76, 2948.0000000003306, 200.20000000014124, 1636.7000000003732 - 0.65, 0.0, 0.8, 3309.79999999932, 227.9000000000601, 1775.3000000000607 - 0.65, 0.0, 0.84, 3517.733142857028, 247.43028571428658, 1861.1971428571542 - 0.65, 0.0, 0.88, 3636.1045714284332, 262.3531428571625, 1916.6885714286482 - 0.65, 0.0, 0.92, 3761.676000000088, 278.2008000000278, 1974.9992000000434 - 0.65, 0.0, 0.96, 3926.2960000002395, 296.56560000004004, 2047.4984000000763 - 0.65, 0.0, 1.0, 4096.900000000471, 315.1000000000537, 2123.7000000001217 - 0.65, 5000.0, 0.52, 809.8999999999904, -15.300000000003926, 774.9000000000003 - 0.65, 5000.0, 0.56, 1220.3999999998478, 36.599999999992164, 948.400000000052 - 0.65, 5000.0, 0.6, 1633.7999999994947, 70.29999999999177, 1093.4000000001977 - 0.65, 5000.0, 0.64, 2037.7999999999925, 121.79999999999454, 1267.9999999999586 - 0.65, 5000.0, 0.68, 2443.699999999969, 160.8999999999749, 1427.5999999999335 - 0.65, 5000.0, 0.72, 2854.2000000003595, 203.80000000003648, 1599.7999999998729 - 0.65, 5000.0, 0.76, 3255.6000000001904, 251.10000000001185, 1772.500000000057 - 0.65, 5000.0, 0.8, 3664.1000000007493, 296.4000000000208, 1943.200000000376 - 0.65, 5000.0, 0.84, 3896.615428571486, 322.4222857143016, 2041.7039999998224 - 0.65, 5000.0, 0.88, 4025.869714285932, 337.0251428571861, 2098.323999999821 - 0.65, 5000.0, 0.92, 4161.4312000002565, 351.7656000000006, 2158.729599999896 - 0.65, 5000.0, 0.96, 4339.178400000461, 370.80319999999494, 2237.87519999987 - 0.65, 5000.0, 1.0, 4521.300000000733, 390.899999999987, 2319.9999999998645 - 0.65, 10000.0, 0.52, 1008.7999999999988, 83.40000000000003, 916.5999999999998 - 0.65, 10000.0, 0.56, 1513.2000000000055, 141.39999999999966, 1111.7999999999972 - 0.65, 10000.0, 0.6, 2017.6000000000108, 198.8999999999989, 1307.8999999999996 - 0.65, 10000.0, 0.64, 2521.9999999999905, 255.90000000000026, 1505.000000000005 - 0.65, 10000.0, 0.68, 3026.3999999999987, 312.7999999999965, 1703.8999999999803 - 0.65, 10000.0, 0.72, 3530.7000000000185, 370.60000000000673, 1906.999999999947 - 0.65, 10000.0, 0.76, 4035.100000000027, 431.4999999999858, 2119.5999999999494 - 0.65, 10000.0, 0.8, 4539.500000000015, 492.50000000000205, 2334.5999999999844 - 0.65, 10000.0, 0.84, 4826.608571428629, 527.1560000000028, 2457.445142857165 - 0.65, 10000.0, 0.88, 4985.134285714386, 546.236000000007, 2525.976571428618 - 0.65, 10000.0, 0.92, 5149.893599999957, 565.8439999999995, 2596.8887999999724 - 0.65, 10000.0, 0.96, 5363.487199999935, 591.4119999999979, 2689.169599999951 - 0.65, 10000.0, 1.0, 5576.29999999991, 617.6999999999953, 2784.099999999923 - 0.65, 15000.0, 0.52, 1118.199999999999, 133.79999999999976, 1002.4999999999995 - 0.65, 15000.0, 0.56, 1677.299999999996, 198.49999999999997, 1215.600000000003 - 0.65, 15000.0, 0.6, 2236.2999999999965, 262.60000000000036, 1429.900000000005 - 0.65, 15000.0, 0.64, 2795.3999999999746, 326.3999999999976, 1645.6999999999646 - 0.65, 15000.0, 0.68, 3354.4999999999727, 390.1000000000029, 1863.5000000000045 - 0.65, 15000.0, 0.72, 3913.600000000023, 454.8000000000038, 2085.899999999964 - 0.65, 15000.0, 0.76, 4472.69999999999, 523.2000000000046, 2319.5000000000205 - 0.65, 15000.0, 0.8, 5031.8000000000375, 591.7999999999894, 2555.700000000038 - 0.65, 15000.0, 0.84, 5351.469714285756, 630.9074285714318, 2691.053714285754 - 0.65, 15000.0, 0.88, 5527.186857142933, 652.4217142857206, 2766.4308571429347 - 0.65, 15000.0, 0.92, 5702.401599999911, 674.0127999999967, 2842.6720000000173 - 0.65, 15000.0, 0.96, 5924.619199999856, 701.8095999999952, 2940.6760000000327 - 0.65, 15000.0, 1.0, 6145.399999999792, 730.3999999999937, 3041.400000000052 - 0.65, 20000.0, 0.52, 1231.1999999999991, 192.39999999999958, 1095.3999999999985 - 0.65, 20000.0, 0.56, 1846.6999999999978, 263.2999999999973, 1325.5999999999988 - 0.65, 20000.0, 0.6, 2462.3000000000093, 333.8999999999911, 1557.4000000000058 - 0.65, 20000.0, 0.64, 3077.899999999995, 404.1000000000018, 1791.1000000000167 - 0.65, 20000.0, 0.68, 3693.5999999999267, 474.4999999999986, 2027.3000000000156 - 0.65, 20000.0, 0.72, 4309.199999999932, 545.8999999999965, 2268.4000000000046 - 0.65, 20000.0, 0.76, 4924.800000000025, 621.8000000000065, 2521.99999999999 - 0.65, 20000.0, 0.8, 5540.400000000042, 697.8000000000127, 2778.700000000005 - 0.65, 20000.0, 0.84, 5894.298857142844, 741.505142857155, 2926.9468571428497 - 0.65, 20000.0, 0.88, 6087.727428571416, 765.756571428595, 3009.95542857142 - 0.65, 20000.0, 0.92, 6270.048799999944, 789.4479999999937, 3091.4344000000046 - 0.65, 20000.0, 0.96, 6494.361599999901, 819.3679999999896, 3194.104800000001 - 0.65, 20000.0, 1.0, 6717.499999999845, 850.1999999999838, 3299.6999999999916 - 0.65, 25000.0, 0.52, 1361.4000000000008, 263.1000000000003, 1211.9999999999984 - 0.65, 25000.0, 0.56, 2042.2000000000032, 340.79999999999836, 1460.3999999999892 - 0.65, 25000.0, 0.6, 2722.800000000008, 418.3999999999948, 1711.3999999999728 - 0.65, 25000.0, 0.64, 3403.599999999991, 495.9999999999917, 1964.900000000015 - 0.65, 25000.0, 0.68, 4084.199999999999, 573.3999999999971, 2220.7999999999847 - 0.65, 25000.0, 0.72, 4764.99999999998, 652.6000000000051, 2482.799999999981 - 0.65, 25000.0, 0.76, 5445.600000000083, 736.8999999999974, 2759.099999999982 - 0.65, 25000.0, 0.8, 6126.40000000009, 821.3000000000078, 3038.200000000074 - 0.65, 25000.0, 0.84, 6518.05942857144, 871.5240000000081, 3204.2394285714313 - 0.65, 25000.0, 0.88, 6731.9337142857285, 900.884000000014, 3301.373714285718 - 0.65, 25000.0, 0.92, 6932.150400000042, 928.7879999999915, 3394.168800000013 - 0.65, 25000.0, 0.96, 7177.292800000061, 962.4519999999857, 3506.369600000017 - 0.65, 25000.0, 1.0, 7420.400000000085, 996.8999999999791, 3620.900000000017 - 0.65, 30000.0, 0.52, 1483.199999999999, 304.70000000000005, 1262.4000000000012 - 0.65, 30000.0, 0.56, 2224.600000000006, 394.1000000000001, 1538.000000000003 - 0.65, 30000.0, 0.6, 2966.2000000000376, 483.20000000000147, 1815.9000000000085 - 0.65, 30000.0, 0.64, 3707.7999999999215, 572.2000000000019, 2096.3999999999837 - 0.65, 30000.0, 0.68, 4449.500000000066, 661.4999999999881, 2381.099999999997 - 0.65, 30000.0, 0.72, 5190.800000000018, 750.800000000003, 2668.700000000013 - 0.65, 30000.0, 0.76, 5932.400000000043, 847.3000000000072, 2974.7000000000153 - 0.65, 30000.0, 0.8, 6673.999999999963, 943.8000000000064, 3285.199999999985 - 0.65, 30000.0, 0.84, 7101.120000000055, 1001.6154285714383, 3471.247428571451 - 0.65, 30000.0, 0.88, 7334.240000000122, 1035.509714285733, 3580.5817142857536 - 0.65, 30000.0, 0.92, 7550.5663999999515, 1066.8567999999893, 3682.5720000000065 - 0.65, 30000.0, 0.96, 7813.852799999946, 1103.8095999999841, 3803.3280000000104 - 0.65, 30000.0, 1.0, 8074.3999999999505, 1141.2999999999777, 3925.700000000014 - 0.65, 35000.0, 0.52, 1632.900000000002, 361.50000000000006, 1343.0999999999983 - 0.65, 35000.0, 0.56, 2449.5000000000095, 464.5000000000012, 1650.1999999999987 - 0.65, 35000.0, 0.6, 3265.700000000031, 567.200000000002, 1960.3999999999976 - 0.65, 35000.0, 0.64, 4082.300000000032, 669.5999999999979, 2273.399999999983 - 0.65, 35000.0, 0.68, 4898.599999999959, 771.6999999999952, 2589.9000000000033 - 0.65, 35000.0, 0.72, 5715.200000000004, 873.799999999988, 2909.6999999999302 - 0.65, 35000.0, 0.76, 6531.499999999962, 983.3000000000014, 3249.0999999999735 - 0.65, 35000.0, 0.8, 7348.100000000084, 1096.8000000000154, 3603.7999999999884 - 0.65, 35000.0, 0.84, 7818.606285714302, 1163.144000000013, 3812.2542857143144 - 0.65, 35000.0, 0.88, 8075.069142857163, 1200.3240000000246, 3930.4971428572007 - 0.65, 35000.0, 0.92, 8311.445599999952, 1234.4319999999877, 4040.013599999954 - 0.65, 35000.0, 0.96, 8597.879199999888, 1275.3599999999767, 4171.387199999926 - 0.65, 35000.0, 1.0, 8880.6999999998, 1316.7999999999624, 4304.299999999888 - 0.7000000000000001, 0.0, 0.52, 738.2000000000118, -80.59999999999746, 673.8999999999996 - 0.7000000000000001, 0.0, 0.56, 1093.6000000000015, -38.099999999990914, 819.4000000000376 - 0.7000000000000001, 0.0, 0.6, 1452.599999999881, -4.8999999999716835, 961.9000000000542 - 0.7000000000000001, 0.0, 0.64, 1823.4000000004567, 54.00000000008495, 1153.4000000004041 - 0.7000000000000001, 0.0, 0.68, 2190.800000000187, 63.000000000049226, 1244.2999999999001 - 0.7000000000000001, 0.0, 0.72, 2561.6000000000345, 115.90000000008331, 1414.3999999999967 - 0.7000000000000001, 0.0, 0.76, 2931.0000000004366, 177.50000000021322, 1603.2000000005073 - 0.7000000000000001, 0.0, 0.8, 3284.3999999989837, 194.9000000000819, 1720.5000000001526 - 0.7000000000000001, 0.0, 0.84, 3490.5302857141164, 212.19314285714373, 1801.5468571428787 - 0.7000000000000001, 0.0, 0.88, 3610.51314285695, 229.68457142860188, 1861.6354285715677 - 0.7000000000000001, 0.0, 0.92, 3735.7088000001313, 248.24480000004607, 1923.192800000083 - 0.7000000000000001, 0.0, 0.96, 3897.001600000358, 267.6136000000677, 1994.3816000001375 - 0.7000000000000001, 0.0, 1.0, 4064.8000000007037, 286.4000000000919, 2069.1000000002136 - 0.7000000000000001, 5000.0, 0.52, 799.2999999999864, -57.30000000000565, 732.8000000000008 - 0.7000000000000001, 5000.0, 0.56, 1209.3999999997584, 3.299999999986767, 916.3000000000667 - 0.7000000000000001, 5000.0, 0.6, 1624.399999999207, 28.499999999980787, 1041.5000000002565 - 0.7000000000000001, 5000.0, 0.64, 2022.599999999913, 89.19999999998285, 1226.9999999999316 - 0.7000000000000001, 5000.0, 0.68, 2423.6999999998466, 126.19999999994727, 1380.7999999998428 - 0.7000000000000001, 5000.0, 0.72, 2833.8000000004577, 169.40000000004574, 1555.799999999749 - 0.7000000000000001, 5000.0, 0.76, 3226.5000000001824, 219.50000000000998, 1726.0000000000468 - 0.7000000000000001, 5000.0, 0.8, 3633.1000000011363, 266.1000000000327, 1890.8000000005964 - 0.7000000000000001, 5000.0, 0.84, 3865.27142857151, 293.10000000002503, 1987.1971428568866 - 0.7000000000000001, 5000.0, 0.88, 3994.3857142860475, 308.34000000006984, 2043.9285714283387 - 0.7000000000000001, 5000.0, 0.92, 4127.359200000445, 323.20240000000723, 2104.461599999879 - 0.7000000000000001, 5000.0, 0.96, 4300.018400000786, 341.984800000001, 2182.8031999998616 - 0.7000000000000001, 5000.0, 1.0, 4477.100000001231, 361.89999999999065, 2263.499999999879 - 0.7000000000000001, 10000.0, 0.52, 988.9999999999976, 39.09999999999999, 872.7999999999997 - 0.7000000000000001, 10000.0, 0.56, 1483.4000000000121, 97.49999999999858, 1063.8999999999926 - 0.7000000000000001, 10000.0, 0.6, 1977.9000000000206, 155.39999999999577, 1256.0999999999956 - 0.7000000000000001, 10000.0, 0.64, 2472.3999999999705, 212.69999999999823, 1449.2000000000062 - 0.7000000000000001, 10000.0, 0.68, 2966.899999999968, 269.99999999998926, 1643.9999999999427 - 0.7000000000000001, 10000.0, 0.72, 3461.5000000000027, 328.00000000001444, 1842.7999999998792 - 0.7000000000000001, 10000.0, 0.76, 3955.9000000000055, 389.2999999999638, 2051.29999999989 - 0.7000000000000001, 10000.0, 0.8, 4450.3000000000375, 450.60000000000474, 2262.099999999973 - 0.7000000000000001, 10000.0, 0.84, 4731.915428571553, 485.610285714291, 2382.8611428571876 - 0.7000000000000001, 10000.0, 0.88, 4887.389714285944, 505.01314285715677, 2450.3925714286665 - 0.7000000000000001, 10000.0, 0.92, 5048.108799999895, 524.7295999999998, 2519.7063999999564 - 0.7000000000000001, 10000.0, 0.96, 5255.973599999848, 550.2031999999964, 2609.4087999999215 - 0.7000000000000001, 10000.0, 1.0, 5463.3999999997895, 576.3999999999915, 2701.699999999875 - 0.7000000000000001, 15000.0, 0.52, 1096.7999999999984, 87.5999999999993, 953.6999999999985 - 0.7000000000000001, 15000.0, 0.56, 1645.2999999999952, 153.2000000000002, 1163.3000000000095 - 0.7000000000000001, 15000.0, 0.6, 2193.7000000000075, 218.29999999999995, 1374.1000000000195 - 0.7000000000000001, 15000.0, 0.64, 2742.0999999999385, 282.8999999999945, 1586.2999999999108 - 0.7000000000000001, 15000.0, 0.68, 3290.399999999983, 347.50000000000756, 1800.500000000035 - 0.7000000000000001, 15000.0, 0.72, 3838.800000000095, 412.90000000001186, 2019.099999999922 - 0.7000000000000001, 15000.0, 0.76, 4387.299999999957, 482.30000000001246, 2248.8000000000397 - 0.7000000000000001, 15000.0, 0.8, 4935.700000000113, 551.6999999999747, 2481.400000000086 - 0.7000000000000001, 15000.0, 0.84, 5248.9994285714965, 591.3297142857195, 2614.7371428572164 - 0.7000000000000001, 15000.0, 0.88, 5421.3537142858395, 613.1868571428666, 2689.028571428719 - 0.7000000000000001, 15000.0, 0.92, 5594.767199999808, 635.1111999999958, 2764.2288000000476 - 0.7000000000000001, 15000.0, 0.96, 5815.546399999703, 663.2583999999939, 2860.817600000086 - 0.7000000000000001, 15000.0, 1.0, 6034.299999999572, 692.0999999999915, 2959.800000000134 - 0.7000000000000001, 20000.0, 0.52, 1206.3, 144.69999999999987, 1043.4999999999995 - 0.7000000000000001, 20000.0, 0.56, 1809.6000000000029, 216.79999999999967, 1269.8 - 0.7000000000000001, 20000.0, 0.6, 2412.7000000000053, 288.399999999999, 1497.9999999999989 - 0.7000000000000001, 20000.0, 0.64, 3015.899999999993, 359.7000000000004, 1727.8999999999985 - 0.7000000000000001, 20000.0, 0.68, 3619.000000000014, 431.0999999999968, 1960.3000000000043 - 0.7000000000000001, 20000.0, 0.72, 4222.299999999992, 503.1000000000008, 2196.8999999999946 - 0.7000000000000001, 20000.0, 0.76, 4825.299999999981, 580.2999999999962, 2447.0999999999945 - 0.7000000000000001, 20000.0, 0.8, 5428.599999999991, 657.5999999999975, 2700.799999999995 - 0.7000000000000001, 20000.0, 0.84, 5775.149714285731, 701.7868571428565, 2846.4885714285792 - 0.7000000000000001, 20000.0, 0.88, 5964.666857142878, 726.035428571427, 2927.2742857142975 - 0.7000000000000001, 20000.0, 0.92, 6144.852799999988, 749.7559999999979, 3006.827999999995 - 0.7000000000000001, 20000.0, 0.96, 6367.4415999999865, 779.8879999999971, 3107.6959999999917 - 0.7000000000000001, 20000.0, 1.0, 6588.199999999982, 810.8999999999957, 3211.2999999999874 - 0.7000000000000001, 25000.0, 0.52, 1334.1, 213.69999999999993, 1155.8999999999996 - 0.7000000000000001, 25000.0, 0.56, 2001.200000000002, 292.80000000000007, 1401.0999999999976 - 0.7000000000000001, 25000.0, 0.6, 2668.200000000005, 371.8999999999996, 1648.7999999999927 - 0.7000000000000001, 25000.0, 0.64, 3335.2999999999856, 450.39999999999907, 1898.2999999999981 - 0.7000000000000001, 25000.0, 0.68, 4002.4999999999973, 529.7999999999972, 2151.799999999994 - 0.7000000000000001, 25000.0, 0.72, 4669.400000000001, 609.9999999999991, 2410.100000000002 - 0.7000000000000001, 25000.0, 0.76, 5336.5999999999985, 695.5999999999977, 2682.2999999999965 - 0.7000000000000001, 25000.0, 0.8, 6003.499999999999, 781.2000000000024, 2957.8999999999955 - 0.7000000000000001, 25000.0, 0.84, 6387.5434285714555, 831.6040000000007, 3120.2634285714416 - 0.7000000000000001, 25000.0, 0.88, 6597.277714285766, 860.5640000000012, 3213.737714285736 - 0.7000000000000001, 25000.0, 0.92, 6792.506399999961, 888.1607999999969, 3303.269599999996 - 0.7000000000000001, 25000.0, 0.96, 7030.520799999938, 921.8175999999955, 3412.6071999999936 - 0.7000000000000001, 25000.0, 1.0, 7266.099999999911, 956.2999999999932, 3524.2999999999893 - 0.7000000000000001, 30000.0, 0.52, 1455.0, 264.99999999999983, 1224.5000000000002 - 0.7000000000000001, 30000.0, 0.56, 2182.3000000000006, 354.7000000000002, 1493.600000000002 - 0.7000000000000001, 30000.0, 0.6, 2909.6999999999953, 444.10000000000053, 1765.6000000000056 - 0.7000000000000001, 30000.0, 0.64, 3637.2999999999693, 533.5000000000038, 2040.4000000000024 - 0.7000000000000001, 30000.0, 0.68, 4364.599999999989, 623.0999999999985, 2318.2999999999984 - 0.7000000000000001, 30000.0, 0.72, 5092.199999999991, 712.6999999999987, 2600.099999999993 - 0.7000000000000001, 30000.0, 0.76, 5819.599999999999, 809.2999999999932, 2899.000000000002 - 0.7000000000000001, 30000.0, 0.8, 6547.000000000017, 906.1000000000039, 3202.3999999999983 - 0.7000000000000001, 30000.0, 0.84, 6966.170285714314, 964.2091428571446, 3384.349714285726 - 0.7000000000000001, 30000.0, 0.88, 7194.873142857193, 998.380571428573, 3491.4068571428784 - 0.7000000000000001, 30000.0, 0.92, 7406.174399999981, 1029.9631999999979, 3591.2031999999986 - 0.7000000000000001, 30000.0, 0.96, 7662.532799999965, 1067.114399999996, 3709.2224000000006 - 0.7000000000000001, 30000.0, 1.0, 7915.7999999999465, 1104.7999999999934, 3828.800000000001 - 0.7000000000000001, 35000.0, 0.52, 1600.0, 319.39999999999986, 1300.8 - 0.7000000000000001, 35000.0, 0.56, 2399.6999999999994, 423.00000000000034, 1601.4000000000003 - 0.7000000000000001, 35000.0, 0.6, 3199.7999999999993, 526.1999999999999, 1904.2999999999945 - 0.7000000000000001, 35000.0, 0.64, 3999.7999999999856, 628.7999999999979, 2210.299999999994 - 0.7000000000000001, 35000.0, 0.68, 4799.799999999972, 731.3999999999995, 2520.000000000005 - 0.7000000000000001, 35000.0, 0.72, 5599.799999999981, 834.199999999998, 2833.999999999987 - 0.7000000000000001, 35000.0, 0.76, 6399.7999999999865, 944.0000000000002, 3165.4999999999895 - 0.7000000000000001, 35000.0, 0.8, 7199.499999999986, 1057.6000000000017, 3511.0999999999913 - 0.7000000000000001, 35000.0, 0.84, 7660.693142857147, 1124.4411428571445, 3715.48742857143 - 0.7000000000000001, 35000.0, 0.88, 7912.164571428568, 1162.2925714285732, 3832.561714285716 - 0.7000000000000001, 35000.0, 0.92, 8142.903200000006, 1196.8736, 3940.586399999994 - 0.7000000000000001, 35000.0, 0.96, 8421.490400000015, 1238.0032, 4069.09679999999 - 0.7000000000000001, 35000.0, 1.0, 8696.100000000022, 1279.6000000000015, 4198.899999999984 - 0.75, 0.0, 0.52, 740.3000000000164, -116.79999999999583, 628.3000000000001 - 0.75, 0.0, 0.56, 1087.2000000000007, -70.39999999998402, 774.5000000000434 - 0.75, 0.0, 0.6, 1440.5999999998055, -38.999999999952564, 916.400000000046 - 0.75, 0.0, 0.64, 1813.5000000005543, 34.20000000011595, 1135.8000000005218 - 0.75, 0.0, 0.68, 2180.90000000027, 23.20000000005996, 1184.8999999998196 - 0.75, 0.0, 0.72, 2553.7999999998992, 87.30000000010247, 1369.0999999999046 - 0.75, 0.0, 0.76, 2924.7000000005523, 164.0000000003058, 1578.000000000662 - 0.75, 0.0, 0.8, 3268.099999998551, 166.20000000010737, 1665.1000000002898 - 0.75, 0.0, 0.84, 3472.797714285481, 180.14171428571498, 1739.7354285714625 - 0.75, 0.0, 0.88, 3595.8548571426036, 201.35885714290197, 1807.1097142859367 - 0.75, 0.0, 0.92, 3721.750400000186, 223.90720000007113, 1874.106400000141 - 0.75, 0.0, 0.96, 3880.1288000005084, 244.79840000010572, 1944.2488000002259 - 0.75, 0.0, 1.0, 4045.8000000010043, 264.00000000014484, 2017.7000000003432 - 0.75, 5000.0, 0.52, 789.4999999999815, -96.80000000000771, 690.5000000000016 - 0.75, 5000.0, 0.56, 1201.7999999996393, -24.0000000000205, 889.1000000000821 - 0.75, 5000.0, 0.6, 1621.699999998828, -11.600000000034981, 985.8000000003217 - 0.75, 5000.0, 0.64, 2014.3999999997889, 62.49999999996572, 1188.9999999998931 - 0.75, 5000.0, 0.68, 2411.199999999661, 96.29999999990719, 1335.2999999997057 - 0.75, 5000.0, 0.72, 2823.5000000005525, 139.80000000005504, 1515.8999999995704 - 0.75, 5000.0, 0.76, 3206.3000000001352, 193.80000000000518, 1683.8000000000222 - 0.75, 5000.0, 0.8, 3613.0000000016353, 242.20000000004927, 1841.3000000008892 - 0.75, 5000.0, 0.84, 3846.131428571539, 270.5200000000369, 1935.2725714282155 - 0.75, 5000.0, 0.88, 3975.8257142861953, 286.6000000001051, 1992.4982857139955 - 0.75, 5000.0, 0.92, 4106.377600000704, 301.63040000001786, 2053.78479999987 - 0.75, 5000.0, 0.96, 4273.755200001236, 320.1008000000111, 2131.885599999872 - 0.75, 5000.0, 1.0, 4445.60000000192, 339.7999999999984, 2211.499999999929 - 0.75, 10000.0, 0.52, 968.9999999999952, -2.9000000000003356, 826.9999999999994 - 0.75, 10000.0, 0.56, 1452.8000000000206, 56.39999999999629, 1013.5999999999852 - 0.75, 10000.0, 0.6, 1937.0000000000239, 114.79999999999015, 1202.1999999999873 - 0.75, 10000.0, 0.64, 2421.7999999999365, 172.5999999999939, 1392.4000000000126 - 0.75, 10000.0, 0.68, 2905.9999999998986, 231.09999999997763, 1584.199999999879 - 0.75, 10000.0, 0.72, 3391.1999999999402, 289.0000000000268, 1777.4999999997817 - 0.75, 10000.0, 0.76, 3875.1999999999343, 350.69999999992757, 1982.49999999981 - 0.75, 10000.0, 0.8, 4359.80000000007, 412.1000000000081, 2189.299999999961 - 0.75, 10000.0, 0.84, 4635.783428571652, 447.68457142857994, 2308.3034285715025 - 0.75, 10000.0, 0.88, 4788.1777142861465, 467.85028571430826, 2375.2177142858754 - 0.75, 10000.0, 0.92, 4946.088799999796, 488.0511999999994, 2443.3415999999525 - 0.75, 10000.0, 0.96, 5150.465599999701, 513.6263999999941, 2530.791199999912 - 0.75, 10000.0, 1.0, 5354.099999999589, 539.7999999999861, 2620.4999999998554 - 0.75, 15000.0, 0.52, 1073.8999999999978, 43.89999999999827, 903.799999999996 - 0.75, 15000.0, 0.56, 1611.599999999996, 110.10000000000034, 1109.7000000000223 - 0.75, 15000.0, 0.6, 2148.9000000000287, 176.9999999999987, 1317.600000000049 - 0.75, 15000.0, 0.64, 2685.9999999998913, 241.69999999999118, 1525.2999999998287 - 0.75, 15000.0, 0.68, 3222.400000000026, 307.400000000016, 1736.2000000000955 - 0.75, 15000.0, 0.72, 3759.5000000002574, 373.4000000000287, 1951.0999999998637 - 0.75, 15000.0, 0.76, 4296.799999999892, 444.4000000000265, 2175.3000000000698 - 0.75, 15000.0, 0.8, 4833.900000000233, 513.8999999999512, 2404.900000000159 - 0.75, 15000.0, 0.84, 5140.50285714295, 554.0674285714351, 2536.4897142858263 - 0.75, 15000.0, 0.88, 5309.351428571605, 576.6417142857251, 2609.7468571430886 - 0.75, 15000.0, 0.92, 5480.843199999666, 599.0815999999965, 2683.938400000099 - 0.75, 15000.0, 0.96, 5700.066399999483, 627.4071999999932, 2779.152800000173 - 0.75, 15000.0, 1.0, 5916.799999999257, 656.1999999999891, 2876.3000000002635 - 0.75, 20000.0, 0.52, 1179.5000000000002, 99.60000000000001, 990.4999999999994 - 0.75, 20000.0, 0.56, 1769.3000000000038, 172.6999999999994, 1212.700000000002 - 0.75, 20000.0, 0.6, 2359.000000000007, 245.39999999999836, 1436.7000000000012 - 0.75, 20000.0, 0.64, 2948.7999999999843, 317.9000000000018, 1662.8 - 0.75, 20000.0, 0.68, 3538.5000000000496, 389.9999999999918, 1890.7000000000203 - 0.75, 20000.0, 0.72, 4128.300000000007, 463.1000000000031, 2123.3999999999933 - 0.75, 20000.0, 0.76, 4717.99999999996, 541.3999999999933, 2369.499999999979 - 0.75, 20000.0, 0.8, 5307.799999999969, 619.5999999999923, 2618.49999999999 - 0.75, 20000.0, 0.84, 5646.232000000031, 664.2725714285705, 2761.4828571428798 - 0.75, 20000.0, 0.88, 5831.552000000042, 688.7582857142826, 2840.791428571465 - 0.75, 20000.0, 0.92, 6010.113599999974, 712.7447999999963, 2919.082399999988 - 0.75, 20000.0, 0.96, 6232.075199999963, 743.225599999994, 3018.3847999999803 - 0.75, 20000.0, 1.0, 6451.399999999955, 774.4999999999918, 3120.099999999966 - 0.75, 25000.0, 0.52, 1305.0999999999995, 166.90000000000015, 1099.1 - 0.75, 25000.0, 0.56, 1957.7000000000046, 247.70000000000056, 1341.0999999999956 - 0.75, 25000.0, 0.6, 2610.100000000011, 328.1000000000009, 1584.5999999999874 - 0.75, 25000.0, 0.64, 3262.6999999999543, 408.39999999999856, 1831.30000000001 - 0.75, 25000.0, 0.68, 3915.3999999999724, 488.9999999999934, 2080.7999999999815 - 0.75, 25000.0, 0.72, 4567.800000000037, 570.2999999999942, 2334.8000000000025 - 0.75, 25000.0, 0.76, 5220.399999999995, 657.1999999999964, 2602.699999999995 - 0.75, 25000.0, 0.8, 5873.000000000003, 744.1000000000058, 2874.3999999999915 - 0.75, 25000.0, 0.84, 6248.869714285774, 794.7125714285745, 3033.0422857143094 - 0.75, 25000.0, 0.88, 6453.926857142969, 823.2582857142911, 3123.0051428571774 - 0.75, 25000.0, 0.92, 6644.0047999999015, 850.5399999999938, 3209.364799999998 - 0.75, 25000.0, 0.96, 6875.105599999839, 884.195999999989, 3315.8015999999934 - 0.75, 25000.0, 1.0, 7103.399999999762, 918.6999999999824, 3424.5999999999854 - 0.75, 30000.0, 0.52, 1424.8999999999999, 229.8999999999998, 1187.8000000000002 - 0.75, 30000.0, 0.56, 2137.1999999999985, 319.60000000000144, 1450.3000000000043 - 0.75, 30000.0, 0.6, 2849.7999999999915, 409.30000000000354, 1715.400000000016 - 0.75, 30000.0, 0.64, 3562.0999999999185, 498.700000000012, 1983.3000000000247 - 0.75, 30000.0, 0.68, 4274.699999999954, 588.2999999999934, 2254.6999999999734 - 0.75, 30000.0, 0.72, 4987.0000000000355, 678.2999999999993, 2529.7000000000044 - 0.75, 30000.0, 0.76, 5699.400000000033, 774.9999999999859, 2821.6999999999966 - 0.75, 30000.0, 0.8, 6411.90000000006, 872.200000000006, 3117.899999999978 - 0.75, 30000.0, 0.84, 6822.594285714351, 930.4034285714331, 3295.165714285756 - 0.75, 30000.0, 0.88, 7046.477142857264, 964.5177142857187, 3399.1828571429387 - 0.75, 30000.0, 0.92, 7252.4111999999795, 996.1327999999958, 3496.380799999999 - 0.75, 30000.0, 0.96, 7501.522399999964, 1033.4735999999912, 3611.701600000002 - 0.75, 30000.0, 1.0, 7747.199999999949, 1071.399999999985, 3728.6000000000067 - 0.75, 35000.0, 0.52, 1565.1000000000004, 281.49999999999994, 1258.8000000000004 - 0.75, 35000.0, 0.56, 2347.499999999999, 385.50000000000165, 1552.0000000000034 - 0.75, 35000.0, 0.6, 3129.9000000000065, 488.70000000000266, 1847.7999999999977 - 0.75, 35000.0, 0.64, 3912.1999999999653, 591.6999999999978, 2146.399999999986 - 0.75, 35000.0, 0.68, 4694.999999999933, 694.6000000000014, 2448.8000000000147 - 0.75, 35000.0, 0.72, 5477.299999999948, 797.8999999999977, 2755.399999999964 - 0.75, 35000.0, 0.76, 6259.700000000037, 908.2000000000018, 3079.799999999976 - 0.75, 35000.0, 0.8, 7042.3999999999505, 1021.5000000000006, 3415.6999999999675 - 0.75, 35000.0, 0.84, 7493.827428571417, 1088.7485714285742, 3615.6125714285768 - 0.75, 35000.0, 0.88, 7739.681714285673, 1127.374285714288, 3731.238285714297 - 0.75, 35000.0, 0.92, 7964.284800000029, 1162.5632000000014, 3837.5039999999813 - 0.75, 35000.0, 0.96, 8234.71360000005, 1203.9864000000039, 3962.8839999999695 - 0.75, 35000.0, 1.0, 8500.800000000077, 1245.8000000000077, 4089.3999999999583 - 0.8, 0.0, 0.52, 747.100000000022, -149.69999999999374, 581.200000000001 - 0.8, 0.0, 0.56, 1084.2999999999981, -98.09999999997468, 729.2000000000479 - 0.8, 0.0, 0.6, 1432.0999999997046, -69.19999999992686, 871.400000000027 - 0.8, 0.0, 0.64, 1809.8000000006484, 23.100000000153102, 1128.9000000006508 - 0.8, 0.0, 0.68, 2179.200000000373, -15.59999999992965, 1121.1999999997092 - 0.8, 0.0, 0.72, 2556.8999999996936, 64.00000000012136, 1326.3999999997632 - 0.8, 0.0, 0.76, 2931.9000000006763, 161.10000000042135, 1563.3000000008367 - 0.8, 0.0, 0.8, 3263.4999999980128, 142.30000000013598, 1609.700000000479 - 0.8, 0.0, 0.84, 3467.257714285403, 151.5760000000003, 1676.125714285762 - 0.8, 0.0, 0.88, 3595.1548571425315, 177.89600000006257, 1754.0228571431858 - 0.8, 0.0, 0.92, 3723.0680000002553, 205.95040000010377, 1829.0976000002192 - 0.8, 0.0, 0.96, 3879.0840000006974, 228.9848000001556, 1898.5352000003447 - 0.8, 0.0, 1.0, 4043.5000000013792, 248.8000000002147, 1971.0000000005175 - 0.8, 5000.0, 0.52, 780.8999999999758, -133.60000000001025, 648.5000000000026 - 0.8, 5000.0, 0.56, 1198.5999999994885, -44.50000000002988, 868.2000000000982 - 0.8, 5000.0, 0.6, 1627.399999998345, -50.00000000005599, 926.1000000003925 - 0.8, 5000.0, 0.64, 2015.099999999612, 42.499999999941565, 1155.199999999843 - 0.8, 5000.0, 0.68, 2408.2999999993963, 71.79999999985246, 1291.9999999995161 - 0.8, 5000.0, 0.72, 2826.000000000639, 115.60000000006342, 1481.5999999993257 - 0.8, 5000.0, 0.76, 3197.6000000000386, 174.7999999999967, 1647.4999999999782 - 0.8, 5000.0, 0.8, 3606.900000002263, 225.60000000007128, 1796.1000000012639 - 0.8, 5000.0, 0.84, 3842.5971428572866, 255.6434285714798, 1887.2937142852363 - 0.8, 5000.0, 0.88, 3973.748571429236, 272.79771428586406, 1945.4708571425058 - 0.8, 5000.0, 0.92, 4102.116000001048, 288.0512000000331, 2008.2655999998708 - 0.8, 5000.0, 0.96, 4264.052000001828, 306.1504000000269, 2086.823199999904 - 0.8, 5000.0, 1.0, 4430.500000002824, 325.60000000001185, 2165.8000000000197 - 0.8, 10000.0, 0.52, 950.0999999999913, -42.700000000001296, 778.0999999999987 - 0.8, 10000.0, 0.56, 1423.0000000000284, 18.499999999992284, 959.9999999999756 - 0.8, 10000.0, 0.6, 1896.9000000000165, 77.69999999998123, 1145.8999999999755 - 0.8, 10000.0, 0.64, 2373.0999999998844, 136.4999999999861, 1335.500000000029 - 0.8, 10000.0, 0.68, 2846.9999999997767, 197.69999999996048, 1526.6999999997836 - 0.8, 10000.0, 0.72, 3323.8999999998096, 255.10000000004425, 1712.7999999996516 - 0.8, 10000.0, 0.76, 3797.599999999791, 317.2999999998736, 1915.6999999997065 - 0.8, 10000.0, 0.8, 4273.500000000116, 378.6000000000113, 2119.2999999999447 - 0.8, 10000.0, 0.84, 4543.937714286082, 415.1502857142977, 2237.248000000112 - 0.8, 10000.0, 0.88, 4693.414857143587, 436.79314285717567, 2304.2080000002484 - 0.8, 10000.0, 0.92, 4851.423199999644, 458.1639999999989, 2372.041599999971 - 0.8, 10000.0, 0.96, 5057.474399999483, 484.31199999999075, 2458.2151999999396 - 0.8, 10000.0, 1.0, 5261.09999999929, 510.6999999999796, 2545.7999999998933 - 0.8, 15000.0, 0.52, 1049.2999999999972, 2.7999999999962597, 852.9999999999918 - 0.8, 15000.0, 0.56, 1576.3000000000002, 69.10000000000036, 1055.000000000044 - 0.8, 15000.0, 0.6, 2102.0000000000673, 139.099999999996, 1261.2000000000985 - 0.8, 15000.0, 0.64, 2627.1999999998334, 202.69999999998748, 1462.9999999997149 - 0.8, 15000.0, 0.68, 3150.300000000119, 269.800000000029, 1671.3000000001969 - 0.8, 15000.0, 0.72, 3675.500000000545, 336.20000000005797, 1882.6999999997915 - 0.8, 15000.0, 0.76, 4200.999999999786, 409.80000000004867, 2099.00000000011 - 0.8, 15000.0, 0.8, 4726.200000000402, 478.1999999999177, 2326.8000000002585 - 0.8, 15000.0, 0.84, 5025.784571428686, 518.9240000000054, 2457.1765714287217 - 0.8, 15000.0, 0.88, 5191.030285714511, 542.8440000000081, 2529.502285714616 - 0.8, 15000.0, 0.92, 5360.634399999468, 566.0919999999987, 2602.752800000178 - 0.8, 15000.0, 0.96, 5578.45279999918, 594.2799999999941, 2696.6976000003006 - 0.8, 15000.0, 1.0, 5793.49999999883, 622.4999999999868, 2791.9000000004485 - 0.8, 20000.0, 0.52, 1151.1, 56.90000000000004, 936.8999999999988 - 0.8, 20000.0, 0.56, 1726.6999999999996, 131.19999999999857, 1154.9000000000037 - 0.8, 20000.0, 0.6, 2302.399999999991, 205.09999999999587, 1374.8000000000025 - 0.8, 20000.0, 0.64, 2877.9999999999704, 278.5000000000004, 1596.3000000000106 - 0.8, 20000.0, 0.68, 3453.5000000001037, 351.89999999998366, 1820.2000000000428 - 0.8, 20000.0, 0.72, 4029.1000000000327, 426.0000000000039, 2048.3999999999915 - 0.8, 20000.0, 0.76, 4604.699999999901, 505.19999999998845, 2289.699999999941 - 0.8, 20000.0, 0.8, 5180.199999999955, 584.1999999999842, 2533.599999999981 - 0.8, 20000.0, 0.84, 5510.153714285759, 629.4194285714284, 2673.9337142857607 - 0.8, 20000.0, 0.88, 5691.070857142921, 654.2937142857113, 2752.0508571429345 - 0.8, 20000.0, 0.92, 5867.386399999943, 678.6751999999939, 2829.2207999999837 - 0.8, 20000.0, 0.96, 6087.684799999924, 709.5823999999909, 2926.8735999999676 - 0.8, 20000.0, 1.0, 6304.699999999901, 741.1999999999881, 3026.599999999941 - 0.8, 25000.0, 0.52, 1274.5999999999985, 123.2000000000004, 1042.9000000000005 - 0.8, 25000.0, 0.56, 1911.900000000004, 205.4000000000019, 1280.4999999999918 - 0.8, 25000.0, 0.6, 2549.200000000011, 287.50000000000364, 1520.3999999999812 - 0.8, 25000.0, 0.64, 3186.4999999999013, 369.39999999999765, 1763.1000000000288 - 0.8, 25000.0, 0.68, 3823.7999999999156, 451.09999999998695, 2008.1999999999596 - 0.8, 25000.0, 0.72, 4461.10000000011, 533.499999999984, 2257.4999999999955 - 0.8, 25000.0, 0.76, 5098.399999999977, 621.5999999999931, 2521.299999999995 - 0.8, 25000.0, 0.8, 5735.699999999997, 709.800000000007, 2788.5999999999844 - 0.8, 25000.0, 0.84, 6102.97542857153, 760.6862857142926, 2943.3862857143095 - 0.8, 25000.0, 0.88, 6303.269714285897, 788.9091428571545, 3029.909142857169 - 0.8, 25000.0, 0.92, 6488.021599999819, 815.9351999999893, 3113.1296000000057 - 0.8, 25000.0, 0.96, 6711.87919999971, 849.5983999999813, 3216.5872000000036 - 0.8, 25000.0, 1.0, 6932.699999999577, 884.0999999999691, 3322.3999999999965 - 0.8, 30000.0, 0.52, 1393.0999999999995, 199.89999999999964, 1153.4 - 0.8, 30000.0, 0.56, 2089.6999999999935, 289.500000000003, 1408.8000000000045 - 0.8, 30000.0, 0.6, 2786.2999999999847, 378.80000000000797, 1666.4000000000203 - 0.8, 30000.0, 0.64, 3482.8999999998223, 467.9000000000236, 1926.6000000000683 - 0.8, 30000.0, 0.68, 4179.399999999887, 557.4999999999814, 2190.599999999913 - 0.8, 30000.0, 0.72, 4876.000000000127, 647.6, 2458.5000000000296 - 0.8, 30000.0, 0.76, 5572.600000000122, 744.3999999999743, 2742.9999999999636 - 0.8, 30000.0, 0.8, 6269.100000000107, 841.500000000005, 3031.3999999999432 - 0.8, 30000.0, 0.84, 6670.848571428687, 899.5817142857236, 3203.6674285715258 - 0.8, 30000.0, 0.88, 6889.794285714496, 933.6188571428669, 3304.501714285903 - 0.8, 30000.0, 0.92, 7090.157600000024, 965.3359999999917, 3398.9488000000015 - 0.8, 30000.0, 0.96, 7331.615200000043, 1002.9559999999844, 3511.3616000000075 - 0.8, 30000.0, 1.0, 7569.300000000063, 1041.1999999999748, 3625.400000000015 - 0.8, 35000.0, 0.52, 1528.2000000000012, 248.2000000000001, 1218.200000000001 - 0.8, 35000.0, 0.56, 2292.200000000004, 351.900000000004, 1503.1000000000101 - 0.8, 35000.0, 0.6, 3056.300000000028, 455.2000000000091, 1790.8000000000047 - 0.8, 35000.0, 0.64, 3820.0999999998994, 558.400000000001, 2081.7999999999674 - 0.8, 35000.0, 0.68, 4584.1999999998825, 661.6000000000024, 2376.7000000000335 - 0.8, 35000.0, 0.72, 5348.299999999879, 765.2000000000007, 2675.7999999999124 - 0.8, 35000.0, 0.76, 6112.400000000117, 875.899999999998, 2992.099999999943 - 0.8, 35000.0, 0.8, 6876.399999999898, 988.5000000000006, 3317.199999999918 - 0.8, 35000.0, 0.84, 7317.391999999944, 1056.118857142862, 3512.3440000000082 - 0.8, 35000.0, 0.88, 7557.551999999866, 1095.667428571431, 3626.7240000000224 - 0.8, 35000.0, 0.92, 7775.856000000067, 1131.5008000000068, 3731.5071999999577 - 0.8, 35000.0, 0.96, 8037.680000000124, 1173.0856000000133, 3853.91039999994 - 0.8, 35000.0, 1.0, 8294.80000000019, 1215.0000000000227, 3977.199999999917 diff --git a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py b/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py deleted file mode 100644 index 229a932d02..0000000000 --- a/aviary/models/large_single_aisle_1/V3_bug_fixed_IO.py +++ /dev/null @@ -1,301 +0,0 @@ -''' -Initial cut at a centralized file for the IO -of the large single aisle 1 V3 bug fixed case for the GASP-based -mass calculations and geometry calculations. -''' -import numpy as np - -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Mission - -V3_bug_fixed_options = get_option_defaults() -V3_bug_fixed_options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') -V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') -# we keep CrewPayload.NUM_PASSENGERS here because preprocess_crewpayload is often not run in these -# tests which prevents these values being assigned from Design.NUM_PASSENGERS as would normally happen -V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') -V3_bug_fixed_options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') -V3_bug_fixed_options.set_val( - Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') -V3_bug_fixed_options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') -V3_bug_fixed_options.set_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') -V3_bug_fixed_options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - - -V3_bug_fixed_options.set_val( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" -) -V3_bug_fixed_options.set_val(Aircraft.Wing.SWEEP, val=25, units="deg") -V3_bug_fixed_options.set_val( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" -) -V3_bug_fixed_options.set_val( - Mission.Design.GROSS_MASS, val=175400, units="lbm" -) -V3_bug_fixed_options.set_val( - Aircraft.Wing.LOADING, val=126, units="lbf/ft**2" -) -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, np.array([28690]), units="lbf" -) -# NOTE override required for mass summation test -V3_bug_fixed_options.set_val( - Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless' -) -V3_bug_fixed_options.set_val( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") - - -V3_bug_fixed_non_metadata = AviaryValues() - - -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.NUM_SEATS_ABREAST, 6, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.NUM_AISLES, 1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.SEAT_PITCH, 29, units="inch" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.WETTED_AREA, 4000, units="ft**2" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" -) -V3_bug_fixed_options.set_val(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") -V3_bug_fixed_options.set_val( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") -V3_bug_fixed_options.set_val(Aircraft.Nacelle.FINENESS, 2, units="unitless") - -V3_bug_fixed_options.set_val( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" -) -V3_bug_fixed_options.set_val( - Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units="1/rad" -) -V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units="lbm" -) -V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' -) -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" -) -V3_bug_fixed_options.set_val( - # TODO: should be lbf/ft**2 I think - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=2.66, units='unitless' -) -V3_bug_fixed_options.set_val( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" -) -V3_bug_fixed_options.set_val( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units="lbm" -) -V3_bug_fixed_options.set_val( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" -) -V3_bug_fixed_options.set_val( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.APU.MASS, val=928.0, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") -V3_bug_fixed_options.set_val( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - -V3_bug_fixed_options.set_val( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" -) - -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' -) -V3_bug_fixed_options.set_val( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" -) -V3_bug_fixed_options.set_val( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" -) # Based on large single aisle 1 for updated flaps mass model -V3_bug_fixed_options.set_val( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" -) # Based on large single aisle 1 for updated flaps mass model -V3_bug_fixed_options.set_val( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") -V3_bug_fixed_options.set_val( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" -) -V3_bug_fixed_options.set_val( - Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3, units='unitless' -) - - -V3_bug_fixed_non_metadata.set_val( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' -) -V3_bug_fixed_non_metadata.set_val( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' -) diff --git a/aviary/models/large_turboprop_freighter/phase_info.py b/aviary/models/large_turboprop_freighter/phase_info.py deleted file mode 100644 index 660a85f53f..0000000000 --- a/aviary/models/large_turboprop_freighter/phase_info.py +++ /dev/null @@ -1,362 +0,0 @@ -from aviary.variable_info.enums import SpeedType - -# Energy method -# phase_info = { -# "pre_mission": {"include_takeoff": False, "optimize_mass": True}, -# "climb": { -# "subsystem_options": {"core_aerodynamics": {"method": "solved_alpha"}}, -# "user_options": { -# "optimize_mach": False, -# "optimize_altitude": False, -# "num_segments": 5, -# "order": 3, -# "solve_for_distance": False, -# "initial_mach": (0.2, "unitless"), -# "final_mach": (0.475, "unitless"), -# "mach_bounds": ((0.08, 0.478), "unitless"), -# "initial_altitude": (0.0, "ft"), -# "final_altitude": (21_000.0, "ft"), -# "altitude_bounds": ((0.0, 22_000.0), "ft"), -# "throttle_enforcement": "path_constraint", -# "fix_initial": True, -# "constrain_final": False, -# "fix_duration": False, -# "initial_bounds": ((0.0, 0.0), "min"), -# "duration_bounds": ((24.0, 192.0), "min"), -# "add_initial_mass_constraint": False, -# }, -# }, -# "cruise": { -# "subsystem_options": {"core_aerodynamics": {"method": "solved_alpha"}}, -# "user_options": { -# "optimize_mach": False, -# "optimize_altitude": False, -# "num_segments": 5, -# "order": 3, -# "solve_for_distance": False, -# "initial_mach": (0.475, "unitless"), -# "final_mach": (0.475, "unitless"), -# "mach_bounds": ((0.47, 0.48), "unitless"), -# "initial_altitude": (21_000.0, "ft"), -# "final_altitude": (21_000.0, "ft"), -# "altitude_bounds": ((20_000.0, 22_000.0), "ft"), -# "throttle_enforcement": "boundary_constraint", -# "fix_initial": False, -# "constrain_final": False, -# "fix_duration": False, -# "initial_bounds": ((64.0, 192.0), "min"), -# "duration_bounds": ((56.5, 169.5), "min"), -# }, -# }, -# "descent": { -# "subsystem_options": {"core_aerodynamics": {"method": "solved_alpha"}}, -# "user_options": { -# "optimize_mach": False, -# "optimize_altitude": False, -# "num_segments": 5, -# "order": 3, -# "solve_for_distance": False, -# "initial_mach": (0.475, "unitless"), -# "final_mach": (0.1, "unitless"), -# "mach_bounds": ((0.08, 0.48), "unitless"), -# "initial_altitude": (21_000.0, "ft"), -# "final_altitude": (500.0, "ft"), -# "altitude_bounds": ((0.0, 22_000.0), "ft"), -# "throttle_enforcement": "path_constraint", -# "fix_initial": False, -# "constrain_final": True, -# "fix_duration": False, -# "initial_bounds": ((100, 361.5), "min"), -# "duration_bounds": ((29.0, 87.0), "min"), -# }, -# }, -# "post_mission": { -# "include_landing": False, -# "constrain_range": True, -# "target_range": (2_020., "nmi"), -# }, -# } - -# 2DOF -phase_info = { - 'groundroll': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'connect_initial_mass': False, - 'fix_initial': True, - 'fix_initial_mass': False, - 'duration_ref': (50.0, 's'), - 'duration_bounds': ((1.0, 100.0), 's'), - 'velocity_lower': (0, 'kn'), - 'velocity_upper': (1000, 'kn'), - 'velocity_ref': (150, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'ft'), - 'distance_upper': (10.0e3, 'ft'), - 'distance_ref': (3000, 'ft'), - 'distance_defect_ref': (3000, 'ft'), - }, - 'initial_guesses': { - 'time': ([0.0, 40.0], 's'), - 'velocity': ([0.066, 143.1], 'kn'), - 'distance': ([0.0, 1000.0], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - }, - }, - 'rotation': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'fix_initial': False, - 'duration_bounds': ((1, 100), 's'), - 'duration_ref': (50.0, 's'), - 'velocity_lower': (0, 'kn'), - 'velocity_upper': (1000, 'kn'), - 'velocity_ref': (100, 'kn'), - 'velocity_ref0': (0, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'ft'), - 'distance_upper': (10_000, 'ft'), - 'distance_ref': (5000, 'ft'), - 'distance_defect_ref': (5000, 'ft'), - 'angle_lower': (0.0, 'rad'), - 'angle_upper': (5.0, 'rad'), - 'angle_ref': (5.0, 'rad'), - 'angle_defect_ref': (5.0, 'rad'), - 'normal_ref': (10000, 'lbf'), - }, - 'initial_guesses': { - 'time': ([40.0, 5.0], 's'), - 'alpha': ([0.0, 2.5], 'deg'), - 'velocity': ([143, 150.0], 'kn'), - 'distance': ([3680.37217765, 4000], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - }, - }, - 'ascent': { - 'user_options': { - 'num_segments': 4, - 'order': 3, - 'fix_initial': False, - 'velocity_lower': (0, 'kn'), - 'velocity_upper': (700, 'kn'), - 'velocity_ref': (200, 'kn'), - 'velocity_ref0': (0, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'ft'), - 'distance_upper': (15_000, 'ft'), - 'distance_ref': (1e4, 'ft'), - 'distance_defect_ref': (1e4, 'ft'), - 'alt_lower': (0, 'ft'), - 'alt_upper': (700, 'ft'), - 'alt_ref': (1000, 'ft'), - 'alt_defect_ref': (1000, 'ft'), - 'final_altitude': (500, 'ft'), - 'alt_constraint_ref': (500, 'ft'), - 'angle_lower': (-10, 'rad'), - 'angle_upper': (20, 'rad'), - 'angle_ref': (57.2958, 'deg'), - 'angle_defect_ref': (57.2958, 'deg'), - 'pitch_constraint_lower': (0.0, 'deg'), - 'pitch_constraint_upper': (15.0, 'deg'), - 'pitch_constraint_ref': (1.0, 'deg'), - }, - 'initial_guesses': { - 'time': ([45.0, 25.0], 's'), - 'flight_path_angle': ([0.0, 8.0], 'deg'), - 'alpha': ([2.5, 1.5], 'deg'), - 'velocity': ([150.0, 185.0], 'kn'), - 'distance': ([4.0e3, 10.0e3], 'ft'), - 'altitude': ([0.0, 500.0], 'ft'), - 'tau_gear': (0.2, 'unitless'), - 'tau_flaps': (0.9, 'unitless'), - 'throttle': ([0.956, 0.956], 'unitless'), - }, - }, - 'accel': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'fix_initial': False, - 'alt': (500, 'ft'), - 'EAS_constraint_eq': (250, 'kn'), - 'duration_bounds': ((1, 200), 's'), - 'duration_ref': (1000, 's'), - 'velocity_lower': (150, 'kn'), - 'velocity_upper': (270, 'kn'), - 'velocity_ref': (250, 'kn'), - 'velocity_ref0': (150, 'kn'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'NM'), - 'distance_upper': (150, 'NM'), - 'distance_ref': (5, 'NM'), - 'distance_defect_ref': (5, 'NM'), - }, - 'initial_guesses': { - 'time': ([70.0, 13.0], 's'), - 'velocity': ([185.0, 250.0], 'kn'), - 'distance': ([10.0e3, 20.0e3], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - }, - }, - 'climb1': { - 'user_options': { - 'num_segments': 1, - 'order': 3, - 'fix_initial': False, - 'EAS_target': (150, 'kn'), - 'mach_cruise': 0.475, - 'target_mach': False, - 'final_altitude': (10.0e3, 'ft'), - 'duration_bounds': ((30, 300), 's'), - 'duration_ref': (1000, 's'), - 'alt_lower': (400, 'ft'), - 'alt_upper': (11_000, 'ft'), - 'alt_ref': (10.0e3, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'NM'), - 'distance_upper': (500, 'NM'), - 'distance_ref': (10, 'NM'), - 'distance_ref0': (0, 'NM'), - }, - 'initial_guesses': { - 'time': ([1.0, 2.0], 'min'), - 'distance': ([20.0e3, 100.0e3], 'ft'), - 'altitude': ([500.0, 10.0e3], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - }, - }, - 'climb2': { - 'user_options': { - 'num_segments': 3, - 'order': 3, - 'fix_initial': False, - 'EAS_target': (160, 'kn'), - 'mach_cruise': 0.475, - 'target_mach': True, - 'final_altitude': (21_000, 'ft'), - 'required_available_climb_rate': (0.1, 'ft/min'), - 'duration_bounds': ((200, 17_000), 's'), - 'duration_ref': (5000, 's'), - 'alt_lower': (9000, 'ft'), - 'alt_upper': (22_000, 'ft'), - 'alt_ref': (20_000, 'ft'), - 'alt_ref0': (0, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (10, 'NM'), - 'distance_upper': (1000, 'NM'), - 'distance_ref': (500, 'NM'), - 'distance_ref0': (0, 'NM'), - 'distance_defect_ref': (500, 'NM'), - }, - 'initial_guesses': { - 'time': ([216.0, 1300.0], 's'), - 'distance': ([100.0e3, 200.0e3], 'ft'), - 'altitude': ([10_000, 20_000], 'ft'), - 'throttle': ([0.956, 0.956], 'unitless'), - }, - }, - 'cruise': { - 'user_options': { - 'alt_cruise': (21_000, 'ft'), - 'mach_cruise': 0.475, - }, - 'initial_guesses': { - # [Initial mass, delta mass] for special cruise phase. - 'mass': ([150_000.0, -35_000], 'lbm'), - 'initial_distance': (100.0e3, 'ft'), - 'initial_time': (1_000.0, 's'), - 'altitude': (21_000, 'ft'), - 'mach': (0.475, 'unitless'), - }, - }, - 'desc1': { - 'user_options': { - 'num_segments': 3, - 'order': 3, - 'fix_initial': False, - 'input_initial': False, - 'EAS_limit': (160, 'kn'), - 'mach_cruise': 0.475, - 'input_speed_type': SpeedType.MACH, - 'final_altitude': (10_000, 'ft'), - 'duration_bounds': ((300.0, 900.0), 's'), - 'duration_ref': (1000, 's'), - 'alt_lower': (1000, 'ft'), - 'alt_upper': (22_000, 'ft'), - 'alt_ref': (20_000, 'ft'), - 'alt_ref0': (0, 'ft'), - 'alt_constraint_ref': (10000, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (140_000, 'lbm'), - 'mass_ref0': (0, 'lbm'), - 'mass_defect_ref': (140_000, 'lbm'), - 'distance_lower': (1_000.0, 'NM'), - 'distance_upper': (3_000.0, 'NM'), - 'distance_ref': (2_020, 'NM'), - 'distance_ref0': (0, 'NM'), - 'distance_defect_ref': (100, 'NM'), - }, - 'initial_guesses': { - 'mass': (136000.0, 'lbm'), - 'altitude': ([20_000, 10_000], 'ft'), - 'throttle': ([0.0, 0.0], 'unitless'), - 'distance': ([0.92 * 2_020, 0.96 * 2_020], 'NM'), - 'time': ([28000.0, 500.0], 's'), - }, - }, - 'desc2': { - 'user_options': { - 'num_segments': 1, - 'order': 7, - 'fix_initial': False, - 'input_initial': False, - 'EAS_limit': (250, 'kn'), - 'mach_cruise': 0.80, - 'input_speed_type': SpeedType.EAS, - 'final_altitude': (1000, 'ft'), - 'duration_bounds': ((100.0, 5000), 's'), - 'duration_ref': (500, 's'), - 'alt_lower': (500, 'ft'), - 'alt_upper': (11_000, 'ft'), - 'alt_ref': (10.0e3, 'ft'), - 'alt_ref0': (1000, 'ft'), - 'alt_constraint_ref': (1000, 'ft'), - 'mass_lower': (0, 'lbm'), - 'mass_upper': (None, 'lbm'), - 'mass_ref': (150_000, 'lbm'), - 'mass_defect_ref': (150_000, 'lbm'), - 'distance_lower': (0, 'NM'), - 'distance_upper': (5000, 'NM'), - 'distance_ref': (3500, 'NM'), - 'distance_defect_ref': (100, 'NM'), - }, - 'initial_guesses': { - 'mass': (136000.0, 'lbm'), - 'altitude': ([10.0e3, 1.0e3], 'ft'), - 'throttle': ([0.0, 0.0], 'unitless'), - 'distance': ([0.96 * 2_020, 2_020], 'NM'), - 'time': ([28500.0, 500.0], 's'), - }, - }, -} diff --git a/aviary/models/missions/height_energy_default.py b/aviary/models/missions/height_energy_default.py new file mode 100644 index 0000000000..f454993927 --- /dev/null +++ b/aviary/models/missions/height_energy_default.py @@ -0,0 +1,180 @@ +from aviary.variable_info.variables import Mission + +# defaults for height energy based phases + +phase_info = { + 'pre_mission': {'include_takeoff': False, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.2, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.18, 0.74), 'unitless'), + 'mach_polynomial_order': 3, + 'altitude_optimize': False, + 'altitude_initial': (0.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'altitude_bounds': ((0.0, 34000.0), 'ft'), + 'altitude_polynomial_order': 3, + 'throttle_enforcement': 'path_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((64.0, 192.0), 'min'), + }, + }, + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'mach_polynomial_order': 3, + 'altitude_optimize': False, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (34000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'altitude_polynomial_order': 3, + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((64.0, 192.0), 'min'), + 'time_duration_bounds': ((56.5, 300.0), 'min'), + }, + }, + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.36, 'unitless'), + 'mach_bounds': ((0.34, 0.74), 'unitless'), + 'mach_polynomial_order': 3, + 'altitude_optimize': False, + 'altitude_initial': (34000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'altitude_bounds': ((0.0, 38000.0), 'ft'), + 'altitude_polynomial_order': 3, + 'throttle_enforcement': 'path_constraint', + 'time_initial_bounds': ((120.5, 361.5), 'min'), + 'time_duration_bounds': ((29.0, 87.0), 'min'), + }, + }, + 'post_mission': { + 'include_landing': False, + 'constrain_range': True, + 'target_range': (1906.0, 'nmi'), + }, +} + + +def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs): + """ + Modify the values in the phase_info dictionary to accommodate different values + for the following mission design inputs: cruise altitude, cruise Mach number, + cruise range, design gross mass. + + Parameters + ---------- + phase_info : dict + Dictionary of phase settings for a mission profile + post_mission_info : dict + Dictionary of phase settings for a post mission profile + aviary_inputs : + Object containing values and units for all aviary inputs and options + + Returns + ------- + dict + Modified phase_info and post_mission_info that have been changed to match + the new mission parameters + """ + alt_cruise = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') + mach_cruise = aviary_inputs.get_val(Mission.Summary.CRUISE_MACH) + + # Range + old_range_cruise, range_units = post_mission_info['target_range'] + range_cruise = aviary_inputs.get_val(Mission.Design.RANGE, units=range_units) + if range_cruise != old_range_cruise: + new_val = post_mission_info['target_range'][0] * range_cruise / old_range_cruise + post_mission_info['target_range'] = (new_val, range_units) + + # Altitude + old_alt_cruise = 32000.0 + if alt_cruise != old_alt_cruise: + new_alt = (alt_cruise, 'ft') + + climb = phase_info['climb'] + user = climb['user_options'] + if 'altitude_final' in user and user['altitude_final'][0] is not None: + user['altitude_final'] = new_alt + + if 'initial_guesses' in climb and 'altitude' in climb['initial_guesses']: + if climb['initial_guesses']['altitude'][0] is not None: + init = climb['initial_guesses']['altitude'][0][0] + climb['initial_guesses']['altitude'] = ([init, alt_cruise], 'ft') + + cruise = phase_info['cruise'] + user = cruise['user_options'] + if 'altitude_initial' in user and user['altitude_initial'][0] is not None: + user['altitude_initial'] = new_alt + + if 'altitude_final' in user and user['altitude_final'][0] is not None: + user['altitude_final'] = new_alt + + if 'initial_guesses' in cruise and 'altitude' in cruise['initial_guesses']: + if cruise['initial_guesses']['altitude'][0] is not None: + cruise['initial_guesses']['altitude'] = ([alt_cruise, alt_cruise], 'ft') + + descent = phase_info['descent'] + user = descent['user_options'] + if 'altitude_initial' in user and user['altitude_initial'][0] is not None: + user['altitude_initial'] = new_alt + + if 'initial_guesses' in descent and 'altitude' in descent['initial_guesses']: + if descent['initial_guesses']['altitude'][0] is not None: + final = climb['initial_guesses']['altitude'][0][0] + descent['initial_guesses']['altitude'] = ([alt_cruise, final], 'ft') + + # Mach + old_mach_cruise = 0.72 + if mach_cruise != old_mach_cruise: + new_mach = (mach_cruise, 'unitless') + + climb = phase_info['climb'] + user = climb['user_options'] + if 'mach_final' in user and user['mach_final'][0] is not None: + user['mach_final'] = new_mach + + if 'initial_guesses' in climb and 'mach' in climb['initial_guesses']: + if climb['initial_guesses']['mach'][0] is not None: + init = climb['initial_guesses']['mach'][0][0] + climb['initial_guesses']['mach'] = ([init, mach_cruise], 'unitless') + + cruise = phase_info['cruise'] + user = cruise['user_options'] + if 'mach_initial' in user and user['mach_initial'][0] is not None: + user['mach_initial'] = new_mach + + if 'mach_final' in user and user['mach_final'][0] is not None: + user['mach_final'] = new_mach + + if 'initial_guesses' in cruise and 'mach' in cruise['initial_guesses']: + if cruise['initial_guesses']['mach'][0] is not None: + cruise['initial_guesses']['mach'] = ([mach_cruise, mach_cruise], 'unitless') + + descent = phase_info['descent'] + user = descent['user_options'] + if 'mach_initial' in user and user['mach_initial'][0] is not None: + user['mach_initial'] = new_mach + + if 'initial_guesses' in descent and 'mach' in descent['initial_guesses']: + if descent['initial_guesses']['mach'][0] is not None: + final = climb['initial_guesses']['mach'][0][0] + descent['initial_guesses']['mach'] = ([mach_cruise, final], 'unitless') + + return phase_info, post_mission_info diff --git a/aviary/models/missions/two_dof_default.py b/aviary/models/missions/two_dof_default.py new file mode 100644 index 0000000000..7704ccaf6d --- /dev/null +++ b/aviary/models/missions/two_dof_default.py @@ -0,0 +1,332 @@ +from aviary.variable_info.enums import SpeedType +from aviary.variable_info.variables import Mission + +# defaults for 2DOF based phases +mission_distance = 3675 + +phase_info = { + 'groundroll': { + 'subsystem_options': {'core_aerodynamics': {'method': 'low_speed'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'time_initial': (0.0, 's'), + 'time_duration_ref': (50.0, 's'), + 'time_duration_bounds': ((1.0, 100.0), 's'), + 'velocity_initial': (0.066, 'kn'), + 'velocity_bounds': ((0, 1000), 'kn'), + 'velocity_ref': (150, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_initial': (0.0, 'ft'), + 'distance_bounds': ((0, 10.0e3), 'ft'), + 'distance_ref': (3000, 'ft'), + 'distance_defect_ref': (3000, 'ft'), + }, + 'initial_guesses': { + 'time': ([0.0, 40.0], 's'), + 'velocity': ([0.066, 143.1], 'kn'), + 'distance': ([0.0, 1000.0], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'rotation': { + 'subsystem_options': {'core_aerodynamics': {'method': 'low_speed'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'time_duration_bounds': ((1, 100), 's'), + 'time_duration_ref': (50.0, 's'), + 'velocity_bounds': ((0, 1000), 'kn'), + 'velocity_ref': (150, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 10.0e3), 'ft'), + 'distance_ref': (5000, 'ft'), + 'distance_defect_ref': (5000, 'ft'), + 'angle_of_attack_initial': (0.0, 'deg'), + 'angle_of_attack_bounds': ((0.0, 12.0), 'deg'), + 'angle_of_attack_ref': (12.0, 'deg'), + 'angle_of_attack_defect_ref': (12.0, 'deg'), + 'normal_ref': (10000, 'lbf'), + }, + 'initial_guesses': { + 'time': ([40.0, 5.0], 's'), + 'angle_of_attack': ([0.0, 2.5], 'deg'), + 'velocity': ([143, 150.0], 'kn'), + 'distance': ([3680.37217765, 4000], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'ascent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'low_speed'}}, + 'user_options': { + 'num_segments': 4, + 'order': 3, + 'velocity_bounds': ((0, 700), 'kn'), + 'velocity_ref': (200, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 15_000), 'ft'), + 'distance_ref': (1e4, 'ft'), + 'distance_defect_ref': (1e4, 'ft'), + 'altitude_bounds': ((0.0, 700.0), 'ft'), + 'altitude_ref': (1000, 'ft'), + 'altitude_defect_ref': (1000, 'ft'), + 'altitude_initial': (0, 'ft'), + 'altitude_final': (500, 'ft'), + 'altitude_constraint_ref': (500, 'ft'), + 'flight_path_angle_bounds': ((-10.0, 20.0), 'deg'), + 'flight_path_angle_ref': (57.2958, 'deg'), + 'flight_path_angle_defect_ref': (57.2958, 'deg'), + 'flight_path_angle_initial': (0.0, 'deg'), + 'pitch_constraint_bounds': ((0.0, 15.0), 'deg'), + 'pitch_constraint_ref': (1.0, 'deg'), + }, + 'initial_guesses': { + 'time': ([45.0, 25.0], 's'), + 'flight_path_angle': ([0.0, 8.0], 'deg'), + 'angle_of_attack': ([2.5, 1.5], 'deg'), + 'velocity': ([150.0, 185.0], 'kn'), + 'distance': ([4.0e3, 10.0e3], 'ft'), + 'altitude': ([0.0, 500.0], 'ft'), + 'tau_gear': (0.2, 'unitless'), + 'tau_flaps': (0.9, 'unitless'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'accel': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'alt': (500, 'ft'), + 'EAS_constraint_eq': (250, 'kn'), + 'time_duration_bounds': ((1, 200), 's'), + 'time_duration_ref': (1000, 's'), + 'velocity_bounds': ((150, 270), 'kn'), + 'velocity_ref': (250, 'kn'), + 'velocity_ref0': (150, 'kn'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 150.0), 'NM'), + 'distance_ref': (5, 'NM'), + 'distance_defect_ref': (5, 'NM'), + }, + 'initial_guesses': { + 'time': ([70.0, 13.0], 's'), + 'velocity': ([185.0, 250.0], 'kn'), + 'distance': ([10.0e3, 20.0e3], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'climb1': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'EAS_target': (250, 'kn'), + 'mach_cruise': 0.8, + 'target_mach': False, + 'time_duration_bounds': ((30, 300), 's'), + 'time_duration_ref': (1000, 's'), + 'altitude_initial': (500.0, 'ft'), + 'altitude_final': (10.0e3, 'ft'), + 'altitude_bounds': ((400.0, 11_000.0), 'ft'), + 'altitude_ref': (10.0e3, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0, 500.0), 'NM'), + 'distance_ref': (10, 'NM'), + }, + 'initial_guesses': { + 'time': ([1.0, 2.0], 'min'), + 'distance': ([20.0e3, 100.0e3], 'ft'), + 'altitude': ([500.0, 10.0e3], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'climb2': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 3, + 'order': 3, + 'EAS_target': (270, 'kn'), + 'mach_cruise': 0.8, + 'target_mach': True, + 'required_available_climb_rate': (0.1, 'ft/min'), + 'time_duration_bounds': ((200, 17_000), 's'), + 'time_duration_ref': (5000, 's'), + 'altitude_final': (37.5e3, 'ft'), + 'altitude_bounds': ((9000.0, 40000.0), 'ft'), + 'altitude_ref': (30000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((10.0, 1000.0), 'NM'), + 'distance_ref': (500, 'NM'), + 'distance_defect_ref': (500, 'NM'), + }, + 'initial_guesses': { + 'time': ([216.0, 1300.0], 's'), + 'distance': ([100.0e3, 200.0e3], 'ft'), + 'altitude': ([10.0e3, 37.5e3], 'ft'), + 'throttle': ([0.956, 0.956], 'unitless'), + }, + }, + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'alt_cruise': (37.5e3, 'ft'), + 'mach_cruise': 0.8, + }, + 'initial_guesses': { + # [Initial mass, delta mass] for special cruise phase. + 'mass': ([171481.0, -35000], 'lbm'), + 'initial_distance': (200.0e3, 'ft'), + 'initial_time': (1516.0, 's'), + 'altitude': (37.5e3, 'ft'), + 'mach': (0.8, 'unitless'), + }, + }, + 'desc1': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 3, + 'order': 3, + 'EAS_limit': (350, 'kn'), + 'mach_cruise': 0.8, + 'input_speed_type': SpeedType.MACH, + 'time_duration_bounds': ((300.0, 900.0), 's'), + 'time_duration_ref': (1000, 's'), + 'altitude_final': (10.0e3, 'ft'), + 'altitude_bounds': ((1000.0, 40_000.0), 'ft'), + 'altitude_ref': (30_000, 'ft'), + 'altitude_constraint_ref': (10000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (140_000, 'lbm'), + 'mass_defect_ref': (140_000, 'lbm'), + 'distance_bounds': ((0.0, 5000.0), 'NM'), + 'distance_ref': (mission_distance, 'NM'), + 'distance_defect_ref': (100, 'NM'), + }, + 'initial_guesses': { + 'mass': (136000.0, 'lbm'), + 'altitude': ([37.5e3, 10.0e3], 'ft'), + 'throttle': ([0.0, 0.0], 'unitless'), + 'distance': ([0.92 * mission_distance, 0.96 * mission_distance], 'NM'), + 'time': ([28000.0, 500.0], 's'), + }, + }, + 'desc2': { + 'subsystem_options': {'core_aerodynamics': {'method': 'cruise'}}, + 'user_options': { + 'num_segments': 1, + 'order': 7, + 'EAS_limit': (250, 'kn'), + 'mach_cruise': 0.80, + 'input_speed_type': SpeedType.EAS, + 'time_duration_bounds': ((100.0, 5000), 's'), + 'time_duration_ref': (500, 's'), + 'altitude_final': (1000, 'ft'), + 'altitude_bounds': ((500.0, 11_000.0), 'ft'), + 'altitude_ref': (10.0e3, 'ft'), + 'altitude_ref0': (1000, 'ft'), + 'altitude_constraint_ref': (1000, 'ft'), + 'mass_bounds': ((0, None), 'lbm'), + 'mass_ref': (150_000, 'lbm'), + 'mass_defect_ref': (150_000, 'lbm'), + 'distance_bounds': ((0.0, 5000.0), 'NM'), + 'distance_ref': (3500, 'NM'), + 'distance_defect_ref': (100, 'NM'), + }, + 'initial_guesses': { + 'mass': (136000.0, 'lbm'), + 'altitude': ([10.0e3, 1.0e3], 'ft'), + 'throttle': ([0.0, 0.0], 'unitless'), + 'distance': ([0.96 * mission_distance, mission_distance], 'NM'), + 'time': ([28500.0, 500.0], 's'), + }, + }, +} + + +def phase_info_parameterization(phase_info, post_mission_info, aviary_inputs): + """ + Modify the values in the phase_info dictionary to accommodate different values + for the following mission design inputs: cruise altitude, cruise Mach number, + cruise range, design gross mass. + + Parameters + ---------- + phase_info : dict + Dictionary of phase settings for a mission profile + post_mission_info : dict + Dictionary of phase settings for a post mission profile + aviary_inputs : + Object containing values and units for all aviary inputs and options + + Returns + ------- + dict + Modified phase_info that has been changed to match the new mission + parameters + """ + range_cruise = aviary_inputs.get_val(Mission.Design.RANGE, units='NM') + alt_cruise = aviary_inputs.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') + gross_mass = aviary_inputs.get_val(Mission.Design.GROSS_MASS, units='lbm') + mach_cruise = aviary_inputs.get_val(Mission.Design.MACH) + + # Range + old_range_cruise = phase_info['desc2']['initial_guesses']['distance'][0][1] + range_scale = 1.0 + if range_cruise != old_range_cruise: + phase_info['desc1']['initial_guesses']['distance'] = ( + [0.92 * range_cruise, 0.96 * range_cruise], + 'NM', + ) + phase_info['desc2']['initial_guesses']['distance'] = ( + [0.96 * range_cruise, range_cruise], + 'NM', + ) + range_scale = range_cruise / old_range_cruise + + # Altitude + old_alt_cruise = phase_info['climb2']['user_options']['altitude_final'][0] + if alt_cruise != old_alt_cruise: + phase_info['climb2']['user_options']['altitude_final'] = (alt_cruise, 'ft') + phase_info['climb2']['initial_guesses']['altitude'] = ([10.0e3, alt_cruise], 'ft') + phase_info['cruise']['initial_guesses']['altitude'] = (alt_cruise, 'ft') + phase_info['desc1']['initial_guesses']['altitude'] = ([alt_cruise, 10.0e3], 'ft') + + # TODO - Could adjust time guesses/bounds in climb2 and desc2. + + # Mass + old_gross_mass = 175400.0 + if gross_mass != old_gross_mass: + # Note, this requires that the guess for gross mass is pretty close to the + # compute mass. + + fuel_used = 35000 * range_scale + phase_info['groundroll']['initial_guesses']['mass'] = ([gross_mass, gross_mass], 'lbm') + phase_info['rotation']['initial_guesses']['mass'] = ([gross_mass, gross_mass], 'lbm') + phase_info['accel']['initial_guesses']['mass'] = ([gross_mass, gross_mass], 'lbm') + phase_info['ascent']['initial_guesses']['mass'] = ([gross_mass, gross_mass], 'lbm') + + phase_info['cruise']['initial_guesses']['mass'] = ([gross_mass, -fuel_used], 'lbm') + + end_mass = gross_mass - fuel_used + phase_info['desc1']['initial_guesses']['mass'] = (end_mass, 'lbm') + phase_info['desc2']['initial_guesses']['mass'] = (end_mass, 'lbm') + + # Mach + old_mach_cruise = phase_info['cruise']['initial_guesses']['mach'][0] + if mach_cruise != old_mach_cruise: + phase_info['cruise']['initial_guesses']['mach'] = (mach_cruise, 'unitless') + + return phase_info, post_mission_info diff --git a/aviary/models/propellers/PropFan.prop b/aviary/models/propellers/PropFan.prop deleted file mode 100644 index 5663c2ec36..0000000000 --- a/aviary/models/propellers/PropFan.prop +++ /dev/null @@ -1,1207 +0,0 @@ -# created 06/24/24 at 17:13 -# GASP propeller map converted from PropFan.map -# Propfan format - CT = f(Mach, Adv Ratio & CP) -# mach_type = mach -# Hamilton Standard 10 Bladed Propfan Performance Deck: Ct Tables - - J, Mach, CP, CT -0.0, 0.0, 0.0465, 0.122634 -0.2, 0.0, 0.0465, 0.095985 -0.4, 0.0, 0.0465, 0.066562 -0.6, 0.0, 0.0465, 0.044919 -0.8, 0.0, 0.0465, 0.040928 -1.0, 0.0, 0.0465, 0.026127 -1.2, 0.0, 0.0465, 0.023982 -1.4, 0.0, 0.0465, 0.015 -1.6, 0.0, 0.0465, 0.003438 -2.0, 0.0, 0.0465, 0.003328 -2.4, 0.0, 0.0465, -0.000759 -2.8, 0.0, 0.0465, -0.006488 -0.0, 0.0, 0.2137, 0.334586 -0.2, 0.0, 0.2137, 0.306967 -0.4, 0.0, 0.2137, 0.272467 -0.6, 0.0, 0.2137, 0.230461 -0.8, 0.0, 0.2137, 0.198847 -1.0, 0.0, 0.2137, 0.169543 -1.2, 0.0, 0.2137, 0.14786 -1.4, 0.0, 0.2137, 0.127271 -1.6, 0.0, 0.2137, 0.102498 -2.0, 0.0, 0.2137, 0.087057 -2.4, 0.0, 0.2137, 0.066929 -2.8, 0.0, 0.2137, 0.052326 -0.0, 0.0, 0.3808, 0.461205 -0.2, 0.0, 0.3808, 0.45162 -0.4, 0.0, 0.3808, 0.415794 -0.6, 0.0, 0.3808, 0.369702 -0.8, 0.0, 0.3808, 0.326128 -1.0, 0.0, 0.3808, 0.287241 -1.2, 0.0, 0.3808, 0.254097 -1.4, 0.0, 0.3808, 0.225627 -1.6, 0.0, 0.3808, 0.201559 -2.0, 0.0, 0.3808, 0.16052 -2.4, 0.0, 0.3808, 0.1331 -2.8, 0.0, 0.3808, 0.110613 -0.0, 0.0, 0.548, 0.534579 -0.2, 0.0, 0.548, 0.54768 -0.4, 0.0, 0.548, 0.518784 -0.6, 0.0, 0.548, 0.474087 -0.8, 0.0, 0.548, 0.430277 -1.0, 0.0, 0.548, 0.387471 -1.2, 0.0, 0.548, 0.347784 -1.4, 0.0, 0.548, 0.312717 -1.6, 0.0, 0.548, 0.281581 -2.0, 0.0, 0.548, 0.234311 -2.4, 0.0, 0.548, 0.196755 -2.8, 0.0, 0.548, 0.166748 -0.0, 0.0, 0.7151, 0.571583 -0.2, 0.0, 0.7151, 0.602153 -0.4, 0.0, 0.7151, 0.591597 -0.6, 0.0, 0.7151, 0.553517 -0.8, 0.0, 0.7151, 0.511769 -1.0, 0.0, 0.7151, 0.47011 -1.2, 0.0, 0.7151, 0.428481 -1.4, 0.0, 0.7151, 0.390349 -1.6, 0.0, 0.7151, 0.355478 -2.0, 0.0, 0.7151, 0.300715 -2.4, 0.0, 0.7151, 0.256006 -2.8, 0.0, 0.7151, 0.220462 -0.0, 0.0, 0.8823, 0.584088 -0.2, 0.0, 0.8823, 0.645651 -0.4, 0.0, 0.8823, 0.643189 -0.6, 0.0, 0.8823, 0.613761 -0.8, 0.0, 0.8823, 0.576476 -1.0, 0.0, 0.8823, 0.535848 -1.2, 0.0, 0.8823, 0.495633 -1.4, 0.0, 0.8823, 0.458273 -1.6, 0.0, 0.8823, 0.423739 -2.0, 0.0, 0.8823, 0.362646 -2.4, 0.0, 0.8823, 0.311562 -2.8, 0.0, 0.8823, 0.270245 -0.0, 0.0, 1.0494, 0.550644 -0.2, 0.0, 1.0494, 0.674687 -0.4, 0.0, 1.0494, 0.68984 -0.6, 0.0, 1.0494, 0.656975 -0.8, 0.0, 1.0494, 0.628747 -1.0, 0.0, 1.0494, 0.589171 -1.2, 0.0, 1.0494, 0.551827 -1.4, 0.0, 1.0494, 0.517772 -1.6, 0.0, 1.0494, 0.481586 -2.0, 0.0, 1.0494, 0.419952 -2.4, 0.0, 1.0494, 0.364576 -2.8, 0.0, 1.0494, 0.318111 -0.0, 0.0, 1.2166, 0.439453 -0.2, 0.0, 1.2166, 0.692238 -0.4, 0.0, 1.2166, 0.726767 -0.6, 0.0, 1.2166, 0.690066 -0.8, 0.0, 1.2166, 0.666318 -1.0, 0.0, 1.2166, 0.63358 -1.2, 0.0, 1.2166, 0.599146 -1.4, 0.0, 1.2166, 0.564195 -1.6, 0.0, 1.2166, 0.531366 -2.0, 0.0, 1.2166, 0.471772 -2.4, 0.0, 1.2166, 0.414529 -2.8, 0.0, 1.2166, 0.364169 -0.0, 0.0, 1.3837, 0.325011 -0.2, 0.0, 1.3837, 0.709789 -0.4, 0.0, 1.3837, 0.75688 -0.6, 0.0, 1.3837, 0.722315 -0.8, 0.0, 1.3837, 0.69239 -1.0, 0.0, 1.3837, 0.66975 -1.2, 0.0, 1.3837, 0.635255 -1.4, 0.0, 1.3837, 0.605501 -1.6, 0.0, 1.3837, 0.575087 -2.0, 0.0, 1.3837, 0.516929 -2.4, 0.0, 1.3837, 0.460329 -2.8, 0.0, 1.3837, 0.408155 -0.0, 0.0, 1.5509, 0.210569 -0.2, 0.0, 1.5509, 0.727339 -0.4, 0.0, 1.5509, 0.769496 -0.6, 0.0, 1.5509, 0.754055 -0.8, 0.0, 1.5509, 0.715055 -1.0, 0.0, 1.5509, 0.696096 -1.2, 0.0, 1.5509, 0.667957 -1.4, 0.0, 1.5509, 0.642314 -1.6, 0.0, 1.5509, 0.610222 -2.0, 0.0, 1.5509, 0.555857 -2.4, 0.0, 1.5509, 0.501971 -2.8, 0.0, 1.5509, 0.449725 -0.0, 0.0, 1.718, 0.096127 -0.2, 0.0, 1.718, 0.74489 -0.4, 0.0, 1.718, 0.775735 -0.6, 0.0, 1.718, 0.765359 -0.8, 0.0, 1.718, 0.738421 -1.0, 0.0, 1.718, 0.7136 -1.2, 0.0, 1.718, 0.696094 -1.4, 0.0, 1.718, 0.668449 -1.6, 0.0, 1.718, 0.643122 -2.0, 0.0, 1.718, 0.589 -2.4, 0.0, 1.718, 0.538383 -2.8, 0.0, 1.718, 0.487828 -0.0, 0.0, 1.8852, -0.018315 -0.2, 0.0, 1.8852, 0.762441 -0.4, 0.0, 1.8852, 0.781974 -0.6, 0.0, 1.8852, 0.776662 -0.8, 0.0, 1.8852, 0.748482 -1.0, 0.0, 1.8852, 0.727936 -1.2, 0.0, 1.8852, 0.711712 -1.4, 0.0, 1.8852, 0.690797 -1.6, 0.0, 1.8852, 0.666296 -2.0, 0.0, 1.8852, 0.617565 -2.4, 0.0, 1.8852, 0.570733 -2.8, 0.0, 1.8852, 0.522422 -0.0, 0.0, 2.0523, -0.132757 -0.2, 0.0, 2.0523, 0.779992 -0.4, 0.0, 2.0523, 0.788214 -0.6, 0.0, 2.0523, 0.787966 -0.8, 0.0, 2.0523, 0.754657 -1.0, 0.0, 2.0523, 0.736096 -1.2, 0.0, 2.0523, 0.721107 -1.4, 0.0, 2.0523, 0.705706 -1.6, 0.0, 2.0523, 0.686994 -2.0, 0.0, 2.0523, 0.644894 -2.4, 0.0, 2.0523, 0.602184 -2.8, 0.0, 2.0523, 0.553482 -0.0, 0.0, 2.2195, -0.247199 -0.2, 0.0, 2.2195, 0.797542 -0.4, 0.0, 2.2195, 0.794453 -0.6, 0.0, 2.2195, 0.799269 -0.8, 0.0, 2.2195, 0.760832 -1.0, 0.0, 2.2195, 0.740302 -1.2, 0.0, 2.2195, 0.730186 -1.4, 0.0, 2.2195, 0.720616 -1.6, 0.0, 2.2195, 0.700047 -2.0, 0.0, 2.2195, 0.672223 -2.4, 0.0, 2.2195, 0.633636 -2.8, 0.0, 2.2195, 0.581251 -0.0, 0.0, 2.3866, -0.361641 -0.2, 0.0, 2.3866, 0.815093 -0.4, 0.0, 2.3866, 0.800692 -0.6, 0.0, 2.3866, 0.810573 -0.8, 0.0, 2.3866, 0.767008 -1.0, 0.0, 2.3866, 0.744509 -1.2, 0.0, 2.3866, 0.739265 -1.4, 0.0, 2.3866, 0.735525 -1.6, 0.0, 2.3866, 0.7131 -2.0, 0.0, 2.3866, 0.699552 -2.4, 0.0, 2.3866, 0.665087 -2.8, 0.0, 2.3866, 0.6061 -0.0, 0.25, 0.0465, 0.122634 -0.2, 0.25, 0.0465, 0.095985 -0.4, 0.25, 0.0465, 0.066562 -0.6, 0.25, 0.0465, 0.044919 -0.8, 0.25, 0.0465, 0.040928 -1.0, 0.25, 0.0465, 0.026127 -1.2, 0.25, 0.0465, 0.023982 -1.4, 0.25, 0.0465, 0.015 -1.6, 0.25, 0.0465, 0.003438 -2.0, 0.25, 0.0465, 0.003328 -2.4, 0.25, 0.0465, -0.000759 -2.8, 0.25, 0.0465, -0.006488 -0.0, 0.25, 0.2137, 0.334586 -0.2, 0.25, 0.2137, 0.306967 -0.4, 0.25, 0.2137, 0.272467 -0.6, 0.25, 0.2137, 0.230461 -0.8, 0.25, 0.2137, 0.198847 -1.0, 0.25, 0.2137, 0.169543 -1.2, 0.25, 0.2137, 0.14786 -1.4, 0.25, 0.2137, 0.127271 -1.6, 0.25, 0.2137, 0.102498 -2.0, 0.25, 0.2137, 0.087057 -2.4, 0.25, 0.2137, 0.066929 -2.8, 0.25, 0.2137, 0.052326 -0.0, 0.25, 0.3808, 0.461205 -0.2, 0.25, 0.3808, 0.45162 -0.4, 0.25, 0.3808, 0.415794 -0.6, 0.25, 0.3808, 0.369702 -0.8, 0.25, 0.3808, 0.326128 -1.0, 0.25, 0.3808, 0.287241 -1.2, 0.25, 0.3808, 0.254097 -1.4, 0.25, 0.3808, 0.225627 -1.6, 0.25, 0.3808, 0.201559 -2.0, 0.25, 0.3808, 0.16052 -2.4, 0.25, 0.3808, 0.1331 -2.8, 0.25, 0.3808, 0.110613 -0.0, 0.25, 0.548, 0.534579 -0.2, 0.25, 0.548, 0.54768 -0.4, 0.25, 0.548, 0.518784 -0.6, 0.25, 0.548, 0.474087 -0.8, 0.25, 0.548, 0.430277 -1.0, 0.25, 0.548, 0.387471 -1.2, 0.25, 0.548, 0.347784 -1.4, 0.25, 0.548, 0.312717 -1.6, 0.25, 0.548, 0.281581 -2.0, 0.25, 0.548, 0.234311 -2.4, 0.25, 0.548, 0.196755 -2.8, 0.25, 0.548, 0.166748 -0.0, 0.25, 0.7151, 0.571583 -0.2, 0.25, 0.7151, 0.602153 -0.4, 0.25, 0.7151, 0.591597 -0.6, 0.25, 0.7151, 0.553517 -0.8, 0.25, 0.7151, 0.511769 -1.0, 0.25, 0.7151, 0.47011 -1.2, 0.25, 0.7151, 0.428481 -1.4, 0.25, 0.7151, 0.390349 -1.6, 0.25, 0.7151, 0.355478 -2.0, 0.25, 0.7151, 0.300715 -2.4, 0.25, 0.7151, 0.256006 -2.8, 0.25, 0.7151, 0.220462 -0.0, 0.25, 0.8823, 0.584088 -0.2, 0.25, 0.8823, 0.645651 -0.4, 0.25, 0.8823, 0.643189 -0.6, 0.25, 0.8823, 0.613761 -0.8, 0.25, 0.8823, 0.576476 -1.0, 0.25, 0.8823, 0.535848 -1.2, 0.25, 0.8823, 0.495633 -1.4, 0.25, 0.8823, 0.458273 -1.6, 0.25, 0.8823, 0.423739 -2.0, 0.25, 0.8823, 0.362646 -2.4, 0.25, 0.8823, 0.311562 -2.8, 0.25, 0.8823, 0.270245 -0.0, 0.25, 1.0494, 0.550644 -0.2, 0.25, 1.0494, 0.674687 -0.4, 0.25, 1.0494, 0.68984 -0.6, 0.25, 1.0494, 0.656975 -0.8, 0.25, 1.0494, 0.628747 -1.0, 0.25, 1.0494, 0.589171 -1.2, 0.25, 1.0494, 0.551827 -1.4, 0.25, 1.0494, 0.517772 -1.6, 0.25, 1.0494, 0.481586 -2.0, 0.25, 1.0494, 0.419952 -2.4, 0.25, 1.0494, 0.364576 -2.8, 0.25, 1.0494, 0.318111 -0.0, 0.25, 1.2166, 0.439453 -0.2, 0.25, 1.2166, 0.692238 -0.4, 0.25, 1.2166, 0.726767 -0.6, 0.25, 1.2166, 0.690066 -0.8, 0.25, 1.2166, 0.666318 -1.0, 0.25, 1.2166, 0.63358 -1.2, 0.25, 1.2166, 0.599146 -1.4, 0.25, 1.2166, 0.564195 -1.6, 0.25, 1.2166, 0.531366 -2.0, 0.25, 1.2166, 0.471772 -2.4, 0.25, 1.2166, 0.414529 -2.8, 0.25, 1.2166, 0.364169 -0.0, 0.25, 1.3837, 0.325011 -0.2, 0.25, 1.3837, 0.709789 -0.4, 0.25, 1.3837, 0.75688 -0.6, 0.25, 1.3837, 0.722315 -0.8, 0.25, 1.3837, 0.69239 -1.0, 0.25, 1.3837, 0.66975 -1.2, 0.25, 1.3837, 0.635255 -1.4, 0.25, 1.3837, 0.605501 -1.6, 0.25, 1.3837, 0.575087 -2.0, 0.25, 1.3837, 0.516929 -2.4, 0.25, 1.3837, 0.460329 -2.8, 0.25, 1.3837, 0.408155 -0.0, 0.25, 1.5509, 0.210569 -0.2, 0.25, 1.5509, 0.727339 -0.4, 0.25, 1.5509, 0.769496 -0.6, 0.25, 1.5509, 0.754055 -0.8, 0.25, 1.5509, 0.715055 -1.0, 0.25, 1.5509, 0.696096 -1.2, 0.25, 1.5509, 0.667957 -1.4, 0.25, 1.5509, 0.642314 -1.6, 0.25, 1.5509, 0.610222 -2.0, 0.25, 1.5509, 0.555857 -2.4, 0.25, 1.5509, 0.501971 -2.8, 0.25, 1.5509, 0.449725 -0.0, 0.25, 1.718, 0.096127 -0.2, 0.25, 1.718, 0.74489 -0.4, 0.25, 1.718, 0.775735 -0.6, 0.25, 1.718, 0.765359 -0.8, 0.25, 1.718, 0.738421 -1.0, 0.25, 1.718, 0.7136 -1.2, 0.25, 1.718, 0.696094 -1.4, 0.25, 1.718, 0.668449 -1.6, 0.25, 1.718, 0.643122 -2.0, 0.25, 1.718, 0.589 -2.4, 0.25, 1.718, 0.538383 -2.8, 0.25, 1.718, 0.487828 -0.0, 0.25, 1.8852, -0.018315 -0.2, 0.25, 1.8852, 0.762441 -0.4, 0.25, 1.8852, 0.781974 -0.6, 0.25, 1.8852, 0.776662 -0.8, 0.25, 1.8852, 0.748482 -1.0, 0.25, 1.8852, 0.727936 -1.2, 0.25, 1.8852, 0.711712 -1.4, 0.25, 1.8852, 0.690797 -1.6, 0.25, 1.8852, 0.666296 -2.0, 0.25, 1.8852, 0.617565 -2.4, 0.25, 1.8852, 0.570733 -2.8, 0.25, 1.8852, 0.522422 -0.0, 0.25, 2.0523, -0.132757 -0.2, 0.25, 2.0523, 0.779992 -0.4, 0.25, 2.0523, 0.788214 -0.6, 0.25, 2.0523, 0.787966 -0.8, 0.25, 2.0523, 0.754657 -1.0, 0.25, 2.0523, 0.736096 -1.2, 0.25, 2.0523, 0.721107 -1.4, 0.25, 2.0523, 0.705706 -1.6, 0.25, 2.0523, 0.686994 -2.0, 0.25, 2.0523, 0.644894 -2.4, 0.25, 2.0523, 0.602184 -2.8, 0.25, 2.0523, 0.553482 -0.0, 0.25, 2.2195, -0.247199 -0.2, 0.25, 2.2195, 0.797542 -0.4, 0.25, 2.2195, 0.794453 -0.6, 0.25, 2.2195, 0.799269 -0.8, 0.25, 2.2195, 0.760832 -1.0, 0.25, 2.2195, 0.740302 -1.2, 0.25, 2.2195, 0.730186 -1.4, 0.25, 2.2195, 0.720616 -1.6, 0.25, 2.2195, 0.700047 -2.0, 0.25, 2.2195, 0.672223 -2.4, 0.25, 2.2195, 0.633636 -2.8, 0.25, 2.2195, 0.581251 -0.0, 0.25, 2.3866, -0.361641 -0.2, 0.25, 2.3866, 0.815093 -0.4, 0.25, 2.3866, 0.800692 -0.6, 0.25, 2.3866, 0.810573 -0.8, 0.25, 2.3866, 0.767008 -1.0, 0.25, 2.3866, 0.744509 -1.2, 0.25, 2.3866, 0.739265 -1.4, 0.25, 2.3866, 0.735525 -1.6, 0.25, 2.3866, 0.7131 -2.0, 0.25, 2.3866, 0.699552 -2.4, 0.25, 2.3866, 0.665087 -2.8, 0.25, 2.3866, 0.6061 -2.0, 0.55, 0.1943, 0.095051 -2.2, 0.55, 0.1943, 0.071348 -2.4, 0.55, 0.1943, 0.084495 -2.6, 0.55, 0.1943, 0.04935 -2.8, 0.55, 0.1943, 0.042556 -3.0, 0.55, 0.1943, 0.036789 -3.2, 0.55, 0.1943, 0.0291 -3.4, 0.55, 0.1943, 0.024314 -2.0, 0.55, 0.3671, 0.165081 -2.2, 0.55, 0.3671, 0.143396 -2.4, 0.55, 0.3671, 0.140262 -2.6, 0.55, 0.3671, 0.116429 -2.8, 0.55, 0.3671, 0.104972 -3.0, 0.55, 0.3671, 0.094598 -3.2, 0.55, 0.3671, 0.084901 -3.4, 0.55, 0.3671, 0.075708 -2.0, 0.55, 0.5399, 0.23511 -2.2, 0.55, 0.5399, 0.214859 -2.4, 0.55, 0.5399, 0.196642 -2.6, 0.55, 0.5399, 0.180371 -2.8, 0.55, 0.5399, 0.165257 -3.0, 0.55, 0.5399, 0.15181 -3.2, 0.55, 0.5399, 0.138861 -3.4, 0.55, 0.5399, 0.127103 -2.0, 0.55, 0.7127, 0.303485 -2.2, 0.55, 0.7127, 0.280226 -2.4, 0.55, 0.7127, 0.259289 -2.6, 0.55, 0.7127, 0.24039 -2.8, 0.55, 0.7127, 0.222216 -3.0, 0.55, 0.7127, 0.206041 -3.2, 0.55, 0.7127, 0.19044 -3.4, 0.55, 0.7127, 0.176114 -2.0, 0.55, 0.8855, 0.367171 -2.2, 0.55, 0.8855, 0.340886 -2.4, 0.55, 0.8855, 0.317341 -2.6, 0.55, 0.8855, 0.296258 -2.8, 0.55, 0.8855, 0.275915 -3.0, 0.55, 0.8855, 0.257375 -3.2, 0.55, 0.8855, 0.239678 -3.4, 0.55, 0.8855, 0.223209 -2.0, 0.55, 1.0583, 0.426518 -2.2, 0.55, 1.0583, 0.398307 -2.4, 0.55, 1.0583, 0.372074 -2.6, 0.55, 1.0583, 0.348642 -2.8, 0.55, 1.0583, 0.326551 -3.0, 0.55, 1.0583, 0.306085 -3.2, 0.55, 1.0583, 0.287021 -3.4, 0.55, 1.0583, 0.268568 -2.0, 0.55, 1.2311, 0.481744 -2.2, 0.55, 1.2311, 0.45193 -2.4, 0.55, 1.2311, 0.424074 -2.6, 0.55, 1.2311, 0.398655 -2.8, 0.55, 1.2311, 0.374667 -3.0, 0.55, 1.2311, 0.352496 -3.2, 0.55, 1.2311, 0.331617 -3.4, 0.55, 1.2311, 0.312453 -2.0, 0.55, 1.4039, 0.534008 -2.2, 0.55, 1.4039, 0.502094 -2.4, 0.55, 1.4039, 0.473089 -2.6, 0.55, 1.4039, 0.446355 -2.8, 0.55, 1.4039, 0.420795 -3.0, 0.55, 1.4039, 0.388187 -3.2, 0.55, 1.4039, 0.374658 -3.4, 0.55, 1.4039, 0.353868 -2.0, 0.55, 1.5768, 0.582501 -2.2, 0.55, 1.5768, 0.549919 -2.4, 0.55, 1.5768, 0.519217 -2.6, 0.55, 1.5768, 0.491355 -2.8, 0.55, 1.5768, 0.465026 -3.0, 0.55, 1.5768, 0.409649 -3.2, 0.55, 1.5768, 0.416324 -3.4, 0.55, 1.5768, 0.393655 -2.0, 0.55, 1.7496, 0.629046 -2.2, 0.55, 1.7496, 0.594429 -2.4, 0.55, 1.7496, 0.563787 -2.6, 0.55, 1.7496, 0.533867 -2.8, 0.55, 1.7496, 0.506669 -3.0, 0.55, 1.7496, 0.43111 -3.2, 0.55, 1.7496, 0.456303 -3.4, 0.55, 1.7496, 0.43261 -2.0, 0.55, 1.9224, 0.680686 -2.2, 0.55, 1.9224, 0.636503 -2.4, 0.55, 1.9224, 0.608102 -2.6, 0.55, 1.9224, 0.576217 -2.8, 0.55, 1.9224, 0.546231 -3.0, 0.55, 1.9224, 0.503909 -3.2, 0.55, 1.9224, 0.494194 -3.4, 0.55, 1.9224, 0.470156 -2.0, 0.55, 2.0952, 0.732326 -2.2, 0.55, 2.0952, 0.678577 -2.4, 0.55, 2.0952, 0.652417 -2.6, 0.55, 2.0952, 0.618566 -2.8, 0.55, 2.0952, 0.585606 -3.0, 0.55, 2.0952, 0.55667 -3.2, 0.55, 2.0952, 0.530669 -3.4, 0.55, 2.0952, 0.506565 -2.0, 0.55, 2.268, 0.783966 -2.2, 0.55, 2.268, 0.72065 -2.4, 0.55, 2.268, 0.696732 -2.6, 0.55, 2.268, 0.660915 -2.8, 0.55, 2.268, 0.624981 -3.0, 0.55, 2.268, 0.592957 -3.2, 0.55, 2.268, 0.565809 -3.4, 0.55, 2.268, 0.540246 -2.0, 0.55, 2.4408, 0.835606 -2.2, 0.55, 2.4408, 0.762724 -2.4, 0.55, 2.4408, 0.741046 -2.6, 0.55, 2.4408, 0.703264 -2.8, 0.55, 2.4408, 0.664356 -3.0, 0.55, 2.4408, 0.629244 -3.2, 0.55, 2.4408, 0.601095 -3.4, 0.55, 2.4408, 0.572992 -2.0, 0.55, 2.6136, 0.887247 -2.2, 0.55, 2.6136, 0.804798 -2.4, 0.55, 2.6136, 0.785361 -2.6, 0.55, 2.6136, 0.745613 -2.8, 0.55, 2.6136, 0.703731 -3.0, 0.55, 2.6136, 0.665532 -3.2, 0.55, 2.6136, 0.636383 -3.4, 0.55, 2.6136, 0.605 -2.2, 0.6, 0.1965, 0.082777 -2.4, 0.6, 0.1965, 0.063291 -2.6, 0.6, 0.1965, 0.050137 -2.8, 0.6, 0.1965, 0.04336 -3.0, 0.6, 0.1965, 0.03741 -3.2, 0.6, 0.1965, 0.0277 -3.4, 0.6, 0.1965, 0.024935 -3.6, 0.6, 0.1965, 0.017674 -2.2, 0.6, 0.3801, 0.153398 -2.4, 0.6, 0.3801, 0.134668 -2.6, 0.6, 0.3801, 0.121356 -2.8, 0.6, 0.3801, 0.109602 -3.0, 0.6, 0.3801, 0.0988 -3.2, 0.6, 0.3801, 0.086876 -3.4, 0.6, 0.3801, 0.079452 -3.6, 0.6, 0.3801, 0.070116 -2.2, 0.6, 0.5637, 0.224019 -2.4, 0.6, 0.5637, 0.205456 -2.6, 0.6, 0.5637, 0.188873 -2.8, 0.6, 0.5637, 0.173269 -3.0, 0.6, 0.5637, 0.159221 -3.2, 0.6, 0.5637, 0.145387 -3.4, 0.6, 0.5637, 0.133872 -3.6, 0.6, 0.5637, 0.121578 -2.2, 0.6, 0.7473, 0.292555 -2.4, 0.6, 0.7473, 0.271166 -2.6, 0.6, 0.7473, 0.25177 -2.8, 0.6, 0.7473, 0.233184 -3.0, 0.6, 0.7473, 0.216286 -3.2, 0.6, 0.7473, 0.200275 -3.4, 0.6, 0.7473, 0.185717 -3.6, 0.6, 0.7473, 0.171648 -2.2, 0.6, 0.931, 0.356123 -2.4, 0.6, 0.931, 0.331904 -2.6, 0.6, 0.931, 0.310002 -2.8, 0.6, 0.931, 0.289411 -3.0, 0.6, 0.931, 0.270575 -3.2, 0.6, 0.931, 0.251972 -3.4, 0.6, 0.931, 0.235012 -3.6, 0.6, 0.931, 0.218814 -2.2, 0.6, 1.1146, 0.415047 -2.4, 0.6, 1.1146, 0.389307 -2.6, 0.6, 1.1146, 0.364888 -2.8, 0.6, 1.1146, 0.342314 -3.0, 0.6, 1.1146, 0.321483 -3.2, 0.6, 1.1146, 0.301686 -3.4, 0.6, 1.1146, 0.282614 -3.6, 0.6, 1.1146, 0.264782 -2.2, 0.6, 1.2982, 0.467139 -2.4, 0.6, 1.2982, 0.4435 -2.6, 0.6, 1.2982, 0.417089 -2.8, 0.6, 1.2982, 0.392629 -3.0, 0.6, 1.2982, 0.371077 -3.2, 0.6, 1.2982, 0.348568 -3.4, 0.6, 1.2982, 0.329055 -3.6, 0.6, 1.2982, 0.309485 -2.2, 0.6, 1.4818, 0.523202 -2.4, 0.6, 1.4818, 0.494257 -2.6, 0.6, 1.4818, 0.466574 -2.8, 0.6, 1.4818, 0.440732 -3.0, 0.6, 1.4818, 0.416591 -3.2, 0.6, 1.4818, 0.393115 -3.4, 0.6, 1.4818, 0.371643 -3.6, 0.6, 1.4818, 0.350791 -2.2, 0.6, 1.6654, 0.572961 -2.4, 0.6, 1.6654, 0.541895 -2.6, 0.6, 1.6654, 0.513242 -2.8, 0.6, 1.6654, 0.486389 -3.0, 0.6, 1.6654, 0.460847 -3.2, 0.6, 1.6654, 0.436458 -3.4, 0.6, 1.6654, 0.415498 -3.6, 0.6, 1.6654, 0.391393 -2.2, 0.6, 1.849, 0.618348 -2.4, 0.6, 1.849, 0.588873 -2.6, 0.6, 1.849, 0.557886 -2.8, 0.6, 1.849, 0.529488 -3.0, 0.6, 1.849, 0.503149 -3.2, 0.6, 1.849, 0.478407 -3.4, 0.6, 1.849, 0.460166 -3.6, 0.6, 1.849, 0.431296 -2.2, 0.6, 2.0326, 0.662625 -2.4, 0.6, 2.0326, 0.635852 -2.6, 0.6, 2.0326, 0.60253 -2.8, 0.6, 2.0326, 0.570845 -3.0, 0.6, 2.0326, 0.543546 -3.2, 0.6, 2.0326, 0.517791 -3.4, 0.6, 2.0326, 0.494837 -3.6, 0.6, 2.0326, 0.469079 -2.2, 0.6, 2.2163, 0.706901 -2.4, 0.6, 2.2163, 0.682831 -2.6, 0.6, 2.2163, 0.647175 -2.8, 0.6, 2.2163, 0.612203 -3.0, 0.6, 2.2163, 0.581799 -3.2, 0.6, 2.2163, 0.555153 -3.4, 0.6, 2.2163, 0.530052 -3.6, 0.6, 2.2163, 0.505772 -2.2, 0.6, 2.3999, 0.751178 -2.4, 0.6, 2.3999, 0.729809 -2.6, 0.6, 2.3999, 0.691819 -2.8, 0.6, 2.3999, 0.653561 -3.0, 0.6, 2.3999, 0.620052 -3.2, 0.6, 2.3999, 0.591663 -3.4, 0.6, 2.3999, 0.565394 -3.6, 0.6, 2.3999, 0.540336 -2.2, 0.6, 2.5835, 0.795454 -2.4, 0.6, 2.5835, 0.776788 -2.6, 0.6, 2.5835, 0.736463 -2.8, 0.6, 2.5835, 0.694919 -3.0, 0.6, 2.5835, 0.658305 -3.2, 0.6, 2.5835, 0.627654 -3.4, 0.6, 2.5835, 0.599255 -3.6, 0.6, 2.5835, 0.573576 -2.2, 0.6, 2.7671, 0.839731 -2.4, 0.6, 2.7671, 0.823766 -2.6, 0.6, 2.7671, 0.781107 -2.8, 0.6, 2.7671, 0.736277 -3.0, 0.6, 2.7671, 0.696558 -3.2, 0.6, 2.7671, 0.663645 -3.4, 0.6, 2.7671, 0.633116 -3.6, 0.6, 2.7671, 0.606 -2.4, 0.65, 0.1988, 0.0646 -2.6, 0.65, 0.1988, 0.051141 -2.8, 0.65, 0.1988, 0.044082 -3.0, 0.65, 0.1988, 0.038172 -3.2, 0.65, 0.1988, 0.0303 -3.4, 0.65, 0.1988, 0.025509 -3.6, 0.65, 0.1988, 0.017231 -3.8, 0.65, 0.1988, 0.014182 -2.4, 0.65, 0.419, 0.149797 -2.6, 0.65, 0.419, 0.136186 -2.8, 0.65, 0.419, 0.123546 -3.0, 0.65, 0.419, 0.111668 -3.2, 0.65, 0.419, 0.101227 -3.4, 0.65, 0.419, 0.090842 -3.6, 0.65, 0.419, 0.080751 -3.8, 0.65, 0.419, 0.071806 -2.4, 0.65, 0.6391, 0.232833 -2.6, 0.65, 0.6391, 0.215617 -2.8, 0.65, 0.6391, 0.198403 -3.0, 0.65, 0.6391, 0.182684 -3.2, 0.65, 0.6391, 0.169023 -3.4, 0.65, 0.6391, 0.155019 -3.6, 0.65, 0.6391, 0.141856 -3.8, 0.65, 0.6391, 0.129429 -2.4, 0.65, 0.8593, 0.308646 -2.6, 0.65, 0.8593, 0.288255 -2.8, 0.65, 0.8593, 0.267931 -3.0, 0.65, 0.8593, 0.249188 -3.2, 0.65, 0.8593, 0.232202 -3.4, 0.65, 0.8593, 0.216101 -3.6, 0.65, 0.8593, 0.20018 -3.8, 0.65, 0.8593, 0.185312 -2.4, 0.65, 1.0795, 0.378135 -2.6, 0.65, 1.0795, 0.354365 -2.8, 0.65, 1.0795, 0.332832 -3.0, 0.65, 1.0795, 0.311499 -3.2, 0.65, 1.0795, 0.292263 -3.4, 0.65, 1.0795, 0.273701 -3.6, 0.65, 1.0795, 0.255937 -3.8, 0.65, 1.0795, 0.239092 -2.4, 0.65, 1.2996, 0.443359 -2.6, 0.65, 1.2996, 0.417532 -2.8, 0.65, 1.2996, 0.393798 -3.0, 0.65, 1.2996, 0.37006 -3.2, 0.65, 1.2996, 0.348693 -3.4, 0.65, 1.2996, 0.32906 -3.6, 0.65, 1.2996, 0.309425 -3.8, 0.65, 1.2996, 0.289531 -2.4, 0.65, 1.5198, 0.50398 -2.6, 0.65, 1.5198, 0.476151 -2.8, 0.65, 1.5198, 0.450132 -3.0, 0.65, 1.5198, 0.425682 -3.2, 0.65, 1.5198, 0.402471 -3.4, 0.65, 1.5198, 0.381151 -3.6, 0.65, 1.5198, 0.359062 -3.8, 0.65, 1.5198, 0.335254 -2.4, 0.65, 1.74, 0.560251 -2.6, 0.65, 1.74, 0.531119 -2.8, 0.65, 1.74, 0.503845 -3.0, 0.65, 1.74, 0.478165 -3.2, 0.65, 1.74, 0.453777 -3.4, 0.65, 1.74, 0.430482 -3.6, 0.65, 1.74, 0.407363 -3.8, 0.65, 1.74, 0.381386 -2.4, 0.65, 1.9601, 0.615385 -2.6, 0.65, 1.9601, 0.583506 -2.8, 0.65, 1.9601, 0.55421 -3.0, 0.65, 1.9601, 0.527534 -3.2, 0.65, 1.9601, 0.502146 -3.4, 0.65, 1.9601, 0.477689 -3.6, 0.65, 1.9601, 0.454343 -3.8, 0.65, 1.9601, 0.430581 -2.4, 0.65, 2.1803, 0.67052 -2.6, 0.65, 2.1803, 0.635396 -2.8, 0.65, 2.1803, 0.603297 -3.0, 0.65, 2.1803, 0.574261 -3.2, 0.65, 2.1803, 0.5478 -3.4, 0.65, 2.1803, 0.52296 -3.6, 0.65, 2.1803, 0.498733 -3.8, 0.65, 2.1803, 0.473638 -2.4, 0.65, 2.4004, 0.725654 -2.6, 0.65, 2.4004, 0.687286 -2.8, 0.65, 2.4004, 0.652385 -3.0, 0.65, 2.4004, 0.619868 -3.2, 0.65, 2.4004, 0.591937 -3.4, 0.65, 2.4004, 0.565392 -3.6, 0.65, 2.4004, 0.54016 -3.8, 0.65, 2.4004, 0.515289 -2.4, 0.65, 2.6206, 0.780789 -2.6, 0.65, 2.6206, 0.739176 -2.8, 0.65, 2.6206, 0.701473 -3.0, 0.65, 2.6206, 0.665475 -3.2, 0.65, 2.6206, 0.636074 -3.4, 0.65, 2.6206, 0.607824 -3.6, 0.65, 2.6206, 0.581187 -3.8, 0.65, 2.6206, 0.555929 -2.4, 0.65, 2.8408, 0.835923 -2.6, 0.65, 2.8408, 0.791066 -2.8, 0.65, 2.8408, 0.750561 -3.0, 0.65, 2.8408, 0.711082 -3.2, 0.65, 2.8408, 0.680212 -3.4, 0.65, 2.8408, 0.650255 -3.6, 0.65, 2.8408, 0.622215 -3.8, 0.65, 2.8408, 0.59269 -2.4, 0.65, 3.0609, 0.891057 -2.6, 0.65, 3.0609, 0.842956 -2.8, 0.65, 3.0609, 0.799649 -3.0, 0.65, 3.0609, 0.756689 -3.2, 0.65, 3.0609, 0.724349 -3.4, 0.65, 3.0609, 0.692687 -3.6, 0.65, 3.0609, 0.663243 -3.8, 0.65, 3.0609, 0.629162 -2.4, 0.65, 3.2811, 0.946192 -2.6, 0.65, 3.2811, 0.894846 -2.8, 0.65, 3.2811, 0.848737 -3.0, 0.65, 3.2811, 0.802295 -3.2, 0.65, 3.2811, 0.768486 -3.4, 0.65, 3.2811, 0.735119 -3.6, 0.65, 3.2811, 0.70427 -3.8, 0.65, 3.2811, 0.6654 -2.6, 0.7, 0.2019, 0.057422 -2.8, 0.7, 0.2019, 0.045251 -3.0, 0.7, 0.2019, 0.035573 -3.2, 0.7, 0.2019, 0.0312 -3.4, 0.7, 0.2019, 0.026212 -3.6, 0.7, 0.2019, 0.01884 -3.8, 0.7, 0.2019, 0.01863 -4.0, 0.7, 0.2019, 0.007229 -4.2, 0.7, 0.2019, -0.00021 -2.6, 0.7, 0.4143, 0.134532 -2.8, 0.7, 0.4143, 0.121564 -3.0, 0.7, 0.4143, 0.112426 -3.2, 0.7, 0.4143, 0.099495 -3.4, 0.7, 0.4143, 0.089202 -3.6, 0.7, 0.4143, 0.079332 -3.8, 0.7, 0.4143, 0.07072 -4.0, 0.7, 0.4143, 0.060543 -4.2, 0.7, 0.4143, 0.050923 -2.6, 0.7, 0.6267, 0.210844 -2.8, 0.7, 0.6267, 0.193987 -3.0, 0.7, 0.6267, 0.182135 -3.2, 0.7, 0.6267, 0.164963 -3.4, 0.7, 0.6267, 0.15085 -3.6, 0.7, 0.6267, 0.138227 -3.8, 0.7, 0.6267, 0.12281 -4.0, 0.7, 0.6267, 0.113858 -4.2, 0.7, 0.6267, 0.102056 -2.6, 0.7, 0.8392, 0.280777 -2.8, 0.7, 0.8392, 0.261699 -3.0, 0.7, 0.8392, 0.243057 -3.2, 0.7, 0.8392, 0.226179 -3.4, 0.7, 0.8392, 0.208382 -3.6, 0.7, 0.8392, 0.194922 -3.8, 0.7, 0.8392, 0.176527 -4.0, 0.7, 0.8392, 0.165679 -4.2, 0.7, 0.8392, 0.151711 -2.6, 0.7, 1.0516, 0.345646 -2.8, 0.7, 1.0516, 0.324324 -3.0, 0.7, 1.0516, 0.303706 -3.2, 0.7, 1.0516, 0.284337 -3.4, 0.7, 1.0516, 0.265725 -3.6, 0.7, 1.0516, 0.248775 -3.8, 0.7, 1.0516, 0.232366 -4.0, 0.7, 1.0516, 0.216063 -4.2, 0.7, 1.0516, 0.199785 -2.6, 0.7, 1.264, 0.406984 -2.8, 0.7, 1.264, 0.383203 -3.0, 0.7, 1.264, 0.360547 -3.2, 0.7, 1.264, 0.339358 -3.4, 0.7, 1.264, 0.319611 -3.6, 0.7, 1.264, 0.30027 -3.8, 0.7, 1.264, 0.281815 -4.0, 0.7, 1.264, 0.262995 -4.2, 0.7, 1.264, 0.24555 -2.6, 0.7, 1.4764, 0.464518 -2.8, 0.7, 1.4764, 0.439202 -3.0, 0.7, 1.4764, 0.414706 -3.2, 0.7, 1.4764, 0.391633 -3.4, 0.7, 1.4764, 0.37072 -3.6, 0.7, 1.4764, 0.349106 -3.8, 0.7, 1.4764, 0.329089 -4.0, 0.7, 1.4764, 0.309096 -4.2, 0.7, 1.4764, 0.290563 -2.6, 0.7, 1.6888, 0.5183 -2.8, 0.7, 1.6888, 0.491645 -3.0, 0.7, 1.6888, 0.466167 -3.2, 0.7, 1.6888, 0.441749 -3.4, 0.7, 1.6888, 0.419265 -3.6, 0.7, 1.6888, 0.395724 -3.8, 0.7, 1.6888, 0.374331 -4.0, 0.7, 1.6888, 0.354014 -4.2, 0.7, 1.6888, 0.333626 -2.6, 0.7, 1.9013, 0.569375 -2.8, 0.7, 1.9013, 0.541054 -3.0, 0.7, 1.9013, 0.514454 -3.2, 0.7, 1.9013, 0.489799 -3.4, 0.7, 1.9013, 0.465315 -3.6, 0.7, 1.9013, 0.440677 -3.8, 0.7, 1.9013, 0.418789 -4.0, 0.7, 1.9013, 0.396464 -4.2, 0.7, 1.9013, 0.375742 -2.6, 0.7, 2.1137, 0.617486 -2.8, 0.7, 2.1137, 0.588323 -3.0, 0.7, 2.1137, 0.56022 -3.2, 0.7, 2.1137, 0.534178 -3.4, 0.7, 2.1137, 0.509161 -3.6, 0.7, 2.1137, 0.484425 -3.8, 0.7, 2.1137, 0.4615 -4.0, 0.7, 2.1137, 0.437791 -4.2, 0.7, 2.1137, 0.415256 -2.6, 0.7, 2.3261, 0.665347 -2.8, 0.7, 2.3261, 0.635593 -3.0, 0.7, 2.3261, 0.600821 -3.2, 0.7, 2.3261, 0.576443 -3.4, 0.7, 2.3261, 0.550662 -3.6, 0.7, 2.3261, 0.52493 -3.8, 0.7, 2.3261, 0.50232 -4.0, 0.7, 2.3261, 0.478104 -4.2, 0.7, 2.3261, 0.454244 -2.6, 0.7, 2.5385, 0.713207 -2.8, 0.7, 2.5385, 0.682863 -3.0, 0.7, 2.5385, 0.641422 -3.2, 0.7, 2.5385, 0.618486 -3.4, 0.7, 2.5385, 0.590714 -3.6, 0.7, 2.5385, 0.560496 -3.8, 0.7, 2.5385, 0.540481 -4.0, 0.7, 2.5385, 0.51691 -4.2, 0.7, 2.5385, 0.49267 -2.6, 0.7, 2.751, 0.761068 -2.8, 0.7, 2.751, 0.730133 -3.0, 0.7, 2.751, 0.682023 -3.2, 0.7, 2.751, 0.660528 -3.4, 0.7, 2.751, 0.630051 -3.6, 0.7, 2.751, 0.600672 -3.8, 0.7, 2.751, 0.577365 -4.0, 0.7, 2.751, 0.553283 -4.2, 0.7, 2.751, 0.528695 -2.6, 0.7, 2.9634, 0.808929 -2.8, 0.7, 2.9634, 0.777403 -3.0, 0.7, 2.9634, 0.722624 -3.2, 0.7, 2.9634, 0.702571 -3.4, 0.7, 2.9634, 0.669389 -3.6, 0.7, 2.9634, 0.641153 -3.8, 0.7, 2.9634, 0.612482 -4.0, 0.7, 2.9634, 0.58759 -4.2, 0.7, 2.9634, 0.563587 -2.6, 0.7, 3.1758, 0.856789 -2.8, 0.7, 3.1758, 0.824673 -3.0, 0.7, 3.1758, 0.763224 -3.2, 0.7, 3.1758, 0.744614 -3.4, 0.7, 3.1758, 0.708726 -3.6, 0.7, 3.1758, 0.681634 -3.8, 0.7, 3.1758, 0.647599 -4.0, 0.7, 3.1758, 0.621 -4.2, 0.7, 3.1758, 0.598478 -2.8, 0.75, 0.2329, 0.05657 -3.0, 0.75, 0.2329, 0.045131 -3.2, 0.75, 0.2329, 0.044235 -3.4, 0.75, 0.2329, 0.035292 -3.6, 0.75, 0.2329, 0.0274 -3.8, 0.75, 0.2329, 0.02277 -4.0, 0.75, 0.2329, 0.014648 -4.2, 0.75, 0.2329, 0.007632 -4.4, 0.75, 0.2329, -0.000595 -2.8, 0.75, 0.4804, 0.144945 -3.0, 0.75, 0.4804, 0.137513 -3.2, 0.75, 0.4804, 0.119778 -3.4, 0.75, 0.4804, 0.108461 -3.6, 0.75, 0.4804, 0.090983 -3.8, 0.75, 0.4804, 0.087228 -4.0, 0.75, 0.4804, 0.076607 -4.2, 0.75, 0.4804, 0.065893 -4.4, 0.75, 0.4804, 0.056112 -2.8, 0.75, 0.728, 0.226204 -3.0, 0.75, 0.728, 0.211461 -3.2, 0.75, 0.728, 0.194192 -3.4, 0.75, 0.728, 0.179193 -3.6, 0.75, 0.728, 0.163055 -3.8, 0.75, 0.728, 0.151687 -4.0, 0.75, 0.728, 0.138566 -4.2, 0.75, 0.728, 0.124154 -4.4, 0.75, 0.728, 0.112818 -2.8, 0.75, 0.9755, 0.301561 -3.0, 0.75, 0.9755, 0.282465 -3.2, 0.75, 0.9755, 0.263404 -3.4, 0.75, 0.9755, 0.245733 -3.6, 0.75, 0.9755, 0.228946 -3.8, 0.75, 0.9755, 0.212905 -4.0, 0.75, 0.9755, 0.197301 -4.2, 0.75, 0.9755, 0.181239 -4.4, 0.75, 0.9755, 0.166801 -2.8, 0.75, 1.2231, 0.371143 -3.0, 0.75, 1.2231, 0.349669 -3.2, 0.75, 1.2231, 0.328637 -3.4, 0.75, 1.2231, 0.308795 -3.6, 0.75, 1.2231, 0.28914 -3.8, 0.75, 1.2231, 0.27152 -4.0, 0.75, 1.2231, 0.253381 -4.2, 0.75, 1.2231, 0.236229 -4.4, 0.75, 1.2231, 0.215149 -2.8, 0.75, 1.4706, 0.436835 -3.0, 0.75, 1.4706, 0.412805 -3.2, 0.75, 1.4706, 0.389659 -3.4, 0.75, 1.4706, 0.368615 -3.6, 0.75, 1.4706, 0.346546 -3.8, 0.75, 1.4706, 0.327372 -4.0, 0.75, 1.4706, 0.307358 -4.2, 0.75, 1.4706, 0.288416 -4.4, 0.75, 1.4706, 0.237918 -2.8, 0.75, 1.7182, 0.497859 -3.0, 0.75, 1.7182, 0.472752 -3.2, 0.75, 1.7182, 0.447146 -3.4, 0.75, 1.7182, 0.424492 -3.6, 0.75, 1.7182, 0.401578 -3.8, 0.75, 1.7182, 0.380005 -4.0, 0.75, 1.7182, 0.360748 -4.2, 0.75, 1.7182, 0.338667 -4.4, 0.75, 1.7182, 0.286849 -2.8, 0.75, 1.9657, 0.554716 -3.0, 0.75, 1.9657, 0.528032 -3.2, 0.75, 1.9657, 0.502776 -3.4, 0.75, 1.9657, 0.478361 -3.6, 0.75, 1.9657, 0.453378 -3.8, 0.75, 1.9657, 0.43082 -4.0, 0.75, 1.9657, 0.409375 -4.2, 0.75, 1.9657, 0.39154 -4.4, 0.75, 1.9657, 0.360591 -2.8, 0.75, 2.2132, 0.609468 -3.0, 0.75, 2.2132, 0.580434 -3.2, 0.75, 2.2132, 0.55384 -3.4, 0.75, 2.2132, 0.528285 -3.6, 0.75, 2.2132, 0.503617 -3.8, 0.75, 2.2132, 0.479512 -4.0, 0.75, 2.2132, 0.455722 -4.2, 0.75, 2.2132, 0.449955 -4.4, 0.75, 2.2132, 0.410322 -2.8, 0.75, 2.4608, 0.6642 -3.0, 0.75, 2.4608, 0.632836 -3.2, 0.75, 2.4608, 0.604904 -3.4, 0.75, 2.4608, 0.575453 -3.6, 0.75, 2.4608, 0.550292 -3.8, 0.75, 2.4608, 0.525573 -4.0, 0.75, 2.4608, 0.501128 -4.2, 0.75, 2.4608, 0.486949 -4.4, 0.75, 2.4608, 0.455027 -2.8, 0.75, 2.7083, 0.718931 -3.0, 0.75, 2.7083, 0.685238 -3.2, 0.75, 2.7083, 0.655968 -3.4, 0.75, 2.7083, 0.621203 -3.6, 0.75, 2.7083, 0.594506 -3.8, 0.75, 2.7083, 0.56794 -4.0, 0.75, 2.7083, 0.544309 -4.2, 0.75, 2.7083, 0.519824 -4.4, 0.75, 2.7083, 0.496362 -2.8, 0.75, 2.9559, 0.773663 -3.0, 0.75, 2.9559, 0.737639 -3.2, 0.75, 2.9559, 0.707032 -3.4, 0.75, 2.9559, 0.666535 -3.6, 0.75, 2.9559, 0.637817 -3.8, 0.75, 2.9559, 0.609912 -4.0, 0.75, 2.9559, 0.585641 -4.2, 0.75, 2.9559, 0.560674 -4.4, 0.75, 2.9559, 0.536369 -2.8, 0.75, 3.2034, 0.828394 -3.0, 0.75, 3.2034, 0.790041 -3.2, 0.75, 3.2034, 0.758096 -3.4, 0.75, 3.2034, 0.711867 -3.6, 0.75, 3.2034, 0.681127 -3.8, 0.75, 3.2034, 0.651847 -4.0, 0.75, 3.2034, 0.624267 -4.2, 0.75, 3.2034, 0.599079 -4.4, 0.75, 3.2034, 0.574783 -2.8, 0.75, 3.451, 0.883126 -3.0, 0.75, 3.451, 0.842443 -3.2, 0.75, 3.451, 0.80916 -3.4, 0.75, 3.451, 0.757199 -3.6, 0.75, 3.451, 0.724437 -3.8, 0.75, 3.451, 0.693781 -4.0, 0.75, 3.451, 0.662893 -4.2, 0.75, 3.451, 0.635875 -4.4, 0.75, 3.451, 0.610573 -2.8, 0.75, 3.6985, 0.937857 -3.0, 0.75, 3.6985, 0.894845 -3.2, 0.75, 3.6985, 0.860223 -3.4, 0.75, 3.6985, 0.802531 -3.6, 0.75, 3.6985, 0.767747 -3.8, 0.75, 3.6985, 0.735715 -4.0, 0.75, 3.6985, 0.701519 -4.2, 0.75, 3.6985, 0.67267 -4.4, 0.75, 3.6985, 0.6454 -2.8, 0.8, 0.1324, 0.020882 -3.0, 0.8, 0.1324, 0.0132 -3.2, 0.8, 0.1324, 0.008737 -3.4, 0.8, 0.1324, 0.006144 -3.6, 0.8, 0.1324, -0.001478 -3.8, 0.8, 0.1324, -0.002662 -4.0, 0.8, 0.1324, -0.010844 -2.8, 0.8, 0.3493, 0.097679 -3.0, 0.8, 0.3493, 0.088055 -3.2, 0.8, 0.3493, 0.078083 -3.4, 0.8, 0.3493, 0.06972 -3.6, 0.8, 0.3493, 0.059986 -3.8, 0.8, 0.3493, 0.053252 -4.0, 0.8, 0.3493, 0.04323 -2.8, 0.8, 0.5662, 0.172739 -3.0, 0.8, 0.5662, 0.159487 -3.2, 0.8, 0.5662, 0.145541 -3.4, 0.8, 0.5662, 0.133296 -3.6, 0.8, 0.5662, 0.120902 -3.8, 0.8, 0.5662, 0.109167 -4.0, 0.8, 0.5662, 0.097304 -2.8, 0.8, 0.7832, 0.242396 -3.0, 0.8, 0.7832, 0.225694 -3.2, 0.8, 0.7832, 0.209422 -3.4, 0.8, 0.7832, 0.193829 -3.6, 0.8, 0.7832, 0.179296 -3.8, 0.8, 0.7832, 0.165082 -4.0, 0.8, 0.7832, 0.151114 -2.8, 0.8, 1.0001, 0.307342 -3.0, 0.8, 1.0001, 0.288178 -3.2, 0.8, 1.0001, 0.269515 -3.4, 0.8, 1.0001, 0.251438 -3.6, 0.8, 1.0001, 0.234194 -3.8, 0.8, 1.0001, 0.217884 -4.0, 0.8, 1.0001, 0.201995 -2.8, 0.8, 1.217, 0.367938 -3.0, 0.8, 1.217, 0.346721 -3.2, 0.8, 1.217, 0.326686 -3.4, 0.8, 1.217, 0.306308 -3.6, 0.8, 1.217, 0.286895 -3.8, 0.8, 1.217, 0.26843 -4.0, 0.8, 1.217, 0.251119 -2.8, 0.8, 1.4339, 0.425328 -3.0, 0.8, 1.4339, 0.402191 -3.2, 0.8, 1.4339, 0.380135 -3.4, 0.8, 1.4339, 0.358573 -3.6, 0.8, 1.4339, 0.337671 -3.8, 0.8, 1.4339, 0.316648 -4.0, 0.8, 1.4339, 0.298142 -2.8, 0.8, 1.6509, 0.479596 -3.0, 0.8, 1.6509, 0.454974 -3.2, 0.8, 1.6509, 0.431353 -3.4, 0.8, 1.6509, 0.408349 -3.6, 0.8, 1.6509, 0.385628 -3.8, 0.8, 1.6509, 0.364866 -4.0, 0.8, 1.6509, 0.343109 -2.8, 0.8, 1.8678, 0.530464 -3.0, 0.8, 1.8678, 0.504883 -3.2, 0.8, 1.8678, 0.480025 -3.4, 0.8, 1.8678, 0.456178 -3.6, 0.8, 1.8678, 0.432252 -3.8, 0.8, 1.8678, 0.409655 -4.0, 0.8, 1.8678, 0.387343 -2.8, 0.8, 2.0847, 0.57847 -3.0, 0.8, 2.0847, 0.55211 -3.2, 0.8, 2.0847, 0.526199 -3.4, 0.8, 2.0847, 0.501827 -3.6, 0.8, 2.0847, 0.477312 -3.8, 0.8, 2.0847, 0.45403 -4.0, 0.8, 2.0847, 0.429986 -2.8, 0.8, 2.3016, 0.624966 -3.0, 0.8, 2.3016, 0.597871 -3.2, 0.8, 2.3016, 0.570167 -3.4, 0.8, 2.3016, 0.544569 -3.6, 0.8, 2.3016, 0.51757 -3.8, 0.8, 2.3016, 0.495366 -4.0, 0.8, 2.3016, 0.471003 -2.8, 0.8, 2.5185, 0.671462 -3.0, 0.8, 2.5185, 0.643632 -3.2, 0.8, 2.5185, 0.612593 -3.4, 0.8, 2.5185, 0.585042 -3.6, 0.8, 2.5185, 0.557991 -3.8, 0.8, 2.5185, 0.535235 -4.0, 0.8, 2.5185, 0.509799 -2.8, 0.8, 2.7355, 0.717958 -3.0, 0.8, 2.7355, 0.689393 -3.2, 0.8, 2.7355, 0.655019 -3.4, 0.8, 2.7355, 0.624813 -3.6, 0.8, 2.7355, 0.598509 -3.8, 0.8, 2.7355, 0.572361 -4.0, 0.8, 2.7355, 0.547046 -2.8, 0.8, 2.9524, 0.764454 -3.0, 0.8, 2.9524, 0.735153 -3.2, 0.8, 2.9524, 0.697445 -3.4, 0.8, 2.9524, 0.664149 -3.6, 0.8, 2.9524, 0.639027 -3.8, 0.8, 2.9524, 0.608752 -4.0, 0.8, 2.9524, 0.583631 -2.8, 0.8, 3.1693, 0.81095 -3.0, 0.8, 3.1693, 0.780914 -3.2, 0.8, 3.1693, 0.739871 -3.4, 0.8, 3.1693, 0.703485 -3.6, 0.8, 3.1693, 0.679545 -3.8, 0.8, 3.1693, 0.6447 -4.0, 0.8, 3.1693, 0.620217 -2.8, 0.85, 0.1324, 0.020671 -3.0, 0.85, 0.1324, 0.013068 -3.2, 0.85, 0.1324, 0.0087 -3.4, 0.85, 0.1324, 0.006044 -3.6, 0.85, 0.1324, -0.001488 -3.8, 0.85, 0.1324, -0.002672 -4.0, 0.85, 0.1324, -0.010944 -2.8, 0.85, 0.3493, 0.0967 -3.0, 0.85, 0.3493, 0.08717 -3.2, 0.85, 0.3493, 0.0773 -3.4, 0.85, 0.3493, 0.069055 -3.6, 0.85, 0.3493, 0.0594 -3.8, 0.85, 0.3493, 0.052719 -4.0, 0.85, 0.3493, 0.0428 -2.8, 0.85, 0.5662, 0.170967 -3.0, 0.85, 0.5662, 0.15789 -3.2, 0.85, 0.5662, 0.144123 -3.4, 0.85, 0.5662, 0.132153 -3.6, 0.85, 0.5662, 0.119777 -3.8, 0.85, 0.5662, 0.108196 -4.0, 0.85, 0.5662, 0.096374 -2.8, 0.85, 0.7832, 0.240022 -3.0, 0.85, 0.7832, 0.223437 -3.2, 0.85, 0.7832, 0.207199 -3.4, 0.85, 0.7832, 0.191896 -3.6, 0.85, 0.7832, 0.17775 -3.8, 0.85, 0.7832, 0.163436 -4.0, 0.85, 0.7832, 0.149656 -2.8, 0.85, 1.0001, 0.304266 -3.0, 0.85, 1.0001, 0.285296 -3.2, 0.85, 1.0001, 0.266876 -3.4, 0.85, 1.0001, 0.248967 -3.6, 0.85, 1.0001, 0.231866 -3.8, 0.85, 1.0001, 0.215708 -4.0, 0.85, 1.0001, 0.200001 -2.8, 0.85, 1.217, 0.364275 -3.0, 0.85, 1.217, 0.343255 -3.2, 0.85, 1.217, 0.323419 -3.4, 0.85, 1.217, 0.303246 -3.6, 0.85, 1.217, 0.28413 -3.8, 0.85, 1.217, 0.265745 -4.0, 0.85, 1.217, 0.24868 -2.8, 0.85, 1.4339, 0.421276 -3.0, 0.85, 1.4339, 0.398178 -3.2, 0.85, 1.4339, 0.376339 -3.4, 0.85, 1.4339, 0.35498 -3.6, 0.85, 1.4339, 0.334293 -3.8, 0.85, 1.4339, 0.313335 -4.0, 0.85, 1.4339, 0.295161 -2.8, 0.85, 1.6509, 0.474804 -3.0, 0.85, 1.6509, 0.45045 -3.2, 0.85, 1.6509, 0.427088 -3.4, 0.85, 1.6509, 0.40427 -3.6, 0.85, 1.6509, 0.381774 -3.8, 0.85, 1.6509, 0.361255 -4.0, 0.85, 1.6509, 0.339679 -2.8, 0.85, 1.8678, 0.525195 -3.0, 0.85, 1.8678, 0.500001 -3.2, 0.85, 1.8678, 0.47525 -3.4, 0.85, 1.8678, 0.451687 -3.6, 0.85, 1.8678, 0.428199 -3.8, 0.85, 1.8678, 0.40565 -4.0, 0.85, 1.8678, 0.383466 -2.8, 0.85, 2.0847, 0.572715 -3.0, 0.85, 2.0847, 0.546678 -3.2, 0.85, 2.0847, 0.520938 -3.4, 0.85, 2.0847, 0.496832 -3.6, 0.85, 2.0847, 0.472539 -3.8, 0.85, 2.0847, 0.449556 -4.0, 0.85, 2.0847, 0.4257 -2.8, 0.85, 2.3016, 0.61875 -3.0, 0.85, 2.3016, 0.591895 -3.2, 0.85, 2.3016, 0.564498 -3.4, 0.85, 2.3016, 0.539125 -3.6, 0.85, 2.3016, 0.512394 -3.8, 0.85, 2.3016, 0.490446 -4.0, 0.85, 2.3016, 0.466785 -2.8, 0.85, 2.5185, 0.664785 -3.0, 0.85, 2.5185, 0.637263 -3.2, 0.85, 2.5185, 0.606474 -3.4, 0.85, 2.5185, 0.579249 -3.6, 0.85, 2.5185, 0.5524 -3.8, 0.85, 2.5185, 0.529898 -4.0, 0.85, 2.5185, 0.504702 -2.8, 0.85, 2.7355, 0.710815 -3.0, 0.85, 2.7355, 0.682506 -3.2, 0.85, 2.7355, 0.648549 -3.4, 0.85, 2.7355, 0.618602 -3.6, 0.85, 2.7355, 0.592641 -3.8, 0.85, 2.7355, 0.566676 -4.0, 0.85, 2.7355, 0.541629 -2.8, 0.85, 2.9524, 0.756806 -3.0, 0.85, 2.9524, 0.727848 -3.2, 0.85, 2.9524, 0.690525 -3.4, 0.85, 2.9524, 0.657585 -3.6, 0.85, 2.9524, 0.632719 -3.8, 0.85, 2.9524, 0.602712 -4.0, 0.85, 2.9524, 0.57816 -2.8, 0.85, 3.1693, 0.802396 -3.0, 0.85, 3.1693, 0.773111 -3.2, 0.85, 3.1693, 0.7326 -3.4, 0.85, 3.1693, 0.696465 -3.6, 0.85, 3.1693, 0.672804 -3.8, 0.85, 3.1693, 0.638253 -4.0, 0.85, 3.1693, 0.614025 diff --git a/aviary/models/propellers/general_aviation.prop b/aviary/models/propellers/general_aviation.prop deleted file mode 100644 index ed2f1d4bc8..0000000000 --- a/aviary/models/propellers/general_aviation.prop +++ /dev/null @@ -1,439 +0,0 @@ -# created 06/24/24 at 17:12 -# GASP propeller map converted from general_aviation.map -# CT = f(Helical Mach at 75% Radius, Adv ratio & CP) -# mach_type = helical_mach -# No. Blades = 3. CLi = 0.62 AF = 104.0 - - J, Helical_Mach, CP, CT -0.001, 0.7, 0.025, 0.1442 - 0.5, 0.7, 0.025, 0.0368 - 0.75, 0.7, 0.025, 0.0254 - 1.0, 0.7, 0.025, 0.0204 - 1.3, 0.7, 0.025, 0.0174 - 1.6, 0.7, 0.025, 0.0129 -0.001, 0.7, 0.05, 0.1595 - 0.5, 0.7, 0.05, 0.071 - 0.75, 0.7, 0.05, 0.0522 - 1.0, 0.7, 0.05, 0.0413 - 1.3, 0.7, 0.05, 0.0323 - 1.6, 0.7, 0.05, 0.0259 -0.001, 0.7, 0.075, 0.1762 - 0.5, 0.7, 0.075, 0.1001 - 0.75, 0.7, 0.075, 0.0766 - 1.0, 0.7, 0.075, 0.0615 - 1.3, 0.7, 0.075, 0.0491 - 1.6, 0.7, 0.075, 0.0404 -0.001, 0.7, 0.1, 0.1887 - 0.5, 0.7, 0.1, 0.1207 - 0.75, 0.7, 0.1, 0.0983 - 1.0, 0.7, 0.1, 0.0806 - 1.3, 0.7, 0.1, 0.0649 - 1.6, 0.7, 0.1, 0.054 -0.001, 0.7, 0.125, 0.1985 - 0.5, 0.7, 0.125, 0.1359 - 0.75, 0.7, 0.125, 0.1159 - 1.0, 0.7, 0.125, 0.0983 - 1.3, 0.7, 0.125, 0.0803 - 1.6, 0.7, 0.125, 0.0671 -0.001, 0.7, 0.15, 0.2075 - 0.5, 0.7, 0.15, 0.1464 - 0.75, 0.7, 0.15, 0.1298 - 1.0, 0.7, 0.15, 0.1135 - 1.3, 0.7, 0.15, 0.0949 - 1.6, 0.7, 0.15, 0.08 -0.001, 0.7, 0.175, 0.2179 - 0.5, 0.7, 0.175, 0.1542 - 0.75, 0.7, 0.175, 0.1404 - 1.0, 0.7, 0.175, 0.1261 - 1.3, 0.7, 0.175, 0.1082 - 1.6, 0.7, 0.175, 0.0923 -0.001, 0.7, 0.2, 0.2248 - 0.5, 0.7, 0.2, 0.1603 - 0.75, 0.7, 0.2, 0.1481 - 1.0, 0.7, 0.2, 0.1367 - 1.3, 0.7, 0.2, 0.12 - 1.6, 0.7, 0.2, 0.1041 -0.001, 0.7, 0.225, 0.2302 - 0.5, 0.7, 0.225, 0.1647 - 0.75, 0.7, 0.225, 0.1542 - 1.0, 0.7, 0.225, 0.1449 - 1.3, 0.7, 0.225, 0.1303 - 1.6, 0.7, 0.225, 0.1149 -0.001, 0.7, 0.25, 0.2346 - 0.5, 0.7, 0.25, 0.1677 - 0.75, 0.7, 0.25, 0.1591 - 1.0, 0.7, 0.25, 0.1513 - 1.3, 0.7, 0.25, 0.1392 - 1.6, 0.7, 0.25, 0.1247 -0.001, 0.7, 0.275, 0.2384 - 0.5, 0.7, 0.275, 0.1695 - 0.75, 0.7, 0.275, 0.1628 - 1.0, 0.7, 0.275, 0.1563 - 1.3, 0.7, 0.275, 0.1465 - 1.6, 0.7, 0.275, 0.1334 -0.001, 0.7, 0.3, 0.2418 - 0.5, 0.7, 0.3, 0.1707 - 0.75, 0.7, 0.3, 0.1653 - 1.0, 0.7, 0.3, 0.1605 - 1.3, 0.7, 0.3, 0.1521 - 1.6, 0.7, 0.3, 0.1412 -0.001, 0.75, 0.025, 0.1443 - 0.5, 0.75, 0.025, 0.0347 - 0.75, 0.75, 0.025, 0.0231 - 1.0, 0.75, 0.025, 0.0193 - 1.3, 0.75, 0.025, 0.0162 - 1.6, 0.75, 0.025, 0.0113 -0.001, 0.75, 0.05, 0.1609 - 0.5, 0.75, 0.05, 0.068 - 0.75, 0.75, 0.05, 0.0505 - 1.0, 0.75, 0.05, 0.0402 - 1.3, 0.75, 0.05, 0.0308 - 1.6, 0.75, 0.05, 0.0243 -0.001, 0.75, 0.075, 0.1784 - 0.5, 0.75, 0.075, 0.0978 - 0.75, 0.75, 0.075, 0.0742 - 1.0, 0.75, 0.075, 0.0596 - 1.3, 0.75, 0.075, 0.048 - 1.6, 0.75, 0.075, 0.0392 -0.001, 0.75, 0.1, 0.1907 - 0.5, 0.75, 0.1, 0.1205 - 0.75, 0.75, 0.1, 0.0962 - 1.0, 0.75, 0.1, 0.0785 - 1.3, 0.75, 0.1, 0.0631 - 1.6, 0.75, 0.1, 0.0528 -0.001, 0.75, 0.125, 0.2004 - 0.5, 0.75, 0.125, 0.1367 - 0.75, 0.75, 0.125, 0.1152 - 1.0, 0.75, 0.125, 0.0964 - 1.3, 0.75, 0.125, 0.0783 - 1.6, 0.75, 0.125, 0.0654 -0.001, 0.75, 0.15, 0.2091 - 0.5, 0.75, 0.15, 0.1473 - 0.75, 0.75, 0.15, 0.1302 - 1.0, 0.75, 0.15, 0.1125 - 1.3, 0.75, 0.15, 0.0929 - 1.6, 0.75, 0.15, 0.078 -0.001, 0.75, 0.175, 0.2171 - 0.5, 0.75, 0.175, 0.1553 - 0.75, 0.75, 0.175, 0.1412 - 1.0, 0.75, 0.175, 0.1261 - 1.3, 0.75, 0.175, 0.1066 - 1.6, 0.75, 0.175, 0.0904 -0.001, 0.75, 0.2, 0.2239 - 0.5, 0.75, 0.2, 0.1618 - 0.75, 0.75, 0.2, 0.149 - 1.0, 0.75, 0.2, 0.1373 - 1.3, 0.75, 0.2, 0.1192 - 1.6, 0.75, 0.2, 0.1022 -0.001, 0.75, 0.225, 0.2298 - 0.5, 0.75, 0.225, 0.1664 - 0.75, 0.75, 0.225, 0.1553 - 1.0, 0.75, 0.225, 0.1458 - 1.3, 0.75, 0.225, 0.1302 - 1.6, 0.75, 0.225, 0.1134 -0.001, 0.75, 0.25, 0.2351 - 0.5, 0.75, 0.25, 0.1694 - 0.75, 0.75, 0.25, 0.1606 - 1.0, 0.75, 0.25, 0.1522 - 1.3, 0.75, 0.25, 0.1397 - 1.6, 0.75, 0.25, 0.1238 -0.001, 0.75, 0.275, 0.2398 - 0.5, 0.75, 0.275, 0.1712 - 0.75, 0.75, 0.275, 0.1645 - 1.0, 0.75, 0.275, 0.1574 - 1.3, 0.75, 0.275, 0.1473 - 1.6, 0.75, 0.275, 0.1332 -0.001, 0.75, 0.3, 0.2441 - 0.5, 0.75, 0.3, 0.1722 - 0.75, 0.75, 0.3, 0.1669 - 1.0, 0.75, 0.3, 0.162 - 1.3, 0.75, 0.3, 0.153 - 1.6, 0.75, 0.3, 0.1415 -0.001, 0.8, 0.025, 0.1435 - 0.5, 0.8, 0.025, 0.0318 - 0.75, 0.8, 0.025, 0.0212 - 1.0, 0.8, 0.025, 0.0184 - 1.3, 0.8, 0.025, 0.0152 - 1.6, 0.8, 0.025, 0.011 -0.001, 0.8, 0.05, 0.1574 - 0.5, 0.8, 0.05, 0.065 - 0.75, 0.8, 0.05, 0.0487 - 1.0, 0.8, 0.05, 0.0384 - 1.3, 0.8, 0.05, 0.029 - 1.6, 0.8, 0.05, 0.0227 -0.001, 0.8, 0.075, 0.1758 - 0.5, 0.8, 0.075, 0.0943 - 0.75, 0.8, 0.075, 0.0718 - 1.0, 0.8, 0.075, 0.0578 - 1.3, 0.8, 0.075, 0.0466 - 1.6, 0.8, 0.075, 0.0376 -0.001, 0.8, 0.1, 0.189 - 0.5, 0.8, 0.1, 0.1168 - 0.75, 0.8, 0.1, 0.0934 - 1.0, 0.8, 0.1, 0.0763 - 1.3, 0.8, 0.1, 0.0614 - 1.6, 0.8, 0.1, 0.0514 -0.001, 0.8, 0.125, 0.199 - 0.5, 0.8, 0.125, 0.1337 - 0.75, 0.8, 0.125, 0.112 - 1.0, 0.8, 0.125, 0.0939 - 1.3, 0.8, 0.125, 0.0763 - 1.6, 0.8, 0.125, 0.0637 -0.001, 0.8, 0.15, 0.2076 - 0.5, 0.8, 0.15, 0.1448 - 0.75, 0.8, 0.15, 0.1271 - 1.0, 0.8, 0.15, 0.1096 - 1.3, 0.8, 0.15, 0.0907 - 1.6, 0.8, 0.15, 0.0761 -0.001, 0.8, 0.175, 0.2149 - 0.5, 0.8, 0.175, 0.1529 - 0.75, 0.8, 0.175, 0.1386 - 1.0, 0.8, 0.175, 0.1231 - 1.3, 0.8, 0.175, 0.1041 - 1.6, 0.8, 0.175, 0.0883 -0.001, 0.8, 0.2, 0.2217 - 0.5, 0.8, 0.2, 0.1597 - 0.75, 0.8, 0.2, 0.1467 - 1.0, 0.8, 0.2, 0.1345 - 1.3, 0.8, 0.2, 0.1164 - 1.6, 0.8, 0.2, 0.0999 -0.001, 0.8, 0.225, 0.228 - 0.5, 0.8, 0.225, 0.1647 - 0.75, 0.8, 0.225, 0.1531 - 1.0, 0.8, 0.225, 0.1433 - 1.3, 0.8, 0.225, 0.1273 - 1.6, 0.8, 0.225, 0.1108 -0.001, 0.8, 0.25, 0.2338 - 0.5, 0.8, 0.25, 0.1679 - 0.75, 0.8, 0.25, 0.1586 - 1.0, 0.8, 0.25, 0.1498 - 1.3, 0.8, 0.25, 0.1369 - 1.6, 0.8, 0.25, 0.121 -0.001, 0.8, 0.275, 0.2393 - 0.5, 0.8, 0.275, 0.1699 - 0.75, 0.8, 0.275, 0.1627 - 1.0, 0.8, 0.275, 0.1552 - 1.3, 0.8, 0.275, 0.1447 - 1.6, 0.8, 0.275, 0.1302 -0.001, 0.8, 0.3, 0.2443 - 0.5, 0.8, 0.3, 0.171 - 0.75, 0.8, 0.3, 0.1655 - 1.0, 0.8, 0.3, 0.1599 - 1.3, 0.8, 0.3, 0.1505 - 1.6, 0.8, 0.3, 0.1385 -0.001, 0.85, 0.025, 0.1234 - 0.5, 0.85, 0.025, 0.0282 - 0.75, 0.85, 0.025, 0.0199 - 1.0, 0.85, 0.025, 0.0176 - 1.3, 0.85, 0.025, 0.0145 - 1.6, 0.85, 0.025, 0.0108 -0.001, 0.85, 0.05, 0.1487 - 0.5, 0.85, 0.05, 0.0621 - 0.75, 0.85, 0.05, 0.0464 - 1.0, 0.85, 0.05, 0.0361 - 1.3, 0.85, 0.05, 0.0272 - 1.6, 0.85, 0.05, 0.0217 -0.001, 0.85, 0.075, 0.1677 - 0.5, 0.85, 0.075, 0.0902 - 0.75, 0.85, 0.075, 0.0694 - 1.0, 0.85, 0.075, 0.0558 - 1.3, 0.85, 0.075, 0.0447 - 1.6, 0.85, 0.075, 0.0356 -0.001, 0.85, 0.1, 0.1827 - 0.5, 0.85, 0.1, 0.1107 - 0.75, 0.85, 0.1, 0.0901 - 1.0, 0.85, 0.1, 0.0741 - 1.3, 0.85, 0.1, 0.0596 - 1.6, 0.85, 0.1, 0.0495 -0.001, 0.85, 0.125, 0.1939 - 0.5, 0.85, 0.125, 0.1269 - 0.75, 0.85, 0.125, 0.1071 - 1.0, 0.85, 0.125, 0.091 - 1.3, 0.85, 0.125, 0.0743 - 1.6, 0.85, 0.125, 0.0619 -0.001, 0.85, 0.15, 0.2031 - 0.5, 0.85, 0.15, 0.1389 - 0.75, 0.85, 0.15, 0.1209 - 1.0, 0.85, 0.15, 0.1055 - 1.3, 0.85, 0.15, 0.0883 - 1.6, 0.85, 0.15, 0.0741 -0.001, 0.85, 0.175, 0.2112 - 0.5, 0.85, 0.175, 0.1472 - 0.75, 0.85, 0.175, 0.1325 - 1.0, 0.85, 0.175, 0.1178 - 1.3, 0.85, 0.175, 0.1009 - 1.6, 0.85, 0.175, 0.0861 -0.001, 0.85, 0.2, 0.2183 - 0.5, 0.85, 0.2, 0.1539 - 0.75, 0.85, 0.2, 0.1411 - 1.0, 0.85, 0.2, 0.1285 - 1.3, 0.85, 0.2, 0.1121 - 1.6, 0.85, 0.2, 0.0972 -0.001, 0.85, 0.225, 0.2248 - 0.5, 0.85, 0.225, 0.1594 - 0.75, 0.85, 0.225, 0.1476 - 1.0, 0.85, 0.225, 0.1375 - 1.3, 0.85, 0.225, 0.122 - 1.6, 0.85, 0.225, 0.1074 -0.001, 0.85, 0.25, 0.2307 - 0.5, 0.85, 0.25, 0.1632 - 0.75, 0.85, 0.25, 0.153 - 1.0, 0.85, 0.25, 0.1442 - 1.3, 0.85, 0.25, 0.131 - 1.6, 0.85, 0.25, 0.1166 -0.001, 0.85, 0.275, 0.2361 - 0.5, 0.85, 0.275, 0.1656 - 0.75, 0.85, 0.275, 0.1574 - 1.0, 0.85, 0.275, 0.1496 - 1.3, 0.85, 0.275, 0.1386 - 1.6, 0.85, 0.275, 0.125 -0.001, 0.85, 0.3, 0.2411 - 0.5, 0.85, 0.3, 0.1671 - 0.75, 0.85, 0.3, 0.1606 - 1.0, 0.85, 0.3, 0.1542 - 1.3, 0.85, 0.3, 0.1447 - 1.6, 0.85, 0.3, 0.1325 -0.001, 0.9, 0.025, 0.1034 - 0.5, 0.9, 0.025, 0.0251 - 0.75, 0.9, 0.025, 0.0192 - 1.0, 0.9, 0.025, 0.0171 - 1.3, 0.9, 0.025, 0.0141 - 1.6, 0.9, 0.025, 0.0108 -0.001, 0.9, 0.05, 0.1341 - 0.5, 0.9, 0.05, 0.0593 - 0.75, 0.9, 0.05, 0.0436 - 1.0, 0.9, 0.05, 0.0336 - 1.3, 0.9, 0.05, 0.0254 - 1.6, 0.9, 0.05, 0.0209 -0.001, 0.9, 0.075, 0.1556 - 0.5, 0.9, 0.075, 0.0862 - 0.75, 0.9, 0.075, 0.0671 - 1.0, 0.9, 0.075, 0.0536 - 1.3, 0.9, 0.075, 0.0422 - 1.6, 0.9, 0.075, 0.0335 -0.001, 0.9, 0.1, 0.1714 - 0.5, 0.9, 0.1, 0.1042 - 0.75, 0.9, 0.1, 0.0868 - 1.0, 0.9, 0.1, 0.072 - 1.3, 0.9, 0.1, 0.0576 - 1.6, 0.9, 0.1, 0.0472 -0.001, 0.9, 0.125, 0.1842 - 0.5, 0.9, 0.125, 0.1177 - 0.75, 0.9, 0.125, 0.102 - 1.0, 0.9, 0.125, 0.088 - 1.3, 0.9, 0.125, 0.0724 - 1.6, 0.9, 0.125, 0.0599 -0.001, 0.9, 0.15, 0.1947 - 0.5, 0.9, 0.15, 0.1296 - 0.75, 0.9, 0.15, 0.1135 - 1.0, 0.9, 0.15, 0.1011 - 1.3, 0.9, 0.15, 0.0858 - 1.6, 0.9, 0.15, 0.0723 -0.001, 0.9, 0.175, 0.2038 - 0.5, 0.9, 0.175, 0.1385 - 0.75, 0.9, 0.175, 0.1238 - 1.0, 0.9, 0.175, 0.1114 - 1.3, 0.9, 0.175, 0.0974 - 1.6, 0.9, 0.175, 0.0839 -0.001, 0.9, 0.2, 0.2127 - 0.5, 0.9, 0.2, 0.1453 - 0.75, 0.9, 0.2, 0.1325 - 1.0, 0.9, 0.2, 0.1204 - 1.3, 0.9, 0.2, 0.1073 - 1.6, 0.9, 0.2, 0.0943 -0.001, 0.9, 0.225, 0.2202 - 0.5, 0.9, 0.225, 0.1507 - 0.75, 0.9, 0.225, 0.1392 - 1.0, 0.9, 0.225, 0.1288 - 1.3, 0.9, 0.225, 0.1155 - 1.6, 0.9, 0.225, 0.1036 -0.001, 0.9, 0.25, 0.2263 - 0.5, 0.9, 0.25, 0.1548 - 0.75, 0.9, 0.25, 0.1445 - 1.0, 0.9, 0.25, 0.1357 - 1.3, 0.9, 0.25, 0.1229 - 1.6, 0.9, 0.25, 0.1117 -0.001, 0.9, 0.275, 0.2315 - 0.5, 0.9, 0.275, 0.1578 - 0.75, 0.9, 0.275, 0.1488 - 1.0, 0.9, 0.275, 0.1411 - 1.3, 0.9, 0.275, 0.1299 - 1.6, 0.9, 0.275, 0.1184 -0.001, 0.9, 0.3, 0.236 - 0.5, 0.9, 0.3, 0.1598 - 0.75, 0.9, 0.3, 0.1522 - 1.0, 0.9, 0.3, 0.1455 - 1.3, 0.9, 0.3, 0.1358 - 1.6, 0.9, 0.3, 0.1246 -0.001, 0.95, 0.025, 0.1014 - 0.5, 0.95, 0.025, 0.0237 - 0.75, 0.95, 0.025, 0.0187 - 1.0, 0.95, 0.025, 0.0167 - 1.3, 0.95, 0.025, 0.0139 - 1.6, 0.95, 0.025, 0.0108 -0.001, 0.95, 0.05, 0.1185 - 0.5, 0.95, 0.05, 0.0563 - 0.75, 0.95, 0.05, 0.0399 - 1.0, 0.95, 0.05, 0.031 - 1.3, 0.95, 0.05, 0.0238 - 1.6, 0.95, 0.05, 0.0203 -0.001, 0.95, 0.075, 0.1396 - 0.5, 0.95, 0.075, 0.0826 - 0.75, 0.95, 0.075, 0.0649 - 1.0, 0.95, 0.075, 0.051 - 1.3, 0.95, 0.075, 0.0391 - 1.6, 0.95, 0.075, 0.0313 -0.001, 0.95, 0.1, 0.1566 - 0.5, 0.95, 0.1, 0.0987 - 0.75, 0.95, 0.1, 0.0836 - 1.0, 0.95, 0.1, 0.0699 - 1.3, 0.95, 0.1, 0.0553 - 1.6, 0.95, 0.1, 0.0442 -0.001, 0.95, 0.125, 0.17 - 0.5, 0.95, 0.125, 0.1093 - 0.75, 0.95, 0.125, 0.0971 - 1.0, 0.95, 0.125, 0.0851 - 1.3, 0.95, 0.125, 0.0705 - 1.6, 0.95, 0.125, 0.0577 -0.001, 0.95, 0.15, 0.1812 - 0.5, 0.95, 0.15, 0.1187 - 0.75, 0.95, 0.15, 0.1064 - 1.0, 0.95, 0.15, 0.0967 - 1.3, 0.95, 0.15, 0.0834 - 1.6, 0.95, 0.15, 0.0704 -0.001, 0.95, 0.175, 0.1914 - 0.5, 0.95, 0.175, 0.1273 - 0.75, 0.95, 0.175, 0.1143 - 1.0, 0.95, 0.175, 0.1053 - 1.3, 0.95, 0.175, 0.0939 - 1.6, 0.95, 0.175, 0.0817 -0.001, 0.95, 0.2, 0.2007 - 0.5, 0.95, 0.2, 0.1343 - 0.75, 0.95, 0.2, 0.1219 - 1.0, 0.95, 0.2, 0.1122 - 1.3, 0.95, 0.2, 0.1025 - 1.6, 0.95, 0.2, 0.0915 -0.001, 0.95, 0.225, 0.2113 - 0.5, 0.95, 0.225, 0.1397 - 0.75, 0.95, 0.225, 0.1283 - 1.0, 0.95, 0.225, 0.1187 - 1.3, 0.95, 0.225, 0.1089 - 1.6, 0.95, 0.225, 0.0997 -0.001, 0.95, 0.25, 0.2207 - 0.5, 0.95, 0.25, 0.1439 - 0.75, 0.95, 0.25, 0.1337 - 1.0, 0.95, 0.25, 0.1249 - 1.3, 0.95, 0.25, 0.1144 - 1.6, 0.95, 0.25, 0.1066 -0.001, 0.95, 0.275, 0.2265 - 0.5, 0.95, 0.275, 0.1468 - 0.75, 0.95, 0.275, 0.138 - 1.0, 0.95, 0.275, 0.1301 - 1.3, 0.95, 0.275, 0.1197 - 1.6, 0.95, 0.275, 0.1116 -0.001, 0.95, 0.3, 0.2309 - 0.5, 0.95, 0.3, 0.1491 - 0.75, 0.95, 0.3, 0.1412 - 1.0, 0.95, 0.3, 0.1344 - 1.3, 0.95, 0.3, 0.1248 - 1.6, 0.95, 0.3, 0.1161 diff --git a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv b/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv deleted file mode 100644 index 703c223d24..0000000000 --- a/aviary/models/test_aircraft/aircraft_for_bench_GwFm.csv +++ /dev/null @@ -1,279 +0,0 @@ -aircraft:air_conditioning:mass_scaler,1.0,unitless -aircraft:air_conditioning:mass_coefficient,1.65,unitless -aircraft:anti_icing:mass,551,lbm -aircraft:anti_icing:mass_scaler,1.0,unitless -aircraft:apu:mass,928,lbm -aircraft:apu:mass_scaler,1.1,unitless -aircraft:avionics:mass,1959,lbm -aircraft:avionics:mass_scaler,1.2,unitless -aircraft:canard:area,0.0,ft**2 -aircraft:canard:aspect_ratio,0.0,unitless -aircraft:canard:thickness_to_chord,0.0,unitless -aircraft:controls:cockpit_control_mass_scaler,1,unitless -aircraft:controls:control_mass_increment,0,lbm -aircraft:controls:stability_augmentation_system_mass_scaler,1,unitless -aircraft:controls:stability_augmentation_system_mass,0,lbm -aircraft:crew_and_payload:cargo_container_mass_scaler,1.0,unitless -aircraft:crew_and_payload:cargo_mass,10040,lbm -aircraft:crew_and_payload:catering_items_mass_per_passenger,7.6,lbm -aircraft:crew_and_payload:design:num_business_class,0,unitless -aircraft:crew_and_payload:design:num_first_class,11,unitless -aircraft:crew_and_payload:design:num_passengers,180,unitless -aircraft:crew_and_payload:design:num_tourist_class,169,unitless -aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless -aircraft:crew_and_payload:mass_per_passenger,180.0,lbm -aircraft:crew_and_payload:misc_cargo,0.0,lbm -aircraft:crew_and_payload:non_flight_crew_mass_scaler,1.0,unitless -aircraft:crew_and_payload:num_flight_attendants,3,unitless -aircraft:crew_and_payload:num_flight_crew,2,unitless -aircraft:crew_and_payload:num_galley_crew,0,unitless -aircraft:crew_and_payload:passenger_mass_with_bags,200,lbm -aircraft:crew_and_payload:passenger_service_mass_per_passenger,5,lbm -aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless -aircraft:crew_and_payload:wing_cargo,0.0,lbm -aircraft:crew_and_payload:water_mass_per_occupant,3,lbm -aircraft:design:base_area,0.0,ft**2 -aircraft:design:cg_delta,0.25,unitless -aircraft:design:cockpit_control_mass_coefficient,16.5,unitless -aircraft:design:compute_htail_volume_coeff,False,unitless -aircraft:design:compute_vtail_volume_coeff,False,unitless -aircraft:design:drag_increment,0.00175,unitless -aircraft:design:empty_mass_margin_scaler,0.0,unitless -aircraft:design:emergency_equipment_mass,50,lbm -aircraft:design:lift_curve_slope,7.1765,1/rad -aircraft:design:lift_dependent_drag_coeff_factor,0.909839381134961,unitless -aircraft:design:touchdown_mass,152800.0,lbm -aircraft:design:max_structural_speed,402.5,mi/h -aircraft:design:part25_structural_category,3,unitless -aircraft:design:reserve_fuel_additional,5000.,lbm -aircraft:design:smooth_mass_discontinuities,False,unitless -aircraft:design:static_margin,0.03,unitless -aircraft:design:structural_mass_increment,0,lbm -aircraft:design:subsonic_drag_coeff_factor,1.0,unitless -aircraft:design:supercritical_drag_shift,0.033,unitless -aircraft:design:supersonic_drag_coeff_factor,1.0,unitless -aircraft:design:ulf_calculated_from_maneuver,False,unitless -aircraft:design:use_alt_mass,False,unitless -aircraft:design:zero_lift_drag_coeff_factor,0.930890028006548,unitless -aircraft:electrical:has_hybrid_system,False,unitless -aircraft:electrical:mass_scaler,1.25,unitless -aircraft:engine:constant_fuel_consumption,0.,lbm/h -aircraft:engine:data_file,models/engines/turbofan_28k.deck,unitless -aircraft:engine:engine_mass_specific,0.21366,lbm/lbf -aircraft:engine:flight_idle_thrust_fraction,0.0,unitless -aircraft:engine:flight_idle_max_fraction,1.0,unitless -aircraft:engine:flight_idle_min_fraction,0.08,unitless -aircraft:engine:fuel_flow_scaler_constant_term,0.,unitless -aircraft:engine:fuel_flow_scaler_linear_term,0.,unitless -aircraft:engine:generate_flight_idle,True,unitless -aircraft:engine:geopotential_alt,False,unitless -aircraft:engine:has_propellers,False,unitless -aircraft:engine:ignore_negative_thrust,False,unitless -aircraft:engine:interpolation_method,slinear,unitless -aircraft:engine:mass_scaler,1.0,unitless -aircraft:engine:mass,7400,lbm -aircraft:engine:additional_mass_fraction,0.14,unitless -aircraft:engine:num_engines,2,unitless -aircraft:engine:num_fuselage_engines,0,unitless -aircraft:engine:num_wing_engines,2,unitless -aircraft:engine:pod_mass_scaler,1,unitless -aircraft:engine:pylon_factor,1.25,unitless -aircraft:engine:reference_diameter,5.8,ft -aircraft:engine:reference_mass,7400,lbm -aircraft:engine:reference_sls_thrust,28928.1,lbf -aircraft:engine:scale_mass,True,unitless -aircraft:engine:scale_performance,True,unitless -aircraft:engine:scaled_sls_thrust,28928.1,lbf -aircraft:engine:subsonic_fuel_flow_scaler,1.,unitless -aircraft:engine:supersonic_fuel_flow_scaler,1.,unitless -aircraft:engine:thrust_reversers_mass_scaler,0.0,unitless -aircraft:engine:type,7,unitless -aircraft:engine:wing_locations,[0.26869218],unitless -aircraft:fins:area,0.0,ft**2 -aircraft:fins:mass_scaler,1.0,unitless -aircraft:fins:mass,0.0,lbm -aircraft:fins:num_fins,0,unitless -aircraft:fins:taper_ratio,10.0,unitless -aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm -aircraft:fuel:density_ratio,1.0,unitless -aircraft:fuel:density,6.687,lbm/galUS -aircraft:fuel:fuel_margin,0,unitless -aircraft:fuel:fuel_system_mass_coefficient,0.041,unitless -aircraft:fuel:fuel_system_mass_scaler,1.0,unitless -aircraft:fuel:fuselage_fuel_capacity,0.0,lbm -aircraft:fuel:num_tanks,7,unitless -aircraft:fuel:total_capacity,45694.0,lbm -aircraft:fuel:unusable_fuel_mass_coefficient,12,unitless -aircraft:fuel:unusable_fuel_mass_scaler,1.0,unitless -aircraft:fuel:wing_fuel_fraction,0,unitless -aircraft:fuel:wing_volume_geometric_max,1114.0,ft**3 -aircraft:furnishings:mass,11192,lbm -aircraft:furnishings:mass_scaler,1.1,unitless -aircraft:fuselage:aisle_width,24,inch -aircraft:fuselage:avg_diameter,12.75,ft -aircraft:fuselage:delta_diameter,4.5,ft -aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 -aircraft:fuselage:form_factor,1.25,unitless -aircraft:fuselage:length,128.0,ft -aircraft:fuselage:mass_coefficient,128,unitless -aircraft:fuselage:mass_scaler,1.0,unitless -aircraft:fuselage:mass,18357.13345514,lbm -aircraft:fuselage:max_height,13.17,ft -aircraft:fuselage:max_width,12.33,ft -aircraft:fuselage:military_cargo_floor,False,unitless -aircraft:fuselage:nose_fineness,1,unitless -aircraft:fuselage:num_aisles,1,unitless -aircraft:fuselage:num_fuselages,1,unitless -aircraft:fuselage:num_seats_abreast,6,unitless -aircraft:fuselage:passenger_compartment_length,85.5,ft -aircraft:fuselage:pilot_compartment_length,9.5,ft -aircraft:fuselage:planform_area,1578.24,ft**2 -aircraft:fuselage:pressure_differential,7.5,psi -aircraft:fuselage:seat_pitch,29,inch -aircraft:fuselage:seat_width,20.2,inch -aircraft:fuselage:tail_fineness,3,unitless -aircraft:fuselage:wetted_area,4158.62,ft**2 -aircraft:horizontal_tail:area,355.0,ft**2 -aircraft:horizontal_tail:aspect_ratio,4.75,unitless -aircraft:horizontal_tail:average_chord,9.577,ft -aircraft:horizontal_tail:form_factor,1.25,unitless -aircraft:horizontal_tail:mass_coefficient,0.232,unitless -aircraft:horizontal_tail:mass_scaler,1.0,unitless -aircraft:horizontal_tail:moment_ratio,0.2307,unitless -aircraft:horizontal_tail:span,42.254,ft -aircraft:horizontal_tail:sweep,25,deg -aircraft:horizontal_tail:taper_ratio,0.22,unitless -aircraft:horizontal_tail:thickness_to_chord,0.125,unitless -aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless -aircraft:horizontal_tail:volume_coefficient,1.189,unitless -aircraft:horizontal_tail:wetted_area_scaler,1.0,unitless -aircraft:horizontal_tail:wetted_area,592.65,ft**2 -aircraft:hydraulics:flight_control_mass_coefficient,0.112,unitless -aircraft:hydraulics:gear_mass_coefficient,0.14,unitless -aircraft:hydraulics:mass_scaler,1.0,unitless -aircraft:hydraulics:system_pressure,3000.0,psi -aircraft:instruments:mass_coefficient,0.0736,unitless -aircraft:instruments:mass_scaler,1.25,unitless -aircraft:landing_gear:carrier_based,False,unitless -aircraft:landing_gear:fixed_gear,True,unitless -aircraft:landing_gear:main_gear_location,0.15,unitless -aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless -aircraft:landing_gear:main_gear_mass_scaler,1.1,unitless -#aircraft:landing_gear:main_gear_mass,6366.615,lbm -aircraft:landing_gear:main_gear_oleo_length,102.0,inch -aircraft:landing_gear:mass_coefficient,0.04,unitless -aircraft:landing_gear:nose_gear_mass_scaler,1.0,unitless -aircraft:landing_gear:nose_gear_oleo_length,67.0,inch -aircraft:landing_gear:tail_hook_mass_scaler,1,unitless -aircraft:landing_gear:total_mass_scaler,1,unitless -aircraft:nacelle:avg_diameter,7.94,ft -aircraft:nacelle:avg_length,12.3,ft -aircraft:nacelle:clearance_ratio,0.2,unitless -aircraft:nacelle:core_diameter_ratio,1.25,unitless -aircraft:nacelle:fineness,2,unitless -aircraft:nacelle:form_factor,1.5,unitless -aircraft:nacelle:mass_scaler,1.0,unitless -aircraft:nacelle:mass_specific,3,lbm/ft**2 -aircraft:nacelle:surface_area,329.615,ft**2 -aircraft:nacelle:wetted_area_scaler,1.0,unitless -aircraft:paint:mass_per_unit_area,0.037,lbm/ft**2 -aircraft:propulsion:engine_oil_mass_scaler,1.0,unitless -aircraft:propulsion:misc_mass_scaler,1.0,unitless -aircraft:propulsion:total_num_engines,2,unitless -aircraft:strut:area_ratio,0,unitless -aircraft:strut:chord,0,ft -aircraft:strut:dimensional_location_specified,True,unitless -aircraft:strut:fuselage_interference_factor,0,unitless -aircraft:vertical_tail:area,284.0,ft**2 -aircraft:vertical_tail:aspect_ratio,1.75,unitless -aircraft:vertical_tail:average_chord,16.832,ft -aircraft:vertical_tail:form_factor,1.25,unitless -aircraft:vertical_tail:mass_coefficient,0.289,unitless -aircraft:vertical_tail:mass_scaler,1.0,unitless -aircraft:vertical_tail:moment_ratio,2.362,unitless -aircraft:vertical_tail:num_tails,1,unitless -aircraft:vertical_tail:span,27.996,ft -aircraft:vertical_tail:sweep,35,deg -aircraft:vertical_tail:taper_ratio,0.33,unitless -aircraft:vertical_tail:thickness_to_chord,0.1195,unitless -aircraft:vertical_tail:volume_coefficient,0.145,unitless -aircraft:vertical_tail:wetted_area_scaler,1.0,unitless -aircraft:vertical_tail:wetted_area,581.13,ft**2 -aircraft:wing:aeroelastic_tailoring_factor,0.0,unitless -aircraft:wing:airfoil_technology,1.92669766647637,unitless -aircraft:wing:area,1370.0,ft**2 -aircraft:wing:aspect_ratio,10.13,unitless -aircraft:wing:average_chord,12.615,ft -aircraft:wing:bending_mass_scaler,1.0,unitless -aircraft:wing:center_distance,0.463,unitless -aircraft:wing:choose_fold_location,True,unitless -aircraft:wing:chord_per_semispan,0.31,0.23,0.084,unitless -aircraft:wing:composite_fraction,0.2,unitless -aircraft:wing:control_surface_area,137,ft**2 -aircraft:wing:control_surface_area_ratio,0.1,unitless -aircraft:wing:flap_chord_ratio,0.3,unitless -aircraft:wing:flap_deflection_landing,40,deg -aircraft:wing:flap_deflection_takeoff,10,deg -aircraft:wing:flap_type,double_slotted,unitless -aircraft:wing:fold_dimensional_location_specified,False,unitless -aircraft:wing:form_factor,1.25,unitless -aircraft:wing:fuselage_interference_factor,1.1,unitless -aircraft:wing:glove_and_bat,134.0,ft**2 -aircraft:wing:has_fold,False,unitless -aircraft:wing:has_strut,False,unitless -aircraft:wing:height,8,ft -aircraft:wing:high_lift_mass_coefficient,1.9,unitless -aircraft:wing:incidence,0,deg -aircraft:wing:input_station_dist,0.,0.2759,0.9367,unitless -aircraft:wing:load_distribution_control,2.0,unitless -aircraft:wing:load_fraction,1.0,unitless -aircraft:wing:load_path_sweep_dist,0.,22.,deg -aircraft:wing:loading_above_20,True,unitless -aircraft:wing:loading,128.0,lbf/ft**2 -aircraft:wing:mass_coefficient,102.5,unitless -aircraft:wing:mass_scaler,1.0,unitless -aircraft:wing:max_camber_at_70_semispan,0.0,unitless -aircraft:wing:max_thickness_location,0.4,unitless -aircraft:wing:min_pressure_location,0.3,unitless -aircraft:wing:misc_mass_scaler,1.0,unitless -aircraft:wing:mounting_type,0,unitless -aircraft:wing:num_integration_stations,50,unitless -aircraft:wing:shear_control_mass_scaler,1.0,unitless -aircraft:wing:span_efficiency_reduction,False,unitless -aircraft:wing:span,117.83,ft -aircraft:wing:strut_bracing_factor,0.0,unitless -aircraft:wing:surface_ctrl_mass_coefficient,0.95,unitless -aircraft:wing:surface_ctrl_mass_scaler,1.0,unitless -aircraft:wing:sweep,25.0,deg -aircraft:wing:taper_ratio,0.33,unitless -aircraft:wing:thickness_to_chord_dist,0.145,0.115,0.104,unitless -aircraft:wing:thickness_to_chord_root,0.15,unitless -aircraft:wing:thickness_to_chord_tip,0.12,unitless -aircraft:wing:thickness_to_chord_unweighted,0.1397,unitless -aircraft:wing:thickness_to_chord,0.13,unitless -aircraft:wing:ultimate_load_factor,3.91650835,unitless -aircraft:wing:var_sweep_mass_penalty,0.0,unitless -aircraft:wing:wetted_area_scaler,1.0,unitless -aircraft:wing:wetted_area,2396.56,ft**2 -aircraft:wing:zero_lift_angle,-1.2,deg -mission:constraints:max_mach,0.785,unitless -mission:design:cruise_altitude,25000,ft -mission:design:gross_mass,175400.0,lbm -mission:design:lift_coefficient_max_flaps_up,1.2596,unitless -mission:design:range,3500,NM -mission:design:thrust_takeoff_per_eng,28928.1,lbf -mission:landing:airport_altitude,0,ft -mission:landing:drag_coefficient_flap_increment,0.0406,unitless -mission:landing:lift_coefficient_flap_increment,1.0293,unitless -mission:landing:lift_coefficient_max,2.8155,unitless -mission:summary:cruise_mach,0.785,unitless -mission:summary:fuel_flow_scaler,1.0,unitless -mission:summary:gross_mass,175400,lbm -mission:takeoff:airport_altitude,0,ft -mission:takeoff:drag_coefficient_flap_increment,0.0085,unitless -mission:takeoff:fuel_simple,577,lbm -mission:takeoff:lift_coefficient_flap_increment,0.4182,unitless -mission:takeoff:lift_coefficient_max,3.0,unitless -mission:takeoff:lift_over_drag,17.354,unitless -settings:equations_of_motion,height_energy -settings:mass_method,GASP \ No newline at end of file diff --git a/aviary/run_all_benchmarks.py b/aviary/run_all_benchmarks.py index 6d9a2c3ceb..eae8eb75e5 100644 --- a/aviary/run_all_benchmarks.py +++ b/aviary/run_all_benchmarks.py @@ -1,3 +1,7 @@ import subprocess -subprocess.run(["testflo", "--testmatch=bench_test*"]) +status = subprocess.run(['testflo', '--testmatch=bench_test*']) +if status.returncode == 1: + # disable mpi and try again - can cause PermissionError for "forbidden sockets" + print('Re-running all benchmark tests with MPI disabled') + subprocess.run(['testflo', '--testmatch=bench_test*', '--nompi']) diff --git a/aviary/sizing_problem.json b/aviary/sizing_problem.json deleted file mode 100644 index 419e442430..0000000000 --- a/aviary/sizing_problem.json +++ /dev/null @@ -1,1307 +0,0 @@ -[ - [ - "aircraft:blended_wing_body_design:num_bays", - 0, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:mass_per_passenger", - 180, - "lbm", - "" - ], - [ - "aircraft:crew_and_payload:num_business_class", - 0, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_first_class", - 11, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_passengers", - 169, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_tourist_class", - 158, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:passenger_mass_with_bags", - 200, - "lbm", - "" - ], - [ - "aircraft:design:compute_htail_volume_coeff", - false, - "unitless", - "" - ], - [ - "aircraft:design:compute_vtail_volume_coeff", - false, - "unitless", - "" - ], - [ - "aircraft:design:part25_structural_category", - 3, - "unitless", - "" - ], - [ - "aircraft:design:reserve_fuel_additional", - 3000, - "lbm", - "" - ], - [ - "aircraft:design:reserve_fuel_fraction", - 0, - "unitless", - "" - ], - [ - "aircraft:design:smooth_mass_discontinuities", - false, - "unitless", - "" - ], - [ - "aircraft:design:ulf_calculated_from_maneuver", - false, - "unitless", - "" - ], - [ - "aircraft:design:use_alt_mass", - false, - "unitless", - "" - ], - [ - "aircraft:electrical:has_hybrid_system", - false, - "unitless", - "" - ], - [ - "aircraft:engine:compute_propeller_installation_loss", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:constant_fuel_consumption", - [ - 0.0 - ], - "lbm/h", - "" - ], - [ - "aircraft:engine:flight_idle_max_fraction", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:flight_idle_min_fraction", - [ - 0.08 - ], - "unitless", - "" - ], - [ - "aircraft:engine:flight_idle_thrust_fraction", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:fuel_flow_scaler_constant_term", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:fuel_flow_scaler_linear_term", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:generate_flight_idle", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:geopotential_alt", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:has_propellers", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:ignore_negative_thrust", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:interpolation_method", - [ - "slinear" - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_engines", - [ - 2 - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_fuselage_engines", - [ - 0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_propeller_blades", - [ - 0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:num_wing_engines", - [ - 2 - ], - "unitless", - "" - ], - [ - "aircraft:engine:scale_mass", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:scale_performance", - [ - true - ], - "unitless", - "" - ], - [ - "aircraft:engine:subsonic_fuel_flow_scaler", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:supersonic_fuel_flow_scaler", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:type", - [ - "[]" - ], - "unitless", - "" - ], - [ - "aircraft:engine:use_propeller_map", - [ - false - ], - "unitless", - "" - ], - [ - "aircraft:engine:shaft_power_design", - [ - 1.0 - ], - "hp", - "" - ], - [ - "aircraft:fins:num_fins", - 0, - "unitless", - "" - ], - [ - "aircraft:fuel:num_tanks", - 7, - "unitless", - "" - ], - [ - "aircraft:fuselage:aisle_width", - 24, - "inch", - "" - ], - [ - "aircraft:fuselage:military_cargo_floor", - false, - "unitless", - "" - ], - [ - "aircraft:fuselage:num_aisles", - 1, - "unitless", - "" - ], - [ - "aircraft:fuselage:num_fuselages", - 1, - "unitless", - "" - ], - [ - "aircraft:fuselage:num_seats_abreast", - 6, - "unitless", - "" - ], - [ - "aircraft:fuselage:seat_pitch", - 29, - "inch", - "" - ], - [ - "aircraft:fuselage:seat_width", - 20, - "inch", - "" - ], - [ - "aircraft:landing_gear:carrier_based", - false, - "unitless", - "" - ], - [ - "aircraft:landing_gear:drag_coefficient", - 0.0, - "unitless", - "" - ], - [ - "aircraft:landing_gear:fixed_gear", - true, - "unitless", - "" - ], - [ - "aircraft:strut:dimensional_location_specified", - true, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:num_tails", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:airfoil_technology", - 1.92669766647637, - "unitless", - "" - ], - [ - "aircraft:wing:choose_fold_location", - true, - "unitless", - "" - ], - [ - "aircraft:wing:detailed_wing", - false, - "unitless", - "" - ], - [ - "aircraft:wing:flap_type", - "[]", - "unitless", - "" - ], - [ - "aircraft:wing:fold_dimensional_location_specified", - false, - "unitless", - "" - ], - [ - "aircraft:wing:has_fold", - false, - "unitless", - "" - ], - [ - "aircraft:wing:has_strut", - false, - "unitless", - "" - ], - [ - "aircraft:wing:load_distribution_control", - 2, - "unitless", - "" - ], - [ - "aircraft:wing:loading_above_20", - true, - "unitless", - "" - ], - [ - "aircraft:wing:num_flap_segments", - 2, - "unitless", - "" - ], - [ - "aircraft:wing:num_integration_stations", - 50, - "unitless", - "" - ], - [ - "aircraft:wing:span_efficiency_reduction", - false, - "unitless", - "" - ], - [ - "mission:design:cruise_altitude", - 35000, - "ft", - "" - ], - [ - "mission:design:rate_of_climb_at_top_of_climb", - 0.0, - "ft/min", - "" - ], - [ - "mission:summary:fuel_flow_scaler", - 1, - "unitless", - "" - ], - [ - "mission:takeoff:angle_of_attack_runway", - 0.0, - "deg", - "" - ], - [ - "mission:takeoff:obstacle_height", - 35.0, - "ft", - "" - ], - [ - "mission:takeoff:thrust_incidence", - 0.0, - "deg", - "" - ], - [ - "mission:taxi:duration", - 0.167, - "h", - "" - ], - [ - "mission:taxi:mach", - 0.0001, - "unitless", - "" - ], - [ - "settings:verbosity", - "[]", - "unitless", - "" - ], - [ - "INGASP.JENGSZ", - 4, - "unitless", - "" - ], - [ - "test_mode", - false, - "unitless", - "" - ], - [ - "use_surrogates", - true, - "unitless", - "" - ], - [ - "mass_defect", - 10000, - "lbm", - "" - ], - [ - "settings:problem_type", - "[]", - "unitless", - "" - ], - [ - "aircraft:air_conditioning:mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:anti_icing:mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:apu:mass_scaler", - 1.1, - "unitless", - "" - ], - [ - "aircraft:avionics:mass_scaler", - 1.2, - "unitless", - "" - ], - [ - "aircraft:canard:area", - 0, - "ft**2", - "" - ], - [ - "aircraft:canard:aspect_ratio", - 0, - "unitless", - "" - ], - [ - "aircraft:canard:thickness_to_chord", - 0, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:baggage_mass_per_passenger", - 45, - "lbm", - "" - ], - [ - "aircraft:crew_and_payload:cargo_container_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:flight_crew_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:misc_cargo", - 0, - "lbm", - "" - ], - [ - "aircraft:crew_and_payload:non_flight_crew_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_flight_attendants", - 3, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_flight_crew", - 2, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:num_galley_crew", - 0, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:passenger_service_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:crew_and_payload:wing_cargo", - 0, - "lbm", - "" - ], - [ - "aircraft:design:base_area", - 0, - "ft**2", - "" - ], - [ - "aircraft:design:empty_mass_margin_scaler", - 0, - "unitless", - "" - ], - [ - "aircraft:design:lift_dependent_drag_coeff_factor", - 0.909839381134961, - "unitless", - "" - ], - [ - "aircraft:design:touchdown_mass", - 152800, - "lbm", - "" - ], - [ - "aircraft:design:subsonic_drag_coeff_factor", - 1, - "unitless", - "" - ], - [ - "aircraft:design:supersonic_drag_coeff_factor", - 1, - "unitless", - "" - ], - [ - "aircraft:design:zero_lift_drag_coeff_factor", - 0.930890028006548, - "unitless", - "" - ], - [ - "aircraft:electrical:mass_scaler", - 1.25, - "unitless", - "" - ], - [ - "aircraft:engine:additional_mass_fraction", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:data_file", - [ - "models/engines/turbofan_28k.deck" - ], - "unitless", - "" - ], - [ - "aircraft:engine:mass_scaler", - [ - 1.15 - ], - "unitless", - "" - ], - [ - "aircraft:engine:mass", - [ - 7400.0 - ], - "lbm", - "" - ], - [ - "aircraft:engine:reference_mass", - [ - 7400 - ], - "lbm", - "" - ], - [ - "aircraft:engine:reference_sls_thrust", - [ - 28928.1 - ], - "lbf", - "" - ], - [ - "aircraft:engine:scaled_sls_thrust", - [ - 28928.1 - ], - "lbf", - "" - ], - [ - "aircraft:engine:thrust_reversers_mass_scaler", - [ - 0.0 - ], - "unitless", - "" - ], - [ - "aircraft:engine:wing_locations", - [ - 0.26869218 - ], - "unitless", - "" - ], - [ - "aircraft:fins:area", - 0, - "ft**2", - "" - ], - [ - "aircraft:fins:mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:fins:mass", - 0, - "lbm", - "" - ], - [ - "aircraft:fins:taper_ratio", - 10, - "unitless", - "" - ], - [ - "aircraft:fuel:auxiliary_fuel_capacity", - 0, - "lbm", - "" - ], - [ - "aircraft:fuel:density_ratio", - 1, - "unitless", - "" - ], - [ - "aircraft:fuel:fuel_system_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:fuel:fuselage_fuel_capacity", - 0, - "lbm", - "" - ], - [ - "aircraft:fuel:total_capacity", - 45694, - "lbm", - "" - ], - [ - "aircraft:fuel:unusable_fuel_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:furnishings:mass_scaler", - 1.1, - "unitless", - "" - ], - [ - "aircraft:fuselage:length", - 128, - "ft", - "" - ], - [ - "aircraft:fuselage:mass_scaler", - 1.05, - "unitless", - "" - ], - [ - "aircraft:fuselage:max_height", - 13.17, - "ft", - "" - ], - [ - "aircraft:fuselage:max_width", - 12.33, - "ft", - "" - ], - [ - "aircraft:fuselage:passenger_compartment_length", - 85.5, - "ft", - "" - ], - [ - "aircraft:fuselage:planform_area", - 1578.24, - "ft**2", - "" - ], - [ - "aircraft:fuselage:wetted_area_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:fuselage:wetted_area", - 4158.62, - "ft**2", - "" - ], - [ - "aircraft:horizontal_tail:area", - 355, - "ft**2", - "" - ], - [ - "aircraft:horizontal_tail:aspect_ratio", - 6, - "unitless", - "" - ], - [ - "aircraft:horizontal_tail:mass_scaler", - 1.2, - "unitless", - "" - ], - [ - "aircraft:horizontal_tail:taper_ratio", - 0.22, - "unitless", - "" - ], - [ - "aircraft:horizontal_tail:thickness_to_chord", - 0.125, - "unitless", - "" - ], - [ - "aircraft:horizontal_tail:vertical_tail_fraction", - 0, - "unitless", - "" - ], - [ - "aircraft:horizontal_tail:wetted_area_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:horizontal_tail:wetted_area", - 592.65, - "ft**2", - "" - ], - [ - "aircraft:hydraulics:mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:hydraulics:system_pressure", - 3000, - "psi", - "" - ], - [ - "aircraft:instruments:mass_scaler", - 1.25, - "unitless", - "" - ], - [ - "aircraft:landing_gear:main_gear_mass_scaler", - 1.1, - "unitless", - "" - ], - [ - "aircraft:landing_gear:main_gear_oleo_length", - 102, - "inch", - "" - ], - [ - "aircraft:landing_gear:nose_gear_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:landing_gear:nose_gear_oleo_length", - 67, - "inch", - "" - ], - [ - "aircraft:nacelle:avg_diameter", - [ - 7.94 - ], - "ft", - "" - ], - [ - "aircraft:nacelle:avg_length", - [ - 12.3 - ], - "ft", - "" - ], - [ - "aircraft:nacelle:mass_scaler", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:nacelle:wetted_area_scaler", - [ - 1.0 - ], - "unitless", - "" - ], - [ - "aircraft:paint:mass_per_unit_area", - 0.037, - "lbm/ft**2", - "" - ], - [ - "aircraft:propulsion:engine_oil_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:propulsion:misc_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:area", - 284, - "ft**2", - "" - ], - [ - "aircraft:vertical_tail:aspect_ratio", - 1.75, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:taper_ratio", - 0.33, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:thickness_to_chord", - 0.1195, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:wetted_area_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:vertical_tail:wetted_area", - 581.13, - "ft**2", - "" - ], - [ - "aircraft:wing:aeroelastic_tailoring_factor", - 0, - "unitless", - "" - ], - [ - "aircraft:wing:area", - 1370, - "ft**2", - "" - ], - [ - "aircraft:wing:aspect_ratio", - 11.22091, - "unitless", - "" - ], - [ - "aircraft:wing:bending_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:chord_per_semispan", - [ - 0.31, - 0.23, - 0.084 - ], - "unitless", - "" - ], - [ - "aircraft:wing:composite_fraction", - 0.2, - "unitless", - "" - ], - [ - "aircraft:wing:control_surface_area", - 137, - "ft**2", - "" - ], - [ - "aircraft:wing:control_surface_area_ratio", - 0.1, - "unitless", - "" - ], - [ - "aircraft:wing:glove_and_bat", - 134, - "ft**2", - "" - ], - [ - "aircraft:wing:input_station_dist", - [ - 0, - 0.2759, - 0.9367 - ], - "unitless", - "" - ], - [ - "aircraft:wing:load_fraction", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:load_path_sweep_dist", - [ - 0, - 22 - ], - "deg", - "" - ], - [ - "aircraft:wing:mass_scaler", - 1.23, - "unitless", - "" - ], - [ - "aircraft:wing:max_camber_at_70_semispan", - 0, - "unitless", - "" - ], - [ - "aircraft:wing:misc_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:shear_control_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:span", - 117.83, - "ft", - "" - ], - [ - "aircraft:wing:strut_bracing_factor", - 0, - "unitless", - "" - ], - [ - "aircraft:wing:surface_ctrl_mass_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:sweep", - 25, - "deg", - "" - ], - [ - "aircraft:wing:taper_ratio", - 0.278, - "unitless", - "" - ], - [ - "aircraft:wing:thickness_to_chord_dist", - [ - 0.145, - 0.115, - 0.104 - ], - "unitless", - "" - ], - [ - "aircraft:wing:thickness_to_chord", - 0.13, - "unitless", - "" - ], - [ - "aircraft:wing:ultimate_load_factor", - 3.75, - "unitless", - "" - ], - [ - "aircraft:wing:var_sweep_mass_penalty", - 0, - "unitless", - "" - ], - [ - "aircraft:wing:wetted_area_scaler", - 1, - "unitless", - "" - ], - [ - "aircraft:wing:wetted_area", - 2396.56, - "ft**2", - "" - ], - [ - "mission:constraints:max_mach", - 0.785, - "unitless", - "" - ], - [ - "mission:design:gross_mass", - 175864.58080717592, - "lbm", - "" - ], - [ - "mission:design:range", - 3375.0, - "NM", - "" - ], - [ - "mission:design:thrust_takeoff_per_eng", - 28928.1, - "lbf", - "" - ], - [ - "mission:landing:lift_coefficient_max", - 2, - "unitless", - "" - ], - [ - "mission:summary:cruise_mach", - 0.785, - "unitless", - "" - ], - [ - "mission:takeoff:fuel_simple", - 577, - "lbm", - "" - ], - [ - "mission:takeoff:lift_coefficient_max", - 3, - "unitless", - "" - ], - [ - "mission:takeoff:lift_over_drag", - 17.354, - "unitless", - "" - ], - [ - "settings:equations_of_motion", - "[]", - "unitless", - "" - ], - [ - "settings:mass_method", - "[]", - "unitless", - "" - ], - [ - "mission:summary:gross_mass", - 175864.58080717592, - "lbm", - "" - ], - [ - "aircraft:propulsion:total_num_engines", - 2, - "unitless", - "" - ], - [ - "aircraft:propulsion:total_num_fuselage_engines", - 0, - "unitless", - "" - ], - [ - "aircraft:propulsion:total_num_wing_engines", - 2, - "unitless", - "" - ] -] \ No newline at end of file diff --git a/aviary/subsystems/aerodynamics/aero_common.py b/aviary/subsystems/aerodynamics/aero_common.py index 964a0fa721..e878585254 100644 --- a/aviary/subsystems/aerodynamics/aero_common.py +++ b/aviary/subsystems/aerodynamics/aero_common.py @@ -1,35 +1,29 @@ import numpy as np import openmdao.api as om +from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Dynamic class DynamicPressure(om.ExplicitComponent): """ Compute dynamic pressure as - Dynamic.Mission.DYNAMIC_PRESSURE = 0.5 * gamma * P * M**2 + Dynamic.Mission.DYNAMIC_PRESSURE = 0.5 * gamma * P * M**2. """ def initialize(self): self.options.declare('num_nodes', types=int) - self.options.declare( - 'gamma', default=1.4, desc='Ratio of specific heats for air.') + self.options.declare('gamma', default=1.4, desc='Ratio of specific heats for air.') def setup(self): nn = self.options['num_nodes'] - self.add_input( - Dynamic.Mission.STATIC_PRESSURE, np.ones(nn), units='lbf/ft**2', - desc='Static pressure at each evaulation point.') + add_aviary_input(self, Dynamic.Atmosphere.STATIC_PRESSURE, shape=nn, units='lbf/ft**2') - self.add_input( - Dynamic.Mission.MACH, np.ones(nn), units='unitless', - desc='Mach at each evaulation point.') + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') - self.add_output( - Dynamic.Mission.DYNAMIC_PRESSURE, val=np.ones(nn), units='lbf/ft**2', - desc='pressure caused by fluid motion') + add_aviary_output(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='lbf/ft**2') def setup_partials(self): nn = self.options['num_nodes'] @@ -37,22 +31,25 @@ def setup_partials(self): rows_cols = np.arange(nn) self.declare_partials( - Dynamic.Mission.DYNAMIC_PRESSURE, [ - Dynamic.Mission.STATIC_PRESSURE, Dynamic.Mission.MACH], - rows=rows_cols, cols=rows_cols) + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + [Dynamic.Atmosphere.STATIC_PRESSURE, Dynamic.Atmosphere.MACH], + rows=rows_cols, + cols=rows_cols, + ) def compute(self, inputs, outputs): gamma = self.options['gamma'] - P = inputs[Dynamic.Mission.STATIC_PRESSURE] - M = inputs[Dynamic.Mission.MACH] + P = inputs[Dynamic.Atmosphere.STATIC_PRESSURE] + M = inputs[Dynamic.Atmosphere.MACH] - outputs[Dynamic.Mission.DYNAMIC_PRESSURE] = 0.5 * gamma * P * M**2 + outputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] = 0.5 * gamma * P * M**2 def compute_partials(self, inputs, partials): gamma = self.options['gamma'] - P = inputs[Dynamic.Mission.STATIC_PRESSURE] - M = inputs[Dynamic.Mission.MACH] + P = inputs[Dynamic.Atmosphere.STATIC_PRESSURE] + M = inputs[Dynamic.Atmosphere.MACH] - partials[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.MACH] = gamma * P * M - partials[Dynamic.Mission.DYNAMIC_PRESSURE, - Dynamic.Mission.STATIC_PRESSURE] = 0.5 * gamma * M**2 + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.MACH] = gamma * P * M + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.STATIC_PRESSURE] = ( + 0.5 * gamma * M**2 + ) diff --git a/aviary/subsystems/aerodynamics/aerodynamics_builder.py b/aviary/subsystems/aerodynamics/aerodynamics_builder.py index f43e459306..abf70bc607 100644 --- a/aviary/subsystems/aerodynamics/aerodynamics_builder.py +++ b/aviary/subsystems/aerodynamics/aerodynamics_builder.py @@ -7,33 +7,29 @@ CoreAerodynamicsBuilder : the interface for Aviary's core aerodynamics subsystem builder """ -from itertools import chain -import numpy as np +import warnings +import numpy as np import openmdao.api as om -from dymos.utils.misc import _unspecified - -from aviary.subsystems.aerodynamics.flops_based.computed_aero_group import \ - ComputedAeroGroup -from aviary.subsystems.aerodynamics.flops_based.takeoff_aero_group import \ - TakeoffAeroGroup -from aviary.subsystems.aerodynamics.flops_based.solved_alpha_group import \ - SolvedAlphaGroup -from aviary.subsystems.aerodynamics.flops_based.tabular_aero_group import \ - TabularAeroGroup -from aviary.subsystems.aerodynamics.flops_based.drag_polar import DragPolar + +# from dymos.utils.misc import _unspecified +from aviary.subsystems.aerodynamics.flops_based.computed_aero_group import ComputedAeroGroup from aviary.subsystems.aerodynamics.flops_based.design import Design +from aviary.subsystems.aerodynamics.flops_based.tabular_aero_group import TabularAeroGroup +from aviary.subsystems.aerodynamics.flops_based.takeoff_aero_group import TakeoffAeroGroup +from aviary.subsystems.aerodynamics.gasp_based.gaspaero import CruiseAero, LowSpeedAero from aviary.subsystems.aerodynamics.gasp_based.premission_aero import PreMissionAero -from aviary.subsystems.aerodynamics.gasp_based.gaspaero import CruiseAero -from aviary.subsystems.aerodynamics.gasp_based.gaspaero import LowSpeedAero -from aviary.subsystems.aerodynamics.gasp_based.table_based import TabularCruiseAero -from aviary.subsystems.aerodynamics.gasp_based.table_based import TabularLowSpeedAero +from aviary.subsystems.aerodynamics.gasp_based.table_based import ( + TabularCruiseAero, + TabularLowSpeedAero, +) +from aviary.subsystems.aerodynamics.solve_alpha_group import SolveAlphaGroup from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.named_values import NamedValues -from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.enums import AircraftTypes, LegacyCode, Verbosity from aviary.variable_info.variable_meta_data import _MetaData -from aviary.variable_info.variables import Aircraft, Mission, Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings GASP = LegacyCode.GASP @@ -44,7 +40,7 @@ class AerodynamicsBuilderBase(SubsystemBuilderBase): """ - Base class of aerodynamics builder + Base class of aerodynamics builder. Methods ------- @@ -89,7 +85,7 @@ class CoreAerodynamicsBuilder(AerodynamicsBuilderBase): Generate the report for Aviary core aerodynamics analysis. """ - def __init__(self, name=None, meta_data=None, code_origin=None): + def __init__(self, name=None, meta_data=None, code_origin=None, tabular=False): if name is None: name = 'core_aerodynamics' @@ -97,214 +93,310 @@ def __init__(self, name=None, meta_data=None, code_origin=None): raise ValueError('Code origin is not one of the following: (FLOPS, GASP)') self.code_origin = code_origin + self.tabular = tabular super().__init__(name=name, meta_data=meta_data) - def build_pre_mission(self, aviary_inputs): + def build_pre_mission(self, aviary_inputs, **kwargs): + # pre-mission is not required when exclusively using tabular aero + if self.tabular: + return + code_origin = self.code_origin + try: + method = kwargs['method'] + except KeyError: + method = None + + if method == 'external': + return None if code_origin is GASP: - aero_group = PreMissionAero(aviary_options=aviary_inputs) + return PreMissionAero() elif code_origin is FLOPS: - aero_group = Design(aviary_options=aviary_inputs) - - return aero_group + return Design() def build_mission(self, num_nodes, aviary_inputs, **kwargs): + aero_opts = kwargs.copy() try: - method = kwargs.pop('method') + method = aero_opts.pop('method') except KeyError: method = None + + if method == 'external': + return None + + aero_group = None + if self.code_origin is FLOPS: + if 'solve_alpha' in aero_opts: + if aviary_inputs.get_val(Settings.VERBOSITY) >= Verbosity.BRIEF: + warnings.warn( + "The 'solve_alpha' flag has been set, but is not used for FLOPS-based " + 'aerodynamics.' + ) + if method is None: - aero_group = ComputedAeroGroup(num_nodes=num_nodes, - aviary_options=aviary_inputs) + aero_group = ComputedAeroGroup(num_nodes=num_nodes) elif method == 'computed': - aero_group = ComputedAeroGroup(num_nodes=num_nodes, - aviary_options=aviary_inputs, - **kwargs) + aero_group = ComputedAeroGroup(num_nodes=num_nodes, **aero_opts) elif method == 'low_speed': - aero_group = TakeoffAeroGroup(num_nodes=num_nodes, - aviary_options=aviary_inputs, - **kwargs) - - # TODO solved alpha belongs in the GASP side, rolled into tabular aero - # It is currently only here because it is not possible to define - # per-subsystem code origins in AviaryProblem yet - elif method == 'solved_alpha': - aero_group = SolvedAlphaGroup(num_nodes=num_nodes, - aero_data=kwargs.pop('aero_data'), - **kwargs) + aero_group = TakeoffAeroGroup(num_nodes=num_nodes, **aero_opts) elif method == 'tabular': - aero_group = TabularAeroGroup(num_nodes=num_nodes, - CD0_data=kwargs.pop('CD0_data'), - CDI_data=kwargs.pop('CDI_data'), - **kwargs) + aero_group = TabularAeroGroup( + num_nodes=num_nodes, + CD0_data=aero_opts.pop('CD0_data'), + CDI_data=aero_opts.pop('CDI_data'), + **aero_opts, + ) else: - raise ValueError('FLOPS-based aero method is not one of the following: ' - '(computed, low_speed, solved_alpha, tabular)') + raise ValueError( + 'FLOPS-based aero method is not one of the following: (computed, ' + 'low_speed, tabular)' + ) elif self.code_origin is GASP: + try: + solve_alpha = aero_opts.pop('solve_alpha') + except KeyError: + solve_alpha = False + if method is None: - aero_group = CruiseAero(num_nodes=num_nodes, - aviary_options=aviary_inputs) + aero_group = CruiseAero(num_nodes=num_nodes) elif method == 'cruise': - if 'aero_data' in kwargs: - aero_group = TabularCruiseAero(num_nodes=num_nodes, - aviary_options=aviary_inputs, - aero_data=kwargs.pop('aero_data'), - **kwargs) - else: - aero_group = CruiseAero(num_nodes=num_nodes, - aviary_options=aviary_inputs, - **kwargs) + aero_group = CruiseAero(num_nodes=num_nodes, **aero_opts) - elif method == 'low_speed': - if any(key in kwargs for key in ['free_aero_data', - 'free_flaps_data', - 'free_ground_data']) in kwargs: - aero_group = TabularLowSpeedAero(num_nodes=num_nodes, - free_aero_data=kwargs.pop( - 'free_aero_data'), - free_flaps_data=kwargs.pop( - 'free_flaps_data'), - free_ground_data=kwargs.pop( - 'free_ground_data'), - **kwargs) + elif method == 'tabular_cruise': + # if 'aero_data' in aero_opts: + aero_group = TabularCruiseAero( + num_nodes=num_nodes, + aero_data=aero_opts.pop('aero_data'), + **aero_opts, + ) + elif method == 'low_speed': + aero_group = LowSpeedAero(num_nodes=num_nodes, **aero_opts) + + elif method == 'tabular_low_speed': + data_tables = [ + key in aero_opts + for key in ['free_aero_data', 'free_flaps_data', 'free_ground_data'] + ] + + if all(data_tables): + aero_group = TabularLowSpeedAero(num_nodes=num_nodes, **aero_opts) + # raise error if only some data types are provided (at this point we know + # not all are present, now need to see if any were provided at all) + elif any(data_tables): + var_msg = set(['free_aero_data', 'free_flaps_data', 'free_ground_data']) - set( + data_tables + ) + raise UserWarning( + f'Low-speed tabular aerodynamics also requires {var_msg} but ' + 'these data sets were not provided.' + ) else: - aero_group = LowSpeedAero(num_nodes=num_nodes, - aviary_options=aviary_inputs, - **kwargs) - + raise UserWarning( + 'Low-speed tabular aerodynamics requires 3 data tables: free_aero_data, ' + 'free_flaps_data, and free_ground_data.' + ) else: - raise ValueError('GASP-based aero method is not one of the following: ' - '(cruise, low_speed)') + raise ValueError( + 'GASP-based aero method is not one of the following: (cruise, ' + 'tabular_cruise, low_speed, tabular_low_speed)' + ) + + if solve_alpha: + # build a group to house the aero method plus the AoA balance comp + aero_supergroup = om.Group() + aero_supergroup.add_subsystem(f'{method}_aero', aero_group, promotes=['*']) + + aero_supergroup.add_subsystem( + 'solve_alpha_group', + SolveAlphaGroup(num_nodes=num_nodes), + promotes=['*'], + ) + + aero_supergroup.linear_solver = om.DirectSolver() + newton = aero_supergroup.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) + newton.options['iprint'] = 2 + newton.options['atol'] = 1e-9 + newton.options['rtol'] = 1e-12 + + # return the supergroup instead of the individual aero method group + aero_group = aero_supergroup return aero_group # TODO DragPolar comp is unfinished and currently does nothing - # def build_post_mission(self, aviary_inputs, **kwargs): + # def build_post_mission(self, aviary_inputs, phase_info, phase_mission_bus_lengths, **kwargs): # aero_group = DragPolar(aviary_options=aviary_inputs), # return aero_group def mission_inputs(self, **kwargs): - method = kwargs['method'] + try: + method = kwargs['method'] + except KeyError: + method = None + promotes = ['*'] if self.code_origin is FLOPS: + # FLOPS default is 'computed' + if method is None: + method = 'computed' + if method == 'computed': - promotes = [Dynamic.Mission.STATIC_PRESSURE, - Dynamic.Mission.MACH, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.MASS, - 'aircraft:*', 'mission:*'] - - elif method == 'solved_alpha': - promotes = [Dynamic.Mission.ALTITUDE, - Dynamic.Mission.MACH, - Dynamic.Mission.MASS, - Dynamic.Mission.STATIC_PRESSURE, - 'aircraft:*'] + promotes = [ + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Vehicle.MASS, + 'aircraft:*', + 'mission:*', + ] elif method == 'low_speed': - promotes = ['angle_of_attack', - Dynamic.Mission.ALTITUDE, - Dynamic.Mission.FLIGHT_PATH_ANGLE, - Mission.Takeoff.DRAG_COEFFICIENT_MIN, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.HEIGHT, - Aircraft.Wing.SPAN, - Dynamic.Mission.DYNAMIC_PRESSURE, - Aircraft.Wing.AREA] + promotes = [ + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.ALTITUDE, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + Mission.Takeoff.DRAG_COEFFICIENT_MIN, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.HEIGHT, + Aircraft.Wing.SPAN, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + Aircraft.Wing.AREA, + ] elif method == 'tabular': - promotes = [Dynamic.Mission.ALTITUDE, - Dynamic.Mission.MACH, - Dynamic.Mission.MASS, - Dynamic.Mission.VELOCITY, - Dynamic.Mission.DENSITY, - 'aircraft:*'] + promotes = [ + Dynamic.Mission.ALTITUDE, + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.MASS, + Dynamic.Mission.VELOCITY, + Dynamic.Atmosphere.DENSITY, + 'aircraft:*', + ] else: - raise ValueError('FLOPS-based aero method is not one of the following: ' - '(computed, low_speed, solved_alpha, tabular)') + raise ValueError( + 'FLOPS-based aero method is not one of the following: ' + '(computed, low_speed, tabular)' + ) elif self.code_origin is GASP: - if method == 'low_speed': - promotes = ['*', - ("airport_alt", Mission.Takeoff.AIRPORT_ALTITUDE), - ("CL_max_flaps", Mission.Takeoff.LIFT_COEFFICIENT_MAX), - ("dCL_flaps_model", Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT), - ("dCD_flaps_model", Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT), - ("flap_defl", Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF)] - - elif method == 'cruise': + # GASP default is 'cruise' + if method is None: + method = 'cruise' + + if method in ('low_speed', 'tabular_low_speed'): + promotes = [ + '*', + ('airport_alt', Mission.Takeoff.AIRPORT_ALTITUDE), + ('CL_max_flaps', Mission.Takeoff.LIFT_COEFFICIENT_MAX), + ( + 'dCL_flaps_model', + Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT, + ), + ( + 'dCD_flaps_model', + Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT, + ), + ('flap_defl', Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF), + ] + + elif method in ('cruise', 'tabular_cruise'): if 'output_alpha' in kwargs: if kwargs['output_alpha']: - promotes = ['*', ("lift_req", "weight")] + promotes = ['*', ('lift_req', 'weight')] else: - raise ValueError('GASP-based aero method is not one of the following: ' - '(low_speed, cruise)') + raise ValueError( + 'GASP-based aero method is not one of the following: (cruise, ' + 'tabular_cruise, low_speed, tabular_low_speed)' + ) return promotes def mission_outputs(self, **kwargs): - method = kwargs['method'] + try: + method = kwargs['method'] + except KeyError: + method = None promotes = ['*'] if self.code_origin is FLOPS: - promotes = [Dynamic.Mission.DRAG, Dynamic.Mission.LIFT] + promotes = [Dynamic.Vehicle.DRAG, Dynamic.Vehicle.LIFT] elif self.code_origin is GASP: - if method == 'low_speed': - promotes = [Dynamic.Mission.DRAG, - Dynamic.Mission.LIFT, - 'CL', 'CD', 'flap_factor', 'gear_factor'] - - elif method == 'cruise': - if 'output_alpha' in kwargs: - if kwargs['output_alpha']: - promotes = [Dynamic.Mission.DRAG, - Dynamic.Mission.LIFT, - 'alpha'] + # GASP default is 'cruise' + if method is None: + method = 'cruise' + + if method in ('low_speed', 'tabular_low_speed'): + promotes = [ + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.LIFT, + 'CL', + 'CD', + 'flap_factor', + 'gear_factor', + ] + + elif method in ('cruise', 'tabular_cruise'): + if method == 'tabular_cruise': + promotes = [Dynamic.Vehicle.DRAG, Dynamic.Vehicle.LIFT] else: - promotes = [Dynamic.Mission.DRAG, - Dynamic.Mission.LIFT, - 'CL_max'] + if 'output_alpha' in kwargs: + if kwargs['output_alpha']: + promotes = [ + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.LIFT, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ] + else: + promotes = [ + Dynamic.Vehicle.DRAG, + Dynamic.Vehicle.LIFT, + 'CL_max', + ] else: - raise ValueError('GASP-based aero method is not one of the following: ' - '(low_speed, cruise)') + raise ValueError( + 'GASP-based aero method is not one of the following: (cruise, ' + 'tabular_cruise, low_speed, tabular_low_speed)' + ) return promotes - def get_parameters(self, aviary_inputs=None, phase_info=None): + def get_parameters(self, aviary_inputs=None, **kwargs): """ Return a dictionary of fixed values for the subsystem. Optional, used if subsystems have fixed values. - Used in the phase builders (e.g. cruise_phase.py) when other parameters are added to the phase. + Used in the phase builders (e.g. cruise_phase.py) when other parameters are + added to the phase. This is distinct from `get_design_vars` in a nuanced way. Design variables are variables that are optimized by the problem that are not at the phase level. - An example would be something that occurs in the pre-mission level of the problem. + An example would be something that occurs in the pre-mission level of the + problem. Parameters are fixed values that are held constant throughout a phase, but if `opt=True`, they are able to change during the optimization. Parameters ---------- - phase_info : dict - The phase_info subdict for this phase. + aviary_info : dict + The AviaryValues for the aircraft problem. Returns ------- @@ -319,65 +411,95 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): - any additional keyword arguments required by OpenMDAO for the fixed variable. """ + try: + method = kwargs['method'] + except KeyError: + method = None + + if method == 'external': + return super().get_parameters() + num_engine_type = len(aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES)) params = {} if self.code_origin is FLOPS: - try: - aero_opt = phase_info['subsystem_options'][self.name] - method = aero_opt['method'] - except KeyError: + # FLOPS default is 'computed' + if method is None: method = 'computed' + if kwargs != {}: + # Only some methods have connectable training inputs. + if method == 'tabular': + CD0_data = kwargs['CD0_data'] - if phase_info is not None: - # Only solved_alpha has connectable inputs. - if method == 'solved_alpha': - aero_data = aero_opt['aero_data'] - - if isinstance(aero_data, NamedValues): - altitude = aero_data.get_item('altitude')[0] - mach = aero_data.get_item('mach')[0] - angle_of_attack = aero_data.get_item('angle_of_attack')[0] + if isinstance(CD0_data, NamedValues): + altitude = CD0_data.get_item('altitude')[0] + mach = CD0_data.get_item('mach')[0] n1 = altitude.size n2 = mach.size - n3 = angle_of_attack.size n1u = np.unique(altitude).size if n1 > n1u: # Data is free-format instead of pre-formatted. n1 = n1u n2 = np.unique(mach).size - n3 = np.unique(angle_of_attack).size - - shape = (n1, n2, n3) - if aviary_inputs is not None and Aircraft.Design.LIFT_POLAR in aviary_inputs: - lift_opts = {'val': aviary_inputs.get_val(Aircraft.Design.LIFT_POLAR), - 'static_target': True} + shape = (n1, n2) + + if ( + aviary_inputs is not None + and Aircraft.Design.LIFT_INDEPENDENT_DRAG_POLAR in aviary_inputs + ): + opts = { + 'val': aviary_inputs.get_val( + Aircraft.Design.LIFT_INDEPENDENT_DRAG_POLAR + ), + 'static_target': True, + } else: - lift_opts = {'shape': shape, - 'static_target': True} + opts = {'shape': shape, 'static_target': True} + + params[Aircraft.Design.LIFT_INDEPENDENT_DRAG_POLAR] = opts + + CDI_data = kwargs['CDI_data'] + + if isinstance(CDI_data, NamedValues): + mach = CDI_data.get_item('mach')[0] + cl = CDI_data.get_item('lift_coefficient')[0] - if aviary_inputs is not None and Aircraft.Design.DRAG_POLAR in aviary_inputs: - drag_opts = {'val': aviary_inputs.get_val(Aircraft.Design.DRAG_POLAR), - 'static_target': True} + n1 = mach.size + n2 = cl.size + n1u = np.unique(mach).size + + if n1 > n1u: + # Data is free-format instead of pre-formatted. + n1 = n1u + n2 = np.unique(cl).size + + shape = (n1, n2) + + if ( + aviary_inputs is not None + and Aircraft.Design.LIFT_DEPENDENT_DRAG_POLAR in aviary_inputs + ): + opts = { + 'val': aviary_inputs.get_val( + Aircraft.Design.LIFT_DEPENDENT_DRAG_POLAR + ), + 'static_target': True, + } else: - drag_opts = {'shape': shape, - 'static_target': True} + opts = {'shape': shape, 'static_target': True} - params[Aircraft.Design.LIFT_POLAR] = lift_opts - params[Aircraft.Design.DRAG_POLAR] = drag_opts + params[Aircraft.Design.LIFT_DEPENDENT_DRAG_POLAR] = opts if method == 'computed': - for var in COMPUTED_CORE_INPUTS: - meta = _MetaData[var] val = meta['default_value'] if val is None: - val = _unspecified + val = 0.0 # _unspecified units = meta['units'] if var in aviary_inputs: @@ -386,21 +508,28 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): except TypeError: val = aviary_inputs.get_val(var) - params[var] = {'val': val, - 'static_target': True} + params[var] = {'val': val, 'units': units, 'static_target': True} for var in ENGINE_SIZED_INPUTS: - params[var] = {'shape': (num_engine_type, ), 'static_target': True} + meta = _MetaData[var] + val = meta['default_value'] + if val is None: + val = [0.0] # _unspecified + units = meta['units'] + params[var] = { + 'val': val, + 'units': units, + 'shape': (num_engine_type,), + 'static_target': True, + } elif method == 'tabular': - for var in TABULAR_CORE_INPUTS: - meta = _MetaData[var] val = meta['default_value'] if val is None: - val = _unspecified + val = 0.0 # _unspecified units = meta['units'] if var in aviary_inputs: @@ -409,18 +538,15 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): except TypeError: val = aviary_inputs.get_val(var) - params[var] = {'val': val, - 'static_target': True} - - elif method == "low_speed": + params[var] = {'val': val, 'units': units, 'static_target': True} + elif method == 'low_speed': for var in LOW_SPEED_CORE_INPUTS: - meta = _MetaData[var] val = meta['default_value'] if val is None: - val = _unspecified + val = 0.0 # _unspecified units = meta['units'] if var in aviary_inputs: @@ -429,26 +555,89 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): except TypeError: val = aviary_inputs.get_val(var) - params[var] = {'val': val, - 'static_target': True} + params[var] = {'val': val, 'units': units, 'static_target': True} + # GASP aero else: - - # TODO: 2DOF/Gasp decided on phases based on phase names. We used - # a saved phase_name to determine the correct aero variables to - # promote. Ideally, this should all be refactored. - if phase_info['phase_type'] in ['ascent', 'groundroll', 'rotation']: - all_vars = (AERO_2DOF_INPUTS, AERO_LS_2DOF_INPUTS) + if method is None: + # GASP default is 'cruise' + method = 'cruise' + try: + solve_alpha = kwargs['solve_alpha'] + except KeyError: + solve_alpha = False + + if solve_alpha and 'tabular' in method: + aero_data = kwargs['aero_data'] + + if isinstance(aero_data, NamedValues): + altitude = aero_data.get_item('altitude')[0] + mach = aero_data.get_item('mach')[0] + angle_of_attack = aero_data.get_item('angle_of_attack')[0] + + n1 = altitude.size + n2 = mach.size + n3 = angle_of_attack.size + n1u = np.unique(altitude).size + + if n1 > n1u: + # Data is free-format instead of pre-formatted. + n1 = n1u + n2 = np.unique(mach).size + n3 = np.unique(angle_of_attack).size + + shape = (n1, n2, n3) + + if aviary_inputs is not None and Aircraft.Design.LIFT_POLAR in aviary_inputs: + lift_opts = { + 'val': aviary_inputs.get_val(Aircraft.Design.LIFT_POLAR), + 'static_target': True, + } + else: + lift_opts = {'shape': shape, 'static_target': True} + + if aviary_inputs is not None and Aircraft.Design.DRAG_POLAR in aviary_inputs: + drag_opts = { + 'val': aviary_inputs.get_val(Aircraft.Design.DRAG_POLAR), + 'static_target': True, + } + else: + drag_opts = {'shape': shape, 'static_target': True} + + params[Aircraft.Design.LIFT_POLAR] = lift_opts + params[Aircraft.Design.DRAG_POLAR] = drag_opts + + all_vars = set() + if method == 'low_speed': + all_vars = set(AERO_2DOF_INPUTS + AERO_LS_2DOF_INPUTS) + elif method == 'cruise': + all_vars = set(AERO_2DOF_INPUTS + AERO_CLEAN_2DOF_INPUTS) + elif method == 'tabular_low_speed': + all_vars = AERO_2DOF_TABULAR_LS_INPUTS + elif method == 'tabular_cruise': + all_vars = TABULAR_CORE_INPUTS else: - all_vars = (AERO_2DOF_INPUTS, AERO_CLEAN_2DOF_INPUTS) - - for var in chain.from_iterable(all_vars): - + raise ValueError( + 'GASP-based aero method is not one of the following: (cruise, ' + 'tabular_cruise, low_speed, tabular_low_speed)' + ) + + design_type = aviary_inputs.get_val(Aircraft.Design.TYPE) + + if design_type is AircraftTypes.BLENDED_WING_BODY: + all_vars.add(Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0) + all_vars.add(Aircraft.Fuselage.HYDRAULIC_DIAMETER) + all_vars.add(Aircraft.Fuselage.PLANFORM_AREA) + all_vars.add(Aircraft.Wing.EXPOSED_AREA) + all_vars.add(Aircraft.Wing.ZERO_LIFT_ANGLE) + + for var in all_vars: + # TODO only checking core metadata here!! meta = _MetaData[var] val = meta['default_value'] if val is None: - val = _unspecified + val = 0.0 # _unspecified units = meta['units'] if var in aviary_inputs: @@ -457,23 +646,22 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): except TypeError: val = aviary_inputs.get_val(var) - params[var] = {'val': val, - 'static_target': True} + params[var] = {'val': val, 'units': units, 'static_target': True} return params - def get_bus_variables(self): - if self.code_origin is GASP: + def get_pre_mission_bus_variables(self, aviary_inputs=None): + if self.code_origin is GASP and not self.tabular: return { - "interference_independent_of_shielded_area": { - "mission_name": ['interference_independent_of_shielded_area'], + 'interference_independent_of_shielded_area': { + 'mission_name': ['interference_independent_of_shielded_area'], # "post_mission_name": ['interference_independent_of_shielded_area'], - "units": "unitless", + 'units': 'unitless', }, - "drag_loss_due_to_shielded_wing_area": { - "mission_name": ['drag_loss_due_to_shielded_wing_area'], + 'drag_loss_due_to_shielded_wing_area': { + 'mission_name': ['drag_loss_due_to_shielded_wing_area'], # "post_mission_name": ['drag_loss_due_to_shielded_wing_area'], - "units": "unitless", + 'units': 'unitless', }, } else: @@ -481,7 +669,7 @@ def get_bus_variables(self): def report(self, prob, reports_folder, **kwargs): """ - Generate the report for Aviary core aerodynamics analysis + Generate the report for Aviary core aerodynamics analysis. Parameters ---------- @@ -490,6 +678,7 @@ def report(self, prob, reports_folder, **kwargs): reports_folder : Path Location of the subsystems_report folder this report will be placed in """ + # TODO drag polar plot should go here! if self.code_origin is FLOPS: # FLOPS aero report goes here return @@ -535,13 +724,15 @@ def report(self, prob, reports_folder, **kwargs): Aircraft.Wing.TAPER_RATIO, Aircraft.Wing.THICKNESS_TO_CHORD, Aircraft.Wing.WETTED_AREA, - Mission.Summary.GROSS_MASS, + # Mission.Summary.GROSS_MASS, Mission.Design.LIFT_COEFFICIENT, Mission.Design.MACH, ] TABULAR_CORE_INPUTS = [ Aircraft.Wing.AREA, + Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, + Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, ] # Parameters for low speed aero. @@ -559,20 +750,20 @@ def report(self, prob, reports_folder, **kwargs): Aircraft.Nacelle.FINENESS, Aircraft.Nacelle.LAMINAR_FLOW_LOWER, Aircraft.Nacelle.LAMINAR_FLOW_UPPER, - Aircraft.Nacelle.WETTED_AREA + Aircraft.Nacelle.WETTED_AREA, ] AERO_2DOF_INPUTS = [ Aircraft.Design.CG_DELTA, - Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, # drag increment? + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, # drag increment? Aircraft.Design.STATIC_MARGIN, Aircraft.Fuselage.AVG_DIAMETER, Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, - Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.WETTED_AREA, Aircraft.HorizontalTail.AREA, Aircraft.HorizontalTail.AVERAGE_CHORD, + Aircraft.HorizontalTail.FORM_FACTOR, Aircraft.HorizontalTail.MOMENT_RATIO, Aircraft.HorizontalTail.SPAN, Aircraft.HorizontalTail.SWEEP, @@ -585,28 +776,40 @@ def report(self, prob, reports_folder, **kwargs): Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, Aircraft.VerticalTail.AREA, Aircraft.VerticalTail.AVERAGE_CHORD, + Aircraft.VerticalTail.FORM_FACTOR, Aircraft.VerticalTail.SPAN, Aircraft.Wing.AVERAGE_CHORD, Aircraft.Wing.AREA, Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, Aircraft.Wing.MAX_THICKNESS_LOCATION, Aircraft.Wing.MIN_PRESSURE_LOCATION, - Aircraft.Wing.MOUNTING_TYPE, Aircraft.Wing.SPAN, Aircraft.Wing.SWEEP, Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, Aircraft.Wing.ZERO_LIFT_ANGLE, ] +AERO_2DOF_TABULAR_LS_INPUTS = [Aircraft.Wing.SPAN, Aircraft.Wing.HEIGHT] + AERO_LS_2DOF_INPUTS = [ Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT, Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT, Mission.Takeoff.LIFT_COEFFICIENT_MAX, + Aircraft.Wing.HEIGHT, + Aircraft.Wing.FLAP_CHORD_RATIO, + Mission.Design.GROSS_MASS, ] AERO_CLEAN_2DOF_INPUTS = [ - Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT, # super drag shift? + Aircraft.Design.DRAG_DIVERGENCE_SHIFT, # super drag shift? Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, + Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, + Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, + Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, + Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, ] diff --git a/aviary/subsystems/aerodynamics/flops_based/buffet_lift.py b/aviary/subsystems/aerodynamics/flops_based/buffet_lift.py index 1a415f7351..af6157a024 100644 --- a/aviary/subsystems/aerodynamics/flops_based/buffet_lift.py +++ b/aviary/subsystems/aerodynamics/flops_based/buffet_lift.py @@ -9,73 +9,68 @@ class BuffetLift(om.ExplicitComponent): - """ - Computes lift margin before buffet onset. - """ + """Computes lift margin before buffet onset.""" def initialize(self): - - self.options.declare("num_nodes", default=1, types=int, - desc="Number of nodes along mission segment") + self.options.declare( + 'num_nodes', default=1, types=int, desc='Number of nodes along mission segment' + ) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # Simulation inputs - self.add_input( - Dynamic.Mission.MACH, - shape=(nn), - units='unitless', - desc="Mach number") + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') # Aero design inputs - add_aviary_input(self, Mission.Design.MACH, 0.0) + add_aviary_input(self, Mission.Design.MACH, units='unitless') # Aircraft design inputs - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, 0.0) - add_aviary_input(self, Aircraft.Wing.SWEEP, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') # Declare outputs - self.add_output("DELCLB", shape=(nn), units='unitless', - desc="Delta lift coefficient before buffet onset") + self.add_output( + 'DELCLB', shape=nn, units='unitless', desc='Delta lift coefficient before buffet onset' + ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] + self.declare_partials( + 'DELCLB', Dynamic.Atmosphere.MACH, rows=np.arange(nn), cols=np.arange(nn) + ) self.declare_partials( 'DELCLB', - Dynamic.Mission.MACH, - rows=np.arange(nn), - cols=np.arange(nn)) - self.declare_partials('DELCLB', [Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, - Aircraft.Wing.SWEEP, - Aircraft.Wing.THICKNESS_TO_CHORD, - Mission.Design.MACH]) + [ + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, + Aircraft.Wing.SWEEP, + Aircraft.Wing.THICKNESS_TO_CHORD, + Mission.Design.MACH, + ], + ) def compute(self, inputs, outputs): - """ - Computes lift margin before buffet onset. - """ + """Computes lift margin before buffet onset.""" mach, design_Mach, AR, CAM, SW25, TC = inputs.values() del_Mach = mach - design_Mach - TC23 = TC**(2.0/3.0) + TC23 = TC ** (2.0 / 3.0) TC23 = np.repeat(TC23, len(del_Mach)) x = np.transpose(np.array([TC23, del_Mach])) # dFCLB = [dFCLB_dTC23, dFCLB_dDELM] FCLB, dFCLB = BUFTTable.interpolate(x, compute_derivative=True) - DELCLB = FCLB * (AR * (1.0 + CAM/10.0) / np.cos(SW25 / _units.degree)) + DELCLB = FCLB * (AR * (1.0 + CAM / 10.0) / np.cos(SW25 / _units.degree)) self.FCLB = FCLB self.dFCLB = dFCLB outputs['DELCLB'] = DELCLB def compute_partials(self, inputs, partials): - TC = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] SW25 = inputs[Aircraft.Wing.SWEEP] AR = inputs[Aircraft.Wing.ASPECT_RATIO] @@ -90,7 +85,7 @@ def compute_partials(self, inputs, partials): cos_fact = 1.0 / np.cos(SW25_rad) dTC23_dTC = (2.0 / 3.0) * TC ** (-1.0 / 3.0) - dDELCLB_dFCLB = AR * (1.0 + CAM/10.0) * cos_fact + dDELCLB_dFCLB = AR * (1.0 + CAM / 10.0) * cos_fact ddel_Mach_dMach = 1.0 ddel_Mach_ddesign_Mach = -1.0 @@ -101,20 +96,19 @@ def compute_partials(self, inputs, partials): dCLB_ddesign_Mach = dDELCLB_dFCLB * dFCLB_ddel_Mach * ddel_Mach_ddesign_Mach # wrt AR - dCLB_dAR = FCLB * (1.0 + CAM/10.0) * cos_fact + dCLB_dAR = FCLB * (1.0 + CAM / 10.0) * cos_fact # wrt TC dCLB_dTC = dDELCLB_dFCLB * dFCLB_dTC23 * dTC23_dTC # wrt SW25 - dCLB_dSW25 = (1.0 / a) * AR * FCLB * (1.0 + CAM/10.0) * \ - np.sin(SW25_rad) * cos_fact ** 2 + dCLB_dSW25 = (1.0 / a) * AR * FCLB * (1.0 + CAM / 10.0) * np.sin(SW25_rad) * cos_fact**2 # wrt CAM dCLB_dCAM = FCLB * AR / 10.0 * cos_fact - partials["DELCLB", Dynamic.Mission.MACH] = dCLB_dMach - partials["DELCLB", Mission.Design.MACH] = dCLB_ddesign_Mach + partials['DELCLB', Dynamic.Atmosphere.MACH] = dCLB_dMach + partials['DELCLB', Mission.Design.MACH] = dCLB_ddesign_Mach partials['DELCLB', Aircraft.Wing.ASPECT_RATIO] = dCLB_dAR partials['DELCLB', Aircraft.Wing.THICKNESS_TO_CHORD] = dCLB_dTC partials['DELCLB', Aircraft.Wing.SWEEP] = dCLB_dSW25 @@ -124,16 +118,20 @@ def compute_partials(self, inputs, partials): BUFT = np.array( - [[8010, -0.8, -0.6, -0.4, -0.3, -0.2, -0.1, 0.0, 0.05, 0.1, 0.15], - [0.1, 0.078, 0.076, 0.061, 0.050, 0.046, 0.051, 0.070, 0.09, 0.12, 0.156], - [0.12, 0.078, 0.076, 0.061, 0.050, 0.043, 0.036, 0.039, 0.051, 0.073, 0.104], - [0.14, 0.078, 0.076, 0.061, 0.050, 0.042, 0.034, 0.030, 0.031, 0.040, 0.057], - [0.16, 0.078, 0.076, 0.061, 0.050, 0.041, 0.031, 0.023, 0.020, 0.016, 0.010], - [0.18, 0.078, 0.076, 0.061, 0.050, 0.040, 0.030, 0.018, 0.010, 0.002, -0.009], - [0.20, 0.078, 0.076, 0.061, 0.050, 0.040, 0.029, 0.015, 0.005, -0.007, -0.020], - [0.24, 0.078, 0.076, 0.061, 0.050, 0.040, 0.028, 0.009, -0.005, -0.020, -0.036], - [0.30, 0.078, 0.076, 0.061, 0.050, 0.040, 0.028, 0.004, -0.015, -0.037, -0.060]]) - - -BUFTTable = InterpND(method='lagrange2', points=(BUFT[1:, 0], BUFT[0, 1:]), values=BUFT[1:, 1:], - extrapolate=True) + [ + [8010, -0.8, -0.6, -0.4, -0.3, -0.2, -0.1, 0.0, 0.05, 0.1, 0.15], + [0.1, 0.078, 0.076, 0.061, 0.050, 0.046, 0.051, 0.070, 0.09, 0.12, 0.156], + [0.12, 0.078, 0.076, 0.061, 0.050, 0.043, 0.036, 0.039, 0.051, 0.073, 0.104], + [0.14, 0.078, 0.076, 0.061, 0.050, 0.042, 0.034, 0.030, 0.031, 0.040, 0.057], + [0.16, 0.078, 0.076, 0.061, 0.050, 0.041, 0.031, 0.023, 0.020, 0.016, 0.010], + [0.18, 0.078, 0.076, 0.061, 0.050, 0.040, 0.030, 0.018, 0.010, 0.002, -0.009], + [0.20, 0.078, 0.076, 0.061, 0.050, 0.040, 0.029, 0.015, 0.005, -0.007, -0.020], + [0.24, 0.078, 0.076, 0.061, 0.050, 0.040, 0.028, 0.009, -0.005, -0.020, -0.036], + [0.30, 0.078, 0.076, 0.061, 0.050, 0.040, 0.028, 0.004, -0.015, -0.037, -0.060], + ] +) + + +BUFTTable = InterpND( + method='lagrange2', points=(BUFT[1:, 0], BUFT[0, 1:]), values=BUFT[1:, 1:], extrapolate=True +) diff --git a/aviary/subsystems/aerodynamics/flops_based/compressibility_drag.py b/aviary/subsystems/aerodynamics/flops_based/compressibility_drag.py index 9a320d2fea..3a5a0c4c70 100644 --- a/aviary/subsystems/aerodynamics/flops_based/compressibility_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/compressibility_drag.py @@ -1,4 +1,3 @@ - import numpy as np import openmdao.api as om from openmdao.components.interp_util.interp import InterpND @@ -8,66 +7,72 @@ class CompressibilityDrag(om.ExplicitComponent): - """ - Computes compressibility drag coefficient. - """ + """Computes compressibility drag coefficient.""" def initialize(self): - - self.options.declare("num_nodes", default=6, types=int, - desc="Number of nodes along mission segment") + self.options.declare( + 'num_nodes', default=6, types=int, desc='Number of nodes along mission segment' + ) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # Simulation inputs - self.add_input( - Dynamic.Mission.MACH, - shape=(nn), - units='unitless', - desc="Mach number") + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') # Aero design inputs - add_aviary_input(self, Mission.Design.MACH, 0.0) + add_aviary_input(self, Mission.Design.MACH, units='unitless') # Aircraft design inputs - add_aviary_input(self, Aircraft.Design.BASE_AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, 0.0) - add_aviary_input(self, Aircraft.Wing.SWEEP, 0.0) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) - add_aviary_input(self, Aircraft.Fuselage.CROSS_SECTION, 0.0) - add_aviary_input(self, Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.0) - add_aviary_input(self, Aircraft.Fuselage.LENGTH_TO_DIAMETER, 0.0) + add_aviary_input(self, Aircraft.Design.BASE_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.CROSS_SECTION, units='ft**2') + add_aviary_input(self, Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.LENGTH_TO_DIAMETER, units='unitless') # Outputs - self.add_output('compress_drag_coeff', shape=(nn, ), units='unitless', - desc="Drag coefficient due to compressibility.") + self.add_output( + 'compress_drag_coeff', + shape=(nn,), + units='unitless', + desc='Drag coefficient due to compressibility.', + ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] row_col = np.arange(nn) - self.declare_partials(of='compress_drag_coeff', wrt=[Dynamic.Mission.MACH], - rows=row_col, cols=row_col) - - wrt2 = [Aircraft.Wing.THICKNESS_TO_CHORD, Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.SWEEP, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, - Aircraft.Fuselage.CROSS_SECTION, Aircraft.Wing.AREA, - Aircraft.Fuselage.LENGTH_TO_DIAMETER, Aircraft.Wing.TAPER_RATIO, - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, Aircraft.Design.BASE_AREA, - Mission.Design.MACH] + self.declare_partials( + of='compress_drag_coeff', + wrt=[Dynamic.Atmosphere.MACH], + rows=row_col, + cols=row_col, + ) + + wrt2 = [ + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.SWEEP, + Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, + Aircraft.Fuselage.CROSS_SECTION, + Aircraft.Wing.AREA, + Aircraft.Fuselage.LENGTH_TO_DIAMETER, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, + Aircraft.Design.BASE_AREA, + Mission.Design.MACH, + ] self.declare_partials(of='compress_drag_coeff', wrt=wrt2) def compute(self, inputs, outputs): - """ - Calculate compressibility drag. - """ - - del_mach = inputs[Dynamic.Mission.MACH] - inputs[Mission.Design.MACH] + """Calculate compressibility drag.""" + del_mach = inputs[Dynamic.Atmosphere.MACH] - inputs[Mission.Design.MACH] idx_super = np.where(del_mach > 0.05) idx_sub = np.where(del_mach <= 0.05) @@ -80,11 +85,8 @@ def compute(self, inputs, outputs): outputs['compress_drag_coeff'][idx_sub] = cdc_sub def _compute_supersonic(self, inputs, outputs, idx): - """ - Calculate compressibility drag for supersonic speeds. - """ - - mach = inputs[Dynamic.Mission.MACH][idx] + """Calculate compressibility drag for supersonic speeds.""" + mach = inputs[Dynamic.Atmosphere.MACH][idx] nn = len(mach) del_mach = mach - inputs[Mission.Design.MACH] AR = inputs[Aircraft.Wing.ASPECT_RATIO] @@ -98,8 +100,7 @@ def _compute_supersonic(self, inputs, outputs, idx): fuselage_len_to_diam_ratio = inputs[Aircraft.Fuselage.LENGTH_TO_DIAMETER] diam_to_wing_span_ratio = inputs[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN] - ART = AR * np.tan(sweep25 / 57.2958) \ - + (1.0 - wing_taper_ratio) / (1.0 + wing_taper_ratio) + ART = AR * np.tan(sweep25 / 57.2958) + (1.0 - wing_taper_ratio) / (1.0 + wing_taper_ratio) x = np.empty((nn, 2), dtype=mach.dtype) x[:, 0] = del_mach x[:, 1] = ART @@ -124,25 +125,25 @@ def _compute_supersonic(self, inputs, outputs, idx): CD4[self.clamp_CD4] = 0.0 self.dCD4[self.clamp_CD4] = 0.0 - fuselage_compress_drag_coeff = CD4 * \ - (fuse_area / wing_area * (1.0 / fuselage_len_to_diam_ratio ** 2)) + fuselage_compress_drag_coeff = CD4 * ( + fuse_area / wing_area * (1.0 / fuselage_len_to_diam_ratio**2) + ) compress_drag_coeff += fuselage_compress_drag_coeff # Wing fuselage interference. idx_mach = np.where(mach >= 1.0) if len(idx_mach[0]) > 0: - x[:, 1] = diam_to_wing_span_ratio - CD5, self.dCD5 = WFITable.interpolate( - x[idx_mach], compute_derivative=True) + CD5, self.dCD5 = WFITable.interpolate(x[idx_mach], compute_derivative=True) # TODO: is this some kind of override? if wing_taper_ratio == 1.0: wing_taper_ratio = 0.5 - int_compress_drag_coeff = CD5 * (1.0 / (1.0 - wing_taper_ratio) - / np.cos(sweep25 / 57.2958)) + int_compress_drag_coeff = CD5 * ( + 1.0 / (1.0 - wing_taper_ratio) / np.cos(sweep25 / 57.2958) + ) compress_drag_coeff[idx_mach] += int_compress_drag_coeff @@ -162,11 +163,8 @@ def _compute_supersonic(self, inputs, outputs, idx): return compress_drag_coeff def _compute_subsonic(self, inputs, outputs, idx): - """ - Calculate compressibility drag for subsonic speeds. - """ - - mach = inputs[Dynamic.Mission.MACH][idx] + """Calculate compressibility drag for subsonic speeds.""" + mach = inputs[Dynamic.Atmosphere.MACH][idx] nn = len(mach) del_mach = mach - inputs[Mission.Design.MACH] TC = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] @@ -201,8 +199,9 @@ def _compute_subsonic(self, inputs, outputs, idx): CD2[self.clamp_CD2] = 0.0 self.dCD2[self.clamp_CD2] = 0.0 - fuselage_compress_drag_coeff = CD2 * \ - (fuse_area / wing_area * (1.0 / fuselage_len_to_diam_ratio ** 2)) + fuselage_compress_drag_coeff = CD2 * ( + fuse_area / wing_area * (1.0 / fuselage_len_to_diam_ratio**2) + ) compress_drag_coeff += fuselage_compress_drag_coeff @@ -223,8 +222,7 @@ def compute_partials(self, inputs, partials): :param partials: _description_ :type partials: _type_ """ - - del_mach = inputs[Dynamic.Mission.MACH] - inputs[Mission.Design.MACH] + del_mach = inputs[Dynamic.Atmosphere.MACH] - inputs[Mission.Design.MACH] idx_super = np.where(del_mach > 0.05) idx_sub = np.where(del_mach <= 0.05) @@ -234,9 +232,7 @@ def compute_partials(self, inputs, partials): self._compute_partials_subsonic(inputs, partials, idx_sub) def _compute_partials_supersonic(self, inputs, partials, idx): - - mach = inputs[Dynamic.Mission.MACH][idx] - nn = len(mach) + mach = inputs[Dynamic.Atmosphere.MACH][idx] AR = inputs[Aircraft.Wing.ASPECT_RATIO] TC = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] max_camber_70 = inputs[Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN] @@ -252,7 +248,7 @@ def _compute_partials_supersonic(self, inputs, partials, idx): CD5 = self.CD5 dCd3_dCD3 = TC ** (5.0 / 3.0) * (1.0 + max_camber_70 / 10.0) - dCd4_dCD4 = (fuse_area / wing_area) * (1.0 / fuselage_len_to_diam_ratio ** 2) + dCd4_dCD4 = (fuse_area / wing_area) * (1.0 / fuselage_len_to_diam_ratio**2) dCd5_dCD5 = 1.0 / (1.0 - wing_taper_ratio) / np.cos(sweep25 / 57.2958) ddel_mach_ddesign_Mach = -1.0 @@ -273,27 +269,27 @@ def _compute_partials_supersonic(self, inputs, partials, idx): dCd_ddesign_Mach = dCd3_dCD3 * dCD3_ddel_mach * ddel_mach_ddesign_Mach # wrt TC - dCd3_dTC = (5.0 / 3.0) * CD3 * TC**(2.0 / 3.0) * (1.0 + 0.1 * max_camber_70) + dCd3_dTC = (5.0 / 3.0) * CD3 * TC ** (2.0 / 3.0) * (1.0 + 0.1 * max_camber_70) dCd_dTC = dCd3_dTC # wrt max_camber_70 - dCd3_dmax_camber_70 = 0.1 * CD3 * TC**(5.0 / 3.0) + dCd3_dmax_camber_70 = 0.1 * CD3 * TC ** (5.0 / 3.0) dCd_dmax_camber_70 = dCd3_dmax_camber_70 # wrt AR dART_dAR = np.tan(sweep25 / 57.2958) dCd_dAR = dCd3_dCD3 * dCD3_dART * dART_dAR - dART_dwing_taper_ratio = -(1 - wing_taper_ratio) / (wing_taper_ratio + 1)**2 \ - - 1.0 / (wing_taper_ratio + 1) + dART_dwing_taper_ratio = -(1 - wing_taper_ratio) / (wing_taper_ratio + 1) ** 2 - 1.0 / ( + wing_taper_ratio + 1 + ) - dART_dsweep25 = AR * (np.tan(sweep25 / 57.2958)**2 + 1) / 57.2958 + dART_dsweep25 = AR * (np.tan(sweep25 / 57.2958) ** 2 + 1) / 57.2958 dCd3_dsweep25 = dCd3_dCD3 * dCD3_dART * dART_dsweep25 dCd_ddiam_to_wing_span_ratio = 0 if fuse_area > 0.0: - # wrt Mach dCd4_dMach = dCd4_dCD4 * dCD4_dMach dCd_dMach = dCd3_dMach + dCd4_dMach @@ -308,16 +304,17 @@ def _compute_partials_supersonic(self, inputs, partials, idx): dCd_dbase_area = dCd4_dCD4 * dCD4_dSOS * dSOS_dbase_area # wrt wing_area - dCd_dwing_area = -CD4 * fuse_area / \ - (wing_area * fuselage_len_to_diam_ratio)**2 + dCd_dwing_area = -CD4 * fuse_area / (wing_area * fuselage_len_to_diam_ratio) ** 2 # wrt fuselage_len_to_diam_ratio - dCd_dfuselage_len_to_diam_ratio = -2.0 * CD4 * fuse_area \ - / (wing_area * fuselage_len_to_diam_ratio**3) + dCd_dfuselage_len_to_diam_ratio = ( + -2.0 * CD4 * fuse_area / (wing_area * fuselage_len_to_diam_ratio**3) + ) # wrt diam_to_wing_span_ratio - dCd_ddiam_to_wing_span_ratio = np.zeros(dCd_dwing_area.shape, - dtype=dCd_dwing_area.dtype) + dCd_ddiam_to_wing_span_ratio = np.zeros( + dCd_dwing_area.shape, dtype=dCd_dwing_area.dtype + ) # wrt wing_taper_ratio dCd_dwing_taper_ratio = dCd3_dCD3 * dCD3_dART * dART_dwing_taper_ratio @@ -328,23 +325,24 @@ def _compute_partials_supersonic(self, inputs, partials, idx): # Wing fuselage interference. idx_mach = np.where(mach >= 1.0) if len(idx_mach[0]) > 0: - dCd_dMach[idx_mach] += dCd5_dCD5 * dCD5_dMach - dCd5_dwing_taper_ratio = CD5 / \ - ((1.0 - wing_taper_ratio)**2 * np.cos(sweep25 / 57.2958)) + dCd5_dwing_taper_ratio = CD5 / ( + (1.0 - wing_taper_ratio) ** 2 * np.cos(sweep25 / 57.2958) + ) dCd_dwing_taper_ratio[idx_mach] += dCd5_dwing_taper_ratio # wrt diam_to_wing_span_ratio - dCd_ddiam_to_wing_span_ratio[idx_mach] = dCd5_dCD5 * \ - dCD5_ddiam_to_wing_span_ratio + dCd_ddiam_to_wing_span_ratio[idx_mach] = dCd5_dCD5 * dCD5_ddiam_to_wing_span_ratio - dCd5_dsweep25 = CD5 * np.sin(sweep25 / 57.2958) / \ - (57.2958 * (1.0 - wing_taper_ratio) * np.cos(sweep25 / 57.2958)**2) + dCd5_dsweep25 = ( + CD5 + * np.sin(sweep25 / 57.2958) + / (57.2958 * (1.0 - wing_taper_ratio) * np.cos(sweep25 / 57.2958) ** 2) + ) dCd_dsweep25[idx_mach] += dCd5_dsweep25 else: - dCd_dMach = dCd3_dMach dCd_dfuse_area = 0.0 dCd_dbase_area = 0.0 @@ -353,32 +351,26 @@ def _compute_partials_supersonic(self, inputs, partials, idx): dCd_dwing_taper_ratio = dCd3_dCD3 * dCD3_dART * dART_dwing_taper_ratio dCd_dsweep25 = dCd3_dsweep25 - partials["compress_drag_coeff", Dynamic.Mission.MACH][idx] = dCd_dMach - partials["compress_drag_coeff", Mission.Design.MACH][idx, 0] = dCd_ddesign_Mach - partials["compress_drag_coeff", Aircraft.Wing.THICKNESS_TO_CHORD][idx, 0] = dCd_dTC - partials["compress_drag_coeff", - Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN][idx, 0] = dCd_dmax_camber_70 - partials["compress_drag_coeff", - Aircraft.Fuselage.CROSS_SECTION][idx, 0] = dCd_dfuse_area - partials["compress_drag_coeff", - Aircraft.Design.BASE_AREA][idx, - 0] = dCd_dbase_area - partials["compress_drag_coeff", Aircraft.Wing.AREA][idx, 0] = dCd_dwing_area - partials["compress_drag_coeff", - Aircraft.Fuselage.LENGTH_TO_DIAMETER][idx, - 0] = dCd_dfuselage_len_to_diam_ratio - partials["compress_drag_coeff", - Aircraft.Wing.TAPER_RATIO][idx, 0] = dCd_dwing_taper_ratio - partials["compress_drag_coeff", Aircraft.Wing.SWEEP][idx, 0] = dCd_dsweep25 - partials["compress_drag_coeff", Aircraft.Wing.ASPECT_RATIO][idx, 0] = dCd_dAR - partials["compress_drag_coeff", - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN][idx, - 0] = dCd_ddiam_to_wing_span_ratio + partials['compress_drag_coeff', Dynamic.Atmosphere.MACH][idx] = dCd_dMach + partials['compress_drag_coeff', Mission.Design.MACH][idx, 0] = dCd_ddesign_Mach + partials['compress_drag_coeff', Aircraft.Wing.THICKNESS_TO_CHORD][idx, 0] = dCd_dTC + partials['compress_drag_coeff', Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN][idx, 0] = ( + dCd_dmax_camber_70 + ) + partials['compress_drag_coeff', Aircraft.Fuselage.CROSS_SECTION][idx, 0] = dCd_dfuse_area + partials['compress_drag_coeff', Aircraft.Design.BASE_AREA][idx, 0] = dCd_dbase_area + partials['compress_drag_coeff', Aircraft.Wing.AREA][idx, 0] = dCd_dwing_area + partials['compress_drag_coeff', Aircraft.Fuselage.LENGTH_TO_DIAMETER][idx, 0] = ( + dCd_dfuselage_len_to_diam_ratio + ) + partials['compress_drag_coeff', Aircraft.Wing.TAPER_RATIO][idx, 0] = dCd_dwing_taper_ratio + partials['compress_drag_coeff', Aircraft.Wing.SWEEP][idx, 0] = dCd_dsweep25 + partials['compress_drag_coeff', Aircraft.Wing.ASPECT_RATIO][idx, 0] = dCd_dAR + partials['compress_drag_coeff', Aircraft.Fuselage.DIAMETER_TO_WING_SPAN][idx, 0] = ( + dCd_ddiam_to_wing_span_ratio + ) def _compute_partials_subsonic(self, inputs, partials, idx): - - mach = inputs[Dynamic.Mission.MACH][idx] - nn = len(mach) TC = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] max_camber_70 = inputs[Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN] fuse_area = inputs[Aircraft.Fuselage.CROSS_SECTION] @@ -390,7 +382,7 @@ def _compute_partials_subsonic(self, inputs, partials, idx): CD2 = self.CD2 dCd1_dCD1 = TC ** (5.0 / 3.0) * (1.0 + 0.1 * max_camber_70) - dCd2_dCD2 = fuse_area / wing_area * (1.0 / fuselage_len_to_diam_ratio ** 2) + dCd2_dCD2 = fuse_area / wing_area * (1.0 / fuselage_len_to_diam_ratio**2) dTOC_dTC = (2.0 / 3.0) * TC ** (-1.0 / 3.0) ddel_mach_dMach = 1.0 @@ -410,22 +402,22 @@ def _compute_partials_subsonic(self, inputs, partials, idx): dCd_ddesign_Mach = -dCd1_dCD1 * dCD1_ddel_mach # wrt TC - dCd1_dTC = (5.0 / 3.0) * CD1 * (1.0 + 0.1 * max_camber_70) * TC**(2.0 / 3.0) + dCd1_dTC = (5.0 / 3.0) * CD1 * (1.0 + 0.1 * max_camber_70) * TC ** (2.0 / 3.0) dCD1_dTC = dCD1_dTOC * dTOC_dTC dCd_dTC = dCd1_dTC + dCd1_dCD1 * dCD1_dTC # wrt max_camber_70 - dCd_dmax_camber_70 = CD1 * (1.0 / 10.0) * TC**(5.0 / 3.0) + dCd_dmax_camber_70 = CD1 * (1.0 / 10.0) * TC ** (5.0 / 3.0) - partials["compress_drag_coeff", Dynamic.Mission.MACH][idx] = dCd_dMach - partials["compress_drag_coeff", Mission.Design.MACH][idx, 0] = dCd_ddesign_Mach - partials["compress_drag_coeff", Aircraft.Wing.THICKNESS_TO_CHORD][idx, 0] = dCd_dTC - partials["compress_drag_coeff", - Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN][idx, 0] = dCd_dmax_camber_70 + partials['compress_drag_coeff', Dynamic.Atmosphere.MACH][idx] = dCd_dMach + partials['compress_drag_coeff', Mission.Design.MACH][idx, 0] = dCd_ddesign_Mach + partials['compress_drag_coeff', Aircraft.Wing.THICKNESS_TO_CHORD][idx, 0] = dCd_dTC + partials['compress_drag_coeff', Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN][idx, 0] = ( + dCd_dmax_camber_70 + ) # Contribution of fuselage. if fuse_area > 0.0: - dCd2_dfuse_area = CD2 / (wing_area * fuselage_len_to_diam_ratio**2) dSOS_dfuse_area = -base_area / fuse_area**2 dCd_dfuse_area = dCd2_dfuse_area + dCd2_dCD2 * dCD2_dSOS * dSOS_dfuse_area @@ -435,130 +427,171 @@ def _compute_partials_subsonic(self, inputs, partials, idx): dCd_dbase_area = dCd2_dCD2 * dCD2_dSOS * dSOS_dbase_area # wrt wing_area - dCd_dwing_area = -CD2 * fuse_area / \ - (wing_area * fuselage_len_to_diam_ratio)**2 + dCd_dwing_area = -CD2 * fuse_area / (wing_area * fuselage_len_to_diam_ratio) ** 2 # wrt fuselage_len_to_diam_ratio - dCd_dfuselage_len_to_diam_ratio = -2.0 * CD2 * fuse_area \ - / (wing_area * fuselage_len_to_diam_ratio**3) - - partials["compress_drag_coeff", - Aircraft.Fuselage.CROSS_SECTION][idx, 0] = dCd_dfuse_area - partials["compress_drag_coeff", - Aircraft.Design.BASE_AREA][idx, 0] = dCd_dbase_area - partials["compress_drag_coeff", Aircraft.Wing.AREA][idx, 0] = dCd_dwing_area - partials["compress_drag_coeff", - Aircraft.Fuselage.LENGTH_TO_DIAMETER][idx, - 0] = dCd_dfuselage_len_to_diam_ratio + dCd_dfuselage_len_to_diam_ratio = ( + -2.0 * CD2 * fuse_area / (wing_area * fuselage_len_to_diam_ratio**3) + ) + + partials['compress_drag_coeff', Aircraft.Fuselage.CROSS_SECTION][idx, 0] = ( + dCd_dfuse_area + ) + partials['compress_drag_coeff', Aircraft.Design.BASE_AREA][idx, 0] = dCd_dbase_area + partials['compress_drag_coeff', Aircraft.Wing.AREA][idx, 0] = dCd_dwing_area + partials['compress_drag_coeff', Aircraft.Fuselage.LENGTH_TO_DIAMETER][idx, 0] = ( + dCd_dfuselage_len_to_diam_ratio + ) else: - partials["compress_drag_coeff", - Aircraft.Fuselage.CROSS_SECTION][idx, 0] = 0.0 - partials["compress_drag_coeff", Aircraft.Design.BASE_AREA][idx, 0] = 0.0 - partials["compress_drag_coeff", Aircraft.Wing.AREA][idx, 0] = 0.0 - partials["compress_drag_coeff", - Aircraft.Fuselage.LENGTH_TO_DIAMETER][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Fuselage.CROSS_SECTION][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Design.BASE_AREA][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Wing.AREA][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Fuselage.LENGTH_TO_DIAMETER][idx, 0] = 0.0 - partials["compress_drag_coeff", Aircraft.Wing.TAPER_RATIO][idx, 0] = 0.0 - partials["compress_drag_coeff", Aircraft.Wing.SWEEP][idx, 0] = 0.0 - partials["compress_drag_coeff", Aircraft.Wing.ASPECT_RATIO][idx, 0] = 0.0 - partials["compress_drag_coeff", - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Wing.TAPER_RATIO][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Wing.SWEEP][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Wing.ASPECT_RATIO][idx, 0] = 0.0 + partials['compress_drag_coeff', Aircraft.Fuselage.DIAMETER_TO_WING_SPAN][idx, 0] = 0.0 # Tables -PCW = np.array([[13007.0, .100, .120, .140, .160, .180, .220, .300], - [-.800, .00, .00, .00, .00, .00, .00, .00], - [-.200, .0600, .040, .020, .0200, .0100, .0080, .0020], - [-.160, .0720, .050, .030, .0260, .0170, .0160, .0060], - [-.120, .1000, .060, .040, .0380, .0250, .0240, .0120], - [-.080, .1250, .080, .050, .0490, .0350, .0330, .0190], - [-.040, .1600, .120, .080, .0680, .0540, .0470, .0300], - [-.020, .2000, .160, .120, .1100, .0700, .0590, .0390], - [0.000, .2800, .220, .160, .1200, .0930, .0770, .0520], - [.010, .3400, .270, .200, .1520, .1180, .0930, .0610], - [.020, .4400, .330, .240, .1970, .1530, .1170, .0730], - [.030, .6400, .450, .310, .2550, .2030, .1480, .0870], - [.040, 1.1000, .660, .410, .3250, .2700, .1870, .1030], - [.050, 1.9000, 1.020, .560, .4000, .3500, .2350, .1270]]) - -BSUB = np.array([[17004.0, 1.00, 1.20, 1.40, 1.50], - [.2000, 0.00, 0.00, 0.00, 0.00], - [.5000, 0.00, 0.00, 0.00, 0.00], - [.7000, 0.00, 0.00, 0.00, 0.00], - [.7800, 0.00, 0.00, 0.00, 0.00], - [.8200, 0.00, 0.00, 0.150, 0.210], - [.8400, 0.00, 0.150, 0.200, 0.350], - [.8600, 0.090, 0.220, 0.400, 0.520], - [.8800, 0.200, 0.380, 0.610, 0.780], - [.9000, 0.380, 0.580, 0.910, 1.100], - [.9100, 0.530, 0.750, 1.100, 1.330], - [.9200, 0.730, 0.950, 1.300, 1.600], - [.9300, 0.950, 1.200, 1.650, 1.930], - [.9400, 1.300, 1.550, 2.050, 2.490], - [.9500, 1.750, 2.200, 2.900, 3.650], - [.9600, 2.450, 3.250, 4.500, 6.400], - [.9650, 3.000, 4.220, 6.300, 8.450], - [.9700, 3.900, 5.600, 9.500, 11.500]]) - -PCAR = np.array([[16009.0, 1.00, 1.50, 2.00, 2.50, 3.00, 3.50, 4.00, 5.00, 6.00], - [.050, 2.400, 1.700, 1.170, .850, .730, .670, .600, .540, .520], - [.070, 3.100, 2.250, 1.580, 1.100, .890, .770, .700, .620, .600], - [.090, 3.550, 2.610, 1.880, 1.240, .990, .870, .750, .670, .650], - [.110, 3.850, 2.880, 2.030, 1.330, 1.070, .920, .800, .710, .680], - [.130, 3.970, 3.050, 2.140, 1.410, 1.120, .960, .840, .740, .710], - [.150, 4.000, 3.100, 2.170, 1.480, 1.160, .990, .860, .750, .720], - [.200, 3.900, 3.000, 2.200, 1.550, 1.200, 1.000, .860, .740, .700], - [.250, 3.680, 2.850, 2.160, 1.570, 1.200, 1.000, .830, .700, .650], - [.300, 3.430, 2.700, 2.100, 1.550, 1.170, .920, .770, .630, .580], - [.400, 3.030, 2.450, 1.900, 1.470, 1.100, .880, .730, .590, .530], - [.500, 2.750, 2.220, 1.710, 1.370, 1.020, .840, .730, .570, .520], - [.600, 2.490, 2.000, 1.550, 1.260, .970, .810, .740, .560, .510], - [.700, 2.250, 1.800, 1.410, 1.170, .910, .790, .710, .550, .510], - [.800, 1.990, 1.620, 1.300, 1.100, .880, .750, .700, .550, .500], - [.900, 1.800, 1.500, 1.200, 1.000, .840, .700, .660, .540, .500], - [1.000, 1.650, 1.400, 1.100, .950, .800, .700, .660, .540, .500]]) - -BSUP = np.array([[14006.0, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50], - [1.000, 24.50, 20.00, 16.20, 13.40, 11.10, 9.50], - [1.050, 30.70, 23.60, 20.00, 16.00, 12.90, 10.50], - [1.100, 33.00, 26.20, 21.50, 17.40, 14.00, 11.10], - [1.150, 34.30, 27.30, 22.30, 18.20, 14.80, 11.60], - [1.200, 34.70, 27.70, 22.50, 18.50, 15.00, 11.90], - [1.250, 34.50, 27.50, 22.40, 18.20, 14.90, 11.90], - [1.300, 33.80, 27.00, 22.00, 17.60, 14.50, 11.70], - [1.350, 32.90, 26.40, 21.70, 17.30, 14.20, 11.40], - [1.400, 32.40, 25.90, 21.40, 17.20, 14.10, 11.00], - [1.500, 32.00, 25.60, 21.10, 17.00, 14.10, 10.90], - [1.600, 32.00, 25.60, 21.00, 17.00, 14.10, 10.90], - [1.800, 32.00, 25.60, 21.00, 17.00, 14.20, 11.40], - [2.000, 32.00, 25.60, 21.00, 17.10, 14.40, 11.80], - [2.200, 32.00, 25.60, 21.00, 17.30, 14.60, 12.00]]) +PCW = np.array( + [ + [13007.0, 0.100, 0.120, 0.140, 0.160, 0.180, 0.220, 0.300], + [-0.800, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00], + [-0.200, 0.0600, 0.040, 0.020, 0.0200, 0.0100, 0.0080, 0.0020], + [-0.160, 0.0720, 0.050, 0.030, 0.0260, 0.0170, 0.0160, 0.0060], + [-0.120, 0.1000, 0.060, 0.040, 0.0380, 0.0250, 0.0240, 0.0120], + [-0.080, 0.1250, 0.080, 0.050, 0.0490, 0.0350, 0.0330, 0.0190], + [-0.040, 0.1600, 0.120, 0.080, 0.0680, 0.0540, 0.0470, 0.0300], + [-0.020, 0.2000, 0.160, 0.120, 0.1100, 0.0700, 0.0590, 0.0390], + [0.000, 0.2800, 0.220, 0.160, 0.1200, 0.0930, 0.0770, 0.0520], + [0.010, 0.3400, 0.270, 0.200, 0.1520, 0.1180, 0.0930, 0.0610], + [0.020, 0.4400, 0.330, 0.240, 0.1970, 0.1530, 0.1170, 0.0730], + [0.030, 0.6400, 0.450, 0.310, 0.2550, 0.2030, 0.1480, 0.0870], + [0.040, 1.1000, 0.660, 0.410, 0.3250, 0.2700, 0.1870, 0.1030], + [0.050, 1.9000, 1.020, 0.560, 0.4000, 0.3500, 0.2350, 0.1270], + ] +) + +BSUB = np.array( + [ + [17004.0, 1.00, 1.20, 1.40, 1.50], + [0.2000, 0.00, 0.00, 0.00, 0.00], + [0.5000, 0.00, 0.00, 0.00, 0.00], + [0.7000, 0.00, 0.00, 0.00, 0.00], + [0.7800, 0.00, 0.00, 0.00, 0.00], + [0.8200, 0.00, 0.00, 0.150, 0.210], + [0.8400, 0.00, 0.150, 0.200, 0.350], + [0.8600, 0.090, 0.220, 0.400, 0.520], + [0.8800, 0.200, 0.380, 0.610, 0.780], + [0.9000, 0.380, 0.580, 0.910, 1.100], + [0.9100, 0.530, 0.750, 1.100, 1.330], + [0.9200, 0.730, 0.950, 1.300, 1.600], + [0.9300, 0.950, 1.200, 1.650, 1.930], + [0.9400, 1.300, 1.550, 2.050, 2.490], + [0.9500, 1.750, 2.200, 2.900, 3.650], + [0.9600, 2.450, 3.250, 4.500, 6.400], + [0.9650, 3.000, 4.220, 6.300, 8.450], + [0.9700, 3.900, 5.600, 9.500, 11.500], + ] +) + +PCAR = np.array( + [ + [16009.0, 1.00, 1.50, 2.00, 2.50, 3.00, 3.50, 4.00, 5.00, 6.00], + [0.050, 2.400, 1.700, 1.170, 0.850, 0.730, 0.670, 0.600, 0.540, 0.520], + [0.070, 3.100, 2.250, 1.580, 1.100, 0.890, 0.770, 0.700, 0.620, 0.600], + [0.090, 3.550, 2.610, 1.880, 1.240, 0.990, 0.870, 0.750, 0.670, 0.650], + [0.110, 3.850, 2.880, 2.030, 1.330, 1.070, 0.920, 0.800, 0.710, 0.680], + [0.130, 3.970, 3.050, 2.140, 1.410, 1.120, 0.960, 0.840, 0.740, 0.710], + [0.150, 4.000, 3.100, 2.170, 1.480, 1.160, 0.990, 0.860, 0.750, 0.720], + [0.200, 3.900, 3.000, 2.200, 1.550, 1.200, 1.000, 0.860, 0.740, 0.700], + [0.250, 3.680, 2.850, 2.160, 1.570, 1.200, 1.000, 0.830, 0.700, 0.650], + [0.300, 3.430, 2.700, 2.100, 1.550, 1.170, 0.920, 0.770, 0.630, 0.580], + [0.400, 3.030, 2.450, 1.900, 1.470, 1.100, 0.880, 0.730, 0.590, 0.530], + [0.500, 2.750, 2.220, 1.710, 1.370, 1.020, 0.840, 0.730, 0.570, 0.520], + [0.600, 2.490, 2.000, 1.550, 1.260, 0.970, 0.810, 0.740, 0.560, 0.510], + [0.700, 2.250, 1.800, 1.410, 1.170, 0.910, 0.790, 0.710, 0.550, 0.510], + [0.800, 1.990, 1.620, 1.300, 1.100, 0.880, 0.750, 0.700, 0.550, 0.500], + [0.900, 1.800, 1.500, 1.200, 1.000, 0.840, 0.700, 0.660, 0.540, 0.500], + [1.000, 1.650, 1.400, 1.100, 0.950, 0.800, 0.700, 0.660, 0.540, 0.500], + ] +) + +BSUP = np.array( + [ + [14006.0, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50], + [1.000, 24.50, 20.00, 16.20, 13.40, 11.10, 9.50], + [1.050, 30.70, 23.60, 20.00, 16.00, 12.90, 10.50], + [1.100, 33.00, 26.20, 21.50, 17.40, 14.00, 11.10], + [1.150, 34.30, 27.30, 22.30, 18.20, 14.80, 11.60], + [1.200, 34.70, 27.70, 22.50, 18.50, 15.00, 11.90], + [1.250, 34.50, 27.50, 22.40, 18.20, 14.90, 11.90], + [1.300, 33.80, 27.00, 22.00, 17.60, 14.50, 11.70], + [1.350, 32.90, 26.40, 21.70, 17.30, 14.20, 11.40], + [1.400, 32.40, 25.90, 21.40, 17.20, 14.10, 11.00], + [1.500, 32.00, 25.60, 21.10, 17.00, 14.10, 10.90], + [1.600, 32.00, 25.60, 21.00, 17.00, 14.10, 10.90], + [1.800, 32.00, 25.60, 21.00, 17.00, 14.20, 11.40], + [2.000, 32.00, 25.60, 21.00, 17.10, 14.40, 11.80], + [2.200, 32.00, 25.60, 21.00, 17.30, 14.60, 12.00], + ] +) # called BINT in FLOPS. -WFI = np.array([[13010.0, .10, .120, .140, .150, .160, .170, .180, .190, .200, .220], - [1.000, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0], - [1.050, 0.0, 0.0, .00040, -.00030, -.00080, -.00110, -.00100, -.00040, .00030, .00180], - [1.100, 0.0, 0.0, .00060, -.00060, -.00140, -.00180, -.00140, -.00060, .00040, .00260], - [1.150, 0.0, 0.0, .00030, -.00080, -.00170, -.00200, -.00150, -.00060, .00040, .00240], - [1.200, 0.0, 0.0, .00020, -.00080, -.00170, -.00180, -.00140, -.00060, .00030, .00200], - [1.300, 0.0, 0.0, .00020, -.00060, -.00100, -.00100, -.00080, -.00050, .00010, .00120], - [1.400, 0.0, 0.0, .00010, -.00030, -.00030, -.00030, -.00020, -.00010, .00030, .00090], - [1.500, 0.0, 0.0, .00010, .00000, .00030, .00030, .00040, .00040, .00050, .00070], - [1.600, 0.0, 0.0, .00000, .00040, .00050, .00090, .00090, .00080, .00070, .00050], - [1.700, 0.0, 0.0, .00000, .00050, .00070, .00120, .00110, .00100, .00080, .00050], - [1.800, 0.0, 0.0, .00000, .00060, .00090, .00120, .00110, .00100, .00080, .00050], - [1.900, 0.0, 0.0, .00000, .00060, .00090, .00100, .00100, .00090, .00080, .00050], - [2.000, 0.0, 0.0, .00000, .00050, .00090, .00110, .00100, .00090, .00070, .00050]]) - -PCWtable = InterpND(method='lagrange2', points=( - PCW[1:, 0], PCW[0, 1:]), values=PCW[1:, 1:], extrapolate=True) -BSUBtable = InterpND(method='lagrange2', points=( - BSUB[1:, 0], BSUB[0, 1:]), values=BSUB[1:, 1:], extrapolate=True) -PCARtable = InterpND(method='lagrange2', points=( - PCAR[1:, 0], PCAR[0, 1:]), values=PCAR[1:, 1:], extrapolate=True) -BSUPtable = InterpND(method='lagrange2', points=( - BSUP[1:, 0], BSUP[0, 1:]), values=BSUP[1:, 1:], extrapolate=True) -WFITable = InterpND(method='lagrange2', points=( - WFI[1:, 0], WFI[0, 1:]), values=WFI[1:, 1:], extrapolate=True) +# fmt: off +WFI = np.array( + [ + [13010.0, 0.10, 0.120, 0.140, 0.150, 0.160, 0.170, 0.180, 0.190, 0.200, 0.220], + [1.000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [ + 1.050, 0.0, 0.0, 0.00040, -0.00030, -0.00080, + -0.00110, -0.00100, -0.00040, 0.00030, 0.00180, + ], + [ + 1.100, 0.0, 0.0, 0.00060, -0.00060, -0.00140, + -0.00180, -0.00140, -0.00060, 0.00040, 0.00260, + ], + [ + 1.150, 0.0, 0.0, 0.00030, -0.00080, -0.00170, + -0.00200, -0.00150, -0.00060, 0.00040, 0.00240, + ], + [ + 1.200, 0.0, 0.0, 0.00020, -0.00080, -0.00170, + -0.00180, -0.00140, -0.00060, 0.00030, 0.00200, + ], + [ + 1.300, 0.0, 0.0, 0.00020, -0.00060, -0.00100, + -0.00100, -0.00080, -0.00050, 0.00010, 0.00120, + ], + [ + 1.400, 0.0, 0.0, 0.00010, -0.00030, -0.00030, + -0.00030, -0.00020, -0.00010, 0.00030, 0.00090, + ], + [1.500, 0.0, 0.0, 0.00010, 0.00000, 0.00030, 0.00030, 0.00040, 0.00040, 0.00050, 0.00070], + [1.600, 0.0, 0.0, 0.00000, 0.00040, 0.00050, 0.00090, 0.00090, 0.00080, 0.00070, 0.00050], + [1.700, 0.0, 0.0, 0.00000, 0.00050, 0.00070, 0.00120, 0.00110, 0.00100, 0.00080, 0.00050], + [1.800, 0.0, 0.0, 0.00000, 0.00060, 0.00090, 0.00120, 0.00110, 0.00100, 0.00080, 0.00050], + [1.900, 0.0, 0.0, 0.00000, 0.00060, 0.00090, 0.00100, 0.00100, 0.00090, 0.00080, 0.00050], + [2.000, 0.0, 0.0, 0.00000, 0.00050, 0.00090, 0.00110, 0.00100, 0.00090, 0.00070, 0.00050], + ] +) +# fmt: on + +PCWtable = InterpND( + method='lagrange2', points=(PCW[1:, 0], PCW[0, 1:]), values=PCW[1:, 1:], extrapolate=True +) +BSUBtable = InterpND( + method='lagrange2', points=(BSUB[1:, 0], BSUB[0, 1:]), values=BSUB[1:, 1:], extrapolate=True +) +PCARtable = InterpND( + method='lagrange2', points=(PCAR[1:, 0], PCAR[0, 1:]), values=PCAR[1:, 1:], extrapolate=True +) +BSUPtable = InterpND( + method='lagrange2', points=(BSUP[1:, 0], BSUP[0, 1:]), values=BSUP[1:, 1:], extrapolate=True +) +WFITable = InterpND( + method='lagrange2', points=(WFI[1:, 0], WFI[0, 1:]), values=WFI[1:, 1:], extrapolate=True +) diff --git a/aviary/subsystems/aerodynamics/flops_based/computed_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/computed_aero_group.py index 33f61c5d69..64a8967096 100644 --- a/aviary/subsystems/aerodynamics/flops_based/computed_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/computed_aero_group.py @@ -1,97 +1,110 @@ -""" -OpenMDAO System to compute drag based on the methods in FLOPS AERO. -""" +"""OpenMDAO System to compute drag based on the methods in FLOPS AERO.""" + import numpy as np import openmdao.api as om from aviary.subsystems.aerodynamics.aero_common import DynamicPressure from aviary.subsystems.aerodynamics.flops_based.buffet_lift import BuffetLift -from aviary.subsystems.aerodynamics.flops_based.compressibility_drag import \ - CompressibilityDrag +from aviary.subsystems.aerodynamics.flops_based.compressibility_drag import CompressibilityDrag from aviary.subsystems.aerodynamics.flops_based.drag import TotalDrag from aviary.subsystems.aerodynamics.flops_based.induced_drag import InducedDrag from aviary.subsystems.aerodynamics.flops_based.lift import LiftEqualsWeight -from aviary.subsystems.aerodynamics.flops_based.lift_dependent_drag import \ - LiftDependentDrag +from aviary.subsystems.aerodynamics.flops_based.lift_dependent_drag import LiftDependentDrag from aviary.subsystems.aerodynamics.flops_based.mux_component import MuxComponent from aviary.subsystems.aerodynamics.flops_based.skin_friction import SkinFriction -from aviary.subsystems.aerodynamics.flops_based.skin_friction_drag import \ - SkinFrictionDrag -from aviary.utils.aviary_values import AviaryValues +from aviary.subsystems.aerodynamics.flops_based.skin_friction_drag import SkinFrictionDrag from aviary.variable_info.variables import Aircraft, Dynamic, Mission class ComputedAeroGroup(om.Group): - """ - FLOPS-based computed aero group - """ + """FLOPS-based computed aero group.""" def initialize(self): self.options.declare( - "num_nodes", default=1, types=int, - desc="Number of nodes along mission segment") - self.options.declare( - 'gamma', default=1.4, - desc='Ratio of specific heats for air.') - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'num_nodes', default=1, types=int, desc='Number of nodes along mission segment' + ) + self.options.declare('gamma', default=1.4, desc='Ratio of specific heats for air.') def setup(self): - num_nodes = self.options["num_nodes"] + num_nodes = self.options['num_nodes'] gamma = self.options['gamma'] - aviary_options: AviaryValues = self.options['aviary_options'] - comp = MuxComponent(aviary_options=aviary_options) + comp = MuxComponent() self.add_subsystem( - 'Mux', comp, + 'Mux', + comp, promotes_inputs=['aircraft:*'], promotes_outputs=[ - 'wetted_areas', 'fineness_ratios', 'characteristic_lengths', - 'laminar_fractions_upper', 'laminar_fractions_lower']) + 'wetted_areas', + 'fineness_ratios', + 'characteristic_lengths', + 'laminar_fractions_upper', + 'laminar_fractions_lower', + ], + ) self.add_subsystem( - 'DynamicPressure', DynamicPressure(num_nodes=num_nodes, gamma=gamma), - promotes_inputs=[Dynamic.Mission.MACH, Dynamic.Mission.STATIC_PRESSURE], - promotes_outputs=[Dynamic.Mission.DYNAMIC_PRESSURE]) + 'DynamicPressure', + DynamicPressure(num_nodes=num_nodes, gamma=gamma), + promotes_inputs=[ + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.STATIC_PRESSURE, + ], + promotes_outputs=[Dynamic.Atmosphere.DYNAMIC_PRESSURE], + ) comp = LiftEqualsWeight(num_nodes=num_nodes) self.add_subsystem( - name=Dynamic.Mission.LIFT, subsys=comp, - promotes_inputs=[Aircraft.Wing.AREA, Dynamic.Mission.MASS, - Dynamic.Mission.DYNAMIC_PRESSURE], - promotes_outputs=['cl', Dynamic.Mission.LIFT]) + name=Dynamic.Vehicle.LIFT, + subsys=comp, + promotes_inputs=[ + Aircraft.Wing.AREA, + Dynamic.Vehicle.MASS, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + ], + promotes_outputs=['cl', Dynamic.Vehicle.LIFT], + ) comp = LiftDependentDrag(num_nodes=num_nodes, gamma=gamma) self.add_subsystem( - 'PressureDrag', comp, + 'PressureDrag', + comp, promotes_inputs=[ - Dynamic.Mission.MACH, Dynamic.Mission.LIFT, Dynamic.Mission.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.LIFT, + Dynamic.Atmosphere.STATIC_PRESSURE, Mission.Design.MACH, Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.AREA, Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, Aircraft.Wing.SWEEP, - Aircraft.Wing.THICKNESS_TO_CHORD]) + Aircraft.Wing.THICKNESS_TO_CHORD, + ], + ) - comp = InducedDrag( - num_nodes=num_nodes, gamma=gamma, aviary_options=aviary_options) + comp = InducedDrag(num_nodes=num_nodes, gamma=gamma) self.add_subsystem( - 'InducedDrag', comp, + 'InducedDrag', + comp, promotes_inputs=[ - Dynamic.Mission.MACH, Dynamic.Mission.LIFT, Dynamic.Mission.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.LIFT, + Dynamic.Atmosphere.STATIC_PRESSURE, Aircraft.Wing.AREA, Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.SPAN_EFFICIENCY_FACTOR, Aircraft.Wing.SWEEP, - Aircraft.Wing.TAPER_RATIO]) + Aircraft.Wing.TAPER_RATIO, + ], + ) comp = CompressibilityDrag(num_nodes=num_nodes) self.add_subsystem( - 'CompressibilityDrag', comp, + 'CompressibilityDrag', + comp, promotes_inputs=[ - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, Mission.Design.MACH, Aircraft.Design.BASE_AREA, Aircraft.Wing.AREA, @@ -102,92 +115,121 @@ def setup(self): Aircraft.Wing.THICKNESS_TO_CHORD, Aircraft.Fuselage.CROSS_SECTION, Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - Aircraft.Fuselage.LENGTH_TO_DIAMETER]) + Aircraft.Fuselage.LENGTH_TO_DIAMETER, + ], + ) - comp = SkinFriction(num_nodes=num_nodes, aviary_options=aviary_options) + comp = SkinFriction(num_nodes=num_nodes) self.add_subsystem( - 'SkinFrictionCoef', comp, + 'SkinFrictionCoef', + comp, promotes_inputs=[ - Dynamic.Mission.MACH, Dynamic.Mission.STATIC_PRESSURE, Dynamic.Mission.TEMPERATURE, - 'characteristic_lengths'], - promotes_outputs=['skin_friction_coeff', 'Re']) - - comp = SkinFrictionDrag(num_nodes=num_nodes, aviary_options=aviary_options) + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.TEMPERATURE, + 'characteristic_lengths', + ], + promotes_outputs=['skin_friction_coeff', 'Re'], + ) + + comp = SkinFrictionDrag(num_nodes=num_nodes) self.add_subsystem( - 'SkinFrictionDrag', comp, + 'SkinFrictionDrag', + comp, promotes_inputs=[ - 'skin_friction_coeff', 'Re', 'fineness_ratios', 'wetted_areas', - 'laminar_fractions_upper', 'laminar_fractions_lower', - Aircraft.Wing.AREA]) + 'skin_friction_coeff', + 'Re', + 'fineness_ratios', + 'wetted_areas', + 'laminar_fractions_upper', + 'laminar_fractions_lower', + Aircraft.Wing.AREA, + ], + ) comp = ComputedDrag(num_nodes=num_nodes) self.add_subsystem( - 'Drag', comp, + 'Drag', + comp, promotes_inputs=[ - Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.MACH, Aircraft.Wing.AREA, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.MACH, + Aircraft.Wing.AREA, Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, - Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR], - promotes_outputs=['CDI', 'CD0', 'CD', Dynamic.Mission.DRAG]) + Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, + ], + promotes_outputs=['CDI', 'CD0', 'CD', Dynamic.Vehicle.DRAG], + ) buf = BuffetLift(num_nodes=num_nodes) self.add_subsystem( - 'Buffet', buf, + 'Buffet', + buf, promotes_inputs=[ - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, Mission.Design.MACH, Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, Aircraft.Wing.SWEEP, - Aircraft.Wing.THICKNESS_TO_CHORD]) + Aircraft.Wing.THICKNESS_TO_CHORD, + ], + ) self.connect('PressureDrag.CD', 'Drag.pressure_drag_coeff') self.connect('InducedDrag.induced_drag_coeff', 'Drag.induced_drag_coeff') - self.connect( - 'CompressibilityDrag.compress_drag_coeff', 'Drag.compress_drag_coeff') - self.connect( - 'SkinFrictionDrag.skin_friction_drag_coeff', 'Drag.skin_friction_drag_coeff') + self.connect('CompressibilityDrag.compress_drag_coeff', 'Drag.compress_drag_coeff') + self.connect('SkinFrictionDrag.skin_friction_drag_coeff', 'Drag.skin_friction_drag_coeff') class ComputedDrag(om.Group): - """ - FLOPS-based computed drag group - """ + """FLOPS-based computed drag group.""" def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] self._setup_drag_coeff( 'CDI', - input0='pressure_drag_coeff', input1='induced_drag_coeff', output='CDI', + input0='pressure_drag_coeff', + input1='induced_drag_coeff', + output='CDI', desc='lift-dependent drag coefficient,' - ' including contributions from pressure drag coefficient') + ' including contributions from pressure drag coefficient', + ) self._setup_drag_coeff( 'CD0', - input0='skin_friction_drag_coeff', input1='compress_drag_coeff', + input0='skin_friction_drag_coeff', + input1='compress_drag_coeff', output='CD0', - desc='zero-lift drag coefficient') + desc='zero-lift drag coefficient', + ) self.add_subsystem( - Dynamic.Mission.DRAG, TotalDrag(num_nodes=nn), + Dynamic.Vehicle.DRAG, + TotalDrag(num_nodes=nn), promotes_inputs=[ Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, Aircraft.Wing.AREA, Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, - 'CDI', 'CD0', Dynamic.Mission.MACH, Dynamic.Mission.DYNAMIC_PRESSURE], - promotes_outputs=['CD', Dynamic.Mission.DRAG]) + 'CDI', + 'CD0', + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + ], + promotes_outputs=['CD', Dynamic.Vehicle.DRAG], + ) - self.set_input_defaults(Aircraft.Wing.AREA, 1., 'ft**2') + self.set_input_defaults(Aircraft.Wing.AREA, 1.0, 'ft**2') def _setup_drag_coeff(self, name, input0, input1, output, desc=None): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] input_args = {'val': np.ones(nn), 'units': 'unitless'} output_args = dict(input_args) @@ -198,6 +240,9 @@ def _setup_drag_coeff(self, name, input0, input1, output, desc=None): kwargs = {input0: input_args, input1: input_args, output: output_args} subsys = self.add_subsystem( - name, om.ExecComp(f'{output} = {input0} + {input1}', **kwargs), - promotes_inputs=[input0, input1], promotes_outputs=[output]) + name, + om.ExecComp(f'{output} = {input0} + {input1}', **kwargs), + promotes_inputs=[input0, input1], + promotes_outputs=[output], + ) subsys.declare_coloring(show_summary=False) diff --git a/aviary/subsystems/aerodynamics/flops_based/design.py b/aviary/subsystems/aerodynamics/flops_based/design.py index e95d5df21f..78dda58b8d 100644 --- a/aviary/subsystems/aerodynamics/flops_based/design.py +++ b/aviary/subsystems/aerodynamics/flops_based/design.py @@ -1,19 +1,19 @@ """ -OpenMDAO component to compute the design mach number and design coefficient of lift, +OpenMDAO component to compute the design Mach number and design coefficient of lift, based on the calculations used in FLOPS and LEAPS 1.0. """ + import numpy as np import openmdao.api as om from openmdao.components.interp_util.interp import InterpND -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class Design(om.ExplicitComponent): """ - Calculates the design mach number and coefficient of lift. + Calculates the design Mach number and coefficient of lift. Based on subroutines MDESN and CLDESN in FLOPS. """ @@ -26,44 +26,42 @@ def __init__(self, **kwargs): self.des_mach_coeff = [0.32, 57.2958, 0.144] def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Wing.AIRFOIL_TECHNOLOGY) + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): # Aircraft design inputs - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, 0.0) - add_aviary_input(self, Aircraft.Wing.SWEEP, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') # Declare outputs - add_aviary_output(self, Mission.Design.MACH, 0.0) - add_aviary_output(self, Mission.Design.LIFT_COEFFICIENT, 0.0) + add_aviary_output(self, Mission.Design.MACH, units='unitless') + add_aviary_output(self, Mission.Design.LIFT_COEFFICIENT, units='unitless') def setup_partials(self): self.declare_partials(of='*', wrt='*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - AITEK = aviary_options.get_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY) - VMAX = aviary_options.get_val(Mission.Constraints.MAX_MACH) + AITEK = self.options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] + VMAX = self.options[Mission.Constraints.MAX_MACH] AR, CAM, SW25, TC = inputs.values() # design lift coefficient equation is selected based on thickness/chord ratio if TC.real > 0.065: a, b, c, d = self.sub_sonic_coeff - CLDES = (a + b*AR) * np.cos(SW25/c) * (1.0 + d*CAM) / np.sqrt(AR) + CLDES = (a + b * AR) * np.cos(SW25 / c) * (1.0 + d * CAM) / np.sqrt(AR) else: a, b, c, d, e = self.super_sonic_coeff FAR = AR * TC**e - CLDES = a + b*FAR + c*FAR**2.0 + d*FAR**3.0 + CLDES = a + b * FAR + c * FAR**2.0 + d * FAR**3.0 outputs[Mission.Design.LIFT_COEFFICIENT] = CLDES - # design mach equation selected based on thickness/chord ratio or maximum mach number + # design Mach equation selected based on thickness/chord ratio or maximum Mach number if TC.real > 0.065 or VMAX < 1.0: # subsonic TC23 = TC ** (2.0 / 3.0) @@ -88,47 +86,44 @@ def compute(self, inputs, outputs): outputs[Mission.Design.MACH] = DESM2D + DMDSWP + DMDAR def compute_partials(self, inputs, partials): - aviary_options: AviaryValues = self.options['aviary_options'] - AITEK = aviary_options.get_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY) - VMAX = aviary_options.get_val(Mission.Constraints.MAX_MACH) + AITEK = self.options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] + VMAX = self.options[Mission.Constraints.MAX_MACH] AR, CAM, SW25, TC = inputs.values() if TC.real > 0.065: # subsonic a, b, c, d = self.sub_sonic_coeff fact1 = a + b * AR - fact2 = np.cos(SW25/c) - fact3 = (1.0 + d*CAM) + fact2 = np.cos(SW25 / c) + fact3 = 1.0 + d * CAM fact4 = 1.0 / np.sqrt(AR) CLDES = fact1 * fact2 * fact3 * fact4 # Calculate derivative of design CL wrt Mach, CL, AR, TC, CAM, and SW25 - dCLDES_dAR = fact3 * fact2 * (b * fact4 - fact1 / (2*AR**1.5)) + dCLDES_dAR = fact3 * fact2 * (b * fact4 - fact1 / (2 * AR**1.5)) dCLDES_dTC = 0.0 dCLDES_dCAM = d * fact1 * fact2 * fact4 - dCLDES_dSW25 = -fact1 * fact3 * np.sin(SW25/c) * fact4/c + dCLDES_dSW25 = -fact1 * fact3 * np.sin(SW25 / c) * fact4 / c else: # supersonic a, b, c, d, e = self.super_sonic_coeff FAR = AR * TC**e - CLDES = a + b*FAR + c*FAR**2.0 + d*FAR**3.0 + CLDES = a + b * FAR + c * FAR**2.0 + d * FAR**3.0 # Calculate derivative of design CL wrt AR, TC, SW25, and CAM dFAR_dAR = TC**e - dFAR_dTC = e * AR * TC**(e - 1.0) - dCLDES_dFAR = b + 2.0*c*FAR + 3.0*d*FAR**2.0 + dFAR_dTC = e * AR * TC ** (e - 1.0) + dCLDES_dFAR = b + 2.0 * c * FAR + 3.0 * d * FAR**2.0 dCLDES_dAR = dCLDES_dFAR * dFAR_dAR dCLDES_dTC = dCLDES_dFAR * dFAR_dTC dCLDES_dSW25 = 0.0 dCLDES_dCAM = 0.0 - partials[Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.ASPECT_RATIO] = \ - dCLDES_dAR - partials[Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.THICKNESS_TO_CHORD] = \ - dCLDES_dTC - partials[ - Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN - ] = dCLDES_dCAM + partials[Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.ASPECT_RATIO] = dCLDES_dAR + partials[Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.THICKNESS_TO_CHORD] = dCLDES_dTC + partials[Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN] = ( + dCLDES_dCAM + ) partials[Mission.Design.LIFT_COEFFICIENT, Aircraft.Wing.SWEEP] = dCLDES_dSW25 if TC.real > 0.065 or VMAX < 1.0: # subsonic @@ -155,7 +150,7 @@ def compute_partials(self, inputs, partials): dDESM2D_dAR = dDESM2D_dANS * dANS_dAR # wrt TC - dTC23_dTC = (2.0/3.0) * TC**(-1.0/3.0) + dTC23_dTC = (2.0 / 3.0) * TC ** (-1.0 / 3.0) dANS_dTC = dANS_dCLDES * dCLDES_dTC + dANS_dTC23 * dTC23_dTC dDESM2D_dTC = dDESM2D_dANS * dANS_dTC @@ -206,47 +201,55 @@ def compute_partials(self, inputs, partials): partials[Mission.Design.MACH, Aircraft.Wing.ASPECT_RATIO] = dDESM_dAR partials[Mission.Design.MACH, Aircraft.Wing.THICKNESS_TO_CHORD] = dDESM_dTC - partials[Mission.Design.MACH, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN] = \ - dDESM_dCAM + partials[Mission.Design.MACH, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN] = dDESM_dCAM partials[Mission.Design.MACH, Aircraft.Wing.SWEEP] = dDESM_dSW25 AMDES = np.array( - [[8003, .180, .240, .300], - [.10, -.2080, -.3330, -.4590], - [.20, -.2180, -.3430, -.4680], - [.30, -.2290, -.3530, -.4780], - [.40, -.2420, -.3650, -.4880], - [.50, -.2580, -.3770, -.4950], - [.60, -.2710, -.3880, -.5070], - [.70, -.2940, -.4130, -.5300], - [.80, -.3170, -.4310, -.5460]]) + [ + [8003, 0.180, 0.240, 0.300], + [0.10, -0.2080, -0.3330, -0.4590], + [0.20, -0.2180, -0.3430, -0.4680], + [0.30, -0.2290, -0.3530, -0.4780], + [0.40, -0.2420, -0.3650, -0.4880], + [0.50, -0.2580, -0.3770, -0.4950], + [0.60, -0.2710, -0.3880, -0.5070], + [0.70, -0.2940, -0.4130, -0.5300], + [0.80, -0.3170, -0.4310, -0.5460], + ] +) CMDES = np.array( - [[7003, 0.180000, 0.240000, 0.300000], - [0.100000, -0.374000, -0.445000, -0.513000], - [0.200000, -0.385000, -0.461000, -0.537000], - [0.300000, -0.401000, -0.478000, -0.556000], - [0.400000, -0.416000, -0.490000, -0.564000], - [0.500000, -0.441000, -0.509000, -0.578000], - [0.600000, -0.474000, -0.532000, -0.591000], - [0.700000, -0.518000, -0.571000, -0.621000]]) + [ + [7003, 0.180000, 0.240000, 0.300000], + [0.100000, -0.374000, -0.445000, -0.513000], + [0.200000, -0.385000, -0.461000, -0.537000], + [0.300000, -0.401000, -0.478000, -0.556000], + [0.400000, -0.416000, -0.490000, -0.564000], + [0.500000, -0.441000, -0.509000, -0.578000], + [0.600000, -0.474000, -0.532000, -0.591000], + [0.700000, -0.518000, -0.571000, -0.621000], + ] +) HSMDES = np.array( - [[6003, 0.020000, 0.040000, 0.060000], - [0.000000, 0.844000, 0.822000, 0.801000], - [0.100000, 0.836000, 0.815000, 0.793000], - [0.200000, 0.829000, 0.807000, 0.786000], - [0.300000, 0.820000, 0.799000, 0.778000], - [0.400000, 0.811000, 0.791000, 0.770000], - [0.500000, 0.802000, 0.781000, 0.759000]]) + [ + [6003, 0.020000, 0.040000, 0.060000], + [0.000000, 0.844000, 0.822000, 0.801000], + [0.100000, 0.836000, 0.815000, 0.793000], + [0.200000, 0.829000, 0.807000, 0.786000], + [0.300000, 0.820000, 0.799000, 0.778000], + [0.400000, 0.811000, 0.791000, 0.770000], + [0.500000, 0.802000, 0.781000, 0.759000], + ] +) AMDEStable = InterpND( - method='slinear', points=(AMDES[1:, 0], AMDES[0, 1:]), values=AMDES[1:, 1:], - extrapolate=True) + method='slinear', points=(AMDES[1:, 0], AMDES[0, 1:]), values=AMDES[1:, 1:], extrapolate=True +) CMDEStable = InterpND( - method='slinear', points=(CMDES[1:, 0], CMDES[0, 1:]), values=CMDES[1:, 1:], - extrapolate=True) + method='slinear', points=(CMDES[1:, 0], CMDES[0, 1:]), values=CMDES[1:, 1:], extrapolate=True +) HSMDEStable = InterpND( - method='slinear', points=(HSMDES[1:, 0], HSMDES[0, 1:]), values=HSMDES[1:, 1:], - extrapolate=True) + method='slinear', points=(HSMDES[1:, 0], HSMDES[0, 1:]), values=HSMDES[1:, 1:], extrapolate=True +) diff --git a/aviary/subsystems/aerodynamics/flops_based/drag.py b/aviary/subsystems/aerodynamics/flops_based/drag.py index d2b5e1b676..1972d54573 100644 --- a/aviary/subsystems/aerodynamics/flops_based/drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/drag.py @@ -1,14 +1,14 @@ import numpy as np import openmdao.api as om -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variable_meta_data import _MetaData as _meta_data from aviary.variable_info.variables import Aircraft, Dynamic -class SimpleCD(om.ExplicitComponent): +class ScaledCD(om.ExplicitComponent): """ - Apply the final drag coefficent factors to the unscaled drag. + Apply the final drag coefficient factors to the unscaled drag. These optional factors (default: 1.0) increase or decrease the drag coefficient before calculating drag. @@ -20,41 +20,38 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, val=1.) - add_aviary_input(self, Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, val=1.) + add_aviary_input(self, Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, units='unitless') - self.add_input( - Dynamic.Mission.MACH, val=np.ones(nn), units='unitless', - desc='ratio of local fluid speed to local speed of sound') + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') self.add_input( - 'CD_prescaled', val=np.ones(nn), units='unitless', - desc='total drag coefficient') + 'CD_prescaled', val=np.ones(nn), units='unitless', desc='total drag coefficient' + ) - self.add_output('CD', val=np.ones(nn), - units='unitless', desc='total drag') + self.add_output('CD', val=np.ones(nn), units='unitless', desc='total drag') def setup_partials(self): - self.declare_partials('CD', - ['CD_prescaled', - Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, - Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR] - ) + self.declare_partials( + 'CD', + [ + 'CD_prescaled', + Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, + Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, + ], + ) - self.declare_partials('CD', - Dynamic.Mission.MACH, dependent=False) + self.declare_partials('CD', Dynamic.Atmosphere.MACH, dependent=False) nn = self.options['num_nodes'] rows_cols = np.arange(nn) - self.declare_partials( - 'CD', 'CD_prescaled', - rows=rows_cols, cols=rows_cols) + self.declare_partials('CD', 'CD_prescaled', rows=rows_cols, cols=rows_cols) def compute(self, inputs, outputs): FCDSUB = inputs[Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR] FCDSUP = inputs[Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR] - M = inputs[Dynamic.Mission.MACH] + M = inputs[Dynamic.Atmosphere.MACH] CD_prescaled = inputs['CD_prescaled'] @@ -66,7 +63,7 @@ def compute(self, inputs, outputs): def compute_partials(self, inputs, partials): FCDSUB = inputs[Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR] FCDSUP = inputs[Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR] - M = inputs[Dynamic.Mission.MACH] + M = inputs[Dynamic.Atmosphere.MACH] CD_prescaled = inputs['CD_prescaled'] idx_sup = np.where(M >= 1.0) @@ -89,9 +86,7 @@ def compute_partials(self, inputs, partials): class SimpleDrag(om.ExplicitComponent): - """ - Calculate drag as a function of wing area, dynamic pressure, and drag coefficient. - """ + """Calculate drag as a function of wing area, dynamic pressure, and drag coefficient.""" def initialize(self): self.options.declare('num_nodes', types=int) @@ -99,52 +94,46 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Wing.AREA, val=1., units='m**2') + add_aviary_input(self, Aircraft.Wing.AREA, units='m**2') - self.add_input( - Dynamic.Mission.DYNAMIC_PRESSURE, val=np.ones(nn), units='N/m**2', - desc='pressure caused by fluid motion') + add_aviary_input(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='N/m**2') - self.add_input( - 'CD', val=np.ones(nn), units='unitless', - desc='total drag coefficient') + self.add_input('CD', val=np.ones(nn), units='unitless', desc='total drag coefficient') - self.add_output(Dynamic.Mission.DRAG, val=np.ones(nn), - units='N', desc='total drag') + add_aviary_output(self, Dynamic.Vehicle.DRAG, shape=nn, units='N') def setup_partials(self): nn = self.options['num_nodes'] rows_cols = np.arange(nn) - self.declare_partials( - Dynamic.Mission.DRAG, - Aircraft.Wing.AREA - ) + self.declare_partials(Dynamic.Vehicle.DRAG, Aircraft.Wing.AREA) self.declare_partials( - Dynamic.Mission.DRAG, - [Dynamic.Mission.DYNAMIC_PRESSURE, 'CD'], - rows=rows_cols, cols=rows_cols) + Dynamic.Vehicle.DRAG, + [Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'CD'], + rows=rows_cols, + cols=rows_cols, + ) def compute(self, inputs, outputs): S = inputs[Aircraft.Wing.AREA] - q = inputs[Dynamic.Mission.DYNAMIC_PRESSURE] + q = inputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] CD = inputs['CD'] - outputs[Dynamic.Mission.DRAG] = q * S * CD + outputs[Dynamic.Vehicle.DRAG] = q * S * CD def compute_partials(self, inputs, partials): S = inputs[Aircraft.Wing.AREA] - q = inputs[Dynamic.Mission.DYNAMIC_PRESSURE] + q = inputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] CD = inputs['CD'] - partials[Dynamic.Mission.DRAG, Aircraft.Wing.AREA] = q * CD - partials[Dynamic.Mission.DRAG, Dynamic.Mission.DYNAMIC_PRESSURE] = S * CD - partials[Dynamic.Mission.DRAG, 'CD'] = q * S + partials[Dynamic.Vehicle.DRAG, Aircraft.Wing.AREA] = q * CD + partials[Dynamic.Vehicle.DRAG, Dynamic.Atmosphere.DYNAMIC_PRESSURE] = S * CD + partials[Dynamic.Vehicle.DRAG, 'CD'] = q * S class TotalDrag(om.Group): - ''' + """ Calculate drag as a function of wing area, dynamic pressure, and lift-dependent and lift-independent drag coefficients. @@ -154,13 +143,13 @@ class TotalDrag(om.Group): Apply an optional factor (default: 1.0) for increasing or decreasing the lift- independent drag coefficient before calculating the total drag coefficient. - Note, the lift-dependent drag coefficient includes contirbutions from the pressure + Note, the lift-dependent drag coefficient includes contributions from the pressure drag coefficient. Apply optional factors (default: 1.0) for increasing or decreasing the total drag - coefficient before calculating drag. The effect is cummulative with the above + coefficient before calculating drag. The effect is cumulative with the above optional factors. - ''' + """ def initialize(self): self.options.declare('num_nodes', types=int) @@ -173,27 +162,31 @@ def setup(self): kwargs = { 'CDI': dict( - val=np.ones(nn), units='unitless', + val=np.ones(nn), + units='unitless', desc='lift-dependent drag coefficient,' - ' including contributions from pressure drag coefficient'), + ' including contributions from pressure drag coefficient', + ), 'CD0': dict( - val=np.ones(nn), units='unitless', - desc='lift-independent drag coefficient'), - 'FCDI': dict(val=1., units='unitless', desc=FCDI_desc), - 'FCD0': dict(val=1., units='unitless', desc=FCD0_desc), - 'CD_prescaled': dict(val=np.ones(nn), units='unitless', - desc='total drag coefficient') + val=np.ones(nn), units='unitless', desc='lift-independent drag coefficient' + ), + 'FCDI': dict(val=1.0, units='unitless', desc=FCDI_desc), + 'FCD0': dict(val=1.0, units='unitless', desc=FCD0_desc), + 'CD_prescaled': dict(val=np.ones(nn), units='unitless', desc='total drag coefficient'), } total_drag_comp = self.add_subsystem( 'total_drag_coeff', om.ExecComp('CD_prescaled = CDI * FCDI + CD0 * FCD0', **kwargs), promotes_inputs=[ - 'CDI', 'CD0', + 'CDI', + 'CD0', ('FCDI', Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR), - ('FCD0', Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR)], - promotes_outputs=['*']) + ('FCD0', Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR), + ], + promotes_outputs=['*'], + ) total_drag_comp.declare_coloring(show_summary=False) - self.add_subsystem('simple_CD', SimpleCD(num_nodes=nn), promotes=['*']) + self.add_subsystem('simple_CD', ScaledCD(num_nodes=nn), promotes=['*']) self.add_subsystem('simple_drag', SimpleDrag(num_nodes=nn), promotes=['*']) diff --git a/aviary/subsystems/aerodynamics/flops_based/drag_polar.py b/aviary/subsystems/aerodynamics/flops_based/drag_polar.py index 1e673bb5c2..9817e4b9d1 100644 --- a/aviary/subsystems/aerodynamics/flops_based/drag_polar.py +++ b/aviary/subsystems/aerodynamics/flops_based/drag_polar.py @@ -1,54 +1,49 @@ -""" -OpenMDAO system for generating the aero tables that were typically printed in FLOPS. -""" -import numpy as np +"""OpenMDAO system for generating the aero tables that were typically printed in FLOPS.""" +import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Aircraft, Mission class DragPolar(om.ExplicitComponent): """ This will need to create an instance of the dynamic aero group, perhaps as a - subproblem, and run it at the table of mach numbers and lift coefficients. Right now, + subproblem, and run it at the table of Mach numbers and lift coefficients. Right now, it is a placeholder, and also serves as a sink for all parts of the aircraft data structures that are passed to the dynamic portion, so that they can be overridden if needed. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - aviary_options = self.options['aviary_options'] - num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - - add_aviary_input(self, Aircraft.Canard.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.Nacelle.WETTED_AREA, np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.WETTED_AREA, 0.0) - - add_aviary_input(self, Aircraft.Canard.FINENESS, 0.0) - add_aviary_input(self, Aircraft.Fuselage.FINENESS, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.FINENESS, 0.0) - add_aviary_input(self, Aircraft.Nacelle.FINENESS, np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.VerticalTail.FINENESS, 0.0) - add_aviary_input(self, Aircraft.Wing.FINENESS, 0.0) - - add_aviary_input(self, Aircraft.Canard.CHARACTERISTIC_LENGTH, 0.0) - add_aviary_input(self, Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 0.0) - add_aviary_input(self, Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, 0.0) - add_aviary_input(self, Aircraft.Wing.CHARACTERISTIC_LENGTH, 0.0) - - add_aviary_input(self, Mission.Design.MACH, 0.0) - add_aviary_input(self, Mission.Design.LIFT_COEFFICIENT, 0.0) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input(self, Aircraft.Canard.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Nacelle.WETTED_AREA, shape=num_engine_type, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.WETTED_AREA, units='ft**2') + + add_aviary_input(self, Aircraft.Canard.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.Nacelle.FINENESS, shape=num_engine_type, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.Wing.FINENESS, units='unitless') + + add_aviary_input(self, Aircraft.Canard.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input(self, Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input( + self, Aircraft.Nacelle.CHARACTERISTIC_LENGTH, np.zeros(num_engine_type), units='ft' + ) + add_aviary_input(self, Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input(self, Aircraft.Wing.CHARACTERISTIC_LENGTH, units='ft') + + add_aviary_input(self, Mission.Design.MACH, units='unitless') + add_aviary_input(self, Mission.Design.LIFT_COEFFICIENT, units='unitless') diff --git a/aviary/subsystems/aerodynamics/flops_based/ground_effect.py b/aviary/subsystems/aerodynamics/flops_based/ground_effect.py index 1b1ca9de64..5eca2ce12b 100644 --- a/aviary/subsystems/aerodynamics/flops_based/ground_effect.py +++ b/aviary/subsystems/aerodynamics/flops_based/ground_effect.py @@ -1,4 +1,4 @@ -''' +""" Define utilities for calculating the effect the ground has on lift-to-drag ratio for aircraft flying in close proximity to the ground. @@ -6,7 +6,8 @@ ---------- .. [1] DeYoung, John. "Advanced Supersonic Technology Concept Study Reference Characteristics," NASA Contractor Report 132374. -''' +""" + import numpy as np import openmdao.api as om @@ -15,15 +16,15 @@ class GroundEffect(om.ExplicitComponent): - ''' - Define a component for adjusting lift and drag to accomodate ground effect. + """ + Define a component for adjusting lift and drag to accommodate ground effect. Note ---- It is an error (no diagnostic) to try to calculate ground effect for an aircraft flying "underground" - current `altitude` must ALWAYS be greater than or equal to `ground_altitude`. - ''' + """ def initialize(self): options = self.options @@ -31,47 +32,55 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'ground_altitude', default=0., types=float, - desc='true altitude of the ground from mean sea level (m)' + 'ground_altitude', + default=0.0, + types=float, + desc='true altitude of the ground from mean sea level (m)', ) def setup(self): nn = self.options['num_nodes'] - self.add_input('angle_of_attack', val=np.zeros(nn), units='rad') + self.add_input(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=np.zeros(nn), units='rad') - add_aviary_input(self, Dynamic.Mission.ALTITUDE, np.zeros(nn), units='m') + add_aviary_input(self, Dynamic.Mission.ALTITUDE, shape=nn, units='m') - add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, - val=np.zeros(nn), units='rad') + add_aviary_input(self, Dynamic.Mission.FLIGHT_PATH_ANGLE, shape=(nn), units='rad') self.add_input( - 'minimum_drag_coefficient', 0.0, - desc='coefficient of minimum drag', units='unitless' + 'minimum_drag_coefficient', 0.0, desc='coefficient of minimum drag', units='unitless' ) self.add_input( - 'base_lift_coefficient', val=np.ones(nn), - desc='coefficient of lift without ground effect', units='unitless' + 'base_lift_coefficient', + val=np.ones(nn), + desc='coefficient of lift without ground effect', + units='unitless', ) self.add_input( - 'base_drag_coefficient', val=np.ones(nn), - desc='coefficient of drag without ground effect', units='unitless' + 'base_drag_coefficient', + val=np.ones(nn), + desc='coefficient of drag without ground effect', + units='unitless', ) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=1.) - add_aviary_input(self, Aircraft.Wing.HEIGHT, val=1., units='m') - add_aviary_input(self, Aircraft.Wing.SPAN, val=1., units='m') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.HEIGHT, units='m') + add_aviary_input(self, Aircraft.Wing.SPAN, units='m') self.add_output( - 'lift_coefficient', val=np.ones(nn), - desc='coefficient of lift with ground effect', units='unitless' + 'lift_coefficient', + val=np.ones(nn), + desc='coefficient of lift with ground effect', + units='unitless', ) self.add_output( - 'drag_coefficient', val=np.ones(nn), - desc='coefficient of drag with ground effect', units='unitless' + 'drag_coefficient', + val=np.ones(nn), + desc='coefficient of drag with ground effect', + units='unitless', ) def setup_partials(self): @@ -79,48 +88,58 @@ def setup_partials(self): self.declare_partials( 'lift_coefficient', - [Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.HEIGHT, Aircraft.Wing.SPAN] + [Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.HEIGHT, Aircraft.Wing.SPAN], ) self.declare_partials( - 'lift_coefficient', [Dynamic.Mission.ALTITUDE, 'base_lift_coefficient'], - rows=rows_cols, cols=rows_cols + 'lift_coefficient', + [Dynamic.Mission.ALTITUDE, 'base_lift_coefficient'], + rows=rows_cols, + cols=rows_cols, ) self.declare_partials( 'lift_coefficient', [ - 'angle_of_attack', Dynamic.Mission.FLIGHT_PATH_ANGLE, 'minimum_drag_coefficient', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + 'minimum_drag_coefficient', 'base_drag_coefficient', ], - dependent=False + dependent=False, ) self.declare_partials( 'drag_coefficient', - [Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.HEIGHT, Aircraft.Wing.SPAN] + [Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.HEIGHT, Aircraft.Wing.SPAN], ) self.declare_partials( 'drag_coefficient', [ - 'angle_of_attack', Dynamic.Mission.ALTITUDE, Dynamic.Mission.FLIGHT_PATH_ANGLE, - 'base_drag_coefficient', 'base_lift_coefficient' + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.ALTITUDE, + Dynamic.Mission.FLIGHT_PATH_ANGLE, + 'base_drag_coefficient', + 'base_lift_coefficient', ], - rows=rows_cols, cols=rows_cols + rows=rows_cols, + cols=rows_cols, ) - self.declare_partials('drag_coefficient', 'minimum_drag_coefficient', - rows=rows_cols, - cols=np.zeros(self.options['num_nodes']) - ) + self.declare_partials( + 'drag_coefficient', + 'minimum_drag_coefficient', + rows=rows_cols, + cols=np.zeros(self.options['num_nodes']), + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): options = self.options ground_altitude = options['ground_altitude'] - angle_of_attack = inputs['angle_of_attack'] + angle_of_attack = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] altitude = inputs[Dynamic.Mission.ALTITUDE] flight_path_angle = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] minimum_drag_coefficient = inputs['minimum_drag_coefficient'] @@ -134,33 +153,36 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): height_factor = np.ones_like(ground_effect_state) idx = np.where(ground_effect_state > 1.0) - height_factor[idx] = 10. * (1.1 - ground_effect_state[idx]) + height_factor[idx] = 10.0 * (1.1 - ground_effect_state[idx]) - aspect_ratio_term = (6. + aspect_ratio)**2 / (36. + aspect_ratio) - ground_effect_term0 = 32. * (ground_effect_state * aspect_ratio_term)**2 + 1. + aspect_ratio_term = (6.0 + aspect_ratio) ** 2 / (36.0 + aspect_ratio) + ground_effect_term0 = 32.0 * (ground_effect_state * aspect_ratio_term) ** 2 + 1.0 lift_coeff_factor_denom = ( - ground_effect_term0 - 0.5 + 4. * ground_effect_state * aspect_ratio_term - * np.sqrt(ground_effect_term0) + ground_effect_term0 + - 0.5 + + 4.0 * ground_effect_state * aspect_ratio_term * np.sqrt(ground_effect_term0) ) - lift_coeff_factor = 1. + height_factor / lift_coeff_factor_denom + lift_coeff_factor = 1.0 + height_factor / lift_coeff_factor_denom lift_coefficient = base_lift_coefficient * lift_coeff_factor combined_angle = angle_of_attack + flight_path_angle - ground_effect_term1 = 1. + 32. * ground_effect_state**2 + ground_effect_term1 = 1.0 + 32.0 * ground_effect_state**2 - drag_coeff_factor_denom = \ - 4. * ground_effect_state * np.sqrt(ground_effect_term1) + ground_effect_term1 + drag_coeff_factor_denom = ( + 4.0 * ground_effect_state * np.sqrt(ground_effect_term1) + ground_effect_term1 + ) - drag_coeff_factor = 1. - height_factor / drag_coeff_factor_denom + drag_coeff_factor = 1.0 - height_factor / drag_coeff_factor_denom drag_coefficient = ( minimum_drag_coefficient - + lift_coeff_factor * drag_coeff_factor + + lift_coeff_factor + * drag_coeff_factor * (base_drag_coefficient - minimum_drag_coefficient) - + combined_angle * base_lift_coefficient * (lift_coeff_factor - 1.) + + combined_angle * base_lift_coefficient * (lift_coeff_factor - 1.0) ) # Check for out of ground effect. @@ -176,7 +198,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): ground_altitude = options['ground_altitude'] - angle_of_attack = inputs['angle_of_attack'] + angle_of_attack = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] altitude = inputs[Dynamic.Mission.ALTITUDE] flight_path_angle = inputs[Dynamic.Mission.FLIGHT_PATH_ANGLE] minimum_drag_coefficient = inputs['minimum_drag_coefficient'] @@ -189,36 +211,31 @@ def compute_partials(self, inputs, J, discrete_inputs=None): # region lift_coefficient wrt [altitude, base_lift_coefficient] ground_effect_state = ((altitude - ground_altitude) + height) / span - d_ges_alt = 1. / span + d_ges_alt = 1.0 / span height_factor = np.ones_like(ground_effect_state) d_hf_alt = np.zeros_like(ground_effect_state) idx = np.where(ground_effect_state > 1.0) - height_factor[idx] = 10. * (1.1 - ground_effect_state[idx]) - d_hf_alt[idx] = -10. / span + height_factor[idx] = 10.0 * (1.1 - ground_effect_state[idx]) + d_hf_alt[idx] = -10.0 / span - aspect_ratio_term = (6. + aspect_ratio)**2 / (36. + aspect_ratio) - ground_effect_term0 = 32. * (ground_effect_state * aspect_ratio_term)**2 + 1. + aspect_ratio_term = (6.0 + aspect_ratio) ** 2 / (36.0 + aspect_ratio) + ground_effect_term0 = 32.0 * (ground_effect_state * aspect_ratio_term) ** 2 + 1.0 - d_get0_alt = (64. * ground_effect_state * aspect_ratio_term**2) * d_ges_alt + d_get0_alt = (64.0 * ground_effect_state * aspect_ratio_term**2) * d_ges_alt sqrt_get0 = np.sqrt(ground_effect_term0) lift_coeff_factor_denom = ( - ground_effect_term0 - 0.5 - + 4. * ground_effect_state * aspect_ratio_term * sqrt_get0 + ground_effect_term0 - 0.5 + 4.0 * ground_effect_state * aspect_ratio_term * sqrt_get0 ) - d_lcfd_alt = ( - d_get0_alt - + 4. * aspect_ratio_term * ( - d_ges_alt * sqrt_get0 - + ground_effect_state * (0.5 / sqrt_get0) * d_get0_alt - ) + d_lcfd_alt = d_get0_alt + 4.0 * aspect_ratio_term * ( + d_ges_alt * sqrt_get0 + ground_effect_state * (0.5 / sqrt_get0) * d_get0_alt ) - lift_coeff_factor = 1. + height_factor / lift_coeff_factor_denom + lift_coeff_factor = 1.0 + height_factor / lift_coeff_factor_denom d_lcf_alt = ( (d_hf_alt * lift_coeff_factor_denom) - (height_factor * d_lcfd_alt) @@ -230,29 +247,27 @@ def compute_partials(self, inputs, J, discrete_inputs=None): # endregion lift_coefficient wrt [altitude, base_lift_coefficient] # region lift_coefficient wrt Aircraft.Wing.ASPECT_RATIO - f = (6. + aspect_ratio)**2 - d_f = 2. * (6. + aspect_ratio) - g = (36. + aspect_ratio) - d_g = 1. + f = (6.0 + aspect_ratio) ** 2 + d_f = 2.0 * (6.0 + aspect_ratio) + g = 36.0 + aspect_ratio + d_g = 1.0 d_art_ar = ((d_f * g) - (f * d_g)) / g**2 - d_get0_ar = 64. * (ground_effect_state**2 * aspect_ratio_term) * d_art_ar + d_get0_ar = 64.0 * (ground_effect_state**2 * aspect_ratio_term) * d_art_ar - d_lcfd_ar = d_get0_ar + 4. * ground_effect_state * ( - d_art_ar * sqrt_get0 - + aspect_ratio_term * 0.5 / sqrt_get0 * d_get0_ar + d_lcfd_ar = d_get0_ar + 4.0 * ground_effect_state * ( + d_art_ar * sqrt_get0 + aspect_ratio_term * 0.5 / sqrt_get0 * d_get0_ar ) f = height_factor - d_f = 0. + d_f = 0.0 g = lift_coeff_factor_denom d_g = d_lcfd_ar d_lcf_ar = -f * d_g / g**2 - J['lift_coefficient', Aircraft.Wing.ASPECT_RATIO] = \ - base_lift_coefficient * d_lcf_ar + J['lift_coefficient', Aircraft.Wing.ASPECT_RATIO] = base_lift_coefficient * d_lcf_ar # endregion lift_coefficient wrt Aircraft.Wing.ASPECT_RATIO J['lift_coefficient', Aircraft.Wing.HEIGHT] = base_lift_coefficient * d_lcf_alt @@ -261,15 +276,12 @@ def compute_partials(self, inputs, J, discrete_inputs=None): d_ges_b = -((altitude - ground_altitude) + height) / span**2 d_hf_b = np.zeros_like(ground_effect_state) - d_hf_b[idx] = -10. * d_ges_b[idx] + d_hf_b[idx] = -10.0 * d_ges_b[idx] - d_get0_b = 64. * (ground_effect_state * aspect_ratio_term**2) * d_ges_b + d_get0_b = 64.0 * (ground_effect_state * aspect_ratio_term**2) * d_ges_b - d_lcfd_b = ( - d_get0_b + 4. * aspect_ratio_term * ( - (d_ges_b * sqrt_get0) - + (ground_effect_state * 0.5 / sqrt_get0 * d_get0_b) - ) + d_lcfd_b = d_get0_b + 4.0 * aspect_ratio_term * ( + (d_ges_b * sqrt_get0) + (ground_effect_state * 0.5 / sqrt_get0 * d_get0_b) ) f = height_factor @@ -285,39 +297,38 @@ def compute_partials(self, inputs, J, discrete_inputs=None): # region drag_coefficient wrt angle_of_attack combined_angle = angle_of_attack + flight_path_angle - d_ca_aoa = 1. + d_ca_aoa = 1.0 - ground_effect_term1 = 1. + 32. * ground_effect_state**2 + ground_effect_term1 = 1.0 + 32.0 * ground_effect_state**2 sqrt_get1 = np.sqrt(ground_effect_term1) - drag_coeff_factor_denom = \ - 4. * ground_effect_state * sqrt_get1 + ground_effect_term1 + drag_coeff_factor_denom = 4.0 * ground_effect_state * sqrt_get1 + ground_effect_term1 - drag_coeff_factor = 1. - height_factor / drag_coeff_factor_denom + drag_coeff_factor = 1.0 - height_factor / drag_coeff_factor_denom - d_dc_aoa = base_lift_coefficient * (lift_coeff_factor - 1.) * d_ca_aoa + d_dc_aoa = base_lift_coefficient * (lift_coeff_factor - 1.0) * d_ca_aoa - J['drag_coefficient', 'angle_of_attack'] = d_dc_aoa + J['drag_coefficient', Dynamic.Vehicle.ANGLE_OF_ATTACK] = d_dc_aoa # endregion drag_coefficient wrt angle_of_attack # region drag_coefficient wrt flight_path_angle - d_ca_fpa = 1. + d_ca_fpa = 1.0 - d_dc_fpa = base_lift_coefficient * (lift_coeff_factor - 1.) * d_ca_fpa + d_dc_fpa = base_lift_coefficient * (lift_coeff_factor - 1.0) * d_ca_fpa J['drag_coefficient', Dynamic.Mission.FLIGHT_PATH_ANGLE] = d_dc_fpa # endregion drag_coefficient wrt flight_path_angle # region drag_coefficient wrt altitude - d_get1_alt = 64. * ground_effect_state * d_ges_alt + d_get1_alt = 64.0 * ground_effect_state * d_ges_alt f = ground_effect_state d_f = d_ges_alt g = sqrt_get1 d_g = 0.5 * d_get1_alt / sqrt_get1 - d_dcfd_alt = 4. * ((d_f * g) + (f * d_g)) + d_get1_alt + d_dcfd_alt = 4.0 * ((d_f * g) + (f * d_g)) + d_get1_alt f = height_factor d_f = d_hf_alt @@ -331,22 +342,21 @@ def compute_partials(self, inputs, J, discrete_inputs=None): g = drag_coeff_factor d_g = d_dcf_alt - d_dc_alt = ( - ((d_f * g) + (d_g * f)) * (base_drag_coefficient - minimum_drag_coefficient) - + combined_angle * base_lift_coefficient * d_lcf_alt - ) + d_dc_alt = ((d_f * g) + (d_g * f)) * ( + base_drag_coefficient - minimum_drag_coefficient + ) + combined_angle * base_lift_coefficient * d_lcf_alt J['drag_coefficient', Dynamic.Mission.ALTITUDE] = d_dc_alt # endregion drag_coefficient wrt altitude # region drag_coefficient wrt minimum_drag_coefficient - d_dc_mdc = 1. - lift_coeff_factor * drag_coeff_factor + d_dc_mdc = 1.0 - lift_coeff_factor * drag_coeff_factor J['drag_coefficient', 'minimum_drag_coefficient'] = d_dc_mdc # endregion drag_coefficient wrt minimum_drag_coefficient # region drag_coefficient wrt base_lift_coefficient - d_dc_blc = combined_angle * (lift_coeff_factor - 1.) + d_dc_blc = combined_angle * (lift_coeff_factor - 1.0) J['drag_coefficient', 'base_lift_coefficient'] = d_dc_blc # endregion drag_coefficient wrt base_lift_coefficient @@ -369,14 +379,14 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J['drag_coefficient', Aircraft.Wing.HEIGHT] = d_dc_alt # region drag_coefficient wrt Aircraft.Wing.SPAN - d_get1_b = 64. * ground_effect_state * d_ges_b + d_get1_b = 64.0 * ground_effect_state * d_ges_b f = ground_effect_state d_f = d_ges_b g = sqrt_get1 d_g = 0.5 * d_get1_b / sqrt_get1 - d_dcfd_b = 4. * ((d_f * g) + (f * d_g)) + d_get1_b + d_dcfd_b = 4.0 * ((d_f * g) + (f * d_g)) + d_get1_b f = height_factor d_f = d_hf_b @@ -390,10 +400,9 @@ def compute_partials(self, inputs, J, discrete_inputs=None): g = drag_coeff_factor d_g = d_dcf_b - d_dc_b = ( - ((d_f * g) + (f * d_g)) * (base_drag_coefficient - minimum_drag_coefficient) - + combined_angle * base_lift_coefficient * d_lcf_b - ) + d_dc_b = ((d_f * g) + (f * d_g)) * ( + base_drag_coefficient - minimum_drag_coefficient + ) + combined_angle * base_lift_coefficient * d_lcf_b J['drag_coefficient', Aircraft.Wing.SPAN] = d_dc_b # endregion drag_coefficient wrt Aircraft.Wing.SPAN @@ -408,7 +417,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J['drag_coefficient', Aircraft.Wing.ASPECT_RATIO][idx] = 0.0 J['drag_coefficient', Aircraft.Wing.HEIGHT][idx] = 0.0 J['drag_coefficient', Aircraft.Wing.SPAN][idx] = 0.0 - J['drag_coefficient', 'angle_of_attack'][idx] = 0.0 + J['drag_coefficient', Dynamic.Vehicle.ANGLE_OF_ATTACK][idx] = 0.0 J['drag_coefficient', Dynamic.Mission.FLIGHT_PATH_ANGLE][idx] = 0.0 J['lift_coefficient', Dynamic.Mission.ALTITUDE][idx] = 0.0 diff --git a/aviary/subsystems/aerodynamics/flops_based/induced_drag.py b/aviary/subsystems/aerodynamics/flops_based/induced_drag.py index 8ac3f47261..a8bedf81b3 100644 --- a/aviary/subsystems/aerodynamics/flops_based/induced_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/induced_drag.py @@ -2,79 +2,74 @@ import openmdao.api as om import scipy.constants as _units -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic class InducedDrag(om.ExplicitComponent): - """ - Calculates induced drag - """ + """Calculates induced drag.""" def initialize(self): self.options.declare( - "num_nodes", default=1, types=int, - desc="Number of nodes along mission segment") - self.options.declare( - 'gamma', default=1.4, - desc='Ratio of specific heats for air.') - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'num_nodes', default=1, types=int, desc='Number of nodes along mission segment' + ) + self.options.declare('gamma', default=1.4, desc='Ratio of specific heats for air.') + + add_aviary_option(self, Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # Simulation inputs - self.add_input( - Dynamic.Mission.MACH, shape=(nn), units='unitless', desc="Mach number") - self.add_input( - Dynamic.Mission.LIFT, shape=(nn), units="lbf", desc="Lift magnitude") - self.add_input( - Dynamic.Mission.STATIC_PRESSURE, np.ones(nn), units='lbf/ft**2', - desc='Static pressure at each evaulation point.') + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=(nn), units='lbf') + add_aviary_input(self, Dynamic.Atmosphere.STATIC_PRESSURE, shape=nn, units='lbf/ft**2') # Aero design inputs - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.SPAN_EFFICIENCY_FACTOR, 0.0) - add_aviary_input(self, Aircraft.Wing.SWEEP, 0.0) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, 0.0) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.SPAN_EFFICIENCY_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') # Declare outputs self.add_output( - "induced_drag_coeff", shape=(nn), units='unitless', - desc="Coefficient of induced drag") + 'induced_drag_coeff', shape=(nn), units='unitless', desc='Coefficient of induced drag' + ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] row_col = np.arange(nn) self.declare_partials( 'induced_drag_coeff', - [Dynamic.Mission.MACH, Dynamic.Mission.LIFT, Dynamic.Mission.STATIC_PRESSURE], - rows=row_col, cols=row_col) + [ + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.LIFT, + Dynamic.Atmosphere.STATIC_PRESSURE, + ], + rows=row_col, + cols=row_col, + ) wrt = [ Aircraft.Wing.AREA, Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.SPAN_EFFICIENCY_FACTOR, Aircraft.Wing.SWEEP, - Aircraft.Wing.TAPER_RATIO] + Aircraft.Wing.TAPER_RATIO, + ] self.declare_partials('induced_drag_coeff', wrt, rows=row_col, cols=np.zeros(nn)) def compute(self, inputs, outputs): options = self.options gamma = options['gamma'] - aviary_options: AviaryValues = options['aviary_options'] mach, lift, P, Sref, AR, span_efficiency_factor, SW25, TR = inputs.values() - CL = 2.0 * lift / (Sref * gamma * P * mach ** 2) + CL = 2.0 * lift / (Sref * gamma * P * mach**2) - redux, _ = aviary_options.get_item( - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, (False, None)) + redux = self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] if redux: # Adjustment for extreme taper ratios. @@ -83,7 +78,7 @@ def compute(self, inputs, outputs): # [1] DeYoung, John. "Advanced Supersonic Technology Concept Study Reference # Characteristics," NASA Contractor Report 132374. - span_efficiency_0 = 1.0 + 0.1 * AR * (.4226 * np.sqrt(AR) - .35 * TR - .143) + span_efficiency_0 = 1.0 + 0.1 * AR * (0.4226 * np.sqrt(AR) - 0.35 * TR - 0.143) else: span_efficiency_0 = 1.0 @@ -92,36 +87,36 @@ def compute(self, inputs, outputs): else: span_efficiency = span_efficiency_0 * span_efficiency_factor - CDi = CL ** 2 / (np.pi * AR * span_efficiency) + CDi = CL**2 / (np.pi * AR * span_efficiency) # If forward sweep, add Warner Robins Factor - if (SW25.real < 0.0): + if SW25.real < 0.0: deg_to_rad = _units.degree TH = (1.0 - TR) / (1.0 + TR) / AR tan_sw = np.tan(SW25 / deg_to_rad) COSA = 1.0 / np.sqrt(1.0 + (tan_sw - 3.0 * TH) ** 2) COSB = 1.0 / np.sqrt(1.0 + (tan_sw + TH) ** 2) - CAYT = 0.5 * ( - (1.1 - .11 / (1.1 - mach * COSA)) - / (1.1 - .11 / (1.1 - mach * COSB)) - 1.0)**2 + CAYT = ( + 0.5 + * ((1.1 - 0.11 / (1.1 - mach * COSA)) / (1.1 - 0.11 / (1.1 - mach * COSB)) - 1.0) + ** 2 + ) - CDi += CAYT * CL ** 2 + CDi += CAYT * CL**2 outputs['induced_drag_coeff'] = CDi def compute_partials(self, inputs, partials): options = self.options gamma = options['gamma'] - aviary_options: AviaryValues = options['aviary_options'] mach, lift, P, Sref, AR, span_efficiency_factor, SW25, TR = inputs.values() - redux, _ = aviary_options.get_item( - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, (False, None)) + redux = self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] if redux: sqrt_AR = np.sqrt(AR) - span_efficiency_0 = 1.0 + 0.1 * AR * (.4226 * sqrt_AR - .35 * TR - .143) - dse0_dAR = 0.1 * (.4226 * (sqrt_AR + 0.5 * AR / sqrt_AR) - .35 * TR - .143) + span_efficiency_0 = 1.0 + 0.1 * AR * (0.4226 * sqrt_AR - 0.35 * TR - 0.143) + dse0_dAR = 0.1 * (0.4226 * (sqrt_AR + 0.5 * AR / sqrt_AR) - 0.35 * TR - 0.143) dse0_dTR = -0.035 * AR else: @@ -132,20 +127,19 @@ def compute_partials(self, inputs, partials): else: span_efficiency = span_efficiency_0 * span_efficiency_factor - CL = 2.0 * lift / (Sref * gamma * P * mach ** 2) - dCL_dL = 2.0 / (Sref * gamma * P * mach ** 2) - dCL_dSref = -2.0 * lift / (Sref ** 2 * gamma * P * mach ** 2) - dCL_dP = -2.0 * lift / (Sref * gamma * P ** 2 * mach ** 2) - dCL_dmach = -4.0 * lift / (Sref * gamma * P * mach ** 3) + CL = 2.0 * lift / (Sref * gamma * P * mach**2) + dCL_dL = 2.0 / (Sref * gamma * P * mach**2) + dCL_dSref = -2.0 * lift / (Sref**2 * gamma * P * mach**2) + dCL_dP = -2.0 * lift / (Sref * gamma * P**2 * mach**2) + dCL_dmach = -4.0 * lift / (Sref * gamma * P * mach**3) - CDi = CL ** 2 / (np.pi * AR * span_efficiency) dCDi_dCL = 2.0 * CL / (np.pi * AR * span_efficiency) - dCDi_dAR = -CL ** 2 / (np.pi * AR ** 2 * span_efficiency) - dCDi_dspan = -CL ** 2 / (np.pi * AR * span_efficiency ** 2) + dCDi_dAR = -(CL**2) / (np.pi * AR**2 * span_efficiency) + dCDi_dspan = -(CL**2) / (np.pi * AR * span_efficiency**2) - partials['induced_drag_coeff', Dynamic.Mission.MACH] = dCDi_dCL * dCL_dmach - partials['induced_drag_coeff', Dynamic.Mission.LIFT] = dCDi_dCL * dCL_dL - partials['induced_drag_coeff', Dynamic.Mission.STATIC_PRESSURE] = dCDi_dCL * dCL_dP + partials['induced_drag_coeff', Dynamic.Atmosphere.MACH] = dCDi_dCL * dCL_dmach + partials['induced_drag_coeff', Dynamic.Vehicle.LIFT] = dCDi_dCL * dCL_dL + partials['induced_drag_coeff', Dynamic.Atmosphere.STATIC_PRESSURE] = dCDi_dCL * dCL_dP partials['induced_drag_coeff', Aircraft.Wing.ASPECT_RATIO] = dCDi_dAR partials['induced_drag_coeff', Aircraft.Wing.SPAN_EFFICIENCY_FACTOR] = 0.0 partials['induced_drag_coeff', Aircraft.Wing.SWEEP] = 0.0 @@ -153,72 +147,71 @@ def compute_partials(self, inputs, partials): partials['induced_drag_coeff', Aircraft.Wing.AREA] = dCDi_dCL * dCL_dSref if span_efficiency_factor <= 0.3: - partials['induced_drag_coeff', Aircraft.Wing.SPAN_EFFICIENCY_FACTOR] = \ - dCDi_dspan + partials['induced_drag_coeff', Aircraft.Wing.SPAN_EFFICIENCY_FACTOR] = dCDi_dspan if redux: - partials['induced_drag_coeff', Aircraft.Wing.ASPECT_RATIO] += \ - dCDi_dspan * dse0_dAR - partials['induced_drag_coeff', Aircraft.Wing.TAPER_RATIO] = \ - dCDi_dspan * dse0_dTR + partials['induced_drag_coeff', Aircraft.Wing.ASPECT_RATIO] += dCDi_dspan * dse0_dAR + partials['induced_drag_coeff', Aircraft.Wing.TAPER_RATIO] = dCDi_dspan * dse0_dTR else: - partials['induced_drag_coeff', Aircraft.Wing.SPAN_EFFICIENCY_FACTOR] = \ + partials['induced_drag_coeff', Aircraft.Wing.SPAN_EFFICIENCY_FACTOR] = ( dCDi_dspan * span_efficiency_0 + ) if redux: - partials['induced_drag_coeff', Aircraft.Wing.ASPECT_RATIO] += \ + partials['induced_drag_coeff', Aircraft.Wing.ASPECT_RATIO] += ( dCDi_dspan * dse0_dAR * span_efficiency_factor - partials['induced_drag_coeff', Aircraft.Wing.TAPER_RATIO] = \ + ) + partials['induced_drag_coeff', Aircraft.Wing.TAPER_RATIO] = ( dCDi_dspan * dse0_dTR * span_efficiency_factor + ) # If forward sweep, add Warner Robins Factor - if (SW25.real < 0.0): + if SW25.real < 0.0: deg_to_rad = _units.degree fact1 = 1.0 - TR fact2 = 1.0 / (1.0 + TR) TH = fact1 * fact2 / AR - dTH_dTR = - (fact2 + fact1 * fact2 ** 2) / AR - dTH_dAR = - fact1 * fact2 / AR ** 2 + dTH_dTR = -(fact2 + fact1 * fact2**2) / AR + dTH_dAR = -fact1 * fact2 / AR**2 tan_sw = np.tan(SW25 / deg_to_rad) dtansw_dsw = 1.0 / (deg_to_rad * np.cos(SW25 / deg_to_rad) ** 2) fact3 = 1.0 + (tan_sw - 3.0 * TH) ** 2 COSA = 1.0 / np.sqrt(fact3) - dCOSA_dtansw = -0.5 / fact3 ** 1.5 * 2.0 * (tan_sw - 3.0 * TH) - dCOSA_dTH = 0.5 / fact3 ** 1.5 * 6.0 * (tan_sw - 3.0 * TH) + dCOSA_dtansw = -0.5 / fact3**1.5 * 2.0 * (tan_sw - 3.0 * TH) + dCOSA_dTH = 0.5 / fact3**1.5 * 6.0 * (tan_sw - 3.0 * TH) fact4 = 1.0 + (tan_sw + TH) ** 2 COSB = 1.0 / np.sqrt(fact4) - dCOSB_dtansw = -0.5 / fact4 ** 1.5 * 2.0 * (tan_sw + TH) - dCOSB_dTH = -0.5 / fact4 ** 1.5 * 2.0 * (tan_sw + TH) + dCOSB_dtansw = -0.5 / fact4**1.5 * 2.0 * (tan_sw + TH) + dCOSB_dTH = -0.5 / fact4**1.5 * 2.0 * (tan_sw + TH) factA = 1.1 - mach * COSA factB = 1.1 - mach * COSB - fact5 = 1.1 - .11 / factA - fact6 = 1.1 - .11 / factB - CAYT = 0.5 * (fact5 / fact6 - 1.0)**2 + fact5 = 1.1 - 0.11 / factA + fact6 = 1.1 - 0.11 / factB + CAYT = 0.5 * (fact5 / fact6 - 1.0) ** 2 dCAYT_dmach = (fact5 / fact6 - 1.0) * ( - -.11 * COSA / (fact6 * factA ** 2) - + .11 * fact5 * COSB / (factB ** 2 * fact6 ** 2)) - dCAYT_dCOSA = (fact5 / fact6 - 1.0) * (-.11 * mach / (fact6 * factA ** 2)) - dCAYT_dCOSB = (fact5 / fact6 - 1.0) * ( - .11 * fact5 * mach / (factB ** 2 * fact6 ** 2)) + -0.11 * COSA / (fact6 * factA**2) + 0.11 * fact5 * COSB / (factB**2 * fact6**2) + ) + dCAYT_dCOSA = (fact5 / fact6 - 1.0) * (-0.11 * mach / (fact6 * factA**2)) + dCAYT_dCOSB = (fact5 / fact6 - 1.0) * (0.11 * fact5 * mach / (factB**2 * fact6**2)) - dCDi_dCAYT = CL ** 2 + dCDi_dCAYT = CL**2 dCDi_dCL = 2.0 * CAYT * CL - partials['induced_drag_coeff', Dynamic.Mission.MACH] += \ + partials['induced_drag_coeff', Dynamic.Atmosphere.MACH] += ( dCDi_dCL * dCL_dmach + dCDi_dCAYT * dCAYT_dmach - partials['induced_drag_coeff', Dynamic.Mission.LIFT] += dCDi_dCL * dCL_dL + ) + partials['induced_drag_coeff', Dynamic.Vehicle.LIFT] += dCDi_dCL * dCL_dL partials['induced_drag_coeff', Aircraft.Wing.ASPECT_RATIO] += ( - dCDi_dCAYT * dTH_dAR - * (dCAYT_dCOSA * dCOSA_dTH + dCAYT_dCOSB * dCOSB_dTH)) + dCDi_dCAYT * dTH_dAR * (dCAYT_dCOSA * dCOSA_dTH + dCAYT_dCOSB * dCOSB_dTH) + ) partials['induced_drag_coeff', Aircraft.Wing.SWEEP] += ( - dCDi_dCAYT * dtansw_dsw - * (dCAYT_dCOSA * dCOSA_dtansw + dCAYT_dCOSB * dCOSB_dtansw)) - partials['induced_drag_coeff', - Dynamic.Mission.STATIC_PRESSURE] += dCDi_dCL * dCL_dP + dCDi_dCAYT * dtansw_dsw * (dCAYT_dCOSA * dCOSA_dtansw + dCAYT_dCOSB * dCOSB_dtansw) + ) + partials['induced_drag_coeff', Dynamic.Atmosphere.STATIC_PRESSURE] += dCDi_dCL * dCL_dP partials['induced_drag_coeff', Aircraft.Wing.TAPER_RATIO] += ( - dCDi_dCAYT * dTH_dTR - * (dCAYT_dCOSA * dCOSA_dTH + dCAYT_dCOSB * dCOSB_dTH)) + dCDi_dCAYT * dTH_dTR * (dCAYT_dCOSA * dCOSA_dTH + dCAYT_dCOSB * dCOSB_dTH) + ) partials['induced_drag_coeff', Aircraft.Wing.AREA] += dCDi_dCL * dCL_dSref diff --git a/aviary/subsystems/aerodynamics/flops_based/lift.py b/aviary/subsystems/aerodynamics/flops_based/lift.py index 7f126d1d7f..11cb1cc420 100644 --- a/aviary/subsystems/aerodynamics/flops_based/lift.py +++ b/aviary/subsystems/aerodynamics/flops_based/lift.py @@ -2,16 +2,14 @@ import openmdao.api as om import aviary.constants as constants -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Dynamic grav_metric = constants.GRAV_METRIC_FLOPS class SimpleLift(om.ExplicitComponent): - ''' - Calculate lift as a function of wing area, dynamic pressure, and lift coefficient. - ''' + """Calculate lift as a function of wing area, dynamic pressure, and lift coefficient.""" def initialize(self): self.options.declare('num_nodes', types=int) @@ -19,43 +17,44 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Wing.AREA, val=1., units='m**2') + add_aviary_input(self, Aircraft.Wing.AREA, units='m**2') - self.add_input( - Dynamic.Mission.DYNAMIC_PRESSURE, val=np.ones(nn), units='N/m**2', - desc='pressure caused by fluid motion') + add_aviary_input(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='N/m**2') self.add_input( - name='cl', val=np.ones(nn), desc='current coefficient of lift', - units='unitless') + name='cl', val=np.ones(nn), desc='current coefficient of lift', units='unitless' + ) - self.add_output(name=Dynamic.Mission.LIFT, - val=np.ones(nn), desc='Lift', units='N') + add_aviary_output(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') def setup_partials(self): nn = self.options['num_nodes'] rows_cols = np.arange(nn) - self.declare_partials(Dynamic.Mission.LIFT, Aircraft.Wing.AREA) + self.declare_partials(Dynamic.Vehicle.LIFT, Aircraft.Wing.AREA) self.declare_partials( - Dynamic.Mission.LIFT, [Dynamic.Mission.DYNAMIC_PRESSURE, 'cl'], rows=rows_cols, cols=rows_cols) + Dynamic.Vehicle.LIFT, + [Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'cl'], + rows=rows_cols, + cols=rows_cols, + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): S = inputs[Aircraft.Wing.AREA] - q = inputs[Dynamic.Mission.DYNAMIC_PRESSURE] + q = inputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] CL = inputs['cl'] - outputs[Dynamic.Mission.LIFT] = q * S * CL + outputs[Dynamic.Vehicle.LIFT] = q * S * CL def compute_partials(self, inputs, partials, discrete_inputs=None): S = inputs[Aircraft.Wing.AREA] - q = inputs[Dynamic.Mission.DYNAMIC_PRESSURE] + q = inputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] CL = inputs['cl'] - partials[Dynamic.Mission.LIFT, Aircraft.Wing.AREA] = q * CL - partials[Dynamic.Mission.LIFT, Dynamic.Mission.DYNAMIC_PRESSURE] = S * CL - partials[Dynamic.Mission.LIFT, 'cl'] = q * S + partials[Dynamic.Vehicle.LIFT, Aircraft.Wing.AREA] = q * CL + partials[Dynamic.Vehicle.LIFT, Dynamic.Atmosphere.DYNAMIC_PRESSURE] = S * CL + partials[Dynamic.Vehicle.LIFT, 'cl'] = q * S class LiftEqualsWeight(om.ExplicitComponent): @@ -71,51 +70,54 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, varname=Aircraft.Wing.AREA, val=1.0, units='m**2') + add_aviary_input(self, Aircraft.Wing.AREA, units='m**2') - self.add_input( - name=Dynamic.Mission.MASS, val=np.ones(nn), desc='current aircraft mass', - units='kg') + add_aviary_input(self, Dynamic.Vehicle.MASS, shape=nn, units='kg') - self.add_input( - Dynamic.Mission.DYNAMIC_PRESSURE, val=np.ones(nn), units='N/m**2', - desc='pressure caused by fluid motion') + add_aviary_input(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='N/m**2') self.add_output( - name='cl', val=np.ones(nn), desc='current coefficient of lift', - units='unitless') + name='cl', val=np.ones(nn), desc='current coefficient of lift', units='unitless' + ) - self.add_output(name=Dynamic.Mission.LIFT, - val=np.ones(nn), desc='Lift', units='N') + add_aviary_output(self, Dynamic.Vehicle.LIFT, shape=nn, units='N') def setup_partials(self): nn = self.options['num_nodes'] row_col = np.arange(nn) self.declare_partials( - Dynamic.Mission.LIFT, Dynamic.Mission.MASS, rows=row_col, cols=row_col, val=grav_metric) + Dynamic.Vehicle.LIFT, Dynamic.Vehicle.MASS, rows=row_col, cols=row_col, val=grav_metric + ) self.declare_partials( - Dynamic.Mission.LIFT, [Aircraft.Wing.AREA, Dynamic.Mission.DYNAMIC_PRESSURE], dependent=False) + Dynamic.Vehicle.LIFT, + [Aircraft.Wing.AREA, Dynamic.Atmosphere.DYNAMIC_PRESSURE], + dependent=False, + ) self.declare_partials('cl', Aircraft.Wing.AREA) self.declare_partials( - 'cl', [Dynamic.Mission.MASS, Dynamic.Mission.DYNAMIC_PRESSURE], rows=row_col, cols=row_col) + 'cl', + [Dynamic.Vehicle.MASS, Dynamic.Atmosphere.DYNAMIC_PRESSURE], + rows=row_col, + cols=row_col, + ) def compute(self, inputs, outputs): S = inputs[Aircraft.Wing.AREA] - q = inputs[Dynamic.Mission.DYNAMIC_PRESSURE] - weight = grav_metric * inputs[Dynamic.Mission.MASS] + q = inputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] + weight = grav_metric * inputs[Dynamic.Vehicle.MASS] outputs['cl'] = weight / (q * S) - outputs[Dynamic.Mission.LIFT] = weight + outputs[Dynamic.Vehicle.LIFT] = weight def compute_partials(self, inputs, partials, discrete_inputs=None): S = inputs[Aircraft.Wing.AREA] - q = inputs[Dynamic.Mission.DYNAMIC_PRESSURE] - weight = grav_metric * inputs[Dynamic.Mission.MASS] + q = inputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] + weight = grav_metric * inputs[Dynamic.Vehicle.MASS] f = weight / q # df = 0. @@ -123,10 +125,10 @@ def compute_partials(self, inputs, partials, discrete_inputs=None): # dg = 1. partials['cl', Aircraft.Wing.AREA] = -f / g**2 - partials['cl', Dynamic.Mission.MASS] = grav_metric / (q * S) + partials['cl', Dynamic.Vehicle.MASS] = grav_metric / (q * S) f = weight / S # df = 0. g = q # dg = 1. - partials['cl', Dynamic.Mission.DYNAMIC_PRESSURE] = -f / g**2 + partials['cl', Dynamic.Atmosphere.DYNAMIC_PRESSURE] = -f / g**2 diff --git a/aviary/subsystems/aerodynamics/flops_based/lift_dependent_drag.py b/aviary/subsystems/aerodynamics/flops_based/lift_dependent_drag.py index 9c8140008b..272bf6c4c0 100644 --- a/aviary/subsystems/aerodynamics/flops_based/lift_dependent_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/lift_dependent_drag.py @@ -8,73 +8,85 @@ class LiftDependentDrag(om.ExplicitComponent): - """ - Calculates lift dependent drag - """ + """Calculates lift dependent drag.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int, - desc="Number of nodes along mission segment") - self.options.declare('gamma', default=1.4, - desc='Ratio of specific heats for air.') + self.options.declare( + 'num_nodes', default=1, types=int, desc='Number of nodes along mission segment' + ) + self.options.declare('gamma', default=1.4, desc='Ratio of specific heats for air.') def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # Simulation inputs - self.add_input(Dynamic.Mission.MACH, shape=( - nn), units='unitless', desc="Mach number") - self.add_input(Dynamic.Mission.LIFT, shape=( - nn), units="lbf", desc="Lift magnitude") - self.add_input(Dynamic.Mission.STATIC_PRESSURE, np.ones(nn), units='lbf/ft**2', - desc='Static pressure at each evaulation point.') + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') + add_aviary_input(self, Dynamic.Vehicle.LIFT, shape=(nn), units='lbf') + add_aviary_input(self, Dynamic.Atmosphere.STATIC_PRESSURE, shape=nn, units='lbf/ft**2') # Aero design inputs - add_aviary_input(self, Mission.Design.LIFT_COEFFICIENT, 0.0) - add_aviary_input(self, Mission.Design.MACH, 0.0) + add_aviary_input(self, Mission.Design.LIFT_COEFFICIENT, units='unitless') + add_aviary_input(self, Mission.Design.MACH, units='unitless') # Aircraft design inputs - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, 0.0) - add_aviary_input(self, Aircraft.Wing.SWEEP, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') # Declare outputs - self.add_output("CD", shape=(nn), units='unitless', - desc="Coefficient of lift dependent drag") + self.add_output( + 'CD', shape=(nn), units='unitless', desc='Coefficient of lift dependent drag' + ) def setup_partials(self): - nn = self.options["num_nodes"] - - self.declare_partials('CD', [Dynamic.Mission.MACH, Dynamic.Mission.LIFT, Dynamic.Mission.STATIC_PRESSURE], - rows=np.arange(nn), cols=np.arange(nn)) - - wrt = [Mission.Design.LIFT_COEFFICIENT, - Mission.Design.MACH, - Aircraft.Wing.AREA, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, - Aircraft.Wing.SWEEP, - Aircraft.Wing.THICKNESS_TO_CHORD] + nn = self.options['num_nodes'] + + self.declare_partials( + 'CD', + [ + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.LIFT, + Dynamic.Atmosphere.STATIC_PRESSURE, + ], + rows=np.arange(nn), + cols=np.arange(nn), + ) + + wrt = [ + Mission.Design.LIFT_COEFFICIENT, + Mission.Design.MACH, + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, + Aircraft.Wing.SWEEP, + Aircraft.Wing.THICKNESS_TO_CHORD, + ] self.declare_partials('CD', wrt) def edge_interp(self, A1, A2, FCDP1, FCDP2, dFCDP1, dFCDP2, A): - - den = 1.0 / ((A - A1)*FCDP1 - (A - A2)*FCDP2) + den = 1.0 / ((A - A1) * FCDP1 - (A - A2) * FCDP2) FCDP = 2.0 * FCDP1 * FCDP2 * den # Derivative of FCDP w.r.t A variable at value of A - dFCDP_dA = 2.0 * FCDP1 * FCDP2 * (FCDP2 - FCDP1) * den ** 2 + dFCDP_dA = 2.0 * FCDP1 * FCDP2 * (FCDP2 - FCDP1) * den**2 - dFCDP_dDEL = 2.0 * den * (dFCDP1 * (FCDP2 - FCDP1 * FCDP2 * den * (A - A1)) + - dFCDP2 * (FCDP1 + FCDP1 * FCDP2 * den * (A - A2))) + dFCDP_dDEL = ( + 2.0 + * den + * ( + dFCDP1 * (FCDP2 - FCDP1 * FCDP2 * den * (A - A1)) + + dFCDP2 * (FCDP1 + FCDP1 * FCDP2 * den * (A - A2)) + ) + ) return FCDP, dFCDP_dDEL[:, 0], dFCDP_dDEL[:, 1], dFCDP_dA - def inner_interp(self, arrA, FCDP1, FCDP2, FCDP3, FCDP4, FCDP5, dFCDP1, dFCDP2, dFCDP3, dFCDP4, dFCDP5, A): - + def inner_interp( + self, arrA, FCDP1, FCDP2, FCDP3, FCDP4, FCDP5, dFCDP1, dFCDP2, dFCDP3, dFCDP4, dFCDP5, A + ): # Derivative of FCDP w.r.t A variable at value of A arrFCDP = np.array([FCDP1, FCDP2, FCDP3, FCDP4, FCDP5]) arrFCDP = np.reshape(arrFCDP, (5)) @@ -84,21 +96,19 @@ def inner_interp(self, arrA, FCDP1, FCDP2, FCDP3, FCDP4, FCDP5, dFCDP1, dFCDP2, # Derivative of FCDP w.r.t DELM variable at value of A arrdFCDP_dDELM = np.array( - [dFCDP1[:, 0], dFCDP2[:, 0], dFCDP3[:, 0], dFCDP4[:, 0], dFCDP5[:, 0]]) + [dFCDP1[:, 0], dFCDP2[:, 0], dFCDP3[:, 0], dFCDP4[:, 0], dFCDP5[:, 0]] + ) arrdFCDP_dDELM = np.reshape(arrdFCDP_dDELM, (5)) - interp_arrdFCDP_dDELM = InterpND( - method='lagrange2', points=(arrA), values=arrdFCDP_dDELM) - dFCDP_dDELM, deriv = interp_arrdFCDP_dDELM.interpolate( - A, compute_derivative=True) # at A + interp_arrdFCDP_dDELM = InterpND(method='lagrange2', points=(arrA), values=arrdFCDP_dDELM) + dFCDP_dDELM, deriv = interp_arrdFCDP_dDELM.interpolate(A, compute_derivative=True) # at A # Derivative of FCDP w.r.t DELCL variable at value of A arrdFCDP_dDELCL = np.array( - [dFCDP1[:, 1], dFCDP2[:, 1], dFCDP3[:, 1], dFCDP4[:, 1], dFCDP5[:, 1]]) + [dFCDP1[:, 1], dFCDP2[:, 1], dFCDP3[:, 1], dFCDP4[:, 1], dFCDP5[:, 1]] + ) arrdFCDP_dDELCL = np.reshape(arrdFCDP_dDELCL, (5)) - interp_arrdFCDP_dDELCL = InterpND( - method='lagrange2', points=(arrA), values=arrdFCDP_dDELCL) - dFCDP_dDELCL, deriv = interp_arrdFCDP_dDELCL.interpolate( - A, compute_derivative=True) # at A + interp_arrdFCDP_dDELCL = InterpND(method='lagrange2', points=(arrA), values=arrdFCDP_dDELCL) + dFCDP_dDELCL, deriv = interp_arrdFCDP_dDELCL.interpolate(A, compute_derivative=True) # at A return FCDP[0], dFCDP_dDELM[0], dFCDP_dDELCL[0], dFCDP_dA[0] @@ -111,7 +121,7 @@ def compute(self, inputs, outputs): :param outputs: _description_ :type outputs: _type_ """ - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] gamma = self.options['gamma'] mach, lift, P, CLDES, MDES, Sref, AR, CAM, SW25, TC = inputs.values() @@ -121,20 +131,17 @@ def compute(self, inputs, outputs): dFCDP_dDELCL = np.empty(nn, dtype=mach.dtype) dFCDP_dA = np.empty(nn, dtype=mach.dtype) - CL = 2.0 * lift / (Sref * gamma * P * mach ** 2) + CL = 2.0 * lift / (Sref * gamma * P * mach**2) DELCL = CL - CLDES DELM = mach - MDES - A = self.A = AR * TC ** (1.0/3.0) + A = self.A = AR * TC ** (1.0 / 3.0) for i in range(0, nn): - x = np.array([DELM[i], DELCL[i]]) if DELM[i].real <= 0.075: - if A.real < 0.5: - FCDP1, dFCDP1 = AR05table.interpolate(x, compute_derivative=True) FCDP2, dFCDP2 = AR1table.interpolate(x, compute_derivative=True) @@ -145,7 +152,6 @@ def compute(self, inputs, outputs): ) elif 0.5 <= A.real < 6: - FCDP1, dFCDP1 = AR05table.interpolate(x, compute_derivative=True) FCDP2, dFCDP2 = AR1table.interpolate(x, compute_derivative=True) FCDP3, dFCDP3 = AR2table.interpolate(x, compute_derivative=True) @@ -154,11 +160,21 @@ def compute(self, inputs, outputs): arrA = np.array([0.5, 1, 2, 4, 6]) FCDP[i], dFCDP_dDELM[i], dFCDP_dDELCL[i], dFCDP_dA[i] = self.inner_interp( - arrA, FCDP1, FCDP2, FCDP3, FCDP4, FCDP5, dFCDP1, dFCDP2, dFCDP3, dFCDP4, dFCDP5, A + arrA, + FCDP1, + FCDP2, + FCDP3, + FCDP4, + FCDP5, + dFCDP1, + dFCDP2, + dFCDP3, + dFCDP4, + dFCDP5, + A, ) else: - FCDP1, dFCDP1 = AR4table.interpolate(x, compute_derivative=True) FCDP2, dFCDP2 = AR6table.interpolate(x, compute_derivative=True) @@ -169,9 +185,7 @@ def compute(self, inputs, outputs): ) else: - if A.real < 0.7: - FCDP1, dFCDP1 = ARS07table.interpolate(x, compute_derivative=True) FCDP2, dFCDP2 = ARS08table.interpolate(x, compute_derivative=True) @@ -182,7 +196,6 @@ def compute(self, inputs, outputs): ) elif 0.7 <= A.real <= 1.4: - FCDP1, dFCDP1 = ARS07table.interpolate(x, compute_derivative=True) FCDP2, dFCDP2 = ARS08table.interpolate(x, compute_derivative=True) FCDP3, dFCDP3 = ARS10table.interpolate(x, compute_derivative=True) @@ -191,11 +204,21 @@ def compute(self, inputs, outputs): arrA = np.array([0.7, 0.8, 1.0, 1.2, 1.4]) FCDP[i], dFCDP_dDELM[i], dFCDP_dDELCL[i], dFCDP_dA[i] = self.inner_interp( - arrA, FCDP1, FCDP2, FCDP3, FCDP4, FCDP5, dFCDP1, dFCDP2, dFCDP3, dFCDP4, dFCDP5, A + arrA, + FCDP1, + FCDP2, + FCDP3, + FCDP4, + FCDP5, + dFCDP1, + dFCDP2, + dFCDP3, + dFCDP4, + dFCDP5, + A, ) elif 1.4 < A.real <= 2.0: - FCDP1, dFCDP1 = ARS12table.interpolate(x, compute_derivative=True) FCDP2, dFCDP2 = ARS14table.interpolate(x, compute_derivative=True) FCDP3, dFCDP3 = ARS16table.interpolate(x, compute_derivative=True) @@ -204,11 +227,21 @@ def compute(self, inputs, outputs): arrA = np.array([1.2, 1.4, 1.6, 1.8, 2.0]) FCDP[i], dFCDP_dDELM[i], dFCDP_dDELCL[i], dFCDP_dA[i] = self.inner_interp( - arrA, FCDP1, FCDP2, FCDP3, FCDP4, FCDP5, dFCDP1, dFCDP2, dFCDP3, dFCDP4, dFCDP5, A + arrA, + FCDP1, + FCDP2, + FCDP3, + FCDP4, + FCDP5, + dFCDP1, + dFCDP2, + dFCDP3, + dFCDP4, + dFCDP5, + A, ) else: - FCDP1, dFCDP1 = ARS18table.interpolate(x, compute_derivative=True) FCDP2, dFCDP2 = ARS20table.interpolate(x, compute_derivative=True) @@ -218,7 +251,7 @@ def compute(self, inputs, outputs): A1, A2, FCDP1, FCDP2, dFCDP1, dFCDP2, A ) - DCDP = FCDP * (1.0 + CAM/10.0) * A/AR + DCDP = FCDP * (1.0 + CAM / 10.0) * A / AR self.clamp_indices = np.where(DCDP < 0) DCDP[DCDP < 0] = 0.0 @@ -227,7 +260,7 @@ def compute(self, inputs, outputs): self.dFCDP_dDELM = dFCDP_dDELM self.dFCDP_dDELCL = dFCDP_dDELCL - outputs["CD"] = DCDP + outputs['CD'] = DCDP def compute_partials(self, inputs, partials): """ @@ -241,26 +274,25 @@ def compute_partials(self, inputs, partials): gamma = self.options['gamma'] mach, lift, P, CLDES, MDES, Sref, AR, CAM, SW25, TC = inputs.values() - ddelCL_dL = 2.0 / (Sref * gamma * P * mach ** 2) - ddelCL_dP = -2.0 * lift / (Sref * gamma * P * P * mach ** 2) - ddelCL_dSref = -2.0 * lift / (Sref * Sref * gamma * P * mach ** 2) - ddelCL_dmach = -4.0 * lift / (Sref * gamma * P * mach ** 3) + ddelCL_dL = 2.0 / (Sref * gamma * P * mach**2) + ddelCL_dP = -2.0 * lift / (Sref * gamma * P * P * mach**2) + ddelCL_dSref = -2.0 * lift / (Sref * Sref * gamma * P * mach**2) + ddelCL_dmach = -4.0 * lift / (Sref * gamma * P * mach**3) - A = self.A FCDP = self.FCDP dFCDP_dA = self.dFCDP_dA dFCDP_dDELM = self.dFCDP_dDELM dFCDP_dDELCL = self.dFCDP_dDELCL # A = AR * TC**(1.0 / 3.0) - dA_dAR = TC**(1.0 / 3.0) - dA_dTC = (1.0 / 3.0) * AR * TC**(-2.0 / 3.0) + dA_dAR = TC ** (1.0 / 3.0) + dA_dTC = (1.0 / 3.0) * AR * TC ** (-2.0 / 3.0) dA_dCAM = 0.0 dA_dSW25 = 0.0 - dDCDP_dFCDP = (1 + CAM/10.0) * TC**(1.0 / 3.0) + dDCDP_dFCDP = (1 + CAM / 10.0) * TC ** (1.0 / 3.0) - ddelCL_dL = 2.0 / (Sref * gamma * P * mach ** 2) + ddelCL_dL = 2.0 / (Sref * gamma * P * mach**2) # Derivative of lift-dependent drag w.r.t. Mach dCD_dmach = dDCDP_dFCDP * dFCDP_dDELM @@ -273,12 +305,12 @@ def compute_partials(self, inputs, partials): dCD_dAR = dDCDP_dFCDP * dFCDP_dAR # Derivative of lift-dependent drag w.r.t. thickness-to-chord ratio - dDCDP_dTC = (1.0 / 3.0) * FCDP * (1 + CAM/10.0) * TC**(-2.0 / 3.0) + dDCDP_dTC = (1.0 / 3.0) * FCDP * (1 + CAM / 10.0) * TC ** (-2.0 / 3.0) dFCDP_dTC = dFCDP_dA * dA_dTC dCD_dTC = dDCDP_dFCDP * dFCDP_dTC + dDCDP_dTC # Derivative of lift-dependent drag w.r.t. wing camber - dDCDP_dCAM = (FCDP / 10.0) * TC**(1.0 / 3.0) + dDCDP_dCAM = (FCDP / 10.0) * TC ** (1.0 / 3.0) dFCDP_dCAM = dFCDP_dA * dA_dCAM dCD_dCAM = dDCDP_dFCDP * dFCDP_dCAM + dDCDP_dCAM @@ -286,334 +318,694 @@ def compute_partials(self, inputs, partials): dFCDP_dSW25 = dFCDP_dA * dA_dSW25 dCD_dSW25 = dDCDP_dFCDP * dFCDP_dSW25 - partials["CD", Dynamic.Mission.MACH] = dCD_dmach + dCD_dCL * ddelCL_dmach - partials["CD", Dynamic.Mission.LIFT] = dCD_dCL * ddelCL_dL - partials["CD", Dynamic.Mission.STATIC_PRESSURE] = dCD_dCL * ddelCL_dP - partials["CD", Aircraft.Wing.AREA] = dCD_dCL * ddelCL_dSref - partials["CD", Aircraft.Wing.ASPECT_RATIO] = dCD_dAR - partials["CD", Aircraft.Wing.THICKNESS_TO_CHORD] = dCD_dTC - partials["CD", Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN] = dCD_dCAM - partials["CD", Aircraft.Wing.SWEEP] = dCD_dSW25 - partials["CD", Mission.Design.LIFT_COEFFICIENT] = -dCD_dCL - partials["CD", Mission.Design.MACH] = -dCD_dmach + partials['CD', Dynamic.Atmosphere.MACH] = dCD_dmach + dCD_dCL * ddelCL_dmach + partials['CD', Dynamic.Vehicle.LIFT] = dCD_dCL * ddelCL_dL + partials['CD', Dynamic.Atmosphere.STATIC_PRESSURE] = dCD_dCL * ddelCL_dP + partials['CD', Aircraft.Wing.AREA] = dCD_dCL * ddelCL_dSref + partials['CD', Aircraft.Wing.ASPECT_RATIO] = dCD_dAR + partials['CD', Aircraft.Wing.THICKNESS_TO_CHORD] = dCD_dTC + partials['CD', Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN] = dCD_dCAM + partials['CD', Aircraft.Wing.SWEEP] = dCD_dSW25 + partials['CD', Mission.Design.LIFT_COEFFICIENT] = -dCD_dCL + partials['CD', Mission.Design.MACH] = -dCD_dmach if self.clamp_indices: - partials["CD", Dynamic.Mission.MACH][self.clamp_indices] = 0.0 - partials["CD", Dynamic.Mission.LIFT][self.clamp_indices] = 0.0 - partials["CD", Dynamic.Mission.STATIC_PRESSURE][self.clamp_indices] = 0.0 - partials["CD", Aircraft.Wing.AREA][self.clamp_indices] = 0.0 - partials["CD", Aircraft.Wing.ASPECT_RATIO][self.clamp_indices] = 0.0 - partials["CD", Aircraft.Wing.THICKNESS_TO_CHORD][self.clamp_indices] = 0.0 - partials["CD", Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN][self.clamp_indices] = 0.0 - partials["CD", Aircraft.Wing.SWEEP][self.clamp_indices] = 0.0 - partials["CD", Mission.Design.LIFT_COEFFICIENT][self.clamp_indices] = 0.0 - partials["CD", Mission.Design.MACH][self.clamp_indices] = 0.0 + partials['CD', Dynamic.Atmosphere.MACH][self.clamp_indices] = 0.0 + partials['CD', Dynamic.Vehicle.LIFT][self.clamp_indices] = 0.0 + partials['CD', Dynamic.Atmosphere.STATIC_PRESSURE][self.clamp_indices] = 0.0 + partials['CD', Aircraft.Wing.AREA][self.clamp_indices] = 0.0 + partials['CD', Aircraft.Wing.ASPECT_RATIO][self.clamp_indices] = 0.0 + partials['CD', Aircraft.Wing.THICKNESS_TO_CHORD][self.clamp_indices] = 0.0 + partials['CD', Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN][self.clamp_indices] = 0.0 + partials['CD', Aircraft.Wing.SWEEP][self.clamp_indices] = 0.0 + partials['CD', Mission.Design.LIFT_COEFFICIENT][self.clamp_indices] = 0.0 + partials['CD', Mission.Design.MACH][self.clamp_indices] = 0.0 # Tables +# fmt: off AR05 = np.array( - [[11010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [-0.800000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, - 0.006000, 0.014000, 0.028000, 0.082500, 0.150000], - [-0.200000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, - 0.006000, 0.014000, 0.028000, 0.082500, 0.150000], - [-0.160000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, - 0.006000, 0.014000, 0.028000, 0.082500, 0.150000], - [-0.120000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, - 0.006000, 0.014000, 0.028000, 0.082500, 0.150000], - [-0.080000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, - 0.006000, 0.014000, 0.028000, 0.082500, 0.150000], - [-0.040000, 0.001500, 0.000400, 0.001500, 0.002600, 0.003500, - 0.007500, 0.014000, 0.028000, 0.082500, 0.152500], - [-0.020000, 0.001600, 0.000400, 0.001600, 0.002800, 0.003500, - 0.008500, 0.014000, 0.029000, 0.084000, 0.156000], - [0.000000, 0.001800, 0.000400, 0.001800, 0.003000, 0.003600, - 0.010000, 0.014000, 0.031000, 0.086000, 0.162000], - [0.020000, 0.002050, 0.000400, 0.002100, 0.003100, 0.003900, - 0.010000, 0.016000, 0.033000, 0.089500, 0.168000], - [0.040000, 0.002300, 0.000400, 0.002300, 0.003200, 0.004500, - 0.010000, 0.018000, 0.034000, 0.095500, 0.172500], - [0.050000, 0.002400, 0.000400, 0.002400, 0.003200, 0.004900, 0.010000, 0.019000, 0.034000, 0.100000, 0.175000]]) + [ + [ + 11010, -0.400000, -0.300000, -0.200000, -0.100000, + -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000 + ], + [ + -0.800000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, + 0.006000, 0.014000, 0.028000, 0.082500, 0.150000 + ], + [ + -0.200000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, + 0.006000, 0.014000, 0.028000, 0.082500, 0.150000 + ], + [ + -0.160000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, + 0.006000, 0.014000, 0.028000, 0.082500, 0.150000 + ], + [ + -0.120000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, + 0.006000, 0.014000, 0.028000, 0.082500, 0.150000 + ], + [ + -0.080000, 0.001500, 0.000400, 0.001500, 0.002400, 0.003500, + 0.006000, 0.014000, 0.028000, 0.082500, 0.150000 + ], + [ + -0.040000, 0.001500, 0.000400, 0.001500, 0.002600, 0.003500, + 0.007500, 0.014000, 0.028000, 0.082500, 0.152500 + ], + [ + -0.020000, 0.001600, 0.000400, 0.001600, 0.002800, 0.003500, + 0.008500, 0.014000, 0.029000, 0.084000, 0.156000 + ], + [ + 0.000000, 0.001800, 0.000400, 0.001800, 0.003000, 0.003600, + 0.010000, 0.014000, 0.031000, 0.086000, 0.162000 + ], + [ + 0.020000, 0.002050, 0.000400, 0.002100, 0.003100, 0.003900, + 0.010000, 0.016000, 0.033000, 0.089500, 0.168000 + ], + [ + 0.040000, 0.002300, 0.000400, 0.002300, 0.003200, 0.004500, + 0.010000, 0.018000, 0.034000, 0.095500, 0.172500 + ], + [ + 0.050000, 0.002400, 0.000400, 0.002400, 0.003200, 0.004900, + 0.010000, 0.019000, 0.034000, 0.100000, 0.175000 + ] + ] +) AR1 = np.array( - [[11010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [-0.800000, 0.001600, 0.000500, 0.001600, 0.002900, 0.005100, - 0.006500, 0.013000, 0.024000, 0.060000, 0.120000], - [-0.200000, 0.001600, 0.000500, 0.001600, 0.002900, 0.005100, - 0.006500, 0.013000, 0.024000, 0.060000, 0.120000], - [-0.160000, 0.001600, 0.000500, 0.001600, 0.002950, 0.005100, - 0.006500, 0.013000, 0.024000, 0.060000, 0.120000], - [-0.120000, 0.001600, 0.000500, 0.001600, 0.003050, 0.005100, - 0.006500, 0.013000, 0.024000, 0.060000, 0.120000], - [-0.080000, 0.001600, 0.000500, 0.001600, 0.003150, 0.005100, - 0.006500, 0.013000, 0.024000, 0.060000, 0.120000], - [-0.040000, 0.001700, 0.000500, 0.001700, 0.003500, 0.005300, - 0.006500, 0.013500, 0.024500, 0.060000, 0.120000], - [-0.020000, 0.001800, 0.000500, 0.001800, 0.003900, 0.005500, - 0.007500, 0.015000, 0.026000, 0.062000, 0.123500], - [0.000000, 0.001900, 0.000500, 0.001900, 0.004250, 0.006000, - 0.009500, 0.016500, 0.027500, 0.064500, 0.127500], - [0.020000, 0.002200, 0.000500, 0.002200, 0.004500, 0.006900, - 0.011500, 0.019000, 0.030000, 0.067000, 0.132500], - [0.040000, 0.002600, 0.000500, 0.002600, 0.004650, 0.008400, - 0.014000, 0.023000, 0.034000, 0.071000, 0.138000], - [0.050000, 0.003000, 0.000500, 0.003000, 0.004750, 0.009300, 0.016000, 0.026000, 0.037500, 0.074000, 0.141000]]) + [ + [ + 11010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + -0.800000, 0.001600, 0.000500, 0.001600, 0.002900, 0.005100, + 0.006500, 0.013000, 0.024000, 0.060000, 0.120000, + ], + [ + -0.200000, 0.001600, 0.000500, 0.001600, 0.002900, 0.005100, + 0.006500, 0.013000, 0.024000, 0.060000, 0.120000, + ], + [ + -0.160000, 0.001600, 0.000500, 0.001600, 0.002950, 0.005100, + 0.006500, 0.013000, 0.024000, 0.060000, 0.120000, + ], + [ + -0.120000, 0.001600, 0.000500, 0.001600, 0.003050, 0.005100, + 0.006500, 0.013000, 0.024000, 0.060000, 0.120000, + ], + [ + -0.080000, 0.001600, 0.000500, 0.001600, 0.003150, 0.005100, + 0.006500, 0.013000, 0.024000, 0.060000, 0.120000, + ], + [ + -0.040000, 0.001700, 0.000500, 0.001700, 0.003500, 0.005300, + 0.006500, 0.013500, 0.024500, 0.060000, 0.120000, + ], + [ + -0.020000, 0.001800, 0.000500, 0.001800, 0.003900, 0.005500, + 0.007500, 0.015000, 0.026000, 0.062000, 0.123500, + ], + [ + 0.000000, 0.001900, 0.000500, 0.001900, 0.004250, 0.006000, + 0.009500, 0.016500, 0.027500, 0.064500, 0.127500, + ], + [ + 0.020000, 0.002200, 0.000500, 0.002200, 0.004500, 0.006900, + 0.011500, 0.019000, 0.030000, 0.067000, 0.132500, + ], + [ + 0.040000, 0.002600, 0.000500, 0.002600, 0.004650, 0.008400, + 0.014000, 0.023000, 0.034000, 0.071000, 0.138000, + ], + [ + 0.050000, 0.003000, 0.000500, 0.003000, 0.004750, 0.009300, + 0.016000, 0.026000, 0.037500, 0.074000, 0.141000, + ], + ] +) AR2 = np.array( - [[11010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [-0.800000, 0.001500, 0.000500, 0.001500, 0.002800, 0.004700, - 0.007500, 0.011000, 0.018000, 0.035000, 0.073000], - [-0.200000, 0.001500, 0.000500, 0.001500, 0.002800, 0.004700, - 0.007500, 0.011000, 0.018000, 0.035000, 0.073000], - [-0.160000, 0.001500, 0.000500, 0.001500, 0.002900, 0.004700, - 0.007500, 0.011000, 0.018000, 0.035000, 0.073000], - [-0.120000, 0.001600, 0.000500, 0.001600, 0.003100, 0.004700, - 0.007500, 0.011000, 0.018000, 0.035000, 0.073000], - [-0.080000, 0.001600, 0.000500, 0.001600, 0.003400, 0.004700, - 0.007500, 0.011000, 0.018000, 0.035000, 0.073000], - [-0.040000, 0.001800, 0.000500, 0.001800, 0.003700, 0.004900, - 0.007500, 0.012000, 0.018500, 0.035000, 0.073000], - [-0.020000, 0.001900, 0.000500, 0.001900, 0.004100, 0.005300, - 0.008700, 0.014000, 0.020500, 0.036500, 0.073500], - [0.000000, 0.002100, 0.000500, 0.002100, 0.004700, 0.006500, - 0.010600, 0.016500, 0.023500, 0.040000, 0.075000], - [0.020000, 0.002200, 0.000600, 0.002600, 0.005700, 0.008400, - 0.014000, 0.019500, 0.028000, 0.046000, 0.078000], - [0.040000, 0.002900, 0.000600, 0.003300, 0.007500, 0.011000, - 0.017000, 0.024500, 0.032500, 0.055000, 0.084000], - [0.050000, 0.003700, 0.000700, 0.003700, 0.008800, 0.013500, 0.021000, 0.029000, 0.037000, 0.060000, 0.090000]]) + [ + [ + 11010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + -0.800000, 0.001500, 0.000500, 0.001500, 0.002800, 0.004700, + 0.007500, 0.011000, 0.018000, 0.035000, 0.073000, + ], + [ + -0.200000, 0.001500, 0.000500, 0.001500, 0.002800, 0.004700, + 0.007500, 0.011000, 0.018000, 0.035000, 0.073000, + ], + [ + -0.160000, 0.001500, 0.000500, 0.001500, 0.002900, 0.004700, + 0.007500, 0.011000, 0.018000, 0.035000, 0.073000, + ], + [ + -0.120000, 0.001600, 0.000500, 0.001600, 0.003100, 0.004700, + 0.007500, 0.011000, 0.018000, 0.035000, 0.073000, + ], + [ + -0.080000, 0.001600, 0.000500, 0.001600, 0.003400, 0.004700, + 0.007500, 0.011000, 0.018000, 0.035000, 0.073000, + ], + [ + -0.040000, 0.001800, 0.000500, 0.001800, 0.003700, 0.004900, + 0.007500, 0.012000, 0.018500, 0.035000, 0.073000, + ], + [ + -0.020000, 0.001900, 0.000500, 0.001900, 0.004100, 0.005300, + 0.008700, 0.014000, 0.020500, 0.036500, 0.073500, + ], + [ + 0.000000, 0.002100, 0.000500, 0.002100, 0.004700, 0.006500, + 0.010600, 0.016500, 0.023500, 0.040000, 0.075000, + ], + [ + 0.020000, 0.002200, 0.000600, 0.002600, 0.005700, 0.008400, + 0.014000, 0.019500, 0.028000, 0.046000, 0.078000, + ], + [ + 0.040000, 0.002900, 0.000600, 0.003300, 0.007500, 0.011000, + 0.017000, 0.024500, 0.032500, 0.055000, 0.084000, + ], + [ + 0.050000, 0.003700, 0.000700, 0.003700, 0.008800, 0.013500, + 0.021000, 0.029000, 0.037000, 0.060000, 0.090000, + ], + ] +) AR4 = np.array( - [[11010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [-0.800000, 0.001100, 0.000400, 0.001100, 0.002800, 0.003400, - 0.005500, 0.008000, 0.011500, 0.020000, 0.036000], - [-0.200000, 0.001100, 0.000400, 0.001100, 0.002800, 0.003400, - 0.005500, 0.008000, 0.011500, 0.020000, 0.036000], - [-0.160000, 0.001100, 0.000400, 0.001100, 0.002800, 0.003450, - 0.005500, 0.008000, 0.011500, 0.020000, 0.036000], - [-0.120000, 0.001200, 0.000400, 0.001200, 0.002850, 0.003550, - 0.005500, 0.008000, 0.011500, 0.020000, 0.036000], - [-0.080000, 0.001300, 0.000400, 0.001300, 0.002900, 0.003650, - 0.005500, 0.008000, 0.011500, 0.020000, 0.036000], - [-0.040000, 0.001400, 0.000400, 0.001400, 0.003050, 0.003900, - 0.005500, 0.008000, 0.011500, 0.020000, 0.036000], - [-0.020000, 0.001600, 0.000400, 0.001600, 0.003200, 0.004100, - 0.005800, 0.008100, 0.012300, 0.021000, 0.037000], - [0.000000, 0.001900, 0.000400, 0.001900, 0.003550, 0.004600, - 0.007500, 0.011200, 0.015800, 0.026000, 0.040000], - [0.020000, 0.002400, 0.000500, 0.002400, 0.004500, 0.006000, - 0.010000, 0.014000, 0.019500, 0.031000, 0.046000], - [0.040000, 0.003200, 0.000600, 0.003500, 0.006800, 0.012200, - 0.018000, 0.024000, 0.030000, 0.043000, 0.056000], - [0.050000, 0.004400, 0.000600, 0.004400, 0.011300, 0.018100, 0.024000, 0.031000, 0.038000, 0.051000, 0.064000]]) + [ + [ + 11010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + -0.800000, 0.001100, 0.000400, 0.001100, 0.002800, 0.003400, + 0.005500, 0.008000, 0.011500, 0.020000, 0.036000, + ], + [ + -0.200000, 0.001100, 0.000400, 0.001100, 0.002800, 0.003400, + 0.005500, 0.008000, 0.011500, 0.020000, 0.036000, + ], + [ + -0.160000, 0.001100, 0.000400, 0.001100, 0.002800, 0.003450, + 0.005500, 0.008000, 0.011500, 0.020000, 0.036000, + ], + [ + -0.120000, 0.001200, 0.000400, 0.001200, 0.002850, 0.003550, + 0.005500, 0.008000, 0.011500, 0.020000, 0.036000, + ], + [ + -0.080000, 0.001300, 0.000400, 0.001300, 0.002900, 0.003650, + 0.005500, 0.008000, 0.011500, 0.020000, 0.036000, + ], + [ + -0.040000, 0.001400, 0.000400, 0.001400, 0.003050, 0.003900, + 0.005500, 0.008000, 0.011500, 0.020000, 0.036000, + ], + [ + -0.020000, 0.001600, 0.000400, 0.001600, 0.003200, 0.004100, + 0.005800, 0.008100, 0.012300, 0.021000, 0.037000, + ], + [ + 0.000000, 0.001900, 0.000400, 0.001900, 0.003550, 0.004600, + 0.007500, 0.011200, 0.015800, 0.026000, 0.040000, + ], + [ + 0.020000, 0.002400, 0.000500, 0.002400, 0.004500, 0.006000, + 0.010000, 0.014000, 0.019500, 0.031000, 0.046000, + ], + [ + 0.040000, 0.003200, 0.000600, 0.003500, 0.006800, 0.012200, + 0.018000, 0.024000, 0.030000, 0.043000, 0.056000, + ], + [ + 0.050000, 0.004400, 0.000600, 0.004400, 0.011300, 0.018100, + 0.024000, 0.031000, 0.038000, 0.051000, 0.064000, + ], + ] +) AR6 = np.array( - [[11009, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000], - [-0.800000, 0.000850, 0.000200, 0.000850, 0.002000, - 0.002700, 0.004100, 0.005800, 0.007100, 0.010700], - [-0.200000, 0.000850, 0.000200, 0.000850, 0.002000, - 0.002700, 0.004100, 0.005800, 0.007100, 0.010700], - [-0.160000, 0.000890, 0.000200, 0.000890, 0.002000, - 0.002700, 0.004100, 0.005800, 0.007100, 0.010700], - [-0.120000, 0.000960, 0.000200, 0.000960, 0.002000, - 0.002700, 0.004100, 0.005800, 0.007100, 0.010700], - [-0.080000, 0.001080, 0.000200, 0.001080, 0.002000, - 0.002700, 0.004100, 0.005800, 0.007100, 0.010700], - [-0.040000, 0.001200, 0.000260, 0.001200, 0.002000, - 0.002700, 0.004100, 0.005800, 0.007100, 0.011700], - [-0.020000, 0.001300, 0.000300, 0.001300, 0.002000, - 0.002700, 0.004100, 0.005800, 0.007700, 0.016700], - [0.000000, 0.001480, 0.000340, 0.001480, 0.002300, - 0.002900, 0.004300, 0.006100, 0.011200, 0.024000], - [0.020000, 0.001850, 0.000370, 0.001850, 0.003200, - 0.004500, 0.007200, 0.013000, 0.018500, 0.039500], - [0.040000, 0.002900, 0.000450, 0.002900, 0.007000, - 0.010500, 0.014500, 0.024000, 0.033000, 0.054500], - [0.050000, 0.003900, 0.000520, 0.003900, 0.011500, 0.016000, 0.027000, 0.037000, 0.047000, 0.068000]]) + [ + [ + 11009, -0.400000, -0.300000, -0.200000, -0.100000, + -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, + ], + [ + -0.800000, 0.000850, 0.000200, 0.000850, 0.002000, + 0.002700, 0.004100, 0.005800, 0.007100, 0.010700, + ], + [ + -0.200000, 0.000850, 0.000200, 0.000850, 0.002000, + 0.002700, 0.004100, 0.005800, 0.007100, 0.010700, + ], + [ + -0.160000, 0.000890, 0.000200, 0.000890, 0.002000, + 0.002700, 0.004100, 0.005800, 0.007100, 0.010700, + ], + [ + -0.120000, 0.000960, 0.000200, 0.000960, 0.002000, + 0.002700, 0.004100, 0.005800, 0.007100, 0.010700, + ], + [ + -0.080000, 0.001080, 0.000200, 0.001080, 0.002000, + 0.002700, 0.004100, 0.005800, 0.007100, 0.010700, + ], + [ + -0.040000, 0.001200, 0.000260, 0.001200, 0.002000, + 0.002700, 0.004100, 0.005800, 0.007100, 0.011700, + ], + [ + -0.020000, 0.001300, 0.000300, 0.001300, 0.002000, + 0.002700, 0.004100, 0.005800, 0.007700, 0.016700, + ], + [ + 0.000000, 0.001480, 0.000340, 0.001480, 0.002300, + 0.002900, 0.004300, 0.006100, 0.011200, 0.024000, + ], + [ + 0.020000, 0.001850, 0.000370, 0.001850, 0.003200, + 0.004500, 0.007200, 0.013000, 0.018500, 0.039500, + ], + [ + 0.040000, 0.002900, 0.000450, 0.002900, 0.007000, + 0.010500, 0.014500, 0.024000, 0.033000, 0.054500, + ], + [ + 0.050000, 0.003900, 0.000520, 0.003900, 0.011500, + 0.016000, 0.027000, 0.037000, 0.047000, 0.068000, + ], + ] +) ARS07 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.001500, 0.000000, 0.001500, 0.004500, 0.008000, - 0.013500, 0.020000, 0.036000, 0.085000, 0.165000], - [0.100000, 0.001700, 0.000000, 0.001700, 0.004500, 0.009000, - 0.015000, 0.023500, 0.041500, 0.091000, 0.200000], - [0.150000, 0.001800, 0.000000, 0.001800, 0.004700, 0.010500, - 0.017000, 0.026500, 0.048000, 0.100000, 0.230000], - [0.200000, 0.002000, 0.000000, 0.002000, 0.005000, 0.012000, - 0.019000, 0.030000, 0.055000, 0.112000, 0.260000], - [0.300000, 0.003000, 0.000000, 0.003000, 0.006000, 0.015500, - 0.024000, 0.039500, 0.072000, 0.145000, 0.320000], - [0.500000, 0.004000, 0.000000, 0.004000, 0.008300, 0.022500, - 0.036000, 0.067500, 0.112000, 0.210000, 0.440000], - [0.700000, 0.004000, 0.000500, 0.004000, 0.012000, 0.029500, - 0.055000, 0.090000, 0.146000, 0.273000, 0.550000], - [0.900000, 0.003600, 0.000700, 0.003600, 0.016000, 0.036500, - 0.065000, 0.110000, 0.174000, 0.330000, 0.630000], - [1.100000, 0.003400, 0.000800, 0.003400, 0.020000, 0.042500, 0.074000, 0.130000, 0.200000, 0.380000, 0.700000]]) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.001500, 0.000000, 0.001500, 0.004500, 0.008000, + 0.013500, 0.020000, 0.036000, 0.085000, 0.165000, + ], + [ + 0.100000, 0.001700, 0.000000, 0.001700, 0.004500, 0.009000, + 0.015000, 0.023500, 0.041500, 0.091000, 0.200000, + ], + [ + 0.150000, 0.001800, 0.000000, 0.001800, 0.004700, 0.010500, + 0.017000, 0.026500, 0.048000, 0.100000, 0.230000, + ], + [ + 0.200000, 0.002000, 0.000000, 0.002000, 0.005000, 0.012000, + 0.019000, 0.030000, 0.055000, 0.112000, 0.260000, + ], + [ + 0.300000, 0.003000, 0.000000, 0.003000, 0.006000, 0.015500, + 0.024000, 0.039500, 0.072000, 0.145000, 0.320000, + ], + [ + 0.500000, 0.004000, 0.000000, 0.004000, 0.008300, 0.022500, + 0.036000, 0.067500, 0.112000, 0.210000, 0.440000, + ], + [ + 0.700000, 0.004000, 0.000500, 0.004000, 0.012000, 0.029500, + 0.055000, 0.090000, 0.146000, 0.273000, 0.550000, + ], + [ + 0.900000, 0.003600, 0.000700, 0.003600, 0.016000, 0.036500, + 0.065000, 0.110000, 0.174000, 0.330000, 0.630000, + ], + [ + 1.100000, 0.003400, 0.000800, 0.003400, 0.020000, 0.042500, + 0.074000, 0.130000, 0.200000, 0.380000, 0.700000, + ], + ] +) ARS08 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.000000, 0.001000, 0.002000, 0.004000, 0.005000, - 0.010000, 0.015000, 0.025000, 0.080000, 0.140000], - [0.100000, 0.000000, 0.001000, 0.002500, 0.005000, 0.007500, - 0.014000, 0.018000, 0.029000, 0.086000, 0.158000], - [0.150000, 0.000000, 0.001000, 0.003000, 0.006200, 0.009000, - 0.017000, 0.026000, 0.037000, 0.094000, 0.171000], - [0.200000, 0.000000, 0.001000, 0.003500, 0.007500, 0.011500, - 0.020000, 0.032000, 0.051000, 0.103000, 0.185000], - [0.300000, 0.000000, 0.001000, 0.004000, 0.009000, 0.016000, - 0.027500, 0.045000, 0.072000, 0.130000, 0.236000], - [0.500000, 0.000000, 0.001000, 0.005000, 0.013000, 0.026500, - 0.044000, 0.069000, 0.106000, 0.190000, 0.335000], - [0.700000, 0.000000, 0.001000, 0.006000, 0.016000, 0.035000, - 0.059000, 0.092000, 0.143000, 0.245000, 0.420000], - [0.900000, 0.000000, 0.001000, 0.006500, 0.021000, 0.043000, - 0.071000, 0.113000, 0.175000, 0.290000, 0.480000], - [1.100000, 0.000000, 0.001000, 0.007000, 0.026000, 0.051000, 0.080000, 0.135000, 0.200000, 0.320000, 0.520000]]) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.000000, 0.001000, 0.002000, 0.004000, 0.005000, + 0.010000, 0.015000, 0.025000, 0.080000, 0.140000, + ], + [ + 0.100000, 0.000000, 0.001000, 0.002500, 0.005000, 0.007500, + 0.014000, 0.018000, 0.029000, 0.086000, 0.158000, + ], + [ + 0.150000, 0.000000, 0.001000, 0.003000, 0.006200, 0.009000, + 0.017000, 0.026000, 0.037000, 0.094000, 0.171000, + ], + [ + 0.200000, 0.000000, 0.001000, 0.003500, 0.007500, 0.011500, + 0.020000, 0.032000, 0.051000, 0.103000, 0.185000, + ], + [ + 0.300000, 0.000000, 0.001000, 0.004000, 0.009000, 0.016000, + 0.027500, 0.045000, 0.072000, 0.130000, 0.236000, + ], + [ + 0.500000, 0.000000, 0.001000, 0.005000, 0.013000, 0.026500, + 0.044000, 0.069000, 0.106000, 0.190000, 0.335000, + ], + [ + 0.700000, 0.000000, 0.001000, 0.006000, 0.016000, 0.035000, + 0.059000, 0.092000, 0.143000, 0.245000, 0.420000, + ], + [ + 0.900000, 0.000000, 0.001000, 0.006500, 0.021000, 0.043000, + 0.071000, 0.113000, 0.175000, 0.290000, 0.480000, + ], + [ + 1.100000, 0.000000, 0.001000, 0.007000, 0.026000, 0.051000, + 0.080000, 0.135000, 0.200000, 0.320000, 0.520000, + ], + ] +) ARS10 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.000000, 0.000100, 0.003000, 0.006000, 0.008000, - 0.015500, 0.020000, 0.027000, 0.072000, 0.126000], - [0.100000, 0.000000, 0.000200, 0.003700, 0.007500, 0.011500, - 0.018700, 0.026000, 0.036500, 0.076000, 0.135000], - [0.150000, 0.000000, 0.000300, 0.004200, 0.009500, 0.013500, - 0.022000, 0.033000, 0.045000, 0.082000, 0.148000], - [0.200000, 0.000000, 0.000400, 0.004800, 0.011500, 0.016000, - 0.025500, 0.040000, 0.053000, 0.089000, 0.160000], - [0.300000, 0.000000, 0.000600, 0.006000, 0.014000, 0.020500, - 0.032500, 0.051000, 0.067000, 0.110000, 0.203000], - [0.500000, 0.000000, 0.001000, 0.007500, 0.018500, 0.031000, - 0.048000, 0.070000, 0.098000, 0.160000, 0.280000], - [0.700000, 0.000000, 0.001400, 0.009000, 0.024500, 0.042500, - 0.065000, 0.090000, 0.127000, 0.204000, 0.350000], - [0.900000, 0.000000, 0.001800, 0.011000, 0.031500, 0.054000, - 0.082000, 0.112000, 0.152000, 0.240000, 0.405000], - [1.100000, 0.000000, 0.002200, 0.012300, 0.038000, 0.065500, 0.100000, 0.136000, 0.176000, 0.270000, 0.450000]]) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.000000, 0.000100, 0.003000, 0.006000, 0.008000, + 0.015500, 0.020000, 0.027000, 0.072000, 0.126000, + ], + [ + 0.100000, 0.000000, 0.000200, 0.003700, 0.007500, 0.011500, + 0.018700, 0.026000, 0.036500, 0.076000, 0.135000, + ], + [ + 0.150000, 0.000000, 0.000300, 0.004200, 0.009500, 0.013500, + 0.022000, 0.033000, 0.045000, 0.082000, 0.148000, + ], + [ + 0.200000, 0.000000, 0.000400, 0.004800, 0.011500, 0.016000, + 0.025500, 0.040000, 0.053000, 0.089000, 0.160000, + ], + [ + 0.300000, 0.000000, 0.000600, 0.006000, 0.014000, 0.020500, + 0.032500, 0.051000, 0.067000, 0.110000, 0.203000, + ], + [ + 0.500000, 0.000000, 0.001000, 0.007500, 0.018500, 0.031000, + 0.048000, 0.070000, 0.098000, 0.160000, 0.280000, + ], + [ + 0.700000, 0.000000, 0.001400, 0.009000, 0.024500, 0.042500, + 0.065000, 0.090000, 0.127000, 0.204000, 0.350000, + ], + [ + 0.900000, 0.000000, 0.001800, 0.011000, 0.031500, 0.054000, + 0.082000, 0.112000, 0.152000, 0.240000, 0.405000, + ], + [ + 1.100000, 0.000000, 0.002200, 0.012300, 0.038000, 0.065500, + 0.100000, 0.136000, 0.176000, 0.270000, 0.450000, + ], + ] +) ARS12 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.000000, 0.000100, 0.003000, 0.008000, 0.011000, - 0.017500, 0.027500, 0.039000, 0.064000, 0.115000], - [0.100000, 0.000000, 0.000200, 0.004000, 0.010000, 0.014500, - 0.022000, 0.032500, 0.045000, 0.068000, 0.120000], - [0.150000, 0.000000, 0.000300, 0.005000, 0.012000, 0.016500, - 0.025000, 0.037500, 0.050000, 0.072000, 0.129000], - [0.200000, 0.000000, 0.000400, 0.006000, 0.013500, 0.018000, - 0.032000, 0.043500, 0.055000, 0.077000, 0.138000], - [0.300000, 0.000000, 0.000600, 0.007000, 0.016500, 0.022500, - 0.035500, 0.049500, 0.065000, 0.094000, 0.165000], - [0.500000, 0.000000, 0.001000, 0.009000, 0.023500, 0.033000, - 0.048000, 0.067000, 0.088000, 0.140000, 0.250000], - [0.700000, 0.000000, 0.001400, 0.015000, 0.030000, 0.046500, - 0.065000, 0.085500, 0.114000, 0.190000, 0.350000], - [0.900000, 0.000000, 0.001800, 0.014000, 0.037500, 0.058000, - 0.083000, 0.108500, 0.140000, 0.240000, 0.460000], - [1.100000, 0.000000, 0.002200, 0.017000, 0.045000, 0.073000, 0.101000, 0.133500, 0.165000, 0.300000, 0.600000]]) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.000000, 0.000100, 0.003000, 0.008000, 0.011000, + 0.017500, 0.027500, 0.039000, 0.064000, 0.115000, + ], + [ + 0.100000, 0.000000, 0.000200, 0.004000, 0.010000, 0.014500, + 0.022000, 0.032500, 0.045000, 0.068000, 0.120000, + ], + [ + 0.150000, 0.000000, 0.000300, 0.005000, 0.012000, 0.016500, + 0.025000, 0.037500, 0.050000, 0.072000, 0.129000, + ], + [ + 0.200000, 0.000000, 0.000400, 0.006000, 0.013500, 0.018000, + 0.032000, 0.043500, 0.055000, 0.077000, 0.138000, + ], + [ + 0.300000, 0.000000, 0.000600, 0.007000, 0.016500, 0.022500, + 0.035500, 0.049500, 0.065000, 0.094000, 0.165000, + ], + [ + 0.500000, 0.000000, 0.001000, 0.009000, 0.023500, 0.033000, + 0.048000, 0.067000, 0.088000, 0.140000, 0.250000, + ], + [ + 0.700000, 0.000000, 0.001400, 0.015000, 0.030000, 0.046500, + 0.065000, 0.085500, 0.114000, 0.190000, 0.350000, + ], + [ + 0.900000, 0.000000, 0.001800, 0.014000, 0.037500, 0.058000, + 0.083000, 0.108500, 0.140000, 0.240000, 0.460000, + ], + [ + 1.100000, 0.000000, 0.002200, 0.017000, 0.045000, 0.073000, + 0.101000, 0.133500, 0.165000, 0.300000, 0.600000, + ], + ] +) ARS14 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.000000, 0.001000, 0.003000, 0.010000, 0.014000, - 0.020000, 0.028000, 0.035500, 0.060000, 0.100000], - [0.100000, 0.000000, 0.001000, 0.004000, 0.011500, 0.014500, - 0.021500, 0.030000, 0.038000, 0.062000, 0.105000], - [0.150000, 0.000000, 0.001100, 0.005000, 0.013000, 0.018000, - 0.025000, 0.033000, 0.044000, 0.066000, 0.111000], - [0.200000, 0.000000, 0.001200, 0.006000, 0.014000, 0.019000, - 0.025000, 0.035000, 0.048000, 0.071000, 0.122000], - [0.300000, 0.000000, 0.001400, 0.007000, 0.017000, 0.023500, - 0.033500, 0.044000, 0.056000, 0.082000, 0.145000], - [0.500000, 0.000000, 0.001700, 0.009500, 0.023500, 0.034500, - 0.048000, 0.063000, 0.081000, 0.116000, 0.235000], - [0.700000, 0.000000, 0.002000, 0.012500, 0.031500, 0.047500, - 0.065000, 0.085000, 0.114000, 0.180000, 0.350000], - [0.900000, 0.000000, 0.002200, 0.015000, 0.039500, 0.059000, - 0.081000, 0.108000, 0.135000, 0.240000, 0.450000], - [1.100000, 0.000000, 0.002500, 0.018500, 0.047500, 0.074000, 0.101000, 0.129000, 0.155000, 0.300000, 0.550000]]) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.000000, 0.001000, 0.003000, 0.010000, 0.014000, + 0.020000, 0.028000, 0.035500, 0.060000, 0.100000, + ], + [ + 0.100000, 0.000000, 0.001000, 0.004000, 0.011500, 0.014500, + 0.021500, 0.030000, 0.038000, 0.062000, 0.105000, + ], + [ + 0.150000, 0.000000, 0.001100, 0.005000, 0.013000, 0.018000, + 0.025000, 0.033000, 0.044000, 0.066000, 0.111000, + ], + [ + 0.200000, 0.000000, 0.001200, 0.006000, 0.014000, 0.019000, + 0.025000, 0.035000, 0.048000, 0.071000, 0.122000, + ], + [ + 0.300000, 0.000000, 0.001400, 0.007000, 0.017000, 0.023500, + 0.033500, 0.044000, 0.056000, 0.082000, 0.145000, + ], + [ + 0.500000, 0.000000, 0.001700, 0.009500, 0.023500, 0.034500, + 0.048000, 0.063000, 0.081000, 0.116000, 0.235000, + ], + [ + 0.700000, 0.000000, 0.002000, 0.012500, 0.031500, 0.047500, + 0.065000, 0.085000, 0.114000, 0.180000, 0.350000, + ], + [ + 0.900000, 0.000000, 0.002200, 0.015000, 0.039500, 0.059000, + 0.081000, 0.108000, 0.135000, 0.240000, 0.450000, + ], + [ + 1.100000, 0.000000, 0.002500, 0.018500, 0.047500, 0.074000, + 0.101000, 0.129000, 0.155000, 0.300000, 0.550000, + ], + ] +) ARS16 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.000000, 0.001000, 0.003500, 0.009500, 0.013000, - 0.020000, 0.028000, 0.037000, 0.055000, 0.088000], - [0.100000, 0.000000, 0.001000, 0.004000, 0.012000, 0.016000, - 0.022500, 0.030000, 0.040000, 0.061000, 0.092000], - [0.150000, 0.000000, 0.001000, 0.005000, 0.013500, 0.018000, - 0.026000, 0.035000, 0.044500, 0.065000, 0.097000], - [0.200000, 0.000000, 0.001000, 0.006000, 0.015000, 0.020000, - 0.029000, 0.039000, 0.048500, 0.072000, 0.104000], - [0.300000, 0.000000, 0.001000, 0.007000, 0.018000, 0.024500, - 0.036000, 0.046000, 0.057500, 0.081000, 0.125000], - [0.500000, 0.000000, 0.001500, 0.009500, 0.024000, 0.035000, - 0.050500, 0.063500, 0.078000, 0.108000, 0.190000], - [0.700000, 0.000000, 0.002000, 0.012500, 0.032000, 0.047000, - 0.064500, 0.087000, 0.108000, 0.170000, 0.280000], - [0.900000, 0.000000, 0.002500, 0.017000, 0.040000, 0.062500, - 0.083000, 0.106000, 0.130000, 0.240000, 0.380000], - [1.100000, 0.000000, 0.003000, 0.022000, 0.048000, 0.076000, 0.102000, 0.129000, 0.154000, 0.300000, 0.490000]]) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.000000, 0.001000, 0.003500, 0.009500, 0.013000, + 0.020000, 0.028000, 0.037000, 0.055000, 0.088000, + ], + [ + 0.100000, 0.000000, 0.001000, 0.004000, 0.012000, 0.016000, + 0.022500, 0.030000, 0.040000, 0.061000, 0.092000, + ], + [ + 0.150000, 0.000000, 0.001000, 0.005000, 0.013500, 0.018000, + 0.026000, 0.035000, 0.044500, 0.065000, 0.097000, + ], + [ + 0.200000, 0.000000, 0.001000, 0.006000, 0.015000, 0.020000, + 0.029000, 0.039000, 0.048500, 0.072000, 0.104000, + ], + [ + 0.300000, 0.000000, 0.001000, 0.007000, 0.018000, 0.024500, + 0.036000, 0.046000, 0.057500, 0.081000, 0.125000, + ], + [ + 0.500000, 0.000000, 0.001500, 0.009500, 0.024000, 0.035000, + 0.050500, 0.063500, 0.078000, 0.108000, 0.190000, + ], + [ + 0.700000, 0.000000, 0.002000, 0.012500, 0.032000, 0.047000, + 0.064500, 0.087000, 0.108000, 0.170000, 0.280000, + ], + [ + 0.900000, 0.000000, 0.002500, 0.017000, 0.040000, 0.062500, + 0.083000, 0.106000, 0.130000, 0.240000, 0.380000, + ], + [ + 1.100000, 0.000000, 0.003000, 0.022000, 0.048000, 0.076000, + 0.102000, 0.129000, 0.154000, 0.300000, 0.490000, + ], + ] +) ARS18 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.000000, 0.000700, 0.003500, 0.011000, 0.014500, - 0.019000, 0.026000, 0.034000, 0.050000, 0.080000], - [0.100000, 0.000000, 0.000800, 0.004200, 0.012000, 0.016500, - 0.024500, 0.031500, 0.040000, 0.060000, 0.082000], - [0.150000, 0.000000, 0.000900, 0.005200, 0.013500, 0.018000, - 0.026500, 0.036500, 0.046500, 0.065500, 0.085000], - [0.200000, 0.000000, 0.001000, 0.006000, 0.015000, 0.020000, - 0.030000, 0.039500, 0.049500, 0.070500, 0.090000], - [0.300000, 0.000000, 0.001200, 0.007000, 0.018000, 0.024500, - 0.035500, 0.046500, 0.058500, 0.079000, 0.105000], - [0.500000, 0.000000, 0.001600, 0.009500, 0.023500, 0.035000, - 0.049000, 0.063500, 0.079500, 0.108000, 0.150000], - [0.700000, 0.000000, 0.002000, 0.012500, 0.031500, 0.047500, - 0.066500, 0.085500, 0.110000, 0.167000, 0.230000], - [0.900000, 0.000000, 0.002500, 0.016400, 0.040000, 0.063000, - 0.086000, 0.108500, 0.131000, 0.232000, 0.330000], - [1.100000, 0.000000, 0.003000, 0.022000, 0.048500, 0.076500, 0.104000, 0.130000, 0.155000, 0.302000, 0.440000]]) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.000000, 0.000700, 0.003500, 0.011000, 0.014500, + 0.019000, 0.026000, 0.034000, 0.050000, 0.080000, + ], + [ + 0.100000, 0.000000, 0.000800, 0.004200, 0.012000, 0.016500, + 0.024500, 0.031500, 0.040000, 0.060000, 0.082000, + ], + [ + 0.150000, 0.000000, 0.000900, 0.005200, 0.013500, 0.018000, + 0.026500, 0.036500, 0.046500, 0.065500, 0.085000, + ], + [ + 0.200000, 0.000000, 0.001000, 0.006000, 0.015000, 0.020000, + 0.030000, 0.039500, 0.049500, 0.070500, 0.090000, + ], + [ + 0.300000, 0.000000, 0.001200, 0.007000, 0.018000, 0.024500, + 0.035500, 0.046500, 0.058500, 0.079000, 0.105000, + ], + [ + 0.500000, 0.000000, 0.001600, 0.009500, 0.023500, 0.035000, + 0.049000, 0.063500, 0.079500, 0.108000, 0.150000, + ], + [ + 0.700000, 0.000000, 0.002000, 0.012500, 0.031500, 0.047500, + 0.066500, 0.085500, 0.110000, 0.167000, 0.230000, + ], + [ + 0.900000, 0.000000, 0.002500, 0.016400, 0.040000, 0.063000, + 0.086000, 0.108500, 0.131000, 0.232000, 0.330000, + ], + [ + 1.100000, 0.000000, 0.003000, 0.022000, 0.048500, 0.076500, + 0.104000, 0.130000, 0.155000, 0.302000, 0.440000, + ], + ] +) ARS20 = np.array( - [[9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, 0.000000, 0.050000, 0.100000, 0.200000, 0.300000], - [0.050000, 0.000000, 0.000700, 0.003000, 0.011000, 0.014000, - 0.020000, 0.027000, 0.034000, 0.051000, 0.068000], - [0.100000, 0.000000, 0.000800, 0.004500, 0.012000, 0.016000, - 0.024000, 0.030000, 0.039000, 0.059000, 0.080500], - [0.150000, 0.000000, 0.000900, 0.005000, 0.013500, 0.018000, - 0.026000, 0.035000, 0.046000, 0.065000, 0.087000], - [0.200000, 0.000000, 0.001000, 0.005700, 0.015000, 0.020000, - 0.030000, 0.039000, 0.049000, 0.069500, 0.091500], - [0.300000, 0.000000, 0.001200, 0.007000, 0.018000, 0.024500, - 0.033000, 0.044000, 0.054000, 0.076000, 0.100000], - [0.500000, 0.000000, 0.001600, 0.009500, 0.024000, 0.035000, - 0.047000, 0.058000, 0.069000, 0.093000, 0.134000], - [0.700000, 0.000000, 0.002000, 0.012600, 0.031500, 0.048000, - 0.066000, 0.084000, 0.105000, 0.146000, 0.200000], - [0.900000, 0.000000, 0.002800, 0.016000, 0.040000, 0.061500, - 0.084000, 0.108000, 0.131000, 0.210000, 0.290000], - [1.100000, 0.000000, 0.003600, 0.022000, 0.048000, 0.075000, 0.102000, 0.128000, 0.155000, 0.269000, 0.375000]]) - -AR05table = InterpND(method='lagrange2', points=( - AR05[1:, 0], AR05[0, 1:]), values=AR05[1:, 1:], extrapolate=True) -AR1table = InterpND(method='lagrange2', points=( - AR1[1:, 0], AR1[0, 1:]), values=AR1[1:, 1:], extrapolate=True) -AR2table = InterpND(method='lagrange2', points=( - AR2[1:, 0], AR2[0, 1:]), values=AR2[1:, 1:], extrapolate=True) -AR4table = InterpND(method='lagrange2', points=( - AR4[1:, 0], AR4[0, 1:]), values=AR4[1:, 1:], extrapolate=True) -AR6table = InterpND(method='lagrange2', points=( - AR6[1:, 0], AR6[0, 1:]), values=AR6[1:, 1:], extrapolate=True) -ARS07table = InterpND(method='lagrange2', points=( - ARS07[1:, 0], ARS07[0, 1:]), values=ARS07[1:, 1:], extrapolate=True) -ARS08table = InterpND(method='lagrange2', points=( - ARS08[1:, 0], ARS08[0, 1:]), values=ARS08[1:, 1:], extrapolate=True) -ARS10table = InterpND(method='lagrange2', points=( - ARS10[1:, 0], ARS10[0, 1:]), values=ARS10[1:, 1:], extrapolate=True) -ARS12table = InterpND(method='lagrange2', points=( - ARS12[1:, 0], ARS12[0, 1:]), values=ARS12[1:, 1:], extrapolate=True) -ARS14table = InterpND(method='lagrange2', points=( - ARS14[1:, 0], ARS14[0, 1:]), values=ARS14[1:, 1:], extrapolate=True) -ARS16table = InterpND(method='lagrange2', points=( - ARS16[1:, 0], ARS16[0, 1:]), values=ARS16[1:, 1:], extrapolate=True) -ARS18table = InterpND(method='lagrange2', points=( - ARS18[1:, 0], ARS18[0, 1:]), values=ARS18[1:, 1:], extrapolate=True) -ARS20table = InterpND(method='lagrange2', points=( - ARS20[1:, 0], ARS20[0, 1:]), values=ARS20[1:, 1:], extrapolate=True) + [ + [ + 9010, -0.400000, -0.300000, -0.200000, -0.100000, -0.050000, + 0.000000, 0.050000, 0.100000, 0.200000, 0.300000, + ], + [ + 0.050000, 0.000000, 0.000700, 0.003000, 0.011000, 0.014000, + 0.020000, 0.027000, 0.034000, 0.051000, 0.068000, + ], + [ + 0.100000, 0.000000, 0.000800, 0.004500, 0.012000, 0.016000, + 0.024000, 0.030000, 0.039000, 0.059000, 0.080500, + ], + [ + 0.150000, 0.000000, 0.000900, 0.005000, 0.013500, 0.018000, + 0.026000, 0.035000, 0.046000, 0.065000, 0.087000, + ], + [ + 0.200000, 0.000000, 0.001000, 0.005700, 0.015000, 0.020000, + 0.030000, 0.039000, 0.049000, 0.069500, 0.091500, + ], + [ + 0.300000, 0.000000, 0.001200, 0.007000, 0.018000, 0.024500, + 0.033000, 0.044000, 0.054000, 0.076000, 0.100000, + ], + [ + 0.500000, 0.000000, 0.001600, 0.009500, 0.024000, 0.035000, + 0.047000, 0.058000, 0.069000, 0.093000, 0.134000, + ], + [ + 0.700000, 0.000000, 0.002000, 0.012600, 0.031500, 0.048000, + 0.066000, 0.084000, 0.105000, 0.146000, 0.200000, + ], + [ + 0.900000, 0.000000, 0.002800, 0.016000, 0.040000, 0.061500, + 0.084000, 0.108000, 0.131000, 0.210000, 0.290000, + ], + [ + 1.100000, 0.000000, 0.003600, 0.022000, 0.048000, 0.075000, + 0.102000, 0.128000, 0.155000, 0.269000, 0.375000, + ], + ] +) +# fmt: on + +AR05table = InterpND( + method='lagrange2', points=(AR05[1:, 0], AR05[0, 1:]), values=AR05[1:, 1:], extrapolate=True +) +AR1table = InterpND( + method='lagrange2', points=(AR1[1:, 0], AR1[0, 1:]), values=AR1[1:, 1:], extrapolate=True +) +AR2table = InterpND( + method='lagrange2', points=(AR2[1:, 0], AR2[0, 1:]), values=AR2[1:, 1:], extrapolate=True +) +AR4table = InterpND( + method='lagrange2', points=(AR4[1:, 0], AR4[0, 1:]), values=AR4[1:, 1:], extrapolate=True +) +AR6table = InterpND( + method='lagrange2', points=(AR6[1:, 0], AR6[0, 1:]), values=AR6[1:, 1:], extrapolate=True +) +ARS07table = InterpND( + method='lagrange2', points=(ARS07[1:, 0], ARS07[0, 1:]), values=ARS07[1:, 1:], extrapolate=True +) +ARS08table = InterpND( + method='lagrange2', points=(ARS08[1:, 0], ARS08[0, 1:]), values=ARS08[1:, 1:], extrapolate=True +) +ARS10table = InterpND( + method='lagrange2', points=(ARS10[1:, 0], ARS10[0, 1:]), values=ARS10[1:, 1:], extrapolate=True +) +ARS12table = InterpND( + method='lagrange2', points=(ARS12[1:, 0], ARS12[0, 1:]), values=ARS12[1:, 1:], extrapolate=True +) +ARS14table = InterpND( + method='lagrange2', points=(ARS14[1:, 0], ARS14[0, 1:]), values=ARS14[1:, 1:], extrapolate=True +) +ARS16table = InterpND( + method='lagrange2', points=(ARS16[1:, 0], ARS16[0, 1:]), values=ARS16[1:, 1:], extrapolate=True +) +ARS18table = InterpND( + method='lagrange2', points=(ARS18[1:, 0], ARS18[0, 1:]), values=ARS18[1:, 1:], extrapolate=True +) +ARS20table = InterpND( + method='lagrange2', points=(ARS20[1:, 0], ARS20[0, 1:]), values=ARS20[1:, 1:], extrapolate=True +) diff --git a/aviary/subsystems/aerodynamics/flops_based/mux_component.py b/aviary/subsystems/aerodynamics/flops_based/mux_component.py index bd0ce2f443..81e2d44404 100644 --- a/aviary/subsystems/aerodynamics/flops_based/mux_component.py +++ b/aviary/subsystems/aerodynamics/flops_based/mux_component.py @@ -1,8 +1,7 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, get_units +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, get_units from aviary.variable_info.variables import Aircraft @@ -23,81 +22,91 @@ def __init__(self, **kwargs): super().__init__(**kwargs) def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Aircraft.VerticalTail.NUM_TAILS) def setup(self): nc = 2 - aviary_options: AviaryValues = self.options['aviary_options'] # Wing (Always 1) - add_aviary_input(self, Aircraft.Wing.WETTED_AREA, 1.0) - add_aviary_input(self, Aircraft.Wing.FINENESS, 1.0) - add_aviary_input(self, Aircraft.Wing.CHARACTERISTIC_LENGTH, 1.0) - add_aviary_input(self, Aircraft.Wing.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.Wing.LAMINAR_FLOW_LOWER, 0.0) + add_aviary_input(self, Aircraft.Wing.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.Wing.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input(self, Aircraft.Wing.LAMINAR_FLOW_UPPER, units='unitless') + add_aviary_input(self, Aircraft.Wing.LAMINAR_FLOW_LOWER, units='unitless') # Horizontal Tail (Always 1) - add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, 1.0) - add_aviary_input(self, Aircraft.HorizontalTail.FINENESS, 1.0) - add_aviary_input(self, Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 1.0) - add_aviary_input(self, Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER, 0.0) + add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input(self, Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER, units='unitless') + + num = self.options[Aircraft.VerticalTail.NUM_TAILS] - zero_count = (0, None) - # Vertical Tail - num, _ = aviary_options.get_item(Aircraft.VerticalTail.NUM_TAILS, zero_count) self.num_tails = num if num > 0: - add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA, 1.0) - add_aviary_input(self, Aircraft.VerticalTail.FINENESS, 1.0) - add_aviary_input(self, Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, 1.0) - add_aviary_input(self, Aircraft.VerticalTail.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.LAMINAR_FLOW_LOWER, 0.0) + add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input(self, Aircraft.VerticalTail.LAMINAR_FLOW_UPPER, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.LAMINAR_FLOW_LOWER, units='unitless') nc += num # Fuselage - num, _ = aviary_options.get_item(Aircraft.Fuselage.NUM_FUSELAGES, zero_count) + num = self.options[Aircraft.Fuselage.NUM_FUSELAGES] self.num_fuselages = num if num > 0: - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, 1.0) - add_aviary_input(self, Aircraft.Fuselage.FINENESS, 1.0) - add_aviary_input(self, Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 1.0) - add_aviary_input(self, Aircraft.Fuselage.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.Fuselage.LAMINAR_FLOW_LOWER, 0.0) + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Fuselage.FINENESS, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.LAMINAR_FLOW_UPPER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.LAMINAR_FLOW_LOWER, units='unitless') nc += num - num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + num_engine_models = len(num_engines) self.num_nacelles = int(sum(num_engines)) + if self.num_nacelles > 0: - add_aviary_input(self, Aircraft.Nacelle.WETTED_AREA, - np.zeros(len(num_engines))) - add_aviary_input(self, Aircraft.Nacelle.FINENESS, - np.zeros(len(num_engines))) - add_aviary_input(self, Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - np.zeros(len(num_engines))) - add_aviary_input(self, Aircraft.Nacelle.LAMINAR_FLOW_UPPER, - np.zeros(len(num_engines))) - add_aviary_input(self, Aircraft.Nacelle.LAMINAR_FLOW_LOWER, - np.zeros(len(num_engines))) + add_aviary_input( + self, Aircraft.Nacelle.WETTED_AREA, np.zeros(num_engine_models), units='ft**2' + ) + add_aviary_input( + self, Aircraft.Nacelle.FINENESS, np.zeros(num_engine_models), units='unitless' + ) + add_aviary_input( + self, + Aircraft.Nacelle.CHARACTERISTIC_LENGTH, + np.zeros(num_engine_models), + units='ft', + ) + add_aviary_input( + self, + Aircraft.Nacelle.LAMINAR_FLOW_UPPER, + np.zeros(num_engine_models), + units='unitless', + ) + add_aviary_input( + self, + Aircraft.Nacelle.LAMINAR_FLOW_LOWER, + np.zeros(num_engine_models), + units='unitless', + ) nc += self.num_nacelles + self.add_output('wetted_areas', shape=nc, units=get_units(Aircraft.Wing.WETTED_AREA)) + self.add_output('fineness_ratios', shape=nc, units=get_units(Aircraft.Wing.FINENESS)) self.add_output( - 'wetted_areas', shape=nc, - units=get_units(Aircraft.Wing.WETTED_AREA)) - self.add_output( - 'fineness_ratios', shape=nc, - units=get_units(Aircraft.Wing.FINENESS)) + 'characteristic_lengths', shape=nc, units=get_units(Aircraft.Wing.CHARACTERISTIC_LENGTH) + ) self.add_output( - 'characteristic_lengths', shape=nc, - units=get_units(Aircraft.Wing.CHARACTERISTIC_LENGTH)) + 'laminar_fractions_upper', shape=nc, units=get_units(Aircraft.Wing.LAMINAR_FLOW_UPPER) + ) self.add_output( - 'laminar_fractions_upper', shape=nc, - units=get_units(Aircraft.Wing.LAMINAR_FLOW_UPPER)) - self.add_output( - 'laminar_fractions_lower', shape=nc, - units=get_units(Aircraft.Wing.LAMINAR_FLOW_LOWER)) + 'laminar_fractions_lower', shape=nc, units=get_units(Aircraft.Wing.LAMINAR_FLOW_LOWER) + ) def setup_partials(self): rows = np.zeros(1) @@ -105,38 +114,62 @@ def setup_partials(self): # Wing self.declare_partials( - 'wetted_areas', Aircraft.Wing.WETTED_AREA, - rows=rows, cols=cols, val=1.0) + 'wetted_areas', Aircraft.Wing.WETTED_AREA, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'fineness_ratios', Aircraft.Wing.FINENESS, - rows=rows, cols=cols, val=1.0) + 'fineness_ratios', Aircraft.Wing.FINENESS, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'characteristic_lengths', Aircraft.Wing.CHARACTERISTIC_LENGTH, - rows=rows, cols=cols, val=1.0) + 'characteristic_lengths', + Aircraft.Wing.CHARACTERISTIC_LENGTH, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_upper', Aircraft.Wing.LAMINAR_FLOW_UPPER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_upper', + Aircraft.Wing.LAMINAR_FLOW_UPPER, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_lower', Aircraft.Wing.LAMINAR_FLOW_LOWER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_lower', + Aircraft.Wing.LAMINAR_FLOW_LOWER, + rows=rows, + cols=cols, + val=1.0, + ) # Horizontal Tail rows = np.ones(1) self.declare_partials( - 'wetted_areas', Aircraft.HorizontalTail.WETTED_AREA, - rows=rows, cols=cols, val=1.0) + 'wetted_areas', Aircraft.HorizontalTail.WETTED_AREA, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'fineness_ratios', Aircraft.HorizontalTail.FINENESS, - rows=rows, cols=cols, val=1.0) + 'fineness_ratios', Aircraft.HorizontalTail.FINENESS, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'characteristic_lengths', Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, - rows=rows, cols=cols, val=1.0) + 'characteristic_lengths', + Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_upper', Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_upper', + Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_lower', Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_lower', + Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER, + rows=rows, + cols=cols, + val=1.0, + ) ic = 2 @@ -145,20 +178,32 @@ def setup_partials(self): rows = ic + np.arange(self.num_tails) cols = np.zeros(self.num_tails) self.declare_partials( - 'wetted_areas', Aircraft.VerticalTail.WETTED_AREA, - rows=rows, cols=cols, val=1.0) + 'wetted_areas', Aircraft.VerticalTail.WETTED_AREA, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'fineness_ratios', Aircraft.VerticalTail.FINENESS, - rows=rows, cols=cols, val=1.0) + 'fineness_ratios', Aircraft.VerticalTail.FINENESS, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'characteristic_lengths', Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, - rows=rows, cols=cols, val=1.0) + 'characteristic_lengths', + Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_upper', Aircraft.VerticalTail.LAMINAR_FLOW_UPPER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_upper', + Aircraft.VerticalTail.LAMINAR_FLOW_UPPER, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_lower', Aircraft.VerticalTail.LAMINAR_FLOW_LOWER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_lower', + Aircraft.VerticalTail.LAMINAR_FLOW_LOWER, + rows=rows, + cols=cols, + val=1.0, + ) ic += self.num_tails # Fuselage @@ -166,109 +211,128 @@ def setup_partials(self): rows = ic + np.arange(self.num_fuselages) cols = np.zeros(self.num_fuselages) self.declare_partials( - 'wetted_areas', Aircraft.Fuselage.WETTED_AREA, - rows=rows, cols=cols, val=1.0) + 'wetted_areas', Aircraft.Fuselage.WETTED_AREA, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'fineness_ratios', Aircraft.Fuselage.FINENESS, - rows=rows, cols=cols, val=1.0) + 'fineness_ratios', Aircraft.Fuselage.FINENESS, rows=rows, cols=cols, val=1.0 + ) self.declare_partials( - 'characteristic_lengths', Aircraft.Fuselage.CHARACTERISTIC_LENGTH, - rows=rows, cols=cols, val=1.0) + 'characteristic_lengths', + Aircraft.Fuselage.CHARACTERISTIC_LENGTH, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_upper', Aircraft.Fuselage.LAMINAR_FLOW_UPPER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_upper', + Aircraft.Fuselage.LAMINAR_FLOW_UPPER, + rows=rows, + cols=cols, + val=1.0, + ) self.declare_partials( - 'laminar_fractions_lower', Aircraft.Fuselage.LAMINAR_FLOW_LOWER, - rows=rows, cols=cols, val=1.0) + 'laminar_fractions_lower', + Aircraft.Fuselage.LAMINAR_FLOW_LOWER, + rows=rows, + cols=cols, + val=1.0, + ) ic += self.num_fuselages # Nacelle if self.num_nacelles > 0: # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engines = self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + rows = ic + np.arange(self.num_nacelles) - cols = [item for sublist in [[i]*j for i, - j in enumerate(num_engines)] for item in sublist] + cols = [ + item for sublist in [[i] * j for i, j in enumerate(num_engines)] for item in sublist + ] self.declare_partials( - 'wetted_areas', Aircraft.Nacelle.WETTED_AREA, - rows=rows, cols=cols, val=1.0 + 'wetted_areas', Aircraft.Nacelle.WETTED_AREA, rows=rows, cols=cols, val=1.0 ) self.declare_partials( - 'fineness_ratios', Aircraft.Nacelle.FINENESS, - rows=rows, cols=cols, val=1.0 + 'fineness_ratios', Aircraft.Nacelle.FINENESS, rows=rows, cols=cols, val=1.0 ) self.declare_partials( - 'characteristic_lengths', Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - rows=rows, cols=cols, val=1.0 + 'characteristic_lengths', + Aircraft.Nacelle.CHARACTERISTIC_LENGTH, + rows=rows, + cols=cols, + val=1.0, ) self.declare_partials( - 'laminar_fractions_upper', Aircraft.Nacelle.LAMINAR_FLOW_UPPER, - rows=rows, cols=cols, val=1.0 + 'laminar_fractions_upper', + Aircraft.Nacelle.LAMINAR_FLOW_UPPER, + rows=rows, + cols=cols, + val=1.0, ) self.declare_partials( - 'laminar_fractions_lower', Aircraft.Nacelle.LAMINAR_FLOW_LOWER, - rows=rows, cols=cols, val=1.0 + 'laminar_fractions_lower', + Aircraft.Nacelle.LAMINAR_FLOW_LOWER, + rows=rows, + cols=cols, + val=1.0, ) def compute(self, inputs, outputs): # Wing - outputs['wetted_areas'][0] = inputs[ - Aircraft.Wing.WETTED_AREA][0] - outputs['fineness_ratios'][0] = inputs[ - Aircraft.Wing.FINENESS][0] - outputs['characteristic_lengths'][0] = inputs[ - Aircraft.Wing.CHARACTERISTIC_LENGTH][0] - outputs['laminar_fractions_upper'][0] = inputs[ - Aircraft.Wing.LAMINAR_FLOW_UPPER][0] - outputs['laminar_fractions_lower'][0] = inputs[ - Aircraft.Wing.LAMINAR_FLOW_LOWER][0] + outputs['wetted_areas'][0] = inputs[Aircraft.Wing.WETTED_AREA][0] + outputs['fineness_ratios'][0] = inputs[Aircraft.Wing.FINENESS][0] + outputs['characteristic_lengths'][0] = inputs[Aircraft.Wing.CHARACTERISTIC_LENGTH][0] + outputs['laminar_fractions_upper'][0] = inputs[Aircraft.Wing.LAMINAR_FLOW_UPPER][0] + outputs['laminar_fractions_lower'][0] = inputs[Aircraft.Wing.LAMINAR_FLOW_LOWER][0] # Horizontal Tail - outputs['wetted_areas'][1] = inputs[ - Aircraft.HorizontalTail.WETTED_AREA][0] - outputs['fineness_ratios'][1] = inputs[ - Aircraft.HorizontalTail.FINENESS][0] + outputs['wetted_areas'][1] = inputs[Aircraft.HorizontalTail.WETTED_AREA][0] + outputs['fineness_ratios'][1] = inputs[Aircraft.HorizontalTail.FINENESS][0] outputs['characteristic_lengths'][1] = inputs[ - Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH][0] - outputs['laminar_fractions_upper'][1] = inputs[ - Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER][0] - outputs['laminar_fractions_lower'][1] = inputs[ - Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER][0] + Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH + ][0] + outputs['laminar_fractions_upper'][1] = inputs[Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER][ + 0 + ] + outputs['laminar_fractions_lower'][1] = inputs[Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER][ + 0 + ] ic = 2 # Vertical Tail if self.num_tails > 0: for j in range(self.num_tails): - outputs['wetted_areas'][ic + j] = inputs[ - Aircraft.VerticalTail.WETTED_AREA][0] - outputs['fineness_ratios'][ic + j] = inputs[ - Aircraft.VerticalTail.FINENESS][0] + outputs['wetted_areas'][ic + j] = inputs[Aircraft.VerticalTail.WETTED_AREA][0] + outputs['fineness_ratios'][ic + j] = inputs[Aircraft.VerticalTail.FINENESS][0] outputs['characteristic_lengths'][ic + j] = inputs[ - Aircraft.VerticalTail.CHARACTERISTIC_LENGTH][0] + Aircraft.VerticalTail.CHARACTERISTIC_LENGTH + ][0] outputs['laminar_fractions_upper'][ic + j] = inputs[ - Aircraft.VerticalTail.LAMINAR_FLOW_UPPER][0] + Aircraft.VerticalTail.LAMINAR_FLOW_UPPER + ][0] outputs['laminar_fractions_lower'][ic + j] = inputs[ - Aircraft.VerticalTail.LAMINAR_FLOW_LOWER][0] + Aircraft.VerticalTail.LAMINAR_FLOW_LOWER + ][0] ic += self.num_tails # Fuselage if self.num_fuselages > 0: for j in range(self.num_fuselages): outputs['wetted_areas'][ic + j] = inputs[Aircraft.Fuselage.WETTED_AREA][0] - outputs['fineness_ratios'][ic + - j] = inputs[Aircraft.Fuselage.FINENESS][0] + outputs['fineness_ratios'][ic + j] = inputs[Aircraft.Fuselage.FINENESS][0] outputs['characteristic_lengths'][ic + j] = inputs[ - Aircraft.Fuselage.CHARACTERISTIC_LENGTH][0] + Aircraft.Fuselage.CHARACTERISTIC_LENGTH + ][0] outputs['laminar_fractions_upper'][ic + j] = inputs[ - Aircraft.Fuselage.LAMINAR_FLOW_UPPER][0] + Aircraft.Fuselage.LAMINAR_FLOW_UPPER + ][0] outputs['laminar_fractions_lower'][ic + j] = inputs[ - Aircraft.Fuselage.LAMINAR_FLOW_LOWER][0] + Aircraft.Fuselage.LAMINAR_FLOW_LOWER + ][0] ic += self.num_fuselages # Nacelle - num_engines = self.options['aviary_options'].get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] wetted_areas = inputs[Aircraft.Nacelle.WETTED_AREA] fineness = inputs[Aircraft.Nacelle.FINENESS] diff --git a/aviary/subsystems/aerodynamics/flops_based/skin_friction.py b/aviary/subsystems/aerodynamics/flops_based/skin_friction.py index 957ad53ac6..502378cf3f 100644 --- a/aviary/subsystems/aerodynamics/flops_based/skin_friction.py +++ b/aviary/subsystems/aerodynamics/flops_based/skin_friction.py @@ -1,7 +1,7 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic @@ -11,7 +11,7 @@ class SkinFriction(om.ImplicitComponent): in FLOPS AERSCL. The fixed-point iteration scheme has been replaced with Newton's method, which can - converge the equations for multiple mach numbers and characteristic lengths + converge the equations for multiple Mach numbers and characteristic lengths simultaneously. """ @@ -22,40 +22,36 @@ def __init__(self, **kwargs): self.TAW = 1.0 self.sea_level_pressure = 14.6959 * 144 # psi -> psf - self.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, - atol=1e-12, rtol=1e-12) + self.nonlinear_solver = om.NewtonSolver(solve_subsystems=False, atol=1e-12, rtol=1e-12) self.linear_solver = om.DirectSolver() self.nonlinear_solver.options['iprint'] = -1 self.linear_solver.options['iprint'] = -1 def initialize(self): - """ - Declare options. - """ + """Declare options.""" self.options.declare( - 'num_nodes', types=int, default=1, - desc='The number of points at which the cross product is computed.') - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'num_nodes', + types=int, + default=1, + desc='The number of points at which the cross product is computed.', + ) + + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Aircraft.VerticalTail.NUM_TAILS) def setup(self): nn = self.options['num_nodes'] - aviary_options: AviaryValues = self.options['aviary_options'] - zero_count = (0, None) - num_tails, _ = aviary_options.get_item( - Aircraft.VerticalTail.NUM_TAILS, zero_count) - num_fuselages, _ = aviary_options.get_item( - Aircraft.Fuselage.NUM_FUSELAGES, zero_count) - # TODO does not used vectorized heterogeneous engines. Temp using single engine - num_engines, _ = aviary_options.get_item( - Aircraft.Engine.NUM_ENGINES, zero_count) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + num_fuselages = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + num_tails = self.options[Aircraft.VerticalTail.NUM_TAILS] + self.nc = nc = 2 + num_tails + num_fuselages + int(sum(num_engines)) # Simulation inputs - self.add_input(Dynamic.Mission.TEMPERATURE, np.ones(nn), units='degR') - self.add_input(Dynamic.Mission.STATIC_PRESSURE, np.ones(nn), units='lbf/ft**2') - self.add_input(Dynamic.Mission.MACH, np.ones(nn), units='unitless') + add_aviary_input(self, Dynamic.Atmosphere.TEMPERATURE, shape=nn, units='degR') + add_aviary_input(self, Dynamic.Atmosphere.STATIC_PRESSURE, shape=nn, units='lbf/ft**2') + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') # Aero subsystem inputs self.add_input('characteristic_lengths', np.ones(nc), units='ft') @@ -66,51 +62,79 @@ def setup(self): self.add_output('wall_temp', np.ones((nn, nc)), units='degR') def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] nc = self.nc n = nn * nc row_col = np.arange(n) self.declare_partials('Re', 'Re', rows=row_col, cols=row_col, val=1.0) self.declare_partials( - 'skin_friction_coeff', 'skin_friction_coeff', - rows=row_col, cols=row_col, val=1.0) + 'skin_friction_coeff', 'skin_friction_coeff', rows=row_col, cols=row_col, val=1.0 + ) + self.declare_partials('cf_iter', ['wall_temp', 'cf_iter'], rows=row_col, cols=row_col) + self.declare_partials('wall_temp', ['wall_temp', 'cf_iter'], rows=row_col, cols=row_col) self.declare_partials( - 'cf_iter', ['wall_temp', 'cf_iter'], rows=row_col, cols=row_col) - self.declare_partials( - 'wall_temp', ['wall_temp', 'cf_iter'], rows=row_col, cols=row_col) - self.declare_partials( - 'skin_friction_coeff', ['wall_temp', 'cf_iter'], rows=row_col, cols=row_col) + 'skin_friction_coeff', ['wall_temp', 'cf_iter'], rows=row_col, cols=row_col + ) col = np.arange(nn) cols = np.repeat(col, nc) self.declare_partials( - 'cf_iter', [Dynamic.Mission.TEMPERATURE, Dynamic.Mission.STATIC_PRESSURE, Dynamic.Mission.MACH], rows=row_col, cols=cols) + 'cf_iter', + [ + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + ], + rows=row_col, + cols=cols, + ) self.declare_partials( - 'wall_temp', [Dynamic.Mission.TEMPERATURE, Dynamic.Mission.STATIC_PRESSURE, Dynamic.Mission.MACH], rows=row_col, cols=cols) + 'wall_temp', + [ + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + ], + rows=row_col, + cols=cols, + ) self.declare_partials( - 'Re', [Dynamic.Mission.TEMPERATURE, Dynamic.Mission.STATIC_PRESSURE, Dynamic.Mission.MACH], rows=row_col, cols=cols) + 'Re', + [ + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + ], + rows=row_col, + cols=cols, + ) self.declare_partials( - 'skin_friction_coeff', [Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, Dynamic.Mission.MACH], - rows=row_col, cols=cols) + 'skin_friction_coeff', + [ + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + ], + rows=row_col, + cols=cols, + ) col = np.arange(nc) cols = np.tile(col, nn) self.declare_partials('Re', 'characteristic_lengths', rows=row_col, cols=cols) - self.declare_partials( - 'cf_iter', 'characteristic_lengths', rows=row_col, cols=cols) + self.declare_partials('cf_iter', 'characteristic_lengths', rows=row_col, cols=cols) def guess_nonlinear(self, inputs, outputs, resids): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] nc = self.nc rankine, pressure, mach, length = inputs.values() Pratio = pressure / self.sea_level_pressure kelvin = rankine / 1.8 - RE = 1.479301E9 * Pratio * (kelvin + 110.4) / kelvin ** 2 + RE = 1.479301e9 * Pratio * (kelvin + 110.4) / kelvin**2 # REYNOLDS NUMBER reynolds_num = np.einsum('i,i,j->ij', RE, mach, length) @@ -133,42 +157,44 @@ def apply_nonlinear(self, inputs, outputs, residuals): Pratio = pressure / self.sea_level_pressure kelvin = T / 1.8 - RE = 1.479301E9 * Pratio * (kelvin + 110.4) / kelvin ** 2 + RE = 1.479301e9 * Pratio * (kelvin + 110.4) / kelvin**2 # SUTHERLAND'S CONSTANT IS 198.72 DEG R FROM 1962 ON suth_const = T + 198.72 E = 0.80 # COMBINED CONSTANT INCLUDING 1/RHO - combined_const = 4.593153E-6 * E * suth_const / (RE * mach * T ** 1.5) + combined_const = 4.593153e-6 * E * suth_const / (RE * mach * T**1.5) # REYNOLDS NUMBER reynolds_num = np.einsum('i,i,j->ij', RE, mach, length) residuals['Re'] = outputs['Re'] - reynolds_num # WALL TEMPERATURE RATIO - wall_temp_ratio = 1.0 + 0.45 * (np.einsum('ij,i->ij', wall_temp, 1.0 / T) - 1.0) + wall_temp_ratio = 1.0 + 0.45 * (np.einsum('ij,i->ij', wall_temp, 1.0 / T) - 1.0) fact = 0.035 * mach * mach for i in range(nc): wall_temp_ratio[:, i] += fact CFL = cf / (1.0 + 3.59 * np.sqrt(cf) * wall_temp_ratio) - prod = np.einsum('j,jk->jk', combined_const, wall_temp ** 3) - residuals['wall_temp'] = ( - self.TAW / (1.0 + prod / CFL) + wall_temp) * 0.5 - wall_temp + prod = np.einsum('j,jk->jk', combined_const, wall_temp**3) + residuals['wall_temp'] = (self.TAW / (1.0 + prod / CFL) + wall_temp) * 0.5 - wall_temp RP = ( - reynolds_num * (np.einsum('ij,i->ij', wall_temp_ratio, T) + 198.72) - / np.einsum('i,ij->ij', suth_const, wall_temp_ratio ** 2.5)) + reynolds_num + * (np.einsum('ij,i->ij', wall_temp_ratio, T) + 198.72) + / np.einsum('i,ij->ij', suth_const, wall_temp_ratio**2.5) + ) residuals['cf_iter'] = (0.242 * self.CONLOG / np.log(RP * cf)) ** 2 - cf - residuals['skin_friction_coeff'] = \ + residuals['skin_friction_coeff'] = ( outputs['skin_friction_coeff'] - outputs['cf_iter'] / wall_temp_ratio + ) def linearize(self, inputs, outputs, partials): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] nc = self.nc T, pressure, mach, length = inputs.values() @@ -177,11 +203,10 @@ def linearize(self, inputs, outputs, partials): Pratio = pressure / self.sea_level_pressure kelvin = T / 1.8 - RE = 1.479301E9 * Pratio * (kelvin + 110.4) / kelvin ** 2 + RE = 1.479301e9 * Pratio * (kelvin + 110.4) / kelvin**2 - dRE_dp = 1.479301E9 * (kelvin + 110.4) / (self.sea_level_pressure * kelvin ** 2) - dRE_dT = -1.479301E9 / 1.8 * ( - Pratio * (1.0 / kelvin ** 2 + 2.0 * 110.4 / kelvin ** 3)) + dRE_dp = 1.479301e9 * (kelvin + 110.4) / (self.sea_level_pressure * kelvin**2) + dRE_dT = -1.479301e9 / 1.8 * (Pratio * (1.0 / kelvin**2 + 2.0 * 110.4 / kelvin**3)) reynolds_num = np.einsum('i,i,j->ij', RE, mach, length) dreyn_dp = np.einsum('i,i,j->ij', dRE_dp, mach, length) @@ -189,67 +214,67 @@ def linearize(self, inputs, outputs, partials): dreyn_dmach = np.einsum('i,j->ij', RE, length) dreyn_dlen = np.tile(RE * mach, nc).reshape((nc, nn)).T - partials['Re', Dynamic.Mission.STATIC_PRESSURE] = -dreyn_dp.ravel() - partials['Re', Dynamic.Mission.TEMPERATURE] = -dreyn_dT.ravel() - partials['Re', Dynamic.Mission.MACH] = -dreyn_dmach.ravel() + partials['Re', Dynamic.Atmosphere.STATIC_PRESSURE] = -dreyn_dp.ravel() + partials['Re', Dynamic.Atmosphere.TEMPERATURE] = -dreyn_dT.ravel() + partials['Re', Dynamic.Atmosphere.MACH] = -dreyn_dmach.ravel() partials['Re', 'characteristic_lengths'] = -dreyn_dlen.ravel() suth_const = T + 198.72 E = 0.80 - combined_const = 4.593153E-6 * E * suth_const / (RE * mach * T ** 1.5) - dcomb_dRE = -4.593153E-6 * E * suth_const / (RE * RE * mach * T ** 1.5) - dcomb_dmach = -4.593153E-6 * E * suth_const / (RE * mach * mach * T ** 1.5) - dcomb_dT = 4.593153E-6 * E * (1.0 / T ** 1.5 - 1.5 * suth_const / T ** 2.5) / ( - RE * mach) + dcomb_dRE * dRE_dT + combined_const = 4.593153e-6 * E * suth_const / (RE * mach * T**1.5) + dcomb_dRE = -4.593153e-6 * E * suth_const / (RE * RE * mach * T**1.5) + dcomb_dmach = -4.593153e-6 * E * suth_const / (RE * mach * mach * T**1.5) + dcomb_dT = ( + 4.593153e-6 * E * (1.0 / T**1.5 - 1.5 * suth_const / T**2.5) / (RE * mach) + + dcomb_dRE * dRE_dT + ) dcomb_dp = dcomb_dRE * dRE_dp - wall_temp_ratio = 1.0 + 0.45 * (np.einsum('ij,i->ij', wall_temp, 1.0 / T) - 1.0) + wall_temp_ratio = 1.0 + 0.45 * (np.einsum('ij,i->ij', wall_temp, 1.0 / T) - 1.0) fact = 0.035 * mach * mach for i in range(nc): wall_temp_ratio[:, i] += fact dwtr_dmach = 0.07 * mach - dwtr_dT = -0.45 * np.einsum('ij,i->ij', wall_temp, 1.0 / T ** 2) + dwtr_dT = -0.45 * np.einsum('ij,i->ij', wall_temp, 1.0 / T**2) dwtr_dwt = 0.45 / T den = 1.0 + 3.59 * np.sqrt(cf) * wall_temp_ratio CFL = cf / den - dCFL_dcf = \ - 1.0 / den - cf * 3.59 * wall_temp_ratio * 0.5 / (np.sqrt(cf) * den ** 2) - dCFL_dwtr = - cf * 3.59 * np.sqrt(cf) / den ** 2 + dCFL_dcf = 1.0 / den - cf * 3.59 * wall_temp_ratio * 0.5 / (np.sqrt(cf) * den**2) + dCFL_dwtr = -cf * 3.59 * np.sqrt(cf) / den**2 dCFL_dmach = np.einsum('ij,i->ij', dCFL_dwtr, dwtr_dmach) dCFL_dT = dCFL_dwtr * dwtr_dT dCFL_dwt = np.einsum('ij,i->ij', dCFL_dwtr, dwtr_dwt) - term = np.einsum('i,ij->ij', combined_const, wall_temp ** 3) + term = np.einsum('i,ij->ij', combined_const, wall_temp**3) den = 1.0 + term / CFL - dreswt_dcomb = -0.5 * self.TAW * wall_temp ** 3 / (CFL * den ** 2) + dreswt_dcomb = -0.5 * self.TAW * wall_temp**3 / (CFL * den**2) dreswt_dCFL = 0.5 * self.TAW * term / (CFL * den) ** 2 - dreswt_dwt = ( - -0.5 - 1.5 * self.TAW * np.einsum('i,ij->ij', combined_const, wall_temp ** 2) - / (CFL * den ** 2)) - - partials['wall_temp', Dynamic.Mission.STATIC_PRESSURE] = ( - np.einsum('ij,i->ij', dreswt_dcomb, dcomb_dp)).ravel() - partials['wall_temp', Dynamic.Mission.TEMPERATURE] = ( - np.einsum('ij,i->ij', dreswt_dcomb, dcomb_dT) - + dreswt_dCFL * dCFL_dT).ravel() - partials['wall_temp', Dynamic.Mission.MACH] = ( - np.einsum('ij,i->ij', dreswt_dcomb, dcomb_dmach) - + dreswt_dCFL * dCFL_dmach).ravel() - partials['wall_temp', 'wall_temp'] = ( - dreswt_dCFL * dCFL_dwt + dreswt_dwt).ravel() + dreswt_dwt = -0.5 - 1.5 * self.TAW * np.einsum('i,ij->ij', combined_const, wall_temp**2) / ( + CFL * den**2 + ) + + partials['wall_temp', Dynamic.Atmosphere.STATIC_PRESSURE] = ( + np.einsum('ij,i->ij', dreswt_dcomb, dcomb_dp) + ).ravel() + partials['wall_temp', Dynamic.Atmosphere.TEMPERATURE] = ( + np.einsum('ij,i->ij', dreswt_dcomb, dcomb_dT) + dreswt_dCFL * dCFL_dT + ).ravel() + partials['wall_temp', Dynamic.Atmosphere.MACH] = ( + np.einsum('ij,i->ij', dreswt_dcomb, dcomb_dmach) + dreswt_dCFL * dCFL_dmach + ).ravel() + partials['wall_temp', 'wall_temp'] = (dreswt_dCFL * dCFL_dwt + dreswt_dwt).ravel() partials['wall_temp', 'cf_iter'] = (dreswt_dCFL * dCFL_dcf).ravel() - den = 1.0 / np.einsum('i,ij->ij', suth_const, wall_temp_ratio ** 2.5) + den = 1.0 / np.einsum('i,ij->ij', suth_const, wall_temp_ratio**2.5) num = np.einsum('ij,i->ij', wall_temp_ratio, T) + 198.72 RP = reynolds_num * num * den dRP_dreyn = num * den term = np.einsum('i,ij->ij', T, 1.0 * den) dRP_dwtr = reynolds_num * ( - term - num * 2.5 - * np.einsum('i,ij->ij', suth_const, wall_temp_ratio ** 1.5) * den ** 2) - dRP_dT = reynolds_num * ( - wall_temp_ratio * den - num * wall_temp_ratio ** 2.5 * den ** 2) + term - num * 2.5 * np.einsum('i,ij->ij', suth_const, wall_temp_ratio**1.5) * den**2 + ) + dRP_dT = reynolds_num * (wall_temp_ratio * den - num * wall_temp_ratio**2.5 * den**2) dRP_dp = dRP_dreyn * dreyn_dp dRP_dT = dRP_dreyn * dreyn_dT + dRP_dwtr * dwtr_dT + dRP_dT dRP_dmach = dRP_dreyn * dreyn_dmach + np.einsum('ij,i->ij', dRP_dwtr, dwtr_dmach) @@ -260,20 +285,22 @@ def linearize(self, inputs, outputs, partials): drescf_dRP = -2.0 * fact / (RP * np.log(RP * cf) ** 3) drescf_dcf = -2.0 * fact / (cf * np.log(RP * cf) ** 3) - 1.0 - partials['cf_iter', Dynamic.Mission.STATIC_PRESSURE] = ( - drescf_dRP * dRP_dp).ravel() - partials['cf_iter', Dynamic.Mission.TEMPERATURE] = (drescf_dRP * dRP_dT).ravel() - partials['cf_iter', Dynamic.Mission.MACH] = (drescf_dRP * dRP_dmach).ravel() + partials['cf_iter', Dynamic.Atmosphere.STATIC_PRESSURE] = (drescf_dRP * dRP_dp).ravel() + partials['cf_iter', Dynamic.Atmosphere.TEMPERATURE] = (drescf_dRP * dRP_dT).ravel() + partials['cf_iter', Dynamic.Atmosphere.MACH] = (drescf_dRP * dRP_dmach).ravel() partials['cf_iter', 'characteristic_lengths'] = (drescf_dRP * dRP_dlen).ravel() partials['cf_iter', 'wall_temp'] = (drescf_dRP * dRP_dwt).ravel() partials['cf_iter', 'cf_iter'] = drescf_dcf.ravel() - dskf_dwtr = outputs['cf_iter'] / wall_temp_ratio ** 2 + dskf_dwtr = outputs['cf_iter'] / wall_temp_ratio**2 - partials['skin_friction_coeff', Dynamic.Mission.TEMPERATURE] = ( - dskf_dwtr * dwtr_dT).ravel() - partials['skin_friction_coeff', Dynamic.Mission.MACH] = np.einsum( - 'ij,i->ij', dskf_dwtr, dwtr_dmach).ravel() + partials['skin_friction_coeff', Dynamic.Atmosphere.TEMPERATURE] = ( + dskf_dwtr * dwtr_dT + ).ravel() + partials['skin_friction_coeff', Dynamic.Atmosphere.MACH] = np.einsum( + 'ij,i->ij', dskf_dwtr, dwtr_dmach + ).ravel() partials['skin_friction_coeff', 'wall_temp'] = np.einsum( - 'ij,i->ij', dskf_dwtr, dwtr_dwt).ravel() - partials['skin_friction_coeff', 'cf_iter'] = (- 1.0 / wall_temp_ratio).ravel() + 'ij,i->ij', dskf_dwtr, dwtr_dwt + ).ravel() + partials['skin_friction_coeff', 'cf_iter'] = (-1.0 / wall_temp_ratio).ravel() diff --git a/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py b/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py index c7a9edd0f0..2324ecee40 100644 --- a/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/skin_friction_drag.py @@ -1,8 +1,7 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, get_units +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, get_units from aviary.variable_info.variables import Aircraft @@ -16,34 +15,43 @@ def __init__(self, **kwargs): super().__init__(**kwargs) # Form factor fit coefficients. - self.F = np.array([ - 4.34255, -1.14281, .171203, -.0138334, .621712e-3, .137442e-6, -.145532e-4, - 2.94206, 7.16974, 48.8876, -1403.02, 8598.76, -15834.3, 4.275]) + # fmt: off + self.F = np.array( + [ + 4.34255, -1.14281, 0.171203, -0.0138334, 0.621712e-3, 0.137442e-6, + -0.145532e-4, 2.94206, 7.16974, 48.8876, -1403.02, 8598.76, -15834.3, 4.275, + ] + ) + # fmt: on def initialize(self): - """ - Declare options. - """ + """Declare options.""" self.options.declare( - 'num_nodes', types=int, default=1, - desc='The number of points at which the cross product is computed.') + 'num_nodes', + types=int, + default=1, + desc='The number of points at which the cross product is computed.', + ) + + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Aircraft.VerticalTail.NUM_TAILS) + add_aviary_option(self, Aircraft.Wing.AIRFOIL_TECHNOLOGY) + + # TODO: Bring this into the variable hierarchy. self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - - # TODO: Convert these into aviary_options entries. - self.options.declare( - 'excrescences_drag', default=0.06, - desc='Drag contribution of excrescences as a percentage.') + 'excrescences_drag', + default=0.06, + desc='Drag contribution of excrescences as a percentage.', + ) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] nn = self.options['num_nodes'] - zero_count = (0, None) - nvtail, _ = aviary_options.get_item(Aircraft.VerticalTail.NUM_TAILS, zero_count) - nfuse, _ = aviary_options.get_item(Aircraft.Fuselage.NUM_FUSELAGES, zero_count) - num_engines, _ = aviary_options.get_item(Aircraft.Engine.NUM_ENGINES, zero_count) + nvtail = self.options[Aircraft.VerticalTail.NUM_TAILS] + nfuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + self.nc = nc = 2 + nvtail + nfuse + int(sum(num_engines)) # Computed by other components in drag group. @@ -52,51 +60,69 @@ def setup(self): # These have been assembled from the individually-titled component variables. self.add_input( - 'fineness_ratios', np.ones(nc), + 'fineness_ratios', + np.ones(nc), desc='Vector of component fineness ratios.', - units='unitless') + units='unitless', + ) self.add_input( - 'wetted_areas', np.ones(nc), units=get_units(Aircraft.Wing.AREA), - desc='Vector of component wetted areas.') + 'wetted_areas', + np.ones(nc), + units=get_units(Aircraft.Wing.AREA), + desc='Vector of component wetted areas.', + ) self.add_input( - 'laminar_fractions_upper', np.ones(nc), units=get_units(Aircraft.Wing.LAMINAR_FLOW_UPPER), - desc='Vector of component upper-surface laminar-flow fractions.') + 'laminar_fractions_upper', + np.ones(nc), + units=get_units(Aircraft.Wing.LAMINAR_FLOW_UPPER), + desc='Vector of component upper-surface laminar-flow fractions.', + ) self.add_input( - 'laminar_fractions_lower', np.ones(nc), units=get_units(Aircraft.Wing.LAMINAR_FLOW_LOWER), - desc='Vector of component lower-surface laminar-flow fractions.') + 'laminar_fractions_lower', + np.ones(nc), + units=get_units(Aircraft.Wing.LAMINAR_FLOW_LOWER), + desc='Vector of component lower-surface laminar-flow fractions.', + ) # Aircraft design inputs - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') # Output self.add_output( - 'skin_friction_drag_coeff', np.zeros(nn), units='unitless', - desc='Skin friction drag coefficient.') + 'skin_friction_drag_coeff', + np.zeros(nn), + units='unitless', + desc='Skin friction drag coefficient.', + ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] nc = self.nc n = nn * nc - self.declare_partials( - of='skin_friction_drag_coeff', - wrt=[Aircraft.Wing.AREA]) + self.declare_partials(of='skin_friction_drag_coeff', wrt=[Aircraft.Wing.AREA]) rows = np.repeat(np.arange(nn), nc) cols = np.tile(np.arange(nc), nn) self.declare_partials( of='skin_friction_drag_coeff', - wrt=['fineness_ratios', 'wetted_areas', - 'laminar_fractions_upper', 'laminar_fractions_lower'], rows=rows, cols=cols) + wrt=[ + 'fineness_ratios', + 'wetted_areas', + 'laminar_fractions_upper', + 'laminar_fractions_lower', + ], + rows=rows, + cols=cols, + ) cols = np.arange(n) self.declare_partials( - of='skin_friction_drag_coeff', - wrt=['skin_friction_coeff', 'Re'], rows=rows, cols=cols) + of='skin_friction_drag_coeff', wrt=['skin_friction_coeff', 'Re'], rows=rows, cols=cols + ) def compute(self, inputs, outputs): nc = self.nc - aviary_options: AviaryValues = self.options['aviary_options'] cf = inputs['skin_friction_coeff'] Re = inputs['Re'] @@ -112,8 +138,7 @@ def compute(self, inputs, outputs): if laminar_flow: laminar_upper = _calc_laminar_flow(lam_up) laminar_lower = _calc_laminar_flow(lam_low) - cf = cf - 0.5 * (cf - 1.328 / np.sqrt(Re)) * \ - (laminar_lower + laminar_upper) + cf = cf - 0.5 * (cf - 1.328 / np.sqrt(Re)) * (laminar_lower + laminar_upper) form_factor = np.empty(nc, dtype=cf.dtype) @@ -127,8 +152,9 @@ def compute(self, inputs, outputs): # Horner expansion seem to be out of order (cf. F[5] + fine * F[6]), and the origin # of this equation is not clear. # However, if you swap the terms, you end up with negative skin friction coef. - form_factor[idx_body] = F[0] + fine * \ - (F[1] + fine * (F[2] + fine * (F[3] + fine * (F[4] + fine * (F[5] * fine + F[6]))))) + form_factor[idx_body] = F[0] + fine * ( + F[1] + fine * (F[2] + fine * (F[3] + fine * (F[4] + fine * (F[5] * fine + F[6])))) + ) idx_max = np.where(fineness >= 20.0) form_factor[idx_max] = 1.0 @@ -136,16 +162,16 @@ def compute(self, inputs, outputs): # Form factor for surfaces. idx_surf = np.where(fineness <= 0.5)[0] fine = fineness[idx_surf] - airfoil = aviary_options.get_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY) + airfoil = self.options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] - FF1 = 1.0 + fine * (F[7] + fine * (F[8] + fine * - (F[9] + fine * (F[10] + fine * (F[11] + fine * F[12]))))) + FF1 = 1.0 + fine * ( + F[7] + fine * (F[8] + fine * (F[9] + fine * (F[10] + fine * (F[11] + fine * F[12])))) + ) FF2 = 1.0 + fine * self.F[13] form_factor[idx_surf] = FF1 * (2.0 - airfoil) + FF2 * (airfoil - 1.0) - CDF = np.einsum('j,ij,j->i', wetted_area, cf, form_factor) * \ - (1.0 / mission_wing_area) + CDF = np.einsum('j,ij,j->i', wetted_area, cf, form_factor) * (1.0 / mission_wing_area) # Add drag for excrescences. @@ -162,8 +188,7 @@ def compute(self, inputs, outputs): def compute_partials(self, inputs, partials): nc = self.nc - nn = self.options["num_nodes"] - aviary_options: AviaryValues = self.options['aviary_options'] + nn = self.options['num_nodes'] cf = inputs['skin_friction_coeff'] Re = inputs['Re'] @@ -183,7 +208,7 @@ def compute_partials(self, inputs, partials): laminar_lower = _calc_laminar_flow(lam_low) lam_sum = laminar_lower + laminar_upper lam_cf = 1.0 - 0.5 * lam_sum - lam_Re = -0.25 * 1.328 / Re ** 1.5 * lam_sum + lam_Re = -0.25 * 1.328 / Re**1.5 * lam_sum cf = cf - 0.5 * (cf - 1.328 * den) * lam_sum @@ -195,10 +220,13 @@ def compute_partials(self, inputs, partials): # Form factor for bodies. idx_body = np.where(fineness > 0.5)[0] fine = fineness[idx_body] - form_factor[idx_body] = F[0] + fine * \ - (F[1] + fine * (F[2] + fine * (F[3] + fine * (F[4] + fine * (F[5] * fine + F[6]))))) - dform_dfine[idx_body] = F[1] + fine * (2.0 * F[2] + fine * ( - 3.0 * F[3] + fine * (4.0 * F[4] + fine * (6.0 * F[5] * fine + 5.0 * F[6])))) + form_factor[idx_body] = F[0] + fine * ( + F[1] + fine * (F[2] + fine * (F[3] + fine * (F[4] + fine * (F[5] * fine + F[6])))) + ) + dform_dfine[idx_body] = F[1] + fine * ( + 2.0 * F[2] + + fine * (3.0 * F[3] + fine * (4.0 * F[4] + fine * (6.0 * F[5] * fine + 5.0 * F[6]))) + ) # When pinned above max fineness, deriv is zero. idx_max = np.where(fineness >= 20.0) @@ -209,16 +237,16 @@ def compute_partials(self, inputs, partials): idx_surf = np.where(fineness <= 0.5)[0] fine = fineness[idx_surf] - airfoil = aviary_options.get_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY) + airfoil = self.options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] FF1 = 1.0 + fine * ( - F[7] + fine - * (F[8] + fine * (F[9] + fine * (F[10] + fine * (F[11] + fine * F[12]))))) + F[7] + fine * (F[8] + fine * (F[9] + fine * (F[10] + fine * (F[11] + fine * F[12])))) + ) FF2 = 1.0 + fine * self.F[13] dFF1 = F[7] + fine * ( - 2.0 * F[8] + fine * ( - 3.0 * F[9] + fine - * (4.0 * F[10] + fine * (5.0 * F[11] + fine * 6.0 * F[12])))) + 2.0 * F[8] + + fine * (3.0 * F[9] + fine * (4.0 * F[10] + fine * (5.0 * F[11] + fine * 6.0 * F[12]))) + ) dFF2 = self.F[13] form_factor[idx_surf] = FF1 * (2.0 - airfoil) + FF2 * (airfoil - 1.0) @@ -232,8 +260,7 @@ def compute_partials(self, inputs, partials): DCDF_dwet = excr * np.einsum('ij,j->ij', cf, form_factor) * den DCDF_dcf = excr * wetted_area * form_factor * den DCDF_dform = excr * np.einsum('j,ij->ij', wetted_area, cf) * den - DCDF_dmwa = -excr * np.einsum('j,ij,j->i', wetted_area, - cf, form_factor) * den ** 2 + DCDF_dmwa = -excr * np.einsum('j,ij,j->i', wetted_area, cf, form_factor) * den**2 DCDF_dlamup = DCDF_dcf * lam_lam * _calc_laminar_flow_deriv(lam_up) DCDF_dlamlow = DCDF_dcf * lam_lam * _calc_laminar_flow_deriv(lam_low) @@ -242,22 +269,20 @@ def compute_partials(self, inputs, partials): DCDF_dRe = np.einsum('j,ij->ij', DCDF_dcf, lam_Re) DCDF_dcf *= lam_cf - partials['skin_friction_drag_coeff', 'skin_friction_coeff'] = np.tile( - DCDF_dcf, nn) + partials['skin_friction_drag_coeff', 'skin_friction_coeff'] = np.tile(DCDF_dcf, nn) if laminar_flow: partials['skin_friction_drag_coeff', 'Re'] = DCDF_dRe.ravel() partials['skin_friction_drag_coeff', 'fineness_ratios'] = np.einsum( - 'ij,j->ij', DCDF_dform, dform_dfine).ravel() + 'ij,j->ij', DCDF_dform, dform_dfine + ).ravel() partials['skin_friction_drag_coeff', 'wetted_areas'] = DCDF_dwet.ravel() - partials['skin_friction_drag_coeff', - 'laminar_fractions_upper'] = DCDF_dlamup.ravel() + partials['skin_friction_drag_coeff', 'laminar_fractions_upper'] = DCDF_dlamup.ravel() - partials['skin_friction_drag_coeff', - 'laminar_fractions_lower'] = DCDF_dlamlow.ravel() + partials['skin_friction_drag_coeff', 'laminar_fractions_lower'] = DCDF_dlamlow.ravel() partials['skin_friction_drag_coeff', Aircraft.Wing.AREA] = DCDF_dmwa.ravel() diff --git a/aviary/subsystems/aerodynamics/flops_based/solved_alpha_group.py b/aviary/subsystems/aerodynamics/flops_based/solved_alpha_group.py deleted file mode 100644 index ace5bb4575..0000000000 --- a/aviary/subsystems/aerodynamics/flops_based/solved_alpha_group.py +++ /dev/null @@ -1,100 +0,0 @@ -import numpy as np -import openmdao.api as om - -from pathlib import Path - -import aviary.constants as constants -from aviary.subsystems.aerodynamics.aero_common import DynamicPressure -from aviary.subsystems.aerodynamics.gasp_based.table_based import TabularCruiseAero -from aviary.utils.named_values import NamedValues -from aviary.variable_info.variables import Aircraft, Dynamic - -grav_metric = constants.GRAV_METRIC_FLOPS - - -class SolvedAlphaGroup(om.Group): - """ - Aerodynmaics group that computes the coefficients of lift and drag on a - structured table of altitude, mach, and angle of attack. The angle of - attack is solved iteratively to balance the lift with the aircraft weight. - - The aerodynamics data can come from a file or can come from the output of - a component in the aviary pre_mission group. - """ - - def initialize(self): - """ - Declare options. - """ - self.options.declare('num_nodes', types=int) - - self.options.declare('aero_data', types=(str, Path, NamedValues), default=None, - desc='Data file or NamedValues object containing lift and ' - 'drag coefficient table as a function of altitude, ' - 'Mach, and angle of attack') - - self.options.declare('connect_training_data', default=False, - desc='When True, the aero tables will be passed as ' - 'OpenMDAO variables') - - self.options.declare('structured', types=bool, default=True, - desc='Flag that sets if data is a structured grid') - - self.options.declare('extrapolate', default=True, desc='Flag that sets if drag ' - 'data can be extrapolated') - - def setup(self): - options = self.options - nn = options['num_nodes'] - aero_data = options['aero_data'] - connect_training_data = options['connect_training_data'] - structured = options['structured'] - extrapolate = options['extrapolate'] - - self.add_subsystem( - 'DynamicPressure', DynamicPressure(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.MACH, Dynamic.Mission.STATIC_PRESSURE], - promotes_outputs=[Dynamic.Mission.DYNAMIC_PRESSURE]) - - aero = TabularCruiseAero(num_nodes=nn, - aero_data=aero_data, - connect_training_data=connect_training_data, - structured=structured, - extrapolate=extrapolate) - - if connect_training_data: - extra_promotes = [Aircraft.Design.DRAG_POLAR, - Aircraft.Design.LIFT_POLAR] - else: - extra_promotes = [] - - self.add_subsystem("tabular_aero", aero, - promotes_inputs=[Dynamic.Mission.ALTITUDE, Dynamic.Mission.MACH, - Aircraft.Wing.AREA, Dynamic.Mission.MACH, - Dynamic.Mission.DYNAMIC_PRESSURE] - + extra_promotes, - promotes_outputs=['CD', Dynamic.Mission.LIFT, Dynamic.Mission.DRAG]) - - balance = self.add_subsystem('balance', om.BalanceComp()) - balance.add_balance('alpha', val=np.ones(nn), units='deg', res_ref=1.0e6) - - self.connect('balance.alpha', 'tabular_aero.alpha') - self.connect('needed_lift.lift_resid', 'balance.lhs:alpha') - - self.add_subsystem('needed_lift', - om.ExecComp('lift_resid = mass * grav_metric - computed_lift', - grav_metric={'val': grav_metric}, - mass={'units': 'kg', 'shape': nn}, - computed_lift={'units': 'N', 'shape': nn}, - lift_resid={'shape': nn}, - has_diag_partials=True, - ), - promotes_inputs=[('mass', Dynamic.Mission.MASS), - ('computed_lift', Dynamic.Mission.LIFT)] - ) - - self.linear_solver = om.DirectSolver() - newton = self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) - newton.options['iprint'] = 2 - newton.options['atol'] = 1e-9 - newton.options['rtol'] = 1e-12 diff --git a/aviary/subsystems/aerodynamics/flops_based/tabular_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/tabular_aero_group.py index 936495c027..58ea109926 100644 --- a/aviary/subsystems/aerodynamics/flops_based/tabular_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/tabular_aero_group.py @@ -1,30 +1,36 @@ +from pathlib import Path + import numpy as np import openmdao.api as om -from pathlib import Path - from aviary.subsystems.aerodynamics.flops_based.drag import TotalDrag as Drag -from aviary.subsystems.aerodynamics.flops_based.lift import \ - LiftEqualsWeight as CL +from aviary.subsystems.aerodynamics.flops_based.lift import LiftEqualsWeight as CL from aviary.utils.csv_data_file import read_data_file from aviary.utils.data_interpolator_builder import build_data_interpolator from aviary.utils.functions import get_path from aviary.utils.named_values import NamedValues +from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Dynamic - # Map of variable names to allowed headers for data files (only lowercase required, # spaces are replaced with underscores when data tables are read) # "Repeated" aliases allows variables with different cases to match with desired # all-lowercase name -aliases = {Dynamic.Mission.ALTITUDE: ['h', 'alt', 'altitude'], - Dynamic.Mission.MACH: ['m', 'mach'], - 'lift_coefficient': ['cl', 'coefficient_of_lift', 'lift_coefficient'], - 'lift_dependent_drag_coefficient': ['cdi', 'lift_dependent_drag_coefficient', - 'lift-dependent_drag_coefficient'], - 'zero_lift_drag_coefficient': ['cd0', 'zero_lift_drag_coefficient', - 'zero-lift_drag_coefficient'], - } +aliases = { + Dynamic.Mission.ALTITUDE: ['h', 'alt', 'altitude'], + Dynamic.Atmosphere.MACH: ['m', 'mach'], + 'lift_coefficient': ['cl', 'coefficient_of_lift', 'lift_coefficient'], + 'lift_dependent_drag_coefficient': [ + 'cdi', + 'lift_dependent_drag_coefficient', + 'lift-dependent_drag_coefficient', + ], + 'zero_lift_drag_coefficient': [ + 'cd0', + 'zero_lift_drag_coefficient', + 'zero-lift_drag_coefficient', + ], +} class TabularAeroGroup(om.Group): @@ -50,16 +56,25 @@ def initialize(self): options.declare('num_nodes', types=int) - options.declare('CD0_data', types=(str, Path, NamedValues), - desc='Data file or NamedValues object containing zero-lift drag ' - 'coefficient table.') + options.declare( + 'CD0_data', + types=(str, Path, NamedValues), + desc='Data file or NamedValues object containing zero-lift drag coefficient table.', + ) - options.declare('CDI_data', types=(str, Path, NamedValues), - desc='Data file or NamedValues object containing lift-dependent ' - 'drag coefficient table.') + options.declare( + 'CDI_data', + types=(str, Path, NamedValues), + desc='Data file or NamedValues object containing lift-dependent ' + 'drag coefficient table.', + ) - options.declare('structured', types=bool, default=True, - desc='Flag that sets if data is a structured grid.') + options.declare( + 'structured', + types=bool, + default=True, + desc='Flag that sets if data is a structured grid.', + ) options.declare( 'connect_training_data', @@ -82,11 +97,11 @@ def setup(self): if isinstance(CDI_table, str): CDI_table = get_path(CDI_table) if isinstance(CDI_table, Path): - CDI_table = read_data_file(CDI_table, aliases=aliases) + CDI_table, _, _ = read_data_file(CDI_table, aliases=aliases) if isinstance(CD0_table, str): CD0_table = get_path(CD0_table) if isinstance(CD0_table, Path): - CD0_table = read_data_file(CD0_table, aliases=aliases) + CD0_table, _, _ = read_data_file(CD0_table, aliases=aliases) if connect_training_data or not structured: method = 'lagrange3' @@ -94,7 +109,7 @@ def setup(self): method = '2D-lagrange3' CD0_interp = build_data_interpolator( - nn, + num_nodes=nn, interpolator_data=CD0_table, interpolator_outputs={'zero_lift_drag_coefficient': 'unitless'}, method=method, @@ -103,7 +118,7 @@ def setup(self): ) CDI_interp = build_data_interpolator( - nn, + num_nodes=nn, interpolator_data=CDI_table, interpolator_outputs={'lift_dependent_drag_coefficient': 'unitless'}, method=method, @@ -113,26 +128,53 @@ def setup(self): # add subsystems self.add_subsystem( - Dynamic.Mission.DYNAMIC_PRESSURE, _DynamicPressure(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.VELOCITY, Dynamic.Mission.DENSITY], - promotes_outputs=[Dynamic.Mission.DYNAMIC_PRESSURE]) + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + _DynamicPressure(num_nodes=nn), + promotes_inputs=[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.DENSITY], + promotes_outputs=[Dynamic.Atmosphere.DYNAMIC_PRESSURE], + ) + + self.add_subsystem( + 'lift_coefficient', + CL(num_nodes=nn), + promotes_inputs=[ + Dynamic.Vehicle.MASS, + Aircraft.Wing.AREA, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + ], + promotes_outputs=[('cl', 'lift_coefficient'), Dynamic.Vehicle.LIFT], + ) + + if connect_training_data: + extra_promotes = [ + ('zero_lift_drag_coefficient_train', Aircraft.Design.LIFT_INDEPENDENT_DRAG_POLAR) + ] + else: + extra_promotes = [] self.add_subsystem( - 'lift_coefficient', CL(num_nodes=nn), - promotes_inputs=[Dynamic.Mission.MASS, - Aircraft.Wing.AREA, Dynamic.Mission.DYNAMIC_PRESSURE], - promotes_outputs=[('cl', 'lift_coefficient'), Dynamic.Mission.LIFT]) + 'CD0_interp', + CD0_interp, + promotes_inputs=['*'] + extra_promotes, + promotes_outputs=['*'], + ) - self.add_subsystem('CD0_interp', CD0_interp, - promotes_inputs=['*'], - promotes_outputs=['*']) + if connect_training_data: + extra_promotes = [ + ('lift_dependent_drag_coefficient_train', Aircraft.Design.LIFT_DEPENDENT_DRAG_POLAR) + ] + else: + extra_promotes = [] - self.add_subsystem('CDI_interp', CDI_interp, - promotes_inputs=['*'], - promotes_outputs=['*']) + self.add_subsystem( + 'CDI_interp', + CDI_interp, + promotes_inputs=['*'] + extra_promotes, + promotes_outputs=['*'], + ) self.add_subsystem( - Dynamic.Mission.DRAG, + Dynamic.Vehicle.DRAG, Drag(num_nodes=nn), promotes_inputs=[ Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, @@ -142,17 +184,15 @@ def setup(self): Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, ('CDI', 'lift_dependent_drag_coefficient'), ('CD0', 'zero_lift_drag_coefficient'), - Dynamic.Mission.MACH, - Dynamic.Mission.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, ], - promotes_outputs=['CD', Dynamic.Mission.DRAG], + promotes_outputs=['CD', Dynamic.Vehicle.DRAG], ) class _DynamicPressure(om.ExplicitComponent): - ''' - Calculate dynamic pressure as a function of velocity and density. - ''' + """Calculate dynamic pressure as a function of velocity and density.""" def initialize(self): self.options.declare('num_nodes', types=int) @@ -160,12 +200,10 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - self.add_input(Dynamic.Mission.VELOCITY, val=np.ones(nn), units='m/s') - self.add_input(Dynamic.Mission.DENSITY, val=np.ones(nn), units='kg/m**3') + add_aviary_input(self, Dynamic.Mission.VELOCITY, shape=nn, units='m/s') + add_aviary_input(self, Dynamic.Atmosphere.DENSITY, shape=nn, units='kg/m**3') - self.add_output( - Dynamic.Mission.DYNAMIC_PRESSURE, val=np.ones(nn), units='N/m**2', - desc='pressure caused by fluid motion') + add_aviary_output(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='N/m**2') def setup_partials(self): nn = self.options['num_nodes'] @@ -173,20 +211,21 @@ def setup_partials(self): rows_cols = np.arange(nn) self.declare_partials( - Dynamic.Mission.DYNAMIC_PRESSURE, [ - Dynamic.Mission.VELOCITY, Dynamic.Mission.DENSITY], - rows=rows_cols, cols=rows_cols) + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + [Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.DENSITY], + rows=rows_cols, + cols=rows_cols, + ) def compute(self, inputs, outputs): TAS = inputs[Dynamic.Mission.VELOCITY] - rho = inputs[Dynamic.Mission.DENSITY] + rho = inputs[Dynamic.Atmosphere.DENSITY] - outputs[Dynamic.Mission.DYNAMIC_PRESSURE] = 0.5 * rho * TAS**2 + outputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] = 0.5 * rho * TAS**2 def compute_partials(self, inputs, partials): TAS = inputs[Dynamic.Mission.VELOCITY] - rho = inputs[Dynamic.Mission.DENSITY] + rho = inputs[Dynamic.Atmosphere.DENSITY] - partials[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.VELOCITY] = rho * TAS - partials[Dynamic.Mission.DYNAMIC_PRESSURE, - Dynamic.Mission.DENSITY] = 0.5 * TAS**2 + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Mission.VELOCITY] = rho * TAS + partials[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.DENSITY] = 0.5 * TAS**2 diff --git a/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py index 85e2186b06..0899aa0663 100644 --- a/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/takeoff_aero_group.py @@ -1,23 +1,20 @@ -''' -Define utilities for calculating takeoff aerodynamics. -''' +"""Define utilities for calculating takeoff aerodynamics.""" + from collections.abc import Sequence import numpy as np import openmdao.api as om import scipy.constants as _units -from aviary.subsystems.aerodynamics.flops_based.ground_effect import \ - GroundEffect +from aviary.subsystems.aerodynamics.flops_based.ground_effect import GroundEffect from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.variable_info.functions import add_aviary_option class TakeoffAeroGroup(om.Group): - ''' - Define a group for calculating takeoff aerodynamics. - ''' + """Define a group for calculating takeoff aerodynamics.""" def initialize(self): options = self.options @@ -25,90 +22,83 @@ def initialize(self): options.declare('num_nodes', default=1, types=int, lower=0) options.declare( - 'ground_altitude', default=0., types=float, - desc='true altitude of the ground from mean sea level (m)' + 'ground_altitude', + default=0.0, + types=float, + desc='true altitude of the ground from mean sea level (m)', ) options.declare( - 'use_spoilers', default=False, types=bool, - desc='true for spoilers deployed' + 'use_spoilers', default=False, types=bool, desc='true for spoilers deployed' ) options.declare( - 'spoiler_drag_coefficient', default=0.0, types=float, - desc='spoiler drag coefficitnt' + 'spoiler_drag_coefficient', default=0.0, types=float, desc='spoiler drag coefficitnt' ) options.declare( - 'spoiler_lift_coefficient', default=0.0, types=float, - desc='spoiler lift coefficitnt' + 'spoiler_lift_coefficient', default=0.0, types=float, desc='spoiler lift coefficitnt' ) options.declare( - 'angles_of_attack', types=Sequence, - desc='sequence of angles of attack (deg); at least two values required' + 'angles_of_attack', + types=Sequence, + desc='sequence of angles of attack (deg); at least two values required', ) options.declare( - 'lift_coefficients', types=Sequence, - desc='sequence of lift coefficients, one for each angle of attack' + 'lift_coefficients', + types=Sequence, + desc='sequence of lift coefficients, one for each angle of attack', ) options.declare( - 'drag_coefficients', types=Sequence, - desc='sequence of drag coefficients, one for each angle of attack' + 'drag_coefficients', + types=Sequence, + desc='sequence of drag coefficients, one for each angle of attack', ) # NOTE: FLOPS did not enforce a lower bound. # - Should Aviary enforce a lower bound? options.declare( - 'lift_coefficient_factor', default=1., types=float, - desc='factor for takeoff lift' + 'lift_coefficient_factor', default=1.0, types=float, desc='factor for takeoff lift' ) options.declare( - 'drag_coefficient_factor', default=1., types=float, - desc='factor for takeoff drag' + 'drag_coefficient_factor', default=1.0, types=float, desc='factor for takeoff drag' ) options.declare( - 'landing_gear_up', default=False, types=bool, - desc='true for retracted landing gear' + 'landing_gear_up', default=False, types=bool, desc='true for retracted landing gear' ) - options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.LandingGear.DRAG_COEFFICIENT) def setup(self): options = self.options - aviary_options = options['aviary_options'] - nn = options['num_nodes'] angles_of_attack = np.array(options['angles_of_attack']) * _units.degree lift_coefficient_factor = options['lift_coefficient_factor'] - lift_coefficients = \ - np.array(options['lift_coefficients']) * lift_coefficient_factor + lift_coefficients = np.array(options['lift_coefficients']) * lift_coefficient_factor drag_coefficient_factor = options['drag_coefficient_factor'] - drag_coefficients = \ - np.array(options['drag_coefficients']) * drag_coefficient_factor + drag_coefficients = np.array(options['drag_coefficients']) * drag_coefficient_factor - inputs = ['angle_of_attack'] + gear_drag = options[Aircraft.LandingGear.DRAG_COEFFICIENT] + + inputs = [Dynamic.Vehicle.ANGLE_OF_ATTACK] takeoff_polar: om.MetaModelSemiStructuredComp = self.add_subsystem( 'takeoff_polar', - om.MetaModelSemiStructuredComp( - method='slinear', extrapolate=False, vec_size=nn - ), + om.MetaModelSemiStructuredComp(method='slinear', extrapolate=False, vec_size=nn), promotes_inputs=inputs, ) - takeoff_polar.add_input('angle_of_attack', angles_of_attack, units='rad') + takeoff_polar.add_input(Dynamic.Vehicle.ANGLE_OF_ATTACK, angles_of_attack, units='rad') takeoff_polar.add_output('lift_coefficient', lift_coefficients, units='unitless') takeoff_polar.add_output('drag_coefficient', drag_coefficients, units='unitless') @@ -121,28 +111,25 @@ def setup(self): } inputs = [ - 'angle_of_attack', Dynamic.Mission.ALTITUDE, Dynamic.Mission.FLIGHT_PATH_ANGLE, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.ALTITUDE, + Dynamic.Mission.FLIGHT_PATH_ANGLE, ('minimum_drag_coefficient', Mission.Takeoff.DRAG_COEFFICIENT_MIN), - Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.HEIGHT, - Aircraft.Wing.SPAN + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.HEIGHT, + Aircraft.Wing.SPAN, ] - self.add_subsystem( - 'ground_effect', GroundEffect(**kwargs), promotes_inputs=inputs - ) + self.add_subsystem('ground_effect', GroundEffect(**kwargs), promotes_inputs=inputs) - self.connect( - 'takeoff_polar.lift_coefficient', 'ground_effect.base_lift_coefficient' - ) + self.connect('takeoff_polar.lift_coefficient', 'ground_effect.base_lift_coefficient') - self.connect( - 'takeoff_polar.drag_coefficient', 'ground_effect.base_drag_coefficient' - ) + self.connect('takeoff_polar.drag_coefficient', 'ground_effect.base_drag_coefficient') - f = f'climb_drag_coefficient = ground_effect_drag' + f = 'climb_drag_coefficient = ground_effect_drag' if not options['landing_gear_up']: - gear_drag = aviary_options.get_val(Aircraft.LandingGear.DRAG_COEFFICIENT) + gear_drag = self.options[Aircraft.LandingGear.DRAG_COEFFICIENT] f = f + f' + {gear_drag}' if options['use_spoilers']: @@ -156,9 +143,11 @@ def setup(self): f'climb_lift_coefficient = ground_effect_lift + {spoiler_lift}', climb_lift_coefficient={'units': 'unitless', 'shape': nn}, ground_effect_lift={'units': 'unitless', 'shape': nn}, - has_diag_partials=True,), + has_diag_partials=True, + ), promotes_inputs=['ground_effect_lift'], - promotes_outputs=['climb_lift_coefficient']) + promotes_outputs=['climb_lift_coefficient'], + ) self.connect('ground_effect.lift_coefficient', 'ground_effect_lift') self.connect('climb_lift_coefficient', 'aero_forces.CL') @@ -172,19 +161,23 @@ def setup(self): f, climb_drag_coefficient={'units': 'unitless', 'shape': nn}, ground_effect_drag={'units': 'unitless', 'shape': nn}, - has_diag_partials=True,), + has_diag_partials=True, + ), promotes_inputs=['ground_effect_drag'], - promotes_outputs=['climb_drag_coefficient']) + promotes_outputs=['climb_drag_coefficient'], + ) self.connect('ground_effect.drag_coefficient', 'ground_effect_drag') self.connect('climb_drag_coefficient', 'aero_forces.CD') - inputs = [Dynamic.Mission.DYNAMIC_PRESSURE, Aircraft.Wing.AREA] - outputs = [Dynamic.Mission.LIFT, Dynamic.Mission.DRAG] + inputs = [Dynamic.Atmosphere.DYNAMIC_PRESSURE, Aircraft.Wing.AREA] + outputs = [Dynamic.Vehicle.LIFT, Dynamic.Vehicle.DRAG] self.add_subsystem( - 'aero_forces', AeroForces(num_nodes=nn), - promotes_inputs=inputs, promotes_outputs=outputs + 'aero_forces', + AeroForces(num_nodes=nn), + promotes_inputs=inputs, + promotes_outputs=outputs, ) - self.set_input_defaults('angle_of_attack', np.zeros(nn), 'rad') + self.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, np.zeros(nn), 'rad') diff --git a/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv b/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv index ebde1eae7c..e125c8ee6c 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv +++ b/aviary/subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv @@ -21,10 +21,12 @@ aircraft:crew_and_payload:wing_cargo,0.01,lbm #check aircraft:design:empty_mass_margin_scaler,0.01,unitless #check aircraft:design:landing_to_takeoff_mass_ratio,0.95,unitless aircraft:design:use_alt_mass,False,unitless +aircraft:design:type,transport,unitless aircraft:electrical:mass_scaler,1.01,unitless #check aircraft:engine:additional_mass_fraction,0.001,unitless aircraft:engine:constant_fuel_consumption,0.,lb/h -aircraft:engine:data_file,validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.deck,unitless +aircraft:engine:data_file,validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.csv,unitless +aircraft:engine:scale_factor,1.0,unitless aircraft:engine:flight_idle_max_fraction,1.01,unitless #check aircraft:engine:flight_idle_min_fraction,0.08,unitless aircraft:engine:flight_idle_thrust_fraction,0.00001,unitless #check @@ -50,7 +52,7 @@ aircraft:engine:thrust_reversers_mass_scaler,0.01,unitless #check aircraft:engine:wing_locations,0.22,unitless aircraft:fins:num_fins,0,unitless aircraft:fuel:auxiliary_fuel_capacity,0.01,lbm #check -aircraft:fuel:density_ratio,1.01,unitless #check +aircraft:fuel:density,6.767,lbm/galUS #check aircraft:fuel:fuel_system_mass_scaler,1.01,unitless #check aircraft:fuel:fuselage_fuel_capacity,7000.0,lbm aircraft:fuel:num_tanks,6,unitless @@ -74,7 +76,6 @@ aircraft:horizontal_tail:vertical_tail_fraction,1.01,unitless #check aircraft:hydraulics:mass_scaler,1.01,unitless #check aircraft:hydraulics:system_pressure,5010.0,lbf/ft**2 aircraft:instruments:mass_scaler,1.01,unitless #check -aircraft:landing_gear:carrier_based,False,unitless aircraft:landing_gear:main_gear_mass_scaler,1.01,unitless #check aircraft:landing_gear:main_gear_oleo_length,55,inch aircraft:landing_gear:nose_gear_mass_scaler,1.01,unitless #check @@ -86,7 +87,7 @@ aircraft:nacelle:mass_scaler,1.01,unitless #check aircraft:paint:mass_per_unit_area,0.01,lbm/ft**2 #check aircraft:propulsion:engine_oil_mass_scaler,1.01,unitless #check aircraft:propulsion:misc_mass_scaler,1.01,unitless #check -aircraft:propulsion:total_num_wing_engines,[2],unitless +aircraft:propulsion:total_num_wing_engines,2,unitless aircraft:vertical_tail:area,297,ft**2 aircraft:vertical_tail:aspect_ratio,0.821,unitless aircraft:vertical_tail:mass_scaler,1.01,unitless #check @@ -98,11 +99,12 @@ aircraft:wing:aeroelastic_tailoring_factor,0.01,unitless #check aircraft:wing:airfoil_technology,1.01,unitless #check aircraft:wing:area,1480,ft**2 aircraft:wing:aspect_ratio_reference,0.01,unitless #check -aircraft:wing:bending_mass_scaler,1.01,unitless #check +aircraft:wing:bending_material_mass_scaler,1.01,unitless #check aircraft:wing:chord_per_semispan,0.13,0.115,0.06,unitless aircraft:wing:composite_fraction,0.01,unitless #check aircraft:wing:dihedral,-1.0,deg aircraft:wing:control_surface_area_ratio,0.2234,unitless +aircraft:wing:detailed_wing,True,unitless aircraft:wing:glove_and_bat,0.01,ft**2 #check aircraft:wing:input_station_dist,0.,0.5,1.,unitless aircraft:wing:load_distribution_control,3,unitless @@ -116,7 +118,7 @@ aircraft:wing:shear_control_mass_scaler,1.01,unitless #check aircraft:wing:span,118,ft aircraft:wing:span_efficiency_reduction,False,unitless aircraft:wing:strut_bracing_factor,1.01,unitless #check -aircraft:wing:surface_ctrl_mass_scaler,1.01,unitless #check +aircraft:wing:surface_control_mass_scaler,1.01,unitless #check aircraft:wing:sweep,25,deg aircraft:wing:taper_ratio,0.33,unitless aircraft:wing:thickness_to_chord,0.1,unitless @@ -137,4 +139,5 @@ mission:takeoff:lift_coefficient_max,2.55,unitless mission:takeoff:lift_over_drag,25,unitless mission:takeoff:rolling_friction_coefficient,0.0175,unitless settings:equations_of_motion,height_energy +settings:aerodynamics_method,FLOPS settings:mass_method,FLOPS \ No newline at end of file diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_buffet_lift.py b/aviary/subsystems/aerodynamics/flops_based/test/test_buffet_lift.py index 4b53f24b48..8f313f5ea0 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_buffet_lift.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_buffet_lift.py @@ -1,30 +1,37 @@ import unittest -import numpy as np +import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.assert_utils import assert_check_partials +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.subsystems.aerodynamics.flops_based.buffet_lift import BuffetLift from aviary.variable_info.variables import Aircraft, Mission class TestBuffetLift(unittest.TestCase): - def test_derivs(self): - mach = [.2, .25, .3, .35, .4, .45, .5, .55, .6, .7, .75, .775, .8, .825, .85, .875, - 0.9, 0.95, 1.05, 1.1] + # fmt: off + mach = [ + 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.7, 0.75, + 0.775, 0.8, 0.825, 0.85, 0.875, 0.9, 0.95, 1.05, 1.1, + ] + # fmt: on nn = len(mach) prob = om.Problem() model = prob.model - model.add_subsystem('BUF', BuffetLift(num_nodes=nn), - promotes_inputs=[Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, - Aircraft.Wing.SWEEP, - Aircraft.Wing.THICKNESS_TO_CHORD, - Mission.Design.MACH]) + model.add_subsystem( + 'BUF', + BuffetLift(num_nodes=nn), + promotes_inputs=[ + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, + Aircraft.Wing.SWEEP, + Aircraft.Wing.THICKNESS_TO_CHORD, + Mission.Design.MACH, + ], + ) prob.setup(force_alloc_complex=True) @@ -37,17 +44,22 @@ def test_derivs(self): prob.set_val(Mission.Design.MACH, 0.801) prob.run_model() - derivs = prob.check_partials(compact_print=True, method="cs") + derivs = prob.check_partials(compact_print=True, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) - truth = np.array([0.86693558, 0.83439662, 0.79510222, 0.74915741, 0.6965622, - 0.63256819, 0.57123245, 0.51727722, 0.45729095, 0.31903298, - 0.2212182, 0.15774801, 0.08446832, -0.00190504, -0.09177745, - -0.18507041, -0.28122907, -0.4820969, -0.91803465, -1.15310457]) + # fmt: off + truth = np.array( + [ + 0.86693558, 0.83439662, 0.79510222, 0.74915741, 0.6965622, 0.63256819, 0.57123245, + 0.51727722, 0.45729095, 0.31903298, 0.2212182, 0.15774801, 0.08446832, -0.00190504, + -0.09177745, -0.18507041, -0.28122907, -0.4820969, -0.91803465, -1.15310457, + ] + ) + # fmt: on assert_near_equal(prob['BUF.DELCLB'], truth, 1e-7) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_compressibility_drag.py b/aviary/subsystems/aerodynamics/flops_based/test/test_compressibility_drag.py index 9dfeca1495..b9e7ce53a1 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_compressibility_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_compressibility_drag.py @@ -4,45 +4,51 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.flops_based.compressibility_drag import \ - CompressibilityDrag +from aviary.subsystems.aerodynamics.flops_based.compressibility_drag import CompressibilityDrag from aviary.variable_info.variables import Aircraft, Mission class CompressibilityDragTest(unittest.TestCase): - def test_derivs(self): - # Nudge the mach and diam/wingspan values off of the table points to prevent problem with # linear interp. delta = 1e-5 - mach = [.2, .25, .3, .35, .4, .45, .5, .55, .6, .7, .75, .775, .8, .825, .85, .875, 0.9, - 0.95, 1.05, 1.1] + # fmt: off + mach = [ + 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.7, 0.75, 0.775, 0.8, 0.825, 0.85, 0.875, 0.9, 0.95, 1.05, 1.1, + ] + # fmt: on + mach = np.array(mach) + delta nn = len(mach) prob = om.Problem() model = prob.model - model.add_subsystem('LID', CompressibilityDrag(num_nodes=nn), - promotes_inputs=[Aircraft.Design.BASE_AREA, - Aircraft.Wing.AREA, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, - Aircraft.Wing.SWEEP, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Fuselage.CROSS_SECTION, - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - Aircraft.Fuselage.LENGTH_TO_DIAMETER, - Mission.Design.MACH], - promotes_outputs=["compress_drag_coeff"]) + model.add_subsystem( + 'LID', + CompressibilityDrag(num_nodes=nn), + promotes_inputs=[ + Aircraft.Design.BASE_AREA, + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, + Aircraft.Wing.SWEEP, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Fuselage.CROSS_SECTION, + Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, + Aircraft.Fuselage.LENGTH_TO_DIAMETER, + Mission.Design.MACH, + ], + promotes_outputs=['compress_drag_coeff'], + ) prob.setup(force_alloc_complex=True) prob.set_val('LID.mach', mach) - prob.set_val(Mission.Design.MACH, .8-delta) + prob.set_val(Mission.Design.MACH, 0.8 - delta) prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, 0.13) prob.set_val(Aircraft.Fuselage.CROSS_SECTION, 128.2) prob.set_val(Aircraft.Design.BASE_AREA, 0.01) @@ -52,39 +58,21 @@ def test_derivs(self): prob.set_val(Aircraft.Wing.SWEEP, 25.07) prob.set_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.15 + delta) prob.set_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER, 10.12345) - prob.set_val(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, 0.) + prob.set_val(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, 0.0) prob.run_model() + # fmt: off expected_compress_drag_coeff = [ - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.00018641, - 0.00079348, - 0.00119559, - 0.00155455, - 0.00214888, - 0.00339369, - 0.01738419, - 0.02046643, - 0.02259292, - 0.03716558, - 0.04926635, - 0.04841961, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.00018641, 0.00079348, 0.00119559, 0.00155455, + 0.00214888, 0.00339369, 0.01738419, 0.02046643, 0.02259292, 0.03716558, 0.04926635, 0.04841961, ] - assert_near_equal( - prob.get_val("compress_drag_coeff"), - expected_compress_drag_coeff, 1e-6) + # fmt: on + assert_near_equal(prob.get_val('compress_drag_coeff'), expected_compress_drag_coeff, 1e-6) - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py index f6d4de0be0..1af28385be 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_computed_aero_group.py @@ -10,11 +10,11 @@ from aviary.utils.preprocessors import preprocess_options from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic, Settings class MissionDragTest(unittest.TestCase): - def test_basic_large_single_aisle_1(self): flops_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') flops_outputs = get_flops_outputs('LargeSingleAisle1FLOPS') @@ -29,17 +29,16 @@ def test_basic_large_single_aisle_1(self): flops_inputs.set_val(key, *(flops_outputs.get_item(key))) flops_inputs.set_val(Settings.VERBOSITY, 0) - engine = build_engine_deck(flops_inputs) - preprocess_options(flops_inputs, engine_models=engine) + engines = [build_engine_deck(flops_inputs)] + preprocess_options(flops_inputs, engine_models=engines) # don't need mass subsystem, so we skip it - default_premission_subsystems = get_default_premission_subsystems( - 'FLOPS', engine)[:-1] + default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines)[:-1] # we just want aero for mission, make a copy by itself aero = default_premission_subsystems[-1] # Design conditions: - alt = 41000 + # alt = 41000 # mach = 0.79 # Is this correct? @@ -48,10 +47,12 @@ def test_basic_large_single_aisle_1(self): # --------------------- # 1D Tables over M # --------------------- - mach = np.array([0.200, 0.300, 0.400, 0.500, 0.600, 0.700, - 0.750, 0.775, 0.800, 0.825, 0.850, 0.875]) - CL = np.array([0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, - 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85]) + mach = np.array( + [0.200, 0.300, 0.400, 0.500, 0.600, 0.700, 0.750, 0.775, 0.800, 0.825, 0.850, 0.875] + ) + CL = np.array( + [0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85] + ) mach = np.repeat(mach, 15) CL = np.tile(CL, 12) @@ -59,7 +60,7 @@ def test_basic_large_single_aisle_1(self): T = 389.97 nn = len(mach) - lift = CL * Sref * 0.5 * 1.4 * P * mach ** 2 + lift = CL * Sref * 0.5 * 1.4 * P * mach**2 mass = lift prob = om.Problem() @@ -68,72 +69,101 @@ def test_basic_large_single_aisle_1(self): # Upstream pre-mission analysis for aero prob.model.add_subsystem( 'pre_mission', - CorePreMission( - aviary_options=flops_inputs, subsystems=default_premission_subsystems - ), + CorePreMission(aviary_options=flops_inputs, subsystems=default_premission_subsystems), promotes_inputs=['aircraft:*'], promotes_outputs=['aircraft:*', 'mission:*'], ) model.add_subsystem( - 'aero', aero.build_mission(num_nodes=nn, - aviary_inputs=flops_inputs, - **{'method': 'computed'}), - promotes=['*'] + 'aero', + aero.build_mission(num_nodes=nn, aviary_inputs=flops_inputs, **{'method': 'computed'}), + promotes=['*'], ) + # Set all options + setup_model_options(prob, flops_inputs) + prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, np.ones(1)) + prob.setup(force_alloc_complex=True) prob.set_solver_print(level=2) # Mission params - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P, units='lbf/ft**2') - prob.set_val(Dynamic.Mission.TEMPERATURE, val=T, units='degR') - prob.set_val(Dynamic.Mission.MASS, val=mass, units='lbm') + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P, units='lbf/ft**2') + prob.set_val(Dynamic.Atmosphere.TEMPERATURE, val=T, units='degR') + prob.set_val(Dynamic.Vehicle.MASS, val=mass, units='lbm') set_aviary_initial_values(prob, flops_inputs) prob.run_model() - D = prob.get_val(Dynamic.Mission.DRAG, 'lbf') - CD = D / (Sref * 0.5 * 1.4 * P * mach ** 2) - - data = np.array([ - [0.02825, 0.02849, 0.02901, 0.02981, 0.03089, 0.03223, 0.03381, 0.03549, - 0.03752, 0.04006, 0.04270, 0.04548, 0.04861, 0.05211, 0.05600], - [0.02637, 0.02662, 0.02714, 0.02794, 0.02901, 0.03035, 0.03193, 0.03361, - 0.03564, 0.03819, 0.04082, 0.04361, 0.04674, 0.05024, 0.05412], - [0.02509, 0.02533, 0.02585, 0.02665, 0.02773, 0.02907, 0.03065, 0.03233, - 0.03436, 0.03690, 0.03954, 0.04232, 0.04545, 0.04895, 0.05284], - [0.02412, 0.02434, 0.02485, 0.02565, 0.02674, 0.02808, 0.02965, 0.03133, - 0.03336, 0.03590, 0.03854, 0.04132, 0.04445, 0.04795, 0.05184], - [0.02351, 0.02370, 0.02420, 0.02500, 0.02611, 0.02745, 0.02900, 0.03068, - 0.03272, 0.03524, 0.03788, 0.04067, 0.04380, 0.04730, 0.05118], - [0.02350, 0.02362, 0.02408, 0.02489, 0.02604, 0.02741, 0.02890, 0.03057, - 0.03261, 0.03512, 0.03776, 0.04054, 0.04368, 0.04717, 0.05106], - [0.02367, 0.02373, 0.02417, 0.02498, 0.02617, 0.02754, 0.02900, 0.03066, - 0.03270, 0.03517, 0.03781, 0.04065, 0.04393, 0.04766, 0.05186], - [0.02392, 0.02394, 0.02436, 0.02518, 0.02639, 0.02777, 0.02920, 0.03084, - 0.03288, 0.03532, 0.03804, 0.04132, 0.04533, 0.05011, 0.05570], - [0.02450, 0.02443, 0.02481, 0.02563, 0.02690, 0.02833, 0.02977, 0.03140, - 0.03349, 0.03612, 0.03970, 0.04440, 0.04951, 0.05510, 0.06116], - [0.02600, 0.02567, 0.02592, 0.02677, 0.02819, 0.02984, 0.03152, 0.03357, - 0.03637, 0.04049, 0.04542, 0.05088, 0.05801, 0.06656, 0.07652], - [0.02926, 0.02811, 0.02800, 0.02891, 0.03084, 0.03348, 0.03664, 0.04043, - 0.04577, 0.05245, 0.05885, 0.06547, 0.07224, 0.07924, 0.08650], - [0.04705, 0.04397, 0.04294, 0.04394, 0.04697, 0.05224, 0.05984, 0.06647, - 0.07918, 0.09321, 0.09807, 0.10514, 0.11100, 0.11651, 0.12197], - ]).ravel() + D = prob.get_val(Dynamic.Vehicle.DRAG, 'lbf') + CD = D / (Sref * 0.5 * 1.4 * P * mach**2) + + # fmt: off + data = np.array( + [ + [ + 0.02825, 0.02849, 0.02901, 0.02981, 0.03089, 0.03223, 0.03381, 0.03549, + 0.03752, 0.04006, 0.04270, 0.04548, 0.04861, 0.05211, 0.05600 + ], + [ + 0.02637, 0.02662, 0.02714, 0.02794, 0.02901, 0.03035, 0.03193, 0.03361, + 0.03564, 0.03819, 0.04082, 0.04361, 0.04674, 0.05024, 0.05412 + ], + [ + 0.02509, 0.02533, 0.02585, 0.02665, 0.02773, 0.02907, 0.03065, 0.03233, + 0.03436, 0.03690, 0.03954, 0.04232, 0.04545, 0.04895, 0.05284 + ], + [ + 0.02412, 0.02434, 0.02485, 0.02565, 0.02674, 0.02808, 0.02965, 0.03133, + 0.03336, 0.03590, 0.03854, 0.04132, 0.04445, 0.04795, 0.05184 + ], + [ + 0.02351, 0.02370, 0.02420, 0.02500, 0.02611, 0.02745, 0.02900, 0.03068, + 0.03272, 0.03524, 0.03788, 0.04067, 0.04380, 0.04730, 0.05118 + ], + [ + 0.02350, 0.02362, 0.02408, 0.02489, 0.02604, 0.02741, 0.02890, 0.03057, + 0.03261, 0.03512, 0.03776, 0.04054, 0.04368, 0.04717, 0.05106 + ], + [ + 0.02367, 0.02373, 0.02417, 0.02498, 0.02617, 0.02754, 0.02900, 0.03066, + 0.03270, 0.03517, 0.03781, 0.04065, 0.04393, 0.04766, 0.05186 + ], + [ + 0.02392, 0.02394, 0.02436, 0.02518, 0.02639, 0.02777, 0.02920, 0.03084, + 0.03288, 0.03532, 0.03804, 0.04132, 0.04533, 0.05011, 0.05570 + ], + [ + 0.02450, 0.02443, 0.02481, 0.02563, 0.02690, 0.02833, 0.02977, 0.03140, + 0.03349, 0.03612, 0.03970, 0.04440, 0.04951, 0.05510, 0.06116 + ], + [ + 0.02600, 0.02567, 0.02592, 0.02677, 0.02819, 0.02984, 0.03152, 0.03357, + 0.03637, 0.04049, 0.04542, 0.05088, 0.05801, 0.06656, 0.07652 + ], + [ + 0.02926, 0.02811, 0.02800, 0.02891, 0.03084, 0.03348, 0.03664, 0.04043, + 0.04577, 0.05245, 0.05885, 0.06547, 0.07224, 0.07924, 0.08650 + ], + [ + 0.04705, 0.04397, 0.04294, 0.04394, 0.04697, 0.05224, 0.05984, 0.06647, + 0.07918, 0.09321, 0.09807, 0.10514, 0.11100, 0.11651, 0.12197 + ], + ] + ).ravel() + # fmt: on # Due to differences in the interp method, certain points that are extrapolated # (i.e., M or CL are well above design) have more than 1% error. - assert_near_equal(CD, data, .05) + assert_near_equal(CD, data, 0.05) - assert_near_equal(CD[:134], data[:134], .004) + assert_near_equal(CD[:134], data[:134], 0.004) def test_n3cc_drag(self): - flops_inputs = get_flops_inputs('N3CC') - flops_outputs = get_flops_outputs('N3CC') + flops_inputs = get_flops_inputs('AdvancedSingleAisle') + flops_outputs = get_flops_outputs('AdvancedSingleAisle') # comparison data is unscaled drag flops_inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 1.0) @@ -145,25 +175,25 @@ def test_n3cc_drag(self): flops_inputs.set_val(key, *(flops_outputs.get_item(key))) flops_inputs.set_val(Settings.VERBOSITY, 0) - engine = build_engine_deck(flops_inputs) - preprocess_options(flops_inputs, engine_models=engine) + engines = [build_engine_deck(flops_inputs)] + preprocess_options(flops_inputs, engine_models=engines) # don't need mass subsystem, so we skip it - default_premission_subsystems = get_default_premission_subsystems( - 'FLOPS', engine)[:-1] + default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines)[:-1] # we just want aero for mission, make a copy by itself aero = default_premission_subsystems[-1] - alt = 43000 Sref = 1220.0 # --------------------- # 1D Tables over M # --------------------- - mach = np.array([0.200, 0.300, 0.400, 0.500, 0.600, - 0.700, 0.750, 0.775, 0.800, 0.825, 0.850]) - CL = np.array([0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, - 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9]) + mach = np.array( + [0.200, 0.300, 0.400, 0.500, 0.600, 0.700, 0.750, 0.775, 0.800, 0.825, 0.850] + ) + CL = np.array( + [0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9] + ) mach = np.repeat(mach, 15) CL = np.tile(CL, 11) @@ -171,7 +201,7 @@ def test_n3cc_drag(self): T = 389.97 nn = len(mach) - lift = CL * Sref * 0.5 * 1.4 * P * mach ** 2 + lift = CL * Sref * 0.5 * 1.4 * P * mach**2 mass = lift prob = om.Problem() @@ -180,65 +210,93 @@ def test_n3cc_drag(self): # Upstream pre-mission analysis for aero prob.model.add_subsystem( 'pre_mission', - CorePreMission( - aviary_options=flops_inputs, subsystems=default_premission_subsystems - ), + CorePreMission(aviary_options=flops_inputs, subsystems=default_premission_subsystems), promotes_inputs=['aircraft:*'], promotes_outputs=['aircraft:*', 'mission:*'], ) model.add_subsystem( - 'aero', aero.build_mission(num_nodes=nn, - aviary_inputs=flops_inputs, - **{'method': 'computed'}), - promotes=['*'] + 'aero', + aero.build_mission(num_nodes=nn, aviary_inputs=flops_inputs, **{'method': 'computed'}), + promotes=['*'], ) + # Set all options + setup_model_options(prob, flops_inputs) + + prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, np.ones(1)) + prob.setup() # Mission params - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P, units='lbf/ft**2') - prob.set_val(Dynamic.Mission.TEMPERATURE, val=T, units='degR') - prob.set_val(Dynamic.Mission.MASS, val=mass, units='lbm') + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P, units='lbf/ft**2') + prob.set_val(Dynamic.Atmosphere.TEMPERATURE, val=T, units='degR') + prob.set_val(Dynamic.Vehicle.MASS, val=mass, units='lbm') set_aviary_initial_values(prob, flops_inputs) prob.run_model() - D = prob.get_val(Dynamic.Mission.DRAG, 'lbf') - CD = D / (Sref * 0.5 * 1.4 * P * mach ** 2) - - data = np.array([ - [0.02494, 0.02544, 0.02621, 0.02727, 0.02859, 0.03015, 0.03191, 0.03381, - 0.03632, 0.03901, 0.04175, 0.04483, 0.04825, 0.05205, 0.05621], - [0.02325, 0.02375, 0.02453, 0.02558, 0.02690, 0.02847, 0.03022, 0.03213, - 0.03464, 0.03733, 0.04006, 0.04315, 0.04657, 0.05037, 0.05452], - [0.02212, 0.02261, 0.02339, 0.02444, 0.02577, 0.02733, 0.02908, 0.03099, - 0.03350, 0.03618, 0.03892, 0.04201, 0.04542, 0.04922, 0.05338], - [0.02125, 0.02173, 0.02250, 0.02357, 0.02491, 0.02646, 0.02820, 0.03011, - 0.03261, 0.03530, 0.03804, 0.04112, 0.04454, 0.04834, 0.05250], - [0.02084, 0.02130, 0.02208, 0.02316, 0.02451, 0.02604, 0.02776, 0.02969, - 0.03218, 0.03487, 0.03761, 0.04069, 0.04411, 0.04791, 0.05207], - [0.02087, 0.02127, 0.02203, 0.02316, 0.02457, 0.02605, 0.02772, 0.02967, - 0.03213, 0.03482, 0.03756, 0.04065, 0.04407, 0.04788, 0.05204], - [0.02115, 0.02152, 0.02228, 0.02343, 0.02486, 0.02632, 0.02795, 0.02991, - 0.03233, 0.03501, 0.03803, 0.04171, 0.04606, 0.05113, 0.05689], - [0.02160, 0.02192, 0.02268, 0.02386, 0.02535, 0.02681, 0.02842, 0.03038, - 0.03291, 0.03596, 0.04024, 0.04509, 0.05057, 0.05668, 0.06342], - [0.02274, 0.02293, 0.02366, 0.02494, 0.02659, 0.02820, 0.03004, 0.03244, - 0.03596, 0.04066, 0.04560, 0.05224, 0.06038, 0.07001, 0.08114], - [0.02516, 0.02493, 0.02561, 0.02720, 0.02954, 0.03219, 0.03543, 0.03964, - 0.04534, 0.05181, 0.05827, 0.06510, 0.07228, 0.07984, 0.08776], - [0.03957, 0.03827, 0.03877, 0.04108, 0.04524, 0.05136, 0.05820, 0.06586, - 0.08233, 0.08717, 0.09438, 0.10072, 0.10656, 0.11240, 0.11803] - ]).ravel() + D = prob.get_val(Dynamic.Vehicle.DRAG, 'lbf') + CD = D / (Sref * 0.5 * 1.4 * P * mach**2) + + # fmt: off + data = np.array( + [ + [ + 0.02494, 0.02544, 0.02621, 0.02727, 0.02859, 0.03015, 0.03191, 0.03381, + 0.03632, 0.03901, 0.04175, 0.04483, 0.04825, 0.05205, 0.05621 + ], + [ + 0.02325, 0.02375, 0.02453, 0.02558, 0.02690, 0.02847, 0.03022, 0.03213, + 0.03464, 0.03733, 0.04006, 0.04315, 0.04657, 0.05037, 0.05452 + ], + [ + 0.02212, 0.02261, 0.02339, 0.02444, 0.02577, 0.02733, 0.02908, 0.03099, + 0.03350, 0.03618, 0.03892, 0.04201, 0.04542, 0.04922, 0.05338 + ], + [ + 0.02125, 0.02173, 0.02250, 0.02357, 0.02491, 0.02646, 0.02820, 0.03011, + 0.03261, 0.03530, 0.03804, 0.04112, 0.04454, 0.04834, 0.05250 + ], + [ + 0.02084, 0.02130, 0.02208, 0.02316, 0.02451, 0.02604, 0.02776, 0.02969, + 0.03218, 0.03487, 0.03761, 0.04069, 0.04411, 0.04791, 0.05207 + ], + [ + 0.02087, 0.02127, 0.02203, 0.02316, 0.02457, 0.02605, 0.02772, 0.02967, + 0.03213, 0.03482, 0.03756, 0.04065, 0.04407, 0.04788, 0.05204 + ], + [ + 0.02115, 0.02152, 0.02228, 0.02343, 0.02486, 0.02632, 0.02795, 0.02991, + 0.03233, 0.03501, 0.03803, 0.04171, 0.04606, 0.05113, 0.05689 + ], + [ + 0.02160, 0.02192, 0.02268, 0.02386, 0.02535, 0.02681, 0.02842, 0.03038, + 0.03291, 0.03596, 0.04024, 0.04509, 0.05057, 0.05668, 0.06342 + ], + [ + 0.02274, 0.02293, 0.02366, 0.02494, 0.02659, 0.02820, 0.03004, 0.03244, + 0.03596, 0.04066, 0.04560, 0.05224, 0.06038, 0.07001, 0.08114 + ], + [ + 0.02516, 0.02493, 0.02561, 0.02720, 0.02954, 0.03219, 0.03543, 0.03964, + 0.04534, 0.05181, 0.05827, 0.06510, 0.07228, 0.07984, 0.08776 + ], + [ + 0.03957, 0.03827, 0.03877, 0.04108, 0.04524, 0.05136, 0.05820, 0.06586, + 0.08233, 0.08717, 0.09438, 0.10072, 0.10656, 0.11240, 0.11803 + ] + ] + ).ravel() + # fmt: on # Due to differences in the interp method, certain points that are extrapolated # (i.e., M or CL are well above design) have more than 1% error. - assert_near_equal(CD, data, .05) + assert_near_equal(CD, data, 0.05) - assert_near_equal(CD[:134], data[:134], .005) + assert_near_equal(CD[:134], data[:134], 0.005) def test_large_single_aisle_2_drag(self): flops_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') @@ -254,25 +312,23 @@ def test_large_single_aisle_2_drag(self): flops_inputs.set_val(key, *(flops_outputs.get_item(key))) flops_inputs.set_val(Settings.VERBOSITY, 0) - engine = build_engine_deck(flops_inputs) - preprocess_options(flops_inputs, engine_models=engine) + engines = [build_engine_deck(flops_inputs)] + preprocess_options(flops_inputs, engine_models=engines) # don't need mass subsystem, so we skip it - default_premission_subsystems = get_default_premission_subsystems( - 'FLOPS', engine)[:-1] + default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines)[:-1] # we just want aero for mission, make a copy by itself aero = default_premission_subsystems[-1] - alt = 41000 Sref = 1341.0 # --------------------- # 1D Tables over M # --------------------- - mach = np.array([0.2, 0.300, 0.400, 0.500, 0.600, 0.700, - 0.750, 0.775, 0.800, 0.825, 0.850]) - CL = np.array([0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, - 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8]) + mach = np.array([0.2, 0.300, 0.400, 0.500, 0.600, 0.700, 0.750, 0.775, 0.800, 0.825, 0.850]) + CL = np.array( + [0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8] + ) nm = len(mach) nc = len(CL) mach = np.repeat(mach, nc) @@ -282,7 +338,7 @@ def test_large_single_aisle_2_drag(self): P = 374.74437747 T = 389.97 - lift = CL * Sref * 0.5 * 1.4 * P * mach ** 2 + lift = CL * Sref * 0.5 * 1.4 * P * mach**2 mass = lift prob = om.Problem() @@ -291,66 +347,102 @@ def test_large_single_aisle_2_drag(self): # Upstream pre-mission analysis for aero prob.model.add_subsystem( 'pre_mission', - CorePreMission( - aviary_options=flops_inputs, subsystems=default_premission_subsystems - ), + CorePreMission(aviary_options=flops_inputs, subsystems=default_premission_subsystems), promotes_inputs=['aircraft:*'], promotes_outputs=['aircraft:*', 'mission:*'], ) model.add_subsystem( - 'aero', aero.build_mission(num_nodes=nn, - aviary_inputs=flops_inputs, - **{'method': 'computed'}), - promotes=['*'] + 'aero', + aero.build_mission(num_nodes=nn, aviary_inputs=flops_inputs, **{'method': 'computed'}), + promotes=['*'], ) + # Set all options + setup_model_options(prob, flops_inputs) + + prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, np.ones(1)) + prob.setup() # Mission params - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P, units='lbf/ft**2') - prob.set_val(Dynamic.Mission.TEMPERATURE, val=T, units='degR') - prob.set_val(Dynamic.Mission.MASS, val=mass, units='lbm') + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P, units='lbf/ft**2') + prob.set_val(Dynamic.Atmosphere.TEMPERATURE, val=T, units='degR') + prob.set_val(Dynamic.Vehicle.MASS, val=mass, units='lbm') set_aviary_initial_values(prob, flops_inputs) prob.run_model() - D = prob.get_val(Dynamic.Mission.DRAG, 'lbf') - CD = D / (Sref * 0.5 * 1.4 * P * mach ** 2) - - data = np.array([ - [0.02748, 0.02748, 0.02777, 0.02834, 0.02919, 0.03031, 0.03167, 0.03308, - 0.03476, 0.03721, 0.03983, 0.04278, 0.04609, 0.04996, 0.05461], - [0.02562, 0.02562, 0.02591, 0.02648, 0.02733, 0.02845, 0.02982, 0.03122, - 0.03290, 0.03536, 0.03797, 0.04093, 0.04423, 0.04810, 0.05276], - [0.02435, 0.02436, 0.02465, 0.02521, 0.02606, 0.02718, 0.02855, 0.02995, - 0.03164, 0.03409, 0.03671, 0.03966, 0.04296, 0.04683, 0.05149], - [0.02338, 0.02338, 0.02366, 0.02423, 0.02508, 0.02620, 0.02757, 0.02898, - 0.03067, 0.03310, 0.03572, 0.03867, 0.04198, 0.04585, 0.05050], - [0.02276, 0.02275, 0.02303, 0.02359, 0.02446, 0.02557, 0.02693, 0.02835, - 0.03007, 0.03246, 0.03509, 0.03804, 0.04134, 0.04521, 0.04987], - [0.02279, 0.02269, 0.02293, 0.02350, 0.02441, 0.02555, 0.02685, 0.02829, - 0.03002, 0.03235, 0.03499, 0.03794, 0.04124, 0.04511, 0.04977], - [0.02297, 0.02282, 0.02303, 0.02360, 0.02454, 0.02571, 0.02699, 0.02843, - 0.03016, 0.03241, 0.03502, 0.03803, 0.04140, 0.04537, 0.05014], - [0.02328, 0.02306, 0.02323, 0.02380, 0.02478, 0.02598, 0.02724, 0.02868, - 0.03042, 0.03260, 0.03512, 0.03860, 0.04232, 0.04671, 0.05204], - [0.02399, 0.02360, 0.02370, 0.02428, 0.02533, 0.02662, 0.02789, 0.02933, - 0.03129, 0.03403, 0.03737, 0.04141, 0.04587, 0.05069, 0.05587], - [0.02567, 0.02496, 0.02490, 0.02548, 0.02670, 0.02821, 0.02970, 0.03157, - 0.03426, 0.03794, 0.04203, 0.04630, 0.05183, 0.05791, 0.06470], - [0.04212, 0.04044, 0.03992, 0.04052, 0.04226, 0.04476, 0.04771, 0.05158, - 0.05638, 0.06166, 0.06690, 0.07238, 0.07763, 0.08296, 0.08858] - ]).ravel() + D = prob.get_val(Dynamic.Vehicle.DRAG, 'lbf') + CD = D / (Sref * 0.5 * 1.4 * P * mach**2) + + # fmt: off + data = np.array( + [ + [ + 0.02748, 0.02748, 0.02777, 0.02834, 0.02919, 0.03031, 0.03167, 0.03308, + 0.03476, 0.03721, 0.03983, 0.04278, 0.04609, 0.04996, 0.05461 + ], + [ + 0.02562, 0.02562, 0.02591, 0.02648, 0.02733, 0.02845, 0.02982, 0.03122, + 0.03290, 0.03536, 0.03797, 0.04093, 0.04423, 0.04810, 0.05276 + ], + [ + 0.02435, 0.02436, 0.02465, 0.02521, 0.02606, 0.02718, 0.02855, 0.02995, + 0.03164, 0.03409, 0.03671, 0.03966, 0.04296, 0.04683, 0.05149 + ], + [ + 0.02338, 0.02338, 0.02366, 0.02423, 0.02508, 0.02620, 0.02757, 0.02898, + 0.03067, 0.03310, 0.03572, 0.03867, 0.04198, 0.04585, 0.05050 + ], + [ + 0.02276, 0.02275, 0.02303, 0.02359, 0.02446, 0.02557, 0.02693, 0.02835, + 0.03007, 0.03246, 0.03509, 0.03804, 0.04134, 0.04521, 0.04987 + ], + [ + + 0.02279, 0.02269, 0.02293, 0.02350, 0.02441, 0.02555, 0.02685, 0.02829, + 0.03002, 0.03235, 0.03499, 0.03794, 0.04124, 0.04511, 0.04977 + ], + [ + + 0.02297, 0.02282, 0.02303, 0.02360, 0.02454, 0.02571, 0.02699, 0.02843, + 0.03016, 0.03241, 0.03502, 0.03803, 0.04140, 0.04537, 0.05014 + ], + [ + + 0.02328, 0.02306, 0.02323, 0.02380, 0.02478, 0.02598, 0.02724, 0.02868, + 0.03042, 0.03260, 0.03512, 0.03860, 0.04232, 0.04671, 0.05204 + ], + [ + + 0.02399, 0.02360, 0.02370, 0.02428, 0.02533, 0.02662, 0.02789, 0.02933, + 0.03129, 0.03403, 0.03737, 0.04141, 0.04587, 0.05069, 0.05587 + ], + [ + + 0.02567, 0.02496, 0.02490, 0.02548, 0.02670, 0.02821, 0.02970, 0.03157, + 0.03426, 0.03794, 0.04203, 0.04630, 0.05183, 0.05791, 0.06470 + ], + [ + + 0.04212, 0.04044, 0.03992, 0.04052, 0.04226, 0.04476, 0.04771, 0.05158, + 0.05638, 0.06166, 0.06690, 0.07238, 0.07763, 0.08296, 0.08858 + ] + ] + ).ravel() + # fmt: on # Due to differences in the interp method, certain points that are extrapolated (i.e., # M or CL are well above design) have more than 1% error. - assert_near_equal(CD, data, .05) + assert_near_equal(CD, data, 0.05) - assert_near_equal(CD[:134], data[:134], .005) + assert_near_equal(CD[:134], data[:134], 0.005) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = MissionDragTest() + # test.test_large_single_aisle_2_drag() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_design.py b/aviary/subsystems/aerodynamics/flops_based/test/test_design.py index 8b9bcb94c0..df2f8b053c 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_design.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_design.py @@ -4,12 +4,10 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.subsystems.aerodynamics.flops_based.design import Design -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Aircraft, Mission class DesignMCLTest(unittest.TestCase): - def test_derivs_supersonic1(self): # Case: THICKNESS_TO_CHORD < 0.065 and MAX_MACH > 1 @@ -17,14 +15,14 @@ def test_derivs_supersonic1(self): model = prob.model options = {} - options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = (1.0, 'unitless') - options[Mission.Constraints.MAX_MACH] = (1.2, 'unitless') + options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = 1.0 + options[Mission.Constraints.MAX_MACH] = 1.2 model.add_subsystem( 'design', - Design(aviary_options=AviaryValues(options)), + Design(**options), promotes_inputs=['*'], - promotes_outputs=[Mission.Design.MACH, Mission.Design.LIFT_COEFFICIENT] + promotes_outputs=[Mission.Design.MACH, Mission.Design.LIFT_COEFFICIENT], ) prob.setup(force_alloc_complex=True) @@ -35,13 +33,11 @@ def test_derivs_supersonic1(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) - assert_near_equal( - prob.get_val(Mission.Design.MACH), [0.753238], 1e-6) - assert_near_equal( - prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.909926], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.MACH), [0.753238], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.909926], 1e-6) def test_derivs_subsonic1(self): # Case: THICKNESS_TO_CHORD > 0.065 and MAX_MACH < 1 @@ -50,12 +46,12 @@ def test_derivs_subsonic1(self): model = prob.model options = {} - options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = (1.0, 'unitless') - options[Mission.Constraints.MAX_MACH] = (0.9, 'unitless') + options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = 1.0 + options[Mission.Constraints.MAX_MACH] = 0.9 model.add_subsystem( 'design', - Design(aviary_options=AviaryValues(options)), + Design(**options), promotes_inputs=['*'], promotes_outputs=[Mission.Design.MACH, Mission.Design.LIFT_COEFFICIENT], ) @@ -68,13 +64,11 @@ def test_derivs_subsonic1(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) - assert_near_equal( - prob.get_val(Mission.Design.MACH), [0.671145], 1e-6) - assert_near_equal( - prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.683002], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.MACH), [0.671145], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.683002], 1e-6) def test_derivs_supersonic2(self): # Case: THICKNESS_TO_CHORD > 0.065 and MAX_MACH > 1 @@ -83,12 +77,12 @@ def test_derivs_supersonic2(self): model = prob.model options = {} - options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = (1.0, 'unitless') - options[Mission.Constraints.MAX_MACH] = (1.2, 'unitless') + options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = 1.0 + options[Mission.Constraints.MAX_MACH] = 1.2 model.add_subsystem( 'design', - Design(aviary_options=AviaryValues(options)), + Design(**options), promotes_inputs=['*'], promotes_outputs=[Mission.Design.MACH, Mission.Design.LIFT_COEFFICIENT], ) @@ -101,13 +95,11 @@ def test_derivs_supersonic2(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) - assert_near_equal( - prob.get_val(Mission.Design.MACH), [0.671145], 1e-6) - assert_near_equal( - prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.683002], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.MACH), [0.671145], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.683002], 1e-6) def test_derivs_subsonic2(self): # Case: THICKNESS_TO_CHORD <= 0.065 and MAX_MACH < 1 @@ -116,12 +108,12 @@ def test_derivs_subsonic2(self): model = prob.model options = {} - options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = (1.0, 'unitless') - options[Mission.Constraints.MAX_MACH] = (0.9, 'unitless') + options[Aircraft.Wing.AIRFOIL_TECHNOLOGY] = 1.0 + options[Mission.Constraints.MAX_MACH] = 0.9 model.add_subsystem( 'design', - Design(aviary_options=AviaryValues(options)), + Design(**options), promotes_inputs=['*'], promotes_outputs=[Mission.Design.MACH, Mission.Design.LIFT_COEFFICIENT], ) @@ -134,14 +126,12 @@ def test_derivs_subsonic2(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) - assert_near_equal( - prob.get_val(Mission.Design.MACH), [0.740390], 1e-6) - assert_near_equal( - prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.753], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.MACH), [0.740390], 1e-6) + assert_near_equal(prob.get_val(Mission.Design.LIFT_COEFFICIENT), [0.753], 1e-6) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_drag.py b/aviary/subsystems/aerodynamics/flops_based/test/test_drag.py index 476c5cac33..d4d529020e 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_drag.py @@ -6,11 +6,7 @@ from parameterized import parameterized from aviary.subsystems.aerodynamics.flops_based.computed_aero_group import ComputedDrag -from aviary.subsystems.aerodynamics.flops_based.drag import ( - SimpleDrag, - SimpleCD, - TotalDrag, -) +from aviary.subsystems.aerodynamics.flops_based.drag import ScaledCD, SimpleDrag, TotalDrag from aviary.utils.aviary_values import AviaryValues from aviary.validation_cases.validation_tests import ( get_flops_case_names, @@ -20,12 +16,11 @@ from aviary.variable_info.variables import Aircraft, Dynamic data_sets = get_flops_case_names( - only=['LargeSingleAisle1FLOPS', 'LargeSingleAisle2FLOPS', 'N3CC'] + only=['LargeSingleAisle1FLOPS', 'LargeSingleAisle2FLOPS', 'advanced_single_aisle'] ) class SimpleDragTest(unittest.TestCase): - @parameterized.expand(data_sets, name_func=print_case) def test_case(self, case_name): flops_inputs = get_flops_inputs(case_name) @@ -44,14 +39,14 @@ def test_case(self, case_name): # dynamic pressure = 4 digits precision # drag coefficient = 5 digits precision mission_keys = ( - Dynamic.Mission.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'CD_prescaled', 'CD', - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, ) # drag = 4 digits precision - outputs_keys = (Dynamic.Mission.DRAG,) + outputs_keys = (Dynamic.Vehicle.DRAG,) # using lowest precision from all available data should "always" work # - will a higher precision comparison work? find a practical tolerance that fits @@ -61,10 +56,10 @@ def test_case(self, case_name): prob = om.Problem() model = prob.model - q, _ = mission_data.get_item(Dynamic.Mission.DYNAMIC_PRESSURE) + q, _ = mission_data.get_item(Dynamic.Atmosphere.DYNAMIC_PRESSURE) nn = len(q) model.add_subsystem('simple_drag', SimpleDrag(num_nodes=nn), promotes=['*']) - model.add_subsystem('simple_cd', SimpleCD(num_nodes=nn), promotes=['*']) + model.add_subsystem('simple_cd', ScaledCD(num_nodes=nn), promotes=['*']) prob.setup(force_alloc_complex=True) @@ -90,17 +85,14 @@ def test_case(self, case_name): raise ValueError(msg) from None - data = prob.check_partials(out_stream=None, method="cs") + data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(data, atol=2.5e-10, rtol=1e-12) - assert_near_equal(prob.get_val("CD"), mission_simple_CD[case_name], 1e-6) - assert_near_equal( - prob.get_val(Dynamic.Mission.DRAG), mission_simple_drag[case_name], 1e-6 - ) + assert_near_equal(prob.get_val('CD'), mission_simple_CD[case_name], 1e-6) + assert_near_equal(prob.get_val(Dynamic.Vehicle.DRAG), mission_simple_drag[case_name], 1e-6) class TotalDragTest(unittest.TestCase): - @parameterized.expand(data_sets, name_func=print_case) def test_case(self, case_name): flops_inputs = get_flops_inputs(case_name) @@ -121,14 +113,14 @@ def test_case(self, case_name): # dynamic pressure = 4 digits precision # drag coefficient = 5 digits precision mission_keys = ( - Dynamic.Mission.DYNAMIC_PRESSURE, - Dynamic.Mission.MACH, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.MACH, 'CD0', 'CDI', ) # drag = 4 digits precision - outputs_keys = ('CD_prescaled', 'CD', Dynamic.Mission.DRAG) + outputs_keys = ('CD_prescaled', 'CD', Dynamic.Vehicle.DRAG) # using lowest precision from all available data should "always" work # - will a higher precision comparison work? find a practical tolerance that fits @@ -138,7 +130,7 @@ def test_case(self, case_name): prob = om.Problem() model = prob.model - q, _ = mission_data.get_item(Dynamic.Mission.DYNAMIC_PRESSURE) + q, _ = mission_data.get_item(Dynamic.Atmosphere.DYNAMIC_PRESSURE) nn = len(q) model.add_subsystem('total_drag', TotalDrag(num_nodes=nn), promotes=['*']) @@ -166,17 +158,14 @@ def test_case(self, case_name): raise ValueError(msg) from None - data = prob.check_partials(out_stream=None, method="cs") + data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(data, atol=2.5e-10, rtol=1e-12) - assert_near_equal(prob.get_val("CD"), mission_total_CD[case_name], 1e-6) - assert_near_equal( - prob.get_val(Dynamic.Mission.DRAG), mission_total_drag[case_name], 1e-6 - ) + assert_near_equal(prob.get_val('CD'), mission_total_CD[case_name], 1e-6) + assert_near_equal(prob.get_val(Dynamic.Vehicle.DRAG), mission_total_drag[case_name], 1e-6) class ComputedDragTest(unittest.TestCase): - def test_derivs(self): nn = 2 @@ -193,7 +182,7 @@ def test_derivs(self): 'computed_drag', ComputedDrag(num_nodes=nn), promotes_inputs=['*'], - promotes_outputs=['CD', Dynamic.Mission.DRAG], + promotes_outputs=['CD', Dynamic.Vehicle.DRAG], ) prob.setup(force_alloc_complex=True) @@ -202,22 +191,22 @@ def test_derivs(self): prob.set_val('pressure_drag_coeff', 0.01 * cdp) prob.set_val('compress_drag_coeff', 0.01 * cdc) prob.set_val('induced_drag_coeff', 0.01 * cdi) - prob.set_val(Dynamic.Mission.MACH, M) + prob.set_val(Dynamic.Atmosphere.MACH, M) prob.set_val(Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, 0.7) prob.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 0.3) prob.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.4) prob.set_val(Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, 1.1) - prob.set_val(Aircraft.Wing.AREA, 1370, units="ft**2") - prob.set_val(Dynamic.Mission.DYNAMIC_PRESSURE, [206.0, 205.6], 'lbf/ft**2') + prob.set_val(Aircraft.Wing.AREA, 1370, units='ft**2') + prob.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [206.0, 205.6], 'lbf/ft**2') prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) - assert_near_equal(prob.get_val("CD"), [0.0249732, 0.0297451], 1e-6) - assert_near_equal(prob.get_val(Dynamic.Mission.DRAG), [31350.8, 37268.8], 1e-6) + assert_near_equal(prob.get_val('CD'), [0.0249732, 0.0297451], 1e-6) + assert_near_equal(prob.get_val(Dynamic.Vehicle.DRAG), [31350.8, 37268.8], 1e-6) # region - mission test data taken from the baseline FLOPS output for each case @@ -235,9 +224,7 @@ def _add_drag_coefficients( CD0_scaled: np.ndarray, CDI_scaled: np.ndarray, ): - ''' - Insert drag coefficients into the mission data, undoing FLOPS scaling. - ''' + """Insert drag coefficients into the mission data, undoing FLOPS scaling.""" flops_inputs = get_flops_inputs(case_name) FCDSUB = flops_inputs.get_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR) FCDSUP = flops_inputs.get_val(Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR) @@ -267,19 +254,17 @@ def _add_drag_coefficients( key = 'LargeSingleAisle1FLOPS' mission_test_data[key] = _mission_data = AviaryValues() _mission_data.set_val( - Dynamic.Mission.DYNAMIC_PRESSURE, np.array([206.0, 205.6, 205.4]), 'lbf/ft**2' + Dynamic.Atmosphere.DYNAMIC_PRESSURE, np.array([206.0, 205.6, 205.4]), 'lbf/ft**2' ) -_mission_data.set_val( - Dynamic.Mission.MASS, np.array([176751.0, 176400.0, 176185.0]), 'lbm' -) -_mission_data.set_val(Dynamic.Mission.DRAG, np.array([9350.0, 9333.0, 9323.0]), 'lbf') +_mission_data.set_val(Dynamic.Vehicle.MASS, np.array([176751.0, 176400.0, 176185.0]), 'lbm') +_mission_data.set_val(Dynamic.Vehicle.DRAG, np.array([9350.0, 9333.0, 9323.0]), 'lbf') M = np.array([0.7750, 0.7750, 0.7750]) CD_scaled = np.array([0.03313, 0.03313, 0.03313]) CD0_scaled = np.array([0.02012, 0.02013, 0.02013]) CDI_scaled = np.array([0.01301, 0.01301, 0.01300]) -_mission_data.set_val(Dynamic.Mission.MACH, M) +_mission_data.set_val(Dynamic.Atmosphere.MACH, M) _add_drag_coefficients(key, _mission_data, M, CD_scaled, CD0_scaled, CDI_scaled) mission_simple_CD[key] = np.array([0.03313, 0.03313, 0.03313]) @@ -289,18 +274,16 @@ def _add_drag_coefficients( key = 'LargeSingleAisle2FLOPS' mission_test_data[key] = _mission_data = AviaryValues() -_mission_data.set_val( - Dynamic.Mission.DYNAMIC_PRESSURE, [215.4, 215.4, 215.4], 'lbf/ft**2' -) -_mission_data.set_val(Dynamic.Mission.MASS, [169730.0, 169200.0, 167400.0], 'lbm') -_mission_data.set_val(Dynamic.Mission.DRAG, [9542.0, 9512.0, 9411.0], 'lbf') +_mission_data.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [215.4, 215.4, 215.4], 'lbf/ft**2') +_mission_data.set_val(Dynamic.Vehicle.MASS, [169730.0, 169200.0, 167400.0], 'lbm') +_mission_data.set_val(Dynamic.Vehicle.DRAG, [9542.0, 9512.0, 9411.0], 'lbf') M = np.array([0.7850, 0.7850, 0.7850]) CD_scaled = np.array([0.03304, 0.03293, 0.03258]) CD0_scaled = np.array([0.02016, 0.02016, 0.02016]) CDI_scaled = np.array([0.01288, 0.01277, 0.01242]) -_mission_data.set_val(Dynamic.Mission.MACH, M) +_mission_data.set_val(Dynamic.Atmosphere.MACH, M) _add_drag_coefficients(key, _mission_data, M, CD_scaled, CD0_scaled, CDI_scaled) mission_simple_CD[key] = np.array([0.03304, 0.03293, 0.03258]) @@ -308,20 +291,18 @@ def _add_drag_coefficients( mission_total_CD[key] = np.array([0.03304, 0.03293, 0.03258]) mission_total_drag[key] = np.array([42452.27140246, 42310.93514779, 41861.22888293]) -key = 'N3CC' +key = 'AdvancedSingleAisle' mission_test_data[key] = _mission_data = AviaryValues() -_mission_data.set_val( - Dynamic.Mission.DYNAMIC_PRESSURE, [208.4, 288.5, 364.0], 'lbf/ft**2' -) -_mission_data.set_val(Dynamic.Mission.MASS, [128777.0, 128721.0, 128667.0], 'lbm') -_mission_data.set_val(Dynamic.Mission.DRAG, [5837.0, 6551.0, 7566.0], 'lbf') +_mission_data.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [208.4, 288.5, 364.0], 'lbf/ft**2') +_mission_data.set_val(Dynamic.Vehicle.MASS, [128777.0, 128721.0, 128667.0], 'lbm') +_mission_data.set_val(Dynamic.Vehicle.DRAG, [5837.0, 6551.0, 7566.0], 'lbf') M = np.array([0.4522, 0.5321, 0.5985]) CD_scaled = np.array([0.02296, 0.01861, 0.01704]) CD0_scaled = np.array([0.01611, 0.01569, 0.01556]) CDI_scaled = np.array([0.00806, 0.00390, 0.00237]) -_mission_data.set_val(Dynamic.Mission.MACH, M) +_mission_data.set_val(Dynamic.Atmosphere.MACH, M) _add_drag_coefficients(key, _mission_data, M, CD_scaled, CD0_scaled, CDI_scaled) # endregion - mission test data taken from the baseline FLOPS output for each case @@ -331,5 +312,5 @@ def _add_drag_coefficients( mission_total_drag[key] = np.array([25968.341729, 29137.353709, 33647.401139]) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py b/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py index 2262993a75..793b67494a 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_ground_effect.py @@ -10,12 +10,12 @@ class TestGroundEffect(unittest.TestCase): - ''' + """ Perform regression test in all three computational ranges: - in ground effect (on the ground); - in transition (in the air, but near enough to the ground for limited effect); - in free flight (no ground effect). - ''' + """ def test_regression(self): prob: om.Problem = make_problem() @@ -24,7 +24,7 @@ def test_regression(self): tol = 1e-12 - for (key, (desired, units)) in get_items(_regression_data): + for key, (desired, units) in get_items(_regression_data): try: actual = prob.get_val(key, units) @@ -35,43 +35,43 @@ def test_regression(self): raise ValueError(msg) from None - partials = prob.check_partials(out_stream=None, method="cs") + partials = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partials, atol=1e-10, rtol=1e-12) - assert_near_equal( - prob.get_val("lift_coefficient"), [0.558234, 1.200676, 2.0], 1e-6) - assert_near_equal( - prob.get_val("drag_coefficient"), [0.02036, 0.0223957, 0.08], 1e-6) + assert_near_equal(prob.get_val('lift_coefficient'), [0.558234, 1.200676, 2.0], 1e-6) + assert_near_equal(prob.get_val('drag_coefficient'), [0.02036, 0.0223957, 0.08], 1e-6) def make_problem(): - ''' + """ Return a problem that covers all three computational ranges: - in ground effect (on the ground); - in transition (in the air, but near enough to the ground for limited effect); - in free flight (no ground effect). - ''' + """ nn = 3 - ground_altitude = 100. # units='m' + ground_altitude = 100.0 # units='m' minimum_drag_coefficient = (0.02036, 'unitless') base_lift_coefficient = (np.array([0.5, 1.2, 2.0]), 'unitless') - base_drag_coefficient = (np.array([0.02036, 1.1 * 0.02036, .08]), 'unitless') + base_drag_coefficient = (np.array([0.02036, 1.1 * 0.02036, 0.08]), 'unitless') aspect_ratio = (9.45, 'unitless') - height = (8., 'ft') - span = (34., 'm') - - inputs = AviaryValues({ - 'angle_of_attack': (np.array([0., 2., 6]), 'deg'), - Dynamic.Mission.ALTITUDE: (np.array([100.0, 132, 155]), 'm'), - Dynamic.Mission.FLIGHT_PATH_ANGLE: (np.array([0., 0.5, 1.0]), 'deg'), - 'minimum_drag_coefficient': minimum_drag_coefficient, - 'base_lift_coefficient': base_lift_coefficient, - 'base_drag_coefficient': base_drag_coefficient, - Aircraft.Wing.ASPECT_RATIO: aspect_ratio, - Aircraft.Wing.HEIGHT: height, - Aircraft.Wing.SPAN: span - }) + height = (8.0, 'ft') + span = (34.0, 'm') + + inputs = AviaryValues( + { + Dynamic.Vehicle.ANGLE_OF_ATTACK: (np.array([0.0, 2.0, 6]), 'deg'), + Dynamic.Mission.ALTITUDE: (np.array([100.0, 132, 155]), 'm'), + Dynamic.Mission.FLIGHT_PATH_ANGLE: (np.array([0.0, 0.5, 1.0]), 'deg'), + 'minimum_drag_coefficient': minimum_drag_coefficient, + 'base_lift_coefficient': base_lift_coefficient, + 'base_drag_coefficient': base_drag_coefficient, + Aircraft.Wing.ASPECT_RATIO: aspect_ratio, + Aircraft.Wing.HEIGHT: height, + Aircraft.Wing.SPAN: span, + } + ) ground_effect = GroundEffect(num_nodes=nn, ground_altitude=ground_altitude) @@ -79,7 +79,7 @@ def make_problem(): prob.model.add_subsystem('ground_effect', ground_effect, promotes=['*']) prob.setup(force_alloc_complex=True) - for (key, (val, units)) in inputs: + for key, (val, units) in inputs: prob.set_val(key, val, units) return prob @@ -90,13 +90,16 @@ def make_problem(): # - last generated 2023 June 7 # - generate new regression data if, and only if, ground effect is updated with a more # trusted implementation -_regression_data = AviaryValues(dict( - lift_coefficient=([0.5582336522780803, 1.200675778095871, 2.0], 'unitless'), - drag_coefficient=([0.02036, 0.022395716686151382, 0.08], 'unitless'))) +_regression_data = AviaryValues( + dict( + lift_coefficient=([0.5582336522780803, 1.200675778095871, 2.0], 'unitless'), + drag_coefficient=([0.02036, 0.022395716686151382, 0.08], 'unitless'), + ) +) def generate_regression_data(): - ''' + """ Generate regression data that covers all three computational ranges: - in ground effect (on the ground); - in transition (in the air, but near enough to the ground for limited effect); @@ -106,7 +109,7 @@ def generate_regression_data(): ----- Use this function to generate new regression data if, and only if, ground effect is updated with a more trusted implementation. - ''' + """ prob: om.Problem = make_problem() prob.run_model() @@ -114,11 +117,11 @@ def generate_regression_data(): lift_coefficient = prob.get_val('lift_coefficient') drag_coefficient = prob.get_val('drag_coefficient') - prob.check_partials(compact_print=True, method="cs") + prob.check_partials(compact_print=True, method='cs') print('lift_coefficient', *lift_coefficient, sep=', ') print('drag_coefficient', *drag_coefficient, sep=', ') -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_induced_drag.py b/aviary/subsystems/aerodynamics/flops_based/test/test_induced_drag.py index 8d5a34d1e3..cf162866dd 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_induced_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_induced_drag.py @@ -5,34 +5,33 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.subsystems.aerodynamics.flops_based.induced_drag import InducedDrag -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Aircraft, Dynamic class InducedDragTest(unittest.TestCase): - def test_derivs(self): P = 2.60239151 Sref = 1370.0 CL = np.array([0.3, 0.35, 0.4, 0.45, 0.5, 0.55]) mach = np.array([0.4, 0.45, 0.5, 0.55, 0.6, 0.85]) - lift = 0.5 * CL * Sref * 1.4 * P * mach ** 2 + lift = 0.5 * CL * Sref * 1.4 * P * mach**2 nn = len(CL) - prob = om.Problem(model=om.Group()) + prob = om.Problem() options = {} - options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] = (False, 'unitless') + options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] = False - prob.model.add_subsystem('induced_drag', InducedDrag( - num_nodes=nn, aviary_options=AviaryValues(options)), promotes=['*']) + prob.model.add_subsystem( + 'induced_drag', InducedDrag(num_nodes=nn, **options), promotes=['*'] + ) prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.LIFT, val=lift) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P) + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Vehicle.LIFT, val=lift) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P) prob.set_val(Aircraft.Wing.AREA, val=Sref) prob.set_val(Aircraft.Wing.SWEEP, val=-25.03) prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.278) @@ -42,11 +41,14 @@ def test_derivs(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=8e-12) assert_near_equal( - prob.get_val("induced_drag_coeff"), [0.00370367, 0.00504111, 0.0065843, 0.00833326, 0.01028797, 0.01244845], 1e-6) + prob.get_val('induced_drag_coeff'), + [0.00370367, 0.00504111, 0.0065843, 0.00833326, 0.01028797, 0.01244845], + 1e-6, + ) def test_derivs_span_eff_redux(self): P = 2.60239151 @@ -54,24 +56,23 @@ def test_derivs_span_eff_redux(self): CL = np.array([0.3, 0.35, 0.4, 0.45, 0.5, 0.55]) mach = np.array([0.4, 0.45, 0.5, 0.55, 0.6, 0.85]) - lift = 0.5 * CL * Sref * 1.4 * P * mach ** 2 + lift = 0.5 * CL * Sref * 1.4 * P * mach**2 nn = len(CL) # High factor - prob = om.Problem(model=om.Group()) + prob = om.Problem() options = {} - options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] = (True, 'unitless') + options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] = True - prob.model.add_subsystem('drag', InducedDrag( - num_nodes=nn, aviary_options=AviaryValues(options)), promotes=['*']) + prob.model.add_subsystem('drag', InducedDrag(num_nodes=nn, **options), promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.LIFT, val=lift) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P) + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Vehicle.LIFT, val=lift) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P) prob.set_val(Aircraft.Wing.AREA, val=Sref) prob.set_val(Aircraft.Wing.SWEEP, val=-25.10) prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.312) @@ -81,26 +82,28 @@ def test_derivs_span_eff_redux(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=8e-12) assert_near_equal( - prob.get_val("induced_drag_coeff"), [0.00216084, 0.00294208, 0.00384454, 0.00486925, 0.00601801, 0.00748097], 1e-6) + prob.get_val('induced_drag_coeff'), + [0.00216084, 0.00294208, 0.00384454, 0.00486925, 0.00601801, 0.00748097], + 1e-6, + ) # Low factor. prob = om.Problem(model=om.Group()) options = {} - options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] = (True, 'unitless') + options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] = True - prob.model.add_subsystem('drag', InducedDrag( - num_nodes=nn, aviary_options=AviaryValues(options)), promotes=['*']) + prob.model.add_subsystem('drag', InducedDrag(num_nodes=nn, **options), promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.LIFT, val=lift) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P) + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Vehicle.LIFT, val=lift) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P) prob.set_val(Aircraft.Wing.AREA, val=Sref) prob.set_val(Aircraft.Wing.SWEEP, val=-25.10) prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.312) @@ -110,12 +113,15 @@ def test_derivs_span_eff_redux(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=8e-12) assert_near_equal( - prob.get_val("induced_drag_coeff"), [0.00216084, 0.00294208, 0.00384454, 0.00486925, 0.00601801, 0.00748097], 1e-6) + prob.get_val('induced_drag_coeff'), + [0.00216084, 0.00294208, 0.00384454, 0.00486925, 0.00601801, 0.00748097], + 1e-6, + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_lift.py b/aviary/subsystems/aerodynamics/flops_based/test/test_lift.py index 65137fec34..4474a74771 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_lift.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_lift.py @@ -14,12 +14,11 @@ from aviary.variable_info.variables import Aircraft, Dynamic data_sets = get_flops_case_names( - only=['LargeSingleAisle1FLOPS', 'LargeSingleAisle2FLOPS', 'N3CC'] + only=['LargeSingleAisle1FLOPS', 'LargeSingleAisle2FLOPS', 'advanced_single_aisle'] ) class SimpleLiftTest(unittest.TestCase): - @parameterized.expand(data_sets, name_func=print_case) def test_case(self, case_name): flops_inputs = get_flops_inputs(case_name) @@ -31,10 +30,10 @@ def test_case(self, case_name): # dynamic pressure = 4 digits precision # lift coefficient = 5 digits precision - mission_keys = (Dynamic.Mission.DYNAMIC_PRESSURE, 'cl') + mission_keys = (Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'cl') # lift = 6 digits precision - outputs_keys = (Dynamic.Mission.LIFT,) + outputs_keys = (Dynamic.Vehicle.LIFT,) # use lowest precision from all available data tol = 1e-4 @@ -42,7 +41,7 @@ def test_case(self, case_name): prob = om.Problem() model = prob.model - q, _ = mission_data.get_item(Dynamic.Mission.DYNAMIC_PRESSURE) + q, _ = mission_data.get_item(Dynamic.Atmosphere.DYNAMIC_PRESSURE) nn = len(q) model.add_subsystem('simple_lift', SimpleLift(num_nodes=nn), promotes=['*']) @@ -70,16 +69,13 @@ def test_case(self, case_name): raise ValueError(msg) from None - data = prob.check_partials(out_stream=None, method="cs") + data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(data, atol=2.5e-10, rtol=1e-12) - assert_near_equal( - prob.get_val(Dynamic.Mission.LIFT), mission_simple_data[case_name], 1e-6 - ) + assert_near_equal(prob.get_val(Dynamic.Vehicle.LIFT), mission_simple_data[case_name], 1e-6) class LiftEqualsWeightTest(unittest.TestCase): - @parameterized.expand(data_sets, name_func=print_case) def test_case(self, case_name): flops_inputs = get_flops_inputs(case_name) @@ -91,11 +87,11 @@ def test_case(self, case_name): # dynamic pressure = 4 digits precision # mass = 6 digits precision - mission_keys = (Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.MASS) + mission_keys = (Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Vehicle.MASS) # lift coefficient = 5 digits precision # lift = 6 digits precision - outputs_keys = ('cl', Dynamic.Mission.LIFT) + outputs_keys = ('cl', Dynamic.Vehicle.LIFT) # use lowest precision from all available data tol = 1e-4 @@ -103,12 +99,10 @@ def test_case(self, case_name): prob = om.Problem() model = prob.model - q, _ = mission_data.get_item(Dynamic.Mission.DYNAMIC_PRESSURE) + q, _ = mission_data.get_item(Dynamic.Atmosphere.DYNAMIC_PRESSURE) nn = len(q) - model.add_subsystem( - 'lift_equals_weight', LiftEqualsWeight(num_nodes=nn), promotes=['*'] - ) + model.add_subsystem('lift_equals_weight', LiftEqualsWeight(num_nodes=nn), promotes=['*']) prob.setup(force_alloc_complex=True) @@ -134,12 +128,10 @@ def test_case(self, case_name): raise ValueError(msg) from None - data = prob.check_partials(out_stream=None, method="cs") + data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(data, atol=2.5e-10, rtol=1e-12) - assert_near_equal( - prob.get_val(Dynamic.Mission.LIFT), mission_equal_data[case_name], 1e-6 - ) + assert_near_equal(prob.get_val(Dynamic.Vehicle.LIFT), mission_equal_data[case_name], 1e-6) # dynamic test data taken from the baseline FLOPS output for each case @@ -151,35 +143,29 @@ def test_case(self, case_name): mission_equal_data = {} mission_test_data['LargeSingleAisle1FLOPS'] = _mission_data = AviaryValues() -_mission_data.set_val( - Dynamic.Mission.DYNAMIC_PRESSURE, [206.0, 205.6, 205.4], 'lbf/ft**2' -) +_mission_data.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [206.0, 205.6, 205.4], 'lbf/ft**2') _mission_data.set_val('cl', [0.62630, 0.62623, 0.62619]) -_mission_data.set_val(Dynamic.Mission.LIFT, [176751.0, 176400.0, 176185.0], 'lbf') -_mission_data.set_val(Dynamic.Mission.MASS, [176751.0, 176400.0, 176185.0], 'lbm') +_mission_data.set_val(Dynamic.Vehicle.LIFT, [176751.0, 176400.0, 176185.0], 'lbf') +_mission_data.set_val(Dynamic.Vehicle.MASS, [176751.0, 176400.0, 176185.0], 'lbm') mission_simple_data['LargeSingleAisle1FLOPS'] = [786242.68, 784628.29, 783814.96] mission_equal_data['LargeSingleAisle1FLOPS'] = [786227.62, 784666.29, 783709.93] mission_test_data['LargeSingleAisle2FLOPS'] = _mission_data = AviaryValues() -_mission_data.set_val( - Dynamic.Mission.DYNAMIC_PRESSURE, [215.4, 215.4, 215.4], 'lbf/ft**2' -) +_mission_data.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [215.4, 215.4, 215.4], 'lbf/ft**2') _mission_data.set_val('cl', [0.58761, 0.58578, 0.57954]) -_mission_data.set_val(Dynamic.Mission.LIFT, [169730.0, 169200.0, 167400.0], 'lbf') -_mission_data.set_val(Dynamic.Mission.MASS, [169730.0, 169200.0, 167400.0], 'lbm') +_mission_data.set_val(Dynamic.Vehicle.LIFT, [169730.0, 169200.0, 167400.0], 'lbf') +_mission_data.set_val(Dynamic.Vehicle.MASS, [169730.0, 169200.0, 167400.0], 'lbm') mission_simple_data['LargeSingleAisle2FLOPS'] = [755005.42, 752654.10, 744636.48] mission_equal_data['LargeSingleAisle2FLOPS'] = [754996.65, 752639.10, 744632.30] -mission_test_data['N3CC'] = _mission_data = AviaryValues() -_mission_data.set_val( - Dynamic.Mission.DYNAMIC_PRESSURE, [208.4, 288.5, 364.0], 'lbf/ft**2' -) +mission_test_data['advanced_single_aisle'] = _mission_data = AviaryValues() +_mission_data.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [208.4, 288.5, 364.0], 'lbf/ft**2') _mission_data.set_val('cl', [0.50651, 0.36573, 0.28970]) -_mission_data.set_val(Dynamic.Mission.LIFT, [128777.0, 128721.0, 128667.0], 'lbf') -_mission_data.set_val(Dynamic.Mission.MASS, [128777.0, 128721.0, 128667.0], 'lbm') -mission_simple_data['N3CC'] = [572838.22, 572601.72, 572263.60] -mission_equal_data['N3CC'] = [572828.63, 572579.53, 572339.33] +_mission_data.set_val(Dynamic.Vehicle.LIFT, [128777.0, 128721.0, 128667.0], 'lbf') +_mission_data.set_val(Dynamic.Vehicle.MASS, [128777.0, 128721.0, 128667.0], 'lbm') +mission_simple_data['advanced_single_aisle'] = [572838.22, 572601.72, 572263.60] +mission_equal_data['advanced_single_aisle'] = [572828.63, 572579.53, 572339.33] -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_lift_dependent_drag.py b/aviary/subsystems/aerodynamics/flops_based/test/test_lift_dependent_drag.py index e02606f6d5..e811b8f103 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_lift_dependent_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_lift_dependent_drag.py @@ -4,22 +4,19 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.flops_based.lift_dependent_drag import \ - LiftDependentDrag +from aviary.subsystems.aerodynamics.flops_based.lift_dependent_drag import LiftDependentDrag from aviary.variable_info.variables import Aircraft, Dynamic, Mission class LiftDependentDragTest(unittest.TestCase): - def test_derivs_edge_interp(self): - # Pressure in lbf/in**2 at 41000 ft. P = 2.60239151 Sref = 1370.0 CL = np.array([0.3, 0.35, 0.4, 0.45, 0.5, 0.55]) mach = np.array([0.4, 0.45, 0.5, 0.55, 0.6, 0.85]) - lift = 0.5 * CL * Sref * 1.4 * P * mach ** 2 + lift = 0.5 * CL * Sref * 1.4 * P * mach**2 nn = len(CL) @@ -27,9 +24,9 @@ def test_derivs_edge_interp(self): prob.model.add_subsystem('drag', LiftDependentDrag(num_nodes=nn), promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.LIFT, val=lift) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P) + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Vehicle.LIFT, val=lift) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P) prob.set_val(Aircraft.Wing.AREA, val=Sref) prob.set_val(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, val=1.0) prob.set_val(Aircraft.Wing.SWEEP, val=25.03) @@ -42,21 +39,23 @@ def test_derivs_edge_interp(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) assert_near_equal( - prob.get_val("CD"), [0.01445345, 0.01278088, 0.01124887, 0.00982434, 0.00844742, 0.0], 1e-6) + prob.get_val('CD'), + [0.01445345, 0.01278088, 0.01124887, 0.00982434, 0.00844742, 0.0], + 1e-6, + ) def test_derivs_inner_interp(self): - # Pressure in lbf/in**2 at 41000 ft. P = 2.60239151 Sref = 1370.0 CL = np.array([0.3, 0.35, 0.4, 0.45, 0.5, 0.55]) mach = np.array([0.4, 0.45, 0.5, 0.55, 0.6, 0.85]) - lift = 0.5 * CL * Sref * 1.4 * P * mach ** 2 + lift = 0.5 * CL * Sref * 1.4 * P * mach**2 nn = len(CL) @@ -64,9 +63,9 @@ def test_derivs_inner_interp(self): prob.model.add_subsystem('drag', LiftDependentDrag(num_nodes=nn), promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.MACH, val=mach) - prob.set_val(Dynamic.Mission.LIFT, val=lift) - prob.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P) + prob.set_val(Dynamic.Atmosphere.MACH, val=mach) + prob.set_val(Dynamic.Vehicle.LIFT, val=lift) + prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P) prob.set_val(Aircraft.Wing.AREA, val=Sref) prob.set_val(Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, val=1.0) prob.set_val(Aircraft.Wing.SWEEP, val=25.07) @@ -79,12 +78,15 @@ def test_derivs_inner_interp(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) assert_near_equal( - prob.get_val("CD"), [0.01333307, 0.02305564, 0.0465636, 0.51400999, 0.79391369, 0.82316212], 1e-6) + prob.get_val('CD'), + [0.01333307, 0.02305564, 0.0465636, 0.51400999, 0.79391369, 0.82316212], + 1e-6, + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_mux_component.py b/aviary/subsystems/aerodynamics/flops_based/test/test_mux_component.py index e26321f57b..0a9fd2ca33 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_mux_component.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_mux_component.py @@ -2,28 +2,24 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.assert_utils import assert_check_partials +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.subsystems.aerodynamics.flops_based.mux_component import MuxComponent -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Aircraft class TestMuxComponent(unittest.TestCase): - def test_mux(self): prob = om.Problem() model = prob.model - aviary_options = AviaryValues() - aviary_options.set_val(Aircraft.VerticalTail.NUM_TAILS, 1) - aviary_options.set_val(Aircraft.Fuselage.NUM_FUSELAGES, 1) - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + aviary_options = { + Aircraft.Engine.NUM_ENGINES: np.array([2]), + Aircraft.Fuselage.NUM_FUSELAGES: 1, + Aircraft.VerticalTail.NUM_TAILS: 1, + } - model.add_subsystem( - 'mux', MuxComponent(aviary_options=aviary_options), - promotes_inputs=['*']) + model.add_subsystem('mux', MuxComponent(**aviary_options), promotes_inputs=['*']) prob.setup(force_alloc_complex=True) @@ -58,16 +54,16 @@ def test_mux(self): prob.set_val(Aircraft.Nacelle.LAMINAR_FLOW_LOWER, np.array([0.10])) prob.run_model() - prob.check_partials(compact_print=True, method="cs") + prob.check_partials(compact_print=True, method='cs') - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) # Truth values for each variable - wetted_areas_truth = np.array([2., 12., 22., 32., 42., 42.]) - fineness_ratios_truth = np.array([3., 13., 23., 33., 43., 43.]) - characteristic_lengths_truth = np.array([4., 14., 24., 34., 44., 44.]) + wetted_areas_truth = np.array([2.0, 12.0, 22.0, 32.0, 42.0, 42.0]) + fineness_ratios_truth = np.array([3.0, 13.0, 23.0, 33.0, 43.0, 43.0]) + characteristic_lengths_truth = np.array([4.0, 14.0, 24.0, 34.0, 44.0, 44.0]) laminar_fractions_upper_truth = np.array([0.01, 0.03, 0.05, 0.07, 0.09, 0.09]) laminar_fractions_lower_truth = np.array([0.02, 0.04, 0.06, 0.08, 0.1, 0.1]) @@ -80,25 +76,21 @@ def test_mux(self): # Assert that the outputs are near the expected values assert_near_equal(wetted_areas_output, wetted_areas_truth, 1e-7) assert_near_equal(fineness_ratios_output, fineness_ratios_truth, 1e-7) - assert_near_equal(characteristic_lengths_output, - characteristic_lengths_truth, 1e-7) - assert_near_equal(laminar_fractions_upper_output, - laminar_fractions_upper_truth, 1e-7) - assert_near_equal(laminar_fractions_lower_output, - laminar_fractions_lower_truth, 1e-7) + assert_near_equal(characteristic_lengths_output, characteristic_lengths_truth, 1e-7) + assert_near_equal(laminar_fractions_upper_output, laminar_fractions_upper_truth, 1e-7) + assert_near_equal(laminar_fractions_lower_output, laminar_fractions_lower_truth, 1e-7) def test_mux_multiengine(self): prob = om.Problem() model = prob.model - aviary_options = AviaryValues() - aviary_options.set_val(Aircraft.VerticalTail.NUM_TAILS, 1) - aviary_options.set_val(Aircraft.Fuselage.NUM_FUSELAGES, 1) - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 3])) + aviary_options = { + Aircraft.Engine.NUM_ENGINES: np.array([2, 3]), + Aircraft.Fuselage.NUM_FUSELAGES: 1, + Aircraft.VerticalTail.NUM_TAILS: 1, + } - model.add_subsystem( - 'mux', MuxComponent(aviary_options=aviary_options), - promotes_inputs=['*']) + model.add_subsystem('mux', MuxComponent(**aviary_options), promotes_inputs=['*']) prob.setup(force_alloc_complex=True) @@ -133,21 +125,24 @@ def test_mux_multiengine(self): prob.set_val(Aircraft.Nacelle.LAMINAR_FLOW_LOWER, np.array([0.10, 0.04])) prob.run_model() - prob.check_partials(compact_print=True, method="cs") + prob.check_partials(compact_print=True, method='cs') - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') assert_check_partials(derivs, atol=1e-12, rtol=1e-12) # Truth values for each variable - wetted_areas_truth = np.array([2., 12., 22., 32., 42., 42., 33.5, 33.5, 33.5]) - fineness_ratios_truth = np.array([3., 13., 23., 33., 43., 43., 37.0, 37.0, 37.0]) + wetted_areas_truth = np.array([2.0, 12.0, 22.0, 32.0, 42.0, 42.0, 33.5, 33.5, 33.5]) + fineness_ratios_truth = np.array([3.0, 13.0, 23.0, 33.0, 43.0, 43.0, 37.0, 37.0, 37.0]) characteristic_lengths_truth = np.array( - [4., 14., 24., 34., 44., 44., 30.0, 30.0, 30.0]) + [4.0, 14.0, 24.0, 34.0, 44.0, 44.0, 30.0, 30.0, 30.0] + ) laminar_fractions_upper_truth = np.array( - [0.01, 0.03, 0.05, 0.07, 0.09, 0.09, 0.13, 0.13, 0.13]) + [0.01, 0.03, 0.05, 0.07, 0.09, 0.09, 0.13, 0.13, 0.13] + ) laminar_fractions_lower_truth = np.array( - [0.02, 0.04, 0.06, 0.08, 0.1, 0.1, 0.04, 0.04, 0.04]) + [0.02, 0.04, 0.06, 0.08, 0.1, 0.1, 0.04, 0.04, 0.04] + ) wetted_areas_output = prob['mux.wetted_areas'] fineness_ratios_output = prob['mux.fineness_ratios'] @@ -158,15 +153,12 @@ def test_mux_multiengine(self): # Assert that the outputs are near the expected values assert_near_equal(wetted_areas_output, wetted_areas_truth, 1e-7) assert_near_equal(fineness_ratios_output, fineness_ratios_truth, 1e-7) - assert_near_equal(characteristic_lengths_output, - characteristic_lengths_truth, 1e-7) - assert_near_equal(laminar_fractions_upper_output, - laminar_fractions_upper_truth, 1e-7) - assert_near_equal(laminar_fractions_lower_output, - laminar_fractions_lower_truth, 1e-7) + assert_near_equal(characteristic_lengths_output, characteristic_lengths_truth, 1e-7) + assert_near_equal(laminar_fractions_upper_output, laminar_fractions_upper_truth, 1e-7) + assert_near_equal(laminar_fractions_lower_output, laminar_fractions_lower_truth, 1e-7) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = TestMuxComponent() # test.test_mux_multiengine() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_coef.py b/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_coef.py index cbb63666b2..9097f4b4cf 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_coef.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_coef.py @@ -5,17 +5,15 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.subsystems.aerodynamics.flops_based.skin_friction import SkinFriction -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Aircraft class SkinFrictionCoeffTest(unittest.TestCase): - def test_derivs(self): n = 12 nc = 3 - machs = np.array([.2, .3, .4, .5, .6, .7, .75, .775, .8, .825, .85, .875]) + machs = np.array([0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.75, 0.775, 0.8, 0.825, 0.85, 0.875]) lens = np.linspace(1, 2, nc) temp = np.ones(n) * 389.97 pres = np.ones(n) * 2.60239151 @@ -24,12 +22,11 @@ def test_derivs(self): model = prob.model options = {} - options[Aircraft.VerticalTail.NUM_TAILS] = (0, 'unitless') - options[Aircraft.Fuselage.NUM_FUSELAGES] = (1, 'unitless') - options[Aircraft.Engine.NUM_ENGINES] = ([0], 'unitless') + options[Aircraft.VerticalTail.NUM_TAILS] = 0 + options[Aircraft.Fuselage.NUM_FUSELAGES] = 1 + options[Aircraft.Engine.NUM_ENGINES] = [0] - model.add_subsystem( - 'cf', SkinFriction(num_nodes=n, aviary_options=AviaryValues(options)), promotes=['*']) + model.add_subsystem('cf', SkinFriction(num_nodes=n, **options), promotes=['*']) prob.setup(force_alloc_complex=True) @@ -44,76 +41,80 @@ def test_derivs(self): # Atol set higher because some derivs are on the order 1e7 assert_check_partials(derivs, atol=1e-08, rtol=1e-12) - expected_ct_iter = np.array([ - [0.01898115, 0.01659121, 0.01513528], - [0.01683023, 0.01479386, 0.01354618], - [0.01552035, 0.01369303, 0.01256915], - [0.01462014, 0.01293339, 0.01189309], - [0.01395886, 0.01237359, 0.01139382], - [0.01345288, 0.01194415, 0.01101014], - [0.01324268, 0.01176543, 0.01085027], - [0.0131464, 0.0116835, 0.01077695], - [0.01305543, 0.01160606, 0.01070762], - [0.0129694, 0.01153279, 0.010642], - [0.01288799, 0.01146341, 0.01057985], - [0.0128109, 0.01139768, 0.01052094], - ]) - expected_skin_cf = np.array([ - [0.02081979, 0.01830256, 0.01676351], - [0.01812046, 0.01601054, 0.01471376], - [0.01644993, 0.01458313, 0.01343178], - [0.01526502, 0.01356561, 0.01251483], - [0.01435403, 0.01277992, 0.01180471], - [0.01361502, 0.01214004, 0.01122482], - [0.01329152, 0.01185913, 0.01096975], - [0.01313905, 0.01172656, 0.01084927], - [0.01299212, 0.0115987, 0.010733], - [0.01285029, 0.01147518, 0.01062061], - [0.0127132, 0.01135567, 0.01051181], - [0.0125805, 0.0112399, 0.01040636], - ]) - expected_re = np.array([ - [2535.112674, 3802.669010, 5070.225348], - [3802.669010, 5704.003516, 7605.338022], - [5070.225348, 7605.338021, 10140.450696], - [6337.781685, 9506.67253, 12675.563370], - [7605.338021, 11408.007033, 15210.676043], - [8872.894359, 13309.341538, 17745.788718], - [9506.672527, 14260.008791, 19013.345055], - [9823.561612, 14735.342417, 19647.123223], - [10140.450696, 15210.676044, 20280.901392], - [10457.339780, 15686.009670, 20914.679560], - [10774.228864, 16161.343297, 21548.457729], - [11091.117949, 16636.676923, 22182.235897], - ]) - expected_wall_temp = np.array([ - [312.2257434, 307.72648885, 304.58447993], - [325.53580719, 321.38549197, 318.47318481], - [336.14581431, 332.22311052, 329.46157595], - [345.77748172, 341.9998021, 339.33440433], - [355.19308974, 351.49805053, 348.88701044], - [364.78724817, 361.12449161, 358.53377984], - [369.724644, 366.0616753, 363.47001514], - [372.23709293, 368.57026339, 365.97557009], - [374.78120136, 371.10811275, 368.50874977], - [377.35853852, 373.67686302, 371.07124056], - [379.97046618, 376.27794052, 373.6645118], - [382.61816115, 378.91258145, 376.2898394], - ]) - assert_near_equal( - prob.get_val('cf_iter'), expected_ct_iter, 1e-6) - assert_near_equal( - prob.get_val('skin_friction_coeff'), expected_skin_cf, 1e-6) - assert_near_equal( - prob.get_val('Re'), expected_re, 1e-6) - assert_near_equal( - prob.get_val('wall_temp'), expected_wall_temp, 1e-6) + expected_ct_iter = np.array( + [ + [0.01898115, 0.01659121, 0.01513528], + [0.01683023, 0.01479386, 0.01354618], + [0.01552035, 0.01369303, 0.01256915], + [0.01462014, 0.01293339, 0.01189309], + [0.01395886, 0.01237359, 0.01139382], + [0.01345288, 0.01194415, 0.01101014], + [0.01324268, 0.01176543, 0.01085027], + [0.0131464, 0.0116835, 0.01077695], + [0.01305543, 0.01160606, 0.01070762], + [0.0129694, 0.01153279, 0.010642], + [0.01288799, 0.01146341, 0.01057985], + [0.0128109, 0.01139768, 0.01052094], + ] + ) + expected_skin_cf = np.array( + [ + [0.02081979, 0.01830256, 0.01676351], + [0.01812046, 0.01601054, 0.01471376], + [0.01644993, 0.01458313, 0.01343178], + [0.01526502, 0.01356561, 0.01251483], + [0.01435403, 0.01277992, 0.01180471], + [0.01361502, 0.01214004, 0.01122482], + [0.01329152, 0.01185913, 0.01096975], + [0.01313905, 0.01172656, 0.01084927], + [0.01299212, 0.0115987, 0.010733], + [0.01285029, 0.01147518, 0.01062061], + [0.0127132, 0.01135567, 0.01051181], + [0.0125805, 0.0112399, 0.01040636], + ] + ) + expected_re = np.array( + [ + [2535.112674, 3802.669010, 5070.225348], + [3802.669010, 5704.003516, 7605.338022], + [5070.225348, 7605.338021, 10140.450696], + [6337.781685, 9506.67253, 12675.563370], + [7605.338021, 11408.007033, 15210.676043], + [8872.894359, 13309.341538, 17745.788718], + [9506.672527, 14260.008791, 19013.345055], + [9823.561612, 14735.342417, 19647.123223], + [10140.450696, 15210.676044, 20280.901392], + [10457.339780, 15686.009670, 20914.679560], + [10774.228864, 16161.343297, 21548.457729], + [11091.117949, 16636.676923, 22182.235897], + ] + ) + expected_wall_temp = np.array( + [ + [312.2257434, 307.72648885, 304.58447993], + [325.53580719, 321.38549197, 318.47318481], + [336.14581431, 332.22311052, 329.46157595], + [345.77748172, 341.9998021, 339.33440433], + [355.19308974, 351.49805053, 348.88701044], + [364.78724817, 361.12449161, 358.53377984], + [369.724644, 366.0616753, 363.47001514], + [372.23709293, 368.57026339, 365.97557009], + [374.78120136, 371.10811275, 368.50874977], + [377.35853852, 373.67686302, 371.07124056], + [379.97046618, 376.27794052, 373.6645118], + [382.61816115, 378.91258145, 376.2898394], + ] + ) + assert_near_equal(prob.get_val('cf_iter'), expected_ct_iter, 1e-6) + assert_near_equal(prob.get_val('skin_friction_coeff'), expected_skin_cf, 1e-6) + assert_near_equal(prob.get_val('Re'), expected_re, 1e-6) + assert_near_equal(prob.get_val('wall_temp'), expected_wall_temp, 1e-6) def test_derivs_multiengine(self): n = 12 nc = 9 - machs = np.array([.2, .3, .4, .5, .6, .7, .75, .775, .8, .825, .85, .875]) + machs = np.array([0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.75, 0.775, 0.8, 0.825, 0.85, 0.875]) lens = np.linspace(1, 2, nc) temp = np.ones(n) * 389.97 pres = np.ones(n) * 2.60239151 @@ -122,12 +123,11 @@ def test_derivs_multiengine(self): model = prob.model options = {} - options[Aircraft.VerticalTail.NUM_TAILS] = (0, 'unitless') - options[Aircraft.Fuselage.NUM_FUSELAGES] = (1, 'unitless') - options[Aircraft.Engine.NUM_ENGINES] = ([2, 4], 'unitless') + options[Aircraft.VerticalTail.NUM_TAILS] = 0 + options[Aircraft.Fuselage.NUM_FUSELAGES] = 1 + options[Aircraft.Engine.NUM_ENGINES] = [2, 4] - model.add_subsystem( - 'cf', SkinFriction(num_nodes=n, aviary_options=AviaryValues(options)), promotes=['*']) + model.add_subsystem('cf', SkinFriction(num_nodes=n, **options), promotes=['*']) prob.setup(force_alloc_complex=True) @@ -142,137 +142,230 @@ def test_derivs_multiengine(self): # Atol set higher because some derivs are on the order 1e7 assert_check_partials(derivs, atol=1e-08, rtol=1e-12) - expected_ct_iter = np.array([ - [0.01898115, 0.01824181, 0.01761276, 0.01706852, 0.01659121, 0.01616784, - 0.01578872, 0.01544645, 0.01513528], - [0.01683023, 0.01620174, 0.01566599, 0.01520168, 0.01479386, 0.01443163, - 0.01410686, 0.01381333, 0.01354618], - [0.01552035, 0.01495726, 0.01447664, 0.01405966, 0.01369303, 0.0133671, - 0.01307463, 0.01281008, 0.01256915], - [0.01462014, 0.01410095, 0.0136574, 0.01327226, 0.01293339, 0.01263193, - 0.01236126, 0.0121163, 0.01189309], - [0.01395886, 0.01347133, 0.01305453, 0.0126924, 0.01237359, 0.01208984, - 0.01183496, 0.01160419, 0.01139382], - [0.01345288, 0.0129892, 0.01259257, 0.0122478, 0.01194415, 0.01167378, - 0.01143082, 0.01121078, 0.01101014], - [0.01324268, 0.0127888, 0.01240047, 0.01206285, 0.01176543, 0.01150057, - 0.01126253, 0.01104691, 0.01085027], - [0.0131464, 0.01269699, 0.01231244, 0.01197807, 0.0116835, 0.01142116, - 0.01118536, 0.01097176, 0.01077695], - [0.01305543, 0.01261023, 0.01222925, 0.01189795, 0.01160606, 0.01134608, - 0.0111124, 0.0109007, 0.01070762], - [0.0129694, 0.01252817, 0.01215056, 0.01182215, 0.01153279, 0.01127505, - 0.01104336, 0.01083345, 0.010642], - [0.01288799, 0.01245051, 0.01207606, 0.01175039, 0.01146341, 0.01120778, - 0.01097797, 0.01076977, 0.01057985], - [0.0128109, 0.01237695, 0.01200549, 0.0116824, 0.01139768, 0.01114404, - 0.01091602, 0.01070941, 0.01052094], - ]) - expected_skin_cf = np.array([ - [0.02081979, 0.02004218, 0.01937982, 0.01880616, 0.01830256, 0.01785549, - 0.01745483, 0.01709284, 0.01676351], - [0.01812046, 0.01747006, 0.01691509, 0.01643371, 0.01601054, 0.01563439, - 0.01529692, 0.0149917, 0.01471376], - [0.01644993, 0.0158753, 0.0153844, 0.01495817, 0.01458313, 0.0142495, - 0.01394994, 0.01367883, 0.01343178], - [0.01526502, 0.01474245, 0.01429566, 0.01390743, 0.01356561, 0.01326134, - 0.01298799, 0.01274048, 0.01251483], - [0.01435403, 0.01387038, 0.0134566, 0.01309684, 0.01277992, 0.01249769, - 0.01224403, 0.01201426, 0.01180471], - [0.01361502, 0.01316212, 0.01277444, 0.01243722, 0.01214004, 0.01187528, - 0.01163725, 0.01142157, 0.01122482], - [0.01329152, 0.01285181, 0.01247535, 0.01214782, 0.01185913, 0.0116019, - 0.0113706, 0.01116099, 0.01096975], - [0.01313905, 0.01270551, 0.01233428, 0.01201128, 0.01172656, 0.01147285, - 0.0112447, 0.01103793, 0.01084927], - [0.01299212, 0.01256448, 0.01219827, 0.01187961, 0.0115987, 0.01134836, - 0.01112323, 0.01091918, 0.010733], - [0.01285029, 0.01242832, 0.01206693, 0.01175244, 0.01147518, 0.01122808, - 0.01100584, 0.01080442, 0.01062061], - [0.0127132, 0.01229667, 0.01193991, 0.01162943, 0.01135567, 0.01111169, - 0.01089225, 0.01069333, 0.01051181], - [0.0125805, 0.01216921, 0.01181691, 0.01151028, 0.0112399, 0.01099892, - 0.01078216, 0.01058567, 0.01040636], - ]) - expected_re = np.array([ - [2535.11267397, 2852.00175822, 3168.89084247, 3485.77992671, - 3802.66901096, 4119.55809521, 4436.44717945, 4753.3362637, - 5070.22534795], - [3802.66901096, 4278.00263733, 4753.3362637, 5228.66989007, - 5704.00351644, 6179.33714281, 6654.67076918, 7130.00439555, - 7605.33802192], - [5070.22534795, 5704.00351644, 6337.78168493, 6971.55985343, - 7605.33802192, 8239.11619041, 8872.89435891, 9506.6725274, - 10140.45069589], - [6337.78168493, 7130.00439555, 7922.22710617, 8714.44981678, - 9506.6725274, 10298.89523802, 11091.11794863, 11883.34065925, - 12675.56336987], - [7605.33802192, 8556.00527466, 9506.6725274, 10457.33978014, - 11408.00703288, 12358.67428562, 13309.34153836, 14260.0087911, - 15210.67604384], - [8872.89435891, 9982.00615377, 11091.11794863, 12200.2297435, - 13309.34153836, 14418.45333323, 15527.56512809, 16636.67692295, - 17745.78871782], - [9506.6725274, 10695.00659333, 11883.34065925, 13071.67472518, - 14260.0087911, 15448.34285703, 16636.67692295, 17825.01098888, - 19013.3450548], - [9823.56161165, 11051.5068131, 12279.45201456, 13507.39721602, - 14735.34241747, 15963.28761893, 17191.23282038, 18419.17802184, - 19647.1232233], - [10140.45069589, 11408.00703288, 12675.56336987, 13943.11970686, - 15210.67604384, 16478.23238083, 17745.78871782, 19013.3450548, - 20280.90139179], - [10457.33978014, 11764.50725266, 13071.67472518, 14378.84219769, - 15686.00967021, 16993.17714273, 18300.34461525, 19607.51208776, - 20914.67956028], - [10774.22886439, 12121.00747244, 13467.78608048, 14814.56468853, - 16161.34329658, 17508.12190463, 18854.90051268, 20201.67912073, - 21548.45772878], - [11091.11794863, 12477.50769221, 13863.89743579, 15250.28717937, - 16636.67692295, 18023.06666653, 19409.45641011, 20795.84615369, - 22182.23589727], - ]) - expected_wall_temp = np.array([ - [312.2257434, 310.91072134, 309.73985349, 308.68528692, 307.72648885, - 306.84789293, 306.03742045, 305.28551328, 304.58447993], - [325.53580719, 324.32521822, 323.24563283, 322.27191154, 321.38549197, - 320.57228106, 319.82132882, 319.12395976, 318.47318481], - [336.14581431, 335.00316978, 333.98309588, 333.06217839, 332.22311052, - 331.45273996, 330.7408387, 330.07929681, 329.46157595], - [345.77748172, 344.67810867, 343.69595071, 342.8086856, 341.9998021, - 341.25674448, 340.56974301, 339.93104691, 339.33440433], - [355.19308974, 354.11844249, 353.15790517, 352.28979071, 351.49805053, - 350.77047571, 350.09756276, 349.47176953, 348.88701044], - [364.78724817, 363.72241041, 362.77035004, 361.90965915, 361.12449161, - 360.40278964, 359.73516534, 359.11416672, 358.53377984], - [369.724644, 368.65987786, 367.70778972, 366.8469981, 366.0616753, - 365.33977678, 364.67192433, 364.05067326, 363.47001514], - [372.23709293, 371.17125423, 370.21817293, 369.35645507, 368.57026339, - 367.84754578, 367.17891796, 366.55693025, 365.97557009], - [374.78120136, 373.71358252, 372.75888265, 371.895679, 371.10811275, - 370.38411524, 369.71428915, 369.09117435, 368.50874977], - [377.35853852, 376.28845297, 375.33152752, 374.46629484, 373.67686302, - 372.95113807, 372.27970293, 371.6550817, 371.07124056], - [379.97046618, 378.89724658, 377.93750541, 377.06971548, 376.27794052, - 375.55005281, 374.87660896, 374.2501122, 373.6645118], - [382.61816115, 381.5411578, 380.5780263, 379.70716469, 378.91258145, - 378.18210689, 377.50626497, 376.87753302, 376.2898394], - ]) - assert_near_equal( - prob.get_val('cf_iter'), expected_ct_iter, 1e-6) - assert_near_equal( - prob.get_val('skin_friction_coeff'), expected_skin_cf, 1e-6) - assert_near_equal( - prob.get_val('Re'), expected_re, 1e-6) - assert_near_equal( - prob.get_val('wall_temp'), expected_wall_temp, 1e-6) + # fmt: off + expected_ct_iter = np.array( + [ + [ + 0.01898115, 0.01824181, 0.01761276, 0.01706852, 0.01659121, + 0.01616784, 0.01578872, 0.01544645, 0.01513528, + ], + [ + 0.01683023, 0.01620174, 0.01566599, 0.01520168, 0.01479386, + 0.01443163, 0.01410686, 0.01381333, 0.01354618, + ], + [ + 0.01552035, 0.01495726, 0.01447664, 0.01405966, 0.01369303, + 0.0133671, 0.01307463, 0.01281008, 0.01256915, + ], + [ + 0.01462014, 0.01410095, 0.0136574, 0.01327226, 0.01293339, + 0.01263193, 0.01236126, 0.0121163, 0.01189309, + ], + [ + 0.01395886, 0.01347133, 0.01305453, 0.0126924, 0.01237359, + 0.01208984, 0.01183496, 0.01160419, 0.01139382, + ], + [ + 0.01345288, 0.0129892, 0.01259257, 0.0122478, 0.01194415, + 0.01167378, 0.01143082, 0.01121078, 0.01101014, + ], + [ + 0.01324268, 0.0127888, 0.01240047, 0.01206285, 0.01176543, + 0.01150057, 0.01126253, 0.01104691, 0.01085027, + ], + [ + 0.0131464, 0.01269699, 0.01231244, 0.01197807, 0.0116835, + 0.01142116, 0.01118536, 0.01097176, 0.01077695, + ], + [ + 0.01305543, 0.01261023, 0.01222925, 0.01189795, 0.01160606, + 0.01134608, 0.0111124, 0.0109007, 0.01070762, + ], + [ + 0.0129694, 0.01252817, 0.01215056, 0.01182215, 0.01153279, + 0.01127505, 0.01104336, 0.01083345, 0.010642, + ], + [ + 0.01288799, 0.01245051, 0.01207606, 0.01175039, 0.01146341, + 0.01120778, 0.01097797, 0.01076977, 0.01057985, + ], + [ + 0.0128109, 0.01237695, 0.01200549, 0.0116824, 0.01139768, + 0.01114404, 0.01091602, 0.01070941, 0.01052094, + ], + ] + ) + + expected_skin_cf = np.array( + [ + [ + 0.02081979, 0.02004218, 0.01937982, 0.01880616, 0.01830256, + 0.01785549, 0.01745483, 0.01709284, 0.01676351, + ], + [ + 0.01812046, 0.01747006, 0.01691509, 0.01643371, 0.01601054, + 0.01563439, 0.01529692, 0.0149917, 0.01471376, + ], + [ + 0.01644993, 0.0158753, 0.0153844, 0.01495817, 0.01458313, + 0.0142495, 0.01394994, 0.01367883, 0.01343178, + ], + [ + 0.01526502, 0.01474245, 0.01429566, 0.01390743, 0.01356561, + 0.01326134, 0.01298799, 0.01274048, 0.01251483, + ], + [ + 0.01435403, 0.01387038, 0.0134566, 0.01309684, 0.01277992, + 0.01249769, 0.01224403, 0.01201426, 0.01180471, + ], + [ + 0.01361502, 0.01316212, 0.01277444, 0.01243722, 0.01214004, + 0.01187528, 0.01163725, 0.01142157, 0.01122482, + ], + [ + 0.01329152, 0.01285181, 0.01247535, 0.01214782, 0.01185913, + 0.0116019, 0.0113706, 0.01116099, 0.01096975, + ], + [ + 0.01313905, 0.01270551, 0.01233428, 0.01201128, 0.01172656, + 0.01147285, 0.0112447, 0.01103793, 0.01084927, + ], + [ + 0.01299212, 0.01256448, 0.01219827, 0.01187961, 0.0115987, + 0.01134836, 0.01112323, 0.01091918, 0.010733, + ], + [ + 0.01285029, 0.01242832, 0.01206693, 0.01175244, 0.01147518, + 0.01122808, 0.01100584, 0.01080442, 0.01062061, + ], + [ + 0.0127132, 0.01229667, 0.01193991, 0.01162943, 0.01135567, + 0.01111169, 0.01089225, 0.01069333, 0.01051181, + ], + [ + 0.0125805, 0.01216921, 0.01181691, 0.01151028, 0.0112399, + 0.01099892, 0.01078216, 0.01058567, 0.01040636, + ], + ] + ) + + expected_re = np.array( + [ + [ + 2535.11267397, 2852.00175822, 3168.89084247, 3485.77992671, + 3802.66901096, 4119.55809521, 4436.44717945, 4753.3362637, 5070.22534795, + ], + [ + 3802.66901096, 4278.00263733, 4753.3362637, 5228.66989007, + 5704.00351644, 6179.33714281, 6654.67076918, 7130.00439555, 7605.33802192, + ], + [ + 5070.22534795, 5704.00351644, 6337.78168493, 6971.55985343, + 7605.33802192, 8239.11619041, 8872.89435891, 9506.6725274, 10140.45069589, + ], + [ + 6337.78168493, 7130.00439555, 7922.22710617, 8714.44981678, + 9506.6725274, 10298.89523802, 11091.11794863, 11883.34065925, 12675.56336987, + ], + [ + 7605.33802192, 8556.00527466, 9506.6725274, 10457.33978014, + 11408.00703288, 12358.67428562, 13309.34153836, 14260.0087911, 15210.67604384, + ], + [ + 8872.89435891, 9982.00615377, 11091.11794863, 12200.2297435, + 13309.34153836, 14418.45333323, 15527.56512809, 16636.67692295, 17745.78871782, + ], + [ + 9506.6725274, 10695.00659333, 11883.34065925, 13071.67472518, + 14260.0087911, 15448.34285703, 16636.67692295, 17825.01098888, 19013.3450548, + ], + [ + 9823.56161165, 11051.5068131, 12279.45201456, 13507.39721602, + 14735.34241747, 15963.28761893, 17191.23282038, 18419.17802184, 19647.1232233, + ], + [ + 10140.45069589, 11408.00703288, 12675.56336987, 13943.11970686, + 15210.67604384, 16478.23238083, 17745.78871782, 19013.3450548, 20280.90139179, + ], + [ + 10457.33978014, 11764.50725266, 13071.67472518, 14378.84219769, + 15686.00967021, 16993.17714273, 18300.34461525, 19607.51208776, 20914.67956028, + ], + [ + 10774.22886439, 12121.00747244, 13467.78608048, 14814.56468853, + 16161.34329658, 17508.12190463, 18854.90051268, 20201.67912073, 21548.45772878, + ], + [ + 11091.11794863, 12477.50769221, 13863.89743579, 15250.28717937, + 16636.67692295, 18023.06666653, 19409.45641011, 20795.84615369, 22182.23589727, + ], + ] + ) + expected_wall_temp = np.array( + [ + [ + 312.2257434, 310.91072134, 309.73985349, 308.68528692, + 307.72648885, 306.84789293, 306.03742045, 305.28551328, 304.58447993, + ], + [ + 325.53580719, 324.32521822, 323.24563283, 322.27191154, + 321.38549197, 320.57228106, 319.82132882, 319.12395976, 318.47318481, + ], + [ + 336.14581431, 335.00316978, 333.98309588, 333.06217839, + 332.22311052, 331.45273996, 330.7408387, 330.07929681, 329.46157595, + ], + [ + 345.77748172, 344.67810867, 343.69595071, 342.8086856, + 341.9998021, 341.25674448, 340.56974301, 339.93104691, 339.33440433, + ], + [ + 355.19308974, 354.11844249, 353.15790517, 352.28979071, + 351.49805053, 350.77047571, 350.09756276, 349.47176953, 348.88701044, + ], + [ + 364.78724817, 363.72241041, 362.77035004, 361.90965915, + 361.12449161, 360.40278964, 359.73516534, 359.11416672, 358.53377984, + ], + [ + 369.724644, 368.65987786, 367.70778972, 366.8469981, + 366.0616753, 365.33977678, 364.67192433, 364.05067326, 363.47001514, + ], + [ + 372.23709293, 371.17125423, 370.21817293, 369.35645507, + 368.57026339, 367.84754578, 367.17891796, 366.55693025, 365.97557009, + ], + [ + 374.78120136, 373.71358252, 372.75888265, 371.895679, + 371.10811275, 370.38411524, 369.71428915, 369.09117435, 368.50874977, + ], + [ + 377.35853852, 376.28845297, 375.33152752, 374.46629484, + 373.67686302, 372.95113807, 372.27970293, 371.6550817, 371.07124056, + ], + [ + 379.97046618, 378.89724658, 377.93750541, 377.06971548, + 376.27794052, 375.55005281, 374.87660896, 374.2501122, 373.6645118, + ], + [ + 382.61816115, 381.5411578, 380.5780263, 379.70716469, + 378.91258145, 378.18210689, 377.50626497, 376.87753302, 376.2898394, + ], + ] + ) + # fmt: on + + assert_near_equal(prob.get_val('cf_iter'), expected_ct_iter, 1e-6) + assert_near_equal(prob.get_val('skin_friction_coeff'), expected_skin_cf, 1e-6) + assert_near_equal(prob.get_val('Re'), expected_re, 1e-6) + assert_near_equal(prob.get_val('wall_temp'), expected_wall_temp, 1e-6) def test_skin_friction_algorithm(self): # Test vs aviary1 algorithm output. n = 12 nc = 3 - machs = np.array([.2, .3, .4, .5, .6, .7, .75, .775, .8, .825, .85, .875]) + machs = np.array([0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.75, 0.775, 0.8, 0.825, 0.85, 0.875]) lens = np.linspace(1, 2, nc) temp = np.ones(n) * 389.97 pres = np.ones(n) * 374.74437747 @@ -281,12 +374,11 @@ def test_skin_friction_algorithm(self): model = prob.model options = {} - options[Aircraft.VerticalTail.NUM_TAILS] = (0, 'unitless') - options[Aircraft.Fuselage.NUM_FUSELAGES] = (1, 'unitless') - options[Aircraft.Engine.NUM_ENGINES] = ([0], 'unitless') + options[Aircraft.VerticalTail.NUM_TAILS] = 0 + options[Aircraft.Fuselage.NUM_FUSELAGES] = 1 + options[Aircraft.Engine.NUM_ENGINES] = [0] - model.add_subsystem( - 'cf', SkinFriction(num_nodes=n, aviary_options=AviaryValues(options))) + model.add_subsystem('cf', SkinFriction(num_nodes=n, **options)) prob.setup(force_alloc_complex=True) @@ -297,44 +389,46 @@ def test_skin_friction_algorithm(self): prob.run_model() - data = np.array([ - [0.005396523989004909, 365059.9023227319], - [0.004966765578135659, 547589.8534840979], - [0.004690457476125405, 730119.8046454638], - [0.004944328211075446, 547589.8534840978], - [0.004562147270958159, 821384.7802261466], - [0.004315727215872133, 1095179.7069681955], - [0.004643056166682007, 730119.8046454638], - [0.00429139345173995, 1095179.7069681957], - [0.004064221738701749, 1460239.6092909276], - [0.004414783804315559, 912649.7558068297], - [0.004085425540068907, 1368974.6337102444], - [0.0038723696464216576, 1825299.5116136593], - [0.004228034334994051, 1095179.7069681955], - [0.0039162899726263006, 1642769.5604522931], - [0.0037144161374653376, 2190359.413936391], - [0.004067313880014865, 1277709.6581295615], - [0.0037702154884929626, 1916564.487194342], - [0.003577666619089076, 2555419.316259123], - [0.003993874389670162, 1368974.6337102444], - [0.003703301621412952, 2053461.9505653665], - [0.0035149162534008037, 2737949.267420489], - [0.0039585444977749615, 1414607.121500586], - [0.003671073155610844, 2121910.682250879], - [0.003484668543701865, 2829214.243001172], - [0.003924040592737333, 1460239.6092909276], - [0.0036395743600069483, 2190359.4139363915], - [0.003455090229668116, 2920479.2185818553], - [0.003890297607565131, 1505872.097081269], - [0.0036087474909260266, 2258808.1456219032], - [0.003426128150494066, 3011744.194162538], - [0.003857257490610407, 1551504.5848716104], - [0.0035785410558282315, 2327256.8773074155], - [0.0033977349180204213, 3103009.169743221], - [0.00382486832849627, 1597137.0726619519], - [0.003548909032785302, 2395705.6089929277], - [0.003369868196564652, 3194274.1453239038] - ]) + data = np.array( + [ + [0.005396523989004909, 365059.9023227319], + [0.004966765578135659, 547589.8534840979], + [0.004690457476125405, 730119.8046454638], + [0.004944328211075446, 547589.8534840978], + [0.004562147270958159, 821384.7802261466], + [0.004315727215872133, 1095179.7069681955], + [0.004643056166682007, 730119.8046454638], + [0.00429139345173995, 1095179.7069681957], + [0.004064221738701749, 1460239.6092909276], + [0.004414783804315559, 912649.7558068297], + [0.004085425540068907, 1368974.6337102444], + [0.0038723696464216576, 1825299.5116136593], + [0.004228034334994051, 1095179.7069681955], + [0.0039162899726263006, 1642769.5604522931], + [0.0037144161374653376, 2190359.413936391], + [0.004067313880014865, 1277709.6581295615], + [0.0037702154884929626, 1916564.487194342], + [0.003577666619089076, 2555419.316259123], + [0.003993874389670162, 1368974.6337102444], + [0.003703301621412952, 2053461.9505653665], + [0.0035149162534008037, 2737949.267420489], + [0.0039585444977749615, 1414607.121500586], + [0.003671073155610844, 2121910.682250879], + [0.003484668543701865, 2829214.243001172], + [0.003924040592737333, 1460239.6092909276], + [0.0036395743600069483, 2190359.4139363915], + [0.003455090229668116, 2920479.2185818553], + [0.003890297607565131, 1505872.097081269], + [0.0036087474909260266, 2258808.1456219032], + [0.003426128150494066, 3011744.194162538], + [0.003857257490610407, 1551504.5848716104], + [0.0035785410558282315, 2327256.8773074155], + [0.0033977349180204213, 3103009.169743221], + [0.00382486832849627, 1597137.0726619519], + [0.003548909032785302, 2395705.6089929277], + [0.003369868196564652, 3194274.1453239038], + ] + ) cf = prob.get_val('cf.skin_friction_coeff').ravel() Re = prob.get_val('cf.Re').ravel() @@ -346,5 +440,5 @@ def test_skin_friction_algorithm(self): assert_near_equal(np.max(Re_diff), 0.0, 1e-4) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_drag.py b/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_drag.py index 3be06d2643..d15e23e5b4 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_drag.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_skinfriction_drag.py @@ -4,40 +4,45 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.flops_based.skin_friction_drag import \ - SkinFrictionDrag -from aviary.utils.aviary_values import AviaryValues +from aviary.subsystems.aerodynamics.flops_based.skin_friction_drag import SkinFrictionDrag from aviary.variable_info.variables import Aircraft class SkinFrictionDragTest(unittest.TestCase): - def test_derivs(self): nn = 2 - fine = np.array([0.13, .125, .1195, 10.0392, 1.5491, 1.5491]) - Re = np.array([[15.0, 11, 18.3, 183.4, 17.6, 17.6], - [17.0, 16, 15.3, 78.4, 23.6, 33.6]]) * 1e-6 - cf = np.array([[.00263, .00276, .00255, .00182, .00256, .00256], - [.00283, .00296, .00235, .00172, .00276, .00276]]) + fine = np.array([0.13, 0.125, 0.1195, 10.0392, 1.5491, 1.5491]) + Re = ( + np.array([[15.0, 11, 18.3, 183.4, 17.6, 17.6], [17.0, 16, 15.3, 78.4, 23.6, 33.6]]) + * 1e-6 + ) + cf = np.array( + [ + [0.00263, 0.00276, 0.00255, 0.00182, 0.00256, 0.00256], + [0.00283, 0.00296, 0.00235, 0.00172, 0.00276, 0.00276], + ] + ) Sw = np.array([2396.56, 592.65, 581.13, 4158.62, 273.45, 273.45]) lam_up = np.array([6 * 0.03]) lam_low = np.array([6 * 0.02]) - nc = len(fine) prob = om.Problem() model = prob.model - options = AviaryValues() - options.set_val(Aircraft.Fuselage.NUM_FUSELAGES, 1) - options.set_val(Aircraft.Engine.NUM_ENGINES, [2]) - options.set_val(Aircraft.VerticalTail.NUM_TAILS, 1) - options.set_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY, 1.93) + options = { + Aircraft.Fuselage.NUM_FUSELAGES: 1, + Aircraft.Engine.NUM_ENGINES: [2], + Aircraft.VerticalTail.NUM_TAILS: 1, + Aircraft.Wing.AIRFOIL_TECHNOLOGY: 1.93, + } model.add_subsystem( - 'CDf', SkinFrictionDrag(num_nodes=nn, aviary_options=options), + 'CDf', + SkinFrictionDrag(num_nodes=nn, **options), promotes_inputs=[Aircraft.Wing.AREA], - promotes_outputs=['skin_friction_drag_coeff']) + promotes_outputs=['skin_friction_drag_coeff'], + ) prob.setup(force_alloc_complex=True) @@ -51,42 +56,76 @@ def test_derivs(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') # atol is low because Re magnitude is 1e8. assert_check_partials(derivs, atol=1e-7, rtol=1e-12) - assert_near_equal( - prob.get_val('skin_friction_drag_coeff'), [14.91229, 15.01284], 1e-6) + assert_near_equal(prob.get_val('skin_friction_drag_coeff'), [14.91229, 15.01284], 1e-6) def test_derivs_multiengine(self): nn = 2 - fine = np.array([0.13, .125, .1195, 10.0392, 1.5491, - 1.5491, 1.125, 1.125, 1.125, 1.125]) - Re = np.array([[15.0, 11, 18.3, 183.4, 17.6, 17.6, 5.55, 5.55, 5.55, 5.55], - [17.0, 16, 15.3, 78.4, 23.6, 33.6, 22.7, 22.7, 22.7, 22.7]]) * 1e-6 - cf = np.array([[.00263, .00276, .00255, .00182, .00256, .00256, 0.0184, 0.0184, 0.0184, 0.0184], - [.00283, .00296, .00235, .00172, .00276, .00276, 0.0203, 0.0203, 0.0203, 0.0203]]) - Sw = np.array([2396.56, 592.65, 581.13, 4158.62, 273.45, - 273.45, 239.1, 239.1, 239.1, 239.1]) + fine = np.array([0.13, 0.125, 0.1195, 10.0392, 1.5491, 1.5491, 1.125, 1.125, 1.125, 1.125]) + Re = ( + np.array( + [ + [15.0, 11, 18.3, 183.4, 17.6, 17.6, 5.55, 5.55, 5.55, 5.55], + [17.0, 16, 15.3, 78.4, 23.6, 33.6, 22.7, 22.7, 22.7, 22.7], + ] + ) + * 1e-6 + ) + cf = np.array( + [ + [ + 0.00263, + 0.00276, + 0.00255, + 0.00182, + 0.00256, + 0.00256, + 0.0184, + 0.0184, + 0.0184, + 0.0184, + ], + [ + 0.00283, + 0.00296, + 0.00235, + 0.00172, + 0.00276, + 0.00276, + 0.0203, + 0.0203, + 0.0203, + 0.0203, + ], + ] + ) + Sw = np.array( + [2396.56, 592.65, 581.13, 4158.62, 273.45, 273.45, 239.1, 239.1, 239.1, 239.1] + ) lam_up = np.array([6 * 0.03]) lam_low = np.array([6 * 0.02]) - nc = len(fine) prob = om.Problem() model = prob.model - options = AviaryValues() - options.set_val(Aircraft.Fuselage.NUM_FUSELAGES, 1) - options.set_val(Aircraft.Engine.NUM_ENGINES, [2, 4]) - options.set_val(Aircraft.VerticalTail.NUM_TAILS, 1) - options.set_val(Aircraft.Wing.AIRFOIL_TECHNOLOGY, 1.93) + options = { + Aircraft.Fuselage.NUM_FUSELAGES: 1, + Aircraft.Engine.NUM_ENGINES: [2, 4], + Aircraft.VerticalTail.NUM_TAILS: 1, + Aircraft.Wing.AIRFOIL_TECHNOLOGY: 1.93, + } model.add_subsystem( - 'CDf', SkinFrictionDrag(num_nodes=nn, aviary_options=options), + 'CDf', + SkinFrictionDrag(num_nodes=nn, **options), promotes_inputs=[Aircraft.Wing.AREA], - promotes_outputs=['skin_friction_drag_coeff']) + promotes_outputs=['skin_friction_drag_coeff'], + ) prob.setup(force_alloc_complex=True) @@ -100,16 +139,15 @@ def test_derivs_multiengine(self): prob.run_model() - derivs = prob.check_partials(out_stream=None, method="cs") + derivs = prob.check_partials(out_stream=None, method='cs') # atol is low because Re magnitude is 1e8. assert_check_partials(derivs, atol=1e-7, rtol=1e-12) - assert_near_equal( - prob.get_val('skin_friction_drag_coeff'), [24.27078, 19.82677], 1e-6) + assert_near_equal(prob.get_val('skin_friction_drag_coeff'), [24.27078, 19.82677], 1e-6) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = SkinFrictionDragTest() # test.test_derivs_multiengine() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py deleted file mode 100644 index 5e752099b1..0000000000 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_solved_aero_group.py +++ /dev/null @@ -1,294 +0,0 @@ -""" -This test validates passing a drag polar into the solved aero in the mission. -Computed lift and drag should be the same as reading the same polar in from -a file. -""" -from copy import deepcopy -import unittest - -import numpy as np -import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.interface.methods_for_level2 import AviaryProblem - -from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.utils.csv_data_file import read_data_file -from aviary.utils.named_values import NamedValues -from aviary.interface.default_phase_info.height_energy import phase_info -from aviary.variable_info.variables import Aircraft - - -# The drag-polar-generating component reads this in, instead of computing the polars. -polar_file = "subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free_reduced_alpha.txt" - -phase_info = deepcopy(phase_info) - -phase_info['pre_mission']['include_takeoff'] = False -phase_info['post_mission']['include_landing'] = False -phase_info['cruise']['subsystem_options']['core_aerodynamics']['method'] = 'solved_alpha' -phase_info['cruise']['subsystem_options']['core_aerodynamics']['aero_data'] = polar_file -phase_info.pop('climb') -phase_info.pop('descent') - -data = read_data_file(polar_file) -ALTITUDE = data.get_val('Altitude', 'ft') -MACH = data.get_val('Mach', 'unitless') -ALPHA = data.get_val('Angle_of_Attack', 'deg') - -shape = (np.unique(ALTITUDE).size, np.unique(MACH).size, np.unique(ALPHA).size) -CL = data.get_val('CL').reshape(shape) -CD = data.get_val('CD').reshape(shape) - - -class TestSolvedAero(unittest.TestCase): - - def test_solved_aero_pass_polar(self): - # Test that passing training data provides the same results - local_phase_info = deepcopy(phase_info) - - prob = AviaryProblem() - - prob.load_inputs( - "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv", local_phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - - prob.link_phases() - - prob.setup() - - prob.set_initial_guesses() - - print('about to run') - prob.run_model() - print('done') - - CL_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") - CD_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") - - # Lift and Drag polars passed from external component in pre-mission. - - ph_in = deepcopy(phase_info) - - polar_builder = FakeDragPolarBuilder(name="aero", altitude=ALTITUDE, mach=MACH, - alpha=ALPHA) - aero_data = NamedValues() - aero_data.set_val('altitude', ALTITUDE, 'ft') - aero_data.set_val('mach', MACH, 'unitless') - aero_data.set_val('angle_of_attack', ALPHA, 'deg') - - subsystem_options = {'method': 'solved_alpha', - 'aero_data': aero_data, - 'connect_training_data': True} - ph_in['pre_mission']['external_subsystems'] = [polar_builder] - - ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} - - prob = AviaryProblem() - - prob.load_inputs( - "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv", ph_in) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, - np.zeros_like(CL), units='unitless') - prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, - np.zeros_like(CD), units='unitless') - - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - - prob.link_phases() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_model() - - CL_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") - CD_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") - - assert_near_equal(CL_pass, CL_base, 1e-6) - assert_near_equal(CD_pass, CD_base, 1e-6) - - def test_solved_aero_pass_polar_unique_abscissa(self): - # Solved Aero with shortened lists of table abscissa. - local_phase_info = deepcopy(phase_info) - - prob = AviaryProblem() - - csv_path = "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv" - prob.load_inputs(csv_path, local_phase_info) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - - prob.link_phases() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_model() - - CL_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") - CD_base = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") - - # Lift and Drag polars passed from external component in pre-mission. - - ph_in = deepcopy(phase_info) - - alt = np.array([0., 3000., 6000., 9000., 12000., 15000., 18000., 21000., - 24000., 27000., 30000., 33000., 36000., 38000., 42000.]) - mach = np.array([0., 0.2, 0.4, 0.5, 0.6, 0.7, 0.75, 0.8, 0.85, 0.9]) - alpha = np.array([-2., 0., 2., 4., 6., 8., 10.]) - - polar_builder = FakeDragPolarBuilder(name="aero", altitude=alt, mach=mach, - alpha=alpha) - aero_data = NamedValues() - aero_data.set_val('altitude', alt, 'ft') - aero_data.set_val('mach', mach, 'unitless') - aero_data.set_val('angle_of_attack', alpha, 'deg') - - subsystem_options = {'method': 'solved_alpha', - 'aero_data': aero_data, - 'connect_training_data': True} - ph_in['pre_mission']['external_subsystems'] = [polar_builder] - - ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} - - prob = AviaryProblem() - - prob.load_inputs(csv_path, ph_in) - - # Preprocess inputs - prob.check_and_preprocess_inputs() - - prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, - np.zeros_like(CL), units='unitless') - prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, - np.zeros_like(CD), units='unitless') - - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - - prob.link_phases() - - prob.setup() - - prob.set_initial_guesses() - - prob.run_model() - - CL_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CL") - CD_pass = prob.get_val("traj.cruise.rhs_all.core_aerodynamics.tabular_aero.CD") - - assert_near_equal(CL_pass, CL_base, 1e-6) - assert_near_equal(CD_pass, CD_base, 1e-6) - - -class FakeCalcDragPolar(om.ExplicitComponent): - """ - This component is a stand-in for an externally computed lift/drag table - calculation. It does nothing but read in the pre-computed table. - """ - - def initialize(self): - """ - Declare options. - """ - self.options.declare("altitude", default=None, allow_none=True, - desc="List of altitudes in ascending order.") - self.options.declare("mach", default=None, allow_none=True, - desc="List of mach numbers in ascending order.") - self.options.declare("alpha", default=None, allow_none=True, - desc="List of angles of attack in ascending order.") - - def setup(self): - altitude = self.options['altitude'] - mach = self.options['mach'] - alpha = self.options['alpha'] - - self.add_input(Aircraft.Wing.AREA, 1.0, units='ft**2') - self.add_input(Aircraft.Wing.SPAN, 1.0, units='ft') - - shape = (len(altitude), len(mach), len(alpha)) - - self.add_output('drag_table', shape=shape, units='unitless') - self.add_output('lift_table', shape=shape, units='unitless') - - def compute(self, inputs, outputs): - """ - This component doesn't do anything, except set the drag and lift - polars from the file we read in. - - Any real analysis would compute these tables. - """ - outputs['drag_table'] = CD - outputs['lift_table'] = CL - - -class FakeDragPolarBuilder(SubsystemBuilderBase): - """ - Prototype of a subsystem that overrides an aviary internally computed var. - - Parameters - ---------- - altitude : list or None - List of altitudes in ascending order. (Optional) - mach : list or None - List of mach numbers in ascending order. (Optional) - alpha : list or None - List of angles of attack in ascending order. (Optional) - """ - - def __init__(self, name='aero', altitude=None, mach=None, - alpha=None): - super().__init__(name) - self.altitude = np.unique(altitude) - self.mach = np.unique(mach) - self.alpha = np.unique(alpha) - - def build_pre_mission(self, aviary_inputs): - """ - Build an OpenMDAO system for the pre-mission computations of the subsystem. - - Returns - ------- - pre_mission_sys : openmdao.core.Group - An OpenMDAO group containing all computations that need to happen in - the pre-mission part of the Aviary problem. This - includes sizing, design, and other non-mission parameters. - """ - - group = om.Group() - - calc_drag_polar = FakeCalcDragPolar(altitude=self.altitude, mach=self.mach, - alpha=self.alpha) - - group.add_subsystem("aero", calc_drag_polar, - promotes_inputs=["aircraft:*"], - promotes_outputs=[('drag_table', Aircraft.Design.DRAG_POLAR), - ('lift_table', Aircraft.Design.LIFT_POLAR)]) - return group - - -if __name__ == "__main__": - # unittest.main() - test = TestSolvedAero() - test.test_solved_aero_pass_polar_unique_abscissa() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py index e458dbb716..3a21f6892e 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_tabular_aero_group.py @@ -1,13 +1,13 @@ -from copy import deepcopy -from parameterized import parameterized import unittest +from copy import deepcopy import numpy as np - import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs +from parameterized import parameterized -from aviary.interface.default_phase_info.height_energy import phase_info +from aviary.models.missions.height_energy_default import phase_info from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.atmosphere.atmosphere import Atmosphere @@ -17,19 +17,19 @@ from aviary.utils.functions import set_aviary_initial_values from aviary.utils.named_values import NamedValues from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems -from aviary.validation_cases.validation_tests import (get_flops_inputs, - get_flops_outputs, - print_case) +from aviary.validation_cases.validation_tests import get_flops_inputs, get_flops_outputs, print_case from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings FLOPS = LegacyCode.FLOPS GASP = LegacyCode.GASP -CDI_table = "subsystems/aerodynamics/flops_based/test/large_single_aisle_1_CDI_polar.csv" -CD0_table = "subsystems/aerodynamics/flops_based/test/large_single_aisle_1_CD0_polar.csv" +CDI_table = 'subsystems/aerodynamics/flops_based/test/large_single_aisle_1_CDI_polar.csv' +CD0_table = 'subsystems/aerodynamics/flops_based/test/large_single_aisle_1_CD0_polar.csv' +@use_tempdirs class TabularAeroGroupFileTest(unittest.TestCase): # Test drag comp with data from file, structured grid def setUp(self): @@ -37,19 +37,21 @@ def setUp(self): aviary_options = AviaryValues() aviary_options.set_val(Settings.VERBOSITY, 0) - kwargs = {'method': 'tabular', 'CDI_data': CDI_table, - 'CD0_data': CD0_table} + kwargs = {'method': 'tabular', 'CDI_data': CDI_table, 'CD0_data': CD0_table} aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) self.prob.model.add_subsystem( - "aero", - aero_builder.build_mission( - num_nodes=1, aviary_inputs=aviary_options, **kwargs), + 'aero', + aero_builder.build_mission(num_nodes=1, aviary_inputs=aviary_options, **kwargs), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options(self.prob, aviary_options) + + self.prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, val=0.3876, units='unitless') + self.prob.setup(check=False, force_alloc_complex=True) def test_case(self): @@ -57,36 +59,30 @@ def test_case(self): # test data from large_single_aisle_2 climb profile # tabular aero was set to large_single_aisle_1, expected value adjusted accordingly self.prob.set_val( - Dynamic.Mission.VELOCITY, - val=115, - units='m/s') # convert from knots to ft/s + Dynamic.Mission.VELOCITY, val=115, units='m/s' + ) # convert from knots to ft/s self.prob.set_val(Dynamic.Mission.ALTITUDE, val=10582, units='m') - self.prob.set_val(Dynamic.Mission.MASS, val=80442, units='kg') - self.prob.set_val(Dynamic.Mission.MACH, val=0.3876, units='unitless') + self.prob.set_val(Dynamic.Vehicle.MASS, val=80442, units='kg') # 1344.5? 'reference' vs 'calculated'? self.prob.set_val(Aircraft.Wing.AREA, val=1341, units='ft**2') # calculated from online atmospheric table - self.prob.set_val(Dynamic.Mission.DENSITY, val=0.88821, units='kg/m**3') + self.prob.set_val(Dynamic.Atmosphere.DENSITY, val=0.88821, units='kg/m**3') self.prob.run_model() # We know that computed drag (from FLOPS) is higher than what this tabular data # computes. Use loose tolerance. - tol = .03 + tol = 0.03 assert_near_equal( - self.prob.get_val(Dynamic.Mission.DRAG, units='N'), 53934.78861492, tol + self.prob.get_val(Dynamic.Vehicle.DRAG, units='N'), 53934.78861492, tol ) # check the value of each output # TODO resolve partials wrt gravity (decide on implementation of gravity) - partial_data = self.prob.check_partials( - out_stream=None, method="cs", step=1.1e-40) - assert_check_partials( - partial_data, atol=1e-9, rtol=1e-12 - ) # check the partial derivatives + partial_data = self.prob.check_partials(out_stream=None, method='cs', step=1.1e-40) + assert_check_partials(partial_data, atol=1e-9, rtol=1e-12) # check the partial derivatives def test_parameters(self): - local_phase_info = deepcopy(phase_info) core_aero = local_phase_info['cruise']['subsystem_options']['core_aerodynamics'] @@ -96,35 +92,29 @@ def test_parameters(self): local_phase_info.pop('climb') local_phase_info.pop('descent') - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs( - "subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv", - local_phase_info + 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv', + local_phase_info, ) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - - prob.link_phases() + prob.build_model() prob.setup() - prob.set_initial_guesses() - print('about to run') prob.run_model() # verify that we are promoting the parameters. - wing_area = prob.get_val("traj.cruise.rhs_all.aircraft:wing:area", units='ft**2') + wing_area = prob.get_val('traj.cruise.rhs_all.aircraft:wing:area', units='ft**2') actual_wing_area = prob.aviary_inputs.get_val(Aircraft.Wing.AREA, units='ft**2') assert_near_equal(wing_area, actual_wing_area) +@use_tempdirs class TabularAeroGroupDataTest(unittest.TestCase): # Test tabular drag comp with training data, structured grid def setUp(self): @@ -134,36 +124,54 @@ def setUp(self): CDI_table = _default_CDI_data() CDI_values = CDI_table.get_val('lift_dependent_drag_coefficient') - # CDI_table.delete('lift_dependent_drag_coefficient') CD0_table = _default_CD0_data() CD0_values = CD0_table.get_val('zero_lift_drag_coefficient') - # CD0_table.delete('zero_lift_drag_coefficient') drag_data = om.ExecComp() - drag_data.add_output('zero_lift_drag_coefficient_train', - CD0_values, units='unitless') - drag_data.add_output('lift_dependent_drag_coefficient_train', - CDI_values, units='unitless') - - self.prob.model.add_subsystem( - "drag_data", - drag_data, - promotes_outputs=['*'] + drag_data.add_output( + Aircraft.Design.LIFT_INDEPENDENT_DRAG_POLAR, CD0_values, units='unitless' + ) + drag_data.add_output( + Aircraft.Design.LIFT_DEPENDENT_DRAG_POLAR, CDI_values, units='unitless' ) - kwargs = {'method': 'tabular', 'CDI_data': CDI_table, 'CD0_data': CD0_table, } - # 'training_data': True} + self.prob.model.add_subsystem('drag_data', drag_data, promotes_outputs=['*']) + + # Pass zero-arrays for the training data, so that this test won't pass unless + # we are passing the values from the drag_data component. + shape = CDI_table.get_item('lift_dependent_drag_coefficient')[0].shape + CDI_clean_table = _default_CDI_data() + CDI_clean_table.set_val('lift_dependent_drag_coefficient', np.zeros(shape)) + + shape = CD0_table.get_item('zero_lift_drag_coefficient')[0].shape + CD0_clean_table = _default_CD0_data() + CD0_clean_table.set_val('zero_lift_drag_coefficient', np.zeros(shape)) + + self.CDI_values = CDI_values + self.CD0_values = CD0_values + self.CDI_clean_table = CDI_clean_table + self.CD0_clean_table = CD0_clean_table + + kwargs = { + 'method': 'tabular', + 'CDI_data': CDI_clean_table, + 'CD0_data': CD0_clean_table, + 'connect_training_data': True, + } aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) self.prob.model.add_subsystem( - "aero", - aero_builder.build_mission( - num_nodes=1, aviary_inputs=aviary_options, **kwargs), + 'aero', + aero_builder.build_mission(num_nodes=1, aviary_inputs=aviary_options, **kwargs), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options(self.prob, aviary_options) + + self.prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, val=0.3876, units='unitless') + self.prob.setup(check=False, force_alloc_complex=True) def test_case(self): @@ -171,40 +179,70 @@ def test_case(self): # test data from large_single_aisle_2 climb profile # tabular aero was set to large_single_aisle_1 data, expected value adjusted accordingly self.prob.set_val( - Dynamic.Mission.VELOCITY, - val=115, - units='m/s') # convert from knots to ft/s + Dynamic.Mission.VELOCITY, val=115, units='m/s' + ) # convert from knots to ft/s self.prob.set_val(Dynamic.Mission.ALTITUDE, val=10582, units='m') - self.prob.set_val(Dynamic.Mission.MASS, val=80442, units='kg') - self.prob.set_val(Dynamic.Mission.MACH, val=0.3876, units='unitless') + self.prob.set_val(Dynamic.Vehicle.MASS, val=80442, units='kg') # 1344.5? 'reference' vs 'calculated'? self.prob.set_val(Aircraft.Wing.AREA, val=1341, units='ft**2') # calculated from online atmospheric table - self.prob.set_val(Dynamic.Mission.DENSITY, val=0.88821, units='kg/m**3') + self.prob.set_val(Dynamic.Atmosphere.DENSITY, val=0.88821, units='kg/m**3') self.prob.run_model() # We know that computed drag (from FLOPS) is higher than what this tabular data # computes. Use loose tolerance. - tol = .03 + tol = 0.03 assert_near_equal( - self.prob.get_val(Dynamic.Mission.DRAG, units='N'), 53934.78861492, tol + self.prob.get_val(Dynamic.Vehicle.DRAG, units='N'), 53934.78861492, tol ) # check the value of each output # TODO resolve partials wrt gravity (decide on implementation of gravity) - partial_data = self.prob.check_partials( - out_stream=None, method="cs", step=1.1e-40) - assert_check_partials( - partial_data, atol=1e-9, rtol=1e-12 - ) # check the partial derivatives + partial_data = self.prob.check_partials(out_stream=None, method='cs', step=1.1e-40) + assert_check_partials(partial_data, atol=1e-9, rtol=1e-12) # check the partial derivatives + def test_parameters(self): + local_phase_info = deepcopy(phase_info) + core_aero = local_phase_info['cruise']['subsystem_options']['core_aerodynamics'] -data_sets = ['LargeSingleAisle1FLOPS', 'LargeSingleAisle2FLOPS', 'N3CC'] + core_aero['method'] = 'tabular' + core_aero['connect_training_data'] = True + core_aero['CDI_data'] = self.CDI_clean_table + core_aero['CD0_data'] = self.CD0_clean_table + local_phase_info.pop('climb') + local_phase_info.pop('descent') + # This is a somewhat contrived problem, so pick a mass. + local_phase_info['cruise']['user_options']['mass_initial'] = (150000.0, 'lbm') -class ComputedVsTabularTest(unittest.TestCase): + prob = AviaryProblem() + + prob.load_inputs( + 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv', + local_phase_info, + ) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + # Connect or set. + prob.aviary_inputs.set_val(Aircraft.Design.LIFT_INDEPENDENT_DRAG_POLAR, self.CD0_values) + prob.aviary_inputs.set_val(Aircraft.Design.LIFT_DEPENDENT_DRAG_POLAR, self.CDI_values) + + prob.setup() + + prob.run_model() + + assert_near_equal(prob.get_val('traj.cruise.rhs_all.drag', units='lbf')[0], 9907.0, 1.0e-3) + +data_sets = ['LargeSingleAisle1FLOPS', 'LargeSingleAisle2FLOPS', 'AdvancedSingleAisle'] + + +@use_tempdirs +class ComputedVsTabularTest(unittest.TestCase): @parameterized.expand(data_sets, name_func=print_case) def test_case(self, case_name): flops_inputs = get_flops_inputs(case_name, preprocess=True) @@ -236,28 +274,28 @@ def test_case(self, case_name): dynamic_inputs.set_val(Dynamic.Mission.VELOCITY, val=vel, units=vel_units) dynamic_inputs.set_val(Dynamic.Mission.ALTITUDE, val=alt, units=alt_units) - dynamic_inputs.set_val(Dynamic.Mission.MASS, val=mass, units=units) + dynamic_inputs.set_val(Dynamic.Vehicle.MASS, val=mass, units=units) prob = _get_computed_aero_data_at_altitude(alt, alt_units) - sos = prob.get_val(Dynamic.Mission.SPEED_OF_SOUND, vel_units) + sos = prob.get_val(Dynamic.Atmosphere.SPEED_OF_SOUND, vel_units) mach = vel / sos - dynamic_inputs.set_val(Dynamic.Mission.MACH, val=mach, units='unitless') + dynamic_inputs.set_val(Dynamic.Atmosphere.MACH, val=mach, units='unitless') - key = Dynamic.Mission.DENSITY + key = Dynamic.Atmosphere.DENSITY units = 'kg/m**3' val = prob.get_val(key, units) dynamic_inputs.set_val(key, val=val, units=units) - key = Dynamic.Mission.TEMPERATURE + key = Dynamic.Atmosphere.TEMPERATURE units = 'degR' val = prob.get_val(key, units) dynamic_inputs.set_val(key, val=val, units=units) - key = Dynamic.Mission.STATIC_PRESSURE + key = Dynamic.Atmosphere.STATIC_PRESSURE units = 'N/m**2' val = prob.get_val(key, units) @@ -265,32 +303,34 @@ def test_case(self, case_name): prob = _run_computed_aero_harness(flops_inputs, dynamic_inputs, 1) - computed_drag = prob.get_val(Dynamic.Mission.DRAG, 'N') + computed_drag = prob.get_val(Dynamic.Vehicle.DRAG, 'N') CDI_data, CD0_data = _computed_aero_drag_data( - flops_inputs, *_design_altitudes.get_item(case_name)) + flops_inputs, *_design_altitudes.get_item(case_name) + ) prob = om.Problem() - kwargs = {'method': 'tabular', 'CDI_data': CDI_data, - 'CD0_data': CD0_data} + kwargs = {'method': 'tabular', 'CDI_data': CDI_data, 'CD0_data': CD0_data} aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) prob.model.add_subsystem( - "aero", - aero_builder.build_mission( - num_nodes=1, aviary_inputs=flops_inputs, **kwargs), + 'aero', + aero_builder.build_mission(num_nodes=1, aviary_inputs=flops_inputs, **kwargs), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options(prob, flops_inputs) + + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, val=0.3876, units='unitless') + prob.setup(check=False, force_alloc_complex=True) - for (key, (val, units)) in dynamic_inputs: + for key, (val, units) in dynamic_inputs: try: prob.set_val(key, val, units) - except: pass # unused variable @@ -298,15 +338,12 @@ def test_case(self, case_name): prob.run_model() - tabular_drag = prob.get_val(Dynamic.Mission.DRAG, 'N') + tabular_drag = prob.get_val(Dynamic.Vehicle.DRAG, 'N') assert_near_equal(tabular_drag, computed_drag, 0.005) - partial_data = prob.check_partials( - out_stream=None, method="cs", step=1.1e-40) - assert_check_partials( - partial_data, atol=1e-9, rtol=1e-12 - ) + partial_data = prob.check_partials(out_stream=None, method='cs', step=1.1e-40) + assert_check_partials(partial_data, atol=1e-9, rtol=1e-12) # region - hardcoded data from large_single_aisle_1 (fixed alt cruise variant) FLOPS model @@ -314,59 +351,62 @@ def _default_CD0_data(): alt_range = _make_default_alt_range() # len == 13 mach_range = _make_default_mach_range() # len == 12 - CD0 = [ + # fmt: off + CD0 = np.array([ [ - 0.02182, 0.02228, 0.02278, 0.02332, - 0.02389, 0.02451, 0.02518, 0.0259, - 0.02689, 0.02801, 0.02921, 0.03049], + 0.02182, 0.02228, 0.02278, 0.02332, 0.02389, 0.02451, + 0.02518, 0.0259, 0.02689, 0.02801, 0.02921, 0.03049, + ], [ - 0.03184, 0.02043, 0.02086, 0.02132, - 0.0218, 0.02233, 0.02289, 0.02349, - 0.02414, 0.02504, 0.02605, 0.02713], + 0.03184, 0.02043, 0.02086, 0.02132, 0.0218, 0.02233, + 0.02289, 0.02349, 0.02414, 0.02504, 0.02605, 0.02713, + ], [ - 0.02827, 0.02949, 0.01946, 0.01987, - 0.02029, 0.02075, 0.02123, 0.02176, - 0.02232, 0.02293, 0.02377, 0.02471], + 0.02827, 0.02949, 0.01946, 0.01987, 0.02029, 0.02075, + 0.02123, 0.02176, 0.02232, 0.02293, 0.02377, 0.02471, + ], [ - 0.0257, 0.02676, 0.02788, 0.0187, - 0.01908, 0.01949, 0.01992, 0.02038, - 0.02088, 0.02141, 0.02199, 0.02278], + 0.0257, 0.02676, 0.02788, 0.0187, 0.01908, 0.01949, + 0.01992, 0.02038, 0.02088, 0.02141, 0.02199, 0.02278, + ], [ - 0.02366, 0.0246, 0.0256, 0.02665, - 0.01824, 0.0186, 0.01899, 0.0194, - 0.01984, 0.02031, 0.02082, 0.02137], + 0.02366, 0.0246, 0.0256, 0.02665, 0.01824, 0.0186, + 0.01899, 0.0194, 0.01984, 0.02031, 0.02082, 0.02137, + ], [ - 0.02212, 0.02297, 0.02386, 0.02481, - 0.02581, 0.01828, 0.01863, 0.019, - 0.0194, 0.01982, 0.02027, 0.02076], + 0.02212, 0.02297, 0.02386, 0.02481, 0.02581, 0.01828, + 0.01863, 0.019, 0.0194, 0.01982, 0.02027, 0.02076, + ], [ - 0.02129, 0.02201, 0.02282, 0.02368, - 0.02458, 0.02554, 0.01843, 0.01878, - 0.01914, 0.01953, 0.01994, 0.02039], + 0.02129, 0.02201, 0.02282, 0.02368, 0.02458, 0.02554, + 0.01843, 0.01878, 0.01914, 0.01953, 0.01994, 0.02039, + ], [ - 0.02087, 0.02139, 0.02209, 0.02289, - 0.02373, 0.02461, 0.02555, 0.01864, - 0.01898, 0.01934, 0.01972, 0.02014], + 0.02087, 0.02139, 0.02209, 0.02289, 0.02373, 0.02461, + 0.02555, 0.01864, 0.01898, 0.01934, 0.01972, 0.02014, + ], [ - 0.02058, 0.02105, 0.02157, 0.02227, - 0.02305, 0.02388, 0.02476, 0.02569, - 0.01909, 0.01943, 0.01979, 0.02017], + 0.02058, 0.02105, 0.02157, 0.02227, 0.02305, 0.02388, + 0.02476, 0.02569, 0.01909, 0.01943, 0.01979, 0.02017, + ], [ - 0.02058, 0.02101, 0.02149, 0.02199, - 0.02269, 0.02347, 0.02429, 0.02516, - 0.02608, 0.02021, 0.02054, 0.02089], + 0.02058, 0.02101, 0.02149, 0.02199, 0.02269, 0.02347, + 0.02429, 0.02516, 0.02608, 0.02021, 0.02054, 0.02089, + ], [ - 0.02127, 0.02168, 0.02211, 0.02258, - 0.02308, 0.02377, 0.02454, 0.02535, - 0.02622, 0.02713, 0.02222, 0.02255], + 0.02127, 0.02168, 0.02211, 0.02258, 0.02308, 0.02377, + 0.02454, 0.02535, 0.02622, 0.02713, 0.02222, 0.02255, + ], [ - 0.0229, 0.02328, 0.02368, 0.02411, - 0.02457, 0.02507, 0.02575, 0.02651, - 0.02732, 0.02818, 0.02908, 0.03704], + 0.0229, 0.02328, 0.02368, 0.02411, 0.02457, 0.02507, + 0.02575, 0.02651, 0.02732, 0.02818, 0.02908, 0.03704, + ], [ - 0.03737, 0.03772, 0.03809, 0.03849, - 0.03891, 0.03937, 0.03987, 0.04054, - 0.0413, 0.0421, 0.04294, 0.04384]] + 0.03737, 0.03772, 0.03809, 0.03849, 0.03891, 0.03937, + 0.03987, 0.04054, 0.0413, 0.0421, 0.04294, 0.04384, + ], + ]) + # fmt: on # mach_list, alt_list = np.meshgrid(mach_range, alt_range) @@ -376,7 +416,7 @@ def _default_CD0_data(): CD0_data = NamedValues() CD0_data.set_val(Dynamic.Mission.ALTITUDE, alt_range, 'ft') - CD0_data.set_val(Dynamic.Mission.MACH, mach_range) + CD0_data.set_val(Dynamic.Atmosphere.MACH, mach_range) CD0_data.set_val('zero_lift_drag_coefficient', CD0) return CD0_data @@ -386,55 +426,58 @@ def _default_CDI_data(): mach_range = _make_default_mach_range() # len == 12 cl_range = _make_default_cl_range() # len == 15 - CDI = [ + # fmt: off + CDI = np.array([ [ - 0.00114, 0.00138, 0.0019, 0.0027, 0.00378, - 0.00511, 0.00669, 0.00837, 0.0104, 0.01295, - 0.01558, 0.01837, 0.0215, 0.025, 0.02888], # 0 + 0.00114, 0.00138, 0.0019, 0.0027, 0.00378, 0.00511, 0.00669, + 0.00837, 0.0104, 0.01295, 0.01558, 0.01837, 0.0215, 0.025, 0.02888, + ], # 0 [ - 0.00113, 0.00137, 0.0019, 0.0027, 0.00377, - 0.00511, 0.00669, 0.00837, 0.0104, 0.01295, - 0.01558, 0.01837, 0.0215, 0.025, 0.02888], # 1 + 0.00113, 0.00137, 0.0019, 0.0027, 0.00377, 0.00511, 0.00669, + 0.00837, 0.0104, 0.01295, 0.01558, 0.01837, 0.0215, 0.025, 0.02888, + ], # 1 [ - 0.00114, 0.00138, 0.0019, 0.0027, 0.00378, - 0.00511, 0.00669, 0.00837, 0.0104, 0.01295, - 0.01558, 0.01837, 0.0215, 0.025, 0.02888], # 2 + 0.00114, 0.00138, 0.0019, 0.0027, 0.00378, 0.00511, 0.00669, + 0.00837, 0.0104, 0.01295, 0.01558, 0.01837, 0.0215, 0.025, 0.02888, + ], # 2 [ - 0.00117, 0.00138, 0.0019, 0.0027, 0.00379, - 0.00513, 0.0067, 0.00837, 0.01041, 0.01295, - 0.01558, 0.01837, 0.0215, 0.025, 0.02888], # 3 + 0.00117, 0.00138, 0.0019, 0.0027, 0.00379, 0.00513, 0.0067, + 0.00837, 0.01041, 0.01295, 0.01558, 0.01837, 0.0215, 0.025, 0.02888, + ], # 3 [ - 0.00121, 0.0014, 0.0019, 0.0027, 0.00381, - 0.00515, 0.0067, 0.00838, 0.01042, 0.01294, - 0.01558, 0.01837, 0.0215, 0.025, 0.02888], # 4 + 0.00121, 0.0014, 0.0019, 0.0027, 0.00381, 0.00515, 0.0067, + 0.00838, 0.01042, 0.01294, 0.01558, 0.01837, 0.0215, 0.025, 0.02888, + ], # 4 [ - 0.00132, 0.00144, 0.0019, 0.00271, 0.00387, - 0.00522, 0.00673, 0.00839, 0.01043, 0.01294, - 0.01558, 0.01837, 0.0215, 0.025, 0.02888], # 5 + 0.00132, 0.00144, 0.0019, 0.00271, 0.00387, 0.00522, 0.00673, + 0.00839, 0.01043, 0.01294, 0.01558, 0.01837, 0.0215, 0.025, 0.02888, + ], # 5 [ - 0.00142, 0.00148, 0.00192, 0.00273, 0.00392, - 0.00529, 0.00675, 0.00841, 0.01045, 0.01293, - 0.01556, 0.01841, 0.02169, 0.02542, 0.02961], # 6 + 0.00142, 0.00148, 0.00192, 0.00273, 0.00392, 0.00529, 0.00675, + 0.00841, 0.01045, 0.01293, 0.01556, 0.01841, 0.02169, 0.02542, 0.02961, + ], # 6 [ - 0.0015, 0.00152, 0.00194, 0.00276, 0.00397, - 0.00534, 0.00678, 0.00842, 0.01046, 0.0129, - 0.01562, 0.01891, 0.02291, 0.02769, 0.03327], # 7 + 0.0015, 0.00152, 0.00194, 0.00276, 0.00397, 0.00534, 0.00678, + 0.00842, 0.01046, 0.0129, 0.01562, 0.01891, 0.02291, 0.02769, 0.03327, + ], # 7 [ - 0.00166, 0.00159, 0.00196, 0.00279, 0.00406, - 0.00549, 0.00693, 0.00855, 0.01065, 0.01328, - 0.01686, 0.02156, 0.02667, 0.03227, 0.03832], # 8 + 0.00166, 0.00159, 0.00196, 0.00279, 0.00406, 0.00549, 0.00693, + 0.00855, 0.01065, 0.01328, 0.01686, 0.02156, 0.02667, 0.03227, 0.03832, + ], # 8 [ - 0.00208, 0.00175, 0.00201, 0.00285, 0.00428, - 0.00592, 0.0076, 0.00965, 0.01245, 0.01657, - 0.0215, 0.02697, 0.0341, 0.04264, 0.0526], # 9 + 0.00208, 0.00175, 0.00201, 0.00285, 0.00428, 0.00592, 0.0076, + 0.00965, 0.01245, 0.01657, 0.0215, 0.02697, 0.0341, 0.04264, 0.0526, + ], # 9 [ - 0.00336, 0.00221, 0.00209, 0.003, 0.00494, - 0.00757, 0.01074, 0.01452, 0.01987, 0.02654, - 0.03295, 0.03957, 0.04634, 0.05334, 0.06059], # 10 + 0.00336, 0.00221, 0.00209, 0.003, 0.00494, 0.00757, 0.01074, + 0.01452, 0.01987, 0.02654, 0.03295, 0.03957, 0.04634, 0.05334, 0.06059, + ], # 10 [ - 0.00636, 0.00327, 0.00224, 0.00324, 0.00627, - 0.01154, 0.01915, 0.02577, 0.03848, 0.05251, - 0.05737, 0.06445, 0.0703, 0.07582, 0.08127]] # 11 + 0.00636, 0.00327, 0.00224, 0.00324, 0.00627, 0.01154, 0.01915, + 0.02577, 0.03848, 0.05251, 0.05737, 0.06445, 0.0703, 0.07582, 0.08127, + ], + ]) # 11 + # fmt: on # cl_list, mach_list = np.meshgrid(cl_range, mach_range) @@ -442,40 +485,36 @@ def _default_CDI_data(): # cl_list = np.array(cl_list).flatten() # mach_list = np.array(mach_list).flatten() CDI_data = NamedValues() - CDI_data.set_val(Dynamic.Mission.MACH, mach_range) + CDI_data.set_val(Dynamic.Atmosphere.MACH, mach_range) CDI_data.set_val('lift_coefficient', cl_range) CDI_data.set_val('lift_dependent_drag_coefficient', CDI) return CDI_data +# fmt: off def _make_default_alt_range(): - alt_range = [ - 0, 5000, 10000, 15000, - 20000, 25000, 30000, 35000, - 40000, 45000, 50000, 55000, - 60000] + alt_range = np.array([ + 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000 + ]) return alt_range def _make_default_mach_range(): - mach_range = [ - 0.200, 0.300, 0.400, 0.500, - 0.600, 0.700, 0.750, 0.775, - 0.800, 0.825, 0.850, 0.875] + mach_range = np.array([ + 0.200, 0.300, 0.400, 0.500, 0.600, 0.700, 0.750, 0.775, 0.800, 0.825, 0.850, 0.875 + ]) return mach_range def _make_default_cl_range(): - cl_range = [ - 0.15, 0.2, 0.25, 0.3, - 0.35, 0.4, 0.45, 0.5, - 0.55, 0.6, 0.65, 0.7, - 0.75, 0.8, 0.85] + cl_range = np.array([0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85]) return cl_range +# fmt: on + # endregion - hardcoded data from large_single_aisle_1 (fixed alt cruise variant) FLOPS model @@ -483,13 +522,13 @@ def _make_default_cl_range(): def _computed_aero_drag_data(flops_inputs: AviaryValues, design_altitude, units): nsteps = 12 - start = 0. - stop = 70000. + start = 0.0 + stop = 70000.0 step = (stop - start) / nsteps alt = np.arange(start, stop, step) # ft start = 0.2 - stop = 1. + stop = 1.0 step = (stop - start) / nsteps seed = np.arange(start, stop, step) @@ -501,20 +540,20 @@ def _computed_aero_drag_data(flops_inputs: AviaryValues, design_altitude, units) # calculate temperature (degR), static pressure (lbf/ft**2), and mass (lbm) at design # altitude from lift coefficients and Mach numbers prob: om.Problem = _get_computed_aero_data_at_altitude(design_altitude, units) - T = prob.get_val(Dynamic.Mission.TEMPERATURE, 'degR') - P = prob.get_val(Dynamic.Mission.STATIC_PRESSURE, 'lbf/ft**2') + T = prob.get_val(Dynamic.Atmosphere.TEMPERATURE, 'degR') + P = prob.get_val(Dynamic.Atmosphere.STATIC_PRESSURE, 'lbf/ft**2') - mass = lift = CL * S * 0.5 * 1.4 * P * mach**2 # lbf -> lbm * 1g + mass = CL * S * 0.5 * 1.4 * P * mach**2 # lbf -> lbm * 1g # calculate lift-dependent drag coefficient table, including pressure drag effects nn = len(mass) dynamic_inputs = AviaryValues() - dynamic_inputs.set_val(Dynamic.Mission.MACH, val=mach) - dynamic_inputs.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P, units='lbf/ft**2') - dynamic_inputs.set_val(Dynamic.Mission.TEMPERATURE, val=T, units='degR') - dynamic_inputs.set_val(Dynamic.Mission.MASS, val=mass, units='lbm') + dynamic_inputs.set_val(Dynamic.Atmosphere.MACH, val=mach) + dynamic_inputs.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P, units='lbf/ft**2') + dynamic_inputs.set_val(Dynamic.Atmosphere.TEMPERATURE, val=T, units='degR') + dynamic_inputs.set_val(Dynamic.Vehicle.MASS, val=mass, units='lbm') prob = _run_computed_aero_harness(flops_inputs, dynamic_inputs, nn) @@ -522,7 +561,7 @@ def _computed_aero_drag_data(flops_inputs: AviaryValues, design_altitude, units) CDI = np.reshape(CDI.flatten(), (nsteps, nsteps)) CDI_data = NamedValues() - CDI_data.set_val(Dynamic.Mission.MACH, seed) + CDI_data.set_val(Dynamic.Atmosphere.MACH, seed) CDI_data.set_val('lift_coefficient', seed) CDI_data.set_val('lift_dependent_drag_coefficient', CDI) @@ -535,18 +574,18 @@ def _computed_aero_drag_data(flops_inputs: AviaryValues, design_altitude, units) dynamic_inputs = AviaryValues() - dynamic_inputs.set_val(Dynamic.Mission.MACH, val=mach) - dynamic_inputs.set_val(Dynamic.Mission.MASS, val=mass, units=units) + dynamic_inputs.set_val(Dynamic.Atmosphere.MACH, val=mach) + dynamic_inputs.set_val(Dynamic.Vehicle.MASS, val=mass, units=units) CD0 = [] for h in alt: prob: om.Problem = _get_computed_aero_data_at_altitude(h, 'ft') - T = prob.get_val(Dynamic.Mission.TEMPERATURE, 'degR') - P = prob.get_val(Dynamic.Mission.STATIC_PRESSURE, 'lbf/ft**2') + T = prob.get_val(Dynamic.Atmosphere.TEMPERATURE, 'degR') + P = prob.get_val(Dynamic.Atmosphere.STATIC_PRESSURE, 'lbf/ft**2') - dynamic_inputs.set_val(Dynamic.Mission.STATIC_PRESSURE, val=P, units='lbf/ft**2') - dynamic_inputs.set_val(Dynamic.Mission.TEMPERATURE, val=T, units='degR') + dynamic_inputs.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, val=P, units='lbf/ft**2') + dynamic_inputs.set_val(Dynamic.Atmosphere.TEMPERATURE, val=T, units='degR') prob = _run_computed_aero_harness(flops_inputs, dynamic_inputs, nn) @@ -556,7 +595,7 @@ def _computed_aero_drag_data(flops_inputs: AviaryValues, design_altitude, units) CD0_data = NamedValues() CD0_data.set_val(Dynamic.Mission.ALTITUDE, alt, 'ft') - CD0_data.set_val(Dynamic.Mission.MACH, seed) + CD0_data.set_val(Dynamic.Atmosphere.MACH, seed) CD0_data.set_val('zero_lift_drag_coefficient', CD0) return (CDI_data, CD0_data) @@ -565,9 +604,7 @@ def _computed_aero_drag_data(flops_inputs: AviaryValues, design_altitude, units) def _get_computed_aero_data_at_altitude(altitude, units): prob = om.Problem() - prob.model.add_subsystem( - name='atmosphere', subsys=Atmosphere(num_nodes=1), promotes=['*'] - ) + prob.model.add_subsystem(name='atmosphere', subsys=Atmosphere(num_nodes=1), promotes=['*']) prob.setup() @@ -579,8 +616,9 @@ def _get_computed_aero_data_at_altitude(altitude, units): def _run_computed_aero_harness(flops_inputs, dynamic_inputs, num_nodes): - prob = om.Problem( - _ComputedAeroHarness(num_nodes=num_nodes, aviary_options=flops_inputs)) + prob = om.Problem(_ComputedAeroHarness(num_nodes=num_nodes, aviary_options=flops_inputs)) + + setup_model_options(prob, flops_inputs) prob.setup() @@ -593,21 +631,20 @@ def _run_computed_aero_harness(flops_inputs, dynamic_inputs, num_nodes): class _ComputedAeroHarness(om.Group): - ''' - Calculate drag and drag polars. - ''' + """Calculate drag and drag polars.""" def initialize(self): options = self.options options.declare('num_nodes', types=int) - options.declare( - 'gamma', default=1.4, desc='Ratio of specific heats for air.') + options.declare('gamma', default=1.4, desc='Ratio of specific heats for air.') options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): options = self.options @@ -616,17 +653,14 @@ def setup(self): gamma = options['gamma'] aviary_options: AviaryValues = options['aviary_options'] - engine = build_engine_deck(aviary_options) + engines = [build_engine_deck(aviary_options)] # don't need mass, skip it - default_premission_subsystems = get_default_premission_subsystems('FLOPS', engine)[ - :-1] + default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines)[:-1] # Upstream pre-mission analysis for aero pre_mission: om.Group = self.add_subsystem( 'pre_mission', - CorePreMission( - aviary_options=aviary_options, subsystems=default_premission_subsystems - ), + CorePreMission(aviary_options=aviary_options, subsystems=default_premission_subsystems), promotes_inputs=['aircraft:*'], promotes_outputs=['aircraft:*', 'mission:*'], ) @@ -636,25 +670,30 @@ def setup(self): aero_builder = CoreAerodynamicsBuilder(code_origin=FLOPS) self.add_subsystem( - "aero", - aero_builder.build_mission( - num_nodes=nn, aviary_inputs=aviary_options, **kwargs), + 'aero', + aero_builder.build_mission(num_nodes=nn, aviary_inputs=aviary_options, **kwargs), promotes_inputs=['*'], promotes_outputs=['*'], ) - key = Aircraft.Engine.SCALED_SLS_THRUST + # key = Aircraft.Engine.SCALED_SLS_THRUST + key = Aircraft.Engine.SCALE_FACTOR val, units = aviary_options.get_item(key) pre_mission.set_input_defaults(key, val, units) -_design_altitudes = AviaryValues({ - 'LargeSingleAisle1FLOPS': (41000, 'ft'), 'LargeSingleAisle2FLOPS': (41000, 'ft'), 'N3CC': (43000, 'ft')}) +_design_altitudes = AviaryValues( + { + 'LargeSingleAisle1FLOPS': (41000, 'ft'), + 'LargeSingleAisle2FLOPS': (41000, 'ft'), + 'AdvancedSingleAisle': (43000, 'ft'), + } +) # endregion - computed aero data -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = TabularAeroGroupDataTest() # test.setUp() - # test.test_case() + # test.test_parameters() diff --git a/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py b/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py index ffddd89f0b..b5eba96430 100644 --- a/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py +++ b/aviary/subsystems/aerodynamics/flops_based/test/test_takeoff_aero_group.py @@ -2,19 +2,23 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + N3CC, + takeoff_subsystem_options, + takeoff_subsystem_options_spoilers, +) from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.utils.aviary_values import AviaryValues, get_items -from aviary.models.N3CC.N3CC_data import ( - N3CC, takeoff_subsystem_options, takeoff_subsystem_options_spoilers) -from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.utils.preprocessors import preprocess_options class TestTakeoffAeroGroup(unittest.TestCase): - def test_takeoff_aero_group(self): prob: om.Problem = make_problem(takeoff_subsystem_options) @@ -22,7 +26,7 @@ def test_takeoff_aero_group(self): tol = 1e-12 - for (key, (desired, units)) in get_items(_regression_data): + for key, (desired, units) in get_items(_regression_data): try: actual = prob.get_val(key, units) @@ -33,7 +37,7 @@ def test_takeoff_aero_group(self): raise ValueError(msg) from None - partials = prob.check_partials(out_stream=None, method="cs") + partials = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partials, atol=1e-10, rtol=1e-12) def test_takeoff_aero_group_spoiler(self): @@ -43,7 +47,7 @@ def test_takeoff_aero_group_spoiler(self): tol = 1e-12 - for (key, (desired, units)) in get_items(_regression_data_spoiler): + for key, (desired, units) in get_items(_regression_data_spoiler): try: actual = prob.get_val(key, units) @@ -54,29 +58,39 @@ def test_takeoff_aero_group_spoiler(self): raise ValueError(msg) from None - partials = prob.check_partials(out_stream=None, method="cs") + partials = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partials, atol=1e-10, rtol=1e-12) def make_problem(subsystem_options={}): - ''' + """ Return a problem that covers all three computational ranges: - in ground effect (on the ground); - in transition (in the air, but near enough to the ground for limited effect); - in free flight (no ground effect). - ''' + """ nn = 3 aviary_keys = ( Mission.Takeoff.DRAG_COEFFICIENT_MIN, - Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.HEIGHT, - Aircraft.Wing.SPAN, Aircraft.Wing.AREA) + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.HEIGHT, + Aircraft.Wing.SPAN, + Aircraft.Wing.AREA, + ) - aviary_inputs = AviaryValues(N3CC['inputs']) + # aviary_inputs = AviaryValues(N3CC['inputs']) + aviary_inputs = AviaryValues() + aviary_inputs.set_val(Aircraft.LandingGear.DRAG_COEFFICIENT, 0.024) + aviary_inputs.set_val(Mission.Takeoff.DRAG_COEFFICIENT_MIN, 0.05) + aviary_inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 11.5587605382765) + aviary_inputs.set_val(Aircraft.Wing.HEIGHT, 8.6, 'ft') + aviary_inputs.set_val(Aircraft.Wing.SPAN, 118.7505278165, 'ft') + aviary_inputs.set_val(Aircraft.Wing.AREA, 1220.0, 'ft**2') dynamic_inputs = AviaryValues( { - 'angle_of_attack': (np.array([0.0, 2.0, 6.0]), 'deg'), + Dynamic.Vehicle.ANGLE_OF_ATTACK: (np.array([0.0, 2.0, 6.0]), 'deg'), Dynamic.Mission.ALTITUDE: (np.array([0.0, 32.0, 55.0]), 'm'), Dynamic.Mission.FLIGHT_PATH_ANGLE: (np.array([0.0, 0.5, 1.0]), 'deg'), } @@ -88,21 +102,24 @@ def make_problem(subsystem_options={}): prob.model.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=nn), - promotes=['*', (Dynamic.Mission.DYNAMIC_PRESSURE, 'skip')], + promotes=['*', (Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'skip')], ) aero_builder = CoreAerodynamicsBuilder(code_origin=LegacyCode.FLOPS) prob.model.add_subsystem( name='core_aerodynamics', - subsys=aero_builder.build_mission(num_nodes=nn, - aviary_inputs=aviary_inputs, - **subsystem_options['core_aerodynamics']), - promotes_inputs=aero_builder.mission_inputs( - **subsystem_options['core_aerodynamics']), - promotes_outputs=aero_builder.mission_outputs(**subsystem_options['core_aerodynamics'])) + subsys=aero_builder.build_mission( + num_nodes=nn, aviary_inputs=aviary_inputs, **subsystem_options['core_aerodynamics'] + ), + promotes_inputs=aero_builder.mission_inputs(**subsystem_options['core_aerodynamics']), + promotes_outputs=aero_builder.mission_outputs(**subsystem_options['core_aerodynamics']), + ) prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, np.zeros(nn), 'm') + prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, np.ones(nn), 'psf') + + setup_model_options(prob, aviary_inputs) prob.setup(force_alloc_complex=True) @@ -117,7 +134,7 @@ def make_problem(subsystem_options={}): prob.set_val(key, val, units) - for (key, (val, units)) in dynamic_inputs: + for key, (val, units) in dynamic_inputs: prob.set_val(key, val, units) return prob @@ -132,26 +149,40 @@ def make_problem(subsystem_options={}): # - last generated 2023 June 8 # - generate new regression data if, and only if, takeoff aero group is updated with a # more trusted implementation -_regression_data = AviaryValues({ - Dynamic.Mission.LIFT: ( - [3028.138891962988, 4072.059743068957, 6240.85493286], _units_lift), - Dynamic.Mission.DRAG: ( - [434.6285684000267, 481.5245555324278, 586.0976806512001], _units_drag)}) +_regression_data = AviaryValues( + { + Dynamic.Vehicle.LIFT: ( + [3028.138891962988, 4072.059743068957, 6240.85493286], + _units_lift, + ), + Dynamic.Vehicle.DRAG: ( + [434.6285684000267, 481.5245555324278, 586.0976806512001], + _units_drag, + ), + } +) # NOTE: # - results from `generate_regression_data_spoiler()` # - last generated 2023 June 8 # - generate new regression data if, and only if, takeoff aero group is updated with a # more trusted implementation -_regression_data_spoiler = AviaryValues({ - Dynamic.Mission.LIFT: ( - [-1367.5937129210124, -323.67286181504335, 1845.1223279759993], _units_lift), - Dynamic.Mission.DRAG: ( - [895.9091503940268, 942.8051375264279, 1047.3782626452], _units_drag)}) +_regression_data_spoiler = AviaryValues( + { + Dynamic.Vehicle.LIFT: ( + [-1367.5937129210124, -323.67286181504335, 1845.1223279759993], + _units_lift, + ), + Dynamic.Vehicle.DRAG: ( + [895.9091503940268, 942.8051375264279, 1047.3782626452], + _units_drag, + ), + } +) def generate_regression_data(): - ''' + """ Generate regression data that covers all three computational ranges: - in ground effect (on the ground); - in transition (in the air, but near enough to the ground for limited effect); @@ -163,12 +194,12 @@ def generate_regression_data(): ----- Use this function to generate new regression data if, and only if, ground effect is updated with a more trusted implementation. - ''' + """ _generate_regression_data(takeoff_subsystem_options) def generate_regression_data_spoiler(): - ''' + """ Generate regression data that covers all three computational ranges: - in ground effect (on the ground); - in transition (in the air, but near enough to the ground for limited effect); @@ -180,12 +211,12 @@ def generate_regression_data_spoiler(): ----- Use this function to generate new regression data if, and only if, ground effect is updated with a more trusted implementation. - ''' + """ _generate_regression_data(takeoff_subsystem_options_spoilers) def _generate_regression_data(subsystem_options={}): - ''' + """ Generate regression data that covers all three computational ranges: - in ground effect (on the ground); - in transition (in the air, but near enough to the ground for limited effect); @@ -197,19 +228,21 @@ def _generate_regression_data(subsystem_options={}): ----- Use this function to generate new regression data if, and only if, ground effect is updated with a more trusted implementation. - ''' + """ prob: om.Problem = make_problem(subsystem_options) prob.run_model() - lift = prob.get_val(Dynamic.Mission.LIFT, _units_lift) - drag = prob.get_val(Dynamic.Mission.DRAG, _units_drag) + lift = prob.get_val(Dynamic.Vehicle.LIFT, _units_lift) + drag = prob.get_val(Dynamic.Vehicle.DRAG, _units_drag) - prob.check_partials(compact_print=True, method="cs") + prob.check_partials(compact_print=True, method='cs') print('lift', *lift, sep=', ') print('drag', *drag, sep=', ') -if __name__ == "__main__": - unittest.main() +if __name__ == '__main__': + # unittest.main() + test = TestTakeoffAeroGroup() + test.test_takeoff_aero_group() diff --git a/aviary/subsystems/aerodynamics/gasp_based/common.py b/aviary/subsystems/aerodynamics/gasp_based/common.py index 8af9801d10..c41b04a896 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/common.py +++ b/aviary/subsystems/aerodynamics/gasp_based/common.py @@ -1,89 +1,94 @@ import numpy as np import openmdao.api as om -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Dynamic class AeroForces(om.ExplicitComponent): - """Compute lift and drag from coefficients""" + """Compute lift and drag from coefficients.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] - self.add_input("CL", 1.0, units="unitless", shape=nn, desc="Lift coefficient") - self.add_input("CD", 1.0, units="unitless", shape=nn, desc="Drag coefficient") - self.add_input(Dynamic.Mission.DYNAMIC_PRESSURE, 1.0, - units="psf", shape=nn, desc="Dynamic pressure") + self.add_input('CL', 1.0, units='unitless', shape=nn, desc='Lift coefficient') + self.add_input('CD', 1.0, units='unitless', shape=nn, desc='Drag coefficient') + add_aviary_input(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, units='psf', shape=nn) - add_aviary_input(self, Aircraft.Wing.AREA, val=1370.3) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') - self.add_output(Dynamic.Mission.LIFT, units="lbf", shape=nn, desc="Lift force") - self.add_output(Dynamic.Mission.DRAG, units="lbf", shape=nn, desc="Drag force") + add_aviary_output(self, Dynamic.Vehicle.LIFT, units='lbf', shape=nn) + add_aviary_output(self, Dynamic.Vehicle.DRAG, units='lbf', shape=nn) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) self.declare_partials( - Dynamic.Mission.LIFT, [ - "CL", Dynamic.Mission.DYNAMIC_PRESSURE], rows=arange, cols=arange) - self.declare_partials(Dynamic.Mission.LIFT, [Aircraft.Wing.AREA]) + Dynamic.Vehicle.LIFT, + ['CL', Dynamic.Atmosphere.DYNAMIC_PRESSURE], + rows=arange, + cols=arange, + ) + self.declare_partials(Dynamic.Vehicle.LIFT, [Aircraft.Wing.AREA]) self.declare_partials( - Dynamic.Mission.DRAG, [ - "CD", Dynamic.Mission.DYNAMIC_PRESSURE], rows=arange, cols=arange) - self.declare_partials(Dynamic.Mission.DRAG, [Aircraft.Wing.AREA]) + Dynamic.Vehicle.DRAG, + ['CD', Dynamic.Atmosphere.DYNAMIC_PRESSURE], + rows=arange, + cols=arange, + ) + self.declare_partials(Dynamic.Vehicle.DRAG, [Aircraft.Wing.AREA]) def compute(self, inputs, outputs): CL, CD, q, wing_area = inputs.values() - outputs[Dynamic.Mission.LIFT] = q * CL * wing_area - outputs[Dynamic.Mission.DRAG] = q * CD * wing_area + outputs[Dynamic.Vehicle.LIFT] = q * CL * wing_area + outputs[Dynamic.Vehicle.DRAG] = q * CD * wing_area def compute_partials(self, inputs, J): CL, CD, q, wing_area = inputs.values() - J[Dynamic.Mission.LIFT, "CL"] = q * wing_area - J[Dynamic.Mission.LIFT, Dynamic.Mission.DYNAMIC_PRESSURE] = CL * wing_area - J[Dynamic.Mission.LIFT, Aircraft.Wing.AREA] = q * CL + J[Dynamic.Vehicle.LIFT, 'CL'] = q * wing_area + J[Dynamic.Vehicle.LIFT, Dynamic.Atmosphere.DYNAMIC_PRESSURE] = CL * wing_area + J[Dynamic.Vehicle.LIFT, Aircraft.Wing.AREA] = q * CL - J[Dynamic.Mission.DRAG, "CD"] = q * wing_area - J[Dynamic.Mission.DRAG, Dynamic.Mission.DYNAMIC_PRESSURE] = CD * wing_area - J[Dynamic.Mission.DRAG, Aircraft.Wing.AREA] = q * CD + J[Dynamic.Vehicle.DRAG, 'CD'] = q * wing_area + J[Dynamic.Vehicle.DRAG, Dynamic.Atmosphere.DYNAMIC_PRESSURE] = CD * wing_area + J[Dynamic.Vehicle.DRAG, Aircraft.Wing.AREA] = q * CD class CLFromLift(om.ExplicitComponent): - """Compute a CL from lift, used commonly for getting CL required""" + """Compute a CL from lift, used commonly for getting CL required.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) def setup(self): - nn = self.options["num_nodes"] - self.add_input("lift_req", 1, units="lbf", shape=nn, desc="Lift force") - self.add_input(Dynamic.Mission.DYNAMIC_PRESSURE, 1.0, - units="psf", shape=nn, desc="Dynamic pressure") + nn = self.options['num_nodes'] + self.add_input('lift_req', 1, units='lbf', shape=nn, desc='Lift force') + add_aviary_input(self, Dynamic.Atmosphere.DYNAMIC_PRESSURE, shape=nn, units='psf') - add_aviary_input(self, Aircraft.Wing.AREA, val=1370.3) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') - self.add_output("CL", shape=nn, units='unitless', desc="Lift coefficient") + self.add_output('CL', shape=nn, units='unitless', desc='Lift coefficient') def setup_partials(self): - ar = np.arange(self.options["num_nodes"]) + ar = np.arange(self.options['num_nodes']) self.declare_partials( - "CL", ["lift_req", Dynamic.Mission.DYNAMIC_PRESSURE], rows=ar, cols=ar) - self.declare_partials("CL", [Aircraft.Wing.AREA]) + 'CL', ['lift_req', Dynamic.Atmosphere.DYNAMIC_PRESSURE], rows=ar, cols=ar + ) + self.declare_partials('CL', [Aircraft.Wing.AREA]) def compute(self, inputs, outputs): lift_req, q, wing_area = inputs.values() - outputs["CL"] = lift_req / (q * wing_area) + outputs['CL'] = lift_req / (q * wing_area) def compute_partials(self, inputs, J): lift_req, q, wing_area = inputs.values() - J["CL", "lift_req"] = 1 / (q * wing_area) - J["CL", Dynamic.Mission.DYNAMIC_PRESSURE] = -lift_req / (q**2 * wing_area) - J["CL", Aircraft.Wing.AREA] = -lift_req / (q * wing_area**2) + J['CL', 'lift_req'] = 1 / (q * wing_area) + J['CL', Dynamic.Atmosphere.DYNAMIC_PRESSURE] = -lift_req / (q**2 * wing_area) + J['CL', Aircraft.Wing.AREA] = -lift_req / (q * wing_area**2) class TimeRamp(om.ExplicitComponent): @@ -94,52 +99,51 @@ def __init__(self, **kwargs): self._last_index = None def initialize(self): - self.options.declare("num_inputs", default=1, types=int) - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_inputs', default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) self.options.declare( - "ramp_up", + 'ramp_up', default=True, types=bool, - desc="True to ramp up from 0, False to ramp down to 0", + desc='True to ramp up from 0, False to ramp down to 0', ) self.options.declare( - "units", - default="unitless", + 'units', + default='unitless', types=str, - desc="Units of the input and output variables", + desc='Units of the input and output variables', ) def setup(self): - k = self.options["num_inputs"] - nn = self.options["num_nodes"] - units = self.options["units"] + k = self.options['num_inputs'] + nn = self.options['num_nodes'] + units = self.options['units'] - self.add_input("t_init", 0.0, units="s", desc="Time at which to start the ramp") - self.add_input("t_curr", 0.0, units="s", shape=nn, desc="Current time") - self.add_input("duration", 1.0, units="s", desc="Time duration of the ramp") + self.add_input('t_init', 0.0, units='s', desc='Time at which to start the ramp') + self.add_input('t_curr', 0.0, units='s', shape=nn, desc='Current time') + self.add_input('duration', 1.0, units='s', desc='Time duration of the ramp') self.add_input( - "x", 1.0, shape=(k, nn), units=units, desc="Input values in the 'on' condition" + 'x', 1.0, shape=(k, nn), units=units, desc="Input values in the 'on' condition" ) - self.add_output("y", shape=(k, nn), units=units, - desc="Input values ramped over time") + self.add_output('y', shape=(k, nn), units=units, desc='Input values ramped over time') # Declare partials, taking advantage of sparsity. row_col = np.arange(k * nn) - self.declare_partials(of="y", wrt="x", rows=row_col, cols=row_col) + self.declare_partials(of='y', wrt='x', rows=row_col, cols=row_col) col = np.tile(np.arange(nn), k) - self.declare_partials(of="y", wrt="t_curr", rows=row_col, cols=col) + self.declare_partials(of='y', wrt='t_curr', rows=row_col, cols=col) - self.declare_partials(of="y", wrt=["t_init", "duration"]) + self.declare_partials(of='y', wrt=['t_init', 'duration']) def compute(self, inputs, outputs): - x = inputs["x"] - y = outputs["y"] - t_init = inputs["t_init"] - t_curr = inputs["t_curr"] - duration = inputs["duration"] + x = inputs['x'] + y = outputs['y'] + t_init = inputs['t_init'] + t_curr = inputs['t_curr'] + duration = inputs['duration'] t_end = t_init + duration idx = np.searchsorted(t_curr.real, [t_init.real, t_end.real]) @@ -150,7 +154,7 @@ def compute(self, inputs, outputs): fact = 1.0 / duration scale = (t_curr[i1:i2] - t_init) * fact - if self.options["ramp_up"]: + if self.options['ramp_up']: y[:, :i1] = 0 y[:, i2:] = x[:, i2:] y[:, i1:i2] = scale * x[:, i1:i2] @@ -160,13 +164,13 @@ def compute(self, inputs, outputs): y[:, i1:i2] = (1 - scale) * x[:, i1:i2] def compute_partials(self, inputs, J): - nn = self.options["num_nodes"] - k = self.options["num_inputs"] + nn = self.options['num_nodes'] + k = self.options['num_inputs'] - x = inputs["x"] - t_init = inputs["t_init"] - t_curr = inputs["t_curr"] - duration = inputs["duration"] + x = inputs['x'] + t_init = inputs['t_init'] + t_curr = inputs['t_curr'] + duration = inputs['duration'] i1, i2 = self._last_index @@ -177,7 +181,7 @@ def compute_partials(self, inputs, J): d_x = np.zeros(nn) d_tcurr = x.copy() - if self.options["ramp_up"]: + if self.options['ramp_up']: d_x[i2:] = 1.0 d_x[i1:i2] = scale @@ -209,14 +213,14 @@ def compute_partials(self, inputs, J): d_tinit[:, :i1] = 0.0 d_tinit[:, i2:] = 0.0 - J["y", "x"] = np.tile(d_x, k) - J["y", "t_curr"] = d_tcurr.ravel() - J["y", "duration"] = d_duration.ravel() - J["y", "t_init"] = d_tinit.ravel() + J['y', 'x'] = np.tile(d_x, k) + J['y', 't_curr'] = d_tcurr.ravel() + J['y', 'duration'] = d_duration.ravel() + J['y', 't_init'] = d_tinit.ravel() class TanhRampComp(om.ExplicitComponent): - """ Differentiable transition from one steady state condition to another using a hyperbolic tangent. + """Differentiable transition from one steady state condition to another using a hyperbolic tangent. The hyperbolic tangent activation function is: r_1(t) = np.tanh(t) This has a response centered about t=0, and a value of (-0.996, 0.996) at (-np.pi, np.pi) (thus the duration @@ -232,10 +236,19 @@ def __init__(self, **kwargs): super().__init__(**kwargs) self._ramps = {} - def add_ramp(self, output_name, output_units=None, shape=(1,), initial_val=0.0, - final_val=1.0, t_init_val=0.0, t_duration_val=1.0): + def add_ramp( + self, + output_name, + output_units=None, + shape=(1,), + initial_val=0.0, + final_val=1.0, + t_init_val=0.0, + t_duration_val=1.0, + ): """ Add a tanh ramp function with the given output name to the component. + Parameters ---------- output_name : str @@ -256,90 +269,105 @@ def add_ramp(self, output_name, output_units=None, shape=(1,), initial_val=0.0, final value. Again, the hyperbolic tangent function will never exactly equal the final value but it is relatively flat after this duration is expired. """ - self._ramps[output_name] = {'shape': shape, - 'units': output_units, - 'initial_val_name': f"{output_name}:initial_val", - 'initial_val': initial_val, - 'final_val_name': f"{output_name}:final_val", - 'final_val': final_val, - 't_init_name': f"{output_name}:t_init", - 't_init_val': t_init_val, - 't_duration_name': f"{output_name}:t_duration", - 't_duration_val': t_duration_val} + self._ramps[output_name] = { + 'shape': shape, + 'units': output_units, + 'initial_val_name': f'{output_name}:initial_val', + 'initial_val': initial_val, + 'final_val_name': f'{output_name}:final_val', + 'final_val': final_val, + 't_init_name': f'{output_name}:t_init', + 't_init_val': t_init_val, + 't_duration_name': f'{output_name}:t_duration', + 't_duration_val': t_duration_val, + } def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare("time_units", types=str, default='s', allow_none=True) + self.options.declare('num_nodes', types=int) + self.options.declare('time_units', types=str, default='s', allow_none=True) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] ar = np.arange(nn, dtype=int) - self.add_input("time", units=self.options["time_units"], shape=(nn,)) + self.add_input('time', units=self.options['time_units'], shape=(nn,)) for output_name, options in self._ramps.items(): size = np.prod(options['shape'], dtype=int) cs = np.tile(np.arange(size, dtype=int), nn) - self.add_output(output_name, shape=(nn,) + - options['shape'], units=options['units']) + self.add_output(output_name, shape=(nn,) + options['shape'], units=options['units']) - self.add_input(options['initial_val_name'], val=options['initial_val'] - * np.ones(options['shape']), units=options['units']) - self.add_input(options['final_val_name'], val=options['final_val'] - * np.ones(options['shape']), units=options['units']) self.add_input( - options['t_init_name'], val=options['t_init_val'], units=self.options['time_units']) + options['initial_val_name'], + val=options['initial_val'] * np.ones(options['shape']), + units=options['units'], + ) self.add_input( - options['t_duration_name'], val=options['t_duration_val'], units=self.options['time_units']) + options['final_val_name'], + val=options['final_val'] * np.ones(options['shape']), + units=options['units'], + ) + self.add_input( + options['t_init_name'], val=options['t_init_val'], units=self.options['time_units'] + ) + self.add_input( + options['t_duration_name'], + val=options['t_duration_val'], + units=self.options['time_units'], + ) self.declare_partials( - of=output_name, wrt=f"{output_name}:initial_val", rows=ar, cols=cs) - self.declare_partials( - of=output_name, wrt=f"{output_name}:final_val", rows=ar, cols=cs) + of=output_name, wrt=f'{output_name}:initial_val', rows=ar, cols=cs + ) + self.declare_partials(of=output_name, wrt=f'{output_name}:final_val', rows=ar, cols=cs) self.declare_partials( - of=output_name, wrt=f"{output_name}:t_init", rows=ar, cols=np.zeros(nn, dtype=int)) - self.declare_partials(of=output_name, wrt=f"{output_name}:t_duration", - rows=ar, cols=np.zeros(nn, dtype=int)) - self.declare_partials(of=output_name, wrt="time", rows=ar, cols=ar) + of=output_name, wrt=f'{output_name}:t_init', rows=ar, cols=np.zeros(nn, dtype=int) + ) + self.declare_partials( + of=output_name, + wrt=f'{output_name}:t_duration', + rows=ar, + cols=np.zeros(nn, dtype=int), + ) + self.declare_partials(of=output_name, wrt='time', rows=ar, cols=ar) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - t = inputs["time"] + t = inputs['time'] for name, options in self._ramps.items(): - initial_val = inputs[options["initial_val_name"]] - final_val = inputs[options["final_val_name"]] - t_init = inputs[options["t_init_name"]] - t_duration = inputs[options["t_duration_name"]] + initial_val = inputs[options['initial_val_name']] + final_val = inputs[options['final_val_name']] + t_init = inputs[options['t_init_name']] + t_duration = inputs[options['t_duration_name']] dval = final_val - initial_val tanh_term = np.tanh(2 * np.pi * (t - t_init) / t_duration - np.pi) - outputs[name] = 0.5 * dval * (1+tanh_term) + initial_val + outputs[name] = 0.5 * dval * (1 + tanh_term) + initial_val def compute_partials(self, inputs, partials, discrete_inputs=None): - t = inputs["time"] + t = inputs['time'] for name, options in self._ramps.items(): - initial_val = inputs[options["initial_val_name"]] - final_val = inputs[options["final_val_name"]] - t_init = inputs[options["t_init_name"]] - t_duration = inputs[options["t_duration_name"]] + initial_val = inputs[options['initial_val_name']] + final_val = inputs[options['final_val_name']] + t_init = inputs[options['t_init_name']] + t_duration = inputs[options['t_duration_name']] dval = final_val - initial_val dvald2 = 0.5 * dval tanh_term = np.tanh(2 * np.pi * (t - t_init) / t_duration - np.pi) - omtanh2 = 1 - tanh_term ** 2 + omtanh2 = 1 - tanh_term**2 dtanh_term_dt = omtanh2 * 2 * np.pi / t_duration dtanh_term_dtinit = -dtanh_term_dt - dtanh_term_dtduration = omtanh2 * \ - (-2 * np.pi * (t - t_init) / t_duration ** 2) + dtanh_term_dtduration = omtanh2 * (-2 * np.pi * (t - t_init) / t_duration**2) - partials[name, "time"] = dvald2 * dtanh_term_dt - partials[name, options["t_init_name"]] = dvald2 * dtanh_term_dtinit - partials[name, options["t_duration_name"]] = dvald2 * dtanh_term_dtduration - partials[name, options["initial_val_name"]] = -0.5 * (1+tanh_term) + 1.0 - partials[name, options["final_val_name"]] = 0.5 * (1+tanh_term) + partials[name, 'time'] = dvald2 * dtanh_term_dt + partials[name, options['t_init_name']] = dvald2 * dtanh_term_dtinit + partials[name, options['t_duration_name']] = dvald2 * dtanh_term_dtduration + partials[name, options['initial_val_name']] = -0.5 * (1 + tanh_term) + 1.0 + partials[name, options['final_val_name']] = 0.5 * (1 + tanh_term) diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_flaps.txt b/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_flaps.txt deleted file mode 100644 index afd8119844..0000000000 --- a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_flaps.txt +++ /dev/null @@ -1,149 +0,0 @@ -# GASP-derived aerodynamics data converted from GASP_aero_flaps.txt -# Incremental Lift and Drag Coeff. for Flaps -# Reference Area = 1370. sqft - -Flap Deflection (deg), Mach, Angle of Attack (deg), Delta CL, Delta CD - 10.0, 0.0, -2.0, 0.44098, 0.01046 - 10.0, 0.0, 0.0, 0.44098, 0.01436 - 10.0, 0.0, 2.0, 0.44098, 0.01829 - 10.0, 0.0, 4.0, 0.44098, 0.02224 - 10.0, 0.0, 6.0, 0.44098, 0.02622 - 10.0, 0.0, 8.0, 0.44098, 0.03021 - 10.0, 0.0, 10.0, 0.44098, 0.03423 - 10.0, 0.0, 12.0, 0.44098, 0.03826 - 10.0, 0.0, 14.0, 0.44098, 0.04232 - 10.0, 0.0, 16.0, 0.44098, 0.0464 - 10.0, 0.0, 18.0, 0.44098, 0.05051 - 10.0, 0.0, 19.69, 0.41324, 0.05048 - 10.0, 0.1, -2.0, 0.44086, 0.01083 - 10.0, 0.1, 0.0, 0.44086, 0.01551 - 10.0, 0.1, 2.0, 0.44086, 0.02022 - 10.0, 0.1, 4.0, 0.44086, 0.02495 - 10.0, 0.1, 6.0, 0.44086, 0.02971 - 10.0, 0.1, 8.0, 0.44086, 0.03449 - 10.0, 0.1, 10.0, 0.44086, 0.03931 - 10.0, 0.1, 12.0, 0.44086, 0.04414 - 10.0, 0.1, 14.0, 0.44086, 0.04901 - 10.0, 0.1, 16.0, 0.44086, 0.0539 - 10.0, 0.1, 18.0, 0.44086, 0.05881 - 10.0, 0.1, 19.62, 0.40665, 0.05764 - 10.0, 0.2, -2.0, 0.44049, 0.01076 - 10.0, 0.2, 0.0, 0.44049, 0.01541 - 10.0, 0.2, 2.0, 0.44049, 0.02008 - 10.0, 0.2, 4.0, 0.44049, 0.02477 - 10.0, 0.2, 6.0, 0.44049, 0.02949 - 10.0, 0.2, 8.0, 0.44049, 0.03424 - 10.0, 0.2, 10.0, 0.44049, 0.03901 - 10.0, 0.2, 12.0, 0.44049, 0.04381 - 10.0, 0.2, 14.0, 0.44049, 0.04864 - 10.0, 0.2, 16.0, 0.44049, 0.05349 - 10.0, 0.2, 18.0, 0.44049, 0.05836 - 10.0, 0.2, 19.4, 0.38648, 0.05373 - 10.0, 0.3, -2.0, 0.43986, 0.0107 - 10.0, 0.3, 0.0, 0.43986, 0.01537 - 10.0, 0.3, 2.0, 0.43986, 0.02006 - 10.0, 0.3, 4.0, 0.43986, 0.02478 - 10.0, 0.3, 6.0, 0.43986, 0.02952 - 10.0, 0.3, 8.0, 0.43986, 0.03429 - 10.0, 0.3, 10.0, 0.43986, 0.03909 - 10.0, 0.3, 12.0, 0.43986, 0.04392 - 10.0, 0.3, 14.0, 0.43986, 0.04877 - 10.0, 0.3, 16.0, 0.43986, 0.05365 - 10.0, 0.3, 18.0, 0.43986, 0.05856 - 10.0, 0.3, 19.04, 0.3514, 0.04793 - 10.0, 0.4, -2.0, 0.4389, 0.01062 - 10.0, 0.4, 0.0, 0.4389, 0.01535 - 10.0, 0.4, 2.0, 0.4389, 0.02011 - 10.0, 0.4, 4.0, 0.4389, 0.0249 - 10.0, 0.4, 6.0, 0.4389, 0.02972 - 10.0, 0.4, 8.0, 0.4389, 0.03456 - 10.0, 0.4, 10.0, 0.4389, 0.03943 - 10.0, 0.4, 12.0, 0.4389, 0.04433 - 10.0, 0.4, 14.0, 0.4389, 0.04926 - 10.0, 0.4, 16.0, 0.4389, 0.05421 - 10.0, 0.4, 18.0, 0.4389, 0.05919 - 10.0, 0.4, 18.52, 0.31496, 0.04199 - 10.0, 0.5, -2.0, 0.43757, 0.01052 - 10.0, 0.5, 0.0, 0.43757, 0.01536 - 10.0, 0.5, 2.0, 0.43757, 0.02023 - 10.0, 0.5, 4.0, 0.43757, 0.02514 - 10.0, 0.5, 6.0, 0.43757, 0.03007 - 10.0, 0.5, 8.0, 0.43757, 0.03503 - 10.0, 0.5, 10.0, 0.43757, 0.04002 - 10.0, 0.5, 12.0, 0.43757, 0.04504 - 10.0, 0.5, 14.0, 0.43757, 0.05009 - 10.0, 0.5, 16.0, 0.43757, 0.05517 - 10.0, 0.5, 17.82, 0.41979, 0.05725 - 10.0, 0.5, 17.82, 0.314, 0.04154 - 40.0, 0.0, -2.0, 1.08538, 0.04726 - 40.0, 0.0, 0.0, 1.08538, 0.05416 - 40.0, 0.0, 2.0, 1.08538, 0.06142 - 40.0, 0.0, 4.0, 1.08538, 0.06905 - 40.0, 0.0, 6.0, 1.08538, 0.07704 - 40.0, 0.0, 8.0, 1.08538, 0.0854 - 40.0, 0.0, 10.0, 1.08538, 0.09412 - 40.0, 0.0, 12.0, 1.08538, 0.1032 - 40.0, 0.0, 14.0, 1.08538, 0.11265 - 40.0, 0.0, 16.0, 1.08538, 0.12246 - 40.0, 0.0, 18.0, 1.08538, 0.13264 - 40.0, 0.0, 19.88, 1.07429, 0.14111 - 40.0, 0.1, -2.0, 1.08508, 0.04854 - 40.0, 0.1, 0.0, 1.08508, 0.0568 - 40.0, 0.1, 2.0, 1.08508, 0.0655 - 40.0, 0.1, 4.0, 1.08508, 0.07464 - 40.0, 0.1, 6.0, 1.08508, 0.08422 - 40.0, 0.1, 8.0, 1.08508, 0.09423 - 40.0, 0.1, 10.0, 1.08508, 0.10469 - 40.0, 0.1, 12.0, 1.08508, 0.11558 - 40.0, 0.1, 14.0, 1.08508, 0.1269 - 40.0, 0.1, 16.0, 1.08508, 0.13867 - 40.0, 0.1, 18.0, 1.08508, 0.15088 - 40.0, 0.1, 19.8, 1.06752, 0.15959 - 40.0, 0.2, -2.0, 1.08417, 0.04834 - 40.0, 0.2, 0.0, 1.08417, 0.05653 - 40.0, 0.2, 2.0, 1.08417, 0.06516 - 40.0, 0.2, 4.0, 1.08417, 0.07422 - 40.0, 0.2, 6.0, 1.08417, 0.08373 - 40.0, 0.2, 8.0, 1.08417, 0.09368 - 40.0, 0.2, 10.0, 1.08417, 0.10406 - 40.0, 0.2, 12.0, 1.08417, 0.11488 - 40.0, 0.2, 14.0, 1.08417, 0.12614 - 40.0, 0.2, 16.0, 1.08417, 0.13785 - 40.0, 0.2, 18.0, 1.08417, 0.14999 - 40.0, 0.2, 19.59, 1.0468, 0.15432 - 40.0, 0.3, -2.0, 1.0826, 0.04815 - 40.0, 0.3, 0.0, 1.0826, 0.05637 - 40.0, 0.3, 2.0, 1.0826, 0.06504 - 40.0, 0.3, 4.0, 1.0826, 0.07416 - 40.0, 0.3, 6.0, 1.0826, 0.08373 - 40.0, 0.3, 8.0, 1.0826, 0.09375 - 40.0, 0.3, 10.0, 1.0826, 0.10422 - 40.0, 0.3, 12.0, 1.0826, 0.11513 - 40.0, 0.3, 14.0, 1.0826, 0.1265 - 40.0, 0.3, 16.0, 1.0826, 0.13831 - 40.0, 0.3, 18.0, 1.0826, 0.15058 - 40.0, 0.3, 19.22, 1.01077, 0.14752 - 40.0, 0.4, -2.0, 1.08026, 0.04794 - 40.0, 0.4, 0.0, 1.08026, 0.05626 - 40.0, 0.4, 2.0, 1.08026, 0.06505 - 40.0, 0.4, 4.0, 1.08026, 0.07431 - 40.0, 0.4, 6.0, 1.08026, 0.08404 - 40.0, 0.4, 8.0, 1.08026, 0.09424 - 40.0, 0.4, 10.0, 1.08026, 0.1049 - 40.0, 0.4, 12.0, 1.08026, 0.11603 - 40.0, 0.4, 14.0, 1.08026, 0.12763 - 40.0, 0.4, 16.0, 1.08026, 0.1397 - 40.0, 0.4, 18.0, 1.08026, 0.15224 - 40.0, 0.4, 18.69, 0.97289, 0.14059 - 40.0, 0.5, -2.0, 1.07697, 0.04767 - 40.0, 0.5, 0.0, 1.07697, 0.05616 - 40.0, 0.5, 2.0, 1.07697, 0.06516 - 40.0, 0.5, 4.0, 1.07697, 0.07465 - 40.0, 0.5, 6.0, 1.07697, 0.08464 - 40.0, 0.5, 8.0, 1.07697, 0.09512 - 40.0, 0.5, 10.0, 1.07697, 0.10611 - 40.0, 0.5, 12.0, 1.07697, 0.11758 - 40.0, 0.5, 14.0, 1.07697, 0.12956 - 40.0, 0.5, 16.0, 1.07697, 0.14204 - 40.0, 0.5, 17.96, 1.07572, 0.15474 - 40.0, 0.5, 17.99, 0.96993, 0.13903 diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt b/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt deleted file mode 100644 index abee57dd7c..0000000000 --- a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt +++ /dev/null @@ -1,1805 +0,0 @@ -# GASP-derived aerodynamics data converted from GASP_aero_free.txt -# Clean / Free Air Aerodynamics -# Reference Area = 1370. sqft - -Altitude (ft), Mach, Angle of Attack (deg), CL, CD - 0.0, 0.0, -2.0, -0.0715, 0.00363 - 0.0, 0.0, 0.0, 0.1072, 0.00384 - 0.0, 0.0, 2.0, 0.286, 0.00621 - 0.0, 0.0, 4.0, 0.4647, 0.01072 - 0.0, 0.0, 6.0, 0.6434, 0.01737 - 0.0, 0.0, 8.0, 0.8222, 0.02618 - 0.0, 0.0, 10.0, 1.0009, 0.03713 - 0.0, 0.0, 12.0, 1.1797, 0.05023 - 0.0, 0.0, 14.0, 1.3584, 0.06548 - 0.0, 0.0, 16.0, 1.5371, 0.08287 - 0.0, 0.0, 18.0, 1.7159, 0.10241 - 0.0, 0.0, 20.0, 1.8946, 0.1241 - 0.0, 0.2, -2.0, -0.0724, 0.01841 - 0.0, 0.2, 0.0, 0.1086, 0.01867 - 0.0, 0.2, 2.0, 0.2896, 0.02152 - 0.0, 0.2, 4.0, 0.4706, 0.02695 - 0.0, 0.2, 6.0, 0.6517, 0.03498 - 0.0, 0.2, 8.0, 0.8327, 0.04559 - 0.0, 0.2, 10.0, 1.0137, 0.05878 - 0.0, 0.2, 12.0, 1.1947, 0.07457 - 0.0, 0.2, 14.0, 1.3757, 0.09294 - 0.0, 0.2, 16.0, 1.5568, 0.1139 - 0.0, 0.2, 18.0, 1.7378, 0.13745 - 0.0, 0.2, 20.0, 1.9188, 0.16359 - 0.0, 0.4, -2.0, -0.0754, 0.01689 - 0.0, 0.4, 0.0, 0.1131, 0.01716 - 0.0, 0.4, 2.0, 0.3016, 0.0202 - 0.0, 0.4, 4.0, 0.4901, 0.026 - 0.0, 0.4, 6.0, 0.6786, 0.03455 - 0.0, 0.4, 8.0, 0.867, 0.04587 - 0.0, 0.4, 10.0, 1.0555, 0.05995 - 0.0, 0.4, 12.0, 1.244, 0.07678 - 0.0, 0.4, 14.0, 1.4325, 0.09638 - 0.0, 0.4, 16.0, 1.621, 0.11874 - 0.0, 0.4, 18.0, 1.8095, 0.14385 - 0.0, 0.4, 19.8, 1.982, 0.16926 - 0.0, 0.5, -2.0, -0.0779, 0.01639 - 0.0, 0.5, 0.0, 0.1169, 0.01668 - 0.0, 0.5, 2.0, 0.3117, 0.01991 - 0.0, 0.5, 4.0, 0.5065, 0.02607 - 0.0, 0.5, 6.0, 0.7013, 0.03515 - 0.0, 0.5, 8.0, 0.8961, 0.04717 - 0.0, 0.5, 10.0, 1.0909, 0.06212 - 0.0, 0.5, 12.0, 1.2857, 0.08 - 0.0, 0.5, 14.0, 1.4806, 0.10081 - 0.0, 0.5, 16.0, 1.6754, 0.12456 - 0.0, 0.5, 18.0, 1.8702, 0.15123 - 0.0, 0.5, 19.1, 1.976, 0.16695 - 0.0, 0.6, -2.0, -0.0814, 0.01598 - 0.0, 0.6, 0.0, 0.1221, 0.01629 - 0.0, 0.6, 2.0, 0.3257, 0.0198 - 0.0, 0.6, 4.0, 0.5293, 0.02648 - 0.0, 0.6, 6.0, 0.7329, 0.03636 - 0.0, 0.6, 8.0, 0.9365, 0.04941 - 0.0, 0.6, 10.0, 1.1401, 0.06566 - 0.0, 0.6, 12.0, 1.3436, 0.08508 - 0.0, 0.6, 14.0, 1.5472, 0.1077 - 0.0, 0.6, 16.0, 1.7508, 0.13349 - 0.0, 0.6, 18.0, 1.9544, 0.16254 - 0.0, 0.6, 18.1, 1.9677, 0.16456 - 0.0, 0.7, -2.0, -0.0863, 0.01561 - 0.0, 0.7, 0.0, 0.1295, 0.01597 - 0.0, 0.7, 2.0, 0.3454, 0.01989 - 0.0, 0.7, 4.0, 0.5613, 0.02737 - 0.0, 0.7, 6.0, 0.7771, 0.03842 - 0.0, 0.7, 8.0, 0.993, 0.05303 - 0.0, 0.7, 10.0, 1.2089, 0.07136 - 0.0, 0.7, 12.0, 1.4247, 0.09434 - 0.0, 0.7, 14.0, 1.6406, 0.12318 - 0.0, 0.7, 16.0, 1.8565, 0.1591 - 0.0, 0.7, 16.9, 1.9562, 0.17842 - 0.0, 0.7, 16.9, 1.9562, 0.17842 - 0.0, 0.75, -2.0, -0.0896, 0.01545 - 0.0, 0.75, 0.0, 0.1343, 0.01583 - 0.0, 0.75, 2.0, 0.3582, 0.02004 - 0.0, 0.75, 4.0, 0.5822, 0.02807 - 0.0, 0.75, 6.0, 0.8061, 0.04007 - 0.0, 0.75, 8.0, 1.03, 0.05703 - 0.0, 0.75, 10.0, 1.2539, 0.08031 - 0.0, 0.75, 12.0, 1.4778, 0.11124 - 0.0, 0.75, 14.0, 1.7017, 0.15118 - 0.0, 0.75, 16.0, 1.9256, 0.20146 - 0.0, 0.75, 16.2, 1.9488, 0.20733 - 0.0, 0.75, 16.2, 1.9488, 0.20733 - 0.0, 0.8, -2.0, -0.0935, 0.0153 - 0.0, 0.8, 0.0, 0.1402, 0.01571 - 0.0, 0.8, 2.0, 0.374, 0.02036 - 0.0, 0.8, 4.0, 0.6077, 0.0302 - 0.0, 0.8, 6.0, 0.8414, 0.04673 - 0.0, 0.8, 8.0, 1.0751, 0.0715 - 0.0, 0.8, 10.0, 1.3089, 0.10604 - 0.0, 0.8, 12.0, 1.5426, 0.15187 - 0.0, 0.8, 14.0, 1.7763, 0.21052 - 0.0, 0.8, 15.4, 1.9399, 0.26004 - 0.0, 0.8, 15.4, 1.9399, 0.26004 - 0.0, 0.8, 15.4, 1.9399, 0.26004 - 0.0, 0.85, -2.0, -0.0984, 0.01517 - 0.0, 0.85, 0.0, 0.1476, 0.01631 - 0.0, 0.85, 2.0, 0.3936, 0.02441 - 0.0, 0.85, 4.0, 0.6396, 0.04125 - 0.0, 0.85, 6.0, 0.8855, 0.06862 - 0.0, 0.85, 8.0, 1.1315, 0.1083 - 0.0, 0.85, 10.0, 1.3775, 0.16207 - 0.0, 0.85, 12.0, 1.6235, 0.23172 - 0.0, 0.85, 14.0, 1.8695, 0.31903 - 0.0, 0.85, 14.5, 1.929, 0.34301 - 0.0, 0.85, 14.5, 1.929, 0.34301 - 0.0, 0.85, 14.5, 1.929, 0.34301 - 0.0, 0.9, -2.0, -0.1047, 0.01712 - 0.0, 0.9, 0.0, 0.1571, 0.02339 - 0.0, 0.9, 2.0, 0.4188, 0.04088 - 0.0, 0.9, 4.0, 0.6806, 0.07174 - 0.0, 0.9, 6.0, 0.9424, 0.11809 - 0.0, 0.9, 8.0, 1.2041, 0.18211 - 0.0, 0.9, 10.0, 1.4659, 0.26594 - 0.0, 0.9, 12.0, 1.7277, 0.37173 - 0.0, 0.9, 13.4, 1.9152, 0.46224 - 0.0, 0.9, 13.4, 1.9152, 0.46224 - 0.0, 0.9, 13.4, 1.9152, 0.46224 - 0.0, 0.9, 13.4, 1.9152, 0.46224 - 3000.0, 0.0, -2.0, -0.0715, 0.00363 - 3000.0, 0.0, 0.0, 0.1072, 0.00384 - 3000.0, 0.0, 2.0, 0.286, 0.00621 - 3000.0, 0.0, 4.0, 0.4647, 0.01072 - 3000.0, 0.0, 6.0, 0.6434, 0.01737 - 3000.0, 0.0, 8.0, 0.8222, 0.02618 - 3000.0, 0.0, 10.0, 1.0009, 0.03713 - 3000.0, 0.0, 12.0, 1.1797, 0.05023 - 3000.0, 0.0, 14.0, 1.3584, 0.06548 - 3000.0, 0.0, 16.0, 1.5371, 0.08287 - 3000.0, 0.0, 18.0, 1.7159, 0.10241 - 3000.0, 0.0, 20.0, 1.8946, 0.1241 - 3000.0, 0.2, -2.0, -0.0724, 0.01859 - 3000.0, 0.2, 0.0, 0.1086, 0.01885 - 3000.0, 0.2, 2.0, 0.2896, 0.0217 - 3000.0, 0.2, 4.0, 0.4706, 0.02715 - 3000.0, 0.2, 6.0, 0.6517, 0.03519 - 3000.0, 0.2, 8.0, 0.8327, 0.04582 - 3000.0, 0.2, 10.0, 1.0137, 0.05904 - 3000.0, 0.2, 12.0, 1.1947, 0.07485 - 3000.0, 0.2, 14.0, 1.3757, 0.09326 - 3000.0, 0.2, 16.0, 1.5568, 0.11426 - 3000.0, 0.2, 18.0, 1.7378, 0.13785 - 3000.0, 0.2, 20.0, 1.9188, 0.16404 - 3000.0, 0.4, -2.0, -0.0754, 0.01704 - 3000.0, 0.4, 0.0, 0.1131, 0.01732 - 3000.0, 0.4, 2.0, 0.3016, 0.02036 - 3000.0, 0.4, 4.0, 0.4901, 0.02617 - 3000.0, 0.4, 6.0, 0.6786, 0.03474 - 3000.0, 0.4, 8.0, 0.867, 0.04607 - 3000.0, 0.4, 10.0, 1.0555, 0.06017 - 3000.0, 0.4, 12.0, 1.244, 0.07703 - 3000.0, 0.4, 14.0, 1.4325, 0.09666 - 3000.0, 0.4, 16.0, 1.621, 0.11905 - 3000.0, 0.4, 18.0, 1.8095, 0.14421 - 3000.0, 0.4, 19.8, 1.982, 0.16966 - 3000.0, 0.5, -2.0, -0.0779, 0.01654 - 3000.0, 0.5, 0.0, 0.1169, 0.01683 - 3000.0, 0.5, 2.0, 0.3117, 0.02006 - 3000.0, 0.5, 4.0, 0.5065, 0.02623 - 3000.0, 0.5, 6.0, 0.7013, 0.03533 - 3000.0, 0.5, 8.0, 0.8961, 0.04737 - 3000.0, 0.5, 10.0, 1.0909, 0.06234 - 3000.0, 0.5, 12.0, 1.2857, 0.08025 - 3000.0, 0.5, 14.0, 1.4806, 0.10109 - 3000.0, 0.5, 16.0, 1.6754, 0.12487 - 3000.0, 0.5, 18.0, 1.8702, 0.15159 - 3000.0, 0.5, 19.1, 1.976, 0.16733 - 3000.0, 0.6, -2.0, -0.0814, 0.01612 - 3000.0, 0.6, 0.0, 0.1221, 0.01644 - 3000.0, 0.6, 2.0, 0.3257, 0.01994 - 3000.0, 0.6, 4.0, 0.5293, 0.02664 - 3000.0, 0.6, 6.0, 0.7329, 0.03653 - 3000.0, 0.6, 8.0, 0.9365, 0.04961 - 3000.0, 0.6, 10.0, 1.1401, 0.06587 - 3000.0, 0.6, 12.0, 1.3436, 0.08533 - 3000.0, 0.6, 14.0, 1.5472, 0.10797 - 3000.0, 0.6, 16.0, 1.7508, 0.13381 - 3000.0, 0.6, 18.0, 1.9544, 0.16289 - 3000.0, 0.6, 18.1, 1.9677, 0.16492 - 3000.0, 0.7, -2.0, -0.0863, 0.01575 - 3000.0, 0.7, 0.0, 0.1295, 0.01611 - 3000.0, 0.7, 2.0, 0.3454, 0.02003 - 3000.0, 0.7, 4.0, 0.5613, 0.02753 - 3000.0, 0.7, 6.0, 0.7771, 0.03859 - 3000.0, 0.7, 8.0, 0.993, 0.05322 - 3000.0, 0.7, 10.0, 1.2089, 0.07157 - 3000.0, 0.7, 12.0, 1.4247, 0.09458 - 3000.0, 0.7, 14.0, 1.6406, 0.12346 - 3000.0, 0.7, 16.0, 1.8565, 0.15942 - 3000.0, 0.7, 16.9, 1.9562, 0.17876 - 3000.0, 0.7, 16.9, 1.9562, 0.17876 - 3000.0, 0.75, -2.0, -0.0896, 0.01558 - 3000.0, 0.75, 0.0, 0.1343, 0.01597 - 3000.0, 0.75, 2.0, 0.3582, 0.02018 - 3000.0, 0.75, 4.0, 0.5822, 0.02822 - 3000.0, 0.75, 6.0, 0.8061, 0.04024 - 3000.0, 0.75, 8.0, 1.03, 0.05722 - 3000.0, 0.75, 10.0, 1.2539, 0.08052 - 3000.0, 0.75, 12.0, 1.4778, 0.11149 - 3000.0, 0.75, 14.0, 1.7017, 0.15146 - 3000.0, 0.75, 16.0, 1.9256, 0.20179 - 3000.0, 0.75, 16.2, 1.9488, 0.20767 - 3000.0, 0.75, 16.2, 1.9488, 0.20767 - 3000.0, 0.8, -2.0, -0.0935, 0.01543 - 3000.0, 0.8, 0.0, 0.1402, 0.01584 - 3000.0, 0.8, 2.0, 0.374, 0.0205 - 3000.0, 0.8, 4.0, 0.6077, 0.03034 - 3000.0, 0.8, 6.0, 0.8414, 0.0469 - 3000.0, 0.8, 8.0, 1.0751, 0.07169 - 3000.0, 0.8, 10.0, 1.3089, 0.10626 - 3000.0, 0.8, 12.0, 1.5426, 0.15212 - 3000.0, 0.8, 14.0, 1.7763, 0.21082 - 3000.0, 0.8, 15.4, 1.9399, 0.26036 - 3000.0, 0.8, 15.4, 1.9399, 0.26036 - 3000.0, 0.8, 15.4, 1.9399, 0.26036 - 3000.0, 0.85, -2.0, -0.0984, 0.0153 - 3000.0, 0.85, 0.0, 0.1476, 0.01644 - 3000.0, 0.85, 2.0, 0.3936, 0.02454 - 3000.0, 0.85, 4.0, 0.6396, 0.0414 - 3000.0, 0.85, 6.0, 0.8855, 0.06878 - 3000.0, 0.85, 8.0, 1.1315, 0.10849 - 3000.0, 0.85, 10.0, 1.3775, 0.16229 - 3000.0, 0.85, 12.0, 1.6235, 0.23198 - 3000.0, 0.85, 14.0, 1.8695, 0.31934 - 3000.0, 0.85, 14.5, 1.929, 0.34333 - 3000.0, 0.85, 14.5, 1.929, 0.34333 - 3000.0, 0.85, 14.5, 1.929, 0.34333 - 3000.0, 0.9, -2.0, -0.1047, 0.01724 - 3000.0, 0.9, 0.0, 0.1571, 0.02352 - 3000.0, 0.9, 2.0, 0.4188, 0.04102 - 3000.0, 0.9, 4.0, 0.6806, 0.07188 - 3000.0, 0.9, 6.0, 0.9424, 0.11826 - 3000.0, 0.9, 8.0, 1.2041, 0.18231 - 3000.0, 0.9, 10.0, 1.4659, 0.26617 - 3000.0, 0.9, 12.0, 1.7277, 0.372 - 3000.0, 0.9, 13.4, 1.9152, 0.46255 - 3000.0, 0.9, 13.4, 1.9152, 0.46255 - 3000.0, 0.9, 13.4, 1.9152, 0.46255 - 3000.0, 0.9, 13.4, 1.9152, 0.46255 - 6000.0, 0.0, -2.0, -0.0715, 0.00363 - 6000.0, 0.0, 0.0, 0.1072, 0.00384 - 6000.0, 0.0, 2.0, 0.286, 0.00621 - 6000.0, 0.0, 4.0, 0.4647, 0.01072 - 6000.0, 0.0, 6.0, 0.6434, 0.01737 - 6000.0, 0.0, 8.0, 0.8222, 0.02618 - 6000.0, 0.0, 10.0, 1.0009, 0.03713 - 6000.0, 0.0, 12.0, 1.1797, 0.05023 - 6000.0, 0.0, 14.0, 1.3584, 0.06548 - 6000.0, 0.0, 16.0, 1.5371, 0.08287 - 6000.0, 0.0, 18.0, 1.7159, 0.10241 - 6000.0, 0.0, 20.0, 1.8946, 0.1241 - 6000.0, 0.2, -2.0, -0.0724, 0.01878 - 6000.0, 0.2, 0.0, 0.1086, 0.01904 - 6000.0, 0.2, 2.0, 0.2896, 0.0219 - 6000.0, 0.2, 4.0, 0.4706, 0.02735 - 6000.0, 0.2, 6.0, 0.6517, 0.0354 - 6000.0, 0.2, 8.0, 0.8327, 0.04605 - 6000.0, 0.2, 10.0, 1.0137, 0.0593 - 6000.0, 0.2, 12.0, 1.1947, 0.07515 - 6000.0, 0.2, 14.0, 1.3757, 0.09359 - 6000.0, 0.2, 16.0, 1.5568, 0.11463 - 6000.0, 0.2, 18.0, 1.7378, 0.13827 - 6000.0, 0.2, 20.0, 1.9188, 0.1645 - 6000.0, 0.4, -2.0, -0.0754, 0.0172 - 6000.0, 0.4, 0.0, 0.1131, 0.01748 - 6000.0, 0.4, 2.0, 0.3016, 0.02053 - 6000.0, 0.4, 4.0, 0.4901, 0.02634 - 6000.0, 0.4, 6.0, 0.6786, 0.03493 - 6000.0, 0.4, 8.0, 0.867, 0.04628 - 6000.0, 0.4, 10.0, 1.0555, 0.0604 - 6000.0, 0.4, 12.0, 1.244, 0.07729 - 6000.0, 0.4, 14.0, 1.4325, 0.09695 - 6000.0, 0.4, 16.0, 1.621, 0.11938 - 6000.0, 0.4, 18.0, 1.8095, 0.14458 - 6000.0, 0.4, 19.8, 1.982, 0.17007 - 6000.0, 0.5, -2.0, -0.0779, 0.01669 - 6000.0, 0.5, 0.0, 0.1169, 0.01699 - 6000.0, 0.5, 2.0, 0.3117, 0.02022 - 6000.0, 0.5, 4.0, 0.5065, 0.0264 - 6000.0, 0.5, 6.0, 0.7013, 0.03551 - 6000.0, 0.5, 8.0, 0.8961, 0.04757 - 6000.0, 0.5, 10.0, 1.0909, 0.06256 - 6000.0, 0.5, 12.0, 1.2857, 0.0805 - 6000.0, 0.5, 14.0, 1.4806, 0.10138 - 6000.0, 0.5, 16.0, 1.6754, 0.1252 - 6000.0, 0.5, 18.0, 1.8702, 0.15195 - 6000.0, 0.5, 19.1, 1.976, 0.16772 - 6000.0, 0.6, -2.0, -0.0814, 0.01626 - 6000.0, 0.6, 0.0, 0.1221, 0.01658 - 6000.0, 0.6, 2.0, 0.3257, 0.0201 - 6000.0, 0.6, 4.0, 0.5293, 0.0268 - 6000.0, 0.6, 6.0, 0.7329, 0.03671 - 6000.0, 0.6, 8.0, 0.9365, 0.0498 - 6000.0, 0.6, 10.0, 1.1401, 0.06609 - 6000.0, 0.6, 12.0, 1.3436, 0.08558 - 6000.0, 0.6, 14.0, 1.5472, 0.10826 - 6000.0, 0.6, 16.0, 1.7508, 0.13413 - 6000.0, 0.6, 18.0, 1.9544, 0.16326 - 6000.0, 0.6, 18.1, 1.9677, 0.16529 - 6000.0, 0.7, -2.0, -0.0863, 0.01589 - 6000.0, 0.7, 0.0, 0.1295, 0.01625 - 6000.0, 0.7, 2.0, 0.3454, 0.02018 - 6000.0, 0.7, 4.0, 0.5613, 0.02768 - 6000.0, 0.7, 6.0, 0.7771, 0.03876 - 6000.0, 0.7, 8.0, 0.993, 0.05342 - 6000.0, 0.7, 10.0, 1.2089, 0.07179 - 6000.0, 0.7, 12.0, 1.4247, 0.09484 - 6000.0, 0.7, 14.0, 1.6406, 0.12376 - 6000.0, 0.7, 16.0, 1.8565, 0.15975 - 6000.0, 0.7, 16.9, 1.9562, 0.17911 - 6000.0, 0.7, 16.9, 1.9562, 0.17911 - 6000.0, 0.75, -2.0, -0.0896, 0.01572 - 6000.0, 0.75, 0.0, 0.1343, 0.0161 - 6000.0, 0.75, 2.0, 0.3582, 0.02032 - 6000.0, 0.75, 4.0, 0.5822, 0.02838 - 6000.0, 0.75, 6.0, 0.8061, 0.04041 - 6000.0, 0.75, 8.0, 1.03, 0.05742 - 6000.0, 0.75, 10.0, 1.2539, 0.08075 - 6000.0, 0.75, 12.0, 1.4778, 0.11175 - 6000.0, 0.75, 14.0, 1.7017, 0.15176 - 6000.0, 0.75, 16.0, 1.9256, 0.20213 - 6000.0, 0.75, 16.2, 1.9488, 0.20801 - 6000.0, 0.75, 16.2, 1.9488, 0.20801 - 6000.0, 0.8, -2.0, -0.0935, 0.01556 - 6000.0, 0.8, 0.0, 0.1402, 0.01598 - 6000.0, 0.8, 2.0, 0.374, 0.02064 - 6000.0, 0.8, 4.0, 0.6077, 0.0305 - 6000.0, 0.8, 6.0, 0.8414, 0.04707 - 6000.0, 0.8, 8.0, 1.0751, 0.07189 - 6000.0, 0.8, 10.0, 1.3089, 0.10649 - 6000.0, 0.8, 12.0, 1.5426, 0.15239 - 6000.0, 0.8, 14.0, 1.7763, 0.21112 - 6000.0, 0.8, 15.4, 1.9399, 0.2607 - 6000.0, 0.8, 15.4, 1.9399, 0.2607 - 6000.0, 0.8, 15.4, 1.9399, 0.2607 - 6000.0, 0.85, -2.0, -0.0984, 0.01543 - 6000.0, 0.85, 0.0, 0.1476, 0.01657 - 6000.0, 0.85, 2.0, 0.3936, 0.02468 - 6000.0, 0.85, 4.0, 0.6396, 0.04155 - 6000.0, 0.85, 6.0, 0.8855, 0.06896 - 6000.0, 0.85, 8.0, 1.1315, 0.10869 - 6000.0, 0.85, 10.0, 1.3775, 0.16253 - 6000.0, 0.85, 12.0, 1.6235, 0.23225 - 6000.0, 0.85, 14.0, 1.8695, 0.31966 - 6000.0, 0.85, 14.5, 1.929, 0.34366 - 6000.0, 0.85, 14.5, 1.929, 0.34366 - 6000.0, 0.85, 14.5, 1.929, 0.34366 - 6000.0, 0.9, -2.0, -0.1047, 0.01737 - 6000.0, 0.9, 0.0, 0.1571, 0.02365 - 6000.0, 0.9, 2.0, 0.4188, 0.04116 - 6000.0, 0.9, 4.0, 0.6806, 0.07204 - 6000.0, 0.9, 6.0, 0.9424, 0.11844 - 6000.0, 0.9, 8.0, 1.2041, 0.18252 - 6000.0, 0.9, 10.0, 1.4659, 0.26642 - 6000.0, 0.9, 12.0, 1.7277, 0.37229 - 6000.0, 0.9, 13.4, 1.9152, 0.46287 - 6000.0, 0.9, 13.4, 1.9152, 0.46287 - 6000.0, 0.9, 13.4, 1.9152, 0.46287 - 6000.0, 0.9, 13.4, 1.9152, 0.46287 - 9000.0, 0.0, -2.0, -0.0715, 0.00363 - 9000.0, 0.0, 0.0, 0.1072, 0.00384 - 9000.0, 0.0, 2.0, 0.286, 0.00621 - 9000.0, 0.0, 4.0, 0.4647, 0.01072 - 9000.0, 0.0, 6.0, 0.6434, 0.01737 - 9000.0, 0.0, 8.0, 0.8222, 0.02618 - 9000.0, 0.0, 10.0, 1.0009, 0.03713 - 9000.0, 0.0, 12.0, 1.1797, 0.05023 - 9000.0, 0.0, 14.0, 1.3584, 0.06548 - 9000.0, 0.0, 16.0, 1.5371, 0.08287 - 9000.0, 0.0, 18.0, 1.7159, 0.10241 - 9000.0, 0.0, 20.0, 1.8946, 0.1241 - 9000.0, 0.2, -2.0, -0.0724, 0.01898 - 9000.0, 0.2, 0.0, 0.1086, 0.01924 - 9000.0, 0.2, 2.0, 0.2896, 0.0221 - 9000.0, 0.2, 4.0, 0.4706, 0.02756 - 9000.0, 0.2, 6.0, 0.6517, 0.03563 - 9000.0, 0.2, 8.0, 0.8327, 0.0463 - 9000.0, 0.2, 10.0, 1.0137, 0.05958 - 9000.0, 0.2, 12.0, 1.1947, 0.07545 - 9000.0, 0.2, 14.0, 1.3757, 0.09393 - 9000.0, 0.2, 16.0, 1.5568, 0.11501 - 9000.0, 0.2, 18.0, 1.7378, 0.13869 - 9000.0, 0.2, 20.0, 1.9188, 0.16498 - 9000.0, 0.4, -2.0, -0.0754, 0.01737 - 9000.0, 0.4, 0.0, 0.1131, 0.01765 - 9000.0, 0.4, 2.0, 0.3016, 0.0207 - 9000.0, 0.4, 4.0, 0.4901, 0.02653 - 9000.0, 0.4, 6.0, 0.6786, 0.03512 - 9000.0, 0.4, 8.0, 0.867, 0.0465 - 9000.0, 0.4, 10.0, 1.0555, 0.06064 - 9000.0, 0.4, 12.0, 1.244, 0.07756 - 9000.0, 0.4, 14.0, 1.4325, 0.09726 - 9000.0, 0.4, 16.0, 1.621, 0.11973 - 9000.0, 0.4, 18.0, 1.8095, 0.14497 - 9000.0, 0.4, 19.8, 1.982, 0.1705 - 9000.0, 0.5, -2.0, -0.0779, 0.01685 - 9000.0, 0.5, 0.0, 0.1169, 0.01715 - 9000.0, 0.5, 2.0, 0.3117, 0.02039 - 9000.0, 0.5, 4.0, 0.5065, 0.02657 - 9000.0, 0.5, 6.0, 0.7013, 0.0357 - 9000.0, 0.5, 8.0, 0.8961, 0.04778 - 9000.0, 0.5, 10.0, 1.0909, 0.0628 - 9000.0, 0.5, 12.0, 1.2857, 0.08076 - 9000.0, 0.5, 14.0, 1.4806, 0.10168 - 9000.0, 0.5, 16.0, 1.6754, 0.12553 - 9000.0, 0.5, 18.0, 1.8702, 0.15233 - 9000.0, 0.5, 19.1, 1.976, 0.16812 - 9000.0, 0.6, -2.0, -0.0814, 0.01641 - 9000.0, 0.6, 0.0, 0.1221, 0.01673 - 9000.0, 0.6, 2.0, 0.3257, 0.02025 - 9000.0, 0.6, 4.0, 0.5293, 0.02697 - 9000.0, 0.6, 6.0, 0.7329, 0.03689 - 9000.0, 0.6, 8.0, 0.9365, 0.05001 - 9000.0, 0.6, 10.0, 1.1401, 0.06632 - 9000.0, 0.6, 12.0, 1.3436, 0.08584 - 9000.0, 0.6, 14.0, 1.5472, 0.10855 - 9000.0, 0.6, 16.0, 1.7508, 0.13447 - 9000.0, 0.6, 18.0, 1.9544, 0.16365 - 9000.0, 0.6, 18.1, 1.9677, 0.16568 - 9000.0, 0.7, -2.0, -0.0863, 0.01603 - 9000.0, 0.7, 0.0, 0.1295, 0.01639 - 9000.0, 0.7, 2.0, 0.3454, 0.02033 - 9000.0, 0.7, 4.0, 0.5613, 0.02785 - 9000.0, 0.7, 6.0, 0.7771, 0.03894 - 9000.0, 0.7, 8.0, 0.993, 0.05362 - 9000.0, 0.7, 10.0, 1.2089, 0.07202 - 9000.0, 0.7, 12.0, 1.4247, 0.0951 - 9000.0, 0.7, 14.0, 1.6406, 0.12406 - 9000.0, 0.7, 16.0, 1.8565, 0.1601 - 9000.0, 0.7, 16.9, 1.9562, 0.17948 - 9000.0, 0.7, 16.9, 1.9562, 0.17948 - 9000.0, 0.75, -2.0, -0.0896, 0.01586 - 9000.0, 0.75, 0.0, 0.1343, 0.01625 - 9000.0, 0.75, 2.0, 0.3582, 0.02047 - 9000.0, 0.75, 4.0, 0.5822, 0.02854 - 9000.0, 0.75, 6.0, 0.8061, 0.04059 - 9000.0, 0.75, 8.0, 1.03, 0.05762 - 9000.0, 0.75, 10.0, 1.2539, 0.08098 - 9000.0, 0.75, 12.0, 1.4778, 0.11201 - 9000.0, 0.75, 14.0, 1.7017, 0.15207 - 9000.0, 0.75, 16.0, 1.9256, 0.20249 - 9000.0, 0.75, 16.2, 1.9488, 0.20837 - 9000.0, 0.75, 16.2, 1.9488, 0.20837 - 9000.0, 0.8, -2.0, -0.0935, 0.0157 - 9000.0, 0.8, 0.0, 0.1402, 0.01612 - 9000.0, 0.8, 2.0, 0.374, 0.02079 - 9000.0, 0.8, 4.0, 0.6077, 0.03066 - 9000.0, 0.8, 6.0, 0.8414, 0.04725 - 9000.0, 0.8, 8.0, 1.0751, 0.0721 - 9000.0, 0.8, 10.0, 1.3089, 0.10672 - 9000.0, 0.8, 12.0, 1.5426, 0.15266 - 9000.0, 0.8, 14.0, 1.7763, 0.21144 - 9000.0, 0.8, 15.4, 1.9399, 0.26105 - 9000.0, 0.8, 15.4, 1.9399, 0.26105 - 9000.0, 0.8, 15.4, 1.9399, 0.26105 - 9000.0, 0.85, -2.0, -0.0984, 0.01557 - 9000.0, 0.85, 0.0, 0.1476, 0.01671 - 9000.0, 0.85, 2.0, 0.3936, 0.02483 - 9000.0, 0.85, 4.0, 0.6396, 0.04171 - 9000.0, 0.85, 6.0, 0.8855, 0.06914 - 9000.0, 0.85, 8.0, 1.1315, 0.1089 - 9000.0, 0.85, 10.0, 1.3775, 0.16277 - 9000.0, 0.85, 12.0, 1.6235, 0.23254 - 9000.0, 0.85, 14.0, 1.8695, 0.31999 - 9000.0, 0.85, 14.5, 1.929, 0.344 - 9000.0, 0.85, 14.5, 1.929, 0.344 - 9000.0, 0.85, 14.5, 1.929, 0.344 - 9000.0, 0.9, -2.0, -0.1047, 0.01751 - 9000.0, 0.9, 0.0, 0.1571, 0.02379 - 9000.0, 0.9, 2.0, 0.4188, 0.0413 - 9000.0, 0.9, 4.0, 0.6806, 0.0722 - 9000.0, 0.9, 6.0, 0.9424, 0.11862 - 9000.0, 0.9, 8.0, 1.2041, 0.18273 - 9000.0, 0.9, 10.0, 1.4659, 0.26667 - 9000.0, 0.9, 12.0, 1.7277, 0.37258 - 9000.0, 0.9, 13.4, 1.9152, 0.4632 - 9000.0, 0.9, 13.4, 1.9152, 0.4632 - 9000.0, 0.9, 13.4, 1.9152, 0.4632 - 9000.0, 0.9, 13.4, 1.9152, 0.4632 - 12000.0, 0.0, -2.0, -0.0715, 0.00363 - 12000.0, 0.0, 0.0, 0.1072, 0.00384 - 12000.0, 0.0, 2.0, 0.286, 0.00621 - 12000.0, 0.0, 4.0, 0.4647, 0.01072 - 12000.0, 0.0, 6.0, 0.6434, 0.01737 - 12000.0, 0.0, 8.0, 0.8222, 0.02618 - 12000.0, 0.0, 10.0, 1.0009, 0.03713 - 12000.0, 0.0, 12.0, 1.1797, 0.05023 - 12000.0, 0.0, 14.0, 1.3584, 0.06548 - 12000.0, 0.0, 16.0, 1.5371, 0.08287 - 12000.0, 0.0, 18.0, 1.7159, 0.10241 - 12000.0, 0.0, 20.0, 1.8946, 0.1241 - 12000.0, 0.2, -2.0, -0.0724, 0.01918 - 12000.0, 0.2, 0.0, 0.1086, 0.01944 - 12000.0, 0.2, 2.0, 0.2896, 0.02231 - 12000.0, 0.2, 4.0, 0.4706, 0.02778 - 12000.0, 0.2, 6.0, 0.6517, 0.03587 - 12000.0, 0.2, 8.0, 0.8327, 0.04656 - 12000.0, 0.2, 10.0, 1.0137, 0.05986 - 12000.0, 0.2, 12.0, 1.1947, 0.07577 - 12000.0, 0.2, 14.0, 1.3757, 0.09428 - 12000.0, 0.2, 16.0, 1.5568, 0.11541 - 12000.0, 0.2, 18.0, 1.7378, 0.13914 - 12000.0, 0.2, 20.0, 1.9188, 0.16548 - 12000.0, 0.4, -2.0, -0.0754, 0.01755 - 12000.0, 0.4, 0.0, 0.1131, 0.01782 - 12000.0, 0.4, 2.0, 0.3016, 0.02088 - 12000.0, 0.4, 4.0, 0.4901, 0.02672 - 12000.0, 0.4, 6.0, 0.6786, 0.03533 - 12000.0, 0.4, 8.0, 0.867, 0.04672 - 12000.0, 0.4, 10.0, 1.0555, 0.06089 - 12000.0, 0.4, 12.0, 1.244, 0.07784 - 12000.0, 0.4, 14.0, 1.4325, 0.09757 - 12000.0, 0.4, 16.0, 1.621, 0.12008 - 12000.0, 0.4, 18.0, 1.8095, 0.14537 - 12000.0, 0.4, 19.8, 1.982, 0.17095 - 12000.0, 0.5, -2.0, -0.0779, 0.01702 - 12000.0, 0.5, 0.0, 0.1169, 0.01731 - 12000.0, 0.5, 2.0, 0.3117, 0.02056 - 12000.0, 0.5, 4.0, 0.5065, 0.02675 - 12000.0, 0.5, 6.0, 0.7013, 0.0359 - 12000.0, 0.5, 8.0, 0.8961, 0.04799 - 12000.0, 0.5, 10.0, 1.0909, 0.06304 - 12000.0, 0.5, 12.0, 1.2857, 0.08104 - 12000.0, 0.5, 14.0, 1.4806, 0.10198 - 12000.0, 0.5, 16.0, 1.6754, 0.12588 - 12000.0, 0.5, 18.0, 1.8702, 0.15273 - 12000.0, 0.5, 19.1, 1.976, 0.16854 - 12000.0, 0.6, -2.0, -0.0814, 0.01657 - 12000.0, 0.6, 0.0, 0.1221, 0.01689 - 12000.0, 0.6, 2.0, 0.3257, 0.02042 - 12000.0, 0.6, 4.0, 0.5293, 0.02715 - 12000.0, 0.6, 6.0, 0.7329, 0.03708 - 12000.0, 0.6, 8.0, 0.9365, 0.05022 - 12000.0, 0.6, 10.0, 1.1401, 0.06656 - 12000.0, 0.6, 12.0, 1.3436, 0.08611 - 12000.0, 0.6, 14.0, 1.5472, 0.10886 - 12000.0, 0.6, 16.0, 1.7508, 0.13482 - 12000.0, 0.6, 18.0, 1.9544, 0.16404 - 12000.0, 0.6, 18.1, 1.9677, 0.16608 - 12000.0, 0.7, -2.0, -0.0863, 0.01619 - 12000.0, 0.7, 0.0, 0.1295, 0.01654 - 12000.0, 0.7, 2.0, 0.3454, 0.02049 - 12000.0, 0.7, 4.0, 0.5613, 0.02802 - 12000.0, 0.7, 6.0, 0.7771, 0.03913 - 12000.0, 0.7, 8.0, 0.993, 0.05383 - 12000.0, 0.7, 10.0, 1.2089, 0.07226 - 12000.0, 0.7, 12.0, 1.4247, 0.09537 - 12000.0, 0.7, 14.0, 1.6406, 0.12437 - 12000.0, 0.7, 16.0, 1.8565, 0.16046 - 12000.0, 0.7, 16.9, 1.9562, 0.17986 - 12000.0, 0.7, 16.9, 1.9562, 0.17986 - 12000.0, 0.75, -2.0, -0.0896, 0.01601 - 12000.0, 0.75, 0.0, 0.1343, 0.0164 - 12000.0, 0.75, 2.0, 0.3582, 0.02063 - 12000.0, 0.75, 4.0, 0.5822, 0.02871 - 12000.0, 0.75, 6.0, 0.8061, 0.04077 - 12000.0, 0.75, 8.0, 1.03, 0.05783 - 12000.0, 0.75, 10.0, 1.2539, 0.08122 - 12000.0, 0.75, 12.0, 1.4778, 0.11229 - 12000.0, 0.75, 14.0, 1.7017, 0.15239 - 12000.0, 0.75, 16.0, 1.9256, 0.20285 - 12000.0, 0.75, 16.2, 1.9488, 0.20874 - 12000.0, 0.75, 16.2, 1.9488, 0.20874 - 12000.0, 0.8, -2.0, -0.0935, 0.01585 - 12000.0, 0.8, 0.0, 0.1402, 0.01627 - 12000.0, 0.8, 2.0, 0.374, 0.02094 - 12000.0, 0.8, 4.0, 0.6077, 0.03083 - 12000.0, 0.8, 6.0, 0.8414, 0.04744 - 12000.0, 0.8, 8.0, 1.0751, 0.07231 - 12000.0, 0.8, 10.0, 1.3089, 0.10697 - 12000.0, 0.8, 12.0, 1.5426, 0.15294 - 12000.0, 0.8, 14.0, 1.7763, 0.21177 - 12000.0, 0.8, 15.4, 1.9399, 0.26141 - 12000.0, 0.8, 15.4, 1.9399, 0.26141 - 12000.0, 0.8, 15.4, 1.9399, 0.26141 - 12000.0, 0.85, -2.0, -0.0984, 0.01571 - 12000.0, 0.85, 0.0, 0.1476, 0.01685 - 12000.0, 0.85, 2.0, 0.3936, 0.02498 - 12000.0, 0.85, 4.0, 0.6396, 0.04188 - 12000.0, 0.85, 6.0, 0.8855, 0.06933 - 12000.0, 0.85, 8.0, 1.1315, 0.10911 - 12000.0, 0.85, 10.0, 1.3775, 0.16302 - 12000.0, 0.85, 12.0, 1.6235, 0.23283 - 12000.0, 0.85, 14.0, 1.8695, 0.32033 - 12000.0, 0.85, 14.5, 1.929, 0.34436 - 12000.0, 0.85, 14.5, 1.929, 0.34436 - 12000.0, 0.85, 14.5, 1.929, 0.34436 - 12000.0, 0.9, -2.0, -0.1047, 0.01765 - 12000.0, 0.9, 0.0, 0.1571, 0.02393 - 12000.0, 0.9, 2.0, 0.4188, 0.04145 - 12000.0, 0.9, 4.0, 0.6806, 0.07236 - 12000.0, 0.9, 6.0, 0.9424, 0.11881 - 12000.0, 0.9, 8.0, 1.2041, 0.18295 - 12000.0, 0.9, 10.0, 1.4659, 0.26693 - 12000.0, 0.9, 12.0, 1.7277, 0.37289 - 12000.0, 0.9, 13.4, 1.9152, 0.46355 - 12000.0, 0.9, 13.4, 1.9152, 0.46355 - 12000.0, 0.9, 13.4, 1.9152, 0.46355 - 12000.0, 0.9, 13.4, 1.9152, 0.46355 - 15000.0, 0.0, -2.0, -0.0715, 0.00363 - 15000.0, 0.0, 0.0, 0.1072, 0.00384 - 15000.0, 0.0, 2.0, 0.286, 0.00621 - 15000.0, 0.0, 4.0, 0.4647, 0.01072 - 15000.0, 0.0, 6.0, 0.6434, 0.01737 - 15000.0, 0.0, 8.0, 0.8222, 0.02618 - 15000.0, 0.0, 10.0, 1.0009, 0.03713 - 15000.0, 0.0, 12.0, 1.1797, 0.05023 - 15000.0, 0.0, 14.0, 1.3584, 0.06548 - 15000.0, 0.0, 16.0, 1.5371, 0.08287 - 15000.0, 0.0, 18.0, 1.7159, 0.10241 - 15000.0, 0.0, 20.0, 1.8946, 0.1241 - 15000.0, 0.2, -2.0, -0.0724, 0.01939 - 15000.0, 0.2, 0.0, 0.1086, 0.01965 - 15000.0, 0.2, 2.0, 0.2896, 0.02252 - 15000.0, 0.2, 4.0, 0.4706, 0.02801 - 15000.0, 0.2, 6.0, 0.6517, 0.03611 - 15000.0, 0.2, 8.0, 0.8327, 0.04683 - 15000.0, 0.2, 10.0, 1.0137, 0.06016 - 15000.0, 0.2, 12.0, 1.1947, 0.0761 - 15000.0, 0.2, 14.0, 1.3757, 0.09465 - 15000.0, 0.2, 16.0, 1.5568, 0.11582 - 15000.0, 0.2, 18.0, 1.7378, 0.1396 - 15000.0, 0.2, 20.0, 1.9188, 0.166 - 15000.0, 0.4, -2.0, -0.0754, 0.01773 - 15000.0, 0.4, 0.0, 0.1131, 0.018 - 15000.0, 0.4, 2.0, 0.3016, 0.02107 - 15000.0, 0.4, 4.0, 0.4901, 0.02691 - 15000.0, 0.4, 6.0, 0.6786, 0.03554 - 15000.0, 0.4, 8.0, 0.867, 0.04696 - 15000.0, 0.4, 10.0, 1.0555, 0.06115 - 15000.0, 0.4, 12.0, 1.244, 0.07814 - 15000.0, 0.4, 14.0, 1.4325, 0.0979 - 15000.0, 0.4, 16.0, 1.621, 0.12045 - 15000.0, 0.4, 18.0, 1.8095, 0.14579 - 15000.0, 0.4, 19.8, 1.982, 0.17141 - 15000.0, 0.5, -2.0, -0.0779, 0.01719 - 15000.0, 0.5, 0.0, 0.1169, 0.01748 - 15000.0, 0.5, 2.0, 0.3117, 0.02073 - 15000.0, 0.5, 4.0, 0.5065, 0.02694 - 15000.0, 0.5, 6.0, 0.7013, 0.0361 - 15000.0, 0.5, 8.0, 0.8961, 0.04822 - 15000.0, 0.5, 10.0, 1.0909, 0.06329 - 15000.0, 0.5, 12.0, 1.2857, 0.08132 - 15000.0, 0.5, 14.0, 1.4806, 0.10231 - 15000.0, 0.5, 16.0, 1.6754, 0.12624 - 15000.0, 0.5, 18.0, 1.8702, 0.15314 - 15000.0, 0.5, 19.1, 1.976, 0.16898 - 15000.0, 0.6, -2.0, -0.0814, 0.01674 - 15000.0, 0.6, 0.0, 0.1221, 0.01706 - 15000.0, 0.6, 2.0, 0.3257, 0.02059 - 15000.0, 0.6, 4.0, 0.5293, 0.02733 - 15000.0, 0.6, 6.0, 0.7329, 0.03728 - 15000.0, 0.6, 8.0, 0.9365, 0.05044 - 15000.0, 0.6, 10.0, 1.1401, 0.06681 - 15000.0, 0.6, 12.0, 1.3436, 0.08639 - 15000.0, 0.6, 14.0, 1.5472, 0.10918 - 15000.0, 0.6, 16.0, 1.7508, 0.13518 - 15000.0, 0.6, 18.0, 1.9544, 0.16446 - 15000.0, 0.6, 18.1, 1.9677, 0.16649 - 15000.0, 0.7, -2.0, -0.0863, 0.01634 - 15000.0, 0.7, 0.0, 0.1295, 0.0167 - 15000.0, 0.7, 2.0, 0.3454, 0.02065 - 15000.0, 0.7, 4.0, 0.5613, 0.02819 - 15000.0, 0.7, 6.0, 0.7771, 0.03932 - 15000.0, 0.7, 8.0, 0.993, 0.05405 - 15000.0, 0.7, 10.0, 1.2089, 0.07251 - 15000.0, 0.7, 12.0, 1.4247, 0.09566 - 15000.0, 0.7, 14.0, 1.6406, 0.1247 - 15000.0, 0.7, 16.0, 1.8565, 0.16083 - 15000.0, 0.7, 16.9, 1.9562, 0.18026 - 15000.0, 0.7, 16.9, 1.9562, 0.18026 - 15000.0, 0.75, -2.0, -0.0896, 0.01617 - 15000.0, 0.75, 0.0, 0.1343, 0.01655 - 15000.0, 0.75, 2.0, 0.3582, 0.02079 - 15000.0, 0.75, 4.0, 0.5822, 0.02888 - 15000.0, 0.75, 6.0, 0.8061, 0.04097 - 15000.0, 0.75, 8.0, 1.03, 0.05805 - 15000.0, 0.75, 10.0, 1.2539, 0.08147 - 15000.0, 0.75, 12.0, 1.4778, 0.11258 - 15000.0, 0.75, 14.0, 1.7017, 0.15272 - 15000.0, 0.75, 16.0, 1.9256, 0.20324 - 15000.0, 0.75, 16.2, 1.9488, 0.20913 - 15000.0, 0.75, 16.2, 1.9488, 0.20913 - 15000.0, 0.8, -2.0, -0.0935, 0.016 - 15000.0, 0.8, 0.0, 0.1402, 0.01642 - 15000.0, 0.8, 2.0, 0.374, 0.0211 - 15000.0, 0.8, 4.0, 0.6077, 0.031 - 15000.0, 0.8, 6.0, 0.8414, 0.04763 - 15000.0, 0.8, 8.0, 1.0751, 0.07253 - 15000.0, 0.8, 10.0, 1.3089, 0.10722 - 15000.0, 0.8, 12.0, 1.5426, 0.15324 - 15000.0, 0.8, 14.0, 1.7763, 0.21211 - 15000.0, 0.8, 15.4, 1.9399, 0.26179 - 15000.0, 0.8, 15.4, 1.9399, 0.26179 - 15000.0, 0.8, 15.4, 1.9399, 0.26179 - 15000.0, 0.85, -2.0, -0.0984, 0.01586 - 15000.0, 0.85, 0.0, 0.1476, 0.017 - 15000.0, 0.85, 2.0, 0.3936, 0.02514 - 15000.0, 0.85, 4.0, 0.6396, 0.04205 - 15000.0, 0.85, 6.0, 0.8855, 0.06952 - 15000.0, 0.85, 8.0, 1.1315, 0.10934 - 15000.0, 0.85, 10.0, 1.3775, 0.16328 - 15000.0, 0.85, 12.0, 1.6235, 0.23313 - 15000.0, 0.85, 14.0, 1.8695, 0.32068 - 15000.0, 0.85, 14.5, 1.929, 0.34473 - 15000.0, 0.85, 14.5, 1.929, 0.34473 - 15000.0, 0.85, 14.5, 1.929, 0.34473 - 15000.0, 0.9, -2.0, -0.1047, 0.01779 - 15000.0, 0.9, 0.0, 0.1571, 0.02408 - 15000.0, 0.9, 2.0, 0.4188, 0.04161 - 15000.0, 0.9, 4.0, 0.6806, 0.07254 - 15000.0, 0.9, 6.0, 0.9424, 0.11901 - 15000.0, 0.9, 8.0, 1.2041, 0.18318 - 15000.0, 0.9, 10.0, 1.4659, 0.2672 - 15000.0, 0.9, 12.0, 1.7277, 0.37321 - 15000.0, 0.9, 13.4, 1.9152, 0.46391 - 15000.0, 0.9, 13.4, 1.9152, 0.46391 - 15000.0, 0.9, 13.4, 1.9152, 0.46391 - 15000.0, 0.9, 13.4, 1.9152, 0.46391 - 18000.0, 0.0, -2.0, -0.0715, 0.00363 - 18000.0, 0.0, 0.0, 0.1072, 0.00384 - 18000.0, 0.0, 2.0, 0.286, 0.00621 - 18000.0, 0.0, 4.0, 0.4647, 0.01072 - 18000.0, 0.0, 6.0, 0.6434, 0.01737 - 18000.0, 0.0, 8.0, 0.8222, 0.02618 - 18000.0, 0.0, 10.0, 1.0009, 0.03713 - 18000.0, 0.0, 12.0, 1.1797, 0.05023 - 18000.0, 0.0, 14.0, 1.3584, 0.06548 - 18000.0, 0.0, 16.0, 1.5371, 0.08287 - 18000.0, 0.0, 18.0, 1.7159, 0.10241 - 18000.0, 0.0, 20.0, 1.8946, 0.1241 - 18000.0, 0.2, -2.0, -0.0724, 0.01961 - 18000.0, 0.2, 0.0, 0.1086, 0.01987 - 18000.0, 0.2, 2.0, 0.2896, 0.02275 - 18000.0, 0.2, 4.0, 0.4706, 0.02825 - 18000.0, 0.2, 6.0, 0.6517, 0.03637 - 18000.0, 0.2, 8.0, 0.8327, 0.04711 - 18000.0, 0.2, 10.0, 1.0137, 0.06046 - 18000.0, 0.2, 12.0, 1.1947, 0.07644 - 18000.0, 0.2, 14.0, 1.3757, 0.09504 - 18000.0, 0.2, 16.0, 1.5568, 0.11625 - 18000.0, 0.2, 18.0, 1.7378, 0.14009 - 18000.0, 0.2, 20.0, 1.9188, 0.16654 - 18000.0, 0.4, -2.0, -0.0754, 0.01791 - 18000.0, 0.4, 0.0, 0.1131, 0.01819 - 18000.0, 0.4, 2.0, 0.3016, 0.02126 - 18000.0, 0.4, 4.0, 0.4901, 0.02712 - 18000.0, 0.4, 6.0, 0.6786, 0.03576 - 18000.0, 0.4, 8.0, 0.867, 0.0472 - 18000.0, 0.4, 10.0, 1.0555, 0.06143 - 18000.0, 0.4, 12.0, 1.244, 0.07844 - 18000.0, 0.4, 14.0, 1.4325, 0.09824 - 18000.0, 0.4, 16.0, 1.621, 0.12084 - 18000.0, 0.4, 18.0, 1.8095, 0.14622 - 18000.0, 0.4, 19.8, 1.982, 0.17189 - 18000.0, 0.5, -2.0, -0.0779, 0.01737 - 18000.0, 0.5, 0.0, 0.1169, 0.01766 - 18000.0, 0.5, 2.0, 0.3117, 0.02092 - 18000.0, 0.5, 4.0, 0.5065, 0.02714 - 18000.0, 0.5, 6.0, 0.7013, 0.03632 - 18000.0, 0.5, 8.0, 0.8961, 0.04846 - 18000.0, 0.5, 10.0, 1.0909, 0.06356 - 18000.0, 0.5, 12.0, 1.2857, 0.08162 - 18000.0, 0.5, 14.0, 1.4806, 0.10264 - 18000.0, 0.5, 16.0, 1.6754, 0.12662 - 18000.0, 0.5, 18.0, 1.8702, 0.15357 - 18000.0, 0.5, 19.1, 1.976, 0.16944 - 18000.0, 0.6, -2.0, -0.0814, 0.01691 - 18000.0, 0.6, 0.0, 0.1221, 0.01723 - 18000.0, 0.6, 2.0, 0.3257, 0.02077 - 18000.0, 0.6, 4.0, 0.5293, 0.02752 - 18000.0, 0.6, 6.0, 0.7329, 0.03749 - 18000.0, 0.6, 8.0, 0.9365, 0.05067 - 18000.0, 0.6, 10.0, 1.1401, 0.06707 - 18000.0, 0.6, 12.0, 1.3436, 0.08668 - 18000.0, 0.6, 14.0, 1.5472, 0.10951 - 18000.0, 0.6, 16.0, 1.7508, 0.13556 - 18000.0, 0.6, 18.0, 1.9544, 0.16489 - 18000.0, 0.6, 18.1, 1.9677, 0.16693 - 18000.0, 0.7, -2.0, -0.0863, 0.01651 - 18000.0, 0.7, 0.0, 0.1295, 0.01687 - 18000.0, 0.7, 2.0, 0.3454, 0.02082 - 18000.0, 0.7, 4.0, 0.5613, 0.02838 - 18000.0, 0.7, 6.0, 0.7771, 0.03953 - 18000.0, 0.7, 8.0, 0.993, 0.05427 - 18000.0, 0.7, 10.0, 1.2089, 0.07277 - 18000.0, 0.7, 12.0, 1.4247, 0.09595 - 18000.0, 0.7, 14.0, 1.6406, 0.12503 - 18000.0, 0.7, 16.0, 1.8565, 0.16122 - 18000.0, 0.7, 16.9, 1.9562, 0.18067 - 18000.0, 0.7, 16.9, 1.9562, 0.18067 - 18000.0, 0.75, -2.0, -0.0896, 0.01633 - 18000.0, 0.75, 0.0, 0.1343, 0.01671 - 18000.0, 0.75, 2.0, 0.3582, 0.02096 - 18000.0, 0.75, 4.0, 0.5822, 0.02907 - 18000.0, 0.75, 6.0, 0.8061, 0.04117 - 18000.0, 0.75, 8.0, 1.03, 0.05828 - 18000.0, 0.75, 10.0, 1.2539, 0.08173 - 18000.0, 0.75, 12.0, 1.4778, 0.11288 - 18000.0, 0.75, 14.0, 1.7017, 0.15306 - 18000.0, 0.75, 16.0, 1.9256, 0.20363 - 18000.0, 0.75, 16.2, 1.9488, 0.20953 - 18000.0, 0.75, 16.2, 1.9488, 0.20953 - 18000.0, 0.8, -2.0, -0.0935, 0.01616 - 18000.0, 0.8, 0.0, 0.1402, 0.01658 - 18000.0, 0.8, 2.0, 0.374, 0.02127 - 18000.0, 0.8, 4.0, 0.6077, 0.03118 - 18000.0, 0.8, 6.0, 0.8414, 0.04783 - 18000.0, 0.8, 8.0, 1.0751, 0.07276 - 18000.0, 0.8, 10.0, 1.3089, 0.10748 - 18000.0, 0.8, 12.0, 1.5426, 0.15354 - 18000.0, 0.8, 14.0, 1.7763, 0.21246 - 18000.0, 0.8, 15.4, 1.9399, 0.26218 - 18000.0, 0.8, 15.4, 1.9399, 0.26218 - 18000.0, 0.8, 15.4, 1.9399, 0.26218 - 18000.0, 0.85, -2.0, -0.0984, 0.01601 - 18000.0, 0.85, 0.0, 0.1476, 0.01716 - 18000.0, 0.85, 2.0, 0.3936, 0.0253 - 18000.0, 0.85, 4.0, 0.6396, 0.04223 - 18000.0, 0.85, 6.0, 0.8855, 0.06972 - 18000.0, 0.85, 8.0, 1.1315, 0.10957 - 18000.0, 0.85, 10.0, 1.3775, 0.16355 - 18000.0, 0.85, 12.0, 1.6235, 0.23345 - 18000.0, 0.85, 14.0, 1.8695, 0.32105 - 18000.0, 0.85, 14.5, 1.929, 0.34511 - 18000.0, 0.85, 14.5, 1.929, 0.34511 - 18000.0, 0.85, 14.5, 1.929, 0.34511 - 18000.0, 0.9, -2.0, -0.1047, 0.01795 - 18000.0, 0.9, 0.0, 0.1571, 0.02423 - 18000.0, 0.9, 2.0, 0.4188, 0.04177 - 18000.0, 0.9, 4.0, 0.6806, 0.07271 - 18000.0, 0.9, 6.0, 0.9424, 0.11922 - 18000.0, 0.9, 8.0, 1.2041, 0.18342 - 18000.0, 0.9, 10.0, 1.4659, 0.26748 - 18000.0, 0.9, 12.0, 1.7277, 0.37354 - 18000.0, 0.9, 13.4, 1.9152, 0.46428 - 18000.0, 0.9, 13.4, 1.9152, 0.46428 - 18000.0, 0.9, 13.4, 1.9152, 0.46428 - 18000.0, 0.9, 13.4, 1.9152, 0.46428 - 21000.0, 0.0, -2.0, -0.0715, 0.00363 - 21000.0, 0.0, 0.0, 0.1072, 0.00384 - 21000.0, 0.0, 2.0, 0.286, 0.00621 - 21000.0, 0.0, 4.0, 0.4647, 0.01072 - 21000.0, 0.0, 6.0, 0.6434, 0.01737 - 21000.0, 0.0, 8.0, 0.8222, 0.02618 - 21000.0, 0.0, 10.0, 1.0009, 0.03713 - 21000.0, 0.0, 12.0, 1.1797, 0.05023 - 21000.0, 0.0, 14.0, 1.3584, 0.06548 - 21000.0, 0.0, 16.0, 1.5371, 0.08287 - 21000.0, 0.0, 18.0, 1.7159, 0.10241 - 21000.0, 0.0, 20.0, 1.8946, 0.1241 - 21000.0, 0.2, -2.0, -0.0724, 0.01983 - 21000.0, 0.2, 0.0, 0.1086, 0.0201 - 21000.0, 0.2, 2.0, 0.2896, 0.02298 - 21000.0, 0.2, 4.0, 0.4706, 0.0285 - 21000.0, 0.2, 6.0, 0.6517, 0.03663 - 21000.0, 0.2, 8.0, 0.8327, 0.0474 - 21000.0, 0.2, 10.0, 1.0137, 0.06079 - 21000.0, 0.2, 12.0, 1.1947, 0.0768 - 21000.0, 0.2, 14.0, 1.3757, 0.09544 - 21000.0, 0.2, 16.0, 1.5568, 0.1167 - 21000.0, 0.2, 18.0, 1.7378, 0.14059 - 21000.0, 0.2, 20.0, 1.9188, 0.1671 - 21000.0, 0.4, -2.0, -0.0754, 0.01811 - 21000.0, 0.4, 0.0, 0.1131, 0.01839 - 21000.0, 0.4, 2.0, 0.3016, 0.02146 - 21000.0, 0.4, 4.0, 0.4901, 0.02733 - 21000.0, 0.4, 6.0, 0.6786, 0.036 - 21000.0, 0.4, 8.0, 0.867, 0.04745 - 21000.0, 0.4, 10.0, 1.0555, 0.06171 - 21000.0, 0.4, 12.0, 1.244, 0.07876 - 21000.0, 0.4, 14.0, 1.4325, 0.0986 - 21000.0, 0.4, 16.0, 1.621, 0.12124 - 21000.0, 0.4, 18.0, 1.8095, 0.14667 - 21000.0, 0.4, 19.8, 1.982, 0.17239 - 21000.0, 0.5, -2.0, -0.0779, 0.01755 - 21000.0, 0.5, 0.0, 0.1169, 0.01785 - 21000.0, 0.5, 2.0, 0.3117, 0.02111 - 21000.0, 0.5, 4.0, 0.5065, 0.02734 - 21000.0, 0.5, 6.0, 0.7013, 0.03654 - 21000.0, 0.5, 8.0, 0.8961, 0.0487 - 21000.0, 0.5, 10.0, 1.0909, 0.06383 - 21000.0, 0.5, 12.0, 1.2857, 0.08192 - 21000.0, 0.5, 14.0, 1.4806, 0.10299 - 21000.0, 0.5, 16.0, 1.6754, 0.12702 - 21000.0, 0.5, 18.0, 1.8702, 0.15401 - 21000.0, 0.5, 19.1, 1.976, 0.16991 - 21000.0, 0.6, -2.0, -0.0814, 0.01708 - 21000.0, 0.6, 0.0, 0.1221, 0.01741 - 21000.0, 0.6, 2.0, 0.3257, 0.02095 - 21000.0, 0.6, 4.0, 0.5293, 0.02771 - 21000.0, 0.6, 6.0, 0.7329, 0.0377 - 21000.0, 0.6, 8.0, 0.9365, 0.05091 - 21000.0, 0.6, 10.0, 1.1401, 0.06734 - 21000.0, 0.6, 12.0, 1.3436, 0.08699 - 21000.0, 0.6, 14.0, 1.5472, 0.10986 - 21000.0, 0.6, 16.0, 1.7508, 0.13595 - 21000.0, 0.6, 18.0, 1.9544, 0.16533 - 21000.0, 0.6, 18.1, 1.9677, 0.16738 - 21000.0, 0.7, -2.0, -0.0863, 0.01668 - 21000.0, 0.7, 0.0, 0.1295, 0.01704 - 21000.0, 0.7, 2.0, 0.3454, 0.021 - 21000.0, 0.7, 4.0, 0.5613, 0.02857 - 21000.0, 0.7, 6.0, 0.7771, 0.03974 - 21000.0, 0.7, 8.0, 0.993, 0.05451 - 21000.0, 0.7, 10.0, 1.2089, 0.07304 - 21000.0, 0.7, 12.0, 1.4247, 0.09626 - 21000.0, 0.7, 14.0, 1.6406, 0.12539 - 21000.0, 0.7, 16.0, 1.8565, 0.16162 - 21000.0, 0.7, 16.9, 1.9562, 0.1811 - 21000.0, 0.7, 16.9, 1.9562, 0.1811 - 21000.0, 0.75, -2.0, -0.0896, 0.01649 - 21000.0, 0.75, 0.0, 0.1343, 0.01688 - 21000.0, 0.75, 2.0, 0.3582, 0.02113 - 21000.0, 0.75, 4.0, 0.5822, 0.02925 - 21000.0, 0.75, 6.0, 0.8061, 0.04138 - 21000.0, 0.75, 8.0, 1.03, 0.05851 - 21000.0, 0.75, 10.0, 1.2539, 0.082 - 21000.0, 0.75, 12.0, 1.4778, 0.11319 - 21000.0, 0.75, 14.0, 1.7017, 0.15342 - 21000.0, 0.75, 16.0, 1.9256, 0.20405 - 21000.0, 0.75, 16.2, 1.9488, 0.20995 - 21000.0, 0.75, 16.2, 1.9488, 0.20995 - 21000.0, 0.8, -2.0, -0.0935, 0.01632 - 21000.0, 0.8, 0.0, 0.1402, 0.01674 - 21000.0, 0.8, 2.0, 0.374, 0.02144 - 21000.0, 0.8, 4.0, 0.6077, 0.03137 - 21000.0, 0.8, 6.0, 0.8414, 0.04804 - 21000.0, 0.8, 8.0, 1.0751, 0.073 - 21000.0, 0.8, 10.0, 1.3089, 0.10776 - 21000.0, 0.8, 12.0, 1.5426, 0.15386 - 21000.0, 0.8, 14.0, 1.7763, 0.21283 - 21000.0, 0.8, 15.4, 1.9399, 0.26259 - 21000.0, 0.8, 15.4, 1.9399, 0.26259 - 21000.0, 0.8, 15.4, 1.9399, 0.26259 - 21000.0, 0.85, -2.0, -0.0984, 0.01617 - 21000.0, 0.85, 0.0, 0.1476, 0.01732 - 21000.0, 0.85, 2.0, 0.3936, 0.02547 - 21000.0, 0.85, 4.0, 0.6396, 0.04241 - 21000.0, 0.85, 6.0, 0.8855, 0.06993 - 21000.0, 0.85, 8.0, 1.1315, 0.10981 - 21000.0, 0.85, 10.0, 1.3775, 0.16383 - 21000.0, 0.85, 12.0, 1.6235, 0.23378 - 21000.0, 0.85, 14.0, 1.8695, 0.32144 - 21000.0, 0.85, 14.5, 1.929, 0.34551 - 21000.0, 0.85, 14.5, 1.929, 0.34551 - 21000.0, 0.85, 14.5, 1.929, 0.34551 - 21000.0, 0.9, -2.0, -0.1047, 0.0181 - 21000.0, 0.9, 0.0, 0.1571, 0.02439 - 21000.0, 0.9, 2.0, 0.4188, 0.04194 - 21000.0, 0.9, 4.0, 0.6806, 0.0729 - 21000.0, 0.9, 6.0, 0.9424, 0.11943 - 21000.0, 0.9, 8.0, 1.2041, 0.18367 - 21000.0, 0.9, 10.0, 1.4659, 0.26777 - 21000.0, 0.9, 12.0, 1.7277, 0.37389 - 21000.0, 0.9, 13.4, 1.9152, 0.46467 - 21000.0, 0.9, 13.4, 1.9152, 0.46467 - 21000.0, 0.9, 13.4, 1.9152, 0.46467 - 21000.0, 0.9, 13.4, 1.9152, 0.46467 - 24000.0, 0.0, -2.0, -0.0715, 0.00363 - 24000.0, 0.0, 0.0, 0.1072, 0.00384 - 24000.0, 0.0, 2.0, 0.286, 0.00621 - 24000.0, 0.0, 4.0, 0.4647, 0.01072 - 24000.0, 0.0, 6.0, 0.6434, 0.01737 - 24000.0, 0.0, 8.0, 0.8222, 0.02618 - 24000.0, 0.0, 10.0, 1.0009, 0.03713 - 24000.0, 0.0, 12.0, 1.1797, 0.05023 - 24000.0, 0.0, 14.0, 1.3584, 0.06548 - 24000.0, 0.0, 16.0, 1.5371, 0.08287 - 24000.0, 0.0, 18.0, 1.7159, 0.10241 - 24000.0, 0.0, 20.0, 1.8946, 0.1241 - 24000.0, 0.2, -2.0, -0.0724, 0.02007 - 24000.0, 0.2, 0.0, 0.1086, 0.02034 - 24000.0, 0.2, 2.0, 0.2896, 0.02323 - 24000.0, 0.2, 4.0, 0.4706, 0.02876 - 24000.0, 0.2, 6.0, 0.6517, 0.03691 - 24000.0, 0.2, 8.0, 0.8327, 0.0477 - 24000.0, 0.2, 10.0, 1.0137, 0.06112 - 24000.0, 0.2, 12.0, 1.1947, 0.07717 - 24000.0, 0.2, 14.0, 1.3757, 0.09585 - 24000.0, 0.2, 16.0, 1.5568, 0.11717 - 24000.0, 0.2, 18.0, 1.7378, 0.14111 - 24000.0, 0.2, 20.0, 1.9188, 0.16769 - 24000.0, 0.4, -2.0, -0.0754, 0.01831 - 24000.0, 0.4, 0.0, 0.1131, 0.01859 - 24000.0, 0.4, 2.0, 0.3016, 0.02167 - 24000.0, 0.4, 4.0, 0.4901, 0.02756 - 24000.0, 0.4, 6.0, 0.6786, 0.03624 - 24000.0, 0.4, 8.0, 0.867, 0.04772 - 24000.0, 0.4, 10.0, 1.0555, 0.062 - 24000.0, 0.4, 12.0, 1.244, 0.07909 - 24000.0, 0.4, 14.0, 1.4325, 0.09897 - 24000.0, 0.4, 16.0, 1.621, 0.12166 - 24000.0, 0.4, 18.0, 1.8095, 0.14714 - 24000.0, 0.4, 19.8, 1.982, 0.17292 - 24000.0, 0.5, -2.0, -0.0779, 0.01775 - 24000.0, 0.5, 0.0, 0.1169, 0.01804 - 24000.0, 0.5, 2.0, 0.3117, 0.02131 - 24000.0, 0.5, 4.0, 0.5065, 0.02755 - 24000.0, 0.5, 6.0, 0.7013, 0.03677 - 24000.0, 0.5, 8.0, 0.8961, 0.04895 - 24000.0, 0.5, 10.0, 1.0909, 0.06411 - 24000.0, 0.5, 12.0, 1.2857, 0.08225 - 24000.0, 0.5, 14.0, 1.4806, 0.10335 - 24000.0, 0.5, 16.0, 1.6754, 0.12743 - 24000.0, 0.5, 18.0, 1.8702, 0.15447 - 24000.0, 0.5, 19.1, 1.976, 0.17041 - 24000.0, 0.6, -2.0, -0.0814, 0.01727 - 24000.0, 0.6, 0.0, 0.1221, 0.01759 - 24000.0, 0.6, 2.0, 0.3257, 0.02114 - 24000.0, 0.6, 4.0, 0.5293, 0.02792 - 24000.0, 0.6, 6.0, 0.7329, 0.03792 - 24000.0, 0.6, 8.0, 0.9365, 0.05116 - 24000.0, 0.6, 10.0, 1.1401, 0.06762 - 24000.0, 0.6, 12.0, 1.3436, 0.08731 - 24000.0, 0.6, 14.0, 1.5472, 0.11022 - 24000.0, 0.6, 16.0, 1.7508, 0.13636 - 24000.0, 0.6, 18.0, 1.9544, 0.1658 - 24000.0, 0.6, 18.1, 1.9677, 0.16785 - 24000.0, 0.7, -2.0, -0.0863, 0.01685 - 24000.0, 0.7, 0.0, 0.1295, 0.01722 - 24000.0, 0.7, 2.0, 0.3454, 0.02119 - 24000.0, 0.7, 4.0, 0.5613, 0.02877 - 24000.0, 0.7, 6.0, 0.7771, 0.03996 - 24000.0, 0.7, 8.0, 0.993, 0.05476 - 24000.0, 0.7, 10.0, 1.2089, 0.07332 - 24000.0, 0.7, 12.0, 1.4247, 0.09658 - 24000.0, 0.7, 14.0, 1.6406, 0.12575 - 24000.0, 0.7, 16.0, 1.8565, 0.16204 - 24000.0, 0.7, 16.9, 1.9562, 0.18155 - 24000.0, 0.7, 16.9, 1.9562, 0.18155 - 24000.0, 0.75, -2.0, -0.0896, 0.01667 - 24000.0, 0.75, 0.0, 0.1343, 0.01705 - 24000.0, 0.75, 2.0, 0.3582, 0.02132 - 24000.0, 0.75, 4.0, 0.5822, 0.02945 - 24000.0, 0.75, 6.0, 0.8061, 0.0416 - 24000.0, 0.75, 8.0, 1.03, 0.05876 - 24000.0, 0.75, 10.0, 1.2539, 0.08228 - 24000.0, 0.75, 12.0, 1.4778, 0.11352 - 24000.0, 0.75, 14.0, 1.7017, 0.1538 - 24000.0, 0.75, 16.0, 1.9256, 0.20448 - 24000.0, 0.75, 16.2, 1.9488, 0.21039 - 24000.0, 0.75, 16.2, 1.9488, 0.21039 - 24000.0, 0.8, -2.0, -0.0935, 0.01649 - 24000.0, 0.8, 0.0, 0.1402, 0.01691 - 24000.0, 0.8, 2.0, 0.374, 0.02162 - 24000.0, 0.8, 4.0, 0.6077, 0.03156 - 24000.0, 0.8, 6.0, 0.8414, 0.04826 - 24000.0, 0.8, 8.0, 1.0751, 0.07325 - 24000.0, 0.8, 10.0, 1.3089, 0.10805 - 24000.0, 0.8, 12.0, 1.5426, 0.15419 - 24000.0, 0.8, 14.0, 1.7763, 0.21322 - 24000.0, 0.8, 15.4, 1.9399, 0.26302 - 24000.0, 0.8, 15.4, 1.9399, 0.26302 - 24000.0, 0.8, 15.4, 1.9399, 0.26302 - 24000.0, 0.85, -2.0, -0.0984, 0.01634 - 24000.0, 0.85, 0.0, 0.1476, 0.01749 - 24000.0, 0.85, 2.0, 0.3936, 0.02565 - 24000.0, 0.85, 4.0, 0.6396, 0.04261 - 24000.0, 0.85, 6.0, 0.8855, 0.07015 - 24000.0, 0.85, 8.0, 1.1315, 0.11006 - 24000.0, 0.85, 10.0, 1.3775, 0.16412 - 24000.0, 0.85, 12.0, 1.6235, 0.23412 - 24000.0, 0.85, 14.0, 1.8695, 0.32184 - 24000.0, 0.85, 14.5, 1.929, 0.34592 - 24000.0, 0.85, 14.5, 1.929, 0.34592 - 24000.0, 0.85, 14.5, 1.929, 0.34592 - 24000.0, 0.9, -2.0, -0.1047, 0.01827 - 24000.0, 0.9, 0.0, 0.1571, 0.02455 - 24000.0, 0.9, 2.0, 0.4188, 0.04211 - 24000.0, 0.9, 4.0, 0.6806, 0.0731 - 24000.0, 0.9, 6.0, 0.9424, 0.11965 - 24000.0, 0.9, 8.0, 1.2041, 0.18393 - 24000.0, 0.9, 10.0, 1.4659, 0.26808 - 24000.0, 0.9, 12.0, 1.7277, 0.37425 - 24000.0, 0.9, 13.4, 1.9152, 0.46507 - 24000.0, 0.9, 13.4, 1.9152, 0.46507 - 24000.0, 0.9, 13.4, 1.9152, 0.46507 - 24000.0, 0.9, 13.4, 1.9152, 0.46507 - 27000.0, 0.0, -2.0, -0.0715, 0.00363 - 27000.0, 0.0, 0.0, 0.1072, 0.00384 - 27000.0, 0.0, 2.0, 0.286, 0.00621 - 27000.0, 0.0, 4.0, 0.4647, 0.01072 - 27000.0, 0.0, 6.0, 0.6434, 0.01737 - 27000.0, 0.0, 8.0, 0.8222, 0.02618 - 27000.0, 0.0, 10.0, 1.0009, 0.03713 - 27000.0, 0.0, 12.0, 1.1797, 0.05023 - 27000.0, 0.0, 14.0, 1.3584, 0.06548 - 27000.0, 0.0, 16.0, 1.5371, 0.08287 - 27000.0, 0.0, 18.0, 1.7159, 0.10241 - 27000.0, 0.0, 20.0, 1.8946, 0.1241 - 27000.0, 0.2, -2.0, -0.0724, 0.02032 - 27000.0, 0.2, 0.0, 0.1086, 0.02058 - 27000.0, 0.2, 2.0, 0.2896, 0.02349 - 27000.0, 0.2, 4.0, 0.4706, 0.02903 - 27000.0, 0.2, 6.0, 0.6517, 0.0372 - 27000.0, 0.2, 8.0, 0.8327, 0.04802 - 27000.0, 0.2, 10.0, 1.0137, 0.06147 - 27000.0, 0.2, 12.0, 1.1947, 0.07756 - 27000.0, 0.2, 14.0, 1.3757, 0.09629 - 27000.0, 0.2, 16.0, 1.5568, 0.11766 - 27000.0, 0.2, 18.0, 1.7378, 0.14166 - 27000.0, 0.2, 20.0, 1.9188, 0.1683 - 27000.0, 0.4, -2.0, -0.0754, 0.01853 - 27000.0, 0.4, 0.0, 0.1131, 0.01881 - 27000.0, 0.4, 2.0, 0.3016, 0.02189 - 27000.0, 0.4, 4.0, 0.4901, 0.02779 - 27000.0, 0.4, 6.0, 0.6786, 0.03649 - 27000.0, 0.4, 8.0, 0.867, 0.048 - 27000.0, 0.4, 10.0, 1.0555, 0.06231 - 27000.0, 0.4, 12.0, 1.244, 0.07943 - 27000.0, 0.4, 14.0, 1.4325, 0.09936 - 27000.0, 0.4, 16.0, 1.621, 0.12209 - 27000.0, 0.4, 18.0, 1.8095, 0.14763 - 27000.0, 0.4, 19.8, 1.982, 0.17346 - 27000.0, 0.5, -2.0, -0.0779, 0.01795 - 27000.0, 0.5, 0.0, 0.1169, 0.01824 - 27000.0, 0.5, 2.0, 0.3117, 0.02152 - 27000.0, 0.5, 4.0, 0.5065, 0.02778 - 27000.0, 0.5, 6.0, 0.7013, 0.03701 - 27000.0, 0.5, 8.0, 0.8961, 0.04922 - 27000.0, 0.5, 10.0, 1.0909, 0.06441 - 27000.0, 0.5, 12.0, 1.2857, 0.08258 - 27000.0, 0.5, 14.0, 1.4806, 0.10373 - 27000.0, 0.5, 16.0, 1.6754, 0.12785 - 27000.0, 0.5, 18.0, 1.8702, 0.15496 - 27000.0, 0.5, 19.1, 1.976, 0.17092 - 27000.0, 0.6, -2.0, -0.0814, 0.01746 - 27000.0, 0.6, 0.0, 0.1221, 0.01778 - 27000.0, 0.6, 2.0, 0.3257, 0.02134 - 27000.0, 0.6, 4.0, 0.5293, 0.02813 - 27000.0, 0.6, 6.0, 0.7329, 0.03816 - 27000.0, 0.6, 8.0, 0.9365, 0.05142 - 27000.0, 0.6, 10.0, 1.1401, 0.06791 - 27000.0, 0.6, 12.0, 1.3436, 0.08764 - 27000.0, 0.6, 14.0, 1.5472, 0.1106 - 27000.0, 0.6, 16.0, 1.7508, 0.13679 - 27000.0, 0.6, 18.0, 1.9544, 0.16628 - 27000.0, 0.6, 18.1, 1.9677, 0.16834 - 27000.0, 0.7, -2.0, -0.0863, 0.01704 - 27000.0, 0.7, 0.0, 0.1295, 0.0174 - 27000.0, 0.7, 2.0, 0.3454, 0.02138 - 27000.0, 0.7, 4.0, 0.5613, 0.02897 - 27000.0, 0.7, 6.0, 0.7771, 0.04019 - 27000.0, 0.7, 8.0, 0.993, 0.05501 - 27000.0, 0.7, 10.0, 1.2089, 0.07361 - 27000.0, 0.7, 12.0, 1.4247, 0.09692 - 27000.0, 0.7, 14.0, 1.6406, 0.12614 - 27000.0, 0.7, 16.0, 1.8565, 0.16248 - 27000.0, 0.7, 16.9, 1.9562, 0.18201 - 27000.0, 0.7, 16.9, 1.9562, 0.18201 - 27000.0, 0.75, -2.0, -0.0896, 0.01685 - 27000.0, 0.75, 0.0, 0.1343, 0.01724 - 27000.0, 0.75, 2.0, 0.3582, 0.02151 - 27000.0, 0.75, 4.0, 0.5822, 0.02966 - 27000.0, 0.75, 6.0, 0.8061, 0.04182 - 27000.0, 0.75, 8.0, 1.03, 0.05902 - 27000.0, 0.75, 10.0, 1.2539, 0.08258 - 27000.0, 0.75, 12.0, 1.4778, 0.11385 - 27000.0, 0.75, 14.0, 1.7017, 0.15419 - 27000.0, 0.75, 16.0, 1.9256, 0.20492 - 27000.0, 0.75, 16.2, 1.9488, 0.21085 - 27000.0, 0.75, 16.2, 1.9488, 0.21085 - 27000.0, 0.8, -2.0, -0.0935, 0.01667 - 27000.0, 0.8, 0.0, 0.1402, 0.01709 - 27000.0, 0.8, 2.0, 0.374, 0.02181 - 27000.0, 0.8, 4.0, 0.6077, 0.03177 - 27000.0, 0.8, 6.0, 0.8414, 0.04849 - 27000.0, 0.8, 8.0, 1.0751, 0.0735 - 27000.0, 0.8, 10.0, 1.3089, 0.10835 - 27000.0, 0.8, 12.0, 1.5426, 0.15454 - 27000.0, 0.8, 14.0, 1.7763, 0.21362 - 27000.0, 0.8, 15.4, 1.9399, 0.26346 - 27000.0, 0.8, 15.4, 1.9399, 0.26346 - 27000.0, 0.8, 15.4, 1.9399, 0.26346 - 27000.0, 0.85, -2.0, -0.0984, 0.01652 - 27000.0, 0.85, 0.0, 0.1476, 0.01766 - 27000.0, 0.85, 2.0, 0.3936, 0.02583 - 27000.0, 0.85, 4.0, 0.6396, 0.04281 - 27000.0, 0.85, 6.0, 0.8855, 0.07038 - 27000.0, 0.85, 8.0, 1.1315, 0.11033 - 27000.0, 0.85, 10.0, 1.3775, 0.16443 - 27000.0, 0.85, 12.0, 1.6235, 0.23448 - 27000.0, 0.85, 14.0, 1.8695, 0.32225 - 27000.0, 0.85, 14.5, 1.929, 0.34636 - 27000.0, 0.85, 14.5, 1.929, 0.34636 - 27000.0, 0.85, 14.5, 1.929, 0.34636 - 27000.0, 0.9, -2.0, -0.1047, 0.01844 - 27000.0, 0.9, 0.0, 0.1571, 0.02473 - 27000.0, 0.9, 2.0, 0.4188, 0.0423 - 27000.0, 0.9, 4.0, 0.6806, 0.0733 - 27000.0, 0.9, 6.0, 0.9424, 0.11988 - 27000.0, 0.9, 8.0, 1.2041, 0.1842 - 27000.0, 0.9, 10.0, 1.4659, 0.26839 - 27000.0, 0.9, 12.0, 1.7277, 0.37462 - 27000.0, 0.9, 13.4, 1.9152, 0.46549 - 27000.0, 0.9, 13.4, 1.9152, 0.46549 - 27000.0, 0.9, 13.4, 1.9152, 0.46549 - 27000.0, 0.9, 13.4, 1.9152, 0.46549 - 30000.0, 0.0, -2.0, -0.0715, 0.00363 - 30000.0, 0.0, 0.0, 0.1072, 0.00384 - 30000.0, 0.0, 2.0, 0.286, 0.00621 - 30000.0, 0.0, 4.0, 0.4647, 0.01072 - 30000.0, 0.0, 6.0, 0.6434, 0.01737 - 30000.0, 0.0, 8.0, 0.8222, 0.02618 - 30000.0, 0.0, 10.0, 1.0009, 0.03713 - 30000.0, 0.0, 12.0, 1.1797, 0.05023 - 30000.0, 0.0, 14.0, 1.3584, 0.06548 - 30000.0, 0.0, 16.0, 1.5371, 0.08287 - 30000.0, 0.0, 18.0, 1.7159, 0.10241 - 30000.0, 0.0, 20.0, 1.8946, 0.1241 - 30000.0, 0.2, -2.0, -0.0724, 0.02058 - 30000.0, 0.2, 0.0, 0.1086, 0.02085 - 30000.0, 0.2, 2.0, 0.2896, 0.02375 - 30000.0, 0.2, 4.0, 0.4706, 0.02931 - 30000.0, 0.2, 6.0, 0.6517, 0.03751 - 30000.0, 0.2, 8.0, 0.8327, 0.04835 - 30000.0, 0.2, 10.0, 1.0137, 0.06184 - 30000.0, 0.2, 12.0, 1.1947, 0.07797 - 30000.0, 0.2, 14.0, 1.3757, 0.09675 - 30000.0, 0.2, 16.0, 1.5568, 0.11817 - 30000.0, 0.2, 18.0, 1.7378, 0.14223 - 30000.0, 0.2, 20.0, 1.9188, 0.16894 - 30000.0, 0.4, -2.0, -0.0754, 0.01875 - 30000.0, 0.4, 0.0, 0.1131, 0.01903 - 30000.0, 0.4, 2.0, 0.3016, 0.02212 - 30000.0, 0.4, 4.0, 0.4901, 0.02803 - 30000.0, 0.4, 6.0, 0.6786, 0.03675 - 30000.0, 0.4, 8.0, 0.867, 0.04828 - 30000.0, 0.4, 10.0, 1.0555, 0.06263 - 30000.0, 0.4, 12.0, 1.244, 0.07979 - 30000.0, 0.4, 14.0, 1.4325, 0.09976 - 30000.0, 0.4, 16.0, 1.621, 0.12255 - 30000.0, 0.4, 18.0, 1.8095, 0.14814 - 30000.0, 0.4, 19.8, 1.982, 0.17404 - 30000.0, 0.5, -2.0, -0.0779, 0.01816 - 30000.0, 0.5, 0.0, 0.1169, 0.01846 - 30000.0, 0.5, 2.0, 0.3117, 0.02174 - 30000.0, 0.5, 4.0, 0.5065, 0.02801 - 30000.0, 0.5, 6.0, 0.7013, 0.03726 - 30000.0, 0.5, 8.0, 0.8961, 0.0495 - 30000.0, 0.5, 10.0, 1.0909, 0.06472 - 30000.0, 0.5, 12.0, 1.2857, 0.08293 - 30000.0, 0.5, 14.0, 1.4806, 0.10412 - 30000.0, 0.5, 16.0, 1.6754, 0.1283 - 30000.0, 0.5, 18.0, 1.8702, 0.15546 - 30000.0, 0.5, 19.1, 1.976, 0.17146 - 30000.0, 0.6, -2.0, -0.0814, 0.01766 - 30000.0, 0.6, 0.0, 0.1221, 0.01799 - 30000.0, 0.6, 2.0, 0.3257, 0.02155 - 30000.0, 0.6, 4.0, 0.5293, 0.02836 - 30000.0, 0.6, 6.0, 0.7329, 0.0384 - 30000.0, 0.6, 8.0, 0.9365, 0.05169 - 30000.0, 0.6, 10.0, 1.1401, 0.06822 - 30000.0, 0.6, 12.0, 1.3436, 0.08798 - 30000.0, 0.6, 14.0, 1.5472, 0.11099 - 30000.0, 0.6, 16.0, 1.7508, 0.13724 - 30000.0, 0.6, 18.0, 1.9544, 0.16679 - 30000.0, 0.6, 18.1, 1.9677, 0.16885 - 30000.0, 0.7, -2.0, -0.0863, 0.01723 - 30000.0, 0.7, 0.0, 0.1295, 0.01759 - 30000.0, 0.7, 2.0, 0.3454, 0.02158 - 30000.0, 0.7, 4.0, 0.5613, 0.02919 - 30000.0, 0.7, 6.0, 0.7771, 0.04043 - 30000.0, 0.7, 8.0, 0.993, 0.05528 - 30000.0, 0.7, 10.0, 1.2089, 0.07391 - 30000.0, 0.7, 12.0, 1.4247, 0.09726 - 30000.0, 0.7, 14.0, 1.6406, 0.12654 - 30000.0, 0.7, 16.0, 1.8565, 0.16294 - 30000.0, 0.7, 16.9, 1.9562, 0.1825 - 30000.0, 0.7, 16.9, 1.9562, 0.1825 - 30000.0, 0.75, -2.0, -0.0896, 0.01704 - 30000.0, 0.75, 0.0, 0.1343, 0.01743 - 30000.0, 0.75, 2.0, 0.3582, 0.0217 - 30000.0, 0.75, 4.0, 0.5822, 0.02987 - 30000.0, 0.75, 6.0, 0.8061, 0.04206 - 30000.0, 0.75, 8.0, 1.03, 0.05929 - 30000.0, 0.75, 10.0, 1.2539, 0.08289 - 30000.0, 0.75, 12.0, 1.4778, 0.11421 - 30000.0, 0.75, 14.0, 1.7017, 0.15459 - 30000.0, 0.75, 16.0, 1.9256, 0.20539 - 30000.0, 0.75, 16.2, 1.9488, 0.21132 - 30000.0, 0.75, 16.2, 1.9488, 0.21132 - 30000.0, 0.8, -2.0, -0.0935, 0.01686 - 30000.0, 0.8, 0.0, 0.1402, 0.01728 - 30000.0, 0.8, 2.0, 0.374, 0.022 - 30000.0, 0.8, 4.0, 0.6077, 0.03198 - 30000.0, 0.8, 6.0, 0.8414, 0.04873 - 30000.0, 0.8, 8.0, 1.0751, 0.07378 - 30000.0, 0.8, 10.0, 1.3089, 0.10866 - 30000.0, 0.8, 12.0, 1.5426, 0.1549 - 30000.0, 0.8, 14.0, 1.7763, 0.21404 - 30000.0, 0.8, 15.4, 1.9399, 0.26393 - 30000.0, 0.8, 15.4, 1.9399, 0.26393 - 30000.0, 0.8, 15.4, 1.9399, 0.26393 - 30000.0, 0.85, -2.0, -0.0984, 0.0167 - 30000.0, 0.85, 0.0, 0.1476, 0.01785 - 30000.0, 0.85, 2.0, 0.3936, 0.02603 - 30000.0, 0.85, 4.0, 0.6396, 0.04302 - 30000.0, 0.85, 6.0, 0.8855, 0.07062 - 30000.0, 0.85, 8.0, 1.1315, 0.1106 - 30000.0, 0.85, 10.0, 1.3775, 0.16475 - 30000.0, 0.85, 12.0, 1.6235, 0.23485 - 30000.0, 0.85, 14.0, 1.8695, 0.32269 - 30000.0, 0.85, 14.5, 1.929, 0.34681 - 30000.0, 0.85, 14.5, 1.929, 0.34681 - 30000.0, 0.85, 14.5, 1.929, 0.34681 - 30000.0, 0.9, -2.0, -0.1047, 0.01862 - 30000.0, 0.9, 0.0, 0.1571, 0.02491 - 30000.0, 0.9, 2.0, 0.4188, 0.04249 - 30000.0, 0.9, 4.0, 0.6806, 0.07351 - 30000.0, 0.9, 6.0, 0.9424, 0.12012 - 30000.0, 0.9, 8.0, 1.2041, 0.18448 - 30000.0, 0.9, 10.0, 1.4659, 0.26872 - 30000.0, 0.9, 12.0, 1.7277, 0.37501 - 30000.0, 0.9, 13.4, 1.9152, 0.46593 - 30000.0, 0.9, 13.4, 1.9152, 0.46593 - 30000.0, 0.9, 13.4, 1.9152, 0.46593 - 30000.0, 0.9, 13.4, 1.9152, 0.46593 - 33000.0, 0.0, -2.0, -0.0715, 0.00363 - 33000.0, 0.0, 0.0, 0.1072, 0.00384 - 33000.0, 0.0, 2.0, 0.286, 0.00621 - 33000.0, 0.0, 4.0, 0.4647, 0.01072 - 33000.0, 0.0, 6.0, 0.6434, 0.01737 - 33000.0, 0.0, 8.0, 0.8222, 0.02618 - 33000.0, 0.0, 10.0, 1.0009, 0.03713 - 33000.0, 0.0, 12.0, 1.1797, 0.05023 - 33000.0, 0.0, 14.0, 1.3584, 0.06548 - 33000.0, 0.0, 16.0, 1.5371, 0.08287 - 33000.0, 0.0, 18.0, 1.7159, 0.10241 - 33000.0, 0.0, 20.0, 1.8946, 0.1241 - 33000.0, 0.2, -2.0, -0.0724, 0.02085 - 33000.0, 0.2, 0.0, 0.1086, 0.02112 - 33000.0, 0.2, 2.0, 0.2896, 0.02404 - 33000.0, 0.2, 4.0, 0.4706, 0.0296 - 33000.0, 0.2, 6.0, 0.6517, 0.03782 - 33000.0, 0.2, 8.0, 0.8327, 0.0487 - 33000.0, 0.2, 10.0, 1.0137, 0.06222 - 33000.0, 0.2, 12.0, 1.1947, 0.0784 - 33000.0, 0.2, 14.0, 1.3757, 0.09722 - 33000.0, 0.2, 16.0, 1.5568, 0.1187 - 33000.0, 0.2, 18.0, 1.7378, 0.14283 - 33000.0, 0.2, 20.0, 1.9188, 0.16962 - 33000.0, 0.4, -2.0, -0.0754, 0.01898 - 33000.0, 0.4, 0.0, 0.1131, 0.01926 - 33000.0, 0.4, 2.0, 0.3016, 0.02236 - 33000.0, 0.4, 4.0, 0.4901, 0.02829 - 33000.0, 0.4, 6.0, 0.6786, 0.03703 - 33000.0, 0.4, 8.0, 0.867, 0.04859 - 33000.0, 0.4, 10.0, 1.0555, 0.06297 - 33000.0, 0.4, 12.0, 1.244, 0.08017 - 33000.0, 0.4, 14.0, 1.4325, 0.10018 - 33000.0, 0.4, 16.0, 1.621, 0.12302 - 33000.0, 0.4, 18.0, 1.8095, 0.14868 - 33000.0, 0.4, 19.8, 1.982, 0.17463 - 33000.0, 0.5, -2.0, -0.0779, 0.01838 - 33000.0, 0.5, 0.0, 0.1169, 0.01868 - 33000.0, 0.5, 2.0, 0.3117, 0.02197 - 33000.0, 0.5, 4.0, 0.5065, 0.02825 - 33000.0, 0.5, 6.0, 0.7013, 0.03752 - 33000.0, 0.5, 8.0, 0.8961, 0.04979 - 33000.0, 0.5, 10.0, 1.0909, 0.06505 - 33000.0, 0.5, 12.0, 1.2857, 0.0833 - 33000.0, 0.5, 14.0, 1.4806, 0.10454 - 33000.0, 0.5, 16.0, 1.6754, 0.12877 - 33000.0, 0.5, 18.0, 1.8702, 0.15599 - 33000.0, 0.5, 19.1, 1.976, 0.17203 - 33000.0, 0.6, -2.0, -0.0814, 0.01787 - 33000.0, 0.6, 0.0, 0.1221, 0.0182 - 33000.0, 0.6, 2.0, 0.3257, 0.02177 - 33000.0, 0.6, 4.0, 0.5293, 0.02859 - 33000.0, 0.6, 6.0, 0.7329, 0.03866 - 33000.0, 0.6, 8.0, 0.9365, 0.05197 - 33000.0, 0.6, 10.0, 1.1401, 0.06853 - 33000.0, 0.6, 12.0, 1.3436, 0.08834 - 33000.0, 0.6, 14.0, 1.5472, 0.1114 - 33000.0, 0.6, 16.0, 1.7508, 0.13771 - 33000.0, 0.6, 18.0, 1.9544, 0.16732 - 33000.0, 0.6, 18.1, 1.9677, 0.16939 - 33000.0, 0.7, -2.0, -0.0863, 0.01743 - 33000.0, 0.7, 0.0, 0.1295, 0.0178 - 33000.0, 0.7, 2.0, 0.3454, 0.02179 - 33000.0, 0.7, 4.0, 0.5613, 0.02942 - 33000.0, 0.7, 6.0, 0.7771, 0.04067 - 33000.0, 0.7, 8.0, 0.993, 0.05556 - 33000.0, 0.7, 10.0, 1.2089, 0.07423 - 33000.0, 0.7, 12.0, 1.4247, 0.09763 - 33000.0, 0.7, 14.0, 1.6406, 0.12696 - 33000.0, 0.7, 16.0, 1.8565, 0.16342 - 33000.0, 0.7, 16.9, 1.9562, 0.18301 - 33000.0, 0.7, 16.9, 1.9562, 0.18301 - 33000.0, 0.75, -2.0, -0.0896, 0.01723 - 33000.0, 0.75, 0.0, 0.1343, 0.01762 - 33000.0, 0.75, 2.0, 0.3582, 0.02191 - 33000.0, 0.75, 4.0, 0.5822, 0.03009 - 33000.0, 0.75, 6.0, 0.8061, 0.04231 - 33000.0, 0.75, 8.0, 1.03, 0.05957 - 33000.0, 0.75, 10.0, 1.2539, 0.08321 - 33000.0, 0.75, 12.0, 1.4778, 0.11458 - 33000.0, 0.75, 14.0, 1.7017, 0.15502 - 33000.0, 0.75, 16.0, 1.9256, 0.20588 - 33000.0, 0.75, 16.2, 1.9488, 0.21182 - 33000.0, 0.75, 16.2, 1.9488, 0.21182 - 33000.0, 0.8, -2.0, -0.0935, 0.01705 - 33000.0, 0.8, 0.0, 0.1402, 0.01747 - 33000.0, 0.8, 2.0, 0.374, 0.02221 - 33000.0, 0.8, 4.0, 0.6077, 0.0322 - 33000.0, 0.8, 6.0, 0.8414, 0.04897 - 33000.0, 0.8, 8.0, 1.0751, 0.07406 - 33000.0, 0.8, 10.0, 1.3089, 0.10898 - 33000.0, 0.8, 12.0, 1.5426, 0.15528 - 33000.0, 0.8, 14.0, 1.7763, 0.21447 - 33000.0, 0.8, 15.4, 1.9399, 0.26441 - 33000.0, 0.8, 15.4, 1.9399, 0.26441 - 33000.0, 0.8, 15.4, 1.9399, 0.26441 - 33000.0, 0.85, -2.0, -0.0984, 0.01689 - 33000.0, 0.85, 0.0, 0.1476, 0.01804 - 33000.0, 0.85, 2.0, 0.3936, 0.02623 - 33000.0, 0.85, 4.0, 0.6396, 0.04324 - 33000.0, 0.85, 6.0, 0.8855, 0.07087 - 33000.0, 0.85, 8.0, 1.1315, 0.11089 - 33000.0, 0.85, 10.0, 1.3775, 0.16508 - 33000.0, 0.85, 12.0, 1.6235, 0.23524 - 33000.0, 0.85, 14.0, 1.8695, 0.32314 - 33000.0, 0.85, 14.5, 1.929, 0.34728 - 33000.0, 0.85, 14.5, 1.929, 0.34728 - 33000.0, 0.85, 14.5, 1.929, 0.34728 - 33000.0, 0.9, -2.0, -0.1047, 0.01881 - 33000.0, 0.9, 0.0, 0.1571, 0.02509 - 33000.0, 0.9, 2.0, 0.4188, 0.04269 - 33000.0, 0.9, 4.0, 0.6806, 0.07373 - 33000.0, 0.9, 6.0, 0.9424, 0.12038 - 33000.0, 0.9, 8.0, 1.2041, 0.18477 - 33000.0, 0.9, 10.0, 1.4659, 0.26907 - 33000.0, 0.9, 12.0, 1.7277, 0.37542 - 33000.0, 0.9, 13.4, 1.9152, 0.46639 - 33000.0, 0.9, 13.4, 1.9152, 0.46639 - 33000.0, 0.9, 13.4, 1.9152, 0.46639 - 33000.0, 0.9, 13.4, 1.9152, 0.46639 - 36000.0, 0.0, -2.0, -0.0715, 0.00363 - 36000.0, 0.0, 0.0, 0.1072, 0.00384 - 36000.0, 0.0, 2.0, 0.286, 0.00621 - 36000.0, 0.0, 4.0, 0.4647, 0.01072 - 36000.0, 0.0, 6.0, 0.6434, 0.01737 - 36000.0, 0.0, 8.0, 0.8222, 0.02618 - 36000.0, 0.0, 10.0, 1.0009, 0.03713 - 36000.0, 0.0, 12.0, 1.1797, 0.05023 - 36000.0, 0.0, 14.0, 1.3584, 0.06548 - 36000.0, 0.0, 16.0, 1.5371, 0.08287 - 36000.0, 0.0, 18.0, 1.7159, 0.10241 - 36000.0, 0.0, 20.0, 1.8946, 0.1241 - 36000.0, 0.2, -2.0, -0.0724, 0.02114 - 36000.0, 0.2, 0.0, 0.1086, 0.0214 - 36000.0, 0.2, 2.0, 0.2896, 0.02433 - 36000.0, 0.2, 4.0, 0.4706, 0.02991 - 36000.0, 0.2, 6.0, 0.6517, 0.03816 - 36000.0, 0.2, 8.0, 0.8327, 0.04906 - 36000.0, 0.2, 10.0, 1.0137, 0.06262 - 36000.0, 0.2, 12.0, 1.1947, 0.07884 - 36000.0, 0.2, 14.0, 1.3757, 0.09772 - 36000.0, 0.2, 16.0, 1.5568, 0.11926 - 36000.0, 0.2, 18.0, 1.7378, 0.14346 - 36000.0, 0.2, 20.0, 1.9188, 0.17032 - 36000.0, 0.4, -2.0, -0.0754, 0.01922 - 36000.0, 0.4, 0.0, 0.1131, 0.01951 - 36000.0, 0.4, 2.0, 0.3016, 0.02262 - 36000.0, 0.4, 4.0, 0.4901, 0.02855 - 36000.0, 0.4, 6.0, 0.6786, 0.03731 - 36000.0, 0.4, 8.0, 0.867, 0.0489 - 36000.0, 0.4, 10.0, 1.0555, 0.06332 - 36000.0, 0.4, 12.0, 1.244, 0.08056 - 36000.0, 0.4, 14.0, 1.4325, 0.10063 - 36000.0, 0.4, 16.0, 1.621, 0.12352 - 36000.0, 0.4, 18.0, 1.8095, 0.14924 - 36000.0, 0.4, 19.8, 1.982, 0.17526 - 36000.0, 0.5, -2.0, -0.0779, 0.01861 - 36000.0, 0.5, 0.0, 0.1169, 0.01891 - 36000.0, 0.5, 2.0, 0.3117, 0.02221 - 36000.0, 0.5, 4.0, 0.5065, 0.0285 - 36000.0, 0.5, 6.0, 0.7013, 0.0378 - 36000.0, 0.5, 8.0, 0.8961, 0.05009 - 36000.0, 0.5, 10.0, 1.0909, 0.06539 - 36000.0, 0.5, 12.0, 1.2857, 0.08368 - 36000.0, 0.5, 14.0, 1.4806, 0.10497 - 36000.0, 0.5, 16.0, 1.6754, 0.12926 - 36000.0, 0.5, 18.0, 1.8702, 0.15654 - 36000.0, 0.5, 19.1, 1.976, 0.17262 - 36000.0, 0.6, -2.0, -0.0814, 0.01809 - 36000.0, 0.6, 0.0, 0.1221, 0.01842 - 36000.0, 0.6, 2.0, 0.3257, 0.022 - 36000.0, 0.6, 4.0, 0.5293, 0.02883 - 36000.0, 0.6, 6.0, 0.7329, 0.03892 - 36000.0, 0.6, 8.0, 0.9365, 0.05227 - 36000.0, 0.6, 10.0, 1.1401, 0.06887 - 36000.0, 0.6, 12.0, 1.3436, 0.08872 - 36000.0, 0.6, 14.0, 1.5472, 0.11183 - 36000.0, 0.6, 16.0, 1.7508, 0.1382 - 36000.0, 0.6, 18.0, 1.9544, 0.16788 - 36000.0, 0.6, 18.1, 1.9677, 0.16995 - 36000.0, 0.7, -2.0, -0.0863, 0.01765 - 36000.0, 0.7, 0.0, 0.1295, 0.01801 - 36000.0, 0.7, 2.0, 0.3454, 0.02201 - 36000.0, 0.7, 4.0, 0.5613, 0.02965 - 36000.0, 0.7, 6.0, 0.7771, 0.04094 - 36000.0, 0.7, 8.0, 0.993, 0.05586 - 36000.0, 0.7, 10.0, 1.2089, 0.07457 - 36000.0, 0.7, 12.0, 1.4247, 0.09801 - 36000.0, 0.7, 14.0, 1.6406, 0.12739 - 36000.0, 0.7, 16.0, 1.8565, 0.16392 - 36000.0, 0.7, 16.9, 1.9562, 0.18355 - 36000.0, 0.7, 16.9, 1.9562, 0.18355 - 36000.0, 0.75, -2.0, -0.0896, 0.01744 - 36000.0, 0.75, 0.0, 0.1343, 0.01783 - 36000.0, 0.75, 2.0, 0.3582, 0.02213 - 36000.0, 0.75, 4.0, 0.5822, 0.03033 - 36000.0, 0.75, 6.0, 0.8061, 0.04257 - 36000.0, 0.75, 8.0, 1.03, 0.05986 - 36000.0, 0.75, 10.0, 1.2539, 0.08354 - 36000.0, 0.75, 12.0, 1.4778, 0.11496 - 36000.0, 0.75, 14.0, 1.7017, 0.15547 - 36000.0, 0.75, 16.0, 1.9256, 0.2064 - 36000.0, 0.75, 16.2, 1.9488, 0.21234 - 36000.0, 0.75, 16.2, 1.9488, 0.21234 - 36000.0, 0.8, -2.0, -0.0935, 0.01725 - 36000.0, 0.8, 0.0, 0.1402, 0.01768 - 36000.0, 0.8, 2.0, 0.374, 0.02242 - 36000.0, 0.8, 4.0, 0.6077, 0.03243 - 36000.0, 0.8, 6.0, 0.8414, 0.04923 - 36000.0, 0.8, 8.0, 1.0751, 0.07435 - 36000.0, 0.8, 10.0, 1.3089, 0.10932 - 36000.0, 0.8, 12.0, 1.5426, 0.15567 - 36000.0, 0.8, 14.0, 1.7763, 0.21493 - 36000.0, 0.8, 15.4, 1.9399, 0.26492 - 36000.0, 0.8, 15.4, 1.9399, 0.26492 - 36000.0, 0.8, 15.4, 1.9399, 0.26492 - 36000.0, 0.85, -2.0, -0.0984, 0.01709 - 36000.0, 0.85, 0.0, 0.1476, 0.01824 - 36000.0, 0.85, 2.0, 0.3936, 0.02644 - 36000.0, 0.85, 4.0, 0.6396, 0.04347 - 36000.0, 0.85, 6.0, 0.8855, 0.07113 - 36000.0, 0.85, 8.0, 1.1315, 0.11119 - 36000.0, 0.85, 10.0, 1.3775, 0.16543 - 36000.0, 0.85, 12.0, 1.6235, 0.23565 - 36000.0, 0.85, 14.0, 1.8695, 0.32362 - 36000.0, 0.85, 14.5, 1.929, 0.34777 - 36000.0, 0.85, 14.5, 1.929, 0.34777 - 36000.0, 0.85, 14.5, 1.929, 0.34777 - 36000.0, 0.9, -2.0, -0.1047, 0.019 - 36000.0, 0.9, 0.0, 0.1571, 0.02529 - 36000.0, 0.9, 2.0, 0.4188, 0.04289 - 36000.0, 0.9, 4.0, 0.6806, 0.07396 - 36000.0, 0.9, 6.0, 0.9424, 0.12064 - 36000.0, 0.9, 8.0, 1.2041, 0.18508 - 36000.0, 0.9, 10.0, 1.4659, 0.26943 - 36000.0, 0.9, 12.0, 1.7277, 0.37585 - 36000.0, 0.9, 13.4, 1.9152, 0.46687 - 36000.0, 0.9, 13.4, 1.9152, 0.46687 - 36000.0, 0.9, 13.4, 1.9152, 0.46687 - 36000.0, 0.9, 13.4, 1.9152, 0.46687 - 38000.0, 0.0, -2.0, -0.0715, 0.00363 - 38000.0, 0.0, 0.0, 0.1072, 0.00384 - 38000.0, 0.0, 2.0, 0.286, 0.00621 - 38000.0, 0.0, 4.0, 0.4647, 0.01072 - 38000.0, 0.0, 6.0, 0.6434, 0.01737 - 38000.0, 0.0, 8.0, 0.8222, 0.02618 - 38000.0, 0.0, 10.0, 1.0009, 0.03713 - 38000.0, 0.0, 12.0, 1.1797, 0.05023 - 38000.0, 0.0, 14.0, 1.3584, 0.06548 - 38000.0, 0.0, 16.0, 1.5371, 0.08287 - 38000.0, 0.0, 18.0, 1.7159, 0.10241 - 38000.0, 0.0, 20.0, 1.8946, 0.1241 - 38000.0, 0.2, -2.0, -0.0724, 0.0214 - 38000.0, 0.2, 0.0, 0.1086, 0.02166 - 38000.0, 0.2, 2.0, 0.2896, 0.0246 - 38000.0, 0.2, 4.0, 0.4706, 0.0302 - 38000.0, 0.2, 6.0, 0.6517, 0.03846 - 38000.0, 0.2, 8.0, 0.8327, 0.04939 - 38000.0, 0.2, 10.0, 1.0137, 0.06299 - 38000.0, 0.2, 12.0, 1.1947, 0.07925 - 38000.0, 0.2, 14.0, 1.3757, 0.09818 - 38000.0, 0.2, 16.0, 1.5568, 0.11977 - 38000.0, 0.2, 18.0, 1.7378, 0.14404 - 38000.0, 0.2, 20.0, 1.9188, 0.17096 - 38000.0, 0.4, -2.0, -0.0754, 0.01945 - 38000.0, 0.4, 0.0, 0.1131, 0.01973 - 38000.0, 0.4, 2.0, 0.3016, 0.02285 - 38000.0, 0.4, 4.0, 0.4901, 0.02879 - 38000.0, 0.4, 6.0, 0.6786, 0.03758 - 38000.0, 0.4, 8.0, 0.867, 0.04919 - 38000.0, 0.4, 10.0, 1.0555, 0.06364 - 38000.0, 0.4, 12.0, 1.244, 0.08092 - 38000.0, 0.4, 14.0, 1.4325, 0.10103 - 38000.0, 0.4, 16.0, 1.621, 0.12397 - 38000.0, 0.4, 18.0, 1.8095, 0.14975 - 38000.0, 0.4, 19.8, 1.982, 0.17583 - 38000.0, 0.5, -2.0, -0.0779, 0.01882 - 38000.0, 0.5, 0.0, 0.1169, 0.01912 - 38000.0, 0.5, 2.0, 0.3117, 0.02242 - 38000.0, 0.5, 4.0, 0.5065, 0.02874 - 38000.0, 0.5, 6.0, 0.7013, 0.03805 - 38000.0, 0.5, 8.0, 0.8961, 0.05037 - 38000.0, 0.5, 10.0, 1.0909, 0.0657 - 38000.0, 0.5, 12.0, 1.2857, 0.08403 - 38000.0, 0.5, 14.0, 1.4806, 0.10536 - 38000.0, 0.5, 16.0, 1.6754, 0.1297 - 38000.0, 0.5, 18.0, 1.8702, 0.15704 - 38000.0, 0.5, 19.1, 1.976, 0.17315 - 38000.0, 0.6, -2.0, -0.0814, 0.01829 - 38000.0, 0.6, 0.0, 0.1221, 0.01862 - 38000.0, 0.6, 2.0, 0.3257, 0.02221 - 38000.0, 0.6, 4.0, 0.5293, 0.02906 - 38000.0, 0.6, 6.0, 0.7329, 0.03917 - 38000.0, 0.6, 8.0, 0.9365, 0.05254 - 38000.0, 0.6, 10.0, 1.1401, 0.06917 - 38000.0, 0.6, 12.0, 1.3436, 0.08907 - 38000.0, 0.6, 14.0, 1.5472, 0.11222 - 38000.0, 0.6, 16.0, 1.7508, 0.13864 - 38000.0, 0.6, 18.0, 1.9544, 0.16838 - 38000.0, 0.6, 18.1, 1.9677, 0.17046 - 38000.0, 0.7, -2.0, -0.0863, 0.01784 - 38000.0, 0.7, 0.0, 0.1295, 0.0182 - 38000.0, 0.7, 2.0, 0.3454, 0.02221 - 38000.0, 0.7, 4.0, 0.5613, 0.02987 - 38000.0, 0.7, 6.0, 0.7771, 0.04117 - 38000.0, 0.7, 8.0, 0.993, 0.05612 - 38000.0, 0.7, 10.0, 1.2089, 0.07487 - 38000.0, 0.7, 12.0, 1.4247, 0.09836 - 38000.0, 0.7, 14.0, 1.6406, 0.12779 - 38000.0, 0.7, 16.0, 1.8565, 0.16437 - 38000.0, 0.7, 16.9, 1.9562, 0.18403 - 38000.0, 0.7, 16.9, 1.9562, 0.18403 - 38000.0, 0.75, -2.0, -0.0896, 0.01763 - 38000.0, 0.75, 0.0, 0.1343, 0.01802 - 38000.0, 0.75, 2.0, 0.3582, 0.02232 - 38000.0, 0.75, 4.0, 0.5822, 0.03054 - 38000.0, 0.75, 6.0, 0.8061, 0.04281 - 38000.0, 0.75, 8.0, 1.03, 0.06013 - 38000.0, 0.75, 10.0, 1.2539, 0.08385 - 38000.0, 0.75, 12.0, 1.4778, 0.11531 - 38000.0, 0.75, 14.0, 1.7017, 0.15587 - 38000.0, 0.75, 16.0, 1.9256, 0.20686 - 38000.0, 0.75, 16.2, 1.9488, 0.21281 - 38000.0, 0.75, 16.2, 1.9488, 0.21281 - 38000.0, 0.8, -2.0, -0.0935, 0.01744 - 38000.0, 0.8, 0.0, 0.1402, 0.01786 - 38000.0, 0.8, 2.0, 0.374, 0.02261 - 38000.0, 0.8, 4.0, 0.6077, 0.03264 - 38000.0, 0.8, 6.0, 0.8414, 0.04947 - 38000.0, 0.8, 8.0, 1.0751, 0.07462 - 38000.0, 0.8, 10.0, 1.3089, 0.10963 - 38000.0, 0.8, 12.0, 1.5426, 0.15603 - 38000.0, 0.8, 14.0, 1.7763, 0.21535 - 38000.0, 0.8, 15.4, 1.9399, 0.26538 - 38000.0, 0.8, 15.4, 1.9399, 0.26538 - 38000.0, 0.8, 15.4, 1.9399, 0.26538 - 38000.0, 0.85, -2.0, -0.0984, 0.01727 - 38000.0, 0.85, 0.0, 0.1476, 0.01842 - 38000.0, 0.85, 2.0, 0.3936, 0.02663 - 38000.0, 0.85, 4.0, 0.6396, 0.04368 - 38000.0, 0.85, 6.0, 0.8855, 0.07137 - 38000.0, 0.85, 8.0, 1.1315, 0.11146 - 38000.0, 0.85, 10.0, 1.3775, 0.16575 - 38000.0, 0.85, 12.0, 1.6235, 0.23602 - 38000.0, 0.85, 14.0, 1.8695, 0.32405 - 38000.0, 0.85, 14.5, 1.929, 0.34822 - 38000.0, 0.85, 14.5, 1.929, 0.34822 - 38000.0, 0.85, 14.5, 1.929, 0.34822 - 38000.0, 0.9, -2.0, -0.1047, 0.01918 - 38000.0, 0.9, 0.0, 0.1571, 0.02547 - 38000.0, 0.9, 2.0, 0.4188, 0.04308 - 38000.0, 0.9, 4.0, 0.6806, 0.07417 - 38000.0, 0.9, 6.0, 0.9424, 0.12088 - 38000.0, 0.9, 8.0, 1.2041, 0.18536 - 38000.0, 0.9, 10.0, 1.4659, 0.26976 - 38000.0, 0.9, 12.0, 1.7277, 0.37624 - 38000.0, 0.9, 13.4, 1.9152, 0.46731 - 38000.0, 0.9, 13.4, 1.9152, 0.46731 - 38000.0, 0.9, 13.4, 1.9152, 0.46731 - 38000.0, 0.9, 13.4, 1.9152, 0.46731 - 42000.0, 0.0, -2.0, -0.0715, 0.00363 - 42000.0, 0.0, 0.0, 0.1072, 0.00384 - 42000.0, 0.0, 2.0, 0.286, 0.00621 - 42000.0, 0.0, 4.0, 0.4647, 0.01072 - 42000.0, 0.0, 6.0, 0.6434, 0.01737 - 42000.0, 0.0, 8.0, 0.8222, 0.02618 - 42000.0, 0.0, 10.0, 1.0009, 0.03713 - 42000.0, 0.0, 12.0, 1.1797, 0.05023 - 42000.0, 0.0, 14.0, 1.3584, 0.06548 - 42000.0, 0.0, 16.0, 1.5371, 0.08287 - 42000.0, 0.0, 18.0, 1.7159, 0.10241 - 42000.0, 0.0, 20.0, 1.8946, 0.1241 - 42000.0, 0.2, -2.0, -0.0724, 0.02194 - 42000.0, 0.2, 0.0, 0.1086, 0.02221 - 42000.0, 0.2, 2.0, 0.2896, 0.02516 - 42000.0, 0.2, 4.0, 0.4706, 0.03079 - 42000.0, 0.2, 6.0, 0.6517, 0.0391 - 42000.0, 0.2, 8.0, 0.8327, 0.05009 - 42000.0, 0.2, 10.0, 1.0137, 0.06376 - 42000.0, 0.2, 12.0, 1.1947, 0.08011 - 42000.0, 0.2, 14.0, 1.3757, 0.09914 - 42000.0, 0.2, 16.0, 1.5568, 0.12085 - 42000.0, 0.2, 18.0, 1.7378, 0.14524 - 42000.0, 0.2, 20.0, 1.9188, 0.17231 - 42000.0, 0.4, -2.0, -0.0754, 0.01991 - 42000.0, 0.4, 0.0, 0.1131, 0.0202 - 42000.0, 0.4, 2.0, 0.3016, 0.02333 - 42000.0, 0.4, 4.0, 0.4901, 0.0293 - 42000.0, 0.4, 6.0, 0.6786, 0.03812 - 42000.0, 0.4, 8.0, 0.867, 0.04979 - 42000.0, 0.4, 10.0, 1.0555, 0.06431 - 42000.0, 0.4, 12.0, 1.244, 0.08167 - 42000.0, 0.4, 14.0, 1.4325, 0.10187 - 42000.0, 0.4, 16.0, 1.621, 0.12493 - 42000.0, 0.4, 18.0, 1.8095, 0.15082 - 42000.0, 0.4, 19.8, 1.982, 0.17702 - 42000.0, 0.5, -2.0, -0.0779, 0.01926 - 42000.0, 0.5, 0.0, 0.1169, 0.01956 - 42000.0, 0.5, 2.0, 0.3117, 0.02288 - 42000.0, 0.5, 4.0, 0.5065, 0.02922 - 42000.0, 0.5, 6.0, 0.7013, 0.03858 - 42000.0, 0.5, 8.0, 0.8961, 0.05095 - 42000.0, 0.5, 10.0, 1.0909, 0.06634 - 42000.0, 0.5, 12.0, 1.2857, 0.08475 - 42000.0, 0.5, 14.0, 1.4806, 0.10618 - 42000.0, 0.5, 16.0, 1.6754, 0.13063 - 42000.0, 0.5, 18.0, 1.8702, 0.1581 - 42000.0, 0.5, 19.1, 1.976, 0.17428 - 42000.0, 0.6, -2.0, -0.0814, 0.01871 - 42000.0, 0.6, 0.0, 0.1221, 0.01904 - 42000.0, 0.6, 2.0, 0.3257, 0.02264 - 42000.0, 0.6, 4.0, 0.5293, 0.02952 - 42000.0, 0.6, 6.0, 0.7329, 0.03968 - 42000.0, 0.6, 8.0, 0.9365, 0.0531 - 42000.0, 0.6, 10.0, 1.1401, 0.06981 - 42000.0, 0.6, 12.0, 1.3436, 0.08979 - 42000.0, 0.6, 14.0, 1.5472, 0.11304 - 42000.0, 0.6, 16.0, 1.7508, 0.13957 - 42000.0, 0.6, 18.0, 1.9544, 0.16944 - 42000.0, 0.6, 18.1, 1.9677, 0.17152 - 42000.0, 0.7, -2.0, -0.0863, 0.01824 - 42000.0, 0.7, 0.0, 0.1295, 0.0186 - 42000.0, 0.7, 2.0, 0.3454, 0.02263 - 42000.0, 0.7, 4.0, 0.5613, 0.03032 - 42000.0, 0.7, 6.0, 0.7771, 0.04167 - 42000.0, 0.7, 8.0, 0.993, 0.05668 - 42000.0, 0.7, 10.0, 1.2089, 0.07551 - 42000.0, 0.7, 12.0, 1.4247, 0.09908 - 42000.0, 0.7, 14.0, 1.6406, 0.12862 - 42000.0, 0.7, 16.0, 1.8565, 0.16533 - 42000.0, 0.7, 16.9, 1.9562, 0.18504 - 42000.0, 0.7, 16.9, 1.9562, 0.18504 - 42000.0, 0.75, -2.0, -0.0896, 0.01802 - 42000.0, 0.75, 0.0, 0.1343, 0.01842 - 42000.0, 0.75, 2.0, 0.3582, 0.02274 - 42000.0, 0.75, 4.0, 0.5822, 0.03099 - 42000.0, 0.75, 6.0, 0.8061, 0.0433 - 42000.0, 0.75, 8.0, 1.03, 0.06069 - 42000.0, 0.75, 10.0, 1.2539, 0.08449 - 42000.0, 0.75, 12.0, 1.4778, 0.11605 - 42000.0, 0.75, 14.0, 1.7017, 0.15672 - 42000.0, 0.75, 16.0, 1.9256, 0.20784 - 42000.0, 0.75, 16.2, 1.9488, 0.2138 - 42000.0, 0.75, 16.2, 1.9488, 0.2138 - 42000.0, 0.8, -2.0, -0.0935, 0.01782 - 42000.0, 0.8, 0.0, 0.1402, 0.01825 - 42000.0, 0.8, 2.0, 0.374, 0.02302 - 42000.0, 0.8, 4.0, 0.6077, 0.03309 - 42000.0, 0.8, 6.0, 0.8414, 0.04996 - 42000.0, 0.8, 8.0, 1.0751, 0.07519 - 42000.0, 0.8, 10.0, 1.3089, 0.11028 - 42000.0, 0.8, 12.0, 1.5426, 0.15678 - 42000.0, 0.8, 14.0, 1.7763, 0.21622 - 42000.0, 0.8, 15.4, 1.9399, 0.26635 - 42000.0, 0.8, 15.4, 1.9399, 0.26635 - 42000.0, 0.8, 15.4, 1.9399, 0.26635 - 42000.0, 0.85, -2.0, -0.0984, 0.01765 - 42000.0, 0.85, 0.0, 0.1476, 0.0188 - 42000.0, 0.85, 2.0, 0.3936, 0.02703 - 42000.0, 0.85, 4.0, 0.6396, 0.04412 - 42000.0, 0.85, 6.0, 0.8855, 0.07186 - 42000.0, 0.85, 8.0, 1.1315, 0.11203 - 42000.0, 0.85, 10.0, 1.3775, 0.16642 - 42000.0, 0.85, 12.0, 1.6235, 0.2368 - 42000.0, 0.85, 14.0, 1.8695, 0.32496 - 42000.0, 0.85, 14.5, 1.929, 0.34916 - 42000.0, 0.85, 14.5, 1.929, 0.34916 - 42000.0, 0.85, 14.5, 1.929, 0.34916 - 42000.0, 0.9, -2.0, -0.1047, 0.01955 - 42000.0, 0.9, 0.0, 0.1571, 0.02584 - 42000.0, 0.9, 2.0, 0.4188, 0.04348 - 42000.0, 0.9, 4.0, 0.6806, 0.07461 - 42000.0, 0.9, 6.0, 0.9424, 0.12138 - 42000.0, 0.9, 8.0, 1.2041, 0.18595 - 42000.0, 0.9, 10.0, 1.4659, 0.27045 - 42000.0, 0.9, 12.0, 1.7277, 0.37705 - 42000.0, 0.9, 13.4, 1.9152, 0.46822 - 42000.0, 0.9, 13.4, 1.9152, 0.46822 - 42000.0, 0.9, 13.4, 1.9152, 0.46822 - 42000.0, 0.9, 13.4, 1.9152, 0.46822 diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free_reduced_alpha.txt b/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free_reduced_alpha.txt deleted file mode 100644 index e61a3fd82e..0000000000 --- a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free_reduced_alpha.txt +++ /dev/null @@ -1,1056 +0,0 @@ -# GASP-derived aerodynamics data converted from GASP_aero_free_reduced_alpha.txt -# Clean / Free Air Aerodynamics -# Copy of GASP_aero_free.txt with alpha above 10 removed -# Reference Area = 1370. sqft - -Altitude (ft), Mach, Angle of Attack (deg), CL, CD - 0.0, 0.0, -2.0, -0.0715, 0.00363 - 0.0, 0.0, 0.0, 0.1072, 0.00384 - 0.0, 0.0, 2.0, 0.286, 0.00621 - 0.0, 0.0, 4.0, 0.4647, 0.01072 - 0.0, 0.0, 6.0, 0.6434, 0.01737 - 0.0, 0.0, 8.0, 0.8222, 0.02618 - 0.0, 0.0, 10.0, 1.0009, 0.03713 - 0.0, 0.2, -2.0, -0.0724, 0.01841 - 0.0, 0.2, 0.0, 0.1086, 0.01867 - 0.0, 0.2, 2.0, 0.2896, 0.02152 - 0.0, 0.2, 4.0, 0.4706, 0.02695 - 0.0, 0.2, 6.0, 0.6517, 0.03498 - 0.0, 0.2, 8.0, 0.8327, 0.04559 - 0.0, 0.2, 10.0, 1.0137, 0.05878 - 0.0, 0.4, -2.0, -0.0754, 0.01689 - 0.0, 0.4, 0.0, 0.1131, 0.01716 - 0.0, 0.4, 2.0, 0.3016, 0.0202 - 0.0, 0.4, 4.0, 0.4901, 0.026 - 0.0, 0.4, 6.0, 0.6786, 0.03455 - 0.0, 0.4, 8.0, 0.867, 0.04587 - 0.0, 0.4, 10.0, 1.0555, 0.05995 - 0.0, 0.5, -2.0, -0.0779, 0.01639 - 0.0, 0.5, 0.0, 0.1169, 0.01668 - 0.0, 0.5, 2.0, 0.3117, 0.01991 - 0.0, 0.5, 4.0, 0.5065, 0.02607 - 0.0, 0.5, 6.0, 0.7013, 0.03515 - 0.0, 0.5, 8.0, 0.8961, 0.04717 - 0.0, 0.5, 10.0, 1.0909, 0.06212 - 0.0, 0.6, -2.0, -0.0814, 0.01598 - 0.0, 0.6, 0.0, 0.1221, 0.01629 - 0.0, 0.6, 2.0, 0.3257, 0.0198 - 0.0, 0.6, 4.0, 0.5293, 0.02648 - 0.0, 0.6, 6.0, 0.7329, 0.03636 - 0.0, 0.6, 8.0, 0.9365, 0.04941 - 0.0, 0.6, 10.0, 1.1401, 0.06566 - 0.0, 0.7, -2.0, -0.0863, 0.01561 - 0.0, 0.7, 0.0, 0.1295, 0.01597 - 0.0, 0.7, 2.0, 0.3454, 0.01989 - 0.0, 0.7, 4.0, 0.5613, 0.02737 - 0.0, 0.7, 6.0, 0.7771, 0.03842 - 0.0, 0.7, 8.0, 0.993, 0.05303 - 0.0, 0.7, 10.0, 1.2089, 0.07136 - 0.0, 0.75, -2.0, -0.0896, 0.01545 - 0.0, 0.75, 0.0, 0.1343, 0.01583 - 0.0, 0.75, 2.0, 0.3582, 0.02004 - 0.0, 0.75, 4.0, 0.5822, 0.02807 - 0.0, 0.75, 6.0, 0.8061, 0.04007 - 0.0, 0.75, 8.0, 1.03, 0.05703 - 0.0, 0.75, 10.0, 1.2539, 0.08031 - 0.0, 0.8, -2.0, -0.0935, 0.0153 - 0.0, 0.8, 0.0, 0.1402, 0.01571 - 0.0, 0.8, 2.0, 0.374, 0.02036 - 0.0, 0.8, 4.0, 0.6077, 0.0302 - 0.0, 0.8, 6.0, 0.8414, 0.04673 - 0.0, 0.8, 8.0, 1.0751, 0.0715 - 0.0, 0.8, 10.0, 1.3089, 0.10604 - 0.0, 0.85, -2.0, -0.0984, 0.01517 - 0.0, 0.85, 0.0, 0.1476, 0.01631 - 0.0, 0.85, 2.0, 0.3936, 0.02441 - 0.0, 0.85, 4.0, 0.6396, 0.04125 - 0.0, 0.85, 6.0, 0.8855, 0.06862 - 0.0, 0.85, 8.0, 1.1315, 0.1083 - 0.0, 0.85, 10.0, 1.3775, 0.16207 - 0.0, 0.9, -2.0, -0.1047, 0.01712 - 0.0, 0.9, 0.0, 0.1571, 0.02339 - 0.0, 0.9, 2.0, 0.4188, 0.04088 - 0.0, 0.9, 4.0, 0.6806, 0.07174 - 0.0, 0.9, 6.0, 0.9424, 0.11809 - 0.0, 0.9, 8.0, 1.2041, 0.18211 - 0.0, 0.9, 10.0, 1.4659, 0.26594 - 3000.0, 0.0, -2.0, -0.0715, 0.00363 - 3000.0, 0.0, 0.0, 0.1072, 0.00384 - 3000.0, 0.0, 2.0, 0.286, 0.00621 - 3000.0, 0.0, 4.0, 0.4647, 0.01072 - 3000.0, 0.0, 6.0, 0.6434, 0.01737 - 3000.0, 0.0, 8.0, 0.8222, 0.02618 - 3000.0, 0.0, 10.0, 1.0009, 0.03713 - 3000.0, 0.2, -2.0, -0.0724, 0.01859 - 3000.0, 0.2, 0.0, 0.1086, 0.01885 - 3000.0, 0.2, 2.0, 0.2896, 0.0217 - 3000.0, 0.2, 4.0, 0.4706, 0.02715 - 3000.0, 0.2, 6.0, 0.6517, 0.03519 - 3000.0, 0.2, 8.0, 0.8327, 0.04582 - 3000.0, 0.2, 10.0, 1.0137, 0.05904 - 3000.0, 0.4, -2.0, -0.0754, 0.01704 - 3000.0, 0.4, 0.0, 0.1131, 0.01732 - 3000.0, 0.4, 2.0, 0.3016, 0.02036 - 3000.0, 0.4, 4.0, 0.4901, 0.02617 - 3000.0, 0.4, 6.0, 0.6786, 0.03474 - 3000.0, 0.4, 8.0, 0.867, 0.04607 - 3000.0, 0.4, 10.0, 1.0555, 0.06017 - 3000.0, 0.5, -2.0, -0.0779, 0.01654 - 3000.0, 0.5, 0.0, 0.1169, 0.01683 - 3000.0, 0.5, 2.0, 0.3117, 0.02006 - 3000.0, 0.5, 4.0, 0.5065, 0.02623 - 3000.0, 0.5, 6.0, 0.7013, 0.03533 - 3000.0, 0.5, 8.0, 0.8961, 0.04737 - 3000.0, 0.5, 10.0, 1.0909, 0.06234 - 3000.0, 0.6, -2.0, -0.0814, 0.01612 - 3000.0, 0.6, 0.0, 0.1221, 0.01644 - 3000.0, 0.6, 2.0, 0.3257, 0.01994 - 3000.0, 0.6, 4.0, 0.5293, 0.02664 - 3000.0, 0.6, 6.0, 0.7329, 0.03653 - 3000.0, 0.6, 8.0, 0.9365, 0.04961 - 3000.0, 0.6, 10.0, 1.1401, 0.06587 - 3000.0, 0.7, -2.0, -0.0863, 0.01575 - 3000.0, 0.7, 0.0, 0.1295, 0.01611 - 3000.0, 0.7, 2.0, 0.3454, 0.02003 - 3000.0, 0.7, 4.0, 0.5613, 0.02753 - 3000.0, 0.7, 6.0, 0.7771, 0.03859 - 3000.0, 0.7, 8.0, 0.993, 0.05322 - 3000.0, 0.7, 10.0, 1.2089, 0.07157 - 3000.0, 0.75, -2.0, -0.0896, 0.01558 - 3000.0, 0.75, 0.0, 0.1343, 0.01597 - 3000.0, 0.75, 2.0, 0.3582, 0.02018 - 3000.0, 0.75, 4.0, 0.5822, 0.02822 - 3000.0, 0.75, 6.0, 0.8061, 0.04024 - 3000.0, 0.75, 8.0, 1.03, 0.05722 - 3000.0, 0.75, 10.0, 1.2539, 0.08052 - 3000.0, 0.8, -2.0, -0.0935, 0.01543 - 3000.0, 0.8, 0.0, 0.1402, 0.01584 - 3000.0, 0.8, 2.0, 0.374, 0.0205 - 3000.0, 0.8, 4.0, 0.6077, 0.03034 - 3000.0, 0.8, 6.0, 0.8414, 0.0469 - 3000.0, 0.8, 8.0, 1.0751, 0.07169 - 3000.0, 0.8, 10.0, 1.3089, 0.10626 - 3000.0, 0.85, -2.0, -0.0984, 0.0153 - 3000.0, 0.85, 0.0, 0.1476, 0.01644 - 3000.0, 0.85, 2.0, 0.3936, 0.02454 - 3000.0, 0.85, 4.0, 0.6396, 0.0414 - 3000.0, 0.85, 6.0, 0.8855, 0.06878 - 3000.0, 0.85, 8.0, 1.1315, 0.10849 - 3000.0, 0.85, 10.0, 1.3775, 0.16229 - 3000.0, 0.9, -2.0, -0.1047, 0.01724 - 3000.0, 0.9, 0.0, 0.1571, 0.02352 - 3000.0, 0.9, 2.0, 0.4188, 0.04102 - 3000.0, 0.9, 4.0, 0.6806, 0.07188 - 3000.0, 0.9, 6.0, 0.9424, 0.11826 - 3000.0, 0.9, 8.0, 1.2041, 0.18231 - 3000.0, 0.9, 10.0, 1.4659, 0.26617 - 6000.0, 0.0, -2.0, -0.0715, 0.00363 - 6000.0, 0.0, 0.0, 0.1072, 0.00384 - 6000.0, 0.0, 2.0, 0.286, 0.00621 - 6000.0, 0.0, 4.0, 0.4647, 0.01072 - 6000.0, 0.0, 6.0, 0.6434, 0.01737 - 6000.0, 0.0, 8.0, 0.8222, 0.02618 - 6000.0, 0.0, 10.0, 1.0009, 0.03713 - 6000.0, 0.2, -2.0, -0.0724, 0.01878 - 6000.0, 0.2, 0.0, 0.1086, 0.01904 - 6000.0, 0.2, 2.0, 0.2896, 0.0219 - 6000.0, 0.2, 4.0, 0.4706, 0.02735 - 6000.0, 0.2, 6.0, 0.6517, 0.0354 - 6000.0, 0.2, 8.0, 0.8327, 0.04605 - 6000.0, 0.2, 10.0, 1.0137, 0.0593 - 6000.0, 0.4, -2.0, -0.0754, 0.0172 - 6000.0, 0.4, 0.0, 0.1131, 0.01748 - 6000.0, 0.4, 2.0, 0.3016, 0.02053 - 6000.0, 0.4, 4.0, 0.4901, 0.02634 - 6000.0, 0.4, 6.0, 0.6786, 0.03493 - 6000.0, 0.4, 8.0, 0.867, 0.04628 - 6000.0, 0.4, 10.0, 1.0555, 0.0604 - 6000.0, 0.5, -2.0, -0.0779, 0.01669 - 6000.0, 0.5, 0.0, 0.1169, 0.01699 - 6000.0, 0.5, 2.0, 0.3117, 0.02022 - 6000.0, 0.5, 4.0, 0.5065, 0.0264 - 6000.0, 0.5, 6.0, 0.7013, 0.03551 - 6000.0, 0.5, 8.0, 0.8961, 0.04757 - 6000.0, 0.5, 10.0, 1.0909, 0.06256 - 6000.0, 0.6, -2.0, -0.0814, 0.01626 - 6000.0, 0.6, 0.0, 0.1221, 0.01658 - 6000.0, 0.6, 2.0, 0.3257, 0.0201 - 6000.0, 0.6, 4.0, 0.5293, 0.0268 - 6000.0, 0.6, 6.0, 0.7329, 0.03671 - 6000.0, 0.6, 8.0, 0.9365, 0.0498 - 6000.0, 0.6, 10.0, 1.1401, 0.06609 - 6000.0, 0.7, -2.0, -0.0863, 0.01589 - 6000.0, 0.7, 0.0, 0.1295, 0.01625 - 6000.0, 0.7, 2.0, 0.3454, 0.02018 - 6000.0, 0.7, 4.0, 0.5613, 0.02768 - 6000.0, 0.7, 6.0, 0.7771, 0.03876 - 6000.0, 0.7, 8.0, 0.993, 0.05342 - 6000.0, 0.7, 10.0, 1.2089, 0.07179 - 6000.0, 0.75, -2.0, -0.0896, 0.01572 - 6000.0, 0.75, 0.0, 0.1343, 0.0161 - 6000.0, 0.75, 2.0, 0.3582, 0.02032 - 6000.0, 0.75, 4.0, 0.5822, 0.02838 - 6000.0, 0.75, 6.0, 0.8061, 0.04041 - 6000.0, 0.75, 8.0, 1.03, 0.05742 - 6000.0, 0.75, 10.0, 1.2539, 0.08075 - 6000.0, 0.8, -2.0, -0.0935, 0.01556 - 6000.0, 0.8, 0.0, 0.1402, 0.01598 - 6000.0, 0.8, 2.0, 0.374, 0.02064 - 6000.0, 0.8, 4.0, 0.6077, 0.0305 - 6000.0, 0.8, 6.0, 0.8414, 0.04707 - 6000.0, 0.8, 8.0, 1.0751, 0.07189 - 6000.0, 0.8, 10.0, 1.3089, 0.10649 - 6000.0, 0.85, -2.0, -0.0984, 0.01543 - 6000.0, 0.85, 0.0, 0.1476, 0.01657 - 6000.0, 0.85, 2.0, 0.3936, 0.02468 - 6000.0, 0.85, 4.0, 0.6396, 0.04155 - 6000.0, 0.85, 6.0, 0.8855, 0.06896 - 6000.0, 0.85, 8.0, 1.1315, 0.10869 - 6000.0, 0.85, 10.0, 1.3775, 0.16253 - 6000.0, 0.9, -2.0, -0.1047, 0.01737 - 6000.0, 0.9, 0.0, 0.1571, 0.02365 - 6000.0, 0.9, 2.0, 0.4188, 0.04116 - 6000.0, 0.9, 4.0, 0.6806, 0.07204 - 6000.0, 0.9, 6.0, 0.9424, 0.11844 - 6000.0, 0.9, 8.0, 1.2041, 0.18252 - 6000.0, 0.9, 10.0, 1.4659, 0.26642 - 9000.0, 0.0, -2.0, -0.0715, 0.00363 - 9000.0, 0.0, 0.0, 0.1072, 0.00384 - 9000.0, 0.0, 2.0, 0.286, 0.00621 - 9000.0, 0.0, 4.0, 0.4647, 0.01072 - 9000.0, 0.0, 6.0, 0.6434, 0.01737 - 9000.0, 0.0, 8.0, 0.8222, 0.02618 - 9000.0, 0.0, 10.0, 1.0009, 0.03713 - 9000.0, 0.2, -2.0, -0.0724, 0.01898 - 9000.0, 0.2, 0.0, 0.1086, 0.01924 - 9000.0, 0.2, 2.0, 0.2896, 0.0221 - 9000.0, 0.2, 4.0, 0.4706, 0.02756 - 9000.0, 0.2, 6.0, 0.6517, 0.03563 - 9000.0, 0.2, 8.0, 0.8327, 0.0463 - 9000.0, 0.2, 10.0, 1.0137, 0.05958 - 9000.0, 0.4, -2.0, -0.0754, 0.01737 - 9000.0, 0.4, 0.0, 0.1131, 0.01765 - 9000.0, 0.4, 2.0, 0.3016, 0.0207 - 9000.0, 0.4, 4.0, 0.4901, 0.02653 - 9000.0, 0.4, 6.0, 0.6786, 0.03512 - 9000.0, 0.4, 8.0, 0.867, 0.0465 - 9000.0, 0.4, 10.0, 1.0555, 0.06064 - 9000.0, 0.5, -2.0, -0.0779, 0.01685 - 9000.0, 0.5, 0.0, 0.1169, 0.01715 - 9000.0, 0.5, 2.0, 0.3117, 0.02039 - 9000.0, 0.5, 4.0, 0.5065, 0.02657 - 9000.0, 0.5, 6.0, 0.7013, 0.0357 - 9000.0, 0.5, 8.0, 0.8961, 0.04778 - 9000.0, 0.5, 10.0, 1.0909, 0.0628 - 9000.0, 0.6, -2.0, -0.0814, 0.01641 - 9000.0, 0.6, 0.0, 0.1221, 0.01673 - 9000.0, 0.6, 2.0, 0.3257, 0.02025 - 9000.0, 0.6, 4.0, 0.5293, 0.02697 - 9000.0, 0.6, 6.0, 0.7329, 0.03689 - 9000.0, 0.6, 8.0, 0.9365, 0.05001 - 9000.0, 0.6, 10.0, 1.1401, 0.06632 - 9000.0, 0.7, -2.0, -0.0863, 0.01603 - 9000.0, 0.7, 0.0, 0.1295, 0.01639 - 9000.0, 0.7, 2.0, 0.3454, 0.02033 - 9000.0, 0.7, 4.0, 0.5613, 0.02785 - 9000.0, 0.7, 6.0, 0.7771, 0.03894 - 9000.0, 0.7, 8.0, 0.993, 0.05362 - 9000.0, 0.7, 10.0, 1.2089, 0.07202 - 9000.0, 0.75, -2.0, -0.0896, 0.01586 - 9000.0, 0.75, 0.0, 0.1343, 0.01625 - 9000.0, 0.75, 2.0, 0.3582, 0.02047 - 9000.0, 0.75, 4.0, 0.5822, 0.02854 - 9000.0, 0.75, 6.0, 0.8061, 0.04059 - 9000.0, 0.75, 8.0, 1.03, 0.05762 - 9000.0, 0.75, 10.0, 1.2539, 0.08098 - 9000.0, 0.8, -2.0, -0.0935, 0.0157 - 9000.0, 0.8, 0.0, 0.1402, 0.01612 - 9000.0, 0.8, 2.0, 0.374, 0.02079 - 9000.0, 0.8, 4.0, 0.6077, 0.03066 - 9000.0, 0.8, 6.0, 0.8414, 0.04725 - 9000.0, 0.8, 8.0, 1.0751, 0.0721 - 9000.0, 0.8, 10.0, 1.3089, 0.10672 - 9000.0, 0.85, -2.0, -0.0984, 0.01557 - 9000.0, 0.85, 0.0, 0.1476, 0.01671 - 9000.0, 0.85, 2.0, 0.3936, 0.02483 - 9000.0, 0.85, 4.0, 0.6396, 0.04171 - 9000.0, 0.85, 6.0, 0.8855, 0.06914 - 9000.0, 0.85, 8.0, 1.1315, 0.1089 - 9000.0, 0.85, 10.0, 1.3775, 0.16277 - 9000.0, 0.9, -2.0, -0.1047, 0.01751 - 9000.0, 0.9, 0.0, 0.1571, 0.02379 - 9000.0, 0.9, 2.0, 0.4188, 0.0413 - 9000.0, 0.9, 4.0, 0.6806, 0.0722 - 9000.0, 0.9, 6.0, 0.9424, 0.11862 - 9000.0, 0.9, 8.0, 1.2041, 0.18273 - 9000.0, 0.9, 10.0, 1.4659, 0.26667 - 12000.0, 0.0, -2.0, -0.0715, 0.00363 - 12000.0, 0.0, 0.0, 0.1072, 0.00384 - 12000.0, 0.0, 2.0, 0.286, 0.00621 - 12000.0, 0.0, 4.0, 0.4647, 0.01072 - 12000.0, 0.0, 6.0, 0.6434, 0.01737 - 12000.0, 0.0, 8.0, 0.8222, 0.02618 - 12000.0, 0.0, 10.0, 1.0009, 0.03713 - 12000.0, 0.2, -2.0, -0.0724, 0.01918 - 12000.0, 0.2, 0.0, 0.1086, 0.01944 - 12000.0, 0.2, 2.0, 0.2896, 0.02231 - 12000.0, 0.2, 4.0, 0.4706, 0.02778 - 12000.0, 0.2, 6.0, 0.6517, 0.03587 - 12000.0, 0.2, 8.0, 0.8327, 0.04656 - 12000.0, 0.2, 10.0, 1.0137, 0.05986 - 12000.0, 0.4, -2.0, -0.0754, 0.01755 - 12000.0, 0.4, 0.0, 0.1131, 0.01782 - 12000.0, 0.4, 2.0, 0.3016, 0.02088 - 12000.0, 0.4, 4.0, 0.4901, 0.02672 - 12000.0, 0.4, 6.0, 0.6786, 0.03533 - 12000.0, 0.4, 8.0, 0.867, 0.04672 - 12000.0, 0.4, 10.0, 1.0555, 0.06089 - 12000.0, 0.5, -2.0, -0.0779, 0.01702 - 12000.0, 0.5, 0.0, 0.1169, 0.01731 - 12000.0, 0.5, 2.0, 0.3117, 0.02056 - 12000.0, 0.5, 4.0, 0.5065, 0.02675 - 12000.0, 0.5, 6.0, 0.7013, 0.0359 - 12000.0, 0.5, 8.0, 0.8961, 0.04799 - 12000.0, 0.5, 10.0, 1.0909, 0.06304 - 12000.0, 0.6, -2.0, -0.0814, 0.01657 - 12000.0, 0.6, 0.0, 0.1221, 0.01689 - 12000.0, 0.6, 2.0, 0.3257, 0.02042 - 12000.0, 0.6, 4.0, 0.5293, 0.02715 - 12000.0, 0.6, 6.0, 0.7329, 0.03708 - 12000.0, 0.6, 8.0, 0.9365, 0.05022 - 12000.0, 0.6, 10.0, 1.1401, 0.06656 - 12000.0, 0.7, -2.0, -0.0863, 0.01619 - 12000.0, 0.7, 0.0, 0.1295, 0.01654 - 12000.0, 0.7, 2.0, 0.3454, 0.02049 - 12000.0, 0.7, 4.0, 0.5613, 0.02802 - 12000.0, 0.7, 6.0, 0.7771, 0.03913 - 12000.0, 0.7, 8.0, 0.993, 0.05383 - 12000.0, 0.7, 10.0, 1.2089, 0.07226 - 12000.0, 0.75, -2.0, -0.0896, 0.01601 - 12000.0, 0.75, 0.0, 0.1343, 0.0164 - 12000.0, 0.75, 2.0, 0.3582, 0.02063 - 12000.0, 0.75, 4.0, 0.5822, 0.02871 - 12000.0, 0.75, 6.0, 0.8061, 0.04077 - 12000.0, 0.75, 8.0, 1.03, 0.05783 - 12000.0, 0.75, 10.0, 1.2539, 0.08122 - 12000.0, 0.8, -2.0, -0.0935, 0.01585 - 12000.0, 0.8, 0.0, 0.1402, 0.01627 - 12000.0, 0.8, 2.0, 0.374, 0.02094 - 12000.0, 0.8, 4.0, 0.6077, 0.03083 - 12000.0, 0.8, 6.0, 0.8414, 0.04744 - 12000.0, 0.8, 8.0, 1.0751, 0.07231 - 12000.0, 0.8, 10.0, 1.3089, 0.10697 - 12000.0, 0.85, -2.0, -0.0984, 0.01571 - 12000.0, 0.85, 0.0, 0.1476, 0.01685 - 12000.0, 0.85, 2.0, 0.3936, 0.02498 - 12000.0, 0.85, 4.0, 0.6396, 0.04188 - 12000.0, 0.85, 6.0, 0.8855, 0.06933 - 12000.0, 0.85, 8.0, 1.1315, 0.10911 - 12000.0, 0.85, 10.0, 1.3775, 0.16302 - 12000.0, 0.9, -2.0, -0.1047, 0.01765 - 12000.0, 0.9, 0.0, 0.1571, 0.02393 - 12000.0, 0.9, 2.0, 0.4188, 0.04145 - 12000.0, 0.9, 4.0, 0.6806, 0.07236 - 12000.0, 0.9, 6.0, 0.9424, 0.11881 - 12000.0, 0.9, 8.0, 1.2041, 0.18295 - 12000.0, 0.9, 10.0, 1.4659, 0.26693 - 15000.0, 0.0, -2.0, -0.0715, 0.00363 - 15000.0, 0.0, 0.0, 0.1072, 0.00384 - 15000.0, 0.0, 2.0, 0.286, 0.00621 - 15000.0, 0.0, 4.0, 0.4647, 0.01072 - 15000.0, 0.0, 6.0, 0.6434, 0.01737 - 15000.0, 0.0, 8.0, 0.8222, 0.02618 - 15000.0, 0.0, 10.0, 1.0009, 0.03713 - 15000.0, 0.2, -2.0, -0.0724, 0.01939 - 15000.0, 0.2, 0.0, 0.1086, 0.01965 - 15000.0, 0.2, 2.0, 0.2896, 0.02252 - 15000.0, 0.2, 4.0, 0.4706, 0.02801 - 15000.0, 0.2, 6.0, 0.6517, 0.03611 - 15000.0, 0.2, 8.0, 0.8327, 0.04683 - 15000.0, 0.2, 10.0, 1.0137, 0.06016 - 15000.0, 0.4, -2.0, -0.0754, 0.01773 - 15000.0, 0.4, 0.0, 0.1131, 0.018 - 15000.0, 0.4, 2.0, 0.3016, 0.02107 - 15000.0, 0.4, 4.0, 0.4901, 0.02691 - 15000.0, 0.4, 6.0, 0.6786, 0.03554 - 15000.0, 0.4, 8.0, 0.867, 0.04696 - 15000.0, 0.4, 10.0, 1.0555, 0.06115 - 15000.0, 0.5, -2.0, -0.0779, 0.01719 - 15000.0, 0.5, 0.0, 0.1169, 0.01748 - 15000.0, 0.5, 2.0, 0.3117, 0.02073 - 15000.0, 0.5, 4.0, 0.5065, 0.02694 - 15000.0, 0.5, 6.0, 0.7013, 0.0361 - 15000.0, 0.5, 8.0, 0.8961, 0.04822 - 15000.0, 0.5, 10.0, 1.0909, 0.06329 - 15000.0, 0.6, -2.0, -0.0814, 0.01674 - 15000.0, 0.6, 0.0, 0.1221, 0.01706 - 15000.0, 0.6, 2.0, 0.3257, 0.02059 - 15000.0, 0.6, 4.0, 0.5293, 0.02733 - 15000.0, 0.6, 6.0, 0.7329, 0.03728 - 15000.0, 0.6, 8.0, 0.9365, 0.05044 - 15000.0, 0.6, 10.0, 1.1401, 0.06681 - 15000.0, 0.7, -2.0, -0.0863, 0.01634 - 15000.0, 0.7, 0.0, 0.1295, 0.0167 - 15000.0, 0.7, 2.0, 0.3454, 0.02065 - 15000.0, 0.7, 4.0, 0.5613, 0.02819 - 15000.0, 0.7, 6.0, 0.7771, 0.03932 - 15000.0, 0.7, 8.0, 0.993, 0.05405 - 15000.0, 0.7, 10.0, 1.2089, 0.07251 - 15000.0, 0.75, -2.0, -0.0896, 0.01617 - 15000.0, 0.75, 0.0, 0.1343, 0.01655 - 15000.0, 0.75, 2.0, 0.3582, 0.02079 - 15000.0, 0.75, 4.0, 0.5822, 0.02888 - 15000.0, 0.75, 6.0, 0.8061, 0.04097 - 15000.0, 0.75, 8.0, 1.03, 0.05805 - 15000.0, 0.75, 10.0, 1.2539, 0.08147 - 15000.0, 0.8, -2.0, -0.0935, 0.016 - 15000.0, 0.8, 0.0, 0.1402, 0.01642 - 15000.0, 0.8, 2.0, 0.374, 0.0211 - 15000.0, 0.8, 4.0, 0.6077, 0.031 - 15000.0, 0.8, 6.0, 0.8414, 0.04763 - 15000.0, 0.8, 8.0, 1.0751, 0.07253 - 15000.0, 0.8, 10.0, 1.3089, 0.10722 - 15000.0, 0.85, -2.0, -0.0984, 0.01586 - 15000.0, 0.85, 0.0, 0.1476, 0.017 - 15000.0, 0.85, 2.0, 0.3936, 0.02514 - 15000.0, 0.85, 4.0, 0.6396, 0.04205 - 15000.0, 0.85, 6.0, 0.8855, 0.06952 - 15000.0, 0.85, 8.0, 1.1315, 0.10934 - 15000.0, 0.85, 10.0, 1.3775, 0.16328 - 15000.0, 0.9, -2.0, -0.1047, 0.01779 - 15000.0, 0.9, 0.0, 0.1571, 0.02408 - 15000.0, 0.9, 2.0, 0.4188, 0.04161 - 15000.0, 0.9, 4.0, 0.6806, 0.07254 - 15000.0, 0.9, 6.0, 0.9424, 0.11901 - 15000.0, 0.9, 8.0, 1.2041, 0.18318 - 15000.0, 0.9, 10.0, 1.4659, 0.2672 - 18000.0, 0.0, -2.0, -0.0715, 0.00363 - 18000.0, 0.0, 0.0, 0.1072, 0.00384 - 18000.0, 0.0, 2.0, 0.286, 0.00621 - 18000.0, 0.0, 4.0, 0.4647, 0.01072 - 18000.0, 0.0, 6.0, 0.6434, 0.01737 - 18000.0, 0.0, 8.0, 0.8222, 0.02618 - 18000.0, 0.0, 10.0, 1.0009, 0.03713 - 18000.0, 0.2, -2.0, -0.0724, 0.01961 - 18000.0, 0.2, 0.0, 0.1086, 0.01987 - 18000.0, 0.2, 2.0, 0.2896, 0.02275 - 18000.0, 0.2, 4.0, 0.4706, 0.02825 - 18000.0, 0.2, 6.0, 0.6517, 0.03637 - 18000.0, 0.2, 8.0, 0.8327, 0.04711 - 18000.0, 0.2, 10.0, 1.0137, 0.06046 - 18000.0, 0.4, -2.0, -0.0754, 0.01791 - 18000.0, 0.4, 0.0, 0.1131, 0.01819 - 18000.0, 0.4, 2.0, 0.3016, 0.02126 - 18000.0, 0.4, 4.0, 0.4901, 0.02712 - 18000.0, 0.4, 6.0, 0.6786, 0.03576 - 18000.0, 0.4, 8.0, 0.867, 0.0472 - 18000.0, 0.4, 10.0, 1.0555, 0.06143 - 18000.0, 0.5, -2.0, -0.0779, 0.01737 - 18000.0, 0.5, 0.0, 0.1169, 0.01766 - 18000.0, 0.5, 2.0, 0.3117, 0.02092 - 18000.0, 0.5, 4.0, 0.5065, 0.02714 - 18000.0, 0.5, 6.0, 0.7013, 0.03632 - 18000.0, 0.5, 8.0, 0.8961, 0.04846 - 18000.0, 0.5, 10.0, 1.0909, 0.06356 - 18000.0, 0.6, -2.0, -0.0814, 0.01691 - 18000.0, 0.6, 0.0, 0.1221, 0.01723 - 18000.0, 0.6, 2.0, 0.3257, 0.02077 - 18000.0, 0.6, 4.0, 0.5293, 0.02752 - 18000.0, 0.6, 6.0, 0.7329, 0.03749 - 18000.0, 0.6, 8.0, 0.9365, 0.05067 - 18000.0, 0.6, 10.0, 1.1401, 0.06707 - 18000.0, 0.7, -2.0, -0.0863, 0.01651 - 18000.0, 0.7, 0.0, 0.1295, 0.01687 - 18000.0, 0.7, 2.0, 0.3454, 0.02082 - 18000.0, 0.7, 4.0, 0.5613, 0.02838 - 18000.0, 0.7, 6.0, 0.7771, 0.03953 - 18000.0, 0.7, 8.0, 0.993, 0.05427 - 18000.0, 0.7, 10.0, 1.2089, 0.07277 - 18000.0, 0.75, -2.0, -0.0896, 0.01633 - 18000.0, 0.75, 0.0, 0.1343, 0.01671 - 18000.0, 0.75, 2.0, 0.3582, 0.02096 - 18000.0, 0.75, 4.0, 0.5822, 0.02907 - 18000.0, 0.75, 6.0, 0.8061, 0.04117 - 18000.0, 0.75, 8.0, 1.03, 0.05828 - 18000.0, 0.75, 10.0, 1.2539, 0.08173 - 18000.0, 0.8, -2.0, -0.0935, 0.01616 - 18000.0, 0.8, 0.0, 0.1402, 0.01658 - 18000.0, 0.8, 2.0, 0.374, 0.02127 - 18000.0, 0.8, 4.0, 0.6077, 0.03118 - 18000.0, 0.8, 6.0, 0.8414, 0.04783 - 18000.0, 0.8, 8.0, 1.0751, 0.07276 - 18000.0, 0.8, 10.0, 1.3089, 0.10748 - 18000.0, 0.85, -2.0, -0.0984, 0.01601 - 18000.0, 0.85, 0.0, 0.1476, 0.01716 - 18000.0, 0.85, 2.0, 0.3936, 0.0253 - 18000.0, 0.85, 4.0, 0.6396, 0.04223 - 18000.0, 0.85, 6.0, 0.8855, 0.06972 - 18000.0, 0.85, 8.0, 1.1315, 0.10957 - 18000.0, 0.85, 10.0, 1.3775, 0.16355 - 18000.0, 0.9, -2.0, -0.1047, 0.01795 - 18000.0, 0.9, 0.0, 0.1571, 0.02423 - 18000.0, 0.9, 2.0, 0.4188, 0.04177 - 18000.0, 0.9, 4.0, 0.6806, 0.07271 - 18000.0, 0.9, 6.0, 0.9424, 0.11922 - 18000.0, 0.9, 8.0, 1.2041, 0.18342 - 18000.0, 0.9, 10.0, 1.4659, 0.26748 - 21000.0, 0.0, -2.0, -0.0715, 0.00363 - 21000.0, 0.0, 0.0, 0.1072, 0.00384 - 21000.0, 0.0, 2.0, 0.286, 0.00621 - 21000.0, 0.0, 4.0, 0.4647, 0.01072 - 21000.0, 0.0, 6.0, 0.6434, 0.01737 - 21000.0, 0.0, 8.0, 0.8222, 0.02618 - 21000.0, 0.0, 10.0, 1.0009, 0.03713 - 21000.0, 0.2, -2.0, -0.0724, 0.01983 - 21000.0, 0.2, 0.0, 0.1086, 0.0201 - 21000.0, 0.2, 2.0, 0.2896, 0.02298 - 21000.0, 0.2, 4.0, 0.4706, 0.0285 - 21000.0, 0.2, 6.0, 0.6517, 0.03663 - 21000.0, 0.2, 8.0, 0.8327, 0.0474 - 21000.0, 0.2, 10.0, 1.0137, 0.06079 - 21000.0, 0.4, -2.0, -0.0754, 0.01811 - 21000.0, 0.4, 0.0, 0.1131, 0.01839 - 21000.0, 0.4, 2.0, 0.3016, 0.02146 - 21000.0, 0.4, 4.0, 0.4901, 0.02733 - 21000.0, 0.4, 6.0, 0.6786, 0.036 - 21000.0, 0.4, 8.0, 0.867, 0.04745 - 21000.0, 0.4, 10.0, 1.0555, 0.06171 - 21000.0, 0.5, -2.0, -0.0779, 0.01755 - 21000.0, 0.5, 0.0, 0.1169, 0.01785 - 21000.0, 0.5, 2.0, 0.3117, 0.02111 - 21000.0, 0.5, 4.0, 0.5065, 0.02734 - 21000.0, 0.5, 6.0, 0.7013, 0.03654 - 21000.0, 0.5, 8.0, 0.8961, 0.0487 - 21000.0, 0.5, 10.0, 1.0909, 0.06383 - 21000.0, 0.6, -2.0, -0.0814, 0.01708 - 21000.0, 0.6, 0.0, 0.1221, 0.01741 - 21000.0, 0.6, 2.0, 0.3257, 0.02095 - 21000.0, 0.6, 4.0, 0.5293, 0.02771 - 21000.0, 0.6, 6.0, 0.7329, 0.0377 - 21000.0, 0.6, 8.0, 0.9365, 0.05091 - 21000.0, 0.6, 10.0, 1.1401, 0.06734 - 21000.0, 0.7, -2.0, -0.0863, 0.01668 - 21000.0, 0.7, 0.0, 0.1295, 0.01704 - 21000.0, 0.7, 2.0, 0.3454, 0.021 - 21000.0, 0.7, 4.0, 0.5613, 0.02857 - 21000.0, 0.7, 6.0, 0.7771, 0.03974 - 21000.0, 0.7, 8.0, 0.993, 0.05451 - 21000.0, 0.7, 10.0, 1.2089, 0.07304 - 21000.0, 0.75, -2.0, -0.0896, 0.01649 - 21000.0, 0.75, 0.0, 0.1343, 0.01688 - 21000.0, 0.75, 2.0, 0.3582, 0.02113 - 21000.0, 0.75, 4.0, 0.5822, 0.02925 - 21000.0, 0.75, 6.0, 0.8061, 0.04138 - 21000.0, 0.75, 8.0, 1.03, 0.05851 - 21000.0, 0.75, 10.0, 1.2539, 0.082 - 21000.0, 0.8, -2.0, -0.0935, 0.01632 - 21000.0, 0.8, 0.0, 0.1402, 0.01674 - 21000.0, 0.8, 2.0, 0.374, 0.02144 - 21000.0, 0.8, 4.0, 0.6077, 0.03137 - 21000.0, 0.8, 6.0, 0.8414, 0.04804 - 21000.0, 0.8, 8.0, 1.0751, 0.073 - 21000.0, 0.8, 10.0, 1.3089, 0.10776 - 21000.0, 0.85, -2.0, -0.0984, 0.01617 - 21000.0, 0.85, 0.0, 0.1476, 0.01732 - 21000.0, 0.85, 2.0, 0.3936, 0.02547 - 21000.0, 0.85, 4.0, 0.6396, 0.04241 - 21000.0, 0.85, 6.0, 0.8855, 0.06993 - 21000.0, 0.85, 8.0, 1.1315, 0.10981 - 21000.0, 0.85, 10.0, 1.3775, 0.16383 - 21000.0, 0.9, -2.0, -0.1047, 0.0181 - 21000.0, 0.9, 0.0, 0.1571, 0.02439 - 21000.0, 0.9, 2.0, 0.4188, 0.04194 - 21000.0, 0.9, 4.0, 0.6806, 0.0729 - 21000.0, 0.9, 6.0, 0.9424, 0.11943 - 21000.0, 0.9, 8.0, 1.2041, 0.18367 - 21000.0, 0.9, 10.0, 1.4659, 0.26777 - 24000.0, 0.0, -2.0, -0.0715, 0.00363 - 24000.0, 0.0, 0.0, 0.1072, 0.00384 - 24000.0, 0.0, 2.0, 0.286, 0.00621 - 24000.0, 0.0, 4.0, 0.4647, 0.01072 - 24000.0, 0.0, 6.0, 0.6434, 0.01737 - 24000.0, 0.0, 8.0, 0.8222, 0.02618 - 24000.0, 0.0, 10.0, 1.0009, 0.03713 - 24000.0, 0.2, -2.0, -0.0724, 0.02007 - 24000.0, 0.2, 0.0, 0.1086, 0.02034 - 24000.0, 0.2, 2.0, 0.2896, 0.02323 - 24000.0, 0.2, 4.0, 0.4706, 0.02876 - 24000.0, 0.2, 6.0, 0.6517, 0.03691 - 24000.0, 0.2, 8.0, 0.8327, 0.0477 - 24000.0, 0.2, 10.0, 1.0137, 0.06112 - 24000.0, 0.4, -2.0, -0.0754, 0.01831 - 24000.0, 0.4, 0.0, 0.1131, 0.01859 - 24000.0, 0.4, 2.0, 0.3016, 0.02167 - 24000.0, 0.4, 4.0, 0.4901, 0.02756 - 24000.0, 0.4, 6.0, 0.6786, 0.03624 - 24000.0, 0.4, 8.0, 0.867, 0.04772 - 24000.0, 0.4, 10.0, 1.0555, 0.062 - 24000.0, 0.5, -2.0, -0.0779, 0.01775 - 24000.0, 0.5, 0.0, 0.1169, 0.01804 - 24000.0, 0.5, 2.0, 0.3117, 0.02131 - 24000.0, 0.5, 4.0, 0.5065, 0.02755 - 24000.0, 0.5, 6.0, 0.7013, 0.03677 - 24000.0, 0.5, 8.0, 0.8961, 0.04895 - 24000.0, 0.5, 10.0, 1.0909, 0.06411 - 24000.0, 0.6, -2.0, -0.0814, 0.01727 - 24000.0, 0.6, 0.0, 0.1221, 0.01759 - 24000.0, 0.6, 2.0, 0.3257, 0.02114 - 24000.0, 0.6, 4.0, 0.5293, 0.02792 - 24000.0, 0.6, 6.0, 0.7329, 0.03792 - 24000.0, 0.6, 8.0, 0.9365, 0.05116 - 24000.0, 0.6, 10.0, 1.1401, 0.06762 - 24000.0, 0.7, -2.0, -0.0863, 0.01685 - 24000.0, 0.7, 0.0, 0.1295, 0.01722 - 24000.0, 0.7, 2.0, 0.3454, 0.02119 - 24000.0, 0.7, 4.0, 0.5613, 0.02877 - 24000.0, 0.7, 6.0, 0.7771, 0.03996 - 24000.0, 0.7, 8.0, 0.993, 0.05476 - 24000.0, 0.7, 10.0, 1.2089, 0.07332 - 24000.0, 0.75, -2.0, -0.0896, 0.01667 - 24000.0, 0.75, 0.0, 0.1343, 0.01705 - 24000.0, 0.75, 2.0, 0.3582, 0.02132 - 24000.0, 0.75, 4.0, 0.5822, 0.02945 - 24000.0, 0.75, 6.0, 0.8061, 0.0416 - 24000.0, 0.75, 8.0, 1.03, 0.05876 - 24000.0, 0.75, 10.0, 1.2539, 0.08228 - 24000.0, 0.8, -2.0, -0.0935, 0.01649 - 24000.0, 0.8, 0.0, 0.1402, 0.01691 - 24000.0, 0.8, 2.0, 0.374, 0.02162 - 24000.0, 0.8, 4.0, 0.6077, 0.03156 - 24000.0, 0.8, 6.0, 0.8414, 0.04826 - 24000.0, 0.8, 8.0, 1.0751, 0.07325 - 24000.0, 0.8, 10.0, 1.3089, 0.10805 - 24000.0, 0.85, -2.0, -0.0984, 0.01634 - 24000.0, 0.85, 0.0, 0.1476, 0.01749 - 24000.0, 0.85, 2.0, 0.3936, 0.02565 - 24000.0, 0.85, 4.0, 0.6396, 0.04261 - 24000.0, 0.85, 6.0, 0.8855, 0.07015 - 24000.0, 0.85, 8.0, 1.1315, 0.11006 - 24000.0, 0.85, 10.0, 1.3775, 0.16412 - 24000.0, 0.9, -2.0, -0.1047, 0.01827 - 24000.0, 0.9, 0.0, 0.1571, 0.02455 - 24000.0, 0.9, 2.0, 0.4188, 0.04211 - 24000.0, 0.9, 4.0, 0.6806, 0.0731 - 24000.0, 0.9, 6.0, 0.9424, 0.11965 - 24000.0, 0.9, 8.0, 1.2041, 0.18393 - 24000.0, 0.9, 10.0, 1.4659, 0.26808 - 27000.0, 0.0, -2.0, -0.0715, 0.00363 - 27000.0, 0.0, 0.0, 0.1072, 0.00384 - 27000.0, 0.0, 2.0, 0.286, 0.00621 - 27000.0, 0.0, 4.0, 0.4647, 0.01072 - 27000.0, 0.0, 6.0, 0.6434, 0.01737 - 27000.0, 0.0, 8.0, 0.8222, 0.02618 - 27000.0, 0.0, 10.0, 1.0009, 0.03713 - 27000.0, 0.2, -2.0, -0.0724, 0.02032 - 27000.0, 0.2, 0.0, 0.1086, 0.02058 - 27000.0, 0.2, 2.0, 0.2896, 0.02349 - 27000.0, 0.2, 4.0, 0.4706, 0.02903 - 27000.0, 0.2, 6.0, 0.6517, 0.0372 - 27000.0, 0.2, 8.0, 0.8327, 0.04802 - 27000.0, 0.2, 10.0, 1.0137, 0.06147 - 27000.0, 0.4, -2.0, -0.0754, 0.01853 - 27000.0, 0.4, 0.0, 0.1131, 0.01881 - 27000.0, 0.4, 2.0, 0.3016, 0.02189 - 27000.0, 0.4, 4.0, 0.4901, 0.02779 - 27000.0, 0.4, 6.0, 0.6786, 0.03649 - 27000.0, 0.4, 8.0, 0.867, 0.048 - 27000.0, 0.4, 10.0, 1.0555, 0.06231 - 27000.0, 0.5, -2.0, -0.0779, 0.01795 - 27000.0, 0.5, 0.0, 0.1169, 0.01824 - 27000.0, 0.5, 2.0, 0.3117, 0.02152 - 27000.0, 0.5, 4.0, 0.5065, 0.02778 - 27000.0, 0.5, 6.0, 0.7013, 0.03701 - 27000.0, 0.5, 8.0, 0.8961, 0.04922 - 27000.0, 0.5, 10.0, 1.0909, 0.06441 - 27000.0, 0.6, -2.0, -0.0814, 0.01746 - 27000.0, 0.6, 0.0, 0.1221, 0.01778 - 27000.0, 0.6, 2.0, 0.3257, 0.02134 - 27000.0, 0.6, 4.0, 0.5293, 0.02813 - 27000.0, 0.6, 6.0, 0.7329, 0.03816 - 27000.0, 0.6, 8.0, 0.9365, 0.05142 - 27000.0, 0.6, 10.0, 1.1401, 0.06791 - 27000.0, 0.7, -2.0, -0.0863, 0.01704 - 27000.0, 0.7, 0.0, 0.1295, 0.0174 - 27000.0, 0.7, 2.0, 0.3454, 0.02138 - 27000.0, 0.7, 4.0, 0.5613, 0.02897 - 27000.0, 0.7, 6.0, 0.7771, 0.04019 - 27000.0, 0.7, 8.0, 0.993, 0.05501 - 27000.0, 0.7, 10.0, 1.2089, 0.07361 - 27000.0, 0.75, -2.0, -0.0896, 0.01685 - 27000.0, 0.75, 0.0, 0.1343, 0.01724 - 27000.0, 0.75, 2.0, 0.3582, 0.02151 - 27000.0, 0.75, 4.0, 0.5822, 0.02966 - 27000.0, 0.75, 6.0, 0.8061, 0.04182 - 27000.0, 0.75, 8.0, 1.03, 0.05902 - 27000.0, 0.75, 10.0, 1.2539, 0.08258 - 27000.0, 0.8, -2.0, -0.0935, 0.01667 - 27000.0, 0.8, 0.0, 0.1402, 0.01709 - 27000.0, 0.8, 2.0, 0.374, 0.02181 - 27000.0, 0.8, 4.0, 0.6077, 0.03177 - 27000.0, 0.8, 6.0, 0.8414, 0.04849 - 27000.0, 0.8, 8.0, 1.0751, 0.0735 - 27000.0, 0.8, 10.0, 1.3089, 0.10835 - 27000.0, 0.85, -2.0, -0.0984, 0.01652 - 27000.0, 0.85, 0.0, 0.1476, 0.01766 - 27000.0, 0.85, 2.0, 0.3936, 0.02583 - 27000.0, 0.85, 4.0, 0.6396, 0.04281 - 27000.0, 0.85, 6.0, 0.8855, 0.07038 - 27000.0, 0.85, 8.0, 1.1315, 0.11033 - 27000.0, 0.85, 10.0, 1.3775, 0.16443 - 27000.0, 0.9, -2.0, -0.1047, 0.01844 - 27000.0, 0.9, 0.0, 0.1571, 0.02473 - 27000.0, 0.9, 2.0, 0.4188, 0.0423 - 27000.0, 0.9, 4.0, 0.6806, 0.0733 - 27000.0, 0.9, 6.0, 0.9424, 0.11988 - 27000.0, 0.9, 8.0, 1.2041, 0.1842 - 27000.0, 0.9, 10.0, 1.4659, 0.26839 - 30000.0, 0.0, -2.0, -0.0715, 0.00363 - 30000.0, 0.0, 0.0, 0.1072, 0.00384 - 30000.0, 0.0, 2.0, 0.286, 0.00621 - 30000.0, 0.0, 4.0, 0.4647, 0.01072 - 30000.0, 0.0, 6.0, 0.6434, 0.01737 - 30000.0, 0.0, 8.0, 0.8222, 0.02618 - 30000.0, 0.0, 10.0, 1.0009, 0.03713 - 30000.0, 0.2, -2.0, -0.0724, 0.02058 - 30000.0, 0.2, 0.0, 0.1086, 0.02085 - 30000.0, 0.2, 2.0, 0.2896, 0.02375 - 30000.0, 0.2, 4.0, 0.4706, 0.02931 - 30000.0, 0.2, 6.0, 0.6517, 0.03751 - 30000.0, 0.2, 8.0, 0.8327, 0.04835 - 30000.0, 0.2, 10.0, 1.0137, 0.06184 - 30000.0, 0.4, -2.0, -0.0754, 0.01875 - 30000.0, 0.4, 0.0, 0.1131, 0.01903 - 30000.0, 0.4, 2.0, 0.3016, 0.02212 - 30000.0, 0.4, 4.0, 0.4901, 0.02803 - 30000.0, 0.4, 6.0, 0.6786, 0.03675 - 30000.0, 0.4, 8.0, 0.867, 0.04828 - 30000.0, 0.4, 10.0, 1.0555, 0.06263 - 30000.0, 0.5, -2.0, -0.0779, 0.01816 - 30000.0, 0.5, 0.0, 0.1169, 0.01846 - 30000.0, 0.5, 2.0, 0.3117, 0.02174 - 30000.0, 0.5, 4.0, 0.5065, 0.02801 - 30000.0, 0.5, 6.0, 0.7013, 0.03726 - 30000.0, 0.5, 8.0, 0.8961, 0.0495 - 30000.0, 0.5, 10.0, 1.0909, 0.06472 - 30000.0, 0.6, -2.0, -0.0814, 0.01766 - 30000.0, 0.6, 0.0, 0.1221, 0.01799 - 30000.0, 0.6, 2.0, 0.3257, 0.02155 - 30000.0, 0.6, 4.0, 0.5293, 0.02836 - 30000.0, 0.6, 6.0, 0.7329, 0.0384 - 30000.0, 0.6, 8.0, 0.9365, 0.05169 - 30000.0, 0.6, 10.0, 1.1401, 0.06822 - 30000.0, 0.7, -2.0, -0.0863, 0.01723 - 30000.0, 0.7, 0.0, 0.1295, 0.01759 - 30000.0, 0.7, 2.0, 0.3454, 0.02158 - 30000.0, 0.7, 4.0, 0.5613, 0.02919 - 30000.0, 0.7, 6.0, 0.7771, 0.04043 - 30000.0, 0.7, 8.0, 0.993, 0.05528 - 30000.0, 0.7, 10.0, 1.2089, 0.07391 - 30000.0, 0.75, -2.0, -0.0896, 0.01704 - 30000.0, 0.75, 0.0, 0.1343, 0.01743 - 30000.0, 0.75, 2.0, 0.3582, 0.0217 - 30000.0, 0.75, 4.0, 0.5822, 0.02987 - 30000.0, 0.75, 6.0, 0.8061, 0.04206 - 30000.0, 0.75, 8.0, 1.03, 0.05929 - 30000.0, 0.75, 10.0, 1.2539, 0.08289 - 30000.0, 0.8, -2.0, -0.0935, 0.01686 - 30000.0, 0.8, 0.0, 0.1402, 0.01728 - 30000.0, 0.8, 2.0, 0.374, 0.022 - 30000.0, 0.8, 4.0, 0.6077, 0.03198 - 30000.0, 0.8, 6.0, 0.8414, 0.04873 - 30000.0, 0.8, 8.0, 1.0751, 0.07378 - 30000.0, 0.8, 10.0, 1.3089, 0.10866 - 30000.0, 0.85, -2.0, -0.0984, 0.0167 - 30000.0, 0.85, 0.0, 0.1476, 0.01785 - 30000.0, 0.85, 2.0, 0.3936, 0.02603 - 30000.0, 0.85, 4.0, 0.6396, 0.04302 - 30000.0, 0.85, 6.0, 0.8855, 0.07062 - 30000.0, 0.85, 8.0, 1.1315, 0.1106 - 30000.0, 0.85, 10.0, 1.3775, 0.16475 - 30000.0, 0.9, -2.0, -0.1047, 0.01862 - 30000.0, 0.9, 0.0, 0.1571, 0.02491 - 30000.0, 0.9, 2.0, 0.4188, 0.04249 - 30000.0, 0.9, 4.0, 0.6806, 0.07351 - 30000.0, 0.9, 6.0, 0.9424, 0.12012 - 30000.0, 0.9, 8.0, 1.2041, 0.18448 - 30000.0, 0.9, 10.0, 1.4659, 0.26872 - 33000.0, 0.0, -2.0, -0.0715, 0.00363 - 33000.0, 0.0, 0.0, 0.1072, 0.00384 - 33000.0, 0.0, 2.0, 0.286, 0.00621 - 33000.0, 0.0, 4.0, 0.4647, 0.01072 - 33000.0, 0.0, 6.0, 0.6434, 0.01737 - 33000.0, 0.0, 8.0, 0.8222, 0.02618 - 33000.0, 0.0, 10.0, 1.0009, 0.03713 - 33000.0, 0.2, -2.0, -0.0724, 0.02085 - 33000.0, 0.2, 0.0, 0.1086, 0.02112 - 33000.0, 0.2, 2.0, 0.2896, 0.02404 - 33000.0, 0.2, 4.0, 0.4706, 0.0296 - 33000.0, 0.2, 6.0, 0.6517, 0.03782 - 33000.0, 0.2, 8.0, 0.8327, 0.0487 - 33000.0, 0.2, 10.0, 1.0137, 0.06222 - 33000.0, 0.4, -2.0, -0.0754, 0.01898 - 33000.0, 0.4, 0.0, 0.1131, 0.01926 - 33000.0, 0.4, 2.0, 0.3016, 0.02236 - 33000.0, 0.4, 4.0, 0.4901, 0.02829 - 33000.0, 0.4, 6.0, 0.6786, 0.03703 - 33000.0, 0.4, 8.0, 0.867, 0.04859 - 33000.0, 0.4, 10.0, 1.0555, 0.06297 - 33000.0, 0.5, -2.0, -0.0779, 0.01838 - 33000.0, 0.5, 0.0, 0.1169, 0.01868 - 33000.0, 0.5, 2.0, 0.3117, 0.02197 - 33000.0, 0.5, 4.0, 0.5065, 0.02825 - 33000.0, 0.5, 6.0, 0.7013, 0.03752 - 33000.0, 0.5, 8.0, 0.8961, 0.04979 - 33000.0, 0.5, 10.0, 1.0909, 0.06505 - 33000.0, 0.6, -2.0, -0.0814, 0.01787 - 33000.0, 0.6, 0.0, 0.1221, 0.0182 - 33000.0, 0.6, 2.0, 0.3257, 0.02177 - 33000.0, 0.6, 4.0, 0.5293, 0.02859 - 33000.0, 0.6, 6.0, 0.7329, 0.03866 - 33000.0, 0.6, 8.0, 0.9365, 0.05197 - 33000.0, 0.6, 10.0, 1.1401, 0.06853 - 33000.0, 0.7, -2.0, -0.0863, 0.01743 - 33000.0, 0.7, 0.0, 0.1295, 0.0178 - 33000.0, 0.7, 2.0, 0.3454, 0.02179 - 33000.0, 0.7, 4.0, 0.5613, 0.02942 - 33000.0, 0.7, 6.0, 0.7771, 0.04067 - 33000.0, 0.7, 8.0, 0.993, 0.05556 - 33000.0, 0.7, 10.0, 1.2089, 0.07423 - 33000.0, 0.75, -2.0, -0.0896, 0.01723 - 33000.0, 0.75, 0.0, 0.1343, 0.01762 - 33000.0, 0.75, 2.0, 0.3582, 0.02191 - 33000.0, 0.75, 4.0, 0.5822, 0.03009 - 33000.0, 0.75, 6.0, 0.8061, 0.04231 - 33000.0, 0.75, 8.0, 1.03, 0.05957 - 33000.0, 0.75, 10.0, 1.2539, 0.08321 - 33000.0, 0.8, -2.0, -0.0935, 0.01705 - 33000.0, 0.8, 0.0, 0.1402, 0.01747 - 33000.0, 0.8, 2.0, 0.374, 0.02221 - 33000.0, 0.8, 4.0, 0.6077, 0.0322 - 33000.0, 0.8, 6.0, 0.8414, 0.04897 - 33000.0, 0.8, 8.0, 1.0751, 0.07406 - 33000.0, 0.8, 10.0, 1.3089, 0.10898 - 33000.0, 0.85, -2.0, -0.0984, 0.01689 - 33000.0, 0.85, 0.0, 0.1476, 0.01804 - 33000.0, 0.85, 2.0, 0.3936, 0.02623 - 33000.0, 0.85, 4.0, 0.6396, 0.04324 - 33000.0, 0.85, 6.0, 0.8855, 0.07087 - 33000.0, 0.85, 8.0, 1.1315, 0.11089 - 33000.0, 0.85, 10.0, 1.3775, 0.16508 - 33000.0, 0.9, -2.0, -0.1047, 0.01881 - 33000.0, 0.9, 0.0, 0.1571, 0.02509 - 33000.0, 0.9, 2.0, 0.4188, 0.04269 - 33000.0, 0.9, 4.0, 0.6806, 0.07373 - 33000.0, 0.9, 6.0, 0.9424, 0.12038 - 33000.0, 0.9, 8.0, 1.2041, 0.18477 - 33000.0, 0.9, 10.0, 1.4659, 0.26907 - 36000.0, 0.0, -2.0, -0.0715, 0.00363 - 36000.0, 0.0, 0.0, 0.1072, 0.00384 - 36000.0, 0.0, 2.0, 0.286, 0.00621 - 36000.0, 0.0, 4.0, 0.4647, 0.01072 - 36000.0, 0.0, 6.0, 0.6434, 0.01737 - 36000.0, 0.0, 8.0, 0.8222, 0.02618 - 36000.0, 0.0, 10.0, 1.0009, 0.03713 - 36000.0, 0.2, -2.0, -0.0724, 0.02114 - 36000.0, 0.2, 0.0, 0.1086, 0.0214 - 36000.0, 0.2, 2.0, 0.2896, 0.02433 - 36000.0, 0.2, 4.0, 0.4706, 0.02991 - 36000.0, 0.2, 6.0, 0.6517, 0.03816 - 36000.0, 0.2, 8.0, 0.8327, 0.04906 - 36000.0, 0.2, 10.0, 1.0137, 0.06262 - 36000.0, 0.4, -2.0, -0.0754, 0.01922 - 36000.0, 0.4, 0.0, 0.1131, 0.01951 - 36000.0, 0.4, 2.0, 0.3016, 0.02262 - 36000.0, 0.4, 4.0, 0.4901, 0.02855 - 36000.0, 0.4, 6.0, 0.6786, 0.03731 - 36000.0, 0.4, 8.0, 0.867, 0.0489 - 36000.0, 0.4, 10.0, 1.0555, 0.06332 - 36000.0, 0.5, -2.0, -0.0779, 0.01861 - 36000.0, 0.5, 0.0, 0.1169, 0.01891 - 36000.0, 0.5, 2.0, 0.3117, 0.02221 - 36000.0, 0.5, 4.0, 0.5065, 0.0285 - 36000.0, 0.5, 6.0, 0.7013, 0.0378 - 36000.0, 0.5, 8.0, 0.8961, 0.05009 - 36000.0, 0.5, 10.0, 1.0909, 0.06539 - 36000.0, 0.6, -2.0, -0.0814, 0.01809 - 36000.0, 0.6, 0.0, 0.1221, 0.01842 - 36000.0, 0.6, 2.0, 0.3257, 0.022 - 36000.0, 0.6, 4.0, 0.5293, 0.02883 - 36000.0, 0.6, 6.0, 0.7329, 0.03892 - 36000.0, 0.6, 8.0, 0.9365, 0.05227 - 36000.0, 0.6, 10.0, 1.1401, 0.06887 - 36000.0, 0.7, -2.0, -0.0863, 0.01765 - 36000.0, 0.7, 0.0, 0.1295, 0.01801 - 36000.0, 0.7, 2.0, 0.3454, 0.02201 - 36000.0, 0.7, 4.0, 0.5613, 0.02965 - 36000.0, 0.7, 6.0, 0.7771, 0.04094 - 36000.0, 0.7, 8.0, 0.993, 0.05586 - 36000.0, 0.7, 10.0, 1.2089, 0.07457 - 36000.0, 0.75, -2.0, -0.0896, 0.01744 - 36000.0, 0.75, 0.0, 0.1343, 0.01783 - 36000.0, 0.75, 2.0, 0.3582, 0.02213 - 36000.0, 0.75, 4.0, 0.5822, 0.03033 - 36000.0, 0.75, 6.0, 0.8061, 0.04257 - 36000.0, 0.75, 8.0, 1.03, 0.05986 - 36000.0, 0.75, 10.0, 1.2539, 0.08354 - 36000.0, 0.8, -2.0, -0.0935, 0.01725 - 36000.0, 0.8, 0.0, 0.1402, 0.01768 - 36000.0, 0.8, 2.0, 0.374, 0.02242 - 36000.0, 0.8, 4.0, 0.6077, 0.03243 - 36000.0, 0.8, 6.0, 0.8414, 0.04923 - 36000.0, 0.8, 8.0, 1.0751, 0.07435 - 36000.0, 0.8, 10.0, 1.3089, 0.10932 - 36000.0, 0.85, -2.0, -0.0984, 0.01709 - 36000.0, 0.85, 0.0, 0.1476, 0.01824 - 36000.0, 0.85, 2.0, 0.3936, 0.02644 - 36000.0, 0.85, 4.0, 0.6396, 0.04347 - 36000.0, 0.85, 6.0, 0.8855, 0.07113 - 36000.0, 0.85, 8.0, 1.1315, 0.11119 - 36000.0, 0.85, 10.0, 1.3775, 0.16543 - 36000.0, 0.9, -2.0, -0.1047, 0.019 - 36000.0, 0.9, 0.0, 0.1571, 0.02529 - 36000.0, 0.9, 2.0, 0.4188, 0.04289 - 36000.0, 0.9, 4.0, 0.6806, 0.07396 - 36000.0, 0.9, 6.0, 0.9424, 0.12064 - 36000.0, 0.9, 8.0, 1.2041, 0.18508 - 36000.0, 0.9, 10.0, 1.4659, 0.0 - 38000.0, 0.0, -2.0, -0.0715, 0.00363 - 38000.0, 0.0, 0.0, 0.1072, 0.00384 - 38000.0, 0.0, 2.0, 0.286, 0.00621 - 38000.0, 0.0, 4.0, 0.4647, 0.01072 - 38000.0, 0.0, 6.0, 0.6434, 0.01737 - 38000.0, 0.0, 8.0, 0.8222, 0.02618 - 38000.0, 0.0, 10.0, 1.0009, 0.03713 - 38000.0, 0.2, -2.0, -0.0724, 0.0214 - 38000.0, 0.2, 0.0, 0.1086, 0.02166 - 38000.0, 0.2, 2.0, 0.2896, 0.0246 - 38000.0, 0.2, 4.0, 0.4706, 0.0302 - 38000.0, 0.2, 6.0, 0.6517, 0.03846 - 38000.0, 0.2, 8.0, 0.8327, 0.04939 - 38000.0, 0.2, 10.0, 1.0137, 0.06299 - 38000.0, 0.4, -2.0, -0.0754, 0.01945 - 38000.0, 0.4, 0.0, 0.1131, 0.01973 - 38000.0, 0.4, 2.0, 0.3016, 0.02285 - 38000.0, 0.4, 4.0, 0.4901, 0.02879 - 38000.0, 0.4, 6.0, 0.6786, 0.03758 - 38000.0, 0.4, 8.0, 0.867, 0.04919 - 38000.0, 0.4, 10.0, 1.0555, 0.06364 - 38000.0, 0.5, -2.0, -0.0779, 0.01882 - 38000.0, 0.5, 0.0, 0.1169, 0.01912 - 38000.0, 0.5, 2.0, 0.3117, 0.02242 - 38000.0, 0.5, 4.0, 0.5065, 0.02874 - 38000.0, 0.5, 6.0, 0.7013, 0.03805 - 38000.0, 0.5, 8.0, 0.8961, 0.05037 - 38000.0, 0.5, 10.0, 1.0909, 0.0657 - 38000.0, 0.6, -2.0, -0.0814, 0.01829 - 38000.0, 0.6, 0.0, 0.1221, 0.01862 - 38000.0, 0.6, 2.0, 0.3257, 0.02221 - 38000.0, 0.6, 4.0, 0.5293, 0.02906 - 38000.0, 0.6, 6.0, 0.7329, 0.03917 - 38000.0, 0.6, 8.0, 0.9365, 0.05254 - 38000.0, 0.6, 10.0, 1.1401, 0.06917 - 38000.0, 0.7, -2.0, -0.0863, 0.01784 - 38000.0, 0.7, 0.0, 0.1295, 0.0182 - 38000.0, 0.7, 2.0, 0.3454, 0.02221 - 38000.0, 0.7, 4.0, 0.5613, 0.02987 - 38000.0, 0.7, 6.0, 0.7771, 0.04117 - 38000.0, 0.7, 8.0, 0.993, 0.05612 - 38000.0, 0.7, 10.0, 1.2089, 0.07487 - 38000.0, 0.75, -2.0, -0.0896, 0.01763 - 38000.0, 0.75, 0.0, 0.1343, 0.01802 - 38000.0, 0.75, 2.0, 0.3582, 0.02232 - 38000.0, 0.75, 4.0, 0.5822, 0.03054 - 38000.0, 0.75, 6.0, 0.8061, 0.04281 - 38000.0, 0.75, 8.0, 1.03, 0.06013 - 38000.0, 0.75, 10.0, 1.2539, 0.08385 - 38000.0, 0.8, -2.0, -0.0935, 0.01744 - 38000.0, 0.8, 0.0, 0.1402, 0.01786 - 38000.0, 0.8, 2.0, 0.374, 0.02261 - 38000.0, 0.8, 4.0, 0.6077, 0.03264 - 38000.0, 0.8, 6.0, 0.8414, 0.04947 - 38000.0, 0.8, 8.0, 1.0751, 0.07462 - 38000.0, 0.8, 10.0, 1.3089, 0.10963 - 38000.0, 0.85, -2.0, -0.0984, 0.01727 - 38000.0, 0.85, 0.0, 0.1476, 0.01842 - 38000.0, 0.85, 2.0, 0.3936, 0.02663 - 38000.0, 0.85, 4.0, 0.6396, 0.04368 - 38000.0, 0.85, 6.0, 0.8855, 0.07137 - 38000.0, 0.85, 8.0, 1.1315, 0.11146 - 38000.0, 0.85, 10.0, 1.3775, 0.16575 - 38000.0, 0.9, -2.0, -0.1047, 0.01918 - 38000.0, 0.9, 0.0, 0.1571, 0.02547 - 38000.0, 0.9, 2.0, 0.4188, 0.04308 - 38000.0, 0.9, 4.0, 0.6806, 0.07417 - 38000.0, 0.9, 6.0, 0.9424, 0.12088 - 38000.0, 0.9, 8.0, 1.2041, 0.18536 - 38000.0, 0.9, 10.0, 1.4659, 0.26976 - 42000.0, 0.0, -2.0, -0.0715, 0.00363 - 42000.0, 0.0, 0.0, 0.1072, 0.00384 - 42000.0, 0.0, 2.0, 0.286, 0.00621 - 42000.0, 0.0, 4.0, 0.4647, 0.01072 - 42000.0, 0.0, 6.0, 0.6434, 0.01737 - 42000.0, 0.0, 8.0, 0.8222, 0.02618 - 42000.0, 0.0, 10.0, 1.0009, 0.03713 - 42000.0, 0.2, -2.0, -0.0724, 0.02194 - 42000.0, 0.2, 0.0, 0.1086, 0.02221 - 42000.0, 0.2, 2.0, 0.2896, 0.02516 - 42000.0, 0.2, 4.0, 0.4706, 0.03079 - 42000.0, 0.2, 6.0, 0.6517, 0.0391 - 42000.0, 0.2, 8.0, 0.8327, 0.05009 - 42000.0, 0.2, 10.0, 1.0137, 0.06376 - 42000.0, 0.4, -2.0, -0.0754, 0.01991 - 42000.0, 0.4, 0.0, 0.1131, 0.0202 - 42000.0, 0.4, 2.0, 0.3016, 0.02333 - 42000.0, 0.4, 4.0, 0.4901, 0.0293 - 42000.0, 0.4, 6.0, 0.6786, 0.03812 - 42000.0, 0.4, 8.0, 0.867, 0.04979 - 42000.0, 0.4, 10.0, 1.0555, 0.06431 - 42000.0, 0.5, -2.0, -0.0779, 0.01926 - 42000.0, 0.5, 0.0, 0.1169, 0.01956 - 42000.0, 0.5, 2.0, 0.3117, 0.02288 - 42000.0, 0.5, 4.0, 0.5065, 0.02922 - 42000.0, 0.5, 6.0, 0.7013, 0.03858 - 42000.0, 0.5, 8.0, 0.8961, 0.05095 - 42000.0, 0.5, 10.0, 1.0909, 0.06634 - 42000.0, 0.6, -2.0, -0.0814, 0.01871 - 42000.0, 0.6, 0.0, 0.1221, 0.01904 - 42000.0, 0.6, 2.0, 0.3257, 0.02264 - 42000.0, 0.6, 4.0, 0.5293, 0.02952 - 42000.0, 0.6, 6.0, 0.7329, 0.03968 - 42000.0, 0.6, 8.0, 0.9365, 0.0531 - 42000.0, 0.6, 10.0, 1.1401, 0.06981 - 42000.0, 0.7, -2.0, -0.0863, 0.01824 - 42000.0, 0.7, 0.0, 0.1295, 0.0186 - 42000.0, 0.7, 2.0, 0.3454, 0.02263 - 42000.0, 0.7, 4.0, 0.5613, 0.03032 - 42000.0, 0.7, 6.0, 0.7771, 0.04167 - 42000.0, 0.7, 8.0, 0.993, 0.05668 - 42000.0, 0.7, 10.0, 1.2089, 0.07551 - 42000.0, 0.75, -2.0, -0.0896, 0.01802 - 42000.0, 0.75, 0.0, 0.1343, 0.01842 - 42000.0, 0.75, 2.0, 0.3582, 0.02274 - 42000.0, 0.75, 4.0, 0.5822, 0.03099 - 42000.0, 0.75, 6.0, 0.8061, 0.0433 - 42000.0, 0.75, 8.0, 1.03, 0.06069 - 42000.0, 0.75, 10.0, 1.2539, 0.08449 - 42000.0, 0.8, -2.0, -0.0935, 0.01782 - 42000.0, 0.8, 0.0, 0.1402, 0.01825 - 42000.0, 0.8, 2.0, 0.374, 0.02302 - 42000.0, 0.8, 4.0, 0.6077, 0.03309 - 42000.0, 0.8, 6.0, 0.8414, 0.04996 - 42000.0, 0.8, 8.0, 1.0751, 0.07519 - 42000.0, 0.8, 10.0, 1.3089, 0.11028 - 42000.0, 0.85, -2.0, -0.0984, 0.01765 - 42000.0, 0.85, 0.0, 0.1476, 0.0188 - 42000.0, 0.85, 2.0, 0.3936, 0.02703 - 42000.0, 0.85, 4.0, 0.6396, 0.04412 - 42000.0, 0.85, 6.0, 0.8855, 0.07186 - 42000.0, 0.85, 8.0, 1.1315, 0.11203 - 42000.0, 0.85, 10.0, 1.3775, 0.16642 - 42000.0, 0.9, -2.0, -0.1047, 0.01955 - 42000.0, 0.9, 0.0, 0.1571, 0.02584 - 42000.0, 0.9, 2.0, 0.4188, 0.04348 - 42000.0, 0.9, 4.0, 0.6806, 0.07461 - 42000.0, 0.9, 6.0, 0.9424, 0.12138 - 42000.0, 0.9, 8.0, 1.2041, 0.18595 - 42000.0, 0.9, 10.0, 1.4659, 0.27045 diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_ground.txt b/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_ground.txt deleted file mode 100644 index 42d962464a..0000000000 --- a/aviary/subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_ground.txt +++ /dev/null @@ -1,797 +0,0 @@ -# GASP-derived aerodynamics data converted from GASP_aero_ground.txt -# Incremental Lift and Drag Coeff. for Ground Effects -# Reference Area = 1370. sqft / Flap Deflection = 10 deg (T.O. Setting) - -Mach, Angle of Attack (deg), Hob, Delta CL, Delta CD - 0.0, -2.0, 0.05, -0.02737, -0.00156 - 0.0, -2.0, 0.1, -0.01769, -0.0012 - 0.0, -2.0, 0.2, -0.01032, -0.00075 - 0.0, -2.0, 0.3, -0.00655, -0.00049 - 0.0, -2.0, 0.4, -0.00431, -0.00033 - 0.0, -2.0, 0.5, -0.00291, -0.00022 - 0.0, -2.0, 0.6, -0.00199, -0.00016 - 0.0, -2.0, 0.8, -0.00097, -8e-05 - 0.0, -2.0, 1.0, -0.00049, -4e-05 - 0.0, -2.0, 1.5, -9e-05, -1e-05 - 0.0, -2.0, 2.0, -1e-05, -0.0 - 0.0, -2.0, 3.0, 0.0, -0.0 - 0.0, 0.0, 0.05, 0.03824, -0.00376 - 0.0, 0.0, 0.1, 0.02525, -0.00269 - 0.0, 0.0, 0.2, 0.01495, -0.00154 - 0.0, 0.0, 0.3, 0.00954, -0.00095 - 0.0, 0.0, 0.4, 0.00628, -0.00062 - 0.0, 0.0, 0.5, 0.00423, -0.00041 - 0.0, 0.0, 0.6, 0.00289, -0.00028 - 0.0, 0.0, 0.8, 0.0014, -0.00014 - 0.0, 0.0, 1.0, 0.00069, -7e-05 - 0.0, 0.0, 1.5, 0.00012, -2e-05 - 0.0, 0.0, 2.0, 1e-05, -0.0 - 0.0, 0.0, 3.0, 0.0, -0.0 - 0.0, 2.0, 0.05, 0.09445, -0.00691 - 0.0, 2.0, 0.1, 0.06394, -0.00476 - 0.0, 2.0, 0.2, 0.03847, -0.00256 - 0.0, 2.0, 0.3, 0.02465, -0.00153 - 0.0, 2.0, 0.4, 0.01626, -0.00097 - 0.0, 2.0, 0.5, 0.01094, -0.00064 - 0.0, 2.0, 0.6, 0.00747, -0.00044 - 0.0, 2.0, 0.8, 0.00358, -0.00021 - 0.0, 2.0, 1.0, 0.00175, -0.00011 - 0.0, 2.0, 1.5, 0.00028, -3e-05 - 0.0, 2.0, 2.0, 1e-05, -1e-05 - 0.0, 2.0, 3.0, 0.0, -0.0 - 0.0, 4.0, 0.05, 0.14127, -0.01115 - 0.0, 4.0, 0.1, 0.09837, -0.00748 - 0.0, 4.0, 0.2, 0.06024, -0.00385 - 0.0, 4.0, 0.3, 0.03878, -0.00224 - 0.0, 4.0, 0.4, 0.02561, -0.0014 - 0.0, 4.0, 0.5, 0.01722, -0.00092 - 0.0, 4.0, 0.6, 0.01173, -0.00062 - 0.0, 4.0, 0.8, 0.00558, -0.00031 - 0.0, 4.0, 1.0, 0.00269, -0.00017 - 0.0, 4.0, 1.5, 0.00038, -4e-05 - 0.0, 4.0, 2.0, 0.0, -2e-05 - 0.0, 4.0, 3.0, 0.0, -0.0 - 0.0, 6.0, 0.05, 0.17869, -0.01661 - 0.0, 6.0, 0.1, 0.12854, -0.01094 - 0.0, 6.0, 0.2, 0.08024, -0.00548 - 0.0, 6.0, 0.3, 0.05193, -0.00312 - 0.0, 6.0, 0.4, 0.03434, -0.00193 - 0.0, 6.0, 0.5, 0.02307, -0.00126 - 0.0, 6.0, 0.6, 0.01568, -0.00085 - 0.0, 6.0, 0.8, 0.00739, -0.00043 - 0.0, 6.0, 1.0, 0.00351, -0.00024 - 0.0, 6.0, 1.5, 0.00043, -7e-05 - 0.0, 6.0, 2.0, 0.0, -2e-05 - 0.0, 6.0, 3.0, 0.0, -0.0 - 0.0, 8.0, 0.05, 0.20671, -0.02343 - 0.0, 8.0, 0.1, 0.15446, -0.01524 - 0.0, 8.0, 0.2, 0.09849, -0.00747 - 0.0, 8.0, 0.3, 0.06411, -0.0042 - 0.0, 8.0, 0.4, 0.04245, -0.00258 - 0.0, 8.0, 0.5, 0.02849, -0.00168 - 0.0, 8.0, 0.6, 0.01931, -0.00114 - 0.0, 8.0, 0.8, 0.00901, -0.00058 - 0.0, 8.0, 1.0, 0.0042, -0.00033 - 0.0, 8.0, 1.5, 0.00042, -0.0001 - 0.0, 8.0, 2.0, 0.0, -3e-05 - 0.0, 8.0, 3.0, 0.0, -0.0 - 0.0, 10.0, 0.05, 0.22534, -0.03174 - 0.0, 10.0, 0.1, 0.17612, -0.02046 - 0.0, 10.0, 0.2, 0.11498, -0.00989 - 0.0, 10.0, 0.3, 0.0753, -0.00552 - 0.0, 10.0, 0.4, 0.04994, -0.00337 - 0.0, 10.0, 0.5, 0.03348, -0.00219 - 0.0, 10.0, 0.6, 0.02263, -0.0015 - 0.0, 10.0, 0.8, 0.01045, -0.00077 - 0.0, 10.0, 1.0, 0.00477, -0.00044 - 0.0, 10.0, 1.5, 0.00035, -0.00015 - 0.0, 10.0, 2.0, 0.0, -4e-05 - 0.0, 10.0, 3.0, 0.0, -0.0 - 0.0, 12.0, 0.05, 0.23457, -0.04167 - 0.0, 12.0, 0.1, 0.19352, -0.02669 - 0.0, 12.0, 0.2, 0.12972, -0.01278 - 0.0, 12.0, 0.3, 0.08552, -0.00709 - 0.0, 12.0, 0.4, 0.0568, -0.00432 - 0.0, 12.0, 0.5, 0.03805, -0.00281 - 0.0, 12.0, 0.6, 0.02564, -0.00193 - 0.0, 12.0, 0.8, 0.01171, -0.00101 - 0.0, 12.0, 1.0, 0.00522, -0.00059 - 0.0, 12.0, 1.5, 0.00023, -0.00021 - 0.0, 12.0, 2.0, 0.0, -5e-05 - 0.0, 12.0, 3.0, 0.0, -0.0 - 0.0, 14.0, 0.05, 0.23441, -0.05335 - 0.0, 14.0, 0.1, 0.20668, -0.034 - 0.0, 14.0, 0.2, 0.1427, -0.01619 - 0.0, 14.0, 0.3, 0.09475, -0.00894 - 0.0, 14.0, 0.4, 0.06303, -0.00545 - 0.0, 14.0, 0.5, 0.04218, -0.00356 - 0.0, 14.0, 0.6, 0.02834, -0.00244 - 0.0, 14.0, 0.8, 0.01277, -0.00129 - 0.0, 14.0, 1.0, 0.00554, -0.00077 - 0.0, 14.0, 1.5, 5e-05, -0.00028 - 0.0, 14.0, 2.0, 0.0, -7e-05 - 0.0, 14.0, 3.0, 0.0, -0.0 - 0.0, 16.0, 0.05, 0.22485, -0.06687 - 0.0, 16.0, 0.1, 0.21557, -0.04249 - 0.0, 16.0, 0.2, 0.15392, -0.02015 - 0.0, 16.0, 0.3, 0.10301, -0.01112 - 0.0, 16.0, 0.4, 0.06865, -0.00678 - 0.0, 16.0, 0.5, 0.04588, -0.00443 - 0.0, 16.0, 0.6, 0.03073, -0.00306 - 0.0, 16.0, 0.8, 0.01366, -0.00164 - 0.0, 16.0, 1.0, 0.00575, -0.00098 - 0.0, 16.0, 1.5, 0.0, -0.00035 - 0.0, 16.0, 2.0, 0.0, -8e-05 - 0.0, 16.0, 3.0, 0.0, -0.0 - 0.0, 18.0, 0.05, 0.15099, -0.08524 - 0.0, 18.0, 0.1, 0.15099, -0.05762 - 0.0, 18.0, 0.2, 0.15099, -0.02604 - 0.0, 18.0, 0.3, 0.11029, -0.01364 - 0.0, 18.0, 0.4, 0.07364, -0.00833 - 0.0, 18.0, 0.5, 0.04916, -0.00546 - 0.0, 18.0, 0.6, 0.0328, -0.00378 - 0.0, 18.0, 0.8, 0.01435, -0.00205 - 0.0, 18.0, 1.0, 0.00583, -0.00124 - 0.0, 18.0, 1.5, 0.0, -0.00042 - 0.0, 18.0, 2.0, 0.0, -9e-05 - 0.0, 18.0, 3.0, 0.0, -0.0 - 0.1, -2.0, 0.05, -0.02752, -0.00188 - 0.1, -2.0, 0.1, -0.01777, -0.00143 - 0.1, -2.0, 0.2, -0.01037, -0.0009 - 0.1, -2.0, 0.3, -0.00658, -0.00059 - 0.1, -2.0, 0.4, -0.00433, -0.00039 - 0.1, -2.0, 0.5, -0.00292, -0.00027 - 0.1, -2.0, 0.6, -0.002, -0.00019 - 0.1, -2.0, 0.8, -0.00097, -9e-05 - 0.1, -2.0, 1.0, -0.00049, -5e-05 - 0.1, -2.0, 1.5, -9e-05, -1e-05 - 0.1, -2.0, 2.0, -1e-05, -0.0 - 0.1, -2.0, 3.0, 0.0, -0.0 - 0.1, 0.0, 0.05, 0.03844, -0.00453 - 0.1, 0.0, 0.1, 0.02537, -0.00323 - 0.1, 0.0, 0.2, 0.01502, -0.00184 - 0.1, 0.0, 0.3, 0.00958, -0.00114 - 0.1, 0.0, 0.4, 0.00631, -0.00074 - 0.1, 0.0, 0.5, 0.00425, -0.0005 - 0.1, 0.0, 0.6, 0.00291, -0.00034 - 0.1, 0.0, 0.8, 0.0014, -0.00017 - 0.1, 0.0, 1.0, 0.0007, -9e-05 - 0.1, 0.0, 1.5, 0.00012, -2e-05 - 0.1, 0.0, 2.0, 1e-05, -1e-05 - 0.1, 0.0, 3.0, 0.0, -0.0 - 0.1, 2.0, 0.05, 0.09493, -0.00831 - 0.1, 2.0, 0.1, 0.06423, -0.00571 - 0.1, 2.0, 0.2, 0.03865, -0.00306 - 0.1, 2.0, 0.3, 0.02476, -0.00183 - 0.1, 2.0, 0.4, 0.01633, -0.00116 - 0.1, 2.0, 0.5, 0.01099, -0.00077 - 0.1, 2.0, 0.6, 0.0075, -0.00052 - 0.1, 2.0, 0.8, 0.0036, -0.00026 - 0.1, 2.0, 1.0, 0.00176, -0.00014 - 0.1, 2.0, 1.5, 0.00028, -3e-05 - 0.1, 2.0, 2.0, 1e-05, -1e-05 - 0.1, 2.0, 3.0, 0.0, -0.0 - 0.1, 4.0, 0.05, 0.14197, -0.0134 - 0.1, 4.0, 0.1, 0.09881, -0.00897 - 0.1, 4.0, 0.2, 0.0605, -0.00462 - 0.1, 4.0, 0.3, 0.03895, -0.00268 - 0.1, 4.0, 0.4, 0.02573, -0.00167 - 0.1, 4.0, 0.5, 0.0173, -0.0011 - 0.1, 4.0, 0.6, 0.01178, -0.00075 - 0.1, 4.0, 0.8, 0.0056, -0.00037 - 0.1, 4.0, 1.0, 0.0027, -0.0002 - 0.1, 4.0, 1.5, 0.00038, -5e-05 - 0.1, 4.0, 2.0, 0.0, -2e-05 - 0.1, 4.0, 3.0, 0.0, -0.0 - 0.1, 6.0, 0.05, 0.17954, -0.01996 - 0.1, 6.0, 0.1, 0.12911, -0.01314 - 0.1, 6.0, 0.2, 0.08059, -0.00657 - 0.1, 6.0, 0.3, 0.05216, -0.00374 - 0.1, 6.0, 0.4, 0.03449, -0.00231 - 0.1, 6.0, 0.5, 0.02317, -0.00151 - 0.1, 6.0, 0.6, 0.01574, -0.00102 - 0.1, 6.0, 0.8, 0.00742, -0.00051 - 0.1, 6.0, 1.0, 0.00352, -0.00028 - 0.1, 6.0, 1.5, 0.00043, -8e-05 - 0.1, 6.0, 2.0, 0.0, -3e-05 - 0.1, 6.0, 3.0, 0.0, -0.0 - 0.1, 8.0, 0.05, 0.20766, -0.02816 - 0.1, 8.0, 0.1, 0.15512, -0.0183 - 0.1, 8.0, 0.2, 0.09891, -0.00896 - 0.1, 8.0, 0.3, 0.06438, -0.00504 - 0.1, 8.0, 0.4, 0.04263, -0.00309 - 0.1, 8.0, 0.5, 0.02861, -0.00201 - 0.1, 8.0, 0.6, 0.01939, -0.00137 - 0.1, 8.0, 0.8, 0.00905, -0.0007 - 0.1, 8.0, 1.0, 0.00422, -0.00039 - 0.1, 8.0, 1.5, 0.00042, -0.00013 - 0.1, 8.0, 2.0, 0.0, -4e-05 - 0.1, 8.0, 3.0, 0.0, -0.0 - 0.1, 10.0, 0.05, 0.22633, -0.03815 - 0.1, 10.0, 0.1, 0.17685, -0.02457 - 0.1, 10.0, 0.2, 0.11546, -0.01187 - 0.1, 10.0, 0.3, 0.07562, -0.00661 - 0.1, 10.0, 0.4, 0.05014, -0.00404 - 0.1, 10.0, 0.5, 0.03362, -0.00263 - 0.1, 10.0, 0.6, 0.02273, -0.00179 - 0.1, 10.0, 0.8, 0.01049, -0.00093 - 0.1, 10.0, 1.0, 0.00479, -0.00053 - 0.1, 10.0, 1.5, 0.00035, -0.00018 - 0.1, 10.0, 2.0, 0.0, -5e-05 - 0.1, 10.0, 3.0, 0.0, -0.0 - 0.1, 12.0, 0.05, 0.23553, -0.05009 - 0.1, 12.0, 0.1, 0.19429, -0.03205 - 0.1, 12.0, 0.2, 0.13024, -0.01534 - 0.1, 12.0, 0.3, 0.08587, -0.0085 - 0.1, 12.0, 0.4, 0.05703, -0.00518 - 0.1, 12.0, 0.5, 0.0382, -0.00337 - 0.1, 12.0, 0.6, 0.02575, -0.00231 - 0.1, 12.0, 0.8, 0.01175, -0.00121 - 0.1, 12.0, 1.0, 0.00524, -0.0007 - 0.1, 12.0, 1.5, 0.00023, -0.00025 - 0.1, 12.0, 2.0, 0.0, -6e-05 - 0.1, 12.0, 3.0, 0.0, -0.0 - 0.1, 14.0, 0.05, 0.23528, -0.06412 - 0.1, 14.0, 0.1, 0.20745, -0.04084 - 0.1, 14.0, 0.2, 0.14326, -0.01943 - 0.1, 14.0, 0.3, 0.09513, -0.01073 - 0.1, 14.0, 0.4, 0.06329, -0.00653 - 0.1, 14.0, 0.5, 0.04235, -0.00427 - 0.1, 14.0, 0.6, 0.02845, -0.00293 - 0.1, 14.0, 0.8, 0.01282, -0.00155 - 0.1, 14.0, 1.0, 0.00556, -0.00092 - 0.1, 14.0, 1.5, 5e-05, -0.00034 - 0.1, 14.0, 2.0, 0.0, -8e-05 - 0.1, 14.0, 3.0, 0.0, -0.0 - 0.1, 16.0, 0.05, 0.22557, -0.08039 - 0.1, 16.0, 0.1, 0.21633, -0.05104 - 0.1, 16.0, 0.2, 0.1545, -0.02419 - 0.1, 16.0, 0.3, 0.10341, -0.01335 - 0.1, 16.0, 0.4, 0.06892, -0.00813 - 0.1, 16.0, 0.5, 0.04606, -0.00532 - 0.1, 16.0, 0.6, 0.03084, -0.00367 - 0.1, 16.0, 0.8, 0.01371, -0.00197 - 0.1, 16.0, 1.0, 0.00577, -0.00118 - 0.1, 16.0, 1.5, 0.0, -0.00043 - 0.1, 16.0, 2.0, 0.0, -0.0001 - 0.1, 16.0, 3.0, 0.0, -0.0 - 0.1, 18.0, 0.05, 0.14509, -0.10285 - 0.1, 18.0, 0.1, 0.14509, -0.06982 - 0.1, 18.0, 0.2, 0.14509, -0.03208 - 0.1, 18.0, 0.3, 0.11071, -0.01638 - 0.1, 18.0, 0.4, 0.07392, -0.00999 - 0.1, 18.0, 0.5, 0.04934, -0.00655 - 0.1, 18.0, 0.6, 0.03292, -0.00454 - 0.1, 18.0, 0.8, 0.0144, -0.00246 - 0.1, 18.0, 1.0, 0.00584, -0.00149 - 0.1, 18.0, 1.5, 0.0, -0.00051 - 0.1, 18.0, 2.0, 0.0, -0.00011 - 0.1, 18.0, 3.0, 0.0, -0.0 - 0.2, -2.0, 0.05, -0.02796, -0.00183 - 0.2, -2.0, 0.1, -0.01803, -0.0014 - 0.2, -2.0, 0.2, -0.01052, -0.00088 - 0.2, -2.0, 0.3, -0.00668, -0.00058 - 0.2, -2.0, 0.4, -0.00439, -0.00039 - 0.2, -2.0, 0.5, -0.00296, -0.00026 - 0.2, -2.0, 0.6, -0.00203, -0.00018 - 0.2, -2.0, 0.8, -0.00099, -9e-05 - 0.2, -2.0, 1.0, -0.0005, -5e-05 - 0.2, -2.0, 1.5, -9e-05, -1e-05 - 0.2, -2.0, 2.0, -2e-05, -0.0 - 0.2, -2.0, 3.0, 0.0, -0.0 - 0.2, 0.0, 0.05, 0.03904, -0.00446 - 0.2, 0.0, 0.1, 0.02574, -0.00318 - 0.2, 0.0, 0.2, 0.01523, -0.00181 - 0.2, 0.0, 0.3, 0.00971, -0.00112 - 0.2, 0.0, 0.4, 0.0064, -0.00073 - 0.2, 0.0, 0.5, 0.00431, -0.00049 - 0.2, 0.0, 0.6, 0.00295, -0.00033 - 0.2, 0.0, 0.8, 0.00142, -0.00016 - 0.2, 0.0, 1.0, 0.00071, -8e-05 - 0.2, 0.0, 1.5, 0.00012, -2e-05 - 0.2, 0.0, 2.0, 1e-05, -1e-05 - 0.2, 0.0, 3.0, 0.0, -0.0 - 0.2, 2.0, 0.05, 0.0964, -0.00821 - 0.2, 2.0, 0.1, 0.06514, -0.00564 - 0.2, 2.0, 0.2, 0.03918, -0.00302 - 0.2, 2.0, 0.3, 0.0251, -0.0018 - 0.2, 2.0, 0.4, 0.01656, -0.00114 - 0.2, 2.0, 0.5, 0.01114, -0.00075 - 0.2, 2.0, 0.6, 0.0076, -0.00051 - 0.2, 2.0, 0.8, 0.00364, -0.00025 - 0.2, 2.0, 1.0, 0.00179, -0.00013 - 0.2, 2.0, 1.5, 0.00028, -3e-05 - 0.2, 2.0, 2.0, 1e-05, -1e-05 - 0.2, 2.0, 3.0, 0.0, -0.0 - 0.2, 4.0, 0.05, 0.1441, -0.01327 - 0.2, 4.0, 0.1, 0.10018, -0.00888 - 0.2, 4.0, 0.2, 0.06132, -0.00456 - 0.2, 4.0, 0.3, 0.03947, -0.00265 - 0.2, 4.0, 0.4, 0.02607, -0.00165 - 0.2, 4.0, 0.5, 0.01753, -0.00108 - 0.2, 4.0, 0.6, 0.01194, -0.00073 - 0.2, 4.0, 0.8, 0.00568, -0.00037 - 0.2, 4.0, 1.0, 0.00274, -0.0002 - 0.2, 4.0, 1.5, 0.00039, -5e-05 - 0.2, 4.0, 2.0, 0.0, -2e-05 - 0.2, 4.0, 3.0, 0.0, -0.0 - 0.2, 6.0, 0.05, 0.18216, -0.01981 - 0.2, 6.0, 0.1, 0.13084, -0.01303 - 0.2, 6.0, 0.2, 0.08165, -0.0065 - 0.2, 6.0, 0.3, 0.05285, -0.0037 - 0.2, 6.0, 0.4, 0.03495, -0.00228 - 0.2, 6.0, 0.5, 0.02348, -0.00149 - 0.2, 6.0, 0.6, 0.01595, -0.00101 - 0.2, 6.0, 0.8, 0.00751, -0.00051 - 0.2, 6.0, 1.0, 0.00356, -0.00028 - 0.2, 6.0, 1.5, 0.00043, -8e-05 - 0.2, 6.0, 2.0, 0.0, -3e-05 - 0.2, 6.0, 3.0, 0.0, -0.0 - 0.2, 8.0, 0.05, 0.21057, -0.02799 - 0.2, 8.0, 0.1, 0.15713, -0.01818 - 0.2, 8.0, 0.2, 0.10019, -0.00889 - 0.2, 8.0, 0.3, 0.06521, -0.00499 - 0.2, 8.0, 0.4, 0.04318, -0.00305 - 0.2, 8.0, 0.5, 0.02898, -0.00199 - 0.2, 8.0, 0.6, 0.01964, -0.00135 - 0.2, 8.0, 0.8, 0.00916, -0.00069 - 0.2, 8.0, 1.0, 0.00427, -0.00039 - 0.2, 8.0, 1.5, 0.00042, -0.00012 - 0.2, 8.0, 2.0, 0.0, -4e-05 - 0.2, 8.0, 3.0, 0.0, -0.0 - 0.2, 10.0, 0.05, 0.22933, -0.03797 - 0.2, 10.0, 0.1, 0.17906, -0.02444 - 0.2, 10.0, 0.2, 0.11692, -0.01178 - 0.2, 10.0, 0.3, 0.07657, -0.00655 - 0.2, 10.0, 0.4, 0.05078, -0.004 - 0.2, 10.0, 0.5, 0.03405, -0.0026 - 0.2, 10.0, 0.6, 0.02301, -0.00178 - 0.2, 10.0, 0.8, 0.01062, -0.00092 - 0.2, 10.0, 1.0, 0.00484, -0.00053 - 0.2, 10.0, 1.5, 0.00035, -0.00018 - 0.2, 10.0, 2.0, 0.0, -5e-05 - 0.2, 10.0, 3.0, 0.0, -0.0 - 0.2, 12.0, 0.05, 0.23844, -0.04991 - 0.2, 12.0, 0.1, 0.19661, -0.03191 - 0.2, 12.0, 0.2, 0.13184, -0.01524 - 0.2, 12.0, 0.3, 0.08693, -0.00843 - 0.2, 12.0, 0.4, 0.05774, -0.00513 - 0.2, 12.0, 0.5, 0.03867, -0.00334 - 0.2, 12.0, 0.6, 0.02606, -0.00229 - 0.2, 12.0, 0.8, 0.01189, -0.0012 - 0.2, 12.0, 1.0, 0.00529, -0.0007 - 0.2, 12.0, 1.5, 0.00022, -0.00025 - 0.2, 12.0, 2.0, 0.0, -6e-05 - 0.2, 12.0, 3.0, 0.0, -0.0 - 0.2, 14.0, 0.05, 0.23791, -0.06395 - 0.2, 14.0, 0.1, 0.2098, -0.0407 - 0.2, 14.0, 0.2, 0.14496, -0.01932 - 0.2, 14.0, 0.3, 0.09628, -0.01066 - 0.2, 14.0, 0.4, 0.06405, -0.00649 - 0.2, 14.0, 0.5, 0.04286, -0.00423 - 0.2, 14.0, 0.6, 0.02879, -0.00291 - 0.2, 14.0, 0.8, 0.01297, -0.00154 - 0.2, 14.0, 1.0, 0.00562, -0.00092 - 0.2, 14.0, 1.5, 4e-05, -0.00034 - 0.2, 14.0, 2.0, 0.0, -8e-05 - 0.2, 14.0, 3.0, 0.0, -0.0 - 0.2, 16.0, 0.05, 0.22773, -0.08024 - 0.2, 16.0, 0.1, 0.21861, -0.05091 - 0.2, 16.0, 0.2, 0.15628, -0.02409 - 0.2, 16.0, 0.3, 0.10463, -0.01327 - 0.2, 16.0, 0.4, 0.06973, -0.00808 - 0.2, 16.0, 0.5, 0.0466, -0.00529 - 0.2, 16.0, 0.6, 0.0312, -0.00365 - 0.2, 16.0, 0.8, 0.01385, -0.00196 - 0.2, 16.0, 1.0, 0.00582, -0.00118 - 0.2, 16.0, 1.5, 0.0, -0.00042 - 0.2, 16.0, 2.0, 0.0, -0.0001 - 0.2, 16.0, 3.0, 0.0, -0.0 - 0.2, 18.0, 0.05, 0.127, -0.1039 - 0.2, 18.0, 0.1, 0.127, -0.07147 - 0.2, 18.0, 0.2, 0.127, -0.03443 - 0.2, 18.0, 0.3, 0.11197, -0.0163 - 0.2, 18.0, 0.4, 0.07477, -0.00994 - 0.2, 18.0, 0.5, 0.0499, -0.00652 - 0.2, 18.0, 0.6, 0.03329, -0.00452 - 0.2, 18.0, 0.8, 0.01455, -0.00245 - 0.2, 18.0, 1.0, 0.00589, -0.00149 - 0.2, 18.0, 1.5, 0.0, -0.00051 - 0.2, 18.0, 2.0, 0.0, -0.00011 - 0.2, 18.0, 3.0, 0.0, -0.0 - 0.3, -2.0, 0.05, -0.02873, -0.0018 - 0.3, -2.0, 0.1, -0.01849, -0.00137 - 0.3, -2.0, 0.2, -0.01077, -0.00086 - 0.3, -2.0, 0.3, -0.00684, -0.00056 - 0.3, -2.0, 0.4, -0.0045, -0.00038 - 0.3, -2.0, 0.5, -0.00303, -0.00026 - 0.3, -2.0, 0.6, -0.00208, -0.00018 - 0.3, -2.0, 0.8, -0.00101, -9e-05 - 0.3, -2.0, 1.0, -0.00051, -5e-05 - 0.3, -2.0, 1.5, -0.0001, -1e-05 - 0.3, -2.0, 2.0, -2e-05, -0.0 - 0.3, -2.0, 3.0, 0.0, -0.0 - 0.3, 0.0, 0.05, 0.0401, -0.00442 - 0.3, 0.0, 0.1, 0.02638, -0.00316 - 0.3, 0.0, 0.2, 0.0156, -0.0018 - 0.3, 0.0, 0.3, 0.00994, -0.00111 - 0.3, 0.0, 0.4, 0.00655, -0.00072 - 0.3, 0.0, 0.5, 0.00441, -0.00048 - 0.3, 0.0, 0.6, 0.00302, -0.00033 - 0.3, 0.0, 0.8, 0.00146, -0.00016 - 0.3, 0.0, 1.0, 0.00072, -8e-05 - 0.3, 0.0, 1.5, 0.00013, -2e-05 - 0.3, 0.0, 2.0, 1e-05, -1e-05 - 0.3, 0.0, 3.0, 0.0, -0.0 - 0.3, 2.0, 0.05, 0.09895, -0.0082 - 0.3, 2.0, 0.1, 0.06672, -0.00563 - 0.3, 2.0, 0.2, 0.04009, -0.00301 - 0.3, 2.0, 0.3, 0.02568, -0.00179 - 0.3, 2.0, 0.4, 0.01694, -0.00113 - 0.3, 2.0, 0.5, 0.0114, -0.00075 - 0.3, 2.0, 0.6, 0.00778, -0.00051 - 0.3, 2.0, 0.8, 0.00373, -0.00025 - 0.3, 2.0, 1.0, 0.00183, -0.00013 - 0.3, 2.0, 1.5, 0.00029, -3e-05 - 0.3, 2.0, 2.0, 1e-05, -1e-05 - 0.3, 2.0, 3.0, 0.0, -0.0 - 0.3, 4.0, 0.05, 0.14781, -0.01332 - 0.3, 4.0, 0.1, 0.10254, -0.00891 - 0.3, 4.0, 0.2, 0.06273, -0.00456 - 0.3, 4.0, 0.3, 0.04038, -0.00264 - 0.3, 4.0, 0.4, 0.02667, -0.00164 - 0.3, 4.0, 0.5, 0.01793, -0.00108 - 0.3, 4.0, 0.6, 0.01221, -0.00073 - 0.3, 4.0, 0.8, 0.0058, -0.00036 - 0.3, 4.0, 1.0, 0.0028, -0.0002 - 0.3, 4.0, 1.5, 0.00039, -5e-05 - 0.3, 4.0, 2.0, 0.0, -2e-05 - 0.3, 4.0, 3.0, 0.0, -0.0 - 0.3, 6.0, 0.05, 0.18669, -0.01995 - 0.3, 6.0, 0.1, 0.13383, -0.0131 - 0.3, 6.0, 0.2, 0.08349, -0.00651 - 0.3, 6.0, 0.3, 0.05403, -0.0037 - 0.3, 6.0, 0.4, 0.03573, -0.00228 - 0.3, 6.0, 0.5, 0.024, -0.00148 - 0.3, 6.0, 0.6, 0.0163, -0.00101 - 0.3, 6.0, 0.8, 0.00768, -0.00051 - 0.3, 6.0, 1.0, 0.00364, -0.00028 - 0.3, 6.0, 1.5, 0.00044, -8e-05 - 0.3, 6.0, 2.0, 0.0, -3e-05 - 0.3, 6.0, 3.0, 0.0, -0.0 - 0.3, 8.0, 0.05, 0.21559, -0.02826 - 0.3, 8.0, 0.1, 0.16061, -0.01832 - 0.3, 8.0, 0.2, 0.10239, -0.00893 - 0.3, 8.0, 0.3, 0.06665, -0.005 - 0.3, 8.0, 0.4, 0.04413, -0.00306 - 0.3, 8.0, 0.5, 0.02962, -0.00199 - 0.3, 8.0, 0.6, 0.02007, -0.00135 - 0.3, 8.0, 0.8, 0.00936, -0.00069 - 0.3, 8.0, 1.0, 0.00435, -0.00039 - 0.3, 8.0, 1.5, 0.00043, -0.00013 - 0.3, 8.0, 2.0, 0.0, -4e-05 - 0.3, 8.0, 3.0, 0.0, -0.0 - 0.3, 10.0, 0.05, 0.2345, -0.03841 - 0.3, 10.0, 0.1, 0.18286, -0.02469 - 0.3, 10.0, 0.2, 0.11942, -0.01186 - 0.3, 10.0, 0.3, 0.07822, -0.00658 - 0.3, 10.0, 0.4, 0.05187, -0.00401 - 0.3, 10.0, 0.5, 0.03478, -0.00261 - 0.3, 10.0, 0.6, 0.0235, -0.00178 - 0.3, 10.0, 0.8, 0.01084, -0.00092 - 0.3, 10.0, 1.0, 0.00494, -0.00053 - 0.3, 10.0, 1.5, 0.00035, -0.00018 - 0.3, 10.0, 2.0, 0.0, -5e-05 - 0.3, 10.0, 3.0, 0.0, -0.0 - 0.3, 12.0, 0.05, 0.24343, -0.05058 - 0.3, 12.0, 0.1, 0.20059, -0.0323 - 0.3, 12.0, 0.2, 0.13459, -0.01537 - 0.3, 12.0, 0.3, 0.08876, -0.00849 - 0.3, 12.0, 0.4, 0.05895, -0.00516 - 0.3, 12.0, 0.5, 0.03948, -0.00336 - 0.3, 12.0, 0.6, 0.0266, -0.0023 - 0.3, 12.0, 0.8, 0.01213, -0.00121 - 0.3, 12.0, 1.0, 0.00539, -0.00071 - 0.3, 12.0, 1.5, 0.00022, -0.00026 - 0.3, 12.0, 2.0, 0.0, -6e-05 - 0.3, 12.0, 3.0, 0.0, -0.0 - 0.3, 14.0, 0.05, 0.24237, -0.06491 - 0.3, 14.0, 0.1, 0.2138, -0.04126 - 0.3, 14.0, 0.2, 0.14788, -0.01953 - 0.3, 14.0, 0.3, 0.09825, -0.01075 - 0.3, 14.0, 0.4, 0.06537, -0.00653 - 0.3, 14.0, 0.5, 0.04373, -0.00426 - 0.3, 14.0, 0.6, 0.02937, -0.00293 - 0.3, 14.0, 0.8, 0.01322, -0.00156 - 0.3, 14.0, 1.0, 0.00571, -0.00093 - 0.3, 14.0, 1.5, 2e-05, -0.00035 - 0.3, 14.0, 2.0, 0.0, -8e-05 - 0.3, 14.0, 3.0, 0.0, -0.0 - 0.3, 16.0, 0.05, 0.23133, -0.08156 - 0.3, 16.0, 0.1, 0.22249, -0.05169 - 0.3, 16.0, 0.2, 0.15932, -0.02439 - 0.3, 16.0, 0.3, 0.10671, -0.01341 - 0.3, 16.0, 0.4, 0.07112, -0.00815 - 0.3, 16.0, 0.5, 0.04752, -0.00533 - 0.3, 16.0, 0.6, 0.03181, -0.00368 - 0.3, 16.0, 0.8, 0.01411, -0.00198 - 0.3, 16.0, 1.0, 0.00591, -0.00119 - 0.3, 16.0, 1.5, 0.0, -0.00043 - 0.3, 16.0, 2.0, 0.0, -0.0001 - 0.3, 16.0, 3.0, 0.0, -0.0 - 0.3, 18.0, 0.05, 0.09556, -0.10771 - 0.3, 18.0, 0.1, 0.09556, -0.07569 - 0.3, 18.0, 0.2, 0.09556, -0.03911 - 0.3, 18.0, 0.3, 0.09556, -0.01911 - 0.3, 18.0, 0.4, 0.07621, -0.01005 - 0.3, 18.0, 0.5, 0.05086, -0.00659 - 0.3, 18.0, 0.6, 0.03391, -0.00457 - 0.3, 18.0, 0.8, 0.0148, -0.00248 - 0.3, 18.0, 1.0, 0.00597, -0.00151 - 0.3, 18.0, 1.5, 0.0, -0.00052 - 0.3, 18.0, 2.0, 0.0, -0.00012 - 0.3, 18.0, 3.0, 0.0, -0.0 - 0.4, -2.0, 0.05, -0.02989, -0.00175 - 0.4, -2.0, 0.1, -0.01917, -0.00134 - 0.4, -2.0, 0.2, -0.01115, -0.00084 - 0.4, -2.0, 0.3, -0.00707, -0.00055 - 0.4, -2.0, 0.4, -0.00466, -0.00037 - 0.4, -2.0, 0.5, -0.00314, -0.00025 - 0.4, -2.0, 0.6, -0.00215, -0.00018 - 0.4, -2.0, 0.8, -0.00105, -9e-05 - 0.4, -2.0, 1.0, -0.00053, -4e-05 - 0.4, -2.0, 1.5, -0.0001, -1e-05 - 0.4, -2.0, 2.0, -2e-05, -0.0 - 0.4, -2.0, 3.0, 0.0, -0.0 - 0.4, 0.0, 0.05, 0.04169, -0.00441 - 0.4, 0.0, 0.1, 0.02732, -0.00314 - 0.4, 0.0, 0.2, 0.01613, -0.00179 - 0.4, 0.0, 0.3, 0.01028, -0.0011 - 0.4, 0.0, 0.4, 0.00677, -0.00072 - 0.4, 0.0, 0.5, 0.00456, -0.00048 - 0.4, 0.0, 0.6, 0.00312, -0.00033 - 0.4, 0.0, 0.8, 0.00151, -0.00016 - 0.4, 0.0, 1.0, 0.00075, -8e-05 - 0.4, 0.0, 1.5, 0.00013, -2e-05 - 0.4, 0.0, 2.0, 1e-05, -0.0 - 0.4, 0.0, 3.0, 0.0, -0.0 - 0.4, 2.0, 0.05, 0.10277, -0.00826 - 0.4, 2.0, 0.1, 0.06906, -0.00566 - 0.4, 2.0, 0.2, 0.04145, -0.00301 - 0.4, 2.0, 0.3, 0.02654, -0.00179 - 0.4, 2.0, 0.4, 0.01751, -0.00113 - 0.4, 2.0, 0.5, 0.01178, -0.00075 - 0.4, 2.0, 0.6, 0.00804, -0.00051 - 0.4, 2.0, 0.8, 0.00385, -0.00025 - 0.4, 2.0, 1.0, 0.00189, -0.00013 - 0.4, 2.0, 1.5, 0.0003, -3e-05 - 0.4, 2.0, 2.0, 1e-05, -1e-05 - 0.4, 2.0, 3.0, 0.0, -0.0 - 0.4, 4.0, 0.05, 0.15335, -0.01349 - 0.4, 4.0, 0.1, 0.10603, -0.009 - 0.4, 4.0, 0.2, 0.06481, -0.00459 - 0.4, 4.0, 0.3, 0.04171, -0.00265 - 0.4, 4.0, 0.4, 0.02755, -0.00165 - 0.4, 4.0, 0.5, 0.01852, -0.00108 - 0.4, 4.0, 0.6, 0.01261, -0.00073 - 0.4, 4.0, 0.8, 0.00599, -0.00036 - 0.4, 4.0, 1.0, 0.00289, -0.0002 - 0.4, 4.0, 1.5, 0.00041, -5e-05 - 0.4, 4.0, 2.0, 0.0, -2e-05 - 0.4, 4.0, 3.0, 0.0, -0.0 - 0.4, 6.0, 0.05, 0.19343, -0.02029 - 0.4, 6.0, 0.1, 0.13826, -0.0133 - 0.4, 6.0, 0.2, 0.08621, -0.00658 - 0.4, 6.0, 0.3, 0.05579, -0.00372 - 0.4, 6.0, 0.4, 0.03689, -0.00229 - 0.4, 6.0, 0.5, 0.02478, -0.00149 - 0.4, 6.0, 0.6, 0.01683, -0.00101 - 0.4, 6.0, 0.8, 0.00792, -0.00051 - 0.4, 6.0, 1.0, 0.00375, -0.00028 - 0.4, 6.0, 1.5, 0.00045, -9e-05 - 0.4, 6.0, 2.0, 0.0, -3e-05 - 0.4, 6.0, 3.0, 0.0, -0.0 - 0.4, 8.0, 0.05, 0.22301, -0.02886 - 0.4, 8.0, 0.1, 0.16572, -0.01868 - 0.4, 8.0, 0.2, 0.10564, -0.00905 - 0.4, 8.0, 0.3, 0.06877, -0.00505 - 0.4, 8.0, 0.4, 0.04553, -0.00308 - 0.4, 8.0, 0.5, 0.03055, -0.002 - 0.4, 8.0, 0.6, 0.0207, -0.00136 - 0.4, 8.0, 0.8, 0.00965, -0.0007 - 0.4, 8.0, 1.0, 0.00448, -0.00039 - 0.4, 8.0, 1.5, 0.00043, -0.00013 - 0.4, 8.0, 2.0, 0.0, -4e-05 - 0.4, 8.0, 3.0, 0.0, -0.0 - 0.4, 10.0, 0.05, 0.2421, -0.03936 - 0.4, 10.0, 0.1, 0.18844, -0.02524 - 0.4, 10.0, 0.2, 0.12311, -0.01207 - 0.4, 10.0, 0.3, 0.08065, -0.00667 - 0.4, 10.0, 0.4, 0.05348, -0.00405 - 0.4, 10.0, 0.5, 0.03585, -0.00263 - 0.4, 10.0, 0.6, 0.02422, -0.0018 - 0.4, 10.0, 0.8, 0.01117, -0.00093 - 0.4, 10.0, 1.0, 0.00508, -0.00054 - 0.4, 10.0, 1.5, 0.00035, -0.00019 - 0.4, 10.0, 2.0, 0.0, -5e-05 - 0.4, 10.0, 3.0, 0.0, -0.0 - 0.4, 12.0, 0.05, 0.25068, -0.05196 - 0.4, 12.0, 0.1, 0.2064, -0.03312 - 0.4, 12.0, 0.2, 0.13861, -0.01569 - 0.4, 12.0, 0.3, 0.09145, -0.00863 - 0.4, 12.0, 0.4, 0.06074, -0.00524 - 0.4, 12.0, 0.5, 0.04067, -0.00341 - 0.4, 12.0, 0.6, 0.0274, -0.00233 - 0.4, 12.0, 0.8, 0.01247, -0.00123 - 0.4, 12.0, 1.0, 0.00553, -0.00072 - 0.4, 12.0, 1.5, 0.00021, -0.00027 - 0.4, 12.0, 2.0, 0.0, -7e-05 - 0.4, 12.0, 3.0, 0.0, -0.0 - 0.4, 14.0, 0.05, 0.24877, -0.06684 - 0.4, 14.0, 0.1, 0.2196, -0.04242 - 0.4, 14.0, 0.2, 0.15216, -0.01999 - 0.4, 14.0, 0.3, 0.10114, -0.01097 - 0.4, 14.0, 0.4, 0.06729, -0.00665 - 0.4, 14.0, 0.5, 0.04501, -0.00434 - 0.4, 14.0, 0.6, 0.03022, -0.00298 - 0.4, 14.0, 0.8, 0.01358, -0.00159 - 0.4, 14.0, 1.0, 0.00585, -0.00095 - 0.4, 14.0, 1.5, 0.0, -0.00036 - 0.4, 14.0, 2.0, 0.0, -8e-05 - 0.4, 14.0, 3.0, 0.0, -0.0 - 0.4, 16.0, 0.05, 0.23636, -0.08415 - 0.4, 16.0, 0.1, 0.22805, -0.05325 - 0.4, 16.0, 0.2, 0.16374, -0.02502 - 0.4, 16.0, 0.3, 0.10975, -0.01371 - 0.4, 16.0, 0.4, 0.07316, -0.00833 - 0.4, 16.0, 0.5, 0.04887, -0.00544 - 0.4, 16.0, 0.6, 0.03269, -0.00376 - 0.4, 16.0, 0.8, 0.01447, -0.00203 - 0.4, 16.0, 1.0, 0.00603, -0.00123 - 0.4, 16.0, 1.5, 0.0, -0.00044 - 0.4, 16.0, 2.0, 0.0, -0.0001 - 0.4, 16.0, 3.0, 0.0, -0.0 - 0.4, 18.0, 0.05, 0.04855, -0.11421 - 0.4, 18.0, 0.1, 0.04855, -0.08256 - 0.4, 18.0, 0.2, 0.04855, -0.0464 - 0.4, 18.0, 0.3, 0.04855, -0.02663 - 0.4, 18.0, 0.4, 0.04855, -0.01478 - 0.4, 18.0, 0.5, 0.04855, -0.00733 - 0.4, 18.0, 0.6, 0.03482, -0.00468 - 0.4, 18.0, 0.8, 0.01516, -0.00255 - 0.4, 18.0, 1.0, 0.00608, -0.00157 - 0.4, 18.0, 1.5, 0.0, -0.00053 - 0.4, 18.0, 2.0, 0.0, -0.00012 - 0.4, 18.0, 3.0, 0.0, -0.0 - 0.5, -2.0, 0.05, -0.03154, -0.0017 - 0.5, -2.0, 0.1, -0.02012, -0.0013 - 0.5, -2.0, 0.2, -0.01168, -0.00082 - 0.5, -2.0, 0.3, -0.00741, -0.00054 - 0.5, -2.0, 0.4, -0.00487, -0.00036 - 0.5, -2.0, 0.5, -0.00328, -0.00025 - 0.5, -2.0, 0.6, -0.00225, -0.00017 - 0.5, -2.0, 0.8, -0.0011, -8e-05 - 0.5, -2.0, 1.0, -0.00055, -4e-05 - 0.5, -2.0, 1.5, -0.00011, -1e-05 - 0.5, -2.0, 2.0, -2e-05, -0.0 - 0.5, -2.0, 3.0, 0.0, -0.0 - 0.5, 0.0, 0.05, 0.04393, -0.00441 - 0.5, 0.0, 0.1, 0.02865, -0.00314 - 0.5, 0.0, 0.2, 0.01689, -0.00178 - 0.5, 0.0, 0.3, 0.01076, -0.0011 - 0.5, 0.0, 0.4, 0.00709, -0.00071 - 0.5, 0.0, 0.5, 0.00477, -0.00048 - 0.5, 0.0, 0.6, 0.00326, -0.00033 - 0.5, 0.0, 0.8, 0.00158, -0.00016 - 0.5, 0.0, 1.0, 0.00078, -8e-05 - 0.5, 0.0, 1.5, 0.00014, -2e-05 - 0.5, 0.0, 2.0, 1e-05, -0.0 - 0.5, 0.0, 3.0, 0.0, -0.0 - 0.5, 2.0, 0.05, 0.10816, -0.00836 - 0.5, 2.0, 0.1, 0.07233, -0.00572 - 0.5, 2.0, 0.2, 0.04336, -0.00303 - 0.5, 2.0, 0.3, 0.02775, -0.00179 - 0.5, 2.0, 0.4, 0.0183, -0.00113 - 0.5, 2.0, 0.5, 0.01231, -0.00075 - 0.5, 2.0, 0.6, 0.0084, -0.00051 - 0.5, 2.0, 0.8, 0.00403, -0.00025 - 0.5, 2.0, 1.0, 0.00197, -0.00013 - 0.5, 2.0, 1.5, 0.00031, -3e-05 - 0.5, 2.0, 2.0, 1e-05, -1e-05 - 0.5, 2.0, 3.0, 0.0, -0.0 - 0.5, 4.0, 0.05, 0.16113, -0.01378 - 0.5, 4.0, 0.1, 0.11091, -0.00918 - 0.5, 4.0, 0.2, 0.06772, -0.00465 - 0.5, 4.0, 0.3, 0.04357, -0.00267 - 0.5, 4.0, 0.4, 0.02877, -0.00166 - 0.5, 4.0, 0.5, 0.01934, -0.00108 - 0.5, 4.0, 0.6, 0.01317, -0.00073 - 0.5, 4.0, 0.8, 0.00626, -0.00037 - 0.5, 4.0, 1.0, 0.00301, -0.0002 - 0.5, 4.0, 1.5, 0.00042, -6e-05 - 0.5, 4.0, 2.0, 0.0, -2e-05 - 0.5, 4.0, 3.0, 0.0, -0.0 - 0.5, 6.0, 0.05, 0.20286, -0.02087 - 0.5, 6.0, 0.1, 0.1444, -0.01365 - 0.5, 6.0, 0.2, 0.08998, -0.00671 - 0.5, 6.0, 0.3, 0.05822, -0.00377 - 0.5, 6.0, 0.4, 0.0385, -0.00231 - 0.5, 6.0, 0.5, 0.02585, -0.0015 - 0.5, 6.0, 0.6, 0.01756, -0.00102 - 0.5, 6.0, 0.8, 0.00826, -0.00052 - 0.5, 6.0, 1.0, 0.00391, -0.00029 - 0.5, 6.0, 1.5, 0.00046, -9e-05 - 0.5, 6.0, 2.0, 0.0, -3e-05 - 0.5, 6.0, 3.0, 0.0, -0.0 - 0.5, 8.0, 0.05, 0.23333, -0.02984 - 0.5, 8.0, 0.1, 0.17279, -0.01926 - 0.5, 8.0, 0.2, 0.11014, -0.00927 - 0.5, 8.0, 0.3, 0.0717, -0.00515 - 0.5, 8.0, 0.4, 0.04748, -0.00313 - 0.5, 8.0, 0.5, 0.03185, -0.00203 - 0.5, 8.0, 0.6, 0.02157, -0.00138 - 0.5, 8.0, 0.8, 0.01005, -0.00071 - 0.5, 8.0, 1.0, 0.00466, -0.0004 - 0.5, 8.0, 1.5, 0.00044, -0.00013 - 0.5, 8.0, 2.0, 0.0, -4e-05 - 0.5, 8.0, 3.0, 0.0, -0.0 - 0.5, 10.0, 0.05, 0.25256, -0.04087 - 0.5, 10.0, 0.1, 0.19609, -0.02615 - 0.5, 10.0, 0.2, 0.12819, -0.01242 - 0.5, 10.0, 0.3, 0.08401, -0.00683 - 0.5, 10.0, 0.4, 0.05571, -0.00414 - 0.5, 10.0, 0.5, 0.03734, -0.00269 - 0.5, 10.0, 0.6, 0.02522, -0.00183 - 0.5, 10.0, 0.8, 0.01161, -0.00096 - 0.5, 10.0, 1.0, 0.00526, -0.00056 - 0.5, 10.0, 1.5, 0.00035, -0.0002 - 0.5, 10.0, 2.0, 0.0, -5e-05 - 0.5, 10.0, 3.0, 0.0, -0.0 - 0.5, 12.0, 0.05, 0.26054, -0.05417 - 0.5, 12.0, 0.1, 0.2143, -0.03444 - 0.5, 12.0, 0.2, 0.14414, -0.01622 - 0.5, 12.0, 0.3, 0.09514, -0.00888 - 0.5, 12.0, 0.4, 0.06319, -0.00537 - 0.5, 12.0, 0.5, 0.04231, -0.00349 - 0.5, 12.0, 0.6, 0.02848, -0.00239 - 0.5, 12.0, 0.8, 0.01295, -0.00127 - 0.5, 12.0, 1.0, 0.00572, -0.00075 - 0.5, 12.0, 1.5, 0.00019, -0.00028 - 0.5, 12.0, 2.0, 0.0, -7e-05 - 0.5, 12.0, 3.0, 0.0, -0.0 - 0.5, 14.0, 0.05, 0.25727, -0.0699 - 0.5, 14.0, 0.1, 0.2274, -0.04426 - 0.5, 14.0, 0.2, 0.15799, -0.02074 - 0.5, 14.0, 0.3, 0.1051, -0.01133 - 0.5, 14.0, 0.4, 0.06994, -0.00686 - 0.5, 14.0, 0.5, 0.04677, -0.00447 - 0.5, 14.0, 0.6, 0.03138, -0.00308 - 0.5, 14.0, 0.8, 0.01406, -0.00165 - 0.5, 14.0, 1.0, 0.00603, -0.00099 - 0.5, 14.0, 1.5, 0.0, -0.00038 - 0.5, 14.0, 2.0, 0.0, -9e-05 - 0.5, 14.0, 3.0, 0.0, -0.0 - 0.5, 16.0, 0.05, 0.17703, -0.09217 - 0.5, 16.0, 0.1, 0.17703, -0.0609 - 0.5, 16.0, 0.2, 0.16973, -0.02605 - 0.5, 16.0, 0.3, 0.11389, -0.01423 - 0.5, 16.0, 0.4, 0.07593, -0.00862 - 0.5, 16.0, 0.5, 0.05071, -0.00563 - 0.5, 16.0, 0.6, 0.0339, -0.0039 - 0.5, 16.0, 0.8, 0.01496, -0.00211 - 0.5, 16.0, 1.0, 0.0062, -0.00129 - 0.5, 16.0, 1.5, 0.0, -0.00047 - 0.5, 16.0, 2.0, 0.0, -0.0001 - 0.5, 16.0, 3.0, 0.0, -0.0 - 0.5, 18.0, 0.05, 0.0, -0.12093 - 0.5, 18.0, 0.1, 0.0, -0.08966 - 0.5, 18.0, 0.2, 0.0, -0.05394 - 0.5, 18.0, 0.3, 0.0, -0.03441 - 0.5, 18.0, 0.4, 0.0, -0.02271 - 0.5, 18.0, 0.5, 0.0, -0.01535 - 0.5, 18.0, 0.6, 0.0, -0.01055 - 0.5, 18.0, 0.8, 0.0, -0.00519 - 0.5, 18.0, 1.0, 0.0, -0.00265 - 0.5, 18.0, 1.5, 0.0, -0.00055 - 0.5, 18.0, 2.0, 0.0, -0.00012 - 0.5, 18.0, 3.0, 0.0, -0.0 diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py index e9e174aede..7325270bcd 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/Cl_max.py @@ -5,257 +5,262 @@ class CLmaxCalculation(om.ExplicitComponent): - """ - CL_max calculation for GASP-based aerodynamics - """ + """CL_max calculation for GASP-based aerodynamics.""" def setup(self): - # inputs # from component 1 outputs self.add_input( - "VLAM8", + 'VLAM8', val=0.74444322, units='unitless', - desc="VLAM8: sensitivity of flap clean wing maximum lift coefficient to wing sweep angle", - ) - self.add_input( - Dynamic.Mission.SPEED_OF_SOUND, - val=1118.21948771, - units="ft/s", - desc="SA: speed of sound at sea level", + desc='VLAM8: sensitivity of flap clean wing maximum lift coefficient to wing sweep angle', ) + add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, desc='INGASP.SA', units='ft/s') # from component 3 outputs - add_aviary_input(self, Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, val=1.5) + add_aviary_input(self, Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, units='unitless') self.add_input( - "VLAM1", + 'VLAM1', val=0.97217, units='unitless', - desc="VLAM1: sensitivity of clean wing maximum lift coefficient to wing aspect ratio", + desc='VLAM1: sensitivity of clean wing maximum lift coefficient to wing aspect ratio', ) self.add_input( - "VLAM2", + 'VLAM2', val=1.09948, units='unitless', - desc="VLAM2: sensitivity of clean wing maximum lift coefficient to wing thickness to chord ratio", + desc='VLAM2: sensitivity of clean wing maximum lift coefficient to wing thickness to chord ratio', ) self.add_input( - "VLAM3", + 'VLAM3', val=0.97217, units='unitless', - desc="VLAM3: sensitivity of flap clean wing maximum lift coefficient to aspect ratio", + desc='VLAM3: sensitivity of flap clean wing maximum lift coefficient to aspect ratio', ) self.add_input( - "VLAM4", + 'VLAM4', val=1.25725, units='unitless', - desc="VLAM4: sensitivity of flap clean wing maximum lift coefficient slope to wing thickness", + desc='VLAM4: sensitivity of flap clean wing maximum lift coefficient slope to wing thickness', ) self.add_input( - "VLAM5", + 'VLAM5', val=1.0, units='unitless', - desc="VLAM5: sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio", + desc='VLAM5: sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio', ) self.add_input( - "VLAM6", + 'VLAM6', val=1.0, units='unitless', - desc="VLAM6: sensitivity of flap clean wing maximum lift coefficient to wing flap deflection", + desc='VLAM6: sensitivity of flap clean wing maximum lift coefficient to wing flap deflection', ) self.add_input( - "VLAM7", + 'VLAM7', val=0.735, units='unitless', - desc="VLAM7: sensitivity of flap clean wing maximum lift coefficient to wing flap span", + desc='VLAM7: sensitivity of flap clean wing maximum lift coefficient to wing flap span', ) self.add_input( - "VLAM13", val=1.03512, units='unitless', desc="VLAM13: reynolds number correction factor" + 'VLAM13', + val=1.03512, + units='unitless', + desc='VLAM13: reynolds number correction factor', ) self.add_input( - "VLAM14", val=0.99124, units='unitless', desc="VLAM14: mach number correction factor " + 'VLAM14', + val=0.99124, + units='unitless', + desc='VLAM14: Mach number correction factor ', ) # other inputs - add_aviary_input(self, Aircraft.Wing.LOADING, val=128) + add_aviary_input(self, Aircraft.Design.WING_LOADING, units='lbf/ft**2') - self.add_input( - Dynamic.Mission.STATIC_PRESSURE, val=(14.696 * 144), units="lbf/ft**2", desc="P0: static pressure" + add_aviary_input( + self, + Dynamic.Atmosphere.STATIC_PRESSURE, + units='lbf/ft**2', + desc='INGASP.P0', ) - add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, val=12.61) + add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.Wing.MAX_LIFT_REF, val=1.15) - add_aviary_input(self, Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, val=0.93) + add_aviary_input(self, Aircraft.Wing.MAX_LIFT_REF, units='unitless') + add_aviary_input(self, Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, units='unitless') self.add_input( - "VLAM9", + 'VLAM9', val=0.9975, units='unitless', - desc="VLAM9: sensitivity of slat clean wing maximum lift coefficient to slat chord", + desc='VLAM9: sensitivity of slat clean wing maximum lift coefficient to slat chord', ) self.add_input( - "VLAM10", + 'VLAM10', val=0.74, units='unitless', - desc="VLAM10: sensitivity of slat clean wing maximum lift coefficient to slat deflection angle", + desc='VLAM10: sensitivity of slat clean wing maximum lift coefficient to slat deflection angle', ) self.add_input( - "VLAM11", + 'VLAM11', val=0.84232, units='unitless', - desc="VLAM11: sensitivity of slat clean wing mazimum lift coefficient to slat span", + desc='VLAM11: sensitivity of slat clean wing mazimum lift coefficient to slat span', ) self.add_input( - "VLAM12", + 'VLAM12', val=0.79208, units='unitless', - desc="VLAM12: sensitivity of slat clean wing maximum lift coefficient to leading edge sweepback", + desc='VLAM12: sensitivity of slat clean wing maximum lift coefficient to leading edge sweepback', ) - self.add_input("fus_lift", val=0.05498, units='unitless', - desc="DELCLF: fuselage lift increment") self.add_input( - Dynamic.Mission.KINEMATIC_VISCOSITY, - val=0.15723e-03, - units="ft**2/s", - desc="XKV: kinematic viscosity", + 'fus_lift', + val=0.05498, + units='unitless', + desc='DELCLF: fuselage lift increment', ) - self.add_input( - Dynamic.Mission.TEMPERATURE, - val=518.67, - units="degR", - desc="T0: static temperature of air cross wing", + add_aviary_input( + self, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + val=0.15723e-03, + desc='INGASP.XKV', ) + add_aviary_input(self, Dynamic.Atmosphere.TEMPERATURE, units='degR', desc='INGASP.T0') # outputs - self.add_output("CL_max", val=2.8155, - desc="CLMAX: maximum lift coefficient", units="unitless") - self.add_output(Dynamic.Mission.MACH, val=0.17522, - units='unitless', desc="SMN: mach number") - self.add_output("reynolds", val=157.1111, units='unitless', - desc="RNW: reynolds number") + self.add_output( + 'CL_max', + val=2.8155, + desc='CLMAX: maximum lift coefficient', + units='unitless', + ) + self.add_output( + Dynamic.Atmosphere.MACH, + val=0.17522, + units='unitless', + desc='SMN: Mach number', + ) + self.add_output('reynolds', val=157.1111, units='unitless', desc='RNW: reynolds number') def setup_partials(self): - self.declare_partials( - "CL_max", + 'CL_max', [ Aircraft.Wing.MAX_LIFT_REF, - "VLAM1", - "VLAM2", + 'VLAM1', + 'VLAM2', Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, - "VLAM3", - "VLAM4", - "VLAM5", - "VLAM6", - "VLAM7", - "VLAM8", + 'VLAM3', + 'VLAM4', + 'VLAM5', + 'VLAM6', + 'VLAM7', + 'VLAM8', Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, - "VLAM9", - "VLAM10", - "VLAM11", - "VLAM12", - "VLAM13", - "VLAM14", - "fus_lift", + 'VLAM9', + 'VLAM10', + 'VLAM11', + 'VLAM12', + 'VLAM13', + 'VLAM14', + 'fus_lift', ], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, [ - Aircraft.Wing.LOADING, - Dynamic.Mission.STATIC_PRESSURE, + Aircraft.Design.WING_LOADING, + Dynamic.Atmosphere.STATIC_PRESSURE, Aircraft.Wing.MAX_LIFT_REF, - "VLAM1", - "VLAM2", + 'VLAM1', + 'VLAM2', Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, - "VLAM3", - "VLAM4", - "VLAM5", - "VLAM6", - "VLAM7", - "VLAM8", + 'VLAM3', + 'VLAM4', + 'VLAM5', + 'VLAM6', + 'VLAM7', + 'VLAM8', Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, - "VLAM9", - "VLAM10", - "VLAM11", - "VLAM12", - "VLAM13", - "VLAM14", - "fus_lift", + 'VLAM9', + 'VLAM10', + 'VLAM11', + 'VLAM12', + 'VLAM13', + 'VLAM14', + 'fus_lift', ], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "reynolds", + 'reynolds', [ - Dynamic.Mission.KINEMATIC_VISCOSITY, - Dynamic.Mission.SPEED_OF_SOUND, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, Aircraft.Wing.AVERAGE_CHORD, - Dynamic.Mission.STATIC_PRESSURE, - Aircraft.Wing.LOADING, + Dynamic.Atmosphere.STATIC_PRESSURE, + Aircraft.Design.WING_LOADING, Aircraft.Wing.MAX_LIFT_REF, - "VLAM1", - "VLAM2", + 'VLAM1', + 'VLAM2', Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, - "VLAM3", - "VLAM4", - "VLAM5", - "VLAM6", - "VLAM7", - "VLAM8", + 'VLAM3', + 'VLAM4', + 'VLAM5', + 'VLAM6', + 'VLAM7', + 'VLAM8', Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, - "VLAM9", - "VLAM10", - "VLAM11", - "VLAM12", - "VLAM13", - "VLAM14", - "fus_lift", + 'VLAM9', + 'VLAM10', + 'VLAM11', + 'VLAM12', + 'VLAM13', + 'VLAM14', + 'fus_lift', ], dependent=True, - method="cs", + method='cs', step=1e-8, ) def compute(self, inputs, outputs): + VLAM1 = inputs['VLAM1'] + VLAM2 = inputs['VLAM2'] + VLAM3 = inputs['VLAM3'] + VLAM4 = inputs['VLAM4'] + VLAM5 = inputs['VLAM5'] + VLAM6 = inputs['VLAM6'] + VLAM7 = inputs['VLAM7'] + VLAM8 = inputs['VLAM8'] + VLAM9 = inputs['VLAM9'] + VLAM10 = inputs['VLAM10'] + VLAM11 = inputs['VLAM11'] + VLAM12 = inputs['VLAM12'] + VLAM13 = inputs['VLAM13'] + VLAM14 = inputs['VLAM14'] - VLAM1 = inputs["VLAM1"] - VLAM2 = inputs["VLAM2"] - VLAM3 = inputs["VLAM3"] - VLAM4 = inputs["VLAM4"] - VLAM5 = inputs["VLAM5"] - VLAM6 = inputs["VLAM6"] - VLAM7 = inputs["VLAM7"] - VLAM8 = inputs["VLAM8"] - VLAM9 = inputs["VLAM9"] - VLAM10 = inputs["VLAM10"] - VLAM11 = inputs["VLAM11"] - VLAM12 = inputs["VLAM12"] - VLAM13 = inputs["VLAM13"] - VLAM14 = inputs["VLAM14"] - - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] - wing_loading = inputs[Aircraft.Wing.LOADING] - P = inputs[Dynamic.Mission.STATIC_PRESSURE] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] + wing_loading = inputs[Aircraft.Design.WING_LOADING] + P = inputs[Dynamic.Atmosphere.STATIC_PRESSURE] avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] - kinematic_viscosity = inputs[Dynamic.Mission.KINEMATIC_VISCOSITY] + kinematic_viscosity = inputs[Dynamic.Atmosphere.KINEMATIC_VISCOSITY] max_lift_reference = inputs[Aircraft.Wing.MAX_LIFT_REF] leading_lift_increment = inputs[Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM] - fus_lift = inputs["fus_lift"] + fus_lift = inputs['fus_lift'] trailing_lift_increment = inputs[Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM] # outputs - outputs["CL_max"] = CL_max = ( + outputs['CL_max'] = CL_max = ( max_lift_reference * VLAM1 * VLAM2 + trailing_lift_increment * VLAM3 * VLAM4 * VLAM5 * VLAM6 * VLAM7 * VLAM8 + leading_lift_increment * VLAM9 * VLAM10 * VLAM11 * VLAM12 @@ -263,7 +268,7 @@ def compute(self, inputs, outputs): Q1 = wing_loading / CL_max - outputs[Dynamic.Mission.MACH] = mach = (Q1 / 0.7 / P) ** 0.5 + outputs[Dynamic.Atmosphere.MACH] = mach = (Q1 / 0.7 / P) ** 0.5 VK = mach * sos - outputs["reynolds"] = reynolds = (avg_chord * VK / kinematic_viscosity) / 100000 + outputs['reynolds'] = (avg_chord * VK / kinematic_viscosity) / 100000 diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py index cdeead0e16..0e86afdb1e 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/L_and_D_increments.py @@ -5,146 +5,153 @@ class LiftAndDragIncrements(om.ExplicitComponent): - """ - Compute lift and drag increments from flaps for GASP-based aerodynamics - """ + """Compute lift and drag increments from flaps for GASP-based aerodynamics.""" def setup(self): - # Inputs self.add_input( - "VDEL5", + 'VDEL5', val=0.90761, units='unitless', - desc="VDEL5: sensitivity of flap minimum drag coefficient to flap hinge line sweep", + desc='VDEL5: sensitivity of flap minimum drag coefficient to flap hinge line sweep', ) self.add_input( - "VLAM8", + 'VLAM8', val=0.74444, units='unitless', - desc="VLAM8: sensitivity of flap clean wing maximum lift coefficient to wing sweep angle", + desc='VLAM8: sensitivity of flap clean wing maximum lift coefficient to wing sweep angle', ) self.add_input( - "VDEL4", + 'VDEL4', val=0.93578, units='unitless', - desc="VDEL4: sensitivity of minimum drag coefficient to fuselage width to span ratio", + desc='VDEL4: sensitivity of minimum drag coefficient to fuselage width to span ratio', ) - add_aviary_input(self, Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, val=0.1) + add_aviary_input(self, Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, units='unitless') self.add_input( - "VDEL1", + 'VDEL1', val=1.0, units='unitless', - desc="VDEL1: sensitivity of flap minimum drag coefficient to flap chord ratio", + desc='VDEL1: sensitivity of flap minimum drag coefficient to flap chord ratio', ) self.add_input( - "VDEL2", + 'VDEL2', val=0.62455, units='unitless', - desc="VDEL2: sensitivity of flap minimum drag coefficient to flap angle", + desc='VDEL2: sensitivity of flap minimum drag coefficient to flap angle', ) self.add_input( - "VDEL3", + 'VDEL3', val=0.765, units='unitless', - desc="VDEL3: sensitivity of flap minimum drag coefficient to partial flap span", + desc='VDEL3: sensitivity of flap minimum drag coefficient to partial flap span', ) - add_aviary_input(self, Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, val=1.5) + add_aviary_input(self, Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, units='unitless') self.add_input( - "VLAM3", + 'VLAM3', val=0.97217, units='unitless', - desc="VLAM3: sensitivity of flap clean wing maximum lift coefficient to aspect ratio", + desc='VLAM3: sensitivity of flap clean wing maximum lift coefficient to aspect ratio', ) self.add_input( - "VLAM4", + 'VLAM4', val=1.25725, units='unitless', - desc="VLAM4: sensitivity of flap clean wing maximum lift coefficient slope to wing thickness", + desc='VLAM4: sensitivity of flap clean wing maximum lift coefficient slope to wing thickness', ) self.add_input( - "VLAM5", + 'VLAM5', val=1, units='unitless', - desc="VLAM5: sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio", + desc='VLAM5: sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio', ) self.add_input( - "VLAM6", + 'VLAM6', val=1, units='unitless', - desc="VLAM6: sensitivity of flap clean wing maximum lift coefficient to wing flap deflection", + desc='VLAM6: sensitivity of flap clean wing maximum lift coefficient to wing flap deflection', ) self.add_input( - "VLAM7", + 'VLAM7', val=0.735, units='unitless', - desc="VLAM7: sensitivity of flap clean wing maximum lift coefficient to wing flap span", + desc='VLAM7: sensitivity of flap clean wing maximum lift coefficient to wing flap span', ) self.add_input( - "VLAM13", val=1.03512, units='unitless', desc="VLAM13: reynolds number correction factor" + 'VLAM13', + val=1.03512, + units='unitless', + desc='VLAM13: reynolds number correction factor', ) self.add_input( - "VLAM14", val=0.99124, units='unitless', desc="VLAM14: mach number correction factor " + 'VLAM14', + val=0.99124, + units='unitless', + desc='VLAM14: Mach number correction factor ', ) # outputs - self.add_output("delta_CD", val=0.0, - desc="DCD: increment on drag coefficient", units="unitless") - self.add_output("delta_CL", val=0.0, - desc="DCL: increment on lift coefficient", units="unitless") + self.add_output( + 'delta_CD', val=0.0, desc='DCD: increment on drag coefficient', units='unitless' + ) + self.add_output( + 'delta_CL', val=0.0, desc='DCL: increment on lift coefficient', units='unitless' + ) def setup_partials(self): - self.declare_partials( - "delta_CD", - [Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, - "VDEL1", "VDEL2", "VDEL3", "VDEL4", "VDEL5"], + 'delta_CD', + [ + Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, + 'VDEL1', + 'VDEL2', + 'VDEL3', + 'VDEL4', + 'VDEL5', + ], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "delta_CL", + 'delta_CL', [ Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, - "VLAM3", - "VLAM4", - "VLAM5", - "VLAM6", - "VLAM7", - "VLAM8", - "VLAM13", - "VLAM14", + 'VLAM3', + 'VLAM4', + 'VLAM5', + 'VLAM6', + 'VLAM7', + 'VLAM8', + 'VLAM13', + 'VLAM14', ], dependent=True, - method="cs", + method='cs', step=1e-8, ) def compute(self, inputs, outputs): - delta_drag_trailing = inputs[Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM] trailing_lift_increment = inputs[Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM] - VDEL1 = inputs["VDEL1"] - VDEL2 = inputs["VDEL2"] - VDEL3 = inputs["VDEL3"] - VDEL4 = inputs["VDEL4"] - VDEL5 = inputs["VDEL5"] - VLAM3 = inputs["VLAM3"] - VLAM4 = inputs["VLAM4"] - VLAM5 = inputs["VLAM5"] - VLAM6 = inputs["VLAM6"] - VLAM7 = inputs["VLAM7"] - VLAM8 = inputs["VLAM8"] - VLAM13 = inputs["VLAM13"] - VLAM14 = inputs["VLAM14"] + VDEL1 = inputs['VDEL1'] + VDEL2 = inputs['VDEL2'] + VDEL3 = inputs['VDEL3'] + VDEL4 = inputs['VDEL4'] + VDEL5 = inputs['VDEL5'] + VLAM3 = inputs['VLAM3'] + VLAM4 = inputs['VLAM4'] + VLAM5 = inputs['VLAM5'] + VLAM6 = inputs['VLAM6'] + VLAM7 = inputs['VLAM7'] + VLAM8 = inputs['VLAM8'] + VLAM13 = inputs['VLAM13'] + VLAM14 = inputs['VLAM14'] - outputs["delta_CD"] = delta_CD = ( - delta_drag_trailing * VDEL1 * VDEL2 * VDEL3 * VDEL4 * VDEL5 - ) - outputs["delta_CL"] = delta_CL = ( + outputs['delta_CD'] = delta_drag_trailing * VDEL1 * VDEL2 * VDEL3 * VDEL4 * VDEL5 + outputs['delta_CL'] = ( trailing_lift_increment * VLAM3 * VLAM4 diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/basic_calculations.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/basic_calculations.py index 48494ba6f5..8ea3e55a25 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/basic_calculations.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/basic_calculations.py @@ -6,108 +6,103 @@ class BasicFlapsCalculations(om.ExplicitComponent): - """ - Intermediate calculations for flaps model of GASP-based aerodynamics - """ + """Intermediate calculations for flaps model of GASP-based aerodynamics.""" def setup(self): - # inputs - add_aviary_input(self, Aircraft.Wing.SWEEP, val=25.0) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) - add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) - add_aviary_input(self, Aircraft.Wing.CENTER_CHORD, val=17.48974) - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=13.1) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15) - add_aviary_input(self, Aircraft.Wing.SPAN, val=117.8) - add_aviary_input(self, Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.CENTER_CHORD, units='ft') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.SLAT_CHORD_RATIO, units='unitless') self.add_input( - "slat_defl", + 'slat_defl', val=10.0, - units="deg", - desc="DELLED: leading edge slat deflection", + units='deg', + desc='DELLED: leading edge slat deflection', ) - add_aviary_input(self, Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, val=20.0) + add_aviary_input(self, Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, units='deg') self.add_input( - "flap_defl", + 'flap_defl', val=10.0, - units="deg", - desc="DFLPTO | DFLPLD: takeoff or landing flap deflection", - ) - add_aviary_input(self, Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, val=55.0) - add_aviary_input(self, Aircraft.Wing.ROOT_CHORD, val=16.406626) - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=129.4) - add_aviary_input(self, Aircraft.Wing.LEADING_EDGE_SWEEP, - val=0.47639, units="rad") + units='deg', + desc='DFLPTO | DFLPLD: takeoff or landing flap deflection', + ) + add_aviary_input(self, Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, units='deg') + add_aviary_input(self, Aircraft.Wing.ROOT_CHORD, units='ft') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Wing.LEADING_EDGE_SWEEP, units='rad') # outputs self.add_output( - "VLAM8", + 'VLAM8', val=0.74444322, units='unitless', - desc="VLAM8: sensitivity of flap clean wing maximum lift coefficient to wing sweep angle", + desc='VLAM8: sensitivity of flap clean wing maximum lift coefficient to wing sweep angle', ) self.add_output( - "VDEL4", + 'VDEL4', val=0.93577864, units='unitless', - desc="VDEL4: sensitivity of flap minimum drag coefficient to flap hinge line sweep", + desc='VDEL4: sensitivity of flap minimum drag coefficient to flap hinge line sweep', ) self.add_output( - "VDEL5", + 'VDEL5', val=0.90759603, units='unitless', - desc="VDEL5: sensitivity of minimum drag coefficient to fuselage width to span ratio", + desc='VDEL5: sensitivity of minimum drag coefficient to fuselage width to span ratio', ) self.add_output( - "VLAM9", + 'VLAM9', val=0.9975, units='unitless', - desc="VLAM9: sensitivity of slat clean wing maximum lift coefficient to slat chord", + desc='VLAM9: sensitivity of slat clean wing maximum lift coefficient to slat chord', ) self.add_output( - "slat_defl_ratio", + 'slat_defl_ratio', val=0.5, units='unitless', - desc="RDELL: ratio of leading edge slat deflection to optimum deflection angle", + desc='RDELL: ratio of leading edge slat deflection to optimum deflection angle', ) self.add_output( - "flap_defl_ratio", + 'flap_defl_ratio', val=0.5, units='unitless', - desc="RDELF: ratio of trailing edge flap deflection to optimum deflection angle", + desc='RDELF: ratio of trailing edge flap deflection to optimum deflection angle', ) - add_aviary_output(self, Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759603) + add_aviary_output(self, Aircraft.Wing.SLAT_SPAN_RATIO, units='unitless') self.add_output( - "chord_to_body_ratio", + 'chord_to_body_ratio', val=0.12679, units='unitless', - desc="CROBL: ratio of root chord to fuselage length", + desc='CROBL: ratio of root chord to fuselage length', ) self.add_output( - "body_to_span_ratio", + 'body_to_span_ratio', val=0.09240397, units='unitless', - desc="FWOB: ratio of body diameter at quarter chord to wing span", + desc='FWOB: ratio of body diameter at quarter chord to wing span', ) self.add_output( - "VLAM12", + 'VLAM12', val=0.79207395, units='unitless', - desc="VLAM12: sensitivity of slat clean wing maximum lift coefficient to leading edge sweepback", + desc='VLAM12: sensitivity of slat clean wing maximum lift coefficient to leading edge sweepback', ) def setup_partials(self): - # output partials self.declare_partials( - "VLAM8", [Aircraft.Wing.SWEEP], dependent=True, method="cs", step=1e-8 + 'VLAM8', [Aircraft.Wing.SWEEP], dependent=True, method='cs', step=1e-8 ) self.declare_partials( - "VDEL4", + 'VDEL4', [ Aircraft.Wing.SWEEP, Aircraft.Wing.ASPECT_RATIO, @@ -115,11 +110,11 @@ def setup_partials(self): Aircraft.Wing.TAPER_RATIO, ], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "VDEL5", + 'VDEL5', [ Aircraft.Wing.SPAN, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, @@ -127,21 +122,21 @@ def setup_partials(self): Aircraft.Fuselage.AVG_DIAMETER, ], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "VLAM9", [Aircraft.Wing.SLAT_CHORD_RATIO], dependent=True, method="cs", step=1e-8 + 'VLAM9', [Aircraft.Wing.SLAT_CHORD_RATIO], dependent=True, method='cs', step=1e-8 ) self.declare_partials( - "slat_defl_ratio", - ["slat_defl", Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION], + 'slat_defl_ratio', + ['slat_defl', Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "flap_defl_ratio", ["flap_defl", Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION], method="cs" + 'flap_defl_ratio', ['flap_defl', Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION], method='cs' ) self.declare_partials( Aircraft.Wing.SLAT_SPAN_RATIO, @@ -152,18 +147,18 @@ def setup_partials(self): Aircraft.Fuselage.AVG_DIAMETER, ], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "chord_to_body_ratio", + 'chord_to_body_ratio', [Aircraft.Wing.ROOT_CHORD, Aircraft.Fuselage.LENGTH], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "body_to_span_ratio", + 'body_to_span_ratio', [ Aircraft.Wing.SPAN, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, @@ -171,19 +166,18 @@ def setup_partials(self): Aircraft.Fuselage.AVG_DIAMETER, ], dependent=True, - method="cs", + method='cs', step=1e-8, ) self.declare_partials( - "VLAM12", + 'VLAM12', [Aircraft.Wing.LEADING_EDGE_SWEEP], dependent=True, - method="cs", + method='cs', step=1e-8, ) def compute(self, inputs, outputs): - sweep_c4 = inputs[Aircraft.Wing.SWEEP] AR = inputs[Aircraft.Wing.ASPECT_RATIO] flap_chord_ratio = inputs[Aircraft.Wing.FLAP_CHORD_RATIO] @@ -193,9 +187,9 @@ def compute(self, inputs, outputs): tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] wingspan = inputs[Aircraft.Wing.SPAN] slat_chord_ratio = inputs[Aircraft.Wing.SLAT_CHORD_RATIO] - slat_defl = inputs["slat_defl"] + slat_defl = inputs['slat_defl'] optimum_slat_defl = inputs[Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION] - flap_defl = inputs["flap_defl"] + flap_defl = inputs['flap_defl'] optimum_flap_defl = inputs[Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION] root_chord = inputs[Aircraft.Wing.ROOT_CHORD] fus_len = inputs[Aircraft.Fuselage.LENGTH] @@ -211,24 +205,19 @@ def compute(self, inputs, outputs): DBALE = ( 2.0 - * ( - tc_ratio_root - * center_chord - * (cabin_width - (tc_ratio_root * center_chord)) - ) - ** 0.5 + * (tc_ratio_root * center_chord * (cabin_width - (tc_ratio_root * center_chord))) ** 0.5 ) + 0.4 SWPL12 = sweep_LE - 5.0 / 57.296 # outputs equations - outputs["VLAM8"] = VLAM8 = (np.cos(RLMC4)) ** 3 - outputs["body_to_span_ratio"] = body_to_span_ratio = DBALE / wingspan - outputs["VDEL4"] = VDEL4 = np.cos(SWPFHL) - outputs["VDEL5"] = VDEL5 = 1.0 - body_to_span_ratio - outputs["VLAM9"] = VLAM9 = 6.65 * slat_chord_ratio - outputs["slat_defl_ratio"] = slat_defl_ratio = slat_defl / optimum_slat_defl - outputs["flap_defl_ratio"] = flap_defl / optimum_flap_defl - outputs[Aircraft.Wing.SLAT_SPAN_RATIO] = slat_span_ratio = 0.99 - DBALE / wingspan - outputs["chord_to_body_ratio"] = chord_to_body_ratio = root_chord / fus_len - outputs["VLAM12"] = VLAM12 = (np.cos(SWPL12)) ** 3 + outputs['VLAM8'] = (np.cos(RLMC4)) ** 3 + outputs['body_to_span_ratio'] = body_to_span_ratio = DBALE / wingspan + outputs['VDEL4'] = np.cos(SWPFHL) + outputs['VDEL5'] = 1.0 - body_to_span_ratio + outputs['VLAM9'] = 6.65 * slat_chord_ratio + outputs['slat_defl_ratio'] = slat_defl / optimum_slat_defl + outputs['flap_defl_ratio'] = flap_defl / optimum_flap_defl + outputs[Aircraft.Wing.SLAT_SPAN_RATIO] = 0.99 - DBALE / wingspan + outputs['chord_to_body_ratio'] = root_chord / fus_len + outputs['VLAM12'] = (np.cos(SWPL12)) ** 3 diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py index 3a4d9ad7db..a255c8d6b5 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/flaps_model.py @@ -1,15 +1,15 @@ import openmdao.api as om -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.basic_calculations import \ - BasicFlapsCalculations -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.Cl_max import \ - CLmaxCalculation -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.L_and_D_increments import \ - LiftAndDragIncrements -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.meta_model import \ - MetaModelGroup -from aviary.utils.aviary_values import AviaryValues +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.basic_calculations import ( + BasicFlapsCalculations, +) +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.Cl_max import CLmaxCalculation +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.L_and_D_increments import ( + LiftAndDragIncrements, +) +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.meta_model import MetaModelGroup from aviary.variable_info.enums import FlapType +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic @@ -21,10 +21,7 @@ class FlapsGroup(om.Group): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Wing.FLAP_TYPE) # optimum trailing edge flap deflection angle defaults (ADELTO table in GASP) self.optimum_flap_defls = { @@ -38,115 +35,111 @@ def initialize(self): } def setup(self): - - aviary_options = self.options['aviary_options'] - self.add_subsystem( - "BasicFlapsCalculations", + 'BasicFlapsCalculations', BasicFlapsCalculations(), promotes_inputs=[ - "slat_defl", - "flap_defl", + 'slat_defl', + 'flap_defl', ] - + ["aircraft:*"], - promotes_outputs=["*"], + + ['aircraft:*'], + promotes_outputs=['*'], ) self.add_subsystem( - "CLmaxCalculation", + 'CLmaxCalculation', CLmaxCalculation(), promotes_inputs=[ - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.STATIC_PRESSURE, - Dynamic.Mission.KINEMATIC_VISCOSITY, - "VLAM1", - "VLAM2", - "VLAM3", - "VLAM4", - "VLAM5", - "VLAM6", - "VLAM7", - "VLAM8", - "VLAM9", - "VLAM10", - "VLAM11", - "VLAM12", - "VLAM13", - "VLAM14", - "fus_lift", - Dynamic.Mission.TEMPERATURE, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + 'VLAM1', + 'VLAM2', + 'VLAM3', + 'VLAM4', + 'VLAM5', + 'VLAM6', + 'VLAM7', + 'VLAM8', + 'VLAM9', + 'VLAM10', + 'VLAM11', + 'VLAM12', + 'VLAM13', + 'VLAM14', + 'fus_lift', + Dynamic.Atmosphere.TEMPERATURE, ] - + ["aircraft:*"], - promotes_outputs=["CL_max", Dynamic.Mission.MACH, "reynolds"], + + ['aircraft:*'], + promotes_outputs=['CL_max', Dynamic.Atmosphere.MACH, 'reynolds'], ) self.add_subsystem( - "LookupTables", - MetaModelGroup(aviary_options=aviary_options), + 'LookupTables', + MetaModelGroup(), promotes_inputs=[ - "flap_defl_ratio", - "flap_defl", - "slat_defl_ratio", - "reynolds", - Dynamic.Mission.MACH, - "body_to_span_ratio", - "chord_to_body_ratio", + 'flap_defl_ratio', + 'flap_defl', + 'slat_defl_ratio', + 'reynolds', + Dynamic.Atmosphere.MACH, + 'body_to_span_ratio', + 'chord_to_body_ratio', ] - + ["aircraft:*"], + + ['aircraft:*'], promotes_outputs=[ - "VDEL1", - "VDEL2", - "VDEL3", - "VLAM1", - "VLAM2", - "VLAM3", - "VLAM4", - "VLAM5", - "VLAM6", - "VLAM7", - "VLAM10", - "VLAM11", - "VLAM13", - "VLAM14", - "fus_lift", + 'VDEL1', + 'VDEL2', + 'VDEL3', + 'VLAM1', + 'VLAM2', + 'VLAM3', + 'VLAM4', + 'VLAM5', + 'VLAM6', + 'VLAM7', + 'VLAM10', + 'VLAM11', + 'VLAM13', + 'VLAM14', + 'fus_lift', ], ) self.add_subsystem( - "LiftAndDragIncrements", + 'LiftAndDragIncrements', LiftAndDragIncrements(), promotes_inputs=[ Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, - "VDEL1", - "VDEL2", - "VDEL3", - "VDEL4", - "VDEL5", - "VLAM3", - "VLAM4", - "VLAM5", - "VLAM6", - "VLAM7", - "VLAM8", - "VLAM13", - "VLAM14", + 'VDEL1', + 'VDEL2', + 'VDEL3', + 'VDEL4', + 'VDEL5', + 'VLAM3', + 'VLAM4', + 'VLAM5', + 'VLAM6', + 'VLAM7', + 'VLAM8', + 'VLAM13', + 'VLAM14', ], - promotes_outputs=["delta_CD", "delta_CL"], + promotes_outputs=['delta_CD', 'delta_CL'], ) self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True) self.linear_solver = om.DirectSolver() - self.nonlinear_solver.options["iprint"] = 0 - self.nonlinear_solver.options["maxiter"] = 25 - self.nonlinear_solver.options["atol"] = 1e-8 - self.nonlinear_solver.options["rtol"] = 1e-8 + self.nonlinear_solver.options['iprint'] = 0 + self.nonlinear_solver.options['maxiter'] = 25 + self.nonlinear_solver.options['atol'] = 1e-8 + self.nonlinear_solver.options['rtol'] = 1e-8 # set default trailing edge deflection angle per GASP self.set_input_defaults( Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, - self.optimum_flap_defls[self.options["aviary_options"].get_val( - Aircraft.Wing.FLAP_TYPE, units='unitless')], - units="deg", + self.optimum_flap_defls[self.options[Aircraft.Wing.FLAP_TYPE]], + units='deg', ) diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py index 5c9e00b4cd..c7631b6353 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/meta_model.py @@ -1,90 +1,83 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import FlapType +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic class MetaModelGroup(om.Group): """ Group of metamodel components to interpolate intermediate calculation values for flaps model in GASP-based - aerodynamics + aerodynamics. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Wing.FLAP_TYPE) def setup(self): - - flap_type = self.options["aviary_options"].get_val( - Aircraft.Wing.FLAP_TYPE, units='unitless') + flap_type = self.options[Aircraft.Wing.FLAP_TYPE] # VDEL1 VDEL1_interp = self.add_subsystem( - "VDEL1_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VDEL1_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "aircraft:*", + 'aircraft:*', ], promotes_outputs=[ - "VDEL1", + 'VDEL1', ], ) VDEL1_interp.add_input( Aircraft.Wing.FLAP_CHORD_RATIO, - 0.3, + 0.0, training_data=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5], - units="unitless", - desc="ratio of flap chord to wing chord", + units='unitless', + desc='ratio of flap chord to wing chord', ) if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: - VDEL1_interp.add_output( - "VDEL1", + 'VDEL1', 1.0, training_data=[0.0, 0.32, 0.66, 1.0, 1.32, 1.70], - units="unitless", - desc="sensitivity of flap minimum drag coefficient to flap chord ratio", + units='unitless', + desc='sensitivity of flap minimum drag coefficient to flap chord ratio', ) else: - VDEL1_interp.add_output( - "VDEL1", + 'VDEL1', 1.0, training_data=[0.0, 0.24, 0.55, 1.00, 1.60, 2.20], - units="unitless", - desc="sensitivity of flap minimum drag coefficient to flap chord ratio", + units='unitless', + desc='sensitivity of flap minimum drag coefficient to flap chord ratio', ) # VDEL2 VDEL2_interp = self.add_subsystem( - "VDEL2_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VDEL2_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "flap_defl_ratio", + 'flap_defl_ratio', ], promotes_outputs=[ - "VDEL2", + 'VDEL2', ], ) VDEL2_interp.add_input( - "flap_defl_ratio", + 'flap_defl_ratio', 0.727273, training_data=[0.0, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 2.25, 2.5, 2.75, 3.0], - units="unitless", - desc="ratio of flap deflection to optimum flap deflection angle", + units='unitless', + desc='ratio of flap deflection to optimum flap deflection angle', ) VDEL2_interp.add_output( - "VDEL2", + 'VDEL2', 0.62455, training_data=[ 0.0, @@ -99,18 +92,18 @@ def setup(self): 4.82, 5.00, ], - units="unitless", - desc="sensitivity of flap minimum drag coefficient to flap angle", + units='unitless', + desc='sensitivity of flap minimum drag coefficient to flap angle', ) # VDEL3 VDEL3_interp = self.add_subsystem( - "VDEL3_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), - promotes_inputs=["aircraft:*"], + 'VDEL3_interp', + om.MetaModelStructuredComp(method='scipy_slinear', extrapolate=True), + promotes_inputs=['aircraft:*'], promotes_outputs=[ - "VDEL3", + 'VDEL3', ], ) @@ -118,23 +111,23 @@ def setup(self): Aircraft.Wing.FLAP_SPAN_RATIO, 0.65, training_data=[0.0, 0.2, 0.4, 0.6, 0.7, 0.8, 0.9, 1.0], - units="unitless", - desc="BTEOB: trailing edge flap span divided by wing span", + units='unitless', + desc='BTEOB: trailing edge flap span divided by wing span', ) VDEL3_interp.add_input( Aircraft.Wing.TAPER_RATIO, - 0.33, + 0.0, training_data=[0.0, 0.33, 1.0], - units="unitless", - desc="taper ratio of wing", + units='unitless', + desc='taper ratio of wing', ) VDEL3_interp.add_output( - "VDEL3", + 'VDEL3', 0.765, - units="unitless", - desc="sensitivity of flap minimum drag coefficient to partial flap span", + units='unitless', + desc='sensitivity of flap minimum drag coefficient to partial flap span', training_data=np.array( [ [0.0, 0.0, 0.0], @@ -153,19 +146,19 @@ def setup(self): # VLAM1 VLAM1_interp = self.add_subsystem( - "VLAM1_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM1_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "aircraft:*", + 'aircraft:*', ], promotes_outputs=[ - "VLAM1", + 'VLAM1', ], ) VLAM1_interp.add_input( Aircraft.Wing.ASPECT_RATIO, - 10.13, + 0.0, training_data=[ 0.0, 0.2, @@ -186,12 +179,12 @@ def setup(self): 12.0, 20.0, ], - units="unitless", - desc="aspect ratio", + units='unitless', + desc='aspect ratio', ) VLAM1_interp.add_output( - "VLAM1", + 'VLAM1', 0.97217, training_data=[ 0.0, @@ -213,23 +206,23 @@ def setup(self): 1.0, 1.0, ], - units="unitless", - desc="sensitivity of clean wing maximum lift coefficient to wing aspect ratio", + units='unitless', + desc='sensitivity of clean wing maximum lift coefficient to wing aspect ratio', ) # VLAM2 VLAM2_interp = self.add_subsystem( - "VLAM2_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM2_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, ], - promotes_outputs=["VLAM2"], + promotes_outputs=['VLAM2'], ) VLAM2_interp.add_input( Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, - 0.13966, + 0.0, training_data=[ 0.0, 0.04, @@ -248,12 +241,12 @@ def setup(self): 0.24, 0.28, ], - units="unitless", - desc="average wing thickness to chord ratio", + units='unitless', + desc='average wing thickness to chord ratio', ) VLAM2_interp.add_output( - "VLAM2", + 'VLAM2', 1.09948, training_data=[ 0.8, @@ -273,23 +266,23 @@ def setup(self): 0.96, 0.80, ], - units="unitless", - desc="sensitivity of clean wing maximum lift coefficient to wing thickness to chord ratio", + units='unitless', + desc='sensitivity of clean wing maximum lift coefficient to wing thickness to chord ratio', ) # VLAM3 VLAM3_interp = self.add_subsystem( - "VLAM3_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM3_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "aircraft:*", + 'aircraft:*', ], - promotes_outputs=["VLAM3"], + promotes_outputs=['VLAM3'], ) VLAM3_interp.add_input( Aircraft.Wing.ASPECT_RATIO, - 10.13, + 0.0, training_data=[ 0.0, 0.2, @@ -310,12 +303,12 @@ def setup(self): 12.0, 20.0, ], - units="unitless", - desc="aspect ratio", + units='unitless', + desc='aspect ratio', ) VLAM3_interp.add_output( - "VLAM3", + 'VLAM3', 0.97217, training_data=[ 0.0, @@ -337,25 +330,25 @@ def setup(self): 1.0, 1.0, ], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing aspect ratio", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing aspect ratio', ) # VLAM4 VLAM4_interp = self.add_subsystem( - "VLAM4_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM4_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, ], promotes_outputs=[ - "VLAM4", + 'VLAM4', ], ) VLAM4_interp.add_input( Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, - 0.13966, + 0.0, training_data=[ 0.0, 0.04, @@ -374,14 +367,13 @@ def setup(self): 0.24, 0.28, ], - units="unitless", - desc="average wing thickness to chord ratio", + units='unitless', + desc='average wing thickness to chord ratio', ) if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: - VLAM4_interp.add_output( - "VLAM4", + 'VLAM4', 1.19742, training_data=[ 1.25, @@ -401,14 +393,13 @@ def setup(self): 2.18, 2.20, ], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient slope to wing thickness", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient slope to wing thickness', ) else: - VLAM4_interp.add_output( - "VLAM4", + 'VLAM4', 1.25725, training_data=[ 0.84, @@ -428,36 +419,35 @@ def setup(self): 1.59, 1.60, ], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient slope to wing thickness", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient slope to wing thickness', ) # VLAM5 VLAM5_interp = self.add_subsystem( - "VLAM5_intep", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM5_intep', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "aircraft:*", + 'aircraft:*', ], - promotes_outputs=["VLAM5"], + promotes_outputs=['VLAM5'], ) VLAM5_interp.add_input( Aircraft.Wing.FLAP_CHORD_RATIO, - 0.3, + 0.0, training_data=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5], - units="unitless", - desc="ratio of flap chord to wing chord", + units='unitless', + desc='ratio of flap chord to wing chord', ) if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: - VLAM5_interp.add_output( - "VLAM5", + 'VLAM5', 1.0, training_data=[0.0, 0.72, 0.94, 1.00, 0.95, 0.73], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio', ) elif ( @@ -465,39 +455,37 @@ def setup(self): or flap_type is FlapType.DOUBLE_SLOTTED or flap_type is FlapType.TRIPLE_SLOTTED ): - VLAM5_interp.add_output( - "VLAM5", + 'VLAM5', 1.0, training_data=[0.0, 0.575, 0.83, 1.00, 1.065, 1.09], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio', ) else: - VLAM5_interp.add_output( - "VLAM5", + 'VLAM5', 1.0, training_data=[0.0, 0.41, 0.73, 1.00, 1.22, 1.40], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing flap to chord ratio', ) # VLAM6 VLAM6_interp = self.add_subsystem( - "VLAM6_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM6_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "flap_defl", + 'flap_defl', ], promotes_outputs=[ - "VLAM6", + 'VLAM6', ], ) VLAM6_interp.add_input( - "flap_defl", + 'flap_defl', 10.0, training_data=[ 0.0, @@ -516,14 +504,13 @@ def setup(self): 55.0, 60.0, ], - units="deg", - desc="flap deflection", + units='deg', + desc='flap deflection', ) if flap_type is FlapType.PLAIN or flap_type is FlapType.SPLIT: - VLAM6_interp.add_output( - "VLAM6", + 'VLAM6', 0.8, training_data=[ 0.0, @@ -542,8 +529,8 @@ def setup(self): 0.98, 1.0, ], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing flap deflection", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing flap deflection', ) elif ( @@ -551,9 +538,8 @@ def setup(self): or flap_type is FlapType.DOUBLE_SLOTTED or flap_type is FlapType.TRIPLE_SLOTTED ): - VLAM6_interp.add_output( - "VLAM6", + 'VLAM6', 1.0, training_data=[ 0.0, @@ -572,14 +558,13 @@ def setup(self): 0.85, 0.75, ], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing flap deflection", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing flap deflection', ) - elif (flap_type is FlapType.FOWLER or flap_type is FlapType.DOUBLE_SLOTTED_FOWLER): - + elif flap_type is FlapType.FOWLER or flap_type is FlapType.DOUBLE_SLOTTED_FOWLER: VLAM6_interp.add_output( - "VLAM6", + 'VLAM6', 1.11, training_data=[ 0.0, @@ -598,8 +583,8 @@ def setup(self): 0.56, 0.20, ], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing flap deflection", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing flap deflection', ) else: @@ -607,13 +592,13 @@ def setup(self): # VLAM7 VLAM7_interp = self.add_subsystem( - "VLAM7_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM7_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ Aircraft.Wing.FLAP_SPAN_RATIO, ], promotes_outputs=[ - "VLAM7", + 'VLAM7', ], ) @@ -621,32 +606,32 @@ def setup(self): Aircraft.Wing.FLAP_SPAN_RATIO, 0.65, training_data=[0.0, 0.2, 0.4, 0.6, 0.8, 0.9, 1.0], - units="unitless", - desc="BTEOB: trailing edge flap span divided by wing span", + units='unitless', + desc='BTEOB: trailing edge flap span divided by wing span', ) VLAM7_interp.add_output( - "VLAM7", + 'VLAM7', 0.735, training_data=[0.0, 0.25, 0.47, 0.69, 0.87, 0.94, 1.00], - units="unitless", - desc="sensitivity of flap clean wing maximum lift coefficient to wing flap span", + units='unitless', + desc='sensitivity of flap clean wing maximum lift coefficient to wing flap span', ) # VLAM10 VLAM10_interp = self.add_subsystem( - "VLAM10_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM10_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "slat_defl_ratio", + 'slat_defl_ratio', ], promotes_outputs=[ - "VLAM10", + 'VLAM10', ], ) VLAM10_interp.add_input( - "slat_defl_ratio", + 'slat_defl_ratio', 0.5, training_data=[ 0.0, @@ -664,12 +649,12 @@ def setup(self): 1.6, 1.7, ], - units="unitless", - desc="Ratio of leading edge slat deflection to optimum deflection angle", + units='unitless', + desc='Ratio of leading edge slat deflection to optimum deflection angle', ) VLAM10_interp.add_output( - "VLAM10", + 'VLAM10', 0.74, training_data=[ 0.0, @@ -687,19 +672,19 @@ def setup(self): 0.49, 0.22, ], - units="unitless", - desc="sensitivity of clean wing maximum lift coefficient to slat deflection angle", + units='unitless', + desc='sensitivity of clean wing maximum lift coefficient to slat deflection angle', ) # VLAM11 VLAM11_interp = self.add_subsystem( - "VLAM11_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM11_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ Aircraft.Wing.SLAT_SPAN_RATIO, ], promotes_outputs=[ - "VLAM11", + 'VLAM11', ], ) @@ -707,32 +692,32 @@ def setup(self): Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759553, training_data=[0.0, 0.2, 0.3, 0.4, 0.47, 0.5, 1.0], - units="unitless", - desc="ratio of leading edge slat span to wing span", + units='unitless', + desc='ratio of leading edge slat span to wing span', ) VLAM11_interp.add_output( - "VLAM11", + 'VLAM11', 0.84232, training_data=[0.0, 0.05, 0.09, 0.15, 0.20, 0.23, 1.00], - units="unitless", - desc="sensitivity of slat clean wing maximum lift coefficient to slat span", + units='unitless', + desc='sensitivity of slat clean wing maximum lift coefficient to slat span', ) # VLAM13 VLAM13_interp = self.add_subsystem( - "VLAM13_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM13_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - "reynolds", + 'reynolds', ], promotes_outputs=[ - "VLAM13", + 'VLAM13', ], ) VLAM13_interp.add_input( - "reynolds", + 'reynolds', val=157.1111, training_data=[ 1.0, @@ -750,12 +735,12 @@ def setup(self): 1000.0, 10000.0, ], - units="unitless", - desc="reynolds number", + units='unitless', + desc='reynolds number', ) VLAM13_interp.add_output( - "VLAM13", + 'VLAM13', 1.03512, training_data=[ 0.70, @@ -773,70 +758,70 @@ def setup(self): 0.90, 0.90, ], - units="unitless", - desc="reynolds number correction factor", + units='unitless', + desc='reynolds number correction factor', ) # VLAM14 VLAM14_interp = self.add_subsystem( - "VLAM14_interp", - om.MetaModelStructuredComp(method="1D-slinear", extrapolate=True), + 'VLAM14_interp', + om.MetaModelStructuredComp(method='1D-slinear', extrapolate=True), promotes_inputs=[ - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, ], promotes_outputs=[ - "VLAM14", + 'VLAM14', ], ) VLAM14_interp.add_input( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, 0.17522, training_data=[0.0, 0.2, 0.4, 0.6, 0.8, 1.0], - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) VLAM14_interp.add_output( - "VLAM14", + 'VLAM14', 0.99124, training_data=[1.0, 0.99, 0.94, 0.87, 0.78, 0.66], - units="unitless", - desc="mach number correction factor", + units='unitless', + desc='Mach number correction factor', ref=100, ) # fus_lift fus_lift_interp = self.add_subsystem( - "fus_lift_interp", - om.MetaModelStructuredComp(method="scipy_slinear", extrapolate=True), - promotes_inputs=["body_to_span_ratio", "chord_to_body_ratio"], + 'fus_lift_interp', + om.MetaModelStructuredComp(method='scipy_slinear', extrapolate=True), + promotes_inputs=['body_to_span_ratio', 'chord_to_body_ratio'], promotes_outputs=[ - "fus_lift", + 'fus_lift', ], ) fus_lift_interp.add_input( - "body_to_span_ratio", + 'body_to_span_ratio', 0.09240447, training_data=[0.0, 0.05, 0.10, 0.12, 0.15, 0.20, 0.25, 0.30, 0.40, 0.50], - units="unitless", - desc="trailing edge flap span divided by wing span", + units='unitless', + desc='trailing edge flap span divided by wing span', ) fus_lift_interp.add_input( - "chord_to_body_ratio", + 'chord_to_body_ratio', 0.12679, training_data=[0.1, 0.2, 0.3, 0.4, 0.5], - units="unitless", - desc="taper ratio of wing", + units='unitless', + desc='taper ratio of wing', ) fus_lift_interp.add_output( - "fus_lift", + 'fus_lift', 0.05498, - units="unitless", - desc="sensitivity of flap minimum drag coefficient to partial flap span", + units='unitless', + desc='sensitivity of flap minimum drag coefficient to partial flap span', training_data=np.array( [ [0.0, 0.0, 0.0, 0.0, 0.0], diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_Clmax.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_Clmax.py index fbc47559be..e1470a7353 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_Clmax.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_Clmax.py @@ -1,12 +1,9 @@ import unittest -import os import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.Cl_max import \ - CLmaxCalculation +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.Cl_max import CLmaxCalculation from aviary.variable_info.variables import Aircraft, Dynamic """ @@ -16,7 +13,6 @@ class CLmaxCalculationTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem(model=om.Group()) self.prob.model.add_subsystem('CLmC', CLmaxCalculation(), promotes=['*']) @@ -24,57 +20,54 @@ def setUp(self): self.prob.setup() # initial conditions - self.prob.set_val("VLAM1", 0.97217) - self.prob.set_val("VLAM2", 1.09948) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.25725) - self.prob.set_val("VLAM5", 1.0000) - self.prob.set_val("VLAM6", 1.0000) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444) - self.prob.set_val("VLAM9", 0.9975) - self.prob.set_val("VLAM10", 0.74) - self.prob.set_val("VLAM11", 0.84232) - self.prob.set_val("VLAM12", 0.79208) - self.prob.set_val("VLAM13", 1.03512) - self.prob.set_val("VLAM14", 0.99124) - - self.prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, 1118.21948771, units="ft/s") # - self.prob.set_val(Aircraft.Wing.LOADING, 128.0, units="lbf/ft**2") - self.prob.set_val(Dynamic.Mission.STATIC_PRESSURE, - (14.696 * 144), units="lbf/ft**2") - self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units="ft") - self.prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, - 0.15723e-3, units="ft**2/s") + self.prob.set_val('VLAM1', 0.97217) + self.prob.set_val('VLAM2', 1.09948) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.25725) + self.prob.set_val('VLAM5', 1.0000) + self.prob.set_val('VLAM6', 1.0000) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444) + self.prob.set_val('VLAM9', 0.9975) + self.prob.set_val('VLAM10', 0.74) + self.prob.set_val('VLAM11', 0.84232) + self.prob.set_val('VLAM12', 0.79208) + self.prob.set_val('VLAM13', 1.03512) + self.prob.set_val('VLAM14', 0.99124) + + self.prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 1118.21948771, units='ft/s') # + self.prob.set_val(Aircraft.Design.WING_LOADING, 128.0, units='lbf/ft**2') + self.prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, (14.696 * 144), units='lbf/ft**2') + self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units='ft') + self.prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, 0.15723e-3, units='ft**2/s') self.prob.set_val(Aircraft.Wing.MAX_LIFT_REF, 1.150) self.prob.set_val(Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, 0.930) - self.prob.set_val("fus_lift", 0.05498) + self.prob.set_val('fus_lift', 0.05498) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.500) - self.prob.set_val(Dynamic.Mission.TEMPERATURE, 518.7, units="degR") + self.prob.set_val(Dynamic.Atmosphere.TEMPERATURE, 518.7, units='degR') def test_case(self): - self.prob.run_model() tol = 6e-4 print() reg_data = 2.8155 - ans = self.prob["CL_max"] + ans = self.prob['CL_max'] assert_near_equal(ans, reg_data, tol) reg_data = 0.17522 - ans = self.prob[Dynamic.Mission.MACH] + ans = self.prob[Dynamic.Atmosphere.MACH] assert_near_equal(ans, reg_data, tol) reg_data = 157.19864 - ans = self.prob["reynolds"] + ans = self.prob['reynolds'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(out_stream=None, method="fd") + data = self.prob.check_partials(out_stream=None, method='fd') assert_check_partials( data, atol=6400, rtol=0.007 ) # large to account for large magnitude value, discrepancies are acceptable -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_basic_calculations.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_basic_calculations.py index 16a7e427d7..1f148c2303 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_basic_calculations.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_basic_calculations.py @@ -1,12 +1,11 @@ import unittest -import os import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.basic_calculations import \ - BasicFlapsCalculations +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.basic_calculations import ( + BasicFlapsCalculations, +) from aviary.variable_info.variables import Aircraft """ @@ -16,7 +15,6 @@ class BasicFlapsCalculationsTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem(model=om.Group()) self.prob.model.add_subsystem('BC', BasicFlapsCalculations(), promotes=['*']) @@ -24,45 +22,45 @@ def setUp(self): self.prob.setup() # initial conditions - self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units="deg") + self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units='deg') self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) - self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15) - self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') self.prob.set_val(Aircraft.Wing.SLAT_CHORD_RATIO, 0.15) - self.prob.set_val("slat_defl", 10.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units="deg") - self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.41, units="ft") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units="rad") + self.prob.set_val('slat_defl', 10.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units='deg') + self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.41, units='ft') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units='rad') + self.prob.set_val(Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, 55.0, units='deg') def test_case(self): - self.prob.run_model() tol = 2.1e-4 print() reg_data = 0.74444 - ans = self.prob["VLAM8"] + ans = self.prob['VLAM8'] assert_near_equal(ans, reg_data, tol) reg_data = 0.93578 - ans = self.prob["VDEL4"] + ans = self.prob['VDEL4'] assert_near_equal(ans, reg_data, tol) reg_data = 0.90761 - ans = self.prob["VDEL5"] + ans = self.prob['VDEL5'] assert_near_equal(ans, reg_data, tol) reg_data = 0.9975 - ans = self.prob["VLAM9"] + ans = self.prob['VLAM9'] assert_near_equal(ans, reg_data, tol) reg_data = 0.5 - ans = self.prob["slat_defl_ratio"] + ans = self.prob['slat_defl_ratio'] assert_near_equal(ans, reg_data, tol) reg_data = 0.89761 @@ -70,20 +68,20 @@ def test_case(self): assert_near_equal(ans, reg_data, tol) reg_data = 0.09239 - ans = self.prob["body_to_span_ratio"] + ans = self.prob['body_to_span_ratio'] assert_near_equal(ans, reg_data, tol) reg_data = 0.12679 - ans = self.prob["chord_to_body_ratio"] + ans = self.prob['chord_to_body_ratio'] assert_near_equal(ans, reg_data, tol) reg_data = 0.79208 - ans = self.prob["VLAM12"] + ans = self.prob['VLAM12'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(out_stream=None, method="fd") + data = self.prob.check_partials(out_stream=None, method='fd') assert_check_partials(data, atol=1e-6, rtol=4e-6) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py index b7b78faedf..b1c16fcbfe 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_flaps_group.py @@ -3,10 +3,10 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.flaps_model import \ - FlapsGroup -from aviary.variable_info.options import get_option_defaults +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.flaps_model import FlapsGroup from aviary.variable_info.enums import FlapType +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic """ @@ -16,103 +16,100 @@ class FlapsGroupTestCaseTripleSlotted(unittest.TestCase): def setUp(self): - self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, - val=FlapType.TRIPLE_SLOTTED, units='unitless') + options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.TRIPLE_SLOTTED, units='unitless') - self.prob.model = FCC = FlapsGroup(aviary_options=options) + self.prob.model = FlapsGroup() + + setup_model_options(self.prob, options) self.prob.setup() - self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units="deg") - self.prob.set_val(Dynamic.Mission.TEMPERATURE, 518.67, units="degR") + self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units='deg') + self.prob.set_val(Dynamic.Atmosphere.TEMPERATURE, 518.67, units='degR') self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) - self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15) - self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') self.prob.set_val(Aircraft.Wing.SLAT_CHORD_RATIO, 0.15) - self.prob.set_val("slat_defl", 10.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units="deg") - self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units="ft") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units="rad") - - self.prob.set_val("VLAM1", 0.97217) - self.prob.set_val("VLAM2", 1.09948) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.25725) - self.prob.set_val("VLAM5", 1.0000) - self.prob.set_val("VLAM6", 1.0000) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444322) - self.prob.set_val("VLAM9", 0.9975) - self.prob.set_val("VLAM10", 0.74) - self.prob.set_val("VLAM11", 0.84232) - self.prob.set_val("VLAM12", 0.79208) - self.prob.set_val("VLAM13", 1.03512) - self.prob.set_val("VLAM14", 0.99124) - - self.prob.set_val("VDEL1", 1.0) - self.prob.set_val("VDEL2", 0.62455) - self.prob.set_val("VDEL3", 0.765) - self.prob.set_val("VDEL4", 0.93578) - self.prob.set_val("VDEL5", 0.90761) - - self.prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, 1118.21948771, units="ft/s") - self.prob.set_val(Aircraft.Wing.LOADING, 128.0, units="lbf/ft**2") - self.prob.set_val(Dynamic.Mission.STATIC_PRESSURE, - (14.696 * 144), units="lbf/ft**2") - self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units="ft") - self.prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, - 0.15723e-3, units="ft**2/s") + self.prob.set_val('slat_defl', 10.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units='deg') + self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units='ft') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units='rad') + + self.prob.set_val('VLAM1', 0.97217) + self.prob.set_val('VLAM2', 1.09948) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.25725) + self.prob.set_val('VLAM5', 1.0000) + self.prob.set_val('VLAM6', 1.0000) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444322) + self.prob.set_val('VLAM9', 0.9975) + self.prob.set_val('VLAM10', 0.74) + self.prob.set_val('VLAM11', 0.84232) + self.prob.set_val('VLAM12', 0.79208) + self.prob.set_val('VLAM13', 1.03512) + self.prob.set_val('VLAM14', 0.99124) + + self.prob.set_val('VDEL1', 1.0) + self.prob.set_val('VDEL2', 0.62455) + self.prob.set_val('VDEL3', 0.765) + self.prob.set_val('VDEL4', 0.93578) + self.prob.set_val('VDEL5', 0.90761) + + self.prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 1118.21948771, units='ft/s') + self.prob.set_val(Aircraft.Design.WING_LOADING, 128.0, units='lbf/ft**2') + self.prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, (14.696 * 144), units='lbf/ft**2') + self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units='ft') + self.prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, 0.15723e-3, units='ft**2/s') self.prob.set_val(Aircraft.Wing.MAX_LIFT_REF, 1.150) self.prob.set_val(Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, 0.930) - self.prob.set_val("fus_lift", 0.05498) + self.prob.set_val('fus_lift', 0.05498) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.500) self.prob.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, 0.1) - self.prob.set_val("flap_defl_ratio", 0.72727273) + self.prob.set_val('flap_defl_ratio', 0.72727273) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') self.prob.set_val(Aircraft.Wing.FLAP_SPAN_RATIO, 0.65) - self.prob.set_val("slat_defl_ratio", 0.5) - self.prob.set_val("body_to_span_ratio", 0.09240447) - self.prob.set_val("chord_to_body_ratio", 0.12679) + self.prob.set_val('slat_defl_ratio', 0.5) + self.prob.set_val('body_to_span_ratio', 0.09240447) + self.prob.set_val('chord_to_body_ratio', 0.12679) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759553) def test_case(self): - self.prob.run_model() tol = 6e-4 # checked. high tol for lack of precision in GASP data. reg_data = 2.8155 - ans = self.prob["CL_max"] + ans = self.prob['CL_max'] assert_near_equal(ans, reg_data, tol) reg_data = 0.17522 - ans = self.prob[Dynamic.Mission.MACH] + ans = self.prob[Dynamic.Atmosphere.MACH] assert_near_equal(ans, reg_data, tol) reg_data = 157.1111 - ans = self.prob["reynolds"] + ans = self.prob['reynolds'] assert_near_equal(ans, reg_data, tol) reg_data = 0.0406 - ans = self.prob["delta_CD"] + ans = self.prob['delta_CD'] assert_near_equal(ans, reg_data, tol) reg_data = 1.0293 - ans = self.prob["delta_CL"] + ans = self.prob['delta_CL'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(method="fd", out_stream=None) + data = self.prob.check_partials(method='fd', out_stream=None) assert_check_partials( data, atol=6315, rtol=7e-3 ) # tolerance at this value for special cases. All other values check out. @@ -120,102 +117,100 @@ def test_case(self): class FlapsGroupTestCaseSplit(unittest.TestCase): def setUp(self): - self.prob = om.Problem() options = get_option_defaults() options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.SPLIT, units='unitless') - self.prob.model = FCC = FlapsGroup(aviary_options=options) + self.prob.model = FlapsGroup() + + setup_model_options(self.prob, options) self.prob.setup() - self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units="deg") - self.prob.set_val(Dynamic.Mission.TEMPERATURE, 518.67, units="degR") + self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units='deg') + self.prob.set_val(Dynamic.Atmosphere.TEMPERATURE, 518.67, units='degR') self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) - self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15) - self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') self.prob.set_val(Aircraft.Wing.SLAT_CHORD_RATIO, 0.15) - self.prob.set_val("slat_defl", 10.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units="deg") - self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units="ft") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units="rad") - - self.prob.set_val("VLAM1", 0.97217) - self.prob.set_val("VLAM2", 1.09948) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.19742) - self.prob.set_val("VLAM5", 1.0000) - self.prob.set_val("VLAM6", 0.8) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444322) - self.prob.set_val("VLAM9", 0.9975) - self.prob.set_val("VLAM10", 0.74) - self.prob.set_val("VLAM11", 0.84232) - self.prob.set_val("VLAM12", 0.79208) - self.prob.set_val("VLAM13", 1.03209) - self.prob.set_val("VLAM14", 0.99082) - - self.prob.set_val("VDEL1", 1.0) - self.prob.set_val("VDEL2", 0.55667) - self.prob.set_val("VDEL3", 0.765) - self.prob.set_val("VDEL4", 0.93578) - self.prob.set_val("VDEL5", 0.90761) - - self.prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, 1118.21948771, units="ft/s") - self.prob.set_val(Aircraft.Wing.LOADING, 128.0, units="lbf/ft**2") - self.prob.set_val(Dynamic.Mission.STATIC_PRESSURE, - (14.696 * 144), units="lbf/ft**2") - self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units="ft") - self.prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, - 0.15723e-3, units="ft**2/s") + self.prob.set_val('slat_defl', 10.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units='deg') + self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units='ft') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units='rad') + + self.prob.set_val('VLAM1', 0.97217) + self.prob.set_val('VLAM2', 1.09948) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.19742) + self.prob.set_val('VLAM5', 1.0000) + self.prob.set_val('VLAM6', 0.8) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444322) + self.prob.set_val('VLAM9', 0.9975) + self.prob.set_val('VLAM10', 0.74) + self.prob.set_val('VLAM11', 0.84232) + self.prob.set_val('VLAM12', 0.79208) + self.prob.set_val('VLAM13', 1.03209) + self.prob.set_val('VLAM14', 0.99082) + + self.prob.set_val('VDEL1', 1.0) + self.prob.set_val('VDEL2', 0.55667) + self.prob.set_val('VDEL3', 0.765) + self.prob.set_val('VDEL4', 0.93578) + self.prob.set_val('VDEL5', 0.90761) + + self.prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 1118.21948771, units='ft/s') + self.prob.set_val(Aircraft.Design.WING_LOADING, 128.0, units='lbf/ft**2') + self.prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, (14.696 * 144), units='lbf/ft**2') + self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units='ft') + self.prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, 0.15723e-3, units='ft**2/s') self.prob.set_val(Aircraft.Wing.MAX_LIFT_REF, 1.150) self.prob.set_val(Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, 0.930) - self.prob.set_val("fus_lift", 0.05498) + self.prob.set_val('fus_lift', 0.05498) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.500) self.prob.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, 0.1) - self.prob.set_val("flap_defl_ratio", 0.6666667) + self.prob.set_val('flap_defl_ratio', 0.6666667) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') self.prob.set_val(Aircraft.Wing.FLAP_SPAN_RATIO, 0.65) - self.prob.set_val("slat_defl_ratio", 0.5) - self.prob.set_val("body_to_span_ratio", 0.09240447) - self.prob.set_val("chord_to_body_ratio", 0.12679) + self.prob.set_val('slat_defl_ratio', 0.5) + self.prob.set_val('body_to_span_ratio', 0.09240447) + self.prob.set_val('chord_to_body_ratio', 0.12679) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759553) def test_case(self): - self.prob.run_model() tol = 9e-4 # checked. high tol for lack of precision in GASP data. reg_data = 2.56197 - ans = self.prob["CL_max"] + ans = self.prob['CL_max'] assert_near_equal(ans, reg_data, tol) reg_data = 0.18368 - ans = self.prob[Dynamic.Mission.MACH] + ans = self.prob[Dynamic.Atmosphere.MACH] assert_near_equal(ans, reg_data, tol) reg_data = 164.78406 - ans = self.prob["reynolds"] + ans = self.prob['reynolds'] assert_near_equal(ans, reg_data, tol) reg_data = 0.0362 - ans = self.prob["delta_CD"] + ans = self.prob['delta_CD'] assert_near_equal(ans, reg_data, tol) reg_data = 0.7816 - ans = self.prob["delta_CL"] + ans = self.prob['delta_CL'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(method="fd", out_stream=None) + data = self.prob.check_partials(method='fd', out_stream=None) assert_check_partials( data, atol=6630, rtol=0.007 ) # tolerance at this value for special cases. All other values check out. @@ -223,104 +218,101 @@ def test_case(self): class FlapsGroupTestCaseSingleSlotted(unittest.TestCase): def setUp(self): - self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, - val=FlapType.SINGLE_SLOTTED, units='unitless') + options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.SINGLE_SLOTTED, units='unitless') + + self.prob.model = FlapsGroup() - self.prob.model = FCC = FlapsGroup(aviary_options=options) + setup_model_options(self.prob, options) self.prob.setup() - self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units="deg") - self.prob.set_val(Dynamic.Mission.TEMPERATURE, 518.67, units="degR") + self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units='deg') + self.prob.set_val(Dynamic.Atmosphere.TEMPERATURE, 518.67, units='degR') self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) - self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15) - self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') self.prob.set_val(Aircraft.Wing.SLAT_CHORD_RATIO, 0.15) - self.prob.set_val("slat_defl", 10.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, 55.0, units="deg") - self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units="ft") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units="rad") - - self.prob.set_val("VLAM1", 0.97217) - self.prob.set_val("VLAM2", 1.09948) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.25725) - self.prob.set_val("VLAM5", 1.0000) - self.prob.set_val("VLAM6", 1.0000) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444322) - self.prob.set_val("VLAM9", 0.9975) - self.prob.set_val("VLAM10", 0.74) - self.prob.set_val("VLAM11", 0.84232) - self.prob.set_val("VLAM12", 0.79208) - self.prob.set_val("VLAM13", 1.03512) - self.prob.set_val("VLAM14", 0.99124) - - self.prob.set_val("VDEL1", 1.0) - self.prob.set_val("VDEL2", 0.62455) - self.prob.set_val("VDEL3", 0.765) - self.prob.set_val("VDEL4", 0.93578) - self.prob.set_val("VDEL5", 0.90761) - - self.prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, 1118.21948771, units="ft/s") - self.prob.set_val(Aircraft.Wing.LOADING, 128.0, units="lbf/ft**2") - self.prob.set_val(Dynamic.Mission.STATIC_PRESSURE, - (14.696 * 144), units="lbf/ft**2") - self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units="ft") - self.prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, - 0.15723e-3, units="ft**2/s") + self.prob.set_val('slat_defl', 10.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, 55.0, units='deg') + self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units='ft') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units='rad') + + self.prob.set_val('VLAM1', 0.97217) + self.prob.set_val('VLAM2', 1.09948) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.25725) + self.prob.set_val('VLAM5', 1.0000) + self.prob.set_val('VLAM6', 1.0000) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444322) + self.prob.set_val('VLAM9', 0.9975) + self.prob.set_val('VLAM10', 0.74) + self.prob.set_val('VLAM11', 0.84232) + self.prob.set_val('VLAM12', 0.79208) + self.prob.set_val('VLAM13', 1.03512) + self.prob.set_val('VLAM14', 0.99124) + + self.prob.set_val('VDEL1', 1.0) + self.prob.set_val('VDEL2', 0.62455) + self.prob.set_val('VDEL3', 0.765) + self.prob.set_val('VDEL4', 0.93578) + self.prob.set_val('VDEL5', 0.90761) + + self.prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 1118.21948771, units='ft/s') + self.prob.set_val(Aircraft.Design.WING_LOADING, 128.0, units='lbf/ft**2') + self.prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, (14.696 * 144), units='lbf/ft**2') + self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units='ft') + self.prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, 0.15723e-3, units='ft**2/s') self.prob.set_val(Aircraft.Wing.MAX_LIFT_REF, 1.150) self.prob.set_val(Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, 0.930) - self.prob.set_val("fus_lift", 0.05498) + self.prob.set_val('fus_lift', 0.05498) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.500) self.prob.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, 0.1) - self.prob.set_val("flap_defl_ratio", 0.72727273) + self.prob.set_val('flap_defl_ratio', 0.72727273) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') self.prob.set_val(Aircraft.Wing.FLAP_SPAN_RATIO, 0.65) - self.prob.set_val("slat_defl_ratio", 0.5) - self.prob.set_val("body_to_span_ratio", 0.09240447) - self.prob.set_val("chord_to_body_ratio", 0.12679) + self.prob.set_val('slat_defl_ratio', 0.5) + self.prob.set_val('body_to_span_ratio', 0.09240447) + self.prob.set_val('chord_to_body_ratio', 0.12679) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759553) def test_case(self): - self.prob.run_model() tol = 6e-4 # checked. high tol for lack of precision in GASP data. reg_data = 2.8155 - ans = self.prob["CL_max"] + ans = self.prob['CL_max'] assert_near_equal(ans, reg_data, tol) reg_data = 0.17522 - ans = self.prob[Dynamic.Mission.MACH] + ans = self.prob[Dynamic.Atmosphere.MACH] assert_near_equal(ans, reg_data, tol) reg_data = 157.1111 - ans = self.prob["reynolds"] + ans = self.prob['reynolds'] assert_near_equal(ans, reg_data, tol) reg_data = 0.0406 - ans = self.prob["delta_CD"] + ans = self.prob['delta_CD'] assert_near_equal(ans, reg_data, tol) reg_data = 1.0293 - ans = self.prob["delta_CL"] + ans = self.prob['delta_CL'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(method="fd", out_stream=None) + data = self.prob.check_partials(method='fd', out_stream=None) assert_check_partials( data, atol=6315, rtol=0.007 ) # tolerance at this value for special cases. All other values check out. @@ -328,102 +320,100 @@ def test_case(self): class FlapsGroupTestCasePlain(unittest.TestCase): def setUp(self): - self.prob = om.Problem() options = get_option_defaults() options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.PLAIN, units='unitless') - self.prob.model = FCC = FlapsGroup(aviary_options=options) + self.prob.model = FlapsGroup() + + setup_model_options(self.prob, options) self.prob.setup() - self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units="deg") - self.prob.set_val(Dynamic.Mission.TEMPERATURE, 518.67, units="degR") + self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units='deg') + self.prob.set_val(Dynamic.Atmosphere.TEMPERATURE, 518.67, units='degR') self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) - self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15) - self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') self.prob.set_val(Aircraft.Wing.SLAT_CHORD_RATIO, 0.15) - self.prob.set_val("slat_defl", 10.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units="deg") - self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units="ft") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units="rad") - - self.prob.set_val("VLAM1", 0.97217) - self.prob.set_val("VLAM2", 1.09948) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.19742) - self.prob.set_val("VLAM5", 1.0000) - self.prob.set_val("VLAM6", 0.8) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444322) - self.prob.set_val("VLAM9", 0.9975) - self.prob.set_val("VLAM10", 0.74) - self.prob.set_val("VLAM11", 0.84232) - self.prob.set_val("VLAM12", 0.79208) - self.prob.set_val("VLAM13", 1.03209) - self.prob.set_val("VLAM14", 0.99082) - - self.prob.set_val("VDEL1", 1.0) - self.prob.set_val("VDEL2", 0.55667) - self.prob.set_val("VDEL3", 0.765) - self.prob.set_val("VDEL4", 0.93578) - self.prob.set_val("VDEL5", 0.90761) - - self.prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, 1118.21948771, units="ft/s") - self.prob.set_val(Aircraft.Wing.LOADING, 128.0, units="lbf/ft**2") - self.prob.set_val(Dynamic.Mission.STATIC_PRESSURE, - (14.696 * 144), units="lbf/ft**2") - self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units="ft") - self.prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, - 0.15723e-3, units="ft**2/s") + self.prob.set_val('slat_defl', 10.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units='deg') + self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units='ft') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units='rad') + + self.prob.set_val('VLAM1', 0.97217) + self.prob.set_val('VLAM2', 1.09948) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.19742) + self.prob.set_val('VLAM5', 1.0000) + self.prob.set_val('VLAM6', 0.8) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444322) + self.prob.set_val('VLAM9', 0.9975) + self.prob.set_val('VLAM10', 0.74) + self.prob.set_val('VLAM11', 0.84232) + self.prob.set_val('VLAM12', 0.79208) + self.prob.set_val('VLAM13', 1.03209) + self.prob.set_val('VLAM14', 0.99082) + + self.prob.set_val('VDEL1', 1.0) + self.prob.set_val('VDEL2', 0.55667) + self.prob.set_val('VDEL3', 0.765) + self.prob.set_val('VDEL4', 0.93578) + self.prob.set_val('VDEL5', 0.90761) + + self.prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 1118.21948771, units='ft/s') + self.prob.set_val(Aircraft.Design.WING_LOADING, 128.0, units='lbf/ft**2') + self.prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, (14.696 * 144), units='lbf/ft**2') + self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units='ft') + self.prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, 0.15723e-3, units='ft**2/s') self.prob.set_val(Aircraft.Wing.MAX_LIFT_REF, 1.150) self.prob.set_val(Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, 0.930) - self.prob.set_val("fus_lift", 0.05498) + self.prob.set_val('fus_lift', 0.05498) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.500) self.prob.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, 0.1) - self.prob.set_val("flap_defl_ratio", 0.6666667) + self.prob.set_val('flap_defl_ratio', 0.6666667) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') self.prob.set_val(Aircraft.Wing.FLAP_SPAN_RATIO, 0.65) - self.prob.set_val("slat_defl_ratio", 0.5) - self.prob.set_val("body_to_span_ratio", 0.09240447) - self.prob.set_val("chord_to_body_ratio", 0.12679) + self.prob.set_val('slat_defl_ratio', 0.5) + self.prob.set_val('body_to_span_ratio', 0.09240447) + self.prob.set_val('chord_to_body_ratio', 0.12679) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759553) def test_case(self): - self.prob.run_model() tol = 9e-4 # checked. high tol for lack of precision in GASP data. reg_data = 2.56197 - ans = self.prob["CL_max"] + ans = self.prob['CL_max'] assert_near_equal(ans, reg_data, tol) reg_data = 0.18368 - ans = self.prob[Dynamic.Mission.MACH] + ans = self.prob[Dynamic.Atmosphere.MACH] assert_near_equal(ans, reg_data, tol) reg_data = 164.78406 - ans = self.prob["reynolds"] + ans = self.prob['reynolds'] assert_near_equal(ans, reg_data, tol) reg_data = 0.0362 - ans = self.prob["delta_CD"] + ans = self.prob['delta_CD'] assert_near_equal(ans, reg_data, tol) reg_data = 0.7816 - ans = self.prob["delta_CL"] + ans = self.prob['delta_CL'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(method="fd", out_stream=None) + data = self.prob.check_partials(method='fd', out_stream=None) assert_check_partials( data, atol=6630, rtol=0.007 ) # tolerance at this value for special cases. All other values check out. @@ -431,102 +421,100 @@ def test_case(self): class FlapsGroupTestCaseFowler(unittest.TestCase): def setUp(self): - self.prob = om.Problem() options = get_option_defaults() options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.FOWLER, units='unitless') - self.prob.model = FCC = FlapsGroup(aviary_options=options) + self.prob.model = FlapsGroup() + + setup_model_options(self.prob, options) self.prob.setup() - self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units="deg") - self.prob.set_val(Dynamic.Mission.TEMPERATURE, 518.67, units="degR") + self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units='deg') + self.prob.set_val(Dynamic.Atmosphere.TEMPERATURE, 518.67, units='degR') self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) - self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15) - self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') self.prob.set_val(Aircraft.Wing.SLAT_CHORD_RATIO, 0.15) - self.prob.set_val("slat_defl", 10.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units="deg") - self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units="ft") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units="rad") - - self.prob.set_val("VLAM1", 0.97217) - self.prob.set_val("VLAM2", 1.09948) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.25725) - self.prob.set_val("VLAM5", 1.0000) - self.prob.set_val("VLAM6", 1.1100) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444322) - self.prob.set_val("VLAM9", 0.9975) - self.prob.set_val("VLAM10", 0.74) - self.prob.set_val("VLAM11", 0.84232) - self.prob.set_val("VLAM12", 0.79208) - self.prob.set_val("VLAM13", 1.03639) - self.prob.set_val("VLAM14", 0.99142) - - self.prob.set_val("VDEL1", 1.0) - self.prob.set_val("VDEL2", 0.64667) - self.prob.set_val("VDEL3", 0.765) - self.prob.set_val("VDEL4", 0.93578) - self.prob.set_val("VDEL5", 0.90761) - - self.prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, 1118.21948771, units="ft/s") - self.prob.set_val(Aircraft.Wing.LOADING, 128.0, units="lbf/ft**2") - self.prob.set_val(Dynamic.Mission.STATIC_PRESSURE, - (14.696 * 144), units="lbf/ft**2") - self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units="ft") - self.prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, - 0.15723e-3, units="ft**2/s") + self.prob.set_val('slat_defl', 10.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units='deg') + self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units='ft') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units='rad') + + self.prob.set_val('VLAM1', 0.97217) + self.prob.set_val('VLAM2', 1.09948) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.25725) + self.prob.set_val('VLAM5', 1.0000) + self.prob.set_val('VLAM6', 1.1100) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444322) + self.prob.set_val('VLAM9', 0.9975) + self.prob.set_val('VLAM10', 0.74) + self.prob.set_val('VLAM11', 0.84232) + self.prob.set_val('VLAM12', 0.79208) + self.prob.set_val('VLAM13', 1.03639) + self.prob.set_val('VLAM14', 0.99142) + + self.prob.set_val('VDEL1', 1.0) + self.prob.set_val('VDEL2', 0.64667) + self.prob.set_val('VDEL3', 0.765) + self.prob.set_val('VDEL4', 0.93578) + self.prob.set_val('VDEL5', 0.90761) + + self.prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 1118.21948771, units='ft/s') + self.prob.set_val(Aircraft.Design.WING_LOADING, 128.0, units='lbf/ft**2') + self.prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, (14.696 * 144), units='lbf/ft**2') + self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units='ft') + self.prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, 0.15723e-3, units='ft**2/s') self.prob.set_val(Aircraft.Wing.MAX_LIFT_REF, 1.150) self.prob.set_val(Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, 0.930) - self.prob.set_val("fus_lift", 0.05498) + self.prob.set_val('fus_lift', 0.05498) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.500) self.prob.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, 0.1) - self.prob.set_val("flap_defl_ratio", 1.333333) + self.prob.set_val('flap_defl_ratio', 1.333333) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') self.prob.set_val(Aircraft.Wing.FLAP_SPAN_RATIO, 0.65) - self.prob.set_val("slat_defl_ratio", 0.5) - self.prob.set_val("body_to_span_ratio", 0.09240447) - self.prob.set_val("chord_to_body_ratio", 0.12679) + self.prob.set_val('slat_defl_ratio', 0.5) + self.prob.set_val('body_to_span_ratio', 0.09240447) + self.prob.set_val('chord_to_body_ratio', 0.12679) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759553) def test_case(self): - self.prob.run_model() tol = 6e-4 # checked. high tol for lack of precision in GASP data. reg_data = 2.93271 - ans = self.prob["CL_max"] + ans = self.prob['CL_max'] assert_near_equal(ans, reg_data, tol) reg_data = 0.17168 - ans = self.prob[Dynamic.Mission.MACH] + ans = self.prob[Dynamic.Atmosphere.MACH] assert_near_equal(ans, reg_data, tol) reg_data = 154.02686 - ans = self.prob["reynolds"] + ans = self.prob['reynolds'] assert_near_equal(ans, reg_data, tol) reg_data = 0.1070 - ans = self.prob["delta_CD"] + ans = self.prob['delta_CD'] assert_near_equal(ans, reg_data, tol) reg_data = 1.1441 - ans = self.prob["delta_CL"] + ans = self.prob['delta_CL'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(method="fd", out_stream=None) + data = self.prob.check_partials(method='fd', out_stream=None) assert_check_partials( data, atol=6200, rtol=0.007 ) # tolerance at this value for special cases. All other values check out. @@ -534,107 +522,106 @@ def test_case(self): class FlapsGroupTestCaseDoubleFowler(unittest.TestCase): def setUp(self): - self.prob = om.Problem() options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, - val=FlapType.DOUBLE_SLOTTED_FOWLER, units='unitless') + options.set_val( + Aircraft.Wing.FLAP_TYPE, val=FlapType.DOUBLE_SLOTTED_FOWLER, units='unitless' + ) - self.prob.model = FCC = FlapsGroup(aviary_options=options) + self.prob.model = FlapsGroup() + + setup_model_options(self.prob, options) self.prob.setup() - self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units="deg") - self.prob.set_val(Dynamic.Mission.TEMPERATURE, 518.67, units="degR") + self.prob.set_val(Aircraft.Wing.SWEEP, 25.0, units='deg') + self.prob.set_val(Dynamic.Atmosphere.TEMPERATURE, 518.67, units='degR') self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) - self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.Wing.CENTER_CHORD, 17.48974, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15) - self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') self.prob.set_val(Aircraft.Wing.SLAT_CHORD_RATIO, 0.15) - self.prob.set_val("slat_defl", 10.0, units="deg") - self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units="deg") - self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units="ft") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units="rad") - - self.prob.set_val("VLAM1", 0.97217) - self.prob.set_val("VLAM2", 1.09948) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.25725) - self.prob.set_val("VLAM5", 1.0000) - self.prob.set_val("VLAM6", 1.1100) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444322) - self.prob.set_val("VLAM9", 0.9975) - self.prob.set_val("VLAM10", 0.74) - self.prob.set_val("VLAM11", 0.84232) - self.prob.set_val("VLAM12", 0.79208) - self.prob.set_val("VLAM13", 1.03639) - self.prob.set_val("VLAM14", 0.99142) - - self.prob.set_val("VDEL1", 1.0) - self.prob.set_val("VDEL2", 0.64667) - self.prob.set_val("VDEL3", 0.765) - self.prob.set_val("VDEL4", 0.93578) - self.prob.set_val("VDEL5", 0.90761) - - self.prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, 1118.21948771, units="ft/s") - self.prob.set_val(Aircraft.Wing.LOADING, 128.0, units="lbf/ft**2") - self.prob.set_val(Dynamic.Mission.STATIC_PRESSURE, - (14.696 * 144), units="lbf/ft**2") - self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units="ft") - self.prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, - 0.15723e-3, units="ft**2/s") + self.prob.set_val('slat_defl', 10.0, units='deg') + self.prob.set_val(Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, 20.0, units='deg') + self.prob.set_val(Aircraft.Wing.ROOT_CHORD, 16.406626, units='ft') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Wing.LEADING_EDGE_SWEEP, 0.47639, units='rad') + + self.prob.set_val('VLAM1', 0.97217) + self.prob.set_val('VLAM2', 1.09948) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.25725) + self.prob.set_val('VLAM5', 1.0000) + self.prob.set_val('VLAM6', 1.1100) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444322) + self.prob.set_val('VLAM9', 0.9975) + self.prob.set_val('VLAM10', 0.74) + self.prob.set_val('VLAM11', 0.84232) + self.prob.set_val('VLAM12', 0.79208) + self.prob.set_val('VLAM13', 1.03639) + self.prob.set_val('VLAM14', 0.99142) + + self.prob.set_val('VDEL1', 1.0) + self.prob.set_val('VDEL2', 0.64667) + self.prob.set_val('VDEL3', 0.765) + self.prob.set_val('VDEL4', 0.93578) + self.prob.set_val('VDEL5', 0.90761) + + self.prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, 1118.21948771, units='ft/s') + self.prob.set_val(Aircraft.Design.WING_LOADING, 128.0, units='lbf/ft**2') + self.prob.set_val(Dynamic.Atmosphere.STATIC_PRESSURE, (14.696 * 144), units='lbf/ft**2') + self.prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.61, units='ft') + self.prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, 0.15723e-3, units='ft**2/s') self.prob.set_val(Aircraft.Wing.MAX_LIFT_REF, 1.150) self.prob.set_val(Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, 0.930) - self.prob.set_val("fus_lift", 0.05498) + self.prob.set_val('fus_lift', 0.05498) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.500) self.prob.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, 0.1) - self.prob.set_val("flap_defl_ratio", 1.333333) + self.prob.set_val('flap_defl_ratio', 1.333333) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') self.prob.set_val(Aircraft.Wing.FLAP_SPAN_RATIO, 0.65) - self.prob.set_val("slat_defl_ratio", 0.5) - self.prob.set_val("body_to_span_ratio", 0.09240447) - self.prob.set_val("chord_to_body_ratio", 0.12679) + self.prob.set_val('slat_defl_ratio', 0.5) + self.prob.set_val('body_to_span_ratio', 0.09240447) + self.prob.set_val('chord_to_body_ratio', 0.12679) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89759553) def test_case(self): - self.prob.run_model() tol = 6e-4 # checked. high tol for lack of precision in GASP data. reg_data = 2.93271 - ans = self.prob["CL_max"] + ans = self.prob['CL_max'] assert_near_equal(ans, reg_data, tol) reg_data = 0.17168 - ans = self.prob[Dynamic.Mission.MACH] + ans = self.prob[Dynamic.Atmosphere.MACH] assert_near_equal(ans, reg_data, tol) reg_data = 154.02686 - ans = self.prob["reynolds"] + ans = self.prob['reynolds'] assert_near_equal(ans, reg_data, tol) reg_data = 0.1070 - ans = self.prob["delta_CD"] + ans = self.prob['delta_CD'] assert_near_equal(ans, reg_data, tol) reg_data = 1.1441 - ans = self.prob["delta_CL"] + ans = self.prob['delta_CL'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(method="fd", out_stream=None) + data = self.prob.check_partials(method='fd', out_stream=None) assert_check_partials( data, atol=6200, rtol=0.007 ) # tolerance at this value for special cases. All other values check out. -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_increments.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_increments.py index 8e9fa1ebb3..920add3b53 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_increments.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_increments.py @@ -1,11 +1,11 @@ import unittest -import os import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.L_and_D_increments import \ - LiftAndDragIncrements +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.L_and_D_increments import ( + LiftAndDragIncrements, +) from aviary.variable_info.variables import Aircraft """ @@ -15,7 +15,6 @@ class LiftAndDragIncrementsTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem(model=om.Group()) self.prob.model.add_subsystem('LaDIs', LiftAndDragIncrements(), promotes=['*']) @@ -25,37 +24,36 @@ def setUp(self): # initial conditions self.prob.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, 0.1) self.prob.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, 1.5) - self.prob.set_val("VDEL1", 1.0) - self.prob.set_val("VDEL2", 1) - self.prob.set_val("VDEL3", 0.765) - self.prob.set_val("VDEL4", 0.93578) - self.prob.set_val("VDEL5", 0.90761) - self.prob.set_val("VLAM3", 0.97217) - self.prob.set_val("VLAM4", 1.25725) - self.prob.set_val("VLAM5", 1.0) - self.prob.set_val("VLAM6", 1.0) - self.prob.set_val("VLAM7", 0.735) - self.prob.set_val("VLAM8", 0.74444) - self.prob.set_val("VLAM13", 1.03512) - self.prob.set_val("VLAM14", 0.99124) + self.prob.set_val('VDEL1', 1.0) + self.prob.set_val('VDEL2', 1) + self.prob.set_val('VDEL3', 0.765) + self.prob.set_val('VDEL4', 0.93578) + self.prob.set_val('VDEL5', 0.90761) + self.prob.set_val('VLAM3', 0.97217) + self.prob.set_val('VLAM4', 1.25725) + self.prob.set_val('VLAM5', 1.0) + self.prob.set_val('VLAM6', 1.0) + self.prob.set_val('VLAM7', 0.735) + self.prob.set_val('VLAM8', 0.74444) + self.prob.set_val('VLAM13', 1.03512) + self.prob.set_val('VLAM14', 0.99124) def test_case(self): - self.prob.run_model() tol = 5e-4 print() reg_data = 0.0650 - ans = self.prob["delta_CD"] + ans = self.prob['delta_CD'] assert_near_equal(ans, reg_data, tol) reg_data = 1.0293 - ans = self.prob["delta_CL"] + ans = self.prob['delta_CL'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(out_stream=None, method="fd") + data = self.prob.check_partials(out_stream=None, method='fd') assert_check_partials(data, atol=1e-4, rtol=1e-4) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py index 84581a8ea5..488a766b09 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py +++ b/aviary/subsystems/aerodynamics/gasp_based/flaps_model/test/test_metamodel.py @@ -1,14 +1,10 @@ import unittest -import os import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.flaps_model.meta_model import \ - MetaModelGroup +from aviary.subsystems.aerodynamics.gasp_based.flaps_model.meta_model import MetaModelGroup from aviary.variable_info.enums import FlapType -from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic """ @@ -18,164 +14,160 @@ class MetaModelTestCasePlain(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.PLAIN, units='unitless') - self.prob.model = LuTMMa = MetaModelGroup(aviary_options=options) + options = { + Aircraft.Wing.FLAP_TYPE: FlapType.PLAIN, + } + self.prob.model = MetaModelGroup(**options) self.prob.setup() self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) - self.prob.set_val("flap_defl_ratio", 40 / 60) + self.prob.set_val('flap_defl_ratio', 40 / 60) self.prob.set_val(Aircraft.Wing.ASPECT_RATIO, 10.13) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') self.prob.set_val(Aircraft.Wing.FLAP_SPAN_RATIO, 0.65) - self.prob.set_val("slat_defl_ratio", 10 / 20) + self.prob.set_val('slat_defl_ratio', 10 / 20) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89761) - self.prob.set_val("reynolds", 164.78406) - self.prob.set_val(Dynamic.Mission.MACH, 0.18368) + self.prob.set_val('reynolds', 164.78406) + self.prob.set_val(Dynamic.Atmosphere.MACH, 0.18368) self.prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.33) self.prob.set_val(Aircraft.Wing.SLAT_SPAN_RATIO, 0.89761) - self.prob.set_val("body_to_span_ratio", 0.09239) - self.prob.set_val("chord_to_body_ratio", 0.12679) + self.prob.set_val('body_to_span_ratio', 0.09239) + self.prob.set_val('chord_to_body_ratio', 0.12679) def test_case(self): - self.prob.run_model() tol = 1e-4 reg_data = 1 - ans = self.prob["VDEL1"] + ans = self.prob['VDEL1'] assert_near_equal(ans, reg_data, tol) reg_data = 0.55667 - ans = self.prob["VDEL2"] + ans = self.prob['VDEL2'] assert_near_equal(ans, reg_data, tol) reg_data = 0.76500 - ans = self.prob["VDEL3"] + ans = self.prob['VDEL3'] assert_near_equal(ans, reg_data, tol) reg_data = 0.05498 - ans = self.prob["fus_lift"] + ans = self.prob['fus_lift'] assert_near_equal(ans, reg_data, tol) reg_data = 0.97217 - ans = self.prob["VLAM1"] + ans = self.prob['VLAM1'] assert_near_equal(ans, reg_data, tol) reg_data = 1.09948 - ans = self.prob["VLAM2"] + ans = self.prob['VLAM2'] assert_near_equal(ans, reg_data, tol) reg_data = 0.97217 - ans = self.prob["VLAM3"] + ans = self.prob['VLAM3'] assert_near_equal(ans, reg_data, tol) reg_data = 1.19742 - ans = self.prob["VLAM4"] + ans = self.prob['VLAM4'] assert_near_equal(ans, reg_data, tol) reg_data = 1 - ans = self.prob["VLAM5"] + ans = self.prob['VLAM5'] assert_near_equal(ans, reg_data, tol) reg_data = 0.80000 - ans = self.prob["VLAM6"] + ans = self.prob['VLAM6'] assert_near_equal(ans, reg_data, tol) reg_data = 0.73500 - ans = self.prob["VLAM7"] + ans = self.prob['VLAM7'] assert_near_equal(ans, reg_data, tol) reg_data = 0.74000 - ans = self.prob["VLAM10"] + ans = self.prob['VLAM10'] assert_near_equal(ans, reg_data, tol) reg_data = 0.84232 - ans = self.prob["VLAM11"] + ans = self.prob['VLAM11'] assert_near_equal(ans, reg_data, tol) reg_data = 1.03209 - ans = self.prob["VLAM13"] + ans = self.prob['VLAM13'] assert_near_equal(ans, reg_data, tol) reg_data = 0.99082 - ans = self.prob["VLAM14"] + ans = self.prob['VLAM14'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(out_stream=None, method="fd") + data = self.prob.check_partials(out_stream=None, method='fd') assert_check_partials(data, atol=1e-4, rtol=1e-4) class MetaModelTestCaseSingleSlotted(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, - val=FlapType.SINGLE_SLOTTED, units='unitless') - self.prob.model = LuTMMb = MetaModelGroup(aviary_options=options) + options = { + Aircraft.Wing.FLAP_TYPE: FlapType.SINGLE_SLOTTED, + } + self.prob.model = MetaModelGroup(**options) self.prob.setup() self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) self.prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13966) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') def test_case(self): - self.prob.run_model() tol = 1e-4 reg_data = 1 - ans = self.prob["VDEL1"] + ans = self.prob['VDEL1'] assert_near_equal(ans, reg_data, tol) reg_data = 1.25725 - ans = self.prob["VLAM4"] + ans = self.prob['VLAM4'] assert_near_equal(ans, reg_data, tol) reg_data = 1 - ans = self.prob["VLAM5"] + ans = self.prob['VLAM5'] assert_near_equal(ans, reg_data, tol) reg_data = 1.0 - ans = self.prob["VLAM6"] + ans = self.prob['VLAM6'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(out_stream=None, method="fd") + data = self.prob.check_partials(out_stream=None, method='fd') assert_check_partials(data, atol=1e-4, rtol=1e-4) class MetaModelTestCaseFowler(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - options = get_option_defaults() - options.set_val(Aircraft.Wing.FLAP_TYPE, val=FlapType.FOWLER, units='unitless') - self.prob.model = LuTMMc = MetaModelGroup(aviary_options=options) + options = { + Aircraft.Wing.FLAP_TYPE: FlapType.FOWLER, + } + self.prob.model = MetaModelGroup(**options) self.prob.setup() self.prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3) - self.prob.set_val("flap_defl", 40.0, units="deg") + self.prob.set_val('flap_defl', 40.0, units='deg') def test_case(self): - self.prob.run_model() tol = 1e-4 reg_data = 1.0 - ans = self.prob["VLAM5"] + ans = self.prob['VLAM5'] assert_near_equal(ans, reg_data, tol) reg_data = 1.11 - ans = self.prob["VLAM6"] + ans = self.prob['VLAM6'] assert_near_equal(ans, reg_data, tol) - data = self.prob.check_partials(out_stream=None, method="fd") + data = self.prob.check_partials(out_stream=None, method='fd') assert_check_partials(data, atol=1e-4, rtol=1e-4) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py b/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py index 0d015677ef..000f797d6e 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gasp_aero_coeffs.py @@ -2,75 +2,110 @@ import openmdao.api as om from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Dynamic, Mission - +from aviary.variable_info.variables import Aircraft, Mission SWETFCT = 1.02 class AeroFormfactors(om.ExplicitComponent): - """Compute aero form factors""" + """Compute aero form factors.""" def setup(self): - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED) + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, units='unitless') # add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP) - add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD) - add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD) - add_aviary_input(self, Aircraft.Strut.THICKNESS_TO_CHORD) + add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Strut.THICKNESS_TO_CHORD, units='unitless') add_aviary_input(self, Aircraft.Wing.SWEEP, units='rad') add_aviary_input(self, Aircraft.VerticalTail.SWEEP, units='rad') add_aviary_input(self, Aircraft.HorizontalTail.SWEEP, units='rad') - add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0) - add_aviary_input(self, Mission.Design.MACH) - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER) - add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH) - - add_aviary_output(self, Aircraft.Wing.FORM_FACTOR, 1.23456) - # add_aviary_output(self, Aircraft.Winglet.FORM_FACTOR) - add_aviary_output(self, Aircraft.VerticalTail.FORM_FACTOR, 1.23456) - add_aviary_output(self, Aircraft.HorizontalTail.FORM_FACTOR, 1.23456) - add_aviary_output(self, Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, 1.23456) - add_aviary_output(self, Aircraft.Nacelle.FORM_FACTOR, 1.23456) + add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, units='unitless') + add_aviary_input(self, Mission.Design.MACH, units='unitless') + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, units='ft') + + add_aviary_output(self, Aircraft.Wing.FORM_FACTOR, units='unitless') + add_aviary_output(self, Aircraft.VerticalTail.FORM_FACTOR, units='unitless') + add_aviary_output(self, Aircraft.HorizontalTail.FORM_FACTOR, units='unitless') + add_aviary_output(self, Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, units='unitless') + add_aviary_output(self, Aircraft.Nacelle.FORM_FACTOR, units='unitless') def setup_partials(self): self.declare_partials( - Aircraft.Wing.FORM_FACTOR, [ - Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, - Mission.Design.MACH, - Aircraft.Wing.SWEEP]) + Aircraft.Wing.FORM_FACTOR, + [Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Mission.Design.MACH, Aircraft.Wing.SWEEP], + ) self.declare_partials( - Aircraft.VerticalTail.FORM_FACTOR, [ + Aircraft.VerticalTail.FORM_FACTOR, + [ Aircraft.VerticalTail.THICKNESS_TO_CHORD, Mission.Design.MACH, - Aircraft.VerticalTail.SWEEP]) + Aircraft.VerticalTail.SWEEP, + ], + ) self.declare_partials( - Aircraft.HorizontalTail.FORM_FACTOR, [ + Aircraft.HorizontalTail.FORM_FACTOR, + [ Aircraft.HorizontalTail.THICKNESS_TO_CHORD, Mission.Design.MACH, Aircraft.HorizontalTail.SWEEP, - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION]) + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, + ], + ) self.declare_partials( - Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, [ - Aircraft.Strut.THICKNESS_TO_CHORD, - Mission.Design.MACH]) + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, + [Aircraft.Strut.THICKNESS_TO_CHORD, Mission.Design.MACH], + ) self.declare_partials( - Aircraft.Nacelle.FORM_FACTOR, [ - Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Nacelle.AVG_LENGTH]) + Aircraft.Nacelle.FORM_FACTOR, + [Aircraft.Nacelle.AVG_DIAMETER, Aircraft.Nacelle.AVG_LENGTH], + ) def compute(self, inputs, outputs): tc, tcvt, tcht, tcstrt, rlmc4, rswpvt, rswpht, sah, smn, dbarn, xln = inputs.values() - ckw = 2.*SWETFCT*(1. + tc * (2.-smn**2)*np.cos(rlmc4) / - np.sqrt(1.-smn**2*(np.cos(rlmc4))**2) + 100.*tc**4) + ckw = ( + 2.0 + * SWETFCT + * ( + 1.0 + + tc * (2.0 - smn**2) * np.cos(rlmc4) / np.sqrt(1.0 - smn**2 * (np.cos(rlmc4)) ** 2) + + 100.0 * tc**4 + ) + ) # ckwglt=2.*SWETFCT*(1. +tct*(2.-smn**2)*np.cos(rlmc4) /np.sqrt(1.-smn**2*(np.cos(rlmc4 ))**2) + 100.*tct**4) - ckvt = 2.*SWETFCT*(1.+tcvt*(2.-smn**2)*np.cos(rswpvt) / - np.sqrt(1.-smn**2*(np.cos(rswpvt))**2) + 100.*tcvt**4) - ckht = 2.*SWETFCT*(1.+tcht*(2.-smn**2)*np.cos(rswpht)/np.sqrt(1. - - smn**2*(np.cos(rswpht))**2) + 100.*tcht**4)*(1.+.05*(1.-sah)) - ckstrt = 2.*SWETFCT*(1.+tcstrt*(2.-smn**2) / np.sqrt(1.-smn**2) + 100.*tcstrt**4) - - ckn = 1.5*(1.+.35/(xln/dbarn)) + ckvt = ( + 2.0 + * SWETFCT + * ( + 1.0 + + tcvt + * (2.0 - smn**2) + * np.cos(rswpvt) + / np.sqrt(1.0 - smn**2 * (np.cos(rswpvt)) ** 2) + + 100.0 * tcvt**4 + ) + ) + ckht = ( + 2.0 + * SWETFCT + * ( + 1.0 + + tcht + * (2.0 - smn**2) + * np.cos(rswpht) + / np.sqrt(1.0 - smn**2 * (np.cos(rswpht)) ** 2) + + 100.0 * tcht**4 + ) + * (1.0 + 0.05 * (1.0 - sah)) + ) + ckstrt = ( + 2.0 + * SWETFCT + * (1.0 + tcstrt * (2.0 - smn**2) / np.sqrt(1.0 - smn**2) + 100.0 * tcstrt**4) + ) + + ckn = 1.5 * (1.0 + 0.35 / (xln / dbarn)) outputs[Aircraft.Wing.FORM_FACTOR] = ckw # outputs[Aircraft.Winglet.FORM_FACTOR] = ckwglt @@ -83,39 +118,59 @@ def compute_partials(self, inputs, J): tc, tcvt, tcht, tcstrt, rlmc4, rswpvt, rswpht, sah, smn, dbarn, xln = inputs.values() cos1 = np.cos(rlmc4) - A1 = np.sqrt(1.-smn**2*(cos1)**2) - J[Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED] = 2 * \ - SWETFCT * ((2-smn**2)*cos1/A1 + 400*tc**3) - J[Aircraft.Wing.FORM_FACTOR, Mission.Design.MACH] = -2 * \ - SWETFCT*(tc*smn*cos1) * ((A1**2 + 1 - 2*cos1**2)/A1**3) - J[Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.SWEEP] = - \ - 2*SWETFCT*(tc*(2-smn**2)*np.sin(rlmc4)) * (1/A1**3) + A1 = np.sqrt(1.0 - smn**2 * (cos1) ** 2) + J[Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED] = ( + 2 * SWETFCT * ((2 - smn**2) * cos1 / A1 + 400 * tc**3) + ) + J[Aircraft.Wing.FORM_FACTOR, Mission.Design.MACH] = ( + -2 * SWETFCT * (tc * smn * cos1) * ((A1**2 + 1 - 2 * cos1**2) / A1**3) + ) + J[Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.SWEEP] = ( + -2 * SWETFCT * (tc * (2 - smn**2) * np.sin(rlmc4)) * (1 / A1**3) + ) cos2 = np.cos(rswpvt) - A2 = np.sqrt(1.-smn**2*(cos2)**2) - J[Aircraft.VerticalTail.FORM_FACTOR, Aircraft.VerticalTail.THICKNESS_TO_CHORD] = 2 * \ - SWETFCT * ((2-smn**2)*cos2/A2 + 400*tcvt**3) - J[Aircraft.VerticalTail.FORM_FACTOR, Mission.Design.MACH] = - \ - 2*SWETFCT*(tcvt*smn*cos2) * ((A2**2 + 1 - 2*cos2**2)/A2**3) - J[Aircraft.VerticalTail.FORM_FACTOR, Aircraft.VerticalTail.SWEEP] = - \ - 2*SWETFCT*(tcvt*(2-smn**2)*np.sin(rswpvt)) * (1/A2**3) + A2 = np.sqrt(1.0 - smn**2 * (cos2) ** 2) + J[Aircraft.VerticalTail.FORM_FACTOR, Aircraft.VerticalTail.THICKNESS_TO_CHORD] = ( + 2 * SWETFCT * ((2 - smn**2) * cos2 / A2 + 400 * tcvt**3) + ) + J[Aircraft.VerticalTail.FORM_FACTOR, Mission.Design.MACH] = ( + -2 * SWETFCT * (tcvt * smn * cos2) * ((A2**2 + 1 - 2 * cos2**2) / A2**3) + ) + J[Aircraft.VerticalTail.FORM_FACTOR, Aircraft.VerticalTail.SWEEP] = ( + -2 * SWETFCT * (tcvt * (2 - smn**2) * np.sin(rswpvt)) * (1 / A2**3) + ) cos3 = np.cos(rswpht) - A3 = np.sqrt(1.-smn**2*(cos3)**2) - J[Aircraft.HorizontalTail.FORM_FACTOR, Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = 2 * \ - SWETFCT * ((2-smn**2)*cos3/A3 + 400*tcht**3) * (1.+.05*(1.-sah)) - J[Aircraft.HorizontalTail.FORM_FACTOR, Mission.Design.MACH] = -2*SWETFCT * \ - (tcht*smn*cos3) * ((A3**2 + 1 - 2*cos3**2)/A3**3) * (1.+.05*(1.-sah)) - J[Aircraft.HorizontalTail.FORM_FACTOR, Aircraft.HorizontalTail.SWEEP] = -2 * \ - SWETFCT*(tcht*(2-smn**2)*np.sin(rswpht)) * (1/A3**3) * (1.+.05*(1.-sah)) - J[Aircraft.HorizontalTail.FORM_FACTOR, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] = 2 * \ - SWETFCT * (1 + tcht*(2-smn**2)*cos3/A3 + 100*tcht**4) * -.05 - - A4 = np.sqrt(1.-smn**2) - J[Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, - Aircraft.Strut.THICKNESS_TO_CHORD] = 2*SWETFCT * ((2-smn**2)/A4 + 400*tcstrt**3) - J[Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, Mission.Design.MACH] = - \ - 2*SWETFCT*(tcstrt*smn) * ((A4**2 - 1)/A4**3) - - J[Aircraft.Nacelle.FORM_FACTOR, Aircraft.Nacelle.AVG_DIAMETER] = 1.5*.35/xln - J[Aircraft.Nacelle.FORM_FACTOR, Aircraft.Nacelle.AVG_LENGTH] = -1.5*.35*dbarn/xln**2 + A3 = np.sqrt(1.0 - smn**2 * (cos3) ** 2) + J[Aircraft.HorizontalTail.FORM_FACTOR, Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = ( + 2 * SWETFCT * ((2 - smn**2) * cos3 / A3 + 400 * tcht**3) * (1.0 + 0.05 * (1.0 - sah)) + ) + J[Aircraft.HorizontalTail.FORM_FACTOR, Mission.Design.MACH] = ( + -2 + * SWETFCT + * (tcht * smn * cos3) + * ((A3**2 + 1 - 2 * cos3**2) / A3**3) + * (1.0 + 0.05 * (1.0 - sah)) + ) + J[Aircraft.HorizontalTail.FORM_FACTOR, Aircraft.HorizontalTail.SWEEP] = ( + -2 + * SWETFCT + * (tcht * (2 - smn**2) * np.sin(rswpht)) + * (1 / A3**3) + * (1.0 + 0.05 * (1.0 - sah)) + ) + J[Aircraft.HorizontalTail.FORM_FACTOR, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] = ( + 2 * SWETFCT * (1 + tcht * (2 - smn**2) * cos3 / A3 + 100 * tcht**4) * -0.05 + ) + + A4 = np.sqrt(1.0 - smn**2) + J[Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, Aircraft.Strut.THICKNESS_TO_CHORD] = ( + 2 * SWETFCT * ((2 - smn**2) / A4 + 400 * tcstrt**3) + ) + J[Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, Mission.Design.MACH] = ( + -2 * SWETFCT * (tcstrt * smn) * ((A4**2 - 1) / A4**3) + ) + + J[Aircraft.Nacelle.FORM_FACTOR, Aircraft.Nacelle.AVG_DIAMETER] = 1.5 * 0.35 / xln + J[Aircraft.Nacelle.FORM_FACTOR, Aircraft.Nacelle.AVG_LENGTH] = -1.5 * 0.35 * dbarn / xln**2 diff --git a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py index abb839cbe2..d4a2ddbad6 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/gaspaero.py @@ -1,19 +1,14 @@ -import numpy as np import warnings - +import numpy as np import openmdao.api as om from openmdao.utils import cs_safe as cs from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.aerodynamics.gasp_based.common import (AeroForces, - CLFromLift, - TanhRampComp) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.utils.aviary_values import AviaryValues -from aviary.subsystems.aerodynamics.gasp_based.interference import WingFuselageInterferenceMission - +from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces, CLFromLift, TanhRampComp +from aviary.utils.functions import sigmoidX, smooth_min, d_smooth_min +from aviary.variable_info.enums import AircraftTypes, Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings # # data from EAERO @@ -45,79 +40,44 @@ # data from DRAG # # flap deflection angles, deg +# block auto-formatting of tables +# autopep8: off +# fmt: off adelfd = np.array( [ - 0.0, - 5.0, - 10.0, - 15.0, - 20.0, - 25.0, - 30.0, - 35.0, - 38.0, - 40.0, - 42.0, - 44.0, - 50.0, - 55.0, - 60.0, + 0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, + 38.0, 40.0, 42.0, 44.0, 50.0, 55.0, 60.0, ] ) # flap angle correction of oswald efficiency factor adel6 = np.array( [ - 1.0, - 0.995, - 0.99, - 0.98, - 0.97, - 0.955, - 0.935, - 0.90, - 0.875, - 0.855, - 0.83, - 0.80, - 0.70, - 0.54, - 0.30, + 1.0, 0.995, 0.99, 0.98, 0.97, 0.955, 0.935, 0.90, + 0.875, 0.855, 0.83, 0.80, 0.70, 0.54, 0.30, ] ) # induced drag correction factors asigma = np.array( [ - 0.0, - 0.16, - 0.285, - 0.375, - 0.435, - 0.48, - 0.52, - 0.55, - 0.575, - 0.58, - 0.59, - 0.60, - 0.62, - 0.635, - 0.65, + 0.0, 0.16, 0.285, 0.375, 0.435, 0.48, 0.52, 0.55, + 0.575, 0.58, 0.59, 0.60, 0.62, 0.635, 0.65, ] ) - +# autopep8: off +# fmt: off def deg2rad(d): - """Complex step safe deg2rad""" + """Complex step safe deg2rad.""" return d * np.pi / 180.0 def rad2deg(r): - """Complex step safe rad2deg""" + """Complex step safe rad2deg.""" return r * 180.0 / np.pi def cla(ar, sweep, mach): - """Lift-curve slope of 3D wings from Seckel equation + """Lift-curve slope of 3D wings from Seckel equation. cla is per radian. Parameters ---------- @@ -131,90 +91,84 @@ def cla(ar, sweep, mach): return ( np.pi * ar - / ( - 1 - + np.sqrt( - 1 - + ( - ((ar / (2 * np.cos(sweep))) ** 2) - * (1 - (mach * np.cos(sweep)) ** 2) - ) - ) - ) + / (1 + np.sqrt(1 + (((ar / (2 * np.cos(sweep))) ** 2) * (1 - (mach * np.cos(sweep)) ** 2)))) ) -def sigmoid(x, x0, alpha=0.1): - """Sigmoid used to smoothly transition between piecewise functions""" - if alpha == 0: - raise ValueError("alpha must be non-zero") - return 1 / (1 + np.exp(-(x - x0) / alpha)) - - class WingTailRatios(om.ExplicitComponent): - """Pre-mission calculation of ratios between tail and wing parameters""" + # NOTE this is actually getting added in mission, not pre-mission. Which place is + # intended for this component?? + """Pre-mission calculation of ratios between tail and wing parameters.""" - def setup(self): + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) - add_aviary_input(self, Aircraft.Wing.AREA, val=1370.3) + def setup(self): + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') - add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, val=0.0) + add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15) + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') - add_aviary_input(self, Aircraft.Wing.MOUNTING_TYPE, val=0.0) + add_aviary_input(self, Aircraft.Wing.VERTICAL_MOUNT_LOCATION, units='unitless') - add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, units='unitless') - add_aviary_input(self, Aircraft.HorizontalTail.SPAN, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.SPAN, units='ft') - add_aviary_input(self, Aircraft.VerticalTail.SPAN, val=0.0) + add_aviary_input(self, Aircraft.VerticalTail.SPAN, units='ft') - add_aviary_input(self, Aircraft.HorizontalTail.AREA, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') - add_aviary_input(self, Aircraft.HorizontalTail.AVERAGE_CHORD, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=0.0) + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') self.add_output( - "hbar", val=0.0, units="unitless", - desc="HBAR: Ratio of HGAP(?) to wing span") - self.add_output( - "bbar", units="unitless", desc="BBAR: Ratio of H tail area to wing area") - self.add_output( - "sbar", units="unitless", desc="SBAR: Ratio of H tail area to wing area") + 'hbar', + val=0.0, + units='unitless', + desc='HBAR: Ratio of HGAP(?) to wing span', + ) + self.add_output('bbar', units='unitless', desc='BBAR: Ratio of H tail area to wing span') + self.add_output('sbar', units='unitless', desc='SBAR: Ratio of H tail area to wing area') + self.add_output('cbar', units='unitless', desc='CBAR: Ratio of H tail chord to wing chord') self.add_output( - "cbar", units="unitless", desc="SBAR: Ratio of H tail chord to wing chord") + 'bbar_alt', units='unitless', desc='BHTqB: Ratio of H tail area to wing span' + ) def setup_partials(self): self.declare_partials( - "hbar", + 'hbar', [ Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, Aircraft.VerticalTail.SPAN, Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Wing.MOUNTING_TYPE, + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, Aircraft.Wing.AREA, Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO, ], - method="cs", + method='cs', ) self.declare_partials( - "bbar", [Aircraft.HorizontalTail.SPAN, Aircraft.Wing.SPAN], method="cs" + 'bbar', [Aircraft.HorizontalTail.SPAN, Aircraft.Wing.SPAN], method='cs' ) self.declare_partials( - "sbar", [Aircraft.HorizontalTail.AREA, Aircraft.Wing.AREA], method="cs" + 'sbar', [Aircraft.HorizontalTail.AREA, Aircraft.Wing.AREA], method='cs' ) self.declare_partials( - "cbar", + 'cbar', [Aircraft.HorizontalTail.AVERAGE_CHORD, Aircraft.Wing.AVERAGE_CHORD], - method="cs", + method='cs', + ) + self.declare_partials( + 'bbar_alt', [Aircraft.HorizontalTail.SPAN, Aircraft.Wing.SPAN], method='cs' ) def compute(self, inputs, outputs): @@ -232,86 +186,159 @@ def compute(self, inputs, outputs): htail_chord, cabin_width, ) = inputs.values() + verbosity = self.options[Settings.VERBOSITY] + + if wing_area == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.AREA is 0.0 in WingTailRatios.') + if wingspan == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.SPAN is 0.0 in WingTailRatios.') + if avg_chord == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.AVERAGE_CHORD is 0.0 in WingTailRatios.') trtw = tc_ratio_root * 2 * wing_area / wingspan / (1 + taper_ratio) - hgap = cs.abs( - htail_loc * span_vtail - 0.5 * (cabin_width - trtw) * (2 * wing_loc - 1) + hgap = cs.abs(htail_loc * span_vtail - 0.5 * (cabin_width - trtw) * (2 * wing_loc - 1)) + outputs['hbar'] = hgap / wingspan + outputs['bbar'] = span_htail / wingspan + outputs['sbar'] = htail_area / wing_area + outputs['cbar'] = htail_chord / avg_chord + # bbar_alt is a modified bbar for tailless BWB + if span_htail < 0.01 * wingspan: + outputs['bbar_alt'] = 1.0 + else: + outputs['bbar_alt'] = outputs['bbar'] + + +class BWBBodyLiftCurveSlope(om.ExplicitComponent): + """Compute body lift curve slope of BWB.""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + nn = self.options['num_nodes'] + # mission inputs + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, units='1/rad') + + self.add_output( + 'body_lift_curve_slope', + units='unitless', + shape=nn, + desc='CLALPH_B: Lift-curve slope of fuselage for the given Mach', + ) + + def setup_partials(self): + arange = np.arange(self.options['num_nodes']) + self.declare_partials( + 'body_lift_curve_slope', + Dynamic.Atmosphere.MACH, + rows=arange, + cols=arange, + ) + self.declare_partials( + 'body_lift_curve_slope', + Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + mach = inputs[Dynamic.Atmosphere.MACH] + + # Provide a little buffer for being close to the limit. + eps = 1e-8 + + if any(x < -eps or x >= 1.0 + eps for x in mach.real): + raise om.AnalysisError('Mach number must be within the range (0, 1).') + elif any(x > 0.8 + eps for x in mach.real): + if verbosity > Verbosity.BRIEF: + warnings.warn( + f"Mach range should be less or equal to 0.8. You've provided a Mach number {mach}." + ) + CLALPH_B0 = inputs[Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0] + CLALPH_B = CLALPH_B0 / np.sqrt(1.0 - mach**2) + outputs['body_lift_curve_slope'] = CLALPH_B + + def compute_partials(self, inputs, J): + mach = inputs[Dynamic.Atmosphere.MACH] + CLALPH_B0 = inputs[Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0] + J['body_lift_curve_slope', Dynamic.Atmosphere.MACH] = ( + CLALPH_B0 * mach / (np.sqrt(1.0 - mach**2)) ** 3 + ) + J['body_lift_curve_slope', Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0] = 1 / np.sqrt( + 1.0 - mach**2 ) - outputs["hbar"] = hgap / wingspan - outputs["bbar"] = span_htail / wingspan - outputs["sbar"] = htail_area / wing_area - outputs["cbar"] = htail_chord / avg_chord class Xlifts(om.ExplicitComponent): - """Compute lift ratio and lift-curve slope for given stability margin""" + """Compute lift ratio and lift-curve slope for given stability margin.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Settings.VERBOSITY) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # mission inputs - self.add_input(Dynamic.Mission.MACH, val=0.0, units="unitless", - shape=nn, desc="Mach number") + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') # stability inputs - add_aviary_input(self, Aircraft.Design.STATIC_MARGIN, val=0.03) + add_aviary_input(self, Aircraft.Design.STATIC_MARGIN, units='unitless') - add_aviary_input(self, Aircraft.Design.CG_DELTA, val=0.25) + add_aviary_input(self, Aircraft.Design.CG_DELTA, units='unitless') # geometry inputs - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') - add_aviary_input(self, Aircraft.Wing.SWEEP, val=25.0) + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') - add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, units='unitless') - add_aviary_input(self, Aircraft.HorizontalTail.SWEEP, val=25.0) + add_aviary_input(self, Aircraft.HorizontalTail.SWEEP, units='deg') - add_aviary_input(self, Aircraft.HorizontalTail.MOMENT_RATIO, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.MOMENT_RATIO, units='unitless') # geometry from wing-tail ratios - self.add_input( - "sbar", units="unitless", desc="SBAR: Ratio of H tail area to wing area") - self.add_input( - "cbar", units="unitless", desc="CBAR: Ratio of H tail chord to wing chord") - self.add_input( - "hbar", units="unitless", desc="HBAR: Ratio of HGAP(?) to wing span") - self.add_input( - "bbar", units="unitless", desc="BBAR: Ratio of H tail area to wing area") + self.add_input('sbar', units='unitless', desc='SBAR: Ratio of H tail area to wing area') + self.add_input('cbar', units='unitless', desc='CBAR: Ratio of H tail chord to wing chord') + self.add_input('hbar', units='unitless', desc='HBAR: Ratio of HGAP(?) to wing span') + self.add_input('bbar', units='unitless', desc='BBAR: Ratio of H tail area to wing span') - self.add_output("lift_curve_slope", units="unitless", - shape=nn, desc="Lift-curve slope") - self.add_output("lift_ratio", units="unitless", shape=nn, desc="Lift ratio") + self.add_output( + 'lift_curve_slope', units='unitless', shape=nn, desc='CLAW: Lift-curve slope' + ) + self.add_output('lift_ratio', units='unitless', shape=nn, desc='BARL: Lift ratio') def setup_partials(self): - ar = np.arange(self.options["num_nodes"]) + ar = np.arange(self.options['num_nodes']) - self.declare_partials("lift_ratio", "*", method="cs") - self.declare_partials("lift_ratio", Dynamic.Mission.MACH, - rows=ar, cols=ar, method="cs") - self.declare_partials("lift_curve_slope", "*", method="cs") + self.declare_partials('lift_ratio', '*', method='cs') + self.declare_partials('lift_ratio', Dynamic.Atmosphere.MACH, rows=ar, cols=ar, method='cs') + self.declare_partials('lift_curve_slope', '*', method='cs') self.declare_partials( - "lift_curve_slope", + 'lift_curve_slope', [ Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.SWEEP, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, Aircraft.HorizontalTail.SWEEP, Aircraft.HorizontalTail.MOMENT_RATIO, - "sbar", - "cbar", - "hbar", - "bbar", + 'sbar', + 'cbar', + 'hbar', + 'bbar', ], - method="cs", + method='cs', + ) + self.declare_partials( + 'lift_curve_slope', Dynamic.Atmosphere.MACH, rows=ar, cols=ar, method='cs' ) - self.declare_partials("lift_curve_slope", Dynamic.Mission.MACH, - rows=ar, cols=ar, method="cs") def compute(self, inputs, outputs): ( @@ -328,6 +355,20 @@ def compute(self, inputs, outputs): hbar, bbar, ) = inputs.values() + verbosity = self.options[Settings.VERBOSITY] + + if h_tail_moment == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.HorizontalTail.MOMENT_RATIO should not be 0.0 in Xlifts.') + if sbar == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('sbar should not be 0.0 in Xlifts.') + if bbar == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('bbar should not be 0.0 in Xlifts.') + if AR == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.ASPECT_RATIO should not be 0.0 in Xlifts.') delta = (static_margin + delta_cg) * h_tail_moment @@ -346,24 +387,346 @@ def compute(self, inputs, outputs): eps2 = 1 / np.pi / AR eps3 = cs.abs(xt) / (np.pi * AR * np.sqrt(xt**2 + h**2 + AR**2 / 4)) eps4 = 1 / np.pi / art - eps5 = cs.abs(xt) / ( - np.pi * art * np.sqrt(xt**2 + h**2 + art**2 * cbar**2 / 4) - ) + eps5 = cs.abs(xt) / (np.pi * art * np.sqrt(xt**2 + h**2 + art**2 * cbar**2 / 4)) - claw = ( - claw0 - * (1 - clat0 * (eps4 - eps5 - cbar * eps1)) - / (1 - clat0 * claw0 * (eps1 + eps2 + eps3) * (eps4 - eps5 - cbar * eps1)) - ) + denom = 1 - clat0 * claw0 * (eps1 + eps2 + eps3) * (eps4 - eps5 - cbar * eps1) + if np.any(denom) == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn( + 'lift_curve_slope is undefined because the denominator is 0.0 in Xlift.' + ) + claw = claw0 * (1 - clat0 * (eps4 - eps5 - cbar * eps1)) / denom clat = clat0 * (1 - claw * (eps1 + eps2 + eps3)) + if np.any(claw) == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('lift_ratio is undefined because the denominator is 0.0 in Xlift.') abar = clat / claw c = 1 / (1 + 1 / abar / sbar) - lift_ratio = (c - delta) / (1 + delta - c) + lift_ratio = (c - delta) / (1 + delta - c) # for AFT Tails + + outputs['lift_curve_slope'] = claw + outputs['lift_ratio'] = lift_ratio + + +class FormFactorAndSIWB(om.ExplicitComponent): + """ + Compute body form factor and SIWB for tube+wing aircraft + Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. + """ + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft', desc='SWF') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') + + add_aviary_output( + self, + Aircraft.Fuselage.FORM_FACTOR, + units='unitless', + desc='FFFUS: fuselage form factor', + ) + self.add_output( + 'siwb', + units='unitless', + desc='SIWB: curve fitting correction factor for Oswald efficiency', + ) + + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.FORM_FACTOR, + [ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.LENGTH, + ], + ) + self.declare_partials( + 'siwb', + [ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.SPAN, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + + if fus_len == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in FormFactorAndSIWB.') + if wingspan == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.SPAN should not be 0.0 in FormFactorAndSIWB.') + + # fuselage form drag factor + fffus = 1 + 1.5 * (cabin_width / fus_len) ** 1.5 + 7 * (cabin_width / fus_len) ** 3 + outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus + + # fuselage width over wing span + wfob = cabin_width / wingspan + siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 + outputs['siwb'] = siwb + + def compute_partials(self, inputs, J): + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + + dfffus_dcabin_width = ( + 2.25 * (cabin_width / fus_len) ** 0.5 / fus_len + + 21 * (cabin_width / fus_len) ** 2.0 / fus_len + ) + dfffus_dfus_len = ( + -2.25 * (cabin_width / fus_len) ** 0.5 * cabin_width / fus_len**2.0 + - 21.0 * (cabin_width / fus_len) ** 2.0 * cabin_width / fus_len**2.0 + ) + + wfob = cabin_width / wingspan + # siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 + + dsiwb_dcabin_width = ( + -0.0088 / wingspan + - 2 * 1.7364 * wfob / wingspan + - 3 * 2.303 * wfob**2 / wingspan + + 4 * 6.0606 * wfob**3 / wingspan + ) + + dsiwb_dwingspan = ( + 0.0088 * cabin_width / wingspan**2 + + 2 * 1.7364 * wfob * cabin_width / wingspan**2 + + 3 * 2.303 * wfob**2 * cabin_width / wingspan**2 + - 4 * 6.0606 * wfob**3 * cabin_width / wingspan**2 + ) + + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.AVG_DIAMETER] = dfffus_dcabin_width + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len + J['siwb', Aircraft.Fuselage.AVG_DIAMETER] = dsiwb_dcabin_width + J['siwb', Aircraft.Wing.SPAN] = dsiwb_dwingspan + + +class BWBFormFactorAndSIWB(om.ExplicitComponent): + """ + Compute body form factor and SIWB for BWB aircraft + Incompressible form factor for streamlined bodies. From Hoerner's "Fluid Dynamic Drag", p. 6-17. + """ + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft', desc='DHYDRAL') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') + + self.add_output( + Aircraft.Fuselage.FORM_FACTOR, + units='unitless', + desc='FFFUS: fuselage form factor', + ) + self.add_output( + 'siwb', + units='unitless', + desc='SIWB: curve fitting correction factor for Oswald efficiency', + ) + + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.FORM_FACTOR, + [ + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + Aircraft.Fuselage.LENGTH, + ], + ) + self.declare_partials( + 'siwb', + [ + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + Aircraft.Wing.SPAN, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] - outputs["lift_curve_slope"] = claw - outputs["lift_ratio"] = lift_ratio + fus_len = inputs[Aircraft.Fuselage.LENGTH] + diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + + if fus_len == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Fuselage.LENGTH should not be 0.0 in FormFactorAndSIWB.') + if wingspan == 0.0: + if verbosity > Verbosity.BRIEF: + warnings.warn('Aircraft.Wing.SPAN should not be 0.0 in FormFactorAndSIWB.') + + # fuselage form drag factor + fffus = 1 + 1.5 * (diam / fus_len) ** 1.5 + 7 * (diam / fus_len) ** 3 + outputs[Aircraft.Fuselage.FORM_FACTOR] = fffus + + # hydraulic diameter over wing span + wfob = diam / wingspan + siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 + outputs['siwb'] = siwb + + def compute_partials(self, inputs, J): + fus_len = inputs[Aircraft.Fuselage.LENGTH] + diam = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + + dfffus_ddiam = ( + 2.25 * (diam / fus_len) ** 0.5 / fus_len + 21 * (diam / fus_len) ** 2.0 / fus_len + ) + dfffus_dfus_len = ( + -2.25 * (diam / fus_len) ** 0.5 * diam / fus_len**2.0 + - 21.0 * (diam / fus_len) ** 2.0 * diam / fus_len**2.0 + ) + + wfob = diam / wingspan + # siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 + + dsiwb_ddiam = ( + -0.0088 / wingspan + - 2 * 1.7364 * wfob / wingspan + - 3 * 2.303 * wfob**2 / wingspan + + 4 * 6.0606 * wfob**3 / wingspan + ) + + dsiwb_dwingspan = ( + 0.0088 * diam / wingspan**2 + + 2 * 1.7364 * wfob * diam / wingspan**2 + + 3 * 2.303 * wfob**2 * diam / wingspan**2 + - 4 * 6.0606 * wfob**3 * diam / wingspan**2 + ) + + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.HYDRAULIC_DIAMETER] = dfffus_ddiam + J[Aircraft.Fuselage.FORM_FACTOR, Aircraft.Fuselage.LENGTH] = dfffus_dfus_len + J['siwb', Aircraft.Fuselage.HYDRAULIC_DIAMETER] = dsiwb_ddiam + J['siwb', Aircraft.Wing.SPAN] = dsiwb_dwingspan + + +class UFac(om.ExplicitComponent): + """GASP EAERO subroutine""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Aircraft.Design.TYPE) + self.options.declare('smooth_ufac', default=False, types=bool) # only for BWB + self.options.declare('mu', default=100.0, types=float) # only for BWB + + def setup(self): + nn = self.options['num_nodes'] + self.add_input('lift_ratio', units='unitless', shape=nn, desc='BARL: Lift ratio') + # bbar is the ratio of horizontal tail span over wing span. + self.add_input('bbar_alt', units='unitless', desc='BBAR') + self.add_input('sigma', units='unitless', desc='interference factor') + self.add_input('sigstr', units='unitless', desc='nonelliptic interference factor') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') + self.add_output('ufac', shape=nn, units='unitless') + + def setup_partials(self): + ar = np.arange(self.options['num_nodes']) + self.declare_partials( + 'ufac', + [ + 'lift_ratio', + ], + rows=ar, + cols=ar, + ) + self.declare_partials( + 'ufac', + [ + 'bbar_alt', + 'sigma', + 'sigstr', + ], + ) + + def compute(self, inputs, outputs): + design_type = self.options[Aircraft.Design.TYPE] + lift_ratio = inputs['lift_ratio'] + bbar = inputs['bbar_alt'] + sigma = inputs['sigma'] + sigstr = inputs['sigstr'] + wingspan = inputs[Aircraft.Wing.SPAN] + + if design_type is AircraftTypes.TRANSPORT: + ufac = (1 + lift_ratio) ** 2 / ( + sigstr * (lift_ratio / bbar) ** 2 + 2 * sigma * lift_ratio / bbar + 1 + ) + else: + # Modify for tailless "BWB" + if bbar < 0.01 * wingspan: + bbar = 1.0 + ufac = (1 + lift_ratio) ** 2 / ( + sigstr * (lift_ratio / bbar) ** 2 + 2 * sigma * lift_ratio / bbar + 1 + ) + # For BWB, GASP has to limit UFAC under 0.975 for good result + smooth = self.options['smooth_ufac'] + if smooth: + mu = self.options['mu'] + ufac = smooth_min(ufac, 0.975, mu) + else: + ufac = np.minimum(ufac, 0.975) + + outputs['ufac'] = ufac + + def compute_partials(self, inputs, J): + design_type = self.options[Aircraft.Design.TYPE] + lift_ratio = inputs['lift_ratio'] + bbar = inputs['bbar_alt'] + sigma = inputs['sigma'] + sigstr = inputs['sigstr'] + + numer = (1 + lift_ratio) ** 2 + denom = sigstr * (lift_ratio / bbar) ** 2 + 2 * sigma * lift_ratio / bbar + 1 + ufac = numer / denom + + # w.r.t. lift_ratio + dnumer = 2 * (1 + lift_ratio) / bbar + ddenom = 2 * sigstr * (lift_ratio / bbar) / bbar + 2 * sigma / bbar + dufac_dlift_ratio = (dnumer * denom - numer * ddenom) / denom**2 + + dufac_dsigstr = -numer * (lift_ratio / bbar) ** 2 / denom**2 + dufac_dsigma = -numer * 2 * lift_ratio / bbar / denom**2 + + ddenom_dbbar = ( + -2 * sigstr * (lift_ratio / bbar) * lift_ratio / bbar**2 + - 2 * sigma * lift_ratio / bbar**2 + ) + dufac_dbbar = -numer * ddenom_dbbar / denom**2 + + if design_type is AircraftTypes.BLENDED_WING_BODY: + smooth = self.options['smooth_ufac'] + if smooth: + mu = self.options['mu'] + dufac_dsigstr = d_smooth_min(ufac, 0.975, mu) * dufac_dsigstr + dufac_dsigma = d_smooth_min(ufac, 0.975, mu) * dufac_dsigma + dufac_dbbar = d_smooth_min(ufac, 0.975, mu) * dufac_dbbar + else: + ufac = np.minimum(ufac, 0.975) + dufac_dsigstr = ( + np.piecewise(ufac, [ufac < 0.975, ufac >= 0.975], [1, 0]) * dufac_dsigstr + ) + dufac_dsigma = ( + np.piecewise(ufac, [ufac < 0.975, ufac >= 0.975], [1, 0]) * dufac_dsigma + ) + dufac_dbbar = ( + np.piecewise(ufac, [ufac < 0.975, ufac >= 0.975], [1, 0]) * dufac_dbbar + ) + + J['ufac', 'lift_ratio'] = dufac_dlift_ratio + J['ufac', 'bbar_alt'] = dufac_dbbar + J['ufac', 'sigma'] = dufac_dsigma + J['ufac', 'sigstr'] = dufac_dsigstr class AeroGeom(om.ExplicitComponent): @@ -374,126 +737,125 @@ class AeroGeom(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_nodes", default=1, types=int) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) def setup(self): - nn = self.options["num_nodes"] - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + nn = self.options['num_nodes'] + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - self.add_input( - Dynamic.Mission.MACH, val=0.0, units="unitless", shape=nn, desc="Current Mach number") - self.add_input( - Dynamic.Mission.SPEED_OF_SOUND, - val=1.0, - units="ft/s", - shape=nn, - desc="Speed of sound at current altitude", - ) - self.add_input( - Dynamic.Mission.KINEMATIC_VISCOSITY, - val=1.0, - units="ft**2/s", - shape=nn, - desc="Kinematic viscosity at current altitude", + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') + add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, shape=nn, units='ft/s') + add_aviary_input( + self, Dynamic.Atmosphere.KINEMATIC_VISCOSITY, val=1.0, shape=nn, units='ft**2/s' ) - self.add_input("ufac", units="unitless", shape=nn, desc="UFAC") + self.add_input('ufac', units='unitless', shape=nn, desc='UFAC') # form factors # user could input these directly or use functions to estimate from geometry - add_aviary_input(self, Aircraft.Wing.FORM_FACTOR, val=1.25) + add_aviary_input(self, Aircraft.Wing.FORM_FACTOR, units='unitless') - add_aviary_input(self, Aircraft.Fuselage.FORM_FACTOR, val=1.25) + add_aviary_input( + self, + Aircraft.Fuselage.FORM_FACTOR, + units='unitless', + desc='FFFUS: fuselage form drag factor', + ) - add_aviary_input(self, Aircraft.Nacelle.FORM_FACTOR, - val=np.full(num_engine_type, 1.5)) + add_aviary_input( + self, Aircraft.Nacelle.FORM_FACTOR, shape=num_engine_type, units='unitless' + ) - add_aviary_input(self, Aircraft.VerticalTail.FORM_FACTOR, val=1.25) + add_aviary_input(self, Aircraft.VerticalTail.FORM_FACTOR, units='unitless') - add_aviary_input(self, Aircraft.HorizontalTail.FORM_FACTOR, val=1.25) + add_aviary_input(self, Aircraft.HorizontalTail.FORM_FACTOR, units='unitless') - add_aviary_input(self, Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, val=1.1) + add_aviary_input(self, Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, units='unitless') - add_aviary_input(self, Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, val=0.0) + add_aviary_input(self, Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, units='unitless') # miscellaneous top-level inputs - add_aviary_input(self, Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, val=0.00175) + add_aviary_input(self, Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, units='unitless') - add_aviary_input(self, Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, val=0.25) + add_aviary_input(self, Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, units='ft**2') - add_aviary_input(self, Aircraft.Wing.MIN_PRESSURE_LOCATION, val=0.3) + add_aviary_input(self, Aircraft.Wing.MIN_PRESSURE_LOCATION, units='unitless') - add_aviary_input(self, Aircraft.Wing.MAX_THICKNESS_LOCATION, val=0.4) + add_aviary_input(self, Aircraft.Wing.MAX_THICKNESS_LOCATION, units='unitless') # geometric user inputs - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') - add_aviary_input(self, Aircraft.Wing.SWEEP, val=25.0) + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') - add_aviary_input(self, Aircraft.Strut.AREA_RATIO, val=0.0) + add_aviary_input(self, Aircraft.Strut.AREA_RATIO, units='unitless') # geometric data from sizing - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) - - add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, val=0.0) + add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.HorizontalTail.AVERAGE_CHORD, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.VerticalTail.AVERAGE_CHORD, val=0.0) + add_aviary_input(self, Aircraft.VerticalTail.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=0.0) + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') - add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, - val=np.zeros(num_engine_type)) + add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, shape=num_engine_type, units='ft') - add_aviary_input(self, Aircraft.HorizontalTail.AREA, val=0.0) + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, val=0.0) + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') - add_aviary_input(self, Aircraft.Nacelle.SURFACE_AREA, - val=np.zeros(num_engine_type)) + add_aviary_input(self, Aircraft.Nacelle.SURFACE_AREA, shape=num_engine_type, units='ft**2') - add_aviary_input(self, Aircraft.Wing.AREA, val=1370.3) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=0.0) + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') - add_aviary_input(self, Aircraft.VerticalTail.AREA, val=0.0) + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, units='unitless') - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, val=0.0) + add_aviary_input(self, Aircraft.Strut.CHORD, units='ft') - add_aviary_input(self, Aircraft.Strut.CHORD, val=0.0) - - self.add_input('interference_independent_of_shielded_area') - self.add_input('drag_loss_due_to_shielded_wing_area') + self.add_input( + 'interference_independent_of_shielded_area', units='unitless' + ) # Is this used? + (self.add_input('drag_loss_due_to_shielded_wing_area', units='unitless'),) # Is this used? + self.add_input( + 'siwb', + units='unitless', + desc='SIWB: curve fitting correction factor for Oswald efficiency', + ) # outputs - for i in range(7): - name = f"SA{i+1}" - self.add_output(name, units="unitless", shape=nn, desc=f"{name}: Drag param") + self.add_output('SA1', units='unitless', shape=nn, desc='SA1: drag param') + self.add_output('SA2', units='unitless', shape=nn, desc='SA2: drag param') + self.add_output('SA3', units='unitless', shape=nn, desc='SA3: drag param, not used') + self.add_output('SA4', units='unitless', shape=nn, desc='SA4: drag param, not used') + self.add_output('SA5', units='unitless', shape=nn, desc='SA5: drag param') + self.add_output('SA6', units='unitless', shape=nn, desc='SA6: drag param') + self.add_output('SA7', units='unitless', shape=nn, desc='SA7: induced drag param') self.add_output( - "cf", units="unitless", shape=nn, - desc="CFIN: Skin friction coefficient at Re=1e7" + 'cf', + units='unitless', + shape=nn, + desc='CFIN: Skin friction coefficient at Re=1e7', ) def setup_partials(self): # self.declare_coloring(method="cs", show_summary=False) - self.declare_partials("*", "*", dependent=False) - ar = np.arange(self.options["num_nodes"]) + self.declare_partials('*', '*', dependent=False) + ar = np.arange(self.options['num_nodes']) self.declare_partials( - "SA1", + 'SA1', [ Aircraft.Wing.MIN_PRESSURE_LOCATION, Aircraft.Wing.MAX_THICKNESS_LOCATION, @@ -502,10 +864,10 @@ def setup_partials(self): Aircraft.Wing.TAPER_RATIO, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, ], - method="cs", + method='cs', ) self.declare_partials( - "SA2", + 'SA2', [ Aircraft.Wing.MIN_PRESSURE_LOCATION, Aircraft.Wing.MAX_THICKNESS_LOCATION, @@ -513,36 +875,55 @@ def setup_partials(self): Aircraft.Wing.SWEEP, Aircraft.Wing.TAPER_RATIO, ], - method="cs", + method='cs', ) self.declare_partials( - "SA3", + 'SA3', [ Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.SWEEP, Aircraft.Wing.TAPER_RATIO, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, ], - method="cs", - ) - self.declare_partials( - "SA4", [Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], method="cs" + method='cs', ) - self.declare_partials("cf", [Dynamic.Mission.MACH], - rows=ar, cols=ar, method="cs") + self.declare_partials('SA4', [Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], method='cs') + self.declare_partials('cf', [Dynamic.Atmosphere.MACH], rows=ar, cols=ar, method='cs') # diag partials for SA5-SA7 self.declare_partials( - "SA5", [Dynamic.Mission.MACH, Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.KINEMATIC_VISCOSITY], rows=ar, cols=ar, method="cs" + 'SA5', + [ + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + ], + rows=ar, + cols=ar, + method='cs', ) self.declare_partials( - "SA6", [Dynamic.Mission.MACH, Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.KINEMATIC_VISCOSITY], rows=ar, cols=ar, method="cs" + 'SA6', + [ + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + ], + rows=ar, + cols=ar, + method='cs', ) self.declare_partials( - "SA7", [Dynamic.Mission.MACH, Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.KINEMATIC_VISCOSITY, "ufac"], rows=ar, cols=ar, method="cs" + 'SA7', + [ + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + 'ufac', + ], + rows=ar, + cols=ar, + method='cs', ) # dense partials for SA5-SA7 @@ -558,7 +939,6 @@ def setup_partials(self): Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, Aircraft.Wing.TAPER_RATIO, Aircraft.Strut.AREA_RATIO, - Aircraft.Wing.SPAN, Aircraft.Wing.AVERAGE_CHORD, Aircraft.HorizontalTail.AVERAGE_CHORD, Aircraft.VerticalTail.AVERAGE_CHORD, @@ -568,19 +948,18 @@ def setup_partials(self): Aircraft.Fuselage.WETTED_AREA, Aircraft.Nacelle.SURFACE_AREA, Aircraft.Wing.AREA, - Aircraft.Fuselage.AVG_DIAMETER, Aircraft.VerticalTail.AREA, 'interference_independent_of_shielded_area', 'drag_loss_due_to_shielded_wing_area', ] - self.declare_partials("SA5", most_params, method="cs") + self.declare_partials('SA5', most_params, method='cs') self.declare_partials( - "SA6", [Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.AVERAGE_CHORD], method="cs" + 'SA6', [Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.AVERAGE_CHORD], method='cs' ) self.declare_partials( - "SA7", - most_params + [Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.SWEEP], - method="cs", + 'SA7', + most_params + [Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.SWEEP] + ['siwb'], + method='cs', ) def compute(self, inputs, outputs): @@ -604,7 +983,6 @@ def compute(self, inputs, outputs): sweep_c4, taper_ratio, strut_wing_area_ratio, - wingspan, avg_chord, htail_chord, vtail_chord, @@ -614,12 +992,12 @@ def compute(self, inputs, outputs): fus_SA, nacelle_area, wing_area, - cabin_width, vtail_area, tc_ratio, strut_chord, feintwf, areashieldwf, + siwb, ) = inputs.values() # skin friction coeff at Re = 10**7 cf = 0.455 / 7**2.58 / (1 + 0.144 * mach**2) ** 0.65 @@ -627,13 +1005,9 @@ def compute(self, inputs, outputs): t = cs.abs(np.tan(deg2rad(sweep_c4))) yale05 = (1 - taper_ratio) / (1 + taper_ratio) # sweep angle to min pressure point - dlmps = rad2deg( - cs.arctan2(AR * t - 4 * (wing_min_pressure_loc - 0.25) * yale05, AR) - ) + dlmps = rad2deg(cs.arctan2(AR * t - 4 * (wing_min_pressure_loc - 0.25) * yale05, AR)) # sweep angle to max thickness point - dlmtcx = rad2deg( - cs.arctan2(AR * t - 4 * (wing_max_thickness_loc - 0.25) * yale05, AR) - ) + dlmtcx = rad2deg(cs.arctan2(AR * t - 4 * (wing_max_thickness_loc - 0.25) * yale05, AR)) # sweep angle of the leading edge rlmle = cs.arctan2(AR * t + yale05, AR) fk = 1 / (1 + yale05 / AR * 4 * taper_ratio**2) @@ -643,16 +1017,16 @@ def compute(self, inputs, outputs): # corresponding to Mach 0.1 at SLS) to help with takeoff. GASP doesn't call AERO # before takeoff, so the RELI used corresponds to the cruise point, and this # isn't a problem. - reli_y1 = 700000 * np.ones(self.options["num_nodes"]) + reli_y1 = 700000 * np.ones(self.options['num_nodes']) reli_y2 = sos * mach / nu - sig = sigmoid(mach, 0.1, alpha=0.005) + sig = sigmoidX(mach, 0.1, mu=0.005) reli = (1 - sig) * reli_y1 + sig * reli_y2 # Re correction factors: fuselage, wing, nacelle, vtail, htail, strut, tip tank # protect against Mach 0, any other small Mach should be ok dtype = complex if self.under_complex_step else float ffre, fwre, fnre, fvtre, fhtre, fstrtre = np.ones( - (6, self.options["num_nodes"]), dtype=dtype + (6, self.options['num_nodes']), dtype=dtype ) if self.under_complex_step: good_mask = reli.real > 1 @@ -663,18 +1037,16 @@ def compute(self, inputs, outputs): fnre[good_mask] = (np.log10(reli[good_mask] * nac_len) / 7) ** -2.6 fvtre[good_mask] = (np.log10(reli[good_mask] * vtail_chord) / 7) ** -2.6 fhtre[good_mask] = (np.log10(reli[good_mask] * htail_chord) / 7) ** -2.6 - include_strut = self.options["aviary_options"].get_val( - Aircraft.Wing.HAS_STRUT, units='unitless') + include_strut = self.options[Aircraft.Wing.HAS_STRUT] if include_strut: fstrtre = (np.log10(reli[good_mask] * strut_chord) / 7) ** -2.6 # fuselage form drag factor - fffus = ( - 1 + 1.5 * (cabin_width / fus_len) ** 1.5 + 7 * (cabin_width / fus_len) ** 3 - ) + # fffus = 1 + 1.5 * (cabin_width / fus_len) ** 1.5 + 7 * (cabin_width / fus_len) ** 3 # flat plate equivalent areas - fef = ff_fus * fus_SA * cf * ffre * fffus + fe_fus_inc + # GASP uses different values of cf for wing, nacelle, fuselage, etc. + fef = fus_SA * cf * ffre * ff_fus + fe_fus_inc few = ff_wing * wing_area * cf * fwre # TODO replace 2 with num_engines fen = 2 * ff_nac * nacelle_area * cf * fnre @@ -691,24 +1063,18 @@ def compute(self, inputs, outputs): # end INTERFERENCE # total flat plate equivalent area + # In GASP, nacelle is excluded. fe = few + fef + fevt + feht + fen + feiwf + festrt + cd0_inc * wing_area - wfob = cabin_width / wingspan - siwb = ( - 1 - - 0.0088 * wfob - - 1.7364 * wfob**2 - - 2.303 * wfob**3 - + 6.0606 * wfob**4 - ) + # wfob = cabin_width / wingspan + # siwb = 1 - 0.0088 * wfob - 1.7364 * wfob**2 - 2.303 * wfob**3 + 6.0606 * wfob**4 # wing-free profile drag coefficient cdpo = (fe - few) / wing_area # Oswald efficiency see = 1.0 / ( - (1 / ufac / siwb) - + 1.1938 * AR * (cdw0 / (np.cos(deg2rad(sweep_c4))) ** 2 + cdpo) + (1 / ufac / siwb) + 1.1938 * AR * (cdw0 / (np.cos(deg2rad(sweep_c4))) ** 2 + cdpo) ) # compressibility drag parameters @@ -716,11 +1082,7 @@ def compute(self, inputs, outputs): sa1 = (1 + 0.0033 * (4 * dlmps - 3 * dlmtcx)) * ( 1 - 1.4 * tc_ratio - 0.06 * (1 - wing_min_pressure_loc) ) - 0.0368 - sa2 = ( - -0.33 - * (0.65 - wing_min_pressure_loc) - * (1 + 0.0033 * (4 * dlmps - 3 * dlmtcx)) - ) + sa2 = -0.33 * (0.65 - wing_min_pressure_loc) * (1 + 0.0033 * (4 * dlmps - 3 * dlmtcx)) sa3 = (1.5 - 2 * fk**2 * np.sin(rlmle) ** 2) * tc_ratio ** (5 / 3.0) sa4 = 0.75 * tc_ratio @@ -731,87 +1093,142 @@ def compute(self, inputs, outputs): # induced drag sa7 = 1.0 / (np.pi * see * AR) - outputs["SA1"] = sa1 - outputs["SA2"] = sa2 - outputs["SA3"] = sa3 - outputs["SA4"] = sa4 - outputs["SA5"] = sa5 - outputs["SA6"] = sa6 - outputs["SA7"] = sa7 - outputs["cf"] = cf + outputs['SA1'] = sa1 + outputs['SA2'] = sa2 + outputs['SA3'] = sa3 + outputs['SA4'] = sa4 + outputs['SA5'] = sa5 + outputs['SA6'] = sa6 + outputs['SA7'] = sa7 + outputs['cf'] = cf class AeroSetup(om.Group): - """Calculations for setting up aero""" + """Calculations for setting up aero.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - self.options.declare( - "input_atmos", + 'input_atmos', default=False, types=bool, - desc="Directly input speed of sound and kinematic viscosity instead of " - "computing them with an atmospherics component. For testing.", - ) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + desc='Directly input speed of sound and kinematic viscosity instead of ' + 'computing them with an atmospherics component. For testing.', ) def setup(self): - nn = self.options["num_nodes"] - aviary_options = self.options['aviary_options'] + nn = self.options['num_nodes'] - self.add_subsystem("ratios", WingTailRatios(), promotes=["*"]) - self.add_subsystem("xlifts", Xlifts(num_nodes=nn), promotes=["*"]) + self.add_subsystem('ratios', WingTailRatios(), promotes=['*']) + self.add_subsystem('xlifts', Xlifts(num_nodes=nn), promotes=['*']) # implements EAERO - interp = om.MetaModelStructuredComp(method="2D-slinear") - interp.add_input("bbar", 0.0, units="unitless", training_data=xbbar) - interp.add_input("hbar", 0.0, units="unitless", training_data=xhbar) - interp.add_output("sigma", 0.0, units="unitless", training_data=sig1) - interp.add_output("sigstr", 0.0, units="unitless", training_data=sig2) - self.add_subsystem("interp", interp, promotes=["*"]) - + interp = om.MetaModelStructuredComp(method='2D-slinear') + interp.add_input('bbar', 0.0, units='unitless', training_data=xbbar) + interp.add_input('hbar', 0.0, units='unitless', training_data=xhbar) + interp.add_output('sigma', 0.0, units='unitless', training_data=sig1) + interp.add_output('sigstr', 0.0, units='unitless', training_data=sig2) + self.add_subsystem('interp', interp, promotes=['*']) + + # Note: It should hold ufac <= 0.975 for BWB self.add_subsystem( - "ufac_calc", + 'ufac_calc', om.ExecComp( - "ufac=(1 + lift_ratio)**2 / (sigstr*(lift_ratio/bbar)**2 + 2*sigma*lift_ratio/bbar + 1)", - lift_ratio={'units': "unitless", "shape": nn}, - bbar={'units': "unitless"}, - sigma={'units': "unitless"}, - sigstr={'units': "unitless"}, - ufac={'units': "unitless", "shape": nn}, - has_diag_partials=True + 'ufac=(1 + lift_ratio)**2 / (sigstr*(lift_ratio/bbar)**2 + 2*sigma*lift_ratio/bbar + 1)', + lift_ratio={'units': 'unitless', 'shape': nn}, + bbar={'units': 'unitless'}, + sigma={'units': 'unitless'}, + sigstr={'units': 'unitless'}, + ufac={'units': 'unitless', 'shape': nn}, + has_diag_partials=True, ), - promotes=["*"], + promotes=['*'], ) - if not self.options["input_atmos"]: + if not self.options['input_atmos']: # self.add_subsystem( # "atmos", # USatm1976Comp(num_nodes=nn), # promotes_inputs=[("h", Dynamic.Mission.ALTITUDE)], - # promotes_outputs=["rho", Dynamic.Mission.SPEED_OF_SOUND, "viscosity"], + # promotes_outputs=["rho", Dynamic.Atmosphere.SPEED_OF_SOUND, "viscosity"], # ) self.add_subsystem( - "kin_visc", + 'kin_visc', + om.ExecComp( + 'nu = viscosity / rho', + viscosity={'units': 'lbf*s/ft**2', 'shape': nn}, + rho={'units': 'slug/ft**3', 'shape': nn}, + nu={'units': 'ft**2/s', 'shape': nn}, + has_diag_partials=True, + ), + promotes=[ + '*', + ('rho', Dynamic.Atmosphere.DENSITY), + ('nu', Dynamic.Atmosphere.KINEMATIC_VISCOSITY), + ], + ) + + self.add_subsystem('form_factor', FormFactorAndSIWB(), promotes=['*']) + self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) + + +class BWBAeroSetup(om.Group): + """Calculations for setting up aero.""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + self.options.declare( + 'input_atmos', + default=False, + types=bool, + desc='Directly input speed of sound and kinematic viscosity instead of ' + 'computing them with an atmospherics component. For testing.', + ) + add_aviary_option(self, Aircraft.Design.TYPE) + + def setup(self): + nn = self.options['num_nodes'] + design_type = self.options[Aircraft.Design.TYPE] + + self.add_subsystem('ratios', WingTailRatios(), promotes=['*']) + self.add_subsystem('xlifts', Xlifts(num_nodes=nn), promotes=['*']) + + # implements EAERO + interp = om.MetaModelStructuredComp(method='2D-slinear') + interp.add_input('bbar_alt', 0.0, units='unitless', training_data=xbbar) + interp.add_input('hbar', 0.0, units='unitless', training_data=xhbar) + interp.add_output('sigma', 0.0, units='unitless', training_data=sig1) + interp.add_output('sigstr', 0.0, units='unitless', training_data=sig2) + self.add_subsystem('interp', interp, promotes=['*']) + + options = { + Aircraft.Design.TYPE: design_type, + } + self.add_subsystem( + 'ufac_calc', + UFac(num_nodes=nn, **options), + promotes=['*'], + ) + + if not self.options['input_atmos']: + self.add_subsystem( + 'kin_visc', om.ExecComp( - "nu = viscosity / rho", - viscosity={"units": "lbf*s/ft**2", "shape": nn}, - rho={"units": "slug/ft**3", "shape": nn}, - nu={"units": "ft**2/s", "shape": nn}, + 'nu = viscosity / rho', + viscosity={'units': 'lbf*s/ft**2', 'shape': nn}, + rho={'units': 'slug/ft**3', 'shape': nn}, + nu={'units': 'ft**2/s', 'shape': nn}, has_diag_partials=True, ), - promotes=["*", ('rho', Dynamic.Mission.DENSITY), - ('nu', Dynamic.Mission.KINEMATIC_VISCOSITY)], + promotes=[ + '*', + ('rho', Dynamic.Atmosphere.DENSITY), + ('nu', Dynamic.Atmosphere.KINEMATIC_VISCOSITY), + ], ) - self.add_subsystem("geom", AeroGeom( - num_nodes=nn, aviary_options=aviary_options), promotes=["*"]) + self.add_subsystem('form_factor', BWBFormFactorAndSIWB(), promotes=['*']) + self.add_subsystem('geom', AeroGeom(num_nodes=nn), promotes=['*']) class DragCoef(om.ExplicitComponent): @@ -823,96 +1240,109 @@ class DragCoef(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # mission inputs - self.add_input(Dynamic.Mission.ALTITUDE, val=0.0, - units="ft", shape=nn, desc="Altitude") - self.add_input( - "CL", val=1.0, units="unitless", shape=nn, desc="Lift coefficient") + add_aviary_input(self, Dynamic.Mission.ALTITUDE, shape=nn, units='ft') + self.add_input('CL', val=1.0, units='unitless', shape=nn, desc='Lift coefficient') # user inputs - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400.0) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') - self.add_input("flap_defl", val=10.0, units="deg", desc="Full flap deflection") + self.add_input('flap_defl', val=10.0, units='deg', desc='Full flap deflection') - add_aviary_input(self, Aircraft.Wing.HEIGHT, val=8.0) + add_aviary_input(self, Aircraft.Wing.HEIGHT, units='ft') - self.add_input( - "airport_alt", val=0.0, units="ft", desc="HPORT: Airport altitude" - ) + self.add_input('airport_alt', val=0.0, units='ft', desc='HPORT: Airport altitude') - add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, units='unitless') # from flaps self.add_input( - "dCL_flaps_model", val=0.0, units="unitless", - desc="Delta CL from flaps model") + 'dCL_flaps_model', + val=0.0, + units='unitless', + desc='DELCL: Delta CL from flaps model', + ) self.add_input( - "dCD_flaps_model", val=0.0, units="unitless", - desc="Delta CD from flaps model") + 'dCD_flaps_model', + val=0.0, + units='unitless', + desc='Delta CD from flaps model', + ) self.add_input( - "dCL_flaps_coef", - val=1.0, units="unitless", - desc="SIGMTO | SIGMLD: Coefficient applied to delta CL from flaps model", + 'dCL_flaps_coef', + val=1.0, + units='unitless', + desc='SIGMTO | SIGMLD: Coefficient applied to delta CL from flaps model', ) self.add_input( - "CDI_factor", - val=1.0, units="unitless", - desc="VDEL6T | VDEL6L: Factor applied to induced drag with flaps", + 'CDI_factor', + val=1.0, + units='unitless', + desc='VDEL6T | VDEL6L: Factor applied to induced drag with flaps', ) # from sizing - add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, val=0.0) + add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') - add_aviary_input(self, Aircraft.Wing.AREA, val=1370.3) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') # from aero setup self.add_input( - "cf", units="unitless", shape=nn, - desc="CFIN: Skin friction coefficient at Re=1e7") - self.add_input("SA5", units="unitless", shape=nn, desc="SA5: Drag param") - self.add_input("SA6", units="unitless", shape=nn, desc="SA6: Drag param") - self.add_input("SA7", units="unitless", shape=nn, desc="SA7: Drag param") + 'cf', + units='unitless', + shape=nn, + desc='CFIN: Skin friction coefficient at Re=1e7', + ) + self.add_input('SA5', units='unitless', shape=nn, desc='SA5: Drag param') + self.add_input('SA6', units='unitless', shape=nn, desc='SA6: Drag param') + self.add_input('SA7', units='unitless', shape=nn, desc='SA7: Drag param') - self.add_output("CD_base", units="unitless", shape=nn, desc="Drag coefficient") + self.add_output('CD_base', units='unitless', shape=nn, desc='Drag coefficient') self.add_output( - "dCD_flaps_full", units="unitless", shape=nn, - desc="CD increment with full flap deflection") + 'dCD_flaps_full', + units='unitless', + shape=nn, + desc='CD increment with full flap deflection', + ) self.add_output( - "dCD_gear_full", units="unitless", - shape=nn, desc="CD increment with landing gear down") + 'dCD_gear_full', + units='unitless', + shape=nn, + desc='CD increment with landing gear down', + ) def setup_partials(self): # self.declare_coloring(method="cs", show_summary=False) - self.declare_partials("*", "*", dependent=False) - ar = np.arange(self.options["num_nodes"]) + self.declare_partials('*', '*', dependent=False) + ar = np.arange(self.options['num_nodes']) - self.declare_partials("CD_base", ["*"], method="cs") + self.declare_partials('CD_base', ['*'], method='cs') self.declare_partials( - "CD_base", - [Dynamic.Mission.ALTITUDE, "CL", "cf", "SA5", "SA6", "SA7"], + 'CD_base', + [Dynamic.Mission.ALTITUDE, 'CL', 'cf', 'SA5', 'SA6', 'SA7'], rows=ar, cols=ar, - method="cs", + method='cs', ) # self.declare_partials( # "CD_base", [Mission.Design.GROSS_MASS, "dCD_flaps_model", "wing_area"], val=0 # ) - self.declare_partials("dCD_flaps_full", ["dCD_flaps_model"], val=1) + self.declare_partials('dCD_flaps_full', ['dCD_flaps_model'], val=1) self.declare_partials( - "dCD_gear_full", - [Mission.Design.GROSS_MASS, Aircraft.Wing.AREA, "flap_defl"], - method="cs", + 'dCD_gear_full', + [Mission.Design.GROSS_MASS, Aircraft.Wing.AREA, 'flap_defl'], + method='cs', ) def compute(self, inputs, outputs): @@ -956,62 +1386,78 @@ def compute(self, inputs, outputs): grfe = 0.0033 * gross_wt_initial**0.785 dcd_gear = (grfe / wing_area) * (1 - 0.454545 * flap_defl / 50) - outputs["CD_base"] = cd0 + cdi + dcd_ground - outputs["dCD_flaps_full"] = dCD_flaps_model - outputs["dCD_gear_full"] = dcd_gear + outputs['CD_base'] = cd0 + cdi + dcd_ground + outputs['dCD_flaps_full'] = dCD_flaps_model # same as inputs['dCD_flaps_model'] + outputs['dCD_gear_full'] = dcd_gear class DragCoefClean(om.ExplicitComponent): - """Clean drag coefficient for high-speed flight""" + """Clean drag coefficient for high-speed flight.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # mission inputs - self.add_input(Dynamic.Mission.MACH, val=0.0, units="unitless", - shape=nn, desc="Mach number") - self.add_input( - "CL", val=1.0, units="unitless", shape=nn, desc="Lift coefficient") + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn, units='unitless') + self.add_input('CL', val=1.0, units='unitless', shape=nn, desc='Lift coefficient') # user inputs - - add_aviary_input(self, Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT, val=0.033) + add_aviary_input(self, Aircraft.Design.DRAG_DIVERGENCE_SHIFT, units='unitless') + add_aviary_input(self, Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, units='unitless') # from aero setup self.add_input( - "cf", units="unitless", shape=nn, - desc="CFIN: Skin friction coefficient at Re=1e7") - self.add_input("SA1", units="unitless", shape=nn, desc="SA1: Drag param") - self.add_input("SA2", units="unitless", shape=nn, desc="SA2: Drag param") - self.add_input("SA5", units="unitless", shape=nn, desc="SA5: Drag param") - self.add_input("SA6", units="unitless", shape=nn, desc="SA6: Drag param") - self.add_input("SA7", units="unitless", shape=nn, desc="SA7: Drag param") + 'cf', + units='unitless', + shape=nn, + desc='CFIN: Skin friction coefficient at Re=1e7', + ) + self.add_input('SA1', units='unitless', shape=nn, desc='SA1: Drag param') + self.add_input('SA2', units='unitless', shape=nn, desc='SA2: Drag param') + self.add_input('SA5', units='unitless', shape=nn, desc='SA5: Drag param') + self.add_input('SA6', units='unitless', shape=nn, desc='SA6: Drag param') + self.add_input('SA7', units='unitless', shape=nn, desc='SA7: Drag param') - self.add_output("CD", units="unitless", shape=nn, desc="Drag coefficient") + self.add_output('CD', units='unitless', shape=nn, desc='Drag coefficient') def setup_partials(self): - ar = np.arange(self.options["num_nodes"]) + ar = np.arange(self.options['num_nodes']) self.declare_partials( - "CD", - [Dynamic.Mission.MACH, "CL", "cf", "SA1", "SA2", "SA5", "SA6", "SA7"], + 'CD', + [Dynamic.Atmosphere.MACH, 'CL', 'cf', 'SA1', 'SA2', 'SA5', 'SA6', 'SA7'], rows=ar, cols=ar, - method="cs", - ) - self.declare_partials( - "CD", [Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT], method="cs" + method='cs', ) + self.declare_partials('CD', [Aircraft.Design.DRAG_DIVERGENCE_SHIFT], method='cs') def compute(self, inputs, outputs): - mach, CL, div_drag_supercrit, cf, SA1, SA2, SA5, SA6, SA7 = inputs.values() + ( + mach, + CL, + div_drag_supercrit, + subsonic_factor, + supersonic_factor, + lift_factor, + zero_lift_factor, + cf, + SA1, + SA2, + SA5, + SA6, + SA7, + ) = inputs.values() mach_div = SA1 + SA2 * CL + div_drag_supercrit - sig = sigmoid(mach, mach_div, alpha=0.005) + sig = sigmoidX(mach, mach_div, mu=0.005) delcdm = sig * (10 * (mach - mach_div) ** 3) # delcdm = np.zeros_like(mach) @@ -1023,99 +1469,77 @@ def compute(self, inputs, outputs): # induced drag cdi = SA7 * CL**2 - outputs["CD"] = cd0 + cdi + delcdm + CD = cd0 * zero_lift_factor + cdi * lift_factor + delcdm + # scale drag + idx_sup = np.where(mach >= 1.0) + CD_scaled = CD * subsonic_factor + CD_scaled[idx_sup] = CD[idx_sup] * supersonic_factor -class LiftCoeff(om.ExplicitComponent): - """GASP lift coefficient calculation for low-speed near-ground flight""" + outputs['CD'] = CD_scaled + + +class GroundEffect(om.ExplicitComponent): + """Factor of CL due to ground effect.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] # mission inputs - self.add_input("alpha", val=0.0, units="deg", shape=nn, desc="Angle of attack") - self.add_input(Dynamic.Mission.ALTITUDE, val=0.0, - units="ft", shape=nn, desc="Altitude") - self.add_input("lift_curve_slope", units="unitless", - shape=nn, desc="Lift-curve slope") - self.add_input("lift_ratio", units="unitless", shape=nn, desc="Lift ratio") - - # user inputs - - add_aviary_input(self, Aircraft.Wing.ZERO_LIFT_ANGLE, val=-1.2) - - add_aviary_input(self, Aircraft.Wing.SWEEP, val=25.0) - - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) - - add_aviary_input(self, Aircraft.Wing.HEIGHT, val=8.0) - + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') + add_aviary_input(self, Dynamic.Mission.ALTITUDE, shape=nn, units='ft') self.add_input( - "airport_alt", val=0.0, units="ft", desc="HPORT: Airport altitude" + 'lift_curve_slope', units='unitless', shape=nn, desc='CLAW: Lift-curve slope' ) - self.add_input("flap_defl", val=10.0, units="deg", desc="Full flap deflection") - - add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) - - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) + # user inputs + add_aviary_input(self, Aircraft.Wing.ZERO_LIFT_ANGLE, units='deg') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.HEIGHT, units='ft') + self.add_input('airport_alt', val=0.0, units='ft', desc='HPORT: Airport altitude') + self.add_input('flap_defl', val=10.0, units='deg', desc='Full flap deflection') + add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') # from flaps self.add_input( - "CL_max_flaps", units="unitless", - desc="CLMWTO | CLMWLD: Max lift coefficient from flaps model", + 'dCL_flaps_model', + val=0.0, + units='unitless', + desc='Delta CL from flaps model', ) - self.add_input( - "dCL_flaps_model", val=0.0, units="unitless", - desc="Delta CL from flaps model") # from sizing + add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') - add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, val=0.0) - - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) - - self.add_output( - "CL_base", units="unitless", shape=nn, desc="Base lift coefficient") self.add_output( - "dCL_flaps_full", units="unitless", shape=nn, - desc="CL increment with full flap deflection" + 'kclge', units='unitless', shape=nn, desc='KCLGE: factor of CL due to ground effect' ) - self.add_output( - "alpha_stall", units="deg", shape=nn, desc="Stall angle of attack" - ) - self.add_output( - "CL_max", units="unitless", shape=nn, desc="Max lift coefficient") def setup_partials(self): # self.declare_coloring(method="cs", show_summary=False) - self.declare_partials("*", "*", dependent=False) - ar = np.arange(self.options["num_nodes"]) + self.declare_partials('*', '*', dependent=False) + ar = np.arange(self.options['num_nodes']) - dynvars = ["alpha", Dynamic.Mission.ALTITUDE, "lift_curve_slope", "lift_ratio"] - - self.declare_partials("CL_base", ["*"], method="cs") - self.declare_partials("CL_base", dynvars, rows=ar, cols=ar, method="cs") - - self.declare_partials("dCL_flaps_full", ["dCL_flaps_model"], method="cs") - self.declare_partials( - "dCL_flaps_full", ["lift_ratio"], rows=ar, cols=ar, method="cs") - - self.declare_partials("alpha_stall", ["*"], method="cs") - self.declare_partials("alpha_stall", dynvars, rows=ar, cols=ar, method="cs") + dynvars = [ + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Dynamic.Mission.ALTITUDE, + 'lift_curve_slope', + ] - self.declare_partials("CL_max", ["CL_max_flaps"], method="cs") - self.declare_partials("CL_max", ["lift_ratio"], rows=ar, cols=ar, method="cs") + self.declare_partials('kclge', ['*'], method='cs') + self.declare_partials('kclge', dynvars, rows=ar, cols=ar, method='cs') def compute(self, inputs, outputs): ( alpha, alt, lift_curve_slope, - lift_ratio, alpha0, sweep_c4, AR, @@ -1124,7 +1548,6 @@ def compute(self, inputs, outputs): flap_defl, flap_chord_ratio, taper_ratio, - CL_max_flaps, dCL_flaps_model, avg_chord, wingspan, @@ -1147,276 +1570,1084 @@ def compute(self, inputs, outputs): - sig * AR * np.cos(rlmc2) / c3 - c4 * (cloge - lift_curve_slope / (16 * hac / avg_chord)) ) + # make sure kclge >= 1.0 kclge = np.clip(kclge, 1.0, None) - outputs["CL_base"] = kclge * lift_curve_slope * \ - deg2rad(alpha - alpha0) * (1 + lift_ratio) - outputs["dCL_flaps_full"] = dCL_flaps_model * (1 + lift_ratio) + hob = hac / wingspan + for i_node in range(self.options['num_nodes']): + if hob[i_node] >= 10.0: + kclge[i_node] = 1.0 + + outputs['kclge'] = kclge + + +class LiftCoeff(om.ExplicitComponent): + """GASP lift coefficient calculation for low-speed near-ground flight.""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + + def setup(self): + nn = self.options['num_nodes'] + + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') + self.add_input( + 'lift_curve_slope', units='unitless', shape=nn, desc='CLAW: Lift-curve slope' + ) + self.add_input('lift_ratio', units='unitless', shape=nn, desc='BARL: Lift ratio') + + add_aviary_input(self, Aircraft.Wing.ZERO_LIFT_ANGLE, units='deg') + + # from flaps + self.add_input( + 'CL_max_flaps', + units='unitless', + desc='CLMWTO | CLMWLD: Max lift coefficient from flaps model (takeoff | landing)', + ) + self.add_input( + 'dCL_flaps_model', + val=0.0, + units='unitless', + desc='Delta CL from flaps model', + ) + + self.add_input( + 'kclge', units='unitless', shape=nn, desc='factor of CL due to ground effect' + ) + self.add_input( + 'flap_factor', shape=nn, units='unitless', desc='factor of CL due to flap deployment' + ) + + self.add_output('CL_base', units='unitless', shape=nn, desc='Base lift coefficient') + self.add_output( + 'dCL_flaps_full', + units='unitless', + shape=nn, + desc='CL increment with full flap deflection', + ) + self.add_output('alpha_stall', units='deg', shape=nn, desc='Stall angle of attack') + self.add_output('CL_max', units='unitless', shape=nn, desc='Max lift coefficient') + + self.add_output( + 'CL_full_flaps', + units='unitless', + shape=nn, + desc='lift coefficient with full flaps deployed', + ) + self.add_output('CL', units='unitless', shape=nn, desc='lift coefficient') + + def setup_partials(self): + # self.declare_coloring(method="cs", show_summary=False) + self.declare_partials('*', '*', dependent=False) + ar = np.arange(self.options['num_nodes']) + + dynvars = [ + Dynamic.Vehicle.ANGLE_OF_ATTACK, + 'lift_curve_slope', + 'lift_ratio', + 'kclge', + ] + + self.declare_partials('CL_base', ['*']) + self.declare_partials('CL_base', dynvars, rows=ar, cols=ar) + + self.declare_partials('dCL_flaps_full', ['dCL_flaps_model']) + self.declare_partials('dCL_flaps_full', ['lift_ratio'], rows=ar, cols=ar) + + self.declare_partials('alpha_stall', ['*']) + self.declare_partials('alpha_stall', dynvars, rows=ar, cols=ar) + + self.declare_partials('CL_max', ['CL_max_flaps']) + self.declare_partials('CL_max', ['lift_ratio'], rows=ar, cols=ar) + + self.declare_partials('CL_full_flaps', ['*']) + self.declare_partials('CL_full_flaps', dynvars, rows=ar, cols=ar) + self.declare_partials('CL_full_flaps', ['dCL_flaps_model']) + self.declare_partials('CL_full_flaps', ['lift_ratio'], rows=ar, cols=ar) + + self.declare_partials('CL', ['*']) + self.declare_partials('CL', dynvars, rows=ar, cols=ar) + self.declare_partials('CL', ['dCL_flaps_model']) + self.declare_partials('CL', ['lift_ratio', 'flap_factor'], rows=ar, cols=ar) + + def compute(self, inputs, outputs): + ( + alpha, + lift_curve_slope, + lift_ratio, + alpha0, + CL_max_flaps, + dCL_flaps_model, + kclge, + flap_factor, + ) = inputs.values() + + # clw_base = kclge * lift_curve_slope * deg2rad(alpha - alpha0) + # clw = clw_base + dCL_flaps_model + + outputs['CL_base'] = kclge * lift_curve_slope * deg2rad(alpha - alpha0) * (1 + lift_ratio) + outputs['dCL_flaps_full'] = dCL_flaps_model * (1 + lift_ratio) + outputs['alpha_stall'] = ( + rad2deg((CL_max_flaps - dCL_flaps_model) / (kclge * lift_curve_slope)) + alpha0 + ) + outputs['CL_max'] = CL_max_flaps * (1 + lift_ratio) + + outputs['CL_full_flaps'] = outputs['CL_base'] + outputs['dCL_flaps_full'] + outputs['CL'] = outputs['CL_base'] + flap_factor * outputs['dCL_flaps_full'] + + def compute_partials(self, inputs, J): + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + lift_curve_slope = inputs['lift_curve_slope'] + lift_ratio = inputs['lift_ratio'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs['CL_max_flaps'] + + dCL_flaps_model = inputs['dCL_flaps_model'] + kclge = inputs['kclge'] + flap_factor = inputs['flap_factor'] + + J['CL_base', 'kclge'] = lift_curve_slope * deg2rad(alpha - alpha0) * (1 + lift_ratio) + J['CL_base', 'lift_curve_slope'] = kclge * deg2rad(alpha - alpha0) * (1 + lift_ratio) + J['CL_base', Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( + kclge * lift_curve_slope * np.pi / 180.0 * (1 + lift_ratio) + ) + J['CL_base', Aircraft.Wing.ZERO_LIFT_ANGLE] = ( + -kclge * lift_curve_slope * np.pi / 180.0 * (1 + lift_ratio) + ) + J['CL_base', 'lift_ratio'] = kclge * lift_curve_slope * deg2rad(alpha - alpha0) + + J['dCL_flaps_full', 'dCL_flaps_model'] = 1 + lift_ratio + J['dCL_flaps_full', 'lift_ratio'] = dCL_flaps_model + + J['alpha_stall', 'CL_max_flaps'] = 180.0 / np.pi / (kclge * lift_curve_slope) + J['alpha_stall', 'dCL_flaps_model'] = -180.0 / np.pi / (kclge * lift_curve_slope) + J['alpha_stall', 'kclge'] = -rad2deg( + (CL_max_flaps - dCL_flaps_model) / (kclge**2 * lift_curve_slope) + ) + J['alpha_stall', 'lift_curve_slope'] = -rad2deg( + (CL_max_flaps - dCL_flaps_model) / (kclge * lift_curve_slope**2) + ) + J['alpha_stall', Aircraft.Wing.ZERO_LIFT_ANGLE] = 1 + + J['CL_max', 'CL_max_flaps'] = 1 + lift_ratio + J['CL_max', 'lift_ratio'] = CL_max_flaps + + J['CL_full_flaps', 'kclge'] = J['CL_base', 'kclge'] + J['CL_full_flaps', 'lift_curve_slope'] = J['CL_base', 'lift_curve_slope'] + J['CL_full_flaps', Dynamic.Vehicle.ANGLE_OF_ATTACK] = J[ + 'CL_base', Dynamic.Vehicle.ANGLE_OF_ATTACK + ] + J['CL_full_flaps', Aircraft.Wing.ZERO_LIFT_ANGLE] = J[ + 'CL_base', Aircraft.Wing.ZERO_LIFT_ANGLE + ] + J['CL_full_flaps', 'lift_ratio'] = ( + J['CL_base', 'lift_ratio'] + J['dCL_flaps_full', 'lift_ratio'] + ) + J['CL_full_flaps', 'dCL_flaps_model'] = J['dCL_flaps_full', 'dCL_flaps_model'] + + J['CL', 'kclge'] = J['CL_base', 'kclge'] + J['CL', 'lift_curve_slope'] = J['CL_base', 'lift_curve_slope'] + J['CL', Dynamic.Vehicle.ANGLE_OF_ATTACK] = J['CL_base', Dynamic.Vehicle.ANGLE_OF_ATTACK] + J['CL', Aircraft.Wing.ZERO_LIFT_ANGLE] = J['CL_base', Aircraft.Wing.ZERO_LIFT_ANGLE] + + J['CL', 'flap_factor'] = dCL_flaps_model * (1 + lift_ratio) + J['CL', 'lift_ratio'] = ( + J['CL_base', 'lift_ratio'] + flap_factor * J['dCL_flaps_full', 'lift_ratio'] + ) + J['CL', 'dCL_flaps_model'] = flap_factor * (1 + lift_ratio) + + +class BWBLiftCoeff(om.ExplicitComponent): + """GASP lift coefficient calculation for low-speed near-ground flight for BWB.""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + nn = self.options['num_nodes'] + + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') + self.add_input( + 'lift_curve_slope', units='unitless', shape=nn, desc='CLAW: Lift-curve slope' + ) + + add_aviary_input(self, Aircraft.Wing.ZERO_LIFT_ANGLE, units='deg') + + # from flaps + self.add_input( + 'CL_max_flaps', + units='unitless', + desc='CLMWTO | CLMWLD: Max lift coefficient from flaps model (takeoff | landing)', + ) + self.add_input( + 'dCL_flaps_model', + val=0.0, + units='unitless', + desc='Delta CL from flaps model', + ) + + self.add_input( + 'kclge', units='unitless', shape=nn, desc='factor of CL due to ground effect' + ) + self.add_input( + 'flap_factor', shape=nn, units='unitless', desc='factor of CL due to flap deployment' + ) + + self.add_input( + 'body_lift_curve_slope', + units='unitless', + shape=nn, + desc='CLALPH_B: Lift-curve slope of fuselage for the given Mach', + ) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2', desc='SREF') + add_aviary_input(self, Aircraft.Wing.EXPOSED_AREA, units='ft**2', desc='SW_EXP') + add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2', desc='SPF_BODY') + + self.add_output('CL_base', units='unitless', shape=nn, desc='Base lift coefficient') + self.add_output( + 'dCL_flaps_full', + units='unitless', + shape=nn, + desc='CL increment with full flap deflection', + ) + self.add_output('alpha_stall', units='deg', shape=nn, desc='Stall angle of attack') + self.add_output('CL_max', units='unitless', shape=nn, desc='Max lift coefficient') + + self.add_output( + 'CL_full_flaps', + units='unitless', + shape=nn, + desc='lift coefficient with full flaps deployed', + ) + self.add_output('CL', units='unitless', shape=nn, desc='lift coefficient') + + def setup_partials(self): + # self.declare_coloring(method="cs", show_summary=False) + ar = np.arange(self.options['num_nodes']) + + self.declare_partials( + 'CL_base', + [ + 'kclge', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + Aircraft.Wing.ZERO_LIFT_ANGLE, + ], + ) + self.declare_partials( + 'CL_base', + [ + Dynamic.Vehicle.ANGLE_OF_ATTACK, + 'lift_curve_slope', + 'kclge', + ], + rows=ar, + cols=ar, + ) + + self.declare_partials('dCL_flaps_full', ['dCL_flaps_model']) + + self.declare_partials('alpha_stall', ['lift_curve_slope', 'kclge'], rows=ar, cols=ar) + self.declare_partials( + 'alpha_stall', + [ + 'CL_max_flaps', + 'dCL_flaps_model', + Aircraft.Wing.ZERO_LIFT_ANGLE, + ], + ) + + self.declare_partials('CL_max', ['CL_max_flaps']) + + self.declare_partials( + 'CL_full_flaps', + [ + Dynamic.Vehicle.ANGLE_OF_ATTACK, + 'lift_curve_slope', + 'kclge', + 'body_lift_curve_slope', + ], + rows=ar, + cols=ar, + ) + self.declare_partials( + 'CL_full_flaps', + [ + 'dCL_flaps_model', + Aircraft.Wing.ZERO_LIFT_ANGLE, + Aircraft.Wing.AREA, + Aircraft.Wing.EXPOSED_AREA, + Aircraft.Fuselage.PLANFORM_AREA, + ], + ) + + # self.declare_partials('CL', ['*']) + self.declare_partials( + 'CL', + [ + Dynamic.Vehicle.ANGLE_OF_ATTACK, + 'lift_curve_slope', + 'kclge', + 'flap_factor', + 'body_lift_curve_slope', + ], + rows=ar, + cols=ar, + ) + self.declare_partials( + 'CL', + [ + 'dCL_flaps_model', + Aircraft.Wing.ZERO_LIFT_ANGLE, + Aircraft.Wing.AREA, + Aircraft.Wing.EXPOSED_AREA, + Aircraft.Fuselage.PLANFORM_AREA, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + lift_curve_slope = inputs['lift_curve_slope'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs['CL_max_flaps'] + dCL_flaps_model = inputs['dCL_flaps_model'] + kclge = inputs['kclge'] + flap_factor = inputs['flap_factor'] + body_lift_curve_slope = inputs['body_lift_curve_slope'] + wing_area = inputs[Aircraft.Wing.AREA] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] + + # clw_base = kclge * lift_curve_slope * deg2rad(alpha - alpha0) + # clw = clw_base + dCL_flaps_model + + # This is actually CLw_base + outputs['CL_base'] = kclge * lift_curve_slope * deg2rad(alpha - alpha0) + outputs['dCL_flaps_full'] = dCL_flaps_model + alpha_stall = ( + rad2deg((CL_max_flaps - dCL_flaps_model) / (kclge * lift_curve_slope)) + alpha0 + ) + outputs['alpha_stall'] = alpha_stall + if any(x > 0.0 for x in alpha.real - alpha_stall.real): + if verbosity > Verbosity.BRIEF: + warnings.warn( + f'Some angle of attack {alpha} might be greater than alpha stall {alpha_stall}.' + ) + outputs['CL_max'] = CL_max_flaps + + CLw_full_flaps = outputs['CL_base'] + outputs['dCL_flaps_full'] + # CL when flaps is partially deployed + CLw_partial_flaps = outputs['CL_base'] + flap_factor * outputs['dCL_flaps_full'] + + CL_body = planform / wing_area * kclge * body_lift_curve_slope * deg2rad(alpha - alpha0) + + outputs['CL_full_flaps'] = exp_wing_area / wing_area * CLw_full_flaps + CL_body + # CL when flaps is partially deployed + outputs['CL'] = exp_wing_area / wing_area * CLw_partial_flaps + CL_body + + def compute_partials(self, inputs, J): + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + lift_curve_slope = inputs['lift_curve_slope'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs['CL_max_flaps'] + dCL_flaps_model = inputs['dCL_flaps_model'] + kclge = inputs['kclge'] + flap_factor = inputs['flap_factor'] + + body_lift_curve_slope = inputs['body_lift_curve_slope'] + wing_area = inputs[Aircraft.Wing.AREA] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] + + J['CL_base', 'kclge'] = lift_curve_slope * deg2rad(alpha - alpha0) + J['CL_base', 'lift_curve_slope'] = kclge * deg2rad(alpha - alpha0) + J['CL_base', Dynamic.Vehicle.ANGLE_OF_ATTACK] = kclge * lift_curve_slope * np.pi / 180.0 + J['CL_base', Aircraft.Wing.ZERO_LIFT_ANGLE] = -kclge * lift_curve_slope * np.pi / 180.0 + + J['dCL_flaps_full', 'dCL_flaps_model'] = 1 + + J['alpha_stall', 'CL_max_flaps'] = 180.0 / np.pi / (kclge * lift_curve_slope) + J['alpha_stall', 'dCL_flaps_model'] = -180.0 / np.pi / (kclge * lift_curve_slope) + J['alpha_stall', 'kclge'] = -rad2deg( + (CL_max_flaps - dCL_flaps_model) / (kclge**2 * lift_curve_slope) + ) + J['alpha_stall', 'lift_curve_slope'] = -rad2deg( + (CL_max_flaps - dCL_flaps_model) / (kclge * lift_curve_slope**2) + ) + J['alpha_stall', Aircraft.Wing.ZERO_LIFT_ANGLE] = 1 + + J['CL_max', 'CL_max_flaps'] = 1 + + # with planform/wing_area factor + # CL_body = planform / wing_area * kclge * body_lift_curve_slope * deg2rad(alpha - alpha0) + + dCL_body_dplanform = 1 / wing_area * kclge * body_lift_curve_slope * deg2rad(alpha - alpha0) + dCL_body_dwing_area = ( + -planform / wing_area**2 * kclge * body_lift_curve_slope * deg2rad(alpha - alpha0) + ) + dCL_body_dkclge = planform / wing_area * body_lift_curve_slope * deg2rad(alpha - alpha0) + dCL_body_dbody_lift_curve_slope = planform / wing_area * kclge * deg2rad(alpha - alpha0) + dCL_body_dalpha = planform / wing_area * kclge * body_lift_curve_slope * np.pi / 180.0 + dCL_body_dalpha0 = -planform / wing_area * kclge * body_lift_curve_slope * np.pi / 180.0 + + # with exp_wing_area/wing_area factor + # CLw_full_flaps = exp_wing_area / wing_area * (kclge * lift_curve_slope * deg2rad(alpha - alpha0) + # + dCL_flaps_model) + + dCLw_full_flaps_dkclge = ( + exp_wing_area / wing_area * lift_curve_slope * deg2rad(alpha - alpha0) + ) + dCLw_full_flaps_dlift_curve_slope = ( + exp_wing_area / wing_area * kclge * deg2rad(alpha - alpha0) + ) + dCLw_full_flaps_dalpha = ( + exp_wing_area / wing_area * kclge * lift_curve_slope * np.pi / 180.0 + ) + dCLw_full_flaps_dalpha0 = ( + -exp_wing_area / wing_area * kclge * lift_curve_slope * np.pi / 180.0 + ) + dCLw_full_flaps_ddCL_flaps_model = exp_wing_area / wing_area + + CL_base = kclge * lift_curve_slope * deg2rad(alpha - alpha0) + dCLw_full_flaps = dCL_flaps_model + CLw_full_flaps = CL_base + dCLw_full_flaps + + J['CL_full_flaps', 'kclge'] = dCLw_full_flaps_dkclge + dCL_body_dkclge + J['CL_full_flaps', 'lift_curve_slope'] = dCLw_full_flaps_dlift_curve_slope + J['CL_full_flaps', Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( + dCLw_full_flaps_dalpha + dCL_body_dalpha + ) + J['CL_full_flaps', Aircraft.Wing.ZERO_LIFT_ANGLE] = ( + dCLw_full_flaps_dalpha0 + dCL_body_dalpha0 + ) + J['CL_full_flaps', 'dCL_flaps_model'] = dCLw_full_flaps_ddCL_flaps_model + + J['CL_full_flaps', Aircraft.Fuselage.PLANFORM_AREA] = dCL_body_dplanform + J['CL_full_flaps', Aircraft.Wing.AREA] = ( + -exp_wing_area / wing_area**2 * CLw_full_flaps + dCL_body_dwing_area + ) + J['CL_full_flaps', Aircraft.Wing.EXPOSED_AREA] = 1 / wing_area * CLw_full_flaps + J['CL_full_flaps', Aircraft.Fuselage.PLANFORM_AREA] = dCL_body_dplanform + J['CL_full_flaps', 'body_lift_curve_slope'] = dCL_body_dbody_lift_curve_slope + + # CL when flaps is partially deployed + # with exp_wing_area/wing_area factor + # CLw_partial_flaps = exp_wing_area / wing_area * (kclge * lift_curve_slope * deg2rad(alpha - alpha0) + # + flap_factor * dCL_flaps_model) + + dCLw_partial_flaps_dkclge = ( + exp_wing_area / wing_area * lift_curve_slope * deg2rad(alpha - alpha0) + ) + dCLw_partial_flaps_dlift_curve_slope = ( + exp_wing_area / wing_area * kclge * deg2rad(alpha - alpha0) + ) + dCLw_partial_flaps_dalpha = ( + exp_wing_area / wing_area * kclge * lift_curve_slope * np.pi / 180.0 + ) + dCLw_partial_flaps_dalpha0 = ( + -exp_wing_area / wing_area * kclge * lift_curve_slope * np.pi / 180.0 + ) + dCLw_partial_flaps_ddCL_flaps_model = exp_wing_area / wing_area * flap_factor + dCLw_partial_flaps_dflap_factor = exp_wing_area / wing_area * dCL_flaps_model + + dCLw_partial_flaps = flap_factor * dCL_flaps_model + CLw_partial_flaps = CL_base + dCLw_partial_flaps + + J['CL', 'kclge'] = dCLw_partial_flaps_dkclge + dCL_body_dkclge + J['CL', 'lift_curve_slope'] = dCLw_partial_flaps_dlift_curve_slope + J['CL', Dynamic.Vehicle.ANGLE_OF_ATTACK] = dCLw_partial_flaps_dalpha + dCL_body_dalpha + J['CL', Aircraft.Wing.ZERO_LIFT_ANGLE] = dCLw_partial_flaps_dalpha0 + dCL_body_dalpha0 + J['CL', 'dCL_flaps_model'] = dCLw_partial_flaps_ddCL_flaps_model - outputs["alpha_stall"] = ( - rad2deg((CL_max_flaps - dCL_flaps_model) / - (kclge * lift_curve_slope)) + alpha0 + J['CL', Aircraft.Fuselage.PLANFORM_AREA] = dCL_body_dplanform + J['CL', Aircraft.Wing.AREA] = ( + -exp_wing_area / wing_area**2 * CLw_partial_flaps + dCL_body_dwing_area ) - outputs["CL_max"] = CL_max_flaps * (1 + lift_ratio) + J['CL', Aircraft.Wing.EXPOSED_AREA] = 1 / wing_area * CLw_partial_flaps + J['CL', Aircraft.Fuselage.PLANFORM_AREA] = dCL_body_dplanform + J['CL', 'body_lift_curve_slope'] = dCL_body_dbody_lift_curve_slope + + J['CL', 'flap_factor'] = dCLw_partial_flaps_dflap_factor class LiftCoeffClean(om.ExplicitComponent): - """Clean wing lift coefficient for high-speed flight""" + """Clean wing lift coefficient for high-speed flight.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) self.options.declare( - "output_alpha", + 'output_alpha', default=False, types=bool, - desc="If True, output alpha for a given input CL", + desc='If True, output alpha for a given input CL', ) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] - if self.options["output_alpha"]: - self.add_output( - "alpha", val=0.0, units="deg", shape=nn, desc="Angle of attack" - ) - self.add_input( - "CL", val=1.0, units="unitless", shape=nn, desc="Lift coefficient") + if self.options['output_alpha']: + add_aviary_output(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') + self.add_input('CL', val=1.0, units='unitless', shape=nn, desc='Lift coefficient') else: - self.add_input( - "alpha", val=0.0, units="deg", shape=nn, desc="Angle of attack" - ) - self.add_output( - "CL", val=1.0, units="unitless", shape=nn, desc="Lift coefficient") + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') + self.add_output('CL', val=1.0, units='unitless', shape=nn, desc='Lift coefficient') - self.add_input("lift_curve_slope", units="unitless", - shape=nn, desc="Lift-curve slope") - self.add_input("lift_ratio", units="unitless", shape=nn, desc="Lift ratio") + self.add_input( + 'lift_curve_slope', units='unitless', shape=nn, desc='CLAW: Lift-curve slope' + ) + self.add_input('lift_ratio', units='unitless', shape=nn, desc='BARL: Lift ratio') - add_aviary_input(self, Aircraft.Wing.ZERO_LIFT_ANGLE, val=-1.2) + add_aviary_input(self, Aircraft.Wing.ZERO_LIFT_ANGLE, units='deg', desc='ALPHL0') - add_aviary_input(self, Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, val=0.0) + add_aviary_input(self, Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, units='unitless') - self.add_output("alpha_stall", shape=nn, desc="Stall angle of attack") - self.add_output( - "CL_max", units="unitless", shape=nn, desc="Max lift coefficient") + self.add_output('alpha_stall', shape=nn, units='deg', desc='Stall angle of attack') + self.add_output('CL_max', units='unitless', shape=nn, desc='Max lift coefficient') def setup_partials(self): # self.declare_coloring(method="cs", show_summary=False) - self.declare_partials("*", "*", dependent=False) - ar = np.arange(self.options["num_nodes"]) + self.declare_partials('*', '*', dependent=False) + ar = np.arange(self.options['num_nodes']) - if self.options["output_alpha"]: + if self.options['output_alpha']: self.declare_partials( - "alpha", ["CL", "lift_ratio", "lift_curve_slope"], rows=ar, cols=ar, method="cs" + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ['CL', 'lift_ratio', 'lift_curve_slope'], + rows=ar, + cols=ar, + ) + self.declare_partials( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + [Aircraft.Wing.ZERO_LIFT_ANGLE], ) - self.declare_partials("alpha", [Aircraft.Wing.ZERO_LIFT_ANGLE], method="cs") else: self.declare_partials( - "CL", ["lift_curve_slope", "alpha", "lift_ratio"], rows=ar, cols=ar, method="cs" + 'CL', + ['lift_curve_slope', Dynamic.Vehicle.ANGLE_OF_ATTACK, 'lift_ratio'], + rows=ar, + cols=ar, ) - self.declare_partials("CL", [Aircraft.Wing.ZERO_LIFT_ANGLE], method="cs") + self.declare_partials('CL', [Aircraft.Wing.ZERO_LIFT_ANGLE]) + self.declare_partials('alpha_stall', ['lift_curve_slope'], rows=ar, cols=ar) self.declare_partials( - "alpha_stall", ["lift_curve_slope"], rows=ar, cols=ar, method="cs") - self.declare_partials( - "alpha_stall", + 'alpha_stall', [ Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, Aircraft.Wing.ZERO_LIFT_ANGLE, ], - method="cs", ) - self.declare_partials("CL_max", ["lift_ratio"], rows=ar, cols=ar, method="cs") - self.declare_partials( - "CL_max", [Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP], method="cs" - ) + self.declare_partials('CL_max', ['lift_ratio'], rows=ar, cols=ar) + self.declare_partials('CL_max', [Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP]) def compute(self, inputs, outputs): _, lift_curve_slope, lift_ratio, alpha0, CL_max_flaps = inputs.values() - if self.options["output_alpha"]: - CL = inputs["CL"] + if self.options['output_alpha']: + CL = inputs['CL'] clw = CL / (1 + lift_ratio) - outputs["alpha"] = rad2deg(clw / lift_curve_slope) + alpha0 + outputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] = rad2deg(clw / lift_curve_slope) + alpha0 else: - alpha = inputs["alpha"] - outputs["CL"] = lift_curve_slope * deg2rad(alpha - alpha0) * (1 + lift_ratio) + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + outputs['CL'] = lift_curve_slope * deg2rad(alpha - alpha0) * (1 + lift_ratio) - outputs["alpha_stall"] = rad2deg(CL_max_flaps / lift_curve_slope) + alpha0 - outputs["CL_max"] = CL_max_flaps * (1 + lift_ratio) + outputs['alpha_stall'] = rad2deg(CL_max_flaps / lift_curve_slope) + alpha0 + outputs['CL_max'] = CL_max_flaps * (1 + lift_ratio) + def compute_partials(self, inputs, J): + lift_curve_slope = inputs['lift_curve_slope'] + lift_ratio = inputs['lift_ratio'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs[Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] -class CruiseAero(om.Group): - """Top-level aerodynamics group for cruise (no flaps, no landing gear)""" + J['alpha_stall', Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] = ( + 180.0 / np.pi / lift_curve_slope + ) + J['alpha_stall', 'lift_curve_slope'] = -180.0 / np.pi * CL_max_flaps / lift_curve_slope**2 + J['alpha_stall', Aircraft.Wing.ZERO_LIFT_ANGLE] = 1 + J['CL_max', Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] = 1 + lift_ratio + J['CL_max', 'lift_ratio'] = CL_max_flaps + + if self.options['output_alpha']: + CL = inputs['CL'] + clw = CL / (1 + lift_ratio) + # outputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] = rad2deg(clw / lift_curve_slope) + alpha0 + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, Aircraft.Wing.ZERO_LIFT_ANGLE] = 1 + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, 'lift_curve_slope'] = ( + -180.0 / np.pi * clw / lift_curve_slope**2 + ) + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, 'CL'] = ( + 180.0 / np.pi / (1 + lift_ratio) / lift_curve_slope + ) + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, 'lift_ratio'] = ( + -180.0 / np.pi * CL / (1 + lift_ratio) ** 2 / lift_curve_slope + ) + else: + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + J['CL', Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( + lift_curve_slope * np.pi / 180.0 * (1 + lift_ratio) + ) + J['CL', 'lift_curve_slope'] = deg2rad(alpha - alpha0) * (1 + lift_ratio) + J['CL', 'lift_ratio'] = lift_curve_slope * deg2rad(alpha - alpha0) + J['CL', Aircraft.Wing.ZERO_LIFT_ANGLE] = ( + -lift_curve_slope * np.pi / 180.0 * (1 + lift_ratio) + ) - def initialize(self): - self.options.declare("num_nodes", default=1, types=int) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') +class BWBLiftCoeffClean(om.ExplicitComponent): + """Clean wing lift coefficient for high-speed flight of BWB.""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) self.options.declare( - "output_alpha", + 'output_alpha', default=False, types=bool, - desc="If True, output alpha for a given input CL", + desc='If True, output alpha for a given input CL', ) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + nn = self.options['num_nodes'] + + if self.options['output_alpha']: + self.add_input('CL', val=1.0, units='unitless', shape=nn, desc='Lift coefficient') + else: + add_aviary_input(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') + + self.add_input( + 'lift_curve_slope', units='unitless', shape=nn, desc='CLAW: Lift-curve slope' + ) + self.add_input( + 'body_lift_curve_slope', + units='unitless', + shape=nn, + desc='CLALPH_B: Lift-curve slope of fuselage for the given Mach', + ) + add_aviary_input(self, Aircraft.Wing.ZERO_LIFT_ANGLE, units='deg', desc='ALPHL0') + add_aviary_input(self, Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, units='unitless') + + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2', desc='SREF') + add_aviary_input(self, Aircraft.Wing.EXPOSED_AREA, units='ft**2', desc='SW_EXP') + add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2', desc='SPF_BODY') + + if self.options['output_alpha']: + self.add_output('mod_lift_curve_slope', units='unitless', shape=nn) + add_aviary_output(self, Dynamic.Vehicle.ANGLE_OF_ATTACK, shape=nn, units='deg') + else: + self.add_output('CL', val=1.0, units='unitless', shape=nn, desc='Lift coefficient') + self.add_output('alpha_stall', shape=nn, desc='Stall angle of attack') + self.add_output('CL_max', units='unitless', shape=nn, desc='Max lift coefficient') + + def setup_partials(self): + # self.declare_coloring(method="cs", show_summary=False) + self.declare_partials('*', '*', dependent=False) + ar = np.arange(self.options['num_nodes']) + + if self.options['output_alpha']: + self.declare_partials( + 'mod_lift_curve_slope', + [ + Aircraft.Wing.AREA, + Aircraft.Wing.EXPOSED_AREA, + Aircraft.Fuselage.PLANFORM_AREA, + ], + ) + self.declare_partials( + 'mod_lift_curve_slope', + [ + 'lift_curve_slope', + 'body_lift_curve_slope', + ], + rows=ar, + cols=ar, + ) + self.declare_partials( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + [ + 'CL', + 'lift_curve_slope', + 'body_lift_curve_slope', + ], + rows=ar, + cols=ar, + ) + self.declare_partials( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + [ + Aircraft.Wing.AREA, + Aircraft.Wing.EXPOSED_AREA, + Aircraft.Fuselage.PLANFORM_AREA, + Aircraft.Wing.ZERO_LIFT_ANGLE, + ], + ) + else: + self.declare_partials( + 'CL', + [ + 'lift_curve_slope', + 'body_lift_curve_slope', + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], + rows=ar, + cols=ar, + ) + self.declare_partials( + 'CL', + [ + Aircraft.Wing.AREA, + Aircraft.Wing.EXPOSED_AREA, + Aircraft.Fuselage.PLANFORM_AREA, + Aircraft.Wing.ZERO_LIFT_ANGLE, + ], + ) + + self.declare_partials('alpha_stall', ['lift_curve_slope'], rows=ar, cols=ar) + self.declare_partials( + 'alpha_stall', + [ + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, + Aircraft.Wing.ZERO_LIFT_ANGLE, + Aircraft.Wing.AREA, + Aircraft.Wing.EXPOSED_AREA, + ], + ) + + self.declare_partials('CL_max', [Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP]) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + lift_curve_slope = inputs['lift_curve_slope'] + body_lift_curve_slope = inputs['body_lift_curve_slope'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs[Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] + wing_area = inputs[Aircraft.Wing.AREA] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] + + if self.options['output_alpha']: + CL = inputs['CL'] + # clw = wing_area / exp_wing_area * CL + mod_lift_curve_slope = ( + exp_wing_area / wing_area * lift_curve_slope + + planform / wing_area * body_lift_curve_slope + ) + outputs['mod_lift_curve_slope'] = mod_lift_curve_slope + alpha = rad2deg(CL / mod_lift_curve_slope) + alpha0 + outputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] = alpha + else: + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + clw = lift_curve_slope * np.pi / 180.0 * (alpha - alpha0) + outputs['CL'] = ( + exp_wing_area / wing_area * clw + + planform / wing_area * deg2rad(alpha - alpha0) * body_lift_curve_slope + ) + + alpha_stall = rad2deg(CL_max_flaps / lift_curve_slope) + alpha0 + outputs['alpha_stall'] = alpha_stall + if any(x > 0.0 for x in alpha.real - alpha_stall.real): + if verbosity >= Verbosity.BRIEF: + warnings.warn( + f'Some angle of attack {alpha} might be greater than alpha stall {alpha_stall}.' + ) + + outputs['CL_max'] = CL_max_flaps + + def compute_partials(self, inputs, J): + lift_curve_slope = inputs['lift_curve_slope'] + body_lift_curve_slope = inputs['body_lift_curve_slope'] + alpha0 = inputs[Aircraft.Wing.ZERO_LIFT_ANGLE] + CL_max_flaps = inputs[Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] + wing_area = inputs[Aircraft.Wing.AREA] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] + + if self.options['output_alpha']: + CL = inputs['CL'] + mod_lift_curve_slope = ( + exp_wing_area / wing_area * lift_curve_slope + + planform / wing_area * body_lift_curve_slope + ) + + # partials of mod_lift_curve_slope + dmod_dexp_wing_area = 1.0 / wing_area * lift_curve_slope + dmod_dwing_area = ( + -exp_wing_area / wing_area**2 * lift_curve_slope + - planform / wing_area**2 * body_lift_curve_slope + ) + dmod_dplanform = 1.0 / wing_area * body_lift_curve_slope + dmod_dlift_curve_slope = exp_wing_area / wing_area + dmod_dbody_lift_curve_slope = planform / wing_area + + J['mod_lift_curve_slope', Aircraft.Wing.EXPOSED_AREA] = dmod_dexp_wing_area + J['mod_lift_curve_slope', Aircraft.Wing.AREA] = dmod_dwing_area + J['mod_lift_curve_slope', Aircraft.Fuselage.PLANFORM_AREA] = dmod_dplanform + J['mod_lift_curve_slope', 'lift_curve_slope'] = dmod_dlift_curve_slope + J['mod_lift_curve_slope', 'body_lift_curve_slope'] = dmod_dbody_lift_curve_slope + + # alpha = rad2deg(CL / mod_lift_curve_slope) + alpha0 + + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, Aircraft.Wing.AREA] = ( + -180.0 / np.pi * CL / mod_lift_curve_slope**2 * dmod_dwing_area + ) + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, Aircraft.Wing.EXPOSED_AREA] = ( + -180.0 / np.pi * CL / mod_lift_curve_slope**2 * dmod_dexp_wing_area + ) + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, Aircraft.Fuselage.PLANFORM_AREA] = ( + -180.0 / np.pi * CL / mod_lift_curve_slope**2 * dmod_dplanform + ) + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, 'lift_curve_slope'] = ( + -180.0 / np.pi * CL / mod_lift_curve_slope**2 * dmod_dlift_curve_slope + ) + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, 'body_lift_curve_slope'] = ( + -180.0 / np.pi * CL / mod_lift_curve_slope**2 * dmod_dbody_lift_curve_slope + ) + + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, 'CL'] = 180.0 / np.pi / mod_lift_curve_slope + J[Dynamic.Vehicle.ANGLE_OF_ATTACK, Aircraft.Wing.ZERO_LIFT_ANGLE] = 1 + else: + alpha = inputs[Dynamic.Vehicle.ANGLE_OF_ATTACK] + # CL_1 = exp_wing_area / wing_area * lift_curve_slope * np.pi / 180.0 * (alpha - alpha0) + # CL_2 = planform / wing_area * np.pi / 180.0 * (alpha - alpha0) * body_lift_curve_slope + # CL = CL_1 + CL_2 + + J['CL', Aircraft.Wing.EXPOSED_AREA] = ( + 1.0 / wing_area * lift_curve_slope * np.pi / 180.0 * (alpha - alpha0) + ) + J['CL', Aircraft.Fuselage.PLANFORM_AREA] = ( + 1.0 / wing_area * deg2rad(alpha - alpha0) * body_lift_curve_slope + ) + J['CL', Aircraft.Wing.AREA] = ( + -exp_wing_area / wing_area**2 * lift_curve_slope * np.pi / 180.0 * (alpha - alpha0) + - planform / wing_area**2 * deg2rad(alpha - alpha0) * body_lift_curve_slope + ) + J['CL', Aircraft.Wing.ZERO_LIFT_ANGLE] = ( + -exp_wing_area / wing_area * lift_curve_slope * np.pi / 180.0 + - planform / wing_area * body_lift_curve_slope * np.pi / 180.0 + ) + J['CL', Dynamic.Vehicle.ANGLE_OF_ATTACK] = ( + exp_wing_area / wing_area * lift_curve_slope * np.pi / 180.0 + + planform / wing_area * body_lift_curve_slope * np.pi / 180.0 + ) + J['CL', 'lift_curve_slope'] = ( + exp_wing_area / wing_area * np.pi / 180.0 * (alpha - alpha0) + ) + J['CL', 'body_lift_curve_slope'] = ( + planform / wing_area * np.pi / 180.0 * (alpha - alpha0) + ) + + J['alpha_stall', Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] = ( + 180.0 / np.pi / lift_curve_slope + ) + J['alpha_stall', 'lift_curve_slope'] = -180.0 / np.pi * CL_max_flaps / lift_curve_slope**2 + J['alpha_stall', Aircraft.Wing.ZERO_LIFT_ANGLE] = 1 + J['CL_max', Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP] = 1 + + +class CruiseAero(om.Group): + """Top-level aerodynamics group for cruise (no flaps, no landing gear).""" + + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Aircraft.Design.TYPE) + self.options.declare( - "input_atmos", + 'output_alpha', default=False, types=bool, - desc="Directly input speed of sound and kinematic viscosity instead of " - "computing them with an atmospherics component. For testing.", + desc='If True, output alpha for a given input CL', ) self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + 'input_atmos', + default=False, + types=bool, + desc='Directly input speed of sound and kinematic viscosity instead of ' + 'computing them with an atmospherics component. For testing.', ) def setup(self): - nn = self.options["num_nodes"] - aviary_options = self.options["aviary_options"] - self.add_subsystem( - "aero_setup", - AeroSetup(num_nodes=nn, aviary_options=aviary_options, - input_atmos=self.options["input_atmos"]), - promotes=["*"], - ) - if self.options["output_alpha"]: + design_type = self.options[Aircraft.Design.TYPE] + nn = self.options['num_nodes'] + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'aero_setup', + BWBAeroSetup( + num_nodes=nn, + input_atmos=self.options['input_atmos'], + ), + promotes=['*'], + ) + else: + self.add_subsystem( + 'aero_setup', + AeroSetup( + num_nodes=nn, + input_atmos=self.options['input_atmos'], + ), + promotes=['*'], + ) + if self.options['output_alpha']: # lift_req -> CL - self.add_subsystem("lift2cl", CLFromLift(num_nodes=nn), promotes=["*"]) - self.add_subsystem( - "lift_coef", - LiftCoeffClean(output_alpha=self.options["output_alpha"], num_nodes=nn), - promotes=["*"], - ) - self.add_subsystem("drag_coef", DragCoefClean(num_nodes=nn), promotes=["*"]) - self.add_subsystem("forces", AeroForces(num_nodes=nn), promotes=["*"]) + self.add_subsystem('lift2cl', CLFromLift(num_nodes=nn), promotes=['*']) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'body_lift_curve', + BWBBodyLiftCurveSlope(num_nodes=nn), + promotes=['*'], + ) + self.add_subsystem( + 'lift_coef', + BWBLiftCoeffClean(output_alpha=self.options['output_alpha'], num_nodes=nn), + promotes=['*'], + ) + else: + self.add_subsystem( + 'lift_coef', + LiftCoeffClean(output_alpha=self.options['output_alpha'], num_nodes=nn), + promotes=['*'], + ) + self.add_subsystem('drag_coef', DragCoefClean(num_nodes=nn), promotes=['*']) + self.add_subsystem('forces', AeroForces(num_nodes=nn), promotes=['*']) class LowSpeedAero(om.Group): - """Top-level aerodynamics group for near-ground flight""" + """Top-level aerodynamics group for near-ground flight.""" def initialize(self): - self.options.declare("num_nodes", default=1, types=int) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Aircraft.Design.TYPE) self.options.declare( - "retract_gear", + 'retract_gear', default=True, types=bool, - desc="True to start with gear landing gear down, False for reverse", + desc='True to start with gear landing gear down, False for reverse', ) self.options.declare( - "retract_flaps", + 'retract_flaps', default=True, types=bool, - desc="True to start with flaps applied, False for reverse", + desc='True to start with flaps applied, False for reverse', ) - # TODO this option does not really exist for LowSpeed and should be renamed - # (the value of having identical option set to cruise aero not worth the added - # confusion of having a mislabeled option here) self.options.declare( - "output_alpha", + 'lift_required', default=False, types=bool, - desc="If True, output alpha for a given input CL", + desc='If True, compute CL from lift required (mass). If False, compute lift ' + 'from current flight conditions including angle of attack.', ) self.options.declare( - "input_atmos", + 'input_atmos', default=False, types=bool, - desc="Directly input speed of sound and kinematic viscosity instead of " - "computing them with an atmospherics component. For testing.", - ) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + desc='Directly input speed of sound and kinematic viscosity instead of ' + 'computing them with an atmospherics component. For testing.', ) def setup(self): - nn = self.options["num_nodes"] - output_alpha = self.options["output_alpha"] - aviary_options = self.options["aviary_options"] + nn = self.options['num_nodes'] + design_type = self.options[Aircraft.Design.TYPE] + lift_required = self.options['lift_required'] + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'aero_setup', + BWBAeroSetup( + num_nodes=nn, + input_atmos=self.options['input_atmos'], + ), + promotes=['*'], + ) + else: + self.add_subsystem( + 'aero_setup', + AeroSetup( + num_nodes=nn, + input_atmos=self.options['input_atmos'], + ), + promotes=['*'], + ) + + aero_ramps = TanhRampComp(time_units='s', num_nodes=nn) + aero_ramps.add_ramp( + 'flap_factor', + output_units='unitless', + initial_val=1.0 if self.options['retract_flaps'] else 0.0, + final_val=0.0 if self.options['retract_flaps'] else 1.0, + ) + aero_ramps.add_ramp( + 'gear_factor', + output_units='unitless', + initial_val=1.0 if self.options['retract_gear'] else 0.0, + final_val=0.0 if self.options['retract_gear'] else 1.0, + ) + self.add_subsystem( - "aero_setup", - AeroSetup(num_nodes=nn, aviary_options=aviary_options, - input_atmos=self.options["input_atmos"]), - promotes=["*"], + 'aero_ramps', + aero_ramps, + promotes_inputs=[ + ('time', 't_curr'), + ('flap_factor:t_init', 't_init_flaps'), + ('flap_factor:t_duration', 'dt_flaps'), + ('gear_factor:t_init', 't_init_gear'), + ('gear_factor:t_duration', 'dt_gear'), + ], + promotes_outputs=['flap_factor', 'gear_factor'], ) - aero_ramps = TanhRampComp(time_units='s', num_nodes=nn) - aero_ramps.add_ramp('flap_factor', output_units='unitless', - initial_val=1.0 if self.options['retract_flaps'] else 0.0, - final_val=0.0 if self.options['retract_flaps'] else 1.0) - aero_ramps.add_ramp('gear_factor', output_units='unitless', - initial_val=1.0 if self.options['retract_gear'] else 0.0, - final_val=0.0 if self.options['retract_gear'] else 1.0) - - self.add_subsystem("aero_ramps", - aero_ramps, - promotes_inputs=[("time", "t_curr"), - ("flap_factor:t_init", "t_init_flaps"), - ("flap_factor:t_duration", "dt_flaps"), - ("gear_factor:t_init", "t_init_gear"), - ("gear_factor:t_duration", "dt_gear")], - promotes_outputs=['flap_factor', - 'gear_factor']) - - if output_alpha: + if lift_required: # lift_req -> CL self.add_subsystem( - "lift2cl", + 'lift2cl', CLFromLift(num_nodes=nn), - promotes_inputs=["*"], + promotes_inputs=['*'], # little bit of a hack here - input CL bypasses CL increment ramp # so ensure this is what's passed to DragCoef - promotes_outputs=[("CL", "CL_full_flaps")], + promotes_outputs=[('CL', 'CL_full_flaps')], ) - warnings.warn("Alpha is NOT an output from LowSpeedAero.") + # NOTE Alpha is NOT an output from LowSpeedAero. else: self.add_subsystem( - "lift_coef", - LiftCoeff(num_nodes=nn), - promotes_inputs=["*"], - promotes_outputs=["*"] - ) - - self.add_subsystem( - "total_cl", - om.ExecComp( - [ - # "CL = CL_base + dCL_flaps", - "CL_full_flaps = CL_base + dCL_flaps_full", - "CL = CL_base + flap_factor * dCL_flaps_full", - ], - CL=dict(shape=nn, units='unitless'), - CL_full_flaps=dict(shape=nn, units='unitless'), - CL_base=dict(shape=nn, units='unitless'), - # dCL_flaps=dict(shape=nn, units='unitless'), - flap_factor=dict(shape=nn, units='unitless'), - dCL_flaps_full=dict(shape=nn, units='unitless'), - has_diag_partials=True - ), - promotes=["*"], + 'kclge', + GroundEffect(num_nodes=nn), + promotes_inputs=['*'], + promotes_outputs=['*'], ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'body_lift_curve', + BWBBodyLiftCurveSlope(num_nodes=nn), + promotes=['*'], + ) + self.add_subsystem( + 'lift_coef', + BWBLiftCoeff(num_nodes=nn), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'lift_coef', + LiftCoeff(num_nodes=nn), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - interp = om.MetaModelStructuredComp(method="slinear") - interp.add_input("flap_defl", 10.0, units="deg", training_data=adelfd) - interp.add_output("dCL_flaps_coef", 0.0, units="unitless", training_data=asigma) - interp.add_output("CDI_factor", 1.0, units="unitless", training_data=adel6) - self.add_subsystem("cdi_flap_interp", interp, promotes=["*"]) + interp = om.MetaModelStructuredComp(method='slinear') + interp.add_input('flap_defl', 10.0, units='deg', training_data=adelfd) + interp.add_output('dCL_flaps_coef', 0.0, units='unitless', training_data=asigma) + interp.add_output('CDI_factor', 1.0, units='unitless', training_data=adel6) + self.add_subsystem('cdi_flap_interp', interp, promotes=['*']) self.add_subsystem( - "drag_coef", DragCoef(num_nodes=nn), promotes=["*", ("CL", "CL_full_flaps")] + 'drag_coef', DragCoef(num_nodes=nn), promotes=['*', ('CL', 'CL_full_flaps')] ) self.add_subsystem( - "total_cd", + 'total_cd', om.ExecComp( - "CD = CD_base + flap_factor * dCD_flaps_full + gear_factor" - " * dCD_gear_full", + 'CD = CD_base + flap_factor * dCD_flaps_full + gear_factor * dCD_gear_full', # "CD = CD_base + dCD_flaps + dCD_gear", CD=dict(shape=nn, units='unitless'), CD_base=dict(shape=nn, units='unitless'), @@ -1426,25 +2657,25 @@ def setup(self): gear_factor=dict(shape=nn, units='unitless'), dCD_gear_full=dict(shape=nn, units='unitless'), dCD_flaps_full=dict(shape=nn, units='unitless'), - has_diag_partials=True + has_diag_partials=True, ), - promotes=["*"], + promotes=['*'], ) - self.add_subsystem("forces", AeroForces(num_nodes=nn), promotes=["*"]) + self.add_subsystem('forces', AeroForces(num_nodes=nn), promotes=['*']) self.set_input_defaults(Dynamic.Mission.ALTITUDE, np.zeros(nn)) - if self.options["retract_gear"]: + if self.options['retract_gear']: # takeoff defaults - self.set_input_defaults("dt_gear", 7) + self.set_input_defaults('dt_gear', 7) # gear not dynamically extended during landing - if self.options["retract_flaps"]: + if self.options['retract_flaps']: # takeoff defaults - self.set_input_defaults("flap_defl", 10) - self.set_input_defaults("dt_flaps", 3) + self.set_input_defaults('flap_defl', 10) + self.set_input_defaults('dt_flaps', 3) else: # landing defaults - self.set_input_defaults("flap_defl", 40) + self.set_input_defaults('flap_defl', 40) # flaps not dynamically extended during landing diff --git a/aviary/subsystems/aerodynamics/gasp_based/interference.py b/aviary/subsystems/aerodynamics/gasp_based/interference.py index 2a1fb74adb..e40998f845 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/interference.py +++ b/aviary/subsystems/aerodynamics/gasp_based/interference.py @@ -1,145 +1,150 @@ import numpy as np import openmdao.api as om from openmdao.utils import cs_safe as cs -import os -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Dynamic, Mission from aviary.constants import GRAV_ENGLISH_GASP +from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.variables import Aircraft, Dynamic -FCFWC = 1 -FCFWT = 1 +FCFWC = 1 # Excrescence drag factor +FCFWT = 1 # Aero technology factors for wing class RootChord(om.ExplicitComponent): - """Calculates the wing root chord""" + """Calculates the wing root chord.""" def setup(self): add_aviary_input(self, Aircraft.Wing.AREA) add_aviary_input(self, Aircraft.Wing.SPAN) add_aviary_input(self, Aircraft.Wing.TAPER_RATIO) - self.add_output('CROOT', 1.23456) + self.add_output('CROOT') def compute(self, inputs, outputs): SW, B, SLM = inputs.values() - outputs['CROOT'] = 2*SW/(B*(1.0 + SLM)) + outputs['CROOT'] = 2 * SW / (B * (1.0 + SLM)) def setup_partials(self): self.declare_partials( - 'CROOT', [ + 'CROOT', + [ Aircraft.Wing.AREA, Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO, - ]) + ], + ) def compute_partials(self, inputs, J): SW, B, SLM = inputs.values() - J['CROOT', Aircraft.Wing.AREA] = 2/(B*(1.0 + SLM)) - J['CROOT', Aircraft.Wing.SPAN] = -2*SW/(B**2*(1.0 + SLM)) - J['CROOT', Aircraft.Wing.TAPER_RATIO] = -2*SW/(B*(1.0 + SLM)**2) + J['CROOT', Aircraft.Wing.AREA] = 2 / (B * (1.0 + SLM)) + J['CROOT', Aircraft.Wing.SPAN] = -2 * SW / (B**2 * (1.0 + SLM)) + J['CROOT', Aircraft.Wing.TAPER_RATIO] = -2 * SW / (B * (1.0 + SLM) ** 2) class CommonVariables(om.ExplicitComponent): """ Calculates the wing_thickness_over_fuselage_diameter and an intermediate reference variable that maps the wing attachment - location from -1 (bottom of fuselage) to +1 (top of fuselage) + location from -1 (bottom of fuselage) to +1 (top of fuselage). """ def setup(self): self.add_input('CROOT') - add_aviary_input(self, Aircraft.Wing.MOUNTING_TYPE) + add_aviary_input(self, Aircraft.Wing.VERTICAL_MOUNT_LOCATION) add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT) add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER) - self.add_output('ZW_RF', 1.23456) - self.add_output('wtofd', 1.23456) + self.add_output('ZW_RF') + self.add_output('wtofd') def compute(self, inputs, outputs): CROOT, HWING, TCR, SWF = inputs.values() - outputs['ZW_RF'] = 2*HWING - 1 - outputs['wtofd'] = TCR*CROOT/SWF # wing_thickness_over_fuselage_diameter + outputs['ZW_RF'] = 2 * HWING - 1 + outputs['wtofd'] = TCR * CROOT / SWF # wing_thickness_over_fuselage_diameter def setup_partials(self): - self.declare_partials('ZW_RF', [Aircraft.Wing.MOUNTING_TYPE], val=2) + self.declare_partials('ZW_RF', [Aircraft.Wing.VERTICAL_MOUNT_LOCATION], val=2) self.declare_partials( - 'wtofd', [ + 'wtofd', + [ Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 'CROOT', Aircraft.Fuselage.AVG_DIAMETER, - ]) + ], + ) def compute_partials(self, inputs, J): CROOT, HWING, TCR, SWF = inputs.values() - J['wtofd', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = CROOT/SWF - J['wtofd', 'CROOT'] = TCR/SWF - J['wtofd', Aircraft.Fuselage.AVG_DIAMETER] = -TCR*CROOT/SWF**2 + J['wtofd', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = CROOT / SWF + J['wtofd', 'CROOT'] = TCR / SWF + J['wtofd', Aircraft.Fuselage.AVG_DIAMETER] = -TCR * CROOT / SWF**2 class TopAndBottomWidth(om.ExplicitComponent): - """Calculates the fuselage width at the top and bottom""" + """Calculates the fuselage width at the top and bottom.""" def setup(self): self.add_input('ZW_RF') self.add_input('wtofd') add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER) - self.add_output('WBODYWF', 1.23456) + self.add_output('WBODYWF') def compute(self, inputs, outputs): ZW_RF, wtofd, SWF = inputs.values() - if (cs.abs(ZW_RF + wtofd) >= 1.0): + if cs.abs(ZW_RF + wtofd) >= 1.0: WIDTHFTOP = 0.0 else: - WIDTHFTOP = SWF*(1.0 - (ZW_RF + wtofd)**2)**0.5 - if (cs.abs(ZW_RF - wtofd) >= 1.0): + WIDTHFTOP = SWF * (1.0 - (ZW_RF + wtofd) ** 2) ** 0.5 + if cs.abs(ZW_RF - wtofd) >= 1.0: WIDTHFBOT = 0.0 else: - WIDTHFBOT = SWF*(1.0 - (ZW_RF - wtofd)**2)**0.5 + WIDTHFBOT = SWF * (1.0 - (ZW_RF - wtofd) ** 2) ** 0.5 - outputs['WBODYWF'] = 0.5*(WIDTHFTOP + WIDTHFBOT) + outputs['WBODYWF'] = 0.5 * (WIDTHFTOP + WIDTHFBOT) def setup_partials(self): self.declare_partials( - 'WBODYWF', [ + 'WBODYWF', + [ 'ZW_RF', 'wtofd', Aircraft.Fuselage.AVG_DIAMETER, - ]) + ], + ) def compute_partials(self, inputs, J): ZW_RF, wtofd, SWF = inputs.values() - if (cs.abs(ZW_RF + wtofd) >= 1.0): + if cs.abs(ZW_RF + wtofd) >= 1.0: dTOP_dZWRF = 0 dTOP_dwtofd = 0 dTOP_dSWF = 0 else: - dTOP_dZWRF = -SWF*(1.0 - (ZW_RF + wtofd)**2)**-0.5 * (ZW_RF + wtofd) - dTOP_dwtofd = -SWF*(1.0 - (ZW_RF + wtofd)**2)**-0.5 * (ZW_RF + wtofd) - dTOP_dSWF = (1.0 - (ZW_RF + wtofd)**2)**0.5 - if (cs.abs(ZW_RF - wtofd) >= 1.0): + dTOP_dZWRF = -SWF * (1.0 - (ZW_RF + wtofd) ** 2) ** -0.5 * (ZW_RF + wtofd) + dTOP_dwtofd = -SWF * (1.0 - (ZW_RF + wtofd) ** 2) ** -0.5 * (ZW_RF + wtofd) + dTOP_dSWF = (1.0 - (ZW_RF + wtofd) ** 2) ** 0.5 + if cs.abs(ZW_RF - wtofd) >= 1.0: dBOT_dZWRF = 0 dBOT_dwtofd = 0 dBOT_dSWF = 0 else: - dBOT_dZWRF = -SWF*(1.0 - (ZW_RF - wtofd)**2)**-0.5 * (ZW_RF - wtofd) - dBOT_dwtofd = SWF*(1.0 - (ZW_RF - wtofd)**2)**-0.5 * (ZW_RF - wtofd) - dBOT_dSWF = (1.0 - (ZW_RF - wtofd)**2)**0.5 + dBOT_dZWRF = -SWF * (1.0 - (ZW_RF - wtofd) ** 2) ** -0.5 * (ZW_RF - wtofd) + dBOT_dwtofd = SWF * (1.0 - (ZW_RF - wtofd) ** 2) ** -0.5 * (ZW_RF - wtofd) + dBOT_dSWF = (1.0 - (ZW_RF - wtofd) ** 2) ** 0.5 - J['WBODYWF', 'ZW_RF'] = 0.5*(dTOP_dZWRF + dBOT_dZWRF) - J['WBODYWF', 'wtofd'] = 0.5*(dTOP_dwtofd + dBOT_dwtofd) - J['WBODYWF', Aircraft.Fuselage.AVG_DIAMETER] = 0.5*(dTOP_dSWF + dBOT_dSWF) + J['WBODYWF', 'ZW_RF'] = 0.5 * (dTOP_dZWRF + dBOT_dZWRF) + J['WBODYWF', 'wtofd'] = 0.5 * (dTOP_dwtofd + dBOT_dwtofd) + J['WBODYWF', Aircraft.Fuselage.AVG_DIAMETER] = 0.5 * (dTOP_dSWF + dBOT_dSWF) class BodyRatios(om.ExplicitComponent): - """Calculates some intermediate variables that are based on unitless ratios""" + """Calculates some intermediate variables that are based on unitless ratios.""" def setup(self): self.add_input('WBODYWF') @@ -149,49 +154,53 @@ def setup(self): add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT) add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP) - self.add_output('TCBODYWF', 1.23456) - self.add_output('CBODYWF', 1.23456) + self.add_output('TCBODYWF') + self.add_output('CBODYWF') def compute(self, inputs, outputs): WBODYWF, CROOT, B, SLM, TCR, TCT = inputs.values() - outputs['TCBODYWF'] = TCR - WBODYWF/B*(TCR - TCT) - outputs['CBODYWF'] = CROOT*(1.0 - WBODYWF/B*(1.0 - SLM)) + outputs['TCBODYWF'] = TCR - WBODYWF / B * (TCR - TCT) + outputs['CBODYWF'] = CROOT * (1.0 - WBODYWF / B * (1.0 - SLM)) def setup_partials(self): self.declare_partials( - 'TCBODYWF', [ + 'TCBODYWF', + [ Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 'WBODYWF', Aircraft.Wing.SPAN, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, - ]) + ], + ) self.declare_partials( - 'CBODYWF', [ + 'CBODYWF', + [ 'CROOT', 'WBODYWF', Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO, - ]) + ], + ) def compute_partials(self, inputs, J): WBODYWF, CROOT, B, SLM, TCR, TCT = inputs.values() - J['TCBODYWF', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = 1 - WBODYWF/B - J['TCBODYWF', 'WBODYWF'] = -1/B*(TCR - TCT) - J['TCBODYWF', Aircraft.Wing.SPAN] = WBODYWF/B**2*(TCR - TCT) - J['TCBODYWF', Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = WBODYWF/B + J['TCBODYWF', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = 1 - WBODYWF / B + J['TCBODYWF', 'WBODYWF'] = -1 / B * (TCR - TCT) + J['TCBODYWF', Aircraft.Wing.SPAN] = WBODYWF / B**2 * (TCR - TCT) + J['TCBODYWF', Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = WBODYWF / B - J['CBODYWF', 'CROOT'] = (1.0 - WBODYWF/B*(1.0 - SLM)) - J['CBODYWF', 'WBODYWF'] = CROOT*(-1/B*(1.0 - SLM)) - J['CBODYWF', Aircraft.Wing.SPAN] = CROOT*(WBODYWF/B**2*(1.0 - SLM)) - J['CBODYWF', Aircraft.Wing.TAPER_RATIO] = CROOT*(WBODYWF/B) + J['CBODYWF', 'CROOT'] = 1.0 - WBODYWF / B * (1.0 - SLM) + J['CBODYWF', 'WBODYWF'] = CROOT * (-1 / B * (1.0 - SLM)) + J['CBODYWF', Aircraft.Wing.SPAN] = CROOT * (WBODYWF / B**2 * (1.0 - SLM)) + J['CBODYWF', Aircraft.Wing.TAPER_RATIO] = CROOT * (WBODYWF / B) class InterferenceDrag(om.ExplicitComponent): """ Calculates the interference_independent_of_shielded_area and - drag_loss_due_to_shielded_wing_area + drag_loss_due_to_shielded_wing_area. """ def setup(self): @@ -203,22 +212,21 @@ def setup(self): add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER) add_aviary_input(self, Aircraft.Wing.CENTER_DISTANCE) - self.add_output('interference_independent_of_shielded_area', 1.23456) - self.add_output('drag_loss_due_to_shielded_wing_area', 1.23456) + self.add_output('interference_independent_of_shielded_area', 1.23456, units='unitless') + self.add_output('drag_loss_due_to_shielded_wing_area', 1.23456, units='unitless') def compute(self, inputs, outputs): WBODYWF, CROOT, TCBODYWF, CBODYWF, ZW_RF, SWF, XWQLF = inputs.values() # factor due to vertical location - KVWF = .0194 - 0.14817*ZW_RF + 1.3515*ZW_RF**2 + KVWF = 0.0194 - 0.14817 * ZW_RF + 1.3515 * ZW_RF**2 # factor due to longitudinal location - KLWF = 0.13077 + 1.9791*XWQLF + 3.3325*XWQLF**2 - \ - 10.095*XWQLF**3 + 4.7229*XWQLF**4 + KLWF = 0.13077 + 1.9791 * XWQLF + 3.3325 * XWQLF**2 - 10.095 * XWQLF**3 + 4.7229 * XWQLF**4 # factor due to fuselage diameter / thickness - KDTWF = 0.73543 + .028571*SWF/(TCBODYWF*CBODYWF) + KDTWF = 0.73543 + 0.028571 * SWF / (TCBODYWF * CBODYWF) - FEINTWF = 1.5*(TCBODYWF**3)*(CBODYWF**2)*KVWF*KLWF*KDTWF - AREASHIELDWF = 0.5*(CROOT + CBODYWF)*WBODYWF + FEINTWF = 1.5 * (TCBODYWF**3) * (CBODYWF**2) * KVWF * KLWF * KDTWF + AREASHIELDWF = 0.5 * (CROOT + CBODYWF) * WBODYWF # interference drag independent of shielded area outputs['interference_independent_of_shielded_area'] = FEINTWF @@ -227,48 +235,60 @@ def compute(self, inputs, outputs): def setup_partials(self): self.declare_partials( - 'interference_independent_of_shielded_area', [ + 'interference_independent_of_shielded_area', + [ 'TCBODYWF', 'CBODYWF', 'ZW_RF', Aircraft.Fuselage.AVG_DIAMETER, Aircraft.Wing.CENTER_DISTANCE, - ]) + ], + ) self.declare_partials( - 'drag_loss_due_to_shielded_wing_area', [ + 'drag_loss_due_to_shielded_wing_area', + [ 'CROOT', 'CBODYWF', 'WBODYWF', - ]) + ], + ) def compute_partials(self, inputs, J): WBODYWF, CROOT, TCBODYWF, CBODYWF, ZW_RF, SWF, XWQLF = inputs.values() - KVWF = .0194 - 0.14817*ZW_RF + 1.3515*ZW_RF**2 - dKVWF_dZWRF = -0.14817 + 2*1.3515*ZW_RF - KLWF = 0.13077 + 1.9791*XWQLF + 3.3325*XWQLF**2 - \ - 10.095*XWQLF**3 + 4.7229*XWQLF**4 - dKLWF_dXWQLF = 1.9791 + 2*3.3325*XWQLF - 3*10.095*XWQLF**2 + 4*4.7229*XWQLF**3 - KDTWF = 0.73543 + .028571*SWF/(TCBODYWF*CBODYWF) - dKDTWF_dSWF = .028571/(TCBODYWF*CBODYWF) + KVWF = 0.0194 - 0.14817 * ZW_RF + 1.3515 * ZW_RF**2 + dKVWF_dZWRF = -0.14817 + 2 * 1.3515 * ZW_RF + KLWF = 0.13077 + 1.9791 * XWQLF + 3.3325 * XWQLF**2 - 10.095 * XWQLF**3 + 4.7229 * XWQLF**4 + dKLWF_dXWQLF = 1.9791 + 2 * 3.3325 * XWQLF - 3 * 10.095 * XWQLF**2 + 4 * 4.7229 * XWQLF**3 + KDTWF = 0.73543 + 0.028571 * SWF / (TCBODYWF * CBODYWF) + dKDTWF_dSWF = 0.028571 / (TCBODYWF * CBODYWF) # dKDTWF_dTCBODYWF = -.028571*SWF/(TCBODYWF*CBODYWF)**2 # dKDTWF_dCBODYWF = -.028571*SWF/(TCBODYWF*CBODYWF)**2 - J['interference_independent_of_shielded_area', 'TCBODYWF'] = \ - 1.5*(TCBODYWF)*(CBODYWF**2)*KVWF*KLWF * \ - (3*0.73543*TCBODYWF + 2*.028571*SWF/CBODYWF) - J['interference_independent_of_shielded_area', 'CBODYWF'] = \ - 1.5*(TCBODYWF**3)*KVWF*KLWF*(2*0.73543*CBODYWF + .028571*SWF/TCBODYWF) - J['interference_independent_of_shielded_area', 'ZW_RF'] = \ - 1.5*(TCBODYWF**3)*(CBODYWF**2)*dKVWF_dZWRF*KLWF*KDTWF - J['interference_independent_of_shielded_area', Aircraft.Wing.CENTER_DISTANCE] = \ - 1.5*(TCBODYWF**3)*(CBODYWF**2)*KVWF*dKLWF_dXWQLF*KDTWF - J['interference_independent_of_shielded_area', Aircraft.Fuselage.AVG_DIAMETER] = \ - 1.5*(TCBODYWF**3)*(CBODYWF**2)*KVWF*KLWF*dKDTWF_dSWF - - J['drag_loss_due_to_shielded_wing_area', 'CROOT'] = 0.5*WBODYWF - J['drag_loss_due_to_shielded_wing_area', 'CBODYWF'] = 0.5*WBODYWF - J['drag_loss_due_to_shielded_wing_area', 'WBODYWF'] = 0.5*(CROOT + CBODYWF) + J['interference_independent_of_shielded_area', 'TCBODYWF'] = ( + 1.5 + * (TCBODYWF) + * (CBODYWF**2) + * KVWF + * KLWF + * (3 * 0.73543 * TCBODYWF + 2 * 0.028571 * SWF / CBODYWF) + ) + J['interference_independent_of_shielded_area', 'CBODYWF'] = ( + 1.5 * (TCBODYWF**3) * KVWF * KLWF * (2 * 0.73543 * CBODYWF + 0.028571 * SWF / TCBODYWF) + ) + J['interference_independent_of_shielded_area', 'ZW_RF'] = ( + 1.5 * (TCBODYWF**3) * (CBODYWF**2) * dKVWF_dZWRF * KLWF * KDTWF + ) + J['interference_independent_of_shielded_area', Aircraft.Wing.CENTER_DISTANCE] = ( + 1.5 * (TCBODYWF**3) * (CBODYWF**2) * KVWF * dKLWF_dXWQLF * KDTWF + ) + J['interference_independent_of_shielded_area', Aircraft.Fuselage.AVG_DIAMETER] = ( + 1.5 * (TCBODYWF**3) * (CBODYWF**2) * KVWF * KLWF * dKDTWF_dSWF + ) + + J['drag_loss_due_to_shielded_wing_area', 'CROOT'] = 0.5 * WBODYWF + J['drag_loss_due_to_shielded_wing_area', 'CBODYWF'] = 0.5 * WBODYWF + J['drag_loss_due_to_shielded_wing_area', 'WBODYWF'] = 0.5 * (CROOT + CBODYWF) class WingFuselageInterferencePremission(om.Group): @@ -281,103 +301,172 @@ class WingFuselageInterferencePremission(om.Group): """ def setup(self): - self.add_subsystem('root_chord', RootChord(), - promotes_inputs=['*'], promotes_outputs=['*']) - self.add_subsystem('common_variables', CommonVariables(), - promotes_inputs=['*'], promotes_outputs=['*']) - self.add_subsystem('top_and_bottom_width', TopAndBottomWidth(), - promotes_inputs=['*'], promotes_outputs=['*']) - self.add_subsystem('body_ratios', BodyRatios(), - promotes_inputs=['*'], promotes_outputs=['*']) - self.add_subsystem('interference_drag', InterferenceDrag(), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('root_chord', RootChord(), promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'common_variables', + CommonVariables(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'top_and_bottom_width', + TopAndBottomWidth(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'body_ratios', BodyRatios(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + self.add_subsystem( + 'interference_drag', + InterferenceDrag(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) class WingFuselageInterferenceMission(om.ExplicitComponent): """ This calculates an additional flat plate drag area due to general aerodynamic interference for wing-fuselage interference - (based on results from Hoerner's drag) + (based on results from Hoerner's drag). """ def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Wing.FORM_FACTOR, 1.25) + add_aviary_input(self, Aircraft.Wing.FORM_FACTOR) add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD) - add_aviary_input(self, Dynamic.Mission.MACH, shape=nn) - add_aviary_input(self, Dynamic.Mission.TEMPERATURE, shape=nn) - add_aviary_input(self, Dynamic.Mission.KINEMATIC_VISCOSITY, - shape=nn) - self.add_input('interference_independent_of_shielded_area') - self.add_input('drag_loss_due_to_shielded_wing_area') + add_aviary_input(self, Dynamic.Atmosphere.MACH, shape=nn) + add_aviary_input(self, Dynamic.Atmosphere.TEMPERATURE, shape=nn) + add_aviary_input(self, Dynamic.Atmosphere.KINEMATIC_VISCOSITY, shape=nn) + self.add_input('interference_independent_of_shielded_area', units='unitless') + self.add_input('drag_loss_due_to_shielded_wing_area', units='unitless') - self.add_output('wing_fuselage_interference_flat_plate_equivalent', - np.full(nn, 1.23456)) + self.add_output('wing_fuselage_interference_flat_plate_equivalent', shape=nn) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) self.declare_partials( - 'wing_fuselage_interference_flat_plate_equivalent', [ - Dynamic.Mission.MACH, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.KINEMATIC_VISCOSITY], - rows=arange, cols=arange) + 'wing_fuselage_interference_flat_plate_equivalent', + [ + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + ], + rows=arange, + cols=arange, + ) self.declare_partials( - 'wing_fuselage_interference_flat_plate_equivalent', [ + 'wing_fuselage_interference_flat_plate_equivalent', + [ Aircraft.Wing.FORM_FACTOR, Aircraft.Wing.AVERAGE_CHORD, - 'interference_independent_of_shielded_area'], - rows=arange, cols=np.zeros(nn)) - self.declare_partials('wing_fuselage_interference_flat_plate_equivalent', [ - 'drag_loss_due_to_shielded_wing_area'], val=1) + 'interference_independent_of_shielded_area', + ], + rows=arange, + cols=np.zeros(nn), + ) + self.declare_partials( + 'wing_fuselage_interference_flat_plate_equivalent', + ['drag_loss_due_to_shielded_wing_area'], + val=1, + ) def compute(self, inputs, outputs): CKW, CBARW, EM, T0, XKV, AREASHIELDWF, FEINTWF = inputs.values() # from gaspmain.f # reli = reynolds number per foot - RELI = np.sqrt(1.4*GRAV_ENGLISH_GASP*53.32) * EM * np.sqrt(T0)/XKV # dynamic + RELI = np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) * EM * np.sqrt(T0) / XKV # dynamic # from aero.f # CFIN CALCULATION FROM SCHLICHTING PG. 635-665 # log10(10_000_000.) = 7 - CFIN = 0.455/7**2.58/(1. + 0.144*EM**2)**0.65 # dynamic - CDWI = FCFWC*FCFWT*CFIN # dynamic - FEW_over_SW = CDWI * CKW * ((np.log10(RELI * CBARW)/7.)**(-2.6)) # dynamic + CFIN = 0.455 / 7**2.58 / (1.0 + 0.144 * EM**2) ** 0.65 # dynamic + CDWI = FCFWC * FCFWT * CFIN # dynamic + FEW_over_SW = CDWI * CKW * ((np.log10(RELI * CBARW) / 7.0) ** (-2.6)) # dynamic # from interference.f - FEIWF = FEINTWF - FEW_over_SW*AREASHIELDWF # dynamic + FEIWF = FEINTWF - FEW_over_SW * AREASHIELDWF # dynamic outputs['wing_fuselage_interference_flat_plate_equivalent'] = FEIWF def compute_partials(self, inputs, J): CKW, CBARW, EM, T0, XKV, AREASHIELDWF, FEINTWF = inputs.values() - RELI = np.sqrt(1.4*GRAV_ENGLISH_GASP*53.32) * EM * np.sqrt(T0)/XKV - dRELI_dEM = np.sqrt(1.4*GRAV_ENGLISH_GASP*53.32) * np.sqrt(T0)/XKV - - CFIN = 0.455/7**2.58/(1. + 0.144*EM**2)**0.65 - dCFIN_dEM = -.65*CFIN/(1. + 0.144*EM**2)*.288*EM - CDWI = FCFWC*FCFWT*CFIN - - J['wing_fuselage_interference_flat_plate_equivalent', Aircraft.Wing.FORM_FACTOR] = \ - -CDWI * ((np.log10(RELI * CBARW)/7.)**(-2.6))*AREASHIELDWF - J['wing_fuselage_interference_flat_plate_equivalent', Aircraft.Wing.AVERAGE_CHORD] = \ - 2.6*CDWI * CKW * ((np.log10(RELI * CBARW)/7.)**(-3.6))*AREASHIELDWF \ - * 1/(np.log(10)*(CBARW)*7) - J['wing_fuselage_interference_flat_plate_equivalent', Dynamic.Mission.MACH] = -CKW * AREASHIELDWF * (((np.log10(RELI * CBARW)/7.)**(-2.6)) * ( - FCFWC*FCFWT * dCFIN_dEM) + CFIN*(-2.6*((np.log10(RELI * CBARW)/7.)**(-3.6)) / (np.log(10)*(RELI)*7)*(dRELI_dEM))) - J['wing_fuselage_interference_flat_plate_equivalent', Dynamic.Mission.TEMPERATURE] = \ - -CDWI * CKW * -2.6*((np.log10(RELI * CBARW)/7.)**(-3.6))*AREASHIELDWF \ - * 1/(np.log(10)*(RELI)*7) * np.sqrt(1.4*GRAV_ENGLISH_GASP*53.32) \ - * EM * .5/(XKV*np.sqrt(T0)) - J['wing_fuselage_interference_flat_plate_equivalent', Dynamic.Mission.KINEMATIC_VISCOSITY] = \ - CDWI * CKW * -2.6*((np.log10(RELI * CBARW)/7.)**(-3.6))*AREASHIELDWF \ - * 1/(np.log(10)*(RELI)*7) * np.sqrt(1.4*GRAV_ENGLISH_GASP*53.32) \ - * EM * np.sqrt(T0) / XKV**2 - J['wing_fuselage_interference_flat_plate_equivalent', - 'interference_independent_of_shielded_area'] = \ - -CDWI * CKW * ((np.log10(RELI * CBARW)/7.)**(-2.6)) + RELI = np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) * EM * np.sqrt(T0) / XKV + dRELI_dEM = np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) * np.sqrt(T0) / XKV + + CFIN = 0.455 / 7**2.58 / (1.0 + 0.144 * EM**2) ** 0.65 + dCFIN_dEM = -0.65 * CFIN / (1.0 + 0.144 * EM**2) * 0.288 * EM + CDWI = FCFWC * FCFWT * CFIN + + J[ + 'wing_fuselage_interference_flat_plate_equivalent', + Aircraft.Wing.FORM_FACTOR, + ] = -CDWI * ((np.log10(RELI * CBARW) / 7.0) ** (-2.6)) * AREASHIELDWF + J[ + 'wing_fuselage_interference_flat_plate_equivalent', + Aircraft.Wing.AVERAGE_CHORD, + ] = ( + 2.6 + * CDWI + * CKW + * ((np.log10(RELI * CBARW) / 7.0) ** (-3.6)) + * AREASHIELDWF + * 1 + / (np.log(10) * (CBARW) * 7) + ) + J['wing_fuselage_interference_flat_plate_equivalent', Dynamic.Atmosphere.MACH] = ( + -CKW + * AREASHIELDWF + * ( + ((np.log10(RELI * CBARW) / 7.0) ** (-2.6)) * (FCFWC * FCFWT * dCFIN_dEM) + + CFIN + * ( + -2.6 + * ((np.log10(RELI * CBARW) / 7.0) ** (-3.6)) + / (np.log(10) * (RELI) * 7) + * (dRELI_dEM) + ) + ) + ) + J[ + 'wing_fuselage_interference_flat_plate_equivalent', + Dynamic.Atmosphere.TEMPERATURE, + ] = ( + -CDWI + * CKW + * -2.6 + * ((np.log10(RELI * CBARW) / 7.0) ** (-3.6)) + * AREASHIELDWF + * 1 + / (np.log(10) * (RELI) * 7) + * np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) + * EM + * 0.5 + / (XKV * np.sqrt(T0)) + ) + J[ + 'wing_fuselage_interference_flat_plate_equivalent', + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, + ] = ( + CDWI + * CKW + * -2.6 + * ((np.log10(RELI * CBARW) / 7.0) ** (-3.6)) + * AREASHIELDWF + * 1 + / (np.log(10) * (RELI) * 7) + * np.sqrt(1.4 * GRAV_ENGLISH_GASP * 53.32) + * EM + * np.sqrt(T0) + / XKV**2 + ) + J[ + 'wing_fuselage_interference_flat_plate_equivalent', + 'interference_independent_of_shielded_area', + ] = -CDWI * CKW * ((np.log10(RELI * CBARW) / 7.0) ** (-2.6)) diff --git a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py index 213b10b9d0..9a4b21ba12 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/premission_aero.py @@ -5,112 +5,117 @@ """ import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.subsystems.aerodynamics.gasp_based.flaps_model import FlapsGroup -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.variable_info.enums import SpeedType from aviary.subsystems.aerodynamics.gasp_based.gasp_aero_coeffs import AeroFormfactors -from aviary.subsystems.aerodynamics.gasp_based.interference import WingFuselageInterferencePremission +from aviary.subsystems.aerodynamics.gasp_based.interference import ( + WingFuselageInterferencePremission, +) +from aviary.subsystems.atmosphere.atmosphere import Atmosphere +from aviary.variable_info.enums import SpeedType +from aviary.variable_info.variables import Aircraft, Dynamic, Mission # TODO: add subsystems to compute CLMXFU, CLMXTO, CLMXLD using dynamic aero components # with alpha > alpha_stall class PreMissionAero(om.Group): - """Takeoff and landing flaps modeling""" - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + """Takeoff and landing flaps modeling.""" def setup(self): + self.add_subsystem( + 'wing_fus_interference_premission', + WingFuselageInterferencePremission(), + promotes_inputs=['*'], + promotes_outputs=[ + 'interference_independent_of_shielded_area', + 'drag_loss_due_to_shielded_wing_area', + ], + ) - aviary_options = self.options['aviary_options'] - - self.add_subsystem("wing_fus_interference_premission", - WingFuselageInterferencePremission(), - promotes_inputs=["aircraft:*"], - promotes_outputs=[ - "interference_independent_of_shielded_area", - "drag_loss_due_to_shielded_wing_area"], - ) - - self.add_subsystem("aero_form_factors", AeroFormfactors(), - promotes_inputs=["*"], - promotes_outputs=["*"], - ) + self.add_subsystem( + 'aero_form_factors', + AeroFormfactors(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) # speeds weren't originally computed here, speedtype of Mach is intended # to avoid multiple sources for computed Mach (gets calculated somewhere upstream) self.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=1, input_speed_type=SpeedType.MACH), - promotes=['*', (Dynamic.Mission.ALTITUDE, "alt_flaps")], + promotes=['*', (Dynamic.Mission.ALTITUDE, 'alt_flaps')], ) self.add_subsystem( - "kin_visc", + 'kin_visc', om.ExecComp( - "kinematic_viscosity = viscosity / rho", - viscosity={"units": "lbf*s/ft**2"}, - rho={"units": "slug/ft**3"}, - kinematic_viscosity={"units": "ft**2/s"}, + 'kinematic_viscosity = viscosity / rho', + viscosity={'units': 'lbf*s/ft**2'}, + rho={'units': 'slug/ft**3'}, + kinematic_viscosity={'units': 'ft**2/s'}, ), - promotes=["viscosity", - ("kinematic_viscosity", Dynamic.Mission.KINEMATIC_VISCOSITY), - ("rho", Dynamic.Mission.DENSITY)], + promotes=[ + 'viscosity', + ('kinematic_viscosity', Dynamic.Atmosphere.KINEMATIC_VISCOSITY), + ('rho', Dynamic.Atmosphere.DENSITY), + ], ) self.add_subsystem( - "flaps_up", - FlapsGroup(aviary_options=aviary_options), + 'flaps_up', + FlapsGroup(), promotes_inputs=[ - "*", - ("flap_defl", "flap_defl_up"), - ("slat_defl", "slat_defl_up"), + '*', + ('flap_defl', 'flap_defl_up'), + ('slat_defl', 'slat_defl_up'), ], - promotes_outputs=[("CL_max", Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP)], + promotes_outputs=[('CL_max', Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP)], ) self.add_subsystem( - "flaps_takeoff", - FlapsGroup(aviary_options=aviary_options), + 'flaps_takeoff', + FlapsGroup(), # slat deflection same for takeoff and landing - promotes_inputs=["*", ("flap_defl", Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF), - ("slat_defl", Aircraft.Wing.MAX_SLAT_DEFLECTION_TAKEOFF)], + promotes_inputs=[ + '*', + ('flap_defl', Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF), + ('slat_defl', Aircraft.Wing.MAX_SLAT_DEFLECTION_TAKEOFF), + ], promotes_outputs=[ - ("CL_max", Mission.Takeoff.LIFT_COEFFICIENT_MAX), + ('CL_max', Mission.Takeoff.LIFT_COEFFICIENT_MAX), ( - "delta_CL", + 'delta_CL', Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT, ), ( - "delta_CD", + 'delta_CD', Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT, ), ], ) self.add_subsystem( - "flaps_landing", - FlapsGroup(aviary_options=aviary_options), - promotes_inputs=["*", ("flap_defl", Aircraft.Wing.FLAP_DEFLECTION_LANDING), - ("slat_defl", Aircraft.Wing.MAX_SLAT_DEFLECTION_LANDING)], + 'flaps_landing', + FlapsGroup(), + promotes_inputs=[ + '*', + ('flap_defl', Aircraft.Wing.FLAP_DEFLECTION_LANDING), + ('slat_defl', Aircraft.Wing.MAX_SLAT_DEFLECTION_LANDING), + ], promotes_outputs=[ - ("CL_max", Mission.Landing.LIFT_COEFFICIENT_MAX), + ('CL_max', Mission.Landing.LIFT_COEFFICIENT_MAX), ( - "delta_CL", + 'delta_CL', Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT, ), ( - "delta_CD", + 'delta_CD', Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT, ), ], ) - self.set_input_defaults("alt_flaps", 0) - self.set_input_defaults("flap_defl_up", 0) - self.set_input_defaults("slat_defl_up", 0) + self.set_input_defaults('alt_flaps', 0) + self.set_input_defaults('flap_defl_up', 0) + self.set_input_defaults('slat_defl_up', 0) + self.set_input_defaults(Aircraft.Wing.SWEEP, units='deg') diff --git a/aviary/subsystems/aerodynamics/gasp_based/table_based.py b/aviary/subsystems/aerodynamics/gasp_based/table_based.py index 670dfb0f9f..85883fce6b 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/table_based.py +++ b/aviary/subsystems/aerodynamics/gasp_based/table_based.py @@ -1,17 +1,15 @@ -import os +from pathlib import Path import numpy as np import openmdao.api as om -from pathlib import Path - from aviary.constants import GRAV_ENGLISH_LBM +from aviary.subsystems.aerodynamics.flops_based.drag import ScaledCD from aviary.subsystems.aerodynamics.gasp_based.common import AeroForces, TimeRamp -from aviary.utils.named_values import NamedValues, get_keys -from aviary.utils.data_interpolator_builder import build_data_interpolator from aviary.utils.csv_data_file import read_data_file +from aviary.utils.data_interpolator_builder import build_data_interpolator from aviary.utils.functions import get_path -from aviary.utils.named_values import get_items +from aviary.utils.named_values import NamedValues, get_items, get_keys from aviary.variable_info.functions import add_aviary_input from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -19,16 +17,17 @@ # spaces are replaced with underscores when data tables are read) # "Repeated" aliases allows variables with different cases to match with desired # all-lowercase name -aliases = {Dynamic.Mission.ALTITUDE: ['h', 'alt', 'altitude'], - Dynamic.Mission.MACH: ['m', 'mach'], - 'angle_of_attack': ['alpha', 'angle_of_attack', 'AoA'], - 'flap_deflection': ['flap_deflection'], - 'hob': ['hob'], - 'lift_coefficient': ['cl', 'lift_coefficient'], - 'drag_coefficient': ['cd', 'drag_coefficient'], - 'delta_lift_coefficient': ['delta_cl', 'dcl'], - 'delta_drag_coefficient': ['delta_cd', 'dcd'] - } +aliases = { + Dynamic.Mission.ALTITUDE: ['h', 'alt', 'altitude'], + Dynamic.Atmosphere.MACH: ['m', 'mach'], + Dynamic.Vehicle.ANGLE_OF_ATTACK: ['alpha', 'angle_of_attack', 'AoA'], + 'flap_deflection': ['flap_deflection'], + 'hob': ['hob'], + 'lift_coefficient': ['cl', 'lift_coefficient'], + 'drag_coefficient': ['cd', 'drag_coefficient'], + 'delta_lift_coefficient': ['delta_cl', 'dcl'], + 'delta_drag_coefficient': ['delta_cd', 'dcd'], +} class TabularCruiseAero(om.Group): @@ -37,20 +36,31 @@ class TabularCruiseAero(om.Group): def initialize(self): self.options.declare('num_nodes', default=1, types=int) - self.options.declare('aero_data', types=(str, Path, NamedValues), default=None, - desc='Data file or NamedValues object containing lift and ' - 'drag coefficient table as a function of altitude, ' - 'Mach, and angle of attack') + self.options.declare( + 'aero_data', + types=(str, Path, NamedValues), + default=None, + desc='Data file or NamedValues object containing lift and ' + 'drag coefficient table as a function of altitude, ' + 'Mach, and angle of attack', + ) - self.options.declare('connect_training_data', default=False, - desc='When True, the aero tables will be passed as ' - 'OpenMDAO variables') + self.options.declare( + 'connect_training_data', + default=False, + desc='When True, the aero tables will be passed as OpenMDAO variables', + ) - self.options.declare('structured', types=bool, default=True, - desc='Flag that sets if data is a structured grid') + self.options.declare( + 'structured', + types=bool, + default=True, + desc='Flag that sets if data is a structured grid', + ) - self.options.declare('extrapolate', default=True, desc='Flag that sets if drag ' - 'data can be extrapolated') + self.options.declare( + 'extrapolate', default=True, desc='Flag that sets if drag data can be extrapolated' + ) def setup(self): options = self.options @@ -63,25 +73,37 @@ def setup(self): # handle aliasing for training data extra_promotes = [] if connect_training_data: - extra_promotes = [('lift_coefficient_train', Aircraft.Design.LIFT_POLAR), - ('drag_coefficient_train', Aircraft.Design.DRAG_POLAR)] + extra_promotes = [ + ('lift_coefficient_train', Aircraft.Design.LIFT_POLAR), + ('drag_coefficient_train', Aircraft.Design.DRAG_POLAR), + ] - interp_comp = _build_free_aero_interp(num_nodes=nn, aero_data=aero_data, - connect_training_data=connect_training_data, - structured=structured, - extrapolate=extrapolate) + interp_comp = _build_free_aero_interp( + num_nodes=nn, + aero_data=aero_data, + connect_training_data=connect_training_data, + structured=structured, + extrapolate=extrapolate, + ) - self.add_subsystem('free_aero_interp', - subsys=interp_comp, - promotes_inputs=[Dynamic.Mission.ALTITUDE, - Dynamic.Mission.MACH, - ('angle_of_attack', 'alpha')] - + extra_promotes, - promotes_outputs=[('lift_coefficient', 'CL'), ('drag_coefficient', 'CD')]) + self.add_subsystem( + 'free_aero_interp', + subsys=interp_comp, + promotes_inputs=[ + Dynamic.Mission.ALTITUDE, + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ] + + extra_promotes, + promotes_outputs=[('lift_coefficient', 'CL'), ('drag_coefficient', 'CD_prescaled')], + ) + + # + self.add_subsystem('simple_CD', ScaledCD(num_nodes=nn), promotes=['*']) - self.add_subsystem("forces", AeroForces(num_nodes=nn), promotes=["*"]) + self.add_subsystem('forces', AeroForces(num_nodes=nn), promotes=['*']) - self.set_input_defaults(Dynamic.Mission.MACH, np.zeros(nn)) + self.set_input_defaults(Dynamic.Atmosphere.MACH, np.zeros(nn)) class TabularLowSpeedAero(om.Group): @@ -93,37 +115,64 @@ class TabularLowSpeedAero(om.Group): """ def initialize(self): - self.options.declare("num_nodes", default=1, types=int) - - self.options.declare('free_aero_data', types=(str, Path, NamedValues), - default=None, - desc='Data file or NamedValues object containing free aero ' - 'lift and drag coefficient table as a function of ' - 'altitude, Mach, and angle of attack') - self.options.declare('flaps_aero_data', types=(str, Path, NamedValues), - default=None, - desc='Data file or NamedValues object containing flaps aero ' - 'lift and drag coefficient table as a function of ' - 'altitude, Mach, and angle of attack') - self.options.declare('ground_aero_data', types=(str, Path, NamedValues), - default=None, - desc='Data file or NamedValues object containing ground ' - 'aero lift and drag coefficient table as a function ' - 'of altitude, Mach, and angle of attack') - - self.options.declare('connect_training_data', types=bool, default=False, - desc='When True, all aero tables will be passed as ' - 'OpenMDAO variables') - self.options.declare('structured', types=bool, default=True, - desc='Flag that sets if all data are structured grids') - self.options.declare('extrapolate', types=bool, default=False, - desc='Flag that sets if all drag data can be extrapolated') - - self.options.declare("retract_gear", default=True, types=bool, - desc="True to start with gear landing gear down, False " - "for reverse") - self.options.declare("retract_flaps", default=True, types=bool, - desc="True to start with flaps applied, False for reverse") + self.options.declare('num_nodes', default=1, types=int) + + self.options.declare( + 'free_aero_data', + types=(str, Path, NamedValues), + default=None, + desc='Data file or NamedValues object containing free aero ' + 'lift and drag coefficient table as a function of ' + 'altitude, Mach, and angle of attack', + ) + self.options.declare( + 'flaps_aero_data', + types=(str, Path, NamedValues), + default=None, + desc='Data file or NamedValues object containing flaps aero ' + 'lift and drag coefficient table as a function of ' + 'altitude, Mach, and angle of attack', + ) + self.options.declare( + 'ground_aero_data', + types=(str, Path, NamedValues), + default=None, + desc='Data file or NamedValues object containing ground ' + 'aero lift and drag coefficient table as a function ' + 'of altitude, Mach, and angle of attack', + ) + + self.options.declare( + 'connect_training_data', + types=bool, + default=False, + desc='When True, all aero tables will be passed as OpenMDAO variables', + ) + self.options.declare( + 'structured', + types=bool, + default=True, + desc='Flag that sets if all data are structured grids', + ) + self.options.declare( + 'extrapolate', + types=bool, + default=False, + desc='Flag that sets if all drag data can be extrapolated', + ) + + self.options.declare( + 'retract_gear', + default=True, + types=bool, + desc='True to start with gear landing gear down, False for reverse', + ) + self.options.declare( + 'retract_flaps', + default=True, + types=bool, + desc='True to start with flaps applied, False for reverse', + ) def setup(self): options = self.options @@ -137,183 +186,189 @@ def setup(self): # convert altitude to height/span for ground effects hob = om.ExecComp( - "hob = (wing_height + altitude - airport_alt) / wingspan", - altitude=dict(val=np.zeros(nn), units="ft"), - airport_alt=dict(val=0, units="ft"), - wingspan=dict(val=117.8, units="ft"), - wing_height=dict( - val=8.0, units="ft", desc="Wing height above ground at 0 alt" - ), - hob=dict(shape=(nn,), desc="Wing height/span", units="unitless"), + 'hob = (wing_height + altitude - airport_alt) / wingspan', + altitude=dict(val=np.zeros(nn), units='ft'), + airport_alt=dict(val=0, units='ft'), + wingspan=dict(val=117.8, units='ft'), + wing_height=dict(val=8.0, units='ft', desc='Wing height above ground at 0 alt'), + hob=dict(shape=(nn,), desc='Wing height/span', units='unitless'), has_diag_partials=True, ) self.add_subsystem( - "hob", + 'hob', hob, promotes_inputs=[ Dynamic.Mission.ALTITUDE, - "airport_alt", - ("wingspan", Aircraft.Wing.SPAN), - ("wing_height", Aircraft.Wing.HEIGHT), + 'airport_alt', + ('wingspan', Aircraft.Wing.SPAN), + ('wing_height', Aircraft.Wing.HEIGHT), ], - promotes_outputs=["hob"], + promotes_outputs=['hob'], ) - free_aero_interp = _build_free_aero_interp(nn, aero_data=free_aero_data, - connect_training_data=connect_training_data, - structured=structured, - extrapolate=extrapolate) + free_aero_interp = _build_free_aero_interp( + nn, + aero_data=free_aero_data, + connect_training_data=connect_training_data, + structured=structured, + extrapolate=extrapolate, + ) # "base" free-air coefficients self.add_subsystem( - "interp_free", + 'interp_free', free_aero_interp, - promotes_inputs=[Dynamic.Mission.ALTITUDE, - Dynamic.Mission.MACH, ('angle_of_attack', 'alpha')], + promotes_inputs=[ + Dynamic.Mission.ALTITUDE, + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], promotes_outputs=[ - ("lift_coefficient", "CL_free"), - ("drag_coefficient", "CD_free"), - ("lift_coefficient_max", "CL_max_free"), + ('lift_coefficient', 'CL_free'), + ('drag_coefficient', 'CD_free'), + ('lift_coefficient_max', 'CL_max_free'), ], ) - flaps_aero_interp = _build_flaps_aero_interp(nn, aero_data=flaps_aero_data, - connect_training_data=connect_training_data, - structured=structured, - extrapolate=extrapolate) + flaps_aero_interp = _build_flaps_aero_interp( + nn, + aero_data=flaps_aero_data, + connect_training_data=connect_training_data, + structured=structured, + extrapolate=extrapolate, + ) # flap drag and lift increment from full flap deflection self.add_subsystem( - "interp_flaps", + 'interp_flaps', flaps_aero_interp, - promotes_inputs=[('flap_deflection', 'flap_defl'), - Dynamic.Mission.MACH, ('angle_of_attack', 'alpha')], + promotes_inputs=[ + ('flap_deflection', 'flap_defl'), + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + ], promotes_outputs=[ - ("delta_lift_coefficient", "dCL_flaps_full"), - ("delta_drag_coefficient", "dCD_flaps_full"), - ("delta_lift_coefficient_max", "dCL_max_flaps"), + ('delta_lift_coefficient', 'dCL_flaps_full'), + ('delta_drag_coefficient', 'dCD_flaps_full'), + ('delta_lift_coefficient_max', 'dCL_max_flaps'), ], ) - ground_aero_interp = _build_ground_aero_interp(nn, aero_data=ground_aero_data, - connect_training_data=connect_training_data, - structured=structured, - extrapolate=extrapolate) + ground_aero_interp = _build_ground_aero_interp( + nn, + aero_data=ground_aero_data, + connect_training_data=connect_training_data, + structured=structured, + extrapolate=extrapolate, + ) # drag and lift increments from ground effects self.add_subsystem( - "interp_ground", + 'interp_ground', ground_aero_interp, - promotes_inputs=[Dynamic.Mission.MACH, ('angle_of_attack', 'alpha'), 'hob'], + promotes_inputs=[ + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + 'hob', + ], promotes_outputs=[ - ("delta_lift_coefficient", "dCL_ground"), - ("delta_drag_coefficient", "dCD_ground"), - ("delta_lift_coefficient_max", "dCL_max_ground"), + ('delta_lift_coefficient', 'dCL_ground'), + ('delta_drag_coefficient', 'dCD_ground'), + ('delta_lift_coefficient_max', 'dCL_max_ground'), ], ) # drag increment from landing gear self.add_subsystem( - "gear_drag", + 'gear_drag', GearDragIncrement(num_nodes=nn), - promotes_inputs=["aircraft:*", "flap_defl", "mission:*"], - promotes_outputs=[("dCD", "dCD_gear_full")], + promotes_inputs=['*'], + promotes_outputs=[('dCD', 'dCD_gear_full')], ) # scale gear drag increment over time self.add_subsystem( - "gear_drag_ramp", - TimeRamp( - num_nodes=nn, num_inputs=1, ramp_up=not self.options["retract_gear"] - ), + 'gear_drag_ramp', + TimeRamp(num_nodes=nn, num_inputs=1, ramp_up=not self.options['retract_gear']), promotes_inputs=[ - ("t_init", "t_init_gear"), - ("duration", "dt_gear"), - ("x", "dCD_gear_full"), - "t_curr", + ('t_init', 't_init_gear'), + ('duration', 'dt_gear'), + ('x', 'dCD_gear_full'), + 't_curr', ], - promotes_outputs=[("y", "dCD_gear")], + promotes_outputs=[('y', 'dCD_gear')], ) # scale flap drag and lift # TODO mux these? self.add_subsystem( - "flaps_drag_ramp", - TimeRamp( - num_nodes=nn, num_inputs=1, ramp_up=not self.options["retract_gear"] - ), + 'flaps_drag_ramp', + TimeRamp(num_nodes=nn, num_inputs=1, ramp_up=not self.options['retract_gear']), promotes_inputs=[ - ("t_init", "t_init_flaps"), - ("duration", "dt_flaps"), - ("x", "dCD_flaps_full"), - "t_curr", + ('t_init', 't_init_flaps'), + ('duration', 'dt_flaps'), + ('x', 'dCD_flaps_full'), + 't_curr', ], - promotes_outputs=[("y", "dCD_flaps")], + promotes_outputs=[('y', 'dCD_flaps')], ) self.add_subsystem( - "flaps_lift_ramp", - TimeRamp( - num_nodes=nn, num_inputs=1, ramp_up=not self.options["retract_gear"] - ), + 'flaps_lift_ramp', + TimeRamp(num_nodes=nn, num_inputs=1, ramp_up=not self.options['retract_gear']), promotes_inputs=[ - ("t_init", "t_init_flaps"), - ("duration", "dt_flaps"), - ("x", "dCL_flaps_full"), - "t_curr", + ('t_init', 't_init_flaps'), + ('duration', 'dt_flaps'), + ('x', 'dCL_flaps_full'), + 't_curr', ], - promotes_outputs=[("y", "dCL_flaps")], + promotes_outputs=[('y', 'dCL_flaps')], ) # add up CL + increments, CD + increments, CL_max + increments adder = om.AddSubtractComp() adder.add_equation( - "CL", vec_size=nn, units='unitless', input_names=["CL_free", "dCL_ground", "dCL_flaps"] + 'CL', vec_size=nn, units='unitless', input_names=['CL_free', 'dCL_ground', 'dCL_flaps'] ) adder.add_equation( - "CD", + 'CD', vec_size=nn, units='unitless', - input_names=["CD_free", "dCD_ground", "dCD_flaps", "dCD_gear"], + input_names=['CD_free', 'dCD_ground', 'dCD_flaps', 'dCD_gear'], ) adder.add_equation( - "CL_max", + 'CL_max', vec_size=nn, units='unitless', - input_names=["CL_max_free", "dCL_max_flaps", "dCL_max_ground"], + input_names=['CL_max_free', 'dCL_max_flaps', 'dCL_max_ground'], ) - self.add_subsystem("coef_sum", adder, promotes=["*"]) + self.add_subsystem('coef_sum', adder, promotes=['*']) # convert coefficients to forces self.add_subsystem( - "forces", + 'forces', AeroForces(num_nodes=nn), - promotes_inputs=[ - "CL", - "CD", - Dynamic.Mission.DYNAMIC_PRESSURE, - ] - + ["aircraft:*"], - promotes_outputs=[Dynamic.Mission.LIFT, Dynamic.Mission.DRAG], + promotes_inputs=['*'], + promotes_outputs=[Dynamic.Vehicle.LIFT, Dynamic.Vehicle.DRAG], ) - if self.options["retract_gear"]: + if self.options['retract_gear']: # takeoff defaults - self.set_input_defaults("dt_gear", 7) + self.set_input_defaults('dt_gear', 7) else: # TODO default gear duration for landing? pass - if self.options["retract_flaps"]: + if self.options['retract_flaps']: # takeoff defaults - self.set_input_defaults("flap_defl", 10 * np.ones(nn)) - self.set_input_defaults("dt_flaps", 3) + self.set_input_defaults('flap_defl', 10 * np.ones(nn)) + self.set_input_defaults('dt_flaps', 3) else: # landing defaults - self.set_input_defaults("flap_defl", 40 * np.ones(nn)) + self.set_input_defaults('flap_defl', 40 * np.ones(nn)) # TODO default flap duration for landing? self.set_input_defaults(Dynamic.Mission.ALTITUDE, np.zeros(nn)) - self.set_input_defaults(Dynamic.Mission.MACH, np.zeros(nn)) + self.set_input_defaults(Dynamic.Atmosphere.MACH, np.zeros(nn)) class GearDragIncrement(om.ExplicitComponent): @@ -323,37 +378,36 @@ class GearDragIncrement(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_nodes", default=1, types=int) + self.options.declare('num_nodes', default=1, types=int) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400.0) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') - add_aviary_input(self, Aircraft.Wing.AREA, val=1370.3) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') # note flap_defl should be a constant (scalar) but interpolation breaks with # mixed scalar/vector inputs so you can just ``prob.set_val("flap_defl", 10)`` self.add_input( - "flap_defl", + 'flap_defl', 0.0, shape=nn, - units="deg", - desc="DFLAP: Flap deflection angle. This is the *full* flap " - "deflection angle for a given flight segment (DFLPLD, " - "DFLPTO).", + units='deg', + desc='DFLAP: Flap deflection angle. This is the *full* flap ' + 'deflection angle for a given flight segment (DFLPLD, ' + 'DFLPTO).', ) self.add_output( - "dCD", units="unitless", shape=nn, - desc="Drag coefficient increment for landing gear" + 'dCD', units='unitless', shape=nn, desc='Drag coefficient increment for landing gear' ) def setup_partials(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] arange = np.arange(nn) - self.declare_partials("dCD", ["flap_defl"], rows=arange, cols=arange) - self.declare_partials("dCD", [Mission.Design.GROSS_MASS, Aircraft.Wing.AREA]) + self.declare_partials('dCD', ['flap_defl'], rows=arange, cols=arange) + self.declare_partials('dCD', [Mission.Design.GROSS_MASS, Aircraft.Wing.AREA]) def compute(self, inputs, outputs): gross_mass_initial, wing_area, flap_defl = inputs.values() @@ -364,7 +418,7 @@ def compute(self, inputs, outputs): # landing gear CD increment for zero flap deflection grcd = grfe / wing_area - outputs["dCD"] = grcd * (1 - 0.454545 * flap_defl / 50) + outputs['dCD'] = grcd * (1 - 0.454545 * flap_defl / 50) def compute_partials(self, inputs, J): gross_mass_initial, wing_area, flap_defl = inputs.values() @@ -372,44 +426,54 @@ def compute_partials(self, inputs, J): grfe = 0.0033 * gross_wt_initial**0.785 grcd = grfe / wing_area - J["dCD", Mission.Design.GROSS_MASS] = ( - 0.0033 * 0.785 * gross_wt_initial ** (0.785 - 1) / wing_area - ) * (1 - 0.454545 * flap_defl / 50) * GRAV_ENGLISH_LBM - J["dCD", Aircraft.Wing.AREA] = -(grfe / wing_area**2) * ( - 1 - 0.454545 * flap_defl / 50 + J['dCD', Mission.Design.GROSS_MASS] = ( + (0.0033 * 0.785 * gross_wt_initial ** (0.785 - 1) / wing_area) + * (1 - 0.454545 * flap_defl / 50) + * GRAV_ENGLISH_LBM ) - J["dCD", "flap_defl"] = -grcd * 0.454545 / 50 - - -def _build_free_aero_interp(num_nodes=0, aero_data=None, connect_training_data=False, - method='lagrange2', structured=True, extrapolate=True): - """creates interpolation components for cruise aero""" + J['dCD', Aircraft.Wing.AREA] = -(grfe / wing_area**2) * (1 - 0.454545 * flap_defl / 50) + J['dCD', 'flap_defl'] = -grcd * 0.454545 / 50 + + +def _build_free_aero_interp( + num_nodes=0, + aero_data=None, + connect_training_data=False, + method='lagrange2', + structured=True, + extrapolate=True, +): + """Creates interpolation components for cruise aero.""" # build_data_interpolator normally handles converting to filepath and reading # data, but here we need to query the data before building the component if isinstance(aero_data, str): aero_data = get_path(aero_data) if isinstance(aero_data, Path): - aero_data = read_data_file(aero_data, aliases=aliases) + aero_data, _, _ = read_data_file(aero_data, aliases=aliases) # aero_data is modified in-place, deepcopy required interp_data = aero_data.deepcopy() interp_data = _structure_special_grid(interp_data) - required_inputs = {Dynamic.Mission.ALTITUDE, Dynamic.Mission.MACH, - 'angle_of_attack'} + required_inputs = { + Dynamic.Mission.ALTITUDE, + Dynamic.Atmosphere.MACH, + Dynamic.Vehicle.ANGLE_OF_ATTACK, + } required_outputs = {'lift_coefficient', 'drag_coefficient'} missing_variables = [] if not required_inputs <= get_keys(interp_data): - missing_variables.append([key for key in - required_inputs.difference(get_keys(interp_data))]) + missing_variables.append([key for key in required_inputs.difference(get_keys(interp_data))]) if not connect_training_data and not required_outputs <= get_keys(interp_data): - missing_variables.append([key for key in - required_outputs.difference(get_keys(interp_data))]) + missing_variables.append( + [key for key in required_outputs.difference(get_keys(interp_data))] + ) if missing_variables: - raise KeyError('GASP-based aerodynamics interpolation missing required ' - f'variables: {missing_variables}') + raise KeyError( + f'GASP-based aerodynamics interpolation missing required variables: {missing_variables}' + ) if connect_training_data: method = 'lagrange2' @@ -417,14 +481,15 @@ def _build_free_aero_interp(num_nodes=0, aero_data=None, connect_training_data=F method = '3D-lagrange2' # add the 3d metamodel to the group, promoting all variables - interp_comp = build_data_interpolator(num_nodes=num_nodes, - interpolator_data=interp_data, - interpolator_outputs={'lift_coefficient': 'unitless', - 'drag_coefficient': 'unitless'}, - method=method, - structured=structured, - connect_training_data=connect_training_data, - extrapolate=extrapolate) + interp_comp = build_data_interpolator( + num_nodes=num_nodes, + interpolator_data=interp_data, + interpolator_outputs={'lift_coefficient': 'unitless', 'drag_coefficient': 'unitless'}, + method=method, + structured=structured, + connect_training_data=connect_training_data, + extrapolate=extrapolate, + ) if connect_training_data: return interp_comp @@ -436,23 +501,33 @@ def _build_free_aero_interp(num_nodes=0, aero_data=None, connect_training_data=F # free aero CL at max alpha is the same across altitudes but ignore that for now cl_max = interp_data.get_val('lift_coefficient', 'unitless')[0, :, -1] # add a 1d metamodel for cl_max, promoting all variables - meta_1d = om.MetaModelStructuredComp(method='1D-lagrange2', - vec_size=num_nodes, - extrapolate=extrapolate) - meta_1d.add_input(Dynamic.Mission.MACH, 0.0, units="unitless", - shape=num_nodes, - training_data=interp_data.get_val(Dynamic.Mission.MACH, - 'unitless')) - meta_1d.add_output('lift_coefficient_max', units="unitless", - shape=num_nodes, training_data=cl_max) - - group.add_subsystem("lift_coefficient_max_interp", meta_1d, promotes=["*"]) + meta_1d = om.MetaModelStructuredComp( + method='1D-lagrange2', vec_size=num_nodes, extrapolate=extrapolate + ) + meta_1d.add_input( + Dynamic.Atmosphere.MACH, + 0.0, + units='unitless', + shape=num_nodes, + training_data=interp_data.get_val(Dynamic.Atmosphere.MACH, 'unitless'), + ) + meta_1d.add_output( + 'lift_coefficient_max', units='unitless', shape=num_nodes, training_data=cl_max + ) + + group.add_subsystem('lift_coefficient_max_interp', meta_1d, promotes=['*']) return group -def _build_flaps_aero_interp(num_nodes=0, aero_data=None, connect_training_data=False, - method='slinear', structured=True, extrapolate=False): - """creates interpolation components for cruise aero""" +def _build_flaps_aero_interp( + num_nodes=0, + aero_data=None, + connect_training_data=False, + method='slinear', + structured=True, + extrapolate=False, +): + """Creates interpolation components for cruise aero.""" # TODO linear method default because standard GASP tables have only two flap # deflections - may want to have option for two separate 2D tables instead? @@ -461,33 +536,36 @@ def _build_flaps_aero_interp(num_nodes=0, aero_data=None, connect_training_data= if isinstance(aero_data, str): aero_data = get_path(aero_data) if isinstance(aero_data, Path): - aero_data = read_data_file(aero_data, aliases=aliases) + aero_data, _, _ = read_data_file(aero_data, aliases=aliases) # aero_data is modified in-place, deepcopy required interp_data = aero_data.deepcopy() interp_data = _structure_special_grid(interp_data) - required_inputs = {'flap_deflection', Dynamic.Mission.MACH, 'angle_of_attack'} + required_inputs = {'flap_deflection', Dynamic.Atmosphere.MACH, Dynamic.Vehicle.ANGLE_OF_ATTACK} required_outputs = {'delta_lift_coefficient', 'delta_drag_coefficient'} missing_variables = [] if not required_inputs <= get_keys(interp_data): - missing_variables.extend([key for key in - required_inputs.difference(get_keys(interp_data))]) + missing_variables.extend([key for key in required_inputs.difference(get_keys(interp_data))]) if not connect_training_data and not required_outputs <= get_keys(interp_data): - missing_variables.extend([key for key in - required_outputs.difference(get_keys(interp_data))]) + missing_variables.extend( + [key for key in required_outputs.difference(get_keys(interp_data))] + ) if missing_variables: - raise KeyError('GASP-based aerodynamics interpolation missing required ' - f'variables: {missing_variables}') + raise KeyError( + f'GASP-based aerodynamics interpolation missing required variables: {missing_variables}' + ) dcl = interp_data.get_val('delta_lift_coefficient', 'unitless') - defl = np.unique(interp_data.get_val('flap_deflection', 'deg') - ) # units don't matter, not using values - alpha = np.unique(interp_data.get_val('angle_of_attack', 'deg') - ) # units don't matter, not using values - mach = np.unique(interp_data.get_val(Dynamic.Mission.MACH, 'unitless')) + defl = np.unique( + interp_data.get_val('flap_deflection', 'deg') + ) # units don't matter, not using values + alpha = np.unique( + interp_data.get_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 'deg') + ) # units don't matter, not using values + mach = np.unique(interp_data.get_val(Dynamic.Atmosphere.MACH, 'unitless')) dcl_max = np.zeros_like(dcl) shape = (defl.size, mach.size, alpha.size) @@ -498,48 +576,60 @@ def _build_flaps_aero_interp(num_nodes=0, aero_data=None, connect_training_data= interp_data.set_val('delta_lift_coefficient_max', dcl_max.flatten(), 'unitless') - return build_data_interpolator(num_nodes=num_nodes, - interpolator_data=interp_data, - interpolator_outputs={'delta_lift_coefficient': 'unitless', - 'delta_drag_coefficient': 'unitless', - 'delta_lift_coefficient_max': 'unitless'}, - method=method, - structured=structured, - connect_training_data=connect_training_data, - extrapolate=extrapolate) - - -def _build_ground_aero_interp(num_nodes=0, aero_data=None, connect_training_data=False, - method='slinear', structured=True, extrapolate=True): - """creates interpolation components for cruise aero""" + return build_data_interpolator( + num_nodes=num_nodes, + interpolator_data=interp_data, + interpolator_outputs={ + 'delta_lift_coefficient': 'unitless', + 'delta_drag_coefficient': 'unitless', + 'delta_lift_coefficient_max': 'unitless', + }, + method=method, + structured=structured, + connect_training_data=connect_training_data, + extrapolate=extrapolate, + ) + + +def _build_ground_aero_interp( + num_nodes=0, + aero_data=None, + connect_training_data=False, + method='slinear', + structured=True, + extrapolate=True, +): + """Creates interpolation components for cruise aero.""" # build_data_interpolator normally handles converting to filepath and reading # data, but here we need to query the data before building the component if isinstance(aero_data, str): aero_data = get_path(aero_data) if isinstance(aero_data, Path): - aero_data = read_data_file(aero_data, aliases=aliases) + aero_data, _, _ = read_data_file(aero_data, aliases=aliases) # aero_data is modified in-place, deepcopy required interp_data = aero_data.deepcopy() - required_inputs = {'hob', Dynamic.Mission.MACH, 'angle_of_attack'} + required_inputs = {'hob', Dynamic.Atmosphere.MACH, Dynamic.Vehicle.ANGLE_OF_ATTACK} required_outputs = {'delta_lift_coefficient', 'delta_drag_coefficient'} missing_variables = [] if not required_inputs <= get_keys(interp_data): - missing_variables.append([key for key in - required_inputs.difference(get_keys(interp_data))]) + missing_variables.append([key for key in required_inputs.difference(get_keys(interp_data))]) if not connect_training_data and not required_outputs <= get_keys(interp_data): - missing_variables.append([key for key in - required_outputs.difference(get_keys(interp_data))]) + missing_variables.append( + [key for key in required_outputs.difference(get_keys(interp_data))] + ) if missing_variables: - raise KeyError('GASP-based aerodynamics interpolation missing required ' - f'variables: {missing_variables}') + raise KeyError( + f'GASP-based aerodynamics interpolation missing required variables: {missing_variables}' + ) dcl = interp_data.get_val('delta_lift_coefficient', 'unitless') - alpha = np.unique(interp_data.get_val('angle_of_attack', 'deg') - ) # units don't matter, not using values - mach = np.unique(interp_data.get_val(Dynamic.Mission.MACH, 'unitless')) + alpha = np.unique( + interp_data.get_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 'deg') + ) # units don't matter, not using values + mach = np.unique(interp_data.get_val(Dynamic.Atmosphere.MACH, 'unitless')) hob = np.unique(interp_data.get_val('hob', 'unitless')) dcl_max = np.zeros_like(dcl) @@ -552,21 +642,25 @@ def _build_ground_aero_interp(num_nodes=0, aero_data=None, connect_training_data interp_data.set_val('delta_lift_coefficient_max', dcl_max.flatten(), 'unitless') # extrapolation fine especially for HOB over max - return build_data_interpolator(num_nodes=num_nodes, - interpolator_data=interp_data, - interpolator_outputs={'delta_lift_coefficient': 'unitless', - 'delta_drag_coefficient': 'unitless', - 'delta_lift_coefficient_max': 'unitless'}, - method=method, - structured=structured, - connect_training_data=connect_training_data, - extrapolate=extrapolate) + return build_data_interpolator( + num_nodes=num_nodes, + interpolator_data=interp_data, + interpolator_outputs={ + 'delta_lift_coefficient': 'unitless', + 'delta_drag_coefficient': 'unitless', + 'delta_lift_coefficient_max': 'unitless', + }, + method=method, + structured=structured, + connect_training_data=connect_training_data, + extrapolate=extrapolate, + ) def _structure_special_grid(aero_data): """ Structure a GASP-based data table that has a special case with incorrect number - of alpha points for a structured grid + of alpha points for a structured grid. This assumes that the first two values in the data table (or directly provided data) are the other independent variables (mach, alt, or hob depending on use case), while @@ -587,7 +681,7 @@ def _structure_special_grid(aero_data): x0 = np.unique(data[0]) x1 = np.unique(data[1]) # units don't matter, not using values - aoa = aero_data.get_val('angle_of_attack', 'deg') + aoa = aero_data.get_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 'deg') if data[0].shape[0] > x0.shape[0]: # special case alpha - this format saturates alpha at its max @@ -598,6 +692,6 @@ def _structure_special_grid(aero_data): _, _, aoa = np.meshgrid(x0, x1, aoa) # put the aoa data back in the NamedValues object - aero_data.set_val('angle_of_attack', aoa.flatten(), 'deg') + aero_data.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, aoa.flatten(), 'deg') return aero_data diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_cruise.csv b/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_cruise.csv index d99c764103..bbd04751f8 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_cruise.csv +++ b/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_cruise.csv @@ -1,176 +1,176 @@ alt,mach,alpha,sos,nu,cl,cd -30000.0,0.7,-2.0,993.117604407563,0.0003488216607365757,-0.08640382438898087,0.0172194205224514 -30000.0,0.7,0.0,993.117604407563,0.0003488216607365757,0.1296057403087616,0.017582233995199203 -30000.0,0.7,2.0,993.117604407563,0.0003488216607365757,0.34561532735824585,0.021573178470134735 -30000.0,0.7,4.0,993.117604407563,0.0003488216607365757,0.5616248846054077,0.029192250221967697 -30000.0,0.7,6.0,993.117604407563,0.0003488216607365757,0.7776344418525696,0.040439456701278687 -30000.0,0.7,8.0,993.117604407563,0.0003488216607365757,0.9936439990997314,0.05531478673219681 -30000.0,0.7,10.0,993.117604407563,0.0003488216607365757,1.209653615951538,0.07397009432315826 -30000.0,0.75,-2.0,993.117604407563,0.0003488216607365757,-0.08962029218673706,0.01702469028532505 -30000.0,0.75,0.0,993.117604407563,0.0003488216607365757,0.13443045318126678,0.017414027824997902 -30000.0,0.75,2.0,993.117604407563,0.0003488216607365757,0.35848119854927063,0.021696723997592926 -30000.0,0.75,4.0,993.117604407563,0.0003488216607365757,0.5825319290161133,0.029872776940464973 -30000.0,0.75,6.0,993.117604407563,0.0003488216607365757,0.8065826296806335,0.04208044335246086 -30000.0,0.75,8.0,993.117604407563,0.0003488216607365757,1.0306333303451538,0.059328723698854446 -30000.0,0.75,10.0,993.117604407563,0.0003488216607365757,1.2546840906143188,0.08296471834182739 -30000.0,0.8,-2.0,993.117604407563,0.0003488216607365757,-0.09355007857084274,0.016843244433403015 -30000.0,0.8,0.0,993.117604407563,0.0003488216607365757,0.1403251439332962,0.017266450449824333 -30000.0,0.8,2.0,993.117604407563,0.0003488216607365757,0.37420034408569336,0.02199641242623329 -30000.0,0.8,4.0,993.117604407563,0.0003488216607365757,0.6080754995346069,0.03198563680052757 -30000.0,0.8,6.0,993.117604407563,0.0003488216607365757,0.8419507741928101,0.048757463693618774 -30000.0,0.8,8.0,993.117604407563,0.0003488216607365757,1.0758259296417236,0.07384493947029114 -30000.0,0.8,10.0,993.117604407563,0.0003488216607365757,1.3097012042999268,0.1087811067700386 -30000.0,0.8500000000000001,-2.0,993.117604407563,0.0003488216607365757,-0.09845549613237381,0.01668662019073963 -30000.0,0.8500000000000001,0.0,993.117604407563,0.0003488216607365757,0.1476832628250122,0.01783456839621067 -30000.0,0.8500000000000001,2.0,993.117604407563,0.0003488216607365757,0.3938220143318176,0.026024600490927696 -30000.0,0.8500000000000001,4.0,993.117604407563,0.0003488216607365757,0.6399607062339783,0.04304378107190132 -30000.0,0.8500000000000001,6.0,993.117604407563,0.0003488216607365757,0.8860995173454285,0.0706791877746582 -30000.0,0.8500000000000001,8.0,993.117604407563,0.0003488216607365757,1.1322382688522339,0.11071794480085373 -30000.0,0.8500000000000001,10.0,993.117604407563,0.0003488216607365757,1.378377079963684,0.1649470329284668 -30000.0,0.9000000000000001,-2.0,993.117604407563,0.0003488216607365757,-0.10476978868246078,0.01860608346760273 -30000.0,0.9000000000000001,0.0,993.117604407563,0.0003488216607365757,0.15715469419956207,0.024898428469896317 -30000.0,0.9000000000000001,2.0,993.117604407563,0.0003488216607365757,0.4190791845321655,0.04249711334705353 -30000.0,0.9000000000000001,4.0,993.117604407563,0.0003488216607365757,0.6810036897659302,0.07355557382106781 -30000.0,0.9000000000000001,6.0,993.117604407563,0.0003488216607365757,0.9429281949996948,0.12022723257541656 -30000.0,0.9000000000000001,8.0,993.117604407563,0.0003488216607365757,1.2048527002334595,0.18466560542583466 -30000.0,0.9000000000000001,10.0,993.117604407563,0.0003488216607365757,1.4667772054672241,0.26902395486831665 -32000.0,0.7,-2.0,984.4119274955854,0.00037028660881333053,-0.08640382438898087,0.01735277660191059 -32000.0,0.7,0.0,984.4119274955854,0.00037028660881333053,0.1296057403087616,0.01771608740091324 -32000.0,0.7,2.0,984.4119274955854,0.00037028660881333053,0.34561532735824585,0.021712495014071465 -32000.0,0.7,4.0,984.4119274955854,0.00037028660881333053,0.5616248846054077,0.02934199944138527 -32000.0,0.7,6.0,984.4119274955854,0.00037028660881333053,0.7776344418525696,0.0406046062707901 -32000.0,0.7,8.0,984.4119274955854,0.00037028660881333053,0.9936439990997314,0.05550030618906021 -32000.0,0.7,10.0,984.4119274955854,0.00037028660881333053,1.209653615951538,0.07418094575405121 -32000.0,0.75,-2.0,984.4119274955854,0.00037028660881333053,-0.08962029218673706,0.01715543493628502 -32000.0,0.75,0.0,984.4119274955854,0.00037028660881333053,0.13443045318126678,0.017545295879244804 -32000.0,0.75,2.0,984.4119274955854,0.00037028660881333053,0.35848119854927063,0.0218337532132864 -32000.0,0.75,4.0,984.4119274955854,0.00037028660881333053,0.5825319290161133,0.030020806938409805 -32000.0,0.75,6.0,984.4119274955854,0.00037028660881333053,0.8065826296806335,0.04224471002817154 -32000.0,0.75,8.0,984.4119274955854,0.00037028660881333053,1.0306333303451538,0.05951446294784546 -32000.0,0.75,10.0,984.4119274955854,0.00037028660881333053,1.2546840906143188,0.08317716419696808 -32000.0,0.8,-2.0,984.4119274955854,0.00037028660881333053,-0.09355007857084274,0.01697150431573391 -32000.0,0.8,0.0,984.4119274955854,0.00037028660881333053,0.1403251439332962,0.017395269125699997 -32000.0,0.8,2.0,984.4119274955854,0.00037028660881333053,0.37420034408569336,0.022131387144327164 -32000.0,0.8,4.0,984.4119274955854,0.00037028660881333053,0.6080754995346069,0.03213236480951309 -32000.0,0.8,6.0,984.4119274955854,0.00037028660881333053,0.8419507741928101,0.04892154410481453 -32000.0,0.8,8.0,984.4119274955854,0.00037028660881333053,1.0758259296417236,0.07403197139501572 -32000.0,0.8,10.0,984.4119274955854,0.00037028660881333053,1.3097012042999268,0.10899668186903 -32000.0,0.8500000000000001,-2.0,984.4119274955854,0.00037028660881333053,-0.09845549613237381,0.016812512651085854 -32000.0,0.8500000000000001,0.0,984.4119274955854,0.00037028660881333053,0.1476832628250122,0.01796106994152069 -32000.0,0.8500000000000001,2.0,984.4119274955854,0.00037028660881333053,0.3938220143318176,0.026157792657613754 -32000.0,0.8500000000000001,4.0,984.4119274955854,0.00037028660881333053,0.6399607062339783,0.043189749121665955 -32000.0,0.8500000000000001,6.0,984.4119274955854,0.00037028660881333053,0.8860995173454285,0.07084401696920395 -32000.0,0.8500000000000001,8.0,984.4119274955854,0.00037028660881333053,1.1322382688522339,0.11090770363807678 -32000.0,0.8500000000000001,10.0,984.4119274955854,0.00037028660881333053,1.378377079963684,0.16516782343387604 -32000.0,0.9000000000000001,-2.0,984.4119274955854,0.00037028660881333053,-0.10476978868246078,0.018729714676737785 -32000.0,0.9000000000000001,0.0,984.4119274955854,0.00037028660881333053,0.15715469419956207,0.025022735819220543 -32000.0,0.9000000000000001,2.0,984.4119274955854,0.00037028660881333053,0.4190791845321655,0.04262885823845863 -32000.0,0.9000000000000001,4.0,984.4119274955854,0.00037028660881333053,0.6810036897659302,0.07370150834321976 -32000.0,0.9000000000000001,6.0,984.4119274955854,0.00037028660881333053,0.9429281949996948,0.12039414048194885 -32000.0,0.9000000000000001,8.0,984.4119274955854,0.00037028660881333053,1.2048527002334595,0.1848602294921875 -32000.0,0.9000000000000001,10.0,984.4119274955854,0.00037028660881333053,1.4667772054672241,0.26925304532051086 -34000.0,0.7,-2.0,975.6336602716075,0.00039345715777017176,-0.08640382438898087,0.017490219324827194 -34000.0,0.7,0.0,975.6336602716075,0.00039345715777017176,0.1296057403087616,0.01785404235124588 -34000.0,0.7,2.0,975.6336602716075,0.00039345715777017176,0.34561532735824585,0.02185608074069023 -34000.0,0.7,4.0,975.6336602716075,0.00039345715777017176,0.5616248846054077,0.029496338218450546 -34000.0,0.7,6.0,975.6336602716075,0.00039345715777017176,0.7776344418525696,0.040774814784526825 -34000.0,0.7,8.0,975.6336602716075,0.00039345715777017176,0.9936439990997314,0.05569150671362877 -34000.0,0.7,10.0,975.6336602716075,0.00039345715777017176,1.209653615951538,0.07439824938774109 -34000.0,0.75,-2.0,975.6336602716075,0.00039345715777017176,-0.08962029218673706,0.01729017309844494 -34000.0,0.75,0.0,975.6336602716075,0.00039345715777017176,0.13443045318126678,0.017680574208498 -34000.0,0.75,2.0,975.6336602716075,0.00039345715777017176,0.35848119854927063,0.021974969655275345 -34000.0,0.75,4.0,975.6336602716075,0.00039345715777017176,0.5825319290161133,0.03017335757613182 -34000.0,0.75,6.0,975.6336602716075,0.00039345715777017176,0.8065826296806335,0.042413994669914246 -34000.0,0.75,8.0,975.6336602716075,0.00039345715777017176,1.0306333303451538,0.059705883264541626 -34000.0,0.75,10.0,975.6336602716075,0.00039345715777017176,1.2546840906143188,0.08339612185955048 -34000.0,0.8,-2.0,975.6336602716075,0.00039345715777017176,-0.09355007857084274,0.01710367761552334 -34000.0,0.8,0.0,975.6336602716075,0.00039345715777017176,0.1403251439332962,0.017528019845485687 -34000.0,0.8,2.0,975.6336602716075,0.00039345715777017176,0.37420034408569336,0.022270483896136284 -34000.0,0.8,4.0,975.6336602716075,0.00039345715777017176,0.6080754995346069,0.03228357434272766 -34000.0,0.8,6.0,975.6336602716075,0.00039345715777017176,0.8419507741928101,0.04909063130617142 -34000.0,0.8,8.0,975.6336602716075,0.00039345715777017176,1.0758259296417236,0.07422471046447754 -34000.0,0.8,10.0,975.6336602716075,0.00039345715777017176,1.3097012042999268,0.10921883583068848 -34000.0,0.8500000000000001,-2.0,975.6336602716075,0.00039345715777017176,-0.09845549613237381,0.01694224588572979 -34000.0,0.8500000000000001,0.0,975.6336602716075,0.00039345715777017176,0.1476832628250122,0.01809142902493477 -34000.0,0.8500000000000001,2.0,975.6336602716075,0.00039345715777017176,0.3938220143318176,0.026295045390725136 -34000.0,0.8500000000000001,4.0,975.6336602716075,0.00039345715777017176,0.6399607062339783,0.04334016516804695 -34000.0,0.8500000000000001,6.0,975.6336602716075,0.00039345715777017176,0.8860995173454285,0.07101386040449142 -34000.0,0.8500000000000001,8.0,975.6336602716075,0.00039345715777017176,1.1322382688522339,0.11110325157642365 -34000.0,0.8500000000000001,10.0,975.6336602716075,0.00039345715777017176,1.378377079963684,0.1653953194618225 -34000.0,0.9000000000000001,-2.0,975.6336602716075,0.00039345715777017176,-0.10476978868246078,0.018857108429074287 -34000.0,0.9000000000000001,0.0,975.6336602716075,0.00039345715777017176,0.15715469419956207,0.025150826200842857 -34000.0,0.9000000000000001,2.0,975.6336602716075,0.00039345715777017176,0.4190791845321655,0.042764611542224884 -34000.0,0.9000000000000001,4.0,975.6336602716075,0.00039345715777017176,0.6810036897659302,0.07385189086198807 -34000.0,0.9000000000000001,6.0,975.6336602716075,0.00039345715777017176,0.9429281949996948,0.12056611478328705 -34000.0,0.9000000000000001,8.0,975.6336602716075,0.00039345715777017176,1.2048527002334595,0.1850607693195343 -34000.0,0.9000000000000001,10.0,975.6336602716075,0.00039345715777017176,1.4667772054672241,0.2694891393184662 -36000.0,0.7,-2.0,966.7807835059835,0.00041850065463222563,-0.08640382438898087,0.017631949856877327 -36000.0,0.7,0.0,966.7807835059835,0.00041850065463222563,0.1296057403087616,0.017996300011873245 -36000.0,0.7,2.0,966.7807835059835,0.00041850065463222563,0.34561532735824585,0.022004147991538048 -36000.0,0.7,4.0,966.7807835059835,0.00041850065463222563,0.5616248846054077,0.029655491933226585 -36000.0,0.7,6.0,966.7807835059835,0.00041850065463222563,0.7776344418525696,0.040950335562229156 -36000.0,0.7,8.0,966.7807835059835,0.00041850065463222563,0.9936439990997314,0.055888671427965164 -36000.0,0.7,10.0,966.7807835059835,0.00041850065463222563,1.209653615951538,0.07462234795093536 -36000.0,0.75,-2.0,966.7807835059835,0.00041850065463222563,-0.08962029218673706,0.017429111525416374 -36000.0,0.75,0.0,966.7807835059835,0.00041850065463222563,0.13443045318126678,0.017820067703723907 -36000.0,0.75,2.0,966.7807835059835,0.00041850065463222563,0.35848119854927063,0.022120587527751923 -36000.0,0.75,4.0,966.7807835059835,0.00041850065463222563,0.5825319290161133,0.030330665409564972 -36000.0,0.75,6.0,966.7807835059835,0.00041850065463222563,0.8065826296806335,0.04258856177330017 -36000.0,0.75,8.0,966.7807835059835,0.00041850065463222563,1.0306333303451538,0.05990327149629593 -36000.0,0.75,10.0,966.7807835059835,0.00041850065463222563,1.2546840906143188,0.08362189680337906 -36000.0,0.8,-2.0,966.7807835059835,0.00041850065463222563,-0.09355007857084274,0.01723996363580227 -36000.0,0.8,0.0,966.7807835059835,0.00041850065463222563,0.1403251439332962,0.017664900049567223 -36000.0,0.8,2.0,966.7807835059835,0.00041850065463222563,0.37420034408569336,0.022413907572627068 -36000.0,0.8,4.0,966.7807835059835,0.00041850065463222563,0.6080754995346069,0.032439492642879486 -36000.0,0.8,6.0,966.7807835059835,0.00041850065463222563,0.8419507741928101,0.04926498979330063 -36000.0,0.8,8.0,966.7807835059835,0.00041850065463222563,1.0758259296417236,0.07442345470190048 -36000.0,0.8,10.0,966.7807835059835,0.00041850065463222563,1.3097012042999268,0.10944792628288269 -36000.0,0.8500000000000001,-2.0,966.7807835059835,0.00041850065463222563,-0.09845549613237381,0.017075998708605766 -36000.0,0.8500000000000001,0.0,966.7807835059835,0.00041850065463222563,0.1476832628250122,0.018225830048322678 -36000.0,0.8500000000000001,2.0,966.7807835059835,0.00041850065463222563,0.3938220143318176,0.02643655613064766 -36000.0,0.8500000000000001,4.0,966.7807835059835,0.00041850065463222563,0.6399607062339783,0.04349524527788162 -36000.0,0.8500000000000001,6.0,966.7807835059835,0.00041850065463222563,0.8860995173454285,0.07118897885084152 -36000.0,0.8500000000000001,8.0,966.7807835059835,0.00041850065463222563,1.1322382688522339,0.1113048642873764 -36000.0,0.8500000000000001,10.0,966.7807835059835,0.00041850065463222563,1.378377079963684,0.16562990844249725 -36000.0,0.9000000000000001,-2.0,966.7807835059835,0.00041850065463222563,-0.10476978868246078,0.018988456577062607 -36000.0,0.9000000000000001,0.0,966.7807835059835,0.00041850065463222563,0.15715469419956207,0.02528289332985878 -36000.0,0.9000000000000001,2.0,966.7807835059835,0.00041850065463222563,0.4190791845321655,0.042904578149318695 -36000.0,0.9000000000000001,4.0,966.7807835059835,0.00041850065463222563,0.6810036897659302,0.07400694489479065 -36000.0,0.9000000000000001,6.0,966.7807835059835,0.00041850065463222563,0.9429281949996948,0.12074342370033264 -36000.0,0.9000000000000001,8.0,966.7807835059835,0.00041850065463222563,1.2048527002334595,0.18526753783226013 -36000.0,0.9000000000000001,10.0,966.7807835059835,0.00041850065463222563,1.4667772054672241,0.2697325348854065 -38000.0,0.7,-2.0,966.0199501498222,0.0004593963676597923,-0.08640382438898087,0.01782325841486454 -38000.0,0.7,0.0,966.0199501498222,0.0004593963676597923,0.1296057403087616,0.018188321962952614 -38000.0,0.7,2.0,966.0199501498222,0.0004593963676597923,0.34561532735824585,0.02220400795340538 -38000.0,0.7,4.0,966.0199501498222,0.0004593963676597923,0.5616248846054077,0.029870320111513138 -38000.0,0.7,6.0,966.0199501498222,0.0004593963676597923,0.7776344418525696,0.04118725657463074 -38000.0,0.7,8.0,966.0199501498222,0.0004593963676597923,0.9936439990997314,0.05615481734275818 -38000.0,0.7,10.0,966.0199501498222,0.0004593963676597923,1.209653615951538,0.07492483407258987 -38000.0,0.75,-2.0,966.0199501498222,0.0004593963676597923,-0.08962029218673706,0.0176166370511055 -38000.0,0.75,0.0,966.0199501498222,0.0004593963676597923,0.13443045318126678,0.018008345738053322 -38000.0,0.75,2.0,966.0199501498222,0.0004593963676597923,0.35848119854927063,0.022317130118608475 -38000.0,0.75,4.0,966.0199501498222,0.0004593963676597923,0.5825319290161133,0.03054298833012581 -38000.0,0.75,6.0,966.0199501498222,0.0004593963676597923,0.8065826296806335,0.04282417893409729 -38000.0,0.75,8.0,966.0199501498222,0.0004593963676597923,1.0306333303451538,0.06016969680786133 -38000.0,0.75,10.0,966.0199501498222,0.0004593963676597923,1.2546840906143188,0.08392664045095444 -38000.0,0.8,-2.0,966.0199501498222,0.0004593963676597923,-0.09355007857084274,0.017423897981643677 -38000.0,0.8,0.0,966.0199501498222,0.0004593963676597923,0.1403251439332962,0.01784963719546795 -38000.0,0.8,2.0,966.0199501498222,0.0004593963676597923,0.37420034408569336,0.02260747365653515 -38000.0,0.8,4.0,966.0199501498222,0.0004593963676597923,0.6080754995346069,0.03264991194009781 -38000.0,0.8,6.0,966.0199501498222,0.0004593963676597923,0.8419507741928101,0.04950029402971268 -38000.0,0.8,8.0,966.0199501498222,0.0004593963676597923,1.0758259296417236,0.07469167560338974 -38000.0,0.8,10.0,966.0199501498222,0.0004593963676597923,1.3097012042999268,0.10975708067417145 -38000.0,0.8500000000000001,-2.0,966.0199501498222,0.0004593963676597923,-0.09845549613237381,0.017256515100598335 -38000.0,0.8500000000000001,0.0,966.0199501498222,0.0004593963676597923,0.1476832628250122,0.018407218158245087 -38000.0,0.8500000000000001,2.0,966.0199501498222,0.0004593963676597923,0.3938220143318176,0.026627538725733757 -38000.0,0.8500000000000001,4.0,966.0199501498222,0.0004593963676597923,0.6399607062339783,0.043704546988010406 -38000.0,0.8500000000000001,6.0,966.0199501498222,0.0004593963676597923,0.8860995173454285,0.07142531871795654 -38000.0,0.8500000000000001,8.0,966.0199501498222,0.0004593963676597923,1.1322382688522339,0.11157697439193726 -38000.0,0.8500000000000001,10.0,966.0199501498222,0.0004593963676597923,1.378377079963684,0.16594651341438293 -38000.0,0.9000000000000001,-2.0,966.0199501498222,0.0004593963676597923,-0.10476978868246078,0.019165704026818275 -38000.0,0.9000000000000001,0.0,966.0199501498222,0.0004593963676597923,0.15715469419956207,0.02546110935509205 -38000.0,0.9000000000000001,2.0,966.0199501498222,0.0004593963676597923,0.4190791845321655,0.04309345781803131 -38000.0,0.9000000000000001,4.0,966.0199501498222,0.0004593963676597923,0.6810036897659302,0.07421617954969406 -38000.0,0.9000000000000001,6.0,966.0199501498222,0.0004593963676597923,0.9429281949996948,0.12098271399736404 -38000.0,0.9000000000000001,8.0,966.0199501498222,0.0004593963676597923,1.2048527002334595,0.18554656207561493 -38000.0,0.9000000000000001,10.0,966.0199501498222,0.0004593963676597923,1.4667772054672241,0.2700609862804413 +30000.0,0.7,-2.0,993.117604407563,0.0003488216607365757,-0.08640382438898087,0.01584287 +30000.0,0.7,0.0,993.117604407563,0.0003488216607365757,0.1296057403087616,0.01620081 +30000.0,0.7,2.0,993.117604407563,0.0003488216607365757,0.34561532735824585,0.02013821 +30000.0,0.7,4.0,993.117604407563,0.0003488216607365757,0.5616248846054077,0.02765504 +30000.0,0.7,6.0,993.117604407563,0.0003488216607365757,0.7776344418525696,0.03875067 +30000.0,0.7,8.0,993.117604407563,0.0003488216607365757,0.9936439990997314,0.05342706 +30000.0,0.7,10.0,993.117604407563,0.0003488216607365757,1.209653615951538,0.07183307 +30000.0,0.75,-2.0,993.117604407563,0.0003488216607365757,-0.08962029218673706,0.0156691 +30000.0,0.75,0.0,993.117604407563,0.0003488216607365757,0.13443045318126678,0.01605327 +30000.0,0.75,2.0,993.117604407563,0.0003488216607365757,0.35848119854927063,0.02027874 +30000.0,0.75,4.0,993.117604407563,0.0003488216607365757,0.5825319290161133,0.0283468 +30000.0,0.75,6.0,993.117604407563,0.0003488216607365757,0.8065826296806335,0.04039371 +30000.0,0.75,8.0,993.117604407563,0.0003488216607365757,1.0306333303451538,0.05743162 +30000.0,0.75,10.0,993.117604407563,0.0003488216607365757,1.2546840906143188,0.08080459 +30000.0,0.8,-2.0,993.117604407563,0.0003488216607365757,-0.09355007857084274,0.01550764 +30000.0,0.8,0.0,993.117604407563,0.0003488216607365757,0.1403251439332962,0.01592437 +30000.0,0.8,2.0,993.117604407563,0.0003488216607365757,0.37420034408569336,0.02059316 +30000.0,0.8,4.0,993.117604407563,0.0003488216607365757,0.6080754995346069,0.03046754 +30000.0,0.8,6.0,993.117604407563,0.0003488216607365757,0.8419507741928101,0.0470678 +30000.0,0.8,8.0,993.117604407563,0.0003488216607365757,1.0758259296417236,0.07192827 +30000.0,0.8,10.0,993.117604407563,0.0003488216607365757,1.3097012042999268,0.10658205 +30000.0,0.850,-2.0,993.117604407563,0.0003488216607365757,-0.09845549613237381,0.0153696 +30000.0,0.850,0.0,993.117604407563,0.0003488216607365757,0.1476832628250122,0.01651247 +30000.0,0.850,2.0,993.117604407563,0.0003488216607365757,0.3938220143318176,0.02463618 +30000.0,0.850,4.0,993.117604407563,0.0003488216607365757,0.6399607062339783,0.04152845 +30000.0,0.850,6.0,993.117604407563,0.0003488216607365757,0.8860995173454285,0.06897653 +30000.0,0.850,8.0,993.117604407563,0.0003488216607365757,1.1322382688522339,0.10876751 +30000.0,0.850,10.0,993.117604407563,0.0003488216607365757,1.378377079963684,0.16268846 +30000.0,0.900,-2.0,993.117604407563,0.0003488216607365757,-0.10476978868246078,0.01730906 +30000.0,0.900,0.0,993.117604407563,0.0003488216607365757,0.15715469419956207,0.02359454 +30000.0,0.900,2.0,993.117604407563,0.0003488216607365757,0.4190791845321655,0.04111895 +30000.0,0.900,4.0,993.117604407563,0.0003488216607365757,0.6810036897659302,0.07203575 +30000.0,0.900,6.0,993.117604407563,0.0003488216607365757,0.9429281949996948,0.11849837 +30000.0,0.900,8.0,993.117604407563,0.0003488216607365757,1.2048527002334595,0.18266025 +30000.0,0.900,10.0,993.117604407563,0.0003488216607365757,1.4667772054672241,0.26667481 +32000.0,0.7,-2.0,984.4119274955854,0.00037028660881333053,-0.08640382438898087,0.01596348 +32000.0,0.7,0.0,984.4119274955854,0.00037028660881333053,0.1296057403087616,0.01632188 +32000.0,0.7,2.0,984.4119274955854,0.00037028660881333053,0.34561532735824585,0.02026424 +32000.0,0.7,4.0,984.4119274955854,0.00037028660881333053,0.5616248846054077,0.02779055 +32000.0,0.7,6.0,984.4119274955854,0.00037028660881333053,0.7776344418525696,0.03890019 +32000.0,0.7,8.0,984.4119274955854,0.00037028660881333053,0.9936439990997314,0.0535951 +32000.0,0.7,10.0,984.4119274955854,0.00037028660881333053,1.209653615951538,0.07202414 +32000.0,0.75,-2.0,984.4119274955854,0.00037028660881333053,-0.08962029218673706,0.01578734 +32000.0,0.75,0.0,984.4119274955854,0.00037028660881333053,0.13443045318126678,0.01617198 +32000.0,0.75,2.0,984.4119274955854,0.00037028660881333053,0.35848119854927063,0.02040269 +32000.0,0.75,4.0,984.4119274955854,0.00037028660881333053,0.5825319290161133,0.02848076 +32000.0,0.75,6.0,984.4119274955854,0.00037028660881333053,0.8065826296806335,0.04054243 +32000.0,0.75,8.0,984.4119274955854,0.00037028660881333053,1.0306333303451538,0.05759986 +32000.0,0.75,10.0,984.4119274955854,0.00037028660881333053,1.2546840906143188,0.08099711 +32000.0,0.8,-2.0,984.4119274955854,0.00037028660881333053,-0.09355007857084274,0.01562362 +32000.0,0.8,0.0,984.4119274955854,0.00037028660881333053,0.1403251439332962,0.01604085 +32000.0,0.8,2.0,984.4119274955854,0.00037028660881333053,0.37420034408569336,0.02071525 +32000.0,0.8,4.0,984.4119274955854,0.00037028660881333053,0.6080754995346069,0.03060031 +32000.0,0.8,6.0,984.4119274955854,0.00037028660881333053,0.8419507741928101,0.04721635 +32000.0,0.8,8.0,984.4119274955854,0.00037028660881333053,1.0758259296417236,0.07209767 +32000.0,0.8,10.0,984.4119274955854,0.00037028660881333053,1.3097012042999268,0.10677741 +32000.0,0.850,-2.0,984.4119274955854,0.00037028660881333053,-0.09845549613237381,0.01548343 +32000.0,0.850,0.0,984.4119274955854,0.00037028660881333053,0.1476832628250122,0.01662685 +32000.0,0.850,2.0,984.4119274955854,0.00037028660881333053,0.3938220143318176,0.02475665 +32000.0,0.850,4.0,984.4119274955854,0.00037028660881333053,0.6399607062339783,0.04166053 +32000.0,0.850,6.0,984.4119274955854,0.00037028660881333053,0.8860995173454285,0.06912575 +32000.0,0.850,8.0,984.4119274955854,0.00037028660881333053,1.1322382688522339,0.1089394 +32000.0,0.850,10.0,984.4119274955854,0.00037028660881333053,1.378377079963684,0.16288854 +32000.0,0.900,-2.0,984.4119274955854,0.00037028660881333053,-0.10476978868246078,0.01742084 +32000.0,0.900,0.0,984.4119274955854,0.00037028660881333053,0.15715469419956207,0.02370693 +32000.0,0.900,2.0,984.4119274955854,0.00037028660881333053,0.4190791845321655,0.04123811 +32000.0,0.900,4.0,984.4119274955854,0.00037028660881333053,0.6810036897659302,0.07216781 +32000.0,0.900,6.0,984.4119274955854,0.00037028660881333053,0.9429281949996948,0.11864948 +32000.0,0.900,8.0,984.4119274955854,0.00037028660881333053,1.2048527002334595,0.18283655 +32000.0,0.900,10.0,984.4119274955854,0.00037028660881333053,1.4667772054672241,0.26688245 +34000.0,0.7,-2.0,975.6336602716075,0.00039345715777017176,-0.08640382438898087,0.0160878 +34000.0,0.7,0.0,975.6336602716075,0.00039345715777017176,0.1296057403087616,0.01644666 +34000.0,0.7,2.0,975.6336602716075,0.00039345715777017176,0.34561532735824585,0.02039414 +34000.0,0.7,4.0,975.6336602716075,0.00039345715777017176,0.5616248846054077,0.02793023 +34000.0,0.7,6.0,975.6336602716075,0.00039345715777017176,0.7776344418525696,0.0390543 +34000.0,0.7,8.0,975.6336602716075,0.00039345715777017176,0.9936439990997314,0.0537683 +34000.0,0.7,10.0,975.6336602716075,0.00039345715777017176,1.209653615951538,0.07222109 +34000.0,0.75,-2.0,975.6336602716075,0.00039345715777017176,-0.08962029218673706,0.0159092 +34000.0,0.75,0.0,975.6336602716075,0.00039345715777017176,0.13443045318126678,0.01629433 +34000.0,0.75,2.0,975.6336602716075,0.00039345715777017176,0.35848119854927063,0.02053044 +34000.0,0.75,4.0,975.6336602716075,0.00039345715777017176,0.5825319290161133,0.02861881 +34000.0,0.75,6.0,975.6336602716075,0.00039345715777017176,0.8065826296806335,0.0406957 +34000.0,0.75,8.0,975.6336602716075,0.00039345715777017176,1.0306333303451538,0.05777326 +34000.0,0.75,10.0,975.6336602716075,0.00039345715777017176,1.2546840906143188,0.08119555 +34000.0,0.8,-2.0,975.6336602716075,0.00039345715777017176,-0.09355007857084274,0.01574315 +34000.0,0.8,0.0,975.6336602716075,0.00039345715777017176,0.1403251439332962,0.01616091 +34000.0,0.8,2.0,975.6336602716075,0.00039345715777017176,0.37420034408569336,0.02084107 +34000.0,0.8,4.0,975.6336602716075,0.00039345715777017176,0.6080754995346069,0.03073715 +34000.0,0.8,6.0,975.6336602716075,0.00039345715777017176,0.8419507741928101,0.04736944 +34000.0,0.8,8.0,975.6336602716075,0.00039345715777017176,1.0758259296417236,0.07227227 +34000.0,0.8,10.0,975.6336602716075,0.00039345715777017176,1.3097012042999268,0.10697875 +34000.0,0.850,-2.0,975.6336602716075,0.00039345715777017176,-0.09845549613237381,0.01560074 +34000.0,0.850,0.0,975.6336602716075,0.00039345715777017176,0.1476832628250122,0.01674473 +34000.0,0.850,2.0,975.6336602716075,0.00039345715777017176,0.3938220143318176,0.0248808 +34000.0,0.850,4.0,975.6336602716075,0.00039345715777017176,0.6399607062339783,0.04179664 +34000.0,0.850,6.0,975.6336602716075,0.00039345715777017176,0.8860995173454285,0.06927953 +34000.0,0.850,8.0,975.6336602716075,0.00039345715777017176,1.1322382688522339,0.10911654 +34000.0,0.850,10.0,975.6336602716075,0.00039345715777017176,1.378377079963684,0.16309475 +34000.0,0.900,-2.0,975.6336602716075,0.00039345715777017176,-0.10476978868246078,0.01753603 +34000.0,0.900,0.0,975.6336602716075,0.00039345715777017176,0.15715469419956207,0.02382276 +34000.0,0.900,2.0,975.6336602716075,0.00039345715777017176,0.4190791845321655,0.0413609 +34000.0,0.900,4.0,975.6336602716075,0.00039345715777017176,0.6810036897659302,0.0723039 +34000.0,0.900,6.0,975.6336602716075,0.00039345715777017176,0.9429281949996948,0.1188052 +34000.0,0.900,8.0,975.6336602716075,0.00039345715777017176,1.2048527002334595,0.18301823 +34000.0,0.900,10.0,975.6336602716075,0.00039345715777017176,1.4667772054672241,0.26709643 +36000.0,0.7,-2.0,966.7807835059835,0.00041850065463222563,-0.08640382438898087,0.016216 +36000.0,0.7,0.0,966.7807835059835,0.00041850065463222563,0.1296057403087616,0.01657535 +36000.0,0.7,2.0,966.7807835059835,0.00041850065463222563,0.34561532735824585,0.02052811 +36000.0,0.7,4.0,966.7807835059835,0.00041850065463222563,0.5616248846054077,0.02807429 +36000.0,0.7,6.0,966.7807835059835,0.00041850065463222563,0.7776344418525696,0.03921324 +36000.0,0.7,8.0,966.7807835059835,0.00041850065463222563,0.9936439990997314,0.05394692 +36000.0,0.7,10.0,966.7807835059835,0.00041850065463222563,1.209653615951538,0.0724242 +36000.0,0.75,-2.0,966.7807835059835,0.00041850065463222563,-0.08962029218673706,0.01603487 +36000.0,0.75,0.0,966.7807835059835,0.00041850065463222563,0.13443045318126678,0.01642051 +36000.0,0.75,2.0,966.7807835059835,0.00041850065463222563,0.35848119854927063,0.02066218 +36000.0,0.75,4.0,966.7807835059835,0.00041850065463222563,0.5825319290161133,0.02876119 +36000.0,0.75,6.0,966.7807835059835,0.00041850065463222563,0.8065826296806335,0.04085377 +36000.0,0.75,8.0,966.7807835059835,0.00041850065463222563,1.0306333303451538,0.05795208 +36000.0,0.75,10.0,966.7807835059835,0.00041850065463222563,1.2546840906143188,0.08140018 +36000.0,0.8,-2.0,966.7807835059835,0.00041850065463222563,-0.09355007857084274,0.01586641 +36000.0,0.8,0.0,966.7807835059835,0.00041850065463222563,0.1403251439332962,0.01628471 +36000.0,0.8,2.0,966.7807835059835,0.00041850065463222563,0.37420034408569336,0.02097082 +36000.0,0.8,4.0,966.7807835059835,0.00041850065463222563,0.6080754995346069,0.03087825 +36000.0,0.8,6.0,966.7807835059835,0.00041850065463222563,0.8419507741928101,0.04752731 +36000.0,0.8,8.0,966.7807835059835,0.00041850065463222563,1.0758259296417236,0.07245231 +36000.0,0.8,10.0,966.7807835059835,0.00041850065463222563,1.3097012042999268,0.10718637 +36000.0,0.850,-2.0,966.7807835059835,0.00041850065463222563,-0.09845549613237381,0.0157217 +36000.0,0.850,0.0,966.7807835059835,0.00041850065463222563,0.1476832628250122,0.01686628 +36000.0,0.850,2.0,966.7807835059835,0.00041850065463222563,0.3938220143318176,0.02500881 +36000.0,0.850,4.0,966.7807835059835,0.00041850065463222563,0.6399607062339783,0.041937 +36000.0,0.850,6.0,966.7807835059835,0.00041850065463222563,0.8860995173454285,0.0694381 +36000.0,0.850,8.0,966.7807835059835,0.00041850065463222563,1.1322382688522339,0.1092992 +36000.0,0.850,10.0,966.7807835059835,0.00041850065463222563,1.378377079963684,0.16330738 +36000.0,0.900,-2.0,966.7807835059835,0.00041850065463222563,-0.10476978868246078,0.0176548 +36000.0,0.900,0.0,966.7807835059835,0.00041850065463222563,0.15715469419956207,0.02394218 +36000.0,0.900,2.0,966.7807835059835,0.00041850065463222563,0.4190791845321655,0.0414875 +36000.0,0.900,4.0,966.7807835059835,0.00041850065463222563,0.6810036897659302,0.07244422 +36000.0,0.900,6.0,966.7807835059835,0.00041850065463222563,0.9429281949996948,0.11896576 +36000.0,0.900,8.0,966.7807835059835,0.00041850065463222563,1.2048527002334595,0.18320557 +36000.0,0.900,10.0,966.7807835059835,0.00041850065463222563,1.4667772054672241,0.26731707 +38000.0,0.7,-2.0,966.0199501498222,0.0004593963676597923,-0.08640382438898087,0.01638908 +38000.0,0.7,0.0,966.0199501498222,0.0004593963676597923,0.1296057403087616,0.01674907 +38000.0,0.7,2.0,966.0199501498222,0.0004593963676597923,0.34561532735824585,0.02070897 +38000.0,0.7,4.0,966.0199501498222,0.0004593963676597923,0.5616248846054077,0.02826876 +38000.0,0.7,6.0,966.0199501498222,0.0004593963676597923,0.7776344418525696,0.0394278 +38000.0,0.7,8.0,966.0199501498222,0.0004593963676597923,0.9936439990997314,0.05418806 +38000.0,0.7,10.0,966.0199501498222,0.0004593963676597923,1.209653615951538,0.0726984 +38000.0,0.75,-2.0,966.0199501498222,0.0004593963676597923,-0.08962029218673706,0.0162045 +38000.0,0.75,0.0,966.0199501498222,0.0004593963676597923,0.13443045318126678,0.01659083 +38000.0,0.75,2.0,966.0199501498222,0.0004593963676597923,0.35848119854927063,0.02084002 +38000.0,0.75,4.0,966.0199501498222,0.0004593963676597923,0.5825319290161133,0.02895338 +38000.0,0.75,6.0,966.0199501498222,0.0004593963676597923,0.8065826296806335,0.04106714 +38000.0,0.75,8.0,966.0199501498222,0.0004593963676597923,1.0306333303451538,0.05819347 +38000.0,0.75,10.0,966.0199501498222,0.0004593963676597923,1.2546840906143188,0.08167642 +38000.0,0.8,-2.0,966.0199501498222,0.0004593963676597923,-0.09355007857084274,0.01603278 +38000.0,0.8,0.0,966.0199501498222,0.0004593963676597923,0.1403251439332962,0.01645181 +38000.0,0.8,2.0,966.0199501498222,0.0004593963676597923,0.37420034408569336,0.02114595 +38000.0,0.8,4.0,966.0199501498222,0.0004593963676597923,0.6080754995346069,0.03106872 +38000.0,0.8,6.0,966.0199501498222,0.0004593963676597923,0.8419507741928101,0.04774041 +38000.0,0.8,8.0,966.0199501498222,0.0004593963676597923,1.0758259296417236,0.07269534 +38000.0,0.8,10.0,966.0199501498222,0.0004593963676597923,1.3097012042999268,0.10746663 +38000.0,0.850,-2.0,966.0199501498222,0.0004593963676597923,-0.09845549613237381,0.01588497 +38000.0,0.850,0.0,966.0199501498222,0.0004593963676597923,0.1476832628250122,0.01703034 +38000.0,0.850,2.0,966.0199501498222,0.0004593963676597923,0.3938220143318176,0.0251816 +38000.0,0.850,4.0,966.0199501498222,0.0004593963676597923,0.6399607062339783,0.04212644 +38000.0,0.850,6.0,966.0199501498222,0.0004593963676597923,0.8860995173454285,0.06965213 +38000.0,0.850,8.0,966.0199501498222,0.0004593963676597923,1.1322382688522339,0.10954575 +38000.0,0.850,10.0,966.0199501498222,0.0004593963676597923,1.378377079963684,0.16359438 +38000.0,0.900,-2.0,966.0199501498222,0.0004593963676597923,-0.10476978868246078,0.01781511 +38000.0,0.900,0.0,966.0199501498222,0.0004593963676597923,0.15715469419956207,0.02410337 +38000.0,0.900,2.0,966.0199501498222,0.0004593963676597923,0.4190791845321655,0.04165838 +38000.0,0.900,4.0,966.0199501498222,0.0004593963676597923,0.6810036897659302,0.07263361 +38000.0,0.900,6.0,966.0199501498222,0.0004593963676597923,0.9429281949996948,0.11918247 +38000.0,0.900,8.0,966.0199501498222,0.0004593963676597923,1.2048527002334595,0.18345841 +38000.0,0.900,10.0,966.0199501498222,0.0004593963676597923,1.4667772054672241,0.26761487 diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_ground.csv b/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_ground.csv index 0efcbb06a0..4dfa95f2ec 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_ground.csv +++ b/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_ground.csv @@ -1,701 +1,701 @@ ilift,alt,mach,alpha,sos,nu,cl,cd -2.0,0.0,0.1,-2.0,1116.1121663638341,0.0001572293695062399,0.3581817150115967,0.05789843946695328 -2.0,0.0,0.1,0.0,1116.1121663638341,0.0001572293695062399,0.562721848487854,0.06019424647092819 -2.0,0.0,0.1,2.0,1116.1121663638341,0.0001572293695062399,0.7605313658714294,0.0637364387512207 -2.0,0.0,0.1,4.0,1116.1121663638341,0.0001572293695062399,0.9516102075576782,0.06839878857135773 -2.0,0.0,0.1,6.0,1116.1121663638341,0.0001572293695062399,1.1359585523605347,0.07405830174684525 -2.0,0.0,0.1,8.0,1116.1121663638341,0.0001572293695062399,1.313576340675354,0.08059531450271606 -2.0,0.0,0.1,10.0,1116.1121663638341,0.0001572293695062399,1.4844634532928467,0.08789363503456116 -2.0,0.0,0.15000000000000002,-2.0,1116.1121663638341,0.0001572293695062399,0.35768309235572815,0.05690142884850502 -2.0,0.0,0.15000000000000002,0.0,1116.1121663638341,0.0001572293695062399,0.5630722641944885,0.05918383598327637 -2.0,0.0,0.15000000000000002,2.0,1116.1121663638341,0.0001572293695062399,0.7616750001907349,0.06271030753850937 -2.0,0.0,0.15000000000000002,4.0,1116.1121663638341,0.0001572293695062399,0.9534913301467896,0.06735431402921677 -2.0,0.0,0.15000000000000002,6.0,1116.1121663638341,0.0001572293695062399,1.1385213136672974,0.07299257814884186 -2.0,0.0,0.15000000000000002,8.0,1116.1121663638341,0.0001572293695062399,1.3167647123336792,0.07950522005558014 -2.0,0.0,0.15000000000000002,10.0,1116.1121663638341,0.0001572293695062399,1.4882217645645142,0.0867757499217987 -2.0,0.0,0.20000000000000004,-2.0,1116.1121663638341,0.0001572293695062399,0.3569739758968353,0.056228574365377426 -2.0,0.0,0.20000000000000004,0.0,1116.1121663638341,0.0001572293695062399,0.5635710954666138,0.05850842222571373 -2.0,0.0,0.20000000000000004,2.0,1116.1121663638341,0.0001572293695062399,0.7633019685745239,0.06203813850879669 -2.0,0.0,0.20000000000000004,4.0,1116.1121663638341,0.0001572293695062399,0.9561665654182434,0.06668983399868011 -2.0,0.0,0.20000000000000004,6.0,1116.1121663638341,0.0001572293695062399,1.142164945602417,0.07233896851539612 -2.0,0.0,0.20000000000000004,8.0,1116.1121663638341,0.0001572293695062399,1.3212971687316895,0.07886436581611633 -2.0,0.0,0.20000000000000004,10.0,1116.1121663638341,0.0001572293695062399,1.493563175201416,0.08614842593669891 -2.0,0.0,0.25000000000000006,-2.0,1116.1121663638341,0.0001572293695062399,0.356042742729187,0.055718544870615005 -2.0,0.0,0.25000000000000006,0.0,1116.1121663638341,0.0001572293695062399,0.5642269849777222,0.058003269135951996 -2.0,0.0,0.25000000000000006,2.0,1116.1121663638341,0.0001572293695062399,0.7654394507408142,0.0615500882267952 -2.0,0.0,0.25000000000000006,4.0,1116.1121663638341,0.0001572293695062399,0.9596801400184631,0.06622885167598724 -2.0,0.0,0.25000000000000006,6.0,1116.1121663638341,0.0001572293695062399,1.146949052810669,0.07191283255815506 -2.0,0.0,0.25000000000000006,8.0,1116.1121663638341,0.0001572293695062399,1.3272463083267212,0.07847882807254791 -2.0,0.0,0.25000000000000006,10.0,1116.1121663638341,0.0001572293695062399,1.5005717277526855,0.08580717444419861 -2.0,0.0,0.30000000000000004,-2.0,1116.1121663638341,0.0001572293695062399,0.35487350821495056,0.0553039126098156 -2.0,0.0,0.30000000000000004,0.0,1116.1121663638341,0.0001572293695062399,0.5650518536567688,0.05759969353675842 -2.0,0.0,0.30000000000000004,2.0,1116.1121663638341,0.0001572293695062399,0.7681247591972351,0.06117578595876694 -2.0,0.0,0.30000000000000004,4.0,1116.1121663638341,0.0001572293695062399,0.9640921354293823,0.06589888036251068 -2.0,0.0,0.30000000000000004,6.0,1116.1121663638341,0.0001572293695062399,1.152953863143921,0.07163920998573303 -2.0,0.0,0.30000000000000004,8.0,1116.1121663638341,0.0001572293695062399,1.3347102403640747,0.07827061414718628 -2.0,0.0,0.30000000000000004,10.0,1116.1121663638341,0.0001572293695062399,1.5093611478805542,0.08567069470882416 -2.0,10.0,0.1,-2.0,1116.0732851388082,0.00015726701531093568,0.3632766604423523,0.05848124623298645 -2.0,10.0,0.1,0.0,1116.0732851388082,0.00015726701531093568,0.5563383102416992,0.06182507798075676 -2.0,10.0,0.1,2.0,1116.0732851388082,0.00015726701531093568,0.7468655109405518,0.06698928028345108 -2.0,10.0,0.1,4.0,1116.0732851388082,0.00015726701531093568,0.9348582625389099,0.07390335947275162 -2.0,10.0,0.1,6.0,1116.0732851388082,0.00015726701531093568,1.1203168630599976,0.08249758929014206 -2.0,10.0,0.1,8.0,1116.0732851388082,0.00015726701531093568,1.3032410144805908,0.09270289540290833 -2.0,10.0,0.1,10.0,1116.0732851388082,0.00015726701531093568,1.4836307764053345,0.10445099323987961 -2.0,10.0,0.15000000000000002,-2.0,1116.0732851388082,0.00015726701531093568,0.36281341314315796,0.05747619643807411 -2.0,10.0,0.15000000000000002,0.0,1116.0732851388082,0.00015726701531093568,0.5566461086273193,0.06079954653978348 -2.0,10.0,0.15000000000000002,2.0,1116.0732851388082,0.00015726701531093568,0.7479233741760254,0.0659395158290863 -2.0,10.0,0.15000000000000002,4.0,1116.0732851388082,0.00015726701531093568,0.9366453289985657,0.07282548397779465 -2.0,10.0,0.15000000000000002,6.0,1116.0732851388082,0.00015726701531093568,1.1228117942810059,0.08138751238584518 -2.0,10.0,0.15000000000000002,8.0,1116.0732851388082,0.00015726701531093568,1.3064229488372803,0.09155642986297607 -2.0,10.0,0.15000000000000002,10.0,1116.0732851388082,0.00015726701531093568,1.4874788522720337,0.10326379537582397 -2.0,10.0,0.20000000000000004,-2.0,1116.0732851388082,0.00015726701531093568,0.3621547818183899,0.0567966029047966 -2.0,10.0,0.20000000000000004,0.0,1116.0732851388082,0.00015726701531093568,0.5570840835571289,0.06011515483260155 -2.0,10.0,0.20000000000000004,2.0,1116.0732851388082,0.00015726701531093568,0.7494280338287354,0.06525830924510956 -2.0,10.0,0.20000000000000004,4.0,1116.0732851388082,0.00015726701531093568,0.9391863942146301,0.07215465605258942 -2.0,10.0,0.20000000000000004,6.0,1116.0732851388082,0.00015726701531093568,1.1263593435287476,0.08073356747627258 -2.0,10.0,0.20000000000000004,8.0,1116.0732851388082,0.00015726701531093568,1.310947060585022,0.09092512726783752 -2.0,10.0,0.20000000000000004,10.0,1116.0732851388082,0.00015726701531093568,1.49294912815094,0.102660171687603 -2.0,10.0,0.25000000000000006,-2.0,1116.0732851388082,0.00015726701531093568,0.36129024624824524,0.05628006532788277 -2.0,10.0,0.25000000000000006,0.0,1116.0732851388082,0.00015726701531093568,0.5576596856117249,0.0596044696867466 -2.0,10.0,0.25000000000000006,2.0,1116.0732851388082,0.00015726701531093568,0.7514040470123291,0.06477063149213791 -2.0,10.0,0.25000000000000006,4.0,1116.0732851388082,0.00015726701531093568,0.9425231218338013,0.0717059075832367 -2.0,10.0,0.25000000000000006,6.0,1116.0732851388082,0.00015726701531093568,1.1310169696807861,0.08033842593431473 -2.0,10.0,0.25000000000000006,8.0,1116.0732851388082,0.00015726701531093568,1.3168858289718628,0.09059707820415497 -2.0,10.0,0.25000000000000006,10.0,1116.0732851388082,0.00015726701531093568,1.5001293420791626,0.10241147875785828 -2.0,10.0,0.30000000000000004,-2.0,1116.0732851388082,0.00015726701531093568,0.36020535230636597,0.05585872009396553 -2.0,10.0,0.30000000000000004,0.0,1116.0732851388082,0.00015726701531093568,0.558383047580719,0.05919772759079933 -2.0,10.0,0.30000000000000004,2.0,1116.0732851388082,0.00015726701531093568,0.7538852095603943,0.0644042119383812 -2.0,10.0,0.30000000000000004,4.0,1116.0732851388082,0.00015726701531093568,0.9467118382453918,0.07140377163887024 -2.0,10.0,0.30000000000000004,6.0,1116.0732851388082,0.00015726701531093568,1.1368629932403564,0.08012281358242035 -2.0,10.0,0.30000000000000004,8.0,1116.0732851388082,0.00015726701531093568,1.3243385553359985,0.09048852324485779 -2.0,10.0,0.30000000000000004,10.0,1116.0732851388082,0.00015726701531093568,1.5091384649276733,0.10242883861064911 -2.0,20.0,0.1,-2.0,1116.0343369575487,0.000157304632011801,0.3652701675891876,0.0588136725127697 -2.0,20.0,0.1,0.0,1116.0343369575487,0.000157304632011801,0.5536910891532898,0.06271958351135254 -2.0,20.0,0.1,2.0,1116.0343369575487,0.000157304632011801,0.7407213449478149,0.06873922049999237 -2.0,20.0,0.1,4.0,1116.0343369575487,0.000157304632011801,0.9263609051704407,0.07682708650827408 -2.0,20.0,0.1,6.0,1116.0343369575487,0.000157304632011801,1.110609769821167,0.08693799376487732 -2.0,20.0,0.1,8.0,1116.0343369575487,0.000157304632011801,1.2934679985046387,0.09902697801589966 -2.0,20.0,0.1,10.0,1116.0343369575487,0.000157304632011801,1.4749356508255005,0.11304935812950134 -2.0,20.0,0.15000000000000002,-2.0,1116.0343369575487,0.000157304632011801,0.3648169934749603,0.05780414119362831 -2.0,20.0,0.15000000000000002,0.0,1116.0343369575487,0.000157304632011801,0.553986668586731,0.0616859495639801 -2.0,20.0,0.15000000000000002,2.0,1116.0343369575487,0.000157304632011801,0.7417541146278381,0.06767712533473969 -2.0,20.0,0.15000000000000002,4.0,1116.0343369575487,0.000157304632011801,0.9281193017959595,0.07573209702968597 -2.0,20.0,0.15000000000000002,6.0,1116.0343369575487,0.000157304632011801,1.1130824089050293,0.08580554276704788 -2.0,20.0,0.15000000000000002,8.0,1116.0343369575487,0.000157304632011801,1.2966432571411133,0.09785241633653641 -2.0,20.0,0.15000000000000002,10.0,1116.0343369575487,0.000157304632011801,1.4788018465042114,0.11182792484760284 -2.0,20.0,0.20000000000000004,-2.0,1116.0343369575487,0.000157304632011801,0.3641727566719055,0.057120759040117264 -2.0,20.0,0.20000000000000004,0.0,1116.0343369575487,0.000157304632011801,0.5544072389602661,0.060996782034635544 -2.0,20.0,0.20000000000000004,2.0,1116.0343369575487,0.000157304632011801,0.7432229518890381,0.0669914186000824 -2.0,20.0,0.20000000000000004,4.0,1116.0343369575487,0.000157304632011801,0.9306199550628662,0.07505859434604645 -2.0,20.0,0.20000000000000004,6.0,1116.0343369575487,0.000157304632011801,1.1165982484817505,0.0851525291800499 -2.0,20.0,0.20000000000000004,8.0,1116.0343369575487,0.000157304632011801,1.3011579513549805,0.09722770005464554 -2.0,20.0,0.20000000000000004,10.0,1116.0343369575487,0.000157304632011801,1.484298825263977,0.11123885214328766 -2.0,20.0,0.25000000000000006,-2.0,1116.0343369575487,0.000157304632011801,0.36332714557647705,0.056600574404001236 -2.0,20.0,0.25000000000000006,0.0,1116.0343369575487,0.000157304632011801,0.554959774017334,0.060483209788799286 -2.0,20.0,0.25000000000000006,2.0,1116.0343369575487,0.000157304632011801,0.745151937007904,0.06650437414646149 -2.0,20.0,0.25000000000000006,4.0,1116.0343369575487,0.000157304632011801,0.9339036345481873,0.07461719959974289 -2.0,20.0,0.25000000000000006,6.0,1116.0343369575487,0.000157304632011801,1.1212148666381836,0.08477510511875153 -2.0,20.0,0.25000000000000006,8.0,1116.0343369575487,0.000157304632011801,1.307085394859314,0.09693174809217453 -2.0,20.0,0.25000000000000006,10.0,1116.0343369575487,0.000157304632011801,1.4915155172348022,0.1110411137342453 -2.0,20.0,0.30000000000000004,-2.0,1116.0343369575487,0.000157304632011801,0.36226609349250793,0.05617543309926987 -2.0,20.0,0.30000000000000004,0.0,1116.0343369575487,0.000157304632011801,0.5556542277336121,0.06007488816976547 -2.0,20.0,0.30000000000000004,2.0,1116.0343369575487,0.000157304632011801,0.7475741505622864,0.06614270061254501 -2.0,20.0,0.30000000000000004,4.0,1116.0343369575487,0.000157304632011801,0.938025951385498,0.0743308886885643 -2.0,20.0,0.30000000000000004,6.0,1116.0343369575487,0.000157304632011801,1.127009630203247,0.08459173142910004 -2.0,20.0,0.30000000000000004,8.0,1116.0343369575487,0.000157304632011801,1.3145252466201782,0.096877820789814 -2.0,20.0,0.30000000000000004,10.0,1116.0343369575487,0.000157304632011801,1.500572681427002,0.11114200204610825 -2.0,30.0,0.1,-2.0,1115.9954531665346,0.0001573422778164968,0.36645734310150146,0.05902458727359772 -2.0,30.0,0.1,0.0,1115.9954531665346,0.0001573422778164968,0.5520625710487366,0.063264861702919 -2.0,30.0,0.1,2.0,1115.9954531665346,0.0001573422778164968,0.7367844581604004,0.0697852075099945 -2.0,30.0,0.1,4.0,1115.9954531665346,0.0001573422778164968,0.9206229448318481,0.07855414599180222 -2.0,30.0,0.1,6.0,1115.9954531665346,0.0001573422778164968,1.103577971458435,0.08954031765460968 -2.0,30.0,0.1,8.0,1115.9954531665346,0.0001573422778164968,1.2856497764587402,0.10271250456571579 -2.0,30.0,0.1,10.0,1115.9954531665346,0.0001573422778164968,1.466838002204895,0.11803954839706421 -2.0,30.0,0.15000000000000002,-2.0,1115.9954531665346,0.0001573422778164968,0.36600953340530396,0.058012232184410095 -2.0,30.0,0.15000000000000002,0.0,1115.9954531665346,0.0001573422778164968,0.5523512959480286,0.06222626939415932 -2.0,30.0,0.15000000000000002,2.0,1115.9954531665346,0.0001573422778164968,0.7378023266792297,0.06871569901704788 -2.0,30.0,0.15000000000000002,4.0,1115.9954531665346,0.0001573422778164968,0.9223626852035522,0.07744897902011871 -2.0,30.0,0.15000000000000002,6.0,1115.9954531665346,0.0001573422778164968,1.1060322523117065,0.0883946642279625 -2.0,30.0,0.15000000000000002,8.0,1115.9954531665346,0.0001573422778164968,1.288811206817627,0.10152146965265274 -2.0,30.0,0.15000000000000002,10.0,1115.9954531665346,0.0001573422778164968,1.470699667930603,0.11679821461439133 -2.0,30.0,0.20000000000000004,-2.0,1115.9954531665346,0.0001573422778164968,0.36537298560142517,0.05732647702097893 -2.0,30.0,0.20000000000000004,0.0,1115.9954531665346,0.0001573422778164968,0.5527620911598206,0.06153416261076927 -2.0,30.0,0.20000000000000004,2.0,1115.9954531665346,0.0001573422778164968,0.7392500042915344,0.06802722811698914 -2.0,30.0,0.20000000000000004,4.0,1115.9954531665346,0.0001573422778164968,0.9248367547988892,0.07677378505468369 -2.0,30.0,0.20000000000000004,6.0,1115.9954531665346,0.0001573422778164968,1.1095224618911743,0.08774209767580032 -2.0,30.0,0.20000000000000004,8.0,1115.9954531665346,0.0001573422778164968,1.293306827545166,0.10090048611164093 -2.0,30.0,0.20000000000000004,10.0,1115.9954531665346,0.0001573422778164968,1.4761899709701538,0.1162174716591835 -2.0,30.0,0.25000000000000006,-2.0,1115.9954531665346,0.0001573422778164968,0.36453744769096375,0.056804001331329346 -2.0,30.0,0.25000000000000006,0.0,1115.9954531665346,0.0001573422778164968,0.5533019304275513,0.06101879104971886 -2.0,30.0,0.25000000000000006,2.0,1115.9954531665346,0.0001573422778164968,0.7411513924598694,0.0675404742360115 -2.0,30.0,0.25000000000000006,4.0,1115.9954531665346,0.0001573422778164968,0.9280857443809509,0.07633659988641739 -2.0,30.0,0.25000000000000006,6.0,1115.9954531665346,0.0001573422778164968,1.114104986190796,0.08737485855817795 -2.0,30.0,0.25000000000000006,8.0,1115.9954531665346,0.0001573422778164968,1.2992093563079834,0.10062307864427567 -2.0,30.0,0.25000000000000006,10.0,1115.9954531665346,0.0001573422778164968,1.483398675918579,0.11604917794466019 -2.0,30.0,0.30000000000000004,-2.0,1115.9954531665346,0.0001573422778164968,0.36348915100097656,0.05637649446725845 -2.0,30.0,0.30000000000000004,0.0,1115.9954531665346,0.0001573422778164968,0.5539802312850952,0.06060944125056267 -2.0,30.0,0.30000000000000004,2.0,1115.9954531665346,0.0001573422778164968,0.7435387372970581,0.06718150526285172 -2.0,30.0,0.30000000000000004,4.0,1115.9954531665346,0.0001573422778164968,0.9321646690368652,0.07605945318937302 -2.0,30.0,0.30000000000000004,6.0,1115.9954531665346,0.0001573422778164968,1.1198580265045166,0.08721020072698593 -2.0,30.0,0.30000000000000004,8.0,1115.9954531665346,0.0001573422778164968,1.3066188097000122,0.10060079395771027 -2.0,30.0,0.30000000000000004,10.0,1115.9954531665346,0.0001573422778164968,1.4924468994140625,0.11619836091995239 -2.0,40.0,0.1,-2.0,1115.9565680934381,0.00015737992362119257,0.36722856760025024,0.059164829552173615 -2.0,40.0,0.1,0.0,1115.9565680934381,0.00015737992362119257,0.5509878993034363,0.0636172741651535 -2.0,40.0,0.1,2.0,1115.9565680934381,0.00015737992362119257,0.7341377139091492,0.07045173645019531 -2.0,40.0,0.1,4.0,1115.9565680934381,0.00015737992362119257,0.9166780710220337,0.07964534312486649 -2.0,40.0,0.1,6.0,1115.9565680934381,0.00015737992362119257,1.0986088514328003,0.09117528796195984 -2.0,40.0,0.1,8.0,1115.9565680934381,0.00015737992362119257,1.2799302339553833,0.10501886904239655 -2.0,40.0,0.1,10.0,1115.9565680934381,0.00015737992362119257,1.4606419801712036,0.12115338444709778 -2.0,40.0,0.15000000000000002,-2.0,1115.9565680934381,0.00015737992362119257,0.36678412556648254,0.05815059691667557 -2.0,40.0,0.15000000000000002,0.0,1115.9565680934381,0.00015737992362119257,0.5512722730636597,0.06257546693086624 -2.0,40.0,0.15000000000000002,2.0,1115.9565680934381,0.00015737992362119257,0.7351458072662354,0.06937745958566666 -2.0,40.0,0.15000000000000002,4.0,1115.9565680934381,0.00015737992362119257,0.9184048175811768,0.07853367179632187 -2.0,40.0,0.15000000000000002,6.0,1115.9565680934381,0.00015737992362119257,1.1010491847991943,0.09002125263214111 -2.0,40.0,0.15000000000000002,8.0,1115.9565680934381,0.00015737992362119257,1.2830791473388672,0.10381743311882019 -2.0,40.0,0.15000000000000002,10.0,1115.9565680934381,0.00015737992362119257,1.4644944667816162,0.11989946663379669 -2.0,40.0,0.20000000000000004,-2.0,1115.9565680934381,0.00015737992362119257,0.3661523163318634,0.05746326595544815 -2.0,40.0,0.20000000000000004,0.0,1115.9565680934381,0.00015737992362119257,0.551676869392395,0.06188143789768219 -2.0,40.0,0.20000000000000004,2.0,1115.9565680934381,0.00015737992362119257,0.7365795969963074,0.06868717074394226 -2.0,40.0,0.20000000000000004,4.0,1115.9565680934381,0.00015737992362119257,0.9208605289459229,0.07785733789205551 -2.0,40.0,0.20000000000000004,6.0,1115.9565680934381,0.00015737992362119257,1.1045197248458862,0.08936884254217148 -2.0,40.0,0.20000000000000004,8.0,1115.9565680934381,0.00015737992362119257,1.2875570058822632,0.10319864749908447 -2.0,40.0,0.20000000000000004,10.0,1115.9565680934381,0.00015737992362119257,1.4699726104736328,0.11932381987571716 -2.0,40.0,0.25000000000000006,-2.0,1115.9565680934381,0.00015737992362119257,0.36532312631607056,0.05693928524851799 -2.0,40.0,0.25000000000000006,0.0,1115.9565680934381,0.00015737992362119257,0.5522085428237915,0.06136486679315567 -2.0,40.0,0.25000000000000006,2.0,1115.9565680934381,0.00015737992362119257,0.7384626269340515,0.06820052117109299 -2.0,40.0,0.25000000000000006,4.0,1115.9565680934381,0.00015737992362119257,0.9240853786468506,0.07742268592119217 -2.0,40.0,0.25000000000000006,6.0,1115.9565680934381,0.00015737992362119257,1.1090768575668335,0.0890078991651535 -2.0,40.0,0.25000000000000006,8.0,1115.9565680934381,0.00015737992362119257,1.2934367656707764,0.10293268412351608 -2.0,40.0,0.25000000000000006,10.0,1115.9565680934381,0.00015737992362119257,1.4771655797958374,0.11917373538017273 -2.0,40.0,0.30000000000000004,-2.0,1115.9565680934381,0.00015737992362119257,0.3642826974391937,0.05651022121310234 -2.0,40.0,0.30000000000000004,0.0,1115.9565680934381,0.00015737992362119257,0.5528766512870789,0.06095482036471367 -2.0,40.0,0.30000000000000004,2.0,1115.9565680934381,0.00015737992362119257,0.7408271431922913,0.06784318387508392 -2.0,40.0,0.30000000000000004,4.0,1115.9565680934381,0.00015737992362119257,0.9281341433525085,0.07715119421482086 -2.0,40.0,0.30000000000000004,6.0,1115.9565680934381,0.00015737992362119257,1.1147977113723755,0.08885478973388672 -2.0,40.0,0.30000000000000004,8.0,1115.9565680934381,0.00015737992362119257,1.300817847251892,0.1029299721121788 -2.0,40.0,0.30000000000000004,10.0,1115.9565680934381,0.00015737992362119257,1.4861946105957031,0.11935283243656158 -2.0,50.0,0.1,-2.0,1115.917615583849,0.00015741751121822745,0.3677496612071991,0.059260882437229156 -2.0,50.0,0.1,0.0,1115.917615583849,0.00015741751121822745,0.5502557754516602,0.06385385990142822 -2.0,50.0,0.1,2.0,1115.917615583849,0.00015741751121822745,0.7323175072669983,0.0708947405219078 -2.0,50.0,0.1,4.0,1115.917615583849,0.00015741751121822745,0.9139347076416016,0.08036628365516663 -2.0,50.0,0.1,6.0,1115.917615583849,0.00015741751121822745,1.0951075553894043,0.09225133061408997 -2.0,50.0,0.1,8.0,1115.917615583849,0.00015741751121822745,1.2758357524871826,0.10653271526098251 -2.0,50.0,0.1,10.0,1115.917615583849,0.00015741751121822745,1.4561196565628052,0.12319332361221313 -2.0,50.0,0.15000000000000002,-2.0,1115.917615583849,0.00015741751121822745,0.3673074245452881,0.058245353400707245 -2.0,50.0,0.15000000000000002,0.0,1115.917615583849,0.00015741751121822745,0.5505372285842896,0.06280986219644547 -2.0,50.0,0.15000000000000002,2.0,1115.917615583849,0.00015741751121822745,0.7333188652992249,0.06981725990772247 -2.0,50.0,0.15000000000000002,4.0,1115.917615583849,0.00015741751121822745,0.9156523942947388,0.07925029844045639 -2.0,50.0,0.15000000000000002,6.0,1115.917615583849,0.00015741751121822745,1.0975377559661865,0.09109173715114594 -2.0,50.0,0.15000000000000002,8.0,1115.917615583849,0.00015741751121822745,1.278975009918213,0.1053244024515152 -2.0,50.0,0.15000000000000002,10.0,1115.917615583849,0.00015741751121822745,1.4599641561508179,0.12193113565444946 -2.0,50.0,0.20000000000000004,-2.0,1115.917615583849,0.00015741751121822745,0.36667880415916443,0.05755694583058357 -2.0,50.0,0.20000000000000004,0.0,1115.917615583849,0.00015741751121822745,0.5509377121925354,0.06211452558636665 -2.0,50.0,0.20000000000000004,2.0,1115.917615583849,0.00015741751121822745,0.7347431182861328,0.06912573426961899 -2.0,50.0,0.20000000000000004,4.0,1115.917615583849,0.00015741751121822745,0.9180951714515686,0.07857315242290497 -2.0,50.0,0.20000000000000004,6.0,1115.917615583849,0.00015741751121822745,1.1009937524795532,0.09043935686349869 -2.0,50.0,0.20000000000000004,8.0,1115.917615583849,0.00015741751121822745,1.283439040184021,0.10470698773860931 -2.0,50.0,0.20000000000000004,10.0,1115.917615583849,0.00015741751121822745,1.465430736541748,0.12135870009660721 -2.0,50.0,0.25000000000000006,-2.0,1115.917615583849,0.00015741751121822745,0.3658537268638611,0.05703192949295044 -2.0,50.0,0.25000000000000006,0.0,1115.917615583849,0.00015741751121822745,0.5514639019966125,0.061597127467393875 -2.0,50.0,0.25000000000000006,2.0,1115.917615583849,0.00015741751121822745,0.7366137504577637,0.0686391070485115 -2.0,50.0,0.25000000000000006,4.0,1115.917615583849,0.00015741751121822745,0.9213030338287354,0.07814011722803116 -2.0,50.0,0.25000000000000006,6.0,1115.917615583849,0.00015741751121822745,1.105532169342041,0.09008245170116425 -2.0,50.0,0.25000000000000006,8.0,1115.917615583849,0.00015741751121822745,1.2893006801605225,0.10444843024015427 -2.0,50.0,0.25000000000000006,10.0,1115.917615583849,0.00015741751121822745,1.472609043121338,0.1212204322218895 -2.0,50.0,0.30000000000000004,-2.0,1115.917615583849,0.00015741751121822745,0.3648185431957245,0.05660180747509003 -2.0,50.0,0.30000000000000004,0.0,1115.917615583849,0.00015741751121822745,0.5521251559257507,0.06118660047650337 -2.0,50.0,0.30000000000000004,2.0,1115.917615583849,0.00015741751121822745,0.7389625310897827,0.06828282028436661 -2.0,50.0,0.30000000000000004,4.0,1115.917615583849,0.00015741751121822745,0.9253306984901428,0.07787228375673294 -2.0,50.0,0.30000000000000004,6.0,1115.917615583849,0.00015741751121822745,1.111229658126831,0.08993687480688095 -2.0,50.0,0.30000000000000004,8.0,1115.917615583849,0.00015741751121822745,1.2966594696044922,0.10445848852396011 -2.0,50.0,0.30000000000000004,10.0,1115.917615583849,0.00015741751121822745,1.481619954109192,0.1214190423488617 -2.0,60.0,0.1,-2.0,1115.878662265104,0.00015745522978249937,0.36811044812202454,0.0593281053006649 -2.0,60.0,0.1,0.0,1115.878662265104,0.00015745522978249937,0.5497466325759888,0.06401705741882324 -2.0,60.0,0.1,2.0,1115.878662265104,0.00015745522978249937,0.7310454249382019,0.07119818031787872 -2.0,60.0,0.1,4.0,1115.878662265104,0.00015745522978249937,0.9120066165924072,0.08085810393095016 -2.0,60.0,0.1,6.0,1115.878662265104,0.00015745522978249937,1.0926305055618286,0.09298350661993027 -2.0,60.0,0.1,8.0,1115.878662265104,0.00015745522978249937,1.2729169130325317,0.10756106674671173 -2.0,60.0,0.1,10.0,1115.878662265104,0.00015745522978249937,1.452865719795227,0.12457746267318726 -2.0,60.0,0.15000000000000002,-2.0,1115.878662265104,0.00015745522978249937,0.3676697611808777,0.05831165984272957 -2.0,60.0,0.15000000000000002,0.0,1115.878662265104,0.00015745522978249937,0.5500261187553406,0.06297153234481812 -2.0,60.0,0.15000000000000002,2.0,1115.878662265104,0.00015745522978249937,0.7320421934127808,0.0701184794306755 -2.0,60.0,0.15000000000000002,4.0,1115.878662265104,0.00015745522978249937,0.9137179851531982,0.07973911613225937 -2.0,60.0,0.15000000000000002,6.0,1115.878662265104,0.00015745522978249937,1.0950535535812378,0.09182008355855942 -2.0,60.0,0.15000000000000002,8.0,1115.878662265104,0.00015745522978249937,1.2760487794876099,0.10634800791740417 -2.0,60.0,0.15000000000000002,10.0,1115.878662265104,0.00015745522978249937,1.4567036628723145,0.12330956012010574 -2.0,60.0,0.20000000000000004,-2.0,1115.878662265104,0.00015745522978249937,0.36704331636428833,0.05762249231338501 -2.0,60.0,0.20000000000000004,0.0,1115.878662265104,0.00015745522978249937,0.5504236221313477,0.06227526813745499 -2.0,60.0,0.20000000000000004,2.0,1115.878662265104,0.00015745522978249937,0.7334598302841187,0.06942607462406158 -2.0,60.0,0.20000000000000004,4.0,1115.878662265104,0.00015745522978249937,0.9161515831947327,0.07906138896942139 -2.0,60.0,0.20000000000000004,6.0,1115.878662265104,0.00015745522978249937,1.0984991788864136,0.09116768091917038 -2.0,60.0,0.20000000000000004,8.0,1115.878662265104,0.00015745522978249937,1.2805025577545166,0.10573148727416992 -2.0,60.0,0.20000000000000004,10.0,1115.878662265104,0.00015745522978249937,1.4621615409851074,0.12273933738470078 -2.0,60.0,0.25000000000000006,-2.0,1115.878662265104,0.00015745522978249937,0.3662210702896118,0.057096753269433975 -2.0,60.0,0.25000000000000006,0.0,1115.878662265104,0.00015745522978249937,0.5509461760520935,0.061757296323776245 -2.0,60.0,0.25000000000000006,2.0,1115.878662265104,0.00015745522978249937,0.7353216409683228,0.0689394399523735 -2.0,60.0,0.25000000000000006,4.0,1115.878662265104,0.00015745522978249937,0.9193476438522339,0.07862942665815353 -2.0,60.0,0.25000000000000006,6.0,1115.878662265104,0.00015745522978249937,1.1030240058898926,0.09081350266933441 -2.0,60.0,0.25000000000000006,8.0,1115.878662265104,0.00015745522978249937,1.2863507270812988,0.10547792911529541 -2.0,60.0,0.25000000000000006,10.0,1115.878662265104,0.00015745522978249937,1.4693281650543213,0.12260904163122177 -2.0,60.0,0.30000000000000004,-2.0,1115.878662265104,0.00015745522978249937,0.36518946290016174,0.05666588991880417 -2.0,60.0,0.30000000000000004,0.0,1115.878662265104,0.00015745522978249937,0.5516027212142944,0.06134641915559769 -2.0,60.0,0.30000000000000004,2.0,1115.878662265104,0.00015745522978249937,0.7376596927642822,0.06858384609222412 -2.0,60.0,0.30000000000000004,4.0,1115.878662265104,0.00015745522978249937,0.923360288143158,0.0783640593290329 -2.0,60.0,0.30000000000000004,6.0,1115.878662265104,0.00015745522978249937,1.108704686164856,0.09067299962043762 -2.0,60.0,0.30000000000000004,8.0,1115.878662265104,0.00015745522978249937,1.293692946434021,0.1054966077208519 -2.0,60.0,0.30000000000000004,10.0,1115.878662265104,0.00015745522978249937,1.4783247709274292,0.12282081693410873 -2.0,70.0,0.1,-2.0,1115.839773344972,0.00015749289013911039,0.36836469173431396,0.059375979006290436 -2.0,70.0,0.1,0.0,1115.839773344972,0.00015749289013911039,0.5493872761726379,0.06413199007511139 -2.0,70.0,0.1,2.0,1115.839773344972,0.00015749289013911039,0.7301454544067383,0.07141080498695374 -2.0,70.0,0.1,4.0,1115.839773344972,0.00015749289013911039,0.9106392860412598,0.08120181411504745 -2.0,70.0,0.1,6.0,1115.839773344972,0.00015749289013911039,1.0908688306808472,0.09349440038204193 -2.0,70.0,0.1,8.0,1115.839773344972,0.00015749289013911039,1.270833969116211,0.10827796906232834 -2.0,70.0,0.1,10.0,1115.839773344972,0.00015749289013911039,1.4505345821380615,0.12554192543029785 -2.0,70.0,0.15000000000000002,-2.0,1115.839773344972,0.00015749289013911039,0.3679250478744507,0.05835886299610138 -2.0,70.0,0.15000000000000002,0.0,1115.839773344972,0.00015749289013911039,0.5496652722358704,0.06308536231517792 -2.0,70.0,0.15000000000000002,2.0,1115.839773344972,0.00015749289013911039,0.7311389446258545,0.07032952457666397 -2.0,70.0,0.15000000000000002,4.0,1115.839773344972,0.00015749289013911039,0.9123459458351135,0.08008070290088654 -2.0,70.0,0.15000000000000002,6.0,1115.839773344972,0.00015749289013911039,1.0932866334915161,0.092328280210495 -2.0,70.0,0.15000000000000002,8.0,1115.839773344972,0.00015749289013911039,1.2739604711532593,0.10706159472465515 -2.0,70.0,0.15000000000000002,10.0,1115.839773344972,0.00015749289013911039,1.454367995262146,0.12427008152008057 -2.0,70.0,0.20000000000000004,-2.0,1115.839773344972,0.00015749289013911039,0.3673001229763031,0.05766913667321205 -2.0,70.0,0.20000000000000004,0.0,1115.839773344972,0.00015749289013911039,0.5500608682632446,0.06238843873143196 -2.0,70.0,0.20000000000000004,2.0,1115.839773344972,0.00015749289013911039,0.7325518727302551,0.06963649392127991 -2.0,70.0,0.20000000000000004,4.0,1115.839773344972,0.00015749289013911039,0.9147732257843018,0.07940254360437393 -2.0,70.0,0.20000000000000004,6.0,1115.839773344972,0.00015749289013911039,1.0967248678207397,0.09167584031820297 -2.0,70.0,0.20000000000000004,8.0,1115.839773344972,0.00015749289013911039,1.2784067392349243,0.10644567012786865 -2.0,70.0,0.20000000000000004,10.0,1115.839773344972,0.00015749289013911039,1.4598191976547241,0.1237013041973114 -2.0,70.0,0.25000000000000006,-2.0,1115.839773344972,0.00015749289013911039,0.36647987365722656,0.05714287981390953 -2.0,70.0,0.25000000000000006,0.0,1115.839773344972,0.00015749289013911039,0.5505806803703308,0.06187005341053009 -2.0,70.0,0.25000000000000006,2.0,1115.839773344972,0.00015749289013911039,0.7344076633453369,0.06914984434843063 -2.0,70.0,0.25000000000000006,4.0,1115.839773344972,0.00015749289013911039,0.9179607033729553,0.07897131145000458 -2.0,70.0,0.25000000000000006,6.0,1115.839773344972,0.00015749289013911039,1.1012400388717651,0.09132353961467743 -2.0,70.0,0.25000000000000006,8.0,1115.839773344972,0.00015749289013911039,1.284245491027832,0.10619558393955231 -2.0,70.0,0.25000000000000006,10.0,1115.839773344972,0.00015749289013911039,1.4669772386550903,0.12357655167579651 -2.0,70.0,0.30000000000000004,-2.0,1115.839773344972,0.00015749289013911039,0.36545076966285706,0.05671149119734764 -2.0,70.0,0.30000000000000004,0.0,1115.839773344972,0.00015749289013911039,0.5512338876724243,0.06145891547203064 -2.0,70.0,0.30000000000000004,2.0,1115.839773344972,0.00015749289013911039,0.7367379665374756,0.06879471242427826 -2.0,70.0,0.30000000000000004,4.0,1115.839773344972,0.00015749289013911039,0.9219629168510437,0.07870765030384064 -2.0,70.0,0.30000000000000004,6.0,1115.839773344972,0.00015749289013911039,1.1069086790084839,0.09118654578924179 -2.0,70.0,0.30000000000000004,8.0,1115.839773344972,0.00015749289013911039,1.29157555103302,0.10622022300958633 -2.0,70.0,0.30000000000000004,10.0,1115.839773344972,0.00015749289013911039,1.4759632349014282,0.12379749119281769 -2.0,80.0,0.1,-2.0,1115.800883142221,0.0001575305504957214,0.3685462176799774,0.05941056087613106 -2.0,80.0,0.1,0.0,1115.800883142221,0.0001575305504957214,0.5491304993629456,0.06421428173780441 -2.0,80.0,0.1,2.0,1115.800883142221,0.0001575305504957214,0.7295024991035461,0.0715625211596489 -2.0,80.0,0.1,4.0,1115.800883142221,0.0001575305504957214,0.9096620678901672,0.08144664019346237 -2.0,80.0,0.1,6.0,1115.800883142221,0.0001575305504957214,1.0896092653274536,0.0938580334186554 -2.0,80.0,0.1,8.0,1115.800883142221,0.0001575305504957214,1.2693443298339844,0.10878811776638031 -2.0,80.0,0.1,10.0,1115.800883142221,0.0001575305504957214,1.4488669633865356,0.12622827291488647 -2.0,80.0,0.15000000000000002,-2.0,1115.800883142221,0.0001575305504957214,0.3681073784828186,0.058392949402332306 -2.0,80.0,0.15000000000000002,0.0,1115.800883142221,0.0001575305504957214,0.5494075417518616,0.06316685676574707 -2.0,80.0,0.15000000000000002,2.0,1115.800883142221,0.0001575305504957214,0.7304936051368713,0.0704800933599472 -2.0,80.0,0.15000000000000002,4.0,1115.800883142221,0.0001575305504957214,0.9113655686378479,0.08032400161027908 -2.0,80.0,0.15000000000000002,6.0,1115.800883142221,0.0001575305504957214,1.0920233726501465,0.09268996864557266 -2.0,80.0,0.15000000000000002,8.0,1115.800883142221,0.0001575305504957214,1.2724671363830566,0.10756934434175491 -2.0,80.0,0.15000000000000002,10.0,1115.800883142221,0.0001575305504957214,1.4526970386505127,0.12495358288288116 -2.0,80.0,0.20000000000000004,-2.0,1115.800883142221,0.0001575305504957214,0.367483526468277,0.05770282447338104 -2.0,80.0,0.20000000000000004,0.0,1115.800883142221,0.0001575305504957214,0.5498017072677612,0.06246945261955261 -2.0,80.0,0.20000000000000004,2.0,1115.800883142221,0.0001575305504957214,0.7319031953811646,0.06978658586740494 -2.0,80.0,0.20000000000000004,4.0,1115.800883142221,0.0001575305504957214,0.9137882590293884,0.079645536839962 -2.0,80.0,0.20000000000000004,6.0,1115.800883142221,0.0001575305504957214,1.0954564809799194,0.09203751385211945 -2.0,80.0,0.20000000000000004,8.0,1115.800883142221,0.0001575305504957214,1.2769081592559814,0.10695385187864304 -2.0,80.0,0.20000000000000004,10.0,1115.800883142221,0.0001575305504957214,1.4581433534622192,0.12438584119081497 -2.0,80.0,0.25000000000000006,-2.0,1115.800883142221,0.0001575305504957214,0.36666467785835266,0.05717618763446808 -2.0,80.0,0.25000000000000006,0.0,1115.800883142221,0.0001575305504957214,0.5503196120262146,0.06195075437426567 -2.0,80.0,0.25000000000000006,2.0,1115.800883142221,0.0001575305504957214,0.7337546348571777,0.06929992139339447 -2.0,80.0,0.25000000000000006,4.0,1115.800883142221,0.0001575305504957214,0.9169696569442749,0.07921480387449265 -2.0,80.0,0.25000000000000006,6.0,1115.800883142221,0.0001575305504957214,1.0999648571014404,0.09168653935194016 -2.0,80.0,0.25000000000000006,8.0,1115.800883142221,0.0001575305504957214,1.2827399969100952,0.10670622438192368 -2.0,80.0,0.25000000000000006,10.0,1115.800883142221,0.0001575305504957214,1.4652950763702393,0.12426501512527466 -2.0,80.0,0.30000000000000004,-2.0,1115.800883142221,0.0001575305504957214,0.36563733220100403,0.05674440786242485 -2.0,80.0,0.30000000000000004,0.0,1115.800883142221,0.0001575305504957214,0.5509704947471619,0.061539433896541595 -2.0,80.0,0.30000000000000004,2.0,1115.800883142221,0.0001575305504957214,0.7360795140266418,0.06894510984420776 -2.0,80.0,0.30000000000000004,4.0,1115.800883142221,0.0001575305504957214,0.9209643602371216,0.0789523497223854 -2.0,80.0,0.30000000000000004,6.0,1115.800883142221,0.0001575305504957214,1.105625033378601,0.09155204892158508 -2.0,80.0,0.30000000000000004,8.0,1115.800883142221,0.0001575305504957214,1.2900614738464355,0.10673512518405914 -2.0,80.0,0.30000000000000004,10.0,1115.800883142221,0.0001575305504957214,1.4742738008499146,0.12449251860380173 -2.0,90.0,0.1,-2.0,1115.761991656717,0.00015756834181956947,0.3686772882938385,0.05943587049841881 -2.0,90.0,0.1,0.0,1115.761991656717,0.00015756834181956947,0.548945426940918,0.06427404284477234 -2.0,90.0,0.1,2.0,1115.761991656717,0.00015756834181956947,0.7290394902229309,0.07167238742113113 -2.0,90.0,0.1,4.0,1115.761991656717,0.00015756834181956947,0.9089594483375549,0.08162378519773483 -2.0,90.0,0.1,6.0,1115.761991656717,0.00015756834181956947,1.08870530128479,0.09412111341953278 -2.0,90.0,0.1,8.0,1115.761991656717,0.00015756834181956947,1.2682771682739258,0.10915728658437729 -2.0,90.0,0.1,10.0,1115.761991656717,0.00015756834181956947,1.4476748704910278,0.12672516703605652 -2.0,90.0,0.15000000000000002,-2.0,1115.761991656717,0.00015756834181956947,0.36823898553848267,0.05841787904500961 -2.0,90.0,0.15000000000000002,0.0,1115.761991656717,0.00015756834181956947,0.5492216944694519,0.06322601437568665 -2.0,90.0,0.15000000000000002,2.0,1115.761991656717,0.00015756834181956947,0.7300289273262024,0.0705891102552414 -2.0,90.0,0.15000000000000002,4.0,1115.761991656717,0.00015756834181956947,0.9106605052947998,0.08050002157688141 -2.0,90.0,0.15000000000000002,6.0,1115.761991656717,0.00015756834181956947,1.0911167860031128,0.09295162558555603 -2.0,90.0,0.15000000000000002,8.0,1115.761991656717,0.00015756834181956947,1.271397352218628,0.1079367846250534 -2.0,90.0,0.15000000000000002,10.0,1115.761991656717,0.00015756834181956947,1.4515026807785034,0.12544839084148407 -2.0,90.0,0.20000000000000004,-2.0,1115.761991656717,0.00015756834181956947,0.3676159083843231,0.057727452367544174 -2.0,90.0,0.20000000000000004,0.0,1115.761991656717,0.00015756834181956947,0.5496147871017456,0.06252825260162354 -2.0,90.0,0.20000000000000004,2.0,1115.761991656717,0.00015756834181956947,0.7314361929893494,0.06989527493715286 -2.0,90.0,0.20000000000000004,4.0,1115.761991656717,0.00015756834181956947,0.9130799174308777,0.07982130348682404 -2.0,90.0,0.20000000000000004,6.0,1115.761991656717,0.00015756834181956947,1.0945461988449097,0.09229914844036102 -2.0,90.0,0.20000000000000004,8.0,1115.761991656717,0.00015756834181956947,1.2758347988128662,0.1073215901851654 -2.0,90.0,0.20000000000000004,10.0,1115.761991656717,0.00015756834181956947,1.4569458961486816,0.12488144636154175 -2.0,90.0,0.25000000000000006,-2.0,1115.761991656717,0.00015756834181956947,0.3667981028556824,0.057200536131858826 -2.0,90.0,0.25000000000000006,0.0,1115.761991656717,0.00015756834181956947,0.5501314401626587,0.06200932338833809 -2.0,90.0,0.25000000000000006,2.0,1115.761991656717,0.00015756834181956947,0.7332844734191895,0.06940858066082001 -2.0,90.0,0.25000000000000006,4.0,1115.761991656717,0.00015756834181956947,0.9162572026252747,0.07939095050096512 -2.0,90.0,0.25000000000000006,6.0,1115.761991656717,0.00015756834181956947,1.0990495681762695,0.09194909781217575 -2.0,90.0,0.25000000000000006,8.0,1115.761991656717,0.00015756834181956947,1.2816616296768188,0.10707572102546692 -2.0,90.0,0.25000000000000006,10.0,1115.761991656717,0.00015756834181956947,1.464093565940857,0.12476348131895065 -2.0,90.0,0.30000000000000004,-2.0,1115.761991656717,0.00015756834181956947,0.365772008895874,0.056768469512462616 -2.0,90.0,0.30000000000000004,0.0,1115.761991656717,0.00015756834181956947,0.5507805347442627,0.061597853899002075 -2.0,90.0,0.30000000000000004,2.0,1115.761991656717,0.00015756834181956947,0.7356053590774536,0.06905397772789001 -2.0,90.0,0.30000000000000004,4.0,1115.761991656717,0.00015756834181956947,0.9202463626861572,0.07912933081388474 -2.0,90.0,0.30000000000000004,6.0,1115.761991656717,0.00015756834181956947,1.104703664779663,0.09181641042232513 -2.0,90.0,0.30000000000000004,8.0,1115.761991656717,0.00015756834181956947,1.2889772653579712,0.10710770636796951 -2.0,90.0,0.30000000000000004,10.0,1115.761991656717,0.00015756834181956947,1.4730669260025024,0.12499568611383438 -3.0,0.0,0.1,-2.0,1116.1121663638341,0.0001572293695062399,1.0067344903945923,0.08343718200922012 -3.0,0.0,0.1,0.0,1116.1121663638341,0.0001572293695062399,1.2001934051513672,0.08693242073059082 -3.0,0.0,0.1,2.0,1116.1121663638341,0.0001572293695062399,1.3868204355239868,0.09158356487751007 -3.0,0.0,0.1,4.0,1116.1121663638341,0.0001572293695062399,1.5666152238845825,0.09725863486528397 -3.0,0.0,0.1,6.0,1116.1121663638341,0.0001572293695062399,1.7395782470703125,0.10382939875125885 -3.0,0.0,0.1,8.0,1116.1121663638341,0.0001572293695062399,1.9102439880371094,0.11138612776994705 -3.0,0.0,0.1,10.0,1116.1121663638341,0.0001572293695062399,2.089658498764038,0.12048513442277908 -3.0,0.0,0.15000000000000002,-2.0,1116.1121663638341,0.0001572293695062399,1.006030559539795,0.08241500705480576 -3.0,0.0,0.15000000000000002,0.0,1116.1121663638341,0.0001572293695062399,1.2002952098846436,0.08588836342096329 -3.0,0.0,0.15000000000000002,2.0,1116.1121663638341,0.0001572293695062399,1.3876711130142212,0.09051550924777985 -3.0,0.0,0.15000000000000002,4.0,1116.1121663638341,0.0001572293695062399,1.5681583881378174,0.09616418927907944 -3.0,0.0,0.15000000000000002,6.0,1116.1121663638341,0.0001572293695062399,1.7417570352554321,0.10270584374666214 -3.0,0.0,0.15000000000000002,8.0,1116.1121663638341,0.0001572293695062399,1.9131406545639038,0.11023540794849396 -3.0,0.0,0.15000000000000002,10.0,1116.1121663638341,0.0001572293695062399,2.093266487121582,0.11930183321237564 -3.0,0.0,0.20000000000000004,-2.0,1116.1121663638341,0.0001572293695062399,1.0050297975540161,0.08172053843736649 -3.0,0.0,0.20000000000000004,0.0,1116.1121663638341,0.0001572293695062399,1.200440764427185,0.08518803864717484 -3.0,0.0,0.20000000000000004,2.0,1116.1121663638341,0.0001572293695062399,1.388882040977478,0.08981481194496155 -3.0,0.0,0.20000000000000004,4.0,1116.1121663638341,0.0001572293695062399,1.570353627204895,0.09546715021133423 -3.0,0.0,0.20000000000000004,6.0,1116.1121663638341,0.0001572293695062399,1.744855284690857,0.1020151823759079 -3.0,0.0,0.20000000000000004,8.0,1116.1121663638341,0.0001572293695062399,1.9172605276107788,0.10956105589866638 -3.0,0.0,0.20000000000000004,10.0,1116.1121663638341,0.0001572293695062399,2.0983974933624268,0.11864732205867767 -3.0,0.0,0.25000000000000006,-2.0,1116.1121663638341,0.0001572293695062399,1.0037161111831665,0.08118928968906403 -3.0,0.0,0.25000000000000006,0.0,1116.1121663638341,0.0001572293695062399,1.2006332874298096,0.08466172218322754 -3.0,0.0,0.25000000000000006,2.0,1116.1121663638341,0.0001572293695062399,1.3904736042022705,0.0893048569560051 -3.0,0.0,0.25000000000000006,4.0,1116.1121663638341,0.0001572293695062399,1.5732371807098389,0.09498263150453568 -3.0,0.0,0.25000000000000006,6.0,1116.1121663638341,0.0001572293695062399,1.7489237785339355,0.10156293958425522 -3.0,0.0,0.25000000000000006,8.0,1116.1121663638341,0.0001572293695062399,1.9226713180541992,0.10915790498256683 -3.0,0.0,0.25000000000000006,10.0,1116.1121663638341,0.0001572293695062399,2.1051363945007324,0.11830347031354904 -3.0,0.0,0.30000000000000004,-2.0,1116.1121663638341,0.0001572293695062399,1.0020676851272583,0.0807524174451828 -3.0,0.0,0.30000000000000004,0.0,1116.1121663638341,0.0001572293695062399,1.2008774280548096,0.08423855155706406 -3.0,0.0,0.30000000000000004,2.0,1116.1121663638341,0.0001572293695062399,1.3924745321273804,0.08891244232654572 -3.0,0.0,0.30000000000000004,4.0,1116.1121663638341,0.0001572293695062399,1.5768592357635498,0.09463469684123993 -3.0,0.0,0.30000000000000004,6.0,1116.1121663638341,0.0001572293695062399,1.7540310621261597,0.10127004235982895 -3.0,0.0,0.30000000000000004,8.0,1116.1121663638341,0.0001572293695062399,1.9294657707214355,0.10894355177879333 -3.0,0.0,0.30000000000000004,10.0,1116.1121663638341,0.0001572293695062399,2.113598108291626,0.11818400770425797 -3.0,10.0,0.1,-2.0,1116.0732851388082,0.00015726701531093568,1.009021282196045,0.08535981923341751 -3.0,10.0,0.1,0.0,1116.0732851388082,0.00015726701531093568,1.1980414390563965,0.09088112413883209 -3.0,10.0,0.1,2.0,1116.0732851388082,0.00015726701531093568,1.3844903707504272,0.09835368394851685 -3.0,10.0,0.1,4.0,1116.0732851388082,0.00015726701531093568,1.5683679580688477,0.10769792646169662 -3.0,10.0,0.1,6.0,1116.0732851388082,0.00015726701531093568,1.7496744394302368,0.11883515864610672 -3.0,10.0,0.1,8.0,1116.0732851388082,0.00015726701531093568,1.9284093379974365,0.1316874921321869 -3.0,10.0,0.1,10.0,1116.0732851388082,0.00015726701531093568,2.1045732498168945,0.1461779922246933 -3.0,10.0,0.15000000000000002,-2.0,1116.0732851388082,0.00015726701531093568,1.0083417892456055,0.08431161940097809 -3.0,10.0,0.15000000000000002,0.0,1116.0732851388082,0.00015726701531093568,1.1981171369552612,0.0897969976067543 -3.0,10.0,0.15000000000000002,2.0,1116.0732851388082,0.00015726701531093568,1.3852999210357666,0.09722962975502014 -3.0,10.0,0.15000000000000002,4.0,1116.0732851388082,0.00015726701531093568,1.569890022277832,0.10652977228164673 -3.0,10.0,0.15000000000000002,6.0,1116.0732851388082,0.00015726701531093568,1.751887559890747,0.11761856079101562 -3.0,10.0,0.15000000000000002,8.0,1116.0732851388082,0.00015726701531093568,1.9312925338745117,0.13041794300079346 -3.0,10.0,0.15000000000000002,10.0,1116.0732851388082,0.00015726701531093568,2.108104944229126,0.14485080540180206 -3.0,10.0,0.20000000000000004,-2.0,1116.0732851388082,0.00015726701531093568,1.0073760747909546,0.08359536528587341 -3.0,10.0,0.20000000000000004,0.0,1116.0732851388082,0.00015726701531093568,1.1982252597808838,0.0890698954463005 -3.0,10.0,0.20000000000000004,2.0,1116.0732851388082,0.00015726701531093568,1.3864516019821167,0.09650025516748428 -3.0,10.0,0.20000000000000004,4.0,1116.0732851388082,0.00015726701531093568,1.5720546245574951,0.10580585151910782 -3.0,10.0,0.20000000000000004,6.0,1116.0732851388082,0.00015726701531093568,1.7550348043441772,0.11690697073936462 -3.0,10.0,0.20000000000000004,8.0,1116.0732851388082,0.00015726701531093568,1.9353916645050049,0.12972477078437805 -3.0,10.0,0.20000000000000004,10.0,1116.0732851388082,0.00015726701531093568,2.1131253242492676,0.1441812962293625 -3.0,10.0,0.25000000000000006,-2.0,1116.0732851388082,0.00015726701531093568,1.0061087608337402,0.08304315060377121 -3.0,10.0,0.25000000000000006,0.0,1116.0732851388082,0.00015726701531093568,1.1983684301376343,0.0885235145688057 -3.0,10.0,0.25000000000000006,2.0,1116.0732851388082,0.00015726701531093568,1.3879648447036743,0.09597813338041306 -3.0,10.0,0.25000000000000006,4.0,1116.0732851388082,0.00015726701531093568,1.5748976469039917,0.10532501339912415 -3.0,10.0,0.25000000000000006,6.0,1116.0732851388082,0.00015726701531093568,1.7591670751571655,0.11648304015398026 -3.0,10.0,0.25000000000000006,8.0,1116.0732851388082,0.00015726701531093568,1.9407730102539062,0.1293720304965973 -3.0,10.0,0.25000000000000006,10.0,1116.0732851388082,0.00015726701531093568,2.119715929031372,0.14391270279884338 -3.0,10.0,0.30000000000000004,-2.0,1116.0732851388082,0.00015726701531093568,1.0045191049575806,0.08258466422557831 -3.0,10.0,0.30000000000000004,0.0,1116.0732851388082,0.00015726701531093568,1.198549747467041,0.08808432519435883 -3.0,10.0,0.30000000000000004,2.0,1116.0732851388082,0.00015726701531093568,1.389865756034851,0.09558583050966263 -3.0,10.0,0.30000000000000004,4.0,1116.0732851388082,0.00015726701531093568,1.5784673690795898,0.10500523447990417 -3.0,10.0,0.30000000000000004,6.0,1116.0732851388082,0.00015726701531093568,1.7643544673919678,0.11625949293375015 -3.0,10.0,0.30000000000000004,8.0,1116.0732851388082,0.00015726701531093568,1.9475270509719849,0.12926644086837769 -3.0,10.0,0.30000000000000004,10.0,1116.0732851388082,0.00015726701531093568,2.1279852390289307,0.14394497871398926 -3.0,20.0,0.1,-2.0,1116.0343369575487,0.000157304632011801,1.010275959968567,0.08643506467342377 -3.0,20.0,0.1,0.0,1116.0343369575487,0.000157304632011801,1.1965079307556152,0.09301955252885818 -3.0,20.0,0.1,2.0,1116.0343369575487,0.000157304632011801,1.381329894065857,0.10195326805114746 -3.0,20.0,0.1,4.0,1116.0343369575487,0.000157304632011801,1.5647422075271606,0.11318392306566238 -3.0,20.0,0.1,6.0,1116.0343369575487,0.000157304632011801,1.7467447519302368,0.12665952742099762 -3.0,20.0,0.1,8.0,1116.0343369575487,0.000157304632011801,1.9273371696472168,0.1423284113407135 -3.0,20.0,0.1,10.0,1116.0343369575487,0.000157304632011801,2.106519937515259,0.16013923287391663 -3.0,20.0,0.15000000000000002,-2.0,1116.0343369575487,0.000157304632011801,1.0096036195755005,0.08537262678146362 -3.0,20.0,0.15000000000000002,0.0,1116.0343369575487,0.000157304632011801,1.19657564163208,0.09191404283046722 -3.0,20.0,0.15000000000000002,2.0,1116.0343369575487,0.000157304632011801,1.3821260929107666,0.10079985111951828 -3.0,20.0,0.15000000000000002,4.0,1116.0343369575487,0.000157304632011801,1.5662550926208496,0.11197767406702042 -3.0,20.0,0.15000000000000002,6.0,1116.0343369575487,0.000157304632011801,1.748962640762329,0.12539538741111755 -3.0,20.0,0.15000000000000002,8.0,1116.0343369575487,0.000157304632011801,1.930248498916626,0.14100119471549988 -3.0,20.0,0.15000000000000002,10.0,1116.0343369575487,0.000157304632011801,2.1101129055023193,0.15874366462230682 -3.0,20.0,0.20000000000000004,-2.0,1116.0343369575487,0.000157304632011801,1.008648157119751,0.08464440703392029 -3.0,20.0,0.20000000000000004,0.0,1116.0343369575487,0.000157304632011801,1.1966726779937744,0.09117264300584793 -3.0,20.0,0.20000000000000004,2.0,1116.0343369575487,0.000157304632011801,1.3832589387893677,0.10005556046962738 -3.0,20.0,0.20000000000000004,4.0,1116.0343369575487,0.000157304632011801,1.5684068202972412,0.1112401932477951 -3.0,20.0,0.20000000000000004,6.0,1116.0343369575487,0.000157304632011801,1.7521166801452637,0.12467394024133682 -3.0,20.0,0.20000000000000004,8.0,1116.0343369575487,0.000157304632011801,1.9343881607055664,0.14030440151691437 -3.0,20.0,0.20000000000000004,10.0,1116.0343369575487,0.000157304632011801,2.1152215003967285,0.15807963907718658 -3.0,20.0,0.25000000000000006,-2.0,1116.0343369575487,0.000157304632011801,1.0073943138122559,0.08408065140247345 -3.0,20.0,0.25000000000000006,0.0,1116.0343369575487,0.000157304632011801,1.1968008279800415,0.09061553329229355 -3.0,20.0,0.25000000000000006,2.0,1116.0343369575487,0.000157304632011801,1.38474702835083,0.0995272621512413 -3.0,20.0,0.25000000000000006,4.0,1116.0343369575487,0.000157304632011801,1.5712329149246216,0.11076194792985916 -3.0,20.0,0.25000000000000006,6.0,1116.0343369575487,0.000157304632011801,1.7562586069107056,0.12426603585481644 -3.0,20.0,0.25000000000000006,8.0,1116.0343369575487,0.000157304632011801,1.9398237466812134,0.13998626172542572 -3.0,20.0,0.25000000000000006,10.0,1116.0343369575487,0.000157304632011801,2.1219284534454346,0.15786975622177124 -3.0,20.0,0.30000000000000004,-2.0,1116.0343369575487,0.000157304632011801,1.0058218240737915,0.08361025899648666 -3.0,20.0,0.30000000000000004,0.0,1116.0343369575487,0.000157304632011801,1.1969635486602783,0.09016779065132141 -3.0,20.0,0.30000000000000004,2.0,1116.0343369575487,0.000157304632011801,1.3866169452667236,0.09913534671068192 -3.0,20.0,0.30000000000000004,4.0,1116.0343369575487,0.000157304632011801,1.574781894683838,0.11045775562524796 -3.0,20.0,0.30000000000000004,6.0,1116.0343369575487,0.000157304632011801,1.7614585161209106,0.12408015877008438 -3.0,20.0,0.30000000000000004,8.0,1116.0343369575487,0.000157304632011801,1.9466466903686523,0.1399480700492859 -3.0,20.0,0.30000000000000004,10.0,1116.0343369575487,0.000157304632011801,2.1303465366363525,0.15800727903842926 -3.0,30.0,0.1,-2.0,1115.9954531665346,0.0001573422778164968,1.0111433267593384,0.08710844814777374 -3.0,30.0,0.1,0.0,1115.9954531665346,0.0001573422778164968,1.1953612565994263,0.0943206399679184 -3.0,30.0,0.1,2.0,1115.9954531665346,0.0001573422778164968,1.378684401512146,0.10410651564598083 -3.0,30.0,0.1,4.0,1115.9954531665346,0.0001573422778164968,1.5611127614974976,0.11642959713935852 -3.0,30.0,0.1,6.0,1115.9954531665346,0.0001573422778164968,1.7426466941833496,0.13125362992286682 -3.0,30.0,0.1,8.0,1115.9954531665346,0.0001573422778164968,1.923285722732544,0.1485423892736435 -3.0,30.0,0.1,10.0,1115.9954531665346,0.0001573422778164968,2.103030204772949,0.1682598739862442 -3.0,30.0,0.15000000000000002,-2.0,1115.9954531665346,0.0001573422778164968,1.0104752779006958,0.08603718131780624 -3.0,30.0,0.15000000000000002,0.0,1115.9954531665346,0.0001573422778164968,1.1954240798950195,0.09320211410522461 -3.0,30.0,0.15000000000000002,2.0,1115.9954531665346,0.0001573422778164968,1.3794708251953125,0.10293544828891754 -3.0,30.0,0.15000000000000002,4.0,1115.9954531665346,0.0001573422778164968,1.5626155138015747,0.11520065367221832 -3.0,30.0,0.15000000000000002,6.0,1115.9954531665346,0.0001573422778164968,1.744857907295227,0.1299613118171692 -3.0,30.0,0.15000000000000002,8.0,1115.9954531665346,0.0001573422778164968,1.9261983633041382,0.14718122780323029 -3.0,30.0,0.15000000000000002,10.0,1115.9954531665346,0.0001573422778164968,2.1066365242004395,0.16682423651218414 -3.0,30.0,0.20000000000000004,-2.0,1115.9954531665346,0.0001573422778164968,1.0095256567001343,0.08530152589082718 -3.0,30.0,0.20000000000000004,0.0,1115.9954531665346,0.0001573422778164968,1.1955140829086304,0.09245194494724274 -3.0,30.0,0.20000000000000004,2.0,1115.9954531665346,0.0001573422778164968,1.3805897235870361,0.10218203067779541 -3.0,30.0,0.20000000000000004,4.0,1115.9954531665346,0.0001573422778164968,1.5647525787353516,0.11445487290620804 -3.0,30.0,0.20000000000000004,6.0,1115.9954531665346,0.0001573422778164968,1.7480028867721558,0.129233717918396 -3.0,30.0,0.20000000000000004,8.0,1115.9954531665346,0.0001573422778164968,1.9303405284881592,0.1464819312095642 -3.0,30.0,0.20000000000000004,10.0,1115.9954531665346,0.0001573422778164968,2.1117653846740723,0.16616299748420715 -3.0,30.0,0.25000000000000006,-2.0,1115.9954531665346,0.0001573422778164968,1.0082796812057495,0.08473066985607147 -3.0,30.0,0.25000000000000006,0.0,1115.9954531665346,0.0001573422778164968,1.1956331729888916,0.09188825637102127 -3.0,30.0,0.25000000000000006,2.0,1115.9954531665346,0.0001573422778164968,1.382059931755066,0.10164981335401535 -3.0,30.0,0.25000000000000006,4.0,1115.9954531665346,0.0001573422778164968,1.567559838294983,0.11397778242826462 -3.0,30.0,0.25000000000000006,6.0,1115.9954531665346,0.0001573422778164968,1.7521331310272217,0.1288347691297531 -3.0,30.0,0.25000000000000006,8.0,1115.9954531665346,0.0001573422778164968,1.9357795715332031,0.14618346095085144 -3.0,30.0,0.25000000000000006,10.0,1115.9954531665346,0.0001573422778164968,2.118499279022217,0.16598676145076752 -3.0,30.0,0.30000000000000004,-2.0,1115.9954531665346,0.0001573422778164968,1.0067168474197388,0.08425289392471313 -3.0,30.0,0.30000000000000004,0.0,1115.9954531665346,0.0001573422778164968,1.195784091949463,0.09143515676259995 -3.0,30.0,0.30000000000000004,2.0,1115.9954531665346,0.0001573422778164968,1.3839069604873657,0.1012577936053276 -3.0,30.0,0.30000000000000004,4.0,1115.9954531665346,0.0001573422778164968,1.5710850954055786,0.11368231475353241 -3.0,30.0,0.30000000000000004,6.0,1115.9954531665346,0.0001573422778164968,1.7573187351226807,0.12867042422294617 -3.0,30.0,0.30000000000000004,8.0,1115.9954531665346,0.0001573422778164968,1.9426078796386719,0.14618396759033203 -3.0,30.0,0.30000000000000004,10.0,1115.9954531665346,0.0001573422778164968,2.1269524097442627,0.16618488729000092 -3.0,40.0,0.1,-2.0,1115.9565680934381,0.00015737992362119257,1.0117446184158325,0.08755215257406235 -3.0,40.0,0.1,0.0,1115.9565680934381,0.00015737992362119257,1.1945427656173706,0.09516104310750961 -3.0,40.0,0.1,2.0,1115.9565680934381,0.00015737992362119257,1.376724123954773,0.10548081248998642 -3.0,40.0,0.1,4.0,1115.9565680934381,0.00015737992362119257,1.558288812637329,0.11848488450050354 -3.0,40.0,0.1,6.0,1115.9565680934381,0.00015737992362119257,1.7392367124557495,0.1341467946767807 -3.0,40.0,0.1,8.0,1115.9565680934381,0.00015737992362119257,1.9195680618286133,0.1524401605129242 -3.0,40.0,0.1,10.0,1115.9565680934381,0.00015737992362119257,2.0992825031280518,0.17333854734897614 -3.0,40.0,0.15000000000000002,-2.0,1115.9565680934381,0.00015737992362119257,1.01107919216156,0.08647508174180984 -3.0,40.0,0.15000000000000002,0.0,1115.9565680934381,0.00015737992362119257,1.1946022510528564,0.09403406083583832 -3.0,40.0,0.15000000000000002,2.0,1115.9565680934381,0.00015737992362119257,1.377503514289856,0.10429837554693222 -3.0,40.0,0.15000000000000002,4.0,1115.9565680934381,0.00015737992362119257,1.5597829818725586,0.11724139750003815 -3.0,40.0,0.15000000000000002,6.0,1115.9565680934381,0.00015737992362119257,1.7414406538009644,0.13283659517765045 -3.0,40.0,0.15000000000000002,8.0,1115.9565680934381,0.00015737992362119257,1.9224762916564941,0.15105748176574707 -3.0,40.0,0.15000000000000002,10.0,1115.9565680934381,0.00015737992362119257,2.1028904914855957,0.17187771201133728 -3.0,40.0,0.20000000000000004,-2.0,1115.9565680934381,0.00015737992362119257,1.0101333856582642,0.08573457598686218 -3.0,40.0,0.20000000000000004,0.0,1115.9565680934381,0.00015737992362119257,1.1946874856948853,0.0932781994342804 -3.0,40.0,0.20000000000000004,2.0,1115.9565680934381,0.00015737992362119257,1.3786123991012573,0.10353904217481613 -3.0,40.0,0.20000000000000004,4.0,1115.9565680934381,0.00015737992362119257,1.5619081258773804,0.11649022251367569 -3.0,40.0,0.20000000000000004,6.0,1115.9565680934381,0.00015737992362119257,1.7445746660232544,0.13210488855838776 -3.0,40.0,0.20000000000000004,8.0,1115.9565680934381,0.00015737992362119257,1.9266122579574585,0.15035632252693176 -3.0,40.0,0.20000000000000004,10.0,1115.9565680934381,0.00015737992362119257,2.108020782470703,0.1712178736925125 -3.0,40.0,0.25000000000000006,-2.0,1115.9565680934381,0.00015737992362119257,1.0088924169540405,0.08515904098749161 -3.0,40.0,0.25000000000000006,0.0,1115.9565680934381,0.00015737992362119257,1.1948002576828003,0.09271018207073212 -3.0,40.0,0.25000000000000006,2.0,1115.9565680934381,0.00015737992362119257,1.380069375038147,0.10300415009260178 -3.0,40.0,0.25000000000000006,4.0,1115.9565680934381,0.00015737992362119257,1.564699649810791,0.11601361632347107 -3.0,40.0,0.25000000000000006,6.0,1115.9565680934381,0.00015737992362119257,1.7486909627914429,0.13171124458312988 -3.0,40.0,0.25000000000000006,8.0,1115.9565680934381,0.00015737992362119257,1.9320436716079712,0.15006984770298004 -3.0,40.0,0.25000000000000006,10.0,1115.9565680934381,0.00015737992362119257,2.1147572994232178,0.17106226086616516 -3.0,40.0,0.30000000000000004,-2.0,1115.9565680934381,0.00015737992362119257,1.0073360204696655,0.08467645943164825 -3.0,40.0,0.30000000000000004,0.0,1115.9565680934381,0.00015737992362119257,1.1949435472488403,0.09225357323884964 -3.0,40.0,0.30000000000000004,2.0,1115.9565680934381,0.00015737992362119257,1.3818999528884888,0.10261189192533493 -3.0,40.0,0.30000000000000004,4.0,1115.9565680934381,0.00015737992362119257,1.5682052373886108,0.1157233864068985 -3.0,40.0,0.30000000000000004,6.0,1115.9565680934381,0.00015737992362119257,1.7538594007492065,0.1315600723028183 -3.0,40.0,0.30000000000000004,8.0,1115.9565680934381,0.00015737992362119257,1.9388625621795654,0.1500941514968872 -3.0,40.0,0.30000000000000004,10.0,1115.9565680934381,0.00015737992362119257,2.1232147216796875,0.17129777371883392 -3.0,50.0,0.1,-2.0,1115.917615583849,0.00015741751121822745,1.0121642351150513,0.08785390853881836 -3.0,50.0,0.1,0.0,1115.917615583849,0.00015741751121822745,1.1939637660980225,0.09572488814592361 -3.0,50.0,0.1,2.0,1115.917615583849,0.00015741751121822745,1.3753139972686768,0.10639534145593643 -3.0,50.0,0.1,4.0,1115.917615583849,0.00015741751121822745,1.5562149286270142,0.11984521895647049 -3.0,50.0,0.1,6.0,1115.917615583849,0.00015741751121822745,1.7366665601730347,0.13605451583862305 -3.0,50.0,0.1,8.0,1115.917615583849,0.00015741751121822745,1.9166691303253174,0.1550033539533615 -3.0,50.0,0.1,10.0,1115.917615583849,0.00015741751121822745,2.096222162246704,0.17667168378829956 -3.0,50.0,0.15000000000000002,-2.0,1115.917615583849,0.00015741751121822745,1.0115004777908325,0.0867728739976883 -3.0,50.0,0.15000000000000002,0.0,1115.917615583849,0.00015741751121822745,1.1940208673477173,0.09459221363067627 -3.0,50.0,0.15000000000000002,2.0,1115.917615583849,0.00015741751121822745,1.376088261604309,0.10520531982183456 -3.0,50.0,0.15000000000000002,4.0,1115.917615583849,0.00015741751121822745,1.5577027797698975,0.11859207600355148 -3.0,50.0,0.15000000000000002,6.0,1115.917615583849,0.00015741751121822745,1.7388640642166138,0.1347324401140213 -3.0,50.0,0.15000000000000002,8.0,1115.917615583849,0.00015741751121822745,1.9195727109909058,0.15360647439956665 -3.0,50.0,0.15000000000000002,10.0,1115.917615583849,0.00015741751121822745,2.099827766418457,0.1751941293478012 -3.0,50.0,0.20000000000000004,-2.0,1115.917615583849,0.00015741751121822745,1.0105572938919067,0.08602907508611679 -3.0,50.0,0.20000000000000004,0.0,1115.917615583849,0.00015741751121822745,1.1941027641296387,0.09383249282836914 -3.0,50.0,0.20000000000000004,2.0,1115.917615583849,0.00015741751121822745,1.3771899938583374,0.10444196313619614 -3.0,50.0,0.20000000000000004,4.0,1115.917615583849,0.00015741751121822745,1.5598188638687134,0.11783719062805176 -3.0,50.0,0.20000000000000004,6.0,1115.917615583849,0.00015741751121822745,1.7419891357421875,0.13399791717529297 -3.0,50.0,0.20000000000000004,8.0,1115.917615583849,0.00015741751121822745,1.923701524734497,0.15290392935276031 -3.0,50.0,0.20000000000000004,10.0,1115.917615583849,0.00015741751121822745,2.1049554347991943,0.17453508079051971 -3.0,50.0,0.25000000000000006,-2.0,1115.917615583849,0.00015741751121822745,1.00931978225708,0.08545037358999252 -3.0,50.0,0.25000000000000006,0.0,1115.917615583849,0.00015741751121822745,1.1942113637924194,0.09326154738664627 -3.0,50.0,0.25000000000000006,2.0,1115.917615583849,0.00015741751121822745,1.3786375522613525,0.10390523821115494 -3.0,50.0,0.25000000000000006,4.0,1115.917615583849,0.00015741751121822745,1.5625983476638794,0.11736079305410385 -3.0,50.0,0.25000000000000006,6.0,1115.917615583849,0.00015741751121822745,1.74609375,0.1336076259613037 -3.0,50.0,0.25000000000000006,8.0,1115.917615583849,0.00015741751121822745,1.929123878479004,0.15262514352798462 -3.0,50.0,0.25000000000000006,10.0,1115.917615583849,0.00015741751121822745,2.1116886138916016,0.17439284920692444 -3.0,50.0,0.30000000000000004,-2.0,1115.917615583849,0.00015741751121822745,1.0077675580978394,0.08496454358100891 -3.0,50.0,0.30000000000000004,0.0,1115.917615583849,0.00015741751121822745,1.1943490505218506,0.09280254691839218 -3.0,50.0,0.30000000000000004,2.0,1115.917615583849,0.00015741751121822745,1.3804562091827393,0.1035127118229866 -3.0,50.0,0.30000000000000004,4.0,1115.917615583849,0.00015741751121822745,1.566089153289795,0.11707388609647751 -3.0,50.0,0.30000000000000004,6.0,1115.917615583849,0.00015741751121822745,1.751247525215149,0.13346494734287262 -3.0,50.0,0.30000000000000004,8.0,1115.917615583849,0.00015741751121822745,1.93593168258667,0.15266485512256622 -3.0,50.0,0.30000000000000004,10.0,1115.917615583849,0.00015741751121822745,2.1201415061950684,0.1746525913476944 -3.0,60.0,0.1,-2.0,1115.878662265104,0.00015745522978249937,1.012459397315979,0.0880637839436531 -3.0,60.0,0.1,0.0,1115.878662265104,0.00015745522978249937,1.1935535669326782,0.09611351788043976 -3.0,60.0,0.1,2.0,1115.878662265104,0.00015745522978249937,1.3743069171905518,0.1070222407579422 -3.0,60.0,0.1,4.0,1115.878662265104,0.00015745522978249937,1.5547194480895996,0.12077441811561584 -3.0,60.0,0.1,6.0,1115.878662265104,0.00015745522978249937,1.7347912788391113,0.1373545378446579 -3.0,60.0,0.1,8.0,1115.878662265104,0.00015745522978249937,1.9145221710205078,0.15674705803394318 -3.0,60.0,0.1,10.0,1115.878662265104,0.00015745522978249937,2.093912363052368,0.17893649637699127 -3.0,60.0,0.15000000000000002,-2.0,1115.878662265104,0.00015745522978249937,1.0117969512939453,0.08698002249002457 -3.0,60.0,0.15000000000000002,0.0,1115.878662265104,0.00015745522978249937,1.1936091184616089,0.09497690200805664 -3.0,60.0,0.15000000000000002,2.0,1115.878662265104,0.00015745522978249937,1.375077724456787,0.1058269664645195 -3.0,60.0,0.15000000000000002,4.0,1115.878662265104,0.00015745522978249937,1.5562026500701904,0.11951461434364319 -3.0,60.0,0.15000000000000002,6.0,1115.878662265104,0.00015745522978249937,1.7369838953018188,0.13602426648139954 -3.0,60.0,0.15000000000000002,8.0,1115.878662265104,0.00015745522978249937,1.9174212217330933,0.15534035861492157 -3.0,60.0,0.15000000000000002,10.0,1115.878662265104,0.00015745522978249937,2.097515344619751,0.17744748294353485 -3.0,60.0,0.20000000000000004,-2.0,1115.878662265104,0.00015745522978249937,1.0108555555343628,0.08623391389846802 -3.0,60.0,0.20000000000000004,0.0,1115.878662265104,0.00015745522978249937,1.1936887502670288,0.09421449899673462 -3.0,60.0,0.20000000000000004,2.0,1115.878662265104,0.00015745522978249937,1.3761742115020752,0.10506084561347961 -3.0,60.0,0.20000000000000004,4.0,1115.878662265104,0.00015745522978249937,1.5583120584487915,0.11875715851783752 -3.0,60.0,0.20000000000000004,6.0,1115.878662265104,0.00015745522978249937,1.7401020526885986,0.13528774678707123 -3.0,60.0,0.20000000000000004,8.0,1115.878662265104,0.00015745522978249937,1.9215446710586548,0.15463685989379883 -3.0,60.0,0.20000000000000004,10.0,1115.878662265104,0.00015745522978249937,2.1026391983032227,0.17678885161876678 -3.0,60.0,0.25000000000000006,-2.0,1115.878662265104,0.00015745522978249937,1.0096203088760376,0.08565300703048706 -3.0,60.0,0.25000000000000006,0.0,1115.878662265104,0.00015745522978249937,1.1937942504882812,0.09364151954650879 -3.0,60.0,0.25000000000000006,2.0,1115.878662265104,0.00015745522978249937,1.377614974975586,0.10452280193567276 -3.0,60.0,0.25000000000000006,4.0,1115.878662265104,0.00015745522978249937,1.5610828399658203,0.11828083544969559 -3.0,60.0,0.25000000000000006,6.0,1115.878662265104,0.00015745522978249937,1.7441976070404053,0.13489964604377747 -3.0,60.0,0.25000000000000006,8.0,1115.878662265104,0.00015745522978249937,1.9269592761993408,0.154363214969635 -3.0,60.0,0.25000000000000006,10.0,1115.878662265104,0.00015745522978249937,2.109367847442627,0.17665556073188782 -3.0,60.0,0.30000000000000004,-2.0,1115.878662265104,0.00015745522978249937,1.0080710649490356,0.08516491204500198 -3.0,60.0,0.30000000000000004,0.0,1115.878662265104,0.00015745522978249937,1.1939281225204468,0.0931808352470398 -3.0,60.0,0.30000000000000004,2.0,1115.878662265104,0.00015745522978249937,1.379425287246704,0.10413004457950592 -3.0,60.0,0.30000000000000004,4.0,1115.878662265104,0.00015745522978249937,1.5645625591278076,0.11799612641334534 -3.0,60.0,0.30000000000000004,6.0,1115.878662265104,0.00015745522978249937,1.749340295791626,0.134762704372406 -3.0,60.0,0.30000000000000004,8.0,1115.878662265104,0.00015745522978249937,1.933758020401001,0.1544133573770523 -3.0,60.0,0.30000000000000004,10.0,1115.878662265104,0.00015745522978249937,2.1178157329559326,0.17693175375461578 -3.0,70.0,0.1,-2.0,1115.839773344972,0.00015749289013911039,1.0126686096191406,0.08821234852075577 -3.0,70.0,0.1,0.0,1115.839773344972,0.00015749289013911039,1.1932618618011475,0.09638690203428268 -3.0,70.0,0.1,2.0,1115.839773344972,0.00015749289013911039,1.3735883235931396,0.10746170580387115 -3.0,70.0,0.1,4.0,1115.839773344972,0.00015749289013911039,1.5536479949951172,0.12142442166805267 -3.0,70.0,0.1,6.0,1115.839773344972,0.00015749289013911039,1.7334407567977905,0.13826264441013336 -3.0,70.0,0.1,8.0,1115.839773344972,0.00015749289013911039,1.9129668474197388,0.1579640954732895 -3.0,70.0,0.1,10.0,1115.839773344972,0.00015749289013911039,2.092226266860962,0.18051643669605255 -3.0,70.0,0.15000000000000002,-2.0,1115.839773344972,0.00015749289013911039,1.0120071172714233,0.08712662011384964 -3.0,70.0,0.15000000000000002,0.0,1115.839773344972,0.00015749289013911039,1.1933162212371826,0.09524748474359512 -3.0,70.0,0.15000000000000002,2.0,1115.839773344972,0.00015749289013911039,1.3743565082550049,0.10626272857189178 -3.0,70.0,0.15000000000000002,4.0,1115.839773344972,0.00015749289013911039,1.5551276206970215,0.12015990912914276 -3.0,70.0,0.15000000000000002,6.0,1115.839773344972,0.00015749289013911039,1.735629916191101,0.13692665100097656 -3.0,70.0,0.15000000000000002,8.0,1115.839773344972,0.00015749289013911039,1.915863037109375,0.15655061602592468 -3.0,70.0,0.15000000000000002,10.0,1115.839773344972,0.00015749289013911039,2.095827102661133,0.17901940643787384 -3.0,70.0,0.20000000000000004,-2.0,1115.839773344972,0.00015749289013911039,1.0110669136047363,0.08637887239456177 -3.0,70.0,0.20000000000000004,0.0,1115.839773344972,0.00015749289013911039,1.1933941841125488,0.09448318183422089 -3.0,70.0,0.20000000000000004,2.0,1115.839773344972,0.00015749289013911039,1.3754494190216064,0.10549461096525192 -3.0,70.0,0.20000000000000004,4.0,1115.839773344972,0.00015749289013911039,1.5572322607040405,0.11940062791109085 -3.0,70.0,0.20000000000000004,6.0,1115.839773344972,0.00015749289013911039,1.7387430667877197,0.13618871569633484 -3.0,70.0,0.20000000000000004,8.0,1115.839773344972,0.00015749289013911039,1.919981837272644,0.15584634244441986 -3.0,70.0,0.20000000000000004,10.0,1115.839773344972,0.00015749289013911039,2.1009480953216553,0.17836105823516846 -3.0,70.0,0.25000000000000006,-2.0,1115.839773344972,0.00015749289013911039,1.0098334550857544,0.08579641580581665 -3.0,70.0,0.25000000000000006,0.0,1115.839773344972,0.00015749289013911039,1.1934975385665894,0.09390874952077866 -3.0,70.0,0.25000000000000006,2.0,1115.839773344972,0.00015749289013911039,1.3768854141235352,0.10495564341545105 -3.0,70.0,0.25000000000000006,4.0,1115.839773344972,0.00015749289013911039,1.5599969625473022,0.1189243495464325 -3.0,70.0,0.25000000000000006,6.0,1115.839773344972,0.00015749289013911039,1.7428319454193115,0.13580211997032166 -3.0,70.0,0.25000000000000006,8.0,1115.839773344972,0.00015749289013911039,1.9253907203674316,0.15557622909545898 -3.0,70.0,0.25000000000000006,10.0,1115.839773344972,0.00015749289013911039,2.107673406600952,0.1782340258359909 -3.0,70.0,0.30000000000000004,-2.0,1115.839773344972,0.00015749289013911039,1.0082862377166748,0.08530672639608383 -3.0,70.0,0.30000000000000004,0.0,1115.839773344972,0.00015749289013911039,1.1936287879943848,0.09344689548015594 -3.0,70.0,0.30000000000000004,2.0,1115.839773344972,0.00015749289013911039,1.3786896467208862,0.10456270724534988 -3.0,70.0,0.30000000000000004,4.0,1115.839773344972,0.00015749289013911039,1.5634688138961792,0.11864113062620163 -3.0,70.0,0.30000000000000004,6.0,1115.839773344972,0.00015749289013911039,1.7479665279388428,0.13566912710666656 -3.0,70.0,0.30000000000000004,8.0,1115.839773344972,0.00015749289013911039,1.9321825504302979,0.1556336134672165 -3.0,70.0,0.30000000000000004,10.0,1115.839773344972,0.00015749289013911039,2.116116762161255,0.17852161824703217 -3.0,80.0,0.1,-2.0,1115.800883142221,0.0001575305504957214,1.0128179788589478,0.08831899613142014 -3.0,80.0,0.1,0.0,1115.800883142221,0.0001575305504957214,1.1930536031723022,0.09658235311508179 -3.0,80.0,0.1,2.0,1115.800883142221,0.0001575305504957214,1.373075008392334,0.10777528584003448 -3.0,80.0,0.1,4.0,1115.800883142221,0.0001575305504957214,1.552882194519043,0.12188774347305298 -3.0,80.0,0.1,6.0,1115.800883142221,0.0001575305504957214,1.7324752807617188,0.13890968263149261 -3.0,80.0,0.1,8.0,1115.800883142221,0.0001575305504957214,1.9118543863296509,0.15883107483386993 -3.0,80.0,0.1,10.0,1115.800883142221,0.0001575305504957214,2.0910191535949707,0.18164195120334625 -3.0,80.0,0.15000000000000002,-2.0,1115.800883142221,0.0001575305504957214,1.0121570825576782,0.0872318297624588 -3.0,80.0,0.15000000000000002,0.0,1115.800883142221,0.0001575305504957214,1.1931071281433105,0.09544092416763306 -3.0,80.0,0.15000000000000002,2.0,1115.800883142221,0.0001575305504957214,1.3738412857055664,0.10657361894845963 -3.0,80.0,0.15000000000000002,4.0,1115.800883142221,0.0001575305504957214,1.5543595552444458,0.12061986327171326 -3.0,80.0,0.15000000000000002,6.0,1115.800883142221,0.0001575305504957214,1.7346618175506592,0.13756956160068512 -3.0,80.0,0.15000000000000002,8.0,1115.800883142221,0.0001575305504957214,1.914748191833496,0.15741266310214996 -3.0,80.0,0.15000000000000002,10.0,1115.800883142221,0.0001575305504957214,2.094618797302246,0.1801392138004303 -3.0,80.0,0.20000000000000004,-2.0,1115.800883142221,0.0001575305504957214,1.0112178325653076,0.08648291230201721 -3.0,80.0,0.20000000000000004,0.0,1115.800883142221,0.0001575305504957214,1.1931838989257812,0.09467526525259018 -3.0,80.0,0.20000000000000004,2.0,1115.800883142221,0.0001575305504957214,1.3749316930770874,0.10580411553382874 -3.0,80.0,0.20000000000000004,4.0,1115.800883142221,0.0001575305504957214,1.5564607381820679,0.11985926330089569 -3.0,80.0,0.20000000000000004,6.0,1115.800883142221,0.0001575305504957214,1.7377715110778809,0.13683058321475983 -3.0,80.0,0.20000000000000004,8.0,1115.800883142221,0.0001575305504957214,1.9188637733459473,0.15670786798000336 -3.0,80.0,0.20000000000000004,10.0,1115.800883142221,0.0001575305504957214,2.0997376441955566,0.17948104441165924 -3.0,80.0,0.25000000000000006,-2.0,1115.800883142221,0.0001575305504957214,1.0099854469299316,0.08589933067560196 -3.0,80.0,0.25000000000000006,0.0,1115.800883142221,0.0001575305504957214,1.1932858228683472,0.09409979730844498 -3.0,80.0,0.25000000000000006,2.0,1115.800883142221,0.0001575305504957214,1.3763642311096191,0.10526444762945175 -3.0,80.0,0.25000000000000006,4.0,1115.800883142221,0.0001575305504957214,1.5592209100723267,0.11938298493623734 -3.0,80.0,0.25000000000000006,6.0,1115.800883142221,0.0001575305504957214,1.7418557405471802,0.1364450454711914 -3.0,80.0,0.25000000000000006,8.0,1115.800883142221,0.0001575305504957214,1.9242689609527588,0.1564403474330902 -3.0,80.0,0.25000000000000006,10.0,1115.800883142221,0.0001575305504957214,2.1064600944519043,0.17935845255851746 -3.0,80.0,0.30000000000000004,-2.0,1115.800883142221,0.0001575305504957214,1.0084398984909058,0.08540849387645721 -3.0,80.0,0.30000000000000004,0.0,1115.800883142221,0.0001575305504957214,1.1934151649475098,0.09363707900047302 -3.0,80.0,0.30000000000000004,2.0,1115.800883142221,0.0001575305504957214,1.378164291381836,0.10487139225006104 -3.0,80.0,0.30000000000000004,4.0,1115.800883142221,0.0001575305504957214,1.5626875162124634,0.11910085380077362 -3.0,80.0,0.30000000000000004,6.0,1115.800883142221,0.0001575305504957214,1.7469844818115234,0.13631485402584076 -3.0,80.0,0.30000000000000004,8.0,1115.800883142221,0.0001575305504957214,1.9310554265975952,0.15650281310081482 -3.0,80.0,0.30000000000000004,10.0,1115.800883142221,0.0001575305504957214,2.1149003505706787,0.17965418100357056 -3.0,90.0,0.1,-2.0,1115.761991656717,0.00015756834181956947,1.012925148010254,0.08839645981788635 -3.0,90.0,0.1,0.0,1115.761991656717,0.00015756834181956947,1.1929042339324951,0.0967240110039711 -3.0,90.0,0.1,2.0,1115.761991656717,0.00015756834181956947,1.3727079629898071,0.10800234228372574 -3.0,90.0,0.1,4.0,1115.761991656717,0.00015756834181956947,1.5523362159729004,0.12222316861152649 -3.0,90.0,0.1,6.0,1115.761991656717,0.00015756834181956947,1.7317891120910645,0.13937819004058838 -3.0,90.0,0.1,8.0,1115.761991656717,0.00015756834181956947,1.9110664129257202,0.15945912897586823 -3.0,90.0,0.1,10.0,1115.761991656717,0.00015756834181956947,2.0901684761047363,0.18245773017406464 -3.0,90.0,0.15000000000000002,-2.0,1115.761991656717,0.00015756834181956947,1.0122647285461426,0.08730826526880264 -3.0,90.0,0.15000000000000002,0.0,1115.761991656717,0.00015756834181956947,1.1929574012756348,0.09558112174272537 -3.0,90.0,0.15000000000000002,2.0,1115.761991656717,0.00015756834181956947,1.3734731674194336,0.10679875314235687 -3.0,90.0,0.15000000000000002,4.0,1115.761991656717,0.00015756834181956947,1.5538119077682495,0.12095282226800919 -3.0,90.0,0.15000000000000002,6.0,1115.761991656717,0.00015756834181956947,1.733973741531372,0.13803507387638092 -3.0,90.0,0.15000000000000002,8.0,1115.761991656717,0.00015756834181956947,1.9139589071273804,0.15803715586662292 -3.0,90.0,0.15000000000000002,10.0,1115.761991656717,0.00015756834181956947,2.093766927719116,0.1809508204460144 -3.0,90.0,0.20000000000000004,-2.0,1115.761991656717,0.00015756834181956947,1.0113261938095093,0.08655847609043121 -3.0,90.0,0.20000000000000004,0.0,1115.761991656717,0.00015756834181956947,1.1930333375930786,0.09481444209814072 -3.0,90.0,0.20000000000000004,2.0,1115.761991656717,0.00015756834181956947,1.3745615482330322,0.10602818429470062 -3.0,90.0,0.20000000000000004,4.0,1115.761991656717,0.00015756834181956947,1.5559108257293701,0.12019127607345581 -3.0,90.0,0.20000000000000004,6.0,1115.761991656717,0.00015756834181956947,1.7370810508728027,0.13729533553123474 -3.0,90.0,0.20000000000000004,8.0,1115.761991656717,0.00015756834181956947,1.91807222366333,0.1573319435119629 -3.0,90.0,0.20000000000000004,10.0,1115.761991656717,0.00015756834181956947,2.0988845825195312,0.18029280006885529 -3.0,90.0,0.25000000000000006,-2.0,1115.761991656717,0.00015756834181956947,1.0100946426391602,0.0859740823507309 -3.0,90.0,0.25000000000000006,0.0,1115.761991656717,0.00015756834181956947,1.193134069442749,0.09423820674419403 -3.0,90.0,0.25000000000000006,2.0,1115.761991656717,0.00015756834181956947,1.375991702079773,0.10548800975084305 -3.0,90.0,0.25000000000000006,4.0,1115.761991656717,0.00015756834181956947,1.558667778968811,0.11971497535705566 -3.0,90.0,0.25000000000000006,6.0,1115.761991656717,0.00015756834181956947,1.7411619424819946,0.136910542845726 -3.0,90.0,0.25000000000000006,8.0,1115.761991656717,0.00015756834181956947,1.9234745502471924,0.1570662260055542 -3.0,90.0,0.25000000000000006,10.0,1115.761991656717,0.00015756834181956947,2.105605363845825,0.18017342686653137 -3.0,90.0,0.30000000000000004,-2.0,1115.761991656717,0.00015756834181956947,1.0085501670837402,0.0854824036359787 -3.0,90.0,0.30000000000000004,0.0,1115.761991656717,0.00015756834181956947,1.1932621002197266,0.09377486258745193 -3.0,90.0,0.30000000000000004,2.0,1115.761991656717,0.00015756834181956947,1.377788782119751,0.10509484261274338 -3.0,90.0,0.30000000000000004,4.0,1115.761991656717,0.00015756834181956947,1.5621304512023926,0.11943360418081284 -3.0,90.0,0.30000000000000004,6.0,1115.761991656717,0.00015756834181956947,1.7462867498397827,0.13678237795829773 -3.0,90.0,0.30000000000000004,8.0,1115.761991656717,0.00015756834181956947,1.9302579164505005,0.15713243186473846 -3.0,90.0,0.30000000000000004,10.0,1115.761991656717,0.00015756834181956947,2.114043712615967,0.18047502636909485 +2.0,0.0,0.1,-2.0,1116.112166363834,0.0001572293695062,0.3581807976630368,0.056246583196763913 +2.0,0.0,0.1,0.0,1116.112166363834,0.0001572293695062,0.5627232602714562,0.05850674898635615 +2.0,0.0,0.1,2.0,1116.112166363834,0.0001572293695062,0.7605351126670163,0.06199402849261314 +2.0,0.0,0.1,4.0,1116.112166363834,0.0001572293695062,0.9516163548497173,0.066584145893255 +2.0,0.0,0.1,6.0,1116.112166363834,0.0001572293695062,1.1359669868195588,0.07215601242300616 +2.0,0.0,0.1,8.0,1116.112166363834,0.0001572293695062,1.3135870085765413,0.07859182530555575 +2.0,0.0,0.1,10.0,1116.112166363834,0.0001572293695062,1.4844764201206644,0.08577716473552566 +2.0,0.0,0.15,-2.0,1116.112166363834,0.0001572293695062,0.357682173129843,0.055327866831523465 +2.0,0.0,0.15,0.0,1116.112166363834,0.0001572293695062,0.563073686766987,0.05757617464686843 +2.0,0.0,0.15,2.0,1116.112166363834,0.0001572293695062,0.7616787770571942,0.061050027916613264 +2.0,0.0,0.15,4.0,1116.112166363834,0.0001572293695062,0.9534974440004647,0.06562478524740471 +2.0,0.0,0.15,6.0,1116.112166363834,0.0001572293695062,1.1385296875967983,0.07117901579001244 +2.0,0.0,0.15,8.0,1116.112166363834,0.0001572293695062,1.3167755078461953,0.07759459927943035 +2.0,0.0,0.15,10.0,1116.112166363834,0.0001572293695062,1.4882349047486554,0.08475682409322859 +2.0,0.0,0.2,-2.0,1116.112166363834,0.0001572293695062,0.3569730668569747,0.054718649012048266 +2.0,0.0,0.2,0.0,1116.112166363834,0.0001572293695062,0.5635725019800485,0.05696559516032092 +2.0,0.0,0.2,2.0,1116.112166363834,0.0001572293695062,0.763305719180241,0.06044443314247412 +2.0,0.0,0.2,4.0,1116.112166363834,0.0001572293695062,0.9561727184575524,0.065029127139095 +2.0,0.0,0.2,6.0,1116.112166363834,0.0001572293695062,1.1421734998119824,0.0705969081040508 +2.0,0.0,0.2,8.0,1116.112166363834,0.0001572293695062,1.321308063243531,0.07702837610493292 +2.0,0.0,0.2,10.0,1116.112166363834,0.0001572293695062,1.4935764087521988,0.08420760062172811 +2.0,0.0,0.25,-2.0,1116.112166363834,0.0001572293695062,0.3560418359064719,0.054256873999652275 +2.0,0.0,0.25,0.0,1116.112166363834,0.0001572293695062,0.5642284009912781,0.05650951168386226 +2.0,0.0,0.25,2.0,1116.112166363834,0.0001572293695062,0.7654432059438034,0.060006578802327695 +2.0,0.0,0.25,4.0,1116.112166363834,0.0001572293695062,0.9596862507640482,0.06461976308233548 +2.0,0.0,0.25,6.0,1116.112166363834,0.0001572293695062,1.1469575354520118,0.07022410521602317 +2.0,0.0,0.25,8.0,1116.112166363834,0.0001572293695062,1.3272570600076947,0.07669810463951358 +2.0,0.0,0.25,10.0,1116.112166363834,0.0001572293695062,1.500584824431097,0.08392382318199744 +2.0,0.0,0.3,-2.0,1116.112166363834,0.0001572293695062,0.3548725732633496,0.05388138272239885 +2.0,0.0,0.3,0.0,1116.112166363834,0.0001572293695062,0.5650532970956581,0.05614565369430287 +2.0,0.0,0.3,2.0,1116.112166363834,0.0001572293695062,0.7681285297247111,0.059672721292116135 +2.0,0.0,0.3,4.0,1116.112166363834,0.0001572293695062,0.9640982711505086,0.06433111260447455 +2.0,0.0,0.3,6.0,1116.112166363834,0.0001572293695062,1.1529625213730508,0.06999282530637956 +2.0,0.0,0.3,8.0,1116.112166363834,0.0001572293695062,1.3347212803923372,0.07653343810806762 +2.0,0.0,0.3,10.0,1116.112166363834,0.0001572293695062,1.5093745482083685,0.08383221895390888 +2.0,10.0,0.1,-2.0,1116.0732851388082,0.0001572670153109,0.36327612400221293,0.05682011850096477 +2.0,10.0,0.1,0.0,1116.0732851388082,0.0001572670153109,0.5563391429032084,0.06011213386027378 +2.0,10.0,0.1,2.0,1116.0732851388082,0.0001572670153109,0.7468677944238651,0.06519634542359694 +2.0,10.0,0.1,4.0,1116.0732851388082,0.0001572670153109,0.9348620785641826,0.07200336484905276 +2.0,10.0,0.1,6.0,1116.0732851388082,0.0001572670153109,1.1203219953241614,0.08046451071320389 +2.0,10.0,0.1,8.0,1116.0732851388082,0.0001572670153109,1.3032475447038014,0.09051181645653995 +2.0,10.0,0.1,10.0,1116.0732851388082,0.0001572670153109,1.4836387267031024,0.1020780382685546 +2.0,10.0,0.15,-2.0,1116.0732851388082,0.0001572670153109,0.3628128478049574,0.05589412113881734 +2.0,10.0,0.15,0.0,1116.0732851388082,0.0001572670153109,0.5566469860087112,0.059167905469656834 +2.0,10.0,0.15,2.0,1116.0732851388082,0.0001572670153109,0.747925740760488,0.06423125883365223 +2.0,10.0,0.15,4.0,1116.0732851388082,0.0001572670153109,0.9366491120602881,0.07101459407566452 +2.0,10.0,0.15,6.0,1116.0732851388082,0.0001572670153109,1.1228170999081113,0.07944903616511717 +2.0,10.0,0.15,8.0,1116.0732851388082,0.0001572670153109,1.3064297043039577,0.08946643023033414 +2.0,10.0,0.15,10.0,1116.0732851388082,0.0001572670153109,1.487486925247827,0.10099934953149896 +2.0,10.0,0.2,-2.0,1116.0732851388082,0.0001572670153109,0.362154229671252,0.055278537404276254 +2.0,10.0,0.2,0.0,1116.0732851388082,0.0001572670153109,0.5570849935407298,0.05854928043395964 +2.0,10.0,0.2,2.0,1116.0732851388082,0.0001572670153109,0.7494303278310587,0.06361835808053191 +2.0,10.0,0.2,4.0,1116.0732851388082,0.0001572670153109,0.9391902325422385,0.0704154125959492 +2.0,10.0,0.2,6.0,1116.0732851388082,0.0001572670153109,1.1263647076742693,0.0788708108207261 +2.0,10.0,0.2,8.0,1116.0732851388082,0.0001572670153109,1.3109537532271511,0.08891565240277605 +2.0,10.0,0.2,10.0,1116.0732851388082,0.0001572670153109,1.4929573692008842,0.10048177795302995 +2.0,10.0,0.25,-2.0,1116.0732851388082,0.0001572670153109,0.36128969202917705,0.05481056961507896 +2.0,10.0,0.25,0.0,1116.0732851388082,0.0001572670153109,0.5576605928737949,0.058088360172578055 +2.0,10.0,0.25,2.0,1116.0732851388082,0.0001572670153109,0.7514063229086335,0.06318211632927181 +2.0,10.0,0.25,4.0,1116.0732851388082,0.0001572670153109,0.942526882133693,0.07002022011438505 +2.0,10.0,0.25,6.0,1116.0732851388082,0.0001572670153109,1.1310222705489732,0.07853179725269974 +2.0,10.0,0.25,8.0,1116.0732851388082,0.0001572670153109,1.3168924881544743,0.08864672565922783 +2.0,10.0,0.25,10.0,1116.0732851388082,0.0001572670153109,1.5001375349501962,0.10029564386795048 +2.0,10.0,0.3,-2.0,1116.0732851388082,0.0001572670153109,0.36020479804074984,0.05442863174747856 +2.0,10.0,0.3,0.0,1116.0732851388082,0.0001572670153109,0.5583839486370616,0.057721883091454526 +2.0,10.0,0.3,2.0,1116.0732851388082,0.0001572670153109,0.7538875728609785,0.06285704296489543 +2.0,10.0,0.3,4.0,1116.0732851388082,0.0001572670153109,0.9467156707125004,0.06976074288656177 +2.0,10.0,0.3,6.0,1116.0732851388082,0.0001572670153109,1.1368682421916274,0.0783603841455698 +2.0,10.0,0.3,8.0,1116.0732851388082,0.0001572670153109,1.3243452872983594,0.08858414667064675 +2.0,10.0,0.3,10.0,1116.0732851388082,0.0001572670153109,1.5091468060326965,0.10036099782976954 +2.0,20.0,0.1,-2.0,1116.0343369575487,0.0001573046320118,0.3652698350684723,0.05714706453474812 +2.0,20.0,0.1,0.0,1116.0343369575487,0.0001573046320118,0.5536916842500864,0.06099245441377439 +2.0,20.0,0.1,2.0,1116.0343369575487,0.0001573046320118,0.7407228601504261,0.0669188309312379 +2.0,20.0,0.1,4.0,1116.0343369575487,0.0001573046320118,0.9263633627694912,0.07488142387435026 +2.0,20.0,0.1,6.0,1116.0343369575487,0.0001573046320118,1.110613192107282,0.0848357203200902 +2.0,20.0,0.1,8.0,1116.0343369575487,0.0001573046320118,1.2934723481637982,0.09673746618722383 +2.0,20.0,0.1,10.0,1116.0343369575487,0.0001573046320118,1.4749408309390402,0.1105426677816702 +2.0,20.0,0.15,-2.0,1116.0343369575487,0.0001573046320118,0.3648166400765763,0.056217153045066345 +2.0,20.0,0.15,0.0,1116.0343369575487,0.0001573046320118,0.5539872507481591,0.06004108133957432 +2.0,20.0,0.15,2.0,1116.0343369575487,0.0001573046320118,0.741755656073491,0.06594294654464339 +2.0,20.0,0.15,4.0,1116.0343369575487,0.0001573046320118,0.9281218560525719,0.07387785002883823 +2.0,20.0,0.15,6.0,1116.0343369575487,0.0001573046320118,1.1130858506854022,0.08380115234002154 +2.0,20.0,0.15,8.0,1116.0343369575487,0.0001573046320118,1.2966476399719815,0.09566847477475493 +2.0,20.0,0.15,10.0,1116.0343369575487,0.0001573046320118,1.4788072239123096,0.10943570094093852 +2.0,20.0,0.2,-2.0,1116.0343369575487,0.0001573046320118,0.3641723895047947,0.05559800668661046 +2.0,20.0,0.2,0.0,1116.0343369575487,0.0001573046320118,0.5544077746460891,0.05941819612382449 +2.0,20.0,0.2,2.0,1116.0343369575487,0.0001573046320118,0.7432244673498813,0.06532649194682032 +2.0,20.0,0.2,4.0,1116.0343369575487,0.0001573046320118,0.9306224676161714,0.07327749830750736 +2.0,20.0,0.2,6.0,1116.0343369575487,0.0001573046320118,1.1166017754449593,0.08322608306467248 +2.0,20.0,0.2,8.0,1116.0343369575487,0.0001573046320118,1.3011623908362449,0.0951273793894497 +2.0,20.0,0.2,10.0,1116.0343369575487,0.0001573046320118,1.4843043137900285,0.10893678736382664 +2.0,20.0,0.25,-2.0,1116.0343369575487,0.0001573046320118,0.3633267750662056,0.05512655800763429 +2.0,20.0,0.25,0.0,1116.0343369575487,0.0001573046320118,0.5549603694265239,0.05895476593891305 +2.0,20.0,0.25,2.0,1116.0343369575487,0.0001573046320118,0.7451534643027252,0.06489154059423813 +2.0,20.0,0.25,4.0,1116.0343369575487,0.0001573046320118,0.9339060596948094,0.07289067297724332 +2.0,20.0,0.25,6.0,1116.0343369575487,0.0001573046320118,1.1212181556027765,0.08290622474054983 +2.0,20.0,0.25,8.0,1116.0343369575487,0.0001573046320118,1.3070897520266263,0.09489252984515653 +2.0,20.0,0.25,10.0,1116.0343369575487,0.0001573046320118,1.4915208489663592,0.1088041962125696 +2.0,20.0,0.3,-2.0,1116.0343369575487,0.0001573046320118,0.3622657299129493,0.05474098362121492 +2.0,20.0,0.3,0.0,1116.0343369575487,0.0001573046320118,0.5556547691805642,0.058586999681294334 +2.0,20.0,0.3,2.0,1116.0343369575487,0.0001573046320118,0.7475756775574882,0.06457169061704952 +2.0,20.0,0.3,4.0,1116.0343369575487,0.0001573046320118,0.9380284550437216,0.07264771792657312 +2.0,20.0,0.3,6.0,1116.0343369575487,0.0001573046320118,1.127013101639264,0.08276802323105016 +2.0,20.0,0.3,8.0,1116.0343369575487,0.0001573046320118,1.3145296173441154,0.09488583000737327 +2.0,20.0,0.3,10.0,1116.0343369575487,0.0001573046320118,1.500578002158276,0.10895464531309319 +2.0,30.0,0.1,-2.0,1115.9954531665346,0.0001573422778164,0.3664571126766803,0.057354359726653106 +2.0,30.0,0.1,0.0,1115.9954531665346,0.0001573422778164,0.5520629565759704,0.061528918087872864 +2.0,30.0,0.1,2.0,1115.9954531665346,0.0001573422778164,0.7367854235575415,0.0679482211038907 +2.0,30.0,0.1,4.0,1115.9954531665346,0.0001573422778164,0.9206245136213939,0.07658128356774421 +2.0,30.0,0.1,6.0,1115.9954531665346,0.0001573422778164,1.1035802267675274,0.08739723552606105 +2.0,30.0,0.1,8.0,1115.9954531665346,0.0001573422778164,1.285652562995942,0.10036532271382873 +2.0,30.0,0.1,10.0,1115.9954531665346,0.0001573422778164,1.4668415223066378,0.11545490698795328 +2.0,30.0,0.15,-2.0,1115.9954531665346,0.0001573422778164,0.3660093164712108,0.0564221021211547 +2.0,30.0,0.15,0.0,1115.9954531665346,0.0001573422778164,0.5523516869099772,0.06057330676211463 +2.0,30.0,0.15,2.0,1115.9954531665346,0.0001573422778164,0.7378033550871418,0.0669659860494213 +2.0,30.0,0.15,4.0,1115.9954531665346,0.0001573422778164,0.922364321002705,0.07556906570875137 +2.0,30.0,0.15,6.0,1115.9954531665346,0.0001573422778164,1.1060345846566664,0.08635158756450415 +2.0,30.0,0.15,8.0,1115.9954531665346,0.0001573422778164,1.2888141460490266,0.09928270997944519 +2.0,30.0,0.15,10.0,1115.9954531665346,0.0001573422778164,1.470703005179785,0.11433170829311905 +2.0,30.0,0.2,-2.0,1115.9954531665346,0.0001573422778164,0.3653727531988231,0.05580072248576051 +2.0,30.0,0.2,0.0,1115.9954531665346,0.0001573422778164,0.5527624841294323,0.05994779848845297 +2.0,30.0,0.2,2.0,1115.9954531665346,0.0001573422778164,0.7392510399461546,0.06634733768203524 +2.0,30.0,0.2,4.0,1115.9954531665346,0.0001573422778164,0.9248384206489902,0.07496792152479198 +2.0,30.0,0.2,6.0,1115.9954531665346,0.0001573422778164,1.109524626237939,0.085778249599505 +2.0,30.0,0.2,8.0,1115.9954531665346,0.0001573422778164,1.2933096567130011,0.09874714006320587 +2.0,30.0,0.2,10.0,1115.9954531665346,0.0001573422778164,1.4761935120741767,0.11384353009566137 +2.0,30.0,0.25,-2.0,1115.9954531665346,0.0001573422778164,0.36453725113847346,0.055327098731156626 +2.0,30.0,0.25,0.0,1115.9954531665346,0.0001573422778164,0.5533022968043141,0.059482800665457546 +2.0,30.0,0.25,2.0,1115.9954531665346,0.0001573422778164,0.7411523151870469,0.06591306168972569 +2.0,30.0,0.25,4.0,1115.9954531665346,0.0001573422778164,0.928087306286672,0.07458590028176378 +2.0,30.0,0.25,6.0,1115.9954531665346,0.0001573422778164,1.1141072701031896,0.08546945615037635 +2.0,30.0,0.25,8.0,1115.9954531665346,0.0001573422778164,1.2992122066365994,0.09853199070023459 +2.0,30.0,0.25,10.0,1115.9954531665346,0.0001573422778164,1.4834021158869015,0.11374188749542011 +2.0,30.0,0.3,-2.0,1115.9954531665346,0.0001573422778164,0.3634889306766323,0.05493925735455434 +2.0,30.0,0.3,0.0,1115.9954531665346,0.0001573422778164,0.553980633373929,0.059114199613752944 +2.0,30.0,0.3,2.0,1115.9954531665346,0.0001573422778164,0.7435397568964551,0.06559621149868436 +2.0,30.0,0.3,4.0,1115.9954531665346,0.0001573422778164,0.9321663012442107,0.07435252948926341 +2.0,30.0,0.3,6.0,1115.9954531665346,0.0001573422778164,1.119860266417196,0.08535051553605909 +2.0,30.0,0.3,8.0,1115.9954531665346,0.0001573422778164,1.3066216524154104,0.09855765754568198 +2.0,30.0,0.3,10.0,1115.9954531665346,0.0001573422778164,1.4924504592388546,0.11394156986477752 +2.0,40.0,0.1,-2.0,1115.956568093438,0.0001573799236211,0.3672284055999665,0.05749207198657447 +2.0,40.0,0.1,0.0,1115.956568093438,0.0001573799236211,0.5509881765451979,0.06187550243737319 +2.0,40.0,0.1,2.0,1115.956568093438,0.0001573799236211,0.7341384354587897,0.06860401847096148 +2.0,40.0,0.1,4.0,1115.956568093438,0.0001573799236211,0.9166791823407417,0.07765512077716111 +2.0,40.0,0.1,6.0,1115.956568093438,0.0001573799236211,1.098610417191054,0.08900636854100163 +2.0,40.0,0.1,8.0,1115.956568093438,0.0001573799236211,1.2799321400097265,0.10263537959331455 +2.0,40.0,0.1,10.0,1115.956568093438,0.0001573799236211,1.4606443507967595,0.11851983056103313 +2.0,40.0,0.15,-2.0,1115.956568093438,0.0001573799236211,0.36678396800181823,0.05655835992458627 +2.0,40.0,0.15,0.0,1115.956568093438,0.0001573799236211,0.5512725502696132,0.06091724702854874 +2.0,40.0,0.15,2.0,1115.956568093438,0.0001573799236211,0.7351465661680978,0.0676178221139075 +2.0,40.0,0.15,4.0,1115.956568093438,0.0001573799236211,0.9184060156972724,0.07663752107391199 +2.0,40.0,0.15,6.0,1115.956568093438,0.0001573799236211,1.101050898857137,0.08795383872561197 +2.0,40.0,0.15,8.0,1115.956568093438,0.0001573799236211,1.2830812156476912,0.10154432896214097 +2.0,40.0,0.15,10.0,1115.956568093438,0.0001573799236211,1.4644969660689353,0.1173866049047008 +2.0,40.0,0.2,-2.0,1115.956568093438,0.0001573799236211,0.36615218512824915,0.05593550211237669 +2.0,40.0,0.2,0.0,1115.956568093438,0.0001573799236211,0.5516771509295967,0.06029001885150703 +2.0,40.0,0.2,2.0,1115.956568093438,0.0001573799236211,0.7365803243074488,0.06699772026190369 +2.0,40.0,0.2,4.0,1115.956568093438,0.0001573799236211,0.9208617052618056,0.07603579216991174 +2.0,40.0,0.2,6.0,1115.956568093438,0.0001573799236211,1.1045212937926667,0.08738148035308303 +2.0,40.0,0.2,8.0,1115.956568093438,0.0001573799236211,1.287559089900033,0.10101209069596227 +2.0,40.0,0.2,10.0,1115.956568093438,0.0001573799236211,1.4699750935839035,0.11690498934556522 +2.0,40.0,0.25,-2.0,1115.956568093438,0.0001573799236211,0.36532296812724263,0.055460444282276956 +2.0,40.0,0.25,0.0,1115.956568093438,0.0001573799236211,0.5522088243511887,0.05982397912284272 +2.0,40.0,0.25,2.0,1115.956568093438,0.0001573799236211,0.7384633304377857,0.06656380533744147 +2.0,40.0,0.25,4.0,1115.956568093438,0.0001573799236211,0.9240864863870335,0.07565669983682288 +2.0,40.0,0.25,6.0,1115.956568093438,0.0001573799236211,1.1090782921989326,0.08707950105859026 +2.0,40.0,0.25,8.0,1115.956568093438,0.0001573799236211,1.2934387478734826,0.10080910912822262 +2.0,40.0,0.25,10.0,1115.956568093438,0.0001573799236211,1.4771678534106836,0.11682248601977617 +2.0,40.0,0.3,-2.0,1115.956568093438,0.0001573799236211,0.3642825508838088,0.055071112590098184 +2.0,40.0,0.3,0.0,1115.956568093438,0.0001573799236211,0.5528769385255453,0.05945480467363798 +2.0,40.0,0.3,2.0,1115.956568093438,0.0001573799236211,0.7408278655831554,0.06624878199232044 +2.0,40.0,0.3,4.0,1115.956568093438,0.0001573799236211,0.9281353320566388,0.07542925346617282 +2.0,40.0,0.3,6.0,1115.956568093438,0.0001573799236211,1.1147993379459957,0.08697249169250343 +2.0,40.0,0.3,8.0,1115.956568093438,0.0001573799236211,1.300819883251226,0.10085483311403441 +2.0,40.0,0.3,10.0,1115.956568093438,0.0001573799236211,1.48619696797233,0.11705267818669621 +2.0,50.0,0.1,-2.0,1115.917615583849,0.0001574175112182,0.3677495544709777,0.05758627420118087 +2.0,50.0,0.1,0.0,1115.917615583849,0.0001574175112182,0.5502559710564555,0.062108040649137664 +2.0,50.0,0.1,2.0,1115.917615583849,0.0001574175112182,0.7323179352551734,0.06903974915713305 +2.0,50.0,0.1,4.0,1115.917615583849,0.0001574175112182,0.9139354470671315,0.07836445059886787 +2.0,50.0,0.1,6.0,1115.917615583849,0.0001574175112182,1.0951085064923296,0.09006522827095811 +2.0,50.0,0.1,8.0,1115.917615583849,0.0001574175112182,1.2758371135307678,0.10412519795333633 +2.0,50.0,0.1,10.0,1115.917615583849,0.0001574175112182,1.4561212681824458,0.12052750796956592 +2.0,50.0,0.15,-2.0,1115.917615583849,0.0001574175112182,0.3673073383951758,0.0566516573031046 +2.0,50.0,0.15,0.0,1115.917615583849,0.0001574175112182,0.5505374231208491,0.06114809905693566 +2.0,50.0,0.15,2.0,1115.917615583849,0.0001574175112182,0.7333193698681343,0.06805100708192942 +2.0,50.0,0.15,4.0,1115.917615583849,0.0001574175112182,0.9156531786370312,0.07734338336045639 +2.0,50.0,0.15,6.0,1115.917615583849,0.0001574175112182,1.0975388494275402,0.08900826253527191 +2.0,50.0,0.15,8.0,1115.917615583849,0.0001574175112182,1.2789763822396607,0.10302871197059528 +2.0,50.0,0.15,10.0,1115.917615583849,0.0001574175112182,1.4599657770733931,0.11938783181310081 +2.0,50.0,0.2,-2.0,1115.917615583849,0.0001574175112182,0.3666787168367251,0.05602778568159823 +2.0,50.0,0.2,0.0,1115.917615583849,0.0001574175112182,0.5509378688658173,0.06051969841927654 +2.0,50.0,0.2,2.0,1115.917615583849,0.0001574175112182,0.7347436137227028,0.0674299048092275 +2.0,50.0,0.2,4.0,1115.917615583849,0.0001574175112182,0.9180959514073814,0.0767412184096831 +2.0,50.0,0.2,6.0,1115.917615583849,0.0001574175112182,1.1009948819198534,0.08843648600846404 +2.0,50.0,0.2,8.0,1115.917615583849,0.0001574175112182,1.2834404052601185,0.1024985876854641 +2.0,50.0,0.2,10.0,1115.917615583849,0.0001574175112182,1.465432521428177,0.11891043687504378 +2.0,50.0,0.25,-2.0,1115.917615583849,0.0001574175112182,0.36585365505451384,0.055551748332364384 +2.0,50.0,0.25,0.0,1115.917615583849,0.0001574175112182,0.5514640859451153,0.06005294078130208 +2.0,50.0,0.25,2.0,1115.917615583849,0.0001574175112182,0.7366141402379471,0.0669961901282066 +2.0,50.0,0.25,4.0,1115.917615583849,0.0001574175112182,0.9213038179330091,0.0763640018244916 +2.0,50.0,0.25,6.0,1115.917615583849,0.0001574175112182,1.1055331190303015,0.08813891542414894 +2.0,50.0,0.25,8.0,1115.917615583849,0.0001574175112182,1.2893020435298241,0.10230350464833363 +2.0,50.0,0.25,10.0,1115.917615583849,0.0001574175112182,1.4726105914315772,0.11884037744985403 +2.0,50.0,0.3,-2.0,1115.917615583849,0.0001574175112182,0.36481846100446713,0.055161401891324 +2.0,50.0,0.3,0.0,1115.917615583849,0.0001574175112182,0.5521253492039198,0.059683361220376055 +2.0,50.0,0.3,2.0,1115.917615583849,0.0001574175112182,0.7389630299430512,0.06668233431919912 +2.0,50.0,0.3,4.0,1115.917615583849,0.0001574175112182,0.9253315032218612,0.0761403986763205 +2.0,50.0,0.3,6.0,1115.917615583849,0.0001574175112182,1.1112307690403498,0.08803966707430816 +2.0,50.0,0.3,8.0,1115.917615583849,0.0001574175112182,1.2966608273985172,0.10236228765720846 +2.0,50.0,0.3,10.0,1115.917615583849,0.0001574175112182,1.4816216782963632,0.11909044399788353 +2.0,60.0,0.1,-2.0,1115.878662265104,0.0001574552297824,0.3681103989689376,0.057652094819240676 +2.0,60.0,0.1,0.0,1115.878662265104,0.0001574552297824,0.5497467989984297,0.06226832256281439 +2.0,60.0,0.1,2.0,1115.878662265104,0.0001574552297824,0.7310457291125245,0.0693380705140113 +2.0,60.0,0.1,4.0,1115.878662265104,0.0001574552297824,0.912007189311222,0.07884818721408701 +2.0,60.0,0.1,6.0,1115.878662265104,0.0001574552297824,1.0926311795945223,0.09078554042811036 +2.0,60.0,0.1,8.0,1115.878662265104,0.0001574552297824,1.2729176999624252,0.10513701717200842 +2.0,60.0,0.1,10.0,1115.878662265104,0.0001574552297824,1.4528667504149309,0.12188952373958178 +2.0,60.0,0.15,-2.0,1115.878662265104,0.0001574552297824,0.3676697031784137,0.05671692936448659 +2.0,60.0,0.15,0.0,1115.878662265104,0.0001574552297824,0.5500262367781824,0.06130730392070814 +2.0,60.0,0.15,2.0,1115.878662265104,0.0001574552297824,0.7320425020158989,0.06834767353544416 +2.0,60.0,0.15,4.0,1115.878662265104,0.0001574552297824,0.9137184988915634,0.07782484875928497 +2.0,60.0,0.15,6.0,1115.878662265104,0.0001574552297824,1.0950542274051756,0.08972565950741161 +2.0,60.0,0.15,8.0,1115.878662265104,0.0001574552297824,1.2760496875567358,0.10403695508694477 +2.0,60.0,0.15,10.0,1115.878662265104,0.0001574552297824,1.4567048793462434,0.12074560422426307 +2.0,60.0,0.2,-2.0,1115.878662265104,0.0001574552297824,0.3670432448023227,0.05609234322114642 +2.0,60.0,0.2,0.0,1115.878662265104,0.0001574552297824,0.5504238182476836,0.060678080685484706 +2.0,60.0,0.2,2.0,1115.878662265104,0.0001574552297824,0.7334601224651063,0.06772586372468323 +2.0,60.0,0.2,4.0,1115.878662265104,0.0001574552297824,0.9161521574545907,0.0772223566602093 +2.0,60.0,0.2,6.0,1115.878662265104,0.0001574552297824,1.0984999232161368,0.08915424351549689 +2.0,60.0,0.2,8.0,1115.878662265104,0.0001574552297824,1.2805034197497447,0.10350822804392458 +2.0,60.0,0.2,10.0,1115.878662265104,0.0001574552297824,1.4621626470554143,0.12027103375676251 +2.0,60.0,0.25,-2.0,1115.878662265104,0.0001574552297824,0.3662210258615799,0.055615618697352265 +2.0,60.0,0.25,0.0,1115.878662265104,0.0001574552297824,0.5509462743396818,0.06021081502594228 +2.0,60.0,0.25,2.0,1115.878662265104,0.0001574552297824,0.7353219617486377,0.06729226274478256 +2.0,60.0,0.25,4.0,1115.878662265104,0.0001574552297824,0.9193480880884478,0.0768463870688909 +2.0,60.0,0.25,6.0,1115.878662265104,0.0001574552297824,1.1030246533591122,0.08885963343270696 +2.0,60.0,0.25,8.0,1115.878662265104,0.0001574552297824,1.2863516575606306,0.10331846751901111 +2.0,60.0,0.25,10.0,1115.878662265104,0.0001574552297824,1.469329100693003,0.12020937528781045 +2.0,60.0,0.3,-2.0,1115.878662265104,0.0001574552297824,0.3651894046190934,0.05522456288295481 +2.0,60.0,0.3,0.0,1115.878662265104,0.0001574552297824,0.5516028160798058,0.05984094313591488 +2.0,60.0,0.3,2.0,1115.878662265104,0.0001574552297824,0.73765996125271,0.06697918066101005 +2.0,60.0,0.3,4.0,1115.878662265104,0.0001574552297824,0.9233608401378061,0.0766253685534976 +2.0,60.0,0.3,6.0,1115.878662265104,0.0001574552297824,1.1087054527350941,0.08876562083429045 +2.0,60.0,0.3,8.0,1115.878662265104,0.0001574552297824,1.293693799044574,0.10338607248015329 +2.0,60.0,0.3,10.0,1115.878662265104,0.0001574552297824,1.4783258790662455,0.1204728794538644 +2.0,70.0,0.1,-2.0,1115.839773344972,0.0001574928901391,0.36836465692861,0.057698855037230073 +2.0,70.0,0.1,0.0,1115.839773344972,0.0001574928901391,0.5493873428853102,0.06238108441325743 +2.0,70.0,0.1,2.0,1115.839773344972,0.0001574928901391,0.7301456618046296,0.06954698904531027 +2.0,70.0,0.1,4.0,1115.839773344972,0.0001574928901391,0.9106396136865682,0.07918611165948602 +2.0,70.0,0.1,6.0,1115.839773344972,0.0001574928901391,1.0908691985311263,0.0912880070103051 +2.0,70.0,0.1,8.0,1115.839773344972,0.0001574928901391,1.2708344163383032,0.1058422418939163 +2.0,70.0,0.1,10.0,1115.839773344972,0.0001574928901391,1.4505352671080998,0.1228383951612911 +2.0,70.0,0.15,-2.0,1115.839773344972,0.0001574928901391,0.36792502513611175,0.05676337786826682 +2.0,70.0,0.15,0.0,1115.839773344972,0.0001574928901391,0.549665366528088,0.061419389095829946 +2.0,70.0,0.15,2.0,1115.839773344972,0.0001574928901391,0.7311391486367449,0.0685555188999345 +2.0,70.0,0.15,4.0,1115.839773344972,0.0001574928901391,0.9123463714620823,0.07816127975976793 +2.0,70.0,0.15,6.0,1115.839773344972,0.0001574928901391,1.0932870350041006,0.09022619627102674 +2.0,70.0,0.15,8.0,1115.839773344972,0.0001574928901391,1.2739611392627996,0.10473980515927028 +2.0,70.0,0.15,10.0,1115.839773344972,0.0001574928901391,1.4543686842381793,0.12169165529326309 +2.0,70.0,0.2,-2.0,1115.839773344972,0.0001574928901391,0.36730008060094155,0.05613827667994034 +2.0,70.0,0.2,0.0,1115.839773344972,0.0001574928901391,0.5500609372367786,0.06078957516947281 +2.0,70.0,0.2,2.0,1115.839773344972,0.0001574928901391,0.7325521003926971,0.06793319759093207 +2.0,70.0,0.2,4.0,1115.839773344972,0.0001574928901391,0.9147735700686968,0.07755854013748495 +2.0,70.0,0.2,6.0,1115.839773344972,0.0001574928901391,1.0967253462647777,0.08965501132985587 +2.0,70.0,0.2,8.0,1115.839773344972,0.0001574928901391,1.2784074289809397,0.10421203202998794 +2.0,70.0,0.2,10.0,1115.839773344972,0.0001574928901391,1.4598198182171829,0.12121903545469215 +2.0,70.0,0.25,-2.0,1115.839773344972,0.0001574928901391,0.36647985096294977,0.055661059462678644 +2.0,70.0,0.25,0.0,1115.839773344972,0.0001574928901391,0.5505807532706422,0.06032194206077757 +2.0,70.0,0.25,2.0,1115.839773344972,0.0001574928901391,0.7344078165781233,0.06749966139160517 +2.0,70.0,0.25,4.0,1115.839773344972,0.0001574928901391,0.9179610408853931,0.07718342350494457 +2.0,70.0,0.25,6.0,1115.839773344972,0.0001574928901391,1.101240426192452,0.08936244710184549 +2.0,70.0,0.25,8.0,1115.839773344972,0.0001574928901391,1.2842459724992998,0.10402596354874472 +2.0,70.0,0.25,10.0,1115.839773344972,0.0001574928901391,1.4669776798059362,0.12116321689157404 +2.0,70.0,0.3,-2.0,1115.839773344972,0.0001574928901391,0.3654507295368778,0.055269497136532966 +2.0,70.0,0.3,0.0,1115.839773344972,0.0001574928901391,0.5512339810319932,0.05995185528536187 +2.0,70.0,0.3,2.0,1115.839773344972,0.0001574928901391,0.7367381407955815,0.06718710619508596 +2.0,70.0,0.3,4.0,1115.839773344972,0.0001574928901391,0.9219632088276429,0.07696419180586585 +2.0,70.0,0.3,6.0,1115.839773344972,0.0001574928901391,1.1069091851281774,0.08927206715093691 +2.0,70.0,0.3,8.0,1115.839773344972,0.0001574928901391,1.2915760696971852,0.10409970037135359 +2.0,70.0,0.3,10.0,1115.839773344972,0.0001574928901391,1.4759638625346656,0.12143607273072035 +2.0,80.0,0.1,-2.0,1115.800883142221,0.0001575305504957,0.3685462364164036,0.057732534538757034 +2.0,80.0,0.1,0.0,1115.800883142221,0.0001575305504957,0.5491305834779425,0.062461718696191354 +2.0,80.0,0.1,2.0,1115.800883142221,0.0001575305504957,0.7295025963379671,0.0696959332283902 +2.0,80.0,0.1,4.0,1115.800883142221,0.0001575305504957,0.9096622749964773,0.07942669054798229 +2.0,80.0,0.1,6.0,1115.800883142221,0.0001575305504957,1.0896096194534732,0.09164551093412152 +2.0,80.0,0.1,8.0,1115.800883142221,0.0001575305504957,1.2693446297089548,0.1063439225394044 +2.0,80.0,0.1,10.0,1115.800883142221,0.0001575305504957,1.4488673057629222,0.12351346139678268 +2.0,80.0,0.15,-2.0,1115.800883142221,0.0001575305504957,0.3681073615433565,0.05679690778124362 +2.0,80.0,0.15,0.0,1115.800883142221,0.0001575305504957,0.5494076011850771,0.06149961809145971 +2.0,80.0,0.15,2.0,1115.800883142221,0.0001575305504957,0.7304937458581489,0.06870378210577763 +2.0,80.0,0.15,4.0,1115.800883142221,0.0001575305504957,0.9113657955625718,0.07840088765772471 +2.0,80.0,0.15,6.0,1115.800883142221,0.0001575305504957,1.0920237502983459,0.09058243050496764 +2.0,80.0,0.15,8.0,1115.800883142221,0.0001575305504957,1.272467610065471,0.10523991433630765 +2.0,80.0,0.15,10.0,1115.800883142221,0.0001575305504957,1.452697374863947,0.12236485077867072 +2.0,80.0,0.2,-2.0,1115.800883142221,0.0001575305504957,0.36748349390129814,0.0561714276309838 +2.0,80.0,0.2,0.0,1115.800883142221,0.0001575305504957,0.5498017416161304,0.06086937110801999 +2.0,80.0,0.2,2.0,1115.800883142221,0.0001575305504957,0.7319033770396592,0.06808108350641326 +2.0,80.0,0.2,4.0,1115.800883142221,0.0001575305504957,0.9137884001718843,0.07779795826938761 +2.0,80.0,0.2,6.0,1115.800883142221,0.0001575305504957,1.0954568110128062,0.09001139690230751 +2.0,80.0,0.2,8.0,1115.800883142221,0.0001575305504957,1.2769086095624242,0.10471280897983386 +2.0,80.0,0.2,10.0,1115.800883142221,0.0001575305504957,1.4581437958207388,0.12189361215307529 +2.0,80.0,0.25,-2.0,1115.800883142221,0.0001575305504957,0.3666646793102754,0.055693850229326346 +2.0,80.0,0.25,0.0,1115.800883142221,0.0001575305504957,0.5503196798562741,0.0604014668116553 +2.0,80.0,0.25,2.0,1115.800883142221,0.0001575305504957,0.733754738513793,0.06764758294116319 +2.0,80.0,0.25,4.0,1115.800883142221,0.0001575305504957,0.9169698552828323,0.07742343772056996 +2.0,80.0,0.25,6.0,1115.800883142221,0.0001575305504957,1.0999650301633919,0.08972027852640907 +2.0,80.0,0.25,8.0,1115.800883142221,0.0001575305504957,1.2827402631554716,0.10452936101642415 +2.0,80.0,0.25,10.0,1115.800883142221,0.0001575305504957,1.4652955542590718,0.12184194913696068 +2.0,80.0,0.3,-2.0,1115.800883142221,0.0001575305504957,0.36563733595654957,0.055301919480128386 +2.0,80.0,0.3,0.0,1115.800883142221,0.0001575305504957,0.5509705506623154,0.06003121910822003 +2.0,80.0,0.3,2.0,1115.800883142221,0.0001575305504957,0.7360796045931596,0.06733539373197252 +2.0,80.0,0.3,4.0,1115.800883142221,0.0001575305504957,0.9209644977490821,0.07720546807464987 +2.0,80.0,0.3,6.0,1115.800883142221,0.0001575305504957,1.105625230130083,0.08963247542222953 +2.0,80.0,0.3,8.0,1115.800883142221,0.0001575305504957,1.2900618017361623,0.1046074576311258 +2.0,80.0,0.3,10.0,1115.800883142221,0.0001575305504957,1.4742742125673196,0.12212146513590796 +2.0,90.0,0.1,-2.0,1115.761991656717,0.0001575683418195,0.36867731448048274,0.057757081951751964 +2.0,90.0,0.1,0.0,1115.761991656717,0.0001575683418195,0.5489454471164193,0.06252016153676748 +2.0,90.0,0.1,2.0,1115.761991656717,0.0001575683418195,0.7290395147297466,0.06980368149516802 +2.0,90.0,0.1,4.0,1115.761991656717,0.0001575683418195,0.9089595173204642,0.07960063151732652 +2.0,90.0,0.1,6.0,1115.761991656717,0.0001575683418195,1.0887054548885726,0.09190400663226483 +2.0,90.0,0.1,8.0,1115.761991656717,0.0001575683418195,1.2682773274340713,0.10670680721149436 +2.0,90.0,0.1,10.0,1115.761991656717,0.0001575683418195,1.4476751349569608,0.1240020389728549 +2.0,90.0,0.15,-2.0,1115.761991656717,0.0001575683418195,0.3682389849228787,0.05682141925734242 +2.0,90.0,0.15,0.0,1115.761991656717,0.0001575683418195,0.5492217420536922,0.06155784415359934 +2.0,90.0,0.15,2.0,1115.761991656717,0.0001575683418195,0.7300289907393627,0.06881112049388488 +2.0,90.0,0.15,4.0,1115.761991656717,0.0001575683418195,0.9106607309798902,0.07857421764449174 +2.0,90.0,0.15,6.0,1115.761991656717,0.0001575683418195,1.091116962775275,0.09084011034946857 +2.0,90.0,0.15,8.0,1115.761991656717,0.0001575683418195,1.271397686125517,0.10560177873450391 +2.0,90.0,0.15,10.0,1115.761991656717,0.0001575683418195,1.4515029010306157,0.12285220831080802 +2.0,90.0,0.2,-2.0,1115.761991656717,0.0001575683418195,0.3676158931030752,0.05619565467455594 +2.0,90.0,0.2,0.0,1115.761991656717,0.0001575683418195,0.5496148548610323,0.060927273347879785 +2.0,90.0,0.2,2.0,1115.761991656717,0.0001575683418195,0.7314362445504564,0.06818813805179529 +2.0,90.0,0.2,4.0,1115.761991656717,0.0001575683418195,0.9130800621713473,0.07797114018684694 +2.0,90.0,0.2,6.0,1115.761991656717,0.0001575683418195,1.0945463077237054,0.09026917662497799 +2.0,90.0,0.2,8.0,1115.761991656717,0.0001575683418195,1.2758349812075298,0.10507514971350373 +2.0,90.0,0.2,10.0,1115.761991656717,0.0001575683418195,1.4569460826228213,0.12238196727908279 +2.0,90.0,0.25,-2.0,1115.761991656717,0.0001575683418195,0.36679809792219503,0.055717809069073185 +2.0,90.0,0.25,0.0,1115.761991656717,0.0001575683418195,0.5501314440146811,0.06045916491361396 +2.0,90.0,0.25,2.0,1115.761991656717,0.0001575683418195,0.7332844885376697,0.06775465486158384 +2.0,90.0,0.25,4.0,1115.761991656717,0.0001575683418195,0.916257231491161,0.07759704282913857 +2.0,90.0,0.25,6.0,1115.761991656717,0.0001575683418195,1.0990496728751553,0.08997909834746969 +2.0,90.0,0.25,8.0,1115.761991656717,0.0001575683418195,1.281661812689652,0.10489359656691154 +2.0,90.0,0.25,10.0,1115.761991656717,0.0001575683418195,1.4640936509346514,0.12233331826104603 +2.0,90.0,0.3,-2.0,1115.761991656717,0.0001575683418195,0.3657720354611611,0.055325605698198804 +2.0,90.0,0.3,0.0,1115.761991656717,0.0001575683418195,0.5507806215935809,0.06008879431004613 +2.0,90.0,0.3,2.0,1115.761991656717,0.0001575683418195,0.7356054476436558,0.06744272339361844 +2.0,90.0,0.3,4.0,1115.761991656717,0.0001575683418195,0.9202465136113859,0.07737997978855357 +2.0,90.0,0.3,6.0,1115.761991656717,0.0001575683418195,1.1047038194967713,0.089893156145568 +2.0,90.0,0.3,8.0,1115.761991656717,0.0001575683418195,1.2889773652998118,0.10497485093074527 +2.0,90.0,0.3,10.0,1115.761991656717,0.0001575683418195,1.4730671510205071,0.12261766842982201 +3.0,0.0,0.1,-2.0,1116.112166363834,0.0001572293695062,1.0067335513219393,0.08175353446277281 +3.0,0.0,0.1,0.0,1116.112166363834,0.0001572293695062,1.2001949719397758,0.08519457484008673 +3.0,0.0,0.1,2.0,1116.112166363834,0.0001572293695062,1.386824359012703,0.08977365972994839 +3.0,0.0,0.1,4.0,1116.112166363834,0.0001572293695062,1.5666217125407211,0.09536083689557467 +3.0,0.0,0.1,6.0,1116.112166363834,0.0001572293695062,1.7395870325238298,0.10182986796331114 +3.0,0.0,0.1,8.0,1116.112166363834,0.0001572293695062,1.9102437545565323,0.10926910216217162 +3.0,0.0,0.1,10.0,1116.112166363834,0.0001572293695062,2.089658057015938,0.11822705416548285 +3.0,0.0,0.15,-2.0,1116.112166363834,0.0001572293695062,1.0060296065016268,0.08081126096997261 +3.0,0.0,0.15,0.0,1116.112166363834,0.0001572293695062,1.200296726837989,0.08423277387802364 +3.0,0.0,0.15,2.0,1116.112166363834,0.0001572293695062,1.387675159449181,0.08879093128625437 +3.0,0.0,0.15,4.0,1116.112166363834,0.0001572293695062,1.568164904335203,0.09435539935670885 +3.0,0.0,0.15,6.0,1116.112166363834,0.0001572293695062,1.7417659614960552,0.10079958538742234 +3.0,0.0,0.15,8.0,1116.112166363834,0.0001572293695062,1.9131405382597333,0.10821643748362494 +3.0,0.0,0.15,10.0,1116.112166363834,0.0001572293695062,2.093266069009761,0.11714756114656012 +3.0,0.0,0.2,-2.0,1116.112166363834,0.0001572293695062,1.0050288487688046,0.08018177692216916 +3.0,0.0,0.2,0.0,1116.112166363834,0.0001572293695062,1.2004422529691383,0.08359928630101342 +3.0,0.0,0.2,2.0,1116.112166363834,0.0001572293695062,1.388885972446658,0.0881594049590409 +3.0,0.0,0.2,4.0,1116.112166363834,0.0001572293695062,1.5703600072013637,0.09373034190616053 +3.0,0.0,0.2,6.0,1116.112166363834,0.0001572293695062,1.7448643572332552,0.10018411267059116 +3.0,0.0,0.2,8.0,1116.112166363834,0.0001572293695062,1.9172603387830662,0.10762084898559021 +3.0,0.0,0.2,10.0,1116.112166363834,0.0001572293695062,2.0983972445492367,0.11657611316350565 +3.0,0.0,0.25,-2.0,1116.112166363834,0.0001572293695062,1.0037152150540676,0.07969986769680033 +3.0,0.0,0.25,0.0,1116.112166363834,0.0001572293695062,1.2006348275973553,0.0831235721267507 +3.0,0.0,0.25,2.0,1116.112166363834,0.0001572293695062,1.3904776227965336,0.08770161971292502 +3.0,0.0,0.25,4.0,1116.112166363834,0.0001572293695062,1.5732436006516024,0.09329984033968594 +3.0,0.0,0.25,6.0,1116.112166363834,0.0001572293695062,1.7489327611625616,0.09978797065425611 +3.0,0.0,0.25,8.0,1116.112166363834,0.0001572293695062,1.9226710386389558,0.10727600303284268 +3.0,0.0,0.25,10.0,1116.112166363834,0.0001572293695062,2.1051359866493424,0.11629328663831968 +3.0,0.0,0.3,-2.0,1116.112166363834,0.0001572293695062,1.0020667837184696,0.07930307477696603 +3.0,0.0,0.3,0.0,1116.112166363834,0.0001572293695062,1.2008789870611896,0.08274140430760876 +3.0,0.0,0.3,2.0,1116.112166363834,0.0001572293695062,1.392478626799951,0.08735124853091561 +3.0,0.0,0.3,4.0,1116.112166363834,0.0001572293695062,1.5768657029347541,0.09299513403726992 +3.0,0.0,0.3,6.0,1116.112166363834,0.0001572293695062,1.754040215465599,0.09953963098499025 +3.0,0.0,0.3,8.0,1116.112166363834,0.0001572293695062,1.9294654093987924,0.10710754446156866 +3.0,0.0,0.3,10.0,1116.112166363834,0.0001572293695062,2.1135976348505214,0.11622130310854863 +3.0,10.0,0.1,-2.0,1116.0732851388082,0.0001572670153109,1.0090207364892587,0.08364637223696968 +3.0,10.0,0.1,0.0,1116.0732851388082,0.0001572670153109,1.1980424174986593,0.08908215006793581 +3.0,10.0,0.1,2.0,1116.0732851388082,0.0001572670153109,1.38449281029611,0.09643898159710675 +3.0,10.0,0.1,4.0,1116.0732851388082,0.0001572670153109,1.5683719148816104,0.10563853613875035 +3.0,10.0,0.1,6.0,1116.0732851388082,0.0001572670153109,1.7496797312551613,0.11660332082997615 +3.0,10.0,0.1,8.0,1116.0732851388082,0.0001572670153109,1.9284162594167618,0.12925668991100622 +3.0,10.0,0.1,10.0,1116.0732851388082,0.0001572670153109,2.1045814993664127,0.1435228539298083 +3.0,10.0,0.15,-2.0,1116.0732851388082,0.0001572670153109,1.0083412381712238,0.08267984221829668 +3.0,10.0,0.15,0.0,1116.0732851388082,0.0001572670153109,1.198118102223765,0.08808343717127468 +3.0,10.0,0.15,2.0,1116.0732851388082,0.0001572670153109,1.385302355829197,0.09540528682862562 +3.0,10.0,0.15,4.0,1116.0732851388082,0.0001572670153109,1.5698939989875194,0.10456683638392701 +3.0,10.0,0.15,6.0,1116.0732851388082,0.0001572670153109,1.7518930316987325,0.11549037501603734 +3.0,10.0,0.15,8.0,1116.0732851388082,0.0001572670153109,1.9312994539628359,0.12809904527306995 +3.0,10.0,0.15,10.0,1116.0732851388082,0.0001572670153109,2.10811326577983,0.14231685237951297 +3.0,10.0,0.2,-2.0,1116.0732851388082,0.0001572670153109,1.0073754694194037,0.08202980268732861 +3.0,10.0,0.2,0.0,1116.0732851388082,0.0001572670153109,1.1982262988257508,0.08742549150539278 +3.0,10.0,0.2,2.0,1116.0732851388082,0.0001572670153109,1.3864540339438485,0.09474885526512979 +3.0,10.0,0.2,4.0,1116.0732851388082,0.0001572670153109,1.5720586747736967,0.10392046971319603 +3.0,10.0,0.2,6.0,1116.0732851388082,0.0001572670153109,1.7550402213152956,0.11486176934225542 +3.0,10.0,0.2,8.0,1116.0732851388082,0.0001572670153109,1.9353986735686448,0.1274950569903335 +3.0,10.0,0.2,10.0,1116.0732851388082,0.0001572670153109,2.113134031533745,0.14174351336101404 +3.0,10.0,0.25,-2.0,1116.0732851388082,0.0001572670153109,1.0061081830117602,0.08152793987689344 +3.0,10.0,0.25,0.0,1116.0732851388082,0.0001572670153109,1.1983693962185542,0.08693149143430665 +3.0,10.0,0.25,2.0,1116.0732851388082,0.0001572670153109,1.3879671949535923,0.09428164920787571 +3.0,10.0,0.25,4.0,1116.0732851388082,0.0001572670153109,1.5749015792168746,0.10349756692896558 +3.0,10.0,0.25,6.0,1116.0732851388082,0.0001572670153109,1.7591725490084011,0.11449927970457646 +3.0,10.0,0.25,8.0,1116.0732851388082,0.0001572670153109,1.940780104328172,0.12720771393870547 +3.0,10.0,0.25,10.0,1116.0732851388082,0.0001572670153109,2.1197242451761866,0.1415446971711599 +3.0,10.0,0.3,-2.0,1116.0732851388082,0.0001572670153109,1.0045185868544788,0.0811104104576537 +3.0,10.0,0.3,0.0,1116.0732851388082,0.0001572670153109,1.1985507000413758,0.08653472529140335 +3.0,10.0,0.3,2.0,1116.0732851388082,0.0001572670153109,1.389868309610735,0.09393349662734915 +3.0,10.0,0.3,4.0,1116.0732851388082,0.0001572670153109,1.5784714155625559,0.10322390290058972 +3.0,10.0,0.3,6.0,1116.0732851388082,0.0001572670153109,1.7643600178968388,0.11432403480438572 +3.0,10.0,0.3,8.0,1116.0732851388082,0.0001572670153109,1.9475341166135836,0.12715290564881002 +3.0,10.0,0.3,10.0,1116.0732851388082,0.0001572670153109,2.1279937117127905,0.14163046163224577 +3.0,20.0,0.1,-2.0,1116.0343369575487,0.0001573046320118,1.0102756346283577,0.08470467037308187 +3.0,20.0,0.1,0.0,1116.0343369575487,0.0001573046320118,1.1965085087207712,0.09118715075072972 +3.0,20.0,0.1,2.0,1116.0343369575487,0.0001573046320118,1.3813315566142648,0.09998247455545048 +3.0,20.0,0.1,4.0,1116.0343369575487,0.0001573046320118,1.564744778308838,0.1110391639921014 +3.0,20.0,0.1,6.0,1116.0343369575487,0.0001573046320118,1.7467481738044914,0.12430604679424426 +3.0,20.0,0.1,8.0,1116.0343369575487,0.0001573046320118,1.9273417431012247,0.1397322580634552 +3.0,20.0,0.1,10.0,1116.0343369575487,0.0001573046320118,2.106525486199039,0.15726724210039902 +3.0,20.0,0.15,-2.0,1116.0343369575487,0.0001573046320118,1.0096033216198614,0.083725062364456 +3.0,20.0,0.15,0.0,1116.0343369575487,0.0001573046320118,1.196576304884382,0.09016895526485101 +3.0,20.0,0.15,2.0,1116.0343369575487,0.0001573046320118,1.3821277710607205,0.0989223129480593 +3.0,20.0,0.15,4.0,1116.0343369575487,0.0001573046320118,1.5662577201488763,0.10993351007192427 +3.0,20.0,0.15,6.0,1116.0343369575487,0.0001573046320118,1.74896615214885,0.12315122906538428 +3.0,20.0,0.15,8.0,1116.0343369575487,0.0001573046320118,1.9302530670606415,0.13852446198837295 +3.0,20.0,0.15,10.0,1116.0343369575487,0.0001573046320118,2.11011846488425,0.15600251238335158 +3.0,20.0,0.2,-2.0,1116.0343369575487,0.0001573046320118,1.0086478029146526,0.083063763779288 +3.0,20.0,0.2,0.0,1116.0343369575487,0.0001573046320118,1.1966732573199779,0.08949797387351068 +3.0,20.0,0.2,2.0,1116.0343369575487,0.0001573046320118,1.3832604804789481,0.09825296683276531 +3.0,20.0,0.2,4.0,1116.0343369575487,0.0001573046320118,1.5684094723915627,0.10927654576567428 +3.0,20.0,0.2,6.0,1116.0343369575487,0.0001573046320118,1.7521202330578223,0.1225168269263478 +3.0,20.0,0.2,8.0,1116.0343369575487,0.0001573046320118,1.9343927624777266,0.13792224161701833 +3.0,20.0,0.2,10.0,1116.0343369575487,0.0001573046320118,2.115227060651275,0.15544153808205752 +3.0,20.0,0.25,-2.0,1116.0343369575487,0.0001573046320118,1.0073940338396794,0.08255093255561678 +3.0,20.0,0.25,0.0,1116.0343369575487,0.0001573046320118,1.1968015425523937,0.0889942174644831 +3.0,20.0,0.25,2.0,1116.0343369575487,0.0001573046320118,1.3847487126366287,0.097781045998596 +3.0,20.0,0.25,4.0,1116.0343369575487,0.0001573046320118,1.5712355440923842,0.10885828650959292 +3.0,20.0,0.25,6.0,1116.0343369575487,0.0001573046320118,1.7562620369196607,0.12217312873545105 +3.0,20.0,0.25,8.0,1116.0343369575487,0.0001573046320118,1.9398281911184578,0.13767308576700787 +3.0,20.0,0.25,10.0,1116.0343369575487,0.0001573046320118,2.1219340066887753,0.15530599600549624 +3.0,20.0,0.3,-2.0,1116.0343369575487,0.0001573046320118,1.0058215011581477,0.08212197142159877 +3.0,20.0,0.3,0.0,1116.0343369575487,0.0001573046320118,1.196964174315797,0.08858965530737609 +3.0,20.0,0.3,2.0,1116.0343369575487,0.0001573046320118,1.3866184968874318,0.09743437233537867 +3.0,20.0,0.3,4.0,1116.0343369575487,0.0001573046320118,1.5747844688730517,0.10860169241376452 +3.0,20.0,0.3,6.0,1116.0343369575487,0.0001573046320118,1.7614620902726572,0.12203751808365876 +3.0,20.0,0.3,8.0,1116.0343369575487,0.0001573046320118,1.9466513610862477,0.137688086572432 +3.0,20.0,0.3,10.0,1116.0343369575487,0.0001573046320118,2.130352281313824,0.155499971837495 +3.0,30.0,0.1,-2.0,1115.9954531665346,0.0001573422778164,1.0111431997975973,0.08536728232925894 +3.0,30.0,0.1,0.0,1115.9954531665346,0.0001573422778164,1.1953616981898822,0.0924677145483529 +3.0,30.0,0.1,2.0,1115.9954531665346,0.0001573422778164,1.3786854948702703,0.10210194943747086 +3.0,30.0,0.1,4.0,1115.9954531665346,0.0001573422778164,1.561114589838761,0.11423410262034595 +3.0,30.0,0.1,6.0,1115.9954531665346,0.0001573422778164,1.742648983095355,0.12882842650884826 +3.0,30.0,0.1,8.0,1115.9954531665346,0.0001573422778164,1.9232886746400522,0.14584931082043842 +3.0,30.0,0.1,10.0,1115.9954531665346,0.0001573422778164,2.1030336644728527,0.16526128309413382 +3.0,30.0,0.15,-2.0,1115.9954531665346,0.0001573422778164,1.0104750284397865,0.08437968790659617 +3.0,30.0,0.15,0.0,1115.9954531665346,0.0001573422778164,1.1954245633674836,0.09143779358331178 +3.0,30.0,0.15,2.0,1115.9954531665346,0.0001573422778164,1.3794719773293043,0.1010260186218025 +3.0,30.0,0.15,4.0,1115.9954531665346,0.0001573422778164,1.5626172703252488,0.11310837554349756 +3.0,30.0,0.15,6.0,1115.9954531665346,0.0001573422778164,1.744860442355317,0.12764901466062492 +3.0,30.0,0.15,8.0,1115.9954531665346,0.0001573422778164,1.9262014934195086,0.14461222459946413 +3.0,30.0,0.15,10.0,1115.9954531665346,0.0001573422778164,2.106640423517824,0.1639624328220878 +3.0,30.0,0.2,-2.0,1115.9954531665346,0.0001573422778164,1.009525409522703,0.08371141732683599 +3.0,30.0,0.2,0.0,1115.9954531665346,0.0001573422778164,1.1955144982336097,0.0907588280607318 +3.0,30.0,0.2,2.0,1115.9954531665346,0.0001573422778164,1.380590858865549,0.10034877284808354 +3.0,30.0,0.2,4.0,1115.9954531665346,0.0001573422778164,1.5647544914185212,0.11244486557890657 +3.0,30.0,0.2,6.0,1115.9954531665346,0.0001573422778164,1.7480053958925263,0.12701086033773987 +3.0,30.0,0.2,8.0,1115.9954531665346,0.0001573422778164,1.9303435722875646,0.14401065193892873 +3.0,30.0,0.2,10.0,1115.9954531665346,0.0001573422778164,2.111769020603636,0.1634082764603512 +3.0,30.0,0.25,-2.0,1115.9954531665346,0.0001573422778164,1.0082794059036713,0.0831918048154835 +3.0,30.0,0.25,0.0,1115.9954531665346,0.0001573422778164,1.1956335585699407,0.09024905173541875 +3.0,30.0,0.25,2.0,1115.9954531665346,0.0001573422778164,1.382060953404748,0.09987378881696493 +3.0,30.0,0.25,4.0,1115.9954531665346,0.0001573422778164,1.567561590408093,0.11202897804882185 +3.0,30.0,0.25,6.0,1115.9954531665346,0.0001573422778164,1.7521354695799758,0.1266777253003895 +3.0,30.0,0.25,8.0,1115.9954531665346,0.0001573422778164,1.9357825909203967,0.14378328087503456 +3.0,30.0,0.25,10.0,1115.9954531665346,0.0001573422778164,2.1185029544293554,0.16330904006173405 +3.0,30.0,0.3,-2.0,1115.9954531665346,0.0001573422778164,1.0067166519260777,0.08275578416221521 +3.0,30.0,0.3,0.0,1115.9954531665346,0.0001573422778164,1.1957845927918718,0.08983963290884715 +3.0,30.0,0.3,2.0,1115.9954531665346,0.0001573422778164,1.383907998921235,0.09952768797670761 +3.0,30.0,0.3,4.0,1115.9954531665346,0.0001573422778164,1.5710868703141674,0.11178200583541736 +3.0,30.0,0.3,6.0,1115.9954531665346,0.0001573422778164,1.7573212069706692,0.12656479186609085 +3.0,30.0,0.3,8.0,1115.9954531665346,0.0001573422778164,1.94261100889074,0.14383840093902456 +3.0,30.0,0.3,10.0,1115.9954531665346,0.0001573422778164,2.12695627607438,0.16356533798967335 +3.0,40.0,0.1,-2.0,1115.956568093438,0.0001573799236211,1.011744541645513,0.08580374970327269 +3.0,40.0,0.1,0.0,1115.956568093438,0.0001573799236211,1.1945430797293184,0.09329469960334079 +3.0,40.0,0.1,2.0,1115.956568093438,0.0001573799236211,1.3767248974265713,0.10345450629138644 +3.0,40.0,0.1,4.0,1115.956568093438,0.0001573799236211,1.5582899947372717,0.11625702770538464 +3.0,40.0,0.1,6.0,1115.956568093438,0.0001573799236211,1.7392383716614197,0.13167619111617632 +3.0,40.0,0.1,8.0,1115.956568093438,0.0001573799236211,1.9195700281990151,0.1496859933068356 +3.0,40.0,0.1,10.0,1115.956568093438,0.0001573799236211,2.0992849643500584,0.17026050075167834 +3.0,40.0,0.15,-2.0,1115.956568093438,0.0001573799236211,1.0110790594965886,0.08481102633359883 +3.0,40.0,0.15,0.0,1115.956568093438,0.0001573799236211,1.19460260263567,0.09225730386927532 +3.0,40.0,0.15,2.0,1115.956568093438,0.0001573799236211,1.3775043112757288,0.10236857733933812 +3.0,40.0,0.15,4.0,1115.956568093438,0.0001573799236211,1.5597841854167644,0.11511862941761095 +3.0,40.0,0.15,6.0,1115.956568093438,0.0001573799236211,1.741442225058777,0.1304813126186538 +3.0,40.0,0.15,8.0,1115.956568093438,0.0001573799236211,1.9224784302017672,0.14843054947914217 +3.0,40.0,0.15,10.0,1115.956568093438,0.0001573799236211,2.1028928008457344,0.16894033273888096 +3.0,40.0,0.2,-2.0,1115.956568093438,0.0001573799236211,1.0101332691492129,0.08413818851076446 +3.0,40.0,0.2,0.0,1115.956568093438,0.0001573799236211,1.1946877833268352,0.09157313995376742 +3.0,40.0,0.2,2.0,1115.956568093438,0.0001573799236211,1.3786131514927835,0.10168617965128285 +3.0,40.0,0.2,4.0,1115.956568093438,0.0001573799236211,1.5619093736470577,0.11445079975689376 +3.0,40.0,0.2,6.0,1115.956568093438,0.0001573799236211,1.7445764497896579,0.12984056348248849 +3.0,40.0,0.2,8.0,1115.956568093438,0.0001573799236211,1.9266143799205842,0.1478291052838114 +3.0,40.0,0.2,10.0,1115.956568093438,0.0001573799236211,2.108023164039836,0.16839013104563785 +3.0,40.0,0.25,-2.0,1115.956568093438,0.0001573799236211,1.008892300850461,0.08361414226163276 +3.0,40.0,0.25,0.0,1115.956568093438,0.0001573799236211,1.1948005983835337,0.09105942187474521 +3.0,40.0,0.25,2.0,1115.956568093438,0.0001573799236211,1.3800700791573892,0.10120909781599219 +3.0,40.0,0.25,4.0,1115.956568093438,0.0001573799236211,1.5647007431720277,0.1140361871636251 +3.0,40.0,0.25,6.0,1115.956568093438,0.0001573799236211,1.7486925904274493,0.12951377992151444 +3.0,40.0,0.25,8.0,1115.956568093438,0.0001573799236211,1.9320456209236538,0.14761503921093636 +3.0,40.0,0.25,10.0,1115.956568093438,0.0001573799236211,2.1147598346606413,0.16831320146196777 +3.0,40.0,0.3,-2.0,1115.956568093438,0.0001573799236211,1.00733588130089,0.08317351267542022 +3.0,40.0,0.3,0.0,1115.956568093438,0.0001573799236211,1.1949437879329843,0.09064679973710374 +3.0,40.0,0.3,2.0,1115.956568093438,0.0001573799236211,1.3819006241356626,0.10086318471555165 +3.0,40.0,0.3,4.0,1115.956568093438,0.0001573799236211,1.5682063899089251,0.11379502479772417 +3.0,40.0,0.3,6.0,1115.956568093438,0.0001573799236211,1.753861085252772,0.1294147526447004 +3.0,40.0,0.3,8.0,1115.956568093438,0.0001573799236211,1.938864710167203,0.14769487659193364 +3.0,40.0,0.3,10.0,1115.956568093438,0.0001573799236211,2.1232172646522183,0.16860798084909337 +3.0,50.0,0.1,-2.0,1115.917615583849,0.0001574175112182,1.0121641074712848,0.08610045059003181 +3.0,50.0,0.1,0.0,1115.917615583849,0.0001574175112182,1.1939639623583382,0.0938494048199696 +3.0,50.0,0.1,2.0,1115.917615583849,0.0001574175112182,1.3753145349528437,0.10435442257615962 +3.0,50.0,0.1,4.0,1115.917615583849,0.0001574175112182,1.5562158252548013,0.11759578012270626 +3.0,50.0,0.1,6.0,1115.917615583849,0.0001574175112182,1.7366678332642111,0.1335537920937346 +3.0,50.0,0.1,8.0,1115.917615583849,0.0001574175112182,1.9166705589810733,0.15220881156528268 +3.0,50.0,0.1,10.0,1115.917615583849,0.0001574175112182,2.0962240024053873,0.17354123012708825 +3.0,50.0,0.15,-2.0,1115.917615583849,0.0001574175112182,1.0115004462841115,0.08510434521930438 +3.0,50.0,0.15,0.0,1115.917615583849,0.0001574175112182,1.1940211703625598,0.09280708804438556 +3.0,50.0,0.15,2.0,1115.917615583849,0.0001574175112182,1.3760888865051621,0.10326192391389982 +3.0,50.0,0.15,4.0,1115.917615583849,0.0001574175112182,1.5577035947119184,0.11644907220951671 +3.0,50.0,0.15,6.0,1115.917615583849,0.0001574175112182,1.738865294982829,0.1323487909639017 +3.0,50.0,0.15,8.0,1115.917615583849,0.0001574175112182,1.919573987317893,0.15094137693341533 +3.0,50.0,0.15,10.0,1115.917615583849,0.0001574175112182,2.099829671717111,0.17220716567070496 +3.0,50.0,0.2,-2.0,1115.917615583849,0.0001574175112182,1.0105572476812548,0.0844284079786466 +3.0,50.0,0.2,0.0,1115.917615583849,0.0001574175112182,1.1941030589539865,0.09211940995979814 +3.0,50.0,0.2,2.0,1115.917615583849,0.0001574175112182,1.37719053583623,0.10257603750077307 +3.0,50.0,0.2,4.0,1115.917615583849,0.0001574175112182,1.559819678327985,0.11577829073177331 +3.0,50.0,0.2,6.0,1115.917615583849,0.0001574175112182,1.741990486429252,0.1317062091075301 +3.0,50.0,0.2,8.0,1115.917615583849,0.0001574175112182,1.9237029601400306,0.15033987148167535 +3.0,50.0,0.2,10.0,1115.917615583849,0.0001574175112182,2.104957099460321,0.17165939618100315 +3.0,50.0,0.25,-2.0,1115.917615583849,0.0001574175112182,1.0093196867507939,0.08390135861003745 +3.0,50.0,0.25,0.0,1115.917615583849,0.0001574175112182,1.194211550633146,0.09160301697297468 +3.0,50.0,0.25,2.0,1115.917615583849,0.0001574175112182,1.3786380349620455,0.10209748571262668 +3.0,50.0,0.25,4.0,1115.917615583849,0.0001574175112182,1.5625991397374925,0.11536440643917084 +3.0,50.0,0.25,6.0,1115.917615583849,0.0001574175112182,1.7460948649594865,0.13138346112032565 +3.0,50.0,0.25,8.0,1115.917615583849,0.0001574175112182,1.9291252106280279,0.15013437215822253 +3.0,50.0,0.25,10.0,1115.917615583849,0.0001574175112182,2.111690176743117,0.17159690246616188 +3.0,50.0,0.3,-2.0,1115.917615583849,0.0001574175112182,1.0077675516030609,0.08345761172863593 +3.0,50.0,0.3,0.0,1115.917615583849,0.0001574175112182,1.194349311631791,0.09118821035142288 +3.0,50.0,0.3,2.0,1115.917615583849,0.0001574175112182,1.380456765278705,0.1017516079504895 +3.0,50.0,0.3,4.0,1115.917615583849,0.0001574175112182,1.5660899125438028,0.11512694814685454 +3.0,50.0,0.3,6.0,1115.917615583849,0.0001574175112182,1.7512487534270842,0.13129341632894362 +3.0,50.0,0.3,8.0,1115.917615583849,0.0001574175112182,1.9359332879285494,0.15023023973285596 +3.0,50.0,0.3,10.0,1115.917615583849,0.0001574175112182,2.120143516048198,0.17191668752250922 +3.0,60.0,0.1,-2.0,1115.878662265104,0.0001574552297824,1.0124592869530569,0.08630671048874601 +3.0,60.0,0.1,0.0,1115.878662265104,0.0001574552297824,1.1935537263662062,0.09423159397153026 +3.0,60.0,0.1,2.0,1115.878662265104,0.0001574552297824,1.3743073277308684,0.10497114838618293 +3.0,60.0,0.1,4.0,1115.878662265104,0.0001574552297824,1.554720091047044,0.11851005866647517 +3.0,60.0,0.1,6.0,1115.878662265104,0.0001574552297824,1.7347920163147326,0.1348330324602456 +3.0,60.0,0.1,8.0,1115.878662265104,0.0001574552297824,1.914523103533934,0.1539248001615497 +3.0,60.0,0.1,10.0,1115.878662265104,0.0001574552297824,2.093913352704649,0.17577011494277286 +3.0,60.0,0.15,-2.0,1115.878662265104,0.0001574552297824,1.0117968869099494,0.08530834679831355 +3.0,60.0,0.15,0.0,1115.878662265104,0.0001574552297824,1.1936093124341394,0.09318597800509326 +3.0,60.0,0.15,2.0,1115.878662265104,0.0001574552297824,1.3750780735331698,0.10387423967229423 +3.0,60.0,0.15,4.0,1115.878662265104,0.0001574552297824,1.5562031702070405,0.117357772500232 +3.0,60.0,0.15,6.0,1115.878662265104,0.0001574552297824,1.7369846024557518,0.13362124006960363 +3.0,60.0,0.15,8.0,1115.878662265104,0.0001574552297824,1.9174223702793032,0.15264932887399763 +3.0,60.0,0.15,10.0,1115.878662265104,0.0001574552297824,2.097516473677695,0.1744267483523678 +3.0,60.0,0.2,-2.0,1115.878662265104,0.0001574552297824,1.0108554830047076,0.0846302517678902 +3.0,60.0,0.2,0.0,1115.878662265104,0.0001574552297824,1.1936888946762736,0.09249585972848232 +3.0,60.0,0.2,2.0,1115.878662265104,0.0001574552297824,1.376174601125979,0.1031859275793604 +3.0,60.0,0.2,4.0,1115.878662265104,0.0001574552297824,1.5583126023538234,0.11668492574535469 +3.0,60.0,0.2,6.0,1115.878662265104,0.0001574552297824,1.7401028983598072,0.13297734793027235 +3.0,60.0,0.2,8.0,1115.878662265104,0.0001574552297824,1.9215454891439303,0.15204771115015556 +3.0,60.0,0.2,10.0,1115.878662265104,0.0001574552297824,2.1026403747061924,0.173880555766502 +3.0,60.0,0.25,-2.0,1115.878662265104,0.0001574552297824,1.0096202810868726,0.08410111573058714 +3.0,60.0,0.25,0.0,1115.878662265104,0.0001574552297824,1.1937943579880552,0.09197760482039588 +3.0,60.0,0.25,2.0,1115.878662265104,0.0001574552297824,1.3776153850107193,0.10270632947961798 +3.0,60.0,0.25,4.0,1115.878662265104,0.0001574552297824,1.561083362154865,0.11627148170431384 +3.0,60.0,0.25,6.0,1115.878662265104,0.0001574552297824,1.7441982894204922,0.1326572773808781 +3.0,60.0,0.25,8.0,1115.878662265104,0.0001574552297824,1.9269601668076006,0.1518479563204159 +3.0,60.0,0.25,10.0,1115.878662265104,0.0001574552297824,2.109368994316191,0.17382778229308002 +3.0,60.0,0.3,-2.0,1115.878662265104,0.0001574552297824,1.0080711113777783,0.08365520606849977 +3.0,60.0,0.3,0.0,1115.878662265104,0.0001574552297824,1.1939283172347188,0.09156127292799465 +3.0,60.0,0.3,2.0,1115.878662265104,0.0001574552297824,1.379425701072754,0.10236043113955587 +3.0,60.0,0.3,4.0,1115.878662265104,0.0001574552297824,1.564563262891883,0.11603648595952379 +3.0,60.0,0.3,6.0,1115.878662265104,0.0001574552297824,1.7493410026921068,0.13257326736896768 +3.0,60.0,0.3,8.0,1115.878662265104,0.0001574552297824,1.9337589204734247,0.1519546301095803 +3.0,60.0,0.3,10.0,1115.878662265104,0.0001574552297824,2.117817016235837,0.1741644537195313 +3.0,70.0,0.1,-2.0,1115.839773344972,0.0001574928901391,1.0126685955135992,0.08645258387399354 +3.0,70.0,0.1,0.0,1115.839773344972,0.0001574928901391,1.1932619766451233,0.09450032134679767 +3.0,70.0,0.1,2.0,1115.839773344972,0.0001574928901391,1.3735885635616194,0.1054033390558448 +3.0,70.0,0.1,4.0,1115.839773344972,0.0001574928901391,1.5536483562630872,0.11914945623293602 +3.0,70.0,0.1,6.0,1115.839773344972,0.0001574928901391,1.733441354749527,0.1357265063009741 +3.0,70.0,0.1,8.0,1115.839773344972,0.0001574928901391,1.9129675590209392,0.15512233688963778 +3.0,70.0,0.1,10.0,1115.839773344972,0.0001574928901391,2.092226969077323,0.17732480985104276 +3.0,70.0,0.15,-2.0,1115.839773344972,0.0001574928901391,1.0120070819674225,0.08545270763077441 +3.0,70.0,0.15,0.0,1115.839773344972,0.0001574928901391,1.1933164171685935,0.09345247340122287 +3.0,70.0,0.15,2.0,1115.839773344972,0.0001574928901391,1.3743567457815897,0.1043034334649565 +3.0,70.0,0.15,4.0,1115.839773344972,0.0001574928901391,1.5551280678064114,0.11799337182621353 +3.0,70.0,0.15,6.0,1115.839773344972,0.0001574928901391,1.7356303832430588,0.13451008678424606 +3.0,70.0,0.15,8.0,1115.839773344972,0.0001574928901391,1.9158636920915315,0.1538413909491706 +3.0,70.0,0.15,10.0,1115.839773344972,0.0001574928901391,2.0958279943518296,0.17597511125780488 +3.0,70.0,0.2,-2.0,1115.839773344972,0.0001574928901391,1.0110669395045195,0.08477307994427308 +3.0,70.0,0.2,0.0,1115.839773344972,0.0001574928901391,1.1933943705944703,0.09276062506419358 +3.0,70.0,0.2,2.0,1115.839773344972,0.0001574928901391,1.375449632124305,0.10361340011796338 +3.0,70.0,0.2,4.0,1115.839773344972,0.0001574928901391,1.5572327240940236,0.11731905366477038 +3.0,70.0,0.2,6.0,1115.839773344972,0.0001574928901391,1.7387436465036261,0.13386524880779424 +3.0,70.0,0.2,8.0,1115.839773344972,0.0001574928901391,1.9199823993531129,0.15323966321042162 +3.0,70.0,0.2,10.0,1115.839773344972,0.0001574928901391,2.100948982642483,0.17542998911244714 +3.0,70.0,0.25,-2.0,1115.839773344972,0.0001574928901391,1.0098333954814067,0.08424246492527723 +3.0,70.0,0.25,0.0,1115.839773344972,0.0001574928901391,1.1934976953867258,0.09224104830550237 +3.0,70.0,0.25,2.0,1115.839773344972,0.0001574928901391,1.3768856421512399,0.1031330475289459 +3.0,70.0,0.25,4.0,1115.839773344972,0.0001574928901391,1.5599972357749494,0.11690588968201154 +3.0,70.0,0.25,6.0,1115.839773344972,0.0001574928901391,1.7428324762578544,0.1335470167769828 +3.0,70.0,0.25,8.0,1115.839773344972,0.0001574928901391,1.9253913635999544,0.15304388576878353 +3.0,70.0,0.25,10.0,1115.839773344972,0.0001574928901391,2.10767389780125,0.17538396857172367 +3.0,70.0,0.3,-2.0,1115.839773344972,0.0001574928901391,1.0082863095547474,0.08379502483266718 +3.0,70.0,0.3,0.0,1115.839773344972,0.0001574928901391,1.1936289703144254,0.09182363167138144 +3.0,70.0,0.3,2.0,1115.839773344972,0.0001574928901391,1.3786899769761822,0.10278711217778197 +3.0,70.0,0.3,4.0,1115.839773344972,0.0001574928901391,1.563469329540018,0.11667258581135698 +3.0,70.0,0.3,6.0,1115.839773344972,0.0001574928901391,1.7479670280059327,0.13346718747868802 +3.0,70.0,0.3,8.0,1115.839773344972,0.0001574928901391,1.9321830723739264,0.1531580675509511 +3.0,70.0,0.3,10.0,1115.839773344972,0.0001574928901391,2.1161174626439996,0.17573239188140177 +3.0,80.0,0.1,-2.0,1115.800883142221,0.0001575305504957,1.0128180158512092,0.08655719155885135 +3.0,80.0,0.1,0.0,1115.800883142221,0.0001575305504957,1.193053644623036,0.09469234119513209 +3.0,80.0,0.1,2.0,1115.800883142221,0.0001575305504957,1.3730751408663855,0.10571160061329538 +3.0,80.0,0.1,4.0,1115.800883142221,0.0001575305504957,1.552882504581257,0.1196050831676636 +3.0,80.0,0.1,6.0,1115.800883142221,0.0001575305504957,1.732475735767651,0.13636291148075808 +3.0,80.0,0.1,8.0,1115.800883142221,0.0001575305504957,1.9118548344255673,0.15597521745149742 +3.0,80.0,0.1,10.0,1115.800883142221,0.0001575305504957,2.091019800555006,0.1784321422633904 +3.0,80.0,0.15,-2.0,1115.800883142221,0.0001575305504957,1.0121571321668374,0.08555631103648532 +3.0,80.0,0.15,0.0,1115.800883142221,0.0001575305504957,1.1931072713617616,0.0936429839256354 +3.0,80.0,0.15,2.0,1115.800883142221,0.0001575305504957,1.373841502348568,0.10460965104843732 +3.0,80.0,0.15,4.0,1115.800883142221,0.0001575305504957,1.5543598251272561,0.11844639713144373 +3.0,80.0,0.15,6.0,1115.800883142221,0.0001575305504957,1.7346622396978262,0.1351433162372801 +3.0,80.0,0.15,8.0,1115.800883142221,0.0001575305504957,1.9147487460602783,0.15469051177293544 +3.0,80.0,0.15,10.0,1115.800883142221,0.0001575305504957,2.0946193442146126,0.17707809649804693 +3.0,80.0,0.2,-2.0,1115.800883142221,0.0001575305504957,1.0112178859258378,0.08487557610264307 +3.0,80.0,0.2,0.0,1115.800883142221,0.0001575305504957,1.193184067753438,0.09294988745063466 +3.0,80.0,0.2,2.0,1115.800883142221,0.0001575305504957,1.3749318027302464,0.10391837527500256 +3.0,80.0,0.2,4.0,1115.800883142221,0.0001575305504957,1.5564610908562633,0.11777101435721722 +3.0,80.0,0.2,6.0,1115.800883142221,0.0001575305504957,1.7377719321314888,0.13449778897740355 +3.0,80.0,0.2,8.0,1115.800883142221,0.0001575305504957,1.9188643265559224,0.15408869292282215 +3.0,80.0,0.2,10.0,1115.800883142221,0.0001575305504957,2.0997382741295647,0.1765337294963448 +3.0,80.0,0.25,-2.0,1115.800883142221,0.0001575305504957,1.0099855197204903,0.08434389528767662 +3.0,80.0,0.25,0.0,1115.800883142221,0.0001575305504957,1.193285873554103,0.0924293565820895 +3.0,80.0,0.25,2.0,1115.800883142221,0.0001575305504957,1.3763644227403133,0.10343747194182837 +3.0,80.0,0.25,4.0,1115.800883142221,0.0001575305504957,1.5592211672791216,0.11735803637260647 +3.0,80.0,0.25,6.0,1115.800883142221,0.0001575305504957,1.7418561071705276,0.13418085462816876 +3.0,80.0,0.25,8.0,1115.800883142221,0.0001575305504957,1.9242692424145316,0.1538957412190586 +3.0,80.0,0.25,10.0,1115.800883142221,0.0001575305504957,2.106460573011133,0.17649252042137778 +3.0,80.0,0.3,-2.0,1115.800883142221,0.0001575305504957,1.0084399140571298,0.08389535444258939 +3.0,80.0,0.3,0.0,1115.800883142221,0.0001575305504957,1.193415241988515,0.09201115643946743 +3.0,80.0,0.3,2.0,1115.800883142221,0.0001575305504957,1.3781645106549432,0.10309149840956668 +3.0,80.0,0.3,4.0,1115.800883142221,0.0001575305504957,1.5626877200564147,0.11712592564905913 +3.0,80.0,0.3,6.0,1115.800883142221,0.0001575305504957,1.7469848701929296,0.13410399354250913 +3.0,80.0,0.3,8.0,1115.800883142221,0.0001575305504957,1.9310559610644882,0.15401526757202713 +3.0,80.0,0.3,10.0,1115.800883142221,0.0001575305504957,2.1149009926710898,0.17684932332641692 +3.0,90.0,0.1,-2.0,1115.761991656717,0.0001575683418195,1.0129252610466077,0.08663308294938242 +3.0,90.0,0.1,0.0,1115.761991656717,0.0001575683418195,1.1929043877067818,0.09483138215962492 +3.0,90.0,0.1,2.0,1115.761991656717,0.0001575683418195,1.3727080848130213,0.10593466932441159 +3.0,90.0,0.1,4.0,1115.761991656717,0.0001575683418195,1.5523363523653257,0.11993477946083006 +3.0,90.0,0.1,6.0,1115.761991656717,0.0001575683418195,1.7317891903636957,0.1368235538680779 +3.0,90.0,0.1,8.0,1115.761991656717,0.0001575683418195,1.911066598808131,0.156592840132008 +3.0,90.0,0.1,10.0,1115.761991656717,0.0001575683418195,2.0901685776986314,0.1792344921296716 +3.0,90.0,0.15,-2.0,1115.761991656717,0.0001575683418195,1.0122648284777265,0.08563155190379951 +3.0,90.0,0.15,0.0,1115.761991656717,0.0001575683418195,1.1929574340547553,0.09378101599904423 +3.0,90.0,0.15,2.0,1115.761991656717,0.0001575683418195,1.3734731553400314,0.10483133352887165 +3.0,90.0,0.15,4.0,1115.761991656717,0.0001575683418195,1.5538119923335547,0.11877431584059997 +3.0,90.0,0.15,6.0,1115.761991656717,0.0001575683418195,1.7339739450353253,0.1356017806096721 +3.0,90.0,0.15,8.0,1115.761991656717,0.0001575683418195,1.9139590134453432,0.1553055518442523 +3.0,90.0,0.15,10.0,1115.761991656717,0.0001575683418195,2.0937671975636083,0.17787745988982015 +3.0,90.0,0.2,-2.0,1115.761991656717,0.0001575683418195,1.0113262241096117,0.0849500048258542 +3.0,90.0,0.2,0.0,1115.761991656717,0.0001575683418195,1.193033405289649,0.09308700505894128 +3.0,90.0,0.2,2.0,1115.761991656717,0.0001575683418195,1.3745616223773776,0.10413914721021147 +3.0,90.0,0.2,4.0,1115.761991656717,0.0001575683418195,1.5559108753727968,0.11809815182219696 +3.0,90.0,0.2,6.0,1115.761991656717,0.0001575683418195,1.7370811642759074,0.13495574587574138 +3.0,90.0,0.2,8.0,1115.761991656717,0.0001575683418195,1.918072489086709,0.15470366279470213 +3.0,90.0,0.2,10.0,1115.761991656717,0.0001575683418195,2.0988848498052017,0.17733364245065017 +3.0,90.0,0.25,-2.0,1115.761991656717,0.0001575683418195,1.0100947014320065,0.0844175446811799 +3.0,90.0,0.25,0.0,1115.761991656717,0.0001575683418195,1.193134127868141,0.0925657752959754 +3.0,90.0,0.25,2.0,1115.761991656717,0.0001575683418195,1.375991839313886,0.10365783690787674 +3.0,90.0,0.25,4.0,1115.761991656717,0.0001575683418195,1.5586678357692412,0.11768530158071788 +3.0,90.0,0.25,6.0,1115.761991656717,0.0001575683418195,1.7411621172342069,0.1346397479856585 +3.0,90.0,0.25,8.0,1115.761991656717,0.0001575683418195,1.923474683708783,0.1545127614060445 +3.0,90.0,0.25,10.0,1115.761991656717,0.0001575683418195,2.1056055351929697,0.1772959337422658 +3.0,90.0,0.3,-2.0,1115.761991656717,0.0001575683418195,1.0085501558632355,0.08396820085897064 +3.0,90.0,0.3,0.0,1115.761991656717,0.0001575683418195,1.1932621368583352,0.0921470013216414 +3.0,90.0,0.3,2.0,1115.761991656717,0.0001575683418195,1.377788917238208,0.1033118291340647 +3.0,90.0,0.3,4.0,1115.761991656717,0.0001575683418195,1.5621304970028538,0.11745405012205264 +3.0,90.0,0.3,6.0,1115.761991656717,0.0001575683418195,1.746286876152273,0.1345650369494221 +3.0,90.0,0.3,8.0,1115.761991656717,0.0001575683418195,1.930258054686465,0.1546361691230699 +3.0,90.0,0.3,10.0,1115.761991656717,0.0001575683418195,2.11404403260543,0.17765883299804525 diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_setup.json b/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_setup.json index df54da1b93..e23bf27c87 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_setup.json +++ b/aviary/subsystems/aerodynamics/gasp_based/test/data/aero_data_setup.json @@ -12,7 +12,6 @@ "cbarvt": 16.832141876220703, "cbarw": 12.614531517028809, "cfoc": 0.30000001192092896, - "ckf": 1.25, "ckht": 1.25, "cki": 1.100000023841858, "ckn": 1.5, diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_common.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_common.py index 3ccd22329e..608882a3d9 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_common.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_common.py @@ -3,35 +3,39 @@ import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.subsystems.aerodynamics.gasp_based.common import (AeroForces, - CLFromLift, - TanhRampComp, - TimeRamp) +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.aerodynamics.gasp_based.common import ( + AeroForces, + CLFromLift, + TanhRampComp, + TimeRamp, +) from aviary.variable_info.variables import Aircraft, Dynamic +@use_tempdirs class TestAeroForces(unittest.TestCase): def testAeroForces(self): nn = 3 af = AeroForces(num_nodes=nn) prob = om.Problem() - prob.model.add_subsystem("comp", af, promotes=["*"]) + prob.model.add_subsystem('comp', af, promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val("CL", [1.0, 0.9, 0.8]) - prob.set_val("CD", [1.0, 0.95, 0.85]) - prob.set_val(Dynamic.Mission.DYNAMIC_PRESSURE, 1, units="psf") - prob.set_val(Aircraft.Wing.AREA, 1370.3, units="ft**2") + prob.set_val('CL', [1.0, 0.9, 0.8]) + prob.set_val('CD', [1.0, 0.95, 0.85]) + prob.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, 1, units='psf') + prob.set_val(Aircraft.Wing.AREA, 1370.3, units='ft**2') prob.run_model() - lift = prob.get_val(Dynamic.Mission.LIFT) - drag = prob.get_val(Dynamic.Mission.DRAG) + lift = prob.get_val(Dynamic.Vehicle.LIFT) + drag = prob.get_val(Dynamic.Vehicle.DRAG) assert_near_equal(lift, [1370.3, 1233.27, 1096.24]) assert_near_equal(drag, [1370.3, 1301.785, 1164.755]) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-15) @@ -46,20 +50,20 @@ def test_single_ramp_up(self): tr = TimeRamp(num_nodes=nn, num_inputs=k, ramp_up=True) prob = om.Problem() - prob.model.add_subsystem("comp", tr, promotes=["*"]) + prob.model.add_subsystem('comp', tr, promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val("t_init", 3) - prob.set_val("t_curr", t) - prob.set_val("duration", 4) - prob.set_val("x", x) + prob.set_val('t_init', 3) + prob.set_val('t_curr', t) + prob.set_val('duration', 4) + prob.set_val('x', x) prob.run_model() y_exp = np.array([[0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.75, 1.0, 1.0, 1.0, 1.0]]) - assert_near_equal(prob["y"], y_exp) + assert_near_equal(prob['y'], y_exp) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) def test_multi_ramp_down(self): @@ -77,42 +81,49 @@ def test_multi_ramp_down(self): tr = TimeRamp(num_nodes=nn, num_inputs=k, ramp_up=False) prob = om.Problem() - prob.model.add_subsystem("comp", tr, promotes=["*"]) + prob.model.add_subsystem('comp', tr, promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val("t_init", 3) - prob.set_val("t_curr", t) - prob.set_val("duration", 5) - prob.set_val("x", x) + prob.set_val('t_init', 3) + prob.set_val('t_curr', t) + prob.set_val('duration', 5) + prob.set_val('x', x) prob.run_model() - assert_near_equal(prob["y"], y_exp) + assert_near_equal(prob['y'], y_exp) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class TestCLFromLift(unittest.TestCase): def test_partials(self): prob = om.Problem() - prob.model.add_subsystem("comp", CLFromLift(num_nodes=2), promotes=["*"]) + prob.model.add_subsystem('comp', CLFromLift(num_nodes=2), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(method="cs", out_stream=None) + prob.set_val(Aircraft.Wing.AREA, 1370) + prob.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, 1) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class TestTanhRampComp(unittest.TestCase): - def test_tanh_ramp_up(self): p = om.Problem() - nn = 1000 + nn = 100 c = TanhRampComp(time_units='s', num_nodes=nn) - c.add_ramp('thruput', output_units='kg/s', initial_val=30, - final_val=40, t_init_val=25, t_duration_val=5) + c.add_ramp( + 'thruput', + output_units='kg/s', + initial_val=30, + final_val=40, + t_init_val=25, + t_duration_val=5, + ) p.model.add_subsystem('tanh_ramp', c) @@ -126,27 +137,33 @@ def test_tanh_ramp_up(self): thruput = p.get_val('tanh_ramp.thruput') - assert_near_equal(thruput[250], desired=30, tolerance=0.01) - assert_near_equal(thruput[275], desired=35, tolerance=0.01) - assert_near_equal(thruput[300], desired=40, tolerance=0.01) + assert_near_equal(thruput[25], desired=30, tolerance=0.01) + assert_near_equal(thruput[27], desired=33.6, tolerance=0.01) + assert_near_equal(thruput[30], desired=40, tolerance=0.01) - assert_near_equal(thruput[500:], desired=40*np.ones((500, 1)), tolerance=0.01) - assert_near_equal(thruput[:200], desired=30*np.ones((200, 1)), tolerance=0.01) + assert_near_equal(thruput[50:], desired=40 * np.ones((50, 1)), tolerance=0.01) + assert_near_equal(thruput[:20], desired=30 * np.ones((20, 1)), tolerance=0.01) self.assertTrue(np.all(thruput >= 30)) self.assertTrue(np.all(thruput <= 40)) - assert_check_partials(cpd, atol=1.0E-9, rtol=1.0E-12) + assert_check_partials(cpd, atol=1.0e-9, rtol=1.0e-12) def test_tanh_ramp_down(self): p = om.Problem() - nn = 1000 + nn = 100 c = TanhRampComp(time_units='s', num_nodes=nn) - c.add_ramp('thruput', output_units='kg/s', initial_val=40, - final_val=30, t_init_val=25, t_duration_val=5) + c.add_ramp( + 'thruput', + output_units='kg/s', + initial_val=40, + final_val=30, + t_init_val=25, + t_duration_val=5, + ) p.model.add_subsystem('tanh_ramp', c) @@ -160,18 +177,18 @@ def test_tanh_ramp_down(self): thruput = p.get_val('tanh_ramp.thruput')[:, 0] - assert_near_equal(thruput[250], desired=40, tolerance=0.01) - assert_near_equal(thruput[275], desired=35, tolerance=0.01) - assert_near_equal(thruput[300], desired=30, tolerance=0.01) + assert_near_equal(thruput[25], desired=40, tolerance=0.01) + assert_near_equal(thruput[27], desired=36.4, tolerance=0.01) + assert_near_equal(thruput[30], desired=30, tolerance=0.01) - assert_near_equal(thruput[500:], desired=30*np.ones(500), tolerance=0.01) - assert_near_equal(thruput[:200], desired=40*np.ones(200), tolerance=0.01) + assert_near_equal(thruput[50:], desired=30 * np.ones(50), tolerance=0.01) + assert_near_equal(thruput[:20], desired=40 * np.ones(20), tolerance=0.01) self.assertTrue(np.all(thruput >= 30)) self.assertTrue(np.all(thruput <= 40)) - assert_check_partials(cpd, atol=1.0E-9, rtol=1.0E-12) + assert_check_partials(cpd, atol=1.0e-9, rtol=1.0e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py index 2a305f8504..a8ea394de1 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gasp_aero_coeffs.py @@ -13,35 +13,32 @@ class TestAeroCoeffs(unittest.TestCase): def test_aero_coeffs(self): aero_coeffs = AeroFormfactors() prob = om.Problem() - prob.model.add_subsystem("comp", aero_coeffs, promotes=["*"]) + prob.model.add_subsystem('comp', aero_coeffs, promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, .12) - prob.set_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, .15) - prob.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, .1) - prob.set_val(Aircraft.Strut.THICKNESS_TO_CHORD, .1) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.12) + prob.set_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.15) + prob.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.1) + prob.set_val(Aircraft.Strut.THICKNESS_TO_CHORD, 0.1) prob.set_val(Aircraft.Wing.SWEEP, 30, units='deg') prob.set_val(Aircraft.VerticalTail.SWEEP, 15, units='deg') prob.set_val(Aircraft.HorizontalTail.SWEEP, 10, units='deg') prob.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0) - prob.set_val(Mission.Design.MACH, .6) + prob.set_val(Mission.Design.MACH, 0.6) prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, 6) prob.set_val(Aircraft.Nacelle.AVG_LENGTH, 10) prob.run_model() assert_near_equal(prob.get_val(Aircraft.Wing.FORM_FACTOR), [2.4892359], tol) - assert_near_equal(prob.get_val( - Aircraft.VerticalTail.FORM_FACTOR), [2.73809734], tol) - assert_near_equal(prob.get_val( - Aircraft.HorizontalTail.FORM_FACTOR), [2.59223754], tol) - assert_near_equal(prob.get_val( - Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR), [2.4786], tol) + assert_near_equal(prob.get_val(Aircraft.VerticalTail.FORM_FACTOR), [2.73809734], tol) + assert_near_equal(prob.get_val(Aircraft.HorizontalTail.FORM_FACTOR), [2.59223754], tol) + assert_near_equal(prob.get_val(Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR), [2.4786], tol) assert_near_equal(prob.get_val(Aircraft.Nacelle.FORM_FACTOR), [1.815], tol) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py index 9e97710a38..abd85d3af7 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_gaspaero.py @@ -7,19 +7,42 @@ import pandas as pd from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.gaspaero import CruiseAero, LowSpeedAero +from aviary.subsystems.aerodynamics.gasp_based.gaspaero import ( + AeroGeom, + CruiseAero, + DragCoef, + DragCoefClean, + FormFactorAndSIWB, + GroundEffect, + LiftCoeff, + LiftCoeffClean, + LowSpeedAero, + UFac, + Xlifts, + WingTailRatios, + BWBBodyLiftCurveSlope, + BWBFormFactorAndSIWB, + BWBLiftCoeff, + BWBLiftCoeffClean, + BWBAeroSetup, +) +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.utils.aviary_values import AviaryValues here = os.path.abspath(os.path.dirname(__file__)) -cruise_data = pd.read_csv(os.path.join(here, "data", "aero_data_cruise.csv")) -ground_data = pd.read_csv(os.path.join(here, "data", "aero_data_ground.csv")) -setup_data = json.load(open(os.path.join(here, "data", "aero_data_setup.json"))) +cruise_data = pd.read_csv(os.path.join(here, 'data', 'aero_data_cruise.csv')) +ground_data = pd.read_csv(os.path.join(here, 'data', 'aero_data_ground.csv')) +with open(os.path.join(here, 'data', 'aero_data_setup.json')) as file: + setup_data = json.load(file) class GASPAeroTest(unittest.TestCase): - """Test overall pre-mission and mission aero systems in cruise and near-ground flight""" + """ + Test overall pre-mission and mission aero systems in cruise and near-ground flight. + Note: The case output_alpha=True is not tested. + """ cruise_tol = 1.5e-3 ground_tol = 0.5e-3 @@ -29,44 +52,55 @@ class GASPAeroTest(unittest.TestCase): def test_cruise(self): prob = om.Problem() prob.model.add_subsystem( - "aero", CruiseAero(num_nodes=2, aviary_options=get_option_defaults(), input_atmos=True), promotes=["*"] + 'aero', + CruiseAero(num_nodes=2, input_atmos=True), + promotes=['*'], ) + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) _init_geom(prob) # extra params needed for cruise aero - prob.set_val(Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, setup_data["clmwfu"]) - prob.set_val( - Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT, setup_data["scfac"] - ) + prob.set_val(Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, setup_data['clmwfu']) + prob.set_val(Aircraft.Design.DRAG_DIVERGENCE_SHIFT, setup_data['scfac']) for i, row in cruise_data.iterrows(): - alt = row["alt"] - mach = row["mach"] - alpha = row["alpha"] + alt = row['alt'] + mach = row['mach'] + alpha = row['alpha'] with self.subTest(alt=alt, mach=mach, alpha=alpha): # prob.set_val(Dynamic.Mission.ALTITUDE, alt) - prob.set_val(Dynamic.Mission.MACH, mach) - prob.set_val("alpha", alpha) - prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, row["sos"]) - prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, row["nu"]) + prob.set_val(Dynamic.Atmosphere.MACH, mach) + prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, alpha) + prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, row['sos']) + prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, row['nu']) prob.run_model() - assert_near_equal(prob["CL"][0], row["cl"], tolerance=self.cruise_tol) - assert_near_equal(prob["CD"][0], row["cd"], tolerance=self.cruise_tol) + assert_near_equal(prob['CL'][0], row['cl'], tolerance=self.cruise_tol) + assert_near_equal(prob['CD'][0], row['cd'], tolerance=self.cruise_tol) # some partials are computed using "cs" method. So, use "fd" here. computation is not as good as "cs". - partial_data = prob.check_partials(method="fd", out_stream=None) + partial_data = prob.check_partials(method='fd', out_stream=None) assert_check_partials(partial_data, atol=0.8, rtol=0.002) def test_ground(self): prob = om.Problem() prob.model.add_subsystem( - "aero", LowSpeedAero(num_nodes=2, aviary_options=get_option_defaults(), input_atmos=True), promotes=["*"] + 'aero', + LowSpeedAero( + num_nodes=2, + input_atmos=True, + ), + promotes=['*'], ) + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) _init_geom(prob) @@ -74,65 +108,67 @@ def test_ground(self): # extra params needed for ground aero # leave time ramp inputs as defaults, gear/flaps extended and stay prob.set_val(Aircraft.Wing.HEIGHT, 8.0) # not defined in standalone aero - prob.set_val("airport_alt", 0.0) # not defined in standalone aero - prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, setup_data["cfoc"]) - prob.set_val(Mission.Design.GROSS_MASS, setup_data["wgto"]) + prob.set_val('airport_alt', 0.0) # not defined in standalone aero + prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, setup_data['cfoc']) + prob.set_val(Mission.Design.GROSS_MASS, setup_data['wgto']) for i, row in ground_data.iterrows(): - ilift = row["ilift"] # 2: takeoff, 3: landing - alt = row["alt"] - mach = row["mach"] - alpha = row["alpha"] + ilift = row['ilift'] # 2: takeoff, 3: landing + alt = row['alt'] + mach = row['mach'] + alpha = row['alpha'] with self.subTest(ilift=ilift, alt=alt, mach=mach, alpha=alpha): - prob.set_val(Dynamic.Mission.MACH, mach) + prob.set_val(Dynamic.Atmosphere.MACH, mach) prob.set_val(Dynamic.Mission.ALTITUDE, alt) - prob.set_val("alpha", alpha) - prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, row["sos"]) - prob.set_val(Dynamic.Mission.KINEMATIC_VISCOSITY, row["nu"]) + prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, alpha) + prob.set_val(Dynamic.Atmosphere.SPEED_OF_SOUND, row['sos']) + prob.set_val(Dynamic.Atmosphere.KINEMATIC_VISCOSITY, row['nu']) # note we're just letting the time ramps for flaps/gear default to the # takeoff config such that the default times correspond to full flap and # gear increments - if row["ilift"] == 2: + if row['ilift'] == 2: # takeoff flaps config - prob.set_val("flap_defl", setup_data["delfto"]) - prob.set_val("CL_max_flaps", setup_data["clmwto"]) - prob.set_val("dCL_flaps_model", setup_data["dclto"]) - prob.set_val("dCD_flaps_model", setup_data["dcdto"]) - prob.set_val("aero_ramps.flap_factor:final_val", 1.) - prob.set_val("aero_ramps.gear_factor:final_val", 1.) + prob.set_val('flap_defl', setup_data['delfto']) + prob.set_val('CL_max_flaps', setup_data['clmwto']) + prob.set_val('dCL_flaps_model', setup_data['dclto']) + prob.set_val('dCD_flaps_model', setup_data['dcdto']) + prob.set_val('aero_ramps.flap_factor:final_val', 1.0) + prob.set_val('aero_ramps.gear_factor:final_val', 1.0) else: # landing flaps config - prob.set_val("flap_defl", setup_data["delfld"]) - prob.set_val("CL_max_flaps", setup_data["clmwld"]) - prob.set_val("dCL_flaps_model", setup_data["dclld"]) - prob.set_val("dCD_flaps_model", setup_data["dcdld"]) + prob.set_val('flap_defl', setup_data['delfld']) + prob.set_val('CL_max_flaps', setup_data['clmwld']) + prob.set_val('dCL_flaps_model', setup_data['dclld']) + prob.set_val('dCD_flaps_model', setup_data['dcdld']) prob.run_model() - assert_near_equal(prob["CL"][0], row["cl"], tolerance=self.ground_tol) - assert_near_equal(prob["CD"][0], row["cd"], tolerance=self.ground_tol) + assert_near_equal(prob['CL'][0], row['cl'], tolerance=self.ground_tol) + assert_near_equal(prob['CD'][0], row['cd'], tolerance=self.ground_tol) - partial_data = prob.check_partials(method="fd", out_stream=None) + partial_data = prob.check_partials(method='fd', out_stream=None) assert_check_partials(partial_data, atol=4.5, rtol=5e-3) def test_ground_alpha_out(self): - # Test that drag output matches between alpha in/out cases + # Test that drag output matches between both CL computation methods prob = om.Problem() prob.model.add_subsystem( - "alpha_in", - LowSpeedAero(aviary_options=get_option_defaults()), - promotes_inputs=["*", ("alpha", "alpha_in")], - promotes_outputs=[(Dynamic.Mission.LIFT, "lift_req")], + 'lift_from_aoa', + LowSpeedAero(), + promotes_inputs=['*', (Dynamic.Vehicle.ANGLE_OF_ATTACK, 'alpha_in')], + promotes_outputs=[(Dynamic.Vehicle.LIFT, 'lift_req')], ) prob.model.add_subsystem( - "alpha_out", - LowSpeedAero(aviary_options=get_option_defaults(), output_alpha=True), - promotes_inputs=["*", "lift_req"], + 'lift_required', + LowSpeedAero(lift_required=True), + promotes_inputs=['*', 'lift_req'], ) + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) _init_geom(prob) @@ -140,70 +176,68 @@ def test_ground_alpha_out(self): # extra params needed for ground aero # leave time ramp inputs as defaults, gear/flaps extended and stay prob.set_val(Aircraft.Wing.HEIGHT, 8.0) # not defined in standalone aero - prob.set_val("airport_alt", 0.0) # not defined in standalone aero - prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, setup_data["cfoc"]) - prob.set_val(Mission.Design.GROSS_MASS, setup_data["wgto"]) + prob.set_val('airport_alt', 0.0) # not defined in standalone aero + prob.set_val(Aircraft.Wing.FLAP_CHORD_RATIO, setup_data['cfoc']) + prob.set_val(Mission.Design.GROSS_MASS, setup_data['wgto']) - prob.set_val(Dynamic.Mission.MACH, 0.1) + prob.set_val(Dynamic.Atmosphere.DYNAMIC_PRESSURE, 1) + prob.set_val(Dynamic.Atmosphere.MACH, 0.1) prob.set_val(Dynamic.Mission.ALTITUDE, 10) - prob.set_val("alpha_in", 5) + prob.set_val('alpha_in', 5) prob.run_model() - assert_near_equal(prob["alpha_in.drag"], prob["alpha_out.drag"], tolerance=1e-6) + assert_near_equal(prob['lift_from_aoa.drag'], prob['lift_required.drag'], tolerance=1e-6) - partial_data = prob.check_partials(method="fd", out_stream=None) + partial_data = prob.check_partials(method='fd', out_stream=None) assert_check_partials(partial_data, atol=0.02, rtol=1e-4) def _init_geom(prob): - """Initialize user inputs and geometry/sizing data""" - prob.set_val("interference_independent_of_shielded_area", 1.89927266) - prob.set_val("drag_loss_due_to_shielded_wing_area", 68.02065834) + """Initialize user inputs and geometry/sizing data.""" + prob.set_val('interference_independent_of_shielded_area', 1.89927266) + prob.set_val('drag_loss_due_to_shielded_wing_area', 68.02065834) # i.e. common auto IVC vars for the setup + cruise and ground aero models - prob.set_val(Aircraft.Wing.AREA, setup_data["sw"]) - prob.set_val(Aircraft.Wing.SPAN, setup_data["b"]) - prob.set_val(Aircraft.Wing.AVERAGE_CHORD, setup_data["cbarw"]) - prob.set_val(Aircraft.Wing.TAPER_RATIO, setup_data["slm"]) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, setup_data["tcr"]) - prob.set_val(Aircraft.Wing.MOUNTING_TYPE, setup_data["hwing"]) - prob.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, setup_data["sah"]) - prob.set_val(Aircraft.HorizontalTail.SPAN, setup_data["bht"]) - prob.set_val(Aircraft.VerticalTail.SPAN, setup_data["bvt"]) - prob.set_val(Aircraft.HorizontalTail.AREA, setup_data["sht"]) - prob.set_val(Aircraft.HorizontalTail.AVERAGE_CHORD, setup_data["cbarht"]) - prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, setup_data["swf"]) + prob.set_val(Aircraft.Wing.AREA, setup_data['sw']) + prob.set_val(Aircraft.Wing.SPAN, setup_data['b']) + prob.set_val(Aircraft.Wing.AVERAGE_CHORD, setup_data['cbarw']) + prob.set_val(Aircraft.Wing.TAPER_RATIO, setup_data['slm']) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, setup_data['tcr']) + prob.set_val(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, setup_data['hwing']) + prob.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, setup_data['sah']) + prob.set_val(Aircraft.HorizontalTail.SPAN, setup_data['bht']) + prob.set_val(Aircraft.VerticalTail.SPAN, setup_data['bvt']) + prob.set_val(Aircraft.HorizontalTail.AREA, setup_data['sht']) + prob.set_val(Aircraft.HorizontalTail.AVERAGE_CHORD, setup_data['cbarht']) + prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, setup_data['swf']) # ground & cruise, mission: mach - prob.set_val(Aircraft.Design.STATIC_MARGIN, setup_data["stmarg"]) - prob.set_val(Aircraft.Design.CG_DELTA, setup_data["delcg"]) - prob.set_val(Aircraft.Wing.ASPECT_RATIO, setup_data["ar"]) - prob.set_val(Aircraft.Wing.SWEEP, setup_data["dlmc4"]) - prob.set_val(Aircraft.HorizontalTail.SWEEP, setup_data["dwpqch"]) - prob.set_val(Aircraft.HorizontalTail.MOMENT_RATIO, setup_data["coelth"]) + prob.set_val(Aircraft.Design.STATIC_MARGIN, setup_data['stmarg']) + prob.set_val(Aircraft.Design.CG_DELTA, setup_data['delcg']) + prob.set_val(Aircraft.Wing.ASPECT_RATIO, setup_data['ar']) + prob.set_val(Aircraft.Wing.SWEEP, setup_data['dlmc4']) + prob.set_val(Aircraft.HorizontalTail.SWEEP, setup_data['dwpqch']) + prob.set_val(Aircraft.HorizontalTail.MOMENT_RATIO, setup_data['coelth']) # ground & cruise, mission: alt - prob.set_val(Aircraft.Wing.FORM_FACTOR, setup_data["ckw"]) - prob.set_val(Aircraft.Fuselage.FORM_FACTOR, setup_data["ckf"]) - prob.set_val(Aircraft.Nacelle.FORM_FACTOR, setup_data["ckn"]) - prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, setup_data["ckvt"]) - prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, setup_data["ckht"]) - prob.set_val(Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, setup_data["cki"]) - prob.set_val(Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, setup_data["ckstrt"]) - prob.set_val(Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, setup_data["delcd"]) - prob.set_val(Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, setup_data["delfe"]) - prob.set_val(Aircraft.Wing.MIN_PRESSURE_LOCATION, setup_data["xcps"]) - prob.set_val( - Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.4 - ) # overriden in standalone code - prob.set_val(Aircraft.Strut.AREA_RATIO, setup_data["sstqsw"]) - prob.set_val(Aircraft.VerticalTail.AVERAGE_CHORD, setup_data["cbarvt"]) - prob.set_val(Aircraft.Fuselage.LENGTH, setup_data["elf"]) - prob.set_val(Aircraft.Nacelle.AVG_LENGTH, setup_data["eln"]) - prob.set_val(Aircraft.Fuselage.WETTED_AREA, setup_data["sf"]) - prob.set_val(Aircraft.Nacelle.SURFACE_AREA, setup_data["sn"] / setup_data["enp"]) - prob.set_val(Aircraft.VerticalTail.AREA, setup_data["svt"]) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, setup_data["tc"]) + prob.set_val(Aircraft.Wing.FORM_FACTOR, setup_data['ckw']) + prob.set_val(Aircraft.Nacelle.FORM_FACTOR, setup_data['ckn']) + prob.set_val(Aircraft.VerticalTail.FORM_FACTOR, setup_data['ckvt']) + prob.set_val(Aircraft.HorizontalTail.FORM_FACTOR, setup_data['ckht']) + prob.set_val(Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, setup_data['cki']) + prob.set_val(Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, setup_data['ckstrt']) + prob.set_val(Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, setup_data['delcd']) + prob.set_val(Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, setup_data['delfe']) + prob.set_val(Aircraft.Wing.MIN_PRESSURE_LOCATION, setup_data['xcps']) + prob.set_val(Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.4) # overridden in standalone code + prob.set_val(Aircraft.Strut.AREA_RATIO, setup_data['sstqsw']) + prob.set_val(Aircraft.VerticalTail.AVERAGE_CHORD, setup_data['cbarvt']) + prob.set_val(Aircraft.Fuselage.LENGTH, setup_data['elf']) + prob.set_val(Aircraft.Nacelle.AVG_LENGTH, setup_data['eln']) + prob.set_val(Aircraft.Fuselage.WETTED_AREA, setup_data['sf']) + prob.set_val(Aircraft.Nacelle.SURFACE_AREA, setup_data['sn'] / setup_data['enp']) + prob.set_val(Aircraft.VerticalTail.AREA, setup_data['svt']) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, setup_data['tc']) prob.set_val(Aircraft.Strut.CHORD, 0) # not defined in standalone aero # ground & cruise, mission: alpha - prob.set_val(Aircraft.Wing.ZERO_LIFT_ANGLE, setup_data["alphl0"]) + prob.set_val(Aircraft.Wing.ZERO_LIFT_ANGLE, setup_data['alphl0']) # ground & cruise, config-specific: CL_max_flaps # ground: wing_height # ground: airport_alt @@ -221,5 +255,1561 @@ def _init_geom(prob): # ground & cruise, mission: q -if __name__ == "__main__": +class XLiftsTest(unittest.TestCase): + def test_case1(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + + prob = om.Problem() + prob.model.add_subsystem( + 'xlifts', + Xlifts(num_nodes=2), + promotes=['*'], + ) + + # Xlifts + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.8, 0.8], units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STATIC_MARGIN, 0.05, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.CG_DELTA, 0.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SWEEP, 45.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + prob.model.set_input_defaults('sbar', 0.001, units='unitless') + prob.model.set_input_defaults('cbar', 0.00173, units='unitless') + prob.model.set_input_defaults('hbar', 0.001, units='unitless') + prob.model.set_input_defaults('bbar', 0.000305, units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-06 + assert_near_equal(prob['lift_curve_slope'], [5.94800206, 5.94800206], tol) + assert_near_equal(prob['lift_ratio'], [-0.140812203, -0.140812203], tol) + + partial_data = prob.check_partials(method='fd', out_stream=None) + assert_check_partials(partial_data, atol=1e-4, rtol=1e-3) + + def test_case2(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + + prob = om.Problem() + prob.model.add_subsystem( + 'xlifts', + Xlifts(num_nodes=2), + promotes=['*'], + ) + + # Xlifts + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.2, 0.2], units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STATIC_MARGIN, 0.05, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.CG_DELTA, 0.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SWEEP, 45.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + prob.model.set_input_defaults('sbar', 0.001, units='unitless') + prob.model.set_input_defaults('cbar', 0.00173, units='unitless') + prob.model.set_input_defaults('hbar', 0.001, units='unitless') + prob.model.set_input_defaults('bbar', 0.000305, units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-06 + assert_near_equal(prob['lift_curve_slope'], [4.638043756, 4.63804375], tol) + assert_near_equal(prob['lift_ratio'], [-0.140812203, -0.140812203], tol) + + partial_data = prob.check_partials(method='fd', out_stream=None) + assert_check_partials(partial_data, atol=1e-4, rtol=1e-3) + + +class LiftCoeffTest(unittest.TestCase): + """Test partials of LiftCoeff""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'lift_coeff', + LiftCoeff(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, [-2.0, -2.0], units='deg') + prob.model.set_input_defaults('lift_curve_slope', [4.876, 4.876], units='unitless') + prob.model.set_input_defaults('lift_ratio', [0.5, 0.5], units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, -1.2, units='deg') + prob.model.set_input_defaults('CL_max_flaps', 2.188, units='unitless') + prob.model.set_input_defaults('dCL_flaps_model', 0.418, units='unitless') + prob.model.set_input_defaults('kclge', [1.15, 1.15], units='unitless') + prob.model.set_input_defaults('flap_factor', [1.0, 1.0], units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class LiftCoeffCleanTest(unittest.TestCase): + """Test partials of LiftCoeffClean""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'lift_coeff', + LiftCoeffClean(num_nodes=2, output_alpha=False), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, [-2.0, -2.0], units='deg') + prob.model.set_input_defaults('lift_curve_slope', [5.975, 5.975], units='unitless') + prob.model.set_input_defaults('lift_ratio', [0.0357, 0.0357], units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, -1.2, units='deg') + prob.model.set_input_defaults( + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, 1.8885, units='unitless' + ) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-7 + assert_near_equal(prob['CL'], [-0.08640507, -0.08640507], tol) + assert_near_equal(prob['alpha_stall'], [16.90930203, 16.90930203], tol) + assert_near_equal(prob['CL_max'], [1.95591945, 1.95591945], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + def test_case2(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'lift_coeff', + LiftCoeffClean(num_nodes=2, output_alpha=True), + promotes=['*'], + ) + + prob.model.set_input_defaults('CL', [-0.08640507, -0.08640507], units='unitless') + prob.model.set_input_defaults('lift_curve_slope', [5.975, 5.975], units='unitless') + prob.model.set_input_defaults('lift_ratio', [0.0357, 0.0357], units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, -1.2, units='deg') + prob.model.set_input_defaults( + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, 1.8885, units='unitless' + ) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-7 + assert_near_equal(prob[Dynamic.Vehicle.ANGLE_OF_ATTACK], [-1.99999997, -1.99999997], tol) + assert_near_equal(prob['alpha_stall'], [16.90930203, 16.90930203], tol) + assert_near_equal(prob['CL_max'], [1.95591945, 1.95591945], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class UFacTest(unittest.TestCase): + """Test UFac computation""" + + def test_case1(self): + """ + aircraft of tube and wing type (not used in AeroSetup) + """ + prob = om.Problem() + + prob.model.add_subsystem( + 'ufac', + UFac(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults( + 'lift_ratio', val=[-0.140812203, -0.140812203], units='unitless' + ) + prob.model.set_input_defaults('bbar_alt', val=1.0, units='unitless') + prob.model.set_input_defaults('sigma', val=1.0, units='unitless') + prob.model.set_input_defaults('sigstr', val=1.0, units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + assert_near_equal(prob['ufac'], [1.0, 1.0], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + def test_case2(self): + """ + BWB case with smooth derivative (used in BWBAeroSetup) + """ + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + + prob = om.Problem() + + prob.model.add_subsystem( + 'ufac', + UFac(num_nodes=2, smooth_ufac=True, mu=150.0), + promotes=['*'], + ) + + prob.model.set_input_defaults( + 'lift_ratio', val=[-0.140812203, -0.140812203], units='unitless' + ) + prob.model.set_input_defaults('bbar_alt', val=1.0, units='unitless') + prob.model.set_input_defaults('sigma', val=1.0, units='unitless') + prob.model.set_input_defaults('sigstr', val=1.0, units='unitless') + + setup_model_options(prob, options) + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + assert_near_equal(prob['ufac'], [0.97484503, 0.97484503], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + def test_case3(self): + """ + BWB case without smoothness, hence exactly the same as GASP (used in BWBAeroSetup) + """ + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + + prob = om.Problem() + + prob.model.add_subsystem( + 'ufac', + UFac(num_nodes=2, smooth_ufac=False), + promotes=['*'], + ) + + prob.model.set_input_defaults( + 'lift_ratio', val=[-0.140812203, -0.140812203], units='unitless' + ) + prob.model.set_input_defaults('bbar_alt', val=1.0, units='unitless') + prob.model.set_input_defaults('sigma', val=1.0, units='unitless') + prob.model.set_input_defaults('sigstr', val=1.0, units='unitless') + + setup_model_options(prob, options) + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + assert_near_equal(prob['ufac'], [0.975, 0.975], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class FormFactorAndSIWBTest(unittest.TestCase): + """Test fuselage form factor computation and SIWB computation""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'form_factor', + FormFactorAndSIWB(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=146.38501, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) + assert_near_equal(prob['siwb'], 0.964972794, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class BWBFormFactorAndSIWBTest(unittest.TestCase): + """Test fuselage form factor computation and SIWB computation""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'form_factor', + BWBFormFactorAndSIWB(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, val=19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=146.38501, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024726, tol) + assert_near_equal(prob['siwb'], 0.964972794, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class WingTailRatiosTest(unittest.TestCase): + def test_case1(self): + """BWB data""" + prob = om.Problem() + prob.model.add_subsystem( + 'wing_tail_ratio', + WingTailRatios(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AVERAGE_CHORD, 0.0280845, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-4 + assert_near_equal(prob['hbar'], 0, tol) + assert_near_equal(prob['bbar'], 0.0003052, tol) + assert_near_equal(prob['sbar'], 0, tol) + assert_near_equal(prob['cbar'], 0.00173147, tol) + assert_near_equal(prob['bbar_alt'], 1.0, tol) + + +class AeroGeomTest(unittest.TestCase): + def test_case1(self): + options = get_option_defaults() + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + options.set_val(Aircraft.Wing.HAS_STRUT, False) + + prob = om.Problem() + prob.model.add_subsystem( + 'aero_geom', + AeroGeom(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.8, 0.8], units='unitless') + prob.model.set_input_defaults( + Dynamic.Atmosphere.SPEED_OF_SOUND, [993.11760441, 993.11760441], units='ft/s' + ) + prob.model.set_input_defaults( + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' + ) + prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.563, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.FORM_FACTOR, 1.2, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.FORM_FACTOR, 2.361, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.FORM_FACTOR, 2.413, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, 0.00025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, 0.25, units='ft**2' + ) + prob.model.set_input_defaults(Aircraft.Wing.MIN_PRESSURE_LOCATION, 0.275, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.325, units='unitless') + prob.model.set_input_defaults(Aircraft.Strut.AREA_RATIO, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.AVERAGE_CHORD, 10.67, units='ft') + prob.model.set_input_defaults(Aircraft.Nacelle.AVG_LENGTH, 18.11, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults(Aircraft.Nacelle.SURFACE_AREA, 411.93, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.1, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13596576, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AVERAGE_CHORD, 0.0280845, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Strut.CHORD, 0.0, units='ft') + prob.model.set_input_defaults('ufac', [0.975, 0.975], units='unitless') + prob.model.set_input_defaults('siwb', 0.96497277, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.FORM_FACTOR, 1.35024721, units='unitless') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-5 + # GASP uses different skin friction parameters for different areas. + # That explains the differences between GASP and Aviary + assert_near_equal(prob['cf'], [0.00283643, 0.00283643], tol) + assert_near_equal(prob['SA1'], [0.80832432, 0.80832432], tol) + assert_near_equal(prob['SA2'], [-0.13650645, -0.13650645], tol) + assert_near_equal(prob['SA3'], [0.03398855, 0.03398855], tol) + assert_near_equal(prob['SA4'], [0.10197432, 0.10197432], tol) + assert_near_equal(prob['SA5'], [0.00773867, 0.00773867], tol) + assert_near_equal(prob['SA6'], [2.09276756, 2.09276756], tol) + assert_near_equal(prob['SA7'], [0.03978045, 0.03978045], tol) + + +class BWBAeroSetupTest(unittest.TestCase): + def test_case1(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + options.set_val(Aircraft.Wing.HAS_STRUT, False) + + prob = om.Problem() + prob.model.add_subsystem( + 'aero_setup', + BWBAeroSetup(num_nodes=2, input_atmos=True), + promotes=['*'], + ) + + # WingTailRatios + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AVERAGE_CHORD, 0.0280845, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + + # Xlifts + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.8, 0.8], units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STATIC_MARGIN, 0.05, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.CG_DELTA, 0.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.HorizontalTail.SWEEP, 45.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + + # BWBFormFactorAndSIWB + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + + # AeroGeom + prob.model.set_input_defaults( + Dynamic.Atmosphere.SPEED_OF_SOUND, [993.11760441, 993.11760441], units='ft/s' + ) + prob.model.set_input_defaults( + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' + ) + prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.563, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.FORM_FACTOR, 1.2, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.FORM_FACTOR, 2.361, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.FORM_FACTOR, 2.413, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, 0.00025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, 0.25, units='ft**2' + ) + prob.model.set_input_defaults(Aircraft.Wing.MIN_PRESSURE_LOCATION, 0.275, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.325, units='unitless') + prob.model.set_input_defaults(Aircraft.Strut.AREA_RATIO, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.AVERAGE_CHORD, 10.67, units='ft') + prob.model.set_input_defaults(Aircraft.Nacelle.AVG_LENGTH, 18.11, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults(Aircraft.Nacelle.SURFACE_AREA, 411.93, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.1, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13596576, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Strut.CHORD, 0.0, units='ft') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-4 + assert_near_equal(prob['hbar'], 0, tol) + assert_near_equal(prob['bbar'], 0.0003052, tol) + assert_near_equal(prob['sbar'], 0, tol) + assert_near_equal(prob['cbar'], 0.00173147, tol) + + tol = 1e-5 + assert_near_equal(prob['lift_curve_slope'], [5.94845697, 5.94845697], tol) + assert_near_equal(prob['lift_ratio'], [-0.140812203, -0.140812203], tol) + + assert_near_equal(prob['ufac'], [0.975, 0.975], tol) + + tol = 1e-6 + assert_near_equal(prob['cf'], [0.00283643, 0.00283643], tol) + assert_near_equal(prob['SA1'], [0.80832432, 0.80832432], tol) + assert_near_equal(prob['SA2'], [-0.13650645, -0.13650645], tol) + assert_near_equal(prob['SA3'], [0.03398855, 0.03398855], tol) + assert_near_equal(prob['SA4'], [0.10197432, 0.10197432], tol) + assert_near_equal(prob['SA5'], [0.00773867, 0.00773867], tol) + assert_near_equal(prob['SA6'], [2.09276756, 2.09276756], tol) + assert_near_equal(prob['SA7'], [0.03978045, 0.03978045], tol) + + assert_near_equal(prob[Aircraft.Fuselage.FORM_FACTOR], 1.35024721, tol) + assert_near_equal(prob['siwb'], 0.96497277, tol) + + +class GroundEffectTest(unittest.TestCase): + """Test fuselage form factor computation and SIWB computation""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'kclge', + GroundEffect(num_nodes=2), + promotes=['*'], + ) + + # mission inputs + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, [-2.0, -2.0], units='deg') + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, [0.0, 0.0], units='ft') + prob.model.set_input_defaults( + 'lift_curve_slope', [5.94845697, 5.94845697], units='unitless' + ) + # user inputs + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, -1.2, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.HEIGHT, 12.5, units='ft') + prob.model.set_input_defaults('airport_alt', 0.0, units='ft') + prob.model.set_input_defaults('flap_defl', 10.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + # from flaps + prob.model.set_input_defaults('dCL_flaps_model', 0.4182, units='unitless') + # from sizing + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-7 + assert_near_equal(prob['kclge'], [1.15064679, 1.15064679], tol) + + +class BWBBodyLiftCurveSlopeTest(unittest.TestCase): + """Body lift curve slope test for BWB""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'body_lift_curve_slope', + BWBBodyLiftCurveSlope(num_nodes=3), + promotes=['*'], + ) + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.2, 0.198, 0.8], units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, 1.8265, units='1/rad' + ) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['body_lift_curve_slope'], [1.86416388, 1.86339139, 3.04416667], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class BWBLiftCoeffTest(unittest.TestCase): + """Body lift curve slope test for BWB""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'lift_coeff', + BWBLiftCoeff(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, [-2.0, -2.0], units='deg') + prob.model.set_input_defaults( + 'lift_curve_slope', [5.94845697, 5.94845697], units='unitless' + ) + prob.model.set_input_defaults( + 'body_lift_curve_slope', [3.04416667, 3.04416667], units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, -1.2, units='deg') + prob.model.set_input_defaults('CL_max_flaps', 2.188, units='unitless') + prob.model.set_input_defaults('dCL_flaps_model', 0.4182, units='unitless') + prob.model.set_input_defaults('kclge', [1.22698872, 1.22698872], units='unitless') + prob.model.set_input_defaults('flap_factor', [0.9, 0.9], units='unitless') + + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['CL'], [0.1258803, 0.1258803], tol) + assert_near_equal(prob['alpha_stall'], [12.69318852, 12.69318852], tol) + assert_near_equal(prob['CL_max'], [2.188, 2.188], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + def test_case2(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'lift_coeff', + BWBLiftCoeff(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, [21.4, 21.4], units='deg') + prob.model.set_input_defaults('lift_curve_slope', [4.6386786, 4.6386786], units='unitless') + prob.model.set_input_defaults( + 'body_lift_curve_slope', [1.85912228, 1.85912228], units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, 0.0, units='deg') + prob.model.set_input_defaults('CL_max_flaps', 2.12823462, units='unitless') + prob.model.set_input_defaults('dCL_flaps_model', 0.390711457, units='unitless') + prob.model.set_input_defaults('kclge', [1.001, 1.001], units='unitless') + prob.model.set_input_defaults('flap_factor', [0.9, 0.9], units='unitless') + + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['CL'], [1.94668613, 1.94668613], tol) + assert_near_equal(prob['alpha_stall'], [21.44000465, 21.44000465], tol) + assert_near_equal(prob['CL_max'], [2.12823462, 2.12823462], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class BWBLiftCoeffCleanTest(unittest.TestCase): + """Body lift curve slope test for BWB""" + + def test_case1(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'body_lift_curve_slope', + BWBLiftCoeffClean(num_nodes=2, output_alpha=False), + promotes=['*'], + ) + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, val=[1.5, 1.5], units='deg') + prob.model.set_input_defaults('lift_curve_slope', [5.9489522, 5.9489522], units='unitless') + prob.model.set_input_defaults( + 'body_lift_curve_slope', [3.04416704, 3.04416704], units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, 0.0, units='deg') + prob.model.set_input_defaults( + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, 1.53789318, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['CL'], [0.17056343, 0.17056343], tol) + assert_near_equal(prob['alpha_stall'], [14.81181653, 14.81181653], tol) + assert_near_equal(prob['CL_max'], [1.53789318, 1.53789318], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + def test_case2(self): + prob = om.Problem() + + prob.model.add_subsystem( + 'lift_coeff_clean', + BWBLiftCoeffClean(num_nodes=2, output_alpha=True), + promotes=['*'], + ) + prob.model.set_input_defaults('CL', val=[0.416944444, 0.416944444], units='unitless') + prob.model.set_input_defaults('lift_curve_slope', [5.9489522, 5.9489522], units='unitless') + prob.model.set_input_defaults( + 'body_lift_curve_slope', [3.04416704, 3.04416704], units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, 0.0, units='deg') + prob.model.set_input_defaults( + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, 1.53789318, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['mod_lift_curve_slope'], [6.51504303212, 6.51504303212], tol) + assert_near_equal(prob[Dynamic.Vehicle.ANGLE_OF_ATTACK], [3.66676903, 3.66676903], tol) + assert_near_equal(prob['alpha_stall'], [14.8118105, 14.8118105], tol) + assert_near_equal(prob['CL_max'], [1.53789318, 1.53789318], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-11) + + +class DragCoefTest(unittest.TestCase): + def test_case1(self): + """BWB data""" + prob = om.Problem() + prob.model.add_subsystem( + 'drag_coeff', + DragCoef(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, [0.0, 0.0], units='ft') + prob.model.set_input_defaults('CL', [0.09930717, 0.09930717], units='unitless') + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults('flap_defl', 10.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.HEIGHT, 12.5, units='ft') + prob.model.set_input_defaults('airport_alt', 0.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3, units='unitless') + # from flaps + prob.model.set_input_defaults('dCL_flaps_model', 0.4182, units='unitless') + prob.model.set_input_defaults('dCD_flaps_model', 0.0, units='unitless') + prob.model.set_input_defaults('dCL_flaps_coef', 0.285, units='unitless') + prob.model.set_input_defaults('CDI_factor', 0.99, units='unitless') + # from sizing + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + + # from aero setup + prob.model.set_input_defaults('cf', [0.00283643, 0.00283643], units='unitless') + prob.model.set_input_defaults('SA5', [0.00962771, 0.00962771], units='unitless') + prob.model.set_input_defaults('SA6', [2.09276756, 2.09276756], units='unitless') + prob.model.set_input_defaults('SA7', [0.04049836, 0.04049836], units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-4 + assert_near_equal(prob['CD_base'], [0.015568, 0.015568], tol) + assert_near_equal(prob['dCD_flaps_full'], [0.0, 0.0], tol) + assert_near_equal(prob['dCD_gear_full'], [0.01619421, 0.01619421], tol) + + def test_case2(self): + """BWB data""" + prob = om.Problem() + prob.model.add_subsystem( + 'drag_coeff', + DragCoef(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, [0.0, 0.0], units='ft') + prob.model.set_input_defaults('CL', [0.153386101, 0.153386101], units='unitless') + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults('flap_defl', 0.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.HEIGHT, 12.5, units='ft') + prob.model.set_input_defaults('airport_alt', 0.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.2, units='unitless') + # from flaps + prob.model.set_input_defaults('dCL_flaps_model', 0.0, units='unitless') + prob.model.set_input_defaults('dCD_flaps_model', 0.0, units='unitless') + prob.model.set_input_defaults('dCL_flaps_coef', 1.0, units='unitless') + prob.model.set_input_defaults('CDI_factor', 1.0, units='unitless') + # from sizing + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + + # from aero setup + prob.model.set_input_defaults('cf', [0.00299267168, 0.00299267168], units='unitless') + prob.model.set_input_defaults('SA5', [0.00469374005, 0.00469374005], units='unitless') + prob.model.set_input_defaults('SA6', [2.2417531, 2.2417531], units='unitless') + prob.model.set_input_defaults('SA7', [0.0343577638, 0.0343577638], units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-4 + assert_near_equal(prob['CD_base'], [0.01177871, 0.01177871], tol) + assert_near_equal(prob['dCD_flaps_full'], [0.0, 0.0], tol) + assert_near_equal(prob['dCD_gear_full'], [0.01781363, 0.01781363], tol) + + +class DragCoefCleanTest(unittest.TestCase): + def test_case1(self): + """BWB data""" + prob = om.Problem() + prob.model.add_subsystem( + 'drag_coeff_clean', + DragCoefClean(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.8, 0.8], units='unitless') + prob.model.set_input_defaults('CL', [0.41069701, 0.41069701], units='unitless') + + # user inputs + prob.model.set_input_defaults( + Aircraft.Design.DRAG_DIVERGENCE_SHIFT, 0.025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + + # from aero setup + prob.model.set_input_defaults('cf', [0.00283643, 0.00283643], units='unitless') + prob.model.set_input_defaults('SA1', [0.80832432, 0.80832432], units='unitless') + prob.model.set_input_defaults('SA2', [-0.13650645, -0.13650645], units='unitless') + prob.model.set_input_defaults('SA5', [0.00962771, 0.00962771], units='unitless') + prob.model.set_input_defaults('SA6', [2.09276756, 2.09276756], units='unitless') + prob.model.set_input_defaults('SA7', [0.04049836, 0.04049836], units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-4 + assert_near_equal(prob['CD'], [0.02251097, 0.02251097], tol) + + def test_case2(self): + """BWB data""" + prob = om.Problem() + prob.model.add_subsystem( + 'drag_coeff_clean', + DragCoefClean(num_nodes=2), + promotes=['*'], + ) + + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.8, 0.8], units='unitless') + prob.model.set_input_defaults('CL', [0.407537609, 0.407537609], units='unitless') + + # user inputs + prob.model.set_input_defaults( + Aircraft.Design.DRAG_DIVERGENCE_SHIFT, 0.025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 0.85, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + + # from aero setup + prob.model.set_input_defaults('cf', [0.00237964187, 0.00283643], units='unitless') + prob.model.set_input_defaults('SA1', [0.814, 0.814], units='unitless') + prob.model.set_input_defaults('SA2', [-0.1374255, -0.1374255], units='unitless') + prob.model.set_input_defaults('SA5', [0.004464, 0.004464], units='unitless') + prob.model.set_input_defaults('SA6', [2.2387743, 2.2387743], units='unitless') + prob.model.set_input_defaults('SA7', [0.0341357663, 0.0341357663], units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-4 + assert_near_equal(prob['CD'], [0.01465816, 0.0156808], tol) + + +class BWBCruiseAeroTest(unittest.TestCase): + def setUp(self): + self.options = options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + options.set_val(Aircraft.Wing.HAS_STRUT, False) + + self.prob = prob = om.Problem() + + # BWBAeroSetup/WingTailRatios + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AVERAGE_CHORD, 0.0280845, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + + # BWBAeroSetup/Xlifts + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.8, 0.8], units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STATIC_MARGIN, 0.05, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.CG_DELTA, 0.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.HorizontalTail.SWEEP, 45.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + + # BWBAeroSetup/BWBFormFactorAndSIWB + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + + # BWBAeroSetup/AeroGeom + prob.model.set_input_defaults( + Dynamic.Atmosphere.SPEED_OF_SOUND, [993.11760441, 993.11760441], units='ft/s' + ) + prob.model.set_input_defaults( + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' + ) + prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.5627, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.FORM_FACTOR, 1.2, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.FORM_FACTOR, 2.361, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.FORM_FACTOR, 2.413, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, 0.00025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, 0.25, units='ft**2' + ) + prob.model.set_input_defaults(Aircraft.Wing.MIN_PRESSURE_LOCATION, 0.275, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.325, units='unitless') + prob.model.set_input_defaults(Aircraft.Strut.AREA_RATIO, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.AVERAGE_CHORD, 10.67, units='ft') + prob.model.set_input_defaults(Aircraft.Nacelle.AVG_LENGTH, 18.11, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults(Aircraft.Nacelle.SURFACE_AREA, 411.93, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.1, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13596576, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Strut.CHORD, 0.0, units='ft') + + # BWBBodyLiftCurveSlope + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, 1.8265, units='1/rad' + ) + + # BWBLiftCoeffClean + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, 0.0, units='deg') + prob.model.set_input_defaults( + Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, 1.53789318, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + # DragCoefClean + prob.model.set_input_defaults( + Aircraft.Design.DRAG_DIVERGENCE_SHIFT, 0.025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, 1.0, units='unitless' + ) + + # AeroForces + prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + + def test_case1(self): + """ + output_alpha = False + GASP resport by ctaer.f + ALPHA = 3.611767 + CL = CLREQ = 0.41069 + CD = 0.014738 + """ + prob = self.prob + options = self.options + + prob.model.add_subsystem( + 'aero', + CruiseAero(num_nodes=2, input_atmos=True), + promotes=['*'], + ) + + # BWBLiftCoeffClean + prob.model.set_input_defaults( + Dynamic.Vehicle.ANGLE_OF_ATTACK, [3.611767, 3.611767], units='deg' + ) + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['body_lift_curve_slope'], [3.04416667, 3.04416667], tol) + + assert_near_equal(prob['CL'], [0.41067052, 0.41067052], tol) + assert_near_equal(prob['alpha_stall'], [14.81304968, 14.81304968], tol) + assert_near_equal(prob['CL_max'], [1.53789318, 1.537893184], tol) + + assert_near_equal(prob['CD'], [0.02049917, 0.02049917], tol) + + CL_over_CD = prob['CL'] / prob['CD'] + assert_near_equal(CL_over_CD, [20.03351946, 20.03351946], tol) + + assert_near_equal(prob[Dynamic.Vehicle.LIFT], [880.00827387, 880.00827387], tol) + assert_near_equal(prob[Dynamic.Vehicle.DRAG], [43.92679357, 43.92679357], tol) + + def test_case2(self): + """output_alpha = True""" + prob = self.prob + options = self.options + + prob.model.add_subsystem( + 'aero', + CruiseAero(num_nodes=2, input_atmos=True, output_alpha=True), + promotes=['*'], + ) + + # CLFromLift + prob.model.set_input_defaults('lift_req', [817.74, 817.74], units='lbf') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['body_lift_curve_slope'], [3.04416667, 3.04416667], tol) + + assert_near_equal(prob['mod_lift_curve_slope'], [6.51473022, 6.51473022], tol) + assert_near_equal(prob[Dynamic.Vehicle.ANGLE_OF_ATTACK], [3.35620293, 3.35620293], tol) + assert_near_equal(prob['alpha_stall'], [14.81304968, 14.81304968], tol) + assert_near_equal(prob['CL_max'], [1.53789318, 1.53789318], tol) + + assert_near_equal(prob['CD'], [0.01953165, 0.01953165], tol) + assert_near_equal(prob[Dynamic.Vehicle.LIFT], [817.74, 817.74], tol) + assert_near_equal(prob[Dynamic.Vehicle.DRAG], [41.8535328, 41.8535328], tol) + + +class BWBLowSpeedAeroTest1(unittest.TestCase): + def setUp(self): + self.options = options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + options.set_val(Aircraft.Wing.HAS_STRUT, False) + + self.prob = prob = om.Problem() + + # BWBAeroSetup/WingTailRatios + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AVERAGE_CHORD, 0.0280845, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + + # BWBAeroSetup/Xlifts + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.2, 0.2], units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STATIC_MARGIN, 0.05, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.CG_DELTA, 0.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.HorizontalTail.SWEEP, 45.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + + # BWBAeroSetup/BWBFormFactorAndSIWB + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + + # BWBAeroSetup/AeroGeom + prob.model.set_input_defaults( + Dynamic.Atmosphere.SPEED_OF_SOUND, [993.11760441, 993.11760441], units='ft/s' + ) + prob.model.set_input_defaults( + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' + ) + prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.563, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.FORM_FACTOR, 1.2, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.FORM_FACTOR, 2.361, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.FORM_FACTOR, 2.413, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, 0.00025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, 0.25, units='ft**2' + ) + prob.model.set_input_defaults(Aircraft.Wing.MIN_PRESSURE_LOCATION, 0.275, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.325, units='unitless') + prob.model.set_input_defaults(Aircraft.Strut.AREA_RATIO, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.AVERAGE_CHORD, 10.67, units='ft') + prob.model.set_input_defaults(Aircraft.Nacelle.AVG_LENGTH, 18.11, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults(Aircraft.Nacelle.SURFACE_AREA, 411.93, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.1, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13596576, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Strut.CHORD, 0.0, units='ft') + + # GroundEffect/mission inputs + prob.model.set_input_defaults(Dynamic.Vehicle.ANGLE_OF_ATTACK, [-2.0, -2.0], units='deg') + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, [0.0, 0.0], units='ft') + # GroundEffect/user inputs + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, -1.2, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.HEIGHT, 12.5, units='ft') + prob.model.set_input_defaults('airport_alt', 0.0, units='ft') + prob.model.set_input_defaults('flap_defl', 10.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3, units='unitless') + # GroundEffect/from flaps + prob.model.set_input_defaults('dCL_flaps_model', 0.4182, units='unitless') + + # BWBBodyLiftCurveSlope + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, 1.8265, units='1/rad' + ) + + # BWBLiftCoeff + prob.model.set_input_defaults('CL_max_flaps', 2.188, units='unitless') + prob.model.set_input_defaults('flap_factor', [0.9, 0.9], units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + # AeroForces + prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + + def test_case1(self): + """BWB data with lift_required = False""" + prob = self.prob + options = self.options + options.set_val('output_alpha', False) + + prob.model.add_subsystem( + 'aero', + LowSpeedAero(num_nodes=2, input_atmos=True), + promotes=['*'], + ) + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + tol = 1e-6 + assert_near_equal(prob['flap_factor'], [[0.89035722], [0.89035722]], tol) + assert_near_equal(prob['gear_factor'], [[0.98888178], [0.98888178]], tol) + + assert_near_equal(prob['lift_ratio'], [-0.140812203, -0.140812203], tol) + assert_near_equal(prob['lift_curve_slope'], [4.63845672, 4.63845672], tol) + assert_near_equal(prob['kclge'], [1.13973561, 1.13973561], tol) + assert_near_equal(prob['body_lift_curve_slope'], [1.86416376, 1.86416376], tol) + + assert_near_equal(prob['CL'], [0.16146027, 0.16146027], tol) + assert_near_equal(prob['alpha_stall'], [17.98090961, 17.98090961], tol) + assert_near_equal(prob['CL_max'], [2.188, 2.188], tol) + + assert_near_equal(prob['CD'], [0.01760887, 0.01760887], tol) + assert_near_equal(prob[Dynamic.Vehicle.LIFT], [345.98630135, 345.98630135], tol) + assert_near_equal(prob[Dynamic.Vehicle.DRAG], [37.73329763, 37.73329763], tol) + + +class BWBLowSpeedAeroTest2(unittest.TestCase): + def setUp(self): + self.options = options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + options.set_val(Aircraft.Wing.HAS_STRUT, False) + options.set_val('output_alpha', False) + + self.prob = prob = om.Problem() + + # BWBAeroSetup/WingTailRatios + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AVERAGE_CHORD, 0.0280845, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + + # BWBAeroSetup/Xlifts + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.2, 0.2], units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STATIC_MARGIN, 0.05, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.CG_DELTA, 0.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.HorizontalTail.SWEEP, 45.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + + # BWBAeroSetup/BWBFormFactorAndSIWB + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + + # BWBAeroSetup/AeroGeom + prob.model.set_input_defaults( + Dynamic.Atmosphere.SPEED_OF_SOUND, [993.11760441, 993.11760441], units='ft/s' + ) + prob.model.set_input_defaults( + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' + ) + prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.563, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.FORM_FACTOR, 1.2, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.FORM_FACTOR, 2.361, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.FORM_FACTOR, 2.413, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, 0.00025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, 0.25, units='ft**2' + ) + prob.model.set_input_defaults(Aircraft.Wing.MIN_PRESSURE_LOCATION, 0.275, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.325, units='unitless') + prob.model.set_input_defaults(Aircraft.Strut.AREA_RATIO, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.AVERAGE_CHORD, 10.67, units='ft') + prob.model.set_input_defaults(Aircraft.Nacelle.AVG_LENGTH, 18.11, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults(Aircraft.Nacelle.SURFACE_AREA, 411.93, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.1, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13596576, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Strut.CHORD, 0.0, units='ft') + + # GroundEffect/mission inputs + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, [1500.0, 1500.0], units='ft') + # GroundEffect/user inputs + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, 0.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.HEIGHT, 12.5, units='ft') + prob.model.set_input_defaults('airport_alt', 0.0, units='ft') + prob.model.set_input_defaults('flap_defl', 15.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3, units='unitless') + # GroundEffect/from flaps + prob.model.set_input_defaults('dCL_flaps_model', 0.38993, units='unitless') + prob.model.set_input_defaults('dCD_flaps_model', 0.0062256, units='unitless') + + # BWBBodyLiftCurveSlope + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, 1.8265, units='1/rad' + ) + + # BWBLiftCoeff + prob.model.set_input_defaults('CL_max_flaps', 1.94939148, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + # AeroForces + prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + + options = self.options + setup_model_options(prob, options) + + prob.model.add_subsystem( + 'aero', + LowSpeedAero(num_nodes=2, input_atmos=True, retract_gear=True, retract_flaps=True), + promotes=['*'], + ) + + def test_case1(self): + """ + BWB data with lift_required = False + Take off + In GASP: + ALPHA = [-2.0, 0.0, 2.0] + ADELF(2) = DFLPTO = 15 + DELCL = DCLTO = 0.38993 + DELCDF = DCDTO = 0.0062256 + CL = 0.07507, 0.23964, 0.40422 + CD = 0.01853, 0.01866, 0.02070 + CL/CD = 4.05136, 12.84433, 19.53199 + """ + + prob = self.prob + tol = 1e-6 + aoas = [-2.0, 0.0, 2.0] + CLs = [0.0578734, 0.21906393, 0.38025445] + CL_Full_Flaps = [0.08484997, 0.24604049, 0.40723101] + CDs = [0.02322085, 0.02348309, 0.02594446] + CL_Over_CDs = [3.65404194, 10.47734718, 15.69626012] + n = len(aoas) + for i in range(n): + prob.model.set_input_defaults( + Dynamic.Vehicle.ANGLE_OF_ATTACK, [aoas[i], aoas[i]], units='deg' + ) + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + assert_near_equal(prob['CL'], [CLs[i], CLs[i]], tol) + assert_near_equal(prob['CL_full_flaps'], [CL_Full_Flaps[i], CL_Full_Flaps[i]], tol) + assert_near_equal(prob['CD'], [CDs[i], CDs[i]], tol) + CL_over_CD = prob['CL_full_flaps'] / prob['CD'] + assert_near_equal(CL_over_CD, [CL_Over_CDs[i], CL_Over_CDs[i]], tol) + + +class BWBLowSpeedAeroTest3(unittest.TestCase): + def setUp(self): + self.options = options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + options.set_val(Aircraft.Wing.HAS_STRUT, False) + options.set_val('output_alpha', False) + + self.prob = prob = om.Problem() + + # BWBAeroSetup/WingTailRatios + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200522, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AVERAGE_CHORD, 0.0280845, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + + # BWBAeroSetup/Xlifts + prob.model.set_input_defaults(Dynamic.Atmosphere.MACH, [0.2, 0.2], units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STATIC_MARGIN, 0.05, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.CG_DELTA, 0.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.HorizontalTail.SWEEP, 45.0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + + # BWBAeroSetup/BWBFormFactorAndSIWB + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + + # BWBAeroSetup/AeroGeom + prob.model.set_input_defaults( + Dynamic.Atmosphere.SPEED_OF_SOUND, [993.11760441, 993.11760441], units='ft/s' + ) + prob.model.set_input_defaults( + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, [0.00034882, 0.00034882], units='ft**2/s' + ) + prob.model.set_input_defaults(Aircraft.Wing.FORM_FACTOR, 2.563, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.FORM_FACTOR, 1.2, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.FORM_FACTOR, 2.361, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.FORM_FACTOR, 2.413, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, 0.00025, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, 0.25, units='ft**2' + ) + prob.model.set_input_defaults(Aircraft.Wing.MIN_PRESSURE_LOCATION, 0.275, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MAX_THICKNESS_LOCATION, 0.325, units='unitless') + prob.model.set_input_defaults(Aircraft.Strut.AREA_RATIO, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.AVERAGE_CHORD, 10.67, units='ft') + prob.model.set_input_defaults(Aircraft.Nacelle.AVG_LENGTH, 18.11, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults(Aircraft.Nacelle.SURFACE_AREA, 411.93, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.1, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, 0.13596576, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Strut.CHORD, 0.0, units='ft') + + # GroundEffect/mission inputs + prob.model.set_input_defaults(Dynamic.Mission.ALTITUDE, [1500.0, 1500.0], units='ft') + # GroundEffect/user inputs + prob.model.set_input_defaults(Aircraft.Wing.ZERO_LIFT_ANGLE, 0.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.HEIGHT, 12.5, units='ft') + prob.model.set_input_defaults('airport_alt', 0.0, units='ft') + prob.model.set_input_defaults('flap_defl', 25.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.3, units='unitless') + # GroundEffect/from flaps + prob.model.set_input_defaults('dCL_flaps_model', 0.56964, units='unitless') + prob.model.set_input_defaults('dCD_flaps_model', 0.0105864, units='unitless') + + # BWBBodyLiftCurveSlope + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, 1.8265, units='1/rad' + ) + + # BWBLiftCoeff + prob.model.set_input_defaults('CL_max_flaps', 1.94939148, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.11353, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, 1943.76587, units='ft**2') + + # AeroForces + prob.model.set_input_defaults(Dynamic.Atmosphere.DYNAMIC_PRESSURE, [1.0, 1.0], units='psf') + + options = self.options + setup_model_options(prob, options) + + prob.model.add_subsystem( + 'aero', + LowSpeedAero(num_nodes=2, input_atmos=True, retract_gear=True, retract_flaps=True), + promotes=['*'], + ) + + def test_case1(self): + """ + BWB data with lift_required = False + Landing + In GASP: + ALPHA = [-2.0, 0.0, 2.0] + ADELF(3) = DFLPLD = 25 + DELCL = DCLLD = 0.56964 + DELCDF = DCDLD = 0.0105864 + CL = 0.18551, 0.35009, 0.51467 + CD = 0.02299, 0.02292, 0.02482 + CL/CD = 8.06918, 15.27225, 20.74018 + """ + + prob = self.prob + tol = 1e-6 + aoas = [-2.0, 0.0, 2.0] + CLs = [0.15883506, 0.32002558, 0.4812161] + CL_Full_Flaps = [0.19824452, 0.35943504, 0.52062556] + CDs = [0.02718958, 0.02726536, 0.02959784] + CL_Over_CDs = [7.29119323, 13.18284568, 17.5899862] + n = len(aoas) + for i in range(n): + print(f'i = {i}') + prob.model.set_input_defaults( + Dynamic.Vehicle.ANGLE_OF_ATTACK, [aoas[i], aoas[i]], units='deg' + ) + prob.setup(check=False, force_alloc_complex=True) + prob.run_model() + + assert_near_equal(prob['CL'], [CLs[i], CLs[i]], tol) + assert_near_equal(prob['CL_full_flaps'], [CL_Full_Flaps[i], CL_Full_Flaps[i]], tol) + assert_near_equal(prob['CD'], [CDs[i], CDs[i]], tol) + CL_over_CD = prob['CL_full_flaps'] / prob['CD'] + assert_near_equal(CL_over_CD, [CL_Over_CDs[i], CL_Over_CDs[i]], tol) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_interference.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_interference.py index 06a5325209..b9b455a505 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_interference.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_interference.py @@ -1,59 +1,64 @@ import unittest -from dymos.models.atmosphere.atmos_1976 import USatm1976Comp import openmdao.api as om +from dymos.models.atmosphere.atmos_1976 import USatm1976Comp from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.aerodynamics.gasp_based.interference import RootChord, \ - CommonVariables, TopAndBottomWidth, BodyRatios, InterferenceDrag, \ - WingFuselageInterferencePremission, WingFuselageInterferenceMission +from aviary.subsystems.aerodynamics.gasp_based.interference import ( + BodyRatios, + CommonVariables, + InterferenceDrag, + RootChord, + TopAndBottomWidth, + WingFuselageInterferenceMission, + WingFuselageInterferencePremission, +) from aviary.variable_info.variables import Aircraft, Dynamic - tol = 1e-6 class TestPreMissionSubComponents(unittest.TestCase): def test_root_chord(self): prob = om.Problem() - prob.model.add_subsystem("comp", RootChord(), promotes=["*"]) + prob.model.add_subsystem('comp', RootChord(), promotes=['*']) prob.setup(force_alloc_complex=True) prob.set_val(Aircraft.Wing.AREA, 1400) prob.set_val(Aircraft.Wing.SPAN, 118) - prob.set_val(Aircraft.Wing.TAPER_RATIO, .9) + prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.9) prob.run_model() assert_near_equal(prob.get_val('CROOT'), [12.48884924], tol) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) def test_common_vars(self): prob = om.Problem() - prob.model.add_subsystem("comp", CommonVariables(), promotes=["*"]) + prob.model.add_subsystem('comp', CommonVariables(), promotes=['*']) prob.setup(force_alloc_complex=True) prob.set_val('CROOT', 12) - prob.set_val(Aircraft.Wing.MOUNTING_TYPE, .1) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, .12) + prob.set_val(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.1) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.12) prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 10) prob.run_model() - assert_near_equal(prob.get_val('ZW_RF'), [-.8], tol) - assert_near_equal(prob.get_val('wtofd'), [.144], tol) + assert_near_equal(prob.get_val('ZW_RF'), [-0.8], tol) + assert_near_equal(prob.get_val('wtofd'), [0.144], tol) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) def test_top_and_bottom(self): prob = om.Problem() - prob.model.add_subsystem("comp", TopAndBottomWidth(), promotes=["*"]) + prob.model.add_subsystem('comp', TopAndBottomWidth(), promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val('wtofd', .14) + prob.set_val('wtofd', 0.14) prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 10) for z in (-1, 1): prob.set_val('ZW_RF', z) @@ -62,49 +67,50 @@ def test_top_and_bottom(self): assert_near_equal(prob.get_val('WBODYWF'), [2.55147016], tol) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) def test_body_ratios(self): prob = om.Problem() - prob.model.add_subsystem("comp", BodyRatios(), promotes=["*"]) + prob.model.add_subsystem('comp', BodyRatios(), promotes=['*']) prob.setup(force_alloc_complex=True) prob.set_val('WBODYWF', 2.5) prob.set_val('CROOT', 12) prob.set_val(Aircraft.Wing.SPAN, 118) - prob.set_val(Aircraft.Wing.TAPER_RATIO, .9) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, .12) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, .1) + prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.9) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.12) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1) prob.run_model() assert_near_equal(prob.get_val('TCBODYWF'), [0.11957627], tol) assert_near_equal(prob.get_val('CBODYWF'), [11.974576], tol) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) def test_interference_drag(self): prob = om.Problem() - prob.model.add_subsystem("comp", InterferenceDrag(), promotes=["*"]) + prob.model.add_subsystem('comp', InterferenceDrag(), promotes=['*']) prob.setup(force_alloc_complex=True) prob.set_val('WBODYWF', 2.5) prob.set_val('CROOT', 12) - prob.set_val('TCBODYWF', .1) + prob.set_val('TCBODYWF', 0.1) prob.set_val('CBODYWF', 12) - prob.set_val('ZW_RF', .5) + prob.set_val('ZW_RF', 0.5) prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 10) - prob.set_val(Aircraft.Wing.CENTER_DISTANCE, .6) + prob.set_val(Aircraft.Wing.CENTER_DISTANCE, 0.6) prob.run_model() - assert_near_equal(prob.get_val( - 'interference_independent_of_shielded_area'), [0.05654201], tol) + assert_near_equal( + prob.get_val('interference_independent_of_shielded_area'), [0.05654201], tol + ) assert_near_equal(prob.get_val('drag_loss_due_to_shielded_wing_area'), [30], tol) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) @@ -112,29 +118,33 @@ class TestPreMission(unittest.TestCase): def test_complete_group(self): prob = om.Problem() prob.model.add_subsystem( - "comp", WingFuselageInterferencePremission(), - promotes=["aircraft:*", - 'interference_independent_of_shielded_area', - 'drag_loss_due_to_shielded_wing_area']) + 'comp', + WingFuselageInterferencePremission(), + promotes=[ + 'aircraft:*', + 'interference_independent_of_shielded_area', + 'drag_loss_due_to_shielded_wing_area', + ], + ) prob.setup(force_alloc_complex=True) prob.set_val(Aircraft.Wing.AREA, 1400) prob.set_val(Aircraft.Wing.SPAN, 118) - prob.set_val(Aircraft.Wing.TAPER_RATIO, .9) - prob.set_val(Aircraft.Wing.MOUNTING_TYPE, .1) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, .12) - prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, .1) + prob.set_val(Aircraft.Wing.TAPER_RATIO, 0.9) + prob.set_val(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.1) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.12) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1) prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 12) - prob.set_val(Aircraft.Wing.CENTER_DISTANCE, .6) + prob.set_val(Aircraft.Wing.CENTER_DISTANCE, 0.6) prob.run_model() - assert_near_equal(prob.get_val( - 'interference_independent_of_shielded_area'), [0.35794891], tol) - assert_near_equal(prob.get_val( - 'drag_loss_due_to_shielded_wing_area'), [83.53366], tol) + assert_near_equal( + prob.get_val('interference_independent_of_shielded_area'), [0.35794891], tol + ) + assert_near_equal(prob.get_val('drag_loss_due_to_shielded_wing_area'), [83.53366], tol) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) @@ -143,43 +153,45 @@ def test_complete_group(self): nn = 2 prob = om.Problem() prob.model.add_subsystem( - "atmos", + 'atmos', USatm1976Comp(num_nodes=nn), - promotes_inputs=[("h", Dynamic.Mission.ALTITUDE)], - promotes_outputs=['rho', "viscosity", - ("temp", Dynamic.Mission.TEMPERATURE)], + promotes_inputs=[('h', Dynamic.Mission.ALTITUDE)], + promotes_outputs=['rho', 'viscosity', ('temp', Dynamic.Atmosphere.TEMPERATURE)], ) prob.model.add_subsystem( - "kin_visc", + 'kin_visc', om.ExecComp( - "nu = viscosity / rho", - viscosity={"units": "lbf*s/ft**2", "shape": nn}, - rho={"units": "slug/ft**3", "shape": nn}, - nu={"units": "ft**2/s", "shape": nn}, + 'nu = viscosity / rho', + viscosity={'units': 'lbf*s/ft**2', 'shape': nn}, + rho={'units': 'slug/ft**3', 'shape': nn}, + nu={'units': 'ft**2/s', 'shape': nn}, has_diag_partials=True, ), - promotes=["*", ('nu', Dynamic.Mission.KINEMATIC_VISCOSITY)], + promotes=['*', ('nu', Dynamic.Atmosphere.KINEMATIC_VISCOSITY)], ) prob.model.add_subsystem( - "comp", WingFuselageInterferenceMission(num_nodes=nn), - promotes=["*"]) + 'comp', WingFuselageInterferenceMission(num_nodes=nn), promotes=['*'] + ) prob.setup(force_alloc_complex=True) prob.set_val(Aircraft.Wing.FORM_FACTOR, 1.25) prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12) - prob.set_val(Dynamic.Mission.MACH, (.6, .65)) + prob.set_val(Dynamic.Atmosphere.MACH, (0.6, 0.65)) prob.set_val(Dynamic.Mission.ALTITUDE, (30000, 30000)) prob.set_val('interference_independent_of_shielded_area', 0.35794891) prob.set_val('drag_loss_due_to_shielded_wing_area', 83.53366) prob.run_model() - assert_near_equal(prob.get_val('wing_fuselage_interference_flat_plate_equivalent'), [ - 83.53249732, 83.53251792], tol) + assert_near_equal( + prob.get_val('wing_fuselage_interference_flat_plate_equivalent'), + [83.53249732, 83.53251792], + tol, + ) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=1e-12, rtol=1e-14) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_solved_aero_group.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_solved_aero_group.py new file mode 100644 index 0000000000..e5b96792e6 --- /dev/null +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_solved_aero_group.py @@ -0,0 +1,351 @@ +""" +This test validates passing a drag polar into the solved aero in the mission. +Computed lift and drag should be the same as reading the same polar in from +a file. +""" + +import unittest +from copy import deepcopy + +import numpy as np +import openmdao.api as om +from openmdao.utils.assert_utils import assert_near_equal + +from aviary.models.missions.height_energy_default import phase_info +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase +from aviary.utils.csv_data_file import read_data_file +from aviary.utils.named_values import NamedValues +from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.variables import Aircraft + +# The drag-polar-generating component reads this in, instead of computing the polars. +polar_file = 'models/large_single_aisle_1/large_single_aisle_1_aero_free_reduced_alpha.csv' + +phase_info = deepcopy(phase_info) + +phase_info['pre_mission']['include_takeoff'] = False +phase_info['post_mission']['include_landing'] = False +phase_info['cruise']['subsystem_options']['core_aerodynamics']['method'] = 'tabular_cruise' +phase_info['cruise']['subsystem_options']['core_aerodynamics']['solve_alpha'] = True +phase_info['cruise']['subsystem_options']['core_aerodynamics']['aero_data'] = polar_file +phase_info.pop('climb') +phase_info.pop('descent') + +data, _, _ = read_data_file(polar_file) +ALTITUDE = data.get_val('Altitude', 'ft') +MACH = data.get_val('Mach', 'unitless') +ALPHA = data.get_val('Angle_of_Attack', 'deg') + +shape = (np.unique(ALTITUDE).size, np.unique(MACH).size, np.unique(ALPHA).size) +CL = data.get_val('CL').reshape(shape) +CD = data.get_val('CD').reshape(shape) + + +class TestSolvedAero(unittest.TestCase): + def get_baseline_tabular_results(self): + # Get the CL, CD of the baseline tabular aero problem + local_phase_info = deepcopy(phase_info) + + prob = AviaryProblem() + + prob.load_inputs( + 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv', + local_phase_info, + ) + prob.model.aero_method = LegacyCode.GASP + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + CL_base = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CL') + CD_base = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CD') + + return CL_base, CD_base + + def test_solved_aero_pass_polar(self): + # Test that passing training data provides the same results + # Lift and Drag polars passed from external component in pre-mission. + CL_base, CD_base = self.get_baseline_tabular_results() + + ph_in = deepcopy(phase_info) + + polar_builder = FakeDragPolarBuilder(name='aero', altitude=ALTITUDE, mach=MACH, alpha=ALPHA) + aero_data = NamedValues() + aero_data.set_val('altitude', ALTITUDE, 'ft') + aero_data.set_val('mach', MACH, 'unitless') + aero_data.set_val('angle_of_attack', ALPHA, 'deg') + + subsystem_options = { + 'method': 'tabular_cruise', + 'solve_alpha': True, + 'aero_data': aero_data, + 'connect_training_data': True, + } + ph_in['pre_mission']['external_subsystems'] = [polar_builder] + + ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} + + prob = AviaryProblem() + + prob.load_inputs( + 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv', + ph_in, + ) + + prob.model.aero_method = LegacyCode.GASP + + prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, np.zeros_like(CL), units='unitless') + prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, np.zeros_like(CD), units='unitless') + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + CL_pass = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CL') + CD_pass = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CD') + + assert_near_equal(CL_pass, CL_base, 1e-6) + assert_near_equal(CD_pass, CD_base, 1e-6) + + # Test the drag scaler + + prob.set_val(Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, 2.0, units='unitless') + + prob.run_model() + + CL_pass = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CL') + CD_pass = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CD') + + assert_near_equal(CL_pass, CL_base, 1e-6) + assert_near_equal(CD_pass, 2.0 * CD_base, 1e-6) + + def test_parameters(self): + # This test is to make sure that the aero builder creates a parameter + # for wing area. It addresses a bug where this was absent. + + local_phase_info = deepcopy(phase_info) + + prob = AviaryProblem() + + prob.load_inputs( + 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv', + local_phase_info, + ) + prob.model.aero_method = LegacyCode.GASP + + # Change value just to be certain. + prob.aviary_inputs.set_val(Aircraft.Wing.AREA, 7777, units='ft**2') + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + # verify that we are promoting the parameters. + wing_area = prob.get_val('traj.cruise.rhs_all.aircraft:wing:area', units='ft**2') + actual_wing_area = prob.aviary_inputs.get_val(Aircraft.Wing.AREA, units='ft**2') + assert_near_equal(wing_area, actual_wing_area) + + def test_solved_aero_pass_polar_unique_abscissa(self): + # Solved Aero with shortened lists of table abscissa. + local_phase_info = deepcopy(phase_info) + + prob = AviaryProblem() + + csv_path = 'subsystems/aerodynamics/flops_based/test/data/high_wing_single_aisle.csv' + prob.load_inputs(csv_path, local_phase_info) + prob.model.aero_method = LegacyCode.GASP + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + CL_base = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CL') + CD_base = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CD') + + # Lift and Drag polars passed from external component in pre-mission. + + ph_in = deepcopy(phase_info) + + alt = np.array( + [ + 0.0, + 3000.0, + 6000.0, + 9000.0, + 12000.0, + 15000.0, + 18000.0, + 21000.0, + 24000.0, + 27000.0, + 30000.0, + 33000.0, + 36000.0, + 38000.0, + 42000.0, + ] + ) + mach = np.array([0.0, 0.2, 0.4, 0.5, 0.6, 0.7, 0.75, 0.8, 0.85, 0.9]) + alpha = np.array([-2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0]) + + polar_builder = FakeDragPolarBuilder(name='aero', altitude=alt, mach=mach, alpha=alpha) + aero_data = NamedValues() + aero_data.set_val('altitude', alt, 'ft') + aero_data.set_val('mach', mach, 'unitless') + aero_data.set_val('angle_of_attack', alpha, 'deg') + + subsystem_options = { + 'method': 'tabular_cruise', + 'solve_alpha': True, + 'aero_data': aero_data, + 'connect_training_data': True, + } + ph_in['pre_mission']['external_subsystems'] = [polar_builder] + + ph_in['cruise']['subsystem_options'] = {'core_aerodynamics': subsystem_options} + + prob = AviaryProblem() + + prob.load_inputs(csv_path, ph_in) + prob.model.aero_method = LegacyCode.GASP + + prob.aviary_inputs.set_val(Aircraft.Design.LIFT_POLAR, np.zeros_like(CL), units='unitless') + prob.aviary_inputs.set_val(Aircraft.Design.DRAG_POLAR, np.zeros_like(CD), units='unitless') + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + CL_pass = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CL') + CD_pass = prob.get_val('traj.cruise.rhs_all.core_aerodynamics.CD') + + assert_near_equal(CL_pass, CL_base, 1e-6) + assert_near_equal(CD_pass, CD_base, 1e-6) + + +class FakeCalcDragPolar(om.ExplicitComponent): + """ + This component is a stand-in for an externally computed lift/drag table + calculation. It does nothing but read in the pre-computed table. + """ + + def initialize(self): + """Declare options.""" + self.options.declare( + 'altitude', + default=None, + allow_none=True, + desc='List of altitudes in ascending order.', + ) + self.options.declare( + 'mach', + default=None, + allow_none=True, + desc='List of mach numbers in ascending order.', + ) + self.options.declare( + 'alpha', + default=None, + allow_none=True, + desc='List of angles of attack in ascending order.', + ) + + def setup(self): + altitude = self.options['altitude'] + mach = self.options['mach'] + alpha = self.options['alpha'] + + self.add_input(Aircraft.Wing.AREA, 1.0, units='ft**2') + self.add_input(Aircraft.Wing.SPAN, 1.0, units='ft') + + shape = (len(altitude), len(mach), len(alpha)) + + self.add_output('drag_table', shape=shape, units='unitless') + self.add_output('lift_table', shape=shape, units='unitless') + + def compute(self, inputs, outputs): + """ + This component doesn't do anything, except set the drag and lift + polars from the file we read in. + + Any real analysis would compute these tables. + """ + outputs['drag_table'] = CD + outputs['lift_table'] = CL + + +class FakeDragPolarBuilder(SubsystemBuilderBase): + """ + Prototype of a subsystem that overrides an aviary internally computed var. + + Parameters + ---------- + altitude : list or None + List of altitudes in ascending order. (Optional) + mach : list or None + List of Mach numbers in ascending order. (Optional) + alpha : list or None + List of angles of attack in ascending order. (Optional) + """ + + def __init__(self, name='aero', altitude=None, mach=None, alpha=None): + super().__init__(name) + self.altitude = np.unique(altitude) + self.mach = np.unique(mach) + self.alpha = np.unique(alpha) + + def build_pre_mission(self, aviary_inputs): + """ + Build an OpenMDAO system for the pre-mission computations of the subsystem. + + Returns + ------- + pre_mission_sys : openmdao.core.Group + An OpenMDAO group containing all computations that need to happen in + the pre-mission part of the Aviary problem. This + includes sizing, design, and other non-mission parameters. + """ + group = om.Group() + + calc_drag_polar = FakeCalcDragPolar( + altitude=self.altitude, mach=self.mach, alpha=self.alpha + ) + + group.add_subsystem( + 'aero', + calc_drag_polar, + promotes_inputs=['aircraft:*'], + promotes_outputs=[ + ('drag_table', Aircraft.Design.DRAG_POLAR), + ('lift_table', Aircraft.Design.LIFT_POLAR), + ], + ) + return group + + +if __name__ == '__main__': + unittest.main() + # test = TestSolvedAero() + # test.test_solved_aero_pass_polar_unique_abscissa() diff --git a/aviary/subsystems/aerodynamics/gasp_based/test/test_table_based.py b/aviary/subsystems/aerodynamics/gasp_based/test/test_table_based.py index cfa949f192..4cbd9366a0 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/test/test_table_based.py +++ b/aviary/subsystems/aerodynamics/gasp_based/test/test_table_based.py @@ -3,75 +3,69 @@ import numpy as np import openmdao import openmdao.api as om -from aviary.utils.functions import get_aviary_resource_path from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from packaging import version from aviary.subsystems.aerodynamics.gasp_based.table_based import ( - GearDragIncrement, TabularCruiseAero, TabularLowSpeedAero) + GearDragIncrement, + TabularCruiseAero, + TabularLowSpeedAero, +) +from aviary.utils.functions import get_aviary_resource_path from aviary.variable_info.variables import Aircraft, Dynamic, Mission class TestCruiseAero(unittest.TestCase): - - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), - "Older version of OpenMDAO does not properly skip Metamodel.") def test_climb(self): prob = om.Problem() - fp = "subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt" + fp = 'models/large_single_aisle_1/large_single_aisle_1_aero_free.csv' prob.model = TabularCruiseAero(num_nodes=8, aero_data=fp) prob.setup(force_alloc_complex=True) + prob.set_val(Dynamic.Atmosphere.MACH, [0.381, 0.384, 0.391, 0.399, 0.8, 0.8, 0.8, 0.8]) prob.set_val( - Dynamic.Mission.MACH, [ - 0.381, 0.384, 0.391, 0.399, 0.8, 0.8, 0.8, 0.8]) - prob.set_val("alpha", [5.19, 5.19, 5.19, 5.18, 3.58, 3.81, 4.05, 4.18]) + Dynamic.Vehicle.ANGLE_OF_ATTACK, [5.19, 5.19, 5.19, 5.18, 3.58, 3.81, 4.05, 4.18] + ) prob.set_val( - Dynamic.Mission.ALTITUDE, [ - 500, 1000, 2000, 3000, 35000, 36000, 37000, 37500]) + Dynamic.Mission.ALTITUDE, + [500, 1000, 2000, 3000, 35000, 36000, 37000, 37500], + ) prob.run_model() - cl_exp = np.array( - [0.5968, 0.5975, 0.5974, 0.5974, 0.5566, 0.5833, 0.6113, 0.6257] - ) - cd_exp = np.array( - [0.0307, 0.0307, 0.0307, 0.0307, 0.0296, 0.0310, 0.0326, 0.0334] - ) + cl_exp = np.array([0.5968, 0.5975, 0.5974, 0.5974, 0.5566, 0.5833, 0.6113, 0.6257]) + cd_exp = np.array([0.0307, 0.0307, 0.0307, 0.0307, 0.0296, 0.0310, 0.0326, 0.0334]) - assert_near_equal(prob["CL"], cl_exp, tolerance=0.005) - assert_near_equal(prob["CD"], cd_exp, tolerance=0.009) + assert_near_equal(prob['CL'], cl_exp, tolerance=0.005) + assert_near_equal(prob['CD'], cd_exp, tolerance=0.009) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=4e-7, rtol=2e-7) - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), - "Older version of OpenMDAO does not properly skip Metamodel.") def test_cruise(self): prob = om.Problem() - ref = 'subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt' + ref = 'models/large_single_aisle_1/large_single_aisle_1_aero_free.csv' fp = get_aviary_resource_path(ref) prob.model = TabularCruiseAero(num_nodes=2, aero_data=fp) prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.MACH, [0.8, 0.8]) - prob.set_val("alpha", [4.216, 3.146]) + prob.set_val(Dynamic.Atmosphere.MACH, [0.8, 0.8]) + prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [4.216, 3.146]) prob.set_val(Dynamic.Mission.ALTITUDE, [37500, 37500]) prob.run_model() cl_exp = np.array([0.6304, 0.5059]) cd_exp = cl_exp / np.array([18.608, 18.425]) - assert_near_equal(prob["CL"], cl_exp, tolerance=0.005) - assert_near_equal(prob["CD"], cd_exp, tolerance=0.005) + assert_near_equal(prob['CL'], cl_exp, tolerance=0.005) + assert_near_equal(prob['CD'], cd_exp, tolerance=0.005) - partial_data = prob.check_partials(method="cs", out_stream=None) + partial_data = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partial_data, atol=9e-8, rtol=2e-7) class TestLowSpeedAero(unittest.TestCase): - # gear retraction start time at takeoff t_init_gear_to = 37.3 # flap retraction start time at takeoff @@ -80,14 +74,15 @@ class TestLowSpeedAero(unittest.TestCase): flap_defl_to = 10 free_data = get_aviary_resource_path( - "subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_free.txt") + 'models/large_single_aisle_1/large_single_aisle_1_aero_free.csv' + ) flaps_data = get_aviary_resource_path( - "subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_flaps.txt") + 'models/large_single_aisle_1/large_single_aisle_1_aero_flaps.csv' + ) ground_data = get_aviary_resource_path( - "subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_ground.txt") + 'models/large_single_aisle_1/large_single_aisle_1_aero_ground.csv' + ) - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), - "Older version of OpenMDAO does not properly skip Metamodel.") def test_groundroll(self): # takeoff with flaps applied, gear down, zero alt prob = om.Problem() @@ -96,34 +91,35 @@ def test_groundroll(self): free_aero_data=self.free_data, flaps_aero_data=self.flaps_data, ground_aero_data=self.ground_data, - extrapolate=True) + extrapolate=True, + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3) prob.setup() - prob.set_val("t_curr", [0.0, 1.0, 2.0, 3.0]) + prob.set_val('t_curr', [0.0, 1.0, 2.0, 3.0]) prob.set_val(Dynamic.Mission.ALTITUDE, 0) - prob.set_val(Dynamic.Mission.MACH, [0.0, 0.009, 0.018, 0.026]) - prob.set_val("alpha", 0) + prob.set_val(Dynamic.Atmosphere.MACH, [0.0, 0.009, 0.018, 0.026]) + prob.set_val(Mission.Design.GROSS_MASS, 175400.0) + prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, 0) # TODO set q if we want to test lift/drag forces - prob.set_val("flap_defl", self.flap_defl_to) - prob.set_val("t_init_gear", self.t_init_gear_to) - prob.set_val("t_init_flaps", self.t_init_flaps_to) + prob.set_val('flap_defl', self.flap_defl_to) + prob.set_val('t_init_gear', self.t_init_gear_to) + prob.set_val('t_init_flaps', self.t_init_flaps_to) prob.run_model() cl_exp = 0.5597 * np.ones(4) cd_exp = 0.0572 * np.ones(4) # TODO yikes @ tolerances - assert_near_equal(prob["CL"], cl_exp, tolerance=0.1) - assert_near_equal(prob["CD"], cd_exp, tolerance=0.3) + assert_near_equal(prob['CL'], cl_exp, tolerance=0.1) + assert_near_equal(prob['CD'], cd_exp, tolerance=0.3) partial_data = prob.check_partials( - method="fd", out_stream=None + method='fd', out_stream=None ) # fd because there is a cs in the time ramp assert_check_partials(partial_data, atol=3e-7, rtol=6e-5) - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), - "Older version of OpenMDAO does not properly skip Metamodel.") def test_takeoff(self): # takeoff crossing flap retraction and gear retraction points prob = om.Problem() @@ -132,43 +128,44 @@ def test_takeoff(self): free_aero_data=self.free_data, flaps_aero_data=self.flaps_data, ground_aero_data=self.ground_data, - extrapolate=True) + extrapolate=True, + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3) prob.setup() prob.set_val( - "t_curr", + 't_curr', [37.0, 38.0, 39.0, 40.0, 47.0, 48.0, 49.0, 50.0], ) alts = [44.2, 62.7, 84.6, 109.7, 373.0, 419.4, 465.3, 507.8] prob.set_val(Dynamic.Mission.ALTITUDE, alts) prob.set_val( - Dynamic.Mission.MACH, [ - 0.257, 0.260, 0.263, 0.265, 0.276, 0.277, 0.279, 0.280]) - prob.set_val("alpha", [8.94, 8.74, 8.44, 8.24, 6.45, 6.34, 6.76, 7.59]) + Dynamic.Atmosphere.MACH, + [0.257, 0.260, 0.263, 0.265, 0.276, 0.277, 0.279, 0.280], + ) + prob.set_val( + Dynamic.Vehicle.ANGLE_OF_ATTACK, [8.94, 8.74, 8.44, 8.24, 6.45, 6.34, 6.76, 7.59] + ) # TODO set q if we want to test lift/drag forces - prob.set_val(Aircraft.Wing.AREA, 1370) prob.set_val(Aircraft.Wing.SPAN, 117.8) - prob.set_val("flap_defl", self.flap_defl_to) - prob.set_val("t_init_gear", self.t_init_gear_to) - prob.set_val("t_init_flaps", self.t_init_flaps_to) + prob.set_val('flap_defl', self.flap_defl_to) + prob.set_val('t_init_gear', self.t_init_gear_to) + prob.set_val('t_init_flaps', self.t_init_flaps_to) + prob.set_val(Mission.Design.GROSS_MASS, 175400.0) prob.run_model() - cl_exp = np.array( - [1.3734, 1.3489, 1.3179, 1.2979, 1.1356, 1.0645, 0.9573, 0.8876] - ) - cd_exp = np.array( - [0.1087, 0.1070, 0.1019, 0.0969, 0.0661, 0.0641, 0.0644, 0.0680] - ) + cl_exp = np.array([1.3734, 1.3489, 1.3179, 1.2979, 1.1356, 1.0645, 0.9573, 0.8876]) + cd_exp = np.array([0.1087, 0.1070, 0.1019, 0.0969, 0.0661, 0.0641, 0.0644, 0.0680]) # TODO yikes @ tolerances - assert_near_equal(prob["CL"], cl_exp, tolerance=0.02) - assert_near_equal(prob["CD"], cd_exp, tolerance=0.09) + assert_near_equal(prob['CL'], cl_exp, tolerance=0.02) + assert_near_equal(prob['CD'], cd_exp, tolerance=0.09) partial_data = prob.check_partials( - method="fd", out_stream=None + method='fd', out_stream=None ) # fd because there is a cs in the time ramp assert_check_partials( partial_data, atol=0.255, rtol=5e-7 @@ -178,14 +175,12 @@ def test_takeoff(self): class GearDragIncrementTest(unittest.TestCase): - """ - Test Gear drag coefficient increment - """ + """Test Gear drag coefficient increment.""" def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "drag_inc", + 'drag_inc', GearDragIncrement(num_nodes=2), promotes_inputs=['*'], promotes_outputs=['*'], @@ -196,37 +191,92 @@ def test_case(self): prob.set_val('flap_defl', [0.0, 0.3], 'deg') prob.run_model() - assert_near_equal(prob["dCD"], [0.04308, 0.04296], 1e-4) - partial_data = prob.check_partials(out_stream=None, method="cs") + assert_near_equal(prob['dCD'], [0.04308, 0.04296], 1e-4) + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class GearDragIncrementTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.aerodynamics.gasp_based.table_based as table + table.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.aerodynamics.gasp_based.table_based as table + table.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "drag_inc", + 'drag_inc', GearDragIncrement(num_nodes=2), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3) prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Mission.Design.GROSS_MASS, 175400.0) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +class BWBCruiseAeroTest(unittest.TestCase): + """ + Test of table based BWB cruise using a table generated by a CFD tool. + The table is modified for demonstration purposes only. It does not represent any actual result. + """ + + def test_climb(self): + prob = om.Problem() + + fp = 'models/aircraft/blended_wing_body/generic_BWB_GASP_aero.csv' + prob.model = TabularCruiseAero(num_nodes=3, aero_data=fp) + + prob.setup(force_alloc_complex=True) + + prob.set_val(Dynamic.Atmosphere.MACH, [0.7, 0.8, 0.82]) + prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [5.0, 10.0, 2.0]) + prob.set_val( + Dynamic.Mission.ALTITUDE, + [10000.0, 30000.0, 35000], + ) + prob.run_model() + + cl_exp = np.array([0.1509, 0.410764, -0.0384316]) + cd_exp = np.array([0.00610224, 0.0205816, 0.00460256]) + + assert_near_equal(prob['CL'], cl_exp, tolerance=0.001) + assert_near_equal(prob['CD'], cd_exp, tolerance=0.001) + + partial_data = prob.check_partials(method='cs', out_stream=None) + assert_check_partials(partial_data, atol=4e-7, rtol=2e-7) + + def test_cruise(self): + prob = om.Problem() + ref = 'models/aircraft/blended_wing_body/generic_BWB_GASP_aero.csv' + fp = get_aviary_resource_path(ref) + prob.model = TabularCruiseAero(num_nodes=2, aero_data=fp) + prob.setup(force_alloc_complex=True) + + prob.set_val(Dynamic.Atmosphere.MACH, [0.8, 0.82]) + prob.set_val(Dynamic.Vehicle.ANGLE_OF_ATTACK, [4.216, 3.146]) + prob.set_val(Dynamic.Mission.ALTITUDE, [37500, 41000]) + prob.run_model() + + cl_exp = np.array([0.1276112, 0.05515637]) + cd_exp = np.array([0.00599297, 0.00570541]) + + assert_near_equal(prob['CL'], cl_exp, tolerance=0.001) + assert_near_equal(prob['CD'], cd_exp, tolerance=0.001) + + partial_data = prob.check_partials(method='cs', out_stream=None) + assert_check_partials(partial_data, atol=9e-8, rtol=2e-7) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/aerodynamics/solve_alpha_group.py b/aviary/subsystems/aerodynamics/solve_alpha_group.py new file mode 100644 index 0000000000..ed1c7cf096 --- /dev/null +++ b/aviary/subsystems/aerodynamics/solve_alpha_group.py @@ -0,0 +1,51 @@ +import numpy as np +import openmdao.api as om + +from aviary import constants +from aviary.variable_info.variables import Dynamic + + +class SolveAlphaGroup(om.Group): + """ + Group that contains components needed to determine angle of attack. Must be paired with + aerodynamics method and a solver to properly balance lift and weight. + """ + + def initialize(self): + self.options.declare('num_nodes', types=int) + + def setup(self): + num_nodes = self.options['num_nodes'] + self.add_subsystem( + 'required_lift', + om.ExecComp( + 'required_lift = mass * grav_metric', + grav_metric={'val': constants.GRAV_METRIC_GASP}, + mass={'units': 'kg', 'shape': num_nodes}, + required_lift={'units': 'N', 'shape': num_nodes}, + has_diag_partials=True, + ), + promotes_inputs=[ + ('mass', Dynamic.Vehicle.MASS), + ], + ) + + balance = self.add_subsystem( + 'balance', + om.BalanceComp(), + promotes=[Dynamic.Vehicle.ANGLE_OF_ATTACK, Dynamic.Vehicle.LIFT], + ) + balance.add_balance( + Dynamic.Vehicle.ANGLE_OF_ATTACK, + val=np.ones(num_nodes), + units='deg', + res_ref=1.0e6, + lhs_name=Dynamic.Vehicle.LIFT, + rhs_name='required_lift', + eq_units='lbf', + ) + + self.connect( + 'required_lift.required_lift', + 'balance.required_lift', + ) diff --git a/aviary/subsystems/aerodynamics/test/__init__.py b/aviary/subsystems/aerodynamics/test/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aviary/subsystems/aerodynamics/test/test_external_mission_aero.py b/aviary/subsystems/aerodynamics/test/test_external_mission_aero.py new file mode 100644 index 0000000000..1aa13fe2d2 --- /dev/null +++ b/aviary/subsystems/aerodynamics/test/test_external_mission_aero.py @@ -0,0 +1,62 @@ +import unittest +from copy import deepcopy + +from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs + +import aviary.api as av +from aviary.examples.external_subsystems.custom_aero.custom_aero_builder import CustomAeroBuilder + +phase_info = deepcopy(av.default_height_energy_phase_info) + + +@use_tempdirs +class TestExternalAero(av.TestSubsystemBuilderBase): + """ + Test replacing internal drag calculation with an external subsystem. + + Mainly, this shows that the "external" method works, and that the external + subsystems in mission are correctly promoting inputs/outputs. + """ + + @require_pyoptsparse(optimizer='IPOPT') + def test_external_drag(self): + # Just do cruise in this example. + phase_info.pop('climb') + phase_info.pop('descent') + + # Add custom aero. + # TODO: This API for replacing aero will be changed an upcoming release. + phase_info['cruise']['external_subsystems'] = [CustomAeroBuilder()] + + # Disable internal aero + # TODO: This API for replacing aero will be changed an upcoming release. + phase_info['cruise']['subsystem_options']['core_aerodynamics'] = { + 'method': 'external', + } + + prob = av.AviaryProblem() + + # Load aircraft and options data from user + prob.load_inputs('models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) + + prob.check_and_preprocess_inputs() + + prob.build_model() + + # SLSQP didn't work so well here. + prob.add_driver('IPOPT') + + prob.add_design_variables() + prob.add_objective() + + prob.setup() + + prob.run_aviary_problem(suppress_solver_print=True) + + drag = prob.get_val('traj.cruise.rhs_all.drag', units='lbf') + assert_near_equal(drag[0], 5540.7442556, tolerance=1e-3) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/aerodynamics/test/test_flops_aero_builder.py b/aviary/subsystems/aerodynamics/test/test_flops_aero_builder.py new file mode 100644 index 0000000000..dbef18b87f --- /dev/null +++ b/aviary/subsystems/aerodynamics/test/test_flops_aero_builder.py @@ -0,0 +1,26 @@ +import unittest + +import aviary.api as av +from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Aircraft + +FLOPS = LegacyCode.FLOPS + + +class TestAeroBuilder(av.TestSubsystemBuilderBase): + """ + That class inherits from TestSubsystemBuilder. So all the test functions are + within that inherited class. The setUp() method prepares the class and is run + before the test methods; then the test methods are run. + """ + + def setUp(self): + self.subsystem_builder = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) + self.aviary_values = av.AviaryValues() + self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/aerodynamics/test/test_gasp_aero_builder.py b/aviary/subsystems/aerodynamics/test/test_gasp_aero_builder.py new file mode 100644 index 0000000000..c2c37ad70a --- /dev/null +++ b/aviary/subsystems/aerodynamics/test/test_gasp_aero_builder.py @@ -0,0 +1,39 @@ +import unittest + +import aviary.api as av +from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder +from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Aircraft + +GASP = LegacyCode.GASP + + +class TestAeroBuilder(av.TestSubsystemBuilderBase): + """ + That class inherits from TestSubsystemBuilder. So all the test functions are + within that inherited class. The setUp() method prepares the class and is run + before the test methods; then the test methods are run. + """ + + def setUp(self): + self.subsystem_builder = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, GASP) + self.aviary_values = av.AviaryValues() + self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') + self.aviary_values.set_val(Aircraft.Design.TYPE, 'transport', units='unitless') + + def test_build_mission(self): + kwargs = {'method': 'cruise'} + return super().test_build_mission(**kwargs) + + def test_get_parameters(self): + kwargs = {'method': 'cruise'} + return super().test_get_parameters(**kwargs) + + def test_check_parameters(self): + kwargs = {'method': 'cruise'} + return super().test_check_parameters(**kwargs) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/aerodynamics/test/test_gasp_drag.py b/aviary/subsystems/aerodynamics/test/test_gasp_drag.py new file mode 100644 index 0000000000..733f84eef9 --- /dev/null +++ b/aviary/subsystems/aerodynamics/test/test_gasp_drag.py @@ -0,0 +1,48 @@ +"""Tests the aero builder with the 2dof (gasp-based) drag.""" + +import unittest +from copy import deepcopy + +from openmdao.utils.assert_utils import assert_near_equal + +from aviary.models.missions.two_dof_default import phase_info +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.variable_info.variables import Aircraft + + +class TestAeroBuilderGasp(unittest.TestCase): + def test_parameters(self): + # This test is to make sure that the aero builder creates a parameter + # for wing height. It addresses a bug where this was absent. + + local_phase_info = deepcopy(phase_info) + + prob = AviaryProblem() + + prob.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', + local_phase_info, + ) + + # Change value just to be certain. + prob.aviary_inputs.set_val(Aircraft.Wing.HEIGHT, 7.7777, units='ft') + + prob.check_and_preprocess_inputs() + + prob.build_model() + + prob.setup() + + prob.run_model() + + # verify that we are promoting the parameters. + wing_height = prob.get_val( + 'traj.rotation.rhs_all.aircraft:wing:height', + units='ft', + ) + actual_wing_height = prob.aviary_inputs.get_val(Aircraft.Wing.HEIGHT, units='ft') + assert_near_equal(wing_height, actual_wing_height) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/atmosphere/atmosphere.py b/aviary/subsystems/atmosphere/atmosphere.py index 2e47e59745..94d42ba382 100644 --- a/aviary/subsystems/atmosphere/atmosphere.py +++ b/aviary/subsystems/atmosphere/atmosphere.py @@ -1,5 +1,4 @@ import openmdao.api as om - from dymos.models.atmosphere.atmos_1976 import USatm1976Comp from aviary.subsystems.atmosphere.flight_conditions import FlightConditions @@ -10,7 +9,7 @@ class Atmosphere(om.Group): """ Group that contains atmospheric conditions for the aircraft's current flight - condition, as well as conversions for different speed types (TAS, EAS, Mach) + condition, as well as conversions for different speed types (TAS, EAS, Mach). """ def initialize(self): @@ -21,7 +20,7 @@ def initialize(self): self.options.declare( 'h_def', values=('geopotential', 'geodetic'), - default='geopotential', + default='geodetic', desc='The definition of altitude provided as input to the component. If ' '"geodetic", it will be converted to geopotential based on Equation 19 in ' 'the original standard.', @@ -31,16 +30,14 @@ def initialize(self): 'output_dsos_dh', types=bool, default=False, - desc='If true, the derivative of the speed of sound will be added as an ' - 'output', + desc='If true, the derivative of the speed of sound will be added as an output', ) self.options.declare( - "input_speed_type", + 'input_speed_type', default=SpeedType.TAS, types=SpeedType, - desc='defines input airspeed as equivalent airspeed, true airspeed, or mach ' - 'number', + desc='defines input airspeed as equivalent airspeed, true airspeed, or mach number', ) def setup(self): @@ -51,16 +48,14 @@ def setup(self): self.add_subsystem( name='standard_atmosphere', - subsys=USatm1976Comp( - num_nodes=nn, h_def=h_def, output_dsos_dh=output_dsos_dh - ), + subsys=USatm1976Comp(num_nodes=nn, h_def=h_def, output_dsos_dh=output_dsos_dh), promotes_inputs=[('h', Dynamic.Mission.ALTITUDE)], promotes_outputs=[ '*', - ('sos', Dynamic.Mission.SPEED_OF_SOUND), - ('rho', Dynamic.Mission.DENSITY), - ('temp', Dynamic.Mission.TEMPERATURE), - ('pres', Dynamic.Mission.STATIC_PRESSURE), + ('sos', Dynamic.Atmosphere.SPEED_OF_SOUND), + ('rho', Dynamic.Atmosphere.DENSITY), + ('temp', Dynamic.Atmosphere.TEMPERATURE), + ('pres', Dynamic.Atmosphere.STATIC_PRESSURE), ], ) diff --git a/aviary/subsystems/atmosphere/flight_conditions.py b/aviary/subsystems/atmosphere/flight_conditions.py index 66b12a2172..8c8fbde010 100644 --- a/aviary/subsystems/atmosphere/flight_conditions.py +++ b/aviary/subsystems/atmosphere/flight_conditions.py @@ -13,254 +13,245 @@ class FlightConditions(om.ExplicitComponent): """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) self.options.declare( - "input_speed_type", + 'input_speed_type', default=SpeedType.TAS, types=SpeedType, - desc="defines input airspeed as equivalent airspeed, true airspeed, or mach number", + desc='defines input airspeed as equivalent airspeed, true airspeed, or Mach number', ) def setup(self): - nn = self.options["num_nodes"] - in_type = self.options["input_speed_type"] - arange = np.arange(self.options["num_nodes"]) + nn = self.options['num_nodes'] + in_type = self.options['input_speed_type'] + arange = np.arange(self.options['num_nodes']) self.add_input( - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.DENSITY, val=np.zeros(nn), - units="slug/ft**3", - desc="density of air", + units='slug/ft**3', + desc='density of air', ) self.add_input( - Dynamic.Mission.SPEED_OF_SOUND, + Dynamic.Atmosphere.SPEED_OF_SOUND, val=np.zeros(nn), - units="ft/s", - desc="speed of sound", + units='ft/s', + desc='speed of sound', ) self.add_output( - Dynamic.Mission.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, val=np.zeros(nn), - units="lbf/ft**2", - desc="dynamic pressure", + units='lbf/ft**2', + desc='dynamic pressure', ) if in_type is SpeedType.TAS: self.add_input( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="ft/s", - desc="true air speed", + units='ft/s', + desc='true air speed', ) self.add_output( - "EAS", + 'EAS', val=np.zeros(nn), - units="ft/s", - desc="equivalent air speed", + units='ft/s', + desc='equivalent air speed', ) self.add_output( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, val=np.zeros(nn), - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) self.declare_partials( - Dynamic.Mission.DYNAMIC_PRESSURE, - [Dynamic.Mission.DENSITY, Dynamic.Mission.VELOCITY], + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + [Dynamic.Atmosphere.DENSITY, Dynamic.Mission.VELOCITY], rows=arange, cols=arange, ) self.declare_partials( - Dynamic.Mission.MACH, - [Dynamic.Mission.SPEED_OF_SOUND, Dynamic.Mission.VELOCITY], + Dynamic.Atmosphere.MACH, + [Dynamic.Atmosphere.SPEED_OF_SOUND, Dynamic.Mission.VELOCITY], rows=arange, cols=arange, ) self.declare_partials( - "EAS", - [Dynamic.Mission.VELOCITY, Dynamic.Mission.DENSITY], + 'EAS', + [Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.DENSITY], rows=arange, cols=arange, ) elif in_type is SpeedType.EAS: self.add_input( - "EAS", + 'EAS', val=np.zeros(nn), - units="ft/s", - desc="equivalent air speed at", + units='ft/s', + desc='equivalent air speed at', ) self.add_output( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="ft/s", - desc="true air speed", + units='ft/s', + desc='true air speed', ) self.add_output( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, val=np.zeros(nn), - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) self.declare_partials( - Dynamic.Mission.DYNAMIC_PRESSURE, - [Dynamic.Mission.DENSITY, "EAS"], + Dynamic.Atmosphere.DYNAMIC_PRESSURE, + [Dynamic.Atmosphere.DENSITY, 'EAS'], rows=arange, cols=arange, ) self.declare_partials( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, [ - Dynamic.Mission.SPEED_OF_SOUND, - "EAS", - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + 'EAS', + Dynamic.Atmosphere.DENSITY, ], rows=arange, cols=arange, ) self.declare_partials( Dynamic.Mission.VELOCITY, - [Dynamic.Mission.DENSITY, "EAS"], + [Dynamic.Atmosphere.DENSITY, 'EAS'], rows=arange, cols=arange, ) elif in_type is SpeedType.MACH: self.add_input( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, val=np.zeros(nn), - units="unitless", - desc="mach number", + units='unitless', + desc='Mach number', ) self.add_output( - "EAS", + 'EAS', val=np.zeros(nn), - units="ft/s", - desc="equivalent air speed", + units='ft/s', + desc='equivalent air speed', ) self.add_output( Dynamic.Mission.VELOCITY, val=np.zeros(nn), - units="ft/s", - desc="true air speed", + units='ft/s', + desc='true air speed', ) self.declare_partials( - Dynamic.Mission.DYNAMIC_PRESSURE, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, [ - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.MACH, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.DENSITY, ], rows=arange, cols=arange, ) self.declare_partials( Dynamic.Mission.VELOCITY, - [Dynamic.Mission.SPEED_OF_SOUND, Dynamic.Mission.MACH], + [Dynamic.Atmosphere.SPEED_OF_SOUND, Dynamic.Atmosphere.MACH], rows=arange, cols=arange, ) self.declare_partials( - "EAS", + 'EAS', [ - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.MACH, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.DENSITY, ], rows=arange, cols=arange, ) def compute(self, inputs, outputs): + in_type = self.options['input_speed_type'] - in_type = self.options["input_speed_type"] - - rho = inputs[Dynamic.Mission.DENSITY] - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] + rho = inputs[Dynamic.Atmosphere.DENSITY] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] if in_type is SpeedType.TAS: TAS = inputs[Dynamic.Mission.VELOCITY] - outputs[Dynamic.Mission.MACH] = mach = TAS / sos - outputs["EAS"] = TAS * (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 - outputs[Dynamic.Mission.DYNAMIC_PRESSURE] = 0.5 * rho * TAS**2 + outputs[Dynamic.Atmosphere.MACH] = mach = TAS / sos + outputs['EAS'] = TAS * (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 + outputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] = 0.5 * rho * TAS**2 elif in_type is SpeedType.EAS: - EAS = inputs["EAS"] + EAS = inputs['EAS'] outputs[Dynamic.Mission.VELOCITY] = TAS = ( EAS / (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 ) - outputs[Dynamic.Mission.MACH] = mach = TAS / sos - outputs[Dynamic.Mission.DYNAMIC_PRESSURE] = ( + outputs[Dynamic.Atmosphere.MACH] = mach = TAS / sos + outputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] = ( 0.5 * EAS**2 * constants.RHO_SEA_LEVEL_ENGLISH ) elif in_type is SpeedType.MACH: - mach = inputs[Dynamic.Mission.MACH] + mach = inputs[Dynamic.Atmosphere.MACH] outputs[Dynamic.Mission.VELOCITY] = TAS = sos * mach - outputs["EAS"] = TAS * (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 - outputs[Dynamic.Mission.DYNAMIC_PRESSURE] = 0.5 * rho * sos**2 * mach**2 + outputs['EAS'] = TAS * (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 + outputs[Dynamic.Atmosphere.DYNAMIC_PRESSURE] = 0.5 * rho * sos**2 * mach**2 def compute_partials(self, inputs, J): - in_type = self.options["input_speed_type"] + in_type = self.options['input_speed_type'] - rho = inputs[Dynamic.Mission.DENSITY] - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] + rho = inputs[Dynamic.Atmosphere.DENSITY] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] if in_type is SpeedType.TAS: TAS = inputs[Dynamic.Mission.VELOCITY] - J[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.VELOCITY] = rho * TAS - J[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.DENSITY] = 0.5 * TAS**2 + J[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Mission.VELOCITY] = rho * TAS + J[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.DENSITY] = 0.5 * TAS**2 - J[Dynamic.Mission.MACH, Dynamic.Mission.VELOCITY] = 1 / sos - J[Dynamic.Mission.MACH, Dynamic.Mission.SPEED_OF_SOUND] = -TAS / sos**2 + J[Dynamic.Atmosphere.MACH, Dynamic.Mission.VELOCITY] = 1 / sos + J[Dynamic.Atmosphere.MACH, Dynamic.Atmosphere.SPEED_OF_SOUND] = -TAS / sos**2 - J["EAS", Dynamic.Mission.VELOCITY] = ( - rho / constants.RHO_SEA_LEVEL_ENGLISH - ) ** 0.5 - J["EAS", Dynamic.Mission.DENSITY] = ( + J['EAS', Dynamic.Mission.VELOCITY] = (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 + J['EAS', Dynamic.Atmosphere.DENSITY] = ( TAS * 0.5 * (rho ** (-0.5) / constants.RHO_SEA_LEVEL_ENGLISH**0.5) ) elif in_type is SpeedType.EAS: - EAS = inputs["EAS"] + EAS = inputs['EAS'] TAS = EAS / (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 dTAS_dRho = -0.5 * EAS * constants.RHO_SEA_LEVEL_ENGLISH**0.5 / rho**1.5 dTAS_dEAS = 1 / (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 - J[Dynamic.Mission.DYNAMIC_PRESSURE, "EAS"] = ( - EAS * constants.RHO_SEA_LEVEL_ENGLISH - ) - J[Dynamic.Mission.MACH, "EAS"] = dTAS_dEAS / sos - J[Dynamic.Mission.MACH, Dynamic.Mission.DENSITY] = dTAS_dRho / sos - J[Dynamic.Mission.MACH, Dynamic.Mission.SPEED_OF_SOUND] = -TAS / sos**2 - J[Dynamic.Mission.VELOCITY, Dynamic.Mission.DENSITY] = dTAS_dRho - J[Dynamic.Mission.VELOCITY, "EAS"] = dTAS_dEAS + J[Dynamic.Atmosphere.DYNAMIC_PRESSURE, 'EAS'] = EAS * constants.RHO_SEA_LEVEL_ENGLISH + J[Dynamic.Atmosphere.MACH, 'EAS'] = dTAS_dEAS / sos + J[Dynamic.Atmosphere.MACH, Dynamic.Atmosphere.DENSITY] = dTAS_dRho / sos + J[Dynamic.Atmosphere.MACH, Dynamic.Atmosphere.SPEED_OF_SOUND] = -TAS / sos**2 + J[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.DENSITY] = dTAS_dRho + J[Dynamic.Mission.VELOCITY, 'EAS'] = dTAS_dEAS elif in_type is SpeedType.MACH: - mach = inputs[Dynamic.Mission.MACH] + mach = inputs[Dynamic.Atmosphere.MACH] TAS = sos * mach - J[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.SPEED_OF_SOUND] = ( + J[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.SPEED_OF_SOUND] = ( rho * sos * mach**2 ) - J[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.MACH] = ( - rho * sos**2 * mach - ) - J[Dynamic.Mission.DYNAMIC_PRESSURE, Dynamic.Mission.DENSITY] = ( + J[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.MACH] = rho * sos**2 * mach + J[Dynamic.Atmosphere.DYNAMIC_PRESSURE, Dynamic.Atmosphere.DENSITY] = ( 0.5 * sos**2 * mach**2 ) - J[Dynamic.Mission.VELOCITY, Dynamic.Mission.SPEED_OF_SOUND] = mach - J[Dynamic.Mission.VELOCITY, Dynamic.Mission.MACH] = sos - J["EAS", Dynamic.Mission.SPEED_OF_SOUND] = ( + J[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.SPEED_OF_SOUND] = mach + J[Dynamic.Mission.VELOCITY, Dynamic.Atmosphere.MACH] = sos + J['EAS', Dynamic.Atmosphere.SPEED_OF_SOUND] = ( mach * (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 ) - J["EAS", Dynamic.Mission.MACH] = ( - sos * (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 - ) - J["EAS", Dynamic.Mission.DENSITY] = ( + J['EAS', Dynamic.Atmosphere.MACH] = sos * (rho / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 + J['EAS', Dynamic.Atmosphere.DENSITY] = ( TAS * (1 / constants.RHO_SEA_LEVEL_ENGLISH) ** 0.5 * 0.5 * rho ** (-0.5) ) diff --git a/aviary/subsystems/atmosphere/test/test_flight_conditions.py b/aviary/subsystems/atmosphere/test/test_flight_conditions.py index 4cfc41c097..9b645587f7 100644 --- a/aviary/subsystems/atmosphere/test/test_flight_conditions.py +++ b/aviary/subsystems/atmosphere/test/test_flight_conditions.py @@ -1,5 +1,4 @@ import unittest -import os import numpy as np import openmdao.api as om @@ -12,22 +11,21 @@ class FlightConditionsTestCase1(unittest.TestCase): def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "group", + 'group', FlightConditions(num_nodes=2, input_speed_type=SpeedType.TAS), - promotes=["*"], + promotes=['*'], ) self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, val=1.22 * np.ones(2), units="kg/m**3" + Dynamic.Atmosphere.DENSITY, val=1.22 * np.ones(2), units='kg/m**3' ) self.prob.model.set_input_defaults( - Dynamic.Mission.SPEED_OF_SOUND, val=344 * np.ones(2), units="m/s" + Dynamic.Atmosphere.SPEED_OF_SOUND, val=344 * np.ones(2), units='m/s' ) self.prob.model.set_input_defaults( - Dynamic.Mission.VELOCITY, val=344 * np.ones(2), units="m/s" + Dynamic.Mission.VELOCITY, val=344 * np.ones(2), units='m/s' ) self.prob.setup(check=False, force_alloc_complex=True) @@ -36,38 +34,31 @@ def test_case1(self): tol = 1e-5 self.prob.run_model() - assert_near_equal( - self.prob[Dynamic.Mission.DYNAMIC_PRESSURE], 1507.6 * np.ones(2), tol - ) - assert_near_equal(self.prob[Dynamic.Mission.MACH], np.ones(2), tol) - assert_near_equal( - self.prob.get_val("EAS", units="m/s"), 343.3 * np.ones(2), tol - ) + assert_near_equal(self.prob[Dynamic.Atmosphere.DYNAMIC_PRESSURE], 1507.6 * np.ones(2), tol) + assert_near_equal(self.prob[Dynamic.Atmosphere.MACH], np.ones(2), tol) + assert_near_equal(self.prob.get_val('EAS', units='m/s'), 343.3 * np.ones(2), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class FlightConditionsTestCase2(unittest.TestCase): def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "group", + 'group', FlightConditions(num_nodes=2, input_speed_type=SpeedType.EAS), - promotes=["*"], + promotes=['*'], ) self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, val=1.05 * np.ones(2), units="kg/m**3" - ) - self.prob.model.set_input_defaults( - Dynamic.Mission.SPEED_OF_SOUND, val=344 * np.ones(2), units="m/s" + Dynamic.Atmosphere.DENSITY, val=1.05 * np.ones(2), units='kg/m**3' ) self.prob.model.set_input_defaults( - "EAS", val=318.4821143 * np.ones(2), units="m/s" + Dynamic.Atmosphere.SPEED_OF_SOUND, val=344 * np.ones(2), units='m/s' ) + self.prob.model.set_input_defaults('EAS', val=318.4821143 * np.ones(2), units='m/s') self.prob.setup(check=False, force_alloc_complex=True) @@ -75,36 +66,31 @@ def test_case1(self): tol = 1e-5 self.prob.run_model() - assert_near_equal( - self.prob[Dynamic.Mission.DYNAMIC_PRESSURE], 1297.54 * np.ones(2), tol - ) - assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY], 1128.61 * np.ones(2), tol - ) - assert_near_equal(self.prob[Dynamic.Mission.MACH], np.ones(2), tol) + assert_near_equal(self.prob[Dynamic.Atmosphere.DYNAMIC_PRESSURE], 1297.54 * np.ones(2), tol) + assert_near_equal(self.prob[Dynamic.Mission.VELOCITY], 1128.61 * np.ones(2), tol) + assert_near_equal(self.prob[Dynamic.Atmosphere.MACH], np.ones(2), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class FlightConditionsTestCase3(unittest.TestCase): def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "group", + 'group', FlightConditions(num_nodes=2, input_speed_type=SpeedType.MACH), - promotes=["*"], + promotes=['*'], ) self.prob.model.set_input_defaults( - Dynamic.Mission.DENSITY, val=1.05 * np.ones(2), units="kg/m**3" + Dynamic.Atmosphere.DENSITY, val=1.05 * np.ones(2), units='kg/m**3' ) self.prob.model.set_input_defaults( - Dynamic.Mission.SPEED_OF_SOUND, val=344 * np.ones(2), units="m/s" + Dynamic.Atmosphere.SPEED_OF_SOUND, val=344 * np.ones(2), units='m/s' ) self.prob.model.set_input_defaults( - Dynamic.Mission.MACH, val=np.ones(2), units="unitless" + Dynamic.Atmosphere.MACH, val=np.ones(2), units='unitless' ) self.prob.setup(check=False, force_alloc_complex=True) @@ -113,19 +99,13 @@ def test_case1(self): tol = 1e-5 self.prob.run_model() - assert_near_equal( - self.prob[Dynamic.Mission.DYNAMIC_PRESSURE], 1297.54 * np.ones(2), tol - ) - assert_near_equal( - self.prob[Dynamic.Mission.VELOCITY], 1128.61 * np.ones(2), tol - ) - assert_near_equal( - self.prob.get_val("EAS", units="m/s"), 318.4821143 * np.ones(2), tol - ) + assert_near_equal(self.prob[Dynamic.Atmosphere.DYNAMIC_PRESSURE], 1297.54 * np.ones(2), tol) + assert_near_equal(self.prob[Dynamic.Mission.VELOCITY], 1128.61 * np.ones(2), tol) + assert_near_equal(self.prob.get_val('EAS', units='m/s'), 318.4821143 * np.ones(2), tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/energy/battery_builder.py b/aviary/subsystems/energy/battery_builder.py index ffc25bd206..41414cffb6 100644 --- a/aviary/subsystems/energy/battery_builder.py +++ b/aviary/subsystems/energy/battery_builder.py @@ -19,9 +19,9 @@ class BatteryBuilder(SubsystemBuilderBase): get_mass_names(self) -> list: Returns the name of variable Aircraft.Battery.MASS as a list get_states(self) -> dict: - Returns a dictionary of the subsystem's states, where the keys are the names - of the state variables, and the values are dictionaries that contain the units - for the state variable and any additional keyword arguments required by OpenMDAO + Returns a dictionary of the subsystem's states, where the keys are the names + of the state variables, and the values are dictionaries that contain the units + for the state variable and any additional keyword arguments required by OpenMDAO for the state variable. get_constraints(self) -> dict: Returns a dictionary of constraints for the battery subsystem. @@ -39,43 +39,72 @@ def get_mass_names(self): def build_mission(self, num_nodes, aviary_inputs=None) -> om.Group: battery_group = om.Group() # Here, the efficiency variable is used as an overall efficiency for the battery - soc = om.ExecComp('state_of_charge = (energy_capacity - (cumulative_electric_energy_used/efficiency)) / energy_capacity', - state_of_charge={'val': np.zeros( - num_nodes), 'units': 'unitless'}, - energy_capacity={'val': 10.0, 'units': 'kJ'}, - cumulative_electric_energy_used={ - 'val': np.zeros(num_nodes), 'units': 'kJ'}, - efficiency={'val': 0.95, 'units': 'unitless'}, - has_diag_partials=True) - - battery_group.add_subsystem('state_of_charge', - subsys=soc, - promotes_inputs=[('energy_capacity', Aircraft.Battery.ENERGY_CAPACITY), - ('cumulative_electric_energy_used', - Dynamic.Mission.CUMULATIVE_ELECTRIC_ENERGY_USED), - ('efficiency', Aircraft.Battery.EFFICIENCY)], - promotes_outputs=[('state_of_charge', Dynamic.Mission.BATTERY_STATE_OF_CHARGE)]) + soc = om.ExecComp( + 'state_of_charge = (energy_capacity - (cumulative_electric_energy_used/efficiency)) / energy_capacity', + state_of_charge={'val': np.zeros(num_nodes), 'units': 'unitless'}, + energy_capacity={'val': 10.0, 'units': 'kJ'}, + cumulative_electric_energy_used={'val': np.zeros(num_nodes), 'units': 'kJ'}, + efficiency={'val': 0.95, 'units': 'unitless'}, + has_diag_partials=True, + ) + + battery_group.add_subsystem( + 'state_of_charge', + subsys=soc, + promotes_inputs=[ + ('energy_capacity', Aircraft.Battery.ENERGY_CAPACITY), + ( + 'cumulative_electric_energy_used', + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, + ), + ('efficiency', Aircraft.Battery.EFFICIENCY), + ], + promotes_outputs=[('state_of_charge', Dynamic.Vehicle.BATTERY_STATE_OF_CHARGE)], + ) return battery_group def get_states(self): - state_dict = {Dynamic.Mission.CUMULATIVE_ELECTRIC_ENERGY_USED: {'fix_initial': True, - 'fix_final': False, - 'lower': 0.0, - 'ref': 1e4, - 'defect_ref': 1e6, - 'units': 'kJ', - 'rate_source': Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL, - 'input_initial': 0.0}} + # need to add subsystem name to target name ('battery.') for state due + # to issue where non aircraft or mission variables are not fully promoted + # TODO fix this by not promoting only 'aircraft:*' and 'mission:*' + state_dict = { + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED: { + 'fix_initial': True, + 'fix_final': False, + 'lower': 0.0, + 'ref': 1e4, + 'defect_ref': 1e6, + 'units': 'kJ', + 'rate_source': Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + 'input_initial': 0.0, + 'targets': f'{self.name}.{Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED}', + } + } return state_dict def get_constraints(self): constraint_dict = { - # Can add constraints here; state of charge is a common one in many battery applications - f'battery.{Dynamic.Mission.BATTERY_STATE_OF_CHARGE}': - {'type': 'boundary', - 'loc': 'final', - 'lower': 0.2}, + # Can add constraints here; state of charge is a common one in many + # battery applications + f'{self.name}.{Dynamic.Vehicle.BATTERY_STATE_OF_CHARGE}': { + 'type': 'boundary', + 'loc': 'final', + 'lower': 0.2, + }, } return constraint_dict + + def get_parameters(self, aviary_inputs=None, phase_info=None): + params = { + Aircraft.Battery.ENERGY_CAPACITY: { + 'val': 0.0, + 'units': 'kJ', + }, + } + return params + + def get_linked_variables(self): + # link cumulative electric energy between phases + return [Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED] diff --git a/aviary/subsystems/energy/battery_sizing.py b/aviary/subsystems/energy/battery_sizing.py index bb7ccaad65..12fa33bf65 100644 --- a/aviary/subsystems/energy/battery_sizing.py +++ b/aviary/subsystems/energy/battery_sizing.py @@ -6,27 +6,48 @@ class SizeBattery(om.ExplicitComponent): - ''' - Calculates battery mass from specific energy and additional mass - ''' + """Calculates battery mass from specific energy and additional mass.""" def initialize(self): self.options.declare( - 'aviary_inputs', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_inputs', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): - add_aviary_input(self, Aircraft.Battery.PACK_MASS, val=0.0, units='kg', - desc='mass of energy-storing components of battery') - add_aviary_input(self, Aircraft.Battery.ADDITIONAL_MASS, val=0.0, units='kg', - desc='mass of non energy-storing components of battery') - add_aviary_input(self, Aircraft.Battery.PACK_ENERGY_DENSITY, val=0.0, units='kJ/kg', - desc='energy density of battery pack') - - add_aviary_output(self, Aircraft.Battery.MASS, val=0.0, - units='kg', desc='total battery mass') - add_aviary_output(self, Aircraft.Battery.ENERGY_CAPACITY, val=0.0, - units='kJ', desc='total battery energy storage') + add_aviary_input( + self, + Aircraft.Battery.PACK_MASS, + val=0.0, + units='kg', + desc='mass of energy-storing components of battery', + ) + add_aviary_input( + self, + Aircraft.Battery.ADDITIONAL_MASS, + val=0.0, + units='kg', + desc='mass of non energy-storing components of battery', + ) + add_aviary_input( + self, + Aircraft.Battery.PACK_ENERGY_DENSITY, + val=0.0, + units='kJ/kg', + desc='energy density of battery pack', + ) + + add_aviary_output( + self, Aircraft.Battery.MASS, val=0.0, units='kg', desc='total battery mass' + ) + add_aviary_output( + self, + Aircraft.Battery.ENERGY_CAPACITY, + val=0.0, + units='kJ', + desc='total battery energy storage', + ) def compute(self, inputs, outputs): energy_density_kj_kg = inputs[Aircraft.Battery.PACK_ENERGY_DENSITY] @@ -40,21 +61,17 @@ def compute(self, inputs, outputs): outputs[Aircraft.Battery.ENERGY_CAPACITY] = total_energy def setup_partials(self): - self.declare_partials(Aircraft.Battery.ENERGY_CAPACITY, - Aircraft.Battery.PACK_ENERGY_DENSITY) - self.declare_partials(Aircraft.Battery.ENERGY_CAPACITY, - Aircraft.Battery.PACK_MASS) + self.declare_partials( + Aircraft.Battery.ENERGY_CAPACITY, Aircraft.Battery.PACK_ENERGY_DENSITY + ) + self.declare_partials(Aircraft.Battery.ENERGY_CAPACITY, Aircraft.Battery.PACK_MASS) - self.declare_partials(Aircraft.Battery.MASS, - Aircraft.Battery.ADDITIONAL_MASS, val=1.0) - self.declare_partials(Aircraft.Battery.MASS, - Aircraft.Battery.PACK_MASS, val=1.0) + self.declare_partials(Aircraft.Battery.MASS, Aircraft.Battery.ADDITIONAL_MASS, val=1.0) + self.declare_partials(Aircraft.Battery.MASS, Aircraft.Battery.PACK_MASS, val=1.0) def compute_partials(self, inputs, J): energy_density_kj_kg = inputs[Aircraft.Battery.PACK_ENERGY_DENSITY] pack_mass = inputs[Aircraft.Battery.PACK_MASS] - J[Aircraft.Battery.ENERGY_CAPACITY, - Aircraft.Battery.PACK_ENERGY_DENSITY] = pack_mass - J[Aircraft.Battery.ENERGY_CAPACITY, - Aircraft.Battery.PACK_MASS] = energy_density_kj_kg + J[Aircraft.Battery.ENERGY_CAPACITY, Aircraft.Battery.PACK_ENERGY_DENSITY] = pack_mass + J[Aircraft.Battery.ENERGY_CAPACITY, Aircraft.Battery.PACK_MASS] = energy_density_kj_kg diff --git a/aviary/subsystems/energy/test/test_battery.py b/aviary/subsystems/energy/test/test_battery.py index 8d6ad7245d..39df1c9103 100644 --- a/aviary/subsystems/energy/test/test_battery.py +++ b/aviary/subsystems/energy/test/test_battery.py @@ -2,16 +2,15 @@ import numpy as np import openmdao.api as om - from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.energy.battery_builder import BatteryBuilder import aviary.api as av +from aviary.subsystems.energy.battery_builder import BatteryBuilder class TestBatteryDerivs(unittest.TestCase): def setUp(self): - self.prob = prob = om.Problem() + self.prob = om.Problem() self.options = av.AviaryValues() @@ -19,9 +18,9 @@ def setUp(self): def test_battery_premission(self): prob = self.prob - prob.model.add_subsystem('battery_premission', - self.battery.build_pre_mission(self.options), - promotes=['*']) + prob.model.add_subsystem( + 'battery_premission', self.battery.build_pre_mission(self.options), promotes=['*'] + ) prob.setup(force_alloc_complex=True) @@ -40,33 +39,34 @@ def test_battery_premission(self): assert_near_equal(mass, mass_expected, tolerance=1e-10) assert_near_equal(energy, energy_expected, tolerance=1e-10) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-9, rtol=1e-9) def test_battery_mission(self): prob = self.prob - prob.model.add_subsystem('battery_mission', - subsys=self.battery.build_mission(num_nodes=4), - promotes=['*']) + prob.model.add_subsystem( + 'battery_mission', subsys=self.battery.build_mission(num_nodes=4), promotes=['*'] + ) efficiency = 0.95 + prob.model.set_input_defaults(av.Aircraft.Battery.ENERGY_CAPACITY, 10_000, units='kJ') + prob.model.set_input_defaults(av.Aircraft.Battery.EFFICIENCY, efficiency, units='unitless') prob.model.set_input_defaults( - av.Aircraft.Battery.ENERGY_CAPACITY, 10_000, units='kJ') - prob.model.set_input_defaults( - av.Aircraft.Battery.EFFICIENCY, efficiency, units='unitless') - prob.model.set_input_defaults(av.Dynamic.Mission.CUMULATIVE_ELECTRIC_ENERGY_USED, [ - 0, 2_000, 5_000, 9_500], units='kJ') + av.Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, + [0, 2_000, 5_000, 9_500], + units='kJ', + ) prob.setup(force_alloc_complex=True) prob.run_model() - soc_expected = np.array([1., 0.7894736842105263, 0.4736842105263159, 0.]) - soc = prob.get_val(av.Dynamic.Mission.BATTERY_STATE_OF_CHARGE, 'unitless') + soc_expected = np.array([1.0, 0.7894736842105263, 0.4736842105263159, 0.0]) + soc = prob.get_val(av.Dynamic.Vehicle.BATTERY_STATE_OF_CHARGE, 'unitless') assert_near_equal(soc, soc_expected, tolerance=1e-10) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-9, rtol=1e-9) diff --git a/aviary/subsystems/geometry/combined_geometry.py b/aviary/subsystems/geometry/combined_geometry.py index f9f21c070a..a8cd18fb44 100644 --- a/aviary/subsystems/geometry/combined_geometry.py +++ b/aviary/subsystems/geometry/combined_geometry.py @@ -2,7 +2,6 @@ from aviary.subsystems.geometry.flops_based.prep_geom import PrepGeom from aviary.subsystems.geometry.gasp_based.size_group import SizeGroup -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import LegacyCode from aviary.variable_info.variables import Aircraft @@ -19,69 +18,61 @@ class CombinedGeometry(om.Group): def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + 'code_origin_to_prioritize', + values=[GASP, FLOPS, None], + default=None, + desc='sets which code origin to prioritize if there are conflicting outputs.', ) - self.options.declare('code_origin_to_prioritize', - values=[GASP, FLOPS, None], - default=None, - desc='sets which code origin to prioritize if there are' - ' conflicting outputs.' - ) - def setup(self): - aviary_inputs = self.options['aviary_options'] - self.add_subsystem( 'gasp_based_geom', - SizeGroup(aviary_options=aviary_inputs,), - promotes_inputs=["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], + promotes_outputs=['aircraft:*'], ) self.add_subsystem( - 'flops_based_geom', - PrepGeom(aviary_options=aviary_inputs), - promotes_inputs=['*'], - promotes_outputs=['*'] + 'flops_based_geom', PrepGeom(), promotes_inputs=['*'], promotes_outputs=['*'] ) def configure(self): prioritize_origin = self.options['code_origin_to_prioritize'] - override = self.manual_overrides = None + override = self.code_origin_overrides = None # These are outputs that are computed by both flops_based and gasp_based # geometry subsystems. flops_geom_pathname = self.flops_based_geom.pathname flops_fus_area_path = flops_geom_pathname + '.fuselage.' + Aircraft.Fuselage.WETTED_AREA - flops_fus_diam_path = flops_geom_pathname + \ - '.fuselage_prelim.' + Aircraft.Fuselage.AVG_DIAMETER + flops_fus_diam_path = ( + flops_geom_pathname + '.fuselage_prelim.' + Aircraft.Fuselage.AVG_DIAMETER + ) gasp_geom_pathname = self.gasp_based_geom.pathname gasp_fus_area_path = gasp_geom_pathname + '.fuselage.size.' + Aircraft.Fuselage.WETTED_AREA - gasp_fus_diam_path = gasp_geom_pathname + \ - '.fuselage.parameters.' + Aircraft.Fuselage.AVG_DIAMETER + gasp_fus_diam_path = ( + gasp_geom_pathname + '.fuselage.parameters.' + Aircraft.Fuselage.AVG_DIAMETER + ) if prioritize_origin is GASP: override = [flops_fus_area_path, flops_fus_diam_path] name = Aircraft.Fuselage.WETTED_AREA - outs = [(name, f"MANUAL_OVERRIDE:{name}")] + outs = [(name, f'CODE_ORIGIN_OVERRIDE:{name}')] self.flops_based_geom.promotes('fuselage', outputs=outs) name = Aircraft.Fuselage.AVG_DIAMETER - outs = [(name, f"MANUAL_OVERRIDE:{name}")] + outs = [(name, f'CODE_ORIGIN_OVERRIDE:{name}')] self.flops_based_geom.promotes('fuselage_prelim', outputs=outs) elif prioritize_origin is FLOPS: override = [gasp_fus_area_path, gasp_fus_diam_path] name = Aircraft.Fuselage.WETTED_AREA - outs = [(name, f"MANUAL_OVERRIDE:{name}")] + outs = [(name, f'CODE_ORIGIN_OVERRIDE:{name}')] self.gasp_based_geom.fuselage.promotes('size', outputs=outs) name = Aircraft.Fuselage.AVG_DIAMETER - outs = [(name, f"MANUAL_OVERRIDE:{name}")] + outs = [(name, f'CODE_ORIGIN_OVERRIDE:{name}')] self.gasp_based_geom.fuselage.promotes('parameters', outputs=outs) - self.manual_overrides = override + self.code_origin_overrides = override diff --git a/aviary/subsystems/geometry/flops_based/bwb_wing_detailed.py b/aviary/subsystems/geometry/flops_based/bwb_wing_detailed.py new file mode 100644 index 0000000000..5cdcf055bc --- /dev/null +++ b/aviary/subsystems/geometry/flops_based/bwb_wing_detailed.py @@ -0,0 +1,398 @@ +import numpy as np +import openmdao.api as om + +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Settings + + +class BWBUpdateDetailedWingDist(om.ExplicitComponent): + """ + Specify the shape using the detailed wing data capability. The root chord is redefined to be + equal to the length of the chord at the outboard cabin wall, and another segment is added for + the cabin itself. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.INPUT_STATION_DIST) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + num_stations = len(self.options[Aircraft.Wing.INPUT_STATION_DIST]) + add_aviary_input( + self, Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, shape=num_stations, units='unitless' + ) + add_aviary_input( + self, Aircraft.Wing.THICKNESS_TO_CHORD_DIST, shape=num_stations, units='unitless' + ) + add_aviary_input(self, Aircraft.Wing.LOAD_PATH_SWEEP_DIST, shape=num_stations, units='deg') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Wing.ROOT_CHORD, units='ft') + self.add_input( + 'Rear_spar_percent_chord', + 0.7, + units='unitless', + desc='RSPSOB: Rear spar percent chord for BWB at side of body', + ) + + self.add_output('BWB_INPUT_STATION_DIST', shape=num_stations, units='unitless') + self.add_output('BWB_CHORD_PER_SEMISPAN_DIST', shape=num_stations, units='unitless') + self.add_output('BWB_THICKNESS_TO_CHORD_DIST', shape=num_stations, units='unitless') + self.add_output('BWB_LOAD_PATH_SWEEP_DIST', shape=num_stations, units='deg') + + def setup_partials(self): + self.declare_partials('BWB_INPUT_STATION_DIST', '*', method='fd', form='forward') + + self.declare_partials('BWB_CHORD_PER_SEMISPAN_DIST', '*', method='fd', form='forward') + + self.declare_partials( + 'BWB_THICKNESS_TO_CHORD_DIST', + [ + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + Aircraft.Wing.THICKNESS_TO_CHORD, + ], + ) + + self.declare_partials( + 'BWB_LOAD_PATH_SWEEP_DIST', + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + val=1.0, + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + width = inputs[Aircraft.Fuselage.MAX_WIDTH][0] + wingspan = inputs[Aircraft.Wing.SPAN][0] + rate_span = (wingspan - width) / wingspan + length = inputs[Aircraft.Fuselage.LENGTH][0] + tc = inputs[Aircraft.Wing.THICKNESS_TO_CHORD][0] + root_chord = inputs[Aircraft.Wing.ROOT_CHORD][0] + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'][0] + if rear_spar_percent_chord <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Rear_spar_percent_chord must be positive.') + xl_out = root_chord / rear_spar_percent_chord + + bwb_input_station_dist = np.array( + self.options[Aircraft.Wing.INPUT_STATION_DIST], dtype=float + ) + bwb_input_station_dist = np.where( + bwb_input_station_dist <= 1.0, + bwb_input_station_dist * rate_span + width / wingspan, # if x <= 1.0 + bwb_input_station_dist + width / 2.0, # else + ) + bwb_input_station_dist[0] = 0.0 + bwb_input_station_dist[1] = width / 2.0 + outputs['BWB_INPUT_STATION_DIST'] = bwb_input_station_dist + + outputs['BWB_CHORD_PER_SEMISPAN_DIST'] = inputs[Aircraft.Wing.CHORD_PER_SEMISPAN_DIST] + idx = np.where(inputs[Aircraft.Wing.CHORD_PER_SEMISPAN_DIST] < 5.0) + outputs['BWB_CHORD_PER_SEMISPAN_DIST'][idx] *= rate_span + outputs['BWB_CHORD_PER_SEMISPAN_DIST'][0] = length + outputs['BWB_CHORD_PER_SEMISPAN_DIST'][1] = xl_out + + outputs['BWB_THICKNESS_TO_CHORD_DIST'][0] = tc + outputs['BWB_THICKNESS_TO_CHORD_DIST'][1] = tc + outputs['BWB_THICKNESS_TO_CHORD_DIST'][2:] = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_DIST][ + 2: + ] + + outputs['BWB_LOAD_PATH_SWEEP_DIST'][:] = inputs[Aircraft.Wing.LOAD_PATH_SWEEP_DIST] + + def compute_partials(self, inputs, J): + # width = inputs[Aircraft.Fuselage.MAX_WIDTH][0] + # wingspan = inputs[Aircraft.Wing.SPAN][0] + # rate_span = (wingspan - width) / wingspan + # length = inputs[Aircraft.Fuselage.LENGTH][0] + # tc = inputs[Aircraft.Wing.THICKNESS_TO_CHORD][0] + # root_chord = inputs[Aircraft.Wing.ROOT_CHORD][0] + # rear_spar_percent_chord = inputs['Rear_spar_percent_chord'][0] + # xl_out = root_chord / rear_spar_percent_chord + + num_stations = len(self.options[Aircraft.Wing.INPUT_STATION_DIST]) + + J['BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD][0] = 1.0 + J['BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD][1] = 1.0 + J['BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD][2:] = 0.0 + + diag2_matrix = np.identity(num_stations) + J['BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD_DIST] = diag2_matrix + J['BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD_DIST][0] = 0.0 + J['BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD_DIST][1] = 0.0 + + +class BWBComputeDetailedWingDist(om.ExplicitComponent): + """ + BWB requires detailed wing. If it is not provided, it will be created. This component + add a trapezoidal panel out to the total semispan with the root chord equal to the length + of the chord at the outboard cabin wall, and the tip chord equal to 6% of wing span. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.INPUT_STATION_DIST) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.ROOT_CHORD, units='ft') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + self.add_input( + 'Rear_spar_percent_chord', + 0.7, + units='unitless', + desc='RSPSOB: Rear spar percent chord for BWB at side of body', + ) + + self.add_output('BWB_INPUT_STATION_DIST', shape=3, units='unitless') + self.add_output('BWB_CHORD_PER_SEMISPAN_DIST', shape=3, units='unitless') + self.add_output('BWB_THICKNESS_TO_CHORD_DIST', shape=3, units='unitless') + self.add_output('BWB_LOAD_PATH_SWEEP_DIST', shape=3, units='deg') + + def setup_partials(self): + self.declare_partials( + 'BWB_INPUT_STATION_DIST', + [ + Aircraft.Fuselage.MAX_WIDTH, + ], + ) + self.declare_partials( + 'BWB_CHORD_PER_SEMISPAN_DIST', + [ + Aircraft.Fuselage.LENGTH, + Aircraft.Wing.ROOT_CHORD, + Aircraft.Wing.SPAN, + 'Rear_spar_percent_chord', + ], + ) + self.declare_partials('BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD) + self.declare_partials( + 'BWB_LOAD_PATH_SWEEP_DIST', + [ + Aircraft.Wing.SWEEP, + Aircraft.Wing.SPAN, + Aircraft.Wing.ROOT_CHORD, + Aircraft.Fuselage.MAX_WIDTH, + 'Rear_spar_percent_chord', + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + width = inputs[Aircraft.Fuselage.MAX_WIDTH][0] + wingspan = inputs[Aircraft.Wing.SPAN][0] + length = inputs[Aircraft.Fuselage.LENGTH][0] + root_chord = inputs[Aircraft.Wing.ROOT_CHORD][0] + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'][0] + if rear_spar_percent_chord <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Rear_spar_percent_chord must be positive.') + xl_out = root_chord / rear_spar_percent_chord + wing_tip_chord = 0.06 * wingspan + tc = inputs[Aircraft.Wing.THICKNESS_TO_CHORD][0] + sweep = inputs[Aircraft.Wing.SWEEP][0] + tr_out = wing_tip_chord / xl_out + ar_out = 2.0 * (wingspan - width) / (wing_tip_chord + xl_out) + + angle = np.tan(sweep / 57.2958) - 2.0 * (1 - tr_out) / (1 + tr_out) / ar_out + swp_ld_path = 57.2958 * np.arctan(angle) + + outputs['BWB_INPUT_STATION_DIST'][0] = 0.0 + outputs['BWB_INPUT_STATION_DIST'][1] = width / 2.0 + outputs['BWB_INPUT_STATION_DIST'][2] = 1.0 + + outputs['BWB_CHORD_PER_SEMISPAN_DIST'][0] = length + outputs['BWB_CHORD_PER_SEMISPAN_DIST'][1] = xl_out + outputs['BWB_CHORD_PER_SEMISPAN_DIST'][2] = wing_tip_chord + + outputs['BWB_THICKNESS_TO_CHORD_DIST'][0] = tc + outputs['BWB_THICKNESS_TO_CHORD_DIST'][1] = tc + outputs['BWB_THICKNESS_TO_CHORD_DIST'][2] = tc + + outputs['BWB_LOAD_PATH_SWEEP_DIST'][0] = 0.0 + outputs['BWB_LOAD_PATH_SWEEP_DIST'][1] = swp_ld_path + outputs['BWB_LOAD_PATH_SWEEP_DIST'][2] = swp_ld_path + + def compute_partials(self, inputs, J): + width = inputs[Aircraft.Fuselage.MAX_WIDTH][0] + wingspan = inputs[Aircraft.Wing.SPAN][0] + length = inputs[Aircraft.Fuselage.LENGTH][0] + root_chord = inputs[Aircraft.Wing.ROOT_CHORD][0] + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'][0] + xl_out = root_chord / rear_spar_percent_chord + wing_tip_chord = 0.06 * wingspan + tc = inputs[Aircraft.Wing.THICKNESS_TO_CHORD][0] + sweep = inputs[Aircraft.Wing.SWEEP][0] + tr_out = wing_tip_chord / xl_out + ar_out = 2.0 * (wingspan - width) / (wing_tip_chord + xl_out) + angle = np.tan(sweep / 57.2958) - 2.0 * (1 - tr_out) / (1 + tr_out) / ar_out + swp_ld_path = 57.2958 * np.arctan(angle) + + J['BWB_INPUT_STATION_DIST', Aircraft.Fuselage.MAX_WIDTH] = [0.0, 0.5, 0.0] + + J['BWB_CHORD_PER_SEMISPAN_DIST', Aircraft.Fuselage.LENGTH] = [1.0, 0.0, 0.0] + J['BWB_CHORD_PER_SEMISPAN_DIST', Aircraft.Wing.ROOT_CHORD] = [ + 0, + 1 / rear_spar_percent_chord, + 0, + ] + J['BWB_CHORD_PER_SEMISPAN_DIST', Aircraft.Wing.SPAN] = [0.0, 0.0, 0.06] + J['BWB_CHORD_PER_SEMISPAN_DIST', 'Rear_spar_percent_chord'] = [ + 0, + -root_chord / rear_spar_percent_chord**2, + 0.0, + ] + + J['BWB_THICKNESS_TO_CHORD_DIST', Aircraft.Wing.THICKNESS_TO_CHORD] = 1 + + dswp_ld_path_dsweep = 1 / (1 + angle**2) / np.cos(sweep / 57.2958) ** 2 + J['BWB_LOAD_PATH_SWEEP_DIST', Aircraft.Wing.SWEEP] = [ + 0.0, + dswp_ld_path_dsweep, + dswp_ld_path_dsweep, + ] + + dtr_out_dspan = 0.06 * rear_spar_percent_chord / root_chord + dar_out_dspan = ( + 2 + * (wing_tip_chord + xl_out - 0.06 * (wingspan - width)) + / (wing_tip_chord + xl_out) ** 2 + ) + dswp_ld_path_dspan = ( + 57.2958 + / (1 + angle**2) + * ( + 4 * dtr_out_dspan / (1 + tr_out) ** 2 / ar_out + + 2 * (2 / (1 + tr_out) - 1) * dar_out_dspan / ar_out**2 + ) + ) + J['BWB_LOAD_PATH_SWEEP_DIST', Aircraft.Wing.SPAN] = [ + 0.0, + dswp_ld_path_dspan, + dswp_ld_path_dspan, + ] + + dtr_out_droot_chord = -wing_tip_chord * rear_spar_percent_chord / root_chord**2 + dar_out_droot_chord = ( + -2 * (wingspan - width) / (wing_tip_chord + xl_out) ** 2 / rear_spar_percent_chord + ) + dswp_ld_path_droot_chord = ( + 57.2958 + / (1 + angle**2) + * ( + 4 * dtr_out_droot_chord / (1 + tr_out) ** 2 / ar_out + + 2 * (2 / (1 + tr_out) - 1) * dar_out_droot_chord / ar_out**2 + ) + ) + J['BWB_LOAD_PATH_SWEEP_DIST', Aircraft.Wing.ROOT_CHORD] = [ + 0.0, + dswp_ld_path_droot_chord, + dswp_ld_path_droot_chord, + ] + + dtr_out_dwidth = 0.0 + dar_out_dwidth = -2 / (wing_tip_chord + xl_out) + dswp_ld_path_dwidth = ( + 57.2958 + / (1 + angle**2) + * ( + 4 * dtr_out_dwidth / (1 + tr_out) ** 2 / ar_out + + 2 * (2 / (1 + tr_out) - 1) * dar_out_dwidth / ar_out**2 + ) + ) + J['BWB_LOAD_PATH_SWEEP_DIST', Aircraft.Fuselage.MAX_WIDTH] = [ + 0.0, + dswp_ld_path_dwidth, + dswp_ld_path_dwidth, + ] + + dtr_out_drear_chord = 0.06 * wingspan / root_chord + dar_out_drear_chord = ( + 2 + * (wingspan - width) + / (wing_tip_chord + xl_out) ** 2 + * root_chord + / rear_spar_percent_chord**2 + ) + dswp_ld_path_drear_chord = ( + 57.2958 + / (1 + angle**2) + * ( + 4 * dtr_out_drear_chord / (1 + tr_out) ** 2 / ar_out + + 2 * (2 / (1 + tr_out) - 1) * dar_out_drear_chord / ar_out**2 + ) + ) + J['BWB_LOAD_PATH_SWEEP_DIST', 'Rear_spar_percent_chord'] = [ + 0.0, + dswp_ld_path_drear_chord, + dswp_ld_path_drear_chord, + ] + + +class BWBWingPrelim(om.ExplicitComponent): + """preliminary calculations of wing aspect ratio for BWB using detailed wing information""" + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.NUM_INTEGRATION_STATIONS) + + def setup(self): + num_stations = self.options[Aircraft.Wing.NUM_INTEGRATION_STATIONS] + + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + self.add_input('BWB_INPUT_STATION_DIST', shape=num_stations, units='unitless') + self.add_input('BWB_CHORD_PER_SEMISPAN_DIST', shape=num_stations, units='unitless') + + add_aviary_output(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_output(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_output(self, Aircraft.Wing.LOAD_FRACTION, units='unitless') + + self.declare_partials('*', '*', method='fd', form='forward') + + def compute(self, inputs, outputs): + input_station_dist = inputs['BWB_INPUT_STATION_DIST'] + num_stations = len(inputs['BWB_INPUT_STATION_DIST']) + + glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] + width = inputs[Aircraft.Fuselage.MAX_WIDTH] + span = inputs[Aircraft.Wing.SPAN][0] + + ssm = 0.0 + bwb_chord_per_semispan_dist = inputs['BWB_CHORD_PER_SEMISPAN_DIST'] + + # Calculate Wing Area and Aspect Ratio for modified planform + if bwb_chord_per_semispan_dist[0] <= 5.0: + C1 = bwb_chord_per_semispan_dist[0] * span / 2.0 + else: + C1 = bwb_chord_per_semispan_dist[0] + if input_station_dist[0] <= 1.1: + Y1 = input_station_dist[0] * span / 2.0 + else: + Y1 = input_station_dist[0] + for n in range(1, num_stations): + if bwb_chord_per_semispan_dist[n] <= 5.0: + C2 = bwb_chord_per_semispan_dist[n] * span / 2.0 + else: + C2 = bwb_chord_per_semispan_dist[n] + if input_station_dist[n] <= 1.1: + Y2 = input_station_dist[n] * span / 2.0 + else: + Y2 = input_station_dist[n] + axp = (Y2 - Y1) * (C1 + C2) + C1 = C2 + Y1 = Y2 + ssm = ssm + axp + ar = span**2 / (ssm - glove_and_bat) + # Calculated wing area for aerodynamics + outputs[Aircraft.Wing.AREA] = ssm + outputs[Aircraft.Wing.ASPECT_RATIO] = ar + + # Estimate the percent load carried by the outboard wing + pct_load = (1.0 - width / span) ** 2 + outputs[Aircraft.Wing.LOAD_FRACTION] = pct_load diff --git a/aviary/subsystems/geometry/flops_based/canard.py b/aviary/subsystems/geometry/flops_based/canard.py index b9ca8d92ae..40095d929f 100644 --- a/aviary/subsystems/geometry/flops_based/canard.py +++ b/aviary/subsystems/geometry/flops_based/canard.py @@ -1,41 +1,42 @@ import openmdao.api as om from aviary.subsystems.geometry.flops_based.utils import ( - calc_lifting_surface_scaler, thickness_to_chord_scaler) + calc_lifting_surface_scaler, + thickness_to_chord_scaler, +) from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft class Canard(om.ExplicitComponent): - """ - Calculate the wetted area of canard. - """ + """Calculate the wetted area of canard.""" def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): - add_aviary_input(self, Aircraft.Canard.AREA, 0.0) - add_aviary_input(self, Aircraft.Canard.THICKNESS_TO_CHORD, 0.0) - add_aviary_input(self, Aircraft.Canard.WETTED_AREA_SCALER, 1.0) + add_aviary_input(self, Aircraft.Canard.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Canard.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Canard.WETTED_AREA_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Canard.WETTED_AREA, 0.0) + add_aviary_output(self, Aircraft.Canard.WETTED_AREA, units='ft**2') def setup_partials(self): self.declare_partials( Aircraft.Canard.WETTED_AREA, [ - Aircraft.Canard.AREA, Aircraft.Canard.THICKNESS_TO_CHORD, + Aircraft.Canard.AREA, + Aircraft.Canard.THICKNESS_TO_CHORD, Aircraft.Canard.WETTED_AREA_SCALER, - ] + ], ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): area = inputs[Aircraft.Canard.AREA] if area <= 0.0: @@ -58,17 +59,10 @@ def compute_partials(self, inputs, J, discrete_inputs=None): XMULTC = calc_lifting_surface_scaler(thickness_to_chord) scaler = inputs[Aircraft.Canard.WETTED_AREA_SCALER] - J[ - Aircraft.Canard.WETTED_AREA, - Aircraft.Canard.AREA - ] = scaler * XMULTC + J[Aircraft.Canard.WETTED_AREA, Aircraft.Canard.AREA] = scaler * XMULTC - J[ - Aircraft.Canard.WETTED_AREA, - Aircraft.Canard.THICKNESS_TO_CHORD - ] = scaler * thickness_to_chord_scaler * area + J[Aircraft.Canard.WETTED_AREA, Aircraft.Canard.THICKNESS_TO_CHORD] = ( + scaler * thickness_to_chord_scaler * area + ) - J[ - Aircraft.Canard.WETTED_AREA, - Aircraft.Canard.WETTED_AREA_SCALER - ] = XMULTC * area + J[Aircraft.Canard.WETTED_AREA, Aircraft.Canard.WETTED_AREA_SCALER] = XMULTC * area diff --git a/aviary/subsystems/geometry/flops_based/characteristic_lengths.py b/aviary/subsystems/geometry/flops_based/characteristic_lengths.py index 474fa7381b..f4fee39259 100644 --- a/aviary/subsystems/geometry/flops_based/characteristic_lengths.py +++ b/aviary/subsystems/geometry/flops_based/characteristic_lengths.py @@ -3,116 +3,217 @@ from aviary.subsystems.geometry.flops_based.utils import Names from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft -class CharacteristicLengths(om.ExplicitComponent): +class WingCharacteristicLength(om.ExplicitComponent): + """ + Calculate the characteristic length and fineness ratio of the wing. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION) + + def setup(self): + self.add_input(Names.CROOT, 0.0, units='unitless') + + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, units='ft**2') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + + add_aviary_output(self, Aircraft.Wing.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_output(self, Aircraft.Wing.FINENESS, units='unitless') + + def setup_partials(self): + wrt = [ + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.GLOVE_AND_BAT, + ] + + if self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION]: + wrt = [ + Names.CROOT, + Aircraft.Wing.TAPER_RATIO, + ] + + self.declare_partials(Aircraft.Wing.CHARACTERISTIC_LENGTH, wrt) + + self.declare_partials(Aircraft.Wing.FINENESS, Aircraft.Wing.THICKNESS_TO_CHORD, val=1.0) + + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + area = inputs[Aircraft.Wing.AREA] + glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] + aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] + + if self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION]: + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + CROOT = inputs[Names.CROOT] + + length = ( + 2.0 * CROOT * (1.0 + taper_ratio + taper_ratio**2.0) / (3.0 + 3.0 * taper_ratio) + ) + else: + length = ((area - glove_and_bat) / aspect_ratio) ** 0.5 + + outputs[Aircraft.Wing.CHARACTERISTIC_LENGTH] = length + + thickness_to_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] + + outputs[Aircraft.Wing.FINENESS] = thickness_to_chord + + def compute_partials(self, inputs, J, discrete_inputs=None): + if self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION]: + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + CROOT = inputs[Names.CROOT] + + a = 2.0 * (1.0 + taper_ratio + taper_ratio**2.0) + f = a * CROOT + df = 2.0 * CROOT * (1.0 + 2.0 * taper_ratio) + g = 3.0 + 3.0 * taper_ratio + dg = 3.0 + + J[Aircraft.Wing.CHARACTERISTIC_LENGTH, Names.CROOT] = a / g + + J[Aircraft.Wing.CHARACTERISTIC_LENGTH, Aircraft.Wing.TAPER_RATIO] = ( + df * g - f * dg + ) / g**2 + + else: + area = inputs[Aircraft.Wing.AREA] + glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] + aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] + + a = area - glove_and_bat + f = 0.5 * (a / aspect_ratio) ** -0.5 + df = f / aspect_ratio + + J[Aircraft.Wing.CHARACTERISTIC_LENGTH, Aircraft.Wing.AREA] = df + + J[Aircraft.Wing.CHARACTERISTIC_LENGTH, Aircraft.Wing.GLOVE_AND_BAT] = -df + + J[Aircraft.Wing.CHARACTERISTIC_LENGTH, Aircraft.Wing.ASPECT_RATIO] = ( + -f * a / aspect_ratio**2.0 + ) + + +class BWBWingCharacteristicLength(om.ExplicitComponent): + """ + Calculate the characteristic length and fineness ratio of the wing of BWB. + """ + + def setup(self): + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + + add_aviary_output(self, Aircraft.Wing.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_output(self, Aircraft.Wing.FINENESS, units='unitless') + + def setup_partials(self): + wrt = [ + Aircraft.Wing.SPAN, + Aircraft.Wing.AREA, + ] + + self.declare_partials(Aircraft.Wing.CHARACTERISTIC_LENGTH, wrt) + + self.declare_partials(Aircraft.Wing.FINENESS, Aircraft.Wing.THICKNESS_TO_CHORD, val=1.0) + + def compute(self, inputs, outputs): + wing_span = inputs[Aircraft.Wing.SPAN] + wing_area = inputs[Aircraft.Wing.AREA] + cl = wing_area / wing_span + outputs[Aircraft.Wing.CHARACTERISTIC_LENGTH] = cl + + # a little redundant but FLOPS used two variables + thickness_to_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] + outputs[Aircraft.Wing.FINENESS] = thickness_to_chord + + def compute_partials(self, inputs, J): + wing_span = inputs[Aircraft.Wing.SPAN] + wing_area = inputs[Aircraft.Wing.AREA] + J[Aircraft.Wing.CHARACTERISTIC_LENGTH, Aircraft.Wing.SPAN] = -wing_area / wing_span**2 + J[Aircraft.Wing.CHARACTERISTIC_LENGTH, Aircraft.Wing.AREA] = 1.0 / wing_span + + +class OtherCharacteristicLengths(om.ExplicitComponent): """ Calculate the characteristic length and fineness ratio of the canard, fuselage, horizontal tail, nacelle, and vertical tail. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) self.add_input(Names.CROOT, 0.0, units='unitless') - add_aviary_input(self, Aircraft.Canard.AREA, 0.0) - add_aviary_input(self, Aircraft.Canard.ASPECT_RATIO, 0.0) + add_aviary_input(self, Aircraft.Canard.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Canard.ASPECT_RATIO, units='unitless') # add_aviary_input(self, Aircraft.Canard.LAMINAR_FLOW_LOWER, 0.0) # add_aviary_input(self, Aircraft.Canard.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.Canard.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.Canard.THICKNESS_TO_CHORD, units='unitless') - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, 0.0) + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') # add_aviary_input(self, Aircraft.Fuselage.LAMINAR_FLOW_LOWER, 0.0) # add_aviary_input(self, Aircraft.Fuselage.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.Fuselage.LENGTH, 0.0) + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') - add_aviary_input(self, Aircraft.HorizontalTail.AREA, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.ASPECT_RATIO, 4.75) + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.ASPECT_RATIO, units='unitless') # add_aviary_input(self, Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER, 0.0) # add_aviary_input(self, Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, units='unitless') - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, np.zeros(num_engine_type)) + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, shape=num_engine_type, units='ft') # add_aviary_input(self, Aircraft.Nacelle.LAMINAR_FLOW_LOWER, 0.0) # add_aviary_input(self, Aircraft.Nacelle.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.AREA, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.ASPECT_RATIO, 0.0) + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.ASPECT_RATIO, units='unitless') # add_aviary_input(self, Aircraft.VerticalTail.LAMINAR_FLOW_LOWER, 0.0) # add_aviary_input(self, Aircraft.VerticalTail.LAMINAR_FLOW_UPPER, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.0) - - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, 0.0) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) - # add_aviary_input(self, Aircraft.Wing.LAMINAR_FLOW_LOWER, 0.0) - # add_aviary_input(self, Aircraft.Wing.LAMINAR_FLOW_UPPER, 0.0) - - add_aviary_output(self, Aircraft.Canard.CHARACTERISTIC_LENGTH, 0.0) - add_aviary_output(self, Aircraft.Canard.FINENESS, 0.0) + add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, units='unitless') - add_aviary_output(self, Aircraft.Fuselage.CHARACTERISTIC_LENGTH, 0.0) - add_aviary_output(self, Aircraft.Fuselage.FINENESS, 0.0) - - add_aviary_output( - self, Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, 0.0 - ) + add_aviary_output(self, Aircraft.Canard.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_output(self, Aircraft.Canard.FINENESS, units='unitless') - add_aviary_output(self, Aircraft.HorizontalTail.FINENESS, 0.0) + add_aviary_output(self, Aircraft.Fuselage.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_output(self, Aircraft.Fuselage.FINENESS, units='unitless') - add_aviary_output(self, Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - np.zeros(num_engine_type)) - add_aviary_output(self, Aircraft.Nacelle.FINENESS, np.zeros(num_engine_type)) + add_aviary_output(self, Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_output(self, Aircraft.HorizontalTail.FINENESS, units='unitless') add_aviary_output( - self, Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, 0.0 + self, Aircraft.Nacelle.CHARACTERISTIC_LENGTH, shape=num_engine_type, units='ft' ) + add_aviary_output(self, Aircraft.Nacelle.FINENESS, shape=num_engine_type, units='unitless') - add_aviary_output(self, Aircraft.VerticalTail.FINENESS, 0.0) - - add_aviary_output(self, Aircraft.Wing.CHARACTERISTIC_LENGTH, 0.0) - add_aviary_output(self, Aircraft.Wing.FINENESS, 0.0) + add_aviary_output(self, Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, units='ft') + add_aviary_output(self, Aircraft.VerticalTail.FINENESS, units='unitless') def setup_partials(self): - self._setup_partials_wing() self._setup_partials_horizontal_tail() self._setup_partials_vertical_tail() self._setup_partials_fuselage() self._setup_partials_nacelles() self._setup_partials_canard() - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - self._compute_wing(inputs, outputs, discrete_inputs, discrete_outputs) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + self._compute_horizontal_tail(inputs, outputs, discrete_inputs, discrete_outputs) - self._compute_horizontal_tail( - inputs, outputs, discrete_inputs, discrete_outputs - ) + self._compute_vertical_tail(inputs, outputs, discrete_inputs, discrete_outputs) - self._compute_vertical_tail( - inputs, outputs, discrete_inputs, discrete_outputs - ) + self._compute_fuselage(inputs, outputs, discrete_inputs, discrete_outputs) - self._compute_fuselage( - inputs, outputs, discrete_inputs, discrete_outputs - ) - - self._compute_nacelles( - inputs, outputs, discrete_inputs, discrete_outputs - ) + self._compute_nacelles(inputs, outputs, discrete_inputs, discrete_outputs) # self._compute_additional_fuselages( # inputs, outputs, discrete_inputs, discrete_outputs @@ -122,51 +223,26 @@ def compute( # inputs, outputs, discrete_inputs, discrete_outputs # ) - self._compute_canard( - inputs, outputs, discrete_inputs, discrete_outputs - ) + self._compute_canard(inputs, outputs, discrete_inputs, discrete_outputs) def compute_partials(self, inputs, J, discrete_inputs=None): - self._compute_partials_wing(inputs, J, discrete_inputs) self._compute_partials_horizontal_tail(inputs, J, discrete_inputs) self._compute_partials_vertical_tail(inputs, J, discrete_inputs) self._compute_partials_fuselage(inputs, J, discrete_inputs) self._compute_partials_nacelles(inputs, J, discrete_inputs) self._compute_partials_canard(inputs, J, discrete_inputs) - def _setup_partials_wing(self): - wrt = [ - Aircraft.Wing.AREA, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.GLOVE_AND_BAT, - ] - - aviary_options: AviaryValues = self.options['aviary_options'] - - if aviary_options.get_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION): - wrt = [ - Names.CROOT, - Aircraft.Wing.TAPER_RATIO, - ] - - self.declare_partials(Aircraft.Wing.CHARACTERISTIC_LENGTH, wrt) - - self.declare_partials( - Aircraft.Wing.FINENESS, Aircraft.Wing.THICKNESS_TO_CHORD, val=1.0 - ) - def _setup_partials_horizontal_tail(self): self.declare_partials( Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, [ Aircraft.HorizontalTail.AREA, Aircraft.HorizontalTail.ASPECT_RATIO, - ] + ], ) self.declare_partials( - Aircraft.HorizontalTail.FINENESS, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=1.0 + Aircraft.HorizontalTail.FINENESS, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=1.0 ) def _setup_partials_vertical_tail(self): @@ -175,18 +251,16 @@ def _setup_partials_vertical_tail(self): [ Aircraft.VerticalTail.AREA, Aircraft.VerticalTail.ASPECT_RATIO, - ] + ], ) self.declare_partials( - Aircraft.VerticalTail.FINENESS, - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=1.0 + Aircraft.VerticalTail.FINENESS, Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=1.0 ) def _setup_partials_fuselage(self): self.declare_partials( - Aircraft.Fuselage.CHARACTERISTIC_LENGTH, - Aircraft.Fuselage.LENGTH, val=1.0 + Aircraft.Fuselage.CHARACTERISTIC_LENGTH, Aircraft.Fuselage.LENGTH, val=1.0 ) self.declare_partials( @@ -194,19 +268,21 @@ def _setup_partials_fuselage(self): [ Aircraft.Fuselage.AVG_DIAMETER, Aircraft.Fuselage.LENGTH, - ] + ], ) def _setup_partials_nacelles(self): # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) self.declare_partials( Aircraft.Nacelle.CHARACTERISTIC_LENGTH, Aircraft.Nacelle.AVG_LENGTH, - rows=shape, cols=shape, val=1.0) + rows=shape, + cols=shape, + val=1.0, + ) self.declare_partials( Aircraft.Nacelle.FINENESS, @@ -214,7 +290,10 @@ def _setup_partials_nacelles(self): Aircraft.Nacelle.AVG_DIAMETER, Aircraft.Nacelle.AVG_LENGTH, ], - rows=shape, cols=shape, val=1.0) + rows=shape, + cols=shape, + val=1.0, + ) def _setup_partials_canard(self): self.declare_partials( @@ -222,7 +301,7 @@ def _setup_partials_canard(self): [ Aircraft.Canard.AREA, Aircraft.Canard.ASPECT_RATIO, - ] + ], ) self.declare_partials( @@ -230,32 +309,6 @@ def _setup_partials_canard(self): Aircraft.Canard.THICKNESS_TO_CHORD, ) - def _compute_wing( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - area = inputs[Aircraft.Wing.AREA] - glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] - aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] - - length = ((area - glove_and_bat) / aspect_ratio)**0.5 - - aviary_options: AviaryValues = self.options['aviary_options'] - - if aviary_options.get_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION): - taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] - CROOT = inputs[Names.CROOT] - - length = ( - 2.0 * CROOT * (1.0 + taper_ratio + taper_ratio**2.0) - / (3.0 + 3.0 * taper_ratio) - ) - - outputs[Aircraft.Wing.CHARACTERISTIC_LENGTH] = length - - thickness_to_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] - - outputs[Aircraft.Wing.FINENESS] = thickness_to_chord - def _compute_horizontal_tail( self, inputs, outputs, discrete_inputs=None, discrete_outputs=None ): @@ -266,7 +319,7 @@ def _compute_horizontal_tail( if 0.0 < aspect_ratio: area = inputs[Aircraft.HorizontalTail.AREA] - length = (area / aspect_ratio)**0.5 + length = (area / aspect_ratio) ** 0.5 outputs[Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH] = length @@ -274,9 +327,7 @@ def _compute_horizontal_tail( outputs[Aircraft.HorizontalTail.FINENESS] = thickness_to_chord - def _compute_vertical_tail( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def _compute_vertical_tail(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): aspect_ratio = inputs[Aircraft.VerticalTail.ASPECT_RATIO] length = 0.0 @@ -284,7 +335,7 @@ def _compute_vertical_tail( if 0.0 < aspect_ratio: area = inputs[Aircraft.VerticalTail.AREA] - length = (area / aspect_ratio)**0.5 + length = (area / aspect_ratio) ** 0.5 outputs[Aircraft.VerticalTail.CHARACTERISTIC_LENGTH] = length @@ -292,9 +343,7 @@ def _compute_vertical_tail( outputs[Aircraft.VerticalTail.FINENESS] = thickness_to_chord - def _compute_fuselage( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def _compute_fuselage(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): length = inputs[Aircraft.Fuselage.LENGTH] outputs[Aircraft.Fuselage.CHARACTERISTIC_LENGTH] = length @@ -305,12 +354,10 @@ def _compute_fuselage( outputs[Aircraft.Fuselage.FINENESS] = fineness - def _compute_nacelles( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def _compute_nacelles(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): # TODO do all engines support nacelles? If not, is this deliberate, or # just an artifact of the implementation? - num_eng = self.options['aviary_options'].get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] avg_diam = inputs[Aircraft.Nacelle.AVG_DIAMETER] avg_length = inputs[Aircraft.Nacelle.AVG_LENGTH] @@ -329,6 +376,7 @@ def _compute_nacelles( outputs[Aircraft.Nacelle.CHARACTERISTIC_LENGTH] = char_len outputs[Aircraft.Nacelle.FINENESS] = fineness + # NOTE this code is currently unused!! def _compute_additional_fuselages( self, inputs, outputs, discrete_inputs=None, discrete_outputs=None ): @@ -359,6 +407,7 @@ def _compute_additional_fuselages( idx += 1 + # NOTE this code is currently unused!! def _compute_additional_vertical_tails( self, inputs, outputs, discrete_inputs=None, discrete_outputs=None ): @@ -390,9 +439,7 @@ def _compute_additional_vertical_tails( idx += 1 - def _compute_canard( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def _compute_canard(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): area = inputs[Aircraft.Canard.AREA] if area <= 0.0: @@ -404,62 +451,13 @@ def _compute_canard( length = 0.0 if 0.0 < aspect_ratio: - length = (area / aspect_ratio)**0.5 + length = (area / aspect_ratio) ** 0.5 outputs[Aircraft.Canard.CHARACTERISTIC_LENGTH] = length outputs[Aircraft.Canard.FINENESS] = thickness_to_chord - def _compute_partials_wing(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - - if aviary_options.get_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION): - taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] - CROOT = inputs[Names.CROOT] - - a = 2.0 * (1.0 + taper_ratio + taper_ratio**2.0) - f = a * CROOT - df = 2.0 * CROOT * (1.0 + 2.0 * taper_ratio) - g = (3.0 + 3.0 * taper_ratio) - dg = 3.0 - - J[ - Aircraft.Wing.CHARACTERISTIC_LENGTH, - Names.CROOT - ] = a / g - - J[ - Aircraft.Wing.CHARACTERISTIC_LENGTH, - Aircraft.Wing.TAPER_RATIO - ] = (df * g - f * dg) / g**2 - - else: - area = inputs[Aircraft.Wing.AREA] - glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] - aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] - - a = area - glove_and_bat - f = 0.5 * (a / aspect_ratio)**-0.5 - df = f / aspect_ratio - - J[ - Aircraft.Wing.CHARACTERISTIC_LENGTH, - Aircraft.Wing.AREA - ] = df - - J[ - Aircraft.Wing.CHARACTERISTIC_LENGTH, - Aircraft.Wing.GLOVE_AND_BAT - ] = -df - - J[ - Aircraft.Wing.CHARACTERISTIC_LENGTH, - Aircraft.Wing.ASPECT_RATIO - ] = -f * a / aspect_ratio**2.0 - - def _compute_partials_horizontal_tail( - self, inputs, J, discrete_inputs=None - ): + def _compute_partials_horizontal_tail(self, inputs, J, discrete_inputs=None): aspect_ratio = inputs[Aircraft.HorizontalTail.ASPECT_RATIO] da = dr = 0.0 @@ -467,19 +465,13 @@ def _compute_partials_horizontal_tail( if 0.0 < aspect_ratio: area = inputs[Aircraft.HorizontalTail.AREA] - f = 0.5 * (area / aspect_ratio)**-0.5 + f = 0.5 * (area / aspect_ratio) ** -0.5 da = f / aspect_ratio dr = -f * area / aspect_ratio**2.0 - J[ - Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, - Aircraft.HorizontalTail.AREA - ] = da + J[Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, Aircraft.HorizontalTail.AREA] = da - J[ - Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, - Aircraft.HorizontalTail.ASPECT_RATIO - ] = dr + J[Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, Aircraft.HorizontalTail.ASPECT_RATIO] = dr def _compute_partials_vertical_tail(self, inputs, J, discrete_inputs=None): aspect_ratio = inputs[Aircraft.VerticalTail.ASPECT_RATIO] @@ -489,36 +481,24 @@ def _compute_partials_vertical_tail(self, inputs, J, discrete_inputs=None): if 0.0 < aspect_ratio: area = inputs[Aircraft.VerticalTail.AREA] - f = 0.5 * (area / aspect_ratio)**-0.5 + f = 0.5 * (area / aspect_ratio) ** -0.5 da = f / aspect_ratio dr = -f * area / aspect_ratio**2.0 - J[ - Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, - Aircraft.VerticalTail.AREA - ] = da + J[Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, Aircraft.VerticalTail.AREA] = da - J[ - Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, - Aircraft.VerticalTail.ASPECT_RATIO - ] = dr + J[Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, Aircraft.VerticalTail.ASPECT_RATIO] = dr def _compute_partials_fuselage(self, inputs, J, discrete_inputs=None): length = inputs[Aircraft.Fuselage.LENGTH] avg_diam = inputs[Aircraft.Fuselage.AVG_DIAMETER] - J[ - Aircraft.Fuselage.FINENESS, - Aircraft.Fuselage.LENGTH - ] = 1.0 / avg_diam + J[Aircraft.Fuselage.FINENESS, Aircraft.Fuselage.LENGTH] = 1.0 / avg_diam - J[ - Aircraft.Fuselage.FINENESS, - Aircraft.Fuselage.AVG_DIAMETER - ] = -length / avg_diam**2.0 + J[Aircraft.Fuselage.FINENESS, Aircraft.Fuselage.AVG_DIAMETER] = -length / avg_diam**2.0 def _compute_partials_nacelles(self, inputs, J, discrete_inputs=None): - num_eng = self.options['aviary_options'].get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] avg_diam = inputs[Aircraft.Nacelle.AVG_DIAMETER] avg_length = inputs[Aircraft.Nacelle.AVG_LENGTH] @@ -533,37 +513,21 @@ def _compute_partials_nacelles(self, inputs, J, discrete_inputs=None): calc_idx = np.where(num_eng >= 1) deriv_char_len[calc_idx] = 1.0 deriv_fine_len[calc_idx] = 1.0 / avg_diam[calc_idx] - deriv_fine_diam[calc_idx] = -avg_length[calc_idx] / avg_diam[calc_idx]**2.0 + deriv_fine_diam[calc_idx] = -avg_length[calc_idx] / avg_diam[calc_idx] ** 2.0 - J[ - Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - Aircraft.Nacelle.AVG_LENGTH - ] = deriv_char_len + J[Aircraft.Nacelle.CHARACTERISTIC_LENGTH, Aircraft.Nacelle.AVG_LENGTH] = deriv_char_len - J[ - Aircraft.Nacelle.FINENESS, - Aircraft.Nacelle.AVG_LENGTH - ] = deriv_fine_len + J[Aircraft.Nacelle.FINENESS, Aircraft.Nacelle.AVG_LENGTH] = deriv_fine_len - J[ - Aircraft.Nacelle.FINENESS, - Aircraft.Nacelle.AVG_DIAMETER - ] = deriv_fine_diam + J[Aircraft.Nacelle.FINENESS, Aircraft.Nacelle.AVG_DIAMETER] = deriv_fine_diam def _compute_partials_canard(self, inputs, J, discrete_inputs=None): area = inputs[Aircraft.Canard.AREA] if area <= 0.0: - J[ - Aircraft.Canard.CHARACTERISTIC_LENGTH, - Aircraft.Canard.AREA - ] = J[ - Aircraft.Canard.CHARACTERISTIC_LENGTH, - Aircraft.Canard.ASPECT_RATIO - ] = J[ - Aircraft.Canard.FINENESS, - Aircraft.Canard.THICKNESS_TO_CHORD - ] = 0.0 + J[Aircraft.Canard.CHARACTERISTIC_LENGTH, Aircraft.Canard.AREA] = J[ + Aircraft.Canard.CHARACTERISTIC_LENGTH, Aircraft.Canard.ASPECT_RATIO + ] = J[Aircraft.Canard.FINENESS, Aircraft.Canard.THICKNESS_TO_CHORD] = 0.0 return @@ -574,21 +538,12 @@ def _compute_partials_canard(self, inputs, J, discrete_inputs=None): if 0.0 < aspect_ratio: area = inputs[Aircraft.Canard.AREA] - f = 0.5 * (area / aspect_ratio)**-0.5 + f = 0.5 * (area / aspect_ratio) ** -0.5 da = f / aspect_ratio dr = -f * area / aspect_ratio**2.0 - J[ - Aircraft.Canard.CHARACTERISTIC_LENGTH, - Aircraft.Canard.AREA - ] = da + J[Aircraft.Canard.CHARACTERISTIC_LENGTH, Aircraft.Canard.AREA] = da - J[ - Aircraft.Canard.CHARACTERISTIC_LENGTH, - Aircraft.Canard.ASPECT_RATIO - ] = dr + J[Aircraft.Canard.CHARACTERISTIC_LENGTH, Aircraft.Canard.ASPECT_RATIO] = dr - J[ - Aircraft.Canard.FINENESS, - Aircraft.Canard.THICKNESS_TO_CHORD - ] = 1.0 + J[Aircraft.Canard.FINENESS, Aircraft.Canard.THICKNESS_TO_CHORD] = 1.0 diff --git a/aviary/subsystems/geometry/flops_based/fuselage.py b/aviary/subsystems/geometry/flops_based/fuselage.py index ff2f87c485..4f5e3de5cd 100644 --- a/aviary/subsystems/geometry/flops_based/fuselage.py +++ b/aviary/subsystems/geometry/flops_based/fuselage.py @@ -1,47 +1,51 @@ -""" -Contains any preliminary calculations on the fuselage. -""" +"""Contains any preliminary calculations on the fuselage.""" +import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft +from aviary.utils.functions import smooth_int_tanh, d_smooth_int_tanh +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Mission, Settings class FuselagePrelim(om.ExplicitComponent): """ Calculate fuselage average diameter and planform area defined by: Aircraft.Fuselage.AVG_DIAMETER = 0.5 * (max_height + max_width) - Aircraft.Fuselage.PLANFORM_AREA = length * max_width + Aircraft.Fuselage.PLANFORM_AREA = length * max_width. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Settings.VERBOSITY) def setup(self): - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=0.0) - add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, val=0.0) - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, val=0.0) + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') - add_aviary_output(self, Aircraft.Fuselage.AVG_DIAMETER, val=0.0) - add_aviary_output(self, Aircraft.Fuselage.PLANFORM_AREA, val=0.0) + add_aviary_output(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_output(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2') def setup_partials(self): - self.declare_partials(of=[Aircraft.Fuselage.AVG_DIAMETER], - wrt=[Aircraft.Fuselage.MAX_HEIGHT, - Aircraft.Fuselage.MAX_WIDTH], - val=0.5) - self.declare_partials(of=[Aircraft.Fuselage.PLANFORM_AREA], - wrt=[Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.MAX_WIDTH]) + self.declare_partials( + of=[Aircraft.Fuselage.AVG_DIAMETER], + wrt=[Aircraft.Fuselage.MAX_HEIGHT, Aircraft.Fuselage.MAX_WIDTH], + val=0.5, + ) + self.declare_partials( + of=[Aircraft.Fuselage.PLANFORM_AREA], + wrt=[Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.MAX_WIDTH], + ) def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] max_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] length = inputs[Aircraft.Fuselage.LENGTH] + if length <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Fuselage.LENGTH must be positive.') avg_diameter = 0.5 * (max_height + max_width) outputs[Aircraft.Fuselage.AVG_DIAMETER] = avg_diameter @@ -52,8 +56,649 @@ def compute_partials(self, inputs, partials, discrete_inputs=None): max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] length = inputs[Aircraft.Fuselage.LENGTH] - partials[Aircraft.Fuselage.PLANFORM_AREA, - Aircraft.Fuselage.LENGTH] = max_width + partials[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Fuselage.LENGTH] = max_width - partials[Aircraft.Fuselage.PLANFORM_AREA, - Aircraft.Fuselage.MAX_WIDTH] = length + partials[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Fuselage.MAX_WIDTH] = length + + +class BWBFuselagePrelim(om.ExplicitComponent): + """Calculate fuselage average diameter and planform area for BWB""" + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_input(self, Aircraft.Wing.ROOT_CHORD, units='ft') + self.add_input( + 'Rear_spar_percent_chord', + 0.7, + units='unitless', + desc='RSPSOB: Rear spar percent chord for BWB at side of body', + ) + + add_aviary_output(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_output(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2') + + def setup_partials(self): + self.declare_partials( + of=[Aircraft.Fuselage.AVG_DIAMETER], + wrt=[Aircraft.Fuselage.MAX_HEIGHT, Aircraft.Fuselage.MAX_WIDTH], + val=0.5, + ) + self.declare_partials( + of=[Aircraft.Fuselage.PLANFORM_AREA], + wrt=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Wing.ROOT_CHORD, + 'Rear_spar_percent_chord', + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] + length = inputs[Aircraft.Fuselage.LENGTH] + max_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] + root_chord = inputs[Aircraft.Wing.ROOT_CHORD] + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'] + + if length <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Fuselage.LENGTH must be positive.') + if rear_spar_percent_chord <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Rear_spar_percent_chord must be positive. It is default to 0.7') + + # not sure if this is right definition and not sure if it is used for BWB. + avg_diameter = 0.5 * (max_height + max_width) + planform_area = max_width * (length + root_chord / rear_spar_percent_chord) / 2.0 + + outputs[Aircraft.Fuselage.AVG_DIAMETER] = avg_diameter + outputs[Aircraft.Fuselage.PLANFORM_AREA] = planform_area + + def compute_partials(self, inputs, partials): + max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] + length = inputs[Aircraft.Fuselage.LENGTH] + root_chord = inputs[Aircraft.Wing.ROOT_CHORD] + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'] + + partials[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Fuselage.LENGTH] = max_width / 2.0 + partials[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Fuselage.MAX_WIDTH] = ( + length + root_chord / rear_spar_percent_chord + ) / 2.0 + partials[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Wing.ROOT_CHORD] = ( + max_width / rear_spar_percent_chord / 2.0 + ) + partials[Aircraft.Fuselage.PLANFORM_AREA, 'Rear_spar_percent_chord'] = ( + -max_width * root_chord / rear_spar_percent_chord**2 / 2.0 + ) + + +class SimpleCabinLayout(om.ExplicitComponent): + """Given fuselage length, height and width, compute passenger compartment length.""" + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + + add_aviary_output(self, Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, units='ft') + + def setup_partials(self): + self.declare_partials( + of=[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH], + wrt=[Aircraft.Fuselage.LENGTH], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + length = inputs[Aircraft.Fuselage.LENGTH] + max_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] + max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] + if length <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Fuselage.LENGTH must be positive to use simple cabin layout.') + if max_height <= 0.0 or max_width <= 0.0: + if verbosity > Verbosity.BRIEF: + print( + 'Aircraft.Fuselage.MAX_HEIGHT & Aircraft.Fuselage.MAX_WIDTH must be positive.' + ) + + pax_compart_length = 0.6085 * length * (np.arctan(length / 59.0)) ** 1.1 + if pax_compart_length > 190.0: + if verbosity > Verbosity.BRIEF: + print( + 'Passenger compartiment lenght is longer than recommended maximum length. ' + 'Suggest use detailed laylout algorithm.' + ) + outputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] = pax_compart_length + + def compute_partials(self, inputs, J): + length = inputs[Aircraft.Fuselage.LENGTH] + atan = np.arctan(length / 59.0) + deriv = 0.6085 * ( + (atan) ** 1.1 + 1.1 * length * atan**0.1 / (1 + (length / 59.0) ** 2) / 59.0 + ) + J[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, Aircraft.Fuselage.LENGTH] = deriv + + +class DetailedCabinLayout(om.ExplicitComponent): + """Compute fuselage dimensions using cabin seat information.""" + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + + def setup(self): + add_aviary_input(self, Mission.Design.RANGE, units='NM') + + add_aviary_output(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_output(self, Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, units='ft') + add_aviary_output(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_output(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + + self.declare_partials('*', '*', method='fd', form='forward') + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + num_first_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + num_tourist_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] + fuselage_multiplier = 1.0 + num_fuselage = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + if num_fuselage > 1: + if verbosity > Verbosity.BRIEF: + print('Multiple fuselage configuration is not implemented yet.') + + num_seat_abreast_first = self.options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST] + num_seat_abreast_tourist = self.options[ + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST + ] + # The 200 was derived from B757 - the largest single aisle western desig. + if num_tourist_class_pax > 200: + if num_seat_abreast_tourist <= 0: + num_seat_abreast_tourist = 8 + if num_seat_abreast_first > 0 and num_seat_abreast_first <= 0: + num_seat_abreast_first = num_seat_abreast_tourist - 2 + + if num_seat_abreast_first <= 0 and num_first_class_pax > 0: + num_seat_abreast_first = 4 + if num_seat_abreast_tourist <= 0 and num_tourist_class_pax > 0: + num_seat_abreast_tourist = 6 + + # Though these are not user definable, the values here are typical for most transport + aisle_width_first_class = 20.0 # inch + aisle_width_tourist_class = 18.0 # inch + + # If there are less than 60 passengers on board, then the aisle should be slightly narrow. + # Also, if the number of passengers abreast was not specified, then set it to 5 as 6 is too much + # for a typical short range transport. + if num_tourist_class_pax < 60: + if num_seat_abreast_tourist <= 0: + num_seat_abreast_tourist = 5 + aisle_width_tourist_class = 15.0 + + if num_seat_abreast_tourist > 6: + num_aisles = 2 + else: + num_aisles = 1 + + # Even though the widebody gives you more room, the aisles in it are a little narrower. + # That is what is set here. It is assumed that if the number of abreast is greater than + # 4 or 6 as shown below that we are working with a widebody aircraft. + if num_seat_abreast_first > 4: + aisle_width_first_class = 18.0 + if num_seat_abreast_tourist > 6: + aisle_width_tourist_class = 15.0 + + seat_pitch_first = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST][0] + if seat_pitch_first <= 0 and num_first_class_pax > 0: + seat_pitch_first = 38.0 # inch + seat_pitch_tourist = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST][0] + if seat_pitch_tourist <= 0 and num_tourist_class_pax > 0: + seat_pitch_tourist = 34.0 # inch + + # set maximum number of galleys based on statistics (this block is not from FLOPS) + num_pax = num_first_class_pax + num_tourist_class_pax + if num_pax < 80: + max_galleys = 1 + max_lav = 1 + max_closets = 1 + elif num_pax < 150: + max_galleys = 2 + max_lav = 2 + max_closets = 2 + elif num_pax < 250: + max_galleys = 3 + max_lav = 4 + max_closets = 3 + elif num_pax < 320: + max_galleys = 4 + max_lav = 6 + max_closets = 4 + elif num_pax < 350: + max_galleys = 5 + max_lav = 8 + max_closets = 5 + elif num_pax < 410: + max_galleys = 6 + max_lav = 12 + max_closets = 6 + elif num_pax < 450: + max_galleys = 7 + max_lav = 13 + max_closets = 7 + elif num_pax < 500: + max_galleys = 8 + max_lav = 14 + max_closets = 8 + elif num_pax < 550: + max_galleys = 9 + max_lav = 15 + max_closets = 9 + elif num_pax < 600: + max_galleys = 10 + max_lav = 16 + max_closets = 10 + else: + max_galleys = 10 + max_lav = 16 + max_closets = 10 + # The above settings are necessary because FLOPS didn't cover all the scenarios. + # They will be over written if FLOPS covered a particular scenario as we see below. + + # Set constraints on the maximum number of galleys and other items so that we don't have + # a flying kitchen or closet or whatever. + # Note: Some of these may need relaxing for larger aircraft. + if num_first_class_pax == 0: + design_range = inputs[Mission.Design.RANGE] + if design_range < 1250.0: + max_lav = 2 + else: + max_lav = 3 + if num_tourist_class_pax < 180: + fuselage_multiplier = 0.91 + max_galleys = 2 + max_closets = 2 + + if num_first_class_pax == 0 and num_tourist_class_pax < 110: + max_lav = 1 + max_galleys = 1 + max_closets = 1 + + if num_tourist_class_pax > 320: + max_lav = 4 + max_galleys = 4 + max_closets = 4 + elif num_tourist_class_pax > 600: + max_lav = 8 + max_galleys = 8 + max_closets = 8 + + if num_first_class_pax > 0 and num_seat_abreast_tourist < 8: + fuselage_multiplier = 0.95 + + # Calculate the number of galleys, lavatories and closets + num_galleys = int(1 + ((num_first_class_pax + num_tourist_class_pax) / 100)) + if num_galleys > max_galleys: + num_galleys = max_galleys + num_lavas = int(1 + (num_tourist_class_pax / 60)) + int(1 + (num_first_class_pax / 100)) + if num_lavas > max_lav: + num_lavas = max_lav + num_closets = int(1 + (num_first_class_pax / 30)) + int(1 + (num_tourist_class_pax / 60)) + if num_closets > max_closets: + num_closets = max_closets + + # Calculate the passenger compartment length + + num_engines = self.options[Aircraft.Engine.NUM_ENGINES][0] + eng_flag = num_engines - 2 * int(num_engines / 2) # a center mounted engine if 1. + first_class_len = num_first_class_pax * seat_pitch_first / num_seat_abreast_first + tourist_class_len = num_tourist_class_pax * seat_pitch_tourist / num_seat_abreast_tourist + pax_compart_length = ( + first_class_len + + (num_galleys + num_lavas) * 36.0 + + tourist_class_len + + num_closets * 12.0 + ) / 12.0 + + # Correct for doors that may be in the way + num_doors = 1 + int((pax_compart_length / 50.0) * num_seat_abreast_tourist / 6.0) + + # Final passenger compartment length + pax_compart_length = (pax_compart_length + num_doors * 2.96) * fuselage_multiplier + fuselage_length = pax_compart_length + 25.0 * eng_flag + 40.0 + outputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] = pax_compart_length + outputs[Aircraft.Fuselage.LENGTH] = fuselage_length + + # Calculate the number of rows of each class of passenger (not needed) + if num_first_class_pax > 0: + num_rows_first = int(np.ceil(num_first_class_pax / num_seat_abreast_first)) + if num_tourist_class_pax > 0: + num_rows_tourist = int(np.ceil(num_tourist_class_pax / num_seat_abreast_tourist)) + + # Calculate the fuselage width of the passenger seats + width_first_class = ( + num_aisles * aisle_width_first_class + num_seat_abreast_first * 20.0 + ) / 12.0 + width_tourist_class = ( + num_aisles * aisle_width_tourist_class + num_seat_abreast_tourist * 25.0 + ) / 12.0 + width_fuselage = np.maximum(width_first_class, width_tourist_class) * 1.06 + outputs[Aircraft.Fuselage.MAX_WIDTH] = width_fuselage + outputs[Aircraft.Fuselage.MAX_HEIGHT] = width_fuselage + 0.9 + + +class BWBSimpleCabinLayout(om.ExplicitComponent): + """Given fuselage length, compute passenger compartment length for BWB.""" + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + add_aviary_option(self, Aircraft.BWB.MAX_NUM_BAYS) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, units='deg') + add_aviary_input(self, Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, units='unitless') + self.add_input( + 'Rear_spar_percent_chord', 0.7, units='unitless', desc='RSPCHD at fuselage centerline' + ) + + add_aviary_output(self, Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, units='ft') + add_aviary_output(self, Aircraft.Wing.ROOT_CHORD, units='ft') + add_aviary_output(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2') + add_aviary_output(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_output(self, Aircraft.BWB.NUM_BAYS, units='unitless') + + def setup_partials(self): + self.declare_partials( + of=[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH], + wrt=[Aircraft.Fuselage.LENGTH, 'Rear_spar_percent_chord'], + ) + self.declare_partials( + of=[Aircraft.Wing.ROOT_CHORD], + wrt=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, + 'Rear_spar_percent_chord', + ], + ) + self.declare_partials( + of=[Aircraft.Fuselage.CABIN_AREA], + wrt=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, + 'Rear_spar_percent_chord', + ], + ) + self.declare_partials( + of=[Aircraft.Fuselage.MAX_HEIGHT], + wrt=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + length = inputs[Aircraft.Fuselage.LENGTH] + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'] + max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] + height_to_width = inputs[Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] + bay_width_max = 12.0 # ft + + if length <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Fuselage.LENGTH must be positive to use simple cabin layout.') + if max_width <= 0.0: + if verbosity > Verbosity.BRIEF: + print( + 'Aircraft.Fuselage.MAX_HEIGHT & Aircraft.Fuselage.MAX_WIDTH must be positive.' + ) + + pax_compart_length = rear_spar_percent_chord * length + if pax_compart_length > 190.0: + if verbosity > Verbosity.BRIEF: + print( + 'Passenger compartiment lenght is longer than recommended maximum length. ' + 'Suggest use detailed laylout algorithm.' + ) + + sweep = inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] + tan_sweep = np.tan(sweep / 57.296) + root_chord = pax_compart_length - tan_sweep * max_width / 2.0 + area_cabin = (pax_compart_length + root_chord) * max_width / 2.0 + max_height = height_to_width * length + + # Enforce maximum number of bays + num_bays_max = self.options[Aircraft.BWB.MAX_NUM_BAYS] + num_bays = int(0.5 + max_width.real / bay_width_max.real) + if num_bays > num_bays_max and num_bays_max > 0: + num_bays = num_bays_max + outputs[Aircraft.BWB.NUM_BAYS] = smooth_int_tanh(num_bays, mu=20.0) + + outputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] = pax_compart_length + outputs[Aircraft.Wing.ROOT_CHORD] = root_chord + outputs[Aircraft.Fuselage.CABIN_AREA] = area_cabin + outputs[Aircraft.Fuselage.MAX_HEIGHT] = max_height + + def compute_partials(self, inputs, J): + length = inputs[Aircraft.Fuselage.LENGTH] + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'] + max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] + sweep = inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] + tan_sweep = np.tan(sweep / 57.296) + pax_compart_length = rear_spar_percent_chord * length + height_to_width = inputs[Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] + + J[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, Aircraft.Fuselage.LENGTH] = ( + rear_spar_percent_chord + ) + J[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, 'Rear_spar_percent_chord'] = length + + J[Aircraft.Wing.ROOT_CHORD, Aircraft.Fuselage.LENGTH] = rear_spar_percent_chord + J[Aircraft.Wing.ROOT_CHORD, 'Rear_spar_percent_chord'] = length + J[Aircraft.Wing.ROOT_CHORD, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = ( + -max_width / (np.cos(sweep / 57.296)) ** 2 / 57.296 / 2.0 + ) + J[Aircraft.Wing.ROOT_CHORD, Aircraft.Fuselage.MAX_WIDTH] = -tan_sweep / 2.0 + + J[Aircraft.Fuselage.CABIN_AREA, Aircraft.Fuselage.LENGTH] = ( + rear_spar_percent_chord * max_width + ) + J[Aircraft.Fuselage.CABIN_AREA, 'Rear_spar_percent_chord'] = length * max_width + J[Aircraft.Fuselage.CABIN_AREA, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = ( + -(max_width**2) / 4.0 / (np.cos(sweep / 57.296)) ** 2 / 57.296 + ) + J[Aircraft.Fuselage.CABIN_AREA, Aircraft.Fuselage.MAX_WIDTH] = ( + pax_compart_length - tan_sweep * max_width / 2.0 + ) + + J[Aircraft.Fuselage.MAX_HEIGHT, Aircraft.Fuselage.LENGTH] = height_to_width + J[Aircraft.Fuselage.MAX_HEIGHT, Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] = length + + +class BWBDetailedCabinLayout(om.ExplicitComponent): + """Compute BWB fuselage dimensions using cabin seat information.""" + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST) + add_aviary_option(self, Aircraft.BWB.MAX_NUM_BAYS) + + def setup(self): + add_aviary_input(self, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, units='deg') + add_aviary_input(self, Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, units='unitless') + self.add_input( + 'Rear_spar_percent_chord', 0.7, units='unitless', desc='RSPCHD at fuselage centerline' + ) + + add_aviary_output(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_output(self, Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, units='ft') + add_aviary_output(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2') + add_aviary_output(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_output(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_output(self, Aircraft.Wing.ROOT_CHORD, units='ft') + add_aviary_output(self, Aircraft.BWB.NUM_BAYS, units='unitless') + + self.declare_partials('*', '*', method='fd', form='forward') + + def compute(self, inputs, outputs): + rear_spar_percent_chord = inputs['Rear_spar_percent_chord'] + sweep = inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] + height_to_width = inputs[Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] + tan_sweep = np.tan(sweep / 57.296) + + bay_width_max = 12.0 # ft + num_bays = 0 + num_bays_loc = num_bays + num_bays_max = self.options[Aircraft.BWB.MAX_NUM_BAYS] + root_chord_min = 38.5 # ft + width_lava = 36.0 # inch + width_galley = 36.0 # inch + width_closet = 12.0 # inch + + # Establish defaults for Number of Passengers Abreast + # and Seat Pitch for First, Business and Tourist classes + + num_seat_abreast_business = self.options[ + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS + ] + if num_seat_abreast_business <= 0: + num_seat_abreast_business = 5 + num_seat_abreast_first = self.options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST] + if num_seat_abreast_first <= 0: + num_seat_abreast_first = 4 + num_seat_abreast_tourist = self.options[ + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST + ] + if num_seat_abreast_tourist <= 0: + num_seat_abreast_tourist = 6 + + seat_pitch_business = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS][0] + if seat_pitch_business <= 0: + seat_pitch_business = 39.0 # inch + seat_pitch_first = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST][0] + if seat_pitch_first <= 0: + seat_pitch_first = 61.0 # inch + seat_pitch_tourist = self.options[Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST][0] + if seat_pitch_tourist <= 0: + seat_pitch_tourist = 32.0 # inch + + # Determine unit seat areas for each type of passenger + area_seat_business = bay_width_max * seat_pitch_business / 12.0 / num_seat_abreast_business + area_seat_first = bay_width_max * seat_pitch_first / 12.0 / num_seat_abreast_first + area_seat_tourist = bay_width_max * seat_pitch_tourist / 12.0 / num_seat_abreast_tourist + + # Find the number of lavatories, galleys and closets based on the + # number of passengers for each class and the area for each + num_business_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] + num_first_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + num_tourist_class_pax = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] + num_lavas = ( + int(0.99 + num_first_class_pax / 16.0) + + int(0.99 + num_business_class_pax / 24.0) + + int(0.99 + num_tourist_class_pax / 40.0) + ) + num_galleys = int(0.99 + 0.6 * num_lavas) + num_closets = int(0.99 + 0.4 * num_lavas) + + area_lava = (bay_width_max / 2.0) * (width_lava / 12.0) + area_galley = (bay_width_max / 2.0) * (width_galley / 12.0) + area_closet = (bay_width_max / 2.0) * (width_closet / 12.0) + + # Calculate area required for passengers and services + area_seats = ( + num_tourist_class_pax * area_seat_tourist + + num_business_class_pax * area_seat_business + + num_first_class_pax * area_seat_first + ) + area_service = num_lavas * area_lava + num_galleys * area_galley + num_closets * area_closet + + # Estimate number of bays based on these areas + num_bays = int(0.5 + (area_seats + area_service) / 550.0) + if num_bays > num_bays_max and num_bays_max > 0: + num_bays = num_bays_max + + while num_bays_loc != num_bays: + num_bays_loc = num_bays + # Cabin area wasted due to slanted != side wall + area_waste = num_bays * tan_sweep * (bay_width_max / 2.0) ** 2 + + # Aisle area for horseshoe (5'), cross (2') and rear (3') aisles + # Aisles only go to center of outboard bays, hence num_bays-1 + area_aisle = 10.0 * (num_bays - 1) * bay_width_max + + # Total pressurized cabin area + area_cabin = area_seats + area_service + area_waste + area_aisle + + # Calculate cabin dimensions + root_chord = root_chord_min + max_width = ( + 2.0 * (-root_chord + np.sqrt(root_chord**2 + tan_sweep * area_cabin)) / tan_sweep + ) + pax_compart_length = root_chord + tan_sweep * max_width / 2.0 + + # Enforce maximum number of bays + num_bays = int(0.5 + max_width / bay_width_max) + if num_bays > num_bays_max and num_bays_max > 0: + num_bays = num_bays_max + + # Enforce maximum bay width + bay_width = max_width / num_bays + if bay_width > bay_width_max: + bay_width = bay_width_max + num_bays = int(0.999 + max_width / bay_width) + if num_bays > num_bays_max and num_bays_max > 0: + num_bays = num_bays_max + max_width = bay_width_max * bay_width + pax_compart_length = area_cabin / max_width + tan_sweep * max_width / 4.0 + root_chord = pax_compart_length - tan_sweep * max_width / 2.0 + # If number of bays has changed, recalculate cabin area + + length = pax_compart_length / rear_spar_percent_chord + max_height = height_to_width * length + outputs[Aircraft.BWB.NUM_BAYS] = smooth_int_tanh(num_bays, mu=20.0) + + outputs[Aircraft.Fuselage.LENGTH] = length + outputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] = pax_compart_length + outputs[Aircraft.Fuselage.CABIN_AREA] = area_cabin + outputs[Aircraft.Fuselage.MAX_WIDTH] = max_width + outputs[Aircraft.Fuselage.MAX_HEIGHT] = max_height + outputs[Aircraft.Wing.ROOT_CHORD] = root_chord + + # TODO: For the int calls, I see that those are part of a while loop that solves + # a nonlinear equation by Gauss-Siedel until it converges. The interesting part is + # that it solves int(x) = f(int(x)) instead of x=f(x). if we smooth any of the ints, + # the algorithm will probably take many more iteratiions. I wonder if it would still + # converge. One solution might be to rewrite this using an openmado solver, solve for + # a real-valued num_bays, then use a smoothed int afterwards. LOPS did something similar + # with the skin friction calculation, except there were no ints. I rewrote the equations + # in residual form and used a Newton solver on them. (Ken) diff --git a/aviary/subsystems/geometry/flops_based/nacelle.py b/aviary/subsystems/geometry/flops_based/nacelle.py index a2f0d58ba3..502e85bd04 100644 --- a/aviary/subsystems/geometry/flops_based/nacelle.py +++ b/aviary/subsystems/geometry/flops_based/nacelle.py @@ -1,8 +1,7 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft @@ -10,58 +9,52 @@ # Aircraft.Nacelle.AVG_LENGTH = 0.07 * sqrt(Aircraft.ENGINE.SCALED_SLS_THRUST) # Aircraft.Nacelle.AVG_DIAMETER = 0.04 * sqrt(Aircraft.ENGINE.SCALED_SLS_THRUST) class Nacelles(om.ExplicitComponent): - """ - Calculate nacelle wetted area and total wetted area - """ + """Calculate nacelle wetted area and total wetted area.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, - val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, - val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Nacelle.WETTED_AREA_SCALER, - val=np.zeros(num_engine_type)) - - add_aviary_output(self, Aircraft.Nacelle.TOTAL_WETTED_AREA, 0.0) - add_aviary_output(self, Aircraft.Nacelle.WETTED_AREA, - val=np.zeros(num_engine_type)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, shape=num_engine_type, units='ft') + add_aviary_input( + self, Aircraft.Nacelle.WETTED_AREA_SCALER, shape=num_engine_type, units='unitless' + ) + + add_aviary_output(self, Aircraft.Nacelle.TOTAL_WETTED_AREA, units='ft**2') + add_aviary_output(self, Aircraft.Nacelle.WETTED_AREA, shape=num_engine_type, units='ft**2') def setup_partials(self): # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) self.declare_partials( Aircraft.Nacelle.TOTAL_WETTED_AREA, [ - Aircraft.Nacelle.AVG_DIAMETER, Aircraft.Nacelle.AVG_LENGTH, + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Nacelle.AVG_LENGTH, Aircraft.Nacelle.WETTED_AREA_SCALER, - ] + ], ) self.declare_partials( Aircraft.Nacelle.WETTED_AREA, [ - Aircraft.Nacelle.AVG_DIAMETER, Aircraft.Nacelle.AVG_LENGTH, + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Nacelle.AVG_LENGTH, Aircraft.Nacelle.WETTED_AREA_SCALER, ], - rows=shape, cols=shape, val=1.0 + rows=shape, + cols=shape, + val=1.0, ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): # how many of each unique engine type are on the aircraft (array) - num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + # how many unique engine types are there (int) num_engine_type = len(num_engines) @@ -72,8 +65,7 @@ def compute( wetted_area = np.zeros(num_engine_type, dtype=avg_diam.dtype) calc_idx = np.where(num_engines >= 1) - wetted_area[calc_idx] = scaler[calc_idx] * 2.8 * \ - avg_diam[calc_idx] * avg_length[calc_idx] + wetted_area[calc_idx] = scaler[calc_idx] * 2.8 * avg_diam[calc_idx] * avg_length[calc_idx] outputs[Aircraft.Nacelle.WETTED_AREA] = wetted_area @@ -82,8 +74,7 @@ def compute( outputs[Aircraft.Nacelle.TOTAL_WETTED_AREA] = total_wetted_area def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] avg_diam = inputs[Aircraft.Nacelle.AVG_DIAMETER] avg_length = inputs[Aircraft.Nacelle.AVG_LENGTH] @@ -104,10 +95,12 @@ def compute_partials(self, inputs, J, discrete_inputs=None): deriv_area_len[calc_idx] = scaler[calc_idx] * area_to_length[calc_idx] deriv_area_diam[calc_idx] = scaler[calc_idx] * area_to_diam[calc_idx] deriv_area_scaler[calc_idx] = area_to_scaler[calc_idx] - deriv_total_len[calc_idx] = scaler[calc_idx] * \ - num_engines[calc_idx] * area_to_length[calc_idx] - deriv_total_diam[calc_idx] = scaler[calc_idx] * \ - num_engines[calc_idx] * area_to_diam[calc_idx] + deriv_total_len[calc_idx] = ( + scaler[calc_idx] * num_engines[calc_idx] * area_to_length[calc_idx] + ) + deriv_total_diam[calc_idx] = ( + scaler[calc_idx] * num_engines[calc_idx] * area_to_diam[calc_idx] + ) deriv_total_scaler[calc_idx] = num_engines[calc_idx] * area_to_scaler[calc_idx] J[Aircraft.Nacelle.WETTED_AREA, Aircraft.Nacelle.AVG_LENGTH] = deriv_area_len @@ -120,5 +113,6 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J[Aircraft.Nacelle.TOTAL_WETTED_AREA, Aircraft.Nacelle.AVG_DIAMETER] = deriv_total_diam - J[Aircraft.Nacelle.TOTAL_WETTED_AREA, - Aircraft.Nacelle.WETTED_AREA_SCALER] = deriv_total_scaler + J[Aircraft.Nacelle.TOTAL_WETTED_AREA, Aircraft.Nacelle.WETTED_AREA_SCALER] = ( + deriv_total_scaler + ) diff --git a/aviary/subsystems/geometry/flops_based/prep_geom.py b/aviary/subsystems/geometry/flops_based/prep_geom.py index 2d54dab228..9f43bf5b84 100644 --- a/aviary/subsystems/geometry/flops_based/prep_geom.py +++ b/aviary/subsystems/geometry/flops_based/prep_geom.py @@ -1,150 +1,227 @@ -''' +""" Define utilities to prepare derived values of aircraft geometry for aerodynamics analysis. TODO: blended-wing-body support TODO: multiple engine model support -''' +""" + import openmdao.api as om from numpy import pi from aviary.subsystems.geometry.flops_based.canard import Canard -from aviary.subsystems.geometry.flops_based.characteristic_lengths import \ - CharacteristicLengths -from aviary.subsystems.geometry.flops_based.fuselage import FuselagePrelim +from aviary.subsystems.geometry.flops_based.characteristic_lengths import ( + BWBWingCharacteristicLength, + OtherCharacteristicLengths, + WingCharacteristicLength, +) +from aviary.subsystems.geometry.flops_based.fuselage import ( + BWBDetailedCabinLayout, + BWBFuselagePrelim, + BWBSimpleCabinLayout, + DetailedCabinLayout, + FuselagePrelim, + SimpleCabinLayout, +) from aviary.subsystems.geometry.flops_based.nacelle import Nacelles from aviary.subsystems.geometry.flops_based.utils import ( - Names, calc_fuselage_adjustment, calc_lifting_surface_scaler, - d_calc_fuselage_adjustment, thickness_to_chord_scaler) + Names, + calc_fuselage_adjustment, + calc_lifting_surface_scaler, + d_calc_fuselage_adjustment, + thickness_to_chord_scaler, +) from aviary.subsystems.geometry.flops_based.wetted_area_total import TotalWettedArea from aviary.subsystems.geometry.flops_based.wing import WingPrelim -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft +from aviary.subsystems.geometry.flops_based.bwb_wing_detailed import ( + BWBUpdateDetailedWingDist, + BWBComputeDetailedWingDist, + BWBWingPrelim, +) +from aviary.variable_info.enums import AircraftTypes, Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Settings class PrepGeom(om.Group): - ''' - Prepare derived values of aircraft geometry for aerodynamics analysis. - ''' + """Prepare derived values of aircraft geometry for aerodynamics analysis.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fuselage.SIMPLE_LAYOUT) + add_aviary_option(self, Aircraft.Design.TYPE) + add_aviary_option(self, Aircraft.BWB.DETAILED_WING_PROVIDED) def setup(self): - aviary_options = self.options['aviary_options'] - - self.add_subsystem( - 'fuselage_prelim', FuselagePrelim(aviary_options=aviary_options), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) + is_simple_layout = self.options[Aircraft.Fuselage.SIMPLE_LAYOUT] + design_type = self.options[Aircraft.Design.TYPE] + + if design_type is AircraftTypes.BLENDED_WING_BODY: + if is_simple_layout: + self.add_subsystem( + 'fuselage_layout', + BWBSimpleCabinLayout(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'fuselage_layout', + BWBDetailedCabinLayout(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + if self.options[Aircraft.BWB.DETAILED_WING_PROVIDED]: + self.add_subsystem( + 'detailed_wing', + BWBUpdateDetailedWingDist(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'detailed_wing', + BWBComputeDetailedWingDist(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + elif design_type is AircraftTypes.TRANSPORT: + if is_simple_layout: + self.add_subsystem( + 'fuselage_layout', + SimpleCabinLayout(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'fuselage_layout', + DetailedCabinLayout(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'fuselage_prelim', + BWBFuselagePrelim(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + elif design_type is AircraftTypes.TRANSPORT: + self.add_subsystem( + 'fuselage_prelim', FuselagePrelim(), promotes_inputs=['*'], promotes_outputs=['*'] + ) - self.add_subsystem( - 'wing_prelim', WingPrelim(aviary_options=aviary_options), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'wing_prelim', BWBWingPrelim(), promotes_inputs=['*'], promotes_outputs=['*'] + ) + elif design_type is AircraftTypes.TRANSPORT: + self.add_subsystem( + 'wing_prelim', WingPrelim(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'prelim', _Prelim(aviary_options=aviary_options), + 'prelim', + _Prelim(), promotes_inputs=['*'], ) - self.add_subsystem( - 'wing', _Wing(aviary_options=aviary_options), - promotes_inputs=['aircraft*'], - promotes_outputs=['*'] - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem('wing', _BWBWing(), promotes_inputs=['*'], promotes_outputs=['*']) + else: + self.add_subsystem( + 'wing', _Wing(), promotes_inputs=['aircraft*'], promotes_outputs=['*'] + ) - self.connect(f'prelim.{Names.CROOT}', f'wing.{Names.CROOT}') - self.connect(f'prelim.{Names.CROOTB}', f'wing.{Names.CROOTB}') - self.connect(f'prelim.{Names.XDX}', f'wing.{Names.XDX}') - self.connect(f'prelim.{Names.XMULT}', f'wing.{Names.XMULT}') + if design_type is AircraftTypes.TRANSPORT: + self.connect(f'prelim.{Names.CROOT}', f'wing.{Names.CROOT}') + self.connect(f'prelim.{Names.CROOTB}', f'wing.{Names.CROOTB}') + self.connect(f'prelim.{Names.XDX}', f'wing.{Names.XDX}') + self.connect(f'prelim.{Names.XMULT}', f'wing.{Names.XMULT}') - self.add_subsystem( - 'tail', _Tail(aviary_options=aviary_options), - promotes_inputs=['aircraft*'], - promotes_outputs=['*'] - ) + self.add_subsystem('tail', _Tail(), promotes_inputs=['aircraft*'], promotes_outputs=['*']) self.connect(f'prelim.{Names.XMULTH}', f'tail.{Names.XMULTH}') self.connect(f'prelim.{Names.XMULTV}', f'tail.{Names.XMULTV}') self.add_subsystem( - 'fuselage', _Fuselage(aviary_options=aviary_options), - promotes_inputs=['aircraft*'], - promotes_outputs=['*'] + 'fus_ratios', _FuselageRatios(), promotes_inputs=['aircraft*'], promotes_outputs=['*'] ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem('fuselage', _BWBFuselage(), promotes_outputs=['*']) + elif design_type is AircraftTypes.TRANSPORT: + self.add_subsystem( + 'fuselage', _Fuselage(), promotes_inputs=['aircraft*'], promotes_outputs=['*'] + ) - self.connect(f'prelim.{Names.CROOTB}', f'fuselage.{Names.CROOTB}') - self.connect(f'prelim.{Names.CROTVT}', f'fuselage.{Names.CROTVT}') - self.connect(f'prelim.{Names.CRTHTB}', f'fuselage.{Names.CRTHTB}') + if design_type is AircraftTypes.TRANSPORT: + self.connect(f'prelim.{Names.CROOTB}', f'fuselage.{Names.CROOTB}') + self.connect(f'prelim.{Names.CROTVT}', f'fuselage.{Names.CROTVT}') + self.connect(f'prelim.{Names.CRTHTB}', f'fuselage.{Names.CRTHTB}') self.add_subsystem( - 'nacelles', Nacelles(aviary_options=aviary_options), - promotes_inputs=['aircraft*'], - promotes_outputs=['*'] + 'nacelles', Nacelles(), promotes_inputs=['aircraft*'], promotes_outputs=['*'] ) self.add_subsystem( - 'canard', Canard(aviary_options=aviary_options), - promotes_inputs=['aircraft*'], - promotes_outputs=['*'] + 'canard', Canard(), promotes_inputs=['aircraft*'], promotes_outputs=['*'] ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'wing_characteristic_lengths', + BWBWingCharacteristicLength(), + promotes_inputs=['aircraft*'], + promotes_outputs=['*'], + ) + elif design_type is AircraftTypes.TRANSPORT: + self.add_subsystem( + 'wing_characteristic_lengths', + WingCharacteristicLength(), + promotes_inputs=['aircraft*'], + promotes_outputs=['*'], + ) self.add_subsystem( - 'characteristic_lengths', - CharacteristicLengths(aviary_options=aviary_options), + 'other_characteristic_lengths', + OtherCharacteristicLengths(), promotes_inputs=['aircraft*'], - promotes_outputs=['*'] + promotes_outputs=['*'], ) - self.connect( - f'prelim.{Names.CROOT}', f'characteristic_lengths.{Names.CROOT}' - ) + self.connect(f'prelim.{Names.CROOT}', f'other_characteristic_lengths.{Names.CROOT}') self.add_subsystem( - 'total_wetted_area', TotalWettedArea(aviary_options=aviary_options), - promotes_inputs=['*'], - promotes_outputs=['*'] + 'total_wetted_area', TotalWettedArea(), promotes_inputs=['*'], promotes_outputs=['*'] ) class _Prelim(om.ExplicitComponent): - ''' - Calculate internal derived values of aircraft geometry for FLOPS-based aerodynamics analysis. - ''' + """Calculate internal derived values of aircraft geometry for FLOPS-based aerodynamics analysis.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION) def setup(self): - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, 0.0) - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, 0.0) - - add_aviary_input(self, Aircraft.HorizontalTail.AREA, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.ASPECT_RATIO, - 4.75, units="unitless") - add_aviary_input(self, Aircraft.HorizontalTail.TAPER_RATIO, - 0.352, units="unitless") - add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.0) - - add_aviary_input(self, Aircraft.VerticalTail.AREA, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.TAPER_RATIO, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.0) - - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, 0.0) + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, units='unitless') + + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, units='unitless') + + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, units='ft**2') # NOTE: FLOPS/aviary1 calculate span locally - add_aviary_input(self, Aircraft.Wing.SPAN, 0.0) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') self.add_output(Names.CROOT, 1.0, units='unitless') self.add_output(Names.CROOTB, 1.0, units='unitless') @@ -161,21 +238,18 @@ def setup(self): def setup_partials(self): fuselage_var = self.fuselage_var - self.declare_partials(Names.XDX, fuselage_var, val=1.) + self.declare_partials(Names.XDX, fuselage_var, val=1.0) self.declare_partials( - Names.XMULT, Aircraft.Wing.THICKNESS_TO_CHORD, - val=thickness_to_chord_scaler + Names.XMULT, Aircraft.Wing.THICKNESS_TO_CHORD, val=thickness_to_chord_scaler ) self.declare_partials( - Names.XMULTH, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - val=thickness_to_chord_scaler + Names.XMULTH, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=thickness_to_chord_scaler ) self.declare_partials( - Names.XMULTV, Aircraft.VerticalTail.THICKNESS_TO_CHORD, - val=thickness_to_chord_scaler + Names.XMULTV, Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=thickness_to_chord_scaler ) self.declare_partials( @@ -183,7 +257,7 @@ def setup_partials(self): [ Aircraft.HorizontalTail.AREA, Aircraft.HorizontalTail.ASPECT_RATIO, - ] + ], ) self.declare_partials( @@ -193,7 +267,7 @@ def setup_partials(self): Aircraft.HorizontalTail.ASPECT_RATIO, Aircraft.HorizontalTail.TAPER_RATIO, fuselage_var, - ] + ], ) self.declare_partials( @@ -203,7 +277,7 @@ def setup_partials(self): Aircraft.Wing.GLOVE_AND_BAT, Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO, - ] + ], ) self.declare_partials( @@ -212,7 +286,7 @@ def setup_partials(self): Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO, fuselage_var, - ] + ], ) self.declare_partials( @@ -223,7 +297,7 @@ def setup_partials(self): Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO, fuselage_var, - ] + ], ) self.declare_partials( @@ -231,7 +305,7 @@ def setup_partials(self): [ Aircraft.VerticalTail.AREA, Aircraft.VerticalTail.ASPECT_RATIO, - ] + ], ) self.declare_partials( @@ -240,12 +314,10 @@ def setup_partials(self): Aircraft.VerticalTail.AREA, Aircraft.VerticalTail.ASPECT_RATIO, Aircraft.VerticalTail.TAPER_RATIO, - ] + ], ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): w_tc = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] h_tc = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] v_tc = inputs[Aircraft.VerticalTail.THICKNESS_TO_CHORD] @@ -260,7 +332,7 @@ def compute( aspect_ratio = inputs[Aircraft.HorizontalTail.ASPECT_RATIO] area = inputs[Aircraft.HorizontalTail.AREA] - span = outputs[Names.SPANHT] = (aspect_ratio * area)**0.5 + span = outputs[Names.SPANHT] = (aspect_ratio * area) ** 0.5 CRTHTB = 0.0 @@ -269,8 +341,8 @@ def compute( CRTHTB = ( 2.0 * area / (span * (1.0 + taper_ratio)) - + ((span / 2.0 - XDX / 4.0) / (span / 2.0)) - * (1.0 - taper_ratio) + taper_ratio + + ((span / 2.0 - XDX / 4.0) / (span / 2.0)) * (1.0 - taper_ratio) + + taper_ratio ) outputs[Names.CRTHTB] = CRTHTB @@ -280,20 +352,18 @@ def compute( span = inputs[Aircraft.Wing.SPAN] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] - CROOT = outputs[Names.CROOT] = \ - ((area - glove_and_bat) * 2.0) / ((1.0 + taper_ratio) * span) + CROOT = outputs[Names.CROOT] = ((area - glove_and_bat) * 2.0) / ((1.0 + taper_ratio) * span) - CROTM = outputs[Names.CROTM] = ( - ((span / 2.0 - XDX / 2.0) / (span / 2.0)) * (1.0 - taper_ratio) - + taper_ratio - ) + CROTM = outputs[Names.CROTM] = ((span / 2.0 - XDX / 2.0) / (span / 2.0)) * ( + 1.0 - taper_ratio + ) + taper_ratio outputs[Names.CROOTB] = CROOT * CROTM area = inputs[Aircraft.VerticalTail.AREA] aspect_ratio = inputs[Aircraft.VerticalTail.ASPECT_RATIO] - span = outputs[Names.SPANVT] = (area * aspect_ratio)**0.5 + span = outputs[Names.SPANVT] = (area * aspect_ratio) ** 0.5 CROTVT = 0.0 @@ -343,7 +413,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): da = ( 2.0 / _1p_tr * (1.0 - area * dspan_darea / span) / span - + _1m_tr * 0.5 * XDX * dspan_darea / span ** 2 + + _1m_tr * 0.5 * XDX * dspan_darea / span**2 ) # dr = d(k0 * a / (a * ar)**0.5) - d(k1 / (a * ar)**0.5) + 0 @@ -410,10 +480,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): # dc = d(f * g) = df * g + f * dg f = CROOT - g = ( - (1.0 - taper_ratio) * ((span / 2.0) - (XDX / 2.0)) / (span / 2.0) - + taper_ratio - ) + g = (1.0 - taper_ratio) * ((span / 2.0) - (XDX / 2.0)) / (span / 2.0) + taper_ratio df = J[Names.CROOT, Aircraft.Wing.AREA] dg = 0.0 @@ -438,24 +505,19 @@ def compute_partials(self, inputs, J, discrete_inputs=None): area = inputs[Aircraft.VerticalTail.AREA] aspect_ratio = inputs[Aircraft.VerticalTail.ASPECT_RATIO] - span = (area * aspect_ratio)**0.5 + span = (area * aspect_ratio) ** 0.5 - J[Names.SPANVT, Aircraft.VerticalTail.AREA] = \ - 0.5 * aspect_ratio / span + J[Names.SPANVT, Aircraft.VerticalTail.AREA] = 0.5 * aspect_ratio / span - J[Names.SPANVT, Aircraft.VerticalTail.ASPECT_RATIO] = \ - 0.5 * area / span + J[Names.SPANVT, Aircraft.VerticalTail.ASPECT_RATIO] = 0.5 * area / span da = dr = dt = 0.0 if 0.0 < span: taper_ratio = inputs[Aircraft.VerticalTail.TAPER_RATIO] - _1p_tr = (1.0 + taper_ratio) - - CROTVT = 2.0 * area / (span * _1p_tr) + _1p_tr = 1.0 + taper_ratio - # da = d(f / g) = (df * g - f * dg) / g**2 f = 2.0 * area / _1p_tr g = span df = 2.0 / _1p_tr @@ -464,7 +526,7 @@ def compute_partials(self, inputs, J, discrete_inputs=None): # dr = d(k / (a * ar)**0.5) # = -0.5 * k / (a * ar)**1.5 * a - dr = -area**2.0 / (_1p_tr * span**3.0) + dr = -(area**2.0) / (_1p_tr * span**3.0) # dt = d(k / (1 + tr)) = -k / (1 + tr)**2 dt = -2.0 * area / (span * _1p_tr**2.0) @@ -475,27 +537,20 @@ def compute_partials(self, inputs, J, discrete_inputs=None): @property def fuselage_var(self): - ''' - Define the variable name associated with XDX. - ''' + """Define the variable name associated with XDX.""" value = Aircraft.Fuselage.AVG_DIAMETER - aviary_options: AviaryValues = self.options['aviary_options'] - if aviary_options.get_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION): + if self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION]: value = Aircraft.Fuselage.MAX_WIDTH return value class _Wing(om.ExplicitComponent): - """ - Calculate wing wetted area of aircraft geometry for FLOPS-based aerodynamics analysis. - """ + """Calculate wing wetted area of aircraft geometry for FLOPS-based aerodynamics analysis.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) def setup(self): self.add_input(Names.CROOT, 0.0, units='unitless') @@ -503,25 +558,26 @@ def setup(self): self.add_input(Names.XDX, 0.0, units='unitless') self.add_input(Names.XMULT, 0.0, units='unitless') - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.WETTED_AREA_SCALER, 1.0) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.WETTED_AREA_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Wing.WETTED_AREA, 0.0) + add_aviary_output(self, Aircraft.Wing.WETTED_AREA, units='ft**2') def setup_partials(self): self.declare_partials( Aircraft.Wing.WETTED_AREA, [ - Names.CROOT, Names.CROOTB, Names.XDX, Names.XMULT, - Aircraft.Wing.AREA, Aircraft.Wing.WETTED_AREA_SCALER, - ] + Names.CROOT, + Names.CROOTB, + Names.XDX, + Names.XMULT, + Aircraft.Wing.AREA, + Aircraft.Wing.WETTED_AREA_SCALER, + ], ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - num_fuselage = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + num_fuselage = self.options[Aircraft.Fuselage.NUM_FUSELAGES] area = inputs[Aircraft.Wing.AREA] CROOT = inputs[Names.CROOT] @@ -530,16 +586,12 @@ def compute( XDX = inputs[Names.XDX] XMULT = inputs[Names.XMULT] - wetted_area = ( - scaler * XMULT - * (area - (num_fuselage * XDX / 2.0) * (CROOT + CROOTB)) - ) + wetted_area = scaler * XMULT * (area - (num_fuselage * XDX / 2.0) * (CROOT + CROOTB)) outputs[Aircraft.Wing.WETTED_AREA] = wetted_area def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - num_fuselage = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) + num_fuselage = self.options[Aircraft.Fuselage.NUM_FUSELAGES] area = inputs[Aircraft.Wing.AREA] CROOT = inputs[Names.CROOT] @@ -550,20 +602,78 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J[Aircraft.Wing.WETTED_AREA, Aircraft.Wing.AREA] = scaler * XMULT - J[Aircraft.Wing.WETTED_AREA, Aircraft.Wing.WETTED_AREA_SCALER] = \ - XMULT * (area - (num_fuselage * XDX / 2.0) * (CROOT + CROOTB)) + J[Aircraft.Wing.WETTED_AREA, Aircraft.Wing.WETTED_AREA_SCALER] = XMULT * ( + area - (num_fuselage * XDX / 2.0) * (CROOT + CROOTB) + ) - J[Aircraft.Wing.WETTED_AREA, Names.CROOT] = \ - - 0.5 * scaler * XMULT * (num_fuselage * XDX) + J[Aircraft.Wing.WETTED_AREA, Names.CROOT] = -0.5 * scaler * XMULT * (num_fuselage * XDX) - J[Aircraft.Wing.WETTED_AREA, Names.CROOTB] = \ - J[Aircraft.Wing.WETTED_AREA, Names.CROOT] + J[Aircraft.Wing.WETTED_AREA, Names.CROOTB] = J[Aircraft.Wing.WETTED_AREA, Names.CROOT] - J[Aircraft.Wing.WETTED_AREA, Names.XDX] = \ + J[Aircraft.Wing.WETTED_AREA, Names.XDX] = ( -0.5 * scaler * XMULT * num_fuselage * (CROOT + CROOTB) + ) + + J[Aircraft.Wing.WETTED_AREA, Names.XMULT] = scaler * ( + area - 0.5 * (num_fuselage * XDX) * (CROOT + CROOTB) + ) - J[Aircraft.Wing.WETTED_AREA, Names.XMULT] = \ - scaler * (area - 0.5*(num_fuselage * XDX) * (CROOT + CROOTB)) + +class _BWBWing(om.ExplicitComponent): + """Calculate wing wetted area of BWB aircraft geometry for FLOPS-based aerodynamics analysis.""" + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.NUM_INTEGRATION_STATIONS) + + def setup(self): + num_stations = self.options[Aircraft.Wing.NUM_INTEGRATION_STATIONS] + + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + self.add_input('BWB_INPUT_STATION_DIST', shape=num_stations, units='unitless') + self.add_input('BWB_CHORD_PER_SEMISPAN_DIST', shape=num_stations, units='unitless') + self.add_input('BWB_THICKNESS_TO_CHORD_DIST', shape=num_stations, units='unitless') + + add_aviary_output(self, Aircraft.Wing.WETTED_AREA, units='ft**2') + + self.declare_partials('*', '*', method='cs') + + def compute(self, inputs, outputs): + input_station_dist = inputs['BWB_INPUT_STATION_DIST'] + num_stations = len(inputs['BWB_INPUT_STATION_DIST']) + + span = inputs[Aircraft.Wing.SPAN] + + ssmw = 0.0 + bwb_chord_per_semispan_dist = inputs['BWB_CHORD_PER_SEMISPAN_DIST'] + bwb_thickness_to_chord_dist = inputs['BWB_THICKNESS_TO_CHORD_DIST'] + + if bwb_chord_per_semispan_dist[0] <= 5.0: + C1 = bwb_chord_per_semispan_dist[0] * span / 2.0 + else: + C1 = bwb_chord_per_semispan_dist[0] + if input_station_dist[0] <= 1.1: + Y1 = input_station_dist[0] * span / 2.0 + else: + Y1 = input_station_dist[0] + for n in range(1, num_stations): + avg_toc = (bwb_thickness_to_chord_dist[n - 1] + bwb_thickness_to_chord_dist[n]) / 2.0 + ckt = 2.0 + 0.387 * avg_toc + if bwb_chord_per_semispan_dist[n] <= 5.0: + C2 = bwb_chord_per_semispan_dist[n] * span / 2.0 + else: + C2 = bwb_chord_per_semispan_dist[n] + if input_station_dist[n] <= 1.1: + Y2 = input_station_dist[n] * span / 2.0 + else: + Y2 = input_station_dist[n] + axp = (Y2 - Y1) * (C1 + C2) + C1 = C2 + Y1 = Y2 + ssmw = ssmw + axp * ckt + + outputs[Aircraft.Wing.WETTED_AREA] = ssmw class _Tail(om.ExplicitComponent): @@ -573,57 +683,49 @@ class _Tail(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + add_aviary_option(self, Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION) def setup(self): self.add_input(Names.XMULTH, 0.0, units='unitless') self.add_input(Names.XMULTV, 0.0, units='unitless') - add_aviary_input(self, Aircraft.HorizontalTail.AREA, 0.0) + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') - add_aviary_input( - self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0.0 - ) + add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, units='unitless') - add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA_SCALER, 1.0) + add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA_SCALER, units='unitless') - add_aviary_input(self, Aircraft.VerticalTail.AREA, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA_SCALER, 1.0) + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA_SCALER, units='unitless') - add_aviary_output(self, Aircraft.HorizontalTail.WETTED_AREA, 0.0) - add_aviary_output(self, Aircraft.VerticalTail.WETTED_AREA, 0.0) + add_aviary_output(self, Aircraft.HorizontalTail.WETTED_AREA, units='ft**2') + add_aviary_output(self, Aircraft.VerticalTail.WETTED_AREA, units='ft**2') def setup_partials(self): self.declare_partials( Aircraft.HorizontalTail.WETTED_AREA, [ - Names.XMULTH, Aircraft.HorizontalTail.AREA, - Aircraft.HorizontalTail.WETTED_AREA_SCALER - ] + Names.XMULTH, + Aircraft.HorizontalTail.AREA, + Aircraft.HorizontalTail.WETTED_AREA_SCALER, + ], ) self.declare_partials( Aircraft.VerticalTail.WETTED_AREA, - [ - Names.XMULTV, Aircraft.VerticalTail.AREA, - Aircraft.VerticalTail.WETTED_AREA_SCALER - ] + [Names.XMULTV, Aircraft.VerticalTail.AREA, Aircraft.VerticalTail.WETTED_AREA_SCALER], ) - aviary_options: AviaryValues = self.options['aviary_options'] - redux = aviary_options.get_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION) + redux = self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] if not redux: self.declare_partials( Aircraft.HorizontalTail.WETTED_AREA, - [Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] + [Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION], ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): # horizontal tail XMULTH = inputs[Names.XMULTH] area = inputs[Aircraft.HorizontalTail.AREA] @@ -631,19 +733,15 @@ def compute( wetted_area = scaler * XMULTH * area - aviary_options: AviaryValues = self.options['aviary_options'] - redux = aviary_options.get_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION) + redux = self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] if not redux: - num_fuselage_engines = \ - aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_fuselage_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] - vertical_tail_fraction = \ - inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] + vertical_tail_fraction = inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] - wetted_area *= ( - 1.0 - (0.185 + num_fuselage_engines * 0.063) - * (1.0 - vertical_tail_fraction) + wetted_area *= 1.0 - (0.185 + num_fuselage_engines * 0.063) * ( + 1.0 - vertical_tail_fraction ) outputs[Aircraft.HorizontalTail.WETTED_AREA] = wetted_area @@ -658,8 +756,7 @@ def compute( outputs[Aircraft.VerticalTail.WETTED_AREA] = wetted_area def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - redux = aviary_options.get_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION) + redux = self.options[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] # horizontal tail XMULTH = inputs[Names.XMULTH] @@ -667,28 +764,23 @@ def compute_partials(self, inputs, J, discrete_inputs=None): scaler = inputs[Aircraft.HorizontalTail.WETTED_AREA_SCALER] if not redux: - num_fuselage_engines = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_fuselage_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] - vertical_tail_fraction = \ - inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] + vertical_tail_fraction = inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] fengines = 0.185 + num_fuselage_engines * 0.063 fact = 1.0 - fengines * (1.0 - vertical_tail_fraction) - J[Aircraft.HorizontalTail.WETTED_AREA, Names.XMULTH] = \ - scaler * area * fact + J[Aircraft.HorizontalTail.WETTED_AREA, Names.XMULTH] = scaler * area * fact - J[ - Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.HorizontalTail.AREA - ] = scaler * XMULTH * fact + J[Aircraft.HorizontalTail.WETTED_AREA, Aircraft.HorizontalTail.AREA] = ( + scaler * XMULTH * fact + ) deriv = scaler * XMULTH * area * fengines J[ - Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION + Aircraft.HorizontalTail.WETTED_AREA, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION ] = deriv J[ @@ -697,13 +789,9 @@ def compute_partials(self, inputs, J, discrete_inputs=None): ] = XMULTH * area * fact else: - J[Aircraft.HorizontalTail.WETTED_AREA, Names.XMULTH] = \ - scaler * area + J[Aircraft.HorizontalTail.WETTED_AREA, Names.XMULTH] = scaler * area - J[ - Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.HorizontalTail.AREA - ] = scaler * XMULTH + J[Aircraft.HorizontalTail.WETTED_AREA, Aircraft.HorizontalTail.AREA] = scaler * XMULTH J[ Aircraft.HorizontalTail.WETTED_AREA, @@ -717,79 +805,57 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J[Aircraft.VerticalTail.WETTED_AREA, Names.XMULTV] = scaler * area - J[ - Aircraft.VerticalTail.WETTED_AREA, - Aircraft.VerticalTail.AREA - ] = scaler * XMULTV + J[Aircraft.VerticalTail.WETTED_AREA, Aircraft.VerticalTail.AREA] = scaler * XMULTV - J[ - Aircraft.VerticalTail.WETTED_AREA, - Aircraft.VerticalTail.WETTED_AREA_SCALER - ] = XMULTV * area + J[Aircraft.VerticalTail.WETTED_AREA, Aircraft.VerticalTail.WETTED_AREA_SCALER] = ( + XMULTV * area + ) + + +class _BWBFuselage(om.ExplicitComponent): + """ + Set BWB fuselage cross sectional area, and fuselage wetted area to zero + for FLOPS-based aerodynamics analysis when BWB has detailed wings. + """ + + def setup(self): + add_aviary_output(self, Aircraft.Fuselage.CROSS_SECTION, units='ft**2') + add_aviary_output(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + + def compute(self, inputs, outputs): + outputs[Aircraft.Fuselage.CROSS_SECTION] = 0.0 + outputs[Aircraft.Fuselage.WETTED_AREA] = 0.0 class _Fuselage(om.ExplicitComponent): """ - Calculate fuselage cross sectional area, fuselage diameter to wing span ratio, - fuselage length to diameter ratio, and fuselage wetted area of aircraft geometry + Calculate fuselage cross sectional area, and fuselage wetted area of aircraft geometry for FLOPS-based aerodynamics analysis. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Settings.VERBOSITY) def setup(self): self.add_input(Names.CROOTB, 0.0, units='unitless') self.add_input(Names.CROTVT, 0.0, units='unitless') self.add_input(Names.CRTHTB, 0.0, units='unitless') - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, 0.0) - add_aviary_input(self, Aircraft.Fuselage.LENGTH, 0.0) - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0) - - add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_SCALER, units='unitless') - add_aviary_input( - self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0.0 - ) - - add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.0) + add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) - - add_aviary_output(self, Aircraft.Fuselage.CROSS_SECTION, 0.0) - add_aviary_output(self, Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, 0.0) - add_aviary_output(self, Aircraft.Fuselage.LENGTH_TO_DIAMETER, 0.0) - add_aviary_output(self, Aircraft.Fuselage.WETTED_AREA, 0.0) + add_aviary_output(self, Aircraft.Fuselage.CROSS_SECTION, units='ft**2') + add_aviary_output(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') def setup_partials(self): - self.declare_partials( - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - [ - Aircraft.Wing.AREA, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Wing.GLOVE_AND_BAT, - ] - ) - - self.declare_partials( - Aircraft.Fuselage.CROSS_SECTION, - Aircraft.Fuselage.AVG_DIAMETER - ) - - self.declare_partials( - Aircraft.Fuselage.LENGTH_TO_DIAMETER, - [ - Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.AVG_DIAMETER, - ] - ) + self.declare_partials(Aircraft.Fuselage.CROSS_SECTION, Aircraft.Fuselage.AVG_DIAMETER) self.declare_partials( Aircraft.Fuselage.WETTED_AREA, @@ -804,122 +870,61 @@ def setup_partials(self): Names.CROOTB, Names.CROTVT, Names.CRTHTB, - ] + ], ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - num_fuselages = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + verbosity = self.options[Settings.VERBOSITY] + num_fuselages = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + if num_fuselages < 1: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Fuselage.NUM_FUSELAGES must be positive.') - area = inputs[Aircraft.Wing.AREA] - aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] avg_diam = inputs[Aircraft.Fuselage.AVG_DIAMETER] - glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] - - diam_to_wing_span = \ - avg_diam / (aspect_ratio * (area - glove_and_bat))**0.5 - - outputs[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN] = diam_to_wing_span - - cross_section = pi * (avg_diam / 2.0)**2.0 + if avg_diam <= 0.0: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Fuselage.AVG_DIAMETER must be positive.') + cross_section = pi * (avg_diam / 2.0) ** 2.0 outputs[Aircraft.Fuselage.CROSS_SECTION] = cross_section - length_to_diam = 100.0 # FLOPS default value - - if 0.0 < avg_diam: - length = inputs[Aircraft.Fuselage.LENGTH] - - length_to_diam = length / avg_diam - - outputs[Aircraft.Fuselage.LENGTH_TO_DIAMETER] = length_to_diam - - wetted_area = 0.0 - scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] - if (0 < num_fuselages) and (0.0 < avg_diam): CROOTB = inputs[Names.CROOTB] thickness_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] CRTHTB = inputs[Names.CRTHTB] - ht_thickness_chord = \ - inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] + scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] + ht_thickness_chord = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] - vertical_tail_fraction = \ - inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] + vertical_tail_fraction = inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] CROTVT = inputs[Names.CROTVT] - vt_thickness_chord = \ - inputs[Aircraft.VerticalTail.THICKNESS_TO_CHORD] + length = inputs[Aircraft.Fuselage.LENGTH] + vt_thickness_chord = inputs[Aircraft.VerticalTail.THICKNESS_TO_CHORD] cfa = calc_fuselage_adjustment(CROOTB, thickness_chord) cfah = calc_fuselage_adjustment(CRTHTB, ht_thickness_chord) cfav = calc_fuselage_adjustment(CROTVT, vt_thickness_chord) wetted_area = scaler * ( - pi * avg_diam ** 2.0 - * (length / avg_diam - 1.7) - 2.0 * cfa - 2.0 * cfah - * (1.0 - vertical_tail_fraction) - cfav + pi * avg_diam**2.0 * (length / avg_diam - 1.7) + - 2.0 * cfa + - 2.0 * cfah * (1.0 - vertical_tail_fraction) + - cfav ) + else: + wetted_area = 0.0 outputs[Aircraft.Fuselage.WETTED_AREA] = wetted_area def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - num_fuselages = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) + num_fuselages = self.options[Aircraft.Fuselage.NUM_FUSELAGES] - area = inputs[Aircraft.Wing.AREA] - aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] avg_diam = inputs[Aircraft.Fuselage.AVG_DIAMETER] - glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] - fact = aspect_ratio * (area - glove_and_bat) - fact2 = 1.0 / fact ** 1.5 - - J[ - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - Aircraft.Fuselage.AVG_DIAMETER - ] = 1.0 / fact ** 0.5 - - J[ - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - Aircraft.Wing.ASPECT_RATIO - ] = -0.5 * avg_diam * (area - glove_and_bat) * fact2 - - J[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, Aircraft.Wing.AREA] = \ - -0.5 * avg_diam * aspect_ratio * fact2 - - J[ - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - Aircraft.Wing.GLOVE_AND_BAT - ] = 0.5 * avg_diam * aspect_ratio * fact2 - - J[Aircraft.Fuselage.CROSS_SECTION, Aircraft.Fuselage.AVG_DIAMETER] = \ - 0.5 * pi * avg_diam - - if 0.0 < avg_diam: - length = inputs[Aircraft.Fuselage.LENGTH] - - J[ - Aircraft.Fuselage.LENGTH_TO_DIAMETER, - Aircraft.Fuselage.AVG_DIAMETER - ] = -length / avg_diam ** 2 - - J[ - Aircraft.Fuselage.LENGTH_TO_DIAMETER, Aircraft.Fuselage.LENGTH - ] = 1.0 / avg_diam - - else: - J[ - Aircraft.Fuselage.LENGTH_TO_DIAMETER, - Aircraft.Fuselage.AVG_DIAMETER - ] = J[ - Aircraft.Fuselage.LENGTH_TO_DIAMETER, Aircraft.Fuselage.LENGTH - ] = 0.0 + J[Aircraft.Fuselage.CROSS_SECTION, Aircraft.Fuselage.AVG_DIAMETER] = 0.5 * pi * avg_diam if (0 < num_fuselages) and (0.0 < avg_diam): CROOTB = inputs[Names.CROOTB] @@ -930,14 +935,12 @@ def compute_partials(self, inputs, J, discrete_inputs=None): thickness_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] - ht_thickness_chord = \ - inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] + ht_thickness_chord = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] - vt_thickness_chord = \ - inputs[Aircraft.VerticalTail.THICKNESS_TO_CHORD] + vt_thickness_chord = inputs[Aircraft.VerticalTail.THICKNESS_TO_CHORD] - vertical_tail_fraction = \ - inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] + length = inputs[Aircraft.Fuselage.LENGTH] + vertical_tail_fraction = inputs[Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] cfa = calc_fuselage_adjustment(CROOTB, thickness_chord) cfah = calc_fuselage_adjustment(CRTHTB, ht_thickness_chord) @@ -947,73 +950,144 @@ def compute_partials(self, inputs, J, discrete_inputs=None): dcfah = d_calc_fuselage_adjustment(CRTHTB, ht_thickness_chord) dcfav = d_calc_fuselage_adjustment(CROTVT, vt_thickness_chord) - J[ - Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.AVG_DIAMETER - ] = scaler * pi * (length - 3.4 * avg_diam) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.AVG_DIAMETER] = ( + scaler * pi * (length - 3.4 * avg_diam) + ) - J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.LENGTH] = \ - scaler * pi * avg_diam + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.LENGTH] = scaler * pi * avg_diam - J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.Fuselage.WETTED_AREA_SCALER - ] = ( - pi * avg_diam ** 2.0 - * (length / avg_diam - 1.7) - 2.0 * cfa - 2.0 * cfah - * (1.0 - vertical_tail_fraction) - cfav + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.WETTED_AREA_SCALER] = ( + pi * avg_diam**2.0 * (length / avg_diam - 1.7) + - 2.0 * cfa + - 2.0 * cfah * (1.0 - vertical_tail_fraction) + - cfav ) - J[Aircraft.Fuselage.WETTED_AREA, Names.CROOTB] = \ - scaler * -2.0 * dcfa[0] + J[Aircraft.Fuselage.WETTED_AREA, Names.CROOTB] = scaler * -2.0 * dcfa[0] - J[Aircraft.Fuselage.WETTED_AREA, Names.CRTHTB] = \ + J[Aircraft.Fuselage.WETTED_AREA, Names.CRTHTB] = ( scaler * -2.0 * dcfah[0] * (1.0 - vertical_tail_fraction) + ) - J[Aircraft.Fuselage.WETTED_AREA, Names.CROTVT] = \ - scaler * -dcfav[0] - - J[ - Aircraft.Fuselage.WETTED_AREA, Aircraft.Wing.THICKNESS_TO_CHORD - ] = scaler * -2.0 * dcfa[1] + J[Aircraft.Fuselage.WETTED_AREA, Names.CROTVT] = scaler * -dcfav[0] - J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD - ] = scaler * -2.0 * dcfah[1] * (1.0 - vertical_tail_fraction) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Wing.THICKNESS_TO_CHORD] = ( + scaler * -2.0 * dcfa[1] + ) - J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.VerticalTail.THICKNESS_TO_CHORD - ] = scaler * -dcfav[1] + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = ( + scaler * -2.0 * dcfah[1] * (1.0 - vertical_tail_fraction) + ) - J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION - ] = scaler * 2.0 * cfah + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.VerticalTail.THICKNESS_TO_CHORD] = ( + scaler * -dcfav[1] + ) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] = ( + scaler * 2.0 * cfah + ) else: - J[ - Aircraft.Fuselage.WETTED_AREA, Names.CROOTB - ] = J[ + J[Aircraft.Fuselage.WETTED_AREA, Names.CROOTB] = J[ Aircraft.Fuselage.WETTED_AREA, Names.CRTHTB - ] = J[ - Aircraft.Fuselage.WETTED_AREA, Names.CROTVT - ] = J[ + ] = J[Aircraft.Fuselage.WETTED_AREA, Names.CROTVT] = J[ Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.AVG_DIAMETER - ] = J[ - Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.LENGTH - ] = J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.Fuselage.WETTED_AREA_SCALER - ] = J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD - ] = J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION - ] = J[ - Aircraft.Fuselage.WETTED_AREA, - Aircraft.VerticalTail.THICKNESS_TO_CHORD - ] = J[ + ] = J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.LENGTH] = J[ + Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.WETTED_AREA_SCALER + ] = J[Aircraft.Fuselage.WETTED_AREA, Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = J[ + Aircraft.Fuselage.WETTED_AREA, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION + ] = J[Aircraft.Fuselage.WETTED_AREA, Aircraft.VerticalTail.THICKNESS_TO_CHORD] = J[ Aircraft.Fuselage.WETTED_AREA, Aircraft.Wing.THICKNESS_TO_CHORD ] = 0.0 + + +class _FuselageRatios(om.ExplicitComponent): + """ + Calculate fuselage diameter to wing span ratio and fuselage length to diameter ratio + of aircraft geometry for FLOPS-based aerodynamics analysis. + """ + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, units='ft**2') + + add_aviary_output(self, Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, units='unitless') + add_aviary_output(self, Aircraft.Fuselage.LENGTH_TO_DIAMETER, units='unitless') + + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, + [ + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.GLOVE_AND_BAT, + ], + ) + + self.declare_partials( + Aircraft.Fuselage.LENGTH_TO_DIAMETER, + [ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.AVG_DIAMETER, + ], + ) + + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + area = inputs[Aircraft.Wing.AREA] + aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] + avg_diam = inputs[Aircraft.Fuselage.AVG_DIAMETER] + glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] + + diam_to_wing_span = avg_diam / (aspect_ratio * (area - glove_and_bat)) ** 0.5 + + outputs[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN] = diam_to_wing_span + + if 0.0 < avg_diam: + length = inputs[Aircraft.Fuselage.LENGTH] + + length_to_diam = length / avg_diam + else: + length_to_diam = 100.0 # FLOPS default value + + outputs[Aircraft.Fuselage.LENGTH_TO_DIAMETER] = length_to_diam + + def compute_partials(self, inputs, J, discrete_inputs=None): + area = inputs[Aircraft.Wing.AREA] + aspect_ratio = inputs[Aircraft.Wing.ASPECT_RATIO] + avg_diam = inputs[Aircraft.Fuselage.AVG_DIAMETER] + glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] + + fact = aspect_ratio * (area - glove_and_bat) + fact2 = 1.0 / fact**1.5 + + J[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, Aircraft.Fuselage.AVG_DIAMETER] = 1.0 / fact**0.5 + + J[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, Aircraft.Wing.ASPECT_RATIO] = ( + -0.5 * avg_diam * (area - glove_and_bat) * fact2 + ) + + J[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, Aircraft.Wing.AREA] = ( + -0.5 * avg_diam * aspect_ratio * fact2 + ) + + J[Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, Aircraft.Wing.GLOVE_AND_BAT] = ( + 0.5 * avg_diam * aspect_ratio * fact2 + ) + + if 0.0 < avg_diam: + length = inputs[Aircraft.Fuselage.LENGTH] + + J[Aircraft.Fuselage.LENGTH_TO_DIAMETER, Aircraft.Fuselage.AVG_DIAMETER] = ( + -length / avg_diam**2 + ) + + J[Aircraft.Fuselage.LENGTH_TO_DIAMETER, Aircraft.Fuselage.LENGTH] = 1.0 / avg_diam + + else: + J[Aircraft.Fuselage.LENGTH_TO_DIAMETER, Aircraft.Fuselage.AVG_DIAMETER] = J[ + Aircraft.Fuselage.LENGTH_TO_DIAMETER, Aircraft.Fuselage.LENGTH + ] = 0.0 diff --git a/aviary/subsystems/geometry/flops_based/test/test_bwb_wing_detailed.py b/aviary/subsystems/geometry/flops_based/test/test_bwb_wing_detailed.py new file mode 100644 index 0000000000..8c8dfa3e79 --- /dev/null +++ b/aviary/subsystems/geometry/flops_based/test/test_bwb_wing_detailed.py @@ -0,0 +1,283 @@ +import unittest +import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.geometry.flops_based.bwb_wing_detailed import ( + BWBComputeDetailedWingDist, + BWBUpdateDetailedWingDist, + BWBWingPrelim, +) +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Settings + + +class BWBUpdateDetailedWingDistTest(unittest.TestCase): + """ + For BWB, test the updated detailed wing information when detailed wing information is given. + """ + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + options = self.aviary_options = AviaryValues() + options.set_val(Settings.VERBOSITY, 1, units='unitless') + options.set_val( + Aircraft.Wing.INPUT_STATION_DIST, + [0.0, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.6499, 0.7, 0.75, 0.8, 0.85, 0.8999, 0.95, 1], + units='unitless', + ) + prob.model.add_subsystem( + 'dist', BWBUpdateDetailedWingDist(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + setup_model_options(self.prob, options) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val( + Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, + val=[ + -1.0, + 58.03, + 0.4491, + 0.3884, + 0.3317, + 0.2886, + 0.2537, + 0.2269, + 0.2121, + 0.1983, + 0.1843, + 0.1704, + 0.1565, + 0.1426, + 0.1287, + ], + ) + prob.set_val( + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + val=[ + -1.0, + 0.15, + 0.1132, + 0.0928, + 0.0822, + 0.0764, + 0.0742, + 0.0746, + 0.0758, + 0.0758, + 0.0756, + 0.0756, + 0.0758, + 0.076, + 0.076, + ], + ) + prob.set_val( + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + val=[0.0, 0, 0, 0, 0, 0, 0, 0, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9], + ) + prob.set_val(Aircraft.Fuselage.MAX_WIDTH, val=64.58) + prob.set_val(Aircraft.Wing.SPAN, val=238.08) + prob.set_val(Aircraft.Fuselage.LENGTH, val=137.5) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, val=0.11) + prob.set_val(Aircraft.Wing.ROOT_CHORD, 7.710195) + prob.run_model() + + out0 = prob.get_val('BWB_INPUT_STATION_DIST') + exp0 = [ + 0.0, + 32.29, + 0.56275201612903225, + 0.59918934811827951, + 0.63562668010752688, + 0.67206401209677424, + 0.7085013440860215, + 0.74486580141129033, + 0.78137600806451613, + 0.81781334005376349, + 0.85425067204301075, + 0.89068800403225801, + 0.92705246135752695, + 0.96356266801075263, + 1.0, + ] + assert_near_equal(out0, exp0, tolerance=1e-10) + + out1 = prob.get_val('BWB_CHORD_PER_SEMISPAN_DIST') + exp1 = [ + 137.5, + 11.0145643, + 0.327280116, + 0.283045195, + 0.241725260, + 0.210316280, + 0.184883023, + 0.165352613, + 0.154567162, + 0.144510459, + 0.134308006, + 0.124178427, + 0.114048849, + 0.103919271, + 0.0937896925, + ] + assert_near_equal(out1, exp1, tolerance=1e-9) + + out2 = prob.get_val('BWB_THICKNESS_TO_CHORD_DIST') + exp2 = [ + 0.11, + 0.11, + 0.1132, + 0.0928, + 0.0822, + 0.0764, + 0.0742, + 0.0746, + 0.0758, + 0.0758, + 0.0756, + 0.0756, + 0.0758, + 0.076, + 0.076, + ] + assert_near_equal(out2, exp2, tolerance=1e-10) + + out3 = prob.get_val('BWB_LOAD_PATH_SWEEP_DIST') + exp3 = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9] + assert_near_equal(out3, exp3, tolerance=1e-10) + + # partial_data = self.prob.check_partials(out_stream=None, method='cs') + # assert_check_partials(partial_data, atol=1e-9, rtol=1e-8) + + +@use_tempdirs +class BWBComputeDetailedWingDistTest(unittest.TestCase): + """ + For BWB, test the updated detailed wing information when detailed wing information is not given. + """ + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + self.aviary_options.set_val( + Aircraft.Wing.INPUT_STATION_DIST, + [0.0, 0.5, 1.0], + units='unitless', + ) + prob.model.add_subsystem( + 'dist', BWBComputeDetailedWingDist(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + setup_model_options(self.prob, self.aviary_options) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Fuselage.MAX_WIDTH, val=64.58) + prob.set_val(Aircraft.Wing.SPAN, val=238.08) + prob.set_val(Aircraft.Fuselage.LENGTH, val=137.5) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, val=0.11) + prob.set_val(Aircraft.Wing.ROOT_CHORD, 7.710195) + prob.set_val(Aircraft.Wing.SWEEP, 35.7, units='deg') + prob.run_model() + + out0 = prob.get_val('BWB_INPUT_STATION_DIST') + exp0 = [0.0, 32.29, 1.0] + assert_near_equal(out0, exp0, tolerance=1e-10) + + out1 = prob.get_val('BWB_CHORD_PER_SEMISPAN_DIST') + exp1 = [137.5, 11.01456429, 14.2848] + assert_near_equal(out1, exp1, tolerance=1e-10) + + out2 = prob.get_val('BWB_THICKNESS_TO_CHORD_DIST') + exp2 = [0.11, 0.11, 0.11] + assert_near_equal(out2, exp2, tolerance=1e-10) + + out3 = prob.get_val('BWB_LOAD_PATH_SWEEP_DIST') + exp3 = [0.0, 36.40586234, 36.40586234] + assert_near_equal(out3, exp3, tolerance=1e-10) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) + + +@use_tempdirs +class BWBWingPrelimTest(unittest.TestCase): + """ + For BWB with given detailed wing information, test the computation of wing parameters. + """ + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + self.aviary_options.set_val(Aircraft.Wing.NUM_INTEGRATION_STATIONS, 15, units='unitless') + prob.model.add_subsystem( + 'dist', BWBWingPrelim(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + setup_model_options(self.prob, self.aviary_options) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Fuselage.MAX_WIDTH, val=64.58) + prob.set_val(Aircraft.Wing.GLOVE_AND_BAT, val=121.05) + prob.set_val(Aircraft.Wing.SPAN, val=238.08) + prob.set_val( + 'BWB_INPUT_STATION_DIST', + [ + 0.0, + 32.29, + 0.56275201612903225, + 0.59918934811827951, + 0.63562668010752688, + 0.67206401209677424, + 0.7085013440860215, + 0.74486580141129033, + 0.78137600806451613, + 0.81781334005376349, + 0.85425067204301075, + 0.89068800403225801, + 0.92705246135752695, + 0.96356266801075263, + 1.0, + ], + units='unitless', + ) + prob.set_val( + 'BWB_CHORD_PER_SEMISPAN_DIST', + val=[ + 137.5, + 11.014564549160855, + 0.32728011592741935, + 0.28304519489247315, + 0.24172526041666667, + 0.21031628024193549, + 0.18488302251344085, + 0.16535261256720429, + 0.1545671622983871, + 0.14451045866935486, + 0.13430800571236559, + 0.12417842741935484, + 0.11404884912634408, + 0.10391927083333334, + 0.093789692540322586, + ], + ) + prob.run_model() + + assert_near_equal(prob.get_val(Aircraft.Wing.AREA), 8668.64638424, tolerance=1e-10) + assert_near_equal( + prob.get_val(Aircraft.Wing.ASPECT_RATIO), 6.6313480248646242, tolerance=1e-10 + ) + assert_near_equal( + prob.get_val(Aircraft.Wing.LOAD_FRACTION), 0.531071664997850196, tolerance=1e-10 + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/geometry/flops_based/test/test_characteristic_lengths.py b/aviary/subsystems/geometry/flops_based/test/test_characteristic_lengths.py index f4fe31abe2..3a44732be9 100644 --- a/aviary/subsystems/geometry/flops_based/test/test_characteristic_lengths.py +++ b/aviary/subsystems/geometry/flops_based/test/test_characteristic_lengths.py @@ -3,15 +3,20 @@ import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs -from aviary.subsystems.geometry.flops_based.characteristic_lengths import CharacteristicLengths +from aviary.subsystems.geometry.flops_based.characteristic_lengths import ( + BWBWingCharacteristicLength, + WingCharacteristicLength, + OtherCharacteristicLengths, +) from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_tests import get_flops_inputs from aviary.variable_info.variables import Aircraft class CharacteristicLengthsTest(unittest.TestCase): - """Test characteristic length and fineness ratio calculations""" + """Test characteristic length and fineness ratio calculations.""" def setUp(self): self.prob = om.Problem() @@ -20,15 +25,30 @@ def test_case_multiengine(self): # test with multiple engine types prob = self.prob - aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 2, 3])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 7) + aviary_inputs = get_flops_inputs('LargeSingleAisle1FLOPS') + + aviary_options_wing = { + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION: aviary_inputs.get_val( + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION + ), + } + + prob.model.add_subsystem( + 'wing_char_length', + WingCharacteristicLength(**aviary_options_wing), + promotes_outputs=['*'], + promotes_inputs=['*'], + ) + + aviary_options_others = { + Aircraft.Engine.NUM_ENGINES: np.array([2, 2, 3]), + } prob.model.add_subsystem( - 'char_lengths', - CharacteristicLengths(aviary_options=aviary_options), + 'other_char_lengths', + OtherCharacteristicLengths(**aviary_options_others), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) @@ -49,10 +69,10 @@ def test_case_multiengine(self): (Aircraft.Wing.ASPECT_RATIO, 'unitless'), (Aircraft.Wing.GLOVE_AND_BAT, 'ft**2'), (Aircraft.Wing.TAPER_RATIO, 'unitless'), - (Aircraft.Wing.THICKNESS_TO_CHORD, 'unitless') + (Aircraft.Wing.THICKNESS_TO_CHORD, 'unitless'), ] for var, units in input_list: - prob.set_val(var, aviary_options.get_val(var, units)) + prob.set_val(var, aviary_inputs.get_val(var, units)) # this is another component's output prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, val=12.75) @@ -65,7 +85,7 @@ def test_case_multiengine(self): length = prob.get_val(Aircraft.Nacelle.CHARACTERISTIC_LENGTH) fineness = prob.get_val(Aircraft.Nacelle.FINENESS) - expected_length = np.array([8.4, 5.75, 10.]) + expected_length = np.array([8.4, 5.75, 10.0]) expected_fineness = np.array([1.4, 1.352941176470, 1.041666666667]) assert_near_equal(length, expected_length, tolerance=1e-10) @@ -73,15 +93,37 @@ def test_case_multiengine(self): # getting nan for undefined partials? # don't see nan anymore. - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +@use_tempdirs +class BWBWingCharacteristicLengthsTest(unittest.TestCase): + """Test characteristic length and fineness ratio calculations for BWB.""" + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + prob.model.add_subsystem( + 'cl', BWBWingCharacteristicLength(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Wing.AREA, val=8668.64638424) + prob.set_val(Aircraft.Wing.SPAN, val=238.08) + prob.run_model() + + out1 = prob.get_val(Aircraft.Wing.CHARACTERISTIC_LENGTH) + exp1 = 36.410645095113139 + assert_near_equal(out1, exp1, tolerance=1e-9) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +if __name__ == '__main__': unittest.main() - # test = CharacteristicLengthsTest() - # test.setUp() - # test.test_case_multiengine() diff --git a/aviary/subsystems/geometry/flops_based/test/test_fuselage.py b/aviary/subsystems/geometry/flops_based/test/test_fuselage.py new file mode 100644 index 0000000000..3bbebd8aa0 --- /dev/null +++ b/aviary/subsystems/geometry/flops_based/test/test_fuselage.py @@ -0,0 +1,204 @@ +import unittest +import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.geometry.flops_based.fuselage import ( + BWBDetailedCabinLayout, + BWBSimpleCabinLayout, + DetailedCabinLayout, + SimpleCabinLayout, + BWBFuselagePrelim, +) +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Settings + + +class SimpleCabinLayoutTest(unittest.TestCase): + """Test simple cabin layout computation.""" + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + prob.model.add_subsystem( + 'layout', SimpleCabinLayout(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Fuselage.LENGTH, val=125.0, units='ft') + prob.run_model() + + pax_compart_length = prob.get_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + assert_near_equal(pax_compart_length, 86.99047784, tolerance=1e-9) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) + + +class DetailedCabinLayoutTest(unittest.TestCase): + """Test simple cabin layout computation.""" + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + options = self.aviary_options = AviaryValues() + options.set_val(Settings.VERBOSITY, 1, units='unitless') + + options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, 158, units='unitless') + # options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST, units='unitless') + # options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, units='unitless') + # options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, units='unitless') + # options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, [2], units='unitless') + + prob.model.add_subsystem( + 'layout', DetailedCabinLayout(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + setup_model_options(self.prob, options) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Fuselage.LENGTH, val=125.0, units='ft') + prob.run_model() + + pax_compart_length = prob.get_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + assert_near_equal(pax_compart_length, 107.53947222, tolerance=1e-9) + fuselage_length = prob.get_val(Aircraft.Fuselage.LENGTH) + assert_near_equal(fuselage_length, 147.53947222, tolerance=1e-9) + + fuselage_width = prob.get_val(Aircraft.Fuselage.MAX_WIDTH) + assert_near_equal(fuselage_width, 14.84, tolerance=1e-9) + + fuselage_height = prob.get_val(Aircraft.Fuselage.MAX_HEIGHT) + assert_near_equal(fuselage_height, 15.74, tolerance=1e-9) + + +class BWBSimpleCabinLayoutTest(unittest.TestCase): + """Test simple cabin layout computation.""" + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + prob.model.add_subsystem( + 'layout', BWBSimpleCabinLayout(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Fuselage.LENGTH, val=137.5, units='ft') + prob.set_val(Aircraft.Fuselage.MAX_WIDTH, val=64.58, units='ft') + prob.set_val(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, val=45.0, units='deg') + prob.set_val(Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, val=0.11, units='unitless') + prob.run_model() + + num_bays = prob.get_val(Aircraft.BWB.NUM_BAYS) + assert_near_equal(num_bays, [5], tolerance=1e-9) + pax_compart_length = prob.get_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + assert_near_equal(pax_compart_length, 96.25, tolerance=1e-9) + root_chord = prob.get_val(Aircraft.Wing.ROOT_CHORD) + assert_near_equal(root_chord, 63.96019518, tolerance=1e-9) + area_cabin = prob.get_val(Aircraft.Fuselage.CABIN_AREA) + assert_near_equal(area_cabin, 5173.1872025, tolerance=1e-9) + fuselage_height = prob.get_val(Aircraft.Fuselage.MAX_HEIGHT) + assert_near_equal(fuselage_height, 15.125, tolerance=1e-9) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) + + +@use_tempdirs +class BWBDetailedCabinLayoutTest(unittest.TestCase): + """Test simple cabin layout computation.""" + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + options = self.aviary_options = AviaryValues() + options.set_val(Settings.VERBOSITY, 1, units='unitless') + + options.set_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, 100, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 28, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, 340, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS, 4, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST, 4, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS, 39.0, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 61.0, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 32.0, units='inch') + options.set_val(Aircraft.BWB.MAX_NUM_BAYS, 0, units='unitless') + + prob.model.add_subsystem( + 'layout', BWBDetailedCabinLayout(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + setup_model_options(self.prob, options) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, val=45.0, units='deg') + prob.set_val(Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, val=0.11, units='unitless') + prob.set_val('Rear_spar_percent_chord', val=0.7, units='unitless') + prob.run_model() + + num_bays = prob.get_val(Aircraft.BWB.NUM_BAYS) + assert_near_equal(num_bays, [7], tolerance=1e-9) + + fuselage_length = prob.get_val(Aircraft.Fuselage.LENGTH) + assert_near_equal(fuselage_length, 112.30019369, tolerance=1e-9) + + pax_compart_length = prob.get_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + assert_near_equal(pax_compart_length, 78.61013558, tolerance=1e-9) + + fuselage_width = prob.get_val(Aircraft.Fuselage.MAX_WIDTH) + assert_near_equal(fuselage_width, 80.22075607, tolerance=1e-9) + + fuselage_height = prob.get_val(Aircraft.Fuselage.MAX_HEIGHT) + assert_near_equal(fuselage_height, 12.35302131, tolerance=1e-9) + + cabin_area = prob.get_val(Aircraft.Fuselage.CABIN_AREA) + assert_near_equal(cabin_area, 4697.33181006, tolerance=1e-9) + + root_chord = prob.get_val(Aircraft.Wing.ROOT_CHORD) + assert_near_equal(root_chord, 38.5, tolerance=1e-9) + + +@use_tempdirs +class BWBFuselagePrelimTest(unittest.TestCase): + """Test simple cabin layout computation.""" + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + prob.model.add_subsystem( + 'layout', BWBFuselagePrelim(), promotes_outputs=['*'], promotes_inputs=['*'] + ) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Fuselage.LENGTH, val=125.0, units='ft') + + prob.set_val(Aircraft.Fuselage.MAX_WIDTH, val=64.58, units='ft') + prob.set_val(Aircraft.Fuselage.MAX_HEIGHT, val=17, units='ft') + prob.set_val(Aircraft.Wing.ROOT_CHORD, val=7.71, units='ft') + prob.set_val('Rear_spar_percent_chord', val=0.7, units='unitless') + prob.run_model() + + avg_diameter = prob.get_val(Aircraft.Fuselage.AVG_DIAMETER) + assert_near_equal(avg_diameter, 40.79, tolerance=1e-9) + planform_area = prob.get_val(Aircraft.Fuselage.PLANFORM_AREA) + assert_near_equal(planform_area, 4391.90128571, tolerance=1e-9) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/geometry/flops_based/test/test_nacelle.py b/aviary/subsystems/geometry/flops_based/test/test_nacelle.py index 61f2ebbafe..137c5301c6 100644 --- a/aviary/subsystems/geometry/flops_based/test/test_nacelle.py +++ b/aviary/subsystems/geometry/flops_based/test/test_nacelle.py @@ -3,17 +3,16 @@ import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs from aviary.subsystems.geometry.flops_based.nacelle import Nacelles from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import get_flops_inputs from aviary.variable_info.variables import Aircraft +@use_tempdirs class NacelleTest(unittest.TestCase): - """ - Test nacelle wetted area computation. - """ + """Test nacelle wetted area computation.""" def setUp(self): self.prob = om.Problem() @@ -22,15 +21,12 @@ def test_case_multiengine(self): # test with multiple engine types prob = self.prob - aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 2, 3])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 7) + options = { + Aircraft.Engine.NUM_ENGINES: np.array([2, 2, 3]), + } prob.model.add_subsystem( - 'nacelles', - Nacelles(aviary_options=aviary_options), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'nacelles', Nacelles(**options), promotes_outputs=['*'], promotes_inputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) @@ -50,15 +46,12 @@ def test_case_multiengine(self): assert_near_equal(wetted_area, expected_wetted_area, tolerance=1e-10) assert_near_equal(total_wetted_area, expected_total_wetted_area, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": - # unittest.main() - test = NacelleTest() - test.setUp() - test.test_case_multiengine() +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/geometry/flops_based/test/test_prep_geom.py b/aviary/subsystems/geometry/flops_based/test/test_prep_geom.py index 58a2391036..0d57bb4736 100644 --- a/aviary/subsystems/geometry/flops_based/test/test_prep_geom.py +++ b/aviary/subsystems/geometry/flops_based/test/test_prep_geom.py @@ -1,163 +1,188 @@ import unittest +import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import assert_check_partials +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs from parameterized import parameterized from aviary.subsystems.geometry.flops_based.canard import Canard -from aviary.subsystems.geometry.flops_based.characteristic_lengths import \ - CharacteristicLengths +from aviary.subsystems.geometry.flops_based.characteristic_lengths import ( + WingCharacteristicLength, + OtherCharacteristicLengths, +) from aviary.subsystems.geometry.flops_based.fuselage import FuselagePrelim from aviary.subsystems.geometry.flops_based.nacelle import Nacelles -from aviary.subsystems.geometry.flops_based.prep_geom import (PrepGeom, - _Fuselage, - _Prelim, _Tail, - _Wing) +from aviary.subsystems.geometry.flops_based.prep_geom import ( + _BWBWing, + PrepGeom, + _Fuselage, + _FuselageRatios, + _Prelim, + _Tail, + _Wing, +) from aviary.subsystems.geometry.flops_based.utils import Names from aviary.subsystems.geometry.flops_based.wing import WingPrelim from aviary.utils.aviary_values import AviaryValues from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (do_validation_test, - flops_validation_test, - get_flops_case_names, - get_flops_data, - get_flops_inputs, - get_flops_outputs, - print_case) -from aviary.variable_info.functions import override_aviary_vars +from aviary.validation_cases.validation_tests import ( + do_validation_test, + flops_validation_test, + get_flops_case_names, + get_flops_data, + get_flops_inputs, + get_flops_outputs, + print_case, +) +from aviary.variable_info.functions import override_aviary_vars, setup_model_options +from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft unit_data_sets = get_flops_case_names( - only=['LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSdw', 'LargeSingleAisle2FLOPSalt', 'LargeSingleAisle1FLOPS']) + only=[ + 'LargeSingleAisle2FLOPS', + 'LargeSingleAisle2FLOPSdw', + 'LargeSingleAisle2FLOPSalt', + 'LargeSingleAisle1FLOPS', + ] +) wetted_area_overide = get_flops_case_names( - only=['N3CC', 'LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSdw', 'LargeSingleAisle2FLOPSalt', 'LargeSingleAisle1FLOPS']) + only=[ + 'AdvancedSingleAisle', + 'LargeSingleAisle2FLOPS', + 'LargeSingleAisle2FLOPSdw', + 'LargeSingleAisle2FLOPSalt', + 'LargeSingleAisle1FLOPS', + ] +) # TODO: We have no integration tests for canard, so canard-related names are commented # out. +@use_tempdirs class PrepGeomTest(unittest.TestCase): - """ - Test computation of derived values of aircraft geometry for aerodynamics analysis - """ + """Test computation of derived values of aircraft geometry for aerodynamics analysis.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - class PreMission(om.Group): - def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) def setup(self): - aviary_options = self.options['aviary_options'] - - self.add_subsystem('prep_geom', PrepGeom(aviary_options=aviary_options), - promotes=['*']) + self.add_subsystem('prep_geom', PrepGeom(), promotes=['*']) def configure(self): aviary_options = self.options['aviary_options'] override_aviary_vars(self, aviary_options) - options = get_flops_data(case_name, preprocess=True, - keys=[ - Aircraft.Fuselage.NUM_FUSELAGES, - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, - Aircraft.VerticalTail.NUM_TAILS, - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, - Aircraft.Engine.NUM_ENGINES, - Aircraft.Propulsion.TOTAL_NUM_ENGINES, - ]) - - prob = self.prob - - prob.model.add_subsystem( - 'premission', PreMission(aviary_options=options), promotes=['*'] - ) - - prob.setup(check=False, force_alloc_complex=True) + keys = [ + Aircraft.Fuselage.NUM_FUSELAGES, + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, + Aircraft.VerticalTail.NUM_TAILS, + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + Aircraft.Engine.NUM_ENGINES, + Aircraft.Propulsion.TOTAL_NUM_ENGINES, + ] - output_keys = [Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Fuselage.CHARACTERISTIC_LENGTH, - Aircraft.Fuselage.CROSS_SECTION, - Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - Aircraft.Fuselage.FINENESS, - Aircraft.Fuselage.LENGTH_TO_DIAMETER, + options = get_flops_data(case_name, preprocess=True, keys=keys) + model_options = {} + for key in keys: + model_options[key] = options.get_item(key)[0] - # Aircraft.Canard.CHARACTERISTIC_LENGTH, - # Aircraft.Canard.FINENESS, + prob = self.prob - Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, - Aircraft.HorizontalTail.FINENESS, + prob.model.add_subsystem('premission', PreMission(aviary_options=options), promotes=['*']) - Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - Aircraft.Nacelle.FINENESS, + prob.model_options['*'] = model_options - Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, - Aircraft.VerticalTail.FINENESS, + prob.setup(check=False, force_alloc_complex=True) - Aircraft.Wing.CHARACTERISTIC_LENGTH, - Aircraft.Wing.FINENESS] + output_keys = [ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.CHARACTERISTIC_LENGTH, + Aircraft.Fuselage.CROSS_SECTION, + Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, + Aircraft.Fuselage.FINENESS, + Aircraft.Fuselage.LENGTH_TO_DIAMETER, + # Aircraft.Canard.CHARACTERISTIC_LENGTH, + # Aircraft.Canard.FINENESS, + Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, + Aircraft.HorizontalTail.FINENESS, + Aircraft.Nacelle.CHARACTERISTIC_LENGTH, + Aircraft.Nacelle.FINENESS, + Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, + Aircraft.VerticalTail.FINENESS, + Aircraft.Wing.CHARACTERISTIC_LENGTH, + Aircraft.Wing.FINENESS, + ] if case_name not in wetted_area_overide: - output_keys.extend([Aircraft.Canard.WETTED_AREA, - Aircraft.Design.TOTAL_WETTED_AREA, - Aircraft.Fuselage.WETTED_AREA, - Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.Nacelle.TOTAL_WETTED_AREA, - Aircraft.Nacelle.WETTED_AREA, - Aircraft.VerticalTail.WETTED_AREA, - Aircraft.Wing.WETTED_AREA]) + output_keys.extend( + [ + Aircraft.Canard.WETTED_AREA, + Aircraft.Design.TOTAL_WETTED_AREA, + Aircraft.Fuselage.WETTED_AREA, + Aircraft.HorizontalTail.WETTED_AREA, + Aircraft.Nacelle.TOTAL_WETTED_AREA, + Aircraft.Nacelle.WETTED_AREA, + Aircraft.VerticalTail.WETTED_AREA, + Aircraft.Wing.WETTED_AREA, + ] + ) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.MAX_HEIGHT, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Fuselage.WETTED_AREA_SCALER, - - # Aircraft.Canard.AREA, - # Aircraft.Canard.ASPECT_RATIO, - # Aircraft.Canard.THICKNESS_TO_CHORD, - # Aircraft.Canard.WETTED_AREA_SCALER, - - Aircraft.HorizontalTail.AREA, - Aircraft.HorizontalTail.ASPECT_RATIO, - Aircraft.HorizontalTail.TAPER_RATIO, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, - Aircraft.HorizontalTail.WETTED_AREA_SCALER, - - Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Nacelle.AVG_LENGTH, - # Aircraft.Nacelle.WETTED_AREA_SCALER, - - Aircraft.VerticalTail.AREA, - Aircraft.VerticalTail.ASPECT_RATIO, - Aircraft.VerticalTail.TAPER_RATIO, - Aircraft.VerticalTail.THICKNESS_TO_CHORD, - Aircraft.VerticalTail.WETTED_AREA_SCALER, - - Aircraft.Wing.AREA, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.GLOVE_AND_BAT, - Aircraft.Wing.SPAN, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Wing.WETTED_AREA_SCALER], + input_keys=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.MAX_HEIGHT, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Fuselage.WETTED_AREA_SCALER, + # Aircraft.Canard.AREA, + # Aircraft.Canard.ASPECT_RATIO, + # Aircraft.Canard.THICKNESS_TO_CHORD, + # Aircraft.Canard.WETTED_AREA_SCALER, + Aircraft.HorizontalTail.AREA, + Aircraft.HorizontalTail.ASPECT_RATIO, + Aircraft.HorizontalTail.TAPER_RATIO, + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, + Aircraft.HorizontalTail.WETTED_AREA_SCALER, + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Nacelle.AVG_LENGTH, + # Aircraft.Nacelle.WETTED_AREA_SCALER, + Aircraft.VerticalTail.AREA, + Aircraft.VerticalTail.ASPECT_RATIO, + Aircraft.VerticalTail.TAPER_RATIO, + Aircraft.VerticalTail.THICKNESS_TO_CHORD, + Aircraft.VerticalTail.WETTED_AREA_SCALER, + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.GLOVE_AND_BAT, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.WETTED_AREA_SCALER, + ], output_keys=output_keys, - aviary_option_keys=[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, - Aircraft.Fuselage.NUM_FUSELAGES], + aviary_option_keys=[ + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + Aircraft.Fuselage.NUM_FUSELAGES, + ], tol=1e-2, atol=1e-6, - rtol=1e-4) + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -166,8 +191,7 @@ def test_prelim_fuselage(self): prob = om.Problem() model = prob.model - model.add_subsystem('comp', FuselagePrelim(), - promotes=['*']) + model.add_subsystem('comp', FuselagePrelim(), promotes=['*']) prob.setup(force_alloc_complex=True) @@ -175,15 +199,14 @@ def test_prelim_fuselage(self): prob.set_val(Aircraft.Fuselage.MAX_HEIGHT, 7.0) prob.set_val(Aircraft.Fuselage.MAX_WIDTH, 4.0) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_prelim_wing(self): prob = om.Problem() model = prob.model - model.add_subsystem('comp', WingPrelim(), - promotes=['*']) + model.add_subsystem('comp', WingPrelim(), promotes=['*']) prob.setup(force_alloc_complex=True) @@ -191,64 +214,68 @@ def test_prelim_wing(self): prob.set_val(Aircraft.Wing.GLOVE_AND_BAT, 7.0) prob.set_val(Aircraft.Wing.SPAN, 4.0) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class _PrelimTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(unit_data_sets, - name_func=print_case) + @parameterized.expand(unit_data_sets, name_func=print_case) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - 'prelim', - _Prelim(aviary_options=get_flops_inputs(case_name, - keys=[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION])), - promotes=['*'] - ) + keys = [Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION] + flops_inputs = get_flops_inputs(case_name, keys=keys) + options = {} + for key in keys: + options[key] = flops_inputs.get_item(key)[0] + + prob.model.add_subsystem('prelim', _Prelim(**options), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=get_flops_data(case_name), - output_validation_data=local_variables[case_name], - input_keys=[Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.HorizontalTail.AREA, - Aircraft.HorizontalTail.ASPECT_RATIO, - Aircraft.HorizontalTail.TAPER_RATIO, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - Aircraft.VerticalTail.AREA, - Aircraft.VerticalTail.ASPECT_RATIO, - Aircraft.VerticalTail.TAPER_RATIO, - Aircraft.VerticalTail.THICKNESS_TO_CHORD, - Aircraft.Wing.AREA, - Aircraft.Wing.GLOVE_AND_BAT, - Aircraft.Wing.SPAN, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD], - output_keys=[Names.CROOT, - Names.CROOTB, - Names.CROTM, - Names.CROTVT, - Names.CRTHTB, - Names.SPANHT, - Names.SPANVT, - Names.XDX, - Names.XMULT, - Names.XMULTH, - Names.XMULTV], - aviary_option_keys=Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, - tol=1e-3, - atol=1e-6, - rtol=1e-4) + do_validation_test( + prob, + case_name, + input_validation_data=get_flops_data(case_name), + output_validation_data=local_variables[case_name], + input_keys=[ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.HorizontalTail.AREA, + Aircraft.HorizontalTail.ASPECT_RATIO, + Aircraft.HorizontalTail.TAPER_RATIO, + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, + Aircraft.VerticalTail.AREA, + Aircraft.VerticalTail.ASPECT_RATIO, + Aircraft.VerticalTail.TAPER_RATIO, + Aircraft.VerticalTail.THICKNESS_TO_CHORD, + Aircraft.Wing.AREA, + Aircraft.Wing.GLOVE_AND_BAT, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD, + ], + output_keys=[ + Names.CROOT, + Names.CROOTB, + Names.CROTM, + Names.CROTVT, + Names.CRTHTB, + Names.SPANHT, + Names.SPANVT, + Names.XDX, + Names.XMULT, + Names.XMULTH, + Names.XMULTV, + ], + aviary_option_keys=Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + tol=1e-3, + atol=1e-6, + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -258,36 +285,40 @@ class _WingTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(unit_data_sets, - name_func=print_case) + @parameterized.expand(unit_data_sets, name_func=print_case) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - 'wings', - _Wing(aviary_options=get_flops_inputs(case_name, - keys=[Aircraft.Fuselage.NUM_FUSELAGES])), - promotes=['*']) + keys = [Aircraft.Fuselage.NUM_FUSELAGES] + flops_inputs = get_flops_inputs(case_name, keys=keys) + options = {} + for key in keys: + options[key] = flops_inputs.get_item(key)[0] + + prob.model.add_subsystem('wings', _Wing(**options), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=_hybrid_input_data(case_name), - output_validation_data=get_flops_outputs(case_name), - input_keys=[Names.CROOT, - Names.CROOTB, - Names.XDX, - Names.XMULT, - Aircraft.Wing.AREA, - Aircraft.Wing.WETTED_AREA_SCALER], - output_keys=Aircraft.Wing.WETTED_AREA, - aviary_option_keys=Aircraft.Fuselage.NUM_FUSELAGES, - check_values=case_name not in wetted_area_overide, - tol=1e-3, - atol=1e-6, - rtol=1e-4) + do_validation_test( + prob, + case_name, + input_validation_data=_hybrid_input_data(case_name), + output_validation_data=get_flops_outputs(case_name), + input_keys=[ + Names.CROOT, + Names.CROOTB, + Names.XDX, + Names.XMULT, + Aircraft.Wing.AREA, + Aircraft.Wing.WETTED_AREA_SCALER, + ], + output_keys=Aircraft.Wing.WETTED_AREA, + aviary_option_keys=Aircraft.Fuselage.NUM_FUSELAGES, + check_values=case_name not in wetted_area_overide, + tol=1e-3, + atol=1e-6, + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -297,39 +328,44 @@ class _TailTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(unit_data_sets, - name_func=print_case) + @parameterized.expand(unit_data_sets, name_func=print_case) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - 'tails', - _Tail(aviary_options=get_flops_inputs(case_name, preprocess=True, - keys=[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES])), - promotes=['*']) + keys = [ + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, + ] + flops_inputs = get_flops_data(case_name, keys=keys) + options = {} + for key in keys: + options[key] = flops_inputs.get_item(key)[0] + + prob.model.add_subsystem('tails', _Tail(**options), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=_hybrid_input_data(case_name), - output_validation_data=get_flops_outputs(case_name), - input_keys=[Names.XMULTH, - Names.XMULTV, - Aircraft.HorizontalTail.AREA, - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, - Aircraft.HorizontalTail.WETTED_AREA_SCALER, - Aircraft.VerticalTail.AREA, - Aircraft.VerticalTail.WETTED_AREA_SCALER], - output_keys=[Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.VerticalTail.WETTED_AREA], - aviary_option_keys=Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, - check_values=case_name not in wetted_area_overide, - tol=1e-3, - atol=1e-6, - rtol=1e-4) + do_validation_test( + prob, + case_name, + input_validation_data=_hybrid_input_data(case_name), + output_validation_data=get_flops_outputs(case_name), + input_keys=[ + Names.XMULTH, + Names.XMULTV, + Aircraft.HorizontalTail.AREA, + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, + Aircraft.HorizontalTail.WETTED_AREA_SCALER, + Aircraft.VerticalTail.AREA, + Aircraft.VerticalTail.WETTED_AREA_SCALER, + ], + output_keys=[Aircraft.HorizontalTail.WETTED_AREA, Aircraft.VerticalTail.WETTED_AREA], + aviary_option_keys=Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + check_values=case_name not in wetted_area_overide, + tol=1e-3, + atol=1e-6, + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -339,53 +375,57 @@ class _FuselageTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(unit_data_sets, - name_func=print_case) + @parameterized.expand(unit_data_sets, name_func=print_case) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - 'fuse', - _Fuselage(aviary_options=get_flops_inputs(case_name, - keys=[Aircraft.Fuselage.NUM_FUSELAGES])), - promotes=['*']) + keys = [Aircraft.Fuselage.NUM_FUSELAGES] + flops_inputs = get_flops_inputs(case_name, keys=keys) + options = {} + for key in keys: + options[key] = flops_inputs.get_item(key)[0] + + prob.model.add_subsystem('fuse', _Fuselage(**options), promotes=['*']) + prob.model.add_subsystem('fuseratio', _FuselageRatios(), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) outputs = [ Aircraft.Fuselage.CROSS_SECTION, Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, - Aircraft.Fuselage.LENGTH_TO_DIAMETER + Aircraft.Fuselage.LENGTH_TO_DIAMETER, ] if case_name not in wetted_area_overide: outputs.extend(Aircraft.Fuselage.WETTED_AREA) - do_validation_test(prob, - case_name, - input_validation_data=_hybrid_input_data(case_name), - output_validation_data=get_flops_outputs(case_name), - input_keys=[Names.CROOTB, - Names.CROTVT, - Names.CRTHTB, - Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.WETTED_AREA_SCALER, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, - Aircraft.VerticalTail.THICKNESS_TO_CHORD, - Aircraft.Wing.AREA, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.GLOVE_AND_BAT, - Aircraft.Wing.THICKNESS_TO_CHORD], - output_keys=[Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.VerticalTail.WETTED_AREA], - aviary_option_keys=Aircraft.Fuselage.NUM_FUSELAGES, - check_values=case_name not in wetted_area_overide, - tol=1e-2, - atol=1e-6, - rtol=1e-4) + do_validation_test( + prob, + case_name, + input_validation_data=_hybrid_input_data(case_name), + output_validation_data=get_flops_outputs(case_name), + input_keys=[ + Names.CROOTB, + Names.CROTVT, + Names.CRTHTB, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.WETTED_AREA_SCALER, + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, + Aircraft.VerticalTail.THICKNESS_TO_CHORD, + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.GLOVE_AND_BAT, + Aircraft.Wing.THICKNESS_TO_CHORD, + ], + output_keys=[Aircraft.HorizontalTail.WETTED_AREA, Aircraft.VerticalTail.WETTED_AREA], + aviary_option_keys=Aircraft.Fuselage.NUM_FUSELAGES, + check_values=case_name not in wetted_area_overide, + tol=1e-2, + atol=1e-6, + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -395,35 +435,38 @@ class NacellesTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(unit_data_sets, - name_func=print_case) + @parameterized.expand(unit_data_sets, name_func=print_case) def test_case(self, case_name): - prob = self.prob - flops_inputs = get_flops_inputs(case_name, preprocess=True, - keys=[Aircraft.Engine.NUM_ENGINES, - Aircraft.Fuselage.NUM_FUSELAGES, - ]) + keys = [Aircraft.Engine.NUM_ENGINES] + flops_inputs = get_flops_inputs(case_name, keys=keys) + options = {} + for key in keys: + options[key] = flops_inputs.get_item(key)[0] - prob.model.add_subsystem( - 'nacelles', - Nacelles(aviary_options=flops_inputs), - promotes=['*']) + prob.model.add_subsystem('nacelles', Nacelles(**options), promotes=['*']) + + setup_model_options( + prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: (np.array([2]), 'unitless')}) + ) prob.setup(check=False, force_alloc_complex=True) - flops_validation_test(prob, - case_name, - input_keys=[Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Nacelle.AVG_LENGTH, - Aircraft.Nacelle.WETTED_AREA_SCALER], - output_keys=[Aircraft.Nacelle.TOTAL_WETTED_AREA, - Aircraft.Nacelle.WETTED_AREA], - aviary_option_keys=[Aircraft.Engine.NUM_ENGINES], - tol=1e-3, - atol=1e-6, - rtol=1e-4) + flops_validation_test( + prob, + case_name, + input_keys=[ + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Nacelle.AVG_LENGTH, + Aircraft.Nacelle.WETTED_AREA_SCALER, + ], + output_keys=[Aircraft.Nacelle.TOTAL_WETTED_AREA, Aircraft.Nacelle.WETTED_AREA], + aviary_option_keys=[Aircraft.Engine.NUM_ENGINES], + tol=1e-3, + atol=1e-6, + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -436,26 +479,29 @@ def setUp(self): def test_case(self): prob = self.prob - prob.model.add_subsystem( - 'canard', - Canard(aviary_options=AviaryValues()), - promotes=['*']) + prob.model.add_subsystem('canard', Canard(), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - 'canard_test', - input_validation_data=Canard_test_data, - output_validation_data=Canard_test_data, - input_keys=[Aircraft.Canard.AREA, - Aircraft.Canard.THICKNESS_TO_CHORD, - Aircraft.Canard.WETTED_AREA_SCALER], - output_keys=Aircraft.Canard.WETTED_AREA, - aviary_option_keys=[Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, - Aircraft.Fuselage.NUM_FUSELAGES], - tol=1e-2, - atol=1e-6, - rtol=1e-4) + do_validation_test( + prob, + 'canard_test', + input_validation_data=Canard_test_data, + output_validation_data=Canard_test_data, + input_keys=[ + Aircraft.Canard.AREA, + Aircraft.Canard.THICKNESS_TO_CHORD, + Aircraft.Canard.WETTED_AREA_SCALER, + ], + output_keys=Aircraft.Canard.WETTED_AREA, + aviary_option_keys=[ + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + Aircraft.Fuselage.NUM_FUSELAGES, + ], + tol=1e-2, + atol=1e-6, + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -465,67 +511,88 @@ class CharacteristicLengthsTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(unit_data_sets, - name_func=print_case) + @parameterized.expand(unit_data_sets, name_func=print_case) def test_case(self, case_name): - prob = self.prob - flops_inputs = get_flops_inputs(case_name, preprocess=True, - keys=[Aircraft.Engine.NUM_ENGINES, - Aircraft.Fuselage.NUM_FUSELAGES, - Aircraft.VerticalTail.NUM_TAILS, - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, - ]) + keys = [ + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + ] + flops_inputs = get_flops_inputs(case_name, keys=keys) + options = {} + for key in keys: + options[key] = flops_inputs.get_item(key)[0] + + prob.model.add_subsystem( + 'wing_characteristic_lengths', WingCharacteristicLength(**options), promotes=['*'] + ) + + keys = [ + Aircraft.Engine.NUM_ENGINES, + ] + flops_inputs = get_flops_inputs(case_name, keys=keys) + options = {} + for key in keys: + options[key] = flops_inputs.get_item(key)[0] prob.model.add_subsystem( - 'characteristic_lengths', - CharacteristicLengths(aviary_options=flops_inputs), - promotes=['*'] + 'other_characteristic_lengths', OtherCharacteristicLengths(**options), promotes=['*'] + ) + + setup_model_options( + prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: (np.array([2]), 'unitless')}) ) prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=_hybrid_input_data(case_name), - output_validation_data=get_flops_outputs(case_name), - input_keys=[Names.CROOT, - Aircraft.Canard.AREA, - Aircraft.Canard.ASPECT_RATIO, - Aircraft.Canard.THICKNESS_TO_CHORD, - Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Fuselage.LENGTH, - Aircraft.HorizontalTail.AREA, - Aircraft.HorizontalTail.ASPECT_RATIO, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Nacelle.AVG_LENGTH, - Aircraft.VerticalTail.AREA, - Aircraft.VerticalTail.ASPECT_RATIO, - Aircraft.VerticalTail.THICKNESS_TO_CHORD, - Aircraft.Wing.AREA, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.GLOVE_AND_BAT, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD], - output_keys=[Aircraft.Canard.CHARACTERISTIC_LENGTH, - Aircraft.Canard.FINENESS, - Aircraft.Fuselage.CHARACTERISTIC_LENGTH, - Aircraft.Fuselage.FINENESS, - Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, - Aircraft.HorizontalTail.FINENESS, - Aircraft.Nacelle.CHARACTERISTIC_LENGTH, - Aircraft.Nacelle.FINENESS, - Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, - Aircraft.VerticalTail.FINENESS, - Aircraft.Wing.CHARACTERISTIC_LENGTH, - Aircraft.Wing.FINENESS], - aviary_option_keys=[ - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, Aircraft.Propulsion.TOTAL_NUM_ENGINES], - tol=1e-2, - atol=1e-6, - rtol=1e-4) + do_validation_test( + prob, + case_name, + input_validation_data=_hybrid_input_data(case_name), + output_validation_data=get_flops_outputs(case_name), + input_keys=[ + Names.CROOT, + Aircraft.Canard.AREA, + Aircraft.Canard.ASPECT_RATIO, + Aircraft.Canard.THICKNESS_TO_CHORD, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.LENGTH, + Aircraft.HorizontalTail.AREA, + Aircraft.HorizontalTail.ASPECT_RATIO, + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Nacelle.AVG_LENGTH, + Aircraft.VerticalTail.AREA, + Aircraft.VerticalTail.ASPECT_RATIO, + Aircraft.VerticalTail.THICKNESS_TO_CHORD, + Aircraft.Wing.AREA, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.GLOVE_AND_BAT, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD, + ], + output_keys=[ + Aircraft.Canard.CHARACTERISTIC_LENGTH, + Aircraft.Canard.FINENESS, + Aircraft.Fuselage.CHARACTERISTIC_LENGTH, + Aircraft.Fuselage.FINENESS, + Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, + Aircraft.HorizontalTail.FINENESS, + Aircraft.Nacelle.CHARACTERISTIC_LENGTH, + Aircraft.Nacelle.FINENESS, + Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, + Aircraft.VerticalTail.FINENESS, + Aircraft.Wing.CHARACTERISTIC_LENGTH, + Aircraft.Wing.FINENESS, + ], + aviary_option_keys=[ + Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, + Aircraft.Propulsion.TOTAL_NUM_ENGINES, + ], + tol=1e-2, + atol=1e-6, + rtol=1e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -537,33 +604,37 @@ def _hybrid_input_data(case_name): return data -_LargeSingleAisle_custom_test_data = AviaryValues({ - Names.CROOT: (16.415788, 'unitless'), - Names.CROOTB: (15.133300, 'unitless'), - Names.CROTM: (0.9218747347874056, 'unitless'), - Names.CROTVT: (19.156603, 'unitless'), - Names.CRTHTB: (13.502073, 'unitless'), - Names.SPANHT: (46.151923036857305, 'unitless'), - Names.SPANVT: (22.293496809607955, 'unitless'), - Names.XDX: (12.750000, 'unitless'), - Names.XMULT: (2.050310, 'unitless'), - Names.XMULTH: (2.048375, 'unitless'), - Names.XMULTV: (2.046247, 'unitless'), -}) - -_other_custom_test_data = AviaryValues({ - Names.CROOT: (19.254769, 'unitless'), - Names.CROOTB: (17.601290, 'unitless'), - Names.CROTM: (0.914126224442001, 'unitless'), - Names.CROTVT: (18.672780, 'unitless'), - Names.CRTHTB: (14.205434, 'unitless'), - Names.SPANHT: (47.09069715015741, 'unitless'), - Names.SPANVT: (25.166513637040453, 'unitless'), - Names.XDX: (12.675400, 'unitless'), - Names.XMULT: (2.050981, 'unitless'), - Names.XMULTH: (2.046247, 'unitless'), - Names.XMULTV: (2.053197, 'unitless'), -}) +_LargeSingleAisle_custom_test_data = AviaryValues( + { + Names.CROOT: (16.415788, 'unitless'), + Names.CROOTB: (15.133300, 'unitless'), + Names.CROTM: (0.9218747347874056, 'unitless'), + Names.CROTVT: (19.156603, 'unitless'), + Names.CRTHTB: (13.502073, 'unitless'), + Names.SPANHT: (46.151923036857305, 'unitless'), + Names.SPANVT: (22.293496809607955, 'unitless'), + Names.XDX: (12.750000, 'unitless'), + Names.XMULT: (2.050310, 'unitless'), + Names.XMULTH: (2.048375, 'unitless'), + Names.XMULTV: (2.046247, 'unitless'), + } +) + +_other_custom_test_data = AviaryValues( + { + Names.CROOT: (19.254769, 'unitless'), + Names.CROOTB: (17.601290, 'unitless'), + Names.CROTM: (0.914126224442001, 'unitless'), + Names.CROTVT: (18.672780, 'unitless'), + Names.CRTHTB: (14.205434, 'unitless'), + Names.SPANHT: (47.09069715015741, 'unitless'), + Names.SPANVT: (25.166513637040453, 'unitless'), + Names.XDX: (12.675400, 'unitless'), + Names.XMULT: (2.050981, 'unitless'), + Names.XMULTH: (2.046247, 'unitless'), + Names.XMULTV: (2.053197, 'unitless'), + } +) local_variables = {} local_variables['LargeSingleAisle1FLOPS'] = _LargeSingleAisle_custom_test_data @@ -572,17 +643,645 @@ def _hybrid_input_data(case_name): local_variables['LargeSingleAisle2FLOPSalt'] = _other_custom_test_data # NOTE: no current data set includes canard -Canard_test_data = AviaryValues({ - Aircraft.Canard.AREA: (10.0, 'ft**2'), - Aircraft.Canard.ASPECT_RATIO: (1.5, 'unitless'), - Aircraft.Canard.CHARACTERISTIC_LENGTH: (2.58, 'ft'), - Aircraft.Canard.FINENESS: (0.3000, 'unitless'), - Aircraft.Canard.TAPER_RATIO: (0.5, 'unitless'), - Aircraft.Canard.THICKNESS_TO_CHORD: (0.3, 'unitless'), - Aircraft.Canard.WETTED_AREA: (21.16, 'ft**2'), - Aircraft.Canard.WETTED_AREA_SCALER: (1.0, 'unitless'), -}) - - -if __name__ == "__main__": +Canard_test_data = AviaryValues( + { + Aircraft.Canard.AREA: (10.0, 'ft**2'), + Aircraft.Canard.ASPECT_RATIO: (1.5, 'unitless'), + Aircraft.Canard.CHARACTERISTIC_LENGTH: (2.58, 'ft'), + Aircraft.Canard.FINENESS: (0.3000, 'unitless'), + Aircraft.Canard.TAPER_RATIO: (0.5, 'unitless'), + Aircraft.Canard.THICKNESS_TO_CHORD: (0.3, 'unitless'), + Aircraft.Canard.WETTED_AREA: (21.16, 'ft**2'), + Aircraft.Canard.WETTED_AREA_SCALER: (1.0, 'unitless'), + } +) + + +@use_tempdirs +class BWBWingTest(unittest.TestCase): + "BWBWing computation test using detailed wing inputs" + + def setUp(self): + self.prob = om.Problem() + + def test_case1(self): + prob = self.prob + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Aircraft.Wing.NUM_INTEGRATION_STATIONS, 15, units='unitless') + prob.model.add_subsystem('wing', _BWBWing(), promotes_outputs=['*'], promotes_inputs=['*']) + setup_model_options(self.prob, self.aviary_options) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val( + 'BWB_INPUT_STATION_DIST', + [ + 0.0, + 32.29, + 0.56275201612903225, + 0.59918934811827951, + 0.63562668010752688, + 0.67206401209677424, + 0.7085013440860215, + 0.74486580141129033, + 0.78137600806451613, + 0.81781334005376349, + 0.85425067204301075, + 0.89068800403225801, + 0.92705246135752695, + 0.96356266801075263, + 1.0, + ], + units='unitless', + ) + prob.set_val( + 'BWB_CHORD_PER_SEMISPAN_DIST', + val=[ + 137.5, + 11.0145643, + 0.327280116, + 0.283045195, + 0.241725260, + 0.210316280, + 0.184883023, + 0.165352613, + 0.154567162, + 0.144510459, + 0.134308006, + 0.124178427, + 0.114048849, + 0.103919271, + 0.0937896925, + ], + ) + prob.set_val( + 'BWB_THICKNESS_TO_CHORD_DIST', + val=[ + 0.11, + 0.11, + 0.1132, + 0.0928, + 0.0822, + 0.0764, + 0.0742, + 0.0746, + 0.0758, + 0.0758, + 0.0756, + 0.0756, + 0.0758, + 0.076, + 0.076, + ], + ) + prob.set_val(Aircraft.Fuselage.MAX_WIDTH, val=64.58) + prob.set_val(Aircraft.Wing.GLOVE_AND_BAT, val=121.05) + prob.set_val(Aircraft.Wing.SPAN, val=238.08) + prob.run_model() + + out1 = prob.get_val(Aircraft.Wing.WETTED_AREA) + exp1 = 17683.7562096 + assert_near_equal(out1, exp1, tolerance=1e-8) + + +@use_tempdirs +class BWBSimplePrepGeomTest(unittest.TestCase): + """ + Test computation of derived values of aircraft geometry for aerodynamics analysis. + In this test, we assume detailed wing is computed instead of provided and we assume + fuselage has a simple layout. Note option Aircraft.Engine.NUM_ENGINES is updated. + """ + + def setUp(self): + options = self.options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, val=True, units='unitless') + options.set_val(Aircraft.BWB.DETAILED_WING_PROVIDED, val=False, units='unitless') + options.set_val(Aircraft.Wing.INPUT_STATION_DIST, [0.0, 0.5, 1.0], units='unitless') + options.set_val(Aircraft.BWB.MAX_NUM_BAYS, 0, units='unitless') + options.set_val(Aircraft.BWB.NUM_BAYS, [2], units='unitless') + options.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 3, units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([3]), units='unitless') + options.set_val(Aircraft.Wing.NUM_INTEGRATION_STATIONS, 3, units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem('prep_geom', PrepGeom(), promotes=['*']) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + # BWBSimpleCabinLayout + prob.set_val(Aircraft.Fuselage.LENGTH, 137.5, units='ft') + prob.set_val(Aircraft.Fuselage.MAX_WIDTH, 64.58, units='ft') + prob.set_val(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 45.0, units='deg') + prob.set_val(Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 0.11, units='unitless') + prob.set_val('Rear_spar_percent_chord', 0.7, units='unitless') + # BWBComputeDetailedWingDist + prob.set_val(Aircraft.Wing.SPAN, val=238.08) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, val=0.11) + prob.set_val(Aircraft.Wing.SWEEP, val=35.7) + # BWBFuselagePrelim + # skip + # BWBWingPrelim + prob.set_val(Aircraft.Wing.GLOVE_AND_BAT, val=121.05) + # _Prelim + prob.set_val(Aircraft.HorizontalTail.AREA, val=0.0) + prob.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, val=0.0) + prob.set_val(Aircraft.HorizontalTail.TAPER_RATIO, val=0) + prob.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.11) + prob.set_val(Aircraft.VerticalTail.AREA, val=0.0) + prob.set_val(Aircraft.VerticalTail.ASPECT_RATIO, val=1.88925) + prob.set_val(Aircraft.VerticalTail.TAPER_RATIO, val=0.0) + prob.set_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.11) + prob.set_val(Aircraft.Wing.TAPER_RATIO, val=0.311) + # _BWBWing + # skip + # _Tail + prob.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0.311) + # _BWBFuselage + # skip + # _FuselageRatios + # Nacelles + # DNAC = 12.608, XNAC = 17.433 originally. It is then scaled down by + # SQRT(ESCALE) = sqrt(0.80963) + # DNAC = 12.608 * sqrt(0.80963) = 11.3446080595 + # XNAC = 17.433 * sqrt(0.80963) = 15.6861161407 + prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, val=11.3446080595) + prob.set_val(Aircraft.Nacelle.AVG_LENGTH, val=15.6861161407) + prob.set_val(Aircraft.Nacelle.WETTED_AREA_SCALER, val=1.0) + # Canard + prob.set_val(Aircraft.Canard.AREA, val=0.0) + prob.set_val(Aircraft.Canard.THICKNESS_TO_CHORD, val=0.0) + prob.set_val(Aircraft.Canard.WETTED_AREA_SCALER, val=0.0) + # BWBWingCharacteristicLength + # OtherCharacteristicLengths + # TotalWettedArea + # TotalWettedArea + + def test_case1(self): + """ + Testing FLOPS data case: + Aircraft.BWB.NUM_BAYS -- NBAY = 5 + Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH -- XLP = 96.25 + Aircraft.Wing.ROOT_CHORD -- XLW = 63.960195184412598 + Aircraft.Fuselage.CABIN_AREA -- ACABIN = 5173.1872025046832 + Aircraft.Fuselage.MAX_HEIGHT -- DF = 15.125 + Aircraft.Wing.INPUT_STATION_DIST -- ETAW = [0, 32.29, 1] + BWB_CHORD_PER_SEMISPAN_DIST -- CHD = [137.5, 91.371707406303713, 14.284802944808163] + BWB_THICKNESS_TO_CHORD_DIST -- TOC = [0.11, 0.11, 0.11] + BWB_LOAD_PATH_SWEEP_DIST -- SWL = [0, 15.337244816188816, 15.337244816188816] + Aircraft.Fuselage.AVG_DIAMETER -- XD = 39.8525 + Aircraft.Fuselage.PLANFORM_AREA -- FPAREA = 7390.267432149546 + Aircraft.Wing.AREA -- XW = 16555.972297926455 + Aircraft.Wing.ASPECT_RATIO -- AR = 3.4488821268812084 + Aircraft.Wing.LOAD_FRACTION -- PCTL = 0.53107174649913569 + prelim.prep_geom:_Names:CROOT -- CROOT = 105.31056813183183 + prelim.prep_geom:_Names:CROOTB -- CROOTB = 93.164834715181058 + prelim.prep_geom:_Names:CROTM -- CROTM = 0.88466747799284229 + prelim.prep_geom:_Names:CROTVT -- CROTVT = 0 + prelim.prep_geom:_Names:CRTHTB -- CRTHTB = 0 + prelim.prep_geom:_Names:SPANHT -- SPANHT = 0 + prelim.prep_geom:_Names:SPANVT -- SPANVT = 0 + prelim.prep_geom:_Names:XDX -- XDX = 39.8525 + prelim.prep_geom:_Names:XMULT -- XMULT = 2.04257 + prelim.prep_geom:_Names:XMULTH -- XMULTH = 2.04257 + prelim.prep_geom:_Names:XMULTV -- XMULTV = 2.04257 + Aircraft.Wing.WETTED_AREA -- SWET(1) = 33816.73 + Aircraft.HorizontalTail.WETTED_AREA -- HORIZONTAL= 0.0 + Aircraft.VerticalTail.WETTED_AREA -- VERTICAL TAIL SWET = 0.0 + Aircraft.Fuselage.DIAMETER_TO_WING_SPAN -- DB = 0.16739117852998228 + Aircraft.Fuselage.LENGTH_TO_DIAMETER -- BODYLD = 3.4502226961922089 + Aircraft.Nacelle.TOTAL_WETTED_AREA -- SWTNA = 498.27*3 + Aircraft.Nacelle.WETTED_AREA -- SWET(5)-SWET(7) = 498.26795086 + Aircraft.Wing.CHARACTERISTIC_LENGTH -- EL(1) = 69.539519845923053 + Aircraft.Fuselage.CHARACTERISTIC_LENGTH -- EL(4) = 137.5 + Aircraft.Nacelle.CHARACTERISTIC_LENGTH -- EL(5)-EL(7) = 15.686120387590995 + Aircraft.Design.TOTAL_WETTED_AREA -- SWTWG + SWTHT + SWTVT + SWTFU + SWTNA + SWTCN = 35311.536998566495 + """ + prob = self.prob + + prob.run_model() + + # BWBSimpleCabinLayout + num_bays = prob.get_val(Aircraft.BWB.NUM_BAYS) + assert_near_equal(num_bays, [5], tolerance=1e-9) + pax_compart_length = prob.get_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + assert_near_equal(pax_compart_length, 96.25, tolerance=1e-8) + root_chord = prob.get_val(Aircraft.Wing.ROOT_CHORD) + assert_near_equal(root_chord, 63.96019518, tolerance=1e-8) + area_cabin = prob.get_val(Aircraft.Fuselage.CABIN_AREA) + assert_near_equal(area_cabin, 5173.1872025, tolerance=1e-8) + fuselage_height = prob.get_val(Aircraft.Fuselage.MAX_HEIGHT) + assert_near_equal(fuselage_height, 15.125, tolerance=1e-8) + + # BWBComputeDetailedWingDist + out1 = prob.get_val('BWB_CHORD_PER_SEMISPAN_DIST') + exp1 = [137.5, 91.37170741, 14.2848] + assert_near_equal(out1, exp1, tolerance=1e-8) + + out2 = prob.get_val('BWB_THICKNESS_TO_CHORD_DIST') + exp2 = [0.11, 0.11, 0.11] + assert_near_equal(out2, exp2, tolerance=1e-8) + + out3 = prob.get_val('BWB_LOAD_PATH_SWEEP_DIST') + exp3 = [0.0, 15.33723721, 15.33723721] + assert_near_equal(out3, exp3, tolerance=1e-8) + + # BWBFuselagePrelim + assert_near_equal(prob.get_val(Aircraft.Fuselage.AVG_DIAMETER), 39.8525, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.Fuselage.PLANFORM_AREA), 7390.26743215, tolerance=1e-8 + ) + + # BWBWingPrelim + assert_near_equal(prob.get_val(Aircraft.Wing.AREA), 16555.96944965, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.Wing.ASPECT_RATIO), + 3.4488813, + tolerance=1e-8, + ) + assert_near_equal( + prob.get_val(Aircraft.Wing.LOAD_FRACTION), + 0.531071664997850196, + tolerance=1e-8, + ) + # _Prelim + assert_near_equal( + prob.get_val('prelim.prep_geom:_Names:CROOT'), 105.310571594, tolerance=1e-8 + ) + assert_near_equal( + prob.get_val('prelim.prep_geom:_Names:CROOTB'), 93.16483527, tolerance=1e-8 + ) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:CROTM'), 0.88466745, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:CROTVT'), 0.0, tolerance=1e-7) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:CRTHTB'), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:SPANHT'), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:SPANVT'), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XDX'), 39.8525, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XMULT'), 2.04257, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XMULTH'), 2.04257, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XMULTV'), 2.04257, tolerance=1e-8) + # _BWBWing + assert_near_equal(prob.get_val(Aircraft.Wing.WETTED_AREA), 33816.72651876, tolerance=1e-8) + # _Tail + assert_near_equal(prob.get_val(Aircraft.HorizontalTail.WETTED_AREA), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val(Aircraft.VerticalTail.WETTED_AREA), 0.0, tolerance=1e-8) + # _BWBFuselage + # _FuselageRatios + assert_near_equal( + prob.get_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN), 0.167391212, tolerance=1e-8 + ) + assert_near_equal( + prob.get_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER), 3.4502227, tolerance=1e-8 + ) + # Nacelles + assert_near_equal( + prob.get_val(Aircraft.Nacelle.TOTAL_WETTED_AREA), 1494.80385257, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Nacelle.WETTED_AREA), 498.26795086, tolerance=1e-8) + # Canard + assert_near_equal(prob.get_val(Aircraft.Canard.WETTED_AREA), 0.0, tolerance=1e-8) + # BWBWingCharacteristicLength + assert_near_equal( + prob.get_val(Aircraft.Wing.CHARACTERISTIC_LENGTH), 69.53952222, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Wing.FINENESS), 0.11, tolerance=1e-8) + # OtherCharacteristicLengths + assert_near_equal(prob.get_val(Aircraft.Canard.CHARACTERISTIC_LENGTH), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val(Aircraft.Canard.FINENESS), 0.0, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH), 137.5, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Fuselage.FINENESS), 3.4502227, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH), 0.0, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.HorizontalTail.FINENESS), 0.11, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.Nacelle.CHARACTERISTIC_LENGTH), 15.68611614, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Nacelle.FINENESS), 1.38269353, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.VerticalTail.CHARACTERISTIC_LENGTH), 0.0, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.VerticalTail.FINENESS), 0.11, tolerance=1e-8) + # TotalWettedArea + assert_near_equal( + prob.get_val(Aircraft.Design.TOTAL_WETTED_AREA), 35311.53037134, tolerance=1e-8 + ) + + +@use_tempdirs +class BWBDetailedPrepGeomTest(unittest.TestCase): + """ + Test computation of derived values of aircraft geometry for aerodynamics analysis. + In this test, we assume detailed wing is provided and we assume fuselage has a detailed layout. + Note options Aircraft.Engine.NUM_ENGINES and Aircraft.Wing.INPUT_STATION_DIST are updated. + """ + + def setUp(self): + options = self.options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Fuselage.SIMPLE_LAYOUT, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, 100, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 28, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, 340, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS, 4, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST, 4, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS, 39.0, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 61.0, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 32.0, units='inch') + options.set_val(Aircraft.BWB.MAX_NUM_BAYS, 0, units='unitless') + options.set_val(Aircraft.BWB.NUM_BAYS, [2], units='unitless') + options.set_val(Aircraft.Wing.DETAILED_WING, val=True, units='unitless') + options.set_val( + Aircraft.Wing.INPUT_STATION_DIST, + [0.0, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.6499, 0.7, 0.75, 0.8, 0.85, 0.8999, 0.95, 1], + units='unitless', + ) + options.set_val(Aircraft.Wing.NUM_INTEGRATION_STATIONS, 15, units='unitless') + options.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, 3, units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([3]), units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem('prep_geom', PrepGeom(), promotes=['*']) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + # BWBDetailedCabinLayout + prob.set_val(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, val=45.0, units='deg') + prob.set_val(Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, val=0.11, units='unitless') + prob.set_val('Rear_spar_percent_chord', val=0.7, units='unitless') + # BWBUpdateDetailedWingDist + prob.set_val( + Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, + val=[ + -1.0, + 58.03, + 0.4491, + 0.3884, + 0.3317, + 0.2886, + 0.2537, + 0.2269, + 0.2121, + 0.1983, + 0.1843, + 0.1704, + 0.1565, + 0.1426, + 0.1287, + ], + ) + prob.set_val( + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + val=[ + -1.0, + 0.15, + 0.1132, + 0.0928, + 0.0822, + 0.0764, + 0.0742, + 0.0746, + 0.0758, + 0.0758, + 0.0756, + 0.0756, + 0.0758, + 0.076, + 0.076, + ], + ) + prob.set_val( + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + val=[0.0, 0, 0, 0, 0, 0, 0, 0, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9], + ) + prob.set_val(Aircraft.Wing.SPAN, val=253.720756) + prob.set_val(Aircraft.Wing.THICKNESS_TO_CHORD, val=0.11) + # BWBFuselagePrelim + # skip + # BWBWingPrelim + prob.set_val(Aircraft.Wing.GLOVE_AND_BAT, val=121.05) + # _Prelim + prob.set_val(Aircraft.HorizontalTail.AREA, val=0.0) + prob.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, val=0.0) + prob.set_val(Aircraft.HorizontalTail.TAPER_RATIO, val=0) + prob.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.11) + prob.set_val(Aircraft.VerticalTail.AREA, val=0.0) + prob.set_val(Aircraft.VerticalTail.ASPECT_RATIO, val=1.88925) + prob.set_val(Aircraft.VerticalTail.TAPER_RATIO, val=0.0) + prob.set_val(Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.11) + prob.set_val(Aircraft.Wing.TAPER_RATIO, val=0.311) + # _BWBWing + # skip + # _Tail + prob.set_val(Aircraft.HorizontalTail.AREA, val=0.0) + prob.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0.311) + prob.set_val(Aircraft.HorizontalTail.WETTED_AREA_SCALER, val=1.0) + prob.set_val(Aircraft.VerticalTail.AREA, val=0.0) + prob.set_val(Aircraft.VerticalTail.WETTED_AREA_SCALER, val=1.0) + # _BWBFuselage + # skip + # _FuselageRatios + # Nacelles + # DNAC = 12.608, XNAC = 17.433 originally. It is then scaled down by + # SQRT(ESCALE) = sqrt(0.80963) + # DNAC = 12.608 * sqrt(0.80963) = 11.3446080595 + # XNAC = 17.433 * sqrt(0.80963) = 15.6861161407 + prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, val=11.3446080595) + prob.set_val(Aircraft.Nacelle.AVG_LENGTH, val=15.6861161407) + prob.set_val(Aircraft.Nacelle.WETTED_AREA_SCALER, val=1.0) + # Canard + prob.set_val(Aircraft.Canard.AREA, val=0.0) + prob.set_val(Aircraft.Canard.THICKNESS_TO_CHORD, val=0.0) + prob.set_val(Aircraft.Canard.WETTED_AREA_SCALER, val=0.0) + # BWBWingCharacteristicLength + # OtherCharacteristicLengths + # TotalWettedArea + # TotalWettedArea + + def test_case1(self): + """ + Testing FLOPS data case: + Aircraft.BWB.NUM_BAYS -- NBAY = 7 + Aircraft.Fuselage.LENGTH -- XL = 112.3 + Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH -- XLP = 78.61 + Aircraft.Fuselage.MAX_WIDTH -- WF = 80.22 + Aircraft.Fuselage.MAX_HEIGHT -- DF = 12.35 + Aircraft.Fuselage.CABIN_AREA -- ACABIN = 4697.33 + Aircraft.Wing.ROOT_CHORD -- XLW = 38.50 + Aircraft.Fuselage.AVG_DIAMETER -- XD = 46.2868886894979 + Aircraft.Fuselage.PLANFORM_AREA -- FPAREA = 6710.4740143724875 + Aircraft.Wing.AREA -- SW = 12109.9 + Aircraft.Wing.ASPECT_RATIO -- AR = 5.370 + Aircraft.Wing.LOAD_FRACTION -- PCTL = 0.4676 + prelim.prep_geom:_Names:CROOT -- CROOT = 72.085530500256112 + prelim.prep_geom:_Names:CROOTB -- CROOTB = 63.024672729456938 + prelim.prep_geom:_Names:CROTM -- CROTM = 0.87430407034644797 + prelim.prep_geom:_Names:CROTVT -- CROTVT = 0 + prelim.prep_geom:_Names:CRTHTB -- CRTHTB = 0 + prelim.prep_geom:_Names:SPANHT -- SPANHT = 0 + prelim.prep_geom:_Names:SPANVT -- SPANVT = 0 + prelim.prep_geom:_Names:XDX -- XDX = 46.2868886894979 + prelim.prep_geom:_Names:XMULT -- XMULT = 2.04257 + prelim.prep_geom:_Names:XMULTH -- XMULTH = 2.04257 + prelim.prep_geom:_Names:XMULTV -- XMULTV = 2.04257 + Aircraft.Wing.WETTED_AREA -- SWET(1) = 24713.661297561481 + Aircraft.HorizontalTail.WETTED_AREA -- HORIZONTAL TAIL SWET = 0.0 + Aircraft.VerticalTail.WETTED_AREA -- VERTICAL TAIL SWET = 0.0 + Aircraft.Fuselage.DIAMETER_TO_WING_SPAN -- DB = 0.18243240878599712 + Aircraft.Fuselage.LENGTH_TO_DIAMETER -- BODYLD = 2.4261771932742167 + Aircraft.Nacelle.TOTAL_WETTED_AREA -- SWTNA = 498.27*3 + Aircraft.Nacelle.WETTED_AREA -- SWET(5)-SWET(7) = 498.26822066361945 + Aircraft.Wing.CHARACTERISTIC_LENGTH -- EL(1) = 47.729164562158907 + Aircraft.Fuselage.CHARACTERISTIC_LENGTH -- EL(4) = 112.3001936860821 + Aircraft.Nacelle.CHARACTERISTIC_LENGTH -- EL(5)-EL(7) = 15.686120387590995 + """ + prob = self.prob + options = self.options + + prob.run_model() + + # BWBDetailedCabinLayout + num_bays = prob.get_val(Aircraft.BWB.NUM_BAYS) + assert_near_equal(num_bays, [7], tolerance=1e-9) + fuselage_length = prob.get_val(Aircraft.Fuselage.LENGTH) + assert_near_equal(fuselage_length, 112.30019369, tolerance=1e-9) + pax_compart_length = prob.get_val(Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH) + assert_near_equal(pax_compart_length, 78.61013558, tolerance=1e-9) + fuselage_width = prob.get_val(Aircraft.Fuselage.MAX_WIDTH) + assert_near_equal(fuselage_width, 80.22075607, tolerance=1e-9) + fuselage_height = prob.get_val(Aircraft.Fuselage.MAX_HEIGHT) + assert_near_equal(fuselage_height, 12.35302131, tolerance=1e-9) + cabin_area = prob.get_val(Aircraft.Fuselage.CABIN_AREA) + assert_near_equal(cabin_area, 4697.33181006, tolerance=1e-9) + root_chord = prob.get_val(Aircraft.Wing.ROOT_CHORD) + assert_near_equal(root_chord, 38.5, tolerance=1e-9) + + # BWBUpdateDetailedWingDist + out1 = prob.get_val('BWB_CHORD_PER_SEMISPAN_DIST') + exp1 = [ + 112.3001936861, + 55.0, + 0.3071047525, + 0.2655967176, + 0.2268239733, + 0.197351217, + 0.1734858065, + 0.1551593595, + 0.1450387842, + 0.1356020317, + 0.1260285145, + 0.1165233797, + 0.1070182448, + 0.09751311, + 0.0880079752, + ] + assert_near_equal(out1, exp1, tolerance=1e-8) + + out2 = prob.get_val('BWB_THICKNESS_TO_CHORD_DIST') + exp2 = [ + 0.11, + 0.11, + 0.1132, + 0.0928, + 0.0822, + 0.0764, + 0.0742, + 0.0746, + 0.0758, + 0.0758, + 0.0756, + 0.0756, + 0.0758, + 0.076, + 0.076, + ] + assert_near_equal(out2, exp2, tolerance=1e-8) + + out3 = prob.get_val('BWB_LOAD_PATH_SWEEP_DIST') + exp3 = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9, 42.9] + assert_near_equal(out3, exp3, tolerance=1e-8) + + # BWBFuselagePrelim + assert_near_equal(prob.get_val(Aircraft.Fuselage.AVG_DIAMETER), 46.28688869, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.Fuselage.PLANFORM_AREA), 6710.47401437, tolerance=1e-8 + ) + + # BWBWingPrelim + assert_near_equal(prob.get_val(Aircraft.Wing.AREA), 12109.8797157, tolerance=1e-8) + assert_near_equal(prob.get_val(Aircraft.Wing.ASPECT_RATIO), 5.36951675, tolerance=1e-8) + assert_near_equal(prob.get_val(Aircraft.Wing.LOAD_FRACTION), 0.46761342, tolerance=1e-8) + # _Prelim + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:CROOT'), 72.0855305, tolerance=1e-8) + assert_near_equal( + prob.get_val('prelim.prep_geom:_Names:CROOTB'), 63.02467273, tolerance=1e-8 + ) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:CROTM'), 0.87430407, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:CROTVT'), 0.0, tolerance=1e-7) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:CRTHTB'), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:SPANHT'), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:SPANVT'), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XDX'), 46.28688869, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XMULT'), 2.04257, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XMULTH'), 2.04257, tolerance=1e-8) + assert_near_equal(prob.get_val('prelim.prep_geom:_Names:XMULTV'), 2.04257, tolerance=1e-8) + # _BWBWing + assert_near_equal(prob.get_val(Aircraft.Wing.WETTED_AREA), 24713.66128988, tolerance=1e-8) + # _Tail + assert_near_equal(prob.get_val(Aircraft.HorizontalTail.WETTED_AREA), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val(Aircraft.VerticalTail.WETTED_AREA), 0.0, tolerance=1e-8) + # _BWBFuselage + # skip + # _FuselageRatios + assert_near_equal( + prob.get_val(Aircraft.Fuselage.DIAMETER_TO_WING_SPAN), + 0.18243241, + tolerance=1e-8, + ) + assert_near_equal( + prob.get_val(Aircraft.Fuselage.LENGTH_TO_DIAMETER), 2.42617719, tolerance=1e-8 + ) + # Nacelles + assert_near_equal( + prob.get_val(Aircraft.Nacelle.TOTAL_WETTED_AREA), 1494.80385258, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Nacelle.WETTED_AREA), 498.26795086, tolerance=1e-8) + # Canard + assert_near_equal(prob.get_val(Aircraft.Canard.WETTED_AREA), 0.0, tolerance=1e-8) + # BWBWingCharacteristicLength + assert_near_equal( + prob.get_val(Aircraft.Wing.CHARACTERISTIC_LENGTH), 47.72916456, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Wing.FINENESS), 0.11, tolerance=1e-8) + # OtherCharacteristicLengths + assert_near_equal(prob.get_val(Aircraft.Canard.CHARACTERISTIC_LENGTH), 0.0, tolerance=1e-8) + assert_near_equal(prob.get_val(Aircraft.Canard.FINENESS), 0.0, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.Fuselage.CHARACTERISTIC_LENGTH), 112.30019369, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Fuselage.FINENESS), 2.42617719, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH), 0.0, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.HorizontalTail.FINENESS), 0.11, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.Nacelle.CHARACTERISTIC_LENGTH), 15.68611614, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.Nacelle.FINENESS), 1.38269353, tolerance=1e-8) + assert_near_equal( + prob.get_val(Aircraft.VerticalTail.CHARACTERISTIC_LENGTH), 0.0, tolerance=1e-8 + ) + assert_near_equal(prob.get_val(Aircraft.VerticalTail.FINENESS), 0.11, tolerance=1e-8) + # TotalWettedArea + assert_near_equal( + prob.get_val(Aircraft.Design.TOTAL_WETTED_AREA), 26208.46514246, tolerance=1e-8 + ) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/flops_based/utils.py b/aviary/subsystems/geometry/flops_based/utils.py index 714c5fc4a0..3f293b3808 100644 --- a/aviary/subsystems/geometry/flops_based/utils.py +++ b/aviary/subsystems/geometry/flops_based/utils.py @@ -11,26 +11,21 @@ def calc_lifting_surface_scaler(thickness_to_chord): def calc_fuselage_adjustment(chord, thickness_to_chord): """Calculate fuselage_adjustment.""" - adjustment = \ - _fuselage_adjustment_scaler * chord * (thickness_to_chord * chord) + adjustment = _fuselage_adjustment_scaler * chord * (thickness_to_chord * chord) return adjustment def d_calc_fuselage_adjustment(chord, thickness_to_chord): - """ - Calculate partial derivatives of fuselage_adjustment with respect to chord and thickness_to_chord. - """ + """Calculate partial derivatives of fuselage_adjustment with respect to chord and thickness_to_chord.""" d1 = 2.0 * _fuselage_adjustment_scaler * thickness_to_chord * chord - d2 = _fuselage_adjustment_scaler * chord ** 2 + d2 = _fuselage_adjustment_scaler * chord**2 return d1, d2 class Names: - ''' - Define component I/O variable names that should not exported. - ''' + """Define component I/O variable names that should not exported.""" CROOT = 'prep_geom:_Names:CROOT' CROOTB = 'prep_geom:_Names:CROOTB' diff --git a/aviary/subsystems/geometry/flops_based/wetted_area_total.py b/aviary/subsystems/geometry/flops_based/wetted_area_total.py index 4bb08d3e8b..7529e17897 100644 --- a/aviary/subsystems/geometry/flops_based/wetted_area_total.py +++ b/aviary/subsystems/geometry/flops_based/wetted_area_total.py @@ -1,6 +1,5 @@ import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft @@ -8,23 +7,18 @@ class TotalWettedArea(om.ExplicitComponent): """ Sum of wetted areas of canard, fuselage, horizontal tail, nacelle, vertical tail and wing. - It is simple enought to skip unit test + It is simple enough to skip unit test. """ - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.Canard.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.Nacelle.TOTAL_WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.WETTED_AREA, 0.0) + add_aviary_input(self, Aircraft.Canard.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Nacelle.TOTAL_WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.WETTED_AREA, units='ft**2') - add_aviary_output(self, Aircraft.Design.TOTAL_WETTED_AREA, 0.0) + add_aviary_output(self, Aircraft.Design.TOTAL_WETTED_AREA, units='ft**2') def setup_partials(self): self.declare_partials('*', '*', val=1.0) @@ -36,4 +30,5 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + inputs[Aircraft.HorizontalTail.WETTED_AREA] + inputs[Aircraft.Nacelle.TOTAL_WETTED_AREA] + inputs[Aircraft.VerticalTail.WETTED_AREA] - + inputs[Aircraft.Wing.WETTED_AREA]) + + inputs[Aircraft.Wing.WETTED_AREA] + ) diff --git a/aviary/subsystems/geometry/flops_based/wing.py b/aviary/subsystems/geometry/flops_based/wing.py index 7eb02513cc..96db7e8343 100644 --- a/aviary/subsystems/geometry/flops_based/wing.py +++ b/aviary/subsystems/geometry/flops_based/wing.py @@ -1,30 +1,20 @@ -""" -Contains any preliminary calculations on the wing. -""" +"""Contains any preliminary calculations on the wing.""" import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft class WingPrelim(om.ExplicitComponent): - """ - preliminary calculations of wing aspect ratio - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """preliminary calculations of wing aspect ratio.""" def setup(self): - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) - add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, val=0.0) - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.GLOVE_AND_BAT, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') - add_aviary_output(self, Aircraft.Wing.ASPECT_RATIO, val=0.0) + add_aviary_output(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') def setup_partials(self): self.declare_partials('*', '*') @@ -34,7 +24,7 @@ def compute(self, inputs, outputs): glove_and_bat = inputs[Aircraft.Wing.GLOVE_AND_BAT] span = inputs[Aircraft.Wing.SPAN] - AR = span ** 2 / (area - glove_and_bat) + AR = span**2 / (area - glove_and_bat) outputs[Aircraft.Wing.ASPECT_RATIO] = AR def compute_partials(self, inputs, partials, discrete_inputs=None): @@ -44,11 +34,8 @@ def compute_partials(self, inputs, partials, discrete_inputs=None): denom = 1.0 / (area - glove_and_bat) - partials[Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.AREA] = -(span * denom) ** 2 + partials[Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.AREA] = -((span * denom) ** 2) - partials[Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.GLOVE_AND_BAT] = (span * denom) ** 2 + partials[Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.GLOVE_AND_BAT] = (span * denom) ** 2 - partials[Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.SPAN] = 2.0 * span * denom + partials[Aircraft.Wing.ASPECT_RATIO, Aircraft.Wing.SPAN] = 2.0 * span * denom diff --git a/aviary/subsystems/geometry/gasp_based/electric.py b/aviary/subsystems/geometry/gasp_based/electric.py index 3196bb92b6..dc54320535 100644 --- a/aviary/subsystems/geometry/gasp_based/electric.py +++ b/aviary/subsystems/geometry/gasp_based/electric.py @@ -1,36 +1,29 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class CableSize(om.ExplicitComponent): - """ - Computation of cable length for hybrid electric augmented system - """ + """Computation of cable length for hybrid electric augmented system.""" def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) def setup(self): - aviary_options = self.options['aviary_options'] - total_num_wing_engines = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) - - add_aviary_input(self, Aircraft.Engine.WING_LOCATIONS, - val=np.full(int(total_num_wing_engines/2), 0.35)) - - add_aviary_input(self, Aircraft.Wing.SPAN, val=128) + total_num_wing_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=10) + add_aviary_input( + self, + Aircraft.Engine.WING_LOCATIONS, + shape=int(total_num_wing_engines / 2), + units='unitless', + ) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') - add_aviary_output(self, Aircraft.Electrical.HYBRID_CABLE_LENGTH, val=0) + add_aviary_output(self, Aircraft.Electrical.HYBRID_CABLE_LENGTH, units='ft') self.declare_partials( Aircraft.Electrical.HYBRID_CABLE_LENGTH, @@ -41,9 +34,8 @@ def setup(self): ) self.declare_partials( - Aircraft.Electrical.HYBRID_CABLE_LENGTH, - Aircraft.Fuselage.AVG_DIAMETER, - val=2.) + Aircraft.Electrical.HYBRID_CABLE_LENGTH, Aircraft.Fuselage.AVG_DIAMETER, val=2.0 + ) def compute(self, inputs, outputs): eng_span_frac = np.sum(inputs[Aircraft.Engine.WING_LOCATIONS]) @@ -62,5 +54,4 @@ def compute_partials(self, inputs, J): Aircraft.Electrical.HYBRID_CABLE_LENGTH, Aircraft.Engine.WING_LOCATIONS, ] = wingspan - J[Aircraft.Electrical.HYBRID_CABLE_LENGTH, - Aircraft.Wing.SPAN] = np.sum(eng_span_frac) + J[Aircraft.Electrical.HYBRID_CABLE_LENGTH, Aircraft.Wing.SPAN] = np.sum(eng_span_frac) diff --git a/aviary/subsystems/geometry/gasp_based/empennage.py b/aviary/subsystems/geometry/gasp_based/empennage.py index c0133bc549..9eab367bdf 100644 --- a/aviary/subsystems/geometry/gasp_based/empennage.py +++ b/aviary/subsystems/geometry/gasp_based/empennage.py @@ -1,8 +1,7 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_output, add_aviary_option from aviary.variable_info.variables import Aircraft @@ -18,70 +17,64 @@ class TailVolCoef(om.ExplicitComponent): def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - self.options.declare( - "vertical", - default=False, - types=bool, - desc=( - "Use vertical tail volume coefficient relationship, " - "otherwise assume a horizontal tail" - ), + 'orientation', + values=['horizontal', 'vertical'], + desc='Tail orientation, can be horizontal or vertical.', ) def setup(self): + veritcal = self.options['orientation'] == 'vertical' + if veritcal: + self.io_names = { + 'vol_coef': Aircraft.VerticalTail.VOLUME_COEFFICIENT, + 'wing_ref': Aircraft.Wing.SPAN, + } + else: + self.io_names = { + 'vol_coef': Aircraft.HorizontalTail.VOLUME_COEFFICIENT, + 'wing_ref': Aircraft.Wing.AVERAGE_CHORD, + } + # coefficients used in the empirical equation - if self.options["vertical"]: + if veritcal: self.k = [0.07, 0.0434, 0.336] else: self.k = [0.43, 0.38, 0.85] - add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0) + add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, units='unitless') - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=129.4) + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') - self.add_input("cab_w", 13.1, units="ft", desc="SWF: Cabin width") + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') - add_aviary_input(self, Aircraft.Wing.AREA, val=1370) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') - self.add_input( - "wing_ref", - 12.615, - units="ft", - desc=( - "CBARW | B: Wing reference parameter. Wing chord for a " - "horizontal tail. Wing span for a vertical tail." - ), - ) + add_aviary_input(self, self.io_names['wing_ref'], val=12.612, units='ft') - self.add_output( - "vol_coef", units="unitless", desc="VBARH | VBARV: Tail volume coefficient") + add_aviary_output(self, self.io_names['vol_coef'], units='unitless') def setup_partials(self): - self.declare_partials("vol_coef", "*") + self.declare_partials(self.io_names['vol_coef'], '*') def compute(self, inputs, outputs): htail_loc, fus_len, cab_w, wing_area, wing_ref = inputs.values() k1, k2, k3 = self.k ch1 = k1 - k2 * htail_loc - outputs["vol_coef"] = k3 * fus_len * cab_w**2 / (wing_area * wing_ref) + ch1 + outputs[self.io_names['vol_coef']] = k3 * fus_len * cab_w**2 / (wing_area * wing_ref) + ch1 def compute_partials(self, inputs, J): + str_vol_coef = self.io_names['vol_coef'] + str_wing_ref = self.io_names['wing_ref'] + htail_loc, fus_len, cab_w, wing_area, wing_ref = inputs.values() k1, k2, k3 = self.k - J["vol_coef", Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] = -k2 - J["vol_coef", Aircraft.Fuselage.LENGTH] = ( - k3 * cab_w**2 / (wing_area * wing_ref) - ) - J["vol_coef", "cab_w"] = 2 * k3 * fus_len * cab_w / (wing_area * wing_ref) - J["vol_coef", Aircraft.Wing.AREA] = ( - -k3 * fus_len * cab_w**2 / (wing_area**2 * wing_ref) - ) - J["vol_coef", "wing_ref"] = ( - -k3 * fus_len * cab_w**2 / (wing_area * wing_ref**2) + J[str_vol_coef, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] = -k2 + J[str_vol_coef, Aircraft.Fuselage.LENGTH] = k3 * cab_w**2 / (wing_area * wing_ref) + J[str_vol_coef, Aircraft.Fuselage.AVG_DIAMETER] = ( + 2 * k3 * fus_len * cab_w / (wing_area * wing_ref) ) + J[str_vol_coef, Aircraft.Wing.AREA] = -k3 * fus_len * cab_w**2 / (wing_area**2 * wing_ref) + J[str_vol_coef, str_wing_ref] = -k3 * fus_len * cab_w**2 / (wing_area * wing_ref**2) class TailSize(om.ExplicitComponent): @@ -94,66 +87,93 @@ class TailSize(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + 'orientation', + values=['horizontal', 'vertical'], + desc='Tail orientation, can be horizontal or vertical.', ) def setup(self): - # defaults here for Large Single Aisle 1 horizontal tail - self.add_input( - "vol_coef", 1.189, units="unitless", - desc="VBARH | VBARV: Horizontal tail volume coefficient" - ) - - add_aviary_input(self, Aircraft.Wing.AREA, val=1370) - - self.add_input( - "r_arm", - 0.2307, - units="unitless", - desc=( - "COELTH | BOELTV: For a horizontal tail, the ratio of " - "wing chord to tail moment arm. For a vertical tail, the " - "ratio of wing span to vertical tail moment arm." - ), - ) - self.add_input( - "wing_ref", - 12.615, - units="ft", - desc=( - "CBARW | B: Reference wing parameter for tail moment arm. " - "For a horizontal tail, the mean wing chord. For a " - "vertical tail, the wing span." - ), - ) - self.add_input( - "ar", 4.75, units="unitless", desc="ARHT | ARVT: Tail aspect ratio.") - self.add_input( - "tr", 0.352, units="unitless", desc="SLMH | SLMV: Tail taper ratio.") - - self.add_output("area", units="ft**2", desc="SHT | SVT: Tail area") - self.add_output("span", units="ft", desc="BHT | BVT: Tail span") - self.add_output("rchord", units="ft", desc="CRCLHT | CRCLVT: Tail root chord") - self.add_output( - "chord", units="ft", desc="CBARHT | CBARVT: Tail mean aerodynamic chord" - ) - self.add_output("arm", units="ft", desc="ELTH | ELTV: Tail moment arm") + orientation = self.options['orientation'] + + if orientation == 'horizontal': + self.io_names = { + 'vol_coef': Aircraft.HorizontalTail.VOLUME_COEFFICIENT, + 'r_arm': Aircraft.HorizontalTail.MOMENT_RATIO, + 'wing_ref': Aircraft.Wing.AVERAGE_CHORD, + 'ar': Aircraft.HorizontalTail.ASPECT_RATIO, + 'tr': Aircraft.HorizontalTail.TAPER_RATIO, + 'area': Aircraft.HorizontalTail.AREA, + 'span': Aircraft.HorizontalTail.SPAN, + 'rchord': Aircraft.HorizontalTail.ROOT_CHORD, + 'chord': Aircraft.HorizontalTail.AVERAGE_CHORD, + 'arm': Aircraft.HorizontalTail.MOMENT_ARM, + } + else: + self.io_names = { + 'vol_coef': Aircraft.VerticalTail.VOLUME_COEFFICIENT, + 'r_arm': Aircraft.VerticalTail.MOMENT_RATIO, + 'wing_ref': Aircraft.Wing.SPAN, + 'ar': Aircraft.VerticalTail.ASPECT_RATIO, + 'tr': Aircraft.VerticalTail.TAPER_RATIO, + 'area': Aircraft.VerticalTail.AREA, + 'span': Aircraft.VerticalTail.SPAN, + 'rchord': Aircraft.VerticalTail.ROOT_CHORD, + 'chord': Aircraft.VerticalTail.AVERAGE_CHORD, + 'arm': Aircraft.VerticalTail.MOMENT_ARM, + } + + vol_coef = self.io_names['vol_coef'] + r_arm = self.io_names['r_arm'] + wing_ref = self.io_names['wing_ref'] + ar = self.io_names['ar'] + tr = self.io_names['tr'] + area = self.io_names['area'] + span = self.io_names['span'] + rchord = self.io_names['rchord'] + chord = self.io_names['chord'] + arm = self.io_names['arm'] + + add_aviary_input(self, vol_coef, units='unitless') + + add_aviary_input(self, Aircraft.Wing.AREA) + + add_aviary_input(self, r_arm, units='unitless') + add_aviary_input(self, wing_ref, units='ft') + add_aviary_input(self, ar, units='unitless') + add_aviary_input(self, tr, units='unitless') + + add_aviary_output(self, area, units='ft**2') + add_aviary_output(self, span, units='ft') + add_aviary_output(self, rchord, units='ft') + add_aviary_output(self, chord, units='ft') + add_aviary_output(self, arm, units='ft') def setup_partials(self): - self.declare_partials("area", ["vol_coef", Aircraft.Wing.AREA, "r_arm"]) - self.declare_partials("span", ["vol_coef", Aircraft.Wing.AREA, "r_arm", "ar"]) - self.declare_partials( - "rchord", ["vol_coef", Aircraft.Wing.AREA, "r_arm", "ar", "tr"] - ) - self.declare_partials( - "chord", ["vol_coef", Aircraft.Wing.AREA, "r_arm", "ar", "tr"] - ) - self.declare_partials("arm", ["r_arm", "wing_ref"]) + vol_coef = self.io_names['vol_coef'] + r_arm = self.io_names['r_arm'] + wing_ref = self.io_names['wing_ref'] + ar = self.io_names['ar'] + tr = self.io_names['tr'] + area = self.io_names['area'] + span = self.io_names['span'] + rchord = self.io_names['rchord'] + chord = self.io_names['chord'] + arm = self.io_names['arm'] + + self.declare_partials(area, [vol_coef, Aircraft.Wing.AREA, r_arm]) + self.declare_partials(span, [vol_coef, Aircraft.Wing.AREA, r_arm, ar]) + self.declare_partials(rchord, [vol_coef, Aircraft.Wing.AREA, r_arm, ar, tr]) + self.declare_partials(chord, [vol_coef, Aircraft.Wing.AREA, r_arm, ar, tr]) + self.declare_partials(arm, [r_arm, wing_ref]) def compute(self, inputs, outputs): + str_area = self.io_names['area'] + str_span = self.io_names['span'] + str_rchord = self.io_names['rchord'] + str_chord = self.io_names['chord'] + str_arm = self.io_names['arm'] + vol_coef, wing_area, r_arm, wing_ref, ar, tr = inputs.values() area = vol_coef * wing_area * r_arm @@ -162,41 +182,52 @@ def compute(self, inputs, outputs): chord = 2 / 3.0 * rchord * ((1 + tr) - (tr / (1 + tr))) arm = wing_ref / r_arm - outputs["area"] = area - outputs["span"] = span - outputs["rchord"] = rchord - outputs["chord"] = chord - outputs["arm"] = arm + outputs[str_area] = area + outputs[str_span] = span + outputs[str_rchord] = rchord + outputs[str_chord] = chord + outputs[str_arm] = arm def compute_partials(self, inputs, J): + str_vol_coef = self.io_names['vol_coef'] + str_r_arm = self.io_names['r_arm'] + str_wing_ref = self.io_names['wing_ref'] + str_ar = self.io_names['ar'] + str_tr = self.io_names['tr'] + str_area = self.io_names['area'] + str_span = self.io_names['span'] + str_rchord = self.io_names['rchord'] + str_chord = self.io_names['chord'] + str_arm = self.io_names['arm'] + vol_coef, wing_area, r_arm, wing_ref, ar, tr = inputs.values() - J["area", "vol_coef"] = wing_area * r_arm - J["area", Aircraft.Wing.AREA] = vol_coef * r_arm - J["area", "r_arm"] = vol_coef * wing_area + J[str_area, str_vol_coef] = wing_area * r_arm + J[str_area, Aircraft.Wing.AREA] = vol_coef * r_arm + J[str_area, str_r_arm] = vol_coef * wing_area cse1 = np.sqrt(vol_coef * wing_area * r_arm * ar) - J["span", "vol_coef"] = cse1 / (2 * vol_coef) - J["span", Aircraft.Wing.AREA] = cse1 / (2 * wing_area) - J["span", "r_arm"] = cse1 / (2 * r_arm) - J["span", "ar"] = cse1 / (2 * ar) + J[str_span, str_vol_coef] = cse1 / (2 * vol_coef) + J[str_span, Aircraft.Wing.AREA] = cse1 / (2 * wing_area) + J[str_span, str_r_arm] = cse1 / (2 * r_arm) + J[str_span, str_ar] = cse1 / (2 * ar) cse2 = cse1 * (tr + 1) - J["rchord", "vol_coef"] = wing_area * r_arm / cse2 - J["rchord", Aircraft.Wing.AREA] = vol_coef * r_arm / cse2 - J["rchord", "r_arm"] = wing_area * vol_coef / cse2 - J["rchord", "ar"] = -vol_coef * wing_area * r_arm / (ar * cse2) - J["rchord", "tr"] = -2 * vol_coef * wing_area * r_arm / (cse2 * (tr + 1)) + J[str_rchord, str_vol_coef] = wing_area * r_arm / cse2 + J[str_rchord, Aircraft.Wing.AREA] = vol_coef * r_arm / cse2 + J[str_rchord, str_r_arm] = wing_area * vol_coef / cse2 + J[str_rchord, str_ar] = -vol_coef * wing_area * r_arm / (ar * cse2) + J[str_rchord, str_tr] = -2 * vol_coef * wing_area * r_arm / (cse2 * (tr + 1)) cse3 = tr - (tr / (tr + 1)) + 1 - J["chord", "vol_coef"] = 2 / 3.0 * wing_area * r_arm * cse3 / cse2 - J["chord", Aircraft.Wing.AREA] = 2 / 3.0 * vol_coef * r_arm * cse3 / cse2 - J["chord", "r_arm"] = 2 / 3.0 * vol_coef * wing_area * cse3 / cse2 - J["chord", "ar"] = -2 / 3.0 * vol_coef * wing_area * r_arm * cse3 / (ar * cse2) - J["chord", "tr"] = 4 / 3.0 * cse1 * (tr - 1) / (ar * (tr + 1) ** 3) + J[str_chord, str_vol_coef] = 2 / 3.0 * wing_area * r_arm * cse3 / cse2 + J[str_chord, Aircraft.Wing.AREA] = 2 / 3.0 * vol_coef * r_arm * cse3 / cse2 + J[str_chord, str_r_arm] = 2 / 3.0 * vol_coef * wing_area * cse3 / cse2 + J[str_chord, str_ar] = -2 / 3.0 * vol_coef * wing_area * r_arm * cse3 / (ar * cse2) + J[str_chord, str_tr] = 4 / 3.0 * cse1 * (tr - 1) / (ar * (tr + 1) ** 3) - J["arm", "r_arm"] = -wing_ref / r_arm**2 - J["arm", "wing_ref"] = 1.0 / r_arm + J[str_arm, str_r_arm] = -wing_ref / r_arm**2 + J[str_arm, str_wing_ref] = 1.0 / r_arm class EmpennageSize(om.Group): @@ -207,10 +238,8 @@ class EmpennageSize(om.Group): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF) + add_aviary_option(self, Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF) def setup(self): # TODO: For cruciform/T-tail configurations, GASP checks to make sure the V tail @@ -220,114 +249,31 @@ def setup(self): # overrides the H tail aspect ratio. H tail taper ratio is used in landing gear # mass calculation. - aviary_options = self.options['aviary_options'] - - # higher inputs that are input to groups other than this one, or calculated in groups other than this one - higher_level_inputs_htail_vc = [ - ("cab_w", Aircraft.Fuselage.AVG_DIAMETER), - ("wing_ref", Aircraft.Wing.AVERAGE_CHORD), - ] - higher_level_inputs_vtail_vc = [ - ("cab_w", Aircraft.Fuselage.AVG_DIAMETER), - ("wing_ref", Aircraft.Wing.SPAN), - ] - higher_level_inputs_htail = [ - ("wing_ref", Aircraft.Wing.AVERAGE_CHORD), - ("tr", Aircraft.HorizontalTail.TAPER_RATIO), - ] - higher_level_inputs_vtail = [ - ("wing_ref", Aircraft.Wing.SPAN), - ("ar", Aircraft.VerticalTail.ASPECT_RATIO), - ] - - # inputs to htail and vtail that are purely promoted to change the name - rename_inputs_htail = [ - ("r_arm", Aircraft.HorizontalTail.MOMENT_RATIO), - ("ar", Aircraft.HorizontalTail.ASPECT_RATIO), - ] - rename_inputs_vtail = [ - ("r_arm", Aircraft.VerticalTail.MOMENT_RATIO), - ("tr", Aircraft.VerticalTail.TAPER_RATIO), - ] - - # outputs that are used in groups other than this one - higher_level_outputs_htail = [ - ("area", Aircraft.HorizontalTail.AREA), - ("span", Aircraft.HorizontalTail.SPAN), - ("rchord", Aircraft.HorizontalTail.ROOT_CHORD), - ("arm", Aircraft.HorizontalTail.MOMENT_ARM), - ] - higher_level_outputs_vtail = [ - ("area", Aircraft.VerticalTail.AREA), - ("span", Aircraft.VerticalTail.SPAN), - ("rchord", Aircraft.VerticalTail.ROOT_CHORD), - ("arm", Aircraft.VerticalTail.MOMENT_ARM), - ] - - # outputs from htail and vtail that are purely promoted to change the name - rename_outputs_htail = [ - ("chord", Aircraft.HorizontalTail.AVERAGE_CHORD), - ] - rename_outputs_vtail = [ - ("chord", Aircraft.VerticalTail.AVERAGE_CHORD), - ] - - # outputs from components in this group that are used in this group - connected_outputs_htail_vc = [ - ("vol_coef", Aircraft.HorizontalTail.VOLUME_COEFFICIENT), - ] - connected_outputs_vtail_vc = [ - ("vol_coef", Aircraft.VerticalTail.VOLUME_COEFFICIENT), - ] - - # inputs to components in this group that are calculated in this group - connected_inputs_htail = [ - ("vol_coef", Aircraft.HorizontalTail.VOLUME_COEFFICIENT), - ] - connected_inputs_vtail = [ - ("vol_coef", Aircraft.VerticalTail.VOLUME_COEFFICIENT), - ] - - if self.options["aviary_options"].get_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, units='unitless'): + if self.options[Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF]: self.add_subsystem( - "htail_vc", - TailVolCoef(aviary_options=aviary_options), - promotes_inputs=higher_level_inputs_htail_vc + ["aircraft:*"], - promotes_outputs=connected_outputs_htail_vc, + 'htail_vc', + TailVolCoef(orientation='horizontal'), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - if self.options["aviary_options"].get_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, units='unitless'): + if self.options[Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF]: self.add_subsystem( - "vtail_vc", - TailVolCoef(aviary_options=aviary_options, vertical=True), - promotes_inputs=higher_level_inputs_vtail_vc + ["aircraft:*"], - promotes_outputs=connected_outputs_vtail_vc, + 'vtail_vc', + TailVolCoef(orientation='vertical'), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "htail", - TailSize(aviary_options=aviary_options,), - promotes_inputs=higher_level_inputs_htail - + rename_inputs_htail - + connected_inputs_htail - + ["aircraft:*"], - promotes_outputs=higher_level_outputs_htail + rename_outputs_htail, + 'htail', + TailSize(orientation='horizontal'), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "vtail", - TailSize(aviary_options=aviary_options,), - promotes_inputs=higher_level_inputs_vtail - + rename_inputs_vtail - + connected_inputs_vtail - + ["aircraft:*"], - promotes_outputs=higher_level_outputs_vtail + rename_outputs_vtail, + 'vtail', + TailSize(orientation='vertical'), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - - self.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 12.615, units="ft") - self.set_input_defaults(Aircraft.Wing.SPAN, 117.8054, units="ft") - - # override horizontal tail defaults - self.set_input_defaults(Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145) - self.set_input_defaults(Aircraft.VerticalTail.MOMENT_RATIO, 2.362) - self.set_input_defaults(Aircraft.VerticalTail.ASPECT_RATIO, 1.67) - self.set_input_defaults(Aircraft.VerticalTail.TAPER_RATIO, 0.801) diff --git a/aviary/subsystems/geometry/gasp_based/engine.py b/aviary/subsystems/geometry/gasp_based/engine.py index b39c7f8361..4db777dbec 100644 --- a/aviary/subsystems/geometry/gasp_based/engine.py +++ b/aviary/subsystems/geometry/gasp_based/engine.py @@ -1,46 +1,197 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Mission, Settings + +epsilon = 0.05 + + +def f(x): + """Valid for x in [0.0, 1.0].""" + diff = 0.5 - x + y = 1.0 - np.arccos(2.0 * diff) / np.pi + return y + + +def df(x): + """First derivative of f(x), valid for x in (0.0, 1.0).""" + diff = 0.5 - x + dy = -2.0 / np.sqrt(1.0 - 4 * diff * diff) / np.pi + return dy + + +def d2f(x): + """Second derivative of f(x), valid for x in (0.0, 1.0).""" + diff = 0.5 - x + d2y = 8.0 * diff / np.sqrt(1.0 - 4 * diff * diff) / (1.0 - 4 * diff * diff) / np.pi + return d2y + + +def g1(x): + """ + Returns a cubic function g1(x) such that: + g1(0) = 1 + g1(ε) = f(ε) + g1'(ε) = f'(ε) + g1"(ε) = f"(ε). + """ + A1 = f(epsilon) + B1 = df(epsilon) + C1 = d2f(epsilon) + d1 = (A1 - 1 - epsilon * B1 + 0.5 * epsilon**2 * C1) / epsilon**3 + c1 = (C1 - 6 * d1 * epsilon) / 2 + b1 = B1 - epsilon * C1 + 3 * d1 * epsilon**2 + a1 = 1 + y = a1 + b1 * x + c1 * x**2 + d1 * x**3 + return y + + +def dg1(x): + """First derivative of g1(x).""" + A1 = f(epsilon) + B1 = df(epsilon) + C1 = d2f(epsilon) + d1 = (A1 - 1 - epsilon * B1 + 0.5 * epsilon**2 * C1) / epsilon**3 + c1 = (C1 - 6 * d1 * epsilon) / 2 + b1 = B1 - epsilon * C1 + 3 * d1 * epsilon**2 + dy = b1 + 2 * c1 * x + 3 * d1 * x**2 + return dy + + +def g2(x): + """ + Returns a cubic function g2(x) such that: + g2(1) = 0 + g2(ε) = f(1-ε) + g2'(ε) = f'(1-ε) + g2"(ε) = f"(1-ε). + """ + delta = 1.0 - epsilon + A2 = f(delta) + B2 = df(delta) + C2 = d2f(delta) + d2 = -(A2 + B2 * epsilon + 0.5 * C2 * epsilon**2) / epsilon**3 + c2 = (C2 - 6.0 * d2 * delta) / 2.0 + b2 = B2 - C2 * delta + 3.0 * d2 * delta**2 + a2 = -(b2 + c2 + d2) + y = a2 + b2 * x + c2 * x**2 + d2 * x**3 + return y + + +def dg2(x): + """First derivative of g2(x).""" + delta = 1.0 - epsilon + A2 = f(delta) + B2 = df(delta) + C2 = d2f(delta) + d2 = -(A2 + B2 * epsilon + 0.5 * C2 * epsilon**2) / epsilon**3 + c2 = (C2 - 6.0 * d2 * delta) / 2.0 + b2 = B2 - C2 * delta + 3.0 * d2 * delta**2 + dy = b2 + 2 * c2 * x + 3.0 * d2 * x**2 + return dy + + +class PercentNotInFuselage(om.ExplicitComponent): + """ + For BWB, engine may be (partially) buried into fuselage. Compute the percentage of + corresponding surface area of nacelles not buried in fuselage. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input( + self, + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, + shape=num_engine_type, + units='unitless', + ) + + self.add_output('percent_exposed', shape=num_engine_type, units='unitless') + + def setup_partials(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + shape = np.arange(num_engine_type) + + self.declare_partials( + 'percent_exposed', + [Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE], + rows=shape, + cols=shape, + ) + + def compute(self, inputs, outputs): + x = inputs[Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE] + if x >= epsilon and x <= 1 - epsilon: + diff = 0.5 - x + pct_swn = 1.0 - np.arccos(2.0 * diff) / np.pi + elif x >= 0.0 and x < epsilon: + pct_swn = g1(x) + elif x <= 1.0 and x > 1 - epsilon: + pct_swn = g2(x) + else: + raise om.AnalysisError( + 'The parameter Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE is out of range.' + ) + + outputs['percent_exposed'] = pct_swn + + def compute_partials(self, inputs, J): + x = inputs[Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE] + if x >= epsilon and x <= 1 - epsilon: + diff = 0.5 - x + d_pct_swn = -2.0 / np.sqrt(1.0 - 4 * diff * diff) / np.pi + elif x >= 0.0 and x < epsilon: + d_pct_swn = dg1(x) + elif x <= 1.0 and x > 1 - epsilon: + d_pct_swn = dg2(x) + else: + raise om.AnalysisError( + 'The parameter Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE is out of range.' + ) + + J['percent_exposed', Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE] = d_pct_swn class EngineSize(om.ExplicitComponent): """ GASP engine geometry calculation. It returns Aircraft.Nacelle.AVG_DIAMETER, - Nacelle.AVG_LENGTH, and Aircraft.Nacelle.SURFACE_AREA. + Nacelle.AVG_LENGTH, and Aircraft.Nacelle.SURFACE_AREA. This does not follow GASP + algorithm exactly. """ def initialize(self): + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Settings.VERBOSITY) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + def setup(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input( + self, Aircraft.Engine.REFERENCE_DIAMETER, shape=num_engine_type, units='ft' + ) + add_aviary_input( + self, Aircraft.Engine.SCALE_FACTOR, shape=num_engine_type, units='unitless' ) + add_aviary_input( + self, Aircraft.Nacelle.CORE_DIAMETER_RATIO, shape=num_engine_type, units='unitless' + ) + add_aviary_input(self, Aircraft.Nacelle.FINENESS, shape=num_engine_type, units='unitless') + self.add_input('percent_exposed', val=np.ones(num_engine_type), units='unitless') - def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - - add_aviary_input(self, Aircraft.Engine.REFERENCE_DIAMETER, - np.full(num_engine_type, 5.8)) - add_aviary_input(self, Aircraft.Engine.SCALE_FACTOR, np.ones(num_engine_type)) - add_aviary_input(self, Aircraft.Nacelle.CORE_DIAMETER_RATIO, - np.full(num_engine_type, 1.25)) - add_aviary_input(self, Aircraft.Nacelle.FINENESS, np.full(num_engine_type, 2)) - - add_aviary_output(self, Aircraft.Nacelle.AVG_DIAMETER, - val=np.zeros(num_engine_type)) - add_aviary_output(self, Aircraft.Nacelle.AVG_LENGTH, - val=np.zeros(num_engine_type)) - add_aviary_output(self, Aircraft.Nacelle.SURFACE_AREA, - val=np.zeros(num_engine_type)) + add_aviary_output(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + add_aviary_output(self, Aircraft.Nacelle.AVG_LENGTH, shape=num_engine_type, units='ft') + add_aviary_output(self, Aircraft.Nacelle.SURFACE_AREA, shape=num_engine_type, units='ft**2') def setup_partials(self): # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) innames = [ @@ -50,28 +201,36 @@ def setup_partials(self): Aircraft.Nacelle.FINENESS, ] - self.declare_partials(Aircraft.Nacelle.AVG_DIAMETER, - innames[:-1], rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Nacelle.AVG_LENGTH, innames, - rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Nacelle.SURFACE_AREA, - innames, rows=shape, cols=shape, val=1.0) + self.declare_partials( + Aircraft.Nacelle.AVG_DIAMETER, innames[:-1], rows=shape, cols=shape, val=1.0 + ) + self.declare_partials(Aircraft.Nacelle.AVG_LENGTH, innames, rows=shape, cols=shape, val=1.0) + self.declare_partials( + Aircraft.Nacelle.SURFACE_AREA, + innames + ['percent_exposed'], + rows=shape, + cols=shape, + val=1.0, + ) def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] d_ref = inputs[Aircraft.Engine.REFERENCE_DIAMETER] scale_fac = inputs[Aircraft.Engine.SCALE_FACTOR] d_nac_eng = inputs[Aircraft.Nacelle.CORE_DIAMETER_RATIO] ld_nac = inputs[Aircraft.Nacelle.FINENESS] + if any(x <= 0.0 for x in scale_fac): + if verbosity > Verbosity.BRIEF: + print('Aircraft.Engine.SCALE_FACTOR must be positive.') d_eng = d_ref * np.sqrt(scale_fac) outputs[Aircraft.Nacelle.AVG_DIAMETER] = d_eng * d_nac_eng - outputs[Aircraft.Nacelle.AVG_LENGTH] = ( - ld_nac * outputs[Aircraft.Nacelle.AVG_DIAMETER] - ) + outputs[Aircraft.Nacelle.AVG_LENGTH] = ld_nac * outputs[Aircraft.Nacelle.AVG_DIAMETER] outputs[Aircraft.Nacelle.SURFACE_AREA] = ( np.pi * outputs[Aircraft.Nacelle.AVG_DIAMETER] * outputs[Aircraft.Nacelle.AVG_LENGTH] + * inputs['percent_exposed'] ) def compute_partials(self, inputs, J): @@ -96,15 +255,175 @@ def compute_partials(self, inputs, J): Aircraft.Engine.SCALE_FACTOR, Aircraft.Nacelle.CORE_DIAMETER_RATIO, ]: - J[Aircraft.Nacelle.AVG_LENGTH, wrt] = ( - J[Aircraft.Nacelle.AVG_DIAMETER, wrt] * ld_nac - ) - J[Aircraft.Nacelle.SURFACE_AREA, wrt] = np.pi * ( - J[Aircraft.Nacelle.AVG_DIAMETER, wrt] * l_nac - + J[Aircraft.Nacelle.AVG_LENGTH, wrt] * d_nac + J[Aircraft.Nacelle.AVG_LENGTH, wrt] = J[Aircraft.Nacelle.AVG_DIAMETER, wrt] * ld_nac + J[Aircraft.Nacelle.SURFACE_AREA, wrt] = ( + np.pi + * ( + J[Aircraft.Nacelle.AVG_DIAMETER, wrt] * l_nac + + J[Aircraft.Nacelle.AVG_LENGTH, wrt] * d_nac + ) + * inputs['percent_exposed'] ) J[Aircraft.Nacelle.AVG_LENGTH, Aircraft.Nacelle.FINENESS] = d_nac J[Aircraft.Nacelle.SURFACE_AREA, Aircraft.Nacelle.FINENESS] = ( - np.pi * J[Aircraft.Nacelle.AVG_LENGTH, Aircraft.Nacelle.FINENESS] * d_nac + np.pi + * J[Aircraft.Nacelle.AVG_LENGTH, Aircraft.Nacelle.FINENESS] + * d_nac + * inputs['percent_exposed'] + ) + J[Aircraft.Nacelle.SURFACE_AREA, 'percent_exposed'] = ( + np.pi * d_eng * d_nac_eng * ld_nac * d_eng * d_nac_eng + ) + + +class BWBEngineSize(om.ExplicitComponent): + """ + Engine geometry calculation for BWB. It returns Aircraft.Nacelle.AVG_DIAMETER, + Nacelle.AVG_LENGTH, and Aircraft.Nacelle.SURFACE_AREA. It follows the algorithm in GASP. + Users can use this component instead of EngineSize. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input( + self, Aircraft.Nacelle.CORE_DIAMETER_RATIO, shape=num_engine_type, units='unitless' + ) + add_aviary_input(self, Aircraft.Nacelle.FINENESS, shape=num_engine_type, units='unitless') + self.add_input('percent_exposed', val=np.ones(num_engine_type), units='unitless') + + add_aviary_output(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + add_aviary_output(self, Aircraft.Nacelle.AVG_LENGTH, shape=num_engine_type, units='ft') + add_aviary_output(self, Aircraft.Nacelle.SURFACE_AREA, shape=num_engine_type, units='ft**2') + + def setup_partials(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + shape = np.arange(num_engine_type) + self.declare_partials( + Aircraft.Nacelle.AVG_DIAMETER, + [ + Mission.Design.GROSS_MASS, + Aircraft.Nacelle.CORE_DIAMETER_RATIO, + ], + rows=shape, + cols=shape, + ) + self.declare_partials( + Aircraft.Nacelle.AVG_LENGTH, + [ + Mission.Design.GROSS_MASS, + Aircraft.Nacelle.CORE_DIAMETER_RATIO, + Aircraft.Nacelle.FINENESS, + ], + rows=shape, + cols=shape, + ) + self.declare_partials( + Aircraft.Nacelle.SURFACE_AREA, + [ + Mission.Design.GROSS_MASS, + Aircraft.Nacelle.CORE_DIAMETER_RATIO, + Aircraft.Nacelle.FINENESS, + 'percent_exposed', + ], + rows=shape, + cols=shape, + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + num_engine = self.options[Aircraft.Engine.NUM_ENGINES] + + gross_mass = inputs[Mission.Design.GROSS_MASS] + core_diam_ratio = inputs[Aircraft.Nacelle.CORE_DIAMETER_RATIO] + fineness_nac = inputs[Aircraft.Nacelle.FINENESS] + pct_exposed = inputs['percent_exposed'] + + area_engine = 0.3 * gross_mass / 1500.0 / num_engine + diam_engine = np.sqrt(4.0 * area_engine / np.pi) + diam_nacelle = core_diam_ratio * diam_engine + len_nacelle = fineness_nac * diam_nacelle + wet_area_nacelle = np.pi * diam_nacelle * len_nacelle * pct_exposed + + outputs[Aircraft.Nacelle.AVG_DIAMETER] = diam_nacelle + outputs[Aircraft.Nacelle.AVG_LENGTH] = len_nacelle + outputs[Aircraft.Nacelle.SURFACE_AREA] = wet_area_nacelle + + def compute_partials(self, inputs, J): + num_engine = self.options[Aircraft.Engine.NUM_ENGINES] + + gross_mass = inputs[Mission.Design.GROSS_MASS] + core_diam_ratio = inputs[Aircraft.Nacelle.CORE_DIAMETER_RATIO] + fineness_nac = inputs[Aircraft.Nacelle.FINENESS] + pct_exposed = inputs['percent_exposed'] + + area_engine = 0.3 * gross_mass / 1500.0 / num_engine + diam_engine = np.sqrt(4.0 * area_engine / np.pi) + diam_nacelle = core_diam_ratio * diam_engine + len_nacelle = fineness_nac * diam_nacelle + wet_area_nacelle = np.pi * diam_nacelle * len_nacelle * pct_exposed + + darea_engine_dgross_mass = 0.3 * np.ones(1) / 1500.0 / num_engine + ddiam_engine_dgross_mass = 2 / np.pi / diam_engine * darea_engine_dgross_mass + ddiam_nacelle_dgross_mass = core_diam_ratio * ddiam_engine_dgross_mass + ddiam_nacelle_dcore_diam_ratio = diam_engine + J[Aircraft.Nacelle.AVG_DIAMETER, Mission.Design.GROSS_MASS] = ddiam_nacelle_dgross_mass + J[Aircraft.Nacelle.AVG_DIAMETER, Aircraft.Nacelle.CORE_DIAMETER_RATIO] = ( + ddiam_nacelle_dcore_diam_ratio + ) + dlen_nacelle_dgross_mass = fineness_nac * ddiam_nacelle_dgross_mass + dlen_nacelle_dcore_diam_ratio = fineness_nac * ddiam_nacelle_dcore_diam_ratio + dlen_nacelle_dfineness_nac = diam_nacelle + J[Aircraft.Nacelle.AVG_LENGTH, Mission.Design.GROSS_MASS] = dlen_nacelle_dgross_mass + J[Aircraft.Nacelle.AVG_LENGTH, Aircraft.Nacelle.CORE_DIAMETER_RATIO] = ( + dlen_nacelle_dcore_diam_ratio + ) + J[Aircraft.Nacelle.AVG_LENGTH, Aircraft.Nacelle.FINENESS] = dlen_nacelle_dfineness_nac + dwet_area_nacelle_dgross_mass = ( + np.pi + * pct_exposed + * (ddiam_nacelle_dgross_mass * len_nacelle + diam_nacelle * dlen_nacelle_dgross_mass) + ) + dwet_area_nacelle_dcore_diam_ratio = ( + np.pi + * pct_exposed + * ( + ddiam_nacelle_dcore_diam_ratio * len_nacelle + + diam_nacelle * dlen_nacelle_dcore_diam_ratio + ) + ) + dwet_area_nacelle_dfineness_nac = ( + np.pi * pct_exposed * diam_nacelle * dlen_nacelle_dfineness_nac + ) + dwet_area_nacelle_dpct_exposed = np.pi * diam_nacelle * len_nacelle + J[Aircraft.Nacelle.SURFACE_AREA, Mission.Design.GROSS_MASS] = dwet_area_nacelle_dgross_mass + J[Aircraft.Nacelle.SURFACE_AREA, Aircraft.Nacelle.CORE_DIAMETER_RATIO] = ( + dwet_area_nacelle_dcore_diam_ratio + ) + J[Aircraft.Nacelle.SURFACE_AREA, Aircraft.Nacelle.FINENESS] = ( + dwet_area_nacelle_dfineness_nac + ) + J[Aircraft.Nacelle.SURFACE_AREA, 'percent_exposed'] = dwet_area_nacelle_dpct_exposed + + +class BWBEngineSizeGroup(om.Group): + def setup(self): + self.add_subsystem( + 'perc', + PercentNotInFuselage(), + promotes_inputs=['*'], + promotes_outputs=['percent_exposed'], + ) + + self.add_subsystem( + 'eng_size', + BWBEngineSize(), + promotes_inputs=['*'] + ['percent_exposed'], + promotes_outputs=['*'], ) diff --git a/aviary/subsystems/geometry/gasp_based/fuselage.py b/aviary/subsystems/geometry/gasp_based/fuselage.py index 9e6c3ffd03..985f17e608 100644 --- a/aviary/subsystems/geometry/gasp_based/fuselage.py +++ b/aviary/subsystems/geometry/gasp_based/fuselage.py @@ -1,82 +1,69 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues +from aviary.utils.functions import sigmoidX from aviary.variable_info.enums import Verbosity -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Settings -def sigX(x): - sig = 1 / (1 + np.exp(-x)) - - return sig - - -def dSigXdX(x): - derivative = -1 / (1 + np.exp(-x)) ** 2 * (-1 * np.exp(-x)) - - return derivative - - class FuselageParameters(om.ExplicitComponent): - """ - Computation of average fuselage diameter, cabin height, cabin length and nose height. - """ + """Computation of average fuselage diameter, cabin height, cabin length and nose height.""" def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.Fuselage.AISLE_WIDTH, units='inch') + add_aviary_option(self, Aircraft.Fuselage.NUM_AISLES) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST) + add_aviary_option(self, Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, units='inch') + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH, units='inch') + add_aviary_option(self, Settings.VERBOSITY) def setup(self): + add_aviary_input(self, Aircraft.Fuselage.DELTA_DIAMETER, units='ft') - add_aviary_input(self, Aircraft.Fuselage.DELTA_DIAMETER, val=4.5) - add_aviary_input(self, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, val=9.5) - - add_aviary_output(self, Aircraft.Fuselage.AVG_DIAMETER, val=0, units='inch') - self.add_output("cabin_height", val=0, units="ft", desc="HC: height of cabin") - self.add_output("cabin_len", val=0, units="ft", desc="LC: length of cabin") - self.add_output("nose_height", val=0, units="ft", desc="HN: height of nose") + add_aviary_output(self, Aircraft.Fuselage.AVG_DIAMETER, units='inch') + self.add_output('cabin_height', val=0, units='ft', desc='HC: height of cabin') + self.add_output('cabin_len', val=0, units='ft', desc='LC: length of cabin') + self.add_output('nose_height', val=0, units='ft', desc='HN: height of nose') self.declare_partials( - "cabin_height", + 'cabin_height', [ Aircraft.Fuselage.DELTA_DIAMETER, ], ) self.declare_partials( - "nose_height", + 'nose_height', [ Aircraft.Fuselage.DELTA_DIAMETER, ], ) def compute(self, inputs, outputs): - verbosity = self.options['aviary_options'].get_val(Settings.VERBOSITY) - aviary_options: AviaryValues = self.options['aviary_options'] - seats_abreast = aviary_options.get_val(Aircraft.Fuselage.NUM_SEATS_ABREAST) - seat_width = aviary_options.get_val(Aircraft.Fuselage.SEAT_WIDTH, units='inch') - num_aisle = aviary_options.get_val(Aircraft.Fuselage.NUM_AISLES) - aisle_width = aviary_options.get_val(Aircraft.Fuselage.AISLE_WIDTH, units='inch') - PAX = aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) - seat_pitch = aviary_options.get_val(Aircraft.Fuselage.SEAT_PITCH, units='inch') + options = self.options + verbosity = options[Settings.VERBOSITY] + seats_abreast = options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST] + seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] + num_aisle = options[Aircraft.Fuselage.NUM_AISLES] + aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] + PAX = options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + seat_pitch, _ = options[Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST] + delta_diameter = inputs[Aircraft.Fuselage.DELTA_DIAMETER] cabin_width = seats_abreast * seat_width + num_aisle * aisle_width + 12 if PAX < 1: if verbosity >= Verbosity.BRIEF: - print("Warning: you have not specified at least one passenger") + print('Warning: you have not specified at least one passenger') # single seat across cabin_len_a = PAX * seat_pitch / 12 nose_height_a = cabin_width / 12 cabin_height_a = nose_height_a + delta_diameter - # multiple seats across + # multiple seats across, assuming no first class seats cabin_len_b = (PAX - 1) * seat_pitch / (seats_abreast * 12) cabin_height_b = cabin_width / 12 nose_height_b = cabin_height_b - delta_diameter @@ -84,62 +71,51 @@ def compute(self, inputs, outputs): outputs[Aircraft.Fuselage.AVG_DIAMETER] = cabin_width # There are separate equations for aircraft with a single seat per row vs. multiple seats per row. # Here and in compute_partials, these equations are smoothed using a sigmoid fnuction centered at - # 1.5 seats, the sigmoid function is steep enough that there should be no noticable difference + # 1.5 seats, the sigmoid function is steep enough that there should be no noticeable difference # between the smoothed function and the stepwise function at 1 and 2 seats. - outputs["cabin_height"] = cabin_height_a * sigX(100*(1.5-seats_abreast)) + \ - cabin_height_b*sigX(100*(seats_abreast-1.5)) - outputs["cabin_len"] = cabin_len_a * sigX(100*(1.5-seats_abreast)) + \ - cabin_len_b*sigX(100*(seats_abreast-1.5)) - outputs["nose_height"] = nose_height_a * sigX(100*(1.5-seats_abreast)) + \ - nose_height_b*sigX(100*(seats_abreast-1.5)) + sig1 = sigmoidX(seats_abreast, 1.5, -0.01) + sig2 = sigmoidX(seats_abreast, 1.5, 0.01) + outputs['cabin_height'] = cabin_height_a * sig1 + cabin_height_b * sig2 + outputs['cabin_len'] = cabin_len_a * sig1 + cabin_len_b * sig2 + outputs['nose_height'] = nose_height_a * sig1 + nose_height_b * sig2 def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - seats_abreast = aviary_options.get_val(Aircraft.Fuselage.NUM_SEATS_ABREAST) + options = self.options + seats_abreast = options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST] - J["nose_height", Aircraft.Fuselage.DELTA_DIAMETER] = sigX( - 100*(seats_abreast-1.5))*(-1) - J["cabin_height", Aircraft.Fuselage.DELTA_DIAMETER] = sigX( - 100*(1.5-seats_abreast))*1 + J['nose_height', Aircraft.Fuselage.DELTA_DIAMETER] = -sigmoidX(seats_abreast, 1.5, 0.01) + J['cabin_height', Aircraft.Fuselage.DELTA_DIAMETER] = sigmoidX(seats_abreast, 1.5, -0.01) class FuselageSize(om.ExplicitComponent): """ Computation of fuselage length, fuselage wetted area, and cabin length - for the tail boom fuselage. + for the tail boom fuselage. """ - def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - def setup(self): - - add_aviary_input(self, Aircraft.Fuselage.NOSE_FINENESS, val=1) - self.add_input("nose_height", val=0, units="ft", desc="HN: height of nose") - add_aviary_input(self, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, val=9.5) - self.add_input("cabin_len", val=0, units="ft", desc="LC: length of cabin") - add_aviary_input(self, Aircraft.Fuselage.TAIL_FINENESS, val=3) - self.add_input("cabin_height", val=0, units="ft", desc="HC: height of cabin") - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_SCALER, - val=1, units="unitless") - - add_aviary_output(self, Aircraft.Fuselage.LENGTH, val=0) - add_aviary_output(self, Aircraft.Fuselage.WETTED_AREA, val=0) - add_aviary_output(self, Aircraft.TailBoom.LENGTH, val=0) + add_aviary_input(self, Aircraft.Fuselage.NOSE_FINENESS, units='unitless') + self.add_input('nose_height', val=0, units='ft', desc='HN: height of nose') + add_aviary_input(self, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, units='ft') + self.add_input('cabin_len', val=0, units='ft', desc='LC: length of cabin') + add_aviary_input(self, Aircraft.Fuselage.TAIL_FINENESS, units='unitless') + self.add_input('cabin_height', val=0, units='ft', desc='HC: height of cabin') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_SCALER, units='unitless') + + add_aviary_output(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') + add_aviary_output(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + add_aviary_output(self, Aircraft.TailBoom.LENGTH, units='ft', desc='ELFFC') + add_aviary_output(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2', desc='ACABIN') self.declare_partials( Aircraft.Fuselage.LENGTH, [ Aircraft.Fuselage.NOSE_FINENESS, - "nose_height", + 'nose_height', Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, - "cabin_len", + 'cabin_len', Aircraft.Fuselage.TAIL_FINENESS, - "cabin_height", + 'cabin_height', ], ) @@ -147,11 +123,11 @@ def setup(self): Aircraft.Fuselage.WETTED_AREA, [ Aircraft.Fuselage.WETTED_AREA_SCALER, - "cabin_height", + 'cabin_height', Aircraft.Fuselage.NOSE_FINENESS, - "nose_height", + 'nose_height', Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, - "cabin_len", + 'cabin_len', Aircraft.Fuselage.TAIL_FINENESS, ], ) @@ -160,29 +136,30 @@ def setup(self): Aircraft.TailBoom.LENGTH, [ Aircraft.Fuselage.NOSE_FINENESS, - "nose_height", + 'nose_height', Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, - "cabin_len", + 'cabin_len', Aircraft.Fuselage.TAIL_FINENESS, - "cabin_height", + 'cabin_height', ], ) + self.declare_partials( + Aircraft.Fuselage.CABIN_AREA, + ['cabin_len', 'cabin_height', Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH], + ) + def compute(self, inputs, outputs): + # length to diameter ratio of nose cone of fuselage LoverD_nose = inputs[Aircraft.Fuselage.NOSE_FINENESS] LoverD_tail = inputs[Aircraft.Fuselage.TAIL_FINENESS] cockpit_len = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] fus_SA_scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] - nose_height = inputs["nose_height"] - cabin_len = inputs["cabin_len"] - cabin_height = inputs["cabin_height"] + nose_height = inputs['nose_height'] + cabin_len = inputs['cabin_len'] + cabin_height = inputs['cabin_height'] - fus_len = ( - LoverD_nose * nose_height - + cockpit_len - + cabin_len - + LoverD_tail * cabin_height - ) + fus_len = LoverD_nose * nose_height + cockpit_len + cabin_len + LoverD_tail * cabin_height fus_SA = cabin_height * ( 2.5 * (LoverD_nose * nose_height + cockpit_len) @@ -194,27 +171,31 @@ def compute(self, inputs, outputs): cabin_len_tailboom = fus_len + cabin_width = cabin_height # assume tube shape + cabin_area = cabin_width * (cockpit_len + cabin_len) + outputs[Aircraft.Fuselage.LENGTH] = fus_len outputs[Aircraft.Fuselage.WETTED_AREA] = fus_SA outputs[Aircraft.TailBoom.LENGTH] = cabin_len_tailboom + outputs[Aircraft.Fuselage.CABIN_AREA] = cabin_area def compute_partials(self, inputs, J): LoverD_nose = inputs[Aircraft.Fuselage.NOSE_FINENESS] LoverD_tail = inputs[Aircraft.Fuselage.TAIL_FINENESS] - nose_height = inputs["nose_height"] - cabin_height = inputs["cabin_height"] + nose_height = inputs['nose_height'] + cabin_height = inputs['cabin_height'] fus_SA_scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] cockpit_len = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] - cabin_len = inputs["cabin_len"] + cabin_len = inputs['cabin_len'] J[Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.NOSE_FINENESS] = nose_height - J[Aircraft.Fuselage.LENGTH, "nose_height"] = LoverD_nose + J[Aircraft.Fuselage.LENGTH, 'nose_height'] = LoverD_nose J[Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = 1 - J[Aircraft.Fuselage.LENGTH, "cabin_len"] = 1 + J[Aircraft.Fuselage.LENGTH, 'cabin_len'] = 1 J[Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.TAIL_FINENESS] = cabin_height - J[Aircraft.Fuselage.LENGTH, "cabin_height"] = LoverD_tail + J[Aircraft.Fuselage.LENGTH, 'cabin_height'] = LoverD_tail - J[Aircraft.Fuselage.WETTED_AREA, "cabin_height"] = fus_SA_scaler * ( + J[Aircraft.Fuselage.WETTED_AREA, 'cabin_height'] = fus_SA_scaler * ( 2.5 * (LoverD_nose * nose_height + cockpit_len) + 3.14 * cabin_len + 2.1 * LoverD_tail * cabin_height @@ -223,15 +204,13 @@ def compute_partials(self, inputs, J): J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.NOSE_FINENESS] = ( fus_SA_scaler * cabin_height * 2.5 * nose_height ) - J[Aircraft.Fuselage.WETTED_AREA, "nose_height"] = ( + J[Aircraft.Fuselage.WETTED_AREA, 'nose_height'] = ( fus_SA_scaler * cabin_height * 2.5 * LoverD_nose ) J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = ( fus_SA_scaler * cabin_height * 2.5 ) - J[Aircraft.Fuselage.WETTED_AREA, "cabin_len"] = ( - fus_SA_scaler * 3.14 * cabin_height - ) + J[Aircraft.Fuselage.WETTED_AREA, 'cabin_len'] = fus_SA_scaler * 3.14 * cabin_height J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.TAIL_FINENESS] = ( fus_SA_scaler * 2.1 * cabin_height**2 ) @@ -242,47 +221,786 @@ def compute_partials(self, inputs, J): ) J[Aircraft.TailBoom.LENGTH, Aircraft.Fuselage.NOSE_FINENESS] = nose_height - J[Aircraft.TailBoom.LENGTH, "nose_height"] = LoverD_nose + J[Aircraft.TailBoom.LENGTH, 'nose_height'] = LoverD_nose J[Aircraft.TailBoom.LENGTH, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = 1 - J[Aircraft.TailBoom.LENGTH, "cabin_len"] = 1 + J[Aircraft.TailBoom.LENGTH, 'cabin_len'] = 1 J[Aircraft.TailBoom.LENGTH, Aircraft.Fuselage.TAIL_FINENESS] = cabin_height - J[Aircraft.TailBoom.LENGTH, "cabin_height"] = LoverD_tail + J[Aircraft.TailBoom.LENGTH, 'cabin_height'] = LoverD_tail + + J[Aircraft.Fuselage.CABIN_AREA, 'cabin_len'] = cabin_height + J[Aircraft.Fuselage.CABIN_AREA, 'cabin_height'] = cabin_len + cockpit_len + J[Aircraft.Fuselage.CABIN_AREA, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = cabin_height class FuselageGroup(om.Group): + """Group to pull together FuselageParameters and FuselageSize.""" + + def setup(self): + # outputs from parameters that are used in size but not outside of this group + connected_input_outputs = ['cabin_height', 'cabin_len', 'nose_height'] + + self.add_subsystem( + 'parameters', + FuselageParameters(), + promotes_inputs=['*'], + promotes_outputs=['*'] + connected_input_outputs, + ) + + self.add_subsystem( + 'size', + FuselageSize(), + promotes_inputs=connected_input_outputs + ['*'], + promotes_outputs=['*'], + ) + + +class BWBFuselageParameters1(om.ExplicitComponent): + """Computation of average fuselage diameter, cabin height, cabin length and nose height for BWB.""" + + def initialize(self): + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.Fuselage.AISLE_WIDTH, units='inch') + add_aviary_option(self, Aircraft.Fuselage.NUM_AISLES) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST) + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH, units='inch') + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.DELTA_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, units='ft') + add_aviary_input(self, Aircraft.Fuselage.NOSE_FINENESS, units='unitless') + + add_aviary_output(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_output(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft', desc='DHYDRAL') + self.add_output('cabin_height', units='ft', desc='HC: height of cabin') + self.add_output('nose_height', units='ft', desc='HN: height of nose') + self.add_output('nose_length', units='ft', desc='L_NOSE: length of nose') + + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.AVG_DIAMETER, + [ + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, + ], + ) + self.declare_partials( + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + [ + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, + ], + ) + self.declare_partials( + 'cabin_height', + [ + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, + ], + ) + self.declare_partials( + 'nose_height', + [ + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, + Aircraft.Fuselage.DELTA_DIAMETER, + ], + ) + self.declare_partials( + 'nose_length', + [ + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, + Aircraft.Fuselage.DELTA_DIAMETER, + Aircraft.Fuselage.NOSE_FINENESS, + ], + ) + + def compute(self, inputs, outputs): + options = self.options + verbosity = options[Settings.VERBOSITY] + + seats_abreast = options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST] + seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] + num_aisle = options[Aircraft.Fuselage.NUM_AISLES] + aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] + PAX = options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] + cabin_width = (seats_abreast * seat_width + num_aisle * aisle_width) / 12.0 + 1.0 + body_width = cabin_width + additional_width + + cabin_height = cabin_width * inputs[Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] + nose_height = cabin_height - inputs[Aircraft.Fuselage.DELTA_DIAMETER] + nose_length = nose_height * inputs[Aircraft.Fuselage.NOSE_FINENESS] + + if PAX < 1: + if verbosity >= Verbosity.BRIEF: + print('Warning: you have not specified at least one passenger') + + fuselage_cross_area = np.pi * body_width * cabin_height / 4.0 + hydraulic_diameter = np.sqrt(4.0 * fuselage_cross_area / np.pi) + + outputs[Aircraft.Fuselage.AVG_DIAMETER] = body_width + outputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] = hydraulic_diameter + outputs['cabin_height'] = cabin_height + outputs['nose_height'] = nose_height + outputs['nose_length'] = nose_length + + def compute_partials(self, inputs, J): + options = self.options + + seats_abreast = options[Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST] + seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] + num_aisle = options[Aircraft.Fuselage.NUM_AISLES] + aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] + additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] + cabin_width = (seats_abreast * seat_width + num_aisle * aisle_width) / 12.0 + 1.0 + body_width = cabin_width + additional_width + + nose_height_to_length = inputs[Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] + delta_diameter = inputs[Aircraft.Fuselage.DELTA_DIAMETER] + nose_fineness = inputs[Aircraft.Fuselage.NOSE_FINENESS] + hydraulic_diameter = np.sqrt(body_width * cabin_width * nose_height_to_length) + + J[Aircraft.Fuselage.AVG_DIAMETER, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] = 1.0 + + J[Aircraft.Fuselage.HYDRAULIC_DIAMETER, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] = ( + 0.5 * cabin_width * nose_height_to_length / hydraulic_diameter + ) + J[Aircraft.Fuselage.HYDRAULIC_DIAMETER, Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] = ( + 0.5 * body_width * cabin_width / hydraulic_diameter + ) + + J['cabin_height', Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] = cabin_width + + J['nose_height', Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] = cabin_width + J['nose_height', Aircraft.Fuselage.DELTA_DIAMETER] = -1.0 + + J['nose_length', Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] = cabin_width * nose_fineness + J['nose_length', Aircraft.Fuselage.DELTA_DIAMETER] = -nose_fineness + J['nose_length', Aircraft.Fuselage.NOSE_FINENESS] = ( + cabin_width * nose_height_to_length - delta_diameter + ) + + +class BWBCabinLayout(om.ExplicitComponent): + """layout of passenger cabin for BWB.""" + + def initialize(self): + add_aviary_option(self, Aircraft.Fuselage.SEAT_WIDTH, units='inch', desc='INGASP.WS') + add_aviary_option(self, Aircraft.Fuselage.NUM_AISLES, units='unitless', desc='INGASP.AS') + add_aviary_option(self, Aircraft.Fuselage.AISLE_WIDTH, units='inch', desc='INGASP.WAS') + add_aviary_option( + self, Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, units='inch', desc='PS_FC' + ) + add_aviary_option( + self, Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, units='inch', desc='INGASP.PS' + ) + add_aviary_option( + self, Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless', desc='INGASP.PAX' + ) + add_aviary_option( + self, + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, + units='unitless', + desc='equiv INGASP.PCT_FC', + ) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input(self, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, units='deg') + add_aviary_input(self, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, units='ft') + self.add_input('nose_length', units='ft', desc='L_NOSE: nose length') + + self.add_output( + 'fuselage_station_aft', + units='ft', + desc='EL_AFT: fuselage station of aft pressure bulkhead', + ) + + self.declare_partials('*', '*', method='fd', form='forward') + + def compute(self, inputs, outputs): + options = self.options + verbosity = options[Settings.VERBOSITY] + rad2deg = 180.0 / np.pi + + # Hard code variables in GASP: + FC_lav_galley_length = 8.0 # EL_FLGC: length of first class lav, galley & closet, ft + FC_seat_width = 28.0 # WS_FC: first class seat width, inch + FC_seat_pitch, _ = options[Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST] + FC_num_aisles = 2 # AS_FC: num of aisles in first class + FC_aisle_width = 24.0 # WAS_FC: First class aisle width, inch + length_FC_to_TC = 5.0 # Length of first class/tourist class aisle, ft + TC_num_pax_per_lav = 78 # NLAVTC: tourist class passengers per lav + TC_lav_width = 42.0 # WIDLAV: Lav width, inches, in FLOPS, WIDTHL + TC_galley_area_per_pax = 0.15 # AGAL_TC: tourist class galley area per passenger, ft**2 + # If there is no first class cabin, please set NUM_FIRST_CLASS = 0. + + TC_seat_pitch, _ = options[Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST] + seat_width, _ = options[Aircraft.Fuselage.SEAT_WIDTH] + if seat_width <= 0.0: + raise ValueError('fuselage seat width must be positive.') + aisle_width, _ = options[Aircraft.Fuselage.AISLE_WIDTH] + num_aisles = options[Aircraft.Fuselage.NUM_AISLES] + + body_width = inputs[Aircraft.Fuselage.AVG_DIAMETER][0] + additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL][0] + cabin_width = body_width - additional_width + + sweep_FB = inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP][0] + pax = options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + pax_FC = options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + if pax_FC <= 0: + if verbosity > Verbosity.BRIEF: + print('Warning: No first class passengers or cabins are included.') + if pax_FC > pax: + raise ValueError( + 'Number of first class passengers must not exceed the total number of passengers.' + ) + pax_TC = pax - pax_FC + + nose_length = inputs['nose_length'][0] + pilot_com_length = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH][0] + if pax_FC > 0: + fwd_pax_fuselage_station = nose_length + pilot_com_length + FC_lav_galley_length + else: + fwd_pax_fuselage_station = nose_length + pilot_com_length + + # First Class + length_FC_by_row = [] # length in first class, ft + width_FC_by_row = [] # width in first class, ft + num_seats_FC_by_row = [] # num of seats in first class + sum_num_seats_FC = 0 + EL_FC_last_row = 0.0 + if pax_FC > 0: + EL_FC_ptr = fwd_pax_fuselage_station - FC_seat_pitch / 12.0 + + Idx_row_FC = -1 + while sum_num_seats_FC < pax_FC: + Idx_row_FC = Idx_row_FC + 1 + len = EL_FC_ptr + FC_seat_pitch / 12.0 + length_FC_by_row.append(len) + wid = 2.0 * length_FC_by_row[Idx_row_FC] / np.tan(sweep_FB / rad2deg) + wid = np.minimum(wid, cabin_width) + width_FC_by_row.append(wid) + wid_aisle = FC_num_aisles * FC_aisle_width / 12.0 + num = int((width_FC_by_row[Idx_row_FC] - wid_aisle) / FC_seat_width * 12.0) + num_seats_FC_by_row.append(num) + prev_sum_num_seats_FC = sum_num_seats_FC + sum_num_seats_FC = sum_num_seats_FC + num_seats_FC_by_row[Idx_row_FC] + EL_FC_ptr = length_FC_by_row[Idx_row_FC] + + # Last row of first class + EL_FC_last_row = length_FC_by_row[Idx_row_FC] + num_seats_last_row = pax_FC - prev_sum_num_seats_FC + # If only one seat in last row, delete last row & assume seat located forward + if num_seats_last_row < 2: + EL_FC_last_row = length_FC_by_row[Idx_row_FC - 1] + EL_FC_ptr = length_FC_by_row[Idx_row_FC - 1] + + sum_num_seats_FC = pax_FC + else: + # If not first class + EL_FC_last_row = 0 + + # First Class/Tourist Class Aisle + if pax_FC > 0: + EL_TC_ptr = EL_FC_last_row + FC_seat_pitch / 12.0 + else: + EL_TC_ptr = fwd_pax_fuselage_station + + # Tourist Class + if pax_FC > 0: + EL_TC_ptr = EL_TC_ptr + length_FC_to_TC - TC_seat_pitch / 12.0 + else: + EL_TC_ptr = EL_TC_ptr - TC_seat_pitch / 12.0 + length_TC_by_row = [] # length in tourist class, ft + width_TC_by_row = [] # width in tourist class, ft + num_seats_TC_by_row = [] # num of seats in tourist class + sum_num_seats_TC = 0 + Idx_row_TC = -1 + while sum_num_seats_TC < pax_TC: + Idx_row_TC = Idx_row_TC + 1 + len = EL_TC_ptr + TC_seat_pitch / 12.0 + length_TC_by_row.append(len) + wid = 2.0 * length_TC_by_row[Idx_row_TC] / np.tan(sweep_FB / rad2deg) + wid = np.minimum(wid, cabin_width) + width_TC_by_row.append(wid) + width_aisle = num_aisles * aisle_width / 12.0 + num = int((width_TC_by_row[Idx_row_TC] - width_aisle) / (seat_width / 12.0)) + num_seats_TC_by_row.append(num) + prev_num_seats_TC = sum_num_seats_TC + sum_num_seats_TC = sum_num_seats_TC + num_seats_TC_by_row[Idx_row_TC] + EL_TC_ptr = length_TC_by_row[Idx_row_TC] + + sum_num_seats_TC = pax_TC + # last row in tourist class: find number of seats in last row + num_seats_last_row = sum_num_seats_TC - prev_num_seats_TC + # find width available for last row for lavs/galleys (Assumes Steward's seat in TC aisle) + width_last_row = num_seats_last_row * seat_width / 12.0 + width_aisle = num_aisles * aisle_width / 12.0 + wid_last_row_avail = cabin_width - width_last_row - width_aisle + # find number of tourist class lavs and aft galley (galley width = lav width) + num_lav_TC = int(sum_num_seats_TC / TC_num_pax_per_lav) + 1 + wid_galley = 144.0 * sum_num_seats_TC * TC_galley_area_per_pax / TC_lav_width + + # find EL_AFT = fuselage station of aft pressure bulkhead. ft + if wid_last_row_avail >= num_lav_TC * TC_lav_width / 12.0 + wid_galley / 12.0: + # Add lavs/gallley to last row + EL_AFT = length_TC_by_row[Idx_row_TC] + TC_lav_width / 12.0 + else: + # add additional row for lavs & galleys to last row + EL_AFT = length_TC_by_row[Idx_row_TC] + TC_seat_pitch / 12.0 + TC_lav_width / 12.0 + + outputs['fuselage_station_aft'] = EL_AFT + + +class BWBFuselageParameters2(om.ExplicitComponent): """ - Group to pull together FuselageParameters and FuselageSize. + Computation of average fuselage diameter, cabin floor area, cabin length and + fuselage planform area. """ def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + def setup(self): + add_aviary_input(self, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, units='deg') + add_aviary_input(self, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, units='ft') + add_aviary_input(self, Aircraft.Fuselage.TAIL_FINENESS, units='unitless', desc='ELODT') + self.add_input( + 'fuselage_station_aft', + val=0.0, + units='ft', + desc='EL_AFT: fuselage station of aft pressure bulkhead', ) + self.add_input('nose_length', val=0.0, units='ft', desc='L_NOSE: length of nose') + self.add_input('cabin_height', val=0.0, units='ft', desc='HC: height of cabin') + + add_aviary_output(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2', desc='ACABIN') + add_aviary_output(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2', desc='SPF_BODY') + self.add_output('cabin_len', units='ft', desc='LC: length of cabin') + self.add_output('forebody_len', units='ft', desc='L_FBODY: length of forebody') + self.add_output('aftbody_len', units='ft', desc='L_ABODY: length of aftbody') + self.add_output('nose_area', units='ft**2', desc='A_NOSE: nose area') + + def setup_partials(self): + self.declare_partials( + 'cabin_len', + [ + 'fuselage_station_aft', + 'nose_length', + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, + ], + ) + + self.declare_partials( + 'forebody_len', + [ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, + ], + ) + + self.declare_partials( + 'aftbody_len', + [ + Aircraft.Fuselage.TAIL_FINENESS, + 'cabin_height', + ], + ) + + self.declare_partials( + 'nose_area', + [ + 'nose_length', + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, + ], + ) + + self.declare_partials( + Aircraft.Fuselage.CABIN_AREA, + [ + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, + 'fuselage_station_aft', + 'nose_length', + ], + ) + + self.declare_partials( + Aircraft.Fuselage.PLANFORM_AREA, + [ + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, + 'fuselage_station_aft', + 'nose_length', + 'cabin_height', + Aircraft.Fuselage.TAIL_FINENESS, + ], + ) + + def compute(self, inputs, outputs): + rad2deg = 180.0 / np.pi + + PASSENGER_LEADING_EDGE_SWEEP = inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] + body_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] + pilot_comp_len = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] + len_to_diam_tail_cone = inputs[Aircraft.Fuselage.TAIL_FINENESS] + nose_len = inputs['nose_length'] + cabin_height = inputs['cabin_height'] + fuselage_station_aft = inputs['fuselage_station_aft'] + + cabin_width = body_width - additional_width + forebody_len = 0.5 * cabin_width * np.tan(PASSENGER_LEADING_EDGE_SWEEP / rad2deg) + nose_width = 2.0 * nose_len / np.tan(PASSENGER_LEADING_EDGE_SWEEP / rad2deg) + aftbody_len = len_to_diam_tail_cone * cabin_height + cabin_len = fuselage_station_aft - nose_len - pilot_comp_len + + area_nose_planform = 0.5 * nose_len * nose_width + area_aftbody_planform = aftbody_len * (cabin_width + body_width) / 2.0 + area_forebody = (forebody_len - nose_len) * (body_width + nose_width) / 2.0 + area_aftbody = body_width * (fuselage_station_aft - forebody_len) + # Cabin Floor Area ("Home Plate" - without the nose) + area_cabin = area_forebody + area_aftbody + + # Planform Area of Body + area_body_planform = area_nose_planform + area_cabin + area_aftbody_planform + + outputs['cabin_len'] = cabin_len + outputs['forebody_len'] = forebody_len + outputs['aftbody_len'] = aftbody_len + outputs['nose_area'] = area_nose_planform + outputs[Aircraft.Fuselage.CABIN_AREA] = area_cabin + outputs[Aircraft.Fuselage.PLANFORM_AREA] = area_body_planform + + def compute_partials(self, inputs, J): + options = self.options + verbosity = options[Settings.VERBOSITY] + rad2deg = 180.0 / np.pi + + PASSENGER_LEADING_EDGE_SWEEP = inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] + body_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] + len_to_diam_tail_cone = inputs[Aircraft.Fuselage.TAIL_FINENESS] + nose_len = inputs['nose_length'] + cabin_height = inputs['cabin_height'] + fuselage_station_aft = inputs['fuselage_station_aft'] + + if PASSENGER_LEADING_EDGE_SWEEP <= 0.0 or PASSENGER_LEADING_EDGE_SWEEP >= 90.0: + if verbosity > Verbosity.BRIEF: + print('Forebody sweep angle must be between 0 and 90 degrees.') + fb_sweep_rad = PASSENGER_LEADING_EDGE_SWEEP / rad2deg + fb_tan = np.tan(fb_sweep_rad) + fb_cos = np.cos(fb_sweep_rad) + fb_dtan = 1.0 / rad2deg / (fb_cos * fb_cos) + + cabin_width = body_width - additional_width + + J['cabin_len', 'fuselage_station_aft'] = 1.0 + J['cabin_len', 'nose_length'] = -1.0 + J['cabin_len', Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = -1.0 + + J['forebody_len', Aircraft.Fuselage.AVG_DIAMETER] = 0.5 * fb_tan + J['forebody_len', Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = 0.5 * cabin_width * fb_dtan + J['forebody_len', Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] = -0.5 * fb_tan + + J['aftbody_len', Aircraft.Fuselage.TAIL_FINENESS] = cabin_height + J['aftbody_len', 'cabin_height'] = len_to_diam_tail_cone + + d_forebody_area_d_bd_width = 0.5 * fb_tan * (0.5 * body_width + nose_len / fb_tan) + ( + 0.5 * cabin_width * fb_tan - nose_len + ) * (0.5) + d_forebody_area_d_ns_length = ( + -(0.5 * body_width + nose_len / fb_tan) + + (0.5 * cabin_width * fb_tan - nose_len) / fb_tan + ) + d_forebody_area_d_add_length = -0.5 * fb_tan * (0.5 * body_width + nose_len / fb_tan) + d_forebody_area_d_sweep = (0.5 * cabin_width * fb_dtan) * ( + 0.5 * body_width + nose_len / fb_tan + ) - (0.5 * cabin_width * fb_tan - nose_len) * nose_len / fb_tan**2 * fb_dtan + d_aftbody_area_d_bd_width = ( + fuselage_station_aft - 0.5 * cabin_width * fb_tan - 0.5 * body_width * fb_tan + ) + d_aftbody_area_d_fuselage_aft = body_width + d_aftbody_area_d_additional = 0.5 * body_width * fb_tan + d_aftbody_area_d_sweep = -0.5 * body_width * cabin_width * fb_dtan + + # + # cabin_area = forebody + aftbody + # + d_cabin_area_d_body_len = d_forebody_area_d_bd_width + d_aftbody_area_d_bd_width + J[Aircraft.Fuselage.CABIN_AREA, Aircraft.Fuselage.AVG_DIAMETER] = d_cabin_area_d_body_len + + d_cabin_area_d_nose_len = d_forebody_area_d_ns_length + J[Aircraft.Fuselage.CABIN_AREA, 'nose_length'] = d_cabin_area_d_nose_len + + d_cabin_area_d_fuselage_aft = d_aftbody_area_d_fuselage_aft + J[Aircraft.Fuselage.CABIN_AREA, 'fuselage_station_aft'] = d_cabin_area_d_fuselage_aft + + d_cabin_area_d_additional = d_forebody_area_d_add_length + d_aftbody_area_d_additional + J[Aircraft.Fuselage.CABIN_AREA, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] = ( + d_cabin_area_d_additional + ) + + d_cabin_area_d_sweep = d_forebody_area_d_sweep + d_aftbody_area_d_sweep + J[Aircraft.Fuselage.CABIN_AREA, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = ( + d_cabin_area_d_sweep + ) + + d_nose_pf_area_d_nose_len = 2 * nose_len / fb_tan + J['nose_area', 'nose_length'] = d_nose_pf_area_d_nose_len + d_nose_pf_area_d_sweep = -nose_len * nose_len / fb_tan / fb_tan * fb_dtan + J['nose_area', Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = d_nose_pf_area_d_sweep + + d_tail_pf_area_d_tail_fineness = cabin_height * (body_width - 0.5 * additional_width) + d_tail_pf_area_d_both_width = len_to_diam_tail_cone * cabin_height + d_tail_pf_area_d_additional = -0.5 * len_to_diam_tail_cone * cabin_height + d_tail_pf_area_d_cabin_height = len_to_diam_tail_cone * ( + body_width - 0.5 * additional_width + ) + + # + # fuselage_planform_area = nose_area + cabin_area + tail_area + # + J[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = ( + d_nose_pf_area_d_sweep + d_cabin_area_d_sweep + ) + J[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Fuselage.AVG_DIAMETER] = ( + d_cabin_area_d_body_len + d_tail_pf_area_d_both_width + ) + J[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] = ( + d_cabin_area_d_additional + d_tail_pf_area_d_additional + ) + J[Aircraft.Fuselage.PLANFORM_AREA, 'fuselage_station_aft'] = d_cabin_area_d_fuselage_aft + J[Aircraft.Fuselage.PLANFORM_AREA, 'nose_length'] = ( + d_nose_pf_area_d_nose_len + d_cabin_area_d_nose_len + ) + J[Aircraft.Fuselage.PLANFORM_AREA, 'cabin_height'] = d_tail_pf_area_d_cabin_height + J[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Fuselage.TAIL_FINENESS] = ( + d_tail_pf_area_d_tail_fineness + ) + + +class BWBFuselageSize(om.ExplicitComponent): + """Computation of fuselage length and wetted area.""" + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) def setup(self): + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, units='ft') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, units='ft', desc='ELPC') + self.add_input('cabin_height', val=0.0, units='ft', desc='HC: height of cabin') + self.add_input('forebody_len', val=0.0, units='ft', desc='L_FBODY: forebody length') + self.add_input( + 'fuselage_station_aft', + val=0.0, + units='ft', + desc='EL_AFT: fuselage station of aft pressure bulkhead', + ) + self.add_input('nose_area', val=0.0, units='ft**2', desc='A_NOSE: nose area') + self.add_input('aftbody_len', val=0.0, units='ft', desc='L_ABODY: aftbody length') + self.add_input('nose_length', val=0.0, units='ft', desc='L_NOSE: nose length') + self.add_input('cabin_len', val=0.0, units='ft', desc='LC: cabin length') - aviary_options = self.options['aviary_options'] + add_aviary_output(self, Aircraft.Fuselage.LENGTH, units='ft', desc='ELF') + add_aviary_output(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2', desc='SF') + # tail boom support is not implemented in Aviary + add_aviary_output(self, Aircraft.TailBoom.LENGTH, units='ft', desc='ELFFC') - # outputs from parameters that are used in size but not outside of this group - connected_input_outputs = ["cabin_height", "cabin_len", "nose_height"] + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.LENGTH, + [ + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, + 'nose_length', + 'aftbody_len', + 'cabin_len', + ], + ) - parameters = self.add_subsystem( - "parameters", - FuselageParameters( - aviary_options=aviary_options, - ), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] + connected_input_outputs, + self.declare_partials( + Aircraft.TailBoom.LENGTH, + [ + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, + 'nose_length', + 'aftbody_len', + 'cabin_len', + ], ) - size = self.add_subsystem( - "size", - FuselageSize(aviary_options=aviary_options,), - promotes_inputs=connected_input_outputs + ["aircraft:*"], - promotes_outputs=["aircraft:*"], + self.declare_partials( + Aircraft.Fuselage.WETTED_AREA, + [ + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, + Aircraft.Fuselage.WETTED_AREA_SCALER, + 'cabin_height', + 'forebody_len', + 'nose_area', + 'aftbody_len', + 'fuselage_station_aft', + ], ) - self.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, val=9.5, units="ft") + def compute(self, inputs, outputs): + cockpit_len = inputs[Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] + cabin_len = inputs['cabin_len'] + nose_length = inputs['nose_length'] + aftbody_len = inputs['aftbody_len'] + + fuselage_length = nose_length + cockpit_len + cabin_len + aftbody_len + outputs[Aircraft.Fuselage.LENGTH] = fuselage_length + + cabin_len_tailboom = fuselage_length + outputs[Aircraft.TailBoom.LENGTH] = cabin_len_tailboom + + body_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] + fus_SA_scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] + fuselage_station_aft = inputs['fuselage_station_aft'] + cabin_height = inputs['cabin_height'] + forebody_len = inputs['forebody_len'] + nose_area = inputs['nose_area'] + + diag_a_c = np.sqrt(aftbody_len**2 + (cabin_height / 2.0) ** 2) + diag_a_a = np.sqrt(aftbody_len**2 + (additional_width / 2.0) ** 2) + diag_f_b = np.sqrt(forebody_len**2 + (body_width / 2.0) ** 2) + diag_f_c = np.sqrt(forebody_len**2 + (cabin_height / 2.0) ** 2) + + # use a simple prismatic surface area estimation + forebody_surface_area = cabin_height * diag_f_b + body_width * diag_f_c + + # just top and bottom surface area for cabin + cabin_surface_area = 2.0 * (body_width * (fuselage_station_aft - forebody_len) + nose_area) + + body_width_pass = body_width - additional_width + aftbody_surface_area = (body_width + body_width_pass) * diag_a_c + cabin_height * diag_a_a + + fuselage_wetted_area = forebody_surface_area + cabin_surface_area + aftbody_surface_area + # Adjust Fuselage Wetted Area by WETTED_AREA_SCALER + fuselage_wetted_area = fuselage_wetted_area * fus_SA_scaler + + outputs[Aircraft.Fuselage.WETTED_AREA] = fuselage_wetted_area + + def compute_partials(self, inputs, J): + J[Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = 1 + J[Aircraft.Fuselage.LENGTH, 'nose_length'] = 1 + J[Aircraft.Fuselage.LENGTH, 'aftbody_len'] = 1 + J[Aircraft.Fuselage.LENGTH, 'cabin_len'] = 1 + + J[Aircraft.TailBoom.LENGTH, Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH] = 1 + J[Aircraft.TailBoom.LENGTH, 'nose_length'] = 1 + J[Aircraft.TailBoom.LENGTH, 'aftbody_len'] = 1 + J[Aircraft.TailBoom.LENGTH, 'cabin_len'] = 1 + + body_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + additional_width = inputs[Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] + fus_SA_scaler = inputs[Aircraft.Fuselage.WETTED_AREA_SCALER] + fuselage_station_aft = inputs['fuselage_station_aft'] + cabin_height = inputs['cabin_height'] + forebody_len = inputs['forebody_len'] + nose_area = inputs['nose_area'] + aftbody_len = inputs['aftbody_len'] + body_width_pass = body_width - additional_width + + diag_a_c = np.sqrt(aftbody_len**2 + (cabin_height / 2.0) ** 2) + diag_a_a = np.sqrt(aftbody_len**2 + (additional_width / 2.0) ** 2) + diag_f_b = np.sqrt(forebody_len**2 + (body_width / 2.0) ** 2) + diag_f_c = np.sqrt(forebody_len**2 + (cabin_height / 2.0) ** 2) + + forebody_surface_area = cabin_height * diag_f_b + body_width * diag_f_c + cabin_surface_area = 2.0 * (body_width * (fuselage_station_aft - forebody_len) + nose_area) + aftbody_surface_area = (body_width + body_width_pass) * diag_a_c + cabin_height * diag_a_a + + d_fb_area_d_cabin_height = diag_f_b + body_width * cabin_height * 0.25 / diag_f_c + d_fb_area_d_fb_len = ( + cabin_height * forebody_len / diag_f_b + body_width * forebody_len / diag_f_c + ) + d_fb_area_d_wody_width = cabin_height * body_width * 0.25 / diag_f_b + diag_f_c + + d_cabin_area_d_body_width = 2.0 * (fuselage_station_aft - forebody_len) + d_cabin_area_d_station_aft = 2.0 * body_width + d_cabin_area_d_fb_len = -2.0 * body_width + d_cabin_area_d_nose_area = 2.0 + + d_aft_d_body_width = 2.0 * diag_a_c + d_aft_d_additional_width = -diag_a_c + cabin_height * additional_width * 0.25 * diag_a_c + d_aft_d_aft_len = ( + 2 * body_width - additional_width + ) * aftbody_len / diag_a_c + cabin_height * aftbody_len / diag_a_a + d_aft_d_cabin_height = ( + 2 * body_width - additional_width + ) * cabin_height * 0.25 / diag_a_c + diag_a_a + + # + # fuselage_wetted_area: + # (forebody_surface_area + cabin_surface_area + aftbody_surface_area) + # * fus_SA_scaler + # + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.WETTED_AREA_SCALER] = ( + forebody_surface_area + cabin_surface_area + aftbody_surface_area + ) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL] = ( + d_aft_d_additional_width * fus_SA_scaler + ) + J[Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.AVG_DIAMETER] = fus_SA_scaler * ( + d_fb_area_d_wody_width + d_cabin_area_d_body_width + d_aft_d_body_width + ) + + J[Aircraft.Fuselage.WETTED_AREA, 'cabin_height'] = ( + d_fb_area_d_cabin_height + d_aft_d_cabin_height + ) * fus_SA_scaler + J[Aircraft.Fuselage.WETTED_AREA, 'forebody_len'] = ( + d_fb_area_d_fb_len + d_cabin_area_d_fb_len + ) * fus_SA_scaler + J[Aircraft.Fuselage.WETTED_AREA, 'fuselage_station_aft'] = ( + d_cabin_area_d_station_aft * fus_SA_scaler + ) + J[Aircraft.Fuselage.WETTED_AREA, 'aftbody_len'] = d_aft_d_aft_len * fus_SA_scaler + J[Aircraft.Fuselage.WETTED_AREA, 'nose_area'] = d_cabin_area_d_nose_area * fus_SA_scaler + + +class BWBFuselageGroup(om.Group): + """ + Group to pull together BWBFuselageParameters1, BWBCabinLayout, BWBFuselageParameters2 + and BWBFuselageSize. + """ + + def setup(self): + self.add_subsystem( + 'parameters1', + BWBFuselageParameters1(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'layout', + BWBCabinLayout(), + promotes_inputs=['*'], + promotes_outputs=['fuselage_station_aft'], + ) + + self.add_subsystem( + 'parameters2', + BWBFuselageParameters2(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'size', + BWBFuselageSize(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) diff --git a/aviary/subsystems/geometry/gasp_based/non_dimensional_conversion.py b/aviary/subsystems/geometry/gasp_based/non_dimensional_conversion.py index 0fd18fdc97..54124166a9 100644 --- a/aviary/subsystems/geometry/gasp_based/non_dimensional_conversion.py +++ b/aviary/subsystems/geometry/gasp_based/non_dimensional_conversion.py @@ -1,152 +1,146 @@ import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class StrutCalcs(om.ExplicitComponent): - """ - Given strut location as a non-dimensional function of wing half-span or distance from aircraft center, compute the other value not provided. - """ + """Given strut location as a non-dimensional function of wing half-span or distance from aircraft center, compute the other value not provided.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) def setup(self): - add_aviary_input(self, Aircraft.Wing.SPAN, val=0) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') - if self.options["aviary_options"].get_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): - add_aviary_input(self, Aircraft.Strut.ATTACHMENT_LOCATION, val=0) + if self.options[Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED]: + add_aviary_input(self, Aircraft.Strut.ATTACHMENT_LOCATION, units='ft') add_aviary_output( - self, Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0) + self, Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, units='unitless' + ) else: add_aviary_input( - self, Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0) - add_aviary_output(self, Aircraft.Strut.ATTACHMENT_LOCATION, val=0) + self, Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, units='unitless' + ) + add_aviary_output(self, Aircraft.Strut.ATTACHMENT_LOCATION, units='ft') def setup_partials(self): - - if self.options["aviary_options"].get_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): + if self.options[Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED]: self.declare_partials( - Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, [Aircraft.Strut.ATTACHMENT_LOCATION, Aircraft.Wing.SPAN]) + Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, + [Aircraft.Strut.ATTACHMENT_LOCATION, Aircraft.Wing.SPAN], + ) else: self.declare_partials( - Aircraft.Strut.ATTACHMENT_LOCATION, [Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, Aircraft.Wing.SPAN]) + Aircraft.Strut.ATTACHMENT_LOCATION, + [Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, Aircraft.Wing.SPAN], + ) def compute(self, inputs, outputs): wing_span = inputs[Aircraft.Wing.SPAN] strut_loc_name = Aircraft.Strut.ATTACHMENT_LOCATION - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): - if self.options["aviary_options"].get_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): + if self.options[Aircraft.Wing.HAS_STRUT]: + if self.options[Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED]: strut_x = inputs[strut_loc_name] - outputs[strut_loc_name+"_dimensionless"] = strut_x / wing_span + outputs[strut_loc_name + '_dimensionless'] = strut_x / wing_span else: - strut_x = inputs[strut_loc_name+"_dimensionless"] + strut_x = inputs[strut_loc_name + '_dimensionless'] outputs[strut_loc_name] = strut_x * wing_span def compute_partials(self, inputs, partials): wing_span = inputs[Aircraft.Wing.SPAN] strut_loc_name = Aircraft.Strut.ATTACHMENT_LOCATION - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): - if self.options["aviary_options"].get_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): - partials[strut_loc_name+"_dimensionless", strut_loc_name] = 1 / wing_span - partials[strut_loc_name+"_dimensionless", - Aircraft.Wing.SPAN] = - inputs[strut_loc_name] / wing_span**2 + if self.options[Aircraft.Wing.HAS_STRUT]: + if self.options[Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED]: + partials[strut_loc_name + '_dimensionless', strut_loc_name] = 1 / wing_span + partials[strut_loc_name + '_dimensionless', Aircraft.Wing.SPAN] = ( + -inputs[strut_loc_name] / wing_span**2 + ) else: - partials[strut_loc_name, strut_loc_name+"_dimensionless"] = wing_span - partials[strut_loc_name, - Aircraft.Wing.SPAN] = inputs[strut_loc_name+"_dimensionless"] + partials[strut_loc_name, strut_loc_name + '_dimensionless'] = wing_span + partials[strut_loc_name, Aircraft.Wing.SPAN] = inputs[ + strut_loc_name + '_dimensionless' + ] class FoldCalcs(om.ExplicitComponent): - """ - Dimensional and non-dimensional conversion of fold calculation. - """ + """Dimensional and non-dimensional conversion of fold calculation.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED) def setup(self): - add_aviary_input(self, Aircraft.Wing.SPAN, val=0) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') - if self.options["aviary_options"].get_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): - add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN, val=25) - add_aviary_output(self, Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, val=0) + if self.options[Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED]: + add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN, units='ft') + add_aviary_output(self, Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, units='unitless') else: - add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, val=0) - add_aviary_output(self, Aircraft.Wing.FOLDED_SPAN, val=0) + add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, units='unitless') + add_aviary_output(self, Aircraft.Wing.FOLDED_SPAN, units='ft') def setup_partials(self): - - if self.options["aviary_options"].get_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): + if self.options[Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED]: self.declare_partials( - Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, [Aircraft.Wing.FOLDED_SPAN, Aircraft.Wing.SPAN]) + Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, + [Aircraft.Wing.FOLDED_SPAN, Aircraft.Wing.SPAN], + ) else: self.declare_partials( - Aircraft.Wing.FOLDED_SPAN, [Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, Aircraft.Wing.SPAN]) + Aircraft.Wing.FOLDED_SPAN, + [Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, Aircraft.Wing.SPAN], + ) def compute(self, inputs, outputs): wing_span = inputs[Aircraft.Wing.SPAN] folded_span_name = Aircraft.Wing.FOLDED_SPAN - if self.options["aviary_options"].get_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): + if self.options[Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED]: fold_y = inputs[folded_span_name] - outputs[folded_span_name+"_dimensionless"] = fold_y / wing_span + outputs[folded_span_name + '_dimensionless'] = fold_y / wing_span else: - fold_y = inputs[folded_span_name+"_dimensionless"] + fold_y = inputs[folded_span_name + '_dimensionless'] outputs[folded_span_name] = fold_y * wing_span def compute_partials(self, inputs, partials): wing_span = inputs[Aircraft.Wing.SPAN] folded_span_name = Aircraft.Wing.FOLDED_SPAN - if self.options["aviary_options"].get_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, units='unitless'): - partials[folded_span_name+"_dimensionless", folded_span_name] = 1 / wing_span - partials[folded_span_name+"_dimensionless", Aircraft.Wing.SPAN] = - \ - inputs[folded_span_name] / (wing_span**2) + if self.options[Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED]: + partials[folded_span_name + '_dimensionless', folded_span_name] = 1 / wing_span + partials[folded_span_name + '_dimensionless', Aircraft.Wing.SPAN] = -inputs[ + folded_span_name + ] / (wing_span**2) else: - partials[folded_span_name, folded_span_name+"_dimensionless"] = wing_span - partials[folded_span_name, - Aircraft.Wing.SPAN] = inputs[folded_span_name+"_dimensionless"] + partials[folded_span_name, folded_span_name + '_dimensionless'] = wing_span + partials[folded_span_name, Aircraft.Wing.SPAN] = inputs[ + folded_span_name + '_dimensionless' + ] class DimensionalNonDimensionalInterchange(om.Group): - """ - Dimensional and non-dimensional conversion of strut and fold calculation if any. - """ + """Dimensional and non-dimensional conversion of strut and fold calculation if any.""" def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) def setup(self): - - aviary_options = self.options['aviary_options'] - - if aviary_options.get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): + if self.options[Aircraft.Wing.HAS_STRUT]: self.add_subsystem( - "strut_calcs", - StrutCalcs(aviary_options=aviary_options,), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], + 'strut_calcs', + StrutCalcs(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - if aviary_options.get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): + if self.options[Aircraft.Wing.HAS_FOLD]: self.add_subsystem( - "fold_calcs", - FoldCalcs(aviary_options=aviary_options,), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], + 'fold_calcs', + FoldCalcs(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) diff --git a/aviary/subsystems/geometry/gasp_based/size_group.py b/aviary/subsystems/geometry/gasp_based/size_group.py index c17acae03c..251f1f0d40 100644 --- a/aviary/subsystems/geometry/gasp_based/size_group.py +++ b/aviary/subsystems/geometry/gasp_based/size_group.py @@ -2,66 +2,79 @@ from aviary.subsystems.geometry.gasp_based.electric import CableSize from aviary.subsystems.geometry.gasp_based.empennage import EmpennageSize -from aviary.subsystems.geometry.gasp_based.engine import EngineSize -from aviary.subsystems.geometry.gasp_based.fuselage import FuselageGroup -from aviary.subsystems.geometry.gasp_based.wing import WingGroup -from aviary.utils.aviary_values import AviaryValues +from aviary.subsystems.geometry.gasp_based.engine import EngineSize, BWBEngineSizeGroup +from aviary.subsystems.geometry.gasp_based.fuselage import FuselageGroup, BWBFuselageGroup +from aviary.subsystems.geometry.gasp_based.wing import WingGroup, BWBWingGroup +from aviary.variable_info.enums import AircraftTypes +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft class SizeGroup(om.Group): - - """ - Group to pull together all the different components and subgroups of the SIZE subroutine - - """ + """Group to pull together all the different components and subgroups of the SIZE subroutine.""" def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Electrical.HAS_HYBRID_SYSTEM) + add_aviary_option(self, Aircraft.Design.TYPE) def setup(self): - aviary_options = self.options['aviary_options'] + design_type = self.options[Aircraft.Design.TYPE] - self.add_subsystem( - "fuselage", - FuselageGroup( - aviary_options=aviary_options, - ), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'fuselage', + BWBFuselageGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'fuselage', + FuselageGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - self.add_subsystem( - "wing", - WingGroup( - aviary_options=aviary_options, - ), - promotes=["aircraft:*", "mission:*"], - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'wing', + BWBWingGroup(), + promotes=['*'], + ) + else: + self.add_subsystem( + 'wing', + WingGroup(), + promotes=['*'], + ) self.add_subsystem( - "empennage", - EmpennageSize(aviary_options=aviary_options,), - promotes=["aircraft:*"], + 'empennage', + EmpennageSize(), + promotes=['*'], ) - self.add_subsystem( - "engine", - EngineSize(aviary_options=aviary_options,), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'engine', + BWBEngineSizeGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'engine', + EngineSize(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - if self.options["aviary_options"].get_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, units='unitless'): + if self.options[Aircraft.Electrical.HAS_HYBRID_SYSTEM]: self.add_subsystem( - "cable", - CableSize(aviary_options=aviary_options,), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], + 'cable', + CableSize(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - self.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, units="inch") + self.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, units='inch') diff --git a/aviary/subsystems/geometry/gasp_based/strut.py b/aviary/subsystems/geometry/gasp_based/strut.py index c6443cc4dc..ef5fe894e1 100644 --- a/aviary/subsystems/geometry/gasp_based/strut.py +++ b/aviary/subsystems/geometry/gasp_based/strut.py @@ -3,42 +3,28 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft class StrutGeom(om.ExplicitComponent): - """ - Computation of strut length, strut area, and strut chord for GASP-based geometry. - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + """Computation of strut length, strut area, and strut chord for GASP-based geometry.""" def setup(self): + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Strut.AREA_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Strut.ATTACHMENT_LOCATION, units='ft') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') - add_aviary_input(self, Aircraft.Wing.AREA, val=150) - add_aviary_input(self, Aircraft.Strut.AREA_RATIO, val=.2) - - add_aviary_input(self, Aircraft.Strut.ATTACHMENT_LOCATION, val=0, units="ft") - - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=10.0) - - self.add_output( - "strut_y", val=30, units="ft", desc="YSTRUT: attachment location of strut" - ) - add_aviary_output(self, Aircraft.Strut.LENGTH, val=1.0) - add_aviary_output(self, Aircraft.Strut.AREA, val=30) - add_aviary_output(self, Aircraft.Strut.CHORD, val=1.0) + self.add_output('strut_y', val=30, units='ft', desc='YSTRUT: attachment location of strut') + add_aviary_output(self, Aircraft.Strut.LENGTH, units='ft') + add_aviary_output(self, Aircraft.Strut.AREA, units='ft**2') + add_aviary_output(self, Aircraft.Strut.CHORD, units='ft') def setup_partials(self): - self.declare_partials( - "strut_y", [Aircraft.Strut.ATTACHMENT_LOCATION], + 'strut_y', + [Aircraft.Strut.ATTACHMENT_LOCATION], ) self.declare_partials( Aircraft.Strut.LENGTH, @@ -58,47 +44,39 @@ def setup_partials(self): ) self.declare_partials( Aircraft.Strut.AREA, - [ - Aircraft.Wing.AREA, - Aircraft.Strut.AREA_RATIO - ], + [Aircraft.Wing.AREA, Aircraft.Strut.AREA_RATIO], ) def compute(self, inputs, outputs): - strut_x = inputs[Aircraft.Strut.ATTACHMENT_LOCATION] wing_area = inputs[Aircraft.Wing.AREA] strut_wing_area_ratio = inputs[Aircraft.Strut.AREA_RATIO] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - outputs["strut_y"] = strut_x / 2 + outputs['strut_y'] = strut_x / 2 - if outputs["strut_y"] < cabin_width / 2: + if outputs['strut_y'] < cabin_width / 2: warnings.warn( - "Strut attachment location on wing is inside fuselage, did you mean to do that?") + 'Strut attachment location on wing is inside fuselage, did you mean to do that?' + ) outputs[Aircraft.Strut.LENGTH] = np.sqrt( - (outputs["strut_y"] - cabin_width / 2) ** 2 + cabin_width**2 + (outputs['strut_y'] - cabin_width / 2) ** 2 + cabin_width**2 ) outputs[Aircraft.Strut.AREA] = strut_area = wing_area * strut_wing_area_ratio outputs[Aircraft.Strut.CHORD] = 0.5 * strut_area / outputs[Aircraft.Strut.LENGTH] def compute_partials(self, inputs, partials): - strut_x = inputs[Aircraft.Strut.ATTACHMENT_LOCATION] wing_area = inputs[Aircraft.Wing.AREA] strut_wing_area_ratio = inputs[Aircraft.Strut.AREA_RATIO] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - dstruty_dstrutx = partials[ - "strut_y", Aircraft.Strut.ATTACHMENT_LOCATION - ] = (1 / 2) + dstruty_dstrutx = partials['strut_y', Aircraft.Strut.ATTACHMENT_LOCATION] = 1 / 2 strut_y = strut_x / 2 strut_length = np.sqrt((strut_y - cabin_width / 2) ** 2 + cabin_width**2) - dlength_dstrutx = partials[ - Aircraft.Strut.LENGTH, Aircraft.Strut.ATTACHMENT_LOCATION - ] = ( + dlength_dstrutx = partials[Aircraft.Strut.LENGTH, Aircraft.Strut.ATTACHMENT_LOCATION] = ( 0.5 * ((strut_y - cabin_width / 2) ** 2 + cabin_width**2) ** -0.5 * 2 @@ -107,14 +85,7 @@ def compute_partials(self, inputs, partials): ) dlength_dwidth = partials[Aircraft.Strut.LENGTH, Aircraft.Fuselage.AVG_DIAMETER] = ( 5 * cabin_width - 2 * strut_y - ) / ( - 2 - * ( - np.sqrt( - 5 * cabin_width**2 - 4 * cabin_width * strut_y + 4 * strut_y**2 - ) - ) - ) + ) / (2 * (np.sqrt(5 * cabin_width**2 - 4 * cabin_width * strut_y + 4 * strut_y**2))) partials[Aircraft.Strut.CHORD, Aircraft.Strut.ATTACHMENT_LOCATION] = ( -1 * 0.5 * wing_area * strut_wing_area_ratio / strut_length**2 * dlength_dstrutx @@ -122,10 +93,10 @@ def compute_partials(self, inputs, partials): partials[Aircraft.Strut.CHORD, Aircraft.Fuselage.AVG_DIAMETER] = ( -1 * 0.5 * wing_area * strut_wing_area_ratio / strut_length**2 * dlength_dwidth ) - partials[Aircraft.Strut.CHORD, Aircraft.Wing.AREA] = 0.5 / \ - strut_length * strut_wing_area_ratio - partials[Aircraft.Strut.CHORD, Aircraft.Strut.AREA_RATIO] = 0.5 / \ - strut_length * wing_area + partials[Aircraft.Strut.CHORD, Aircraft.Wing.AREA] = ( + 0.5 / strut_length * strut_wing_area_ratio + ) + partials[Aircraft.Strut.CHORD, Aircraft.Strut.AREA_RATIO] = 0.5 / strut_length * wing_area partials[Aircraft.Strut.AREA, Aircraft.Wing.AREA] = strut_wing_area_ratio partials[Aircraft.Strut.AREA, Aircraft.Strut.AREA_RATIO] = wing_area diff --git a/aviary/subsystems/geometry/gasp_based/test/test_electric.py b/aviary/subsystems/geometry/gasp_based/test/test_electric.py index 05ac0bd71c..e09c55a97a 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_electric.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_electric.py @@ -3,37 +3,39 @@ import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs from aviary.subsystems.geometry.gasp_based.electric import CableSize -from aviary.variable_info.variables import Aircraft from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft +@use_tempdirs class ElectricTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem() aviary_options = AviaryValues() aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2) - self.prob.model.add_subsystem("cable", CableSize( - aviary_options=aviary_options), promotes=["*"]) + self.prob.model.add_subsystem('cable', CableSize(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, 0.35, units="unitless" + Aircraft.Engine.WING_LOCATIONS, 0.35, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, 128, units="ft" + Aircraft.Wing.SPAN, 128, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 10, units="ft" + Aircraft.Fuselage.AVG_DIAMETER, 10, units='ft' ) # not actual GASP value + setup_model_options(self.prob, aviary_options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 @@ -41,10 +43,11 @@ def test_case1(self): self.prob[Aircraft.Electrical.HYBRID_CABLE_LENGTH], 64.8, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) +@use_tempdirs class ElectricTestCaseMultiEngine(unittest.TestCase): def test_case_multiengine(self): prob = om.Problem() @@ -53,31 +56,26 @@ def test_case_multiengine(self): # aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 4])) aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 6) - prob.model.add_subsystem("cable", CableSize( - aviary_options=aviary_options), promotes=["*"]) + prob.model.add_subsystem('cable', CableSize(), promotes=['*']) prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, np.array([0.35, 0.2, 0.6]), units="unitless" - ) - prob.model.set_input_defaults( - Aircraft.Wing.SPAN, 128, units="ft" - ) - prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 10, units="ft" + Aircraft.Engine.WING_LOCATIONS, np.array([0.35, 0.2, 0.6]), units='unitless' ) + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 128, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 10, units='ft') + + setup_model_options(prob, aviary_options) prob.setup(check=False, force_alloc_complex=True) prob.run_model() tol = 1e-4 - assert_near_equal( - prob[Aircraft.Electrical.HYBRID_CABLE_LENGTH], 167.2, tol - ) + assert_near_equal(prob[Aircraft.Electrical.HYBRID_CABLE_LENGTH], 167.2, tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_empennage.py b/aviary/subsystems/geometry/gasp_based/test/test_empennage.py index d5eb4e8137..5100e72dd4 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_empennage.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_empennage.py @@ -1,17 +1,16 @@ import unittest -import os import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs -from aviary.subsystems.geometry.gasp_based.empennage import (EmpennageSize, - TailSize, - TailVolCoef) +from aviary.subsystems.geometry.gasp_based.empennage import EmpennageSize, TailSize, TailVolCoef +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft tol = 5e-4 -partial_tols = {"atol": 1e-8, "rtol": 1e-8} +partial_tols = {'atol': 1e-8, 'rtol': 1e-8} class TestTailVolCoef( @@ -20,51 +19,38 @@ class TestTailVolCoef( def setUp(self): self.prob = om.Problem() self.prob.model.add_subsystem( - "hvc", - TailVolCoef(vertical=False), - promotes_inputs=[ - "aircraft:*", - ], + 'hvc', + TailVolCoef(orientation='horizontal'), + promotes=['aircraft:*'], ) self.prob.model.add_subsystem( - "vvc", - TailVolCoef(vertical=True), - promotes_inputs=[ - "aircraft:*", - ], + 'vvc', + TailVolCoef(orientation='vertical'), + promotes=['aircraft:*'], ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=12.615, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) - self.prob.model.set_input_defaults("hvc.cab_w", val=13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" - ) - self.prob.model.set_input_defaults("hvc.wing_ref", val=12.615, units="ft") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" - ) - self.prob.model.set_input_defaults("vvc.cab_w", val=13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" - ) - self.prob.model.set_input_defaults("vvc.wing_ref", 117.8054, units="ft") + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, 117.8054, units='ft') self.prob.setup(check=False, force_alloc_complex=True) def test_large_sinle_aisle_1_volcoefs(self): self.prob.run_model() - assert_near_equal( - self.prob["hvc.vol_coef"], 1.52233, tol - ) # not actual GASP value - assert_near_equal( - self.prob["vvc.vol_coef"], 0.11623, tol - ) # not actual GASP value + + # These are not actual GASP values. + assert_near_equal(self.prob[Aircraft.HorizontalTail.VOLUME_COEFFICIENT], 1.52233, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.VOLUME_COEFFICIENT], 0.11623, tol) def test_partials(self): - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, **partial_tols) @@ -73,93 +59,99 @@ class TestTailComp( ): # this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem("tail", TailSize(), promotes=["*"]) - self.prob.setup(check=False, force_alloc_complex=True) - # values for horizontal tail - self.prob.model.set_input_defaults("vol_coef", val=1.189, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" - ) - self.prob.model.set_input_defaults("r_arm", val=0.2307, units="unitless") - self.prob.model.set_input_defaults("wing_ref", val=12.615, units="ft") - self.prob.model.set_input_defaults("ar", val=4.75, units="unitless") - self.prob.model.set_input_defaults("tr", val=0.352, units="unitless") + def test_large_single_aisle_1_htail(self): + prob = self.prob + prob.model.add_subsystem('tail', TailSize(orientation='horizontal'), promotes=['*']) - def test_large_sinle_aisle_1_htail(self): - self.prob.run_model() + prob.setup(check=False, force_alloc_complex=True) - assert_near_equal(self.prob["area"], 375.9, tol) - assert_near_equal(self.prob["span"], 42.25, tol) - assert_near_equal( - self.prob["rchord"], 13.16130387591471, tol - ) # (potentially not actual GASP value, it is calculated twice in different places) - assert_near_equal(self.prob["chord"], 9.57573, tol) - assert_near_equal(self.prob["arm"], 54.7, tol) - - def test_large_sinle_aisle_1_vtail(self): - # override horizontal tail defaults for vertical tail - self.prob.set_val("vol_coef", 0.145, units="unitless") - self.prob.set_val(Aircraft.Wing.AREA, 1370.3, units="ft**2") - self.prob.set_val("r_arm", 2.362, units="unitless") - self.prob.set_val("wing_ref", 117.8, units="ft") - self.prob.set_val("ar", 1.67, units="unitless") - self.prob.set_val("tr", 0.801, units="unitless") + prob.set_val(Aircraft.HorizontalTail.VOLUME_COEFFICIENT, 1.189, units='unitless') + prob.set_val(Aircraft.Wing.AREA, 1370.3, units='ft**2') + prob.set_val(Aircraft.HorizontalTail.MOMENT_RATIO, 0.2307, units='unitless') + prob.set_val(Aircraft.Wing.AVERAGE_CHORD, 12.615, units='ft') + prob.set_val(Aircraft.HorizontalTail.ASPECT_RATIO, 4.75, units='unitless') + prob.set_val(Aircraft.HorizontalTail.TAPER_RATIO, 0.352, units='unitless') - self.prob.run_model() + prob.run_model() - assert_near_equal(self.prob["area"], 469.3, tol) - assert_near_equal(self.prob["span"], 28, tol) - assert_near_equal(self.prob["rchord"], 18.61267549773935, tol) - assert_near_equal(self.prob["chord"], 16.83022, tol) - assert_near_equal( - self.prob["arm"], 49.87526, tol - ) # note: slightly different from GASP output value, likely truncation differences, this value is from Kenny + assert_near_equal(prob[Aircraft.HorizontalTail.AREA], 375.9, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.SPAN], 42.25, tol) - def test_partials(self): - partial_data = self.prob.check_partials(out_stream=None, method="cs") + # (potentially not actual GASP value, it is calculated twice in different places) + assert_near_equal(prob[Aircraft.HorizontalTail.ROOT_CHORD], 13.16130387591471, tol) + + assert_near_equal(prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.57573, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MOMENT_ARM], 54.7, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, **partial_tols) + + def test_large_single_aisle_1_vtail(self): + prob = self.prob + prob.model.add_subsystem('tail', TailSize(orientation='vertical'), promotes=['*']) + + prob.setup(check=False, force_alloc_complex=True) + + prob.set_val(Aircraft.Wing.AREA, 1370.3, units='ft**2') + prob.set_val(Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless') + prob.set_val(Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless') + prob.set_val(Aircraft.Wing.SPAN, 117.8, units='ft') + prob.set_val(Aircraft.VerticalTail.ASPECT_RATIO, 1.67, units='unitless') + prob.set_val(Aircraft.VerticalTail.TAPER_RATIO, 0.801, units='unitless') + + prob.run_model() + + assert_near_equal(prob[Aircraft.VerticalTail.AREA], 469.3, tol) + assert_near_equal(prob[Aircraft.VerticalTail.SPAN], 28, tol) + assert_near_equal(prob[Aircraft.VerticalTail.ROOT_CHORD], 18.61267549773935, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.83022, tol) + + # note: slightly different from GASP output value, likely truncation differences, this value is from Kenny + assert_near_equal(prob[Aircraft.VerticalTail.MOMENT_ARM], 49.87526, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, **partial_tols) +@use_tempdirs class TestEmpennageGroup( unittest.TestCase ): # this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem("emp", EmpennageSize(), promotes=["*"]) + self.prob.model.add_subsystem('emp', EmpennageSize(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=12.615, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.AVERAGE_CHORD, val=12.615, units="ft" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, val=0.145, units="unitless") + Aircraft.VerticalTail.VOLUME_COEFFICIENT, val=0.145, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, val=2.362, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") + Aircraft.VerticalTail.MOMENT_RATIO, val=2.362, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) def test_large_sinle_aisle_1_defaults(self): - self.prob.model.emp.options["aviary_options"] = get_option_defaults() - self.prob.setup(check=False, force_alloc_complex=True) self.prob.run_model() @@ -169,37 +161,32 @@ def test_large_sinle_aisle_1_defaults(self): assert_near_equal( self.prob[Aircraft.HorizontalTail.ROOT_CHORD], 13.16130387591471, tol ) # (potentially not actual GASP value, it is calculated twice in different places) - assert_near_equal( - self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.57573, tol - ) + assert_near_equal(self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.57573, tol) assert_near_equal(self.prob[Aircraft.HorizontalTail.MOMENT_ARM], 54.7, tol) assert_near_equal(self.prob[Aircraft.VerticalTail.AREA], 469.3, tol) assert_near_equal(self.prob[Aircraft.VerticalTail.SPAN], 28, tol) - assert_near_equal( - self.prob[Aircraft.VerticalTail.ROOT_CHORD], 18.61267549773935, tol - ) + assert_near_equal(self.prob[Aircraft.VerticalTail.ROOT_CHORD], 18.61267549773935, tol) assert_near_equal(self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.83022, tol) assert_near_equal( self.prob[Aircraft.VerticalTail.MOMENT_ARM], 49.87526, tol ) # note: slightly different from GASP output value, likely numerical diff.s, this value is from Kenny - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, **partial_tols) def test_large_sinle_aisle_1_calc_volcoefs(self): options = get_option_defaults() - options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, - val=True, units='unitless') - options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, - val=True, units='unitless') - self.prob.model.emp.options["aviary_options"] = options + options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val=True, units='unitless') + options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, val=True, units='unitless') + + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) - self.prob.set_val( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units="unitless") - self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units="ft") - self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.set_val(Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless') + self.prob.set_val(Aircraft.Fuselage.LENGTH, 129.4, units='ft') + self.prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.run_model() @@ -210,9 +197,67 @@ def test_large_sinle_aisle_1_calc_volcoefs(self): self.prob[Aircraft.VerticalTail.VOLUME_COEFFICIENT], 0.11623, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, **partial_tols) + + +@use_tempdirs +class BWBTestEmpennageGroup(unittest.TestCase): + """BWB model""" + + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('emp', EmpennageSize(), promotes=['*']) + + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=0.000001, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=2142.85714286, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.5463, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=16.2200522, units='ft') + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.ASPECT_RATIO, val=1.705, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.TAPER_RATIO, val=0.366, units='unitless' + ) + + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.VOLUME_COEFFICIENT, val=0.0150, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.MOMENT_RATIO, val=5.2615, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=146.38501094, units='ft') + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.ASPECT_RATIO, val=1.705, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.TAPER_RATIO, val=0.366, units='unitless' + ) + + def test_case1(self): + self.prob.setup(check=False, force_alloc_complex=True) + + self.prob.run_model() + + assert_near_equal(self.prob[Aircraft.HorizontalTail.AREA], 0.00117064, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.SPAN], 0.04467601, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.ROOT_CHORD], 0.03836448, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 0.02808445, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.MOMENT_ARM], 29.69074172, tol) + + assert_near_equal(self.prob[Aircraft.VerticalTail.AREA], 169.11964286, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.SPAN], 16.98084188, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.ROOT_CHORD], 14.58190052, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 10.67457744, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.MOMENT_ARM], 27.82191598, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, **partial_tols) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_engine.py b/aviary/subsystems/geometry/gasp_based/test/test_engine.py index 5e9538972c..e6d5090379 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_engine.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_engine.py @@ -3,10 +3,79 @@ import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs -from aviary.subsystems.geometry.gasp_based.engine import EngineSize -from aviary.variable_info.variables import Aircraft +from aviary.subsystems.geometry.gasp_based.engine import ( + BWBEngineSize, + BWBEngineSizeGroup, + EngineSize, + PercentNotInFuselage, +) from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import extract_options, setup_model_options +from aviary.variable_info.variables import Aircraft, Mission + + +class TestPercentNotInFuselage(unittest.TestCase): + def setUp(self): + self.prob = om.Problem() + + aviary_options = AviaryValues() + aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, [3]) + + self.prob.model.add_subsystem('perc', PercentNotInFuselage(), promotes=['*']) + + self.prob.model.set_input_defaults( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, 0.0, units='unitless' + ) + + setup_model_options(self.prob, aviary_options) + self.prob.setup(check=False, force_alloc_complex=True) + + def test_zero_buried(self): + self.prob.run_model() + tol = 1e-7 + assert_near_equal(self.prob['percent_exposed'], 1.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + def test_half_buried(self): + """Test in the range (epsilon, 1.0 - epsilon).""" + self.prob.set_val( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, val=0.5, units='unitless' + ) + self.prob.run_model() + tol = 1e-7 + assert_near_equal(self.prob['percent_exposed'], 0.5, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + def test_left_buried(self): + """Test in the range (0.0, epsilon).""" + self.prob.set_val( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, val=0.03, units='unitless' + ) + self.prob.run_model() + tol = 1e-7 + assert_near_equal(self.prob['percent_exposed'], 0.89181881, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + def test_right_buried(self): + """Test in the range (1.0 - epsilon, 1.0).""" + self.prob.set_val( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, val=0.97, units='unitless' + ) + self.prob.run_model() + tol = 1e-7 + + assert_near_equal(self.prob['percent_exposed'], 0.10818119, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class TestEngine( @@ -18,18 +87,16 @@ def setUp(self): aviary_options = AviaryValues() aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) - self.prob.model.add_subsystem("engsz", EngineSize( - aviary_options=aviary_options), promotes=["*"]) + self.prob.model.add_subsystem('engsz', EngineSize(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, val=1.028233) self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, val=1.028233 + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') + + setup_model_options(self.prob, aviary_options) self.prob.setup(check=False, force_alloc_complex=True) @@ -41,7 +108,73 @@ def test_large_sinle_aisle_1_defaults(self): assert_near_equal(self.prob[Aircraft.Nacelle.SURFACE_AREA], 339.58389, tol) def test_partials(self): - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + +class TestEngineBWB(unittest.TestCase): + """Test engine size using EngineSize class and BWB data""" + + def setUp(self): + self.prob = om.Problem() + + aviary_options = AviaryValues() + aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + + self.prob.model.add_subsystem('engsz', EngineSize(), promotes=['*']) + + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, val=1.3053677239456256) + self.prob.model.set_input_defaults( + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2205, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.3588, units='unitless') + + setup_model_options(self.prob, aviary_options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + tol = 1e-4 + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_DIAMETER], 8.08783369, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 10.98974842, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.SURFACE_AREA], 279.23498901, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + +class BWBTestEngine(unittest.TestCase): + """Test engine size using BWBEngineSize class and BWB data""" + + def setUp(self): + self.prob = om.Problem() + + aviary_options = AviaryValues() + aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) + + self.prob.model.add_subsystem('engsz', BWBEngineSize(), promotes=['*']) + + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + self.prob.model.set_input_defaults('percent_exposed', 1.0) + self.prob.model.set_input_defaults( + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2205, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.3588, units='unitless') + + setup_model_options(self.prob, aviary_options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + tol = 1e-6 + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_DIAMETER], 5.33382144, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 7.24759657, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.SURFACE_AREA], 121.44575974, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) @@ -52,18 +185,20 @@ def test_case_multiengine(self): aviary_options = AviaryValues() aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 4])) - prob.model.add_subsystem("cable", EngineSize( - aviary_options=aviary_options), promotes=["*"]) + prob.model.add_subsystem('cable', EngineSize(), promotes=['*']) prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, np.array([5.8, 8.2]), units="ft") - prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, val=np.array([1.028233, 0.9]) + Aircraft.Engine.REFERENCE_DIAMETER, np.array([5.8, 8.2]), units='ft' ) + prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, val=np.array([1.028233, 0.9])) prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, np.array([1.25, 1.02]), units="unitless") + Aircraft.Nacelle.CORE_DIAMETER_RATIO, np.array([1.25, 1.02]), units='unitless' + ) prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, np.array([2, 2.21]), units="unitless") + Aircraft.Nacelle.FINENESS, np.array([2, 2.21]), units='unitless' + ) + + prob.model_options['*'] = extract_options(aviary_options) prob.setup(check=False, force_alloc_complex=True) @@ -73,12 +208,57 @@ def test_case_multiengine(self): assert_near_equal(prob[Aircraft.Nacelle.AVG_DIAMETER], [7.35163, 7.9347871], tol) assert_near_equal(prob[Aircraft.Nacelle.AVG_LENGTH], [14.70326, 17.5358795], tol) - assert_near_equal(prob[Aircraft.Nacelle.SURFACE_AREA], - [339.58389, 437.13210486], tol) + assert_near_equal(prob[Aircraft.Nacelle.SURFACE_AREA], [339.58389, 437.13210486], tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + +@use_tempdirs +class BWBEngineSizeGroupTestCase(unittest.TestCase): + """this is the GASP BWB test case""" + + def setUp(self): + aviary_options = AviaryValues() + aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, [2]) + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + BWBEngineSizeGroup(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, 0.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2205, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.3588, units='unitless') + + setup_model_options(self.prob, aviary_options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + Testing GASP data case: + Aircraft.Nacelle.AVG_DIAMETER -- DBARN = 5.3338151 + Aircraft.Nacelle.AVG_LENGTH -- ELN = 7.24758816 + Aircraft.Nacelle.SURFACE_AREA -- SN/2 = 121.445763 (for one engine) + """ + self.prob.run_model() + + tol = 1e-6 + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_DIAMETER], 5.33382144, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 7.24759657, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.SURFACE_AREA], 121.44575974, tol) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py b/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py index ed0d336932..e9e5d0fbe4 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_fuselage.py @@ -2,123 +2,117 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.subsystems.geometry.gasp_based.fuselage import (FuselageGroup, - FuselageParameters, - FuselageSize) +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.geometry.gasp_based.fuselage import ( + BWBCabinLayout, + BWBFuselageGroup, + BWBFuselageParameters1, + BWBFuselageParameters2, + BWBFuselageSize, + FuselageGroup, + FuselageParameters, + FuselageSize, +) +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft +from aviary.variable_info.variables import Aircraft, Settings class FuselageParametersTestCase1(unittest.TestCase): - """ - this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix - """ + """this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix.""" def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( - "parameters", - FuselageParameters(aviary_options=options), - promotes=["*"], + 'parameters', + FuselageParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal(self.prob[Aircraft.Fuselage.AVG_DIAMETER], 157.2, tol) - assert_near_equal(self.prob["cabin_height"], 13.1, tol) - assert_near_equal(self.prob["cabin_len"], 72.1, tol) - assert_near_equal(self.prob["nose_height"], 8.6, tol) + assert_near_equal(self.prob['cabin_height'], 13.1, tol) + assert_near_equal(self.prob['cabin_len'], 72.1, tol) + assert_near_equal(self.prob['nose_height'], 8.6, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class FuselageParametersTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=30, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=30, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 1) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( - "parameters", - FuselageParameters(aviary_options=options), - promotes=["*"], + 'parameters', + FuselageParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case2(self): - self.prob.run_model() tol = 1e-4 assert_near_equal(self.prob[Aircraft.Fuselage.AVG_DIAMETER], 56.2, tol) - assert_near_equal(self.prob["cabin_height"], 9.183, tol) # not actual GASP value - assert_near_equal(self.prob["cabin_len"], 72.5, tol) # not actual GASP value - assert_near_equal(self.prob["nose_height"], 4.683, tol) # not actual GASP value + assert_near_equal(self.prob['cabin_height'], 9.183, tol) # not actual GASP value + assert_near_equal(self.prob['cabin_len'], 72.5, tol) # not actual GASP value + assert_near_equal(self.prob['nose_height'], 4.683, tol) # not actual GASP value - partial_data2 = self.prob.check_partials(out_stream=None, method="cs") + partial_data2 = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data2, atol=1e-8, rtol=1e-8) class FuselageSizeTestCase1(unittest.TestCase): - """ - this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix - """ + """this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "size", FuselageSize(aviary_options=get_option_defaults()), promotes=["*"] - ) + self.prob.model.add_subsystem('size', FuselageSize(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults('nose_height', 8.6, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") - self.prob.model.set_input_defaults("nose_height", 8.6, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults("cabin_len", 72.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults("cabin_height", 13.1, units="ft") + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' + ) + self.prob.model.set_input_defaults('cabin_len', 72.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') + self.prob.model.set_input_defaults('cabin_height', 13.1, units='ft') self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 @@ -129,55 +123,49 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol ) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 + assert_near_equal(self.prob[Aircraft.Fuselage.CABIN_AREA], 1068.96, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class FuselageSizeTestCase2(unittest.TestCase): - """ - this is the GASP test case for V3.6 advanced tube and wing - """ + """this is the GASP test case for V3.6 advanced tube and wing.""" def setUp(self): - options = get_option_defaults() self.prob = om.Problem() - self.prob.model.add_subsystem( - "parameters", FuselageSize(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('parameters', FuselageSize(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults('nose_height', 8.6, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") - self.prob.model.set_input_defaults("nose_height", 8.6, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults("cabin_len", 61.6, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults("cabin_height", 13.1, units="ft") + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' + ) + self.prob.model.set_input_defaults('cabin_len', 61.6, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') + self.prob.model.set_input_defaults('cabin_height', 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units="unitless") + Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units='unitless' + ) - self.prob.setup(check=False, force_alloc_complex=True) + setup_model_options(self.prob, options) - def test_case2(self): + self.prob.setup(check=False, force_alloc_complex=True) + def test_case1(self): self.prob.run_model() tol = 3e-4 - assert_near_equal( - self.prob[Aircraft.Fuselage.LENGTH], 119.03, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 119.03, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuselage.WETTED_AREA], 4209, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.TailBoom.LENGTH], 119.03, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 119.03, tol) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Fuselage.CABIN_AREA], 931.41, tol) - partial_data2 = self.prob.check_partials(out_stream=None, method="cs") + partial_data2 = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data2, atol=1e-8, rtol=1e-8) @@ -185,38 +173,35 @@ class FuselageGroupTestCase1( unittest.TestCase ): # this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - FuselageGroup(aviary_options=options), - promotes=["*"], + 'group', + FuselageGroup(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft") + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' + ) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 @@ -229,192 +214,468 @@ def test_case1(self): self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol ) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class FuselageGroupTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, - units="inch") # not actual GASP value + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') # not actual GASP value options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) # not actual GASP value - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, - units="inch") # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, - units="inch") # not actual GASP value + options.set_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6 + ) # not actual GASP value + options.set_val( + Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch' + ) # not actual GASP value + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') # not actual GASP value self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - FuselageGroup(aviary_options=options), - promotes=["*"], + 'group', + FuselageGroup(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Fuselage.AVG_DIAMETER], 157.2, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.565, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class FuselageGroupTestCase3(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=30, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, - units="inch") # not actual GASP value + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=30, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') # not actual GASP value options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) # not actual GASP value - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 1) # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, - units="inch") # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, - units="inch") # not actual GASP value + options.set_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 1 + ) # not actual GASP value + options.set_val( + Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch' + ) # not actual GASP value + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') # not actual GASP value self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - FuselageGroup(aviary_options=options), - promotes=["*"], + 'group', + FuselageGroup(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Fuselage.AVG_DIAMETER], 56.2, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Fuselage.LENGTH], 114.23, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 114.23, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuselage.WETTED_AREA], 2947.51, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.TailBoom.LENGTH], 114.23, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 114.23, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class FuselageGroupTestCase4(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=30, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, - units="inch") # not actual GASP value + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=30, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') # not actual GASP value options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) # not actual GASP value - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 1) # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, - units="inch") # not actual GASP value - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, - units="inch") # not actual GASP value + options.set_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 1 + ) # not actual GASP value + options.set_val( + Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch' + ) # not actual GASP value + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') # not actual GASP value self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - FuselageGroup(aviary_options=options), - promotes=["*"], + 'group', + FuselageGroup(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Fuselage.AVG_DIAMETER], 56.2, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Fuselage.LENGTH], 114.23, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 114.23, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuselage.WETTED_AREA], 2947.51, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.TailBoom.LENGTH], 114.23, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 114.23, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +class BWBFuselageParameters1TestCase(unittest.TestCase): + def setUp(self): + self.prob = om.Problem() + + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 18) + self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + self.aviary_options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) + self.aviary_options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') + self.aviary_options.set_val( + Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 32, units='inch' + ) + self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, 150) + self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 18) + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + + self.prob.model.add_subsystem( + 'bwb_fuselage_parameters1', BWBFuselageParameters1(), promotes=['*'] + ) + + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 5.0, units='ft') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 0.25970, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, 0.0, units='ft' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 0.6, units='unitless') + + setup_model_options(self.prob, self.aviary_options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """Testing GASP data case.""" + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Fuselage.AVG_DIAMETER], 38.0, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.HYDRAULIC_DIAMETER], 19.36509231, tol) + assert_near_equal(self.prob['cabin_height'], 9.86859989, tol) + assert_near_equal(self.prob['nose_height'], 4.86859989, tol) + assert_near_equal(self.prob['nose_length'], 2.92115998, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) + + +class BWBLayoutTestCase(unittest.TestCase): + def setUp(self): + self.prob = om.Problem() + + self.aviary_options = AviaryValues() + + self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 18) + self.aviary_options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + self.aviary_options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) + self.aviary_options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') + self.aviary_options.set_val( + Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 32, units='inch' + ) + self.aviary_options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 36, units='inch') + self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, 150) + self.aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11) + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + + self.prob.model.add_subsystem('bwb_cabin_layout', BWBCabinLayout(), promotes=['*']) + + self.prob.model.set_input_defaults( + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 65.0, units='deg' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 7.5, units='ft' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, 0.0, units='ft' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + self.prob.model.set_input_defaults('nose_length', 2.92115998, units='ft') + + setup_model_options(self.prob, self.aviary_options) + + self.prob.setup() + + def test_case1(self): + """Testing GASP data case.""" + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['fuselage_station_aft'], 54.25449, tol) + + partial_data = self.prob.check_partials( + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + minimum_step=1e-12, + abs_err_tol=5.0e-4, + rel_err_tol=5.0e-5, + ) + assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) + + def test_case2(self): + """Testing 0 First Class case.""" + self.aviary_options.set_val( + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, + val=0, + units='unitless', + ) + setup_model_options(self.prob, self.aviary_options) + self.prob.setup() + + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['fuselage_station_aft'], 51.25449, tol) + + partial_data = self.prob.check_partials( + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + minimum_step=1e-12, + abs_err_tol=5.0e-4, + rel_err_tol=5.0e-5, + ) + assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) + + +class BWBFuselageParameters2TestCase(unittest.TestCase): + def setUp(self): + self.prob = om.Problem() + + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + + self.prob.model.add_subsystem( + 'bwb_fuselage_parameters2', BWBFuselageParameters2(), promotes=['*'] + ) + + self.prob.model.set_input_defaults( + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 65.0, units='deg' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 7.5, units='ft' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 1.75, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + self.prob.model.set_input_defaults('nose_length', 2.92115998, units='ft') + self.prob.model.set_input_defaults('cabin_height', 9.86859989, units='ft') + self.prob.model.set_input_defaults('fuselage_station_aft', 54.254501, units='ft') + + setup_model_options(self.prob, self.aviary_options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """Testing GASP data case.""" + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Fuselage.PLANFORM_AREA], 1943.76594, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.CABIN_AREA], 1283.52497, tol) + assert_near_equal(self.prob['cabin_len'], 43.83334, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) + + +class BWBFuselageSizeTestCase(unittest.TestCase): + def setUp(self): + self.prob = om.Problem() + + self.aviary_options = AviaryValues() + self.aviary_options.set_val(Settings.VERBOSITY, 1, units='unitless') + + self.prob.model.add_subsystem('bwb_fuselage_size', BWBFuselageSize(), promotes=['*']) + + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, 0.0, units='ft' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 7.5, units='ft' + ) + self.prob.model.set_input_defaults('cabin_height', 9.86859989, units='ft') + self.prob.model.set_input_defaults('forebody_len', 40.7456322, units='ft') + self.prob.model.set_input_defaults('fuselage_station_aft', 54.254501, units='ft') + self.prob.model.set_input_defaults('nose_area', 3.97908521, units='ft**2') + self.prob.model.set_input_defaults('aftbody_len', 17.27005, units='ft') + self.prob.model.set_input_defaults('nose_length', 2.921159934, units='ft') + self.prob.model.set_input_defaults('cabin_len', 43.8333397, units='ft') + + setup_model_options(self.prob, self.aviary_options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """Testing GASP data case.""" + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4573.42578, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 71.5245514, tol) + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 71.5245514, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) + + +@use_tempdirs +class BWBFuselageGroupTestCase(unittest.TestCase): + """this is the GASP test case.""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 18) + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 32, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 36, units='inch') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, 150) + options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11) + + options.set_val(Settings.VERBOSITY, 1, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + BWBFuselageGroup(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 5.0, units='ft') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 0.25970, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, 0.0, units='ft' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 0.6, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 65.0, units='deg' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 7.5, units='ft' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 1.75, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0, units='unitless' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """Testing GASP data case.""" + self.prob.run_model() + + tol = 1e-4 + assert_near_equal(self.prob[Aircraft.Fuselage.AVG_DIAMETER], 38.0, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.HYDRAULIC_DIAMETER], 19.36509, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.CABIN_AREA], 1283.52497, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.PLANFORM_AREA], 1943.76594, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 71.5245514, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4573.42510, tol) + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 71.5245514, tol) + + partial_data = self.prob.check_partials( + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + minimum_step=1e-12, + abs_err_tol=5.0e-4, + rel_err_tol=5.0e-5, + ) + assert_check_partials(partial_data, atol=1e-6, rtol=1e-6) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_non_dimensional_conversion.py b/aviary/subsystems/geometry/gasp_based/test/test_non_dimensional_conversion.py index adc7f69638..e2efbb9180 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_non_dimensional_conversion.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_non_dimensional_conversion.py @@ -2,37 +2,41 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs -from aviary.subsystems.geometry.gasp_based.non_dimensional_conversion import \ - DimensionalNonDimensionalInterchange -from aviary.variable_info.variables import Aircraft - -from aviary.subsystems.geometry.gasp_based.non_dimensional_conversion import DimensionalNonDimensionalInterchange +from aviary.subsystems.geometry.gasp_based.non_dimensional_conversion import ( + DimensionalNonDimensionalInterchange, +) +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults +from aviary.variable_info.variables import Aircraft class FoldOnlyTestCase1(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) self.prob = om.Problem() - self.prob.model.add_subsystem("dimensionless_calcs", - DimensionalNonDimensionalInterchange( - aviary_options=options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] - ) + self.prob.model.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['aircraft:*'], + promotes_outputs=['aircraft:*'], + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=180.0, units="ft" + Aircraft.Wing.SPAN, val=180.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN, val=118.0, units="ft" + Aircraft.Wing.FOLDED_SPAN, val=118.0, units='ft' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): @@ -42,7 +46,7 @@ def test_case1(self): self.prob[Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS], 0.65556, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) @@ -50,34 +54,35 @@ class FoldOnlyTestCase2(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=False, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=False, units='unitless' + ) self.prob = om.Problem() - self.prob.model.add_subsystem("dimensionless_calcs", - DimensionalNonDimensionalInterchange( - aviary_options=options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] - ) + self.prob.model.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['aircraft:*'], + promotes_outputs=['aircraft:*'], + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=150.0, units="ft" + Aircraft.Wing.SPAN, val=150.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, val=0.5, units="unitless" + Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, val=0.5, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): self.prob.run_model() tol = 1e-4 - assert_near_equal( - self.prob[Aircraft.Wing.FOLDED_SPAN], 75.0, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.FOLDED_SPAN], 75.0, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) @@ -85,24 +90,25 @@ class StrutOnlyTestCase1(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem("dimensionless_calcs", - DimensionalNonDimensionalInterchange( - aviary_options=options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] - ) + self.prob.model.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['aircraft:*'], + promotes_outputs=['aircraft:*'], + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=180.0, units="ft" + Aircraft.Wing.SPAN, val=180.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=118.0, units="ft" + Aircraft.Strut.ATTACHMENT_LOCATION, val=118.0, units='ft' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): @@ -112,7 +118,7 @@ def test_case1(self): self.prob[Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS], 0.65556, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) @@ -120,24 +126,25 @@ class StrutOnlyTestCase2(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=False, units='unitless') + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=False, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem("dimensionless_calcs", - DimensionalNonDimensionalInterchange( - aviary_options=options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] - ) + self.prob.model.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['aircraft:*'], + promotes_outputs=['aircraft:*'], + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=150.0, units="ft" + Aircraft.Wing.SPAN, val=150.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0.5, units="unitless" + Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0.5, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): @@ -147,38 +154,41 @@ def test_case1(self): self.prob[Aircraft.Strut.ATTACHMENT_LOCATION], 75.0, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) +@use_tempdirs class FoldAndStrutTestCase1(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=False, units='unitless') + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=False, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem("dimensionless_calcs", - DimensionalNonDimensionalInterchange( - aviary_options=options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] - ) + self.prob.model.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['aircraft:*'], + promotes_outputs=['aircraft:*'], + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=180.0, units="ft" + Aircraft.Wing.SPAN, val=180.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN, val=118.0, units="ft" + Aircraft.Wing.FOLDED_SPAN, val=118.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0.5, units="unitless" + Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0.5, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): @@ -191,82 +201,86 @@ def test_case1(self): self.prob[Aircraft.Strut.ATTACHMENT_LOCATION], 90.0, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) +@use_tempdirs class FoldAndStrutTestCase2(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=False, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=False, units='unitless' + ) options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem("dimensionless_calcs", - DimensionalNonDimensionalInterchange( - aviary_options=options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] - ) + self.prob.model.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['aircraft:*'], + promotes_outputs=['aircraft:*'], + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=150.0, units="ft" + Aircraft.Wing.SPAN, val=150.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, val=0.8, units="unitless" + Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, val=0.8, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=90.0, units="ft" + Aircraft.Strut.ATTACHMENT_LOCATION, val=90.0, units='ft' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): self.prob.run_model() tol = 1e-4 - assert_near_equal( - self.prob[Aircraft.Wing.FOLDED_SPAN], 120.0, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.FOLDED_SPAN], 120.0, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS], 0.6, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) +@use_tempdirs class FoldAndStrutTestCase3(unittest.TestCase): def setUp(self): options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem("dimensionless_calcs", - DimensionalNonDimensionalInterchange( - aviary_options=options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] - ) + self.prob.model.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['aircraft:*'], + promotes_outputs=['aircraft:*'], + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=180.0, units="ft" + Aircraft.Wing.SPAN, val=180.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN, val=118.0, units="ft" + Aircraft.Wing.FOLDED_SPAN, val=118.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=108.0, units="ft" + Aircraft.Strut.ATTACHMENT_LOCATION, val=108.0, units='ft' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): @@ -276,12 +290,12 @@ def test_case1(self): self.prob[Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS], 0.65556, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS], .6, tol + self.prob[Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS], 0.6, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_override.py b/aviary/subsystems/geometry/gasp_based/test/test_override.py index 2b7973093a..ef87489989 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_override.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_override.py @@ -1,47 +1,47 @@ +import unittest +import warnings + import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryGroup +from aviary.subsystems.aerodynamics.gasp_based.gaspaero import AeroGeom from aviary.subsystems.premission import CorePreMission -from aviary.variable_info.variables import Aircraft - -from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.subsystems.aerodynamics.gasp_based.gaspaero import AeroGeom -from aviary.utils.process_input_decks import create_vehicle from aviary.utils.preprocessors import preprocess_propulsion +from aviary.utils.process_input_decks import create_vehicle +from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData - -import warnings -import unittest +from aviary.variable_info.variables import Aircraft +@use_tempdirs class GASPOverrideTestCase(unittest.TestCase): def setUp(self): aviary_inputs, initial_guesses = create_vehicle( - 'models/test_aircraft/converter_configuration_test_data_GwGm.csv') + 'models/aircraft/test_aircraft/configuration_test_GASP.csv' + ) - engines = build_engine_deck(aviary_inputs) + engines = [build_engine_deck(aviary_inputs)] core_subsystems = get_default_premission_subsystems('GASP', engines) preprocess_propulsion(aviary_inputs, engines) - self.aviary_inputs = aviary_inputs - prob = om.Problem() - aviary_options = aviary_inputs subsystems = core_subsystems - prob.model = AviaryGroup(aviary_options=aviary_options, - aviary_metadata=BaseMetaData) + prob.model = AviaryGroup() + prob.model.aviary_inputs = aviary_inputs + prob.model.meta_data = BaseMetaData prob.model.add_subsystem( 'pre_mission', - CorePreMission(aviary_options=aviary_options, - subsystems=subsystems), + CorePreMission(aviary_options=aviary_inputs, subsystems=subsystems), promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['aircraft:*', 'mission:*'] + promotes_outputs=['aircraft:*', 'mission:*'], ) self.prob = prob @@ -50,11 +50,12 @@ def test_case1(self): # Test override: expect the given value prob = self.prob - self.aviary_inputs.set_val( - Aircraft.Fuselage.WETTED_AREA, val=4000.0, units="ft**2") + prob.model.aviary_inputs.set_val(Aircraft.Fuselage.WETTED_AREA, val=4000.0, units='ft**2') + + setup_model_options(prob, prob.model.aviary_inputs, prob.model.meta_data) with warnings.catch_warnings(): - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) prob.setup() prob.run_model() @@ -67,8 +68,10 @@ def test_case2(self): # self.aviary_inputs.set_val(Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2") + setup_model_options(prob, prob.model.aviary_inputs, prob.model.meta_data) + with warnings.catch_warnings(): - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) prob.setup() prob.run_model() @@ -80,11 +83,14 @@ def test_case3(self): prob = self.prob # self.aviary_inputs.set_val(Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2") - self.aviary_inputs.set_val( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.5, units="unitless") + prob.model.aviary_inputs.set_val( + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.5, units='unitless' + ) + + setup_model_options(prob, prob.model.aviary_inputs, prob.model.meta_data) with warnings.catch_warnings(): - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) prob.setup() prob.run_model() @@ -95,13 +101,15 @@ def test_case4(self): # Test WETTED_AREA_SCALER: expect no effect prob = self.prob - self.aviary_inputs.set_val( - Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2") - self.aviary_inputs.set_val( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.5, units="unitless") + prob.model.aviary_inputs.set_val(Aircraft.Fuselage.WETTED_AREA, val=4000, units='ft**2') + prob.model.aviary_inputs.set_val( + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.5, units='unitless' + ) + + setup_model_options(prob, prob.model.aviary_inputs, prob.model.meta_data) with warnings.catch_warnings(): - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) prob.setup() prob.run_model() @@ -111,15 +119,16 @@ def test_case4(self): def test_case_aero_coeffs(self): """ Test overriding from csv (vertical tail) and overriding from code (horizontal tail) - Also checks non-overriden (wing) and default (strut) + Also checks non-overriden (wing) and default (strut). """ prob = self.prob - prob.model.add_subsystem("geom", AeroGeom( - aviary_options=self.aviary_inputs), promotes=["*"]) - self.aviary_inputs.set_val(Aircraft.HorizontalTail.FORM_FACTOR, val=1.5) + prob.model.add_subsystem('geom', AeroGeom(), promotes=['*']) + prob.model.aviary_inputs.set_val(Aircraft.HorizontalTail.FORM_FACTOR, val=1.5) + + setup_model_options(prob, prob.model.aviary_inputs, prob.model.meta_data) with warnings.catch_warnings(): - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) prob.setup() prob.run_model() @@ -127,9 +136,37 @@ def test_case_aero_coeffs(self): assert_near_equal(self.prob[Aircraft.Wing.FORM_FACTOR], 2.47320154, 1e-6) assert_near_equal(self.prob[Aircraft.HorizontalTail.FORM_FACTOR], 1.5, 1e-6) assert_near_equal(self.prob[Aircraft.VerticalTail.FORM_FACTOR], 2, 1e-6) + assert_near_equal(self.prob[Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR], 1.125, 1e-6) + + def test_case_emp_geo(self): + # Make sure we can override horizontal and veritcal tail geo vars. + prob = self.prob + + prob.model.aviary_inputs.set_val(Aircraft.HorizontalTail.AREA, val=7777.0, units='ft**2') + prob.model.aviary_inputs.set_val(Aircraft.VerticalTail.SPAN, val=8888.0, units='ft') + + setup_model_options(prob, prob.model.aviary_inputs, prob.model.meta_data) + + with warnings.catch_warnings(): + warnings.simplefilter('ignore', om.PromotionWarning) + prob.setup() + + prob.run_model() + + assert_near_equal( + self.prob.get_val(Aircraft.HorizontalTail.AREA, units='ft**2'), + 7777.0, + 1e-6, + ) assert_near_equal( - self.prob[Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR], 1.125, 1e-6) + self.prob.get_val(Aircraft.VerticalTail.SPAN, units='ft'), + 8888.0, + 1e-6, + ) if __name__ == '__main__': - unittest.main() + # unittest.main() + test = GASPOverrideTestCase() + test.setUp() + test.test_case_emp_geo() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_size_group.py b/aviary/subsystems/geometry/gasp_based/test/test_size_group.py index dc7c1bb1f4..735e2ad46a 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_size_group.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_size_group.py @@ -1,124 +1,104 @@ import unittest -import os import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs from aviary.subsystems.geometry.gasp_based.size_group import SizeGroup +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Mission # this is the GASP test case, input and output values based on large single aisle 1 v3 without bug fix +@use_tempdirs class SizeGroupTestCase1(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes=["*"], + 'size', + SizeGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" - ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2') self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, val=1.028233) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, val=1.028233 + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) - + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 assert_near_equal(self.prob[Aircraft.Fuselage.AVG_DIAMETER], 157.2, tol) - assert_near_equal(self.prob["fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["fuselage.cabin_len"], 72.1, tol) - assert_near_equal(self.prob["fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['cabin_height'], 13.1, tol) + assert_near_equal(self.prob['cabin_len'], 72.1, tol) + assert_near_equal(self.prob['nose_height'], 8.6, tol) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 - assert_near_equal( - self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol - ) + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol) assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.57, tol) # note: this is the actual GASP value, but for version 3.5. Version 3 has 129.4 - assert_near_equal( - self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol - ) + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol) assert_near_equal(self.prob[Aircraft.Wing.AREA], 1370.3, tol) assert_near_equal(self.prob[Aircraft.Wing.SPAN], 117.8, tol) @@ -133,19 +113,13 @@ def test_case1(self): assert_near_equal(self.prob[Aircraft.HorizontalTail.AREA], 375.9, tol) assert_near_equal(self.prob[Aircraft.HorizontalTail.SPAN], 42.25, tol) - assert_near_equal( - self.prob[Aircraft.HorizontalTail.ROOT_CHORD], 13.16130387591471, tol - ) - assert_near_equal( - self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.57573, tol - ) + assert_near_equal(self.prob[Aircraft.HorizontalTail.ROOT_CHORD], 13.16130387591471, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.57573, tol) assert_near_equal(self.prob[Aircraft.HorizontalTail.MOMENT_ARM], 54.7, tol) assert_near_equal(self.prob[Aircraft.VerticalTail.AREA], 469.3, tol) assert_near_equal(self.prob[Aircraft.VerticalTail.SPAN], 28, tol) - assert_near_equal( - self.prob[Aircraft.VerticalTail.ROOT_CHORD], 18.61267549773935, tol - ) + assert_near_equal(self.prob[Aircraft.VerticalTail.ROOT_CHORD], 18.61267549773935, tol) assert_near_equal(self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.83022, tol) assert_near_equal(self.prob[Aircraft.VerticalTail.MOMENT_ARM], 49.9, tol) @@ -153,143 +127,116 @@ def test_case1(self): assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 14.7, tol) assert_near_equal(self.prob[Aircraft.Nacelle.SURFACE_AREA], 339.58, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) +@use_tempdirs class SizeGroupTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes=["*"], + 'size', + SizeGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2') + self.prob.model.set_input_defaults(Aircraft.Strut.ATTACHMENT_LOCATION, val=12, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Strut.AREA_RATIO, val=0.021893, units='unitless' ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" - ) - self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=12, units='ft' - ) - self.prob.model.set_input_defaults( - Aircraft.Strut.AREA_RATIO, val=0.021893, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, val=1.028233) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, val=1.028233 + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Fuselage.AVG_DIAMETER], 157.2, tol ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.cabin_height"], 13.1, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.cabin_len"], 72.09722222, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.nose_height"], 8.6, tol - ) # not actual GASP value + assert_near_equal(self.prob['cabin_height'], 13.1, tol) # not actual GASP value + assert_near_equal(self.prob['cabin_len'], 72.09722222, tol) # not actual GASP value + assert_near_equal(self.prob['nose_height'], 8.6, tol) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 129.5, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuselage.WETTED_AREA], 4639.57, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 129.5, tol) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.AREA], 1370.3125, tol - ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.SPAN], 117.81878299, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.AREA], 1370.3125, tol) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.SPAN], 117.81878299, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.CENTER_CHORD], 17.48974356, tol @@ -305,31 +252,27 @@ def test_case1(self): ) # not actual GASP value assert_near_equal( - self.prob["wing.fold.nonfolded_taper_ratio"], 0.93175961, tol + self.prob['nonfolded_taper_ratio'], 0.93175961, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.FOLDING_AREA], 1167.5966191, tol ) # not actual GASP value assert_near_equal( - self.prob["wing.fold.nonfolded_wing_area"], 202.7158809, tol + self.prob['nonfolded_wing_area'], 202.7158809, tol ) # not actual GASP value assert_near_equal( - self.prob["wing.fold.tc_ratio_mean_folded"], 0.14847223, tol - ) # not actual GASP value - assert_near_equal( - self.prob["wing.fold.nonfolded_AR"], 0.71035382, tol + self.prob['tc_ratio_mean_folded'], 0.14847223, tol ) # not actual GASP value + assert_near_equal(self.prob['nonfolded_AR'], 0.71035382, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 208.08091725, tol ) # not actual GASP value - assert_near_equal(self.prob["wing.strut_y"], 6, tol) # not actual GASP value + assert_near_equal(self.prob['strut_y'], 6, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Strut.LENGTH], 13.11154072, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Strut.CHORD], 1.14403031, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Strut.CHORD], 1.14403031, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.HorizontalTail.AREA], 375.87987047, tol @@ -373,130 +316,106 @@ def test_case1(self): self.prob[Aircraft.Nacelle.SURFACE_AREA], 339.58410134, tol ) # may not be actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-10, rtol=1e-12) +@use_tempdirs class SizeGroupTestCase3(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, - val=True, units='unitless') - options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, - val=True, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val=True, units='unitless') + options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, val=True, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 1) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes=["*"], + 'size', + SizeGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" - ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, val=25, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN, val=25, units="ft" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, val=1.028233) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, val=1.028233 + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) - + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Fuselage.AVG_DIAMETER], 56.2, tol ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.cabin_height"], 9.18333, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.cabin_len"], 435, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.nose_height"], 4.68333, tol - ) # not actual GASP value + assert_near_equal(self.prob['cabin_height'], 9.18333, tol) # not actual GASP value + assert_near_equal(self.prob['cabin_len'], 435, tol) # not actual GASP value + assert_near_equal(self.prob['nose_height'], 4.68333, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuselage.LENGTH], 476.7333, tol @@ -508,12 +427,8 @@ def test_case1(self): self.prob[Aircraft.TailBoom.LENGTH], 476.7333, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.AREA], 1370.3125, tol - ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.SPAN], 117.81878299, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.AREA], 1370.3125, tol) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.SPAN], 117.81878299, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.CENTER_CHORD], 17.48974356, tol @@ -521,28 +436,24 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Wing.AVERAGE_CHORD], 12.61453233, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.ROOT_CHORD], 16.988, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.988, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.14151, tol ) # not actual GASP value assert_near_equal( - self.prob["wing.fold.nonfolded_taper_ratio"], 0.85783252, tol + self.prob['nonfolded_taper_ratio'], 0.85783252, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.FOLDING_AREA], 964.14982163, tol ) # not actual GASP value assert_near_equal( - self.prob["wing.fold.nonfolded_wing_area"], 406.16267837, tol - ) # not actual GASP value - assert_near_equal( - self.prob["wing.fold.tc_ratio_mean_folded"], 0.14681715, tol + self.prob['nonfolded_wing_area'], 406.16267837, tol ) # not actual GASP value assert_near_equal( - self.prob["wing.fold.nonfolded_AR"], 1.5387923, tol + self.prob['tc_ratio_mean_folded'], 0.14681715, tol ) # not actual GASP value + assert_near_equal(self.prob['nonfolded_AR'], 1.5387923, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 406.53567274, tol ) # not actual GASP value @@ -593,132 +504,106 @@ def test_case1(self): self.prob[Aircraft.Electrical.HYBRID_CABLE_LENGTH], 50.6032, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-9, rtol=1e-12) +@use_tempdirs class SizeGroupTestCase4(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, - val=True, units='unitless') - options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, - val=True, units='unitless') + options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val=True, units='unitless') + options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=False, units='unitless') - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=False, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 1) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes=["*"], + 'size', + SizeGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Strut.AREA_RATIO, val=0.021893, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Strut.AREA_RATIO, val=0.021893, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, val=1.028233) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, val=1.028233 + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Fuselage.AVG_DIAMETER], 56.2, tol ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.cabin_height"], 9.18333, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.cabin_len"], 435, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fuselage.nose_height"], 4.68333, tol - ) # not actual GASP value + assert_near_equal(self.prob['cabin_height'], 9.18333, tol) # not actual GASP value + assert_near_equal(self.prob['cabin_len'], 435, tol) # not actual GASP value + assert_near_equal(self.prob['nose_height'], 4.68333, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuselage.LENGTH], 476.7333, tol @@ -730,12 +615,8 @@ def test_case1(self): self.prob[Aircraft.TailBoom.LENGTH], 476.7333, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.AREA], 1370.3125, tol - ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.SPAN], 117.81878299, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.AREA], 1370.3125, tol) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.SPAN], 117.81878299, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.CENTER_CHORD], 17.48974356, tol @@ -743,22 +624,14 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Wing.AVERAGE_CHORD], 12.61453233, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.ROOT_CHORD], 16.988, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.988, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.14151, tol ) # not actual GASP value - assert_near_equal( - self.prob["wing.strut.strut_y"], 0, tol - ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Strut.LENGTH], 5.2361, tol - ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Strut.CHORD], 2.8647, tol - ) # not actual GASP value + assert_near_equal(self.prob['strut_y'], 0, tol) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Strut.LENGTH], 5.2361, tol) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Strut.CHORD], 2.8647, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.HorizontalTail.AREA], 298.484, tol @@ -802,9 +675,191 @@ def test_case1(self): self.prob[Aircraft.Nacelle.SURFACE_AREA], 339.58410134, tol ) # may not be actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) -if __name__ == "__main__": +@use_tempdirs +class BWBSizeGroupTestCase1(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val=False, units='unitless') + options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, val=False, units='unitless') + options.set_val(Aircraft.Wing.HAS_STRUT, val=False, units='unitless') + options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') + options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 18) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 36, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 32, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11) + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'size', + SizeGroup(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + self.prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 70.0, units='lbf/ft**2') + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.ASPECT_RATIO, 1.705, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.TAPER_RATIO, 0.366, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.TAPER_RATIO, 0.366, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.45, units='unitless') + + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, 0.000001, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.015, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 5.0, units='ft') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 7.5, units='ft' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 0.6, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 1.75, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.MOMENT_RATIO, 5.2615, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.ASPECT_RATIO, 1.705, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2205, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.3588, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0.0, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, 118, units='ft') + self.prob.model.set_input_defaults( + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 0.25970, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 65.0, units='deg' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, 0.0, units='ft' + ) + self.prob.model.set_input_defaults( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, 0.0, units='unitless' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + Testing GASP data case: + Aircraft.Fuselage.AVG_DIAMETER -- SWF = 38.00 + fuselage.cabin_height -- HC = 9.87 + fuselage.cabin_len -- LC = 43.8 + fuselage.parameters1.nose_height -- HN = 4.87 + Aircraft.Fuselage.LENGTH -- ELF = 71.52 + Aircraft.Fuselage.WETTED_AREA -- SF = 4574. + Aircraft.TailBoom.LENGTH -- ELFFC = 71.5 + Aircraft.Wing.AREA -- SW = 2142.9 + Aircraft.Wing.SPAN -- B = 146.4 + Aircraft.Wing.CENTER_CHORD -- CROOT = 23.3 + Aircraft.Wing.AVERAGE_CHORD -- CBARW = 16.22 + Aircraft.Wing.ROOT_CHORD -- CROOTW = 20.0657883 + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED TCM = 0.124 + wing.wing_volume_no_fold -- FVOLW_GEOMX = 783.6 + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX -- FVOLW_GEOM = 605.9 + Aircraft.Wing.EXPOSED_AREA -- SW_EXP = 1352.1 + Aircraft.HorizontalTail.AREA -- SHT = 0. + Aircraft.HorizontalTail.SPAN -- BHT = 0.04 + Aircraft.HorizontalTail.ROOT_CHORD -- CRCLHT = 0.0383644775 + Aircraft.HorizontalTail.AVERAGE_CHORD -- CBARHT = 0.03 + Aircraft.HorizontalTail.MOMENT_ARM -- ELTH = 29.7 + Aircraft.VerticalTail.AREA -- SVT = 169.1 + Aircraft.VerticalTail.SPAN -- BVT = 16.98 + Aircraft.VerticalTail.ROOT_CHORD -- CRCLVT = 14.5819016 + Aircraft.VerticalTail.AVERAGE_CHORD -- CBARVT = 10.67 + Aircraft.VerticalTail.MOMENT_ARM -- ELTV = 27.8 + Aircraft.Nacelle.AVG_DIAMETER -- DBARN = 6.95 + Aircraft.Nacelle.AVG_LENGTH -- ELN = 9.44 + Aircraft.Nacelle.SURFACE_AREA -- SN = 205.965 (for one engine) + """ + self.prob.run_model() + + tol = 1e-4 + + # BWBFuselageGroup + assert_near_equal(self.prob[Aircraft.Fuselage.AVG_DIAMETER], 38, tol) + assert_near_equal(self.prob['cabin_height'], 9.86859989, tol) + # assert_near_equal(self.prob['fuselage.cabin_len'], 43.83334, tol) + assert_near_equal(self.prob['nose_height'], 4.86859989, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.LENGTH], 71.5245514, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.WETTED_AREA], 4573.42578, tol) + assert_near_equal(self.prob[Aircraft.TailBoom.LENGTH], 71.5245514, tol) + + # BWBWingGroup + assert_near_equal(self.prob[Aircraft.Wing.AREA], 2142.85714286, tol) + assert_near_equal(self.prob[Aircraft.Wing.SPAN], 146.38501094, tol) + assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 22.97244452, tol) + assert_near_equal(self.prob[Aircraft.Wing.AVERAGE_CHORD], 16.2200522, tol) + assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 20.33371617, tol) + assert_near_equal(self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.13596576, tol) + assert_near_equal(self.prob['wing_volume_no_fold'], 783.62100035, tol) + assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 605.90781747, tol) + assert_near_equal(self.prob[Aircraft.Wing.EXPOSED_AREA], 1352.1135998, tol) + + # EmpennageSize + assert_near_equal(self.prob[Aircraft.HorizontalTail.AREA], 0.00117064, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.SPAN], 0.04467601, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.ROOT_CHORD], 0.03836448, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 0.02808445, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.MOMENT_ARM], 29.69074172, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.AREA], 169.11964286, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.SPAN], 16.98084188, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.ROOT_CHORD], 14.58190052, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 10.67457744, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.MOMENT_ARM], 27.82191598, tol) + + # BWBEngineSizeGroup + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_DIAMETER], 5.33382144, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 7.24759657, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.SURFACE_AREA], 121.44575974, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=3e-9, rtol=3e-9) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_strut.py b/aviary/subsystems/geometry/gasp_based/test/test_strut.py index d2c14daa88..764929556d 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_strut.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_strut.py @@ -4,48 +4,42 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from aviary.subsystems.geometry.gasp_based.strut import StrutGeom -from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft class SizeGroupTestCase1(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("strut", StrutGeom( - aviary_options=get_option_defaults()), promotes=["*"]) + self.prob.model.add_subsystem('strut', StrutGeom(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Strut.AREA_RATIO, val=.2, units=None + Aircraft.Strut.AREA_RATIO, val=0.2, units=None ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=150, units="ft**2" + Aircraft.Wing.AREA, val=150, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( Aircraft.Strut.ATTACHMENT_LOCATION, val=1.0 ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=10.0, units="ft" + Aircraft.Fuselage.AVG_DIAMETER, val=10.0, units='ft' ) # not actual GASP value self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["strut_y"], 0.5, tol) # not actual GASP value + assert_near_equal(self.prob['strut_y'], 0.5, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Strut.LENGTH], 10.9658561, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Strut.CHORD], 1.36788226, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Strut.CHORD], 1.36788226, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/test/test_wing.py b/aviary/subsystems/geometry/gasp_based/test/test_wing.py index 0bbd89fbc9..cd37a45e17 100644 --- a/aviary/subsystems/geometry/gasp_based/test/test_wing.py +++ b/aviary/subsystems/geometry/gasp_based/test/test_wing.py @@ -2,10 +2,21 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.subsystems.geometry.gasp_based.wing import (WingFold, WingGroup, - WingParameters, - WingSize) +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.geometry.gasp_based.wing import ( + BWBWingVolume, + BWBWingFoldVolume, + BWBWingGroup, + ExposedWing, + WingFoldArea, + WingFoldVolume, + WingGroup, + WingParameters, + WingSize, + WingVolume, +) +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Mission @@ -14,53 +25,75 @@ class WingSizeTestCase1( unittest.TestCase ): # actual GASP test case, input and output values based on large single aisle 1 v3 without bug fix def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("size", WingSize(), promotes=["*"]) + self.prob.model.add_subsystem('size', WingSize(), promotes=['*']) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, 175400, units="lbm" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, 128, units="lbf/ft**2" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, 10.13, units="unitless" - ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 128, units='lbf/ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 2e-4 assert_near_equal(self.prob[Aircraft.Wing.AREA], 1370.3, tol) assert_near_equal(self.prob[Aircraft.Wing.SPAN], 117.8, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class WingSizeTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.geometry.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.geometry.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): self.prob = om.Problem() - self.prob.model.add_subsystem("size", WingSize(), promotes=["*"]) + self.prob.model.add_subsystem('size', WingSize(), promotes=['*']) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 128, units='lbf/ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') self.prob.setup(check=False, force_alloc_complex=True) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BWBWingSizeTestCase1(unittest.TestCase): + """ + BWB model + """ + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('size', WingSize(), promotes=['*']) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 70.0, units='lbf/ft**2') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + prob = self.prob + prob.run_model() + + tol = 1e-7 + assert_near_equal(prob[Aircraft.Wing.AREA], 2142.8571, tol) + assert_near_equal(prob[Aircraft.Wing.SPAN], 146.38501, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) @@ -68,36 +101,25 @@ class WingParametersTestCase1( unittest.TestCase ): # actual GASP test case, input and output values based on large single aisle 1 v3 without bug fix def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "parameters", WingParameters(aviary_options=get_option_defaults()), promotes=["*"] - ) + self.prob.model.add_subsystem('parameters', WingParameters(), promotes=['*']) - self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units="ft**2") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, 117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, 10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, 117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -107,44 +129,35 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.1397, tol ) # this is slightly different from the GASP output value, likely due to rounding error - assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 1114, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class WingParametersTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - self.prob = om.Problem() - self.prob.model.add_subsystem( - "parameters", WingParameters(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('parameters', WingParameters(), promotes=['*']) - self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units="ft**2") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, 117.8, units="ft") + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, 117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, 10.13, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -155,183 +168,494 @@ def test_case1(self): self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.1397, tol ) # this is slightly different from the GASP output value, likely due to rounding error - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -class WingFoldTestCase1(unittest.TestCase): +class BWBWingParametersTestCase1(unittest.TestCase): + """Test BWB data for BWBWingParameters""" + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('parameters', WingParameters(), promotes=['*']) + + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.385, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless') + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + prob = self.prob + prob.run_model() + + tol = 1e-7 + assert_near_equal(prob[Aircraft.Wing.CENTER_CHORD], 22.97244663, tol) + assert_near_equal(prob[Aircraft.Wing.AVERAGE_CHORD], 16.2200537, tol) + assert_near_equal(prob[Aircraft.Wing.ROOT_CHORD], 20.33371818, tol) + assert_near_equal(prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.13596576, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) - options = get_option_defaults() - options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') +class WingVolumeTestCase1( + unittest.TestCase +): # actual GASP test case, input and output values based on large single aisle 1 v3 without bug fix + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.HAS_FOLD, val=False, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", - WingFold( - aviary_options=options, - ), - promotes=["*"], - ) + self.prob.model.add_subsystem('wing_vol', WingVolume(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, 1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, 117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) - self.prob.model.set_input_defaults( - "strut_y", val=25, units="ft" + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 5e-4 + assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 1114, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BWBWingVolumeTestCase(unittest.TestCase): + """Test BWB data for BWBWingVolume""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.HAS_FOLD, val=False, units='unitless') + prob = self.prob = om.Problem() + prob.model.add_subsystem('wing_vol', BWBWingVolume(), promotes=['*']) + + prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0.0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.385, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.CENTER_CHORD, 22.9724445, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.45, units='unitless') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + prob = self.prob + prob.run_model() + + tol = 1e-7 + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 783.6209, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +class WingFoldAreaTestCase1(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + WingFoldArea(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults('strut_y', val=25, units='ft') # not actual GASP value + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-4 + + assert_near_equal( + self.prob[Aircraft.Wing.FOLDING_AREA], 620.04352246, tol ) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class WingFoldVolumeTestCase1(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + WingFoldVolume(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) + self.prob.model.set_input_defaults('strut_y', val=25, units='ft') # not actual GASP value + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDING_AREA, val=620.0435, units='ft**2') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( - self.prob["nonfolded_taper_ratio"], 0.71561969, tol + self.prob['nonfolded_taper_ratio'], 0.71561969, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Wing.FOLDING_AREA], 620.04352246, tol + self.prob['nonfolded_wing_area'], 750.25647754, tol ) # not actual GASP value assert_near_equal( - self.prob["nonfolded_wing_area"], 750.25647754, tol + self.prob['tc_ratio_mean_folded'], 0.14363328, tol ) # not actual GASP value + assert_near_equal(self.prob['nonfolded_AR'], 3.33219382, tol) # not actual GASP value assert_near_equal( - self.prob["tc_ratio_mean_folded"], 0.14363328, tol + self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 712.3428037422319, tol ) # not actual GASP value - assert_near_equal( - self.prob["nonfolded_AR"], 3.33219382, tol + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +class WingFoldAreaTestCase2(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + WingFoldArea(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.Wing.FOLDED_SPAN, val=25, units='ft' ) # not actual GASP value + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-4 + assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 712.3428037422319, tol + self.prob[Aircraft.Wing.FOLDING_AREA], 964.0812219, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) -class WingFoldTestCase2(unittest.TestCase): +class BWBWingFoldAreaTestCase1(unittest.TestCase): def setUp(self): + options = get_option_defaults() + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'group', + WingFoldArea(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, 118, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.385, units='ft') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + prob = self.prob + prob.run_model() + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Wing.FOLDING_AREA], 224.82521003, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) + + +class WingFoldVolumeTestCase1(unittest.TestCase): + def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingFold( - aviary_options=options - ), - promotes=["*"], + 'group', + WingFoldVolume(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN, val=25, units="ft" + self.prob.model.set_input_defaults('strut_y', val=25, units='ft') # not actual GASP value + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDING_AREA, val=620.0435, units='ft**2') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-4 + + assert_near_equal( + self.prob['nonfolded_taper_ratio'], 0.71561969, tol + ) # not actual GASP value + assert_near_equal( + self.prob['nonfolded_wing_area'], 750.25647754, tol + ) # not actual GASP value + assert_near_equal( + self.prob['tc_ratio_mean_folded'], 0.14363328, tol ) # not actual GASP value + assert_near_equal(self.prob['nonfolded_AR'], 3.33219382, tol) # not actual GASP value + assert_near_equal( + self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 712.3428037422319, tol + ) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +class WingFoldVolumeTestCase2(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + WingFoldVolume(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) + self.prob.model.set_input_defaults( + Aircraft.Wing.FOLDED_SPAN, val=25, units='ft' + ) # not actual GASP value + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDING_AREA, 964.0812219, units='ft**2') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( - self.prob["nonfolded_taper_ratio"], 0.85780985, tol + self.prob['nonfolded_taper_ratio'], 0.85780985, tol ) # not actual GASP value assert_near_equal( - self.prob[Aircraft.Wing.FOLDING_AREA], 964.0812219, tol + self.prob['nonfolded_wing_area'], 406.2187781, tol ) # not actual GASP value assert_near_equal( - self.prob["nonfolded_wing_area"], 406.2187781, tol - ) # not actual GASP value - assert_near_equal( - self.prob["tc_ratio_mean_folded"], 0.14681664, tol - ) # not actual GASP value - assert_near_equal( - self.prob["nonfolded_AR"], 1.53857978, tol + self.prob['tc_ratio_mean_folded'], 0.14681664, tol ) # not actual GASP value + assert_near_equal(self.prob['nonfolded_AR'], 1.53857978, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 406.64971668264957, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) -class WingGroupTestCase1( - unittest.TestCase -): # actual GASP test case, input and output values based on large single aisle 1 v3 without bug fix +@use_tempdirs +class BWBWingFoldVolumeTestCase1(unittest.TestCase): + """ + Test against GASP BWB model, CHOOSE_FOLD_LOCATION = False + This case should not be allowed, but it is tested anyway. + """ + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", WingGroup(aviary_options=get_option_defaults()), promotes=["*"] + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'group', + BWBWingFoldVolume(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, 175400, units="lbm" + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, 128, units="lbf/ft**2" + prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless') + prob.model.set_input_defaults('strut_y', val=59, units='ft') + prob.model.set_input_defaults('wing_volume_no_fold', val=783.6209, units='ft**3') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + + setup_model_options(prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + prob = self.prob + prob.run_model() + + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 605.90774, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +@use_tempdirs +class BWBWingFoldVolumeTestCase2(unittest.TestCase): + """ + Test against GASP BWB model, CHOOSE_FOLD_LOCATION = True + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=True, units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'group', + BWBWingFoldVolume(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, 10.13, units="unitless" + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' ) + prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, 118.0, units='ft') + prob.model.set_input_defaults('wing_volume_no_fold', val=783.6209, units='ft**3') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + prob = self.prob + self.prob.run_model() + + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 605.90774, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +@use_tempdirs +class WingGroupTestCase1(unittest.TestCase): + """ + actual GASP test case, input and output values based on large single aisle 1 v3 without bug fix + HAS_FOLD = False + HAS_STRUT = False + CHOOSE_FOLD_LOCATION = True + DIMENSIONAL_LOCATION_SPECIFIED = False + FOLD_DIMENSIONAL_LOCATION_SPECIFIED = False + """ + + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('group', WingGroup(), promotes=['*']) + + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 128, units='lbf/ft**2') + + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -347,73 +671,64 @@ def test_case1(self): ) # this is slightly different from the GASP output value, likely due to rounding error assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 1114, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) +@use_tempdirs class WingGroupTestCase2(unittest.TestCase): """ Wing with both folds and struts which has fold dimensional location and strut dimensional location specified - with the fold at the strut connection + with the fold at the strut connection. + HAS_FOLD = True + HAS_STRUT = True + CHOOSE_FOLD_LOCATION = False + DIMENSIONAL_LOCATION_SPECIFIED = True + FOLD_DIMENSIONAL_LOCATION_SPECIFIED = False """ def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingGroup( - aviary_options=options, - ), - promotes=["*"], + 'group', + WingGroup(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, 175400, units="lbm" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, 128, units="lbf/ft**2" - ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 128, units='lbf/ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, 10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Strut.AREA_RATIO, val=0.02189, units="unitless" + Aircraft.Strut.AREA_RATIO, val=0.02189, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=1.0, units="ft" + Aircraft.Strut.ATTACHMENT_LOCATION, val=1.0, units='ft' ) # not actual GASP value - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -429,20 +744,18 @@ def test_case1(self): ) # this is slightly different from the GASP output value, likely due to rounding error assert_near_equal( - self.prob["fold.nonfolded_taper_ratio"], 0.9943133, tol + self.prob['nonfolded_taper_ratio'], 0.9943133, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.FOLDING_AREA], 1352.8724859, tol ) # not actual GASP value assert_near_equal( - self.prob["fold.nonfolded_wing_area"], 17.4400141, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fold.tc_ratio_mean_folded"], 0.14987269, tol + self.prob['nonfolded_wing_area'], 17.4400141, tol ) # not actual GASP value assert_near_equal( - self.prob["fold.nonfolded_AR"], 0.0573394, tol + self.prob['tc_ratio_mean_folded'], 0.14987269, tol ) # not actual GASP value + assert_near_equal(self.prob['nonfolded_AR'], 0.0573394, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 18.26837098, tol ) # not actual GASP value @@ -450,68 +763,61 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Strut.LENGTH], 14.42957033, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Strut.CHORD], 1.03953199, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Strut.CHORD], 1.03953199, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=7e-12, rtol=1e-12) +@use_tempdirs class WingGroupTestCase3(unittest.TestCase): """ - Wing with folds which has dimensional location specified + Wing with folds which has dimensional location specified. + HAS_FOLD = True + HAS_STRUT = False + CHOOSE_FOLD_LOCATION = True + DIMENSIONAL_LOCATION_SPECIFIED = True + FOLD_DIMENSIONAL_LOCATION_SPECIFIED = False """ def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingGroup( - aviary_options=options, - ), - promotes=["*"], + 'group', + WingGroup(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, 175400, units="lbm" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, 128, units="lbf/ft**2" - ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 128, units='lbf/ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, 10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN, val=25, units="ft" + Aircraft.Wing.FOLDED_SPAN, val=25, units='ft' ) # not actual GASP value - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -527,58 +833,73 @@ def test_case1(self): ) # this is slightly different from the GASP output value, likely due to rounding error assert_near_equal( - self.prob["fold.nonfolded_taper_ratio"], 0.85780985, tol + self.prob['nonfolded_taper_ratio'], 0.85780985, tol ) # not actual GASP value assert_near_equal( self.prob[Aircraft.Wing.FOLDING_AREA], 964.14982163, tol ) # not actual GASP value assert_near_equal( - self.prob["fold.nonfolded_wing_area"], 406.16267837, tol + self.prob['nonfolded_wing_area'], 406.16267837, tol ) # not actual GASP value assert_near_equal( - self.prob["fold.tc_ratio_mean_folded"], 0.14681715, tol - ) # not actual GASP value - assert_near_equal( - self.prob["fold.nonfolded_AR"], 1.5387923, tol + self.prob['tc_ratio_mean_folded'], 0.14681715, tol ) # not actual GASP value + assert_near_equal(self.prob['nonfolded_AR'], 1.5387923, tol) # not actual GASP value assert_near_equal( self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 406.64971668264957, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) +@use_tempdirs class WingGroupTestCase4(unittest.TestCase): """ - Wing with both folds and struts which has fold dimensional location and strut dimensional location specified + Wing with both folds and struts which has fold dimensional location and strut dimensional location specified. + HAS_FOLD = True + HAS_STRUT = True + CHOOSE_FOLD_LOCATION = True + DIMENSIONAL_LOCATION_SPECIFIED = True + FOLD_DIMENSIONAL_LOCATION_SPECIFIED = True """ def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingGroup( - aviary_options=options, - ), - promotes=["*"], + 'group', + WingGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, val=1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Strut.ATTACHMENT_LOCATION, val=0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Strut.AREA_RATIO, val=0.2, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=10.0, units='ft') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=152000.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 128, units='lbf/ft**2') self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDED_SPAN, val=1, units="ft" + Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units='unitless' ) + + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=0, units="ft" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units='unitless' ) + self.prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, val=0.1, units='unitless' + ) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) @@ -591,87 +912,78 @@ def test_case1(self): assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 16.2814, tol) assert_near_equal(self.prob[Aircraft.Wing.AVERAGE_CHORD], 11.7430, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 15.4789, tol) - assert_near_equal( - self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.1067, tol) - assert_near_equal(self.prob["fold.nonfolded_taper_ratio"], 0.9939, tol) + assert_near_equal(self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.1067, tol) + assert_near_equal(self.prob['nonfolded_taper_ratio'], 0.9939, tol) assert_near_equal(self.prob[Aircraft.Wing.FOLDING_AREA], 1171.2684, tol) - assert_near_equal(self.prob["fold.nonfolded_wing_area"], 16.2316, tol) - assert_near_equal(self.prob["fold.tc_ratio_mean_folded"], 0.10995, tol) - assert_near_equal(self.prob["fold.nonfolded_AR"], 0.06161, tol) - assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 11.61131, tol) + assert_near_equal(self.prob['nonfolded_wing_area'], 16.2316, tol) + assert_near_equal(self.prob['tc_ratio_mean_folded'], 0.10995, tol) + assert_near_equal(self.prob['nonfolded_AR'], 0.06161, tol) + assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 11.61131, tol) assert_near_equal(self.prob[Aircraft.Strut.LENGTH], 11.18034, tol) assert_near_equal(self.prob[Aircraft.Strut.CHORD], 10.62132, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-12, rtol=1e-13) +@use_tempdirs class WingGroupTestCase5(unittest.TestCase): """ - Wing with struts which has dimentional location specified + Wing with struts which has dimentional location specified. + HAS_FOLD = False + HAS_STRUT = True + CHOOSE_FOLD_LOCATION = False + DIMENSIONAL_LOCATION_SPECIFIED = True + FOLD_DIMENSIONAL_LOCATION_SPECIFIED = False """ def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingGroup( - aviary_options=options, - ), - promotes=["*"], + 'group', + WingGroup(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, 175400, units="lbm" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, 128, units="lbf/ft**2" - ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 128, units='lbf/ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, 10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, 0.33, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.15, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, 13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Strut.AREA_RATIO, val=.2, units="unitless" + Aircraft.Strut.AREA_RATIO, val=0.2, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=150, units="ft**2" + Aircraft.Wing.AREA, val=150, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=1.0, units="ft" + Aircraft.Strut.ATTACHMENT_LOCATION, val=1.0, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.AREA_RATIO, val=0.021893, units="unitless" + Aircraft.Strut.AREA_RATIO, val=0.021893, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -689,13 +1001,200 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Strut.LENGTH], 14.42957033, tol ) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Strut.CHORD], 1.03953199, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Strut.CHORD], 1.03953199, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) -if __name__ == "__main__": +@use_tempdirs +class BWBWingGroupTestCase1(unittest.TestCase): + """ + actual GASP test case, input and output values based on large single aisle 1 v3 without bug fix + HAS_FOLD = True + HAS_STRUT = False + CHOOSE_FOLD_LOCATION = True + FOLD_DIMENSIONAL_LOCATION_SPECIFIED = True + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + prob = self.prob = om.Problem() + prob.model.add_subsystem('group', BWBWingGroup(), promotes=['*']) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 70.0, units='lbf/ft**2') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.385, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.45, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless') + + prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.CENTER_CHORD, 22.9724445, units='ft') + + prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, 118, units='ft') + + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 0.25970, units='unitless' + ) + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + Testing GASP data case: + Aircraft.Wing.AREA -- SW = 2142.9 + Aircraft.Wing.SPAN -- B = 146.4 + Aircraft.Wing.CENTER_CHORD -- CROOT = 23.3 + Aircraft.Wing.AVERAGE_CHORD -- CBARW = 16.22 + Aircraft.Wing.ROOT_CHORD -- CROOTW = 20.0657883 + Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED -- TCM = 0.124 + wing_volume_no_fold -- FVOLW_GEOMX = 783.6 + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX -- FVOLW_GEOM = 605.9 + Aircraft.Wing.FOLDING_AREA -- SWFOLD = 224.8 + Aircraft.Wing.EXPOSED_AREA -- SW_EXP = 1352.1 + Note: CROOT in GASP matches with Aircraft.Wing.CENTER_CHORD + """ + prob = self.prob + prob.run_model() + + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Wing.AREA], 2142.85714286, tol) + assert_near_equal(prob[Aircraft.Wing.SPAN], 146.38501094, tol) + assert_near_equal(prob[Aircraft.Wing.CENTER_CHORD], 22.97244452, tol) + assert_near_equal(prob[Aircraft.Wing.AVERAGE_CHORD], 16.2200522, tol) + assert_near_equal(prob[Aircraft.Wing.ROOT_CHORD], 20.33371617, tol) + assert_near_equal(prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.13596576, tol) + assert_near_equal(prob['wing_volume_no_fold'], 783.62100035, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 605.90781747, tol) + assert_near_equal(prob[Aircraft.Wing.FOLDING_AREA], 224.82529025, tol) + assert_near_equal(prob[Aircraft.Wing.EXPOSED_AREA], 1352.1135998, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) + + +class BWBExposedWingTestCase(unittest.TestCase): + """BWB case.""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'bwb_expo_wing', + ExposedWing(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 0.25970, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.274439991, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case_middle(self): + prob = self.prob + prob.set_val(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.run_model() + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Wing.EXPOSED_AREA], 1352.11359987, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=5e-11) + + +class ExposedWingTestCase(unittest.TestCase): + """Tube + Wing case.""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='transport', units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'expo_wing', + ExposedWing(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 1.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.274439991, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case_middle(self): + """Test in the range (epsilon, 1.0 - epsilon).""" + prob = self.prob + prob.set_val(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.run_model() + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Wing.EXPOSED_AREA], 1352.1135998, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=5e-11) + + def test_case_left(self): + """Test in the range (0.0, epsilon).""" + prob = self.prob + prob.set_val(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.049, units='unitless') + prob.run_model() + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Wing.EXPOSED_AREA], 1781.29634277, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=5e-11) + + def test_case_right(self): + prob = self.prob + """Test in the range (1.0 - epsilon, 1.0).""" + prob.set_val(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.951, units='unitless') + prob.run_model() + tol = 1e-7 + + assert_near_equal(prob[Aircraft.Wing.EXPOSED_AREA], 1781.29634277, tol) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=5e-10, rtol=5e-12) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/geometry/gasp_based/wing.py b/aviary/subsystems/geometry/gasp_based/wing.py index 122938c2db..34b38fa169 100644 --- a/aviary/subsystems/geometry/gasp_based/wing.py +++ b/aviary/subsystems/geometry/gasp_based/wing.py @@ -2,51 +2,43 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.geometry.gasp_based.non_dimensional_conversion import \ - DimensionalNonDimensionalInterchange +from aviary.subsystems.geometry.gasp_based.non_dimensional_conversion import ( + DimensionalNonDimensionalInterchange, +) from aviary.subsystems.geometry.gasp_based.strut import StrutGeom -from aviary.utils.aviary_values import AviaryValues from aviary.utils.conflict_checks import check_fold_location_definition -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission +from aviary.utils.functions import sigmoidX, dSigmoidXdx +from aviary.variable_info.enums import AircraftTypes, Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Mission, Settings class WingSize(om.ExplicitComponent): - """ - Computation of wing area and wing span for GASP-based aerodynamics. - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + """Computation of wing area and wing span for GASP-based aerodynamics.""" def setup(self): + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.WING_LOADING, units='lbf/ft**2') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') - add_aviary_input(self, Mission.Design.GROSS_MASS, val=152000) - add_aviary_input(self, Aircraft.Wing.LOADING, val=128) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) - - add_aviary_output(self, Aircraft.Wing.AREA, val=0) - add_aviary_output(self, Aircraft.Wing.SPAN, val=0) + add_aviary_output(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_output(self, Aircraft.Wing.SPAN, units='ft') self.declare_partials( - Aircraft.Wing.AREA, [Mission.Design.GROSS_MASS, Aircraft.Wing.LOADING] + Aircraft.Wing.AREA, [Mission.Design.GROSS_MASS, Aircraft.Design.WING_LOADING] ) self.declare_partials( Aircraft.Wing.SPAN, [ Aircraft.Wing.ASPECT_RATIO, Mission.Design.GROSS_MASS, - Aircraft.Wing.LOADING, + Aircraft.Design.WING_LOADING, ], ) def compute(self, inputs, outputs): - gross_mass_initial = inputs[Mission.Design.GROSS_MASS] - wing_loading = inputs[Aircraft.Wing.LOADING] + wing_loading = inputs[Aircraft.Design.WING_LOADING] AR = inputs[Aircraft.Wing.ASPECT_RATIO] wing_area = gross_mass_initial * GRAV_ENGLISH_LBM / wing_loading @@ -56,79 +48,48 @@ def compute(self, inputs, outputs): outputs[Aircraft.Wing.SPAN] = wingspan def compute_partials(self, inputs, J): - gross_mass_initial = inputs[Mission.Design.GROSS_MASS] - wing_loading = inputs[Aircraft.Wing.LOADING] + wing_loading = inputs[Aircraft.Design.WING_LOADING] AR = inputs[Aircraft.Wing.ASPECT_RATIO] wing_area = gross_mass_initial * GRAV_ENGLISH_LBM / wing_loading - J[Aircraft.Wing.AREA, - Mission.Design.GROSS_MASS] = dWA_dGMT = GRAV_ENGLISH_LBM / wing_loading - J[Aircraft.Wing.AREA, Aircraft.Wing.LOADING] = dWA_dWL = ( + J[Aircraft.Wing.AREA, Mission.Design.GROSS_MASS] = dWA_dGMT = ( + GRAV_ENGLISH_LBM / wing_loading + ) + J[Aircraft.Wing.AREA, Aircraft.Design.WING_LOADING] = dWA_dWL = ( -gross_mass_initial * GRAV_ENGLISH_LBM / wing_loading**2 ) - J[Aircraft.Wing.SPAN, Aircraft.Wing.ASPECT_RATIO] = ( - 0.5 * wing_area**0.5 * AR ** (-0.5) - ) + J[Aircraft.Wing.SPAN, Aircraft.Wing.ASPECT_RATIO] = 0.5 * wing_area**0.5 * AR ** (-0.5) J[Aircraft.Wing.SPAN, Mission.Design.GROSS_MASS] = ( 0.5 * AR**0.5 * wing_area ** (-0.5) * dWA_dGMT ) - J[Aircraft.Wing.SPAN, Aircraft.Wing.LOADING] = ( + J[Aircraft.Wing.SPAN, Aircraft.Design.WING_LOADING] = ( 0.5 * AR**0.5 * wing_area ** (-0.5) * dWA_dWL ) class WingParameters(om.ExplicitComponent): - """ - Computation of various wing parameters for GASP-based geometry. - """ - - def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + """Computation of various wing parameters for GASP-based geometry.""" def setup(self): - - add_aviary_input(self, Aircraft.Wing.AREA, val=2) - add_aviary_input(self, Aircraft.Wing.SPAN, val=2) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) - add_aviary_input(self, Aircraft.Wing.SWEEP, val=25) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11) - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=10) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, val=0.1) - - if not self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): - - add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6) - add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=0) - - self.declare_partials( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, - [ - Aircraft.Fuel.WING_FUEL_FRACTION, - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, - Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Wing.SPAN, - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, - Aircraft.Wing.AREA, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.ASPECT_RATIO, - ], - ) - - add_aviary_output(self, Aircraft.Wing.CENTER_CHORD, val=0) - add_aviary_output(self, Aircraft.Wing.AVERAGE_CHORD, val=0) - add_aviary_output(self, Aircraft.Wing.ROOT_CHORD, val=0) - add_aviary_output(self, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, val=0) - add_aviary_output(self, Aircraft.Wing.LEADING_EDGE_SWEEP, - val=0.4763948, units="rad") - + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, units='unitless') + + add_aviary_output(self, Aircraft.Wing.CENTER_CHORD, units='ft') + add_aviary_output(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') + add_aviary_output(self, Aircraft.Wing.ROOT_CHORD, units='ft') + add_aviary_output(self, Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, units='unitless') + add_aviary_output(self, Aircraft.Wing.LEADING_EDGE_SWEEP, units='rad') + + def setup_partials(self): self.declare_partials( Aircraft.Wing.CENTER_CHORD, [Aircraft.Wing.AREA, Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO], @@ -169,7 +130,6 @@ def setup(self): ) def compute(self, inputs, outputs): - wing_area = inputs[Aircraft.Wing.AREA] wingspan = inputs[Aircraft.Wing.SPAN] AR = inputs[Aircraft.Wing.ASPECT_RATIO] @@ -190,15 +150,11 @@ def compute(self, inputs, outputs): tan_sweep_TE = 3.0 * (taper_ratio - 1.0) / (1.0 + taper_ratio) / AR + np.tan( sweep_c4 * (np.pi / 180) ) - sweep_TE = np.arctan(tan_sweep_TE) + + # For BWB, this formula might need correction FHP = ( 2.0 - * ( - tc_ratio_root - * center_chord - * (cabin_width - (tc_ratio_root * center_chord)) - ) - ** 0.5 + * (tc_ratio_root * center_chord * (cabin_width - (tc_ratio_root * center_chord))) ** 0.5 + 0.4 ) HP = FHP * tan_sweep_LE / 2.0 @@ -214,20 +170,7 @@ def compute(self, inputs, outputs): outputs[Aircraft.Wing.ROOT_CHORD] = root_chord outputs[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED] = tc_ratio_avg - if not self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): - fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] - - geometric_fuel_vol = ( - fuel_vol_frac - * 0.888889 - * tc_ratio_avg - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - outputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = geometric_fuel_vol - def compute_partials(self, inputs, J): - wing_area = inputs[Aircraft.Wing.AREA] wingspan = inputs[Aircraft.Wing.SPAN] AR = inputs[Aircraft.Wing.ASPECT_RATIO] @@ -240,12 +183,7 @@ def compute_partials(self, inputs, J): center_chord = 2.0 * wing_area / wingspan / (1.0 + taper_ratio) FHP = ( 2.0 - * ( - tc_ratio_root - * center_chord - * (cabin_width - (tc_ratio_root * center_chord)) - ) - ** 0.5 + * (tc_ratio_root * center_chord * (cabin_width - (tc_ratio_root * center_chord))) ** 0.5 + 0.4 ) @@ -259,48 +197,26 @@ def compute_partials(self, inputs, J): dCenterChord_dWingArea = 2 / (wingspan * (1 + taper_ratio)) dCenterChord_dWingspan = -2 * wing_area / ((1 + taper_ratio) * wingspan**2) dCenterChord_dTaperRatio = -2 * wing_area / (wingspan * (1 + taper_ratio) ** 2) - dFHP_dTcRatioRoot = ( + dFHP_dtc_ratio_rootatioRoot = ( tc_ratio_root * center_chord * (cabin_width - tc_ratio_root * center_chord) - ) ** (-0.5) * ( - center_chord * cabin_width - 2 * tc_ratio_root * center_chord**2 - ) + ) ** (-0.5) * (center_chord * cabin_width - 2 * tc_ratio_root * center_chord**2) dFHP_dCabinWidth = ( - ( - tc_ratio_root - * center_chord - * (cabin_width - tc_ratio_root * center_chord) - ) - ** (-0.5) + (tc_ratio_root * center_chord * (cabin_width - tc_ratio_root * center_chord)) ** (-0.5) * tc_ratio_root * center_chord ) dFHP_dWingArea = ( - ( - tc_ratio_root - * center_chord - * (cabin_width - tc_ratio_root * center_chord) - ) - ** (-0.5) + (tc_ratio_root * center_chord * (cabin_width - tc_ratio_root * center_chord)) ** (-0.5) * (tc_ratio_root * cabin_width - 2 * tc_ratio_root**2 * center_chord) * dCenterChord_dWingArea ) dFHP_dWingspan = ( - ( - tc_ratio_root - * center_chord - * (cabin_width - tc_ratio_root * center_chord) - ) - ** (-0.5) + (tc_ratio_root * center_chord * (cabin_width - tc_ratio_root * center_chord)) ** (-0.5) * (tc_ratio_root * cabin_width - 2 * tc_ratio_root**2 * center_chord) * dCenterChord_dWingspan ) dFHP_dTaperRatio = ( - ( - tc_ratio_root - * center_chord - * (cabin_width - tc_ratio_root * center_chord) - ) - ** (-0.5) + (tc_ratio_root * center_chord * (cabin_width - tc_ratio_root * center_chord)) ** (-0.5) * (tc_ratio_root * cabin_width - 2 * tc_ratio_root**2 * center_chord) * dCenterChord_dTaperRatio ) @@ -313,9 +229,7 @@ def compute_partials(self, inputs, J): (np.pi / 180) * 1 / np.cos(sweep_c4 * (np.pi / 180)) ** 2 ) dTanSweepTE_dTaperRatio = ( - 3 - * ((1 + taper_ratio) * AR - (taper_ratio - 1) * AR) - / ((1 + taper_ratio) ** 2 * AR**2) + 3 * ((1 + taper_ratio) * AR - (taper_ratio - 1) * AR) / ((1 + taper_ratio) ** 2 * AR**2) ) dTanSweepTE_dAR = -3 * (taper_ratio - 1) / ((1 + taper_ratio) * AR**2) @@ -330,30 +244,26 @@ def compute_partials(self, inputs, J): + dFHP_dTaperRatio * (-tan_sweep_LE / 2 + tan_sweep_TE / 2) + FHP * (-dTanSweepLE_dTaperRatio / 2 + dTanSweepTE_dTaperRatio / 2) ) - dRootChord_dTcRatioRoot = dFHP_dTcRatioRoot * ( - -tan_sweep_LE / 2 + tan_sweep_TE / 2 - ) - dRootChord_dCabinWidth = dFHP_dCabinWidth * ( + dRootChord_dtc_ratio_rootatioRoot = dFHP_dtc_ratio_rootatioRoot * ( -tan_sweep_LE / 2 + tan_sweep_TE / 2 ) + dRootChord_dCabinWidth = dFHP_dCabinWidth * (-tan_sweep_LE / 2 + tan_sweep_TE / 2) dRootChord_dAR = FHP * (-dTanSweepLE_dAR / 2 + dTanSweepTE_dAR / 2) dRootChord_dSweepC4 = FHP * 0.5 * (-dTanSweepLE_dSweepC4 + dTanSweepTE_dSweepC4) J[Aircraft.Wing.ROOT_CHORD, Aircraft.Wing.AREA] = dRootChord_dWingArea J[Aircraft.Wing.ROOT_CHORD, Aircraft.Wing.SPAN] = dRootChord_dWingspan J[Aircraft.Wing.ROOT_CHORD, Aircraft.Wing.TAPER_RATIO] = dRootChord_dTaperRatio - J[ - Aircraft.Wing.ROOT_CHORD, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT - ] = dRootChord_dTcRatioRoot + J[Aircraft.Wing.ROOT_CHORD, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + dRootChord_dtc_ratio_rootatioRoot + ) J[Aircraft.Wing.ROOT_CHORD, Aircraft.Fuselage.AVG_DIAMETER] = dRootChord_dCabinWidth J[Aircraft.Wing.ROOT_CHORD, Aircraft.Wing.ASPECT_RATIO] = dRootChord_dAR J[Aircraft.Wing.ROOT_CHORD, Aircraft.Wing.SWEEP] = dRootChord_dSweepC4 J[Aircraft.Wing.CENTER_CHORD, Aircraft.Wing.AREA] = dCenterChord_dWingArea J[Aircraft.Wing.CENTER_CHORD, Aircraft.Wing.SPAN] = dCenterChord_dWingspan - J[ - Aircraft.Wing.CENTER_CHORD, Aircraft.Wing.TAPER_RATIO - ] = dCenterChord_dTaperRatio + J[Aircraft.Wing.CENTER_CHORD, Aircraft.Wing.TAPER_RATIO] = dCenterChord_dTaperRatio J[Aircraft.Wing.AVERAGE_CHORD, Aircraft.Wing.AREA] = ( (2.0 / 3.0) @@ -365,30 +275,18 @@ def compute_partials(self, inputs, J): * ((1.0 + taper_ratio) - (taper_ratio / (1.0 + taper_ratio))) * dCenterChord_dWingspan ) - J[ - Aircraft.Wing.AVERAGE_CHORD, Aircraft.Wing.TAPER_RATIO - ] = dCenterChord_dTaperRatio * (2.0 / 3.0) * ( - (1.0 + taper_ratio) - (taper_ratio / (1.0 + taper_ratio)) - ) + ( + J[Aircraft.Wing.AVERAGE_CHORD, Aircraft.Wing.TAPER_RATIO] = dCenterChord_dTaperRatio * ( + 2.0 / 3.0 + ) * ((1.0 + taper_ratio) - (taper_ratio / (1.0 + taper_ratio))) + ( 2.0 * center_chord / 3.0 - ) * ( - 1 - ((1 + taper_ratio) - taper_ratio) / (1.0 + taper_ratio) ** 2 - ) + ) * (1 - ((1 + taper_ratio) - taper_ratio) / (1.0 + taper_ratio) ** 2) - tc_ratio_avg = ( - (tc_ratio_root - cabin_width / wingspan * (tc_ratio_root - tc_ratio_tip)) - * (1.0 - cabin_width / wingspan * (1.0 - taper_ratio)) - + taper_ratio * tc_ratio_tip - ) / (1.0 + taper_ratio - cabin_width / wingspan * (1.0 - taper_ratio)) a = tc_ratio_root - cabin_width / wingspan * (tc_ratio_root - tc_ratio_tip) b = 1.0 - cabin_width / wingspan * (1.0 - taper_ratio) c = taper_ratio * tc_ratio_tip d = 1.0 + taper_ratio - cabin_width / wingspan * (1.0 - taper_ratio) - dAB_dCabW = ( - a * (taper_ratio - 1) / wingspan - + b * (tc_ratio_tip - tc_ratio_root) / wingspan - ) + dAB_dCabW = a * (taper_ratio - 1) / wingspan + b * (tc_ratio_tip - tc_ratio_root) / wingspan dD_dCabW = (taper_ratio - 1) / wingspan dAB_dWingspan = ( a * cabin_width * (1 - taper_ratio) / wingspan**2 @@ -401,22 +299,20 @@ def compute_partials(self, inputs, J): J[ Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, - ] = dTCA_dTCR = ( - (1 - cabin_width / wingspan) * b / d - ) - J[ - Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Fuselage.AVG_DIAMETER - ] = dTCA_dCabW = (d * dAB_dCabW - (a * b + c) * dD_dCabW) / d**2 - J[ - Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Wing.SPAN - ] = dTCA_dWingspan = (d * dAB_dWingspan - (a * b + c) * dD_dWingspan) / d**2 + ] = (1 - cabin_width / wingspan) * b / d + J[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Fuselage.AVG_DIAMETER] = ( + d * dAB_dCabW - (a * b + c) * dD_dCabW + ) / d**2 + J[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Wing.SPAN] = ( + d * dAB_dWingspan - (a * b + c) * dD_dWingspan + ) / d**2 J[ Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, - ] = dTCA_dTCT = (cabin_width / wingspan * b + taper_ratio) / d - J[ - Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Wing.TAPER_RATIO - ] = dTCA_dTR = (d * dABC_dTR - (a * b + c) * dD_dTR) / d**2 + ] = (cabin_width / wingspan * b + taper_ratio) / d + J[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, Aircraft.Wing.TAPER_RATIO] = ( + d * dABC_dTR - (a * b + c) * dD_dTR + ) / d**2 trp1 = taper_ratio + 1 swprad = np.pi * sweep_c4 / 180.0 @@ -430,316 +326,861 @@ def compute_partials(self, inputs, J): np.pi * AR**2 * trp1**2 / denom / 180 / np.cos(swprad) ** 2 ) - if not self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): - fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] - geometric_fuel_vol = ( - fuel_vol_frac - * 0.888889 - * tc_ratio_avg - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - num = ( - fuel_vol_frac - * 0.888889 - * tc_ratio_avg - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) - den = (AR**0.5) * ((taper_ratio + 1.0) ** 2.0) - dNum_dTR = ( - fuel_vol_frac - * 0.888889 - * dTCA_dTR - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - + fuel_vol_frac * 0.888889 * tc_ratio_avg * (wing_area**1.5) * 2 - ) - dDen_dTR = 2 * (AR**0.5) * (taper_ratio + 1.0) - - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuel.WING_FUEL_FRACTION] = ( - 0.888889 * tc_ratio_avg * (wing_area**1.5) * (2.0 * taper_ratio + 1.0) - ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.AREA] = ( - 1.5 - * ( - fuel_vol_frac - * 0.888889 - * tc_ratio_avg - * (wing_area**0.5) - * (2.0 * taper_ratio + 1.0) - ) - / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - ) - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.TAPER_RATIO] = ( - den * dNum_dTR - num * dDen_dTR - ) / den**2 - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.ASPECT_RATIO] = ( - -0.5 - * ( - fuel_vol_frac - * 0.888889 - * tc_ratio_avg - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) - / ((AR**1.5) * (taper_ratio + 1.0) ** 2.0) - ) - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( - fuel_vol_frac - * 0.888889 - * dTCA_dTCR - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuselage.AVG_DIAMETER] = ( - fuel_vol_frac - * 0.888889 - * dTCA_dCabW - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.SPAN] = ( - fuel_vol_frac - * 0.888889 - * dTCA_dWingspan - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = ( - fuel_vol_frac - * 0.888889 - * dTCA_dTCT - * (wing_area**1.5) - * (2.0 * taper_ratio + 1.0) - ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) - -class WingFold(om.ExplicitComponent): +class WingVolume(om.ExplicitComponent): """ - Computation of taper ratio between wing root and fold location, wing area of - part of wings that does not fold, mean value of thickess to chord ratio between - root and fold, aspect ratio of non-folding part of wing, wing tank fuel volume. + Computation of Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX without considering folds + for GASP-based geometry. If there are folds, it will be computed again in WingFold. """ def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) def setup(self): - - if not self.options["aviary_options"].get_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, units='unitless'): - self.add_input( - "strut_y", - val=25, - units="ft", - desc="YSTRUT: attachment location of strut", - ) - - self.declare_partials("nonfolded_taper_ratio", "strut_y") - self.declare_partials(Aircraft.Wing.FOLDING_AREA, "strut_y") - self.declare_partials("nonfolded_wing_area", "strut_y") - self.declare_partials("tc_ratio_mean_folded", "strut_y") - self.declare_partials("nonfolded_AR", "strut_y") - self.declare_partials(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, "strut_y") - - else: - self.declare_partials("nonfolded_taper_ratio", Aircraft.Wing.FOLDED_SPAN) - self.declare_partials(Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.FOLDED_SPAN) - self.declare_partials("nonfolded_wing_area", Aircraft.Wing.FOLDED_SPAN) - self.declare_partials("tc_ratio_mean_folded", Aircraft.Wing.FOLDED_SPAN) - self.declare_partials("nonfolded_AR", Aircraft.Wing.FOLDED_SPAN) - self.declare_partials(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, - Aircraft.Wing.FOLDED_SPAN) - - add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN, val=25, units='ft') - - add_aviary_input(self, Aircraft.Wing.AREA, val=200) - add_aviary_input(self, Aircraft.Wing.SPAN, val=118) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, val=0.1) - add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6) - - self.add_output( - "nonfolded_taper_ratio", - val=0.1, - units="unitless", - desc="SLM_NF: taper ratio between wing root and fold location", - ) - - add_aviary_output(self, Aircraft.Wing.FOLDING_AREA, val=50) - - self.add_output( - "nonfolded_wing_area", - val=150, - units="ft**2", - desc="SW_NF: wing area of part of wings that does not fold", - ) - self.add_output( - "tc_ratio_mean_folded", - val=0.12, - units="unitless", - desc="TCM: mean value of thickess to chord ratio between root and fold", - ) - self.add_output( - "nonfolded_AR", - val=10, - units="unitless", - desc="AR_NF: aspect ratio of non-folding part of wing", - ) - - add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=0) - - self.declare_partials( - "nonfolded_taper_ratio", - [Aircraft.Wing.AREA, Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO], - ) - self.declare_partials( - Aircraft.Wing.FOLDING_AREA, - [Aircraft.Wing.SPAN, Aircraft.Wing.AREA, Aircraft.Wing.TAPER_RATIO], - ) - self.declare_partials( - "nonfolded_wing_area", - [Aircraft.Wing.AREA, Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO], - ) - self.declare_partials( - "tc_ratio_mean_folded", - [ - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, - Aircraft.Wing.SPAN, - ], - ) - self.declare_partials( - "nonfolded_AR", - [Aircraft.Wing.AREA, Aircraft.Wing.SPAN, Aircraft.Wing.TAPER_RATIO], - ) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, units='unitless') + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, units='unitless') + + add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, units='ft**3') + + def setup_partials(self): self.declare_partials( Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, [ Aircraft.Fuel.WING_FUEL_FRACTION, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, + Aircraft.Fuselage.AVG_DIAMETER, Aircraft.Wing.SPAN, + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, Aircraft.Wing.AREA, Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.ASPECT_RATIO, ], ) def compute(self, inputs, outputs): - + if self.options[Aircraft.Wing.HAS_FOLD]: + print('Warning: Aircraft.Wing.HAS_FOLD should be False.') wing_area = inputs[Aircraft.Wing.AREA] wingspan = inputs[Aircraft.Wing.SPAN] + AR = inputs[Aircraft.Wing.ASPECT_RATIO] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] - if not self.options["aviary_options"].get_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, units='unitless'): - - strut_y = inputs["strut_y"] - location = strut_y - - else: - fold_y = inputs[Aircraft.Wing.FOLDED_SPAN] - location = fold_y / 2.0 - - root_chord_wing = 2 * wing_area / (wingspan * (1 + taper_ratio)) - tip_chord = taper_ratio * root_chord_wing - fold_chord = root_chord_wing + location * (tip_chord - root_chord_wing) / ( - wingspan / 2.0 - ) - nonfolded_taper_ratio = fold_chord / root_chord_wing - folding_area = (wingspan / 2.0 - location) * (fold_chord + tip_chord) - - nonfolded_wing_area = wing_area - folding_area - - if (wingspan / 2.0) < location: - raise ValueError( - "Error: The wingspan provided is less than the wingspan of the wing fold." - ) + tc_ratio_avg = ( + (tc_ratio_root - cabin_width / wingspan * (tc_ratio_root - tc_ratio_tip)) + * (1.0 - cabin_width / wingspan * (1.0 - taper_ratio)) + + taper_ratio * tc_ratio_tip + ) / (1.0 + taper_ratio - cabin_width / wingspan * (1.0 - taper_ratio)) - tc_ratio_fold = tc_ratio_root + location * (tc_ratio_tip - tc_ratio_root) / ( - wingspan / 2.0 - ) - tc_ratio_mean_folded = 0.5 * (tc_ratio_root + tc_ratio_fold) - nonfolded_AR = 4.0 * location**2 / nonfolded_wing_area geometric_fuel_vol = ( - fuel_vol_frac - * 0.888889 - * tc_ratio_mean_folded - * (nonfolded_wing_area**1.5) - * (2.0 * nonfolded_taper_ratio + 1.0) - ) / ((nonfolded_AR**0.5) * ((nonfolded_taper_ratio + 1.0) ** 2.0)) - - outputs["nonfolded_taper_ratio"] = nonfolded_taper_ratio - outputs[Aircraft.Wing.FOLDING_AREA] = folding_area - outputs["nonfolded_wing_area"] = nonfolded_wing_area - outputs["tc_ratio_mean_folded"] = tc_ratio_mean_folded - outputs["nonfolded_AR"] = nonfolded_AR + fuel_vol_frac * 0.888889 * tc_ratio_avg * (wing_area**1.5) * (2.0 * taper_ratio + 1.0) + ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) outputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = geometric_fuel_vol def compute_partials(self, inputs, J): - wing_area = inputs[Aircraft.Wing.AREA] wingspan = inputs[Aircraft.Wing.SPAN] + AR = inputs[Aircraft.Wing.ASPECT_RATIO] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] - fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] - if not self.options["aviary_options"].get_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, units='unitless'): - - strut_y = inputs["strut_y"] - location = strut_y - dLoc_dWingspan = 0 - dLoc_dy = 1 - wrt = "strut_y" - - else: - fold_y = inputs[Aircraft.Wing.FOLDED_SPAN] - wrt = Aircraft.Wing.FOLDED_SPAN - - location = fold_y / 2.0 - dLoc_dWingspan = 0 - dLoc_dy = 1 / 2 + tc_ratio_avg = ( + (tc_ratio_root - cabin_width / wingspan * (tc_ratio_root - tc_ratio_tip)) + * (1.0 - cabin_width / wingspan * (1.0 - taper_ratio)) + + taper_ratio * tc_ratio_tip + ) / (1.0 + taper_ratio - cabin_width / wingspan * (1.0 - taper_ratio)) + a = tc_ratio_root - cabin_width / wingspan * (tc_ratio_root - tc_ratio_tip) + b = 1.0 - cabin_width / wingspan * (1.0 - taper_ratio) + c = taper_ratio * tc_ratio_tip + d = 1.0 + taper_ratio - cabin_width / wingspan * (1.0 - taper_ratio) - root_chord_wing = 2 * wing_area / (wingspan * (1 + taper_ratio)) - tip_chord = taper_ratio * root_chord_wing - fold_chord = root_chord_wing + location * (tip_chord - root_chord_wing) / ( - wingspan / 2.0 - ) - nonfolded_taper_ratio = fold_chord / root_chord_wing - folding_area = (wingspan / 2.0 - location) * (fold_chord + tip_chord) - nonfolded_wing_area = wing_area - folding_area - tc_ratio_fold = tc_ratio_root + location * (tc_ratio_tip - tc_ratio_root) / ( - wingspan / 2.0 + dAB_dCabW = a * (taper_ratio - 1) / wingspan + b * (tc_ratio_tip - tc_ratio_root) / wingspan + dD_dCabW = (taper_ratio - 1) / wingspan + dAB_dWingspan = ( + a * cabin_width * (1 - taper_ratio) / wingspan**2 + + b * cabin_width * (tc_ratio_root - tc_ratio_tip) / wingspan**2 ) - tc_ratio_mean_folded = 0.5 * (tc_ratio_root + tc_ratio_fold) - nonfolded_AR = 4.0 * location**2 / nonfolded_wing_area + dD_dWingspan = cabin_width * (1 - taper_ratio) / wingspan**2 + dABC_dTR = a * cabin_width / wingspan + tc_ratio_tip + dD_dTR = 1 + cabin_width / wingspan - dRootChordWing_dWingArea = 2 / (wingspan * (1 + taper_ratio)) - dRootChordWing_dWingspan = -2 * wing_area / (wingspan**2 * (1 + taper_ratio)) - dRootChordWing_dTaperRatio = ( - -2 * wing_area / (wingspan * (1 + taper_ratio) ** 2) - ) + dTCA_dtc_ratio_root = (1 - cabin_width / wingspan) * b / d + dTCA_dCabW = (d * dAB_dCabW - (a * b + c) * dD_dCabW) / d**2 + dTCA_dWingspan = (d * dAB_dWingspan - (a * b + c) * dD_dWingspan) / d**2 + dTCA_dtc_ratio_tip = (cabin_width / wingspan * b + taper_ratio) / d + dTCA_dTR = (d * dABC_dTR - (a * b + c) * dD_dTR) / d**2 - dTipChord_dTaperRatio = ( - taper_ratio * dRootChordWing_dTaperRatio + root_chord_wing + fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] + num = fuel_vol_frac * 0.888889 * tc_ratio_avg * (wing_area**1.5) * (2.0 * taper_ratio + 1.0) + den = (AR**0.5) * ((taper_ratio + 1.0) ** 2.0) + dNum_dTR = ( + fuel_vol_frac * 0.888889 * dTCA_dTR * (wing_area**1.5) * (2.0 * taper_ratio + 1.0) + + fuel_vol_frac * 0.888889 * tc_ratio_avg * (wing_area**1.5) * 2 ) - dTipChord_dWingArea = taper_ratio * dRootChordWing_dWingArea - dTipChord_dWingspan = taper_ratio * dRootChordWing_dWingspan + dDen_dTR = 2 * (AR**0.5) * (taper_ratio + 1.0) - dFoldChord_dWingArea = dRootChordWing_dWingArea + location * ( - dTipChord_dWingArea - dRootChordWing_dWingArea - ) / (wingspan / 2) - dFoldChord_dWingspan = ( - dRootChordWing_dWingspan - + location + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuel.WING_FUEL_FRACTION] = ( + 0.888889 * tc_ratio_avg * (wing_area**1.5) * (2.0 * taper_ratio + 1.0) + ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.AREA] = ( + 1.5 + * ( + fuel_vol_frac + * 0.888889 + * tc_ratio_avg + * (wing_area**0.5) + * (2.0 * taper_ratio + 1.0) + ) + / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.TAPER_RATIO] = ( + den * dNum_dTR - num * dDen_dTR + ) / den**2 + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.ASPECT_RATIO] = ( + -0.5 + * ( + fuel_vol_frac + * 0.888889 + * tc_ratio_avg + * (wing_area**1.5) + * (2.0 * taper_ratio + 1.0) + ) + / ((AR**1.5) * (taper_ratio + 1.0) ** 2.0) + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + fuel_vol_frac + * 0.888889 + * dTCA_dtc_ratio_root + * (wing_area**1.5) + * (2.0 * taper_ratio + 1.0) + ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuselage.AVG_DIAMETER] = ( + fuel_vol_frac * 0.888889 * dTCA_dCabW * (wing_area**1.5) * (2.0 * taper_ratio + 1.0) + ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.SPAN] = ( + fuel_vol_frac * 0.888889 * dTCA_dWingspan * (wing_area**1.5) * (2.0 * taper_ratio + 1.0) + ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = ( + fuel_vol_frac + * 0.888889 + * dTCA_dtc_ratio_tip + * (wing_area**1.5) + * (2.0 * taper_ratio + 1.0) + ) / ((AR**0.5) * ((taper_ratio + 1.0) ** 2.0)) + + +class BWBWingVolume(om.ExplicitComponent): + """ + Computation of Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX for BWB + without considering fold for GASP-based geometry. If HAS_FOLD is True, + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX will be updated using this one. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + self.options.declare('mu', default=10.0, types=float) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input( + self, Aircraft.LandingGear.MAIN_GEAR_LOCATION, units='unitless', desc='YMG' + ) + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless', desc='TCR') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, units='unitless', desc='TCT') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft', desc='SWF') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') + # In GASP, the variable is CROOT. In Aviary, it is Aircraft.Wing.CENTER_CHORD + add_aviary_input(self, Aircraft.Wing.CENTER_CHORD, units='ft', desc='CROOT') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless', desc='SLM') + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, units='unitless', desc='SKWF') + + if self.options[Aircraft.Wing.HAS_FOLD]: + self.add_output('wing_volume_no_fold', units='ft**3', desc='FVOLW_GEOMX') + else: + add_aviary_output( + self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, units='ft**3', desc='FVOLW_GEOM' + ) + + def setup_partials(self): + if self.options[Aircraft.Wing.HAS_FOLD]: + self.declare_partials( + 'wing_volume_no_fold', + [ + Aircraft.LandingGear.MAIN_GEAR_LOCATION, + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, + Aircraft.Wing.SPAN, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.CENTER_CHORD, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Fuel.WING_FUEL_FRACTION, + ], + ) + else: + self.declare_partials( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, + [ + Aircraft.LandingGear.MAIN_GEAR_LOCATION, + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, + Aircraft.Wing.SPAN, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.CENTER_CHORD, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Fuel.WING_FUEL_FRACTION, + ], + ) + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + mu = self.options['mu'] + + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + loc_main_gear = inputs[Aircraft.LandingGear.MAIN_GEAR_LOCATION] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] + fuselage_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] + center_chort = inputs[Aircraft.Wing.CENTER_CHORD] + + if smooth: + WID_GRX = 6 * sigmoidX(loc_main_gear, 0.0, mu) + else: + if loc_main_gear > 0: + WID_GRX = 6 + else: + WID_GRX = 0 + + CTIP = taper_ratio * center_chort + TCF = ( + tc_ratio_root + - 2.0 * (0.5 * fuselage_width + WID_GRX) * (tc_ratio_root - tc_ratio_tip) / wingspan + ) + CFUEL = ( + center_chort + 2.0 * (0.5 * fuselage_width + WID_GRX) * (CTIP - center_chort) / wingspan + ) + if CFUEL == 0.0: + if verbosity > Verbosity.BRIEF: + print('warning: CFUEL is 0.0') + SW_NFX = (0.5 * wingspan - (0.5 * fuselage_width + WID_GRX)) * (CFUEL + CTIP) + if SW_NFX == 0.0: + if verbosity > Verbosity.BRIEF: + print('warning: SW_NFX is 0.0') + SLM_NFX = CTIP / CFUEL + AR_NFX = (wingspan - fuselage_width - 2.0 * WID_GRX) ** 2 / SW_NFX + if AR_NFX == 0.0: + if verbosity > Verbosity.BRIEF: + print('warning: AR_NFX is 0.0') + TCM = 0.5 * (TCF + tc_ratio_tip) + # 0.888889 is some empirical factor derived from historical data to estimate + # the wing fuel volume based on the wing geometric characteristics. + numer = fuel_vol_frac * 0.888889 * TCM * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + denom = AR_NFX**0.5 * (SLM_NFX + 1.0) ** 2 + FVOLW_GEOM = numer / denom + if self.options[Aircraft.Wing.HAS_FOLD]: + outputs['wing_volume_no_fold'] = FVOLW_GEOM + else: + outputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = FVOLW_GEOM + + def compute_partials(self, inputs, J): + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + mu = self.options['mu'] + + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + loc_main_gear = inputs[Aircraft.LandingGear.MAIN_GEAR_LOCATION] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] + fuselage_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wingspan = inputs[Aircraft.Wing.SPAN] + fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] + center_chort = inputs[Aircraft.Wing.CENTER_CHORD] + + if smooth: + WID_GRX = 6 * sigmoidX(loc_main_gear, 0.0, mu) + dWID_GRX_dloc_main_gear = dSigmoidXdx(loc_main_gear, 0.0, mu) / mu + else: + if loc_main_gear > 0: + WID_GRX = 6.0 + else: + WID_GRX = 0.0 + dWID_GRX_dloc_main_gear = 0.0 + + TCF = ( + tc_ratio_root + - 2.0 * (0.5 * fuselage_width + WID_GRX) * (tc_ratio_root - tc_ratio_tip) / wingspan + ) + dTCF_dloc_main_gear = ( + -2.0 * dWID_GRX_dloc_main_gear * (tc_ratio_root - tc_ratio_tip) / wingspan + ) + dTCF_dtaper_ratio = 0.0 + dTCF_dcenter_chord_wing = 0.0 + dTCF_dtc_ratio_root = 1.0 - 2.0 * (0.5 * fuselage_width + WID_GRX) / wingspan + dTCF_dtc_ratio_tip = 2.0 * (0.5 * fuselage_width + WID_GRX) / wingspan + dTCF_dSWF = -(tc_ratio_root - tc_ratio_tip) / wingspan + dTCF_dwingspan = ( + 2.0 * (0.5 * fuselage_width + WID_GRX) * (tc_ratio_root - tc_ratio_tip) / wingspan**2 + ) + + CFUEL = ( + center_chort + + 2.0 * (0.5 * fuselage_width + WID_GRX) * (taper_ratio - 1.0) * center_chort / wingspan + ) + dCFUEL_dcenter_chord_wing = ( + 1.0 + 2.0 * (0.5 * fuselage_width + WID_GRX) * (taper_ratio - 1.0) / wingspan + ) + dCFUEL_dSWF = (taper_ratio - 1.0) * center_chort / wingspan + dCFUEL_dloc_main_gear = 2.0 * dWID_GRX_dloc_main_gear * (taper_ratio - 1.0) / wingspan + dCFUEL_dtaper_ratio = 2.0 * (0.5 * fuselage_width + WID_GRX) * center_chort / wingspan + dCFUEL_dwingspan = ( + -2.0 + * (0.5 * fuselage_width + WID_GRX) + * (taper_ratio - 1.0) + * center_chort + / wingspan**2 + ) + + SW_NFX = (0.5 * wingspan - (0.5 * fuselage_width + WID_GRX)) * ( + CFUEL + taper_ratio * center_chort + ) + dSW_NFX_dcenter_chord_wing = (0.5 * wingspan - (0.5 * fuselage_width + WID_GRX)) * ( + dCFUEL_dcenter_chord_wing + taper_ratio + ) + dSW_NFX_dSWF = ( + -0.5 * (CFUEL + taper_ratio * center_chort) + + (0.5 * wingspan - (0.5 * fuselage_width + WID_GRX)) * dCFUEL_dSWF + ) + dSW_NFX_dloc_main_gear = -dWID_GRX_dloc_main_gear * (CFUEL + taper_ratio * center_chort) + dSW_NFX_dtaper_ratio = (0.5 * wingspan - (0.5 * fuselage_width + WID_GRX)) * ( + dCFUEL_dtaper_ratio + center_chort + ) + dSW_NFX_dwingspan = ( + 0.5 * (CFUEL + taper_ratio * center_chort) + + (0.5 * wingspan - (0.5 * fuselage_width + WID_GRX)) * dCFUEL_dwingspan + ) + + SLM_NFX = taper_ratio * center_chort / CFUEL + dtaper_ratio_NFX_dtaper_ratio = ( + center_chort / CFUEL - taper_ratio * center_chort * dCFUEL_dtaper_ratio / CFUEL**2 + ) + dtaper_ratio_NFX_dcenter_chord_wing = ( + taper_ratio / CFUEL - taper_ratio * center_chort * dCFUEL_dcenter_chord_wing / CFUEL**2 + ) + dtaper_ratio_NFX_dSWF = -taper_ratio * center_chort * dCFUEL_dSWF / CFUEL**2 + dtaper_ratio_NFX_dloc_main_gear = ( + -taper_ratio * center_chort * dCFUEL_dloc_main_gear / CFUEL**2 + ) + dtaper_ratio_NFX_dwingspan = -taper_ratio * center_chort * dCFUEL_dwingspan / CFUEL**2 + + AR_NFX = (wingspan - fuselage_width - 2.0 * WID_GRX) ** 2 / SW_NFX + dAR_NFX_dtaper_ratio = ( + -((wingspan - fuselage_width - 2.0 * WID_GRX) ** 2) * dSW_NFX_dtaper_ratio / SW_NFX**2 + ) + dAR_NFX_dcenter_chord_wing = ( + -((wingspan - fuselage_width - 2.0 * WID_GRX) ** 2) + * dSW_NFX_dcenter_chord_wing + / SW_NFX**2 + ) + dAR_NFX_dSWF = ( + -2 * (wingspan - fuselage_width - 2.0 * WID_GRX) / SW_NFX + - (wingspan - fuselage_width - 2.0 * WID_GRX) ** 2 * dSW_NFX_dSWF / SW_NFX**2 + ) + dAR_NFX_dloc_main_gear = ( + -((wingspan - fuselage_width - 2.0 * WID_GRX) ** 2) * dSW_NFX_dloc_main_gear / SW_NFX**2 + ) + dAR_NFX_dwingspan = ( + 2 * (wingspan - fuselage_width - 2.0 * WID_GRX) / SW_NFX + - (wingspan - fuselage_width - 2.0 * WID_GRX) ** 2 * dSW_NFX_dwingspan / SW_NFX**2 + ) + + TCM = 0.5 * (TCF + tc_ratio_tip) + dTCM_dloc_main_gear = 0.5 * dTCF_dloc_main_gear + dTCM_dtaper_ratio = 0.5 * dTCF_dtaper_ratio + dTCM_dcenter_chord_wing = 0.5 * dTCF_dcenter_chord_wing + dTCM_dtc_ratio_root = 0.5 * dTCF_dtc_ratio_root + dTCM_dtc_ratio_tip = 0.5 * dTCF_dtc_ratio_tip + 0.5 + dTCM_dSWF = 0.5 * dTCF_dSWF + dTCM_dwingspan = 0.5 * dTCF_dwingspan + + numer = fuel_vol_frac * 0.888889 * TCM * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + dnumer_dfuel_vol_frac = 0.888889 * TCM * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + dnumer_dloc_main_gear = ( + fuel_vol_frac * 0.888889 * dTCM_dloc_main_gear * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac + * 0.888889 + * TCM + * 1.5 + * dSW_NFX_dloc_main_gear + * SW_NFX**0.5 + * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac * 0.888889 * TCM * SW_NFX**1.5 * (2.0 * dtaper_ratio_NFX_dloc_main_gear) + ) + dnumer_dtaper_ratio = ( + fuel_vol_frac * 0.888889 * dTCM_dtaper_ratio * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac + * 0.888889 + * TCM + * 1.5 + * dSW_NFX_dtaper_ratio + * SW_NFX**0.5 + * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac * 0.888889 * TCM * SW_NFX**1.5 * (2.0 * dtaper_ratio_NFX_dtaper_ratio) + ) + dnumer_dcenter_chord_wing = ( + fuel_vol_frac * 0.888889 * dTCM_dcenter_chord_wing * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac + * 0.888889 + * TCM + * 1.5 + * dSW_NFX_dcenter_chord_wing + * SW_NFX**0.5 + * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac + * 0.888889 + * TCM + * SW_NFX**1.5 + * (2.0 * dtaper_ratio_NFX_dcenter_chord_wing) + ) + dnumer_dtc_ratio_root = ( + fuel_vol_frac * 0.888889 * dTCM_dtc_ratio_root * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + ) + dnumer_dtc_ratio_tip = ( + fuel_vol_frac * 0.888889 * dTCM_dtc_ratio_tip * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + ) + dnumer_dSWF = ( + fuel_vol_frac * 0.888889 * dTCM_dSWF * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac + * 0.888889 + * TCM + * 1.5 + * dSW_NFX_dSWF + * SW_NFX**0.5 + * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac * 0.888889 * TCM * SW_NFX**1.5 * (2.0 * dtaper_ratio_NFX_dSWF) + ) + dnumer_dwingspan = ( + fuel_vol_frac * 0.888889 * dTCM_dwingspan * SW_NFX**1.5 * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac + * 0.888889 + * TCM + * 1.5 + * dSW_NFX_dwingspan + * SW_NFX**0.5 + * (2.0 * SLM_NFX + 1.0) + + fuel_vol_frac * 0.888889 * TCM * SW_NFX**1.5 * (2.0 * dtaper_ratio_NFX_dwingspan) + ) + + denom = AR_NFX**0.5 * (SLM_NFX + 1.0) ** 2 + ddenom_dtaper_ratio = 0.5 * dAR_NFX_dtaper_ratio / AR_NFX**0.5 * ( + SLM_NFX + 1.0 + ) ** 2 + 2 * AR_NFX**0.5 * dtaper_ratio_NFX_dtaper_ratio * (SLM_NFX + 1.0) + ddenom_dcenter_chord_wing = 0.5 * dAR_NFX_dcenter_chord_wing / AR_NFX**0.5 * ( + SLM_NFX + 1.0 + ) ** 2 + 2 * AR_NFX**0.5 * dtaper_ratio_NFX_dcenter_chord_wing * (SLM_NFX + 1.0) + ddenom_dSWF = 0.5 * dAR_NFX_dSWF / AR_NFX**0.5 * ( + SLM_NFX + 1.0 + ) ** 2 + 2 * AR_NFX**0.5 * dtaper_ratio_NFX_dSWF * (SLM_NFX + 1.0) + ddenom_dloc_main_gear = 0.5 * dAR_NFX_dloc_main_gear / AR_NFX**0.5 * ( + SLM_NFX + 1.0 + ) ** 2 + 2 * AR_NFX**0.5 * dtaper_ratio_NFX_dloc_main_gear * (SLM_NFX + 1.0) + ddenom_dwingspan = 0.5 * dAR_NFX_dwingspan / AR_NFX**0.5 * ( + SLM_NFX + 1.0 + ) ** 2 + 2 * AR_NFX**0.5 * dtaper_ratio_NFX_dwingspan * (SLM_NFX + 1.0) + ddenom_dfuel_vol_frac = 0.0 + ddenom_dtc_ratio_root = 0.0 + ddenom_dtc_ratio_tip = 0.0 + + # FVOLW_GEOM = numer / denom + dFVOLW_GEOM_dfuel_vol_frac = ( + dnumer_dfuel_vol_frac * denom - numer * ddenom_dfuel_vol_frac + ) / denom**2 + dFVOLW_GEOM_dtc_ratio_root = ( + dnumer_dtc_ratio_root * denom - numer * ddenom_dtc_ratio_root + ) / denom**2 + dFVOLW_GEOM_dtc_ratio_tip = ( + dnumer_dtc_ratio_tip * denom - numer * ddenom_dtc_ratio_tip + ) / denom**2 + dFVOLW_GEOM_dloc_main_gear = ( + dnumer_dloc_main_gear * denom - numer * ddenom_dloc_main_gear + ) / denom**2 + dFVOLW_GEOM_dtaper_ratio = ( + dnumer_dtaper_ratio * denom - numer * ddenom_dtaper_ratio + ) / denom**2 + dFVOLW_GEOM_dcenter_chord_wing = ( + dnumer_dcenter_chord_wing * denom - numer * ddenom_dcenter_chord_wing + ) / denom**2 + dFVOLW_GEOM_dSWF = (dnumer_dSWF * denom - numer * ddenom_dSWF) / denom**2 + dFVOLW_GEOM_dwingspan = (dnumer_dwingspan * denom - numer * ddenom_dwingspan) / denom**2 + + if self.options[Aircraft.Wing.HAS_FOLD]: + J['wing_volume_no_fold', Aircraft.Fuel.WING_FUEL_FRACTION] = dFVOLW_GEOM_dfuel_vol_frac + J['wing_volume_no_fold', Aircraft.LandingGear.MAIN_GEAR_LOCATION] = ( + dFVOLW_GEOM_dloc_main_gear + ) + J['wing_volume_no_fold', Aircraft.Wing.TAPER_RATIO] = dFVOLW_GEOM_dtaper_ratio + J['wing_volume_no_fold', Aircraft.Wing.CENTER_CHORD] = dFVOLW_GEOM_dcenter_chord_wing + J['wing_volume_no_fold', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + dFVOLW_GEOM_dtc_ratio_root + ) + J['wing_volume_no_fold', Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = ( + dFVOLW_GEOM_dtc_ratio_tip + ) + J['wing_volume_no_fold', Aircraft.Fuselage.AVG_DIAMETER] = dFVOLW_GEOM_dSWF + J['wing_volume_no_fold', Aircraft.Wing.SPAN] = dFVOLW_GEOM_dwingspan + else: + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuel.WING_FUEL_FRACTION] = ( + dFVOLW_GEOM_dfuel_vol_frac + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.LandingGear.MAIN_GEAR_LOCATION] = ( + dFVOLW_GEOM_dloc_main_gear + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.TAPER_RATIO] = ( + dFVOLW_GEOM_dtaper_ratio + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.CENTER_CHORD] = ( + dFVOLW_GEOM_dcenter_chord_wing + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + dFVOLW_GEOM_dtc_ratio_root + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = ( + dFVOLW_GEOM_dtc_ratio_tip + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuselage.AVG_DIAMETER] = ( + dFVOLW_GEOM_dSWF + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.SPAN] = dFVOLW_GEOM_dwingspan + + +class WingFoldArea(om.ExplicitComponent): + """ + Computation of folding area. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.CHOOSE_FOLD_LOCATION) + + def setup(self): + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + self.add_input( + 'strut_y', val=25, units='ft', desc='YSTRUT: attachment location of strut' + ) + else: + add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN, units='ft') + + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + + add_aviary_output(self, Aircraft.Wing.FOLDING_AREA, units='ft**2') + + def setup_partials(self): + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + self.declare_partials(Aircraft.Wing.FOLDING_AREA, 'strut_y') + else: + self.declare_partials(Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.FOLDED_SPAN) + + self.declare_partials( + Aircraft.Wing.FOLDING_AREA, + [Aircraft.Wing.SPAN, Aircraft.Wing.AREA, Aircraft.Wing.TAPER_RATIO], + ) + + def compute(self, inputs, outputs): + wing_area = inputs[Aircraft.Wing.AREA] + wingspan = inputs[Aircraft.Wing.SPAN] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + strut_y = inputs['strut_y'] + location = strut_y + else: + fold_y = inputs[Aircraft.Wing.FOLDED_SPAN] + location = fold_y / 2.0 + + root_chord_wing = 2 * wing_area / (wingspan * (1 + taper_ratio)) + tip_chord = taper_ratio * root_chord_wing + fold_chord = root_chord_wing + location * (tip_chord - root_chord_wing) / (wingspan / 2.0) + folding_area = (wingspan / 2.0 - location) * (fold_chord + tip_chord) + + if (wingspan / 2.0) < location: + raise ValueError( + 'Error: The wingspan provided is less than the wingspan of the wing fold.' + ) + + outputs[Aircraft.Wing.FOLDING_AREA] = folding_area + + def compute_partials(self, inputs, J): + wing_area = inputs[Aircraft.Wing.AREA] + wingspan = inputs[Aircraft.Wing.SPAN] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + strut_y = inputs['strut_y'] + location = strut_y + dLoc_dWingspan = 0 + dLoc_dy = 1 + wrt = 'strut_y' + + else: + fold_y = inputs[Aircraft.Wing.FOLDED_SPAN] + wrt = Aircraft.Wing.FOLDED_SPAN + + location = fold_y / 2.0 + dLoc_dWingspan = 0 + dLoc_dy = 1 / 2 + + root_chord_wing = 2 * wing_area / (wingspan * (1 + taper_ratio)) + tip_chord = taper_ratio * root_chord_wing + fold_chord = root_chord_wing + location * (tip_chord - root_chord_wing) / (wingspan / 2.0) + + dRootChordWing_dWingArea = 2 / (wingspan * (1 + taper_ratio)) + dRootChordWing_dWingspan = -2 * wing_area / (wingspan**2 * (1 + taper_ratio)) + dRootChordWing_dTaperRatio = -2 * wing_area / (wingspan * (1 + taper_ratio) ** 2) + + dTipChord_dTaperRatio = taper_ratio * dRootChordWing_dTaperRatio + root_chord_wing + dTipChord_dWingArea = taper_ratio * dRootChordWing_dWingArea + dTipChord_dWingspan = taper_ratio * dRootChordWing_dWingspan + + dFoldChord_dWingArea = dRootChordWing_dWingArea + location * ( + dTipChord_dWingArea - dRootChordWing_dWingArea + ) / (wingspan / 2) + dFoldChord_dWingspan = ( + dRootChordWing_dWingspan + + location + * ( + (wingspan / 2) * (dTipChord_dWingspan - dRootChordWing_dWingspan) + - (tip_chord - root_chord_wing) * (1 / 2) + ) + / (wingspan / 2) ** 2 + + dLoc_dWingspan * (tip_chord - root_chord_wing) / (wingspan / 2.0) + ) + dFoldChord_dTaperRatio = dRootChordWing_dTaperRatio + location * ( + dTipChord_dTaperRatio - dRootChordWing_dTaperRatio + ) / (wingspan / 2) + + J[Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.AREA] = (wingspan / 2.0 - location) * ( + dFoldChord_dWingArea + dTipChord_dWingArea + ) + J[Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.SPAN] = (wingspan / 2.0 - location) * ( + dFoldChord_dWingspan + dTipChord_dWingspan + ) + (fold_chord + tip_chord) * (0.5 - dLoc_dWingspan) + J[Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.TAPER_RATIO] = (wingspan / 2.0 - location) * ( + dFoldChord_dTaperRatio + dTipChord_dTaperRatio + ) + J[Aircraft.Wing.FOLDING_AREA, wrt] = -dLoc_dy * (fold_chord + tip_chord) + ( + wingspan / 2 - location + ) * dLoc_dy * (tip_chord - root_chord_wing) / (wingspan / 2.0) + + +class WingFoldVolume(om.ExplicitComponent): + """ + Computation of taper ratio between wing root and fold location, wing area of + part of wings that does not fold, mean value of thickess to chord ratio between + root and fold, aspect ratio of non-folding part of wing, wing tank fuel volume. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.CHOOSE_FOLD_LOCATION) + + def setup(self): + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + self.add_input( + 'strut_y', val=25, units='ft', desc='YSTRUT: attachment location of strut' + ) + else: + add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN) + + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, units='unitless') + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.Wing.FOLDING_AREA, units='ft**2') + + # all of the non-Aviary variable outputs are not needed. + self.add_output( + 'nonfolded_taper_ratio', + val=0.1, + units='unitless', + desc='SLM_NF: taper ratio between wing root and fold location', + ) + self.add_output( + 'nonfolded_wing_area', + val=150, + units='ft**2', + desc='SW_NF: wing area of part of wings that does not fold', + ) + self.add_output( + 'tc_ratio_mean_folded', + val=0.12, + units='unitless', + desc='TCM: mean value of thickess to chord ratio between root and fold', + ) + self.add_output( + 'nonfolded_AR', + val=10, + units='unitless', + desc='AR_NF: aspect ratio of non-folding part of wing', + ) + + add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, units='ft**3') + + def setup_partials(self): + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + self.declare_partials('nonfolded_taper_ratio', 'strut_y') + self.declare_partials('nonfolded_wing_area', 'strut_y') + self.declare_partials('tc_ratio_mean_folded', 'strut_y') + self.declare_partials('nonfolded_AR', 'strut_y') + self.declare_partials(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 'strut_y') + else: + self.declare_partials('nonfolded_taper_ratio', Aircraft.Wing.FOLDED_SPAN) + self.declare_partials('nonfolded_wing_area', Aircraft.Wing.FOLDED_SPAN) + self.declare_partials('tc_ratio_mean_folded', Aircraft.Wing.FOLDED_SPAN) + self.declare_partials('nonfolded_AR', Aircraft.Wing.FOLDED_SPAN) + self.declare_partials( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.FOLDED_SPAN + ) + + self.declare_partials( + 'nonfolded_taper_ratio', + [ + Aircraft.Wing.AREA, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + ], + ) + self.declare_partials( + 'nonfolded_wing_area', + [ + Aircraft.Wing.AREA, + Aircraft.Wing.FOLDING_AREA, + ], + ) + self.declare_partials( + 'tc_ratio_mean_folded', + [ + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, + Aircraft.Wing.SPAN, + ], + ) + self.declare_partials( + 'nonfolded_AR', + [ + Aircraft.Wing.AREA, + Aircraft.Wing.SPAN, + Aircraft.Wing.FOLDING_AREA, + ], + ) + self.declare_partials( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, + [ + Aircraft.Fuel.WING_FUEL_FRACTION, + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, + Aircraft.Wing.SPAN, + Aircraft.Wing.AREA, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.FOLDING_AREA, + ], + ) + + def compute(self, inputs, outputs): + wing_area = inputs[Aircraft.Wing.AREA] + wingspan = inputs[Aircraft.Wing.SPAN] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] + fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] + folding_area = inputs[Aircraft.Wing.FOLDING_AREA] + + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + strut_y = inputs['strut_y'] + location = strut_y + + else: + fold_y = inputs[Aircraft.Wing.FOLDED_SPAN] + location = fold_y / 2.0 + + root_chord_wing = 2 * wing_area / (wingspan * (1 + taper_ratio)) + tip_chord = taper_ratio * root_chord_wing + fold_chord = root_chord_wing + location * (tip_chord - root_chord_wing) / (wingspan / 2.0) + nonfolded_taper_ratio = fold_chord / root_chord_wing + nonfolded_wing_area = wing_area - folding_area + + tc_ratio_fold = tc_ratio_root + location * (tc_ratio_tip - tc_ratio_root) / (wingspan / 2.0) + tc_ratio_mean_folded = 0.5 * (tc_ratio_root + tc_ratio_fold) + nonfolded_AR = 4.0 * location**2 / nonfolded_wing_area + geometric_fuel_vol = ( + fuel_vol_frac + * 0.888889 + * tc_ratio_mean_folded + * (nonfolded_wing_area**1.5) + * (2.0 * nonfolded_taper_ratio + 1.0) + ) / ((nonfolded_AR**0.5) * ((nonfolded_taper_ratio + 1.0) ** 2.0)) + + outputs['nonfolded_taper_ratio'] = nonfolded_taper_ratio + outputs['nonfolded_wing_area'] = nonfolded_wing_area + outputs['tc_ratio_mean_folded'] = tc_ratio_mean_folded + outputs['nonfolded_AR'] = nonfolded_AR + outputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = geometric_fuel_vol + + def compute_partials(self, inputs, J): + wing_area = inputs[Aircraft.Wing.AREA] + wingspan = inputs[Aircraft.Wing.SPAN] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] + fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] + folding_area = inputs[Aircraft.Wing.FOLDING_AREA] + + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + strut_y = inputs['strut_y'] + location = strut_y + dLoc_dWingspan = 0 + dLoc_dy = 1 + wrt = 'strut_y' + + else: + fold_y = inputs[Aircraft.Wing.FOLDED_SPAN] + wrt = Aircraft.Wing.FOLDED_SPAN + + location = fold_y / 2.0 + dLoc_dWingspan = 0 + dLoc_dy = 1 / 2 + + root_chord_wing = 2 * wing_area / (wingspan * (1 + taper_ratio)) + dRootChordWing_dWingArea = 2 / (wingspan * (1 + taper_ratio)) + dRootChordWing_dWingspan = -2 * wing_area / (wingspan**2 * (1 + taper_ratio)) + dRootChordWing_dTaperRatio = -2 * wing_area / (wingspan * (1 + taper_ratio) ** 2) + + tip_chord = taper_ratio * root_chord_wing + dTipChord_dTaperRatio = taper_ratio * dRootChordWing_dTaperRatio + root_chord_wing + dTipChord_dWingArea = taper_ratio * dRootChordWing_dWingArea + dTipChord_dWingspan = taper_ratio * dRootChordWing_dWingspan + + fold_chord = root_chord_wing + location * (tip_chord - root_chord_wing) / (wingspan / 2.0) + dFoldChord_dWingArea = dRootChordWing_dWingArea + location * ( + dTipChord_dWingArea - dRootChordWing_dWingArea + ) / (wingspan / 2) + dFoldChord_dWingspan = ( + dRootChordWing_dWingspan + + location * ( (wingspan / 2) * (dTipChord_dWingspan - dRootChordWing_dWingspan) - (tip_chord - root_chord_wing) * (1 / 2) @@ -752,139 +1193,79 @@ def compute_partials(self, inputs, J): ) / (wingspan / 2) dFoldChord_dy = dLoc_dy * (tip_chord - root_chord_wing) / (wingspan / 2.0) - dTcRatioFold_dTCR = 1 + location * (-1) / (wingspan / 2) - dTcRatioFold_dTCT = location / (wingspan / 2) - dTcRatioFold_dWingspan = ( - (tc_ratio_tip - tc_ratio_root) - * ((wingspan / 2) * dLoc_dWingspan - location * 0.5) - / (wingspan / 2) ** 2 - ) - dTcRatioFold_dy = dLoc_dy * (tc_ratio_tip - tc_ratio_root) / (wingspan / 2.0) - - J["nonfolded_taper_ratio", Aircraft.Wing.AREA] = dNFTR_dWingArea = ( - root_chord_wing * dFoldChord_dWingArea - - fold_chord * dRootChordWing_dWingArea + nonfolded_taper_ratio = fold_chord / root_chord_wing + dNFTR_dWingArea = ( + root_chord_wing * dFoldChord_dWingArea - fold_chord * dRootChordWing_dWingArea ) / root_chord_wing**2 - J["nonfolded_taper_ratio", Aircraft.Wing.SPAN] = dNFTR_dWingspan = ( - root_chord_wing * dFoldChord_dWingspan - - fold_chord * dRootChordWing_dWingspan + dNFTR_dWingspan = ( + root_chord_wing * dFoldChord_dWingspan - fold_chord * dRootChordWing_dWingspan ) / root_chord_wing**2 - J["nonfolded_taper_ratio", Aircraft.Wing.TAPER_RATIO] = dNFTR_dTaperRatio = ( - root_chord_wing * dFoldChord_dTaperRatio - - fold_chord * dRootChordWing_dTaperRatio + dNFTR_dTaperRatio = ( + root_chord_wing * dFoldChord_dTaperRatio - fold_chord * dRootChordWing_dTaperRatio ) / root_chord_wing**2 - J["nonfolded_taper_ratio", wrt] = dNFTR_dy = dFoldChord_dy / root_chord_wing + dNFTR_dy = dFoldChord_dy / root_chord_wing - J[Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.AREA] = dFoldingArea_dWingArea = ( - wingspan / 2.0 - location - ) * (dFoldChord_dWingArea + dTipChord_dWingArea) - J[Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.SPAN] = dFoldingArea_dWingspan = ( - wingspan / 2.0 - location - ) * (dFoldChord_dWingspan + dTipChord_dWingspan) + (fold_chord + tip_chord) * ( - 0.5 - dLoc_dWingspan - ) - J[ - Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.TAPER_RATIO - ] = dFoldingArea_dTaperRatio = (wingspan / 2.0 - location) * ( - dFoldChord_dTaperRatio + dTipChord_dTaperRatio - ) - J[Aircraft.Wing.FOLDING_AREA, wrt] = dFoldingArea_dy = -dLoc_dy * ( - fold_chord + tip_chord - ) + (wingspan / 2 - location) * dLoc_dy * (tip_chord - root_chord_wing) / ( - wingspan / 2.0 - ) + J['nonfolded_taper_ratio', Aircraft.Wing.AREA] = dNFTR_dWingArea + J['nonfolded_taper_ratio', Aircraft.Wing.SPAN] = dNFTR_dWingspan + J['nonfolded_taper_ratio', Aircraft.Wing.TAPER_RATIO] = dNFTR_dTaperRatio + J['nonfolded_taper_ratio', wrt] = dNFTR_dy - J["nonfolded_wing_area", Aircraft.Wing.AREA] = dNFWA_dWingArea = ( - 1 - dFoldingArea_dWingArea + nonfolded_wing_area = wing_area - folding_area + dNFWA_dWingArea = 1 + dNFWA_dWingFoldArea = -1 + J['nonfolded_wing_area', Aircraft.Wing.AREA] = dNFWA_dWingArea + J['nonfolded_wing_area', Aircraft.Wing.FOLDING_AREA] = dNFWA_dWingFoldArea + + tc_ratio_fold = tc_ratio_root + location * (tc_ratio_tip - tc_ratio_root) / (wingspan / 2.0) + dtc_ratio_rootatioFold_dtc_ratio_root = 1 + location * (-1) / (wingspan / 2) + dtc_ratio_rootatioFold_dtc_ratio_tip = location / (wingspan / 2) + dtc_ratio_rootatioFold_dWingspan = ( + (tc_ratio_tip - tc_ratio_root) + * ((wingspan / 2) * dLoc_dWingspan - location * 0.5) + / (wingspan / 2) ** 2 ) - J[ - "nonfolded_wing_area", Aircraft.Wing.SPAN - ] = dNFWA_dWingspan = -dFoldingArea_dWingspan - J[ - "nonfolded_wing_area", Aircraft.Wing.TAPER_RATIO - ] = dNFWA_dTaperRatio = -dFoldingArea_dTaperRatio - J["nonfolded_wing_area", wrt] = dNFWA_dy = -dFoldingArea_dy + dtc_ratio_rootatioFold_dy = dLoc_dy * (tc_ratio_tip - tc_ratio_root) / (wingspan / 2.0) - J[ - "tc_ratio_mean_folded", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT - ] = dTCRMeanFolded_dTCR = 0.5 * (1 + dTcRatioFold_dTCR) - J[ - "tc_ratio_mean_folded", Aircraft.Wing.THICKNESS_TO_CHORD_TIP - ] = dTCRMeanFolded_dTCT = (0.5 * dTcRatioFold_dTCT) - J["tc_ratio_mean_folded", Aircraft.Wing.SPAN] = dTCRMeanFolded_dWingspan = ( - 0.5 * dTcRatioFold_dWingspan - ) - J["tc_ratio_mean_folded", wrt] = dTCRMeanFolded_dy = 0.5 * dTcRatioFold_dy + tc_ratio_mean_folded = 0.5 * (tc_ratio_root + tc_ratio_fold) + dtc_ratio_rootMeanFolded_dtc_ratio_root = 0.5 * (1 + dtc_ratio_rootatioFold_dtc_ratio_root) + dtc_ratio_rootMeanFolded_dtc_ratio_tip = 0.5 * dtc_ratio_rootatioFold_dtc_ratio_tip + dtc_ratio_rootMeanFolded_dWingspan = 0.5 * dtc_ratio_rootatioFold_dWingspan + dtc_ratio_rootMeanFolded_dy = 0.5 * dtc_ratio_rootatioFold_dy - J["nonfolded_AR", Aircraft.Wing.AREA] = dNFAR_dWingArea = ( - -4 * location**2 / nonfolded_wing_area**2 * dNFWA_dWingArea - ) - J["nonfolded_AR", Aircraft.Wing.SPAN] = dNFAR_dWingspan = ( - 4 - * ( - nonfolded_wing_area * 2 * location * dLoc_dWingspan - - location**2 * dNFWA_dWingspan - ) - / nonfolded_wing_area**2 + J['tc_ratio_mean_folded', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + dtc_ratio_rootMeanFolded_dtc_ratio_root ) - J["nonfolded_AR", Aircraft.Wing.TAPER_RATIO] = dNFAR_dTaperRatio = ( - -4 * location**2 / nonfolded_wing_area**2 * dNFWA_dTaperRatio - ) - J["nonfolded_AR", wrt] = dNFAR_dy = ( - 4 - * (nonfolded_wing_area * 2 * location * dLoc_dy - location**2 * dNFWA_dy) - / nonfolded_wing_area**2 + J['tc_ratio_mean_folded', Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = ( + dtc_ratio_rootMeanFolded_dtc_ratio_tip ) + J['tc_ratio_mean_folded', Aircraft.Wing.SPAN] = dtc_ratio_rootMeanFolded_dWingspan + J['tc_ratio_mean_folded', wrt] = dtc_ratio_rootMeanFolded_dy - geometric_fuel_vol = ( - fuel_vol_frac - * 0.888889 - * tc_ratio_mean_folded - * (nonfolded_wing_area**1.5) - * (2.0 * nonfolded_taper_ratio + 1.0) - ) / ((nonfolded_AR**0.5) * ((nonfolded_taper_ratio + 1.0) ** 2.0)) - a = (nonfolded_wing_area**1.5) * (2.0 * nonfolded_taper_ratio + 1.0) - num = fuel_vol_frac * 0.888889 * tc_ratio_mean_folded * a - den = (nonfolded_AR**0.5) * ((nonfolded_taper_ratio + 1.0) ** 2.0) + nonfolded_AR = 4.0 * location**2 / nonfolded_wing_area + dNFAR_dWingArea = -4.0 * location**2 / nonfolded_wing_area**2 + dNFAR_dWingFoldArea = 4.0 * location**2 / nonfolded_wing_area**2 + dNFAR_dWingspan = 4.0 * (2.0 * location * dLoc_dWingspan) / nonfolded_wing_area + dNFAR_dTaperRatio = 0 + dNFAR_dy = 4 * (2.0 * location * dLoc_dy) / nonfolded_wing_area - dA_dWingspan = ( - 1.5 - * nonfolded_wing_area**0.5 - * dNFWA_dWingspan - * (2 * nonfolded_taper_ratio + 1) - + nonfolded_wing_area**1.5 * 2 * dNFTR_dWingspan - ) - dA_dy = ( - 1.5 - * nonfolded_wing_area**0.5 - * dNFWA_dy - * (2 * nonfolded_taper_ratio + 1) - + nonfolded_wing_area**1.5 * 2 * dNFTR_dy - ) + J['nonfolded_AR', Aircraft.Wing.AREA] = dNFAR_dWingArea + J['nonfolded_AR', Aircraft.Wing.FOLDING_AREA] = dNFAR_dWingFoldArea + J['nonfolded_AR', Aircraft.Wing.SPAN] = dNFAR_dWingspan + J['nonfolded_AR', wrt] = dNFAR_dy + a = (nonfolded_wing_area**1.5) * (2.0 * nonfolded_taper_ratio + 1.0) + dA_dWingspan = nonfolded_wing_area**1.5 * 2 * dNFTR_dWingspan + dA_dy = nonfolded_wing_area**1.5 * 2 * dNFTR_dy + + num = fuel_vol_frac * 0.888889 * tc_ratio_mean_folded * a dNum_dWingspan = ( - fuel_vol_frac * 0.888889 * dTCRMeanFolded_dWingspan * a + fuel_vol_frac * 0.888889 * dtc_ratio_rootMeanFolded_dWingspan * a + fuel_vol_frac * 0.888889 * tc_ratio_mean_folded * dA_dWingspan ) - dDen_dWingspan = ( - 0.5 - * (nonfolded_AR ** (-0.5)) - * dNFAR_dWingspan - * ((nonfolded_taper_ratio + 1.0) ** 2.0) - + ((nonfolded_AR**0.5) * 2 * ((nonfolded_taper_ratio + 1.0))) - * dNFTR_dWingspan - ) dNum_dy = ( - fuel_vol_frac * 0.888889 * dTCRMeanFolded_dy * a + fuel_vol_frac * 0.888889 * dtc_ratio_rootMeanFolded_dy * a + fuel_vol_frac * 0.888889 * tc_ratio_mean_folded * dA_dy ) - dDen_dy = ( - 0.5 - * (nonfolded_AR ** (-0.5)) - * dNFAR_dy - * ((nonfolded_taper_ratio + 1.0) ** 2.0) - + ((nonfolded_AR**0.5) * 2 * ((nonfolded_taper_ratio + 1.0))) * dNFTR_dy - ) dNum_dWingArea = ( fuel_vol_frac * 0.888889 @@ -894,42 +1275,54 @@ def compute_partials(self, inputs, J): * dNFWA_dWingArea * (2.0 * nonfolded_taper_ratio + 1.0) ) + ( + fuel_vol_frac * 0.888889 * tc_ratio_mean_folded * (nonfolded_wing_area**1.5) * 2 + ) * dNFTR_dWingArea + dNum_dWingFoldArea = ( fuel_vol_frac * 0.888889 * tc_ratio_mean_folded - * (nonfolded_wing_area**1.5) - * 2 - ) * dNFTR_dWingArea + * 1.5 + * (nonfolded_wing_area**0.5) + * dNFWA_dWingFoldArea + * (2.0 * nonfolded_taper_ratio + 1.0) + ) + + dNum_dTaperRatio = ( + fuel_vol_frac * 0.888889 * tc_ratio_mean_folded * (nonfolded_wing_area**1.5) * 2 + ) * dNFTR_dTaperRatio + + den = (nonfolded_AR**0.5) * ((nonfolded_taper_ratio + 1.0) ** 2.0) + + dDen_dWingspan = ( + 0.5 + * (nonfolded_AR ** (-0.5)) + * dNFAR_dWingspan + * ((nonfolded_taper_ratio + 1.0) ** 2.0) + + ((nonfolded_AR**0.5) * 2 * (nonfolded_taper_ratio + 1.0)) * dNFTR_dWingspan + ) + dDen_dy = ( + 0.5 * (nonfolded_AR ** (-0.5)) * dNFAR_dy * ((nonfolded_taper_ratio + 1.0) ** 2.0) + + ((nonfolded_AR**0.5) * 2 * (nonfolded_taper_ratio + 1.0)) * dNFTR_dy + ) dDen_dWingArea = ( 0.5 * (nonfolded_AR ** (-0.5)) * dNFAR_dWingArea * ((nonfolded_taper_ratio + 1.0) ** 2.0) - + ((nonfolded_AR**0.5) * 2 * ((nonfolded_taper_ratio + 1.0))) - * dNFTR_dWingArea + + ((nonfolded_AR**0.5) * 2 * (nonfolded_taper_ratio + 1.0)) * dNFTR_dWingArea + ) + dDen_dWingFoldArea = ( + 0.5 + * (nonfolded_AR ** (-0.5)) + * dNFAR_dWingFoldArea + * ((nonfolded_taper_ratio + 1.0) ** 2.0) ) - dNum_dTaperRatio = ( - fuel_vol_frac - * 0.888889 - * tc_ratio_mean_folded - * 1.5 - * (nonfolded_wing_area**0.5) - * dNFWA_dTaperRatio - * (2.0 * nonfolded_taper_ratio + 1.0) - ) + ( - fuel_vol_frac - * 0.888889 - * tc_ratio_mean_folded - * (nonfolded_wing_area**1.5) - * 2 - ) * dNFTR_dTaperRatio dDen_dTaperRatio = ( 0.5 * (nonfolded_AR ** (-0.5)) * dNFAR_dTaperRatio * ((nonfolded_taper_ratio + 1.0) ** 2.0) - + ((nonfolded_AR**0.5) * 2 * ((nonfolded_taper_ratio + 1.0))) - * dNFTR_dTaperRatio + + ((nonfolded_AR**0.5) * 2 * (nonfolded_taper_ratio + 1.0)) * dNFTR_dTaperRatio ) J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuel.WING_FUEL_FRACTION] = ( @@ -941,14 +1334,14 @@ def compute_partials(self, inputs, J): J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( fuel_vol_frac * 0.888889 - * dTCRMeanFolded_dTCR + * dtc_ratio_rootMeanFolded_dtc_ratio_root * (nonfolded_wing_area**1.5) * (2.0 * nonfolded_taper_ratio + 1.0) ) / ((nonfolded_AR**0.5) * ((nonfolded_taper_ratio + 1.0) ** 2.0)) J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = ( fuel_vol_frac * 0.888889 - * dTCRMeanFolded_dTCT + * dtc_ratio_rootMeanFolded_dtc_ratio_tip * (nonfolded_wing_area**1.5) * (2.0 * nonfolded_taper_ratio + 1.0) ) / ((nonfolded_AR**0.5) * ((nonfolded_taper_ratio + 1.0) ** 2.0)) @@ -958,81 +1351,630 @@ def compute_partials(self, inputs, J): J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.AREA] = ( den * dNum_dWingArea - num * dDen_dWingArea ) / den**2 + + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.FOLDING_AREA] = ( + den * dNum_dWingFoldArea - num * dDen_dWingFoldArea + ) / den**2 + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.TAPER_RATIO] = ( den * dNum_dTaperRatio - num * dDen_dTaperRatio ) / den**2 - J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, wrt] = ( - den * dNum_dy - num * dDen_dy) / den**2 + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, wrt] = (den * dNum_dy - num * dDen_dy) / den**2 -class WingGroup(om.Group): +class BWBWingFoldVolume(om.ExplicitComponent): """ - Group of WingSize, WingParameters, and WingFold for wing parameter computations. + Computation of wing tank fuel volume. """ def initialize(self): + add_aviary_option(self, Aircraft.Wing.CHOOSE_FOLD_LOCATION) + + def setup(self): + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + self.add_input( + 'strut_y', val=25, units='ft', desc='YSTRUT: attachment location of strut' + ) + else: + add_aviary_input(self, Aircraft.Wing.FOLDED_SPAN) + + self.add_input('wing_volume_no_fold', units='ft**3', desc='FVOLW_GEOMX') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_TIP, units='unitless') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + + add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, units='ft**3') + + def setup_partials(self): + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + self.declare_partials(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 'strut_y') + else: + self.declare_partials( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.FOLDED_SPAN + ) + + self.declare_partials( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, + [ + 'wing_volume_no_fold', + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, + Aircraft.Wing.SPAN, + ], + ) + + def compute(self, inputs, outputs): + wingspan = inputs[Aircraft.Wing.SPAN] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] + fuselage_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wing_volume_no_fold = inputs['wing_volume_no_fold'] + + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + strut_span = inputs['strut_y'] # assume fold at strut location + fold_span = strut_span * 2.0 + else: + fold_span = inputs[Aircraft.Wing.FOLDED_SPAN] + location = fold_span / 2.0 + + tc_ratio_fold = tc_ratio_root + 2.0 * location * (tc_ratio_tip - tc_ratio_root) / wingspan + tc_fac = (1.0 + tc_ratio_fold / tc_ratio_root) / (1.0 + tc_ratio_tip / tc_ratio_root) + geometric_fuel_vol = ( + tc_fac + * (fold_span - fuselage_width) + / (wingspan - fuselage_width) + * wing_volume_no_fold + ) + outputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = geometric_fuel_vol + + def compute_partials(self, inputs, J): + wingspan = inputs[Aircraft.Wing.SPAN] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + tc_ratio_tip = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_TIP] + fuselage_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + wing_volume_no_fold = inputs['wing_volume_no_fold'] + + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + strut_span = inputs['strut_y'] + fold_span = strut_span * 2.0 + wrt = 'strut_y' + dLoc_dspan = 1 + else: + fold_span = inputs[Aircraft.Wing.FOLDED_SPAN] + wrt = Aircraft.Wing.FOLDED_SPAN + dLoc_dspan = 1 / 2 + location = fold_span / 2.0 + dlocation_wrt = dLoc_dspan + + tc_ratio_fold = tc_ratio_root + 2.0 * location * (tc_ratio_tip - tc_ratio_root) / wingspan + dtc_ratio_fold_wrt = 2.0 * dlocation_wrt * (tc_ratio_tip - tc_ratio_root) / wingspan + dtc_ratio_fold_dwingspan = -2.0 * location * (tc_ratio_tip - tc_ratio_root) / wingspan**2 + dtc_ratio_fold_dtc_ratio_root = 1 - 2.0 * location / wingspan + dtc_ratio_fold_dtc_ratio_tip = 2.0 * location / wingspan + + u = 1.0 + tc_ratio_fold / tc_ratio_root + v = 1.0 + tc_ratio_tip / tc_ratio_root + tc_fac = (1.0 + tc_ratio_fold / tc_ratio_root) / (1.0 + tc_ratio_tip / tc_ratio_root) + dtc_fac_wrt = dtc_ratio_fold_wrt / tc_ratio_root / (1.0 + tc_ratio_tip / tc_ratio_root) + dtc_fac_dwingspan = ( + dtc_ratio_fold_dwingspan / tc_ratio_root / (1.0 + tc_ratio_tip / tc_ratio_root) + ) + + du_tip = dtc_ratio_fold_dtc_ratio_tip / tc_ratio_root + dv_tip = 1.0 / tc_ratio_root + dtc_fac_dtc_ratio_tip = (du_tip * v - u * dv_tip) / v**2 + du_root = (dtc_ratio_fold_dtc_ratio_root * tc_ratio_root - tc_ratio_fold) / tc_ratio_root**2 + dv_root = -tc_ratio_tip / tc_ratio_root**2 + dtc_fac_dtc_ratio_root = (du_root * v - u * dv_root) / v**2 + + dgeometric_fuel_vol_dtc_ratio_root = ( + dtc_fac_dtc_ratio_root + * (fold_span - fuselage_width) + / (wingspan - fuselage_width) + * wing_volume_no_fold + ) + dgeometric_fuel_vol_dtc_ratio_tip = ( + dtc_fac_dtc_ratio_tip + * (fold_span - fuselage_width) + / (wingspan - fuselage_width) + * wing_volume_no_fold + ) + dgeometric_fuel_vol_dwingspan = ( + dtc_fac_dwingspan + * (fold_span - fuselage_width) + / (wingspan - fuselage_width) + * wing_volume_no_fold + - tc_fac + * (fold_span - fuselage_width) + / (wingspan - fuselage_width) ** 2 + * wing_volume_no_fold + ) + dgeometric_fuel_vol_wrt = ( + dtc_fac_wrt + * (fold_span - fuselage_width) + / (wingspan - fuselage_width) + * wing_volume_no_fold + + tc_fac * 2 * dlocation_wrt / (wingspan - fuselage_width) * wing_volume_no_fold + ) + dgeometric_fuel_vol_dwing_volume_no_fold = ( + tc_fac * (fold_span - fuselage_width) / (wingspan - fuselage_width) + ) + dgeometric_fuel_vol_dfuselage_width = ( + -tc_fac + * (wingspan - fold_span) + / (wingspan - fuselage_width) ** 2 + * wing_volume_no_fold + ) + + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 'wing_volume_no_fold'] = ( + dgeometric_fuel_vol_dwing_volume_no_fold + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuselage.AVG_DIAMETER] = ( + dgeometric_fuel_vol_dfuselage_width + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, wrt] = dgeometric_fuel_vol_wrt + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.SPAN] = ( + dgeometric_fuel_vol_dwingspan + ) + + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + dgeometric_fuel_vol_dtc_ratio_root + ) + J[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Wing.THICKNESS_TO_CHORD_TIP] = ( + dgeometric_fuel_vol_dtc_ratio_tip + ) + + +class WingGroup(om.Group): + """Group of WingSize, WingParameters, and WingFold for wing parameter computations.""" + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.CHOOSE_FOLD_LOCATION) + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) + + def setup(self): + has_fold = self.options[Aircraft.Wing.HAS_FOLD] + has_strut = self.options[Aircraft.Wing.HAS_STRUT] + + self.add_subsystem( + 'size', + WingSize(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + if has_fold or has_strut: + self.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + self.add_subsystem( + 'parameters', + WingParameters(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) + if not has_fold: + self.add_subsystem( + 'wing_vol', + WingVolume(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + if has_strut: + self.add_subsystem( + 'strut', + StrutGeom(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + if has_fold: + self.add_subsystem( + 'fold_area', + WingFoldArea(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'fold_vol', + WingFoldVolume(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + choose_fold_location = self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION] + if not choose_fold_location: + check_fold_location_definition(choose_fold_location, has_strut) + self.promotes('strut', outputs=['strut_y']) + self.promotes('fold_area', inputs=['strut_y']) + self.promotes('fold_vol', inputs=['strut_y']) + + +class BWBWingGroup(om.Group): + """ + Group of WingSize, WingParameters, WingFoldArea and BWBWingVolumeArea for wing parameter computations. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.CHOOSE_FOLD_LOCATION) + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) + add_aviary_option(self, Settings.VERBOSITY) + def setup(self): + verbosity = self.options[Settings.VERBOSITY] + has_fold = self.options[Aircraft.Wing.HAS_FOLD] + has_strut = self.options[Aircraft.Wing.HAS_STRUT] + + if has_strut: + if verbosity >= 1: + print('BWB does not have strut implemented.') + if not self.options[Aircraft.Wing.CHOOSE_FOLD_LOCATION]: + raise ('There is no strut. Aircraft.Wing.CHOOSE_FOLD_LOCATION must be True.') + + self.add_subsystem( + 'size', + WingSize(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + if has_fold: + self.add_subsystem( + 'dimensionless_calcs', + DimensionalNonDimensionalInterchange(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - aviary_options = self.options['aviary_options'] + self.add_subsystem( + 'parameters', + WingParameters(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - size = self.add_subsystem( - "size", - WingSize(aviary_options=aviary_options,), - promotes_inputs=["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], + self.add_subsystem( + 'wing_vol', + BWBWingVolume(), + promotes_inputs=['*'], ) + if has_fold: + self.promotes('wing_vol', outputs=['wing_volume_no_fold']) + else: + self.promotes('wing_vol', outputs=['*']) - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless') or self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): + if has_fold: self.add_subsystem( - "dimensionless_calcs", - DimensionalNonDimensionalInterchange(aviary_options=aviary_options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"] + 'fold_area', + WingFoldArea(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'fold_vol', + BWBWingFoldVolume(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'exposed_wing', + ExposedWing(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + +epsilon = 0.05 + + +def f(x): + """Valid for x in [0.0, 1.0].""" + diff = 0.5 - x + y = np.sqrt(0.25 - diff**2) + return y + + +def df(x): + """First derivative of f(x), valid for x in (0.0, 1.0).""" + diff = 0.5 - x + dy = (0.5 - x) / np.sqrt(0.25 - diff**2) + return dy + + +def d2f(x): + """Second derivative of f(x), valid for x in (0.0, 1.0).""" + diff = 0.5 - x + d2y = -0.25 / np.sqrt(0.25 - diff**2) ** 3 + return d2y + + +def g1(x): + """ + Returns a cubic function g1(x) such that: + g1(0.0) = 0.0 + g1(ε) = f(ε) + g1'(ε) = f'(ε) + g1"(ε) = f"(ε). + """ + A1 = f(epsilon) + B1 = df(epsilon) + C1 = d2f(epsilon) + d1 = (A1 - epsilon * B1 + 0.5 * epsilon**2 * C1) / epsilon**3 + c1 = (C1 - 6.0 * d1 * epsilon) / 2.0 + b1 = B1 - epsilon * C1 + 3 * d1 * epsilon**2 + a1 = 0.0 + y = a1 + b1 * x + c1 * x**2 + d1 * x**3 + return y + + +def dg1(x): + """First derivative of g1(x).""" + A1 = f(epsilon) + B1 = df(epsilon) + C1 = d2f(epsilon) + d1 = (A1 - epsilon * B1 + 0.5 * epsilon**2 * C1) / epsilon**3 + c1 = (C1 - 6.0 * d1 * epsilon) / 2.0 + b1 = B1 - epsilon * C1 + 3.0 * d1 * epsilon**2 + dy = b1 + 2.0 * c1 * x + 3.0 * d1 * x**2 + return dy + + +def g2(x): + """ + Returns a cubic function g2(x) such that: + g2(1.0) = 0.0 + g2(ε) = f(1.0-ε) + g2'(ε) = f'(1.0-ε) + g2"(ε) = f"(1.0-ε). + """ + delta = 1.0 - epsilon + A2 = f(delta) + B2 = df(delta) + C2 = d2f(delta) + d2 = -(A2 + B2 * epsilon + 0.5 * C2 * epsilon**2) / epsilon**3 + c2 = (C2 - 6.0 * d2 * delta) / 2.0 + b2 = B2 - C2 * delta + 3.0 * d2 * delta**2 + a2 = -(b2 + c2 + d2) + y = a2 + b2 * x + c2 * x**2 + d2 * x**3 + return y + + +def dg2(x): + """First derivative of g2(x).""" + delta = 1.0 - epsilon + A2 = f(delta) + B2 = df(delta) + C2 = d2f(delta) + d2 = -(A2 + B2 * epsilon + 0.5 * C2 * epsilon**2) / epsilon**3 + c2 = (C2 - 6 * d2 * delta) / 2.0 + b2 = B2 - C2 * delta + 3.0 * d2 * delta**2 + dy = b2 + 2.0 * c2 * x + 3.0 * d2 * x**2 + return dy + + +class ExposedWing(om.ExplicitComponent): + """ + Computation of exposed wing area. This is useful for BWB, + but is available to tube + wing model too. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Design.TYPE) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + add_aviary_input( + self, Aircraft.Wing.VERTICAL_MOUNT_LOCATION, units='unitless', desc='HWING' + ) + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft', desc='SWF') + add_aviary_input( + self, Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, units='unitless', desc='HGTqWID' + ) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft', desc='B') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless', desc='SLM') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2', desc='SW') + + add_aviary_output(self, Aircraft.Wing.EXPOSED_AREA, units='ft**2', desc='SW_EXP') + + def setup_partials(self): + design_type = self.options[Aircraft.Design.TYPE] + + self.declare_partials( + Aircraft.Wing.EXPOSED_AREA, + [ + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.AREA, + ], + ) + + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.declare_partials( + Aircraft.Wing.EXPOSED_AREA, + [ + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, + ], ) - parameters = self.add_subsystem( - "parameters", - WingParameters(aviary_options=aviary_options,), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], - ) - - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): - strut = self.add_subsystem( - "strut", - StrutGeom( - aviary_options=aviary_options, - ), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], + def compute(self, inputs, outputs): + design_type = self.options[Aircraft.Design.TYPE] + verbosity = self.options[Settings.VERBOSITY] + + h_wing = inputs[Aircraft.Wing.VERTICAL_MOUNT_LOCATION] + body_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + + if h_wing >= epsilon and h_wing <= 1.0 - epsilon: + sqt = np.sqrt(0.25 - (0.5 - h_wing) ** 2) + elif h_wing >= 0.0 and h_wing < epsilon: + sqt = g1(h_wing) + elif h_wing <= 1.0 and h_wing > 1.0 - epsilon: + sqt = g2(h_wing) + else: + raise 'The given parameter Aircraft.Wing.VERTICAL_MOUNT_LOCATION is out of range.' + + if design_type is AircraftTypes.BLENDED_WING_BODY: + cabin_height = body_width * inputs[Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] + b_fus = 0.5 * (body_width - cabin_height) + cabin_height * sqt + else: + b_fus = body_width * sqt + + wingspan = inputs[Aircraft.Wing.SPAN] + wing_area = inputs[Aircraft.Wing.AREA] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + if wingspan <= 0: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Wing.SPAN must be positive.') + if taper_ratio <= 0: + if verbosity > Verbosity.BRIEF: + print('Aircraft.Wing.TAPER_RATIO must be positive.') + + root_chord_wing = 2.0 * wing_area / (wingspan * (1.0 + taper_ratio)) + tip_chord = taper_ratio * root_chord_wing + c_fus = root_chord_wing + 2.0 * b_fus * (tip_chord - root_chord_wing) / wingspan + + exp_wing_area = (wingspan / 2.0 - b_fus) * (c_fus + tip_chord) + outputs[Aircraft.Wing.EXPOSED_AREA] = exp_wing_area + + def compute_partials(self, inputs, J): + design_type = self.options[Aircraft.Design.TYPE] + + h_wing = inputs[Aircraft.Wing.VERTICAL_MOUNT_LOCATION] + body_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + height_to_width = inputs[Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] + + if h_wing >= epsilon and h_wing <= 1.0 - epsilon: + sqt = np.sqrt(0.25 - (0.5 - h_wing) ** 2) + d_sqt = df(h_wing) + elif h_wing >= 0.0 and h_wing < epsilon: + sqt = g1(h_wing) + d_sqt = dg1(h_wing) + elif h_wing <= 1.0 and h_wing > 1.0 - epsilon: + sqt = g2(h_wing) + d_sqt = dg2(h_wing) + else: + raise 'The given parameter Aircraft.Wing.VERTICAL_MOUNT_LOCATION is out of range.' + + if design_type is AircraftTypes.BLENDED_WING_BODY: + cabin_height = body_width * height_to_width + b_fus = 0.5 * (body_width - cabin_height) + cabin_height * sqt + else: + b_fus = body_width * sqt + + wingspan = inputs[Aircraft.Wing.SPAN] + wing_area = inputs[Aircraft.Wing.AREA] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + + root_chord_wing = 2.0 * wing_area / (wingspan * (1.0 + taper_ratio)) + tip_chord = taper_ratio * root_chord_wing + c_fus = root_chord_wing + 2.0 * b_fus * (tip_chord - root_chord_wing) / wingspan + + if design_type is AircraftTypes.BLENDED_WING_BODY: + d_b_fus_d_hwing = body_width * height_to_width * d_sqt + d_b_fus_d_body_width = 0.5 * (1.0 - height_to_width) + height_to_width * sqt + d_b_fus_d_height_to_width = -0.5 * body_width + body_width * sqt + d_c_fus_d_height_to_width = ( + 4 + * d_b_fus_d_height_to_width + * (taper_ratio - 1.0) + / (taper_ratio + 1.0) + * wing_area + / wingspan**2 ) - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): - fold = self.add_subsystem( - "fold", - WingFold( - aviary_options=aviary_options, - ), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aircraft:*"], + d_exp_area_d_height_to_width = ( + -d_b_fus_d_height_to_width * c_fus + + (wingspan * 0.5 - b_fus) * d_c_fus_d_height_to_width + - d_b_fus_d_height_to_width + * 2.0 + * wing_area + * taper_ratio + / wingspan + / (1.0 + taper_ratio) + ) + J[Aircraft.Wing.EXPOSED_AREA, Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO] = ( + d_exp_area_d_height_to_width ) - if not self.options["aviary_options"].get_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, units='unitless'): - check_fold_location_definition(None, aviary_options) - self.promotes("strut", outputs=["strut_y"]) - self.promotes("fold", inputs=["strut_y"]) + else: + d_b_fus_d_hwing = body_width * d_sqt + d_b_fus_d_body_width = sqt + + d_c_fus_d_hwing = ( + 4.0 + * d_b_fus_d_hwing + * (taper_ratio - 1.0) + / (taper_ratio + 1.0) + * wing_area + / wingspan**2 + ) + d_c_fus_d_body_width = ( + 4.0 + * d_b_fus_d_body_width + * (taper_ratio - 1.0) + / (taper_ratio + 1.0) + * wing_area + / wingspan**2 + ) + d_c_fus_d_wing_area = ( + 2.0 + / (1.0 + taper_ratio) + * (1.0 / wingspan + b_fus * 2 * (taper_ratio - 1.0) / wingspan**2) + ) + d_c_fus_d_wingspan = ( + -2.0 + * wing_area + / (1.0 + taper_ratio) + * (1.0 / wingspan**2 + b_fus * 4.0 * (taper_ratio - 1.0) / wingspan**3) + ) + d_c_fus_d_taper_ratio = ( + -2.0 * wing_area / (1.0 + taper_ratio) ** 2 / wingspan + + b_fus * 8.0 * wing_area / wingspan**2 / (taper_ratio + 1) ** 2 + ) + + d_exp_area_d_hwing = ( + -d_b_fus_d_hwing * c_fus + + (wingspan * 0.5 - b_fus) * d_c_fus_d_hwing + - d_b_fus_d_hwing * 2.0 * wing_area * taper_ratio / wingspan / (1.0 + taper_ratio) + ) + J[Aircraft.Wing.EXPOSED_AREA, Aircraft.Wing.VERTICAL_MOUNT_LOCATION] = d_exp_area_d_hwing + + d_exp_area_d_body_width = ( + -d_b_fus_d_body_width * c_fus + + (wingspan * 0.5 - b_fus) * d_c_fus_d_body_width + - d_b_fus_d_body_width * 2.0 * wing_area * taper_ratio / wingspan / (1 + taper_ratio) + ) + J[Aircraft.Wing.EXPOSED_AREA, Aircraft.Fuselage.AVG_DIAMETER] = d_exp_area_d_body_width + + d_exp_area_d_wingspan = ( + 0.5 * c_fus + + (0.5 * wingspan - b_fus) * d_c_fus_d_wingspan + + b_fus * 2.0 * wing_area * taper_ratio / wingspan**2 / (1.0 + taper_ratio) + ) + J[Aircraft.Wing.EXPOSED_AREA, Aircraft.Wing.SPAN] = d_exp_area_d_wingspan - self.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless") - self.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless") - self.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units="unitless" + d_exp_area_d_taper_ratio = ( + (0.5 * wingspan - b_fus) * d_c_fus_d_taper_ratio + + wing_area / (1.0 + taper_ratio) ** 2 + - b_fus * 2.0 * wing_area / wingspan / (1.0 + taper_ratio) ** 2 ) - self.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, val=0.1, units="unitless" + J[Aircraft.Wing.EXPOSED_AREA, Aircraft.Wing.TAPER_RATIO] = d_exp_area_d_taper_ratio + + d_exp_area_d_wing_area = ( + (0.5 * wingspan - b_fus) * d_c_fus_d_wing_area + + taper_ratio / (1.0 + taper_ratio) + - b_fus * 2.0 * taper_ratio / wingspan / (1.0 + taper_ratio) ) + J[Aircraft.Wing.EXPOSED_AREA, Aircraft.Wing.AREA] = d_exp_area_d_wing_area diff --git a/aviary/subsystems/geometry/geometry_builder.py b/aviary/subsystems/geometry/geometry_builder.py index 93c2352bb1..5a3e6608a5 100644 --- a/aviary/subsystems/geometry/geometry_builder.py +++ b/aviary/subsystems/geometry/geometry_builder.py @@ -8,14 +8,13 @@ CoreGeometryBuilder : the interface for Aviary's core geometry subsystem builder """ -from aviary.interface.utils.markdown_utils import write_markdown_variable_table -from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase +from aviary.interface.utils import write_markdown_variable_table from aviary.subsystems.geometry.combined_geometry import CombinedGeometry from aviary.subsystems.geometry.flops_based.prep_geom import PrepGeom from aviary.subsystems.geometry.gasp_based.size_group import SizeGroup -from aviary.variable_info.variables import Aircraft +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.variable_info.enums import LegacyCode -from aviary.variable_info.variable_meta_data import _MetaData +from aviary.variable_info.variables import Aircraft GASP = LegacyCode.GASP FLOPS = LegacyCode.FLOPS @@ -25,7 +24,7 @@ class GeometryBuilderBase(SubsystemBuilderBase): """ - Base geometry builder + Base geometry builder. Methods ------- @@ -52,12 +51,12 @@ def mission_outputs(self, **kwargs): class CoreGeometryBuilder(GeometryBuilderBase): """ - Core geometry builder + Core geometry builder. - Method - ------ + Methods + ------- __init__(self, name=None, meta_data=None, code_origin=None, - use_both_geometries=False, code_origin_to_prioritize=None): + code_origin_to_prioritize=None): build_pre_mission(self, aviary_inputs) -> openmdao.core.System: Builds an OpenMDAO system for the pre-mission computations of the subsystem. build_mission(self, num_nodes, aviary_inputs, **kwargs) -> openmdao.core.System: @@ -68,60 +67,82 @@ class CoreGeometryBuilder(GeometryBuilderBase): Generate the report for Aviary core geometry analysis. """ - def __init__(self, name=None, meta_data=None, code_origin=None, - use_both_geometries=False, code_origin_to_prioritize=None): + def __init__( + self, + name=None, + meta_data=None, + code_origin=None, + code_origin_to_prioritize=None, + ): if name is None: name = 'core_geometry' - if code_origin not in (FLOPS, GASP) and not use_both_geometries: + if code_origin not in (FLOPS, GASP) and set(code_origin) != set((FLOPS, GASP)): raise ValueError('Code origin is not one of the following: (FLOPS, GASP)') self.code_origin = code_origin - self.use_both_geometries = use_both_geometries + self.use_both_geometries = code_origin == (FLOPS, GASP) self.code_origin_to_prioritize = code_origin_to_prioritize super().__init__(name=name, meta_data=meta_data) - def build_pre_mission(self, aviary_inputs): + def build_pre_mission(self, aviary_inputs, **kwargs): code_origin = self.code_origin both_geom = self.use_both_geometries code_origin_to_prioritize = self.code_origin_to_prioritize + try: + method = kwargs['method'] + except KeyError: + method = None geom_group = None - if both_geom: - geom_group = CombinedGeometry(aviary_options=aviary_inputs, - code_origin_to_prioritize=code_origin_to_prioritize) + if method != 'external': + if both_geom: + geom_group = CombinedGeometry(code_origin_to_prioritize=code_origin_to_prioritize) - elif code_origin is GASP: - geom_group = SizeGroup(aviary_options=aviary_inputs) - geom_group.manual_overrides = None + elif code_origin is GASP: + geom_group = SizeGroup() + geom_group.code_origin_overrides = None - elif code_origin is FLOPS: - geom_group = PrepGeom(aviary_options=aviary_inputs) - geom_group.manual_overrides = None + elif code_origin is FLOPS: + geom_group = PrepGeom() + geom_group.code_origin_overrides = None return geom_group def build_mission(self, num_nodes, aviary_inputs, **kwargs): - super().build_mission(num_nodes, aviary_inputs) + # by default there is no geom mission, but call super for safety/future-proofing + try: + method = kwargs['method'] + except KeyError: + method = None + geom_group = None + + if method != 'external': + geom_group = super().build_mission(num_nodes, aviary_inputs) + + return geom_group def get_parameters(self, aviary_inputs=None, phase_info=None): num_engine_type = len(aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES)) params = {} for entry in Aircraft.Nacelle.__dict__: - if entry != "__dict__": # cannot get attribute from mappingproxy + if entry != '__dict__': # cannot get attribute from mappingproxy var = getattr(Aircraft.Nacelle, entry) if var in aviary_inputs: if 'total' not in var: - params[var] = {'shape': (num_engine_type), 'static_target': True} + params[var] = { + 'shape': (num_engine_type), + 'static_target': True, + } return params def report(self, prob, reports_folder, **kwargs): """ - Generate the report for Aviary core geometry analysis + Generate the report for Aviary core geometry analysis. Parameters ---------- @@ -135,18 +156,18 @@ def report(self, prob, reports_folder, **kwargs): # TODO output differs by method # TODO finish variables of interest - wing_outputs = [Aircraft.Wing.AREA, - Aircraft.Wing.SPAN, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.SWEEP] - htail_outputs = [Aircraft.HorizontalTail.AREA, - Aircraft.VerticalTail.AREA] - fuselage_outputs = [Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.AVG_DIAMETER] + wing_outputs = [ + Aircraft.Wing.AREA, + Aircraft.Wing.SPAN, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.SWEEP, + ] + htail_outputs = [Aircraft.HorizontalTail.AREA, Aircraft.VerticalTail.AREA] + fuselage_outputs = [Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.AVG_DIAMETER] with open(filepath, mode='w') as f: if self.use_both_geometries: - method = ('FLOPS and GASP methods') + method = 'FLOPS and GASP methods' else: method = self.code_origin.value + ' method' f.write(f'# Geometry: {method}\n') diff --git a/aviary/subsystems/geometry/test/test_flops_geom_builder.py b/aviary/subsystems/geometry/test/test_flops_geom_builder.py index fb8e44cded..6c9de0b9e3 100644 --- a/aviary/subsystems/geometry/test/test_flops_geom_builder.py +++ b/aviary/subsystems/geometry/test/test_flops_geom_builder.py @@ -1,19 +1,18 @@ import unittest -import numpy as np -import openmdao.api as om - -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs +import aviary.api as av from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder from aviary.variable_info.enums import LegacyCode -from aviary.variable_info.variables import Aircraft from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -import aviary.api as av +from aviary.variable_info.variables import Aircraft FLOPS = LegacyCode.FLOPS +GASP = LegacyCode.GASP +@use_tempdirs class TestFLOPSGeomBuilder(av.TestSubsystemBuilderBase): """ That class inherits from TestSubsystemBuilder. So all the test functions are @@ -25,27 +24,28 @@ def setUp(self): self.subsystem_builder = CoreGeometryBuilder( 'core_geometry', BaseMetaData, - use_both_geometries=False, code_origin=FLOPS, - code_origin_to_prioritize=FLOPS) + code_origin_to_prioritize=FLOPS, + ) self.aviary_values = av.AviaryValues() self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') - self.aviary_values.set_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, False, units='unitless') + self.aviary_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, False, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_FOLD, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_STRUT, True, units='unitless') self.aviary_values.set_val( - Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless') + Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') + Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless' + ) + self.aviary_values.set_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') + self.aviary_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') self.aviary_values.set_val( - Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') + Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) class TestFLOPSGeomBuilderHybrid(av.TestSubsystemBuilderBase): @@ -59,29 +59,29 @@ def setUp(self): self.subsystem_builder = CoreGeometryBuilder( 'core_geometry', BaseMetaData, - use_both_geometries=False, - code_origin=FLOPS, - code_origin_to_prioritize=FLOPS) + code_origin=(FLOPS, GASP), + code_origin_to_prioritize=FLOPS, + ) self.aviary_values = av.AviaryValues() self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') - self.aviary_values.set_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, True, units='unitless') + self.aviary_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_FOLD, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_STRUT, True, units='unitless') self.aviary_values.set_val( - Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') + Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') + Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless' + ) + self.aviary_values.set_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') + self.aviary_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') self.aviary_values.set_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2, units='unitless') + Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) + self.aviary_values.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2, units='unitless') if __name__ == '__main__': diff --git a/aviary/subsystems/geometry/test/test_gasp_geom_builder.py b/aviary/subsystems/geometry/test/test_gasp_geom_builder.py index 9443845bd6..fa59cf5328 100644 --- a/aviary/subsystems/geometry/test/test_gasp_geom_builder.py +++ b/aviary/subsystems/geometry/test/test_gasp_geom_builder.py @@ -1,19 +1,18 @@ import unittest -import numpy as np -import openmdao.api as om - -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs +import aviary.api as av from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder from aviary.variable_info.enums import LegacyCode -from aviary.variable_info.variables import Aircraft from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -import aviary.api as av +from aviary.variable_info.variables import Aircraft GASP = LegacyCode.GASP +FLOPS = LegacyCode.FLOPS +@use_tempdirs class TestGASPGeomBuilder(av.TestSubsystemBuilderBase): """ That class inherits from TestSubsystemBuilder. So all the test functions are @@ -25,27 +24,28 @@ def setUp(self): self.subsystem_builder = CoreGeometryBuilder( 'core_geometry', BaseMetaData, - use_both_geometries=False, code_origin=GASP, - code_origin_to_prioritize=GASP) + code_origin_to_prioritize=GASP, + ) self.aviary_values = av.AviaryValues() self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') - self.aviary_values.set_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, False, units='unitless') + self.aviary_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, False, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_FOLD, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_STRUT, True, units='unitless') self.aviary_values.set_val( - Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless') + Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') + Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless' + ) + self.aviary_values.set_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') + self.aviary_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') self.aviary_values.set_val( - Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') + Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) class TestGASPGeomBuilderHybrid(av.TestSubsystemBuilderBase): @@ -59,29 +59,29 @@ def setUp(self): self.subsystem_builder = CoreGeometryBuilder( 'core_geometry', BaseMetaData, - use_both_geometries=False, - code_origin=GASP, - code_origin_to_prioritize=GASP) + code_origin=(GASP, FLOPS), + code_origin_to_prioritize=GASP, + ) self.aviary_values = av.AviaryValues() self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') - self.aviary_values.set_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, True, units='unitless') + self.aviary_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_FOLD, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_STRUT, True, units='unitless') self.aviary_values.set_val( - Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') - self.aviary_values.set_val( - Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') + Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') + Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, True, units='unitless' + ) + self.aviary_values.set_val(Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, True, units='unitless') + self.aviary_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, True, units='unitless') self.aviary_values.set_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless') + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) self.aviary_values.set_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2, units='unitless') + Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, True, units='unitless' + ) + self.aviary_values.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 2, units='unitless') if __name__ == '__main__': diff --git a/aviary/subsystems/mass/flops_based/air_conditioning.py b/aviary/subsystems/mass/flops_based/air_conditioning.py index 894ca14dd2..c394edbec0 100644 --- a/aviary/subsystems/mass/flops_based/air_conditioning.py +++ b/aviary/subsystems/mass/flops_based/air_conditioning.py @@ -1,117 +1,103 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.mass.flops_based.distributed_prop import ( - distributed_engine_count_factor, distributed_thrust_factor) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class TransportAirCondMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the air conditioning group using the transport/general aviation method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): - add_aviary_input(self, Aircraft.AirConditioning.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.AirConditioning.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Avionics.MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2') - add_aviary_input(self, Aircraft.Avionics.MASS, val=0.0) - - add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, val=0.0) - - add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, val=0.0) - - add_aviary_output(self, Aircraft.AirConditioning.MASS, val=0.0) + add_aviary_output(self, Aircraft.AirConditioning.MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] scaler = inputs[Aircraft.AirConditioning.MASS_SCALER] avionics_wt = inputs[Aircraft.Avionics.MASS] * GRAV_ENGLISH_LBM height = inputs[Aircraft.Fuselage.MAX_HEIGHT] planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] - outputs[Aircraft.AirConditioning.MASS] = \ - ((3.2 * (planform * height)**0.6 + 9 * pax**0.83) - * max_mach + 0.075 * avionics_wt) * scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.AirConditioning.MASS] = ( + ((3.2 * (planform * height) ** 0.6 + 9 * pax**0.83) * max_mach + 0.075 * avionics_wt) + * scaler + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] scaler = inputs[Aircraft.AirConditioning.MASS_SCALER] avionics_wt = inputs[Aircraft.Avionics.MASS] * GRAV_ENGLISH_LBM height = inputs[Aircraft.Fuselage.MAX_HEIGHT] planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] planform_exp = planform**0.6 height_exp = height**0.6 pax_exp = pax**0.83 J[Aircraft.AirConditioning.MASS, Aircraft.AirConditioning.MASS_SCALER] = ( - (3.2 * planform_exp * height_exp + 9 * pax_exp) * - max_mach + 0.075 * avionics_wt) / GRAV_ENGLISH_LBM + (3.2 * planform_exp * height_exp + 9 * pax_exp) * max_mach + 0.075 * avionics_wt + ) / GRAV_ENGLISH_LBM - J[Aircraft.AirConditioning.MASS, Aircraft.Avionics.MASS] = \ - 0.075 * scaler + J[Aircraft.AirConditioning.MASS, Aircraft.Avionics.MASS] = 0.075 * scaler - J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.MAX_HEIGHT] = \ + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.MAX_HEIGHT] = ( 1.92 * planform_exp * height**-0.4 * max_mach * scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.PLANFORM_AREA] = \ + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.PLANFORM_AREA] = ( 1.92 * planform**-0.4 * height_exp * max_mach * scaler / GRAV_ENGLISH_LBM + ) class AltAirCondMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the air conditioning group using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) def setup(self): - add_aviary_input(self, Aircraft.AirConditioning.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.AirConditioning.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.AirConditioning.MASS, val=0.0) + add_aviary_output(self, Aircraft.AirConditioning.MASS, units='lbm') def setup_partials(self): self.declare_partials(of=Aircraft.AirConditioning.MASS, wrt='*') def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - num_pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + num_pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] scaler = inputs[Aircraft.AirConditioning.MASS_SCALER] - outputs[Aircraft.AirConditioning.MASS] = \ - 26.0 * num_pax * scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.AirConditioning.MASS] = 26.0 * num_pax * scaler / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + num_pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] - J[Aircraft.AirConditioning.MASS, Aircraft.AirConditioning.MASS_SCALER] = \ + J[Aircraft.AirConditioning.MASS, Aircraft.AirConditioning.MASS_SCALER] = ( 26.0 * num_pax / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/anti_icing.py b/aviary/subsystems/mass/flops_based/anti_icing.py index 779fc3ca0e..eedacad1a9 100644 --- a/aviary/subsystems/mass/flops_based/anti_icing.py +++ b/aviary/subsystems/mass/flops_based/anti_icing.py @@ -5,47 +5,43 @@ from aviary.subsystems.mass.flops_based.distributed_prop import ( distributed_engine_count_factor, distributed_nacelle_diam_factor, - distributed_nacelle_diam_factor_deriv) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output + distributed_nacelle_diam_factor_deriv, +) +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class AntiIcingMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the anti-icing system. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) + add_aviary_option(self, Aircraft.Engine.REFERENCE_SLS_THRUST, units='lbf') def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Aircraft.AntiIcing.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.AntiIcing.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input( + self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type, units='lbf' + ) - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, val=0.0) - - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, - val=np.zeros(num_engine_type)) - - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) - - add_aviary_input(self, Aircraft.Wing.SWEEP, val=0.0) - - add_aviary_output(self, Aircraft.AntiIcing.MASS, val=0.0) + add_aviary_output(self, Aircraft.AntiIcing.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - total_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + total_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] scaler = inputs[Aircraft.AntiIcing.MASS_SCALER] max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] @@ -53,44 +49,72 @@ def compute(self, inputs, outputs): span = inputs[Aircraft.Wing.SPAN] sweep = inputs[Aircraft.Wing.SWEEP] + thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] + ref_sls_thrust, _ = self.options[Aircraft.Engine.REFERENCE_SLS_THRUST] + thrust_rat = thrust / ref_sls_thrust + adjusted_avg_diam = avg_diam * np.sqrt(thrust_rat) + count_factor = distributed_engine_count_factor(total_engines) - f_nacelle = distributed_nacelle_diam_factor(avg_diam, num_engines) + f_nacelle = distributed_nacelle_diam_factor(adjusted_avg_diam, num_engines) outputs[Aircraft.AntiIcing.MASS] = ( - (span / np.cos(sweep * np.pi / 180)) - + 3.8 * f_nacelle * count_factor + 1.5 * max_width) * scaler / GRAV_ENGLISH_LBM + ( + (span / np.cos(sweep * np.pi / 180)) + + 3.8 * f_nacelle * count_factor + + 1.5 * max_width + ) + * scaler + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - total_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + total_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] scaler = inputs[Aircraft.AntiIcing.MASS_SCALER] max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] avg_diam = inputs[Aircraft.Nacelle.AVG_DIAMETER] - count_factor = distributed_engine_count_factor(total_engines) - f_nacelle = distributed_nacelle_diam_factor(avg_diam, num_engines) span = inputs[Aircraft.Wing.SPAN] sweep = inputs[Aircraft.Wing.SWEEP] + # scale avg_diam by thrust ratio + thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] + ref_sls_thrust, _ = self.options[Aircraft.Engine.REFERENCE_SLS_THRUST] + thrust_rat = thrust / ref_sls_thrust + adjusted_avg_diam = avg_diam * np.sqrt(thrust_rat) + + count_factor = distributed_engine_count_factor(total_engines) + f_nacelle = distributed_nacelle_diam_factor(adjusted_avg_diam, num_engines) + diam_deriv_fact = distributed_nacelle_diam_factor_deriv(num_engines) cos_sweep = np.cos(sweep * np.pi / 180) sin_sweep = np.sin(sweep * np.pi / 180) J[Aircraft.AntiIcing.MASS, Aircraft.AntiIcing.MASS_SCALER] = ( - span / cos_sweep + 3.8 * f_nacelle * count_factor + - 1.5 * max_width) / GRAV_ENGLISH_LBM - - J[Aircraft.AntiIcing.MASS, Aircraft.Fuselage.MAX_WIDTH] = \ - 1.5 * scaler / GRAV_ENGLISH_LBM - - J[Aircraft.AntiIcing.MASS, Aircraft.Nacelle.AVG_DIAMETER] = \ - 3.8 * diam_deriv_fact * count_factor * scaler / GRAV_ENGLISH_LBM - - J[Aircraft.AntiIcing.MASS, Aircraft.Wing.SPAN] = \ - 1 / cos_sweep * scaler / GRAV_ENGLISH_LBM - - J[Aircraft.AntiIcing.MASS, Aircraft.Wing.SWEEP] = \ - span * (np.pi / 180) * sin_sweep / (cos_sweep) ** 2 * \ - scaler / GRAV_ENGLISH_LBM + span / cos_sweep + 3.8 * f_nacelle * count_factor + 1.5 * max_width + ) / GRAV_ENGLISH_LBM + + J[Aircraft.AntiIcing.MASS, Aircraft.Fuselage.MAX_WIDTH] = 1.5 * scaler / GRAV_ENGLISH_LBM + + J[Aircraft.AntiIcing.MASS, Aircraft.Nacelle.AVG_DIAMETER] = ( + 3.8 * diam_deriv_fact * np.sqrt(thrust_rat) * count_factor * scaler / GRAV_ENGLISH_LBM + ) + + J[Aircraft.AntiIcing.MASS, Aircraft.Wing.SPAN] = 1 / cos_sweep * scaler / GRAV_ENGLISH_LBM + + J[Aircraft.AntiIcing.MASS, Aircraft.Wing.SWEEP] = ( + span * (np.pi / 180) * sin_sweep / (cos_sweep) ** 2 * scaler / GRAV_ENGLISH_LBM + ) + + J[Aircraft.AntiIcing.MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + 3.8 + * diam_deriv_fact + * avg_diam + * 0.5 + * np.sqrt(ref_sls_thrust / thrust) + / ref_sls_thrust + * count_factor + * scaler + / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/apu.py b/aviary/subsystems/mass/flops_based/apu.py index 3a8fec0518..cff979c9fc 100644 --- a/aviary/subsystems/mass/flops_based/apu.py +++ b/aviary/subsystems/mass/flops_based/apu.py @@ -1,8 +1,7 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft @@ -13,38 +12,34 @@ class TransportAPUMass(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) def setup(self): - add_aviary_input(self, Aircraft.APU.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.APU.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2') - add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, val=0.0) - - add_aviary_output(self, Aircraft.APU.MASS, val=0.0) + add_aviary_output(self, Aircraft.APU.MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] scaler = inputs[Aircraft.APU.MASS_SCALER] planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] outputs[Aircraft.APU.MASS] = ( - 54.0 * planform ** 0.3 + 5.4 * pax ** 0.9) * scaler / GRAV_ENGLISH_LBM + (54.0 * planform**0.3 + 5.4 * pax**0.9) * scaler / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] scaler = inputs[Aircraft.APU.MASS_SCALER] planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] J[Aircraft.APU.MASS, Aircraft.APU.MASS_SCALER] = ( - 54.0 * planform ** 0.3 + 5.4 * pax ** 0.9) / GRAV_ENGLISH_LBM - J[Aircraft.APU.MASS, Aircraft.Fuselage.PLANFORM_AREA] = \ - 16.2 * planform ** -0.7 * scaler / GRAV_ENGLISH_LBM + 54.0 * planform**0.3 + 5.4 * pax**0.9 + ) / GRAV_ENGLISH_LBM + J[Aircraft.APU.MASS, Aircraft.Fuselage.PLANFORM_AREA] = ( + 16.2 * planform**-0.7 * scaler / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/avionics.py b/aviary/subsystems/mass/flops_based/avionics.py index 0c6e545228..fe2ad529b2 100644 --- a/aviary/subsystems/mass/flops_based/avionics.py +++ b/aviary/subsystems/mass/flops_based/avionics.py @@ -1,48 +1,42 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class TransportAvionicsMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the avionics group using the transport/general aviation method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.NUM_FLIGHT_CREW) def setup(self): - add_aviary_input(self, Aircraft.Avionics.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Avionics.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2') + add_aviary_input(self, Mission.Design.RANGE, units='NM') - add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, val=0.0) - - add_aviary_input(self, Mission.Design.RANGE, val=0.0) - - add_aviary_output(self, Aircraft.Avionics.MASS, val=0.0) + add_aviary_output(self, Aircraft.Avionics.MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - crew = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) + crew = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] scaler = inputs[Aircraft.Avionics.MASS_SCALER] planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] des_range = inputs[Mission.Design.RANGE] - outputs[Aircraft.Avionics.MASS] = \ + outputs[Aircraft.Avionics.MASS] = ( 15.8 * des_range**0.1 * crew**0.7 * planform**0.43 * scaler / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - crew = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) + crew = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] scaler = inputs[Aircraft.Avionics.MASS_SCALER] planform = inputs[Aircraft.Fuselage.PLANFORM_AREA] des_range = inputs[Mission.Design.RANGE] @@ -51,11 +45,14 @@ def compute_partials(self, inputs, J): crew_exp = crew**0.7 planform_exp = planform**0.43 - J[Aircraft.Avionics.MASS, Aircraft.Avionics.MASS_SCALER] = 15.8 * \ - des_range_exp * crew_exp * planform_exp / GRAV_ENGLISH_LBM + J[Aircraft.Avionics.MASS, Aircraft.Avionics.MASS_SCALER] = ( + 15.8 * des_range_exp * crew_exp * planform_exp / GRAV_ENGLISH_LBM + ) - J[Aircraft.Avionics.MASS, Aircraft.Fuselage.PLANFORM_AREA] = 6.794 * \ - des_range_exp * crew_exp * planform**-0.57 * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Avionics.MASS, Aircraft.Fuselage.PLANFORM_AREA] = ( + 6.794 * des_range_exp * crew_exp * planform**-0.57 * scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Avionics.MASS, Mission.Design.RANGE] = 1.58 * \ - des_range**-0.9 * crew_exp * planform_exp * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Avionics.MASS, Mission.Design.RANGE] = ( + 1.58 * des_range**-0.9 * crew_exp * planform_exp * scaler / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/canard.py b/aviary/subsystems/mass/flops_based/canard.py index 9223872f19..2c1533df5e 100644 --- a/aviary/subsystems/mass/flops_based/canard.py +++ b/aviary/subsystems/mass/flops_based/canard.py @@ -1,41 +1,36 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class CanardMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the canard. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Canard.AREA, val=0.0) - add_aviary_input(self, Aircraft.Canard.TAPER_RATIO, val=00) - add_aviary_input(self, Aircraft.Canard.MASS_SCALER, val=1.0) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Canard.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Canard.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Canard.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Canard.MASS, val=0.0) + add_aviary_output(self, Aircraft.Canard.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): togw = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM area = inputs[Aircraft.Canard.AREA] taper_ratio = inputs[Aircraft.Canard.TAPER_RATIO] - canard_weight = 0.53 * area * togw**0.2 * (taper_ratio+0.5) - outputs[Aircraft.Canard.MASS] = canard_weight * \ - inputs[Aircraft.Canard.MASS_SCALER] / GRAV_ENGLISH_LBM + canard_weight = 0.53 * area * togw**0.2 * (taper_ratio + 0.5) + outputs[Aircraft.Canard.MASS] = ( + canard_weight * inputs[Aircraft.Canard.MASS_SCALER] / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): area = inputs[Aircraft.Canard.AREA] @@ -45,14 +40,18 @@ def compute_partials(self, inputs, J): gross_weight_exp = gross_weight**0.2 - J[Aircraft.Canard.MASS, Aircraft.Canard.AREA] = 0.53 * \ - scaler * (taper_ratio+0.5) * gross_weight_exp / GRAV_ENGLISH_LBM + J[Aircraft.Canard.MASS, Aircraft.Canard.AREA] = ( + 0.53 * scaler * (taper_ratio + 0.5) * gross_weight_exp / GRAV_ENGLISH_LBM + ) - J[Aircraft.Canard.MASS, Aircraft.Canard.TAPER_RATIO] = \ - 0.53*area * scaler * gross_weight_exp / GRAV_ENGLISH_LBM + J[Aircraft.Canard.MASS, Aircraft.Canard.TAPER_RATIO] = ( + 0.53 * area * scaler * gross_weight_exp / GRAV_ENGLISH_LBM + ) - J[Aircraft.Canard.MASS, Aircraft.Canard.MASS_SCALER] = \ - 0.53*area * (taper_ratio+0.5) * gross_weight_exp / GRAV_ENGLISH_LBM + J[Aircraft.Canard.MASS, Aircraft.Canard.MASS_SCALER] = ( + 0.53 * area * (taper_ratio + 0.5) * gross_weight_exp / GRAV_ENGLISH_LBM + ) - J[Aircraft.Canard.MASS, Mission.Design.GROSS_MASS] = \ - (0.106*area * scaler * (taper_ratio+0.5)) / gross_weight**0.8 + J[Aircraft.Canard.MASS, Mission.Design.GROSS_MASS] = ( + 0.106 * area * scaler * (taper_ratio + 0.5) + ) / gross_weight**0.8 diff --git a/aviary/subsystems/mass/flops_based/cargo.py b/aviary/subsystems/mass/flops_based/cargo.py index 8ac83f493a..558e7b1d20 100644 --- a/aviary/subsystems/mass/flops_based/cargo.py +++ b/aviary/subsystems/mass/flops_based/cargo.py @@ -1,83 +1,86 @@ -''' +""" Define utilities to calculate the estimated mass of any passengers, their baggage, and other cargo. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. -''' -import openmdao.api as om +""" -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission +import openmdao.api as om +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft -class CargoMass(om.ExplicitComponent): - ''' - Calculate the estimated mass of any passengers, their baggage, and other - cargo. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') +class PayloadGroup(om.Group): def setup(self): - add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_MASS, 0.) - add_aviary_output(self, Aircraft.CrewPayload.BAGGAGE_MASS, 0.) - add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 0.) + self.add_subsystem('cargo_mass', CargoMass(), promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'total_payload_mass', TotalPayload(), promotes_inputs=['*'], promotes_outputs=['*'] + ) - add_aviary_input(self, Aircraft.CrewPayload.WING_CARGO, 0.) - add_aviary_input(self, Aircraft.CrewPayload.MISC_CARGO, 0.) - add_aviary_output(self, Aircraft.CrewPayload.CARGO_MASS, 0.) - add_aviary_output(self, Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 0.) +class TotalPayload(om.ExplicitComponent): + """Calculate the total payload mass.""" - def setup_partials(self): + def setup(self): + add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, units='lbm') + add_aviary_output(self, Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, units='lbm') + def setup_partials(self): self.declare_partials( - Aircraft.CrewPayload.CARGO_MASS, Aircraft.CrewPayload.WING_CARGO, val=1. + Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, + [Aircraft.CrewPayload.CARGO_MASS, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], + val=1.0, ) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + cargo_mass = inputs[Aircraft.CrewPayload.CARGO_MASS] + passenger_payload_mass = inputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] + + outputs[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS] = passenger_payload_mass + cargo_mass + + +class CargoMass(om.ExplicitComponent): + """Calculate the mass of any passengers, their baggage, and other cargo.""" + + def initialize(self): + add_aviary_option(self, Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, units='lbm') + add_aviary_option(self, Aircraft.CrewPayload.MASS_PER_PASSENGER, units='lbm') + add_aviary_option(self, Aircraft.CrewPayload.NUM_PASSENGERS) + + def setup(self): + add_aviary_input(self, Aircraft.CrewPayload.WING_CARGO, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.MISC_CARGO, units='lbm') + add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_MASS, units='lbm') + add_aviary_output(self, Aircraft.CrewPayload.BAGGAGE_MASS, units='lbm') + add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, units='lbm') + add_aviary_output(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm') + + def setup_partials(self): self.declare_partials( - Aircraft.CrewPayload.CARGO_MASS, Aircraft.CrewPayload.MISC_CARGO, val=1. + Aircraft.CrewPayload.CARGO_MASS, Aircraft.CrewPayload.WING_CARGO, val=1.0 ) self.declare_partials( - Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, - [ - Aircraft.CrewPayload.WING_CARGO, - Aircraft.CrewPayload.MISC_CARGO - ], - val=1.0 + Aircraft.CrewPayload.CARGO_MASS, Aircraft.CrewPayload.MISC_CARGO, val=1.0 ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - passenger_count = aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) - - mass_per_passenger = aviary_options.get_val( - Aircraft.CrewPayload.MASS_PER_PASSENGER, units='lbm') + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + passenger_count = self.options[Aircraft.CrewPayload.NUM_PASSENGERS] + mass_per_passenger, _ = self.options[Aircraft.CrewPayload.MASS_PER_PASSENGER] + baggage_mass_per_passenger, _ = self.options[ + Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER + ] - baggage_mass_per_passenger = aviary_options.get_val( - Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 'lbm') + outputs[Aircraft.CrewPayload.PASSENGER_MASS] = mass_per_passenger * passenger_count - outputs[Aircraft.CrewPayload.PASSENGER_MASS] = \ - mass_per_passenger * passenger_count + outputs[Aircraft.CrewPayload.BAGGAGE_MASS] = baggage_mass_per_passenger * passenger_count - outputs[Aircraft.CrewPayload.BAGGAGE_MASS] = \ - baggage_mass_per_passenger * passenger_count - - outputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] = outputs[Aircraft.CrewPayload.PASSENGER_MASS] + \ - outputs[Aircraft.CrewPayload.BAGGAGE_MASS] + outputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] = ( + mass_per_passenger * passenger_count + baggage_mass_per_passenger * passenger_count + ) wing_cargo = inputs[Aircraft.CrewPayload.WING_CARGO] misc_cargo = inputs[Aircraft.CrewPayload.MISC_CARGO] outputs[Aircraft.CrewPayload.CARGO_MASS] = wing_cargo + misc_cargo - - outputs[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS] = ( - outputs[Aircraft.CrewPayload.PASSENGER_MASS] - + outputs[Aircraft.CrewPayload.BAGGAGE_MASS] - + outputs[Aircraft.CrewPayload.CARGO_MASS]) diff --git a/aviary/subsystems/mass/flops_based/cargo_containers.py b/aviary/subsystems/mass/flops_based/cargo_containers.py index df09674393..349d3448ea 100644 --- a/aviary/subsystems/mass/flops_based/cargo_containers.py +++ b/aviary/subsystems/mass/flops_based/cargo_containers.py @@ -2,39 +2,29 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues +from aviary.utils.functions import sin_int4, dydx_sin_int4 from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft class TransportCargoContainersMass(om.ExplicitComponent): - ''' + """ Calculate the estimated mass for cargo containers. Use for both traditional and blended-wing-body type transports. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input( - self, Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, val=1.0) - - add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, val=0.0) - - add_aviary_input(self, Aircraft.CrewPayload.BAGGAGE_MASS, val=0.0) + add_aviary_input(self, Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.BAGGAGE_MASS, units='lbm') - add_aviary_output(self, Aircraft.CrewPayload.CARGO_CONTAINER_MASS, val=0.0) + add_aviary_output(self, Aircraft.CrewPayload.CARGO_CONTAINER_MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): scaler = inputs[Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER] cargo = inputs[Aircraft.CrewPayload.CARGO_MASS] baggage = inputs[Aircraft.CrewPayload.BAGGAGE_MASS] @@ -43,8 +33,9 @@ def compute( container_count = sin_int4(temp) cargo_container_weight = container_count * 175.0 * scaler - outputs[Aircraft.CrewPayload.CARGO_CONTAINER_MASS] = \ + outputs[Aircraft.CrewPayload.CARGO_CONTAINER_MASS] = ( cargo_container_weight / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J, discrete_inputs=None): scaler = inputs[Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER] @@ -58,63 +49,13 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J[ Aircraft.CrewPayload.CARGO_CONTAINER_MASS, - Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER + Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, ] = container_count * 175.0 / GRAV_ENGLISH_LBM - J[ - Aircraft.CrewPayload.CARGO_CONTAINER_MASS, - Aircraft.CrewPayload.CARGO_MASS - ] = partial * scaler / GRAV_ENGLISH_LBM - - J[ - Aircraft.CrewPayload.CARGO_CONTAINER_MASS, - Aircraft.CrewPayload.BAGGAGE_MASS - ] = partial * scaler / GRAV_ENGLISH_LBM - - -# region TODO: move this to an appropriate module for import -def sin_int4(val): - ''' - Define a smooth, differentialbe approximation to the 'int' function. - ''' - return sin_int(sin_int(sin_int(sin_int(val)))) - 0.5 - - -def dydx_sin_int4(val): - ''' - Define the derivative (dy/dx) of sin_int4, at x = val. - ''' - y0 = sin_int(val) - y1 = sin_int(y0) - y2 = sin_int(y1) - - dydx3 = dydx_sin_int(y2) - dydx2 = dydx_sin_int(y1) - dydx1 = dydx_sin_int(y0) - dydx0 = dydx_sin_int(val) - - dydx = dydx3 * dydx2 * dydx1 * dydx0 - - return dydx - - -# 'int' function can be approximated by recursively applying this sin function -# which makes a smooth, differentialbe function -def sin_int(val): - ''' - Define one step in approximating the 'int' function with a smooth, - differentialbe function. - ''' - int_val = val - np.sin(2*np.pi*(val+0.5))/(2*np.pi) - - return int_val - - -def dydx_sin_int(val): - ''' - Define the derivative (dy/dx) of sin_int, at x = val. - ''' - dydx = 1.0 - np.cos(2 * np.pi * (val + 0.5)) + J[Aircraft.CrewPayload.CARGO_CONTAINER_MASS, Aircraft.CrewPayload.CARGO_MASS] = ( + partial * scaler / GRAV_ENGLISH_LBM + ) - return dydx -# endregion TODO: move this to an appropriate module for import + J[Aircraft.CrewPayload.CARGO_CONTAINER_MASS, Aircraft.CrewPayload.BAGGAGE_MASS] = ( + partial * scaler / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/crew.py b/aviary/subsystems/mass/flops_based/crew.py index 60030710b8..854b376d2e 100644 --- a/aviary/subsystems/mass/flops_based/crew.py +++ b/aviary/subsystems/mass/flops_based/crew.py @@ -1,50 +1,40 @@ -''' +""" Define utilities to calculate the estimated mass of the crew (both flight and non-flight) as well as their baggage. -''' +""" + import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class NonFlightCrewMass(om.ExplicitComponent): - ''' - Calculate the estimated mass for the non-flight and their baggage. - ''' + """Calculate the estimated mass for the non-flight and their baggage.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS) + add_aviary_option(self, Aircraft.CrewPayload.NUM_GALLEY_CREW) def setup(self): - add_aviary_input( - self, Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, 1.) + add_aviary_input(self, Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, 0) + add_aviary_output(self, Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, units='lbm') def setup_partials(self): self.declare_partials( Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, - Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER + Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - flight_attendants_count = \ - aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS) - galley_crew_count = \ - aviary_options.get_val(Aircraft.CrewPayload.NUM_GALLEY_CREW) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + flight_attendants_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS] + galley_crew_count = self.options[Aircraft.CrewPayload.NUM_GALLEY_CREW] mass_per_flight_attendant = self._mass_per_flight_attendant mass_per_galley_crew = self._mass_per_galley_crew - mass_scaler = \ - inputs[Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER] + mass_scaler = inputs[Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER] outputs[Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS] = ( flight_attendants_count * mass_per_flight_attendant @@ -52,85 +42,66 @@ def compute( ) * mass_scaler def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - flight_attendants_count = \ - aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS) - galley_crew_count = \ - aviary_options.get_val(Aircraft.CrewPayload.NUM_GALLEY_CREW) + flight_attendants_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS] + galley_crew_count = self.options[Aircraft.CrewPayload.NUM_GALLEY_CREW] mass_per_flight_attendant = self._mass_per_flight_attendant mass_per_galley_crew = self._mass_per_galley_crew J[ Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, - Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER + Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, ] = ( flight_attendants_count * mass_per_flight_attendant + galley_crew_count * mass_per_galley_crew ) - _mass_per_flight_attendant = 155. # lbm - _mass_per_galley_crew = 200. # lbm + _mass_per_flight_attendant = 155.0 # lbm + _mass_per_galley_crew = 200.0 # lbm class FlightCrewMass(om.ExplicitComponent): - ''' - Calculate the estimated mass for the flight crew and their baggage. - ''' + """Calculate the estimated mass for the flight crew and their baggage.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.NUM_FLIGHT_CREW) def setup(self): - add_aviary_input( - self, Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, 1.) + add_aviary_input(self, Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.CrewPayload.FLIGHT_CREW_MASS, 0.) + add_aviary_output(self, Aircraft.CrewPayload.FLIGHT_CREW_MASS, units='lbm') def setup_partials(self): self.declare_partials( - Aircraft.CrewPayload.FLIGHT_CREW_MASS, - Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER + Aircraft.CrewPayload.FLIGHT_CREW_MASS, Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - flight_crew_count = \ - aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + flight_crew_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] mass_per_flight_crew = self._mass_per_flight_crew(inputs) mass_scaler = inputs[Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER] - outputs[Aircraft.CrewPayload.FLIGHT_CREW_MASS] = \ + outputs[Aircraft.CrewPayload.FLIGHT_CREW_MASS] = ( flight_crew_count * mass_per_flight_crew * mass_scaler + ) def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - flight_crew_count = \ - aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) + flight_crew_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] mass_per_flight_crew = self._mass_per_flight_crew(inputs) - J[ - Aircraft.CrewPayload.FLIGHT_CREW_MASS, - Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER - ] = flight_crew_count * mass_per_flight_crew + J[Aircraft.CrewPayload.FLIGHT_CREW_MASS, Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER] = ( + flight_crew_count * mass_per_flight_crew + ) def _mass_per_flight_crew(self, inputs): - ''' + """ Return the mass, in pounds, of one member of the flight crew and their baggage. - ''' - aviary_options: AviaryValues = self.options['aviary_options'] + """ + # TODO this should be its own variable mass_per_flight_crew = 225.0 # lbm - # account for machine precision error - if 0.9 <= aviary_options.get_val(Aircraft.LandingGear.CARRIER_BASED): - mass_per_flight_crew -= 35.0 # lbm - return mass_per_flight_crew diff --git a/aviary/subsystems/mass/flops_based/distributed_prop.py b/aviary/subsystems/mass/flops_based/distributed_prop.py index e2d212b1e1..8edab19312 100644 --- a/aviary/subsystems/mass/flops_based/distributed_prop.py +++ b/aviary/subsystems/mass/flops_based/distributed_prop.py @@ -12,7 +12,6 @@ def distributed_engine_count_factor(total_num_eng: int) -> float: total_num_eng : int Total number of engines """ - factor = float(total_num_eng) if total_num_eng > 4: @@ -32,7 +31,6 @@ def distributed_thrust_factor(max_sls_thrust: float, total_num_eng: int) -> floa total_num_eng : iterable or int Total number of engines """ - num_engine_factor = distributed_engine_count_factor(total_num_eng) return max_sls_thrust / num_engine_factor @@ -50,7 +48,6 @@ def distributed_nacelle_diam_factor(diam_nacelle: list, num_eng: list) -> float: num_eng : iterable or int Number of engines for each engine model """ - # If there is more than one engine model, use the global average diameter try: total_num_eng = sum(num_eng) @@ -61,14 +58,14 @@ def distributed_nacelle_diam_factor(diam_nacelle: list, num_eng: list) -> float: diam_factor = diam_avg if total_num_eng > 4: - diam_factor = 0.5 * diam_avg * total_num_eng ** 0.5 + diam_factor = 0.5 * diam_avg * total_num_eng**0.5 return diam_factor def distributed_nacelle_diam_factor_deriv(num_eng: int) -> float: """ - Returns the derivative of the distributed propulsion nacelle average diameter factor + Returns the derivative of the distributed propulsion nacelle average diameter factor w.r.t. the global nacelle average diameter. Parameters @@ -76,7 +73,6 @@ def distributed_nacelle_diam_factor_deriv(num_eng: int) -> float: num_eng : iterable or int Number of engines for each engine model """ - try: total_num_engines = sum(num_eng) except TypeError: @@ -84,7 +80,7 @@ def distributed_nacelle_diam_factor_deriv(num_eng: int) -> float: deriv = 1.0 if total_num_engines > 4: - deriv = num_eng * (0.5 * total_num_engines ** 0.5)/total_num_engines + deriv = num_eng * (0.5 * total_num_engines**0.5) / total_num_engines return deriv @@ -96,7 +92,7 @@ def nacelle_count_factor(num_eng): engine if the number of engines is odd (for each unique engine type). If there are multiple engine types, each engine type gets its own nacelle count - factor. This methodology does not account for potential conflict of engines present + factor. This methodology does not account for potential conflict of engines present on the aircraft centerline. Parameters diff --git a/aviary/subsystems/mass/flops_based/electrical.py b/aviary/subsystems/mass/flops_based/electrical.py index 1430945f7e..d3dcc9641d 100644 --- a/aviary/subsystems/mass/flops_based/electrical.py +++ b/aviary/subsystems/mass/flops_based/electrical.py @@ -1,10 +1,8 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.mass.flops_based.distributed_prop import \ - distributed_engine_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.subsystems.mass.flops_based.distributed_prop import distributed_engine_count_factor +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft @@ -15,45 +13,51 @@ class ElectricalMass(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.NUM_FLIGHT_CREW) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) def setup(self): - add_aviary_input(self, Aircraft.Fuselage.LENGTH, 0.0) - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, 0.0) - add_aviary_input(self, Aircraft.Electrical.MASS_SCALER, 1.0) + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Electrical.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Electrical.MASS, 1.0) + add_aviary_output(self, Aircraft.Electrical.MASS, units='lbm') def setup_partials(self): self.declare_partials(of='*', wrt='*') def compute(self, inputs, outputs): - options: AviaryValues = self.options['aviary_options'] - nfuse = options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) - ncrew = options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - npass = options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + nfuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + ncrew = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + npass = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + length = inputs[Aircraft.Fuselage.LENGTH] width = inputs[Aircraft.Fuselage.MAX_WIDTH] - num_eng = options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_engines_factor = distributed_engine_count_factor(num_eng) mass_scaler = inputs[Aircraft.Electrical.MASS_SCALER] outputs[Aircraft.Electrical.MASS] = ( - 92.0 * length**0.4 * width**0.14 * nfuse**0.27 * num_engines_factor**0.69 - * (1.0 + 0.044 * ncrew + 0.0015 * npass) * mass_scaler / GRAV_ENGLISH_LBM) + 92.0 + * length**0.4 + * width**0.14 + * nfuse**0.27 + * num_engines_factor**0.69 + * (1.0 + 0.044 * ncrew + 0.0015 * npass) + * mass_scaler + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - options: AviaryValues = self.options['aviary_options'] - nfuse = options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) - ncrew = options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - npass = options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + nfuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + ncrew = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + npass = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + length = inputs[Aircraft.Fuselage.LENGTH] width = inputs[Aircraft.Fuselage.MAX_WIDTH] - num_eng = options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_engines_factor = distributed_engine_count_factor(num_eng) mass_scaler = inputs[Aircraft.Electrical.MASS_SCALER] @@ -62,49 +66,42 @@ def compute_partials(self, inputs, J): width_fact = width**0.14 ecf_fact = num_engines_factor**0.69 - J[Aircraft.Electrical.MASS, Aircraft.Fuselage.LENGTH] = \ - 0.4 * length**-0.6 * fact * width_fact * ecf_fact * \ - mass_scaler / GRAV_ENGLISH_LBM + J[Aircraft.Electrical.MASS, Aircraft.Fuselage.LENGTH] = ( + 0.4 * length**-0.6 * fact * width_fact * ecf_fact * mass_scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Electrical.MASS, Aircraft.Fuselage.MAX_WIDTH] = \ - 0.14 * width**-0.86 * fact * length_fact * \ - ecf_fact * mass_scaler / GRAV_ENGLISH_LBM + J[Aircraft.Electrical.MASS, Aircraft.Fuselage.MAX_WIDTH] = ( + 0.14 * width**-0.86 * fact * length_fact * ecf_fact * mass_scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Electrical.MASS, Aircraft.Electrical.MASS_SCALER] = \ + J[Aircraft.Electrical.MASS, Aircraft.Electrical.MASS_SCALER] = ( fact * length_fact * ecf_fact * width_fact / GRAV_ENGLISH_LBM + ) class AltElectricalMass(om.ExplicitComponent): - """ - Computes the mass of the electrical susbsystems using the alternate method. - """ + """Computes the mass of the electrical subsystems using the alternate method.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) def setup(self): - add_aviary_input(self, Aircraft.Electrical.MASS_SCALER, 1.0) + add_aviary_input(self, Aircraft.Electrical.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Electrical.MASS, 1.0) + add_aviary_output(self, Aircraft.Electrical.MASS, units='lbm') def setup_partials(self): self.declare_partials(of='*', wrt='*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - npass = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + npass = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] mass_scaler = inputs[Aircraft.Electrical.MASS_SCALER] - outputs[Aircraft.Electrical.MASS] = 16.3 * \ - npass * mass_scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.Electrical.MASS] = 16.3 * npass * mass_scaler / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - npass = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + npass = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] - J[Aircraft.Electrical.MASS, Aircraft.Electrical.MASS_SCALER] = \ + J[Aircraft.Electrical.MASS, Aircraft.Electrical.MASS_SCALER] = ( 16.3 * npass / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/empty_margin.py b/aviary/subsystems/mass/flops_based/empty_margin.py index 4c4b5cf33a..09e088dbff 100644 --- a/aviary/subsystems/mass/flops_based/empty_margin.py +++ b/aviary/subsystems/mass/flops_based/empty_margin.py @@ -1,30 +1,19 @@ import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft class EmptyMassMargin(om.ExplicitComponent): - """ - Calculates the empty mass margin. - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """Calculates the empty mass margin.""" def setup(self): - add_aviary_input(self, Aircraft.Propulsion.MASS, val=0.) - - add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, val=0.) - - add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, val=0.) + add_aviary_input(self, Aircraft.Propulsion.MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, units='unitless') - add_aviary_input(self, Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, val=0.0) - - add_aviary_output(self, Aircraft.Design.EMPTY_MASS_MARGIN, val=0.0) + add_aviary_output(self, Aircraft.Design.EMPTY_MASS_MARGIN, units='lbm') def setup_partials(self): self.declare_partials('*', '*') @@ -36,10 +25,10 @@ def compute(self, inputs, outputs): scaler = inputs[Aircraft.Design.EMPTY_MASS_MARGIN_SCALER] outputs[Aircraft.Design.EMPTY_MASS_MARGIN] = ( - prop_mass + struct_mass + sys_eq_mass) * scaler + prop_mass + struct_mass + sys_eq_mass + ) * scaler def compute_partials(self, inputs, J): - prop_mass = inputs[Aircraft.Propulsion.MASS] struct_mass = inputs[Aircraft.Design.STRUCTURE_MASS] sys_eq_mass = inputs[Aircraft.Design.SYSTEMS_EQUIP_MASS] @@ -47,8 +36,7 @@ def compute_partials(self, inputs, J): J[Aircraft.Design.EMPTY_MASS_MARGIN, Aircraft.Propulsion.MASS] = scaler J[Aircraft.Design.EMPTY_MASS_MARGIN, Aircraft.Design.STRUCTURE_MASS] = scaler - J[Aircraft.Design.EMPTY_MASS_MARGIN, Aircraft.Design.SYSTEMS_EQUIP_MASS] = \ - scaler - J[ - Aircraft.Design.EMPTY_MASS_MARGIN, - Aircraft.Design.EMPTY_MASS_MARGIN_SCALER] = prop_mass + struct_mass + sys_eq_mass + J[Aircraft.Design.EMPTY_MASS_MARGIN, Aircraft.Design.SYSTEMS_EQUIP_MASS] = scaler + J[Aircraft.Design.EMPTY_MASS_MARGIN, Aircraft.Design.EMPTY_MASS_MARGIN_SCALER] = ( + prop_mass + struct_mass + sys_eq_mass + ) diff --git a/aviary/subsystems/mass/flops_based/engine.py b/aviary/subsystems/mass/flops_based/engine.py index 34c792f6cc..5778937c5f 100644 --- a/aviary/subsystems/mass/flops_based/engine.py +++ b/aviary/subsystems/mass/flops_based/engine.py @@ -1,52 +1,45 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft - # TODO should additional misc mass be separated out into a separate component? +# TODO include estimation for baseline (unscaled) mass if not provided (NTRS paper on FLOPS equations pg. 30) class EngineMass(om.ExplicitComponent): - ''' + """ Calculate scaled engine mass and additional miscellaneous mass for a single named engine model. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.ADDITIONAL_MASS_FRACTION) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Engine.REFERENCE_MASS, units='lbm') + add_aviary_option(self, Aircraft.Engine.REFERENCE_SLS_THRUST, units='lbf') + add_aviary_option(self, Aircraft.Engine.SCALE_MASS) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, - val=np.zeros(num_engine_type)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Aircraft.Engine.MASS_SCALER, - val=np.zeros(num_engine_type)) + add_aviary_input( + self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type, units='lbf' + ) + add_aviary_input(self, Aircraft.Engine.MASS_SCALER, shape=num_engine_type, units='unitless') - add_aviary_output(self, Aircraft.Engine.MASS, val=np.zeros(num_engine_type)) - add_aviary_output(self, Aircraft.Engine.ADDITIONAL_MASS, - val=np.zeros(num_engine_type)) - add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_MASS, val=0.0) + add_aviary_output(self, Aircraft.Engine.MASS, shape=num_engine_type, units='lbm') + add_aviary_output(self, Aircraft.Engine.ADDITIONAL_MASS, shape=num_engine_type, units='lbm') + add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_MASS, units='lbm') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - - # cast to numpy arrays to ensure values are always correct type - num_engines = np.array(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - scale_mass = np.array(aviary_options.get_val(Aircraft.Engine.SCALE_MASS)) - addtl_mass_fraction = np.array(aviary_options.get_val( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION)) - ref_engine_mass = np.array(aviary_options.get_val( - Aircraft.Engine.REFERENCE_MASS, units='lbm')) - ref_sls_thrust = np.array(aviary_options.get_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, units='lbf')) + options = self.options + num_engines = options[Aircraft.Engine.NUM_ENGINES] + scale_mass = options[Aircraft.Engine.SCALE_MASS] + addtl_mass_fraction = options[Aircraft.Engine.ADDITIONAL_MASS_FRACTION] + ref_engine_mass, _ = options[Aircraft.Engine.REFERENCE_MASS] + ref_sls_thrust, _ = options[Aircraft.Engine.REFERENCE_SLS_THRUST] scaled_sls_thrust = np.array(inputs[Aircraft.Engine.SCALED_SLS_THRUST]) scaling_parameter = np.array(inputs[Aircraft.Engine.MASS_SCALER]) @@ -62,47 +55,39 @@ def compute(self, inputs, outputs): # scale engine mass using equation chosen by value of user-provided mass scaler thrust_ratio = scaled_sls_thrust / ref_sls_thrust - calc_mass[scale_idx] = ref_engine_mass[scale_idx] + ( - scaled_sls_thrust[scale_idx] - ref_sls_thrust[scale_idx]) * scaling_parameter[scale_idx] + calc_mass[scale_idx] = ( + ref_engine_mass[scale_idx] + + (scaled_sls_thrust[scale_idx] - ref_sls_thrust[scale_idx]) + * scaling_parameter[scale_idx] + ) - calc_mass[param_idx] = ref_engine_mass[param_idx] * \ - thrust_ratio[param_idx]**scaling_parameter[param_idx] + calc_mass[param_idx] = ( + ref_engine_mass[param_idx] * thrust_ratio[param_idx] ** scaling_parameter[param_idx] + ) addtl_mass = addtl_mass_fraction * calc_mass outputs[Aircraft.Engine.MASS] = calc_mass - outputs[Aircraft.Propulsion.TOTAL_ENGINE_MASS] = sum( - calc_mass * num_engines) + outputs[Aircraft.Propulsion.TOTAL_ENGINE_MASS] = sum(calc_mass * num_engines) outputs[Aircraft.Engine.ADDITIONAL_MASS] = addtl_mass def setup_partials(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) - self.declare_partials(Aircraft.Engine.MASS, - ['*'], - rows=shape, cols=shape) - self.declare_partials( - Aircraft.Engine.ADDITIONAL_MASS, - ['*'], - rows=shape, cols=shape) - self.declare_partials( - Aircraft.Propulsion.TOTAL_ENGINE_MASS, - ['*']) + self.declare_partials(Aircraft.Engine.MASS, ['*'], rows=shape, cols=shape) + self.declare_partials(Aircraft.Engine.ADDITIONAL_MASS, ['*'], rows=shape, cols=shape) + self.declare_partials(Aircraft.Propulsion.TOTAL_ENGINE_MASS, ['*']) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - - num_engines = np.array(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - scale_mass = np.array(aviary_options.get_val(Aircraft.Engine.SCALE_MASS)) - addtl_mass_fraction = np.array(aviary_options.get_val( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION)) - ref_engine_mass = np.array(aviary_options.get_val( - Aircraft.Engine.REFERENCE_MASS, units='lbm')) - ref_sls_thrust = np.array(aviary_options.get_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, units='lbf')) + options = self.options + num_engines = options[Aircraft.Engine.NUM_ENGINES] + num_engine_type = len(num_engines) + + scale_mass = options[Aircraft.Engine.SCALE_MASS] + addtl_mass_fraction = options[Aircraft.Engine.ADDITIONAL_MASS_FRACTION] + ref_engine_mass, _ = options[Aircraft.Engine.REFERENCE_MASS] + ref_sls_thrust, _ = options[Aircraft.Engine.REFERENCE_SLS_THRUST] scaled_sls_thrust = np.array(inputs[Aircraft.Engine.SCALED_SLS_THRUST]) scaling_parameter = np.array(inputs[Aircraft.Engine.MASS_SCALER]) @@ -120,39 +105,37 @@ def compute_partials(self, inputs, J): param_idx = np.where(scaling_parameter[scale_idx] >= 0.3) thrust_deriv[scale_idx] = scaling_parameter[scale_idx] - scaled_mass = ref_engine_mass[param_idx] * \ - thrust_ratio[param_idx]**scaling_parameter[param_idx] - thrust_deriv[param_idx] = (scaling_parameter[param_idx] * - scaled_mass) / scaled_sls_thrust[param_idx] - - scale_deriv[scale_idx] = ( - scaled_sls_thrust[scale_idx] - ref_sls_thrust[scale_idx]) - - scale_deriv[param_idx] = ref_engine_mass[param_idx] * \ - thrust_ratio[param_idx]**scaling_parameter[param_idx] + scaled_mass = ( + ref_engine_mass[param_idx] * thrust_ratio[param_idx] ** scaling_parameter[param_idx] + ) + thrust_deriv[param_idx] = (scaling_parameter[param_idx] * scaled_mass) / scaled_sls_thrust[ + param_idx + ] + + scale_deriv[scale_idx] = scaled_sls_thrust[scale_idx] - ref_sls_thrust[scale_idx] + + scale_deriv[param_idx] = ( + ref_engine_mass[param_idx] * thrust_ratio[param_idx] ** scaling_parameter[param_idx] + ) if len(param_idx) > 0: scale_deriv[param_idx] = scaled_mass * np.log(thrust_ratio[param_idx]) - J[Aircraft.Engine.MASS, - Aircraft.Engine.SCALED_SLS_THRUST - ] = thrust_deriv + J[Aircraft.Engine.MASS, Aircraft.Engine.SCALED_SLS_THRUST] = thrust_deriv - J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, - Aircraft.Engine.SCALED_SLS_THRUST - ] = thrust_deriv * num_engines + J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + thrust_deriv * num_engines + ) - J[Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Engine.SCALED_SLS_THRUST - ] = addtl_mass_fraction * thrust_deriv + J[Aircraft.Engine.ADDITIONAL_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + addtl_mass_fraction * thrust_deriv + ) - J[Aircraft.Engine.MASS, - Aircraft.Engine.MASS_SCALER - ] = scale_deriv + J[Aircraft.Engine.MASS, Aircraft.Engine.MASS_SCALER] = scale_deriv - J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, - Aircraft.Engine.MASS_SCALER - ] = scale_deriv * num_engines + J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, Aircraft.Engine.MASS_SCALER] = ( + scale_deriv * num_engines + ) - J[Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Engine.MASS_SCALER - ] = addtl_mass_fraction * scale_deriv + J[Aircraft.Engine.ADDITIONAL_MASS, Aircraft.Engine.MASS_SCALER] = ( + addtl_mass_fraction * scale_deriv + ) diff --git a/aviary/subsystems/mass/flops_based/engine_controls.py b/aviary/subsystems/mass/flops_based/engine_controls.py index c17868c1f9..490b8da369 100644 --- a/aviary/subsystems/mass/flops_based/engine_controls.py +++ b/aviary/subsystems/mass/flops_based/engine_controls.py @@ -2,14 +2,15 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.subsystems.mass.flops_based.distributed_prop import ( - distributed_engine_count_factor, distributed_thrust_factor) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output + distributed_engine_count_factor, + distributed_thrust_factor, +) +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class TransportEngineCtrlsMass(om.ExplicitComponent): - ''' + """ Calculate the estimated mass of the engine controls. Use for both traditional and blended-wing-body type transports. @@ -22,28 +23,24 @@ class TransportEngineCtrlsMass(om.ExplicitComponent): Calculates total propulsion-system level mass of all engine controls All engines have engine controls that use this equation - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) def setup(self): - add_aviary_input( - self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=0.0, units='lbf') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, units='lbf') - add_aviary_output( - self, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, val=0.0, units='lbm') + add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, units='lbm') def setup_partials(self): - self.declare_partials(Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - [Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST]) + self.declare_partials( + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, + [Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST], + ) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - - num_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_engines_factor = distributed_engine_count_factor(num_engines) max_sls_thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] @@ -51,13 +48,12 @@ def compute(self, inputs, outputs): total_controls_weight = 0.26 * num_engines_factor * thrust_factor**0.5 - outputs[Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] = \ + outputs[Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] = ( total_controls_weight / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - - num_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] max_sls_thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] thrust_factor = distributed_thrust_factor(max_sls_thrust, num_engines) @@ -65,5 +61,5 @@ def compute_partials(self, inputs, J, discrete_inputs=None): J[ Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, ] = 0.13 / distributed_thrust_factor_exp / GRAV_ENGLISH_LBM diff --git a/aviary/subsystems/mass/flops_based/engine_oil.py b/aviary/subsystems/mass/flops_based/engine_oil.py index d82cd8e63f..a8ce26037e 100644 --- a/aviary/subsystems/mass/flops_based/engine_oil.py +++ b/aviary/subsystems/mass/flops_based/engine_oil.py @@ -2,14 +2,15 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.subsystems.mass.flops_based.distributed_prop import ( - distributed_engine_count_factor, distributed_thrust_factor) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output + distributed_engine_count_factor, + distributed_thrust_factor, +) +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class TransportEngineOilMass(om.ExplicitComponent): - ''' + """ Calculates the mass of engine oil using the transport/general aviation method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. @@ -19,86 +20,77 @@ class TransportEngineOilMass(om.ExplicitComponent): Calculates total, propulsion-system level mass of all engine oil All engines assumed to use engine oil whose mass follows this equation - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) def setup(self): - add_aviary_input(self, Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, units='lbf') - add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=0.0) - - add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, val=0.0) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] scaler = inputs[Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER] - num_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_eng_fact = distributed_engine_count_factor(num_eng) max_sls_thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] thrust_factor = distributed_thrust_factor(max_sls_thrust, num_eng) - outputs[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS] = \ + outputs[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS] = ( 0.082 * num_eng_fact * thrust_factor**0.65 * scaler / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] scaler = inputs[Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER] - num_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_eng_fact = distributed_engine_count_factor(num_eng) max_sls_thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] thrust_factor = distributed_thrust_factor(max_sls_thrust, num_eng) - J[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, - Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER - ] = 0.082 * num_eng_fact * thrust_factor**0.65 / GRAV_ENGLISH_LBM + J[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER] = ( + 0.082 * num_eng_fact * thrust_factor**0.65 / GRAV_ENGLISH_LBM + ) - J[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST - ] = 0.0533 * thrust_factor**-0.35 * scaler / GRAV_ENGLISH_LBM + J[ + Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST + ] = 0.0533 * thrust_factor**-0.35 * scaler / GRAV_ENGLISH_LBM class AltEngineOilMass(om.ExplicitComponent): - ''' + """ Calculates the mass of engine oil using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) def setup(self): - add_aviary_input(self, Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, val=0.0) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] scaler = inputs[Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER] - outputs[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS] = \ + outputs[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS] = ( 240.0 * ((pax + 39) // 40) * scaler / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - pax = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + pax = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] - J[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, - Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER - ] = 240.0 * ((pax + 39) // 40) / GRAV_ENGLISH_LBM + J[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER] = ( + 240.0 * ((pax + 39) // 40) / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/engine_pod.py b/aviary/subsystems/mass/flops_based/engine_pod.py index 256c26d26f..2cbc49ef75 100644 --- a/aviary/subsystems/mass/flops_based/engine_pod.py +++ b/aviary/subsystems/mass/flops_based/engine_pod.py @@ -2,73 +2,77 @@ import openmdao.api as om from aviary.subsystems.mass.flops_based.distributed_prop import nacelle_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class EnginePodMass(om.ExplicitComponent): - ''' + """ Calculates the mass of a single engine pod for each unique engine type. ASSUMPTIONS: - System-level masses are estimated per engine by normalizing with ratio of total engine model set's thrust to total aircraft thrust - Engine mount location (wing vs. fueselage) has no impact on pod mass - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - - add_aviary_input(self, Aircraft.Electrical.MASS, val=0.0) - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, val=0.0) - add_aviary_input(self, Aircraft.Hydraulics.MASS, val=0.0) - add_aviary_input(self, Aircraft.Instruments.MASS, val=0.0) - add_aviary_input(self, Aircraft.Nacelle.MASS, val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Engine.MASS, val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_STARTER_MASS, val=0.0) - add_aviary_input(self, Aircraft.Engine.THRUST_REVERSERS_MASS, - val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, - val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=0.0) - - add_aviary_output(self, Aircraft.Engine.POD_MASS, val=np.zeros(num_engine_type)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input(self, Aircraft.Electrical.MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, units='lbm') + add_aviary_input(self, Aircraft.Hydraulics.MASS, units='lbm') + add_aviary_input(self, Aircraft.Instruments.MASS, units='lbm') + add_aviary_input(self, Aircraft.Nacelle.MASS, shape=num_engine_type, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Engine.MASS, shape=num_engine_type, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_STARTER_MASS, units='lbm') + add_aviary_input( + self, Aircraft.Engine.THRUST_REVERSERS_MASS, shape=num_engine_type, units='lbm' + ) + add_aviary_input( + self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type, units='lbf' + ) + add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, units='lbf') + + add_aviary_output(self, Aircraft.Engine.POD_MASS, shape=num_engine_type, units='lbm') def setup_partials(self): self.declare_partials('*', '*') # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) - self.declare_partials(Aircraft.Engine.POD_MASS, - Aircraft.Engine.THRUST_REVERSERS_MASS, - rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Engine.POD_MASS, - Aircraft.Engine.MASS, - rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Engine.POD_MASS, - Aircraft.Nacelle.MASS, - rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Engine.POD_MASS, - Aircraft.Engine.SCALED_SLS_THRUST, - rows=shape, cols=shape, val=1.0) + self.declare_partials( + Aircraft.Engine.POD_MASS, + Aircraft.Engine.THRUST_REVERSERS_MASS, + rows=shape, + cols=shape, + val=1.0, + ) + self.declare_partials( + Aircraft.Engine.POD_MASS, Aircraft.Engine.MASS, rows=shape, cols=shape, val=1.0 + ) + self.declare_partials( + Aircraft.Engine.POD_MASS, Aircraft.Nacelle.MASS, rows=shape, cols=shape, val=1.0 + ) + self.declare_partials( + Aircraft.Engine.POD_MASS, + Aircraft.Engine.SCALED_SLS_THRUST, + rows=shape, + cols=shape, + val=1.0, + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - # BUG this methodology completely ignores miscellaneous mass. There is a discrepency between this calculation + # BUG this methodology completely ignores miscellaneous mass. There is a discrepancy between this calculation # and miscellaneous mass. Engine control, starter, and additional mass have a scaler applied to them, and # if their calculated values are used directly this scaler is skipped - aviary_options: AviaryValues = self.options['aviary_options'] - num_eng = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] nacelle_count = nacelle_count_factor(num_eng) eng_thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] @@ -93,28 +97,22 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): (num_eng * m_eng) + m_thr + engine_thrust_ratio - * ( - m_start - + .25 * (m_ctrl + m_fsys) - + .13 * (m_elec + m_hyd) - + .11 * m_inst - ) + * (m_start + 0.25 * (m_ctrl + m_fsys) + 0.13 * (m_elec + m_hyd) + 0.11 * m_inst) ) pod_mass = np.array([]) # calculate engine pod mass for single engine of each type for i in range(len(num_eng)): - pod_mass = np.append(pod_mass, - nacelle_content_mass[i] / max(1, - num_eng[i]) + m_nac[i] / max(1, - nacelle_count[i])) + pod_mass = np.append( + pod_mass, + nacelle_content_mass[i] / max(1, num_eng[i]) + m_nac[i] / max(1, nacelle_count[i]), + ) outputs[Aircraft.Engine.POD_MASS] = pod_mass def compute_partials(self, inputs, partials, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - num_eng = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] count_factor = nacelle_count_factor(num_eng) m_start = inputs[Aircraft.Propulsion.TOTAL_STARTER_MASS] @@ -123,7 +121,6 @@ def compute_partials(self, inputs, partials, discrete_inputs=None): m_elec = inputs[Aircraft.Electrical.MASS] m_hyd = inputs[Aircraft.Hydraulics.MASS] m_fsys = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS] - m_nac = inputs[Aircraft.Nacelle.MASS] eng_thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] total_thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] @@ -134,39 +131,32 @@ def compute_partials(self, inputs, partials, discrete_inputs=None): fact1 = np.array([1.0 / max(1, eng) for eng in num_eng]) fact2 = np.array([1.0 / max(1, fact) for fact in count_factor]) - nac_fact = (m_start + 0.25 * (m_ctrl + m_fsys) + - 0.13 * (m_elec + m_hyd) + 0.11 * m_inst) + nac_fact = m_start + 0.25 * (m_ctrl + m_fsys) + 0.13 * (m_elec + m_hyd) + 0.11 * m_inst partials[Aircraft.Engine.POD_MASS, Aircraft.Engine.MASS] = 1.0 - partials[Aircraft.Engine.POD_MASS, Aircraft.Engine.THRUST_REVERSERS_MASS] = \ - fact1 + partials[Aircraft.Engine.POD_MASS, Aircraft.Engine.THRUST_REVERSERS_MASS] = fact1 - partials[Aircraft.Engine.POD_MASS, - Aircraft.Propulsion.TOTAL_STARTER_MASS] = fact1 * ratio + partials[Aircraft.Engine.POD_MASS, Aircraft.Propulsion.TOTAL_STARTER_MASS] = fact1 * ratio - partials[Aircraft.Engine.POD_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] = .25 * fact1 * ratio + partials[Aircraft.Engine.POD_MASS, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] = ( + 0.25 * fact1 * ratio + ) - partials[Aircraft.Engine.POD_MASS, Aircraft.Instruments.MASS] = \ - .11 * fact1 * ratio + partials[Aircraft.Engine.POD_MASS, Aircraft.Instruments.MASS] = 0.11 * fact1 * ratio - partials[Aircraft.Engine.POD_MASS, Aircraft.Electrical.MASS] = \ - .13 * fact1 * ratio + partials[Aircraft.Engine.POD_MASS, Aircraft.Electrical.MASS] = 0.13 * fact1 * ratio - partials[Aircraft.Engine.POD_MASS, Aircraft.Hydraulics.MASS] = \ - .13 * fact1 * ratio + partials[Aircraft.Engine.POD_MASS, Aircraft.Hydraulics.MASS] = 0.13 * fact1 * ratio - partials[Aircraft.Engine.POD_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS] = \ - .25 * fact1 * ratio + partials[Aircraft.Engine.POD_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS] = 0.25 * fact1 * ratio - partials[Aircraft.Engine.POD_MASS, Aircraft.Nacelle.MASS] = \ - fact2 + partials[Aircraft.Engine.POD_MASS, Aircraft.Nacelle.MASS] = fact2 - partials[Aircraft.Engine.POD_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = \ - (num_eng * nac_fact * fact1) / total_thrust + partials[Aircraft.Engine.POD_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + num_eng * nac_fact * fact1 + ) / total_thrust - partials[ - Aircraft.Engine.POD_MASS, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] = \ - -(num_eng * eng_thrust * nac_fact * fact1) / (total_thrust ** 2) + partials[Aircraft.Engine.POD_MASS, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] = -( + num_eng * eng_thrust * nac_fact * fact1 + ) / (total_thrust**2) diff --git a/aviary/subsystems/mass/flops_based/fin.py b/aviary/subsystems/mass/flops_based/fin.py index 989ee1ee2a..cbc918ba96 100644 --- a/aviary/subsystems/mass/flops_based/fin.py +++ b/aviary/subsystems/mass/flops_based/fin.py @@ -1,48 +1,44 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class FinMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the fin(s). The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fins.NUM_FINS) def setup(self): - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Fins.AREA, val=0.0) - add_aviary_input(self, Aircraft.Fins.TAPER_RATIO, val=0.0) - add_aviary_input(self, Aircraft.Fins.MASS_SCALER, val=1.0) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fins.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Fins.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Fins.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Fins.MASS, val=0.0) + add_aviary_output(self, Aircraft.Fins.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - num_fins = aviary_options.get_val(Aircraft.Fins.NUM_FINS) + num_fins = self.options[Aircraft.Fins.NUM_FINS] if num_fins > 0: togw = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM area = inputs[Aircraft.Fins.AREA] taper_ratio = inputs[Aircraft.Fins.TAPER_RATIO] - fin_weight = 0.32 * togw**0.3 * area**0.85 * (taper_ratio+0.5) * num_fins - outputs[Aircraft.Fins.MASS] = fin_weight * \ - inputs[Aircraft.Fins.MASS_SCALER] / GRAV_ENGLISH_LBM + fin_weight = 0.32 * togw**0.3 * area**0.85 * (taper_ratio + 0.5) * num_fins + outputs[Aircraft.Fins.MASS] = ( + fin_weight * inputs[Aircraft.Fins.MASS_SCALER] / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_fins = aviary_options.get_val(Aircraft.Fins.NUM_FINS) + num_fins = self.options[Aircraft.Fins.NUM_FINS] if num_fins > 0: area = inputs[Aircraft.Fins.AREA] taper_ratio = inputs[Aircraft.Fins.TAPER_RATIO] @@ -53,13 +49,19 @@ def compute_partials(self, inputs, J): gross_weight_exp = gross_weight**0.3 J[Aircraft.Fins.MASS, Aircraft.Fins.AREA] = ( - (0.272 * num_fins * scaler * (taper_ratio + 0.5) * gross_weight_exp) - / area**0.15) / GRAV_ENGLISH_LBM - J[Aircraft.Fins.MASS, Aircraft.Fins.TAPER_RATIO] = \ + (0.272 * num_fins * scaler * (taper_ratio + 0.5) * gross_weight_exp) / area**0.15 + ) / GRAV_ENGLISH_LBM + J[Aircraft.Fins.MASS, Aircraft.Fins.TAPER_RATIO] = ( 0.32 * area_exp * num_fins * scaler * gross_weight_exp / GRAV_ENGLISH_LBM - J[Aircraft.Fins.MASS, Aircraft.Fins.MASS_SCALER] = \ - 0.32 * area_exp * num_fins * \ - (taper_ratio + 0.5) * gross_weight_exp / GRAV_ENGLISH_LBM + ) + J[Aircraft.Fins.MASS, Aircraft.Fins.MASS_SCALER] = ( + 0.32 + * area_exp + * num_fins + * (taper_ratio + 0.5) + * gross_weight_exp + / GRAV_ENGLISH_LBM + ) J[Aircraft.Fins.MASS, Mission.Design.GROSS_MASS] = ( - (0.096 * area_exp * num_fins * scaler * (taper_ratio + 0.5)) - / gross_weight**0.7) + 0.096 * area_exp * num_fins * scaler * (taper_ratio + 0.5) + ) / gross_weight**0.7 diff --git a/aviary/subsystems/mass/flops_based/fuel_capacity.py b/aviary/subsystems/mass/flops_based/fuel_capacity.py index 98d50b2e95..932588d3b6 100644 --- a/aviary/subsystems/mass/flops_based/fuel_capacity.py +++ b/aviary/subsystems/mass/flops_based/fuel_capacity.py @@ -1,151 +1,134 @@ import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft +from openmdao.utils.units import convert_units class FuelCapacityGroup(om.Group): - """ - Compute the maximum fuel that can be carried. - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """Compute the maximum fuel that can be carried.""" def setup(self): - aviary_options = self.options['aviary_options'] - self.add_subsystem( - 'wing_fuel_capacity', - WingFuelCapacity(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'wing_fuel_capacity', WingFuelCapacity(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( 'fuselage_fuel_capacity', FuselageFuelCapacity(), - promotes_inputs=['*'], promotes_outputs=['*']) + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'auxiliary_fuel_capacity', AuxFuelCapacity(), - promotes_inputs=['*'], promotes_outputs=['*']) + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'total_fuel_capacity', TotalFuelCapacity(), - promotes_inputs=['*'], promotes_outputs=['*']) + promotes_inputs=['*'], + promotes_outputs=['*'], + ) class FuselageFuelCapacity(om.ExplicitComponent): - """ - Compute the maximum fuel that can be carried in the fuselage. - """ + """Compute the maximum fuel that can be carried in the fuselage.""" def setup(self): - add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, 0.0), - add_aviary_input(self, Aircraft.Fuel.WING_FUEL_CAPACITY, 0.0), - add_aviary_output(self, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0), + add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_CAPACITY, units='lbm') + add_aviary_output(self, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, units='lbm') def setup_partials(self): self.declare_partials( - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, - Aircraft.Fuel.TOTAL_CAPACITY, val=1.0) + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, Aircraft.Fuel.TOTAL_CAPACITY, val=1.0 + ) self.declare_partials( - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, - Aircraft.Fuel.WING_FUEL_CAPACITY, val=-1.0) + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, Aircraft.Fuel.WING_FUEL_CAPACITY, val=-1.0 + ) def compute(self, inputs, outputs): outputs[Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY] = ( - inputs[Aircraft.Fuel.TOTAL_CAPACITY] - - inputs[Aircraft.Fuel.WING_FUEL_CAPACITY]) + inputs[Aircraft.Fuel.TOTAL_CAPACITY] - inputs[Aircraft.Fuel.WING_FUEL_CAPACITY] + ) class AuxFuelCapacity(om.ExplicitComponent): - """ - Compute the maximum fuel that can be carried in the auxiliary tanks. - """ + """Compute the maximum fuel that can be carried in the auxiliary tanks.""" def setup(self): - add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, 0.0), - add_aviary_input(self, Aircraft.Fuel.WING_FUEL_CAPACITY, 0.0), - add_aviary_input(self, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0), - add_aviary_output(self, Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0), + add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, units='lbm') + add_aviary_output(self, Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, units='lbm') def setup_partials(self): self.declare_partials( - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - Aircraft.Fuel.TOTAL_CAPACITY, val=1.0) + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, Aircraft.Fuel.TOTAL_CAPACITY, val=1.0 + ) self.declare_partials( - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - Aircraft.Fuel.WING_FUEL_CAPACITY, val=-1.0) + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, Aircraft.Fuel.WING_FUEL_CAPACITY, val=-1.0 + ) self.declare_partials( - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, val=-1.0) + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, val=-1.0 + ) def compute(self, inputs, outputs): outputs[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY] = ( inputs[Aircraft.Fuel.TOTAL_CAPACITY] - inputs[Aircraft.Fuel.WING_FUEL_CAPACITY] - - inputs[Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY]) + - inputs[Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY] + ) class TotalFuelCapacity(om.ExplicitComponent): - """ - Compute the total fuel that can be carried in all tanks. - """ + """Compute the total fuel that can be carried in all tanks.""" def setup(self): - add_aviary_input(self, Aircraft.Fuel.WING_FUEL_CAPACITY, 0.0), - add_aviary_input(self, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0), - add_aviary_input(self, Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0), - add_aviary_output(self, Aircraft.Fuel.TOTAL_CAPACITY, 0.0), + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, units='lbm') + add_aviary_output(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') def setup_partials(self): self.declare_partials( - Aircraft.Fuel.TOTAL_CAPACITY, - Aircraft.Fuel.WING_FUEL_CAPACITY, val=1.0) + Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Fuel.WING_FUEL_CAPACITY, val=1.0 + ) self.declare_partials( - Aircraft.Fuel.TOTAL_CAPACITY, - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, val=1.0) + Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, val=1.0 + ) self.declare_partials( - Aircraft.Fuel.TOTAL_CAPACITY, - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, val=1.0) + Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, val=1.0 + ) def compute(self, inputs, outputs): outputs[Aircraft.Fuel.TOTAL_CAPACITY] = ( inputs[Aircraft.Fuel.WING_FUEL_CAPACITY] + inputs[Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY] - + inputs[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY]) + + inputs[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY] + ) class WingFuelCapacity(om.ExplicitComponent): - """ - Compute the maximum fuel that can be carried in the wing's enclosed space. - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """Compute the maximum fuel that can be carried in the wing's enclosed space.""" def setup(self): - add_aviary_input(self, Aircraft.Fuel.DENSITY_RATIO, 1.0) - add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY, 0.0) - add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY_AREA, 0.0) - add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY_TERM_A, 0.0) - add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY_TERM_B, 0.0) - - add_aviary_input(self, Aircraft.Fuel.CAPACITY_FACTOR, 23.0) - - add_aviary_input(self, Aircraft.Wing.AREA, 0.0) - add_aviary_input(self, Aircraft.Wing.SPAN, 0.0) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, 0.0) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, 0.0) - - add_aviary_output(self, Aircraft.Fuel.WING_FUEL_CAPACITY, 0.0) + add_aviary_input(self, Aircraft.Fuel.DENSITY, units='lbm/galUS') + add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY_AREA, units='unitless') + add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY_TERM_A, units='unitless') + add_aviary_input(self, Aircraft.Fuel.WING_REF_CAPACITY_TERM_B, units='unitless') + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + + add_aviary_output(self, Aircraft.Fuel.WING_FUEL_CAPACITY, units='lbm') def setup_partials(self): self.declare_partials('*', '*') @@ -162,18 +145,24 @@ def compute(self, inputs, outputs): fuel_cap_wing = ( wing_ref_cap + wing_ref_cap_terma * (wing_area**1.5 - wing_ref_cap_area**1.5) - + wing_ref_cap_termb * (wing_area - wing_ref_cap_area)) + + wing_ref_cap_termb * (wing_area - wing_ref_cap_area) + ) else: - density_ratio = inputs[Aircraft.Fuel.DENSITY_RATIO] - cap_factor = inputs[Aircraft.Fuel.CAPACITY_FACTOR] + fuel_density = convert_units(inputs[Aircraft.Fuel.DENSITY], 'lbm/galUS', 'lbm/ft**3') + volume_fraction = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] span = inputs[Aircraft.Wing.SPAN] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] thickness_to_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] - - fuel_cap_wing = ( - density_ratio * cap_factor * wing_area**2 * thickness_to_chord - * (1.0 - taper_ratio / (1.0 + taper_ratio)**2) / span) + # calculate volume of wing assuming truncated rectangular based pyramid: + volume_of_wing = ( + (2 / 3) + * wing_area**2 + * thickness_to_chord + * (1.0 - taper_ratio / (1.0 + taper_ratio) ** 2) + / span + ) + fuel_cap_wing = fuel_density * volume_fraction * volume_of_wing outputs[Aircraft.Fuel.WING_FUEL_CAPACITY] = fuel_cap_wing @@ -185,55 +174,75 @@ def compute_partials(self, inputs, partials): wing_ref_cap_area = inputs[Aircraft.Fuel.WING_REF_CAPACITY_AREA] wing_ref_cap_termb = inputs[Aircraft.Fuel.WING_REF_CAPACITY_TERM_B] - partials[ - Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.WING_REF_CAPACITY] = 1.0 + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.WING_REF_CAPACITY] = 1.0 - partials[ - Aircraft.Fuel.WING_FUEL_CAPACITY, - Aircraft.Fuel.WING_REF_CAPACITY_TERM_A] = \ + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.WING_REF_CAPACITY_TERM_A] = ( wing_area**1.5 - wing_ref_cap_area**1.5 + ) - partials[ - Aircraft.Fuel.WING_FUEL_CAPACITY, - Aircraft.Fuel.WING_REF_CAPACITY_TERM_B] = wing_area - wing_ref_cap_area + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.WING_REF_CAPACITY_TERM_B] = ( + wing_area - wing_ref_cap_area + ) - partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Wing.AREA] = \ + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Wing.AREA] = ( 1.5 * wing_ref_cap_terma * wing_area**0.5 + wing_ref_cap_termb + ) - partials[ - Aircraft.Fuel.WING_FUEL_CAPACITY, - Aircraft.Fuel.WING_REF_CAPACITY_AREA] = \ + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.WING_REF_CAPACITY_AREA] = ( -1.5 * wing_ref_cap_terma * wing_ref_cap_area**0.5 - wing_ref_cap_termb + ) else: - density_ratio = inputs[Aircraft.Fuel.DENSITY_RATIO] - cap_factor = inputs[Aircraft.Fuel.CAPACITY_FACTOR] + fuel_density = convert_units(inputs[Aircraft.Fuel.DENSITY], 'lbm/galUS', 'lbm/ft**3') + volume_fraction = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] span = inputs[Aircraft.Wing.SPAN] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] thickness_to_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD] - den = (1.0 + taper_ratio) - tr_fact = (1.0 - taper_ratio / den**2) - dfact = - 1.0/den**2 + 2.0 * taper_ratio / den**3 + den = 1.0 + taper_ratio + tr_fact = 1.0 - taper_ratio / den**2 + dfact = -1.0 / den**2 + 2.0 * taper_ratio / den**3 - partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.DENSITY_RATIO] = \ - cap_factor * wing_area**2 * thickness_to_chord * tr_fact / span + conversion_factor = convert_units(1.0, 'lbm/galUS', 'lbm/ft**3') + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.DENSITY] = ( + volume_fraction * (2 / 3) * wing_area**2 * thickness_to_chord * tr_fact / span + ) * conversion_factor - partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.CAPACITY_FACTOR] = \ - density_ratio * wing_area**2 * thickness_to_chord * tr_fact / span + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Fuel.WING_FUEL_FRACTION] = ( + fuel_density * (2 / 3) * wing_area**2 * thickness_to_chord * tr_fact / span + ) partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Wing.SPAN] = ( - -density_ratio * cap_factor * wing_area**2 * thickness_to_chord * tr_fact - / span**2) + -fuel_density + * volume_fraction + * (2 / 3) + * wing_area**2 + * thickness_to_chord + * tr_fact + / span**2 + ) partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Wing.TAPER_RATIO] = ( - density_ratio * cap_factor * wing_area**2 * thickness_to_chord * dfact - / span) - - partials[ - Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Wing.THICKNESS_TO_CHORD] = \ - density_ratio * cap_factor * wing_area**2 * tr_fact / span + fuel_density + * volume_fraction + * (2 / 3) + * wing_area**2 + * thickness_to_chord + * dfact + / span + ) + + partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Wing.THICKNESS_TO_CHORD] = ( + fuel_density * volume_fraction * (2 / 3) * wing_area**2 * tr_fact / span + ) partials[Aircraft.Fuel.WING_FUEL_CAPACITY, Aircraft.Wing.AREA] = ( - 2.0 * density_ratio * cap_factor * wing_area * thickness_to_chord - * tr_fact / span) + 2.0 + * fuel_density + * volume_fraction + * (2 / 3) + * wing_area + * thickness_to_chord + * tr_fact + / span + ) diff --git a/aviary/subsystems/mass/flops_based/fuel_system.py b/aviary/subsystems/mass/flops_based/fuel_system.py index a78851fe2b..4230bf921d 100644 --- a/aviary/subsystems/mass/flops_based/fuel_system.py +++ b/aviary/subsystems/mass/flops_based/fuel_system.py @@ -1,10 +1,8 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.mass.flops_based.distributed_prop import \ - distributed_engine_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.subsystems.mass.flops_based.distributed_prop import distributed_engine_count_factor +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission @@ -16,46 +14,49 @@ class TransportFuelSystemMass(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') - add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, 0.0) - - add_aviary_output(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, val=0.0) + add_aviary_output(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] scaler = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] - num_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_eng_fact = distributed_engine_count_factor(num_eng) - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] outputs[Aircraft.Fuel.FUEL_SYSTEM_MASS] = ( - 1.07 * capacity**0.58 - * num_eng_fact**0.43 * max_mach**0.34 * scaler) / GRAV_ENGLISH_LBM + 1.07 * capacity**0.58 * num_eng_fact**0.43 * max_mach**0.34 * scaler + ) / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] scaler = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] - num_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_eng_fact = distributed_engine_count_factor(num_eng) - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] = ( - 1.07 * capacity**0.58 * num_eng_fact**0.43 * max_mach**0.34 / GRAV_ENGLISH_LBM) + 1.07 * capacity**0.58 * num_eng_fact**0.43 * max_mach**0.34 / GRAV_ENGLISH_LBM + ) J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.TOTAL_CAPACITY] = ( - 1.07 * 0.58 * capacity**-0.42 * num_eng**0.43 * max_mach**0.34 - * scaler / GRAV_ENGLISH_LBM) + 1.07 + * 0.58 + * capacity**-0.42 + * num_eng**0.43 + * max_mach**0.34 + * scaler + / GRAV_ENGLISH_LBM + ) class AltFuelSystemMass(om.ExplicitComponent): @@ -66,51 +67,51 @@ class AltFuelSystemMass(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fuel.NUM_TANKS) def setup(self): - add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, val=0.0) - - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, val=0.0) + add_aviary_output(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - number_of_fuel_tanks = aviary_options.get_val(Aircraft.Fuel.NUM_TANKS) + number_of_fuel_tanks = self.options[Aircraft.Fuel.NUM_TANKS] total_fuel_capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] scaler = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] fuel_sys_weight = ( - 978.6 * - (number_of_fuel_tanks / 13.0) - + 2283.4 - * (total_fuel_capacity / 208100.0)**(2.0 / 3.0) - + 350.0 + 0.00029 * total_fuel_capacity) * scaler + 978.6 * (number_of_fuel_tanks / 13.0) + + 2283.4 * (total_fuel_capacity / 208100.0) ** (2.0 / 3.0) + + 350.0 + + 0.00029 * total_fuel_capacity + ) * scaler - outputs[Aircraft.Fuel.FUEL_SYSTEM_MASS] = \ - fuel_sys_weight / GRAV_ENGLISH_LBM + outputs[Aircraft.Fuel.FUEL_SYSTEM_MASS] = fuel_sys_weight / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - number_of_fuel_tanks = aviary_options.get_val(Aircraft.Fuel.NUM_TANKS) + number_of_fuel_tanks = self.options[Aircraft.Fuel.NUM_TANKS] total_fuel_capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] scaler = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.TOTAL_CAPACITY] = ( - (2283.4 * (2.0 / 3.0) * (1 / 208100.0)**(2.0 / 3.0) - * total_fuel_capacity ** (-1.0/3.0) - + 0.00029) * scaler / GRAV_ENGLISH_LBM + ( + 2283.4 + * (2.0 / 3.0) + * (1 / 208100.0) ** (2.0 / 3.0) + * total_fuel_capacity ** (-1.0 / 3.0) + + 0.00029 + ) + * scaler + / GRAV_ENGLISH_LBM ) J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] = ( - 0.3 * 3262.0 * - (number_of_fuel_tanks / 13.0) - + 0.7 * 3262.0 - * (total_fuel_capacity / 208100.0)**(2.0 / 3.0) - + 350.0 + 0.00029 * total_fuel_capacity) / GRAV_ENGLISH_LBM + 0.3 * 3262.0 * (number_of_fuel_tanks / 13.0) + + 0.7 * 3262.0 * (total_fuel_capacity / 208100.0) ** (2.0 / 3.0) + + 350.0 + + 0.00029 * total_fuel_capacity + ) / GRAV_ENGLISH_LBM diff --git a/aviary/subsystems/mass/flops_based/furnishings.py b/aviary/subsystems/mass/flops_based/furnishings.py index 3dfa8416b1..20112ad616 100644 --- a/aviary/subsystems/mass/flops_based/furnishings.py +++ b/aviary/subsystems/mass/flops_based/furnishings.py @@ -2,322 +2,262 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft class TransportFurnishingsGroupMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the furnishings group using the transport/general aviation method. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.NUM_FLIGHT_CREW) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) def setup(self): - add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') - add_aviary_input(self, Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, val=0.0) - - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, val=0.0) - - add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, val=0.0) - - add_aviary_output(self, Aircraft.Furnishings.MASS, val=0.0) + add_aviary_output(self, Aircraft.Furnishings.MASS, units='lbm') def setup_partials(self): self.declare_partials(of=Aircraft.Furnishings.MASS, wrt='*') - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - - flight_crew_count = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - first_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) - - business_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + flight_crew_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + first_class_count = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + business_class_count = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] + tourist_class_count = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] - tourist_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) - - fuse_count = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) + fuse_count = self.options[Aircraft.Fuselage.NUM_FUSELAGES] scaler = inputs[Aircraft.Furnishings.MASS_SCALER] - pax_compart_length = \ - inputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] + pax_compart_length = inputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] fuse_max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] fuse_max_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] outputs[Aircraft.Furnishings.MASS] = ( - 127.0 * flight_crew_count + 112.0 * first_class_count - + 78.0 * business_class_count + 44.0 * tourist_class_count - + 2.6 * pax_compart_length * (fuse_max_width + fuse_max_height) - * fuse_count + 127.0 * flight_crew_count + + 112.0 * first_class_count + + 78.0 * business_class_count + + 44.0 * tourist_class_count + + 2.6 * pax_compart_length * (fuse_max_width + fuse_max_height) * fuse_count ) * scaler def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - - flight_crew_count = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - first_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) - - business_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) - - tourist_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + flight_crew_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + first_class_count = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + business_class_count = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] + tourist_class_count = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] - fuse_count = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) + fuse_count = self.options[Aircraft.Fuselage.NUM_FUSELAGES] scaler = inputs[Aircraft.Furnishings.MASS_SCALER] fuse_max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] fuse_max_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] - pax_compart_length = \ - inputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] + pax_compart_length = inputs[Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] J[Aircraft.Furnishings.MASS, Aircraft.Furnishings.MASS_SCALER] = ( - 127.0 * flight_crew_count + 112.0 * first_class_count - + 78.0 * business_class_count + 44.0 * tourist_class_count - + 2.6 * pax_compart_length * (fuse_max_width + fuse_max_height) - * fuse_count + 127.0 * flight_crew_count + + 112.0 * first_class_count + + 78.0 * business_class_count + + 44.0 * tourist_class_count + + 2.6 * pax_compart_length * (fuse_max_width + fuse_max_height) * fuse_count ) - J[ - Aircraft.Furnishings.MASS, - Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH - ] = 2.6 * scaler * (fuse_max_width + fuse_max_height) * fuse_count + J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH] = ( + 2.6 * scaler * (fuse_max_width + fuse_max_height) * fuse_count + ) - J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_WIDTH] = \ - J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_HEIGHT] = \ - 2.6 * scaler * pax_compart_length * fuse_count + J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_WIDTH] = J[ + Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_HEIGHT + ] = 2.6 * scaler * pax_compart_length * fuse_count class BWBFurnishingsGroupMass(om.ExplicitComponent): - ''' - Calculates the mass of the furnishings group for HWB aircraft. - ''' + """Calculates the mass of the furnishings group for HWB aircraft.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.NUM_FLIGHT_CREW) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + add_aviary_option(self, Aircraft.Fuselage.MILITARY_CARGO_FLOOR) def setup(self): - add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, val=1.0) - - add_aviary_input(self, Aircraft.BWB.CABIN_AREA, val=100.0) + add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2') - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, val=30.0) + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') - add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, val=15.0) + add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_input(self, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, units='deg') + add_aviary_input(self, Aircraft.BWB.NUM_BAYS, units='unitless') - add_aviary_input( - self, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, val=45.0 - ) - - add_aviary_output(self, Aircraft.Furnishings.MASS, val=0.0) + add_aviary_output(self, Aircraft.Furnishings.MASS, units='lbm') def setup_partials(self): self.declare_partials(of=Aircraft.Furnishings.MASS, wrt='*') - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - - flight_crew_count = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - first_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) - - business_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) - - tourist_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + flight_crew_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + first_class_count = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + business_class_count = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] + tourist_class_count = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] scaler = inputs[Aircraft.Furnishings.MASS_SCALER] fuse_max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] fuse_max_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] weight = ( - 127.0 * flight_crew_count + 112.0 * first_class_count - + 78.0 * business_class_count + 44.0 * tourist_class_count + 127.0 * flight_crew_count + + 112.0 * first_class_count + + 78.0 * business_class_count + + 44.0 * tourist_class_count ) # outputs[Aircraft.Furnishings.MASS] = weight / GRAV_ENGLISH_LBM - if not aviary_options.get_val(Aircraft.Fuselage.MILITARY_CARGO_FLOOR): - acabin = inputs[Aircraft.BWB.CABIN_AREA] - nbay = aviary_options.get_val(Aircraft.BWB.NUM_BAYS) + if not self.options[Aircraft.Fuselage.MILITARY_CARGO_FLOOR]: + acabin = inputs[Aircraft.Fuselage.CABIN_AREA] + nbay = inputs[Aircraft.BWB.NUM_BAYS] - cos = np.cos( - np.pi/180*(inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP]) - ) + cos = np.cos(np.pi / 180 * (inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP])) weight += 2.6 * ( - (acabin / fuse_max_width) - * (fuse_max_width + fuse_max_height * nbay) + (acabin / fuse_max_width) * (fuse_max_width + fuse_max_height * nbay) + (fuse_max_width * (1.0 + 1.0 / cos) * fuse_max_height) ) outputs[Aircraft.Furnishings.MASS] = weight * scaler / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - - flight_crew_count = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - first_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) - - business_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) - - tourist_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + flight_crew_count = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + first_class_count = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + business_class_count = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] + tourist_class_count = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] scaler = inputs[Aircraft.Furnishings.MASS_SCALER] J[Aircraft.Furnishings.MASS, Aircraft.Furnishings.MASS_SCALER] = ( - 127.0 * flight_crew_count + 112.0 * first_class_count - + 78.0 * business_class_count + 44.0 * tourist_class_count + 127.0 * flight_crew_count + + 112.0 * first_class_count + + 78.0 * business_class_count + + 44.0 * tourist_class_count ) / GRAV_ENGLISH_LBM - if aviary_options.get_val(Aircraft.Fuselage.MILITARY_CARGO_FLOOR): - J[Aircraft.Furnishings.MASS, Aircraft.BWB.CABIN_AREA] = 0.0 + if self.options[Aircraft.Fuselage.MILITARY_CARGO_FLOOR]: + J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.CABIN_AREA] = 0.0 J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_WIDTH] = 0.0 J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_HEIGHT] = 0.0 - J[ - Aircraft.Furnishings.MASS, - Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP - ] = 0.0 + J[Aircraft.Furnishings.MASS, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = 0.0 else: d2r = np.radians(inputs[Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP]) cos = np.cos(d2r) tan = np.tan(d2r) - acabin = inputs[Aircraft.BWB.CABIN_AREA] - nbay = aviary_options.get_val(Aircraft.BWB.NUM_BAYS) + acabin = inputs[Aircraft.Fuselage.CABIN_AREA] + nbay = inputs[Aircraft.BWB.NUM_BAYS] fuse_max_width = inputs[Aircraft.Fuselage.MAX_WIDTH] fuse_max_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] - cabin_area = inputs[Aircraft.BWB.CABIN_AREA] - - J[ - Aircraft.Furnishings.MASS, - Aircraft.Furnishings.MASS_SCALER - ] += 2.6 * ( - (acabin / fuse_max_width) - * (fuse_max_width + fuse_max_height * nbay) - + (fuse_max_width * (1.0 + 1.0 / cos) * fuse_max_height) - ) / GRAV_ENGLISH_LBM + cabin_area = inputs[Aircraft.Fuselage.CABIN_AREA] - J[Aircraft.Furnishings.MASS, Aircraft.BWB.CABIN_AREA] = ( - 2.6 * scaler - * (fuse_max_width + fuse_max_height * nbay) - / fuse_max_width + J[Aircraft.Furnishings.MASS, Aircraft.Furnishings.MASS_SCALER] += ( + 2.6 + * ( + (acabin / fuse_max_width) * (fuse_max_width + fuse_max_height * nbay) + + (fuse_max_width * (1.0 + 1.0 / cos) * fuse_max_height) + ) + / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.CABIN_AREA] = ( + 2.6 * scaler * (fuse_max_width + fuse_max_height * nbay) / fuse_max_width ) / GRAV_ENGLISH_LBM J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_WIDTH] = ( - 2.6 * scaler * ( - -cabin_area * fuse_max_height * nbay - / (fuse_max_width * fuse_max_width) + 2.6 + * scaler + * ( + -cabin_area * fuse_max_height * nbay / (fuse_max_width * fuse_max_width) + (1.0 + 1.0 / cos) * fuse_max_height ) ) / GRAV_ENGLISH_LBM J[Aircraft.Furnishings.MASS, Aircraft.Fuselage.MAX_HEIGHT] = ( - 2.6 * scaler * ( - (cabin_area / fuse_max_width) * nbay - + fuse_max_width * (1.0 + 1.0 / cos) - ) + 2.6 + * scaler + * ((cabin_area / fuse_max_width) * nbay + fuse_max_width * (1.0 + 1.0 / cos)) + ) / GRAV_ENGLISH_LBM + + J[Aircraft.Furnishings.MASS, Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP] = ( + 2.6 * scaler * fuse_max_width * fuse_max_height * tan / cos / (180 / np.pi) ) / GRAV_ENGLISH_LBM - J[ - Aircraft.Furnishings.MASS, - Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP - ] = ( - 2.6 * scaler * fuse_max_width * fuse_max_height - * tan / cos / (180 / np.pi) + J[Aircraft.Furnishings.MASS, Aircraft.BWB.NUM_BAYS] = ( + 2.6 * scaler * (acabin / fuse_max_width) * (fuse_max_height) ) / GRAV_ENGLISH_LBM class AltFurnishingsGroupMassBase(om.ExplicitComponent): - ''' + """ Calculates the base mass of the furnishings group using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) def setup(self): - add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Furnishings.MASS_BASE, val=0.0) + add_aviary_output(self, Aircraft.Furnishings.MASS_BASE, units='lbm') def setup_partials(self): self.declare_partials(of=Aircraft.Furnishings.MASS_BASE, wrt='*') - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - pax_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + pax_count = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] scaler = inputs[Aircraft.Furnishings.MASS_SCALER] - outputs[Aircraft.Furnishings.MASS_BASE] = \ - (82.15 * pax_count + 3600.0) * scaler + outputs[Aircraft.Furnishings.MASS_BASE] = (82.15 * pax_count + 3600.0) * scaler def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - pax_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + pax_count = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] - J[ - Aircraft.Furnishings.MASS_BASE, - Aircraft.Furnishings.MASS_SCALER - ] = 82.15 * pax_count + 3600.0 + J[Aircraft.Furnishings.MASS_BASE, Aircraft.Furnishings.MASS_SCALER] = ( + 82.15 * pax_count + 3600.0 + ) class AltFurnishingsGroupMass(om.ExplicitComponent): - ''' + """ Completes the mass calculation for the furnishings group using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.Furnishings.MASS_BASE, val=0.0) - - add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, val=0.0) + add_aviary_input(self, Aircraft.Furnishings.MASS_BASE, units='lbm') + add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, units='lbm') - add_aviary_input(self, Aircraft.Propulsion.MASS, val=0.0) - - add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, val=0.0) - - add_aviary_output(self, Aircraft.Furnishings.MASS, val=0.0) + add_aviary_output(self, Aircraft.Furnishings.MASS, units='lbm') def setup_partials(self): self.declare_partials( @@ -325,24 +265,21 @@ def setup_partials(self): wrt=[ Aircraft.Design.STRUCTURE_MASS, Aircraft.Propulsion.MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE + Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, ], - val=0.01 + val=0.01, ) self.declare_partials( - of=Aircraft.Furnishings.MASS, - wrt=Aircraft.Furnishings.MASS_BASE, - val=1. + of=Aircraft.Furnishings.MASS, wrt=Aircraft.Furnishings.MASS_BASE, val=1.0 ) - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): furn_mass_base = inputs[Aircraft.Furnishings.MASS_BASE] struct_mass = inputs[Aircraft.Design.STRUCTURE_MASS] prop_mass = inputs[Aircraft.Propulsion.MASS] syseq_mass_base = inputs[Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE] - outputs[Aircraft.Furnishings.MASS] = furn_mass_base \ - + 0.01 * (struct_mass + prop_mass + syseq_mass_base) + outputs[Aircraft.Furnishings.MASS] = furn_mass_base + 0.01 * ( + struct_mass + prop_mass + syseq_mass_base + ) diff --git a/aviary/subsystems/mass/flops_based/fuselage.py b/aviary/subsystems/mass/flops_based/fuselage.py index 6b349ec205..d8b8a08ff7 100644 --- a/aviary/subsystems/mass/flops_based/fuselage.py +++ b/aviary/subsystems/mass/flops_based/fuselage.py @@ -1,10 +1,8 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.mass.flops_based.distributed_prop import \ - distributed_engine_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.subsystems.mass.flops_based.distributed_prop import distributed_engine_count_factor +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft @@ -16,65 +14,68 @@ class TransportFuselageMass(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fuselage.MILITARY_CARGO_FLOOR) + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) def setup(self): - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=0.0) + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') - add_aviary_input(self, Aircraft.Fuselage.MASS_SCALER, val=1.0) - - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=0.0) - - add_aviary_output(self, Aircraft.Fuselage.MASS, val=0.0) + add_aviary_output(self, Aircraft.Fuselage.MASS, units='lbm') def setup_partials(self): - self.declare_partials(Aircraft.Fuselage.MASS, "*") + self.declare_partials(Aircraft.Fuselage.MASS, '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] length = inputs[Aircraft.Fuselage.LENGTH] scaler = inputs[Aircraft.Fuselage.MASS_SCALER] avg_diameter = inputs[Aircraft.Fuselage.AVG_DIAMETER] - num_fuse = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) - num_fuse_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_fuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + num_fuse_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] + num_fuse_eng_fact = distributed_engine_count_factor(num_fuse_eng) - military_cargo = aviary_options.get_val(Aircraft.Fuselage.MILITARY_CARGO_FLOOR) + military_cargo = self.options[Aircraft.Fuselage.MILITARY_CARGO_FLOOR] mil_factor = 1.38 if military_cargo else 1.0 outputs[Aircraft.Fuselage.MASS] = ( - scaler * 1.35 * (avg_diameter * length) ** 1.28 * (1.0 + 0.05 * num_fuse_eng_fact) * - mil_factor * num_fuse / GRAV_ENGLISH_LBM + scaler + * 1.35 + * (avg_diameter * length) ** 1.28 + * (1.0 + 0.05 * num_fuse_eng_fact) + * mil_factor + * num_fuse + / GRAV_ENGLISH_LBM ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] length = inputs[Aircraft.Fuselage.LENGTH] scaler = inputs[Aircraft.Fuselage.MASS_SCALER] avg_diameter = inputs[Aircraft.Fuselage.AVG_DIAMETER] - num_fuse = aviary_options.get_val(Aircraft.Fuselage.NUM_FUSELAGES) - num_fuse_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_fuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] + num_fuse_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] num_fuse_eng_fact = distributed_engine_count_factor(num_fuse_eng) - military_cargo = aviary_options.get_val(Aircraft.Fuselage.MILITARY_CARGO_FLOOR) + military_cargo = self.options[Aircraft.Fuselage.MILITARY_CARGO_FLOOR] # avg_diameter = (max_height + max_width) / 2. - avg_diameter_exp = avg_diameter ** 1.28 - length_exp = length ** 1.28 - height_width_exp = (avg_diameter)**0.28 + avg_diameter_exp = avg_diameter**1.28 + length_exp = length**1.28 + height_width_exp = (avg_diameter) ** 0.28 mil_factor = 1.38 if military_cargo else 1.0 addtl_factor = (1.0 + 0.05 * num_fuse_eng_fact) * mil_factor * num_fuse - J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MASS_SCALER] = 1.35 * \ - avg_diameter_exp * length_exp * addtl_factor / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.LENGTH] = scaler * \ - 1.728 * avg_diameter_exp * length ** 0.28 * addtl_factor / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.AVG_DIAMETER] = scaler * \ - 1.728 * length_exp * height_width_exp * addtl_factor / GRAV_ENGLISH_LBM + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MASS_SCALER] = ( + 1.35 * avg_diameter_exp * length_exp * addtl_factor / GRAV_ENGLISH_LBM + ) + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.LENGTH] = ( + scaler * 1.728 * avg_diameter_exp * length**0.28 * addtl_factor / GRAV_ENGLISH_LBM + ) + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.AVG_DIAMETER] = ( + scaler * 1.728 * length_exp * height_width_exp * addtl_factor / GRAV_ENGLISH_LBM + ) class AltFuselageMass(om.ExplicitComponent): @@ -84,21 +85,13 @@ class AltFuselageMass(om.ExplicitComponent): of weight. """ - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.Fuselage.MASS_SCALER, 1.0) - - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, 0.0) - - add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, 0.0) - - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, 0.0) + add_aviary_input(self, Aircraft.Fuselage.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Fuselage.MAX_HEIGHT, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') - add_aviary_output(self, Aircraft.Fuselage.MASS, 1.0) + add_aviary_output(self, Aircraft.Fuselage.MASS, units='lbm') def setup_partials(self): self.declare_partials(of='*', wrt='*') @@ -110,8 +103,11 @@ def compute(self, inputs, outputs): fuse_width = inputs[Aircraft.Fuselage.MAX_WIDTH] outputs[Aircraft.Fuselage.MASS] = ( - 3.939 * fuse_wetted_area / - (fuse_height / fuse_width)**0.221 * mass_scaler / GRAV_ENGLISH_LBM + 3.939 + * fuse_wetted_area + / (fuse_height / fuse_width) ** 0.221 + * mass_scaler + / GRAV_ENGLISH_LBM ) def compute_partials(self, inputs, J): @@ -119,8 +115,8 @@ def compute_partials(self, inputs, J): fuse_wetted_area = inputs[Aircraft.Fuselage.WETTED_AREA] fuse_height = inputs[Aircraft.Fuselage.MAX_HEIGHT] fuse_width = inputs[Aircraft.Fuselage.MAX_WIDTH] - fuse_height_fact = fuse_height ** 0.221 - fuse_width_fact = fuse_width ** 0.221 + fuse_height_fact = fuse_height**0.221 + fuse_width_fact = fuse_width**0.221 total_fact = fuse_height_fact / fuse_width_fact J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MASS_SCALER] = ( @@ -132,11 +128,19 @@ def compute_partials(self, inputs, J): ) J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MAX_HEIGHT] = ( - -0.870519 * fuse_wetted_area * fuse_width_fact - * fuse_height**-1.221 * mass_scaler / GRAV_ENGLISH_LBM + -0.870519 + * fuse_wetted_area + * fuse_width_fact + * fuse_height**-1.221 + * mass_scaler + / GRAV_ENGLISH_LBM ) J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MAX_WIDTH] = ( - 0.870519 * fuse_wetted_area * fuse_width**-0.779 / - fuse_height_fact * mass_scaler / GRAV_ENGLISH_LBM + 0.870519 + * fuse_wetted_area + * fuse_width**-0.779 + / fuse_height_fact + * mass_scaler + / GRAV_ENGLISH_LBM ) diff --git a/aviary/subsystems/mass/flops_based/horizontal_tail.py b/aviary/subsystems/mass/flops_based/horizontal_tail.py index 3c182a5b23..bcbd609f3f 100644 --- a/aviary/subsystems/mass/flops_based/horizontal_tail.py +++ b/aviary/subsystems/mass/flops_based/horizontal_tail.py @@ -1,35 +1,26 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class HorizontalTailMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the horizontal tail. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.HorizontalTail.AREA, val=0.0) - - add_aviary_input(self, Aircraft.HorizontalTail.TAPER_RATIO, val=0.352) - - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - - add_aviary_input(self, Aircraft.HorizontalTail.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.TAPER_RATIO, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.HorizontalTail.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.HorizontalTail.MASS, val=0.0) + add_aviary_output(self, Aircraft.HorizontalTail.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): area = inputs[Aircraft.HorizontalTail.AREA] @@ -37,9 +28,9 @@ def compute(self, inputs, outputs): scaler = inputs[Aircraft.HorizontalTail.MASS_SCALER] taper_ratio = inputs[Aircraft.HorizontalTail.TAPER_RATIO] - outputs[Aircraft.HorizontalTail.MASS] = scaler * 0.530 * \ - area * gross_weight ** 0.20 * \ - (taper_ratio + 0.50) / GRAV_ENGLISH_LBM + outputs[Aircraft.HorizontalTail.MASS] = ( + scaler * 0.530 * area * gross_weight**0.20 * (taper_ratio + 0.50) / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): area = inputs[Aircraft.HorizontalTail.AREA] @@ -47,50 +38,46 @@ def compute_partials(self, inputs, J): scaler = inputs[Aircraft.HorizontalTail.MASS_SCALER] taper_ratio = inputs[Aircraft.HorizontalTail.TAPER_RATIO] - gross_weight_exp = gross_weight ** 0.20 + gross_weight_exp = gross_weight**0.20 - J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.AREA] = scaler * \ - 0.530 * gross_weight_exp * (taper_ratio + 0.50) / GRAV_ENGLISH_LBM + J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.AREA] = ( + scaler * 0.530 * gross_weight_exp * (taper_ratio + 0.50) / GRAV_ENGLISH_LBM + ) - J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.MASS_SCALER] = \ - 0.530 * area * gross_weight_exp * \ - (taper_ratio + 0.50) / GRAV_ENGLISH_LBM + J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.MASS_SCALER] = ( + 0.530 * area * gross_weight_exp * (taper_ratio + 0.50) / GRAV_ENGLISH_LBM + ) - J[Aircraft.HorizontalTail.MASS, Mission.Design.GROSS_MASS] = \ - scaler * 0.106 * area * gross_weight ** -0.8 * (taper_ratio + 0.50) + J[Aircraft.HorizontalTail.MASS, Mission.Design.GROSS_MASS] = ( + scaler * 0.106 * area * gross_weight**-0.8 * (taper_ratio + 0.50) + ) - J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.TAPER_RATIO] = \ + J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.TAPER_RATIO] = ( scaler * 0.530 * area * gross_weight_exp / GRAV_ENGLISH_LBM + ) class AltHorizontalTailMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the horizontal tail using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.HorizontalTail.AREA, val=0.0) - - add_aviary_input(self, Aircraft.HorizontalTail.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.HorizontalTail.MASS, val=0.0) + add_aviary_output(self, Aircraft.HorizontalTail.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): area = inputs[Aircraft.HorizontalTail.AREA] scaler = inputs[Aircraft.HorizontalTail.MASS_SCALER] - outputs[Aircraft.HorizontalTail.MASS] = scaler * \ - 5.4 * area / GRAV_ENGLISH_LBM + outputs[Aircraft.HorizontalTail.MASS] = scaler * 5.4 * area / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): area = inputs[Aircraft.HorizontalTail.AREA] diff --git a/aviary/subsystems/mass/flops_based/hydraulics.py b/aviary/subsystems/mass/flops_based/hydraulics.py index aed93313f2..cfa2427b21 100644 --- a/aviary/subsystems/mass/flops_based/hydraulics.py +++ b/aviary/subsystems/mass/flops_based/hydraulics.py @@ -1,10 +1,8 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.mass.flops_based.distributed_prop import \ - distributed_engine_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.subsystems.mass.flops_based.distributed_prop import distributed_engine_count_factor +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission # TODO: update non-transport components to new standard to remove these variables @@ -14,41 +12,34 @@ class TransportHydraulicsGroupMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the hydraulics group using the transport/general aviation method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. ASSUMPTIONS: all engines use hydraulics which follow this equation - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): - add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, val=0.0) + add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Hydraulics.SYSTEM_PRESSURE, units='psi') + add_aviary_input(self, Aircraft.Hydraulics.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, units='unitless') - add_aviary_input(self, Aircraft.Hydraulics.SYSTEM_PRESSURE, val=0.0) - - add_aviary_input(self, Aircraft.Hydraulics.MASS_SCALER, val=1.0) - - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) - - add_aviary_input(self, Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, val=0.0) - - add_aviary_output(self, Aircraft.Hydraulics.MASS, val=0.0) + add_aviary_output(self, Aircraft.Hydraulics.MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - num_wing_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) - num_fuse_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_wing_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] + num_fuse_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] num_wing_eng_fact = distributed_engine_count_factor(num_wing_eng) num_fuse_eng_fact = distributed_engine_count_factor(num_fuse_eng) @@ -57,20 +48,22 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): scaler = inputs[Aircraft.Hydraulics.MASS_SCALER] area = inputs[Aircraft.Wing.AREA] var_sweep = inputs[Aircraft.Wing.VAR_SWEEP_MASS_PENALTY] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] outputs[Aircraft.Hydraulics.MASS] = ( - 0.57 * (planform + 0.27 * area) + 0.57 + * (planform + 0.27 * area) * (1 + 0.03 * num_wing_eng_fact + 0.05 * num_fuse_eng_fact) - * (3000 / sys_press)**0.35 * (1 + 0.04 * var_sweep) * max_mach**0.33 - * scaler / GRAV_ENGLISH_LBM) + * (3000 / sys_press) ** 0.35 + * (1 + 0.04 * var_sweep) + * max_mach**0.33 + * scaler + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_wing_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) - num_fuse_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_wing_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] + num_fuse_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] num_wing_eng_fact = distributed_engine_count_factor(num_wing_eng) num_fuse_eng_fact = distributed_engine_count_factor(num_fuse_eng) @@ -79,55 +72,57 @@ def compute_partials(self, inputs, J): scaler = inputs[Aircraft.Hydraulics.MASS_SCALER] area = inputs[Aircraft.Wing.AREA] var_sweep = inputs[Aircraft.Wing.VAR_SWEEP_MASS_PENALTY] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] - term1 = (planform + 0.27 * area) - term2 = (1.0 + 0.03 * num_wing_eng_fact + 0.05 * num_fuse_eng_fact) - term3 = (3000.0 / sys_press)**0.35 - term4 = (1.0 + 0.04 * var_sweep) + term1 = planform + 0.27 * area + term2 = 1.0 + 0.03 * num_wing_eng_fact + 0.05 * num_fuse_eng_fact + term3 = (3000.0 / sys_press) ** 0.35 + term4 = 1.0 + 0.04 * var_sweep term5 = max_mach**0.33 J[Aircraft.Hydraulics.MASS, Aircraft.Fuselage.PLANFORM_AREA] = ( - 0.57 * term2 * term3 * term4 * term5 * scaler / GRAV_ENGLISH_LBM) + 0.57 * term2 * term3 * term4 * term5 * scaler / GRAV_ENGLISH_LBM + ) J[Aircraft.Hydraulics.MASS, Aircraft.Wing.AREA] = ( - 0.1539 * term2 * term3 * term4 * term5 * scaler / GRAV_ENGLISH_LBM) + 0.1539 * term2 * term3 * term4 * term5 * scaler / GRAV_ENGLISH_LBM + ) J[Aircraft.Hydraulics.MASS, Aircraft.Hydraulics.SYSTEM_PRESSURE] = ( - -3.2880267277063872637891549227565 * term1 * term2 - * sys_press**-1.35 * term4 * term5 * scaler / GRAV_ENGLISH_LBM) + -3.2880267277063872637891549227565 + * term1 + * term2 + * sys_press**-1.35 + * term4 + * term5 + * scaler + / GRAV_ENGLISH_LBM + ) J[Aircraft.Hydraulics.MASS, Aircraft.Wing.VAR_SWEEP_MASS_PENALTY] = ( - 0.0228 * term1 * term2 * term3 * term5 * scaler / GRAV_ENGLISH_LBM) + 0.0228 * term1 * term2 * term3 * term5 * scaler / GRAV_ENGLISH_LBM + ) J[Aircraft.Hydraulics.MASS, Aircraft.Hydraulics.MASS_SCALER] = ( - 0.57 * term1 * term2 * term3 * term4 * term5 / GRAV_ENGLISH_LBM) + 0.57 * term1 * term2 * term3 * term4 * term5 / GRAV_ENGLISH_LBM + ) class AltHydraulicsGroupMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the hydraulics group using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) - - add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, val=0.0) - - add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.0) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Hydraulics.MASS_SCALER, units='unitless') - add_aviary_input(self, Aircraft.VerticalTail.AREA, val=0.0) - - add_aviary_input(self, Aircraft.Hydraulics.MASS_SCALER, val=1.0) - - add_aviary_output(self, Aircraft.Hydraulics.MASS, val=0.0) + add_aviary_output(self, Aircraft.Hydraulics.MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') @@ -140,30 +135,32 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): scaler = inputs[Aircraft.Hydraulics.MASS_SCALER] outputs[Aircraft.Hydraulics.MASS] = ( - 0.6053 * (area + 1.44 * (horiz_wetted_area / - (2.0 + 0.387 * horiz_thick_chord) + vert_area)) * scaler / GRAV_ENGLISH_LBM + 0.6053 + * (area + 1.44 * (horiz_wetted_area / (2.0 + 0.387 * horiz_thick_chord) + vert_area)) + * scaler + / GRAV_ENGLISH_LBM ) def compute_partials(self, inputs, J): area = inputs[Aircraft.Wing.AREA] horiz_wetted_area = inputs[Aircraft.HorizontalTail.WETTED_AREA] horiz_thick_chord = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] - thick_chord_term = \ - 2.0 + 0.387 * inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] + thick_chord_term = 2.0 + 0.387 * inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] vert_area = inputs[Aircraft.VerticalTail.AREA] scaler = inputs[Aircraft.Hydraulics.MASS_SCALER] - J[Aircraft.Hydraulics.MASS, Aircraft.Wing.AREA] = ( - 0.6053 * scaler / GRAV_ENGLISH_LBM - ) + J[Aircraft.Hydraulics.MASS, Aircraft.Wing.AREA] = 0.6053 * scaler / GRAV_ENGLISH_LBM J[Aircraft.Hydraulics.MASS, Aircraft.HorizontalTail.WETTED_AREA] = ( 0.871632 / thick_chord_term * scaler / GRAV_ENGLISH_LBM ) J[Aircraft.Hydraulics.MASS, Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = ( - -0.337321584 * horiz_wetted_area / - (thick_chord_term * thick_chord_term) * scaler / GRAV_ENGLISH_LBM + -0.337321584 + * horiz_wetted_area + / (thick_chord_term * thick_chord_term) + * scaler + / GRAV_ENGLISH_LBM ) J[Aircraft.Hydraulics.MASS, Aircraft.VerticalTail.AREA] = ( @@ -171,6 +168,7 @@ def compute_partials(self, inputs, J): ) J[Aircraft.Hydraulics.MASS, Aircraft.Hydraulics.MASS_SCALER] = ( - 0.6053 * (area + 1.44 * (horiz_wetted_area / - (2.0 + 0.387 * horiz_thick_chord) + vert_area)) / GRAV_ENGLISH_LBM + 0.6053 + * (area + 1.44 * (horiz_wetted_area / (2.0 + 0.387 * horiz_thick_chord) + vert_area)) + / GRAV_ENGLISH_LBM ) diff --git a/aviary/subsystems/mass/flops_based/instruments.py b/aviary/subsystems/mass/flops_based/instruments.py index 3b0c50f841..874e46870d 100644 --- a/aviary/subsystems/mass/flops_based/instruments.py +++ b/aviary/subsystems/mass/flops_based/instruments.py @@ -1,72 +1,66 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.subsystems.mass.flops_based.distributed_prop import \ - distributed_engine_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.subsystems.mass.flops_based.distributed_prop import distributed_engine_count_factor +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class TransportInstrumentMass(om.ExplicitComponent): - ''' + """ Calculates mass of instrument group for transports and GA aircraft. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. ASSUMPTIONS: All engines have instrument mass that follows this equation - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.NUM_FLIGHT_CREW) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): - add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, 0.0) - add_aviary_input(self, Aircraft.Instruments.MASS_SCALER, 1.0) + add_aviary_input(self, Aircraft.Fuselage.PLANFORM_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Instruments.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Instruments.MASS, 0.0) + add_aviary_output(self, Aircraft.Instruments.MASS, units='lbm') - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - num_crew = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - num_wing_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) - num_fuse_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_crew = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + num_wing_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] + num_fuse_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] num_wing_eng_fact = distributed_engine_count_factor(num_wing_eng) num_fuse_eng_fact = distributed_engine_count_factor(num_fuse_eng) fuse_area = inputs[Aircraft.Fuselage.PLANFORM_AREA] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] mass_scaler = inputs[Aircraft.Instruments.MASS_SCALER] instrument_weight = ( - 0.48 * fuse_area**0.57 * max_mach**0.5 + 0.48 + * fuse_area**0.57 + * max_mach**0.5 * (10.0 + 2.5 * num_crew + num_wing_eng_fact + 1.5 * num_fuse_eng_fact) ) - outputs[Aircraft.Instruments.MASS] = instrument_weight * \ - mass_scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.Instruments.MASS] = instrument_weight * mass_scaler / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_crew = aviary_options.get_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW) - num_wing_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) - num_fuse_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES) + num_crew = self.options[Aircraft.CrewPayload.NUM_FLIGHT_CREW] + num_wing_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] + num_fuse_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES] num_wing_eng_fact = distributed_engine_count_factor(num_wing_eng) num_fuse_eng_fact = distributed_engine_count_factor(num_fuse_eng) fuse_area = inputs[Aircraft.Fuselage.PLANFORM_AREA] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] mass_scaler = inputs[Aircraft.Instruments.MASS_SCALER] - fact = (10.0 + 2.5 * num_crew + num_wing_eng_fact + 1.5 * num_fuse_eng_fact) + fact = 10.0 + 2.5 * num_crew + num_wing_eng_fact + 1.5 * num_fuse_eng_fact area_fact = fuse_area**0.57 mach_fact = max_mach**0.5 diff --git a/aviary/subsystems/mass/flops_based/landing_gear.py b/aviary/subsystems/mass/flops_based/landing_gear.py index db87a4aeec..055cfd9edb 100644 --- a/aviary/subsystems/mass/flops_based/landing_gear.py +++ b/aviary/subsystems/mass/flops_based/landing_gear.py @@ -3,41 +3,33 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.subsystems.mass.flops_based.distributed_prop import ( - distributed_nacelle_diam_factor, distributed_nacelle_diam_factor_deriv) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output + distributed_nacelle_diam_factor, + distributed_nacelle_diam_factor_deriv, +) +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission DEG2RAD = np.pi / 180.0 class LandingGearMass(om.ExplicitComponent): - ''' + """ Calculate the mass of the landing gear. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ + # TODO: add in aircraft type and carrier factors as options and modify # equations - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, val=0.0) - - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, units='inch') + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, units='inch') + add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Design.TOUCHDOWN_MASS, units='lbm') - add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, val=0.0) - - add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, val=1.0) - - add_aviary_input(self, Aircraft.Design.TOUCHDOWN_MASS, val=0.0) - - add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_MASS, val=0.0) - - add_aviary_output(self, Aircraft.LandingGear.NOSE_GEAR_MASS, val=0.0) + add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_MASS, units='lbm') + add_aviary_output(self, Aircraft.LandingGear.NOSE_GEAR_MASS, units='lbm') # TODO landing weight is not a landing_gear component level variable # self.add_input('aircraft:landing_gear:weights:landing_weight', val=0.0, desc='design landing weight', units='lbf') @@ -59,29 +51,39 @@ def setup_partials(self): [ Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, - Aircraft.Design.TOUCHDOWN_MASS]) + Aircraft.Design.TOUCHDOWN_MASS, + ], + ) self.declare_partials( Aircraft.LandingGear.NOSE_GEAR_MASS, [ Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, - Aircraft.Design.TOUCHDOWN_MASS]) + Aircraft.Design.TOUCHDOWN_MASS, + ], + ) def compute(self, inputs, outputs): - main_gear_length = inputs[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] main_gear_scaler = inputs[Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER] nose_gear_length = inputs[Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] nose_gear_scaler = inputs[Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER] - landing_weight = inputs[Aircraft.Design.TOUCHDOWN_MASS] * \ - GRAV_ENGLISH_LBM - - outputs[Aircraft.LandingGear.MAIN_GEAR_MASS] = 0.0117 * \ - landing_weight**0.95 * main_gear_length**0.43 * \ - main_gear_scaler / GRAV_ENGLISH_LBM - outputs[Aircraft.LandingGear.NOSE_GEAR_MASS] = 0.048 * \ - landing_weight**0.67 * nose_gear_length**0.43 * \ - nose_gear_scaler / GRAV_ENGLISH_LBM + landing_weight = inputs[Aircraft.Design.TOUCHDOWN_MASS] * GRAV_ENGLISH_LBM + + outputs[Aircraft.LandingGear.MAIN_GEAR_MASS] = ( + 0.0117 + * landing_weight**0.95 + * main_gear_length**0.43 + * main_gear_scaler + / GRAV_ENGLISH_LBM + ) + outputs[Aircraft.LandingGear.NOSE_GEAR_MASS] = ( + 0.048 + * landing_weight**0.67 + * nose_gear_length**0.43 + * nose_gear_scaler + / GRAV_ENGLISH_LBM + ) # main_gear_weight = (0.0117 - 0.0012 * type_factor) * landing_weight**0.95 * main_gear_length**0.43 # outputs['TBD:landing_gear:weights:main_landing_gear_weight'] = main_gear_weight * inputs['TBD:aircraft:landing_gear:main_landing_gear_weight_multipler'] @@ -93,81 +95,77 @@ def compute_partials(self, inputs, J): main_gear_scaler = inputs[Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER] nose_gear_length = inputs[Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] nose_gear_scaler = inputs[Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER] - landing_weight = \ - inputs[Aircraft.Design.TOUCHDOWN_MASS] * GRAV_ENGLISH_LBM + landing_weight = inputs[Aircraft.Design.TOUCHDOWN_MASS] * GRAV_ENGLISH_LBM landing_weight_exp1 = landing_weight**0.95 landing_weight_exp2 = landing_weight**0.67 main_gear_length_exp = main_gear_length**0.43 nose_gear_length_exp = nose_gear_length**0.43 - J[ - Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] = 0.005031 * \ - landing_weight_exp1 * main_gear_length**-0.57 * \ - main_gear_scaler / GRAV_ENGLISH_LBM - J[ - Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER] = 0.0117 * \ - landing_weight_exp1 * main_gear_length_exp / GRAV_ENGLISH_LBM - J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.Design.TOUCHDOWN_MASS] = \ - 0.011115 * \ - landing_weight**-0.05 * main_gear_length_exp * main_gear_scaler + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] = ( + 0.005031 + * landing_weight_exp1 + * main_gear_length**-0.57 + * main_gear_scaler + / GRAV_ENGLISH_LBM + ) + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER] = ( + 0.0117 * landing_weight_exp1 * main_gear_length_exp / GRAV_ENGLISH_LBM + ) + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.Design.TOUCHDOWN_MASS] = ( + 0.011115 * landing_weight**-0.05 * main_gear_length_exp * main_gear_scaler + ) - J[ - Aircraft.LandingGear.NOSE_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = 0.02064 * \ - landing_weight_exp2 * nose_gear_length**-0.57 * \ - nose_gear_scaler / GRAV_ENGLISH_LBM - J[ - Aircraft.LandingGear.NOSE_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER] = 0.048 * \ - landing_weight_exp2 * nose_gear_length_exp / GRAV_ENGLISH_LBM - J[Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.Design.TOUCHDOWN_MASS] = \ - 0.03216 * \ - landing_weight**-0.33 * nose_gear_length_exp * \ - nose_gear_scaler + J[Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = ( + 0.02064 + * landing_weight_exp2 + * nose_gear_length**-0.57 + * nose_gear_scaler + / GRAV_ENGLISH_LBM + ) + J[Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER] = ( + 0.048 * landing_weight_exp2 * nose_gear_length_exp / GRAV_ENGLISH_LBM + ) + J[Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.Design.TOUCHDOWN_MASS] = ( + 0.03216 * landing_weight**-0.33 * nose_gear_length_exp * nose_gear_scaler + ) class AltLandingGearMass(om.ExplicitComponent): - ''' + """ Calculate the mass of the landing gear using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, val=0.0) - - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, val=1.0) - - add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, val=0.0) + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, units='inch') + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, units='inch') + add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') - add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, val=1.0) - - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - - add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_MASS, val=0.0) - - add_aviary_output(self, Aircraft.LandingGear.NOSE_GEAR_MASS, val=0.0) + add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_MASS, units='lbm') + add_aviary_output(self, Aircraft.LandingGear.NOSE_GEAR_MASS, units='lbm') def setup_partials(self): - self.declare_partials(Aircraft.LandingGear.MAIN_GEAR_MASS, [ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, - Mission.Design.GROSS_MASS] + self.declare_partials( + Aircraft.LandingGear.MAIN_GEAR_MASS, + [ + Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, + Mission.Design.GROSS_MASS, + ], ) - self.declare_partials(Aircraft.LandingGear.NOSE_GEAR_MASS, [ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, - Mission.Design.GROSS_MASS] + self.declare_partials( + Aircraft.LandingGear.NOSE_GEAR_MASS, + [ + Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, + Mission.Design.GROSS_MASS, + ], ) def compute(self, inputs, outputs): @@ -178,16 +176,20 @@ def compute(self, inputs, outputs): gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM total_gear_weight = gross_weight * ( - (30100.0 + - 0.3876 * main_gear_length * main_gear_length + - 0.09579 * nose_gear_length * nose_gear_length - ) / 1.0e6 + ( + 30100.0 + + 0.3876 * main_gear_length * main_gear_length + + 0.09579 * nose_gear_length * nose_gear_length + ) + / 1.0e6 ) - outputs[Aircraft.LandingGear.MAIN_GEAR_MASS] = 0.85 * \ - total_gear_weight * main_gear_scaler / GRAV_ENGLISH_LBM - outputs[Aircraft.LandingGear.NOSE_GEAR_MASS] = 0.15 * \ - total_gear_weight * nose_gear_scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.LandingGear.MAIN_GEAR_MASS] = ( + 0.85 * total_gear_weight * main_gear_scaler / GRAV_ENGLISH_LBM + ) + outputs[Aircraft.LandingGear.NOSE_GEAR_MASS] = ( + 0.15 * total_gear_weight * nose_gear_scaler / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): main_gear_length = inputs[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] @@ -196,29 +198,24 @@ def compute_partials(self, inputs, J): nose_gear_scaler = inputs[Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - total_gear_fact = (30100.0 + - 0.3876 * main_gear_length * main_gear_length + - 0.09579 * nose_gear_length * nose_gear_length - ) / 1.0e6 + total_gear_fact = ( + 30100.0 + + 0.3876 * main_gear_length * main_gear_length + + 0.09579 * nose_gear_length * nose_gear_length + ) / 1.0e6 total_gear_weight = gross_weight * total_gear_fact total_gear_weight_dmain = gross_weight * 7.752e-7 * main_gear_length total_gear_weight_dnose = gross_weight * 1.9158e-7 * nose_gear_length - J[ - Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] = ( + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] = ( 0.85 * total_gear_weight_dmain * main_gear_scaler / GRAV_ENGLISH_LBM ) - J[ - Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = ( + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = ( 0.85 * total_gear_weight_dnose * main_gear_scaler / GRAV_ENGLISH_LBM ) - J[ - Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER] = ( + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER] = ( 0.85 * total_gear_weight / GRAV_ENGLISH_LBM ) @@ -226,21 +223,15 @@ def compute_partials(self, inputs, J): 0.85 * total_gear_fact * main_gear_scaler ) - J[ - Aircraft.LandingGear.NOSE_GEAR_MASS, - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] = ( + J[Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] = ( 0.15 * total_gear_weight_dmain * nose_gear_scaler / GRAV_ENGLISH_LBM ) - J[ - Aircraft.LandingGear.NOSE_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = ( + J[Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = ( 0.15 * total_gear_weight_dnose * nose_gear_scaler / GRAV_ENGLISH_LBM ) - J[ - Aircraft.LandingGear.NOSE_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER] = ( + J[Aircraft.LandingGear.NOSE_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER] = ( 0.15 * total_gear_weight / GRAV_ENGLISH_LBM ) @@ -252,70 +243,74 @@ def compute_partials(self, inputs, J): class NoseGearLength(om.ExplicitComponent): """ Computation of nose gear oleo strut length from main gear oleo strut length: - NOSE_GEAR_OLEO_LENGTH = 0.7 * MAIN_GEAR_OLEO_LENGTH + NOSE_GEAR_OLEO_LENGTH = 0.7 * MAIN_GEAR_OLEO_LENGTH. """ - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, val=0.0) - add_aviary_output(self, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, val=0.0) + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, units='inch') + add_aviary_output(self, Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, units='inch') def setup_partials(self): - self.declare_partials(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - val=0.7) + self.declare_partials( + Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, + val=0.7, + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - outputs[Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = 0.7 * \ - inputs[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] + outputs[Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH] = ( + 0.7 * inputs[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] + ) class MainGearLength(om.ExplicitComponent): """ Computation of main gear length. + + TODO does not support more than two wing engines, or more than one engine model """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Engine.NUM_WING_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - num_wing_engines = self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_WING_ENGINES) - - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=0.0) - add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, val=0.0) - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, - val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Engine.WING_LOCATIONS, - val=np.zeros((num_engine_type, int(num_wing_engines[0]/2)))) - add_aviary_input(self, Aircraft.Wing.DIHEDRAL, val=0.0) - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) - - add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, val=0.0) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + num_wing_engines_total = sum(self.options[Aircraft.Engine.NUM_WING_ENGINES]) + + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.MAX_WIDTH, units='ft') + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + if num_wing_engines_total > 1: + add_aviary_input( + self, + Aircraft.Engine.WING_LOCATIONS, + shape=int(num_wing_engines_total / 2), + units='unitless', + ) + else: # this case is not tested + add_aviary_input(self, Aircraft.Engine.WING_LOCATIONS, units='unitless') + + add_aviary_input(self, Aircraft.Wing.DIHEDRAL, units='deg') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + + add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, units='inch') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - options: AviaryValues = self.options['aviary_options'] - # TODO temp using first engine, heterogeneous engines not supported - num_eng = options.get_val(Aircraft.Engine.NUM_ENGINES)[0] - num_wing_eng = options.get_val(Aircraft.Engine.NUM_WING_ENGINES)[0] + num_eng = self.options[Aircraft.Engine.NUM_ENGINES][0] - y_eng_fore = inputs[Aircraft.Engine.WING_LOCATIONS][0][0] + # TODO temp using first engine, heterogeneous engines not supported + num_wing_eng = self.options[Aircraft.Engine.NUM_WING_ENGINES][0] - # TODO: high engine-count configuation. + # TODO: high engine-count configuration. y_eng_aft = 0 if num_wing_eng > 0: + y_eng_fore = inputs[Aircraft.Engine.WING_LOCATIONS][0] + tan_dih = np.tan(inputs[Aircraft.Wing.DIHEDRAL] * DEG2RAD) fuse_half_width = inputs[Aircraft.Fuselage.MAX_WIDTH] * 6.0 @@ -345,15 +340,15 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): outputs[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH] = cmlg def compute_partials(self, inputs, partials, discrete_inputs=None): - options: AviaryValues = self.options['aviary_options'] # TODO temp using first engine, heterogeneous engines not supported - num_eng = options.get_val(Aircraft.Engine.NUM_ENGINES)[0] - num_wing_eng = options.get_val(Aircraft.Engine.NUM_WING_ENGINES)[0] + num_eng = self.options[Aircraft.Engine.NUM_ENGINES][0] + num_wing_eng = self.options[Aircraft.Engine.NUM_WING_ENGINES][0] - y_eng_fore = inputs[Aircraft.Engine.WING_LOCATIONS][0][0] y_eng_aft = 0 if num_wing_eng > 0: + y_eng_fore = inputs[Aircraft.Engine.WING_LOCATIONS][0] + tan_dih = np.tan(inputs[Aircraft.Wing.DIHEDRAL] * DEG2RAD) dtan_dih = DEG2RAD / np.cos(inputs[Aircraft.Wing.DIHEDRAL] * DEG2RAD) ** 2 @@ -385,56 +380,48 @@ def compute_partials(self, inputs, partials, discrete_inputs=None): cmlg = 12.0 * f_nacelle + (0.26 - tan_dih) * (yee - fuse_half_width) dcmlg_dnac = 12.0 * d_nac dcmlg_dtan = -(yee - fuse_half_width) - dcmlg_dyee = (0.26 - tan_dih) - dcmlg_dhw = (tan_dih - 0.26) + dcmlg_dyee = 0.26 - tan_dih + dcmlg_dhw = tan_dih - 0.26 else: cmlg = 0.0 if cmlg < 12.0: - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Fuselage.LENGTH] = 0.75 + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Fuselage.LENGTH] = 0.75 - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Fuselage.MAX_WIDTH] = 0.0 + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Fuselage.MAX_WIDTH] = 0.0 - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Nacelle.AVG_DIAMETER] = 0.0 + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Nacelle.AVG_DIAMETER] = ( + 0.0 + ) - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Engine.WING_LOCATIONS] = 0.0 + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Engine.WING_LOCATIONS] = ( + 0.0 + ) - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Wing.DIHEDRAL] = 0.0 + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Wing.DIHEDRAL] = 0.0 - partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Wing.SPAN] = \ - 0.0 + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Wing.SPAN] = 0.0 else: - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Fuselage.LENGTH] = \ - 0.0 + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Fuselage.LENGTH] = 0.0 - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Fuselage.MAX_WIDTH] = dcmlg_dhw * dhw_dfuse_wid + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Fuselage.MAX_WIDTH] = ( + dcmlg_dhw * dhw_dfuse_wid + ) - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Nacelle.AVG_DIAMETER][:] = dcmlg_dnac + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Nacelle.AVG_DIAMETER][ + : + ] = dcmlg_dnac - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Engine.WING_LOCATIONS] = dcmlg_dyee * dyee_dwel + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Engine.WING_LOCATIONS] = ( + dcmlg_dyee * dyee_dwel + ) - partials[ - Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.Wing.DIHEDRAL] = dcmlg_dtan * dtan_dih + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Wing.DIHEDRAL] = ( + dcmlg_dtan * dtan_dih + ) - partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Wing.SPAN] = \ + partials[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, Aircraft.Wing.SPAN] = ( dcmlg_dyee * dyee_dspan + ) diff --git a/aviary/subsystems/mass/flops_based/landing_group.py b/aviary/subsystems/mass/flops_based/landing_group.py index 13978daf8c..21601867d3 100644 --- a/aviary/subsystems/mass/flops_based/landing_group.py +++ b/aviary/subsystems/mass/flops_based/landing_group.py @@ -1,10 +1,13 @@ import openmdao.api as om from aviary.subsystems.mass.flops_based.landing_gear import ( - AltLandingGearMass, LandingGearMass, MainGearLength, NoseGearLength) -from aviary.subsystems.mass.flops_based.landing_mass import ( - LandingMass, LandingTakeoffMassRatio) -from aviary.utils.aviary_values import AviaryValues + AltLandingGearMass, + LandingGearMass, + MainGearLength, + NoseGearLength, +) +from aviary.subsystems.mass.flops_based.landing_mass import LandingMass, LandingTakeoffMassRatio +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft @@ -15,35 +18,41 @@ class LandingMassGroup(om.Group): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Design.USE_ALT_MASS) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] - alt_mass = aviary_options.get_val(Aircraft.Design.USE_ALT_MASS) - - self.add_subsystem('landing_to_takeoff_mass_ratio', - LandingTakeoffMassRatio(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) - - self.add_subsystem('main_landing_gear_length', - MainGearLength(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) - - self.add_subsystem('nose_landing_gear_length', - NoseGearLength(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) - - self.add_subsystem('landing_mass', - LandingMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + alt_mass = self.options[Aircraft.Design.USE_ALT_MASS] + + self.add_subsystem( + 'landing_to_takeoff_mass_ratio', + LandingTakeoffMassRatio(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'main_landing_gear_length', + MainGearLength(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'nose_landing_gear_length', + NoseGearLength(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'landing_mass', LandingMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) if alt_mass: - self.add_subsystem('landing_gear', - AltLandingGearMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'landing_gear', AltLandingGearMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) else: - self.add_subsystem('landing_gear', - LandingGearMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'landing_gear', LandingGearMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) diff --git a/aviary/subsystems/mass/flops_based/landing_mass.py b/aviary/subsystems/mass/flops_based/landing_mass.py index c34686fbec..84f3b1b6d5 100644 --- a/aviary/subsystems/mass/flops_based/landing_mass.py +++ b/aviary/subsystems/mass/flops_based/landing_mass.py @@ -1,27 +1,18 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class LandingTakeoffMassRatio(om.ExplicitComponent): - ''' - Calculate the ratio of maximum landing mass to maximum takeoff gross mass. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """Calculate the ratio of maximum landing mass to maximum takeoff gross mass.""" def setup(self): - add_aviary_input(self, Mission.Summary.CRUISE_MACH, val=0.0) - - add_aviary_input(self, Mission.Design.RANGE, val=0.0) + add_aviary_input(self, Mission.Summary.CRUISE_MACH, units='unitless') + add_aviary_input(self, Mission.Design.RANGE, units='NM') - add_aviary_output(self, Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, val=0.0) + add_aviary_output(self, Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, units='unitless') def setup_partials(self): self.declare_partials('*', '*') @@ -33,62 +24,48 @@ def compute(self, inputs, outputs): # cruise factor set by the cruise Mach number # (If statement replaced with expression to give continuous derivatives around # Mach=1.0) - cruise_factor = 5e-5 / (1. + np.exp(-1000 * (cruise_mach - 1))) + 4e-5 + cruise_factor = 5e-5 / (1.0 + np.exp(-1000 * (cruise_mach - 1))) + 4e-5 - outputs[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] = 1 - \ - cruise_factor * des_range + outputs[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] = 1 - cruise_factor * des_range def compute_partials(self, inputs, J): cruise_mach = inputs[Mission.Summary.CRUISE_MACH] des_range = inputs[Mission.Design.RANGE] - den = (1. + np.exp(-1000 * (cruise_mach - 1))) + den = 1.0 + np.exp(-1000 * (cruise_mach - 1)) cruise_factor = 5e-5 / den + 4e-5 - dfact_dmach = 5e-2 / den ** 2 * np.exp(-1000 * (cruise_mach - 1)) + dfact_dmach = 5e-2 / den**2 * np.exp(-1000 * (cruise_mach - 1)) - J[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, Mission.Design.RANGE] = \ - -cruise_factor - J[ - Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, - Mission.Summary.CRUISE_MACH] = -des_range * dfact_dmach + J[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, Mission.Design.RANGE] = -cruise_factor + J[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, Mission.Summary.CRUISE_MACH] = ( + -des_range * dfact_dmach + ) class LandingMass(om.ExplicitComponent): - ''' - Maximum landing mass is maximum takeoff gross mass times the ratio of landing/takeoff mass. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """Maximum landing mass is maximum takeoff gross mass times the ratio of landing/takeoff mass.""" def setup(self): - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - - add_aviary_input(self, Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, val=0.0) + add_aviary_input(self, Mission.Design.GROSS_MASS) + add_aviary_input(self, Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO) - add_aviary_output(self, Aircraft.Design.TOUCHDOWN_MASS, val=0.0) + add_aviary_output(self, Aircraft.Design.TOUCHDOWN_MASS) def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs): gross_mass = inputs[Mission.Design.GROSS_MASS] - landing_to_takeoff_mass_ratio = \ - inputs[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] + landing_to_takeoff_mass_ratio = inputs[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] - outputs[Aircraft.Design.TOUCHDOWN_MASS] = gross_mass * \ - landing_to_takeoff_mass_ratio + outputs[Aircraft.Design.TOUCHDOWN_MASS] = gross_mass * landing_to_takeoff_mass_ratio def compute_partials(self, inputs, J): gross_mass = inputs[Mission.Design.GROSS_MASS] - landing_to_takeoff_mass_ratio = \ - inputs[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] + landing_to_takeoff_mass_ratio = inputs[Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] - J[Aircraft.Design.TOUCHDOWN_MASS, Mission.Design.GROSS_MASS] = \ - landing_to_takeoff_mass_ratio + J[Aircraft.Design.TOUCHDOWN_MASS, Mission.Design.GROSS_MASS] = landing_to_takeoff_mass_ratio - J[ - Aircraft.Design.TOUCHDOWN_MASS, - Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] = gross_mass + J[Aircraft.Design.TOUCHDOWN_MASS, Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO] = ( + gross_mass + ) diff --git a/aviary/subsystems/mass/flops_based/mass_premission.py b/aviary/subsystems/mass/flops_based/mass_premission.py index b60b2ebd37..0bf6ba2a8e 100644 --- a/aviary/subsystems/mass/flops_based/mass_premission.py +++ b/aviary/subsystems/mass/flops_based/mass_premission.py @@ -1,33 +1,37 @@ import openmdao.api as om -from aviary.subsystems.mass.flops_based.air_conditioning import ( - AltAirCondMass, TransportAirCondMass) +from aviary.subsystems.mass.flops_based.air_conditioning import AltAirCondMass, TransportAirCondMass from aviary.subsystems.mass.flops_based.anti_icing import AntiIcingMass from aviary.subsystems.mass.flops_based.apu import TransportAPUMass from aviary.subsystems.mass.flops_based.avionics import TransportAvionicsMass from aviary.subsystems.mass.flops_based.canard import CanardMass -from aviary.subsystems.mass.flops_based.cargo import CargoMass +from aviary.subsystems.mass.flops_based.cargo import PayloadGroup from aviary.subsystems.mass.flops_based.cargo_containers import TransportCargoContainersMass -from aviary.subsystems.mass.flops_based.crew import NonFlightCrewMass, FlightCrewMass -from aviary.subsystems.mass.flops_based.electrical import ( - AltElectricalMass, ElectricalMass) +from aviary.subsystems.mass.flops_based.crew import FlightCrewMass, NonFlightCrewMass +from aviary.subsystems.mass.flops_based.electrical import AltElectricalMass, ElectricalMass from aviary.subsystems.mass.flops_based.engine import EngineMass from aviary.subsystems.mass.flops_based.engine_controls import TransportEngineCtrlsMass -from aviary.subsystems.mass.flops_based.engine_oil import ( - TransportEngineOilMass, AltEngineOilMass) +from aviary.subsystems.mass.flops_based.engine_oil import AltEngineOilMass, TransportEngineOilMass from aviary.subsystems.mass.flops_based.fin import FinMass from aviary.subsystems.mass.flops_based.fuel_capacity import FuelCapacityGroup from aviary.subsystems.mass.flops_based.fuel_system import ( - AltFuelSystemMass, TransportFuelSystemMass) + AltFuelSystemMass, + TransportFuelSystemMass, +) from aviary.subsystems.mass.flops_based.furnishings import ( - AltFurnishingsGroupMass, AltFurnishingsGroupMassBase, - TransportFurnishingsGroupMass) -from aviary.subsystems.mass.flops_based.fuselage import ( - AltFuselageMass, TransportFuselageMass) + AltFurnishingsGroupMass, + AltFurnishingsGroupMassBase, + TransportFurnishingsGroupMass, +) +from aviary.subsystems.mass.flops_based.fuselage import AltFuselageMass, TransportFuselageMass from aviary.subsystems.mass.flops_based.horizontal_tail import ( - AltHorizontalTailMass, HorizontalTailMass) + AltHorizontalTailMass, + HorizontalTailMass, +) from aviary.subsystems.mass.flops_based.hydraulics import ( - AltHydraulicsGroupMass, TransportHydraulicsGroupMass) + AltHydraulicsGroupMass, + TransportHydraulicsGroupMass, +) from aviary.subsystems.mass.flops_based.instruments import TransportInstrumentMass from aviary.subsystems.mass.flops_based.landing_group import LandingMassGroup from aviary.subsystems.mass.flops_based.mass_summation import MassSummation @@ -35,271 +39,299 @@ from aviary.subsystems.mass.flops_based.nacelle import NacelleMass from aviary.subsystems.mass.flops_based.paint import PaintMass from aviary.subsystems.mass.flops_based.passenger_service import ( - AltPassengerServiceMass, PassengerServiceMass) + AltPassengerServiceMass, + PassengerServiceMass, +) from aviary.subsystems.mass.flops_based.starter import TransportStarterMass from aviary.subsystems.mass.flops_based.surface_controls import ( - AltSurfaceControlMass, SurfaceControlMass) + AltSurfaceControlMass, + SurfaceControlMass, +) from aviary.subsystems.mass.flops_based.thrust_reverser import ThrustReverserMass from aviary.subsystems.mass.flops_based.unusable_fuel import ( - AltUnusableFuelMass, TransportUnusableFuelMass) -from aviary.subsystems.mass.flops_based.vertical_tail import ( - AltVerticalTailMass, VerticalTailMass) + AltUnusableFuelMass, + TransportUnusableFuelMass, +) +from aviary.subsystems.mass.flops_based.vertical_tail import AltVerticalTailMass, VerticalTailMass from aviary.subsystems.mass.flops_based.wing_group import WingMassGroup -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.functions import add_aviary_option +from aviary.variable_info.variables import Aircraft class MassPremission(om.Group): """ Pre-mission group of top-level mass estimation groups and components for FLOPS-based analysis: - CargoMass, TransportCargoContainersMass, TransportEngineCtrlsMass, TransportAvionicsMass, + PayloadGroup, TransportCargoContainersMass, TransportEngineCtrlsMass, TransportAvionicsMass, FuelCapacityGroup, EngineMass, etc. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Design.USE_ALT_MASS) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] - alt_mass = aviary_options.get_val(Aircraft.Design.USE_ALT_MASS) + alt_mass = self.options[Aircraft.Design.USE_ALT_MASS] - self.add_subsystem( - 'cargo', - CargoMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('cargo', PayloadGroup(), promotes_inputs=['*'], promotes_outputs=['*']) self.add_subsystem( 'cargo_containers', - TransportCargoContainersMass( - aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + TransportCargoContainersMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( 'engine_controls', - TransportEngineCtrlsMass(aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + TransportEngineCtrlsMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( - 'avionics', - TransportAvionicsMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'avionics', TransportAvionicsMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( 'fuel_capacity_group', - FuelCapacityGroup(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + FuelCapacityGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - 'engine_mass', - EngineMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'engine_mass', EngineMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) if alt_mass: self.add_subsystem( 'fuel_system', - AltFuelSystemMass(aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + AltFuelSystemMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( - 'AC', - AltAirCondMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'AC', AltAirCondMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'engine_oil', - AltEngineOilMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'engine_oil', AltEngineOilMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( 'furnishing_base', - AltFurnishingsGroupMassBase( - aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + AltFurnishingsGroupMassBase(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'furnishings', - AltFurnishingsGroupMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + AltFurnishingsGroupMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'hydraulics', - AltHydraulicsGroupMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + AltHydraulicsGroupMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'pass_service', - AltPassengerServiceMass( - aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + AltPassengerServiceMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'unusable_fuel', - AltUnusableFuelMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + AltUnusableFuelMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - 'electrical', - AltElectricalMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'electrical', AltElectricalMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) else: self.add_subsystem( 'fuel_system', - TransportFuelSystemMass(aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + TransportFuelSystemMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( - 'AC', - TransportAirCondMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'AC', TransportAirCondMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( 'engine_oil', - TransportEngineOilMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + TransportEngineOilMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'furnishings', - TransportFurnishingsGroupMass( - aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + TransportFurnishingsGroupMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'hydraulics', - TransportHydraulicsGroupMass( - aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + TransportHydraulicsGroupMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'pass_service', - PassengerServiceMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + PassengerServiceMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'unusable_fuel', - TransportUnusableFuelMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + TransportUnusableFuelMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - 'electrical', - ElectricalMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'electrical', ElectricalMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'starter', - TransportStarterMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'starter', TransportStarterMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'anti_icing', - AntiIcingMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'anti_icing', AntiIcingMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) - self.add_subsystem( - 'apu', - TransportAPUMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('apu', TransportAPUMass(), promotes_inputs=['*'], promotes_outputs=['*']) self.add_subsystem( - 'nonflight_crew', - NonFlightCrewMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'nonflight_crew', NonFlightCrewMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'flight_crew', - FlightCrewMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'flight_crew', FlightCrewMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'instruments', - TransportInstrumentMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'instruments', TransportInstrumentMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'misc_engine', - EngineMiscMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'misc_engine', EngineMiscMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) - self.add_subsystem( - 'nacelle', - NacelleMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('nacelle', NacelleMass(), promotes_inputs=['*'], promotes_outputs=['*']) - self.add_subsystem( - 'paint', - PaintMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('paint', PaintMass(), promotes_inputs=['*'], promotes_outputs=['*']) self.add_subsystem( - 'thrust_rev', - ThrustReverserMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'thrust_rev', ThrustReverserMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'landing_group', - LandingMassGroup(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'landing_group', LandingMassGroup(), promotes_inputs=['*'], promotes_outputs=['*'] + ) if alt_mass: self.add_subsystem( - 'surf_ctrl', - AltSurfaceControlMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'surf_ctrl', AltSurfaceControlMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( 'fuselage', - AltFuselageMass(aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + AltFuselageMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( 'htail', - AltHorizontalTailMass(aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + AltHorizontalTailMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( - 'vert_tail', - AltVerticalTailMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'vert_tail', AltVerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) else: self.add_subsystem( - 'surf_ctrl', - SurfaceControlMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'surf_ctrl', SurfaceControlMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( 'fuselage', - TransportFuselageMass(aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + TransportFuselageMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( 'htail', - HorizontalTailMass(aviary_options=aviary_options), - promotes_inputs=['*', ], promotes_outputs=['*', ]) + HorizontalTailMass(), + promotes_inputs=[ + '*', + ], + promotes_outputs=[ + '*', + ], + ) self.add_subsystem( - 'vert_tail', - VerticalTailMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'vert_tail', VerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) - self.add_subsystem( - 'canard', - CanardMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('canard', CanardMass(), promotes_inputs=['*'], promotes_outputs=['*']) - self.add_subsystem( - 'fin', - FinMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('fin', FinMass(), promotes_inputs=['*'], promotes_outputs=['*']) self.add_subsystem( - 'wing_group', - WingMassGroup(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'wing_group', WingMassGroup(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'total_mass', - MassSummation(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'total_mass', MassSummation(), promotes_inputs=['*'], promotes_outputs=['*'] + ) diff --git a/aviary/subsystems/mass/flops_based/mass_summation.py b/aviary/subsystems/mass/flops_based/mass_summation.py index d1294985eb..7cd8919149 100644 --- a/aviary/subsystems/mass/flops_based/mass_summation.py +++ b/aviary/subsystems/mass/flops_based/mass_summation.py @@ -1,112 +1,110 @@ import numpy as np - import openmdao.api as om from aviary.subsystems.mass.flops_based.empty_margin import EmptyMassMargin -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class MassSummation(om.Group): """ Group to compute various design masses for FLOPS-based mass: - Aircraft.Design.STRUCTURE_MASS, Aircraft.Propulsion.MASS, + Aircraft.Design.STRUCTURE_MASS, Aircraft.Propulsion.MASS, Aircraft.Design.SYSTEMS_EQUIP_MASS, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, Aircraft.Design.SYSTEMS_EQUIP_MASS, Aircraft.Design.EMPTY_MASS, - Aircraft.Design.OPERATING_MASS, Aircraft.Design.ZERO_FUEL_MASS, - Mission.Design.FUEL_MASS. + Mission.Summary.OPERATING_MASS, Mission.Summary.ZERO_FUEL_MASS, + Mission.Summary.FUEL_MASS. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Design.USE_ALT_MASS) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] - alt_mass = aviary_options.get_val(Aircraft.Design.USE_ALT_MASS) + alt_mass = self.options[Aircraft.Design.USE_ALT_MASS] self.add_subsystem( - 'structure_mass', StructureMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'structure_mass', StructureMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'propulsion_mass', PropulsionMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'propulsion_mass', PropulsionMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) if alt_mass: self.add_subsystem( 'system_equip_mass_base', - AltSystemsEquipMassBase(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + AltSystemsEquipMassBase(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( 'system_equip_mass', - AltSystemsEquipMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + AltSystemsEquipMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) else: self.add_subsystem( - 'system_equip_mass', SystemsEquipMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'system_equip_mass', + SystemsEquipMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - 'empty_mass_margin', EmptyMassMargin(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'empty_mass_margin', EmptyMassMargin(), promotes_inputs=['*'], promotes_outputs=['*'] + ) if alt_mass: self.add_subsystem( - 'empty_mass', AltEmptyMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'empty_mass', AltEmptyMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) else: - self.add_subsystem('empty_mass', EmptyMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'empty_mass', EmptyMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'operating_mass', OperatingMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'operating_mass', OperatingMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) self.add_subsystem( - 'zero_fuel_mass', ZeroFuelMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + 'zero_fuel_mass', ZeroFuelMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) - self.add_subsystem('fuel_mass', FuelMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem('fuel_mass', FuelMass(), promotes_inputs=['*'], promotes_outputs=['*']) class StructureMass(om.ExplicitComponent): - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - - add_aviary_input(self, Aircraft.Canard.MASS, val=0.0) - add_aviary_input(self, Aircraft.Fins.MASS, val=0.0) - add_aviary_input(self, Aircraft.Fuselage.MASS, val=0.0) - add_aviary_input(self, Aircraft.HorizontalTail.MASS, val=0.0) - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS, val=0.0) - add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_MASS, val=0.0) - add_aviary_input(self, Aircraft.Nacelle.MASS, val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Paint.MASS, val=0.0) - add_aviary_input(self, Aircraft.VerticalTail.MASS, val=0.0) - add_aviary_input(self, Aircraft.Wing.MASS, val=0.0) - - add_aviary_output(self, Aircraft.Design.STRUCTURE_MASS, val=0.0) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input(self, Aircraft.Canard.MASS, units='lbm') + add_aviary_input(self, Aircraft.Fins.MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.MASS, units='lbm') + add_aviary_input(self, Aircraft.HorizontalTail.MASS, units='lbm') + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS, units='lbm') + add_aviary_input(self, Aircraft.LandingGear.NOSE_GEAR_MASS, units='lbm') + add_aviary_input(self, Aircraft.Nacelle.MASS, shape=num_engine_type, units='lbm') + add_aviary_input(self, Aircraft.Paint.MASS, units='lbm') + add_aviary_input(self, Aircraft.VerticalTail.MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.MASS, units='lbm') + + add_aviary_output(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') def setup_partials(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) self.declare_partials(Aircraft.Design.STRUCTURE_MASS, '*', val=1) - self.declare_partials(Aircraft.Design.STRUCTURE_MASS, Aircraft.Nacelle.MASS, - val=np.ones(num_engine_type)) + self.declare_partials( + Aircraft.Design.STRUCTURE_MASS, Aircraft.Nacelle.MASS, val=np.ones(num_engine_type) + ) def compute(self, inputs, outputs): canard_mass = inputs[Aircraft.Canard.MASS] @@ -120,33 +118,36 @@ def compute(self, inputs, outputs): vtail_mass = inputs[Aircraft.VerticalTail.MASS] wing_mass = inputs[Aircraft.Wing.MASS] - outputs[Aircraft.Design.STRUCTURE_MASS] = \ - wing_mass + htail_mass + vtail_mass + fin_mass + canard_mass + \ - fus_mass + main_gear_mass + nose_gear_mass + np.sum(nac_mass) + paint_mass + outputs[Aircraft.Design.STRUCTURE_MASS] = ( + wing_mass + + htail_mass + + vtail_mass + + fin_mass + + canard_mass + + fus_mass + + main_gear_mass + + nose_gear_mass + + np.sum(nac_mass) + + paint_mass + ) class PropulsionMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_MISC_MASS, val=0.0) - add_aviary_input( - self, Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_MASS, val=0.0) + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_MISC_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_MASS, units='lbm') - add_aviary_output(self, Aircraft.Propulsion.MASS, val=0.0) + add_aviary_output(self, Aircraft.Propulsion.MASS, units='lbm') def setup_partials(self): prop_wrt = [ Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, Aircraft.Propulsion.TOTAL_MISC_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_MASS] + Aircraft.Propulsion.TOTAL_ENGINE_MASS, + ] self.declare_partials(Aircraft.Propulsion.MASS, prop_wrt, val=1) @@ -156,30 +157,25 @@ def compute(self, inputs, outputs): thrust_rev_mass = inputs[Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS] total_eng_mass = inputs[Aircraft.Propulsion.TOTAL_ENGINE_MASS] - outputs[Aircraft.Propulsion.MASS] = \ + outputs[Aircraft.Propulsion.MASS] = ( thrust_rev_mass + misc_prop_mass + fuel_sys_mass + total_eng_mass + ) class SystemsEquipMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.AirConditioning.MASS, val=0.0) - add_aviary_input(self, Aircraft.AntiIcing.MASS, val=0.0) - add_aviary_input(self, Aircraft.APU.MASS, val=0.0) - add_aviary_input(self, Aircraft.Avionics.MASS, val=0.0) - add_aviary_input(self, Aircraft.Electrical.MASS, val=0.0) - add_aviary_input(self, Aircraft.Furnishings.MASS, val=0.0) - add_aviary_input(self, Aircraft.Hydraulics.MASS, val=0.0) - add_aviary_input(self, Aircraft.Instruments.MASS, val=0.0) - add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS, val=0.0) - add_aviary_input(self, Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, val=0.0) - - add_aviary_output(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, val=0.0) + add_aviary_input(self, Aircraft.AirConditioning.MASS, units='lbm') + add_aviary_input(self, Aircraft.AntiIcing.MASS, units='lbm') + add_aviary_input(self, Aircraft.APU.MASS, units='lbm') + add_aviary_input(self, Aircraft.Avionics.MASS, units='lbm') + add_aviary_input(self, Aircraft.Electrical.MASS, units='lbm') + add_aviary_input(self, Aircraft.Furnishings.MASS, units='lbm') + add_aviary_input(self, Aircraft.Hydraulics.MASS, units='lbm') + add_aviary_input(self, Aircraft.Instruments.MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, units='lbm') + + add_aviary_output(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, units='lbm') def setup_partials(self): self.declare_partials(Aircraft.Design.SYSTEMS_EQUIP_MASS, '*', val=1) @@ -193,35 +189,37 @@ def compute(self, inputs, outputs): furnish_mass = inputs[Aircraft.Furnishings.MASS] hydraulics_mass = inputs[Aircraft.Hydraulics.MASS] instrument_mass = inputs[Aircraft.Instruments.MASS] - surf_ctrl_mass = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS] + surf_control_mass = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS] subsystems_mass = inputs[Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS] - outputs[Aircraft.Design.SYSTEMS_EQUIP_MASS] = \ - surf_ctrl_mass + APU_mass + instrument_mass + hydraulics_mass + \ - elec_mass + avionics_mass + furnish_mass + AC_mass + anti_icing_mass + \ - subsystems_mass + outputs[Aircraft.Design.SYSTEMS_EQUIP_MASS] = ( + surf_control_mass + + APU_mass + + instrument_mass + + hydraulics_mass + + elec_mass + + avionics_mass + + furnish_mass + + AC_mass + + anti_icing_mass + + subsystems_mass + ) class AltSystemsEquipMassBase(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.AirConditioning.MASS, val=0.0) - add_aviary_input(self, Aircraft.AntiIcing.MASS, val=0.0) - add_aviary_input(self, Aircraft.APU.MASS, val=0.0) - add_aviary_input(self, Aircraft.Avionics.MASS, val=0.0) - add_aviary_input(self, Aircraft.Electrical.MASS, val=0.0) - add_aviary_input(self, Aircraft.Furnishings.MASS_BASE, val=0.0) - add_aviary_input(self, Aircraft.Hydraulics.MASS, val=0.0) - add_aviary_input(self, Aircraft.Instruments.MASS, val=0.0) - add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS, val=0.0) - add_aviary_input(self, Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, val=0.0) - - add_aviary_output(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, val=0.0) + add_aviary_input(self, Aircraft.AirConditioning.MASS, units='lbm') + add_aviary_input(self, Aircraft.AntiIcing.MASS, units='lbm') + add_aviary_input(self, Aircraft.APU.MASS, units='lbm') + add_aviary_input(self, Aircraft.Avionics.MASS, units='lbm') + add_aviary_input(self, Aircraft.Electrical.MASS, units='lbm') + add_aviary_input(self, Aircraft.Furnishings.MASS_BASE, units='lbm') + add_aviary_input(self, Aircraft.Hydraulics.MASS, units='lbm') + add_aviary_input(self, Aircraft.Instruments.MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, units='lbm') + + add_aviary_output(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, units='lbm') def setup_partials(self): self.declare_partials(Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, '*', val=1) @@ -235,40 +233,40 @@ def compute(self, inputs, outputs): furnish_mass_base = inputs[Aircraft.Furnishings.MASS_BASE] hydraulics_mass = inputs[Aircraft.Hydraulics.MASS] instrument_mass = inputs[Aircraft.Instruments.MASS] - surf_ctrl_mass = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS] + surf_control_mass = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS] subsystems_mass = inputs[Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS] - outputs[Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE] = \ - surf_ctrl_mass + APU_mass + instrument_mass + hydraulics_mass + \ - elec_mass + avionics_mass + furnish_mass_base + AC_mass + anti_icing_mass + \ - subsystems_mass + outputs[Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE] = ( + surf_control_mass + + APU_mass + + instrument_mass + + hydraulics_mass + + elec_mass + + avionics_mass + + furnish_mass_base + + AC_mass + + anti_icing_mass + + subsystems_mass + ) class AltSystemsEquipMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, val=0.0) - add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.MASS, val=0.0) + add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, units='lbm') + add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.MASS, units='lbm') - add_aviary_output(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, val=0.0) + add_aviary_output(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, units='lbm') def setup_partials(self): self.declare_partials( Aircraft.Design.SYSTEMS_EQUIP_MASS, [Aircraft.Design.STRUCTURE_MASS, Aircraft.Propulsion.MASS], - val=0.01 + val=0.01, ) self.declare_partials( - Aircraft.Design.SYSTEMS_EQUIP_MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, - val=1.01 + Aircraft.Design.SYSTEMS_EQUIP_MASS, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, val=1.01 ) def compute(self, inputs, outputs): @@ -276,25 +274,19 @@ def compute(self, inputs, outputs): structure_mass = inputs[Aircraft.Design.STRUCTURE_MASS] prop_mass = inputs[Aircraft.Propulsion.MASS] - outputs[Aircraft.Design.SYSTEMS_EQUIP_MASS] = \ - sys_equip_mass_base + 0.01 * \ - (structure_mass + prop_mass + sys_equip_mass_base) + outputs[Aircraft.Design.SYSTEMS_EQUIP_MASS] = sys_equip_mass_base + 0.01 * ( + structure_mass + prop_mass + sys_equip_mass_base + ) class EmptyMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.Design.EMPTY_MASS_MARGIN, val=0.0) - add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.MASS, val=0.0) - add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, val=0.0) + add_aviary_input(self, Aircraft.Design.EMPTY_MASS_MARGIN, units='lbm') + add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS, units='lbm') - add_aviary_output(self, Aircraft.Design.EMPTY_MASS, val=0.0) + add_aviary_output(self, Aircraft.Design.EMPTY_MASS, units='lbm') def setup_partials(self): self.declare_partials(Aircraft.Design.EMPTY_MASS, '*', val=1) @@ -305,34 +297,33 @@ def compute(self, inputs, outputs): sys_equip_mass = inputs[Aircraft.Design.SYSTEMS_EQUIP_MASS] empty_mass_margin = inputs[Aircraft.Design.EMPTY_MASS_MARGIN] - outputs[Aircraft.Design.EMPTY_MASS] = \ + outputs[Aircraft.Design.EMPTY_MASS] = ( structure_mass + prop_mass + sys_equip_mass + empty_mass_margin + ) class AltEmptyMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.Design.EMPTY_MASS_MARGIN, val=0.0) - add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.MASS, val=0.0) - add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, val=0.0) + add_aviary_input(self, Aircraft.Design.EMPTY_MASS_MARGIN, units='lbm') + add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, units='lbm') - add_aviary_output(self, Aircraft.Design.EMPTY_MASS, val=0.0) + add_aviary_output(self, Aircraft.Design.EMPTY_MASS, units='lbm') def setup_partials(self): - self.declare_partials(Aircraft.Design.EMPTY_MASS, - [Aircraft.Design.STRUCTURE_MASS, - Aircraft.Propulsion.MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE], - val=1.01) - self.declare_partials(Aircraft.Design.EMPTY_MASS, - Aircraft.Design.EMPTY_MASS_MARGIN, - val=1.0) + self.declare_partials( + Aircraft.Design.EMPTY_MASS, + [ + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Propulsion.MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, + ], + val=1.01, + ) + self.declare_partials( + Aircraft.Design.EMPTY_MASS, Aircraft.Design.EMPTY_MASS_MARGIN, val=1.0 + ) def compute(self, inputs, outputs): structure_mass = inputs[Aircraft.Design.STRUCTURE_MASS] @@ -340,30 +331,25 @@ def compute(self, inputs, outputs): sys_equip_mass_base = inputs[Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE] empty_mass_margin = inputs[Aircraft.Design.EMPTY_MASS_MARGIN] - outputs[Aircraft.Design.EMPTY_MASS] = \ + outputs[Aircraft.Design.EMPTY_MASS] = ( 1.01 * (structure_mass + prop_mass + sys_equip_mass_base) + empty_mass_margin + ) class OperatingMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.CrewPayload.CARGO_CONTAINER_MASS, val=0.0) - add_aviary_input(self, Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, val=0.0) - add_aviary_input(self, Aircraft.CrewPayload.FLIGHT_CREW_MASS, val=0.0) - add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, val=0.0) - add_aviary_input(self, Aircraft.Design.EMPTY_MASS, val=0.0) - add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, val=0.0) + add_aviary_input(self, Aircraft.CrewPayload.CARGO_CONTAINER_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.FLIGHT_CREW_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.EMPTY_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, units='lbm') - add_aviary_output(self, Aircraft.Design.OPERATING_MASS, val=0.0) + add_aviary_output(self, Mission.Summary.OPERATING_MASS, units='lbm') def setup_partials(self): - self.declare_partials(Aircraft.Design.OPERATING_MASS, '*', val=1) + self.declare_partials(Mission.Summary.OPERATING_MASS, '*', val=1) def compute(self, inputs, outputs): cargo_container_mass = inputs[Aircraft.CrewPayload.CARGO_CONTAINER_MASS] @@ -374,60 +360,51 @@ def compute(self, inputs, outputs): pass_service_mass = inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS] unusable_fuel_mass = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS] - outputs[Aircraft.Design.OPERATING_MASS] = \ - empty_mass + non_flight_crew_mass + flight_crew_mass + \ - unusable_fuel_mass + oil_mass + pass_service_mass + cargo_container_mass + outputs[Mission.Summary.OPERATING_MASS] = ( + empty_mass + + non_flight_crew_mass + + flight_crew_mass + + unusable_fuel_mass + + oil_mass + + pass_service_mass + + cargo_container_mass + ) class ZeroFuelMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_MASS, val=0.0) - add_aviary_input(self, Aircraft.CrewPayload.BAGGAGE_MASS, val=0.0) - add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, val=0.0) - add_aviary_input(self, Aircraft.Design.OPERATING_MASS, val=0.0) + add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.BAGGAGE_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm') + add_aviary_input(self, Mission.Summary.OPERATING_MASS, units='lbm') - add_aviary_output(self, Aircraft.Design.ZERO_FUEL_MASS, val=0.0) + add_aviary_output(self, Mission.Summary.ZERO_FUEL_MASS, units='lbm') def setup_partials(self): - self.declare_partials(Aircraft.Design.ZERO_FUEL_MASS, '*', val=1) + self.declare_partials(Mission.Summary.ZERO_FUEL_MASS, '*', val=1) def compute(self, inputs, outputs): pass_mass = inputs[Aircraft.CrewPayload.PASSENGER_MASS] bag_mass = inputs[Aircraft.CrewPayload.BAGGAGE_MASS] cargo_mass = inputs[Aircraft.CrewPayload.CARGO_MASS] - operating_mass = inputs[Aircraft.Design.OPERATING_MASS] + operating_mass = inputs[Mission.Summary.OPERATING_MASS] - outputs[Aircraft.Design.ZERO_FUEL_MASS] = \ - operating_mass + pass_mass + bag_mass + cargo_mass + outputs[Mission.Summary.ZERO_FUEL_MASS] = operating_mass + pass_mass + bag_mass + cargo_mass class FuelMass(om.ExplicitComponent): - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - def setup(self): - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Design.ZERO_FUEL_MASS, val=0.0) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Mission.Summary.ZERO_FUEL_MASS, units='lbm') - add_aviary_output(self, Mission.Design.FUEL_MASS, val=0.0) + add_aviary_output(self, Mission.Summary.FUEL_MASS, units='lbm') def setup_partials(self): - self.declare_partials(Mission.Design.FUEL_MASS, - Mission.Design.GROSS_MASS, val=1) - self.declare_partials(Mission.Design.FUEL_MASS, - Aircraft.Design.ZERO_FUEL_MASS, val=-1) + self.declare_partials(Mission.Summary.FUEL_MASS, Mission.Design.GROSS_MASS, val=1) + self.declare_partials(Mission.Summary.FUEL_MASS, Mission.Summary.ZERO_FUEL_MASS, val=-1) def compute(self, inputs, outputs): - zero_fuel_mass = inputs[Aircraft.Design.ZERO_FUEL_MASS] + zero_fuel_mass = inputs[Mission.Summary.ZERO_FUEL_MASS] gross_mass = inputs[Mission.Design.GROSS_MASS] - outputs[Mission.Design.FUEL_MASS] = gross_mass - zero_fuel_mass + outputs[Mission.Summary.FUEL_MASS] = gross_mass - zero_fuel_mass diff --git a/aviary/subsystems/mass/flops_based/misc_engine.py b/aviary/subsystems/mass/flops_based/misc_engine.py index dba079072d..5f2e9f9433 100644 --- a/aviary/subsystems/mass/flops_based/misc_engine.py +++ b/aviary/subsystems/mass/flops_based/misc_engine.py @@ -1,14 +1,11 @@ -import numpy as np import openmdao.api as om -import numpy as np -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class EngineMiscMass(om.ExplicitComponent): - ''' + """ Calculates miscellaneous mass for a set of a engine model. Assumptions @@ -17,39 +14,36 @@ class EngineMiscMass(om.ExplicitComponent): Currently using engine-level additional mass (scaled by num_engines) and propulsion-level starter and controls mass, not heterogeneous engine safe! - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input( - self, Aircraft.Engine.ADDITIONAL_MASS, val=np.zeros(num_engine_type)) - add_aviary_input(self, Aircraft.Propulsion.MISC_MASS_SCALER, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_STARTER_MASS, val=0.0) + add_aviary_input(self, Aircraft.Engine.ADDITIONAL_MASS, shape=num_engine_type, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.MISC_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_STARTER_MASS, units='lbm') - add_aviary_output(self, Aircraft.Propulsion.TOTAL_MISC_MASS, val=0.0) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_MISC_MASS, units='lbm') self.declare_partials( of=Aircraft.Propulsion.TOTAL_MISC_MASS, - wrt=[Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - Aircraft.Propulsion.TOTAL_STARTER_MASS, - Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Propulsion.MISC_MASS_SCALER], - val=1 + wrt=[ + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, + Aircraft.Propulsion.TOTAL_STARTER_MASS, + Aircraft.Engine.ADDITIONAL_MASS, + Aircraft.Propulsion.MISC_MASS_SCALER, + ], + val=1, ) def compute(self, inputs, outputs): # TODO temporarily using engine-level additional mass and multiplying # by num_engines to get propulsion-level additional mass - options: AviaryValues = self.options['aviary_options'] - num_engines = options.get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] addtl_mass = sum(inputs[Aircraft.Engine.ADDITIONAL_MASS] * num_engines) ctrl_mass = inputs[Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] @@ -63,26 +57,23 @@ def compute(self, inputs, outputs): def compute_partials(self, inputs, J): # TODO temporarily using engine-level additional mass and multiplying # by num_engines to get propulsion-level additional mass - options: AviaryValues = self.options['aviary_options'] - num_engines = options.get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] addtl_mass = inputs[Aircraft.Engine.ADDITIONAL_MASS] * num_engines ctrl_mass = inputs[Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] starter_mass = inputs[Aircraft.Propulsion.TOTAL_STARTER_MASS] scaler = inputs[Aircraft.Propulsion.MISC_MASS_SCALER] - J[Aircraft.Propulsion.TOTAL_MISC_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS - ] = scaler + J[Aircraft.Propulsion.TOTAL_MISC_MASS, Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] = ( + scaler + ) - J[Aircraft.Propulsion.TOTAL_MISC_MASS, - Aircraft.Propulsion.TOTAL_STARTER_MASS - ] = scaler + J[Aircraft.Propulsion.TOTAL_MISC_MASS, Aircraft.Propulsion.TOTAL_STARTER_MASS] = scaler - J[Aircraft.Propulsion.TOTAL_MISC_MASS, - Aircraft.Engine.ADDITIONAL_MASS - ] = scaler * num_engines + J[Aircraft.Propulsion.TOTAL_MISC_MASS, Aircraft.Engine.ADDITIONAL_MASS] = ( + scaler * num_engines + ) - J[Aircraft.Propulsion.TOTAL_MISC_MASS, - Aircraft.Propulsion.MISC_MASS_SCALER - ] = starter_mass + sum(addtl_mass) + ctrl_mass + J[Aircraft.Propulsion.TOTAL_MISC_MASS, Aircraft.Propulsion.MISC_MASS_SCALER] = ( + starter_mass + sum(addtl_mass) + ctrl_mass + ) diff --git a/aviary/subsystems/mass/flops_based/nacelle.py b/aviary/subsystems/mass/flops_based/nacelle.py index 398d8f0afc..48e610d23f 100644 --- a/aviary/subsystems/mass/flops_based/nacelle.py +++ b/aviary/subsystems/mass/flops_based/nacelle.py @@ -3,13 +3,12 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.subsystems.mass.flops_based.distributed_prop import nacelle_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class NacelleMass(om.ExplicitComponent): - ''' + """ Calculates total mass of all nacelles in a set for an engine model. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. @@ -18,49 +17,49 @@ class NacelleMass(om.ExplicitComponent): ----------- all engines have identical nacelles, so Nacelle values are being used for propulsion -level totals as well as totals for a set of engines for an engine model - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, - val=np.zeros(num_engine_type)) + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, shape=num_engine_type, units='ft') + add_aviary_input( + self, Aircraft.Nacelle.MASS_SCALER, shape=num_engine_type, units='unitless' + ) + add_aviary_input( + self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type, units='lbf' + ) - add_aviary_input(self, Aircraft.Nacelle.AVG_LENGTH, - val=np.zeros(num_engine_type)) - - add_aviary_input(self, Aircraft.Nacelle.MASS_SCALER, - val=np.ones(num_engine_type)) - - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, - val=np.zeros(num_engine_type)) - - add_aviary_output(self, Aircraft.Nacelle.MASS, val=np.zeros(num_engine_type)) + add_aviary_output(self, Aircraft.Nacelle.MASS, shape=num_engine_type, units='lbm') def setup_partials(self): # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) - self.declare_partials(Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_DIAMETER, - rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_LENGTH, - rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Nacelle.MASS, Aircraft.Nacelle.MASS_SCALER, - rows=shape, cols=shape, val=1.0) - self.declare_partials(Aircraft.Nacelle.MASS, Aircraft.Engine.SCALED_SLS_THRUST, - rows=shape, cols=shape, val=1.0) + self.declare_partials( + Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_DIAMETER, rows=shape, cols=shape, val=1.0 + ) + self.declare_partials( + Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_LENGTH, rows=shape, cols=shape, val=1.0 + ) + self.declare_partials( + Aircraft.Nacelle.MASS, Aircraft.Nacelle.MASS_SCALER, rows=shape, cols=shape, val=1.0 + ) + self.declare_partials( + Aircraft.Nacelle.MASS, + Aircraft.Engine.SCALED_SLS_THRUST, + rows=shape, + cols=shape, + val=1.0, + ) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - num_eng = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] avg_diam = inputs[Aircraft.Nacelle.AVG_DIAMETER] avg_length = inputs[Aircraft.Nacelle.AVG_LENGTH] scaler = inputs[Aircraft.Nacelle.MASS_SCALER] @@ -69,12 +68,12 @@ def compute(self, inputs, outputs): # TODO: This should be distributed thrust factor thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] - outputs[Aircraft.Nacelle.MASS] = 0.25 * count_factor * \ - avg_diam * avg_length * thrust**0.36 * scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.Nacelle.MASS] = ( + 0.25 * count_factor * avg_diam * avg_length * thrust**0.36 * scaler / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_eng = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] avg_diam = inputs[Aircraft.Nacelle.AVG_DIAMETER] avg_length = inputs[Aircraft.Nacelle.AVG_LENGTH] scaler = inputs[Aircraft.Nacelle.MASS_SCALER] @@ -85,11 +84,15 @@ def compute_partials(self, inputs, J): thrust_exp = thrust**0.36 - J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_DIAMETER] = 0.25 * \ - count_factor * avg_length * thrust_exp * scaler / GRAV_ENGLISH_LBM - J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_LENGTH] = 0.25 * \ - count_factor * avg_diam * thrust_exp * scaler / GRAV_ENGLISH_LBM - J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.MASS_SCALER] = 0.25 * \ - count_factor * avg_diam * avg_length * thrust_exp / GRAV_ENGLISH_LBM - J[Aircraft.Nacelle.MASS, Aircraft.Engine.SCALED_SLS_THRUST] = 0.09 * \ - count_factor * avg_diam * avg_length * thrust**-0.64 * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_DIAMETER] = ( + 0.25 * count_factor * avg_length * thrust_exp * scaler / GRAV_ENGLISH_LBM + ) + J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.AVG_LENGTH] = ( + 0.25 * count_factor * avg_diam * thrust_exp * scaler / GRAV_ENGLISH_LBM + ) + J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.MASS_SCALER] = ( + 0.25 * count_factor * avg_diam * avg_length * thrust_exp / GRAV_ENGLISH_LBM + ) + J[Aircraft.Nacelle.MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + 0.09 * count_factor * avg_diam * avg_length * thrust**-0.64 * scaler / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/paint.py b/aviary/subsystems/mass/flops_based/paint.py index 7e1df471af..146b5e5ace 100644 --- a/aviary/subsystems/mass/flops_based/paint.py +++ b/aviary/subsystems/mass/flops_based/paint.py @@ -1,33 +1,22 @@ import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variables import Aircraft class PaintMass(om.ExplicitComponent): - ''' - Calculates the mass of paint based on total wetted area. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """Calculates the mass of paint based on total wetted area.""" def setup(self): - add_aviary_input(self, Aircraft.Design.TOTAL_WETTED_AREA, val=0.0) - - add_aviary_input(self, Aircraft.Paint.MASS_PER_UNIT_AREA, val=0.0) + add_aviary_input(self, Aircraft.Design.TOTAL_WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Paint.MASS_PER_UNIT_AREA, units='lbm/ft**2') - add_aviary_output(self, Aircraft.Paint.MASS, val=0.0) + add_aviary_output(self, Aircraft.Paint.MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): wetted_area = inputs[Aircraft.Design.TOTAL_WETTED_AREA] mass_per_area = inputs[Aircraft.Paint.MASS_PER_UNIT_AREA] @@ -37,8 +26,6 @@ def compute_partials(self, inputs, J): wetted_area = inputs[Aircraft.Design.TOTAL_WETTED_AREA] mass_per_area = inputs[Aircraft.Paint.MASS_PER_UNIT_AREA] - J[Aircraft.Paint.MASS, Aircraft.Design.TOTAL_WETTED_AREA] = \ - mass_per_area + J[Aircraft.Paint.MASS, Aircraft.Design.TOTAL_WETTED_AREA] = mass_per_area - J[Aircraft.Paint.MASS, Aircraft.Paint.MASS_PER_UNIT_AREA] = \ - wetted_area + J[Aircraft.Paint.MASS, Aircraft.Paint.MASS_PER_UNIT_AREA] = wetted_area diff --git a/aviary/subsystems/mass/flops_based/passenger_service.py b/aviary/subsystems/mass/flops_based/passenger_service.py index 7d16880858..3037841cee 100644 --- a/aviary/subsystems/mass/flops_based/passenger_service.py +++ b/aviary/subsystems/mass/flops_based/passenger_service.py @@ -1,156 +1,121 @@ -''' +""" Define utilities to calculate the estimated mass of passenger service equipment. -''' +""" + import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class PassengerServiceMass(om.ExplicitComponent): - ''' + """ Define the default component to calculate the estimated mass of passenger service equipment. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): - add_aviary_input( - self, - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, - val=1., - ) + add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, units='unitless') + add_aviary_input(self, Mission.Design.RANGE, units='NM') - add_aviary_input( - self, - Mission.Design.RANGE, - val=0.0, - ) - - add_aviary_output( - self, - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, - val=0.0, - ) + add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - first_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) + first_class_count = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + business_class_count = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] + tourist_class_count = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] - business_class_count = \ - aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) - - tourist_class_count = \ - aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) design_range = inputs[Mission.Design.RANGE] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] - passenger_service_mass_scaler = \ - inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER] + passenger_service_mass_scaler = inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER] passenger_service_weight = ( - ( - 5.164 * first_class_count - + 3.846 * business_class_count - + 2.529 * tourist_class_count - ) * (design_range / max_mach)**0.225 + (5.164 * first_class_count + 3.846 * business_class_count + 2.529 * tourist_class_count) + * (design_range / max_mach) ** 0.225 ) * passenger_service_mass_scaler - outputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS] = \ + outputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS] = ( passenger_service_weight / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - first_class_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) - - business_class_count = \ - aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) + first_class_count = self.options[Aircraft.CrewPayload.Design.NUM_FIRST_CLASS] + business_class_count = self.options[Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS] + tourist_class_count = self.options[Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS] - tourist_class_count = \ - aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) design_range = inputs[Mission.Design.RANGE] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] - passenger_service_mass_scaler = \ - inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER] + passenger_service_mass_scaler = inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER] - J[ - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, - Mission.Design.RANGE - ] = passenger_service_mass_scaler * ( - 5.164 * first_class_count - + 3.846 * business_class_count - + 2.529 * tourist_class_count - ) * 0.225 * ((design_range / max_mach)**-0.775) / max_mach / GRAV_ENGLISH_LBM + J[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, Mission.Design.RANGE] = ( + passenger_service_mass_scaler + * ( + 5.164 * first_class_count + + 3.846 * business_class_count + + 2.529 * tourist_class_count + ) + * 0.225 + * ((design_range / max_mach) ** -0.775) + / max_mach + / GRAV_ENGLISH_LBM + ) J[ Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, ] = ( - ( - 5.164 * first_class_count - + 3.846 * business_class_count - + 2.529 * tourist_class_count - ) * (design_range / max_mach)**0.225 + (5.164 * first_class_count + 3.846 * business_class_count + 2.529 * tourist_class_count) + * (design_range / max_mach) ** 0.225 ) / GRAV_ENGLISH_LBM class AltPassengerServiceMass(om.ExplicitComponent): - ''' + """ Define the alternate component to calculate the estimated mass of passenger service equipment. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) def setup(self): - add_aviary_input( - self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, val=1.) + add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, val=0.0) + add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, units='lbm') def setup_partials(self): self.declare_partials('*', '*') - def compute( - self, inputs, outputs, discrete_inputs=None, discrete_outputs=None - ): - aviary_options: AviaryValues = self.options['aviary_options'] - passenger_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): + passenger_count = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] - passenger_service_mass_scaler = \ - inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER] + passenger_service_mass_scaler = inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER] - passenger_service_weight = \ - 31.7 * passenger_count * passenger_service_mass_scaler + passenger_service_weight = 31.7 * passenger_count * passenger_service_mass_scaler - outputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS] = \ + outputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS] = ( passenger_service_weight / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J, discrete_inputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - passenger_count = aviary_options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') + passenger_count = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] J[ Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, ] = 31.7 * passenger_count / GRAV_ENGLISH_LBM diff --git a/aviary/subsystems/mass/flops_based/starter.py b/aviary/subsystems/mass/flops_based/starter.py index e7b06a4d9f..741c0a0728 100644 --- a/aviary/subsystems/mass/flops_based/starter.py +++ b/aviary/subsystems/mass/flops_based/starter.py @@ -1,68 +1,65 @@ import openmdao.api as om -import numpy as np from aviary.constants import GRAV_ENGLISH_LBM from aviary.subsystems.mass.flops_based.distributed_prop import ( - distributed_engine_count_factor, distributed_nacelle_diam_factor) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output + distributed_engine_count_factor, + distributed_nacelle_diam_factor, +) +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class TransportStarterMass(om.ExplicitComponent): - ''' + """ Calculates total sum of all engine starter masses for the entire propulsion system (all engines). The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, - val=np.zeros(num_engine_type)) + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') - add_aviary_output(self, Aircraft.Propulsion.TOTAL_STARTER_MASS, val=0.0) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_STARTER_MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - total_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + total_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + max_mach = self.options[Mission.Constraints.MAX_MACH] d_nacelle = inputs[Aircraft.Nacelle.AVG_DIAMETER] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) num_engines_factor = distributed_engine_count_factor(total_engines) f_nacelle = distributed_nacelle_diam_factor(d_nacelle, num_engines) outputs[Aircraft.Propulsion.TOTAL_STARTER_MASS] = ( - 11.0 * num_engines_factor * max_mach**0.32 * f_nacelle**1.6) / GRAV_ENGLISH_LBM + 11.0 * num_engines_factor * max_mach**0.32 * f_nacelle**1.6 + ) / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - total_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - num_engines = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + total_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + max_mach = self.options[Mission.Constraints.MAX_MACH] d_nacelle = inputs[Aircraft.Nacelle.AVG_DIAMETER] eng_count_factor = distributed_engine_count_factor(total_engines) - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) d_avg = sum(d_nacelle * num_engines) / total_engines diam_deriv_fact = 1 if total_engines > 4: - diam_deriv_fact = (0.5 * total_engines ** 0.5)**1.6 + diam_deriv_fact = (0.5 * total_engines**0.5) ** 1.6 - diam_exp = diam_deriv_fact * d_avg**1.6 max_mach_exp = max_mach**0.32 - J[Aircraft.Propulsion.TOTAL_STARTER_MASS, Aircraft.Nacelle.AVG_DIAMETER] = \ + J[Aircraft.Propulsion.TOTAL_STARTER_MASS, Aircraft.Nacelle.AVG_DIAMETER] = ( 17.6 * eng_count_factor * max_mach_exp * diam_deriv_fact * d_avg**0.6 / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/surface_controls.py b/aviary/subsystems/mass/flops_based/surface_controls.py index 441a7fcde0..d7acc95e22 100644 --- a/aviary/subsystems/mass/flops_based/surface_controls.py +++ b/aviary/subsystems/mass/flops_based/surface_controls.py @@ -1,113 +1,115 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class SurfaceControlMass(om.ExplicitComponent): - ''' + """ Calculate the mass of the surface controls. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Mission.Constraints.MAX_MACH) def setup(self): - add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1.0) - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, val=0.0) - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) + add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') - add_aviary_output(self, Aircraft.Wing.SURFACE_CONTROL_MASS, val=10) - add_aviary_output(self, Aircraft.Wing.CONTROL_SURFACE_AREA, val=2) + add_aviary_output(self, Aircraft.Wing.SURFACE_CONTROL_MASS, units='lbm') + add_aviary_output(self, Aircraft.Wing.CONTROL_SURFACE_AREA, units='ft**2') self.declare_partials(Aircraft.Wing.SURFACE_CONTROL_MASS, '*') - self.declare_partials(Aircraft.Wing.CONTROL_SURFACE_AREA, [ - Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, Aircraft.Wing.AREA]) + self.declare_partials( + Aircraft.Wing.CONTROL_SURFACE_AREA, + [Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, Aircraft.Wing.AREA], + ) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] scaler = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM flap_ratio = inputs[Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] wing_area = inputs[Aircraft.Wing.AREA] - surface_flap_area = flap_ratio*wing_area + surface_flap_area = flap_ratio * wing_area - surface_ctrls_wt = \ - 1.1*max_mach**.52 * surface_flap_area**.6 * gross_weight**.32 * scaler + surface_ctrls_wt = ( + 1.1 * max_mach**0.52 * surface_flap_area**0.6 * gross_weight**0.32 * scaler + ) outputs[Aircraft.Wing.CONTROL_SURFACE_AREA] = surface_flap_area - outputs[Aircraft.Wing.SURFACE_CONTROL_MASS] = surface_ctrls_wt / \ - GRAV_ENGLISH_LBM + outputs[Aircraft.Wing.SURFACE_CONTROL_MASS] = surface_ctrls_wt / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] scaler = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] - max_mach = aviary_options.get_val(Mission.Constraints.MAX_MACH) + max_mach = self.options[Mission.Constraints.MAX_MACH] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM flap_ratio = inputs[Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] wing_area = inputs[Aircraft.Wing.AREA] - surface_flap_area = flap_ratio*wing_area - - max_mach_exp = max_mach**.52 - surface_area_exp = surface_flap_area**.6 - gross_weight_exp = gross_weight**.32 - - J[ - Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] = \ - 1.1*max_mach_exp * surface_area_exp * gross_weight_exp / GRAV_ENGLISH_LBM - - J[Aircraft.Wing.SURFACE_CONTROL_MASS, Mission.Design.GROSS_MASS] = \ - 1.1*max_mach_exp * surface_area_exp * .32 * \ - gross_weight**(.32-1) * scaler - - J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] = \ - 1.1*max_mach_exp * .6 * \ - surface_flap_area**(.6-1) * gross_weight_exp * wing_area * \ - scaler / GRAV_ENGLISH_LBM - - J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.AREA] = \ - 1.1*max_mach_exp * .6 * \ - surface_flap_area**(.6-1) * gross_weight_exp * \ - flap_ratio * scaler / GRAV_ENGLISH_LBM - - J[Aircraft.Wing.CONTROL_SURFACE_AREA, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] = \ - wing_area + surface_flap_area = flap_ratio * wing_area + + max_mach_exp = max_mach**0.52 + surface_area_exp = surface_flap_area**0.6 + gross_weight_exp = gross_weight**0.32 + + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] = ( + 1.1 * max_mach_exp * surface_area_exp * gross_weight_exp / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Mission.Design.GROSS_MASS] = ( + 1.1 * max_mach_exp * surface_area_exp * 0.32 * gross_weight ** (0.32 - 1) * scaler + ) + + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] = ( + 1.1 + * max_mach_exp + * 0.6 + * surface_flap_area ** (0.6 - 1) + * gross_weight_exp + * wing_area + * scaler + / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.AREA] = ( + 1.1 + * max_mach_exp + * 0.6 + * surface_flap_area ** (0.6 - 1) + * gross_weight_exp + * flap_ratio + * scaler + / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Wing.CONTROL_SURFACE_AREA, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] = wing_area J[Aircraft.Wing.CONTROL_SURFACE_AREA, Aircraft.Wing.AREA] = flap_ratio class AltSurfaceControlMass(om.ExplicitComponent): - ''' + """ Calculate the mass of the surface controls using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1.0) - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) - add_aviary_input(self, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, val=0.0) - add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, val=0.0) - add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.0) - add_aviary_input(self, Aircraft.VerticalTail.AREA, val=0.0) + add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') - add_aviary_output(self, Aircraft.Wing.CONTROL_SURFACE_AREA, val=2) - add_aviary_output(self, Aircraft.Wing.SURFACE_CONTROL_MASS, val=0.0) + add_aviary_output(self, Aircraft.Wing.CONTROL_SURFACE_AREA, units='ft**2') + add_aviary_output(self, Aircraft.Wing.SURFACE_CONTROL_MASS, units='lbm') self.declare_partials('*', '*') @@ -119,11 +121,11 @@ def compute(self, inputs, outputs): htail_TCR = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] vtail_area = inputs[Aircraft.VerticalTail.AREA] - surface_ctrls_wt = (480 + .99*wing_area + 2.5*htail_area / - (2 + .387*htail_TCR) + 1.6*vtail_area) * scaler + surface_ctrls_wt = ( + 480 + 0.99 * wing_area + 2.5 * htail_area / (2 + 0.387 * htail_TCR) + 1.6 * vtail_area + ) * scaler - outputs[Aircraft.Wing.SURFACE_CONTROL_MASS] = surface_ctrls_wt / \ - GRAV_ENGLISH_LBM + outputs[Aircraft.Wing.SURFACE_CONTROL_MASS] = surface_ctrls_wt / GRAV_ENGLISH_LBM outputs[Aircraft.Wing.CONTROL_SURFACE_AREA] = flap_ratio * wing_area @@ -135,27 +137,23 @@ def compute_partials(self, inputs, J): htail_TCR = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] vtail_area = inputs[Aircraft.VerticalTail.AREA] - J[ - Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] = ( - 480 + .99 * wing_area + 2.5 * htail_area / (2 + .387 * htail_TCR) - + 1.6 * vtail_area) / GRAV_ENGLISH_LBM + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] = ( + 480 + 0.99 * wing_area + 2.5 * htail_area / (2 + 0.387 * htail_TCR) + 1.6 * vtail_area + ) / GRAV_ENGLISH_LBM - J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.AREA] = \ - .99 * scaler / GRAV_ENGLISH_LBM - J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.HorizontalTail.WETTED_AREA] = \ - 2.5/(2 + .387*htail_TCR) * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.AREA] = 0.99 * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.HorizontalTail.WETTED_AREA] = ( + 2.5 / (2 + 0.387 * htail_TCR) * scaler / GRAV_ENGLISH_LBM + ) - J[ - Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = \ - -2.5*htail_area/(2 + .387*htail_TCR)**2 * .387 * \ - scaler / GRAV_ENGLISH_LBM + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = ( + -2.5 * htail_area / (2 + 0.387 * htail_TCR) ** 2 * 0.387 * scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.VerticalTail.AREA] = \ + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.VerticalTail.AREA] = ( 1.6 * scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.CONTROL_SURFACE_AREA, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] = \ - wing_area + J[Aircraft.Wing.CONTROL_SURFACE_AREA, Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO] = wing_area J[Aircraft.Wing.CONTROL_SURFACE_AREA, Aircraft.Wing.AREA] = flap_ratio diff --git a/aviary/subsystems/mass/flops_based/test/test_air_conditioning.py b/aviary/subsystems/mass/flops_based/test/test_air_conditioning.py index b0becd20f4..f2f488a149 100644 --- a/aviary/subsystems/mass/flops_based/test/test_air_conditioning.py +++ b/aviary/subsystems/mass/flops_based/test/test_air_conditioning.py @@ -4,110 +4,114 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.air_conditioning import ( - AltAirCondMass, TransportAirCondMass) +from aviary.subsystems.mass.flops_based.air_conditioning import AltAirCondMass, TransportAirCondMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class TransportAirCondMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "air_cond", - TransportAirCondMass(aviary_options=get_flops_inputs(case_name)), + 'air_cond', + TransportAirCondMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.AirConditioning.MASS_SCALER, - Aircraft.Avionics.MASS, - Aircraft.Fuselage.MAX_HEIGHT, - Aircraft.Fuselage.PLANFORM_AREA], + input_keys=[ + Aircraft.AirConditioning.MASS_SCALER, + Aircraft.Avionics.MASS, + Aircraft.Fuselage.MAX_HEIGHT, + Aircraft.Fuselage.PLANFORM_AREA, + ], output_keys=Aircraft.AirConditioning.MASS, aviary_option_keys=[Aircraft.CrewPayload.Design.NUM_PASSENGERS], version=Version.TRANSPORT, tol=3.0e-4, - atol=1e-11) + atol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class TransportAirCondMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.air_conditioning as ac + ac.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.air_conditioning as ac + ac.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() + prob.model.add_subsystem( - "air_cond", - TransportAirCondMass(aviary_options=get_flops_inputs("N3CC")), + 'air_cond', + TransportAirCondMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle') + prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_SCALER, val=0.98094, units="unitless") - prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=2032., units="lbm") - prob.model.set_input_defaults( - Aircraft.Fuselage.MAX_HEIGHT, val=13., units="ft") - prob.model.set_input_defaults( - Aircraft.Fuselage.PLANFORM_AREA, val=1537.5, units="ft**2") + Aircraft.AirConditioning.MASS_SCALER, val=0.98094, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=2032.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.MAX_HEIGHT, val=13.0, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.PLANFORM_AREA, val=1537.5, units='ft**2') + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AltAirCondMassTest(unittest.TestCase): - ''' - Tests alternate air conditioning mass calculation. - ''' + """Tests alternate air conditioning mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( 'air_cond', - AltAirCondMass(aviary_options=get_flops_inputs(case_name)), + AltAirCondMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( @@ -116,38 +120,44 @@ def test_case(self, case_name): input_keys=Aircraft.AirConditioning.MASS_SCALER, output_keys=Aircraft.AirConditioning.MASS, aviary_option_keys=Aircraft.CrewPayload.Design.NUM_PASSENGERS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltAirCondMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.air_conditioning as ac + ac.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.air_conditioning as ac + ac.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() + prob.model.add_subsystem( 'air_cond', - AltAirCondMass(aviary_options=get_flops_inputs("N3CC")), + AltAirCondMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle') + prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_SCALER, val=0.98094, units="unitless") + Aircraft.AirConditioning.MASS_SCALER, val=0.98094, units='unitless' + ) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/mass/flops_based/test/test_anti_icing.py b/aviary/subsystems/mass/flops_based/test/test_anti_icing.py index b028442086..b756bbad7e 100644 --- a/aviary/subsystems/mass/flops_based/test/test_anti_icing.py +++ b/aviary/subsystems/mass/flops_based/test/test_anti_icing.py @@ -2,65 +2,71 @@ import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import parameterized from aviary.subsystems.mass.flops_based.anti_icing import AntiIcingMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class AntiIcingMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "anti_icing", - AntiIcingMass(aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'anti_icing', + AntiIcingMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.AntiIcing.MASS_SCALER, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Wing.SPAN, - Aircraft.Wing.SWEEP], + input_keys=[ + Aircraft.AntiIcing.MASS_SCALER, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Wing.SPAN, + Aircraft.Wing.SWEEP, + Aircraft.Engine.SCALED_SLS_THRUST, + ], output_keys=Aircraft.AntiIcing.MASS, - tol=3.0e-3) + tol=3.0e-3, + ) def test_case_2(self): # test with more than four engines prob = self.prob - aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([5])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 5) + options = get_flops_options('LargeSingleAisle1FLOPS') + options[Aircraft.Engine.NUM_ENGINES] = np.array([5]) + options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] = 5 prob.model.add_subsystem( - "anti_icing", - AntiIcingMass(aviary_options=aviary_options), + 'anti_icing', + AntiIcingMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = options + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.AntiIcing.MASS_SCALER, 1.0) @@ -68,6 +74,15 @@ def test_case_2(self): prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, np.array([7.94]), 'ft') prob.set_val(Aircraft.Wing.SPAN, 117.83, 'ft') prob.set_val(Aircraft.Wing.SWEEP, 25.0, 'deg') + prob.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, + np.array( + [ + 28928.1, + ] + ), + 'lbf', + ) prob.run_model() @@ -76,24 +91,29 @@ def test_case_2(self): assert_near_equal(mass, expected_mass, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_case_3(self): # test with multiple engine types prob = self.prob - aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 2, 4])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 8) + options = get_flops_options('LargeSingleAisle1FLOPS') + options[Aircraft.Engine.NUM_ENGINES] = np.array([2, 2, 4]) + options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] = 8 prob.model.add_subsystem( - "anti_icing", - AntiIcingMass(aviary_options=aviary_options), + 'anti_icing', + AntiIcingMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = options + prob.model_options[Aircraft.Engine.REFERENCE_SLS_THRUST] = np.array( + [28928.1, 28928.1, 28928.1] + ) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.AntiIcing.MASS_SCALER, 1.0) @@ -101,6 +121,9 @@ def test_case_3(self): prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, np.array([7.94, 8, 5]), 'ft') prob.set_val(Aircraft.Wing.SPAN, 117.83, 'ft') prob.set_val(Aircraft.Wing.SWEEP, 25.0, 'deg') + prob.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, np.array([28928.1, 28928.1, 28928.1]), 'lbf' + ) prob.run_model() @@ -109,8 +132,7 @@ def test_case_3(self): assert_near_equal(mass, expected_mass, tolerance=1e-10) - partial_data = self.prob.check_partials( - out_stream=None, method="cs", compact_print=False) + partial_data = self.prob.check_partials(out_stream=None, method='cs', compact_print=False) assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_IO(self): @@ -118,39 +140,53 @@ def test_IO(self): class AntiIcingMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.anti_icing as antiicing + antiicing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.anti_icing as antiicing + antiicing.GRAV_ENGLISH_LBM = 1.0 def test_case_2(self): prob = om.Problem() - aviary_options = get_flops_inputs('N3CC') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([5])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 5) + + options = get_flops_options('AdvancedSingleAisle') + options[Aircraft.Engine.NUM_ENGINES] = np.array([5]) + options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] = 5 + prob.model.add_subsystem( - "anti_icing", - AntiIcingMass(aviary_options=aviary_options), + 'anti_icing', + AntiIcingMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = options + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.AntiIcing.MASS_SCALER, 1.0) prob.set_val(Aircraft.Fuselage.MAX_WIDTH, 12.33, 'ft') prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, np.array([7.94]), 'ft') prob.set_val(Aircraft.Wing.SPAN, 117.83, 'ft') prob.set_val(Aircraft.Wing.SWEEP, 25.0, 'deg') + prob.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, + np.array( + [ + 28928.1, + ] + ), + 'lbf', + ) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_apu.py b/aviary/subsystems/mass/flops_based/test/test_apu.py index e9050e459d..92abe3c3ec 100644 --- a/aviary/subsystems/mass/flops_based/test/test_apu.py +++ b/aviary/subsystems/mass/flops_based/test/test_apu.py @@ -6,72 +6,76 @@ from aviary.subsystems.mass.flops_based.apu import TransportAPUMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class APUMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "apu", - TransportAPUMass(aviary_options=get_flops_inputs(case_name)), + 'apu', + TransportAPUMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.APU.MASS_SCALER, - Aircraft.Fuselage.PLANFORM_AREA], + input_keys=[Aircraft.APU.MASS_SCALER, Aircraft.Fuselage.PLANFORM_AREA], output_keys=Aircraft.APU.MASS, - tol=5.0e-4) + tol=5.0e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) class APUMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.apu as apu + apu.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.apu as apu + apu.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "apu", - TransportAPUMass(aviary_options=get_flops_inputs("N3CC")), + 'apu', + TransportAPUMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuselage.PLANFORM_AREA, 100.0, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_avionics.py b/aviary/subsystems/mass/flops_based/test/test_avionics.py index 3ce67ff86e..b56fc86cb1 100644 --- a/aviary/subsystems/mass/flops_based/test/test_avionics.py +++ b/aviary/subsystems/mass/flops_based/test/test_avionics.py @@ -6,78 +6,82 @@ from aviary.subsystems.mass.flops_based.avionics import TransportAvionicsMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class TransportAvionicsMassTest(unittest.TestCase): - ''' - Tests transport/GA avionics mass calculation. - ''' + """Tests transport/GA avionics mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "avionics", - TransportAvionicsMass(aviary_options=get_flops_inputs( - case_name, preprocess=True)), + 'avionics', + TransportAvionicsMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Avionics.MASS_SCALER, - Aircraft.Fuselage.PLANFORM_AREA, - Mission.Design.RANGE], + input_keys=[ + Aircraft.Avionics.MASS_SCALER, + Aircraft.Fuselage.PLANFORM_AREA, + Mission.Design.RANGE, + ], output_keys=Aircraft.Avionics.MASS, aviary_option_keys=[Aircraft.CrewPayload.NUM_FLIGHT_CREW], - tol=2.0e-4) + tol=2.0e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) class TransportAvionicsMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.avionics as avionics + avionics.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.avionics as avionics + avionics.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "avionics", - TransportAvionicsMass(aviary_options=get_flops_inputs( - "N3CC", preprocess=True)), + 'avionics', + TransportAvionicsMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuselage.PLANFORM_AREA, 1500.0, 'ft**2') prob.set_val(Mission.Design.RANGE, 3500.0, 'nmi') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/mass/flops_based/test/test_canard.py b/aviary/subsystems/mass/flops_based/test/test_canard.py index 9e44b23a37..41a0e254a1 100644 --- a/aviary/subsystems/mass/flops_based/test/test_canard.py +++ b/aviary/subsystems/mass/flops_based/test/test_canard.py @@ -11,31 +11,31 @@ from aviary.variable_info.variables import Aircraft, Mission canard_test_data = {} -canard_test_data['1'] = AviaryValues({ - Mission.Design.GROSS_MASS: (100000, "lbm"), - Aircraft.Canard.AREA: (250.00, 'ft**2'), - Aircraft.Canard.TAPER_RATIO: (0.330, 'unitless'), - Aircraft.Canard.MASS_SCALER: (1.0, 'unitless'), - Aircraft.Canard.MASS: (1099.75, 'lbm') -}) +canard_test_data['1'] = AviaryValues( + { + Mission.Design.GROSS_MASS: (100000, 'lbm'), + Aircraft.Canard.AREA: (250.00, 'ft**2'), + Aircraft.Canard.TAPER_RATIO: (0.330, 'unitless'), + Aircraft.Canard.MASS_SCALER: (1.0, 'unitless'), + Aircraft.Canard.MASS: (1099.75, 'lbm'), + } +) canard_data_sets = [key for key in canard_test_data] class CanardMassTest(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - @parameterized.expand(canard_data_sets, - name_func=print_case) + @parameterized.expand(canard_data_sets, name_func=print_case) def test_case1(self, case_name): # TODO: No test cases with canards. Use dummy vars. validation_data = canard_test_data[case_name] prob = self.prob prob.model.add_subsystem( - "canard", + 'canard', CanardMass(), promotes_inputs=['*'], promotes_outputs=['*'], @@ -43,40 +43,44 @@ def test_case1(self, case_name): prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=validation_data, - output_validation_data=validation_data, - input_keys=[Mission.Design.GROSS_MASS, - Aircraft.Canard.AREA, - Aircraft.Canard.TAPER_RATIO, - Aircraft.Canard.MASS_SCALER], - output_keys=Aircraft.Canard.MASS, - tol=1.0e-3, - atol=1e-10, - rtol=1e-10) + do_validation_test( + prob, + case_name, + input_validation_data=validation_data, + output_validation_data=validation_data, + input_keys=[ + Mission.Design.GROSS_MASS, + Aircraft.Canard.AREA, + Aircraft.Canard.TAPER_RATIO, + Aircraft.Canard.MASS_SCALER, + ], + output_keys=Aircraft.Canard.MASS, + tol=1.0e-3, + atol=1e-10, + rtol=1e-10, + ) def test_IO(self): assert_match_varnames(self.prob.model) class CanardMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.canard as canard + canard.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.canard as canard + canard.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() prob.model.add_subsystem( - "canard", + 'canard', CanardMass(), promotes_inputs=['*'], promotes_outputs=['*'], @@ -88,9 +92,9 @@ def test_case1(self): prob.set_val(Aircraft.Canard.MASS_SCALER, 1.0, 'unitless') prob.set_val(Aircraft.Canard.MASS, 1099.75, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_cargo.py b/aviary/subsystems/mass/flops_based/test/test_cargo.py index 7d388fc1c9..c8050b3c4b 100644 --- a/aviary/subsystems/mass/flops_based/test/test_cargo.py +++ b/aviary/subsystems/mass/flops_based/test/test_cargo.py @@ -3,63 +3,68 @@ import openmdao.api as om from parameterized import parameterized -from aviary.subsystems.mass.flops_based.cargo import CargoMass +from aviary.subsystems.mass.flops_based.cargo import PayloadGroup from aviary.utils.aviary_values import AviaryValues from aviary.utils.test_utils.variable_test import assert_match_varnames from aviary.validation_cases.validation_tests import do_validation_test, print_case from aviary.variable_info.variables import Aircraft cargo_test_data = {} -cargo_test_data['1'] = AviaryValues({ - Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER: (50, 'lbm'), - Aircraft.CrewPayload.MISC_CARGO: (2000., 'lbm'), # custom - Aircraft.CrewPayload.MASS_PER_PASSENGER: (180., 'lbm'), - Aircraft.CrewPayload.WING_CARGO: (1000., 'lbm'), # custom - Aircraft.CrewPayload.BAGGAGE_MASS: (9200., 'lbm'), # custom - Aircraft.CrewPayload.NUM_PASSENGERS: (184, 'unitless'), # custom - Aircraft.CrewPayload.PASSENGER_MASS: (33120., 'lbm'), # custom - Aircraft.CrewPayload.CARGO_MASS: (3000., 'lbm'), # custom - Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS: (45320., 'lbm') # custom -}) +cargo_test_data['1'] = AviaryValues( + { + Aircraft.CrewPayload.MISC_CARGO: (2000.0, 'lbm'), # custom + Aircraft.CrewPayload.WING_CARGO: (1000.0, 'lbm'), # custom + Aircraft.CrewPayload.BAGGAGE_MASS: (9200.0, 'lbm'), # custom + Aircraft.CrewPayload.PASSENGER_MASS: (33120.0, 'lbm'), # custom + Aircraft.CrewPayload.CARGO_MASS: (3000.0, 'lbm'), # custom + Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS: (45320.0, 'lbm'), # custom + } +) cargo_data_sets = [key for key in cargo_test_data] -class CargoMassTest(unittest.TestCase): - +class PayloadGroupTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(cargo_data_sets, - name_func=print_case) + @parameterized.expand(cargo_data_sets, name_func=print_case) def test_case(self, case_name): validation_data = cargo_test_data[case_name] prob = self.prob prob.model.add_subsystem( 'cargo_passenger', - CargoMass(aviary_options=validation_data), + PayloadGroup(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = { + Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER: (50, 'lbm'), + Aircraft.CrewPayload.MASS_PER_PASSENGER: (180.0, 'lbm'), + Aircraft.CrewPayload.NUM_PASSENGERS: 184, # custom + } + prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=validation_data, - output_validation_data=validation_data, - input_keys=[Aircraft.CrewPayload.MISC_CARGO, - Aircraft.CrewPayload.WING_CARGO], - output_keys=[Aircraft.CrewPayload.BAGGAGE_MASS, - Aircraft.CrewPayload.PASSENGER_MASS, - Aircraft.CrewPayload.CARGO_MASS, - Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, - ]) + do_validation_test( + prob, + case_name, + input_validation_data=validation_data, + output_validation_data=validation_data, + input_keys=[Aircraft.CrewPayload.MISC_CARGO, Aircraft.CrewPayload.WING_CARGO], + output_keys=[ + Aircraft.CrewPayload.BAGGAGE_MASS, + Aircraft.CrewPayload.PASSENGER_MASS, + Aircraft.CrewPayload.CARGO_MASS, + Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, + ], + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_cargo_containers.py b/aviary/subsystems/mass/flops_based/test/test_cargo_containers.py index 9b5c303c9f..2a7c7e5668 100644 --- a/aviary/subsystems/mass/flops_based/test/test_cargo_containers.py +++ b/aviary/subsystems/mass/flops_based/test/test_cargo_containers.py @@ -4,81 +4,83 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.cargo_containers import \ - TransportCargoContainersMass +from aviary.subsystems.mass.flops_based.cargo_containers import TransportCargoContainersMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class CargoContainerMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "cargo_containers", - TransportCargoContainersMass( - aviary_options=get_flops_inputs(case_name)), + 'cargo_containers', + TransportCargoContainersMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, - Aircraft.CrewPayload.CARGO_MASS, - Aircraft.CrewPayload.BAGGAGE_MASS], + input_keys=[ + Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, + Aircraft.CrewPayload.CARGO_MASS, + Aircraft.CrewPayload.BAGGAGE_MASS, + ], output_keys=Aircraft.CrewPayload.CARGO_CONTAINER_MASS, - rtol=1e-10) + rtol=1e-10, + ) def test_IO(self): assert_match_varnames(self.prob.model) class CargoContainerMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.anti_icing as antiicing + antiicing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.anti_icing as antiicing + antiicing.GRAV_ENGLISH_LBM = 1.0 def test_case(self): - prob = om.Problem() prob.model.add_subsystem( - "cargo_containers", - TransportCargoContainersMass( - aviary_options=get_flops_inputs("N3CC")), + 'cargo_containers', + TransportCargoContainersMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.CrewPayload.BAGGAGE_MASS, 5000.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_crew.py b/aviary/subsystems/mass/flops_based/test/test_crew.py index bcd0dc2ced..e8bf532e34 100644 --- a/aviary/subsystems/mass/flops_based/test/test_crew.py +++ b/aviary/subsystems/mass/flops_based/test/test_crew.py @@ -5,32 +5,32 @@ from aviary.subsystems.mass.flops_based.crew import FlightCrewMass, NonFlightCrewMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class NonFlightCrewMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "non_flight_crew", - NonFlightCrewMass(aviary_options=get_flops_inputs( - case_name, preprocess=True)), + 'non_flight_crew', + NonFlightCrewMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( @@ -38,30 +38,30 @@ def test_case(self, case_name): case_name, input_keys=Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, output_keys=Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, - atol=1e-11) + atol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class FlightCrewMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "flight_crew", - FlightCrewMass(aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'flight_crew', + FlightCrewMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( @@ -69,7 +69,8 @@ def test_case(self, case_name): case_name, input_keys=Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, output_keys=Aircraft.CrewPayload.FLIGHT_CREW_MASS, - atol=1e-11) + atol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) diff --git a/aviary/subsystems/mass/flops_based/test/test_distributed_prop.py b/aviary/subsystems/mass/flops_based/test/test_distributed_prop.py index 570f90404c..7c0961364c 100644 --- a/aviary/subsystems/mass/flops_based/test/test_distributed_prop.py +++ b/aviary/subsystems/mass/flops_based/test/test_distributed_prop.py @@ -3,8 +3,11 @@ from openmdao.utils.assert_utils import assert_near_equal from aviary.subsystems.mass.flops_based.distributed_prop import ( - distributed_engine_count_factor, distributed_nacelle_diam_factor, - distributed_nacelle_diam_factor_deriv, distributed_thrust_factor) + distributed_engine_count_factor, + distributed_nacelle_diam_factor, + distributed_nacelle_diam_factor_deriv, + distributed_thrust_factor, +) class DistributedPropulsionFactorsTest(unittest.TestCase): @@ -28,11 +31,11 @@ def test_case_dist_thrust(self): for num_eng in [1, 2, 3, 4]: thrust_fact = distributed_thrust_factor(max_thrust, num_eng) - assert_near_equal(thrust_fact, max_thrust/num_eng, tol) + assert_near_equal(thrust_fact, max_thrust / num_eng, tol) num_eng = 5 thrust_fact = distributed_thrust_factor(max_thrust, num_eng) - assert_near_equal(thrust_fact, max_thrust/4.643501108793284, tol) + assert_near_equal(thrust_fact, max_thrust / 4.643501108793284, tol) def test_case_dist_nacelle_diam(self): tol = 1e-12 @@ -44,7 +47,7 @@ def test_case_dist_nacelle_diam(self): num_eng = 5 diam_fact = distributed_nacelle_diam_factor(diam_nacelle, num_eng) - assert_near_equal(diam_fact, diam_nacelle*1.11803398875, tol) + assert_near_equal(diam_fact, diam_nacelle * 1.11803398875, tol) def test_case_dist_nacelle_diam_deriv(self): tol = 1e-12 @@ -58,5 +61,5 @@ def test_case_dist_nacelle_diam_deriv(self): assert_near_equal(diam_fact, 1.11803398875, tol) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_electrical.py b/aviary/subsystems/mass/flops_based/test/test_electrical.py index f9abb531a6..f5b3854683 100644 --- a/aviary/subsystems/mass/flops_based/test/test_electrical.py +++ b/aviary/subsystems/mass/flops_based/test/test_electrical.py @@ -4,149 +4,154 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.electrical import (AltElectricalMass, - ElectricalMass) +from aviary.subsystems.mass.flops_based.electrical import AltElectricalMass, ElectricalMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class ElectricMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "electric_test", - ElectricalMass(aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'electric_test', + ElectricalMass(), promotes_outputs=[ Aircraft.Electrical.MASS, ], promotes_inputs=[ Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Electrical.MASS_SCALER - ] + Aircraft.Electrical.MASS_SCALER, + ], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( self.prob, case_name, - input_keys=[Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Electrical.MASS_SCALER], + input_keys=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Electrical.MASS_SCALER, + ], output_keys=Aircraft.Electrical.MASS, - version=Version.TRANSPORT) + version=Version.TRANSPORT, + ) def test_IO(self): assert_match_varnames(self.prob.model) class ElectricMassTest0(unittest.TestCase): - def setUp(self): self.prob = om.Problem() def test_case(self): - prob = self.prob prob.model.add_subsystem( - "electric_test", - ElectricalMass(aviary_options=get_flops_inputs("N3CC", preprocess=True)), + 'electric_test', + ElectricalMass(), promotes_outputs=[ Aircraft.Electrical.MASS, ], promotes_inputs=[ Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Electrical.MASS_SCALER - ] + Aircraft.Electrical.MASS_SCALER, + ], ) + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( self.prob, - "N3CC", - input_keys=[Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Electrical.MASS_SCALER], + 'AdvancedSingleAisle', + input_keys=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Electrical.MASS_SCALER, + ], output_keys=Aircraft.Electrical.MASS, - version=Version.TRANSPORT) + version=Version.TRANSPORT, + ) prob.list_indep_vars() class ElectricMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.electrical as electrical + electrical.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.electrical as electrical + electrical.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "electric_test", - ElectricalMass(aviary_options=get_flops_inputs("N3CC", preprocess=True)), + 'electric_test', + ElectricalMass(), promotes_outputs=[ Aircraft.Electrical.MASS, ], promotes_inputs=[ Aircraft.Fuselage.LENGTH, Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Electrical.MASS_SCALER - ] + Aircraft.Electrical.MASS_SCALER, + ], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuselage.LENGTH, 100.0, 'ft') prob.set_val(Aircraft.Fuselage.MAX_WIDTH, 12.0, 'ft') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AltElectricMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "electric_test", - AltElectricalMass(aviary_options=get_flops_inputs( - case_name, preprocess=True)), + 'electric_test', + AltElectricalMass(), promotes_outputs=[ Aircraft.Electrical.MASS, ], - promotes_inputs=[ - Aircraft.Electrical.MASS_SCALER - ] + promotes_inputs=[Aircraft.Electrical.MASS_SCALER], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( @@ -154,11 +159,12 @@ def test_case(self, case_name): case_name, input_keys=Aircraft.Electrical.MASS_SCALER, output_keys=Aircraft.Electrical.MASS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_empty_margin.py b/aviary/subsystems/mass/flops_based/test/test_empty_margin.py index 29b45f3fb3..21a1663df5 100644 --- a/aviary/subsystems/mass/flops_based/test/test_empty_margin.py +++ b/aviary/subsystems/mass/flops_based/test/test_empty_margin.py @@ -5,47 +5,51 @@ from aviary.subsystems.mass.flops_based.empty_margin import EmptyMassMargin from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class EmptyMassMarginTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "margin", - EmptyMassMargin(aviary_options=get_flops_inputs(case_name)), + 'margin', + EmptyMassMargin(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Propulsion.MASS, - Aircraft.Design.STRUCTURE_MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS, - Aircraft.Design.EMPTY_MASS_MARGIN_SCALER], + input_keys=[ + Aircraft.Propulsion.MASS, + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS, + Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, + ], output_keys=Aircraft.Design.EMPTY_MASS_MARGIN, tol=1e-3, - atol=2e-11) + atol=2e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_engine.py b/aviary/subsystems/mass/flops_based/test/test_engine.py index 8f249a1621..06ffcb2d2a 100644 --- a/aviary/subsystems/mass/flops_based/test/test_engine.py +++ b/aviary/subsystems/mass/flops_based/test/test_engine.py @@ -8,49 +8,56 @@ from aviary.subsystems.mass.flops_based.engine import EngineMass from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.utils.aviary_values import AviaryValues +from aviary.utils.functions import get_path from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.utils.functions import get_path -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft, Settings class EngineMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "engine_mass", - EngineMass(aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'engine_mass', + EngineMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) + prob.set_val(Aircraft.Engine.MASS_SCALER, val=np.zeros(1)) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Engine.SCALED_SLS_THRUST, - Aircraft.Engine.MASS, - Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_MASS], - output_keys=[Aircraft.Engine.MASS, - Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_MASS], + input_keys=[ + Aircraft.Engine.SCALED_SLS_THRUST, + Aircraft.Engine.MASS, + Aircraft.Engine.ADDITIONAL_MASS, + Aircraft.Propulsion.TOTAL_ENGINE_MASS, + ], + output_keys=[ + Aircraft.Engine.MASS, + Aircraft.Engine.ADDITIONAL_MASS, + Aircraft.Propulsion.TOTAL_ENGINE_MASS, + ], list_inputs=True, list_outputs=True, - rtol=1e-10) + rtol=1e-10, + ) def test_case_2(self): # arbitrary case to trigger both types of scaling equations, multiengine @@ -71,8 +78,7 @@ def test_case_2(self): options.set_val(Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION, 1.0) options.set_val(Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION, 0.08) - options.set_val(Aircraft.Engine.DATA_FILE, get_path( - 'models/engines/turbofan_28k.deck')) + options.set_val(Aircraft.Engine.DATA_FILE, get_path('models/engines/turbofan_28k.csv')) engine = EngineDeck(options=options) options.set_val(Aircraft.Engine.SCALE_MASS, False) engine2 = EngineDeck(name='engine2', options=options) @@ -81,12 +87,27 @@ def test_case_2(self): engine3 = EngineDeck(name='engine3', options=options) preprocess_propulsion(options, [engine, engine2, engine3]) - prob.model.add_subsystem('engine_mass', EngineMass( - aviary_options=options), promotes=['*']) + prob.model.add_subsystem('engine_mass', EngineMass(), promotes=['*']) + + opts = { + Aircraft.Engine.ADDITIONAL_MASS_FRACTION: options.get_val( + Aircraft.Engine.ADDITIONAL_MASS_FRACTION + ), + Aircraft.Engine.NUM_ENGINES: options.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Engine.REFERENCE_MASS: options.get_item(Aircraft.Engine.REFERENCE_MASS), + Aircraft.Engine.REFERENCE_SLS_THRUST: options.get_item( + Aircraft.Engine.REFERENCE_SLS_THRUST + ), + Aircraft.Engine.SCALE_MASS: options.get_val(Aircraft.Engine.SCALE_MASS), + } + + prob.model_options['*'] = opts + prob.setup(force_alloc_complex=True) - prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - np.array([28000.0, 28000.0, 28000.0]), units='lbf') + prob.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, np.array([28000.0, 28000.0, 28000.0]), units='lbf' + ) # Pull value from the processed options. val, units = options.get_item(Aircraft.Engine.MASS_SCALER) prob.set_val(Aircraft.Engine.MASS_SCALER, val, units=units) @@ -99,19 +120,20 @@ def test_case_2(self): mass_expected = np.array([5779.16494294, 6000.0, 5814.38]) total_mass_expected = np.array([35187.08988589]) - additional_mass_expected = np.array([5201.24844865, 5400., 5232.942]) + additional_mass_expected = np.array([5201.24844865, 5400.0, 5232.942]) assert_near_equal(mass, mass_expected, tolerance=1e-10) assert_near_equal(total_mass, total_mass_expected, tolerance=1e-10) assert_near_equal(additional_mass, additional_mass_expected, tolerance=1e-10) partial_data = prob.check_partials( - out_stream=None, compact_print=True, show_only_incorrect=True, method="cs") + out_stream=None, compact_print=True, show_only_incorrect=True, method='cs' + ) assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_engine_controls.py b/aviary/subsystems/mass/flops_based/test/test_engine_controls.py index 9df3af1524..d0b1c1225c 100644 --- a/aviary/subsystems/mass/flops_based/test/test_engine_controls.py +++ b/aviary/subsystems/mass/flops_based/test/test_engine_controls.py @@ -4,38 +4,36 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.engine_controls import \ - TransportEngineCtrlsMass +from aviary.subsystems.mass.flops_based.engine_controls import TransportEngineCtrlsMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class BasicTransportEngineCtrlsTest(unittest.TestCase): - ''' - Test the BasicTransportEngineCtrls component. - ''' + """Test the BasicTransportEngineCtrls component.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(omit='N3CC'), - name_func=print_case) + @parameterized.expand(get_flops_case_names(omit='AdvancedSingleAisle'), name_func=print_case) def test_case(self, case_name): - flops_inputs = get_flops_inputs(case_name, preprocess=True) - prob = self.prob prob.model.add_subsystem( 'engine_ctrls', - TransportEngineCtrlsMass(aviary_options=flops_inputs), + TransportEngineCtrlsMass(), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(force_alloc_complex=True) flops_validation_test( @@ -44,38 +42,41 @@ def test_case(self, case_name): input_keys=[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST], output_keys=Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, atol=2e-12, - excludes=['size_prop.*']) + excludes=['size_prop.*'], + ) def test_IO(self): assert_match_varnames(self.prob.model) class BasicTransportEngineCtrlsTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.engine_controls as control + control.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.engine_controls as control + control.GRAV_ENGLISH_LBM = 1.0 def test_case(self): - flops_inputs = get_flops_inputs("LargeSingleAisle1FLOPS", preprocess=True) prob = om.Problem() prob.model.add_subsystem( 'engine_ctrls', - TransportEngineCtrlsMass(aviary_options=flops_inputs), + TransportEngineCtrlsMass(), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + + prob.model_options['*'] = get_flops_options('LargeSingleAisle1FLOPS', preprocess=True) + prob.setup(force_alloc_complex=True) prob.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 50000.0, 'lbf') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/mass/flops_based/test/test_engine_oil.py b/aviary/subsystems/mass/flops_based/test/test_engine_oil.py index 8ec1239170..e61cb04eb5 100644 --- a/aviary/subsystems/mass/flops_based/test/test_engine_oil.py +++ b/aviary/subsystems/mass/flops_based/test/test_engine_oil.py @@ -4,150 +4,162 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.engine_oil import ( - AltEngineOilMass, TransportEngineOilMass) +from aviary.subsystems.mass.flops_based.engine_oil import AltEngineOilMass, TransportEngineOilMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.variables import Aircraft class TransportEngineOilMassTest(unittest.TestCase): - ''' - Tests transport/GA engine oil mass calculation. - ''' + """Tests transport/GA engine oil mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob - options = get_flops_inputs(case_name) - options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) + options = { + Aircraft.Propulsion.TOTAL_NUM_ENGINES: 2, + } prob.model.add_subsystem( 'engine_oil', - TransportEngineOilMass(aviary_options=options), + TransportEngineOilMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + prob.model_options['*'] = options + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST], + input_keys=[ + Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, + ], output_keys=[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS], version=Version.TRANSPORT, - tol=4.0e-3) + tol=4.0e-3, + ) def test_IO(self): assert_match_varnames(self.prob.model) class TransportEngineOilMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.engine_oil as oil + oil.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.engine_oil as oil + oil.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - options = get_flops_inputs("N3CC") - options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) + + options = { + Aircraft.Propulsion.TOTAL_NUM_ENGINES: 2, + } prob.model.add_subsystem( 'engine_oil', - TransportEngineOilMass(aviary_options=options), + TransportEngineOilMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 50000.0, 'lbf') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AltEngineOilMassTest(unittest.TestCase): - ''' - Tests alternate engine oil mass calculation. - ''' + """Tests alternate engine oil mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob - options = get_flops_inputs(case_name) - options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.CrewPayload.Design.NUM_PASSENGERS: inputs.get_val( + Aircraft.CrewPayload.Design.NUM_PASSENGERS + ), + } prob.model.add_subsystem( - 'engine_oil', - AltEngineOilMass(aviary_options=options), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'engine_oil', AltEngineOilMass(), promotes_outputs=['*'], promotes_inputs=['*'] ) + prob.model_options['*'] = options + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER,], + input_keys=[ + Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, + ], output_keys=[Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS], - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltEngineOilMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.engine_oil as oil + oil.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.engine_oil as oil + oil.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - options = get_flops_inputs("N3CC") - options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2) + + inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + options = { + Aircraft.CrewPayload.Design.NUM_PASSENGERS: inputs.get_val( + Aircraft.CrewPayload.Design.NUM_PASSENGERS + ), + } + prob.model.add_subsystem( - 'engine_oil', - AltEngineOilMass(aviary_options=options), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'engine_oil', AltEngineOilMass(**options), promotes_outputs=['*'], promotes_inputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/mass/flops_based/test/test_engine_pod.py b/aviary/subsystems/mass/flops_based/test/test_engine_pod.py index 7882b71783..cee8550474 100644 --- a/aviary/subsystems/mass/flops_based/test/test_engine_pod.py +++ b/aviary/subsystems/mass/flops_based/test/test_engine_pod.py @@ -1,42 +1,47 @@ -import numpy as np import unittest +import numpy as np import openmdao.api as om -from openmdao.utils.assert_utils import (assert_check_partials, - assert_near_equal) +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import parameterized from aviary.subsystems.mass.flops_based.engine_pod import EnginePodMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.variables import Aircraft class EnginePodMassTest(unittest.TestCase): - ''' - Tests the engine pod mass needed for the detailed wing calculation. - ''' + """Tests the engine pod mass needed for the detailed wing calculation.""" def setUp(self): self.prob = om.Problem() # Only cases that use detailed wing weight. - @parameterized.expand(get_flops_case_names(omit=['LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSalt']), - name_func=print_case) + @parameterized.expand( + get_flops_case_names(omit=['LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSalt']), + name_func=print_case, + ) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + } + prob.model.add_subsystem( - 'engine_pod', - EnginePodMass(aviary_options=get_flops_inputs(case_name, preprocess=True)), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'engine_pod', EnginePodMass(), promotes_outputs=['*'], promotes_inputs=['*'] ) + prob.model_options['*'] = options + prob.setup(check=False, force_alloc_complex=True) # Tol not that tight, but it is unclear where the pod mass values in files come from, @@ -44,33 +49,33 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Electrical.MASS, - Aircraft.Fuel.FUEL_SYSTEM_MASS, - Aircraft.Hydraulics.MASS, - Aircraft.Instruments.MASS, - Aircraft.Nacelle.MASS, - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - Aircraft.Engine.MASS, - Aircraft.Propulsion.TOTAL_STARTER_MASS, - Aircraft.Engine.THRUST_REVERSERS_MASS, - Aircraft.Engine.SCALED_SLS_THRUST, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST], + input_keys=[ + Aircraft.Electrical.MASS, + Aircraft.Fuel.FUEL_SYSTEM_MASS, + Aircraft.Hydraulics.MASS, + Aircraft.Instruments.MASS, + Aircraft.Nacelle.MASS, + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, + Aircraft.Engine.MASS, + Aircraft.Propulsion.TOTAL_STARTER_MASS, + Aircraft.Engine.THRUST_REVERSERS_MASS, + Aircraft.Engine.SCALED_SLS_THRUST, + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, + ], output_keys=Aircraft.Engine.POD_MASS, - tol=3e-3) + tol=3e-3, + ) def test_case_multiengine(self): # test with multiple engine types prob = self.prob - aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 2, 3])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 7) + options = { + Aircraft.Engine.NUM_ENGINES: np.array([2, 2, 3]), + } prob.model.add_subsystem( - 'engine_pod', - EnginePodMass(aviary_options=aviary_options), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'engine_pod', EnginePodMass(**options), promotes_outputs=['*'], promotes_inputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) @@ -78,18 +83,17 @@ def test_case_multiengine(self): prob.set_val(Aircraft.Nacelle.MASS, val=np.array([100, 30, 95])) prob.set_val(Aircraft.Engine.MASS, val=np.array([410, 45, 315])) prob.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS, val=np.array([130, 0, 60])) - prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - val=np.array([36000, 22500, 18000])) + prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, val=np.array([36000, 22500, 18000])) prob.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=189000.0) prob.run_model() mass = prob.get_val(Aircraft.Engine.POD_MASS) - expected_mass = np.array([525., 60., 362.14285714]) + expected_mass = np.array([525.0, 60.0, 362.14285714]) assert_near_equal(mass, expected_mass, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_IO(self): diff --git a/aviary/subsystems/mass/flops_based/test/test_fin.py b/aviary/subsystems/mass/flops_based/test/test_fin.py index 095ce75c24..010a6881e6 100644 --- a/aviary/subsystems/mass/flops_based/test/test_fin.py +++ b/aviary/subsystems/mass/flops_based/test/test_fin.py @@ -13,71 +13,81 @@ # TODO - None of the flops cases have any fins. fin_test_data = {} -fin_test_data['1'] = AviaryValues({ - Aircraft.Fins.NUM_FINS: (1, 'unitless'), - Mission.Design.GROSS_MASS: (100000, 'lbm'), - Aircraft.Fins.TAPER_RATIO: (0.3300, 'unitless'), - Aircraft.Fins.AREA: (250.00, 'ft**2'), - Aircraft.Fins.MASS_SCALER: (1.0, 'unitless'), - Aircraft.Fins.MASS: (917.228, 'lbm') -}) +fin_test_data['1'] = AviaryValues( + { + Aircraft.Fins.NUM_FINS: (1, 'unitless'), + Mission.Design.GROSS_MASS: (100000, 'lbm'), + Aircraft.Fins.TAPER_RATIO: (0.3300, 'unitless'), + Aircraft.Fins.AREA: (250.00, 'ft**2'), + Aircraft.Fins.MASS_SCALER: (1.0, 'unitless'), + Aircraft.Fins.MASS: (917.228, 'lbm'), + } +) fin_data_sets = [key for key in fin_test_data] class FinMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(fin_data_sets, - name_func=print_case) + @parameterized.expand(fin_data_sets, name_func=print_case) def test_case(self, case_name): validation_data = fin_test_data[case_name] prob = self.prob + options = { + Aircraft.Fins.NUM_FINS: 1, + } prob.model.add_subsystem( - "fin", - FinMass(aviary_options=validation_data), + 'fin', + FinMass(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=validation_data, - output_validation_data=validation_data, - input_keys=[Mission.Design.GROSS_MASS, - Aircraft.Fins.TAPER_RATIO, - Aircraft.Fins.AREA, - Aircraft.Fins.MASS_SCALER], - output_keys=Aircraft.Fins.MASS) + do_validation_test( + prob, + case_name, + input_validation_data=validation_data, + output_validation_data=validation_data, + input_keys=[ + Mission.Design.GROSS_MASS, + Aircraft.Fins.TAPER_RATIO, + Aircraft.Fins.AREA, + Aircraft.Fins.MASS_SCALER, + ], + output_keys=Aircraft.Fins.MASS, + ) def test_IO(self): assert_match_varnames(self.prob.model) class FinMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.fin as fin + fin.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.fin as fin + fin.GRAV_ENGLISH_LBM = 1.0 def test_case(self): - validation_data = fin_test_data["1"] prob = om.Problem() + + options = { + Aircraft.Fins.NUM_FINS: 1, + } prob.model.add_subsystem( - "fin", - FinMass(aviary_options=validation_data), + 'fin', + FinMass(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -87,9 +97,9 @@ def test_case(self): prob.set_val(Aircraft.Fins.AREA, 250.0, 'ft**2') prob.set_val(Aircraft.Fins.MASS, 1000.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_fuel_capacity.py b/aviary/subsystems/mass/flops_based/test/test_fuel_capacity.py index 1e2b94ad36..a0a6db7b53 100644 --- a/aviary/subsystems/mass/flops_based/test/test_fuel_capacity.py +++ b/aviary/subsystems/mass/flops_based/test/test_fuel_capacity.py @@ -4,38 +4,38 @@ from parameterized import parameterized from aviary.subsystems.mass.flops_based.fuel_capacity import ( - AuxFuelCapacity, FuelCapacityGroup, FuselageFuelCapacity, - TotalFuelCapacity, WingFuelCapacity) + AuxFuelCapacity, + FuelCapacityGroup, + FuselageFuelCapacity, + TotalFuelCapacity, + WingFuelCapacity, +) from aviary.utils.aviary_values import AviaryValues from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (do_validation_test, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + do_validation_test, + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.functions import override_aviary_vars from aviary.variable_info.variables import Aircraft class FuelCapacityGroupTest(unittest.TestCase): - - @parameterized.expand(get_flops_case_names(only=['N3CC']), - name_func=print_case) + @parameterized.expand(get_flops_case_names(only=['AdvancedSingleAisle']), name_func=print_case) def test_case(self, case_name): - class PreMission(om.Group): - def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='Aircraft options dictionary') + 'aviary_options', types=AviaryValues, desc='Aircraft options dictionary' + ) def setup(self): - aviary_options = self.options['aviary_options'] - self.add_subsystem( 'fuel_capacity_group', - FuelCapacityGroup(aviary_options=aviary_options), + FuelCapacityGroup(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -48,7 +48,7 @@ def configure(self): prob = om.Problem() prob.model.add_subsystem( - "premission", + 'premission', PreMission(aviary_options=get_flops_inputs(case_name)), promotes_outputs=['*'], promotes_inputs=['*'], @@ -59,132 +59,132 @@ def configure(self): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - Aircraft.Fuel.CAPACITY_FACTOR, - Aircraft.Fuel.DENSITY_RATIO, - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, - Aircraft.Wing.AREA, - Aircraft.Wing.SPAN, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD], + input_keys=[ + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, + Aircraft.Fuel.WING_FUEL_FRACTION, + Aircraft.Fuel.DENSITY, + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, + Aircraft.Wing.AREA, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD, + ], output_keys=Aircraft.Fuel.TOTAL_CAPACITY, atol=1e-10, - rtol=1e-10) + rtol=1e-10, + ) wing_capacity_data = {} -wing_capacity_data['1'] = AviaryValues({ - Aircraft.Fuel.DENSITY_RATIO: (1.2, 'unitless'), - Aircraft.Fuel.WING_REF_CAPACITY: (30.0, 'lbm'), - Aircraft.Fuel.WING_REF_CAPACITY_AREA: (200.0, 'unitless'), - Aircraft.Fuel.WING_REF_CAPACITY_TERM_B: (1.3, 'unitless'), - Aircraft.Fuel.CAPACITY_FACTOR: (1.0, 'unitless'), - Aircraft.Wing.AREA: (150.0, 'ft**2'), - Aircraft.Wing.SPAN: (17.0, 'ft'), - Aircraft.Wing.TAPER_RATIO: (1.5, 'unitless'), - Aircraft.Wing.THICKNESS_TO_CHORD: (0.33, 'unitless'), - Aircraft.Fuel.WING_REF_CAPACITY_TERM_A: (-100.0, 'unitless') -}) -wing_capacity_data['2'] = AviaryValues({ - Aircraft.Fuel.DENSITY_RATIO: (1.2, 'unitless'), - Aircraft.Fuel.WING_REF_CAPACITY: (30.0, 'lbm'), - Aircraft.Fuel.WING_REF_CAPACITY_AREA: (200.0, 'unitless'), - Aircraft.Fuel.WING_REF_CAPACITY_TERM_B: (1.3, 'unitless'), - Aircraft.Fuel.CAPACITY_FACTOR: (1.0, 'unitless'), - Aircraft.Wing.AREA: (150.0, 'ft**2'), - Aircraft.Wing.SPAN: (17.0, 'ft'), - Aircraft.Wing.TAPER_RATIO: (1.5, 'unitless'), - Aircraft.Wing.THICKNESS_TO_CHORD: (0.33, 'unitless'), - Aircraft.Fuel.WING_REF_CAPACITY_TERM_A: (1.2, 'unitless') -}) +wing_capacity_data['1'] = AviaryValues( + { + Aircraft.Fuel.DENSITY: (8.04, 'lbm/galUS'), + Aircraft.Fuel.WING_REF_CAPACITY: (30.0, 'lbm'), + Aircraft.Fuel.WING_REF_CAPACITY_AREA: (200.0, 'unitless'), + Aircraft.Fuel.WING_REF_CAPACITY_TERM_B: (1.3, 'unitless'), + Aircraft.Fuel.WING_FUEL_FRACTION: (0.7752, 'unitless'), + Aircraft.Wing.AREA: (150.0, 'ft**2'), + Aircraft.Wing.SPAN: (17.0, 'ft'), + Aircraft.Wing.TAPER_RATIO: (1.5, 'unitless'), + Aircraft.Wing.THICKNESS_TO_CHORD: (0.33, 'unitless'), + Aircraft.Fuel.WING_REF_CAPACITY_TERM_A: (-100.0, 'unitless'), + } +) +wing_capacity_data['2'] = AviaryValues( + { + Aircraft.Fuel.DENSITY: (8.04, 'lbm/galUS'), + Aircraft.Fuel.WING_REF_CAPACITY: (30.0, 'lbm'), + Aircraft.Fuel.WING_REF_CAPACITY_AREA: (200.0, 'unitless'), + Aircraft.Fuel.WING_REF_CAPACITY_TERM_B: (1.3, 'unitless'), + Aircraft.Fuel.WING_FUEL_FRACTION: (0.7752, 'unitless'), + Aircraft.Wing.AREA: (150.0, 'ft**2'), + Aircraft.Wing.SPAN: (17.0, 'ft'), + Aircraft.Wing.TAPER_RATIO: (1.5, 'unitless'), + Aircraft.Wing.THICKNESS_TO_CHORD: (0.33, 'unitless'), + Aircraft.Fuel.WING_REF_CAPACITY_TERM_A: (1.2, 'unitless'), + } +) wing_capacity_cases = [key for key in wing_capacity_data] class WingFuelCapacityTest(unittest.TestCase): - - @parameterized.expand(wing_capacity_cases, - name_func=print_case) + @parameterized.expand(wing_capacity_cases, name_func=print_case) def test_derivs(self, case_name): validation_data = wing_capacity_data[case_name] prob = om.Problem() - prob.model.add_subsystem( - 'comp', - WingFuelCapacity(), - promotes=['*'] - ) + prob.model.add_subsystem('comp', WingFuelCapacity(), promotes=['*']) prob.setup(force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=validation_data, - output_validation_data=validation_data, - input_keys=[ - Aircraft.Fuel.DENSITY_RATIO, - Aircraft.Fuel.WING_REF_CAPACITY, - Aircraft.Fuel.WING_REF_CAPACITY_AREA, - Aircraft.Fuel.WING_REF_CAPACITY_TERM_B, - Aircraft.Fuel.CAPACITY_FACTOR, - Aircraft.Wing.AREA, - Aircraft.Wing.SPAN, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Fuel.WING_REF_CAPACITY_TERM_A - ], - output_keys=Aircraft.Fuel.WING_FUEL_CAPACITY, - atol=1e-10, - # TODO: No wing fuel capacity validation data, check only partials - check_values=False) + do_validation_test( + prob, + case_name, + input_validation_data=validation_data, + output_validation_data=validation_data, + input_keys=[ + Aircraft.Fuel.DENSITY, + Aircraft.Fuel.WING_REF_CAPACITY, + Aircraft.Fuel.WING_REF_CAPACITY_AREA, + Aircraft.Fuel.WING_REF_CAPACITY_TERM_B, + Aircraft.Fuel.WING_FUEL_FRACTION, + Aircraft.Wing.AREA, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Fuel.WING_REF_CAPACITY_TERM_A, + ], + output_keys=Aircraft.Fuel.WING_FUEL_CAPACITY, + atol=1e-10, + # TODO: No wing fuel capacity validation data, check only partials + check_values=False, + ) fuse_capacity_data = {} -fuse_capacity_data['1'] = AviaryValues({ - Aircraft.Fuel.TOTAL_CAPACITY: (100.0, 'lbm'), - Aircraft.Fuel.WING_FUEL_CAPACITY: (73.0, 'lbm'), - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY: (27.0, 'lbm') -}) +fuse_capacity_data['1'] = AviaryValues( + { + Aircraft.Fuel.TOTAL_CAPACITY: (100.0, 'lbm'), + Aircraft.Fuel.WING_FUEL_CAPACITY: (73.0, 'lbm'), + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY: (27.0, 'lbm'), + } +) fuse_capacity_cases = [key for key in fuse_capacity_data] class FuselageFuelCapacityTest(unittest.TestCase): - - @parameterized.expand(fuse_capacity_cases, - name_func=print_case) + @parameterized.expand(fuse_capacity_cases, name_func=print_case) def test_basic(self, case_name): validation_data = fuse_capacity_data[case_name] prob = om.Problem() - prob.model.add_subsystem( - 'fuel', - FuselageFuelCapacity(), - promotes=['*'] - ) + prob.model.add_subsystem('fuel', FuselageFuelCapacity(), promotes=['*']) prob.setup(force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=validation_data, - output_validation_data=validation_data, - input_keys=[ - Aircraft.Fuel.TOTAL_CAPACITY, - Aircraft.Fuel.WING_FUEL_CAPACITY - ], - output_keys=Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, - tol=1.0e-10, - atol=1e-10) + do_validation_test( + prob, + case_name, + input_validation_data=validation_data, + output_validation_data=validation_data, + input_keys=[Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Fuel.WING_FUEL_CAPACITY], + output_keys=Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, + tol=1.0e-10, + atol=1e-10, + ) aux_capacity_data = {} -aux_capacity_data['1'] = AviaryValues({ - Aircraft.Fuel.TOTAL_CAPACITY: (100.0, 'lbm'), - Aircraft.Fuel.WING_FUEL_CAPACITY: (25.0, 'lbm'), - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY: (33.0, 'lbm'), - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY: (42.0, 'lbm') -}) +aux_capacity_data['1'] = AviaryValues( + { + Aircraft.Fuel.TOTAL_CAPACITY: (100.0, 'lbm'), + Aircraft.Fuel.WING_FUEL_CAPACITY: (25.0, 'lbm'), + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY: (33.0, 'lbm'), + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY: (42.0, 'lbm'), + } +) aux_capacity_cases = [key for key in aux_capacity_data] @@ -193,44 +193,43 @@ class AuxFuelCapacityTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(aux_capacity_cases, - name_func=print_case) + @parameterized.expand(aux_capacity_cases, name_func=print_case) def test_basic(self, case_name): validation_data = aux_capacity_data[case_name] prob = self.prob - prob.model.add_subsystem( - 'fuel', - AuxFuelCapacity(), - promotes=['*'] - ) + prob.model.add_subsystem('fuel', AuxFuelCapacity(), promotes=['*']) prob.setup(force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=validation_data, - output_validation_data=validation_data, - input_keys=[ - Aircraft.Fuel.TOTAL_CAPACITY, - Aircraft.Fuel.WING_FUEL_CAPACITY, - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY - ], - output_keys=Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - tol=1.0e-10, - atol=1e-10) + do_validation_test( + prob, + case_name, + input_validation_data=validation_data, + output_validation_data=validation_data, + input_keys=[ + Aircraft.Fuel.TOTAL_CAPACITY, + Aircraft.Fuel.WING_FUEL_CAPACITY, + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, + ], + output_keys=Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, + tol=1.0e-10, + atol=1e-10, + ) def test_IO(self): assert_match_varnames(self.prob.model) total_capacity_data = {} -total_capacity_data['1'] = AviaryValues({ - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY: (100.0, 'lbm'), - Aircraft.Fuel.WING_FUEL_CAPACITY: (25.0, 'lbm'), - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY: (33.0, 'lbm'), - Aircraft.Fuel.TOTAL_CAPACITY: (158.0, 'lbm') -}) +total_capacity_data['1'] = AviaryValues( + { + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY: (100.0, 'lbm'), + Aircraft.Fuel.WING_FUEL_CAPACITY: (25.0, 'lbm'), + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY: (33.0, 'lbm'), + Aircraft.Fuel.TOTAL_CAPACITY: (158.0, 'lbm'), + } +) total_capacity_cases = [key for key in total_capacity_data] @@ -239,36 +238,33 @@ class TotalFuelCapacityTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(total_capacity_cases, - name_func=print_case) + @parameterized.expand(total_capacity_cases, name_func=print_case) def test_basic(self, case_name): validation_data = total_capacity_data[case_name] prob = self.prob - prob.model.add_subsystem( - 'fuel', - TotalFuelCapacity(), - promotes=['*'] - ) + prob.model.add_subsystem('fuel', TotalFuelCapacity(), promotes=['*']) prob.setup(force_alloc_complex=True) - do_validation_test(prob, - case_name, - input_validation_data=validation_data, - output_validation_data=validation_data, - input_keys=[ - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - Aircraft.Fuel.WING_FUEL_CAPACITY, - Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY - ], - output_keys=Aircraft.Fuel.TOTAL_CAPACITY, - tol=1.0e-10, - atol=1e-10) + do_validation_test( + prob, + case_name, + input_validation_data=validation_data, + output_validation_data=validation_data, + input_keys=[ + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, + Aircraft.Fuel.WING_FUEL_CAPACITY, + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, + ], + output_keys=Aircraft.Fuel.TOTAL_CAPACITY, + tol=1.0e-10, + atol=1e-10, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_fuel_system.py b/aviary/subsystems/mass/flops_based/test/test_fuel_system.py index c1c0f9dd82..f4d7f2a301 100644 --- a/aviary/subsystems/mass/flops_based/test/test_fuel_system.py +++ b/aviary/subsystems/mass/flops_based/test/test_fuel_system.py @@ -4,34 +4,40 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.fuel_system import (AltFuelSystemMass, - TransportFuelSystemMass) +from aviary.subsystems.mass.flops_based.fuel_system import ( + AltFuelSystemMass, + TransportFuelSystemMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) -from aviary.variable_info.variables import Aircraft +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) +from aviary.variable_info.variables import Aircraft, Mission class AltFuelSystemTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Fuel.NUM_TANKS: inputs.get_val(Aircraft.Fuel.NUM_TANKS), + } + prob.model.add_subsystem( - "alt_fuel_sys_test", - AltFuelSystemMass(aviary_options=get_flops_inputs( - case_name, preprocess=True)), + 'alt_fuel_sys_test', + AltFuelSystemMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) @@ -39,61 +45,72 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, - Aircraft.Fuel.TOTAL_CAPACITY], + input_keys=[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, Aircraft.Fuel.TOTAL_CAPACITY], output_keys=Aircraft.Fuel.FUEL_SYSTEM_MASS, - version=Version.ALTERNATE,) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltFuelSystemTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.fuel_system as fuel + fuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.fuel_system as fuel + fuel.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() + + inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + options = { + Aircraft.Fuel.NUM_TANKS: inputs.get_val(Aircraft.Fuel.NUM_TANKS), + } + prob.model.add_subsystem( - "alt_fuel_sys_test", - AltFuelSystemMass(aviary_options=get_flops_inputs( - "N3CC", preprocess=True)), + 'alt_fuel_sys_test', + AltFuelSystemMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 100.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class TransportFuelSystemTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Propulsion.TOTAL_NUM_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_ENGINES + ), + Mission.Constraints.MAX_MACH: inputs.get_val(Mission.Constraints.MAX_MACH), + } + prob.model.add_subsystem( - "transport_fuel_sys_test", - TransportFuelSystemMass( - aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'transport_fuel_sys_test', + TransportFuelSystemMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) @@ -101,44 +118,53 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, - Aircraft.Fuel.TOTAL_CAPACITY], + input_keys=[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, Aircraft.Fuel.TOTAL_CAPACITY], output_keys=Aircraft.Fuel.FUEL_SYSTEM_MASS, version=Version.TRANSPORT, - tol=8.0e-4) + tol=8.0e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) class TransportFuelSystemTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.fuel_system as fuel + fuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.fuel_system as fuel + fuel.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() + + inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + options = { + Aircraft.Propulsion.TOTAL_NUM_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_ENGINES + ), + Mission.Constraints.MAX_MACH: inputs.get_val(Mission.Constraints.MAX_MACH), + } + prob.model.add_subsystem( - "transport_fuel_sys_test", - TransportFuelSystemMass( - aviary_options=get_flops_inputs("N3CC", preprocess=True)), + 'transport_fuel_sys_test', + TransportFuelSystemMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 100.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_furnishings.py b/aviary/subsystems/mass/flops_based/test/test_furnishings.py index b6885b17bd..8b5d236749 100644 --- a/aviary/subsystems/mass/flops_based/test/test_furnishings.py +++ b/aviary/subsystems/mass/flops_based/test/test_furnishings.py @@ -2,84 +2,103 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials +from openmdao.utils.testing_utils import use_tempdirs from parameterized import parameterized from aviary.subsystems.mass.flops_based.furnishings import ( - AltFurnishingsGroupMass, AltFurnishingsGroupMassBase, - BWBFurnishingsGroupMass, TransportFurnishingsGroupMass) + AltFurnishingsGroupMass, + AltFurnishingsGroupMassBase, + BWBFurnishingsGroupMass, + TransportFurnishingsGroupMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) -from aviary.variable_info.variables import Aircraft, Mission - - +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + get_flops_options, + print_case, +) +from aviary.variable_info.variables import Aircraft + + +@use_tempdirs class TransportFurnishingsGroupMassTest(unittest.TestCase): - ''' - Tests transport/GA furnishings mass calculation. - ''' + """Tests transport/GA furnishings mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( 'furnishings', - TransportFurnishingsGroupMass( - aviary_options=get_flops_inputs(case_name, preprocess=True)), + TransportFurnishingsGroupMass(), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Furnishings.MASS_SCALER, - Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Fuselage.MAX_HEIGHT], + input_keys=[ + Aircraft.Furnishings.MASS_SCALER, + Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Fuselage.MAX_HEIGHT, + ], output_keys=Aircraft.Furnishings.MASS, - version=Version.TRANSPORT) + version=Version.TRANSPORT, + ) def test_IO(self): assert_match_varnames(self.prob.model) +@use_tempdirs class BWBFurnishingsGroupMassTest(unittest.TestCase): - ''' - Tests BWB furnishings mass calculation. - ''' + """Tests BWB furnishings mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob flops_inputs = get_flops_inputs(case_name, preprocess=True) - flops_inputs.update({ - Aircraft.Fuselage.MILITARY_CARGO_FLOOR: (False, 'unitless'), - Aircraft.BWB.NUM_BAYS: (5, 'unitless') - }) + + opts = { + Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS: flops_inputs.get_val( + Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS + ), + Aircraft.CrewPayload.NUM_FLIGHT_CREW: flops_inputs.get_val( + Aircraft.CrewPayload.NUM_FLIGHT_CREW + ), + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS: flops_inputs.get_val( + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS + ), + Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS: flops_inputs.get_val( + Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS + ), + Aircraft.Fuselage.MILITARY_CARGO_FLOOR: False, + } prob.model.add_subsystem( 'furnishings', - BWBFurnishingsGroupMass(aviary_options=flops_inputs), + BWBFurnishingsGroupMass(**opts), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) # TODO: add FLOPS tests cases with BWB furnishings mass calculations @@ -87,17 +106,20 @@ def test_case(self, case_name): # These inputs aren't in the FLOPS input data so we'll give dummy values here, # instead of trying to transfer them from the FLOPS input data. The test # case will only check the partials. - prob.set_val(Aircraft.BWB.CABIN_AREA, 1000.0, units='ft**2') + prob.set_val(Aircraft.Fuselage.CABIN_AREA, 1000.0, units='ft**2') prob.set_val(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 30.0, units='deg') + prob.set_val(Aircraft.BWB.NUM_BAYS, 5.0, units='unitless') flops_validation_test( prob, case_name, - input_keys=[Aircraft.Furnishings.MASS_SCALER, - # Aircraft.BWB.CABIN_AREA, - # Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Fuselage.MAX_HEIGHT], + input_keys=[ + Aircraft.Furnishings.MASS_SCALER, + # Aircraft.Fuselage.CABIN_AREA, + # Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Fuselage.MAX_HEIGHT, + ], output_keys=Aircraft.AirConditioning.MASS, version=Version.BWB, tol=1.0e-3, @@ -109,60 +131,77 @@ def test_IO(self): assert_match_varnames(self.prob.model) +@use_tempdirs class BWBFurnishingsGroupMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.furnishings as furnishings + furnishings.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.furnishings as furnishings + furnishings.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - flops_inputs = get_flops_inputs("N3CC", preprocess=True) - flops_inputs.update({ - Aircraft.Fuselage.MILITARY_CARGO_FLOOR: (False, 'unitless'), - Aircraft.BWB.NUM_BAYS: (5, 'unitless') - }) + + flops_inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + opts = { + Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS: flops_inputs.get_val( + Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS + ), + Aircraft.CrewPayload.NUM_FLIGHT_CREW: flops_inputs.get_val( + Aircraft.CrewPayload.NUM_FLIGHT_CREW + ), + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS: flops_inputs.get_val( + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS + ), + Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS: flops_inputs.get_val( + Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS + ), + Aircraft.Fuselage.MILITARY_CARGO_FLOOR: False, + } + prob.model.add_subsystem( 'furnishings', - BWBFurnishingsGroupMass(aviary_options=flops_inputs), + BWBFurnishingsGroupMass(**opts), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=100.0, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.MAX_WIDTH, val=30.0, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.MAX_HEIGHT, val=15.0, units='ft') + prob.model.set_input_defaults(Aircraft.BWB.NUM_BAYS, 5.0, units='unitless') prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) +@use_tempdirs class AltFurnishingsGroupMassBaseTest(unittest.TestCase): - ''' - Tests alternate base furnishings mass calculation. - ''' + """Tests alternate base furnishings mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( 'furnishings', - AltFurnishingsGroupMassBase( - aviary_options=get_flops_inputs(case_name, preprocess=True)), + AltFurnishingsGroupMassBase(), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( @@ -170,45 +209,44 @@ def test_case(self, case_name): case_name, input_keys=Aircraft.Furnishings.MASS_SCALER, output_keys=Aircraft.Furnishings.MASS_BASE, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) +@use_tempdirs class AltFurnishingsGroupMassTest(unittest.TestCase): - ''' - Tests alternate furnishings mass calculation. - ''' + """Tests alternate furnishings mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - 'furnishings', - AltFurnishingsGroupMass( - aviary_options=get_flops_inputs(case_name, preprocess=True)), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'furnishings', AltFurnishingsGroupMass(), promotes_outputs=['*'], promotes_inputs=['*'] ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Furnishings.MASS_BASE, - Aircraft.Design.STRUCTURE_MASS, - Aircraft.Propulsion.MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE], + input_keys=[ + Aircraft.Furnishings.MASS_BASE, + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Propulsion.MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, + ], output_keys=Aircraft.Furnishings.MASS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) diff --git a/aviary/subsystems/mass/flops_based/test/test_fuselage.py b/aviary/subsystems/mass/flops_based/test/test_fuselage.py index e9bda3a9d9..25595ccd2e 100644 --- a/aviary/subsystems/mass/flops_based/test/test_fuselage.py +++ b/aviary/subsystems/mass/flops_based/test/test_fuselage.py @@ -4,96 +4,97 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.fuselage import (AltFuselageMass, - TransportFuselageMass) +from aviary.subsystems.mass.flops_based.fuselage import AltFuselageMass, TransportFuselageMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class FuselageMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "fuselage", - TransportFuselageMass(aviary_options=get_flops_inputs( - case_name, preprocess=True)), + 'fuselage', + TransportFuselageMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Fuselage.MASS_SCALER], + input_keys=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.MASS_SCALER, + ], output_keys=Aircraft.Fuselage.MASS, version=Version.TRANSPORT, - atol=1e-10) + atol=1e-10, + ) def test_IO(self): assert_match_varnames(self.prob.model) class FuselageMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.fuselage as fuselage + fuselage.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.fuselage as fuselage + fuselage.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "fuselage", - TransportFuselageMass(aviary_options=get_flops_inputs( - "N3CC", preprocess=True)), + 'fuselage', + TransportFuselageMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuselage.LENGTH, 100.0, 'ft') prob.set_val(Aircraft.Fuselage.AVG_DIAMETER, 10.0, 'ft') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) class AltFuselageMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "fuselage", - AltFuselageMass(aviary_options=get_flops_inputs(case_name)), + 'fuselage', + AltFuselageMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -103,35 +104,38 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuselage.MASS_SCALER, - Aircraft.Fuselage.WETTED_AREA, - Aircraft.Fuselage.MAX_HEIGHT, - Aircraft.Fuselage.MAX_WIDTH], + input_keys=[ + Aircraft.Fuselage.MASS_SCALER, + Aircraft.Fuselage.WETTED_AREA, + Aircraft.Fuselage.MAX_HEIGHT, + Aircraft.Fuselage.MAX_WIDTH, + ], output_keys=Aircraft.Fuselage.MASS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltFuselageMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.fuselage as fuselage + fuselage.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.fuselage as fuselage + fuselage.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "fuselage", - AltFuselageMass(aviary_options=get_flops_inputs("N3CC")), + 'fuselage', + AltFuselageMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -140,9 +144,9 @@ def test_case(self): prob.set_val(Aircraft.Fuselage.MAX_HEIGHT, 15.0, 'ft') prob.set_val(Aircraft.Fuselage.MAX_WIDTH, 15.0, 'ft') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_horizontail_tail.py b/aviary/subsystems/mass/flops_based/test/test_horizontail_tail.py index 2269d0aeca..13eed03397 100644 --- a/aviary/subsystems/mass/flops_based/test/test_horizontail_tail.py +++ b/aviary/subsystems/mass/flops_based/test/test_horizontail_tail.py @@ -4,31 +4,31 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.horizontal_tail import (AltHorizontalTailMass, - HorizontalTailMass) +from aviary.subsystems.mass.flops_based.horizontal_tail import ( + AltHorizontalTailMass, + HorizontalTailMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class ExplicitHorizontalTailMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "horizontal_tail", - HorizontalTailMass(aviary_options=get_flops_inputs(case_name)), + 'horizontal_tail', + HorizontalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -38,36 +38,39 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.HorizontalTail.AREA, - Aircraft.HorizontalTail.TAPER_RATIO, - Mission.Design.GROSS_MASS, - Aircraft.HorizontalTail.MASS_SCALER], + input_keys=[ + Aircraft.HorizontalTail.AREA, + Aircraft.HorizontalTail.TAPER_RATIO, + Mission.Design.GROSS_MASS, + Aircraft.HorizontalTail.MASS_SCALER, + ], output_keys=Aircraft.HorizontalTail.MASS, version=Version.TRANSPORT, - tol=2.0e-4) + tol=2.0e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) class ExplicitHorizontalTailMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.horizontal_tail as htail + htail.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.horizontal_tail as htail + htail.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "horizontal_tail", - HorizontalTailMass(aviary_options=get_flops_inputs("N3CC")), + 'horizontal_tail', + HorizontalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -76,24 +79,21 @@ def test_case(self): prob.set_val(Aircraft.HorizontalTail.TAPER_RATIO, 10.0, 'unitless') prob.set_val(Mission.Design.GROSS_MASS, 1000.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class ExplicitAltHorizontalTailMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "horizontal_tail", - AltHorizontalTailMass(aviary_options=get_flops_inputs(case_name)), + 'horizontal_tail', + AltHorizontalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -103,42 +103,42 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.HorizontalTail.AREA, - Aircraft.HorizontalTail.MASS_SCALER], + input_keys=[Aircraft.HorizontalTail.AREA, Aircraft.HorizontalTail.MASS_SCALER], output_keys=Aircraft.HorizontalTail.MASS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class ExplicitAltHorizontalTailMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.horizontal_tail as htail + htail.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.horizontal_tail as htail + htail.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "horizontal_tail", - AltHorizontalTailMass(aviary_options=get_flops_inputs("N3CC")), + 'horizontal_tail', + AltHorizontalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.HorizontalTail.AREA, 10.0, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_hydraulics.py b/aviary/subsystems/mass/flops_based/test/test_hydraulics.py index 2ce70522d7..465f1cfe46 100644 --- a/aviary/subsystems/mass/flops_based/test/test_hydraulics.py +++ b/aviary/subsystems/mass/flops_based/test/test_hydraulics.py @@ -4,37 +4,48 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.hydraulics import (AltHydraulicsGroupMass, - TransportHydraulicsGroupMass) +from aviary.subsystems.mass.flops_based.hydraulics import ( + AltHydraulicsGroupMass, + TransportHydraulicsGroupMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class TransportHydraulicsGroupMassTest(unittest.TestCase): - ''' - Tests transport/GA hydraulics mass calculation. - ''' + """Tests transport/GA hydraulics mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Mission.Constraints.MAX_MACH: inputs.get_val(Mission.Constraints.MAX_MACH), + } + prob.model.add_subsystem( 'hydraulics', - TransportHydraulicsGroupMass( - aviary_options=get_flops_inputs(case_name, preprocess=True)), + TransportHydraulicsGroupMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) @@ -42,70 +53,77 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuselage.PLANFORM_AREA, - Aircraft.Hydraulics.SYSTEM_PRESSURE, - Aircraft.Hydraulics.MASS_SCALER, - Aircraft.Wing.AREA, - Aircraft.Wing.VAR_SWEEP_MASS_PENALTY], + input_keys=[ + Aircraft.Fuselage.PLANFORM_AREA, + Aircraft.Hydraulics.SYSTEM_PRESSURE, + Aircraft.Hydraulics.MASS_SCALER, + Aircraft.Wing.AREA, + Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, + ], output_keys=Aircraft.Hydraulics.MASS, version=Version.TRANSPORT, - tol=4.0e-4) + tol=4.0e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) class TransportHydraulicsGroupMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.hydraulics as hydraulics + hydraulics.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.hydraulics as hydraulics + hydraulics.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() + + inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + options = { + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Mission.Constraints.MAX_MACH: inputs.get_val(Mission.Constraints.MAX_MACH), + } + prob.model.add_subsystem( 'hydraulics', - TransportHydraulicsGroupMass( - aviary_options=get_flops_inputs("N3CC", preprocess=True)), + TransportHydraulicsGroupMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuselage.PLANFORM_AREA, 1500.0, 'ft**2') prob.set_val(Aircraft.Hydraulics.SYSTEM_PRESSURE, 5000.0, 'psi') prob.set_val(Aircraft.Wing.AREA, 1000.0, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AltHydraulicsGroupMassTest(unittest.TestCase): - ''' - Tests alternate hydraulics mass calculation. - ''' + """Tests alternate hydraulics mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - 'hydraulics', - AltHydraulicsGroupMass( - aviary_options=get_flops_inputs(case_name, preprocess=True)), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'hydraulics', AltHydraulicsGroupMass(), promotes_outputs=['*'], promotes_inputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) @@ -113,39 +131,38 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.AREA, - Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - Aircraft.VerticalTail.AREA, - Aircraft.Hydraulics.MASS_SCALER], + input_keys=[ + Aircraft.Wing.AREA, + Aircraft.HorizontalTail.WETTED_AREA, + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, + Aircraft.VerticalTail.AREA, + Aircraft.Hydraulics.MASS_SCALER, + ], output_keys=Aircraft.Hydraulics.MASS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltHydraulicsGroupMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.hydraulics as hydraulics + hydraulics.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.hydraulics as hydraulics + hydraulics.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - 'hydraulics', - AltHydraulicsGroupMass( - aviary_options=get_flops_inputs("N3CC", preprocess=True)), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'hydraulics', AltHydraulicsGroupMass(), promotes_outputs=['*'], promotes_inputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Wing.AREA, 10.0, 'ft**2') @@ -153,7 +170,7 @@ def test_case(self): prob.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.1, 'unitless') prob.set_val(Aircraft.VerticalTail.AREA, 10.0, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/mass/flops_based/test/test_instruments.py b/aviary/subsystems/mass/flops_based/test/test_instruments.py index b8b5fabca0..8e5237cb4e 100644 --- a/aviary/subsystems/mass/flops_based/test/test_instruments.py +++ b/aviary/subsystems/mass/flops_based/test/test_instruments.py @@ -6,35 +6,45 @@ from aviary.subsystems.mass.flops_based.instruments import TransportInstrumentMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class TransportInstrumentsMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.CrewPayload.NUM_FLIGHT_CREW: inputs.get_val( + Aircraft.CrewPayload.NUM_FLIGHT_CREW + ), + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Mission.Constraints.MAX_MACH: inputs.get_val(Mission.Constraints.MAX_MACH), + } + prob.model.add_subsystem( - "instruments_tests", - TransportInstrumentMass( - aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'instruments_tests', + TransportInstrumentMass(**options), promotes_outputs=[ Aircraft.Instruments.MASS, ], - promotes_inputs=[ - Aircraft.Fuselage.PLANFORM_AREA, - Aircraft.Instruments.MASS_SCALER - ] + promotes_inputs=[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Instruments.MASS_SCALER], ) prob.setup(check=False, force_alloc_complex=True) @@ -42,48 +52,60 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuselage.PLANFORM_AREA, - Aircraft.Instruments.MASS_SCALER], + input_keys=[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Instruments.MASS_SCALER], output_keys=Aircraft.Instruments.MASS, - tol=1e-3) + tol=1e-3, + ) def test_IO(self): assert_match_varnames(self.prob.model) class TransportInstrumentsMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.instruments as instruments + instruments.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.instruments as instruments + instruments.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() + + inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + options = { + Aircraft.CrewPayload.NUM_FLIGHT_CREW: inputs.get_val( + Aircraft.CrewPayload.NUM_FLIGHT_CREW + ), + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Mission.Constraints.MAX_MACH: inputs.get_val(Mission.Constraints.MAX_MACH), + } + prob.model.add_subsystem( - "instruments_tests", - TransportInstrumentMass( - aviary_options=get_flops_inputs("N3CC", preprocess=True)), + 'instruments_tests', + TransportInstrumentMass(**options), promotes_outputs=[ Aircraft.Instruments.MASS, ], - promotes_inputs=[ - Aircraft.Fuselage.PLANFORM_AREA, - Aircraft.Instruments.MASS_SCALER - ] + promotes_inputs=[Aircraft.Fuselage.PLANFORM_AREA, Aircraft.Instruments.MASS_SCALER], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuselage.PLANFORM_AREA, 1500.0, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_landing_gear.py b/aviary/subsystems/mass/flops_based/test/test_landing_gear.py index 59a0569840..2cc50e4d3d 100644 --- a/aviary/subsystems/mass/flops_based/test/test_landing_gear.py +++ b/aviary/subsystems/mass/flops_based/test/test_landing_gear.py @@ -1,5 +1,3 @@ -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.preprocessors import preprocess_options import unittest import openmdao.api as om @@ -7,30 +5,33 @@ from parameterized import parameterized from aviary.subsystems.mass.flops_based.landing_gear import ( - AltLandingGearMass, LandingGearMass, MainGearLength, NoseGearLength) + AltLandingGearMass, + LandingGearMass, + MainGearLength, + NoseGearLength, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class LandingGearMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "landing_gear", - LandingGearMass(aviary_options=get_flops_inputs(case_name)), + 'landing_gear', + LandingGearMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -40,35 +41,38 @@ def test_case(self, case_name): flops_validation_test( self.prob, case_name, - input_keys=[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, - Aircraft.Design.TOUCHDOWN_MASS], - output_keys=[Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_MASS], + input_keys=[ + Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, + Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, + Aircraft.Design.TOUCHDOWN_MASS, + ], + output_keys=[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_MASS], version=Version.TRANSPORT, - atol=1e-11) + atol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class LandingGearMassTest2(unittest.TestCase): - def setUp(self): import aviary.subsystems.mass.flops_based.landing_gear as gear + gear.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.landing_gear as gear + gear.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "landing_gear", - LandingGearMass(aviary_options=get_flops_inputs("N3CC")), + 'landing_gear', + LandingGearMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -77,24 +81,21 @@ def test_case(self): prob.set_val(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, 75.0, 'inch') prob.set_val(Aircraft.Design.TOUCHDOWN_MASS, 100000.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) class AltLandingGearMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "landing_gear_alt", - AltLandingGearMass(aviary_options=get_flops_inputs(case_name)), + 'landing_gear_alt', + AltLandingGearMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -104,35 +105,38 @@ def test_case(self, case_name): flops_validation_test( self.prob, case_name, - input_keys=[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, - Mission.Design.GROSS_MASS], - output_keys=[Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_MASS], + input_keys=[ + Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, + Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, + Mission.Design.GROSS_MASS, + ], + output_keys=[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.NOSE_GEAR_MASS], version=Version.ALTERNATE, - atol=1e-11) + atol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltLandingGearMassTest2(unittest.TestCase): - def setUp(self): import aviary.subsystems.mass.flops_based.landing_gear as gear + gear.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.landing_gear as gear + gear.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "landing_gear_alt", - AltLandingGearMass(aviary_options=get_flops_inputs("N3CC")), + 'landing_gear_alt', + AltLandingGearMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -141,51 +145,55 @@ def test_case(self): prob.set_val(Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, 75.0, 'inch') prob.set_val(Mission.Design.GROSS_MASS, 100000.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class LandingGearLengthTest(unittest.TestCase): - """ - This component is unrepresented in our test data. - """ + """This component is unrepresented in our test data.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(only='N3CC'), - name_func=print_case) + @parameterized.expand(get_flops_case_names(only='AdvancedSingleAisle'), name_func=print_case) def test_derivs(self, case_name): prob = self.prob model = prob.model - flops_inputs = get_flops_inputs(case_name) - engine = build_engine_deck(flops_inputs) - preprocess_options(flops_inputs, engine_models=engine) - model.add_subsystem( - 'main', MainGearLength(aviary_options=flops_inputs), promotes=['*']) - model.add_subsystem( - 'nose', NoseGearLength(aviary_options=flops_inputs), promotes=['*']) + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Engine.NUM_WING_ENGINES: inputs.get_val(Aircraft.Engine.NUM_WING_ENGINES), + } + + model.add_subsystem('main', MainGearLength(**options), promotes=['*']) + model.add_subsystem('nose', NoseGearLength(), promotes=['*']) prob.setup(force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuselage.LENGTH, - Aircraft.Fuselage.MAX_WIDTH, - Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Engine.WING_LOCATIONS, - Aircraft.Wing.DIHEDRAL, - Aircraft.Wing.SPAN], - output_keys=[Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, - Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH], + input_keys=[ + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.MAX_WIDTH, + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Engine.WING_LOCATIONS, + Aircraft.Wing.DIHEDRAL, + Aircraft.Wing.SPAN, + ], + output_keys=[ + Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, + Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, + ], version=Version.ALTERNATE, - atol=1e-11) + atol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_landing_mass.py b/aviary/subsystems/mass/flops_based/test/test_landing_mass.py index 0493c022a6..ca46bdad35 100644 --- a/aviary/subsystems/mass/flops_based/test/test_landing_mass.py +++ b/aviary/subsystems/mass/flops_based/test/test_landing_mass.py @@ -5,41 +5,35 @@ from aviary.subsystems.mass.flops_based.landing_mass import LandingMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class LandingMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(omit='LargeSingleAisle1FLOPS'), - name_func=print_case) + @parameterized.expand(get_flops_case_names(omit='LargeSingleAisle1FLOPS'), name_func=print_case) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - "landing_mass", - LandingMass(aviary_options=get_flops_inputs(case_name)), - promotes=['*'] - ) + prob.model.add_subsystem('landing_mass', LandingMass(), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Mission.Design.GROSS_MASS, - Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO], - output_keys=Aircraft.Design.TOUCHDOWN_MASS) + input_keys=[Mission.Design.GROSS_MASS, Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO], + output_keys=Aircraft.Design.TOUCHDOWN_MASS, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_mass_summation.py b/aviary/subsystems/mass/flops_based/test/test_mass_summation.py index dbb14b1218..8078d61233 100644 --- a/aviary/subsystems/mass/flops_based/test/test_mass_summation.py +++ b/aviary/subsystems/mass/flops_based/test/test_mass_summation.py @@ -2,88 +2,98 @@ import numpy as np import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import parameterized from aviary.subsystems.mass.flops_based.mass_summation import MassSummation, StructureMass -from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) -from aviary.variable_info.variables import Aircraft, Mission, Settings +from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.propulsion.engine_deck import EngineDeck +from aviary.utils.test_utils.variable_test import assert_match_varnames +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Mission, Settings class TotalSummationTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "tot", - MassSummation(aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'tot', + MassSummation(), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.AirConditioning.MASS, - Aircraft.AntiIcing.MASS, - Aircraft.APU.MASS, - Aircraft.Avionics.MASS, - Aircraft.Canard.MASS, - Aircraft.CrewPayload.PASSENGER_MASS, - Aircraft.CrewPayload.BAGGAGE_MASS, - Aircraft.CrewPayload.CARGO_MASS, - Aircraft.CrewPayload.CARGO_CONTAINER_MASS, - Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, - Aircraft.CrewPayload.FLIGHT_CREW_MASS, - Aircraft.Design.EMPTY_MASS_MARGIN, - Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, - Aircraft.Electrical.MASS, - Aircraft.Fins.MASS, - Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, - Aircraft.Fuel.FUEL_SYSTEM_MASS, - Aircraft.Furnishings.MASS, - Aircraft.Fuselage.MASS, - Aircraft.HorizontalTail.MASS, - Aircraft.Hydraulics.MASS, - Aircraft.Instruments.MASS, - Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_MASS, - Aircraft.Nacelle.MASS, - Aircraft.Paint.MASS, - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, - Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - Aircraft.Fuel.UNUSABLE_FUEL_MASS, - Aircraft.VerticalTail.MASS, - Aircraft.Wing.MASS, - Mission.Design.GROSS_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_MASS, - Aircraft.Propulsion.TOTAL_MISC_MASS], - output_keys=[Aircraft.Design.STRUCTURE_MASS, - Aircraft.Propulsion.MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS, - Aircraft.Design.EMPTY_MASS, - Aircraft.Design.OPERATING_MASS, - Aircraft.Design.ZERO_FUEL_MASS, - Mission.Design.FUEL_MASS], + input_keys=[ + Aircraft.AirConditioning.MASS, + Aircraft.AntiIcing.MASS, + Aircraft.APU.MASS, + Aircraft.Avionics.MASS, + Aircraft.Canard.MASS, + Aircraft.CrewPayload.PASSENGER_MASS, + Aircraft.CrewPayload.BAGGAGE_MASS, + Aircraft.CrewPayload.CARGO_MASS, + Aircraft.CrewPayload.CARGO_CONTAINER_MASS, + Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, + Aircraft.CrewPayload.FLIGHT_CREW_MASS, + Aircraft.Design.EMPTY_MASS_MARGIN, + Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, + Aircraft.Electrical.MASS, + Aircraft.Fins.MASS, + Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, + Aircraft.Fuel.FUEL_SYSTEM_MASS, + Aircraft.Furnishings.MASS, + Aircraft.Fuselage.MASS, + Aircraft.HorizontalTail.MASS, + Aircraft.Hydraulics.MASS, + Aircraft.Instruments.MASS, + Aircraft.LandingGear.MAIN_GEAR_MASS, + Aircraft.LandingGear.NOSE_GEAR_MASS, + Aircraft.Nacelle.MASS, + Aircraft.Paint.MASS, + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, + Aircraft.Wing.SURFACE_CONTROL_MASS, + Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, + Aircraft.Fuel.UNUSABLE_FUEL_MASS, + Aircraft.VerticalTail.MASS, + Aircraft.Wing.MASS, + Mission.Design.GROSS_MASS, + Aircraft.Propulsion.TOTAL_ENGINE_MASS, + Aircraft.Propulsion.TOTAL_MISC_MASS, + ], + output_keys=[ + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Propulsion.MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS, + Aircraft.Design.EMPTY_MASS, + Mission.Summary.OPERATING_MASS, + Mission.Summary.ZERO_FUEL_MASS, + Mission.Summary.FUEL_MASS, + ], version=Version.TRANSPORT, - atol=1e-10) + atol=1e-10, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -93,68 +103,81 @@ class AltTotalSummationTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Design.USE_ALT_MASS: inputs.get_val(Aircraft.Design.USE_ALT_MASS), + } + prob.model.add_subsystem( - "tot", - MassSummation(aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'tot', + MassSummation(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.AirConditioning.MASS, - Aircraft.AntiIcing.MASS, - Aircraft.APU.MASS, - Aircraft.Avionics.MASS, - Aircraft.Canard.MASS, - Aircraft.CrewPayload.PASSENGER_MASS, - Aircraft.CrewPayload.BAGGAGE_MASS, - Aircraft.CrewPayload.CARGO_MASS, - Aircraft.CrewPayload.CARGO_CONTAINER_MASS, - Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, - Aircraft.CrewPayload.FLIGHT_CREW_MASS, - Aircraft.Design.EMPTY_MASS_MARGIN, - Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, - Aircraft.Electrical.MASS, - Aircraft.Fins.MASS, - Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, - Aircraft.Fuel.FUEL_SYSTEM_MASS, - Aircraft.Furnishings.MASS_BASE, - Aircraft.Fuselage.MASS, - Aircraft.HorizontalTail.MASS, - Aircraft.Hydraulics.MASS, - Aircraft.Instruments.MASS, - Aircraft.LandingGear.MAIN_GEAR_MASS, - Aircraft.LandingGear.NOSE_GEAR_MASS, - Aircraft.Propulsion.TOTAL_MISC_MASS, - Aircraft.Nacelle.MASS, - Aircraft.Paint.MASS, - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, - Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - Aircraft.Fuel.UNUSABLE_FUEL_MASS, - Aircraft.VerticalTail.MASS, - Aircraft.Wing.MASS, - Mission.Design.GROSS_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_MASS], - output_keys=[Aircraft.Design.STRUCTURE_MASS, - Aircraft.Propulsion.MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS, - Aircraft.Design.EMPTY_MASS, - Aircraft.Design.OPERATING_MASS, - Aircraft.Design.ZERO_FUEL_MASS, - Mission.Design.FUEL_MASS], + input_keys=[ + Aircraft.AirConditioning.MASS, + Aircraft.AntiIcing.MASS, + Aircraft.APU.MASS, + Aircraft.Avionics.MASS, + Aircraft.Canard.MASS, + Aircraft.CrewPayload.PASSENGER_MASS, + Aircraft.CrewPayload.BAGGAGE_MASS, + Aircraft.CrewPayload.CARGO_MASS, + Aircraft.CrewPayload.CARGO_CONTAINER_MASS, + Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, + Aircraft.CrewPayload.FLIGHT_CREW_MASS, + Aircraft.Design.EMPTY_MASS_MARGIN, + Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, + Aircraft.Electrical.MASS, + Aircraft.Fins.MASS, + Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, + Aircraft.Fuel.FUEL_SYSTEM_MASS, + Aircraft.Furnishings.MASS_BASE, + Aircraft.Fuselage.MASS, + Aircraft.HorizontalTail.MASS, + Aircraft.Hydraulics.MASS, + Aircraft.Instruments.MASS, + Aircraft.LandingGear.MAIN_GEAR_MASS, + Aircraft.LandingGear.NOSE_GEAR_MASS, + Aircraft.Propulsion.TOTAL_MISC_MASS, + Aircraft.Nacelle.MASS, + Aircraft.Paint.MASS, + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, + Aircraft.Wing.SURFACE_CONTROL_MASS, + Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, + Aircraft.Fuel.UNUSABLE_FUEL_MASS, + Aircraft.VerticalTail.MASS, + Aircraft.Wing.MASS, + Mission.Design.GROSS_MASS, + Aircraft.Propulsion.TOTAL_ENGINE_MASS, + ], + output_keys=[ + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Propulsion.MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS, + Aircraft.Design.EMPTY_MASS, + Mission.Summary.OPERATING_MASS, + Mission.Summary.ZERO_FUEL_MASS, + Mission.Summary.FUEL_MASS, + ], version=Version.ALTERNATE, - atol=1e-10) + atol=1e-10, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -170,7 +193,7 @@ def test_case_multiengine(self): options = AviaryValues() options.set_val(Aircraft.Engine.NUM_ENGINES, 4) - options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.deck') + options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.csv') # suppress some warning messages about required option for EngineDecks options.set_val(Settings.VERBOSITY, 0) engineModel1 = EngineDeck(options=options) @@ -180,8 +203,11 @@ def test_case_multiengine(self): preprocess_propulsion(options, [engineModel1, engineModel2, engineModel3]) - prob.model.add_subsystem('structure_mass', StructureMass( - aviary_options=options), promotes=['*']) + comp_options = { + Aircraft.Engine.NUM_ENGINES: options.get_val(Aircraft.Engine.NUM_ENGINES), + } + + prob.model.add_subsystem('structure_mass', StructureMass(**comp_options), promotes=['*']) prob.setup(force_alloc_complex=True) prob.set_val(Aircraft.Canard.MASS, val=10.0, units='lbm') @@ -190,8 +216,7 @@ def test_case_multiengine(self): prob.set_val(Aircraft.HorizontalTail.MASS, val=40.0, units='lbm') prob.set_val(Aircraft.LandingGear.MAIN_GEAR_MASS, val=50.0, units='lbm') prob.set_val(Aircraft.LandingGear.NOSE_GEAR_MASS, val=60.0, units='lbm') - prob.set_val(Aircraft.Nacelle.MASS, - val=np.array([1000.0, 500.0, 1500.0]), units='lbm') + prob.set_val(Aircraft.Nacelle.MASS, val=np.array([1000.0, 500.0, 1500.0]), units='lbm') prob.set_val(Aircraft.Paint.MASS, val=70.0, units='lbm') prob.set_val(Aircraft.VerticalTail.MASS, val=80.0, units='lbm') prob.set_val(Aircraft.Wing.MASS, val=90.0, units='lbm') @@ -203,9 +228,14 @@ def test_case_multiengine(self): assert_near_equal(structure_mass, structure_mass_expected, tolerance=1e-8) partial_data = prob.check_partials( - out_stream=None, compact_print=True, show_only_incorrect=True, form='central', method="fd") + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + ) assert_check_partials(partial_data, atol=1e-6, rtol=1e-6) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_misc_engine.py b/aviary/subsystems/mass/flops_based/test/test_misc_engine.py index dc90b0b999..88d412fc76 100644 --- a/aviary/subsystems/mass/flops_based/test/test_misc_engine.py +++ b/aviary/subsystems/mass/flops_based/test/test_misc_engine.py @@ -2,37 +2,40 @@ import numpy as np import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import parameterized from aviary.subsystems.mass.flops_based.misc_engine import EngineMiscMass from aviary.subsystems.propulsion.engine_deck import EngineDeck -from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) -from aviary.variable_info.variables import Aircraft, Settings -from aviary.utils.functions import get_path from aviary.utils.aviary_values import AviaryValues +from aviary.utils.functions import get_path from aviary.utils.preprocessors import preprocess_propulsion -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from aviary.utils.test_utils.variable_test import assert_match_varnames +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) +from aviary.variable_info.variables import Aircraft, Settings class MiscEngineMassTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + } + prob.model.add_subsystem( - "misc_mass", - EngineMiscMass(aviary_options=get_flops_inputs(case_name, preprocess=True)), - promotes_inputs=['*'], - promotes_outputs=['*'] + 'misc_mass', EngineMiscMass(**options), promotes_inputs=['*'], promotes_outputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) @@ -40,11 +43,14 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Propulsion.MISC_MASS_SCALER, - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, - Aircraft.Propulsion.TOTAL_STARTER_MASS], - output_keys=Aircraft.Propulsion.TOTAL_MISC_MASS) + input_keys=[ + Aircraft.Engine.ADDITIONAL_MASS, + Aircraft.Propulsion.MISC_MASS_SCALER, + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, + Aircraft.Propulsion.TOTAL_STARTER_MASS, + ], + output_keys=Aircraft.Propulsion.TOTAL_MISC_MASS, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -55,8 +61,7 @@ def test_case_multiengine(self): options = AviaryValues() options.set_val(Aircraft.Engine.NUM_ENGINES, 4) - options.set_val(Aircraft.Engine.DATA_FILE, get_path( - 'models/engines/turbofan_28k.deck')) + options.set_val(Aircraft.Engine.DATA_FILE, get_path('models/engines/turbofan_28k.csv')) options.set_val(Settings.VERBOSITY, 0) engineModel1 = EngineDeck(options=options) options.set_val(Aircraft.Engine.NUM_ENGINES, 2) @@ -65,11 +70,15 @@ def test_case_multiengine(self): preprocess_propulsion(options, [engineModel1, engineModel2, engineModel3]) - prob.model.add_subsystem('misc_engine_mass', EngineMiscMass( - aviary_options=options), promotes=['*']) + comp_options = { + Aircraft.Engine.NUM_ENGINES: options.get_val(Aircraft.Engine.NUM_ENGINES), + } + + prob.model.add_subsystem('misc_engine_mass', EngineMiscMass(**comp_options), promotes=['*']) + prob.setup(force_alloc_complex=True) - prob.set_val(Aircraft.Engine.ADDITIONAL_MASS, - np.array([100, 26, 30]), units='lbm') + + prob.set_val(Aircraft.Engine.ADDITIONAL_MASS, np.array([100, 26, 30]), units='lbm') prob.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, 1.02, units='unitless') prob.set_val(Aircraft.Propulsion.TOTAL_STARTER_MASS, 50.0, units='lbm') prob.set_val(Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, 10.0, units='lbm') @@ -78,13 +87,18 @@ def test_case_multiengine(self): total_misc_mass = prob.get_val(Aircraft.Propulsion.TOTAL_MISC_MASS, 'lbm') # manual computation of expected misc mass - total_misc_mass_expected = (50 + (100*4 + 26*2 + 30*2) + 10)*1.02 + total_misc_mass_expected = (50 + (100 * 4 + 26 * 2 + 30 * 2) + 10) * 1.02 assert_near_equal(total_misc_mass, total_misc_mass_expected, tolerance=1e-10) partial_data = prob.check_partials( - out_stream=None, compact_print=True, show_only_incorrect=True, form='central', method="fd") + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + ) assert_check_partials(partial_data, atol=1e-7, rtol=1e-7) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_nacelle.py b/aviary/subsystems/mass/flops_based/test/test_nacelle.py index 975abc97e6..46aa59375c 100644 --- a/aviary/subsystems/mass/flops_based/test/test_nacelle.py +++ b/aviary/subsystems/mass/flops_based/test/test_nacelle.py @@ -2,35 +2,41 @@ import numpy as np import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import parameterized from aviary.subsystems.mass.flops_based.nacelle import NacelleMass from aviary.subsystems.propulsion.engine_deck import EngineDeck -from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) -from aviary.variable_info.variables import Aircraft, Settings -from aviary.utils.functions import get_path from aviary.utils.aviary_values import AviaryValues +from aviary.utils.functions import get_path from aviary.utils.preprocessors import preprocess_propulsion -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from aviary.utils.test_utils.variable_test import assert_match_varnames +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) +from aviary.variable_info.variables import Aircraft, Settings class NacelleMassTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + } + prob.model.add_subsystem( - "nacelle", - NacelleMass(aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'nacelle', + NacelleMass(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -40,11 +46,14 @@ def test_case(self, case_name): flops_validation_test( self.prob, case_name, - input_keys=[Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Nacelle.AVG_LENGTH, - Aircraft.Nacelle.MASS_SCALER, - Aircraft.Engine.SCALED_SLS_THRUST], - output_keys=Aircraft.Nacelle.MASS) + input_keys=[ + Aircraft.Nacelle.AVG_DIAMETER, + Aircraft.Nacelle.AVG_LENGTH, + Aircraft.Nacelle.MASS_SCALER, + Aircraft.Engine.SCALED_SLS_THRUST, + ], + output_keys=Aircraft.Nacelle.MASS, + ) def test_IO(self): assert_match_varnames(self.prob.model) @@ -55,8 +64,7 @@ def test_case_multiengine(self): options = AviaryValues() options.set_val(Aircraft.Engine.NUM_ENGINES, 4) - options.set_val(Aircraft.Engine.DATA_FILE, get_path( - 'models/engines/turbofan_28k.deck')) + options.set_val(Aircraft.Engine.DATA_FILE, get_path('models/engines/turbofan_28k.csv')) # suppress some warning messages about required option for EngineDecks options.set_val(Settings.VERBOSITY, 0) engineModel1 = EngineDeck(options=options) @@ -66,17 +74,18 @@ def test_case_multiengine(self): preprocess_propulsion(options, [engineModel1, engineModel2, engineModel3]) - prob.model.add_subsystem('nacelle_mass', NacelleMass( - aviary_options=options), promotes=['*']) + comp_options = { + Aircraft.Engine.NUM_ENGINES: options.get_val(Aircraft.Engine.NUM_ENGINES), + } + + prob.model.add_subsystem('nacelle_mass', NacelleMass(**comp_options), promotes=['*']) + prob.setup(force_alloc_complex=True) - prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, - np.array([5.0, 3.0, 8.0]), units='ft') - prob.set_val(Aircraft.Nacelle.AVG_LENGTH, - np.array([14.0, 13.0, 12.0]), units='ft') - prob.set_val(Aircraft.Nacelle.MASS_SCALER, - np.array([1.0] * 3), units='unitless') - prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - np.array([28000] * 3), units='lbf') + + prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, np.array([5.0, 3.0, 8.0]), units='ft') + prob.set_val(Aircraft.Nacelle.AVG_LENGTH, np.array([14.0, 13.0, 12.0]), units='ft') + prob.set_val(Aircraft.Nacelle.MASS_SCALER, np.array([1.0] * 3), units='unitless') + prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, np.array([28000] * 3), units='lbf') prob.run_model() @@ -85,28 +94,40 @@ def test_case_multiengine(self): assert_near_equal(nacelle_mass, nacelle_mass_expected, tolerance=1e-8) partial_data = prob.check_partials( - out_stream=None, compact_print=True, show_only_incorrect=True, form='central', method="fd") + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + ) assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) class NacelleMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.nacelle as nacelle + nacelle.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.nacelle as nacelle + nacelle.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() + + inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + } + prob.model.add_subsystem( - "nacelle", - NacelleMass(aviary_options=get_flops_inputs("N3CC", preprocess=True)), + 'nacelle', + NacelleMass(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -115,37 +136,39 @@ def test_case(self): prob.set_val(Aircraft.Nacelle.AVG_LENGTH, 35.0, 'ft') prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 10000.0, 'lbf') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_case_multiengine(self): prob = om.Problem() options = AviaryValues() options.set_val(Aircraft.Engine.NUM_ENGINES, 4) - options.set_val(Aircraft.Engine.DATA_FILE, get_path( - 'models/engines/turbofan_28k.deck')) + options.set_val(Aircraft.Engine.DATA_FILE, get_path('models/engines/turbofan_28k.csv')) # suppress some warning messages about required option for EngineDecks options.set_val(Settings.VERBOSITY, 0) engineModel1 = EngineDeck(options=options) options.set_val(Aircraft.Engine.NUM_ENGINES, 2) engineModel2 = EngineDeck(options=options) engineModel3 = EngineDeck(options=options) + preprocess_propulsion(options, [engineModel1, engineModel2, engineModel3]) - prob.model.add_subsystem('nacelle_mass', NacelleMass( - aviary_options=options), promotes=['*']) + + comp_options = { + Aircraft.Engine.NUM_ENGINES: options.get_val(Aircraft.Engine.NUM_ENGINES), + } + + prob.model.add_subsystem('nacelle_mass', NacelleMass(**comp_options), promotes=['*']) + prob.setup(force_alloc_complex=True) - prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, - np.array([5.0, 3.0, 8.0]), units='ft') - prob.set_val(Aircraft.Nacelle.AVG_LENGTH, - np.array([14.0, 13.0, 12.0]), units='ft') - prob.set_val(Aircraft.Nacelle.MASS_SCALER, - np.array([1.0] * 3), units='unitless') - prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - np.array([28000] * 3), units='lbf') - - partial_data = prob.check_partials(out_stream=None, method="cs") + + prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, np.array([5.0, 3.0, 8.0]), units='ft') + prob.set_val(Aircraft.Nacelle.AVG_LENGTH, np.array([14.0, 13.0, 12.0]), units='ft') + prob.set_val(Aircraft.Nacelle.MASS_SCALER, np.array([1.0] * 3), units='unitless') + prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, np.array([28000] * 3), units='lbf') + + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_paint.py b/aviary/subsystems/mass/flops_based/test/test_paint.py index bb434b1369..b0bd8dcf4c 100644 --- a/aviary/subsystems/mass/flops_based/test/test_paint.py +++ b/aviary/subsystems/mass/flops_based/test/test_paint.py @@ -5,10 +5,11 @@ from aviary.subsystems.mass.flops_based.paint import PaintMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + print_case, +) from aviary.variable_info.variables import Aircraft @@ -16,15 +17,13 @@ class PaintMassTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "paint", - PaintMass(aviary_options=get_flops_inputs(case_name)), + 'paint', + PaintMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -34,13 +33,13 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Design.TOTAL_WETTED_AREA, - Aircraft.Paint.MASS_PER_UNIT_AREA], - output_keys=Aircraft.Paint.MASS) + input_keys=[Aircraft.Design.TOTAL_WETTED_AREA, Aircraft.Paint.MASS_PER_UNIT_AREA], + output_keys=Aircraft.Paint.MASS, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_passenger_service.py b/aviary/subsystems/mass/flops_based/test/test_passenger_service.py index 448eb8532f..c350fd06cd 100644 --- a/aviary/subsystems/mass/flops_based/test/test_passenger_service.py +++ b/aviary/subsystems/mass/flops_based/test/test_passenger_service.py @@ -5,95 +5,100 @@ from parameterized import parameterized from aviary.subsystems.mass.flops_based.passenger_service import ( - AltPassengerServiceMass, PassengerServiceMass) + AltPassengerServiceMass, + PassengerServiceMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class PassengerServiceMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( 'passenger_service_weight', - PassengerServiceMass(aviary_options=get_flops_inputs(case_name)), + PassengerServiceMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, - Mission.Design.RANGE], + input_keys=[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, Mission.Design.RANGE], output_keys=Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, version=Version.TRANSPORT, - tol=2e-4) + tol=2e-4, + ) def test_IO(self): assert_match_varnames(self.prob.model) class PassengerServiceMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.passenger_service as service + service.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.passenger_service as service + service.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( 'passenger_service_weight', - PassengerServiceMass(aviary_options=get_flops_inputs("N3CC")), + PassengerServiceMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Mission.Design.RANGE, 3500.0, 'nmi') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AlternatePassengerServiceMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( 'alternate_passenger_service_weight', - AltPassengerServiceMass(aviary_options=get_flops_inputs(case_name)), + AltPassengerServiceMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( @@ -101,38 +106,42 @@ def test_case(self, case_name): case_name, input_keys=Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, output_keys=Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AlternatePassengerServiceMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.nacelle as nacelle + nacelle.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.nacelle as nacelle + nacelle.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( 'alternate_passenger_service_weight', - AltPassengerServiceMass(aviary_options=get_flops_inputs("N3CC")), + AltPassengerServiceMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_starter.py b/aviary/subsystems/mass/flops_based/test/test_starter.py index 426afa6bb7..74e3ee8768 100644 --- a/aviary/subsystems/mass/flops_based/test/test_starter.py +++ b/aviary/subsystems/mass/flops_based/test/test_starter.py @@ -7,30 +7,38 @@ from aviary.subsystems.mass.flops_based.starter import TransportStarterMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class TransportStarterMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(omit='N3CC'), - name_func=print_case) + @parameterized.expand(get_flops_case_names(omit='AdvancedSingleAisle'), name_func=print_case) def test_case_1(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Propulsion.TOTAL_NUM_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_ENGINES + ), + Mission.Constraints.MAX_MACH: inputs.get_val(Mission.Constraints.MAX_MACH), + } + prob.model.add_subsystem( - "starter_test", - TransportStarterMass(aviary_options=get_flops_inputs( - case_name, preprocess=True)), + 'starter_test', + TransportStarterMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) @@ -39,22 +47,24 @@ def test_case_1(self, case_name): prob, case_name, input_keys=[Aircraft.Nacelle.AVG_DIAMETER], - output_keys=Aircraft.Propulsion.TOTAL_STARTER_MASS) + output_keys=Aircraft.Propulsion.TOTAL_STARTER_MASS, + ) def test_case_2(self): # test with more than 4 engines prob = self.prob - aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([5])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 5) - aviary_options.set_val(Mission.Constraints.MAX_MACH, 0.785) + options = { + Aircraft.Engine.NUM_ENGINES: np.array([5]), + Aircraft.Propulsion.TOTAL_NUM_ENGINES: 5, + Mission.Constraints.MAX_MACH: 0.785, + } prob.model.add_subsystem( - "starter_test", - TransportStarterMass(aviary_options=aviary_options), + 'starter_test', + TransportStarterMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) @@ -68,7 +78,7 @@ def test_case_2(self): assert_near_equal(mass, expected_mass, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_IO(self): @@ -76,36 +86,39 @@ def test_IO(self): class TransportStarterMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.starter as starter + starter.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.starter as starter + starter.GRAV_ENGLISH_LBM = 1.0 def test_case_2(self): prob = om.Problem() - aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') - aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([5])) - aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 5) - aviary_options.set_val(Mission.Constraints.MAX_MACH, 0.785) + + options = { + Aircraft.Engine.NUM_ENGINES: np.array([5]), + Aircraft.Propulsion.TOTAL_NUM_ENGINES: 5, + Mission.Constraints.MAX_MACH: 0.785, + } + prob.model.add_subsystem( - "starter_test", - TransportStarterMass(aviary_options=aviary_options), + 'starter_test', + TransportStarterMass(**options), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, np.array([7.94]), 'ft') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_surface_controls.py b/aviary/subsystems/mass/flops_based/test/test_surface_controls.py index 0e96f7dc31..98948493f7 100644 --- a/aviary/subsystems/mass/flops_based/test/test_surface_controls.py +++ b/aviary/subsystems/mass/flops_based/test/test_surface_controls.py @@ -5,79 +5,79 @@ from parameterized import parameterized from aviary.subsystems.mass.flops_based.surface_controls import ( - AltSurfaceControlMass, SurfaceControlMass) + AltSurfaceControlMass, + SurfaceControlMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class SurfaceCtrlMassTest(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - "surf_ctrl", - SurfaceControlMass(aviary_options=get_flops_inputs(case_name)), - promotes=['*'] - ) + prob.model.add_subsystem('surf_ctrl', SurfaceControlMass(), promotes=['*']) + + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, - Mission.Design.GROSS_MASS, - Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, - Aircraft.Wing.AREA], - output_keys=[Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Wing.CONTROL_SURFACE_AREA], + input_keys=[ + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, + Mission.Design.GROSS_MASS, + Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, + Aircraft.Wing.AREA, + ], + output_keys=[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.CONTROL_SURFACE_AREA], version=Version.TRANSPORT, tol=2e-4, atol=1e-11, - rtol=1e-11) + rtol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class SurfaceCtrlMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.surface_controls as surface + surface.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.surface_controls as surface + surface.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - prob.model.add_subsystem( - "surf_ctrl", - SurfaceControlMass(aviary_options=get_flops_inputs("N3CC")), - promotes=['*'] - ) + prob.model.add_subsystem('surf_ctrl', SurfaceControlMass(), promotes=['*']) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Mission.Design.GROSS_MASS, 130000, 'lbm') prob.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, 1, 'unitless') prob.set_val(Aircraft.Wing.AREA, 1000, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) @@ -85,66 +85,64 @@ class AltSurfaceCtrlMassTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - "surf_ctrl", - AltSurfaceControlMass(aviary_options=get_flops_inputs(case_name)), - promotes=['*'] - ) + prob.model.add_subsystem('surf_ctrl', AltSurfaceControlMass(), promotes=['*']) + + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, - Aircraft.Wing.AREA, - Aircraft.HorizontalTail.WETTED_AREA, - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, - Aircraft.VerticalTail.AREA], + input_keys=[ + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, + Aircraft.Wing.AREA, + Aircraft.HorizontalTail.WETTED_AREA, + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, + Aircraft.VerticalTail.AREA, + ], output_keys=Aircraft.Wing.SURFACE_CONTROL_MASS, version=Version.ALTERNATE, atol=1e-11, - rtol=1e-11) + rtol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltSurfaceCtrlMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.surface_controls as surface + surface.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.surface_controls as surface + surface.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - prob.model.add_subsystem( - "surf_ctrl", - AltSurfaceControlMass(aviary_options=get_flops_inputs("N3CC")), - promotes=['*'] - ) + prob.model.add_subsystem('surf_ctrl', AltSurfaceControlMass(), promotes=['*']) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Wing.AREA, 1000, 'ft**2') prob.set_val(Aircraft.HorizontalTail.WETTED_AREA, 100, 'ft**2') prob.set_val(Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.1, 'unitless') prob.set_val(Aircraft.VerticalTail.AREA, 100, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py b/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py index e77408cf63..67be045a7f 100644 --- a/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py +++ b/aviary/subsystems/mass/flops_based/test/test_thrust_reverser.py @@ -2,48 +2,56 @@ import numpy as np import openmdao.api as om - +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import parameterized from aviary.subsystems.mass.flops_based.thrust_reverser import ThrustReverserMass -from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) -from aviary.variable_info.variables import Aircraft, Settings +from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion -from aviary.subsystems.propulsion.engine_deck import EngineDeck -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from aviary.utils.test_utils.variable_test import assert_match_varnames +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) +from aviary.variable_info.variables import Aircraft, Settings class ThrustReverserMassTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(omit=['LargeSingleAisle1FLOPS', 'N3CC']), - name_func=print_case) + @parameterized.expand( + get_flops_case_names(omit=['LargeSingleAisle1FLOPS', 'AdvancedSingleAisle']), + name_func=print_case, + ) def test_case(self, case_name): - prob = self.prob - prob.model.add_subsystem( - "thrust_rev", - ThrustReverserMass(aviary_options=get_flops_inputs( - case_name, preprocess=True)), - promotes=['*'] - ) + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + } + + prob.model.add_subsystem('thrust_rev', ThrustReverserMass(**options), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, - Aircraft.Engine.SCALED_SLS_THRUST], - output_keys=[Aircraft.Engine.THRUST_REVERSERS_MASS, - Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS]) + input_keys=[ + Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, + Aircraft.Engine.SCALED_SLS_THRUST, + ], + output_keys=[ + Aircraft.Engine.THRUST_REVERSERS_MASS, + Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, + ], + ) def test_case_multiengine(self): prob = om.Problem() @@ -51,44 +59,55 @@ def test_case_multiengine(self): aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') engine_options = AviaryValues() - engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) - engine_options.set_val(Aircraft.Engine.DATA_FILE, - 'models/engines/turbofan_28k.deck') engine_options.set_val(Settings.VERBOSITY, 0) + engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) + engine_options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.csv') engineModel1 = EngineDeck(options=engine_options) engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) engineModel2 = EngineDeck(options=engine_options) engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 4) engineModel3 = EngineDeck(options=engine_options) - preprocess_propulsion(aviary_options, [engineModel1, engineModel2, engineModel3]) + preprocess_propulsion( + aviary_options, [engineModel1, engineModel2, engineModel3], verbosity=0 + ) + + options = { + Aircraft.Engine.NUM_ENGINES: aviary_options.get_val(Aircraft.Engine.NUM_ENGINES), + } - prob.model.add_subsystem('thrust_reverser_mass', ThrustReverserMass( - aviary_options=aviary_options), promotes=['*']) + prob.model.add_subsystem( + 'thrust_reverser_mass', ThrustReverserMass(**options), promotes=['*'] + ) prob.setup(force_alloc_complex=True) - prob.set_val(Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, - np.array([1.0, 1.22, 0.0]), units='unitless') + prob.set_val( + Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, + np.array([1.0, 1.22, 0.0]), + units='unitless', + ) - prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - np.array([1000, 20000, 150]), 'lbf') + prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, np.array([1000, 20000, 150]), 'lbf') prob.run_model() thrust_rev_mass = prob.get_val(Aircraft.Engine.THRUST_REVERSERS_MASS, 'lbm') - total_thrust_rev_mass = prob.get_val( - Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, 'lbm') + total_thrust_rev_mass = prob.get_val(Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, 'lbm') # manual computation of expected thrust reverser mass - thrust_rev_mass_expected = [68., 1659.2, 0.] + thrust_rev_mass_expected = [68.0, 1659.2, 0.0] total_thrust_rev_mass_expected = sum(thrust_rev_mass_expected) assert_near_equal(thrust_rev_mass, thrust_rev_mass_expected, tolerance=1e-10) - assert_near_equal(total_thrust_rev_mass, - total_thrust_rev_mass_expected, tolerance=1e-10) + assert_near_equal(total_thrust_rev_mass, total_thrust_rev_mass_expected, tolerance=1e-10) partial_data = prob.check_partials( - out_stream=None, compact_print=True, show_only_incorrect=True, form='central', method="fd") + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + ) assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) def test_IO(self): @@ -96,32 +115,34 @@ def test_IO(self): class ThrustReverserMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.thrust_reverser as reverser + reverser.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.thrust_reverser as reverser + reverser.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - prob.model.add_subsystem( - "thrust_rev", - ThrustReverserMass(aviary_options=get_flops_inputs( - "N3CC", preprocess=True)), - promotes=['*'] - ) + + inputs = get_flops_inputs('AdvancedSingleAisle', preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + } + + prob.model.add_subsystem('thrust_rev', ThrustReverserMass(**options), promotes=['*']) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, 10000.0, 'lbf') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_unusable_fuel.py b/aviary/subsystems/mass/flops_based/test/test_unusable_fuel.py index f479b7488d..9727e20f1a 100644 --- a/aviary/subsystems/mass/flops_based/test/test_unusable_fuel.py +++ b/aviary/subsystems/mass/flops_based/test/test_unusable_fuel.py @@ -5,108 +5,109 @@ from parameterized import parameterized from aviary.subsystems.mass.flops_based.unusable_fuel import ( - AltUnusableFuelMass, TransportUnusableFuelMass) + AltUnusableFuelMass, + TransportUnusableFuelMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft class TransportUnusableFuelMassTest(unittest.TestCase): - ''' - Tests transport/GA unusable fuel mass calculation. - ''' + """Tests transport/GA unusable fuel mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob - flops_inputs = get_flops_inputs(case_name, preprocess=True) prob.model.add_subsystem( 'unusable_fuel', - TransportUnusableFuelMass(aviary_options=flops_inputs), + TransportUnusableFuelMass(), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, - Aircraft.Fuel.DENSITY_RATIO, - Aircraft.Fuel.TOTAL_CAPACITY, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, - Aircraft.Wing.AREA], + input_keys=[ + Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, + Aircraft.Fuel.DENSITY, + Aircraft.Fuel.TOTAL_CAPACITY, + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, + Aircraft.Wing.AREA, + ], output_keys=[ # Aircraft.Fuel.TOTAL_VOLUME, - Aircraft.Fuel.UNUSABLE_FUEL_MASS], + Aircraft.Fuel.UNUSABLE_FUEL_MASS + ], version=Version.TRANSPORT, tol=5e-4, - excludes=['size_prop.*']) + excludes=['size_prop.*'], + ) def test_IO(self): assert_match_varnames(self.prob.model) class TransportUnusableFuelMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.unusable_fuel as ufuel + ufuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.unusable_fuel as ufuel + ufuel.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - flops_inputs = get_flops_inputs("N3CC", preprocess=True) + prob.model.add_subsystem( 'unusable_fuel', - TransportUnusableFuelMass(aviary_options=flops_inputs), + TransportUnusableFuelMass(), promotes_outputs=['*'], - promotes_inputs=['*'] + promotes_inputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 30000.0, 'lbm') prob.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 40000.0, 'lbf') prob.set_val(Aircraft.Wing.AREA, 1000.0, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AltUnusableFuelMassTest(unittest.TestCase): - ''' - Tests alternate unusable fuel mass calculation. - ''' + """Tests alternate unusable fuel mass calculation.""" def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - 'unusable_fuel', - AltUnusableFuelMass(aviary_options=get_flops_inputs(case_name)), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'unusable_fuel', AltUnusableFuelMass(), promotes_outputs=['*'], promotes_inputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) @@ -114,41 +115,39 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, - Aircraft.Fuel.TOTAL_CAPACITY], + input_keys=[Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, Aircraft.Fuel.TOTAL_CAPACITY], output_keys=[ # Aircraft.Fuel.TOTAL_VOLUME, - Aircraft.Fuel.UNUSABLE_FUEL_MASS], - version=Version.ALTERNATE) + Aircraft.Fuel.UNUSABLE_FUEL_MASS + ], + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) class AltUnusableFuelMassTest2(unittest.TestCase): - ''' - Test mass-weight conversion - ''' + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.unusable_fuel as ufuel + ufuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.unusable_fuel as ufuel + ufuel.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - 'unusable_fuel', - AltUnusableFuelMass(aviary_options=get_flops_inputs("N3CC")), - promotes_outputs=['*'], - promotes_inputs=['*'] + 'unusable_fuel', AltUnusableFuelMass(), promotes_outputs=['*'], promotes_inputs=['*'] ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Fuel.TOTAL_CAPACITY, 30000.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/mass/flops_based/test/test_vertical_tail.py b/aviary/subsystems/mass/flops_based/test/test_vertical_tail.py index fc9801613c..07d29bf3c0 100644 --- a/aviary/subsystems/mass/flops_based/test/test_vertical_tail.py +++ b/aviary/subsystems/mass/flops_based/test/test_vertical_tail.py @@ -4,94 +4,97 @@ from openmdao.utils.assert_utils import assert_check_partials from parameterized import parameterized -from aviary.subsystems.mass.flops_based.vertical_tail import (AltVerticalTailMass, - VerticalTailMass) +from aviary.subsystems.mass.flops_based.vertical_tail import AltVerticalTailMass, VerticalTailMass from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (Version, - flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + Version, + flops_validation_test, + get_flops_case_names, + get_flops_options, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission class VerticalTailMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "vertical_tail", - VerticalTailMass(aviary_options=get_flops_inputs(case_name)), + 'vertical_tail', + VerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + prob.model_options['*'] = get_flops_options(case_name, preprocess=True) + prob.setup(check=False, force_alloc_complex=True) flops_validation_test( prob, case_name, - input_keys=[Aircraft.VerticalTail.AREA, - Aircraft.VerticalTail.TAPER_RATIO, - Mission.Design.GROSS_MASS, - Aircraft.VerticalTail.MASS_SCALER], + input_keys=[ + Aircraft.VerticalTail.AREA, + Aircraft.VerticalTail.TAPER_RATIO, + Mission.Design.GROSS_MASS, + Aircraft.VerticalTail.MASS_SCALER, + ], output_keys=Aircraft.VerticalTail.MASS, - version=Version.TRANSPORT) + version=Version.TRANSPORT, + ) def test_IO(self): assert_match_varnames(self.prob.model) class VerticalTailMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.vertical_tail as vtail + vtail.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.vertical_tail as vtail + vtail.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "vertical_tail", - VerticalTailMass(aviary_options=get_flops_inputs("N3CC")), + 'vertical_tail', + VerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) + + prob.model_options['*'] = get_flops_options('AdvancedSingleAisle', preprocess=True) + prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.VerticalTail.AREA, 100, 'ft**2') prob.set_val(Mission.Design.GROSS_MASS, 1000.0, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AltVerticalTailMassTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob prob.model.add_subsystem( - "vertical_tail", - AltVerticalTailMass(aviary_options=get_flops_inputs(case_name)), + 'vertical_tail', + AltVerticalTailMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -101,14 +104,14 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.VerticalTail.AREA, - Aircraft.VerticalTail.MASS_SCALER], + input_keys=[Aircraft.VerticalTail.AREA, Aircraft.VerticalTail.MASS_SCALER], output_keys=Aircraft.VerticalTail.MASS, - version=Version.ALTERNATE) + version=Version.ALTERNATE, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_wing_common.py b/aviary/subsystems/mass/flops_based/test/test_wing_common.py index 69134fa47d..b416113f43 100644 --- a/aviary/subsystems/mass/flops_based/test/test_wing_common.py +++ b/aviary/subsystems/mass/flops_based/test/test_wing_common.py @@ -5,12 +5,16 @@ from parameterized import parameterized from aviary.subsystems.mass.flops_based.wing_common import ( - WingBendingMass, WingMiscMass, WingShearControlMass) -from aviary.variable_info.options import get_option_defaults + WingBendingMass, + WingMiscMass, + WingShearControlMass, +) from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + print_case, +) from aviary.variable_info.variables import Aircraft, Mission @@ -18,7 +22,7 @@ class WingShearControlMassTest(unittest.TestCase): def setUp(self): prob = self.prob = om.Problem() prob.model.add_subsystem( - "wing", + 'wing', WingShearControlMass(), promotes_inputs=['*'], promotes_outputs=['*'], @@ -26,44 +30,45 @@ def setUp(self): prob.setup(check=False, force_alloc_complex=True) - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.COMPOSITE_FRACTION, - Aircraft.Wing.CONTROL_SURFACE_AREA, - Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, - Mission.Design.GROSS_MASS], + input_keys=[ + Aircraft.Wing.COMPOSITE_FRACTION, + Aircraft.Wing.CONTROL_SURFACE_AREA, + Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, + Mission.Design.GROSS_MASS, + ], output_keys=Aircraft.Wing.SHEAR_CONTROL_MASS, atol=1e-11, - rtol=1e-11) + rtol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class WingShearControlMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.wing_common as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.wing_common as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "wing", + 'wing', WingShearControlMass(), promotes_inputs=['*'], promotes_outputs=['*'], @@ -73,15 +78,15 @@ def test_case(self): prob.set_val(Aircraft.Wing.CONTROL_SURFACE_AREA, 400, 'ft**2') prob.set_val(Mission.Design.GROSS_MASS, 100000, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=5e-12, rtol=1e-12) + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) class WingMiscMassTest(unittest.TestCase): def setUp(self): prob = self.prob = om.Problem() prob.model.add_subsystem( - "wing", + 'wing', WingMiscMass(), promotes_inputs=['*'], promotes_outputs=['*'], @@ -89,43 +94,44 @@ def setUp(self): prob.setup(check=False, force_alloc_complex=True) - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.COMPOSITE_FRACTION, - Aircraft.Wing.AREA, - Aircraft.Wing.MISC_MASS_SCALER], + input_keys=[ + Aircraft.Wing.COMPOSITE_FRACTION, + Aircraft.Wing.AREA, + Aircraft.Wing.MISC_MASS_SCALER, + ], output_keys=Aircraft.Wing.MISC_MASS, atol=1e-11, - rtol=1e-11) + rtol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class WingMiscMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.wing_common as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.wing_common as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "wing", + 'wing', WingMiscMass(), promotes_inputs=['*'], promotes_outputs=['*'], @@ -134,79 +140,85 @@ def test_case(self): prob.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.333, 'unitless') prob.set_val(Aircraft.Wing.AREA, 1000, 'ft**2') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class WingBendingMassTest(unittest.TestCase): def setUp(self): prob = self.prob = om.Problem() + + opts = { + Aircraft.Fuselage.NUM_FUSELAGES: 1, + } + prob.model.add_subsystem( - "wing", - WingBendingMass(aviary_options=get_option_defaults()), + 'wing', + WingBendingMass(**opts), promotes_inputs=['*'], promotes_outputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): - prob = self.prob flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, - Aircraft.Wing.BENDING_FACTOR, - Aircraft.Wing.BENDING_MASS_SCALER, - Aircraft.Wing.COMPOSITE_FRACTION, - Aircraft.Wing.ENG_POD_INERTIA_FACTOR, - Mission.Design.GROSS_MASS, - Aircraft.Wing.LOAD_FRACTION, - Aircraft.Wing.MISC_MASS, - Aircraft.Wing.MISC_MASS_SCALER, - Aircraft.Wing.SHEAR_CONTROL_MASS, - Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, - Aircraft.Wing.SPAN, - Aircraft.Wing.SWEEP, - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - Aircraft.Wing.VAR_SWEEP_MASS_PENALTY], - output_keys=Aircraft.Wing.BENDING_MASS, + input_keys=[ + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Wing.BENDING_MATERIAL_FACTOR, + Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, + Aircraft.Wing.COMPOSITE_FRACTION, + Aircraft.Wing.ENG_POD_INERTIA_FACTOR, + Mission.Design.GROSS_MASS, + Aircraft.Wing.LOAD_FRACTION, + Aircraft.Wing.MISC_MASS, + Aircraft.Wing.MISC_MASS_SCALER, + Aircraft.Wing.SHEAR_CONTROL_MASS, + Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, + Aircraft.Wing.SPAN, + Aircraft.Wing.SWEEP, + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, + Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, + ], + output_keys=Aircraft.Wing.BENDING_MATERIAL_MASS, atol=1e-11, - rtol=1e-11) + rtol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) class WingBendingMassTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.flops_based.wing_common as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.flops_based.wing_common as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case(self): - prob = om.Problem() + prob.model.add_subsystem( - "wing", - WingBendingMass(aviary_options=get_option_defaults()), + 'wing', + WingBendingMass(), promotes_inputs=['*'], promotes_outputs=['*'], ) prob.setup(check=False, force_alloc_complex=True) prob.set_val(Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, 0.333, 'unitless') - prob.set_val(Aircraft.Wing.BENDING_FACTOR, 10, 'unitless') + prob.set_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR, 10, 'unitless') prob.set_val(Aircraft.Wing.COMPOSITE_FRACTION, 0.333, 'unitless') prob.set_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR, 1, 'unitless') prob.set_val(Mission.Design.GROSS_MASS, 100000, 'lbm') @@ -215,10 +227,11 @@ def test_case(self): prob.set_val(Aircraft.Wing.SHEAR_CONTROL_MASS, 4000, 'lbm') prob.set_val(Aircraft.Wing.SPAN, 100, 'ft') prob.set_val(Aircraft.Wing.SWEEP, 20, 'deg') + prob.set_val(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.75, 'unitless') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py b/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py index 075fd3261f..681b10ae1c 100644 --- a/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py +++ b/aviary/subsystems/mass/flops_based/test/test_wing_detailed.py @@ -2,39 +2,55 @@ import numpy as np import openmdao.api as om - +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import parameterized -from aviary.subsystems.mass.flops_based.wing_detailed import \ - DetailedWingBendingFact -from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) -from aviary.variable_info.variables import Aircraft, Mission, Settings +from aviary.subsystems.mass.flops_based.wing_detailed import DetailedWingBendingFact +from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.utils.aviary_values import AviaryValues from aviary.utils.preprocessors import preprocess_propulsion -from aviary.subsystems.propulsion.engine_deck import EngineDeck -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from aviary.utils.test_utils.variable_test import assert_match_varnames +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) +from aviary.variable_info.variables import Aircraft, Mission, Settings class DetailedWingBendingTest(unittest.TestCase): - def setUp(self): self.prob = om.Problem() # Skip model that doesn't use detailed wing. - @parameterized.expand(get_flops_case_names(omit=['LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSalt']), - name_func=print_case) + @parameterized.expand( + get_flops_case_names(omit=['LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSalt']), + name_func=print_case, + ) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Engine.NUM_ENGINES: inputs.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Engine.NUM_WING_ENGINES: inputs.get_val(Aircraft.Engine.NUM_WING_ENGINES), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Aircraft.Wing.INPUT_STATION_DIST: inputs.get_val(Aircraft.Wing.INPUT_STATION_DIST), + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL: inputs.get_val( + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL + ), + Aircraft.Wing.NUM_INTEGRATION_STATIONS: inputs.get_val( + Aircraft.Wing.NUM_INTEGRATION_STATIONS + ), + } + self.prob.model.add_subsystem( - "wing", - DetailedWingBendingFact( - aviary_options=get_flops_inputs(case_name, preprocess=True)), + 'wing', + DetailedWingBendingFact(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -43,33 +59,38 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.LOAD_PATH_SWEEP_DIST, - Aircraft.Wing.THICKNESS_TO_CHORD_DIST, - Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, - Mission.Design.GROSS_MASS, - Aircraft.Engine.POD_MASS, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.ASPECT_RATIO_REF, - Aircraft.Wing.STRUT_BRACING_FACTOR, - Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, - Aircraft.Engine.WING_LOCATIONS, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Wing.THICKNESS_TO_CHORD_REF], - output_keys=[Aircraft.Wing.BENDING_FACTOR, - Aircraft.Wing.ENG_POD_INERTIA_FACTOR], + input_keys=[ + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, + Mission.Design.GROSS_MASS, + Aircraft.Engine.POD_MASS, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.ASPECT_RATIO_REF, + Aircraft.Wing.STRUT_BRACING_FACTOR, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Engine.WING_LOCATIONS, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.THICKNESS_TO_CHORD_REF, + ], + output_keys=[ + Aircraft.Wing.BENDING_MATERIAL_FACTOR, + Aircraft.Wing.ENG_POD_INERTIA_FACTOR, + ], method='fd', atol=1e-3, - rtol=1e-5) + rtol=1e-5, + ) def test_case_multiengine(self): prob = self.prob aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') + aviary_options.set_val(Settings.VERBOSITY, 0) engine_options = AviaryValues() engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) - engine_options.set_val(Aircraft.Engine.DATA_FILE, - 'models/engines/turbofan_28k.deck') + engine_options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.csv') engine_options.set_val(Settings.VERBOSITY, 0) engineModel1 = EngineDeck(options=engine_options) engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) @@ -79,21 +100,43 @@ def test_case_multiengine(self): preprocess_propulsion(aviary_options, [engineModel1, engineModel2, engineModel3]) - prob.model.add_subsystem('detailed_wing', DetailedWingBendingFact( - aviary_options=aviary_options), promotes=['*']) + options = { + Aircraft.Engine.NUM_ENGINES: aviary_options.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Engine.NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Engine.NUM_WING_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Aircraft.Wing.INPUT_STATION_DIST: aviary_options.get_val( + Aircraft.Wing.INPUT_STATION_DIST + ), + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL: aviary_options.get_val( + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL + ), + Aircraft.Wing.NUM_INTEGRATION_STATIONS: aviary_options.get_val( + Aircraft.Wing.NUM_INTEGRATION_STATIONS + ), + } + + prob.model.add_subsystem( + 'detailed_wing', DetailedWingBendingFact(**options), promotes=['*'] + ) prob.setup(force_alloc_complex=True) - input_keys = [Aircraft.Wing.LOAD_PATH_SWEEP_DIST, - Aircraft.Wing.THICKNESS_TO_CHORD_DIST, - Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, - Mission.Design.GROSS_MASS, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.ASPECT_RATIO_REF, - Aircraft.Wing.STRUT_BRACING_FACTOR, - Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Wing.THICKNESS_TO_CHORD_REF] + input_keys = [ + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, + Mission.Design.GROSS_MASS, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.ASPECT_RATIO_REF, + Aircraft.Wing.STRUT_BRACING_FACTOR, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.THICKNESS_TO_CHORD_REF, + ] for key in input_keys: val, units = aviary_options.get_item(key) @@ -110,29 +153,195 @@ def test_case_multiengine(self): prob.run_model() - bending_factor = prob.get_val(Aircraft.Wing.BENDING_FACTOR) + BENDING_MATERIAL_FACTOR = prob.get_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR) pod_inertia = prob.get_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR) - # manual computation of expected thrust reverser mass - bending_factor_expected = 11.59165669761 + BENDING_MATERIAL_FACTOR_expected = 11.59165669761 # 0.9600334354133278 if the factors are additive pod_inertia_expected = 0.9604608395586276 - assert_near_equal(bending_factor, bending_factor_expected, tolerance=1e-10) + assert_near_equal( + BENDING_MATERIAL_FACTOR, BENDING_MATERIAL_FACTOR_expected, tolerance=1e-10 + ) assert_near_equal(pod_inertia, pod_inertia_expected, tolerance=1e-10) partial_data = prob.check_partials( - out_stream=None, compact_print=True, show_only_incorrect=True, form='central', method="fd") + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + ) assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) - def test_extreme_engine_loc(self): + def test_case_fuselage_engines(self): + prob = self.prob aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') engine_options = AviaryValues() + engine_options.set_val(Settings.VERBOSITY, 0) + engine_options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.csv') + engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) + engine_options.set_val(Aircraft.Engine.NUM_WING_ENGINES, 0) + engine_options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 2) + engineModel = EngineDeck(options=engine_options) + + preprocess_propulsion(aviary_options, [engineModel]) + + options = { + Aircraft.Engine.NUM_ENGINES: aviary_options.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Engine.NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Engine.NUM_WING_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Aircraft.Wing.INPUT_STATION_DIST: aviary_options.get_val( + Aircraft.Wing.INPUT_STATION_DIST + ), + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL: aviary_options.get_val( + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL + ), + Aircraft.Wing.NUM_INTEGRATION_STATIONS: aviary_options.get_val( + Aircraft.Wing.NUM_INTEGRATION_STATIONS + ), + } + + prob.model.add_subsystem( + 'detailed_wing', + DetailedWingBendingFact(**options), + promotes=['*'], + ) + + prob.setup(force_alloc_complex=True) + + input_keys = [ + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, + Mission.Design.GROSS_MASS, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.ASPECT_RATIO_REF, + Aircraft.Wing.STRUT_BRACING_FACTOR, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.THICKNESS_TO_CHORD_REF, + ] + + for key in input_keys: + val, units = aviary_options.get_item(key) + prob.set_val(key, val, units) + + prob.set_val(Aircraft.Engine.POD_MASS, np.array([0]), units='lbm') + + wing_location = np.zeros(0) + wing_location = np.append(wing_location, [0.0]) + + prob.set_val(Aircraft.Engine.WING_LOCATIONS, wing_location) + + prob.run_model() + + BENDING_MATERIAL_FACTOR = prob.get_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR) + pod_inertia = prob.get_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR) + + BENDING_MATERIAL_FACTOR_expected = 11.59165669761 + pod_inertia_expected = 0.84 + assert_near_equal( + BENDING_MATERIAL_FACTOR, BENDING_MATERIAL_FACTOR_expected, tolerance=1e-10 + ) + assert_near_equal(pod_inertia, pod_inertia_expected, tolerance=1e-10) + + def test_case_fuselage_multiengine(self): + prob = self.prob + + aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') + + engine_options = AviaryValues() + engine_options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.csv') engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) engine_options.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2) - engine_options.set_val(Aircraft.Engine.DATA_FILE, - 'models/engines/turbofan_28k.deck') + engine_options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 0) + engineModel1 = EngineDeck(options=engine_options) + + engine_options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_22k.csv') + engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) + engine_options.set_val(Aircraft.Engine.NUM_WING_ENGINES, 0) + engine_options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 2) + engineModel2 = EngineDeck(options=engine_options) + + preprocess_propulsion(aviary_options, [engineModel1, engineModel2]) + + options = { + Aircraft.Engine.NUM_ENGINES: aviary_options.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Engine.NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Engine.NUM_WING_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Aircraft.Wing.INPUT_STATION_DIST: aviary_options.get_val( + Aircraft.Wing.INPUT_STATION_DIST + ), + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL: aviary_options.get_val( + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL + ), + Aircraft.Wing.NUM_INTEGRATION_STATIONS: aviary_options.get_val( + Aircraft.Wing.NUM_INTEGRATION_STATIONS + ), + } + + prob.model.add_subsystem( + 'detailed_wing', + DetailedWingBendingFact(**options), + promotes=['*'], + ) + + prob.setup(force_alloc_complex=True) + + input_keys = [ + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, + Mission.Design.GROSS_MASS, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.ASPECT_RATIO_REF, + Aircraft.Wing.STRUT_BRACING_FACTOR, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.THICKNESS_TO_CHORD_REF, + ] + + for key in input_keys: + val, units = aviary_options.get_item(key) + prob.set_val(key, val, units) + + prob.set_val(Aircraft.Engine.POD_MASS, np.array([1130, 0]), units='lbm') + + wing_locations = np.zeros(0) + wing_locations = np.append(wing_locations, [0.5]) + + prob.set_val(Aircraft.Engine.WING_LOCATIONS, wing_locations) + + prob.run_model() + + BENDING_MATERIAL_FACTOR = prob.get_val(Aircraft.Wing.BENDING_MATERIAL_FACTOR) + pod_inertia = prob.get_val(Aircraft.Wing.ENG_POD_INERTIA_FACTOR) + + BENDING_MATERIAL_FACTOR_expected = 11.59165669761 + pod_inertia_expected = 0.84 + assert_near_equal( + BENDING_MATERIAL_FACTOR, BENDING_MATERIAL_FACTOR_expected, tolerance=1e-10 + ) + assert_near_equal(pod_inertia, pod_inertia_expected, tolerance=1e-10) + + def test_extreme_engine_loc(self): + aviary_options = get_flops_inputs('LargeSingleAisle1FLOPS') + aviary_options.set_val(Settings.VERBOSITY, 0) + + engine_options = AviaryValues() + engine_options.set_val(Aircraft.Engine.NUM_ENGINES, 2) + engine_options.set_val(Aircraft.Engine.NUM_WING_ENGINES, 2) + engine_options.set_val(Aircraft.Engine.DATA_FILE, 'models/engines/turbofan_28k.csv') engine_options.set_val(Settings.VERBOSITY, 0) engineModel = EngineDeck(options=engine_options) @@ -140,24 +349,45 @@ def test_extreme_engine_loc(self): preprocess_propulsion(aviary_options, [engineModel]) + options = { + Aircraft.Engine.NUM_ENGINES: aviary_options.get_val(Aircraft.Engine.NUM_ENGINES), + Aircraft.Engine.NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Engine.NUM_WING_ENGINES + ), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: aviary_options.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + Aircraft.Wing.INPUT_STATION_DIST: aviary_options.get_val( + Aircraft.Wing.INPUT_STATION_DIST + ), + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL: aviary_options.get_val( + Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL + ), + Aircraft.Wing.NUM_INTEGRATION_STATIONS: aviary_options.get_val( + Aircraft.Wing.NUM_INTEGRATION_STATIONS + ), + } + self.prob.model.add_subsystem( - "wing", - DetailedWingBendingFact(aviary_options=aviary_options), + 'wing', + DetailedWingBendingFact(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) self.prob.setup(check=False) - input_keys = [Aircraft.Wing.LOAD_PATH_SWEEP_DIST, - Aircraft.Wing.THICKNESS_TO_CHORD_DIST, - Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, - Mission.Design.GROSS_MASS, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.ASPECT_RATIO_REF, - Aircraft.Wing.STRUT_BRACING_FACTOR, - Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Wing.THICKNESS_TO_CHORD_REF] + input_keys = [ + Aircraft.Wing.LOAD_PATH_SWEEP_DIST, + Aircraft.Wing.THICKNESS_TO_CHORD_DIST, + Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, + Mission.Design.GROSS_MASS, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.ASPECT_RATIO_REF, + Aircraft.Wing.STRUT_BRACING_FACTOR, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.THICKNESS_TO_CHORD_REF, + ] for key in input_keys: val, units = aviary_options.get_item(key) @@ -183,9 +413,9 @@ def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = DetailedWingBendingTest() # test.setUp() # test.test_case(case_name='LargeSingleAisle1FLOPS') - # test.test_extreme_engine_loc() + # test.test_case_multiengine() diff --git a/aviary/subsystems/mass/flops_based/test/test_wing_simple.py b/aviary/subsystems/mass/flops_based/test/test_wing_simple.py index da5d4148bb..2fb53b4b95 100644 --- a/aviary/subsystems/mass/flops_based/test/test_wing_simple.py +++ b/aviary/subsystems/mass/flops_based/test/test_wing_simple.py @@ -5,10 +5,12 @@ from aviary.subsystems.mass.flops_based.wing_simple import SimpleWingBendingFact from aviary.utils.test_utils.variable_test import assert_match_varnames -from aviary.validation_cases.validation_tests import (flops_validation_test, - get_flops_case_names, - get_flops_inputs, - print_case) +from aviary.validation_cases.validation_tests import ( + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + print_case, +) from aviary.variable_info.variables import Aircraft @@ -17,16 +19,24 @@ def setUp(self): self.prob = om.Problem() # Only dataset that uses the simple wing. - @parameterized.expand(get_flops_case_names(only=['LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSalt']), - name_func=print_case) + @parameterized.expand( + get_flops_case_names(only=['LargeSingleAisle2FLOPS', 'LargeSingleAisle2FLOPSalt']), + name_func=print_case, + ) def test_case(self, case_name): - prob = self.prob + inputs = get_flops_inputs(case_name, preprocess=True) + + options = { + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: inputs.get_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES + ), + } + prob.model.add_subsystem( - "wing", - SimpleWingBendingFact(aviary_options=get_flops_inputs( - case_name, preprocess=True)), + 'wing', + SimpleWingBendingFact(**options), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -36,22 +46,27 @@ def test_case(self, case_name): flops_validation_test( prob, case_name, - input_keys=[Aircraft.Wing.AREA, - Aircraft.Wing.SPAN, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Wing.STRUT_BRACING_FACTOR, - Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.SWEEP], - output_keys=[Aircraft.Wing.BENDING_FACTOR, - Aircraft.Wing.ENG_POD_INERTIA_FACTOR], + input_keys=[ + Aircraft.Wing.AREA, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.STRUT_BRACING_FACTOR, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.SWEEP, + ], + output_keys=[ + Aircraft.Wing.BENDING_MATERIAL_FACTOR, + Aircraft.Wing.ENG_POD_INERTIA_FACTOR, + ], atol=1e-11, - rtol=1e-11) + rtol=1e-11, + ) def test_IO(self): assert_match_varnames(self.prob.model) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/flops_based/thrust_reverser.py b/aviary/subsystems/mass/flops_based/thrust_reverser.py index 028c2969c5..0b83cd05b0 100644 --- a/aviary/subsystems/mass/flops_based/thrust_reverser.py +++ b/aviary/subsystems/mass/flops_based/thrust_reverser.py @@ -3,13 +3,12 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.subsystems.mass.flops_based.distributed_prop import nacelle_count_factor -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class ThrustReverserMass(om.ExplicitComponent): - ''' + """ Calculates mass of thrust reversers for entire set of an engine model. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. @@ -20,76 +19,89 @@ class ThrustReverserMass(om.ExplicitComponent): Currently assumed engine set level thrust reversers is the same as propulsion-level total sum of thrust reverser masses - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) add_aviary_input( - self, Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, val=np.zeros(num_engine_type)) + self, + Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, + shape=num_engine_type, + units='unitless', + ) add_aviary_input( - self, Aircraft.Engine.SCALED_SLS_THRUST, val=np.zeros(num_engine_type)) + self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type, units='lbf' + ) add_aviary_output( - self, Aircraft.Engine.THRUST_REVERSERS_MASS, val=np.zeros(num_engine_type)) - add_aviary_output( - self, Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, val=0) + self, Aircraft.Engine.THRUST_REVERSERS_MASS, shape=num_engine_type, units='lbm' + ) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, units='lbm') def setup_partials(self): # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) - self.declare_partials(Aircraft.Engine.THRUST_REVERSERS_MASS, - Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, - rows=shape, cols=shape, val=1.0) - - self.declare_partials(Aircraft.Engine.THRUST_REVERSERS_MASS, - Aircraft.Engine.SCALED_SLS_THRUST, - rows=shape, cols=shape, val=1.0) - - self.declare_partials(Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, - val=1.0) - - self.declare_partials(Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - Aircraft.Engine.SCALED_SLS_THRUST, - val=1.0) + self.declare_partials( + Aircraft.Engine.THRUST_REVERSERS_MASS, + Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, + rows=shape, + cols=shape, + val=1.0, + ) + + self.declare_partials( + Aircraft.Engine.THRUST_REVERSERS_MASS, + Aircraft.Engine.SCALED_SLS_THRUST, + rows=shape, + cols=shape, + val=1.0, + ) + + self.declare_partials( + Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, + Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, + val=1.0, + ) + + self.declare_partials( + Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, + Aircraft.Engine.SCALED_SLS_THRUST, + val=1.0, + ) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - num_eng = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] scaler = inputs[Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER] max_thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] nac_count = nacelle_count_factor(num_eng) - thrust_reverser_mass = .034 * max_thrust * nac_count * scaler / GRAV_ENGLISH_LBM + thrust_reverser_mass = 0.034 * max_thrust * nac_count * scaler / GRAV_ENGLISH_LBM outputs[Aircraft.Engine.THRUST_REVERSERS_MASS] = thrust_reverser_mass - outputs[Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS] = sum( - thrust_reverser_mass) + outputs[Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS] = sum(thrust_reverser_mass) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_eng = aviary_options.get_val(Aircraft.Engine.NUM_ENGINES) + num_eng = self.options[Aircraft.Engine.NUM_ENGINES] scaler = inputs[Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER] max_thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] nac_count = nacelle_count_factor(num_eng) - J[Aircraft.Engine.THRUST_REVERSERS_MASS, - Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER] = \ - .034 * max_thrust * nac_count / GRAV_ENGLISH_LBM - J[Aircraft.Engine.THRUST_REVERSERS_MASS, - Aircraft.Engine.SCALED_SLS_THRUST] = .034*nac_count * scaler / GRAV_ENGLISH_LBM - - J[Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER] = \ - .034 * max_thrust * nac_count / GRAV_ENGLISH_LBM - J[Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - Aircraft.Engine.SCALED_SLS_THRUST] = .034*nac_count * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Engine.THRUST_REVERSERS_MASS, Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER] = ( + 0.034 * max_thrust * nac_count / GRAV_ENGLISH_LBM + ) + J[Aircraft.Engine.THRUST_REVERSERS_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + 0.034 * nac_count * scaler / GRAV_ENGLISH_LBM + ) + + J[ + Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, + Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, + ] = 0.034 * max_thrust * nac_count / GRAV_ENGLISH_LBM + J[Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + 0.034 * nac_count * scaler / GRAV_ENGLISH_LBM + ) diff --git a/aviary/subsystems/mass/flops_based/unusable_fuel.py b/aviary/subsystems/mass/flops_based/unusable_fuel.py index 6b994718ad..d8e14fe168 100644 --- a/aviary/subsystems/mass/flops_based/unusable_fuel.py +++ b/aviary/subsystems/mass/flops_based/unusable_fuel.py @@ -2,14 +2,15 @@ from aviary.constants import GRAV_ENGLISH_LBM from aviary.subsystems.mass.flops_based.distributed_prop import ( - distributed_engine_count_factor, distributed_thrust_factor) -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output + distributed_engine_count_factor, + distributed_thrust_factor, +) +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class TransportUnusableFuelMass(om.ExplicitComponent): - ''' + """ Calculates the mass of unusable fuel using the default method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. @@ -18,49 +19,45 @@ class TransportUnusableFuelMass(om.ExplicitComponent): -----------. All engines use fuel, single engine model on aircraft (both engine level thrust (scaled by num_engines) and propulsion-level count factor is being used) - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fuel.NUM_TANKS) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) def setup(self): - add_aviary_input( - self, Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuel.DENSITY, units='lbm/galUS') + add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, units='lbf') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_output(self, Aircraft.Fuel.TOTAL_VOLUME, units='galUS') - add_aviary_input(self, Aircraft.Fuel.DENSITY_RATIO, 1.0) - - add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, 0.0) - - add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=0.0) - - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) - - add_aviary_output(self, Aircraft.Fuel.TOTAL_VOLUME, val=0.0) - - add_aviary_output(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS, val=0.0) + add_aviary_output(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS, units='lbm') def setup_partials(self): - self.declare_partials( - Aircraft.Fuel.TOTAL_VOLUME, - [Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Fuel.DENSITY_RATIO]) + Aircraft.Fuel.TOTAL_VOLUME, [Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Fuel.DENSITY] + ) self.declare_partials( Aircraft.Fuel.UNUSABLE_FUEL_MASS, [ Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, Aircraft.Wing.AREA, - Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Fuel.DENSITY_RATIO]) + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, + Aircraft.Wing.AREA, + Aircraft.Fuel.TOTAL_CAPACITY, + Aircraft.Fuel.DENSITY, + ], + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - aviary_options: AviaryValues = self.options['aviary_options'] - tank_count = aviary_options.get_val(Aircraft.Fuel.NUM_TANKS) + tank_count = self.options[Aircraft.Fuel.NUM_TANKS] scaler = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] - density_ratio = inputs[Aircraft.Fuel.DENSITY_RATIO] + # Calculate fuel density ratio relative to Jet A: 6.7 lbm/galUS = 50.11948 lbm/ft**3 + density_ratio = inputs[Aircraft.Fuel.DENSITY] / 6.7 total_capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] - num_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_eng_fact = distributed_engine_count_factor(num_eng) max_sls_thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] thrust_factor = distributed_thrust_factor(max_sls_thrust, num_eng) @@ -70,16 +67,24 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): # outputs[Aircraft.Fuel.TOTAL_VOLUME] = total_capacity / density_ratio outputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS] = ( - (11.5 * num_eng_fact * thrust_factor**0.2 + 0.07 * wing_area + 1.6 * tank_count * - total_capacity**0.28) * density_ratio) * scaler / GRAV_ENGLISH_LBM + ( + ( + 11.5 * num_eng_fact * thrust_factor**0.2 + + 0.07 * wing_area + + 1.6 * tank_count * total_capacity**0.28 + ) + * density_ratio + ) + * scaler + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - tank_count = aviary_options.get_val(Aircraft.Fuel.NUM_TANKS) + tank_count = self.options[Aircraft.Fuel.NUM_TANKS] scaler = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] - density_ratio = inputs[Aircraft.Fuel.DENSITY_RATIO] + density_ratio = inputs[Aircraft.Fuel.DENSITY] / 6.7 total_capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] - num_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) + num_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] num_eng_fact = distributed_engine_count_factor(num_eng) max_sls_thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] thrust_factor = distributed_thrust_factor(max_sls_thrust, num_eng) @@ -94,43 +99,44 @@ def compute_partials(self, inputs, J): # J[Aircraft.Fuel.TOTAL_VOLUME, Aircraft.Fuel.DENSITY_RATIO] = ( # -total_capacity / (density_ratio * density_ratio)) - J[ - Aircraft.Fuel.UNUSABLE_FUEL_MASS, - Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] = ( + J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] = ( (11.5 * num_eng_fact * term1 + 0.07 * wing_area + 1.6 * tank_count * term2) - * density_ratio / GRAV_ENGLISH_LBM) + * density_ratio + / GRAV_ENGLISH_LBM + ) J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] = ( - 2.3 * thrust_factor**-0.8 * density_ratio * scaler / GRAV_ENGLISH_LBM) + 2.3 * thrust_factor**-0.8 * density_ratio * scaler / GRAV_ENGLISH_LBM + ) J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Wing.AREA] = ( - 0.07 * density_ratio * scaler / GRAV_ENGLISH_LBM) + 0.07 * density_ratio * scaler / GRAV_ENGLISH_LBM + ) J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Fuel.TOTAL_CAPACITY] = ( - 0.448 * tank_count * total_capacity**-0.72 * density_ratio * scaler / GRAV_ENGLISH_LBM) + 0.448 * tank_count * total_capacity**-0.72 * density_ratio * scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Fuel.DENSITY_RATIO] = ( - 11.5 * num_eng_fact * term1 + 0.07 * wing_area + 1.6 * tank_count * term2) * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Fuel.DENSITY] = ( + ((11.5 * num_eng_fact * term1 + 0.07 * wing_area + 1.6 * tank_count * term2) / 6.7) + * scaler + / GRAV_ENGLISH_LBM + ) class AltUnusableFuelMass(om.ExplicitComponent): - ''' + """ Calculates the mass of unusable fuel using the alternate method. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, units='unitless') - add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, 0.0) + add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') - add_aviary_output(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS, 0.0) + add_aviary_output(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS, units='lbm') def setup_partials(self): self.declare_partials(of='*', wrt='*') @@ -139,21 +145,14 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): total_fuel_capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] scaler = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] - outputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS] = ( - 0.0084 * total_fuel_capacity * scaler - ) + outputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS] = 0.0084 * total_fuel_capacity * scaler def compute_partials(self, inputs, J): - total_fuel_capacity = inputs[Aircraft.Fuel.TOTAL_CAPACITY] scaler = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] - J[ - Aircraft.Fuel.UNUSABLE_FUEL_MASS, - Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] = ( + J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER] = ( 0.0084 * total_fuel_capacity ) - J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Fuel.TOTAL_CAPACITY] = ( - 0.0084 * scaler - ) + J[Aircraft.Fuel.UNUSABLE_FUEL_MASS, Aircraft.Fuel.TOTAL_CAPACITY] = 0.0084 * scaler diff --git a/aviary/subsystems/mass/flops_based/vertical_tail.py b/aviary/subsystems/mass/flops_based/vertical_tail.py index 68df78b736..db6f29eb8d 100644 --- a/aviary/subsystems/mass/flops_based/vertical_tail.py +++ b/aviary/subsystems/mass/flops_based/vertical_tail.py @@ -1,100 +1,104 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class VerticalTailMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the vertical tail(s). The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.VerticalTail.NUM_TAILS) def setup(self): - add_aviary_input(self, Aircraft.VerticalTail.AREA, val=0.0) + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.MASS_SCALER, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') - add_aviary_input(self, Aircraft.VerticalTail.TAPER_RATIO, val=0.0) - - add_aviary_input(self, Aircraft.VerticalTail.MASS_SCALER, val=1.0) - - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - - add_aviary_output(self, Aircraft.VerticalTail.MASS, val=0.0) + add_aviary_output(self, Aircraft.VerticalTail.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - num_tails = aviary_options.get_val(Aircraft.VerticalTail.NUM_TAILS) + num_tails = self.options[Aircraft.VerticalTail.NUM_TAILS] area = inputs[Aircraft.VerticalTail.AREA] taper_ratio = inputs[Aircraft.VerticalTail.TAPER_RATIO] scaler = inputs[Aircraft.VerticalTail.MASS_SCALER] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - outputs[Aircraft.VerticalTail.MASS] = scaler * 0.32 * \ - gross_weight ** 0.30 * (taper_ratio + 0.50) * area ** 0.85 * \ - num_tails ** 0.7 / GRAV_ENGLISH_LBM + outputs[Aircraft.VerticalTail.MASS] = ( + scaler + * 0.32 + * gross_weight**0.30 + * (taper_ratio + 0.50) + * area**0.85 + * num_tails**0.7 + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_tails = aviary_options.get_val(Aircraft.VerticalTail.NUM_TAILS) + num_tails = self.options[Aircraft.VerticalTail.NUM_TAILS] area = inputs[Aircraft.VerticalTail.AREA] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM taper_ratio = inputs[Aircraft.VerticalTail.TAPER_RATIO] scaler = inputs[Aircraft.VerticalTail.MASS_SCALER] - gross_weight_exp = gross_weight ** 0.30 - area_exp = area ** 0.85 - num_tails_exp = num_tails ** 0.7 + gross_weight_exp = gross_weight**0.30 + area_exp = area**0.85 + num_tails_exp = num_tails**0.7 - J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.AREA] = \ - scaler * 0.272 * gross_weight_exp * \ - (taper_ratio + 0.50) * area ** -0.15 * \ - num_tails_exp / GRAV_ENGLISH_LBM + J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.AREA] = ( + scaler + * 0.272 + * gross_weight_exp + * (taper_ratio + 0.50) + * area**-0.15 + * num_tails_exp + / GRAV_ENGLISH_LBM + ) - J[Aircraft.VerticalTail.MASS, Mission.Design.GROSS_MASS] = \ - scaler * 0.096 * gross_weight ** -0.70 * \ - (taper_ratio + 0.50) * area_exp * num_tails_exp + J[Aircraft.VerticalTail.MASS, Mission.Design.GROSS_MASS] = ( + scaler * 0.096 * gross_weight**-0.70 * (taper_ratio + 0.50) * area_exp * num_tails_exp + ) - J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.TAPER_RATIO] = \ + J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.TAPER_RATIO] = ( scaler * 0.32 * gross_weight_exp * area_exp * num_tails_exp / GRAV_ENGLISH_LBM + ) - J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.MASS_SCALER] = \ - 0.32 * gross_weight_exp * (taper_ratio + 0.50) * \ - area_exp * num_tails_exp / GRAV_ENGLISH_LBM + J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.MASS_SCALER] = ( + 0.32 + * gross_weight_exp + * (taper_ratio + 0.50) + * area_exp + * num_tails_exp + / GRAV_ENGLISH_LBM + ) class AltVerticalTailMass(om.ExplicitComponent): - ''' + """ Calculates the mass of the vertical tail(s) using the alternate method. The methodology is based on the FLOPS weight- equations, modified to output mass instead of weight. - ''' - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """ def setup(self): - add_aviary_input(self, Aircraft.VerticalTail.AREA, val=0.0) + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') - add_aviary_input(self, Aircraft.VerticalTail.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.VerticalTail.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.VerticalTail.MASS, val=0.0) + add_aviary_output(self, Aircraft.VerticalTail.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): area = inputs[Aircraft.VerticalTail.AREA] @@ -106,10 +110,6 @@ def compute_partials(self, inputs, J): area = inputs[Aircraft.VerticalTail.AREA] scaler = inputs[Aircraft.VerticalTail.MASS_SCALER] - J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.AREA] = ( - 6.0 * scaler - ) + J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.AREA] = 6.0 * scaler - J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.MASS_SCALER] = ( - 6.0 * area - ) + J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.MASS_SCALER] = 6.0 * area diff --git a/aviary/subsystems/mass/flops_based/wing_common.py b/aviary/subsystems/mass/flops_based/wing_common.py index e810dad45e..0850db114b 100644 --- a/aviary/subsystems/mass/flops_based/wing_common.py +++ b/aviary/subsystems/mass/flops_based/wing_common.py @@ -2,49 +2,46 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class WingBendingMass(om.ExplicitComponent): - ''' + """ Calculates the mass of wing bending material. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Fuselage.NUM_FUSELAGES) def setup(self): - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - add_aviary_input(self, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, val=0.0) - add_aviary_input(self, Aircraft.Wing.BENDING_FACTOR, val=0.0) - add_aviary_input(self, Aircraft.Wing.BENDING_MASS_SCALER, val=1.0) - add_aviary_input(self, Aircraft.Wing.COMPOSITE_FRACTION, val=0.0) - add_aviary_input(self, Aircraft.Wing.ENG_POD_INERTIA_FACTOR, val=0.0) - add_aviary_input(self, Aircraft.Wing.LOAD_FRACTION, val=0.0) - add_aviary_input(self, Aircraft.Wing.MISC_MASS, val=0.0) - add_aviary_input(self, Aircraft.Wing.MISC_MASS_SCALER, val=1.0) - add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS, val=0.0) - add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, val=1.0) - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) - add_aviary_input(self, Aircraft.Wing.SWEEP, val=0.0) - add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.75) - add_aviary_input(self, Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, val=0.0) - - add_aviary_output(self, Aircraft.Wing.BENDING_MASS, val=0.0) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.BENDING_MATERIAL_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Wing.COMPOSITE_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.Wing.ENG_POD_INERTIA_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.LOAD_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.Wing.MISC_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.MISC_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS) + add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, units='unitless') + + add_aviary_output(self, Aircraft.Wing.BENDING_MATERIAL_MASS, units='lbm') self.A1 = 8.80 self.A2 = 6.25 def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): - bt = inputs[Aircraft.Wing.BENDING_FACTOR] + bt = inputs[Aircraft.Wing.BENDING_MATERIAL_FACTOR] ulf = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] span = inputs[Aircraft.Wing.SPAN] comp_frac = inputs[Aircraft.Wing.COMPOSITE_FRACTION] @@ -54,30 +51,48 @@ def compute(self, inputs, outputs): sweep = inputs[Aircraft.Wing.SWEEP] gross_weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM CAYE = inputs[Aircraft.Wing.ENG_POD_INERTIA_FACTOR] - scaler = inputs[Aircraft.Wing.BENDING_MASS_SCALER] + scaler = inputs[Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER] - num_fuse = self.options['aviary_options'].get_val( - Aircraft.Fuselage.NUM_FUSELAGES) + num_fuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] # Note: Calculation requires weights prior to being scaled, so we need to divide # by the scale factor. - W2 = inputs[Aircraft.Wing.SHEAR_CONTROL_MASS] / \ - inputs[Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] * GRAV_ENGLISH_LBM - W3 = inputs[Aircraft.Wing.MISC_MASS] / \ - inputs[Aircraft.Wing.MISC_MASS_SCALER] * GRAV_ENGLISH_LBM - - vfact = 1.0 + varswp * (0.96 / np.cos(np.pi / 180. * sweep) - 1.0) + W2 = ( + inputs[Aircraft.Wing.SHEAR_CONTROL_MASS] + / inputs[Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] + * GRAV_ENGLISH_LBM + ) + W3 = ( + inputs[Aircraft.Wing.MISC_MASS] + / inputs[Aircraft.Wing.MISC_MASS_SCALER] + * GRAV_ENGLISH_LBM + ) + + vfact = 1.0 + varswp * (0.96 / np.cos(np.pi / 180.0 * sweep) - 1.0) cayf = 0.5 if num_fuse > 1 else 1.0 - W1NIR = self.A1 * bt * (1.0 + (self.A2 / span)**0.5) * ulf * span * \ - (1.0 - 0.4 * comp_frac) * (1.0 - 0.1 * faert) * cayf * vfact * pctl * 1.0e-6 - - outputs[Aircraft.Wing.BENDING_MASS] = ( - (gross_weight * CAYE * W1NIR + W2 + W3) / (1.0 + W1NIR) - W2 - W3) \ - * scaler / GRAV_ENGLISH_LBM + W1NIR = ( + self.A1 + * bt + * (1.0 + (self.A2 / span) ** 0.5) + * ulf + * span + * (1.0 - 0.4 * comp_frac) + * (1.0 - 0.1 * faert) + * cayf + * vfact + * pctl + * 1.0e-6 + ) + + outputs[Aircraft.Wing.BENDING_MATERIAL_MASS] = ( + ((gross_weight * CAYE * W1NIR + W2 + W3) / (1.0 + W1NIR) - W2 - W3) + * scaler + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): - bt = inputs[Aircraft.Wing.BENDING_FACTOR] + bt = inputs[Aircraft.Wing.BENDING_MATERIAL_FACTOR] ulf = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] span = inputs[Aircraft.Wing.SPAN] comp_frac = inputs[Aircraft.Wing.COMPOSITE_FRACTION] @@ -91,128 +106,143 @@ def compute_partials(self, inputs, J): W3 = inputs[Aircraft.Wing.MISC_MASS] * GRAV_ENGLISH_LBM W2scale = inputs[Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] W3scale = inputs[Aircraft.Wing.MISC_MASS_SCALER] - scaler = inputs[Aircraft.Wing.BENDING_MASS_SCALER] + scaler = inputs[Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER] - num_fuse = self.options['aviary_options'].get_val( - Aircraft.Fuselage.NUM_FUSELAGES) + num_fuse = self.options[Aircraft.Fuselage.NUM_FUSELAGES] - deg2rad = np.pi / 180. + deg2rad = np.pi / 180.0 term = 0.96 / np.cos(deg2rad * sweep) vfact = 1.0 + varswp * (term - 1.0) - dvfact_varswp = (term - 1.0) + dvfact_varswp = term - 1.0 dvfact_sweep = varswp * deg2rad * term * np.tan(deg2rad * sweep) cayf = 0.5 if num_fuse > 1 else 1.0 - fact0 = (self.A2 / span)**0.5 + fact0 = (self.A2 / span) ** 0.5 fact1 = 1.0 + fact0 fact2 = 1.0 - 0.4 * comp_frac fact3 = 1.0 - 0.1 * faert - W1NIR = ( - self.A1 * bt * fact1 * ulf * span * fact2 * fact3 * cayf * vfact * pctl - * 1.0e-6) - dW1NIR_bt = \ - self.A1 * fact1 * ulf * span * fact2 * fact3 * cayf * vfact * pctl * 1.0e-6 - dW1NIR_ulf = \ - self.A1 * bt * fact1 * span * fact2 * fact3 * cayf * vfact * pctl * 1.0e-6 - dW1NIR_pctl = \ - self.A1 * bt * fact1 * ulf * span * fact2 * fact3 * cayf * vfact * 1.0e-6 - dW1NIR_cayf = \ - self.A1 * bt * fact1 * ulf * span * fact2 * fact3 * vfact * pctl * 1.0e-6 - dW1NIR_compfrac = -self.A1 * bt * fact1 * ulf * \ - span * 0.4 * fact3 * cayf * vfact * pctl * 1.0e-6 - dW1NIR_faert = -self.A1 * bt * fact1 * ulf * \ - span * fact2 * 0.1 * cayf * vfact * pctl * 1.0e-6 - dW1NIR_varswp = self.A1 * bt * fact1 * ulf * span * \ - fact2 * fact3 * cayf * dvfact_varswp * pctl * 1.0e-6 - dW1NIR_sweep = self.A1 * bt * fact1 * ulf * span * \ - fact2 * fact3 * cayf * dvfact_sweep * pctl * 1.0e-6 + W1NIR = self.A1 * bt * fact1 * ulf * span * fact2 * fact3 * cayf * vfact * pctl * 1.0e-6 + dW1NIR_bt = self.A1 * fact1 * ulf * span * fact2 * fact3 * cayf * vfact * pctl * 1.0e-6 + dW1NIR_ulf = self.A1 * bt * fact1 * span * fact2 * fact3 * cayf * vfact * pctl * 1.0e-6 + dW1NIR_pctl = self.A1 * bt * fact1 * ulf * span * fact2 * fact3 * cayf * vfact * 1.0e-6 + dW1NIR_compfrac = ( + -self.A1 * bt * fact1 * ulf * span * 0.4 * fact3 * cayf * vfact * pctl * 1.0e-6 + ) + dW1NIR_faert = ( + -self.A1 * bt * fact1 * ulf * span * fact2 * 0.1 * cayf * vfact * pctl * 1.0e-6 + ) + dW1NIR_varswp = ( + self.A1 * bt * fact1 * ulf * span * fact2 * fact3 * cayf * dvfact_varswp * pctl * 1.0e-6 + ) + dW1NIR_sweep = ( + self.A1 * bt * fact1 * ulf * span * fact2 * fact3 * cayf * dvfact_sweep * pctl * 1.0e-6 + ) dfact1_span = -0.5 * self.A2 / (fact0 * span * span) - dW1NIR_span = self.A1 * bt * \ - (dfact1_span * span + fact1) * ulf * \ - fact2 * fact3 * cayf * vfact * pctl * 1.0e-6 - - fact1 = gross_weight * CAYE * W1NIR + W2/W2scale + W3/W3scale + dW1NIR_span = ( + self.A1 + * bt + * (dfact1_span * span + fact1) + * ulf + * fact2 + * fact3 + * cayf + * vfact + * pctl + * 1.0e-6 + ) + + fact1 = gross_weight * CAYE * W1NIR + W2 / W2scale + W3 / W3scale fact2 = 1.0 / (1.0 + W1NIR) dbend_w1nir = scaler * (gross_weight * CAYE * fact2 - fact1 * fact2**2) - J[Aircraft.Wing.BENDING_MASS, Mission.Design.GROSS_MASS] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Mission.Design.GROSS_MASS] = ( CAYE * W1NIR * fact2 * scaler + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.ENG_POD_INERTIA_FACTOR] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.ENG_POD_INERTIA_FACTOR] = ( gross_weight * W1NIR * fact2 * scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.SHEAR_CONTROL_MASS] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.SHEAR_CONTROL_MASS] = ( (fact2 - 1.0) * scaler / W2scale + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] = \ - -(fact2 - 1.0) * scaler * W2 / W2scale ** 2 / GRAV_ENGLISH_LBM + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] = ( + -(fact2 - 1.0) * scaler * W2 / W2scale**2 / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.MISC_MASS] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.MISC_MASS] = ( (fact2 - 1.0) * scaler / W3scale + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.MISC_MASS_SCALER] = \ - -(fact2 - 1.0) * scaler * W3 / W3scale ** 2 / GRAV_ENGLISH_LBM + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.MISC_MASS_SCALER] = ( + -(fact2 - 1.0) * scaler * W3 / W3scale**2 / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.BENDING_MASS_SCALER] = \ - (fact1 * fact2 - W2/W2scale - W3/W3scale) / GRAV_ENGLISH_LBM + J[ + Aircraft.Wing.BENDING_MATERIAL_MASS, + Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, + ] = (fact1 * fact2 - W2 / W2scale - W3 / W3scale) / GRAV_ENGLISH_LBM - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.BENDING_FACTOR] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.BENDING_MATERIAL_FACTOR] = ( dbend_w1nir * dW1NIR_bt / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ( dbend_w1nir * dW1NIR_ulf / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.LOAD_FRACTION] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.LOAD_FRACTION] = ( dbend_w1nir * dW1NIR_pctl / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.COMPOSITE_FRACTION] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.COMPOSITE_FRACTION] = ( dbend_w1nir * dW1NIR_compfrac / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR] = \ - dbend_w1nir * dW1NIR_faert / GRAV_ENGLISH_LBM + J[ + Aircraft.Wing.BENDING_MATERIAL_MASS, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + ] = dbend_w1nir * dW1NIR_faert / GRAV_ENGLISH_LBM - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.VAR_SWEEP_MASS_PENALTY] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.VAR_SWEEP_MASS_PENALTY] = ( dbend_w1nir * dW1NIR_varswp / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.SWEEP] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.SWEEP] = ( dbend_w1nir * dW1NIR_sweep / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.BENDING_MASS, Aircraft.Wing.SPAN] = \ + J[Aircraft.Wing.BENDING_MATERIAL_MASS, Aircraft.Wing.SPAN] = ( dbend_w1nir * dW1NIR_span / GRAV_ENGLISH_LBM + ) class WingShearControlMass(om.ExplicitComponent): - ''' + """ Calculates the mass of wing shear control material. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - self.options.declare( 'aircraft_type', default='Transport', values=['Transport', 'HWB', 'GA'], - desc='Aircfaft type: Tranpsport, HWB, or GA') + desc='Aircfaft type: Tranpsport, HWB, or GA', + ) def setup(self): - add_aviary_input(self, Aircraft.Wing.COMPOSITE_FRACTION, val=0.0) - - add_aviary_input(self, Aircraft.Wing.CONTROL_SURFACE_AREA, val=0.0) - - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - - add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Wing.COMPOSITE_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.Wing.CONTROL_SURFACE_AREA, units='ft**2') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Wing.SHEAR_CONTROL_MASS, val=0.0) + add_aviary_output(self, Aircraft.Wing.SHEAR_CONTROL_MASS, units='lbm') - if ( - (self.options['aircraft_type'] == 'Transport') - or (self.options['aircraft_type'] == 'HWB') + if (self.options['aircraft_type'] == 'Transport') or ( + self.options['aircraft_type'] == 'HWB' ): self.A3 = 0.68 self.A4 = 0.34 @@ -223,7 +253,7 @@ def setup(self): self.A5 = 0.50 def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): comp_frac = inputs[Aircraft.Wing.COMPOSITE_FRACTION] @@ -231,9 +261,14 @@ def compute(self, inputs, outputs): ctrl_area = inputs[Aircraft.Wing.CONTROL_SURFACE_AREA] scaler = inputs[Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] - outputs[Aircraft.Wing.SHEAR_CONTROL_MASS] = \ - self.A3 * (1.0 - 0.17 * comp_frac) * ctrl_area ** self.A4 * \ - gross_weight ** self.A5 * scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.Wing.SHEAR_CONTROL_MASS] = ( + self.A3 + * (1.0 - 0.17 * comp_frac) + * ctrl_area**self.A4 + * gross_weight**self.A5 + * scaler + / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): comp_frac = inputs[Aircraft.Wing.COMPOSITE_FRACTION] @@ -243,55 +278,55 @@ def compute_partials(self, inputs, J): comp_frac_term = self.A3 * (1.0 - 0.17 * comp_frac) - J[Aircraft.Wing.SHEAR_CONTROL_MASS, Aircraft.Wing.COMPOSITE_FRACTION] = \ - -0.17 * self.A3 * ctrl_area ** self.A4 * \ - gross_weight ** self.A5 * scaler / GRAV_ENGLISH_LBM + J[Aircraft.Wing.SHEAR_CONTROL_MASS, Aircraft.Wing.COMPOSITE_FRACTION] = ( + -0.17 * self.A3 * ctrl_area**self.A4 * gross_weight**self.A5 * scaler / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.SHEAR_CONTROL_MASS, Aircraft.Wing.CONTROL_SURFACE_AREA] = \ - comp_frac_term * self.A4 * \ - ctrl_area ** (self.A4-1.0) * gross_weight ** self.A5 * \ - scaler / GRAV_ENGLISH_LBM + J[Aircraft.Wing.SHEAR_CONTROL_MASS, Aircraft.Wing.CONTROL_SURFACE_AREA] = ( + comp_frac_term + * self.A4 + * ctrl_area ** (self.A4 - 1.0) + * gross_weight**self.A5 + * scaler + / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.SHEAR_CONTROL_MASS, Mission.Design.GROSS_MASS] = \ - comp_frac_term * ctrl_area ** self.A4 * self.A5 * \ - gross_weight ** (self.A5-1.0) * scaler + J[Aircraft.Wing.SHEAR_CONTROL_MASS, Mission.Design.GROSS_MASS] = ( + comp_frac_term * ctrl_area**self.A4 * self.A5 * gross_weight ** (self.A5 - 1.0) * scaler + ) - J[ - Aircraft.Wing.SHEAR_CONTROL_MASS, - Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] = \ - self.A3 * (1.0 - 0.17 * comp_frac) * \ - ctrl_area ** self.A4 * gross_weight ** self.A5 / GRAV_ENGLISH_LBM + J[Aircraft.Wing.SHEAR_CONTROL_MASS, Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER] = ( + self.A3 + * (1.0 - 0.17 * comp_frac) + * ctrl_area**self.A4 + * gross_weight**self.A5 + / GRAV_ENGLISH_LBM + ) class WingMiscMass(om.ExplicitComponent): - ''' + """ Calculates the mass of wing miscellaneous material. The methodology is based on the FLOPS weight equations, modified to output mass instead of weight. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - self.options.declare( 'aircraft_type', default='Transport', values=['Transport', 'HWB', 'GA'], - desc='Aircfaft type: Tranpsport, HWB, or GA') + desc='Aircfaft type: Tranpsport, HWB, or GA', + ) def setup(self): - add_aviary_input(self, Aircraft.Wing.COMPOSITE_FRACTION, val=0.0) - - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) + add_aviary_input(self, Aircraft.Wing.COMPOSITE_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.MISC_MASS_SCALER, units='unitless') - add_aviary_input(self, Aircraft.Wing.MISC_MASS_SCALER, val=1.0) + add_aviary_output(self, Aircraft.Wing.MISC_MASS, units='lbm') - add_aviary_output(self, Aircraft.Wing.MISC_MASS, val=0.0) - - if ( - (self.options['aircraft_type'] == 'Transport') - or (self.options['aircraft_type'] == 'HWB') + if (self.options['aircraft_type'] == 'Transport') or ( + self.options['aircraft_type'] == 'HWB' ): self.A6 = 0.035 self.A7 = 1.50 @@ -300,59 +335,55 @@ def setup(self): self.A7 = 1.2 def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): comp_frac = inputs[Aircraft.Wing.COMPOSITE_FRACTION] area = inputs[Aircraft.Wing.AREA] scaler = inputs[Aircraft.Wing.MISC_MASS_SCALER] - outputs[Aircraft.Wing.MISC_MASS] = self.A6 * \ - (1.0 - 0.3 * comp_frac) * area ** self.A7 * \ - scaler / GRAV_ENGLISH_LBM + outputs[Aircraft.Wing.MISC_MASS] = ( + self.A6 * (1.0 - 0.3 * comp_frac) * area**self.A7 * scaler / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): comp_frac = inputs[Aircraft.Wing.COMPOSITE_FRACTION] area = inputs[Aircraft.Wing.AREA] scaler = inputs[Aircraft.Wing.MISC_MASS_SCALER] - J[Aircraft.Wing.MISC_MASS, Aircraft.Wing.COMPOSITE_FRACTION] = - \ - 0.3 * self.A6 * area ** self.A7 * scaler / GRAV_ENGLISH_LBM - J[Aircraft.Wing.MISC_MASS, Aircraft.Wing.AREA] = self.A6 * \ - (1.0 - 0.3 * comp_frac) * self.A7 * \ - area ** (self.A7-1) * scaler / GRAV_ENGLISH_LBM - J[Aircraft.Wing.MISC_MASS, Aircraft.Wing.MISC_MASS_SCALER] = self.A6 * \ - (1.0 - 0.3 * comp_frac) * area ** self.A7 / GRAV_ENGLISH_LBM + J[Aircraft.Wing.MISC_MASS, Aircraft.Wing.COMPOSITE_FRACTION] = ( + -0.3 * self.A6 * area**self.A7 * scaler / GRAV_ENGLISH_LBM + ) + J[Aircraft.Wing.MISC_MASS, Aircraft.Wing.AREA] = ( + self.A6 + * (1.0 - 0.3 * comp_frac) + * self.A7 + * area ** (self.A7 - 1) + * scaler + / GRAV_ENGLISH_LBM + ) + J[Aircraft.Wing.MISC_MASS, Aircraft.Wing.MISC_MASS_SCALER] = ( + self.A6 * (1.0 - 0.3 * comp_frac) * area**self.A7 / GRAV_ENGLISH_LBM + ) class WingTotalMass(om.ExplicitComponent): - """ - Computation of wing mass using FLOPS-based detailed wing mass equations. - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + """Computation of wing mass using FLOPS-based detailed wing mass equations.""" def setup(self): - add_aviary_input(self, Aircraft.Wing.BENDING_MASS, val=0.0) - - add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS, val=0.0) - - add_aviary_input(self, Aircraft.Wing.MISC_MASS, val=0.0) - - add_aviary_input(self, Aircraft.Wing.BWB_AFTBODY_MASS, val=0.0) - - add_aviary_input(self, Aircraft.Wing.MASS_SCALER, val=1.0) + add_aviary_input(self, Aircraft.Wing.BENDING_MATERIAL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.SHEAR_CONTROL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.MISC_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.BWB_AFTBODY_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.MASS_SCALER, units='unitless') - add_aviary_output(self, Aircraft.Wing.MASS, val=0) + add_aviary_output(self, Aircraft.Wing.MASS, units='lbm') def setup_partials(self): - self.declare_partials("*", "*") + self.declare_partials('*', '*') def compute(self, inputs, outputs): - m1 = inputs[Aircraft.Wing.BENDING_MASS] + m1 = inputs[Aircraft.Wing.BENDING_MATERIAL_MASS] m2 = inputs[Aircraft.Wing.SHEAR_CONTROL_MASS] m3 = inputs[Aircraft.Wing.MISC_MASS] m4 = inputs[Aircraft.Wing.BWB_AFTBODY_MASS] @@ -361,13 +392,13 @@ def compute(self, inputs, outputs): outputs[Aircraft.Wing.MASS] = (m1 + m2 + m3 + m4) * m_scaler def compute_partials(self, inputs, J): - m1 = inputs[Aircraft.Wing.BENDING_MASS] + m1 = inputs[Aircraft.Wing.BENDING_MATERIAL_MASS] m2 = inputs[Aircraft.Wing.SHEAR_CONTROL_MASS] m3 = inputs[Aircraft.Wing.MISC_MASS] m4 = inputs[Aircraft.Wing.BWB_AFTBODY_MASS] m_scaler = inputs[Aircraft.Wing.MASS_SCALER] - J[Aircraft.Wing.MASS, Aircraft.Wing.BENDING_MASS] = m_scaler + J[Aircraft.Wing.MASS, Aircraft.Wing.BENDING_MATERIAL_MASS] = m_scaler J[Aircraft.Wing.MASS, Aircraft.Wing.SHEAR_CONTROL_MASS] = m_scaler J[Aircraft.Wing.MASS, Aircraft.Wing.MISC_MASS] = m_scaler J[Aircraft.Wing.MASS, Aircraft.Wing.BWB_AFTBODY_MASS] = m_scaler diff --git a/aviary/subsystems/mass/flops_based/wing_detailed.py b/aviary/subsystems/mass/flops_based/wing_detailed.py index 521f3c9d0f..29e8adec6f 100644 --- a/aviary/subsystems/mass/flops_based/wing_detailed.py +++ b/aviary/subsystems/mass/flops_based/wing_detailed.py @@ -1,10 +1,8 @@ import numpy as np - import openmdao.api as om from openmdao.components.interp_util.interp import InterpND -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission @@ -12,70 +10,68 @@ class DetailedWingBendingFact(om.ExplicitComponent): """ Computation of wing bending factor and engine inertia relief factor used for FLOPS-based detailed wing mass estimation. + + If one or zero wing-mounted engines are present, it is assumed there is no engine + inertial relief factor (i.e. the single engine is mounted at the wing root) """ + # Basically, Engine.WING_LOCATIONS is ignored if there are one or fewer wing engines + def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Engine.NUM_WING_ENGINES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) + add_aviary_option(self, Aircraft.Wing.INPUT_STATION_DIST) + add_aviary_option(self, Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL) + add_aviary_option(self, Aircraft.Wing.NUM_INTEGRATION_STATIONS) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] - input_station_dist = aviary_options.get_val(Aircraft.Wing.INPUT_STATION_DIST) + input_station_dist = self.options[Aircraft.Wing.INPUT_STATION_DIST] num_input_stations = len(input_station_dist) - total_num_wing_engines = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) - num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - - # wing locations are different for each engine type - ragged array! - # this "tricks" numpy into allowing a ragged array, with limitations (each index - # in the numpy array contains a list, instead of being a true 2d matrix) - # wing_location_default = np.empty(num_engine_type, object) - # wing_location_default[:] = [np.array([0]*int(num)) for num in num_wing_engines/2] - - add_aviary_input(self, Aircraft.Wing.LOAD_PATH_SWEEP_DIST, - val=np.zeros(num_input_stations - 1)) - - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_DIST, - val=np.zeros(num_input_stations)) - - add_aviary_input(self, Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, - val=np.zeros(num_input_stations)) - - add_aviary_input(self, Mission.Design.GROSS_MASS, val=0.0) - - add_aviary_input(self, Aircraft.Engine.POD_MASS, val=np.zeros(num_engine_type)) - - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=0.0) - - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO_REF, val=0.0) - - add_aviary_input(self, Aircraft.Wing.STRUT_BRACING_FACTOR, val=0.0) - - add_aviary_input(self, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, val=0.0) - - add_aviary_input(self, Aircraft.Engine.WING_LOCATIONS, - val=np.zeros(int(total_num_wing_engines/2))) - - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, val=0.0) - - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_REF, val=0.0) + total_num_wing_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input( + self, Aircraft.Wing.LOAD_PATH_SWEEP_DIST, shape=num_input_stations - 1, units='deg' + ) + add_aviary_input( + self, Aircraft.Wing.THICKNESS_TO_CHORD_DIST, shape=num_input_stations, units='unitless' + ) + add_aviary_input( + self, Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, shape=num_input_stations, units='unitless' + ) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Engine.POD_MASS, shape=num_engine_type, units='lbm') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO_REF, units='unitless') + add_aviary_input(self, Aircraft.Wing.STRUT_BRACING_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, units='unitless') + + if total_num_wing_engines > 1: + add_aviary_input( + self, + Aircraft.Engine.WING_LOCATIONS, + shape=int(total_num_wing_engines / 2), + units='unitless', + ) + else: + add_aviary_input(self, Aircraft.Engine.WING_LOCATIONS, units='unitless') - add_aviary_output(self, Aircraft.Wing.BENDING_FACTOR, val=0.0) + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_REF, units='unitless') - add_aviary_output(self, Aircraft.Wing.ENG_POD_INERTIA_FACTOR, val=0.0) + add_aviary_output(self, Aircraft.Wing.BENDING_MATERIAL_FACTOR, units='unitless') + add_aviary_output(self, Aircraft.Wing.ENG_POD_INERTIA_FACTOR, units='unitless') def setup_partials(self): # TODO: Analytic derivs will be challenging, but possible. - self.declare_partials("*", "*", method='cs') + self.declare_partials('*', '*', method='cs') def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - input_station_dist = aviary_options.get_val(Aircraft.Wing.INPUT_STATION_DIST) + input_station_dist = self.options[Aircraft.Wing.INPUT_STATION_DIST] inp_stations = np.array(input_station_dist) - num_integration_stations = \ - aviary_options.get_val(Aircraft.Wing.NUM_INTEGRATION_STATIONS) - num_wing_engines = aviary_options.get_val(Aircraft.Engine.NUM_WING_ENGINES) + num_integration_stations = self.options[Aircraft.Wing.NUM_INTEGRATION_STATIONS] + num_wing_engines = self.options[Aircraft.Engine.NUM_WING_ENGINES] num_engine_type = len(num_wing_engines) # TODO: Support all options for this parameter. @@ -85,8 +81,7 @@ def compute(self, inputs, outputs): # 3.0 : rectangular distribution # 1.0-2.0 : blend of triangular and elliptical # 2.0-3.0 : blend of elliptical and rectangular - load_distribution_factor = \ - aviary_options.get_val(Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL) + load_distribution_factor = self.options[Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL] load_path_sweep = inputs[Aircraft.Wing.LOAD_PATH_SWEEP_DIST] thickness_to_chord = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_DIST] @@ -121,53 +116,67 @@ def compute(self, inputs, outputs): per_section = int(stations_per_section[i]) integration_stations = np.append( integration_stations, - np.linspace(inp_stations[i], val, per_section, endpoint=endpoint)) - sweep_int_stations = np.append(sweep_int_stations, - load_path_sweep[i] * np.ones(per_section)) + np.linspace(inp_stations[i], val, per_section, endpoint=endpoint), + ) + sweep_int_stations = np.append( + sweep_int_stations, load_path_sweep[i] * np.ones(per_section) + ) dy = np.diff(integration_stations) - avg_sweep = np.sum((dy[1:] + 2.0 * integration_stations[1:-1]) * dy[1:] * - sweep_int_stations[1:-1]) + avg_sweep = np.sum( + (dy[1:] + 2.0 * integration_stations[1:-1]) * dy[1:] * sweep_int_stations[1:-1] + ) # TODO: add all load_distribution_factor options if load_distribution_factor == 1: load_intensity = 1.0 - integration_stations elif load_distribution_factor == 2: - load_intensity = np.sqrt(1.0 - integration_stations ** 2) + load_intensity = np.sqrt(1.0 - integration_stations**2) elif load_distribution_factor == 3: load_intensity = np.ones(num_integration_stations + 1) else: raise om.AnalysisError( - f'{load_distribution_factor} is not a valid value for {Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL}, it must be "1", "2", or "3".') - - chord_interp = InterpND(method='slinear', points=(inp_stations), - x_interp=integration_stations) - chord_int_stations = chord_interp.evaluate_spline( - chord, compute_derivative=False) + f'{load_distribution_factor} is not a valid value for ' + f'{Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL}, it must be "1", "2", or "3".' + ) + + chord_interp = InterpND( + method='slinear', points=(inp_stations), x_interp=integration_stations + ) + chord_int_stations = chord_interp.evaluate_spline(chord, compute_derivative=False) if arref > 0.0: # Scale chord_int_stations *= arref / ar - del_load = dy * ( - chord_int_stations[:-1] * (2*load_intensity[:-1] + load_intensity[1:]) + - chord_int_stations[1:] * (2*load_intensity[1:] + load_intensity[:-1])) / 6 + del_load = ( + dy + * ( + chord_int_stations[:-1] * (2 * load_intensity[:-1] + load_intensity[1:]) + + chord_int_stations[1:] * (2 * load_intensity[1:] + load_intensity[:-1]) + ) + / 6 + ) el = np.sum(del_load) - del_moment = dy**2 * ( - chord_int_stations[:-1] * (load_intensity[:-1]+load_intensity[1:]) + - chord_int_stations[1:] * (3*load_intensity[1:]+load_intensity[:-1])) / 12 + del_moment = ( + dy**2 + * ( + chord_int_stations[:-1] * (load_intensity[:-1] + load_intensity[1:]) + + chord_int_stations[1:] * (3 * load_intensity[1:] + load_intensity[:-1]) + ) + / 12 + ) load_path_length = np.flip( - np.append(np.zeros(1, chord.dtype), np.cumsum(np.flip(del_load)[:-1]))) - csw = 1. / np.cos(sweep_int_stations[:-1] * np.pi/180.) + np.append(np.zeros(1, chord.dtype), np.cumsum(np.flip(del_load)[:-1])) + ) + csw = 1.0 / np.cos(sweep_int_stations[:-1] * np.pi / 180.0) emi = (del_moment + dy * load_path_length) * csw # em = np.sum(emi) - tc_interp = InterpND(method='slinear', points=(inp_stations), - x_interp=integration_stations) - tc_int_stations = tc_interp.evaluate_spline( - thickness_to_chord, compute_derivative=False) + tc_interp = InterpND(method='slinear', points=(inp_stations), x_interp=integration_stations) + tc_int_stations = tc_interp.evaluate_spline(thickness_to_chord, compute_derivative=False) if tcref > 0.0: tc_int_stations *= tc / tcref @@ -181,16 +190,18 @@ def compute(self, inputs, outputs): btb = 4 * pm / el - sa = np.sin(avg_sweep * np.pi / 180.) + sa = np.sin(avg_sweep * np.pi / 180.0) if ar <= 5.0: caya = 0.0 else: caya = ar - 5.0 - bt = btb / (ar**(0.25*fstrt) * (1.0 + (0.5*faert - 0.16*fstrt) - * sa**2 + 0.03*caya * (1.0-0.5*faert)*sa)) + bt = btb / ( + ar ** (0.25 * fstrt) + * (1.0 + (0.5 * faert - 0.16 * fstrt) * sa**2 + 0.03 * caya * (1.0 - 0.5 * faert) * sa) + ) - outputs[Aircraft.Wing.BENDING_FACTOR] = bt + outputs[Aircraft.Wing.BENDING_MATERIAL_FACTOR] = bt inertia_factor = np.zeros(num_engine_type, dtype=chord.dtype) eel = np.zeros(len(dy) + 1, dtype=chord.dtype) @@ -200,25 +211,29 @@ def compute(self, inputs, outputs): # i is the counter for which engine model we are checking for i in range(num_engine_type): # idx2 is the last index for the range of engines of this type - idx2 = idx + int(num_wing_engines[i]/2) + idx2 = idx + int(num_wing_engines[i] / 2) + if num_wing_engines[i] > 1: + # engine locations must be in order from wing root to tip + eng_loc = np.sort(engine_locations[idx:idx2]) - eng_loc = engine_locations[idx:idx2][0] + else: + continue - if eng_loc <= integration_stations[0]: + if eng_loc[0] <= integration_stations[0]: inertia_factor[i] = 1.0 - elif eng_loc >= integration_stations[-1]: + elif eng_loc[0] >= integration_stations[-1]: inertia_factor[i] = 0.84 else: eel[:] = 0.0 - loc = np.where(integration_stations < eng_loc)[0] + # Find all points on integration station before first engine + loc = np.where(integration_stations < eng_loc[0])[0] eel[loc] = 1.0 delme = dy * eel[1:] - delme[loc[-1]] = engine_locations[idx:idx2][0] - \ - integration_stations[loc[-1]] + delme[loc[-1]] = eng_loc[0] - integration_stations[loc[-1]] eem = delme * csw eem = np.cumsum(eem[::-1])[::-1] @@ -227,7 +242,9 @@ def compute(self, inputs, outputs): bte = 8 * np.sum((ea[:-1] + ea[1:]) * dy[:-1] * 0.5) - inertia_factor[i] = 1 - bte / bt * pod_mass[i] / gross_mass + inertia_factor_i = 1 - bte / bt[0] * pod_mass[i] / gross_mass[0] + # avoid passing an array into specific index of inertia_factor + inertia_factor[i] = inertia_factor_i # increment idx to next engine set idx = idx2 diff --git a/aviary/subsystems/mass/flops_based/wing_group.py b/aviary/subsystems/mass/flops_based/wing_group.py index 9be1571f3f..64b7b6c31b 100644 --- a/aviary/subsystems/mass/flops_based/wing_group.py +++ b/aviary/subsystems/mass/flops_based/wing_group.py @@ -1,54 +1,68 @@ -import numpy as np import openmdao.api as om from aviary.subsystems.mass.flops_based.engine_pod import EnginePodMass from aviary.subsystems.mass.flops_based.wing_common import ( - WingBendingMass, WingMiscMass, WingShearControlMass, WingTotalMass) + WingBendingMass, + WingMiscMass, + WingShearControlMass, + WingTotalMass, +) from aviary.subsystems.mass.flops_based.wing_detailed import DetailedWingBendingFact from aviary.subsystems.mass.flops_based.wing_simple import SimpleWingBendingFact -from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft class WingMassGroup(om.Group): - """ - Group of components used for FLOPS-based wing mass computation. - """ + """Group of components used for FLOPS-based wing mass computation.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + # TODO this requires a special workaround in + # variable_info/functions.py, add_aviary_output() + # default to None instead of default value + add_aviary_option(self, Aircraft.Wing.DETAILED_WING) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] - - self.add_subsystem('engine_pod_mass', - EnginePodMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) - - if Aircraft.Wing.INPUT_STATION_DIST in aviary_options: - self.add_subsystem('wing_bending_factor', - DetailedWingBendingFact(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'engine_pod_mass', + EnginePodMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + if self.options[Aircraft.Wing.DETAILED_WING]: + self.add_subsystem( + 'wing_bending_material_factor', + DetailedWingBendingFact(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) else: - self.add_subsystem('wing_bending_factor', - SimpleWingBendingFact(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'wing_bending_material_factor', + SimpleWingBendingFact(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - self.add_subsystem('wing_misc', - WingMiscMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'wing_misc', WingMiscMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) - self.add_subsystem('wing_shear_control', - WingShearControlMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'wing_shear_control', + WingShearControlMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - self.add_subsystem('wing_bending', - WingBendingMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'wing_bending', + WingBendingMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) - self.add_subsystem('wing_total', - WingTotalMass(aviary_options=aviary_options), - promotes_inputs=['*'], promotes_outputs=['*']) + self.add_subsystem( + 'wing_total', WingTotalMass(), promotes_inputs=['*'], promotes_outputs=['*'] + ) diff --git a/aviary/subsystems/mass/flops_based/wing_simple.py b/aviary/subsystems/mass/flops_based/wing_simple.py index 180c8f3dec..93e24c7422 100644 --- a/aviary/subsystems/mass/flops_based/wing_simple.py +++ b/aviary/subsystems/mass/flops_based/wing_simple.py @@ -1,8 +1,7 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft @@ -13,45 +12,38 @@ class SimpleWingBendingFact(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) def setup(self): - add_aviary_input(self, Aircraft.Wing.AREA, val=0.0) - - add_aviary_input(self, Aircraft.Wing.SPAN, val=0.0) - - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.0) - - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, val=0.0) - - add_aviary_input(self, Aircraft.Wing.STRUT_BRACING_FACTOR, val=0.0) - - add_aviary_input(self, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, val=0.0) - - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=0.0) - - add_aviary_input(self, Aircraft.Wing.SWEEP, val=0.0) - - add_aviary_output(self, Aircraft.Wing.BENDING_FACTOR, val=0.0) - - add_aviary_output(self, Aircraft.Wing.ENG_POD_INERTIA_FACTOR, val=0.0) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.Wing.STRUT_BRACING_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='deg') + + add_aviary_output(self, Aircraft.Wing.BENDING_MATERIAL_FACTOR, units='unitless') + add_aviary_output(self, Aircraft.Wing.ENG_POD_INERTIA_FACTOR, units='unitless') def setup_partials(self): - self.declare_partials(of=Aircraft.Wing.BENDING_FACTOR, - wrt=[Aircraft.Wing.STRUT_BRACING_FACTOR, - Aircraft.Wing.SPAN, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.AREA, - Aircraft.Wing.THICKNESS_TO_CHORD, - Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, - Aircraft.Wing.ASPECT_RATIO, - Aircraft.Wing.SWEEP]) + self.declare_partials( + of=Aircraft.Wing.BENDING_MATERIAL_FACTOR, + wrt=[ + Aircraft.Wing.STRUT_BRACING_FACTOR, + Aircraft.Wing.SPAN, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.AREA, + Aircraft.Wing.THICKNESS_TO_CHORD, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + Aircraft.Wing.ASPECT_RATIO, + Aircraft.Wing.SWEEP, + ], + ) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - num_wing_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) + num_wing_eng = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] fstrt = inputs[Aircraft.Wing.STRUT_BRACING_FACTOR] span = inputs[Aircraft.Wing.SPAN] tr = inputs[Aircraft.Wing.TAPER_RATIO] @@ -69,22 +61,21 @@ def compute(self, inputs, outputs): else: caya = ar - 5.0 - tlam = np.tan(np.pi / 180. * sweep) - 2 * (1 - tr) / (ar * (1 + tr)) + tlam = np.tan(np.pi / 180.0 * sweep) - 2 * (1 - tr) / (ar * (1 + tr)) - slam = tlam / (1.0 + tlam**2)**0.5 + slam = tlam / (1.0 + tlam**2) ** 0.5 cayl = (1.0 - slam**2) * (1.0 + C6 * slam**2 + 0.03 * caya * C4 * slam) ems = 1.0 - 0.25 * fstrt - outputs[Aircraft.Wing.BENDING_FACTOR] = \ - 0.215 * (0.37 + 0.7 * tr) * (span**2 / area)**ems / (cayl * tca) + outputs[Aircraft.Wing.BENDING_MATERIAL_FACTOR] = ( + 0.215 * (0.37 + 0.7 * tr) * (span**2 / area) ** ems / (cayl * tca) + ) outputs[Aircraft.Wing.ENG_POD_INERTIA_FACTOR] = 1.0 - 0.03 * num_wing_eng def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_wing_eng = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) fstrt = inputs[Aircraft.Wing.STRUT_BRACING_FACTOR] span = inputs[Aircraft.Wing.SPAN] tr = inputs[Aircraft.Wing.TAPER_RATIO] @@ -103,7 +94,7 @@ def compute_partials(self, inputs, J): else: caya = ar - 5.0 - deg2rad = np.pi / 180. + deg2rad = np.pi / 180.0 den = ar * (1 + tr) tlam = np.tan(deg2rad * sweep) - 2 * (1 - tr) / den dtlam_sweep = deg2rad / np.cos(deg2rad * sweep) ** 2 @@ -126,34 +117,43 @@ def compute_partials(self, inputs, J): ems = 1.0 - 0.25 * fstrt # bend = 0.215 * (0.37 + 0.7 * tr) * (span**2 / area)**ems / (cayl * tca) - term1 = (0.37 + 0.7 * tr) - term2a = (span**2 / area) - term2 = term2a ** ems + term1 = 0.37 + 0.7 * tr + term2a = span**2 / area + term2 = term2a**ems term3 = 1.0 / (cayl * tca) dbend_exp = -0.215 * term1 * term2 * term3 * np.log(term2a) * 0.25 dbend_tr = 0.215 * 0.7 * term2 * term3 dbend_cayl = -0.215 * term1 * term2 * tca * term3**2 - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.STRUT_BRACING_FACTOR] = \ + J[Aircraft.Wing.BENDING_MATERIAL_FACTOR, Aircraft.Wing.STRUT_BRACING_FACTOR] = ( dbend_exp + dbend_cayl * dcayl_fstrt + ) - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.SPAN] = \ - 2.0 * 0.215 * term1 * ems * term2a**(ems - 1) * term3 * span / area + J[Aircraft.Wing.BENDING_MATERIAL_FACTOR, Aircraft.Wing.SPAN] = ( + 2.0 * 0.215 * term1 * ems * term2a ** (ems - 1) * term3 * span / area + ) - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.TAPER_RATIO] = \ + J[Aircraft.Wing.BENDING_MATERIAL_FACTOR, Aircraft.Wing.TAPER_RATIO] = ( dbend_tr + dbend_cayl * (dcayl_slam * dslam * dtlam_tr) + ) - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.AREA] = \ - -0.215 * term1 * ems * term2a**(ems - 1) * term3 * term2a / area + J[Aircraft.Wing.BENDING_MATERIAL_FACTOR, Aircraft.Wing.AREA] = ( + -0.215 * term1 * ems * term2a ** (ems - 1) * term3 * term2a / area + ) - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.THICKNESS_TO_CHORD] = \ + J[Aircraft.Wing.BENDING_MATERIAL_FACTOR, Aircraft.Wing.THICKNESS_TO_CHORD] = ( -0.215 * term1 * term2 * cayl * term3**2 + ) - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR] = \ - dbend_cayl * dcayl_faert + J[ + Aircraft.Wing.BENDING_MATERIAL_FACTOR, + Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, + ] = dbend_cayl * dcayl_faert - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.ASPECT_RATIO] = \ - dbend_cayl * (dcayl_ar + dcayl_slam * dslam * dtlam_ar) + J[Aircraft.Wing.BENDING_MATERIAL_FACTOR, Aircraft.Wing.ASPECT_RATIO] = dbend_cayl * ( + dcayl_ar + dcayl_slam * dslam * dtlam_ar + ) - J[Aircraft.Wing.BENDING_FACTOR, Aircraft.Wing.SWEEP] = \ - dbend_cayl * (dcayl_slam * dslam * dtlam_sweep) + J[Aircraft.Wing.BENDING_MATERIAL_FACTOR, Aircraft.Wing.SWEEP] = dbend_cayl * ( + dcayl_slam * dslam * dtlam_sweep + ) diff --git a/aviary/subsystems/mass/gasp_based/design_load.py b/aviary/subsystems/mass/gasp_based/design_load.py index d88a41ea2e..484dd59575 100644 --- a/aviary/subsystems/mass/gasp_based/design_load.py +++ b/aviary/subsystems/mass/gasp_based/design_load.py @@ -2,20 +2,14 @@ import openmdao.api as om from aviary.constants import RHO_SEA_LEVEL_ENGLISH -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission - - -def sig(x): - return 1 / (1 + np.exp(-100 * x)) - - -def dsig(x): - return 100 * np.exp(-100 * x) / (np.exp(-100 * x) + 1) ** 2 +from aviary.utils.functions import sigmoidX, dSigmoidXdx +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Mission, Settings def dquotient(u, v, du, dv): + """d(u/v) / dv.""" return (du * v - u * dv) / v**2 @@ -27,58 +21,46 @@ class LoadSpeeds(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Design.PART25_STRUCTURAL_CATEGORY) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Aircraft.Wing.LOADING_ABOVE_20) def setup(self): + add_aviary_input(self, Aircraft.Design.MAX_STRUCTURAL_SPEED, units='mi/h') - add_aviary_input(self, Aircraft.Design.MAX_STRUCTURAL_SPEED, - val=200, units="mi/h") - - if self.options["aviary_options"].get_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, units='unitless') < 3: - - add_aviary_input(self, Aircraft.Wing.LOADING, val=128) + if self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] < 3: + add_aviary_input(self, Aircraft.Design.WING_LOADING, units='lbf/ft**2') self.add_output( - "max_airspeed", - val=0, - units="kn", - desc="VM0: maximum operating equivalent airspeed", + 'max_airspeed', + units='kn', + desc='VM0: maximum operating equivalent airspeed', ) self.add_output( - "vel_c", - val=0, - units="kn", - desc="VGC: Velocity used in Gust Load Factor calculation at cruise conditions.\ - This is Minimum Design Cruise Speed for Part 23 aircraft and VM0 for Part 25 aircraft", + 'vel_c', + units='kn', + desc='VGC: Velocity used in Gust Load Factor calculation at cruise conditions.\ + This is Minimum Design Cruise Speed for Part 23 aircraft and VM0 for Part 25 aircraft', ) self.add_output( - "max_maneuver_factor", - val=0, - units="unitless", - desc="EMLF: maximum maneuver load factor, units are in g`s", + 'max_maneuver_factor', + units='unitless', + desc='EMLF: maximum maneuver load factor, units are in g`s', ) - self.add_output("min_dive_vel", val=0, units="kn", desc="VDMIN: dive velocity") - - self.declare_partials("*", "*") + self.add_output('min_dive_vel', units='kn', desc='VDMIN: dive velocity') + self.declare_partials('*', '*') def compute(self, inputs, outputs): - max_struct_speed_mph = inputs[Aircraft.Design.MAX_STRUCTURAL_SPEED] - CATD = self.options["aviary_options"].get_val( - Aircraft.Design.PART25_STRUCTURAL_CATEGORY, units='unitless') - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') - WGS_greater_than_20_flag = self.options["aviary_options"].get_val( - Aircraft.Wing.LOADING_ABOVE_20, units='unitless') + CATD = self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + WGS_greater_than_20_flag = self.options[Aircraft.Wing.LOADING_ABOVE_20] max_struct_speed_kts = max_struct_speed_mph / 1.15 if CATD < 3: - wing_loading = inputs[Aircraft.Wing.LOADING] + wing_loading = inputs[Aircraft.Design.WING_LOADING] VCMAX = 0.9 * max_struct_speed_kts VCCOF = 33.0 @@ -93,10 +75,9 @@ def compute(self, inputs, outputs): VCMIN = VCCOF * (wing_loading**0.5) if smooth: - VCMIN = VCMIN * sig((VCMAX - VCMIN) / VCMAX) + VCMAX * sig( - (VCMIN - VCMAX) / VCMAX + VCMIN = VCMIN * sigmoidX(VCMIN / VCMAX, 1, -0.01) + VCMAX * sigmoidX( + VCMIN / VCMAX, 1, 0.01 ) - else: if VCMIN > VCMAX: VCMIN = VCMAX @@ -118,21 +99,20 @@ def compute(self, inputs, outputs): min_dive_vel = VDCOF * VCMIN if smooth: - min_dive_vel = max_struct_speed_kts * sig( - (max_struct_speed_kts - min_dive_vel) / max_struct_speed_kts - ) + min_dive_vel * sig( - (min_dive_vel - max_struct_speed_kts) / max_struct_speed_kts - ) + min_dive_vel = max_struct_speed_kts * sigmoidX( + min_dive_vel / max_struct_speed_kts, 1, -0.01 + ) + min_dive_vel * sigmoidX(min_dive_vel / max_struct_speed_kts, 1, 0.01) else: if min_dive_vel < max_struct_speed_kts: min_dive_vel = max_struct_speed_kts max_airspeed = 0.85 * min_dive_vel vel_c = VCMIN - max_maneuver_factor = 3.8 - if CATD == 1.0: + if CATD == 0: + max_maneuver_factor = 3.8 + if CATD == 1: max_maneuver_factor = 4.4 - elif CATD == 2.0: + elif CATD == 2: max_maneuver_factor = 6.0 elif CATD == 3: @@ -147,28 +127,24 @@ def compute(self, inputs, outputs): max_airspeed = max_struct_speed_kts vel_c = max_airspeed - outputs["max_airspeed"] = max_airspeed - outputs["vel_c"] = vel_c - outputs["max_maneuver_factor"] = max_maneuver_factor - outputs["min_dive_vel"] = min_dive_vel + outputs['max_airspeed'] = max_airspeed + outputs['vel_c'] = vel_c + outputs['max_maneuver_factor'] = max_maneuver_factor + outputs['min_dive_vel'] = min_dive_vel def compute_partials(self, inputs, partials): - max_struct_speed_mph = inputs[Aircraft.Design.MAX_STRUCTURAL_SPEED] - CATD = self.options["aviary_options"].get_val( - Aircraft.Design.PART25_STRUCTURAL_CATEGORY, units='unitless') - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') - WGS_greater_than_20_flag = self.options["aviary_options"].get_val( - Aircraft.Wing.LOADING_ABOVE_20, units='unitless') + CATD = self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + WGS_greater_than_20_flag = self.options[Aircraft.Wing.LOADING_ABOVE_20] max_struct_speed_kts = max_struct_speed_mph / 1.15 dmax_struct_speed_kts_dmax_struct_speed_mph = 1 / 1.15 dmax_struct_speed_kts_dwing_loading = 0.0 if CATD < 3: - wing_loading = inputs[Aircraft.Wing.LOADING] + wing_loading = inputs[Aircraft.Design.WING_LOADING] VCMAX = 0.9 * max_struct_speed_kts VCCOF = 33.0 dVCCOF_dwing_loading = 0.0 @@ -187,39 +163,33 @@ def compute_partials(self, inputs, partials): VCMIN = VCCOF * (wing_loading**0.5) dVCMIN_dwing_loading = ( - dVCCOF_dwing_loading * (wing_loading**0.5) - + VCCOF * 0.5 * wing_loading**-0.5 + dVCCOF_dwing_loading * (wing_loading**0.5) + VCCOF * 0.5 * wing_loading**-0.5 ) dVCMIN_dmax_struct_speed_mph = 0.0 if smooth: - VCMIN_1 = VCMIN * sig((VCMAX - VCMIN) / VCMAX) + VCMAX * sig( - (VCMIN - VCMAX) / VCMAX - ) + SigA = sigmoidX(VCMIN / VCMAX, 1, -0.01) + SigB = sigmoidX(VCMIN / VCMAX, 1, 0.01) + DSigB = dSigmoidXdx(VCMIN / VCMAX, 1, 0.01) + VCMIN_1 = VCMIN * SigA + VCMAX * SigB dVCMIN_dwing_loading = ( - dVCMIN_dwing_loading * sig((VCMAX - VCMIN) / VCMAX) - + VCMIN - * dsig((VCMAX - VCMIN) / VCMAX) - * -dVCMIN_dwing_loading - / VCMAX - + VCMAX - * dsig((VCMIN - VCMAX) / VCMAX) - * dVCMIN_dwing_loading - / VCMAX + dVCMIN_dwing_loading * SigA + + VCMIN * DSigB * -dVCMIN_dwing_loading / VCMAX + + VCMAX * DSigB * dVCMIN_dwing_loading / VCMAX ) dVCMIN_dmax_struct_speed_mph = ( - dVCMIN_dmax_struct_speed_mph * sig((VCMAX - VCMIN) / VCMAX) + dVCMIN_dmax_struct_speed_mph * SigA + VCMIN - * dsig((VCMAX - VCMIN) / VCMAX) + * DSigB * dquotient( (VCMAX - VCMIN), VCMAX, dVCMAX_dmax_struct_speed_mph - dVCMIN_dmax_struct_speed_mph, dVCMAX_dmax_struct_speed_mph, ) - + dVCMAX_dmax_struct_speed_mph * sig((VCMIN - VCMAX) / VCMAX) + + dVCMAX_dmax_struct_speed_mph * SigB + VCMAX - * dsig((VCMIN - VCMAX) / VCMAX) + * DSigB * dquotient( (VCMIN - VCMAX), VCMAX, @@ -234,8 +204,8 @@ def compute_partials(self, inputs, partials): dVCMIN_dmax_struct_speed_mph = dVCMAX_dmax_struct_speed_mph dVCMIN_dwing_loading = 0.0 + # why this block? if CATD == 1: - dVCMIN_dwing_loading = 0.0 dVCMIN_dmax_struct_speed_mph = 0.9 / 1.15 @@ -254,6 +224,7 @@ def compute_partials(self, inputs, partials): dVDCOF_dwing_loading = -0.001875 if CATD != 1: + VDCOF = 1.55 dVDCOF_dwing_loading = 0.0 if WGS_greater_than_20_flag: VDCOF = 1.55 - (0.0025 * (wing_loading - 20.0)) @@ -266,29 +237,24 @@ def compute_partials(self, inputs, partials): dmin_dive_vel_dmax_struct_speed_mph = VDCOF * dVCMIN_dmax_struct_speed_mph if smooth: - min_dive_vel_1 = max_struct_speed_kts * sig( - (max_struct_speed_kts - min_dive_vel) / max_struct_speed_kts - ) + min_dive_vel * sig( - (min_dive_vel - max_struct_speed_kts) / max_struct_speed_kts - ) + SigC = sigmoidX(min_dive_vel / max_struct_speed_kts, 1, -0.01) + SigD = sigmoidX(min_dive_vel / max_struct_speed_kts, 1, 0.01) + DSigD = dSigmoidXdx(min_dive_vel / max_struct_speed_kts, 1, 0.01) + min_dive_vel_1 = max_struct_speed_kts * SigC + min_dive_vel * SigD dmin_dive_vel_dmax_struct_speed_mph = ( - dmax_struct_speed_kts_dmax_struct_speed_mph - * sig((max_struct_speed_kts - min_dive_vel) / max_struct_speed_kts) + dmax_struct_speed_kts_dmax_struct_speed_mph * SigC + max_struct_speed_kts - * dsig((max_struct_speed_kts - min_dive_vel) / max_struct_speed_kts) + * DSigD * dquotient( (max_struct_speed_kts - min_dive_vel), max_struct_speed_kts, - ( - dmax_struct_speed_kts_dmax_struct_speed_mph - - dmin_dive_vel_dmax_struct_speed_mph - ), + dmax_struct_speed_kts_dmax_struct_speed_mph + - dmin_dive_vel_dmax_struct_speed_mph, dmax_struct_speed_kts_dmax_struct_speed_mph, ) - + dmin_dive_vel_dmax_struct_speed_mph - * sig((min_dive_vel - max_struct_speed_kts) / max_struct_speed_kts) + + dmin_dive_vel_dmax_struct_speed_mph * SigD + min_dive_vel - * dsig((min_dive_vel - max_struct_speed_kts) / max_struct_speed_kts) + * DSigD * dquotient( (min_dive_vel - max_struct_speed_kts), max_struct_speed_kts, @@ -298,151 +264,140 @@ def compute_partials(self, inputs, partials): ) ) dmin_dive_vel_dwing_loading = ( - dmax_struct_speed_kts_dwing_loading - * sig((max_struct_speed_kts - min_dive_vel) / max_struct_speed_kts) + dmax_struct_speed_kts_dwing_loading * SigC + max_struct_speed_kts - * dsig((max_struct_speed_kts - min_dive_vel) / max_struct_speed_kts) + * DSigD * dquotient( max_struct_speed_kts - min_dive_vel, max_struct_speed_kts, - dmax_struct_speed_kts_dwing_loading - - dmin_dive_vel_dwing_loading, + dmax_struct_speed_kts_dwing_loading - dmin_dive_vel_dwing_loading, dmax_struct_speed_kts_dwing_loading, ) - + dmin_dive_vel_dwing_loading - * sig((min_dive_vel - max_struct_speed_kts) / max_struct_speed_kts) + + dmin_dive_vel_dwing_loading * SigD + min_dive_vel - * dsig((min_dive_vel - max_struct_speed_kts) / max_struct_speed_kts) + * DSigD * dquotient( (min_dive_vel - max_struct_speed_kts), max_struct_speed_kts, - dmin_dive_vel_dwing_loading - - dmax_struct_speed_kts_dwing_loading, + dmin_dive_vel_dwing_loading - dmax_struct_speed_kts_dwing_loading, dmax_struct_speed_kts_dwing_loading, ) ) min_dive_vel = min_dive_vel_1 else: - if ( - min_dive_vel < max_struct_speed_kts - ): # note: this creates a discontinuity + if min_dive_vel < max_struct_speed_kts: # note: this creates a discontinuity min_dive_vel = max_struct_speed_kts dmin_dive_vel_dwing_loading = 0 dmin_dive_vel_dmax_struct_speed_mph = ( dmax_struct_speed_kts_dmax_struct_speed_mph ) - partials[ - "min_dive_vel", Aircraft.Wing.LOADING - ] = dmin_dive_vel_dwing_loading - partials[ - "min_dive_vel", Aircraft.Design.MAX_STRUCTURAL_SPEED - ] = dmin_dive_vel_dmax_struct_speed_mph + partials['min_dive_vel', Aircraft.Design.WING_LOADING] = dmin_dive_vel_dwing_loading + partials['min_dive_vel', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + dmin_dive_vel_dmax_struct_speed_mph + ) - partials["max_airspeed", Aircraft.Wing.LOADING] = ( + partials['max_airspeed', Aircraft.Design.WING_LOADING] = ( 0.85 * dmin_dive_vel_dwing_loading ) - partials["max_airspeed", Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + partials['max_airspeed', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( 0.85 * dmin_dive_vel_dmax_struct_speed_mph ) - partials["vel_c", Aircraft.Wing.LOADING] = dVCMIN_dwing_loading - partials["vel_c", Aircraft.Design.MAX_STRUCTURAL_SPEED] = dVCMIN_dmax_struct_speed_mph + partials['vel_c', Aircraft.Design.WING_LOADING] = dVCMIN_dwing_loading + partials['vel_c', Aircraft.Design.MAX_STRUCTURAL_SPEED] = dVCMIN_dmax_struct_speed_mph if CATD == 3: - - partials[ - "max_airspeed", Aircraft.Design.MAX_STRUCTURAL_SPEED - ] = dmax_struct_speed_kts_dmax_struct_speed_mph - partials["min_dive_vel", Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + partials['max_airspeed', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + dmax_struct_speed_kts_dmax_struct_speed_mph + ) + partials['min_dive_vel', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( 1.2 * dmax_struct_speed_kts_dmax_struct_speed_mph ) - partials["vel_c", Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + partials['vel_c', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( 1.0 * dmax_struct_speed_kts_dmax_struct_speed_mph ) elif CATD > 3.001: - - partials["max_airspeed", Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + partials['max_airspeed', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( 1 * dmax_struct_speed_kts_dmax_struct_speed_mph ) - partials["min_dive_vel", Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + partials['min_dive_vel', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( 1.2 * dmax_struct_speed_kts_dmax_struct_speed_mph ) - partials["vel_c", Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + partials['vel_c', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( 1.0 * dmax_struct_speed_kts_dmax_struct_speed_mph ) class LoadParameters(om.ExplicitComponent): """ - Computation of load parameters (such as maximum operating mach number, - density ratio, etc.) + Computation of load parameters (such as maximum operating Mach number, + density ratio, etc.). """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Design.PART25_STRUCTURAL_CATEGORY) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Mission.Design.CRUISE_ALTITUDE, units='ft') def setup(self): - self.add_input( - "vel_c", + 'vel_c', val=100, - units="kn", - desc="VGC: Velocity used in Gust Load Factor calculation at cruise conditions.\ - This is Minimum Design Cruise Speed for Part 23 aircraft and VM0 for Part 25 aircraft", + units='kn', + desc='VGC: Velocity used in Gust Load Factor calculation at cruise conditions.\ + This is Minimum Design Cruise Speed for Part 23 aircraft and VM0 for Part 25 aircraft', ) self.add_input( - "max_airspeed", + 'max_airspeed', val=200, - units="kn", - desc="VM0: maximum operating equivalent airspeed", + units='kn', + desc='VM0: maximum operating equivalent airspeed', ) self.add_output( - "max_mach", val=0, units="unitless", desc="EMM0: maximum operating mach number" + 'max_mach', + val=0, + units='unitless', + desc='EMM0: maximum operating Mach number', ) self.add_output( - "density_ratio", + 'density_ratio', val=0, - units="unitless", - desc="SIGMA (in GASP): density ratio = density at Altitude / density at Sea level", + units='unitless', + desc='SIGMA (in GASP): density ratio = density at Altitude / density at Sea level', ) self.add_output( - "V9", val=0, units="kn", desc="V9: intermediate value. Typically it is maximum flight speed." + 'V9', + val=0, + units='kn', + desc='V9: intermediate value. Typically it is maximum flight speed.', ) - self.declare_partials("max_mach", "max_airspeed") - self.declare_partials("density_ratio", "max_airspeed") - self.declare_partials("V9", "*") + self.declare_partials('max_mach', 'max_airspeed') + self.declare_partials('density_ratio', 'max_airspeed') + self.declare_partials('V9', '*') def compute(self, inputs, outputs): + vel_c = inputs['vel_c'] + max_airspeed = inputs['max_airspeed'] - vel_c = inputs["vel_c"] - max_airspeed = inputs["max_airspeed"] - - cruise_alt = self.options["aviary_options"].get_val( - Mission.Design.CRUISE_ALTITUDE, units='ft') - CATD = self.options["aviary_options"].get_val( - Aircraft.Design.PART25_STRUCTURAL_CATEGORY, units='unitless') - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + cruise_alt, _ = self.options[Mission.Design.CRUISE_ALTITUDE] + CATD = self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] if cruise_alt <= 22500.0: max_mach = max_airspeed / 486.33 if cruise_alt > 22500.0 and cruise_alt <= 36000.0: max_mach = max_airspeed / 424.73 - dmax_mach_dmax_airspeed = 1 / 424.73 if cruise_alt > 36000.0: max_mach = max_airspeed / 372.34 if smooth: - max_mach = max_mach * sig((0.9 - max_mach) / 0.9) + 0.9 * sig( - (max_mach - 0.9) / 0.9 + max_mach = max_mach * sigmoidX(max_mach / 0.9, 1, -0.01) + 0.9 * sigmoidX( + max_mach / 0.9, 1, 0.01 ) else: @@ -452,25 +407,24 @@ def compute(self, inputs, outputs): density_ratio = (max_airspeed / (661.7 * max_mach)) ** 1.61949 if smooth: - V9 = vel_c * sig(1 - density_ratio) + 661.7 * \ - max_mach * sig(density_ratio - 1) + SigE = sigmoidX(density_ratio, 1, -0.01) + SigF = sigmoidX(density_ratio, 1, 0.01) + V9 = vel_c * SigE + 661.7 * max_mach * SigF if CATD < 3: # this line creates a smooth bounded density_ratio such that .6820<=density_ratio<=1 density_ratio = ( - 0.6820 * sig((0.6820 - density_ratio) / 0.6820) - + density_ratio * sig((density_ratio - 0.6820) / - 0.6820) * sig(1 - density_ratio) - + sig(density_ratio - 1) + 0.6820 * sigmoidX(density_ratio / 0.6820, 1, -0.01) + + density_ratio * sigmoidX(density_ratio / 0.6820, 1, 0.01) * SigE + + SigF ) else: # this line creates a smooth bounded density_ratio such that .53281<=density_ratio<=1 density_ratio = ( - 0.53281 * sig((0.53281 - density_ratio) / 0.53281) - + density_ratio * sig((density_ratio - 0.53281) / - 0.53281) * sig(1 - density_ratio) - + sig(density_ratio - 1) + 0.53281 * sigmoidX(density_ratio / 0.53281, 1, -0.01) + + density_ratio * sigmoidX(density_ratio / 0.53281, 1, 0.01) * SigE + + SigF ) else: @@ -487,21 +441,17 @@ def compute(self, inputs, outputs): if CATD < 3.0 and density_ratio <= 0.6820: # note: this creates a discontinuity density_ratio = 0.6820 - outputs["max_mach"] = max_mach - outputs["density_ratio"] = density_ratio - outputs["V9"] = V9 + outputs['max_mach'] = max_mach + outputs['density_ratio'] = density_ratio + outputs['V9'] = V9 def compute_partials(self, inputs, partials): + vel_c = inputs['vel_c'] + max_airspeed = inputs['max_airspeed'] - vel_c = inputs["vel_c"] - max_airspeed = inputs["max_airspeed"] - - cruise_alt = self.options["aviary_options"].get_val( - Mission.Design.CRUISE_ALTITUDE, units='ft') - CATD = self.options["aviary_options"].get_val( - Aircraft.Design.PART25_STRUCTURAL_CATEGORY, units='unitless') - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + cruise_alt, _ = self.options[Mission.Design.CRUISE_ALTITUDE] + CATD = self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] if cruise_alt <= 22500.0: max_mach = max_airspeed / 486.33 @@ -514,16 +464,16 @@ def compute_partials(self, inputs, partials): dmax_mach_dmax_airspeed = 1 / 372.34 if smooth: - max_mach_1 = max_mach * sig((0.9 - max_mach) / 0.9) + 0.9 * sig( - (max_mach - 0.9) / 0.9 + max_mach_1 = max_mach * sigmoidX(max_mach / 0.9, 1, -0.01) + 0.9 * sigmoidX( + max_mach / 0.9, 1, 0.01 ) dmax_mach_dmax_airspeed = ( - dmax_mach_dmax_airspeed * sig((0.9 - max_mach) / 0.9) + dmax_mach_dmax_airspeed * sigmoidX(max_mach / 0.9, 1, -0.01) + max_mach - * dsig((0.9 - max_mach) / 0.9) + * dSigmoidXdx(max_mach / 0.9, 1, 0.01) * dquotient((0.9 - max_mach), 0.9, -dmax_mach_dmax_airspeed, 0.0) + 0.9 - * dsig((max_mach - 0.9) / 0.9) + * dSigmoidXdx(max_mach / 0.9, 1, 0.01) * dquotient((max_mach - 0.9), 0.9, dmax_mach_dmax_airspeed, 0.0) ) max_mach = max_mach_1 @@ -536,94 +486,88 @@ def compute_partials(self, inputs, partials): ddensity_ratio_dmax_airspeed = ( 1.61949 * (max_airspeed / (661.7 * max_mach)) ** 0.61949 - * dquotient( - max_airspeed, (661.7 * max_mach), 1, 661.7 * dmax_mach_dmax_airspeed - ) + * dquotient(max_airspeed, (661.7 * max_mach), 1, 661.7 * dmax_mach_dmax_airspeed) ) if smooth: - V9_1 = vel_c * sig(1 - density_ratio) + 661.7 * \ - max_mach * sig(density_ratio - 1) + SigE = sigmoidX(density_ratio, 1, -0.01) + SigF = sigmoidX(density_ratio, 1, 0.01) + DSigF = dSigmoidXdx(density_ratio, 1, 0.01) dV9_dmax_airspeed = ( - vel_c * dsig(1 - density_ratio) * -ddensity_ratio_dmax_airspeed + vel_c * DSigF * (-ddensity_ratio_dmax_airspeed) + 661.7 * dmax_mach_dmax_airspeed - * sig(density_ratio - 1) + * SigF * 661.7 * max_mach - * dsig(density_ratio - 1) + * DSigF * ddensity_ratio_dmax_airspeed ) - dV9_dvel_c = sig(1 - density_ratio) - V9 = V9_1 + dV9_dvel_c = SigE if CATD < 3: # this line creates a smooth bounded density_ratio such that .6820<=density_ratio<=1 density_ratio_1 = ( - 0.6820 * sig((0.6820 - density_ratio) / 0.6820) - + density_ratio * sig((density_ratio - 0.6820) / - 0.6820) * sig(1 - density_ratio) - + sig(density_ratio - 1) + 0.6820 * sigmoidX(density_ratio / 0.6820, 1, -0.01) + + density_ratio * sigmoidX(density_ratio / 0.6820, 1, 0.01) * SigE + + SigF ) ddensity_ratio_dmax_airspeed = ( 0.6820 - * dsig((0.6820 - density_ratio) / 0.6820) + * dSigmoidXdx(density_ratio / 0.6820, 1, 0.01) * -ddensity_ratio_dmax_airspeed / 0.6820 + ddensity_ratio_dmax_airspeed - * sig((density_ratio - 0.6820) / 0.6820) - * sig(1 - density_ratio) + * sigmoidX(density_ratio / 0.6820, 1, 0.01) + * SigF + density_ratio * ( - dsig((density_ratio - 0.6820) / 0.6820) + dSigmoidXdx(density_ratio / 0.6820, 1, 0.01) * ddensity_ratio_dmax_airspeed / 0.6820 - * sig(1 - density_ratio) - + sig((density_ratio - 0.6820) / 0.6820) - * dsig(1 - density_ratio) + * SigE + + sigmoidX(density_ratio / 0.6820, 1, 0.01) + * DSigF * -ddensity_ratio_dmax_airspeed ) - + dsig(density_ratio - 1) * ddensity_ratio_dmax_airspeed + + DSigF * ddensity_ratio_dmax_airspeed ) density_ratio = density_ratio_1 else: # this line creates a smooth bounded density_ratio such that .53281<=density_ratio<=1 density_ratio_1 = ( - 0.53281 * sig((0.53281 - density_ratio) / 0.53281) - + density_ratio * sig((density_ratio - 0.53281) / - 0.53281) * sig(1 - density_ratio) - + sig(density_ratio - 1) + 0.53281 * sigmoidX(density_ratio / 0.53281, 1, -0.01) + + density_ratio * sigmoidX(density_ratio / 0.53281, 1, 0.01) * SigE + + SigF ) ddensity_ratio_dmax_airspeed = ( 0.53281 - * dsig((0.53281 - density_ratio) / 0.53281) + * dSigmoidXdx(density_ratio / 0.53281, 1, 0.01) * -ddensity_ratio_dmax_airspeed / 0.53281 + ddensity_ratio_dmax_airspeed - * sig((density_ratio - 0.53281) / 0.53281) - * sig(1 - density_ratio) + * sigmoidX(density_ratio / 0.53281, 1, 0.01) + * SigE + density_ratio * ( - dsig((density_ratio - 0.53281) / 0.53281) + dSigmoidXdx(density_ratio / 0.53281, 1, 0.01) * ddensity_ratio_dmax_airspeed / 0.53281 - * sig(1 - density_ratio) - + sig((density_ratio - 0.53281) / 0.53281) - * dsig(1 - density_ratio) + * SigE + + sigmoidX(density_ratio / 0.53281, 1, -0.01) + * SigF * -ddensity_ratio_dmax_airspeed ) - + dsig(density_ratio - 1) * ddensity_ratio_dmax_airspeed + + DSigF * ddensity_ratio_dmax_airspeed ) density_ratio = density_ratio_1 else: if density_ratio >= 0.53281: # note: this creates a discontinuity - V9 = vel_c dV9_dvel_c = 1.0 dV9_dmax_airspeed = 0.0 if density_ratio > 1: # note: this creates a discontinuity - V9 = 661.7 * max_mach density_ratio = 1.0 dV9_dvel_c = 0.0 @@ -632,7 +576,6 @@ def compute_partials(self, inputs, partials): else: # note: this creates a discontinuity density_ratio = 0.53281 - V9 = vel_c dV9_dvel_c = 1.0 dV9_dmax_airspeed = 0.0 @@ -642,177 +585,182 @@ def compute_partials(self, inputs, partials): density_ratio = 0.6820 ddensity_ratio_dmax_airspeed = 0.0 - partials["max_mach", "max_airspeed"] = dmax_mach_dmax_airspeed - partials["density_ratio", "max_airspeed"] = ddensity_ratio_dmax_airspeed - partials["V9", "max_airspeed"] = dV9_dmax_airspeed - partials["V9", "vel_c"] = dV9_dvel_c + partials['max_mach', 'max_airspeed'] = dmax_mach_dmax_airspeed + partials['density_ratio', 'max_airspeed'] = ddensity_ratio_dmax_airspeed + partials['V9', 'max_airspeed'] = dV9_dmax_airspeed + partials['V9', 'vel_c'] = dV9_dvel_c class LiftCurveSlopeAtCruise(om.ExplicitComponent): - """ - Computation of lift curve slope at cruise mach number - """ + """Computation of lift curve slope at cruise Mach number.""" + + def initialize(self): + add_aviary_option(self, Settings.VERBOSITY) def setup(self): - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) - add_aviary_input(self, Aircraft.Wing.SWEEP, val=0.436, units="rad") - add_aviary_input(self, Mission.Design.MACH, val=0.8) + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.SWEEP, units='rad') + add_aviary_input(self, Mission.Design.MACH, units='unitless') - add_aviary_output(self, Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765) + add_aviary_output(self, Aircraft.Design.LIFT_CURVE_SLOPE, units='1/rad') - self.declare_partials(Aircraft.Design.LIFT_CURVE_SLOPE, "*") + self.declare_partials(Aircraft.Design.LIFT_CURVE_SLOPE, '*') def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + AR = inputs[Aircraft.Wing.ASPECT_RATIO] DLMC4 = inputs[Aircraft.Wing.SWEEP] mach = inputs[Mission.Design.MACH] + if verbosity > Verbosity.BRIEF: + if AR <= 0.0: + print('Aircraft.Wing.ASPECT_RATIO must be positive.') + if DLMC4 == np.pi / 2.0: + print('Aircraft.Wing.SWEEP can not be 90 degrees.') + outputs[Aircraft.Design.LIFT_CURVE_SLOPE] = ( - np.pi * AR / (1 + np.sqrt(1 + (((AR / (2 * np.cos(DLMC4))) ** 2) * (1 - (mach * np.cos(DLMC4)) ** 2))))) + np.pi + * AR + / ( + 1 + + np.sqrt( + 1 + (((AR / (2 * np.cos(DLMC4))) ** 2) * (1 - (mach * np.cos(DLMC4)) ** 2)) + ) + ) + ) def compute_partials(self, inputs, partials): AR = inputs[Aircraft.Wing.ASPECT_RATIO] DLMC4 = inputs[Aircraft.Wing.SWEEP] mach = inputs[Mission.Design.MACH] - c1 = np.sqrt(AR**2 * (-mach**2*np.cos(DLMC4)**2 + 1) + 4*np.cos(DLMC4)**2) - c2 = 2*np.cos(DLMC4) + c1 + c1 = np.sqrt(AR**2 * (-(mach**2) * np.cos(DLMC4) ** 2 + 1) + 4 * np.cos(DLMC4) ** 2) + c2 = 2 * np.cos(DLMC4) + c1 partials[Aircraft.Design.LIFT_CURVE_SLOPE, Aircraft.Wing.ASPECT_RATIO] = ( - 4 * np.pi * np.cos(DLMC4)**2) / (c1 * c2) + 4 * np.pi * np.cos(DLMC4) ** 2 + ) / (c1 * c2) partials[Aircraft.Design.LIFT_CURVE_SLOPE, Mission.Design.MACH] = ( - 2 * np.pi * AR**3 * mach * np.cos(DLMC4)**3) / (c1 * c2**2) - partials[Aircraft.Design.LIFT_CURVE_SLOPE, Aircraft.Wing.SWEEP] = (-np.pi * AR * (-8 * np.cos(DLMC4)**3 * np.sin( - DLMC4) + 4 * np.cos(DLMC4)**2 * np.sin(2*DLMC4) + AR**2 * np.sin(2*DLMC4))) / (np.cos(DLMC4) * c1 * c2**2) + 2 * np.pi * AR**3 * mach * np.cos(DLMC4) ** 3 + ) / (c1 * c2**2) + partials[Aircraft.Design.LIFT_CURVE_SLOPE, Aircraft.Wing.SWEEP] = ( + -np.pi + * AR + * ( + -8 * np.cos(DLMC4) ** 3 * np.sin(DLMC4) + + 4 * np.cos(DLMC4) ** 2 * np.sin(2 * DLMC4) + + AR**2 * np.sin(2 * DLMC4) + ) + ) / (np.cos(DLMC4) * c1 * c2**2) class LoadFactors(om.ExplicitComponent): - """ - Computation of structural ultimate load factor. - """ + """Computation of structural ultimate load factor.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER) def setup(self): - - add_aviary_input(self, Aircraft.Wing.LOADING, val=128) + add_aviary_input(self, Aircraft.Design.WING_LOADING, units='lbf/ft**2') self.add_input( - "density_ratio", + 'density_ratio', val=0.5, - units="unitless", - desc="SIGMA (in GASP): density ratio = density at Altitude / density at Sea level", + units='unitless', + desc='SIGMA (in GASP): density ratio = density at Altitude / density at Sea level', ) self.add_input( - "V9", + 'V9', val=100, - units="kn", - desc="V9: intermediate value. Typically it is maximum flight speed.", + units='kn', + desc='V9: intermediate value. Typically it is maximum flight speed.', ) - self.add_input("min_dive_vel", val=250, units="kn", desc="VDMIN: dive velocity") + self.add_input('min_dive_vel', val=250, units='kn', desc='VDMIN: dive velocity') self.add_input( - "max_maneuver_factor", + 'max_maneuver_factor', val=0.72, - units="unitless", - desc="EMLF: maximum maneuver load factor, units are in g`s", + units='unitless', + desc='EMLF: maximum maneuver load factor, units are in g`s', ) - add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, val=12.6131) - add_aviary_input(self, Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765) + add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') + add_aviary_input(self, Aircraft.Design.LIFT_CURVE_SLOPE, units='1/rad') - add_aviary_output(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.5) + add_aviary_output(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, units='unitless') - self.declare_partials(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, "*") + self.declare_partials(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, '*') def compute(self, inputs, outputs): - - wing_loading = inputs[Aircraft.Wing.LOADING] - density_ratio = inputs["density_ratio"] - V9 = inputs["V9"] - min_dive_vel = inputs["min_dive_vel"] - max_maneuver_factor = inputs["max_maneuver_factor"] + wing_loading = inputs[Aircraft.Design.WING_LOADING] + density_ratio = inputs['density_ratio'] + V9 = inputs['V9'] + min_dive_vel = inputs['min_dive_vel'] + max_maneuver_factor = inputs['max_maneuver_factor'] avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] Cl_alpha = inputs[Aircraft.Design.LIFT_CURVE_SLOPE] - ULF_from_maneuver = self.options["aviary_options"].get_val( - Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, units='unitless') - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + ULF_from_maneuver = self.options[Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] mass_ratio = ( - 2.0 * wing_loading / - (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) + 2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) ) k_load_factor = 0.88 * mass_ratio / (5.3 + mass_ratio) - cruise_load_factor = 1.0 + ( - (k_load_factor * 50.0 * V9 * Cl_alpha) / (498.0 * wing_loading) - ) + cruise_load_factor = 1.0 + ((k_load_factor * 50.0 * V9 * Cl_alpha) / (498.0 * wing_loading)) dive_load_factor = 1.0 + ( (k_load_factor * 25.0 * min_dive_vel * Cl_alpha) / (498.0 * wing_loading) ) gust_load_factor = dive_load_factor if smooth: - gust_load_factor = dive_load_factor * sig( - (dive_load_factor - cruise_load_factor) / dive_load_factor - ) + cruise_load_factor * sig( - (cruise_load_factor - dive_load_factor) / dive_load_factor - ) + gust_load_factor = dive_load_factor * sigmoidX( + cruise_load_factor / dive_load_factor, 1, -0.01 + ) + cruise_load_factor * sigmoidX(cruise_load_factor / dive_load_factor, 1, 0.01) else: - if ( - cruise_load_factor > dive_load_factor - ): # note: this creates a discontinuity + if cruise_load_factor > dive_load_factor: # note: this creates a discontinuity gust_load_factor = cruise_load_factor ULF = 1.5 * max_maneuver_factor if smooth: ULF = 1.5 * ( - gust_load_factor - * sig((gust_load_factor - max_maneuver_factor) / gust_load_factor) - + max_maneuver_factor - * sig((max_maneuver_factor - gust_load_factor) / gust_load_factor) + gust_load_factor * sigmoidX(max_maneuver_factor / gust_load_factor, 1, -0.01) + + max_maneuver_factor * sigmoidX(max_maneuver_factor / gust_load_factor, 1, 0.01) ) else: - if ( - gust_load_factor > max_maneuver_factor - ): # note: this creates a discontinuity + if gust_load_factor > max_maneuver_factor: # note: this creates a discontinuity ULF = 1.5 * gust_load_factor - if ULF_from_maneuver == True: + if ULF_from_maneuver is True: ULF = 1.5 * max_maneuver_factor outputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ULF def compute_partials(self, inputs, partials): - - wing_loading = inputs[Aircraft.Wing.LOADING] - density_ratio = inputs["density_ratio"] - V9 = inputs["V9"] - min_dive_vel = inputs["min_dive_vel"] - max_maneuver_factor = inputs["max_maneuver_factor"] + wing_loading = inputs[Aircraft.Design.WING_LOADING] + density_ratio = inputs['density_ratio'] + V9 = inputs['V9'] + min_dive_vel = inputs['min_dive_vel'] + max_maneuver_factor = inputs['max_maneuver_factor'] avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] Cl_alpha = inputs[Aircraft.Design.LIFT_CURVE_SLOPE] - ULF_from_maneuver = self.options["aviary_options"].get_val( - Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, units='unitless') - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + ULF_from_maneuver = self.options[Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] mass_ratio = ( - 2.0 * wing_loading / - (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) + 2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) ) k_load_factor = 0.88 * mass_ratio / (5.3 + mass_ratio) - cruise_load_factor = 1.0 + ( - (k_load_factor * 50.0 * V9 * Cl_alpha) / (498.0 * wing_loading) - ) + cruise_load_factor = 1.0 + ((k_load_factor * 50.0 * V9 * Cl_alpha) / (498.0 * wing_loading)) dive_load_factor = 1.0 + ( (k_load_factor * 25.0 * min_dive_vel * Cl_alpha) / (498.0 * wing_loading) ) @@ -822,16 +770,19 @@ def compute_partials(self, inputs, partials): density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2 ) dmass_ratio_ddensity_ratio = ( - -2.0 * wing_loading / (density_ratio**2 * RHO_SEA_LEVEL_ENGLISH * - avg_chord * Cl_alpha * 32.2) + -2.0 + * wing_loading + / (density_ratio**2 * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) ) dmass_ratio_davg_chord = ( - -2.0 * wing_loading / (density_ratio * RHO_SEA_LEVEL_ENGLISH * - avg_chord**2 * Cl_alpha * 32.2) + -2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord**2 * Cl_alpha * 32.2) ) dmass_ratio_dCl_alpha = ( - -2.0 * wing_loading / (density_ratio * RHO_SEA_LEVEL_ENGLISH * - avg_chord * Cl_alpha**2 * 32.2) + -2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha**2 * 32.2) ) dk_load_factor_dwing_loading = dquotient( @@ -865,19 +816,16 @@ def compute_partials(self, inputs, partials): (dk_load_factor_dwing_loading * 50.0 * V9 * Cl_alpha), 498, ) - dcruise_load_factor_ddensity_ratio = (dk_load_factor_ddensity_ratio * 50.0 * V9 * Cl_alpha) / ( + dcruise_load_factor_ddensity_ratio = ( + dk_load_factor_ddensity_ratio * 50.0 * V9 * Cl_alpha + ) / (498.0 * wing_loading) + dcruise_load_factor_davg_chord = (dk_load_factor_davg_chord * 50.0 * V9 * Cl_alpha) / ( 498.0 * wing_loading ) - dcruise_load_factor_davg_chord = ( - dk_load_factor_davg_chord * 50.0 * V9 * Cl_alpha - ) / (498.0 * wing_loading) dcruise_load_factor_dCl_alpha = ( dk_load_factor_dCl_alpha * 50.0 * V9 * Cl_alpha + k_load_factor * 50 * V9 ) / (498.0 * wing_loading) - dcruise_load_factor_dV9 = (k_load_factor * 50.0 * Cl_alpha) / ( - 498.0 * wing_loading - ) - dcruise_load_factor_dmin_dive_vel = 0.0 + dcruise_load_factor_dV9 = (k_load_factor * 50.0 * Cl_alpha) / (498.0 * wing_loading) ddive_load_factor_dwing_loading = dquotient( (k_load_factor * 25.0 * min_dive_vel * Cl_alpha), @@ -895,9 +843,7 @@ def compute_partials(self, inputs, partials): dk_load_factor_dCl_alpha * 25 * min_dive_vel * Cl_alpha + k_load_factor * 50 * min_dive_vel ) / (498.0 * wing_loading) - ddive_load_factor_dmin_dive_vel = (k_load_factor * 25 * Cl_alpha) / ( - 498.0 * wing_loading - ) + (k_load_factor * 25 * Cl_alpha) / (498.0 * wing_loading) ddive_load_factor_dV9 = 0.0 dgust_load_factor_dwing_loading = dquotient( @@ -914,34 +860,30 @@ def compute_partials(self, inputs, partials): ) / (498.0 * wing_loading) dgust_load_factor_dCl_alpha = ( dk_load_factor_dCl_alpha * 25 * min_dive_vel * Cl_alpha - + k_load_factor * 50 * min_dive_vel + + k_load_factor * 25 * min_dive_vel ) / (498.0 * wing_loading) - dgust_load_factor_dmin_dive_vel = (k_load_factor * 25 * Cl_alpha) / ( - 498.0 * wing_loading - ) + dgust_load_factor_dmin_dive_vel = (k_load_factor * 25 * Cl_alpha) / (498.0 * wing_loading) dgust_load_factor_dV9 = 0.0 if smooth: - gust_load_factor_1 = dive_load_factor * sig( - (dive_load_factor - cruise_load_factor) / dive_load_factor - ) + cruise_load_factor * sig( - (cruise_load_factor - dive_load_factor) / dive_load_factor - ) + SigG = sigmoidX(cruise_load_factor / dive_load_factor, 1, -0.01) + SigH = sigmoidX(cruise_load_factor / dive_load_factor, 1, 0.01) + DSigG = dSigmoidXdx(cruise_load_factor / dive_load_factor, 1, -0.01) + DSigH = dSigmoidXdx(cruise_load_factor / dive_load_factor, 1, 0.01) + gust_load_factor_1 = dive_load_factor * SigG + cruise_load_factor * SigH dgust_load_factor_dwing_loading = ( - ddive_load_factor_dwing_loading - * sig((dive_load_factor - cruise_load_factor) / dive_load_factor) + ddive_load_factor_dwing_loading * SigG + dive_load_factor - * dsig((dive_load_factor - cruise_load_factor) / dive_load_factor) + * DSigG * dquotient( (dive_load_factor - cruise_load_factor), dive_load_factor, ddive_load_factor_dwing_loading - dcruise_load_factor_dwing_loading, ddive_load_factor_dwing_loading, ) - + dcruise_load_factor_dwing_loading - * sig((cruise_load_factor - dive_load_factor) / dive_load_factor) + + dcruise_load_factor_dwing_loading * SigH + cruise_load_factor - * dsig((cruise_load_factor - dive_load_factor) / dive_load_factor) + * DSigG * dquotient( (cruise_load_factor - dive_load_factor), dive_load_factor, @@ -950,20 +892,18 @@ def compute_partials(self, inputs, partials): ) ) dgust_load_factor_ddensity_ratio = ( - ddive_load_factor_ddensity_ratio - * sig((dive_load_factor - cruise_load_factor) / dive_load_factor) + ddive_load_factor_ddensity_ratio * SigG + dive_load_factor - * dsig((dive_load_factor - cruise_load_factor) / dive_load_factor) + * DSigG * dquotient( (dive_load_factor - cruise_load_factor), dive_load_factor, ddive_load_factor_ddensity_ratio - dcruise_load_factor_ddensity_ratio, ddive_load_factor_ddensity_ratio, ) - + dcruise_load_factor_ddensity_ratio - * sig((cruise_load_factor - dive_load_factor) / dive_load_factor) + + dcruise_load_factor_ddensity_ratio * SigH + cruise_load_factor - * dsig((cruise_load_factor - dive_load_factor) / dive_load_factor) + * DSigH * dquotient( (cruise_load_factor - dive_load_factor), dive_load_factor, @@ -972,20 +912,18 @@ def compute_partials(self, inputs, partials): ) ) dgust_load_factor_davg_chord = ( - ddive_load_factor_davg_chord - * sig((dive_load_factor - cruise_load_factor) / dive_load_factor) + ddive_load_factor_davg_chord * SigG + dive_load_factor - * dsig((dive_load_factor - cruise_load_factor) / dive_load_factor) + * DSigH * dquotient( (dive_load_factor - cruise_load_factor), dive_load_factor, ddive_load_factor_davg_chord - dcruise_load_factor_davg_chord, ddive_load_factor_davg_chord, ) - + dcruise_load_factor_davg_chord - * sig((cruise_load_factor - dive_load_factor) / dive_load_factor) + + dcruise_load_factor_davg_chord * SigH + cruise_load_factor - * dsig((cruise_load_factor - dive_load_factor) / dive_load_factor) + * DSigH * dquotient( (cruise_load_factor - dive_load_factor), dive_load_factor, @@ -994,20 +932,18 @@ def compute_partials(self, inputs, partials): ) ) dgust_load_factor_dCl_alpha = ( - ddive_load_factor_dCl_alpha - * sig((dive_load_factor - cruise_load_factor) / dive_load_factor) + ddive_load_factor_dCl_alpha * SigG + dive_load_factor - * dsig((dive_load_factor - cruise_load_factor) / dive_load_factor) + * DSigH * dquotient( (dive_load_factor - cruise_load_factor), dive_load_factor, ddive_load_factor_dCl_alpha - dcruise_load_factor_dCl_alpha, ddive_load_factor_dCl_alpha, ) - + dcruise_load_factor_dCl_alpha - * sig((cruise_load_factor - dive_load_factor) / dive_load_factor) + + dcruise_load_factor_dCl_alpha * SigH + cruise_load_factor - * dsig((cruise_load_factor - dive_load_factor) / dive_load_factor) + * DSigH * dquotient( (cruise_load_factor - dive_load_factor), dive_load_factor, @@ -1017,17 +953,16 @@ def compute_partials(self, inputs, partials): ) dgust_load_factor_dV9 = ( dive_load_factor - * dsig((dive_load_factor - cruise_load_factor) / dive_load_factor) + * DSigH * dquotient( (dive_load_factor - cruise_load_factor), dive_load_factor, ddive_load_factor_dV9 - dcruise_load_factor_dV9, ddive_load_factor_dV9, ) - + dcruise_load_factor_dV9 - * sig((cruise_load_factor - dive_load_factor) / dive_load_factor) + + dcruise_load_factor_dV9 * SigH + cruise_load_factor - * dsig((cruise_load_factor - dive_load_factor) / dive_load_factor) + * DSigH * dquotient( (cruise_load_factor - dive_load_factor), dive_load_factor, @@ -1035,32 +970,9 @@ def compute_partials(self, inputs, partials): ddive_load_factor_dV9, ) ) - dgust_loading_dmin_dive_vel = ( - ddive_load_factor_dmin_dive_vel - * sig((dive_load_factor - cruise_load_factor) / dive_load_factor) - + dive_load_factor - * dsig((dive_load_factor - cruise_load_factor) / dive_load_factor) - * dquotient( - (dive_load_factor - cruise_load_factor), - dive_load_factor, - ddive_load_factor_dmin_dive_vel, - ddive_load_factor_dmin_dive_vel, - ) - + cruise_load_factor - * dsig((cruise_load_factor - dive_load_factor) / dive_load_factor) - * dquotient( - (cruise_load_factor - dive_load_factor), - dive_load_factor, - -ddive_load_factor_dmin_dive_vel, - ddive_load_factor_dmin_dive_vel, - ) - ) gust_load_factor = gust_load_factor_1 else: - - if ( - cruise_load_factor > dive_load_factor - ): # note: this creates a discontinuity + if cruise_load_factor > dive_load_factor: # note: this creates a discontinuity gust_load_factor = cruise_load_factor dgust_load_factor_dwing_loading = dcruise_load_factor_dwing_loading @@ -1070,7 +982,6 @@ def compute_partials(self, inputs, partials): dgust_load_factor_dV9 = dcruise_load_factor_dV9 dgust_load_factor_dmin_dive_vel = 0.0 - ULF = 1.5 * max_maneuver_factor dULF_dmax_maneuver_factor = 1.5 dULF_dwing_loading = 0.0 dULF_ddensity_ratio = 0.0 @@ -1080,33 +991,27 @@ def compute_partials(self, inputs, partials): dULF_dmin_dive_vel = 0.0 if smooth: - ULF_1 = 1.5 * ( - gust_load_factor - * sig((gust_load_factor - max_maneuver_factor) / gust_load_factor) - + max_maneuver_factor - * sig((max_maneuver_factor - gust_load_factor) / gust_load_factor) - ) + SigK = sigmoidX(max_maneuver_factor / gust_load_factor, 1, -0.01) + SigL = sigmoidX(max_maneuver_factor / gust_load_factor, 1, 0.01) + DSigL = dSigmoidXdx(max_maneuver_factor / gust_load_factor, 1, 0.01) dULF_dmax_maneuver_factor = 1.5 * ( gust_load_factor - * dsig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + * DSigL * dquotient( (gust_load_factor - max_maneuver_factor), gust_load_factor, -1.0, 0.0, ) - + sig((max_maneuver_factor - gust_load_factor) / gust_load_factor) + + SigL + max_maneuver_factor - * dsig((max_maneuver_factor - gust_load_factor) / gust_load_factor) - * dquotient( - (max_maneuver_factor - gust_load_factor), gust_load_factor, 1.0, 0.0 - ) + * DSigL + * dquotient((max_maneuver_factor - gust_load_factor), gust_load_factor, 1.0, 0.0) ) dULF_dwing_loading = 1.5 * ( - dgust_load_factor_dwing_loading - * sig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + dgust_load_factor_dwing_loading * SigK + gust_load_factor - * dsig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + * DSigL * dquotient( (gust_load_factor - max_maneuver_factor), gust_load_factor, @@ -1114,7 +1019,7 @@ def compute_partials(self, inputs, partials): dgust_load_factor_dwing_loading, ) + max_maneuver_factor - * dsig((max_maneuver_factor - gust_load_factor) / gust_load_factor) + * DSigL * dquotient( (max_maneuver_factor - gust_load_factor), gust_load_factor, @@ -1123,10 +1028,9 @@ def compute_partials(self, inputs, partials): ) ) dULF_ddensity_ratio = 1.5 * ( - dgust_load_factor_ddensity_ratio - * sig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + dgust_load_factor_ddensity_ratio * SigK + gust_load_factor - * dsig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + * DSigL * dquotient( (gust_load_factor - max_maneuver_factor), gust_load_factor, @@ -1134,7 +1038,7 @@ def compute_partials(self, inputs, partials): dgust_load_factor_ddensity_ratio, ) + max_maneuver_factor - * dsig((max_maneuver_factor - gust_load_factor) / gust_load_factor) + * DSigL * dquotient( (max_maneuver_factor - gust_load_factor), gust_load_factor, @@ -1143,10 +1047,9 @@ def compute_partials(self, inputs, partials): ) ) dULF_davg_chord = 1.5 * ( - dgust_load_factor_davg_chord - * sig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + dgust_load_factor_davg_chord * SigK + gust_load_factor - * dsig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + * DSigL * dquotient( (gust_load_factor - max_maneuver_factor), gust_load_factor, @@ -1154,7 +1057,7 @@ def compute_partials(self, inputs, partials): dgust_load_factor_davg_chord, ) + max_maneuver_factor - * dsig((max_maneuver_factor - gust_load_factor) / gust_load_factor) + * DSigL * dquotient( (max_maneuver_factor - gust_load_factor), gust_load_factor, @@ -1163,10 +1066,9 @@ def compute_partials(self, inputs, partials): ) ) dULF_dCl_alpha = 1.5 * ( - dgust_load_factor_dCl_alpha - * sig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + dgust_load_factor_dCl_alpha * SigK + gust_load_factor - * dsig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + * DSigL * dquotient( (gust_load_factor - max_maneuver_factor), gust_load_factor, @@ -1174,7 +1076,7 @@ def compute_partials(self, inputs, partials): dgust_load_factor_dCl_alpha, ) + max_maneuver_factor - * dsig((max_maneuver_factor - gust_load_factor) / gust_load_factor) + * DSigL * dquotient( (max_maneuver_factor - gust_load_factor), gust_load_factor, @@ -1183,10 +1085,9 @@ def compute_partials(self, inputs, partials): ) ) dULF_dV9 = 1.5 * ( - dgust_load_factor_dV9 - * sig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + dgust_load_factor_dV9 * SigK + gust_load_factor - * dsig((gust_load_factor - max_maneuver_factor) / gust_load_factor) + * DSigL * dquotient( (gust_load_factor - max_maneuver_factor), gust_load_factor, @@ -1194,7 +1095,7 @@ def compute_partials(self, inputs, partials): dgust_load_factor_dV9, ) + max_maneuver_factor - * dsig((max_maneuver_factor - gust_load_factor) / gust_load_factor) + * DSigL * dquotient( (max_maneuver_factor - gust_load_factor), gust_load_factor, @@ -1203,13 +1104,8 @@ def compute_partials(self, inputs, partials): ) ) dULF_dmin_dive_vel = 0.0 - ULF = ULF_1 else: - if ( - gust_load_factor > max_maneuver_factor - ): # note: this creates a discontinuity - ULF = 1.5 * gust_load_factor - + if gust_load_factor > max_maneuver_factor: # note: this creates a discontinuity dULF_dmax_maneuver_factor = 0.0 dULF_dwing_loading = 1.5 * dgust_load_factor_dwing_loading dULF_ddensity_ratio = 1.5 * dgust_load_factor_ddensity_ratio @@ -1218,9 +1114,7 @@ def compute_partials(self, inputs, partials): dULF_dV9 = 1.5 * dgust_load_factor_dV9 dULF_dmin_dive_vel = 1.5 * dgust_load_factor_dmin_dive_vel - if ULF_from_maneuver == True: - ULF = 1.5 * max_maneuver_factor - + if ULF_from_maneuver is True: dULF_dmax_maneuver_factor = 1.5 dULF_dwing_loading = 0.0 dULF_ddensity_ratio = 0.0 @@ -1229,80 +1123,1112 @@ def compute_partials(self, inputs, partials): dULF_dV9 = 0.0 dULF_dmin_dive_vel = 0.0 - partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - "max_maneuver_factor"] = dULF_dmax_maneuver_factor - partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - Aircraft.Wing.LOADING] = dULF_dwing_loading - partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - "density_ratio"] = dULF_ddensity_ratio - partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - Aircraft.Wing.AVERAGE_CHORD] = dULF_davg_chord - partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - Aircraft.Design.LIFT_CURVE_SLOPE] = dULF_dCl_alpha - partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, "V9"] = dULF_dV9 - partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, "min_dive_vel"] = dULF_dmin_dive_vel + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'max_maneuver_factor'] = ( + dULF_dmax_maneuver_factor + ) + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, Aircraft.Design.WING_LOADING] = ( + dULF_dwing_loading + ) + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'density_ratio'] = dULF_ddensity_ratio + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, Aircraft.Wing.AVERAGE_CHORD] = dULF_davg_chord + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, Aircraft.Design.LIFT_CURVE_SLOPE] = ( + dULF_dCl_alpha + ) + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'V9'] = dULF_dV9 + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'min_dive_vel'] = dULF_dmin_dive_vel class DesignLoadGroup(om.Group): """ - Design load group for GASP-based mass. + Design load group for GASP-based tube and wing type aircraft mass. + """ + + def setup(self): + self.add_subsystem( + 'speeds', + LoadSpeeds(), + promotes_inputs=['*'], + promotes_outputs=[ + 'max_airspeed', + 'vel_c', + 'max_maneuver_factor', + 'min_dive_vel', + ], + ) + + self.add_subsystem( + 'params', + LoadParameters(), + promotes_inputs=[ + 'max_airspeed', + 'vel_c', + ], + promotes_outputs=['density_ratio', 'V9', 'max_mach'], + ) + + self.add_subsystem( + 'Cl_Alpha_calc', + LiftCurveSlopeAtCruise(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'factors', + LoadFactors(), + promotes_inputs=[ + 'max_maneuver_factor', + 'min_dive_vel', + 'density_ratio', + 'V9', + ] + + ['aircraft:*'], + promotes_outputs=['*'], + ) + + +class BWBLoadSpeeds(om.ExplicitComponent): + """ + Computation of load speeds (such as maximum operating equivalent airspeed, + velocity used in Gust Load Factor calculation at cruise conditions, maximum + maneuver load factor, and minimum dive velocity). """ def initialize(self): + add_aviary_option(self, Aircraft.Design.PART25_STRUCTURAL_CATEGORY) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Aircraft.Wing.LOADING_ABOVE_20) + add_aviary_option(self, Settings.VERBOSITY) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + def setup(self): + add_aviary_input(self, Aircraft.Design.MAX_STRUCTURAL_SPEED, units='mi/h') + + if self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] < 3: + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.EXPOSED_AREA, units='ft**2') + + self.add_output( + 'max_airspeed', + units='kn', + desc='VM0: maximum operating equivalent airspeed', + ) + self.add_output( + 'vel_c', + units='kn', + desc='VGC: Velocity used in Gust Load Factor calculation at cruise conditions.\ + This is Minimum Design Cruise Speed for Part 23 aircraft and \ + VM0 for Part 25 aircraft', + ) + self.add_output( + 'max_maneuver_factor', + units='unitless', + desc='EMLF: maximum maneuver load factor, units are in g`s', ) + self.add_output('min_dive_vel', units='kn', desc='VDMIN: dive velocity') + self.declare_partials('*', '*') + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + + max_struct_speed_mph = inputs[Aircraft.Design.MAX_STRUCTURAL_SPEED] + + CATD = self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + WGS_greater_than_20_flag = self.options[Aircraft.Wing.LOADING_ABOVE_20] + + max_struct_speed_kts = max_struct_speed_mph / 1.15 + + if CATD < 3: + gross_mass = inputs[Mission.Design.GROSS_MASS] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + if verbosity > Verbosity.BRIEF: + if exp_wing_area <= 0.0: + print('Aircraft.Wing.EXPOSED_AREA must be positive.') + if gross_mass <= 0.0: + print('Mission.Design.GROSS_MASS must be positive.') + wing_loading = gross_mass / exp_wing_area + + VCMAX = 0.9 * max_struct_speed_kts + if CATD <= 1: + if WGS_greater_than_20_flag: + VCCOF = 33.0 - (0.0550 * (wing_loading - 20.0)) + else: + VCCOF = 33.0 + elif CATD == 2: + if WGS_greater_than_20_flag: + VCCOF = 36.0 - (0.0925 * (wing_loading - 20.0)) + else: + VCCOF = 36.0 + + VCMIN = VCCOF * (wing_loading**0.5) + + if smooth: + VCMIN = VCMIN * sigmoidX(VCMIN / VCMAX, 1, -0.01) + VCMAX * sigmoidX( + VCMIN / VCMAX, 1, 0.01 + ) + else: + if VCMIN > VCMAX: + VCMIN = VCMAX + + if CATD == 0: + if WGS_greater_than_20_flag: + VDCOF = 1.4 - (0.000625 * (wing_loading - 20.0)) + else: + VDCOF = 1.4 + elif CATD == 1: + if WGS_greater_than_20_flag: + VDCOF = 1.5 - (0.001875 * (wing_loading - 20.0)) + else: + VDCOF = 1.5 + elif CATD == 2: + if WGS_greater_than_20_flag: + VDCOF = 1.55 - (0.0025 * (wing_loading - 20.0)) + else: + VDCOF = 1.55 + + min_dive_vel = VDCOF * VCMIN + + if smooth: + min_dive_vel = max_struct_speed_kts * sigmoidX( + min_dive_vel / max_struct_speed_kts, 1, -0.01 + ) + min_dive_vel * sigmoidX(min_dive_vel / max_struct_speed_kts, 1, 0.01) + else: + if min_dive_vel < max_struct_speed_kts: + min_dive_vel = max_struct_speed_kts + + max_airspeed = 0.85 * min_dive_vel + vel_c = VCMIN + + if CATD == 0: + max_maneuver_factor = 3.8 + elif CATD == 1: + max_maneuver_factor = 4.4 + elif CATD == 2: + max_maneuver_factor = 6.0 + + elif CATD == 3: + max_maneuver_factor = 2.5 + min_dive_vel = 1.2 * max_struct_speed_kts + max_airspeed = max_struct_speed_kts + vel_c = max_airspeed + + elif CATD > 3.001: + max_maneuver_factor = CATD + min_dive_vel = 1.2 * max_struct_speed_kts + max_airspeed = max_struct_speed_kts + vel_c = max_airspeed + + outputs['max_airspeed'] = max_airspeed + outputs['vel_c'] = vel_c + outputs['max_maneuver_factor'] = max_maneuver_factor + outputs['min_dive_vel'] = min_dive_vel + + def compute_partials(self, inputs, partials): + max_struct_speed_mph = inputs[Aircraft.Design.MAX_STRUCTURAL_SPEED] + + CATD = self.options[Aircraft.Design.PART25_STRUCTURAL_CATEGORY] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + WGS_greater_than_20_flag = self.options[Aircraft.Wing.LOADING_ABOVE_20] + + max_struct_speed_kts = max_struct_speed_mph / 1.15 + dmax_struct_speed_kts_dmax_struct_speed_mph = 1 / 1.15 + dmax_struct_speed_kts_dgross_mass = 0.0 + dmax_struct_speed_kts_dexp_wing_area = 0.0 + + if CATD < 3: + gross_mass = inputs[Mission.Design.GROSS_MASS] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + wing_loading = gross_mass / exp_wing_area + dwing_loading_dgross_mass = 1 / exp_wing_area + dwing_loading_dexp_wing_area = -gross_mass / exp_wing_area**2 + + VCMAX = 0.9 * max_struct_speed_kts + dVCMAX_dmax_struct_speed_mph = 0.9 / 1.15 + + if CATD <= 1: + if WGS_greater_than_20_flag: + VCCOF = 33.0 - (0.0550 * (wing_loading - 20.0)) + dVCCOF_dwing_loading = -0.0550 + dVCCOF_dgross_mass = dVCCOF_dwing_loading * dwing_loading_dgross_mass + dVCCOF_dexp_wing_area = dVCCOF_dwing_loading * dwing_loading_dexp_wing_area + else: + VCCOF = 33.0 + dVCCOF_dwing_loading = 0.0 + dVCCOF_dgross_mass = 0.0 + dVCCOF_dexp_wing_area = 0.0 + elif CATD == 2: + if WGS_greater_than_20_flag: + VCCOF = 36.0 - (0.0925 * (wing_loading - 20.0)) + dVCCOF_dwing_loading = -0.0925 + dVCCOF_dgross_mass = dVCCOF_dwing_loading * dwing_loading_dgross_mass + dVCCOF_dexp_wing_area = dVCCOF_dwing_loading * dwing_loading_dexp_wing_area + else: + VCCOF = 36 + dVCCOF_dwing_loading = 0.0 + dVCCOF_dgross_mass = 0.0 + dVCCOF_dexp_wing_area = 0.0 + + wl_sqrt = wing_loading**0.5 + d_wl_sqrt_d_wing_loading = 0.5 * wing_loading**-0.5 + VCMIN = VCCOF * wl_sqrt + dVCMIN_dgross_mass = ( + dVCCOF_dgross_mass * wl_sqrt + + VCCOF * d_wl_sqrt_d_wing_loading * dwing_loading_dgross_mass + ) + dVCMIN_dexp_wing_area = ( + dVCCOF_dexp_wing_area * wl_sqrt + + VCCOF * d_wl_sqrt_d_wing_loading * dwing_loading_dexp_wing_area + ) + dVCMIN_dmax_struct_speed_mph = 0.0 + + if smooth: + SigA = sigmoidX(VCMIN / VCMAX, 1, -0.01) + SigB = sigmoidX(VCMIN / VCMAX, 1, 0.01) + DSigB = dSigmoidXdx(VCMIN / VCMAX, 1, 0.01) + VCMIN_1 = VCMIN * SigA + VCMAX * SigB + dVCMIN_dgross_mass = ( + dVCMIN_dgross_mass * SigA + - VCMIN * DSigB * dVCMIN_dgross_mass / VCMAX + + VCMAX * DSigB * dVCMIN_dgross_mass / VCMAX + ) + dVCMIN_dexp_wing_area = ( + dVCMIN_dexp_wing_area * SigA + - VCMIN * DSigB * dVCMIN_dexp_wing_area / VCMAX + + VCMAX * DSigB * dVCMIN_dexp_wing_area / VCMAX + ) + dVCMIN_dmax_struct_speed_mph = ( + dVCMIN_dmax_struct_speed_mph * sigmoidX(VCMIN / VCMAX, 1, -0.01) + + VCMIN + * DSigB + * dquotient( + (VCMAX - VCMIN), + VCMAX, + dVCMAX_dmax_struct_speed_mph - dVCMIN_dmax_struct_speed_mph, + dVCMAX_dmax_struct_speed_mph, + ) + + dVCMAX_dmax_struct_speed_mph * SigB + + VCMAX + * DSigB + * dquotient( + (VCMIN - VCMAX), + VCMAX, + dVCMIN_dmax_struct_speed_mph - dVCMAX_dmax_struct_speed_mph, + dVCMAX_dmax_struct_speed_mph, + ) + ) + VCMIN = VCMIN_1 + else: + if VCMIN > VCMAX: + VCMIN = VCMAX + dVCMIN_dmax_struct_speed_mph = dVCMAX_dmax_struct_speed_mph + dVCMIN_dgross_mass = 0.0 + dVCMIN_dexp_wing_area = 0.0 + + if CATD == 0: + if WGS_greater_than_20_flag: + VDCOF = 1.4 - (0.000625 * (wing_loading - 20.0)) + dVDCOF_dwing_loading = -0.000625 + dVDCOF_dgross_mass = dVDCOF_dwing_loading * dwing_loading_dgross_mass + dVDCOF_dexp_wing_area = dVDCOF_dwing_loading * dwing_loading_dexp_wing_area + else: + VDCOF = 1.4 + dVDCOF_dwing_loading = 0.0 + dVDCOF_dgross_mass = 0.0 + dVDCOF_dexp_wing_area = 0.0 + if CATD == 1: + if WGS_greater_than_20_flag: + VDCOF = 1.5 - (0.001875 * (wing_loading - 20.0)) + dVDCOF_dwing_loading = -0.001875 + dVDCOF_dgross_mass = dVDCOF_dwing_loading * dwing_loading_dgross_mass + dVDCOF_dexp_wing_area = dVDCOF_dwing_loading * dwing_loading_dexp_wing_area + else: + VDCOF = 1.5 + dVDCOF_dwing_loading = 0.0 + dVDCOF_dgross_mass = 0.0 + dVDCOF_dexp_wing_area = 0.0 + if CATD == 2: + if WGS_greater_than_20_flag: + VDCOF = 1.55 - (0.0025 * (wing_loading - 20.0)) + dVDCOF_dwing_loading = -0.0025 + dVDCOF_dgross_mass = dVDCOF_dwing_loading * dwing_loading_dgross_mass + dVDCOF_dexp_wing_area = dVDCOF_dwing_loading * dwing_loading_dexp_wing_area + else: + VDCOF = 1.55 + dVDCOF_dwing_loading = 0.0 + dVDCOF_dgross_mass = 0.0 + dVDCOF_dexp_wing_area = 0.0 + + min_dive_vel = VDCOF * VCMIN + dmin_dive_vel_dgross_mass = dVDCOF_dgross_mass * VCMIN + VDCOF * dVCMIN_dgross_mass + dmin_dive_vel_dexp_wing_area = ( + dVDCOF_dexp_wing_area * VCMIN + VDCOF * dVCMIN_dexp_wing_area + ) + dmin_dive_vel_dmax_struct_speed_mph = VDCOF * dVCMIN_dmax_struct_speed_mph + + if smooth: + SigC = sigmoidX(min_dive_vel / max_struct_speed_kts, 1, -0.01) + SigD = sigmoidX(min_dive_vel / max_struct_speed_kts, 1, 0.01) + DSigD = dSigmoidXdx(min_dive_vel / max_struct_speed_kts, 1, 0.01) + min_dive_vel_1 = max_struct_speed_kts * SigC + min_dive_vel * SigD + dmin_dive_vel_dmax_struct_speed_mph = ( + dmax_struct_speed_kts_dmax_struct_speed_mph * SigC + + max_struct_speed_kts + * DSigD + * dquotient( + (max_struct_speed_kts - min_dive_vel), + max_struct_speed_kts, + ( + dmax_struct_speed_kts_dmax_struct_speed_mph + - dmin_dive_vel_dmax_struct_speed_mph + ), + dmax_struct_speed_kts_dmax_struct_speed_mph, + ) + + dmin_dive_vel_dmax_struct_speed_mph * SigD + + min_dive_vel + * DSigD + * dquotient( + (min_dive_vel - max_struct_speed_kts), + max_struct_speed_kts, + dmin_dive_vel_dmax_struct_speed_mph + - dmax_struct_speed_kts_dmax_struct_speed_mph, + dmax_struct_speed_kts_dmax_struct_speed_mph, + ) + ) + dmin_dive_vel_dgross_mass = ( + dmax_struct_speed_kts_dgross_mass * SigC + + max_struct_speed_kts + * DSigD + * dquotient( + max_struct_speed_kts - min_dive_vel, + max_struct_speed_kts, + dmax_struct_speed_kts_dgross_mass - dmin_dive_vel_dgross_mass, + dmax_struct_speed_kts_dgross_mass, + ) + + dmin_dive_vel_dgross_mass * SigD + + min_dive_vel + * DSigD + * dquotient( + (min_dive_vel - max_struct_speed_kts), + max_struct_speed_kts, + dmin_dive_vel_dgross_mass - dmax_struct_speed_kts_dgross_mass, + dmax_struct_speed_kts_dgross_mass, + ) + ) + dmin_dive_vel_dexp_wing_area = ( + dmax_struct_speed_kts_dexp_wing_area * SigC + + max_struct_speed_kts + * DSigD + * dquotient( + max_struct_speed_kts - min_dive_vel, + max_struct_speed_kts, + dmax_struct_speed_kts_dexp_wing_area - dmin_dive_vel_dexp_wing_area, + dmax_struct_speed_kts_dexp_wing_area, + ) + + dmin_dive_vel_dexp_wing_area * SigD + + min_dive_vel + * DSigD + * dquotient( + (min_dive_vel - max_struct_speed_kts), + max_struct_speed_kts, + dmin_dive_vel_dexp_wing_area - dmax_struct_speed_kts_dexp_wing_area, + dmax_struct_speed_kts_dexp_wing_area, + ) + ) + min_dive_vel = min_dive_vel_1 + else: + if min_dive_vel < max_struct_speed_kts: # note: this creates a discontinuity + min_dive_vel = max_struct_speed_kts + dmin_dive_vel_dgross_mass = 0 + dmin_dive_vel_dexp_wing_area = 0 + dmin_dive_vel_dmax_struct_speed_mph = ( + dmax_struct_speed_kts_dmax_struct_speed_mph + ) + + partials['min_dive_vel', Mission.Design.GROSS_MASS] = dmin_dive_vel_dgross_mass + partials['min_dive_vel', Aircraft.Wing.EXPOSED_AREA] = dmin_dive_vel_dexp_wing_area + partials['min_dive_vel', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + dmin_dive_vel_dmax_struct_speed_mph + ) + + partials['max_airspeed', Mission.Design.GROSS_MASS] = 0.85 * dmin_dive_vel_dgross_mass + partials['max_airspeed', Aircraft.Wing.EXPOSED_AREA] = ( + 0.85 * dmin_dive_vel_dexp_wing_area + ) + partials['max_airspeed', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + 0.85 * dmin_dive_vel_dmax_struct_speed_mph + ) + + partials['vel_c', Mission.Design.GROSS_MASS] = dVCMIN_dgross_mass + partials['vel_c', Aircraft.Wing.EXPOSED_AREA] = dVCMIN_dexp_wing_area + partials['vel_c', Aircraft.Design.MAX_STRUCTURAL_SPEED] = dVCMIN_dmax_struct_speed_mph + + if CATD == 3: + partials['max_airspeed', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + dmax_struct_speed_kts_dmax_struct_speed_mph + ) + partials['min_dive_vel', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + 1.2 * dmax_struct_speed_kts_dmax_struct_speed_mph + ) + partials['vel_c', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + 1.0 * dmax_struct_speed_kts_dmax_struct_speed_mph + ) + elif CATD > 3.001: + partials['max_airspeed', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + 1.0 * dmax_struct_speed_kts_dmax_struct_speed_mph + ) + partials['min_dive_vel', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + 1.2 * dmax_struct_speed_kts_dmax_struct_speed_mph + ) + partials['vel_c', Aircraft.Design.MAX_STRUCTURAL_SPEED] = ( + 1.0 * dmax_struct_speed_kts_dmax_struct_speed_mph + ) + + +class BWBLoadFactors(om.ExplicitComponent): + """ + Computation of structural ultimate load factor. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER) + add_aviary_option(self, Settings.VERBOSITY) def setup(self): + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.EXPOSED_AREA, units='ft**2') + + self.add_input( + 'density_ratio', + units='unitless', + desc='SIGMA (in GASP): density ratio = density at Altitude / density at Sea level', + ) + self.add_input( + 'V9', + units='kn', + desc='V9: intermediate value. Typically it is maximum flight speed.', + ) + self.add_input('min_dive_vel', units='kn', desc='VDMIN: dive velocity') + self.add_input( + 'max_maneuver_factor', + units='unitless', + desc='EMLF: maximum maneuver load factor, units are in g`s', + ) + add_aviary_input(self, Aircraft.Wing.AVERAGE_CHORD, units='ft') + add_aviary_input(self, Aircraft.Design.LIFT_CURVE_SLOPE, units='1/rad') + + add_aviary_output(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, units='unitless') + + self.declare_partials(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, '*') + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + ULF_from_maneuver = self.options[Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER] + + if ULF_from_maneuver == True: + ULF = 1.5 * max_maneuver_factor + else: + gross_mass = inputs[Mission.Design.GROSS_MASS] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + if verbosity > Verbosity.BRIEF: + if exp_wing_area <= 0.0: + print('Aircraft.Wing.EXPOSED_AREA must be positive.') + if gross_mass <= 0.0: + print('Mission.Design.GROSS_MASS must be positive.') + wing_loading = gross_mass / exp_wing_area + + density_ratio = inputs['density_ratio'] + V9 = inputs['V9'] + min_dive_vel = inputs['min_dive_vel'] + max_maneuver_factor = inputs['max_maneuver_factor'] + avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] + Cl_alpha = inputs[Aircraft.Design.LIFT_CURVE_SLOPE] + + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + + mass_ratio = ( + 2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) + ) + k_load_factor = 0.88 * mass_ratio / (5.3 + mass_ratio) + cruise_load_factor = 1.0 + ( + (k_load_factor * 50.0 * V9 * Cl_alpha) / (498.0 * wing_loading) + ) + dive_load_factor = 1.0 + ( + (k_load_factor * 25.0 * min_dive_vel * Cl_alpha) / (498.0 * wing_loading) + ) + + # set gust_load_factor between cruise_load_factor and dive_load_factor + if smooth: + gust_load_factor = dive_load_factor * sigmoidX( + cruise_load_factor / dive_load_factor, 1, -0.01 + ) + cruise_load_factor * sigmoidX(cruise_load_factor / dive_load_factor, 1, 0.01) + else: + if cruise_load_factor > dive_load_factor: + gust_load_factor = cruise_load_factor + else: + gust_load_factor = dive_load_factor + + # set ULF between max_maneuver_factor and gust_load_factor + if smooth: + ULF = 1.5 * ( + gust_load_factor * sigmoidX(max_maneuver_factor / gust_load_factor, 1, -0.01) + + max_maneuver_factor + * sigmoidX(max_maneuver_factor / gust_load_factor, 1, 0.01) + ) + else: + if gust_load_factor > max_maneuver_factor: + ULF = 1.5 * gust_load_factor + else: + ULF = 1.5 * max_maneuver_factor + + outputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ULF + + def compute_partials(self, inputs, partials): + ULF_from_maneuver = self.options[Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER] + + if ULF_from_maneuver == True: + # ULF = 1.5 * max_maneuver_factor + dULF_dmax_maneuver_factor = 1.5 + dULF_dgross_mass = 0.0 + dULF_dexp_wing_areas = 0.0 + dULF_ddensity_ratio = 0.0 + dULF_davg_chord = 0.0 + dULF_dCl_alpha = 0.0 + dULF_dV9 = 0.0 + dULF_dmin_dive_vel = 0.0 + else: + gross_mass = inputs[Mission.Design.GROSS_MASS] + exp_wing_area = inputs[Aircraft.Wing.EXPOSED_AREA] + wing_loading = gross_mass / exp_wing_area + dwing_loading_dgross_mass = 1 / exp_wing_area + dwing_loading_dexp_wing_area = -gross_mass / exp_wing_area**2 + + density_ratio = inputs['density_ratio'] + V9 = inputs['V9'] + min_dive_vel = inputs['min_dive_vel'] + max_maneuver_factor = inputs['max_maneuver_factor'] + avg_chord = inputs[Aircraft.Wing.AVERAGE_CHORD] + Cl_alpha = inputs[Aircraft.Design.LIFT_CURVE_SLOPE] + + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + + mass_ratio = ( + 2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) + ) + k_load_factor = 0.88 * mass_ratio / (5.3 + mass_ratio) + cruise_load_factor = 1.0 + ( + (k_load_factor * 50.0 * V9 * Cl_alpha) / (498.0 * wing_loading) + ) + dive_load_factor = 1.0 + ( + (k_load_factor * 25.0 * min_dive_vel * Cl_alpha) / (498.0 * wing_loading) + ) + + dmass_ratio_dgross_mass = ( + 2.0 + * dwing_loading_dgross_mass + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) + ) + dmass_ratio_dexp_wing_area = ( + 2.0 + * dwing_loading_dexp_wing_area + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) + ) + dmass_ratio_ddensity_ratio = ( + -2.0 + * wing_loading + / (density_ratio**2 * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha * 32.2) + ) + dmass_ratio_davg_chord = ( + -2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord**2 * Cl_alpha * 32.2) + ) + dmass_ratio_dCl_alpha = ( + -2.0 + * wing_loading + / (density_ratio * RHO_SEA_LEVEL_ENGLISH * avg_chord * Cl_alpha**2 * 32.2) + ) + + dk_load_factor_dgross_mass = dquotient( + 0.88 * mass_ratio, + 5.3 + mass_ratio, + 0.88 * dmass_ratio_dgross_mass, + dmass_ratio_dgross_mass, + ) + dk_load_factor_dexp_wing_areas = dquotient( + 0.88 * mass_ratio, + 5.3 + mass_ratio, + 0.88 * dmass_ratio_dexp_wing_area, + dmass_ratio_dexp_wing_area, + ) + dk_load_factor_ddensity_ratio = dquotient( + 0.88 * mass_ratio, + 5.3 + mass_ratio, + 0.88 * dmass_ratio_ddensity_ratio, + dmass_ratio_ddensity_ratio, + ) + dk_load_factor_davg_chord = dquotient( + 0.88 * mass_ratio, + 5.3 + mass_ratio, + 0.88 * dmass_ratio_davg_chord, + dmass_ratio_davg_chord, + ) + dk_load_factor_dCl_alpha = dquotient( + 0.88 * mass_ratio, + 5.3 + mass_ratio, + 0.88 * dmass_ratio_dCl_alpha, + dmass_ratio_dCl_alpha, + ) + + dcruise_load_factor_dgross_mass = dquotient( + (k_load_factor * 50.0 * V9 * Cl_alpha), + (498.0 * wing_loading), + (dk_load_factor_dgross_mass * 50.0 * V9 * Cl_alpha), + 498 * dwing_loading_dgross_mass, + ) + dcruise_load_factor_dexp_wing_areas = dquotient( + (k_load_factor * 50.0 * V9 * Cl_alpha), + (498.0 * wing_loading), + (dk_load_factor_dexp_wing_areas * 50.0 * V9 * Cl_alpha), + 498 * dwing_loading_dexp_wing_area, + ) + dcruise_load_factor_ddensity_ratio = ( + dk_load_factor_ddensity_ratio * 50.0 * V9 * Cl_alpha + ) / (498.0 * wing_loading) + dcruise_load_factor_davg_chord = (dk_load_factor_davg_chord * 50.0 * V9 * Cl_alpha) / ( + 498.0 * wing_loading + ) + dcruise_load_factor_dCl_alpha = ( + dk_load_factor_dCl_alpha * 50.0 * V9 * Cl_alpha + k_load_factor * 50 * V9 + ) / (498.0 * wing_loading) + dcruise_load_factor_dV9 = (k_load_factor * 50.0 * Cl_alpha) / (498.0 * wing_loading) + dcruise_load_factor_dmin_dive_vel = 0.0 + + ddive_load_factor_dgross_mass = dquotient( + (k_load_factor * 25.0 * min_dive_vel * Cl_alpha), + (498.0 * wing_loading), + (dk_load_factor_dgross_mass * 25.0 * min_dive_vel * Cl_alpha), + 498 * dwing_loading_dgross_mass, + ) + ddive_load_factor_dexp_wing_areas = dquotient( + (k_load_factor * 25.0 * min_dive_vel * Cl_alpha), + (498.0 * wing_loading), + (dk_load_factor_dexp_wing_areas * 25.0 * min_dive_vel * Cl_alpha), + 498 * dwing_loading_dexp_wing_area, + ) + ddive_load_factor_ddensity_ratio = ( + dk_load_factor_ddensity_ratio * 25 * min_dive_vel * Cl_alpha + ) / (498.0 * wing_loading) + ddive_load_factor_davg_chord = ( + dk_load_factor_davg_chord * 25 * min_dive_vel * Cl_alpha + ) / (498.0 * wing_loading) + ddive_load_factor_dCl_alpha = ( + dk_load_factor_dCl_alpha * 25 * min_dive_vel * Cl_alpha + + k_load_factor * 50 * min_dive_vel + ) / (498.0 * wing_loading) + ddive_load_factor_dmin_dive_vel = (k_load_factor * 25 * Cl_alpha) / ( + 498.0 * wing_loading + ) + ddive_load_factor_dV9 = 0.0 + + # set gust_load_factor and gust_load_factor partials + if smooth: + SigG = sigmoidX(cruise_load_factor / dive_load_factor, 1, -0.01) + SigH = sigmoidX(cruise_load_factor / dive_load_factor, 1, 0.01) + DSigG = dSigmoidXdx(cruise_load_factor / dive_load_factor, 1, -0.01) + DSigH = dSigmoidXdx(cruise_load_factor / dive_load_factor, 1, 0.01) + gust_load_factor = dive_load_factor * SigG + cruise_load_factor * SigH + dgust_load_factor_dgross_mass = ( + ddive_load_factor_dgross_mass * SigG + + dive_load_factor + * DSigG + * dquotient( + (dive_load_factor - cruise_load_factor), + dive_load_factor, + ddive_load_factor_dgross_mass - dcruise_load_factor_dgross_mass, + ddive_load_factor_dgross_mass, + ) + + dcruise_load_factor_dgross_mass * SigH + + cruise_load_factor + * DSigG + * dquotient( + (cruise_load_factor - dive_load_factor), + dive_load_factor, + dcruise_load_factor_dgross_mass - ddive_load_factor_dgross_mass, + ddive_load_factor_dgross_mass, + ) + ) + dgust_load_factor_dexp_wing_areas = ( + ddive_load_factor_dexp_wing_areas * SigG + + dive_load_factor + * DSigG + * dquotient( + (dive_load_factor - cruise_load_factor), + dive_load_factor, + ddive_load_factor_dexp_wing_areas - dcruise_load_factor_dexp_wing_areas, + ddive_load_factor_dexp_wing_areas, + ) + + dcruise_load_factor_dexp_wing_areas * SigH + + cruise_load_factor + * DSigG + * dquotient( + (cruise_load_factor - dive_load_factor), + dive_load_factor, + dcruise_load_factor_dexp_wing_areas - ddive_load_factor_dexp_wing_areas, + ddive_load_factor_dexp_wing_areas, + ) + ) + dgust_load_factor_ddensity_ratio = ( + ddive_load_factor_ddensity_ratio * SigG + + dive_load_factor + * DSigG + * dquotient( + (dive_load_factor - cruise_load_factor), + dive_load_factor, + ddive_load_factor_ddensity_ratio - dcruise_load_factor_ddensity_ratio, + ddive_load_factor_ddensity_ratio, + ) + + dcruise_load_factor_ddensity_ratio * SigH + + cruise_load_factor + * DSigH + * dquotient( + (cruise_load_factor - dive_load_factor), + dive_load_factor, + dcruise_load_factor_ddensity_ratio - ddive_load_factor_ddensity_ratio, + ddive_load_factor_ddensity_ratio, + ) + ) + dgust_load_factor_davg_chord = ( + ddive_load_factor_davg_chord * SigG + + dive_load_factor + * DSigH + * dquotient( + (dive_load_factor - cruise_load_factor), + dive_load_factor, + ddive_load_factor_davg_chord - dcruise_load_factor_davg_chord, + ddive_load_factor_davg_chord, + ) + + dcruise_load_factor_davg_chord * SigH + + cruise_load_factor + * DSigH + * dquotient( + (cruise_load_factor - dive_load_factor), + dive_load_factor, + dcruise_load_factor_davg_chord - ddive_load_factor_davg_chord, + ddive_load_factor_davg_chord, + ) + ) + dgust_load_factor_dCl_alpha = ( + ddive_load_factor_dCl_alpha * SigG + + dive_load_factor + * DSigH + * dquotient( + (dive_load_factor - cruise_load_factor), + dive_load_factor, + ddive_load_factor_dCl_alpha - dcruise_load_factor_dCl_alpha, + ddive_load_factor_dCl_alpha, + ) + + dcruise_load_factor_dCl_alpha * SigH + + cruise_load_factor + * DSigH + * dquotient( + (cruise_load_factor - dive_load_factor), + dive_load_factor, + dcruise_load_factor_dCl_alpha - ddive_load_factor_dCl_alpha, + ddive_load_factor_dCl_alpha, + ) + ) + dgust_load_factor_dV9 = ( + dive_load_factor + * DSigH + * dquotient( + (dive_load_factor - cruise_load_factor), + dive_load_factor, + ddive_load_factor_dV9 - dcruise_load_factor_dV9, + ddive_load_factor_dV9, + ) + + dcruise_load_factor_dV9 * SigH + + cruise_load_factor + * DSigH + * dquotient( + (cruise_load_factor - dive_load_factor), + dive_load_factor, + dcruise_load_factor_dV9 - ddive_load_factor_dV9, + ddive_load_factor_dV9, + ) + ) + dgust_loading_dmin_dive_vel = ( + ddive_load_factor_dmin_dive_vel * SigG + + dive_load_factor + * DSigH + * dquotient( + (dive_load_factor - cruise_load_factor), + dive_load_factor, + ddive_load_factor_dmin_dive_vel, + ddive_load_factor_dmin_dive_vel, + ) + + cruise_load_factor + * DSigH + * dquotient( + (cruise_load_factor - dive_load_factor), + dive_load_factor, + -ddive_load_factor_dmin_dive_vel, + ddive_load_factor_dmin_dive_vel, + ) + ) + else: + if cruise_load_factor > dive_load_factor: + gust_load_factor = cruise_load_factor + dgust_load_factor_dgross_mass = dcruise_load_factor_dgross_mass + dgust_load_factor_dexp_wing_areas = dcruise_load_factor_dexp_wing_areas + dgust_load_factor_ddensity_ratio = dcruise_load_factor_ddensity_ratio + dgust_load_factor_davg_chord = dcruise_load_factor_davg_chord + dgust_load_factor_dCl_alpha = dcruise_load_factor_dCl_alpha + dgust_load_factor_dV9 = dcruise_load_factor_dV9 + dgust_load_factor_dmin_dive_vel = 0.0 + else: + gust_load_factor = dive_load_factor + dgust_load_factor_dgross_mass = dquotient( + (k_load_factor * 25.0 * min_dive_vel * Cl_alpha), + (498.0 * wing_loading), + (dk_load_factor_dgross_mass * 25.0 * min_dive_vel * Cl_alpha), + 498 * dwing_loading_dgross_mass, + ) + dgust_load_factor_dexp_wing_areas = dquotient( + (k_load_factor * 25.0 * min_dive_vel * Cl_alpha), + (498.0 * wing_loading), + (dk_load_factor_dexp_wing_areas * 25.0 * min_dive_vel * Cl_alpha), + 498 * dwing_loading_dexp_wing_area, + ) + dgust_load_factor_ddensity_ratio = ( + dk_load_factor_ddensity_ratio * 25 * min_dive_vel * Cl_alpha + ) / (498.0 * wing_loading) + dgust_load_factor_davg_chord = ( + dk_load_factor_davg_chord * 25 * min_dive_vel * Cl_alpha + ) / (498.0 * wing_loading) + dgust_load_factor_dCl_alpha = ( + dk_load_factor_dCl_alpha * 25 * min_dive_vel * Cl_alpha + + k_load_factor * 25 * min_dive_vel + ) / (498.0 * wing_loading) + dgust_load_factor_dmin_dive_vel = (k_load_factor * 25 * Cl_alpha) / ( + 498.0 * wing_loading + ) + dgust_load_factor_dV9 = 0.0 + + # set ULF partials + if smooth: + SigK = sigmoidX(max_maneuver_factor / gust_load_factor, 1, -0.01) + SigL = sigmoidX(max_maneuver_factor / gust_load_factor, 1, 0.01) + DSigL = dSigmoidXdx(max_maneuver_factor / gust_load_factor, 1, 0.01) + # ULF = 1.5 * ( + # gust_load_factor + # * sigmoidX(max_maneuver_factor / gust_load_factor, 1, 0.01) + # + max_maneuver_factor + # * sigmoidX(max_maneuver_factor / gust_load_factor, 1, 0.01) + # ) + dULF_dmax_maneuver_factor = 1.5 * ( + gust_load_factor + * DSigL + * dquotient( + (gust_load_factor - max_maneuver_factor), + gust_load_factor, + -1.0, + 0.0, + ) + + SigL + + max_maneuver_factor + * DSigL + * dquotient( + (max_maneuver_factor - gust_load_factor), gust_load_factor, 1.0, 0.0 + ) + ) + dULF_dgross_mass = 1.5 * ( + dgust_load_factor_dgross_mass * SigK + + gust_load_factor + * DSigL + * dquotient( + (gust_load_factor - max_maneuver_factor), + gust_load_factor, + dgust_load_factor_dgross_mass, + dgust_load_factor_dgross_mass, + ) + + max_maneuver_factor + * DSigL + * dquotient( + (max_maneuver_factor - gust_load_factor), + gust_load_factor, + -dgust_load_factor_dgross_mass, + dgust_load_factor_dgross_mass, + ) + ) + dULF_dexp_wing_areas = 1.5 * ( + dgust_load_factor_dexp_wing_areas * SigK + + gust_load_factor + * DSigL + * dquotient( + (gust_load_factor - max_maneuver_factor), + gust_load_factor, + dgust_load_factor_dexp_wing_areas, + dgust_load_factor_dexp_wing_areas, + ) + + max_maneuver_factor + * DSigL + * dquotient( + (max_maneuver_factor - gust_load_factor), + gust_load_factor, + -dgust_load_factor_dexp_wing_areas, + dgust_load_factor_dexp_wing_areas, + ) + ) + dULF_ddensity_ratio = 1.5 * ( + dgust_load_factor_ddensity_ratio * SigK + + gust_load_factor + * DSigL + * dquotient( + (gust_load_factor - max_maneuver_factor), + gust_load_factor, + dgust_load_factor_ddensity_ratio, + dgust_load_factor_ddensity_ratio, + ) + + max_maneuver_factor + * DSigL + * dquotient( + (max_maneuver_factor - gust_load_factor), + gust_load_factor, + -dgust_load_factor_ddensity_ratio, + dgust_load_factor_ddensity_ratio, + ) + ) + dULF_davg_chord = 1.5 * ( + dgust_load_factor_davg_chord * SigK + + gust_load_factor + * DSigL + * dquotient( + (gust_load_factor - max_maneuver_factor), + gust_load_factor, + dgust_load_factor_davg_chord, + dgust_load_factor_davg_chord, + ) + + max_maneuver_factor + * DSigL + * dquotient( + (max_maneuver_factor - gust_load_factor), + gust_load_factor, + -dgust_load_factor_davg_chord, + dgust_load_factor_davg_chord, + ) + ) + dULF_dCl_alpha = 1.5 * ( + dgust_load_factor_dCl_alpha * SigK + + gust_load_factor + * DSigL + * dquotient( + (gust_load_factor - max_maneuver_factor), + gust_load_factor, + dgust_load_factor_dCl_alpha, + dgust_load_factor_dCl_alpha, + ) + + max_maneuver_factor + * DSigL + * dquotient( + (max_maneuver_factor - gust_load_factor), + gust_load_factor, + -dgust_load_factor_dCl_alpha, + dgust_load_factor_dCl_alpha, + ) + ) + dULF_dV9 = 1.5 * ( + dgust_load_factor_dV9 * SigK + + gust_load_factor + * DSigL + * dquotient( + (gust_load_factor - max_maneuver_factor), + gust_load_factor, + dgust_load_factor_dV9, + dgust_load_factor_dV9, + ) + + max_maneuver_factor + * DSigL + * dquotient( + (max_maneuver_factor - gust_load_factor), + gust_load_factor, + -dgust_load_factor_dV9, + dgust_load_factor_dV9, + ) + ) + dULF_dmin_dive_vel = 0.0 + else: + if gust_load_factor > max_maneuver_factor: + # ULF = 1.5 * gust_load_factor + dULF_dmax_maneuver_factor = 0.0 + dULF_dgross_mass = 1.5 * dgust_load_factor_dgross_mass + dULF_dexp_wing_areas = 1.5 * dgust_load_factor_dexp_wing_areas + dULF_ddensity_ratio = 1.5 * dgust_load_factor_ddensity_ratio + dULF_davg_chord = 1.5 * dgust_load_factor_davg_chord + dULF_dCl_alpha = 1.5 * dgust_load_factor_dCl_alpha + dULF_dV9 = 1.5 * dgust_load_factor_dV9 + dULF_dmin_dive_vel = 1.5 * dgust_load_factor_dmin_dive_vel + else: + # ULF = 1.5 * max_maneuver_factor + dULF_dmax_maneuver_factor = 1.5 + dULF_dgross_mass = 0.0 + dULF_dexp_wing_areas = 0.0 + dULF_ddensity_ratio = 0.0 + dULF_davg_chord = 0.0 + dULF_dCl_alpha = 0.0 + dULF_dV9 = 0.0 + dULF_dmin_dive_vel = 0.0 + + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'max_maneuver_factor'] = ( + dULF_dmax_maneuver_factor + ) + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, Mission.Design.GROSS_MASS] = dULF_dgross_mass + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, Aircraft.Wing.EXPOSED_AREA] = ( + dULF_dexp_wing_areas + ) + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'density_ratio'] = dULF_ddensity_ratio + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, Aircraft.Wing.AVERAGE_CHORD] = dULF_davg_chord + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, Aircraft.Design.LIFT_CURVE_SLOPE] = ( + dULF_dCl_alpha + ) + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'V9'] = dULF_dV9 + partials[Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 'min_dive_vel'] = dULF_dmin_dive_vel + - aviary_options = self.options['aviary_options'] +class BWBDesignLoadGroup(om.Group): + """ + Design load group for GASP-based BWB type aircraft mass. + """ + def setup(self): self.add_subsystem( - "speeds", - LoadSpeeds( - aviary_options=aviary_options, - ), - promotes_inputs=['aircraft:*'], - promotes_outputs=[ - "max_airspeed", - "vel_c", - "max_maneuver_factor", - "min_dive_vel", - ], + 'speeds', + BWBLoadSpeeds(), + promotes_inputs=['*'], + promotes_outputs=['max_airspeed', 'vel_c', 'max_maneuver_factor', 'min_dive_vel'], ) self.add_subsystem( - "params", - LoadParameters( - aviary_options=aviary_options, - ), - promotes_inputs=["max_airspeed", "vel_c"], - promotes_outputs=["density_ratio", "V9", "max_mach"], + 'params', + LoadParameters(), + promotes_inputs=['max_airspeed', 'vel_c'], + promotes_outputs=['density_ratio', 'V9', 'max_mach'], ) self.add_subsystem( - "Cl_Alpha_calc", + 'CL_Alpha', LiftCurveSlopeAtCruise(), - promotes_inputs=["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "factors", - LoadFactors( - aviary_options=aviary_options, - ), - promotes_inputs=[ - "max_maneuver_factor", - "min_dive_vel", - "density_ratio", - "V9", - ] - + ["aircraft:*"], - promotes_outputs=[ - "aircraft:*" - ], + 'factors', + BWBLoadFactors(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - self.set_input_defaults(Aircraft.Wing.LOADING, val=128, units="lbf/ft**2") diff --git a/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py b/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py index c229c11a4d..d741cd6a5c 100644 --- a/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py +++ b/aviary/subsystems/mass/gasp_based/equipment_and_useful_load.py @@ -2,129 +2,139 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import GASPEngineType -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Mission - - -def sig(x): - return 1 / (1 + np.exp(-100 * x)) - - -def dsig(x): - return 100 * np.exp(-100 * x) / (np.exp(-100 * x) + 1) ** 2 - - -class EquipAndUsefulLoadMass(om.ExplicitComponent): +from aviary.utils.functions import sigmoidX, dSigmoidXdx, smooth_max, d_smooth_max +from aviary.variable_info.enums import AircraftTypes, GASPEngineType, Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Mission, Settings + + +def get_num_of_flight_attendent(num_pax): + num_flight_attendants = 0 + if num_pax >= 20.0: + num_flight_attendants = 1 + if num_pax >= 51.0: + num_flight_attendants = 2 + if num_pax >= 101.0: + num_flight_attendants = 3 + if num_pax >= 151.0: + num_flight_attendants = 4 + if num_pax >= 201.0: + num_flight_attendants = 5 + if num_pax >= 251.0: + num_flight_attendants = 6 + + return num_flight_attendants + + +def get_num_of_pilots(num_pax, engine_type): + num_pilots = 1 + if num_pax > 9.0: + num_pilots = 2 + if engine_type is GASPEngineType.TURBOJET and num_pax > 5.0: + num_pilots = 2 + if num_pax >= 351.0: + num_pilots = 3 + + return num_pilots + + +def get_num_of_lavatories(num_pax): + num_lavatories = 0 + if num_pax > 25.0: + num_lavatories = 1 + if num_pax >= 51.0: + num_lavatories = 2 + if num_pax >= 101.0: + num_lavatories = 3 + if num_pax >= 151.0: + num_lavatories = 4 + if num_pax >= 201.0: + num_lavatories = 5 + if num_pax >= 251.0: + num_lavatories = 6 + + return num_lavatories + + +class EquipMassPartialSum(om.ExplicitComponent): """ Computation of fixed equipment mass and useful load for GASP-based mass. + AC and furnishing masses are removed. Others will be moved to individual components. """ def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Aircraft.Engine.TYPE) + add_aviary_option(self, Aircraft.LandingGear.FIXED_GEAR) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - - add_aviary_input( - self, Aircraft.AirConditioning.MASS_COEFFICIENT, val=1, units="unitless") - add_aviary_input(self, Aircraft.AntiIcing.MASS, val=2, units="lbm") - add_aviary_input(self, Aircraft.APU.MASS, val=3, units="lbm") - add_aviary_input(self, Aircraft.Avionics.MASS, val=4, units="lbm") - add_aviary_input( - self, Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=5, units="lbm") - add_aviary_input(self, Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, - val=6, units="lbm") - add_aviary_input(self, Aircraft.Furnishings.MASS, val=7, units="lbm") - add_aviary_input( - self, Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=8, units="unitless") + add_aviary_input(self, Aircraft.AntiIcing.MASS, units='lbm') + add_aviary_input(self, Aircraft.APU.MASS, units='lbm') + add_aviary_input(self, Aircraft.Avionics.MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, units='lbm') + add_aviary_input(self, Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, units='lbm') add_aviary_input( - self, Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=9, units="unitless") - add_aviary_input( - self, Aircraft.Instruments.MASS_COEFFICIENT, val=10, units="unitless") - add_aviary_input( - self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=11, units="lbm") - add_aviary_input( - self, Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12, units="unitless") + self, Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, units='unitless' + ) + add_aviary_input(self, Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Instruments.MASS_COEFFICIENT, units='unitless') add_aviary_input( - self, Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=13, units="lbm") - - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400) - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=128) - add_aviary_input(self, Aircraft.Wing.SPAN, val=117.8) - add_aviary_input(self, Aircraft.LandingGear.TOTAL_MASS, val=200) - add_aviary_input(self, Aircraft.Controls.TOTAL_MASS, val=150) - add_aviary_input(self, Aircraft.Wing.AREA, val=150) - add_aviary_input(self, Aircraft.HorizontalTail.AREA, val=150) - add_aviary_input(self, Aircraft.VerticalTail.AREA, val=150) - add_aviary_input(self, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5) - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=13.1) - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, - val=np.full(num_engine_type, 4000), units="lbf") - add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, val=0.5) - add_aviary_input(self, Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, val=0.) - - add_aviary_output(self, Aircraft.Design.FIXED_USEFUL_LOAD, val=0) - add_aviary_output(self, Aircraft.Design.FIXED_EQUIPMENT_MASS, val=0) - - self.declare_partials(Aircraft.Design.FIXED_USEFUL_LOAD, '*', val=0.0) - self.declare_partials(Aircraft.Design.FIXED_EQUIPMENT_MASS, '*', val=0.0) - self.declare_partials(Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, val=1./GRAV_ENGLISH_LBM) + self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, units='lbm' + ) + add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT) + + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.LandingGear.TOTAL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Controls.TOTAL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, units='lbm') + + self.add_output('equip_mass_part', units='lbm') + + self.declare_partials('equip_mass_part', '*') + self.declare_partials( + 'equip_mass_part', + Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, + val=1.0 / GRAV_ENGLISH_LBM, + ) def compute(self, inputs, outputs): - - options: AviaryValues = self.options["aviary_options"] - PAX = options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') - smooth = options.get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - num_engines = self.options['aviary_options'].get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] fus_len = inputs[Aircraft.Fuselage.LENGTH] wingspan = inputs[Aircraft.Wing.SPAN] - if options.get_val(Aircraft.LandingGear.FIXED_GEAR, units='unitless'): - gear_type = 1 - else: - gear_type = 0 - landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * \ - GRAV_ENGLISH_LBM + landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * GRAV_ENGLISH_LBM control_wt = inputs[Aircraft.Controls.TOTAL_MASS] * GRAV_ENGLISH_LBM wing_area = inputs[Aircraft.Wing.AREA] htail_area = inputs[Aircraft.HorizontalTail.AREA] vtail_area = inputs[Aircraft.VerticalTail.AREA] - p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] - cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - Fn_SLS = inputs[Aircraft.Engine.SCALED_SLS_THRUST] - fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] subsystems_wt = inputs[Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS] + elec_mass_coeff = inputs[Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER] * GRAV_ENGLISH_LBM - engine_type = options.get_val(Aircraft.Engine.TYPE, units='unitless')[0] + engine_type = self.options[Aircraft.Engine.TYPE][0] - APU_wt = 0.0 if PAX > 35.0: APU_wt = 26.2 * PAX**0.944 - 13.6 * PAX - if ~( - -1e-5 < inputs[Aircraft.APU.MASS] < 1e-5 - ): # note: this technically creates a discontinuity + else: + APU_wt = 0.0 + # TODO The following if-block should be removed. Aircraft.APU.MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.APU.MASS] < 1e-5): + # note: this technically creates a discontinuity APU_wt = inputs[Aircraft.APU.MASS] * GRAV_ENGLISH_LBM - num_pilots = 1.0 - if PAX > 9.0: - num_pilots = 2.0 - if engine_type is GASPEngineType.TURBOJET and PAX > 5.0: - num_pilots = 2.0 - if PAX >= 251.0: - num_pilots = 3.0 + num_pilots = get_num_of_pilots(PAX, engine_type) instrument_wt = ( inputs[Aircraft.Instruments.MASS_COEFFICIENT] @@ -134,303 +144,124 @@ def compute(self, inputs, outputs): * fus_len**0.05 * wingspan**0.696 ) - gear_val = 1 - gear_type - hydraulic_wt = ( - inputs[Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT] * control_wt + - inputs[Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT] * - landing_gear_wt * gear_val + + hydraulic_wt = inputs[ + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT + ] * control_wt + inputs[Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT] * landing_gear_wt * ( + not self.options[Aircraft.LandingGear.FIXED_GEAR] ) - electrical_wt = 16.0 * PAX + 170.0 - if PAX <= 12.0: + if PAX <= 12: electrical_wt = 0.03217 * gross_wt_initial - 20.0 - if num_engines == 1.0: - electrical_wt = 0.00778 * gross_wt_initial + 33.0 + else: + if num_engines == 1: + electrical_wt = 0.00778 * gross_wt_initial + 33.0 + else: + electrical_wt = elec_mass_coeff * PAX + 170.0 avionics_wt = 27.0 - if smooth: - - avionics_wt = 35.538 * np.exp(0.0002 * gross_wt_initial) - - else: - if ( - gross_wt_initial >= 3000.0 - ): # note: this technically creates a discontinuity - avionics_wt = 65.0 - if ( - gross_wt_initial >= 5500.0 - ): # note: this technically creates a discontinuity - avionics_wt = 113.0 - if ( - gross_wt_initial >= 7500.0 - ): # note: this technically creates a discontinuity - avionics_wt = 163.0 - if ( - gross_wt_initial >= 11000.0 - ): # note: this technically creates a discontinuity - avionics_wt = 340.0 - - if PAX >= 20.0 and PAX < 30.0: + # GASP avionics weight model was put together long before modern systems + # came on-board, and should be updated. + if PAX < 20: + if smooth: + # Exponential regression from four points: + # (3000, 65), (5500, 113), (7500, 163), (11000, 340) + # avionics_wt = 36.2 * exp(0.0002024 * gross_wt_initial) + # Exponential regression from five points: + # (0, 27), (3000, 65), (5500, 113), (7500, 163), (11000, 340) + # avionics_wt = 30.03 * exp(0.0002262 * gross_wt_initial) + # Should we use use 4 sigmoid functions (one for each transition zone) instead? + avionics_wt = 35.538 * np.exp(0.0002 * gross_wt_initial) + else: + if gross_wt_initial >= 3000.0: # note: this technically creates a discontinuity + avionics_wt = 65.0 + if gross_wt_initial >= 5500.0: # note: this technically creates a discontinuity + avionics_wt = 113.0 + if gross_wt_initial >= 7500.0: # note: this technically creates a discontinuity + avionics_wt = 163.0 + if gross_wt_initial >= 11000.0: # note: this technically creates a discontinuity + avionics_wt = 340.0 + if PAX >= 20 and PAX < 30: avionics_wt = 400.0 - elif PAX >= 30.0 and PAX <= 50.0: + elif PAX >= 30 and PAX <= 50: avionics_wt = 500.0 - elif PAX > 50.0: + elif PAX > 50 and PAX <= 100: avionics_wt = 600.0 - if PAX > 100.0: + if PAX > 100: avionics_wt = 2.8 * PAX + 1010.0 - if ~( - -1e-5 < inputs[Aircraft.Avionics.MASS] < 1e-5 - ): # note: this technically creates a discontinuity !WILL NOT CHANGE + # TODO The following if-block should be removed. Aircraft.Avionics.MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.Avionics.MASS] < 1e-5): + # note: this technically creates a discontinuity !WILL NOT CHANGE avionics_wt = inputs[Aircraft.Avionics.MASS] * GRAV_ENGLISH_LBM - air_conditioning_wt = 5.0 - - if gross_wt_initial > 3500.0: # note: this technically creates a discontinuity - air_conditioning_wt = ( - inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] - * (1.5 + p_diff_fus) - * (0.358 * fus_len * cabin_width**2) ** 0.5 - ) - SSUM = wing_area + htail_area + vtail_area icing_wt = 22.7 * (SSUM**0.5) - 385.0 if smooth: + # This should be implemented: + # icing_wt = smooth_max(icing_wt, 0.0, mu) pass else: if icing_wt < 0.0: # note: this technically creates a discontinuity icing_wt = 0.0 - if ~( - -1e-5 < inputs[Aircraft.AntiIcing.MASS] < 1e-5 - ): # note: this technically creates a discontinuity !WILL NOT CHANGE + # TODO The following if-block should be removed. Aircraft.AntiIcing.MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.AntiIcing.MASS] < 1e-5): + # note: this technically creates a discontinuity !WILL NOT CHANGE icing_wt = inputs[Aircraft.AntiIcing.MASS] * GRAV_ENGLISH_LBM - aux_wt = 0.0 - - if smooth: - aux_wt = 3 * sig((gross_wt_initial - 3000) / 3000) - - else: - if ( - gross_wt_initial > 3000.0 - ): # note: this technically creates a discontinuity - aux_wt = 3.0 - - if PAX >= 9.0: + if PAX < 9: + if smooth: + aux_wt = 3 * sigmoidX(gross_wt_initial / 3000, 1.0, 0.01) + else: + if gross_wt_initial > 3000.0: # note: this technically creates a discontinuity + aux_wt = 3.0 + else: + aux_wt = 0.0 + elif PAX >= 9 and PAX < 20: aux_wt = 10.0 - if PAX > 19.0: + elif PAX >= 20 and PAX < 75: aux_wt = 20.0 - if PAX > 74.0: - aux_wt = 50.0 - - CPX = 28.0 + 10.516 * (cabin_width - 5.667) - - if smooth: - CPX = ( - 28 * sig((28 - CPX) / 28) - + CPX * sig((CPX - 28) / 28) * sig((62 - CPX) / 62) - + 62 * sig((CPX - 62) / 62) - ) - else: - if cabin_width <= 5.667: # note: this technically creates a discontinuity - CPX = 28.0 - if cabin_width > 8.90: # note: this technically creates a discontinuity - CPX = 62.0 - - furnishing_wt = CPX * PAX + 310.0 - if PAX > 80: - furnishing_wt = 118.4 * PAX - 4190.0 - if ( - gross_wt_initial <= 10000.0 - ): # note: this technically creates a discontinuity #TODO: Doesn't occur in large single aisle - furnishing_wt = 0.065 * gross_wt_initial - 59.0 + aux_wt = 50.0 - if smooth: - pass - else: - if furnishing_wt <= 30.0: # note: this technically creates a discontinuity - furnishing_wt = 30.0 - if ~( - -1e-5 < inputs[Aircraft.Furnishings.MASS] < 1e-5 - ): # note: this technically creates a discontinuity #WONT CHANGE - furnishing_wt = inputs[Aircraft.Furnishings.MASS] * GRAV_ENGLISH_LBM fixed_equip_wt = ( APU_wt + instrument_wt + hydraulic_wt + electrical_wt + avionics_wt - + air_conditioning_wt + icing_wt + aux_wt - + furnishing_wt + subsystems_wt ) - outputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] = fixed_equip_wt / \ - GRAV_ENGLISH_LBM - - num_flight_attendants = 0.0 - if PAX >= 20.0: - num_flight_attendants = 1.0 - if PAX >= 51.0: - num_flight_attendants = 2.0 - if PAX >= 101.0: - num_flight_attendants = 3.0 - if PAX >= 151.0: - num_flight_attendants = 4.0 - if PAX >= 201.0: - num_flight_attendants = 5.0 - if PAX >= 251.0: - num_flight_attendants = 6.0 - - # note: the average weight of a pilot was calulated using the following equation: - # avg_wt = pct_male*avg_wt_male + pct_female*avg_wt_female where - # pct_male = the percentage of US airline pilots that are male (based on data from - # the center for aviation in 2018, which listed this percentage as 95.6%, and slightly - # deflated to account for the upward trend in female pilots, resulting in an estimated - # percentage of 94%) - # avg_wt_male is the average weight of males according to the CDC, and is 199.8 lbf - # pct_female is calculated from the same methods as pct_male, and results in 6% - # avg_wt_female is the average weight of females according to the CDC, and is 170.8 lbf - # the resulting value is that the average weight of the US airline pilot is 198 lbf - pilot_wt = 198 * num_pilots - # note: the average weight of a flight attendant was calulated using the following equation: - # avg_wt = pct_male*avg_wt_male + pct_female*avg_wt_female where - # pct_male = the percentage of US flight attendants that are male (based on data from - # the women in aerospace international organization in 2020, which listed this percentage as - # 20.8%) - # avg_wt_male is the average weight of males according to the CDC, and is 199.8 lbf - # pct_female is calculated from the same methods as pct_male, and results in 79.2% - # avg_wt_female is the average weight of females according to the CDC, and is 170.8 lbf - # the resulting value is that the average weight of the US flight attendant is 177 lbf - flight_attendant_wt = 177 * num_flight_attendants - - crew_bag_wt = 25.0 * num_pilots - if PAX >= 20.0: - crew_bag_wt = 10.0 * (num_pilots + num_flight_attendants) + 25.0 - if PAX >= 40.0: - crew_bag_wt = ( - 20.0 * (num_flight_attendants + num_pilots) + 25.0 * num_pilots - ) - - if engine_type is GASPEngineType.TURBOJET: - oil_per_eng_wt = 0.0054 * Fn_SLS + 12.0 - elif engine_type is GASPEngineType.TURBOSHAFT or engine_type is GASPEngineType.TURBOPROP: - oil_per_eng_wt = 0.0124 * Fn_SLS + 14 - # else: - # oil_per_eng_wt = 0.062 * (Fn_SLS - 100) + 11 - else: - # Other engine types are currently not supported in Aviary - oil_per_eng_wt = 0 - - oil_wt = num_engines * oil_per_eng_wt - - lavatories = 0.0 - if PAX > 25.0: - lavatories = 1.0 - if PAX >= 51.0: - lavatories = 2.0 - if PAX >= 101.0: - lavatories = 3.0 - if PAX >= 151.0: - lavatories = 4.0 - if PAX >= 201.0: - lavatories = 5.0 - if PAX >= 251.0: - lavatories = 6.0 - - service_wt = 0.0 - if PAX > 9.0: - service_wt = inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER] * PAX * \ - GRAV_ENGLISH_LBM + 16.0 * lavatories - - water_wt = 0.0 - if PAX > 19.0: - water_wt = inputs[Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT] * \ - (PAX + num_pilots + num_flight_attendants) * GRAV_ENGLISH_LBM - - emergency_wt = 0.0 - if PAX > 5.0: - emergency_wt = 10.0 - if PAX > 9.0: - emergency_wt = 15.0 - if PAX >= 35.0: - emergency_wt = 25.0 * num_flight_attendants + 15.0 - if ~(-1e-5 < inputs[Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] < 1e-5): - emergency_wt = inputs[Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] * \ - GRAV_ENGLISH_LBM - - catering_wt = 0.0 - if PAX > 19.0: - catering_wt = inputs[Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER] * \ - PAX * GRAV_ENGLISH_LBM - - trapped_fuel_wt = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] * \ - (wing_area**0.5) * fuel_vol_frac / 0.430 - if ( - fuel_vol_frac <= 0.075 - ): # note: this technically creates a discontinuity # won't change - trapped_fuel_wt = inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] * \ - 0.18 * (wing_area**0.5) - - useful_wt = ( - pilot_wt - + flight_attendant_wt - + crew_bag_wt - + oil_wt - + service_wt - + water_wt - + emergency_wt - + catering_wt - + trapped_fuel_wt - ) - - outputs[Aircraft.Design.FIXED_USEFUL_LOAD] = useful_wt / \ - GRAV_ENGLISH_LBM + outputs['equip_mass_part'] = fixed_equip_wt / GRAV_ENGLISH_LBM def compute_partials(self, inputs, partials): - options = self.options['aviary_options'] - PAX = options.get_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, units='unitless') - smooth = options.get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - num_engines = self.options['aviary_options'].get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] fus_len = inputs[Aircraft.Fuselage.LENGTH] wingspan = inputs[Aircraft.Wing.SPAN] - if options.get_val(Aircraft.LandingGear.FIXED_GEAR, units='unitless'): - gear_type = 1 - else: - gear_type = 0 - landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * \ - GRAV_ENGLISH_LBM + + landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * GRAV_ENGLISH_LBM control_wt = inputs[Aircraft.Controls.TOTAL_MASS] * GRAV_ENGLISH_LBM wing_area = inputs[Aircraft.Wing.AREA] htail_area = inputs[Aircraft.HorizontalTail.AREA] vtail_area = inputs[Aircraft.VerticalTail.AREA] - p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] - cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] - fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] - engine_type = options.get_val(Aircraft.Engine.TYPE, units='unitless')[0] + engine_type = self.options[Aircraft.Engine.TYPE][0] dAPU_wt_dmass_coeff_0 = 0.0 - if ~( - -1e-5 < inputs[Aircraft.APU.MASS] < 1e-5 - ): # note: this technically creates a discontinuity + # TODO The following if-block should be removed. Aircraft.APU.MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.APU.MASS] < 1e-5): + # note: this technically creates a discontinuity dAPU_wt_dmass_coeff_0 = GRAV_ENGLISH_LBM - num_pilots = 1.0 - if PAX > 9.0: - num_pilots = 2.0 - if engine_type is GASPEngineType.TURBOJET and PAX > 5.0: - num_pilots = 2.0 - if PAX >= 251.0: - num_pilots = 3.0 + num_pilots = get_num_of_pilots(PAX, engine_type) dinstrument_wt_dmass_coeff_1 = ( gross_wt_initial**0.386 @@ -467,90 +298,41 @@ def compute_partials(self, inputs, partials): * wingspan ** (0.696 - 1) ) - gear_val = 1 - gear_type + gear_val = not self.options[Aircraft.LandingGear.FIXED_GEAR] dhydraulic_wt_dmass_coeff_2 = control_wt dhydraulic_wt_dcontrol_wt = inputs[Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT] dhydraulic_wt_dmass_coeff_3 = landing_gear_wt * gear_val - dhydraulic_wt_dlanding_gear_weight = inputs[Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT] * gear_val + dhydraulic_wt_dlanding_gear_weight = ( + inputs[Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT] * gear_val + ) - delectrical_wt_dgross_wt_initial = 0.0 if PAX <= 12.0: delectrical_wt_dgross_wt_initial = 0.03217 - if num_engines == 1.0: - delectrical_wt_dgross_wt_initial = 0.0078 + delectrical_wt_delec_mass_coeff = 0.0 + else: + if num_engines == 1: + delectrical_wt_dgross_wt_initial = 0.0078 + delectrical_wt_delec_mass_coeff = 0.0 + else: + delectrical_wt_dgross_wt_initial = 0.0 + delectrical_wt_delec_mass_coeff = PAX * GRAV_ENGLISH_LBM davionics_wt_dmass_coeff_4 = 0.0 - if smooth: - - davionics_wt_dgross_wt_initial = 0.0071076 * np.exp( - 0.0002 * gross_wt_initial - ) - - else: - if ( - gross_wt_initial >= 3000.0 - ): # note: this technically creates a discontinuity + if PAX < 20: + if smooth: + davionics_wt_dgross_wt_initial = 0.0071076 * np.exp(0.0002 * gross_wt_initial) + else: davionics_wt_dgross_wt_initial = 0.0 - if ( - gross_wt_initial >= 5500.0 - ): # note: this technically creates a discontinuity - davionics_wt_dgross_wt_initial = 0.0 - if ( - gross_wt_initial >= 7500.0 - ): # note: this technically creates a discontinuity - davionics_wt_dgross_wt_initial = 0.0 - if ( - gross_wt_initial >= 11000.0 - ): # note: this technically creates a discontinuity - davionics_wt_dgross_wt_initial = 0.0 - - if PAX >= 20.0 and PAX < 30.0: - davionics_wt_dgross_wt_initial = 0.0 - elif PAX >= 30.0 and PAX <= 50.0: - davionics_wt_dgross_wt_initial = 0.0 - elif PAX > 50.0: - davionics_wt_dgross_wt_initial = 0.0 - if PAX > 100.0: + else: davionics_wt_dgross_wt_initial = 0.0 - if ~( - -1e-5 < inputs[Aircraft.Avionics.MASS] < 1e-5 - ): # note: this technically creates a discontinuity !WILL NOT CHANGE + # TODO The following if-block should be removed. Aircraft.Avionics.MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.Avionics.MASS] < 1e-5): + # note: this technically creates a discontinuity !WILL NOT CHANGE davionics_wt_dgross_wt_initial = 0.0 davionics_wt_dmass_coeff_4 = GRAV_ENGLISH_LBM - dair_conditioning_wt_dmass_coeff_5 = 0.0 - dair_conditioning_wt_dp_diff_fus = 0.0 - dair_conditioning_wt_dfus_len = 0.0 - dair_conditioning_wt_dcabin_width = 0.0 - if gross_wt_initial > 3500.0: # note: this technically creates a discontinuity - dair_conditioning_wt_dmass_coeff_5 = (1.5 + p_diff_fus) * ( - 0.358 * fus_len * cabin_width**2 - ) ** 0.5 - dair_conditioning_wt_dp_diff_fus = ( - inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] * - (0.358 * fus_len * cabin_width**2) ** 0.5 - ) - dair_conditioning_wt_dfus_len = ( - 0.5 - * inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] - * (1.5 + p_diff_fus) - * (0.358 * fus_len * cabin_width**2) ** -0.5 - * 0.358 - * cabin_width**2 - ) - dair_conditioning_wt_dcabin_width = ( - 0.5 - * inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] - * (1.5 + p_diff_fus) - * (0.358 * fus_len * cabin_width**2) ** -0.5 - * 2 - * 0.358 - * fus_len - * cabin_width - ) - SSUM = wing_area + htail_area + vtail_area icing_wt = 22.7 * (SSUM**0.5) - 385.0 @@ -560,6 +342,7 @@ def compute_partials(self, inputs, partials): dicing_weight_dmass_coeff_6 = 0.0 if smooth: + # The partials of smooth_max should be implemented here. pass else: if icing_wt < 0.0: # note: this technically creates a discontinuity @@ -568,117 +351,37 @@ def compute_partials(self, inputs, partials): dicing_weight_dhtail_area = 0.0 dicing_weight_dvtail_area = 0.0 dicing_weight_dmass_coeff_6 = 0.0 - if ~( - -1e-5 < inputs[Aircraft.AntiIcing.MASS] < 1e-5 - ): # note: this technically creates a discontinuity !WILL NOT CHANGE + # TODO The following if-block should be removed. Aircraft.AntiIcing.MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.AntiIcing.MASS] < 1e-5): + # note: this technically creates a discontinuity !WILL NOT CHANGE icing_wt = inputs[Aircraft.AntiIcing.MASS] * GRAV_ENGLISH_LBM dicing_weight_dwing_area = 0.0 dicing_weight_dhtail_area = 0.0 dicing_weight_dvtail_area = 0.0 dicing_weight_dmass_coeff_6 = GRAV_ENGLISH_LBM - if smooth: - d_aux_wt_dgross_wt_initial = ( - 3 * dsig((gross_wt_initial - 3000) / 3000) * 1 / 3000 - ) - else: - if ( - gross_wt_initial > 3000.0 - ): # note: this technically creates a discontinuity - d_aux_wt_dgross_wt_initial = 0.0 - - if PAX >= 9.0: - d_aux_wt_dgross_wt_initial = 0.0 - if PAX > 19.0: - d_aux_wt_dgross_wt_initial = 0.0 - if PAX > 74.0: - d_aux_wt_dgross_wt_initial = 0.0 - - CPX = 28.0 + 10.516 * (cabin_width - 5.667) - dCPX_dcabin_width = 10.516 - - if smooth: - CPX_1 = ( - 28 * sig((28 - CPX) / 28) - + CPX * sig((CPX - 28) / 28) * sig((62 - CPX) / 62) - + 62 * sig((CPX - 62) / 62) - ) - - dCPX_dcabin_width = ( - 28 * dsig((28 - CPX) / 28) * -dCPX_dcabin_width - + ( - dCPX_dcabin_width * sig((CPX - 28) / 28) - + CPX * dsig((CPX - 28) / 28) * dCPX_dcabin_width + if PAX < 9: + if smooth: + d_aux_wt_dgross_wt_initial = ( + 3 * dSigmoidXdx(gross_wt_initial / 3000, 1, 0.01) * 1 / 3000 ) - * sig((62 - CPX) / 62) - + CPX - * sig((CPX - 28) / 28) - * dsig((62 - CPX) / 62) - * -dCPX_dcabin_width - + 62 * dsig((CPX - 62) / 62) * dCPX_dcabin_width - ) - - CPX = CPX_1 - dfurnishing_wt_dgross_wt_initial = 0.0 - dfurnishing_wt_dgross_wt_initial = 0.0 - dfurnishing_wt_dmass_coeff_7 = 0.0 - else: - if cabin_width <= 5.667: # note: this technically creates a discontinuity - CPX = 28.0 - dCPX_dcabin_width = 0.0 - dfurnishing_wt_dgross_wt_initial = 0.0 - dfurnishing_wt_dmass_coeff_7 = 0.0 - if cabin_width > 8.90: # note: this technically creates a discontinuity - CPX = 62.0 - dCPX_dcabin_width = 0.0 - dfurnishing_wt_dgross_wt_initial = 0.0 - dfurnishing_wt_dmass_coeff_7 = 0.0 - - furnishing_wt = CPX * PAX + 310.0 - dfurnishing_wt_dgross_wt_initial = 0.0 - dfurnishing_wt_dmass_coeff_7 = 0.0 - dfurnishing_wt_dcabin_width = PAX * dCPX_dcabin_width - if PAX > 80: - furnishing_wt = 118.4 * PAX - 4190.0 - dfurnishing_wt_dgross_wt_initial = 0.0 - dfurnishing_wt_dcabin_width = 0.0 - dfurnishing_wt_dmass_coeff_7 = 0.0 - if ( - gross_wt_initial <= 10000.0 - ): # note: this technically creates a discontinuity #TODO: Doesn't occur in large single aisle - furnishing_wt = 0.065 * gross_wt_initial - 59.0 - dfurnishing_wt_dgross_wt_initial = 0.065 - dfurnishing_wt_dcabin_width = 0.0 - dfurnishing_wt_dmass_coeff_7 = 0.0 - - if smooth: - pass + else: + if gross_wt_initial > 3000.0: # note: this technically creates a discontinuity + d_aux_wt_dgross_wt_initial = 0.0 else: - if furnishing_wt <= 30.0: # note: this technically creates a discontinuity - furnishing_wt = 30.0 - dfurnishing_wt_dgross_wt_initial = 0.0 - dfurnishing_wt_dcabin_width = 0.0 - dfurnishing_wt_dmass_coeff_7 = 0.0 - if ~( - -1e-5 < inputs[Aircraft.Furnishings.MASS] < 1e-5 - ): # note: this technically creates a discontinuity #WONT CHANGE - furnishing_wt = inputs[Aircraft.Furnishings.MASS] * GRAV_ENGLISH_LBM - dfurnishing_wt_dmass_coeff_7 = GRAV_ENGLISH_LBM - dfurnishing_wt_dcabin_width = 0.0 - dfurnishing_wt_dgross_wt_initial = 0.0 + d_aux_wt_dgross_wt_initial = 0.0 dfixed_equip_mass_dmass_coeff_0 = dAPU_wt_dmass_coeff_0 / GRAV_ENGLISH_LBM dfixed_equip_mass_dmass_coeff_1 = dinstrument_wt_dmass_coeff_1 / GRAV_ENGLISH_LBM dfixed_equip_wt_dgross_wt_initial = ( dinstrument_wt_dgross_wt_initial + delectrical_wt_dgross_wt_initial - + dfurnishing_wt_dgross_wt_initial + davionics_wt_dgross_wt_initial + d_aux_wt_dgross_wt_initial - + dfurnishing_wt_dcabin_width ) + dfixed_equip_wt_delec_mass_coeff = delectrical_wt_delec_mass_coeff / GRAV_ENGLISH_LBM dfixed_equip_mass_dfus_len = ( - dinstrument_wt_dfus_len + dair_conditioning_wt_dfus_len + dinstrument_wt_dfus_len # + dair_conditioning_wt_dfus_len ) / GRAV_ENGLISH_LBM dfixed_equip_mass_dwingspan = dinstrument_wt_dwingspan / GRAV_ENGLISH_LBM dfixed_equip_mass_dmass_coeff_2 = dhydraulic_wt_dmass_coeff_2 / GRAV_ENGLISH_LBM @@ -687,147 +390,1075 @@ def compute_partials(self, inputs, partials): dfixed_equip_wt_dlanding_gear_weight = dhydraulic_wt_dlanding_gear_weight dfixed_equip_mass_dmass_coeff_4 = davionics_wt_dmass_coeff_4 / GRAV_ENGLISH_LBM - dfixed_equip_mass_dmass_coeff_5 = dair_conditioning_wt_dmass_coeff_5 / GRAV_ENGLISH_LBM - dfixed_equip_mass_dp_diff_fus = dair_conditioning_wt_dp_diff_fus / GRAV_ENGLISH_LBM - dfixed_equip_mass_dcabin_width = dair_conditioning_wt_dcabin_width / GRAV_ENGLISH_LBM - dfixed_equip_mass_dwing_area = dicing_weight_dwing_area / GRAV_ENGLISH_LBM - dfixed_equip_mass_dhtail_area = dicing_weight_dhtail_area / \ - GRAV_ENGLISH_LBM - dfixed_equip_mass_dvtail_area = dicing_weight_dvtail_area / \ - GRAV_ENGLISH_LBM + dfixed_equip_mass_dhtail_area = dicing_weight_dhtail_area / GRAV_ENGLISH_LBM + dfixed_equip_mass_dvtail_area = dicing_weight_dvtail_area / GRAV_ENGLISH_LBM dfixed_equip_mass_dmass_coeff_6 = dicing_weight_dmass_coeff_6 / GRAV_ENGLISH_LBM - dfixed_equip_mass_dmass_coeff_7 = dfurnishing_wt_dmass_coeff_7 / GRAV_ENGLISH_LBM - - num_flight_attendants = 0.0 - if PAX >= 20.0: - num_flight_attendants = 1.0 - if PAX >= 51.0: - num_flight_attendants = 2.0 - if PAX >= 101.0: - num_flight_attendants = 3.0 - if PAX >= 151.0: - num_flight_attendants = 4.0 - if PAX >= 201.0: - num_flight_attendants = 5.0 - if PAX >= 251.0: - num_flight_attendants = 6.0 - - if engine_type is GASPEngineType.TURBOJET: - doil_per_eng_wt_dFn_SLS = 0.0054 - elif engine_type is GASPEngineType.TURBOSHAFT or engine_type is GASPEngineType.TURBOPROP: - doil_per_eng_wt_dFn_SLS = 0.0124 - # else: - # doil_per_eng_wt_dFn_SLS = 0.062 - else: - # Other engine types are currently not supported in Aviary - doil_per_eng_wt_dFn_SLS = 0.0 - dservice_wt_dmass_coeff_8 = 0.0 - if PAX > 9.0: - dservice_wt_dmass_coeff_8 = PAX * GRAV_ENGLISH_LBM + partials['equip_mass_part', Aircraft.APU.MASS] = dfixed_equip_mass_dmass_coeff_0 + partials['equip_mass_part', Aircraft.Instruments.MASS_COEFFICIENT] = ( + dfixed_equip_mass_dmass_coeff_1 + ) + partials[ + 'equip_mass_part', + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, + ] = dfixed_equip_mass_dmass_coeff_2 + partials['equip_mass_part', Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT] = ( + dfixed_equip_mass_dmass_coeff_3 + ) + partials['equip_mass_part', Aircraft.Avionics.MASS] = dfixed_equip_mass_dmass_coeff_4 + partials['equip_mass_part', Aircraft.AntiIcing.MASS] = dfixed_equip_mass_dmass_coeff_6 + partials['equip_mass_part', Mission.Design.GROSS_MASS] = dfixed_equip_wt_dgross_wt_initial + partials['equip_mass_part', Aircraft.Fuselage.LENGTH] = dfixed_equip_mass_dfus_len + partials['equip_mass_part', Aircraft.Wing.SPAN] = dfixed_equip_mass_dwingspan + partials['equip_mass_part', Aircraft.Controls.TOTAL_MASS] = dfixed_equip_wt_dcontrol_wt + partials['equip_mass_part', Aircraft.LandingGear.TOTAL_MASS] = ( + dfixed_equip_wt_dlanding_gear_weight + ) - dwater_wt_dmass_coeff_9 = 0.0 - if PAX > 19.0: - dwater_wt_dmass_coeff_9 = ( - PAX + num_pilots + num_flight_attendants) * GRAV_ENGLISH_LBM + partials['equip_mass_part', Aircraft.Wing.AREA] = dfixed_equip_mass_dwing_area + partials['equip_mass_part', Aircraft.HorizontalTail.AREA] = dfixed_equip_mass_dhtail_area + partials['equip_mass_part', Aircraft.VerticalTail.AREA] = dfixed_equip_mass_dvtail_area + partials['equip_mass_part', Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER] = ( + dfixed_equip_wt_delec_mass_coeff + ) - demergency_wt_dmass_coeff_10 = 0.0 - if ~(-1e-5 < inputs[Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] < 1e-5): - demergency_wt_dmass_coeff_10 = GRAV_ENGLISH_LBM - dcatering_wt_dmass_coeff_11 = 0.0 - if PAX > 19.0: - dcatering_wt_dmass_coeff_11 = PAX * GRAV_ENGLISH_LBM +class ACMass(om.ExplicitComponent): + """ + Computation of air conditioning mass. + """ - dtrapped_fuel_wt_dmass_coeff_12 = (wing_area**0.5) * fuel_vol_frac / 0.430 - dtrapped_fuel_wt_dwing_area = ( - 0.5 * inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] * - (wing_area**-0.5) * fuel_vol_frac / 0.430 - ) - dtrapped_fuel_wt_dfuel_vol_frac = ( - inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] * - (wing_area**0.5) / 0.430 + def setup(self): + add_aviary_input(self, Aircraft.AirConditioning.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, units='psi') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + + self.add_output(Aircraft.AirConditioning.MASS, units='lbm') + + self.declare_partials( + Aircraft.AirConditioning.MASS, + [ + Aircraft.AirConditioning.MASS_COEFFICIENT, + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, + Mission.Design.GROSS_MASS, + ], ) - if ( - fuel_vol_frac <= 0.075 - ): # note: this technically creates a discontinuity # won't change - dtrapped_fuel_wt_dmass_coeff_12 = 0.18 * (wing_area**0.5) - dtrapped_fuel_wt_dwing_area = ( - 0.5 * inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] * - 0.18 * (wing_area**-0.5) + def compute(self, inputs, outputs): + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + ac_coeff = inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] + + # note: this technically creates a discontinuity but we will not smooth it. + if gross_wt_initial > 3500.0: + air_conditioning_wt = ( + ac_coeff * (1.5 + p_diff_fus) * (0.358 * fus_len * cabin_width**2) ** 0.5 ) - dtrapped_fuel_wt_dfuel_vol_frac = 0.0 + else: + air_conditioning_wt = 5.0 - doil_wt_dFnSLS = num_engines * doil_per_eng_wt_dFn_SLS + outputs[Aircraft.AirConditioning.MASS] = air_conditioning_wt / GRAV_ENGLISH_LBM - duseful_mass_dFn_SLS = doil_wt_dFnSLS / GRAV_ENGLISH_LBM - duseful_mass_dmass_coeff_8 = dservice_wt_dmass_coeff_8 / GRAV_ENGLISH_LBM - duseful_mass_dmass_coeff_9 = dwater_wt_dmass_coeff_9 / GRAV_ENGLISH_LBM - duseful_mass_dmass_coeff_10 = demergency_wt_dmass_coeff_10 / GRAV_ENGLISH_LBM - duseful_mass_dmass_coeff_11 = dcatering_wt_dmass_coeff_11 / GRAV_ENGLISH_LBM - duseful_mass_dmass_coeff_12 = dtrapped_fuel_wt_dmass_coeff_12 / GRAV_ENGLISH_LBM - duseful_mass_dwing_area = dtrapped_fuel_wt_dwing_area / GRAV_ENGLISH_LBM - duseful_mass_dfuel_vol_frac = dtrapped_fuel_wt_dfuel_vol_frac / GRAV_ENGLISH_LBM - partials[Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.Engine.SCALED_SLS_THRUST] = duseful_mass_dFn_SLS - partials[Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER] = duseful_mass_dmass_coeff_8 - partials[Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT] = duseful_mass_dmass_coeff_9 - partials[Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] = duseful_mass_dmass_coeff_10 - partials[Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER] = duseful_mass_dmass_coeff_11 - partials[Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] = duseful_mass_dmass_coeff_12 - - partials[Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.Wing.AREA] = duseful_mass_dwing_area - partials[ - Aircraft.Design.FIXED_USEFUL_LOAD, Aircraft.Fuel.WING_FUEL_FRACTION - ] = duseful_mass_dfuel_vol_frac - - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.APU.MASS] = dfixed_equip_mass_dmass_coeff_0 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Instruments.MASS_COEFFICIENT] = dfixed_equip_mass_dmass_coeff_1 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT] = dfixed_equip_mass_dmass_coeff_2 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT] = dfixed_equip_mass_dmass_coeff_3 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Avionics.MASS] = dfixed_equip_mass_dmass_coeff_4 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.AirConditioning.MASS_COEFFICIENT] = dfixed_equip_mass_dmass_coeff_5 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.AntiIcing.MASS] = dfixed_equip_mass_dmass_coeff_6 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Furnishings.MASS] = dfixed_equip_mass_dmass_coeff_7 - partials[ - Aircraft.Design.FIXED_EQUIPMENT_MASS, Mission.Design.GROSS_MASS - ] = dfixed_equip_wt_dgross_wt_initial - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Fuselage.LENGTH] = dfixed_equip_mass_dfus_len - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Wing.SPAN] = dfixed_equip_mass_dwingspan - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Controls.TOTAL_MASS] = dfixed_equip_wt_dcontrol_wt - partials[ - Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.LandingGear.TOTAL_MASS - ] = dfixed_equip_wt_dlanding_gear_weight + def compute_partials(self, inputs, J): + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + ac_coeff = inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] = dfixed_equip_mass_dp_diff_fus - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Fuselage.AVG_DIAMETER] = dfixed_equip_mass_dcabin_width + dac_wt_dgross_wt = 0.0 - partials[Aircraft.Design.FIXED_EQUIPMENT_MASS, - Aircraft.Wing.AREA] = dfixed_equip_mass_dwing_area - partials[ - Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.HorizontalTail.AREA - ] = dfixed_equip_mass_dhtail_area - partials[ - Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.VerticalTail.AREA - ] = dfixed_equip_mass_dvtail_area + if gross_wt_initial > 3500.0: + dac_wt_dfus_len = ( + 0.5 + * ac_coeff + * (1.5 + p_diff_fus) + * 0.358 + * cabin_width**2 + * (0.358 * fus_len * cabin_width**2) ** -0.5 + ) + dac_wt_dp_diff_fus = ac_coeff * (0.358 * fus_len * cabin_width**2) ** 0.5 + dac_wt_dcabin_width = ( + ac_coeff + * (1.5 + p_diff_fus) + * 0.358 + * fus_len + * cabin_width + * (0.358 * fus_len * cabin_width**2) ** -0.5 + ) + dac_wt_dac_coeff = (1.5 + p_diff_fus) * (0.358 * fus_len * cabin_width**2) ** 0.5 + else: + dac_wt_dfus_len = 0.0 + dac_wt_dp_diff_fus = 0.0 + dac_wt_dcabin_width = 0.0 + dac_wt_dac_coeff = 0.0 + + J[Aircraft.AirConditioning.MASS, Mission.Design.GROSS_MASS] = dac_wt_dgross_wt + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.LENGTH] = ( + dac_wt_dfus_len / GRAV_ENGLISH_LBM + ) + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] = ( + dac_wt_dp_diff_fus / GRAV_ENGLISH_LBM + ) + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.AVG_DIAMETER] = ( + dac_wt_dcabin_width / GRAV_ENGLISH_LBM + ) + J[Aircraft.AirConditioning.MASS, Aircraft.AirConditioning.MASS_COEFFICIENT] = ( + dac_wt_dac_coeff / GRAV_ENGLISH_LBM + ) + + +class FurnishingMass(om.ExplicitComponent): + """ + Computation of furnishing mass. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Aircraft.Engine.TYPE) + add_aviary_option(self, Aircraft.Furnishings.USE_EMPIRICAL_EQUATION) + self.options.declare('mu', default=1.0, types=float) + + def setup(self): + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2') + + self.add_output(Aircraft.Furnishings.MASS, units='lbm') + + self.declare_partials( + Aircraft.Furnishings.MASS, + [ + Aircraft.Fuselage.AVG_DIAMETER, + Mission.Design.GROSS_MASS, + Aircraft.Furnishings.MASS_SCALER, + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.CABIN_AREA, + ], + ) + + def compute(self, inputs, outputs): + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + empirical = self.options[Aircraft.Furnishings.USE_EMPIRICAL_EQUATION] + engine_type = self.options[Aircraft.Engine.TYPE][0] + mu = self.options['mu'] + + num_pilots = get_num_of_pilots(PAX, engine_type) + num_flight_attendants = get_num_of_flight_attendent(PAX) + lavatories = get_num_of_lavatories(PAX) + + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + scaler = inputs[Aircraft.Furnishings.MASS_SCALER] + acabin = inputs[Aircraft.Fuselage.CABIN_AREA] + + if gross_wt_initial <= 10000.0: + # note: this technically creates a discontinuity + # TODO: Doesn't occur in large single aisle + furnishing_wt = 0.065 * gross_wt_initial - 59.0 + else: + if PAX >= 50: + if empirical: + # commonly used empirical furnishing weight equation + furnishing_wt_additional = scaler * PAX + else: + # linear regression formula + furnishing_wt_additional = 118.4 * PAX - 4190.0 + # baseline furnishings (crew seats, cockpit, lavatories, galleys) + cabin_len = 0.75 * fus_len + agalley = 0.50 * PAX + furnishing_wt = ( + furnishing_wt_additional + + num_pilots * (1.0 + cabin_width / 12.0) * 90.0 + + num_flight_attendants * 30.0 + + lavatories * 240.0 + + agalley * 12.0 + + 1.5 * cabin_len * cabin_width * np.pi / 2.0 + + 0.5 * acabin + ) + else: + CPX_lin = 28.0 + 10.516 * (cabin_width - 5.667) + if smooth: + CPX = ( + 28 * sigmoidX(CPX_lin / 28, 1, -0.01) + + CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * sigmoidX(CPX_lin / 62, 1, -0.01) + + 62 * sigmoidX(CPX_lin / 62, 1, 0.01) + ) + else: + if cabin_width <= 5.667: # note: this technically creates a discontinuity + CPX = 28.0 + elif cabin_width > 8.90: # note: this technically creates a discontinuity + CPX = 62.0 + furnishing_wt = CPX * PAX + 310.0 + # Theoretically, we should make sure that furnishing_wt >= 0 here + + if smooth: + furnishing_wt = smooth_max(furnishing_wt, 30.0, mu) + else: + furnishing_wt = np.maximum(furnishing_wt, 30.0) + + outputs[Aircraft.Furnishings.MASS] = furnishing_wt / GRAV_ENGLISH_LBM + + def compute_partials(self, inputs, partials): + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + empirical = self.options[Aircraft.Furnishings.USE_EMPIRICAL_EQUATION] + engine_type = self.options[Aircraft.Engine.TYPE][0] + mu = self.options['mu'] + + num_pilots = get_num_of_pilots(PAX, engine_type) + num_flight_attendants = get_num_of_flight_attendent(PAX) + lavatories = get_num_of_lavatories(PAX) + + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + scaler = inputs[Aircraft.Furnishings.MASS_SCALER] + acabin = inputs[Aircraft.Fuselage.CABIN_AREA] + + if gross_wt_initial <= 10000.0: + furnishing_wt = 0.065 * gross_wt_initial - 59.0 + dfurnishing_wt_dgross_wt_initial = 0.065 + dfurnishing_wt_dcabin_width = 0.0 + dfurnishing_wt_dfus_len = 0.0 + dfurnishing_wt_dscaler = 0.0 + dfurnishing_wt_dacabin = 0.0 + else: + if PAX >= 50: + if empirical: + furnishing_wt_additional = scaler * PAX + dfurnishing_wt_additional_dgross_wt_initial = 0.0 + dfurnishing_wt_additional_dcabin_width = 0.0 + dfurnishing_wt_additional_dfus_len = 0.0 + dfurnishing_wt_additional_dscaler = PAX + dfurnishing_wt_additional_dacabin = 0.0 + else: + furnishing_wt_additional = 118.4 * PAX - 4190.0 + dfurnishing_wt_additional_dgross_wt_initial = 0.0 + dfurnishing_wt_additional_dcabin_width = 0.0 + dfurnishing_wt_additional_dfus_len = 0.0 + dfurnishing_wt_additional_dscaler = 0.0 + dfurnishing_wt_additional_dacabin = 0.0 + cabin_len = 0.75 * fus_len + agalley = 0.50 * PAX + furnishing_wt = ( + furnishing_wt_additional + + num_pilots * (1.0 + cabin_width / 12.0) * 90.0 + + num_flight_attendants * 30.0 + + lavatories * 240.0 + + agalley * 12.0 + + 1.5 * cabin_len * cabin_width * np.pi / 2.0 + + 0.5 * acabin + ) + dfurnishing_wt_dgross_wt_initial = dfurnishing_wt_additional_dgross_wt_initial + 0.0 + dfurnishing_wt_dcabin_width = ( + dfurnishing_wt_additional_dcabin_width + + num_pilots * (1.0 / 12.0) * 90.0 + + 1.5 * 0.75 * fus_len * np.pi / 2.0 + ) + dfurnishing_wt_dfus_len = ( + dfurnishing_wt_additional_dfus_len + 1.5 * 0.75 * cabin_width * np.pi / 2.0 + ) + dfurnishing_wt_dscaler = dfurnishing_wt_additional_dscaler + 0.0 + dfurnishing_wt_dacabin = dfurnishing_wt_additional_dacabin + 0.5 + else: + CPX_lin = 28.0 + 10.516 * (cabin_width - 5.667) + if smooth: + CPX = ( + 28 * sigmoidX(CPX_lin / 28, 1, -0.01) + + CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * sigmoidX(CPX_lin / 62, 1, -0.01) + + 62 * sigmoidX(CPX_lin / 62, 1, 0.01) + ) + else: + if cabin_width <= 5.667: # note: this technically creates a discontinuity + CPX = 28.0 + elif cabin_width > 8.90: # note: this technically creates a discontinuity + CPX = 62.0 + furnishing_wt = CPX * PAX + 310.0 + + dCPX_lin_dcabin_width = 10.516 + if smooth: + dCPX_dcabin_width = ( + 1 * dSigmoidXdx(CPX_lin / 28, 1, 0.01) * -dCPX_lin_dcabin_width + + dCPX_lin_dcabin_width + * CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * sigmoidX(CPX_lin / 62, 1, -0.01) + + CPX_lin + * dSigmoidXdx(CPX_lin / 28, 1, 0.01) + / 28 + * sigmoidX(CPX_lin / 62, 1, -0.01) + * dCPX_lin_dcabin_width + + CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * dSigmoidXdx(CPX_lin / 62, 1, -0.01) + / 62 + * -dCPX_lin_dcabin_width + + 1 * dSigmoidXdx(CPX_lin / 62, 1, 0.01) * dCPX_lin_dcabin_width + ) + else: + if cabin_width <= 5.667: # note: this technically creates a discontinuity + dCPX_dcabin_width = 0.0 + if cabin_width > 8.90: # note: this technically creates a discontinuity + dCPX_dcabin_width = 0.0 + + dfurnishing_wt_dcabin_width = PAX * dCPX_dcabin_width + dfurnishing_wt_dgross_wt_initial = 0.0 + dfurnishing_wt_dfus_len = 0.0 + dfurnishing_wt_dscaler = 0.0 + dfurnishing_wt_dacabin = 0.0 + + if smooth: + sm_fac = d_smooth_max(furnishing_wt, 30.0, mu) + dfurnishing_wt_dcabin_width = sm_fac * dfurnishing_wt_dcabin_width + dfurnishing_wt_dgross_wt_initial = sm_fac * dfurnishing_wt_dgross_wt_initial + dfurnishing_wt_dfus_len = sm_fac * dfurnishing_wt_dfus_len + dfurnishing_wt_dscaler = sm_fac * dfurnishing_wt_dscaler + dfurnishing_wt_dacabin = sm_fac * dfurnishing_wt_dacabin + else: + if furnishing_wt < 30.0: # note: this technically creates a discontinuity + dfurnishing_wt_dcabin_width = 0.0 + dfurnishing_wt_dgross_wt_initial = 0.0 + dfurnishing_wt_dfus_len = 0.0 + dfurnishing_wt_dscaler = 0.0 + dfurnishing_wt_dacabin = 0.0 + + partials[Aircraft.Furnishings.MASS, Mission.Design.GROSS_MASS] = ( + dfurnishing_wt_dgross_wt_initial + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Fuselage.AVG_DIAMETER] = ( + dfurnishing_wt_dcabin_width / GRAV_ENGLISH_LBM + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Fuselage.LENGTH] = ( + dfurnishing_wt_dfus_len / GRAV_ENGLISH_LBM + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Furnishings.MASS_SCALER] = ( + dfurnishing_wt_dscaler / GRAV_ENGLISH_LBM + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Fuselage.CABIN_AREA] = ( + dfurnishing_wt_dacabin / GRAV_ENGLISH_LBM + ) + + +class EquipMassSum(om.ExplicitComponent): + def setup(self): + self.add_input('equip_mass_part', units='lbm') + add_aviary_input(self, Aircraft.AirConditioning.MASS, units='lbm') + self.add_input(Aircraft.Furnishings.MASS, units='lbm') + + add_aviary_output(self, Aircraft.Design.FIXED_EQUIPMENT_MASS, units='lbm') + + self.declare_partials( + Aircraft.Design.FIXED_EQUIPMENT_MASS, + [ + 'equip_mass_part', + Aircraft.AirConditioning.MASS, + Aircraft.Furnishings.MASS, + ], + ) + + def compute(self, inputs, outputs): + equip_mass_part = inputs['equip_mass_part'] + air_conditioning_mass = inputs[Aircraft.AirConditioning.MASS] + furnishing_mass = inputs[Aircraft.Furnishings.MASS] + + equip_mass_sum = equip_mass_part + air_conditioning_mass + furnishing_mass + outputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] = equip_mass_sum + + def compute_partials(self, inputs, J): + J[Aircraft.Design.FIXED_EQUIPMENT_MASS, 'equip_mass_part'] = 1 + J[Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.AirConditioning.MASS] = 1 + J[Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.Furnishings.MASS] = 1 + + +class EquipMassGroup(om.Group): + def setup(self): + self.add_subsystem( + 'equip_partial', + EquipMassPartialSum(), + promotes_inputs=['*'], + promotes_outputs=['equip_mass_part'], + ) + self.add_subsystem( + 'ac', + ACMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'furnishing', + FurnishingMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'equip_sum', + EquipMassSum(), + promotes_inputs=['*'] + ['equip_mass_part'], + promotes_outputs=['*'], + ) + + +class UsefulLoadMass(om.ExplicitComponent): + """ + Computation of fixed equipment mass and useful load for GASP-based mass. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Engine.TYPE) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) + add_aviary_option(self, Settings.VERBOSITY) + add_aviary_option(self, Aircraft.CrewPayload.ULD_MASS_PER_PASSENGER, units='lbm') + + def setup(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input(self, Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, units='lbm') + add_aviary_input(self, Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, units='lbm') + add_aviary_input( + self, Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, units='lbm' + ) + add_aviary_input(self, Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT) + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input( + self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type, units='lbf' + ) + add_aviary_input(self, Aircraft.Fuel.WING_FUEL_FRACTION, units='unitless') + + add_aviary_output(self, Aircraft.Design.FIXED_USEFUL_LOAD, units='lbm') + + self.declare_partials(Aircraft.Design.FIXED_USEFUL_LOAD, '*') + + def compute(self, inputs, outputs): + verbosity = self.options[Settings.VERBOSITY] + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + + wing_area = inputs[Aircraft.Wing.AREA] + Fn_SLS = inputs[Aircraft.Engine.SCALED_SLS_THRUST] + fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] + uld_per_pax = self.options[Aircraft.CrewPayload.ULD_MASS_PER_PASSENGER][0] + + engine_type = self.options[Aircraft.Engine.TYPE][0] + num_flight_attendants = get_num_of_flight_attendent(PAX) + num_pilots = get_num_of_pilots(PAX, engine_type) + + # note: the average weight of a pilot was calculated using the following equation: + # avg_wt = pct_male*avg_wt_male + pct_female*avg_wt_female where + # pct_male = the percentage of US airline pilots that are male (based on data from + # the center for aviation in 2018, which listed this percentage as 95.6%, and slightly + # deflated to account for the upward trend in female pilots, resulting in an estimated + # percentage of 94%) + # avg_wt_male is the average weight of males according to the CDC, and is 199.8 lbf + # pct_female is calculated from the same methods as pct_male, and results in 6% + # avg_wt_female is the average weight of females according to the CDC, and is 170.8 lbf + # the resulting value is that the average weight of the US airline pilot is 198 lbf + pilot_wt = 198 * num_pilots + + # note: the average weight of a flight attendant was calulated using the following equation: + # avg_wt = pct_male*avg_wt_male + pct_female*avg_wt_female where + # pct_male = the percentage of US flight attendants that are male (based on data from + # the women in aerospace international organization in 2020, which listed this percentage as + # 20.8%) + # avg_wt_male is the average weight of males according to the CDC, and is 199.8 lbf + # pct_female is calculated from the same methods as pct_male, and results in 79.2% + # avg_wt_female is the average weight of females according to the CDC, and is 170.8 lbf + # the resulting value is that the average weight of the US flight attendant is 177 lbf + flight_attendant_wt = 177 * num_flight_attendants + + if PAX >= 40.0: + crew_bag_wt = 20.0 * (num_flight_attendants + num_pilots) + 25.0 * num_pilots + elif PAX < 20: + crew_bag_wt = 25.0 * num_pilots + else: + crew_bag_wt = 10.0 * (num_pilots + num_flight_attendants) + 25.0 + + if engine_type is GASPEngineType.TURBOJET: + oil_per_eng_wt = 0.0054 * Fn_SLS + 12.0 + elif engine_type is GASPEngineType.TURBOSHAFT or engine_type is GASPEngineType.TURBOPROP: + oil_per_eng_wt = 0.0214 * Fn_SLS + 14 + # else: + # oil_per_eng_wt = 0.062 * (Fn_SLS - 100) + 11 + else: + # Other engine types are currently not supported in Aviary + if verbosity > Verbosity.BRIEF: + print('This engine_type is not curretly supported in Aviary.') + oil_per_eng_wt = 0 + + oil_wt = num_engines * oil_per_eng_wt + + lavatories = get_num_of_lavatories(PAX) + + service_wt = 0.0 + if PAX > 9.0: + service_wt = ( + inputs[Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER] + * PAX + * GRAV_ENGLISH_LBM + + 16.0 * lavatories + ) + + water_wt = 0.0 + if PAX > 19.0: + water_wt = ( + inputs[Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT] + * (PAX + num_pilots + num_flight_attendants) + * GRAV_ENGLISH_LBM + ) + + emergency_wt = 0.0 + if PAX > 5.0: + emergency_wt = 10.0 + if PAX > 9.0: + emergency_wt = 15.0 + if PAX >= 35.0: + emergency_wt = 25.0 * num_flight_attendants + 15.0 + # TODO The following if-block should be removed. Aircraft.Design.EMERGENCY_EQUIPMENT_MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] < 1e-5): + emergency_wt = inputs[Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] * GRAV_ENGLISH_LBM + + catering_wt = 0.0 + if PAX > 19.0: + catering_wt = ( + inputs[Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER] + * PAX + * GRAV_ENGLISH_LBM + ) + + trapped_fuel_wt = ( + inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] + * (wing_area**0.5) + * fuel_vol_frac + / 0.430 + ) + if fuel_vol_frac <= 0.075: # note: this technically creates a discontinuity # won't change + trapped_fuel_wt = ( + inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] * 0.18 * (wing_area**0.5) + ) + + unit_weight_cargo_handling = 165.0 + uld_per_pax = uld_per_pax.real + cargo_handling_wt = (int(PAX * uld_per_pax) + 1) * unit_weight_cargo_handling + + useful_wt = ( + pilot_wt + + flight_attendant_wt + + crew_bag_wt + + oil_wt + + service_wt + + water_wt + + emergency_wt + + catering_wt + + trapped_fuel_wt + + cargo_handling_wt + ) + + outputs[Aircraft.Design.FIXED_USEFUL_LOAD] = useful_wt / GRAV_ENGLISH_LBM + + def compute_partials(self, inputs, partials): + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + + wing_area = inputs[Aircraft.Wing.AREA] + fuel_vol_frac = inputs[Aircraft.Fuel.WING_FUEL_FRACTION] + + engine_type = self.options[Aircraft.Engine.TYPE][0] + + num_pilots = get_num_of_pilots(PAX, engine_type) + + num_flight_attendants = get_num_of_flight_attendent(PAX) + + if engine_type is GASPEngineType.TURBOJET: + doil_per_eng_wt_dFn_SLS = 0.0054 + elif engine_type is GASPEngineType.TURBOSHAFT or engine_type is GASPEngineType.TURBOPROP: + doil_per_eng_wt_dFn_SLS = 0.0124 + # else: + # doil_per_eng_wt_dFn_SLS = 0.062 + else: + # Other engine types are currently not supported in Aviary + doil_per_eng_wt_dFn_SLS = 0.0 + + dservice_wt_dmass_coeff_8 = 0.0 + if PAX > 9.0: + dservice_wt_dmass_coeff_8 = PAX * GRAV_ENGLISH_LBM + + dwater_wt_dmass_coeff_9 = 0.0 + if PAX > 19.0: + dwater_wt_dmass_coeff_9 = (PAX + num_pilots + num_flight_attendants) * GRAV_ENGLISH_LBM + + demergency_wt_dmass_coeff_10 = 0.0 + # TODO The following if-block should be removed. Aircraft.Design.EMERGENCY_EQUIPMENT_MASS should be output, not input. + if not (-1e-5 < inputs[Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] < 1e-5): + demergency_wt_dmass_coeff_10 = GRAV_ENGLISH_LBM + + dcatering_wt_dmass_coeff_11 = 0.0 + if PAX > 19.0: + dcatering_wt_dmass_coeff_11 = PAX * GRAV_ENGLISH_LBM + + dtrapped_fuel_wt_dmass_coeff_12 = (wing_area**0.5) * fuel_vol_frac / 0.430 + dtrapped_fuel_wt_dwing_area = ( + 0.5 + * inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] + * (wing_area**-0.5) + * fuel_vol_frac + / 0.430 + ) + dtrapped_fuel_wt_dfuel_vol_frac = ( + inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] * (wing_area**0.5) / 0.430 + ) + + if fuel_vol_frac <= 0.075: # note: this technically creates a discontinuity # won't change + dtrapped_fuel_wt_dmass_coeff_12 = 0.18 * (wing_area**0.5) + dtrapped_fuel_wt_dwing_area = ( + 0.5 + * inputs[Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT] + * 0.18 + * (wing_area**-0.5) + ) + dtrapped_fuel_wt_dfuel_vol_frac = 0.0 + + doil_wt_dFnSLS = num_engines * doil_per_eng_wt_dFn_SLS + duseful_mass_dFn_SLS = doil_wt_dFnSLS / GRAV_ENGLISH_LBM + + duseful_mass_dmass_coeff_8 = dservice_wt_dmass_coeff_8 / GRAV_ENGLISH_LBM + duseful_mass_dmass_coeff_9 = dwater_wt_dmass_coeff_9 / GRAV_ENGLISH_LBM + duseful_mass_dmass_coeff_10 = demergency_wt_dmass_coeff_10 / GRAV_ENGLISH_LBM + duseful_mass_dmass_coeff_11 = dcatering_wt_dmass_coeff_11 / GRAV_ENGLISH_LBM + duseful_mass_dmass_coeff_12 = dtrapped_fuel_wt_dmass_coeff_12 / GRAV_ENGLISH_LBM + duseful_mass_dwing_area = dtrapped_fuel_wt_dwing_area / GRAV_ENGLISH_LBM + duseful_mass_dfuel_vol_frac = dtrapped_fuel_wt_dfuel_vol_frac / GRAV_ENGLISH_LBM + partials[Aircraft.Design.FIXED_USEFUL_LOAD, Aircraft.Engine.SCALED_SLS_THRUST] = ( + duseful_mass_dFn_SLS + ) + partials[ + Aircraft.Design.FIXED_USEFUL_LOAD, + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, + ] = duseful_mass_dmass_coeff_8 + partials[ + Aircraft.Design.FIXED_USEFUL_LOAD, Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT + ] = duseful_mass_dmass_coeff_9 + partials[Aircraft.Design.FIXED_USEFUL_LOAD, Aircraft.Design.EMERGENCY_EQUIPMENT_MASS] = ( + duseful_mass_dmass_coeff_10 + ) + partials[ + Aircraft.Design.FIXED_USEFUL_LOAD, + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, + ] = duseful_mass_dmass_coeff_11 + partials[ + Aircraft.Design.FIXED_USEFUL_LOAD, Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT + ] = duseful_mass_dmass_coeff_12 + + partials[Aircraft.Design.FIXED_USEFUL_LOAD, Aircraft.Wing.AREA] = duseful_mass_dwing_area + partials[Aircraft.Design.FIXED_USEFUL_LOAD, Aircraft.Fuel.WING_FUEL_FRACTION] = ( + duseful_mass_dfuel_vol_frac + ) + + +class BWBACMass(om.ExplicitComponent): + """ + Computation of air conditioning mass for BWB + """ + + def setup(self): + add_aviary_input(self, Aircraft.AirConditioning.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, units='psi') + add_aviary_input(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft') + + self.add_output(Aircraft.AirConditioning.MASS, units='lbm') + + self.declare_partials( + Aircraft.AirConditioning.MASS, + [ + Aircraft.AirConditioning.MASS_COEFFICIENT, + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, + Mission.Design.GROSS_MASS, + ], + ) + + def compute(self, inputs, outputs): + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] + cabin_width = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + ac_coeff = inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] + + # note: this technically creates a discontinuity but we will not smooth it. + if gross_wt_initial > 3500.0: + air_conditioning_wt = ( + ac_coeff * (1.5 + p_diff_fus) * (0.358 * fus_len * cabin_width**2) ** 0.5 + ) + else: + air_conditioning_wt = 5.0 + + outputs[Aircraft.AirConditioning.MASS] = air_conditioning_wt / GRAV_ENGLISH_LBM + + def compute_partials(self, inputs, J): + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] + cabin_width = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + ac_coeff = inputs[Aircraft.AirConditioning.MASS_COEFFICIENT] + + dac_wt_dgross_wt = 0.0 + + if gross_wt_initial > 3500.0: + dac_wt_dfus_len = ( + 0.5 + * ac_coeff + * (1.5 + p_diff_fus) + * 0.358 + * cabin_width**2 + * (0.358 * fus_len * cabin_width**2) ** -0.5 + ) + dac_wt_dp_diff_fus = ac_coeff * (0.358 * fus_len * cabin_width**2) ** 0.5 + dac_wt_dcabin_width = ( + ac_coeff + * (1.5 + p_diff_fus) + * 0.358 + * fus_len + * cabin_width + * (0.358 * fus_len * cabin_width**2) ** -0.5 + ) + dac_wt_dac_coeff = (1.5 + p_diff_fus) * (0.358 * fus_len * cabin_width**2) ** 0.5 + else: + dac_wt_dfus_len = 0.0 + dac_wt_dp_diff_fus = 0.0 + dac_wt_dcabin_width = 0.0 + dac_wt_dac_coeff = 0.0 + + J[Aircraft.AirConditioning.MASS, Mission.Design.GROSS_MASS] = dac_wt_dgross_wt + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.LENGTH] = ( + dac_wt_dfus_len / GRAV_ENGLISH_LBM + ) + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] = ( + dac_wt_dp_diff_fus / GRAV_ENGLISH_LBM + ) + J[Aircraft.AirConditioning.MASS, Aircraft.Fuselage.HYDRAULIC_DIAMETER] = ( + dac_wt_dcabin_width / GRAV_ENGLISH_LBM + ) + J[Aircraft.AirConditioning.MASS, Aircraft.AirConditioning.MASS_COEFFICIENT] = ( + dac_wt_dac_coeff / GRAV_ENGLISH_LBM + ) + + +class BWBFurnishingMass(om.ExplicitComponent): + """ + Computation of furnishing mass for BWB + """ + + def initialize(self): + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) + add_aviary_option(self, Aircraft.Engine.TYPE) + add_aviary_option(self, Aircraft.Furnishings.USE_EMPIRICAL_EQUATION) + self.options.declare('mu', default=1.0, types=float) + + def setup(self): + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.HYDRAULIC_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.Furnishings.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2') + + self.add_output(Aircraft.Furnishings.MASS, units='lbm') + + self.declare_partials( + Aircraft.Furnishings.MASS, + [ + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + Mission.Design.GROSS_MASS, + Aircraft.Furnishings.MASS_SCALER, + Aircraft.Fuselage.LENGTH, + Aircraft.Fuselage.CABIN_AREA, + ], + ) + + def compute(self, inputs, outputs): + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + empirical = self.options[Aircraft.Furnishings.USE_EMPIRICAL_EQUATION] + engine_type = self.options[Aircraft.Engine.TYPE][0] + mu = self.options['mu'] + + num_pilots = get_num_of_pilots(PAX, engine_type) + num_flight_attendants = get_num_of_flight_attendent(PAX) + lavatories = get_num_of_lavatories(PAX) + + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + scaler = inputs[Aircraft.Furnishings.MASS_SCALER] + acabin = inputs[Aircraft.Fuselage.CABIN_AREA] + + if gross_wt_initial <= 10000.0: + # note: this technically creates a discontinuity + # TODO: Doesn't occur in large single aisle + furnishing_wt = 0.065 * gross_wt_initial - 59.0 + else: + if PAX >= 50: + if empirical: + # commonly used empirical furnishing weight equation + furnishing_wt_additional = scaler * PAX + else: + # linear regression formula + furnishing_wt_additional = 118.4 * PAX - 4190.0 + # baseline furnishings (crew seats, cockpit, lavatories, galleys) + cabin_len = 0.75 * fus_len + agalley = 0.50 * PAX + furnishing_wt = ( + furnishing_wt_additional + + num_pilots * (1.0 + cabin_width / 12.0) * 90.0 + + num_flight_attendants * 30.0 + + lavatories * 240.0 + + agalley * 12.0 + + 1.5 * cabin_len * cabin_width * np.pi / 2.0 + + 0.5 * acabin + ) + else: + CPX_lin = 28.0 + 10.516 * (cabin_width - 5.667) + if smooth: + CPX = ( + 28 * sigmoidX(CPX_lin / 28, 1, -0.01) + + CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * sigmoidX(CPX_lin / 62, 1, -0.01) + + 62 * sigmoidX(CPX_lin / 62, 1, 0.01) + ) + else: + if cabin_width <= 5.667: # note: this technically creates a discontinuity + CPX = 28.0 + elif cabin_width > 8.90: # note: this technically creates a discontinuity + CPX = 62.0 + furnishing_wt = CPX * PAX + 310.0 + + if smooth: + furnishing_wt = smooth_max(furnishing_wt, 30.0, mu) + else: + furnishing_wt = np.maximum(furnishing_wt, 30.0) + + outputs[Aircraft.Furnishings.MASS] = furnishing_wt / GRAV_ENGLISH_LBM + + def compute_partials(self, inputs, partials): + PAX = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + empirical = self.options[Aircraft.Furnishings.USE_EMPIRICAL_EQUATION] + engine_type = self.options[Aircraft.Engine.TYPE][0] + mu = self.options['mu'] + + num_pilots = get_num_of_pilots(PAX, engine_type) + num_flight_attendants = get_num_of_flight_attendent(PAX) + lavatories = get_num_of_lavatories(PAX) + + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + fus_len = inputs[Aircraft.Fuselage.LENGTH] + cabin_width = inputs[Aircraft.Fuselage.HYDRAULIC_DIAMETER] + scaler = inputs[Aircraft.Furnishings.MASS_SCALER] + acabin = inputs[Aircraft.Fuselage.CABIN_AREA] + + if gross_wt_initial <= 10000.0: + furnishing_wt = 0.065 * gross_wt_initial - 59.0 + dfurnishing_wt_dgross_wt_initial = 0.065 + dfurnishing_wt_dcabin_width = 0.0 + dfurnishing_wt_dfus_len = 0.0 + dfurnishing_wt_dscaler = 0.0 + dfurnishing_wt_dacabin = 0.0 + else: + if PAX >= 50: + if empirical: + furnishing_wt_additional = scaler * PAX + dfurnishing_wt_additional_dgross_wt_initial = 0.0 + dfurnishing_wt_additional_dcabin_width = 0.0 + dfurnishing_wt_additional_dfus_len = 0.0 + dfurnishing_wt_additional_dscaler = PAX + dfurnishing_wt_additional_dacabin = 0.0 + else: + furnishing_wt_additional = 118.4 * PAX - 4190.0 + dfurnishing_wt_additional_dgross_wt_initial = 0.0 + dfurnishing_wt_additional_dcabin_width = 0.0 + dfurnishing_wt_additional_dfus_len = 0.0 + dfurnishing_wt_additional_dscaler = 0.0 + dfurnishing_wt_additional_dacabin = 0.0 + cabin_len = 0.75 * fus_len + agalley = 0.50 * PAX + furnishing_wt = ( + furnishing_wt_additional + + num_pilots * (1.0 + cabin_width / 12.0) * 90.0 + + num_flight_attendants * 30.0 + + lavatories * 240.0 + + agalley * 12.0 + + 1.5 * cabin_len * cabin_width * np.pi / 2.0 + + 0.5 * acabin + ) + dfurnishing_wt_dgross_wt_initial = dfurnishing_wt_additional_dgross_wt_initial + 0.0 + dfurnishing_wt_dcabin_width = ( + dfurnishing_wt_additional_dcabin_width + + num_pilots * (1.0 / 12.0) * 90.0 + + 1.5 * 0.75 * fus_len * np.pi / 2.0 + ) + dfurnishing_wt_dfus_len = ( + dfurnishing_wt_additional_dfus_len + 1.5 * 0.75 * cabin_width * np.pi / 2.0 + ) + dfurnishing_wt_dscaler = dfurnishing_wt_additional_dscaler + 0.0 + dfurnishing_wt_dacabin = dfurnishing_wt_additional_dacabin + 0.5 + else: + CPX_lin = 28.0 + 10.516 * (cabin_width - 5.667) + if smooth: + CPX = ( + 28 * sigmoidX(CPX_lin / 28, 1, -0.01) + + CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * sigmoidX(CPX_lin / 62, 1, -0.01) + + 62 * sigmoidX(CPX_lin / 62, 1, 0.01) + ) + else: + if cabin_width <= 5.667: # note: this technically creates a discontinuity + CPX = 28.0 + elif cabin_width > 8.90: # note: this technically creates a discontinuity + CPX = 62.0 + furnishing_wt = CPX * PAX + 310.0 + + dCPX_lin_dcabin_width = 10.516 + if smooth: + dCPX_dcabin_width = ( + 1 * dSigmoidXdx(CPX_lin / 28, 1, 0.01) * -dCPX_lin_dcabin_width + + dCPX_lin_dcabin_width + * CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * sigmoidX(CPX_lin / 62, 1, -0.01) + + CPX_lin + * dSigmoidXdx(CPX_lin / 28, 1, 0.01) + / 28 + * sigmoidX(CPX_lin / 62, 1, -0.01) + * dCPX_lin_dcabin_width + + CPX_lin + * sigmoidX(CPX_lin / 28, 1, 0.01) + * dSigmoidXdx(CPX_lin / 62, 1, -0.01) + / 62 + * -dCPX_lin_dcabin_width + + 1 * dSigmoidXdx(CPX_lin / 62, 1, 0.01) * dCPX_lin_dcabin_width + ) + else: + if cabin_width <= 5.667: # note: this technically creates a discontinuity + dCPX_dcabin_width = 0.0 + if cabin_width > 8.90: # note: this technically creates a discontinuity + dCPX_dcabin_width = 0.0 + + dfurnishing_wt_dcabin_width = PAX * dCPX_dcabin_width + dfurnishing_wt_dgross_wt_initial = 0.0 + dfurnishing_wt_dfus_len = 0.0 + dfurnishing_wt_dscaler = 0.0 + dfurnishing_wt_dacabin = 0.0 + + if smooth: + sm_fac = d_smooth_max(furnishing_wt, 30.0, mu) + dfurnishing_wt_dcabin_width = sm_fac * dfurnishing_wt_dcabin_width + dfurnishing_wt_dgross_wt_initial = sm_fac * dfurnishing_wt_dgross_wt_initial + dfurnishing_wt_dfus_len = sm_fac * dfurnishing_wt_dfus_len + dfurnishing_wt_dscaler = sm_fac * dfurnishing_wt_dscaler + dfurnishing_wt_dacabin = sm_fac * dfurnishing_wt_dacabin + else: + if furnishing_wt < 30.0: # note: this technically creates a discontinuity + dfurnishing_wt_dcabin_width = 0.0 + dfurnishing_wt_dgross_wt_initial = 0.0 + dfurnishing_wt_dfus_len = 0.0 + dfurnishing_wt_dscaler = 0.0 + dfurnishing_wt_dacabin = 0.0 + + partials[Aircraft.Furnishings.MASS, Mission.Design.GROSS_MASS] = ( + dfurnishing_wt_dgross_wt_initial + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Fuselage.HYDRAULIC_DIAMETER] = ( + dfurnishing_wt_dcabin_width / GRAV_ENGLISH_LBM + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Fuselage.LENGTH] = ( + dfurnishing_wt_dfus_len / GRAV_ENGLISH_LBM + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Furnishings.MASS_SCALER] = ( + dfurnishing_wt_dscaler / GRAV_ENGLISH_LBM + ) + partials[Aircraft.Furnishings.MASS, Aircraft.Fuselage.CABIN_AREA] = ( + dfurnishing_wt_dacabin / GRAV_ENGLISH_LBM + ) + + +class BWBEquipMassGroup(om.Group): + def setup(self): + self.add_subsystem( + 'equip_partial', + EquipMassPartialSum(), + promotes_inputs=['*'], + promotes_outputs=['equip_mass_part'], + ) + self.add_subsystem( + 'ac', + BWBACMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'furnishing', + BWBFurnishingMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + self.add_subsystem( + 'equip_sum', + EquipMassSum(), + promotes_inputs=['*'] + ['equip_mass_part'], + promotes_outputs=['*'], + ) + + +class EquipAndUsefulLoadMassGroup(om.Group): + def initialize(self): + add_aviary_option(self, Aircraft.Design.TYPE) + + def setup(self): + design_type = self.options[Aircraft.Design.TYPE] + + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'equip', + BWBEquipMassGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'equip', + EquipMassGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + self.add_subsystem( + 'useful', + UsefulLoadMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) diff --git a/aviary/subsystems/mass/gasp_based/fixed.py b/aviary/subsystems/mass/gasp_based/fixed.py index 3f083f3b3c..24c35e6c4d 100644 --- a/aviary/subsystems/mass/gasp_based/fixed.py +++ b/aviary/subsystems/mass/gasp_based/fixed.py @@ -3,75 +3,67 @@ from openmdao.components.ks_comp import KSfunction from aviary.constants import GRAV_ENGLISH_LBM, RHO_SEA_LEVEL_ENGLISH -from aviary.utils.aviary_values import AviaryValues +from aviary.utils.functions import dSigmoidXdx, sigmoidX from aviary.variable_info.enums import FlapType -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission -def sigX(x): - # sig = np.divide(1, (1 + np.exp(-320*x)), out=np.zeros_like(x), where=x>-1) - sig = 1 / (1 + np.exp(-320*x)) if x > -1 else 0 - return sig - - -def dSigXdX(x): - derivative = -1 / (1 + np.exp(-320 * x)) ** 2 * \ - (-320 * np.exp(-320 * x)) if x > -1 else 0 - return derivative - - class MassParameters(om.ExplicitComponent): """ Computation of various parameters (such as correction factor for the use of non optimum material, reduction in bending moment factor for strut braced wing, landing gear location factor, engine position factor, and wing chord half sweep - angle) + angle). """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Engine.NUM_FUSELAGE_ENGINES) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Aircraft.Wing.SWEEP, val=0.436, units='rad') - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) - add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, val=10.13) - add_aviary_input(self, Aircraft.Wing.SPAN, val=117.8) + add_aviary_input(self, Aircraft.Wing.SWEEP, units='rad') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') self.add_input( - "max_mach", val=0.9, units="unitless", - desc="EMM0: maximum operating mach number" + 'max_mach', + val=0.9, + units='unitless', + desc='EMM0: maximum operating Mach number', ) - add_aviary_input( - self, Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=0, - units='unitless') + add_aviary_input(self, Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, units='unitless') - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15) + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_LOCATION, units='unitless') - add_aviary_output(self, Aircraft.Wing.MATERIAL_FACTOR, val=0) + add_aviary_output(self, Aircraft.Wing.MATERIAL_FACTOR, units='unitless') self.add_output( - "c_strut_braced", + 'c_strut_braced', val=0, - units="unitless", - desc="SKSTR: reduction in bending moment factor for strut braced wing", + units='unitless', + desc='SKSTR: reduction in bending moment factor for strut braced wing', ) self.add_output( - "c_gear_loc", val=0, units="unitless", - desc="SKGEAR: landing gear location factor" + 'c_gear_loc', + val=0, + units='unitless', + desc='SKGEAR: landing gear location factor', ) - add_aviary_output(self, Aircraft.Engine.POSITION_FACTOR, - val=np.zeros(num_engine_type)) - self.add_output( - "half_sweep", val=0, units="rad", desc="SWC2: wing chord half sweep angle" + add_aviary_output( + self, + Aircraft.Engine.POSITION_FACTOR, + shape=num_engine_type, + units='unitless', ) + self.add_output('half_sweep', val=0, units='rad', desc='SWC2: wing chord half sweep angle') + def setup_partials(self): self.declare_partials( Aircraft.Wing.MATERIAL_FACTOR, [ @@ -81,9 +73,9 @@ def setup(self): Aircraft.Wing.ASPECT_RATIO, ], ) - self.declare_partials(Aircraft.Engine.POSITION_FACTOR, ["max_mach"]) + self.declare_partials(Aircraft.Engine.POSITION_FACTOR, ['max_mach']) self.declare_partials( - "half_sweep", + 'half_sweep', [ Aircraft.Wing.SWEEP, Aircraft.Wing.TAPER_RATIO, @@ -92,29 +84,23 @@ def setup(self): ) self.declare_partials( - "c_strut_braced", + 'c_strut_braced', [Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, Aircraft.Wing.SPAN], ) - self.declare_partials( - "c_gear_loc", Aircraft.LandingGear.MAIN_GEAR_LOCATION) + self.declare_partials('c_gear_loc', Aircraft.LandingGear.MAIN_GEAR_LOCATION) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - sweep_c4 = inputs[Aircraft.Wing.SWEEP] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] AR = inputs[Aircraft.Wing.ASPECT_RATIO] wingspan = inputs[Aircraft.Wing.SPAN] - num_engines = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') - max_mach = inputs["max_mach"] + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + max_mach = inputs['max_mach'] strut_x = inputs[Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS] - gear_location = inputs[Aircraft.LandingGear.MAIN_GEAR_LOCATION] + loc_main_gear = inputs[Aircraft.LandingGear.MAIN_GEAR_LOCATION] - tan_half_sweep = \ - np.tan(sweep_c4) - \ - (1.0 - taper_ratio) / (1.0 + taper_ratio) / AR + tan_half_sweep = np.tan(sweep_c4) - (1.0 - taper_ratio) / (1.0 + taper_ratio) / AR half_sweep = np.arctan(tan_half_sweep) cos_half_sweep = np.cos(half_sweep) @@ -122,69 +108,60 @@ def compute(self, inputs, outputs): c_material = 1.0 + 2.5 / (struct_span**0.5) c_strut_braced = 1.0 - strut_x**2 - not_fuselage_mounted = self.options["aviary_options"].get_val( - Aircraft.Engine.NUM_FUSELAGE_ENGINES) == 0 + not_fuselage_mounted = self.options[Aircraft.Engine.NUM_FUSELAGE_ENGINES] == 0 # note: c_gear_loc doesn't actually depend on any of the inputs... perhaps use a # set_input_defaults call to declare this at a higher level c_gear_loc = 1.0 - if aviary_options.get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless' - ): + if self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES]: # smooth transition for c_gear_loc from 0.95 to 1 when gear_location varies # between 0 and 1% of span - c_gear_loc = .95 * sigX((0.005 - gear_location)*100) + \ - 1 * sigX(100*(gear_location - 0.005)) + c_gear_loc = 0.95 * sigmoidX(loc_main_gear, 0.005, -0.01 / 320.0) + 1 * sigmoidX( + loc_main_gear, 0.005, 0.01 / 320.0 + ) else: - if gear_location == 0: + if loc_main_gear == 0: c_gear_loc = 0.95 - c_eng_pos = 1.0 * sigX(0.75 - max_mach) + 1.05 * sigX(max_mach - 0.75) - if ( - not_fuselage_mounted - and num_engines == 2 - or num_engines == 3 - ): - c_eng_pos = 0.98 * sigX(0.75 - max_mach) + 0.95 * sigX(max_mach - 0.75) + # why always use sigmoid function? + c_eng_pos = 1.0 * sigmoidX(max_mach, 0.75, -1.0 / 320.0) + 1.05 * sigmoidX( + max_mach, 0.75, 1.0 / 320.0 + ) + if not_fuselage_mounted and num_engines == 2 or num_engines == 3: + c_eng_pos = 0.98 * sigmoidX(max_mach, 0.75, -1.0 / 320.0) + 0.95 * sigmoidX( + max_mach, 0.75, 1.0 / 320.0 + ) if not_fuselage_mounted and num_engines == 4: - c_eng_pos = 0.95 * sigX(0.75 - max_mach) + 0.9 * sigX(max_mach - 0.75) + c_eng_pos = 0.95 * sigmoidX(max_mach, 0.75, -1.0 / 320.0) + 0.9 * sigmoidX( + max_mach, 0.75, 1.0 / 320.0 + ) outputs[Aircraft.Wing.MATERIAL_FACTOR] = c_material - outputs["c_strut_braced"] = c_strut_braced - outputs["c_gear_loc"] = c_gear_loc + outputs['c_strut_braced'] = c_strut_braced + outputs['c_gear_loc'] = c_gear_loc outputs[Aircraft.Engine.POSITION_FACTOR] = c_eng_pos - outputs["half_sweep"] = half_sweep + outputs['half_sweep'] = half_sweep def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - sweep_c4 = inputs[Aircraft.Wing.SWEEP] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] AR = inputs[Aircraft.Wing.ASPECT_RATIO] wingspan = inputs[Aircraft.Wing.SPAN] - num_engines = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') - max_mach = inputs["max_mach"] + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] + max_mach = inputs['max_mach'] strut_x = inputs[Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS] - gear_location = inputs[Aircraft.LandingGear.MAIN_GEAR_LOCATION] + loc_main_gear = inputs[Aircraft.LandingGear.MAIN_GEAR_LOCATION] - tan_half_sweep = ( - np.tan(sweep_c4) - - (1.0 - taper_ratio) / (1.0 + taper_ratio) / AR - ) + tan_half_sweep = np.tan(sweep_c4) - (1.0 - taper_ratio) / (1.0 + taper_ratio) / AR half_sweep = np.arctan(tan_half_sweep) cos_half_sweep = np.cos(half_sweep) struct_span = wingspan / cos_half_sweep - c_material = 1.0 + 2.5 / (struct_span**0.5) - not_fuselage_mounted = self.options["aviary_options"].get_val( - Aircraft.Engine.NUM_FUSELAGE_ENGINES) == 0 + not_fuselage_mounted = self.options[Aircraft.Engine.NUM_FUSELAGE_ENGINES] == 0 - dTanHS_dSC4 = (1 / np.cos(sweep_c4) ** 2) + dTanHS_dSC4 = 1 / np.cos(sweep_c4) ** 2 dTanHS_TR = ( - -(1 / AR) - * ((1 + taper_ratio) * (-1) - (1 - taper_ratio)) - / (1 + taper_ratio) ** 2 + -(1 / AR) * ((1 + taper_ratio) * (-1) - (1 - taper_ratio)) / (1 + taper_ratio) ** 2 ) dTanHS_dAR = (1.0 - taper_ratio) / (1.0 + taper_ratio) / AR**2 @@ -219,229 +196,214 @@ def compute_partials(self, inputs, J): * dTanHS_dAR ) - J[Aircraft.Engine.POSITION_FACTOR, "max_mach"] = -dSigXdX( - 0.75 - max_mach - ) + 1.05 * dSigXdX(max_mach - 0.75) - if ( - not_fuselage_mounted - and num_engines == 2 - or num_engines == 3 - ): - J[Aircraft.Engine.POSITION_FACTOR, "max_mach"] = -0.98 * dSigXdX( - 0.75 - max_mach - ) + 0.95 * dSigXdX(max_mach - 0.75) + J[Aircraft.Engine.POSITION_FACTOR, 'max_mach'] = -dSigmoidXdx( + max_mach, 0.75, 1 / 320.0 + ) + 1.05 * dSigmoidXdx(max_mach, 0.75, 1 / 320.0) + if not_fuselage_mounted and num_engines == 2 or num_engines == 3: + J[Aircraft.Engine.POSITION_FACTOR, 'max_mach'] = -0.98 * dSigmoidXdx( + max_mach, 0.75, 1 / 320.0 + ) + 0.95 * dSigmoidXdx(max_mach, 0.75, 1 / 320.0) if not_fuselage_mounted and num_engines == 4: - J[Aircraft.Engine.POSITION_FACTOR, "max_mach"] = -0.95 * dSigXdX( - 0.75 - max_mach - ) + 0.9 * dSigXdX(max_mach - 0.75) + J[Aircraft.Engine.POSITION_FACTOR, 'max_mach'] = -0.95 * dSigmoidXdx( + max_mach, 0.75, 1 / 320.0 + ) + 0.9 * dSigmoidXdx(max_mach, 0.75, 1 / 320.0) - J["half_sweep", Aircraft.Wing.SWEEP] = ( - 1 / (tan_half_sweep**2 + 1) * dTanHS_dSC4 - ) - J["half_sweep", Aircraft.Wing.TAPER_RATIO] = ( - 1 / (tan_half_sweep**2 + 1) * dTanHS_TR - ) - J["half_sweep", Aircraft.Wing.ASPECT_RATIO] = ( - 1 / (tan_half_sweep**2 + 1) * dTanHS_dAR - ) + J['half_sweep', Aircraft.Wing.SWEEP] = 1 / (tan_half_sweep**2 + 1) * dTanHS_dSC4 + J['half_sweep', Aircraft.Wing.TAPER_RATIO] = 1 / (tan_half_sweep**2 + 1) * dTanHS_TR + J['half_sweep', Aircraft.Wing.ASPECT_RATIO] = 1 / (tan_half_sweep**2 + 1) * dTanHS_dAR - J["c_strut_braced", Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS] = \ - -2 * strut_x + J['c_strut_braced', Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS] = -2 * strut_x - if aviary_options.get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless' - ): - J["c_gear_loc", Aircraft.LandingGear.MAIN_GEAR_LOCATION] = ( - .95 * (-100) * dSigXdX((0.005 - gear_location)*100) - + 1 * (100) * dSigXdX(100*(gear_location - 0.005))) + if self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES]: + J['c_gear_loc', Aircraft.LandingGear.MAIN_GEAR_LOCATION] = 0.95 * (-100) * dSigmoidXdx( + loc_main_gear, 0.005, 0.01 / 320.0 + ) + 1 * (100) * dSigmoidXdx(loc_main_gear, 0.005, 0.01 / 320.0) -class PayloadMass(om.ExplicitComponent): - """ - Computation of maximum payload that the aircraft is being asked to carry - """ +class PayloadGroup(om.ExplicitComponent): + """Computation of maximum payload that the aircraft is being asked to carry.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.CrewPayload.NUM_PASSENGERS) + add_aviary_option(self, Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, units='lbm') + add_aviary_option(self, Aircraft.CrewPayload.Design.NUM_PASSENGERS) def setup(self): - add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, val=10040) + add_aviary_input(self, Aircraft.CrewPayload.CARGO_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.Design.CARGO_MASS, units='lbm') + add_aviary_input(self, Aircraft.CrewPayload.Design.MAX_CARGO_MASS, units='lbm') - add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=0) + add_aviary_output(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, units='lbm') + add_aviary_output(self, Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, units='lbm') + self.add_output('payload_mass_des', val=0, units='lbm', desc='WPLDES: design payload') self.add_output( - "payload_mass_des", val=0, units="lbm", desc="WPLDES: design payload" - ) - self.add_output( - "payload_mass_max", + 'payload_mass_max', val=0, - units="lbm", - desc="WPLMAX: maximum payload that the aircraft is being asked to carry" - " (design payload + cargo)", + units='lbm', + desc='WPLMAX: maximum payload that the aircraft is being asked to carry' + ' (design payload + cargo)', ) + def setup_partials(self): + self.declare_partials( + Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, + [Aircraft.CrewPayload.CARGO_MASS], + val=1.0, + ) + self.declare_partials('payload_mass_des', [Aircraft.CrewPayload.Design.CARGO_MASS], val=1.0) self.declare_partials( - "payload_mass_max", [ - Aircraft.CrewPayload.CARGO_MASS], - val=1.0) + 'payload_mass_max', [Aircraft.CrewPayload.Design.MAX_CARGO_MASS], val=1.0 + ) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options['aviary_options'] - pax_mass = aviary_options.get_val( - Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, units='lbm') - PAX = aviary_options.get_val( - Aircraft.CrewPayload.NUM_PASSENGERS, units='unitless') + pax_mass, _ = self.options[Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS] + pax = self.options[Aircraft.CrewPayload.NUM_PASSENGERS] + pax_des = self.options[Aircraft.CrewPayload.Design.NUM_PASSENGERS] cargo_mass = inputs[Aircraft.CrewPayload.CARGO_MASS] + cargo_mass_des = inputs[Aircraft.CrewPayload.Design.CARGO_MASS] + cargo_mass_max = inputs[Aircraft.CrewPayload.Design.MAX_CARGO_MASS] - outputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] = \ - payload_mass = pax_mass * PAX - outputs["payload_mass_des"] = payload_mass - outputs["payload_mass_max"] = pax_mass * PAX + cargo_mass + outputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] = pax_mass * pax + outputs['payload_mass_des'] = pax_mass * pax_des + cargo_mass_des + outputs['payload_mass_max'] = pax_mass * pax_des + cargo_mass_max + outputs[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS] = pax_mass * pax + cargo_mass class ElectricAugmentationMass(om.ExplicitComponent): - """ - Computation of electrical augmentation system mass - """ + """Computation of electrical augmentation system mass.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_ENGINES) def setup(self): self.add_input( - "motor_power", + 'motor_power', val=200, - units="kW", - desc="MOTRKW: power of augmentation motor", + units='kW', + desc='MOTRKW: power of augmentation motor', ) self.add_input( - "motor_voltage", + 'motor_voltage', val=50, - units="V", - desc="VOLTS: voltage of augmentation system", + units='V', + desc='VOLTS: voltage of augmentation system', ) self.add_input( - "max_amp_per_wire", + 'max_amp_per_wire', val=50, - units="A", - desc="AMPSPW: maximum amperage of each cable in augmentation system", + units='A', + desc='AMPSPW: maximum amperage of each cable in augmentation system', ) self.add_input( - "safety_factor", + 'safety_factor', val=1.33, - units="unitless", - desc="REDUNCY: cable mass redundancy/safety factor", + units='unitless', + desc='REDUNCY: cable mass redundancy/safety factor', ) - add_aviary_input(self, Aircraft.Electrical.HYBRID_CABLE_LENGTH, val=200) + add_aviary_input(self, Aircraft.Electrical.HYBRID_CABLE_LENGTH, units='ft') self.add_input( - "wire_area", + 'wire_area', val=0.0015, - units="ft**2", - desc="ACSWIRE: cross sectional area of electrical augmentation system wire", + units='ft**2', + desc='ACSWIRE: cross sectional area of electrical augmentation system wire', ) self.add_input( - "rho_wire", + 'rho_wire', val=1, - units="lbm/ft**3", - desc="DENWIRE: density of wire for electrical augmentation system", + units='lbm/ft**3', + desc='DENWIRE: density of wire for electrical augmentation system', ) self.add_input( - "battery_energy", + 'battery_energy', val=1, - units="MJ", - desc="EBATT: energy coming from the battery", + units='MJ', + desc='EBATT: energy coming from the battery', ) self.add_input( - "motor_eff", + 'motor_eff', val=1, - units="unitless", - desc="EFF_MTR: efficiency of electrical augmentation motor", + units='unitless', + desc='EFF_MTR: efficiency of electrical augmentation motor', ) self.add_input( - "inverter_eff", + 'inverter_eff', val=1, - units="unitless", - desc="EFF_INV: efficiency of electrical augmentation inverter/controller", + units='unitless', + desc='EFF_INV: efficiency of electrical augmentation inverter/controller', ) self.add_input( - "transmission_eff", + 'transmission_eff', val=1, - units="unitless", - desc="EFF_TRN: efficiency of electrical augmentation system power" - " transmission", + units='unitless', + desc='EFF_TRN: efficiency of electrical augmentation system power transmission', ) self.add_input( - "battery_eff", + 'battery_eff', val=1, - units="unitless", - desc="EFF_BAT: efficiency of electrical augmentation battery storage", + units='unitless', + desc='EFF_BAT: efficiency of electrical augmentation battery storage', ) self.add_input( - "rho_battery", + 'rho_battery', val=200, - units="MJ/lb", - desc="ENGYDEN: energy density of electrical augmentation system battery", + units='MJ/lb', + desc='ENGYDEN: energy density of electrical augmentation system battery', ) self.add_input( - "motor_spec_mass", + 'motor_spec_mass', val=10, - units="hp/lbm", - desc="SWT_MTR: specific mass of electrical augmentation motor", + units='hp/lbm', + desc='SWT_MTR: specific mass of electrical augmentation motor', ) self.add_input( - "inverter_spec_mass", + 'inverter_spec_mass', val=10, - units="kW/lbm", - desc="SWT_INV: specific mass of electrical augmentation inverter", + units='kW/lbm', + desc='SWT_INV: specific mass of electrical augmentation inverter', ) self.add_input( - "TMS_spec_mass", + 'TMS_spec_mass', val=10, - units="lbm/kW", - desc="SWT_TMS: specific mass of thermal managements system", + units='lbm/kW', + desc='SWT_TMS: specific mass of thermal managements system', ) self.add_output( - "aug_mass", + 'aug_mass', val=0, - units="lbm", - desc="WEAUG: mass of electrical augmentation system", + units='lbm', + desc='WEAUG: mass of electrical augmentation system', ) - self.declare_partials("aug_mass", "*") + self.declare_partials('aug_mass', '*') def compute(self, inputs, outputs): - motor_power = inputs["motor_power"] - motor_voltage = inputs["motor_voltage"] - max_amp_per_wire = inputs["max_amp_per_wire"] - safety_factor = inputs["safety_factor"] + motor_power = inputs['motor_power'] + motor_voltage = inputs['motor_voltage'] + max_amp_per_wire = inputs['max_amp_per_wire'] + safety_factor = inputs['safety_factor'] cable_len = inputs[Aircraft.Electrical.HYBRID_CABLE_LENGTH] - wire_area = inputs["wire_area"] - rho_wire = inputs["rho_wire"] - battery_energy = inputs["battery_energy"] - motor_eff = inputs["motor_eff"] - inverter_eff = inputs["inverter_eff"] - transmission_eff = inputs["transmission_eff"] - battery_eff = inputs["battery_eff"] - rho_battery = inputs["rho_battery"] - motor_spec_wt = inputs["motor_spec_mass"] / GRAV_ENGLISH_LBM - inverter_spec_wt = inputs["inverter_spec_mass"] / GRAV_ENGLISH_LBM - TMS_spec_wt = inputs["TMS_spec_mass"] * GRAV_ENGLISH_LBM - num_engines = self.options['aviary_options'].get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') + wire_area = inputs['wire_area'] + rho_wire = inputs['rho_wire'] + battery_energy = inputs['battery_energy'] + motor_eff = inputs['motor_eff'] + inverter_eff = inputs['inverter_eff'] + transmission_eff = inputs['transmission_eff'] + battery_eff = inputs['battery_eff'] + rho_battery = inputs['rho_battery'] + motor_spec_wt = inputs['motor_spec_mass'] / GRAV_ENGLISH_LBM + inverter_spec_wt = inputs['inverter_spec_mass'] / GRAV_ENGLISH_LBM + TMS_spec_wt = inputs['TMS_spec_mass'] * GRAV_ENGLISH_LBM + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] motor_current = 1000.0 * motor_power / motor_voltage num_wires = motor_current / max_amp_per_wire - cable_wt = 1.15 * safety_factor * num_wires * cable_len * \ - wire_area * rho_wire * GRAV_ENGLISH_LBM + cable_wt = ( + 1.15 * safety_factor * num_wires * cable_len * wire_area * rho_wire * GRAV_ENGLISH_LBM + ) actual_battery_energy = battery_energy / ( motor_eff * inverter_eff * transmission_eff * battery_eff ) @@ -458,55 +420,40 @@ def compute(self, inputs, outputs): + num_engines * TMS_wt ) - outputs["aug_mass"] = aug_wt / GRAV_ENGLISH_LBM + outputs['aug_mass'] = aug_wt / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - motor_power = inputs["motor_power"] - motor_voltage = inputs["motor_voltage"] - max_amp_per_wire = inputs["max_amp_per_wire"] - safety_factor = inputs["safety_factor"] + motor_power = inputs['motor_power'] + motor_voltage = inputs['motor_voltage'] + max_amp_per_wire = inputs['max_amp_per_wire'] + safety_factor = inputs['safety_factor'] cable_len = inputs[Aircraft.Electrical.HYBRID_CABLE_LENGTH] - wire_area = inputs["wire_area"] - rho_wire = inputs["rho_wire"] - battery_energy = inputs["battery_energy"] - motor_eff = inputs["motor_eff"] - inverter_eff = inputs["inverter_eff"] - transmission_eff = inputs["transmission_eff"] - battery_eff = inputs["battery_eff"] - rho_battery = inputs["rho_battery"] - motor_spec_wt = inputs["motor_spec_mass"] / GRAV_ENGLISH_LBM - inverter_spec_wt = inputs["inverter_spec_mass"] / GRAV_ENGLISH_LBM - TMS_spec_wt = inputs["TMS_spec_mass"] * GRAV_ENGLISH_LBM - num_engines = self.options['aviary_options'].get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') + wire_area = inputs['wire_area'] + rho_wire = inputs['rho_wire'] + battery_energy = inputs['battery_energy'] + motor_eff = inputs['motor_eff'] + inverter_eff = inputs['inverter_eff'] + transmission_eff = inputs['transmission_eff'] + battery_eff = inputs['battery_eff'] + rho_battery = inputs['rho_battery'] + motor_spec_wt = inputs['motor_spec_mass'] / GRAV_ENGLISH_LBM + inverter_spec_wt = inputs['inverter_spec_mass'] / GRAV_ENGLISH_LBM + TMS_spec_wt = inputs['TMS_spec_mass'] * GRAV_ENGLISH_LBM + num_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_ENGINES] motor_current = 1000.0 * motor_power / motor_voltage num_wires = motor_current / max_amp_per_wire - cable_wt = 1.15 * safety_factor * num_wires * cable_len * \ - wire_area * rho_wire * GRAV_ENGLISH_LBM actual_battery_energy = battery_energy / ( motor_eff * inverter_eff * transmission_eff * battery_eff ) - battery_wt = actual_battery_energy / rho_battery - motor_wt = motor_power / 0.746 / motor_spec_wt - inverter_wt = motor_power / inverter_spec_wt - - TMS_wt = TMS_spec_wt * motor_power - - aug_wt = ( - battery_wt - + cable_wt - + num_engines * inverter_wt - + num_engines * motor_wt - + num_engines * TMS_wt - ) dCableWt_dMotorPower = ( 1.15 * safety_factor * cable_len * wire_area - * rho_wire * GRAV_ENGLISH_LBM + * rho_wire + * GRAV_ENGLISH_LBM * 1000.0 / motor_voltage / max_amp_per_wire @@ -516,190 +463,201 @@ def compute_partials(self, inputs, J): dMotorWt_dMotorPower = 1 / 0.746 / motor_spec_wt dTMSwt_dMotorPower = TMS_spec_wt - J["aug_mass", "motor_power"] = ( + J['aug_mass', 'motor_power'] = ( dCableWt_dMotorPower + num_engines * dInverterWt_dMotorPower + num_engines * dMotorWt_dMotorPower + num_engines * dTMSwt_dMotorPower ) / GRAV_ENGLISH_LBM - J["aug_mass", "motor_voltage"] = ( + J['aug_mass', 'motor_voltage'] = ( -1.15 * safety_factor * cable_len * wire_area - * rho_wire * GRAV_ENGLISH_LBM + * rho_wire + * GRAV_ENGLISH_LBM / max_amp_per_wire * 1000.0 * motor_power - / motor_voltage**2 / GRAV_ENGLISH_LBM + / motor_voltage**2 + / GRAV_ENGLISH_LBM ) - J["aug_mass", "max_amp_per_wire"] = ( + J['aug_mass', 'max_amp_per_wire'] = ( -1.15 * safety_factor * cable_len * wire_area - * rho_wire * GRAV_ENGLISH_LBM + * rho_wire + * GRAV_ENGLISH_LBM * motor_current - / max_amp_per_wire**2 / GRAV_ENGLISH_LBM - ) - J["aug_mass", "safety_factor"] = ( - 1.15 * num_wires * cable_len * wire_area * rho_wire + / max_amp_per_wire**2 + / GRAV_ENGLISH_LBM ) - J["aug_mass", Aircraft.Electrical.HYBRID_CABLE_LENGTH] = ( + J['aug_mass', 'safety_factor'] = 1.15 * num_wires * cable_len * wire_area * rho_wire + J['aug_mass', Aircraft.Electrical.HYBRID_CABLE_LENGTH] = ( 1.15 * safety_factor * num_wires * wire_area * rho_wire ) - J["aug_mass", "wire_area"] = ( - 1.15 * safety_factor * num_wires * cable_len * rho_wire - ) - J["aug_mass", "rho_wire"] = ( - 1.15 * safety_factor * num_wires * cable_len * wire_area - ) - J["aug_mass", "battery_energy"] = ( + J['aug_mass', 'wire_area'] = 1.15 * safety_factor * num_wires * cable_len * rho_wire + J['aug_mass', 'rho_wire'] = 1.15 * safety_factor * num_wires * cable_len * wire_area + J['aug_mass', 'battery_energy'] = ( 1 / (motor_eff * inverter_eff * transmission_eff * battery_eff) - / rho_battery / GRAV_ENGLISH_LBM + / rho_battery + / GRAV_ENGLISH_LBM ) - J["aug_mass", "motor_eff"] = ( + J['aug_mass', 'motor_eff'] = ( -battery_energy / (motor_eff**2 * inverter_eff * transmission_eff * battery_eff) - / rho_battery / GRAV_ENGLISH_LBM + / rho_battery + / GRAV_ENGLISH_LBM ) - J["aug_mass", "inverter_eff"] = ( + J['aug_mass', 'inverter_eff'] = ( -battery_energy / (motor_eff * inverter_eff**2 * transmission_eff * battery_eff) - / rho_battery / GRAV_ENGLISH_LBM + / rho_battery + / GRAV_ENGLISH_LBM ) - J["aug_mass", "transmission_eff"] = ( + J['aug_mass', 'transmission_eff'] = ( -battery_energy / (motor_eff * inverter_eff * transmission_eff**2 * battery_eff) - / rho_battery / GRAV_ENGLISH_LBM + / rho_battery + / GRAV_ENGLISH_LBM ) - J["aug_mass", "battery_eff"] = ( + J['aug_mass', 'battery_eff'] = ( -battery_energy / (motor_eff * inverter_eff * transmission_eff * battery_eff**2) - / rho_battery / GRAV_ENGLISH_LBM + / rho_battery + / GRAV_ENGLISH_LBM ) - J["aug_mass", "rho_battery"] = -actual_battery_energy / \ - rho_battery**2 / GRAV_ENGLISH_LBM - J["aug_mass", "motor_spec_mass"] = ( + J['aug_mass', 'rho_battery'] = -actual_battery_energy / rho_battery**2 / GRAV_ENGLISH_LBM + J['aug_mass', 'motor_spec_mass'] = ( -num_engines * motor_power / 0.746 / motor_spec_wt**2 / GRAV_ENGLISH_LBM**2 ) - J["aug_mass", "inverter_spec_mass"] = ( + J['aug_mass', 'inverter_spec_mass'] = ( -num_engines * motor_power / inverter_spec_wt**2 / GRAV_ENGLISH_LBM**2 ) - J["aug_mass", "TMS_spec_mass"] = num_engines * motor_power + J['aug_mass', 'TMS_spec_mass'] = num_engines * motor_power class EngineMass(om.ExplicitComponent): """ - Computation of total engine mass, nacelle mass, pylon mass, total engine POD mass, - additional engine mass + Computation of total engine mass, nacelle mass, pylon mass, total engine POD mass, + additional engine mass. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Electrical.HAS_HYBRID_SYSTEM) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Aircraft.Engine.ADDITIONAL_MASS_FRACTION) + add_aviary_option(self, Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] - num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) - total_num_engines = aviary_options.get_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES) - - add_aviary_input(self, Aircraft.Engine.MASS_SPECIFIC, - val=np.full(num_engine_type, 0.21366)) - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, - val=np.full(num_engine_type, 4000), units="lbf") - add_aviary_input(self, Aircraft.Nacelle.MASS_SPECIFIC, - val=np.full(num_engine_type, 3)) - add_aviary_input(self, Aircraft.Nacelle.SURFACE_AREA, - val=np.full(num_engine_type, 5)) - add_aviary_input(self, Aircraft.Engine.PYLON_FACTOR, - val=np.full(num_engine_type, 1.25)) - add_aviary_input(self, Aircraft.Engine.ADDITIONAL_MASS_FRACTION, - val=np.full(num_engine_type, 0.14)) - add_aviary_input(self, Aircraft.Engine.MASS_SCALER, - val=np.full(num_engine_type, 1.0)) - add_aviary_input(self, Aircraft.Propulsion.MISC_MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.Engine.WING_LOCATIONS, - val=np.full(int(total_num_engines/2), 0.35)) - - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS, - val=500, units="lbm", desc="WMG: mass of main gear") - - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15) - - has_hybrid_system = aviary_options.get_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, units='unitless') + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + total_num_wing_engines = self.options[Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES] + + add_aviary_input( + self, Aircraft.Engine.MASS_SPECIFIC, shape=num_engine_type, units='lbm/lbf' + ) + add_aviary_input( + self, Aircraft.Engine.SCALED_SLS_THRUST, shape=num_engine_type, units='lbf' + ) + add_aviary_input( + self, + Aircraft.Nacelle.MASS_SPECIFIC, + shape=num_engine_type, + units='lbm/ft**2', + ) + add_aviary_input(self, Aircraft.Nacelle.SURFACE_AREA, shape=num_engine_type, units='ft**2') + add_aviary_input( + self, Aircraft.Engine.PYLON_FACTOR, shape=num_engine_type, units='unitless' + ) + add_aviary_input(self, Aircraft.Engine.MASS_SCALER, shape=num_engine_type, units='unitless') + add_aviary_input(self, Aircraft.Propulsion.MISC_MASS_SCALER, units='unitless') + + if total_num_wing_engines > 1: + add_aviary_input( + self, + Aircraft.Engine.WING_LOCATIONS, + shape=int(total_num_wing_engines / 2), + units='unitless', + ) + else: + add_aviary_input(self, Aircraft.Engine.WING_LOCATIONS, units='unitless') + + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS, units='lbm') + + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_LOCATION, units='unitless') + + has_hybrid_system = self.options[Aircraft.Electrical.HAS_HYBRID_SYSTEM] if has_hybrid_system: self.add_input( - "aug_mass", + 'aug_mass', val=400, - units="lbm", - desc="WEAUG: mass of electrical augmentation system", + units='lbm', + desc='WEAUG: mass of electrical augmentation system', ) - add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_MASS, val=0) - add_aviary_output(self, Aircraft.Nacelle.MASS, val=np.zeros(num_engine_type)) - self.add_output('pylon_mass', units='lbm', - desc='WPYLON: mass of each pylon', val=np.zeros(num_engine_type)) - add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=0) - add_aviary_output(self, Aircraft.Engine.ADDITIONAL_MASS, - val=np.zeros(num_engine_type)) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_MASS, units='lbm') + add_aviary_output(self, Aircraft.Nacelle.MASS, shape=num_engine_type) self.add_output( - "eng_comb_mass", + 'pylon_mass', + units='lbm', + desc='WPYLON: mass of each pylon', + val=np.zeros(num_engine_type), + ) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, units='lbm', desc='WPES') + add_aviary_output(self, Aircraft.Engine.ADDITIONAL_MASS, shape=num_engine_type, units='lbm') + self.add_output( + 'eng_comb_mass', val=0, - units="lbm", - desc="WPSTAR: combined mass of dry engine and engine installation," - " includes mass of electrical augmentation system", + units='lbm', + desc='WPSTAR: combined mass of dry engine and engine installation,' + ' includes mass of electrical augmentation system', ) self.add_output( - "wing_mounted_mass", + 'wing_mounted_mass', val=0, - units="lbm", - desc="WM: mass of gear and engine, basically everything mounted on the" - " wing", + units='lbm', + desc='WM: mass of gear and engine, basically everything mounted on the wing', ) - # for multiengine implementation needs this to always be avaliable + # for multiengine implementation needs this to always be available self.add_input( - "prop_mass", + 'prop_mass', # val=np.full(num_engine_type, 0.000000001), val=np.zeros(num_engine_type), - units="lbm", - desc="WPROP1: mass of one propeller", + units='lbm', + desc='WPROP1: mass of one propeller', ) - self.add_output( - "prop_mass_all", - val=0, - units="lbm", - desc="WPROP: mass of all propellers", - ) + self.add_output('prop_mass_all', val=0, units='lbm', desc='WPROP: mass of all propellers') + + def setup_partials(self): + has_hybrid_system = self.options[Aircraft.Electrical.HAS_HYBRID_SYSTEM] - self.declare_partials("prop_mass_all", ["prop_mass"]) - self.declare_partials("wing_mounted_mass", "prop_mass") + self.declare_partials('prop_mass_all', ['prop_mass']) + self.declare_partials('wing_mounted_mass', 'prop_mass') # derivatives w.r.t vectorized engine inputs have known sparsity pattern - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) shape = np.arange(num_engine_type) self.declare_partials( - Aircraft.Propulsion.TOTAL_ENGINE_MASS, [ - Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST] + Aircraft.Propulsion.TOTAL_ENGINE_MASS, + [Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST], ) self.declare_partials( Aircraft.Nacelle.MASS, [Aircraft.Nacelle.MASS_SPECIFIC, Aircraft.Nacelle.SURFACE_AREA], - rows=shape, cols=shape, val=1.0 + rows=shape, + cols=shape, + val=1.0, ) self.declare_partials( - "pylon_mass", + 'pylon_mass', [ Aircraft.Nacelle.MASS_SPECIFIC, Aircraft.Nacelle.SURFACE_AREA, @@ -707,7 +665,9 @@ def setup(self): Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST, ], - rows=shape, cols=shape, val=1.0 + rows=shape, + cols=shape, + val=1.0, ) self.declare_partials( @@ -721,18 +681,19 @@ def setup(self): ], ) self.declare_partials( - Aircraft.Engine.ADDITIONAL_MASS, [Aircraft.Engine.ADDITIONAL_MASS_FRACTION, - Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST], - rows=shape, cols=shape, val=1.0 + Aircraft.Engine.ADDITIONAL_MASS, + [Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST], + rows=shape, + cols=shape, + val=1.0, ) self.declare_partials( - "wing_mounted_mass", + 'wing_mounted_mass', [ Aircraft.Engine.WING_LOCATIONS, Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST, - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, Aircraft.Nacelle.MASS_SPECIFIC, Aircraft.Nacelle.SURFACE_AREA, Aircraft.Engine.PYLON_FACTOR, @@ -742,40 +703,36 @@ def setup(self): ) if not has_hybrid_system: self.declare_partials( - "eng_comb_mass", + 'eng_comb_mass', [ Aircraft.Engine.MASS_SCALER, Aircraft.Propulsion.MISC_MASS_SCALER, - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST, ], ) else: self.declare_partials( - "eng_comb_mass", + 'eng_comb_mass', [ Aircraft.Engine.MASS_SCALER, Aircraft.Propulsion.MISC_MASS_SCALER, - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, Aircraft.Engine.MASS_SPECIFIC, Aircraft.Engine.SCALED_SLS_THRUST, - "aug_mass", + 'aug_mass', ], ) def compute(self, inputs, outputs): - aviary_options = self.options['aviary_options'] - num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + num_engine_type = len(num_engines) + c_instl = self.options[Aircraft.Engine.ADDITIONAL_MASS_FRACTION] + eng_spec_wt = inputs[Aircraft.Engine.MASS_SPECIFIC] * GRAV_ENGLISH_LBM Fn_SLS = inputs[Aircraft.Engine.SCALED_SLS_THRUST] - num_engines = aviary_options.get_val( - Aircraft.Engine.NUM_ENGINES, units='unitless') - spec_nacelle_wt = inputs[Aircraft.Nacelle.MASS_SPECIFIC] * GRAV_ENGLISH_LBM nacelle_area = inputs[Aircraft.Nacelle.SURFACE_AREA] pylon_fac = inputs[Aircraft.Engine.PYLON_FACTOR] - c_instl = inputs[Aircraft.Engine.ADDITIONAL_MASS_FRACTION] CK5 = inputs[Aircraft.Engine.MASS_SCALER] CK7 = inputs[Aircraft.Propulsion.MISC_MASS_SCALER] eng_span_frac = inputs[Aircraft.Engine.WING_LOCATIONS] @@ -786,60 +743,65 @@ def compute(self, inputs, outputs): dry_wt_eng_all = sum(dry_wt_eng * num_engines) nacelle_wt = spec_nacelle_wt * nacelle_area pylon_wt = pylon_fac * ((dry_wt_eng + nacelle_wt) ** 0.736) - pod_wt = (nacelle_wt + pylon_wt) + pod_wt = nacelle_wt + pylon_wt # sec_wt_all = sum((nacelle_wt + pylon_wt) * num_engines) + # In GASP, WPEI = SKPEI * (WEP + ENP*WTGB), even though WTGB = 0. eng_instl_wt = c_instl * dry_wt_eng eng_instl_wt_all = sum(eng_instl_wt * num_engines) outputs[Aircraft.Propulsion.TOTAL_ENGINE_MASS] = dry_wt_eng_all / GRAV_ENGLISH_LBM outputs[Aircraft.Nacelle.MASS] = nacelle_wt / GRAV_ENGLISH_LBM outputs['pylon_mass'] = pylon_wt / GRAV_ENGLISH_LBM - outputs[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS] = sum( - pod_wt * num_engines) / GRAV_ENGLISH_LBM + outputs[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS] = ( + sum(pod_wt * num_engines) / GRAV_ENGLISH_LBM + ) outputs[Aircraft.Engine.ADDITIONAL_MASS] = eng_instl_wt / GRAV_ENGLISH_LBM - outputs["eng_comb_mass"] = (sum( - CK5 * dry_wt_eng * num_engines) + CK7 * eng_instl_wt_all) / GRAV_ENGLISH_LBM + # In GASP, WPSTAR=CK5*WEP+CK7*WPEI+WPROP+WTGB*ENP, even though the last two terms are 0. + outputs['eng_comb_mass'] = ( + sum(CK5 * dry_wt_eng * num_engines) + CK7 * eng_instl_wt_all + ) / GRAV_ENGLISH_LBM - if aviary_options.get_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, units='unitless' - ): - aug_wt = inputs["aug_mass"] * GRAV_ENGLISH_LBM - outputs["eng_comb_mass"] = (sum(CK5 * dry_wt_eng * num_engines) + - CK7 * eng_instl_wt_all + aug_wt) / GRAV_ENGLISH_LBM + if self.options[Aircraft.Electrical.HAS_HYBRID_SYSTEM]: + aug_wt = inputs['aug_mass'] * GRAV_ENGLISH_LBM + outputs['eng_comb_mass'] = ( + sum(CK5 * dry_wt_eng * num_engines) + CK7 * eng_instl_wt_all + aug_wt + ) / GRAV_ENGLISH_LBM # prop_wt = np.zeros(num_engine_type) - # prop_idx = np.where(aviary_options.get_val(Aircraft.Engine.HAS_PROPELLERS)) - # prop_wt[prop_idx] = inputs["prop_mass"] * GRAV_ENGLISH_LBM - prop_wt = inputs["prop_mass"] * GRAV_ENGLISH_LBM - outputs["prop_mass_all"] = sum(num_engines * prop_wt) / GRAV_ENGLISH_LBM + # prop_idx = np.where(self.options[Aircraft.Engine.HAS_PROPELLERS)) + # prop_wt[prop_idx] = inputs['prop_mass'] * GRAV_ENGLISH_LBM + prop_wt = inputs['prop_mass'] * GRAV_ENGLISH_LBM + outputs['prop_mass_all'] = sum(num_engines * prop_wt) / GRAV_ENGLISH_LBM span_frac_factor = eng_span_frac / (eng_span_frac + 0.001) # sum span_frac_factor for each engine type span_frac_factor_sum = np.zeros(num_engine_type, dtype=Fn_SLS.dtype) idx = 0 for i in range(num_engine_type): - span_frac_factor_sum[i] = sum(span_frac_factor[idx:idx+num_engines[i]]) + # fmt: off + span_frac_factor_sum[i] = sum(span_frac_factor[idx : idx + num_engines[i]]) + # fmt: on idx = idx + num_engines[i] - outputs["wing_mounted_mass"] = (sum(span_frac_factor_sum * ( - dry_wt_eng + eng_instl_wt + pod_wt + prop_wt) * num_engines - ) + main_gear_wt * loc_main_gear / (loc_main_gear + 0.001)) / GRAV_ENGLISH_LBM + # In GASP, + # WM = YP/(YP+.001)*(WEP+WPEI+WPES+WPROP+ENP*WTGB) + # + WMG*YMG/(YMG+.001) + # + WCMIN*YC/(YC+.001) + outputs['wing_mounted_mass'] = ( + sum(span_frac_factor_sum * (dry_wt_eng + eng_instl_wt + pod_wt + prop_wt) * num_engines) + + main_gear_wt * loc_main_gear / (loc_main_gear + 0.001) + ) / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options['aviary_options'] - num_engine_type = len(aviary_options.get_val(Aircraft.Engine.NUM_ENGINES)) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + num_engine_type = len(num_engines) + c_instl = self.options[Aircraft.Engine.ADDITIONAL_MASS_FRACTION] eng_spec_wt = inputs[Aircraft.Engine.MASS_SPECIFIC] * GRAV_ENGLISH_LBM Fn_SLS = inputs[Aircraft.Engine.SCALED_SLS_THRUST] - num_engines = self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES, units='unitless') - total_num_engines = self.options['aviary_options'].get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') - spec_nacelle_wt = inputs[Aircraft.Nacelle.MASS_SPECIFIC] * GRAV_ENGLISH_LBM nacelle_area = inputs[Aircraft.Nacelle.SURFACE_AREA] pylon_fac = inputs[Aircraft.Engine.PYLON_FACTOR] - c_instl = inputs[Aircraft.Engine.ADDITIONAL_MASS_FRACTION] CK5 = inputs[Aircraft.Engine.MASS_SCALER] CK7 = inputs[Aircraft.Propulsion.MISC_MASS_SCALER] eng_span_frac = inputs[Aircraft.Engine.WING_LOCATIONS] @@ -849,82 +811,92 @@ def compute_partials(self, inputs, J): dDWEA_dESW = num_engines * Fn_SLS dDWEA_dFNSLS = num_engines * eng_spec_wt dNW_dNWS = nacelle_area - dPW_dNWS = 0.736 * pylon_fac * \ - (eng_spec_wt * Fn_SLS + spec_nacelle_wt * - nacelle_area) ** (-0.264) * nacelle_area + dPW_dNWS = ( + 0.736 + * pylon_fac + * (eng_spec_wt * Fn_SLS + spec_nacelle_wt * nacelle_area) ** (-0.264) + * nacelle_area + ) dNW_dNSA = spec_nacelle_wt - dPW_dNSA = 0.736 * pylon_fac * \ - (eng_spec_wt * Fn_SLS + spec_nacelle_wt * - nacelle_area) ** (-0.264) * spec_nacelle_wt + dPW_dNSA = ( + 0.736 + * pylon_fac + * (eng_spec_wt * Fn_SLS + spec_nacelle_wt * nacelle_area) ** (-0.264) + * spec_nacelle_wt + ) dPW_dPF = (eng_spec_wt * Fn_SLS + spec_nacelle_wt * nacelle_area) ** 0.736 - dPW_dEWS = 0.736 * pylon_fac * \ - (eng_spec_wt * Fn_SLS + spec_nacelle_wt * nacelle_area) ** (-0.264) * Fn_SLS - dPW_dSLST = (pylon_fac * 0.736 * (eng_spec_wt * Fn_SLS + - spec_nacelle_wt * nacelle_area) ** (-0.264) * eng_spec_wt) - - J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, - Aircraft.Engine.MASS_SPECIFIC] = dDWEA_dESW - J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, - Aircraft.Engine.SCALED_SLS_THRUST] = dDWEA_dFNSLS / GRAV_ENGLISH_LBM - - J[Aircraft.Nacelle.MASS, - Aircraft.Nacelle.MASS_SPECIFIC] = dNW_dNWS - J["pylon_mass", - Aircraft.Nacelle.MASS_SPECIFIC] = dPW_dNWS - J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, - Aircraft.Nacelle.MASS_SPECIFIC] = num_engines * (dNW_dNWS + dPW_dNWS) - J[Aircraft.Nacelle.MASS, - Aircraft.Nacelle.SURFACE_AREA] = dNW_dNSA / GRAV_ENGLISH_LBM - J["pylon_mass", - Aircraft.Nacelle.SURFACE_AREA] = dPW_dNSA / GRAV_ENGLISH_LBM - J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, - Aircraft.Nacelle.SURFACE_AREA] = num_engines * (dNW_dNSA + dPW_dNSA) / GRAV_ENGLISH_LBM - J["pylon_mass", - Aircraft.Engine.PYLON_FACTOR] = dPW_dPF / GRAV_ENGLISH_LBM - J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, - Aircraft.Engine.PYLON_FACTOR] = num_engines * dPW_dPF / GRAV_ENGLISH_LBM - J["pylon_mass", - Aircraft.Engine.MASS_SPECIFIC] = dPW_dEWS - J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, - Aircraft.Engine.MASS_SPECIFIC] = num_engines * dPW_dEWS - J["pylon_mass", - Aircraft.Engine.SCALED_SLS_THRUST] = dPW_dSLST / GRAV_ENGLISH_LBM - J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, - Aircraft.Engine.SCALED_SLS_THRUST] = num_engines * dPW_dSLST / GRAV_ENGLISH_LBM - - J[Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Engine.ADDITIONAL_MASS_FRACTION] = eng_spec_wt * Fn_SLS / GRAV_ENGLISH_LBM - J[Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Engine.MASS_SPECIFIC] = c_instl * Fn_SLS - J[Aircraft.Engine.ADDITIONAL_MASS, - Aircraft.Engine.SCALED_SLS_THRUST] = c_instl * eng_spec_wt / GRAV_ENGLISH_LBM - - J["eng_comb_mass", Aircraft.Engine.MASS_SCALER] = eng_spec_wt * \ - Fn_SLS * num_engines / GRAV_ENGLISH_LBM - J["eng_comb_mass", Aircraft.Propulsion.MISC_MASS_SCALER] = sum( - c_instl * eng_spec_wt * Fn_SLS * num_engines) / GRAV_ENGLISH_LBM - J["eng_comb_mass", Aircraft.Engine.ADDITIONAL_MASS_FRACTION] = eng_spec_wt * \ - CK7 * Fn_SLS * num_engines / GRAV_ENGLISH_LBM - J["eng_comb_mass", Aircraft.Engine.MASS_SPECIFIC] = ( - CK5 + CK7 * c_instl) * num_engines * Fn_SLS - J["eng_comb_mass", Aircraft.Engine.SCALED_SLS_THRUST] = ( - CK5 + CK7 * c_instl) * num_engines * eng_spec_wt / GRAV_ENGLISH_LBM + dPW_dEWS = ( + 0.736 + * pylon_fac + * (eng_spec_wt * Fn_SLS + spec_nacelle_wt * nacelle_area) ** (-0.264) + * Fn_SLS + ) + dPW_dSLST = ( + pylon_fac + * 0.736 + * (eng_spec_wt * Fn_SLS + spec_nacelle_wt * nacelle_area) ** (-0.264) + * eng_spec_wt + ) + + J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, Aircraft.Engine.MASS_SPECIFIC] = dDWEA_dESW + J[Aircraft.Propulsion.TOTAL_ENGINE_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + dDWEA_dFNSLS / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.MASS_SPECIFIC] = dNW_dNWS + J['pylon_mass', Aircraft.Nacelle.MASS_SPECIFIC] = dPW_dNWS + J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, Aircraft.Nacelle.MASS_SPECIFIC] = ( + num_engines * (dNW_dNWS + dPW_dNWS) + ) + J[Aircraft.Nacelle.MASS, Aircraft.Nacelle.SURFACE_AREA] = dNW_dNSA / GRAV_ENGLISH_LBM + J['pylon_mass', Aircraft.Nacelle.SURFACE_AREA] = dPW_dNSA / GRAV_ENGLISH_LBM + J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, Aircraft.Nacelle.SURFACE_AREA] = ( + num_engines * (dNW_dNSA + dPW_dNSA) / GRAV_ENGLISH_LBM + ) + J['pylon_mass', Aircraft.Engine.PYLON_FACTOR] = dPW_dPF / GRAV_ENGLISH_LBM + J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, Aircraft.Engine.PYLON_FACTOR] = ( + num_engines * dPW_dPF / GRAV_ENGLISH_LBM + ) + J['pylon_mass', Aircraft.Engine.MASS_SPECIFIC] = dPW_dEWS + J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, Aircraft.Engine.MASS_SPECIFIC] = ( + num_engines * dPW_dEWS + ) + J['pylon_mass', Aircraft.Engine.SCALED_SLS_THRUST] = dPW_dSLST / GRAV_ENGLISH_LBM + J[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + num_engines * dPW_dSLST / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Engine.ADDITIONAL_MASS, Aircraft.Engine.MASS_SPECIFIC] = c_instl * Fn_SLS + J[Aircraft.Engine.ADDITIONAL_MASS, Aircraft.Engine.SCALED_SLS_THRUST] = ( + c_instl * eng_spec_wt / GRAV_ENGLISH_LBM + ) + + J['eng_comb_mass', Aircraft.Engine.MASS_SCALER] = ( + eng_spec_wt * Fn_SLS * num_engines / GRAV_ENGLISH_LBM + ) + J['eng_comb_mass', Aircraft.Propulsion.MISC_MASS_SCALER] = ( + sum(c_instl * eng_spec_wt * Fn_SLS * num_engines) / GRAV_ENGLISH_LBM + ) + J['eng_comb_mass', Aircraft.Engine.MASS_SPECIFIC] = ( + (CK5 + CK7 * c_instl) * num_engines * Fn_SLS + ) + J['eng_comb_mass', Aircraft.Engine.SCALED_SLS_THRUST] = ( + (CK5 + CK7 * c_instl) * num_engines * eng_spec_wt / GRAV_ENGLISH_LBM + ) dry_wt_eng = eng_spec_wt * Fn_SLS nacelle_wt = spec_nacelle_wt * nacelle_area pylon_wt = pylon_fac * ((dry_wt_eng + nacelle_wt) ** 0.736) - pod_wt = (nacelle_wt + pylon_wt) + pod_wt = nacelle_wt + pylon_wt eng_instl_wt = c_instl * dry_wt_eng - # prop_idx = np.where(aviary_options.get_val(Aircraft.Engine.HAS_PROPELLERS)) - prop_wt = inputs["prop_mass"] * GRAV_ENGLISH_LBM + # prop_idx = np.where(self.options[Aircraft.Engine.HAS_PROPELLERS)) + prop_wt = inputs['prop_mass'] * GRAV_ENGLISH_LBM # prop_wt_all = sum(num_engines * prop_wt) / GRAV_ENGLISH_LBM - J["prop_mass_all", "prop_mass"] = num_engines + J['prop_mass_all', 'prop_mass'] = num_engines - dPylonWt_dFnSLS = ( - pylon_fac * 0.736 * (dry_wt_eng + nacelle_wt) ** (0.736 - 1) * eng_spec_wt - ) + dPylonWt_dFnSLS = pylon_fac * 0.736 * (dry_wt_eng + nacelle_wt) ** (0.736 - 1) * eng_spec_wt dPylonWt_dEngSpecWt = ( pylon_fac * 0.736 * ((dry_wt_eng + nacelle_wt) ** (0.736 - 1) * Fn_SLS) ) @@ -938,89 +910,112 @@ def compute_partials(self, inputs, J): # sec_wt + prop_wt) * num_engines wing_mass_vec = (dry_wt_eng + eng_instl_wt + pod_wt + prop_wt) * num_engines for i in range(num_engine_type): - span_frac_factor_sum[i] = sum(span_frac_factor[idx:idx+num_engines[i]]) - wing_mass_deriv[idx:idx+num_engines[i]] = wing_mass_vec[i] + span_frac_factor_sum[i] = sum(span_frac_factor[idx : idx + num_engines[i]]) + wing_mass_deriv[idx : idx + num_engines[i]] = wing_mass_vec[i] idx = idx + num_engines[i] - J["wing_mounted_mass", Aircraft.Engine.WING_LOCATIONS] = 0.001 \ - / (eng_span_frac + 0.001) ** 2 * wing_mass_deriv / GRAV_ENGLISH_LBM - - J["wing_mounted_mass", Aircraft.Engine.MASS_SPECIFIC] = span_frac_factor_sum \ - * (Fn_SLS + c_instl * Fn_SLS + dPylonWt_dEngSpecWt) * num_engines + J['wing_mounted_mass', Aircraft.Engine.WING_LOCATIONS] = ( + 0.001 / (eng_span_frac + 0.001) ** 2 * wing_mass_deriv / GRAV_ENGLISH_LBM + ) - J["wing_mounted_mass", Aircraft.Engine.SCALED_SLS_THRUST] = span_frac_factor_sum \ - * (num_engines * eng_spec_wt + c_instl * num_engines * eng_spec_wt + dPylonWt_dFnSLS * num_engines) / GRAV_ENGLISH_LBM + J['wing_mounted_mass', Aircraft.Engine.MASS_SPECIFIC] = ( + span_frac_factor_sum * (Fn_SLS + c_instl * Fn_SLS + dPylonWt_dEngSpecWt) * num_engines + ) - J["wing_mounted_mass", Aircraft.Engine.ADDITIONAL_MASS_FRACTION] = span_frac_factor_sum \ - * (eng_spec_wt * Fn_SLS * num_engines) / GRAV_ENGLISH_LBM + J['wing_mounted_mass', Aircraft.Engine.SCALED_SLS_THRUST] = ( + span_frac_factor_sum + * ( + num_engines * eng_spec_wt + + c_instl * num_engines * eng_spec_wt + + dPylonWt_dFnSLS * num_engines + ) + / GRAV_ENGLISH_LBM + ) - J["wing_mounted_mass", Aircraft.Nacelle.MASS_SPECIFIC] = (span_frac_factor_sum * num_engines - * (nacelle_area + pylon_fac * 0.736 * ((dry_wt_eng + spec_nacelle_wt * nacelle_area) ** (0.736 - 1) * nacelle_area))) + J['wing_mounted_mass', Aircraft.Nacelle.MASS_SPECIFIC] = ( + span_frac_factor_sum + * num_engines + * ( + nacelle_area + + pylon_fac + * 0.736 + * ((dry_wt_eng + spec_nacelle_wt * nacelle_area) ** (0.736 - 1) * nacelle_area) + ) + ) - J["wing_mounted_mass", Aircraft.Nacelle.SURFACE_AREA] = (span_frac_factor_sum * num_engines - * (spec_nacelle_wt + pylon_fac * 0.736 * ((dry_wt_eng + spec_nacelle_wt * nacelle_area) ** (0.736 - 1) * spec_nacelle_wt))) / GRAV_ENGLISH_LBM + J['wing_mounted_mass', Aircraft.Nacelle.SURFACE_AREA] = ( + span_frac_factor_sum + * num_engines + * ( + spec_nacelle_wt + + pylon_fac + * 0.736 + * ((dry_wt_eng + spec_nacelle_wt * nacelle_area) ** (0.736 - 1) * spec_nacelle_wt) + ) + ) / GRAV_ENGLISH_LBM - J["wing_mounted_mass", Aircraft.Engine.PYLON_FACTOR] = ( - span_frac_factor_sum * num_engines * (((dry_wt_eng + spec_nacelle_wt * nacelle_area) ** 0.736))) / GRAV_ENGLISH_LBM + J['wing_mounted_mass', Aircraft.Engine.PYLON_FACTOR] = ( + span_frac_factor_sum + * num_engines + * ((dry_wt_eng + spec_nacelle_wt * nacelle_area) ** 0.736) + ) / GRAV_ENGLISH_LBM - J["wing_mounted_mass", Aircraft.LandingGear.MAIN_GEAR_MASS] = loc_main_gear / \ - (loc_main_gear + 0.001) + J['wing_mounted_mass', Aircraft.LandingGear.MAIN_GEAR_MASS] = loc_main_gear / ( + loc_main_gear + 0.001 + ) - J["wing_mounted_mass", Aircraft.LandingGear.MAIN_GEAR_LOCATION] = ( - main_gear_wt / GRAV_ENGLISH_LBM * ((loc_main_gear + 0.001) - loc_main_gear) / (loc_main_gear + 0.001) ** 2) + J['wing_mounted_mass', Aircraft.LandingGear.MAIN_GEAR_LOCATION] = ( + main_gear_wt + / GRAV_ENGLISH_LBM + * ((loc_main_gear + 0.001) - loc_main_gear) + / (loc_main_gear + 0.001) ** 2 + ) - J["wing_mounted_mass", "prop_mass"] = span_frac_factor_sum * num_engines + J['wing_mounted_mass', 'prop_mass'] = span_frac_factor_sum * num_engines - if self.options["aviary_options"].get_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, units='unitless'): - J["eng_comb_mass", "aug_mass"] = 1 + if self.options[Aircraft.Electrical.HAS_HYBRID_SYSTEM]: + J['eng_comb_mass', 'aug_mass'] = 1 class TailMass(om.ExplicitComponent): - """ - Computation of horizontal tail mass and vertical tail mass. - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + """Computation of horizontal tail mass and vertical tail mass.""" def setup(self): - add_aviary_input(self, Aircraft.VerticalTail.TAPER_RATIO, val=0.801) - add_aviary_input(self, Aircraft.VerticalTail.ASPECT_RATIO, val=1.67) - add_aviary_input(self, Aircraft.VerticalTail.SWEEP, val=0.1, units="rad") - add_aviary_input(self, Aircraft.VerticalTail.SPAN, val=5) - add_aviary_input(self, Mission.Design.GROSS_MASS, val=152000) - add_aviary_input(self, Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232) - add_aviary_input(self, Aircraft.Fuselage.LENGTH, val=200) - add_aviary_input(self, Aircraft.HorizontalTail.SPAN, val=7) - add_aviary_input(self, Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.HorizontalTail.TAPER_RATIO, val=0.352) - add_aviary_input(self, Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289) - add_aviary_input(self, Aircraft.Wing.SPAN, val=118) - add_aviary_input(self, Aircraft.HorizontalTail.AREA, val=15) - self.add_input("min_dive_vel", val=200, units="kn", desc="VDMIN: dive velocity") - add_aviary_input(self, Aircraft.HorizontalTail.MOMENT_ARM, val=20) - add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.11) - add_aviary_input(self, Aircraft.HorizontalTail.ROOT_CHORD, val=2) - add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0) - add_aviary_input(self, Aircraft.VerticalTail.AREA, val=20) - add_aviary_input(self, Aircraft.VerticalTail.MOMENT_ARM, val=20) - add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=200) - add_aviary_input(self, Aircraft.VerticalTail.ROOT_CHORD, val=0.12) + add_aviary_input(self, Aircraft.VerticalTail.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.ASPECT_RATIO, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.SWEEP, units='rad') + add_aviary_input(self, Aircraft.VerticalTail.SPAN, units='ft') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.HorizontalTail.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.LENGTH, units='ft') + add_aviary_input(self, Aircraft.HorizontalTail.SPAN, units='ft') + add_aviary_input(self, Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.HorizontalTail.AREA, units='ft**2') + self.add_input('min_dive_vel', val=200, units='kn', desc='VDMIN: dive velocity') + add_aviary_input(self, Aircraft.HorizontalTail.MOMENT_ARM, units='ft') + add_aviary_input(self, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.ROOT_CHORD, units='ft') + add_aviary_input(self, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.AREA, units='ft**2') + add_aviary_input(self, Aircraft.VerticalTail.MOMENT_ARM, units='ft') + add_aviary_input(self, Aircraft.VerticalTail.THICKNESS_TO_CHORD, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.ROOT_CHORD, units='ft') self.add_output( - "loc_MAC_vtail", + 'loc_MAC_vtail', val=0, - units="ft", - desc="XVMAC: location of mean aerodynamic chord on the vertical tail", + units='ft', + desc='XVMAC: location of mean aerodynamic chord on the vertical tail', ) - add_aviary_output(self, Aircraft.HorizontalTail.MASS, val=0) - add_aviary_output(self, Aircraft.VerticalTail.MASS, val=0) + add_aviary_output(self, Aircraft.HorizontalTail.MASS, units='lbm') + add_aviary_output(self, Aircraft.VerticalTail.MASS, units='lbm') + def setup_partials(self): self.declare_partials( - "loc_MAC_vtail", + 'loc_MAC_vtail', [ Aircraft.VerticalTail.SPAN, Aircraft.VerticalTail.TAPER_RATIO, @@ -1038,7 +1033,7 @@ def setup(self): Aircraft.HorizontalTail.SPAN, Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, Aircraft.HorizontalTail.TAPER_RATIO, - "min_dive_vel", + 'min_dive_vel', Aircraft.HorizontalTail.MOMENT_ARM, Aircraft.HorizontalTail.THICKNESS_TO_CHORD, Aircraft.HorizontalTail.ROOT_CHORD, @@ -1059,7 +1054,7 @@ def setup(self): Aircraft.HorizontalTail.TAPER_RATIO, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, Aircraft.VerticalTail.AREA, - "min_dive_vel", + 'min_dive_vel', Aircraft.VerticalTail.MOMENT_ARM, Aircraft.VerticalTail.THICKNESS_TO_CHORD, Aircraft.VerticalTail.ROOT_CHORD, @@ -1080,7 +1075,7 @@ def compute(self, inputs, outputs): coef_vtail = inputs[Aircraft.VerticalTail.MASS_COEFFICIENT] wingspan = inputs[Aircraft.Wing.SPAN] htail_area = inputs[Aircraft.HorizontalTail.AREA] - min_dive_vel = inputs["min_dive_vel"] + min_dive_vel = inputs['min_dive_vel'] htail_mom_arm = inputs[Aircraft.HorizontalTail.MOMENT_ARM] tc_ratio_root_htail = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] root_chord_htail = inputs[Aircraft.HorizontalTail.ROOT_CHORD] @@ -1111,7 +1106,7 @@ def compute(self, inputs, outputs): / (1000000.0 * (1.0 + taper_ratio_vtail)) ) / 2 - outputs["loc_MAC_vtail"] = ( + outputs['loc_MAC_vtail'] = ( span_vtail * tan_sweep_vtail_LE * (1.0 + 2.0 * taper_ratio_vtail) @@ -1119,7 +1114,8 @@ def compute(self, inputs, outputs): / (1.0 + taper_ratio_vtail) ) outputs[Aircraft.HorizontalTail.MASS] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * ( htail_area * FH @@ -1129,7 +1125,8 @@ def compute(self, inputs, outputs): ** 0.54 ) outputs[Aircraft.VerticalTail.MASS] = ( - 380.0 / GRAV_ENGLISH_LBM + 380.0 + / GRAV_ENGLISH_LBM * ( (FV + htail_loc * FH / 2.0) * vtail_area @@ -1153,7 +1150,7 @@ def compute_partials(self, inputs, J): coef_vtail = inputs[Aircraft.VerticalTail.MASS_COEFFICIENT] wingspan = inputs[Aircraft.Wing.SPAN] htail_area = inputs[Aircraft.HorizontalTail.AREA] - min_dive_vel = inputs["min_dive_vel"] + min_dive_vel = inputs['min_dive_vel'] htail_mom_arm = inputs[Aircraft.HorizontalTail.MOMENT_ARM] tc_ratio_root_htail = inputs[Aircraft.HorizontalTail.THICKNESS_TO_CHORD] root_chord_htail = inputs[Aircraft.HorizontalTail.ROOT_CHORD] @@ -1185,8 +1182,7 @@ def compute_partials(self, inputs, J): ) / 2 dTanSweepVtailLE_dTaperRatioVtail = ( - -((1.0 + taper_ratio_vtail) * AR_vtail * 2.0) - - (1.0 - taper_ratio_vtail) * 2 * AR_vtail + -((1.0 + taper_ratio_vtail) * AR_vtail * 2.0) - (1.0 - taper_ratio_vtail) * 2 * AR_vtail ) / ((1.0 + taper_ratio_vtail) * AR_vtail * 2.0) ** 2 dTanSweepVtailLE_dARVtail = ( -(1.0 - taper_ratio_vtail) @@ -1296,29 +1292,26 @@ def compute_partials(self, inputs, J): / (2 * 1000000.0 * (1.0 + taper_ratio_vtail)) ** 2 ) - temp = ( - (3.0 * (1.0 + taper_ratio_vtail)) * 2 - (1.0 + 2.0 * taper_ratio_vtail) * 3 - ) / (3.0 * (1.0 + taper_ratio_vtail)) ** 2 + temp = ((3.0 * (1.0 + taper_ratio_vtail)) * 2 - (1.0 + 2.0 * taper_ratio_vtail) * 3) / ( + 3.0 * (1.0 + taper_ratio_vtail) + ) ** 2 - J["loc_MAC_vtail", Aircraft.VerticalTail.SPAN] = ( - tan_sweep_vtail_LE - * (1.0 + 2.0 * taper_ratio_vtail) - / 3.0 - / (1.0 + taper_ratio_vtail) + J['loc_MAC_vtail', Aircraft.VerticalTail.SPAN] = ( + tan_sweep_vtail_LE * (1.0 + 2.0 * taper_ratio_vtail) / 3.0 / (1.0 + taper_ratio_vtail) ) - J["loc_MAC_vtail", Aircraft.VerticalTail.TAPER_RATIO] = span_vtail * ( + J['loc_MAC_vtail', Aircraft.VerticalTail.TAPER_RATIO] = span_vtail * ( dTanSweepVtailLE_dTaperRatioVtail * (1.0 + 2.0 * taper_ratio_vtail) / (3.0 * (1.0 + taper_ratio_vtail)) + tan_sweep_vtail_LE * temp ) - J["loc_MAC_vtail", Aircraft.VerticalTail.ASPECT_RATIO] = ( + J['loc_MAC_vtail', Aircraft.VerticalTail.ASPECT_RATIO] = ( dTanSweepVtailLE_dARVtail * span_vtail * (1.0 + 2.0 * taper_ratio_vtail) / (3.0 * (1.0 + taper_ratio_vtail)) ) - J["loc_MAC_vtail", Aircraft.VerticalTail.SWEEP] = ( + J['loc_MAC_vtail', Aircraft.VerticalTail.SWEEP] = ( dTanSweepVtailLE_dQuarterSweepTail * span_vtail * (1.0 + 2.0 * taper_ratio_vtail) @@ -1326,7 +1319,8 @@ def compute_partials(self, inputs, J): ) J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.AREA] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * 0.54 * ( FH @@ -1349,7 +1343,8 @@ def compute_partials(self, inputs, J): * dFH_dGrossWtInitial ) J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.MASS_COEFFICIENT] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * 0.54 * ( htail_area @@ -1361,7 +1356,8 @@ def compute_partials(self, inputs, J): * dFH_dCoefHtail ) J[Aircraft.HorizontalTail.MASS, Aircraft.Fuselage.LENGTH] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * 0.54 * ( htail_area @@ -1373,7 +1369,8 @@ def compute_partials(self, inputs, J): * dFH_dFusLen ) J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.SPAN] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * 0.54 * ( htail_area @@ -1385,7 +1382,8 @@ def compute_partials(self, inputs, J): * dFH_dSpanHtail ) J[Aircraft.HorizontalTail.MASS, Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * 0.54 * ( htail_area @@ -1397,7 +1395,8 @@ def compute_partials(self, inputs, J): * dFH_dHookFac ) J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.TAPER_RATIO] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * 0.54 * ( htail_area @@ -1408,20 +1407,18 @@ def compute_partials(self, inputs, J): * FH ** (-0.46) * dFH_dTaperRatioHtail ) - J[Aircraft.HorizontalTail.MASS, "min_dive_vel"] = ( - 350.0 / GRAV_ENGLISH_LBM + J[Aircraft.HorizontalTail.MASS, 'min_dive_vel'] = ( + 350.0 + / GRAV_ENGLISH_LBM * 0.54 - * ( - htail_area - * FH - / (100.0 * htail_mom_arm * tc_ratio_root_htail * root_chord_htail) - ) + * (htail_area * FH / (100.0 * htail_mom_arm * tc_ratio_root_htail * root_chord_htail)) ** 0.54 * (np.log10(min_dive_vel)) ** (-0.46) / (min_dive_vel * np.log(10)) ) J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.MOMENT_ARM] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * ( htail_area * FH @@ -1433,7 +1430,8 @@ def compute_partials(self, inputs, J): * htail_mom_arm ** (-1.54) ) J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.THICKNESS_TO_CHORD] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * ( htail_area * FH @@ -1445,7 +1443,8 @@ def compute_partials(self, inputs, J): * tc_ratio_root_htail ** (-1.54) ) J[Aircraft.HorizontalTail.MASS, Aircraft.HorizontalTail.ROOT_CHORD] = ( - 350.0 / GRAV_ENGLISH_LBM + 350.0 + / GRAV_ENGLISH_LBM * ( htail_area * FH @@ -1474,29 +1473,31 @@ def compute_partials(self, inputs, J): * (dFV_dGrossWtInitial + htail_loc * dFH_dGrossWtInitial / 2) ) J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.MASS_COEFFICIENT] = ( - temp * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * - dFV_dCoefVtail / GRAV_ENGLISH_LBM + temp * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * dFV_dCoefVtail / GRAV_ENGLISH_LBM ) J[Aircraft.VerticalTail.MASS, Aircraft.Fuselage.LENGTH] = ( - temp / GRAV_ENGLISH_LBM + temp + / GRAV_ENGLISH_LBM * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * (dFV_dFusLen + htail_loc * dFH_dFusLen / 2) ) J[Aircraft.VerticalTail.MASS, Aircraft.Wing.SPAN] = ( - temp * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * - dFV_dWingspan / GRAV_ENGLISH_LBM + temp * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * dFV_dWingspan / GRAV_ENGLISH_LBM ) J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.SPAN] = ( - temp * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * - dFV_dSpanVtail / GRAV_ENGLISH_LBM + temp * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * dFV_dSpanVtail / GRAV_ENGLISH_LBM ) J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.TAPER_RATIO] = ( - temp * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * - dFV_dTaperRatioVtail / GRAV_ENGLISH_LBM + temp + * 0.54 + * (FV + htail_loc * FH / 2.0) ** (-0.46) + * dFV_dTaperRatioVtail + / GRAV_ENGLISH_LBM ) J[Aircraft.VerticalTail.MASS, Aircraft.HorizontalTail.MASS_COEFFICIENT] = ( - temp / GRAV_ENGLISH_LBM + temp + / GRAV_ENGLISH_LBM * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * dFH_dCoefHtail @@ -1504,7 +1505,8 @@ def compute_partials(self, inputs, J): / 2 ) J[Aircraft.VerticalTail.MASS, Aircraft.HorizontalTail.SPAN] = ( - temp / GRAV_ENGLISH_LBM + temp + / GRAV_ENGLISH_LBM * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * dFH_dSpanHtail @@ -1512,7 +1514,8 @@ def compute_partials(self, inputs, J): / 2 ) J[Aircraft.VerticalTail.MASS, Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER] = ( - temp / GRAV_ENGLISH_LBM + temp + / GRAV_ENGLISH_LBM * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * dFH_dHookFac @@ -1520,7 +1523,8 @@ def compute_partials(self, inputs, J): / 2 ) J[Aircraft.VerticalTail.MASS, Aircraft.HorizontalTail.TAPER_RATIO] = ( - temp / GRAV_ENGLISH_LBM + temp + / GRAV_ENGLISH_LBM * 0.54 * (FV + htail_loc * FH / 2.0) ** (-0.46) * dFH_dTaperRatioHtail @@ -1528,7 +1532,8 @@ def compute_partials(self, inputs, J): / 2 ) J[Aircraft.VerticalTail.MASS, Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION] = ( - 380.0 / GRAV_ENGLISH_LBM + 380.0 + / GRAV_ENGLISH_LBM * ( vtail_area * np.log10(min_dive_vel) @@ -1541,7 +1546,8 @@ def compute_partials(self, inputs, J): / 2 ) J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.AREA] = ( - 380.0 / GRAV_ENGLISH_LBM + 380.0 + / GRAV_ENGLISH_LBM * ( (FV + htail_loc * FH / 2.0) * np.log10(min_dive_vel) @@ -1551,8 +1557,9 @@ def compute_partials(self, inputs, J): * 0.54 * vtail_area ** (-0.46) ) - J[Aircraft.VerticalTail.MASS, "min_dive_vel"] = ( - 380.0 / GRAV_ENGLISH_LBM + J[Aircraft.VerticalTail.MASS, 'min_dive_vel'] = ( + 380.0 + / GRAV_ENGLISH_LBM * ( (FV + htail_loc * FH / 2.0) * vtail_area @@ -1564,7 +1571,8 @@ def compute_partials(self, inputs, J): / (min_dive_vel * np.log(10)) ) J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.MOMENT_ARM] = ( - 380.0 / GRAV_ENGLISH_LBM + 380.0 + / GRAV_ENGLISH_LBM * ( (FV + htail_loc * FH / 2.0) * vtail_area @@ -1576,7 +1584,8 @@ def compute_partials(self, inputs, J): * vtail_mom_arm ** (-1.54) ) J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.THICKNESS_TO_CHORD] = ( - 380.0 / GRAV_ENGLISH_LBM + 380.0 + / GRAV_ENGLISH_LBM * ( (FV + htail_loc * FH / 2.0) * vtail_area @@ -1588,7 +1597,8 @@ def compute_partials(self, inputs, J): * tc_ratio_root_vtail ** (-1.54) ) J[Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.ROOT_CHORD] = ( - 380.0 / GRAV_ENGLISH_LBM + 380.0 + / GRAV_ENGLISH_LBM * ( (FV + htail_loc * FH / 2.0) * vtail_area @@ -1608,96 +1618,129 @@ class HighLiftMass(om.ExplicitComponent): """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Wing.FLAP_TYPE) + add_aviary_option(self, Aircraft.Wing.NUM_FLAP_SEGMENTS) def setup(self): - add_aviary_input(self, Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=2.66) - add_aviary_input(self, Aircraft.Wing.AREA, val=200) - add_aviary_input(self, Aircraft.Wing.SLAT_CHORD_RATIO, val=.15) - add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, val=.3) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=.33) - add_aviary_input(self, Aircraft.Wing.SLAT_SPAN_RATIO, val=.9) - add_aviary_input(self, Aircraft.Wing.FLAP_SPAN_RATIO, val=.65) - add_aviary_input(self, Aircraft.Wing.LOADING, val=128) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=.15) - add_aviary_input(self, Aircraft.Wing.SPAN, val=118) - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=13.1) - add_aviary_input(self, Aircraft.Wing.CENTER_CHORD, val=17.48974) - add_aviary_input(self, Mission.Landing.LIFT_COEFFICIENT_MAX, val=1.8) - self.add_input("density", val=RHO_SEA_LEVEL_ENGLISH, units='slug/ft**3', - desc='RHO: Density of air') - - add_aviary_output(self, Aircraft.Wing.HIGH_LIFT_MASS, val=0) - self.add_output("flap_mass", val=0, units="lbm", - desc="WFLAP: mass of trailing edge devices") - self.add_output("slat_mass", val=0, units="lbm", - desc="WLED: mass of leading edge devices") + add_aviary_input(self, Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.SLAT_CHORD_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.FLAP_CHORD_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.SLAT_SPAN_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.FLAP_SPAN_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Design.WING_LOADING, units='lbf/ft**2') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Wing.CENTER_CHORD, units='ft') + add_aviary_input(self, Mission.Landing.LIFT_COEFFICIENT_MAX, units='unitless') + self.add_input( + 'density', + val=RHO_SEA_LEVEL_ENGLISH, + units='slug/ft**3', + desc='RHO: Density of air', + ) + + add_aviary_output(self, Aircraft.Wing.HIGH_LIFT_MASS, units='lbm') + self.add_output( + 'flap_mass', val=0, units='lbm', desc='WFLAP: mass of trailing edge devices' + ) + self.add_output('slat_mass', val=0, units='lbm', desc='WLED: mass of leading edge devices') + def setup_partials(self): self.declare_partials( - "slat_mass", + 'slat_mass', [ - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, Aircraft.Wing.CENTER_CHORD, - Aircraft.Fuselage.AVG_DIAMETER, Aircraft.Wing.SPAN, - Aircraft.Wing.SLAT_CHORD_RATIO, Aircraft.Wing.AREA, - Aircraft.Wing.TAPER_RATIO, Aircraft.Wing.SLAT_SPAN_RATIO]) + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, + Aircraft.Wing.CENTER_CHORD, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.SPAN, + Aircraft.Wing.SLAT_CHORD_RATIO, + Aircraft.Wing.AREA, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.SLAT_SPAN_RATIO, + ], + ) self.declare_partials( - "flap_mass", + 'flap_mass', [ Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, - Aircraft.Wing.CENTER_CHORD, Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Wing.SPAN, Aircraft.Wing.FLAP_CHORD_RATIO, - Aircraft.Wing.AREA, Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.FLAP_SPAN_RATIO, Aircraft.Wing.LOADING, "density", - Mission.Landing.LIFT_COEFFICIENT_MAX]) + Aircraft.Wing.CENTER_CHORD, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.SPAN, + Aircraft.Wing.FLAP_CHORD_RATIO, + Aircraft.Wing.AREA, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.FLAP_SPAN_RATIO, + Aircraft.Design.WING_LOADING, + 'density', + Mission.Landing.LIFT_COEFFICIENT_MAX, + ], + ) self.declare_partials( Aircraft.Wing.HIGH_LIFT_MASS, [ Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, - Aircraft.Wing.CENTER_CHORD, Aircraft.Fuselage.AVG_DIAMETER, - Aircraft.Wing.SPAN, Aircraft.Wing.FLAP_CHORD_RATIO, - Aircraft.Wing.SLAT_CHORD_RATIO, Aircraft.Wing.AREA, - Aircraft.Wing.TAPER_RATIO, Aircraft.Wing.FLAP_SPAN_RATIO, - Aircraft.Wing.SLAT_SPAN_RATIO, Aircraft.Wing.LOADING, "density", - Mission.Landing.LIFT_COEFFICIENT_MAX]) + Aircraft.Wing.CENTER_CHORD, + Aircraft.Fuselage.AVG_DIAMETER, + Aircraft.Wing.SPAN, + Aircraft.Wing.FLAP_CHORD_RATIO, + Aircraft.Wing.SLAT_CHORD_RATIO, + Aircraft.Wing.AREA, + Aircraft.Wing.TAPER_RATIO, + Aircraft.Wing.FLAP_SPAN_RATIO, + Aircraft.Wing.SLAT_SPAN_RATIO, + Aircraft.Design.WING_LOADING, + 'density', + Mission.Landing.LIFT_COEFFICIENT_MAX, + ], + ) def compute(self, inputs, outputs): - aviary_options: AviaryValues = self.options["aviary_options"] - flap_type = aviary_options.get_val(Aircraft.Wing.FLAP_TYPE, units='unitless') + flap_type = self.options[Aircraft.Wing.FLAP_TYPE] c_mass_trend_high_lift = inputs[Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] wing_area = inputs[Aircraft.Wing.AREA] - num_flaps = aviary_options.get_val(Aircraft.Wing.NUM_FLAP_SEGMENTS) + num_flaps = self.options[Aircraft.Wing.NUM_FLAP_SEGMENTS] slat_chord_ratio = inputs[Aircraft.Wing.SLAT_CHORD_RATIO] flap_chord_ratio = inputs[Aircraft.Wing.FLAP_CHORD_RATIO] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] flap_span_ratio = inputs[Aircraft.Wing.FLAP_SPAN_RATIO] slat_span_ratio = inputs[Aircraft.Wing.SLAT_SPAN_RATIO] - wing_loading = inputs[Aircraft.Wing.LOADING] + wing_loading = inputs[Aircraft.Design.WING_LOADING] tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] wingspan = inputs[Aircraft.Wing.SPAN] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] center_chord = inputs[Aircraft.Wing.CENTER_CHORD] CL_max_flaps_landing = inputs[Mission.Landing.LIFT_COEFFICIENT_MAX] - RHO = inputs["density"] + RHO = inputs['density'] - body_to_span_ratio = (2. * np.sqrt(tc_ratio_root*center_chord * - (cabin_width-(tc_ratio_root*center_chord))) + 0.4)/wingspan + body_to_span_ratio = ( + 2.0 + * np.sqrt(tc_ratio_root * center_chord * (cabin_width - (tc_ratio_root * center_chord))) + + 0.4 + ) / wingspan SFLAP = ( - flap_chord_ratio * wing_area / (1. + taper_ratio) + flap_chord_ratio + * wing_area + / (1.0 + taper_ratio) * (flap_span_ratio - body_to_span_ratio) - * (2. - ((1. - taper_ratio) * (flap_span_ratio + body_to_span_ratio)))) + * (2.0 - ((1.0 - taper_ratio) * (flap_span_ratio + body_to_span_ratio))) + ) - SLE = slat_chord_ratio*wing_area / \ - (1.+taper_ratio)*slat_span_ratio * \ - (2.-((1.-taper_ratio)*(.99+body_to_span_ratio))) - VSTALL = .5921*np.sqrt(2.*wing_loading/(RHO*CL_max_flaps_landing)) + SLE = ( + slat_chord_ratio + * wing_area + / (1.0 + taper_ratio) + * slat_span_ratio + * (2.0 - ((1.0 - taper_ratio) * (0.99 + body_to_span_ratio))) + ) + VSTALL = 0.5921 * np.sqrt(2.0 * wing_loading / (RHO * CL_max_flaps_landing)) VFLAP = 1.8 * VSTALL # Slat Mass @@ -1706,375 +1749,712 @@ def compute(self, inputs, outputs): # Flap Mass if flap_type is FlapType.PLAIN: - outputs["flap_mass"] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*SFLAP*num_flaps**(-.5) / GRAV_ENGLISH_LBM + outputs['flap_mass'] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * SFLAP + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) elif flap_type is FlapType.SPLIT: if VFLAP > 160: - outputs["flap_mass"] = c_mass_trend_high_lift*SFLAP * \ - (VFLAP**2.195)/45180. / GRAV_ENGLISH_LBM + outputs['flap_mass'] = ( + c_mass_trend_high_lift * SFLAP * (VFLAP**2.195) / 45180.0 / GRAV_ENGLISH_LBM + ) else: - outputs["flap_mass"] = c_mass_trend_high_lift*SFLAP * \ - 0.369*VFLAP**0.2733 / GRAV_ENGLISH_LBM + outputs['flap_mass'] = ( + c_mass_trend_high_lift * SFLAP * 0.369 * VFLAP**0.2733 / GRAV_ENGLISH_LBM + ) elif ( - flap_type is FlapType.SINGLE_SLOTTED or flap_type is FlapType.DOUBLE_SLOTTED + flap_type is FlapType.SINGLE_SLOTTED + or flap_type is FlapType.DOUBLE_SLOTTED or flap_type is FlapType.TRIPLE_SLOTTED ): - outputs["flap_mass"] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*SFLAP*num_flaps**.5 / GRAV_ENGLISH_LBM + outputs['flap_mass'] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * SFLAP + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) elif flap_type is FlapType.FOWLER or flap_type is FlapType.DOUBLE_SLOTTED_FOWLER: - outputs["flap_mass"] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*SFLAP**1.19 / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM + outputs['flap_mass'] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * SFLAP**1.19 + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) else: raise ValueError(flap_type + ' is not a valid flap type') - outputs[Aircraft.Wing.HIGH_LIFT_MASS] = outputs["flap_mass"] + \ - WLED / GRAV_ENGLISH_LBM + outputs[Aircraft.Wing.HIGH_LIFT_MASS] = outputs['flap_mass'] + WLED / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - aviary_options: AviaryValues = self.options["aviary_options"] - flap_type = aviary_options.get_val(Aircraft.Wing.FLAP_TYPE, units='unitless') + flap_type = self.options[Aircraft.Wing.FLAP_TYPE] c_mass_trend_high_lift = inputs[Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] wing_area = inputs[Aircraft.Wing.AREA] - num_flaps = aviary_options.get_val(Aircraft.Wing.NUM_FLAP_SEGMENTS) + num_flaps = self.options[Aircraft.Wing.NUM_FLAP_SEGMENTS] slat_chord_ratio = inputs[Aircraft.Wing.SLAT_CHORD_RATIO] flap_chord_ratio = inputs[Aircraft.Wing.FLAP_CHORD_RATIO] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] flap_span_ratio = inputs[Aircraft.Wing.FLAP_SPAN_RATIO] slat_span_ratio = inputs[Aircraft.Wing.SLAT_SPAN_RATIO] - wing_loading = inputs[Aircraft.Wing.LOADING] + wing_loading = inputs[Aircraft.Design.WING_LOADING] tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] wingspan = inputs[Aircraft.Wing.SPAN] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] center_chord = inputs[Aircraft.Wing.CENTER_CHORD] CL_max_flaps_landing = inputs[Mission.Landing.LIFT_COEFFICIENT_MAX] - RHO = inputs["density"] + RHO = inputs['density'] - u1 = tc_ratio_root*center_chord * (cabin_width-(tc_ratio_root*center_chord)) - body_to_span_ratio = (2 * np.sqrt(u1) + 0.4)/wingspan - dBTSR_dwingspan = -(1/wingspan) * body_to_span_ratio + u1 = tc_ratio_root * center_chord * (cabin_width - (tc_ratio_root * center_chord)) + body_to_span_ratio = (2 * np.sqrt(u1) + 0.4) / wingspan + dBTSR_dwingspan = -(1 / wingspan) * body_to_span_ratio dBTSR_dTCRR = ( - (1 / wingspan) * (1 / np.sqrt(u1)) - * (center_chord * cabin_width - 2 * tc_ratio_root * center_chord**2)) + (1 / wingspan) + * (1 / np.sqrt(u1)) + * (center_chord * cabin_width - 2 * tc_ratio_root * center_chord**2) + ) dBTSR_dCC = ( - (1 / wingspan) * (1 / np.sqrt(u1)) - * (tc_ratio_root * cabin_width - 2 * tc_ratio_root**2 * center_chord)) + (1 / wingspan) + * (1 / np.sqrt(u1)) + * (tc_ratio_root * cabin_width - 2 * tc_ratio_root**2 * center_chord) + ) - dBTSR_dCW = (1/wingspan) * (1/np.sqrt(u1)) * (tc_ratio_root*center_chord) + dBTSR_dCW = (1 / wingspan) * (1 / np.sqrt(u1)) * (tc_ratio_root * center_chord) SFLAP = ( - flap_chord_ratio * wing_area / (1. + taper_ratio) + flap_chord_ratio + * wing_area + / (1.0 + taper_ratio) * (flap_span_ratio - body_to_span_ratio) - * (2 - ((1 - taper_ratio) * (flap_span_ratio + body_to_span_ratio)))) + * (2 - ((1 - taper_ratio) * (flap_span_ratio + body_to_span_ratio))) + ) - dSFLAP_dFCR = wing_area/(1.+taper_ratio)*(flap_span_ratio-body_to_span_ratio)*( - 2-((1-taper_ratio)*(flap_span_ratio+body_to_span_ratio))) + dSFLAP_dFCR = ( + wing_area + / (1.0 + taper_ratio) + * (flap_span_ratio - body_to_span_ratio) + * (2 - ((1 - taper_ratio) * (flap_span_ratio + body_to_span_ratio))) + ) dSFLAP_dWA = ( - flap_chord_ratio / (1. + taper_ratio) + flap_chord_ratio + / (1.0 + taper_ratio) * (flap_span_ratio - body_to_span_ratio) - * (2 - ((1 - taper_ratio) * (flap_span_ratio + body_to_span_ratio)))) - - dSFLAP_dFSR = flap_chord_ratio*wing_area * \ - (2/(1.+taper_ratio)*(1-2*flap_span_ratio) + 2*flap_span_ratio) - dSFLAP_dBTSR = flap_chord_ratio*wing_area * \ - (2/(1.+taper_ratio)*(2*body_to_span_ratio-1) - 2*body_to_span_ratio) - dSFLAP_dTR = flap_chord_ratio*wing_area * -2 / \ - (1.+taper_ratio)**2 * (flap_span_ratio-body_to_span_ratio) * \ - (1-flap_span_ratio-body_to_span_ratio) - - SLE = slat_chord_ratio*wing_area / \ - (1+taper_ratio)*slat_span_ratio * \ - (2-((1-taper_ratio)*(.99+body_to_span_ratio))) - dSLE_dSCR = wing_area/(1+taper_ratio)*slat_span_ratio * \ - (2-((1-taper_ratio)*(.99+body_to_span_ratio))) + * (2 - ((1 - taper_ratio) * (flap_span_ratio + body_to_span_ratio))) + ) + + dSFLAP_dFSR = ( + flap_chord_ratio + * wing_area + * (2 / (1.0 + taper_ratio) * (1 - 2 * flap_span_ratio) + 2 * flap_span_ratio) + ) + dSFLAP_dBTSR = ( + flap_chord_ratio + * wing_area + * (2 / (1.0 + taper_ratio) * (2 * body_to_span_ratio - 1) - 2 * body_to_span_ratio) + ) + dSFLAP_dTR = ( + flap_chord_ratio + * wing_area + * -2 + / (1.0 + taper_ratio) ** 2 + * (flap_span_ratio - body_to_span_ratio) + * (1 - flap_span_ratio - body_to_span_ratio) + ) + + SLE = ( + slat_chord_ratio + * wing_area + / (1 + taper_ratio) + * slat_span_ratio + * (2 - ((1 - taper_ratio) * (0.99 + body_to_span_ratio))) + ) + dSLE_dSCR = ( + wing_area + / (1 + taper_ratio) + * slat_span_ratio + * (2 - ((1 - taper_ratio) * (0.99 + body_to_span_ratio))) + ) dSLE_dWA = ( - slat_chord_ratio / (1 + taper_ratio) - * slat_span_ratio * (2 - ((1 - taper_ratio) * (.99 + body_to_span_ratio)))) - - dSLE_dSSR = (slat_chord_ratio*wing_area)/(1+taper_ratio) * \ - (2-((1-taper_ratio)*(.99+body_to_span_ratio))) - dSLE_dBTSR = -(slat_chord_ratio*wing_area)/(1+taper_ratio) * \ - slat_span_ratio*(1-taper_ratio) - dSLE_dTR = (2*slat_chord_ratio*wing_area*slat_span_ratio) / \ - ((1+taper_ratio)**2)*(.99+body_to_span_ratio-1) - - u2 = 2*wing_loading/(RHO*CL_max_flaps_landing) - VFLAP = 1.8 * (.5921*np.sqrt(u2)) - dVFLAP_dWL = (1.8*.5921) * (1/np.sqrt(u2)) * (1/(RHO*CL_max_flaps_landing)) - dVFLAP_drho = -(1.8*.5921) * (1/np.sqrt(u2)) * \ - (wing_loading/(RHO**2*CL_max_flaps_landing)) - dVFLAP_dCMFL = -(1.8*.5921) * (1/np.sqrt(u2)) * \ - (wing_loading/(RHO*CL_max_flaps_landing**2)) + slat_chord_ratio + / (1 + taper_ratio) + * slat_span_ratio + * (2 - ((1 - taper_ratio) * (0.99 + body_to_span_ratio))) + ) + + dSLE_dSSR = ( + (slat_chord_ratio * wing_area) + / (1 + taper_ratio) + * (2 - ((1 - taper_ratio) * (0.99 + body_to_span_ratio))) + ) + dSLE_dBTSR = ( + -(slat_chord_ratio * wing_area) + / (1 + taper_ratio) + * slat_span_ratio + * (1 - taper_ratio) + ) + dSLE_dTR = ( + (2 * slat_chord_ratio * wing_area * slat_span_ratio) + / ((1 + taper_ratio) ** 2) + * (0.99 + body_to_span_ratio - 1) + ) + + u2 = 2 * wing_loading / (RHO * CL_max_flaps_landing) + VFLAP = 1.8 * (0.5921 * np.sqrt(u2)) + dVFLAP_dWL = (1.8 * 0.5921) * (1 / np.sqrt(u2)) * (1 / (RHO * CL_max_flaps_landing)) + dVFLAP_drho = ( + -(1.8 * 0.5921) * (1 / np.sqrt(u2)) * (wing_loading / (RHO**2 * CL_max_flaps_landing)) + ) + dVFLAP_dCMFL = ( + -(1.8 * 0.5921) * (1 / np.sqrt(u2)) * (wing_loading / (RHO * CL_max_flaps_landing**2)) + ) # Slat Mass - J['slat_mass', Aircraft.Wing.SLAT_CHORD_RATIO] = 3.28 * \ - 1.13*(SLE**.13)*dSLE_dSCR / GRAV_ENGLISH_LBM - J['slat_mass', Aircraft.Wing.AREA] = 3.28*1.13 * \ - (SLE**.13)*dSLE_dWA / GRAV_ENGLISH_LBM - J['slat_mass', Aircraft.Wing.SLAT_SPAN_RATIO] = 3.28 * \ - 1.13*(SLE**.13)*dSLE_dSSR / GRAV_ENGLISH_LBM - J['slat_mass', Aircraft.Wing.TAPER_RATIO] = 3.28*1.13 * \ - (SLE**.13)*dSLE_dTR / GRAV_ENGLISH_LBM - J['slat_mass', Aircraft.Wing.SPAN] = 3.28 * \ - 1.13*(SLE**.13)*dSLE_dBTSR*dBTSR_dwingspan / GRAV_ENGLISH_LBM - J['slat_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = 3.28 * \ - 1.13*(SLE**.13)*dSLE_dBTSR*dBTSR_dTCRR / GRAV_ENGLISH_LBM - J['slat_mass', Aircraft.Wing.CENTER_CHORD] = 3.28 * \ - 1.13*(SLE**.13)*dSLE_dBTSR*dBTSR_dCC / GRAV_ENGLISH_LBM - J['slat_mass', Aircraft.Fuselage.AVG_DIAMETER] = 3.28 * \ - 1.13*(SLE**.13)*dSLE_dBTSR*dBTSR_dCW / GRAV_ENGLISH_LBM + J['slat_mass', Aircraft.Wing.SLAT_CHORD_RATIO] = ( + 3.28 * 1.13 * (SLE**0.13) * dSLE_dSCR / GRAV_ENGLISH_LBM + ) + J['slat_mass', Aircraft.Wing.AREA] = 3.28 * 1.13 * (SLE**0.13) * dSLE_dWA / GRAV_ENGLISH_LBM + J['slat_mass', Aircraft.Wing.SLAT_SPAN_RATIO] = ( + 3.28 * 1.13 * (SLE**0.13) * dSLE_dSSR / GRAV_ENGLISH_LBM + ) + J['slat_mass', Aircraft.Wing.TAPER_RATIO] = ( + 3.28 * 1.13 * (SLE**0.13) * dSLE_dTR / GRAV_ENGLISH_LBM + ) + J['slat_mass', Aircraft.Wing.SPAN] = ( + 3.28 * 1.13 * (SLE**0.13) * dSLE_dBTSR * dBTSR_dwingspan / GRAV_ENGLISH_LBM + ) + J['slat_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + 3.28 * 1.13 * (SLE**0.13) * dSLE_dBTSR * dBTSR_dTCRR / GRAV_ENGLISH_LBM + ) + J['slat_mass', Aircraft.Wing.CENTER_CHORD] = ( + 3.28 * 1.13 * (SLE**0.13) * dSLE_dBTSR * dBTSR_dCC / GRAV_ENGLISH_LBM + ) + J['slat_mass', Aircraft.Fuselage.AVG_DIAMETER] = ( + 3.28 * 1.13 * (SLE**0.13) * dSLE_dBTSR * dBTSR_dCW / GRAV_ENGLISH_LBM + ) # Flap Mass if flap_type is FlapType.PLAIN: # c_wt_trend_high_lift * (VFLAP/100.)**2*SFLAP*num_flaps**(-.5) - J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( - VFLAP/100)**2 * SFLAP * num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.LOADING] = c_mass_trend_high_lift * \ - (2*VFLAP/100**2)*dVFLAP_dWL * SFLAP * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", "density"] = c_mass_trend_high_lift * \ - (2*VFLAP/100**2)*dVFLAP_drho * SFLAP * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Mission.Landing.LIFT_COEFFICIENT_MAX] = c_mass_trend_high_lift * \ - (2*VFLAP/100**2)*dVFLAP_dCMFL * SFLAP * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.FLAP_CHORD_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100)**2 * dSFLAP_dFCR * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.AREA] = c_mass_trend_high_lift * \ - (VFLAP/100)**2 * dSFLAP_dWA * num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.FLAP_SPAN_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100)**2 * dSFLAP_dFSR * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.TAPER_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100)**2 * dSFLAP_dTR * num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.SPAN] = c_mass_trend_high_lift * \ - (VFLAP/100)**2 * dSFLAP_dBTSR * dBTSR_dwingspan * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( - c_mass_trend_high_lift * (VFLAP / 100)**2 * dSFLAP_dBTSR * dBTSR_dTCRR - * num_flaps**(-.5) / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.CENTER_CHORD] = c_mass_trend_high_lift * \ - (VFLAP/100)**2 * dSFLAP_dBTSR * dBTSR_dCC * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] = c_mass_trend_high_lift * \ - (VFLAP/100)**2 * dSFLAP_dBTSR * dBTSR_dCW * \ - num_flaps**(-.5) / GRAV_ENGLISH_LBM + J['flap_mass', Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( + (VFLAP / 100) ** 2 * SFLAP * num_flaps ** (-0.5) / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Design.WING_LOADING] = ( + c_mass_trend_high_lift + * (2 * VFLAP / 100**2) + * dVFLAP_dWL + * SFLAP + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', 'density'] = ( + c_mass_trend_high_lift + * (2 * VFLAP / 100**2) + * dVFLAP_drho + * SFLAP + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Mission.Landing.LIFT_COEFFICIENT_MAX] = ( + c_mass_trend_high_lift + * (2 * VFLAP / 100**2) + * dVFLAP_dCMFL + * SFLAP + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.FLAP_CHORD_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dFCR + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.AREA] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dWA + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.FLAP_SPAN_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dFSR + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.TAPER_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dTR + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.SPAN] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dBTSR + * dBTSR_dwingspan + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dBTSR + * dBTSR_dTCRR + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.CENTER_CHORD] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dBTSR + * dBTSR_dCC + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Fuselage.AVG_DIAMETER] = ( + c_mass_trend_high_lift + * (VFLAP / 100) ** 2 + * dSFLAP_dBTSR + * dBTSR_dCW + * num_flaps ** (-0.5) + / GRAV_ENGLISH_LBM + ) elif flap_type is FlapType.SPLIT: if VFLAP > 160: # c_wt_trend_high_lift*SFLAP*(VFLAP**2.195)/45180. - J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = SFLAP * \ - (VFLAP**2.195)/45180. / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.LOADING] = c_mass_trend_high_lift * \ - SFLAP*(2.195*VFLAP**1.195*dVFLAP_dWL) / \ - 45180. / GRAV_ENGLISH_LBM - J["flap_mass", "density"] = c_mass_trend_high_lift * \ - SFLAP*(2.195*VFLAP**1.195*dVFLAP_drho) / \ - 45180. / GRAV_ENGLISH_LBM - - J["flap_mass", Mission.Landing.LIFT_COEFFICIENT_MAX] = ( - c_mass_trend_high_lift * SFLAP - * (2.195 * VFLAP**1.195 * dVFLAP_dCMFL) / 45180. / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.FLAP_CHORD_RATIO] = ( - c_mass_trend_high_lift * dSFLAP_dFCR - * (VFLAP**2.195) / 45180. / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.AREA] = c_mass_trend_high_lift * \ - dSFLAP_dWA*(VFLAP**2.195)/45180. / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Wing.FLAP_SPAN_RATIO] = ( - c_mass_trend_high_lift * dSFLAP_dFSR - * (VFLAP**2.195) / 45180. / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.TAPER_RATIO] = c_mass_trend_high_lift * \ - dSFLAP_dTR*(VFLAP**2.195)/45180. / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.SPAN] = c_mass_trend_high_lift * \ - dSFLAP_dBTSR*dBTSR_dwingspan * \ - (VFLAP**2.195)/45180. / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( - c_mass_trend_high_lift * dSFLAP_dBTSR * dBTSR_dTCRR - * (VFLAP**2.195) / 45180. / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.CENTER_CHORD] = c_mass_trend_high_lift * \ - dSFLAP_dBTSR*dBTSR_dCC*(VFLAP**2.195)/45180. / \ - GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] = ( - c_mass_trend_high_lift * dSFLAP_dBTSR * dBTSR_dCW - * (VFLAP**2.195) / 45180. / GRAV_ENGLISH_LBM) + J['flap_mass', Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( + SFLAP * (VFLAP**2.195) / 45180.0 / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Design.WING_LOADING] = ( + c_mass_trend_high_lift + * SFLAP + * (2.195 * VFLAP**1.195 * dVFLAP_dWL) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', 'density'] = ( + c_mass_trend_high_lift + * SFLAP + * (2.195 * VFLAP**1.195 * dVFLAP_drho) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Mission.Landing.LIFT_COEFFICIENT_MAX] = ( + c_mass_trend_high_lift + * SFLAP + * (2.195 * VFLAP**1.195 * dVFLAP_dCMFL) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.FLAP_CHORD_RATIO] = ( + c_mass_trend_high_lift + * dSFLAP_dFCR + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.AREA] = ( + c_mass_trend_high_lift + * dSFLAP_dWA + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.FLAP_SPAN_RATIO] = ( + c_mass_trend_high_lift + * dSFLAP_dFSR + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.TAPER_RATIO] = ( + c_mass_trend_high_lift + * dSFLAP_dTR + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.SPAN] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dwingspan + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dTCRR + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.CENTER_CHORD] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dCC + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Fuselage.AVG_DIAMETER] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dCW + * (VFLAP**2.195) + / 45180.0 + / GRAV_ENGLISH_LBM + ) else: # c_wt_trend_high_lift*SFLAP*0.369*VFLAP**0.2733 - J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = SFLAP * \ - 0.369*VFLAP**0.2733 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.LOADING] = c_mass_trend_high_lift * \ - SFLAP*0.369*(.2733*VFLAP**(-.7267)*dVFLAP_dWL) / \ - GRAV_ENGLISH_LBM - J["flap_mass", "density"] = c_mass_trend_high_lift * \ - SFLAP*0.369*(.2733*VFLAP**(-.7267)*dVFLAP_drho) / \ - GRAV_ENGLISH_LBM - - J["flap_mass", Mission.Landing.LIFT_COEFFICIENT_MAX] = ( - c_mass_trend_high_lift * SFLAP * 0.369 - * (.2733 * VFLAP**(-.7267) * dVFLAP_dCMFL) / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.FLAP_CHORD_RATIO] = ( - c_mass_trend_high_lift * dSFLAP_dFCR * 0.369 * VFLAP**0.2733 - / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.AREA] = c_mass_trend_high_lift * \ - dSFLAP_dWA*0.369*VFLAP**0.2733 / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Wing.FLAP_SPAN_RATIO] = ( - c_mass_trend_high_lift * dSFLAP_dFSR * 0.369 * VFLAP**0.2733 - / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.TAPER_RATIO] = c_mass_trend_high_lift * \ - dSFLAP_dTR*0.369*VFLAP**0.2733 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.SPAN] = c_mass_trend_high_lift * \ - dSFLAP_dBTSR*dBTSR_dwingspan*0.369*VFLAP**0.2733 / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( - c_mass_trend_high_lift * dSFLAP_dBTSR * dBTSR_dTCRR * 0.369 - * VFLAP**0.2733 / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.CENTER_CHORD] = c_mass_trend_high_lift * \ - dSFLAP_dBTSR*dBTSR_dCC*0.369*VFLAP**0.2733 / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] = ( - c_mass_trend_high_lift * dSFLAP_dBTSR * dBTSR_dCW * 0.369 - * VFLAP**0.2733 / GRAV_ENGLISH_LBM) + J['flap_mass', Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( + SFLAP * 0.369 * VFLAP**0.2733 / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Design.WING_LOADING] = ( + c_mass_trend_high_lift + * SFLAP + * 0.369 + * (0.2733 * VFLAP ** (-0.7267) * dVFLAP_dWL) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', 'density'] = ( + c_mass_trend_high_lift + * SFLAP + * 0.369 + * (0.2733 * VFLAP ** (-0.7267) * dVFLAP_drho) + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Mission.Landing.LIFT_COEFFICIENT_MAX] = ( + c_mass_trend_high_lift + * SFLAP + * 0.369 + * (0.2733 * VFLAP ** (-0.7267) * dVFLAP_dCMFL) + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.FLAP_CHORD_RATIO] = ( + c_mass_trend_high_lift * dSFLAP_dFCR * 0.369 * VFLAP**0.2733 / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.AREA] = ( + c_mass_trend_high_lift * dSFLAP_dWA * 0.369 * VFLAP**0.2733 / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.FLAP_SPAN_RATIO] = ( + c_mass_trend_high_lift * dSFLAP_dFSR * 0.369 * VFLAP**0.2733 / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.TAPER_RATIO] = ( + c_mass_trend_high_lift * dSFLAP_dTR * 0.369 * VFLAP**0.2733 / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.SPAN] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dwingspan + * 0.369 + * VFLAP**0.2733 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dTCRR + * 0.369 + * VFLAP**0.2733 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.CENTER_CHORD] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dCC + * 0.369 + * VFLAP**0.2733 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Fuselage.AVG_DIAMETER] = ( + c_mass_trend_high_lift + * dSFLAP_dBTSR + * dBTSR_dCW + * 0.369 + * VFLAP**0.2733 + / GRAV_ENGLISH_LBM + ) elif ( - flap_type is FlapType.SINGLE_SLOTTED or flap_type is FlapType.DOUBLE_SLOTTED + flap_type is FlapType.SINGLE_SLOTTED + or flap_type is FlapType.DOUBLE_SLOTTED or flap_type is FlapType.TRIPLE_SLOTTED ): # c_wt_trend_high_lift*(VFLAP/100.)**2*SFLAP*num_flaps**.5 - J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( - VFLAP/100.)**2*SFLAP*num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.LOADING] = c_mass_trend_high_lift * \ - (2*VFLAP/100**2)*dVFLAP_dWL*SFLAP * \ - num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", "density"] = c_mass_trend_high_lift * \ - (2*VFLAP/100**2)*dVFLAP_drho*SFLAP * \ - num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Mission.Landing.LIFT_COEFFICIENT_MAX] = c_mass_trend_high_lift * \ - (2*VFLAP/100**2)*dVFLAP_dCMFL*SFLAP * \ - num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.FLAP_CHORD_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*dSFLAP_dFCR*num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.AREA] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*dSFLAP_dWA*num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.FLAP_SPAN_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*dSFLAP_dFSR*num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.TAPER_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*dSFLAP_dTR*num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.SPAN] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*dSFLAP_dBTSR*dBTSR_dwingspan * \ - num_flaps**.5 / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( - c_mass_trend_high_lift * (VFLAP / 100.)**2 * dSFLAP_dBTSR * dBTSR_dTCRR - * num_flaps**.5 / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.CENTER_CHORD] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*dSFLAP_dBTSR*dBTSR_dCC * \ - num_flaps**.5 / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2*dSFLAP_dBTSR*dBTSR_dCW * \ - num_flaps**.5 / GRAV_ENGLISH_LBM + J['flap_mass', Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( + (VFLAP / 100.0) ** 2 * SFLAP * num_flaps**0.5 / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Design.WING_LOADING] = ( + c_mass_trend_high_lift + * (2 * VFLAP / 100**2) + * dVFLAP_dWL + * SFLAP + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', 'density'] = ( + c_mass_trend_high_lift + * (2 * VFLAP / 100**2) + * dVFLAP_drho + * SFLAP + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Mission.Landing.LIFT_COEFFICIENT_MAX] = ( + c_mass_trend_high_lift + * (2 * VFLAP / 100**2) + * dVFLAP_dCMFL + * SFLAP + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.FLAP_CHORD_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dFCR + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.AREA] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dWA + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.FLAP_SPAN_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dFSR + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.TAPER_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dTR + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.SPAN] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dBTSR + * dBTSR_dwingspan + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dBTSR + * dBTSR_dTCRR + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.CENTER_CHORD] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dBTSR + * dBTSR_dCC + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Fuselage.AVG_DIAMETER] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2 + * dSFLAP_dBTSR + * dBTSR_dCW + * num_flaps**0.5 + / GRAV_ENGLISH_LBM + ) elif flap_type is FlapType.FOWLER or flap_type is FlapType.DOUBLE_SLOTTED_FOWLER: # c_wt_trend_high_lift * (VFLAP/100.)**2.38*SFLAP**1.19/(num_flaps**.595) - J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( - VFLAP/100.)**2.38*SFLAP**1.19/(num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.LOADING] = c_mass_trend_high_lift * \ - (2.38*VFLAP**1.38/100.**2.38)*dVFLAP_dWL*SFLAP**1.19 / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", "density"] = c_mass_trend_high_lift * \ - (2.38*VFLAP**1.38/100.**2.38)*dVFLAP_drho*SFLAP**1.19 / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Mission.Landing.LIFT_COEFFICIENT_MAX] = c_mass_trend_high_lift * \ - (2.38*VFLAP**1.38/100.**2.38)*dVFLAP_dCMFL*SFLAP**1.19 / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.FLAP_CHORD_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*(1.19*SFLAP**.19)*dSFLAP_dFCR / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.AREA] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*(1.19*SFLAP**.19)*dSFLAP_dWA / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.FLAP_SPAN_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*(1.19*SFLAP**.19)*dSFLAP_dFSR / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.TAPER_RATIO] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*(1.19*SFLAP**.19)*dSFLAP_dTR / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Wing.SPAN] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*(1.19*SFLAP**.19) * \ - dSFLAP_dBTSR*dBTSR_dwingspan / \ - (num_flaps**.595) / GRAV_ENGLISH_LBM - - J["flap_mass", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( - c_mass_trend_high_lift * (VFLAP / 100.)**2.38 * (1.19 * SFLAP**.19) - * dSFLAP_dBTSR * dBTSR_dTCRR / (num_flaps**.595) / GRAV_ENGLISH_LBM) - - J["flap_mass", Aircraft.Wing.CENTER_CHORD] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*(1.19*SFLAP**.19) * \ - dSFLAP_dBTSR*dBTSR_dCC/(num_flaps**.595) / GRAV_ENGLISH_LBM - J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] = c_mass_trend_high_lift * \ - (VFLAP/100.)**2.38*(1.19*SFLAP**.19) * \ - dSFLAP_dBTSR*dBTSR_dCW/(num_flaps**.595) / GRAV_ENGLISH_LBM - - J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = \ - J["flap_mass", Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] - - J[Aircraft.Wing.HIGH_LIFT_MASS, - Aircraft.Wing.LOADING] = J["flap_mass", Aircraft.Wing.LOADING] - J[Aircraft.Wing.HIGH_LIFT_MASS, "density"] = J["flap_mass", "density"] - - J[Aircraft.Wing.HIGH_LIFT_MASS, Mission.Landing.LIFT_COEFFICIENT_MAX] = \ - J["flap_mass", Mission.Landing.LIFT_COEFFICIENT_MAX] - - J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.FLAP_CHORD_RATIO] = \ - J["flap_mass", Aircraft.Wing.FLAP_CHORD_RATIO] - - J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.SLAT_CHORD_RATIO] = \ - J['slat_mass', Aircraft.Wing.SLAT_CHORD_RATIO] - - J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.AREA] = \ - J["flap_mass", Aircraft.Wing.AREA] + J['slat_mass', Aircraft.Wing.AREA] - - J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.FLAP_SPAN_RATIO] = \ - J["flap_mass", Aircraft.Wing.FLAP_SPAN_RATIO] - - J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.SLAT_SPAN_RATIO] = \ - J['slat_mass', Aircraft.Wing.SLAT_SPAN_RATIO] + J['flap_mass', Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = ( + (VFLAP / 100.0) ** 2.38 * SFLAP**1.19 / (num_flaps**0.595) / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Design.WING_LOADING] = ( + c_mass_trend_high_lift + * (2.38 * VFLAP**1.38 / 100.0**2.38) + * dVFLAP_dWL + * SFLAP**1.19 + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', 'density'] = ( + c_mass_trend_high_lift + * (2.38 * VFLAP**1.38 / 100.0**2.38) + * dVFLAP_drho + * SFLAP**1.19 + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Mission.Landing.LIFT_COEFFICIENT_MAX] = ( + c_mass_trend_high_lift + * (2.38 * VFLAP**1.38 / 100.0**2.38) + * dVFLAP_dCMFL + * SFLAP**1.19 + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.FLAP_CHORD_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dFCR + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.AREA] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dWA + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.FLAP_SPAN_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dFSR + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.TAPER_RATIO] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dTR + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Wing.SPAN] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dBTSR + * dBTSR_dwingspan + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dBTSR + * dBTSR_dTCRR + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + + J['flap_mass', Aircraft.Wing.CENTER_CHORD] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dBTSR + * dBTSR_dCC + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + J['flap_mass', Aircraft.Fuselage.AVG_DIAMETER] = ( + c_mass_trend_high_lift + * (VFLAP / 100.0) ** 2.38 + * (1.19 * SFLAP**0.19) + * dSFLAP_dBTSR + * dBTSR_dCW + / (num_flaps**0.595) + / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT] = J[ + 'flap_mass', Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT + ] + + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Design.WING_LOADING] = J[ + 'flap_mass', Aircraft.Design.WING_LOADING + ] + J[Aircraft.Wing.HIGH_LIFT_MASS, 'density'] = J['flap_mass', 'density'] + + J[Aircraft.Wing.HIGH_LIFT_MASS, Mission.Landing.LIFT_COEFFICIENT_MAX] = J[ + 'flap_mass', Mission.Landing.LIFT_COEFFICIENT_MAX + ] + + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.FLAP_CHORD_RATIO] = J[ + 'flap_mass', Aircraft.Wing.FLAP_CHORD_RATIO + ] + + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.SLAT_CHORD_RATIO] = J[ + 'slat_mass', Aircraft.Wing.SLAT_CHORD_RATIO + ] + + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.AREA] = ( + J['flap_mass', Aircraft.Wing.AREA] + J['slat_mass', Aircraft.Wing.AREA] + ) + + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.FLAP_SPAN_RATIO] = J[ + 'flap_mass', Aircraft.Wing.FLAP_SPAN_RATIO + ] + + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.SLAT_SPAN_RATIO] = J[ + 'slat_mass', Aircraft.Wing.SLAT_SPAN_RATIO + ] J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.TAPER_RATIO] = ( - J["flap_mass", Aircraft.Wing.TAPER_RATIO] - + J['slat_mass', Aircraft.Wing.TAPER_RATIO]) + J['flap_mass', Aircraft.Wing.TAPER_RATIO] + J['slat_mass', Aircraft.Wing.TAPER_RATIO] + ) - J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.SPAN] = \ - J["flap_mass", Aircraft.Wing.SPAN] + J['slat_mass', Aircraft.Wing.SPAN] + J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.SPAN] = ( + J['flap_mass', Aircraft.Wing.SPAN] + J['slat_mass', Aircraft.Wing.SPAN] + ) J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( - J["flap_mass", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] - + J['slat_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT]) + J['flap_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + + J['slat_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + ) J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Wing.CENTER_CHORD] = ( - J["flap_mass", Aircraft.Wing.CENTER_CHORD] - + J['slat_mass', Aircraft.Wing.CENTER_CHORD]) + J['flap_mass', Aircraft.Wing.CENTER_CHORD] + J['slat_mass', Aircraft.Wing.CENTER_CHORD] + ) J[Aircraft.Wing.HIGH_LIFT_MASS, Aircraft.Fuselage.AVG_DIAMETER] = ( - J["flap_mass", Aircraft.Fuselage.AVG_DIAMETER] - + J['slat_mass', Aircraft.Fuselage.AVG_DIAMETER]) + J['flap_mass', Aircraft.Fuselage.AVG_DIAMETER] + + J['slat_mass', Aircraft.Fuselage.AVG_DIAMETER] + ) class ControlMass(om.ExplicitComponent): @@ -2083,59 +2463,57 @@ class ControlMass(om.ExplicitComponent): and mass of surface controls. """ - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - def setup(self): + add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, units='unitless') + self.add_input('min_dive_vel', val=700, units='kn', desc='VDMIN: dive velocity') + add_aviary_input(self, Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, units='lbm') + add_aviary_input(self, Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, units='unitless') add_aviary_input( - self, Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95) - add_aviary_input(self, Aircraft.Wing.AREA, val=200) - add_aviary_input(self, Mission.Design.GROSS_MASS, val=20000) - add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=7) - self.add_input("min_dive_vel", val=700, units="kn", desc="VDMIN: dive velocity") - add_aviary_input( - self, Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5) - add_aviary_input( - self, Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=200) - add_aviary_input(self, Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1) - add_aviary_input( - self, Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0) + self, + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, + units='unitless', + ) + add_aviary_input(self, Aircraft.Controls.CONTROL_MASS_INCREMENT, units='lbm') - add_aviary_output(self, Aircraft.Controls.TOTAL_MASS, val=0) - add_aviary_output(self, Aircraft.Wing.SURFACE_CONTROL_MASS, val=0) + add_aviary_output(self, Aircraft.Controls.TOTAL_MASS, units='lbm') + add_aviary_output(self, Aircraft.Wing.SURFACE_CONTROL_MASS, units='lbm') - self.declare_partials(Aircraft.Controls.TOTAL_MASS, "*") + def setup_partials(self): + self.declare_partials(Aircraft.Controls.TOTAL_MASS, '*') self.declare_partials( Aircraft.Wing.SURFACE_CONTROL_MASS, [ - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, Aircraft.Wing.AREA, - Mission.Design.GROSS_MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - "min_dive_vel", Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT]) + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, + Aircraft.Wing.AREA, + Mission.Design.GROSS_MASS, + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, + 'min_dive_vel', + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, + ], + ) def compute(self, inputs, outputs): - c_mass_trend_wing_control = \ - inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT] + c_mass_trend_wing_control = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT] wing_area = inputs[Aircraft.Wing.AREA] gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] - c_mass_trend_cockpit_control = \ - inputs[Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT] + c_mass_trend_cockpit_control = inputs[Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT] - stab_aug_wt = inputs[Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS] * \ - GRAV_ENGLISH_LBM + stab_aug_wt = ( + inputs[Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS] * GRAV_ENGLISH_LBM + ) CK15 = inputs[Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER] CK18 = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] CK19 = inputs[Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER] - delta_control_wt = inputs[Aircraft.Controls.CONTROL_MASS_INCREMENT] * \ - GRAV_ENGLISH_LBM - min_dive_vel = inputs["min_dive_vel"] + delta_control_wt = inputs[Aircraft.Controls.CONTROL_MASS_INCREMENT] * GRAV_ENGLISH_LBM + min_dive_vel = inputs['min_dive_vel'] dive_param = (1.15 * min_dive_vel) ** 2 / 391.0 @@ -2146,12 +2524,9 @@ def compute(self, inputs, outputs): * ULF**0.525 * dive_param**0.345 ) - cockpit_control_wt = ( - c_mass_trend_cockpit_control * (gross_wt_initial / 1000.0) ** 0.41 - ) + cockpit_control_wt = c_mass_trend_cockpit_control * (gross_wt_initial / 1000.0) ** 0.41 wing_control_wt = intermediate_control_wt - cockpit_control_wt - outputs[Aircraft.Wing.SURFACE_CONTROL_MASS] = wing_control_wt / \ - GRAV_ENGLISH_LBM + outputs[Aircraft.Wing.SURFACE_CONTROL_MASS] = wing_control_wt / GRAV_ENGLISH_LBM stab_control_wt = stab_aug_wt outputs[Aircraft.Controls.TOTAL_MASS] = ( @@ -2162,23 +2537,19 @@ def compute(self, inputs, outputs): ) / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - c_mass_trend_wing_control = \ - inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT] + c_mass_trend_wing_control = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT] wing_area = inputs[Aircraft.Wing.AREA] gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] - c_mass_trend_cockpit_control = \ - inputs[Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT] + c_mass_trend_cockpit_control = inputs[Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT] stab_aug_wt = inputs[Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS] CK15 = inputs[Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER] CK18 = inputs[Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] CK19 = inputs[Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER] - delta_control_wt = inputs[Aircraft.Controls.CONTROL_MASS_INCREMENT] * \ - GRAV_ENGLISH_LBM - min_dive_vel = inputs["min_dive_vel"] + min_dive_vel = inputs['min_dive_vel'] dive_param = (1.15 * min_dive_vel) ** 2 / 391.0 @@ -2189,39 +2560,25 @@ def compute_partials(self, inputs, J): * ULF**0.525 * dive_param**0.345 ) - cockpit_control_wt = ( - c_mass_trend_cockpit_control * (gross_wt_initial / 1000.0) ** 0.41 - ) + cockpit_control_wt = c_mass_trend_cockpit_control * (gross_wt_initial / 1000.0) ** 0.41 wing_control_wt = intermediate_control_wt - cockpit_control_wt dSCW_dSWCC = ( - wing_area**0.317 - * (gross_wt_initial / 1000.0) ** 0.602 - * ULF**0.525 - * dive_param**0.345 - ) - dSCW_dWA = ( - 0.317 - * ( - c_mass_trend_wing_control - * wing_area ** (0.317 - 1) - * (gross_wt_initial / 1000.0) ** 0.602 - * ULF**0.525 - * dive_param**0.345 - ) + wing_area**0.317 * (gross_wt_initial / 1000.0) ** 0.602 * ULF**0.525 * dive_param**0.345 ) - dSCW_dWG = ( - 0.602 - * c_mass_trend_wing_control - * wing_area**0.317 - * (gross_wt_initial / 1000.0) ** (0.602 - 1) - * (1 / 1000) + dSCW_dWA = 0.317 * ( + c_mass_trend_wing_control + * wing_area ** (0.317 - 1) + * (gross_wt_initial / 1000.0) ** 0.602 * ULF**0.525 * dive_param**0.345 - - 0.41 - * c_mass_trend_cockpit_control - * (gross_wt_initial / 1000.0) ** (0.41 - 1) - * (1 / 1000) ) + dSCW_dWG = 0.602 * c_mass_trend_wing_control * wing_area**0.317 * ( + gross_wt_initial / 1000.0 + ) ** (0.602 - 1) * ( + 1 / 1000 + ) * ULF**0.525 * dive_param**0.345 - 0.41 * c_mass_trend_cockpit_control * ( + gross_wt_initial / 1000.0 + ) ** (0.41 - 1) * (1 / 1000) dSCW_dULF = ( 0.525 * c_mass_trend_wing_control @@ -2243,108 +2600,111 @@ def compute_partials(self, inputs, J): * 1.15 / 391 ) - dSCW_dCCWC = - (gross_wt_initial / 1000.0) ** 0.41 + dSCW_dCCWC = -((gross_wt_initial / 1000.0) ** 0.41) J[ Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT] = \ - dSCW_dSWCC / GRAV_ENGLISH_LBM + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, + ] = dSCW_dSWCC / GRAV_ENGLISH_LBM - J[ - Aircraft.Controls.TOTAL_MASS, - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT] = \ + J[Aircraft.Controls.TOTAL_MASS, Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT] = ( CK18 * dSCW_dSWCC / GRAV_ENGLISH_LBM + ) - J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.AREA] = dSCW_dWA / \ - GRAV_ENGLISH_LBM + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.AREA] = dSCW_dWA / GRAV_ENGLISH_LBM - J[Aircraft.Controls.TOTAL_MASS, Aircraft.Wing.AREA] = CK18 * \ - dSCW_dWA / GRAV_ENGLISH_LBM + J[Aircraft.Controls.TOTAL_MASS, Aircraft.Wing.AREA] = CK18 * dSCW_dWA / GRAV_ENGLISH_LBM J[Aircraft.Wing.SURFACE_CONTROL_MASS, Mission.Design.GROSS_MASS] = dSCW_dWG - J[Aircraft.Controls.TOTAL_MASS, Mission.Design.GROSS_MASS] = 0.41 * CK15 * ( - c_mass_trend_cockpit_control - * (gross_wt_initial / 1000.0) ** (0.41 - 1) - * (1 / 1000) - ) + CK18 * dSCW_dWG - J[Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = dSCW_dULF / GRAV_ENGLISH_LBM - - J[Aircraft.Controls.TOTAL_MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = CK18 * \ + J[Aircraft.Controls.TOTAL_MASS, Mission.Design.GROSS_MASS] = ( + 0.41 + * CK15 + * ( + c_mass_trend_cockpit_control + * (gross_wt_initial / 1000.0) ** (0.41 - 1) + * (1 / 1000) + ) + + CK18 * dSCW_dWG + ) + J[Aircraft.Wing.SURFACE_CONTROL_MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ( dSCW_dULF / GRAV_ENGLISH_LBM - J[Aircraft.Wing.SURFACE_CONTROL_MASS, "min_dive_vel"] = dSCW_dMDV / \ - GRAV_ENGLISH_LBM - J[Aircraft.Controls.TOTAL_MASS, "min_dive_vel"] = CK18 * \ - dSCW_dMDV / GRAV_ENGLISH_LBM + ) + + J[Aircraft.Controls.TOTAL_MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ( + CK18 * dSCW_dULF / GRAV_ENGLISH_LBM + ) + J[Aircraft.Wing.SURFACE_CONTROL_MASS, 'min_dive_vel'] = dSCW_dMDV / GRAV_ENGLISH_LBM + J[Aircraft.Controls.TOTAL_MASS, 'min_dive_vel'] = CK18 * dSCW_dMDV / GRAV_ENGLISH_LBM J[ Aircraft.Wing.SURFACE_CONTROL_MASS, - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT] = \ - dSCW_dCCWC / GRAV_ENGLISH_LBM + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, + ] = dSCW_dCCWC / GRAV_ENGLISH_LBM J[ Aircraft.Controls.TOTAL_MASS, - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT] = ( - CK15 * (gross_wt_initial / 1000.0) ** 0.41 - + CK18 * dSCW_dCCWC - ) / GRAV_ENGLISH_LBM - - J[Aircraft.Controls.TOTAL_MASS, - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS] = CK19 + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, + ] = (CK15 * (gross_wt_initial / 1000.0) ** 0.41 + CK18 * dSCW_dCCWC) / GRAV_ENGLISH_LBM J[ Aircraft.Controls.TOTAL_MASS, - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER] = \ + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, + ] = CK19 + + J[Aircraft.Controls.TOTAL_MASS, Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER] = ( cockpit_control_wt / GRAV_ENGLISH_LBM + ) - J[ - Aircraft.Controls.TOTAL_MASS, - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] = \ + J[Aircraft.Controls.TOTAL_MASS, Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER] = ( wing_control_wt / GRAV_ENGLISH_LBM + ) - J[Aircraft.Controls.TOTAL_MASS, - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER] = stab_aug_wt + J[ + Aircraft.Controls.TOTAL_MASS, + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, + ] = stab_aug_wt J[Aircraft.Controls.TOTAL_MASS, Aircraft.Controls.CONTROL_MASS_INCREMENT] = 1 class GearMass(om.ExplicitComponent): - """ - Computation of total mass of landing gear and mass of main landing gear. - """ + """Computation of total mass of landing gear and mass of main landing gear.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - - add_aviary_input(self, Aircraft.Wing.MOUNTING_TYPE, val=0) - add_aviary_input(self, Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04) - add_aviary_input(self, Mission.Design.GROSS_MASS, val=152000) - add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85) - add_aviary_input(self, Aircraft.Nacelle.CLEARANCE_RATIO, - val=np.full(num_engine_type, 0.2), units="unitless") - add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, - val=np.full(num_engine_type, 7.5)) - - add_aviary_output(self, Aircraft.LandingGear.TOTAL_MASS, val=0) - add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_MASS, val=0, units="lbm", - desc="WMG: mass of main gear") + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + add_aviary_input(self, Aircraft.Wing.VERTICAL_MOUNT_LOCATION, units='unitless') + add_aviary_input(self, Aircraft.LandingGear.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, units='unitless') + add_aviary_input( + self, + Aircraft.Nacelle.CLEARANCE_RATIO, + shape=num_engine_type, + units='unitless', + ) + add_aviary_input(self, Aircraft.Nacelle.AVG_DIAMETER, shape=num_engine_type, units='ft') + + add_aviary_output(self, Aircraft.LandingGear.TOTAL_MASS, units='lbm') + add_aviary_output(self, Aircraft.LandingGear.MAIN_GEAR_MASS, units='lbm') + + def setup_partials(self): self.declare_partials( - Aircraft.LandingGear.TOTAL_MASS, [ - Aircraft.LandingGear.MASS_COEFFICIENT, Mission.Design.GROSS_MASS, - Aircraft.Nacelle.CLEARANCE_RATIO, Aircraft.Nacelle.AVG_DIAMETER] + Aircraft.LandingGear.TOTAL_MASS, + [ + Aircraft.LandingGear.MASS_COEFFICIENT, + Mission.Design.GROSS_MASS, + Aircraft.Nacelle.CLEARANCE_RATIO, + Aircraft.Nacelle.AVG_DIAMETER, + ], ) - self.declare_partials(Aircraft.LandingGear.MAIN_GEAR_MASS, "*") + self.declare_partials(Aircraft.LandingGear.MAIN_GEAR_MASS, '*') def compute(self, inputs, outputs): - wing_loc = inputs[Aircraft.Wing.MOUNTING_TYPE] + wing_loc = inputs[Aircraft.Wing.VERTICAL_MOUNT_LOCATION] c_gear_mass = inputs[Aircraft.LandingGear.MASS_COEFFICIENT] gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM c_main_gear = inputs[Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT] @@ -2355,36 +2715,36 @@ def compute(self, inputs, outputs): # TODO this does not match variable description (e.g. clearance ratio of 1.0 is # actually two nacelle diameters above ground) # Note: KSFunction for smooth derivatives. - gear_height_temp = KSfunction.compute( - (1.0 + clearance_ratio) * nacelle_diam, 50.0) + gear_height_temp = KSfunction.compute((1.0 + clearance_ratio) * nacelle_diam, 50.0) # A minimum gear height of 6 feet is enforced here using a smoothing function to # prevent discontinuities in the function and it's derivatives. - gear_height = gear_height_temp * \ - sigX(gear_height_temp-6) + 6 * sigX(6-gear_height_temp) + gear_height_temp = gear_height_temp[0] + gear_height = gear_height_temp * sigmoidX(gear_height_temp, 6, 1 / 320.0) + 6 * sigmoidX( + gear_height_temp, 6, -1 / 320.0 + ) # Low wing aircraft (defined as having the wing at the lowest position on the # fuselage) have a separate equation for calculating gear mass. A smoothing # function centered at a wing height of .5% smooths the equations between 0 and - # 1%. The equations should produce no noticable difference between the stepwise + # 1%. The equations should produce no noticeable difference between the stepwise # versions at 0% and at or above 1%. - c_gear_mass_modified = ( - (c_gear_mass * 0.85 * (1.0 + 0.1765 * gear_height / 6.0)) - * sigX(100 * (.005 - wing_loc)) - + c_gear_mass * sigX(100 * (wing_loc - .005))) + c_gear_mass_modified = (c_gear_mass * 0.85 * (1.0 + 0.1765 * gear_height / 6.0)) * sigmoidX( + wing_loc, 0.005, -0.01 / 320 + ) + c_gear_mass * sigmoidX(wing_loc, 0.005, 0.01 / 320) landing_gear_wt = c_gear_mass_modified * gross_wt_initial - outputs[Aircraft.LandingGear.TOTAL_MASS] = landing_gear_wt / \ - GRAV_ENGLISH_LBM - outputs[Aircraft.LandingGear.MAIN_GEAR_MASS] = c_main_gear * \ - landing_gear_wt / GRAV_ENGLISH_LBM + outputs[Aircraft.LandingGear.TOTAL_MASS] = landing_gear_wt / GRAV_ENGLISH_LBM + outputs[Aircraft.LandingGear.MAIN_GEAR_MASS] = ( + c_main_gear * landing_gear_wt / GRAV_ENGLISH_LBM + ) def compute_partials(self, inputs, J): c_gear_mass = inputs[Aircraft.LandingGear.MASS_COEFFICIENT] gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM c_main_gear = inputs[Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT] - wing_loc = inputs[Aircraft.Wing.MOUNTING_TYPE] + wing_loc = inputs[Aircraft.Wing.VERTICAL_MOUNT_LOCATION] clearance_ratio = inputs[Aircraft.Nacelle.CLEARANCE_RATIO] nacelle_diam = inputs[Aircraft.Nacelle.AVG_DIAMETER] @@ -2392,65 +2752,73 @@ def compute_partials(self, inputs, J): gear_height_temp = KSfunction.compute(val, 50.0) dKS, _ = KSfunction.derivatives(val, 50.0) - gear_height = gear_height_temp * \ - sigX(gear_height_temp-6) + 6 * sigX(6-gear_height_temp) + gear_height_temp = gear_height_temp[0] + gear_height = gear_height_temp * sigmoidX(gear_height_temp, 6, 1 / 320.0) + +6 * sigmoidX(gear_height_temp, 6, -1 / 320.0) dLGW_dCGW = ( - (0.85 * (1.0 + 0.1765 * gear_height / 6.0)) - * sigX(100 * (.005 - wing_loc)) - + sigX(100 * (wing_loc - .005))) * gross_wt_initial + (0.85 * (1.0 + 0.1765 * gear_height / 6.0)) * sigmoidX(wing_loc, 0.005, -0.01 / 320.0) + + sigmoidX(wing_loc, 0.005, 0.01 / 320.0) + ) * gross_wt_initial dGH_dCR = ( ( - sigX(gear_height_temp - 6) * nacelle_diam - + gear_height_temp * dSigXdX(gear_height_temp - 6) * nacelle_diam) - + (6 * dSigXdX(6 - gear_height_temp) * -nacelle_diam)) * dKS + sigmoidX(gear_height_temp, 6, 1 / 320.0) * nacelle_diam + + gear_height_temp * dSigmoidXdx(gear_height_temp, 6, 1 / 320.0) * nacelle_diam + ) + + (6 * dSigmoidXdx(gear_height_temp, 6, 1 / 320.0) * -nacelle_diam) + ) * dKS dGH_dND = ( - ( - sigX(gear_height_temp - 6) * (1 + clearance_ratio) - + gear_height_temp * dSigXdX(gear_height_temp - 6) - * (1 + clearance_ratio)) * dKS + sigmoidX(gear_height_temp, 6, 1 / 320.0) * (1 + clearance_ratio) + + gear_height_temp * dSigmoidXdx(gear_height_temp, 6, 1 / 320.0) * (1 + clearance_ratio) + ) * dKS + (6 * dSigmoidXdx(gear_height_temp, 6, 1 / 320.0) * (1 + clearance_ratio)) - + (6 * dSigXdX(6 - gear_height_temp) * (1 + clearance_ratio))) - - c_gear_mass_modified = ( - (c_gear_mass * 0.85 * (1.0 + 0.1765 * gear_height / 6.0)) - * sigX(100 * (.005 - wing_loc)) - + c_gear_mass * sigX(100 * (wing_loc - .005))) + c_gear_mass_modified = (c_gear_mass * 0.85 * (1.0 + 0.1765 * gear_height / 6.0)) * sigmoidX( + wing_loc, 0.005, -0.01 / 320.0 + ) + c_gear_mass * sigmoidX(wing_loc, 0.005, 0.01 / 320.0) dLGW_dCR = max( (c_gear_mass * 0.85 * 0.1765 / 6 * dGH_dCR * gross_wt_initial) - * sigX(100 * (.005 - wing_loc))) + * sigmoidX(wing_loc, 0.005, -0.01 / 320.0) + ) dLGW_dND = max( (c_gear_mass * 0.85 * 0.1765 / 6 * dGH_dND * gross_wt_initial) - * sigX(100 * (.005 - wing_loc))) + * sigmoidX(wing_loc, 0.005, -0.01 / 320.0) + ) - J[Aircraft.LandingGear.TOTAL_MASS, Aircraft.LandingGear.MASS_COEFFICIENT] = \ + J[Aircraft.LandingGear.TOTAL_MASS, Aircraft.LandingGear.MASS_COEFFICIENT] = ( dLGW_dCGW / GRAV_ENGLISH_LBM + ) - J[Aircraft.LandingGear.TOTAL_MASS, Aircraft.Nacelle.CLEARANCE_RATIO] = \ + J[Aircraft.LandingGear.TOTAL_MASS, Aircraft.Nacelle.CLEARANCE_RATIO] = ( dLGW_dCR / GRAV_ENGLISH_LBM + ) - J[Aircraft.LandingGear.TOTAL_MASS, Aircraft.Nacelle.AVG_DIAMETER] = \ + J[Aircraft.LandingGear.TOTAL_MASS, Aircraft.Nacelle.AVG_DIAMETER] = ( dLGW_dND / GRAV_ENGLISH_LBM + ) - J[Aircraft.LandingGear.TOTAL_MASS, Mission.Design.GROSS_MASS] = \ - c_gear_mass_modified + J[Aircraft.LandingGear.TOTAL_MASS, Mission.Design.GROSS_MASS] = c_gear_mass_modified - J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.Nacelle.CLEARANCE_RATIO] = \ + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.Nacelle.CLEARANCE_RATIO] = ( c_main_gear * dLGW_dCR / GRAV_ENGLISH_LBM + ) - J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.Nacelle.AVG_DIAMETER] = \ + J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.Nacelle.AVG_DIAMETER] = ( c_main_gear * dLGW_dND / GRAV_ENGLISH_LBM + ) J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.MASS_COEFFICIENT] = ( - c_main_gear * dLGW_dCGW * sigX(100 * (.005 - wing_loc)) - + c_main_gear * gross_wt_initial * sigX(100 * (wing_loc - .005))) / GRAV_ENGLISH_LBM + c_main_gear * dLGW_dCGW * sigmoidX(wing_loc, 0.005, -0.01 / 320.0) + + c_main_gear * gross_wt_initial * sigmoidX(wing_loc, 0.005, 0.01 / 320.0) + ) / GRAV_ENGLISH_LBM - J[Aircraft.LandingGear.MAIN_GEAR_MASS, Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT] = \ - c_gear_mass_modified * gross_wt_initial / GRAV_ENGLISH_LBM + J[ + Aircraft.LandingGear.MAIN_GEAR_MASS, + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, + ] = c_gear_mass_modified * gross_wt_initial / GRAV_ENGLISH_LBM J[Aircraft.LandingGear.MAIN_GEAR_MASS, Mission.Design.GROSS_MASS] = ( c_gear_mass_modified * c_main_gear @@ -2458,93 +2826,74 @@ def compute_partials(self, inputs, J): class FixedMassGroup(om.Group): - """ - Group of all fixed mass components for GASP-based mass. - """ + """Group of all fixed mass components for GASP-based mass.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Electrical.HAS_HYBRID_SYSTEM) def setup(self): - aviary_options: AviaryValues = self.options['aviary_options'] - - n_eng = aviary_options.get_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, units='unitless') - self.add_subsystem( - "params", - MassParameters( - aviary_options=aviary_options, - ), - promotes_inputs=["max_mach", ] + ["aircraft:*"], - promotes_outputs=["c_strut_braced", "c_gear_loc", - "half_sweep", ] + ["aircraft:*"], + 'params', + MassParameters(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "payload", - PayloadMass(aviary_options=aviary_options), - promotes_inputs=["aircraft:*"], - promotes_outputs=["payload_mass_des", "payload_mass_max", ] + ["aircraft:*"], + 'payload', + PayloadGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "tail", - TailMass(aviary_options=aviary_options), - promotes_inputs=["min_dive_vel", ] + ["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], + 'tail', + TailMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "HL", - HighLiftMass(aviary_options=aviary_options), - promotes_inputs=["density"] + ["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], + 'HL', + HighLiftMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "controls", - ControlMass(aviary_options=aviary_options), - promotes_inputs=["min_dive_vel", ] + ["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], + 'controls', + ControlMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "gear", - GearMass(aviary_options=aviary_options), - promotes_inputs=["mission:*", "aircraft:*"], - promotes_outputs=[Aircraft.LandingGear.MAIN_GEAR_MASS, ] + ["aircraft:*"], + 'gear', + GearMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - has_hybrid_system = aviary_options.get_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, units='unitless') + has_hybrid_system = self.options[Aircraft.Electrical.HAS_HYBRID_SYSTEM] if has_hybrid_system: self.add_subsystem( - "augmentation", - ElectricAugmentationMass( - aviary_options=aviary_options, - ), - promotes_inputs=["aircraft:*"], - promotes_outputs=["aug_mass", ], + 'augmentation', + ElectricAugmentationMass(), + promotes_inputs=['*'], + promotes_outputs=['aug_mass'], ) self.add_subsystem( - "engine", - EngineMass(aviary_options=aviary_options), - promotes_inputs=["aircraft:*"] + [Aircraft.LandingGear.MAIN_GEAR_MASS, ], - promotes_outputs=["wing_mounted_mass", "eng_comb_mass"] + ["aircraft:*"], + 'engine', + EngineMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) if has_hybrid_system: self.promotes( - "engine", - inputs=["aug_mass", ], + 'engine', + inputs=['aug_mass'], ) - self.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units="lbm") - self.set_input_defaults("min_dive_vel", val=420, units="kn") - self.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units="ft**2") + self.set_input_defaults('min_dive_vel', val=420, units='kn') diff --git a/aviary/subsystems/mass/gasp_based/fuel.py b/aviary/subsystems/mass/gasp_based/fuel.py index b9b973fc9a..4a237e5b84 100644 --- a/aviary/subsystems/mass/gasp_based/fuel.py +++ b/aviary/subsystems/mass/gasp_based/fuel.py @@ -1,30 +1,14 @@ import numpy as np - import openmdao.api as om +from openmdao.utils.units import convert_units + from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.enums import Verbosity -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.utils.functions import d_smooth_max, dSigmoidXdx, sigmoidX, smooth_max +from aviary.variable_info.enums import AircraftTypes, Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission, Settings -check = 1 - - -def sigX(x): - sig = 1 / (1 + np.exp(-check * x)) - - return sig - - -def dSigXdX(x): - # avoid overflow in squared term, underflow seems to be ok - if x[0] < -300: - return 0 - derivative = -1 / (1 + np.exp(-check * x)) ** 2 * (-check * np.exp(-check * x)) - - return derivative - class BodyTankCalculations(om.ExplicitComponent): """ @@ -32,67 +16,71 @@ class BodyTankCalculations(om.ExplicitComponent): along with mass of fuel in it, and minimum wing fuel mass. """ + def __init__(self, **kwargs): + super().__init__(**kwargs) + + # Flag so warning doesn't print constantly. + self.warned_vol = False + self.warned_mass = False + def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, True) + add_aviary_option(self, Settings.VERBOSITY) + self.options.declare('mu', default=1.0, types=float) def setup(self): - - add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_DESIGN, val=2) - add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=3) + add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_DESIGN, units='ft**3') + add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, units='ft**3') self.add_input( - "fuel_mass_min", + 'fuel_mass_min', val=2000, - units="lbm", - desc="WFAMIN: minimum value of fuel mass (set when max payload is carried)", + units='lbm', + desc='WFAMIN: minimum value of fuel mass (set when max payload is carried)', ) - add_aviary_input(self, Mission.Design.FUEL_MASS_REQUIRED, val=7) - self.add_input( - "max_wingfuel_mass", val=6, units="lbm", desc="WFWMX: maximum wingfuel mass" + add_aviary_input( + self, Mission.Summary.FUEL_MASS_REQUIRED, units='lbm', desc='WFAREQ: no margin' ) - add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=5000) - add_aviary_input(self, Aircraft.Fuel.DENSITY, val=6.687, units="lbm/ft**3") - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400) - add_aviary_input(self, Mission.Design.FUEL_MASS, val=3000) - add_aviary_input(self, Aircraft.Design.OPERATING_MASS, val=94417) + self.add_input('max_wingfuel_mass', val=6, units='lbm', desc='WFWMX: maximum wingfuel mass') + add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, units='ft**3') + add_aviary_input(self, Aircraft.Fuel.DENSITY, units='lbm/galUS') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Mission.Summary.FUEL_MASS, units='lbm') + add_aviary_input(self, Mission.Summary.OPERATING_MASS, units='lbm') + # WFXTRA: extra amount of fuel that is required but does not fit in wings + add_aviary_output(self, Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, units='lbm') self.add_output( - Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, + 'extra_fuel_volume', val=0, - units="lbm", - desc="WFXTRA: extra amount of fuel that is required but does not fit in wings", - ) + units='ft**3', + desc='FVOLXTRA: excess required design fuel volume (including fuel margin) greater than geometric fuel volume of wings', + ) # there is no FVOLXTRA in GASP self.add_output( - "extra_fuel_volume", + 'max_extra_fuel_mass', val=0, - units="ft**3", - desc="FVOLXTRA: excess required design fuel volume (including fuel margin) greater than geometric fuel volume of wings", - ) + units='lbm', + desc='WFXTRAMX: mass of fuel that fits in extra_fuel_volume', + ) # there is no WFXTRAMX in GASP self.add_output( - "max_extra_fuel_mass", - val=0, - units="lbm", - desc="WFXTRAMX: mass of fuel that fits in extra_fuel_volume", + 'wingfuel_mass_min', val=0, units='lbm', desc='WFWMIN: minimum wing fuel mass' ) - self.add_output( - "wingfuel_mass_min", - val=0, - units="lbm", - desc="WFWMIN: minimum wing fuel mass", - ) - add_aviary_output(self, Aircraft.Fuel.TOTAL_CAPACITY, val=0) + add_aviary_output(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm', desc='WFAMAX') - self.declare_partials(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, [ - Mission.Design.FUEL_MASS_REQUIRED, "max_wingfuel_mass"]) + def setup_partials(self): + self.declare_partials( + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, + [Mission.Summary.FUEL_MASS_REQUIRED, 'max_wingfuel_mass'], + ) self.declare_partials( - "extra_fuel_volume", - [Aircraft.Fuel.WING_VOLUME_DESIGN, Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], + 'extra_fuel_volume', + [ + Aircraft.Fuel.WING_VOLUME_DESIGN, + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, + ], ) self.declare_partials( - "max_extra_fuel_mass", + 'max_extra_fuel_mass', [ Aircraft.Fuel.WING_VOLUME_DESIGN, Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, @@ -101,9 +89,9 @@ def setup(self): ], ) self.declare_partials( - "wingfuel_mass_min", + 'wingfuel_mass_min', [ - "fuel_mass_min", + 'fuel_mass_min', Aircraft.Fuel.WING_VOLUME_DESIGN, Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, @@ -113,243 +101,394 @@ def setup(self): self.declare_partials( Aircraft.Fuel.TOTAL_CAPACITY, [ - Mission.Design.FUEL_MASS, - Mission.Design.FUEL_MASS_REQUIRED, - "max_wingfuel_mass", + Mission.Summary.FUEL_MASS, + Mission.Summary.FUEL_MASS_REQUIRED, + 'max_wingfuel_mass', Mission.Design.GROSS_MASS, - Aircraft.Design.OPERATING_MASS, + Mission.Summary.OPERATING_MASS, ], ) def compute(self, inputs, outputs): - design_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_DESIGN] max_wingfuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] - fuel_wt_min = inputs["fuel_mass_min"] * GRAV_ENGLISH_LBM - req_fuel_wt = inputs[Mission.Design.FUEL_MASS_REQUIRED] * \ - GRAV_ENGLISH_LBM - max_wingfuel_wt = inputs["max_wingfuel_mass"] * GRAV_ENGLISH_LBM - geometric_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] - rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM + fuel_wt_min = inputs['fuel_mass_min'] * GRAV_ENGLISH_LBM + req_fuel_wt = inputs[Mission.Summary.FUEL_MASS_REQUIRED] * GRAV_ENGLISH_LBM + max_wingfuel_wt = inputs['max_wingfuel_mass'] * GRAV_ENGLISH_LBM + geom_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] + rho_fuel = ( + convert_units(inputs[Aircraft.Fuel.DENSITY], 'lbm/galUS', 'lbm/ft**3') + * GRAV_ENGLISH_LBM + ) gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - fuel_wt_des = inputs[Mission.Design.FUEL_MASS] * GRAV_ENGLISH_LBM - OEW = inputs[Aircraft.Design.OPERATING_MASS] * GRAV_ENGLISH_LBM + fuel_wt_des = inputs[Mission.Summary.FUEL_MASS] * GRAV_ENGLISH_LBM + OEW = inputs[Mission.Summary.OPERATING_MASS] * GRAV_ENGLISH_LBM - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + mu = self.options['mu'] - extra_fuel_volume = sigX(design_fuel_vol - max_wingfuel_vol) * ( - design_fuel_vol - geometric_fuel_vol - ) + if smooth: + extra_fuel_volume = sigmoidX(design_fuel_vol - max_wingfuel_vol, 0) * ( + design_fuel_vol - geom_fuel_vol + ) + else: + if design_fuel_vol < max_wingfuel_vol: + extra_fuel_volume = 0.0 + else: + extra_fuel_volume = design_fuel_vol - geom_fuel_vol + # make sure extra_fuel_volume is not negative + if smooth: + extra_fuel_volume = smooth_max(extra_fuel_volume, 0.0, mu) + else: + extra_fuel_volume = np.maximum(extra_fuel_volume, 0.0) - verbosity = self.options['aviary_options'].get_val(Settings.VERBOSITY) + max_extra_fuel_wt = extra_fuel_volume * rho_fuel + + verbosity = self.options[Settings.VERBOSITY] if verbosity >= Verbosity.BRIEF: if (req_fuel_wt > max_wingfuel_wt) and (design_fuel_vol > max_wingfuel_vol): - print("Warning: req_fuel_mass > max_wingfuel_mass, adding a body tank") + if not self.warned_mass: + print('Warning: req_fuel_mass > max_wingfuel_mass, adding a body tank') + self.warned_mass = True + else: + self.warned_mass = False + if (req_fuel_wt < max_wingfuel_wt) and (design_fuel_vol > max_wingfuel_vol): - print("Warning: design_fuel_vol > max_wingfuel_vol, adding a body tank") + if not self.warned_vol: + print('Warning: design_fuel_vol > max_wingfuel_vol, adding a body tank') + self.warned_vol = True + else: + self.warned_vol = False + # TODO: where is the code that adds a body tank? extra_fuel_wt = req_fuel_wt - max_wingfuel_wt if smooth: - extra_fuel_wt = extra_fuel_wt * sigX(extra_fuel_wt / 50) + extra_fuel_wt = extra_fuel_wt * sigmoidX(extra_fuel_wt, 0, 1 / 50) else: if extra_fuel_wt < 0: extra_fuel_wt = 0 - max_extra_fuel_wt = extra_fuel_volume * rho_fuel + wingfuel_wt_min = fuel_wt_min - max_extra_fuel_wt - wingfuel_wt_min = wingfuel_wt_min * sigX(wingfuel_wt_min) + if smooth: + wingfuel_wt_min = wingfuel_wt_min * sigmoidX(wingfuel_wt_min, 0) + else: + if wingfuel_wt_min < 0.0: + wingfuel_wt_min = 0.0 + max_fuel_avail_est = fuel_wt_des + extra_fuel_wt max_fuel_avail_new = gross_wt_initial - OEW est_GTOW = OEW + max_fuel_avail_est - max_fuel_avail = max_fuel_avail_est * sigX( - (gross_wt_initial - est_GTOW) / 110 - ) + max_fuel_avail_new * sigX((est_GTOW - gross_wt_initial) / 110) - - outputs[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY] = \ - extra_fuel_wt / GRAV_ENGLISH_LBM - outputs["extra_fuel_volume"] = extra_fuel_volume - outputs["max_extra_fuel_mass"] = max_extra_fuel_wt / GRAV_ENGLISH_LBM - outputs["wingfuel_mass_min"] = wingfuel_wt_min / GRAV_ENGLISH_LBM - outputs[Aircraft.Fuel.TOTAL_CAPACITY] = \ - max_fuel_avail / GRAV_ENGLISH_LBM + if smooth: + max_fuel_avail = max_fuel_avail_est * sigmoidX( + gross_wt_initial - est_GTOW, 0, 1.0 / 110.0 + ) + max_fuel_avail_new * sigmoidX(est_GTOW - gross_wt_initial, 0, 1 / 110.0) + else: + if gross_wt_initial > est_GTOW: + max_fuel_avail = max_fuel_avail_est + elif gross_wt_initial < est_GTOW: + max_fuel_avail = max_fuel_avail_new + else: + max_fuel_avail = (max_fuel_avail_est + max_fuel_avail_new) / 2.0 + + outputs[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY] = extra_fuel_wt / GRAV_ENGLISH_LBM + outputs['extra_fuel_volume'] = extra_fuel_volume + outputs['max_extra_fuel_mass'] = max_extra_fuel_wt / GRAV_ENGLISH_LBM + + # pass back to FuelSysAndFullFuselageMass + outputs['wingfuel_mass_min'] = wingfuel_wt_min / GRAV_ENGLISH_LBM + # pass back to FuelAndOEMOutputs + outputs[Aircraft.Fuel.TOTAL_CAPACITY] = max_fuel_avail / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - design_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_DESIGN] max_wingfuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] - fuel_wt_min = inputs["fuel_mass_min"] * GRAV_ENGLISH_LBM - req_fuel_wt = inputs[Mission.Design.FUEL_MASS_REQUIRED] * \ - GRAV_ENGLISH_LBM - max_wingfuel_wt = inputs["max_wingfuel_mass"] * GRAV_ENGLISH_LBM - geometric_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] - rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM + fuel_wt_min = inputs['fuel_mass_min'] * GRAV_ENGLISH_LBM + req_fuel_wt = inputs[Mission.Summary.FUEL_MASS_REQUIRED] * GRAV_ENGLISH_LBM + max_wingfuel_wt = inputs['max_wingfuel_mass'] * GRAV_ENGLISH_LBM + geom_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] + rho_fuel = ( + convert_units(inputs[Aircraft.Fuel.DENSITY], 'lbm/galUS', 'lbm/ft**3') + * GRAV_ENGLISH_LBM + ) gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - fuel_wt_des = inputs[Mission.Design.FUEL_MASS] * GRAV_ENGLISH_LBM - OEW = inputs[Aircraft.Design.OPERATING_MASS] * GRAV_ENGLISH_LBM + fuel_wt_des = inputs[Mission.Summary.FUEL_MASS] * GRAV_ENGLISH_LBM + OEW = inputs[Mission.Summary.OPERATING_MASS] * GRAV_ENGLISH_LBM - smooth = self.options["aviary_options"].get_val( - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, units='unitless') + smooth = self.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] + mu = self.options['mu'] - extra_fuel_volume = sigX(design_fuel_vol - max_wingfuel_vol) * ( - design_fuel_vol - geometric_fuel_vol - ) + # partials of extra_fuel_volume + if smooth: + extra_fuel_volume = sigmoidX(design_fuel_vol - max_wingfuel_vol, 0) * ( + design_fuel_vol - geom_fuel_vol + ) + dextra_fuel_volume_ddesign_fuel_vol = dSigmoidXdx( + design_fuel_vol - max_wingfuel_vol, 0 + ) * (design_fuel_vol - geom_fuel_vol) + sigmoidX(design_fuel_vol - max_wingfuel_vol, 0) + dextra_fuel_volume_dmax_wingfuel_vol = dSigmoidXdx( + design_fuel_vol - max_wingfuel_vol, 0 + ) * -(design_fuel_vol - geom_fuel_vol) + dextra_fuel_volume_dgeom_fuel_vol = -sigmoidX(design_fuel_vol - max_wingfuel_vol, 0) + else: + if design_fuel_vol < max_wingfuel_vol: + extra_fuel_volume = 0.0 + dextra_fuel_volume_ddesign_fuel_vol = 0.0 + dextra_fuel_volume_dmax_wingfuel_vol = 0.0 + dextra_fuel_volume_dgeom_fuel_vol = 0.0 + else: + extra_fuel_volume = design_fuel_vol - geom_fuel_vol + dextra_fuel_volume_ddesign_fuel_vol = 1.0 + dextra_fuel_volume_dmax_wingfuel_vol = 0.0 + dextra_fuel_volume_dgeom_fuel_vol = -1.0 + # make sure extra_fuel_volume is not negative + if smooth: + sm_fac = d_smooth_max(extra_fuel_volume, 0.0, mu) + dextra_fuel_volume_ddesign_fuel_vol = sm_fac * dextra_fuel_volume_ddesign_fuel_vol + dextra_fuel_volume_dmax_wingfuel_vol = sm_fac * dextra_fuel_volume_dmax_wingfuel_vol + dextra_fuel_volume_dgeom_fuel_vol = sm_fac * dextra_fuel_volume_dgeom_fuel_vol + extra_fuel_volume = smooth_max(extra_fuel_volume, 0.0, mu) + else: + if extra_fuel_volume < 0: + extra_fuel_volume = 0.0 + dextra_fuel_volume_ddesign_fuel_vol = 0.0 + dextra_fuel_volume_dmax_wingfuel_vol = 0.0 + dextra_fuel_volume_dgeom_fuel_vol = 0.0 + + # partials of max_extra_fuel_mass max_extra_fuel_wt = extra_fuel_volume * rho_fuel + dmax_extra_fuel_wt_ddesign_fuel_vol = dextra_fuel_volume_ddesign_fuel_vol * rho_fuel + dmax_extra_fuel_wt_dmax_wingfuel_vol = dextra_fuel_volume_dmax_wingfuel_vol * rho_fuel + dmax_extra_fuel_wt_dgeom_fuel_vol = dextra_fuel_volume_dgeom_fuel_vol * rho_fuel + dmax_extra_fuel_wt_drho_fuel = extra_fuel_volume + # Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY extra_fuel_wt = req_fuel_wt - max_wingfuel_wt + dextra_fuel_wt_dreq_fuel_wt = 1 + dextra_fuel_wt_dmax_wingfuel_wt = -1 if smooth: - extra_fuel_wt = extra_fuel_wt * sigX(extra_fuel_wt / 50) + extra_fuel_wt = extra_fuel_wt * sigmoidX(extra_fuel_wt, 0, 1 / 50.0) + dextra_fuel_wt_dreq_fuel_wt = ( + sigmoidX(req_fuel_wt - max_wingfuel_wt, 0, 1 / 50.0) + + (req_fuel_wt - max_wingfuel_wt) + * dSigmoidXdx(req_fuel_wt - max_wingfuel_wt, 0, 1 / 50.0) + * 1 + / 50 + ) + dextra_fuel_wt_dmax_wingfuel_wt = -1 * sigmoidX( + (req_fuel_wt - max_wingfuel_wt), 0, 1 / 50.0 + ) + (req_fuel_wt - max_wingfuel_wt) * dSigmoidXdx( + req_fuel_wt - max_wingfuel_wt, 0, 1 / 50.0 + ) * (-1 / 50) else: if extra_fuel_wt < 0: - extra_fuel_wt = 0 + extra_fuel_wt = 0.0 + dextra_fuel_wt_dreq_fuel_wt = 0.0 + dextra_fuel_wt_dmax_wingfuel_wt = 0.0 + + # partials of wingfuel_mass_min + wingfuel_wt_min = fuel_wt_min - max_extra_fuel_wt + dwingfuel_wt_min_dfuel_wt_min = 1 + dwingfuel_wt_min_ddesign_fuel_vol = -dmax_extra_fuel_wt_ddesign_fuel_vol + dwingfuel_wt_min_dmax_wingfuel_vol = -dmax_extra_fuel_wt_dmax_wingfuel_vol + dwingfuel_wt_min_dgeom_fuel_vol = -dmax_extra_fuel_wt_dgeom_fuel_vol + dwingfuel_wt_min_drho_fuel = -dmax_extra_fuel_wt_drho_fuel + if smooth: + wingfuel_wt_min = wingfuel_wt_min * sigmoidX(wingfuel_wt_min, 0) + dwingfuel_wt_min_dfuel_wt_min = ( + dwingfuel_wt_min_dfuel_wt_min * sigmoidX(wingfuel_wt_min, 0) + + wingfuel_wt_min * dSigmoidXdx(wingfuel_wt_min, 0) * dwingfuel_wt_min_dfuel_wt_min + ) + dwingfuel_wt_min_ddesign_fuel_vol = ( + dwingfuel_wt_min_ddesign_fuel_vol * sigmoidX(wingfuel_wt_min, 0) + + wingfuel_wt_min + * dSigmoidXdx(wingfuel_wt_min, 0) + * dwingfuel_wt_min_ddesign_fuel_vol + ) + dwingfuel_wt_min_dmax_wingfuel_vol = ( + dwingfuel_wt_min_dmax_wingfuel_vol * sigmoidX(wingfuel_wt_min, 0) + + wingfuel_wt_min + * dSigmoidXdx(wingfuel_wt_min, 0) + * dwingfuel_wt_min_dmax_wingfuel_vol + ) + dwingfuel_wt_min_dgeom_fuel_vol = ( + dwingfuel_wt_min_dgeom_fuel_vol * sigmoidX(wingfuel_wt_min, 0) + + wingfuel_wt_min + * dSigmoidXdx(wingfuel_wt_min, 0) + * dwingfuel_wt_min_dgeom_fuel_vol + ) + dwingfuel_wt_min_drho_fuel = ( + dwingfuel_wt_min_drho_fuel * sigmoidX(wingfuel_wt_min, 0) + + wingfuel_wt_min * dSigmoidXdx(wingfuel_wt_min, 0) * dwingfuel_wt_min_drho_fuel + ) + else: + if wingfuel_wt_min < 0.0: + wingfuel_wt_min = 0.0 + dwingfuel_wt_min_dfuel_wt_min = 0.0 + dwingfuel_wt_min_ddesign_fuel_vol = 0.0 + dwingfuel_wt_min_dmax_wingfuel_vol = 0.0 + dwingfuel_wt_min_dgeom_fuel_vol = 0.0 + dwingfuel_wt_min_drho_fuel = 0.0 + + # partials of Aircraft.Fuel.TOTAL_CAPACITY max_fuel_avail_est = fuel_wt_des + extra_fuel_wt + dmax_fuel_avail_est_dfuel_wt_des = 1 + dmax_fuel_avail_est_dreq_fuel_wt = dextra_fuel_wt_dreq_fuel_wt + dmax_fuel_avail_est_dmax_wingfuel_wt = dextra_fuel_wt_dmax_wingfuel_wt + dmax_fuel_avail_est_dgross_wt_initial = 0.0 + dmax_fuel_avail_est_dOEW = 0.0 + max_fuel_avail_new = gross_wt_initial - OEW - est_GTOW = OEW + max_fuel_avail_est + dmax_fuel_avail_new_dfuel_wt_des = 0.0 + dmax_fuel_avail_new_dreq_fuel_wt = 0.0 + dmax_fuel_avail_new_dmax_wingfuel_wt = 0.0 + dmax_fuel_avail_new_dgross_wt_initial = 1.0 + dmax_fuel_avail_new_dOEW = -1.0 + est_GTOW = OEW + fuel_wt_des + extra_fuel_wt if smooth: - dExtraFuelWt_dReqFuelWt = ( - sigX((req_fuel_wt - max_wingfuel_wt) / 50) - + (req_fuel_wt - max_wingfuel_wt) - * dSigXdX((req_fuel_wt - max_wingfuel_wt) / 50) - * 1 - / 50 + Int1 = sigmoidX(gross_wt_initial - est_GTOW, 0, 1 / 110.0) + Int2 = sigmoidX(est_GTOW - gross_wt_initial, 0, 1 / 110.0) + + # max_fuel_avail = max_fuel_avail_est * Int1 + max_fuel_avail_new * Int2 + dInt1_dfuel_wt_des = dSigmoidXdx(gross_wt_initial - est_GTOW, 0, 1 / 110.0) * ( + -1 / 110.0 + ) + dInt1_dreq_fuel_wt = ( + dSigmoidXdx(gross_wt_initial - est_GTOW, 0, 1 / 110.0) + * -dextra_fuel_wt_dreq_fuel_wt + / 100.0 + ) + dInt1_dmax_wingfuel_wt = ( + dSigmoidXdx(gross_wt_initial - est_GTOW, 0, 1 / 110.0) + * -dmax_extra_fuel_wt_dmax_wingfuel_vol + / 100.0 + ) + dInt1_dgross_wt_initial = dSigmoidXdx(gross_wt_initial - est_GTOW, 0, 1 / 110.0) / 110.0 + dInt1_dOEW = dSigmoidXdx(gross_wt_initial - est_GTOW, 0, 1 / 110.0) * (-1 / 110.0) + + dInt2_dfuel_wt_des = dSigmoidXdx(est_GTOW - gross_wt_initial, 0, 1 / 110.0) / 110.0 + dInt2_dreq_fuel_wt = ( + dSigmoidXdx(est_GTOW - gross_wt_initial, 0, 1 / 110.0) + * dextra_fuel_wt_dreq_fuel_wt + / 100.0 + ) + dInt2_dmax_wingfuel_wt = ( + dSigmoidXdx(est_GTOW - gross_wt_initial, 0, 1 / 110.0) + * dmax_extra_fuel_wt_dmax_wingfuel_vol + / 100.0 + ) + dInt2_dgross_wt_initial = dSigmoidXdx(est_GTOW - gross_wt_initial, 0, 1 / 110.0) * ( + -1 / 110.0 + ) + dInt2_dOEW = dSigmoidXdx(est_GTOW - gross_wt_initial, 0, 1 / 110.0) / 110.0 + dmax_fuel_avail_dfuel_wt_des = ( + dmax_fuel_avail_est_dfuel_wt_des * Int1 + + max_fuel_avail_est * dInt1_dfuel_wt_des + + dmax_fuel_avail_new_dfuel_wt_des * Int2 + + max_fuel_avail_new * dInt2_dfuel_wt_des + ) + dmax_fuel_avail_dreq_fuel_wt = ( + dmax_fuel_avail_est_dreq_fuel_wt * Int1 + + max_fuel_avail_est * dInt1_dreq_fuel_wt + + dmax_fuel_avail_new_dreq_fuel_wt * Int2 + + max_fuel_avail_new * dInt2_dreq_fuel_wt + ) + dmax_fuel_avail_dmax_wingfuel_wt = ( + dmax_fuel_avail_est_dmax_wingfuel_wt * Int1 + + max_fuel_avail_est * dInt1_dmax_wingfuel_wt + + dmax_fuel_avail_new_dmax_wingfuel_wt * Int2 + + max_fuel_avail_new * dInt2_dmax_wingfuel_wt ) - dExtraFuelWt_dMaxWingfuelWt = -1 * sigX( - (req_fuel_wt - max_wingfuel_wt) / 50 - ) + (req_fuel_wt - max_wingfuel_wt) * dSigXdX( - (req_fuel_wt - max_wingfuel_wt) / 50 - ) * ( - -1 / 50 + dmax_fuel_avail_dgross_wt_initial = ( + dmax_fuel_avail_est_dgross_wt_initial * Int1 + + max_fuel_avail_est * dInt1_dgross_wt_initial + + dmax_fuel_avail_new_dgross_wt_initial * Int2 + + max_fuel_avail_new * dInt2_dgross_wt_initial + ) + dmax_fuel_avail_dOEW = ( + dmax_fuel_avail_est_dOEW * Int1 + + max_fuel_avail_est * dInt1_dOEW + + dmax_fuel_avail_new_dOEW * Int2 + + max_fuel_avail_new * dInt2_dOEW ) else: - dExtraFuelWt_dReqFuelWt = 1 if extra_fuel_wt > 0 else 0 - dExtraFuelWt_dMaxWingfuelWt = -1 if extra_fuel_wt > 0 else 0 - J[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - Mission.Design.FUEL_MASS_REQUIRED] = dExtraFuelWt_dReqFuelWt - J[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, - "max_wingfuel_mass"] = dExtraFuelWt_dMaxWingfuelWt - - J["extra_fuel_volume", Aircraft.Fuel.WING_VOLUME_DESIGN] = dSigXdX( - design_fuel_vol - max_wingfuel_vol - ) * (design_fuel_vol - geometric_fuel_vol) + sigX( - design_fuel_vol - max_wingfuel_vol - ) - J["extra_fuel_volume", Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] = ( - dSigXdX(design_fuel_vol - max_wingfuel_vol) - * (-1) - * (design_fuel_vol - geometric_fuel_vol) - ) - J["extra_fuel_volume", Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = -sigX( - design_fuel_vol - max_wingfuel_vol - ) - - dMEFWt_dDesFuelVol = ( - dSigXdX(design_fuel_vol - max_wingfuel_vol) - * (design_fuel_vol - geometric_fuel_vol) - + sigX(design_fuel_vol - max_wingfuel_vol) - ) * rho_fuel - dMEFWt_dMaxWingfuelVol = ( - dSigXdX(design_fuel_vol - max_wingfuel_vol) - * (-1) - * (design_fuel_vol - geometric_fuel_vol) - * rho_fuel + if gross_wt_initial > est_GTOW: + # max_fuel_avail = max_fuel_avail_est + dmax_fuel_avail_dfuel_wt_des = 1.0 + dmax_fuel_avail_dreq_fuel_wt = dextra_fuel_wt_dreq_fuel_wt + dmax_fuel_avail_dmax_wingfuel_wt = dmax_fuel_avail_est_dmax_wingfuel_wt + dmax_fuel_avail_dgross_wt_initial = 0.0 + dmax_fuel_avail_dOEW = 0.0 + elif gross_wt_initial < est_GTOW: + # max_fuel_avail = max_fuel_avail_new + dmax_fuel_avail_dfuel_wt_des = 0.0 + dmax_fuel_avail_dreq_fuel_wt = 0.0 + dmax_fuel_avail_dmax_wingfuel_wt = 0.0 + dmax_fuel_avail_dgross_wt_initial = 1.0 + dmax_fuel_avail_dOEW = -1.0 + else: + # max_fuel_avail = (max_fuel_avail_est + max_fuel_avail_new) / 2.0 + dmax_fuel_avail_dfuel_wt_des = 1.0 / 2.0 + dmax_fuel_avail_dreq_fuel_wt = dextra_fuel_wt_dreq_fuel_wt / 2.0 + dmax_fuel_avail_dmax_wingfuel_wt = 0.0 + dmax_fuel_avail_dgross_wt_initial = 1.0 / 2.0 + dmax_fuel_avail_dOEW = -1.0 / 2.0 + + J['extra_fuel_volume', Aircraft.Fuel.WING_VOLUME_DESIGN] = ( + dextra_fuel_volume_ddesign_fuel_vol ) - dMEFWt_dGeomFuelVol = ( - -sigX(design_fuel_vol - max_wingfuel_vol) * rho_fuel - ) - - J["max_extra_fuel_mass", Aircraft.Fuel.WING_VOLUME_DESIGN] = \ - dMEFWt_dDesFuelVol / GRAV_ENGLISH_LBM - J["max_extra_fuel_mass", Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] = \ - dMEFWt_dMaxWingfuelVol / GRAV_ENGLISH_LBM - J["max_extra_fuel_mass", Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = \ - dMEFWt_dGeomFuelVol / GRAV_ENGLISH_LBM - J["max_extra_fuel_mass", Aircraft.Fuel.DENSITY] = dMEFWt_dRhoFuel = extra_fuel_volume - - J["wingfuel_mass_min", "fuel_mass_min"] = sigX(fuel_wt_min - max_extra_fuel_wt) + ( - fuel_wt_min - max_extra_fuel_wt - ) * dSigXdX(fuel_wt_min - max_extra_fuel_wt) - J["wingfuel_mass_min", Aircraft.Fuel.WING_VOLUME_DESIGN] = (( - fuel_wt_min - max_extra_fuel_wt - ) * dSigXdX(fuel_wt_min - max_extra_fuel_wt) * ( - -dMEFWt_dDesFuelVol - ) - dMEFWt_dDesFuelVol * sigX( - fuel_wt_min - max_extra_fuel_wt - )) / GRAV_ENGLISH_LBM - J["wingfuel_mass_min", Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] = (fuel_wt_min * dSigXdX( - fuel_wt_min - max_extra_fuel_wt - ) * (-dMEFWt_dMaxWingfuelVol) - ( - dMEFWt_dMaxWingfuelVol * sigX(fuel_wt_min - max_extra_fuel_wt) - + max_extra_fuel_wt - * dSigXdX(fuel_wt_min - max_extra_fuel_wt) - * (-dMEFWt_dMaxWingfuelVol) - )) / GRAV_ENGLISH_LBM - J["wingfuel_mass_min", Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = (fuel_wt_min * dSigXdX( - fuel_wt_min - max_extra_fuel_wt - ) * (-dMEFWt_dGeomFuelVol) - ( - dMEFWt_dGeomFuelVol * sigX(fuel_wt_min - max_extra_fuel_wt) - + max_extra_fuel_wt - * dSigXdX(fuel_wt_min - max_extra_fuel_wt) - * (-dMEFWt_dGeomFuelVol) - )) / GRAV_ENGLISH_LBM - J["wingfuel_mass_min", Aircraft.Fuel.DENSITY] = fuel_wt_min * dSigXdX( - fuel_wt_min - max_extra_fuel_wt - ) * (-dMEFWt_dRhoFuel) - ( - dMEFWt_dRhoFuel * sigX(fuel_wt_min - max_extra_fuel_wt) - + max_extra_fuel_wt - * dSigXdX(fuel_wt_min - max_extra_fuel_wt) - * (-dMEFWt_dRhoFuel) - ) - - int1 = sigX((gross_wt_initial - est_GTOW) / 110) - int2 = sigX((est_GTOW - gross_wt_initial) / 110) - max_fuel_avail = max_fuel_avail_est * int1 + max_fuel_avail_new * int2 - - dInt1_dFuelWtDes = dSigXdX((gross_wt_initial - est_GTOW) / 110) * (-1 / 110) - dInt1_dReqFuelWt = dSigXdX((gross_wt_initial - est_GTOW) / 110) * ( - -dExtraFuelWt_dReqFuelWt - ) - dInt1_dMaxWingfuelWt = dSigXdX((gross_wt_initial - est_GTOW) / 110) * ( - -dExtraFuelWt_dMaxWingfuelWt - ) - - dInt2_dOEM = dSigXdX((est_GTOW - gross_wt_initial) / 110) / 110 - dInt2_dFuelWtDes = dSigXdX((est_GTOW - gross_wt_initial) / 110) / 110 - dInt2_dReqFuelWt = ( - dSigXdX((est_GTOW - gross_wt_initial) / 110) * dExtraFuelWt_dReqFuelWt - ) - dInt2_dMaxWingfuelWt = ( - dSigXdX((est_GTOW - gross_wt_initial) / 110) * dExtraFuelWt_dMaxWingfuelWt - ) - dInt2_dGTOW = dSigXdX((est_GTOW - gross_wt_initial) / 110) * (-1 / 110) - - dMFAest_dFuelWtDes = 1 - dMFAest_dReqFuelWt = dExtraFuelWt_dReqFuelWt - dMFAest_dMaxWingfuelWt = dExtraFuelWt_dMaxWingfuelWt - - J[Aircraft.Fuel.TOTAL_CAPACITY, Mission.Design.FUEL_MASS] = ( - int1 - + max_fuel_avail_est * dInt1_dFuelWtDes - + max_fuel_avail_new * dInt2_dFuelWtDes - ) - J[Aircraft.Fuel.TOTAL_CAPACITY, Mission.Design.FUEL_MASS_REQUIRED] = ( - dMFAest_dReqFuelWt * int1 - + max_fuel_avail_est * dInt1_dReqFuelWt - + max_fuel_avail_new * dInt2_dReqFuelWt - ) - J[Aircraft.Fuel.TOTAL_CAPACITY, "max_wingfuel_mass"] = ( - dMFAest_dMaxWingfuelWt * int1 - + max_fuel_avail_est * dInt1_dMaxWingfuelWt - + max_fuel_avail_new * dInt2_dMaxWingfuelWt + J['extra_fuel_volume', Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] = ( + dextra_fuel_volume_dmax_wingfuel_vol ) - J[Aircraft.Fuel.TOTAL_CAPACITY, Mission.Design.GROSS_MASS] = ( - max_fuel_avail_est * dInt2_dGTOW - + 1 * int2 - + max_fuel_avail_new * dInt2_dGTOW + J['extra_fuel_volume', Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = ( + dextra_fuel_volume_dgeom_fuel_vol + ) + + J['max_extra_fuel_mass', Aircraft.Fuel.WING_VOLUME_DESIGN] = ( + dmax_extra_fuel_wt_ddesign_fuel_vol / GRAV_ENGLISH_LBM + ) + J['max_extra_fuel_mass', Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] = ( + dmax_extra_fuel_wt_dmax_wingfuel_vol / GRAV_ENGLISH_LBM + ) + J['max_extra_fuel_mass', Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = ( + dmax_extra_fuel_wt_dgeom_fuel_vol / GRAV_ENGLISH_LBM, + ) + conversion_factor = convert_units(1.0, 'lbm/galUS', 'lbm/ft**3') + J['max_extra_fuel_mass', Aircraft.Fuel.DENSITY] = ( + dmax_extra_fuel_wt_drho_fuel * conversion_factor + ) + + J[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, Mission.Summary.FUEL_MASS_REQUIRED] = ( + dextra_fuel_wt_dreq_fuel_wt ) - J[Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Design.OPERATING_MASS] = ( - max_fuel_avail_est * dInt2_dOEM - 1 * int2 + max_fuel_avail_new * dInt2_dOEM + J[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 'max_wingfuel_mass'] = ( + dextra_fuel_wt_dmax_wingfuel_wt ) + J['wingfuel_mass_min', 'fuel_mass_min'] = dwingfuel_wt_min_dfuel_wt_min + J['wingfuel_mass_min', Aircraft.Fuel.WING_VOLUME_DESIGN] = ( + dwingfuel_wt_min_ddesign_fuel_vol / GRAV_ENGLISH_LBM + ) + J['wingfuel_mass_min', Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] = ( + dwingfuel_wt_min_dmax_wingfuel_vol / GRAV_ENGLISH_LBM + ) + J['wingfuel_mass_min', Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = ( + dwingfuel_wt_min_dgeom_fuel_vol / GRAV_ENGLISH_LBM + ) + J['wingfuel_mass_min', Aircraft.Fuel.DENSITY] = ( + dwingfuel_wt_min_drho_fuel * conversion_factor + ) + + J[Aircraft.Fuel.TOTAL_CAPACITY, Mission.Summary.FUEL_MASS] = dmax_fuel_avail_dfuel_wt_des + J[Aircraft.Fuel.TOTAL_CAPACITY, Mission.Summary.FUEL_MASS_REQUIRED] = ( + dmax_fuel_avail_dreq_fuel_wt + ) + J[Aircraft.Fuel.TOTAL_CAPACITY, 'max_wingfuel_mass'] = dmax_fuel_avail_dmax_wingfuel_wt + J[Aircraft.Fuel.TOTAL_CAPACITY, Mission.Design.GROSS_MASS] = ( + dmax_fuel_avail_dgross_wt_initial + ) + J[Aircraft.Fuel.TOTAL_CAPACITY, Mission.Summary.OPERATING_MASS] = dmax_fuel_avail_dOEW + class FuelAndOEMOutputs(om.ExplicitComponent): """ @@ -361,60 +500,54 @@ class FuelAndOEMOutputs(om.ExplicitComponent): wing fuel weight). """ - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - def setup(self): - - add_aviary_input(self, Aircraft.Fuel.DENSITY, val=6.687, units="lbm/ft**3") - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400) - add_aviary_input(self, Aircraft.Propulsion.MASS, val=16129) - add_aviary_input(self, Aircraft.Controls.TOTAL_MASS, val=3895.0) - add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, val=50461.0) - add_aviary_input(self, Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0) - add_aviary_input(self, Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0) - add_aviary_input(self, Mission.Design.FUEL_MASS_REQUIRED, val=42892.0) - add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=5000) - add_aviary_input(self, Aircraft.Fuel.FUEL_MARGIN, val=10) - add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, val=46000) + add_aviary_input(self, Aircraft.Fuel.DENSITY, units='lbm/galUS') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Propulsion.MASS, units='lbm') + add_aviary_input(self, Aircraft.Controls.TOTAL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.FIXED_EQUIPMENT_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.FIXED_USEFUL_LOAD, units='lbm') + add_aviary_input(self, Mission.Summary.FUEL_MASS_REQUIRED, units='lbm') + add_aviary_input(self, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, units='ft**3') + add_aviary_input(self, Aircraft.Fuel.FUEL_MARGIN, units='unitless') + add_aviary_input(self, Aircraft.Fuel.TOTAL_CAPACITY, units='lbm') self.add_output( - "OEM_wingfuel_mass", + 'OEM_wingfuel_mass', val=0, - units="lbm", - desc="WFWOWE: wing fuel mass when operating empty", + units='lbm', + desc='WFWOWE: wing fuel mass when operating empty', ) self.add_output( - "OEM_fuel_vol", + 'OEM_fuel_vol', val=0, - units="ft**3", - desc="FVOLW: wing tank fuel volume when carrying maximum fuel", + units='ft**3', + desc='FVOLW: wing tank fuel volume when carrying maximum fuel', ) - add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_DESIGN, val=0) - add_aviary_output(self, Aircraft.Design.OPERATING_MASS, val=0) + add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_DESIGN, units='ft**3') + add_aviary_output(self, Mission.Summary.OPERATING_MASS, units='lbm') self.add_output( - "payload_mass_max_fuel", + 'payload_mass_max_fuel', val=0, - units="lbm", - desc="WPLMXF: allowable payload mass with maximum fuel", + units='lbm', + desc='WPLMXF: allowable payload mass with maximum fuel', ) self.add_output( - "volume_wingfuel_mass", + 'volume_wingfuel_mass', val=0, - units="lbm", - desc=" mass of wing fuel based on volume, sometimes set as WFWMX in GASP, depending on if it exceeds the OEM fuel mass", + units='lbm', + desc=' mass of wing fuel based on volume, sometimes set as WFWMX in GASP, depending on if it exceeds the OEM fuel mass', ) self.add_output( - "max_wingfuel_mass", val=0, units="lbm", desc="WFWMX: maximum wingfuel mass" + 'max_wingfuel_mass', val=0, units='lbm', desc='WFWMX: maximum wingfuel mass' ) - add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=0) + add_aviary_output(self, Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, units='ft**3') + def setup_partials(self): self.declare_partials( - "OEM_wingfuel_mass", + 'OEM_wingfuel_mass', [ Mission.Design.GROSS_MASS, Aircraft.Propulsion.MASS, @@ -425,7 +558,7 @@ def setup(self): ], ) self.declare_partials( - "OEM_fuel_vol", + 'OEM_fuel_vol', [ Mission.Design.GROSS_MASS, Aircraft.Propulsion.MASS, @@ -437,20 +570,23 @@ def setup(self): ], ) self.declare_partials( - Aircraft.Fuel.WING_VOLUME_DESIGN, [Mission.Design.FUEL_MASS_REQUIRED, - Aircraft.Fuel.DENSITY, Aircraft.Fuel.FUEL_MARGIN] + Aircraft.Fuel.WING_VOLUME_DESIGN, + [Mission.Summary.FUEL_MASS_REQUIRED, Aircraft.Fuel.DENSITY, Aircraft.Fuel.FUEL_MARGIN], ) self.declare_partials( - Aircraft.Design.OPERATING_MASS, - [Aircraft.Propulsion.MASS, Aircraft.Controls.TOTAL_MASS, Aircraft.Design.STRUCTURE_MASS, - Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.Design.FIXED_USEFUL_LOAD], + Mission.Summary.OPERATING_MASS, + [ + Aircraft.Propulsion.MASS, + Aircraft.Controls.TOTAL_MASS, + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Design.FIXED_EQUIPMENT_MASS, + Aircraft.Design.FIXED_USEFUL_LOAD, + ], val=1, ) + self.declare_partials('payload_mass_max_fuel', [Mission.Design.GROSS_MASS], val=1) self.declare_partials( - "payload_mass_max_fuel", [Mission.Design.GROSS_MASS], val=1 - ) - self.declare_partials( - "payload_mass_max_fuel", + 'payload_mass_max_fuel', [ Aircraft.Fuel.TOTAL_CAPACITY, Aircraft.Propulsion.MASS, @@ -462,11 +598,10 @@ def setup(self): val=-1, ) self.declare_partials( - "volume_wingfuel_mass", [ - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuel.DENSITY] + 'volume_wingfuel_mass', [Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, Aircraft.Fuel.DENSITY] ) self.declare_partials( - "max_wingfuel_mass", + 'max_wingfuel_mass', [ Mission.Design.GROSS_MASS, Aircraft.Propulsion.MASS, @@ -493,30 +628,23 @@ def setup(self): ) def compute(self, inputs, outputs): - - rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM + rho_fuel = ( + convert_units(inputs[Aircraft.Fuel.DENSITY], 'lbm/galUS', 'lbm/ft**3') + * GRAV_ENGLISH_LBM + ) gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM propulsion_wt = inputs[Aircraft.Propulsion.MASS] * GRAV_ENGLISH_LBM control_wt = inputs[Aircraft.Controls.TOTAL_MASS] * GRAV_ENGLISH_LBM struct_wt = inputs[Aircraft.Design.STRUCTURE_MASS] * GRAV_ENGLISH_LBM - fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * \ - GRAV_ENGLISH_LBM - useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * \ - GRAV_ENGLISH_LBM - req_fuel_wt = inputs[Mission.Design.FUEL_MASS_REQUIRED] * \ - GRAV_ENGLISH_LBM + fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * GRAV_ENGLISH_LBM + useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * GRAV_ENGLISH_LBM + req_fuel_wt = inputs[Mission.Summary.FUEL_MASS_REQUIRED] * GRAV_ENGLISH_LBM geometric_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] fuel_margin = inputs[Aircraft.Fuel.FUEL_MARGIN] - max_fuel_avail = inputs[Aircraft.Fuel.TOTAL_CAPACITY] * \ - GRAV_ENGLISH_LBM + max_fuel_avail = inputs[Aircraft.Fuel.TOTAL_CAPACITY] * GRAV_ENGLISH_LBM OEM_wingfuel_wt = ( - gross_wt_initial - - propulsion_wt - - control_wt - - struct_wt - - fixed_equip_wt - - useful_wt + gross_wt_initial - propulsion_wt - control_wt - struct_wt - fixed_equip_wt - useful_wt ) OEM_fuel_vol = OEM_wingfuel_wt / rho_fuel @@ -525,281 +653,264 @@ def compute(self, inputs, outputs): OEW = propulsion_wt + control_wt + struct_wt + fixed_equip_wt + useful_wt volume_wingfuel_wt = geometric_fuel_vol * rho_fuel - max_wingfuel_wt = OEM_wingfuel_wt * sigX( - (volume_wingfuel_wt - OEM_wingfuel_wt) / 95 - ) + volume_wingfuel_wt * sigX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + # always smoothing + max_wingfuel_wt = OEM_wingfuel_wt * sigmoidX( + volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0 + ) + volume_wingfuel_wt * sigmoidX(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) payload_wt_max_fuel = gross_wt_initial - OEW - max_fuel_avail - max_wingfuel_vol = max_wingfuel_wt / (rho_fuel) + max_wingfuel_vol = max_wingfuel_wt / rho_fuel - outputs["OEM_wingfuel_mass"] = OEM_wingfuel_wt / GRAV_ENGLISH_LBM - outputs["OEM_fuel_vol"] = OEM_fuel_vol + outputs['OEM_wingfuel_mass'] = OEM_wingfuel_wt / GRAV_ENGLISH_LBM + outputs['OEM_fuel_vol'] = OEM_fuel_vol outputs[Aircraft.Fuel.WING_VOLUME_DESIGN] = design_fuel_vol - outputs[Aircraft.Design.OPERATING_MASS] = OEW / GRAV_ENGLISH_LBM - outputs["payload_mass_max_fuel"] = \ - payload_wt_max_fuel / GRAV_ENGLISH_LBM - outputs["volume_wingfuel_mass"] = volume_wingfuel_wt / GRAV_ENGLISH_LBM - outputs["max_wingfuel_mass"] = max_wingfuel_wt / GRAV_ENGLISH_LBM + outputs[Mission.Summary.OPERATING_MASS] = OEW / GRAV_ENGLISH_LBM + outputs['payload_mass_max_fuel'] = payload_wt_max_fuel / GRAV_ENGLISH_LBM + outputs['volume_wingfuel_mass'] = volume_wingfuel_wt / GRAV_ENGLISH_LBM + outputs['max_wingfuel_mass'] = max_wingfuel_wt / GRAV_ENGLISH_LBM outputs[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX] = max_wingfuel_vol def compute_partials(self, inputs, J): - - rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM + rho_fuel = ( + convert_units(inputs[Aircraft.Fuel.DENSITY], 'lbm/galUS', 'lbm/ft**3') + * GRAV_ENGLISH_LBM + ) gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM propulsion_wt = inputs[Aircraft.Propulsion.MASS] * GRAV_ENGLISH_LBM control_wt = inputs[Aircraft.Controls.TOTAL_MASS] * GRAV_ENGLISH_LBM struct_wt = inputs[Aircraft.Design.STRUCTURE_MASS] * GRAV_ENGLISH_LBM - fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * \ - GRAV_ENGLISH_LBM - useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * \ - GRAV_ENGLISH_LBM - req_fuel_wt = inputs[Mission.Design.FUEL_MASS_REQUIRED] * \ - GRAV_ENGLISH_LBM + fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * GRAV_ENGLISH_LBM + useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * GRAV_ENGLISH_LBM + req_fuel_wt = inputs[Mission.Summary.FUEL_MASS_REQUIRED] * GRAV_ENGLISH_LBM geometric_fuel_vol = inputs[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] fuel_margin = inputs[Aircraft.Fuel.FUEL_MARGIN] - max_fuel_avail = inputs[Aircraft.Fuel.TOTAL_CAPACITY] * \ - GRAV_ENGLISH_LBM OEM_wingfuel_wt = ( - gross_wt_initial - - propulsion_wt - - control_wt - - struct_wt - - fixed_equip_wt - - useful_wt + gross_wt_initial - propulsion_wt - control_wt - struct_wt - fixed_equip_wt - useful_wt ) volume_wingfuel_wt = geometric_fuel_vol * rho_fuel - max_wingfuel_wt = OEM_wingfuel_wt * sigX( - (volume_wingfuel_wt - OEM_wingfuel_wt) / 95 - ) + volume_wingfuel_wt * sigX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) - - J["OEM_wingfuel_mass", Mission.Design.GROSS_MASS] = dOEMwingfuelWt_dGTOW = 1 - J["OEM_wingfuel_mass", Aircraft.Propulsion.MASS] = dOEMwingfuelWt_dPropWt = -1 - J["OEM_wingfuel_mass", Aircraft.Controls.TOTAL_MASS] = dOEMwingfuelWt_dControlWt = -1 - J["OEM_wingfuel_mass", Aircraft.Design.STRUCTURE_MASS] = dOEMwingfuelWt_dStructWt = -1 - J["OEM_wingfuel_mass", Aircraft.Design.FIXED_EQUIPMENT_MASS] = dOEMwingfuelWt_dFEqWt = -1 - J["OEM_wingfuel_mass", Aircraft.Design.FIXED_USEFUL_LOAD] = dOEMwingfuelWt_dUsefulWt = -1 - - J["OEM_fuel_vol", Mission.Design.GROSS_MASS] = \ - 1 / rho_fuel * GRAV_ENGLISH_LBM - J["OEM_fuel_vol", Aircraft.Propulsion.MASS] = \ - -1 / rho_fuel * GRAV_ENGLISH_LBM - J["OEM_fuel_vol", Aircraft.Controls.TOTAL_MASS] = \ - -1 / rho_fuel * GRAV_ENGLISH_LBM - J["OEM_fuel_vol", Aircraft.Design.STRUCTURE_MASS] = \ - -1 / rho_fuel * GRAV_ENGLISH_LBM - J["OEM_fuel_vol", Aircraft.Design.FIXED_EQUIPMENT_MASS] = \ - -1 / rho_fuel * GRAV_ENGLISH_LBM - J["OEM_fuel_vol", Aircraft.Design.FIXED_USEFUL_LOAD] = \ - -1 / rho_fuel * GRAV_ENGLISH_LBM - J["OEM_fuel_vol", Aircraft.Fuel.DENSITY] = \ - -OEM_wingfuel_wt / rho_fuel**2 * GRAV_ENGLISH_LBM - - J[Aircraft.Fuel.WING_VOLUME_DESIGN, Mission.Design.FUEL_MASS_REQUIRED] = ( - 1.0 + fuel_margin / 100.0) / rho_fuel * GRAV_ENGLISH_LBM + max_wingfuel_wt = OEM_wingfuel_wt * sigmoidX( + volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0 + ) + volume_wingfuel_wt * sigmoidX(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) + + J['OEM_wingfuel_mass', Mission.Design.GROSS_MASS] = dOEMwingfuelWt_dGTOW = 1 + J['OEM_wingfuel_mass', Aircraft.Propulsion.MASS] = dOEMwingfuelWt_dPropWt = -1 + J['OEM_wingfuel_mass', Aircraft.Controls.TOTAL_MASS] = dOEMwingfuelWt_dControlWt = -1 + J['OEM_wingfuel_mass', Aircraft.Design.STRUCTURE_MASS] = dOEMwingfuelWt_dStructWt = -1 + J['OEM_wingfuel_mass', Aircraft.Design.FIXED_EQUIPMENT_MASS] = dOEMwingfuelWt_dFEqWt = -1 + J['OEM_wingfuel_mass', Aircraft.Design.FIXED_USEFUL_LOAD] = dOEMwingfuelWt_dUsefulWt = -1 + + J['OEM_fuel_vol', Mission.Design.GROSS_MASS] = 1 / rho_fuel * GRAV_ENGLISH_LBM + J['OEM_fuel_vol', Aircraft.Propulsion.MASS] = -1 / rho_fuel * GRAV_ENGLISH_LBM + J['OEM_fuel_vol', Aircraft.Controls.TOTAL_MASS] = -1 / rho_fuel * GRAV_ENGLISH_LBM + J['OEM_fuel_vol', Aircraft.Design.STRUCTURE_MASS] = -1 / rho_fuel * GRAV_ENGLISH_LBM + J['OEM_fuel_vol', Aircraft.Design.FIXED_EQUIPMENT_MASS] = -1 / rho_fuel * GRAV_ENGLISH_LBM + J['OEM_fuel_vol', Aircraft.Design.FIXED_USEFUL_LOAD] = -1 / rho_fuel * GRAV_ENGLISH_LBM + conversion_factor = convert_units(1.0, 'lbm/galUS', 'lbm/ft**3') + J['OEM_fuel_vol', Aircraft.Fuel.DENSITY] = ( + -OEM_wingfuel_wt / rho_fuel**2 * conversion_factor * GRAV_ENGLISH_LBM + ) + + J[Aircraft.Fuel.WING_VOLUME_DESIGN, Mission.Summary.FUEL_MASS_REQUIRED] = ( + (1.0 + fuel_margin / 100.0) / rho_fuel * GRAV_ENGLISH_LBM + ) J[Aircraft.Fuel.WING_VOLUME_DESIGN, Aircraft.Fuel.DENSITY] = ( - -(1.0 + fuel_margin / 100.0) * req_fuel_wt / - rho_fuel**2 * GRAV_ENGLISH_LBM + -(1.0 + fuel_margin / 100.0) + * req_fuel_wt + / rho_fuel**2 + * conversion_factor + * GRAV_ENGLISH_LBM ) J[Aircraft.Fuel.WING_VOLUME_DESIGN, Aircraft.Fuel.FUEL_MARGIN] = ( 1 / 100.0 * req_fuel_wt / rho_fuel ) - J["volume_wingfuel_mass", Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = rho_fuel / \ - GRAV_ENGLISH_LBM - J["volume_wingfuel_mass", Aircraft.Fuel.DENSITY] = geometric_fuel_vol + J['volume_wingfuel_mass', Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = ( + rho_fuel / GRAV_ENGLISH_LBM + ) + J['volume_wingfuel_mass', Aircraft.Fuel.DENSITY] = geometric_fuel_vol * conversion_factor dMaxWFWt_dGTOW = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dGTOW - + dOEMwingfuelWt_dGTOW * - sigX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + + dOEMwingfuelWt_dGTOW * sigmoidX(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dGTOW ) dMaxWFWt_dPropWt = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dPropWt - + dOEMwingfuelWt_dPropWt * - sigX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + + dOEMwingfuelWt_dPropWt * sigmoidX(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dPropWt ) dMaxWFWt_dControlWt = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dControlWt + dOEMwingfuelWt_dControlWt - * sigX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * sigmoidX(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dControlWt ) dMaxWFWt_dControlWt = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dControlWt + dOEMwingfuelWt_dControlWt - * sigX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * sigmoidX(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dControlWt ) dMaxWFWt_dStructWt = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dStructWt - + dOEMwingfuelWt_dStructWt - * sigX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + + dOEMwingfuelWt_dStructWt * sigmoidX(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dStructWt ) dMaxWFWt_dFEqWt = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dFEqWt - + dOEMwingfuelWt_dFEqWt * - sigX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + + dOEMwingfuelWt_dFEqWt * sigmoidX(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dFEqWt ) dMaxWFWt_dUsefulWt = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dUsefulWt - + dOEMwingfuelWt_dUsefulWt - * sigX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + + dOEMwingfuelWt_dUsefulWt * sigmoidX(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * dOEMwingfuelWt_dUsefulWt ) dMaxWFWt_dGeomFuelVol = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * rho_fuel + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * rho_fuel - + rho_fuel * sigX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + + rho_fuel * sigmoidX(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) ) dMaxWFWt_dRhoFuel = ( OEM_wingfuel_wt - * dSigXdX((volume_wingfuel_wt - OEM_wingfuel_wt) / 95) + * dSigmoidXdx(volume_wingfuel_wt - OEM_wingfuel_wt, 0, 1 / 95.0) * geometric_fuel_vol + volume_wingfuel_wt - * dSigXdX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) + * dSigmoidXdx(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) * geometric_fuel_vol - + geometric_fuel_vol * sigX((OEM_wingfuel_wt - volume_wingfuel_wt) / 95) - ) - - J["max_wingfuel_mass", Mission.Design.GROSS_MASS] = dMaxWFWt_dGTOW - J["max_wingfuel_mass", Aircraft.Propulsion.MASS] = dMaxWFWt_dPropWt - J["max_wingfuel_mass", Aircraft.Controls.TOTAL_MASS] = dMaxWFWt_dControlWt - J["max_wingfuel_mass", Aircraft.Design.STRUCTURE_MASS] = dMaxWFWt_dStructWt - J["max_wingfuel_mass", Aircraft.Design.FIXED_EQUIPMENT_MASS] = dMaxWFWt_dFEqWt - J["max_wingfuel_mass", Aircraft.Design.FIXED_USEFUL_LOAD] = dMaxWFWt_dUsefulWt - J["max_wingfuel_mass", Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = dMaxWFWt_dGeomFuelVol / \ - GRAV_ENGLISH_LBM - J["max_wingfuel_mass", Aircraft.Fuel.DENSITY] = dMaxWFWt_dRhoFuel - - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, - Mission.Design.GROSS_MASS] = dMaxWFWt_dGTOW / (rho_fuel) - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, - Aircraft.Propulsion.MASS] = dMaxWFWt_dPropWt / (rho_fuel) - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, - Aircraft.Controls.TOTAL_MASS] = dMaxWFWt_dControlWt / (rho_fuel) - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, - Aircraft.Design.STRUCTURE_MASS] = dMaxWFWt_dStructWt / (rho_fuel) - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, - Aircraft.Design.FIXED_EQUIPMENT_MASS] = dMaxWFWt_dFEqWt / (rho_fuel) - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, - Aircraft.Design.FIXED_USEFUL_LOAD] = dMaxWFWt_dUsefulWt / (rho_fuel) - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = dMaxWFWt_dGeomFuelVol / ( + + geometric_fuel_vol * sigmoidX(OEM_wingfuel_wt - volume_wingfuel_wt, 0, 1 / 95.0) + ) + + J['max_wingfuel_mass', Mission.Design.GROSS_MASS] = dMaxWFWt_dGTOW + J['max_wingfuel_mass', Aircraft.Propulsion.MASS] = dMaxWFWt_dPropWt + J['max_wingfuel_mass', Aircraft.Controls.TOTAL_MASS] = dMaxWFWt_dControlWt + J['max_wingfuel_mass', Aircraft.Design.STRUCTURE_MASS] = dMaxWFWt_dStructWt + J['max_wingfuel_mass', Aircraft.Design.FIXED_EQUIPMENT_MASS] = dMaxWFWt_dFEqWt + J['max_wingfuel_mass', Aircraft.Design.FIXED_USEFUL_LOAD] = dMaxWFWt_dUsefulWt + J['max_wingfuel_mass', Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = ( + dMaxWFWt_dGeomFuelVol / GRAV_ENGLISH_LBM + ) + J['max_wingfuel_mass', Aircraft.Fuel.DENSITY] = dMaxWFWt_dRhoFuel * conversion_factor + + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Mission.Design.GROSS_MASS] = dMaxWFWt_dGTOW / ( rho_fuel ) - J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Fuel.DENSITY] = dMaxWFWt_dRhoFuel / ( + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Propulsion.MASS] = dMaxWFWt_dPropWt / ( rho_fuel - ) - max_wingfuel_wt / (rho_fuel**2) + ) + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Controls.TOTAL_MASS] = ( + dMaxWFWt_dControlWt / (rho_fuel) + ) + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Design.STRUCTURE_MASS] = ( + dMaxWFWt_dStructWt / (rho_fuel) + ) + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Design.FIXED_EQUIPMENT_MASS] = ( + dMaxWFWt_dFEqWt / (rho_fuel) + ) + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Design.FIXED_USEFUL_LOAD] = ( + dMaxWFWt_dUsefulWt / (rho_fuel) + ) + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX] = ( + dMaxWFWt_dGeomFuelVol / (rho_fuel) + ) + J[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, Aircraft.Fuel.DENSITY] = ( + dMaxWFWt_dRhoFuel / (rho_fuel) - max_wingfuel_wt / (rho_fuel**2) + ) * conversion_factor class FuelSysAndFullFuselageMass(om.ExplicitComponent): - """ - Computation of fuselage mass and fuel system mass - """ - - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + """Computation of fuselage mass and fuel system mass.""" def setup(self): + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400) - - add_aviary_input(self, Aircraft.Wing.MASS, val=15830.0) + add_aviary_input(self, Aircraft.Wing.MASS, units='lbm') self.add_input( - "wing_mounted_mass", + 'wing_mounted_mass', val=24446.343040697346, - units="lbm", - desc="WM: mass of gear and engine (everything on wing that isn`t wing itself or fuel", - ) - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041) - add_aviary_input(self, Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - add_aviary_input(self, Mission.Design.FUEL_MASS, val=3000) - add_aviary_input(self, Aircraft.Fuel.FUEL_MARGIN, val=10) + units='lbm', + desc='WM: mass of gear and engine (everything on wing that isn`t wing itself or fuel', + ) + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Fuel.DENSITY, units='lbm/galUS') + add_aviary_input(self, Mission.Summary.FUEL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuel.FUEL_MARGIN, units='unitless') self.add_input( - "wingfuel_mass_min", - val=32850, - units="lbm", - desc="WFWMIN: minimum wing fuel mass", + 'wingfuel_mass_min', val=32850, units='lbm', desc='WFWMIN: minimum wing fuel mass' ) self.add_output( - "fus_mass_full", + 'fus_mass_full', val=0, - units="lbm", - desc="WX: mass of fuselage and contents, including empennage", + units='lbm', + desc='WX: mass of fuselage and contents, including empennage', ) - add_aviary_output(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, val=0) + add_aviary_output(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, units='lbm', desc='WFSS?') + def setup_partials(self): self.declare_partials( Aircraft.Fuel.FUEL_SYSTEM_MASS, [ Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, Aircraft.Fuel.DENSITY, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, - Mission.Design.FUEL_MASS, + Mission.Summary.FUEL_MASS, Aircraft.Fuel.FUEL_MARGIN, ], ) self.declare_partials( - "fus_mass_full", + 'fus_mass_full', [ Mission.Design.GROSS_MASS, Aircraft.Wing.MASS, - "wingfuel_mass_min", - "wing_mounted_mass", + 'wingfuel_mass_min', + 'wing_mounted_mass', ], ) def compute(self, inputs, outputs): - gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM total_wing_wt = inputs[Aircraft.Wing.MASS] * GRAV_ENGLISH_LBM - wing_mounted_wt = inputs["wing_mounted_mass"] * GRAV_ENGLISH_LBM + wing_mounted_wt = inputs['wing_mounted_mass'] * GRAV_ENGLISH_LBM CK21 = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] c_mass_trend_fuel_sys = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT] rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM - fuel_wt_des = inputs[Mission.Design.FUEL_MASS] * GRAV_ENGLISH_LBM + fuel_wt_des = inputs[Mission.Summary.FUEL_MASS] * GRAV_ENGLISH_LBM fuel_margin = inputs[Aircraft.Fuel.FUEL_MARGIN] - wingfuel_wt_min = inputs["wingfuel_mass_min"] * GRAV_ENGLISH_LBM + wingfuel_wt_min = inputs['wingfuel_mass_min'] * GRAV_ENGLISH_LBM outputs[Aircraft.Fuel.FUEL_SYSTEM_MASS] = ( CK21 @@ -809,21 +920,16 @@ def compute(self, inputs, outputs): * (1.0 + fuel_margin / 100.0) / GRAV_ENGLISH_LBM ) - outputs["fus_mass_full"] = ( + outputs['fus_mass_full'] = ( gross_wt_initial - total_wing_wt - wingfuel_wt_min - wing_mounted_wt ) / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - - gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - total_wing_wt = inputs[Aircraft.Wing.MASS] * GRAV_ENGLISH_LBM - wing_mounted_wt = inputs["wing_mounted_mass"] * GRAV_ENGLISH_LBM CK21 = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] c_mass_trend_fuel_sys = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT] rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM - fuel_wt_des = inputs[Mission.Design.FUEL_MASS] * GRAV_ENGLISH_LBM + fuel_wt_des = inputs[Mission.Summary.FUEL_MASS] * GRAV_ENGLISH_LBM fuel_margin = inputs[Aircraft.Fuel.FUEL_MARGIN] - wingfuel_wt_min = inputs["wingfuel_mass_min"] * GRAV_ENGLISH_LBM J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] = ( (6.687 / rho_fuel) @@ -840,129 +946,87 @@ def compute_partials(self, inputs, J): * (1.0 + fuel_margin / 100.0) ) J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT] = ( - CK21 * (6.687 / rho_fuel) * fuel_wt_des * - (1.0 + fuel_margin / 100.0) / GRAV_ENGLISH_LBM + CK21 * (6.687 / rho_fuel) * fuel_wt_des * (1.0 + fuel_margin / 100.0) / GRAV_ENGLISH_LBM + ) + J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Mission.Summary.FUEL_MASS] = ( + CK21 * (6.687 / rho_fuel) * c_mass_trend_fuel_sys * (1.0 + fuel_margin / 100.0) ) - J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Mission.Design.FUEL_MASS] = ( + J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.FUEL_MARGIN] = ( CK21 * (6.687 / rho_fuel) * c_mass_trend_fuel_sys - * (1.0 + fuel_margin / 100.0) - ) - J[Aircraft.Fuel.FUEL_SYSTEM_MASS, Aircraft.Fuel.FUEL_MARGIN] = ( - CK21 * (6.687 / rho_fuel) * c_mass_trend_fuel_sys * - fuel_wt_des * (1 / 100.0) / GRAV_ENGLISH_LBM + * fuel_wt_des + * (1 / 100.0) + / GRAV_ENGLISH_LBM ) - J["fus_mass_full", Mission.Design.GROSS_MASS] = 1 - J["fus_mass_full", Aircraft.Wing.MASS] = -1 - J["fus_mass_full", "wingfuel_mass_min"] = -1 - J["fus_mass_full", "wing_mounted_mass"] = -1 + J['fus_mass_full', Mission.Design.GROSS_MASS] = 1 + J['fus_mass_full', Aircraft.Wing.MASS] = -1 + J['fus_mass_full', 'wingfuel_mass_min'] = -1 + J['fus_mass_full', 'wing_mounted_mass'] = -1 -class FuselageAndStructMass(om.ExplicitComponent): +class FuselageMass(om.ExplicitComponent): """ - Computation of total structural group mass and mass of the fuselage structure. + Computation of the fuselage structure mass. """ - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) - self.add_input( - "fus_mass_full", + 'fus_mass_full', val=4000, - units="lbm", - desc="WX: mass of fuselage and contents, including empennage", - ) - add_aviary_input(self, Aircraft.Fuselage.MASS_COEFFICIENT, val=128) - add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, val=4000) - add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, val=13.1) - add_aviary_input(self, Aircraft.TailBoom.LENGTH, val=129.4) + units='lbm', + desc='WX: mass of fuselage and contents, including empennage', + ) + add_aviary_input(self, Aircraft.Fuselage.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.TailBoom.LENGTH, units='ft') + # pylon_len is not computed in Aviary self.add_input( - "pylon_len", + 'pylon_len', val=0, - units="ft", - desc="ELRW: length of pylon for fuselage mounted engines", + units='ft', + desc='ELRW: length of pylon for fuselage mounted engines', ) + self.add_input('min_dive_vel', val=419.75918333, units='kn', desc='VDMIN: dive velocity') + add_aviary_input(self, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, units='psi') + add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, units='unitless') + # MAT is not computed in Aviary self.add_input( - "min_dive_vel", val=419.75918333, units="kn", desc="VDMIN: dive velocity" + 'MAT', val=0, units='lbm', desc='WAT: Weight of the Fuselage Acoustic Treatment' ) - add_aviary_input(self, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5) - add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893) - self.add_input( - "MAT", - val=0, - units="lbm", - desc="WAT: Weight of the Fuselage Acoustic Treatment", - ) - add_aviary_input(self, Aircraft.Wing.MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.Wing.MASS, val=5000) - add_aviary_input(self, Aircraft.HorizontalTail.MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.HorizontalTail.MASS, val=2275) - add_aviary_input(self, Aircraft.VerticalTail.MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.VerticalTail.MASS, val=2297) - add_aviary_input(self, Aircraft.Fuselage.MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.LandingGear.TOTAL_MASS, val=7511) - add_aviary_input(self, Aircraft.Engine.POD_MASS_SCALER, - val=np.ones(num_engine_type)) - add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785) - add_aviary_input(self, Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0) - - add_aviary_output(self, Aircraft.Design.STRUCTURE_MASS, val=0) - add_aviary_output(self, Aircraft.Fuselage.MASS, val=0) + add_aviary_output(self, Aircraft.Fuselage.MASS, units='lbm') + + def setup_partials(self): self.declare_partials( Aircraft.Fuselage.MASS, [ Aircraft.Fuselage.MASS_COEFFICIENT, - "fus_mass_full", + 'fus_mass_full', Aircraft.Fuselage.WETTED_AREA, Aircraft.Fuselage.AVG_DIAMETER, Aircraft.TailBoom.LENGTH, - "pylon_len", - "min_dive_vel", + 'pylon_len', + 'min_dive_vel', Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, - "MAT", + 'MAT', ], ) - self.declare_partials(Aircraft.Design.STRUCTURE_MASS, "*") def compute(self, inputs, outputs): - - fus_wt_full = inputs["fus_mass_full"] * GRAV_ENGLISH_LBM + fus_wt_full = inputs['fus_mass_full'] * GRAV_ENGLISH_LBM c_fuselage = inputs[Aircraft.Fuselage.MASS_COEFFICIENT] fus_SA = inputs[Aircraft.Fuselage.WETTED_AREA] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] cabin_len_tailboom = inputs[Aircraft.TailBoom.LENGTH] - pylon_len = inputs["pylon_len"] - min_dive_vel = inputs["min_dive_vel"] + pylon_len = inputs['pylon_len'] + min_dive_vel = inputs['min_dive_vel'] p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] - WAT = inputs["MAT"] * GRAV_ENGLISH_LBM - CK8 = inputs[Aircraft.Wing.MASS_SCALER] - total_wing_wt = inputs[Aircraft.Wing.MASS] * GRAV_ENGLISH_LBM - CK9 = inputs[Aircraft.HorizontalTail.MASS_SCALER] - htail_wt = inputs[Aircraft.HorizontalTail.MASS] * GRAV_ENGLISH_LBM - CK10 = inputs[Aircraft.VerticalTail.MASS_SCALER] - vtail_wt = inputs[Aircraft.VerticalTail.MASS] * GRAV_ENGLISH_LBM - CK11 = inputs[Aircraft.Fuselage.MASS_SCALER] - CK12 = inputs[Aircraft.LandingGear.TOTAL_MASS_SCALER] - landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * \ - GRAV_ENGLISH_LBM - CK14 = inputs[Aircraft.Engine.POD_MASS_SCALER] - sec_wt = inputs[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS] * \ - GRAV_ENGLISH_LBM - delta_struct_wt = inputs[Aircraft.Design.STRUCTURAL_MASS_INCREMENT] * \ - GRAV_ENGLISH_LBM + WAT = inputs['MAT'] * GRAV_ENGLISH_LBM fus_wt = ( c_fuselage @@ -980,43 +1044,17 @@ def compute(self, inputs, outputs): ) outputs[Aircraft.Fuselage.MASS] = fus_wt / GRAV_ENGLISH_LBM - outputs[Aircraft.Design.STRUCTURE_MASS] = ( - CK8 * total_wing_wt - + CK9 * htail_wt - + CK10 * vtail_wt - + CK11 * fus_wt - + CK12 * landing_gear_wt - + CK14 * sec_wt - + delta_struct_wt - ) / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - - fus_wt_full = inputs["fus_mass_full"] * GRAV_ENGLISH_LBM + fus_wt_full = inputs['fus_mass_full'] * GRAV_ENGLISH_LBM c_fuselage = inputs[Aircraft.Fuselage.MASS_COEFFICIENT] fus_SA = inputs[Aircraft.Fuselage.WETTED_AREA] cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] cabin_len_tailboom = inputs[Aircraft.TailBoom.LENGTH] - pylon_len = inputs["pylon_len"] - min_dive_vel = inputs["min_dive_vel"] + pylon_len = inputs['pylon_len'] + min_dive_vel = inputs['min_dive_vel'] p_diff_fus = inputs[Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] - WAT = inputs["MAT"] * GRAV_ENGLISH_LBM - CK8 = inputs[Aircraft.Wing.MASS_SCALER] - total_wing_wt = inputs[Aircraft.Wing.MASS] * GRAV_ENGLISH_LBM - CK9 = inputs[Aircraft.HorizontalTail.MASS_SCALER] - htail_wt = inputs[Aircraft.HorizontalTail.MASS] * GRAV_ENGLISH_LBM - CK10 = inputs[Aircraft.VerticalTail.MASS_SCALER] - vtail_wt = inputs[Aircraft.VerticalTail.MASS] * GRAV_ENGLISH_LBM - CK11 = inputs[Aircraft.Fuselage.MASS_SCALER] - CK12 = inputs[Aircraft.LandingGear.TOTAL_MASS_SCALER] - landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * \ - GRAV_ENGLISH_LBM - CK14 = inputs[Aircraft.Engine.POD_MASS_SCALER] - sec_wt = inputs[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS] * \ - GRAV_ENGLISH_LBM - delta_struct_wt = inputs[Aircraft.Design.STRUCTURAL_MASS_INCREMENT] * \ - GRAV_ENGLISH_LBM x = 0.508 * ( (fus_wt_full / 10000.0) ** 0.7 @@ -1027,20 +1065,6 @@ def compute_partials(self, inputs, J): * (p_diff_fus + 1.0) ** 0.2 * ULF**0.3 ) ** (0.508 - 1) - fus_wt = ( - c_fuselage - * ( - (fus_wt_full / 10000.0) ** 0.7 - * (fus_SA / 1000.0) - * cabin_width - * (cabin_len_tailboom + pylon_len) ** 0.5 - * np.log10(min_dive_vel) - * (p_diff_fus + 1.0) ** 0.2 - * ULF**0.3 - ) - ** 0.508 - + WAT - ) dFusWt_dCFus = ( (fus_wt_full / 10000.0) ** 0.7 * (fus_SA / 1000.0) @@ -1145,59 +1169,195 @@ def compute_partials(self, inputs, J): * ULF ** (0.3 - 1) ) - J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MASS_COEFFICIENT] = \ + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MASS_COEFFICIENT] = ( dFusWt_dCFus / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, "fus_mass_full"] = dFusWt_dFusWtFull - J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.WETTED_AREA] = \ - dFusWt_dFusSA / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.AVG_DIAMETER] = \ + ) + J[Aircraft.Fuselage.MASS, 'fus_mass_full'] = dFusWt_dFusWtFull + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.WETTED_AREA] = dFusWt_dFusSA / GRAV_ENGLISH_LBM + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.AVG_DIAMETER] = ( dFusWt_dCabWidth / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, Aircraft.TailBoom.LENGTH] = \ - dFusWt_dCabLenBoom / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, "pylon_len"] = \ - dFusWt_dPylonLen / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, "min_dive_vel"] = \ - dFusWt_dMinDiveVel / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] = \ + ) + J[Aircraft.Fuselage.MASS, Aircraft.TailBoom.LENGTH] = dFusWt_dCabLenBoom / GRAV_ENGLISH_LBM + J[Aircraft.Fuselage.MASS, 'pylon_len'] = dFusWt_dPylonLen / GRAV_ENGLISH_LBM + J[Aircraft.Fuselage.MASS, 'min_dive_vel'] = dFusWt_dMinDiveVel / GRAV_ENGLISH_LBM + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] = ( dFusWt_dPdiffFus / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = \ + ) + J[Aircraft.Fuselage.MASS, Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ( dFusWt_dULF / GRAV_ENGLISH_LBM - J[Aircraft.Fuselage.MASS, "MAT"] = dFusWt_dWAT = 1 - - J[Aircraft.Design.STRUCTURE_MASS, - Aircraft.Fuselage.MASS_COEFFICIENT] = dFusWt_dCFus * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, "fus_mass_full"] = dFusWt_dFusWtFull * CK11 - J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Fuselage.WETTED_AREA] = \ - dFusWt_dFusSA * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, - Aircraft.Fuselage.AVG_DIAMETER] = dFusWt_dCabWidth * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, Aircraft.TailBoom.LENGTH] = \ - dFusWt_dCabLenBoom * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, "pylon_len"] = \ - dFusWt_dPylonLen * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, "min_dive_vel"] = \ - dFusWt_dMinDiveVel * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL] = dFusWt_dPdiffFus * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, - Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = dFusWt_dULF * CK11 / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, "MAT"] = dFusWt_dWAT * CK11 - J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Wing.MASS_SCALER] = \ + ) + J[Aircraft.Fuselage.MASS, 'MAT'] = 1 + + +class BWBFuselageMass(om.ExplicitComponent): + """ + Computation of the fuselage structure mass of BWB type aircraft. The empirical + equation is completely different from tube and wing type aircraft. + """ + + def setup(self): + add_aviary_input(self, Aircraft.Fuselage.CABIN_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Fuselage.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input( + self, Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL, units='unitless' + ) + add_aviary_input(self, Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA, units='lbm/ft**2') + add_aviary_input(self, Aircraft.Fuselage.WETTED_AREA, units='ft**2') + + add_aviary_output(self, Aircraft.Fuselage.MASS, units='lbm') + + def setup_partials(self): + self.declare_partials( + Aircraft.Fuselage.MASS, + [ + Aircraft.Fuselage.CABIN_AREA, + Aircraft.Fuselage.WETTED_AREA, + Aircraft.Fuselage.MASS_COEFFICIENT, + Mission.Design.GROSS_MASS, + Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL, + Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA, + ], + ) + + def compute(self, inputs, outputs): + c_fuselage = inputs[Aircraft.Fuselage.MASS_COEFFICIENT] + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + area_cabin = inputs[Aircraft.Fuselage.CABIN_AREA] + area_aft_to_total = inputs[Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL] + uwt_aft = inputs[Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA] * GRAV_ENGLISH_LBM + fus_SA = inputs[Aircraft.Fuselage.WETTED_AREA] + + fus_wt_fb = c_fuselage * 1.8 * (gross_wt_initial**0.167) * (area_cabin**1.06) + fus_wt_ab = c_fuselage * fus_SA * area_aft_to_total * uwt_aft + fus_mass = (fus_wt_fb + fus_wt_ab) / GRAV_ENGLISH_LBM + + outputs[Aircraft.Fuselage.MASS] = fus_mass + + def compute_partials(self, inputs, J): + c_fuselage = inputs[Aircraft.Fuselage.MASS_COEFFICIENT] + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + area_cabin = inputs[Aircraft.Fuselage.CABIN_AREA] + area_aft_to_total = inputs[Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL] + uwt_aft = inputs[Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA] * GRAV_ENGLISH_LBM + fus_SA = inputs[Aircraft.Fuselage.WETTED_AREA] + + dFusWt_dc_fuselage = ( + 1.8 * (gross_wt_initial**0.167) * (area_cabin**1.06) + + fus_SA * area_aft_to_total * uwt_aft + ) / GRAV_ENGLISH_LBM + dFusWt_dgross_wt_initial = ( + 0.167 * c_fuselage * 1.8 * (gross_wt_initial**-0.833) * (area_cabin**1.06) + ) / GRAV_ENGLISH_LBM + dFusWt_darea_cabin = ( + 1.06 * c_fuselage * 1.8 * (gross_wt_initial**0.167) * (area_cabin**0.06) + ) + dFusWt_darea_aft_to_total = c_fuselage * fus_SA * uwt_aft + dFusWt_duwt_aft = c_fuselage * fus_SA * area_aft_to_total + dFusWt_dfus_SA = c_fuselage * area_aft_to_total * uwt_aft + + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.MASS_COEFFICIENT] = dFusWt_dc_fuselage + J[Aircraft.Fuselage.MASS, Mission.Design.GROSS_MASS] = dFusWt_dgross_wt_initial + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.CABIN_AREA] = dFusWt_darea_cabin + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL] = ( + dFusWt_darea_aft_to_total + ) + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA] = dFusWt_duwt_aft + J[Aircraft.Fuselage.MASS, Aircraft.Fuselage.WETTED_AREA] = dFusWt_dfus_SA + + +class StructMass(om.ExplicitComponent): + """ + Computation of total structural group mass. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + + def setup(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input(self, Aircraft.Fuselage.MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Wing.MASS, units='lbm') + add_aviary_input(self, Aircraft.HorizontalTail.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.HorizontalTail.MASS, units='lbm') + add_aviary_input(self, Aircraft.VerticalTail.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.VerticalTail.MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuselage.MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.LandingGear.TOTAL_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.LandingGear.TOTAL_MASS, units='lbm') + add_aviary_input( + self, Aircraft.Engine.POD_MASS_SCALER, shape=num_engine_type, units='unitless' + ) + add_aviary_input(self, Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.STRUCTURAL_MASS_INCREMENT, units='lbm') + + add_aviary_output(self, Aircraft.Design.STRUCTURE_MASS, units='lbm', desc='WST') + + self.declare_partials(Aircraft.Design.STRUCTURE_MASS, '*') + + def compute(self, inputs, outputs): + fus_wt = inputs[Aircraft.Fuselage.MASS] * GRAV_ENGLISH_LBM + CK8 = inputs[Aircraft.Wing.MASS_SCALER] + total_wing_wt = inputs[Aircraft.Wing.MASS] * GRAV_ENGLISH_LBM + CK9 = inputs[Aircraft.HorizontalTail.MASS_SCALER] + htail_wt = inputs[Aircraft.HorizontalTail.MASS] * GRAV_ENGLISH_LBM + CK10 = inputs[Aircraft.VerticalTail.MASS_SCALER] + vtail_wt = inputs[Aircraft.VerticalTail.MASS] * GRAV_ENGLISH_LBM + CK11 = inputs[Aircraft.Fuselage.MASS_SCALER] + CK12 = inputs[Aircraft.LandingGear.TOTAL_MASS_SCALER] + landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * GRAV_ENGLISH_LBM + CK14 = inputs[Aircraft.Engine.POD_MASS_SCALER] + sec_wt = inputs[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS] * GRAV_ENGLISH_LBM + delta_struct_wt = inputs[Aircraft.Design.STRUCTURAL_MASS_INCREMENT] * GRAV_ENGLISH_LBM + + outputs[Aircraft.Design.STRUCTURE_MASS] = ( + CK8 * total_wing_wt + + CK9 * htail_wt + + CK10 * vtail_wt + + CK11 * fus_wt + + CK12 * landing_gear_wt + + CK14 * sec_wt + + delta_struct_wt + ) / GRAV_ENGLISH_LBM + + def compute_partials(self, inputs, J): + fus_wt = inputs[Aircraft.Fuselage.MASS] * GRAV_ENGLISH_LBM + CK8 = inputs[Aircraft.Wing.MASS_SCALER] + total_wing_wt = inputs[Aircraft.Wing.MASS] * GRAV_ENGLISH_LBM + CK9 = inputs[Aircraft.HorizontalTail.MASS_SCALER] + htail_wt = inputs[Aircraft.HorizontalTail.MASS] * GRAV_ENGLISH_LBM + CK10 = inputs[Aircraft.VerticalTail.MASS_SCALER] + vtail_wt = inputs[Aircraft.VerticalTail.MASS] * GRAV_ENGLISH_LBM + CK11 = inputs[Aircraft.Fuselage.MASS_SCALER] + CK12 = inputs[Aircraft.LandingGear.TOTAL_MASS_SCALER] + landing_gear_wt = inputs[Aircraft.LandingGear.TOTAL_MASS] * GRAV_ENGLISH_LBM + CK14 = inputs[Aircraft.Engine.POD_MASS_SCALER] + sec_wt = inputs[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS] * GRAV_ENGLISH_LBM + delta_struct_wt = inputs[Aircraft.Design.STRUCTURAL_MASS_INCREMENT] * GRAV_ENGLISH_LBM + + J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Wing.MASS_SCALER] = ( total_wing_wt / GRAV_ENGLISH_LBM + ) J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Wing.MASS] = CK8 - J[Aircraft.Design.STRUCTURE_MASS, - Aircraft.HorizontalTail.MASS_SCALER] = htail_wt / GRAV_ENGLISH_LBM + J[Aircraft.Design.STRUCTURE_MASS, Aircraft.HorizontalTail.MASS_SCALER] = ( + htail_wt / GRAV_ENGLISH_LBM + ) J[Aircraft.Design.STRUCTURE_MASS, Aircraft.HorizontalTail.MASS] = CK9 - J[Aircraft.Design.STRUCTURE_MASS, - Aircraft.VerticalTail.MASS_SCALER] = vtail_wt / GRAV_ENGLISH_LBM + J[Aircraft.Design.STRUCTURE_MASS, Aircraft.VerticalTail.MASS_SCALER] = ( + vtail_wt / GRAV_ENGLISH_LBM + ) J[Aircraft.Design.STRUCTURE_MASS, Aircraft.VerticalTail.MASS] = CK10 - J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Fuselage.MASS_SCALER] = \ - fus_wt / GRAV_ENGLISH_LBM - J[Aircraft.Design.STRUCTURE_MASS, - Aircraft.LandingGear.TOTAL_MASS_SCALER] = landing_gear_wt / GRAV_ENGLISH_LBM + J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Fuselage.MASS_SCALER] = fus_wt / GRAV_ENGLISH_LBM + J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Fuselage.MASS] = CK11 + J[Aircraft.Design.STRUCTURE_MASS, Aircraft.LandingGear.TOTAL_MASS_SCALER] = ( + landing_gear_wt / GRAV_ENGLISH_LBM + ) J[Aircraft.Design.STRUCTURE_MASS, Aircraft.LandingGear.TOTAL_MASS] = CK12 - J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Engine.POD_MASS_SCALER] = \ + J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Engine.POD_MASS_SCALER] = ( sec_wt / GRAV_ENGLISH_LBM + ) J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS] = CK14 J[Aircraft.Design.STRUCTURE_MASS, Aircraft.Design.STRUCTURAL_MASS_INCREMENT] = 1 @@ -1208,122 +1368,125 @@ class FuelMass(om.ExplicitComponent): and minimum value of fuel mass. """ - def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - def setup(self): - - add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, val=50461.0) - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, val=1759,) - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400) + add_aviary_input(self, Aircraft.Design.STRUCTURE_MASS, units='lbm') + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS, units='lbm') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') self.add_input( - "eng_comb_mass", + 'eng_comb_mass', val=14371.0, - units="lbm", - desc="WPSTAR: mass of dry engine and engine installation. Includes mass of electrical augmentation system.", - ) - add_aviary_input(self, Aircraft.Controls.TOTAL_MASS, val=3895.0) - add_aviary_input(self, Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0) - add_aviary_input(self, Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0) - self.add_input( - "payload_mass_des", val=36000, units="lbm", desc="WPLDES: design payload" + units='lbm', + desc='WPSTAR: mass of dry engine and engine installation. Includes mass of electrical augmentation system.', ) - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1) - add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041) - add_aviary_input(self, Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - add_aviary_input(self, Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=36000) + add_aviary_input(self, Aircraft.Controls.TOTAL_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.FIXED_EQUIPMENT_MASS, units='lbm') + add_aviary_input(self, Aircraft.Design.FIXED_USEFUL_LOAD, units='lbm') + self.add_input('payload_mass_des', val=36000, units='lbm', desc='WPLDES: design payload') + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, units='unitless') + add_aviary_input(self, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Fuel.DENSITY, units='lbm/galUS') self.add_input( - "payload_mass_max", + 'payload_mass_max', val=46040, - units="lbm", - desc="WPLMAX: maximum payload that the aircraft is being asked to carry (design payload + cargo)", + units='lbm', + desc='WPLMAX: maximum payload that the aircraft is being asked to carry (design payload + cargo)', ) - add_aviary_input(self, Aircraft.Fuel.FUEL_MARGIN, val=10) + add_aviary_input(self, Aircraft.Fuel.FUEL_MARGIN, units='unitless') - add_aviary_output(self, Mission.Design.FUEL_MASS, val=0) - add_aviary_output(self, Aircraft.Propulsion.MASS, val=0) - add_aviary_output(self, Mission.Design.FUEL_MASS_REQUIRED, val=0) + add_aviary_output(self, Mission.Summary.FUEL_MASS, units='lbm', desc='WFADES') + add_aviary_output(self, Aircraft.Propulsion.MASS, units='lbm', desc='WP') + add_aviary_output(self, Mission.Summary.FUEL_MASS_REQUIRED, units='lbm', desc='WFAREQ') self.add_output( - "fuel_mass_min", + 'fuel_mass_min', val=0, - units="lbm", - desc="WFAMIN: minimum value of fuel mass (set when max payload is carried)", + units='lbm', + desc='WFAMIN: minimum value of fuel mass (set when max payload is carried)', ) + def setup_partials(self): self.declare_partials( - Mission.Design.FUEL_MASS, + Mission.Summary.FUEL_MASS, [ Mission.Design.GROSS_MASS, - "eng_comb_mass", + 'eng_comb_mass', Aircraft.Design.STRUCTURE_MASS, Aircraft.Controls.TOTAL_MASS, Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.Design.FIXED_USEFUL_LOAD, - "payload_mass_des", + 'payload_mass_des', Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, Aircraft.Fuel.DENSITY, Aircraft.Fuel.FUEL_MARGIN, ], ) - self.declare_partials(Aircraft.Propulsion.MASS, [ - "eng_comb_mass", Aircraft.Fuel.FUEL_SYSTEM_MASS], val=1) - self.declare_partials(Mission.Design.FUEL_MASS_REQUIRED, [ - Mission.Design.GROSS_MASS], val=1) self.declare_partials( - Mission.Design.FUEL_MASS_REQUIRED, + Aircraft.Propulsion.MASS, ['eng_comb_mass', Aircraft.Fuel.FUEL_SYSTEM_MASS], val=1 + ) + self.declare_partials( + Mission.Summary.FUEL_MASS_REQUIRED, [Mission.Design.GROSS_MASS], val=1 + ) + self.declare_partials( + Mission.Summary.FUEL_MASS_REQUIRED, [ - "eng_comb_mass", + 'eng_comb_mass', Aircraft.Design.STRUCTURE_MASS, Aircraft.Controls.TOTAL_MASS, Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.Design.FIXED_USEFUL_LOAD, - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS, + 'payload_mass_des', ], val=-1, ) - self.declare_partials("fuel_mass_min", [Mission.Design.GROSS_MASS], val=1) + self.declare_partials('fuel_mass_min', [Mission.Design.GROSS_MASS], val=1) self.declare_partials( - "fuel_mass_min", + 'fuel_mass_min', [ - "eng_comb_mass", + 'eng_comb_mass', Aircraft.Design.STRUCTURE_MASS, Aircraft.Controls.TOTAL_MASS, Aircraft.Design.FIXED_EQUIPMENT_MASS, Aircraft.Design.FIXED_USEFUL_LOAD, - "payload_mass_max", + 'payload_mass_max', Aircraft.Fuel.FUEL_SYSTEM_MASS, ], val=-1, ) def compute(self, inputs, outputs): - struct_wt = inputs[Aircraft.Design.STRUCTURE_MASS] * GRAV_ENGLISH_LBM fuel_sys_wt = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS] * GRAV_ENGLISH_LBM gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - eng_comb_wt = inputs["eng_comb_mass"] * GRAV_ENGLISH_LBM + eng_comb_wt = inputs['eng_comb_mass'] * GRAV_ENGLISH_LBM control_wt = inputs[Aircraft.Controls.TOTAL_MASS] * GRAV_ENGLISH_LBM - fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * \ - GRAV_ENGLISH_LBM - useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * \ - GRAV_ENGLISH_LBM - payload_wt_des = inputs["payload_mass_des"] * GRAV_ENGLISH_LBM + fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * GRAV_ENGLISH_LBM + useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * GRAV_ENGLISH_LBM + payload_wt_des = inputs['payload_mass_des'] * GRAV_ENGLISH_LBM CK21 = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] c_mass_trend_fuel_sys = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT] rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM - payload_wt = inputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] * \ - GRAV_ENGLISH_LBM - payload_wt_max = inputs["payload_mass_max"] * GRAV_ENGLISH_LBM + payload_wt_max = inputs['payload_mass_max'] * GRAV_ENGLISH_LBM fuel_margin = inputs[Aircraft.Fuel.FUEL_MARGIN] - outputs[Mission.Design.FUEL_MASS] = ( + # GASP code is updated later than the following formula. + outputs[Mission.Summary.FUEL_MASS] = ( + ( + gross_wt_initial + - eng_comb_wt + - struct_wt + - control_wt + - fixed_equip_wt + - useful_wt + - payload_wt_des + ) + / (1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel) + / GRAV_ENGLISH_LBM + ) + outputs[Aircraft.Propulsion.MASS] = (eng_comb_wt + fuel_sys_wt) / GRAV_ENGLISH_LBM + outputs[Mission.Summary.FUEL_MASS_REQUIRED] = ( gross_wt_initial - eng_comb_wt - struct_wt @@ -1331,23 +1494,9 @@ def compute(self, inputs, outputs): - fixed_equip_wt - useful_wt - payload_wt_des - ) / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel - ) / GRAV_ENGLISH_LBM - outputs[Aircraft.Propulsion.MASS] = ( - eng_comb_wt + fuel_sys_wt) / GRAV_ENGLISH_LBM - outputs[Mission.Design.FUEL_MASS_REQUIRED] = ( - gross_wt_initial - - eng_comb_wt - - struct_wt - - control_wt - - fixed_equip_wt - - useful_wt - - payload_wt - fuel_sys_wt ) / GRAV_ENGLISH_LBM - outputs["fuel_mass_min"] = ( + outputs['fuel_mass_min'] = ( gross_wt_initial - eng_comb_wt - struct_wt @@ -1359,54 +1508,40 @@ def compute(self, inputs, outputs): ) / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): - struct_wt = inputs[Aircraft.Design.STRUCTURE_MASS] * GRAV_ENGLISH_LBM - fuel_sys_wt = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS] * GRAV_ENGLISH_LBM gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - eng_comb_wt = inputs["eng_comb_mass"] * GRAV_ENGLISH_LBM + eng_comb_wt = inputs['eng_comb_mass'] * GRAV_ENGLISH_LBM control_wt = inputs[Aircraft.Controls.TOTAL_MASS] * GRAV_ENGLISH_LBM - fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * \ - GRAV_ENGLISH_LBM - useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * \ - GRAV_ENGLISH_LBM - payload_wt_des = inputs["payload_mass_des"] * GRAV_ENGLISH_LBM + fixed_equip_wt = inputs[Aircraft.Design.FIXED_EQUIPMENT_MASS] * GRAV_ENGLISH_LBM + useful_wt = inputs[Aircraft.Design.FIXED_USEFUL_LOAD] * GRAV_ENGLISH_LBM + payload_wt_des = inputs['payload_mass_des'] * GRAV_ENGLISH_LBM CK21 = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] c_mass_trend_fuel_sys = inputs[Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT] rho_fuel = inputs[Aircraft.Fuel.DENSITY] * GRAV_ENGLISH_LBM - payload_wt = inputs[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS] * \ - GRAV_ENGLISH_LBM - payload_wt_max = inputs["payload_mass_max"] * GRAV_ENGLISH_LBM fuel_margin = inputs[Aircraft.Fuel.FUEL_MARGIN] - J[Mission.Design.FUEL_MASS, Mission.Design.GROSS_MASS] = 1 / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel + J[Mission.Summary.FUEL_MASS, Mission.Design.GROSS_MASS] = 1 / ( + 1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel ) - J[Mission.Design.FUEL_MASS, "eng_comb_mass"] = -1 / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel + J[Mission.Summary.FUEL_MASS, 'eng_comb_mass'] = -1 / ( + 1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel ) - J[Mission.Design.FUEL_MASS, Aircraft.Design.STRUCTURE_MASS] = -1 / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel + J[Mission.Summary.FUEL_MASS, Aircraft.Design.STRUCTURE_MASS] = -1 / ( + 1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel ) - J[Mission.Design.FUEL_MASS, Aircraft.Controls.TOTAL_MASS] = -1 / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel + J[Mission.Summary.FUEL_MASS, Aircraft.Controls.TOTAL_MASS] = -1 / ( + 1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel ) - J[Mission.Design.FUEL_MASS, Aircraft.Design.FIXED_EQUIPMENT_MASS] = -1 / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel + J[Mission.Summary.FUEL_MASS, Aircraft.Design.FIXED_EQUIPMENT_MASS] = -1 / ( + 1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel ) - J[Mission.Design.FUEL_MASS, Aircraft.Design.FIXED_USEFUL_LOAD] = -1 / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel + J[Mission.Summary.FUEL_MASS, Aircraft.Design.FIXED_USEFUL_LOAD] = -1 / ( + 1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel ) - J[Mission.Design.FUEL_MASS, "payload_mass_des"] = -1 / ( - 1.0 - + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel + J[Mission.Summary.FUEL_MASS, 'payload_mass_des'] = -1 / ( + 1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel ) - J[Mission.Design.FUEL_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] = ( + J[Mission.Summary.FUEL_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER] = ( -( gross_wt_initial - eng_comb_wt @@ -1416,21 +1551,14 @@ def compute_partials(self, inputs, J): - useful_wt - payload_wt_des ) - / ( - 1.0 - + CK21 - * c_mass_trend_fuel_sys - * (1 + fuel_margin / 100) - * 6.687 - / rho_fuel - ) - ** 2 + / (1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel) ** 2 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 - / rho_fuel / GRAV_ENGLISH_LBM + / rho_fuel + / GRAV_ENGLISH_LBM ) - J[Mission.Design.FUEL_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT] = ( + J[Mission.Summary.FUEL_MASS, Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT] = ( -( gross_wt_initial - eng_comb_wt @@ -1440,21 +1568,14 @@ def compute_partials(self, inputs, J): - useful_wt - payload_wt_des ) - / ( - 1.0 - + CK21 - * c_mass_trend_fuel_sys - * (1 + fuel_margin / 100) - * 6.687 - / rho_fuel - ) - ** 2 + / (1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel) ** 2 * CK21 * (1 + fuel_margin / 100) * 6.687 - / rho_fuel / GRAV_ENGLISH_LBM + / rho_fuel + / GRAV_ENGLISH_LBM ) - J[Mission.Design.FUEL_MASS, Aircraft.Fuel.DENSITY] = ( + J[Mission.Summary.FUEL_MASS, Aircraft.Fuel.DENSITY] = ( -( gross_wt_initial - eng_comb_wt @@ -1464,24 +1585,10 @@ def compute_partials(self, inputs, J): - useful_wt - payload_wt_des ) - / ( - 1.0 - + CK21 - * c_mass_trend_fuel_sys - * (1 + fuel_margin / 100) - * 6.687 - / rho_fuel - ) - ** 2 - * ( - -CK21 - * c_mass_trend_fuel_sys - * (1 + fuel_margin / 100) - * 6.687 - / rho_fuel**2 - ) + / (1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel) ** 2 + * (-CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel**2) ) - J[Mission.Design.FUEL_MASS, Aircraft.Fuel.FUEL_MARGIN] = ( + J[Mission.Summary.FUEL_MASS, Aircraft.Fuel.FUEL_MARGIN] = ( -( gross_wt_initial - eng_comb_wt @@ -1491,132 +1598,91 @@ def compute_partials(self, inputs, J): - useful_wt - payload_wt_des ) - / ( - 1.0 - + CK21 - * c_mass_trend_fuel_sys - * (1 + fuel_margin / 100) - * 6.687 - / rho_fuel - ) - ** 2 + / (1.0 + CK21 * c_mass_trend_fuel_sys * (1 + fuel_margin / 100) * 6.687 / rho_fuel) ** 2 * CK21 * c_mass_trend_fuel_sys * (1 / 100) * 6.687 - / rho_fuel / GRAV_ENGLISH_LBM + / rho_fuel + / GRAV_ENGLISH_LBM ) class FuelMassGroup(om.Group): """ Group of fuel related components including FuelSysAndFullFuselageMass, - FuselageAndStructMass, FuelMass, FuelAndOEMOutputs, and BodyTankCalculations. + FuselageMass, StructMass, FuelMass, FuelAndOEMOutputs, and BodyTankCalculations. + In case of BWB, FuselageMass is replaced by BWBFuselageMass. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Design.TYPE) def setup(self): - - aviary_options = self.options['aviary_options'] - - # variables that are calculated at a higher level - higher_level_inputs1 = ["wing_mounted_mass"] - higher_level_inputs2 = [ - "min_dive_vel", - ] - higher_level_inputs3 = [ - "payload_mass_des", - "payload_mass_max", - "eng_comb_mass", - ] - - # variables that are passed within the group but not used at a higher level - connected_inputs1 = ["wingfuel_mass_min"] - connected_inputs2 = [ - "fus_mass_full", - ] - connected_inputs5 = [ - "fuel_mass_min", - "max_wingfuel_mass", - ] - - connected_outputs1 = ["fus_mass_full"] - connected_outputs3 = [ - "fuel_mass_min", - ] - connected_outputs4 = [ - "max_wingfuel_mass", - ] - connected_outputs5 = ["wingfuel_mass_min"] + design_type = self.options[Aircraft.Design.TYPE] self.add_subsystem( - "sys_and_full_fus", - FuelSysAndFullFuselageMass(aviary_options=aviary_options), - promotes_inputs=connected_inputs1 - + higher_level_inputs1 - + ["aircraft:*", "mission:*"], - promotes_outputs=connected_outputs1 + ["aircraft:*"], - ) + 'sys_and_full_fus', + FuelSysAndFullFuselageMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'fuselage', + BWBFuselageMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'fuselage', + FuselageMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - "fus_and_struct", - FuselageAndStructMass(aviary_options=aviary_options), - promotes_inputs=connected_inputs2 + higher_level_inputs2 + ["aircraft:*"], - promotes_outputs=["aircraft:*"], + 'struct', + StructMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "fuel", - FuelMass(aviary_options=aviary_options), - promotes_inputs=higher_level_inputs3 - + ["aircraft:*", "mission:*"], - promotes_outputs=connected_outputs3 + ["aircraft:*", "mission:*"], + 'fuel', + FuelMass(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "fuel_and_oem", - FuelAndOEMOutputs(aviary_options=aviary_options), - promotes_inputs=["aircraft:*", "mission:*"], - promotes_outputs=connected_outputs4 + ["aircraft:*"], + 'fuel_and_oem', + FuelAndOEMOutputs(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "body_tank", - BodyTankCalculations(aviary_options=aviary_options), - promotes_inputs=connected_inputs5 - + ["aircraft:*", "mission:*"], - promotes_outputs=connected_outputs5 + ["aircraft:*"], - ) - - self.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units="lbm") - self.set_input_defaults(Aircraft.Wing.MASS, val=15830, units="lbm") - self.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - self.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - self.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895, units="lbm") - self.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units="lbm") - self.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, val=4932, units="lbm") + 'body_tank', + BodyTankCalculations(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) newton = self.nonlinear_solver = om.NewtonSolver() - newton.options["atol"] = 1e-9 - newton.options["rtol"] = 1e-9 - newton.options["iprint"] = 2 - newton.options["maxiter"] = 10 - newton.options["solve_subsystems"] = True - newton.options["max_sub_solves"] = 10 - newton.options["err_on_non_converge"] = True - newton.options["reraise_child_analysiserror"] = False + newton.options['atol'] = 1e-9 + newton.options['rtol'] = 1e-9 + newton.options['iprint'] = 2 + newton.options['maxiter'] = 10 + newton.options['solve_subsystems'] = True + newton.options['max_sub_solves'] = 10 + newton.options['err_on_non_converge'] = True + newton.options['reraise_child_analysiserror'] = False newton.linesearch = om.BoundsEnforceLS() - newton.linesearch.options["bound_enforcement"] = "scalar" - newton.linesearch.options["iprint"] = -1 - newton.options["err_on_non_converge"] = False + newton.linesearch.options['bound_enforcement'] = 'scalar' + newton.linesearch.options['iprint'] = -1 + newton.options['err_on_non_converge'] = False self.linear_solver = om.DirectSolver(assemble_jac=True) diff --git a/aviary/subsystems/mass/gasp_based/mass_premission.py b/aviary/subsystems/mass/gasp_based/mass_premission.py index 187df60a2f..71b6fed561 100644 --- a/aviary/subsystems/mass/gasp_based/mass_premission.py +++ b/aviary/subsystems/mass/gasp_based/mass_premission.py @@ -1,114 +1,106 @@ import openmdao.api as om -from aviary.subsystems.mass.gasp_based.design_load import DesignLoadGroup -from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import \ - EquipAndUsefulLoadMass +from aviary.subsystems.mass.gasp_based.design_load import DesignLoadGroup, BWBDesignLoadGroup +from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import EquipAndUsefulLoadMassGroup from aviary.subsystems.mass.gasp_based.fixed import FixedMassGroup from aviary.subsystems.mass.gasp_based.fuel import FuelMassGroup -from aviary.subsystems.mass.gasp_based.wing import WingMassGroup -from aviary.utils.aviary_values import AviaryValues +from aviary.subsystems.mass.gasp_based.wing import WingMassGroup, BWBWingMassGroup +from aviary.variable_info.enums import AircraftTypes +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft class MassPremission(om.Group): - """ - Pre-mission mass group for GASP-based mass. - """ + """Pre-mission mass group for GASP-based mass.""" def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Design.TYPE) def setup(self): - - aviary_options = self.options['aviary_options'] + design_type = self.options[Aircraft.Design.TYPE] # output values from design_load that are connected to fixed_mass via promotion - fixed_mass_design_load_values = [ - "max_mach", "min_dive_vel"] + fixed_mass_design_load_values = ['max_mach', 'min_dive_vel'] # output values from fixed_mass that are connected to wing_mass via promotion wing_mass_fixed_mass_values = [ - "c_strut_braced", - "c_gear_loc", - "half_sweep", + 'c_strut_braced', + 'c_gear_loc', + 'half_sweep', ] # output values from design_load that are connected to fuel_mass via promotion - fuel_mass_design_load_values = ["min_dive_vel"] + fuel_mass_design_load_values = ['min_dive_vel'] # output values from fixed_mass that are connected to fuel_mass via promotion fuel_mass_fixed_mass_values = [ - "payload_mass_des", - "payload_mass_max", - "wing_mounted_mass", - "eng_comb_mass", + 'payload_mass_des', + 'payload_mass_max', + 'wing_mounted_mass', + 'eng_comb_mass', ] # combine all necessary inputs and outputs for each group - design_load_outputs = fixed_mass_design_load_values - - fixed_mass_inputs = fixed_mass_design_load_values + ["density"] + fixed_mass_inputs = fixed_mass_design_load_values + ['density'] fixed_mass_outputs = wing_mass_fixed_mass_values + fuel_mass_fixed_mass_values wing_mass_inputs = wing_mass_fixed_mass_values - fuel_mass_inputs = ( - fuel_mass_design_load_values - + fuel_mass_fixed_mass_values - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + fuel_mass_inputs = fuel_mass_fixed_mass_values + else: + fuel_mass_inputs = fuel_mass_design_load_values + fuel_mass_fixed_mass_values # create the instances of the groups - self.add_subsystem( - "design_load", - DesignLoadGroup( - aviary_options=aviary_options, - ), - promotes_inputs=["aircraft:*", "mission:*"], - promotes_outputs=["*"], - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'design_load', + BWBDesignLoadGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'design_load', + DesignLoadGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - "fixed_mass", - FixedMassGroup( - aviary_options=aviary_options, - ), - promotes_inputs=fixed_mass_inputs + ["aircraft:*", "mission:*"], - promotes_outputs=fixed_mass_outputs + ["aircraft:*"], + 'fixed_mass', + FixedMassGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) self.add_subsystem( - "equip_and_useful_mass", - EquipAndUsefulLoadMass( - aviary_options=aviary_options, - ), - promotes_inputs=["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], + 'equip_and_useful_mass', + EquipAndUsefulLoadMassGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - self.add_subsystem( - "wing_mass", - WingMassGroup( - aviary_options=aviary_options, - ), - promotes_inputs=wing_mass_inputs + ["aircraft:*", "mission:*"], - promotes_outputs=["aircraft:*"], - ) + if design_type is AircraftTypes.BLENDED_WING_BODY: + self.add_subsystem( + 'wing_mass', + BWBWingMassGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + else: + self.add_subsystem( + 'wing_mass', + WingMassGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) self.add_subsystem( - "fuel_mass", - FuelMassGroup(aviary_options=aviary_options), - promotes_inputs=fuel_mass_inputs + ["aircraft:*", "mission:*"], - promotes_outputs=[ - "aircraft:*", "mission:*" - ], + 'fuel_mass', + FuelMassGroup(), + promotes_inputs=['*'], + promotes_outputs=['*'], ) - - self.set_input_defaults(Aircraft.Fuselage.LENGTH, 200, 'ft') - self.set_input_defaults(Aircraft.HorizontalTail.AREA, 20, 'ft**2') - self.set_input_defaults(Aircraft.VerticalTail.AREA, 20, 'ft**2') diff --git a/aviary/subsystems/mass/gasp_based/test/test_design_load.py b/aviary/subsystems/mass/gasp_based/test/test_design_load.py index 5a9674f94e..e1f58cc988 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_design_load.py +++ b/aviary/subsystems/mass/gasp_based/test/test_design_load.py @@ -2,212 +2,195 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.subsystems.mass.gasp_based.design_load import (DesignLoadGroup, - LoadFactors, - LoadParameters, - LiftCurveSlopeAtCruise, - LoadSpeeds) +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.mass.gasp_based.design_load import ( + DesignLoadGroup, + LiftCurveSlopeAtCruise, + LoadFactors, + LoadParameters, + LoadSpeeds, +) +from aviary.subsystems.mass.gasp_based.design_load import ( + BWBDesignLoadGroup, + BWBLoadFactors, + BWBLoadSpeeds, +) +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Mission class LoadSpeedsTestCase1(unittest.TestCase): - """this is the large single aisle 1 V3 test case""" + """this is the large single aisle 1 V3 test case.""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds(aviary_options=get_option_defaults()), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_airspeed"], 350, tol) # bug fixed value - assert_near_equal(self.prob["vel_c"], 350, tol) # bug fixed value - assert_near_equal(self.prob["max_maneuver_factor"], 2.5, tol) # bug fixed value - assert_near_equal(self.prob["min_dive_vel"], 420, tol) # bug fixed value + assert_near_equal(self.prob['max_airspeed'], 350, tol) # bug fixed value + assert_near_equal(self.prob['vel_c'], 350, tol) # bug fixed value + assert_near_equal(self.prob['max_maneuver_factor'], 2.5, tol) # bug fixed value + assert_near_equal(self.prob['min_dive_vel'], 420, tol) # bug fixed value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class LoadSpeedsTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=0, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=0, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds(aviary_options=options), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal( - self.prob["max_airspeed"], 346.75, tol - ) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 306.15, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 3.8, tol - ) # not actual GASP value - assert_near_equal( - self.prob["min_dive_vel"], 407.94, tol - ) # not actual GASP value - - partial_data = self.prob.check_partials(out_stream=None, method="cs") + assert_near_equal(self.prob['max_airspeed'], 346.75, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 306.15, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 3.8, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 407.94, tol) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class LoadSpeedsTestCase3(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=1, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=1, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds(aviary_options=options), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal( - self.prob["max_airspeed"], 401.6, tol - ) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 315, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 4.4, tol - ) # not actual GASP value - assert_near_equal( - self.prob["min_dive_vel"], 472.5, tol - ) # not actual GASP value - - partial_data = self.prob.check_partials(out_stream=None, method="cs") + assert_near_equal(self.prob['max_airspeed'], 401.6, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 315, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 4.4, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 472.5, tol) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class LoadSpeedsTestCase4(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=2, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=2, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds(aviary_options=options), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal( - self.prob["max_airspeed"], 320.17, tol - ) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 294.27, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 6, tol - ) # not actual GASP value - assert_near_equal( - self.prob["min_dive_vel"], 376.67, tol - ) # not actual GASP value - - partial_data = self.prob.check_partials(out_stream=None, method="cs") + assert_near_equal(self.prob['max_airspeed'], 320.17, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 294.27, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 6, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 376.67, tol) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) class LoadSpeedsTestCase5(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=4, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=4, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds(aviary_options=options), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_airspeed"], 350, tol) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 350, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 4, tol - ) # not actual GASP value - assert_near_equal(self.prob["min_dive_vel"], 420, tol) # not actual GASP value - - partial_data = self.prob.check_partials(out_stream=None, method="cs") + assert_near_equal(self.prob['max_airspeed'], 350, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 350, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 4, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 420, tol) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) @@ -215,462 +198,374 @@ class LoadSpeedsTestCase6smooth( unittest.TestCase ): # this is the large single aisle 1 V3 test case (LoadSpeedsTestCase1) with smooth functions def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds( - aviary_options=options - ), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_airspeed"], 350, tol) # bug fixed value - assert_near_equal(self.prob["vel_c"], 350, tol) # bug fixed value - assert_near_equal(self.prob["max_maneuver_factor"], 2.5, tol) # bug fixed value - assert_near_equal(self.prob["min_dive_vel"], 420, tol) # bug fixed value + assert_near_equal(self.prob['max_airspeed'], 350, tol) # bug fixed value + assert_near_equal(self.prob['vel_c'], 350, tol) # bug fixed value + assert_near_equal(self.prob['max_maneuver_factor'], 2.5, tol) # bug fixed value + assert_near_equal(self.prob['min_dive_vel'], 420, tol) # bug fixed value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class LoadSpeedsTestCase7smooth(unittest.TestCase): # TestCase2 with smooth functions def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=0, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=0, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds( - aviary_options=options - ), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 2e-3 - assert_near_equal( - self.prob["max_airspeed"], 346.75, tol - ) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 306.15, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 3.8, tol - ) # not actual GASP value - assert_near_equal( - self.prob["min_dive_vel"], 407.94, tol - ) # not actual GASP value - - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) + assert_near_equal(self.prob['max_airspeed'], 346.75, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 306.15, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 3.8, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 407.94, tol) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-14, rtol=2e-13) class LoadSpeedsTestCase8smooth(unittest.TestCase): # TestCase3 with smooth functions def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=1, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=1, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds( - aviary_options=options, - ), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal( - self.prob["max_airspeed"], 401.6, tol - ) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 315, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 4.4, tol - ) # not actual GASP value - assert_near_equal( - self.prob["min_dive_vel"], 472.5, tol - ) # not actual GASP value - - partial_data = self.prob.check_partials(out_stream=None, method="cs") + assert_near_equal(self.prob['max_airspeed'], 401.6, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 315, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 4.4, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 472.5, tol) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=5e-7, rtol=1e-6) class LoadSpeedsTestCase9smooth(unittest.TestCase): # TestCase4 with smooth functions def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=2, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=2, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds( - aviary_options=options, - ), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal( - self.prob["max_airspeed"], 320.17, tol - ) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 294.27, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 6, tol - ) # not actual GASP value - assert_near_equal( - self.prob["min_dive_vel"], 376.67, tol - ) # not actual GASP value + assert_near_equal(self.prob['max_airspeed'], 320.17, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 294.27, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 6, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 376.67, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=1e-15, rtol=2e-14) + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-13) class LoadSpeedsTestCase10smooth(unittest.TestCase): # TestCase5 with smooth functions def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=4, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=4, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "speeds", - LoadSpeeds( - aviary_options=options, - ), - promotes=["*"], + 'speeds', + LoadSpeeds(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # not actual bug fixed value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_airspeed"], 350, tol) # not actual GASP value - assert_near_equal(self.prob["vel_c"], 350, tol) # not actual GASP value - assert_near_equal( - self.prob["max_maneuver_factor"], 4, tol - ) # not actual GASP value - assert_near_equal(self.prob["min_dive_vel"], 420, tol) # not actual GASP value - - partial_data = self.prob.check_partials(out_stream=None, method="cs") + assert_near_equal(self.prob['max_airspeed'], 350, tol) # not actual GASP value + assert_near_equal(self.prob['vel_c'], 350, tol) # not actual GASP value + assert_near_equal(self.prob['max_maneuver_factor'], 4, tol) # not actual GASP value + assert_near_equal(self.prob['min_dive_vel'], 420, tol) # not actual GASP value + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) # this is the large single aisle 1 V3 test case class LoadParametersTestCase1(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') self.prob = om.Problem() - self.prob.model.add_subsystem( - "params", LoadParameters(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('params', LoadParameters(), promotes=['*']) - self.prob.model.set_input_defaults( - "vel_c", val=350, units="kn" - ) # bug fixed value - self.prob.model.set_input_defaults( - "max_airspeed", val=350, units="kn" - ) # bug fixed value + self.prob.model.set_input_defaults('vel_c', val=350, units='kn') # bug fixed value + self.prob.model.set_input_defaults('max_airspeed', val=350, units='kn') # bug fixed value + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 4e-4 - assert_near_equal(self.prob["max_mach"], 0.9, tol) # bug fixed value - assert_near_equal(self.prob["density_ratio"], 0.533, tol) # bug fixed value - assert_near_equal(self.prob["V9"], 350, tol) # bug fixed value + assert_near_equal(self.prob['max_mach'], 0.9, tol) # bug fixed value + assert_near_equal(self.prob['density_ratio'], 0.533, tol) # bug fixed value + assert_near_equal(self.prob['V9'], 350, tol) # bug fixed value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class LoadParametersTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=2, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=2, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=30000, units='ft') self.prob = om.Problem() - self.prob.model.add_subsystem( - "params", LoadParameters(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('params', LoadParameters(), promotes=['*']) - self.prob.model.set_input_defaults( - "vel_c", val=350, units="mi/h" - ) # bug fixed value - self.prob.model.set_input_defaults( - "max_airspeed", val=350, units="kn" - ) # bug fixed value + self.prob.model.set_input_defaults('vel_c', val=350, units='mi/h') # bug fixed value + self.prob.model.set_input_defaults('max_airspeed', val=350, units='kn') # bug fixed value + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_mach"], 0.824, tol) # not actual GASP value - assert_near_equal(self.prob["density_ratio"], 0.682, - tol) # not actual GASP value - assert_near_equal(self.prob["V9"], 304.14, tol) # not actual GASP value + assert_near_equal(self.prob['max_mach'], 0.824, tol) # not actual GASP value + assert_near_equal(self.prob['density_ratio'], 0.682, tol) # not actual GASP value + assert_near_equal(self.prob['V9'], 304.14, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class LoadParametersTestCase3(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=4, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=4, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=22000, units='ft') self.prob = om.Problem() - self.prob.model.add_subsystem( - "params", LoadParameters(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('params', LoadParameters(), promotes=['*']) - self.prob.model.set_input_defaults( - "vel_c", val=350, units="mi/h" - ) # bug fixed value - self.prob.model.set_input_defaults( - "max_airspeed", val=350, units="kn" - ) # bug fixed value + self.prob.model.set_input_defaults('vel_c', val=350, units='mi/h') # bug fixed value + self.prob.model.set_input_defaults('max_airspeed', val=350, units='kn') # bug fixed value + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 2e-4 - assert_near_equal(self.prob["max_mach"], 0.7197, tol) # not actual GASP value - assert_near_equal(self.prob["density_ratio"], 0.6073, - tol) # not actual GASP value - assert_near_equal(self.prob["V9"], 304.14, tol) # not actual GASP value + assert_near_equal(self.prob['max_mach'], 0.7197, tol) # not actual GASP value + assert_near_equal(self.prob['density_ratio'], 0.6073, tol) # not actual GASP value + assert_near_equal(self.prob['V9'], 304.14, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) # this is the large single aisle 1 V3 test case class LoadParametersTestCase4smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "params", - LoadParameters(aviary_options=options,), - promotes=["*"], + 'params', + LoadParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - "vel_c", val=350, units="kn" - ) # bug fixed value - self.prob.model.set_input_defaults( - "max_airspeed", val=350, units="kn" - ) # bug fixed value + self.prob.model.set_input_defaults('vel_c', val=350, units='kn') # bug fixed value + self.prob.model.set_input_defaults('max_airspeed', val=350, units='kn') # bug fixed value + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 6e-4 - assert_near_equal(self.prob["max_mach"], 0.9, tol) # bug fixed value - assert_near_equal(self.prob["density_ratio"], 0.533, tol) # bug fixed value - assert_near_equal(self.prob["V9"], 350, tol) # bug fixed value + assert_near_equal(self.prob['max_mach'], 0.9, tol) # bug fixed value + assert_near_equal(self.prob['density_ratio'], 0.533, tol) # bug fixed value + assert_near_equal(self.prob['V9'], 350, tol) # bug fixed value - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=5e-14) class LoadParametersTestCase5smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=2, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=2, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=30000, units='ft') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "params", - LoadParameters(aviary_options=options,), - promotes=["*"], + 'params', + LoadParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - "vel_c", val=350, units="mi/h" - ) # bug fixed value - self.prob.model.set_input_defaults( - "max_airspeed", val=350, units="kn" - ) # bug fixed value + self.prob.model.set_input_defaults('vel_c', val=350, units='mi/h') # bug fixed value + self.prob.model.set_input_defaults('max_airspeed', val=350, units='kn') # bug fixed value + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_mach"], 0.824, tol) # not actual GASP value - assert_near_equal(self.prob["density_ratio"], 0.682, - tol) # not actual GASP value - assert_near_equal(self.prob["V9"], 304.14, tol) # not actual GASP value + assert_near_equal(self.prob['max_mach'], 0.824, tol) # not actual GASP value + assert_near_equal(self.prob['density_ratio'], 0.682, tol) # not actual GASP value + assert_near_equal(self.prob['V9'], 304.14, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) class LoadParametersTestCase6smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, - val=4, units='unitless') + options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=4, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=22000, units='ft') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "params", - LoadParameters(aviary_options=options,), - promotes=["*"], + 'params', + LoadParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - "vel_c", val=350, units="mi/h" - ) # bug fixed value - self.prob.model.set_input_defaults( - "max_airspeed", val=350, units="kn" - ) # bug fixed value + self.prob.model.set_input_defaults('vel_c', val=350, units='mi/h') # bug fixed value + self.prob.model.set_input_defaults('max_airspeed', val=350, units='kn') # bug fixed value + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_mach"], 0.7197, tol) # not actual GASP value - assert_near_equal(self.prob["density_ratio"], 0.6073, - tol) # not actual GASP value - assert_near_equal(self.prob["V9"], 304.14, tol) # not actual GASP value + assert_near_equal(self.prob['max_mach'], 0.7197, tol) # not actual GASP value + assert_near_equal(self.prob['density_ratio'], 0.6073, tol) # not actual GASP value + assert_near_equal(self.prob['V9'], 304.14, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-8) class LiftCurveSlopeAtCruiseTest(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "factors", LiftCurveSlopeAtCruise(), promotes=["*"]) - self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.SWEEP, val=0.436, units="rad" - ) - self.prob.model.set_input_defaults( - Mission.Design.MACH, val=0.8, units="unitless" - ) + self.prob.model.add_subsystem('factors', LiftCurveSlopeAtCruise(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=0.436, units='rad') + self.prob.model.set_input_defaults(Mission.Design.MACH, val=0.8, units='unitless') self.prob.setup(check=False, force_alloc_complex=True) @@ -679,279 +574,934 @@ def test_slope(self): tol = 1e-4 assert_near_equal(self.prob[Aircraft.Design.LIFT_CURVE_SLOPE], 6.3967, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) # this is the large single aisle 1 V3 test case class LoadFactorsTestCase1(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "factors", LoadFactors(aviary_options=get_option_defaults()), promotes=["*"] - ) + self.prob.model.add_subsystem('factors', LoadFactors(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=126, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=126, units='lbf/ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - "density_ratio", val=0.533, units="unitless" + 'density_ratio', val=0.533, units='unitless' ) # bug fixed value - self.prob.model.set_input_defaults("V9", val=350, units="kn") # bug fixed value + self.prob.model.set_input_defaults('V9', val=350, units='kn') # bug fixed value self.prob.model.set_input_defaults( - "min_dive_vel", val=420, units="kn" + 'min_dive_vel', val=420, units='kn' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "max_maneuver_factor", val=2.5, units="unitless" + 'max_maneuver_factor', val=2.5, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.AVERAGE_CHORD, val=12.71, units="ft" + Aircraft.Wing.AVERAGE_CHORD, val=12.71, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units="1/rad" + Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units='1/rad' ) # bug fixed value and original value self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 # bug fixed value assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.9502, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) class LoadFactorsTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, - val=True, units='unitless') + options.set_val(Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, val=True, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem( - "factors", LoadFactors(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('factors', LoadFactors(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value self.prob.model.set_input_defaults( - "density_ratio", val=0.5328, units="unitless" + 'density_ratio', val=0.5328, units='unitless' ) # may not be actual GASP value self.prob.model.set_input_defaults( - "V9", val=304.14, units="kn" + 'V9', val=304.14, units='kn' ) # may not be actual GASP value - self.prob.model.set_input_defaults("min_dive_vel", val=420, units="kn") - self.prob.model.set_input_defaults( - "max_maneuver_factor", val=2.5, units="unitless") + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') + self.prob.model.set_input_defaults('max_maneuver_factor', val=2.5, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=12.615, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.AVERAGE_CHORD, val=12.615, units="ft" + Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units='1/rad' ) - self.prob.model.set_input_defaults( - Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units="1/rad") + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 # not actual GASP value assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) # this is the large single aisle 1 V3 test case class LoadFactorsTestCase3smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "factors", - LoadFactors(aviary_options=options), - promotes=["*"], + 'factors', + LoadFactors(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=126, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=126, units='lbf/ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - "density_ratio", val=0.533, units="unitless" + 'density_ratio', val=0.533, units='unitless' ) # bug fixed value - self.prob.model.set_input_defaults("V9", val=350, units="kn") # bug fixed value + self.prob.model.set_input_defaults('V9', val=350, units='kn') # bug fixed value self.prob.model.set_input_defaults( - "min_dive_vel", val=420, units="kn" + 'min_dive_vel', val=420, units='kn' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "max_maneuver_factor", val=2.5, units="unitless" + 'max_maneuver_factor', val=2.5, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.AVERAGE_CHORD, val=12.71, units="ft" + Aircraft.Wing.AVERAGE_CHORD, val=12.71, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units="1/rad" + Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units='1/rad' ) # bug fixed value and original value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 4e-4 # bug fixed value assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.9502, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=5e-14, rtol=2e-13) + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-13, rtol=2e-13) class LoadFactorsTestCase4smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, - val=True, units='unitless') + options.set_val(Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "factors", - LoadFactors(aviary_options=options,), - promotes=["*"], + 'factors', + LoadFactors(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2' ) # not actual bug fixed value self.prob.model.set_input_defaults( - "density_ratio", val=0.5328, units="unitless" + 'density_ratio', val=0.5328, units='unitless' ) # may not be actual GASP value self.prob.model.set_input_defaults( - "V9", val=304.14, units="kn" + 'V9', val=304.14, units='kn' ) # may not be actual GASP value - self.prob.model.set_input_defaults("min_dive_vel", val=420, units="kn") - self.prob.model.set_input_defaults( - "max_maneuver_factor", val=2.5, units="unitless") + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') + self.prob.model.set_input_defaults('max_maneuver_factor', val=2.5, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=12.615, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.AVERAGE_CHORD, val=12.615, units="ft" + Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units='1/rad' ) - self.prob.model.set_input_defaults( - Aircraft.Design.LIFT_CURVE_SLOPE, val=7.1765, units="1/rad") + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 # not actual GASP value assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) # this is the large single aisle 1 V3 test case class DesignLoadGroupTestCase1(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') self.prob = om.Problem() self.prob.model.add_subsystem( - "Dload", - DesignLoadGroup( - aviary_options=options, - ), - promotes=["*"], + 'Dload', + DesignLoadGroup(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed and original value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=126, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=126, units='lbf/ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.AVERAGE_CHORD, val=12.71, units="ft" + Aircraft.Wing.AVERAGE_CHORD, val=12.71, units='ft' ) # bug fixed value + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob["max_mach"], 0.9, tol) # bug fixed value + assert_near_equal(self.prob['max_mach'], 0.9, tol) # bug fixed value # bug fixed value assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) # this is the large single aisle 1 V3 test case class DesignLoadGroupTestCase2smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "Dload", - DesignLoadGroup( - aviary_options=options, - ), - promotes=["*"], + 'Dload', + DesignLoadGroup(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) # bug fixed and original value self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=126, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=126, units='lbf/ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.AVERAGE_CHORD, val=12.71, units="ft" + Aircraft.Wing.AVERAGE_CHORD, val=12.71, units='ft' ) # bug fixed value + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=0.436, units='rad') + self.prob.model.set_input_defaults(Mission.Design.MACH, val=0.8, units='unitless') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 6e-4 - assert_near_equal(self.prob["max_mach"], 0.9, tol) # bug fixed value + assert_near_equal(self.prob['max_mach'], 0.9, tol) # bug fixed value # bug fixed value assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.7397, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=2e-14, rtol=2e-12) + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-13, rtol=5e-12) + + +class BWBLoadSpeedsTestCATD3(unittest.TestCase): + """PART25_STRUCTURAL_CATEGORY = 3.""" + + def setUp(self): + self.options = get_option_defaults() + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') # default + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'speeds', + BWBLoadSpeeds(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' + ) + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """GASP data""" + + self.options.set_val( + Aircraft.Design.PART25_STRUCTURAL_CATEGORY, + val=3, + units='unitless', + ) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 2.5, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + def test_case2(self): + """Aviary enhanced algorithms""" + + # case 2A + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 2.5, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2B + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 2.5, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2C + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 2.5, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + +class BWBLoadSpeedsTestCATD0(unittest.TestCase): + """PART25_STRUCTURAL_CATEGORY = 0.""" + + def setUp(self): + self.options = get_option_defaults() + self.options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=0, units='unitless') + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') # default + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'speeds', + BWBLoadSpeeds(), + promotes=['*'], + ) + self.prob.model.set_input_defaults( + Aircraft.Design.MAX_STRUCTURAL_SPEED, 402.5, units='mi/h' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.1136, units='ft**2') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """GASP data""" + + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 336.68277925, tol) + assert_near_equal(self.prob['vel_c'], 294.8987279, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 3.8, tol) + assert_near_equal(self.prob['min_dive_vel'], 396.09738736, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + def test_case2(self): + """Aviary enhanced algorithms""" + + # case 2A + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 336.68277925, tol) + assert_near_equal(self.prob['vel_c'], 294.8987279, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 3.8, tol) + assert_near_equal(self.prob['min_dive_vel'], 396.09738736, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2B + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 374.85124973, tol) + assert_near_equal(self.prob['vel_c'], 315.0010502, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 3.8, tol) + assert_near_equal(self.prob['min_dive_vel'], 441.00147028, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=5e-14) + + # case 2C + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 336.72148918, tol) + assert_near_equal(self.prob['vel_c'], 294.93269834, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 3.8, tol) + assert_near_equal(self.prob['min_dive_vel'], 396.14292844, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=5e-14) + + +class BWBLoadSpeedsTestCATD1(unittest.TestCase): + """PART25_STRUCTURAL_CATEGORY = 1.""" + + def setUp(self): + self.options = get_option_defaults() + self.options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=1, units='unitless') + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') # default + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'speeds', + BWBLoadSpeeds(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.Design.MAX_STRUCTURAL_SPEED, 402.5, units='mi/h' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.1136, units='ft**2') + + setup_model_options(self.prob, self.options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """GASP data""" + + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 333.25575724, tol) + assert_near_equal(self.prob['vel_c'], 294.8987279, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.4, tol) + assert_near_equal(self.prob['min_dive_vel'], 392.06559676, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + def test_case2(self): + """Aviary enhanced algorithms""" + + # case 2A + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 401.625, tol) + assert_near_equal(self.prob['vel_c'], 315.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.4, tol) + assert_near_equal(self.prob['min_dive_vel'], 472.5, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2B + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 401.626339, tol) + assert_near_equal(self.prob['vel_c'], 315.0010502, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.4, tol) + assert_near_equal(self.prob['min_dive_vel'], 472.5015753, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + # assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2C + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 333.29393309, tol) + assert_near_equal(self.prob['vel_c'], 294.93269834, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.4, tol) + assert_near_equal(self.prob['min_dive_vel'], 392.11050952, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=5e-14) + + +class BWBLoadSpeedsTestCATD2(unittest.TestCase): + def setUp(self): + self.options = get_option_defaults() + self.options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=2, units='unitless') + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') # default + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'speeds', + BWBLoadSpeeds(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.Design.MAX_STRUCTURAL_SPEED, 402.5, units='mi/h' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.1136, units='ft**2') + + setup_model_options(self.prob, self.options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """GASP data""" + + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 326.68543372, tol) + assert_near_equal(self.prob['vel_c'], 290.57871182, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 6.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 384.33580438, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + def test_case2(self): + """Aviary enhanced algorithms""" + + # case 2A + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 415.0125, tol) + assert_near_equal(self.prob['vel_c'], 315.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 6.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 488.25, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2B + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 415.01250012, tol) + assert_near_equal(self.prob['vel_c'], 315.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 6.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 488.25, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=5e-14) + + # case 2C + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 326.69562597, tol) + assert_near_equal(self.prob['vel_c'], 290.5891973, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 6.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 384.34779526, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=5e-14) + + +class BWBLoadSpeedsTestCATD4(unittest.TestCase): + def setUp(self): + self.options = get_option_defaults() + # In this case, the value of PART25_STRUCTURAL_CATEGORY is used as max_maneuver_factor + self.options.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, val=4, units='unitless') + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') # default + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'speeds', + BWBLoadSpeeds(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.Design.MAX_STRUCTURAL_SPEED, 402.5, units='mi/h' + ) + + setup_model_options(self.prob, self.options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """GASP data""" + + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + def test_case2(self): + """Aviary enhanced algorithms""" + + # case 2A + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2B + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) # default + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=False, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + # case 2C + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val(Aircraft.Wing.LOADING_ABOVE_20, val=True, units='unitless') + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_airspeed'], 350.0, tol) + assert_near_equal(self.prob['vel_c'], 350.0, tol) + assert_near_equal(self.prob['max_maneuver_factor'], 4.0, tol) + assert_near_equal(self.prob['min_dive_vel'], 420.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + +class BWBLoadFactorsTestCaseNonsmooth(unittest.TestCase): + """GASP data""" + + def setUp(self): + prob = self.prob = om.Problem() + self.prob.model.add_subsystem('factors', BWBLoadFactors(), promotes=['*']) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, 1352.1136, units='ft**2') + prob.model.set_input_defaults('density_ratio', 0.692859828, units='unitless') + prob.model.set_input_defaults('V9', 350.0, units='kn') + prob.model.set_input_defaults('min_dive_vel', 420, units='kn') + prob.model.set_input_defaults('max_maneuver_factor', 2.5, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, 16.2200546, units='ft') + prob.model.set_input_defaults(Aircraft.Design.LIFT_CURVE_SLOPE, 5.94851685, units='1/rad') + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + Test the simplest scenario + """ + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) + + def test_case2(self): + """ + Test all other if-else branches comparing + cruise_load_factor vs dive_load_factor, and gust_load_factor vs max_maneuver_factor + """ + + # Case 2A + self.prob.set_val('density_ratio', 0.53281, units='unitless') + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.77353191, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) + + # Case 2B + self.prob.set_val('density_ratio', 0.53281, units='unitless') + self.prob.set_val('V9', 210.0, units='kn') + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) + + # Case 2C + self.prob.set_val('density_ratio', 0.53281, units='unitless') + self.prob.set_val('V9', 209.9, units='kn') + self.prob.set_val('max_maneuver_factor', 1.9, units='unitless') + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 2.86411929, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) + + +class BWBLoadFactorsTestCaseSmooth(unittest.TestCase): + """Test for smoothing technique""" + + def setUp(self): + self.options = get_option_defaults() + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + + prob = self.prob = om.Problem() + prob.model.add_subsystem('factors', BWBLoadFactors(), promotes=['*']) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, val=1352.1136, units='ft**2') + prob.model.set_input_defaults('density_ratio', val=0.692859828, units='unitless') + prob.model.set_input_defaults('V9', val=350.0, units='kn') + prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') + prob.model.set_input_defaults('max_maneuver_factor', val=2.5, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=16.2200546, units='ft') + prob.model.set_input_defaults(Aircraft.Design.LIFT_CURVE_SLOPE, val=5.94852, units='1/rad') + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + Test the simplest scenario + """ + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-14) + + +@use_tempdirs +class BWBDesignLoadGroupTestCaseNonsmooth(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') + + prob = self.prob = om.Problem() + + self.prob.model.add_subsystem( + 'Dload', + BWBDesignLoadGroup(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h') + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, val=1352.1136, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=12.71, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + + setup_model_options(self.prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_mach'], 0.9, tol) + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-15, rtol=1e-15) + + +@use_tempdirs +class BWBDesignLoadGroupTestCaseSmooth(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') + options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') + + prob = self.prob = om.Problem() + + prob.model.add_subsystem( + 'Dload', + BWBDesignLoadGroup(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h') + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.EXPOSED_AREA, val=1352.1136, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.AVERAGE_CHORD, val=12.71, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=0.436, units='rad') + prob.model.set_input_defaults(Mission.Design.MACH, val=0.8, units='unitless') + + setup_model_options(self.prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['max_mach'], 0.90046425, tol) + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.97744787, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-13, rtol=5e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py b/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py index bb1328cf9a..accd329265 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py +++ b/aviary/subsystems/mass/gasp_based/test/test_equipment_and_useful_load.py @@ -1,754 +1,1740 @@ import unittest -import os import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import \ - EquipAndUsefulLoadMass +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.mass.gasp_based.equipment_and_useful_load import ( + BWBACMass, + BWBFurnishingMass, + BWBEquipMassGroup, + ACMass, + EquipMassPartialSum, + FurnishingMass, + EquipMassSum, + EquipMassGroup, + UsefulLoadMass, + EquipAndUsefulLoadMassGroup, +) from aviary.variable_info.enums import GASPEngineType +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.variables import Aircraft, Mission, Settings class FixedEquipMassTestCase1(unittest.TestCase): - """ this is the large single aisle 1 V3 test case""" + """this is the large single aisle 1 V3 test case""" def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "equip", - EquipAndUsefulLoadMass(aviary_options=options), - promotes=["*"], + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=[29500.0], units="lbf" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' ) + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 1e-4 - assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 21089, tol) - assert_near_equal( - self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5176, tol - ) # modified from GASP value to account for updated crew mass. GASP value is 4932 + tol = 1e-7 + assert_near_equal(self.prob['equip_mass_part'], 8573.19157631, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -class FixedEquipMassTestCase2(unittest.TestCase): +class EquipMassTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=5, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=5, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "equip", - EquipAndUsefulLoadMass(aviary_options=options), - promotes=["*"], + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' ) + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 1e-4 + tol = 1e-7 # not actual GASP value - assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 1235.4, tol) assert_near_equal( - self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 23509, tol + self.prob['equip_mass_part'], 10992.96303693, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -class FixedEquipMassTestCase3(unittest.TestCase): +class EquipMassTestCase3(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Engine.TYPE, - val=[GASPEngineType.RECIP_CARB], units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') + options.set_val(Aircraft.Engine.TYPE, val=[GASPEngineType.RECIP_CARB], units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + # PAX = 0 self.prob = om.Problem() self.prob.model.add_subsystem( - "equip", - EquipAndUsefulLoadMass(aviary_options=options), - promotes=["*"], + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' ) + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 1e-4 + tol = 1e-7 # not actual GASP value - assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 892.83, tol) assert_near_equal( - self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 23509, tol + self.prob['equip_mass_part'], 10992.96303693, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -class FixedEquipMassTestCase4smooth(unittest.TestCase): - """this is the large single aisle 1 V3 test case""" +class FixedEquipMassTestCase4(unittest.TestCase): + """ + Test mass-weight conversion + """ def setUp(self): + import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + + equip.GRAV_ENGLISH_LBM = 1.1 + + def tearDown(self): + import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + + equip.GRAV_ENGLISH_LBM = 1.0 + + def test_case1(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + + prob = om.Problem() + prob.model.add_subsystem( + 'equip', + EquipMassPartialSum(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' + ) + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FixedEquipMassTestCase5smooth(unittest.TestCase): + """this is the large single aisle 1 V3 test case""" + def setUp(self): options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "equip", - EquipAndUsefulLoadMass( - aviary_options=options, - ), - promotes=["*"], + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' + ) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 1e-4 + tol = 1e-7 - assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 21089, tol) - assert_near_equal( - self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5176, tol - ) # modified from GASP value to account for updated crew mass. GASP value is 4932 + assert_near_equal(self.prob['equip_mass_part'], 8573.19157631, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -class FixedEquipMassTestCase5smooth(unittest.TestCase): +class FixedEquipMassTestCase6smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=5, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=5, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "equip", - EquipAndUsefulLoadMass( - aviary_options=options, - ), - promotes=["*"], + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' + ) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 1e-4 + tol = 1e-7 # not actual GASP value - assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 1235.4, tol) assert_near_equal( - self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 23509, tol + self.prob['equip_mass_part'], 10992.96303693, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -class FixedEquipMassTestCase6smooth(unittest.TestCase): +class FixedEquipMassTestCase7smooth(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=5, units='unitless') - options.set_val(Aircraft.Engine.TYPE, - val=[GASPEngineType.RECIP_CARB], units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=5, units='unitless') + options.set_val(Aircraft.Engine.TYPE, val=[GASPEngineType.RECIP_CARB], units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "equip", - EquipAndUsefulLoadMass( - aviary_options=options - ), - promotes=["*"], + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' ) + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 1e-4 + tol = 1e-7 # not actual GASP value - assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 892.83, tol) assert_near_equal( - self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 23509, tol + self.prob['equip_mass_part'], 10992.96303693, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -class EquipAndUsefulMassGroupTestCase1(unittest.TestCase): - """this is the large single aisle 1 V3 test case""" +class FixedEquipMassTestCase8(unittest.TestCase): + """ + this is the same case as EquipMassTestCase1, except: + Aircraft.APU.MASS = 0.0, + Aircraft.Avionics.MASS = 0.0, + Aircraft.AntiIcing.MASS = 0.0, + Aircraft.Furnishings.MASS = 0.0 + """ def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - EquipAndUsefulLoadMass(aviary_options=options), - promotes=["*"], + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=0.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=0.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=0.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' + ) - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['equip_mass_part'], 8410.62948115, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FixedEquipMassTestCase9smooth(unittest.TestCase): + """ + this is the same case as EquipMassTestCase5smooth, except: + Aircraft.APU.MASS = 0.0, + Aircraft.Avionics.MASS = 0.0, + Aircraft.AntiIcing.MASS = 0.0, + Aircraft.Furnishings.MASS = 0.0 + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'equip', + EquipMassPartialSum(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=0.0, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=0.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=0.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['equip_mass_part'], 8410.62948115, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +@use_tempdirs +class ACMassTestCase1(unittest.TestCase): + """ + Created based on EquipMassTestCase1 + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'ac', + ACMass(), + promotes=['*'], + ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 1e-4 - assert_near_equal( - self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5176, tol - ) # modified from GASP value to account for updated crew mass. GASP value is 4932 - assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 21089, tol) + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.AirConditioning.MASS], 1324.0561, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -class FixedEquipMassTestCase7(unittest.TestCase): +class ACMassTestCase2(unittest.TestCase): """ Test mass-weight conversion """ def setUp(self): import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + equip.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + equip.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): options = get_option_defaults() - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'ac', + ACMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FurnishingMassTestCase1(unittest.TestCase): + """Created based on EquipMassTestCase1""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.Furnishings.USE_EMPIRICAL_EQUATION, val=True, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'furnishing', + FurnishingMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 13266.56, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FurnishingMassTestCase2(unittest.TestCase): + """Test mass-weight conversion""" + + def setUp(self): + import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + + equip.GRAV_ENGLISH_LBM = 1.1 + + def tearDown(self): + import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + + equip.GRAV_ENGLISH_LBM = 1.0 + + def test_case1(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.Furnishings.USE_EMPIRICAL_EQUATION, val=True, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'furnishing', + FurnishingMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FurnishingMassTestCase3(unittest.TestCase): + """ + Created based on GASP BWB model where SWF is DHYDRAL + NUM_PASSENGERS < 50 + """ + + def setUp(self): + self.options = get_option_defaults() + self.options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=49, units='unitless') + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'furnishing', + FurnishingMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=19.365, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.CABIN_AREA, val=1283.5249, units='ft**2' + ) + + setup_model_options(self.prob, self.options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + SMOOTH_MASS_DISCONTINUITIES = False + """ + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 3348.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + def test_case2(self): + """ + SMOOTH_MASS_DISCONTINUITIES = True + """ + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 3348.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FixedEquipMassSumTestCase1(unittest.TestCase): + """ + Created based on EquipMassTestCase1 + """ + + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'sum', + EquipMassSum(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults('equip_mass_part', val=8573.19157631, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.AirConditioning.MASS, val=1324.0561, units='lbm' + ) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 21089.248, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FixedEquipMassGroupTest(unittest.TestCase): + """this is the large single aisle 1 V3 test case""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + EquipMassGroup(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + + self.prob.model.set_input_defaults( + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1068.96, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Furnishings.MASS_SCALER, val=40.0, units='unitless' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 20283.787, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class UsefulMassTestCase1(unittest.TestCase): + """this is the large single aisle 1 V3 test case""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Settings.VERBOSITY, 0) + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'useful', + UsefulLoadMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Engine.SCALED_SLS_THRUST, val=[29500.0], units='lbf' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units='unitless' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal( + self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5341.42896854, tol + ) # modified from GASP value to account for updated crew mass. GASP value is 4932 + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class UsefulMassTestCase2(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=5, units='unitless') + options.set_val(Settings.VERBOSITY, 0) + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'useful', + UsefulLoadMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units='unitless' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + # not actual GASP value + assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 1400.42896854, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class UsefulMassTestCase3(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Engine.TYPE, val=[GASPEngineType.RECIP_CARB], units='unitless') + options.set_val(Settings.VERBOSITY, 0) + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'useful', + UsefulLoadMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units='unitless' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + # not actual GASP value + assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 1057.82896854, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class UsefulMassTestCase4(unittest.TestCase): + """ + Test mass-weight conversion + """ + + def setUp(self): + import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + + equip.GRAV_ENGLISH_LBM = 1.1 + + def tearDown(self): + import aviary.subsystems.mass.gasp_based.equipment_and_useful_load as equip + + equip.GRAV_ENGLISH_LBM = 1.0 + + def test_case1(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Settings.VERBOSITY, 0) prob = om.Problem() prob.model.add_subsystem( - "equip", - EquipAndUsefulLoadMass(aviary_options=options), - promotes=["*"], + 'useful', + UsefulLoadMass(), + promotes=['*'], + ) + + prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + prob.model.set_input_defaults(Aircraft.Engine.SCALED_SLS_THRUST, val=[29500.0], units='lbf') + prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units='unitless') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class UsefulMassTestCase5(unittest.TestCase): + """ + this is the same case as UsefulMassTestCase1, except: + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS = 0.0 + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Settings.VERBOSITY, 0) + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'useful', + UsefulLoadMass(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=0.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Engine.SCALED_SLS_THRUST, val=[29500.0], units='lbf' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units='unitless' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal( + self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5406.429, tol + ) # modified from GASP value to account for updated crew mass. GASP value is 4932 + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class FixedEquipAndUsefulMassGroupTest(unittest.TestCase): + """this is the large single aisle 1 V3 test case""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.TYPE, val='transport', units='unitless') + + self.prob = om.Problem() + self.prob.model.add_subsystem( + 'group', + EquipAndUsefulLoadMassGroup(), + promotes=['*'], + ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + # self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' + ) + + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1370.3, units='ft**2') + + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, val=469.3, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + + self.prob.model.set_input_defaults( + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1068.96, units='ft**2') + self.prob.model.set_input_defaults( + Aircraft.Furnishings.MASS_SCALER, val=40.0, units='unitless' + ) + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5341.429, tol) + assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 23163.787, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class BWBACMassTestCase1(unittest.TestCase): + """ + Created based on GASP BWB model + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + + prob = self.prob = om.Problem() + self.prob.model.add_subsystem( + 'ac', + BWBACMass(), + promotes=['*'], + ) + + prob.model.set_input_defaults( + Aircraft.AirConditioning.MASS_COEFFICIENT, 1.155, units='unitless' + ) + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.52455, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, 10.0, units='psi') + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.365, units='ft') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.AirConditioning.MASS], 1301.5666, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class BWBFurnishingMassTestCase1(unittest.TestCase): + """ + Created based on GASP BWB model + """ + + def setUp(self): + self.options = get_option_defaults() + self.options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + self.options.set_val( + Aircraft.Furnishings.USE_EMPIRICAL_EQUATION, val=True, units='unitless' + ) + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'furnishing', + BWBFurnishingMass(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, 1283.5249, units='ft**2') + + setup_model_options(self.prob, self.options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + USE_EMPIRICAL_EQUATION = True + SMOOTH_MASS_DISCONTINUITIES = False + """ + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 11269.863, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + def test_case2(self): + # case 2A + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) + self.options.set_val( + Aircraft.Furnishings.USE_EMPIRICAL_EQUATION, val=False, units='unitless' + ) + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 18839.863, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + # case 2B + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val( + Aircraft.Furnishings.USE_EMPIRICAL_EQUATION, val=True, units='unitless' + ) + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + # assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 11269.863, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + # case 2C + self.options.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless' + ) + self.options.set_val( + Aircraft.Furnishings.USE_EMPIRICAL_EQUATION, val=False, units='unitless' + ) + setup_model_options(self.prob, self.options) + self.prob.setup(check=False, force_alloc_complex=True) + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 18839.863, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class BWBFurnishingMassTestCase2(unittest.TestCase): + """ + Created based on GASP BWB model + GROSS_MASS < 10000 + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'furnishing', + BWBFurnishingMass(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 9999.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.365, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, 1283.5249, units='ft**2') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 590.935, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +@use_tempdirs +class BWBFixedEquipMassGroupTest(unittest.TestCase): + """Created based on GASP BWB modele""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'group', + BWBEquipMassGroup(), + promotes=['*'], ) + prob.model.set_input_defaults(Aircraft.APU.MASS, 710.0, units='lbm') prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") + Aircraft.Instruments.MASS_COEFFICIENT, 0.116, units='unitless' + ) prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, 0.107, units='unitless' + ) prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, 0.135, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Avionics.MASS, 3225.0, units='lbm') + prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, 236.0, units='lbm') prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, 6.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, 3, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, 100.0, units='lbm') prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, 5.0, units='lbm' + ) prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, 12.0, units='unitless' + ) + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, 7800.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, 2115.19946, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00170628, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.119629, units='ft**2') prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") + Aircraft.AirConditioning.MASS_COEFFICIENT, 1.155, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, 10.0, units='psi') + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, 1283.5249, units='ft**2') + prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, 11.45, units='lbm' + ) + + setup_model_options(self.prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 20876.476, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +class BWBUsefulMassTestCase1(unittest.TestCase): + """ + Created based on GASP BWB modele + """ + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Settings.VERBOSITY, 0) + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'useful', + UsefulLoadMass(), + promotes=['*'], + ) + prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, 6.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, 3, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, 100.0, units='lbm') prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, 5.0, units='lbm' + ) prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, 12.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Engine.SCALED_SLS_THRUST, [19580.1602], units='lbf') + prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.45, units='unitless') + + setup_model_options(self.prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 4321.79463506, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) + + +@use_tempdirs +class BWBFixedEquipAndUsefulMassGroupTest(unittest.TestCase): + """this is the large single aisle 1 V3 test case""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'group', + EquipAndUsefulLoadMassGroup(), + promotes=['*'], + ) + + # inputs to BWBEquipMassGroup + prob.model.set_input_defaults(Aircraft.APU.MASS, 710.0, units='lbm') prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") + Aircraft.Instruments.MASS_COEFFICIENT, 0.116, units='unitless' + ) prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, 0.107, units='unitless' + ) prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm") + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, 0.135, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Avionics.MASS, 3225.0, units='lbm') + prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, 236.0, units='lbm') prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft") - prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, 6.0, units='lbm' + ) prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, 3.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, 100.0, units='lbm') prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, 5.0, units='lbm' + ) prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2") + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, 12.0, units='unitless' + ) + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, 7800.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, 2115.19946, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.001706279, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.119629, units='ft**2') prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2") + Aircraft.AirConditioning.MASS_COEFFICIENT, 1.155, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, 10.0, units='psi') + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, 1283.5249, units='ft**2') + prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2") + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, 11.45, units='lbm' + ) + + # inputs to UsefulLoadMass prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, 6.0, units='lbm' + ) prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, 3.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, 100.0, units='lbm') prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=[29500.0], units="lbf") + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, 5.0, units='lbm' + ) prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, val=0.6, units="unitless") + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, 12.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Engine.SCALED_SLS_THRUST, [19580.1602], units='lbf') + prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.45, units='unitless') + + setup_model_options(self.prob, options) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.AirConditioning.MASS], 1301.573, tol) + assert_near_equal(self.prob[Aircraft.Furnishings.MASS], 11269.877, tol) + assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 20876.477, tol) + assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 4321.79463506, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=8e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/gasp_based/test/test_fixed.py b/aviary/subsystems/mass/gasp_based/test/test_fixed.py index 522d7d469a..6dde3cc8aa 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_fixed.py +++ b/aviary/subsystems/mass/gasp_based/test/test_fixed.py @@ -2,323 +2,290 @@ import numpy as np import openmdao.api as om - from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs from aviary import constants from aviary.constants import RHO_SEA_LEVEL_ENGLISH - -from aviary.subsystems.mass.gasp_based.fixed import (ControlMass, - ElectricAugmentationMass, - EngineMass, - FixedMassGroup, GearMass, - HighLiftMass, - MassParameters, - PayloadMass, TailMass) +from aviary.subsystems.mass.gasp_based.fixed import ( + ControlMass, + ElectricAugmentationMass, + EngineMass, + FixedMassGroup, + GearMass, + HighLiftMass, + MassParameters, + PayloadGroup, + TailMass, +) from aviary.utils.aviary_values import AviaryValues, get_keys +from aviary.variable_info.functions import extract_options, setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.variables import Aircraft, Mission, Settings +@use_tempdirs class MassParametersTestCase1(unittest.TestCase): - """this is large single aisle 1 v3 bug fixed test case""" + """this is large single aisle 1 v3 bug fixed test case.""" def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') + options.set_val(Settings.VERBOSITY, 0) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, val=0) self.prob = om.Problem() self.prob.model.add_subsystem( - "parameters", - MassParameters( - aviary_options=options - ), - promotes=["*"], + 'parameters', + MassParameters(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Wing.SWEEP, val=25, units="deg" - ) # bug fixed value - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.SWEEP, val=25, units='deg' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" + Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=118.8, units="ft" + Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless' ) # bug fixed value self.prob.model.set_input_defaults( - "max_mach", val=0.9, units="unitless" + Aircraft.Wing.SPAN, val=118.8, units='ft' ) # bug fixed value + self.prob.model.set_input_defaults('max_mach', val=0.9, units='unitless') # bug fixed value + self.prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2203729275531838, tol ) # bug fixed value - assert_near_equal(self.prob["c_strut_braced"], 1, tol) # bug fixed value - assert_near_equal(self.prob["c_gear_loc"], 1, tol) # bug fixed value + assert_near_equal(self.prob['c_strut_braced'], 1, tol) # bug fixed value + assert_near_equal(self.prob['c_gear_loc'], 1, tol) # bug fixed value # bug fixed value assert_near_equal(self.prob[Aircraft.Engine.POSITION_FACTOR], 0.95, tol) - assert_near_equal( - self.prob["half_sweep"], 0.3947081519145335, tol - ) # bug fixed value + assert_near_equal(self.prob['half_sweep'], 0.3947081519145335, tol) # bug fixed value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) +@use_tempdirs class MassParametersTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, val=2, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "parameters", - MassParameters( - aviary_options=options, - ), - promotes=["*"], + 'parameters', + MassParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=117.8, units="ft" + Aircraft.Wing.SPAN, val=117.8, units='ft' ) # not actual bug fixed value self.prob.model.set_input_defaults( - "max_mach", val=0.72, units="unitless" + 'max_mach', val=0.72, units='unitless' ) # not actual bug fixed value - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0 - ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2213063198183813, tol ) # not actual bug fixed value - assert_near_equal(self.prob["c_strut_braced"], 1, tol) - assert_near_equal( - self.prob["c_gear_loc"], 0.95, tol - ) # not actual bug fixed value + assert_near_equal(self.prob['c_strut_braced'], 1, tol) + assert_near_equal(self.prob['c_gear_loc'], 0.95, tol) # not actual bug fixed value # not actual bug fixed value assert_near_equal(self.prob[Aircraft.Engine.POSITION_FACTOR], 1, tol) - assert_near_equal(self.prob["half_sweep"], 0.3947081519145335, tol) + assert_near_equal(self.prob['half_sweep'], 0.3947081519145335, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) +@use_tempdirs class MassParametersTestCase3(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, val=3, units='unitless') options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, val=0, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "parameters", - MassParameters( - aviary_options=options, - ), - promotes=["*"], + 'parameters', + MassParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=117.8, units="ft" + Aircraft.Wing.SPAN, val=117.8, units='ft' ) # not actual bug fixed value self.prob.model.set_input_defaults( - "max_mach", val=0.72, units="unitless" + 'max_mach', val=0.72, units='unitless' ) # not actual bug fixed value - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0 - ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2213063198183813, tol ) # not actual bug fixed value - assert_near_equal(self.prob["c_strut_braced"], 1, tol) - assert_near_equal( - self.prob["c_gear_loc"], 0.95, tol - ) # not actual bug fixed value + assert_near_equal(self.prob['c_strut_braced'], 1, tol) + assert_near_equal(self.prob['c_gear_loc'], 0.95, tol) # not actual bug fixed value assert_near_equal( self.prob[Aircraft.Engine.POSITION_FACTOR], 0.98, tol ) # not actual bug fixed value - assert_near_equal(self.prob["half_sweep"], 0.3947081519145335, tol) + assert_near_equal(self.prob['half_sweep'], 0.3947081519145335, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) +@use_tempdirs class MassParametersTestCase4(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, val=4, units='unitless') options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, val=0, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "parameters", - MassParameters( - aviary_options=options, - ), - promotes=["*"], + 'parameters', + MassParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=117.8, units="ft" + Aircraft.Wing.SPAN, val=117.8, units='ft' ) # not actual bug fixed value self.prob.model.set_input_defaults( - "max_mach", val=0.72, units="unitless" + 'max_mach', val=0.72, units='unitless' ) # not actual bug fixed value - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0 - ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2213063198183813, tol ) # not actual bug fixed value - assert_near_equal(self.prob["c_strut_braced"], 1, tol) - assert_near_equal( - self.prob["c_gear_loc"], 0.95, tol - ) # not actual bug fixed value + assert_near_equal(self.prob['c_strut_braced'], 1, tol) + assert_near_equal(self.prob['c_gear_loc'], 0.95, tol) # not actual bug fixed value assert_near_equal( self.prob[Aircraft.Engine.POSITION_FACTOR], 0.95, tol ) # not actual bug fixed value - assert_near_equal(self.prob["half_sweep"], 0.3947081519145335, tol) + assert_near_equal(self.prob['half_sweep'], 0.3947081519145335, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) +@use_tempdirs class MassParametersTestCase5(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, val=4, units='unitless') options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, val=0, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "parameters", - MassParameters( - aviary_options=options, - ), - promotes=["*"], + 'parameters', + MassParameters(), + promotes=['*'], ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=117.8, units="ft" + Aircraft.Wing.SPAN, val=117.8, units='ft' ) # not actual bug fixed value self.prob.model.set_input_defaults( - "max_mach", val=0.9, units="unitless" + 'max_mach', val=0.9, units='unitless' ) # not actual bug fixed value - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0 - ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 assert_near_equal( self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2213063198183813, tol ) # not actual bug fixed value - assert_near_equal(self.prob["c_strut_braced"], 1, tol) - assert_near_equal( - self.prob["c_gear_loc"], 0.95, tol - ) # not actual bug fixed value + assert_near_equal(self.prob['c_strut_braced'], 1, tol) + assert_near_equal(self.prob['c_gear_loc'], 0.95, tol) # not actual bug fixed value assert_near_equal( self.prob[Aircraft.Engine.POSITION_FACTOR], 0.9, tol ) # not actual bug fixed value - assert_near_equal(self.prob["half_sweep"], 0.3947081519145335, tol) + assert_near_equal(self.prob['half_sweep'], 0.3947081519145335, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) # this is the large single aisle 1 V3 test case -class PayloadMassTestCase(unittest.TestCase): +@use_tempdirs +class PayloadGroupTestCase(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") # bug fixed value and original value + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val( + Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm' + ) # bug fixed value and original value self.prob = om.Problem() - self.prob.model.add_subsystem("payload", PayloadMass( - aviary_options=options), promotes=["*"]) + self.prob.model.add_subsystem('payload', PayloadGroup(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" - ) # bug fixed value and original value + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' + ) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 @@ -326,139 +293,138 @@ def test_case1(self): self.prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 36000, tol ) # bug fixed value and original value assert_near_equal( - self.prob["payload_mass_des"], 36000, tol + self.prob['payload_mass_des'], 36000, tol ) # bug fixed value and original value assert_near_equal( - self.prob["payload_mass_max"], 46040, tol + self.prob['payload_mass_max'], 46040, tol ) # bug fixed value and original value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) +@use_tempdirs class ElectricAugmentationTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "aug", ElectricAugmentationMass(aviary_options=get_option_defaults()), promotes=["*"] - ) + + options = { + Aircraft.Propulsion.TOTAL_NUM_ENGINES: 2, + } + self.prob.model.add_subsystem('aug', ElectricAugmentationMass(**options), promotes=['*']) self.prob.model.set_input_defaults( - "motor_power", val=830, units="kW" + 'motor_power', val=830, units='kW' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "motor_voltage", val=850, units="V" + 'motor_voltage', val=850, units='V' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "max_amp_per_wire", val=260, units="A" + 'max_amp_per_wire', val=260, units='A' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "safety_factor", val=1.0, units="unitless" + 'safety_factor', val=1.0, units='unitless' ) # not included in eTTVW v3.6 self.prob.model.set_input_defaults( - Aircraft.Electrical.HYBRID_CABLE_LENGTH, val=65.6, units="ft" + Aircraft.Electrical.HYBRID_CABLE_LENGTH, val=65.6, units='ft' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "wire_area", val=0.0015, units="ft**2" + 'wire_area', val=0.0015, units='ft**2' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "rho_wire", val=565, units="lbm/ft**3" + 'rho_wire', val=565, units='lbm/ft**3' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "battery_energy", val=6077, units="MJ" + 'battery_energy', val=6077, units='MJ' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "motor_eff", val=0.98, units="unitless" + 'motor_eff', val=0.98, units='unitless' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "inverter_eff", val=0.99, units="unitless" + 'inverter_eff', val=0.99, units='unitless' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "transmission_eff", val=0.975, units="unitless" + 'transmission_eff', val=0.975, units='unitless' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "battery_eff", val=0.975, units="unitless" + 'battery_eff', val=0.975, units='unitless' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "rho_battery", val=0.5, units="kW*h/kg" + 'rho_battery', val=0.5, units='kW*h/kg' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "motor_spec_mass", val=4, units="hp/lbm" + 'motor_spec_mass', val=4, units='hp/lbm' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "inverter_spec_mass", val=12, units="kW/kg" + 'inverter_spec_mass', val=12, units='kW/kg' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - "TMS_spec_mass", val=0.125, units="lbm/kW" + 'TMS_spec_mass', val=0.125, units='lbm/kW' ) # electrified diff configuration value v3.6 + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - tol = 5e-4 assert_near_equal( - self.prob["aug_mass"], 9394.3, 0.0017 + self.prob['aug_mass'], 9394.3, 0.0017 ) # electrified diff configuration value v3.6. Higher tol because num_wires is discrete in GASP and is not in Aviary - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=4e-12, rtol=1e-12) +@use_tempdirs class EngineTestCase1(unittest.TestCase): # this is the large single aisle 1 V3 test case def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14) self.prob = om.Problem() self.prob.model.add_subsystem( - "engine", - EngineMass(aviary_options=options), - promotes=["*"], + 'engine', + EngineMass(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.SURFACE_AREA, val=339.58, units="ft**2" + Aircraft.Nacelle.SURFACE_AREA, val=339.58, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Engine.MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS, val=6384.35, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS, val=6384.35, units="lbm" - ) # bug fixed value and original value - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) # bug fixed value and original value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -469,76 +435,76 @@ def test_case1(self): self.prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 3785.0, tol ) # bug fixed value and original value assert_near_equal( - self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765.0/2, tol + self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765.0 / 2, tol ) # bug fixed value and original value assert_near_equal( - self.prob["eng_comb_mass"], 14370.8, tol + self.prob['eng_comb_mass'], 14370.8, tol ) # bug fixed value and original value assert_near_equal( - self.prob["wing_mounted_mass"], 24446.343040697346, tol + self.prob['wing_mounted_mass'], 24446.343040697346, tol ) # bug fixed value and original value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-11, rtol=1e-12) +@use_tempdirs class EngineTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Engine.HAS_PROPELLERS, val=[True], units='unitless') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14) + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "engine", - EngineMass(aviary_options=options), - promotes=["*"], + 'engine', + EngineMass(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.SURFACE_AREA, val=339.58, units="ft**2" + Aircraft.Nacelle.SURFACE_AREA, val=339.58, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Engine.MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless" + 'prop_mass', val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "prop_mass", val=0, units="lbm" + 'aug_mass', val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "aug_mass", val=0, units="lbm" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS, val=6384.35, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS, val=6384.35, units="lbm" - ) # bug fixed value and original value - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) # bug fixed value and original value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -549,62 +515,72 @@ def test_case1(self): self.prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 3785.0, tol ) # note: these are only the right values because this was given a prop mass of zero. This is not a large single aisle test case assert_near_equal( - self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765.0/2, tol + self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765.0 / 2, tol ) # note: these are only the right values because this was given a prop mass of zero. This is not a large single aisle test case assert_near_equal( - self.prob["eng_comb_mass"], 14370.8, tol + self.prob['eng_comb_mass'], 14370.8, tol ) # note: these are only the right values because this was given a prop mass of zero. This is not a large single aisle test case assert_near_equal( - self.prob["prop_mass_all"], 0, tol + self.prob['prop_mass_all'], 0, tol ) # note: these are only the right values because this was given a prop mass of zero. This is not a large single aisle test case assert_near_equal( - self.prob["wing_mounted_mass"], 24446.343040697346, tol + self.prob['wing_mounted_mass'], 24446.343040697346, tol ) # note: these are only the right values because this was given a prop mass of zero. This is not a large single aisle test case - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-11, rtol=1e-12) -# arbitarary test case with multiple engine types +# arbitrary test case with multiple engine types +@use_tempdirs class EngineTestCaseMultiEngine(unittest.TestCase): def test_case_1(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2, 4])) - options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 6) + options.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 6) + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, np.array([0.14, 0.19])) self.prob = om.Problem() self.prob.model.add_subsystem( - "engine", - EngineMass(aviary_options=options), - promotes=["*"], + 'engine', + EngineMass(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=[0.21366, 0.15], units="lbm/lbf") - self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=[29500.0, 18000], units="lbf") + Aircraft.Engine.MASS_SPECIFIC, val=[0.21366, 0.15], units='lbm/lbf' + ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=[3, 2.45], units="lbm/ft**2") + Aircraft.Engine.SCALED_SLS_THRUST, val=[29500.0, 18000], units='lbf' + ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.SURFACE_AREA, val=[339.58, 235.66], units="ft**2") + Aircraft.Nacelle.MASS_SPECIFIC, val=[3, 2.45], units='lbm/ft**2' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=[1.25, 1.28], units="unitless") + Aircraft.Nacelle.SURFACE_AREA, val=[339.58, 235.66], units='ft**2' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=[0.14, 0.19], units="unitless") + Aircraft.Engine.PYLON_FACTOR, val=[1.25, 1.28], units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=[1, 0.9], units="unitless") + Aircraft.Engine.MASS_SCALER, val=[1, 0.9], units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=[0.35, 0.0, 0.1], units="unitless") + Aircraft.Engine.WING_LOCATIONS, val=[0.35, 0.0, 0.1], units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS, val=6384.35, units="lbm") + Aircraft.LandingGear.MAIN_GEAR_MASS, val=6384.35, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless") + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' + ) + + self.prob.model_options['*'] = extract_options(options) self.prob.setup(check=False, force_alloc_complex=True) @@ -618,170 +594,151 @@ def test_case_1(self): self.prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 8074.09809932, tol ) # bug fixed value and original value assert_near_equal( - self.prob[Aircraft.Engine.ADDITIONAL_MASS], [882.4158, 513.], tol + self.prob[Aircraft.Engine.ADDITIONAL_MASS], [882.4158, 513.0], tol ) # bug fixed value and original value assert_near_equal( - self.prob["eng_comb_mass"], 26142.7716, tol + self.prob['eng_comb_mass'], 26142.7716, tol ) # bug fixed value and original value assert_near_equal( - self.prob["wing_mounted_mass"], 41417.49593562, tol + self.prob['wing_mounted_mass'], 41417.49593562, tol ) # bug fixed value and original value - partial_data = self.prob.check_partials(out_stream=None, method="cs") - assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) +@use_tempdirs class TailTestCase(unittest.TestCase): # this is the large single aisle 1 V3 test case def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "tail", TailMass(aviary_options=get_option_defaults()), promotes=["*"] - ) + self.prob.model.add_subsystem('tail', TailMass(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units="rad" + Aircraft.VerticalTail.SWEEP, val=0, units='rad' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SPAN, val=28.22, units="ft" + Aircraft.VerticalTail.SPAN, val=28.22, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Mission.Design.GROSS_MASS, val=175400, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Fuselage.LENGTH, val=129.4, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.SPAN, val=42.59, units="ft" + Aircraft.HorizontalTail.SPAN, val=42.59, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=118.8, units="ft" + Aircraft.Wing.SPAN, val=118.8, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=381.8, units="ft**2" + Aircraft.HorizontalTail.AREA, val=381.8, units='ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - "min_dive_vel", val=420, units="kn" + 'min_dive_vel', val=420, units='kn' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_ARM, val=55.1, units="ft" + Aircraft.HorizontalTail.MOMENT_ARM, val=55.1, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ROOT_CHORD, val=13.261162230765065, units="ft" + Aircraft.HorizontalTail.ROOT_CHORD, val=13.261162230765065, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=476.8, units="ft**2" + Aircraft.VerticalTail.AREA, val=476.8, units='ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_ARM, val=50.3, units="ft" + Aircraft.VerticalTail.MOMENT_ARM, val=50.3, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ROOT_CHORD, val=18.762708015981357, units="ft" + Aircraft.VerticalTail.ROOT_CHORD, val=18.762708015981357, units='ft' ) # bug fixed value self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal( - self.prob["loc_MAC_vtail"], 0.44959578484694906, tol - ) # bug fixed value + assert_near_equal(self.prob['loc_MAC_vtail'], 0.44959578484694906, tol) # bug fixed value # bug fixed value assert_near_equal(self.prob[Aircraft.HorizontalTail.MASS], 2285, tol) - assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], - 2312, tol) # bug fixed value + assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], 2312, tol) # bug fixed value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) # this is a different configuration with turbofan_23k_1 test case +@use_tempdirs class HighLiftTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem() aviary_options = get_option_defaults() aviary_options.set_val(Aircraft.Wing.NUM_FLAP_SEGMENTS, val=2) - self.prob.model.add_subsystem( - "HL", HighLiftMass(aviary_options=aviary_options), promotes=["*"] - ) + self.prob.model.add_subsystem('HL', HighLiftMass(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1764.6, units="ft**2" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.SLAT_CHORD_RATIO, val=0.1, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.FLAP_CHORD_RATIO, val=0.25, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=1764.6, units='ft**2') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.346, units="unitless" + Aircraft.Wing.SLAT_CHORD_RATIO, val=0.1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9, units="unitless" + Aircraft.Wing.FLAP_CHORD_RATIO, val=0.25, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.346, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.FLAP_SPAN_RATIO, val=0.88, units="unitless" + Aircraft.Wing.FLAP_SPAN_RATIO, val=0.88, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=93.1, units="lbf/ft**2" + Aircraft.Design.WING_LOADING, val=93.1, units='lbf/ft**2' ) self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=185.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.CENTER_CHORD, val=13.979, units='ft') self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=185.8, units="ft" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.CENTER_CHORD, val=13.979, units="ft" - ) - self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.3648, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.3648, units='unitless' ) + setup_model_options(self.prob, aviary_options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -789,96 +746,97 @@ def test_case1(self): assert_near_equal(self.prob[Aircraft.Wing.HIGH_LIFT_MASS], 4829.6, tol) partial_data = self.prob.check_partials( - out_stream=None, method="cs", show_only_incorrect=True) + out_stream=None, method='cs', show_only_incorrect=True + ) assert_check_partials(partial_data, atol=5e-10, rtol=1e-12) # this is the large single aisle 1 V3 test case +@use_tempdirs class ControlMassTestCase(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("payload", ControlMass( - aviary_options=get_option_defaults()), promotes=["*"]) + self.prob.model.add_subsystem('control_mass', ControlMass(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1392.1, units="ft**2" + Aircraft.Wing.AREA, val=1392.1, units='ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Mission.Design.GROSS_MASS, val=175400, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.951, units="unitless" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.951, units='unitless' ) # bug fixed value self.prob.model.set_input_defaults( - "min_dive_vel", val=420, units="kn" + 'min_dive_vel', val=420, units='kn' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless" + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units="lbm" + Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units='lbm' ) # bug fixed value and original value self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # bug fixed value assert_near_equal(self.prob[Aircraft.Controls.TOTAL_MASS], 3945, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) +@use_tempdirs class GearTestCase1(unittest.TestCase): # this is the large single aisle 1 V3 test case def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "payload", GearMass(aviary_options=get_option_defaults()), promotes=["*"] - ) + self.prob.model.add_subsystem('gear_mass', GearMass(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Mission.Design.GROSS_MASS, val=175400, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.AVG_DIAMETER, val=7.35, units="ft" + Aircraft.Nacelle.AVG_DIAMETER, val=7.35, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.MOUNTING_TYPE, val=0, units="unitless") + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, val=0, units='unitless' + ) + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -889,35 +847,35 @@ def test_case1(self): self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.35, tol ) # bug fixed value and original value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-11, rtol=1e-12) +@use_tempdirs class GearTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() self.prob = om.Problem() - self.prob.model.add_subsystem( - "payload", GearMass(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('gear_mass', GearMass(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Mission.Design.GROSS_MASS, val=175400, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.MOUNTING_TYPE, val=0.1, units="unitless") + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, val=0.1, units='unitless' + ) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -928,10 +886,11 @@ def test_case1(self): self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 5963.6, tol ) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) +@use_tempdirs class GearTestCaseMultiengine(unittest.TestCase): def test_case1(self): options = get_option_defaults() @@ -940,9 +899,9 @@ def test_case1(self): self.prob = om.Problem() self.prob.model.add_subsystem( - "gear_mass", - GearMass(aviary_options=options), - promotes=["*"], + 'gear_mass', + GearMass(), + promotes=['*'], ) self.prob.model.set_input_defaults( @@ -951,6 +910,13 @@ def test_case1(self): self.prob.model.set_input_defaults( Aircraft.Nacelle.AVG_DIAMETER, val=[7.5, 8.22], units='ft' ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04) + self.prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85 + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=152000) + + self.prob.model_options['*'] = extract_options(options) self.prob.setup(check=False, force_alloc_complex=True) @@ -961,193 +927,201 @@ def test_case1(self): self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 5614.3311546, tol ) # bug fixed value and original value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) # this is the large single aisle 1 V3 test case +@use_tempdirs class FixedMassGroupTestCase1(unittest.TestCase): def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") # bug fixed value and original value + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') + options.set_val( + Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm' + ) # bug fixed value and original value + options.set_val(Settings.VERBOSITY, 0) + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14) self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - FixedMassGroup( - aviary_options=options, - ), - promotes=["*"], + 'group', + FixedMassGroup(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=118.8, units="ft" + Aircraft.Wing.SPAN, val=118.8, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Mission.Design.GROSS_MASS, val=175400, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "min_dive_vel", val=420, units="kn" + 'min_dive_vel', val=420, units='kn' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1392.1, units="ft**2" + Aircraft.Wing.AREA, val=1392.1, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SWEEP, val=25, units="deg" + Aircraft.Wing.SWEEP, val=25, units='deg' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" + Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "max_mach", val=0.9, units="unitless" + 'max_mach', val=0.9, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" + Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm' ) # bug fixed value and original value - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units="rad" + Aircraft.VerticalTail.SWEEP, val=0, units='rad' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SPAN, val=28.22, units="ft" + Aircraft.VerticalTail.SPAN, val=28.22, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Fuselage.LENGTH, val=129.4, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.SPAN, val=42.59, units="ft" + Aircraft.HorizontalTail.SPAN, val=42.59, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=381.8, units="ft**2" + Aircraft.HorizontalTail.AREA, val=381.8, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_ARM, val=55.1, units="ft" + Aircraft.HorizontalTail.MOMENT_ARM, val=55.1, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ROOT_CHORD, val=13.261162230765065, units="ft" + Aircraft.HorizontalTail.ROOT_CHORD, val=13.261162230765065, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=476.8, units="ft**2" + Aircraft.VerticalTail.AREA, val=476.8, units='ft**2' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_ARM, val=50.3, units="ft" + Aircraft.VerticalTail.MOMENT_ARM, val=50.3, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ROOT_CHORD, val=18.762708015981357, units="ft" + Aircraft.VerticalTail.ROOT_CHORD, val=18.762708015981357, units='ft' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.966, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.966, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.951, units="unitless" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.951, units='unitless' ) # bug fixed value self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless" + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units="lbm" + Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.AVG_DIAMETER, val=7.35, units="ft" + Aircraft.Nacelle.AVG_DIAMETER, val=7.35, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500, units="lbf" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500, units='lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.SURFACE_AREA, val=339.58, units="ft**2" + Aircraft.Nacelle.SURFACE_AREA, val=339.58, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Engine.MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" - ) # bug fixed value and original value - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) # bug fixed value and original value + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128) + self.prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.CENTER_CHORD, val=17.48974) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 @@ -1158,36 +1132,29 @@ def test_case1(self): assert_near_equal( self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2203729275531838, tol ) # bug fixed value - assert_near_equal( - self.prob["c_strut_braced"], 1, tol - ) # bug fixed value and original value - assert_near_equal( - self.prob["c_gear_loc"], 1, tol - ) # bug fixed value and original value + assert_near_equal(self.prob['c_strut_braced'], 1, tol) # bug fixed value and original value + assert_near_equal(self.prob['c_gear_loc'], 1, tol) # bug fixed value and original value assert_near_equal( self.prob[Aircraft.Engine.POSITION_FACTOR], 0.95, tol ) # bug fixed value and original value assert_near_equal( - self.prob["half_sweep"], 0.3947081519145335, tol + self.prob['half_sweep'], 0.3947081519145335, tol ) # bug fixed value and original value assert_near_equal( self.prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 36000, tol ) # bug fixed value and original value assert_near_equal( - self.prob["payload_mass_des"], 36000, tol + self.prob['payload_mass_des'], 36000, tol ) # bug fixed value and original value assert_near_equal( - self.prob["payload_mass_max"], 46040, tol + self.prob['payload_mass_max'], 46040, tol ) # bug fixed value and original value - assert_near_equal( - self.prob["tail.loc_MAC_vtail"], 0.44959578484694906, tol - ) # bug fixed value + assert_near_equal(self.prob['loc_MAC_vtail'], 0.44959578484694906, tol) # bug fixed value # bug fixed value assert_near_equal(self.prob[Aircraft.HorizontalTail.MASS], 2285, tol) - assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], - 2312, tol) # bug fixed value + assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], 2312, tol) # bug fixed value # bug fixed value assert_near_equal(self.prob[Aircraft.Wing.HIGH_LIFT_MASS], 4082.1, tol) @@ -1205,294 +1172,293 @@ def test_case1(self): self.prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 3785, tol ) # bug fixed value and original value assert_near_equal( - self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol + self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol ) # bug fixed value and original value assert_near_equal( - self.prob["eng_comb_mass"], 14370.8, tol + self.prob['eng_comb_mass'], 14370.8, tol ) # bug fixed value and original value assert_near_equal( - self.prob["wing_mounted_mass"], 24446.343040697346, tol + self.prob['wing_mounted_mass'], 24446.343040697346, tol ) # bug fixed value and original value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-11, rtol=1e-12) +@use_tempdirs class FixedMassGroupTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, val=2, units='unitless') options.set_val(Aircraft.Engine.HAS_PROPELLERS, val=[True], units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") # bug fixed value and original value + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=False, units='unitless') + options.set_val( + Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm' + ) # bug fixed value and original value + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14) + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - FixedMassGroup( - aviary_options=options, - ), - promotes=["*"], + 'group', + FixedMassGroup(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.Wing.SPAN, val=117.8, units="ft" + Aircraft.Wing.SPAN, val=117.8, units='ft' ) # original GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.MOUNTING_TYPE, val=.1, units="unitless") + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, val=0.1, units='unitless' + ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Mission.Design.GROSS_MASS, val=175400, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "min_dive_vel", val=420, units="kn" + 'min_dive_vel', val=420, units='kn' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=1370.3, units="ft**2" + Aircraft.Wing.AREA, val=1370.3, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SWEEP, val=25, units="deg" + Aircraft.Wing.SWEEP, val=25, units='deg' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" + Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "max_mach", val=0.72, units="unitless" + 'max_mach', val=0.72, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=10/117.8, units='unitless' + Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, val=10 / 117.8, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" + Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0.1, units="rad" + Aircraft.VerticalTail.SWEEP, val=0.1, units='rad' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SPAN, val=28, units="ft" + Aircraft.VerticalTail.SPAN, val=28, units='ft' ) # original GASP value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Fuselage.LENGTH, val=129.4, units="ft" + Aircraft.Fuselage.LENGTH, val=129.4, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.SPAN, val=42.25, units="ft" + Aircraft.HorizontalTail.SPAN, val=42.25, units='ft' ) # original GASP value self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.AREA, val=375.9, units="ft**2" + Aircraft.HorizontalTail.AREA, val=375.9, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_ARM, val=54.7, units="ft" + Aircraft.HorizontalTail.MOMENT_ARM, val=54.7, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ROOT_CHORD, val=13.16130387591471, units="ft" + Aircraft.HorizontalTail.ROOT_CHORD, val=13.16130387591471, units='ft' ) # original GASP value self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.AREA, val=469.3, units="ft**2" + Aircraft.VerticalTail.AREA, val=469.3, units='ft**2' ) # original GASP value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_ARM, val=49.9, units="ft" + Aircraft.VerticalTail.MOMENT_ARM, val=49.9, units='ft' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ROOT_CHORD, val=18.61267549773935, units="ft" + Aircraft.VerticalTail.ROOT_CHORD, val=18.61267549773935, units='ft' ) # original GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless" + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units="lbm" + Aircraft.Controls.CONTROL_MASS_INCREMENT, val=0, units='lbm' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "augmentation.motor_power", val=200, units="kW" + 'motor_power', val=200, units='kW' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.motor_voltage", val=50, units="V" + 'motor_voltage', val=50, units='V' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.max_amp_per_wire", val=50, units="A" + 'max_amp_per_wire', val=50, units='A' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.safety_factor", val=1.33, units="unitless" + 'safety_factor', val=1.33, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Electrical.HYBRID_CABLE_LENGTH, val=200, units="ft" + Aircraft.Electrical.HYBRID_CABLE_LENGTH, val=200, units='ft' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.wire_area", val=0.0015, units="ft**2" + 'wire_area', val=0.0015, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.rho_wire", val=1, units="lbm/ft**3" + 'rho_wire', val=1, units='lbm/ft**3' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.battery_energy", val=1, units="MJ" + 'battery_energy', val=1, units='MJ' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.motor_eff", val=1, units="unitless" + 'motor_eff', val=1, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.inverter_eff", val=1, units="unitless" + 'inverter_eff', val=1, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.transmission_eff", val=1, units="unitless" + 'transmission_eff', val=1, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.battery_eff", val=1, units="unitless" + 'battery_eff', val=1, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.rho_battery", val=200, units="kW*h/kg" + 'rho_battery', val=200, units='kW*h/kg' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.motor_spec_mass", val=10, units="hp/lbm" + 'motor_spec_mass', val=10, units='hp/lbm' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.inverter_spec_mass", val=10, units="kW/kg" + 'inverter_spec_mass', val=10, units='kW/kg' ) # not actual GASP value self.prob.model.set_input_defaults( - "augmentation.TMS_spec_mass", val=0.125, units="lbm/kW" + 'TMS_spec_mass', val=0.125, units='lbm/kW' ) # electrified diff configuration value v3.6 self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500, units="lbf" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500, units='lbf' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Nacelle.SURFACE_AREA, val=339.58, units="ft**2" + Aircraft.Nacelle.SURFACE_AREA, val=339.58, units='ft**2' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" - ) # bug fixed value and original value - self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless" + Aircraft.Engine.MASS_SCALER, val=1, units='unitless' ) # bug fixed value and original value # self.prob.model.set_input_defaults( - # Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless" + # Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' # ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) # bug fixed value and original value self.prob.model.set_input_defaults( - "engine.prop_mass", val=0, units="lbm" + 'prop_mass', val=0, units='lbm' ) # bug fixed value and original value + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128) + self.prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.CENTER_CHORD, val=17.48974) + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 assert_near_equal( self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 5963.6, tol ) # not actual GASP value - assert_near_equal( - self.prob["aug_mass"], 228.51036478, tol - ) # not actual GASP value + assert_near_equal(self.prob['aug_mass'], 228.51036478, tol) # not actual GASP value - assert_near_equal( - self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2213063198183813, tol) - assert_near_equal( - self.prob["c_strut_braced"], 0.9928, tol - ) # not actual GASP value - assert_near_equal(self.prob["c_gear_loc"], 1, tol) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.2213063198183813, tol) + assert_near_equal(self.prob['c_strut_braced'], 0.9928, tol) # not actual GASP value + assert_near_equal(self.prob['c_gear_loc'], 1, tol) # not actual GASP value # not actual GASP value assert_near_equal(self.prob[Aircraft.Engine.POSITION_FACTOR], 1, tol) assert_near_equal( - self.prob["half_sweep"], 0.3947081519145335, tol + self.prob['half_sweep'], 0.3947081519145335, tol ) # bug fixed and original value assert_near_equal( self.prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 36000, tol ) # bug fixed and original value - assert_near_equal( - self.prob["payload_mass_des"], 36000, tol - ) # bug fixed and original value - assert_near_equal( - self.prob["payload_mass_max"], 46040, tol - ) # bug fixed and original value + assert_near_equal(self.prob['payload_mass_des'], 36000, tol) # bug fixed and original value + assert_near_equal(self.prob['payload_mass_max'], 46040, tol) # bug fixed and original value - assert_near_equal( - self.prob["tail.loc_MAC_vtail"], 1.799, tol - ) # not actual GASP value + assert_near_equal(self.prob['loc_MAC_vtail'], 1.799, tol) # not actual GASP value # original GASP value assert_near_equal(self.prob[Aircraft.HorizontalTail.MASS], 2275, tol) - assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], - 2297, tol) # original GASP value + assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], 2297, tol) # original GASP value # original GASP value assert_near_equal(self.prob[Aircraft.Wing.HIGH_LIFT_MASS], 4162.1, tol) @@ -1510,35 +1476,39 @@ def test_case1(self): self.prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 3785, tol ) # bug fixed and original value assert_near_equal( - self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol - ) # bug fixed and original value - assert_near_equal( - self.prob["eng_comb_mass"], 14599.28196478, tol - ) # not actual GASP value - assert_near_equal( - self.prob["wing_mounted_mass"], 24027.6, tol - ) # not actual GASP value - assert_near_equal( - self.prob["engine.prop_mass_all"], 0, tol + self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol ) # bug fixed and original value + assert_near_equal(self.prob['eng_comb_mass'], 14599.28196478, tol) # not actual GASP value + assert_near_equal(self.prob['wing_mounted_mass'], 24027.6, tol) # not actual GASP value + assert_near_equal(self.prob['prop_mass_all'], 0, tol) # bug fixed and original value partial_data = self.prob.check_partials( - out_stream=None, method="cs", form="central", + out_stream=None, + method='cs', + form='central', ) assert_check_partials(partial_data, atol=3e-10, rtol=1e-12) +@use_tempdirs class FixedMassGroupTestCase3(unittest.TestCase): # Tests partials calculations in FixedMassGroup using as complete code coverage as possible. def _run_case(self, data): - prob = om.Problem() prob.model.add_subsystem( 'fixed_mass', - FixedMassGroup(aviary_options=data), + FixedMassGroup(), promotes=['*'], ) + + setup_model_options(prob, data) + + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' + ) + prob.setup(force_alloc_complex=True) for key in get_keys(data): @@ -1563,97 +1533,107 @@ def setUp(self): def tearDown(self): import aviary.subsystems.mass.gasp_based.fixed as fixed + constants.GRAV_ENGLISH_LBM = 1.0 fixed.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): - - data = AviaryValues({ - Aircraft.Engine.NUM_ENGINES: ([2], 'unitless'), - Aircraft.Propulsion.TOTAL_NUM_ENGINES: (2, 'unitless'), - Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES: (False, 'unitless'), - Aircraft.Engine.NUM_FUSELAGE_ENGINES: (0, 'unitless'), - Aircraft.CrewPayload.NUM_PASSENGERS: (150, 'unitless'), - Aircraft.Electrical.HAS_HYBRID_SYSTEM: (False, 'unitless'), - Aircraft.Engine.HAS_PROPELLERS: ([False], 'unitless'), - Aircraft.Wing.FLAP_TYPE: ('plain', 'unitless'), - Aircraft.Wing.SWEEP: (30.0, 'deg'), - Aircraft.Wing.MOUNTING_TYPE: (0, 'unitless'), - Aircraft.Wing.TAPER_RATIO: (0.25, 'unitless'), - Aircraft.Wing.ASPECT_RATIO: (11.0, 'unitless'), - Aircraft.Wing.SPAN: (100.0, 'ft'), - 'max_mach': (0.9, 'unitless'), - Aircraft.Strut.ATTACHMENT_LOCATION: (10.0, 'ft'), - Aircraft.LandingGear.MAIN_GEAR_LOCATION: (0.2, 'unitless'), - Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS: (200.0, 'lbm'), - Aircraft.CrewPayload.CARGO_MASS: (10040.0, 'lbm'), - 'wire_area': (0.0015, 'ft**2'), - 'rho_wire': (1.1, 'lbm/ft**3'), - 'battery_energy': (0.0, 'MJ'), - 'motor_eff': (1.5, 'unitless'), - 'inverter_eff': (0.95, 'unitless'), - 'transmission_eff': (0.96, 'unitless'), - 'battery_eff': (0.97, 'unitless'), - 'rho_battery': (210.0, 'MJ/lb'), - 'motor_spec_mass': (10.0, 'hp/lbm'), - 'inverter_spec_mass': (10.5, 'kW/lbm'), - 'TMS_spec_mass': (10.6, 'lbm/kW'), - Aircraft.Engine.MASS_SPECIFIC: (0.21366, 'lbm/lbf'), - Aircraft.Engine.SCALED_SLS_THRUST: (4000.0, 'lbf'), - Aircraft.Nacelle.MASS_SPECIFIC: (3.0, 'lbm/ft**2'), - Aircraft.Nacelle.SURFACE_AREA: (5.0, 'ft**2'), - Aircraft.Engine.PYLON_FACTOR: (1.25, 'unitless'), - Aircraft.Engine.ADDITIONAL_MASS_FRACTION: (0.14, 'unitless'), - Aircraft.Engine.MASS_SCALER: (1.05, 'unitless'), - Aircraft.Propulsion.MISC_MASS_SCALER: (1.06, 'unitless'), - Aircraft.Engine.WING_LOCATIONS: (0.35, 'unitless'), - 'prop_mass': (0.5, 'lbm'), - Aircraft.VerticalTail.TAPER_RATIO: (0.26, 'unitless'), - Aircraft.VerticalTail.ASPECT_RATIO: (5.0, 'unitless'), - Aircraft.VerticalTail.SWEEP: (25.0, 'deg'), - Aircraft.VerticalTail.SPAN: (20.0, 'ft'), - Mission.Design.GROSS_MASS: (152000.0, 'lbm'), - Aircraft.HorizontalTail.MASS_COEFFICIENT: (1.07, 'unitless'), - Aircraft.Fuselage.LENGTH: (120.0, 'ft'), - Aircraft.HorizontalTail.SPAN: (14.0, 'ft'), - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER: (1.08, 'unitless'), - Aircraft.HorizontalTail.TAPER_RATIO: (0.35, 'unitless'), - Aircraft.VerticalTail.MASS_COEFFICIENT: (1.09, 'unitless'), - Aircraft.HorizontalTail.AREA: (500.0, 'ft**2'), - 'min_dive_vel': (200.0, 'kn'), - Aircraft.HorizontalTail.MOMENT_ARM: (20.0, 'ft'), - Aircraft.HorizontalTail.THICKNESS_TO_CHORD: (0.15, 'unitless'), - Aircraft.HorizontalTail.ROOT_CHORD: (8.0, 'ft'), - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION: (0.3, 'unitless'), - Aircraft.VerticalTail.AREA: (250.0, 'ft**2'), - Aircraft.VerticalTail.MOMENT_ARM: (6.0, 'ft'), - Aircraft.VerticalTail.THICKNESS_TO_CHORD: (0.12, 'unitless'), - Aircraft.VerticalTail.ROOT_CHORD: (7.0, 'ft'), - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT: (1.10, 'unitless'), - Aircraft.Wing.AREA: (3500.0, 'ft**2'), - Aircraft.Wing.NUM_FLAP_SEGMENTS: (2, 'unitless'), - Aircraft.Wing.SLAT_CHORD_RATIO: (0.15, 'unitless'), - Aircraft.Wing.FLAP_CHORD_RATIO: (0.3, 'unitless'), - Aircraft.Wing.SLAT_SPAN_RATIO: (0.9, 'unitless'), - Aircraft.Wing.FLAP_SPAN_RATIO: (0.65, 'unitless'), - Aircraft.Wing.LOADING: (128.0, 'lbf/ft**2'), - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT: (0.15, 'unitless'), - Aircraft.Fuselage.AVG_DIAMETER: (11.0, 'ft'), - Aircraft.Wing.CENTER_CHORD: (17.0, 'ft'), - Mission.Landing.LIFT_COEFFICIENT_MAX: (1.8, 'unitless'), - 'density': (RHO_SEA_LEVEL_ENGLISH, 'slug/ft**3'), - Aircraft.Wing.ULTIMATE_LOAD_FACTOR: (7.0, 'unitless'), - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT: (1.11, 'unitless'), - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS: (200.0, 'lbm'), - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER: (1.12, 'unitless'), - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER: (1.13, 'unitless'), - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER: (1.14, 'unitless'), - Aircraft.Controls.CONTROL_MASS_INCREMENT: (25.0, 'lbm'), - Aircraft.LandingGear.MASS_COEFFICIENT: (1.15, 'unitless'), - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT: (1.16, 'unitless'), - Aircraft.Nacelle.CLEARANCE_RATIO: (0.2, 'unitless'), - Aircraft.Nacelle.AVG_DIAMETER: (7.5, 'ft'), - }) + data = AviaryValues( + { + Aircraft.Engine.NUM_ENGINES: (np.array([2]), 'unitless'), + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES: (2, 'unitless'), + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES: (False, 'unitless'), + Aircraft.Engine.NUM_FUSELAGE_ENGINES: (np.array([0]), 'unitless'), + Aircraft.CrewPayload.NUM_PASSENGERS: (150, 'unitless'), + Aircraft.CrewPayload.Design.NUM_PASSENGERS: (150, 'unitless'), + Aircraft.Electrical.HAS_HYBRID_SYSTEM: (False, 'unitless'), + Aircraft.Engine.HAS_PROPELLERS: ([False], 'unitless'), + Aircraft.Wing.FLAP_TYPE: ('plain', 'unitless'), + Aircraft.Wing.SWEEP: (30.0, 'deg'), + Aircraft.Wing.VERTICAL_MOUNT_LOCATION: (0, 'unitless'), + Aircraft.Wing.TAPER_RATIO: (0.25, 'unitless'), + Aircraft.Wing.ASPECT_RATIO: (11.0, 'unitless'), + Aircraft.Wing.SPAN: (100.0, 'ft'), + 'max_mach': (0.9, 'unitless'), + Aircraft.Strut.ATTACHMENT_LOCATION: (10.0, 'ft'), + Aircraft.LandingGear.MAIN_GEAR_LOCATION: (0.2, 'unitless'), + Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS: (200.0, 'lbm'), + Aircraft.CrewPayload.CARGO_MASS: (0.0, 'lbm'), + Aircraft.CrewPayload.Design.MAX_CARGO_MASS: (10040.0, 'lbm'), + 'wire_area': (0.0015, 'ft**2'), + 'rho_wire': (1.1, 'lbm/ft**3'), + 'battery_energy': (0.0, 'MJ'), + 'motor_eff': (1.5, 'unitless'), + 'inverter_eff': (0.95, 'unitless'), + 'transmission_eff': (0.96, 'unitless'), + 'battery_eff': (0.97, 'unitless'), + 'rho_battery': (210.0, 'MJ/lb'), + 'motor_spec_mass': (10.0, 'hp/lbm'), + 'inverter_spec_mass': (10.5, 'kW/lbm'), + 'TMS_spec_mass': (10.6, 'lbm/kW'), + Aircraft.Engine.MASS_SPECIFIC: (np.array([0.21366]), 'lbm/lbf'), + Aircraft.Engine.SCALED_SLS_THRUST: (np.array([4000.0]), 'lbf'), + Aircraft.Nacelle.MASS_SPECIFIC: (3.0, 'lbm/ft**2'), + Aircraft.Nacelle.SURFACE_AREA: (5.0, 'ft**2'), + Aircraft.Engine.PYLON_FACTOR: (np.array([1.25]), 'unitless'), + Aircraft.Engine.ADDITIONAL_MASS_FRACTION: ( + np.array([0.14]), + 'unitless', + ), + Aircraft.Engine.MASS_SCALER: (np.array([1.05]), 'unitless'), + Aircraft.Propulsion.MISC_MASS_SCALER: (1.06, 'unitless'), + Aircraft.Engine.WING_LOCATIONS: (np.array([0.35]), 'unitless'), + 'prop_mass': (0.5, 'lbm'), + Aircraft.VerticalTail.TAPER_RATIO: (0.26, 'unitless'), + Aircraft.VerticalTail.ASPECT_RATIO: (5.0, 'unitless'), + Aircraft.VerticalTail.SWEEP: (25.0, 'deg'), + Aircraft.VerticalTail.SPAN: (20.0, 'ft'), + Mission.Design.GROSS_MASS: (152000.0, 'lbm'), + Aircraft.HorizontalTail.MASS_COEFFICIENT: (1.07, 'unitless'), + Aircraft.Fuselage.LENGTH: (120.0, 'ft'), + Aircraft.HorizontalTail.SPAN: (14.0, 'ft'), + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER: (1.08, 'unitless'), + Aircraft.HorizontalTail.TAPER_RATIO: (0.35, 'unitless'), + Aircraft.VerticalTail.MASS_COEFFICIENT: (1.09, 'unitless'), + Aircraft.HorizontalTail.AREA: (500.0, 'ft**2'), + 'min_dive_vel': (200.0, 'kn'), + Aircraft.HorizontalTail.MOMENT_ARM: (20.0, 'ft'), + Aircraft.HorizontalTail.THICKNESS_TO_CHORD: (0.15, 'unitless'), + Aircraft.HorizontalTail.ROOT_CHORD: (8.0, 'ft'), + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION: (0.3, 'unitless'), + Aircraft.VerticalTail.AREA: (250.0, 'ft**2'), + Aircraft.VerticalTail.MOMENT_ARM: (6.0, 'ft'), + Aircraft.VerticalTail.THICKNESS_TO_CHORD: (0.12, 'unitless'), + Aircraft.VerticalTail.ROOT_CHORD: (7.0, 'ft'), + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT: (1.10, 'unitless'), + Aircraft.Wing.AREA: (3500.0, 'ft**2'), + Aircraft.Wing.NUM_FLAP_SEGMENTS: (2, 'unitless'), + Aircraft.Wing.SLAT_CHORD_RATIO: (0.15, 'unitless'), + Aircraft.Wing.FLAP_CHORD_RATIO: (0.3, 'unitless'), + Aircraft.Wing.SLAT_SPAN_RATIO: (0.9, 'unitless'), + Aircraft.Wing.FLAP_SPAN_RATIO: (0.65, 'unitless'), + Aircraft.Design.WING_LOADING: (128.0, 'lbf/ft**2'), + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT: (0.15, 'unitless'), + Aircraft.Fuselage.AVG_DIAMETER: (11.0, 'ft'), + Aircraft.Wing.CENTER_CHORD: (17.0, 'ft'), + Mission.Landing.LIFT_COEFFICIENT_MAX: (1.8, 'unitless'), + 'density': (RHO_SEA_LEVEL_ENGLISH, 'slug/ft**3'), + Aircraft.Wing.ULTIMATE_LOAD_FACTOR: (7.0, 'unitless'), + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT: (1.11, 'unitless'), + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS: (200.0, 'lbm'), + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER: (1.12, 'unitless'), + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER: (1.13, 'unitless'), + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER: ( + 1.14, + 'unitless', + ), + Aircraft.Controls.CONTROL_MASS_INCREMENT: (25.0, 'lbm'), + Aircraft.LandingGear.MASS_COEFFICIENT: (1.15, 'unitless'), + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT: (1.16, 'unitless'), + Aircraft.Nacelle.CLEARANCE_RATIO: (0.2, 'unitless'), + Aircraft.Nacelle.AVG_DIAMETER: (7.5, 'ft'), + } + ) # Try to cover all if-then branches in fixed.py. for flap_type in ['split', 'single_slotted', 'fowler']: @@ -1663,26 +1643,481 @@ def test_case1(self): for fuse_mounted in [False, True]: for num_engines in [2, 4]: num_fuse_eng = num_engines if fuse_mounted else 0 - data.set_val( - Aircraft.Engine.NUM_FUSELAGE_ENGINES, num_fuse_eng) - data.set_val( - Aircraft.Engine.NUM_ENGINES, [num_engines]) - data.set_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, num_engines) - data.set_val( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, gear_loc) - data.set_val( - Aircraft.Wing.FLAP_TYPE, flap_type) - data.set_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, has_hybrid) - data.set_val( - Aircraft.Engine.HAS_PROPELLERS, [has_prop]) + data.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, num_fuse_eng) + data.set_val(Aircraft.Engine.NUM_ENGINES, [num_engines]) + data.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, num_engines) + data.set_val(Aircraft.LandingGear.MAIN_GEAR_LOCATION, gear_loc) + data.set_val(Aircraft.Wing.FLAP_TYPE, flap_type) + data.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, has_hybrid) + data.set_val(Aircraft.Engine.HAS_PROPELLERS, [has_prop]) self._run_case(data) -if __name__ == "__main__": +class BWBMassParametersTestCase(unittest.TestCase): + """GASP BWB model""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Settings.VERBOSITY, 0) + options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 2, units='unitless') + + prob = self.prob = om.Problem() + self.prob.model.add_subsystem( + 'parameters', + MassParameters(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501094, units='ft') + prob.model.set_input_defaults('max_mach', 0.9, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0, units='unitless') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.19461189, tol) + assert_near_equal(self.prob['c_strut_braced'], 1, tol) + assert_near_equal(self.prob['c_gear_loc'], 0.95, tol) + assert_near_equal(self.prob[Aircraft.Engine.POSITION_FACTOR], 1.05, tol) + assert_near_equal(self.prob['half_sweep'], 0.47984874, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BWBPayloadGroupTestCase(unittest.TestCase): + "GASP BWB model" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=225, units='lbm') + + self.prob = om.Problem() + self.prob.model.add_subsystem('payload', PayloadGroup(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, 0.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, 15000.0, units='lbm' + ) + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(self.prob[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(self.prob['payload_mass_des'], 33750.0, tol) + assert_near_equal(self.prob['payload_mass_max'], 48750.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BWBEngineTestCase(unittest.TestCase): + "GASP BWB model" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.04373) + + prob = self.prob = om.Problem() + self.prob.model.add_subsystem( + 'engine', + EngineMass(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Engine.MASS_SPECIFIC, 0.178884, units='lbm/lbf') + prob.model.set_input_defaults(Aircraft.Engine.SCALED_SLS_THRUST, 19580.1602, units='lbf') + prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, 2.5, units='lbm/ft**2') + prob.model.set_input_defaults( + Aircraft.Nacelle.SURFACE_AREA, 194.957186763, units='ft**2' + ) # 6.76*3.14159265*9.18 + prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, 1.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Propulsion.MISC_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.WING_LOCATIONS, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_MASS, 6630.0, units='lbm') + prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0, units='unitless') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 7005.15475443, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.MASS], 487.39296691, tol) + assert_near_equal(self.prob['pylon_mass'], 558.757916785, tol) + assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 2092.30176475, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 153.16770871, tol) + assert_near_equal(self.prob['eng_comb_mass'], 7311.49017184, tol) + assert_near_equal(self.prob['wing_mounted_mass'], 0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-9, rtol=1e-12) + + +class BWBTailTestCase(unittest.TestCase): + """GASP BWB model""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('tail', TailMass(), promotes=['*']) + + prob.model.set_input_defaults(Aircraft.VerticalTail.TAPER_RATIO, 0.366, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.ASPECT_RATIO, 1.705, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, 0.0, units='rad') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MASS_COEFFICIENT, 0.124, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults( + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, 1.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.TAPER_RATIO, 0.366, units='unitless') + prob.model.set_input_defaults( + Aircraft.VerticalTail.MASS_COEFFICIENT, 0.119, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501094, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults('min_dive_vel', 420, units='kn') + prob.model.set_input_defaults(Aircraft.HorizontalTail.MOMENT_ARM, 29.6907417, units='ft') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.1, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.ROOT_CHORD, 0.03836448, units='ft') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.11964286, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.MOMENT_ARM, 27.82191598, units='ft') + prob.model.set_input_defaults( + Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.1, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.VerticalTail.ROOT_CHORD, 14.58190052, units='ft') + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['loc_MAC_vtail'], 0.97683077, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.MASS], 1.02401953, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], 864.17404177, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +class BWBHighLiftTestCase(unittest.TestCase): + def setUp(self): + prob = self.prob = om.Problem() + + aviary_options = get_option_defaults() + aviary_options.set_val(Aircraft.Wing.FLAP_TYPE, val=4) + aviary_options.set_val(Aircraft.Wing.NUM_FLAP_SEGMENTS, val=2) + + prob.model.add_subsystem('HL', HighLiftMass(), promotes=['*']) + + prob.model.set_input_defaults( + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, 1.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85714286, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, 0.0001, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.2, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, 0.831687927, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_SPAN_RATIO, 0.61, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 70.0, units='lbf/ft**2') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501094, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.CENTER_CHORD, 22.97244452, units='ft') + prob.model.set_input_defaults( + Mission.Landing.LIFT_COEFFICIENT_MAX, 1.94034, units='unitless' + ) # 1.94034 is taken from .out file. In GASP, CLMAX is computed for different phases + + setup_model_options(self.prob, aviary_options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + + assert_near_equal(self.prob[Aircraft.Wing.HIGH_LIFT_MASS], 1068.88854499, tol) + assert_near_equal(self.prob['flap_mass'], 1068.46572125, tol) # WFLAP = 997.949249689 + assert_near_equal(self.prob['slat_mass'], 0.42282374, tol) # WLED + + partial_data = self.prob.check_partials( + out_stream=None, method='cs', show_only_incorrect=True + ) + assert_check_partials(partial_data, atol=5e-10, rtol=1e-12) + + +@use_tempdirs +class BWBControlMassTestCase(unittest.TestCase): + """GAST BWB model""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('control_mass', ControlMass(), promotes=['*']) + + prob.model.set_input_defaults( + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, 0.5, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85714286, units='ft**2') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults( + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.97744787, units='unitless' + ) + prob.model.set_input_defaults('min_dive_vel', 420, units='kn') + prob.model.set_input_defaults( + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, 16.5, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, 0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Controls.CONTROL_MASS_INCREMENT, 0, units='lbm') + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.SURFACE_CONTROL_MASS], 2045.5556421, tol) + assert_near_equal(self.prob[Aircraft.Controls.TOTAL_MASS], 2174.28611375, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +class BWBGearTestCase(unittest.TestCase): + """GASP BWB model""" + + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('gear_mass', GearMass(), promotes=['*']) + + self.prob.model.set_input_defaults( + Aircraft.LandingGear.MASS_COEFFICIENT, 0.0520, units='unitless' + ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, 0.85, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.CLEARANCE_RATIO, 0.2, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Nacelle.AVG_DIAMETER, 7.35163168, units='ft') + self.prob.model.set_input_defaults( + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless' + ) + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.LandingGear.TOTAL_MASS], 7800.0, tol) + assert_near_equal(self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6630.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=3e-11, rtol=1e-12) + + +class BWBFixedMassGroupTestCase1(unittest.TestCase): + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=225, units='lbm') + options.set_val(Settings.VERBOSITY, 0) + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.04373) + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'group', + FixedMassGroup(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501094, units='ft') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults('min_dive_vel', 420, units='kn') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85714286, units='ft**2') + + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30, units='deg') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults('max_mach', 0.9, units='unitless') + prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, 0, units='lbm') + prob.model.set_input_defaults( + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, 15000.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.VerticalTail.TAPER_RATIO, 0.366, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.ASPECT_RATIO, 1.705, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, 0.0, units='rad') + prob.model.set_input_defaults(Aircraft.VerticalTail.SPAN, 16.98084188, units='ft') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MASS_COEFFICIENT, 0.124, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.HorizontalTail.SPAN, 0.04467601, units='ft') + prob.model.set_input_defaults( + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.TAPER_RATIO, 0.366, units='unitless') + prob.model.set_input_defaults( + Aircraft.VerticalTail.MASS_COEFFICIENT, 0.119, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.00117064, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.MOMENT_ARM, 29.6907417, units='ft') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.1, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.HorizontalTail.ROOT_CHORD, 0.03836448, units='ft') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.11964286, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.MOMENT_ARM, 27.82191598, units='ft') + prob.model.set_input_defaults( + Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.1, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.VerticalTail.ROOT_CHORD, 14.58190052, units='ft') + prob.model.set_input_defaults( + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Mission.Landing.LIFT_COEFFICIENT_MAX, 1.94034, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, 0.5, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.77335889, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, 16.5, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, 0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Controls.CONTROL_MASS_INCREMENT, 0, units='lbm') + prob.model.set_input_defaults( + Aircraft.LandingGear.MASS_COEFFICIENT, 0.0520, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, 0.85, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Nacelle.CLEARANCE_RATIO, 0.2, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.AVG_DIAMETER, 7.35163168, units='ft') + prob.model.set_input_defaults(Aircraft.Engine.MASS_SPECIFIC, 0.178884, units='lbm/lbf') + prob.model.set_input_defaults(Aircraft.Engine.SCALED_SLS_THRUST, 19580.1602, units='lbf') + prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, 2.5, units='lbm/ft**2') + prob.model.set_input_defaults(Aircraft.Nacelle.SURFACE_AREA, 219.95229788, units='ft**2') + prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, 1.25, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, 1, units='unitless') + + prob.model.set_input_defaults(Aircraft.Engine.WING_LOCATIONS, 0.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0.0, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38) + prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, 0.0001) + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.2) + prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, 0.831687927) + prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 70.0) + prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165) + prob.model.set_input_defaults(Aircraft.Wing.CENTER_CHORD, 22.97244452) + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_SPAN_RATIO, 0.61, units='unitless') + + setup_model_options(self.prob, options) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.LandingGear.TOTAL_MASS], 7800.0, tol) + assert_near_equal(self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6630.0, tol) + assert_near_equal(self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.19461189, tol) + assert_near_equal(self.prob['c_strut_braced'], 1, tol) + assert_near_equal(self.prob['c_gear_loc'], 0.95, tol) + assert_near_equal(self.prob[Aircraft.Engine.POSITION_FACTOR], 0.95, tol) + assert_near_equal(self.prob['half_sweep'], 0.47984874, tol) + assert_near_equal(self.prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(self.prob['payload_mass_des'], 33750, tol) + assert_near_equal(self.prob['payload_mass_max'], 48750, tol) + assert_near_equal(self.prob['loc_MAC_vtail'], 0.97683077, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.MASS], 1.02401953, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], 864.17404177, tol) + assert_near_equal(self.prob[Aircraft.Wing.HIGH_LIFT_MASS], 1068.88854499, tol) + assert_near_equal(self.prob[Aircraft.Controls.TOTAL_MASS], 2114.98158947, tol) + assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 7005.15475443, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.MASS], 549.8807447, tol) + assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 2230.13208284, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 153.16770871, tol) + assert_near_equal(self.prob['pylon_mass'], 565.18529673, tol) + assert_near_equal(self.prob['eng_comb_mass'], 7311.49017184, tol) + assert_near_equal(self.prob['wing_mounted_mass'], 0.0, tol) + assert_near_equal(self.prob[Aircraft.Wing.SURFACE_CONTROL_MASS], 1986.25111783, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-9, rtol=1e-12) + + +if __name__ == '__main__': unittest.main() - # test = GearTestCaseMultiengine() - # test = EngineTestCaseMultiEngine() - # test.test_case_1() diff --git a/aviary/subsystems/mass/gasp_based/test/test_fuel.py b/aviary/subsystems/mass/gasp_based/test/test_fuel.py index 6953f8a20a..60be322bd1 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_fuel.py +++ b/aviary/subsystems/mass/gasp_based/test/test_fuel.py @@ -2,70 +2,70 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.subsystems.mass.gasp_based.fuel import (BodyTankCalculations, - FuelAndOEMOutputs, - FuelMass, FuelMassGroup, - FuelSysAndFullFuselageMass, - FuselageAndStructMass) +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.subsystems.mass.gasp_based.fuel import ( + BodyTankCalculations, + FuelAndOEMOutputs, + FuelMass, + FuelMassGroup, + FuelSysAndFullFuselageMass, + FuselageMass, + StructMass, + BWBFuselageMass, +) +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Mission +from aviary.variable_info.variables import Aircraft, Mission, Settings class BodyCalculationTestCase1(unittest.TestCase): - """this is the large single aisle 1 V3 test case""" + """this is the large single aisle 1 V3 test case.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "wing_calcs", BodyTankCalculations(aviary_options=get_option_defaults(), ), promotes=["*"] - ) + self.prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_DESIGN, val=857.480639944284, units="ft**3" + Aircraft.Fuel.WING_VOLUME_DESIGN, val=857.480639944284, units='ft**3' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=1114.006551379108, units="ft**3" + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=1114.006551379108, units='ft**3' ) - self.prob.model.set_input_defaults("fuel_mass_min", val=32853, units="lbm") + self.prob.model.set_input_defaults('fuel_mass_min', val=32853, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS_REQUIRED, val=42892.0, units="lbm") - self.prob.model.set_input_defaults("max_wingfuel_mass", val=55725.1, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=1114.0, units="ft**3" + Mission.Summary.FUEL_MASS_REQUIRED, val=42892.0, units='lbm' ) + self.prob.model.set_input_defaults('max_wingfuel_mass', val=55725.1, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" - ) - self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS, val=42893.1, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.OPERATING_MASS, val=96508, units="lbm" + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=1114.0, units='ft**3' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=42893.1, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.OPERATING_MASS, val=96508, units='lbm') self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 2e-4 assert_near_equal( self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol - ) # note: not in version 3 output, calulated by hand + ) # note: not in version 3 output, calculated by hand assert_near_equal( - self.prob["extra_fuel_volume"], 0, tol - ) # note: not in version 3 output, calulated by hand + self.prob['extra_fuel_volume'], 0.69314718, tol + ) # note: not in version 3 output, calculated by hand assert_near_equal( - self.prob["max_extra_fuel_mass"], 0, tol - ) # note: not in version 3 output, calulated by hand - assert_near_equal(self.prob["wingfuel_mass_min"], 32853.0, tol) + self.prob['max_extra_fuel_mass'], 34.67277748, tol + ) # note: not in version 3 output, calculated by hand + assert_near_equal(self.prob['wingfuel_mass_min'], 32818.32722252, tol) # note: Aircraft.Fuel.TOTAL_CAPACITY is calculated differently in V3, so it is not included here - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) @@ -73,190 +73,383 @@ class BodyCalculationTestCase2( unittest.TestCase ): # this is v 3.6 large single aisle 1 test case with wing loading of 150 psf and fuel margin of 10% def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "wing_calcs", BodyTankCalculations(aviary_options=get_option_defaults(), ), promotes=["*"] - ) + self.prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_DESIGN, val=989.2, units="ft**3") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=876.7, units="ft**3") - self.prob.model.set_input_defaults("fuel_mass_min", val=34942.7, units="lbm") - self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS_REQUIRED, val=44982.7, units="lbm") - self.prob.model.set_input_defaults("max_wingfuel_mass", val=43852.1, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=876.7, units="ft**3" + Aircraft.Fuel.WING_VOLUME_DESIGN, val=989.2, units='ft**3' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=876.7, units='ft**3' ) + self.prob.model.set_input_defaults('fuel_mass_min', val=34942.7, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS, val=44973.0, units="lbm") + Mission.Summary.FUEL_MASS_REQUIRED, val=44982.7, units='lbm' + ) + self.prob.model.set_input_defaults('max_wingfuel_mass', val=43852.1, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.OPERATING_MASS, val=94417, units="lbm" + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=876.7, units='ft**3' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=44973.0, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.OPERATING_MASS, val=94417, units='lbm') self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 3e-4 assert_near_equal(self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 1130.6, tol) - assert_near_equal(self.prob["extra_fuel_volume"], 112.5, tol) - assert_near_equal(self.prob["max_extra_fuel_mass"], 5628.9, tol) - assert_near_equal(self.prob["wingfuel_mass_min"], 29313.9, tol) + assert_near_equal(self.prob['extra_fuel_volume'], 112.5, tol) + assert_near_equal(self.prob['max_extra_fuel_mass'], 5628.9, tol) + assert_near_equal(self.prob['wingfuel_mass_min'], 29313.9, tol) assert_near_equal(self.prob[Aircraft.Fuel.TOTAL_CAPACITY], 46093.7, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class BodyCalculationTestCase3(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): self.prob = om.Problem() - self.prob.model.add_subsystem( - "wing_calcs", BodyTankCalculations(aviary_options=get_option_defaults(), ), promotes=["*"] - ) + self.prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_DESIGN, val=989.2, units="ft**3") + Aircraft.Fuel.WING_VOLUME_DESIGN, val=989.2, units='ft**3' + ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=876.7, units="ft**3") - self.prob.model.set_input_defaults("fuel_mass_min", val=34942.7, units="lbm") + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=876.7, units='ft**3' + ) + self.prob.model.set_input_defaults('fuel_mass_min', val=34942.7, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS_REQUIRED, val=44982.7, units="lbm") - self.prob.model.set_input_defaults("max_wingfuel_mass", val=43852.1, units="lbm") + Mission.Summary.FUEL_MASS_REQUIRED, val=44982.7, units='lbm' + ) + self.prob.model.set_input_defaults('max_wingfuel_mass', val=43852.1, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=876.7, units="ft**3") + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=876.7, units='ft**3' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=44973.0, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.OPERATING_MASS, val=94417, units='lbm') + + self.prob.setup(check=False, force_alloc_complex=True) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BodyCalculationTestCase4smooth(unittest.TestCase): + """ + this is the large single aisle 1 V3 test case. + It tests the case Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES = True. + """ + + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) + self.prob.model.wing_calcs.options[Settings.VERBOSITY] = Verbosity.QUIET + self.prob.model.wing_calcs.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] = True + self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") + Aircraft.Fuel.WING_VOLUME_DESIGN, val=857.480639944284, units='ft**3' + ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm") + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=1114.006551379108, units='ft**3' + ) + self.prob.model.set_input_defaults('fuel_mass_min', val=32853, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS, val=44973.0, units="lbm") + Mission.Summary.FUEL_MASS_REQUIRED, val=42892.0, units='lbm' + ) + self.prob.model.set_input_defaults('max_wingfuel_mass', val=55725.1, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.OPERATING_MASS, val=94417, units="lbm") + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=1114.0, units='ft**3' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=42893.1, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.OPERATING_MASS, val=96508, units='lbm') + self.prob.setup(check=False, force_alloc_complex=True) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + def test_case1(self): + self.prob.run_model() + + tol = 2e-4 + assert_near_equal( + self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol + ) # note: not in version 3 output, calculated by hand + assert_near_equal( + self.prob['extra_fuel_volume'], 0.69314718, tol + ) # note: not in version 3 output, calculated by hand + assert_near_equal( + self.prob['max_extra_fuel_mass'], 34.67277748, tol + ) # note: not in version 3 output, calculated by hand + assert_near_equal(self.prob['wingfuel_mass_min'], 32818.32722252, tol) + # note: Aircraft.Fuel.TOTAL_CAPACITY is calculated differently in V3, so it is not included here + + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -# this is the large single aisle 1 V3 test case -class FuelAndOEMTestCase(unittest.TestCase): +class BodyCalculationTestCase5(unittest.TestCase): + """ + This is the Advanced Tube and Wing V3.6 test case. + It tests the case Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES = True. + """ + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) + self.prob.model.wing_calcs.options[Settings.VERBOSITY] = Verbosity.QUIET + self.prob.model.wing_calcs.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] = False + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_VOLUME_DESIGN, val=661.583, units='ft**3' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=677.554, units='ft**3' + ) + self.prob.model.set_input_defaults('fuel_mass_min', val=14115.342, units='lbm') + self.prob.model.set_input_defaults( + Mission.Summary.FUEL_MASS_REQUIRED, val=30085.342, units='lbm' + ) + self.prob.model.set_input_defaults('max_wingfuel_mass', val=33892.8, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=677.554, units='ft**3' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=145388, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=30085.342, units='lbm') + self.prob.model.set_input_defaults( + Mission.Summary.OPERATING_MASS, val=84502.658, units='lbm' + ) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal( + self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol + ) # note: not in version 3 output, calulated by hand + assert_near_equal( + self.prob['extra_fuel_volume'], 0.0, tol + ) # note: not in version 3 output, calulated by hand + assert_near_equal( + self.prob['max_extra_fuel_mass'], 0.0, tol + ) # note: not in version 3 output, calulated by hand + assert_near_equal(self.prob['wingfuel_mass_min'], 14115.342, tol) + # note: Aircraft.Fuel.TOTAL_CAPACITY is calculated differently in V3, so it is not included here + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BodyCalculationTestCase6smooth(unittest.TestCase): + """ + This is the Advanced Tube and Wing V3.6 test case. + It tests the case Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES = True. + """ + + def setUp(self): self.prob = om.Problem() - self.prob.model.add_subsystem("wing_calcs", FuelAndOEMOutputs( - aviary_options=get_option_defaults(), ), promotes=["*"]) + self.prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) + self.prob.model.wing_calcs.options[Settings.VERBOSITY] = Verbosity.QUIET + self.prob.model.wing_calcs.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] = True self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") + Aircraft.Fuel.WING_VOLUME_DESIGN, val=661.583, units='ft**3' + ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=677.554, units='ft**3' ) + self.prob.model.set_input_defaults('fuel_mass_min', val=14115.342, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Propulsion.MASS, val=16129, units="lbm") + Mission.Summary.FUEL_MASS_REQUIRED, val=30085.342, units='lbm' + ) + self.prob.model.set_input_defaults('max_wingfuel_mass', val=33892.8, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=677.554, units='ft**3' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=145388, units='lbm') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=30085.342, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURE_MASS, val=50461.0, units="lbm") + Mission.Summary.OPERATING_MASS, val=84502.658, units='lbm' + ) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal( + self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol + ) # note: not in version 3 output, calulated by hand + assert_near_equal( + self.prob['extra_fuel_volume'], 0.69314626, tol + ) # note: not in version 3 output, calulated by hand + assert_near_equal( + self.prob['max_extra_fuel_mass'], 34.672731, tol + ) # note: not in version 3 output, calulated by hand + assert_near_equal(self.prob['wingfuel_mass_min'], 14080.669, tol) + # note: Aircraft.Fuel.TOTAL_CAPACITY is calculated differently in V3, so it is not included here + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BodyCalculationTestCase7smooth(unittest.TestCase): + """ + It tests the case Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES = True. + """ + + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) + self.prob.model.wing_calcs.options[Settings.VERBOSITY] = Verbosity.QUIET + self.prob.model.wing_calcs.options[Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES] = True + self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units="lbm") + Aircraft.Fuel.WING_VOLUME_DESIGN, val=615.03323815, units='ft**3' + ) self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units="lbm") + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, val=620.75516364, units='ft**3' + ) + self.prob.model.set_input_defaults('fuel_mass_min', val=11998.49344063, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS_REQUIRED, val=42892.0, units="lbm") + Mission.Summary.FUEL_MASS_REQUIRED, val=27968.49344063, units='lbm' + ) + self.prob.model.set_input_defaults('max_wingfuel_mass', val=31051.56633854, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 1114, units="ft**3" + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, val=620.75516364, units='ft**3' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=143100.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") + Mission.Summary.FUEL_MASS, val=26236.86063849, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Fuel.TOTAL_CAPACITY, val=55725.1, units="lbm") + Mission.Summary.OPERATING_MASS, val=84331.50655937, units='lbm' + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal( + self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol + ) # note: not in version 3 output, calulated by hand + assert_near_equal(self.prob['extra_fuel_volume'], 0.68385622, tol) + assert_near_equal(self.prob['max_extra_fuel_mass'], 34.20802285, tol) + assert_near_equal(self.prob['wingfuel_mass_min'], 11964.285, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +# this is the large single aisle 1 V3 test case +class FuelAndOEMTestCase(unittest.TestCase): + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('wing_calcs', FuelAndOEMOutputs(), promotes=['*']) + + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Propulsion.MASS, val=16129, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.STRUCTURE_MASS, val=50461.0, units='lbm') + self.prob.model.set_input_defaults( + Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Mission.Summary.FUEL_MASS_REQUIRED, val=42892.0, units='lbm' + ) + self.prob.model.set_input_defaults( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 1114, units='ft**3' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuel.TOTAL_CAPACITY, val=55725.1, units='lbm') + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): self.prob.run_model() tol = 2e-4 - assert_near_equal(self.prob["OEM_wingfuel_mass"], 78894, tol) - assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 857.480639944284, tol) - assert_near_equal(self.prob["OEM_fuel_vol"], 1577.160566039489, tol) - assert_near_equal(self.prob[Aircraft.Design.OPERATING_MASS], 96508.0, tol) + assert_near_equal(self.prob['OEM_wingfuel_mass'], 78894, tol) + assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 857.480639944284, tol) + assert_near_equal(self.prob['OEM_fuel_vol'], 1577.160566039489, tol) + assert_near_equal(self.prob[Mission.Summary.OPERATING_MASS], 96508.0, tol) - assert_near_equal(self.prob["payload_mass_max_fuel"], 23166.9, tol) - assert_near_equal(self.prob["volume_wingfuel_mass"], 55725.1, tol) - assert_near_equal(self.prob["max_wingfuel_mass"], 55725.1, tol) + assert_near_equal(self.prob['payload_mass_max_fuel'], 23166.9, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 55725.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 55725.1, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) class FuelAndOEMTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem("wing_calcs", FuelAndOEMOutputs( - aviary_options=get_option_defaults(), ), promotes=["*"] - ) - prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm") - prob.model.set_input_defaults( - Aircraft.Propulsion.MASS, val=16129, units="lbm") - prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Design.STRUCTURE_MASS, val=50461.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units="lbm") - prob.model.set_input_defaults( - Mission.Design.FUEL_MASS_REQUIRED, val=42892.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 1114, units="ft**3") - prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") + prob.model.add_subsystem('wing_calcs', FuelAndOEMOutputs(), promotes=['*']) + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + prob.model.set_input_defaults(Aircraft.Propulsion.MASS, val=16129, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.STRUCTURE_MASS, val=50461.0, units='lbm') prob.model.set_input_defaults( - Aircraft.Fuel.TOTAL_CAPACITY, val=55725.1, units="lbm") + Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units='lbm') + prob.model.set_input_defaults(Mission.Summary.FUEL_MASS_REQUIRED, val=42892.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 1114, units='ft**3') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuel.TOTAL_CAPACITY, val=55725.1, units='lbm') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) @@ -264,426 +457,470 @@ class FuelSysAndFullFusMassTestCase( unittest.TestCase ): # this is the large single aisle 1 V3 test case def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "sys_and_fus", FuelSysAndFullFuselageMass(aviary_options=get_option_defaults(), ), promotes=["*"] - ) + self.prob.model.add_subsystem('sys_and_fus', FuelSysAndFullFuselageMass(), promotes=['*']) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830.0, units='lbm') + self.prob.model.set_input_defaults('wing_mounted_mass', val=24446.343040697346, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS, val=15830.0, units="lbm") - self.prob.model.set_input_defaults( - "wing_mounted_mass", val=24446.343040697346, units="lbm" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=42893, units='lbm') + self.prob.model.set_input_defaults('wingfuel_mass_min', val=32853, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) ) - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS, val=42893, units="lbm") - self.prob.model.set_input_defaults("wingfuel_mass_min", val=32853, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal(self.prob["fus_mass_full"], 102270, tol) + assert_near_equal(self.prob['fus_mass_full'], 102270, tol) assert_near_equal(self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1759, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -class FuelSysAndFullFusMassTestCase(unittest.TestCase): - """ - Test mass-weight conversion - """ +class FuelSysAndFullFusMassTestCase2(unittest.TestCase): + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): self.prob = om.Problem() - self.prob.model.add_subsystem( - "sys_and_fus", FuelSysAndFullFuselageMass(aviary_options=get_option_defaults(), ), promotes=["*"] - ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS, val=15830.0, units="lbm") - self.prob.model.set_input_defaults( - "wing_mounted_mass", val=24446.343040697346, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") + self.prob.model.add_subsystem('sys_and_fus', FuelSysAndFullFuselageMass(), promotes=['*']) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830.0, units='lbm') + self.prob.model.set_input_defaults('wing_mounted_mass', val=24446.343040697346, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.FUEL_MASS, val=42893, units="lbm") - self.prob.model.set_input_defaults("wingfuel_mass_min", val=32853, units="lbm") + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, val=42893, units='lbm') + self.prob.model.set_input_defaults('wingfuel_mass_min', val=32853, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + self.prob.setup(check=False, force_alloc_complex=True) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) # this is the large single aisle 1 V3 test case -class FusAndStructMassTestCase(unittest.TestCase): +class FuselageMassTestCase1(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem( - "fus_and_struct", FuselageAndStructMass(aviary_options=get_option_defaults(), ), promotes=["*"] - ) + self.prob.model.add_subsystem('fuselage', FuselageMass(), promotes=['*']) - self.prob.model.set_input_defaults("fus_mass_full", val=102270, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless") + self.prob.model.set_input_defaults('fus_mass_full', val=102270, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, val=4000, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.TailBoom.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.TailBoom.LENGTH, val=129.4, units="ft" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) - self.prob.model.set_input_defaults("pylon_len", val=0, units="ft") - self.prob.model.set_input_defaults("min_dive_vel", val=420, units="kn") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults("MAT", val=0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS, val=2275, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS, val=2297, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless") self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units="lbm") + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' + ) + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50461.0, tol) assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18763, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=4e-12, rtol=1e-12) -class FusAndStructMassTestCase2(unittest.TestCase): +class FuselageMassTestCase2(unittest.TestCase): """ Test mass-weight conversion """ def setUp(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): self.prob = om.Problem() - self.prob.model.add_subsystem( - "fus_and_struct", FuselageAndStructMass(aviary_options=get_option_defaults(), ), promotes=["*"] - ) + self.prob.model.add_subsystem('fuselage', FuselageMass(), promotes=['*']) - self.prob.model.set_input_defaults("fus_mass_full", val=102270, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") + self.prob.model.set_input_defaults('fus_mass_full', val=102270, units='lbm') self.prob.model.set_input_defaults( - Aircraft.TailBoom.LENGTH, val=129.4, units="ft") - self.prob.model.set_input_defaults("pylon_len", val=0, units="ft") - self.prob.model.set_input_defaults("min_dive_vel", val=420, units="kn") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, val=4000, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.TailBoom.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults("MAT", val=0, units="lbm") + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830, units="lbm") + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' + ) + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') + + self.prob.setup(check=False, force_alloc_complex=True) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) + + +# this is the large single aisle 1 V3 test case +class StructMassTestCase1(unittest.TestCase): + def setUp(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('struct', StructMass(), promotes=['*']) + + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS, val=18763, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless") + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, val=2275, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS, val=2275, units="lbm") + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, val=2297, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS, val=2297, units="lbm") + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless") + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' + ) + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + + self.prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-4 + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50461.0, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=4e-12, rtol=1e-12) + + +class StructMassTestCase2(unittest.TestCase): + """ + Test mass-weight conversion + """ + + def setUp(self): + import aviary.subsystems.mass.gasp_based.fuel as fuel + + fuel.GRAV_ENGLISH_LBM = 1.1 + + def tearDown(self): + import aviary.subsystems.mass.gasp_based.fuel as fuel + + fuel.GRAV_ENGLISH_LBM = 1.0 + + def test_case1(self): + self.prob = om.Problem() + self.prob.model.add_subsystem('struct', StructMass(), promotes=['*']) + + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS, val=18763, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless") + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, val=2275, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, val=2297, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units="lbm") + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units="lbm") + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' + ) + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + self.prob.setup(check=False, force_alloc_complex=True) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) class FuelMassTestCase(unittest.TestCase): # this is the large single aisle 1 V3 test case def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("fuel", FuelMass( - aviary_options=get_option_defaults(), ), promotes=["*"]) + self.prob.model.add_subsystem('fuel', FuelMass(), promotes=['*']) + self.prob.model.set_input_defaults(Aircraft.Design.STRUCTURE_MASS, val=50461.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS, val=1759, units='lbm') + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults('eng_comb_mass', val=14370.8, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURE_MASS, val=50461.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS, val=1759, units="lbm") - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units='lbm' ) - self.prob.model.set_input_defaults("eng_comb_mass", val=14370.8, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units="lbm") - self.prob.model.set_input_defaults("payload_mass_des", val=36000, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") + Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units='lbm' + ) + self.prob.model.set_input_defaults('payload_mass_des', val=36000, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=36000, units="lbm" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) - self.prob.model.set_input_defaults("payload_mass_max", val=46040, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults('payload_mass_max', val=46040, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 1e-4 - assert_near_equal(self.prob[Mission.Design.FUEL_MASS], 42893, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS], 42893, tol) assert_near_equal(self.prob[Aircraft.Propulsion.MASS], 16129, tol) - assert_near_equal(self.prob[Mission.Design.FUEL_MASS_REQUIRED], 42892.0, tol) - assert_near_equal(self.prob["fuel_mass_min"], 32853, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 42892.0, tol) + assert_near_equal(self.prob['fuel_mass_min'], 32853, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class FuelMassTestCase2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.fuel as fuel + fuel.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem("fuel", FuelMass( - aviary_options=get_option_defaults(), ), promotes=["*"]) - prob.model.set_input_defaults( - Aircraft.Design.STRUCTURE_MASS, val=50461.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS, val=1759, units="lbm") + prob.model.add_subsystem('fuel', FuelMass(), promotes=['*']) + prob.model.set_input_defaults(Aircraft.Design.STRUCTURE_MASS, val=50461.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS, val=1759, units='lbm') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + prob.model.set_input_defaults('eng_comb_mass', val=14370.8, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895.0, units='lbm') prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm") - prob.model.set_input_defaults("eng_comb_mass", val=14370.8, units="lbm") - prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units="lbm") - prob.model.set_input_defaults("payload_mass_des", val=36000, units="lbm") - prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") + Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, val=4932.0, units='lbm') + prob.model.set_input_defaults('payload_mass_des', val=36000, units='lbm') prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=36000, units="lbm") - prob.model.set_input_defaults("payload_mass_max", val=46040, units="lbm") + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + prob.model.set_input_defaults('payload_mass_max', val=46040, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-11, rtol=1e-12) # this is the large single aisle 1 V3 test case class FuelMassGroupTestCase1(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("group", FuelMassGroup( - aviary_options=get_option_defaults(), ), promotes=["*"]) + self.prob.model.add_subsystem('group', FuelMassGroup(), promotes=['*']) # top level + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15830, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3895, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units="lbm") + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3895, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_USEFUL_LOAD, val=4932, units="lbm") + Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21089.0, units='lbm' + ) + self.prob.model.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, val=4932, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 1114.0, units="ft**3" + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 1114.0, units='ft**3' ) # sys and fus - self.prob.model.set_input_defaults( - "wing_mounted_mass", val=24446.343040697346, units="lbm" - ) + self.prob.model.set_input_defaults('wing_mounted_mass', val=24446.343040697346, units='lbm') # fus and struct self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, val=4000, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.TailBoom.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.TailBoom.LENGTH, val=129.4, units="ft" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' ) + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - "fus_and_struct.pylon_len", val=0, units="ft" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) - self.prob.model.set_input_defaults("min_dive_vel", val=420, units="kn") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults("fus_and_struct.MAT", val=0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless") + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, val=2275, units='lbm') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless") + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, val=2297, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS, val=2275, units="lbm") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless") + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units='lbm' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.TailBoom.LENGTH, val=129.4, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS, val=2297, units="lbm") + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' + ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' + ) + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless") + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, val=2275, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, val=2297, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units="lbm") + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units="lbm" + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) # fuel - self.prob.model.set_input_defaults("eng_comb_mass", val=14370.8, units="lbm") - self.prob.model.set_input_defaults("payload_mass_des", val=36000, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=36000, units="lbm" + self.prob.model.set_input_defaults('eng_comb_mass', val=14370.8, units='lbm') + self.prob.model.set_input_defaults('payload_mass_des', val=36000, units='lbm') + self.prob.model.set_input_defaults('payload_mass_max', val=46040, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) ) - self.prob.model.set_input_defaults("payload_mass_max", val=46040, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # wingfuel - assert_near_equal(self.prob["fuel_and_oem.OEM_wingfuel_mass"], 78894, tol) - assert_near_equal( - self.prob["fuel_and_oem.OEM_fuel_vol"], 1577.160566039489, tol - ) - assert_near_equal(self.prob[Aircraft.Design.OPERATING_MASS], 96508.0, tol) + assert_near_equal(self.prob['OEM_wingfuel_mass'], 78894, tol) + assert_near_equal(self.prob['OEM_fuel_vol'], 1577.160566039489, tol) + assert_near_equal(self.prob[Mission.Summary.OPERATING_MASS], 96508.0, tol) assert_near_equal( - self.prob["fuel_and_oem.payload_mass_max_fuel"], 36000, tol + self.prob['payload_mass_max_fuel'], 36000, tol ) # note: this is calculated differently in V3, so this is the V3.6 value - assert_near_equal(self.prob["fuel_and_oem.volume_wingfuel_mass"], 55725.1, tol) - assert_near_equal(self.prob["max_wingfuel_mass"], 55725.1, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 55725.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 55725.1, tol) # sys and fus - assert_near_equal(self.prob["fus_mass_full"], 102270, tol) + assert_near_equal(self.prob['fus_mass_full'], 102270, tol) assert_near_equal(self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1759, tol) # fus and struct @@ -691,24 +928,24 @@ def test_case1(self): assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18763, tol) # fuel - assert_near_equal(self.prob[Mission.Design.FUEL_MASS], 42893, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS], 42893, tol) assert_near_equal(self.prob[Aircraft.Propulsion.MASS], 16129, tol) - assert_near_equal(self.prob[Mission.Design.FUEL_MASS_REQUIRED], 42892.0, tol) - assert_near_equal(self.prob["fuel_mass_min"], 32853, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 42892.0, tol) + assert_near_equal(self.prob['fuel_mass_min'], 32853, tol) # body tank assert_near_equal( self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol - ) # note: not in version 3 output, calulated by hand + ) # note: not in version 3 output, calculated by hand assert_near_equal( - self.prob["body_tank.extra_fuel_volume"], 0, tol - ) # note: not in version 3 output, calulated by hand + self.prob['extra_fuel_volume'], 0.69314718, tol + ) # note: not in version 3 output, calculated by hand assert_near_equal( - self.prob["body_tank.max_extra_fuel_mass"], 0, tol - ) # note: not in version 3 output, calulated by hand + self.prob['max_extra_fuel_mass'], 34.67277748, tol + ) # note: not in version 3 output, calculated by hand # note: Aircraft.Fuel.TOTAL_CAPACITY is calculated differently in V3, so it is not included here - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-11, rtol=1e-12) @@ -716,112 +953,104 @@ class FuelMassGroupTestCase2( unittest.TestCase ): # this is v 3.6 large single aisle 1 test case with wing loading of 150 psf and fuel margin of 10% def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("group", FuelMassGroup( - aviary_options=get_option_defaults(), ), promotes=["*"]) + self.prob.model.add_subsystem('group', FuelMassGroup(), promotes=['*']) # top level + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=13833, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=13833, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3632, units="lbm") + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3632, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21031.0, units="lbm") + Aircraft.Design.FIXED_EQUIPMENT_MASS, val=21031.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_USEFUL_LOAD, val=4885.18, units="lbm") + Aircraft.Design.FIXED_USEFUL_LOAD, val=4885.18, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 876.7, units="ft**3" + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 876.7, units='ft**3' ) # sys and fus self.prob.model.set_input_defaults( - "wing_mounted_mass", val=24446.343040697346, units="lbm" + 'wing_mounted_mass', val=24446.343040697346, units='lbm' ) # note: calculated by hand # fus and struct self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA, val=4000, units="ft**2" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, val=4000, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.TailBoom.LENGTH, val=129.5, units="ft" + Aircraft.TailBoom.LENGTH, val=129.5, units='ft' ) # note: calculated by hand self.prob.model.set_input_defaults( - "fus_and_struct.pylon_len", val=0, units="ft" + 'pylon_len', val=0, units='ft' ) # note: calculated by hand - self.prob.model.set_input_defaults("min_dive_vel", val=420, units="kn") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.75, units="unitless") - self.prob.model.set_input_defaults("fus_and_struct.MAT", val=0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless") + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS, val=2181, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS, val=2158, units="lbm") + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' + ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.75, units='unitless' + ) + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless") + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, val=2181, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=7511, units="lbm") + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, val=2158, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=7511, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units="lbm") + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=3785, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units="lbm" + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) # fuel - self.prob.model.set_input_defaults("eng_comb_mass", val=14370.8, units="lbm") - self.prob.model.set_input_defaults("payload_mass_des", val=36000, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=36000, units="lbm" - ) - self.prob.model.set_input_defaults("payload_mass_max", val=46040, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=10, units="unitless" + self.prob.model.set_input_defaults('eng_comb_mass', val=14370.8, units='lbm') + self.prob.model.set_input_defaults('payload_mass_des', val=36000, units='lbm') + self.prob.model.set_input_defaults('payload_mass_max', val=46040, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=10, units='unitless') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # wingfuel - assert_near_equal(self.prob["fuel_and_oem.OEM_wingfuel_mass"], 80982.7, tol) - assert_near_equal(self.prob["fuel_and_oem.OEM_fuel_vol"], 1618.9, tol) - assert_near_equal(self.prob[Aircraft.Design.OPERATING_MASS], 94417.0, tol) - assert_near_equal(self.prob["fuel_and_oem.payload_mass_max_fuel"], 34879.2, tol) - assert_near_equal(self.prob["fuel_and_oem.volume_wingfuel_mass"], 43852.1, tol) - assert_near_equal(self.prob["max_wingfuel_mass"], 43852.1, tol) + assert_near_equal(self.prob['OEM_wingfuel_mass'], 80982.7, tol) + assert_near_equal(self.prob['OEM_fuel_vol'], 1618.9, tol) + assert_near_equal(self.prob[Mission.Summary.OPERATING_MASS], 94417.0, tol) + assert_near_equal(self.prob['payload_mass_max_fuel'], 34879.2, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 43852.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 43852.1, tol) # sys and fus assert_near_equal( - self.prob["fus_mass_full"], 107806.75695930266, tol + self.prob['fus_mass_full'], 107806.75695930266, tol ) # note: calculated by hand assert_near_equal(self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 2029, tol) @@ -832,132 +1061,145 @@ def test_case1(self): ) # tol is slightly higher because GASP iteration is less rigorous. # fuel - assert_near_equal(self.prob[Mission.Design.FUEL_MASS], 44982.7, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS], 44982.7, tol) assert_near_equal(self.prob[Aircraft.Propulsion.MASS], 16399.0, tol) - assert_near_equal(self.prob[Mission.Design.FUEL_MASS_REQUIRED], 44982.7, tol) - assert_near_equal(self.prob["fuel_mass_min"], 34942.7, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 44982.7, tol) + assert_near_equal(self.prob['fuel_mass_min'], 34942.7, tol) # body tank assert_near_equal( self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 1130.6, 0.0112 ) # tol is slightly higher because GASP iteration is less rigorous, and also because of numerical issues with inputs. assert_near_equal( - self.prob["body_tank.extra_fuel_volume"], 112.5, 0.0022 + self.prob['extra_fuel_volume'], 112.5, 0.0022 ) # tol is slightly higher because GASP iteration is less rigorous. assert_near_equal( - self.prob["body_tank.max_extra_fuel_mass"], 5628.9, 0.0025 + self.prob['max_extra_fuel_mass'], 5628.9, 0.0025 ) # tol is slightly higher because GASP iteration is less rigorous. - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-11, rtol=1e-12) -class FuelMassGroupTestCase3( - unittest.TestCase -): # this is v 3.6 advanced tube and wing case +class FuelMassGroupTestCase3(unittest.TestCase): # this is v 3.6 advanced tube and wing case def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("group", FuelMassGroup( - aviary_options=get_option_defaults(), ), promotes=["*"]) + self.prob.model.add_subsystem('group', FuelMassGroup(), promotes=['*']) # top level + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=145388.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS, val=15098.0, units='lbm') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=145388.0, units="lbm" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS, val=15098.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS") - self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=3765, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_EQUIPMENT_MASS, val=17201.0, units="lbm") + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=3765, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.FIXED_USEFUL_LOAD, val=4701, units="lbm") + Aircraft.Design.FIXED_EQUIPMENT_MASS, val=17201.0, units='lbm' + ) + self.prob.model.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, val=4701, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 677.6, units="ft**3" + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 677.6, units='ft**3' ) # sys and fus self.prob.model.set_input_defaults( - "wing_mounted_mass", val=17272.898624554255, units="lbm" + 'wing_mounted_mass', val=17272.898624554255, units='lbm' ) # note: calculated by hand # fus and struct self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, val=4209, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.TailBoom.LENGTH, val=119.03, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA, val=4209, units="ft**2" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units="ft") - self.prob.model.set_input_defaults( - Aircraft.TailBoom.LENGTH, val=119.03, units="ft" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=4.484, units='unitless' ) + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - "fus_and_struct.pylon_len", val=0, units="ft" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) - self.prob.model.set_input_defaults("min_dive_vel", val=420, units="kn") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, val=2018, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=4.484, units="unitless") - self.prob.model.set_input_defaults("fus_and_struct.MAT", val=0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless") + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, val=1500, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS, val=2018, units="lbm") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=6140, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless") + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=2795, units='lbm' + ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, val=13.1, units='ft') + self.prob.model.set_input_defaults(Aircraft.TailBoom.LENGTH, val=119.03, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('min_dive_vel', val=420, units='kn') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS, val=1500, units="lbm") + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' + ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=4.484, units='unitless' + ) + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless") + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, val=2018, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS, val=6140, units="lbm") + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, val=1500, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, val=6140, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=2795, units="lbm") + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, val=2795, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units="lbm" + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) # fuel - self.prob.model.set_input_defaults("eng_comb_mass", val=9328.2, units="lbm") - self.prob.model.set_input_defaults("payload_mass_des", val=30800, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, val=30800, units="lbm" - ) - self.prob.model.set_input_defaults("payload_mass_max", val=46770.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=10, units="unitless" + self.prob.model.set_input_defaults('eng_comb_mass', val=9328.2, units='lbm') + self.prob.model.set_input_defaults('payload_mass_des', val=30800, units='lbm') + self.prob.model.set_input_defaults('payload_mass_max', val=46770.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=10, units='unitless') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # wingfuel - assert_near_equal(self.prob["fuel_and_oem.OEM_wingfuel_mass"], 62427.2, tol) - assert_near_equal(self.prob["fuel_and_oem.OEM_fuel_vol"], 1248.0, tol) - assert_near_equal(self.prob[Aircraft.Design.OPERATING_MASS], 82961.0, tol) - assert_near_equal(self.prob["fuel_and_oem.volume_wingfuel_mass"], 33892.8, tol) - assert_near_equal(self.prob["max_wingfuel_mass"], 33892.8, tol) + assert_near_equal(self.prob['OEM_wingfuel_mass'], 62427.2, tol) + assert_near_equal(self.prob['OEM_fuel_vol'], 1248.0, tol) + assert_near_equal(self.prob[Mission.Summary.OPERATING_MASS], 82961.0, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 33892.8, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 33892.8, tol) # sys and fus assert_near_equal(self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1426, tol) @@ -967,18 +1209,372 @@ def test_case1(self): assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18988, tol) # fuel - assert_near_equal(self.prob[Mission.Design.FUEL_MASS], 31627.2, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS], 31627.2, tol) assert_near_equal(self.prob[Aircraft.Propulsion.MASS], 10755.0, tol) - assert_near_equal(self.prob[Mission.Design.FUEL_MASS_REQUIRED], 31627, tol) - assert_near_equal(self.prob["fuel_mass_min"], 15657.2, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 31627, tol) + assert_near_equal(self.prob['fuel_mass_min'], 15657.2, tol) # body tank assert_near_equal(self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol) - assert_near_equal(self.prob["body_tank.extra_fuel_volume"], 17.9, tol) + assert_near_equal(self.prob['extra_fuel_volume'], 17.9, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-9, rtol=6e-11) -if __name__ == "__main__": +class BWBFuelSysAndFullFusMassTestCase(unittest.TestCase): + """Using BWB data""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('sys_and_fus', FuelSysAndFullFuselageMass(), promotes=['*']) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.MASS, 7055.90333649, units='lbm') + prob.model.set_input_defaults('wing_mounted_mass', 0.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, 0.035, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, 6.687, units='lbm/galUS') + prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, 24229.3, units='lbm') + prob.model.set_input_defaults('wingfuel_mass_min', 9221.6, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, 10.0, units='unitless') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['fus_mass_full'], 133722.49666351, tol) + assert_near_equal(self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 932.82805, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BWBFuselageMassTestCase(unittest.TestCase): + """GASP data""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('fuselage', BWBFuselageMass(), promotes=['*']) + + prob.model.set_input_defaults(Aircraft.Fuselage.MASS_COEFFICIENT, 0.889, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL, 0.2, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA, 5.0, units='lbm/ft**2' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, 1283.5249, units='ft**2') + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 27159.69841266, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=4e-11, rtol=1e-12) + + +class BWBStructMassTestCase(unittest.TestCase): + """Using BWB data""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('struct', StructMass(), promotes=['*']) + + prob.model.set_input_defaults(Aircraft.Fuselage.MASS, 27159.69841266, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MASS, 7055.90333649, units='lbm') + prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, 1.02401953, units='lbm') + prob.model.set_input_defaults(Aircraft.VerticalTail.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, 864.17404177, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, 7800.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, 2230.13208284, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Design.STRUCTURAL_MASS_INCREMENT, 0.0, units='lbm') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 45110.93189329, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=4e-12, rtol=1e-12) + + +class BWBFuelMassTestCase(unittest.TestCase): + """Using BWB data""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('fuel', FuelMass(), promotes=['*']) + + prob.model.set_input_defaults(Aircraft.Design.STRUCTURE_MASS, 45110.93189329, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS, 932.82805, units='lbm') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults('eng_comb_mass', 6934.7, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, 2115.19946, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.FIXED_EQUIPMENT_MASS, 20876.477, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, 4156.795, units='lbm') + prob.model.set_input_defaults('payload_mass_des', 33750.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, 0.035, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, 6.687, units='lbm/galUS') + prob.model.set_input_defaults('payload_mass_max', 48750.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, 10.0, units='unitless') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS], 35682.13446963, tol) + assert_near_equal(self.prob[Aircraft.Propulsion.MASS], 7867.52805, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 36123.06859671, tol) + assert_near_equal(self.prob['fuel_mass_min'], 21123.06859671, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +class BWBFuelAndOEMTestCase(unittest.TestCase): + """Using BWB data""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('wing_calcs', FuelAndOEMOutputs(), promotes=['*']) + + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, 6.687, units='lbm/galUS') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Propulsion.MASS, 16161.21, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, 1942.3, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.STRUCTURE_MASS, 43566.079, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.FIXED_EQUIPMENT_MASS, 20876.477, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, 5736.3, units='lbm') + prob.model.set_input_defaults(Mission.Summary.FUEL_MASS_REQUIRED, 26652.3, units='lbm') + prob.model.set_input_defaults( + Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 605.90781747, units='ft**3' + ) + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuel.TOTAL_CAPACITY, 26652.3, units='lbm') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob['OEM_wingfuel_mass'], 61717.634, tol) + assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 586.08986, tol) + assert_near_equal(self.prob['OEM_fuel_vol'], 1233.80378225, tol) + assert_near_equal(self.prob[Mission.Summary.OPERATING_MASS], 88282.366, tol) + + assert_near_equal(self.prob['payload_mass_max_fuel'], 35065.334, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 30308.86876357, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 30308.86876357, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) + + +@use_tempdirs +class BWBBodyCalculationTest(unittest.TestCase): + """Using BWB data""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('wing_calcs', BodyTankCalculations(), promotes=['*']) + + prob.model.set_input_defaults(Aircraft.Fuel.WING_VOLUME_DESIGN, 532.8, units='ft**3') + prob.model.set_input_defaults( + Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, 1159.1, units='ft**3' + ) + prob.model.set_input_defaults('fuel_mass_min', 9229.6045, units='lbm') + prob.model.set_input_defaults(Mission.Summary.FUEL_MASS_REQUIRED, 26652.3, units='lbm') + prob.model.set_input_defaults('max_wingfuel_mass', 26646.849, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 532.7, units='ft**3') + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, 6.687, units='lbm/galUS') + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000.0, units='lbm') + prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, 24229.0, units='lbm') + prob.model.set_input_defaults(Mission.Summary.OPERATING_MASS, 79825.3, units='lbm') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Fuel.TOTAL_CAPACITY], 24234.451, tol) + assert_near_equal(self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 5.451, tol) + assert_near_equal(self.prob['extra_fuel_volume'], 0.69314718, tol) + assert_near_equal(self.prob['max_extra_fuel_mass'], 34.67277748, tol) + assert_near_equal(self.prob['wingfuel_mass_min'], 9194.93172252, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +@use_tempdirs +class BWBFuelMassGroupTest(unittest.TestCase): + """Using BWB data""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Engine.NUM_ENGINES, val=[2], units='unitless') + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem('group', FuelMassGroup(), promotes=['*']) + + # FuelSysAndFullFuselageMass + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.MASS, 6962.4, units='lbm') + prob.model.set_input_defaults('wing_mounted_mass', 0.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, 0.035, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, 6.687, units='lbm/galUS') + prob.model.set_input_defaults(Mission.Summary.FUEL_MASS, 33268.2, units='lbm') + # prob.model.set_input_defaults('wingfuel_mass_min', 0.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, 10.0, units='unitless') + + # BWBFuselageMass + prob.model.set_input_defaults(Aircraft.Fuselage.MASS_COEFFICIENT, 0.889, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA, 4573.8833, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL, 0.2, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA, 5.0, units='lbm/ft**2' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, 1283.5249, units='ft**2') + + # StructMass + # prob.model.set_input_defaults(Aircraft.Fuselage.MASS, 27159.7, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS, 1.0, units='lbm') + prob.model.set_input_defaults(Aircraft.VerticalTail.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.MASS, 790.1, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS, 7800.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, 2153.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Design.STRUCTURAL_MASS_INCREMENT, 0.0, units='lbm') + + # FuelMass + prob.model.set_input_defaults('eng_comb_mass', 7311.5, units='lbm') + prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, 2115, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.FIXED_EQUIPMENT_MASS, 20876, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.FIXED_USEFUL_LOAD, 5775, units='lbm') + prob.model.set_input_defaults('payload_mass_des', 33750.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, 0.035, units='unitless' + ) + prob.model.set_input_defaults('payload_mass_max', 48750.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, 10.0, units='unitless') + + # FuelAndOEMOutputs + prob.model.set_input_defaults(Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, 783.6, units='ft**3') + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + Testing GASP data case: + Aircraft.Fuel.FUEL_SYSTEM_MASS -- WFSS = 1281 + fus_mass_full -- 124040.19837521 -- WX = 121864 + Mission.Summary.OPERATING_MASS -- OWE = 82982. + fuel_and_oem.OEM_wingfuel_mass -- WFWOWE(WFW_MAX) = 67018.2 + fuel_and_oem.OEM_fuel_vol -- FVOLW_MAX = 1339.8 + fuel_and_oem.payload_mass_max_fuel -- WPLMXF = 30423.2 + max_wingfuel_mass -- WFWMX = 30309.0 + Aircraft.Design.STRUCTURE_MASS -- WST = 45623. + Aircraft.Fuselage.MASS -- WB = 27160. + Mission.Summary.FUEL_MASS -- WFADES = 33268.2 + Aircraft.Propulsion.MASS -- WP = 8592. + Mission.Summary.FUEL_MASS_REQUIRED -- WFAREQ = 36595.0 + fuel_mass_min -- WFAMIN = 18268.2 + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY -- 0.0 + Aircraft.Fuel.TOTAL_CAPACITY -- WFAMAX = 33268.2 + body_tank.extra_fuel_volume -- FVOLAUX = 0.2 + body_tank.max_extra_fuel_mass -- 0.0 + wingfuel_mass_min -- WFWMIN = 11982.2 + Note: can not match Aircraft.Fuel.FUEL_SYSTEM_MASS to GASP. Guess it is WFSS + """ + self.prob.run_model() + + tol = 1e-7 + + # sys and fus + assert_near_equal(self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1308.89996255, tol) + assert_near_equal(self.prob['fus_mass_full'], 124040.19837521, tol) + + # wingfuel + assert_near_equal(self.prob[Mission.Summary.OPERATING_MASS], 82252.59837521, tol) + assert_near_equal(self.prob['OEM_wingfuel_mass'], 67747.40162479, tol) + assert_near_equal(self.prob['OEM_fuel_vol'], 1354.34550784, tol) + assert_near_equal(self.prob['payload_mass_max_fuel'], 33750.0, tol) + # assert_near_equal(self.prob['volume_wingfuel_mass'], 26646.849, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 39197.43049744, tol) + + # fus and struct + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 44866.19841266, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 27159.69841266, tol) + + # fuel + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS], 33997.40162479, tol) + assert_near_equal(self.prob[Aircraft.Propulsion.MASS], 8620.39996255, tol) + assert_near_equal(self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 33997.40162479, tol) + assert_near_equal(self.prob['fuel_mass_min'], 18997.40162479, tol) + + # body tank + assert_near_equal(self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0.0, tol) + assert_near_equal(self.prob[Aircraft.Fuel.TOTAL_CAPACITY], 33997.40162479, tol) + assert_near_equal(self.prob['extra_fuel_volume'], 0.0, tol) + assert_near_equal(self.prob['max_extra_fuel_mass'], 0.0, tol) + assert_near_equal(self.prob['wingfuel_mass_min'], 18997.40162479, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=2e-11, rtol=1e-12) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py b/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py index b1924dac6c..6f635217ed 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py +++ b/aviary/subsystems/mass/gasp_based/test/test_mass_summation.py @@ -1,15 +1,18 @@ import unittest -import os import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs +from aviary.models.aircraft.large_single_aisle_1.V3_bug_fixed_IO import ( + V3_bug_fixed_non_metadata, + V3_bug_fixed_options, +) from aviary.subsystems.geometry.gasp_based.size_group import SizeGroup from aviary.subsystems.mass.gasp_based.mass_premission import MassPremission from aviary.utils.aviary_values import get_items +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults, is_option -from aviary.models.large_single_aisle_1.V3_bug_fixed_IO import ( - V3_bug_fixed_non_metadata, V3_bug_fixed_options) from aviary.variable_info.variables import Aircraft, Mission @@ -21,55 +24,55 @@ class MassSummationTestCase1(unittest.TestCase): """ def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "gasp_based_geom", - SizeGroup( - aviary_options=V3_bug_fixed_options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'gasp_based_geom', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "total_mass", - MassPremission( - aviary_options=V3_bug_fixed_options, - ), + 'total_mass', + MassPremission(), promotes=['*'], ) - for (key, (val, units)) in get_items(V3_bug_fixed_options): + for key, (val, units) in get_items(V3_bug_fixed_options): if not is_option(key): self.prob.model.set_input_defaults(key, val=val, units=units) - for (key, (val, units)) in get_items(V3_bug_fixed_non_metadata): + for key, (val, units) in get_items(V3_bug_fixed_non_metadata): self.prob.model.set_input_defaults(key, val=val, units=units) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + # self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') + + setup_model_options(self.prob, V3_bug_fixed_options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() - # print(f"wetted_area: {self.prob[Aircraft.Fuselage.WETTED_AREA]}") + # print(f'wetted_area: {self.prob[Aircraft.Fuselage.WETTED_AREA]}') tol = 5e-4 # size values: - assert_near_equal(self.prob["gasp_based_geom.fuselage.cabin_height"], 13.1, tol) - assert_near_equal( - self.prob["gasp_based_geom.fuselage.cabin_len"], 72.09722222222223, tol) - assert_near_equal(self.prob["gasp_based_geom.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['gasp_based_geom.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['gasp_based_geom.cabin_len'], 72.09722222222223, tol) + assert_near_equal(self.prob['gasp_based_geom.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 17.63, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.54, tol) @@ -77,88 +80,69 @@ def test_case1(self): self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.1397, tol ) # not exact GASP value from the output file, likely due to rounding error - assert_near_equal( - self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.6509873673743, tol - ) - assert_near_equal( - self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.96457870166355, tol - ) + assert_near_equal(self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.6509873673743, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.96457870166355, tol) assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 14.7, tol) # fixed mass values: - assert_near_equal( - self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.35, tol) - assert_near_equal( - self.prob["total_mass.fixed_mass.tail.loc_MAC_vtail"], 0.44959578484694906, tol - ) + assert_near_equal(self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.35, tol) + assert_near_equal(self.prob['loc_MAC_vtail'], 0.44959578484694906, tol) # wing values: - assert_near_equal( - self.prob["total_mass.wing_mass.isolated_wing_mass"], 15758, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 15758, tol) assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12606, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol) # fuel values: # modified from GASP value to account for updated crew mass. GASP value is # 78843.6 - assert_near_equal( - self.prob["total_mass.fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 78846.0, tol - ) + assert_near_equal(self.prob['OEM_wingfuel_mass'], 79500.16001078, tol) # modified from GASP value to account for updated crew mass. GASP value is # 102408.05695930264 - assert_near_equal( - self.prob["total_mass.fuel_mass.fus_mass_full"], 102408.4, tol - ) + assert_near_equal(self.prob['fus_mass_full'], 101735.01012115, tol) # modified from GASP value to account for updated crew mass. GASP value is # 1757 assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1756.7, tol + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1783.50656044, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1757 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50319.9, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50266.438, tol) assert_near_equal( - self.prob[Aircraft.Fuselage.MASS], 18667, tol + self.prob[Aircraft.Fuselage.MASS], 18624.42144949, tol ) # modified from GASP value to account for updated crew mass. GASP value is 18814 # modified from GASP value to account for updated crew mass. GASP value is # 42843.6 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 42846.3, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 43500.16001078, tol ) # modified from GASP value to account for updated crew mass. GASP value is 42843.6 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 16127.5, tol + self.prob[Aircraft.Propulsion.MASS], 16161.21, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16127 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 42846.3, tol + self.prob[Mission.Summary.FUEL_MASS], 43500.16001078, tol ) # modified from GASP value to account for updated crew mass. GASP value is 42844.0 assert_near_equal( - self.prob["total_mass.fuel_mass.fuel_mass_min"], 32806.3, tol + self.prob['fuel_mass_min'], 33460.16001078, tol ) # modified from GASP value to account for updated crew mass. GASP value is 32803.6 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 856.55, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 869.61632311, tol ) # modified from GASP value to account for updated crew mass. GASP value is 856.4910800459031 assert_near_equal( - self.prob["total_mass.fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1576.22, tol + self.prob['OEM_fuel_vol'], 1589.29615013, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1576.1710061411081 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 96553.7, tol + self.prob[Mission.Summary.OPERATING_MASS], 95899.83998922, tol ) # modified from GASP value to account for updated crew mass. GASP value is 96556.0 - # extra_fuel_mass calculated differently in this version, so test for fuel_mass.fuel_and_oem.payload_mass_max_fuel not included - assert_near_equal( - self.prob["total_mass.fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 57066.3, tol - ) - assert_near_equal( - self.prob["total_mass.fuel_mass.max_wingfuel_mass"], 57066.3, tol) + # extra_fuel_mass calculated differently in this version, so test for payload_mass_max_fuel not included + assert_near_equal(self.prob['volume_wingfuel_mass'], 57066.3, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 57066.3, tol) assert_near_equal( self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol ) # always zero when no body tank - assert_near_equal( - self.prob["total_mass.fuel_mass.body_tank.extra_fuel_volume"], 0, tol - ) # always zero when no body tank - assert_near_equal( - self.prob["total_mass.fuel_mass.body_tank.max_extra_fuel_mass"], 0, tol - ) # always zero when no body tank + assert_near_equal(self.prob['extra_fuel_volume'], 0, tol) # always zero when no body tank + assert_near_equal(self.prob['max_extra_fuel_mass'], 0, tol) # always zero when no body tank - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-10, rtol=1e-12) @@ -170,295 +154,267 @@ class MassSummationTestCase2(unittest.TestCase): """ def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" - ) - self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless') - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") - - self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, val=0, units='deg') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Controls.TOTAL_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2') + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' - ) # note: not actually defined in program, likely an error + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults( + 'MAT', val=0, units='lbm' + ) # note: not actually defined in program, likely an error + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') + + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 72.1, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 72.1, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 17.49, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.41, tol) @@ -468,14 +424,10 @@ def test_case1(self): # note: this is not the value in the GASP output, because the output calculates # them differently. This was calculated by hand. - assert_near_equal( - self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.578314120156815, tol - ) + assert_near_equal(self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.578314120156815, tol) # note: this is not the value in the GASP output, because the output calculates # them differently. This was calculated by hand. - assert_near_equal( - self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.828924591320984, tol - ) + assert_near_equal(self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.828924591320984, tol) assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 14.7, tol) # fixed mass values: @@ -483,74 +435,66 @@ def test_case1(self): self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.35, tol ) # calculated by hand - # note: fixed_mass.tail.loc_MAC_vtail not included in v3.5 + # note: tail.loc_MAC_vtail not included in v3.5 assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12606, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol) # wing values: - assert_near_equal(self.prob["wing_mass.isolated_wing_mass"], 15653, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 15653, tol) # fuel values: # modified from GASP value to account for updated crew mass. GASP value is # 79147.2 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 79002.9, tol + self.prob['OEM_wingfuel_mass'], 79656.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 79147.2 # calculated by hand, #modified from GASP value to account for updated crew # mass. GASP value is 102321.45695930265 - assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 102359.6, tol - ) + assert_near_equal(self.prob['fus_mass_full'], 101684.81858046, tol) # modified from GASP value to account for updated crew mass. GASP value is # 1769 assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1763.1, tol + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1789.92707671, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1769 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50186, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50132.58, tol) assert_near_equal( - self.prob[Aircraft.Fuselage.MASS], 18663, tol + self.prob[Aircraft.Fuselage.MASS], 18621.15351242, tol ) # modified from GASP value to account for updated crew mass. GASP value is 18787 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 43002.9, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 43656.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 43147.2 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 16133.9, tol + self.prob[Aircraft.Propulsion.MASS], 16167.631, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16140 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 43002.9, tol + self.prob[Mission.Summary.FUEL_MASS], 43656.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 43147 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 32962.9, tol + self.prob['fuel_mass_min'], 33616.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 33107.2 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 859.68, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 872.74688953, tol ) # calculated by hand, #modified from GASP value to account for updated crew mass. GASP value is 862.5603807559726 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1579.36, tol + self.prob['OEM_fuel_vol'], 1592.42671655, tol ) # calculated by hand, #modified from GASP value to account for updated crew mass. GASP value is 1582.2403068511774 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 96397.1, tol + self.prob[Mission.Summary.OPERATING_MASS], 95743.24203151, tol ) # modified from GASP value to account for updated crew mass. GASP value is 96253.0 - # extra_fuel_mass calculated differently in this version, so fuel_mass.fuel_and_oem.payload_mass_max_fuel test not included - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 55725.1, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 55725.1, tol) + # extra_fuel_mass calculated differently in this version, so payload_mass_max_fuel test not included + assert_near_equal(self.prob['volume_wingfuel_mass'], 55725.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 55725.1, tol) assert_near_equal( self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol ) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 0, tol - ) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 0, tol - ) # always zero when no body tank + assert_near_equal(self.prob['extra_fuel_volume'], 0, tol) # always zero when no body tank + assert_near_equal(self.prob['max_extra_fuel_mass'], 0, tol) # always zero when no body tank - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-10, rtol=1e-12) @@ -561,296 +505,269 @@ class MassSummationTestCase3(unittest.TestCase): """ def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" - ) - self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless' + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, val=0, units='deg') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' - ) - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # Based on large single aisle 1 for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Controls.TOTAL_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2') + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' - ) # note: not actually defined in program, likely an error + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults( + 'MAT', val=0, units='lbm' + ) # note: not actually defined in program, likely an error + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0, units='unitless') - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 72.1, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 72.1, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 17.49, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.41, tol) @@ -872,67 +789,61 @@ def test_case1(self): ) # calculated by hand assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12606, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol) # wing values: - assert_near_equal(self.prob["wing_mass.isolated_wing_mass"], 15653, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 15653, tol) # fuel values: assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 79002.9, tol + self.prob['OEM_wingfuel_mass'], 79656.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 79147.2 assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 102359.6, tol + self.prob['fus_mass_full'], 101684.818580466, tol ) # calculated by hand, #modified from GASP value to account for updated crew mass. GASP value is 102321.45695930265 assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1763.1, tol - ) # modified from GASP value to account for updated crew mass. GASP value is 102321.45695930265 + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1789.92707671, tol + ) # modified from GASP value to account for updated crew mass. GASP value is 102321.45695930265 (is it correct?) - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50186, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50132.58, tol) assert_near_equal( - self.prob[Aircraft.Fuselage.MASS], 18663, tol + self.prob[Aircraft.Fuselage.MASS], 18621.15351242, tol ) # modified from GASP value to account for updated crew mass. GASP value is 18787 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 43002.9, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 43656.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 43147.2 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 16133.9, tol + self.prob[Aircraft.Propulsion.MASS], 16167.631, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16140 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 43002.9, tol + self.prob[Mission.Summary.FUEL_MASS], 43656.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 43147 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 32962.9, tol + self.prob['fuel_mass_min'], 33616.75796849, tol ) # modified from GASP value to account for updated crew mass. GASP value is 33107.2 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 859.68, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 872.74688953, tol ) # modified from GASP value to account for updated crew mass. GASP value is 862.6 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1579.36, tol + self.prob['OEM_fuel_vol'], 1592.42671655, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1582.2 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 96397.1, tol + self.prob[Mission.Summary.OPERATING_MASS], 95743.24203151, tol ) # modified from GASP value to account for updated crew mass. GASP value is 96253.0 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.payload_mass_max_fuel"], 36000, tol + self.prob['payload_mass_max_fuel'], 36000, tol ) # note: value came from running the GASP code on my own and printing it out - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 55725.1, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 55725.1, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 55725.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 55725.1, tol) assert_near_equal( self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol ) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 0, tol - ) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 0, tol - ) # always zero when no body tank + assert_near_equal(self.prob['extra_fuel_volume'], 0, tol) # always zero when no body tank + assert_near_equal(self.prob['max_extra_fuel_mass'], 0, tol) # always zero when no body tank - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-10, rtol=1e-12) @@ -943,297 +854,269 @@ class MassSummationTestCase4(unittest.TestCase): """ def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=128, units='lbf/ft**2') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=128, units="lbf/ft**2" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless' + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, val=0, units='deg') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' - ) - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # Based on large single aisle 1 for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Controls.TOTAL_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2') + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) - + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' - ) # note: not actually defined in program, likely an error + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + 'MAT', val=0, units='lbm' + ) # note: not actually defined in program, likely an error + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=10, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=10, units='unitless') + + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 72.1, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 72.1, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 17.49, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.41, tol) @@ -1255,67 +1138,69 @@ def test_case1(self): ) # calculated by hand assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12606, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol) # wing values: - assert_near_equal(self.prob["wing_mass.isolated_wing_mass"], 15653, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 15653, tol) # fuel values: assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 78823.0, tol + self.prob['OEM_wingfuel_mass'], 79474.11569854, tol ) # modified from GASP value to account for updated crew mass. GASP value is 78966.7 assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 102541.4, tol + self.prob['fus_mass_full'], 101867.46, tol ) # calculated by hand, #modified from GASP value to account for updated crew mass. GASP value is 102501.95695930265 + assert_near_equal(self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1960.68, tol) assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1931.3, tol + self.prob['OEM_wingfuel_mass'], 79474.11569854, tol + ) # modified from GASP value to account for updated crew mass. GASP value is 78966.7 + + assert_near_equal( + self.prob['fus_mass_full'], 101867.46085041, tol + ) # calculated by hand, #modified from GASP value to account for updated crew mass. GASP value is 102501.95695930265 + assert_near_equal( + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1960.682618, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1938 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50198, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50144.527, tol) assert_near_equal( - self.prob[Aircraft.Fuselage.MASS], 18675, tol + self.prob[Aircraft.Fuselage.MASS], 18633.04024108, tol ) # modified from GASP value to account for updated crew mass. GASP value is 18799 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 42823.0, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 43474.11569854, tol ) # modified from GASP value to account for updated crew mass. GASP value is 42966.7 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 16302.1, tol + self.prob[Aircraft.Propulsion.MASS], 16339.047, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16309 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 42823.0, tol + self.prob[Mission.Summary.FUEL_MASS], 43474.11569854, tol ) # modified from GASP value to account for updated crew mass. GASP value is 42967 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 32783.0, tol + self.prob['fuel_mass_min'], 33434.11569854, tol ) # modified from GASP value to account for updated crew mass. GASP value is 32926.7 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 941.69, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 956.00523534, tol ) # modified from GASP value to account for updated crew mass. GASP value is 944.8 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1575.76, tol + self.prob['OEM_fuel_vol'], 1588.77549551, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1578.6 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 96577.0, tol + self.prob[Mission.Summary.OPERATING_MASS], 95925.88430146, tol ) # modified from GASP value to account for updated crew mass. GASP value is 96433.0 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.payload_mass_max_fuel"], 36000, tol + self.prob['payload_mass_max_fuel'], 36000, tol ) # note: value came from running the GASP code on my own and printing it out - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 55725.1, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 55725.1, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 55725.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 55725.1, tol) assert_near_equal( self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol ) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 0, tol - ) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 0, tol - ) # always zero when no body tank + assert_near_equal(self.prob['extra_fuel_volume'], 0, tol) # always zero when no body tank + assert_near_equal(self.prob['max_extra_fuel_mass'], 0, tol) # always zero when no body tank - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-10, rtol=1e-12) @@ -1326,297 +1211,269 @@ class MassSummationTestCase5(unittest.TestCase): """ def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=150, units='lbf/ft**2') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=150, units="lbf/ft**2" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" - ) - self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless' + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, val=0, units='deg') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # Based on large single aisle 1 for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Controls.TOTAL_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2') + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) - + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' - ) # note: not actually defined in program, likely an error + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults( + 'MAT', val=0, units='lbm' + ) # note: not actually defined in program, likely an error + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0.0, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0.0, units='unitless') - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 72.1, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 72.1, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 16.16, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 15.1, tol) @@ -1634,70 +1491,68 @@ def test_case1(self): # fixed mass values: assert_near_equal( - self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.349999999999, tol - # self.prob["fixed_mass.main_gear_mass"], 6384.349999999999, tol + self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], + 6384.349999999999, + tol, + # self.prob['main_gear_mass'], 6384.349999999999, tol ) # calculated by hand assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12606, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol) # wing values: - assert_near_equal(self.prob["wing_mass.isolated_wing_mass"], 14631, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 14631, tol) # fuel values: assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 80475.9, tol + self.prob['OEM_wingfuel_mass'], 81085.9308234, tol ) # modified from GASP value to account for updated crew mass. GASP value is 81424.8 + assert_near_equal(self.prob['fus_mass_full'], 102510.642, tol) # calculated by hand assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 102510.7, tol - ) # calculated by hand - assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1823.4, tol + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1848.52316376, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1862 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 48941, tol) - assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18675, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 48940.74, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18674.791, tol) assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 44472.9, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 45085.9308234, tol ) # modified from GASP value to account for updated crew mass. GASP value is 45424.8 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 16194.2, tol + self.prob[Aircraft.Propulsion.MASS], 16225.793, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16233 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 44472.9, tol + self.prob[Mission.Summary.FUEL_MASS], 45085.9308234, tol ) # modified from GASP value to account for updated crew mass. GASP value is 45425 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 34432.9, tol + self.prob['fuel_mass_min'], 35045.9308234, tol ) # modified from GASP value to account for updated crew mass. GASP value is 35384.8 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 889.06, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 901.317636, tol ) # modified from GASP value to account for updated crew mass. GASP value is 908.1 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1608.74, tol + self.prob['OEM_fuel_vol'], 1620.99746302, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1627.8 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 94927.1, tol + self.prob[Mission.Summary.OPERATING_MASS], 94314.0691766, tol ) # modified from GASP value to account for updated crew mass. GASP value is 93975 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.payload_mass_max_fuel"], 35380.5, tol + self.prob['payload_mass_max_fuel'], 34766.20684105, tol ) # note: value came from running the GASP code on my own and printing it out, #modified from GASP value to account for updated crew mass. GASP value is 34427.4 + assert_near_equal(self.prob['volume_wingfuel_mass'], 43852.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 43852.1, tol) assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 43852.1, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 43852.1, tol) - assert_near_equal( - self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 620.739, tol + self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 1233.79315895, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1572.6 assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 12.4092, tol + self.prob['extra_fuel_volume'], 24.6648902, tol ) # slightly different from GASP value, likely a rounding error, #modified from GASP value to account for updated crew mass. GASP value is 31.43 assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 620.736, tol + self.prob['max_extra_fuel_mass'], 1233.79315895, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1572.6 - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-10, rtol=1e-12) @@ -1708,297 +1563,269 @@ class MassSummationTestCase6(unittest.TestCase): """ def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=180, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37500, units='ft') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.14, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=10.13, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=10.13, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" - ) - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, val=150, units='lbf/ft**2') self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=150, units="lbf/ft**2" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units="lbf" - ) - self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.Engine.SCALED_SLS_THRUST, val=29500.0, units='lbf' ) - self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units="unitless" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.6, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.145, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 2.362, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units="ft") + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 5.8, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 1.02823, units='unitless' + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.25, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 2, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 2, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=10040, units="lbm" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=10040, units='lbm' ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, val=0, units='deg') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Controls.TOTAL_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.21366, units='lbm/lbf' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2') + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=928.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.14, units="unitless" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=928.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.112, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1959.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=551.0, units="lbm") self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=11192.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.14, units='unitless' ) - + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1959.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=551.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=11192.0, units='lbm') self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' - ) # note: not actually defined in program, likely an error + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=50.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=7.6, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + 'MAT', val=0, units='lbm' + ) # note: not actually defined in program, likely an error + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=10.0, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=10.0, units='unitless') + + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 72.1, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 72.1, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 16.16, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 15.1, tol) @@ -2016,376 +1843,354 @@ def test_case1(self): # fixed mass values: assert_near_equal( - self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.349999999999, tol - # self.prob["fixed_mass.main_gear_mass"], 6384.349999999999, tol + self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], + 6384.349999999999, + tol, + # self.prob['main_gear_mass'], 6384.349999999999, tol ) # calculated by hand assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12606, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol) # wing values: - assert_near_equal(self.prob["wing_mass.isolated_wing_mass"], 14631, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 14631, tol) # fuel values: assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 80029.2, tol + self.prob['OEM_wingfuel_mass'], 80636.1673241, tol ) # modified from GASP value to account for updated crew mass. GASP value is 80982.7 + assert_near_equal(self.prob['fus_mass_full'], 106989.952, tol) # calculated by hand assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 106913.6, tol - ) # calculated by hand - assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1985.7, tol + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 2013.09114511, tol ) # modified from GASP value to account for updated crew mass. GASP value is 2029 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 49222, tol) - assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18956, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 49209.648, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18960.975, tol) assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 44029.2, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 44636.1673241, tol ) # modified from GASP value to account for updated crew mass. GASP value is 44982.7 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 16356.5, tol + self.prob[Aircraft.Propulsion.MASS], 16390.94, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16399 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 44029.2, tol + self.prob[Mission.Summary.FUEL_MASS], 44636.16732294, tol ) # modified from GASP value to account for updated crew mass. GASP value is 44982.7 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 33989.2, tol + self.prob['fuel_mass_min'], 34596.1673241, tol ) # modified from GASP value to account for updated crew mass. GASP value is 34942.7 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 968.21, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 981.55900268, tol ) # modified from GASP value to account for updated crew mass. GASP value is 989.2 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1599.87, tol + self.prob['OEM_fuel_vol'], 1612.00619309, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1618.9 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 95370.8, tol + self.prob[Mission.Summary.OPERATING_MASS], 94763.8326759, tol ) # modified from GASP value to account for updated crew mass. GASP value is 94417 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.payload_mass_max_fuel"], 35823.0, tol + self.prob['payload_mass_max_fuel'], 35215.97039402, tol ) # note: value came from running the GASP code on my own and printing it out, #modified from GASP value to account for updated crew mass. GASP value is 34879.2 + assert_near_equal(self.prob['volume_wingfuel_mass'], 43852.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 43852.1, tol) assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 43852.1, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 43852.1, tol) - assert_near_equal( - self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 177.042, tol + self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 784.02965965, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1120.9 assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 91.5585, tol + self.prob['extra_fuel_volume'], 104.90625688, tol ) # modified from GASP value to account for updated crew mass. GASP value is 112.3 assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 4579.96, tol + self.prob['max_extra_fuel_mass'], 5247.64639206, tol ) # modified from GASP value to account for updated crew mass. GASP value is 5618.2 - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-10, rtol=1e-12) class MassSummationTestCase7(unittest.TestCase): """ - This is the Advanced Tube and Wing V3.6 test case + This is the Advanced Tube and Wing V3.6 test case. All values are from V3.6 output, hand calculated from the output, or were printed out after running the code manually. Values not directly from the output are labeled as such. """ def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=154, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=154, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=154, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=37100, units='ft') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 29, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 29, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.165, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=11, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units='deg') self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=11, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.12, units='unitless' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=25, units="deg") + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=145388.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.12, units="unitless" + Aircraft.Design.WING_LOADING, val=104.50, units='lbf/ft**2' ) self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=145388.0, units="lbm" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=104.50, units="lbf/ft**2" + Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=0, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=1.67, units="unitless" + Aircraft.Engine.SCALED_SLS_THRUST, val=17000.0, units='lbf' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.35, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=17000.0, units="lbf" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.35, units="unitless" + Aircraft.Fuel.WING_FUEL_FRACTION, 0.475, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.475, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.09986, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.189, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.09986, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 3, units="unitless" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 9.5, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 3, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.2307, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 2.1621, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 2.1621, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units="unitless" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.75, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 7.36, units="ft") + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 7.36, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28620.0, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28620.0, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 0.594, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 0.594, units='unitless' - ) - self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2095, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 1.715, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, 118, units="ft") - - self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2095, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.715, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, 118, units='ft') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=15970.0, units="lbm" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=15970.0, units='lbm' ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, val=0, units='deg') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.232, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.289, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.12, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # Based on large single aisle 1 for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.95, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=16.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Controls.TOTAL_MASS, val=0, units='lbm' ) # note: not actually defined in program, likely an error self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.04, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units="unitless" + Aircraft.Nacelle.CLEARANCE_RATIO, val=0.2, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.2355, units="lbm/lbf" + Aircraft.Engine.MASS_SPECIFIC, val=0.2355, units='lbm/lbf' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, val=3, units='lbm/ft**2') + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=3, units="lbm/ft**2" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units='unitless' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=1014.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.165, units="unitless" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0.15, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.085, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=1014.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.085, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.105, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1504.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=126.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=9114.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.105, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1504.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=126.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=9114.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=0.0, units="lbm") + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=10.0, units="lbm") + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=0.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=85, units="unitless" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=10.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_COEFFICIENT, val=85, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) + self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' - ) # note: not actually defined in program, likely an error - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=128, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" - ) + 'MAT', val=0, units='lbm' + ) # note: not actually defined in program, likely an error + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=10.0, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.041, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=10.0, units='unitless') + + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Mission.Design.MACH, val=0.8, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 61.6, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 61.6, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 16.91, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.01, tol) @@ -2394,81 +2199,87 @@ def test_case1(self): ) # slightly different from GASP value, likely a rounding error assert_near_equal( - self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.6498, tol + self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], + 9.6498, + tol, # note: value came from running the GASP code on my own and printing it out (GASP output calculates this differently) ) assert_near_equal( - self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 13.4662, tol + self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], + 13.4662, + tol, # note: value came from running the GASP code on my own and printing it out (GASP output calculates this differently) ) assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 11.77, tol) # fixed mass values: assert_near_equal( - self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 5219.3076, tol - # self.prob["fixed_mass.main_gear_mass"], 5219.3076, tol + self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], + 5219.3076, + tol, + # self.prob['main_gear_mass'], 5219.3076, tol ) # note: value came from running the GASP code on my own and printing it out assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 8007, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1321/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1321 / 2, tol) # wing values: assert_near_equal( - self.prob["wing_mass.isolated_wing_mass"], 13993, tol + self.prob['isolated_wing_mass'], 13993, tol ) # calculated as difference between wing mass and fold mass, not an actual GASP variable # fuel values: assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 63452.2, tol + self.prob['OEM_wingfuel_mass'], 63122.20489199, tol ) # modified from GASP value to account for updated crew mass. GASP value is 62427.2 assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 99396.7, tol + self.prob['fus_mass_full'], 99380.387, tol ) # note: value came from running the GASP code on my own and printing it out assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1472.6, tol + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1457.73144048, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1426 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 45373.4, tol) - assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18859.9, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 45370.902, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 18858.356, tol) assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 32652.2, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 32322.20489199, tol ) # modified from GASP value to account for updated crew mass. GASP value is 31627.2 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 10800.8, tol + self.prob[Aircraft.Propulsion.MASS], 10785.88644048, tol ) # modified from GASP value to account for updated crew mass. GASP value is 10755.0 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 32652.2, tol + self.prob[Mission.Summary.FUEL_MASS], 32322.20489185, tol ) # modified from GASP value to account for updated crew mass. GASP value is 31627.0 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 16682.2, tol + self.prob['fuel_mass_min'], 16352.20489199, tol ) # modified from GASP value to account for updated crew mass. GASP value is 15657.2 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 718.03, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 710.77229745, tol ) # modified from GASP value to account for updated crew mass. GASP value is 695.5 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1268.48, tol + self.prob['OEM_fuel_vol'], 1261.88270827, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1248.0 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 81935.8, tol + self.prob[Mission.Summary.OPERATING_MASS], 82265.79510801, tol ) # modified from GASP value to account for updated crew mass. GASP value is 82961.0 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.payload_mass_max_fuel"], 30800.0039, tol + self.prob['payload_mass_max_fuel'], 30800.0039, tol ) # note: value came from running the GASP code on my own and printing it out - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 33892.8, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 33892.8, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 33892.8, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 33892.8, tol) assert_near_equal(self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol) assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 40.4789, 0.005 + self.prob['extra_fuel_volume'], 33.21832644, tol ) # note: higher tol because slightly different from GASP value, likely numerical issues, #modified from GASP value to account for updated crew mass. GASP value is 17.9 assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 2024.70, 0.003 + self.prob['max_extra_fuel_mass'], 1661.65523441, tol ) # note: higher tol because slightly different from GASP value, likely numerical issues, #modified from GASP value to account for updated crew mass. GASP value is 897.2 + assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX], 677.554, tol) + assert_near_equal(self.prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 677.554, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-9, rtol=6e-11) @@ -2480,313 +2291,291 @@ class MassSummationTestCase8(unittest.TestCase): """ def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, - val=False, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=154, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=154, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=154, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=43000, units='ft') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 44.2, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 44.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.163, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.13067, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.13067, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.025, units="unitless" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.025, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 3.0496, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 3.0496, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 7.642, units="ft") + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 7.642, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28620.0, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28620.0, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 1.35255, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 1.35255, units='unitless' + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2095, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.660, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2095, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 1.660, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 6.85, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 1.18, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 6.85, units="ft" + Aircraft.Design.WING_LOADING, val=87.5, units='lbf/ft**2' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 1.18, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0, units="unitless" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=1014.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=87.5, units="lbf/ft**2" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.085, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.105, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=1014.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.085, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.105, units="unitless") + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1504.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1504.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=126.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=9114.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=0.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=10.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' + ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=126.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=9114.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=21160.0, units="lbf" + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 0.73934, units='unitless' + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.5625, units="unitless" + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=0.0, units='lbm' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=22.47, units="deg") self.prob.model.set_input_defaults( - Aircraft.Wing.MOUNTING_TYPE, val=.1, units="unitless") + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=10.0, units='lbm' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=19.565, units="unitless" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=118, units="ft" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=15970.0, units="lbm" + Aircraft.Engine.SCALED_SLS_THRUST, val=21160.0, units='lbf' ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 0.73934, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.2470, units="lbm/lbf" + Aircraft.Fuel.WING_FUEL_FRACTION, 0.5625, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=22.47, units='deg') self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=2.5, units="lbm/ft**2" + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, val=0.1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=19.565, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Strut.ATTACHMENT_LOCATION, val=118, units='ft') + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=15970.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.163, units="unitless" + Aircraft.Engine.MASS_SPECIFIC, val=0.2470, units='lbm/lbf' ) self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") + Aircraft.Nacelle.MASS_SPECIFIC, val=2.5, units='lbm/ft**2' + ) + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.2143, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.2143, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=0.825, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=0.825, units='unitless' ) self.prob.model.set_input_defaults( Aircraft.VerticalTail.SWEEP, val=0, units='deg' ) # not in file self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.2076, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.2076, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.2587, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.2587, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.11, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.11, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=1, units="unitless" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.1, units="unitless" + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' ) # Based on large single aisle 1 for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.5936, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.5936, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=30, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=30, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units="lbm" - ) # not in file - self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=0, units='lbm' ) # not in file self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.03390, units="unitless" + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=10.0, units="unitless" - ) + Aircraft.Controls.TOTAL_MASS, val=0, units='lbm' + ) # not in file self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.060, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.03390, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=89.66, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=10.0, units='unitless') self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.060, units='unitless' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' - ) # not in file - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=89.66, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=10.0, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.060, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=89.66, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') # not in file + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=143100.0, units="lbm" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=78.94, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=143100.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.346, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=78.94, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.346, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.43, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.43, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.066, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.066, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) # self.prob.model.set_input_defaults( - # Aircraft.Strut.AREA, 523.337, units="ft**2" + # Aircraft.Strut.AREA, 523.337, units='ft**2' # ) # had to calculate by hand - self.prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, 0.238, units="unitless" - ) + self.prob.model.set_input_defaults(Aircraft.Strut.MASS_COEFFICIENT, 0.238, units='unitless') + + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Mission.Design.MACH, val=0.8, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 93.9, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 93.9, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 13.59, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 13.15, tol) @@ -2804,69 +2593,71 @@ def test_case1(self): # fixed mass values: assert_near_equal( - self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 4123.4, tol - # self.prob["fixed_mass.main_gear_mass"], 4123.4, tol + self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], + 4123.4, + tol, + # self.prob['main_gear_mass'], 4123.4, tol ) # note:printed out from GASP code assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 10453.0, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1704.0/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1704.0 / 2, tol) # wing values: - assert_near_equal(self.prob["wing_mass.isolated_wing_mass"], 14040, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 14040, tol) assert_near_equal(self.prob[Aircraft.Wing.MASS], 18031, tol) # fuel values: assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 60410.9, tol + self.prob['OEM_wingfuel_mass'], 59780.52528506, tol ) # modified from GASP value to account for updated crew mass. GASP value is 59372.3 assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 97697.5, tol + self.prob['fus_mass_full'], 97651.376, tol ) # note:printed out from GASP code assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1954.3, tol + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1912.71466876, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1886.0 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 43660.4, tol) - assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 14657.4, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 43655.977, tol) + assert_near_equal(self.prob[Aircraft.Fuselage.MASS], 14654.517, tol) assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 29610.9, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 28980.52528506, tol ) # modified from GASP value to account for updated crew mass. GASP value is 28572.3 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 14111.2, tol + self.prob[Aircraft.Propulsion.MASS], 14069.60018876, tol ) # modified from GASP value to account for updated crew mass. GASP value is 14043.0 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 29610.9, tol + self.prob[Mission.Summary.FUEL_MASS], 28980.52528501, tol ) # modified from GASP value to account for updated crew mass. GASP value is 28572.0 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 13640.9, tol + self.prob['fuel_mass_min'], 13010.52528506, tol ) # modified from GASP value to account for updated crew mass. GASP value is 12602.3 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 651.15, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 637.28803796, tol ) # modified from GASP value to account for updated crew mass. GASP value is 628.3 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1207.68, tol + self.prob['OEM_fuel_vol'], 1195.07883601, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1186.9 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 82689.1, tol + self.prob[Mission.Summary.OPERATING_MASS], 83319.47471494, tol ) # modified from GASP value to account for updated crew mass. GASP value is 83728.0 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.payload_mass_max_fuel"], 30800.0, tol + self.prob['payload_mass_max_fuel'], 30800.0, tol ) # note:printed out from GASP code - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 31051.6, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 31051.6, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 31051.6, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 31051.6, tol) assert_near_equal(self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol) + # TODO: extra_fuel_volume < 0. need investigate assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 30.3942, 0.009 - ) # note: higher tol because slightly different from GASP value, likely numerical issues, printed out from the GASP code, #modified from GASP value to account for updated crew mass. GASP value is 7.5568 + self.prob['extra_fuel_volume'], 16.53287329, tol + ) # note: printed out from the GASP code, #modified from GASP value to account for updated crew mass. GASP value is 7.5568 + # TODO: extra_fuel_volume < 0. need investigate assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 1520.384, 0.009 - ) # note: higher tol because slightly different from GASP value, likely numerical issues, printed out from the GASP code, #modified from GASP value to account for updated crew mass. GASP value is 378.0062 + self.prob['max_extra_fuel_mass'], 827.01142371, tol + ) # note: printed out from the GASP code, #modified from GASP value to account for updated crew mass. GASP value is 378.0062 - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-9, rtol=6e-11) @@ -2878,356 +2669,311 @@ class MassSummationTestCase9(unittest.TestCase): """ def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') - options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, - val=154, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=154, units='unitless') options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=154, units='unitless') options.set_val(Mission.Design.CRUISE_ALTITUDE, val=43000, units='ft') options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=False, units='unitless') - options.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, - val=True, units='unitless') - options.set_val(Aircraft.LandingGear.FIXED_GEAR, - val=False, units='unitless') - options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, - val=True, units='unitless') - options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, - val=200, units="lbm") - options.set_val(Aircraft.Fuselage.NUM_SEATS_ABREAST, 6) - options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units="inch") + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=True, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=200, units='lbm') + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 6) + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 24, units='inch') options.set_val(Aircraft.Fuselage.NUM_AISLES, 1) - options.set_val(Aircraft.Fuselage.SEAT_PITCH, 44.2, units="inch") - options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units="inch") + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 44.2, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 20.2, units='inch') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.163, units='unitless') + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "size", - SizeGroup( - aviary_options=options, - ), - promotes_inputs=["aircraft:*", "mission:*"], + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], promotes_outputs=[ - "aircraft:*", + 'aircraft:*', ], ) self.prob.model.add_subsystem( - "GASP_mass", - MassPremission( - aviary_options=options, - ), - promotes=["*"], + 'GASP_mass', + MassPremission(), + promotes=['*'], ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units="unitless" + Aircraft.HorizontalTail.TAPER_RATIO, val=0.352, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MOMENT_RATIO, val=0.13067, units="unitless" + Aircraft.HorizontalTail.MOMENT_RATIO, val=0.13067, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.ASPECT_RATIO, val=4.025, units="unitless" + Aircraft.HorizontalTail.ASPECT_RATIO, val=4.025, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MOMENT_RATIO, 3.0496, units="unitless" + Aircraft.VerticalTail.MOMENT_RATIO, 3.0496, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units="unitless" + Aircraft.VerticalTail.TAPER_RATIO, val=0.801, units='unitless' ) - self.prob.model.set_input_defaults( - Aircraft.Engine.REFERENCE_DIAMETER, 8.425, units="ft") + self.prob.model.set_input_defaults(Aircraft.Engine.REFERENCE_DIAMETER, 8.425, units='ft') # self.prob.model.set_input_defaults( - # Aircraft.Engine.REFERENCE_SLS_THRUST, 28620, units="lbf" + # Aircraft.Engine.REFERENCE_SLS_THRUST, 28620, units='lbf' # ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 0.73934, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 0.73934, units='unitless' + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2095, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.569, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units='ft') + self.prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2095, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Nacelle.FINENESS, 1.569, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Fuselage.DELTA_DIAMETER, 4.5, units="ft" + Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 6.85, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 1.18, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.NOSE_FINENESS, 1, units="unitless" + Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 6.85, units="ft" + Aircraft.Design.WING_LOADING, val=96.10, units='lbf/ft**2' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.TAIL_FINENESS, 1.18, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuselage.WETTED_AREA_SCALER, 1, units="unitless" + Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units='mi/h' ) + + self.prob.model.set_input_defaults(Aircraft.APU.MASS, val=1014.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.LOADING, val=96.10, units="lbf/ft**2" + Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units="unitless" + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.085, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.MAX_STRUCTURAL_SPEED, val=402.5, units="mi/h" + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.105, units='unitless' ) - - self.prob.model.set_input_defaults( - Aircraft.APU.MASS, val=1014.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Instruments.MASS_COEFFICIENT, val=0.0736, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, val=0.085, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, val=0.105, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Avionics.MASS, val=1504.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.AntiIcing.MASS, val=126.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Furnishings.MASS, val=9114.0, units="lbm") + self.prob.model.set_input_defaults(Aircraft.Avionics.MASS, val=1504.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=0.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=10.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units="unitless") - - self.prob.model.set_input_defaults( - Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units="psi") - self.prob.model.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=23750.0, units="lbf" + Aircraft.AirConditioning.MASS_COEFFICIENT, val=1.65, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, val=126.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS, val=9114.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Engine.SCALE_FACTOR, 0.82984, units='unitless' + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, val=5.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.WING_FUEL_FRACTION, 0.5936, units="unitless" + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, val=3.0, units='lbm' ) - self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=22.47, units="deg") - self.prob.model.set_input_defaults( - Aircraft.Wing.MOUNTING_TYPE, val=.1, units="unitless") self.prob.model.set_input_defaults( - Aircraft.Wing.ASPECT_RATIO, val=19.565, units="unitless" + Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, val=0.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Strut.ATTACHMENT_LOCATION, val=118.0, units="ft" + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, val=10.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.CrewPayload.CARGO_MASS, val=15970.0, units="lbm" + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, val=12.0, units='unitless' ) + self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SPECIFIC, val=0.2744, units="lbm/lbf" + Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, val=7.5, units='psi' ) self.prob.model.set_input_defaults( - Aircraft.Nacelle.MASS_SPECIFIC, val=2.5, units="lbm/ft**2" + Aircraft.Engine.SCALED_SLS_THRUST, val=23750.0, units='lbf' ) + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, 0.82984, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.PYLON_FACTOR, val=1.25, units="unitless" + Aircraft.Fuel.WING_FUEL_FRACTION, 0.5936, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.SWEEP, val=22.47, units='deg') self.prob.model.set_input_defaults( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION, val=0.163, units="unitless" + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, val=0.1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, val=19.565, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Engine.MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Engine.WING_LOCATIONS, val=0.2143, units="unitless" + Aircraft.Strut.ATTACHMENT_LOCATION, val=118.0, units='ft' ) + self.prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0, units="unitless" + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, val=15970.0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.ASPECT_RATIO, val=0.825, units="unitless" + Aircraft.Engine.MASS_SPECIFIC, val=0.2744, units='lbm/lbf' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.SWEEP, val=0, units='deg' + Aircraft.Nacelle.MASS_SPECIFIC, val=2.5, units='lbm/ft**2' ) + self.prob.model.set_input_defaults(Aircraft.Engine.PYLON_FACTOR, val=1.25, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.2076, units="unitless" + Aircraft.Propulsion.MISC_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units="unitless" + Aircraft.Engine.WING_LOCATIONS, val=0.2143, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.2587, units="unitless" + Aircraft.LandingGear.MAIN_GEAR_LOCATION, val=0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.11, units="unitless" + Aircraft.VerticalTail.ASPECT_RATIO, val=0.825, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, val=0, units='deg') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_COEFFICIENT, val=0.2076, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.1, units="unitless" + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units="unitless" - ) # Based onlarge single aisle 1for updated flaps mass model - self.prob.model.set_input_defaults( - Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units="unitless" - ) # Based on large single aisle 1 for updated flaps mass model - self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.5936, units="unitless" + Aircraft.VerticalTail.MASS_COEFFICIENT, val=0.2587, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=30.0, units="unitless" + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, val=0.11, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=1, units="lbm" + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.VerticalTail.THICKNESS_TO_CHORD, val=0.1, units='unitless' + ) self.prob.model.set_input_defaults( - Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units="unitless") + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, val=1.9, units='unitless' + ) # Based onlarge single aisle 1for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units="unitless") + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.817, units='unitless' + ) # Based on large single aisle 1 for updated flaps mass model self.prob.model.set_input_defaults( - Aircraft.Controls.TOTAL_MASS, val=0, units="lbm" + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, val=0.5936, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MASS_COEFFICIENT, val=0.03390, units="unitless" + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, val=30.0, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units="unitless" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, val=1, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.DENSITY, val=6.687, units="lbm/galUS" + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_MARGIN, val=0.0, units="unitless" + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.060, units="unitless" + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Controls.TOTAL_MASS, val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_COEFFICIENT, val=96.94, units="unitless" + Aircraft.LandingGear.MASS_COEFFICIENT, val=0.03390, units='unitless' ) self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.pylon_len", val=0, units='ft' + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, val=0.85, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, val=6.687, units='lbm/galUS') + self.prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, val=0.0, units='unitless') self.prob.model.set_input_defaults( - "fuel_mass.fus_and_struct.MAT", val=0, units='lbm' + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, val=0.060, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=96.94, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.MASS_SCALER, val=1, units="unitless" + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuselage.MASS_SCALER, val=1, units="unitless" + Aircraft.Fuselage.MASS_COEFFICIENT, val=96.94, units='unitless' ) + self.prob.model.set_input_defaults('pylon_len', val=0, units='ft') + self.prob.model.set_input_defaults('MAT', val=0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units="unitless" + Aircraft.HorizontalTail.MASS_SCALER, val=1, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.POD_MASS_SCALER, val=1, units="unitless" + Aircraft.VerticalTail.MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' + Aircraft.LandingGear.TOTAL_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, val=1, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units="unitless") - self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=166100.0, units="lbm" + Aircraft.Design.STRUCTURAL_MASS_INCREMENT, val=0, units='lbm' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=78.94, units="unitless" + Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, val=1, units='unitless' ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=166100.0, units='lbm') self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.346, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=78.94, units='unitless' ) + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.346, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.11, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.43, units="unitless" + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, val=1.43, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.066, units="unitless" + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.066, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) # self.prob.model.set_input_defaults( - # Aircraft.Strut.AREA, 553.1, units="ft**2" + # Aircraft.Strut.AREA, 553.1, units='ft**2' # ) + self.prob.model.set_input_defaults(Aircraft.Strut.MASS_COEFFICIENT, 0.238, units='unitless') + self.prob.model.set_input_defaults('motor_power', 830, units='kW') + self.prob.model.set_input_defaults('motor_voltage', 850, units='V') + self.prob.model.set_input_defaults('max_amp_per_wire', 260, units='A') self.prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, 0.238, units="unitless" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.motor_power", 830, units="kW" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.motor_voltage", 850, units="V" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.max_amp_per_wire", 260, units="A" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.safety_factor", 1, units="unitless" + 'safety_factor', 1, units='unitless' ) # (not in this GASP code) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.wire_area", 0.0015, units="ft**2" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.rho_wire", 565, units="lbm/ft**3" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.battery_energy", 6077, units="MJ" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.motor_eff", 0.98, units="unitless" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.inverter_eff", 0.99, units="unitless" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.transmission_eff", 0.975, units="unitless" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.battery_eff", 0.975, units="unitless" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.rho_battery", 0.5, units="kW*h/kg" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.motor_spec_mass", 4, units="hp/lbm" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.inverter_spec_mass", 12, units="kW/kg" - ) - self.prob.model.set_input_defaults( - "fixed_mass.augmentation.TMS_spec_mass", 0.125, units="lbm/kW" - ) - - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units="ft") + self.prob.model.set_input_defaults('wire_area', 0.0015, units='ft**2') + self.prob.model.set_input_defaults('rho_wire', 565, units='lbm/ft**3') + self.prob.model.set_input_defaults('battery_energy', 6077, units='MJ') + self.prob.model.set_input_defaults('motor_eff', 0.98, units='unitless') + self.prob.model.set_input_defaults('inverter_eff', 0.99, units='unitless') + self.prob.model.set_input_defaults('transmission_eff', 0.975, units='unitless') + self.prob.model.set_input_defaults('battery_eff', 0.975, units='unitless') + self.prob.model.set_input_defaults('rho_battery', 0.5, units='kW*h/kg') + self.prob.model.set_input_defaults('motor_spec_mass', 4, units='hp/lbm') + self.prob.model.set_input_defaults('inverter_spec_mass', 12, units='kW/kg') + self.prob.model.set_input_defaults('TMS_spec_mass', 0.125, units='lbm/kW') + + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=0.0, units='ft') + self.prob.model.set_input_defaults(Mission.Design.MACH, val=0.8, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, val=0.3) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, val=1069.0, units='ft**2') + + setup_model_options(self.prob, options) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 # size values: - assert_near_equal(self.prob["size.fuselage.cabin_height"], 13.1, tol) - assert_near_equal(self.prob["size.fuselage.cabin_len"], 93.9, tol) - assert_near_equal(self.prob["size.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['size.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['size.cabin_len'], 93.9, tol) + assert_near_equal(self.prob['size.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 13.97, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 13.53, tol) @@ -3249,73 +2995,475 @@ def test_case1(self): ) # (printed out from GASP code) assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 13034.0, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 2124.5/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 2124.5 / 2, tol) # wing values: - assert_near_equal(self.prob["wing_mass.isolated_wing_mass"], 15895, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 15895, tol) assert_near_equal(self.prob[Aircraft.Wing.MASS], 20461.7, tol) # fuel values: assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 64594.0, tol + self.prob['OEM_wingfuel_mass'], 63921.50874092, tol ) # modified from GASP value to account for updated crew mass. GASP value is 63707.6 assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 108803.9, tol + self.prob['fus_mass_full'], 109537.46058162, tol ) # (printed out from GASP code), #modified from GASP value to account for updated crew mass. GASP value is 108754.4 assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 2027.6, 0.00055 + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1987.29052446, 0.00055 ) # slightly above tol, due to non-integer number of wires, #modified from GASP value to account for updated crew mass. GASP value is 1974.5 - assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 49582, tol) + assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 49609.317, tol) assert_near_equal( - self.prob[Aircraft.Fuselage.MASS], 16313.0, tol + self.prob[Aircraft.Fuselage.MASS], 16350.28996446, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16436.0 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 33794.0, 0.00058 + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 33121.50874092, 0.00058 ) # slightly above tol, due to non-integer number of wires, #modified from GASP value to account for updated crew mass. GASP value is 32907.6 assert_near_equal( - self.prob[Aircraft.Propulsion.MASS], 26565.2, 0.00054 + self.prob[Aircraft.Propulsion.MASS], 26534.716, 0.00054 ) # slightly above tol, due to non-integer number of wires, #modified from GASP value to account for updated crew mass. GASP value is 26527.0 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 33794.0, 0.00056 + self.prob[Mission.Summary.FUEL_MASS], 33121.50874092, 0.00056 ) # slightly above tol, due to non-integer number of wires, #modified from GASP value to account for updated crew mass. GASP value is 32908 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 17824.0, 0.0012 + self.prob['fuel_mass_min'], 17151.50874092, 0.0012 ) # slightly above tol, due to non-integer number of wires, #modified from GASP value to account for updated crew mass. GASP value is 16937.6 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 675.58, 0.00051 + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 662.13560226, 0.00051 ) # slightly above tol, due to non-integer number of wires, #modified from GASP value to account for updated crew mass. GASP value is 657.9 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1291.31, tol + self.prob['OEM_fuel_vol'], 1277.86167649, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1273.6 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 101506.0, tol + self.prob[Mission.Summary.OPERATING_MASS], 102178.49125908, tol ) # modified from GASP value to account for updated crew mass. GASP value is 102392.0 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.payload_mass_max_fuel"], 30800.0, tol + self.prob['payload_mass_max_fuel'], 30800.0, tol ) # (printed out from GASP code) - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 35042.1, tol - ) - assert_near_equal(self.prob["fuel_mass.max_wingfuel_mass"], 35042.1, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 35042.1, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 35042.1, tol) assert_near_equal(self.prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol) - assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 0, tol - ) - assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 0, tol - ) + assert_near_equal(self.prob['extra_fuel_volume'], 0.69314718, tol) + assert_near_equal(self.prob['max_extra_fuel_mass'], 34.67277748, tol) assert_near_equal(self.prob[Aircraft.Electrical.HYBRID_CABLE_LENGTH], 65.6, tol) assert_near_equal( - self.prob["fixed_mass.aug_mass"], 9394.3, 0.0017 + self.prob['aug_mass'], 9394.3, 0.0017 ) # slightly above tol, due to non-integer number of wires - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-9, rtol=6e-11) -if __name__ == "__main__": +@use_tempdirs +class BWBMassSummationTestCase(unittest.TestCase): + """ + GASP BWB model + """ + + def setUp(self): + options = get_option_defaults() + # options from SizeGroup + options.set_val(Aircraft.Design.TYPE, val='BWB', units='unitless') + options.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val=False, units='unitless') + options.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, val=False, units='unitless') + options.set_val(Aircraft.Wing.HAS_STRUT, val=False, units='unitless') + options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') + options.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=True, units='unitless') + options.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True, units='unitless' + ) + options.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=150, units='unitless') + options.set_val(Aircraft.Fuselage.AISLE_WIDTH, 22, units='inch') + options.set_val(Aircraft.Fuselage.NUM_AISLES, 3) + options.set_val(Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 18) + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, 36, units='inch') + options.set_val(Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, 32, units='inch') + options.set_val(Aircraft.Fuselage.SEAT_WIDTH, 21, units='inch') + options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 11) + # options from MassPremission + options.set_val(Mission.Design.CRUISE_ALTITUDE, val=41000, units='ft') + options.set_val(Aircraft.LandingGear.FIXED_GEAR, val=False, units='unitless') + options.set_val(Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless') + options.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=225, units='lbm') + options.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, 0.04373, units='unitless') + options.set_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES, 2, units='unitless') + options.set_val(Aircraft.CrewPayload.ULD_MASS_PER_PASSENGER, 0.0667, units='lbm') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'size', + SizeGroup(), + promotes_inputs=['aircraft:*', 'mission:*'], + promotes_outputs=[ + 'aircraft:*', + ], + ) + prob.model.add_subsystem( + 'GASP_mass', + MassPremission(), + promotes=['*'], + ) + + # inputs from SizeGroup + prob.model.set_input_defaults(Aircraft.Wing.ASPECT_RATIO, 10.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SWEEP, 30.0, units='deg') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults(Aircraft.Design.WING_LOADING, 70.0, units='lbf/ft**2') + # prob.model.set_input_defaults(Aircraft.VerticalTail.ASPECT_RATIO, 1.705, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.TAPER_RATIO, 0.366, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.TAPER_RATIO, 0.366, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuel.WING_FUEL_FRACTION, 0.45, units='unitless') + + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, 0.000001, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.VerticalTail.VOLUME_COEFFICIENT, 0.015, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.DELTA_DIAMETER, 5.0, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, 7.5, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.NOSE_FINENESS, 0.6, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.TAIL_FINENESS, 1.75, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.THICKNESS_TO_CHORD_TIP, 0.1, units='unitless') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MOMENT_RATIO, 0.5463, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.VerticalTail.MOMENT_RATIO, 5.2615, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.ASPECT_RATIO, 1.705, units='unitless') + prob.model.set_input_defaults( + Aircraft.Nacelle.CORE_DIAMETER_RATIO, 1.2205, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Nacelle.FINENESS, 1.3588, units='unitless') + # prob.model.set_input_defaults( + # Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0.0, units='unitless' + # ) + prob.model.set_input_defaults(Aircraft.Wing.FOLDED_SPAN, 118, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.VERTICAL_MOUNT_LOCATION, 0.5, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, 0.2597, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.WETTED_AREA_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, 65.0, units='deg') + prob.model.set_input_defaults( + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, 0.0, units='ft' + ) + prob.model.set_input_defaults( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, 0.0, units='unitless' + ) + # inputs from MassPremission + self.prob.model.set_input_defaults( + Aircraft.HorizontalTail.ROOT_CHORD, val=0.03836448, units='ft' + ) + # prob.model.set_input_defaults( + # Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, 0.107, units='unitless' + # ) + # prob.model.set_input_defaults( + # Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, 0.135, units='unitless' + # ) + # prob.model.set_input_defaults(Aircraft.Avionics.MASS, 1504.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.AirConditioning.MASS_COEFFICIENT, 1.155, units='unitless' + ) + # prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, 236.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Furnishings.MASS, 9114.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, 6.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, 100.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, 5.0, units='lbm' + ) + # prob.model.set_input_defaults( + # Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, 12.0, units='unitless' + # ) + prob.model.set_input_defaults(Aircraft.CrewPayload.CARGO_MASS, 0.0, units='lbm') + prob.model.set_input_defaults(Aircraft.CrewPayload.Design.CARGO_MASS, 0.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, 15000.0, units='lbm' + ) + prob.model.set_input_defaults(Aircraft.Engine.MASS_SPECIFIC, 0.178884, units='lbm/lbf') + prob.model.set_input_defaults(Aircraft.Nacelle.MASS_SPECIFIC, 2.5, units='lbm/ft**2') + prob.model.set_input_defaults( + Aircraft.Engine.PYLON_FACTOR, 1.25, units='unitless' + ) # PYL default and the GASP manual don't agree. Think(?) the default should be 0.7,and not 0. + prob.model.set_input_defaults(Aircraft.Engine.MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Propulsion.MISC_MASS_SCALER, 1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.WING_LOCATIONS, 0.0, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.MAIN_GEAR_LOCATION, 0, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.ASPECT_RATIO, 1.705, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.SWEEP, 0, units='deg') + prob.model.set_input_defaults( + Aircraft.HorizontalTail.MASS_COEFFICIENT, 0.124, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.VerticalTail.MASS_COEFFICIENT, 0.119, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.HorizontalTail.THICKNESS_TO_CHORD, 0.1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, 0, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.VerticalTail.THICKNESS_TO_CHORD, 0.1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, 1.0, units='unitless' + ) + prob.model.set_input_defaults( + Mission.Landing.LIFT_COEFFICIENT_MAX, 2.13421583, units='unitless' + ) # 2.13421583 is for landing. In GASP, CLMAX is computed for different phases. For takeoff, 1.94302452 + prob.model.set_input_defaults( + Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, 0.5, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, 16.5, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, 0, units='lbm' + ) + prob.model.set_input_defaults( + Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, 1, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.LandingGear.MASS_COEFFICIENT, 0.0520, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, 0.85, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuel.DENSITY, 6.687, units='lbm/galUS') + + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_MARGIN, 10.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, 0.035, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Fuselage.MASS_COEFFICIENT, 0.889, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MASS_SCALER, 1, units='unitless') + prob.model.set_input_defaults(Aircraft.HorizontalTail.MASS_SCALER, 1, units='unitless') + prob.model.set_input_defaults(Aircraft.VerticalTail.MASS_SCALER, 1, units='unitless') + prob.model.set_input_defaults(Aircraft.Fuselage.MASS_SCALER, 1, units='unitless') + prob.model.set_input_defaults(Aircraft.LandingGear.TOTAL_MASS_SCALER, 1, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.POD_MASS_SCALER, 1, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.STRUCTURAL_MASS_INCREMENT, 0, units='lbm') + prob.model.set_input_defaults(Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, 1, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MASS_COEFFICIENT, 75.78, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FOLD_MASS_COEFFICIENT, 0.15, units='unitless') + prob.model.set_input_defaults(Mission.Design.MACH, 0.8, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, 0.0001, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_CHORD_RATIO, 0.2, units='unitless') + prob.model.set_input_defaults(Aircraft.Furnishings.MASS_SCALER, 40.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, 0.827296853, units='unitless') + prob.model.set_input_defaults(Aircraft.Design.MAX_STRUCTURAL_SPEED, 402.5, units='mi/h') + prob.model.set_input_defaults(Aircraft.Wing.FLAP_SPAN_RATIO, 0.61, units='unitless') + prob.model.set_input_defaults(Aircraft.Nacelle.CLEARANCE_RATIO, 0.2, units='unitless') + + prob.model.set_input_defaults(Aircraft.APU.MASS, 710.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.Instruments.MASS_COEFFICIENT, 0.116, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, 0.107, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, 0.135, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Avionics.MASS, 3225.0, units='lbm') + prob.model.set_input_defaults(Aircraft.AntiIcing.MASS, 236.0, units='lbm') + prob.model.set_input_defaults( + Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, 3.0, units='lbm' + ) + # prob.model.set_input_defaults( + # Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, 12.0, units='unitless' + # ) + prob.model.set_input_defaults(Aircraft.Fuselage.LENGTH, 71.5245514, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + # prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.HorizontalTail.AREA, 0.001706279, units='ft**2') + prob.model.set_input_defaults(Aircraft.VerticalTail.AREA, 169.119629, units='ft**2') + prob.model.set_input_defaults(Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, 10.0, units='psi') + prob.model.set_input_defaults(Aircraft.Fuselage.HYDRAULIC_DIAMETER, 19.3650932, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.CABIN_AREA, 1283.5249, units='ft**2') + prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, 11.45, units='lbm' + ) + + # inputs to UsefulLoadMass + prob.model.set_input_defaults( + Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, 12.0, units='unitless' + ) + # prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Engine.SCALED_SLS_THRUST, [19580.1602], units='lbf') + prob.model.set_input_defaults(Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.7734, units='unitless') + + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING, 0.35, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL, 0.2, units='unitless' + ) + prob.model.set_input_defaults( + Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA, 5.0, units='lbm/ft**2' + ) + + setup_model_options(prob, options) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + """ + Testing GASP data case: + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS -- WPES = 2055 + Aircraft.LandingGear.TOTAL_MASS -- WLG = 7800 + Aircraft.LandingGear.MAIN_GEAR_MASS -- WMG = 6630 + Aircraft.Wing.MATERIAL_FACTOR -- SKNO = 1.19461238 + half_sweep -- SWC2 = 0.479839474 + Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS -- WPL = 33750 + payload_mass_des -- WPLDES = 33750 + payload_mass_max -- WPLMAX = 48750 + Aircraft.HorizontalTail.MASS -- WHT = 1 + Aircraft.VerticalTail.MASS -- WVT = 864 + Aircraft.Wing.HIGH_LIFT_MASS -- WHLDEV = 974.0 + Aircraft.Controls.TOTAL_MASS -- WFC = 2115 + Aircraft.Propulsion.TOTAL_ENGINE_MASS -- WEP = 7005. + Aircraft.Nacelle.MASS -- WNAC = 514.9 + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS -- WPES = 2153 + Aircraft.Engine.POSITION_FACTOR -- SKEPOS = 1.05 + Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS -- WPL = 33750 + Aircraft.Design.FIXED_EQUIPMENT_MASS - WFE = 20876. + Aircraft.Design.FIXED_USEFUL_LOAD -- WFUL = 5775. + Aircraft.Wing.MASS -- WW = 7645. + Aircraft.Strut.MASS -- WSTRUT = 0 + Aircraft.Wing.FOLD_MASS -- WWFOLD = 107.9 + Aircraft.Fuel.FUEL_SYSTEM_MASS -- WFSS = 1280.8 + fus_mass_full -- WX = 142354.9 + Aircraft.Fuselage.MASS -- WB = 27160 + Aircraft.Fuel.WING_VOLUME_DESIGN -- FVOLREQ = 731.6 + Mission.Summary.OPERATING_MASS -- OWE = 82982. + fus_mass_full -- WX = 121864 + OEM_wingfuel_mass -- WFWOWE(WFW_MAX) = 67018.2 + OEM_fuel_vol -- FVOLW_MAX = 1339.8 + payload_mass_max_fuel -- WPLMXF = 30423.2 + max_wingfuel_mass -- WFWMX = 30309.0 + Aircraft.Design.STRUCTURE_MASS -- WST = 45623. + Mission.Summary.FUEL_MASS -- WFADES = 33268.2 + Aircraft.Propulsion.MASS -- WP = 8592. + Mission.Summary.FUEL_MASS_REQUIRED -- WFAREQ = 36595.0 + fuel_mass_min -- WFAMIN = 18268.2 + fuel_mass.wingfuel_mass_min -- WFWMIN = 11982.2 + Aircraft.Fuel.TOTAL_CAPACITY -- WFAMAX = 33268.2 + """ + prob = self.prob + prob.run_model() + + tol = 1e-5 + + # outputs from SizeGroup + assert_near_equal(prob[Aircraft.Fuselage.AVG_DIAMETER], 38, tol) + + assert_near_equal(prob[Aircraft.Fuselage.LENGTH], 71.5245514, tol) + assert_near_equal(prob[Aircraft.Fuselage.WETTED_AREA], 4573.42578, tol) + assert_near_equal(prob[Aircraft.TailBoom.LENGTH], 71.5245514, tol) + + assert_near_equal(prob[Aircraft.Wing.AREA], 2142.85714286, tol) + assert_near_equal(prob[Aircraft.Wing.SPAN], 146.38501094, tol) + + assert_near_equal(prob[Aircraft.Wing.CENTER_CHORD], 22.97244452, tol) + assert_near_equal(prob[Aircraft.Wing.AVERAGE_CHORD], 16.2200522, tol) + assert_near_equal(prob[Aircraft.Wing.ROOT_CHORD], 20.33371617, tol) + assert_near_equal(prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.13596576, tol) + + assert_near_equal(prob[Aircraft.HorizontalTail.AREA], 0.00117064, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.SPAN], 0.04467601, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.ROOT_CHORD], 0.03836448, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 0.02808445, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MOMENT_ARM], 29.69074172, tol) + + assert_near_equal(prob[Aircraft.VerticalTail.AREA], 169.11964286, tol) + assert_near_equal(prob[Aircraft.VerticalTail.SPAN], 16.98084188, tol) + assert_near_equal(prob[Aircraft.VerticalTail.ROOT_CHORD], 14.58190052, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AVERAGE_CHORD], 10.67457744, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MOMENT_ARM], 27.82191598, tol) + + assert_near_equal(prob[Aircraft.Nacelle.AVG_DIAMETER], 5.33382144, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_LENGTH], 7.24759657, tol) + assert_near_equal(prob[Aircraft.Nacelle.SURFACE_AREA], 121.44575974, tol) + + # outputs from MassPremission + assert_near_equal(prob[Aircraft.LandingGear.TOTAL_MASS], 7800.0, tol) + assert_near_equal(prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6630.0, tol) + assert_near_equal(prob[Aircraft.Wing.MATERIAL_FACTOR], 1.19461189, tol) + assert_near_equal(prob['c_strut_braced'], 1, tol) + assert_near_equal(prob['c_gear_loc'], 0.95, tol) + assert_near_equal(prob[Aircraft.Engine.POSITION_FACTOR], 1.05, tol) + assert_near_equal(prob['half_sweep'], 0.47984874, tol) + assert_near_equal(prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(prob['payload_mass_des'], 33750.0, tol) + assert_near_equal(prob['payload_mass_max'], 48750, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MASS], 1.02401953, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MASS], 864.17404177, tol) + assert_near_equal(prob[Aircraft.Wing.HIGH_LIFT_MASS], 971.82476285, tol) + assert_near_equal(prob[Aircraft.Controls.TOTAL_MASS], 2114.98159054, tol) + assert_near_equal(prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 7005.15475443, tol) + assert_near_equal(prob[Aircraft.Nacelle.MASS], 303.61439936, tol) + assert_near_equal(prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 1686.626, tol) + assert_near_equal(prob[Aircraft.Engine.ADDITIONAL_MASS], 153.16770871, tol) + assert_near_equal(prob[Aircraft.Engine.POSITION_FACTOR], 1.05, tol) + assert_near_equal(prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 20876.477, tol) + assert_near_equal(prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5971.79463002, tol) + assert_near_equal(prob[Aircraft.Wing.SURFACE_CONTROL_MASS], 1986.25111783, tol) + + # BWBWingMassGroup + assert_near_equal(prob[Aircraft.Wing.MASS], 6959.72619224, tol) + assert_near_equal(prob[Aircraft.Strut.MASS], 0, tol) + assert_near_equal(prob[Aircraft.Wing.FOLD_MASS], 107.83351322, tol) + + # FuelMassGroup + # FuelSysAndFullFuselageMass + assert_near_equal(prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 1686.62563123, tol) + assert_near_equal(prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1316.24565033, tol) + assert_near_equal(prob['fus_mass_full'], 131150.22491506, tol) + # BWBFuselageMass + assert_near_equal(prob[Aircraft.Fuselage.MASS], 27159.28655493, tol) + # StructMass + assert_near_equal(prob[Aircraft.Design.STRUCTURE_MASS], 44470.83642382, tol) + # FuelMass + assert_near_equal(prob[Mission.Summary.FUEL_MASS], 34188.19870988, tol) + assert_near_equal(prob[Aircraft.Propulsion.MASS], 8627.73582218, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS_REQUIRED], 34188.19870988, tol) + assert_near_equal(prob['fuel_mass_min'], 19188.19870988, tol) + # FuelAndOEMOutputs + assert_near_equal(prob['OEM_wingfuel_mass'], 67938.19870988, tol) + assert_near_equal(prob['OEM_fuel_vol'], 1358.15975265, tol) + assert_near_equal(prob['payload_mass_max_fuel'], 29870.67005382, tol) + assert_near_equal(prob['volume_wingfuel_mass'], 30308.8688, tol) + assert_near_equal(prob['max_wingfuel_mass'], 30308.86876369, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 751.80590631, tol) + assert_near_equal(prob[Mission.Summary.OPERATING_MASS], 82061.80129012, tol) + # BodyTankCalculations + assert_near_equal(prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 3879.32994618, tol) + assert_near_equal(prob[Aircraft.Fuel.TOTAL_CAPACITY], 38067.52865606, tol) + assert_near_equal(prob['extra_fuel_volume'], 145.89808883, tol) + assert_near_equal(prob['max_extra_fuel_mass'], 7298.14981717, tol) + assert_near_equal(prob['wingfuel_mass_min'], 11890.0488927, tol) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/gasp_based/test/test_wing.py b/aviary/subsystems/mass/gasp_based/test/test_wing.py index 43f4814887..999a2ca90d 100644 --- a/aviary/subsystems/mass/gasp_based/test/test_wing.py +++ b/aviary/subsystems/mass/gasp_based/test/test_wing.py @@ -2,331 +2,319 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs -from aviary.subsystems.mass.gasp_based.wing import (WingMassGroup, - WingMassSolve, - WingMassTotal) +from aviary.subsystems.mass.gasp_based.wing import WingMassGroup, WingMassSolve, WingMassTotal +from aviary.subsystems.mass.gasp_based.wing import BWBWingMassSolve, BWBWingMassGroup +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Mission +from aviary.utils.aviary_values import AviaryValues class WingMassSolveTestCase(unittest.TestCase): - """this is the large single aisle 1 V3 test case""" + """this is the large single aisle 1 V3 test case.""" def setUp(self): - self.prob = om.Problem() - self.prob.model.add_subsystem("wingfuel", WingMassSolve( - aviary_options=get_option_defaults()), promotes=["*"]) + self.prob.model.add_subsystem('wingfuel', WingMassSolve(), promotes=['*']) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units='lbm') + self.prob.model.set_input_defaults('c_strut_braced', val=1.0, units='unitless') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units="lbm") - self.prob.model.set_input_defaults("c_strut_braced", val=1.0, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.POSITION_FACTOR, val=0.98, units="unitless") - self.prob.model.set_input_defaults("c_gear_loc", val=1.0, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Engine.POSITION_FACTOR, val=0.98, units='unitless' ) + self.prob.model.set_input_defaults('c_gear_loc', val=1.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') self.prob.model.set_input_defaults( - "half_sweep", val=0.3947081519145335, units="rad" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults('half_sweep', val=0.3947081519145335, units='rad') newton = self.prob.model.nonlinear_solver = om.NewtonSolver() - newton.options["atol"] = 1e-9 - newton.options["rtol"] = 1e-9 - newton.options["iprint"] = 2 - newton.options["maxiter"] = 10 - newton.options["solve_subsystems"] = True - newton.options["max_sub_solves"] = 10 - newton.options["err_on_non_converge"] = True - newton.options["reraise_child_analysiserror"] = False + newton.options['atol'] = 1e-9 + newton.options['rtol'] = 1e-9 + newton.options['iprint'] = 2 + newton.options['maxiter'] = 10 + newton.options['solve_subsystems'] = True + newton.options['max_sub_solves'] = 10 + newton.options['err_on_non_converge'] = True + newton.options['reraise_child_analysiserror'] = False newton.linesearch = om.BoundsEnforceLS() - newton.linesearch.options["bound_enforcement"] = "scalar" - newton.linesearch.options["iprint"] = -1 - newton.options["err_on_non_converge"] = False + newton.linesearch.options['bound_enforcement'] = 'scalar' + newton.linesearch.options['iprint'] = -1 + newton.options['err_on_non_converge'] = False self.prob.model.linear_solver = om.DirectSolver(assemble_jac=True) + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal(self.prob["isolated_wing_mass"], 15830, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 15830, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class WingMassSolveTestCase2(unittest.TestCase): def setUp(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() - prob.model.add_subsystem("wingfuel", WingMassSolve( - aviary_options=get_option_defaults()), promotes=["*"]) + prob.model.add_subsystem('wingfuel', WingMassSolve(), promotes=['*']) + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units='lbm') + prob.model.set_input_defaults('c_strut_braced', val=1.0, units='unitless') prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm") + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MATERIAL_FACTOR, val=1.2213, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.POSITION_FACTOR, val=0.98, units='unitless') + prob.model.set_input_defaults('c_gear_loc', val=1.0, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units="lbm") - prob.model.set_input_defaults("c_strut_braced", val=1.0, units="unitless") - prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless") - prob.model.set_input_defaults( - Aircraft.Wing.MATERIAL_FACTOR, val=1.2213, units="unitless") - prob.model.set_input_defaults( - Aircraft.Engine.POSITION_FACTOR, val=0.98, units="unitless") - prob.model.set_input_defaults("c_gear_loc", val=1.0, units="unitless") - prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless") - prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless") - prob.model.set_input_defaults( - "half_sweep", val=0.3947, units="rad") + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' + ) + prob.model.set_input_defaults('half_sweep', val=0.3947, units='rad') newton = prob.model.nonlinear_solver = om.NewtonSolver() - newton.options["atol"] = 1e-9 - newton.options["rtol"] = 1e-9 - newton.options["iprint"] = 2 - newton.options["maxiter"] = 10 - newton.options["solve_subsystems"] = True - newton.options["max_sub_solves"] = 10 - newton.options["err_on_non_converge"] = True - newton.options["reraise_child_analysiserror"] = False + newton.options['atol'] = 1e-9 + newton.options['rtol'] = 1e-9 + newton.options['iprint'] = 2 + newton.options['maxiter'] = 10 + newton.options['solve_subsystems'] = True + newton.options['max_sub_solves'] = 10 + newton.options['err_on_non_converge'] = True + newton.options['reraise_child_analysiserror'] = False newton.linesearch = om.BoundsEnforceLS() - newton.linesearch.options["bound_enforcement"] = "scalar" - newton.linesearch.options["iprint"] = -1 - newton.options["err_on_non_converge"] = False + newton.linesearch.options['bound_enforcement'] = 'scalar' + newton.linesearch.options['iprint'] = -1 + newton.options['err_on_non_converge'] = False prob.model.linear_solver = om.DirectSolver(assemble_jac=True) + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=5e-11, rtol=1e-12) class TotalWingMassTestCase1(unittest.TestCase): - """this is the large single aisle 1 V3 test case""" + """this is the large single aisle 1 V3 test case.""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "total", - WingMassTotal(aviary_options=get_option_defaults()), - promotes=["*"], + 'total', + WingMassTotal(), + promotes=['*'], ) - self.prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") + self.prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 assert_near_equal(self.prob[Aircraft.Wing.MASS], 15830.0, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class TotalWingMassTestCase2(unittest.TestCase): - """ - Has fold and no strut - """ + """Has fold and no strut.""" def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "total", - WingMassTotal(aviary_options=options), - promotes=["*"], + 'total', + WingMassTotal(), + promotes=['*'], ) + self.prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') self.prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=100, units="ft**2" + Aircraft.Wing.AREA, val=100, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDING_AREA, val=50, units="ft**2" + Aircraft.Wing.FOLDING_AREA, val=50, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal( - self.prob[Aircraft.Wing.MASS], 17413, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.MASS], 17413, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class TotalWingMassTestCase3(unittest.TestCase): - """ - Has strut and no fold - """ + """Has strut and no fold.""" def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "total", - WingMassTotal(aviary_options=options), - promotes=["*"], + 'total', + WingMassTotal(), + promotes=['*'], ) + self.prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') self.prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units="unitless" + Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal( - self.prob[Aircraft.Wing.MASS], 23745, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.MASS], 23745, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class TotalWingMassTestCase4(unittest.TestCase): - """ - Has fold and strut - """ + """Has fold and strut.""" def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem( - "total", WingMassTotal(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('total', WingMassTotal(), promotes=['*']) + self.prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') self.prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=100, units="ft**2" + Aircraft.Wing.AREA, val=100, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDING_AREA, val=50, units="ft**2" + Aircraft.Wing.FOLDING_AREA, val=50, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units="unitless" + Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal( - self.prob[Aircraft.Wing.MASS], 25328, tol - ) # not actual GASP value + assert_near_equal(self.prob[Aircraft.Wing.MASS], 25328, tol) # not actual GASP value - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class TotalWingMassTestCase5(unittest.TestCase): """ Test mass-weight conversion - No fold, no strut + No fold, no strut. """ def setUp(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): prob = om.Problem() prob.model.add_subsystem( - "total", - WingMassTotal(aviary_options=get_option_defaults()), - promotes=["*"], + 'total', + WingMassTotal(), + promotes=['*'], ) - prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") + prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') + + setup_model_options(prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')})) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class TotalWingMassTestCase6(unittest.TestCase): """ Test mass-weight conversion - Has fold and no strut + Has fold and no strut. """ def setUp(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): @@ -334,36 +322,39 @@ def test_case1(self): options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "total", - WingMassTotal(aviary_options=options), - promotes=["*"], + 'total', + WingMassTotal(), + promotes=['*'], ) + self.prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.AREA, val=100, units='ft**2') + self.prob.model.set_input_defaults(Aircraft.Wing.FOLDING_AREA, val=50, units='ft**2') self.prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=100, units="ft**2") - self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDING_AREA, val=50, units="ft**2") - self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless") + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' + ) + + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class TotalWingMassTestCase7(unittest.TestCase): """ Test mass-weight conversion - Has strut and no fold + Has strut and no fold. """ def setUp(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): @@ -371,32 +362,35 @@ def test_case1(self): options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') prob = om.Problem() prob.model.add_subsystem( - "total", - WingMassTotal(aviary_options=options), - promotes=["*"], + 'total', + WingMassTotal(), + promotes=['*'], ) - prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") - prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units="unitless") + prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units='unitless') + + setup_model_options(prob, options) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) class TotalWingMassTestCase8(unittest.TestCase): """ Test mass-weight conversion - Has fold and strut + Has fold and strut. """ def setUp(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.gasp_based.wing as wing + wing.GRAV_ENGLISH_LBM = 1.0 def test_case1(self): @@ -404,271 +398,361 @@ def test_case1(self): options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') prob = om.Problem() - prob.model.add_subsystem( - "total", WingMassTotal(aviary_options=options), promotes=["*"]) - prob.model.set_input_defaults( - "isolated_wing_mass", val=15830.0, units="lbm") + prob.model.add_subsystem('total', WingMassTotal(), promotes=['*']) + prob.model.set_input_defaults('isolated_wing_mass', val=15830.0, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.AREA, val=100, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.FOLDING_AREA, val=50, units='ft**2') prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=100, units="ft**2") - prob.model.set_input_defaults( - Aircraft.Wing.FOLDING_AREA, val=50, units="ft**2") - prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless") - prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units="unitless") + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units='unitless') + + setup_model_options(prob, options) + prob.setup(check=False, force_alloc_complex=True) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=2e-12, rtol=1e-12) class WingMassGroupTestCase1(unittest.TestCase): - """this is the large single aisle 1 V3 test case""" + """this is the large single aisle 1 V3 test case.""" def setUp(self): - self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingMassGroup(aviary_options=get_option_defaults()), - promotes=["*"], + 'group', + WingMassGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units='lbm') + self.prob.model.set_input_defaults('c_strut_braced', val=1.0, units='unitless') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units="lbm") - self.prob.model.set_input_defaults("c_strut_braced", val=1.0, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units="unitless" + Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.POSITION_FACTOR, val=0.98, units="unitless") - self.prob.model.set_input_defaults("c_gear_loc", val=1.0, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Engine.POSITION_FACTOR, val=0.98, units='unitless' ) + self.prob.model.set_input_defaults('c_gear_loc', val=1.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) - self.prob.model.set_input_defaults( - "half_sweep", val=0.3947081519145335, units="rad" + self.prob.model.set_input_defaults('half_sweep', val=0.3947081519145335, units='rad') + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) ) self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 assert_near_equal(self.prob[Aircraft.Wing.MASS], 15830, tol) - assert_near_equal(self.prob["isolated_wing_mass"], 15830, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 15830, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class WingMassGroupTestCase2(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingMassGroup(aviary_options=options), - promotes=["*"], + 'group', + WingMassGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units='lbm') + self.prob.model.set_input_defaults('c_strut_braced', val=1.0, units='unitless') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units="lbm") - self.prob.model.set_input_defaults("c_strut_braced", val=1.0, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units="unitless" + Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.POSITION_FACTOR, val=0.98, units="unitless") - self.prob.model.set_input_defaults("c_gear_loc", val=1.0, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Engine.POSITION_FACTOR, val=0.98, units='unitless' ) + self.prob.model.set_input_defaults('c_gear_loc', val=1.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults('half_sweep', val=0.3947081519145335, units='rad') self.prob.model.set_input_defaults( - "half_sweep", val=0.3947081519145335, units="rad" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=100, units="ft**2" + Aircraft.Wing.AREA, val=100, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDING_AREA, val=50, units="ft**2" + Aircraft.Wing.FOLDING_AREA, val=50, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal( - self.prob[Aircraft.Wing.MASS], 17417, tol - ) # not actual GASP value - assert_near_equal(self.prob["isolated_wing_mass"], 15830, tol) + assert_near_equal(self.prob[Aircraft.Wing.MASS], 17417, tol) # not actual GASP value + assert_near_equal(self.prob['isolated_wing_mass'], 15830, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class WingMassGroupTestCase3(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') self.prob = om.Problem() self.prob.model.add_subsystem( - "group", - WingMassGroup(aviary_options=options), - promotes=["*"], + 'group', + WingMassGroup(), + promotes=['*'], ) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units='lbm') + self.prob.model.set_input_defaults('c_strut_braced', val=1.0, units='unitless') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units="lbm") - self.prob.model.set_input_defaults("c_strut_braced", val=1.0, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units="unitless" + Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.POSITION_FACTOR, val=0.98, units="unitless") - self.prob.model.set_input_defaults("c_gear_loc", val=1.0, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Engine.POSITION_FACTOR, val=0.98, units='unitless' ) + self.prob.model.set_input_defaults('c_gear_loc', val=1.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') self.prob.model.set_input_defaults( - "half_sweep", val=0.3947081519145335, units="rad" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults('half_sweep', val=0.3947081519145335, units='rad') self.prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units="unitless" + Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 - assert_near_equal( - self.prob[Aircraft.Wing.MASS], 23750, tol - ) # not actual GASP value - assert_near_equal(self.prob["isolated_wing_mass"], 15830, tol) + assert_near_equal(self.prob[Aircraft.Wing.MASS], 23750, tol) # not actual GASP value + assert_near_equal(self.prob['isolated_wing_mass'], 15830, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) class WingMassGroupTestCase4(unittest.TestCase): def setUp(self): - options = get_option_defaults() options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') options.set_val(Aircraft.Wing.HAS_STRUT, val=True, units='unitless') self.prob = om.Problem() - self.prob.model.add_subsystem( - "group", WingMassGroup(aviary_options=options), promotes=["*"] - ) + self.prob.model.add_subsystem('group', WingMassGroup(), promotes=['*']) + self.prob.model.set_input_defaults(Mission.Design.GROSS_MASS, val=175400, units='lbm') + self.prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units='lbm') + self.prob.model.set_input_defaults('c_strut_braced', val=1.0, units='unitless') self.prob.model.set_input_defaults( - Mission.Design.GROSS_MASS, val=175400, units="lbm" + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.HIGH_LIFT_MASS, val=3645, units="lbm") - self.prob.model.set_input_defaults("c_strut_braced", val=1.0, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.893, units="unitless") - self.prob.model.set_input_defaults( - Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units="unitless" + Aircraft.Wing.MASS_COEFFICIENT, val=102.5, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units="unitless" + Aircraft.Wing.MATERIAL_FACTOR, val=1.2213063198183813, units='unitless' ) self.prob.model.set_input_defaults( - Aircraft.Engine.POSITION_FACTOR, val=0.98, units="unitless") - self.prob.model.set_input_defaults("c_gear_loc", val=1.0, units="unitless") - self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units="ft") - self.prob.model.set_input_defaults( - Aircraft.Wing.TAPER_RATIO, val=0.33, units="unitless" + Aircraft.Engine.POSITION_FACTOR, val=0.98, units='unitless' ) + self.prob.model.set_input_defaults('c_gear_loc', val=1.0, units='unitless') + self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=117.8, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, val=0.33, units='unitless') self.prob.model.set_input_defaults( - Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units="unitless" + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15, units='unitless' ) + self.prob.model.set_input_defaults('half_sweep', val=0.3947081519145335, units='rad') self.prob.model.set_input_defaults( - "half_sweep", val=0.3947081519145335, units="rad" - ) - self.prob.model.set_input_defaults( - Aircraft.Wing.AREA, val=100, units="ft**2" + Aircraft.Wing.AREA, val=100, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLDING_AREA, val=50, units="ft**2" + Aircraft.Wing.FOLDING_AREA, val=50, units='ft**2' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units="unitless" + Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2, units='unitless' ) # not actual GASP value self.prob.model.set_input_defaults( - Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units="unitless" + Aircraft.Strut.MASS_COEFFICIENT, val=0.5, units='unitless' ) # not actual GASP value + setup_model_options(self.prob, options) + self.prob.setup(check=False, force_alloc_complex=True) def test_case1(self): - self.prob.run_model() tol = 5e-4 + assert_near_equal(self.prob[Aircraft.Wing.MASS], 25333, tol) # not actual GASP value + assert_near_equal(self.prob['isolated_wing_mass'], 15830, tol) + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + +class BWBWingMassSolveTestCase(unittest.TestCase): + """this is the large single aisle 1 V3 test case""" + + def setUp(self): + prob = self.prob = om.Problem() + prob.model.add_subsystem('wingfuel', BWBWingMassSolve(), promotes=['*']) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, 1068.88854499, units='lbm') + prob.model.set_input_defaults('c_strut_braced', 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.77335889, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.MASS_COEFFICIENT, 75.78, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MATERIAL_FACTOR, 1.19461189, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.POSITION_FACTOR, 1.05, units='unitless') + prob.model.set_input_defaults('c_gear_loc', 0.95, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults('half_sweep', 0.479839474, units='rad') + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING, 0.35, units='unitless' + ) + + newton = self.prob.model.nonlinear_solver = om.NewtonSolver() + newton.options['atol'] = 1e-9 + newton.options['rtol'] = 1e-9 + newton.options['iprint'] = 2 + newton.options['maxiter'] = 10 + newton.options['solve_subsystems'] = True + newton.options['max_sub_solves'] = 10 + newton.options['err_on_non_converge'] = True + newton.options['reraise_child_analysiserror'] = False + newton.linesearch = om.BoundsEnforceLS() + newton.linesearch.options['bound_enforcement'] = 'scalar' + newton.linesearch.options['iprint'] = -1 + newton.options['err_on_non_converge'] = False + + prob.model.linear_solver = om.DirectSolver(assemble_jac=True) + + setup_model_options( + self.prob, AviaryValues({Aircraft.Engine.NUM_ENGINES: ([2], 'unitless')}) + ) + + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 assert_near_equal( - self.prob[Aircraft.Wing.MASS], 25333, tol - ) # not actual GASP value - assert_near_equal(self.prob["isolated_wing_mass"], 15830, tol) + self.prob['isolated_wing_mass'], 6946.57966315, tol + ) # 7645.-107.9-682.6=6854.5 + + partial_data = self.prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) + + +@use_tempdirs +class BWBWingMassGroupTest(unittest.TestCase): + """this is the large single aisle 1 V3 test case""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Wing.HAS_FOLD, val=True, units='unitless') + options.set_val(Aircraft.Engine.NUM_ENGINES, val=[2], units='unitless') + + prob = self.prob = om.Problem() + prob.model.add_subsystem( + 'group', + BWBWingMassGroup(), + promotes=['*'], + ) + + prob.model.set_input_defaults(Mission.Design.GROSS_MASS, 150000, units='lbm') + prob.model.set_input_defaults(Aircraft.Wing.HIGH_LIFT_MASS, 1068.88854499, units='lbm') + prob.model.set_input_defaults('c_strut_braced', 1.0, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.ULTIMATE_LOAD_FACTOR, 3.77335889, units='unitless' + ) + prob.model.set_input_defaults(Aircraft.Wing.MASS_COEFFICIENT, 75.78, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.MATERIAL_FACTOR, 1.19461189, units='unitless') + prob.model.set_input_defaults(Aircraft.Engine.POSITION_FACTOR, 1.05, units='unitless') + prob.model.set_input_defaults('c_gear_loc', 0.95, units='unitless') + prob.model.set_input_defaults(Aircraft.Wing.SPAN, 146.38501, units='ft') + prob.model.set_input_defaults(Aircraft.Fuselage.AVG_DIAMETER, 38.0, units='ft') + prob.model.set_input_defaults(Aircraft.Wing.TAPER_RATIO, 0.27444, units='unitless') + prob.model.set_input_defaults( + Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, 0.165, units='unitless' + ) + prob.model.set_input_defaults('half_sweep', 0.479839474, units='rad') + prob.model.set_input_defaults(Aircraft.Wing.AREA, 2142.85718, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.FOLDING_AREA, 224.82529025, units='ft**2') + prob.model.set_input_defaults(Aircraft.Wing.FOLD_MASS_COEFFICIENT, 0.15, units='unitless') + prob.model.set_input_defaults( + Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING, 0.35, units='unitless' + ) + + setup_model_options(self.prob, options) + prob.setup(check=False, force_alloc_complex=True) + + def test_case1(self): + self.prob.run_model() + + tol = 1e-7 + assert_near_equal(self.prob[Aircraft.Wing.MASS], 7055.90333649, tol) + assert_near_equal(self.prob[Aircraft.Strut.MASS], 0, tol) + assert_near_equal(self.prob[Aircraft.Wing.FOLD_MASS], 109.32367334, tol) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-8, rtol=1e-8) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/mass/gasp_based/wing.py b/aviary/subsystems/mass/gasp_based/wing.py index 0c9954abbb..c94fab0973 100644 --- a/aviary/subsystems/mass/gasp_based/wing.py +++ b/aviary/subsystems/mass/gasp_based/wing.py @@ -2,85 +2,73 @@ import openmdao.api as om from aviary.constants import GRAV_ENGLISH_LBM -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Mission class WingMassSolve(om.ImplicitComponent): """ - Computation of isolated wing mass, namely wing mass including high lift devices + Computation of isolated wing mass, namely wing mass including high lift devices (but excluding struts and fold effects) using a nonlinear solver. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Mission.Design.GROSS_MASS, val=175400) - add_aviary_input(self, Aircraft.Wing.HIGH_LIFT_MASS, val=3645) + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.HIGH_LIFT_MASS, units='lbm') self.add_input( - "c_strut_braced", + 'c_strut_braced', val=1.00000001, - units="unitless", - desc="SKSTR: reduction in bending moment factor for strut braced wing", - ) - add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, val=3.75) - add_aviary_input(self, Aircraft.Wing.MASS_COEFFICIENT, val=102.5) - add_aviary_input(self, Aircraft.Wing.MATERIAL_FACTOR, val=1.22130632) - add_aviary_input(self, Aircraft.Engine.POSITION_FACTOR, - val=np.full(num_engine_type, 0.98)) + units='unitless', + desc='SKSTR: reduction in bending moment factor for strut braced wing', + ) + add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Wing.MATERIAL_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Engine.POSITION_FACTOR, shape=num_engine_type) self.add_input( - "c_gear_loc", + 'c_gear_loc', val=1.000000001, - units="unitless", - desc="SKGEAR: landing gear location factor", + units='unitless', + desc='SKGEAR: landing gear location factor', ) - add_aviary_input(self, Aircraft.Wing.SPAN, val=117.8) - add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, val=0.33) - add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, val=0.15) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') self.add_input( - "half_sweep", - val=0.3947081519, - units="rad", - desc="SWC2: wing half-chord sweep angle", + 'half_sweep', val=0.3947081519, units='rad', desc='SWC2: wing half-chord sweep angle' ) self.add_output( - "isolated_wing_mass", + 'isolated_wing_mass', val=17670, - units="lbm", - desc="WW: wing mass including high lift devices (but excluding struts and fold effects)", + units='lbm', + desc='WW: wing mass including high lift devices (but excluding struts and fold effects)', ) - self.declare_partials("isolated_wing_mass", "*") + self.declare_partials('isolated_wing_mass', '*') def apply_nonlinear(self, inputs, outputs, residuals): - gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM high_lift_wt = inputs[Aircraft.Wing.HIGH_LIFT_MASS] * GRAV_ENGLISH_LBM - c_strut_braced = inputs["c_strut_braced"] + c_strut_braced = inputs['c_strut_braced'] ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] c_wing_mass = inputs[Aircraft.Wing.MASS_COEFFICIENT] c_material = inputs[Aircraft.Wing.MATERIAL_FACTOR] c_eng_pos = inputs[Aircraft.Engine.POSITION_FACTOR] - c_gear_loc = inputs["c_gear_loc"] + c_gear_loc = inputs['c_gear_loc'] wingspan = inputs[Aircraft.Wing.SPAN] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] - half_sweep = inputs["half_sweep"] + half_sweep = inputs['half_sweep'] - isolated_wing_wt = outputs["isolated_wing_mass"] * GRAV_ENGLISH_LBM + isolated_wing_wt = outputs['isolated_wing_mass'] * GRAV_ENGLISH_LBM - foo = ( - c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt) - ) ** 0.757 + foo = (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) ** 0.757 wing_wt_guess = ( c_wing_mass * c_material @@ -89,46 +77,28 @@ def apply_nonlinear(self, inputs, outputs, residuals): * foo * wingspan**1.049 * (1.0 + taper_ratio) ** 0.4 - ) / ( - 100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535 - ) + high_lift_wt + ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + high_lift_wt - residuals["isolated_wing_mass"] = ( - isolated_wing_wt - wing_wt_guess) / GRAV_ENGLISH_LBM + residuals['isolated_wing_mass'] = (isolated_wing_wt - wing_wt_guess) / GRAV_ENGLISH_LBM def linearize(self, inputs, outputs, J): - gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM - high_lift_wt = inputs[Aircraft.Wing.HIGH_LIFT_MASS] * GRAV_ENGLISH_LBM - c_strut_braced = inputs["c_strut_braced"] + c_strut_braced = inputs['c_strut_braced'] ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] c_wing_mass = inputs[Aircraft.Wing.MASS_COEFFICIENT] c_material = inputs[Aircraft.Wing.MATERIAL_FACTOR] c_eng_pos = inputs[Aircraft.Engine.POSITION_FACTOR] - c_gear_loc = inputs["c_gear_loc"] + c_gear_loc = inputs['c_gear_loc'] wingspan = inputs[Aircraft.Wing.SPAN] taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] - half_sweep = inputs["half_sweep"] + half_sweep = inputs['half_sweep'] - isolated_wing_wt = outputs["isolated_wing_mass"] * GRAV_ENGLISH_LBM + isolated_wing_wt = outputs['isolated_wing_mass'] * GRAV_ENGLISH_LBM - foo = ( - c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt) - ) ** 0.757 - wing_wt_guess = ( - c_wing_mass - * c_material - * c_eng_pos - * c_gear_loc - * foo - * wingspan**1.049 - * (1.0 + taper_ratio) ** 0.4 - ) / ( - 100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535 - ) + high_lift_wt + foo = (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) ** 0.757 - J["isolated_wing_mass", Mission.Design.GROSS_MASS] = ( + J['isolated_wing_mass', Mission.Design.GROSS_MASS] = ( -( c_wing_mass * c_material @@ -139,13 +109,12 @@ def linearize(self, inputs, outputs, J): ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) * 0.757 - * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) - ** (-0.243) + * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) ** (-0.243) * c_strut_braced * ULF ) - J["isolated_wing_mass", Aircraft.Wing.HIGH_LIFT_MASS] = -1 - J["isolated_wing_mass", "c_strut_braced"] = ( + J['isolated_wing_mass', Aircraft.Wing.HIGH_LIFT_MASS] = -1 + J['isolated_wing_mass', 'c_strut_braced'] = ( -( c_wing_mass * c_material @@ -156,13 +125,12 @@ def linearize(self, inputs, outputs, J): ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) * 0.757 - * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) - ** (-0.243) + * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) ** (-0.243) * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt) / GRAV_ENGLISH_LBM ) - J["isolated_wing_mass", Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ( + J['isolated_wing_mass', Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ( -( c_wing_mass * c_material @@ -173,13 +141,12 @@ def linearize(self, inputs, outputs, J): ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) * 0.757 - * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) - ** (-0.243) + * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) ** (-0.243) * c_strut_braced * (gross_wt_initial - 0.8 * isolated_wing_wt) / GRAV_ENGLISH_LBM ) - J["isolated_wing_mass", Aircraft.Wing.MASS_COEFFICIENT] = -( + J['isolated_wing_mass', Aircraft.Wing.MASS_COEFFICIENT] = -( c_material * c_eng_pos * c_gear_loc @@ -188,7 +155,7 @@ def linearize(self, inputs, outputs, J): * (1.0 + taper_ratio) ** 0.4 / GRAV_ENGLISH_LBM ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) - J["isolated_wing_mass", Aircraft.Wing.MATERIAL_FACTOR] = -( + J['isolated_wing_mass', Aircraft.Wing.MATERIAL_FACTOR] = -( c_wing_mass * c_eng_pos * c_gear_loc @@ -197,7 +164,7 @@ def linearize(self, inputs, outputs, J): * (1.0 + taper_ratio) ** 0.4 / GRAV_ENGLISH_LBM ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) - J["isolated_wing_mass", Aircraft.Engine.POSITION_FACTOR] = -( + J['isolated_wing_mass', Aircraft.Engine.POSITION_FACTOR] = -( c_wing_mass * c_material * c_gear_loc @@ -206,7 +173,7 @@ def linearize(self, inputs, outputs, J): * (1.0 + taper_ratio) ** 0.4 / GRAV_ENGLISH_LBM ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) - J["isolated_wing_mass", "c_gear_loc"] = -( + J['isolated_wing_mass', 'c_gear_loc'] = -( c_wing_mass * c_material * c_eng_pos @@ -215,7 +182,7 @@ def linearize(self, inputs, outputs, J): * (1.0 + taper_ratio) ** 0.4 / GRAV_ENGLISH_LBM ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) - J["isolated_wing_mass", Aircraft.Wing.SPAN] = ( + J['isolated_wing_mass', Aircraft.Wing.SPAN] = ( -1.049 * ( c_wing_mass @@ -229,7 +196,7 @@ def linearize(self, inputs, outputs, J): / GRAV_ENGLISH_LBM / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) ) - J["isolated_wing_mass", Aircraft.Wing.TAPER_RATIO] = ( + J['isolated_wing_mass', Aircraft.Wing.TAPER_RATIO] = ( -0.4 * ( c_wing_mass @@ -243,7 +210,7 @@ def linearize(self, inputs, outputs, J): / GRAV_ENGLISH_LBM / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) ) - J["isolated_wing_mass", Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + J['isolated_wing_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( 0.4 * ( c_wing_mass @@ -257,7 +224,7 @@ def linearize(self, inputs, outputs, J): / GRAV_ENGLISH_LBM / (100000.0 * tc_ratio_root**1.4 * np.cos(half_sweep) ** 1.535) ) - J["isolated_wing_mass", "half_sweep"] = ( + J['isolated_wing_mass', 'half_sweep'] = ( 1.535 * ( c_wing_mass @@ -272,7 +239,7 @@ def linearize(self, inputs, outputs, J): / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 2.535) * (-np.sin(half_sweep)) ) - J["isolated_wing_mass", "isolated_wing_mass"] = ( + J['isolated_wing_mass', 'isolated_wing_mass'] = ( 1 - ( c_wing_mass @@ -284,8 +251,7 @@ def linearize(self, inputs, outputs, J): ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) * 0.757 - * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) - ** (-0.243) + * (c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt)) ** (-0.243) * (-0.8) * c_strut_braced * ULF @@ -293,52 +259,52 @@ def linearize(self, inputs, outputs, J): class WingMassTotal(om.ExplicitComponent): - """ - Computation of wing mass, strut mass, and wing fold mass. - """ + """Computation of wing mass, strut mass, and wing fold mass.""" def initialize(self): - - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) def setup(self): - self.add_input( - "isolated_wing_mass", + 'isolated_wing_mass', val=1500, - units="lbm", - desc="WW: wing mass including high lift devices (but excluding struts and fold effects)", + units='lbm', + desc='WW: wing mass including high lift devices (but excluding struts and fold effects)', ) - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): - add_aviary_input(self, Aircraft.Strut.MASS_COEFFICIENT, val=0.000000000001) - - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless') == True: + if self.options[Aircraft.Wing.HAS_STRUT]: + add_aviary_input(self, Aircraft.Strut.MASS_COEFFICIENT, units='unitless') - add_aviary_input(self, Aircraft.Wing.AREA, val=100) - add_aviary_input(self, Aircraft.Wing.FOLDING_AREA, val=50) - add_aviary_input(self, Aircraft.Wing.FOLD_MASS_COEFFICIENT, val=0.2) + if self.options[Aircraft.Wing.HAS_FOLD]: + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.FOLDING_AREA, units='ft**2') + add_aviary_input(self, Aircraft.Wing.FOLD_MASS_COEFFICIENT, units='unitless') - add_aviary_output(self, Aircraft.Wing.MASS, val=0) - add_aviary_output(self, Aircraft.Strut.MASS, val=0) - add_aviary_output(self, Aircraft.Wing.FOLD_MASS, val=0) + add_aviary_output(self, Aircraft.Wing.MASS, units='lbm') + add_aviary_output(self, Aircraft.Strut.MASS, units='lbm') + add_aviary_output(self, Aircraft.Wing.FOLD_MASS, units='lbm') - self.declare_partials(Aircraft.Wing.MASS, "*") - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): - self.declare_partials(Aircraft.Strut.MASS, [ - Aircraft.Strut.MASS_COEFFICIENT, "isolated_wing_mass"]) - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): - self.declare_partials(Aircraft.Wing.FOLD_MASS, [ - Aircraft.Wing.AREA, Aircraft.Wing.FOLDING_AREA, Aircraft.Wing.FOLD_MASS_COEFFICIENT, "isolated_wing_mass"]) + self.declare_partials(Aircraft.Wing.MASS, '*') + if self.options[Aircraft.Wing.HAS_STRUT]: + self.declare_partials( + Aircraft.Strut.MASS, [Aircraft.Strut.MASS_COEFFICIENT, 'isolated_wing_mass'] + ) + if self.options[Aircraft.Wing.HAS_FOLD]: + self.declare_partials( + Aircraft.Wing.FOLD_MASS, + [ + Aircraft.Wing.AREA, + Aircraft.Wing.FOLDING_AREA, + Aircraft.Wing.FOLD_MASS_COEFFICIENT, + 'isolated_wing_mass', + ], + ) def compute(self, inputs, outputs): + isolated_wing_wt = inputs['isolated_wing_mass'] * GRAV_ENGLISH_LBM - isolated_wing_wt = inputs["isolated_wing_mass"] * GRAV_ENGLISH_LBM - - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): + if self.options[Aircraft.Wing.HAS_STRUT]: c_strut_mass = inputs[Aircraft.Strut.MASS_COEFFICIENT] strut_wt = c_strut_mass * isolated_wing_wt @@ -347,7 +313,7 @@ def compute(self, inputs, outputs): else: outputs[Aircraft.Strut.MASS] = strut_wt = 0 - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): + if self.options[Aircraft.Wing.HAS_FOLD]: wing_area = inputs[Aircraft.Wing.AREA] folding_area = inputs[Aircraft.Wing.FOLDING_AREA] c_wing_fold = inputs[Aircraft.Wing.FOLD_MASS_COEFFICIENT] @@ -364,19 +330,18 @@ def compute(self, inputs, outputs): outputs[Aircraft.Wing.MASS] = total_wing_wt / GRAV_ENGLISH_LBM def compute_partials(self, inputs, J): + isolated_wing_wt = inputs['isolated_wing_mass'] * GRAV_ENGLISH_LBM - isolated_wing_wt = inputs["isolated_wing_mass"] * GRAV_ENGLISH_LBM - - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): + if self.options[Aircraft.Wing.HAS_STRUT]: c_strut_mass = inputs[Aircraft.Strut.MASS_COEFFICIENT] - J[Aircraft.Wing.MASS, Aircraft.Strut.MASS_COEFFICIENT] = \ - J[Aircraft.Strut.MASS, Aircraft.Strut.MASS_COEFFICIENT] = \ - isolated_wing_wt / GRAV_ENGLISH_LBM - J[Aircraft.Wing.MASS, "isolated_wing_mass"] = 1 + c_strut_mass - J[Aircraft.Strut.MASS, "isolated_wing_mass"] = c_strut_mass + J[Aircraft.Wing.MASS, Aircraft.Strut.MASS_COEFFICIENT] = J[ + Aircraft.Strut.MASS, Aircraft.Strut.MASS_COEFFICIENT + ] = isolated_wing_wt / GRAV_ENGLISH_LBM + J[Aircraft.Wing.MASS, 'isolated_wing_mass'] = 1 + c_strut_mass + J[Aircraft.Strut.MASS, 'isolated_wing_mass'] = c_strut_mass - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless'): + if self.options[Aircraft.Wing.HAS_FOLD]: wing_area = inputs[Aircraft.Wing.AREA] folding_area = inputs[Aircraft.Wing.FOLDING_AREA] c_wing_fold = inputs[Aircraft.Wing.FOLD_MASS_COEFFICIENT] @@ -384,105 +349,452 @@ def compute_partials(self, inputs, J): wt_per_area = isolated_wing_wt / wing_area temp_fold_wt = folding_area * wt_per_area - J[Aircraft.Wing.MASS, Aircraft.Wing.AREA] = \ - J[Aircraft.Wing.FOLD_MASS, Aircraft.Wing.AREA] = ( - -c_wing_fold * folding_area * isolated_wing_wt / wing_area**2 / GRAV_ENGLISH_LBM - ) - J[Aircraft.Wing.MASS, Aircraft.Wing.FOLDING_AREA] = \ - J[Aircraft.Wing.FOLD_MASS, Aircraft.Wing.FOLDING_AREA] = \ - c_wing_fold * wt_per_area / GRAV_ENGLISH_LBM - J[Aircraft.Wing.MASS, Aircraft.Wing.FOLD_MASS_COEFFICIENT] = \ - J[Aircraft.Wing.FOLD_MASS, Aircraft.Wing.FOLD_MASS_COEFFICIENT] = \ - temp_fold_wt / GRAV_ENGLISH_LBM - J[Aircraft.Wing.MASS, "isolated_wing_mass"] = ( - 1 + c_wing_fold * folding_area / wing_area + J[Aircraft.Wing.MASS, Aircraft.Wing.AREA] = J[ + Aircraft.Wing.FOLD_MASS, Aircraft.Wing.AREA + ] = -c_wing_fold * folding_area * isolated_wing_wt / wing_area**2 / GRAV_ENGLISH_LBM + J[Aircraft.Wing.MASS, Aircraft.Wing.FOLDING_AREA] = J[ + Aircraft.Wing.FOLD_MASS, Aircraft.Wing.FOLDING_AREA + ] = c_wing_fold * wt_per_area / GRAV_ENGLISH_LBM + J[Aircraft.Wing.MASS, Aircraft.Wing.FOLD_MASS_COEFFICIENT] = J[ + Aircraft.Wing.FOLD_MASS, Aircraft.Wing.FOLD_MASS_COEFFICIENT + ] = temp_fold_wt / GRAV_ENGLISH_LBM + J[Aircraft.Wing.MASS, 'isolated_wing_mass'] = 1 + c_wing_fold * folding_area / wing_area + J[Aircraft.Wing.FOLD_MASS, 'isolated_wing_mass'] = ( + c_wing_fold * folding_area / wing_area ) - J[Aircraft.Wing.FOLD_MASS, "isolated_wing_mass"] = c_wing_fold * \ - folding_area / wing_area - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless') and \ - self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): - - J[Aircraft.Wing.MASS, "isolated_wing_mass"] = ( + if self.options[Aircraft.Wing.HAS_FOLD] and self.options[Aircraft.Wing.HAS_STRUT]: + J[Aircraft.Wing.MASS, 'isolated_wing_mass'] = ( 1 + c_wing_fold * folding_area / wing_area + c_strut_mass ) if ( - self.options["aviary_options"].get_val( - Aircraft.Wing.HAS_STRUT, units='unitless') == False - and self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless') == False + self.options[Aircraft.Wing.HAS_STRUT] is False + and self.options[Aircraft.Wing.HAS_FOLD] is False ): - J[Aircraft.Wing.MASS, "isolated_wing_mass"] = 1 + J[Aircraft.Wing.MASS, 'isolated_wing_mass'] = 1 -class WingMassGroup(om.Group): +class BWBWingMassSolve(om.ImplicitComponent): """ - Group to compute wing mass for GASP-based mass. + Computation of isolated wing mass, namely wing mass including high lift devices + (but excluding struts and fold effects) using a nonlinear solver. """ def initialize(self): + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + + def setup(self): + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) + + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.HIGH_LIFT_MASS, units='lbm') + self.add_input( + 'c_strut_braced', + val=1.00000001, + units='unitless', + desc='SKSTR: reduction in bending moment factor for strut braced wing', + ) + add_aviary_input(self, Aircraft.Wing.ULTIMATE_LOAD_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Wing.MASS_COEFFICIENT, units='unitless') + add_aviary_input(self, Aircraft.Wing.MATERIAL_FACTOR, units='unitless') + add_aviary_input(self, Aircraft.Engine.POSITION_FACTOR, shape=num_engine_type) + self.add_input( + 'c_gear_loc', + val=1.000000001, + units='unitless', + desc='SKGEAR: landing gear location factor', + ) + add_aviary_input(self, Aircraft.Wing.SPAN, units='ft') + add_aviary_input(self, Aircraft.Fuselage.AVG_DIAMETER, units='ft') + add_aviary_input(self, Aircraft.Wing.TAPER_RATIO, units='unitless') + add_aviary_input(self, Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, units='unitless') + self.add_input( + 'half_sweep', val=0.3947081519, units='rad', desc='SWC2: wing half-chord sweep angle' + ) + add_aviary_input( + self, Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING, units='unitless' + ) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + self.add_output( + 'isolated_wing_mass', + val=12973.96759, + units='lbm', + desc='WW: wing mass including high lift devices (but excluding struts and fold effects)', ) - def setup(self): + self.declare_partials('isolated_wing_mass', '*') + + def apply_nonlinear(self, inputs, outputs, residuals): + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + high_lift_wt = inputs[Aircraft.Wing.HIGH_LIFT_MASS] * GRAV_ENGLISH_LBM + c_strut_braced = inputs['c_strut_braced'] + ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] + c_wing_mass = inputs[Aircraft.Wing.MASS_COEFFICIENT] + c_material = inputs[Aircraft.Wing.MATERIAL_FACTOR] + c_eng_pos = inputs[Aircraft.Engine.POSITION_FACTOR] + c_gear_loc = inputs['c_gear_loc'] + wingspan = inputs[Aircraft.Wing.SPAN] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + half_sweep = inputs['half_sweep'] + CLBqCLW = inputs[Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING] - aviary_options = self.options['aviary_options'] + isolated_wing_wt = outputs['isolated_wing_mass'] * GRAV_ENGLISH_LBM + foo_numer = c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt) + foo_denom = 1.0 + CLBqCLW + foo = (foo_numer / foo_denom) ** 0.757 + wingspan_mod = wingspan - cabin_width + wing_wt_guess = ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + high_lift_wt + + residuals['isolated_wing_mass'] = (isolated_wing_wt - wing_wt_guess) / GRAV_ENGLISH_LBM + + def linearize(self, inputs, outputs, J): + gross_wt_initial = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + high_lift_wt = inputs[Aircraft.Wing.HIGH_LIFT_MASS] * GRAV_ENGLISH_LBM + c_strut_braced = inputs['c_strut_braced'] + ULF = inputs[Aircraft.Wing.ULTIMATE_LOAD_FACTOR] + c_wing_mass = inputs[Aircraft.Wing.MASS_COEFFICIENT] + c_material = inputs[Aircraft.Wing.MATERIAL_FACTOR] + c_eng_pos = inputs[Aircraft.Engine.POSITION_FACTOR] + c_gear_loc = inputs['c_gear_loc'] + wingspan = inputs[Aircraft.Wing.SPAN] + cabin_width = inputs[Aircraft.Fuselage.AVG_DIAMETER] + taper_ratio = inputs[Aircraft.Wing.TAPER_RATIO] + tc_ratio_root = inputs[Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] + half_sweep = inputs['half_sweep'] + CLBqCLW = inputs[Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING] + + isolated_wing_wt = outputs['isolated_wing_mass'] * GRAV_ENGLISH_LBM + + foo_numer = c_strut_braced * ULF * (gross_wt_initial - 0.8 * isolated_wing_wt) + foo_denom = 1.0 + CLBqCLW + foo = (foo_numer / foo_denom) ** 0.757 + wingspan_mod = wingspan - cabin_width # modification for BWB + wing_wt_guess = ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + high_lift_wt + + J['isolated_wing_mass', Mission.Design.GROSS_MASS] = ( + -( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + * 0.757 + * (foo_numer / foo_denom) ** (-0.243) + * c_strut_braced + / foo_denom + * ULF + ) + J['isolated_wing_mass', Aircraft.Wing.HIGH_LIFT_MASS] = -1 + J['isolated_wing_mass', 'c_strut_braced'] = ( + -( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + * 0.757 + * (foo_numer / foo_denom) ** (-0.243) + * ULF + * (gross_wt_initial - 0.8 * isolated_wing_wt) + / foo_denom + / GRAV_ENGLISH_LBM + ) + J['isolated_wing_mass', Aircraft.Wing.ULTIMATE_LOAD_FACTOR] = ( + -( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + * 0.757 + * (foo_numer / foo_denom) ** (-0.243) + * c_strut_braced + * (gross_wt_initial - 0.8 * isolated_wing_wt) + / foo_denom + / GRAV_ENGLISH_LBM + ) + J['isolated_wing_mass', Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING] = ( + ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + * 0.757 + * (foo_numer / foo_denom) ** (-0.243) + * foo_numer + / foo_denom**2 + / GRAV_ENGLISH_LBM + ) + J['isolated_wing_mass', Aircraft.Wing.MASS_COEFFICIENT] = -( + c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + / GRAV_ENGLISH_LBM + ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + J['isolated_wing_mass', Aircraft.Wing.MATERIAL_FACTOR] = -( + c_wing_mass + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + / GRAV_ENGLISH_LBM + ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + J['isolated_wing_mass', Aircraft.Engine.POSITION_FACTOR] = -( + c_wing_mass + * c_material + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + / GRAV_ENGLISH_LBM + ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + J['isolated_wing_mass', 'c_gear_loc'] = -( + c_wing_mass + * c_material + * c_eng_pos + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + / GRAV_ENGLISH_LBM + ) / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + J['isolated_wing_mass', Aircraft.Wing.SPAN] = ( + -1.049 + * ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**0.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / GRAV_ENGLISH_LBM + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + ) + J['isolated_wing_mass', Aircraft.Fuselage.AVG_DIAMETER] = ( + 1.049 + * ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**0.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / GRAV_ENGLISH_LBM + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + ) + J['isolated_wing_mass', Aircraft.Wing.TAPER_RATIO] = ( + -0.4 + * ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** (-0.6) + ) + / GRAV_ENGLISH_LBM + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + ) + J['isolated_wing_mass', Aircraft.Wing.THICKNESS_TO_CHORD_ROOT] = ( + 0.4 + * ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / GRAV_ENGLISH_LBM + / (100000.0 * tc_ratio_root**1.4 * np.cos(half_sweep) ** 1.535) + ) + J['isolated_wing_mass', 'half_sweep'] = ( + 1.535 + * ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * foo + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / GRAV_ENGLISH_LBM + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 2.535) + * (-np.sin(half_sweep)) + ) + J['isolated_wing_mass', 'isolated_wing_mass'] = ( + 1 + - ( + c_wing_mass + * c_material + * c_eng_pos + * c_gear_loc + * wingspan_mod**1.049 + * (1.0 + taper_ratio) ** 0.4 + ) + / (100000.0 * tc_ratio_root**0.4 * np.cos(half_sweep) ** 1.535) + * 0.757 + * (foo_numer / foo_denom) ** (-0.243) + * (-0.8) + * c_strut_braced + / foo_denom + * ULF + ) + + +class WingMassGroup(om.Group): + """Group to compute wing mass for GASP-based mass.""" + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) + + def setup(self): # variables that are calculated at a higher level higher_level_inputs_isolated = [ - "c_strut_braced", - "c_gear_loc", - "half_sweep", + 'c_strut_braced', + 'c_gear_loc', + 'half_sweep', ] - if self.options["aviary_options"].get_val(Aircraft.Wing.HAS_FOLD, units='unitless') or \ - self.options["aviary_options"].get_val(Aircraft.Wing.HAS_STRUT, units='unitless'): + if self.options[Aircraft.Wing.HAS_FOLD] or self.options[Aircraft.Wing.HAS_STRUT]: + higher_level_inputs_total = ['*'] + else: + higher_level_inputs_total = [] - higher_level_inputs_total = [ - "aircraft:*" - ] + # variables that are passed within the group but not used at a higher level + connected_outputs_isolated = [ + 'isolated_wing_mass', + ] + connected_inputs_total = [ + 'isolated_wing_mass', + ] + + isolated_mass = self.add_subsystem( + 'isolated_mass', + WingMassSolve(), + promotes_inputs=higher_level_inputs_isolated + ['*'], + promotes_outputs=connected_outputs_isolated, + ) + + self.add_subsystem( + 'total_mass', + WingMassTotal(), + promotes_inputs=connected_inputs_total + higher_level_inputs_total, + promotes_outputs=['*'], + ) + + newton = isolated_mass.nonlinear_solver = om.NewtonSolver() + + newton.options['atol'] = 1e-9 + newton.options['rtol'] = 1e-9 + newton.options['iprint'] = 2 + newton.options['maxiter'] = 10 + newton.options['solve_subsystems'] = True + newton.options['max_sub_solves'] = 10 + newton.options['err_on_non_converge'] = True + newton.options['reraise_child_analysiserror'] = False + newton.linesearch = om.BoundsEnforceLS() + newton.linesearch.options['bound_enforcement'] = 'scalar' + newton.linesearch.options['iprint'] = -1 + newton.options['err_on_non_converge'] = False + + isolated_mass.linear_solver = om.DirectSolver(assemble_jac=True) + + +class BWBWingMassGroup(om.Group): + """ + Group to compute wing mass for GASP-based mass. + """ + + def initialize(self): + add_aviary_option(self, Aircraft.Wing.HAS_FOLD) + add_aviary_option(self, Aircraft.Wing.HAS_STRUT) + + def setup(self): + # variables that are calculated at a higher level + if self.options[Aircraft.Wing.HAS_FOLD] or self.options[Aircraft.Wing.HAS_STRUT]: + higher_level_inputs_total = ['*'] else: higher_level_inputs_total = [] # variables that are passed within the group but not used at a higher level connected_outputs_isolated = [ - "isolated_wing_mass", + 'isolated_wing_mass', ] connected_inputs_total = [ - "isolated_wing_mass", + 'isolated_wing_mass', ] isolated_mass = self.add_subsystem( - "isolated_mass", - WingMassSolve(aviary_options=aviary_options), - promotes_inputs=higher_level_inputs_isolated + ["aircraft:*", "mission:*"], + 'isolated_mass', + BWBWingMassSolve(), + promotes_inputs=['*'], promotes_outputs=connected_outputs_isolated, ) - total_mass = self.add_subsystem( - "total_mass", - WingMassTotal( - aviary_options=aviary_options, - ), + self.add_subsystem( + 'total_mass', + WingMassTotal(), promotes_inputs=connected_inputs_total + higher_level_inputs_total, - promotes_outputs=["aircraft:*"], + promotes_outputs=['*'], ) newton = isolated_mass.nonlinear_solver = om.NewtonSolver() - newton.options["atol"] = 1e-9 - newton.options["rtol"] = 1e-9 - newton.options["iprint"] = 2 - newton.options["maxiter"] = 10 - newton.options["solve_subsystems"] = True - newton.options["max_sub_solves"] = 10 - newton.options["err_on_non_converge"] = True - newton.options["reraise_child_analysiserror"] = False + newton.options['atol'] = 1e-9 + newton.options['rtol'] = 1e-9 + newton.options['iprint'] = 2 + newton.options['maxiter'] = 10 + newton.options['solve_subsystems'] = True + newton.options['max_sub_solves'] = 10 + newton.options['err_on_non_converge'] = True + newton.options['reraise_child_analysiserror'] = False newton.linesearch = om.BoundsEnforceLS() - newton.linesearch.options["bound_enforcement"] = "scalar" - newton.linesearch.options["iprint"] = -1 - newton.options["err_on_non_converge"] = False + newton.linesearch.options['bound_enforcement'] = 'scalar' + newton.linesearch.options['iprint'] = -1 + newton.options['err_on_non_converge'] = False isolated_mass.linear_solver = om.DirectSolver(assemble_jac=True) diff --git a/aviary/subsystems/mass/mass_builder.py b/aviary/subsystems/mass/mass_builder.py index 07ee3a0df1..8b5cc483c2 100644 --- a/aviary/subsystems/mass/mass_builder.py +++ b/aviary/subsystems/mass/mass_builder.py @@ -7,13 +7,13 @@ CoreMassBuilder : the interface for Aviary's core mass subsystem builder """ -from aviary.interface.utils.markdown_utils import write_markdown_variable_table + +from aviary.interface.utils import write_markdown_variable_table from aviary.subsystems.mass.flops_based.mass_premission import MassPremission as MassPremissionFLOPS from aviary.subsystems.mass.gasp_based.mass_premission import MassPremission as MassPremissionGASP from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.variable_info.variables import Aircraft, Mission from aviary.variable_info.enums import LegacyCode - +from aviary.variable_info.variables import Aircraft, Mission GASP = LegacyCode.GASP FLOPS = LegacyCode.FLOPS @@ -22,9 +22,7 @@ class MassBuilderBase(SubsystemBuilderBase): - """ - Base mass builder - """ + """Base mass builder.""" def __init__(self, name=None, meta_data=None): if name is None: @@ -40,9 +38,7 @@ def mission_outputs(self, **kwargs): class CoreMassBuilder(MassBuilderBase): - """ - Core mass subsystem builder - """ + """Core mass subsystem builder.""" def __init__(self, name=None, meta_data=None, code_origin=None): if name is None: @@ -55,23 +51,39 @@ def __init__(self, name=None, meta_data=None, code_origin=None): super().__init__(name=name, meta_data=meta_data) - def build_pre_mission(self, aviary_inputs): + def build_pre_mission(self, aviary_inputs, **kwargs): code_origin = self.code_origin + try: + method = kwargs['method'] + except KeyError: + method = None + mass_group = None - if code_origin is GASP: - mass_premission = MassPremissionGASP(aviary_options=aviary_inputs,) + if method != 'external': + if code_origin is GASP: + mass_group = MassPremissionGASP() - elif code_origin is FLOPS: - mass_premission = MassPremissionFLOPS(aviary_options=aviary_inputs) + elif code_origin is FLOPS: + mass_group = MassPremissionFLOPS() - return mass_premission + return mass_group def build_mission(self, num_nodes, aviary_inputs, **kwargs): - super().build_mission(num_nodes, aviary_inputs) + # by default there is no mass mission, but call super for safety/future-proofing + try: + method = kwargs['method'] + except KeyError: + method = None + mass_group = None + + if method != 'external': + mass_group = super().build_mission(num_nodes, aviary_inputs) + + return mass_group def report(self, prob, reports_folder, **kwargs): """ - Generate the report for Aviary core mass + Generate the report for Aviary core mass. Parameters ---------- @@ -84,47 +96,50 @@ def report(self, prob, reports_folder, **kwargs): filepath = reports_folder / filename # TODO break out table into constituent categories (SAWE standard??) - outputs = [Aircraft.Wing.MASS, - Aircraft.HorizontalTail.MASS, - Aircraft.VerticalTail.MASS, - Aircraft.Fins.MASS, - Aircraft.Canard.MASS, - Aircraft.Fuselage.MASS, - Aircraft.LandingGear.TOTAL_MASS, - Aircraft.Nacelle.MASS, - Aircraft.Design.STRUCTURE_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_MASS, - Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, - Aircraft.Propulsion.TOTAL_MISC_MASS, - Aircraft.Fuel.FUEL_SYSTEM_MASS, - Aircraft.Propulsion.MASS, - Aircraft.Controls.TOTAL_MASS, - Aircraft.APU.MASS, - Aircraft.Instruments.MASS, - Aircraft.Hydraulics.MASS, - Aircraft.Electrical.MASS, - Aircraft.Avionics.MASS, - Aircraft.Furnishings.MASS, - Aircraft.AirConditioning.MASS, - Aircraft.AntiIcing.MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS, - Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, - Aircraft.Design.EMPTY_MASS, - Aircraft.CrewPayload.FLIGHT_CREW_MASS, - Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, - Aircraft.Fuel.UNUSABLE_FUEL_MASS, - Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, - Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, - Aircraft.CrewPayload.CARGO_CONTAINER_MASS, - Aircraft.Design.OPERATING_MASS, - Aircraft.CrewPayload.PASSENGER_MASS, - Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, - Aircraft.CrewPayload.CARGO_MASS, - Aircraft.Design.ZERO_FUEL_MASS, - Mission.Design.FUEL_MASS, - Mission.Summary.TOTAL_FUEL_MASS, - Mission.Summary.GROSS_MASS - ] + outputs = [ + Aircraft.Wing.MASS, + Aircraft.HorizontalTail.MASS, + Aircraft.VerticalTail.MASS, + Aircraft.Fins.MASS, + Aircraft.Canard.MASS, + Aircraft.Fuselage.MASS, + Aircraft.LandingGear.NOSE_GEAR_MASS, + Aircraft.LandingGear.MAIN_GEAR_MASS, + Aircraft.Paint.MASS, + Aircraft.Nacelle.MASS, + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Propulsion.TOTAL_ENGINE_MASS, + Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, + Aircraft.Propulsion.TOTAL_MISC_MASS, + Aircraft.Fuel.FUEL_SYSTEM_MASS, + Aircraft.Propulsion.MASS, + Aircraft.Wing.SURFACE_CONTROL_MASS, + Aircraft.APU.MASS, + Aircraft.Instruments.MASS, + Aircraft.Hydraulics.MASS, + Aircraft.Electrical.MASS, + Aircraft.Avionics.MASS, + Aircraft.Furnishings.MASS, + Aircraft.AirConditioning.MASS, + Aircraft.AntiIcing.MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS, + Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, + Aircraft.Design.EMPTY_MASS, + Aircraft.CrewPayload.FLIGHT_CREW_MASS, + Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, + Aircraft.Fuel.UNUSABLE_FUEL_MASS, + Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, + Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, + Aircraft.CrewPayload.CARGO_CONTAINER_MASS, + Mission.Summary.OPERATING_MASS, + Aircraft.CrewPayload.PASSENGER_MASS, + Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, + Aircraft.CrewPayload.CARGO_MASS, + Mission.Summary.ZERO_FUEL_MASS, + Mission.Summary.FUEL_MASS, + Mission.Summary.TOTAL_FUEL_MASS, + Mission.Summary.GROSS_MASS, + ] with open(filepath, mode='w') as f: method = self.code_origin.value + '-derived relations' diff --git a/aviary/subsystems/mass/mass_to_weight.py b/aviary/subsystems/mass/mass_to_weight.py index f748e1640c..203f544655 100644 --- a/aviary/subsystems/mass/mass_to_weight.py +++ b/aviary/subsystems/mass/mass_to_weight.py @@ -1,12 +1,11 @@ import numpy as np import openmdao.api as om + from aviary.constants import GRAV_ENGLISH_LBM class MassToWeight(om.ExplicitComponent): - """ - Component to convert mass to weight. - """ + """Component to convert mass to weight.""" def initialize(self): self.options.declare('num_nodes', types=int, default=1) @@ -15,28 +14,25 @@ def setup(self): nn = self.options['num_nodes'] self.add_input( - "mass", + 'mass', val=np.ones(nn), - units="lbm", - desc="mass of the aircraft", + units='lbm', + desc='mass of the aircraft', ) self.add_output( - "weight", + 'weight', val=np.ones(nn), - units="lbf", - desc="weight of the aircraft", + units='lbf', + desc='weight of the aircraft', ) def setup_partials(self): nn = self.options['num_nodes'] arange = np.arange(nn) - self.declare_partials("weight", - "mass", - rows=arange, - cols=arange, - val=np.full(nn, GRAV_ENGLISH_LBM) - ) + self.declare_partials( + 'weight', 'mass', rows=arange, cols=arange, val=np.full(nn, GRAV_ENGLISH_LBM) + ) def compute(self, inputs, outputs): - outputs["weight"] = inputs["mass"] * GRAV_ENGLISH_LBM + outputs['weight'] = inputs['mass'] * GRAV_ENGLISH_LBM diff --git a/aviary/subsystems/mass/test/test_flops_mass_builder.py b/aviary/subsystems/mass/test/test_flops_mass_builder.py index 2e9b0ee984..27bab5ebd0 100644 --- a/aviary/subsystems/mass/test/test_flops_mass_builder.py +++ b/aviary/subsystems/mass/test/test_flops_mass_builder.py @@ -1,15 +1,12 @@ import unittest import numpy as np -import openmdao.api as om - -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +import aviary.api as av from aviary.subsystems.mass.mass_builder import CoreMassBuilder from aviary.variable_info.enums import LegacyCode -from aviary.variable_info.variables import Aircraft from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -import aviary.api as av +from aviary.variable_info.variables import Aircraft FLOPS = LegacyCode.FLOPS @@ -23,12 +20,14 @@ class TestFLOPSMassBuilder(av.TestSubsystemBuilderBase): def setUp(self): self.subsystem_builder = CoreMassBuilder( - 'test_core_mass', meta_data=BaseMetaData, code_origin=FLOPS) + 'test_core_mass', meta_data=BaseMetaData, code_origin=FLOPS + ) self.aviary_values = av.AviaryValues() self.aviary_values.set_val(Aircraft.Design.USE_ALT_MASS, False, units='unitless') - self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') + self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, np.array([1]), units='unitless') self.aviary_values.set_val( - Aircraft.Engine.NUM_WING_ENGINES, [2], units='unitless') + Aircraft.Engine.NUM_WING_ENGINES, np.array([2]), units='unitless' + ) class TestFLOPSMassBuilderAltMass(av.TestSubsystemBuilderBase): @@ -40,12 +39,14 @@ class TestFLOPSMassBuilderAltMass(av.TestSubsystemBuilderBase): def setUp(self): self.subsystem_builder = CoreMassBuilder( - 'test_core_mass', meta_data=BaseMetaData, code_origin=FLOPS) + 'test_core_mass', meta_data=BaseMetaData, code_origin=FLOPS + ) self.aviary_values = av.AviaryValues() self.aviary_values.set_val(Aircraft.Design.USE_ALT_MASS, True, units='unitless') - self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') + self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, np.array([1]), units='unitless') self.aviary_values.set_val( - Aircraft.Engine.NUM_WING_ENGINES, [2], units='unitless') + Aircraft.Engine.NUM_WING_ENGINES, np.array([2]), units='unitless' + ) if __name__ == '__main__': diff --git a/aviary/subsystems/mass/test/test_gasp_mass_builder.py b/aviary/subsystems/mass/test/test_gasp_mass_builder.py index d21613463f..4282c5e3ea 100644 --- a/aviary/subsystems/mass/test/test_gasp_mass_builder.py +++ b/aviary/subsystems/mass/test/test_gasp_mass_builder.py @@ -1,16 +1,10 @@ import unittest -import numpy as np -import openmdao.api as om - -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - +import aviary.api as av from aviary.subsystems.mass.mass_builder import CoreMassBuilder - from aviary.variable_info.enums import LegacyCode -from aviary.variable_info.variables import Aircraft from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -import aviary.api as av +from aviary.variable_info.variables import Aircraft GASP = LegacyCode.GASP @@ -24,17 +18,16 @@ class TestGASPMassBuilderHybrid(av.TestSubsystemBuilderBase): def setUp(self): self.subsystem_builder = CoreMassBuilder( - 'test_core_mass', meta_data=BaseMetaData, code_origin=GASP) + 'test_core_mass', meta_data=BaseMetaData, code_origin=GASP + ) self.aviary_values = av.AviaryValues() - self.aviary_values.set_val( - Aircraft.Design.PART25_STRUCTURAL_CATEGORY, 3, units='unitless') - self.aviary_values.set_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2, units='unitless') - self.aviary_values.set_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, True, units='unitless') + self.aviary_values.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, 3, units='unitless') + self.aviary_values.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2, units='unitless') + self.aviary_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_FOLD, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_STRUT, True, units='unitless') self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') + self.aviary_values.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 1) class TestGASPMassBuilder(av.TestSubsystemBuilderBase): @@ -46,17 +39,16 @@ class TestGASPMassBuilder(av.TestSubsystemBuilderBase): def setUp(self): self.subsystem_builder = CoreMassBuilder( - 'test_core_mass', meta_data=BaseMetaData, code_origin=GASP) + 'test_core_mass', meta_data=BaseMetaData, code_origin=GASP + ) self.aviary_values = av.AviaryValues() - self.aviary_values.set_val( - Aircraft.Design.PART25_STRUCTURAL_CATEGORY, 3, units='unitless') - self.aviary_values.set_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2, units='unitless') - self.aviary_values.set_val( - Aircraft.Electrical.HAS_HYBRID_SYSTEM, False, units='unitless') + self.aviary_values.set_val(Aircraft.Design.PART25_STRUCTURAL_CATEGORY, 3, units='unitless') + self.aviary_values.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, 2, units='unitless') + self.aviary_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, False, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_FOLD, True, units='unitless') self.aviary_values.set_val(Aircraft.Wing.HAS_STRUT, True, units='unitless') self.aviary_values.set_val(Aircraft.Engine.NUM_ENGINES, [1], units='unitless') + self.aviary_values.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, 1) if __name__ == '__main__': diff --git a/aviary/subsystems/mass/test/test_mass_to_weight.py b/aviary/subsystems/mass/test/test_mass_to_weight.py index acc95bd34b..cacbc760c7 100644 --- a/aviary/subsystems/mass/test/test_mass_to_weight.py +++ b/aviary/subsystems/mass/test/test_mass_to_weight.py @@ -9,22 +9,15 @@ class MassToWeightTest(unittest.TestCase): - """ - Test computation of weight from mass. - """ + """Test computation of weight from mass.""" def setUp(self): self.prob = om.Problem() def test_case(self): - prob = om.Problem() - prob.model.add_subsystem( - "calc_weight", - MassToWeight(), - promotes=['mass', 'weight'] - ) + prob.model.add_subsystem('calc_weight', MassToWeight(), promotes=['mass', 'weight']) prob.setup(force_alloc_complex=True) @@ -33,9 +26,8 @@ def test_case(self): prob.run_model() prob.model.list_inputs() prob.model.list_outputs() - assert_near_equal(prob.get_val('weight', 'lbf'), - 120_000 * GRAV_ENGLISH_LBM, 1.0e-12) - partial_data = prob.check_partials(compact_print=True, method="cs") + assert_near_equal(prob.get_val('weight', 'lbf'), 120_000 * GRAV_ENGLISH_LBM, 1.0e-12) + partial_data = prob.check_partials(compact_print=True, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-12) nn = 3 @@ -44,9 +36,7 @@ def test_case(self): prob = om.Problem() prob.model.add_subsystem( - "calc_weight", - MassToWeight(num_nodes=nn), - promotes=['mass', 'weight'] + 'calc_weight', MassToWeight(num_nodes=nn), promotes=['mass', 'weight'] ) prob.setup(force_alloc_complex=True) @@ -56,50 +46,43 @@ def test_case(self): prob.run_model() prob.model.list_inputs() prob.model.list_outputs() - assert_near_equal(prob.get_val('weight', 'lbf'), - mass * GRAV_ENGLISH_LBM, 1.0e-12) - partial_data = prob.check_partials(compact_print=True, method="cs") + assert_near_equal(prob.get_val('weight', 'lbf'), mass * GRAV_ENGLISH_LBM, 1.0e-12) + partial_data = prob.check_partials(compact_print=True, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-12) class MassToWeightTest2(unittest.TestCase): - """ - Test mass-weight conversion - """ + """Test mass-weight conversion.""" def setUp(self): import aviary.subsystems.mass.mass_to_weight as m_to_w + m_to_w.GRAV_ENGLISH_LBM = 1.1 def tearDown(self): import aviary.subsystems.mass.mass_to_weight as m_to_w + m_to_w.GRAV_ENGLISH_LBM = 1.0 def test_case(self): prob = om.Problem() - prob.model.add_subsystem( - "calc_weight", - MassToWeight(), - promotes=['mass', 'weight'] - ) + prob.model.add_subsystem('calc_weight', MassToWeight(), promotes=['mass', 'weight']) prob.setup(force_alloc_complex=True) prob.set_val('mass', 120_000, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) nn = 2 mass = np.full(nn, 120_000) prob = om.Problem() prob.model.add_subsystem( - "calc_weight", - MassToWeight(num_nodes=nn), - promotes=['mass', 'weight'] + 'calc_weight', MassToWeight(num_nodes=nn), promotes=['mass', 'weight'] ) prob.setup(force_alloc_complex=True) prob.set_val('mass', mass, 'lbm') - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/performance/__init__.py b/aviary/subsystems/performance/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/aviary/subsystems/performance/performance_builder.py b/aviary/subsystems/performance/performance_builder.py new file mode 100644 index 0000000000..5a18acadb7 --- /dev/null +++ b/aviary/subsystems/performance/performance_builder.py @@ -0,0 +1,15 @@ +from aviary.subsystems.performance.performance_premission import PerformancePremission +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase + + +class CorePerformanceBuilder(SubsystemBuilderBase): + """Core performance analysis subsystem builder.""" + + def __init__(self, name=None, meta_data=None): + if name is None: + name = 'core_performance' + + super().__init__(name=name, meta_data=meta_data) + + def build_pre_mission(self, aviary_inputs, **kwargs): + return PerformancePremission() diff --git a/aviary/subsystems/performance/performance_premission.py b/aviary/subsystems/performance/performance_premission.py new file mode 100644 index 0000000000..f0563ff225 --- /dev/null +++ b/aviary/subsystems/performance/performance_premission.py @@ -0,0 +1,51 @@ +import openmdao.api as om + +from aviary.constants import GRAV_ENGLISH_LBM +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Mission + + +class PerformancePremission(om.ExplicitComponent): + """Calculates the thrust-to-weight ratio and wing loading of the aircraft.""" + + def setup(self): + add_aviary_input(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, units='lbf') + add_aviary_input(self, Mission.Design.GROSS_MASS, units='lbm') + add_aviary_input(self, Aircraft.Wing.AREA, units='ft**2') + + add_aviary_output(self, Aircraft.Design.THRUST_TO_WEIGHT_RATIO, units='unitless') + add_aviary_output(self, Aircraft.Design.WING_LOADING, units='lbf/ft**2') + + def setup_partials(self): + self.declare_partials( + Aircraft.Design.THRUST_TO_WEIGHT_RATIO, + [Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, Mission.Design.GROSS_MASS], + ) + self.declare_partials( + Aircraft.Design.WING_LOADING, [Mission.Design.GROSS_MASS, Aircraft.Wing.AREA] + ) + + def compute(self, inputs, outputs): + thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] + weight = inputs[Mission.Design.GROSS_MASS] * GRAV_ENGLISH_LBM + area = inputs[Aircraft.Wing.AREA] + + outputs[Aircraft.Design.THRUST_TO_WEIGHT_RATIO] = thrust / weight + outputs[Aircraft.Design.WING_LOADING] = weight / area + + def compute_partials(self, inputs, J): + thrust = inputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] + mass = inputs[Mission.Design.GROSS_MASS] + area = inputs[Aircraft.Wing.AREA] + + J[Aircraft.Design.THRUST_TO_WEIGHT_RATIO, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] = ( + 1 / (mass * GRAV_ENGLISH_LBM) + ) + + J[Aircraft.Design.THRUST_TO_WEIGHT_RATIO, Mission.Design.GROSS_MASS] = -thrust / ( + mass**2 * GRAV_ENGLISH_LBM + ) + + J[Aircraft.Design.WING_LOADING, Mission.Design.GROSS_MASS] = GRAV_ENGLISH_LBM / area + + J[Aircraft.Design.WING_LOADING, Aircraft.Wing.AREA] = -mass * GRAV_ENGLISH_LBM / area**2 diff --git a/aviary/subsystems/performance/test/test_performance_premission.py b/aviary/subsystems/performance/test/test_performance_premission.py new file mode 100644 index 0000000000..7bd33b6ea8 --- /dev/null +++ b/aviary/subsystems/performance/test/test_performance_premission.py @@ -0,0 +1,40 @@ +import unittest + +import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal +from aviary.variable_info.variables import Aircraft, Mission +from aviary.subsystems.performance.performance_premission import PerformancePremission + + +class PerformancePremissionTest(unittest.TestCase): + """Test computation of parameters in performance premission.""" + + def test_case(self): + prob = om.Problem() + + prob.model.add_subsystem('perf_premission', PerformancePremission(), promotes=['*']) + + prob.setup(force_alloc_complex=True) + + # arbitrary numbers in roughly correct order of magnitude for testing + prob.set_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 32745, 'lbf') + prob.set_val(Aircraft.Wing.AREA, 1823, 'ft**2') + prob.set_val(Mission.Design.GROSS_MASS, 203154, 'lbm') + + prob.run_model() + + TW = prob.get_val(Aircraft.Design.THRUST_TO_WEIGHT_RATIO) + WS = prob.get_val(Aircraft.Design.WING_LOADING) + + TW_expected = 0.161183141853 + WS_expected = 111.4393856281 + + assert_near_equal(TW, TW_expected, 1e-12) + assert_near_equal(WS, WS_expected, 1e-12) + + partial_data = prob.check_partials(out_stream=None, method='cs') + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/premission.py b/aviary/subsystems/premission.py index d36a9cdb67..b55a49c3d8 100644 --- a/aviary/subsystems/premission.py +++ b/aviary/subsystems/premission.py @@ -1,35 +1,33 @@ -from packaging import version - import openmdao import openmdao.api as om +from packaging import version from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.functions import override_aviary_vars +from aviary.variable_info.variable_meta_data import _MetaData -use_new_openmdao_syntax = version.parse(openmdao.__version__) >= version.parse("3.28") +use_new_openmdao_syntax = version.parse(openmdao.__version__) >= version.parse('3.28') class CorePreMission(om.Group): - """ - Group that contains all pre-mission groups of core Aviary subsystems (geometry, mass, propulsion, aerodynamics) - """ + """Group that contains all pre-mission groups of core Aviary subsystems (geometry, mass, propulsion, aerodynamics).""" def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - self.options.declare( - 'subsystems', desc='list of core subsystem builders' + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', ) + self.options.declare('subsystems', desc='list of core subsystem builders') + self.options.declare('meta_data', desc='problem metadata', default=_MetaData) + # NOTE this flag is only needed for tests - in AviaryProblem it should always be False self.options.declare( - 'meta_data', desc='problem metadata', default=_MetaData + 'process_overrides', + types=bool, + default=True, + desc='When True, overrides are handled here, otherwise, ' + 'they are handled in the parent system.', ) - # NOTE this flag is only needed for tests - in AviaryProblem it should always be False - self.options.declare('process_overrides', types=bool, default=True, - desc='When True, overrides are handled here, otherwise, ' - 'they are handled in the parent system.') def setup(self, **kwargs): if use_new_openmdao_syntax: @@ -40,22 +38,28 @@ def setup(self, **kwargs): core_subsystems = self.options['subsystems'] for subsystem in core_subsystems: - self.add_subsystem( - subsystem.name, - subsystem.build_pre_mission(aviary_options), - promotes_inputs=['*'], - promotes_outputs=['*'] - ) + pre_mission_system = subsystem.build_pre_mission(aviary_options) + if pre_mission_system is not None: + self.add_subsystem( + subsystem.name, + pre_mission_system, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) def configure(self): - self.manual_overrides = [] + self.code_origin_overrides = [] for subsystem in self.options['subsystems']: try: - self.manual_overrides.extend(getattr(getattr(self, subsystem.name), - 'manual_overrides')) + self.code_origin_overrides.extend( + getattr(getattr(self, subsystem.name), 'code_origin_overrides') + ) except: continue if self.options['process_overrides']: - override_aviary_vars(self, self.options["aviary_options"], - manual_overrides=self.manual_overrides) + override_aviary_vars( + self, + self.options['aviary_options'], + code_origin_overrides=self.code_origin_overrides, + ) diff --git a/aviary/subsystems/propulsion/engine_deck.py b/aviary/subsystems/propulsion/engine_deck.py index 6ec669cb15..3b14e9edb3 100644 --- a/aviary/subsystems/propulsion/engine_deck.py +++ b/aviary/subsystems/propulsion/engine_deck.py @@ -28,27 +28,25 @@ import numpy as np import openmdao.api as om - from openmdao.utils.units import convert_units -from aviary.interface.utils.markdown_utils import round_it +from aviary.interface.utils import round_it from aviary.subsystems.propulsion.engine_model import EngineModel from aviary.subsystems.propulsion.engine_scaling import EngineScaling from aviary.subsystems.propulsion.engine_sizing import SizeEngine -from aviary.subsystems.propulsion.utils import UncorrectData from aviary.subsystems.propulsion.utils import ( EngineModelVariables, + UncorrectData, convert_geopotential_altitude, default_units, max_variables, ) -from aviary.utils.aviary_values import AviaryValues, NamedValues, get_keys, get_items +from aviary.utils.aviary_values import AviaryValues, NamedValues, get_items, get_keys from aviary.utils.csv_data_file import read_data_file from aviary.variable_info.enums import Verbosity from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings - MACH = EngineModelVariables.MACH ALTITUDE = EngineModelVariables.ALTITUDE THROTTLE = EngineModelVariables.THROTTLE @@ -63,6 +61,8 @@ ELECTRIC_POWER_IN = EngineModelVariables.ELECTRIC_POWER_IN NOX_RATE = EngineModelVariables.NOX_RATE TEMPERATURE = EngineModelVariables.TEMPERATURE_T4 +RPM = EngineModelVariables.RPM + # EXIT_AREA = EngineModelVariables.EXIT_AREA # EngineDeck assumes all aliases point to an enum, these are used internally only @@ -88,35 +88,34 @@ SHAFT_POWER: ['shaft_power', 'shp'], SHAFT_POWER_CORRECTED: ['shaft_power_corrected', 'shpcor', 'corrected_horsepower'], TAILPIPE_THRUST: ['tailpipe_thrust'], + RPM: ['rpm', 'rotations_per_minute'], } # these variables must be present in engine performance data -default_required_variables = { - MACH, - ALTITUDE, - THROTTLE, - THRUST -} +default_required_variables = {MACH, ALTITUDE, THROTTLE, THRUST} # EngineDecks internally require these options to have values. Input checks will set # these options to default values in self.options if they are not provided -# TODO should this instead be a set to prevent duplicates? required_options = ( Aircraft.Engine.SCALE_PERFORMANCE, Aircraft.Engine.IGNORE_NEGATIVE_THRUST, Aircraft.Engine.GEOPOTENTIAL_ALT, Aircraft.Engine.GENERATE_FLIGHT_IDLE, + Aircraft.Engine.INTERPOLATION_METHOD, + Aircraft.Engine.INTERPOLATION_SORT, # TODO fuel flow scaler is required for the EngineScaling component but does not need # to be defined on a per-engine basis, so it could exist only in the problem- # level aviary_options without issue. Is this a propulsion_preprocessor task? - Mission.Summary.FUEL_FLOW_SCALER + Mission.Summary.FUEL_FLOW_SCALER, ) # options that are only required based on the value of another option dependent_options = { - Aircraft.Engine.GENERATE_FLIGHT_IDLE: (Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION, - Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION, - Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION,) + Aircraft.Engine.GENERATE_FLIGHT_IDLE: ( + Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION, + Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION, + Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION, + ) } @@ -146,9 +145,14 @@ class EngineDeck(EngineModel): update """ - def __init__(self, name='engine_deck', options: AviaryValues = None, - data: NamedValues = None, - required_variables: set = default_required_variables): + def __init__( + self, + name='engine_deck', + options: AviaryValues = None, + data: NamedValues = None, + required_variables: set = default_required_variables, + meta_data: dict = _MetaData, + ): if data is not None: self.read_from_file = False else: @@ -156,7 +160,13 @@ def __init__(self, name='engine_deck', options: AviaryValues = None, # TODO update default name to be based on filename # also calls _preprocess_inputs() as part of EngineModel __init__ - super().__init__(name, options) + super().__init__(name, options, meta_data=meta_data) + + # custom error messages depending on data type + if self.read_from_file: + self.error_message = f'<{self.get_val(Aircraft.Engine.DATA_FILE)}>' + else: + self.error_message = f'EngineDeck <{self.name}>' # copy of raw data read from data_file or memory, never modified or used outside # EngineDeck @@ -180,12 +190,20 @@ def __init__(self, name='engine_deck', options: AviaryValues = None, # Create dict for variables present in engine data with associated units self.engine_variables = {} - # TODO make this an option - disabling global throttle ranges is better to - # prevent unintended extrapolation, but breaks missions using GASP-based - # engines that have uneven throttle ranges (need t4 constraint on mission - # to truly fix) - self.global_throttle = True - self.global_hybrid_throttle = True + if Aircraft.Engine.GLOBAL_THROTTLE in options: + self.global_throttle = self.options.get_val(Aircraft.Engine.GLOBAL_THROTTLE) + else: + default = meta_data[Aircraft.Engine.GLOBAL_THROTTLE]['default_value'] + self.options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, default) + self.global_throttle = default + if Aircraft.Engine.GLOBAL_HYBRID_THROTTLE in options: + self.global_hybrid_throttle = self.options.get_val( + Aircraft.Engine.GLOBAL_HYBRID_THROTTLE + ) + else: + default = meta_data[Aircraft.Engine.GLOBAL_HYBRID_THROTTLE]['default_value'] + self.options.set_val(Aircraft.Engine.GLOBAL_HYBRID_THROTTLE, default) + self.global_hybrid_throttle = default # ensure required variables are a set self.required_variables = {*required_variables} @@ -216,14 +234,16 @@ def _preprocess_inputs(self): for key in additional_options + required_options: if key not in options: - val = _MetaData[key]['default_value'] - units = _MetaData[key]['units'] + val = self.meta_data[key]['default_value'] + units = self.meta_data[key]['units'] - if self.get_val(Settings.VERBOSITY) >= Verbosity.BRIEF: + if self.get_val(Settings.VERBOSITY) > Verbosity.BRIEF: warnings.warn( f'<{key}> is a required option for EngineDecks, but has not been ' f'specified for EngineDeck <{self.name}>. The default value ' - f"{val}{' ' + units if units != 'unitless' else ''} will be used.") + f'{val}{" " + units if units != "unitless" else ""} will ' + 'be used.' + ) self.set_val(key, val, units) @@ -232,8 +252,8 @@ def _preprocess_inputs(self): if self.get_val(key): for item in dependent_options[key]: if item not in options: - val = _MetaData[item]['default_value'] - units = _MetaData[item]['units'] + val = self.meta_data[item]['default_value'] + units = self.meta_data[item]['units'] self.set_val(item, val, units) # LOGIC CHECKS @@ -249,10 +269,8 @@ def _preprocess_inputs(self): 'exceeds maximum flight idle fraction. Values for min and max ' 'fraction will be flipped.' ) - self.set_val(Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION, - val=idle_max) - self.set_val(Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION, - val=idle_min) + self.set_val(Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION, val=idle_max) + self.set_val(Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION, val=idle_min) # check that sufficient information on engine scaling is provided # default behavior is to calculate scale factor based on thrust target @@ -274,17 +292,30 @@ def _preprocess_inputs(self): thrust_provided = True # user provided target thrust or scale factor, but performance scaling is off - if not scale_performance and (scale_factor_provided or thrust_provided) and self.get_val(Settings.VERBOSITY).value >= 1: + if ( + not scale_performance + and (scale_factor_provided or thrust_provided) + and self.get_val(Settings.VERBOSITY).value >= 1 + ): warnings.warn( f'EngineDeck <{self.name}>: Scaling targets are provided, but will be ' 'ignored because performance scaling is disabled. Set ' - 'aircraft:engine:SCALE_PERFORMANCE to True to enable scaling.' + 'aircraft:engine:scale_performance to True to enable scaling.' + ) + + # Check validity of interp_sort. + # TODO: support this as an enum instead. + interp_sort = self.get_val(Aircraft.Engine.INTERPOLATION_SORT) + if interp_sort not in ['mach', 'altitude']: + raise ValueError( + f'EngineDeck <{self.name}>: Invalid value of Aircraft.Engine.INTERPOLATION_SORT.' + f' Expected "altitude" or "mach", but found "{interp_sort}".' ) def _set_variable_flags(self): """ Sets flags in EngineDeck to communicate which (non-required) variables are - avaliable to greater propulsion module. + available to greater propulsion module. """ engine_variables = self.engine_variables @@ -303,19 +334,13 @@ def _set_variable_flags(self): def _setup(self, data): """ - Read in and process engine data: - - Check data consistency. - - Convert altitudes to geometric. - - Sort and pack data. - - Determine reference thrust. - - Normalize throttles/hybrid throttles. - - Fill flight idle points. + Read in and process engine data. + - Check data consistency. + - Convert altitudes to geometric. + - Sort and pack data. + - Determine reference thrust. + - Normalize throttles & hybrid throttles. + - Fill flight idle points if requested. """ self._read_data(data) @@ -324,8 +349,7 @@ def _setup(self, data): # convert geopotential altitude to geometric if required if self.get_val(Aircraft.Engine.GEOPOTENTIAL_ALT): - self.data[ALTITUDE] = convert_geopotential_altitude( - self.data[ALTITUDE]) + self.data[ALTITUDE] = convert_geopotential_altitude(self.data[ALTITUDE]) # sort and organize data self._pack_data() @@ -356,18 +380,12 @@ def _read_data(self, raw_data: NamedValues): ValueError If non-numerical data found in DATA_FILE (not including header or comments). """ - # custom error messages depending on data type - if self.read_from_file: - message = f'<{self.get_val(Aircraft.Engine.DATA_FILE)}>' - else: - message = f'EngineDeck <{self.name}>' - # get data (as NamedValues object) from data file if self.read_from_file: data_file = self.get_val(Aircraft.Engine.DATA_FILE) # read csv file - currently not saving comments - raw_data = read_data_file(data_file, aliases=aliases) + raw_data, self.inputs, self.outputs = read_data_file(data_file, aliases=aliases) else: # run provided data through aliases @@ -397,11 +415,10 @@ def _read_data(self, raw_data: NamedValues): # Convert data to expected units. Required so settings like tolerances # that assume units work as expected try: - val = np.array([convert_units(i, units, default_units[key]) - for i in val]) + val = np.array([convert_units(i, units, default_units[key]) for i in val]) except TypeError: raise TypeError( - f"{message}: units of '{units}' provided for " + f"{self.error_message}: units of '{units}' provided for " f'<{key.name}> are not compatible with expected ' f'units of {default_units[key]}' ) @@ -413,13 +430,14 @@ def _read_data(self, raw_data: NamedValues): else: if self.get_val(Settings.VERBOSITY) >= Verbosity.BRIEF: warnings.warn( - f'{message}: header <{key}> was not recognized, and will be skipped') + f'{self.error_message}: header <{key}> was not recognized, and will be skipped' + ) # save all data in self._original_data, including skipped variables self._original_data[key] = val if not self.engine_variables: - raise UserWarning(f'No valid engine variables found in data for {message}') + raise UserWarning(f'No valid engine variables found in data for {self.error_message}') # Copy data from original data (never modified) to working data (changed through # sorting, generating missing data, etc.) @@ -429,7 +447,7 @@ def _read_data(self, raw_data: NamedValues): def _check_data(self): """ Checks for consistency of provided thrust and drag data, ensures no required - variables are missing, fills unused variabes with a default value of zero, and + variables are missing, fills unused variables with a default value of zero, and removes negative thrusts if requested. Raises @@ -443,31 +461,28 @@ def _check_data(self): original_data = self._original_data data = self.data - # custom error messages depending on data type - if self.read_from_file: - message = f'<{self.get_val(Aircraft.Engine.DATA_FILE)}>' - else: - message = f'EngineDeck <{self.name}>' - engine_variables = self.engine_variables # Handle ram drag, net and gross thrust and potential conflicts in value or units - # Warn user if they provide partial info for calulated thrust + # Warn user if they provide partial info for calculated thrust # Not a fail state if net thrust is still provided # If both net thrust and components for calculated thrust both provided, a sanity # check that they match is done after reading data if THRUST in engine_variables: # if thrust is present, but gross thrust or ram drag also present raise warning - if GROSS_THRUST in engine_variables and not RAM_DRAG in engine_variables: - warnings.warn(f'{message} contains both net and ' - 'gross thrust. Only net thrust will be used.') - if not GROSS_THRUST in engine_variables and RAM_DRAG in engine_variables: - warnings.warn(f'{message} contains both net thrust ' - 'and ram drag. Only net thrust will be used.') + if GROSS_THRUST in engine_variables and RAM_DRAG not in engine_variables: + warnings.warn( + f'{self.error_message} contains both net and gross thrust. Only net thrust will be used.' + ) + if GROSS_THRUST not in engine_variables and RAM_DRAG in engine_variables: + warnings.warn( + f'{self.error_message} contains both net thrust ' + 'and ram drag. Only net thrust will be used.' + ) if RAM_DRAG in engine_variables and GROSS_THRUST in engine_variables: # Check that units are the same. Variables have already been checked for valid - # units, so it is assumed they are convertable. Prioritizes thrust units + # units, so it is assumed they are convertible. Prioritizes thrust units if engine_variables[RAM_DRAG] != engine_variables[GROSS_THRUST]: data[RAM_DRAG] = convert_units( original_data[RAM_DRAG], @@ -481,9 +496,11 @@ def _check_data(self): if THRUST in engine_variables: res = abs(net_thrust_calc - original_data[THRUST]) if np.any(self.thrust_tol > res): - raise UserWarning('Provided net thrust is not equal to difference ' - '(within tolerance) between gross thrust and ram ' - f'drag in {message}') + raise UserWarning( + 'Provided net thrust is not equal to difference ' + '(within tolerance) between gross thrust and ram ' + f'drag in {self.error_message}' + ) else: # store net thrust in THRUST key instead of gross thrust data[THRUST] = net_thrust_calc @@ -493,7 +510,7 @@ def _check_data(self): # tailpipe thrust is not bookept separately in Aviary. Add to net thrust. if THRUST in engine_variables: # Check that units are the same. Variables have already been checked for valid - # units, so it is assumed they are convertable. Prioritizes thrust units + # units, so it is assumed they are convertible. Prioritizes thrust units if engine_variables[THRUST] != engine_variables[TAILPIPE_THRUST]: data[TAILPIPE_THRUST] = convert_units( data, @@ -518,7 +535,7 @@ def _check_data(self): self.data.pop(TAILPIPE_THRUST) # Handle shaft power (corrected and uncorrected). It is not possible to compare - # them for consistency, as that requires information not avaliable during setup + # them for consistency, as that requires information not available during setup # (freestream air temp and pressure). Instead, we must trust the source and # assume either data set is valid and can be used. if ( @@ -528,7 +545,7 @@ def _check_data(self): ): warnings.warn( 'Both corrected and uncorrected shaft horsepower are ' - f'present in {message}. The two cannot be validated for ' + f'present in {self.error_message}. The two cannot be validated for ' 'consistency, and only uncorrected shaft power will be used.' ) engine_variables.pop(SHAFT_POWER_CORRECTED) @@ -536,8 +553,6 @@ def _check_data(self): self._set_variable_flags() - self.model_length = len(self.data[ALTITUDE]) - # check that all required variables are present in engine data if not self.required_variables.issubset(engine_variables): # gather all missing required variables @@ -548,14 +563,9 @@ def _check_data(self): # if missing_variables is not empty if not missing_variables: - raise UserWarning(f'Required variables {missing_variables} are ' - f'missing from {message}' - ) - - # Set all unused variables to default value of zero - for key in data: - if not len(data[key]): - data[key] = np.zeros(self.model_length) + raise UserWarning( + f'Required variables {missing_variables} are missing from {self.error_message}' + ) # removes data points with negative thrust if requested if self.get_val(Aircraft.Engine.IGNORE_NEGATIVE_THRUST): @@ -563,6 +573,13 @@ def _check_data(self): for key in data: data[key] = data[key][keep_idx] + self.model_length = len(self.data[ALTITUDE]) + + # Set all unused variables to default value of zero + for key in data: + if not len(data[key]): + data[key] = np.zeros(self.model_length) + # set flags using updated engine_variables self._set_variable_flags() @@ -575,6 +592,7 @@ def _generate_flight_idle(self): Modifies unpacked data in place, updates packed data. """ + def _extrapolate(array): """ Linearly extrapolate variable to idle thrust point. @@ -595,9 +613,7 @@ def _extrapolate(array): if y0 == 0 and y1 == 0: return 0 - rvalue = ( - y0 + (y1 - y0) * extrap_term - ) + rvalue = y0 + (y1 - y0) * extrap_term return rvalue @@ -656,33 +672,45 @@ def _extrapolate(array): # define known data for idle point (independent variables) idle_points[MACH] = np.append( - idle_points[MACH], [packed_data[MACH][M, A, 0]] * num_points) + idle_points[MACH], [packed_data[MACH][M, A, 0]] * num_points + ) idle_points[ALTITUDE] = np.append( - idle_points[ALTITUDE], [packed_data[ALTITUDE][M, A, 0]] * num_points) + idle_points[ALTITUDE], [packed_data[ALTITUDE][M, A, 0]] * num_points + ) idle_points[THROTTLE] = np.append( - idle_points[THROTTLE], [throttle_idle] * num_points) + idle_points[THROTTLE], [throttle_idle] * num_points + ) if self.use_hybrid_throttle: - hybrid_throttle_range = np.linspace(hybrid_throttle_idle-h_tol, - hybrid_throttle_idle+h_tol, - num_points) + hybrid_throttle_range = np.linspace( + hybrid_throttle_idle - h_tol, + hybrid_throttle_idle + h_tol, + num_points, + ) idle_points[HYBRID_THROTTLE] = np.append( - idle_points[HYBRID_THROTTLE], hybrid_throttle_range) + idle_points[HYBRID_THROTTLE], hybrid_throttle_range + ) else: idle_points[HYBRID_THROTTLE] = np.append( - idle_points[HYBRID_THROTTLE], hybrid_throttle_idle) + idle_points[HYBRID_THROTTLE], hybrid_throttle_idle + ) # if there is only one data point at this Mach, alt combination, use # thrust fraction instead of extrapolation - # TODO idle currently calculated using lowest index data points - this is not - # guaranteed to be at hybrid throttle idle point, could be negative if data_indices[M, A] == 1: + # Find the point closest to hybrid throttle idle (0) if hybrid throttle is present + if self.use_hybrid_throttle: + hybrid_throttle_data = packed_data[HYBRID_THROTTLE][M, A] + # Find index of point closest to hybrid throttle idle (0) + idle_idx = np.argmin(np.abs(hybrid_throttle_data)) + else: + idle_idx = 0 + for key in packed_data: - if key not in [ - MACH, - ALTITUDE, - THROTTLE, - HYBRID_THROTTLE] + direct_calc_vars: - idle_value = packed_data[key][M, A, 0] * idle_thrust_fract + if ( + key + not in [MACH, ALTITUDE, THROTTLE, HYBRID_THROTTLE] + direct_calc_vars + ): + idle_value = packed_data[key][M, A, idle_idx] * idle_thrust_fract var_min = packed_data[key][M, A, -1] * idle_min_fract var_max = packed_data[key][M, A, -1] * idle_max_fract @@ -691,27 +719,27 @@ def _extrapolate(array): elif idle_value > var_max: idle_value = var_max - idle_points[key] = np.append(idle_points[key], - [idle_value] * num_points) - # add Mach, alt combination to idle_points with idle power - # codes + idle_points[key] = np.append( + idle_points[key], [idle_value] * num_points + ) # thrust, shaft powers do not get idle_min/max checks for var in direct_calc_vars: - idle_points[var] = np.append(idle_points[var], - [[packed_data[var][M, A, 0] - * idle_thrust_fract]] * num_points) + idle_points[var] = np.append( + idle_points[var], + [[packed_data[var][M, A, idle_idx] * idle_thrust_fract]] * num_points, + ) # move to next data point continue # calculate idle thrust, shaft powers as a percentage of max thrust at Mach, alt point for var in direct_calc_vars: - idle_calc_value = packed_data[var][M, A, data_indices[M, A] - 1]\ - * idle_thrust_fract + idle_calc_value = ( + packed_data[var][M, A, data_indices[M, A] - 1] * idle_thrust_fract + ) # add this point to idle_points - idle_points[var] = np.append(idle_points[var], - [idle_calc_value] * num_points) + idle_points[var] = np.append(idle_points[var], [idle_calc_value] * num_points) # Calculate term for linear extrapolation - shaft power has highest # "preference" since it is last in the list, followed by corrected @@ -719,16 +747,13 @@ def _extrapolate(array): # with turboshaft engine decks in TurbopropModels. # Only one extrapolation term can be used for all dependent vars extrap_term = (idle_calc_value - packed_data[var][M, A, 0]) / ( - packed_data[var][M, A, 1] - packed_data[var][M, A, 0]) + packed_data[var][M, A, 1] - packed_data[var][M, A, 0] + ) # compute idle data for key in packed_data: # skip independent variables or thrust, which is already calculated - if key not in [ - MACH, - ALTITUDE, - THROTTLE, - HYBRID_THROTTLE] + direct_calc_vars: + if key not in [MACH, ALTITUDE, THROTTLE, HYBRID_THROTTLE] + direct_calc_vars: # extrapolate to idle from lowest two throttle points in data idle_value = _extrapolate(packed_data[key][M, A]) @@ -742,8 +767,7 @@ def _extrapolate(array): idle_value = var_max # store newly computed idle point - idle_points[key] = np.append(idle_points[key], - [idle_value] * num_points) + idle_points[key] = np.append(idle_points[key], [idle_value] * num_points) # add idle points to data for key in packed_data: @@ -762,7 +786,7 @@ def _extrapolate(array): # Re-normalize throttle since "dummy" idle values were used self._normalize_throttle() - def build_pre_mission(self, aviary_inputs) -> om.ExplicitComponent: + def build_pre_mission(self, aviary_inputs, **kwargs) -> om.ExplicitComponent: """ Build components to be added to pre-mission propulsion subsystem. @@ -771,8 +795,7 @@ def build_pre_mission(self, aviary_inputs) -> om.ExplicitComponent: SizeEngine component specific to this EngineDeck, used for calculating engine scaling factors. """ - - return SizeEngine(aviary_options=self.options) + return SizeEngine() def _build_engine_interpolator(self, num_nodes, aviary_inputs): """ @@ -780,9 +803,11 @@ def _build_engine_interpolator(self, num_nodes, aviary_inputs): Currently only the semistructured model is supported. """ interp_method = self.get_val(Aircraft.Engine.INTERPOLATION_METHOD) + interp_sort = self.get_val(Aircraft.Engine.INTERPOLATION_SORT) # interpolator object for engine data engine = om.MetaModelSemiStructuredComp( - method=interp_method, extrapolate=True, vec_size=num_nodes) + method=interp_method, extrapolate=True, vec_size=num_nodes + ) units = default_units for key in self.engine_variables: @@ -790,15 +815,46 @@ def _build_engine_interpolator(self, num_nodes, aviary_inputs): self.engine_variable_units = units # add inputs and outputs to interpolator - independent_variables = [MACH, ALTITUDE, THROTTLE, HYBRID_THROTTLE] - no_scale_variables = [TEMPERATURE] + # independent variables that currently MUST be inputs + if interp_sort == 'altitude': + independent_variables = [ALTITUDE, MACH, THROTTLE, HYBRID_THROTTLE] + else: + independent_variables = [MACH, ALTITUDE, THROTTLE, HYBRID_THROTTLE] + + if self.inputs == []: + self.inputs = independent_variables + else: + for var in independent_variables: + if var in self.outputs: + raise UserWarning( + f'Variable {var} is defined as an output in {self.error_message}, but ' + 'Aviary requires it to be an input.' + ) + + no_scale_variables = [TEMPERATURE, RPM] + + # Add the first table inputs in the requested order. + for variable in independent_variables: + if variable in self.inputs and variable in self.engine_variables: + engine.add_input( + variable.value, + self.data[variable], + units=default_units[variable], + ) + + # Add the remaining variables. for variable in self.engine_variables: - if variable in independent_variables: + if variable in self.inputs: + if variable in independent_variables: + # Already handled above. + continue + engine.add_input( variable.value, self.data[variable], units=default_units[variable], ) + else: # don't append 'unscaled' to variables that will not be passed to scaling if variable in no_scale_variables: @@ -813,10 +869,10 @@ def _build_engine_interpolator(self, num_nodes, aviary_inputs): return engine - def build_mission(self, num_nodes, aviary_inputs) -> om.Group: + def build_mission(self, num_nodes, aviary_inputs, **kwargs) -> om.Group: """ Creates interpolator objects to be added to mission-level propulsion subsystem. - Interpolators must be re-generated for each ODE due to potentialy different + Interpolators must be re-generated for each ODE due to potentially different num_nodes in each mission segment. Parameters @@ -832,6 +888,7 @@ def build_mission(self, num_nodes, aviary_inputs) -> om.Group: needed for this EngineDeck. """ interp_method = self.get_val(Aircraft.Engine.INTERPOLATION_METHOD) + interp_sort = self.get_val(Aircraft.Engine.INTERPOLATION_SORT) engine_group = om.Group() @@ -846,27 +903,29 @@ def build_mission(self, num_nodes, aviary_inputs) -> om.Group: # Pre-solve max throttle/hybrid throttle for each flight condition, interpolate on # reduced data set? if self.use_thrust or self.use_shaft_power: - if self.global_throttle or (self.global_hybrid_throttle - and self.use_hybrid_throttle): + if self.global_throttle or (self.global_hybrid_throttle and self.use_hybrid_throttle): # create IndepVarComp to pass maximum throttle is to max thrust interpolator fixed_throttles = om.IndepVarComp() if self.global_throttle: - fixed_throttles.add_output('throttle_max', - val=np.ones(num_nodes) * - self.throttle_max, - units='unitless', - desc='Engine maximum throttle') + fixed_throttles.add_output( + 'throttle_max', + val=np.ones(num_nodes) * self.throttle_max, + units='unitless', + desc='Engine maximum throttle', + ) if self.global_hybrid_throttle and self.use_hybrid_throttle: - fixed_throttles.add_output('hybrid_throttle_max', - val=np.ones(num_nodes) * - self.hybrid_throttle_max, - units='unitless', - desc='Engine maximum hybrid throttle') - if not (self.global_throttle or (self.global_hybrid_throttle - and self.use_hybrid_throttle)): - interp_throttles = om.MetaModelSemiStructuredComp(method=interp_method, - extrapolate=False, - vec_size=num_nodes) + fixed_throttles.add_output( + 'hybrid_throttle_max', + val=np.ones(num_nodes) * self.hybrid_throttle_max, + units='unitless', + desc='Engine maximum hybrid throttle', + ) + if not ( + self.global_throttle or (self.global_hybrid_throttle and self.use_hybrid_throttle) + ): + interp_throttles = om.MetaModelSemiStructuredComp( + method=interp_method, extrapolate=False, vec_size=num_nodes + ) packed_data = self.packed_data mach_table = np.array([]) @@ -875,136 +934,191 @@ def build_mission(self, num_nodes, aviary_inputs) -> om.Group: for M in range(self.mach_max_count): for A in range(self.alt_max_count): if self.data_indices[M, A] != 0: - mach_table = np.append( - mach_table, packed_data[MACH][M, A, 0]) - alt_table = np.append( - alt_table, packed_data[ALTITUDE][M, A, 0]) + mach_table = np.append(mach_table, packed_data[MACH][M, A, 0]) + alt_table = np.append(alt_table, packed_data[ALTITUDE][M, A, 0]) # add inputs and outputs to interpolator - interp_throttles.add_input(Dynamic.Mission.MACH, - mach_table, - units='unitless', - desc='Current flight Mach number') - interp_throttles.add_input(Dynamic.Mission.ALTITUDE, - alt_table, - units=units[ALTITUDE], - desc='Current flight altitude') + if interp_sort == 'altitude': + interp_throttles.add_input( + Dynamic.Mission.ALTITUDE, + alt_table, + units=units[ALTITUDE], + desc='Current flight altitude', + ) + interp_throttles.add_input( + Dynamic.Atmosphere.MACH, + mach_table, + units='unitless', + desc='Current flight Mach number', + ) + else: + interp_throttles.add_input( + Dynamic.Atmosphere.MACH, + mach_table, + units='unitless', + desc='Current flight Mach number', + ) + interp_throttles.add_input( + Dynamic.Mission.ALTITUDE, + alt_table, + units=units[ALTITUDE], + desc='Current flight altitude', + ) + if not self.global_throttle: - interp_throttles.add_output('throttle_max', - self.throttle_max, - units='unitless', - desc='max throttle avaliable at current ' - 'flight condition') + interp_throttles.add_output( + 'throttle_max', + self.throttle_max, + units='unitless', + desc='max throttle available at current flight condition', + ) if not self.global_hybrid_throttle and self.use_hybrid_throttle: - interp_throttles.add_output('hybrid_throttle_max', - self.hybrid_throttle_max, - units='unitless', - desc='max hybrid throttle avaliable at ' - 'current flight condition') + interp_throttles.add_output( + 'hybrid_throttle_max', + self.hybrid_throttle_max, + units='unitless', + desc='max hybrid throttle available at current flight condition', + ) # Calculation of max thrust currently done with a duplicate of the engine # model and scaling components max_thrust_engine = om.MetaModelSemiStructuredComp( - method=interp_method, extrapolate=False, vec_size=num_nodes) - - max_thrust_engine.add_input(Dynamic.Mission.MACH, - self.data[MACH], - units='unitless', - desc='Current flight Mach number') - max_thrust_engine.add_input(Dynamic.Mission.ALTITUDE, - self.data[ALTITUDE], - units=units[ALTITUDE], - desc='Current flight altitude') + method=interp_method, extrapolate=False, vec_size=num_nodes + ) + + if interp_sort == 'altitude': + max_thrust_engine.add_input( + Dynamic.Mission.ALTITUDE, + self.data[ALTITUDE], + units=units[ALTITUDE], + desc='Current flight altitude', + ) + max_thrust_engine.add_input( + Dynamic.Atmosphere.MACH, + self.data[MACH], + units='unitless', + desc='Current flight Mach number', + ) + else: + max_thrust_engine.add_input( + Dynamic.Atmosphere.MACH, + self.data[MACH], + units='unitless', + desc='Current flight Mach number', + ) + max_thrust_engine.add_input( + Dynamic.Mission.ALTITUDE, + self.data[ALTITUDE], + units=units[ALTITUDE], + desc='Current flight altitude', + ) + # replace throttle coming from mission with max value based on flight condition - max_thrust_engine.add_input('throttle_max', - self.data[THROTTLE], - units='unitless', - desc='Current engine throttle') + max_thrust_engine.add_input( + 'throttle_max', + self.data[THROTTLE], + units='unitless', + desc='Current engine throttle', + ) if self.use_hybrid_throttle: # replace hybrid throttle coming from mission with max value based on # flight condition - max_thrust_engine.add_input('hybrid_throttle_max', - self.data[HYBRID_THROTTLE], - units='unitless', - desc='Current engine hybrid throttle') - max_thrust_engine.add_output('thrust_net_max_unscaled', - self.data[THRUST], - units=units[THRUST], - desc='maximum thrust that can currently be produced') + max_thrust_engine.add_input( + 'hybrid_throttle_max', + self.data[HYBRID_THROTTLE], + units='unitless', + desc='Current engine hybrid throttle', + ) + max_thrust_engine.add_output( + 'thrust_net_max_unscaled', + self.data[THRUST], + units=units[THRUST], + desc='maximum thrust that can currently be produced', + ) if self.use_shaft_power: if SHAFT_POWER in self.engine_variables: - max_thrust_engine.add_output('shaft_power_max_unscaled', - self.data[SHAFT_POWER], - units=units[SHAFT_POWER], - desc='maximum shaft power that can currently be produced') + max_thrust_engine.add_output( + 'shaft_power_max_unscaled', + self.data[SHAFT_POWER], + units=units[SHAFT_POWER], + desc='maximum shaft power that can currently be produced', + ) else: - max_thrust_engine.add_output('shaft_power_corrected_max_unscaled', - self.data[SHAFT_POWER_CORRECTED], - units=units[SHAFT_POWER_CORRECTED], - desc='maximum corrected shaft power that can currently be produced') + max_thrust_engine.add_output( + 'shaft_power_corrected_max_unscaled', + self.data[SHAFT_POWER_CORRECTED], + units=units[SHAFT_POWER_CORRECTED], + desc='maximum corrected shaft power that can currently be produced', + ) # add created subsystems to engine_group outputs = [] if getattr(self, 'use_t4', False): - outputs.append(Dynamic.Mission.TEMPERATURE_T4) + outputs.append(Dynamic.Vehicle.Propulsion.TEMPERATURE_T4) - engine_group.add_subsystem('interpolation', - engine, - promotes_inputs=['*'], - promotes_outputs=outputs) + engine_group.add_subsystem( + 'interpolation', engine, promotes_inputs=['*'], promotes_outputs=outputs + ) # check if uncorrection component is needed uncorrect_shp = False - if SHAFT_POWER_CORRECTED in self.engine_variables\ - and SHAFT_POWER not in self.engine_variables: + if ( + SHAFT_POWER_CORRECTED in self.engine_variables + and SHAFT_POWER not in self.engine_variables + ): uncorrect_shp = True engine_group.add_subsystem( 'uncorrect_shaft_power', - subsys=UncorrectData(num_nodes=num_nodes, aviary_options=self.options), + subsys=UncorrectData(num_nodes=num_nodes), promotes_inputs=[ - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, - Dynamic.Mission.MACH, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, ], ) - engine_group.connect('interpolation.shaft_power_corrected_unscaled', - 'uncorrect_shaft_power.corrected_data') + engine_group.connect( + 'interpolation.shaft_power_corrected_unscaled', + 'uncorrect_shaft_power.corrected_data', + ) if self.use_thrust or self.use_shaft_power: - if self.global_throttle or (self.global_hybrid_throttle - and self.use_hybrid_throttle): - engine_group.add_subsystem('fixed_max_throttles', - fixed_throttles, - promotes_outputs=['*']) - - if not (self.global_throttle or (self.global_hybrid_throttle - and self.use_hybrid_throttle)): - engine_group.add_subsystem('interp_max_throttles', - interp_throttles, - promotes_inputs=['*'], - promotes_outputs=['*']) + if self.global_throttle or (self.global_hybrid_throttle and self.use_hybrid_throttle): + engine_group.add_subsystem( + 'fixed_max_throttles', fixed_throttles, promotes_outputs=['*'] + ) + + if not ( + self.global_throttle or (self.global_hybrid_throttle and self.use_hybrid_throttle) + ): + engine_group.add_subsystem( + 'interp_max_throttles', + interp_throttles, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) engine_group.add_subsystem( - 'max_interpolation', - max_thrust_engine, - promotes_inputs=['*']) + 'max_interpolation', max_thrust_engine, promotes_inputs=['*'] + ) if uncorrect_shp: engine_group.add_subsystem( 'uncorrect_max_shaft_power', subsys=UncorrectData( - num_nodes=num_nodes, aviary_options=self.options + num_nodes=num_nodes, ), promotes_inputs=[ - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE, - Dynamic.Mission.MACH, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, ], ) - engine_group.connect('max_interpolation.shaft_power_corrected_max_unscaled', - 'uncorrect_max_shaft_power.corrected_data') + engine_group.connect( + 'max_interpolation.shaft_power_corrected_max_unscaled', + 'uncorrect_max_shaft_power.corrected_data', + ) engine_outputs = self.engine_variables.copy() if SHAFT_POWER_CORRECTED in engine_outputs: @@ -1015,10 +1129,9 @@ def build_mission(self, num_nodes, aviary_inputs) -> om.Group: 'engine_scaling', subsys=EngineScaling( num_nodes=num_nodes, - aviary_options=self.options, engine_variables=engine_outputs, ), - promotes_inputs=[Aircraft.Engine.SCALE_FACTOR, Dynamic.Mission.MACH], + promotes_inputs=[Aircraft.Engine.SCALE_FACTOR, Dynamic.Atmosphere.MACH], promotes_outputs=['*'], ) @@ -1031,6 +1144,7 @@ def build_mission(self, num_nodes, aviary_inputs) -> om.Group: HYBRID_THROTTLE, TEMPERATURE, SHAFT_POWER_CORRECTED, + RPM, ] for variable in self.engine_variables: @@ -1058,18 +1172,26 @@ def build_mission(self, num_nodes, aviary_inputs) -> om.Group: return engine_group def get_parameters(self): - params = {Aircraft.Engine.SCALE_FACTOR: {'static_target': True}} + params = { + Aircraft.Engine.SCALE_FACTOR: { + 'val': 1.0, + 'units': 'unitless', + 'static_target': True, + } + } return params def report(self, problem, reports_file, **kwargs): meta_data = kwargs['meta_data'] engine_idx = kwargs['engine_idx'] - outputs = [Aircraft.Engine.NUM_ENGINES, - Aircraft.Engine.SCALED_SLS_THRUST, - Aircraft.Engine.SCALE_FACTOR] + outputs = [ + Aircraft.Engine.NUM_ENGINES, + Aircraft.Engine.SCALED_SLS_THRUST, + Aircraft.Engine.SCALE_FACTOR, + ] - # modified version of markdown table util adjusted to handle engine decks + # modified version of markdown table until adjusted to handle engine decks with open(reports_file, mode='a') as f: f.write(f'\n### {self.name}') f.write('\n| Variable Name | Value | Units |\n') @@ -1116,7 +1238,7 @@ def report(self, problem, reports_file, **kwargs): # handle rounding + formatting if isinstance(val, (np.ndarray, list, tuple)): val = [round_it(item) for item in val] - # if an interable with a length of 1, remove bracket/paretheses, etc. + # if an interable with a length of 1, remove bracket/parentheses, etc. if len(val) == 1: val = val[0] else: @@ -1147,27 +1269,38 @@ def _set_reference_thrust(self): alt_tol = self.alt_tol mach_tol = self.mach_tol # NOTE This fails if there is no data point at SLS (within tolerance) - sea_level_idx = (np.intersect1d( + sea_level_idx = np.intersect1d( np.where(-alt_tol < self.data[ALTITUDE])[0], - np.where(self.data[ALTITUDE] <= alt_tol)[0])) - static_idx = (np.intersect1d( + np.where(self.data[ALTITUDE] <= alt_tol)[0], + ) + static_idx = np.intersect1d( np.where(-mach_tol < self.data[MACH]), - np.where(self.data[MACH] < self.mach_tol))) + np.where(self.data[MACH] < self.mach_tol), + ) sls_idx = np.intersect1d(sea_level_idx, static_idx) if sls_idx.size == 0: raise UserWarning( - 'Could not find sea-level static max thrust point for ' - f'EngineDeck <{self.name}>. Please review the data ' - f'file <{self.get_val(Aircraft.Engine.DATA_FILE)}> or ' - 'manually specify Aircraft.Engine.REFERENCE_SLS_THRUST ' - 'in EngineDeck options' + 'Could not find sea-level static max thrust point for EngineDeck ' + f'<{self.name}>. Please review the data file ' + f'<{self.get_val(Aircraft.Engine.DATA_FILE)}> or manually specify ' + 'aircraft:engine:reference_sls_thrust in EngineDeck options' ) reference_sls_thrust = max(self.data[THRUST][sls_idx]) - self.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, - reference_sls_thrust, units=self.engine_variables[THRUST]) + if self.get_val(Settings.VERBOSITY) >= Verbosity.VERBOSE: + print( + f'EngineDeck <{self.name}>: found reference SLS thrust of ' + f'{reference_sls_thrust} {self.engine_variables[THRUST]} in ' + 'provided performance data' + ) + + self.set_val( + Aircraft.Engine.REFERENCE_SLS_THRUST, + reference_sls_thrust, + units=self.engine_variables[THRUST], + ) # Update SCALED_SLS_THRUST if required based on scaling information provided scale_performance = self.get_val(Aircraft.Engine.SCALE_PERFORMANCE) @@ -1187,41 +1320,76 @@ def _set_reference_thrust(self): # both scale factor and target thrust provided: if thrust_provided: scaled_thrust = self.get_val(Aircraft.Engine.SCALED_SLS_THRUST, 'lbf') - if scale_performance: # using very rough tolerance - if not math.isclose(scaled_thrust/ref_thrust, scale_factor, abs_tol=1e-2): + if scale_performance: + # Check if target thrust and ref thrust * scale factor match using + # rough tolerance + # Tolerance is arbitrary, but designed to handle thrusts in the + # hundreds of thousands via rel_tol, and the hundreds via abs_tol + if not math.isclose( + scaled_thrust, + ref_thrust * scale_factor, + abs_tol=1e-1, + rel_tol=1e-4, + ): # user wants scaling but provided conflicting inputs, # cannot be resolved raise AttributeError( - f'EngineModel <{self.name}>: Conflicting values provided ' + f'EngineDeck <{self.name}>: Conflicting values provided ' 'for aircraft:engine:scale_factor and ' - 'aircraft:engine:scaled_sls_thrust' + 'aircraft:engine:scaled_sls_thrust when compared against ' + 'aircraft:engine:reference_sls_thrust' ) # get thrust target & scale factor matching exactly. Scale factor is # design variable, so don't touch it!! Instead change output thrust else: - self.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - ref_thrust*scale_factor, 'lbf') + target_thrust = ref_thrust * scale_factor + if self.get_val(Settings.VERBOSITY) >= Verbosity.VERBOSE: + warnings.warn( + f'EngineDeck <{self.name}>: ' + 'aircraft:engine:scaled_sls_thrust and ' + 'product of aircraft:engine_scale_factor and ' + 'aircraft:engine:reference_sls_thrust are not an exact ' + 'match but within tolerance. Setting scaled thrust ' + f'target to calculated value of {target_thrust} lbf.' + ) + self.set_val(Aircraft.Engine.SCALED_SLS_THRUST, target_thrust, 'lbf') else: - # engine is not scaled: just make sure scaled thrust = ref thrust - self.set_val( - Aircraft.Engine.SCALED_SLS_THRUST, ref_thrust, 'lbf') + # engine is not scaled: make sure scaled thrust = ref thrust and + # scale factor = 1 + self.set_val(Aircraft.Engine.SCALED_SLS_THRUST, ref_thrust, 'lbf') + self.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) # scale factor provided, but not target thrust else: # calculate new scaled thrust value - scaled_thrust = ref_thrust*scale_factor + scaled_thrust = ref_thrust * scale_factor self.set_val(Aircraft.Engine.SCALED_SLS_THRUST, scaled_thrust, 'lbf') + # target thrust provided, but not scale factor + elif thrust_provided: + scaled_thrust = self.get_val(Aircraft.Engine.SCALED_SLS_THRUST, 'lbf') + if scale_performance: + scale_factor = scaled_thrust / ref_thrust + if self.get_val(Settings.VERBOSITY) >= Verbosity.VERBOSE: + warnings.warn( + f'EngineDeck <{self.name}>: aircraft:engine:scale_factor has ' + 'been indirectly set by the ratio of ' + 'aircraft:engine:scaled_sls_thrust and ' + f'aircraft:engine:reference_sls_thrust to {scale_factor}' + ) + self.set_val(Aircraft.Engine.SCALE_FACTOR, scale_factor) + else: + # engine is not scaled: just make sure scale_factor = 1 + self.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) + # neither scale factor nor target thrust are provided - if not scale_factor_provided and not thrust_provided: + elif not thrust_provided: if scale_performance: # user wants to scale, but provided no scaling info: default to # scale factor of 1, set scaled thrust = ref thrust scale_factor = 1 - self.set_val( - Aircraft.Engine.SCALE_FACTOR, scale_factor) - self.set_val( - Aircraft.Engine.SCALED_SLS_THRUST, ref_thrust, 'lbf') + self.set_val(Aircraft.Engine.SCALE_FACTOR, scale_factor) + self.set_val(Aircraft.Engine.SCALED_SLS_THRUST, ref_thrust, 'lbf') else: # engine is not scaled: just make sure scaled thrust = ref thrust scaled_thrust = ref_thrust @@ -1239,10 +1407,12 @@ def _normalize_throttle(self): Normalization can be "global" (using max and min values from entire data set), or "local" (using the max and min values from each individual flight condition). """ + def _hybrid_throttle_norm(hybrid_throttle_list): """ - Normalize hybrid throttle to the scale: + Normalizes hybrid throttle. + Uses the scale: [-1 (minimum negative hybrid throttle) <-> 0 (idle hybrid throttle) <-> 1 (max positive hybrid throttle)] @@ -1286,10 +1456,17 @@ def _hybrid_throttle_norm(hybrid_throttle_list): return norm_hybrid_list + # vectors of the normalized throttle data normalized_throttle = np.array([]) normalized_hybrid_throttle = np.array([]) + + # Min and max throttle value vectors + # If using "global" throttle setting, max & min are single values and these are unused, + # otherwise they contain min or max throttle per unique flight condition throttle_min = np.array([]) throttle_max = np.array([]) + hybrid_throttle_min = np.array([]) + hybrid_throttle_max = np.array([]) # information on packed data packed_throttle = self.packed_data[THROTTLE] @@ -1304,9 +1481,8 @@ def _hybrid_throttle_norm(hybrid_throttle_list): continue if not self.global_throttle: - throttle_list = normalize( - packed_throttle[M, A][:data_indices[M, A]+1]) # normalize throttles for this flight condition from 0 to 1 + throttle_list = normalize(packed_throttle[M, A][: data_indices[M, A] + 1]) normalized_throttle = np.append(normalized_throttle, throttle_list) throttle_min = np.append(throttle_min, min(throttle_list)) throttle_max = np.append(throttle_max, max(throttle_list)) @@ -1314,13 +1490,13 @@ def _hybrid_throttle_norm(hybrid_throttle_list): if not self.global_hybrid_throttle and self.use_hybrid_throttle: # normalize hybrid throttles for this flight condition hybrid_throttle_list = _hybrid_throttle_norm( - packed_hybrid_throttle[M, A][:data_indices[M, A]+1]) + packed_hybrid_throttle[M, A][: data_indices[M, A] + 1] + ) normalized_hybrid_throttle = np.append( - normalized_hybrid_throttle, hybrid_throttle_list) - hybrid_throttle_min = np.append( - hybrid_throttle_min, min(hybrid_throttle_list)) - hybrid_throttle_max = np.append( - hybrid_throttle_max, max(hybrid_throttle_list)) + normalized_hybrid_throttle, hybrid_throttle_list + ) + hybrid_throttle_min = np.append(hybrid_throttle_min, min(hybrid_throttle_list)) + hybrid_throttle_max = np.append(hybrid_throttle_max, max(hybrid_throttle_list)) # store normalized throttle data if self.global_throttle: @@ -1350,9 +1526,12 @@ def _hybrid_throttle_norm(hybrid_throttle_list): def _sort_data(self): """ - Sort unpacked engine data in order of mach number, altitude, throttle, + Sort unpacked engine data in order based on Aircraft.Engine.INTERPOLATION_SORT. When this + is set to "mach", sort by Mach number, altitude, throttle. When it is set to "altitude", + sort by altitude, Mach number, throttle. hybrid throttle. """ + interp_sort = self.get_val(Aircraft.Engine.INTERPOLATION_SORT) engine_data = self.data # sort engine data to ensure independent variables are always in @@ -1361,12 +1540,26 @@ def _sort_data(self): # convert engine_data from dict to list so it can be sorted sorted_values = np.array([engine_data[key] for key in engine_data]).transpose() - # Sort by mach, then altitude, then throttle, then hybrid throttle - sorted_values = sorted_values[np.lexsort( - [engine_data[HYBRID_THROTTLE], - engine_data[THROTTLE], - engine_data[ALTITUDE], - engine_data[MACH]])] + if interp_sort == 'altitude': + # Sort by mach, then altitude, then throttle, then hybrid throttle + sort_keys = [ + engine_data[HYBRID_THROTTLE], + engine_data[THROTTLE], + engine_data[MACH], + engine_data[ALTITUDE], + ] + + else: + # Sort by mach, then altitude, then throttle, then hybrid throttle + sort_keys = [ + engine_data[HYBRID_THROTTLE], + engine_data[THROTTLE], + engine_data[ALTITUDE], + engine_data[MACH], + ] + + sorted_values = sorted_values[np.lexsort(sort_keys)] + for idx, var in enumerate(engine_data): engine_data[var] = sorted_values[:, idx] @@ -1396,7 +1589,6 @@ def _pack_data(self): packed_data[key] = np.zeros((mach_max_count, alt_max_count, data_max_count)) for M in range(mach_max_count): - for A in range(alt_max_count): if data_indices[M, A] == 0: # skip point if there is no data @@ -1421,11 +1613,13 @@ def _count_data(self): If insufficient number of altitude points (<2) provided for a given Mach number. """ + interp_sort = self.get_val(Aircraft.Engine.INTERPOLATION_SORT) + mach_count = 0 - # First mach number must have at least one altitude associated with it + # First Mach number must have at least one altitude associated with it alt_count = 1 max_alt_count = 0 - # First mach number must have at least one data point associated with it + # First Mach number must have at least one data point associated with it data_count = 1 max_data_count = 0 @@ -1446,13 +1640,23 @@ def _count_data(self): alt = altitudes[idx] if math.isclose(mach_num, curr_mach, abs_tol=self.mach_tol): - if math.isclose(alt, curr_alt, abs_tol=self.alt_tol): data_indices[mach_count - 1, alt_count - 1] = data_count data_count += 1 else: - # new altitude for this mach number, count it + # new altitude for this Mach number, count it + + # if there are less than two Machs for this altitude, quit + if interp_sort == 'altitude': + if mach_count < 2 and alt_count > 0: + raise UserWarning( + 'Only one Mach provided for altitude ' + f'{altitudes[alt_count]:6.3f} in engine data ' + 'file ' + f'<{self.get_val(Aircraft.Engine.DATA_FILE).name}>' + ) + curr_alt = alt alt_count += 1 data_indices = extend_array(data_indices, [mach_count, alt_count]) @@ -1466,16 +1670,18 @@ def _count_data(self): else: # new Mach number + # if there are less than two altitudes for this Mach number, quit - if alt_count < 2 and mach_count > 0: - raise UserWarning( - 'Only one altitude provided for Mach number ' - f'{mach_numbers[mach_count]:6.3f} in engine data ' - 'file ' - f'<{self.get_val(Aircraft.Engine.DATA_FILE).name}>' - ) + if interp_sort == 'mach': + if alt_count < 2 and mach_count > 0: + raise UserWarning( + 'Only one altitude provided for Mach number ' + f'{mach_numbers[mach_count]:6.3f} in engine data ' + 'file ' + f'<{self.get_val(Aircraft.Engine.DATA_FILE).name}>' + ) - # record and count mach numbers + # record and count Mach numbers curr_mach = mach_num mach_count += 1 @@ -1543,11 +1749,11 @@ def normalize(base_list, maximum=None, minimum=None): def extend_array(inp_array, size): """ - Extends input array such that it is at least as large as the target size in - all dimensions. If input array is smaller in any dimension, extends input - array to match target size in that dimension. Works on arrays up to 3 - dimensions. Returns copy of input array extended in required dimensions with newly - created points set to 0. + Extends input array such that it is at least as large as the target size in each dimension. + Works on arrays of any dimension. + Returns copy of input array extended in required dimensions with newly created points set to 0. + If requested size is smaller than inp_array in any dimensions, original inp_array is not + modified along that dimension. Parameters ---------- @@ -1559,24 +1765,28 @@ def extend_array(inp_array, size): Returns ------- inp_array : numpy.ndarray - The provided array extended in the desired dimensions with with newly created - points set to 0. + The provided array extended in the desired dimensions with newly created points set to 0. """ - # TODO may be built-in numpy functions that can replace this and support n dimensions - dims = np.array(np.shape(inp_array)) - while size[0] > dims[0]: - inp_array = np.concatenate( - (inp_array, np.zeros((1, *dims[1:]))), 0) - dims[0] += 1 - if len(dims) > 1: - while size[1] > dims[1]: - inp_array = np.concatenate( - (inp_array, np.zeros((dims[0], 1, *dims[2:]))), 1) - dims[1] += 1 - if len(dims) > 2: - while size[2] > dims[2]: - inp_array = np.concatenate( - (inp_array, np.zeros((*dims[:2], 1))), 2) - dims[2] += 1 - - return inp_array + # Convert input to numpy array if it isn't already + inp_array = np.asarray(inp_array) + + # Calculate padding needed for each dimension + current_shape = np.array(inp_array.shape) + target_shape = np.array(size) + + # If target has more dimensions, add new dimensions to input array + if len(target_shape) > len(current_shape): + # Create new shape with additional dimensions of size 1 + new_shape = np.ones(len(target_shape), dtype=int) + new_shape[: len(current_shape)] = current_shape + # Reshape input array to add new dimensions + inp_array = inp_array.reshape(new_shape) + current_shape = np.array(inp_array.shape) + + padding = np.maximum(0, target_shape - current_shape) + + # Create padding tuple for np.pad + pad_width = tuple((0, p) for p in padding) + + # Pad array with zeros + return np.pad(inp_array, pad_width, mode='constant', constant_values=0) diff --git a/aviary/subsystems/propulsion/engine_model.py b/aviary/subsystems/propulsion/engine_model.py index c2200da2ff..6ce59d69d4 100644 --- a/aviary/subsystems/propulsion/engine_model.py +++ b/aviary/subsystems/propulsion/engine_model.py @@ -5,14 +5,15 @@ ------- EngineModel : the interface for an engine model builder. """ + import warnings import numpy as np from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Settings from aviary.variable_info.enums import Verbosity +from aviary.variable_info.variables import Settings class EngineModel(SubsystemBuilderBase): @@ -40,7 +41,7 @@ class EngineModel(SubsystemBuilderBase): default_name = 'engine_model' def __init__( - self, name: str = None, options: AviaryValues = None, meta_data: dict = None, + self, name: str = None, options: AviaryValues = None, meta_data: dict = None, **kwargs ): super().__init__(name, meta_data=meta_data) if options is not None: @@ -61,9 +62,12 @@ def _setup(self, **kwargs): All attributes and values for options in EngineModel are finalized for analysis. """ + DeprecationWarning( + 'EngineModel._setup() is redundant and will be removed in a future update.' + ) self._preprocess_inputs() - def build_pre_mission(self, aviary_inputs): + def build_pre_mission(self, aviary_inputs, **kwargs): """ Build an OpenMDAO system for the pre-mission computations of the engine model, such as sizing. @@ -80,7 +84,7 @@ def build_pre_mission(self, aviary_inputs): """ return None - def build_mission(self, num_nodes, aviary_inputs): + def build_mission(self, num_nodes, aviary_inputs, **kwargs): """ Build an OpenMDAO system for the mission computations of the engine model. @@ -95,10 +99,12 @@ def build_mission(self, num_nodes, aviary_inputs): being integrated as well as any other variables that vary during the mission. """ - raise NotImplementedError('build_mission() is a required method but has not ' - f'been implemented in EngineModel <{self.name}>') + raise NotImplementedError( + 'build_mission() is a required method but has not ' + f'been implemented in EngineModel <{self.name}>' + ) - def build_post_mission(self, aviary_inputs): + def build_post_mission(self, aviary_inputs, phase_info, phase_mission_bus_lengths, **kwargs): """ Build an OpenMDAO system for the post-mission computations of the engine model. @@ -135,38 +141,41 @@ def _preprocess_inputs(self): if not isinstance(options, AviaryValues): raise TypeError('EngineModel options must be an AviaryValues object') - for (key, (val, units)) in options: + for key, (val, units) in options: # only perform vector check for variables related to engines and nacelles if key.startswith('aircraft:engine:') or key.startswith('aircraft:nacelle'): # if val is an iterable... if type(val) in (list, np.ndarray, tuple): # but meta_data says it is not supposed to be... - if not isinstance(self.meta_data[key]['default_value'], - (list, np.ndarray, tuple)): - + if not isinstance( + self.meta_data[key]['default_value'], (list, np.ndarray, tuple) + ): # if val is multidimensional, raise error if isinstance(val[0], (list, np.ndarray, tuple)): - raise UserWarning(f'Multidimensional {type(val)} was given ' - f'for variable {key} in EngineModel ' - f'<{self.name}>, but ' - f"{type(self.meta_data[key]['default_value'])} " - 'was expected.') + raise UserWarning( + f'Multidimensional {type(val)} was given for variable ' + f'{key} in EngineModel <{self.name}>, but ' + f'{type(self.meta_data[key]["default_value"])} ' + 'was expected.' + ) # use first item in val and warn user if verbosity >= 1: if len(val) > 1: warnings.warn( f'The value of {key} passed to EngineModel ' - f'<{self.name}> is {type(val)}. Only the first entry in ' - 'this iterable will be used.') + f'<{self.name}> is {type(val)}. Only the first ' + 'entry in this iterable will be used.' + ) # if val is supposed to be an iterable... else: # but val is multidimensional, use first item and warn user if isinstance(val[0], (list, np.ndarray, tuple)): warnings.warn( - f'The value of {key} passed to EngineModel <{self.name}> ' - f'is multidimensional {type(val)}. Only the first entry ' - 'in this iterable will be used.') + f'The value of {key} passed to EngineModel ' + f'<{self.name}> is multidimensional {type(val)}. Only ' + 'the first entry in this iterable will be used.' + ) # and val is 1-D, then it is ok! else: continue @@ -186,9 +195,7 @@ def _preprocess_inputs(self): # options.delete(key) def update(self, options: AviaryValues, **kwargs): - """ - Given a new set of AviaryValues, update the engine model and rerun setup. - """ + """Given a new set of AviaryValues, update the engine model and rerun setup.""" self.options = options.deepcopy() self._setup(**kwargs) @@ -198,7 +205,7 @@ def get_val(self, key, units='unitless'): Returns desired value from options in specified units. Parameters - ------- + ---------- key : str Name of requested option. units : str @@ -212,7 +219,7 @@ def get_val(self, key, units='unitless'): return self.options.get_val(key, units) def get_item(self, key, default=(None, None)): - ''' + """ Return the named value and its associated units. Note, this method never raises `KeyError` or `TypeError`. @@ -228,7 +235,7 @@ def get_item(self, key, default=(None, None)): Returns ------- OptionalValueAndUnits - ''' + """ return self.options.get_item(key, default) def set_val(self, key, val, units='unitless'): @@ -236,7 +243,7 @@ def set_val(self, key, val, units='unitless'): Updates desired value in options with specified units. Parameters - ------- + ---------- key : str Name of option whose value will be updated. val diff --git a/aviary/subsystems/propulsion/engine_scaling.py b/aviary/subsystems/propulsion/engine_scaling.py index 2366aff8a0..2bb833e8e7 100644 --- a/aviary/subsystems/propulsion/engine_scaling.py +++ b/aviary/subsystems/propulsion/engine_scaling.py @@ -1,12 +1,10 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.subsystems.propulsion.utils import EngineModelVariables, max_variables -from aviary.variable_info.functions import add_aviary_input +from aviary.variable_info.functions import add_aviary_input, add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Mission - MACH = EngineModelVariables.MACH ALTITUDE = EngineModelVariables.ALTITUDE THROTTLE = EngineModelVariables.THROTTLE @@ -28,36 +26,43 @@ class EngineScaling(om.ExplicitComponent): - ''' + """ Scales an engine's thrust, fuel flow rate, nox rate, exit area, and electric power based on provided scaling factors. Can be vectorized for all unique engine present on aircraft. Each index represents a single instance of an engine model. - ''' + """ def initialize(self): self.options.declare('num_nodes', types=int) - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') - self.options.declare( 'engine_variables', types=dict, desc='dict of variables to be scaled for this engine with units', ) + add_aviary_option(self, Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, units='lbm/h') + add_aviary_option(self, Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM) + add_aviary_option(self, Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM) + add_aviary_option(self, Aircraft.Engine.SCALE_PERFORMANCE) + add_aviary_option(self, Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER) + add_aviary_option(self, Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER) + add_aviary_option(self, Mission.Summary.FUEL_FLOW_SCALER) + def setup(self): nn = self.options['num_nodes'] - options: AviaryValues = self.options['aviary_options'] engine_variables = self.options['engine_variables'] add_aviary_input(self, Aircraft.Engine.SCALE_FACTOR, val=1.0) - self.add_input(Dynamic.Mission.MACH, val=np.zeros(nn), - desc='current Mach number', units='unitless') + self.add_input( + Dynamic.Atmosphere.MACH, + val=np.zeros(nn), + desc='current Mach number', + units='unitless', + ) # loop through all variables, special handling for fuel flow to output negative version # add outputs for 'max' counterpart of variables that have them @@ -71,7 +76,7 @@ def setup(self): if variable is FUEL_FLOW: self.add_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, val=np.zeros(nn), units=engine_variables[variable], ) @@ -96,24 +101,21 @@ def setup(self): ) def compute(self, inputs, outputs): - nn = self.options['num_nodes'] - options: AviaryValues = self.options['aviary_options'] - engine_variables = self.options['engine_variables'] - scale_performance = options.get_val(Aircraft.Engine.SCALE_PERFORMANCE) - - subsonic_fuel_factor = options.get_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER) - supersonic_fuel_factor = options.get_val( - Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER) - constant_fuel_term = options.get_val( - Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM) - linear_fuel_term = options.get_val(Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM) - constant_fuel_flow = options.get_val( - Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, units='lbm/h') - mission_fuel_scaler = options.get_val(Mission.Summary.FUEL_FLOW_SCALER) + options = self.options + nn = options['num_nodes'] + engine_variables = options['engine_variables'] + scale_performance = options[Aircraft.Engine.SCALE_PERFORMANCE] + + subsonic_fuel_factor = options[Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER] + supersonic_fuel_factor = options[Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER] + constant_fuel_term = options[Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM] + linear_fuel_term = options[Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM] + constant_fuel_flow, _ = options[Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION] + mission_fuel_scaler = options[Mission.Summary.FUEL_FLOW_SCALER] # thrust-based engine scaling factor engine_scale_factor = inputs[Aircraft.Engine.SCALE_FACTOR] - mach_number = inputs[Dynamic.Mission.MACH] + mach_number = inputs[Dynamic.Atmosphere.MACH] scale_factor = 1 fuel_flow_scale_factor = np.ones(nn, dtype=engine_scale_factor.dtype) @@ -126,16 +128,22 @@ def compute(self, inputs, outputs): # Calculate fuel flow rate scaling factor using FLOPS-derived equation fuel_flow_equation_scaling = ( - 1 + constant_fuel_term + linear_fuel_term * (1 - engine_scale_factor)) + 1 + constant_fuel_term + linear_fuel_term * (1 - engine_scale_factor) + ) # use dtype to make complex safe - fuel_flow_mach_scaling = np.ones( - nn, dtype=engine_scale_factor.dtype) * subsonic_fuel_factor + fuel_flow_mach_scaling = ( + np.ones(nn, dtype=engine_scale_factor.dtype) * subsonic_fuel_factor + ) supersonic_idx = np.where(mach_number >= 1.0) fuel_flow_mach_scaling[supersonic_idx] = supersonic_fuel_factor - fuel_flow_scale_factor = engine_scale_factor * fuel_flow_mach_scaling\ - * fuel_flow_equation_scaling * mission_fuel_scaler + fuel_flow_scale_factor = ( + engine_scale_factor + * fuel_flow_mach_scaling + * fuel_flow_equation_scaling + * mission_fuel_scaler + ) scale_factor = engine_scale_factor @@ -144,14 +152,12 @@ def compute(self, inputs, outputs): for variable in engine_variables: if variable not in skip_variables: if variable is FUEL_FLOW: - outputs[Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE] = -( + outputs[Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE] = -( inputs['fuel_flow_rate_unscaled'] * fuel_flow_scale_factor + constant_fuel_flow ) else: - outputs[variable.value] = ( - inputs[variable.value + '_unscaled'] * scale_factor - ) + outputs[variable.value] = inputs[variable.value + '_unscaled'] * scale_factor if variable in max_variables: outputs[variable.value + '_max'] = ( @@ -170,13 +176,13 @@ def setup_partials(self): if variable not in skip_variables: if variable is FUEL_FLOW: self.declare_partials( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, Aircraft.Engine.SCALE_FACTOR, rows=r, cols=c, ) self.declare_partials( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, 'fuel_flow_rate_unscaled', rows=r, cols=r, @@ -210,20 +216,18 @@ def setup_partials(self): ) def compute_partials(self, inputs, J): - nn = self.options['num_nodes'] - options: AviaryValues = self.options['aviary_options'] - engine_variables = self.options['engine_variables'] - scale_performance = options.get_val(Aircraft.Engine.SCALE_PERFORMANCE) - - subsonic_fuel_factor = options.get_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER) - supersonic_fuel_factor = options.get_val( - Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER) - constant_fuel_term = options.get_val( - Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, units='unitless') - linear_fuel_term = options.get_val(Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM) - mission_fuel_scaler = options.get_val(Mission.Summary.FUEL_FLOW_SCALER) - - mach_number = inputs[Dynamic.Mission.MACH] + options = self.options + nn = options['num_nodes'] + engine_variables = options['engine_variables'] + scale_performance = options[Aircraft.Engine.SCALE_PERFORMANCE] + + subsonic_fuel_factor = options[Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER] + supersonic_fuel_factor = options[Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER] + constant_fuel_term = options[Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM] + linear_fuel_term = options[Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM] + mission_fuel_scaler = options[Mission.Summary.FUEL_FLOW_SCALER] + + mach_number = inputs[Dynamic.Atmosphere.MACH] engine_scale_factor = inputs[Aircraft.Engine.SCALE_FACTOR] # determine which mach-based fuel flow scaler is applied at each node @@ -239,9 +243,7 @@ def compute_partials(self, inputs, J): if FUEL_FLOW in engine_variables: # Calculate fuel flow rate scaling factor using FLOPS-derived equation fuel_flow_equation_scaling = ( - 1 - + constant_fuel_term - + linear_fuel_term * (1 - engine_scale_factor) + 1 + constant_fuel_term + linear_fuel_term * (1 - engine_scale_factor) ) fuel_flow_deriv = ( @@ -270,11 +272,11 @@ def compute_partials(self, inputs, J): if variable not in skip_variables: if variable is FUEL_FLOW: J[ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, 'fuel_flow_rate_unscaled', ] = fuel_flow_deriv J[ - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, Aircraft.Engine.SCALE_FACTOR, ] = fuel_flow_scale_deriv else: @@ -284,9 +286,7 @@ def compute_partials(self, inputs, J): ) if variable in max_variables: - J[variable.value + '_max', variable.value + '_max_unscaled'] = ( - scale_factor - ) + J[variable.value + '_max', variable.value + '_max_unscaled'] = scale_factor J[variable.value + '_max', Aircraft.Engine.SCALE_FACTOR] = ( inputs[variable.value + '_max_unscaled'] * deriv_factor ) diff --git a/aviary/subsystems/propulsion/engine_sizing.py b/aviary/subsystems/propulsion/engine_sizing.py index 379c5272b4..84c43dbd62 100644 --- a/aviary/subsystems/propulsion/engine_sizing.py +++ b/aviary/subsystems/propulsion/engine_sizing.py @@ -1,29 +1,26 @@ -import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft class SizeEngine(om.ExplicitComponent): - ''' + """ Calculates thrust scaling factors for mission performance parameters. Designed for use with EngineDecks. Can be vectorized for all unique engines present on aircraft. Each index represents a single instance of an engine model. - ''' + """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.REFERENCE_SLS_THRUST, units='lbf') + add_aviary_option(self, Aircraft.Engine.SCALE_PERFORMANCE) def setup(self): - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, val=0.0) + add_aviary_input(self, Aircraft.Engine.SCALE_FACTOR, val=1.0) - add_aviary_output(self, Aircraft.Engine.SCALE_FACTOR, val=0.0) + add_aviary_output(self, Aircraft.Engine.SCALED_SLS_THRUST, val=0.0) # variables that also may require scaling # TODO - inlet_weight @@ -34,36 +31,27 @@ def setup(self): # TODO - nacelle_wetted_area: if length, diam get scaled - this should be covered by geom def compute(self, inputs, outputs): - options: AviaryValues = self.options['aviary_options'] + scale_engine = self.options[Aircraft.Engine.SCALE_PERFORMANCE] + reference_sls_thrust, _ = self.options[Aircraft.Engine.REFERENCE_SLS_THRUST] - scale_engine = options.get_val(Aircraft.Engine.SCALE_PERFORMANCE) - - reference_sls_thrust = options.get_val(Aircraft.Engine.REFERENCE_SLS_THRUST, - units='lbf') - - scaled_sls_thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] + engine_scale_factor = inputs[Aircraft.Engine.SCALE_FACTOR] # Engine is only scaled if required # engine scale factor is ratio of scaled thrust target and reference thrust - engine_scale_factor = 1 if scale_engine: - engine_scale_factor = scaled_sls_thrust / reference_sls_thrust + scaled_sls_thrust = engine_scale_factor * reference_sls_thrust + else: + scaled_sls_thrust = reference_sls_thrust - outputs[Aircraft.Engine.SCALE_FACTOR] = engine_scale_factor + outputs[Aircraft.Engine.SCALED_SLS_THRUST] = scaled_sls_thrust def setup_partials(self): - self.declare_partials(Aircraft.Engine.SCALE_FACTOR, - Aircraft.Engine.SCALED_SLS_THRUST) - - def compute_partials(self, inputs, J): - options: AviaryValues = self.options['aviary_options'] - scale_engine = options.get_val(Aircraft.Engine.SCALE_PERFORMANCE) - reference_sls_thrust = options.get_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, units='lbf') + scale_engine = self.options[Aircraft.Engine.SCALE_PERFORMANCE] - deriv_scale_factor = 0 if scale_engine: - deriv_scale_factor = 1.0 / reference_sls_thrust + self.declare_partials(Aircraft.Engine.SCALED_SLS_THRUST, Aircraft.Engine.SCALE_FACTOR) + + def compute_partials(self, inputs, J): + reference_sls_thrust, _ = self.options[Aircraft.Engine.REFERENCE_SLS_THRUST] - J[Aircraft.Engine.SCALE_FACTOR, - Aircraft.Engine.SCALED_SLS_THRUST] = deriv_scale_factor + J[Aircraft.Engine.SCALED_SLS_THRUST, Aircraft.Engine.SCALE_FACTOR] = reference_sls_thrust diff --git a/aviary/subsystems/propulsion/gearbox/gearbox_builder.py b/aviary/subsystems/propulsion/gearbox/gearbox_builder.py index f850f3870a..44a8d37400 100644 --- a/aviary/subsystems/propulsion/gearbox/gearbox_builder.py +++ b/aviary/subsystems/propulsion/gearbox/gearbox_builder.py @@ -1,6 +1,6 @@ -from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.subsystems.propulsion.gearbox.model.gearbox_premission import GearboxPreMission from aviary.subsystems.propulsion.gearbox.model.gearbox_mission import GearboxMission +from aviary.subsystems.propulsion.gearbox.model.gearbox_premission import GearboxPreMission +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -26,47 +26,45 @@ def __init__(self, name='gearbox', include_constraints=True): def build_pre_mission(self, aviary_inputs): """Builds an OpenMDAO system for the pre-mission computations of the subsystem.""" - return GearboxPreMission(aviary_inputs=aviary_inputs, simple_mass=True) + return GearboxPreMission(simple_mass=True) def build_mission(self, num_nodes, aviary_inputs): """Builds an OpenMDAO system for the mission computations of the subsystem.""" - return GearboxMission(num_nodes=num_nodes, aviary_inputs=aviary_inputs) + return GearboxMission(num_nodes=num_nodes) def get_design_vars(self): """ Design vars are only tested to see if they exist in pre_mission - Returns a dictionary of design variables for the gearbox subsystem, where the keys are the - names of the design variables, and the values are dictionaries that contain the units for - the design variable, the lower and upper bounds for the design variable, and any + Returns a dictionary of design variables for the gearbox subsystem, where the keys are the + names of the design variables, and the values are dictionaries that contain the units for + the design variable, the lower and upper bounds for the design variable, and any additional keyword arguments required by OpenMDAO for the design variable. """ - DVs = { Aircraft.Engine.Gearbox.GEAR_RATIO: { - 'opt': True, 'units': 'unitless', 'lower': 1.0, 'upper': 20.0, - 'val': 10 # initial value + # 'val': 10 # initial value }, # This var appears in both mission and pre-mission Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN: { - 'val': 10000, + # 'val': 10000, 'units': 'kW', 'lower': 1.0, 'upper': None, - } + }, } return DVs def get_parameters(self, aviary_inputs=None, phase_info=None): """ Parameters are only tested to see if they exist in mission. - A value the doesn't change throught the mission mission - Returns a dictionary of fixed values for the gearbox subsystem, where the keys are the names - of the fixed values, and the values are dictionaries that contain the fixed value for the - variable, the units for the variable, and any additional keyword arguments required by - OpenMDAO for the variable. + The value doesn't change throughout the mission. + Returns a dictionary of fixed values for the gearbox subsystem, where the keys + are the names of the fixed values, and the values are dictionaries that contain + the fixed value for the variable, the units for the variable, and any additional + keyword arguments required by OpenMDAO for the variable. Returns ------- @@ -75,8 +73,19 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): """ parameters = { Aircraft.Engine.Gearbox.EFFICIENCY: { - 'val': 0.98, + 'val': 1.0, 'units': 'unitless', + 'static_target': True, + }, + Aircraft.Engine.Gearbox.GEAR_RATIO: { + 'val': 1.0, + 'units': 'unitless', + 'static_target': True, + }, + Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN: { + 'val': 1.0, + 'units': 'kW', + 'static_target': True, }, } @@ -87,10 +96,10 @@ def get_mass_names(self): def get_outputs(self): return [ - Dynamic.Mission.SHAFT_POWER + '_out', - Dynamic.Mission.SHAFT_POWER_MAX + '_out', - Dynamic.Mission.RPM + '_out', - Dynamic.Mission.TORQUE + '_out', + Dynamic.Vehicle.Propulsion.SHAFT_POWER + '_out', + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_out', + Dynamic.Vehicle.Propulsion.RPM + '_out', + Dynamic.Vehicle.Propulsion.TORQUE + '_out', Mission.Constraints.GEARBOX_SHAFT_POWER_RESIDUAL, ] diff --git a/aviary/subsystems/propulsion/gearbox/model/gearbox_mission.py b/aviary/subsystems/propulsion/gearbox/model/gearbox_mission.py index 62a9587b45..f7b41b9466 100644 --- a/aviary/subsystems/propulsion/gearbox/model/gearbox_mission.py +++ b/aviary/subsystems/propulsion/gearbox/model/gearbox_mission.py @@ -1,27 +1,18 @@ import numpy as np - import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Dynamic, Aircraft, Mission +from aviary.variable_info.variables import Aircraft, Dynamic, Mission class GearboxMission(om.Group): - """ - Calculates the mission performance of a single gearbox. - """ + """Calculates the mission performance of a single gearbox.""" def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare( - 'aviary_inputs', types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - default=None, - ) + self.options.declare('num_nodes', types=int) self.name = 'gearbox_mission' def setup(self): - n = self.options["num_nodes"] + n = self.options['num_nodes'] self.add_subsystem( 'rpm_comp', @@ -33,10 +24,10 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - ('rpm_in', Dynamic.Mission.RPM + '_in'), + ('rpm_in', Dynamic.Vehicle.Propulsion.RPM + '_in'), ('gear_ratio', Aircraft.Engine.Gearbox.GEAR_RATIO), ], - promotes_outputs=[('rpm_out', Dynamic.Mission.RPM + '_out')], + promotes_outputs=[('rpm_out', Dynamic.Vehicle.Propulsion.RPM + '_out')], ) self.add_subsystem( @@ -49,12 +40,10 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - ('shaft_power_in', Dynamic.Mission.SHAFT_POWER + '_in'), + ('shaft_power_in', Dynamic.Vehicle.Propulsion.SHAFT_POWER + '_in'), ('efficiency', Aircraft.Engine.Gearbox.EFFICIENCY), ], - promotes_outputs=[ - ('shaft_power_out', Dynamic.Mission.SHAFT_POWER + '_out') - ], + promotes_outputs=[('shaft_power_out', Dynamic.Vehicle.Propulsion.SHAFT_POWER + '_out')], ) self.add_subsystem( @@ -66,16 +55,16 @@ def setup(self): rpm_out={'val': np.ones(n), 'units': 'rad/s'}, has_diag_partials=True, ), - promotes_outputs=[('torque_out', Dynamic.Mission.TORQUE + '_out')], + promotes_outputs=[('torque_out', Dynamic.Vehicle.Propulsion.TORQUE + '_out')], ) self.connect( - f'{Dynamic.Mission.SHAFT_POWER}_out', - f'torque_comp.shaft_power_out', + f'{Dynamic.Vehicle.Propulsion.SHAFT_POWER}_out', + 'torque_comp.shaft_power_out', ) self.connect( - f'{Dynamic.Mission.RPM}_out', - f'torque_comp.rpm_out', + f'{Dynamic.Vehicle.Propulsion.RPM}_out', + 'torque_comp.rpm_out', ) # Determine the maximum power available at this flight condition @@ -90,11 +79,11 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - ('shaft_power_in', Dynamic.Mission.SHAFT_POWER_MAX + '_in'), + ('shaft_power_in', Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_in'), ('efficiency', Aircraft.Engine.Gearbox.EFFICIENCY), ], promotes_outputs=[ - ('shaft_power_out', Dynamic.Mission.SHAFT_POWER_MAX + '_out') + ('shaft_power_out', Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_out') ], ) @@ -113,7 +102,7 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - ('shaft_power_max', Dynamic.Mission.SHAFT_POWER_MAX + '_in'), + ('shaft_power_max', Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_in'), ('shaft_power_design', Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN), ], promotes_outputs=[ diff --git a/aviary/subsystems/propulsion/gearbox/model/gearbox_premission.py b/aviary/subsystems/propulsion/gearbox/model/gearbox_premission.py index d43c08b63e..be66f15bbe 100644 --- a/aviary/subsystems/propulsion/gearbox/model/gearbox_premission.py +++ b/aviary/subsystems/propulsion/gearbox/model/gearbox_premission.py @@ -1,51 +1,57 @@ import openmdao.api as om -import numpy as np -from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.variables import Aircraft class GearboxPreMission(om.Group): """ Calculate gearbox mass for a single gearbox. - Gearbox design assumes collective control which means that RPM coming into the + Gearbox design assumes collective control which means that RPM coming into the gearbox is fixed and RPM going out of the gearbox is fixed over the whole mission. """ - def initialize(self, ): - self.options.declare("simple_mass", types=bool, default=True) - self.options.declare( - "aviary_inputs", types=AviaryValues, - desc="collection of Aircraft/Mission specific options", - default=None, - ) + def initialize( + self, + ): + self.options.declare('simple_mass', types=bool, default=True) self.name = 'gearbox_premission' def setup(self): - self.add_subsystem('gearbox_PRM', - om.ExecComp('RPM_out = RPM_in / gear_ratio', - RPM_out={'val': 0.0, 'units': 'rpm'}, - gear_ratio={'val': 1.0, 'units': 'unitless'}, - RPM_in={'val': 0.0, 'units': 'rpm'}, - has_diag_partials=True), - promotes_inputs=[('RPM_in', Aircraft.Engine.RPM_DESIGN), - ('gear_ratio', Aircraft.Engine.Gearbox.GEAR_RATIO)], - promotes_outputs=['RPM_out']) + self.add_subsystem( + 'gearbox_RPM', + om.ExecComp( + 'RPM_out = RPM_in / gear_ratio', + RPM_out={'val': 0.0, 'units': 'rpm'}, + gear_ratio={'val': 1.0, 'units': 'unitless'}, + RPM_in={'val': 0.0, 'units': 'rpm'}, + has_diag_partials=True, + ), + promotes_inputs=[ + ('RPM_in', Aircraft.Engine.RPM_DESIGN), + ('gear_ratio', Aircraft.Engine.Gearbox.GEAR_RATIO), + ], + # promotes_outputs=['RPM_out'], + ) # max torque is calculated based on input shaft power and output RPM - self.add_subsystem('torque_comp', - om.ExecComp('torque_max = shaft_power / RPM_out', - shaft_power={'val': 1.0, 'units': 'kW'}, - torque_max={'val': 1.0, 'units': 'kN*m'}, - RPM_out={'val': 1.0, 'units': 'rad/s'}, - has_diag_partials=True), - promotes_inputs=[('shaft_power', Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN), - 'RPM_out'], - promotes_outputs=['torque_max']) + self.add_subsystem( + 'torque_comp', + om.ExecComp( + 'torque_max = shaft_power / RPM_out', + shaft_power={'val': 1.0, 'units': 'kW'}, + torque_max={'val': 1.0, 'units': 'kN*m'}, + RPM_out={'val': 1.0, 'units': 'rad/s'}, + has_diag_partials=True, + ), + promotes_inputs=[('shaft_power', Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN)], + # 'RPM_out'], + # promotes_outputs=['torque_max'], + ) - if self.options["simple_mass"]: - # Simple gearbox mass will always produce positive values for mass based on a fixed specific torque + if self.options['simple_mass']: + # Simple gearbox mass will always produce positive values for mass based + # on a fixed specific torque self.add_subsystem( 'mass_comp', om.ExecComp( @@ -56,7 +62,7 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - 'torque_max', + # 'torque_max', ('specific_torque', Aircraft.Engine.Gearbox.SPECIFIC_TORQUE), ], promotes_outputs=[('gearbox_mass', Aircraft.Engine.Gearbox.MASS)], @@ -66,13 +72,26 @@ def setup(self): # This gearbox mass calc can work for large systems but can produce negative weights for some inputs # Gearbox mass from "An N+3 Technolgoy Level Reference Propulsion System" by Scott Jones, William Haller, and Michael Tong # NASA TM 2017-219501 - self.add_subsystem('gearbox_mass', - om.ExecComp('gearbox_mass = (shaftpower / RPM_out)**(0.75) * (RPM_in / RPM_out)**(0.15)', - gearbox_mass={'val': 0.0, 'units': 'lb'}, - shaftpower={'val': 0.0, 'units': 'hp'}, - RPM_out={'val': 0.0, 'units': 'rpm'}, - RPM_in={'val': 0.0, 'units': 'rpm'}, - has_diag_partials=True), - promotes_inputs=[('shaftpower', Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN), - 'RPM_out', ('RPM_in', Aircraft.Engine.RPM_DESIGN)], - promotes_outputs=[('gearbox_mass', Aircraft.Engine.Gearbox.MASS)]) + self.add_subsystem( + 'gearbox_mass', + om.ExecComp( + 'gearbox_mass = (shaftpower / RPM_out)**(0.75) * (RPM_in / RPM_out)**(0.15)', + gearbox_mass={'val': 0.0, 'units': 'lb'}, + shaftpower={'val': 0.0, 'units': 'hp'}, + RPM_out={'val': 0.0, 'units': 'rpm'}, + RPM_in={'val': 0.0, 'units': 'rpm'}, + has_diag_partials=True, + ), + promotes_inputs=[ + ('shaftpower', Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN), + # 'RPM_out', + ('RPM_in', Aircraft.Engine.RPM_DESIGN), + ], + promotes_outputs=[('gearbox_mass', Aircraft.Engine.Gearbox.MASS)], + ) + + self.connect('gearbox_RPM.RPM_out', 'torque_comp.RPM_out') + if self.options['simple_mass']: + self.connect('torque_comp.torque_max', 'mass_comp.torque_max') + else: + self.connect('gearbox_RPM.RPM_out', 'gearbox_mass.RPM_out') diff --git a/aviary/subsystems/propulsion/gearbox/test/test_gearbox.py b/aviary/subsystems/propulsion/gearbox/test/test_gearbox.py index 816b8ac03f..c56ad0aefe 100644 --- a/aviary/subsystems/propulsion/gearbox/test/test_gearbox.py +++ b/aviary/subsystems/propulsion/gearbox/test/test_gearbox.py @@ -1,17 +1,15 @@ import unittest -import numpy as np import openmdao.api as om - from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.propulsion.gearbox.gearbox_builder import GearboxBuilder import aviary.api as av +from aviary.subsystems.propulsion.gearbox.gearbox_builder import GearboxBuilder class TestGearbox(unittest.TestCase): def setUp(self): - self.prob = prob = om.Problem() + self.prob = om.Problem() self.options = av.AviaryValues() @@ -19,9 +17,9 @@ def setUp(self): def test_gearbox_premission(self): prob = self.prob - prob.model.add_subsystem('gearbox_premission', - self.gearbox.build_pre_mission(self.options), - promotes=['*']) + prob.model.add_subsystem( + 'gearbox_premission', self.gearbox.build_pre_mission(self.options), promotes=['*'] + ) prob.setup(force_alloc_complex=True) @@ -33,65 +31,57 @@ def test_gearbox_premission(self): prob.run_model() mass = prob.get_val(av.Aircraft.Engine.Gearbox.MASS, 'lb') - torque_max = prob.get_val('torque_max', 'lbf*ft') + torque_max = prob.get_val('gearbox_premission.torque_comp.torque_max', 'lbf*ft') torque_max_expected = 4005.84967696 mass_expected = 116.25002688 assert_near_equal(mass, mass_expected, tolerance=1e-6) assert_near_equal(torque_max, torque_max_expected, tolerance=1e-6) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-9, rtol=1e-9) def test_gearbox_mission(self): prob = self.prob num_nodes = 3 - prob.model.add_subsystem('gearbox_mission', - self.gearbox.build_mission( - num_nodes=num_nodes, aviary_inputs=self.options), - promotes=['*']) + prob.model.add_subsystem( + 'gearbox_mission', + self.gearbox.build_mission(num_nodes=num_nodes, aviary_inputs=self.options), + promotes=['*'], + ) prob.setup(force_alloc_complex=True) - prob.set_val(av.Dynamic.Mission.RPM + '_in', [5000, 6195, 6195], units='rpm') + prob.set_val(av.Dynamic.Vehicle.Propulsion.RPM + '_in', [5000, 6195, 6195], units='rpm') + prob.set_val(av.Dynamic.Vehicle.Propulsion.SHAFT_POWER + '_in', [100, 200, 375], units='hp') prob.set_val( - av.Dynamic.Mission.SHAFT_POWER + '_in', [100, 200, 375], units='hp' - ) - prob.set_val( - av.Dynamic.Mission.SHAFT_POWER_MAX + '_in', [375, 300, 375], units='hp' + av.Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_in', [375, 300, 375], units='hp' ) prob.set_val(av.Aircraft.Engine.Gearbox.GEAR_RATIO, 12.6, units=None) prob.set_val(av.Aircraft.Engine.Gearbox.EFFICIENCY, 0.98, units=None) prob.run_model() - SHAFT_POWER_GEARBOX = prob.get_val( - av.Dynamic.Mission.SHAFT_POWER + '_out', 'hp' - ) - RPM_GEARBOX = prob.get_val(av.Dynamic.Mission.RPM + '_out', 'rpm') - TORQUE_GEARBOX = prob.get_val(av.Dynamic.Mission.TORQUE + '_out', 'ft*lbf') - SHAFT_POWER_MAX_GEARBOX = prob.get_val( - av.Dynamic.Mission.SHAFT_POWER_MAX + '_out', 'hp' - ) + shaft_power = prob.get_val(av.Dynamic.Vehicle.Propulsion.SHAFT_POWER + '_out', 'hp') + rpm = prob.get_val(av.Dynamic.Vehicle.Propulsion.RPM + '_out', 'rpm') + torque = prob.get_val(av.Dynamic.Vehicle.Propulsion.TORQUE + '_out', 'ft*lbf') + shaft_power_max = prob.get_val(av.Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_out', 'hp') - SHAFT_POWER_GEARBOX_expected = [98., 196., 367.5] - RPM_GEARBOX_expected = [396.82539683, 491.66666667, 491.66666667] - TORQUE_GEARBOX_expected = [1297.0620786, 2093.72409783, 3925.73268342] - SHAFT_POWER_MAX_GEARBOX_expected = [367.5, 294., 367.5] + shaft_power_expected = [98.0, 196.0, 367.5] + rpm_expected = [396.82539683, 491.66666667, 491.66666667] + torque_expected = [1297.0620786, 2093.72409783, 3925.73268342] + shaft_power_max_expected = [367.5, 294.0, 367.5] - assert_near_equal(SHAFT_POWER_GEARBOX, - SHAFT_POWER_GEARBOX_expected, tolerance=1e-6) - assert_near_equal(RPM_GEARBOX, RPM_GEARBOX_expected, tolerance=1e-6) - assert_near_equal(TORQUE_GEARBOX, TORQUE_GEARBOX_expected, tolerance=1e-6) - assert_near_equal(SHAFT_POWER_MAX_GEARBOX, - SHAFT_POWER_MAX_GEARBOX_expected, tolerance=1e-6) + assert_near_equal(shaft_power, shaft_power_expected, tolerance=1e-6) + assert_near_equal(rpm, rpm_expected, tolerance=1e-6) + assert_near_equal(torque, torque_expected, tolerance=1e-6) + assert_near_equal(shaft_power_max, shaft_power_max_expected, tolerance=1e-6) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-9, rtol=1e-9) class TestGearboxBuilder(av.TestSubsystemBuilderBase): - def setUp(self): self.subsystem_builder = GearboxBuilder() self.aviary_values = av.AviaryValues() diff --git a/aviary/subsystems/propulsion/motor/model/motor_map.py b/aviary/subsystems/propulsion/motor/model/motor_map.py index 894c154f8e..106f4ada2b 100644 --- a/aviary/subsystems/propulsion/motor/model/motor_map.py +++ b/aviary/subsystems/propulsion/motor/model/motor_map.py @@ -1,10 +1,10 @@ import numpy as np - import openmdao.api as om -from aviary.variable_info.variables import Dynamic, Aircraft - +from aviary.variable_info.variables import Aircraft, Dynamic +# block auto-formatting of tables +# fmt: off motor_map = np.array([ # speed---- .0 .083333 .16667 .25 .33333.41667 .5, .58333 .66667 .75, .83333, .91667 1. [.871, .872, .862, .853, .845, .838, .832, .825, .819, .813, .807, .802, .796], # 0 @@ -25,61 +25,76 @@ [.807, .808, .884, .912, .927, .936, .942, .947, .950, .952, .954, .955, .956], # 0.936 [.795, .796, .877, .907, .923, .933, .939, .944, .948, .950, .952, .953, .954] # 1.000 ]).T +# fmt: on class MotorMap(om.Group): - - ''' + """ This function takes in 0-1 values for electric motor throttle, scales those values into 0 to max_torque on the motor map this also allows us to solve for motor efficiency then we scale the torque up based on the actual scale factor of the motor. This avoids the need to rescale the map values, and still allows for the motor scale to be optimized. - Scaling only effects Torque. RPM is not scaled and is assumed to be maxed at 6,000 rpm. + Scaling only effects torque (and therefore shaft power production, and electric power consumption). + RPM is not scaled and is assumed to be maxed at 6,000 rpm. The original maps were put together for a 746kw (1,000 hp) electric motor published in the TTBW paper: https://ntrs.nasa.gov/api/citations/20230016987/downloads/TTBW_SciTech_2024_Final_12_5_2023.pdf The map is shown in Figure 4. Inputs ---------- - Dynamic.Mission.THROTTLE : float (unitless) (0 to 1) + Dynamic.Vehicle.Propulsion.THROTTLE : float (unitless) (0 to 1) The throttle command which will be translated into torque output from the engine - Aircraft.Engine.SCALE_FACTOR : float (unitless) (positive) + Aircraft.Engine.SCALE_FACTOR : float (unitless) (positive) Aircraft.Motor.RPM : float (rpm) (0 to 6000) Outputs ---------- - Dynamic.Mission.TORQUE : float (positive) + Dynamic.Vehicle.Propulsion.TORQUE : float (positive) Dynamic.Mission.Motor.EFFICIENCY : float (positive) - ''' + """ def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) def setup(self): - n = self.options["num_nodes"] + n = self.options['num_nodes'] # Training data - rpm_vals = np.array([0, .083333, .16667, .25, .33333, .41667, .5, - .58333, .66667, .75, .83333, .91667, 1.])*6000 - torque_vals = np.array([0.0, 0.040, 0.104, 0.168, 0.232, 0.296, 0.360, - 0.424, 0.488, 0.552, 0.616, 0.680, 0.744, 0.808, - 0.872, 0.936, 1.000])*1800 - + # fmt: off + rpm_vals = np.array( + [ + 0, .083333, .16667, .25, .33333, .41667, .5, .58333, .66667, .75, .83333, .91667, 1. + ] + ) * 6000 + torque_vals = np.array( + [ + 0.0, 0.040, 0.104, 0.168, 0.232, 0.296, 0.360, 0.424, 0.488, + 0.552, 0.616, 0.680, 0.744, 0.808, 0.872, 0.936, 1.000 + ] + ) * 1800 + # fmt: on # Create a structured metamodel to compute motor efficiency from rpm - motor = om.MetaModelStructuredComp(method="slinear", - vec_size=n, - extrapolate=True) - motor.add_input(Dynamic.Mission.RPM, val=np.ones(n), - training_data=rpm_vals, - units="rpm") - motor.add_input("torque_unscaled", val=np.ones(n), # unscaled torque - training_data=torque_vals, - units="N*m") - motor.add_output("motor_efficiency", val=np.ones(n), - training_data=motor_map, - units='unitless') + motor = om.MetaModelStructuredComp(method='slinear', vec_size=n, extrapolate=True) + motor.add_input( + Dynamic.Vehicle.Propulsion.RPM, + val=np.ones(n), + training_data=rpm_vals, + units='rpm', + ) + motor.add_input( + 'torque_unscaled', + val=np.ones(n), # unscaled torque + training_data=torque_vals, + units='N*m', + ) + motor.add_output( + 'motor_efficiency', + val=np.ones(n), + training_data=motor_map, + units='unitless', + ) self.add_subsystem( 'throttle_to_torque', @@ -90,15 +105,18 @@ def setup(self): throttle={'val': np.ones(n), 'units': 'unitless'}, has_diag_partials=True, ), - promotes=["torque_unscaled", ("throttle", Dynamic.Mission.THROTTLE)], + promotes=[('throttle', Dynamic.Vehicle.Propulsion.THROTTLE)], ) - self.add_subsystem(name="motor_efficiency", - subsys=motor, - promotes_inputs=[Dynamic.Mission.RPM, "torque_unscaled"], - promotes_outputs=["motor_efficiency"]) + self.add_subsystem( + name='motor_efficiency', + subsys=motor, + promotes_inputs=[Dynamic.Vehicle.Propulsion.RPM], + promotes_outputs=['motor_efficiency'], + ) - # now that we know the efficiency, scale up the torque correctly for the engine size selected + # Now that we know the efficiency, scale up the torque correctly for the engine + # size selected # Note: This allows the optimizer to optimize the motor size if desired self.add_subsystem( 'scale_motor_torque', @@ -110,8 +128,12 @@ def setup(self): has_diag_partials=True, ), promotes=[ - ("torque", Dynamic.Mission.TORQUE), - "torque_unscaled", - ("scale_factor", Aircraft.Engine.SCALE_FACTOR), + ('torque', Dynamic.Vehicle.Propulsion.TORQUE), + ('scale_factor', Aircraft.Engine.SCALE_FACTOR), ], ) + + self.connect( + 'throttle_to_torque.torque_unscaled', + ['motor_efficiency.torque_unscaled', 'scale_motor_torque.torque_unscaled'], + ) diff --git a/aviary/subsystems/propulsion/motor/model/motor_mission.py b/aviary/subsystems/propulsion/motor/model/motor_mission.py index 843603727f..cb71a13e7c 100644 --- a/aviary/subsystems/propulsion/motor/model/motor_mission.py +++ b/aviary/subsystems/propulsion/motor/model/motor_mission.py @@ -1,29 +1,26 @@ import numpy as np - import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Dynamic, Aircraft from aviary.subsystems.propulsion.motor.model.motor_map import MotorMap +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.variables import Aircraft, Dynamic class MotorMission(om.Group): - - ''' - Calculates the mission performance (ODE) of a single electric motor. - ''' + """Calculates the mission performance (ODE) of a single electric motor.""" def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) self.options.declare( - 'aviary_inputs', types=AviaryValues, + 'aviary_inputs', + types=AviaryValues, desc='collection of Aircraft/Mission specific options', default=None, ) self.name = 'motor_mission' def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] ivc = om.IndepVarComp() ivc.add_output('max_throttle', val=np.ones(nn), units='unitless') @@ -36,12 +33,12 @@ def setup(self): 'motor_map', MotorMap(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.THROTTLE, + Dynamic.Vehicle.Propulsion.THROTTLE, Aircraft.Engine.SCALE_FACTOR, - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, ], promotes_outputs=[ - Dynamic.Mission.TORQUE, + Dynamic.Vehicle.Propulsion.TORQUE, 'motor_efficiency', ], ) @@ -55,13 +52,13 @@ def setup(self): RPM={'val': np.ones(nn), 'units': 'rad/s'}, has_diag_partials=True, ), # fixed RPM system - promotes_inputs=[('RPM', Dynamic.Mission.RPM)], - promotes_outputs=[('shaft_power', Dynamic.Mission.SHAFT_POWER)], + promotes_inputs=[('RPM', Dynamic.Vehicle.Propulsion.RPM)], + promotes_outputs=[('shaft_power', Dynamic.Vehicle.Propulsion.SHAFT_POWER)], ) # Can't promote torque as an input, as it will create a feedback loop with # propulsion mux component. Connect it here instead - motor_group.connect(Dynamic.Mission.TORQUE, 'power_comp.torque') + motor_group.connect(Dynamic.Vehicle.Propulsion.TORQUE, 'power_comp.torque') motor_group.add_subsystem( 'energy_comp', @@ -73,16 +70,16 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[('efficiency', 'motor_efficiency')], - promotes_outputs=[('power_elec', Dynamic.Mission.ELECTRIC_POWER_IN)], + promotes_outputs=[('power_elec', Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN)], ) # Can't promote shaft power as an input, as it will create a feedback loop with # propulsion mux component. Connect it here instead - motor_group.connect(Dynamic.Mission.SHAFT_POWER, 'energy_comp.shaft_power') + motor_group.connect(Dynamic.Vehicle.Propulsion.SHAFT_POWER, 'energy_comp.shaft_power') - self.add_subsystem('motor_group', motor_group, - promotes_inputs=['*'], - promotes_outputs=['*']) + self.add_subsystem( + 'motor_group', motor_group, promotes_inputs=['*'], promotes_outputs=['*'] + ) # Determine the maximum power available at this flight condition # this is used for excess power constraints @@ -93,12 +90,15 @@ def setup(self): 'motor_map_max', MotorMap(num_nodes=nn), promotes_inputs=[ - (Dynamic.Mission.THROTTLE, 'max_throttle'), + (Dynamic.Vehicle.Propulsion.THROTTLE, 'max_throttle'), Aircraft.Engine.SCALE_FACTOR, - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, ], promotes_outputs=[ - (Dynamic.Mission.TORQUE, Dynamic.Mission.TORQUE_MAX), + ( + Dynamic.Vehicle.Propulsion.TORQUE, + Dynamic.Vehicle.Propulsion.TORQUE_MAX, + ), 'motor_efficiency', ], ) @@ -113,10 +113,10 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - ('max_torque', Dynamic.Mission.TORQUE_MAX), - ('RPM', Dynamic.Mission.RPM), + ('max_torque', Dynamic.Vehicle.Propulsion.TORQUE_MAX), + ('RPM', Dynamic.Vehicle.Propulsion.RPM), ], - promotes_outputs=[('max_power', Dynamic.Mission.SHAFT_POWER_MAX)], + promotes_outputs=[('max_power', Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX)], ) self.add_subsystem( @@ -124,9 +124,9 @@ def setup(self): motor_group_max, promotes_inputs=['*', 'max_throttle'], promotes_outputs=[ - Dynamic.Mission.SHAFT_POWER_MAX, - Dynamic.Mission.TORQUE_MAX, + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, + Dynamic.Vehicle.Propulsion.TORQUE_MAX, ], ) - self.set_input_defaults(Dynamic.Mission.RPM, val=np.ones(nn), units='rpm') + self.set_input_defaults(Dynamic.Vehicle.Propulsion.RPM, val=np.ones(nn), units='rpm') diff --git a/aviary/subsystems/propulsion/motor/model/motor_premission.py b/aviary/subsystems/propulsion/motor/model/motor_premission.py index c6964d41d5..24d46150e7 100644 --- a/aviary/subsystems/propulsion/motor/model/motor_premission.py +++ b/aviary/subsystems/propulsion/motor/model/motor_premission.py @@ -1,20 +1,18 @@ import openmdao.api as om -import numpy as np -from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.utils.aviary_values import AviaryValues from aviary.subsystems.propulsion.motor.model.motor_map import MotorMap +from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.variables import Aircraft, Dynamic class MotorPreMission(om.Group): - """ - Calculate electric motor mass for a single motor - """ + """Calculate electric motor mass for a single motor.""" def initialize(self): self.options.declare( - "aviary_inputs", types=AviaryValues, - desc="collection of Aircraft/Mission specific options", + 'aviary_inputs', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', default=None, ) self.name = 'motor_premission' @@ -27,11 +25,9 @@ def setup(self): # Without inputs it will return the max torque based on the non-dimensional # scale factor chosen by the optimizer. # The max torque is then used in pre-mission to determine weight of the system. - design_rpm = self.options['aviary_inputs'].get_val( - Aircraft.Engine.RPM_DESIGN, units='rpm' - ) + design_rpm = self.options['aviary_inputs'].get_val(Aircraft.Engine.RPM_DESIGN, units='rpm') - self.set_input_defaults(Dynamic.Mission.THROTTLE, 1.0, units=None) + self.set_input_defaults(Dynamic.Vehicle.Propulsion.THROTTLE, 1.0, units=None) self.set_input_defaults('design_rpm', design_rpm, units='rpm') self.add_subsystem( @@ -39,11 +35,11 @@ def setup(self): MotorMap(num_nodes=1), promotes_inputs=[ Aircraft.Engine.SCALE_FACTOR, - Dynamic.Mission.THROTTLE, - (Dynamic.Mission.RPM, 'design_rpm'), + Dynamic.Vehicle.Propulsion.THROTTLE, + (Dynamic.Vehicle.Propulsion.RPM, 'design_rpm'), ], promotes_outputs=[ - (Dynamic.Mission.TORQUE, Aircraft.Engine.Motor.TORQUE_MAX) + (Dynamic.Vehicle.Propulsion.TORQUE, Aircraft.Engine.Motor.TORQUE_MAX) ], ) diff --git a/aviary/subsystems/propulsion/motor/motor_builder.py b/aviary/subsystems/propulsion/motor/motor_builder.py index 3f199bcb73..338f0b954b 100644 --- a/aviary/subsystems/propulsion/motor/motor_builder.py +++ b/aviary/subsystems/propulsion/motor/motor_builder.py @@ -1,16 +1,21 @@ -from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.subsystems.propulsion.motor.model.motor_premission import MotorPreMission from aviary.subsystems.propulsion.motor.model.motor_mission import MotorMission +from aviary.subsystems.propulsion.motor.model.motor_premission import MotorPreMission +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.variable_info.variables import Aircraft, Dynamic class MotorBuilder(SubsystemBuilderBase): - ''' - Define the builder for a single motor subsystem that provides methods to define the motor subsystem's states, design variables, fixed values, initial guesses, and mass names. + """ + Define the builder for a single motor subsystem that provides methods to define the + motor subsystem's states, design variables, fixed values, initial guesses, and mass + names. - It also provides methods to build OpenMDAO systems for the pre-mission and mission computations of the subsystem, to get the constraints for the subsystem, and to preprocess the inputs for the subsystem. + It also provides methods to build OpenMDAO systems for the pre-mission and mission + computations of the subsystem, to get the constraints for the subsystem, and to + preprocess the inputs for the subsystem. - This is meant to be computations for a single motor, so there is no notion of "num_motors" in this code. + This is meant to be computations for a single motor, so there is no notion of + "num_motors" in this code. Attributes ---------- @@ -22,7 +27,10 @@ class MotorBuilder(SubsystemBuilderBase): __init__(self, name='motor'): Initializes the MotorBuilder object with a given name. get_states(self) -> dict: - Returns a dictionary of the subsystem's states, where the keys are the names of the state variables, and the values are dictionaries that contain the units for the state variable and any additional keyword arguments required by OpenMDAO for the state variable. + Returns a dictionary of the subsystem's states, where the keys are the names of + the state variables, and the values are dictionaries that contain the units for + the state variable and any additional keyword arguments required by OpenMDAO for + the state variable. get_linked_variables(self) -> list: Links voltage input from the battery subsystem build_pre_mission(self) -> openmdao.core.System: @@ -30,25 +38,38 @@ class MotorBuilder(SubsystemBuilderBase): build_mission(self, num_nodes, aviary_inputs) -> openmdao.core.System: Builds an OpenMDAO system for the mission computations of the subsystem. get_constraints(self) -> dict: - Returns a dictionary of constraints for the motor subsystem, where the keys are the names of the variables to be constrained, and the values are dictionaries that contain the lower and upper bounds for the constraint and any additional keyword arguments accepted by Dymos for the constraint. + Returns a dictionary of constraints for the motor subsystem, where the keys are + the names of the variables to be constrained, and the values are dictionaries + that contain the lower and upper bounds for the constraint and any additional + keyword arguments accepted by Dymos for the constraint. get_design_vars(self) -> dict: - Returns a dictionary of design variables for the motor subsystem, where the keys are the names of the design variables, and the values are dictionaries that contain the units for the design variable, the lower and upper bounds for the design variable, and any additional keyword arguments required by OpenMDAO for the design variable. + Returns a dictionary of design variables for the motor subsystem, where the keys + are the names of the design variables, and the values are dictionaries that + contain the units for the design variable, the lower and upper bounds for the + design variable, and any additional keyword arguments required by OpenMDAO for + the design variable. get_parameters(self) -> dict: - Returns a dictionary of fixed values for the motor subsystem, where the keys are the names of the fixed values, and the values are dictionaries that contain the fixed value for the variable, the units for the variable, and any additional keyword arguments required by OpenMDAO for the variable. + Returns a dictionary of fixed values for the motor subsystem, where the keys are + the names of the fixed values, and the values are dictionaries that contain the + fixed value for the variable, the units for the variable, and any additional + keyword arguments required by OpenMDAO for the variable. get_initial_guesses(self) -> dict: - Returns a dictionary of initial guesses for the motor subsystem, where the keys are the names of the initial guesses, and the values are dictionaries that contain the initial guess value, the type of variable (state or control), and any additional keyword arguments required by OpenMDAO for the variable. + Returns a dictionary of initial guesses for the motor subsystem, where the keys + are the names of the initial guesses, and the values are dictionaries that + contain the initial guess value, the type of variable (state or control), and any + additional keyword arguments required by OpenMDAO for the variable. get_mass_names(self) -> list: Returns a list of names for the motor subsystem mass. preprocess_inputs(self, aviary_inputs) -> aviary_inputs: No preprocessing needed for the motor subsystem. - ''' + """ - def __init__(self, name='motor', include_constraints=True): - self.include_constraints = include_constraints + def __init__(self, name='motor'): # , include_constraints=True): + # self.include_constraints = include_constraints super().__init__(name) def build_pre_mission(self, aviary_inputs): - return MotorPreMission(aviary_inputs=aviary_inputs, simple_mass=True) + return MotorPreMission(aviary_inputs=aviary_inputs) # , simple_mass=True) def build_mission(self, num_nodes, aviary_inputs): return MotorMission(num_nodes=num_nodes, aviary_inputs=aviary_inputs) @@ -56,11 +77,7 @@ def build_mission(self, num_nodes, aviary_inputs): # def get_constraints(self): # if self.include_constraints: # constraints = { - # Dynamic.Mission.Motor.TORQUE_CON: { - # 'upper': 0.0, - # 'type': 'path' - # } - # TBD Gearbox torque constraint + # Dynamic.Mission.Motor.TORQUE_CON: {'upper': 0.0, 'type': 'path'} # } # else: # constraints = {} @@ -72,17 +89,22 @@ def get_design_vars(self): Aircraft.Engine.SCALE_FACTOR: { 'units': 'unitless', 'lower': 0.001, - 'upper': None + 'upper': None, }, - Aircraft.Engine.Gearbox.GEAR_RATIO: { - 'units': None, - 'lower': 1.0, - 'upper': 1.0, - } } return DVs + def get_parameters(self): + params = { + Aircraft.Engine.SCALE_FACTOR: { + 'val': 1.0, + 'units': 'unitless', + 'static_target': True, + } + } + return params + # def get_initial_guesses(self): # initial_guess_dict = { # Aircraft.Motor.RPM: { @@ -95,30 +117,28 @@ def get_design_vars(self): # return initial_guess_dict def get_mass_names(self): - ''' + """ Return a list of names for the motor subsystem. Returns ------- mass_names : list A list of names for the motor subsystem. - ''' - return [Aircraft.Engine.Motor.MASS, - Aircraft.Engine.Gearbox.MASS] + """ + return [Aircraft.Engine.Motor.MASS, Aircraft.Engine.Gearbox.MASS] def get_outputs(self): - ''' + """ Return a list of output names for the motor subsystem. Returns ------- outputs : list A list of variable names for the motor subsystem. - ''' - + """ return [ - Dynamic.Mission.TORQUE, - Dynamic.Mission.SHAFT_POWER, - Dynamic.Mission.SHAFT_POWER_MAX, - Dynamic.Mission.ELECTRIC_POWER_IN, + Dynamic.Vehicle.Propulsion.TORQUE, + Dynamic.Vehicle.Propulsion.SHAFT_POWER, + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, ] diff --git a/aviary/subsystems/propulsion/motor/test/test_motor_map.py b/aviary/subsystems/propulsion/motor/test/test_motor_map.py index 20256022f0..90173be583 100644 --- a/aviary/subsystems/propulsion/motor/test/test_motor_map.py +++ b/aviary/subsystems/propulsion/motor/test/test_motor_map.py @@ -10,7 +10,6 @@ class TestGearbox(unittest.TestCase): - @use_tempdirs def test_motor_map(self): nn = 3 @@ -21,14 +20,13 @@ def test_motor_map(self): prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.THROTTLE, np.linspace(0, 1, nn)) - prob.set_val(Dynamic.Mission.RPM, np.linspace(0, 6000, nn)) - prob.set_val('torque_unscaled', np.linspace(0, 1800, nn), 'N*m') + prob.set_val(Dynamic.Vehicle.Propulsion.THROTTLE, np.linspace(0, 1, nn)) + prob.set_val(Dynamic.Vehicle.Propulsion.RPM, np.linspace(0, 6000, nn)) prob.set_val(Aircraft.Engine.SCALE_FACTOR, 1.12) prob.run_model() - torque = prob.get_val(Dynamic.Mission.TORQUE) + torque = prob.get_val(Dynamic.Vehicle.Propulsion.TORQUE) efficiency = prob.get_val('motor_efficiency') torque_expected = np.array([0.0, 900.0, 1800.0]) * 1.12 @@ -36,7 +34,7 @@ def test_motor_map(self): assert_near_equal(torque, torque_expected, tolerance=1e-9) assert_near_equal(efficiency, eff_expected, tolerance=1e-9) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/propulsion/motor/test/test_motor_mission.py b/aviary/subsystems/propulsion/motor/test/test_motor_mission.py index 0b1b278714..7efdeee635 100644 --- a/aviary/subsystems/propulsion/motor/test/test_motor_mission.py +++ b/aviary/subsystems/propulsion/motor/test/test_motor_mission.py @@ -10,32 +10,29 @@ class TestMotorMission(unittest.TestCase): - @use_tempdirs def test_motor_map(self): nn = 3 prob = om.Problem() - prob.model.add_subsystem( - 'motor_map', MotorMission(num_nodes=nn), promotes=['*'] - ) + prob.model.add_subsystem('motor_map', MotorMission(num_nodes=nn), promotes=['*']) prob.setup(force_alloc_complex=True) - prob.set_val(Dynamic.Mission.THROTTLE, np.linspace(0, 1, nn)) - prob.set_val(Dynamic.Mission.RPM, np.linspace(0, 6000, nn)) + prob.set_val(Dynamic.Vehicle.Propulsion.THROTTLE, np.linspace(0, 1, nn)) + prob.set_val(Dynamic.Vehicle.Propulsion.RPM, np.linspace(0, 6000, nn)) # prob.set_val('torque_unscaled', np.linspace(0, 1800, nn), 'N*m') prob.set_val(Aircraft.Engine.SCALE_FACTOR, 1.12) prob.run_model() - torque = prob.get_val(Dynamic.Mission.TORQUE, 'N*m') - max_torque = prob.get_val(Dynamic.Mission.TORQUE_MAX, 'N*m') + torque = prob.get_val(Dynamic.Vehicle.Propulsion.TORQUE, 'N*m') + max_torque = prob.get_val(Dynamic.Vehicle.Propulsion.TORQUE_MAX, 'N*m') efficiency = prob.get_val('motor_efficiency') - shp = prob.get_val(Dynamic.Mission.SHAFT_POWER) - max_shp = prob.get_val(Dynamic.Mission.SHAFT_POWER_MAX) - power = prob.get_val(Dynamic.Mission.ELECTRIC_POWER_IN, 'kW') + shp = prob.get_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER) + max_shp = prob.get_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX) + power = prob.get_val(Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, 'kW') torque_expected = np.array([0.0, 900.0, 1800.0]) * 1.12 max_torque_expected = [2016, 2016, 2016] @@ -51,7 +48,7 @@ def test_motor_map(self): assert_near_equal(max_shp, max_shp_expected, tolerance=1e-9) assert_near_equal(power, power, tolerance=1e-9) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/propulsion/motor/test/test_motor_premission.py b/aviary/subsystems/propulsion/motor/test/test_motor_premission.py index b9ec5a567a..28cf3d39ba 100644 --- a/aviary/subsystems/propulsion/motor/test/test_motor_premission.py +++ b/aviary/subsystems/propulsion/motor/test/test_motor_premission.py @@ -1,17 +1,15 @@ import unittest -import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from openmdao.utils.testing_utils import use_tempdirs from aviary.subsystems.propulsion.motor.model.motor_premission import MotorPreMission from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Aircraft, Dynamic +from aviary.variable_info.variables import Aircraft class TestGearbox(unittest.TestCase): - @use_tempdirs def test_motor_map(self): prob = om.Problem() @@ -24,7 +22,6 @@ def test_motor_map(self): prob.setup(force_alloc_complex=True) - # prob.set_val('torque_unscaled', np.linspace(0, 1800, nn), 'N*m') prob.set_val(Aircraft.Engine.SCALE_FACTOR, 1.12) prob.run_model() @@ -38,7 +35,7 @@ def test_motor_map(self): assert_near_equal(torque_max, torque_max_expected, tolerance=1e-9) assert_near_equal(mass, mass_expected, tolerance=1e-9) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) diff --git a/aviary/subsystems/propulsion/propeller/hamilton_standard.py b/aviary/subsystems/propulsion/propeller/hamilton_standard.py index 6091a10f47..06635dab05 100644 --- a/aviary/subsystems/propulsion/propeller/hamilton_standard.py +++ b/aviary/subsystems/propulsion/propeller/hamilton_standard.py @@ -4,77 +4,75 @@ import numpy as np import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues +from aviary.constants import RHO_SEA_LEVEL_ENGLISH from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Dynamic, Settings -from aviary.constants import RHO_SEA_LEVEL_ENGLISH -from aviary.utils.functions import add_aviary_input, add_aviary_output def _unint(xa, ya, x): """ - univariate table routine with seperate arrays for x and y + Univariate table routine with separate arrays for x and y This routine interpolates over a 4 point interval using a variation of 3nd degree interpolation to produce a continuity of slope between adjacent intervals. """ - Lmt = 0 n = len(xa) # test for off low end - if (xa[0] > x): + if xa[0] > x: Lmt = 1 # off low end y = ya[0] - elif (xa[0] == x): + elif xa[0] == x: y = ya[0] # at low end else: ifnd = 0 idx = 0 for i in range(1, n): - if (xa[i] == x): + if xa[i] == x: ifnd = 1 # at a node idx = i break - elif (xa[i] > x): + elif xa[i] > x: ifnd = 2 # between (xa[i-1],xa[i]) idx = i break - if (ifnd == 0): + if ifnd == 0: idx = n Lmt = 2 # off high end - y = ya[n-1] - elif (ifnd == 1): + y = ya[n - 1] + elif ifnd == 1: y = ya[idx] - elif (ifnd == 2): + elif ifnd == 2: # jx1: the first point of four points - if (idx == 1): + if idx == 1: # first interval jx1 = 0 ra = 1.0 - elif (idx == n-1): + elif idx == n - 1: # last interval jx1 = n - 4 ra = 0.0 else: jx1 = idx - 2 - ra = (xa[idx] - x)/(xa[idx] - xa[idx-1]) + ra = (xa[idx] - x) / (xa[idx] - xa[idx - 1]) rb = 1.0 - ra - # get coefficeints and results - p1 = xa[jx1+1] - xa[jx1] - p2 = xa[jx1+2] - xa[jx1+1] - p3 = xa[jx1+3] - xa[jx1+2] + # get coefficients and results + p1 = xa[jx1 + 1] - xa[jx1] + p2 = xa[jx1 + 2] - xa[jx1 + 1] + p3 = xa[jx1 + 3] - xa[jx1 + 2] p4 = p1 + p2 p5 = p2 + p3 d1 = x - xa[jx1] - d2 = x - xa[jx1+1] - d3 = x - xa[jx1+2] - d4 = x - xa[jx1+3] + d2 = x - xa[jx1 + 1] + d3 = x - xa[jx1 + 2] + d4 = x - xa[jx1 + 3] c1 = ra / p1 * d2 / p4 * d3 c2 = -ra / p1 * d1 / p2 * d3 + rb / p2 * d3 / p5 * d4 c3 = ra / p2 * d1 / p4 * d2 - rb / p2 * d2 / p3 * d4 c4 = rb / p5 * d2 / p3 * d3 - y = ya[jx1]*c1 + ya[jx1+1]*c2 + ya[jx1+2]*c3 + ya[jx1+3]*c4 + y = ya[jx1] * c1 + ya[jx1 + 1] * c2 + ya[jx1 + 2] * c3 + ya[jx1 + 3] * c4 # we don't want y to be an array try: @@ -88,7 +86,7 @@ def _unint(xa, ya, x): def _biquad(T, i, xi, yi): """ - This routine interpolates over a 4 point interval using a + This routine interpolates over a 4 point interval using a variation of 2nd degree interpolation to produce a continuity of slope between adjacent intervals. @@ -98,10 +96,9 @@ def _biquad(T, i, xi, yi): T(i+2) = number of y values in yi array T(i+3) = values of x in ascending order """ - lmt = 0 nx = int(T[i]) - ny = int(T[i+1]) + ny = int(T[i + 1]) j1 = int(i + 2) j2 = j1 + nx - 1 # search in x sense @@ -114,12 +111,12 @@ def _biquad(T, i, xi, yi): ifnd_x = 0 jn = 0 xc = [0, 0, 0, 0] - for j in range(j1, j2+1): - if (T[j] >= x): + for j in range(j1, j2 + 1): + if T[j] >= x: ifnd_x = 1 jn = j break - if (ifnd_x == 0): + if ifnd_x == 0: # off high end x = T[j2] kx = 2 @@ -128,29 +125,29 @@ def _biquad(T, i, xi, yi): ra_x = 0.0 else: # test for -- off low end, first interval, other - if (jn < j1+1): - if (T[jn] != x): + if jn < j1 + 1: + if T[jn] != x: kx = 1 x = T[j1] - if (jn <= j1+1): + if jn <= j1 + 1: jx1 = j1 ra_x = 1.0 else: # test for last interval - if (j == j2): + if j == j2: jx1 = j2 - 3 ra_x = 0.0 else: jx1 = jn - 2 - ra_x = (T[jn] - x)/(T[jn] - T[jn-1]) - rb_x = 1. - ra_x + ra_x = (T[jn] - x) / (T[jn] - T[jn - 1]) + rb_x = 1.0 - ra_x # return here from search of x lmt = kx jx = jx1 # The following code puts x values in xc blocks for j in range(4): - xc[j] = T[jx1+j] + xc[j] = T[jx1 + j] # get coeff. in x sense # coefficient routine - input x,x1,x2,x3,x4,ra_x,rb_x p1 = xc[1] - xc[0] @@ -162,17 +159,17 @@ def _biquad(T, i, xi, yi): d2 = x - xc[1] d3 = x - xc[2] d4 = x - xc[3] - cx1 = ra_x/p1*d2/p4*d3 - cx2 = -ra_x/p1*d1/p2*d3 + rb_x/p2*d3/p5*d4 - cx3 = ra_x/p2*d1/p4*d2 - rb_x/p2*d2/p3*d4 - cx4 = rb_x/p5*d2/p3*d3 + cx1 = ra_x / p1 * d2 / p4 * d3 + cx2 = -ra_x / p1 * d1 / p2 * d3 + rb_x / p2 * d3 / p5 * d4 + cx3 = ra_x / p2 * d1 / p4 * d2 - rb_x / p2 * d2 / p3 * d4 + cx4 = rb_x / p5 * d2 / p3 * d3 # return to main body # return here with coeff. test for univariate or bivariate - if (ny == 0): + if ny == 0: z = 0.0 jy = jx + nx - z = cx1*T[jy] + cx2*T[jy+1] + cx3*T[jy+2] + cx4*T[jy+3] + z = cx1 * T[jy] + cx2 * T[jy + 1] + cx3 * T[jy + 2] + cx4 * T[jy + 3] else: # bivariate table y = yi @@ -184,11 +181,11 @@ def _biquad(T, i, xi, yi): # - output ra_y,rb_y,ky,,jy1 ky = 0 ifnd_y = 0 - for j in range(j3, j4+1): - if (T[j] >= y): + for j in range(j3, j4 + 1): + if T[j] >= y: ifnd_y = 1 break - if (ifnd_y == 0): + if ifnd_y == 0: # off high end y = T[j4] ky = 2 @@ -197,31 +194,31 @@ def _biquad(T, i, xi, yi): ra_y = 0.0 else: # test for off low end, first interval - if (j < j3 + 1): - if (T[j] != y): + if j < j3 + 1: + if T[j] != y: ky = 1 y = T[j3] - if (j <= j3 + 1): + if j <= j3 + 1: jy1 = j3 ra_y = 1.0 else: # test for last interval - if (j == j4): + if j == j4: jy1 = j4 - 3 ra_y = 0.0 else: jy1 = j - 2 - ra_y = (T[j] - y)/(T[j] - T[j-1]) + ra_y = (T[j] - y) / (T[j] - T[j - 1]) rb_y = 1.0 - ra_y - lmt = lmt + 3*ky + lmt = lmt + 3 * ky # interpolate in y sense # subscript - base, num. of col., num. of y's - jy = (j4 + 1) + (jx - i - 2)*ny + (jy1 - j3) + jy = (j4 + 1) + (jx - i - 2) * ny + (jy1 - j3) yt = [0, 0, 0, 0] for m in range(4): jx = jy - yt[m] = cx1*T[jx] + cx2*T[jx+ny] + cx3*T[jx+2*ny] + cx4*T[jx+3*ny] + yt[m] = cx1 * T[jx] + cx2 * T[jx + ny] + cx3 * T[jx + 2 * ny] + cx4 * T[jx + 3 * ny] jy = jy + 1 # the following code puts y values in yc block @@ -230,7 +227,7 @@ def _biquad(T, i, xi, yi): yc[j] = T[jy1] jy1 = jy1 + 1 # get coeff. in y sense - # coeffient routine - input y, y1, y2, y3, y4, ra_y, rb_y + # coefficient routine - input y, y1, y2, y3, y4, ra_y, rb_y p1 = yc[1] - yc[0] p2 = yc[2] - yc[1] p3 = yc[3] - yc[2] @@ -240,34 +237,26 @@ def _biquad(T, i, xi, yi): d2 = y - yc[1] d3 = y - yc[2] d4 = y - yc[3] - cy1 = ra_y/p1*d2/p4*d3 - cy2 = -ra_y/p1*d1/p2*d3 + rb_y/p2*d3/p5*d4 - cy3 = ra_y/p2*d1/p4*d2 - rb_y/p2*d2/p3*d4 - cy4 = rb_y/p5*d2/p3*d3 - z = cy1*yt[0] + cy2*yt[1] + cy3*yt[2] + cy4*yt[3] + cy1 = ra_y / p1 * d2 / p4 * d3 + cy2 = -ra_y / p1 * d1 / p2 * d3 + rb_y / p2 * d3 / p5 * d4 + cy3 = ra_y / p2 * d1 / p4 * d2 - rb_y / p2 * d2 / p3 * d4 + cy4 = rb_y / p5 * d2 / p3 * d3 + z = cy1 * yt[0] + cy2 * yt[1] + cy3 * yt[2] + cy4 * yt[3] return z, lmt -# DO NOT AUTO-FORMAT TABLES -# autopep8: off +# block auto-formatting of tables # fmt: off CP_Angle_table = np.array([ [ # 2 blades - [0.0158, 0.0165, .0188, .0230, .0369, - .0588, .0914, .1340, .1816, .22730], # advance_ratio = 0.0 - [0.0215, 0.0459, .0829, .1305, .1906, - .2554, 0.000, 0.000, 0.000, 0.0000], # advance_ratio = 0.5 - [-.0149, -.0088, .0173, .0744, .1414, - .2177, .3011, .3803, 0.000, 0.0000], # advance_ratio = 1.0 - [-.0670, -.0385, .0285, .1304, .2376, - .3536, .4674, .5535, 0.000, 0.0000], # advance_ratio = 1.5 - [-.1150, -.0281, .1086, .2646, .4213, - .5860, .7091, 0.000, 0.000, 0.0000], # advance_ratio = 2.0 - [-.1151, 0.0070, .1436, .2910, .4345, - .5744, .7142, .8506, .9870, 1.1175], # advance_ratio = 3.0 - [-.2427, 0.0782, .4242, .7770, 1.1164, - 1.4443, 0.000, 0.000, 0.000, 0.000], # advance_ratio = 5.0 + [0.0158, 0.0165, .0188, .0230, .0369, .0588, .0914, .1340, .1816, .22730], # advance_ratio = 0.0 + [0.0215, 0.0459, .0829, .1305, .1906, .2554, 0.000, 0.000, 0.000, 0.0000], # advance_ratio = 0.5 + [-.0149, -.0088, .0173, .0744, .1414, .2177, .3011, .3803, 0.000, 0.0000], # advance_ratio = 1.0 + [-.0670, -.0385, .0285, .1304, .2376, .3536, .4674, .5535, 0.000, 0.0000], # advance_ratio = 1.5 + [-.1150, -.0281, .1086, .2646, .4213, .5860, .7091, 0.000, 0.000, 0.0000], # advance_ratio = 2.0 + [-.1151, 0.0070, .1436, .2910, .4345, .5744, .7142, .8506, .9870, 1.1175], # advance_ratio = 3.0 + [-.2427, 0.0782, .4242, .7770, 1.1164, 1.4443, 0.000, 0.000, 0.000, 0.000], # advance_ratio = 5.0 ], [ # 4 blades [.0311, .0320, .0360, .0434, .0691, .1074, .1560, .2249, .3108, .4026], @@ -470,14 +459,11 @@ def _biquad(T, i, xi, yi): .525, .540, .565, .615, .670, .710, .745, .790, .825, .860, .880, .895, # X = 0.20 .225, .260, .320, .375, .430, .495, .550, .610, .660, .710, .740, .775, # X = 0.30 ]) -# autopep8: on # fmt: on class PreHamiltonStandard(om.ExplicitComponent): - """ - Pre-process parameters needed by HamiltonStandard component - """ + """Pre-process parameters needed by HamiltonStandard component.""" def initialize(self): self.options.declare('num_nodes', default=1, types=int) @@ -485,20 +471,17 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Engine.PROPELLER_DIAMETER, val=0.0, units='ft') - add_aviary_input( - self, Dynamic.Mission.PROPELLER_TIP_SPEED, val=np.zeros(nn), units='ft/s' - ) + add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, val=0.0, units='ft') add_aviary_input( - self, Dynamic.Mission.SHAFT_POWER, val=np.zeros(nn), units='hp' - ) - add_aviary_input( - self, Dynamic.Mission.DENSITY, val=np.zeros(nn), units='slug/ft**3' + self, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + val=np.zeros(nn), + units='ft/s', ) + add_aviary_input(self, Dynamic.Vehicle.Propulsion.SHAFT_POWER, val=np.zeros(nn), units='hp') + add_aviary_input(self, Dynamic.Atmosphere.DENSITY, val=np.zeros(nn), units='slug/ft**3') add_aviary_input(self, Dynamic.Mission.VELOCITY, val=np.zeros(nn), units='ft/s') - add_aviary_input( - self, Dynamic.Mission.SPEED_OF_SOUND, val=np.zeros(nn), units='ft/s' - ) + add_aviary_input(self, Dynamic.Atmosphere.SPEED_OF_SOUND, val=np.zeros(nn), units='ft/s') self.add_output('power_coefficient', val=np.zeros(nn), units='unitless') self.add_output('advance_ratio', val=np.zeros(nn), units='unitless') @@ -511,121 +494,140 @@ def setup_partials(self): arange = np.arange(self.options['num_nodes']) # self.declare_partials( - # 'density_ratio', Dynamic.Mission.DENSITY, rows=arange, cols=arange) + # 'density_ratio', Dynamic.Atmosphere.DENSITY, rows=arange, cols=arange) self.declare_partials( 'tip_mach', [ - Dynamic.Mission.PROPELLER_TIP_SPEED, - Dynamic.Mission.SPEED_OF_SOUND, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + Dynamic.Atmosphere.SPEED_OF_SOUND, + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + 'advance_ratio', + [ + Dynamic.Mission.VELOCITY, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, ], rows=arange, cols=arange, ) - self.declare_partials('advance_ratio', [ - Dynamic.Mission.VELOCITY, - Dynamic.Mission.PROPELLER_TIP_SPEED, - ], rows=arange, cols=arange) - self.declare_partials('power_coefficient', [ - Dynamic.Mission.SHAFT_POWER, - Dynamic.Mission.DENSITY, - Dynamic.Mission.PROPELLER_TIP_SPEED, - ], rows=arange, cols=arange) - self.declare_partials('power_coefficient', Aircraft.Engine.PROPELLER_DIAMETER) + self.declare_partials( + 'power_coefficient', + [ + Dynamic.Vehicle.Propulsion.SHAFT_POWER, + Dynamic.Atmosphere.DENSITY, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + ], + rows=arange, + cols=arange, + ) + self.declare_partials('power_coefficient', Aircraft.Engine.Propeller.DIAMETER) def compute(self, inputs, outputs): - diam_prop = inputs[Aircraft.Engine.PROPELLER_DIAMETER] - shp = inputs[Dynamic.Mission.SHAFT_POWER] + diam_prop = inputs[Aircraft.Engine.Propeller.DIAMETER] + shp = inputs[Dynamic.Vehicle.Propulsion.SHAFT_POWER] vtas = inputs[Dynamic.Mission.VELOCITY] - tipspd = inputs[Dynamic.Mission.PROPELLER_TIP_SPEED] - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] + tipspd = inputs[Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] # arbitrarily small number to keep advance ratio nonzero, which allows for static thrust prediction vtas[np.where(vtas <= 1e-6)] = 1e-6 - density_ratio = inputs[Dynamic.Mission.DENSITY] / RHO_SEA_LEVEL_ENGLISH + density_ratio = inputs[Dynamic.Atmosphere.DENSITY] / RHO_SEA_LEVEL_ENGLISH if diam_prop <= 0.0: - raise om.AnalysisError( - "Aircraft.Engine.PROPELLER_DIAMETER must be positive.") + raise om.AnalysisError('Aircraft.Engine.Propeller.DIAMETER must be positive.') if any(tipspd) <= 0.0: raise om.AnalysisError( - "Dynamic.Mission.PROPELLER_TIP_SPEED must be positive.") + 'Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED must be positive.' + ) if any(sos) <= 0.0: - raise om.AnalysisError( - "Dynamic.Mission.SPEED_OF_SOUND must be positive.") + raise om.AnalysisError('Dynamic.Atmosphere.SPEED_OF_SOUND must be positive.') if any(density_ratio) <= 0.0: - raise om.AnalysisError("Dynamic.Mission.DENSITY must be positive.") + raise om.AnalysisError('Dynamic.Atmosphere.DENSITY must be positive.') if any(shp) < 0.0: - raise om.AnalysisError("Dynamic.Mission.SHAFT_POWER must be non-negative.") + raise om.AnalysisError('Dynamic.Vehicle.Propulsion.SHAFT_POWER must be non-negative.') # outputs['density_ratio'] = density_ratio # TODO tip mach was already calculated, revisit this outputs['tip_mach'] = tipspd / sos outputs['advance_ratio'] = math.pi * vtas / tipspd # TODO back out what is going on with unit conversion factor 10e10/(2*6966) + outputs['power_coefficient'] = ( - shp - * 10.0e10 - / (2 * 6966.0) - / density_ratio - / (tipspd**3 * diam_prop**2) + shp * 10.0e10 / (2 * 6966.0) / density_ratio / (tipspd**3 * diam_prop**2) ) def compute_partials(self, inputs, partials): vtas = inputs[Dynamic.Mission.VELOCITY] - tipspd = inputs[Dynamic.Mission.PROPELLER_TIP_SPEED] - rho = inputs[Dynamic.Mission.DENSITY] - diam_prop = inputs[Aircraft.Engine.PROPELLER_DIAMETER] - shp = inputs[Dynamic.Mission.SHAFT_POWER] - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] - - unit_conversion_const = 10.E10 / (2 * 6966.) - - # partials["density_ratio", Dynamic.Mission.DENSITY] = 1 / RHO_SEA_LEVEL_ENGLISH - partials["tip_mach", Dynamic.Mission.PROPELLER_TIP_SPEED] = 1 / sos - partials["tip_mach", Dynamic.Mission.SPEED_OF_SOUND] = -tipspd / sos**2 - partials["advance_ratio", Dynamic.Mission.VELOCITY] = math.pi / tipspd - partials["advance_ratio", Dynamic.Mission.PROPELLER_TIP_SPEED] = ( + tipspd = inputs[Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] + rho = inputs[Dynamic.Atmosphere.DENSITY] + diam_prop = inputs[Aircraft.Engine.Propeller.DIAMETER] + shp = inputs[Dynamic.Vehicle.Propulsion.SHAFT_POWER] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] + + unit_conversion_const = 10.0e10 / (2 * 6966.0) + + # partials["density_ratio", Dynamic.Atmosphere.DENSITY] = 1 / RHO_SEA_LEVEL_ENGLISH + partials['tip_mach', Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] = 1 / sos + partials['tip_mach', Dynamic.Atmosphere.SPEED_OF_SOUND] = -tipspd / sos**2 + partials['advance_ratio', Dynamic.Mission.VELOCITY] = math.pi / tipspd + partials['advance_ratio', Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] = ( -math.pi * vtas / (tipspd * tipspd) ) - partials["power_coefficient", Dynamic.Mission.SHAFT_POWER] = unit_conversion_const * \ - RHO_SEA_LEVEL_ENGLISH / (rho * tipspd**3*diam_prop**2) - partials["power_coefficient", Dynamic.Mission.DENSITY] = -unit_conversion_const * shp * \ - RHO_SEA_LEVEL_ENGLISH / (rho * rho * tipspd**3*diam_prop**2) - partials["power_coefficient", Dynamic.Mission.PROPELLER_TIP_SPEED] = -3 * \ - unit_conversion_const * shp * RHO_SEA_LEVEL_ENGLISH / \ - (rho * tipspd**4*diam_prop**2) - partials["power_coefficient", Aircraft.Engine.PROPELLER_DIAMETER] = -2 * \ - unit_conversion_const * shp * RHO_SEA_LEVEL_ENGLISH / \ - (rho * tipspd**3*diam_prop**3) + partials['power_coefficient', Dynamic.Vehicle.Propulsion.SHAFT_POWER] = ( + unit_conversion_const * RHO_SEA_LEVEL_ENGLISH / (rho * tipspd**3 * diam_prop**2) + ) + partials['power_coefficient', Dynamic.Atmosphere.DENSITY] = ( + -unit_conversion_const + * shp + * RHO_SEA_LEVEL_ENGLISH + / (rho * rho * tipspd**3 * diam_prop**2) + ) + partials['power_coefficient', Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] = ( + -3 + * unit_conversion_const + * shp + * RHO_SEA_LEVEL_ENGLISH + / (rho * tipspd**4 * diam_prop**2) + ) + partials['power_coefficient', Aircraft.Engine.Propeller.DIAMETER] = ( + -2 + * unit_conversion_const + * shp + * RHO_SEA_LEVEL_ENGLISH + / (rho * tipspd**3 * diam_prop**3) + ) class HamiltonStandard(om.ExplicitComponent): """ - This is Hamilton Standard component rewritten from Fortran code. - The original documentation is available at + This is Hamilton Standard component rewritten from Fortran code. + The original documentation is available at https://ntrs.nasa.gov/api/citations/19720010354/downloads/19720010354.pdf It computes the thrust coefficient of a propeller blade. """ def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') self.options.declare('num_nodes', default=1, types=int) + add_aviary_option(self, Aircraft.Engine.Propeller.NUM_BLADES) + add_aviary_option(self, Settings.VERBOSITY) + def setup(self): nn = self.options['num_nodes'] self.add_input('power_coefficient', val=np.zeros(nn), units='unitless') self.add_input('advance_ratio', val=np.zeros(nn), units='unitless') - add_aviary_input(self, Dynamic.Mission.MACH, val=np.zeros(nn), units='unitless') + add_aviary_input(self, Dynamic.Atmosphere.MACH, val=np.zeros(nn), units='unitless') self.add_input('tip_mach', val=np.zeros(nn), units='unitless') add_aviary_input( - self, Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, val=0.0, units='unitless' + self, Aircraft.Engine.Propeller.ACTIVITY_FACTOR, val=0.0, units='unitless' ) # Actitivty Factor per Blade add_aviary_input( self, - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, val=0.0, units='unitless', ) # blade integrated lift coeff @@ -634,15 +636,15 @@ def setup(self): # propeller tip compressibility loss factor self.add_output('comp_tip_loss_factor', val=np.zeros(nn), units='unitless') - self.declare_partials('*', '*', method='fd', form='forward') + self.declare_partials('*', '*', method='cs') def compute(self, inputs, outputs): - verbosity = self.options['aviary_options'].get_val(Settings.VERBOSITY) - act_factor = inputs[Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR][0] - cli = inputs[Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT][0] - num_blades = self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_PROPELLER_BLADES - ) + verbosity = self.options[Settings.VERBOSITY] + num_blades = self.options[Aircraft.Engine.Propeller.NUM_BLADES] + + act_factor = inputs[Aircraft.Engine.Propeller.ACTIVITY_FACTOR][0] + cli = inputs[Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT][0] + # TODO verify this works with multiple engine models (i.e. prop mission is # properly slicing these inputs) # ensure num_blades is an int, so it can be used as array index later @@ -653,22 +655,35 @@ def compute(self, inputs, outputs): else: num_blades = int(num_blades[0]) + AF_adj_CP = np.zeros(7, dtype=cli.dtype) # AFCP: an AF adjustment of CP to be assigned + AF_adj_CT = np.zeros(7, dtype=cli.dtype) # AFCT: an AF adjustment of CT to be assigned + + CTT = np.zeros(7, dtype=cli.dtype) + BLL = np.zeros(7, dtype=cli.dtype) + BLLL = np.zeros(7, dtype=cli.dtype) + PXCLI = np.zeros(7, dtype=cli.dtype) + XFFT = np.zeros(6, dtype=cli.dtype) + CTG = np.zeros(11, dtype=cli.dtype) + CTG1 = np.zeros(11, dtype=cli.dtype) + TXCLI = np.zeros(6, dtype=cli.dtype) + CTTT = np.zeros(4, dtype=cli.dtype) + XXXFT = np.zeros(4, dtype=cli.dtype) + for i_node in range(self.options['num_nodes']): ichck = 0 run_flag = 0 xft = 1.0 - AF_adj_CP = np.zeros(7) # AFCP: an AF adjustment of CP to be assigned - AF_adj_CT = np.zeros(7) # AFCT: an AF adjustment of CT to be assigned - CTT = np.zeros(7) - BLL = np.zeros(7) - BLLL = np.zeros(7) - PXCLI = np.zeros(7) - XFFT = np.zeros(6) - CTG = np.zeros(11) - CTG1 = np.zeros(11) - TXCLI = np.zeros(6) - CTTT = np.zeros(4) - XXXFT = np.zeros(4) + + CTT[:] = 0.0 + BLL[:] = 0.0 + BLLL[:] = 0.0 + PXCLI[:] = 0.0 + XFFT[:] = 0.0 + CTG[:] = 0.0 + CTG1[:] = 0.0 + TXCLI[:] = 0.0 + CTTT[:] = 0.0 + XXXFT[:] = 0.0 for k in range(2): AF_adj_CP[k], run_flag = _unint(Act_Factor_arr, AFCPC[k], act_factor) @@ -676,20 +691,22 @@ def compute(self, inputs, outputs): for k in range(2, 7): AF_adj_CP[k] = AF_adj_CP[1] AF_adj_CT[k] = AF_adj_CT[1] - if (inputs['advance_ratio'][i_node] <= 0.5): - AFCTE = 2.*inputs['advance_ratio'][i_node] * \ - (AF_adj_CT[1] - AF_adj_CT[0]) + AF_adj_CT[0] + if inputs['advance_ratio'][i_node] <= 0.5: + AFCTE = ( + 2.0 * inputs['advance_ratio'][i_node] * (AF_adj_CT[1] - AF_adj_CT[0]) + + AF_adj_CT[0] + ) else: AFCTE = AF_adj_CT[1] # bounding J (advance ratio) for setting up interpolation - if (inputs['advance_ratio'][i_node] <= 1.0): + if inputs['advance_ratio'][i_node] <= 1.0: J_begin = 0 J_end = 3 - elif (inputs['advance_ratio'][i_node] <= 1.5): + elif inputs['advance_ratio'][i_node] <= 1.5: J_begin = 1 J_end = 4 - elif (inputs['advance_ratio'][i_node] <= 2.0): + elif inputs['advance_ratio'][i_node] <= 2.0: J_begin = 2 J_end = 5 else: @@ -705,14 +722,14 @@ def compute(self, inputs, outputs): power_coefficient = inputs['power_coefficient'][i_node] for ii in range(6): cl_idx = ii - if (abs(cli - CL_arr[ii]) <= 0.0009): + if abs(cli - CL_arr[ii]) <= 0.0009: ifnd = 1 break - if (ifnd == 0): - if (cli <= 0.6): + if ifnd == 0: + if cli <= 0.6: CL_tab_idx_begin = 0 CL_tab_idx_end = 3 - elif (cli <= 0.7): + elif cli <= 0.7: CL_tab_idx_begin = 1 CL_tab_idx_end = 4 else: @@ -725,7 +742,7 @@ def compute(self, inputs, outputs): CL_tab_idx_flg = 1 lmod = (num_blades % 2) + 1 - if (lmod == 1): + if lmod == 1: nbb = 1 idx_blade = int(num_blades / 2) # even number of blades idx_blade = 1 if 2 blades; @@ -742,43 +759,55 @@ def compute(self, inputs, outputs): # nbb = 1 even number of blades. No interpolation needed # nbb = 4 odd number of blades. So, interpolation done # using 4 sets of even J (advance ratio) interpolation - for kdx in range(J_begin, J_end+1): - CP_Eff = power_coefficient*AF_adj_CP[kdx] + for kdx in range(J_begin, J_end + 1): + CP_Eff = power_coefficient * AF_adj_CP[kdx] PBL, run_flag = _unint(CPEC, BL_P_corr_table[idx_blade], CP_Eff) # PBL = number of blades correction for power_coefficient - CPE1 = CP_Eff*PBL*PF_CLI_arr[kdx] + CPE1 = CP_Eff * PBL * PF_CLI_arr[kdx] CL_tab_idx = CL_tab_idx_begin - for kl in range(CL_tab_idx_begin, CL_tab_idx_end+1): + for kl in range(CL_tab_idx_begin, CL_tab_idx_end + 1): CPE1X = CPE1 - if (CPE1 < CP_CLi_table[CL_tab_idx][0]): + if CPE1 < CP_CLi_table[CL_tab_idx][0]: CPE1X = CP_CLi_table[CL_tab_idx][0] cli_len = cli_arr_len[CL_tab_idx] PXCLI[kl], run_flag = _unint( - CP_CLi_table[CL_tab_idx][:cli_len], XPCLI[CL_tab_idx], CPE1X) - if (run_flag == 1): + CP_CLi_table[CL_tab_idx][:cli_len], XPCLI[CL_tab_idx], CPE1X + ) + if run_flag == 1: ichck = ichck + 1 - if verbosity >= Verbosity.DEBUG or ichck <= 1: - if (run_flag == 1): + if verbosity == Verbosity.DEBUG or ichck <= Verbosity.BRIEF: + if run_flag == 1: warnings.warn( - f"Mach,VTMACH,J,power_coefficient,CP_Eff =: {inputs[Dynamic.Mission.MACH][i_node]},{inputs['tip_mach'][i_node]},{inputs['advance_ratio'][i_node]},{power_coefficient},{CP_Eff}") - if (kl == 4 and CPE1 < 0.010): + f'Mach = {inputs[Dynamic.Atmosphere.MACH][i_node]}\n' + f'VTMACH = {inputs["tip_mach"][i_node]}\n' + f'J = {inputs["advance_ratio"][i_node]}\n' + f'power_coefficient = {power_coefficient}\n' + f'CP_Eff = {CP_Eff}' + ) + if kl == 4 and CPE1 < 0.010: print( - f"Extrapolated data is being used for CLI=.6--CPE1,PXCLI,L= , {CPE1},{PXCLI[kl]},{idx_blade} Suggest inputting CLI=.5") - if (kl == 5 and CPE1 < 0.010): + f'Extrapolated data is being used for CLI=.6--CPE1,PXCLI,L= , {CPE1},{PXCLI[kl]},{idx_blade} Suggest inputting CLI=.5' + ) + if kl == 5 and CPE1 < 0.010: print( - f"Extrapolated data is being used for CLI=.7--CPE1,PXCLI,L= , {CPE1},{PXCLI[kl]},{idx_blade} Suggest inputting CLI=.5") - if (kl == 6 and CPE1 < 0.010): + f'Extrapolated data is being used for CLI=.7--CPE1,PXCLI,L= , {CPE1},{PXCLI[kl]},{idx_blade} Suggest inputting CLI=.5' + ) + if kl == 6 and CPE1 < 0.010: print( - f"Extrapolated data is being used for CLI=.8--CPE1,PXCLI,L= , {CPE1},{PXCLI[kl]},{idx_blade} Suggest inputting CLI=.5") + f'Extrapolated data is being used for CLI=.8--CPE1,PXCLI,L= , {CPE1},{PXCLI[kl]},{idx_blade} Suggest inputting CLI=.5' + ) NERPT = 1 - CL_tab_idx = CL_tab_idx+1 - if (CL_tab_idx_flg != 1): + CL_tab_idx = CL_tab_idx + 1 + if CL_tab_idx_flg != 1: PCLI, run_flag = _unint( - CL_arr[CL_tab_idx_begin:CL_tab_idx_begin+4], PXCLI[CL_tab_idx_begin:CL_tab_idx_begin+4], inputs[Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT][0]) + CL_arr[CL_tab_idx_begin : CL_tab_idx_begin + 4], + PXCLI[CL_tab_idx_begin : CL_tab_idx_begin + 4], + inputs[Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT][0], + ) else: PCLI = PXCLI[CL_tab_idx_begin] # PCLI = CLI adjustment to power_coefficient - CP_Eff = CP_Eff*PCLI # the effective CP at baseline point for kdx + CP_Eff = CP_Eff * PCLI # the effective CP at baseline point for kdx ang_len = ang_arr_len[kdx] BLL[kdx], run_flag = _unint( # blade angle at baseline point for kdx @@ -789,115 +818,134 @@ def compute(self, inputs, outputs): try: CTT[kdx], run_flag = _unint( # thrust coeff at baseline point for kdx - Blade_angle_table[kdx][:ang_len], CT_Angle_table[idx_blade][kdx][:ang_len], BLL[kdx]) + Blade_angle_table[kdx][:ang_len], + CT_Angle_table[idx_blade][kdx][:ang_len], + BLL[kdx], + ) except IndexError: raise om.AnalysisError( - "interp failed for CTT (thrust coefficient) in hamilton_standard.py") + 'interp failed for CTT (thrust coefficient) in hamilton_standard.py' + ) if run_flag > 1: NERPT = 2 - if verbosity >= Verbosity.DEBUG: - print( - f"ERROR IN PROP. PERF.-- NERPT={NERPT}, run_flag={run_flag}") + print(f'ERROR IN PROP. PERF.-- NERPT={NERPT}, run_flag={run_flag}') BLLL[ibb], run_flag = _unint( - advance_ratio_array[J_begin:J_begin+4], BLL[J_begin:J_begin+4], inputs['advance_ratio'][i_node]) + advance_ratio_array[J_begin : J_begin + 4], + BLL[J_begin : J_begin + 4], + inputs['advance_ratio'][i_node], + ) ang_blade = BLLL[ibb] CTTT[ibb], run_flag = _unint( - advance_ratio_array[J_begin:J_begin+4], CTT[J_begin:J_begin+4], inputs['advance_ratio'][i_node]) + advance_ratio_array[J_begin : J_begin + 4], + CTT[J_begin : J_begin + 4], + inputs['advance_ratio'][i_node], + ) # make extra correction. CTG is an "error" function, and the iteration (loop counter = "IL") tries to drive CTG/CT to 0 # ERR_CT = CTG1[il]/CTTT[ibb], where CTG1 =CT_Eff - CTTT(IBB). - CTG[0] = .100 - CTG[1] = .200 + CTG[0] = 0.100 + CTG[1] = 0.200 TFCLII, run_flag = _unint( - advance_ratio_array, TF_CLI_arr, inputs['advance_ratio'][i_node]) + advance_ratio_array, TF_CLI_arr, inputs['advance_ratio'][i_node] + ) NCTG = 10 ifnd1 = 0 ifnd2 = 0 for il in range(NCTG): ct = CTG[il] - CT_Eff = CTG[il]*AFCTE + CT_Eff = CTG[il] * AFCTE TBL, run_flag = _unint(CTEC, BL_T_corr_table[idx_blade], CT_Eff) # TBL = number of blades correction for thrust_coefficient - CTE1 = CT_Eff*TBL*TFCLII + CTE1 = CT_Eff * TBL * TFCLII CL_tab_idx = CL_tab_idx_begin - for kl in range(CL_tab_idx_begin, CL_tab_idx_end+1): + for kl in range(CL_tab_idx_begin, CL_tab_idx_end + 1): CTE1X = CTE1 - if (CTE1 < CT_CLi_table[CL_tab_idx][0]): + if CTE1 < CT_CLi_table[CL_tab_idx][0]: CTE1X = CT_CLi_table[CL_tab_idx][0] cli_len = cli_arr_len[CL_tab_idx] TXCLI[kl], run_flag = _unint( - CT_CLi_table[CL_tab_idx][:cli_len], XTCLI[CL_tab_idx][:cli_len], CTE1X) + CT_CLi_table[CL_tab_idx][:cli_len], XTCLI[CL_tab_idx][:cli_len], CTE1X + ) NERPT = 5 - if (run_flag == 1): + if run_flag == 1: # off lower bound only. - if verbosity >= Verbosity.DEBUG: - print( - f"ERROR IN PROP. PERF.-- NERPT={NERPT}, run_flag={run_flag}, il = {il}, kl = {kl}") - if (inputs['advance_ratio'][i_node] != 0.0): + print( + f'ERROR IN PROP. PERF.-- NERPT={NERPT}, ' + f'run_flag={run_flag}, il={il}, kl = {kl}' + ) + if inputs['advance_ratio'][i_node] != 0.0: ZMCRT, run_flag = _unint( - advance_ratio_array2, mach_corr_table[CL_tab_idx], inputs['advance_ratio'][i_node]) - DMN = inputs[Dynamic.Mission.MACH][i_node] - ZMCRT + advance_ratio_array2, + mach_corr_table[CL_tab_idx], + inputs['advance_ratio'][i_node], + ) + DMN = inputs[Dynamic.Atmosphere.MACH][i_node] - ZMCRT else: ZMCRT = mach_tip_corr_arr[CL_tab_idx] DMN = inputs['tip_mach'][i_node] - ZMCRT XFFT[kl] = 1.0 # compressibility tip loss factor - if (DMN > 0.0): - CTE2 = CT_Eff*TXCLI[kl]*TBL + if DMN > 0.0: + CTE2 = CT_Eff * TXCLI[kl] * TBL XFFT[kl], run_flag = _biquad(comp_mach_CT_arr, 1, DMN, CTE2) CL_tab_idx = CL_tab_idx + 1 - if (CL_tab_idx_flg != 1): - cli = inputs[Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT][0] + if CL_tab_idx_flg != 1: + cli = inputs[Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT][0] TCLII, run_flag = _unint( - CL_arr[CL_tab_idx_begin:CL_tab_idx_begin+4], TXCLI[CL_tab_idx_begin:CL_tab_idx_begin+4], cli) + CL_arr[CL_tab_idx_begin : CL_tab_idx_begin + 4], + TXCLI[CL_tab_idx_begin : CL_tab_idx_begin + 4], + cli, + ) xft, run_flag = _unint( - CL_arr[CL_tab_idx_begin:CL_tab_idx_begin+4], XFFT[CL_tab_idx_begin:CL_tab_idx_begin+4], cli) + CL_arr[CL_tab_idx_begin : CL_tab_idx_begin + 4], + XFFT[CL_tab_idx_begin : CL_tab_idx_begin + 4], + cli, + ) else: TCLII = TXCLI[CL_tab_idx_begin] xft = XFFT[CL_tab_idx_begin] ct = CTG[il] - CT_Eff = CTG[il]*AFCTE*TCLII + CT_Eff = CTG[il] * AFCTE * TCLII CTG1[il] = CT_Eff - CTTT[ibb] - if (abs(CTG1[il]/CTTT[ibb]) < 0.001): + if abs(CTG1[il] / CTTT[ibb]) < 0.001: ifnd1 = 1 break - if (il > 0): - CTG[il+1] = -CTG1[il-1] * \ - (CTG[il] - CTG[il-1])/(CTG1[il] - CTG1[il-1]) + CTG[il-1] - if (CTG[il+1] <= 0): + if il > 0: + CTG[il + 1] = ( + -CTG1[il - 1] * (CTG[il] - CTG[il - 1]) / (CTG1[il] - CTG1[il - 1]) + + CTG[il - 1] + ) + if CTG[il + 1] <= 0: ifnd2 = 1 break - if (ifnd1 == 0 and ifnd2 == 0): + if ifnd1 == 0 and ifnd2 == 0: raise ValueError( - "Integrated design cl adjustment not working properly for ct " - f"definition (ibb={ibb})" + 'Integrated design cl adjustment not working properly for ct ' + f'definition (ibb={ibb})' ) - if (ifnd1 == 0 and ifnd2 == 1): + if ifnd1 == 0 and ifnd2 == 1: ct = 0.0 CTTT[ibb] = ct XXXFT[ibb] = xft idx_blade = idx_blade + 1 - if (nbb != 1): + if nbb != 1: # interpolation by the number of blades if odd number - ang_blade, run_flag = _unint( - num_blades_arr, BLLL[:4], num_blades) + ang_blade, run_flag = _unint(num_blades_arr, BLLL[:4], num_blades) ct, run_flag = _unint(num_blades_arr, CTTT, num_blades) xft, run_flag = _unint(num_blades_arr, XXXFT, num_blades) # NOTE this could be handled via the metamodel comps (extrapolate flag) - if verbosity >= Verbosity.DEBUG and ichck > 0: - print(f" table look-up error = {ichck} (if you go outside the tables.)") + if ichck > 0: + print(f' table look-up error = {ichck} (if you go outside the tables.)') outputs['thrust_coefficient'][i_node] = ct outputs['comp_tip_loss_factor'][i_node] = xft class PostHamiltonStandard(om.ExplicitComponent): - """ - Post-process after HamiltonStandard run to get thrust and compressibility - """ + """Post-process after HamiltonStandard run to get thrust and compressibility.""" def initialize(self): self.options.declare('num_nodes', default=1, types=int) @@ -905,21 +953,22 @@ def initialize(self): def setup(self): nn = self.options['num_nodes'] - add_aviary_input(self, Aircraft.Engine.PROPELLER_DIAMETER, val=0.0, units='ft') - self.add_input('install_loss_factor', - val=np.zeros(nn), units='unitless') + add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, val=0.0, units='ft') + self.add_input('install_loss_factor', val=np.zeros(nn), units='unitless') self.add_input('thrust_coefficient', val=np.zeros(nn), units='unitless') self.add_input('comp_tip_loss_factor', val=np.zeros(nn), units='unitless') add_aviary_input( - self, Dynamic.Mission.PROPELLER_TIP_SPEED, val=np.zeros(nn), units='ft/s' + self, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + val=np.zeros(nn), + units='ft/s', ) - self.add_input(Dynamic.Mission.DENSITY, val=np.zeros(nn), units='slug/ft**3') + self.add_input(Dynamic.Atmosphere.DENSITY, val=np.zeros(nn), units='slug/ft**3') self.add_input('advance_ratio', val=np.zeros(nn), units='unitless') self.add_input('power_coefficient', val=np.zeros(nn), units='unitless') - self.add_output('thrust_coefficient_comp_loss', - val=np.zeros(nn), units='unitless') - add_aviary_output(self, Dynamic.Mission.THRUST, val=np.zeros(nn), units='lbf') + self.add_output('thrust_coefficient_comp_loss', val=np.zeros(nn), units='unitless') + add_aviary_output(self, Dynamic.Vehicle.Propulsion.THRUST, val=np.zeros(nn), units='lbf') # keep them for reporting but don't seem to be required self.add_output('propeller_efficiency', val=np.zeros(nn), units='unitless') self.add_output('install_efficiency', val=np.zeros(nn), units='unitless') @@ -927,48 +976,65 @@ def setup(self): def setup_partials(self): arange = np.arange(self.options['num_nodes']) - self.declare_partials('thrust_coefficient_comp_loss', [ - 'thrust_coefficient', - 'comp_tip_loss_factor', - ], rows=arange, cols=arange) self.declare_partials( - Dynamic.Mission.THRUST, + 'thrust_coefficient_comp_loss', + [ + 'thrust_coefficient', + 'comp_tip_loss_factor', + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + Dynamic.Vehicle.Propulsion.THRUST, [ 'thrust_coefficient', 'comp_tip_loss_factor', - Dynamic.Mission.PROPELLER_TIP_SPEED, - Dynamic.Mission.DENSITY, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + Dynamic.Atmosphere.DENSITY, + 'install_loss_factor', + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + Dynamic.Vehicle.Propulsion.THRUST, + [ + Aircraft.Engine.Propeller.DIAMETER, + ], + ) + self.declare_partials( + 'propeller_efficiency', + [ + 'advance_ratio', + 'power_coefficient', + 'thrust_coefficient', + 'comp_tip_loss_factor', + ], + rows=arange, + cols=arange, + ) + self.declare_partials( + 'install_efficiency', + [ + 'advance_ratio', + 'power_coefficient', + 'thrust_coefficient', + 'comp_tip_loss_factor', 'install_loss_factor', ], rows=arange, cols=arange, ) - self.declare_partials(Dynamic.Mission.THRUST, [ - Aircraft.Engine.PROPELLER_DIAMETER, - ]) - self.declare_partials('propeller_efficiency', [ - 'advance_ratio', - 'power_coefficient', - 'thrust_coefficient', - 'comp_tip_loss_factor', - ], rows=arange, cols=arange) - self.declare_partials('install_efficiency', [ - 'advance_ratio', - 'power_coefficient', - 'thrust_coefficient', - 'comp_tip_loss_factor', - 'install_loss_factor', - ], rows=arange, cols=arange) def compute(self, inputs, outputs): - ctx = inputs['thrust_coefficient']*inputs['comp_tip_loss_factor'] + ctx = inputs['thrust_coefficient'] * inputs['comp_tip_loss_factor'] outputs['thrust_coefficient_comp_loss'] = ctx - diam_prop = inputs[Aircraft.Engine.PROPELLER_DIAMETER] - tipspd = inputs[Dynamic.Mission.PROPELLER_TIP_SPEED] + diam_prop = inputs[Aircraft.Engine.Propeller.DIAMETER] + tipspd = inputs[Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] install_loss_factor = inputs['install_loss_factor'] - density_ratio = inputs[Dynamic.Mission.DENSITY] / RHO_SEA_LEVEL_ENGLISH - - outputs[Dynamic.Mission.THRUST] = ( + density_ratio = inputs[Dynamic.Atmosphere.DENSITY] / RHO_SEA_LEVEL_ENGLISH + outputs[Dynamic.Vehicle.Propulsion.THRUST] = ( ctx * tipspd**2 * diam_prop**2 @@ -981,26 +1047,31 @@ def compute(self, inputs, outputs): # avoid divide by zero when shaft power is zero calc_idx = np.where(inputs['power_coefficient'] > 1e-6) # index where CP > 1e-5 prop_eff = np.zeros(self.options['num_nodes']) - prop_eff[calc_idx] = inputs['advance_ratio'][calc_idx] * ctx[calc_idx] \ + prop_eff[calc_idx] = ( + inputs['advance_ratio'][calc_idx] + * ctx[calc_idx] / inputs['power_coefficient'][calc_idx] + ) outputs['propeller_efficiency'] = prop_eff - outputs['install_efficiency'] = outputs['propeller_efficiency'] * \ - (1. - install_loss_factor) + outputs['install_efficiency'] = outputs['propeller_efficiency'] * ( + 1.0 - install_loss_factor + ) def compute_partials(self, inputs, partials): nn = self.options['num_nodes'] XFT = inputs['comp_tip_loss_factor'] - ctx = inputs['thrust_coefficient']*XFT - diam_prop = inputs[Aircraft.Engine.PROPELLER_DIAMETER] + ctx = inputs['thrust_coefficient'] * XFT + diam_prop = inputs[Aircraft.Engine.Propeller.DIAMETER] install_loss_factor = inputs['install_loss_factor'] - tipspd = inputs[Dynamic.Mission.PROPELLER_TIP_SPEED] - density_ratio = inputs[Dynamic.Mission.DENSITY] / RHO_SEA_LEVEL_ENGLISH - - unit_conversion_factor = 364.76 / 1.515E06 - partials["thrust_coefficient_comp_loss", 'thrust_coefficient'] = XFT - partials["thrust_coefficient_comp_loss", - 'comp_tip_loss_factor'] = inputs['thrust_coefficient'] - partials[Dynamic.Mission.THRUST, 'thrust_coefficient'] = ( + tipspd = inputs[Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] + density_ratio = inputs[Dynamic.Atmosphere.DENSITY] / RHO_SEA_LEVEL_ENGLISH + + unit_conversion_factor = 364.76 / 1.515e06 + partials['thrust_coefficient_comp_loss', 'thrust_coefficient'] = XFT + partials['thrust_coefficient_comp_loss', 'comp_tip_loss_factor'] = inputs[ + 'thrust_coefficient' + ] + partials[Dynamic.Vehicle.Propulsion.THRUST, 'thrust_coefficient'] = ( XFT * tipspd**2 * diam_prop**2 @@ -1008,7 +1079,7 @@ def compute_partials(self, inputs, partials): * unit_conversion_factor * (1.0 - install_loss_factor) ) - partials[Dynamic.Mission.THRUST, 'comp_tip_loss_factor'] = ( + partials[Dynamic.Vehicle.Propulsion.THRUST, 'comp_tip_loss_factor'] = ( inputs['thrust_coefficient'] * tipspd**2 * diam_prop**2 @@ -1016,7 +1087,9 @@ def compute_partials(self, inputs, partials): * unit_conversion_factor * (1.0 - install_loss_factor) ) - partials[Dynamic.Mission.THRUST, Dynamic.Mission.PROPELLER_TIP_SPEED] = ( + partials[ + Dynamic.Vehicle.Propulsion.THRUST, Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED + ] = ( 2 * ctx * tipspd @@ -1025,7 +1098,7 @@ def compute_partials(self, inputs, partials): * unit_conversion_factor * (1.0 - install_loss_factor) ) - partials[Dynamic.Mission.THRUST, Aircraft.Engine.PROPELLER_DIAMETER] = ( + partials[Dynamic.Vehicle.Propulsion.THRUST, Aircraft.Engine.Propeller.DIAMETER] = ( 2 * ctx * tipspd**2 @@ -1034,14 +1107,15 @@ def compute_partials(self, inputs, partials): * unit_conversion_factor * (1.0 - install_loss_factor) ) - partials[Dynamic.Mission.THRUST, Dynamic.Mission.DENSITY] = ( + partials[Dynamic.Vehicle.Propulsion.THRUST, Dynamic.Atmosphere.DENSITY] = ( ctx * tipspd**2 * diam_prop**2 * unit_conversion_factor - * (1.0 - install_loss_factor) / RHO_SEA_LEVEL_ENGLISH + * (1.0 - install_loss_factor) + / RHO_SEA_LEVEL_ENGLISH ) - partials[Dynamic.Mission.THRUST, 'install_loss_factor'] = ( + partials[Dynamic.Vehicle.Propulsion.THRUST, 'install_loss_factor'] = ( -ctx * tipspd**2 * diam_prop**2 * density_ratio * unit_conversion_factor ) @@ -1055,17 +1129,16 @@ def compute_partials(self, inputs, partials): deriv_propeff_cp = np.zeros(nn, dtype=pow_coeff.dtype) deriv_propeff_adv[calc_idx] = ctx[calc_idx] / pow_coeff[calc_idx] - deriv_propeff_ct[calc_idx] = adv_ratio[calc_idx] * \ - XFT[calc_idx]/pow_coeff[calc_idx] - deriv_propeff_tip[calc_idx] = adv_ratio[calc_idx] * \ - inputs['thrust_coefficient'][calc_idx]/pow_coeff[calc_idx] - deriv_propeff_cp[calc_idx] = - \ - adv_ratio[calc_idx]*ctx[calc_idx]/pow_coeff[calc_idx]**2 - - partials["propeller_efficiency", "advance_ratio"] = deriv_propeff_adv - partials["propeller_efficiency", "thrust_coefficient"] = deriv_propeff_ct - partials["propeller_efficiency", "comp_tip_loss_factor"] = deriv_propeff_tip - partials["propeller_efficiency", "power_coefficient"] = deriv_propeff_cp + deriv_propeff_ct[calc_idx] = adv_ratio[calc_idx] * XFT[calc_idx] / pow_coeff[calc_idx] + deriv_propeff_tip[calc_idx] = ( + adv_ratio[calc_idx] * inputs['thrust_coefficient'][calc_idx] / pow_coeff[calc_idx] + ) + deriv_propeff_cp[calc_idx] = -adv_ratio[calc_idx] * ctx[calc_idx] / pow_coeff[calc_idx] ** 2 + + partials['propeller_efficiency', 'advance_ratio'] = deriv_propeff_adv + partials['propeller_efficiency', 'thrust_coefficient'] = deriv_propeff_ct + partials['propeller_efficiency', 'comp_tip_loss_factor'] = deriv_propeff_tip + partials['propeller_efficiency', 'power_coefficient'] = deriv_propeff_cp deriv_insteff_adv = np.zeros(nn, dtype=pow_coeff.dtype) deriv_insteff_ct = np.zeros(nn, dtype=pow_coeff.dtype) @@ -1073,20 +1146,31 @@ def compute_partials(self, inputs, partials): deriv_insteff_cp = np.zeros(nn, dtype=pow_coeff.dtype) deriv_insteff_lf = np.zeros(nn, dtype=pow_coeff.dtype) - deriv_insteff_adv[calc_idx] = ctx[calc_idx] / \ - pow_coeff[calc_idx] * (1. - install_loss_factor[calc_idx]) - deriv_insteff_ct[calc_idx] = adv_ratio[calc_idx] * \ - XFT[calc_idx]/pow_coeff[calc_idx] * (1. - install_loss_factor[calc_idx]) - deriv_insteff_tip[calc_idx] = adv_ratio[calc_idx] * \ - inputs['thrust_coefficient'][calc_idx] / \ - pow_coeff[calc_idx] * (1. - install_loss_factor[calc_idx]) - deriv_insteff_cp[calc_idx] = -adv_ratio[calc_idx] * \ - ctx[calc_idx]/pow_coeff[calc_idx]**2 * (1. - install_loss_factor[calc_idx]) - deriv_insteff_lf[calc_idx] = - \ - adv_ratio[calc_idx]*ctx[calc_idx]/pow_coeff[calc_idx] - - partials["install_efficiency", "advance_ratio"] = deriv_insteff_adv - partials["install_efficiency", "thrust_coefficient"] = deriv_insteff_ct - partials["install_efficiency", "comp_tip_loss_factor"] = deriv_insteff_tip - partials["install_efficiency", "power_coefficient"] = deriv_insteff_cp - partials["install_efficiency", 'install_loss_factor'] = deriv_insteff_lf + deriv_insteff_adv[calc_idx] = ( + ctx[calc_idx] / pow_coeff[calc_idx] * (1.0 - install_loss_factor[calc_idx]) + ) + deriv_insteff_ct[calc_idx] = ( + adv_ratio[calc_idx] + * XFT[calc_idx] + / pow_coeff[calc_idx] + * (1.0 - install_loss_factor[calc_idx]) + ) + deriv_insteff_tip[calc_idx] = ( + adv_ratio[calc_idx] + * inputs['thrust_coefficient'][calc_idx] + / pow_coeff[calc_idx] + * (1.0 - install_loss_factor[calc_idx]) + ) + deriv_insteff_cp[calc_idx] = ( + -adv_ratio[calc_idx] + * ctx[calc_idx] + / pow_coeff[calc_idx] ** 2 + * (1.0 - install_loss_factor[calc_idx]) + ) + deriv_insteff_lf[calc_idx] = -adv_ratio[calc_idx] * ctx[calc_idx] / pow_coeff[calc_idx] + + partials['install_efficiency', 'advance_ratio'] = deriv_insteff_adv + partials['install_efficiency', 'thrust_coefficient'] = deriv_insteff_ct + partials['install_efficiency', 'comp_tip_loss_factor'] = deriv_insteff_tip + partials['install_efficiency', 'power_coefficient'] = deriv_insteff_cp + partials['install_efficiency', 'install_loss_factor'] = deriv_insteff_lf diff --git a/aviary/subsystems/propulsion/propeller/propeller_builder.py b/aviary/subsystems/propulsion/propeller/propeller_builder.py new file mode 100644 index 0000000000..8070e7d24d --- /dev/null +++ b/aviary/subsystems/propulsion/propeller/propeller_builder.py @@ -0,0 +1,129 @@ +from aviary.subsystems.propulsion.propeller.propeller_performance import PropellerPerformance +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase +from aviary.utils.named_values import NamedValues +from aviary.variable_info.variables import Aircraft, Dynamic, Mission + + +class PropellerBuilder(SubsystemBuilderBase): + """ + Define the builder for a propeller model using the Hamilton Standard methodology that provides + methods to define the propeller subsystem's states, design variables, fixed values, initial + guesses, and mass names. It also provides methods to build OpenMDAO systems for the pre-mission + and mission computations of the subsystem, to get the constraints for the subsystem, and to + preprocess the inputs for + the subsystem. + + Attributes + ---------- + name : str ('propeller') + Object label. + data : NamedVaues (), optional + Propeller performance data (optional). If provided, used instead of tabular data file + (Aircraft.Engine.Propeller.DATA_FILE). + """ + + def __init__(self, name='propeller', data: NamedValues = None): + """Initializes the PropellerBuilder object with a given name.""" + super().__init__(name) + self.data = data + + def build_pre_mission(self, aviary_inputs): + """Builds an OpenMDAO system for the pre-mission computations of the subsystem.""" + return + + def build_mission(self, num_nodes, aviary_inputs): + """Builds an OpenMDAO system for the mission computations of the subsystem.""" + return PropellerPerformance( + num_nodes=num_nodes, aviary_options=aviary_inputs, propeller_data=self.data + ) + + def get_design_vars(self): + """ + Design vars are only tested to see if they exist in pre_mission + Returns a dictionary of design variables for the gearbox subsystem, where the keys are the + names of the design variables, and the values are dictionaries that contain the units for + the design variable, the lower and upper bounds for the design variable, and any + additional keyword arguments required by OpenMDAO for the design variable. + + Returns + ------- + parameters : dict + A dict of names for the propeller subsystem. + """ + # TODO bounds are rough placeholders + DVs = { + Aircraft.Engine.Propeller.ACTIVITY_FACTOR: { + 'units': 'unitless', + 'lower': 100, + 'upper': 200, + # 'val': 100, # initial value + }, + Aircraft.Engine.Propeller.DIAMETER: { + 'units': 'ft', + 'lower': 0.0, + 'upper': None, + # 'val': 8, # initial value + }, + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT: { + 'units': 'unitless', + 'lower': 0.0, + 'upper': 0.5, + # 'val': 0.5, + }, + } + return DVs + + def get_parameters(self, aviary_inputs=None, phase_info=None): + """ + Parameters are only tested to see if they exist in mission. + The value doesn't change throughout the mission. + Returns a dictionary of fixed values for the propeller subsystem, where the keys + are the names of the fixed values, and the values are dictionaries that contain + the fixed value for the variable, the units for the variable, and any additional + keyword arguments required by OpenMDAO for the variable. + + Returns + ------- + parameters : dict + A dict of names for the propeller subsystem. + """ + parameters = { + Aircraft.Engine.Propeller.TIP_MACH_MAX: { + 'val': 1.0, + 'units': 'unitless', + }, + Aircraft.Engine.Propeller.TIP_SPEED_MAX: { + 'val': 0.0, + 'units': 'ft/s', + }, + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT: { + 'val': 0.0, + 'units': 'unitless', + }, + Aircraft.Engine.Propeller.ACTIVITY_FACTOR: { + 'val': 0.0, + 'units': 'unitless', + }, + Aircraft.Engine.Propeller.DIAMETER: { + 'val': 0.0, + 'units': 'ft', + }, + Aircraft.Nacelle.AVG_DIAMETER: { + 'val': 0.0, + 'units': 'ft', + }, + } + + return parameters + + def get_mass_names(self): + return [Aircraft.Engine.Gearbox.MASS] + + def get_outputs(self): + return [ + Dynamic.Vehicle.Propulsion.SHAFT_POWER + '_out', + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX + '_out', + Dynamic.Vehicle.Propulsion.RPM + '_out', + Dynamic.Vehicle.Propulsion.TORQUE + '_out', + Mission.Constraints.GEARBOX_SHAFT_POWER_RESIDUAL, + ] diff --git a/aviary/subsystems/propulsion/propeller/propeller_map.py b/aviary/subsystems/propulsion/propeller/propeller_map.py index 29cdd7a8bf..9c24d0aa86 100644 --- a/aviary/subsystems/propulsion/propeller/propeller_map.py +++ b/aviary/subsystems/propulsion/propeller/propeller_map.py @@ -1,142 +1,103 @@ -import numpy as np import warnings +from pathlib import Path + +import numpy as np import openmdao.api as om -from openmdao.utils.units import convert_units -from aviary.subsystems.propulsion.utils import PropellerModelVariables, default_propeller_units -from aviary.utils.aviary_values import AviaryValues, NamedValues, get_keys from aviary.utils.csv_data_file import read_data_file -from aviary.utils.functions import get_path -from aviary.variable_info.enums import OutMachType -from aviary.variable_info.variables import Aircraft, Settings - - -MACH = PropellerModelVariables.MACH -CP = PropellerModelVariables.CP -CT = PropellerModelVariables.CT -J = PropellerModelVariables.J +from aviary.utils.data_interpolator_builder import build_data_interpolator +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_option +from aviary.variable_info.variables import Aircraft, Dynamic, Settings +from aviary.utils.named_values import NamedValues aliases = { # whitespaces are replaced with underscores converted to lowercase before # comparison with keys - MACH: ['m', 'mn', 'mach', 'mach_number', 'helical_mach'], - CP: ['cp', 'power_coefficient'], - CT: ['ct', 'thrust_coefficient'], - J: ['j', 'advance_ratio'], + 'helical_mach': [ + 'helical_mach', + 'mach_helical', + 'm_helical', + 'mn_helical', + 'mach_number_helical', + 'helical_mach_number', + ], + Dynamic.Atmosphere.MACH: ['m', 'mn', 'mach', 'mach_number'], + 'power_coefficient': ['cp', 'power_coefficient'], + 'thrust_coefficient': ['ct', 'thrust_coefficient'], + 'advance_ratio': ['j', 'advance_ratio'], } -class PropellerMap(om.ExplicitComponent): +class PropellerMap(om.Group): """ - This class loads a user provided propeller map into memory and builds a propeller. - Attributes - ---------- - name : str ('propeller') - Object label. - options : AviaryValues () - Inputs and options related to propeller model. - data : NamedVaues (), optional - propeller map data. - mach_type: OutMachType (MACH or HELICAL_MACH) + An OpenMDAO group that contains a metamodel comp for given propeller performance data as well as + optional conversion component if required Mach number for data is helical. Used in + PropellerPerformance. """ - def __init__(self, name='propeller', options: AviaryValues = None, - data: NamedValues = None): - super().__init__() - - # working copy of propeller performance data, is modified during data pre-processing - self.data = {key: np.array([]) for key in PropellerModelVariables} - - # Create dict for variables present in propeller data with associated units - self.propeller_variables = {} - - data_file = options.get_val(Aircraft.Engine.PROPELLER_DATA_FILE) - self._read_data(data_file) - - def _read_data(self, data_file): - # read csv file - raw_data = read_data_file(data_file, aliases=aliases) - - message = f'<{data_file}>' - # Loop through all variables in provided data. Track which valid variables are - # included with the data and save raw data for reference - for key in get_keys(raw_data): - val, units = raw_data.get_item(key) - if key in aliases: - # Convert data to expected units. Required so settings like tolerances - # that assume units work as expected - try: - val = np.array([convert_units(i, units, default_propeller_units[key]) - for i in val]) - except TypeError: - raise TypeError(f"{message}: units of '{units}' provided for " - f'<{key.name}> are not compatible with expected units ' - f'of {default_propeller_units[key]}') - - # propeller_variables currently only used to store "valid" engine variables - # as defined in PropellerModelVariables Enum - self.propeller_variables[key] = default_propeller_units[key] - - else: - if self.get_val(Settings.VERBOSITY).value >= 1: + def initialize(self): + self.options.declare('num_nodes', default=1, types=int) + self.options.declare( + 'propeller_data', + types=NamedValues, + default=None, + desc='propeller performance data to be used instead of data file (optional)', + ) + add_aviary_option(self, Aircraft.Engine.Propeller.DATA_FILE) + add_aviary_option(self, Settings.VERBOSITY) + + def setup(self): + nn = self.options['num_nodes'] + data = self.options['propeller_data'] + data_file = self.options[Aircraft.Engine.Propeller.DATA_FILE] + verbosity = self.options[Settings.VERBOSITY] + + if data is None: + data, inputs, outputs = read_data_file(data_file, aliases=aliases, verbosity=verbosity) + if verbosity > Verbosity.BRIEF: + print(f'Reading propeller performance data from {data_file}') + else: + if verbosity > Verbosity.BRIEF: + if data_file is not None: warnings.warn( - f'{message}: header <{key}> was not recognized, and will be skipped') - - self.data[key] = val - - if not self.propeller_variables: + f'Propeller performance map provided as both a data file and as data ' + 'passed in-memory. Provided data file will be not be used.' + ) + print(f'Reading propeller performance data from {data_file}') + + # determine the mach type from data + mach_types = [key for key in ['mach', 'helical_mach'] if key in data] + + # Both machs being present is fine. Default to Mach number + if len(mach_types) > 1: + if verbosity > Verbosity.BRIEF: # VERBOSE, DEBUG + warnings.warn( + 'Both Mach and helical Mach are present in propeller data file ' + f'<{data_file}>. Using Mach number.' + ) + # if neither Mach is present, raise an error + if len(mach_types) == 0: raise UserWarning( - f'No valid propeller variables found in data for {message}') - - def read_and_set_mach_type(self, data_file): - # read the mach type from header. - # sample header: - # J, Helical_Mach, CP, CT - - m_type = 'mach' # default to freestream Mach number - m_type_define = False - fp = get_path(data_file) - with open(fp, "r") as f: - for line in f: - tokens = line.split(',') - if len(tokens) > 1: - s = tokens[1].strip().lower() - if s == 'mach' or s == 'helical_mach': - m_type = s - m_type_define = True - break - - if not m_type_define: - warnings.warn( - f"String 'mach_type' is not defined. Assume freestream Mach in the table.") - - return OutMachType.get_element_by_value(m_type) - - def build_propeller_interpolator(self, num_nodes, options=None): - """ - Builds the OpenMDAO metamodel component for the propeller map. - """ - interp_method = options.get_val(Aircraft.Engine.INTERPOLATION_METHOD) - # interpolator object for propeller data - propeller = om.MetaModelSemiStructuredComp( - method=interp_method, extrapolate=True, vec_size=num_nodes) - - # add inputs and outputs to interpolator - # depending on p, selected_mach can be Mach number (Dynamic.Mission.MACH) or helical Mach number - propeller.add_input('selected_mach', - self.data[MACH], - units='unitless', - desc='Current Mach number (flight or helical)') - propeller.add_input('power_coefficient', - self.data[CP], - units='unitless', - desc='Current power coefficient') - propeller.add_input('advance_ratio', - self.data[J], - units='unitless', - desc='Current advance ratio') - propeller.add_output('thrust_coefficient', - self.data[CT], - units='unitless', - desc='Current thrust coefficient') - return propeller + 'Neither Mach or helical Mach are present in propeller data file ' + f'<{data_file}>. At least one Mach input is required.' + ) + + # if propeller map requires helical mach, add a component to compute it + if mach_types == ['helical_mach']: + helical_mach = om.ExecComp( + 'helical_mach=(mach**2 + tip_mach**2)**0.5', + helical_mach={'val': np.ones(nn), 'units': 'unitless'}, + mach={'val': np.ones(nn), 'units': 'unitless'}, + tip_mach={'val': np.ones(nn), 'units': 'unitless'}, + ) + self.add_subsystem( + 'helical_mach_calc', helical_mach, promotes=['*', ('mach', Dynamic.Atmosphere.MACH)] + ) + + propeller_interp = build_data_interpolator( + interpolator_data=data, + interpolator_outputs=outputs, + num_nodes=nn, + ) + self.add_subsystem('propeller_map', propeller_interp, promotes=['*']) diff --git a/aviary/subsystems/propulsion/propeller/propeller_performance.py b/aviary/subsystems/propulsion/propeller/propeller_performance.py index 9d952eb60c..c6b34bbd24 100644 --- a/aviary/subsystems/propulsion/propeller/propeller_performance.py +++ b/aviary/subsystems/propulsion/propeller/propeller_performance.py @@ -1,8 +1,7 @@ import math -import openmdao.api as om import numpy as np - +import openmdao.api as om from openmdao.components.ks_comp import KSfunction from aviary.subsystems.propulsion.propeller.hamilton_standard import ( @@ -12,50 +11,17 @@ ) from aviary.subsystems.propulsion.propeller.propeller_map import PropellerMap from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.enums import OutMachType +from aviary.utils.functions import d_smooth_min, smooth_min +from aviary.utils.named_values import NamedValues +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output from aviary.variable_info.variables import Aircraft, Dynamic -def smooth_min(x, b, alpha=100.0): - """ - Smooth approximation of the min function using the log-sum-exp trick. - - Parameters: - x (float or array-like): First value. - b (float or array-like): Second value. - alpha (float): The smoothing factor. Higher values make it closer to the true minimum. Try between 75 and 275. - - Returns: - float or array-like: The smooth approximation of min(x, b). - """ - sum_log_exp = np.log(np.exp(np.multiply(-alpha, x)) + np.exp(np.multiply(-alpha, b))) - rv = -(1 / alpha) * sum_log_exp - return rv - - -def d_smooth_min(x, b, alpha=100.0): - """ - Derivative of function smooth_min(x) - - Parameters: - x (float or array-like): First value. - b (float or array-like): Second value. - alpha (float): The smoothing factor. Higher values make it closer to the true minimum. Try between 75 and 275. - - Returns: - float or array-like: The smooth approximation of derivative of min(x, b). - """ - d_sum_log_exp = np.exp(np.multiply(-alpha, x)) / \ - (np.exp(np.multiply(-alpha, x)) + np.exp(np.multiply(-alpha, b))) - return d_sum_log_exp - - class TipSpeed(om.ExplicitComponent): """ Compute current propeller speed and allowable max tip speed Maximum allowable tip speed is lower of helical tip Mach limited speed and - tip rotational speed limit + tip rotational speed limit. """ def initialize(self): @@ -69,33 +35,26 @@ def initialize(self): def setup(self): num_nodes = self.options['num_nodes'] + add_aviary_input(self, Dynamic.Mission.VELOCITY, val=np.zeros(num_nodes), units='ft/s') add_aviary_input( - self, Dynamic.Mission.VELOCITY, val=np.zeros(num_nodes), units='ft/s' - ) - add_aviary_input( - self, Dynamic.Mission.SPEED_OF_SOUND, val=np.zeros(num_nodes), units='ft/s' - ) - add_aviary_input( - self, Dynamic.Mission.RPM, val=np.zeros(num_nodes), units='rpm' - ) - add_aviary_input( - self, Aircraft.Engine.PROPELLER_TIP_MACH_MAX, val=1.0, units='unitless' + self, + Dynamic.Atmosphere.SPEED_OF_SOUND, + val=np.zeros(num_nodes), + units='ft/s', ) + add_aviary_input(self, Dynamic.Vehicle.Propulsion.RPM, val=np.zeros(num_nodes), units='rpm') + add_aviary_input(self, Aircraft.Engine.Propeller.TIP_MACH_MAX, val=1.0, units='unitless') - add_aviary_input( - self, Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, val=0.0, units='ft/s' - ) - add_aviary_input(self, Aircraft.Engine.PROPELLER_DIAMETER, val=0.0, units='ft') + add_aviary_input(self, Aircraft.Engine.Propeller.TIP_SPEED_MAX, val=0.0, units='ft/s') + add_aviary_input(self, Aircraft.Engine.Propeller.DIAMETER, val=0.0, units='ft') add_aviary_output( self, - Dynamic.Mission.PROPELLER_TIP_SPEED, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, val=np.zeros(num_nodes), units='ft/s', ) - self.add_output( - 'propeller_tip_speed_limit', val=np.zeros(num_nodes), units='ft/s' - ) + self.add_output('propeller_tip_speed_limit', val=np.zeros(num_nodes), units='ft/s') def setup_partials(self): num_nodes = self.options['num_nodes'] @@ -107,7 +66,7 @@ def setup_partials(self): 'propeller_tip_speed_limit', [ Dynamic.Mission.VELOCITY, - Dynamic.Mission.SPEED_OF_SOUND, + Dynamic.Atmosphere.SPEED_OF_SOUND, ], rows=r, cols=r, @@ -115,24 +74,24 @@ def setup_partials(self): self.declare_partials( 'propeller_tip_speed_limit', [ - Aircraft.Engine.PROPELLER_TIP_MACH_MAX, - Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, + Aircraft.Engine.Propeller.TIP_MACH_MAX, + Aircraft.Engine.Propeller.TIP_SPEED_MAX, ], ) self.declare_partials( - Dynamic.Mission.PROPELLER_TIP_SPEED, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, [ - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, ], rows=r, cols=r, ) self.declare_partials( - Dynamic.Mission.PROPELLER_TIP_SPEED, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, [ - Aircraft.Engine.PROPELLER_DIAMETER, + Aircraft.Engine.Propeller.DIAMETER, ], ) @@ -140,32 +99,32 @@ def compute(self, inputs, outputs): num_nodes = self.options['num_nodes'] velocity = inputs[Dynamic.Mission.VELOCITY] - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] - tip_mach_max = inputs[Aircraft.Engine.PROPELLER_TIP_MACH_MAX] - tip_speed_max = inputs[Aircraft.Engine.PROPELLER_TIP_SPEED_MAX] - rpm = inputs[Dynamic.Mission.RPM] - diam = inputs[Aircraft.Engine.PROPELLER_DIAMETER] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] + tip_mach_max = inputs[Aircraft.Engine.Propeller.TIP_MACH_MAX] + tip_speed_max = inputs[Aircraft.Engine.Propeller.TIP_SPEED_MAX] + rpm = inputs[Dynamic.Vehicle.Propulsion.RPM] + diam = inputs[Aircraft.Engine.Propeller.DIAMETER] tip_speed_mach_limit = ((sos * tip_mach_max) ** 2 - velocity**2) ** 0.5 - # use KSfunction for smooth derivitive across minimum + # use KSfunction for smooth derivative across minimum tip_speed_max_nn = np.tile(tip_speed_max, num_nodes) propeller_tip_speed_limit = -KSfunction.compute( -np.stack((tip_speed_max_nn, tip_speed_mach_limit), axis=1) ).flatten() propeller_tip_speed = rpm * diam * math.pi / 60 - outputs[Dynamic.Mission.PROPELLER_TIP_SPEED] = propeller_tip_speed + outputs[Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED] = propeller_tip_speed outputs['propeller_tip_speed_limit'] = propeller_tip_speed_limit def compute_partials(self, inputs, J): num_nodes = self.options['num_nodes'] velocity = inputs[Dynamic.Mission.VELOCITY] - sos = inputs[Dynamic.Mission.SPEED_OF_SOUND] - rpm = inputs[Dynamic.Mission.RPM] - tip_mach_max = inputs[Aircraft.Engine.PROPELLER_TIP_MACH_MAX] - tip_speed_max = inputs[Aircraft.Engine.PROPELLER_TIP_SPEED_MAX] - diam = inputs[Aircraft.Engine.PROPELLER_DIAMETER] + sos = inputs[Dynamic.Atmosphere.SPEED_OF_SOUND] + rpm = inputs[Dynamic.Vehicle.Propulsion.RPM] + tip_mach_max = inputs[Aircraft.Engine.Propeller.TIP_MACH_MAX] + tip_speed_max = inputs[Aircraft.Engine.Propeller.TIP_SPEED_MAX] + diam = inputs[Aircraft.Engine.Propeller.DIAMETER] tip_speed_max_nn = np.tile(tip_speed_max, num_nodes) @@ -185,423 +144,144 @@ def compute_partials(self, inputs, J): dspeed_dsm = dKS[:, 0] J['propeller_tip_speed_limit', Dynamic.Mission.VELOCITY] = dspeed_dv - J['propeller_tip_speed_limit', Dynamic.Mission.SPEED_OF_SOUND] = dspeed_ds - J['propeller_tip_speed_limit', Aircraft.Engine.PROPELLER_TIP_MACH_MAX] = ( - dspeed_dmm - ) - J['propeller_tip_speed_limit', Aircraft.Engine.PROPELLER_TIP_SPEED_MAX] = ( - dspeed_dsm - ) + J['propeller_tip_speed_limit', Dynamic.Atmosphere.SPEED_OF_SOUND] = dspeed_ds + J['propeller_tip_speed_limit', Aircraft.Engine.Propeller.TIP_MACH_MAX] = dspeed_dmm + J['propeller_tip_speed_limit', Aircraft.Engine.Propeller.TIP_SPEED_MAX] = dspeed_dsm - J[Dynamic.Mission.PROPELLER_TIP_SPEED, Dynamic.Mission.RPM] = ( + J[Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, Dynamic.Vehicle.Propulsion.RPM] = ( diam * math.pi / 60 ) - J[Dynamic.Mission.PROPELLER_TIP_SPEED, Aircraft.Engine.PROPELLER_DIAMETER] = ( + J[Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, Aircraft.Engine.Propeller.DIAMETER] = ( rpm * math.pi / 60 ) -class OutMachs(om.ExplicitComponent): - """ - This utility sets up relations among helical Mach, free stream Mach and propeller tip Mach. - helical_mach = sqrt(mach^2 + tip_mach^2). - It computes the value of one from the inputs of the other two. - """ - - def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare( - "output_mach_type", - default=OutMachType.HELICAL_MACH, - types=OutMachType, - desc="get one type of Mach number from the other two", - ) - - def setup(self): - nn = self.options["num_nodes"] - out_type = self.options["output_mach_type"] - arange = np.arange(self.options["num_nodes"]) - - if out_type is OutMachType.HELICAL_MACH: - self.add_input( - "mach", - val=np.zeros(nn), - units="unitless", - desc="Mach number", - ) - self.add_input( - "tip_mach", - val=np.zeros(nn), - units="unitless", - desc="tip Mach number of a blade", - ) - self.add_output( - "helical_mach", - val=np.zeros(nn), - units="unitless", - desc="helical Mach number", - ) - self.declare_partials( - "helical_mach", ["tip_mach", "mach"], rows=arange, cols=arange - ) - elif out_type is OutMachType.MACH: - self.add_input( - "tip_mach", - val=np.zeros(nn), - units="unitless", - desc="tip Mach number of a blade", - ) - self.add_input( - "helical_mach", - val=np.zeros(nn), - units="unitless", - desc="helical Mach number", - ) - self.add_output( - "mach", - val=np.zeros(nn), - units="unitless", - desc="Mach number", - ) - self.declare_partials( - "mach", ["tip_mach", "helical_mach"], rows=arange, cols=arange - ) - elif out_type is OutMachType.TIP_MACH: - self.add_input( - "mach", - val=np.zeros(nn), - units="unitless", - desc="Mach number", - ) - self.add_input( - "helical_mach", - val=np.zeros(nn), - units="unitless", - desc="helical Mach number", - ) - self.add_output( - "tip_mach", - val=np.zeros(nn), - units="unitless", - desc="tip Mach number of a blade", - ) - self.declare_partials( - "tip_mach", ["mach", "helical_mach"], rows=arange, cols=arange - ) - - def compute(self, inputs, outputs): - out_type = self.options["output_mach_type"] - - if out_type is OutMachType.HELICAL_MACH: - mach = inputs["mach"] - tip_mach = inputs["tip_mach"] - outputs["helical_mach"] = np.sqrt(mach * mach + tip_mach * tip_mach) - elif out_type is OutMachType.MACH: - tip_mach = inputs["tip_mach"] - helical_mach = inputs["helical_mach"] - outputs["mach"] = np.sqrt(helical_mach * helical_mach - tip_mach * tip_mach) - elif out_type is OutMachType.TIP_MACH: - mach = inputs["mach"] - helical_mach = inputs["helical_mach"] - outputs["tip_mach"] = np.sqrt(helical_mach * helical_mach - mach * mach) - - def compute_partials(self, inputs, J): - out_type = self.options["output_mach_type"] - - if out_type is OutMachType.HELICAL_MACH: - mach = inputs["mach"] - tip_mach = inputs["tip_mach"] - J["helical_mach", "mach"] = mach / np.sqrt( - mach * mach + tip_mach * tip_mach - ) - J["helical_mach", "tip_mach"] = tip_mach / np.sqrt( - mach * mach + tip_mach * tip_mach - ) - elif out_type is OutMachType.MACH: - tip_mach = inputs["tip_mach"] - helical_mach = inputs["helical_mach"] - J["mach", "helical_mach"] = helical_mach / np.sqrt( - helical_mach * helical_mach - tip_mach * tip_mach - ) - J["mach", "tip_mach"] = -tip_mach / np.sqrt( - helical_mach * helical_mach - tip_mach * tip_mach - ) - elif out_type is OutMachType.TIP_MACH: - mach = inputs["mach"] - helical_mach = inputs["helical_mach"] - J["tip_mach", "helical_mach"] = helical_mach / np.sqrt( - helical_mach * helical_mach - mach * mach - ) - J["tip_mach", "mach"] = -mach / np.sqrt( - helical_mach * helical_mach - mach * mach - ) - - class AreaSquareRatio(om.ExplicitComponent): - """ - Compute the area ratio nacelle and propeller with a maximum 0.5. - """ + """Compute the area ratio nacelle and propeller with a maximum 0.5.""" def initialize(self): - self.options.declare("num_nodes", types=int) + self.options.declare('num_nodes', types=int) self.options.declare('smooth_sqa', default=True, types=bool) - self.options.declare('alpha', default=100.0, types=float) - - def setup(self): - nn = self.options["num_nodes"] - arange = np.arange(self.options["num_nodes"]) - self.add_input("DiamNac", val=0.0, units='ft') - self.add_input("DiamProp", val=0.0, units='ft') - - self.add_output('sqa_array', val=np.zeros(nn), units='unitless') - - self.declare_partials("sqa_array", - [ - "DiamNac", - "DiamProp", - ], - rows=arange, cols=np.zeros(nn)) - - def compute(self, inputs, outputs): - nn = self.options["num_nodes"] - diamNac = inputs["DiamNac"] - diamProp = inputs["DiamProp"] - sqa = diamNac**2 / diamProp**2 - - smooth = self.options["smooth_sqa"] - if smooth: - alpha = self.options['alpha'] - sqa = smooth_min(sqa, 0.50, alpha) - else: - sqa = np.minimum(sqa, 0.50) - outputs["sqa_array"] = np.ones(nn) * sqa - - def compute_partials(self, inputs, partials): - diamNac = inputs["DiamNac"] - diamProp = inputs["DiamProp"] - sqa = diamNac**2 / diamProp**2 - - dSQA_dNacDiam = 2 * diamNac / diamProp**2 - dSQA_dPropDiam = -2 * diamNac**2 / diamProp**3 - - smooth = self.options["smooth_sqa"] - if smooth: - alpha = self.options['alpha'] - dSQA_dNacDiam = d_smooth_min(sqa, 0.50, alpha) * dSQA_dNacDiam - dSQA_dPropDiam = d_smooth_min(sqa, 0.50, alpha) * dSQA_dPropDiam - else: - dSQA_dNacDiam = np.piecewise( - sqa, [sqa < 0.5, sqa >= 0.5], [1, 0]) * dSQA_dNacDiam - dSQA_dPropDiam = np.piecewise( - sqa, [sqa < 0.5, sqa >= 0.5], [1, 0]) * dSQA_dPropDiam - partials['sqa_array', "DiamNac"] = dSQA_dNacDiam - partials['sqa_array', "DiamProp"] = dSQA_dPropDiam - - -class AdvanceRatio(om.ExplicitComponent): - """ - Compute the advance ratio jze with a maximum 5.0. - """ - - def initialize(self): - self.options.declare( - 'num_nodes', types=int, default=1, - desc='Number of nodes to be evaluated in the RHS') - self.options.declare('smooth_zje', default=True, types=bool) - self.options.declare('alpha', default=100.0, types=float) + self.options.declare('mu', default=100.0, types=float) def setup(self): nn = self.options['num_nodes'] - range = np.arange(nn) - self.add_input("vtas", val=np.zeros(nn), units='ft/s') - self.add_input("tipspd", val=np.zeros(nn), units='ft/s') - self.add_input("sqa_array", val=np.zeros(nn), units='unitless') - self.add_output("equiv_adv_ratio", val=np.zeros(nn), units='unitless') - - self.declare_partials("equiv_adv_ratio", - ["vtas", "tipspd"], - rows=range, cols=range) - - self.declare_partials("equiv_adv_ratio", - ["sqa_array"], - rows=range, cols=range) - - def compute(self, inputs, outputs): - nn = self.options['num_nodes'] - vtas = inputs["vtas"] - tipspd = inputs["tipspd"] - sqa_array = inputs["sqa_array"] - equiv_adv_ratio = (1.0 - 0.254 * sqa_array) * math.pi * vtas / tipspd - - smooth = self.options["smooth_zje"] - if smooth: - alpha = self.options['alpha'] - jze = smooth_min(equiv_adv_ratio, np.ones(nn) * 5.0, alpha) - else: - jze = np.minimum(equiv_adv_ratio, np.ones(nn) * 5.0) - outputs["equiv_adv_ratio"] = jze - - def compute_partials(self, inputs, partials): - nn = self.options['num_nodes'] - vtas = inputs["vtas"] - tipspd = inputs["tipspd"] - sqa_array = inputs["sqa_array"] - jze = (1.0 - 0.254 * sqa_array) * math.pi * vtas / tipspd - - djze_dsqa = -0.254 * math.pi * vtas / tipspd - djze_dvtas = (1.0 - 0.254 * sqa_array) * math.pi / tipspd - djze_dtipspd = -(1.0 - 0.254 * sqa_array) * math.pi * vtas / tipspd**2 - - smooth = self.options["smooth_zje"] - if smooth: - alpha = self.options["alpha"] - djze_dsqa = d_smooth_min(jze, np.ones(nn) * 5.0, alpha) * djze_dsqa - djze_dvtas = d_smooth_min(jze, np.ones(nn) * 5.0, alpha) * djze_dvtas - djze_dtipspd = d_smooth_min(jze, np.ones(nn) * 5.0, alpha) * djze_dtipspd - else: - djze_dsqa = np.piecewise(jze, [jze < 5, jze >= 5], [1, 0]) * djze_dsqa - djze_dvtas = np.piecewise(jze, [jze < 5, jze >= 5], [1, 0]) * djze_dvtas - djze_dtipspd = np.piecewise(jze, [jze < 5, jze >= 5], [1, 0]) * djze_dtipspd - partials["equiv_adv_ratio", "sqa_array"] = djze_dsqa - partials["equiv_adv_ratio", "vtas"] = djze_dvtas - partials["equiv_adv_ratio", "tipspd"] = djze_dtipspd - - -class AreaSquareRatio(om.ExplicitComponent): - """ - Compute the area ratio nacelle and propeller with a maximum 0.5. - """ - - def initialize(self): - self.options.declare("num_nodes", types=int) - self.options.declare('smooth_sqa', default=True, types=bool) - self.options.declare('alpha', default=100.0, types=float) - - def setup(self): - nn = self.options["num_nodes"] - arange = np.arange(self.options["num_nodes"]) - self.add_input("DiamNac", val=0.0, units='ft') - self.add_input("DiamProp", val=0.0, units='ft') + arange = np.arange(self.options['num_nodes']) + self.add_input('DiamNac', val=0.0, units='ft') + self.add_input('DiamProp', val=0.0, units='ft') self.add_output('sqa_array', val=np.zeros(nn), units='unitless') - self.declare_partials("sqa_array", - [ - "DiamNac", - "DiamProp", - ], - rows=arange, cols=np.zeros(nn)) + self.declare_partials( + 'sqa_array', + [ + 'DiamNac', + 'DiamProp', + ], + rows=arange, + cols=np.zeros(nn), + ) def compute(self, inputs, outputs): - nn = self.options["num_nodes"] - diamNac = inputs["DiamNac"] - diamProp = inputs["DiamProp"] + nn = self.options['num_nodes'] + diamNac = inputs['DiamNac'] + diamProp = inputs['DiamProp'] sqa = diamNac**2 / diamProp**2 - smooth = self.options["smooth_sqa"] + smooth = self.options['smooth_sqa'] if smooth: - alpha = self.options['alpha'] - sqa = smooth_min(sqa, 0.50, alpha) + mu = self.options['mu'] + sqa = smooth_min(sqa, 0.50, mu) else: sqa = np.minimum(sqa, 0.50) - outputs["sqa_array"] = np.ones(nn) * sqa + outputs['sqa_array'] = np.ones(nn) * sqa def compute_partials(self, inputs, partials): - diamNac = inputs["DiamNac"] - diamProp = inputs["DiamProp"] + diamNac = inputs['DiamNac'] + diamProp = inputs['DiamProp'] sqa = diamNac**2 / diamProp**2 dSQA_dNacDiam = 2 * diamNac / diamProp**2 dSQA_dPropDiam = -2 * diamNac**2 / diamProp**3 - smooth = self.options["smooth_sqa"] + smooth = self.options['smooth_sqa'] if smooth: - alpha = self.options['alpha'] - dSQA_dNacDiam = d_smooth_min(sqa, 0.50, alpha) * dSQA_dNacDiam - dSQA_dPropDiam = d_smooth_min(sqa, 0.50, alpha) * dSQA_dPropDiam + mu = self.options['mu'] + dSQA_dNacDiam = d_smooth_min(sqa, 0.50, mu) * dSQA_dNacDiam + dSQA_dPropDiam = d_smooth_min(sqa, 0.50, mu) * dSQA_dPropDiam else: - dSQA_dNacDiam = np.piecewise( - sqa, [sqa < 0.5, sqa >= 0.5], [1, 0]) * dSQA_dNacDiam - dSQA_dPropDiam = np.piecewise( - sqa, [sqa < 0.5, sqa >= 0.5], [1, 0]) * dSQA_dPropDiam - partials['sqa_array', "DiamNac"] = dSQA_dNacDiam - partials['sqa_array', "DiamProp"] = dSQA_dPropDiam + dSQA_dNacDiam = np.piecewise(sqa, [sqa < 0.5, sqa >= 0.5], [1, 0]) * dSQA_dNacDiam + dSQA_dPropDiam = np.piecewise(sqa, [sqa < 0.5, sqa >= 0.5], [1, 0]) * dSQA_dPropDiam + partials['sqa_array', 'DiamNac'] = dSQA_dNacDiam + partials['sqa_array', 'DiamProp'] = dSQA_dPropDiam class AdvanceRatio(om.ExplicitComponent): - """ - Compute the advance ratio jze with a maximum 5.0. - """ + """Compute the advance ratio jze with a maximum 5.0.""" def initialize(self): self.options.declare( - 'num_nodes', types=int, default=1, - desc='Number of nodes to be evaluated in the RHS') + 'num_nodes', types=int, default=1, desc='Number of nodes to be evaluated in the RHS' + ) self.options.declare('smooth_zje', default=True, types=bool) - self.options.declare('alpha', default=100.0, types=float) + self.options.declare('mu', default=100.0, types=float) def setup(self): nn = self.options['num_nodes'] range = np.arange(nn) - self.add_input("vtas", val=np.zeros(nn), units='ft/s') - self.add_input("tipspd", val=np.zeros(nn), units='ft/s') - self.add_input("sqa_array", val=np.zeros(nn), units='unitless') - self.add_output("equiv_adv_ratio", val=np.zeros(nn), units='unitless') + self.add_input('vtas', val=np.zeros(nn), units='ft/s') + self.add_input('tipspd', val=np.zeros(nn), units='ft/s') + self.add_input('sqa_array', val=np.zeros(nn), units='unitless') + self.add_output('equiv_adv_ratio', val=np.zeros(nn), units='unitless') - self.declare_partials("equiv_adv_ratio", - ["vtas", "tipspd"], - rows=range, cols=range) + self.declare_partials('equiv_adv_ratio', ['vtas', 'tipspd'], rows=range, cols=range) - self.declare_partials("equiv_adv_ratio", - ["sqa_array"], - rows=range, cols=range) + self.declare_partials('equiv_adv_ratio', ['sqa_array'], rows=range, cols=range) def compute(self, inputs, outputs): nn = self.options['num_nodes'] - vtas = inputs["vtas"] - tipspd = inputs["tipspd"] - sqa_array = inputs["sqa_array"] + vtas = inputs['vtas'] + tipspd = inputs['tipspd'] + sqa_array = inputs['sqa_array'] equiv_adv_ratio = (1.0 - 0.254 * sqa_array) * math.pi * vtas / tipspd - smooth = self.options["smooth_zje"] + smooth = self.options['smooth_zje'] if smooth: - alpha = self.options['alpha'] - jze = smooth_min(equiv_adv_ratio, np.ones(nn) * 5.0, alpha) + mu = self.options['mu'] + jze = smooth_min(equiv_adv_ratio, np.ones(nn) * 5.0, mu) else: jze = np.minimum(equiv_adv_ratio, np.ones(nn) * 5.0) - outputs["equiv_adv_ratio"] = jze + outputs['equiv_adv_ratio'] = jze def compute_partials(self, inputs, partials): nn = self.options['num_nodes'] - vtas = inputs["vtas"] - tipspd = inputs["tipspd"] - sqa_array = inputs["sqa_array"] + vtas = inputs['vtas'] + tipspd = inputs['tipspd'] + sqa_array = inputs['sqa_array'] jze = (1.0 - 0.254 * sqa_array) * math.pi * vtas / tipspd djze_dsqa = -0.254 * math.pi * vtas / tipspd djze_dvtas = (1.0 - 0.254 * sqa_array) * math.pi / tipspd djze_dtipspd = -(1.0 - 0.254 * sqa_array) * math.pi * vtas / tipspd**2 - smooth = self.options["smooth_zje"] + smooth = self.options['smooth_zje'] if smooth: - alpha = self.options["alpha"] - djze_dsqa = d_smooth_min(jze, np.ones(nn) * 5.0, alpha) * djze_dsqa - djze_dvtas = d_smooth_min(jze, np.ones(nn) * 5.0, alpha) * djze_dvtas - djze_dtipspd = d_smooth_min(jze, np.ones(nn) * 5.0, alpha) * djze_dtipspd + mu = self.options['mu'] + djze_dsqa = d_smooth_min(jze, np.ones(nn) * 5.0, mu) * djze_dsqa + djze_dvtas = d_smooth_min(jze, np.ones(nn) * 5.0, mu) * djze_dvtas + djze_dtipspd = d_smooth_min(jze, np.ones(nn) * 5.0, mu) * djze_dtipspd else: djze_dsqa = np.piecewise(jze, [jze < 5, jze >= 5], [1, 0]) * djze_dsqa djze_dvtas = np.piecewise(jze, [jze < 5, jze >= 5], [1, 0]) * djze_dvtas djze_dtipspd = np.piecewise(jze, [jze < 5, jze >= 5], [1, 0]) * djze_dtipspd - partials["equiv_adv_ratio", "sqa_array"] = djze_dsqa - partials["equiv_adv_ratio", "vtas"] = djze_dvtas - partials["equiv_adv_ratio", "tipspd"] = djze_dtipspd + partials['equiv_adv_ratio', 'sqa_array'] = djze_dsqa + partials['equiv_adv_ratio', 'vtas'] = djze_dvtas + partials['equiv_adv_ratio', 'tipspd'] = djze_dtipspd class InstallLoss(om.Group): - """ - Compute installation loss - """ + """Compute installation loss.""" def initialize(self): self.options.declare( @@ -610,62 +290,60 @@ def initialize(self): default=1, desc='Number of nodes to be evaluated in the RHS', ) - self.options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - ) def setup(self): nn = self.options['num_nodes'] self.add_subsystem( name='sqa_comp', subsys=AreaSquareRatio(num_nodes=nn, smooth_sqa=True), - promotes_inputs=[("DiamNac", Aircraft.Nacelle.AVG_DIAMETER), - ("DiamProp", Aircraft.Engine.PROPELLER_DIAMETER)], - promotes_outputs=["sqa_array"], + promotes_inputs=[ + ('DiamNac', Aircraft.Nacelle.AVG_DIAMETER), + ('DiamProp', Aircraft.Engine.Propeller.DIAMETER), + ], + promotes_outputs=['sqa_array'], ) self.add_subsystem( name='zje_comp', subsys=AdvanceRatio(num_nodes=nn, smooth_zje=True), - promotes_inputs=["sqa_array", ("vtas", Dynamic.Mission.VELOCITY), - ("tipspd", Dynamic.Mission.PROPELLER_TIP_SPEED)], - promotes_outputs=["equiv_adv_ratio"], + promotes_inputs=[ + 'sqa_array', + ('vtas', Dynamic.Mission.VELOCITY), + ('tipspd', Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED), + ], + promotes_outputs=['equiv_adv_ratio'], ) self.blockage_factor_interp = self.add_subsystem( - "blockage_factor_interp", - om.MetaModelStructuredComp( - method="2D-slinear", extrapolate=True, vec_size=nn - ), - promotes_inputs=["sqa_array", "equiv_adv_ratio"], + 'blockage_factor_interp', + om.MetaModelStructuredComp(method='2D-slinear', extrapolate=True, vec_size=nn), + promotes_inputs=['sqa_array', 'equiv_adv_ratio'], promotes_outputs=[ - "blockage_factor", + 'blockage_factor', ], ) self.blockage_factor_interp.add_input( - "sqa_array", + 'sqa_array', 0.0, training_data=[0.00, 0.04, 0.08, 0.12, 0.16, 0.20, 0.24, 0.28, 0.32, 0.50], - units="unitless", - desc="square of DiamNac/DiamProp", + units='unitless', + desc='square of DiamNac/DiamProp', ) self.blockage_factor_interp.add_input( - "equiv_adv_ratio", + 'equiv_adv_ratio', 0.0, training_data=[0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0], - units="unitless", - desc="square of DiamNac vs DiamProp", + units='unitless', + desc='square of DiamNac vs DiamProp', ) self.blockage_factor_interp.add_output( - "blockage_factor", + 'blockage_factor', 0.765, - units="unitless", - desc="blockage factor", + units='unitless', + desc='blockage factor', training_data=np.array( [ [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], @@ -690,8 +368,8 @@ def setup(self): install_loss_factor={'units': 'unitless', 'val': np.zeros(nn)}, has_diag_partials=True, ), - promotes_inputs=["blockage_factor"], - promotes_outputs=["install_loss_factor"], + promotes_inputs=['blockage_factor'], + promotes_outputs=['install_loss_factor'], ) @@ -699,7 +377,7 @@ class PropellerPerformance(om.Group): """ Computation of propeller thrust coefficient based on the Hamilton Standard model or a user provided propeller map. Note that a propeller map allows either the helical Mach number or - free stream Mach number as input. This infomation will be detected automatically when the + free stream Mach number as input. This information will be detected automatically when the propeller map is loaded into memory. The installation loss factor is either a user input or computed internally. """ @@ -718,29 +396,45 @@ def initialize(self): desc='collection of Aircraft/Mission specific options', ) + self.options.declare( + 'propeller_data', + types=NamedValues, + default=None, + desc='propeller performance data to be used instead of data file (optional)', + ) + + add_aviary_option(self, Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS) + add_aviary_option(self, Aircraft.Engine.Propeller.DATA_FILE) + def setup(self): options = self.options nn = options['num_nodes'] aviary_options = options['aviary_options'] + data = options['propeller_data'] # TODO options are lists here when using full Aviary problem - need # further investigation - compute_installation_loss = aviary_options.get_val( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS - ) + compute_installation_loss = options[Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS] + if isinstance(compute_installation_loss, (list, np.ndarray)): compute_installation_loss = compute_installation_loss[0] - use_propeller_map = aviary_options.get_val(Aircraft.Engine.USE_PROPELLER_MAP) - if isinstance(use_propeller_map, (list, np.ndarray)): - use_propeller_map = use_propeller_map[0] + if data is None: + try: + prop_file_path = aviary_options.get_val(Aircraft.Engine.Propeller.DATA_FILE) + except KeyError: + use_propeller_map = False + else: + use_propeller_map = True + if isinstance(prop_file_path, (list, np.ndarray)): + prop_file_path = prop_file_path[0] + else: + use_propeller_map = True # compute the propeller tip speed based on the input RPM and diameter of the propeller # NOTE allows for violation of tip speed limits # TODO provide warning to user when max tip speeds are violated - self.add_subsystem( - 'compute_tip_speed', subsys=TipSpeed(num_nodes=nn), promotes=['*'] - ) + self.add_subsystem('compute_tip_speed', subsys=TipSpeed(num_nodes=nn), promotes=['*']) if compute_installation_loss: self.add_subsystem( @@ -748,74 +442,43 @@ def setup(self): subsys=InstallLoss(num_nodes=nn), promotes_inputs=[ Aircraft.Nacelle.AVG_DIAMETER, - Aircraft.Engine.PROPELLER_DIAMETER, + Aircraft.Engine.Propeller.DIAMETER, Dynamic.Mission.VELOCITY, - Dynamic.Mission.PROPELLER_TIP_SPEED, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, ], promotes_outputs=['install_loss_factor'], ) else: - self.set_input_defaults( - 'install_loss_factor', val=np.ones(nn), units="unitless" - ) + self.set_input_defaults('install_loss_factor', val=np.ones(nn), units='unitless') self.add_subsystem( name='pre_hamilton_standard', subsys=PreHamiltonStandard(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.DENSITY, - Dynamic.Mission.SPEED_OF_SOUND, + Dynamic.Atmosphere.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, Dynamic.Mission.VELOCITY, - Dynamic.Mission.PROPELLER_TIP_SPEED, - Aircraft.Engine.PROPELLER_DIAMETER, - Dynamic.Mission.SHAFT_POWER, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + Aircraft.Engine.Propeller.DIAMETER, + Dynamic.Vehicle.Propulsion.SHAFT_POWER, ], promotes_outputs=[ - "power_coefficient", - "advance_ratio", - "tip_mach", + 'power_coefficient', + 'advance_ratio', + 'tip_mach', # "density_ratio", ], ) if use_propeller_map: - prop_model = PropellerMap('prop', aviary_options) - prop_file_path = aviary_options.get_val(Aircraft.Engine.PROPELLER_DATA_FILE) - mach_type = prop_model.read_and_set_mach_type(prop_file_path) - if mach_type == OutMachType.HELICAL_MACH: - self.add_subsystem( - name='selectedMach', - subsys=OutMachs( - num_nodes=nn, output_mach_type=OutMachType.HELICAL_MACH - ), - promotes_inputs=[("mach", Dynamic.Mission.MACH), "tip_mach"], - promotes_outputs=[("helical_mach", "selected_mach")], - ) - else: - self.add_subsystem( - name='selectedMach', - subsys=om.ExecComp( - 'selected_mach = mach', - mach={'units': 'unitless', 'shape': nn}, - selected_mach={'units': 'unitless', 'shape': nn}, - has_diag_partials=True, - ), - promotes_inputs=[ - ("mach", Dynamic.Mission.MACH), - ], - promotes_outputs=["selected_mach"], - ) - propeller = prop_model.build_propeller_interpolator(nn, aviary_options) + propeller_map = PropellerMap(num_nodes=nn, propeller_data=data) + self.add_subsystem( name='propeller_map', - subsys=propeller, - promotes_inputs=[ - "selected_mach", - "power_coefficient", - "advance_ratio", - ], + subsys=propeller_map, + promotes_inputs=['*'], promotes_outputs=[ - "thrust_coefficient", + 'thrust_coefficient', ], ) @@ -826,18 +489,18 @@ def setup(self): else: self.add_subsystem( name='hamilton_standard', - subsys=HamiltonStandard(num_nodes=nn, aviary_options=aviary_options), + subsys=HamiltonStandard(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.MACH, - "power_coefficient", - "advance_ratio", - "tip_mach", - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, + Dynamic.Atmosphere.MACH, + 'power_coefficient', + 'advance_ratio', + 'tip_mach', + Aircraft.Engine.Propeller.ACTIVITY_FACTOR, + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, ], promotes_outputs=[ - "thrust_coefficient", - "comp_tip_loss_factor", + 'thrust_coefficient', + 'comp_tip_loss_factor', ], ) @@ -845,19 +508,19 @@ def setup(self): name='post_hamilton_standard', subsys=PostHamiltonStandard(num_nodes=nn), promotes_inputs=[ - "thrust_coefficient", - "comp_tip_loss_factor", - Dynamic.Mission.PROPELLER_TIP_SPEED, - Aircraft.Engine.PROPELLER_DIAMETER, - Dynamic.Mission.DENSITY, + 'thrust_coefficient', + 'comp_tip_loss_factor', + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + Aircraft.Engine.Propeller.DIAMETER, + Dynamic.Atmosphere.DENSITY, 'install_loss_factor', - "advance_ratio", - "power_coefficient", + 'advance_ratio', + 'power_coefficient', ], promotes_outputs=[ - "thrust_coefficient_comp_loss", - Dynamic.Mission.THRUST, - "propeller_efficiency", - "install_efficiency", + 'thrust_coefficient_comp_loss', + Dynamic.Vehicle.Propulsion.THRUST, + 'propeller_efficiency', + 'install_efficiency', ], ) diff --git a/aviary/subsystems/propulsion/propeller/test/test_hamilton_standard.py b/aviary/subsystems/propulsion/propeller/test/test_hamilton_standard.py new file mode 100644 index 0000000000..cfa721d7d2 --- /dev/null +++ b/aviary/subsystems/propulsion/propeller/test/test_hamilton_standard.py @@ -0,0 +1,205 @@ +import unittest + +import numpy as np +import openmdao.api as om +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal + +from aviary.constants import RHO_SEA_LEVEL_ENGLISH +from aviary.subsystems.propulsion.propeller.hamilton_standard import ( + HamiltonStandard, + PostHamiltonStandard, + PreHamiltonStandard, +) +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.options import get_option_defaults +from aviary.variable_info.variables import Aircraft, Dynamic + + +class PreHamiltonStandardTest(unittest.TestCase): + """Test computation in PreHamiltonStandard class.""" + + def setUp(self): + prob = om.Problem() + + num_nodes = 3 + + prob.model.add_subsystem( + 'prehs', + PreHamiltonStandard(num_nodes=num_nodes), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + prob.setup() + self.prob = prob + + def test_preHS(self): + prob = self.prob + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 10, units='ft') + prob.set_val( + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + [700.0, 750.0, 800.0], + units='ft/s', + ) + prob.set_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, [1850.0, 1850.0, 900.0], units='hp') + prob.set_val( + Dynamic.Atmosphere.DENSITY, + [0.00237717, 0.00237717, 0.00106526], + units='slug/ft**3', + ) + prob.set_val(Dynamic.Mission.VELOCITY, [100.0, 100, 100], units='ft/s') + prob.set_val( + Dynamic.Atmosphere.SPEED_OF_SOUND, + [661.46474547, 661.46474547, 601.93668333], + units='knot', + ) + + prob.run_model() + + tol = 5e-4 + assert_near_equal( + prob.get_val('power_coefficient'), [0.3871, 0.3147, 0.2815], tolerance=tol + ) + assert_near_equal( + prob.get_val('advance_ratio'), + [0.44879895, 0.41887902, 0.39269908], + tolerance=tol, + ) + assert_near_equal( + prob.get_val('tip_mach'), [0.6270004, 0.67178614, 0.78743671], tolerance=tol + ) + + partial_data = prob.check_partials( + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + minimum_step=1e-12, + abs_err_tol=5.0e-4, + rel_err_tol=5.0e-5, + ) + assert_check_partials(partial_data, atol=0.0003, rtol=7e-7) + + +class HamiltonStandardTest(unittest.TestCase): + """Test computation in HamiltonStandard class.""" + + def setUp(self): + options = get_option_defaults() + options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=4, units='unitless') + + prob = om.Problem() + + num_nodes = 3 + + prob.model.add_subsystem( + 'hs', + HamiltonStandard(num_nodes=num_nodes), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + setup_model_options(prob, options) + + prob.setup() + self.prob = prob + + def test_HS(self): + prob = self.prob + prob.set_val('power_coefficient', [0.2352, 0.2352, 0.2553], units='unitless') + prob.set_val('advance_ratio', [0.0066, 0.8295, 1.9908], units='unitless') + prob.set_val(Dynamic.Atmosphere.MACH, [0.001509, 0.1887, 0.4976], units='unitless') + prob.set_val('tip_mach', [1.2094, 1.2094, 1.3290], units='unitless') + prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 114.0, units='unitless') + prob.set_val(Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless') + + prob.run_model() + + tol = 5e-4 + assert_near_equal( + prob.get_val('thrust_coefficient'), [0.2763, 0.2052, 0.1158], tolerance=tol + ) + assert_near_equal(prob.get_val('comp_tip_loss_factor'), [1.0, 1.0, 0.9818], tolerance=tol) + + partial_data = prob.check_partials( + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='fd', + minimum_step=1e-12, + abs_err_tol=5.0e-4, + rel_err_tol=5.0e-5, + ) + assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) + + +class PostHamiltonStandardTest(unittest.TestCase): + """Test computation in PostHamiltonStandard class.""" + + def setUp(self): + prob = om.Problem() + + num_nodes = 3 + + prob.model.add_subsystem( + 'posths', + PostHamiltonStandard(num_nodes=num_nodes), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + prob.setup() + self.prob = prob + + def test_postHS(self): + prob = self.prob + prob.set_val('power_coefficient', [0.3871, 0.3147, 0.2815], units='unitless') + prob.set_val('advance_ratio', [0.4494, 0.4194, 0.3932], units='unitless') + prob.set_val( + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, [700.0, 750.0, 800.0], units='ft/s' + ) + prob.set_val( + Dynamic.Atmosphere.DENSITY, + np.array([1.0001, 1.0001, 0.4482]) * RHO_SEA_LEVEL_ENGLISH, + units='slug/ft**3', + ) + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 10.0, units='ft') + prob.set_val('thrust_coefficient', [0.2765, 0.2052, 0.1158], units='unitless') + prob.set_val('install_loss_factor', [0.0133, 0.0200, 0.0325], units='unitless') + prob.set_val('comp_tip_loss_factor', [1.0, 1.0, 0.9819], units='unitless') + + prob.run_model() + + tol = 5e-4 + assert_near_equal( + prob.get_val('thrust_coefficient_comp_loss'), [0.2765, 0.2052, 0.1137], tolerance=tol + ) + assert_near_equal( + prob.get_val(Dynamic.Vehicle.Propulsion.THRUST), + [3218.9508, 2723.7294, 759.7543], + tolerance=tol, + ) + assert_near_equal( + prob.get_val('propeller_efficiency'), [0.321, 0.2735, 0.1588], tolerance=tol + ) + assert_near_equal( + prob.get_val('install_efficiency'), [0.3167, 0.2680, 0.15378], tolerance=tol + ) + + partial_data = prob.check_partials( + out_stream=None, + compact_print=True, + show_only_incorrect=True, + form='central', + method='cs', + ) + assert_check_partials(partial_data, atol=1e-7, rtol=1e-7) + + +if __name__ == '__main__': + unittest.main() + # test = HamiltonStandardTest() + # test.setUp() + # test.test_HS() diff --git a/aviary/subsystems/propulsion/propeller/test/test_propeller_map.py b/aviary/subsystems/propulsion/propeller/test/test_propeller_map.py new file mode 100644 index 0000000000..e3549a9114 --- /dev/null +++ b/aviary/subsystems/propulsion/propeller/test/test_propeller_map.py @@ -0,0 +1,63 @@ +import unittest + +import openmdao.api as om +from openmdao.utils.assert_utils import assert_near_equal + +from aviary.subsystems.propulsion.propeller.propeller_map import PropellerMap +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft +from aviary.utils.aviary_values import AviaryValues + + +class PropellerMapTest(unittest.TestCase): + """ + Test propeller map using OpenMDAO interpolator to make sure + it provides correct error and gets correct Mach type. + """ + + def test_general_aviation(self): + # The case when prop_type is helical_mach. + tol = 0.005 + aviary_options = AviaryValues() + prop_file_path = 'models/engines/propellers/general_aviation.csv' + aviary_options.set_val(Aircraft.Engine.Propeller.DATA_FILE, prop_file_path) + + prob = om.Problem() + prob.model.add_subsystem('propeller_map', PropellerMap(), promotes=['*']) + setup_model_options(prob, aviary_options) + prob.setup() + prob.set_val('mach', 0.56568) # targeting helical mach of 0.8 + prob.set_val('tip_mach', 0.56568) + prob.set_val('power_coefficient', 0.1) + prob.set_val('advance_ratio', 0.75) + prob.run_model() + + # Mach, CP, J from general_aviation, expected CT: 0.0934 + ct = prob.get_val('thrust_coefficient') + assert_near_equal(ct, 0.0934, tolerance=tol) + + def test_propfan(self): + # The case when prop_type is mach. + tol = 0.005 + aviary_options = AviaryValues() + prop_file_path = 'models/engines/propellers/PropFan.csv' + aviary_options.set_val( + Aircraft.Engine.Propeller.DATA_FILE, val=prop_file_path, units='unitless' + ) + + prob = om.Problem() + prob.model.add_subsystem('propeller_map', PropellerMap(), promotes=['*']) + setup_model_options(prob, aviary_options) + prob.setup() + prob.set_val('mach', 0.25) + prob.set_val('power_coefficient', 0.0465) + prob.set_val('advance_ratio', 0.2) + prob.run_model() + + # Mach, CP, J from PropFan, expected CT: 0.095985 + ct = prob.get_val('thrust_coefficient') + assert_near_equal(ct, 0.095985, tolerance=tol) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/propulsion/test/test_propeller_performance.py b/aviary/subsystems/propulsion/propeller/test/test_propeller_performance.py similarity index 56% rename from aviary/subsystems/propulsion/test/test_propeller_performance.py rename to aviary/subsystems/propulsion/propeller/test/test_propeller_performance.py index ecd6d6c3f5..0bc279d680 100644 --- a/aviary/subsystems/propulsion/test/test_propeller_performance.py +++ b/aviary/subsystems/propulsion/propeller/test/test_propeller_performance.py @@ -3,20 +3,21 @@ import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from openmdao.core.constants import _DEFAULT_OUT_STREAM, _UNDEFINED from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.subsystems.propulsion.propeller.propeller_performance import ( - OutMachs, PropellerPerformance, TipSpeed, AreaSquareRatio, AdvanceRatio + AdvanceRatio, + AreaSquareRatio, + PropellerPerformance, + TipSpeed, ) -from aviary.variable_info.enums import OutMachType -from aviary.variable_info.variables import Aircraft, Dynamic, Settings +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Dynamic +from aviary.variable_info.variables import Aircraft, Dynamic, Settings # Setting up truth values from GASP (The first 12 are actual truth values, the rest are intelligent guesses) # test values now are slightly different due to setup - max tip speed was limited to test -# that it is being properly constrained (and that derivitives work across constraints) +# that it is being properly constrained (and that derivatives work across constraints) # CT = np.array([0.27651, 0.20518, 0.13093, 0.10236, 0.10236, 0.19331, # 0.10189, 0.10189, 0.18123, 0.08523, 0.06463, 0.02800]) CT = np.array( @@ -42,8 +43,26 @@ ] ) XFT = np.array( - [1.0, 1.0, 0.9976, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 1.0, 1.0, 0.9976, 1.0, 1.0, 1.0,] + [ + 1.0, + 1.0, + 0.9976, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 0.9976, + 1.0, + 1.0, + 1.0, + ] ) # CTX = np.array([0.27651, 0.20518, 0.13062, 0.10236, 0.10236, 0.19331, # 0.10189, 0.10189, 0.18123, 0.08523, 0.06463, 0.02800]) @@ -166,20 +185,17 @@ class PropellerPerformanceTest(unittest.TestCase): - """ - Test computation of propeller performance test using Hamilton Standard model. - """ + """Test computation of propeller performance test using Hamilton Standard model.""" def setUp(self): options = get_option_defaults() options.set_val( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=True, units='unitless', ) - options.set_val(Aircraft.Engine.NUM_PROPELLER_BLADES, val=4, units='unitless') + options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=4, units='unitless') options.set_val(Aircraft.Engine.GENERATE_FLIGHT_IDLE, False) - options.set_val(Aircraft.Engine.USE_PROPELLER_MAP, False) options.set_val(Settings.VERBOSITY, 0) prob = om.Problem() @@ -196,32 +212,31 @@ def setUp(self): 'pp', PropellerPerformance(num_nodes=num_nodes, aviary_options=options), promotes_inputs=['*'], - promotes_outputs=["*"], + promotes_outputs=['*'], ) - pp.set_input_defaults(Aircraft.Engine.PROPELLER_DIAMETER, 10, units="ft") - pp.set_input_defaults( - Dynamic.Mission.PROPELLER_TIP_SPEED, 800 * np.ones(num_nodes), units="ft/s" - ) + pp.set_input_defaults(Aircraft.Engine.Propeller.DIAMETER, 10, units='ft') pp.set_input_defaults( - Dynamic.Mission.VELOCITY, 100.0 * np.ones(num_nodes), units="knot" + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, + 800 * np.ones(num_nodes), + units='ft/s', ) + pp.set_input_defaults(Dynamic.Mission.VELOCITY, 100.0 * np.ones(num_nodes), units='knot') num_blades = 4 + options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=num_blades, units='unitless') options.set_val( - Aircraft.Engine.NUM_PROPELLER_BLADES, val=num_blades, units='unitless' - ) - options.set_val( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=True, units='unitless', ) + + setup_model_options(prob, options) + prob.setup() - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10.5, units="ft") - prob.set_val(Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 114.0, units="unitless") - prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, 0.5, units="unitless" - ) + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 10.5, units='ft') + prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 114.0, units='unitless') + prob.set_val(Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless') prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, 2.8875, units='ft') self.prob = prob @@ -232,7 +247,7 @@ def compare_results(self, case_idx_begin, case_idx_end): cthr = p.get_val('thrust_coefficient') ctlf = p.get_val('comp_tip_loss_factor') tccl = p.get_val('thrust_coefficient_comp_loss') - thrt = p.get_val(Dynamic.Mission.THRUST) + thrt = p.get_val(Dynamic.Vehicle.Propulsion.THRUST) peff = p.get_val('propeller_efficiency') lfac = p.get_val('install_loss_factor') ieff = p.get_val('install_efficiency') @@ -252,16 +267,16 @@ def compare_results(self, case_idx_begin, case_idx_end): def test_case_0_1_2(self): # Case 0, 1, 2, to test installation loss factor computation. prob = self.prob - prob.set_val(Dynamic.Mission.ALTITUDE, [0.0, 0.0, 25000.0], units="ft") - prob.set_val(Dynamic.Mission.VELOCITY, [0.10, 125.0, 300.0], units="knot") + prob.set_val(Dynamic.Mission.ALTITUDE, [0.0, 0.0, 25000.0], units='ft') + prob.set_val(Dynamic.Mission.VELOCITY, [0.10, 125.0, 300.0], units='knot') prob.set_val( - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, [1455.13090827, 1455.13090827, 1455.13090827], units='rpm', ) - prob.set_val(Dynamic.Mission.SHAFT_POWER, [1850.0, 1850.0, 900.0], units="hp") - prob.set_val(Aircraft.Engine.PROPELLER_TIP_MACH_MAX, 1.0, units="unitless") - prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 800.0, units="ft/s") + prob.set_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, [1850.0, 1850.0, 900.0], units='hp') + prob.set_val(Aircraft.Engine.Propeller.TIP_MACH_MAX, 1.0, units='unitless') + prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 800.0, units='ft/s') prob.run_model() self.compare_results(case_idx_begin=0, case_idx_end=2) @@ -271,11 +286,11 @@ def test_case_0_1_2(self): compact_print=True, show_only_incorrect=True, form='central', - method="fd", + method='fd', minimum_step=1e-12, abs_err_tol=5.0e-4, rel_err_tol=5.0e-5, - excludes=["*atmosphere*"], + excludes=['*atmosphere*'], ) assert_check_partials(partial_data, atol=5e-4, rtol=1e-4) @@ -285,26 +300,27 @@ def test_case_3_4_5(self): options = self.options options.set_val( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=False, units='unitless', ) + + setup_model_options(prob, options) + prob.setup() - prob.set_val('install_loss_factor', [0.0, 0.05, 0.05], units="unitless") - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 12.0, units="ft") - prob.set_val(Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 150.0, units="unitless") - prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, 0.5, units="unitless" - ) - prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 0.0], units="ft") - prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 50.0], units="knot") - prob.set_val(Dynamic.Mission.SHAFT_POWER, [1000.0, 1000.0, 1250.0], units="hp") + prob.set_val('install_loss_factor', [0.0, 0.05, 0.05], units='unitless') + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 12.0, units='ft') + prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 150.0, units='unitless') + prob.set_val(Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless') + prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 0.0], units='ft') + prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 50.0], units='knot') + prob.set_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, [1000.0, 1000.0, 1250.0], units='hp') prob.set_val( - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, [1225.02, 1225.02, 1225.02], units='rpm', ) - prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 769.70, units="ft/s") + prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 769.70, units='ft/s') prob.run_model() @@ -315,11 +331,11 @@ def test_case_3_4_5(self): compact_print=True, show_only_incorrect=True, form='central', - method="fd", + method='fd', minimum_step=1e-12, abs_err_tol=5.0e-4, rel_err_tol=5.0e-5, - excludes=["*atmosphere*"], + excludes=['*atmosphere*'], ) assert_check_partials(partial_data, atol=1.5e-4, rtol=1e-4) @@ -329,30 +345,29 @@ def test_case_6_7_8(self): options = self.options num_blades = 3 + options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=num_blades, units='unitless') options.set_val( - Aircraft.Engine.NUM_PROPELLER_BLADES, val=num_blades, units='unitless' - ) - options.set_val( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=False, units='unitless', ) + + setup_model_options(prob, options) + prob.setup() - prob.set_val('install_loss_factor', [0.0, 0.05, 0.05], units="unitless") - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 12.0, units="ft") - prob.set_val(Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 150.0, units="unitless") - prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, 0.5, units="unitless" - ) - prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 0.0], units="ft") - prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 50.0], units="knot") - prob.set_val(Dynamic.Mission.SHAFT_POWER, [1000.0, 1000.0, 1250.0], units="hp") + prob.set_val('install_loss_factor', [0.0, 0.05, 0.05], units='unitless') + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 12.0, units='ft') + prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 150.0, units='unitless') + prob.set_val(Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless') + prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 0.0], units='ft') + prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 50.0], units='knot') + prob.set_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, [1000.0, 1000.0, 1250.0], units='hp') prob.set_val( - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, [1193.66207319, 1193.66207319, 1193.66207319], units='rpm', ) - prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 750.0, units="ft/s") + prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 750.0, units='ft/s') prob.run_model() self.compare_results(case_idx_begin=6, case_idx_end=8) @@ -362,35 +377,35 @@ def test_case_6_7_8(self): compact_print=True, show_only_incorrect=True, form='central', - method="fd", + method='fd', minimum_step=1e-12, abs_err_tol=5.0e-4, rel_err_tol=5.0e-5, - excludes=["*atmosphere*"], + excludes=['*atmosphere*'], ) assert_check_partials(partial_data, atol=1e-4, rtol=1e-4) def test_case_9_10_11(self): # Case 9, 10, 11, to test CLI > 0.5 prob = self.prob - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 12.0, units="ft") + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 12.0, units='ft') prob.set_val(Aircraft.Nacelle.AVG_DIAMETER, 2.4, units='ft') - prob.set_val(Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 150.0, units="unitless") + prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 150.0, units='unitless') prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.65, - units="unitless", + units='unitless', ) - prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 10000.0], units="ft") - prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 200.0], units="knot") - prob.set_val(Dynamic.Mission.SHAFT_POWER, [900.0, 750.0, 500.0], units="hp") + prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 10000.0], units='ft') + prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 200.0], units='knot') + prob.set_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, [900.0, 750.0, 500.0], units='hp') prob.set_val( - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, [1193.66207319, 1193.66207319, 1193.66207319], units='rpm', ) - prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 750.0, units="ft/s") + prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 750.0, units='ft/s') prob.run_model() self.compare_results(case_idx_begin=9, case_idx_end=11) @@ -400,18 +415,18 @@ def test_case_9_10_11(self): compact_print=True, show_only_incorrect=True, form='central', - method="fd", + method='fd', minimum_step=1e-12, abs_err_tol=5.0e-4, rel_err_tol=5.0e-5, - excludes=["*atmosphere*"], + excludes=['*atmosphere*'], ) # remove partial derivative of 'comp_tip_loss_factor' with respect to - # 'aircraft:engine:propeller_integrated_lift_coefficient' from assert_check_partials + # integrated lift coefficient from assert_check_partials partial_data_hs = partial_data['pp.hamilton_standard'] key_pair = ( 'comp_tip_loss_factor', - 'aircraft:engine:propeller_integrated_lift_coefficient', + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, ) del partial_data_hs[key_pair] assert_check_partials(partial_data, atol=1.5e-3, rtol=1e-4) @@ -419,16 +434,16 @@ def test_case_9_10_11(self): def test_case_12_13_14(self): # Case 12, 13, 14, to test mach limited tip speed. prob = self.prob - prob.set_val(Dynamic.Mission.ALTITUDE, [0.0, 0.0, 25000.0], units="ft") - prob.set_val(Dynamic.Mission.VELOCITY, [0.10, 125.0, 300.0], units="knot") - prob.set_val(Dynamic.Mission.SHAFT_POWER, [1850.0, 1850.0, 900.0], units="hp") + prob.set_val(Dynamic.Mission.ALTITUDE, [0.0, 0.0, 25000.0], units='ft') + prob.set_val(Dynamic.Mission.VELOCITY, [0.10, 125.0, 300.0], units='knot') + prob.set_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, [1850.0, 1850.0, 900.0], units='hp') prob.set_val( - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, [1455.1309082687574, 1455.1309082687574, 1156.4081529986502], units='rpm', ) - prob.set_val(Aircraft.Engine.PROPELLER_TIP_MACH_MAX, 0.8, units="unitless") - prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 800.0, units="ft/s") + prob.set_val(Aircraft.Engine.Propeller.TIP_MACH_MAX, 0.8, units='unitless') + prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 800.0, units='ft/s') prob.run_model() self.compare_results(case_idx_begin=12, case_idx_end=13) @@ -438,11 +453,11 @@ def test_case_12_13_14(self): compact_print=True, show_only_incorrect=True, form='central', - method="fd", + method='fd', minimum_step=1e-12, abs_err_tol=5.0e-4, rel_err_tol=5.0e-5, - excludes=["*atmosphere*"], + excludes=['*atmosphere*'], ) assert_check_partials(partial_data, atol=5e-4, rtol=1e-4) @@ -451,160 +466,73 @@ def test_case_15_16_17(self): prob = self.prob options = self.options - options.set_val(Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, - val=False, units='unitless') - options.set_val(Aircraft.Engine.USE_PROPELLER_MAP, - val=True, units='unitless') - prop_file_path = 'models/propellers/PropFan.prop' - options.set_val(Aircraft.Engine.PROPELLER_DATA_FILE, - val=prop_file_path, units='unitless') - options.set_val(Aircraft.Engine.INTERPOLATION_METHOD, - val='slinear', units='unitless') + options.set_val( + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, + val=False, + units='unitless', + ) + prop_file_path = 'models/engines/propellers/PropFan.csv' + options.set_val(Aircraft.Engine.Propeller.DATA_FILE, val=prop_file_path, units='unitless') + + setup_model_options(prob, options) prob.setup(force_alloc_complex=True) - prob.set_val('install_loss_factor', [0.0, 0.05, 0.05], units="unitless") - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 12.0, units="ft") - prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 0.0], units="ft") - prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 50.0], units="knot") - prob.set_val(Dynamic.Mission.SHAFT_POWER, [1000.0, 1000.0, 1250.0], units="hp") + prob.set_val('install_loss_factor', [0.0, 0.05, 0.05], units='unitless') + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 12.0, units='ft') + prob.set_val(Dynamic.Mission.ALTITUDE, [10000.0, 10000.0, 0.0], units='ft') + prob.set_val(Dynamic.Mission.VELOCITY, [200.0, 200.0, 50.0], units='knot') + prob.set_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, [1000.0, 1000.0, 1250.0], units='hp') prob.set_val( - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.RPM, [1225.0155969783186, 1225.0155969783186, 1225.0155969783186], units='rpm', ) - prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 769.70, units="ft/s") - - prob.run_model() - self.compare_results(case_idx_begin=15, case_idx_end=17) - - partial_data = prob.check_partials( - out_stream=None, - compact_print=True, - show_only_incorrect=True, - form='central', method="fd", - minimum_step=1e-12, - abs_err_tol=5.0E-4, - rel_err_tol=5.0E-5, - includes=["*selectedMach*"]) - assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) - + prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 769.70, units='ft/s') -class OutMachsTest(unittest.TestCase): - """ - Test the computation of OutMachs: Given two of Mach, helical Mach, and tip Mach, - compute the other. - """ - - def test_helical_mach(self): - # Given Mach and tip Mach, compute helical Mach. - tol = 1e-5 - prob = om.Problem() - prob.model.add_subsystem( - "group", - OutMachs(num_nodes=2, output_mach_type=OutMachType.HELICAL_MACH), - promotes=["*"], - ) - prob.setup() - prob.set_val("mach", val=[0.5, 0.7], units="unitless") - prob.set_val("tip_mach", val=[0.5, 0.7], units="unitless") prob.run_model() - y = prob.get_val("helical_mach") - y_exact = np.sqrt([0.5 * 0.5 + 0.5 * 0.5, 0.7 * 0.7 + 0.7 * 0.7]) - assert_near_equal(y, y_exact, tolerance=tol) - - partial_data = prob.check_partials( - out_stream=None, - compact_print=True, - show_only_incorrect=True, - form='central', - method="fd", - minimum_step=1e-12, - abs_err_tol=5.0E-4, - rel_err_tol=5.0E-5) - assert_check_partials(partial_data, atol=1e-4, rtol=1e-4) - - def test_mach(self): - # Given helical Mach and tip Mach, compute Mach. - tol = 1e-5 - prob = om.Problem() - prob.model.add_subsystem( - "group", - OutMachs(num_nodes=2, output_mach_type=OutMachType.MACH), - promotes=["*"], - ) - prob.setup() - prob.set_val("helical_mach", val=[0.7, 0.8], units="unitless") - prob.set_val("tip_mach", val=[0.5, 0.4], units="unitless") - prob.run_model() - y = prob.get_val("mach") - y_exact = np.sqrt([0.7 * 0.7 - 0.5 * 0.5, 0.8 * 0.8 - 0.4 * 0.4]) - - assert_near_equal(y, y_exact, tolerance=tol) + self.compare_results(case_idx_begin=15, case_idx_end=17) partial_data = prob.check_partials( out_stream=None, compact_print=True, show_only_incorrect=True, form='central', - method="fd", + method='fd', minimum_step=1e-12, - abs_err_tol=5.0E-4, - rel_err_tol=5.0E-5) - assert_check_partials(partial_data, atol=1e-4, rtol=1e-4) - - def test_tip_mach(self): - # Given helical Mach and Mach, compute tip Mach. - tol = 1e-5 - prob = om.Problem() - prob.model.add_subsystem( - "group", - OutMachs(num_nodes=2, output_mach_type=OutMachType.TIP_MACH), - promotes=["*"], + abs_err_tol=5.0e-4, + rel_err_tol=5.0e-5, + includes=['*selectedMach*'], ) - prob.setup() - prob.set_val("helical_mach", val=[0.7, 0.8], units="unitless") - prob.set_val("mach", val=[0.5, 0.4], units="unitless") - prob.run_model() - y = prob.get_val("tip_mach") - y_exact = np.sqrt([0.7 * 0.7 - 0.5 * 0.5, 0.8 * 0.8 - 0.4 * 0.4]) - - assert_near_equal(y, y_exact, tolerance=tol) - - partial_data = prob.check_partials( - out_stream=None, - compact_print=True, - show_only_incorrect=True, - form='central', - method="fd", - minimum_step=1e-12, - abs_err_tol=5.0E-4, - rel_err_tol=5.0E-5) - assert_check_partials(partial_data, atol=1e-4, rtol=1e-4) + assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class TipSpeedLimitTest(unittest.TestCase): - """ - Test computation of tip speed limit in TipSpeedLimit class. - """ + """Test computation of tip speed limit in TipSpeedLimit class.""" def test_tipspeed(self): tol = 1e-5 prob = om.Problem() prob.model.add_subsystem( - "group", + 'group', TipSpeed(num_nodes=3), - promotes=["*"], + promotes=['*'], ) prob.setup() - prob.set_val(Dynamic.Mission.VELOCITY, - val=[0.16878, 210.97623, 506.34296], units='ft/s') - prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, - val=[1116.42671, 1116.42671, 1015.95467], units='ft/s') - prob.set_val(Aircraft.Engine.PROPELLER_TIP_MACH_MAX, val=[0.8], units='unitless') - prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, val=[800], units='ft/s') - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, val=[10.5], units='ft') + prob.set_val( + Dynamic.Mission.VELOCITY, + val=[0.16878, 210.97623, 506.34296], + units='ft/s', + ) + prob.set_val( + Dynamic.Atmosphere.SPEED_OF_SOUND, + val=[1116.42671, 1116.42671, 1015.95467], + units='ft/s', + ) + prob.set_val(Aircraft.Engine.Propeller.TIP_MACH_MAX, val=[0.8], units='unitless') + prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, val=[800], units='ft/s') + prob.set_val(Aircraft.Engine.Propeller.DIAMETER, val=[10.5], units='ft') prob.run_model() @@ -616,7 +544,7 @@ def test_tipspeed(self): compact_print=True, show_only_incorrect=True, form='central', - method="fd", + method='fd', minimum_step=1e-12, abs_err_tol=5.0e-4, rel_err_tol=5.0e-5, @@ -625,120 +553,116 @@ def test_tipspeed(self): class SquareRatioTest(unittest.TestCase): - """ - Test the computation of square ratio with a maximum - """ + """Test the computation of square ratio with a maximum.""" def test_sqa_ratio_1(self): prob = om.Problem() prob.model.add_subsystem( - "group", + 'group', AreaSquareRatio(num_nodes=2, smooth_sqa=False), - promotes=["*"], + promotes=['*'], ) prob.setup(force_alloc_complex=True) - prob.set_val("DiamNac", val=2.8875, units='ft') - prob.set_val("DiamProp", val=10.0, units='ft') + prob.set_val('DiamNac', val=2.8875, units='ft') + prob.set_val('DiamProp', val=10.0, units='ft') prob.run_model() - sqa_ratio = prob.get_val("sqa_array", units='unitless') - assert_near_equal(sqa_ratio, [ - 0.08337656, 0.08337656], tolerance=1e-5) + sqa_ratio = prob.get_val('sqa_array', units='unitless') + assert_near_equal(sqa_ratio, [0.08337656, 0.08337656], tolerance=1e-5) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_sqa_ratio_2(self): prob = om.Problem() prob.model.add_subsystem( - "group", + 'group', AreaSquareRatio(num_nodes=2, smooth_sqa=True), - promotes=["*"], + promotes=['*'], ) prob.setup(force_alloc_complex=True) - prob.set_val("DiamNac", val=2.8875, units='ft') - prob.set_val("DiamProp", val=10.0, units='ft') + prob.set_val('DiamNac', val=2.8875, units='ft') + prob.set_val('DiamProp', val=10.0, units='ft') prob.run_model() - sqa_ratio = prob.get_val("sqa_array", units='unitless') + sqa_ratio = prob.get_val('sqa_array', units='unitless') assert_near_equal(sqa_ratio, [0.08337656, 0.08337656], tolerance=1e-5) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_sqa_ratio_3(self): - """ - Smooth, above 0.5 - """ + """Smooth, above 0.5.""" prob = om.Problem() prob.model.add_subsystem( - "group", + 'group', AreaSquareRatio(num_nodes=2, smooth_sqa=True), - promotes=["*"], + promotes=['*'], ) prob.setup(force_alloc_complex=True) - prob.set_val("DiamNac", val=8, units='ft') - prob.set_val("DiamProp", val=10.0, units='ft') + prob.set_val('DiamNac', val=8, units='ft') + prob.set_val('DiamProp', val=10.0, units='ft') prob.run_model() - sqa_ratio = prob.get_val("sqa_array", units='unitless') + sqa_ratio = prob.get_val('sqa_array', units='unitless') assert_near_equal(sqa_ratio, [0.5, 0.5], tolerance=1e-5) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) class AdvanceRatioTest(unittest.TestCase): - """ - Test the computation of advanced ratio with a maximum - """ + """Test the computation of advanced ratio with a maximum.""" def test_zje_1(self): prob = om.Problem() prob.model.add_subsystem( - "group", + 'group', AdvanceRatio(num_nodes=4, smooth_zje=False), - promotes=["*"], + promotes=['*'], ) prob.setup(force_alloc_complex=True) - prob.set_val("vtas", val=[0.1, 125., 300., 1000.], units='knot') - prob.set_val("tipspd", val=[800., 800., 750., 500.], units='ft/s') - prob.set_val("sqa_array", val=[0.0756, 0.0756, 0.0756, 1.0], units='unitless') + prob.set_val('vtas', val=[0.1, 125.0, 300.0, 1000.0], units='knot') + prob.set_val('tipspd', val=[800.0, 800.0, 750.0, 500.0], units='ft/s') + prob.set_val('sqa_array', val=[0.0756, 0.0756, 0.0756, 1.0], units='unitless') prob.run_model() - equiv_adv_ratio = prob.get_val("equiv_adv_ratio", units='unitless') - assert_near_equal(equiv_adv_ratio, [ - 6.50074004e-04, 8.12592505e-01, 2.08023681e+00, 5.0], tolerance=1e-5) + equiv_adv_ratio = prob.get_val('equiv_adv_ratio', units='unitless') + assert_near_equal( + equiv_adv_ratio, + [6.50074004e-04, 8.12592505e-01, 2.08023681e00, 5.0], + tolerance=1e-5, + ) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) def test_zje_2(self): prob = om.Problem() prob.model.add_subsystem( - "group", + 'group', AdvanceRatio(num_nodes=4, smooth_zje=True), - promotes=["*"], + promotes=['*'], ) prob.setup(force_alloc_complex=True) - prob.set_val("vtas", val=[0.1, 125., 300., 1000.], units='knot') - prob.set_val("tipspd", val=[800., 800., 750., 500.], units='ft/s') - prob.set_val("sqa_array", val=[0.0756, 0.0756, 0.0756, 1.0], units='unitless') + prob.set_val('vtas', val=[0.1, 125.0, 300.0, 1000.0], units='knot') + prob.set_val('tipspd', val=[800.0, 800.0, 750.0, 500.0], units='ft/s') + prob.set_val('sqa_array', val=[0.0756, 0.0756, 0.0756, 1.0], units='unitless') prob.run_model() - equiv_adv_ratio = prob.get_val("equiv_adv_ratio", units='unitless') + equiv_adv_ratio = prob.get_val('equiv_adv_ratio', units='unitless') assert_near_equal( equiv_adv_ratio, - [6.50074004e-04, 8.12592505e-01, 2.08023681e+00, 5.0], - tolerance=1e-5 + [6.50074004e-04, 8.12592505e-01, 2.08023681e00, 5.0], + tolerance=1e-5, ) - partial_data = prob.check_partials(out_stream=None, method="cs") + partial_data = prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-12) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = PropellerPerformanceTest() # test.setUp() - # test.test_case_3_4_5() + # test.test_case_15_16_17() diff --git a/aviary/subsystems/propulsion/propulsion_builder.py b/aviary/subsystems/propulsion/propulsion_builder.py index 3ba9ea8722..b22298a32f 100644 --- a/aviary/subsystems/propulsion/propulsion_builder.py +++ b/aviary/subsystems/propulsion/propulsion_builder.py @@ -10,12 +10,11 @@ import numpy as np -from aviary.interface.utils.markdown_utils import write_markdown_variable_table - -from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.subsystems.propulsion.propulsion_premission import PropulsionPreMission -from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission +from aviary.interface.utils import write_markdown_variable_table from aviary.subsystems.propulsion.engine_model import EngineModel +from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission +from aviary.subsystems.propulsion.propulsion_premission import PropulsionPreMission +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase # NOTE These are currently needed to get around variable hierarchy being class-based. # Ideally, an alternate solution to loop through the hierarchy will be created and @@ -28,11 +27,11 @@ class PropulsionBuilderBase(SubsystemBuilderBase): """ - Base class for propulsion builder + Base class for propulsion builder. Note ---- - unlike the other subsystem builders, it is not reccomended to create additional + unlike the other subsystem builders, it is not recommended to create additional propulsion subsystems, as propulsion is intended to be an agnostic carrier of all propulsion-related subsystem builders in the form of EngineModels. @@ -60,6 +59,7 @@ def mission_outputs(self, **kwargs): class CorePropulsionBuilder(PropulsionBuilderBase): """ Core propulsion builder. + Methods ------- build_pre_mission(self, aviary_inputs) -> openmdao.core.System: @@ -74,7 +74,7 @@ class CorePropulsionBuilder(PropulsionBuilderBase): Call get_controls() on all engine models and return combined result. get_linked_variables(self) -> dict: Call get_linked_variables() on all engine models and return combined result. - get_bus_variables(self) -> dict + get_pre_mission_bus_variables(self) -> dict Call get_linked_variables() on all engine models and return combined result. define_order(self) -> list: Call define_order() on all engine models and return combined result. @@ -103,24 +103,28 @@ def __init__(self, name=None, meta_data=None, engine_models=None, **kwargs): for engine in engine_models: if not isinstance(engine, EngineModel): - raise UserWarning('Engine provided to propulsion builder is not an ' - 'EngineModel object') + raise UserWarning( + 'Engine provided to propulsion builder is not an EngineModel object' + ) self.engine_models = engine_models - def build_pre_mission(self, aviary_inputs): - return PropulsionPreMission(aviary_options=aviary_inputs, - engine_models=self.engine_models) + def build_pre_mission(self, aviary_inputs, **kwargs): + return PropulsionPreMission( + aviary_options=aviary_inputs, engine_models=self.engine_models, engine_options=kwargs + ) def build_mission(self, num_nodes, aviary_inputs, **kwargs): - return PropulsionMission(num_nodes=num_nodes, aviary_options=aviary_inputs, - engine_models=self.engine_models) - - # NOTE untested! + return PropulsionMission( + num_nodes=num_nodes, + aviary_options=aviary_inputs, + engine_models=self.engine_models, + engine_options=kwargs, + ) + + # NOTE no unittests! def get_states(self): - """ - Call get_states() on all engine models and return combined result. - """ + """Call get_states() on all engine models and return combined result.""" states = {} for engine in self.engine_models: engine_states = engine.get_states() @@ -129,9 +133,7 @@ def get_states(self): return states def get_controls(self, phase_name=None): - """ - Call get_controls() on all engine models and return combined result. - """ + """Call get_controls() on all engine models and return combined result.""" controls = {} for engine in self.engine_models: engine_controls = engine.get_controls(phase_name=phase_name) @@ -139,7 +141,7 @@ def get_controls(self, phase_name=None): return controls - # NOTE untested! + # NOTE no unittests! def get_parameters(self, aviary_inputs=None, phase_info=None): """ Set expected shape of all variables that need to be vectorized for multiple @@ -151,11 +153,23 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): # collect all the parameters for engines for engine in self.engine_models: engine_params = engine.get_parameters() + # for param in engine_params: + # # For any parameters that need to be vectorized for multiple engines, + # # apply correct shape + # if param in params: + # try: + # shape_old = params[param]['shape'][0] + # except KeyError: + # # If shape is not defined yet, this is the first time there is + # # a duplicate + # shape_old = 1 + # engine_params[param]['shape'] = (shape_old + 1,) + params.update(engine_params) # for any parameters that need to be vectorized for multiple engines, apply # correct shape - engine_vars = _get_engine_variables() + engine_vars = [var for var in _get_engine_variables()] for var in params: if var in engine_vars: # TODO shape for variables that are supposed to be vectors, like wing @@ -165,11 +179,9 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): return params - # NOTE untested! + # NOTE no unittests! def get_constraints(self): - """ - Call get_constraints() on all engine models and return combined result. - """ + """Call get_constraints() on all engine models and return combined result.""" constraints = {} for engine in self.engine_models: engine_constraints = engine.get_constraints() @@ -177,11 +189,9 @@ def get_constraints(self): return constraints - # NOTE untested! + # NOTE no unittests! def get_linked_variables(self): - """ - Call get_linked_variables() on all engine models and return combined result. - """ + """Call get_linked_variables() on all engine models and return combined result.""" linked_vars = {} for engine in self.engine_models: engine_linked_vars = engine.get_linked_variables() @@ -189,13 +199,11 @@ def get_linked_variables(self): return linked_vars - def get_bus_variables(self): - """ - Call get_linked_variables() on all engine models and return combined result. - """ + def get_pre_mission_bus_variables(self, aviary_inputs=None): + """Call get_linked_variables() on all engine models and return combined result.""" bus_vars = {} for engine in self.engine_models: - engine_bus_vars = engine.get_bus_variables() + engine_bus_vars = engine.get_pre_mission_bus_variables(aviary_inputs) bus_vars.update(engine_bus_vars) # append propulsion group name to all engine-level bus variables @@ -207,11 +215,9 @@ def get_bus_variables(self): return complete_bus_vars - # NOTE untested! + # NOTE no unittests! def define_order(self): - """ - Call define_order() on all engine models and return combined result. - """ + """Call define_order() on all engine models and return combined result.""" subsys_order = [] for engine in self.engine_models: engine_subsys_order = engine.define_order() @@ -219,11 +225,9 @@ def define_order(self): return subsys_order - # NOTE untested! + # NOTE no unittests! def get_design_vars(self): - """ - Call get_design_vars() on all engine models and return combined result. - """ + """Call get_design_vars() on all engine models and return combined result.""" design_vars = {} for engine in self.engine_models: engine_design_vars = engine.get_design_vars() @@ -232,9 +236,7 @@ def get_design_vars(self): return design_vars def get_initial_guesses(self): - """ - Call get_initial_guesses() on all engine models and return combined result. - """ + """Call get_initial_guesses() on all engine models and return combined result.""" initial_guesses = {} for engine in self.engine_models: engine_initial_guesses = engine.get_initial_guesses() @@ -242,11 +244,9 @@ def get_initial_guesses(self): return initial_guesses - # NOTE untested! + # NOTE no unittests! def get_mass_names(self): - """ - Call get_mass_names() on all engine models and return combined result. - """ + """Call get_mass_names() on all engine models and return combined result.""" mass_names = {} for engine in self.engine_models: engine_mass_names = engine.get_mass_names() @@ -254,11 +254,9 @@ def get_mass_names(self): return mass_names - # NOTE untested! + # NOTE no unittests! def preprocess_inputs(self): - """ - Call get_mass_names() on all engine models and return combined result. - """ + """Call get_mass_names() on all engine models and return combined result.""" mass_names = {} for engine in self.engine_models: engine_mass_names = engine.get_mass_names() @@ -266,11 +264,9 @@ def preprocess_inputs(self): return mass_names - # NOTE untested! + # NOTE no unittests! def get_outputs(self): - """ - Call get_outputs() on all engine models and return combined result. - """ + """Call get_outputs() on all engine models and return combined result.""" outputs = [] for engine in self.engine_models: engine_outputs = engine.get_outputs() @@ -280,7 +276,7 @@ def get_outputs(self): def report(self, prob, reports_folder, **kwargs): """ - Generate the report for Aviary core propulsion analysis + Generate the report for Aviary core propulsion analysis. Parameters ---------- @@ -292,8 +288,10 @@ def report(self, prob, reports_folder, **kwargs): filename = self.name + '.md' filepath = reports_folder / filename - propulsion_outputs = [Aircraft.Propulsion.TOTAL_NUM_ENGINES, - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] + propulsion_outputs = [ + Aircraft.Propulsion.TOTAL_NUM_ENGINES, + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, + ] with open(filepath, mode='w') as f: f.write('# Propulsion') diff --git a/aviary/subsystems/propulsion/propulsion_mission.py b/aviary/subsystems/propulsion/propulsion_mission.py index 6237f7dcfb..0414d87cb0 100644 --- a/aviary/subsystems/propulsion/propulsion_mission.py +++ b/aviary/subsystems/propulsion/propulsion_mission.py @@ -4,15 +4,16 @@ import openmdao.api as om from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic, Settings class PropulsionMission(om.Group): - ''' + """ Group that tracks all engine models used during mission analysis. Accounts for number of engines for each type and returns aircraft-total dynamic values such as net thrust and fuel flow rate. - ''' + """ def initialize(self): self.options.declare('num_nodes', types=int, lower=0) @@ -23,107 +24,173 @@ def initialize(self): desc='collection of Aircraft/Mission specific options', ) + self.options.declare('engine_models', types=list, desc='list of EngineModels on aircraft') + + # engine options is optional self.options.declare( - 'engine_models', types=list, desc='list of EngineModels on aircraft' + 'engine_options', + types=dict, + default={}, + desc='dictionary of options for each EngineModel', ) def setup(self): nn = self.options['num_nodes'] options: AviaryValues = self.options['aviary_options'] engine_models = self.options['engine_models'] + engine_options = self.options['engine_options'] num_engine_type = len(engine_models) if num_engine_type > 1: + # We need a component to add parameters to problem. Dymos can't find it when + # it is already sliced across several components. + # TODO is this problem fixable from dymos end (introspection includes parameters)? + + # create set of params + # TODO get_parameters() should have access to aviary options + phase info + param_dict = {} + # save parameters for use in configure() + parameters = self.parameters = set() + for engine in engine_models: + eng_params = engine.get_parameters() + param_dict.update(eng_params) + + parameters.update(param_dict.keys()) + + # if params exist, create execcomp, fill with placeholder equations + if len(parameters) != 0: + comp = om.ExecComp(has_diag_partials=True) + + for i, param in enumerate(parameters): + # try to find units information + try: + units = param_dict[param]['units'] + except KeyError: + units = 'unitless' + + attrs = { + f'x_{i}': { + 'val': np.ones(num_engine_type), + 'units': units, + }, + f'y_{i}': { + 'val': np.ones(num_engine_type), + 'units': units, + }, + } + comp.add_expr( + f'y_{i}=x_{i}', + **attrs, + ) - # We need a single component with scale_factor. Dymos can't find it when it is - # already sliced across several component. - # TODO this only works for engine decks. Need to fix problem in generic way - comp = om.ExecComp( - "y=x", - y={'val': np.ones(num_engine_type), 'units': 'unitless'}, - x={'val': np.ones(num_engine_type), 'units': 'unitless'}, - has_diag_partials=True, - ) self.add_subsystem( - "scale_passthrough", + 'parameter_passthrough', comp, - promotes_inputs=[('x', Aircraft.Engine.SCALE_FACTOR)], - promotes_outputs=[('y', 'passthrough_scale_factor')], ) for i, engine in enumerate(engine_models): + kwargs = {} + if engine.name in engine_options: + kwargs = engine_options[engine.name] self.add_subsystem( engine.name, - subsys=engine.build_mission(num_nodes=nn, aviary_inputs=options), + subsys=engine.build_mission(num_nodes=nn, aviary_inputs=options, **kwargs), promotes_inputs=['*'], ) # split vectorized throttles and connect to the correct engine model self.promotes( engine.name, - inputs=[Dynamic.Mission.THROTTLE], + inputs=[Dynamic.Vehicle.Propulsion.THROTTLE], src_indices=om.slicer[:, i], ) - self.promotes( - engine.name, - inputs=[(Aircraft.Engine.SCALE_FACTOR, 'passthrough_scale_factor')], - src_indices=om.slicer[i], - ) + # loop through params and slice as needed + params = engine.get_parameters() + for param in params: + self.promotes( + engine.name, + inputs=[(param, param + '_passthrough')], + src_indices=om.slicer[i], + ) # TODO if only some engine use hybrid throttle, source vector will have an # index for that engine that is unused, will this confuse optimizer? if engine.use_hybrid_throttle: self.promotes( engine.name, - inputs=[Dynamic.Mission.HYBRID_THROTTLE], + inputs=[Dynamic.Vehicle.Propulsion.HYBRID_THROTTLE], src_indices=om.slicer[:, i], ) else: engine = engine_models[0] + kwargs = {} + if engine.name in engine_options: + kwargs = engine_options[engine.name] + self.add_subsystem( + engine.name, + subsys=engine.build_mission(num_nodes=nn, aviary_inputs=options, **kwargs), + promotes_inputs=['*'], + ) - for i, engine in enumerate(engine_models): - self.add_subsystem( - engine.name, - subsys=engine.build_mission(num_nodes=nn, aviary_inputs=options), - promotes_inputs=['*'], - ) + self.promotes(engine.name, inputs=[Dynamic.Vehicle.Propulsion.THROTTLE]) - self.promotes(engine.name, inputs=[Dynamic.Mission.THROTTLE]) - if engine.use_hybrid_throttle: - self.promotes(engine.name, inputs=[Dynamic.Mission.HYBRID_THROTTLE]) + if engine.use_hybrid_throttle: + self.promotes(engine.name, inputs=[Dynamic.Vehicle.Propulsion.HYBRID_THROTTLE]) # TODO might be able to avoid hardcoding using propulsion Enums # mux component to vectorize individual engine outputs into 2d arrays perf_mux = om.MuxComp(vec_size=num_engine_type) # add each engine data variable to mux component + perf_mux.add_var(Dynamic.Vehicle.Propulsion.THRUST, val=0, shape=(nn,), axis=1, units='lbf') perf_mux.add_var( - Dynamic.Mission.THRUST, val=0, shape=(nn,), axis=1, units='lbf' - ) - perf_mux.add_var( - Dynamic.Mission.THRUST_MAX, val=0, shape=(nn,), axis=1, units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_MAX, + val=0, + shape=(nn,), + axis=1, + units='lbf', ) perf_mux.add_var( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, val=0, shape=(nn,), axis=1, units='lbm/h', ) perf_mux.add_var( - Dynamic.Mission.ELECTRIC_POWER_IN, val=0, shape=(nn,), axis=1, units='kW' + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, + val=0, + shape=(nn,), + axis=1, + units='kW', ) perf_mux.add_var( - Dynamic.Mission.NOX_RATE, val=0, shape=(nn,), axis=1, units='lb/h' + Dynamic.Vehicle.Propulsion.NOX_RATE, + val=0, + shape=(nn,), + axis=1, + units='lb/h', ) perf_mux.add_var( - Dynamic.Mission.TEMPERATURE_T4, val=0, shape=(nn,), axis=1, units='degR' + Dynamic.Vehicle.Propulsion.TEMPERATURE_T4, + val=0, + shape=(nn,), + axis=1, + units='degR', ) perf_mux.add_var( - Dynamic.Mission.SHAFT_POWER, val=0, shape=(nn,), axis=1, units='hp' + Dynamic.Vehicle.Propulsion.SHAFT_POWER, + val=0, + shape=(nn,), + axis=1, + units='hp', ) perf_mux.add_var( - Dynamic.Mission.SHAFT_POWER_MAX, val=0, shape=(nn,), axis=1, units='hp' + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, + val=0, + shape=(nn,), + axis=1, + units='hp', ) # perf_mux.add_var( # 'exit_area_unscaled', @@ -131,13 +198,11 @@ def setup(self): # axis=1, # units='ft**2') - self.add_subsystem( - 'vectorize_performance', subsys=perf_mux, promotes_outputs=['*'] - ) + self.add_subsystem('vectorize_performance', subsys=perf_mux, promotes_outputs=['*']) self.add_subsystem( 'propulsion_sum', - subsys=PropulsionSum(num_nodes=nn, aviary_options=options), + subsys=PropulsionSum(num_nodes=nn), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -149,19 +214,19 @@ def configure(self): # TODO this list shouldn't be hardcoded so it can be extended by users supported_outputs = [ - Dynamic.Mission.ELECTRIC_POWER_IN, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, - Dynamic.Mission.NOX_RATE, - Dynamic.Mission.SHAFT_POWER, - Dynamic.Mission.SHAFT_POWER_MAX, - Dynamic.Mission.TEMPERATURE_T4, - Dynamic.Mission.THRUST, - Dynamic.Mission.THRUST_MAX, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.NOX_RATE, + Dynamic.Vehicle.Propulsion.SHAFT_POWER, + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, + Dynamic.Vehicle.Propulsion.TEMPERATURE_T4, + Dynamic.Vehicle.Propulsion.THRUST, + Dynamic.Vehicle.Propulsion.THRUST_MAX, ] engine_models = self.options['engine_models'] engine_names = [engine.name for engine in engine_models] - # num_engine_type = len(engine_models) + num_engine_type = len(engine_models) # determine if openMDAO messages and warnings should be suppressed verbosity = self.options['aviary_options'].get_val(Settings.VERBOSITY) @@ -189,8 +254,7 @@ def configure(self): key for key in comp_outputs if '.' not in comp_outputs[key]['prom_name'] ] output_dict[comp.name] = dict( - (comp_outputs[key]['prom_name'], comp_outputs[key]) - for key in promoted_outputs + (comp_outputs[key]['prom_name'], comp_outputs[key]) for key in promoted_outputs ) unique_outputs.update( [ @@ -218,64 +282,98 @@ def configure(self): ) # TODO handle setting of other variables from engine outputs (e.g. Aircraft.Engine.****) + if num_engine_type > 1: + # commented out block of code is for experimenting with automatically finding + # inputs that need a passthrough, rather than relying on get_parameters() + # being properly set up + + # custom promote parameters with aliasing to connect to passthrough component + # for engine in engine_models: + # get inputs to engine model + # engine_comp = self._get_subsystem(engine.name) + # input_dict = engine_comp.list_inputs( + # return_format='dict', units=True, out_stream=None, all_procs=True + # ) + # # TODO this catches not fully promoted variables are caught - is this + # # wanted? + # input_list = list( + # set( + # input_dict[key]['prom_name'] + # for key in input_dict + # if '.' not in input_dict[key]['prom_name'] + # ) + # ) + # promotions = [] + for i, param in enumerate(self.parameters): + self.promotes( + 'parameter_passthrough', + inputs=[(f'x_{i}', param)], + outputs=[(f'y_{i}', param + '_passthrough')], + ) + # if param in input_dict: + # promotions.append((param, param + '_passthrough')) + # self.promotes(engine.name, inputs=promotions) + class PropulsionSum(om.ExplicitComponent): - ''' - Calculates propulsion system level sums of individual engine performance parameters. - ''' + """Calculates propulsion system level sums of individual engine performance parameters.""" def initialize(self): self.options.declare('num_nodes', types=int, lower=0) - - self.options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options', - ) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): nn = self.options['num_nodes'] - num_engine_type = len( - self.options['aviary_options'].get_val(Aircraft.Engine.NUM_ENGINES) - ) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) self.add_input( - Dynamic.Mission.THRUST, val=np.zeros((nn, num_engine_type)), units='lbf' + Dynamic.Vehicle.Propulsion.THRUST, + val=np.zeros((nn, num_engine_type)), + units='lbf', ) self.add_input( - Dynamic.Mission.THRUST_MAX, val=np.zeros((nn, num_engine_type)), units='lbf' + Dynamic.Vehicle.Propulsion.THRUST_MAX, + val=np.zeros((nn, num_engine_type)), + units='lbf', ) self.add_input( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, val=np.zeros((nn, num_engine_type)), units='lbm/h', ) self.add_input( - Dynamic.Mission.ELECTRIC_POWER_IN, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, val=np.zeros((nn, num_engine_type)), units='kW', ) self.add_input( - Dynamic.Mission.NOX_RATE, val=np.zeros((nn, num_engine_type)), units='lbm/h' + Dynamic.Vehicle.Propulsion.NOX_RATE, + val=np.zeros((nn, num_engine_type)), + units='lbm/h', ) - self.add_output(Dynamic.Mission.THRUST_TOTAL, val=np.zeros(nn), units='lbf') - self.add_output(Dynamic.Mission.THRUST_MAX_TOTAL, val=np.zeros(nn), units='lbf') + self.add_output(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, val=np.zeros(nn), units='lbf') self.add_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + val=np.zeros(nn), + units='lbf', + ) + self.add_output( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, val=np.zeros(nn), units='lbm/h', ) self.add_output( - Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL, val=np.zeros(nn), units='kW' + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + val=np.zeros(nn), + units='kW', ) - self.add_output(Dynamic.Mission.NOX_RATE_TOTAL, val=np.zeros(nn), units='lbm/h') + self.add_output(Dynamic.Vehicle.Propulsion.NOX_RATE_TOTAL, val=np.zeros(nn), units='lbm/h') def setup_partials(self): nn = self.options['num_nodes'] - num_engines = self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES - ) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] + num_engine_type = len(num_engines) deriv = np.tile(num_engines, nn) @@ -283,56 +381,54 @@ def setup_partials(self): c = np.arange(nn * num_engine_type, dtype=int) self.declare_partials( - Dynamic.Mission.THRUST_TOTAL, - Dynamic.Mission.THRUST, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST, val=deriv, rows=r, cols=c, ) self.declare_partials( - Dynamic.Mission.THRUST_MAX_TOTAL, - Dynamic.Mission.THRUST_MAX, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_MAX, val=deriv, rows=r, cols=c, ) self.declare_partials( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, val=deriv, rows=r, cols=c, ) self.declare_partials( - Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL, - Dynamic.Mission.ELECTRIC_POWER_IN, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, val=deriv, rows=r, cols=c, ) self.declare_partials( - Dynamic.Mission.NOX_RATE_TOTAL, - Dynamic.Mission.NOX_RATE, + Dynamic.Vehicle.Propulsion.NOX_RATE_TOTAL, + Dynamic.Vehicle.Propulsion.NOX_RATE, val=deriv, rows=r, cols=c, ) def compute(self, inputs, outputs): - num_engines = self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES - ) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] - thrust = inputs[Dynamic.Mission.THRUST] - thrust_max = inputs[Dynamic.Mission.THRUST_MAX] - fuel_flow = inputs[Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE] - electric = inputs[Dynamic.Mission.ELECTRIC_POWER_IN] - nox = inputs[Dynamic.Mission.NOX_RATE] + thrust = inputs[Dynamic.Vehicle.Propulsion.THRUST] + thrust_max = inputs[Dynamic.Vehicle.Propulsion.THRUST_MAX] + fuel_flow = inputs[Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE] + electric = inputs[Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN] + nox = inputs[Dynamic.Vehicle.Propulsion.NOX_RATE] - outputs[Dynamic.Mission.THRUST_TOTAL] = np.dot(thrust, num_engines) - outputs[Dynamic.Mission.THRUST_MAX_TOTAL] = np.dot(thrust_max, num_engines) - outputs[Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL] = np.dot( + outputs[Dynamic.Vehicle.Propulsion.THRUST_TOTAL] = np.dot(thrust, num_engines) + outputs[Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL] = np.dot(thrust_max, num_engines) + outputs[Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL] = np.dot( fuel_flow, num_engines ) - outputs[Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL] = np.dot(electric, num_engines) - outputs[Dynamic.Mission.NOX_RATE_TOTAL] = np.dot(nox, num_engines) + outputs[Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL] = np.dot(electric, num_engines) + outputs[Dynamic.Vehicle.Propulsion.NOX_RATE_TOTAL] = np.dot(nox, num_engines) diff --git a/aviary/subsystems/propulsion/propulsion_premission.py b/aviary/subsystems/propulsion/propulsion_premission.py index 7480211bf7..09e4ed9058 100644 --- a/aviary/subsystems/propulsion/propulsion_premission.py +++ b/aviary/subsystems/propulsion/propulsion_premission.py @@ -4,63 +4,74 @@ import openmdao.api as om from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.functions import add_aviary_input, add_aviary_output -from aviary.variable_info.variables import Aircraft, Settings from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output +from aviary.variable_info.variables import Aircraft, Settings class PropulsionPreMission(om.Group): - ''' + """ Group that contains propulsion calculations for pre-mission analysis, such as computing scaling factors, and sums propulsion-system level totals. - ''' + """ def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', + ) + + self.options.declare('engine_models', types=list, desc='list of EngineModels on aircraft') + + # engine options is optional self.options.declare( - 'engine_models', types=list, - desc='list of EngineModels on aircraft' + 'engine_options', + types=dict, + default={}, + desc='dictionary of options for each EngineModel', ) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + add_aviary_option(self, Settings.VERBOSITY) + def setup(self): - options = self.options['aviary_options'] + aviary_options = self.options['aviary_options'] engine_models = self.options['engine_models'] + engine_options = self.options['engine_options'] num_engine_type = len(engine_models) # Each engine model pre_mission component only needs to accept and output single # value relevant to that variable - this group's configure step will handle # promoting/connecting just the relevant index in vectorized inputs/outputs for # each component here - # Promotions are handled in self.configure() + # Promotions are handled in configure() for engine in engine_models: - subsys = engine.build_pre_mission(options) + options = {} + if engine.name in engine_options: + options = engine_options[engine.name] + subsys = engine.build_pre_mission(aviary_options, **options) if subsys: if num_engine_type > 1: proms = None else: proms = ['*'] - self.add_subsystem(engine.name, - subsys=subsys, - promotes_outputs=proms, - ) + self.add_subsystem( + engine.name, + subsys=subsys, + promotes_outputs=proms, + ) if num_engine_type > 1: # Add an empty mux comp, which will be customized to handle all required - # outputs in self.configure() - self.add_subsystem( - 'pre_mission_mux', - subsys=om.MuxComp(), - promotes_outputs=['*'] - ) + # outputs in configure() + self.add_subsystem('pre_mission_mux', subsys=om.MuxComp(), promotes_outputs=['*']) self.add_subsystem( 'propulsion_sum', - subsys=PropulsionSum( - aviary_options=options), + subsys=PropulsionSum(), promotes_inputs=['*'], - promotes_outputs=['*'] + promotes_outputs=['*'], ) def configure(self): @@ -69,88 +80,99 @@ def configure(self): # so vectorized inputs/outputs are a problem. Slice all needed vector inputs and pass # pre_mission components only the value they need, then mux all the outputs back together - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + engine_models = self.options['engine_models'] + num_engine_type = len(engine_models) # determine if openMDAO messages and warnings should be suppressed - verbosity = self.options['aviary_options'].get_val(Settings.VERBOSITY) + verbosity = self.options[Settings.VERBOSITY] out_stream = None # DEBUG if verbosity > Verbosity.VERBOSE: out_stream = sys.stdout - comp_list = [ - self._get_subsystem(group) - for group in dir(self) - if self._get_subsystem(group) - and group not in ['pre_mission_mux', 'propulsion_sum'] - ] + # Patterns to identify which inputs/outputs are vectorized and need to be + # split then re-muxed + pattern = ['engine:', 'nacelle:'] # Dictionary of all unique inputs/outputs from all new components, keys are # units for each var unique_outputs = {} - unique_inputs = {} + # unique_inputs = {} - # dictionaries of inputs/outputs for each added component in prop pre-mission + # dictionaries of inputs/outputs for engine in prop pre-mission input_dict = {} output_dict = {} - for idx, comp in enumerate(comp_list): + for idx, engine_model in enumerate(engine_models): + engine = self._get_subsystem(engine_model.name) # Patterns to identify which inputs/outputs are vectorized and need to be # split then re-muxed pattern = ['engine:', 'nacelle:'] # pull out all inputs (in dict format) in component - comp_inputs = comp.list_inputs( - return_format='dict', units=True, out_stream=out_stream, all_procs=True + eng_inputs = engine.list_inputs( + return_format='dict', + units=True, + out_stream=out_stream, + all_procs=True, + ) + # switch dictionary keys to promoted name rather than full path + # only handle variables that were top-level promoted inside engine model + eng_inputs = dict( + [ + (eng_inputs[key]['prom_name'], eng_inputs[key]) + for key in eng_inputs + if '.' not in eng_inputs[key]['prom_name'] + ] ) # only keep inputs if they contain the pattern - input_dict[comp.name] = dict( - (key, comp_inputs[key]) - for key in comp_inputs - if any([x in key for x in pattern]) + input_dict[engine.name] = dict( + (key, eng_inputs[key]) for key in eng_inputs if any([x in key for x in pattern]) ) - # Track list of ALL inputs present in prop pre-mission in a "flat" dict. - # Repeating inputs will just override what's already in the dict - we don't - # care if units get overridden, if they differ openMDAO will convert - # (if they aren't compatible, then a component specified the wrong units and - # needs to be fixed there) - unique_inputs.update([(key, input_dict[comp.name][key]['units']) - for key in input_dict[comp.name]]) # do the same thing with outputs - comp_outputs = comp.list_outputs( + eng_outputs = engine.list_outputs( return_format='dict', units=True, out_stream=out_stream, all_procs=True ) - output_dict[comp.name] = dict( - (key, comp_outputs[key]) - for key in comp_outputs - if any([x in key for x in pattern]) + eng_outputs = dict( + [ + (eng_outputs[key]['prom_name'], eng_outputs[key]) + for key in eng_outputs + if '.' not in eng_outputs[key]['prom_name'] + ] + ) + output_dict[engine.name] = dict( + (key, eng_outputs[key]) for key in eng_outputs if any([x in key for x in pattern]) ) unique_outputs.update( [ - (key, output_dict[comp.name][key]['units']) - for key in output_dict[comp.name] + ( + key, + output_dict[engine.name][key]['units'], + ) + for key in output_dict[engine.name] ] ) - # slice incoming inputs for this component, so it only gets the correct index + # slice incoming inputs for this engine, so it only gets the correct index + if num_engine_type > 1: + src_indices = om.slicer[idx] + else: + src_indices = None + self.promotes( - comp.name, inputs=input_dict[comp.name].keys(), src_indices=om.slicer[idx]) + engine.name, + inputs=[*input_dict[engine.name]], + src_indices=src_indices, + ) - # promote all other inputs/outputs for this component normally (handle vectorized outputs later) + # promote all other inputs/outputs for this engine normally (handle vectorized outputs later) self.promotes( - comp.name, - inputs=[ - comp_inputs[input]['prom_name'] - for input in comp_inputs - if input not in input_dict[comp.name] - ], + engine.name, + inputs=[input for input in eng_inputs if input not in input_dict[engine.name]], outputs=[ - comp_outputs[output]['prom_name'] - for output in comp_outputs - if output not in output_dict[comp.name] + output for output in eng_outputs if output not in output_dict[engine.name] ], ) @@ -160,11 +182,11 @@ def configure(self): for output in unique_outputs: self.pre_mission_mux.add_var(output, units=unique_outputs[output]) # promote/alias outputs for each comp that has relevant outputs - for i, comp in enumerate(output_dict): - if output in output_dict[comp]: + for i, engine in enumerate(output_dict): + if output in output_dict[engine]: # if this component provides the output, connect it to the correct mux input self.connect( - comp + '.' + output, + engine + '.' + output, 'pre_mission_mux.' + output + '_' + str(i), ) else: @@ -178,35 +200,30 @@ def configure(self): class PropulsionSum(om.ExplicitComponent): - ''' - Calculates propulsion system level sums of individual engine performance parameters. - ''' + """Calculates propulsion system level sums of individual engine performance parameters.""" def initialize(self): - self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options') + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) def setup(self): - num_engine_type = len(self.options['aviary_options'].get_val( - Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, - val=np.zeros(num_engine_type)) + add_aviary_input(self, Aircraft.Engine.SCALED_SLS_THRUST, val=np.zeros(num_engine_type)) - add_aviary_output( - self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=0.0) + add_aviary_output(self, Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, val=0.0) def setup_partials(self): - num_engines = self.options['aviary_options'].get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] - self.declare_partials(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, - Aircraft.Engine.SCALED_SLS_THRUST, val=num_engines) + self.declare_partials( + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, + Aircraft.Engine.SCALED_SLS_THRUST, + val=num_engines, + ) def compute(self, inputs, outputs): - num_engines = self.options['aviary_options'].get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = self.options[Aircraft.Engine.NUM_ENGINES] thrust = inputs[Aircraft.Engine.SCALED_SLS_THRUST] - outputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] = np.dot( - thrust, num_engines) + outputs[Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST] = np.dot(thrust, num_engines) diff --git a/aviary/subsystems/propulsion/test/test_custom_engine_model.py b/aviary/subsystems/propulsion/test/test_custom_engine_model.py index 91db9831e5..462ab81fd7 100644 --- a/aviary/subsystems/propulsion/test/test_custom_engine_model.py +++ b/aviary/subsystems/propulsion/test/test_custom_engine_model.py @@ -2,25 +2,14 @@ import dymos as dm import openmdao.api as om +from dymos.transcriptions.transcription_base import TranscriptionBase from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs +from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.propulsion.engine_model import EngineModel from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Aircraft, Dynamic -from openmdao.utils.assert_utils import assert_near_equal -from openmdao.utils.testing_utils import use_tempdirs -from aviary.subsystems.propulsion.turboprop_model import TurbopropModel -from aviary.variable_info.options import get_option_defaults -from aviary.utils.functions import get_path -from aviary.interface.methods_for_level2 import AviaryProblem - - -from dymos.transcriptions.transcription_base import TranscriptionBase - -if hasattr(TranscriptionBase, 'setup_polynomial_controls'): - use_new_dymos_syntax = False -else: - use_new_dymos_syntax = True +from aviary.variable_info.variables import Dynamic class PreMissionEngine(om.Group): @@ -40,7 +29,7 @@ def setup(self): nn = self.options['num_nodes'] # add inputs and outputs to interpolator self.add_input( - Dynamic.Mission.MACH, + Dynamic.Atmosphere.MACH, shape=nn, units='unitless', desc='Current flight Mach number', @@ -52,7 +41,7 @@ def setup(self): desc='Current flight altitude', ) self.add_input( - Dynamic.Mission.THROTTLE, + Dynamic.Vehicle.Propulsion.THROTTLE, shape=nn, units='unitless', desc='Current engine throttle', @@ -66,37 +55,37 @@ def setup(self): self.add_input('y', units='m**2', desc='Dummy variable for bus testing') self.add_output( - Dynamic.Mission.THRUST, + Dynamic.Vehicle.Propulsion.THRUST, shape=nn, units='lbf', desc='Current net thrust produced (scaled)', ) self.add_output( - Dynamic.Mission.THRUST_MAX, + Dynamic.Vehicle.Propulsion.THRUST_MAX, shape=nn, units='lbf', desc='Current net thrust produced (scaled)', ) self.add_output( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, shape=nn, units='lbm/s', desc='Current fuel flow rate (scaled)', ) self.add_output( - Dynamic.Mission.ELECTRIC_POWER_IN, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, shape=nn, units='W', desc='Current electric energy rate (scaled)', ) self.add_output( - Dynamic.Mission.NOX_RATE, + Dynamic.Vehicle.Propulsion.NOX_RATE, shape=nn, units='lbm/s', desc='Current NOx emission rate (scaled)', ) self.add_output( - Dynamic.Mission.TEMPERATURE_T4, + Dynamic.Vehicle.Propulsion.TEMPERATURE_T4, shape=nn, units='degR', desc='Current turbine exit temperature', @@ -106,14 +95,14 @@ def setup(self): def compute(self, inputs, outputs): combined_throttle = ( - inputs[Dynamic.Mission.THROTTLE] + inputs['different_throttle'] + inputs[Dynamic.Vehicle.Propulsion.THROTTLE] + inputs['different_throttle'] ) # calculate outputs - outputs[Dynamic.Mission.THRUST] = 10000.0 * combined_throttle - outputs[Dynamic.Mission.THRUST_MAX] = 10000.0 - outputs[Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE] = -10.0 * combined_throttle - outputs[Dynamic.Mission.TEMPERATURE_T4] = 2800.0 + outputs[Dynamic.Vehicle.Propulsion.THRUST] = 10000.0 * combined_throttle + outputs[Dynamic.Vehicle.Propulsion.THRUST_MAX] = 10000.0 + outputs[Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE] = -10.0 * combined_throttle + outputs[Dynamic.Vehicle.Propulsion.TEMPERATURE_T4] = 2800.0 class SimpleTestEngine(EngineModel): @@ -129,28 +118,31 @@ def build_mission(self, num_nodes, aviary_inputs): def get_controls(self, **kwargs): controls_dict = { - "different_throttle": {'units': 'unitless', 'lower': 0.0, 'upper': 0.1}, + 'different_throttle': { + 'units': 'unitless', + 'lower': 0.0, + 'upper': 0.1, + 'control_type': 'polynomial', + 'order': 3, + }, } - if use_new_dymos_syntax: - controls_dict['different_throttle']['control_type'] = 'polynomial' - controls_dict['different_throttle']['order'] = 3 return controls_dict - def get_bus_variables(self): + def get_pre_mission_bus_variables(self, aviary_inputs): bus_dict = { - "y": { - "mission_name": "y", - "units": "m**2", + 'y': { + 'mission_name': 'y', + 'units': 'm**2', }, } return bus_dict def get_initial_guesses(self): initial_guesses_dict = { - "different_throttle": { - "val": 0.05, - "units": "unitless", - "type": "control", + 'different_throttle': { + 'val': 0.05, + 'units': 'unitless', + 'type': 'control', } } return initial_guesses_dict @@ -159,7 +151,6 @@ def get_initial_guesses(self): @use_tempdirs class CustomEngineTest(unittest.TestCase): def test_custom_engine(self): - phase_info = { 'pre_mission': { 'include_takeoff': False, @@ -167,28 +158,25 @@ def test_custom_engine(self): 'optimize_mass': True, }, 'cruise': { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 2, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((10.0, 30.0), "min"), + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 2, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_final': (35000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((10.0, 30.0), 'min'), }, - "initial_guesses": {"time": ([0, 30], "min")}, + 'initial_guesses': {'time': ([0, 30], 'min')}, }, 'post_mission': { 'include_landing': False, @@ -201,24 +189,16 @@ def test_custom_engine(self): # Load aircraft and options data from user # Allow for user overrides here prob.load_inputs( - "models/test_aircraft/aircraft_for_bench_GwFm.csv", + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, engine_builders=[SimpleTestEngine()], ) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() + prob.build_model() - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP", verbosity=0) + prob.add_driver('SLSQP', verbosity=0) prob.add_design_variables() @@ -226,14 +206,10 @@ def test_custom_engine(self): prob.setup() - prob.set_initial_guesses() - prob.final_setup() # check that the different throttle initial guess has been set correctly - initial_guesses = prob.get_val( - 'traj.phases.cruise.controls:different_throttle' - )[0] + initial_guesses = prob.get_val('traj.cruise.controls:different_throttle')[0] assert_near_equal(float(initial_guesses), 0.05) # and run mission @@ -241,7 +217,7 @@ def test_custom_engine(self): tol = 1.0e-4 - assert_near_equal(float(prob.get_val('traj.cruise.rhs_all.y')), 4.0, tol) + assert_near_equal(prob.get_val('traj.cruise.rhs_all.y'), 4.0, tol) if __name__ == '__main__': diff --git a/aviary/subsystems/propulsion/test/test_data_interpolator.py b/aviary/subsystems/propulsion/test/test_data_interpolator.py index cdefe0590d..2c2f7bb622 100644 --- a/aviary/subsystems/propulsion/test/test_data_interpolator.py +++ b/aviary/subsystems/propulsion/test/test_data_interpolator.py @@ -1,27 +1,24 @@ - -import csv import unittest import numpy as np import openmdao.api as om - from openmdao.utils.assert_utils import assert_near_equal -from aviary.subsystems.propulsion.utils import EngineDataInterpolator, EngineModelVariables as keys +from aviary.subsystems.propulsion.utils import EngineDataInterpolator, build_engine_deck +from aviary.subsystems.propulsion.utils import EngineModelVariables as keys from aviary.utils.named_values import NamedValues -from aviary.variable_info.variables import Dynamic -from aviary.validation_cases.validation_data.flops_data.FLOPS_Test_Data import \ - FLOPS_Test_Data -from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.validation_cases.validation_tests import get_flops_inputs +from aviary.variable_info.variables import Aircraft, Dynamic class DataInterpolationTest(unittest.TestCase): def test_data_interpolation(self): tol = 1e-6 - aviary_values = FLOPS_Test_Data['LargeSingleAisle2FLOPS']['inputs'] + aviary_values = get_flops_inputs('LargeSingleAisle2FLOPS') + aviary_values.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) - model = build_engine_deck(aviary_values)[0] + model = build_engine_deck(aviary_values) mach_number = model.data[keys.MACH] altitude = model.data[keys.ALTITUDE] @@ -30,43 +27,58 @@ def test_data_interpolation(self): fuel_flow_rate = model.data[keys.FUEL_FLOW] inputs = NamedValues() - inputs.set_val(Dynamic.Mission.MACH, mach_number) + inputs.set_val(Dynamic.Atmosphere.MACH, mach_number) inputs.set_val(Dynamic.Mission.ALTITUDE, altitude, units='ft') - inputs.set_val(Dynamic.Mission.THROTTLE, throttle) + inputs.set_val(Dynamic.Vehicle.Propulsion.THROTTLE, throttle) - outputs = {Dynamic.Mission.THRUST: 'lbf', - Dynamic.Mission.FUEL_FLOW_RATE: 'lbm/h'} + outputs = { + Dynamic.Vehicle.Propulsion.THRUST: 'lbf', + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE: 'lbm/h', + } test_mach_list = np.linspace(0, 0.85, 5) test_alt_list = np.linspace(0, 40_000, 5) test_throttle_list = np.linspace(0, 1, 5) test_mach, test_alt, test_throttle = np.meshgrid( - test_mach_list, test_alt_list, test_throttle_list) + test_mach_list, test_alt_list, test_throttle_list + ) num_nodes = len(test_mach.flatten()) engine_data = om.IndepVarComp() - engine_data.add_output(Dynamic.Mission.MACH + '_train', - val=np.array(mach_number), - units='unitless') - engine_data.add_output(Dynamic.Mission.ALTITUDE + '_train', - val=np.array(altitude), - units='ft') - engine_data.add_output(Dynamic.Mission.THROTTLE + '_train', - val=np.array(throttle), - units='unitless') - engine_data.add_output(Dynamic.Mission.THRUST + '_train', - val=np.array(thrust), - units='lbf') - engine_data.add_output(Dynamic.Mission.FUEL_FLOW_RATE + '_train', - val=np.array(fuel_flow_rate), - units='lbm/h') - - engine_interpolator = EngineDataInterpolator(num_nodes=num_nodes, - interpolator_inputs=inputs, - interpolator_outputs=outputs, - interpolation_method='slinear') + engine_data.add_output( + Dynamic.Atmosphere.MACH + '_train', + val=np.array(mach_number), + units='unitless', + ) + engine_data.add_output( + Dynamic.Mission.ALTITUDE + '_train', + val=np.array(altitude), + units='ft', + ) + engine_data.add_output( + Dynamic.Vehicle.Propulsion.THROTTLE + '_train', + val=np.array(throttle), + units='unitless', + ) + engine_data.add_output( + Dynamic.Vehicle.Propulsion.THRUST + '_train', + val=np.array(thrust), + units='lbf', + ) + engine_data.add_output( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE + '_train', + val=np.array(fuel_flow_rate), + units='lbm/h', + ) + + engine_interpolator = EngineDataInterpolator( + num_nodes=num_nodes, + interpolator_inputs=inputs, + interpolator_outputs=outputs, + interpolation_method='slinear', + ) prob = om.Problem() prob.model.add_subsystem('engine_data', engine_data, promotes=['*']) @@ -74,87 +86,95 @@ def test_data_interpolation(self): prob.setup() - prob.set_val(Dynamic.Mission.MACH, np.array(test_mach.flatten()), 'unitless') + prob.set_val(Dynamic.Atmosphere.MACH, np.array(test_mach.flatten()), 'unitless') prob.set_val(Dynamic.Mission.ALTITUDE, np.array(test_alt.flatten()), 'ft') - prob.set_val(Dynamic.Mission.THROTTLE, np.array( - test_throttle.flatten()), 'unitless') + prob.set_val( + Dynamic.Vehicle.Propulsion.THROTTLE, + np.array(test_throttle.flatten()), + 'unitless', + ) prob.run_model() - interp_thrust = prob.get_val(Dynamic.Mission.THRUST, 'lbf') - interp_fuel_flow = prob.get_val(Dynamic.Mission.FUEL_FLOW_RATE, 'lbm/h') - - expected_thrust = [0.00000000e+00, 3.54196788e+02, 6.13575369e+03, 1.44653862e+04, - 2.65599096e+04, -3.53133516e+02, 5.80901330e+01, 4.31423671e+03, - 1.15501937e+04, 2.19787604e+04, -4.73948819e+03, -5.95006857e+02, - 3.45048183e+03, 9.91821892e+03, 1.90355375e+04, -5.43678184e+03, - -1.26223518e+03, 2.84220746e+03, 8.67608781e+03, 1.73404730e+04, - -6.15599576e+03, -1.94268249e+03, 1.99628555e+03, 7.48137208e+03, - 1.59182336e+04, -9.08601805e+03, 5.39769591e+02, 5.35677809e+03, - 1.21142135e+04, 2.26706698e+04, -3.58679582e+03, -2.69259549e+01, - 3.89947345e+03, 9.58195492e+03, 1.81800588e+04, -3.78789411e+03, - -4.33551733e+02, 3.14978564e+03, 8.31981857e+03, 1.57364339e+04, - -4.37631447e+03, -9.62213760e+02, 2.53081763e+03, 7.40602072e+03, - 1.43984450e+04, -5.01565861e+03, -1.51671152e+03, 1.87792594e+03, - 6.52078396e+03, 1.34001292e+04, -1.81720361e+04, 7.25342394e+02, - 4.57780250e+03, 9.76304079e+03, 1.87814301e+04, -3.32023617e+03, - -2.63838155e+02, 3.32181093e+03, 7.48346225e+03, 1.35905054e+04, - -1.70547950e+03, -1.07909398e+03, 7.12762853e+02, 5.99809055e+03, - 1.17250860e+04, -3.31584709e+03, -6.62192338e+02, 2.21942781e+03, - 6.13595362e+03, 1.14564170e+04, -3.87532147e+03, -1.09074056e+03, - 1.75956633e+03, 5.56019585e+03, 1.08820247e+04, -2.72580542e+04, - 9.10915198e+02, 3.79882691e+03, 7.41186808e+03, 1.48921903e+04, - -3.05367653e+03, -5.00750355e+02, 2.74414840e+03, 5.38496959e+03, - 9.00095204e+03, 1.42902796e+03, -2.56968919e+03, -3.71509100e+03, - 2.94919637e+03, 7.57037021e+03, -2.70147046e+03, -5.76530275e+02, - 1.71686482e+03, 4.88952762e+03, 8.31589720e+03, -2.80337875e+03, - -7.11794624e+02, 1.54949925e+03, 4.54611557e+03, 8.21531510e+03, - -3.63440722e+04, 1.09648800e+03, 3.01985132e+03, 5.06069537e+03, - 1.10029506e+04, -2.78711688e+03, -7.37662555e+02, 2.16648587e+03, - 3.28647692e+03, 4.41139864e+03, 4.56353542e+03, -4.06028441e+03, - -8.14294484e+03, -9.96978057e+01, 3.41565444e+03, -3.71372809e+03, - -1.50841466e+03, 6.94449058e+02, 3.10611945e+03, 5.29028554e+03, - -2.72709143e+03, -1.02697915e+03, 7.18371174e+02, 2.92355330e+03, - 5.46566595e+03] - - expected_fuel_flow = [0., 784.57285754, 2348.89278057, 5207.14987319, - 9804.78619087, -82.1064164, 767.9051634, 2370.28450696, - 5385.95260343, 10005.6473849, -1257.46789462, 640.93270326, - 2491.41105639, 5619.63531352, 10283.2705124, -1731.30009381, - 479.01364582, 2654.76634078, 5884.39467187, 11678.58301406, - -2209.3392748, 317.43357365, 2677.74875142, 6101.09281052, - 12085.93480086, -1324.33749838, 576.62564909, 2003.50853694, - 4297.49813227, 8920.18884072, -818.75078773, 517.92823002, - 2021.46552219, 4336.76135656, 8303.53636898, -1009.09452361, - 492.92667628, 2113.44966162, 4587.663812, 8727.89498417, - -1361.40028651, 402.52184706, 2214.55868319, 4870.95427868, - 9392.5084187, -1766.02516195, 287.54068271, 2279.99341748, - 5129.0875517, 9982.6035355, -2648.67499676, 368.67844064, - 1658.1242933, 3387.84639134, 8035.59149057, -891.35864118, - 248.9028017, 1628.47391324, 3270.2157656, 5931.5008023, - -346.72644954, 103.68457403, 1132.82096916, 4165.19469995, - 8111.56286758, -991.50047921, 326.03004831, 1774.35102561, - 3857.51388549, 7106.43382334, -1322.7110491, 257.64779176, - 1882.23808354, 4157.08229287, 7879.27227013, -3973.01249515, - 160.73123218, 1312.74004967, 2478.19465042, 7150.99414042, - -963.96649463, -20.12262663, 1235.48230429, 2203.67017464, - 3559.46523561, 662.96289568, -556.75610165, -368.87273293, - 4389.93259999, 9274.46251656, -821.01947442, 190.11665662, - 1293.98507822, 2959.36438862, 5327.19716906, -922.52811183, - 214.43709568, 1454.9322017, 3192.99190078, 5922.9275864, - -5297.34999353, -47.21597627, 967.35580604, 1568.5429095, - 6266.39679027, -1036.57434808, -289.14805495, 842.49069534, - 1137.12458369, 1187.42966893, 1672.6522409, -1217.19677732, - -1870.56643501, 4614.67050003, 10437.36216555, -1385.91734397, - -350.97279954, 683.12046854, 1935.47982391, 3474.12897476, - -1052.57680083, -120.81294188, 835.8741762, 2105.98459735, - 3898.27697684] + interp_thrust = prob.get_val(Dynamic.Vehicle.Propulsion.THRUST, 'lbf') + interp_fuel_flow = prob.get_val(Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE, 'lbm/h') + + # fmt: off + expected_thrust = [ + 0.00000000e+00, 3.55065352e+02, 6.13698222e+03, 1.44665836e+04, + 2.65615937e+04, -3.53119530e+02, 5.78899978e+01, 4.31466665e+03, + 1.15498581e+04, 2.19794592e+04, -4.73864181e+03, -5.94671264e+02, + 3.45070726e+03, 9.92076882e+03, 1.90369137e+04, -5.43519088e+03, + -1.26106424e+03, 2.84361024e+03, 8.67974734e+03, 1.73441197e+04, + -6.15575104e+03, -1.94432076e+03, 1.99215933e+03, 7.48264753e+03, + 1.59228344e+04, -9.08865342e+03, 5.37685968e+02, 5.35583466e+03, + 1.21151072e+04, 2.26660362e+04, -3.58793342e+03, -2.71834035e+01, + 3.89987504e+03, 9.58185277e+03, 1.81789167e+04, -3.78809006e+03, + -4.33378636e+02, 3.15036858e+03, 8.32044337e+03, 1.57379685e+04, + -4.37553297e+03, -9.61693742e+02, 2.53140782e+03, 7.40786480e+03, + 1.44001589e+04, -5.01552946e+03, -1.51762853e+03, 1.87563989e+03, + 6.52178915e+03, 1.34026165e+04, -1.81773068e+04, 7.20306584e+02, + 4.57468711e+03, 9.76363079e+03, 1.87704788e+04, -3.32285440e+03, + -2.63984092e+02, 3.32372050e+03, 7.48270002e+03, 1.35883187e+04, + -1.70555042e+03, -1.07904612e+03, 7.12944116e+02, 5.99814421e+03, + 1.17247455e+04, -3.31587507e+03, -6.62323244e+02, 2.21920540e+03, + 6.13598226e+03, 1.14561982e+04, -3.87530788e+03, -1.09093631e+03, + 1.75912045e+03, 5.56093076e+03, 1.08823986e+04, -2.72659602e+04, + 9.02927199e+02, 3.79353955e+03, 7.41215439e+03, 1.48749213e+04, + -3.05777539e+03, -5.00784780e+02, 2.74756596e+03, 5.38354727e+03, + 8.99772073e+03, 1.42906311e+03, -2.56961554e+03, -3.71517220e+03, + 2.94773975e+03, 7.56546280e+03, -2.70156421e+03, -5.76393414e+02, + 1.71710215e+03, 4.88958815e+03, 8.31651069e+03, -2.80337627e+03, + -7.11736241e+02, 1.54948167e+03, 4.54627324e+03, 8.21492229e+03, + -3.63546137e+04, 1.08554782e+03, 3.01239200e+03, 5.06067799e+03, + 1.09793639e+04, -2.79269638e+03, -7.37585468e+02, 2.17141142e+03, + 3.28439452e+03, 4.40712274e+03, 4.56367663e+03, -4.06018495e+03, + -8.14328851e+03, -1.02664701e+02, 3.40618008e+03, -3.71362507e+03, + -1.50857755e+03, 6.94269750e+02, 3.10639193e+03, 5.29068910e+03, + -2.72727452e+03, -1.02679445e+03, 7.18732279e+02, 2.92409044e+03, + 5.46623231e+03 + ] + + expected_fuel_flow = [ + 0., 784.80638673, 2349.31436014, 5207.56361423, + 9805.42086121, -82.10073461, 767.83063507, 2370.44372031, + 5385.82159643, 10005.94167255, -1257.08525784, 641.08961166, + 2491.53226474, 5620.96913826, 10283.8742694, -1730.5170532, + 479.59595976, 2655.50337931, 5886.47010294, 11680.97519949, + -2209.1681144, 316.50921259, 2675.30699721, 6102.00265701, + 12089.27460107, -1325.03725809, 576.06448338, 2003.17555803, + 4297.86775644, 8918.31003046, -819.17336107, 517.83396036, + 2021.62580201, 4336.71915396, 8302.99796048, -1009.1751228, + 493.00527239, 2113.7188098, 4587.99071223, 8728.77501625, + -1361.01696195, 402.77963737, 2214.86937809, 4872.00105095, + 9393.63638683, -1765.93365194, 287.0228723, 2278.63827718, + 5129.78265006, 9984.41243031, -2650.07451618, 367.32258004, + 1657.03675592, 3388.17189864, 8031.19919972, -892.34016611, + 248.85134815, 1629.24168652, 3269.88662379, 5930.49680185, + -346.75263699, 103.70879831, 1132.91036663, 4165.20338232, + 8111.3038636, -991.5168707, 325.96331497, 1774.23537687, + 3857.53199897, 7106.29757417, -1322.69918947, 257.53653201, + 1881.96955716, 4157.56264311, 7879.55025955, -3975.11177427, + 158.58067669, 1310.8979538, 2478.47604084, 7144.08836897, + -965.50697114, -20.13126406, 1236.85757102, 2203.05409363, + 3557.99564321, 662.99850057, -556.71835084, -368.89137529, + 4389.08545714, 9271.4815779, -821.06449641, 190.18169299, + 1294.09858554, 2959.39577555, 5327.64621324, -922.52712826, + 214.46850819, 1454.92120063, 3193.09136912, 5922.60625685, + -5300.14903236, -50.16122665, 964.75915169, 1568.78018304, + 6256.97753822, -1038.67377618, -289.11387628, 844.47345552, + 1136.22156347, 1185.49448458, 1672.74963814, -1217.14549998, + -1870.69311722, 4612.96753196, 10431.65929221, -1385.86919921, + -351.04997996, 683.04014878, 1935.63927112, 3474.42264817, + -1052.67755001, -120.71167359, 836.07027945, 2106.31322146, + 3898.69137097 + ] assert_near_equal(interp_thrust, expected_thrust, tolerance=tol) assert_near_equal(interp_fuel_flow, expected_fuel_flow, tolerance=tol) -if __name__ == "__main__": +if __name__ == '__main__': # unittest.main() test = DataInterpolationTest() test.test_data_interpolation() diff --git a/aviary/subsystems/propulsion/test/test_engine_deck.py b/aviary/subsystems/propulsion/test/test_engine_deck.py index 93a8136a77..540bb15945 100644 --- a/aviary/subsystems/propulsion/test/test_engine_deck.py +++ b/aviary/subsystems/propulsion/test/test_engine_deck.py @@ -6,19 +6,23 @@ from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.subsystems.propulsion.utils import EngineModelVariables as keys -from aviary.utils.named_values import NamedValues -from aviary.validation_cases.validation_data.flops_data.FLOPS_Test_Data import \ - FLOPS_Test_Data from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.named_values import NamedValues +from aviary.validation_cases.validation_tests import get_flops_inputs +from aviary.variable_info.variables import Aircraft class EngineDeckTest(unittest.TestCase): def test_flight_idle(self): - tol = 1e-6 + # original test data was created with old version of converted GASP engine deck w/o + # rounding, so tol must be lower here for comparison with modern engine + tol = 1e-4 - aviary_values = FLOPS_Test_Data['LargeSingleAisle2FLOPS']['inputs'] + aviary_values = get_flops_inputs('LargeSingleAisle2FLOPS') + # Test data grabbed from LEAPS uses the global throttle approach + aviary_values.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) - model = build_engine_deck(aviary_values)[0] + model = build_engine_deck(aviary_values) expected_mach_number = [] expected_altitude = [] @@ -53,9 +57,9 @@ def test_flight_idle(self): def test_flight_idle_2(self): tol = 1e-6 - aviary_values = FLOPS_Test_Data['LargeSingleAisle1FLOPS']['inputs'] + aviary_values = get_flops_inputs('LargeSingleAisle1FLOPS') - model = build_engine_deck(aviary_values)[0] + model = build_engine_deck(aviary_values) # hardcoded data of processed engine model from LEAPS1 after flight idle # point generation, sorted in Aviary order @@ -79,7 +83,7 @@ def test_flight_idle_2(self): mach_number = model.data[keys.MACH] altitude = model.data[keys.ALTITUDE] - throttle = model.data[keys.THROTTLE] + # throttle = model.data[keys.THROTTLE] thrust = model.data[keys.THRUST] fuel_flow_rate = model.data[keys.FUEL_FLOW] @@ -92,7 +96,7 @@ def test_flight_idle_2(self): def test_load_from_memory(self): tol = 1e-6 - aviary_values = FLOPS_Test_Data['LargeSingleAisle2FLOPS']['inputs'] + aviary_values = get_flops_inputs('LargeSingleAisle2FLOPS') expected_mach_number = [] expected_altitude = [] @@ -122,7 +126,7 @@ def test_load_from_memory(self): mach_number = model.data[keys.MACH] altitude = model.data[keys.ALTITUDE] - throttle = model.data[keys.THROTTLE] + # throttle = model.data[keys.THROTTLE] thrust = model.data[keys.THRUST] fuel_flow_rate = model.data[keys.FUEL_FLOW] @@ -132,6 +136,16 @@ def test_load_from_memory(self): assert_near_equal(thrust, expected_thrust, tolerance=tol) assert_near_equal(fuel_flow_rate, expected_fuel_flow_rate, tolerance=tol) + def test_error_message(self): + aviary_values = get_flops_inputs('LargeSingleAisle1FLOPS') + aviary_values.set_val(Aircraft.Engine.INTERPOLATION_SORT, 'junk', units='unitless') + + msg = 'EngineDeck : Invalid value of Aircraft.Engine.INTERPOLATION_SORT.' + msg += ' Expected "altitude" or "mach", but found "junk".' + with self.assertRaises(ValueError) as cm: + build_engine_deck(aviary_values) + self.assertEqual(str(cm.exception), msg) + -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/propulsion/test/test_engine_scaling.py b/aviary/subsystems/propulsion/test/test_engine_scaling.py index 75daf047ba..5a9435db15 100644 --- a/aviary/subsystems/propulsion/test/test_engine_scaling.py +++ b/aviary/subsystems/propulsion/test/test_engine_scaling.py @@ -6,11 +6,12 @@ from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.subsystems.propulsion.engine_scaling import EngineScaling +from aviary.subsystems.propulsion.utils import EngineModelVariables from aviary.utils.aviary_values import AviaryValues -from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.subsystems.propulsion.utils import EngineModelVariables +from aviary.utils.preprocessors import preprocess_propulsion +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings class EngineScalingTest(unittest.TestCase): @@ -21,10 +22,11 @@ def test_case(self): nn = 4 count = 1 - filename = 'models/engines/turbofan_28k.deck' + filename = 'models/engines/turbofan_28k.csv' filename = get_path(filename) options = AviaryValues() + options.set_val(Settings.VERBOSITY, 0) options.set_val(Aircraft.Engine.DATA_FILE, filename) options.set_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, 0.9) # make supersonic scaling factor extremely high so it is obvious if it gets used @@ -56,31 +58,27 @@ def test_case(self): self.prob.model.add_subsystem( 'engine', - EngineScaling( - num_nodes=nn, aviary_options=options, engine_variables=engine_variables - ), + EngineScaling(num_nodes=nn, engine_variables=engine_variables), promotes=['*'], ) + + setup_model_options(self.prob, options) + self.prob.setup(force_alloc_complex=True) - self.prob.set_val( - 'thrust_net_unscaled', np.ones([nn, count]) * 1000, units='lbf' - ) - self.prob.set_val( - 'fuel_flow_rate_unscaled', np.ones([nn, count]) * 100, units='lbm/h' - ) + + self.prob.set_val('thrust_net_unscaled', np.ones([nn, count]) * 1000, units='lbf') + self.prob.set_val('fuel_flow_rate_unscaled', np.ones([nn, count]) * 100, units='lbm/h') self.prob.set_val('nox_rate_unscaled', np.ones([nn, count]) * 10, units='lbm/h') - self.prob.set_val( - Dynamic.Mission.MACH, np.linspace(0, 0.75, nn), units='unitless' - ) + self.prob.set_val(Dynamic.Atmosphere.MACH, np.linspace(0, 0.75, nn), units='unitless') self.prob.set_val( Aircraft.Engine.SCALE_FACTOR, options.get_val(Aircraft.Engine.SCALE_FACTOR) ) self.prob.run_model() - thrust = self.prob.get_val(Dynamic.Mission.THRUST) - fuel_flow = self.prob.get_val(Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE) - nox_rate = self.prob.get_val(Dynamic.Mission.NOX_RATE) + thrust = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST) + fuel_flow = self.prob.get_val(Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE) + nox_rate = self.prob.get_val(Dynamic.Vehicle.Propulsion.NOX_RATE) # exit_area = self.prob.get_val(Dynamic.Mission.EXIT_AREA) thrust_expected = np.array([900.0, 900.0, 900.0, 900]) @@ -93,9 +91,9 @@ def test_case(self): assert_near_equal(fuel_flow, fuel_flow_expected, tolerance=1e-10) assert_near_equal(nox_rate, nox_rate_expected, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-11, rtol=1e-10) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/propulsion/test/test_engine_sizing.py b/aviary/subsystems/propulsion/test/test_engine_sizing.py index b273050a99..f7313f7f74 100644 --- a/aviary/subsystems/propulsion/test/test_engine_sizing.py +++ b/aviary/subsystems/propulsion/test/test_engine_sizing.py @@ -13,16 +13,15 @@ class EngineSizingTest1(unittest.TestCase): def setUp(self): - self.prob = om.Problem(model=om.Group()) + self.prob = om.Problem() def test_case_multiengine(self): - filename = 'models/engines/turbofan_28k.deck' + filename = 'models/engines/turbofan_28k.csv' filename = get_path(filename) options = AviaryValues() options.set_val(Aircraft.Engine.DATA_FILE, filename) options.set_val(Aircraft.Engine.SCALE_PERFORMANCE, True) - options.set_val(Aircraft.Engine.SCALE_FACTOR, 1.0) options.set_val(Aircraft.Engine.GENERATE_FLIGHT_IDLE, True) options.set_val(Aircraft.Engine.IGNORE_NEGATIVE_THRUST, False) options.set_val(Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION, 0.0) @@ -31,31 +30,33 @@ def test_case_multiengine(self): options.set_val(Aircraft.Engine.GEOPOTENTIAL_ALT, False) engine = EngineDeck(name='engine', options=options) - options.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, engine.get_val( - Aircraft.Engine.REFERENCE_SLS_THRUST, 'lbf'), 'lbf') # options.set_val(Aircraft.Engine.SCALE_PERFORMANCE, False) # engine2 = EngineDeck(name='engine2', options=options) # preprocess_propulsion(options, [engine, engine2]) - self.prob.model.add_subsystem('engine', SizeEngine( - aviary_options=options), promotes=['*']) + ref_thrust = engine.get_item(Aircraft.Engine.REFERENCE_SLS_THRUST) + options = { + Aircraft.Engine.SCALE_PERFORMANCE: True, + Aircraft.Engine.REFERENCE_SLS_THRUST: ref_thrust, + } + + self.prob.model.add_subsystem('engine', SizeEngine(**options), promotes=['*']) + self.prob.setup(force_alloc_complex=True) - self.prob.set_val( - Aircraft.Engine.SCALED_SLS_THRUST, - np.array([15250]), - units='lbf') + + self.prob.set_val(Aircraft.Engine.SCALE_FACTOR, np.array([0.52716908])) self.prob.run_model() - scale_factor = self.prob.get_val(Aircraft.Engine.SCALE_FACTOR) + sls_thrust = self.prob.get_val(Aircraft.Engine.SCALED_SLS_THRUST, units='lbf') - expected_scale_factor = np.array([0.52716908]) + expected_sls_thrust = np.array([15250]) - assert_near_equal(scale_factor, expected_scale_factor, tolerance=1e-8) + assert_near_equal(sls_thrust, expected_sls_thrust, tolerance=1e-8) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-12, rtol=1e-10) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/propulsion/test/test_hamilton_standard.py b/aviary/subsystems/propulsion/test/test_hamilton_standard.py deleted file mode 100644 index 515ce449b3..0000000000 --- a/aviary/subsystems/propulsion/test/test_hamilton_standard.py +++ /dev/null @@ -1,194 +0,0 @@ -import unittest -import numpy as np -import openmdao.api as om - -from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal - -from aviary.subsystems.propulsion.propeller.hamilton_standard import ( - HamiltonStandard, PreHamiltonStandard, PostHamiltonStandard, -) -from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft, Dynamic -from aviary.constants import RHO_SEA_LEVEL_ENGLISH - - -class PreHamiltonStandardTest(unittest.TestCase): - """ - Test computation in PreHamiltonStandard class. - """ - - def setUp(self): - prob = om.Problem() - - num_nodes = 3 - - prob.model.add_subsystem( - 'prehs', - PreHamiltonStandard(num_nodes=num_nodes), - promotes_inputs=['*'], - promotes_outputs=["*"], - ) - - prob.setup() - self.prob = prob - - def test_preHS(self): - prob = self.prob - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10, units="ft") - prob.set_val(Dynamic.Mission.PROPELLER_TIP_SPEED, - [700.0, 750.0, 800.0], units="ft/s") - prob.set_val(Dynamic.Mission.SHAFT_POWER, [1850.0, 1850.0, 900.0], units="hp") - prob.set_val(Dynamic.Mission.DENSITY, - [0.00237717, 0.00237717, 0.00106526], units="slug/ft**3") - prob.set_val(Dynamic.Mission.VELOCITY, [100.0, 100, 100], units="ft/s") - prob.set_val(Dynamic.Mission.SPEED_OF_SOUND, - [661.46474547, 661.46474547, 601.93668333], units="knot") - - prob.run_model() - - tol = 5e-4 - assert_near_equal(prob.get_val("power_coefficient"), - [0.3871, 0.3147, 0.2815], tolerance=tol) - assert_near_equal( - prob.get_val("advance_ratio"), - [0.44879895, 0.41887902, 0.39269908], - tolerance=tol, - ) - assert_near_equal( - prob.get_val("tip_mach"), [0.6270004, 0.67178614, 0.78743671], tolerance=tol - ) - - partial_data = prob.check_partials( - out_stream=None, - compact_print=True, - show_only_incorrect=True, - form='central', - method="fd", - minimum_step=1e-12, - abs_err_tol=5.0e-4, - rel_err_tol=5.0e-5, - ) - assert_check_partials(partial_data, atol=0.0003, rtol=7e-7) - - -class HamiltonStandardTest(unittest.TestCase): - """ - Test computation in HamiltonStandard class. - """ - - def setUp(self): - options = get_option_defaults() - options.set_val(Aircraft.Engine.NUM_PROPELLER_BLADES, val=4, units='unitless') - - prob = om.Problem() - - num_nodes = 3 - - prob.model.add_subsystem( - 'hs', - HamiltonStandard(num_nodes=num_nodes, aviary_options=options), - promotes_inputs=['*'], - promotes_outputs=["*"], - ) - - prob.setup() - self.prob = prob - - def test_HS(self): - prob = self.prob - prob.set_val("power_coefficient", [0.2352, 0.2352, 0.2553], units="unitless") - prob.set_val("advance_ratio", [0.0066, 0.8295, 1.9908], units="unitless") - prob.set_val(Dynamic.Mission.MACH, [0.001509, 0.1887, 0.4976], units="unitless") - prob.set_val("tip_mach", [1.2094, 1.2094, 1.3290], units="unitless") - prob.set_val(Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 114.0, units="unitless") - prob.set_val(Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, - 0.5, units="unitless") - - prob.run_model() - - tol = 5e-4 - assert_near_equal(prob.get_val("thrust_coefficient"), - [0.2763, 0.2052, 0.1158], tolerance=tol) - assert_near_equal(prob.get_val("comp_tip_loss_factor"), - [1.0, 1.0, 0.9818], tolerance=tol) - - partial_data = prob.check_partials( - out_stream=None, - compact_print=True, - show_only_incorrect=True, - form='central', - method="fd", - minimum_step=1e-12, - abs_err_tol=5.0e-4, - rel_err_tol=5.0e-5, - ) - assert_check_partials(partial_data, atol=1e-5, rtol=1e-5) - - -class PostHamiltonStandardTest(unittest.TestCase): - """ - Test computation in PostHamiltonStandard class. - """ - - def setUp(self): - prob = om.Problem() - - num_nodes = 3 - - prob.model.add_subsystem( - 'posths', - PostHamiltonStandard(num_nodes=num_nodes), - promotes_inputs=['*'], - promotes_outputs=["*"], - ) - - prob.setup() - self.prob = prob - - def test_postHS(self): - prob = self.prob - prob.set_val("power_coefficient", [0.3871, 0.3147, 0.2815], units="unitless") - prob.set_val("advance_ratio", [0.4494, 0.4194, 0.3932], units="unitless") - prob.set_val(Dynamic.Mission.PROPELLER_TIP_SPEED, - [700.0, 750.0, 800.0], units="ft/s") - prob.set_val( - Dynamic.Mission.DENSITY, - np.array([1.0001, 1.0001, 0.4482]) * RHO_SEA_LEVEL_ENGLISH, - units="slug/ft**3", - ) - prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10.0, units="ft") - prob.set_val("thrust_coefficient", [0.2765, 0.2052, 0.1158], units="unitless") - prob.set_val("install_loss_factor", [0.0133, 0.0200, 0.0325], units="unitless") - prob.set_val("comp_tip_loss_factor", [1.0, 1.0, 0.9819], units="unitless") - - prob.run_model() - - tol = 5e-4 - assert_near_equal(prob.get_val("thrust_coefficient_comp_loss"), - [0.2765, 0.2052, 0.1137], tolerance=tol) - assert_near_equal(prob.get_val(Dynamic.Mission.THRUST), - [3218.9508, 2723.7294, 759.7543], tolerance=tol) - assert_near_equal(prob.get_val("propeller_efficiency"), - [0.321, 0.2735, 0.1588], tolerance=tol) - assert_near_equal(prob.get_val("install_efficiency"), - [0.3167, 0.2680, 0.15378], tolerance=tol) - - partial_data = prob.check_partials( - out_stream=None, - compact_print=True, - show_only_incorrect=True, - form='central', - method="fd", - minimum_step=1e-12, - abs_err_tol=5.0e-4, - rel_err_tol=5.0e-5, - ) - assert_check_partials(partial_data, atol=5e-4, rtol=1e-4) - - -if __name__ == "__main__": - unittest.main() - # test = HamiltonStandardTest() - # test.setUp() - # test.test_HS() diff --git a/aviary/subsystems/propulsion/test/test_propeller_map.py b/aviary/subsystems/propulsion/test/test_propeller_map.py deleted file mode 100644 index f3b2ce3a4b..0000000000 --- a/aviary/subsystems/propulsion/test/test_propeller_map.py +++ /dev/null @@ -1,86 +0,0 @@ -import numpy as np -import unittest - -from openmdao.components.interp_util.interp_semi import InterpNDSemi -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.subsystems.propulsion.propeller.propeller_map import PropellerMap -from aviary.subsystems.propulsion.utils import PropellerModelVariables as keys -from aviary.variable_info.enums import OutMachType -from aviary.variable_info.options import get_option_defaults -from aviary.variable_info.variables import Aircraft - - -class PropellerMapTest(unittest.TestCase): - """ - Test propeller map using OpenMDAO interpolator to make sure - it provides correct error and gets correct Mach type. - """ - - def test_general_aviation(self): - # The case when prop_type is helical_mach. - tol = 0.005 - aviary_options = get_option_defaults() - prop_file_path = 'models/propellers/general_aviation.prop' - aviary_options.set_val( - Aircraft.Engine.PROPELLER_DATA_FILE, val=prop_file_path, units='unitless') - aviary_options.set_val( - Aircraft.Engine.INTERPOLATION_METHOD, val='slinear', units='unitless') - aviary_options.set_val( - Aircraft.Engine.USE_PROPELLER_MAP, val=True, units='unitless') - prop_model = PropellerMap('prop', aviary_options) - prop_model.build_propeller_interpolator(3, aviary_options) - - x1 = prop_model.data[keys.MACH] - x2 = prop_model.data[keys.CP] - x3 = prop_model.data[keys.J] - y = prop_model.data[keys.CT] - grid = np.array([x1, x2, x3]).T - interp = InterpNDSemi(grid, y, method='slinear') - # Mach, CP, J from general_aviation, expected CT: 0.0934 - x = np.array([0.8, 0.1, 0.75]) - f, df_dx = interp.interpolate(x, compute_derivative=True) - assert_near_equal(f, 0.0934, tolerance=tol) - - def test_propfan(self): - # The case when prop_type is mach. - tol = 0.005 - aviary_options = get_option_defaults() - prop_file_path = 'models/propellers/PropFan.prop' - aviary_options.set_val( - Aircraft.Engine.PROPELLER_DATA_FILE, val=prop_file_path, units='unitless') - aviary_options.set_val( - Aircraft.Engine.INTERPOLATION_METHOD, val='slinear', units='unitless') - aviary_options.set_val( - Aircraft.Engine.USE_PROPELLER_MAP, val=True, units='unitless') - prop_model = PropellerMap('prop', aviary_options) - prop_model.build_propeller_interpolator(3, aviary_options) - - x1 = prop_model.data[keys.MACH] - x2 = prop_model.data[keys.CP] - x3 = prop_model.data[keys.J] - y = prop_model.data[keys.CT] - grid = np.array([x1, x2, x3]).T - interp = InterpNDSemi(grid, y, method='slinear') - # Mach, CP, J from PropFan, expected CT: 0.095985 - x = np.array([0.25, 0.0465, 0.2]) - f, df_dx = interp.interpolate(x, compute_derivative=True) - assert_near_equal(f, 0.095985, tolerance=tol) - - def test_mach_type(self): - # Test reading prop_type from .prop file. - aviary_options = get_option_defaults() - prop_file_path = 'models/propellers/general_aviation.prop' - aviary_options.set_val( - Aircraft.Engine.PROPELLER_DATA_FILE, val=prop_file_path, units='unitless') - aviary_options.set_val( - Aircraft.Engine.INTERPOLATION_METHOD, val='slinear', units='unitless') - aviary_options.set_val( - Aircraft.Engine.USE_PROPELLER_MAP, val=True, units='unitless') - prop_model = PropellerMap('prop', aviary_options) - out_mach_type = prop_model.read_and_set_mach_type(prop_file_path) - self.assertEqual(out_mach_type, OutMachType.HELICAL_MACH) - - -if __name__ == "__main__": - unittest.main() diff --git a/aviary/subsystems/propulsion/test/test_propulsion_mission.py b/aviary/subsystems/propulsion/test/test_propulsion_mission.py index b334b10d31..88efdf42f3 100644 --- a/aviary/subsystems/propulsion/test/test_propulsion_mission.py +++ b/aviary/subsystems/propulsion/test/test_propulsion_mission.py @@ -7,14 +7,14 @@ from packaging import version from aviary.subsystems.propulsion.engine_deck import EngineDeck -from aviary.subsystems.propulsion.propulsion_mission import ( - PropulsionMission, PropulsionSum) +from aviary.subsystems.propulsion.propulsion_mission import PropulsionMission, PropulsionSum +from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.aviary_values import AviaryValues -from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path +from aviary.utils.preprocessors import preprocess_propulsion from aviary.validation_cases.validation_tests import get_flops_inputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings -from aviary.subsystems.propulsion.utils import build_engine_deck class PropulsionMissionTest(unittest.TestCase): @@ -23,114 +23,158 @@ def setUp(self): self.options = AviaryValues() self.options.set_val(Settings.VERBOSITY, 0) - @unittest.skipIf(version.parse(openmdao.__version__) < version.parse("3.26"), "Skipping due to OpenMDAO version being too low (<3.26)") + @unittest.skipIf( + version.parse(openmdao.__version__) < version.parse('3.26'), + 'Skipping due to OpenMDAO version being too low (<3.26)', + ) def test_case_1(self): # 'clean' test using GASP-derived engine deck nn = 20 - filename = get_path( - 'models/engines/turbofan_24k_1.deck') + filename = get_path('models/engines/turbofan_24k_1.csv') options = self.options options.set_val(Aircraft.Engine.DATA_FILE, filename) + options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) options.set_val(Aircraft.Engine.NUM_ENGINES, 2) options.set_val(Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, 1.0) options.set_val(Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER, 1.0) options.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, 0.0) options.set_val(Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM, 1.0) options.set_val(Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, 0.0, units='lbm/h') - options.set_val(Aircraft.Engine.SCALE_PERFORMANCE, True) options.set_val(Mission.Summary.FUEL_FLOW_SCALER, 1.0) options.set_val(Aircraft.Engine.SCALE_FACTOR, 0.5) - options.set_val(Aircraft.Engine.GENERATE_FLIGHT_IDLE, False) options.set_val(Aircraft.Engine.IGNORE_NEGATIVE_THRUST, False) - options.set_val(Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION, 0.0) - options.set_val(Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION, 1.0) - options.set_val(Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION, 0.08) - options.set_val(Aircraft.Engine.GEOPOTENTIAL_ALT, False) - options.set_val(Aircraft.Engine.INTERPOLATION_METHOD, 'slinear') engine = EngineDeck(options=options) preprocess_propulsion(options, [engine]) self.prob.model = PropulsionMission( - num_nodes=nn, aviary_options=options, engine_models=[engine]) - - IVC = om.IndepVarComp(Dynamic.Mission.MACH, - np.linspace(0, 0.8, nn), - units='unitless') - IVC.add_output(Dynamic.Mission.ALTITUDE, - np.linspace(0, 40000, nn), - units='ft') - IVC.add_output(Dynamic.Mission.THROTTLE, - np.linspace(1, 0.7, nn), - units='unitless') + num_nodes=nn, aviary_options=options, engine_models=[engine] + ) + + IVC = om.IndepVarComp(Dynamic.Atmosphere.MACH, np.linspace(0, 0.8, nn), units='unitless') + IVC.add_output(Dynamic.Mission.ALTITUDE, np.linspace(0, 40000, nn), units='ft') + IVC.add_output( + Dynamic.Vehicle.Propulsion.THROTTLE, + np.linspace(1, 0.7, nn), + units='unitless', + ) self.prob.model.add_subsystem('IVC', IVC, promotes=['*']) + setup_model_options(self.prob, options) + self.prob.setup(force_alloc_complex=True) - self.prob.set_val(Aircraft.Engine.SCALE_FACTOR, options.get_val( - Aircraft.Engine.SCALE_FACTOR), units='unitless') + self.prob.set_val( + Aircraft.Engine.SCALE_FACTOR, + options.get_val(Aircraft.Engine.SCALE_FACTOR), + units='unitless', + ) self.prob.run_model() - thrust = self.prob.get_val(Dynamic.Mission.THRUST_TOTAL, units='lbf') + thrust = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, units='lbf') fuel_flow = self.prob.get_val( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h') - - expected_thrust = np.array([26559.90955398, 24186.4637312, 21938.65874407, - 19715.77939805, 17507.00655484, 15461.29892872, - 13781.56317005, 12281.64477782, 10975.64977233, - 9457.34056514, 7994.85977229, 7398.22905691, - 7147.50679938, 6430.71565916, 5774.57932944, - 5165.15558103, 4583.1380952, 3991.15088149, - 3338.98524687, 2733.56788119]) - - expected_fuel_flow = np.array([-14707.1792863, -14065.2831058, -13383.11681516, - -12535.21693425, -11524.37848035, -10514.44342419, - -9697.03653898, -8936.66146966, -8203.85487648, - -8447.54167564, -8705.14277314, -7470.29404109, - -5980.15247732, -5493.23821772, -5071.79842346, - -4660.12833977, -4260.89619679, -3822.61002621, - -3344.41332545, -2889.68646353]) + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' + ) + + expected_thrust = np.array( + [ + 26561.59369395, + 24186.86894359, + 21938.27488056, + 19715.05735655, + 17506.16718894, + 15460.34459449, + 13780.48894973, + 12280.8193203, + 10975.41682925, + 9457.56468145, + 7995.21902953, + 7398.69940308, + 7148.11078578, + 6431.41457704, + 5775.06520451, + 5165.40974506, + 4583.11663348, + 3991.15103423, + 3339.07858092, + 2733.73087418, + ] + ) + + expected_fuel_flow = np.array( + [ + -14708.13129181, + -14065.48817451, + -13382.86563425, + -12534.77028836, + -11523.83568308, + -10513.77300372, + -9696.27706444, + -8936.08244404, + -8203.69933068, + -8447.76373904, + -8705.57372767, + -7470.81543322, + -5980.73136927, + -5493.90702754, + -5072.25036487, + -4660.36809371, + -4260.86577106, + -3822.5941721, + -3344.49786121, + -2889.82801889, + ] + ) assert_near_equal(thrust, expected_thrust, tolerance=1e-10) assert_near_equal(fuel_flow, expected_fuel_flow, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_propulsion_sum(self): nn = 2 - options = self.options - options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([3, 2])) + options = { + Aircraft.Engine.NUM_ENGINES: np.array([3, 2]), + } self.prob.model = om.Group() - self.prob.model.add_subsystem('propsum', - PropulsionSum(num_nodes=nn, - aviary_options=options), - promotes=['*']) + self.prob.model.add_subsystem( + 'propsum', PropulsionSum(num_nodes=nn, **options), promotes=['*'] + ) self.prob.setup(force_alloc_complex=True) - self.prob.set_val(Dynamic.Mission.THRUST, np.array( - [[500.4, 423.001], [325, 6780]])) - self.prob.set_val(Dynamic.Mission.THRUST_MAX, - np.array([[602.11, 3554], [100, 9000]])) - self.prob.set_val(Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, - np.array([[123, -221.44], [-765.2, -1]])) - self.prob.set_val(Dynamic.Mission.ELECTRIC_POWER_IN, - np.array([[3.01, -12], [484.2, 8123]])) - self.prob.set_val(Dynamic.Mission.NOX_RATE, - np.array([[322, 4610], [1.54, 2.844]])) + self.prob.set_val( + Dynamic.Vehicle.Propulsion.THRUST, np.array([[500.4, 423.001], [325, 6780]]) + ) + self.prob.set_val( + Dynamic.Vehicle.Propulsion.THRUST_MAX, + np.array([[602.11, 3554], [100, 9000]]), + ) + self.prob.set_val( + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, + np.array([[123, -221.44], [-765.2, -1]]), + ) + self.prob.set_val( + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, np.array([[3.01, -12], [484.2, 8123]]) + ) + self.prob.set_val( + Dynamic.Vehicle.Propulsion.NOX_RATE, np.array([[322, 4610], [1.54, 2.844]]) + ) self.prob.run_model() - thrust = self.prob.get_val(Dynamic.Mission.THRUST_TOTAL, units='lbf') - thrust_max = self.prob.get_val(Dynamic.Mission.THRUST_MAX_TOTAL, units='lbf') + thrust = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, units='lbf') + thrust_max = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, units='lbf') fuel_flow = self.prob.get_val( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lb/h') + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lb/h' + ) electric_power_in = self.prob.get_val( - Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL, units='kW') - nox = self.prob.get_val(Dynamic.Mission.NOX_RATE_TOTAL, units='lb/h') + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, units='kW' + ) + nox = self.prob.get_val(Dynamic.Vehicle.Propulsion.NOX_RATE_TOTAL, units='lb/h') expected_thrust = np.array([2347.202, 14535]) expected_thrust_max = np.array([8914.33, 18300]) @@ -144,7 +188,7 @@ def test_propulsion_sum(self): assert_near_equal(electric_power_in, expected_electric_power_in, tolerance=1e-12) assert_near_equal(nox, expected_nox, tolerance=1e-12) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_case_multiengine(self): @@ -153,65 +197,93 @@ def test_case_multiengine(self): options = get_flops_inputs('LargeSingleAisle2FLOPS') options.set_val(Settings.VERBOSITY, 0) + options.set_val(Aircraft.Engine.GLOBAL_THROTTLE, True) - engine = build_engine_deck(options)[0] - engine2 = build_engine_deck(options)[0] + engine = build_engine_deck(options) + engine2 = build_engine_deck(options) engine2.name = 'engine2' engine_models = [engine, engine2] preprocess_propulsion(options, engine_models=engine_models) - self.prob.model = PropulsionMission( - num_nodes=20, aviary_options=options, engine_models=engine_models) + model = self.prob.model + prop = PropulsionMission( + num_nodes=20, + aviary_options=options, + engine_models=engine_models, + ) + model.add_subsystem('core_propulsion', prop, promotes=['*']) - self.prob.model.add_subsystem(Dynamic.Mission.MACH, - om.IndepVarComp(Dynamic.Mission.MACH, - np.linspace(0, 0.85, nn), - units='unitless'), - promotes=['*']) + self.prob.model.add_subsystem( + Dynamic.Atmosphere.MACH, + om.IndepVarComp(Dynamic.Atmosphere.MACH, np.linspace(0, 0.85, nn), units='unitless'), + promotes=['*'], + ) self.prob.model.add_subsystem( Dynamic.Mission.ALTITUDE, - om.IndepVarComp( - Dynamic.Mission.ALTITUDE, - np.linspace(0, 40000, nn), - units='ft'), - promotes=['*']) + om.IndepVarComp(Dynamic.Mission.ALTITUDE, np.linspace(0, 40000, nn), units='ft'), + promotes=['*'], + ) throttle = np.linspace(1.0, 0.6, nn) self.prob.model.add_subsystem( - Dynamic.Mission.THROTTLE, om.IndepVarComp(Dynamic.Mission.THROTTLE, np.vstack((throttle, throttle)).transpose(), units='unitless'), promotes=['*']) + Dynamic.Vehicle.Propulsion.THROTTLE, + om.IndepVarComp( + Dynamic.Vehicle.Propulsion.THROTTLE, + np.vstack((throttle, throttle)).transpose(), + units='unitless', + ), + promotes=['*'], + ) + + setup_model_options(self.prob, options, engine_models=engine_models) self.prob.setup(force_alloc_complex=True) - self.prob.set_val(Aircraft.Engine.SCALE_FACTOR, [0.975], units='unitless') + self.prob.set_val(Aircraft.Engine.SCALE_FACTOR, [0.975, 0.975], units='unitless') self.prob.run_model() - thrust = self.prob.get_val(Dynamic.Mission.THRUST_TOTAL, units='lbf') + thrust = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST_TOTAL, units='lbf') fuel_flow = self.prob.get_val( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h') - nox_rate = self.prob.get_val(Dynamic.Mission.NOX_RATE_TOTAL, units='lbm/h') - - expected_thrust = np.array([103583.64726051, 92899.15059987, 82826.62014006, 73006.74478288, - 63491.73778033, 55213.71927899, 48317.05801159, 42277.98362824, - 36870.43915515, 29716.58670587, 26271.29434561, 24680.25359966, - 22043.65303425, 19221.1253513, 16754.1861966, 14405.43665682, - 12272.31373152, 10141.72397926, 7869.3816548, 5792.62871788]) - - expected_fuel_flow = np.array([-38238.66614438, -36078.76817864, -33777.65206416, -31057.41872898, - -28036.92997813, -25279.48301301, -22902.98616678, -20749.08916211, - -19058.23299911, -19972.32193796, -17701.86829646, -14370.68121827, - -12584.1724091, -11320.06786905, -10192.11938107, -9100.08365082, - -8100.4835652, -7069.62950088, -5965.78834865, -4914.94081538]) + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, units='lbm/h' + ) + nox_rate = self.prob.get_val(Dynamic.Vehicle.Propulsion.NOX_RATE_TOTAL, units='lbm/h') + + # block auto-formatting of tables + # fmt: off + expected_thrust = np.array( + [ + 103590.21540641, 92900.83040046, 82825.70799328, 73005.10411666, 63489.74235503, + 55210.75770546, 48313.84938232, 42275.86826606, 36870.28719096, 29717.82022574, + 26272.78176894, 24682.2638022, 22044.68474877, 19221.64939296, 16753.74585058, + 14404.83725986, 12273.31369208, 10143.03504195, 7869.72781898, 5794.48172967 + ] + ) + + expected_fuel_flow = np.array( + [ + -38241.14135872, -36079.34764117, -33777.26289895, -31056.78302442, -28036.07645153, + -25278.09940003, -22901.48613868, -20748.0936975, -19058.14550597, -19973.09349768, + -17702.71563899, -14371.77422339, -12584.74775338, -11320.39115751, -10191.86597545, + -9099.77210032, -8101.06611515, -7070.33673028, -5965.98165626, -4915.97493174 + ] + ) expected_nox_rate = np.array( - [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) + [ + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + ] + ) + + # fmt: on assert_near_equal(thrust, expected_thrust, tolerance=1e-10) assert_near_equal(fuel_flow, expected_fuel_flow, tolerance=1e-10) assert_near_equal(nox_rate, expected_nox_rate, tolerance=1e-9) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/propulsion/test/test_propulsion_premission.py b/aviary/subsystems/propulsion/test/test_propulsion_premission.py index a56a17d3a0..51950e9fe4 100644 --- a/aviary/subsystems/propulsion/test/test_propulsion_premission.py +++ b/aviary/subsystems/propulsion/test/test_propulsion_premission.py @@ -4,14 +4,16 @@ import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.propulsion.propulsion_premission import ( - PropulsionPreMission, PropulsionSum) -from aviary.utils.aviary_values import AviaryValues +from aviary.models.aircraft.multi_engine_single_aisle.multi_engine_single_aisle_data import ( + engine_1_inputs, + engine_2_inputs, +) +from aviary.subsystems.propulsion.propulsion_premission import PropulsionPreMission, PropulsionSum from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.preprocessors import preprocess_options from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.models.multi_engine_single_aisle.multi_engine_single_aisle_data import engine_1_inputs, engine_2_inputs +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Settings -from aviary.utils.preprocessors import preprocess_options class PropulsionPreMissionTest(unittest.TestCase): @@ -23,40 +25,53 @@ def test_case(self): options.set_val(Settings.VERBOSITY, 0) options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([2])) - self.prob.model = PropulsionPreMission(aviary_options=options, - engine_models=build_engine_deck(options)) + self.prob.model = PropulsionPreMission( + aviary_options=options, engine_models=[build_engine_deck(options)] + ) + + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, np.ones(1)) + + setup_model_options(self.prob, options) self.prob.setup(force_alloc_complex=True) - self.prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, options.get_val( - Aircraft.Engine.SCALED_SLS_THRUST, units='lbf')) + # self.prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, options.get_val( + # Aircraft.Engine.SCALED_SLS_THRUST, units='lbf')) self.prob.run_model() sls_thrust = self.prob.get_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST) - expected_sls_thrust = np.array([54602.]) + expected_sls_thrust = np.array([54602.0]) assert_near_equal(sls_thrust, expected_sls_thrust, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_multi_engine(self): options = get_flops_inputs('MultiEngineSingleAisle') options.set_val(Settings.VERBOSITY, 0) - engine1 = build_engine_deck(engine_1_inputs)[0] - engine2 = build_engine_deck(engine_2_inputs)[0] + engine1 = build_engine_deck(engine_1_inputs) + engine2 = build_engine_deck(engine_2_inputs) engine_models = [engine1, engine2] - preprocess_options(options, engine_models=engine_models) - self.prob.model = PropulsionPreMission(aviary_options=options, - engine_models=engine_models) + setup_model_options(self.prob, options, engine_models=engine_models) + + model = self.prob.model + prop = PropulsionPreMission(aviary_options=options, engine_models=engine_models) + model.add_subsystem('core_propulsion', prop, promotes=['*']) + + setup_model_options(self.prob, options, engine_models=engine_models) + + self.prob.model.set_input_defaults(Aircraft.Engine.SCALE_FACTOR, np.ones(2) * 0.5) self.prob.setup(force_alloc_complex=True) - self.prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, options.get_val( - Aircraft.Engine.SCALED_SLS_THRUST, units='lbf')) + self.prob.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, + options.get_val(Aircraft.Engine.SCALED_SLS_THRUST, units='lbf'), + ) self.prob.run_model() @@ -66,37 +81,36 @@ def test_multi_engine(self): assert_near_equal(sls_thrust, expected_sls_thrust, tolerance=1e-10) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) def test_propulsion_sum(self): - options = AviaryValues() - options.set_val(Aircraft.Engine.NUM_ENGINES, np.array([1, 2, 5])) - options.set_val(Settings.VERBOSITY, 0) + options = { + Aircraft.Engine.NUM_ENGINES: np.array([1, 2, 5]), + } self.prob.model = om.Group() - self.prob.model.add_subsystem('propsum', - PropulsionSum(aviary_options=options), - promotes=['*']) + self.prob.model.add_subsystem('propsum', PropulsionSum(**options), promotes=['*']) self.prob.setup(force_alloc_complex=True) - self.prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, - np.array([1000, 3000, 13200]), units='lbf') + self.prob.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, np.array([1000, 3000, 13200]), units='lbf' + ) self.prob.run_model() - total_thrust = self.prob.get_val( - Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, units='lbf') + total_thrust = self.prob.get_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, units='lbf') expected_thrust = 73000.0 assert_near_equal(total_thrust, expected_thrust, tolerance=1e-12) - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=1e-10, rtol=1e-10) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = PropulsionPreMissionTest() # test.setUp() + # test.test_multi_engine() # test.test_case() diff --git a/aviary/subsystems/propulsion/test/test_throttle_allocation.py b/aviary/subsystems/propulsion/test/test_throttle_allocation.py index 969e28c601..d6bbb4d415 100644 --- a/aviary/subsystems/propulsion/test/test_throttle_allocation.py +++ b/aviary/subsystems/propulsion/test/test_throttle_allocation.py @@ -1,60 +1,62 @@ -from copy import deepcopy import unittest import numpy as np - import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials from aviary.subsystems.propulsion.throttle_allocation import ThrottleAllocator -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import ThrottleAllocation from aviary.variable_info.variables import Aircraft class ThrottleAllocationTest(unittest.TestCase): - def setUp(self): - aviary_inputs = AviaryValues() - aviary_inputs.set_val(Aircraft.Engine.NUM_ENGINES, np.array([1, 1, 1])) - - self.aviary_inputs = aviary_inputs + self.options = { + Aircraft.Engine.NUM_ENGINES: np.array([1, 1, 1]), + } def test_derivs_fixed_or_static(self): prob = om.Problem() model = prob.model - model.add_subsystem('comp', ThrottleAllocator(num_nodes=4, - aviary_options=self.aviary_inputs, - throttle_allocation=ThrottleAllocation.FIXED), - promotes=['*']) + model.add_subsystem( + 'comp', + ThrottleAllocator( + num_nodes=4, throttle_allocation=ThrottleAllocation.FIXED, **self.options + ), + promotes=['*'], + ) prob.setup(force_alloc_complex=True) - prob.set_val("throttle_allocations", val=np.array([0.24, 0.55])) - prob.set_val("aggregate_throttle", val=np.array([0.3, 0.41, 0.52, 0.64])) + prob.set_val('throttle_allocations', val=np.array([0.24, 0.55])) + prob.set_val('aggregate_throttle', val=np.array([0.3, 0.41, 0.52, 0.64])) prob.run_model() - partials = prob.check_partials(method="cs", out_stream=None) + partials = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partials, atol=1e-10, rtol=1e-10) def test_derivs_dynamic(self): prob = om.Problem() model = prob.model - model.add_subsystem('comp', ThrottleAllocator(num_nodes=4, - aviary_options=self.aviary_inputs, - throttle_allocation=ThrottleAllocation.DYNAMIC), - promotes=['*']) + model.add_subsystem( + 'comp', + ThrottleAllocator( + num_nodes=4, throttle_allocation=ThrottleAllocation.DYNAMIC, **self.options + ), + promotes=['*'], + ) prob.setup(force_alloc_complex=True) - prob.set_val("throttle_allocations", val=np.array( - [0.24, 0.55, 0.33, 0.33, 0.6, 0.1, 0.1, 0.6])) - prob.set_val("aggregate_throttle", val=np.array([0.3, 0.41, 0.52, 0.64])) + prob.set_val( + 'throttle_allocations', val=np.array([0.24, 0.55, 0.33, 0.33, 0.6, 0.1, 0.1, 0.6]) + ) + prob.set_val('aggregate_throttle', val=np.array([0.3, 0.41, 0.52, 0.64])) prob.run_model() - partials = prob.check_partials(method="cs", out_stream=None) + partials = prob.check_partials(method='cs', out_stream=None) assert_check_partials(partials, atol=1e-10, rtol=1e-10) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/subsystems/propulsion/test/test_turboprop_model.py b/aviary/subsystems/propulsion/test/test_turboprop_model.py index 01ddcbdcdc..5e6ba77e9b 100644 --- a/aviary/subsystems/propulsion/test/test_turboprop_model.py +++ b/aviary/subsystems/propulsion/test/test_turboprop_model.py @@ -1,37 +1,31 @@ import unittest +from pathlib import Path import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.atmosphere.atmosphere import Atmosphere -from pathlib import Path from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.subsystems.atmosphere.atmosphere import Atmosphere +from aviary.subsystems.propulsion.motor.motor_builder import MotorBuilder +from aviary.subsystems.propulsion.propeller.propeller_performance import PropellerPerformance from aviary.subsystems.propulsion.turboprop_model import TurbopropModel -from aviary.subsystems.propulsion.propeller.propeller_performance import ( - PropellerPerformance, -) -from aviary.utils.preprocessors import preprocess_propulsion +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.functions import get_path -from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.utils.preprocessors import preprocess_propulsion from aviary.variable_info.enums import SpeedType +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.options import get_option_defaults -from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.subsystems.propulsion.motor.motor_builder import MotorBuilder +from aviary.variable_info.variables import Aircraft, Dynamic, Mission @use_tempdirs -class TurbopropTest(unittest.TestCase): +class TurbopropMissionTest(unittest.TestCase): def setUp(self): self.prob = om.Problem() def prepare_model( - self, - test_points=[(0, 0, 0), (0, 0, 1)], - shp_model=None, - prop_model=None, - **kwargs + self, test_points=[(0, 0, 0), (0, 0, 1)], shp_model=None, prop_model=None, **kwargs ): options = get_option_defaults() if isinstance(shp_model, Path): @@ -60,11 +54,11 @@ def prepare_model( ) options.set_val( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=True, units='unitless', ) - options.set_val(Aircraft.Engine.NUM_PROPELLER_BLADES, val=4, units='unitless') + options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=4, units='unitless') num_nodes = len(test_points) @@ -74,9 +68,9 @@ def prepare_model( preprocess_propulsion(options, [engine]) machs, alts, throttles = zip(*test_points) - IVC = om.IndepVarComp(Dynamic.Mission.MACH, np.array(machs), units='unitless') + IVC = om.IndepVarComp(Dynamic.Atmosphere.MACH, np.array(machs), units='unitless') IVC.add_output(Dynamic.Mission.ALTITUDE, np.array(alts), units='ft') - IVC.add_output(Dynamic.Mission.THROTTLE, np.array(throttles), units='unitless') + IVC.add_output(Dynamic.Vehicle.Propulsion.THROTTLE, np.array(throttles), units='unitless') self.prob.model.add_subsystem('IVC', IVC, promotes=['*']) # calculate atmospheric properties @@ -88,26 +82,24 @@ def prepare_model( self.prob.model.add_subsystem( engine.name, - subsys=engine.build_mission( - num_nodes=num_nodes, aviary_inputs=options, **kwargs - ), + subsys=engine.build_mission(num_nodes=num_nodes, aviary_inputs=options, **kwargs), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options(self.prob, options) + self.prob.setup(force_alloc_complex=False) self.prob.set_val(Aircraft.Engine.SCALE_FACTOR, 1, units='unitless') def get_results(self, point_names=None, display_results=False): - shp = self.prob.get_val(Dynamic.Mission.SHAFT_POWER, units='hp') - total_thrust = self.prob.get_val(Dynamic.Mission.THRUST, units='lbf') - prop_thrust = self.prob.get_val('turboprop_model.propeller_thrust', units='lbf') - tailpipe_thrust = self.prob.get_val( - 'turboprop_model.turboshaft_thrust', units='lbf' - ) - max_thrust = self.prob.get_val(Dynamic.Mission.THRUST_MAX, units='lbf') + shp = self.prob.get_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, units='hp') + total_thrust = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST, units='lbf') + prop_thrust = self.prob.get_val('propeller_thrust', units='lbf') + tailpipe_thrust = self.prob.get_val('turboshaft_thrust', units='lbf') + max_thrust = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST_MAX, units='lbf') fuel_flow = self.prob.get_val( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, units='lbm/h' + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, units='lbm/h' ) results = [] @@ -126,61 +118,59 @@ def get_results(self, point_names=None, display_results=False): def test_case_1(self): # test case using GASP-derived engine deck and "user specified" prop model - filename = get_path('models/engines/turboshaft_1120hp.deck') + filename = get_path('models/engines/turboshaft_1120hp.csv') # Mach, alt, throttle @ idle, SLS, TOC test_points = [(0, 0, 0), (0, 0, 1), (0.6, 25000, 1)] # shp, tailpipe thrust, prop_thrust, total_thrust, max_thrust, fuel flow truth_vals = [ ( - 223.99923788786057, + 111.99923788786062, 37.699999999999996, - 1195.4410222483584, - 1233.1410222483585, - 4983.816420783667, + 610.3580810058977, + 648.0580810058977, + 4184.157517016291, -195.79999999999995, ), ( - 2239.9923788786077, + 1119.992378878607, 136.29999999999967, - 4847.516420783668, - 4983.816420783667, - 4983.816420783667, + 4047.857517016292, + 4184.157517016291, + 4184.157517016291, -643.9999999999998, ), ( - 2466.55094358958, + 778.2106659424866, 21.30000000000001, - 1834.6578916888234, - 1855.9578916888233, - 1855.9578916888233, + 558.2951237599805, + 579.5951237599804, + 579.5951237599804, -839.7000000000685, ), ] options = get_option_defaults() options.set_val( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, val=True, units='unitless', ) - options.set_val(Aircraft.Engine.NUM_PROPELLER_BLADES, val=4, units='unitless') + options.set_val(Aircraft.Engine.Propeller.NUM_BLADES, val=4, units='unitless') options.set_val('speed_type', SpeedType.MACH) prop_group = ExamplePropModel('custom_prop_model') self.prepare_model(test_points, filename, prop_group) - self.prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10.5, units="ft") - self.prob.set_val( - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 114.0, units="unitless" - ) + self.prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 10.5, units='ft') + self.prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 114.0, units='unitless') # self.prob.set_val(Dynamic.Mission.PERCENT_ROTOR_RPM_CORRECTED, - # np.array([1, 1, 0.7]), units="unitless") + # np.array([1, 1, 0.7]), units='unitless') self.prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, 0.5, units="unitless" + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless' ) - self.prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 800, units="ft/s") + self.prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 800, units='ft/s') self.prob.run_model() results = self.get_results() @@ -188,54 +178,46 @@ def test_case_1(self): assert_near_equal(results[1], truth_vals[1], tolerance=1.5e-12) assert_near_equal(results[2], truth_vals[2], tolerance=1.5e-12) - # because Hamilton Standard model uses fd method, the following may not be accurate. - partial_data = self.prob.check_partials(out_stream=None, form="central") + # because Hamilton Standard model uses fd method, the following may not be + # accurate. + partial_data = self.prob.check_partials(out_stream=None, form='central') assert_check_partials(partial_data, atol=0.2, rtol=0.2) def test_case_2(self): # test case using GASP-derived engine deck and default HS prop model. - filename = get_path('models/engines/turboshaft_1120hp.deck') + filename = get_path('models/engines/turboshaft_1120hp.csv') test_points = [(0.001, 0, 0), (0, 0, 1), (0.6, 25000, 1)] truth_vals = [ + (111.99470752, 37.507376, 610.74316698, 648.25054298, 4174.71028286, -195.78762), ( - 223.99007751511726, - 37.507374999999996, - 1186.7060713100836, - 1224.2134463100836, - 4984.168016782585, - -195.78762499999996, - ), - ( - 2239.9923788786077, + 1119.992378878607, 136.29999999999967, - 4847.516420783668, - 4983.816420783667, - 4983.816420783667, + 4047.857517016292, + 4184.157517016291, + 4184.157517016291, -643.9999999999998, ), ( - 2466.55094358958, + 778.2106659424866, 21.30000000000001, - 1834.6578916888234, - 1855.9578916888233, - 1855.9578916888233, + 558.2951237599805, + 579.5951237599804, + 579.5951237599804, -839.7000000000685, ), ] self.prepare_model(test_points, filename) - self.prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10.5, units="ft") - self.prob.set_val( - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 114.0, units="unitless" - ) + self.prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 10.5, units='ft') + self.prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 114.0, units='unitless') # self.prob.set_val(Dynamic.Mission.PERCENT_ROTOR_RPM_CORRECTED, - # np.array([1,1,0.7]), units="unitless") + # np.array([1,1,0.7]), units='unitless') self.prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, 0.5, units="unitless" + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless' ) - self.prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 800, units="ft/s") + self.prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 800, units='ft/s') self.prob.run_model() @@ -244,50 +226,49 @@ def test_case_2(self): assert_near_equal(results[1], truth_vals[1], tolerance=1.5e-12) assert_near_equal(results[2], truth_vals[2], tolerance=1.5e-12) - partial_data = self.prob.check_partials(out_stream=None, form="central") + partial_data = self.prob.check_partials(out_stream=None, form='central') assert_check_partials(partial_data, atol=0.15, rtol=0.15) def test_case_3(self): - # test case using GASP-derived engine deck w/o tailpipe thrust and default HS prop model. - filename = get_path('models/engines/turboshaft_1120hp_no_tailpipe.deck') + # test case using GASP-derived engine deck w/o tailpipe thrust and default + # HS prop model. + filename = get_path('models/engines/turboshaft_1120hp_no_tailpipe.csv') test_points = [(0, 0, 0), (0, 0, 1), (0.6, 25000, 1)] truth_vals = [ ( - 223.99923788786057, + 111.99923788786062, 0.0, - 1195.4410222483584, - 1195.4410222483584, - 4847.516420783668, + 610.3580810058977, + 610.3580810058977, + 4047.857517016292, -195.79999999999995, ), ( - 2239.9923788786077, + 1119.992378878607, 0.0, - 4847.516420783668, - 4847.516420783668, - 4847.516420783668, + 4047.857517016292, + 4047.857517016292, + 4047.857517016292, -643.9999999999998, ), ( - 2466.55094358958, + 778.2106659424866, 0.0, - 1834.6578916888234, - 1834.6578916888234, - 1834.6578916888234, + 558.2951237599805, + 558.2951237599805, + 558.2951237599805, -839.7000000000685, ), ] self.prepare_model(test_points, filename) - self.prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10.5, units="ft") - self.prob.set_val( - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 114.0, units="unitless" - ) + self.prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 10.5, units='ft') + self.prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 114.0, units='unitless') self.prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, 0.5, units="unitless" + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless' ) - self.prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 800, units="ft/s") + self.prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 800, units='ft/s') self.prob.run_model() @@ -296,8 +277,10 @@ def test_case_3(self): assert_near_equal(results[1], truth_vals[1], tolerance=1.5e-12) assert_near_equal(results[2], truth_vals[2], tolerance=1.5e-12) - partial_data = self.prob.check_partials(out_stream=None, form="central") - assert_check_partials(partial_data, atol=0.15, rtol=0.15) + # Note: There isn't much point in checking the partials of a component + # that computes them with FD. + partial_data = self.prob.check_partials(out_stream=None, form='forward', step=1.01e-6) + assert_check_partials(partial_data, atol=1e10, rtol=1e-3) def test_electroprop(self): # test case using electric motor and default HS prop model. @@ -307,44 +290,40 @@ def test_electroprop(self): motor_model = MotorBuilder() self.prepare_model(test_points, motor_model, input_rpm=True) - self.prob.set_val(Dynamic.Mission.RPM, np.ones(num_nodes) * 2000.0, units='rpm') + self.prob.set_val(Dynamic.Vehicle.Propulsion.RPM, np.ones(num_nodes) * 2000.0, units='rpm') - self.prob.set_val(Aircraft.Engine.PROPELLER_DIAMETER, 10.5, units="ft") - self.prob.set_val( - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, 114.0, units="unitless" - ) + self.prob.set_val(Aircraft.Engine.Propeller.DIAMETER, 10.5, units='ft') + self.prob.set_val(Aircraft.Engine.Propeller.ACTIVITY_FACTOR, 114.0, units='unitless') self.prob.set_val( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, 0.5, units="unitless" + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, 0.5, units='unitless' ) - self.prob.set_val(Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, 800, units="ft/s") + self.prob.set_val(Aircraft.Engine.Propeller.TIP_SPEED_MAX, 800, units='ft/s') self.prob.run_model() - shp_expected = [0.0, 505.55333, 505.55333] + shp_expected = [0.0, 367.82313837, 367.82313837] prop_thrust_expected = total_thrust_expected = [ - 610.35808276, - 2627.2632965, - 312.64111293, + 610.3580827654595, + 2083.253331913252, + 184.38117745374652, ] - electric_power_expected = [0.0, 408.4409047, 408.4409047] + electric_power_expected = [0.0, 303.31014553, 303.31014553] - shp = self.prob.get_val(Dynamic.Mission.SHAFT_POWER, units='hp') - total_thrust = self.prob.get_val(Dynamic.Mission.THRUST, units='lbf') - prop_thrust = self.prob.get_val('turboprop_model.propeller_thrust', units='lbf') - electric_power = self.prob.get_val( - Dynamic.Mission.ELECTRIC_POWER_IN, units='kW' - ) + shp = self.prob.get_val(Dynamic.Vehicle.Propulsion.SHAFT_POWER, units='hp') + total_thrust = self.prob.get_val(Dynamic.Vehicle.Propulsion.THRUST, units='lbf') + prop_thrust = self.prob.get_val('propeller_thrust', units='lbf') + electric_power = self.prob.get_val(Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, units='kW') assert_near_equal(shp, shp_expected, tolerance=1e-8) assert_near_equal(total_thrust, total_thrust_expected, tolerance=1e-8) assert_near_equal(prop_thrust, prop_thrust_expected, tolerance=1e-8) assert_near_equal(electric_power, electric_power_expected, tolerance=1e-8) - partial_data = self.prob.check_partials( - out_stream=None, method="fd", form="central" - ) - assert_check_partials(partial_data, atol=0.17, rtol=0.15) + # Note: There isn't much point in checking the partials of a component + # that computes them with FD. + partial_data = self.prob.check_partials(out_stream=None, form='forward', step=1.01e-6) + assert_check_partials(partial_data, atol=1e10, rtol=1e-3) class ExamplePropModel(SubsystemBuilderBase): @@ -355,38 +334,32 @@ def build_mission(self, num_nodes, aviary_inputs, **kwargs): 'propeller_performance', PropellerPerformance(aviary_options=aviary_inputs, num_nodes=num_nodes), promotes_inputs=[ - Dynamic.Mission.MACH, - Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, - Aircraft.Engine.PROPELLER_TIP_MACH_MAX, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.MACH, + Aircraft.Engine.Propeller.TIP_SPEED_MAX, + Aircraft.Engine.Propeller.TIP_MACH_MAX, + Dynamic.Atmosphere.DENSITY, Dynamic.Mission.VELOCITY, - Aircraft.Engine.PROPELLER_DIAMETER, - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, + Aircraft.Engine.Propeller.DIAMETER, + Aircraft.Engine.Propeller.ACTIVITY_FACTOR, + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, Aircraft.Nacelle.AVG_DIAMETER, - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.RPM, - Dynamic.Mission.SHAFT_POWER, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Vehicle.Propulsion.RPM, + Dynamic.Vehicle.Propulsion.SHAFT_POWER, ], promotes_outputs=['*'], ) - pp.set_input_defaults(Aircraft.Engine.PROPELLER_DIAMETER, 10, units="ft") + pp.set_input_defaults(Aircraft.Engine.Propeller.DIAMETER, 10, units='ft') pp.set_input_defaults( - Dynamic.Mission.PROPELLER_TIP_SPEED, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, 800.0 * np.ones(num_nodes), - units="ft/s", - ) - pp.set_input_defaults( - Dynamic.Mission.VELOCITY, 100.0 * np.ones(num_nodes), units="knot" + units='ft/s', ) + pp.set_input_defaults(Dynamic.Mission.VELOCITY, 100.0 * np.ones(num_nodes), units='knot') return prop_group -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() - # test = TurbopropTest() - # test.setUp() - # test.test_electroprop() - # test.test_case_2() diff --git a/aviary/subsystems/propulsion/throttle_allocation.py b/aviary/subsystems/propulsion/throttle_allocation.py index fd0543fe27..411d7d4460 100644 --- a/aviary/subsystems/propulsion/throttle_allocation.py +++ b/aviary/subsystems/propulsion/throttle_allocation.py @@ -1,9 +1,8 @@ import numpy as np - import openmdao.api as om -from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.enums import ThrottleAllocation +from aviary.variable_info.functions import add_aviary_option from aviary.variable_info.variables import Aircraft, Dynamic @@ -14,52 +13,45 @@ class ThrottleAllocator(om.ExplicitComponent): """ def initialize(self): + self.options.declare('num_nodes', types=int, lower=0) self.options.declare( - 'num_nodes', - types=int, - lower=0 - ) - self.options.declare( - 'aviary_options', - types=AviaryValues, - desc='collection of Aircraft/Mission specific options' - ) - self.options.declare( - 'throttle_allocation', default=ThrottleAllocation.FIXED, + 'throttle_allocation', + default=ThrottleAllocation.FIXED, types=ThrottleAllocation, - desc='Flag that determines how to handle throttles for multiple engines.' + desc='Flag that determines how to handle throttles for multiple engines.', ) + add_aviary_option(self, Aircraft.Engine.NUM_ENGINES) + def setup(self): - options: AviaryValues = self.options['aviary_options'] nn = self.options['num_nodes'] - num_engine_type = len(options.get_val(Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) alloc_mode = self.options['throttle_allocation'] self.add_input( - "aggregate_throttle", + 'aggregate_throttle', np.ones(nn), - units="unitless", - desc="Solver-controlled aggregate throttle." + units='unitless', + desc='Solver-controlled aggregate throttle.', ) if alloc_mode == ThrottleAllocation.DYNAMIC: alloc_shape = (nn, num_engine_type - 1) else: - alloc_shape = (num_engine_type - 1, ) + alloc_shape = (num_engine_type - 1,) self.add_input( - "throttle_allocations", + 'throttle_allocations', np.ones(alloc_shape) * 1.0 / num_engine_type, - units="unitless", - desc="Throttle allocation for engines." + units='unitless', + desc='Throttle allocation for engines.', ) self.add_output( - Dynamic.Mission.THROTTLE, + Dynamic.Vehicle.Propulsion.THROTTLE, np.ones((nn, num_engine_type)), - units="unitless", - desc="Throttle setting for all engines." + units='unitless', + desc='Throttle setting for all engines.', ) if alloc_mode == ThrottleAllocation.DYNAMIC: @@ -68,15 +60,19 @@ def setup(self): alloc_shape = 1 self.add_output( - "throttle_allocation_sum", + 'throttle_allocation_sum', np.ones(alloc_shape), - desc="Sum of the optimizer allocation values. Constrain to less than 1.0." + desc='Sum of the optimizer allocation values. Constrain to less than 1.0.', ) cols = np.repeat(np.arange(nn), num_engine_type) rows = np.arange(nn * num_engine_type) - self.declare_partials(of=[Dynamic.Mission.THROTTLE], wrt=["aggregate_throttle"], - rows=rows, cols=cols) + self.declare_partials( + of=[Dynamic.Vehicle.Propulsion.THROTTLE], + wrt=['aggregate_throttle'], + rows=rows, + cols=cols, + ) if alloc_mode == ThrottleAllocation.DYNAMIC: a = num_engine_type @@ -87,77 +83,89 @@ def setup(self): cols = np.tile(col, num_engine_type) all_rows = np.tile(rows, nn) + a * np.repeat(np.arange(nn), a * b) all_cols = np.tile(cols, nn) + b * np.repeat(np.arange(nn), a * b) - self.declare_partials(of=[Dynamic.Mission.THROTTLE], wrt=["throttle_allocations"], - rows=all_rows, cols=all_cols) + self.declare_partials( + of=[Dynamic.Vehicle.Propulsion.THROTTLE], + wrt=['throttle_allocations'], + rows=all_rows, + cols=all_cols, + ) rows = np.repeat(np.arange(nn), b) cols = np.arange(nn * b) - self.declare_partials(of=["throttle_allocation_sum"], wrt=["throttle_allocations"], - rows=rows, cols=cols, val=1.0) + self.declare_partials( + of=['throttle_allocation_sum'], + wrt=['throttle_allocations'], + rows=rows, + cols=cols, + val=1.0, + ) else: - self.declare_partials(of=[Dynamic.Mission.THROTTLE], - wrt=["throttle_allocations"]) - self.declare_partials(of=["throttle_allocation_sum"], wrt=["throttle_allocations"], - val=1.0) + self.declare_partials( + of=[Dynamic.Vehicle.Propulsion.THROTTLE], wrt=['throttle_allocations'] + ) + self.declare_partials( + of=['throttle_allocation_sum'], wrt=['throttle_allocations'], val=1.0 + ) def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None): - nn = self.options['num_nodes'] alloc_mode = self.options['throttle_allocation'] - agg_throttle = inputs["aggregate_throttle"] - allocation = inputs["throttle_allocations"] + agg_throttle = inputs['aggregate_throttle'] + allocation = inputs['throttle_allocations'] if alloc_mode == ThrottleAllocation.DYNAMIC: - outputs[Dynamic.Mission.THROTTLE][:, :- - 1] = np.einsum("i,ij->ij", agg_throttle, allocation) + outputs[Dynamic.Vehicle.Propulsion.THROTTLE][:, :-1] = np.einsum( + 'i,ij->ij', agg_throttle, allocation + ) sum_alloc = np.sum(allocation, axis=1) else: - outputs[Dynamic.Mission.THROTTLE][:, :- - 1] = np.einsum("i,j->ij", agg_throttle, allocation) + outputs[Dynamic.Vehicle.Propulsion.THROTTLE][:, :-1] = np.einsum( + 'i,j->ij', agg_throttle, allocation + ) sum_alloc = np.sum(allocation) - outputs[Dynamic.Mission.THROTTLE][:, -1] = agg_throttle * (1.0 - sum_alloc) + outputs[Dynamic.Vehicle.Propulsion.THROTTLE][:, -1] = agg_throttle * (1.0 - sum_alloc) - outputs["throttle_allocation_sum"] = sum_alloc + outputs['throttle_allocation_sum'] = sum_alloc def compute_partials(self, inputs, partials, discrete_inputs=None): - options: AviaryValues = self.options['aviary_options'] nn = self.options['num_nodes'] alloc_mode = self.options['throttle_allocation'] - num_engine_type = len(options.get_val(Aircraft.Engine.NUM_ENGINES)) + num_engine_type = len(self.options[Aircraft.Engine.NUM_ENGINES]) - agg_throttle = inputs["aggregate_throttle"] - allocation = inputs["throttle_allocations"] + agg_throttle = inputs['aggregate_throttle'] + allocation = inputs['throttle_allocations'] if alloc_mode == ThrottleAllocation.DYNAMIC: sum_alloc = np.sum(allocation, axis=1) allocs = np.vstack((allocation.T, 1.0 - sum_alloc)) - partials[Dynamic.Mission.THROTTLE, "aggregate_throttle"] = allocs.T.ravel() + partials[Dynamic.Vehicle.Propulsion.THROTTLE, 'aggregate_throttle'] = allocs.T.ravel() ne = num_engine_type - 1 mask1 = np.eye(ne) - mask2 = - np.ones(ne) + mask2 = -np.ones(ne) mask = np.vstack((mask1, mask2)).ravel() deriv = np.outer(agg_throttle, mask).reshape((nn * (ne + 1), ne)) - partials[Dynamic.Mission.THROTTLE, "throttle_allocations"] = deriv.ravel() + partials[Dynamic.Vehicle.Propulsion.THROTTLE, 'throttle_allocations'] = deriv.ravel() else: sum_alloc = np.sum(allocation) allocs = np.hstack((allocation, 1.0 - sum_alloc)) - partials[Dynamic.Mission.THROTTLE, - "aggregate_throttle"] = np.tile(allocs, nn) + partials[Dynamic.Vehicle.Propulsion.THROTTLE, 'aggregate_throttle'] = np.tile( + allocs, nn + ) ne = num_engine_type - 1 mask1 = np.eye(ne) - mask2 = - np.ones(ne) + mask2 = -np.ones(ne) mask = np.vstack((mask1, mask2)).ravel() deriv = np.outer(agg_throttle, mask).reshape((nn * (ne + 1), ne)) - partials[Dynamic.Mission.THROTTLE, "throttle_allocations"] = deriv + partials[Dynamic.Vehicle.Propulsion.THROTTLE, 'throttle_allocations'] = deriv # sum_alloc = np.sum(allocation) - # outputs[Dynamic.Mission.THROTTLE][:, -1] = agg_throttle * (1.0 - sum_alloc) + # outputs[Dynamic.Vehicle.Propulsion.THROTTLE][:, -1] = agg_throttle * (1.0 - sum_alloc) # outputs["throttle_allocation_sum"] = sum_alloc diff --git a/aviary/subsystems/propulsion/turboprop_model.py b/aviary/subsystems/propulsion/turboprop_model.py index 354830a40e..bc3e5fa0da 100644 --- a/aviary/subsystems/propulsion/turboprop_model.py +++ b/aviary/subsystems/propulsion/turboprop_model.py @@ -3,16 +3,15 @@ import numpy as np import openmdao.api as om -from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase -from aviary.subsystems.propulsion.engine_model import EngineModel from aviary.subsystems.propulsion.engine_deck import EngineDeck -from aviary.subsystems.propulsion.utils import EngineModelVariables -from aviary.utils.named_values import NamedValues +from aviary.subsystems.propulsion.engine_model import EngineModel +from aviary.subsystems.propulsion.gearbox.gearbox_builder import GearboxBuilder +from aviary.subsystems.propulsion.propeller.propeller_builder import PropellerBuilder +from aviary.subsystems.propulsion.utils import EngineModelVariables, build_engine_deck +from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Aircraft, Dynamic, Settings from aviary.variable_info.enums import Verbosity -from aviary.subsystems.propulsion.propeller.propeller_performance import PropellerPerformance -from aviary.subsystems.propulsion.gearbox.gearbox_builder import GearboxBuilder +from aviary.variable_info.variables import Aircraft, Dynamic, Settings class TurbopropModel(EngineModel): @@ -26,9 +25,6 @@ class TurbopropModel(EngineModel): Object label. options : AviaryValues () Inputs and options related to engine model. - data : NamedVaues () - If using an engine deck, engine performance data (optional). If provided, used - instead of tabular data file. shaft_power_model : SubsystemBuilderBase () Subsystem builder for the shaft power generating component. If None, an EngineDeck built using provided options is used. @@ -53,12 +49,10 @@ def __init__( self, name='turboprop_model', options: AviaryValues = None, - data: NamedValues = None, shaft_power_model: SubsystemBuilderBase = None, propeller_model: SubsystemBuilderBase = None, gearbox_model: SubsystemBuilderBase = None, ): - # also calls _preprocess_inputs() as part of EngineModel __init__ super().__init__(name, options) @@ -68,10 +62,9 @@ def __init__( # Initialize turboshaft engine deck. New required variable set w/o thrust if shaft_power_model is None: - self.shaft_power_model = EngineDeck( - name=name + '_engine_deck', + self.shaft_power_model = build_engine_deck( + name='engine_deck', options=options, - data=data, required_variables={ EngineModelVariables.ALTITUDE, EngineModelVariables.MACH, @@ -81,15 +74,17 @@ def __init__( # TODO No reason gearbox model needs to be required. All connections can # be handled in configure - need to figure out when user wants gearbox without - # directly passing builder + # having to directly pass builder if gearbox_model is None: # TODO where can we bring in include_constraints? kwargs in init is an option, # but that still requires the L2 interface - self.gearbox_model = GearboxBuilder( - name=name + '_gearbox', include_constraints=True - ) + self.gearbox_model = GearboxBuilder(name='gearbox', include_constraints=True) - # BUG if using both custom subsystems that happen to share a kwarg but need different values, this breaks + if propeller_model is None: + self.propeller_model = PropellerBuilder(name='propeller') + + # BUG if using both custom subsystems that happen to share a kwarg but + # need different values, this breaks def build_pre_mission(self, aviary_inputs, **kwargs) -> om.Group: shp_model = self.shaft_power_model propeller_model = self.propeller_model @@ -98,18 +93,14 @@ def build_pre_mission(self, aviary_inputs, **kwargs) -> om.Group: # TODO engine scaling for turboshafts requires EngineSizing to be refactored to # accept target scaling variable as an option, skipping for now - if type(shp_model) is not EngineDeck: - shp_model_pre_mission = shp_model.build_pre_mission(aviary_inputs, **kwargs) + if not isinstance(shp_model, EngineDeck): + shp_model_pre_mission = shp_model.build_pre_mission(self.options, **kwargs) if shp_model_pre_mission is not None: turboprop_group.add_subsystem( - shp_model_pre_mission.name, - subsys=shp_model_pre_mission, - promotes=['*'] + shp_model_pre_mission.name, subsys=shp_model_pre_mission, promotes=['*'] ) - gearbox_model_pre_mission = gearbox_model.build_pre_mission( - aviary_inputs, **kwargs - ) + gearbox_model_pre_mission = gearbox_model.build_pre_mission(self.options, **kwargs) if gearbox_model_pre_mission is not None: turboprop_group.add_subsystem( gearbox_model_pre_mission.name, @@ -117,16 +108,13 @@ def build_pre_mission(self, aviary_inputs, **kwargs) -> om.Group: promotes=['*'], ) - if propeller_model is not None: - propeller_model_pre_mission = propeller_model.build_pre_mission( - aviary_inputs, **kwargs + propeller_model_pre_mission = propeller_model.build_pre_mission(self.options, **kwargs) + if propeller_model_pre_mission is not None: + turboprop_group.add_subsystem( + propeller_model_pre_mission.name, + subsys=propeller_model_pre_mission, + promotes=['*'], ) - if propeller_model_pre_mission is not None: - turboprop_group.add_subsystem( - propeller_model_pre_mission.name, - subsys=propeller_model_pre_mission, - promotes=['*'] - ) return turboprop_group @@ -136,19 +124,21 @@ def build_mission(self, num_nodes, aviary_inputs, **kwargs): shaft_power_model=self.shaft_power_model, propeller_model=self.propeller_model, gearbox_model=self.gearbox_model, - aviary_inputs=aviary_inputs, + aviary_inputs=self.options, kwargs=kwargs, ) return turboprop_group - def build_post_mission(self, aviary_inputs, **kwargs): + def build_post_mission(self, aviary_inputs, phase_data, phase_mission_bus_lengths, **kwargs): shp_model = self.shaft_power_model gearbox_model = self.gearbox_model propeller_model = self.propeller_model turboprop_group = om.Group() - shp_model_post_mission = shp_model.build_post_mission(aviary_inputs, **kwargs) + shp_model_post_mission = shp_model.build_post_mission( + aviary_inputs, phase_data, phase_mission_bus_lengths, **kwargs + ) if shp_model_post_mission is not None: turboprop_group.add_subsystem( shp_model.name, @@ -157,7 +147,10 @@ def build_post_mission(self, aviary_inputs, **kwargs): ) gearbox_model_post_mission = gearbox_model.build_post_mission( - aviary_inputs, **kwargs + aviary_inputs, + phase_data, + phase_mission_bus_lengths, + **kwargs, ) if gearbox_model_post_mission is not None: turboprop_group.add_subsystem( @@ -166,19 +159,41 @@ def build_post_mission(self, aviary_inputs, **kwargs): aviary_options=aviary_inputs, ) - if propeller_model is not None: - propeller_model_post_mission = propeller_model.build_post_mission( - aviary_inputs, **kwargs + propeller_model_post_mission = propeller_model.build_post_mission( + aviary_inputs, + phase_data, + phase_mission_bus_lengths, + **kwargs, + ) + if propeller_model_post_mission is not None: + turboprop_group.add_subsystem( + propeller_model.name, + subsys=propeller_model_post_mission, + aviary_options=aviary_inputs, ) - if propeller_model_post_mission is not None: - turboprop_group.add_subsystem( - propeller_model.name, - subsys=propeller_model_post_mission, - aviary_options=aviary_inputs, - ) return turboprop_group + def get_parameters(self): + params = super().get_parameters() # calls from EngineModel + if self.shaft_power_model is not None: + params.update(self.shaft_power_model.get_parameters()) + if self.gearbox_model is not None: + params.update(self.gearbox_model.get_parameters()) + if self.propeller_model is not None: + params.update(self.propeller_model.get_parameters()) + return params + + def get_design_vars(self): + desvars = super().get_design_vars() # calls from EngineModel + if self.shaft_power_model is not None: + desvars.update(self.shaft_power_model.get_design_vars()) + if self.gearbox_model is not None: + desvars.update(self.gearbox_model.get_design_vars()) + if self.propeller_model is not None: + desvars.update(self.propeller_model.get_design_vars()) + return desvars + class TurbopropMission(om.Group): def initialize(self): @@ -189,9 +204,7 @@ def initialize(self): self.options.declare('propeller_model', desc='propeller model') self.options.declare('gearbox_model', desc='gearbox model') self.options.declare('kwargs', desc='kwargs for turboprop mission model') - self.options.declare( - 'aviary_inputs', desc='aviary inputs for turboprop mission model' - ) + self.options.declare('aviary_inputs', desc='aviary inputs for turboprop mission model') def setup(self): # All promotions for configurable components in this group are handled during @@ -206,20 +219,19 @@ def setup(self): # save aviary_inputs for use in configure() self.aviary_inputs = aviary_inputs = self.options['aviary_inputs'] + # NOTE: this subsystem is a empty component that has fixed RPM added as an output + # in configure() if provided in aviary_inputs + self.add_subsystem('fixed_rpm_source', subsys=om.IndepVarComp()) + # Shaft Power Model try: shp_kwargs = kwargs[shp_model.name] except (AttributeError, KeyError): shp_kwargs = {} - shp_model_mission = shp_model.build_mission( - num_nodes, aviary_inputs, **shp_kwargs) + shp_model_mission = shp_model.build_mission(num_nodes, aviary_inputs, **shp_kwargs) if shp_model_mission is not None: self.add_subsystem(shp_model.name, subsys=shp_model_mission) - # NOTE: this subsystem is a empty component that has fixed RPM added as an output - # in configure() if provided in aviary_inputs - self.add_subsystem('fixed_rpm_source', subsys=om.IndepVarComp()) - # Gearbox Model try: gearbox_kwargs = kwargs[gearbox_model.name] @@ -237,84 +249,87 @@ def setup(self): propeller_kwargs = kwargs[propeller_model.name] except (AttributeError, KeyError): propeller_kwargs = {} - if propeller_model is not None: - propeller_group = om.Group() - propeller_model_mission = propeller_model.build_mission( - num_nodes, aviary_inputs, **propeller_kwargs - ) - if propeller_model_mission is not None: - propeller_group.add_subsystem( - propeller_model.name + '_base', - subsys=propeller_model_mission, - promotes_inputs=['*'], - promotes_outputs=[Dynamic.Mission.THRUST], - ) - propeller_model_mission_max = propeller_model.build_mission( - num_nodes, aviary_inputs, **propeller_kwargs - ) - propeller_group.add_subsystem( - propeller_model.name + '_max', - subsys=propeller_model_mission_max, - promotes_inputs=[ - '*', - (Dynamic.Mission.SHAFT_POWER, Dynamic.Mission.SHAFT_POWER_MAX), - ], - promotes_outputs=[ - (Dynamic.Mission.THRUST, Dynamic.Mission.THRUST_MAX) - ], - ) - - self.add_subsystem(propeller_model.name, propeller_group) + propeller_group = om.Group() + propeller_model_mission = propeller_model.build_mission( + num_nodes, aviary_inputs, **propeller_kwargs + ) - else: + if isinstance(propeller_model, PropellerBuilder): # use the Hamilton Standard model # only promote top-level inputs to avoid conflicts with max group prop_inputs = [ - Dynamic.Mission.MACH, - Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, - Aircraft.Engine.PROPELLER_TIP_MACH_MAX, - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.MACH, + Aircraft.Engine.Propeller.TIP_SPEED_MAX, + Aircraft.Engine.Propeller.TIP_MACH_MAX, + Dynamic.Atmosphere.DENSITY, Dynamic.Mission.VELOCITY, - Aircraft.Engine.PROPELLER_DIAMETER, - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, + Aircraft.Engine.Propeller.DIAMETER, + Aircraft.Engine.Propeller.ACTIVITY_FACTOR, + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, Aircraft.Nacelle.AVG_DIAMETER, - Dynamic.Mission.SPEED_OF_SOUND, - Dynamic.Mission.RPM, + Dynamic.Atmosphere.SPEED_OF_SOUND, + Dynamic.Vehicle.Propulsion.RPM, ] try: propeller_kwargs = kwargs['hamilton_standard'] except KeyError: propeller_kwargs = {} - propeller_group = om.Group() - propeller_group.add_subsystem( 'propeller_model_base', - PropellerPerformance( - aviary_options=aviary_inputs, - num_nodes=num_nodes, - **propeller_kwargs, - ), + propeller_model_mission, promotes=['*'], ) + propeller_model_mission_max = propeller_model.build_mission( + num_nodes, aviary_inputs, **propeller_kwargs + ) propeller_group.add_subsystem( 'propeller_model_max', - PropellerPerformance( - aviary_options=aviary_inputs, - num_nodes=num_nodes, - **propeller_kwargs, - ), + propeller_model_mission_max, promotes_inputs=[ *prop_inputs, - (Dynamic.Mission.SHAFT_POWER, Dynamic.Mission.SHAFT_POWER_MAX), + ( + Dynamic.Vehicle.Propulsion.SHAFT_POWER, + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, + ), + ], + promotes_outputs=[ + (Dynamic.Vehicle.Propulsion.THRUST, Dynamic.Vehicle.Propulsion.THRUST_MAX) ], - promotes_outputs=[(Dynamic.Mission.THRUST, Dynamic.Mission.THRUST_MAX)], ) - self.add_subsystem('propeller_model', propeller_group) + self.add_subsystem(propeller_model.name, propeller_group) + + else: + if propeller_model_mission is not None: + propeller_group.add_subsystem( + propeller_model.name + '_base', + subsys=propeller_model_mission, + promotes_inputs=['*'], + promotes_outputs=[Dynamic.Vehicle.Propulsion.THRUST], + ) + + propeller_model_mission_max = propeller_model.build_mission( + num_nodes, aviary_inputs, **propeller_kwargs + ) + propeller_group.add_subsystem( + propeller_model.name + '_max', + subsys=propeller_model_mission_max, + promotes_inputs=[ + '*', + ( + Dynamic.Vehicle.Propulsion.SHAFT_POWER, + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, + ), + ], + promotes_outputs=[ + (Dynamic.Vehicle.Propulsion.THRUST, Dynamic.Vehicle.Propulsion.THRUST_MAX) + ], + ) + + self.add_subsystem(propeller_model.name, propeller_group) thrust_adder = om.ExecComp( 'turboprop_thrust=turboshaft_thrust+propeller_thrust', @@ -336,14 +351,14 @@ def setup(self): 'thrust_adder', subsys=thrust_adder, promotes_inputs=['*'], - promotes_outputs=[('turboprop_thrust', Dynamic.Mission.THRUST)], + promotes_outputs=[('turboprop_thrust', Dynamic.Vehicle.Propulsion.THRUST)], ) self.add_subsystem( 'max_thrust_adder', subsys=max_thrust_adder, promotes_inputs=['*'], - promotes_outputs=[('turboprop_thrust_max', Dynamic.Mission.THRUST_MAX)], + promotes_outputs=[('turboprop_thrust_max', Dynamic.Vehicle.Propulsion.THRUST_MAX)], ) def configure(self): @@ -366,14 +381,14 @@ def configure(self): # of this system, also having it as an input causes feedback loop problem at # the propulsion level skipped_inputs = [ - Dynamic.Mission.ELECTRIC_POWER_IN, - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, - Dynamic.Mission.NOX_RATE, - Dynamic.Mission.SHAFT_POWER, - Dynamic.Mission.SHAFT_POWER_MAX, - Dynamic.Mission.TEMPERATURE_T4, - Dynamic.Mission.THRUST, - Dynamic.Mission.THRUST_MAX, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, + Dynamic.Vehicle.Propulsion.NOX_RATE, + Dynamic.Vehicle.Propulsion.SHAFT_POWER, + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, + Dynamic.Vehicle.Propulsion.TEMPERATURE_T4, + Dynamic.Vehicle.Propulsion.THRUST, + Dynamic.Vehicle.Propulsion.THRUST_MAX, ] # Build lists of inputs/outputs for each component as needed: @@ -383,6 +398,16 @@ def configure(self): # given component, which is done at the end as a bulk promote. shp_model = self._get_subsystem(self.options['shaft_power_model'].name) + shp_input_dict = shp_model.list_inputs( + return_format='dict', units=True, out_stream=None, all_procs=True + ) + shp_input_list = list( + set( + shp_input_dict[key]['prom_name'] + for key in shp_input_dict + if '.' not in shp_input_dict[key]['prom_name'] + ) + ) shp_output_dict = shp_model.list_outputs( return_format='dict', units=True, out_stream=None, all_procs=True ) @@ -427,10 +452,7 @@ def configure(self): ) gearbox_outputs = [] - if self.options['propeller_model'] is None: - propeller_model_name = 'propeller_model' - else: - propeller_model_name = self.options['propeller_model'].name + propeller_model_name = self.options['propeller_model'].name propeller_model = self._get_subsystem(propeller_model_name) propeller_input_dict = propeller_model.list_inputs( return_format='dict', units=True, out_stream=None, all_procs=True @@ -446,8 +468,8 @@ def configure(self): # always promote all propeller model outputs w/o aliasing except thrust propeller_outputs = [ '*', - (Dynamic.Mission.THRUST, 'propeller_thrust'), - (Dynamic.Mission.THRUST_MAX, 'propeller_thrust_max'), + (Dynamic.Vehicle.Propulsion.THRUST, 'propeller_thrust'), + (Dynamic.Vehicle.Propulsion.THRUST_MAX, 'propeller_thrust_max'), ] ######################### @@ -455,13 +477,13 @@ def configure(self): ######################### # Everything not explicitly handled here gets promoted later on # Thrust outputs are directly promoted with alias (this is a special case) - if Dynamic.Mission.THRUST in shp_output_list: - shp_outputs.append((Dynamic.Mission.THRUST, 'turboshaft_thrust')) - shp_output_list.remove(Dynamic.Mission.THRUST) + if Dynamic.Vehicle.Propulsion.THRUST in shp_output_list: + shp_outputs.append((Dynamic.Vehicle.Propulsion.THRUST, 'turboshaft_thrust')) + shp_output_list.remove(Dynamic.Vehicle.Propulsion.THRUST) - if Dynamic.Mission.THRUST_MAX in shp_output_list: - shp_outputs.append((Dynamic.Mission.THRUST_MAX, 'turboshaft_thrust_max')) - shp_output_list.remove(Dynamic.Mission.THRUST_MAX) + if Dynamic.Vehicle.Propulsion.THRUST_MAX in shp_output_list: + shp_outputs.append((Dynamic.Vehicle.Propulsion.THRUST_MAX, 'turboshaft_thrust_max')) + shp_output_list.remove(Dynamic.Vehicle.Propulsion.THRUST_MAX) # Gearbox connections if has_gearbox: @@ -469,12 +491,10 @@ def configure(self): # Check for case: var is output from shp_model, connects to gearbox, then # gets updated by gearbox # RPM has special handling, so skip it here - if var + '_in' in gearbox_input_list and var != Dynamic.Mission.RPM: - # if var is in gearbox input and output, connect on shp -> gearbox side - if ( - var in gearbox_output_list - or var + '_out' in gearbox_output_list - ): + if var + '_in' in gearbox_input_list and var != Dynamic.Vehicle.Propulsion.RPM: + # if var is in gearbox input and output, connect on shp -> gearbox + # side + if var in gearbox_output_list or var + '_out' in gearbox_output_list: shp_outputs.append((var, var + '_gearbox')) shp_output_list.remove(var) gearbox_inputs.append((var + '_in', var + '_gearbox')) @@ -486,11 +506,9 @@ def configure(self): rpm_ivc = self._get_subsystem('fixed_rpm_source') if Aircraft.Engine.FIXED_RPM in self.aviary_inputs: - fixed_rpm = self.aviary_inputs.get_val( - Aircraft.Engine.FIXED_RPM, units='rpm' - ) + fixed_rpm = self.aviary_inputs.get_val(Aircraft.Engine.FIXED_RPM, units='rpm') - if Dynamic.Mission.RPM in shp_output_list: + if Dynamic.Vehicle.Propulsion.RPM in shp_output_list: if self.aviary_inputs.get_val(Settings.VERBOSITY) >= Verbosity.BRIEF: warnings.warn( 'Overriding RPM value outputted by EngineModel' @@ -498,31 +516,45 @@ def configure(self): ) shp_outputs.append( - (Dynamic.Mission.RPM, 'AUTO_OVERRIDE:' + Dynamic.Mission.RPM) + ( + Dynamic.Vehicle.Propulsion.RPM, + 'AIRCRAFT_DATA_OVERRIDE:' + Dynamic.Vehicle.Propulsion.RPM, + ) ) - shp_output_list.remove(Dynamic.Mission.RPM) + shp_output_list.remove(Dynamic.Vehicle.Propulsion.RPM) fixed_rpm_nn = np.ones(self.num_nodes) * fixed_rpm - rpm_ivc.add_output(Dynamic.Mission.RPM, fixed_rpm_nn, units='rpm') + rpm_ivc.add_output(Dynamic.Vehicle.Propulsion.RPM, fixed_rpm_nn, units='rpm') if has_gearbox: - self.promotes('fixed_rpm_source', [(Dynamic.Mission.RPM, 'fixed_rpm')]) - gearbox_inputs.append((Dynamic.Mission.RPM + '_in', 'fixed_rpm')) - gearbox_input_list.remove(Dynamic.Mission.RPM + '_in') + self.promotes('fixed_rpm_source', [(Dynamic.Vehicle.Propulsion.RPM, 'fixed_rpm')]) + gearbox_inputs.append((Dynamic.Vehicle.Propulsion.RPM + '_in', 'fixed_rpm')) + gearbox_input_list.remove(Dynamic.Vehicle.Propulsion.RPM + '_in') else: self.promotes('fixed_rpm_source', ['*']) + # models such as motor take RPM as input + if Dynamic.Vehicle.Propulsion.RPM in shp_input_list: + shp_inputs.append((Dynamic.Vehicle.Propulsion.RPM, 'fixed_rpm')) else: - rpm_ivc.add_output('AUTO_OVERRIDE:' + Dynamic.Mission.RPM, 1.0, units='rpm') + rpm_ivc.add_output( + 'AIRCRAFT_DATA_OVERRIDE:' + Dynamic.Vehicle.Propulsion.RPM, 1.0, units='rpm' + ) if has_gearbox: - if Dynamic.Mission.RPM in shp_output_list: + if Dynamic.Vehicle.Propulsion.RPM in shp_output_list: shp_outputs.append( - (Dynamic.Mission.RPM, Dynamic.Mission.RPM + '_gearbox') + ( + Dynamic.Vehicle.Propulsion.RPM, + Dynamic.Vehicle.Propulsion.RPM + '_gearbox', + ) ) - shp_output_list.remove(Dynamic.Mission.RPM) + shp_output_list.remove(Dynamic.Vehicle.Propulsion.RPM) gearbox_inputs.append( - (Dynamic.Mission.RPM + '_in', Dynamic.Mission.RPM + '_gearbox') + ( + Dynamic.Vehicle.Propulsion.RPM + '_in', + Dynamic.Vehicle.Propulsion.RPM + '_gearbox', + ) ) - gearbox_input_list.remove(Dynamic.Mission.RPM + '_in') + gearbox_input_list.remove(Dynamic.Vehicle.Propulsion.RPM + '_in') # All other shp model outputs that don't interact with gearbox will be promoted for var in shp_output_list: @@ -581,14 +613,11 @@ def configure(self): ############## # PROMOTIONS # ############## - # bulk promote desired inputs and outputs for each subsystem we have been tracking + # bulk promote desired inputs and outputs for each subsystem we have been + # tracking self.promotes(shp_model.name, inputs=shp_inputs, outputs=shp_outputs) if has_gearbox: - self.promotes( - gearbox_model.name, inputs=gearbox_inputs, outputs=gearbox_outputs - ) + self.promotes(gearbox_model.name, inputs=gearbox_inputs, outputs=gearbox_outputs) - self.promotes( - propeller_model_name, inputs=propeller_inputs, outputs=propeller_outputs - ) + self.promotes(propeller_model_name, inputs=propeller_inputs, outputs=propeller_outputs) diff --git a/aviary/subsystems/propulsion/utils.py b/aviary/subsystems/propulsion/utils.py index 83c3e5f988..50d31b1925 100644 --- a/aviary/subsystems/propulsion/utils.py +++ b/aviary/subsystems/propulsion/utils.py @@ -12,33 +12,32 @@ import openmdao.api as om import aviary.constants as constants - from aviary.utils.aviary_values import AviaryValues -from aviary.utils.named_values import NamedValues, get_keys, get_items -from aviary.variable_info.variables import Aircraft, Dynamic, Mission +from aviary.utils.named_values import NamedValues, get_items, get_keys +from aviary.utils.utils import isiterable from aviary.variable_info.variable_meta_data import _MetaData +from aviary.variable_info.variables import Aircraft, Dynamic, Mission class EngineModelVariables(Enum): - """ - Define constants that map to supported variable names in an engine model. - """ + """Define constants that map to supported variable names in an engine model.""" - MACH = Dynamic.Mission.MACH + MACH = Dynamic.Atmosphere.MACH ALTITUDE = Dynamic.Mission.ALTITUDE - THROTTLE = Dynamic.Mission.THROTTLE - HYBRID_THROTTLE = Dynamic.Mission.HYBRID_THROTTLE - THRUST = Dynamic.Mission.THRUST + THROTTLE = Dynamic.Vehicle.Propulsion.THROTTLE + HYBRID_THROTTLE = Dynamic.Vehicle.Propulsion.HYBRID_THROTTLE + THRUST = Dynamic.Vehicle.Propulsion.THRUST TAILPIPE_THRUST = 'tailpipe_thrust' GROSS_THRUST = 'gross_thrust' - SHAFT_POWER = Dynamic.Mission.SHAFT_POWER + SHAFT_POWER = Dynamic.Vehicle.Propulsion.SHAFT_POWER SHAFT_POWER_CORRECTED = 'shaft_power_corrected' RAM_DRAG = 'ram_drag' - FUEL_FLOW = Dynamic.Mission.FUEL_FLOW_RATE - ELECTRIC_POWER_IN = Dynamic.Mission.ELECTRIC_POWER_IN - NOX_RATE = Dynamic.Mission.NOX_RATE - TEMPERATURE_T4 = Dynamic.Mission.TEMPERATURE_T4 - TORQUE = Dynamic.Mission.TORQUE + RPM = Dynamic.Vehicle.Propulsion.RPM + FUEL_FLOW = Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE + ELECTRIC_POWER_IN = Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN + NOX_RATE = Dynamic.Vehicle.Propulsion.NOX_RATE + TEMPERATURE_T4 = Dynamic.Vehicle.Propulsion.TEMPERATURE_T4 + TORQUE = Dynamic.Vehicle.Propulsion.TORQUE # EXIT_AREA = auto() @@ -58,15 +57,25 @@ class EngineModelVariables(Enum): EngineModelVariables.NOX_RATE: 'lb/h', EngineModelVariables.TEMPERATURE_T4: 'degR', EngineModelVariables.TORQUE: 'ft*lbf', + EngineModelVariables.RPM: 'rpm', # EngineModelVariables.EXIT_AREA: 'ft**2', } # variables that have an accompanying max value max_variables = { - EngineModelVariables.THRUST: Dynamic.Mission.THRUST_MAX, - EngineModelVariables.SHAFT_POWER: Dynamic.Mission.SHAFT_POWER_MAX, + EngineModelVariables.THRUST: Dynamic.Vehicle.Propulsion.THRUST_MAX, + EngineModelVariables.SHAFT_POWER: Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, } +# class InstallationDragFlag(Enum): +# """ +# Define constants that map to supported options for scaling of installation drag. +# """ +# OFF = auto() +# DELTA_MAX_NOZZLE_AREA = auto() +# MAX_NOZZLE_AREA = auto() +# REF_NOZZLE_EXIT_AREA = auto() + def convert_geopotential_altitude(altitude): """ @@ -79,7 +88,7 @@ def convert_geopotential_altitude(altitude): geopotential altitudes (in ft) to be converted. Returns - ---------- + ------- altitude_list : geometric altitudes (ft). """ @@ -104,10 +113,7 @@ def convert_geopotential_altitude(altitude): while abs(DH) > 1.0: R = radius_earth + Z GN = GNS * (radius_earth / R) ** (CM1 + 1.0) - H = ( - R * GN * ((R / radius_earth) ** CM1 - 1.0) / CM1 - - Z * (R - Z / 2.0) * OC2 - ) / g + H = (R * GN * ((R / radius_earth) ** CM1 - 1.0) / CM1 - Z * (R - Z / 2.0) * OC2) / g DH = HO - H Z += DH @@ -120,22 +126,37 @@ def convert_geopotential_altitude(altitude): # TODO build test for this function # TODO upgrade to be able to turn vectorized AviaryValues into multiple engine decks -def build_engine_deck(aviary_options: AviaryValues, meta_data=_MetaData): +def build_engine_deck( + options: AviaryValues, + name: str = None, + required_variables=None, + meta_data=_MetaData, +): """ - Creates an EngineDeck using avaliable inputs and options in aviary_options. + Creates an EngineDeck using available inputs and options in aviary_options. Parameter ---------- - aviary_options : AviaryValues - Options to use in creation of EngineDecks. + options : AviaryValues + Options to use in creation of EngineDeck + + name : str, optional + The name of the newly created EngineDeck + + required_variables : set, optional + A set of required variables (from EngineModelVariables) for the newly created + EngineDeck. Defaults to the required set {ALTITUDE, MACH, THROTTLE, THRUST}. + + meta_data : dict, optional + The metadata to be used while creating the EngineDeck. If None, use Aviary's + default metadata. Returns - ---------- - engine_models : - List of EngineDecks created using provided aviary_options. + ------- + EngineDeck + EngineDeck created using provided options. """ - - # Required engine vars include one setting from Mission.Summary. + # Required engine vars include one setting from Mission.Summary engine_vars = [item for item in Aircraft.Engine.__dict__.values()] engine_vars.append(Mission.Summary.FUEL_FLOW_SCALER) @@ -145,52 +166,28 @@ def build_engine_deck(aviary_options: AviaryValues, meta_data=_MetaData): for var in engine_vars: # check if this variable exist with useable metadata try: - units = _MetaData[var]['units'] + units = meta_data[var]['units'] + except (KeyError, TypeError): + continue + else: try: - aviary_val = aviary_options.get_val(var, units) - default_value = meta_data[var]['default_value'] + aviary_val = options.get_val(var, units) # if not, use default value from _MetaData? except KeyError: - # engine_options.set_val(var, _MetaData[var]['default_value'], units) + # currently skipping filling "missing" variables with defaults + # engine_options.set_val(var, meta_data[var]['default_value'], units) continue - # add value from aviary_options to engine_options + # add value from options to engine_options else: - # special handling for numpy arrays - check if they are multidimensional, - # which implies multiple engine models, and only use the value intended - # for the first engine model - if isinstance(aviary_val, np.ndarray) and isinstance( - default_value, np.ndarray - ): - expected_dim = default_value.ndim - val_dim = aviary_val.ndim - # if aviary_values has one more dimension than expected per-engine, - # we know aviary_values is for heterogeneous engine type. Currently only using - # first index - if val_dim == expected_dim + 1: - aviary_val = aviary_val[0] - # if aviary_values has more than one dimension from expected, then - # something is very wrong and cannot be fixed here - if val_dim > expected_dim + 1: - UserWarning( - f'Provided vector for {var} has too many dimensions: ' - 'expecting a {expected_dim+1}D array ({expected_dim}D ' - 'per engine)' - ) - # if neither metadata nor aviary_val are numpy arrays, cannot check dimensions - # in robust way, so a reduced check is done. No raised, errors, must - # assume aviary_val data is formatted correctly - elif isinstance(aviary_val, (list, tuple, np.ndarray)): + if isiterable(aviary_val): try: aviary_val_0 = aviary_val[0] except TypeError: pass else: - # if item in first index is also iterable, aviary_val is multi-dimensional array - # if array only contains a single value, use that - if ( - isinstance(aviary_val_0, (list, tuple, np.ndarray)) - or len(aviary_val) == 1 - ): + # if item in first index is also iterable, or if array only + # contains a single value, use that + if isiterable(aviary_val_0) or len(aviary_val) == 1: aviary_val = aviary_val_0 # "Convert" numpy types to standard Python types. Wrap first # index in numpy array before calling item() to safeguard against @@ -199,27 +196,31 @@ def build_engine_deck(aviary_options: AviaryValues, meta_data=_MetaData): aviary_val = np.array(aviary_val).item() engine_options.set_val(var, aviary_val, units) - except (KeyError, TypeError): - continue + # Build EngineDeck object + # gather arguments for building EngineDeck + kwargs = {'options': engine_options} + + # name engine deck after filename if name is not provided + if name is None: + kwargs['name'] = Path(engine_options.get_val(Aircraft.Engine.DATA_FILE)).stem + else: + kwargs['name'] = name + + if required_variables is not None: + kwargs['required_variables'] = required_variables # local import to avoid circular import from aviary.subsystems.propulsion.engine_deck import EngineDeck - # name engine deck after filename - return [ - EngineDeck( - Path(engine_options.get_val(Aircraft.Engine.DATA_FILE)).stem, - options=engine_options, - ) - ] + return EngineDeck(**kwargs) # TODO combine with aviary/utils/data_interpolator_builder.py build_data_interpolator class EngineDataInterpolator(om.Group): - ''' + """ Group that contains interpolators that get passed training data directly through - openMDAO connections - ''' + openMDAO connections. + """ def initialize(self): self.options.declare('num_nodes', types=int) @@ -241,7 +242,7 @@ def initialize(self): self.options.declare( 'interpolator_outputs', types=dict, - desc='Dictionary describing which variables will be avaliable to the ' + desc='Dictionary describing which variables will be available to the ' 'interpolator as training data at runtime, and their units', ) @@ -285,8 +286,7 @@ def setup(self): model_length = len(val) if model_length != prev_model_length: raise IndexError( - 'Lengths of data provided for engine performance ' - 'interpolation do not match.' + 'Lengths of data provided for engine performance interpolation do not match.' ) # add inputs and outputs to interpolator @@ -330,13 +330,9 @@ def setup(self): ) # add created subsystems to engine_group - self.add_subsystem( - 'interpolation', engine, promotes_inputs=['*'], promotes_outputs=['*'] - ) + self.add_subsystem('interpolation', engine, promotes_inputs=['*'], promotes_outputs=['*']) - self.add_subsystem( - 'fixed_max_throttles', fixed_throttles, promotes_outputs=['*'] - ) + self.add_subsystem('fixed_max_throttles', fixed_throttles, promotes_outputs=['*']) self.add_subsystem( 'max_thrust_interpolation', @@ -347,9 +343,7 @@ def setup(self): class UncorrectData(om.Group): - """ - Calculations to recover physical parameter values that have been corrected based on ambient atmospheric conditions - """ + """Calculations to recover physical parameter values that have been corrected based on ambient atmospheric conditions.""" def initialize(self): self.options.declare('num_nodes', types=int, default=1) @@ -366,7 +360,7 @@ def setup(self): 'pressure_term', om.ExecComp( 'delta_T = (P0 * (1 + .2*mach**2)**3.5) / P_amb', - delta_T={'units': "unitless", 'shape': num_nodes}, + delta_T={'units': 'unitless', 'shape': num_nodes}, P0={'units': 'psi', 'shape': num_nodes}, mach={'units': 'unitless', 'shape': num_nodes}, P_amb={ @@ -376,8 +370,8 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - ('P0', Dynamic.Mission.STATIC_PRESSURE), - ('mach', Dynamic.Mission.MACH), + ('P0', Dynamic.Atmosphere.STATIC_PRESSURE), + ('mach', Dynamic.Atmosphere.MACH), ], promotes_outputs=['delta_T'], ) @@ -386,7 +380,7 @@ def setup(self): 'temperature_term', om.ExecComp( 'theta_T = T0 * (1 + .2*mach**2)/T_amb', - theta_T={'units': "unitless", 'shape': num_nodes}, + theta_T={'units': 'unitless', 'shape': num_nodes}, T0={'units': 'degR', 'shape': num_nodes}, mach={'units': 'unitless', 'shape': num_nodes}, T_amb={ @@ -396,8 +390,8 @@ def setup(self): has_diag_partials=True, ), promotes_inputs=[ - ('T0', Dynamic.Mission.TEMPERATURE), - ('mach', Dynamic.Mission.MACH), + ('T0', Dynamic.Atmosphere.TEMPERATURE), + ('mach', Dynamic.Atmosphere.MACH), ], promotes_outputs=['theta_T'], ) @@ -405,43 +399,12 @@ def setup(self): self.add_subsystem( 'uncorrection', om.ExecComp( - 'uncorrected_data = corrected_data * (delta_T + theta_T**.5)', - uncorrected_data={'units': "hp", 'shape': num_nodes}, - delta_T={'units': "unitless", 'shape': num_nodes}, - theta_T={'units': "unitless", 'shape': num_nodes}, - corrected_data={'units': "hp", 'shape': num_nodes}, + 'uncorrected_data = corrected_data * (delta_T * theta_T**.5)', + uncorrected_data={'units': 'hp', 'shape': num_nodes}, + delta_T={'units': 'unitless', 'shape': num_nodes}, + theta_T={'units': 'unitless', 'shape': num_nodes}, + corrected_data={'units': 'hp', 'shape': num_nodes}, has_diag_partials=True, ), promotes=['*'], ) - - -# class InstallationDragFlag(Enum): -# """ -# Define constants that map to supported options for scaling of installation drag. -# """ -# OFF = auto() -# DELTA_MAX_NOZZLE_AREA = auto() -# MAX_NOZZLE_AREA = auto() -# REF_NOZZLE_EXIT_AREA = auto() - - -class PropellerModelVariables(Enum): - """ - Define constants that map to supported variable names in a propeller model. - """ - - HELICAL_MACH = 'Helical_Mach' - MACH = 'Mach' - CP = 'CP' # power coefficient - CT = 'CT' # thrust coefficient - J = 'J' # advanced ratio - - -default_propeller_units = { - PropellerModelVariables.HELICAL_MACH: 'unitless', - PropellerModelVariables.MACH: 'unitless', - PropellerModelVariables.CP: 'unitless', - PropellerModelVariables.CT: 'unitless', - PropellerModelVariables.J: 'unitless', -} diff --git a/aviary/subsystems/subsystem_builder_base.py b/aviary/subsystems/subsystem_builder_base.py index 9eab4a7fa7..e8a1148213 100644 --- a/aviary/subsystems/subsystem_builder_base.py +++ b/aviary/subsystems/subsystem_builder_base.py @@ -30,6 +30,14 @@ def __init__(self, name=None, meta_data=None): meta_data = _MetaData self.meta_data = meta_data + def needs_mission_solver(self, aviary_inputs): + """ + Return True if the mission subsystem needs to be in the solver loop in mission, otherwise + return False. Aviary will only place it in the solver loop when True. The default is + True. + """ + return True + def build_pre_mission(self, aviary_inputs, **kwargs): """ Build an OpenMDAO System for the pre-mission computations of the subsystem. @@ -99,7 +107,7 @@ def get_controls(self, phase_name=None): """ return {} - def get_parameters(self, aviary_inputs=None, phase_info=None): + def get_parameters(self, aviary_inputs=None, **kwargs): """ Return a dictionary of fixed values for the subsystem. @@ -117,8 +125,6 @@ def get_parameters(self, aviary_inputs=None, phase_info=None): ---------- aviary_inputs : dict A dictionary containing the inputs to the subsystem. - phase_info : dict - The phase_info subdict for this phase. Returns ------- @@ -168,11 +174,16 @@ def get_linked_variables(self): """ return [] - def get_bus_variables(self): + def get_pre_mission_bus_variables(self, aviary_inputs=None): """ Return a dictionary of variables that will be passed from the pre-mission to mission systems. + Parameters + ---------- + aviary_inputs : dict + A dictionary containing the inputs to the subsystem. + Returns ------- bus_variables : dict @@ -189,7 +200,8 @@ def get_bus_variables(self): - 'units' : str This is temporary and will be removed, however, it is currently a requirement. - + - 'src_indices': int or list of ints or tuple of ints or int ndarray or Iterable or None + Indices of the pre-mission variable for connection. """ return {} @@ -211,6 +223,20 @@ def build_mission(self, num_nodes, aviary_inputs, **kwargs): """ return None + def mission_inputs(self, **kwargs): + """ + Returns list of mission inputs to be promoted out of the external subsystem. By + default, all aircraft:* and mission:* inputs are promoted. + """ + return [] + + def mission_outputs(self, **kwargs): + """ + Returns list of mission outputs to be promoted out of the external subsystem. By + default, all aircraft:* and mission:* outputs are promoted. + """ + return [] + def define_order(self): """ Return a list of subsystem names that must be defined before this one. E.g., must go before or after aero or prop. @@ -303,12 +329,70 @@ def get_outputs(self): """ return [] - def build_post_mission(self, aviary_inputs, **kwargs): + def get_post_mission_bus_variables(self, aviary_inputs=None, phase_info=None): + """ + Return a dict mapping phase names to a dict mapping mission variable names to (a list of) post-mission variable names. + + Mission variables local to a given external subsystem should be prefixed with that subsystem's name. + For example, to connect a variable 'bar' that is an output of the external subsystem "foo"'s mission to the post-mission variable "cruise_foo", map "foo.bar" to "cruise_foo". + + Parameters + ---------- + aviary_inputs : dict + A dictionary containing the inputs to the subsystem. + phase_info : dict + The phase_info dict for all phases + + Returns + ------- + bus_variables : dict + A dictionary where the keys are the phase name and the values are dictionaries with the keys being the mission variable names to connect from, + and values are dictionaries with the following keys: + - 'post_mission_name': str or list + Names of the input variable to be connected in the post-mission subsystem + - 'src_indices': int or list of ints or tuple of ints or int ndarray or Iterable or None + Indices of the mission variable for connection + + Example + ------- + bus_variables = {} + if phase_info: + for phase_name, phase_data in phase_info.items(): + phase_d = {} + if phase_data["do_the_thing"]: + phase_d[f"{self.name}.mission_variable_a"] = {"post_mission_name": f"{self.name}.{phase_name}_post_mission_variable_a", "src_indices": -1} + phase_d[f"{self.name}.mission_variable_b"] = {"post_mission_name": [f"{self.name}.{phase_name}_post_mission_variable_b_name1", f"{self.name}.{phase_name}_post_mission_variable_b_name2"]} + phase_d[f"{self.name}.mission_variable_c"] = {"post_mission_name": [f"{self.name}.{phase_name}_post_mission_variable_c_name1"]} + phase_d[Dynamic.Mission.VELOCITY] = {"post_mission_name": f"{self.name}.{phase_name}_post_mission_velocity_name1"} + if phase_data["do_the_other_thing"]: + phase_d[f"{self.name}.mission_variable_d"] = {"post_mission_name": f"{self.name}.{phase_name}_post_mission_variable_d", "src_indices": [0, 1]} + phase_d[f"{self.name}.mission_variable_e"] = {"post_mission_name": [f"{self.name}.{phase_name}_post_mission_variable_e_name1", f"{self.name}.{phase_name}_post_mission_variable_e_name2"]} + phase_d[f"{self.name}.mission_variable_f"] = {"post_mission_name": [f"{self.name}.{phase_name}_post_mission_variable_f_name1"]} + phase_d[Dynamic.Atmosphere.KINEMATIC_VISCOSITY] = {"post_mission_name": f"{self.name}.{phase_name}_post_mission_nu_name1"} + + bus_variables[phase_name] = phase_d + + return bus_variables + """ + return {} + + def build_post_mission( + self, aviary_inputs, phase_info=None, phase_mission_bus_lengths=None, **kwargs + ): """ Build an OpenMDAO System for the post-mission computations of the subsystem. Required for subsystems with post-mission-based analyses. + Parameters + ---------- + aviary_inputs : dict + A dictionary containing the inputs to the subsystem. + phase_info : dict + The phase_info dict for all phases + phase_mission_bus_lengths : dict + Mapping from phase names to the lengths of the phase's "mission_bus_variables" timeseries + Returns ------- post_mission_sys : openmdao.core.System diff --git a/aviary/subsystems/test/subsystem_tester.py b/aviary/subsystems/test/subsystem_tester.py index 771ceb0034..8f289ad4f4 100644 --- a/aviary/subsystems/test/subsystem_tester.py +++ b/aviary/subsystems/test/subsystem_tester.py @@ -1,12 +1,13 @@ import unittest +from importlib import import_module import numpy as np -from importlib import import_module import openmdao.api as om from openmdao.core.system import System from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase from aviary.utils.aviary_values import AviaryValues +from aviary.variable_info.functions import setup_model_options def skipIfMissingDependencies(builder): @@ -16,16 +17,17 @@ def skipIfMissingDependencies(builder): class TestSubsystemBuilderBase(unittest.TestCase): @staticmethod def import_builder(path_to_builder: str, base_package='aviary.examples.external_subsystems'): - ''' - import a subsytem builder + """ + Import a subsystem builder. This is intended to be used with skipIfMissingDependencies - ''' + """ try: package, method = path_to_builder.rsplit('.', 1) package_path, package_name = package.rsplit('.', 1) - module_path = '.'.join([path_to_builder, package_path]) if package_path \ - else path_to_builder + module_path = ( + '.'.join([path_to_builder, package_path]) if package_path else path_to_builder + ) module = import_module(package_name, module_path) builder = getattr(module, method) except ImportError: @@ -43,11 +45,13 @@ def test_get_states(self): self.assertIsInstance(states, dict, msg='get_states should return a dictionary') for key, value in states.items(): - self.assertIsInstance( - value, dict, msg=f"the value for '{key}' should be a dictionary") + self.assertIsInstance(value, dict, msg=f"the value for '{key}' should be a dictionary") self.assertIsInstance( - value['rate_source'], str, msg=f"the value for 'rate_source' key in '{key}' should be a string") + value['rate_source'], + str, + msg=f"the value for 'rate_source' key in '{key}' should be a string", + ) def test_get_linked_variables(self): linked_variables = self.subsystem_builder.get_linked_variables() @@ -55,47 +59,60 @@ def test_get_linked_variables(self): for var in linked_variables: self.assertIsInstance(var, str) - def test_get_bus_variables(self): - bus_variables = self.subsystem_builder.get_bus_variables() + def test_get_pre_mission_bus_variables(self): + bus_variables = self.subsystem_builder.get_pre_mission_bus_variables() # Check that a dictionary is returned self.assertIsInstance( - bus_variables, dict, 'get_bus_variables should return a dictionary') + bus_variables, dict, 'get_pre_mission_bus_variables should return a dictionary' + ) for name, values in bus_variables.items(): # Check that the bus_variable has the required keys - self.assertIn('mission_name', values.keys(), - f'Bus Variable "{name}" is missing the "mission_name" key') - self.assertIn('units', values.keys(), - f'Bus Variable "{name}" is missing the "units" key') + self.assertIn( + 'mission_name', + values.keys(), + f'Bus Variable "{name}" is missing the "mission_name" key', + ) + self.assertIn( + 'units', values.keys(), f'Bus Variable "{name}" is missing the "units" key' + ) - # Check that the values of the keys are the expected types + # Check that the values of the keys are the expected types (allow list) self.assertIsInstance( - values['mission_name'], (str, type(None)), f'Bus Variable "{name}"\'s "mission_name" value should be a string or None') + values['mission_name'], + (str, list, type(None)), + f'Bus Variable "{name}"\'s "mission_name" value should be a string or None', + ) self.assertIsInstance( - values['units'], str, f'Bus Variable "{name}"\'s "units" value should be a string') + values['units'], str, f'Bus Variable "{name}"\'s "units" value should be a string' + ) def test_build_pre_mission(self): if not hasattr(self, 'aviary_values'): self.aviary_values = AviaryValues() - pre_mission_sys = self.subsystem_builder.build_pre_mission( - aviary_inputs=self.aviary_values) + pre_mission_sys = self.subsystem_builder.build_pre_mission(aviary_inputs=self.aviary_values) if pre_mission_sys is not None: # Check that pre_mission_sys is an OpenMDAO System self.assertIsInstance( - pre_mission_sys, System, msg="The returned object from `build_pre_mission` is not an OpenMDAO System.") + pre_mission_sys, + System, + msg='The returned object from `build_pre_mission` is not an OpenMDAO System.', + ) - def test_build_mission(self): + def test_build_mission(self, **kwargs): if not hasattr(self, 'aviary_values'): self.aviary_values = AviaryValues() # Test that the method returns an OpenMDAO System object mission_sys = self.subsystem_builder.build_mission( - 10, aviary_inputs=self.aviary_values) + 10, aviary_inputs=self.aviary_values, **kwargs + ) if mission_sys is not None: - self.assertIsInstance(mission_sys, System, - "The method should return an OpenMDAO System object.") + self.assertIsInstance( + mission_sys, System, 'The method should return an OpenMDAO System object.' + ) with self.assertRaises(TypeError, msg='num_nodes argument missing from build_mission().'): self.subsystem_builder.build_mission(aviary_inputs=self.aviary_values) @@ -104,135 +121,173 @@ def test_get_constraints(self): constraints = self.subsystem_builder.get_constraints() # Check that a dictionary is returned - self.assertIsInstance( - constraints, dict, 'get_constraints should return a dictionary') + self.assertIsInstance(constraints, dict, 'get_constraints should return a dictionary') for name, values in constraints.items(): # Check that the constraint has the required keys - self.assertIn('type', values.keys(), - f'Constraint "{name}" is missing the "type" key') + self.assertIn('type', values.keys(), f'Constraint "{name}" is missing the "type" key') # Check that the values of the keys are the expected types self.assertIsInstance( - values['type'], str, f'Constraint "{name}"\'s "type" value should be a string') + values['type'], str, f'Constraint "{name}"\'s "type" value should be a string' + ) def test_get_design_vars(self): # Verify that the method returns a dictionary design_vars = self.subsystem_builder.get_design_vars() - self.assertIsInstance( - design_vars, dict, "get_design_vars() should return a dictionary") + self.assertIsInstance(design_vars, dict, 'get_design_vars() should return a dictionary') # Verify that the keys in the dictionary are strings for key in design_vars.keys(): self.assertIsInstance( - key, str, "The keys in the dictionary returned by get_design_vars() should be strings") + key, + str, + 'The keys in the dictionary returned by get_design_vars() should be strings', + ) # Verify that the values in the dictionary are also dictionaries for val in design_vars.values(): self.assertIsInstance( - val, dict, "The values in the dictionary returned by get_design_vars() should be dictionaries") + val, + dict, + 'The values in the dictionary returned by get_design_vars() should be dictionaries', + ) # Verify that the dictionaries have the correct keys for val in design_vars.values(): self.assertIn( - 'units', val, "The dictionaries returned by get_design_vars() should have a 'units' key") + 'units', + val, + "The dictionaries returned by get_design_vars() should have a 'units' key", + ) self.assertIn( - 'lower', val, "The dictionaries returned by get_design_vars() should have a 'lower' key") + 'lower', + val, + "The dictionaries returned by get_design_vars() should have a 'lower' key", + ) self.assertIn( - 'upper', val, "The dictionaries returned by get_design_vars() should have an 'upper' key") + 'upper', + val, + "The dictionaries returned by get_design_vars() should have an 'upper' key", + ) - def test_get_parameters(self): + def test_get_parameters(self, **kwargs): if not hasattr(self, 'aviary_values'): self.aviary_values = AviaryValues() # Verify that the method returns a dictionary parameters = self.subsystem_builder.get_parameters( - aviary_inputs=self.aviary_values, - phase_info={} + aviary_inputs=self.aviary_values, **kwargs ) - self.assertIsInstance( - parameters, dict, "get_parameters() should return a dictionary") + self.assertIsInstance(parameters, dict, 'get_parameters() should return a dictionary') # Verify that the keys in the dictionary are strings for key in parameters.keys(): self.assertIsInstance( - key, str, "The keys in the dictionary returned by get_parameters() should be strings") + key, + str, + 'The keys in the dictionary returned by get_parameters() should be strings', + ) # Verify that the values in the dictionary are also dictionaries for val in parameters.values(): self.assertIsInstance( - val, dict, "The values in the dictionary returned by get_parameters() should be dictionaries") + val, + dict, + 'The values in the dictionary returned by get_parameters() should be dictionaries', + ) # Verify that the dictionaries have the correct keys - for val in parameters.values(): + for key, val in parameters.items(): self.assertIn( - 'val', val, "The dictionaries returned by get_parameters() should have a 'val' key") + 'val', + val, + f"The dictionaries returned by get_parameters() should have a 'val' key for {key}", + ) self.assertIn( - 'units', val, "The dictionaries returned by get_parameters() should have a 'units' key") + 'units', + val, + f"The dictionaries returned by get_parameters() should have a 'units' key for {key}", + ) def test_get_initial_guesses(self): initial_guesses = self.subsystem_builder.get_initial_guesses() - self.assertIsInstance(initial_guesses, dict, - msg="get_initial_guesses() should return a dictionary") + self.assertIsInstance( + initial_guesses, dict, msg='get_initial_guesses() should return a dictionary' + ) for key, val in initial_guesses.items(): - self.assertIsInstance( - val, dict, msg=f"The value for '{key}' should be a dictionary") + self.assertIsInstance(val, dict, msg=f"The value for '{key}' should be a dictionary") self.assertIn( - 'val', val, msg=f"The value for '{key}' dictionary should have a 'val' key") + 'val', val, msg=f"The value for '{key}' dictionary should have a 'val' key" + ) self.assertIn( - 'type', val, msg=f"The value for '{key}' dictionary should have a 'type' key") + 'type', val, msg=f"The value for '{key}' dictionary should have a 'type' key" + ) guess_val = val['val'] - self.assertIsInstance(guess_val, (float, list, np.ndarray), - msg=f"The value for '{key}' should be a float, list, or array") + self.assertIsInstance( + guess_val, + (float, list, np.ndarray), + msg=f"The value for '{key}' should be a float, list, or array", + ) def test_get_mass_names(self): # Instantiate a user-defined subsystem builder subsystem_builder = self.subsystem_builder # Ensure get_mass_names method returns a list - self.assertIsInstance(subsystem_builder.get_mass_names(), list, - "get_mass_names should return a list of mass names") + self.assertIsInstance( + subsystem_builder.get_mass_names(), + list, + 'get_mass_names should return a list of mass names', + ) # Ensure each mass name is a string for mass_name in subsystem_builder.get_mass_names(): - self.assertIsInstance(mass_name, str, - "Each mass name in the list should be a string") + self.assertIsInstance(mass_name, str, 'Each mass name in the list should be a string') def test_preprocess_inputs(self): if not hasattr(self, 'aviary_values'): self.aviary_values = AviaryValues() inputs = self.subsystem_builder.preprocess_inputs(self.aviary_values) - self.assertIsInstance(inputs, AviaryValues, - "preprocess_inputs did not return an AviaryValues object") + self.assertIsInstance( + inputs, AviaryValues, 'preprocess_inputs did not return an AviaryValues object' + ) def test_build_post_mission(self): # Perform post-mission operations if not hasattr(self, 'aviary_values'): self.aviary_values = AviaryValues() - post_mission_sys = self.subsystem_builder.build_post_mission(self.aviary_values) + phase_info = {} + phase_mission_bus_lengths = {'foo': 10, 'bar': 11} + post_mission_sys = self.subsystem_builder.build_post_mission( + self.aviary_values, phase_info, phase_mission_bus_lengths + ) if post_mission_sys is not None: # Check that post_mission_sys is an OpenMDAO system self.assertIsInstance( - post_mission_sys, System, msg="post_mission_sys is not an OpenMDAO System.") + post_mission_sys, System, msg='post_mission_sys is not an OpenMDAO System.' + ) def test_define_order(self): order = self.subsystem_builder.define_order() - self.assertIsInstance(order, list, "define_order should return a list") + self.assertIsInstance(order, list, 'define_order should return a list') for subsystem_name in order: self.assertIsInstance( - subsystem_name, str, "Each subsystem name in the list should be a string") + subsystem_name, str, 'Each subsystem name in the list should be a string' + ) def test_get_outputs(self): outputs = self.subsystem_builder.get_outputs() - self.assertIsInstance(outputs, list, "get_outputs should return a list") + self.assertIsInstance(outputs, list, 'get_outputs should return a list') for output_name in outputs: self.assertIsInstance( - output_name, str, "Each output name in the list should be a string") + output_name, str, 'Each output name in the list should be a string' + ) def test_check_state_variables(self): if not hasattr(self, 'aviary_values'): @@ -241,7 +296,8 @@ def test_check_state_variables(self): states = self.subsystem_builder.get_states() mission_sys = self.subsystem_builder.build_mission( - num_nodes=5, aviary_inputs=self.aviary_values) + num_nodes=5, aviary_inputs=self.aviary_values + ) if mission_sys is None: return @@ -249,6 +305,9 @@ def test_check_state_variables(self): group = om.Group() group.add_subsystem('mission', mission_sys, promotes=['*']) prob = om.Problem(group) + + setup_model_options(prob, self.aviary_values) + prob.setup() prob.final_setup() @@ -258,8 +317,7 @@ def test_check_state_variables(self): if mission_sys is not None: # Check state variable existence state_var_exists = any(key == input[1]['prom_name'] for input in inputs) - self.assertTrue(state_var_exists, - f"State variable '{key}' not found in the model.") + self.assertTrue(state_var_exists, f"State variable '{key}' not found in the model.") def test_check_pre_mission(self): if not hasattr(self, 'aviary_values'): @@ -273,11 +331,15 @@ def test_check_pre_mission(self): group = om.Group() group.add_subsystem('pre_mission_sys', pre_mission_sys) prob = om.Problem(group) + + setup_model_options(prob, self.aviary_values) + prob.setup() prob.final_setup() - self.assertIsInstance(pre_mission_sys, System, - "The method should return an OpenMDAO System object.") + self.assertIsInstance( + pre_mission_sys, System, 'The method should return an OpenMDAO System object.' + ) mass_names = self.subsystem_builder.get_mass_names() outputs = pre_mission_sys.list_outputs(out_stream=None, prom_name=True) @@ -285,19 +347,20 @@ def test_check_pre_mission(self): for name in mass_names: mass_var_exists = any(name == output_[1]['prom_name'] for output_ in outputs) self.assertTrue( - mass_var_exists, f"Mass variable '{name}' not found in the pre-mission model.") + mass_var_exists, f"Mass variable '{name}' not found in the pre-mission model." + ) - def test_check_parameters(self): + def test_check_parameters(self, **kwargs): if not hasattr(self, 'aviary_values'): self.aviary_values = AviaryValues() parameters = self.subsystem_builder.get_parameters( - aviary_inputs=self.aviary_values, - phase_info={} + aviary_inputs=self.aviary_values, **kwargs ) mission_sys = self.subsystem_builder.build_mission( - num_nodes=5, aviary_inputs=self.aviary_values) + num_nodes=5, aviary_inputs=self.aviary_values + ) if mission_sys is None: return @@ -305,6 +368,9 @@ def test_check_parameters(self): group = om.Group() group.add_subsystem('mission', mission_sys, promotes=['*']) prob = om.Problem(group) + + setup_model_options(prob, self.aviary_values) + prob.setup() prob.final_setup() @@ -322,7 +388,8 @@ def test_check_constraints(self): constraints = self.subsystem_builder.get_constraints() mission_sys = self.subsystem_builder.build_mission( - num_nodes=5, aviary_inputs=self.aviary_values) + num_nodes=5, aviary_inputs=self.aviary_values + ) if mission_sys is None: return @@ -330,6 +397,9 @@ def test_check_constraints(self): group = om.Group() group.add_subsystem('mission', mission_sys, promotes=['*']) prob = om.Problem(group) + + setup_model_options(prob, self.aviary_values) + prob.setup() prob.final_setup() @@ -339,10 +409,13 @@ def test_check_constraints(self): for key, value in constraints.items(): # Check constraint existence - constraint_exists = (any(key == output[1]['prom_name'] for output in outputs) or any( - key == input[1]['prom_name'] for input in inputs) or any(key == f'{name}.{output[1]["prom_name"]}' for output in outputs) or any(key == f'{name}.{input[1]["prom_name"]}' for input in inputs)) - self.assertTrue(constraint_exists, - f"Constraint '{key}' not found in the model.") + constraint_exists = ( + any(key == output[1]['prom_name'] for output in outputs) + or any(key == input[1]['prom_name'] for input in inputs) + or any(key == f'{name}.{output[1]["prom_name"]}' for output in outputs) + or any(key == f'{name}.{input[1]["prom_name"]}' for input in inputs) + ) + self.assertTrue(constraint_exists, f"Constraint '{key}' not found in the model.") def test_check_design_variables(self): if not hasattr(self, 'aviary_values'): @@ -350,8 +423,7 @@ def test_check_design_variables(self): design_vars = self.subsystem_builder.get_design_vars() - pre_mission_sys = self.subsystem_builder.build_pre_mission( - aviary_inputs=self.aviary_values) + pre_mission_sys = self.subsystem_builder.build_pre_mission(aviary_inputs=self.aviary_values) if pre_mission_sys is None: return @@ -359,6 +431,9 @@ def test_check_design_variables(self): group = om.Group() group.add_subsystem('pre_mission', pre_mission_sys, promotes=['*']) prob = om.Problem(group) + + setup_model_options(prob, self.aviary_values) + prob.setup() prob.final_setup() @@ -367,8 +442,7 @@ def test_check_design_variables(self): for key, value in design_vars.items(): # Check design variable existence design_var_exists = any(key == input_[1]['prom_name'] for input_ in inputs) - self.assertTrue(design_var_exists, - f"Design variable '{key}' not found in the model.") + self.assertTrue(design_var_exists, f"Design variable '{key}' not found in the model.") def test_check_initial_guesses(self): if not hasattr(self, 'aviary_values'): @@ -377,7 +451,8 @@ def test_check_initial_guesses(self): initial_guesses = self.subsystem_builder.get_initial_guesses() mission_sys = self.subsystem_builder.build_mission( - num_nodes=5, aviary_inputs=self.aviary_values) + num_nodes=5, aviary_inputs=self.aviary_values + ) if mission_sys is None: return @@ -385,6 +460,9 @@ def test_check_initial_guesses(self): group = om.Group() group.add_subsystem('mission', mission_sys, promotes=['*']) prob = om.Problem(group) + + setup_model_options(prob, self.aviary_values) + prob.setup() prob.final_setup() @@ -393,8 +471,7 @@ def test_check_initial_guesses(self): for key, value in initial_guesses.items(): # Check initial guess existence initial_guess_exists = any(key == input[1]['prom_name'] for input in inputs) - self.assertTrue(initial_guess_exists, - f"Initial guess '{key}' not found in the model.") + self.assertTrue(initial_guess_exists, f"Initial guess '{key}' not found in the model.") if __name__ == '__main__': diff --git a/aviary/subsystems/test/test_dummy_subsystem.py b/aviary/subsystems/test/test_dummy_subsystem.py index 4c68f694b5..882f2d6a17 100644 --- a/aviary/subsystems/test/test_dummy_subsystem.py +++ b/aviary/subsystems/test/test_dummy_subsystem.py @@ -1,5 +1,4 @@ import unittest - from copy import deepcopy import openmdao.api as om @@ -13,30 +12,30 @@ class Aircraft(av_Aircraft): class Dummy: - VARIABLE = "aircraft:dummy:VARIABLE" - VARIABLE_OUT = "aircraft:dummy:VARIABLE_OUT" - PARAMETER = "aircraft:dummy:PARAMETER" + VARIABLE = 'aircraft:dummy:VARIABLE' + VARIABLE_OUT = 'aircraft:dummy:VARIABLE_OUT' + PARAMETER = 'aircraft:dummy:PARAMETER' class Mission(av_Mission): class Dummy: - VARIABLE = "mission:dummy:VARIABLE" - VARIABLE_RATE = "mission:dummy:VARIABLE_RATE" + VARIABLE = 'mission:dummy:VARIABLE' + VARIABLE_RATE = 'mission:dummy:VARIABLE_RATE' class MoreAircraft(av_Aircraft): class Dummy: - DUMMY_WINGSPAN = "aircraft:dummy:DUMMY_WINGSPAN" - DUMMY_AIRSPEED = "aircraft:dummy:DUMMY_AIRSPEED" - DUMMY_FUEL_CAPACITY = "aircraft:dummy:DUMMY_FUEL_CAPACITY" + DUMMY_WINGSPAN = 'aircraft:dummy:DUMMY_WINGSPAN' + DUMMY_AIRSPEED = 'aircraft:dummy:DUMMY_AIRSPEED' + DUMMY_FUEL_CAPACITY = 'aircraft:dummy:DUMMY_FUEL_CAPACITY' class MoreMission(av_Mission): class Dummy: - DUMMY_FLIGHT_DURATION = "mission:dummy:DUMMY_FLIGHT_DURATION" - DUMMY_TAKEOFF_WEIGHT = "mission:dummy:DUMMY_TAKEOFF_WEIGHT" - DUMMY_CONTROL = "mission:dummy:DUMMY_CONTROL" - TIMESERIES_VAR = "mission:dummy:TIMESERIES_VAR" + DUMMY_FLIGHT_DURATION = 'mission:dummy:DUMMY_FLIGHT_DURATION' + DUMMY_TAKEOFF_WEIGHT = 'mission:dummy:DUMMY_TAKEOFF_WEIGHT' + DUMMY_CONTROL = 'mission:dummy:DUMMY_CONTROL' + TIMESERIES_VAR = 'mission:dummy:TIMESERIES_VAR' ExtendedMetaData = deepcopy(av.CoreMetaData) @@ -45,156 +44,156 @@ class Dummy: # Variables for ExtendedMetaData av.add_meta_data( Aircraft.Dummy.VARIABLE, - desc="Dummy aircraft variable", + desc='Dummy aircraft variable', default_value=0.5, option=False, units='kn', - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Dummy.VARIABLE_OUT, - desc="Dummy aircraft variable out", + desc='Dummy aircraft variable out', default_value=0.5, option=False, units='kg', - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Aircraft.Dummy.PARAMETER, - desc="Dummy mission parameter", + desc='Dummy mission parameter', default_value=0.5, option=False, units='m', - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Mission.Dummy.VARIABLE, - desc="Dummy mission variable", + desc='Dummy mission variable', default_value=0.5, option=False, units='m', - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) av.add_meta_data( Mission.Dummy.VARIABLE_RATE, - desc="Dummy mission variable rate", + desc='Dummy mission variable rate', default_value=0.5, option=False, units='m/s', - meta_data=ExtendedMetaData + meta_data=ExtendedMetaData, ) # Variables for AdditionalMetaData av.add_meta_data( MoreAircraft.Dummy.DUMMY_WINGSPAN, - desc="Dummy wingspan variable", + desc='Dummy wingspan variable', default_value=35.0, option=False, units='m', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( - MoreAircraft.Dummy.DUMMY_WINGSPAN+'_out', - desc="Output of dummy wingspan variable", + MoreAircraft.Dummy.DUMMY_WINGSPAN + '_out', + desc='Output of dummy wingspan variable', default_value=70.0, option=False, units='m', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( MoreAircraft.Dummy.DUMMY_AIRSPEED, - desc="Dummy airspeed variable", + desc='Dummy airspeed variable', default_value=500.0, option=False, units='kn', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( - MoreAircraft.Dummy.DUMMY_AIRSPEED+'_out', - desc="Output of dummy airspeed variable", + MoreAircraft.Dummy.DUMMY_AIRSPEED + '_out', + desc='Output of dummy airspeed variable', default_value=1000.0, option=False, units='kn', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( MoreAircraft.Dummy.DUMMY_FUEL_CAPACITY, - desc="Dummy fuel capacity variable", + desc='Dummy fuel capacity variable', default_value=20000.0, option=False, units='kg', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( - MoreAircraft.Dummy.DUMMY_FUEL_CAPACITY+'_out', - desc="Output of dummy fuel capacity variable", + MoreAircraft.Dummy.DUMMY_FUEL_CAPACITY + '_out', + desc='Output of dummy fuel capacity variable', default_value=40000.0, option=False, units='kg', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( MoreMission.Dummy.DUMMY_FLIGHT_DURATION, - desc="Dummy flight duration variable", + desc='Dummy flight duration variable', default_value=6.0, option=False, units='hr', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( - MoreMission.Dummy.DUMMY_FLIGHT_DURATION+'_rate', - desc="Rate of dummy flight duration variable", + MoreMission.Dummy.DUMMY_FLIGHT_DURATION + '_rate', + desc='Rate of dummy flight duration variable', default_value=12.0, option=False, units='hr/s', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( MoreMission.Dummy.DUMMY_TAKEOFF_WEIGHT, - desc="Dummy takeoff weight variable", + desc='Dummy takeoff weight variable', default_value=80000.0, option=False, units='kg', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( - MoreMission.Dummy.DUMMY_TAKEOFF_WEIGHT+'_rate', - desc="Rate of dummy takeoff weight variable", + MoreMission.Dummy.DUMMY_TAKEOFF_WEIGHT + '_rate', + desc='Rate of dummy takeoff weight variable', default_value=160000.0, option=False, units='kg/s', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( MoreMission.Dummy.DUMMY_CONTROL, - desc="Dummy control variable", + desc='Dummy control variable', default_value=0.5, option=False, units='unitless', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) av.add_meta_data( MoreMission.Dummy.TIMESERIES_VAR, - desc="Dummy timeseries variable", + desc='Dummy timeseries variable', default_value=0.5, option=False, units='unitless', - meta_data=AdditionalMetaData + meta_data=AdditionalMetaData, ) @@ -222,8 +221,9 @@ def setup(self): self.declare_partials('*', '*', method='fd') def compute(self, inputs, outputs): - outputs[Mission.Dummy.VARIABLE_RATE] = 2 * \ - inputs[Mission.Dummy.VARIABLE] + inputs[Aircraft.Dummy.PARAMETER] * 0.5 + outputs[Mission.Dummy.VARIABLE_RATE] = ( + 2 * inputs[Mission.Dummy.VARIABLE] + inputs[Aircraft.Dummy.PARAMETER] * 0.5 + ) class PreOnlyBuilder(SubsystemBuilderBase): @@ -237,7 +237,7 @@ def get_mass_names(self): class PostOnlyBuilder(SubsystemBuilderBase): - def build_post_mission(self, aviary_values): + def build_post_mission(self, aviary_inputs, phase_info, phase_mission_bus_lengths): group = om.Group() group.add_subsystem('comp', om.ExecComp('y = x**2'), promotes=['*']) return group @@ -268,8 +268,7 @@ def build_pre_mission(self, aviary_inputs): def build_mission(self, num_nodes, aviary_inputs): group = om.Group() - group.add_subsystem('comp', DummyMissionComp( - num_nodes=num_nodes), promotes=['*']) + group.add_subsystem('comp', DummyMissionComp(num_nodes=num_nodes), promotes=['*']) return group def get_initial_guesses(self): @@ -293,19 +292,20 @@ def get_controls(self, **kwargs): return {} def get_parameters(self, aviary_inputs=None, phase_info=None): - return {Aircraft.Dummy.PARAMETER: {'val': 2., 'units': 'm'}} + return {Aircraft.Dummy.PARAMETER: {'val': 2.0, 'units': 'm'}} class DummyWingspanComp(om.ExplicitComponent): def setup(self): self.add_input(MoreAircraft.Dummy.DUMMY_WINGSPAN, units='m') - self.add_output(MoreAircraft.Dummy.DUMMY_WINGSPAN+'_out', units='m') + self.add_output(MoreAircraft.Dummy.DUMMY_WINGSPAN + '_out', units='m') self.declare_partials('*', '*', method='fd') def compute(self, inputs, outputs): - outputs[MoreAircraft.Dummy.DUMMY_WINGSPAN+'_out'] = 2 * \ - inputs[MoreAircraft.Dummy.DUMMY_WINGSPAN] + outputs[MoreAircraft.Dummy.DUMMY_WINGSPAN + '_out'] = ( + 2 * inputs[MoreAircraft.Dummy.DUMMY_WINGSPAN] + ) class DummyFlightDurationComp(om.ExplicitComponent): @@ -316,17 +316,20 @@ def setup(self): nn = self.options['num_nodes'] self.add_input(MoreMission.Dummy.DUMMY_FLIGHT_DURATION, units='h', shape=nn) self.add_input(MoreMission.Dummy.DUMMY_CONTROL, units='unitless', shape=nn) - self.add_output(MoreMission.Dummy.DUMMY_FLIGHT_DURATION + - '_rate', units='h/s', shape=nn) + self.add_output(MoreMission.Dummy.DUMMY_FLIGHT_DURATION + '_rate', units='h/s', shape=nn) self.add_output(MoreMission.Dummy.TIMESERIES_VAR, units='unitless', shape=nn) self.declare_partials('*', '*', method='fd') def compute(self, inputs, outputs): - outputs[MoreMission.Dummy.DUMMY_FLIGHT_DURATION+'_rate'] = 2 * \ - inputs[MoreMission.Dummy.DUMMY_FLIGHT_DURATION] * \ - inputs[MoreMission.Dummy.DUMMY_CONTROL] - outputs[MoreMission.Dummy.TIMESERIES_VAR] = inputs[MoreMission.Dummy.DUMMY_CONTROL] ** 2 + 0.5 + outputs[MoreMission.Dummy.DUMMY_FLIGHT_DURATION + '_rate'] = ( + 2 + * inputs[MoreMission.Dummy.DUMMY_FLIGHT_DURATION] + * inputs[MoreMission.Dummy.DUMMY_CONTROL] + ) + outputs[MoreMission.Dummy.TIMESERIES_VAR] = ( + inputs[MoreMission.Dummy.DUMMY_CONTROL] ** 2 + 0.5 + ) class AdditionalArrayGuessSubsystemBuilder(SubsystemBuilderBase): @@ -340,8 +343,7 @@ def build_pre_mission(self, aviary_inputs): def build_mission(self, num_nodes, aviary_inputs): group = om.Group() - group.add_subsystem('comp', DummyFlightDurationComp( - num_nodes=num_nodes), promotes=['*']) + group.add_subsystem('comp', DummyFlightDurationComp(num_nodes=num_nodes), promotes=['*']) return group def get_initial_guesses(self): @@ -356,13 +358,13 @@ def get_initial_guesses(self): def get_states(self): return { MoreMission.Dummy.DUMMY_FLIGHT_DURATION: { - 'rate_source': MoreMission.Dummy.DUMMY_FLIGHT_DURATION+'_rate', + 'rate_source': MoreMission.Dummy.DUMMY_FLIGHT_DURATION + '_rate', 'units': 'h', } } def get_controls(self, phase_name=None): - if phase_name == "cruise": + if phase_name == 'cruise': controls_dict = { MoreMission.Dummy.DUMMY_CONTROL: { 'units': 'unitless', diff --git a/aviary/subsystems/test/test_external_subsystem_bus.py b/aviary/subsystems/test/test_external_subsystem_bus.py index a5a3294681..49ef0a3ee2 100644 --- a/aviary/subsystems/test/test_external_subsystem_bus.py +++ b/aviary/subsystems/test/test_external_subsystem_bus.py @@ -1,123 +1,378 @@ -""" -Test external subsystem bus API. -""" -from copy import deepcopy +"""Test external subsystem bus API.""" + import unittest +from copy import deepcopy import numpy as np - import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs -from aviary.interface.default_phase_info.height_energy import phase_info as ph_in +import aviary.api as av +from aviary.models.missions.height_energy_default import phase_info as ph_in from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.subsystem_builder_base import SubsystemBuilderBase +from aviary.variable_info.variables import Dynamic + + +ExtendedMetaData = av.CoreMetaData + + +av.add_meta_data( + 'the_shape_for_the_thing_dim0', + units='unitless', + desc='length for the first dimension PreMissionComp outputs', + default_value=2, + types=int, + option=True, + meta_data=ExtendedMetaData, +) + +av.add_meta_data( + 'the_shape_for_the_thing_dim1', + units='unitless', + desc='length for the second dimension PreMissionComp outputs', + default_value=3, + types=int, + option=True, + meta_data=ExtendedMetaData, +) class PreMissionComp(om.ExplicitComponent): + def initialize(self): + self.options.declare('shape', default=(2, 3)) def setup(self): - self.add_output('for_climb', np.ones((2, 1)), units='ft') - self.add_output('for_cruise', np.ones((2, 1)), units='ft') - self.add_output('for_descent', np.ones((2, 1)), units='ft') + shape = self.options['shape'] + self.add_output('for_climb', np.ones(shape), units='ft') + self.add_output('for_cruise', np.ones(shape), units='ft') + self.add_output('for_descent', np.ones(shape), units='ft') def compute(self, inputs, outputs): - outputs['for_climb'] = np.array([[3.1], [1.7]]) - outputs['for_cruise'] = np.array([[1.2], [4.1]]) - outputs['for_descent'] = np.array([[3.], [8.]]) + shape = self.options['shape'] + outputs['for_climb'] = np.random.random(shape) + outputs['for_cruise'] = np.random.random(shape) + outputs['for_descent'] = np.random.random(shape) class MissionComp(om.ExplicitComponent): + def initialize(self): + self.options.declare('shape', default=1) + self.options.declare('num_nodes', default=1) + + def setup(self): + shape = self.options['shape'] + num_nodes = self.options['num_nodes'] + self.add_input('xx', shape=shape, units='ft') + self.add_output('yy', shape=num_nodes, units='ft') + self.add_output('zz', shape=num_nodes, units='ft') + def compute(self, inputs, outputs): + num_nodes = self.options['num_nodes'] + outputs['yy'] = 2.0 * np.sum(inputs['xx']) * range(num_nodes) + outputs['zz'] = 3.0 * np.sum(inputs['xx']) * range(num_nodes) + + +class PostMissionComp(om.ExplicitComponent): def initialize(self): - self.options.declare('shape', default=(1, )) + self.options.declare('do_the_zz_thing', types=bool, default=False) + self.options.declare('shape', default=(2, 3)) + self.options.declare('num_nodes', default=1) def setup(self): shape = self.options['shape'] + num_nodes = self.options['num_nodes'] self.add_input('xx', shape=shape, units='ft') - self.add_output('yy', shape=shape, units='ft') + if self.options['do_the_zz_thing']: + self.add_input('zz', shape=num_nodes, units='ft') + self.add_input('velocity', shape=num_nodes, units='ft/s') + self.add_output('zzz', shape=1, units='ft') def compute(self, inputs, outputs): - outputs['yy'] = 2.0 * inputs['xx'] + outputs['zzz'] = np.sum(inputs['xx']) + if self.options['do_the_zz_thing']: + outputs['zzz'] *= np.sum(inputs['zz'] * inputs['velocity']) class CustomBuilder(SubsystemBuilderBase): + def __init__(self, name, mangle_names=False): + self.mangle_names = mangle_names + super().__init__(name) def build_pre_mission(self, aviary_inputs): - return PreMissionComp() + shape = ( + aviary_inputs.get_val('the_shape_for_the_thing_dim0'), + aviary_inputs.get_val('the_shape_for_the_thing_dim1'), + ) + if self.mangle_names: + sys = om.Group() + name = self.name + sys.add_subsystem( + 'foo', + PreMissionComp(shape=shape), + promotes_outputs=[ + ('for_climb', f'{name}_for_climb'), + ('for_cruise', f'{name}_for_cruise'), + ('for_descent', f'{name}_for_descent'), + ], + ) + + else: + sys = PreMissionComp(shape=shape) + return sys def build_mission(self, num_nodes, aviary_inputs): sub_group = om.Group() - sub_group.add_subsystem('electric', MissionComp(shape=(2, 1)), - promotes_inputs=['*'], - promotes_outputs=['*'], - ) + shape = ( + aviary_inputs.get_val('the_shape_for_the_thing_dim0'), + aviary_inputs.get_val('the_shape_for_the_thing_dim1'), + ) + comp = MissionComp(shape=shape, num_nodes=num_nodes) + if self.mangle_names: + name = self.name + sub_group.add_subsystem( + 'electric', + comp, + promotes_inputs=[('xx', f'{name}_xx')], + promotes_outputs=[('yy', f'{name}_yy'), ('zz', f'{name}_zz')], + ) + else: + sub_group.add_subsystem( + 'electric', + comp, + promotes_inputs=['*'], + promotes_outputs=['*'], + ) return sub_group - def get_bus_variables(self): - vars_to_connect = { - "test.for_climb": { - "mission_name": ['test.xx'], - "units": 'ft', - "shape": (2, 1), - "phases": ['climb'] - }, - "test.for_cruise": { - "mission_name": ['test.xx'], - "units": 'ft', - "shape": (2, 1), - "phases": ['cruise'] - }, - "test.for_descent": { - "mission_name": ['test.xx'], - "units": 'ft', - "shape": (2, 1), - "phases": ['descent'] - }, - } - + def get_pre_mission_bus_variables(self, aviary_inputs): + shape = ( + aviary_inputs.get_val('the_shape_for_the_thing_dim0'), + aviary_inputs.get_val('the_shape_for_the_thing_dim1'), + ) + name = self.name + if self.mangle_names: + vars_to_connect = { + f'{name}.{name}_for_climb': { + 'mission_name': [f'{name}.{name}_xx'], + 'post_mission_name': f'{name}.climb_{name}_xx', + 'units': 'ft', + 'shape': shape, + 'phases': ['climb'], + }, + f'{name}.{name}_for_cruise': { + 'mission_name': [f'{name}.{name}_xx'], + 'post_mission_name': f'{name}.cruise_{name}_xx', + 'units': 'ft', + 'shape': shape, + 'phases': ['cruise'], + }, + f'{name}.{name}_for_descent': { + 'mission_name': [f'{name}.{name}_xx'], + 'post_mission_name': [f'{name}.descent_{name}_xx'], + 'units': 'ft', + 'shape': shape, + 'phases': ['descent'], + }, + } + else: + vars_to_connect = { + f'{name}.for_climb': { + 'mission_name': [f'{name}.xx'], + 'post_mission_name': f'{name}.climb_xx', + 'units': 'ft', + 'shape': shape, + 'phases': ['climb'], + }, + f'{name}.for_cruise': { + 'mission_name': [f'{name}.xx'], + 'post_mission_name': f'{name}.cruise_xx', + 'units': 'ft', + 'shape': shape, + 'phases': ['cruise'], + }, + f'{name}.for_descent': { + 'mission_name': [f'{name}.xx'], + 'post_mission_name': [f'{name}.descent_xx'], + 'units': 'ft', + 'shape': shape, + 'phases': ['descent'], + }, + } return vars_to_connect + def get_post_mission_bus_variables(self, aviary_inputs, phase_info): + name = self.name + out = {} + for phase_name, phase_data in phase_info.items(): + phase_d = {} + if phase_data.get('do_the_zz_thing', False): + if self.mangle_names: + phase_d[f'{name}.{name}_zz'] = { + 'post_mission_name': f'{name}.{phase_name}_{name}_zz' + } + phase_d[Dynamic.Mission.VELOCITY] = { + 'post_mission_name': f'{name}.{phase_name}_{name}_velocity' + } + else: + phase_d[f'{name}.zz'] = {'post_mission_name': f'{name}.{phase_name}_zz'} + phase_d[Dynamic.Mission.VELOCITY] = { + 'post_mission_name': f'{name}.{phase_name}_velocity' + } + out[phase_name] = phase_d + return out + + def build_post_mission(self, aviary_inputs, phase_info, phase_mission_bus_lengths, **kwargs): + shape = ( + aviary_inputs.get_val('the_shape_for_the_thing_dim0'), + aviary_inputs.get_val('the_shape_for_the_thing_dim1'), + ) + group = om.Group() + name = self.name + for phase_name, phase_data in phase_info.items(): + do_the_zz_thing = phase_data.get('do_the_zz_thing', False) + num_nodes = phase_mission_bus_lengths[phase_name] + comp = PostMissionComp( + num_nodes=num_nodes, shape=shape, do_the_zz_thing=do_the_zz_thing + ) + if self.mangle_names: + pi = [('xx', f'{phase_name}_{name}_xx')] + if do_the_zz_thing: + pi.append(('zz', f'{phase_name}_{name}_zz')) + pi.append(('velocity', f'{phase_name}_{name}_velocity')) + po = [('zzz', f'{phase_name}_{name}_zzz')] + else: + pi = [('xx', f'{phase_name}_xx')] + if do_the_zz_thing: + pi.append(('zz', f'{phase_name}_zz')) + pi.append(('velocity', f'{phase_name}_velocity')) + po = [('zzz', f'{phase_name}_zzz')] + group.add_subsystem( + f'{phase_name}_post_mission', comp, promotes_inputs=pi, promotes_outputs=po + ) + return group -class TestExternalSubsystemBus(unittest.TestCase): +@use_tempdirs +class TestExternalSubsystemBus(unittest.TestCase): def test_external_subsystem_bus(self): phase_info = deepcopy(ph_in) - phase_info['pre_mission']['external_subsystems'] = [CustomBuilder(name='test')] - phase_info['climb']['external_subsystems'] = [CustomBuilder(name='test')] - phase_info['cruise']['external_subsystems'] = [CustomBuilder(name='test')] - phase_info['descent']['external_subsystems'] = [CustomBuilder(name='test')] + # Adding two `CustomBuilder` external subsystems will test that we can request `Dynamic.Mission.VELOCITY` be a mission bus variable twice. + phase_info['pre_mission']['external_subsystems'] = [ + CustomBuilder(name='test'), + CustomBuilder(name='test2', mangle_names=True), + ] + phase_info['climb']['external_subsystems'] = [ + CustomBuilder(name='test'), + CustomBuilder(name='test2', mangle_names=True), + ] + phase_info['cruise']['external_subsystems'] = [ + CustomBuilder(name='test'), + CustomBuilder(name='test2', mangle_names=True), + ] + phase_info['descent']['external_subsystems'] = [ + CustomBuilder(name='test'), + CustomBuilder(name='test2', mangle_names=True), + ] + phase_info['post_mission']['external_subsystems'] = [ + CustomBuilder(name='test'), + CustomBuilder(name='test2', mangle_names=True), + ] + + phase_info['climb']['do_the_zz_thing'] = True + phase_info['descent']['do_the_zz_thing'] = False prob = AviaryProblem() - csv_path = "models/test_aircraft/aircraft_for_bench_FwFm.csv" + csv_path = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' prob.load_inputs(csv_path, phase_info) + prob.aviary_inputs.set_val('the_shape_for_the_thing_dim0', 3, meta_data=ExtendedMetaData) + prob.aviary_inputs.set_val('the_shape_for_the_thing_dim1', 4, meta_data=ExtendedMetaData) prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() + prob.build_model() prob.setup() - prob.set_initial_guesses() # Just run once to pass data. prob.run_model() - # Each phase should have a different value passed from pre using the bus. - assert_near_equal( - prob.model.get_val('traj.climb.rhs_all.test.yy'), - 2.0 * np.array([[3.1], [1.7]]), - ) - assert_near_equal( - prob.model.get_val('traj.cruise.rhs_all.test.yy'), - 2.0 * np.array([[1.2], [4.1]]), - ) - assert_near_equal( - prob.model.get_val('traj.descent.rhs_all.test.yy'), - 2.0 * np.array([[3.], [8.]]), - ) + # Make sure the values are correct. + yy_actual = prob.model.get_val('traj.climb.rhs_all.test.yy') + xx = prob.model.get_val('pre_mission.test.for_climb') + yy_expected = 2.0 * np.sum(xx) * range(len(yy_actual)) + assert_near_equal(yy_actual, yy_expected) + zz_actual = prob.model.get_val('traj.climb.rhs_all.test.zz') + zz_expected = 3.0 * np.sum(xx) * range(len(zz_actual)) + assert_near_equal(zz_actual, zz_expected) + + yy_actual = prob.model.get_val('traj.climb.rhs_all.test2.test2_yy') + xx = prob.model.get_val('pre_mission.test2.test2_for_climb') + yy_expected = 2.0 * np.sum(xx) * range(len(yy_actual)) + assert_near_equal(yy_actual, yy_expected) + zz_actual = prob.model.get_val('traj.climb.rhs_all.test2.test2_zz') + zz_expected = 3.0 * np.sum(xx) * range(len(zz_actual)) + assert_near_equal(zz_actual, zz_expected) + + yy_actual = prob.model.get_val('traj.cruise.rhs_all.test.yy') + xx = prob.model.get_val('pre_mission.test.for_cruise') + yy_expected = 2.0 * np.sum(xx) * range(len(yy_actual)) + assert_near_equal(yy_actual, yy_expected) + zz_actual = prob.model.get_val('traj.cruise.rhs_all.test.zz') + zz_expected = 3.0 * np.sum(xx) * range(len(zz_actual)) + assert_near_equal(zz_actual, zz_expected) + + yy_actual = prob.model.get_val('traj.cruise.rhs_all.test2.test2_yy') + xx = prob.model.get_val('pre_mission.test2.test2_for_cruise') + yy_expected = 2.0 * np.sum(xx) * range(len(yy_actual)) + assert_near_equal(yy_actual, yy_expected) + zz_actual = prob.model.get_val('traj.cruise.rhs_all.test2.test2_zz') + zz_expected = 3.0 * np.sum(xx) * range(len(zz_actual)) + assert_near_equal(zz_actual, zz_expected) + + yy_actual = prob.model.get_val('traj.descent.rhs_all.test.yy') + xx = prob.model.get_val('pre_mission.test.for_descent') + yy_expected = 2.0 * np.sum(xx) * range(len(yy_actual)) + assert_near_equal(yy_actual, yy_expected) + zz_actual = prob.model.get_val('traj.descent.rhs_all.test.zz') + zz_expected = 3.0 * np.sum(xx) * range(len(zz_actual)) + assert_near_equal(zz_actual, zz_expected) + + # Only climb should have the zz and velocity outputs connected to post-mission. + zzz_actual = prob.model.get_val('test.climb_zzz') + xx = prob.model.get_val('pre_mission.test.for_climb') + zz = prob.model.get_val('traj.climb.mission_bus_variables.zz') + velocity = prob.model.get_val('traj.climb.mission_bus_variables.velocity') + zzz_expected = np.sum(xx) * np.sum(zz * velocity) + assert_near_equal(zzz_actual, zzz_expected) + + zzz_actual = prob.model.get_val('test2.climb_test2_zzz') + xx = prob.model.get_val('pre_mission.test2.test2_for_climb') + zz = prob.model.get_val('traj.climb.mission_bus_variables.test2_zz') + velocity = prob.model.get_val('traj.climb.mission_bus_variables.velocity') + zzz_expected = np.sum(xx) * np.sum(zz * velocity) + assert_near_equal(zzz_actual, zzz_expected) + + zzz_actual = prob.model.get_val('test.cruise_zzz') + xx = prob.model.get_val('pre_mission.test.for_cruise') + zzz_expected = np.sum(xx) + assert_near_equal(zzz_actual, zzz_expected) + + zzz_actual = prob.model.get_val('test2.cruise_test2_zzz') + xx = prob.model.get_val('pre_mission.test2.test2_for_cruise') + zzz_expected = np.sum(xx) + assert_near_equal(zzz_actual, zzz_expected) + + zzz_actual = prob.model.get_val('test.descent_zzz') + xx = prob.model.get_val('pre_mission.test.for_descent') + zzz_expected = np.sum(xx) + assert_near_equal(zzz_actual, zzz_expected) + + zzz_actual = prob.model.get_val('test2.descent_test2_zzz') + xx = prob.model.get_val('pre_mission.test2.test2_for_descent') + zzz_expected = np.sum(xx) + assert_near_equal(zzz_actual, zzz_expected) if __name__ == '__main__': diff --git a/aviary/subsystems/test/test_flops_based_premission.py b/aviary/subsystems/test/test_flops_based_premission.py index 7d8934b442..4256a71099 100644 --- a/aviary/subsystems/test/test_flops_based_premission.py +++ b/aviary/subsystems/test/test_flops_based_premission.py @@ -1,50 +1,60 @@ import unittest -from parameterized import parameterized import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials +from openmdao.utils.testing_utils import use_tempdirs +from parameterized import parameterized from aviary.subsystems.premission import CorePreMission -from aviary.utils.aviary_values import AviaryValues +from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.functions import set_aviary_initial_values +from aviary.utils.preprocessors import preprocess_options +from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems from aviary.validation_cases.validation_tests import ( - flops_validation_test, get_flops_inputs, get_flops_outputs, get_flops_case_names, print_case + flops_validation_test, + get_flops_case_names, + get_flops_inputs, + get_flops_outputs, + print_case, ) +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Mission, Settings -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.test_utils.default_subsystems import get_default_premission_subsystems -from aviary.utils.preprocessors import preprocess_options +@use_tempdirs class PreMissionGroupTest(unittest.TestCase): def setUp(self): - self.prob = om.Problem() - @parameterized.expand(get_flops_case_names(), - name_func=print_case) + @parameterized.expand(get_flops_case_names(), name_func=print_case) def test_case(self, case_name): flops_inputs = get_flops_inputs(case_name) flops_outputs = get_flops_outputs(case_name) - flops_inputs.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, - flops_outputs.get_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES)) + flops_inputs.set_val( + Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, + flops_outputs.get_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES), + ) flops_inputs.set_val(Settings.VERBOSITY, 0) - engine = build_engine_deck(flops_inputs) - preprocess_options(flops_inputs, engine_models=engine) - default_premission_subsystems = get_default_premission_subsystems( - 'FLOPS', engine) + engines = [build_engine_deck(flops_inputs)] + preprocess_options(flops_inputs, engine_models=engines) + default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines) prob = self.prob prob.model.add_subsystem( - "pre_mission", - CorePreMission(aviary_options=flops_inputs, - subsystems=default_premission_subsystems), + 'pre_mission', + CorePreMission(aviary_options=flops_inputs, subsystems=default_premission_subsystems), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options(prob, flops_inputs) + + # prob.model.set_input_defaults( + # Aircraft.Engine.SCALE_FACTOR, + # flops_inputs.get_val( + # Aircraft.Engine.SCALE_FACTOR)) + prob.setup(check=False, force_alloc_complex=True) prob.set_solver_print(2) @@ -61,64 +71,125 @@ def test_case(self, case_name): prob[Aircraft.Wing.THICKNESS_TO_CHORD_REF] = prob[Aircraft.Wing.THICKNESS_TO_CHORD] prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS] = flops_outputs.get_val( - Aircraft.Propulsion.TOTAL_ENGINE_MASS, units='lbm') + Aircraft.Propulsion.TOTAL_ENGINE_MASS, units='lbm' + ) prob[Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS] = flops_outputs.get_val( - Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, units='lbm') + Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, units='lbm' + ) flops_validation_test( prob, case_name, input_keys=[], - output_keys=[Aircraft.Design.STRUCTURE_MASS, - Aircraft.Propulsion.MASS, - Aircraft.Design.SYSTEMS_EQUIP_MASS, - Aircraft.Design.EMPTY_MASS, - Aircraft.Design.OPERATING_MASS, - Aircraft.Design.ZERO_FUEL_MASS, - Mission.Design.FUEL_MASS], + output_keys=[ + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Propulsion.MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS, + Aircraft.Design.EMPTY_MASS, + Mission.Summary.OPERATING_MASS, + Mission.Summary.ZERO_FUEL_MASS, + Mission.Summary.FUEL_MASS, + ], step=1.01e-40, atol=1e-8, - rtol=1e-10) + rtol=1e-10, + ) def test_diff_configuration_mass(self): # This standalone test provides coverage for some features unique to this # model. - from aviary.models.large_single_aisle_2.large_single_aisle_2_FLOPS_data import LargeSingleAisle2FLOPS prob = om.Problem() - flops_inputs: AviaryValues = LargeSingleAisle2FLOPS['inputs'] - flops_outputs: AviaryValues = LargeSingleAisle2FLOPS['outputs'] + flops_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') + flops_outputs = get_flops_outputs('LargeSingleAisle2FLOPS') flops_inputs.set_val(Settings.VERBOSITY, 0) - engine = build_engine_deck(flops_inputs) - preprocess_options(flops_inputs, engine_models=engine) - default_premission_subsystems = get_default_premission_subsystems( - 'FLOPS', engine) + engines = [build_engine_deck(flops_inputs)] + preprocess_options(flops_inputs, engine_models=engines) + default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines) prob.model.add_subsystem( - "pre_mission", - CorePreMission(aviary_options=flops_inputs, - subsystems=default_premission_subsystems), + 'pre_mission', + CorePreMission(aviary_options=flops_inputs, subsystems=default_premission_subsystems), promotes_inputs=['*'], promotes_outputs=['*'], ) + setup_model_options(prob, flops_inputs) + prob.setup(check=False) set_aviary_initial_values(prob, flops_inputs) flops_validation_test( prob, - "LargeSingleAisle2FLOPS", + 'LargeSingleAisle2FLOPS', + input_keys=[], + output_keys=[Mission.Summary.FUEL_MASS], + atol=1e-4, + rtol=1e-4, + check_partials=False, + flops_inputs=flops_inputs, + flops_outputs=flops_outputs, + ) + + def test_mass_aero_only(self): + # tests geom, mass, aero only, similar to IANAL=2 mode in FLOPS + prob = om.Problem() + + flops_inputs = get_flops_inputs('LargeSingleAisle2FLOPS') + flops_outputs = get_flops_outputs('LargeSingleAisle2FLOPS') + flops_inputs.set_val(Settings.VERBOSITY, 0) + + engines = [build_engine_deck(flops_inputs)] + + preprocess_options(flops_inputs, engine_models=engines) + + default_premission_subsystems = get_default_premission_subsystems('FLOPS', engines=engines)[ + 1: + ] + + prob.model.add_subsystem( + 'mass_and_aero_premission', + CorePreMission(aviary_options=flops_inputs, subsystems=default_premission_subsystems), + promotes=['*'], + ) + + setup_model_options(prob, flops_inputs) + prob.setup() + set_aviary_initial_values(prob, flops_inputs) + + prob.set_val( + Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, + flops_outputs.get_val(Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, 'lbf'), + 'lbf', + ) + prob.run_model() + + flops_validation_test( + prob, + 'LargeSingleAisle2FLOPS', input_keys=[], - output_keys=[Mission.Design.FUEL_MASS], + output_keys=[ + Aircraft.Design.STRUCTURE_MASS, + Aircraft.Propulsion.MASS, + Aircraft.Design.SYSTEMS_EQUIP_MASS, + Aircraft.Design.EMPTY_MASS, + Mission.Summary.OPERATING_MASS, + Mission.Summary.ZERO_FUEL_MASS, + Mission.Summary.FUEL_MASS, + ], atol=1e-4, rtol=1e-4, check_partials=False, flops_inputs=flops_inputs, - flops_outputs=flops_outputs) + flops_outputs=flops_outputs, + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = PreMissionGroupTest() + # test.setUp() + # test.test_mass_aero_only() diff --git a/aviary/subsystems/test/test_gasp_based_premission.py b/aviary/subsystems/test/test_gasp_based_premission.py new file mode 100644 index 0000000000..9cf8eabf39 --- /dev/null +++ b/aviary/subsystems/test/test_gasp_based_premission.py @@ -0,0 +1,415 @@ +import unittest + +from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.subsystems.premission import CorePreMission +from aviary.subsystems.propulsion.utils import build_engine_deck +from aviary.utils.functions import set_aviary_initial_values +from aviary.utils.preprocessors import preprocess_options +from aviary.utils.test_utils.default_subsystems import ( + get_default_premission_subsystems, + get_geom_and_mass_subsystems, +) +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Mission + + +@use_tempdirs +class PreMissionGroupTest(unittest.TestCase): + def setUp(self): + prob = self.prob = AviaryProblem() + + csv_path = 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv' + self.gasp_inputs = prob.load_inputs(csv_path) + self.gasp_inputs.set_val( + Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, val=False, units='unitless' + ) + prob.check_and_preprocess_inputs() + + def test_case1(self): + """premission: geometry + mass.""" + prob = self.prob + preprocess_options(self.gasp_inputs) + geom_and_mass_subsystems = get_geom_and_mass_subsystems('GASP') + + prob.model.add_subsystem( + 'pre_mission', + CorePreMission(aviary_options=self.gasp_inputs, subsystems=geom_and_mass_subsystems), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + setup_model_options(prob, self.gasp_inputs) + prob.setup(check=False) + set_aviary_initial_values(prob, self.gasp_inputs) + + prob.set_val(Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.3648, units='unitless') + prob.set_val(Aircraft.Engine.SCALED_SLS_THRUST, val=29500, units='lbf') + + prob.run_model() + + tol = 1e-5 + # propulsion subsystem + # geometry subsystem + assert_near_equal(prob[Aircraft.Fuselage.AVG_DIAMETER], 157.2, tol) + assert_near_equal(prob[Aircraft.Fuselage.LENGTH], 129.497, tol) + assert_near_equal(prob[Aircraft.Fuselage.WETTED_AREA], 4000.0, tol) + assert_near_equal(prob[Aircraft.Wing.AREA], 1370.3125, tol) + assert_near_equal(prob[Aircraft.Wing.SPAN], 117.81878299, tol) + assert_near_equal(prob[Aircraft.Wing.CENTER_CHORD], 17.48974356, tol) + assert_near_equal(prob[Aircraft.Wing.AVERAGE_CHORD], 12.61453233, tol) + assert_near_equal(prob[Aircraft.Wing.ROOT_CHORD], 16.40711451, tol) + assert_near_equal(prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.139656, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 1114.0056, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AREA], 375.8798, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.SPAN], 42.2543, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.ROOT_CHORD], 13.1592, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.5768, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MOMENT_ARM], 54.6793, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AREA], 469.3183, tol) + assert_near_equal(prob[Aircraft.VerticalTail.SPAN], 27.9957, tol) + assert_near_equal(prob[Aircraft.VerticalTail.ROOT_CHORD], 18.6162, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.8321, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MOMENT_ARM], 49.8809, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_DIAMETER], 7.25, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_LENGTH], 14.5, tol) + assert_near_equal(prob[Aircraft.Nacelle.SURFACE_AREA], 330.2599, tol) + # mass subsystem + assert_near_equal(self.prob[Aircraft.Design.LIFT_CURVE_SLOPE], 6.39471, tol) + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) + assert_near_equal(self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.22129, tol) + assert_near_equal(self.prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 36000.0, tol) + assert_near_equal(self.prob[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS], 36000.0, tol) + assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12605.94, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.MASS], 990.7798, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.MASS], 2276.1316, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], 2297.9697, tol) + assert_near_equal(self.prob[Aircraft.Wing.HIGH_LIFT_MASS], 4740.1241, tol) + assert_near_equal(self.prob[Aircraft.Controls.TOTAL_MASS], 3819.3564, tol) + assert_near_equal(self.prob[Aircraft.Wing.SURFACE_CONTROL_MASS], 3682.099, tol) + assert_near_equal(prob[Aircraft.LandingGear.TOTAL_MASS], 7489.8343, tol) + assert_near_equal(prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6366.3591, tol) + assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 21078.3911, tol) + assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5341.4317956, tol) + + assert_near_equal(prob[Aircraft.Engine.ADDITIONAL_MASS], 850.90095, tol) + assert_near_equal(prob[Aircraft.Wing.MASS], 16206.8122, tol) + assert_near_equal(prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1740.2606, tol) + assert_near_equal(prob[Aircraft.Design.STRUCTURE_MASS], 50667.4376, tol) + assert_near_equal(prob[Aircraft.Fuselage.MASS], 18673.0352, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS_REQUIRED], 42445.3806, tol) + assert_near_equal(prob[Aircraft.Propulsion.MASS], 16048.0025, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS], 42445.3806, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 848.5301, tol) + assert_near_equal(prob[Mission.Summary.OPERATING_MASS], 96954.6194, tol) + assert_near_equal(prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol) + + def test_case2(self): + """premission: propulsion + geometry + aerodynamics + mass""" + + prob = self.prob + engines = [build_engine_deck(self.gasp_inputs)] + preprocess_options(self.gasp_inputs, engine_models=engines) + default_premission_subsystems = get_default_premission_subsystems('GASP', engines) + + prob.model.add_subsystem( + 'pre_mission', + CorePreMission( + aviary_options=self.gasp_inputs, subsystems=default_premission_subsystems + ), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + setup_model_options(prob, self.gasp_inputs) + prob.setup(check=False) + set_aviary_initial_values(prob, self.gasp_inputs) + + prob.run_model() + + tol = 1e-5 + # propulsion subsystem + assert_near_equal(prob[Aircraft.Engine.SCALED_SLS_THRUST], 28690.0, tol) + # geometry subsystem + assert_near_equal(prob[Aircraft.Fuselage.AVG_DIAMETER], 157.2, tol) + assert_near_equal(prob[Aircraft.Fuselage.LENGTH], 129.497, tol) + assert_near_equal(prob[Aircraft.Fuselage.WETTED_AREA], 4000.0, tol) + assert_near_equal(prob[Aircraft.Wing.AREA], 1370.3125, tol) + assert_near_equal(prob[Aircraft.Wing.SPAN], 117.81878299, tol) + assert_near_equal(prob[Aircraft.Wing.CENTER_CHORD], 17.48974356, tol) + assert_near_equal(prob[Aircraft.Wing.AVERAGE_CHORD], 12.61453233, tol) + assert_near_equal(prob[Aircraft.Wing.ROOT_CHORD], 16.40711451, tol) + assert_near_equal(prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.139656, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 1114.0056, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AREA], 375.8798, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.SPAN], 42.2543, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.ROOT_CHORD], 13.1592, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.5768, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MOMENT_ARM], 54.6793, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AREA], 469.3183, tol) + assert_near_equal(prob[Aircraft.VerticalTail.SPAN], 27.9957, tol) + assert_near_equal(prob[Aircraft.VerticalTail.ROOT_CHORD], 18.6162, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.8321, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MOMENT_ARM], 49.8809, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_DIAMETER], 7.25, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_LENGTH], 14.5, tol) + assert_near_equal(prob[Aircraft.Nacelle.SURFACE_AREA], 330.2599, tol) + # aerodynamics subsystem + assert_near_equal(prob[Mission.Landing.LIFT_COEFFICIENT_MAX], 2.82008, tol) + # mass subsystem + assert_near_equal(self.prob[Aircraft.Design.LIFT_CURVE_SLOPE], 6.39471, tol) + assert_near_equal(self.prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.75, tol) + assert_near_equal(self.prob[Aircraft.Wing.MATERIAL_FACTOR], 1.22129, tol) + assert_near_equal(self.prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 36000.0, tol) + assert_near_equal(self.prob[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS], 36000.0, tol) + assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12259.8108, tol) + assert_near_equal(self.prob[Aircraft.Nacelle.MASS], 990.7798, tol) + assert_near_equal(self.prob[Aircraft.HorizontalTail.MASS], 2276.1316, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.MASS], 2297.9697, tol) + assert_near_equal(self.prob[Aircraft.Wing.HIGH_LIFT_MASS], 4158.5858, tol) + assert_near_equal(self.prob[Aircraft.Controls.TOTAL_MASS], 3819.3564, tol) + assert_near_equal(self.prob[Aircraft.Wing.SURFACE_CONTROL_MASS], 3682.099, tol) + assert_near_equal(prob[Aircraft.LandingGear.TOTAL_MASS], 7489.8343, tol) + assert_near_equal(prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6366.3591, tol) + assert_near_equal(self.prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 21078.3911, tol) + assert_near_equal(self.prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5332.684, tol) + assert_near_equal(prob[Aircraft.Engine.ADDITIONAL_MASS], 827.5372, tol) + assert_near_equal(prob[Aircraft.Wing.MASS], 15649.1082, tol) + assert_near_equal(prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1779.1662, tol) + assert_near_equal(prob[Aircraft.Design.STRUCTURE_MASS], 50081.2197, tol) + assert_near_equal(prob[Aircraft.Fuselage.MASS], 18675.0408, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS_REQUIRED], 43394.2976, tol) + assert_near_equal(prob[Aircraft.Propulsion.MASS], 15694.0515, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS], 43394.2976, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 867.5, tol) + assert_near_equal(prob[Mission.Summary.OPERATING_MASS], 96005.7024, tol) + assert_near_equal(prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 0, tol) + + +@use_tempdirs +class BWBPreMissionGroupTest(unittest.TestCase): + def setUp(self): + prob = self.prob = AviaryProblem() + + csv_path = 'models/aircraft/blended_wing_body/generic_BWB_GASP.csv' + self.gasp_inputs = prob.load_inputs(csv_path) + prob.check_and_preprocess_inputs() + + def test_case1(self): + """ + premission: propulsion + geometry + aerodynamics + mass + Testing GASP data case: + Aircraft.Design.LIFT_CURVE_SLOPE -- CLALPH = 6.515 + Note: In GASP, CLALPH is first calculated in CLA() and get 5.9485 and + later updated in CLIFT() and get 6.515. + Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS -- WPES = 2055 + Aircraft.Wing.ULTIMATE_LOAD_FACTOR -- ULF = 3.7734 + Aircraft.Wing.MATERIAL_FACTOR -- SKNO = 1.19461238 + Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS -- WPL = 33750 + Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS -- not in GASP + Aircraft.Propulsion.TOTAL_ENGINE_MASS -- WEP = 7005. + Aircraft.Nacelle.MASS -- WNAC = 303.6144075 by hand computation + Aircraft.HorizontalTail.MASS -- WHT = 1 + Aircraft.VerticalTail.MASS -- WVT = 864 + Aircraft.Wing.HIGH_LIFT_MASS -- WHLDEV = 974.0 + Aircraft.Controls.TOTAL_MASS -- WFC = 2115 + Aircraft.Wing.SURFACE_CONTROL_MASS -- not in GASP + Aircraft.LandingGear.TOTAL_MASS -- WLG = 7800 + Aircraft.LandingGear.MAIN_GEAR_MASS -- WMG = 6630 + Aircraft.Avionics.MASS -- CW(5) = 3225.0 + Aircraft.AirConditioning.MASS -- WAC = 1301.57 + Aircraft.Furnishings.MASS -- 11269.88 + Aircraft.Design.FIXED_EQUIPMENT_MASS -- WFE = 20876. + Aircraft.Design.FIXED_USEFUL_LOAD -- WFUL = 5775. + Aircraft.Engine.ADDITIONAL_MASS -- not in GASP + Aircraft.Wing.FOLD_MASS -- WWFOLD = 107.9 + Aircraft.Wing.MASS -- WW = 7645. + Aircraft.Fuel.FUEL_SYSTEM_MASS -- WFSS = 1281. + Note: In GASP, fuel related masses are based on sized engine. + See the computation of Aircraft.Proplusion.TOTAL_ENGINE_POD_MASS + in FuelMassGroup closure loop. + Aircraft.Design.STRUCTURE_MASS -- WST = 45623. + Aircraft.Fuselage.MASS -- WB = 27160 + Mission.Summary.FUEL_MASS_REQUIRED tol -- WFAREQ = 36595.0 + Aircraft.Propulsion.MASS tol -- WP = 8592. + Mission.Summary.FUEL_MASS -- WFADES = 33268.2 + Aircraft.Fuel.WING_VOLUME_DESIGN -- FVOLREQ = 731.6 + Mission.Summary.OPERATING_MASS tol -- OWE = 82982. + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY -- not in GASP + """ + prob = self.prob + + engines = [build_engine_deck(self.gasp_inputs)] + preprocess_options(self.gasp_inputs, engine_models=engines) + default_premission_subsystems = get_default_premission_subsystems('GASP', engines=engines) + + prob.model.add_subsystem( + 'pre_mission', + CorePreMission( + aviary_options=self.gasp_inputs, subsystems=default_premission_subsystems + ), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + setup_model_options(prob, self.gasp_inputs) + prob.setup(check=False) + set_aviary_initial_values(prob, self.gasp_inputs) + + prob.run_model() + + tol = 1e-5 + # geometry subsystem + assert_near_equal(prob[Aircraft.Fuselage.AVG_DIAMETER], 38, tol) + assert_near_equal(prob[Aircraft.Fuselage.LENGTH], 71.52455, tol) + assert_near_equal(prob[Aircraft.Fuselage.WETTED_AREA], 4573.882, tol) + assert_near_equal(prob[Aircraft.Wing.AREA], 2142.857, tol) + assert_near_equal(prob[Aircraft.Wing.SPAN], 146.385, tol) + assert_near_equal(prob[Aircraft.Wing.CENTER_CHORD], 22.97244, tol) + assert_near_equal(prob[Aircraft.Wing.AVERAGE_CHORD], 16.22, tol) + assert_near_equal(prob[Aircraft.Wing.ROOT_CHORD], 20.3337, tol) + assert_near_equal(prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.135966, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 605.9078, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AREA], 0.00117064, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.SPAN], 0.04467601, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.ROOT_CHORD], 0.0383645, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 0.0280845, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MOMENT_ARM], 29.6907, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AREA], 169.1196, tol) + assert_near_equal(prob[Aircraft.VerticalTail.SPAN], 16.98084, tol) + assert_near_equal(prob[Aircraft.VerticalTail.ROOT_CHORD], 14.5819, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AVERAGE_CHORD], 10.6746, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MOMENT_ARM], 27.8219, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_DIAMETER], 5.33382, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_LENGTH], 7.2476, tol) + assert_near_equal(prob[Aircraft.Nacelle.SURFACE_AREA], 121.4458, tol) + # mass subsystem + assert_near_equal(prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 1686.6256, tol) + assert_near_equal(prob[Aircraft.Design.LIFT_CURVE_SLOPE], 5.948, tol) + assert_near_equal(prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.77336, tol) + assert_near_equal(prob[Aircraft.Wing.MATERIAL_FACTOR], 1.194612, tol) + assert_near_equal(prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(prob[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 7005.15475, tol) + assert_near_equal(prob[Aircraft.Nacelle.MASS], 303.6144, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MASS], 1.02402, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MASS], 864.174, tol) + assert_near_equal(prob[Aircraft.Wing.HIGH_LIFT_MASS], 973.10188, tol) + assert_near_equal(prob[Aircraft.Controls.TOTAL_MASS], 2114.982, tol) + assert_near_equal(prob[Aircraft.Wing.SURFACE_CONTROL_MASS], 1986.251, tol) + assert_near_equal(prob[Aircraft.LandingGear.TOTAL_MASS], 7800.0, tol) + assert_near_equal(prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6630.0, tol) + assert_near_equal(prob[Aircraft.Avionics.MASS], 3225.0, tol) + assert_near_equal(prob[Aircraft.AirConditioning.MASS], 1301.573, tol) + assert_near_equal(prob[Aircraft.Furnishings.MASS], 11269.876, tol) + assert_near_equal(prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 20876.453, tol) + assert_near_equal(prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5971.7946, tol) + assert_near_equal(prob[Aircraft.Engine.ADDITIONAL_MASS], 153.1677, tol) + assert_near_equal(prob[Aircraft.Wing.FOLD_MASS], 107.85313, tol) + assert_near_equal(prob[Aircraft.Wing.MASS], 6960.992, tol) + assert_near_equal(prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1316.1836, tol) + assert_near_equal(prob[Aircraft.Design.STRUCTURE_MASS], 44472.509, tol) + assert_near_equal(prob[Aircraft.Fuselage.MASS], 27159.693, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS_REQUIRED], 34186.5881, tol) + assert_near_equal(prob[Aircraft.Propulsion.MASS], 8627.6738, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS], 34186.588, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 751.7705, tol) + assert_near_equal(prob[Mission.Summary.OPERATING_MASS], 82063.412, tol) + assert_near_equal(prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 3877.719, tol) + + def test_case2(self): + """ + premission: geometry + mass + """ + prob = self.prob + + preprocess_options(self.gasp_inputs) + geom_and_mass_subsystems = get_geom_and_mass_subsystems('GASP') + + prob.model.add_subsystem( + 'pre_mission', + CorePreMission(aviary_options=self.gasp_inputs, subsystems=geom_and_mass_subsystems), + promotes_inputs=['*'], + promotes_outputs=['*'], + ) + + setup_model_options(prob, self.gasp_inputs) + prob.setup(check=False) + set_aviary_initial_values(prob, self.gasp_inputs) + + prob.set_val( + Mission.Landing.LIFT_COEFFICIENT_MAX, val=2.13421583, units='unitless' + ) # 2.13421583 for landing, 1.94302452 for takeoff + prob.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, val=19580.1602, units='lbf' + ) # not 37451.0 as in .dat file. It is computed in propulsion_premission.py + prob.set_val( + Aircraft.Wing.SLAT_SPAN_RATIO, 0.827296853, units='unitless' + ) # It is computed in basic_calculations.py + + prob.run_model() + + tol = 1e-5 + # geometry subsystem + assert_near_equal(prob[Aircraft.Fuselage.AVG_DIAMETER], 38, tol) + assert_near_equal(prob[Aircraft.Fuselage.LENGTH], 71.52455, tol) + assert_near_equal(prob[Aircraft.Fuselage.WETTED_AREA], 4573.882, tol) + assert_near_equal(prob[Aircraft.Wing.AREA], 2142.857, tol) + assert_near_equal(prob[Aircraft.Wing.SPAN], 146.385, tol) + assert_near_equal(prob[Aircraft.Wing.CENTER_CHORD], 22.97244, tol) + assert_near_equal(prob[Aircraft.Wing.AVERAGE_CHORD], 16.22, tol) + assert_near_equal(prob[Aircraft.Wing.ROOT_CHORD], 20.3337, tol) + assert_near_equal(prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.135966, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX], 605.9078, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AREA], 0.00117064, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.SPAN], 0.04467601, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.ROOT_CHORD], 0.0383645, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 0.0280845, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MOMENT_ARM], 29.6907, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AREA], 169.1196, tol) + assert_near_equal(prob[Aircraft.VerticalTail.SPAN], 16.98084, tol) + assert_near_equal(prob[Aircraft.VerticalTail.ROOT_CHORD], 14.5819, tol) + assert_near_equal(prob[Aircraft.VerticalTail.AVERAGE_CHORD], 10.6746, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MOMENT_ARM], 27.8219, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_DIAMETER], 5.33382, tol) + assert_near_equal(prob[Aircraft.Nacelle.AVG_LENGTH], 7.2476, tol) + assert_near_equal(prob[Aircraft.Nacelle.SURFACE_AREA], 121.4458, tol) + # mass subsystem + assert_near_equal(prob[Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS], 1686.6256, tol) + assert_near_equal(prob[Aircraft.Design.LIFT_CURVE_SLOPE], 5.948, tol) + assert_near_equal(prob[Aircraft.Wing.ULTIMATE_LOAD_FACTOR], 3.77336, tol) + assert_near_equal(prob[Aircraft.Wing.MATERIAL_FACTOR], 1.194612, tol) + assert_near_equal(prob[Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(prob[Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS], 33750.0, tol) + assert_near_equal(prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 7005.155, tol) + assert_near_equal(prob[Aircraft.Nacelle.MASS], 303.6144, tol) + assert_near_equal(prob[Aircraft.HorizontalTail.MASS], 1.02402, tol) + assert_near_equal(prob[Aircraft.VerticalTail.MASS], 864.174, tol) + assert_near_equal(prob[Aircraft.Wing.HIGH_LIFT_MASS], 971.8248, tol) + assert_near_equal(prob[Aircraft.Controls.TOTAL_MASS], 2114.982, tol) + assert_near_equal(prob[Aircraft.Wing.SURFACE_CONTROL_MASS], 1986.251, tol) + assert_near_equal(prob[Aircraft.LandingGear.TOTAL_MASS], 7800.0, tol) + assert_near_equal(prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6630.0, tol) + assert_near_equal(prob[Aircraft.Avionics.MASS], 3225.0, tol) + assert_near_equal(prob[Aircraft.AirConditioning.MASS], 1301.573, tol) + assert_near_equal(prob[Aircraft.Furnishings.MASS], 11269.876, tol) + assert_near_equal(prob[Aircraft.Design.FIXED_EQUIPMENT_MASS], 20876.453, tol) + assert_near_equal(prob[Aircraft.Design.FIXED_USEFUL_LOAD], 5971.7946, tol) + assert_near_equal(prob[Aircraft.Engine.ADDITIONAL_MASS], 153.1677, tol) + assert_near_equal(prob[Aircraft.Wing.FOLD_MASS], 107.8335, tol) + assert_near_equal(prob[Aircraft.Wing.MASS], 6959.7262, tol) + assert_near_equal(prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1316.2306, tol) + assert_near_equal(prob[Aircraft.Design.STRUCTURE_MASS], 44471.243, tol) + assert_near_equal(prob[Aircraft.Fuselage.MASS], 27159.693, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS_REQUIRED], 34187.8, tol) + assert_near_equal(prob[Aircraft.Propulsion.MASS], 8627.72, tol) + assert_near_equal(prob[Mission.Summary.FUEL_MASS], 34187.807, tol) + assert_near_equal(prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 751.7973, tol) + assert_near_equal(prob[Mission.Summary.OPERATING_MASS], 82062.193, tol) + assert_near_equal(prob[Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY], 3878.938, tol) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/subsystems/test/test_premission.py b/aviary/subsystems/test/test_premission.py index 4ed926b356..8226d8062e 100644 --- a/aviary/subsystems/test/test_premission.py +++ b/aviary/subsystems/test/test_premission.py @@ -1,24 +1,26 @@ import unittest import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal, assert_check_partials +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal -from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder +from aviary.models.aircraft.large_single_aisle_1.V3_bug_fixed_IO import ( + V3_bug_fixed_non_metadata, + V3_bug_fixed_options, +) +from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder from aviary.subsystems.mass.mass_builder import CoreMassBuilder -from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.premission import CorePreMission +from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder +from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.aviary_values import get_items, get_keys -from aviary.validation_cases.validation_tests import ( - get_flops_case_names, get_flops_inputs, get_flops_outputs -) -from aviary.variable_info.variables import Aircraft, Mission -from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData -from aviary.models.large_single_aisle_1.V3_bug_fixed_IO import V3_bug_fixed_options, V3_bug_fixed_non_metadata from aviary.utils.functions import set_aviary_initial_values +from aviary.utils.preprocessors import preprocess_options +from aviary.validation_cases.validation_tests import get_flops_case_names, get_flops_inputs from aviary.variable_info.enums import LegacyCode -from aviary.subsystems.propulsion.utils import build_engine_deck - +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.variable_info.variables import Aircraft, Mission FLOPS = LegacyCode.FLOPS GASP = LegacyCode.GASP @@ -31,7 +33,7 @@ def setup_options(priority_data, backfill_data): full_data = priority_data.deepcopy() # add options to priority data that exist in backfill data but not priorirty - for (key, (val, units)) in get_items(backfill_data): + for key, (val, units) in get_items(backfill_data): if key not in priority_keys: (new_val, new_unit) = backfill_data.get_item(key) full_data.set_val(key, val=new_val, units=new_unit) @@ -40,15 +42,13 @@ def setup_options(priority_data, backfill_data): class PreMissionTestCase(unittest.TestCase): - def setUp(self): - # set up inputs such that GASP inputs take priority case_name = 'LargeSingleAisle1FLOPS' flops_inputs = get_flops_inputs(case_name) - flops_outputs = get_flops_outputs(case_name) + # flops_outputs = get_flops_outputs(case_name) FLOPS_input = flops_inputs GASP_input = V3_bug_fixed_options @@ -66,23 +66,26 @@ def setUp(self): input_options.delete(Aircraft.Wing.ULTIMATE_LOAD_FACTOR) input_options.delete(Aircraft.Fuel.TOTAL_CAPACITY) input_options.delete(Aircraft.Nacelle.AVG_LENGTH) + input_options.delete(Aircraft.HorizontalTail.AREA) + input_options.delete(Aircraft.VerticalTail.AREA) - engine = build_engine_deck(input_options) + engines = [build_engine_deck(input_options)] - prop = CorePropulsionBuilder('core_propulsion', BaseMetaData, engine) + prop = CorePropulsionBuilder('core_propulsion', BaseMetaData, engines) mass = CoreMassBuilder('core_mass', BaseMetaData, GASP) aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) - geom = CoreGeometryBuilder('core_geometry', - BaseMetaData, - use_both_geometries=True, - code_origin_to_prioritize=GASP) + geom = CoreGeometryBuilder( + 'core_geometry', + BaseMetaData, + code_origin=(FLOPS, GASP), + code_origin_to_prioritize=GASP, + ) core_subsystems = [prop, geom, mass, aero] self.prob.model.add_subsystem( 'pre_mission', - CorePreMission(aviary_options=input_options, - subsystems=core_subsystems), + CorePreMission(aviary_options=input_options, subsystems=core_subsystems), promotes_inputs=['*'], promotes_outputs=['*'], ) @@ -90,19 +93,27 @@ def setUp(self): # set defaults for all the vars val, units = input_options.get_item(Aircraft.Engine.SCALED_SLS_THRUST) self.prob.model.pre_mission.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=val, units=units) + Aircraft.Engine.SCALED_SLS_THRUST, val=val, units=units + ) - for (key, (val, units)) in get_items(GASP_input): + for key, (val, units) in get_items(GASP_input): try: if not BaseMetaData[key]['option']: self.prob.model.set_input_defaults(key, val, units) except KeyError: continue - for (key, (val, units)) in get_items(V3_bug_fixed_non_metadata): + for key, (val, units) in get_items(V3_bug_fixed_non_metadata): self.prob.model.set_input_defaults(key, val=val, units=units) self.prob.model.set_input_defaults(Aircraft.Wing.SPAN, val=1.0, units='ft') + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_SPAN_RATIO, val=0.9) + self.prob.model.set_input_defaults(Aircraft.Wing.SLAT_CHORD_RATIO, val=0.15) + self.prob.model.set_input_defaults( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, val=16.0, units='lbm' + ) + + setup_model_options(self.prob, input_options) self.prob.setup(check=False, force_alloc_complex=True) @@ -112,24 +123,22 @@ def setUp(self): # We set it to an unconverged value to test convergence. self.prob.set_val(Mission.Design.GROSS_MASS, val=1000.0) - # Set inital values for all variables. + # Set initial values for all variables. set_aviary_initial_values(self.prob, input_options) # Adjust WETTED_AREA_SCALER such that WETTED_AREA = 4000.0 - self.prob.set_val( - Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units="unitless") + self.prob.set_val(Aircraft.Fuselage.WETTED_AREA_SCALER, val=0.86215, units='unitless') def test_GASP_mass_FLOPS_everything_else(self): self.prob.run_model() - # check the outputs from GASP mass and geometry (FLOPS outputs are not tested) + # Check the outputs from GASP mass and geometry (FLOPS outputs are not tested) tol = 5e-4 # size values: - assert_near_equal(self.prob["gasp_based_geom.fuselage.cabin_height"], 13.1, tol) - assert_near_equal( - self.prob["gasp_based_geom.fuselage.cabin_len"], 72.09722222222223, tol) - assert_near_equal(self.prob["gasp_based_geom.fuselage.nose_height"], 8.6, tol) + assert_near_equal(self.prob['gasp_based_geom.cabin_height'], 13.1, tol) + assert_near_equal(self.prob['gasp_based_geom.cabin_len'], 72.09722222222223, tol) + assert_near_equal(self.prob['gasp_based_geom.nose_height'], 8.6, tol) assert_near_equal(self.prob[Aircraft.Wing.CENTER_CHORD], 17.63, tol) assert_near_equal(self.prob[Aircraft.Wing.ROOT_CHORD], 16.54, tol) @@ -137,42 +146,30 @@ def test_GASP_mass_FLOPS_everything_else(self): self.prob[Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED], 0.1397, tol ) # not exact GASP value from the output file, likely due to rounding error - assert_near_equal( - self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.6509873673743, tol - ) - assert_near_equal( - self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.96457870166355, tol - ) + assert_near_equal(self.prob[Aircraft.HorizontalTail.AVERAGE_CHORD], 9.6509873673743, tol) + assert_near_equal(self.prob[Aircraft.VerticalTail.AVERAGE_CHORD], 16.96457870166355, tol) assert_near_equal(self.prob[Aircraft.Nacelle.AVG_LENGTH], 14.7, tol) # fixed mass values: - assert_near_equal( - self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.35, tol) - assert_near_equal( - self.prob["fixed_mass.tail.loc_MAC_vtail"], 0.44959578484694906, tol - ) + assert_near_equal(self.prob[Aircraft.LandingGear.MAIN_GEAR_MASS], 6384.35, tol) + assert_near_equal(self.prob['loc_MAC_vtail'], 0.44959578484694906, tol) # wing values: - assert_near_equal( - self.prob["wing_mass.isolated_wing_mass"], 16205, tol) + assert_near_equal(self.prob['isolated_wing_mass'], 16205, tol) assert_near_equal(self.prob[Aircraft.Propulsion.TOTAL_ENGINE_MASS], 12606, tol) - assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765/2, tol) + assert_near_equal(self.prob[Aircraft.Engine.ADDITIONAL_MASS], 1765 / 2, tol) # fuel values: # modified from GASP value to account for updated crew mass. GASP value is # 78843.6 - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_wingfuel_mass"], 78145.0, tol - ) + assert_near_equal(self.prob['OEM_wingfuel_mass'], 77977.7, tol) # modified from GASP value to account for updated crew mass. GASP value is # 102408.05695930264 - assert_near_equal( - self.prob["fuel_mass.fus_mass_full"], 102663.6529626, tol - ) + assert_near_equal(self.prob['fus_mass_full'], 102812.6654177, tol) # modified from GASP value to account for updated crew mass. GASP value is # 1757 assert_near_equal( - self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1727.9, tol + self.prob[Aircraft.Fuel.FUEL_SYSTEM_MASS], 1721.08, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1757 assert_near_equal(self.prob[Aircraft.Design.STRUCTURE_MASS], 50931.4, tol) assert_near_equal( @@ -182,88 +179,84 @@ def test_GASP_mass_FLOPS_everything_else(self): # modified from GASP value to account for updated crew mass. GASP value is # 42843.6 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS_REQUIRED], 42145.0, tol + self.prob[Mission.Summary.FUEL_MASS_REQUIRED], 41977.7, tol ) # modified from GASP value to account for updated crew mass. GASP value is 42843.6 assert_near_equal( self.prob[Aircraft.Propulsion.MASS], 16098.7, tol ) # modified from GASP value to account for updated crew mass. GASP value is 16127 assert_near_equal( - self.prob[Mission.Design.FUEL_MASS], 42145.0, tol + self.prob[Mission.Summary.FUEL_MASS], 41977.68, tol ) # modified from GASP value to account for updated crew mass. GASP value is 42844.0 assert_near_equal( - self.prob["fuel_mass.fuel_mass_min"], 32105.0, tol + self.prob['fuel_mass_min'], 31937.68, tol ) # modified from GASP value to account for updated crew mass. GASP value is 32803.6 assert_near_equal( - self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 842.53, tol + self.prob[Aircraft.Fuel.WING_VOLUME_DESIGN], 839.18, tol ) # modified from GASP value to account for updated crew mass. GASP value is 856.4910800459031 assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.OEM_fuel_vol"], 1562.21, tol + self.prob['OEM_fuel_vol'], 1558.86, tol ) # modified from GASP value to account for updated crew mass. GASP value is 1576.1710061411081 assert_near_equal( - self.prob[Aircraft.Design.OPERATING_MASS], 97255.0, tol + self.prob[Mission.Summary.OPERATING_MASS], 97422.32, tol ) # modified from GASP value to account for updated crew mass. GASP value is 96556.0 # extra_fuel_mass calculated differently in this version, so test for fuel_mass.fuel_and_oem.payload_mass_max_fuel not included - assert_near_equal( - self.prob["fuel_mass.fuel_and_oem.volume_wingfuel_mass"], 57066.3, tol - ) - assert_near_equal( - self.prob["fuel_mass.max_wingfuel_mass"], 57066.3, tol) + assert_near_equal(self.prob['volume_wingfuel_mass'], 57066.3, tol) + assert_near_equal(self.prob['max_wingfuel_mass'], 57066.3, tol) - # This is not in the model because it has been overridden, but is not an - # input to any other component in the GASP premission model. - err_text = '\' : Variable "aircraft:fuel:auxiliary_fuel_capacity" not found.\'' - with self.assertRaises(KeyError) as cm: - self.prob.get_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY) - self.assertEqual(str(cm.exception), err_text) + assert_near_equal(self.prob['extra_fuel_volume'], 0, tol) # always zero when no body tank + assert_near_equal(self.prob['max_extra_fuel_mass'], 0, tol) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.extra_fuel_volume"], 0, tol - ) # always zero when no body tank - assert_near_equal( - self.prob["fuel_mass.body_tank.max_extra_fuel_mass"], 0, tol - ) # always zero when no body tank - - partial_data = self.prob.check_partials(out_stream=None, method="cs") + partial_data = self.prob.check_partials(out_stream=None, method='cs') assert_check_partials(partial_data, atol=3e-10, rtol=1e-12) - def test_manual_override(self): - - # Problem in setup is GASP prioritized, so shared inputs for FLOPS will be manually overriden. + def test_code_origin_override(self): + # Problem in setup is GASP prioritized, so shared inputs for FLOPS will be overridden. outs = self.prob.model.pre_mission.list_outputs( - includes='*gasp*fuselage:avg_diam*', prom_name=True) + includes='*gasp*fuselage:avg_diam*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.gasp_based_geom.fuselage.parameters.{Aircraft.Fuselage.AVG_DIAMETER}') - self.assertTrue('MANUAL_OVERRIDE' not in outs[0][1]['prom_name']) + outs[0][0] + == f'core_geometry.gasp_based_geom.fuselage.parameters.{Aircraft.Fuselage.AVG_DIAMETER}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' not in outs[0][1]['prom_name']) outs = self.prob.model.pre_mission.list_outputs( - includes='*flops*fuselage:avg_diam*', prom_name=True) + includes='*flops*fuselage:avg_diam*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.flops_based_geom.fuselage_prelim.{Aircraft.Fuselage.AVG_DIAMETER}') - self.assertTrue('MANUAL_OVERRIDE' in outs[0][1]['prom_name']) + outs[0][0] + == f'core_geometry.flops_based_geom.fuselage_prelim.{Aircraft.Fuselage.AVG_DIAMETER}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' in outs[0][1]['prom_name']) outs = self.prob.model.pre_mission.list_outputs( - includes='*gasp*fuselage:wetted_area*', prom_name=True) + includes='*gasp*fuselage:wetted_area*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.gasp_based_geom.fuselage.size.{Aircraft.Fuselage.WETTED_AREA}') - self.assertTrue('MANUAL_OVERRIDE' not in outs[0][1]['prom_name']) + outs[0][0] + == f'core_geometry.gasp_based_geom.fuselage.size.{Aircraft.Fuselage.WETTED_AREA}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' not in outs[0][1]['prom_name']) outs = self.prob.model.pre_mission.list_outputs( - includes='*flops*fuselage:wetted_area*', prom_name=True) + includes='*flops*fuselage:wetted_area*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.flops_based_geom.fuselage.{Aircraft.Fuselage.WETTED_AREA}') - self.assertTrue('MANUAL_OVERRIDE' in outs[0][1]['prom_name']) + outs[0][0] == f'core_geometry.flops_based_geom.fuselage.{Aircraft.Fuselage.WETTED_AREA}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' in outs[0][1]['prom_name']) # Setup FLOPS prioritized problem. case_name = 'LargeSingleAisle1FLOPS' flops_inputs = get_flops_inputs(case_name) - flops_outputs = get_flops_outputs(case_name) + # flops_outputs = get_flops_outputs(case_name) FLOPS_input = flops_inputs GASP_input = V3_bug_fixed_options @@ -273,78 +266,91 @@ def test_manual_override(self): aviary_inputs = setup_options(GASP_input, FLOPS_input) aviary_inputs.delete(Aircraft.Fuselage.WETTED_AREA) - engine = build_engine_deck(aviary_inputs) + engines = [build_engine_deck(aviary_inputs)] + preprocess_options(aviary_inputs, engine_models=engines) prob = om.Problem() model = prob.model - prop = CorePropulsionBuilder('core_propulsion', BaseMetaData, engine) + prop = CorePropulsionBuilder('core_propulsion', BaseMetaData, engines) mass = CoreMassBuilder('core_mass', BaseMetaData, GASP) aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) - geom = CoreGeometryBuilder('core_geometry', - BaseMetaData, - use_both_geometries=True, - code_origin_to_prioritize=FLOPS) + geom = CoreGeometryBuilder( + 'core_geometry', + BaseMetaData, + code_origin=(FLOPS, GASP), + code_origin_to_prioritize=FLOPS, + ) core_subsystems = [prop, geom, mass, aero] model.add_subsystem( 'pre_mission', - CorePreMission(aviary_options=aviary_inputs, - subsystems=core_subsystems), + CorePreMission(aviary_options=aviary_inputs, subsystems=core_subsystems), promotes_inputs=['*'], promotes_outputs=['*'], ) val, units = aviary_inputs.get_item(Aircraft.Engine.SCALED_SLS_THRUST) prob.model.pre_mission.set_input_defaults( - Aircraft.Engine.SCALED_SLS_THRUST, val=val, units=units) + Aircraft.Engine.SCALED_SLS_THRUST, val=val, units=units + ) - for (key, (val, units)) in get_items(GASP_input): + for key, (val, units) in get_items(GASP_input): try: if not BaseMetaData[key]['option']: prob.model.set_input_defaults(key, val, units) except KeyError: continue - for (key, (val, units)) in get_items(V3_bug_fixed_non_metadata): + for key, (val, units) in get_items(V3_bug_fixed_non_metadata): prob.model.set_input_defaults(key, val=val, units=units) + setup_model_options(prob, aviary_inputs) + prob.setup() - # Problem in setup is FLOPS prioritized, so shared inputs for FLOPS will be manually overriden. + # Problem in setup is FLOPS prioritized, so shared inputs for FLOPS will be overridden. outs = prob.model.pre_mission.list_outputs( - includes='*gasp*fuselage:avg_diam*', prom_name=True) + includes='*gasp*fuselage:avg_diam*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.gasp_based_geom.fuselage.parameters.{Aircraft.Fuselage.AVG_DIAMETER}') - self.assertTrue('MANUAL_OVERRIDE' in outs[0][1]['prom_name']) + outs[0][0] + == f'core_geometry.gasp_based_geom.fuselage.parameters.{Aircraft.Fuselage.AVG_DIAMETER}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' in outs[0][1]['prom_name']) outs = prob.model.pre_mission.list_outputs( - includes='*flops*fuselage:avg_diam*', prom_name=True) + includes='*flops*fuselage:avg_diam*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.flops_based_geom.fuselage_prelim.{Aircraft.Fuselage.AVG_DIAMETER}') - self.assertTrue('MANUAL_OVERRIDE' not in outs[0][1]['prom_name']) + outs[0][0] + == f'core_geometry.flops_based_geom.fuselage_prelim.{Aircraft.Fuselage.AVG_DIAMETER}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' not in outs[0][1]['prom_name']) outs = prob.model.pre_mission.list_outputs( - includes='*gasp*fuselage:wetted_area*', prom_name=True) + includes='*gasp*fuselage:wetted_area*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.gasp_based_geom.fuselage.size.{Aircraft.Fuselage.WETTED_AREA}') - self.assertTrue('MANUAL_OVERRIDE' in outs[0][1]['prom_name']) + outs[0][0] + == f'core_geometry.gasp_based_geom.fuselage.size.{Aircraft.Fuselage.WETTED_AREA}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' in outs[0][1]['prom_name']) outs = prob.model.pre_mission.list_outputs( - includes='*flops*fuselage:wetted_area*', prom_name=True) + includes='*flops*fuselage:wetted_area*', prom_name=True, out_stream=None + ) self.assertTrue( - outs[0][0] == f'core_geometry.flops_based_geom.fuselage.{Aircraft.Fuselage.WETTED_AREA}') - self.assertTrue('MANUAL_OVERRIDE' not in outs[0][1]['prom_name']) + outs[0][0] == f'core_geometry.flops_based_geom.fuselage.{Aircraft.Fuselage.WETTED_AREA}' + ) + self.assertTrue('CODE_ORIGIN_OVERRIDE' not in outs[0][1]['prom_name']) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() - # test = PreMissionTestCase() - # test.setUp() - # test.test_GASP_mass_FLOPS_everything_else() diff --git a/aviary/utils/aero_table_conversion.py b/aviary/utils/aero_table_conversion.py index 08efacb769..350da60366 100644 --- a/aviary/utils/aero_table_conversion.py +++ b/aviary/utils/aero_table_conversion.py @@ -2,13 +2,16 @@ import argparse import re - -import numpy as np - from enum import Enum from pathlib import Path +from scipy.interpolate import interp1d + +import numpy as np +from openmdao.components.interp_util.interp import InterpND from aviary.api import NamedValues +from aviary.interface.utils import round_it +from aviary.utils.conversion_utils import _parse, _read_map, _rep from aviary.utils.csv_data_file import write_data_file from aviary.utils.functions import get_path @@ -16,6 +19,17 @@ class CodeOrigin(Enum): FLOPS = 'FLOPS' GASP = 'GASP' + GASP_ALT = 'GASP_ALT' + + +_gasp_keys = ['Altitude', 'Mach', 'Angle of Attack'] +default_units = { + 'Altitude': 'ft', + 'Mach': 'unitless', + 'Angle of Attack': 'deg', + 'CL': 'unitless', + 'CD': 'unitless', +} allowed_headers = { @@ -29,15 +43,27 @@ class CodeOrigin(Enum): 'cd': 'CD', 'hob': 'Hob', 'del_cl': 'Delta CL', - 'del_cd': 'Delta CD' + 'del_cd': 'Delta CD', +} + +outputs = ['CL', 'CL', 'CD', 'Hob', 'Delta CL', 'Delta CD'] + +# number of sig figs to round each header to, if requested +sig_figs = { + 'Altitude': 7, + 'Mach': 4, + 'Angle of Attack': 4, + 'CL': 4, + 'CD': 4, } -def AeroDataConverter(input_file=None, output_file=None, data_format=None): +def convert_aero_table(input_file=None, output_file=None, data_format=None): """This is a utility class to convert a legacy aero data file to Aviary format. There are two options for the legacy aero data file format: FLOPS and GASP. As an Aviary command, the usage is: - aviary convert_aero_table -F {FLOPS|GASP} input_file output_file + aviary convert_aero_table -F {FLOPS|GASP|GASP_ALT} input_file output_file. + Note: In case of GASP, reading of a possible cd0 table is not implemented yet. """ data_format = CodeOrigin(data_format) data_file = get_path(input_file) @@ -47,13 +73,12 @@ def AeroDataConverter(input_file=None, output_file=None, data_format=None): for ii, file in enumerate(output_file): output_file[ii] = Path(file) if not output_file: - if data_format is CodeOrigin.GASP: + if data_format in (CodeOrigin.GASP, CodeOrigin.GASP_ALT): # Default output file name is same location and name as input file, with # '_aviary' appended to filename path = data_file.parents[0] name = data_file.stem - suffix = data_file.suffix - output_file = path / (name + '_aviary' + suffix) + output_file = path / (name + '_aviary.csv') elif data_format is CodeOrigin.FLOPS: # Default output file name is same location and name as input file, with # '_aviary' appended to filename @@ -66,11 +91,70 @@ def AeroDataConverter(input_file=None, output_file=None, data_format=None): stamp = f'# {data_format.value}-derived aerodynamics data converted from {data_file.name}' - if data_format is CodeOrigin.GASP: + if data_format is CodeOrigin.GASP_ALT: data, comments = _load_gasp_aero_table(data_file) comments = [stamp] + comments + write_data_file(output_file, data, outputs, comments, include_timestamp=True) + elif data_format is CodeOrigin.GASP: + data = {key: [] for key in _gasp_keys} + scalars, tables, fields = _load_gasp_alt_aero_table(data_file) + # save scalars as comments + comments = [] + comments.extend(['# ' + key + ': ' + str(scalars[key]) for key in scalars.keys()]) + structured_data = _make_structured_grid(tables, method='lagrange3', fields=fields) + data['Altitude'] = structured_data['CL']['alts'] + data['Mach'] = structured_data['CL']['machs'] + data['Angle of Attack'] = structured_data['CL']['aoas'] + data['CL'] = structured_data['CL']['vals'] + data['CD'] = structured_data['CD']['vals'] + + # round data if requested, using sig_figs as guide + round_data = True + if round_data: + for key in data: + data[key] = np.array([round_it(val, sig_figs[key]) for val in data[key]]) + + # data needs to be string so column length can be easily found later + for var in data: + data[var] = np.array([str(item) for item in data[var]]) + + # sort data + # create parallel dict to data that stores floats + formatted_data = {} + for key in data: + formatted_data[key] = data[key].astype(float) + + # convert engine_data from dict to list so it can be sorted + sorted_values = np.array(list(formatted_data.values())).transpose() + + # Sort by altitude, then mach, then angle of attack + sorted_values = sorted_values[ + np.lexsort( + [ + formatted_data['Angle of Attack'], + formatted_data['Mach'], + formatted_data['Altitude'], + ] + ) + ] + for idx, key in enumerate(formatted_data): + formatted_data[key] = sorted_values[:, idx] + + # store formatted data into NamedValues object + write_data = NamedValues() + + header_names = { + 'Altitude': 'Altitude', + 'Mach': 'Mach', + 'Angle of Attack': 'Angle of Attack', + 'CL': 'CL', + 'CD': 'CD', + } + for key in data: + write_data.set_val(header_names[key], formatted_data[key], default_units[key]) - write_data_file(output_file, data, comments, include_timestamp=True) + comments = [stamp] + comments + write_data_file(output_file, write_data, outputs, comments, include_timestamp=True) elif data_format is CodeOrigin.FLOPS: if type(output_file) is not list: # if only one filename is given, split into two @@ -81,23 +165,23 @@ def AeroDataConverter(input_file=None, output_file=None, data_format=None): file2 = path / (name + '_CD0' + suffix) output_file = [file1, file2] - lift_drag_data, lift_drag_comments, \ - zero_lift_drag_data, zero_lift_drag_comments = _load_flops_aero_table( - data_file) + lift_drag_data, lift_drag_comments, zero_lift_drag_data, zero_lift_drag_comments = ( + _load_flops_aero_table(data_file) + ) # write lift-dependent drag file lift_drag_comments = [stamp] + lift_drag_comments - write_data_file(output_file[0], lift_drag_data, - lift_drag_comments, include_timestamp=True) + write_data_file(output_file[0], lift_drag_data, lift_drag_comments, include_timestamp=True) # write zero-lift drag file zero_lift_drag_comments = [stamp] + zero_lift_drag_comments - write_data_file(output_file[1], zero_lift_drag_data, - zero_lift_drag_comments, include_timestamp=True) + write_data_file( + output_file[1], zero_lift_drag_data, zero_lift_drag_comments, include_timestamp=True + ) def _load_flops_aero_table(filepath: Path): - """Load an aero table in FLOPS format""" + """Load an aero table in FLOPS format.""" def _read_line(line_count, comments): line = file_contents[line_count].strip() @@ -107,7 +191,7 @@ def _read_line(line_count, comments): nonlocal offset offset += 1 try: - items = _read_line(line_count+1, comments) + items = _read_line(line_count + 1, comments) except IndexError: return else: @@ -115,10 +199,11 @@ def _read_line(line_count, comments): try: items = [float(var) for var in items] # data contains things other than floats - except (ValueError): + except ValueError: raise ValueError( f'Non-numerical value found in data file <{filepath.name}> on ' - f'line {str(line_count)}') + f'line {str(line_count)}' + ) return items @@ -145,18 +230,21 @@ def _read_line(line_count, comments): if len(drag) == len(cls): lift_drag.append(drag) else: - raise ValueError('Number of data points provided for ' - f'lift-dependent drag at Mach {lift_drag_machs[i]} ' - 'does not match number of CLs provided ' - f'(FLOPS aero data file {filepath.name})') + raise ValueError( + 'Number of data points provided for ' + f'lift-dependent drag at Mach {lift_drag_machs[i]} ' + 'does not match number of CLs provided ' + f'(FLOPS aero data file {filepath.name})' + ) if len(lift_drag) != len(lift_drag_machs): - raise ValueError('Number of data rows provided for lift-dependent drag does ' - 'not match number of Mach numbers provided (FLOPS aero data ' - f'file {filepath.name})') + raise ValueError( + 'Number of data rows provided for lift-dependent drag does ' + 'not match number of Mach numbers provided (FLOPS aero data ' + f'file {filepath.name})' + ) offset = offset + i # these are not needed, we can determine the length of data vectors directly - altitude_count, zero_lift_mach_count = _read_line( - 4 + offset, zero_lift_drag_comments) + altitude_count, zero_lift_mach_count = _read_line(4 + offset, zero_lift_drag_comments) zero_lift_machs = _read_line(5 + offset, zero_lift_drag_comments) altitudes = _read_line(6 + offset, zero_lift_drag_comments) for i in range(len(zero_lift_machs)): @@ -164,32 +252,38 @@ def _read_line(line_count, comments): if len(drag) == len(altitudes): zero_lift_drag.append(drag) else: - raise ValueError('Number of data points provided for ' - f'zero-lift drag at Mach {zero_lift_machs[i]} ' - 'does not match number of Altitudes provided ' - f'(FLOPS aero data file {filepath.name})') + raise ValueError( + 'Number of data points provided for ' + f'zero-lift drag at Mach {zero_lift_machs[i]} ' + 'does not match number of Altitudes provided ' + f'(FLOPS aero data file {filepath.name})' + ) if len(zero_lift_drag) != len(zero_lift_machs): - raise ValueError('Number of data rows provided for zero-lift drag does ' - 'not match number of Mach numbers provided (FLOPS aero data ' - f'file {filepath.name})') + raise ValueError( + 'Number of data rows provided for zero-lift drag does ' + 'not match number of Mach numbers provided (FLOPS aero data ' + f'file {filepath.name})' + ) cl, mach = np.meshgrid(cls, lift_drag_machs) lift_drag_data.set_val('Mach', mach.flatten(), 'unitless') lift_drag_data.set_val('Lift Coefficient', cl.flatten(), 'unitless') - lift_drag_data.set_val('Lift-Dependent Drag Coefficient', - np.array(lift_drag).flatten(), 'unitless') + lift_drag_data.set_val( + 'Lift-Dependent Drag Coefficient', np.array(lift_drag).flatten(), 'unitless' + ) altitude, mach = np.meshgrid(altitudes, zero_lift_machs) zero_lift_drag_data.set_val('Altitude', altitude.flatten(), 'ft') zero_lift_drag_data.set_val('Mach', mach.flatten(), 'unitless') - zero_lift_drag_data.set_val('Zero-Lift Drag Coefficient', - np.array(zero_lift_drag).flatten(), 'unitless') + zero_lift_drag_data.set_val( + 'Zero-Lift Drag Coefficient', np.array(zero_lift_drag).flatten(), 'unitless' + ) return lift_drag_data, lift_drag_comments, zero_lift_drag_data, zero_lift_drag_comments def _load_gasp_aero_table(filepath: Path): - """Load an aero table in GASP format""" + """Load an aero table in GASP format.""" data = NamedValues() raw_data = [] comments = [] @@ -229,10 +323,11 @@ def _load_gasp_aero_table(filepath: Path): try: line_data = [float(var) for var in items] # data contains things other than floats - except (ValueError): + except ValueError: raise ValueError( f'Non-numerical value found in data file <{filepath.name}> on ' - f'line {str(line_count)}') + f'line {str(line_count)}' + ) else: raw_data.append(line_data) @@ -246,26 +341,178 @@ def _load_gasp_aero_table(filepath: Path): return data, comments +def _load_gasp_alt_aero_table(filepath: Path): + with open(filepath, 'r') as f: + fields = ['CL', 'CD'] + scalars = _read_header(f) + tables = {k: _read_table(f) for k in fields} + + # Now, tables['CD'] is a function of altitude, Mach, and CL. + # For Aviary table, we need to convert it to a function of Altitude, Mach and alpha. + cl_table = tables['CL'] + cd_table = tables['CD'] + n = len(cl_table) + cd_table_new = np.zeros((n, 4)) + i = 0 + for elem in cl_table: + alt = elem[0] + alpha = elem[1] + mach = elem[2] + cl = elem[3] + selected_cd_table = cd_table[(cd_table[:, 0] == alt) & (cd_table[:, 2] == mach)] + # print(selected_cd_table) + x = selected_cd_table[:, 1] + y = selected_cd_table[:, 3] + f_interp = interp1d(x, y, kind='linear', fill_value='extrapolate') + z = float(f_interp(cl)) + new_elem = [alt, alpha, mach, z] + cd_table_new[i] = new_elem + i = i + 1 + tables['CD'] = cd_table_new + + return scalars, tables, fields + + +def _read_header(f): + """Read GASP aero header, returning the area scalars in a dict.""" + # file header: FORMAT(4I5,10X,2F10.4) + iread, iprint, icd0, icompss, sref_at, cbar_at = _parse( + f, [*_rep(4, (int, 5)), *_rep(2, (float, 10))] + ) + if iread == 1: + raise Exception('Reading of Reynolds number is not implemented yet.') + if icd0 == 1: + raise Exception('Reading of CD0 table is not implemented yet.') + + return { + 'sref_at': sref_at, + 'cbar_at': cbar_at, + } + + +def _read_table(f, is_turbo_prop=False): + """Read an entire table from a GASP area file. + The table data is returned as a "tidy format" array with three columns for the + independent variables (altitude, alpha, and Mach number) and the final columns for + the table field (CL and CD). + """ + tab_data = None + + # strip out table title, not used + f.readline().strip() + # number of maps in the table + (nmaps,) = _parse(f, [(int, 5)]) + # blank line + f.readline() + + for i in range(nmaps): + map_data = _read_map(f, is_turbo_prop) + + # blank line following all but the last map in the table + if i < nmaps - 1: + f.readline() + + if tab_data is None: + tab_data = map_data + else: + tab_data = np.r_[tab_data, map_data] + + return tab_data + + +def _make_structured_grid(data, method='lagrange3', fields=['CL', 'CD']): + """Generate a structured grid of unique mach/aoa/alt values in the deck.""" + aoa_step = 0.05 + # step size in Mach number used in generating the structured grid + # mach_step = 0.02 # original value + mach_step = 0.05 + + structured_data = {} + + # find min/max from CL table + aoa = data['CL'][:, 1] + tma = data['CL'][:, 2] + min_aoa = min(aoa) + max_aoa = max(aoa) + aoa_step + min_tma = min(tma) + max_tma = max(tma) + mach_step + + aoas = np.arange(min_aoa, max_aoa + aoa_step, aoa_step) + machs = np.arange(min_tma, max_tma + mach_step, mach_step) + + # need altitude in first column, mach varies on each row + pts = np.dstack(np.meshgrid(aoas, machs, indexing='ij')).reshape(-1, 2) + npts = pts.shape[0] + + for field in fields: + map_data = data[field] + all_alts = map_data[:, 0] + alts = np.unique(all_alts) + + sizes = (alts.size, aoas.size, machs.size) + vals = np.zeros(np.prod(sizes), dtype=float) + alt_vec = np.zeros(np.prod(sizes), dtype=float) + mach_vec = np.zeros(np.prod(sizes), dtype=float) + aoa_vec = np.zeros(np.prod(sizes), dtype=float) + + for i, alt in enumerate(alts): + d = map_data[all_alts == alt] + aoa = np.unique(d[:, 1]) + mach = np.unique(d[:, 2]) + f = d[:, 3].reshape(aoa.size, mach.size) + + # would explicitly use lagrange3 here to mimic GASP, but some aero + # tables may not have enough points per dimension + # For GASP aero table, try to provide at least 4 Mach numbers. + # avoid devide-by-zero RuntimeWarning + if len(mach) == 3 and method == 'lagrange3': + method = 'lagrange2' + elif len(mach) == 2: + method = 'slinear' + interp = InterpND(method='2D-' + method, points=(aoa, mach), values=f, extrapolate=True) + sl = slice(i * npts, (i + 1) * npts) + vals[sl] = interp.interpolate(pts) + alt_vec[sl] = [alt] * len(pts) + mach_vec[sl] = pts[:, 1] + aoa_vec[sl] = pts[:, 0] + + structured_data[field] = { + 'alts': alt_vec, + 'machs': mach_vec, + 'aoas': aoa_vec, + 'vals': vals, + } + + return structured_data + + def _setup_ATC_parser(parser): - parser.add_argument('input_file', type=str, - help='path to aero data file to be converted') - parser.add_argument('output_file', type=str, nargs='?', - help='path to file where new converted data will be written') - parser.add_argument('-f', '--data_format', type=str, choices=[origin.value for origin in CodeOrigin], - help='data format used by input_file') + parser.add_argument('input_file', type=str, help='path to aero data file to be converted') + parser.add_argument( + 'output_file', + type=str, + nargs='?', + help='path to file where new converted data will be written', + ) + parser.add_argument( + '-f', + '--data_format', + type=str, + choices=[origin.value for origin in CodeOrigin], + help='data format used by input_file', + ) def _exec_ATC(args, user_args): - AeroDataConverter( - input_file=args.input_file, - output_file=args.output_file, - data_format=args.data_format + convert_aero_table( + input_file=args.input_file, output_file=args.output_file, data_format=args.data_format ) if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Converts FLOPS- or GASP-formatted ' - 'aero data files into Aviary csv format.\n') + parser = argparse.ArgumentParser( + description='Converts FLOPS- or GASP-formatted aero data files into Aviary csv format.\n' + ) _setup_ATC_parser(parser) args = parser.parse_args() _exec_ATC(args, None) diff --git a/aviary/utils/aviary_options_dict.py b/aviary/utils/aviary_options_dict.py new file mode 100644 index 0000000000..84af0b6c7a --- /dev/null +++ b/aviary/utils/aviary_options_dict.py @@ -0,0 +1,457 @@ +import openmdao.api as om +from openmdao.core.constants import _UNDEFINED + +from aviary.utils.utils import wrapped_convert_units + + +def units_setter(opt_meta, value): + """ + Convert units for a tuple with form (val, "unitstring"). + + Parameters + ---------- + opt_meta : dict + Dictionary of entries for the option. + value : any + New value for the option. + + Returns + ------- + any + Post processed value to set into the option. + """ + new_val, _ = value + _, units = opt_meta['val'] + + if new_val is not None: + new_val = wrapped_convert_units(value, units) + + return (new_val, units) + + +class AviaryOptionsDictionary(om.OptionsDictionary): + """ + Modified OptionsDictionary that is used by Aviary to store the user_options + for a phase. + + This subclass adds support for declaring options and getting options with units. + + Parameters + ---------- + data : dict + Dictionary of option name: value to set. + parent_name : str + Name or class name of System that owns this OptionsDictionary. + """ + + def __init__(self, data=None, parent_name=None): + super().__init__(parent_name) + + self.declare_options() + + if data is None: + return + + # Loop over all user_options and set them. + for name, val in data.items(): + # Support for legacy format (unitless) + if ( + isinstance(val, tuple) + and self._dict[name]['set_function'] is None + and val[1] == 'unitless' + ): + val = val[0] + + self[name] = val + + def declare_options(self): + """Hook for declaring options for a phase builder.""" + pass + + def declare( + self, + name, + default=_UNDEFINED, + values=None, + types=None, + desc='', + units=None, + upper=None, + lower=None, + check_valid=None, + allow_none=False, + deprecation=None, + ): + if units is not None: + set_function = units_setter + default = (default, units) + types = tuple + else: + set_function = None + + super().declare( + name, + default=default, + values=values, + types=types, + desc=desc, + upper=upper, + lower=lower, + check_valid=check_valid, + allow_none=allow_none, + set_function=set_function, + deprecation=deprecation, + ) + + def get_val(self, key, units=None): + """ + Return the current value for the requested default. + + Parameters + ---------- + key : str + the name of the item + units : str ('unitless') + the units of the returned value + + Returns + ------- + val + """ + if units is not None: + if self._dict[key]['set_function'] is None: + self._raise( + f"Option '{key}' does not have declared units.", + exc_type=AttributeError, + ) + + val, base_units = self[key] + + if units != base_units: + val = wrapped_convert_units((val, base_units), units) + + else: + val = self[key] + + return val + + def to_phase_info(self): + """ + Returns an equivalent phase_info dictionary for this options dict. + + Returns + ------- + dict + Equivalent phase_info. + """ + phase_info = {} + for name, val in self.items(): + phase_info[name] = val + + return phase_info + + def add_state_options(self, state_name: str, units: str = None, defaults=None): + """ + Adds all options needed for a state variable. + + For a state named mass, these are mass_initial, mass_final, mass_bounds, mass_ref, + mass_ref0, mass_defect_ref, mass_solve_segments, mass_constraint_ref. + + Parameters + ---------- + state_name : str + Name of this state. + units : str + Units for this state if it has them. + defaults : dict or None + Optional dictionary of default values for any state option. + """ + if defaults is None: + defaults = {} + + name = f'{state_name}_initial' + default = defaults.get(name, None) + desc = f'Tuple of (value, units) containing value of {state_name} ' + desc += 'at the start of the phase.\n' + desc += 'When unspecified, the optimizer controls the value.\n' + desc += f'When specified, a constraint is created on the initial {state_name}.' + self.declare( + name=name, + default=default, + types=tuple, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{state_name}_final' + default = defaults.get(name, None) + desc = f'Tuple of (value, units) containing value of {state_name} ' + desc += 'at the end of the phase.\n' + desc += 'If this phase is connected to a downstream phase, final values should be ' + desc += f'specified with {state_name}_initial in that phase instead of here.\n' + desc += f'When specified, a constraint is created on the final {state_name}.' + self.declare( + name=name, + default=default, + types=tuple, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{state_name}_bounds' + default = defaults.get(name, (None, None)) + desc = 'Tuple of form ((lower, upper), units) containing the upper and lower bounds for ' + desc += f'all values of {state_name} in the phase.\n' + desc += 'The default of None for upper or lower means that bound will not be declared.\n' + self.declare( + name=name, + default=default, + types=tuple, + units=units, + desc=desc, + ) + + name = f'{state_name}_ref' + default = defaults.get(name, 1.0) + desc = f'Multiplicative scale factor "ref" for {state_name}.\n' + desc += 'Default is 1.0' + self.declare( + name=name, + default=default, + types=float, + units=units, + desc=desc, + ) + + name = f'{state_name}_ref0' + default = defaults.get(name, None) + desc = f'Additive scale factor "ref0" for {state_name}.\n' + self.declare( + name=name, + default=default, + types=float, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{state_name}_defect_ref' + default = defaults.get(name, None) + desc = f'Multiplicative scale factor "ref" for the {state_name} defect constraint.\n' + desc += 'Default is None, which means the ref and defect_ref are the same.' + self.declare( + name=name, + default=default, + types=float, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{state_name}_solve_segments' + default = defaults.get(name, False) + desc = 'When True, a solver will be used to converge the collocation defects within a ' + desc += 'segment. Note that the state continuity defects between segements will still be ' + desc += 'handled by the optimizer.' + self.declare( + name=name, + default=default, + types=bool, + desc=desc, + ) + + name = f'{state_name}_constraint_ref' + default = defaults.get(name, None) + desc = f'Multiplicative scale factor "ref" for the {state_name} boundary constraint.\n' + desc += f'If unspecified, then the value in {state_name}_final is used. ' + desc += 'At present, only a final constraint is added.' + self.declare( + name=name, + default=default, + types=float, + allow_none=True, + units=units, + desc=desc, + ) + + def add_control_options(self, ctrl_name: str, units: str = None, defaults=None): + """ + Adds all options needed for a control variable. + + For a control named mach, these are mach_initial, mach_final, mach_bounds, mach_ref, + mach_ref0, mach_polynomial_order, mach_optimize, mach_rate_constraint. + + Parameters + ---------- + ctrl_name : str + Name of this control variable. + units : str + Units for this control if it has them. + defaults : dict or None + Optional dictionary of default values for any control option. + """ + if defaults is None: + defaults = {} + + name = f'{ctrl_name}_optimize' + default = defaults.get(name, True) + desc = f'When True, the optimizer will set this value. When False, the initial value ' + desc += 'for all nodes can be set in the initial_conditions section of the phase.' + self.declare( + name=name, + default=default, + types=bool, + desc=desc, + ) + + name = f'{ctrl_name}_initial' + default = defaults.get(name, None) + desc = f'Tuple of (value, units) containing value of {ctrl_name} ' + desc += 'at the start of the phase.\n' + desc += 'When unspecified, the value comes from upstream.\n' + desc += f'When specified, a constraint is created on the initial {ctrl_name}.' + self.declare( + name=name, + default=default, + types=tuple, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{ctrl_name}_final' + default = defaults.get(name, None) + desc = f'Tuple of (value, units) containing value of {ctrl_name} ' + desc += 'at the end of the phase.\n' + desc += 'If this phase is connected to a downstream phase, final values should be ' + desc += f'specified with {ctrl_name}_initial in that phase instead of here.\n' + desc += f'When specified, a constraint is created on the final {ctrl_name}.' + self.declare( + name=name, + default=default, + types=tuple, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{ctrl_name}_bounds' + default = defaults.get(name, (None, None)) + desc = 'Tuple of form ((lower, upper), units) containing the upper and lower bounds for ' + desc += f'all values of {ctrl_name} in the phase.\n' + desc += 'The default of None for upper or lower means that bound will not be declared.\n' + self.declare( + name=name, + default=default, + types=tuple, + units=units, + desc=desc, + ) + + name = f'{ctrl_name}_ref' + default = defaults.get(name, 1.0) + desc = f'Multiplicative scale factor "ref" for {ctrl_name}.\n' + desc += 'Default is 1.0' + self.declare( + name=name, + default=default, + types=float, + units=units, + desc=desc, + ) + + name = f'{ctrl_name}_ref0' + default = defaults.get(name, None) + desc = f'Additive scale factor "ref0" for {ctrl_name}.\n' + self.declare( + name=name, + default=default, + types=float, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{ctrl_name}_polynomial_order' + default = defaults.get(name, None) + desc = f'The order of polynomials for interpolation in the transcription.\n' + desc += 'Default is None, which does not use a polynomial.' + self.declare( + name=name, + default=default, + types=int, + allow_none=True, + desc=desc, + ) + + name = f'{ctrl_name}_rate_constraint' + default = defaults.get(name, None) + desc = f'Can be (None, positive, negative.) When not None, adds a constraint that keeps ' + desc += 'the rate positive or negative as requested. For altitude in a flight phase, ' + desc += 'negative means no climb, and positive means no descent.' + self.declare( + name=name, + default=default, + values=[None, 'positive', 'negative'], + desc=desc, + ) + + def add_time_options(self, units: str = None, defaults=None): + """ + Adds all options for controlling time initial and duration. + + This adds ref and bounds for both. + + Parameters + ---------- + units : str + Units for this control if it has them. + defaults : dict or None + Optional dictionary of default values for any control option. + """ + if defaults is None: + defaults = {} + + for stem in ['time_initial', 'time_duration']: + name = stem + default = defaults.get(name, None) + desc = f'Tuple of (value, units) containing value of {stem} ' + desc += 'at the start of the phase.\n' + desc += 'When unspecified, the value comes from upstream.\n' + desc += f'When specified, a constraint is created on the initial {stem}.' + self.declare( + name=name, + default=default, + types=tuple, + allow_none=True, + units=units, + desc=desc, + ) + + name = f'{stem}_bounds' + default = defaults.get(name, (None, None)) + desc = 'Tuple of form ((lower, upper), units) containing the upper and lower bounds ' + desc += f'for all values of {stem} in the phase.\n' + desc += 'The default of None for upper or lower means that bound will not be ' + desc += 'declared.\n' + self.declare( + name=name, + default=default, + types=tuple, + units=units, + desc=desc, + ) + + name = f'{stem}_ref' + default = defaults.get(name, 1.0) + desc = f'Multiplicative scale factor "ref" for {stem}.\n' + desc += 'Default is 1.0' + self.declare( + name=name, + default=default, + types=float, + units=units, + desc=desc, + ) diff --git a/aviary/utils/aviary_values.py b/aviary/utils/aviary_values.py index 23736a4cab..88968ee1f5 100644 --- a/aviary/utils/aviary_values.py +++ b/aviary/utils/aviary_values.py @@ -1,4 +1,4 @@ -''' +""" Define utilities for using aviary values with associated units and testing for compatibility with aviary metadata dictionary. @@ -15,24 +15,26 @@ class AviaryValues define a collection of named values with associated units -''' -from enum import EnumMeta +""" -import numpy as np from openmdao.utils.units import convert_units as _convert_units -from aviary.utils.named_values import (NamedValues, get_items, get_keys, - get_values) +from aviary.utils.named_values import NamedValues, get_items, get_keys, get_values +from aviary.utils.utils import cast_type, check_type from aviary.variable_info.variable_meta_data import _MetaData +# TODO: workaround to avoid unused imports - a better solution is desired such as utils or making +# get_*() methods of NamedValues +get_items = get_items +get_keys = get_keys +get_values = get_values + class AviaryValues(NamedValues): - ''' - Define a collection of aviary values with associated units and aviary tests. - ''' + """Define a collection of aviary values with associated units and aviary tests.""" def set_val(self, key, val, units='unitless', meta_data=_MetaData): - ''' + """ Update the named value and its associated units. Note, specifying units of `None` or units of any type other than `str` will raise @@ -53,101 +55,49 @@ def set_val(self, key, val, units='unitless', meta_data=_MetaData): ------ TypeError if units of `None` were specified or units of any type other than `str` - ''' - - # Special handling to access an Enum member from either the member name or its value. - my_val = val - if key in _MetaData.keys(): - expected_types = _MetaData[key]['types'] - if type(expected_types) is EnumMeta: - if self._is_iterable(val): - my_val = [self._convert_to_enum( - item, expected_types) for item in val] - else: - my_val = self._convert_to_enum(val, expected_types) - - # Special handling if the variable is supposed to be an array - if key in _MetaData.keys(): - default_value = _MetaData[key]['default_value'] - # if the item is supposed to be an iterable... - if self._is_iterable(default_value): - # but the provided value is not... - if not self._is_iterable(my_val): - # make object the correct iterable - if isinstance(default_value, tuple): - my_val = (my_val,) - else: - my_val = np.array([my_val], dtype=type(default_value[0])) - - self._check_type(key, my_val, meta_data=meta_data) - self._check_units_compatability(key, my_val, units, meta_data=meta_data) - - super().set_val(key=key, val=my_val, units=units) - - def _check_type(self, key, val, meta_data=_MetaData): - if key in meta_data.keys(): - expected_types = meta_data[key]['types'] - if expected_types is not None: - if self._is_iterable(expected_types): - expected_types = tuple(expected_types) - # if val is not iterable, add it to a list (length 1), checks assume - # val is iterable - if not self._is_iterable(val): - val = [val] - # numpy arrays have special typings. Extract item of equivalent built-in python type - # numpy arrays do not allow mixed types, only have to check first entry - # empty arrays do not need this check - if isinstance(val, np.ndarray) and len(val) > 0: - # NoneType numpy arrays do not need to be "converted" to built-in python types - if val.dtype == type(None): - val = [val[0]] - else: - # item() gets us native Python equivalent object (i.e. int vs. numpy.int64) - # wrap first index in np array to ensures works on any dtype - val = [np.array(val[0]).item()] - for item in val: - has_bool = False # needs some fancy shenanigans because bools will register as ints - if (isinstance(expected_types, type)): - if expected_types is bool: - has_bool = True - elif bool in expected_types: - has_bool = True - if (not isinstance(item, expected_types)) or ( - (has_bool == False) and (isinstance(item, bool))): - raise TypeError( - f'{key} is of type(s) {meta_data[key]["types"]} but you ' - f'have provided a value of type {type(item)}.') - - def _check_units_compatability(self, key, val, units, meta_data=_MetaData): - if key in meta_data.keys(): - expected_units = meta_data[key]['units'] - - try: - # NOTE the value here is unimportant, we only care if OpenMDAO will - # convert the units - _convert_units(10, expected_units, units) - except ValueError: - raise ValueError( - f'The units {units} which you have provided for {key} are invalid.') - except TypeError: - raise TypeError( - f'The base units of {key} are {expected_units}, and you have tried to set {key} with units of {units}, which are not compatible.') - except BaseException: - raise KeyError('There is an unknown error with your units.') - - def _is_iterable(self, val): - return isinstance(val, _valid_iterables) - - def _convert_to_enum(self, val, enum_type): - if isinstance(val, str): - try: - # see if str maps to ENUM value - return enum_type(val) - except ValueError: - # str instead maps to ENUM name - return enum_type[val.upper()] - else: - return enum_type(val) - - -_valid_iterables = (list, np.ndarray, tuple) + """ + if key in meta_data: + val = cast_type(key, val, meta_data) + check_type(key, val, meta_data) + + self._check_units_compatibility(key, val, units, meta_data=meta_data) + + super().set_val(key=key, val=val, units=units) + + def _check_units_compatibility(self, key, val, units, meta_data=_MetaData): + """ + Check that the two provided units are compatible - we don't actually want to + convert here, just verify that the provided units are allowed. + """ + expected_units = meta_data[key]['units'] + + try: + # NOTE the value here is unimportant, we only care if OpenMDAO will + # convert the units + _convert_units(10, expected_units, units) + except ValueError: + raise ValueError(f'The units {units} which you have provided for {key} are invalid.') + except TypeError: + raise TypeError( + f'The base units of {key} are {expected_units}, and you have tried to ' + f'set {key} with units of {units}, which are not compatible.' + ) + except BaseException: + raise KeyError('There is an unknown error with your units.') + + def items(self): + """ + Return (name, value) for variables contained in this vector. + + Note that AviaryValues is not a dictionary, but this adds support for iterating over + its contents. + + Yields + ------ + str + The name of an item. + object + The value of that item. + """ + for key, val in self._mapping.items(): + yield key, val diff --git a/aviary/utils/compare_hierarchies.py b/aviary/utils/compare_hierarchies.py index cfa1a7e998..7162f45832 100644 --- a/aviary/utils/compare_hierarchies.py +++ b/aviary/utils/compare_hierarchies.py @@ -8,14 +8,14 @@ def compare_inner_classes(class1, class2, show_all=False): Summary: This function takes in two classes that both are part of variable hierarchies and may contain - inner-classes or variables with string-named values. This function compares those two classes - and returns a set of inner classes that have the same name in both inputted classes. It will throw + inner-classes or variables with string-named values. This function compares those two classes + and returns a set of inner classes that have the same name in both inputted classes. It will throw an error if the two classes have the same variable with a different string-named value. Parameters ---------- class1 : class - A class that is all or part of a variable hierarchy. This can be the top-level + A class that is all or part of a variable hierarchy. This can be the top-level class in the hierarchy, or any inner class nested at any depth within that top-level class. class2 : class A class that is all or part of a variable hierarchy. This can be the top-level @@ -30,7 +30,7 @@ class in the hierarchy, or any inner class nested at any depth within that top-l A set of string names of all the inner classes which are common between the two input classes. class1_vars_set : set of strings, optional - Set of string names of the variables belonging to class1, optional return based + Set of string names of the variables belonging to class1, optional return based on show_all flag. class2_vars_set : set of strings, optional Set of string names of the variables belonging to class2, optional return based @@ -45,7 +45,7 @@ class in the hierarchy, or any inner class nested at any depth within that top-l Raises ------ ValueError - If the two input classes both have a variable with the same variable name but + If the two input classes both have a variable with the same variable name but different string-named value. """ class1_vars_inner_classes = vars(class1) @@ -61,14 +61,22 @@ class in the hierarchy, or any inner class nested at any depth within that top-l # just checks if it is a class if type(class1_vars_inner_classes[key]) == type(class1): class1_inner_classes.append(key) - elif (type(class1_vars_inner_classes[key]) == str) and not (key == '__module__') and not (key == '__doc__'): + elif ( + (type(class1_vars_inner_classes[key]) == str) + and not (key == '__module__') + and not (key == '__doc__') + ): class1_vars.append(key) # separate out a list of string names of the variables belonging to class2, and the inner classes belonging to class2 for key in class2_vars_inner_classes.keys(): if type(class2_vars_inner_classes[key]) == type(class2): class2_inner_classes.append(key) - elif (type(class2_vars_inner_classes[key]) == str) and not (key == '__module__') and not (key == '__doc__'): + elif ( + (type(class2_vars_inner_classes[key]) == str) + and not (key == '__module__') + and not (key == '__doc__') + ): class2_vars.append(key) class1_vars_set = set(class1_vars) @@ -81,17 +89,24 @@ class in the hierarchy, or any inner class nested at any depth within that top-l if value1 != value2: raise ValueError( - f"You have attempted to merge two variable hierarchies together that have the same variable with a different string name associated to it. The offending variable is '{var}'. In '{class1.__qualname__}' it has a value of '{value1}' and in '{class2.__qualname__}' it has a value of '{value2}'.") + f"You have attempted to merge two variable hierarchies together that have the same variable with a different string name associated to it. The offending variable is '{var}'. In '{class1.__qualname__}' it has a value of '{value1}' and in '{class2.__qualname__}' it has a value of '{value2}'." + ) class1_inner_classes_set = set(class1_inner_classes) class2_inner_classes_set = set(class2_inner_classes) overlapping_inner_classes = class1_inner_classes_set & class2_inner_classes_set if show_all: - return (overlapping_inner_classes, class1_vars_set, class2_vars_set, class1_inner_classes_set, class2_inner_classes_set) + return ( + overlapping_inner_classes, + class1_vars_set, + class2_vars_set, + class1_inner_classes_set, + class2_inner_classes_set, + ) else: - return (overlapping_inner_classes) + return overlapping_inner_classes def recursive_comparison(overlapping_inner_classes, outer_class_a, outer_class_b): @@ -108,10 +123,10 @@ def recursive_comparison(overlapping_inner_classes, outer_class_a, outer_class_b This is a set of strings where each string is the name of an inner class that outer_class_a and outer_class_b have in common. outer_class_a : class - A class that is all or part of a variable hierarchy. This can be the top-level class in the + A class that is all or part of a variable hierarchy. This can be the top-level class in the hierarchy, or any inner class nested at any depth within that top-level class. outer_class_b : class - A class that is all or part of a variable hierarchy. This can be the top-level class in the + A class that is all or part of a variable hierarchy. This can be the top-level class in the hierarchy, or any inner class nested at any depth within that top-level class. Returns @@ -126,9 +141,11 @@ def recursive_comparison(overlapping_inner_classes, outer_class_a, outer_class_b overlapping_inner_class_a = getattr(outer_class_a, overlapping_class_name) overlapping_inner_class_b = getattr(outer_class_b, overlapping_class_name) overlapping_second_inner_classes = compare_inner_classes( - overlapping_inner_class_a, overlapping_inner_class_b) - recursive_comparison(overlapping_second_inner_classes, - overlapping_inner_class_a, overlapping_inner_class_b) + overlapping_inner_class_a, overlapping_inner_class_b + ) + recursive_comparison( + overlapping_second_inner_classes, overlapping_inner_class_a, overlapping_inner_class_b + ) def compare_hierarchies_to_merge(hierarchies_to_merge): @@ -154,7 +171,6 @@ def compare_hierarchies_to_merge(hierarchies_to_merge): ------ No explicit exceptions are raised by this function, although called functions may raise exceptions. """ - for hierarchy in hierarchies_to_merge: # check if hierarchy has developed conflicts with original hierarchy if issubclass(hierarchy, _Aircraft): diff --git a/aviary/utils/conflict_checks.py b/aviary/utils/conflict_checks.py index fd79461ed2..183e031aaa 100644 --- a/aviary/utils/conflict_checks.py +++ b/aviary/utils/conflict_checks.py @@ -1,18 +1,10 @@ - -from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Aircraft - - -def check_fold_location_definition(inputs, options: AviaryValues): - """ - If there is no strut, then CHOOSE_FOLD_LOCATION must be true. - """ - choose_fold_location = options.get_val( - Aircraft.Wing.CHOOSE_FOLD_LOCATION, units='unitless') - has_strut = options.get_val(Aircraft.Wing.HAS_STRUT, units='unitless') +def check_fold_location_definition(choose_fold_location, has_strut): + """If there is no strut, then CHOOSE_FOLD_LOCATION must be true.""" if not choose_fold_location and not has_strut: raise RuntimeError( - "The option CHOOSE_FOLD_LOCATION can only be False if the option HAS_STRUT is True.") + 'The option CHOOSE_FOLD_LOCATION can only be False if the option HAS_STRUT is True.' + ) + # Possible TODO # Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER - Aircraft.Design.PART25_STRUCTURAL_CATEGORY diff --git a/aviary/utils/conversion_utils.py b/aviary/utils/conversion_utils.py index 7c151614d1..a3998e455f 100644 --- a/aviary/utils/conversion_utils.py +++ b/aviary/utils/conversion_utils.py @@ -1,4 +1,5 @@ import itertools + import numpy as np @@ -8,7 +9,7 @@ def _rep(n, t): def _parse(f, fmt): - """Read a line from file ``f`` and parse it according to the given ``fmt``""" + """Read a line from file ``f`` and parse it according to the given ``fmt``.""" return _strparse(f.readline(), fmt) @@ -19,7 +20,7 @@ def _strparse(s, fmt): """ p = 0 for typ, length in fmt: - sub = s[p: p + length] + sub = s[p : p + length] if typ is not None: yield typ(sub) p += length diff --git a/aviary/utils/csv_data_file.py b/aviary/utils/csv_data_file.py index 551c938fea..377acbc976 100644 --- a/aviary/utils/csv_data_file.py +++ b/aviary/utils/csv_data_file.py @@ -1,78 +1,93 @@ import getpass -import numpy as np import re import warnings - from datetime import datetime from pathlib import Path -from openmdao.utils.units import valid_units, is_compatible +import numpy as np +from openmdao.utils.units import is_compatible, valid_units -from aviary.utils.named_values import get_items, get_keys from aviary.utils.functions import get_path -from aviary.utils.named_values import NamedValues +from aviary.utils.named_values import NamedValues, get_items, get_keys +from aviary.variable_info.enums import Verbosity # multiple type annotation uses "typeA | typeB" syntax, but requires Python 3.10+ -def read_data_file(filename: (str, Path), metadata=None, aliases=None, - save_comments=False): +# filename: (str, Path) +def read_data_file( + filename, + metadata=None, + aliases=None, + save_comments=False, + verbosity=Verbosity.BRIEF, +): """ - Read data file in Aviary format, which is data delimited by commas with any amount of - whitespace allowed between data entries. Spaces are not allowed in openMDAO - variables, so any spaces in header entries are replaced with underscores. + Read data file in Aviary format, which is data delimited by commas with any amount of whitespace + allowed between data entries. Spaces are not allowed in openMDAO variables, so any spaces in + header entries are replaced with underscores. Parameters ---------- filename : (str, Path) filename or filepath of data file to be read metadata : dict, optional - metadata to check validity of variable names provided in data file. Columns with - variable names that can't be found in metadata will be skipped. If not provided, - all validly formatted columns are always read. + metadata to check validity of variable names provided in data file. Columns with variable + names that can't be found in metadata will be skipped. If not provided, all validly + formatted columns are always read. aliases : dict, optional - optional dictionary to define a mapping of variables to allowable aliases in the - data file header. Keys are variable names, to be used in openMDAO, values - are a list of headers that correspond to that variable. Alias matching is not - case-sensitive, and underscores and spaces are treated as equivalent. + optional dictionary to define a mapping of variables to allowable aliases in the data file + header. Keys are variable names, to be used in openMDAO, values are a list of headers that + correspond to that variable. Alias matching is not case-sensitive, and underscores and + spaces are treated as equivalent. save_comments : bool, optional - flag if comments in data file should be returned along with data. Defaults to - False. + flag if comments in data file should be returned along with data. Defaults to False. + verbosity : (int, Verbosity), optional + controls level of printouts when running this method. Default is BRIEF (1). Returns ------- data : NamedValues - data read from file in NamedValues format, including variable name, units, and - values (stored in a numpy array) - comments : list of str - any comments from file, with comment characters ('#') stripped out (only if + data read from file in NamedValues format, including variable name, units, and values + (stored in a numpy array) + inputs : list + list of strings containing variables labeled as inputs in data file + outputs : list + list of strings containing variables labeled as outputs in data file + comments : list of str, optional + any comments from file, with comment characters ('#') stripped out (only if save_comments=True) """ + verbosity = Verbosity(verbosity) + filepath = get_path(filename) data = NamedValues() comments = [] + inputs = [] + outputs = [] # prep aliases for case-insensitive matching, with spaces == underscores if aliases: for key in aliases: if isinstance(aliases[key], str): aliases[key] = [aliases[key]] - aliases[key] = [re.sub('\s', '_', item).lower() for item in aliases[key]] + aliases[key] = [re.sub('\\s', '_', item).lower() for item in aliases[key]] with open(filepath, newline=None, encoding='utf-8-sig') as file: - # csv.reader() and other avaliable packages that can read csv files are not used - # Manual control of file reading ensures that comments are kept intact and other - # checks can be performed + # csv.reader() and other available packages that can read csv files are not used + # Manual control of file reading ensures that comments are kept intact and other checks can + # be performed check_for_header = True for line_count, line_data in enumerate(file): # if comments are present in line, strip them out if '#' in line_data: index = line_data.index('#') - comments.append(line_data[index+1:].strip()) + comments.append(line_data[index + 1 :].strip()) line_data = line_data[:index] # split by delimiters, remove whitespace and newline characters - line_data = re.split(r'[;,]\s*', line_data.strip()) + # do not split by delimiters inside parentheses yet + line_data = re.split(r'[;,]\s*(?![^()]*\))', line_data.strip()) # ignore empty lines if not line_data or line_data == ['']: @@ -82,7 +97,7 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, try: line_data = [float(var) for var in line_data if var != ''] # data contains things other than floats - except (ValueError): + except ValueError: # skip checking for header data if not required if check_for_header: # dictionary of header name: units @@ -90,56 +105,80 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, # list of which column goes with each valid header entry valid_indices = [] for index in range(len(line_data)): - item = re.split('[(]', line_data[index]) + item = re.split('[(,]', line_data[index]) item = [item[i].strip(') ') for i in range(len(item))] - # openMDAO vars can't have spaces, convert to underscores - name = re.sub('\s', '_', item[0]) + # OpenMDAO vars can't have spaces, convert to underscores + name = re.sub('\\s', '_', item[0]) if aliases: # "reverse" lookup name in alias dict for key in aliases: if name.lower() in aliases[key]: name = key break - # 'default' default_units + default_units = 'unitless' - # if metadata is provided, ensure variable exists and update - # default_units + # if metadata is provided, ensure variable exists and update default_units if metadata is not None: if name not in metadata.keys(): - warnings.warn(f'Header <{name}> was not recognized, and ' - 'will be skipped' - ) + if verbosity > Verbosity.QUIET: # BRIEF, VERBOSE, DEBUG + warnings.warn( + f'<{filename}: Header <{name}> was not recognized, and ' + 'will be skipped' + ) continue else: default_units = metadata[name]['units'] - # if units are provided, check that they are valid + provided_units = False if len(item) > 1: - units = item[-1] - if valid_units(item[1]): - # check that units are compatible with expected units - if metadata is not None: - if not is_compatible(units, default_units): - # Raising error here, as trying to use default - # units could mean accidental conversion which - # would significantly impact analysis - raise ValueError(f'Provided units of <{units}> ' - f'for column <{name}>, which ' - 'are not compatible with default ' - f'units of {default_units}') - else: - # Units were not recognized. Raise error - raise ValueError(f'Invalid units <{units}> provided for ' - f'column <{name}> while reading ' - f'<{filepath}>.') - else: + # check if variables are labeled inputs or outputs + if 'input' in item: + # edge case where user provides both for some reason + if 'output' in item: + raise UserWarning( + f'{filepath}: Variable {name} is listed as both an input ' + 'and an output.' + ) + item.pop(item.index('input')) + inputs.append(name) + elif 'output' in item: + item.pop(item.index('output')) + outputs.append(name) + + # if units are provided, check that they are valid + if len(item) > 1: + provided_units = True + units = item[-1] + if valid_units(item[1]): + # check that units are compatible with expected units + if metadata is not None: + if not is_compatible(units, default_units): + # Raising error here, as trying to use default units + # could mean accidental conversion which would + # significantly impact analysis + raise ValueError( + f'{filepath}: Provided units of <{units}> for ' + f'column <{name}>, which are not compatible with ' + f'default units of {default_units}.' + ) + else: + # Units were not recognized. Raise error + raise ValueError( + f'Invalid units <{units}> provided for ' + f'column <{name}> while reading ' + f'<{filepath}>.' + ) + + if not provided_units: if metadata is not None and default_units != 'unitless': - # units were not provided, but variable should have them - # assume default units for that variable - warning = f'Units were not provided for column <{name}> '\ - f'while reading <{filepath}>. Using default '\ - f'units of {default_units}.' - warnings.warn(warning) + # units were not provided, but variable should have them assume + # default units for that variable + if verbosity > Verbosity.BRIEF: # VERBOSE, DEBUG + warnings.warn( + f'Units were not provided for column <{name}> while ' + f'reading <{filepath}>. Using default units of ' + f'{default_units}.' + ) units = default_units header[name] = units @@ -152,11 +191,11 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, # only raise error if not checking for header, or invalid header found raise ValueError( - f'Non-numerical value found in data file <{filepath}> on line ' - f'{str(line_count)}') + f'Non-numerical value found in data file <{filepath}> on line {str(line_count)}' + ) - # This point is reached when the first valid numerical entry in data file - # is found. Stop looking for header data from now on + # This point is reached when the first valid numerical entry in data file is found. Stop + # looking for header data from now on check_for_header = False # pull out data for each valid header, ignore other columns @@ -169,14 +208,21 @@ def read_data_file(filename: (str, Path), metadata=None, aliases=None, data.set_val(variable, val=np.array(raw_data[variable]), units=header[variable]) if save_comments: - return data, comments + return data, inputs, outputs, comments else: - return data + return data, inputs, outputs # multiple type annotation uses "typeA | typeB" syntax, but requires Python 3.10+ -def write_data_file(filename: (str, Path) = None, data: NamedValues = None, - comments: (str, list) = [], include_timestamp: bool = False): +# filename: (str, Path) +# comments: (str, list) +def write_data_file( + filename, + data: NamedValues = None, + outputs: list = None, + comments=[], + include_timestamp: bool = False, +): """ Write data to a comma-separated values (csv) format file using the Aviary data table format. @@ -186,13 +232,14 @@ def write_data_file(filename: (str, Path) = None, data: NamedValues = None, filename : (str, Path) filename or filepath for data file to be written data : NamedValues - NamedValues object containing data that will be written to file, which includes - variable name, units, and values + NamedValues object containing data that will be written to file, which includes variable + name, units, and values + outputs : list of str, optional + list of variable names in data that are dependents comments : (str, list of str), optional - optional comments that will be included in the top of the output file, before - data begins + optional comments that will be included in the top of the output file, before data begins include_timestamp : bool, optional - optional flag to set if timestamp and user should be include in file comments + optional flag to set if timestamp and user should be included in file comments """ if isinstance(filename, str): filepath = Path(filename) @@ -202,6 +249,10 @@ def write_data_file(filename: (str, Path) = None, data: NamedValues = None, if data is None: raise UserWarning(f'No data provided to write to {filepath.name}') + label_variables = False + if outputs is not None: + label_variables = True + if type(comments) is str: comments = [comments] @@ -212,7 +263,7 @@ def write_data_file(filename: (str, Path) = None, data: NamedValues = None, comments[idx] = '# ' + line.strip() # if there are comments, add some spacing afterwards - otherwise it should be empty - if comments: + if comments != []: comments.append('\n') if include_timestamp: @@ -221,19 +272,34 @@ def write_data_file(filename: (str, Path) = None, data: NamedValues = None, user = ' by ' + getpass.getuser() except Exception: user = '' - stamp = [f'# created {timestamp}{user}\n'] + stamp = [f'# created {timestamp}{user}'] + # edge case of no comments but timestamp, make sure there is a space before data + if comments == []: + comments = ['\n'] comments = stamp + comments - # assemble separate variable name and units information into single list for header + # assemble separate variable name, units, and dependence information into single list for header header = [] data_dict = {} for var, val_and_units in get_items(data): units = val_and_units[1] - formatted_units = '' + var_info = '' # only explicitly include units if there are any if units is not None and units != 'unitless': - formatted_units = ' (' + units + ')' - header.append(var + formatted_units) + var_info = units + # label variables as inputs/outputs if information is avaliable + if label_variables: + if var_info != '': + var_info = var_info + ', ' + if var in outputs: + var_info = var_info + 'output' + else: + var_info = var_info + 'input' + + if var_info != '': + var_info = f' ({var_info})' + + header.append(var + var_info) data_dict[var] = np.array([str(i) for i in data.get_val(var, units)]) # set column widths, for more human-readable format @@ -251,12 +317,12 @@ def write_data_file(filename: (str, Path) = None, data: NamedValues = None, # if headers are smaller than column, pad with leading whitespace if header_len < col_len: - header[i] = ' '*(col_len-header_len) + header[i] + header[i] = ' ' * (col_len - header_len) + header[i] # special string to define column formatting with specific width format = f'%{col_len}s' # don't include commas for last column - if i < len(header)-1: + if i < len(header) - 1: format = format + ', ' col_format.append(format) @@ -264,8 +330,11 @@ def write_data_file(filename: (str, Path) = None, data: NamedValues = None, formatted_data = np.array([data_dict[key] for key in data_dict]).transpose() # write to output file w/ header and comments - np.savetxt(filepath, formatted_data, - fmt=''.join(col_format), - delimiter=',', - header=', '.join(header), - comments='\n'.join(comments)) + np.savetxt( + filepath, + formatted_data, + fmt=''.join(col_format), + delimiter=',', + header=', '.join(header), + comments='\n'.join(comments), + ) diff --git a/aviary/utils/data_interpolator_builder.py b/aviary/utils/data_interpolator_builder.py index 2e641fd5c1..55937e993a 100644 --- a/aviary/utils/data_interpolator_builder.py +++ b/aviary/utils/data_interpolator_builder.py @@ -1,57 +1,64 @@ -import warnings +from pathlib import Path + import numpy as np import openmdao.api as om -from pathlib import Path - -from aviary.utils.named_values import get_keys, get_items from aviary.utils.csv_data_file import read_data_file from aviary.utils.functions import get_path -from aviary.utils.named_values import NamedValues - - -def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outputs=None, - method='slinear', extrapolate=True, structured=None, - connect_training_data=False): +from aviary.utils.named_values import NamedValues, get_items, get_keys + + +def build_data_interpolator( + interpolator_data=None, + interpolator_outputs=None, + num_nodes=1, + method='slinear', + extrapolate=True, + structured=None, + connect_training_data=False, +): """ - Builder for openMDAO metamodel components using data provided via data file, directly - provided as an argument, or training data passed through openMDAO connections. - If using a structured grid, data can either be converted from a semistructured - grid format, or directly provided in structured grid format. + Builder for openMDAO metamodel components using data provided via data file, directly provided + as an argument, or training data passed through openMDAO connections. Data is converted to a + structured grid format if possible, otherwise a semistructured grid is assumed. Parameters ---------- - num_nodes : int - Number of points that will be simultaneously interpolated during model executuion. + Number of points that will be simultaneously interpolated during model execution. interpolator_data : (str, Path, NamedValues) - Path to the Aviary csv file containing all data required for interpolation, or - the data directly given as a NamedValues object. + Path to the Aviary csv file containing all data required for interpolation, or the data + directly given as a NamedValues object. + + interpolator_outputs : list, dict, optional + if connect_training_data is true, a dictionary describing the names of dependent variables + (keys) and their units (values). This dictionary describes the names and units for training + data that will be provided via openMDAO connections during model execution. - interpolator_outputs : dict - Dictionary describing the names of dependent variables (keys) and their - units (values). If connect_training_data is False, these variable names must reference - variables in data_file or interpolator_data. If connect_training_data is True, then - this dictionary describes the names and units for training data that will be - provided via openMDAO connections during model execution. + If connect_training_data is False, a list of the names of dependent variables in + interpolator_data. These variable names should reference variables in interpolator_data, + and are ignored otherwise. + + Required if interpolator_data is a NamedValues object. + + num_nodes : int + Number of points that will be simultaneously interpolated during model executuion. method : str, optional - Interpolation method for metamodel. See openMDAO documentation for valid - options. + Interpolation method for metamodel. See openMDAO documentation for valid options. extrapolate : bool, optional Flag that sets if metamodel should allow extrapolation structured : bool, optional - Flag to set if interpolation data is a structure grid. If True, the - structured metamodel component is used, if False, the semistructured metamodel is - used. If None, the builder chooses based on provided data structure. + Flag to set if interpolation data is a structure grid. If True, the structured metamodel + component is used, if False, the semistructured metamodel is used. If None, the builder + chooses based on provided data structure. connect_training_data : bool, optional - Flag that sets if dependent data for interpolation will be passed via openMDAO - connections. If True, any provided values for dependent variables will - be ignored. + Flag that sets if dependent data for interpolation will be passed via openMDAO connections. + If True, any provided values for dependent variables will be ignored. Returns ------- @@ -59,20 +66,63 @@ def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outp OpenMDAO metamodel component using the provided data and flags """ # Argument checking # - if interpolator_outputs is None: - raise UserWarning('Independent variables for interpolation were not provided.') # if interpolator data is a filepath, get data from file if isinstance(interpolator_data, str): interpolator_data = get_path(interpolator_data) if isinstance(interpolator_data, Path): - interpolator_data = read_data_file(interpolator_data) + interpolator_data, inputs, outputs = read_data_file(interpolator_data) + else: + inputs = [] + outputs = [] + + # Determine if independent and dependent variables are accounted for + # Combine interpolator_outputs & outputs found in data file + if interpolator_outputs is not None: + if isinstance(interpolator_outputs, dict): + addtl_outputs = list(interpolator_outputs.keys()) + else: + addtl_outputs = interpolator_outputs + outputs = list(set(outputs + addtl_outputs)) + + all_vars = get_keys(interpolator_data) + + # Scenario 1: Only outputs provided in data file + if len(inputs) == 0 and len(outputs) != 0: + for key in all_vars: + if key not in outputs: + inputs.append(key) + # Scenario 2: Only inputs provided in data file + elif len(inputs) != 0 and len(outputs) == 0: + for key in all_vars: + if key not in inputs: + outputs.append(key) + + # Raise UserWarning if Scenario 1 or 2 fails + if len(outputs) == 0: + raise UserWarning( + 'Insufficient information on inputs and outputs for interpolation was provided' + ) + # Scenario 3: Both inputs and outputs provided + # Check that nothing in interpolator_outputs conflicts with inputs - read_data_file() already + # checks for "double labeling" of inputs/outputs in data file + for key in interpolator_outputs: + if key in inputs: + raise UserWarning(f'Variable <{key}> was specified as both an input and a output.') + for key in all_vars: + if key in inputs: + continue + if key in outputs: + continue + raise UserWarning( + 'Insufficient information on inputs and outputs for interpolation was provided' + ) # Pre-format data: Independent variables placed before dependent variables - position # of these variables relative to others of their type is preserved # All data converted to numpy arrays indep_vars = NamedValues() dep_vars = NamedValues() - for (key, (val, units)) in get_items(interpolator_data): + for key, (val, units) in get_items(interpolator_data): if not isinstance(val, np.ndarray): val = np.array(val) if key in interpolator_outputs: @@ -81,7 +131,7 @@ def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outp indep_vars.set_val(key, val, units) # update interpolator_data with correctly ordered indep/dep vars in numpy arrays interpolator_data.update(indep_vars) - for (key, (val, units)) in get_items(dep_vars): + for key, (val, units) in get_items(dep_vars): interpolator_data.set_val(key, val, units) # TODO investigate creating structured grid from semistructured grid via extrapolation @@ -91,9 +141,9 @@ def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outp data_pre_structured = True shape = [] # check inputs, should be vector of unique values only - for (key, (val, units)) in get_items(interpolator_data): + for key, (val, units) in get_items(interpolator_data): if len(val.shape) == 1: - if key not in interpolator_outputs: + if key not in outputs: # try: if np.array_equal(np.unique(val), val): # if vector is only unique values, could be structured! @@ -107,15 +157,17 @@ def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outp # check outputs, should be array matching shape of input vector lengths # if we already know data needs formatting, don't bother checking outputs if data_pre_structured: - for key in interpolator_outputs: + for key in outputs: (val, units) = interpolator_data.get_item(key) if np.shape(val) != tuple(shape): if len(np.shape(val)) > 1: # we assume user was *trying* to set up a structured grid # if output is multi-dimensional array. If output is 1d it could - # be a strucured grid with one input, or a semistructured grid - raise ValueError(f'shape of output <{key}>, {np.shape(val)}, does ' - f'not match expected shape {tuple(shape)}') + # be a structured grid with one input, or a semistructured grid + raise ValueError( + f'shape of output <{key}>, {np.shape(val)}, does ' + f'not match expected shape {tuple(shape)}' + ) else: # We don't know if data is structured or not if 1d. No harm # in sorting and "reformatting", so assume it needs to be converted @@ -132,7 +184,7 @@ def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outp if not connect_training_data: # Sort and format data. Only if not using training data - since we have control - # over both input and output data they are guarenteed to match after reformatting + # over both input and output data they are guaranteed to match after reformatting # sort data in semistructured grid format # always sort unless data is in structured format @@ -147,16 +199,15 @@ def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outp prev_model_length = len(interpolator_data.get_val(key, units)) model_length = len(interpolator_data.get_val(key, units)) if model_length != prev_model_length: - raise IndexError('Lengths of data provided for interpolation do not ' - 'match.') + raise IndexError('Lengths of data provided for interpolation do not match.') # get data into column array format - sorted_values = np.array([val for (key, (val, units)) - in get_items(interpolator_data)]).transpose() + sorted_values = np.array( + [val for (key, (val, units)) in get_items(interpolator_data)] + ).transpose() # get all the independent values in format needed for sorting - independent_vals = np.array([val for (key, (val, units)) - in get_items(indep_vars)]) + independent_vals = np.array([val for (key, (val, units)) in get_items(indep_vars)]) # Sort by dependent variables in priority order of their appearance sorted_values = sorted_values[np.lexsort(np.flip(independent_vals, 0))] @@ -206,33 +257,32 @@ def build_data_interpolator(num_nodes, interpolator_data=None, interpolator_outp # create interpolation component if structured: - interp_comp = om.MetaModelStructuredComp(method=method, - extrapolate=extrapolate, - vec_size=num_nodes, - training_data_gradients=connect_training_data) + interp_comp = om.MetaModelStructuredComp( + method=method, + extrapolate=extrapolate, + vec_size=num_nodes, + training_data_gradients=connect_training_data, + ) else: - interp_comp = om.MetaModelSemiStructuredComp(method=method, - extrapolate=extrapolate, - vec_size=num_nodes, - training_data_gradients=connect_training_data) + interp_comp = om.MetaModelSemiStructuredComp( + method=method, + extrapolate=extrapolate, + vec_size=num_nodes, + training_data_gradients=connect_training_data, + ) # add interpolator inputs for key in get_keys(indep_vars): values, units = interpolator_data.get_item(key) - interp_comp.add_input(key, - training_data=values, - units=units) + interp_comp.add_input(key, training_data=values, units=units) # add interpolator outputs - for key in interpolator_outputs: - if key in interpolator_data: - values, units = interpolator_data.get_item(key) - if connect_training_data: + if connect_training_data: + for key in interpolator_outputs: units = interpolator_outputs[key] - interp_comp.add_output(key, - units=units) - else: - interp_comp.add_output(key, - training_data=values, - units=units) + interp_comp.add_output(key, units=units) + else: + for key in outputs: + values, units = interpolator_data.get_item(key) + interp_comp.add_output(key, training_data=values, units=units) return interp_comp diff --git a/aviary/utils/develop_metadata.py b/aviary/utils/develop_metadata.py index 4950a2d60d..66ad65620c 100644 --- a/aviary/utils/develop_metadata.py +++ b/aviary/utils/develop_metadata.py @@ -1,14 +1,16 @@ def add_meta_data( - key, - meta_data, - units='unitless', - desc=None, - default_value=0.0, - option=False, - types=None, - historical_name=None, - _check_unique=True): - ''' + key: str, + meta_data: dict, + units='unitless', + default_value=0.0, + types=None, + multivalue: bool = False, + option: bool = False, + desc: str = None, + historical_name=None, + _check_unique=True, +): + """ Add new meta data associated with variables in the Aviary data hierarchy. Parameters @@ -32,78 +34,104 @@ def add_meta_data( Note, a default value of `None` indicates that the variable is optional, but that there is no default. + types : type, optional + gives the allowable type(s) of the variable in the aviary API. if `multivalue` is + True, this specifies which types individual elements in the list can be. If + `types` is not provided, the type of `default_value` is used. Numerical data + for `default_value` is assumed to be a float in this case. + option : bool indicates that this variable is an option, rather than a normal input - types : type - gives the allowable type(s) of the variable + multivalue : bool + when True, the variable can become an iterable (list, tuple, numpy array) of + elements whose type is in `types`. historical_name : dict or None dictionary of names that the variable held in prior codes - Example: {"FLOPS":"WTIN.WNGWT", "LEAPS1": "aircraft.inputs.wing_weight", "GASP": "INGASP.WWGHT"} + Example: {"FLOPS":"WTIN.WNGWT", "LEAPS1": "aircraft.inputs.wing_weight", "GASP": + "INGASP.WWGHT"} - NAMELIST nameing convention - &.. + NAMELIST naming convention + &.. - Example: &DEFINE.CONFIN.GW - represents the GW variable of the CONFIN namelist as defined in - the DEFINE subroutine + Example: &DEFINE.CONFIN.GW + represents the GW variable of the CONFIN namelist as defined in + the DEFINE subroutine COMMON block naming convention, including aliases: - . + . - Example: CONFIG.GW - represents the GW variable of the CONFIG common block + Example: CONFIG.GW + represents the GW variable of the CONFIG common block - Local variable naming convention, including equivalence statements, parameters, and other local declarations: - ~. + Local variable naming convention, including equivalence statements, parameters, + and other local declarations: + ~. - Example: ~ANALYS.GWTOL - represents the GWTOL variable of the ANALYS subroutine + Example: ~ANALYS.GWTOL + represents the GWTOL variable of the ANALYS subroutine _check_unique : bool - private use only flag that tells whether to check the meta_data for the pre-existing presence - of the provided key. This should only be set to false when update_meta_data is the calling function. + private use only flag that tells whether to check the meta_data for the + pre-existing presence of the provided key. This should only be set to false when + update_meta_data is the calling function. Returns - ------- + ------- None No variables returned by this method. Raises - ---------- + ------ None - No exceptions raised by this method, although other methods called within may raise exceptions. - ''' - + No exceptions raised by this method, although other methods called within may + raise exceptions. + """ if key in meta_data and _check_unique: raise ValueError( - f'You added the variable {key} to a variable metadata dictionary via the add_meta_data function, but {key} already was present in the dictionary. If you are sure you want to overwrite this variable, call the update_meta_data function instead.') + f'You added the variable {key} to a variable metadata dictionary via the ' + f'add_meta_data function, but {key} already was present in the dictionary. ' + 'If you are sure you want to overwrite this variable, call the ' + 'update_meta_data function instead.' + ) if units is None: units = 'unitless' + if types is None and default_value is not None: + try: + # Try casting to float, as it is common for users to intend use of floats but + # not include decimal points in default_value + default_value = float(default_value) + except (ValueError, TypeError): + pass # default_value is not a numerical value + types = type(default_value) + meta_data[key] = { 'historical_name': historical_name, 'units': units, 'desc': desc, 'option': option, 'default_value': default_value, - 'types': types + 'types': types, + 'multivalue': multivalue, } def update_meta_data( - key, - meta_data, - units='unitless', - desc=None, - default_value=0.0, - option=False, - types=None, - historical_name=None): - ''' + key: str, + meta_data: dict, + units='unitless', + desc: str = None, + default_value=0.0, + option: bool = False, + types=None, + multivalue: bool = False, + historical_name=None, +): + """ Update existing meta data associated with variables in the Aviary data hierarchy. Parameters @@ -133,44 +161,64 @@ def update_meta_data( types : type gives the allowable type(s) of the variable + multivalue : bool + when True, the variable can become a list of elements whose type is in types. + This is mainly used when there are multiple engine types. + historical_name : dict or None dictionary of names that the variable held in prior codes - Example: {"FLOPS":"WTIN.WNGWT", "LEAPS1": "aircraft.inputs.wing_weight", "GASP": "INGASP.WWGHT"} + Example: {"FLOPS":"WTIN.WNGWT", "LEAPS1": "aircraft.inputs.wing_weight", "GASP": + "INGASP.WWGHT"} - NAMELIST nameing convention - &.. + NAMELIST naming convention + &.. - Example: &DEFINE.CONFIN.GW - represents the GW variable of the CONFIN namelist as defined in - the DEFINE subroutine + Example: &DEFINE.CONFIN.GW + represents the GW variable of the CONFIN namelist as defined in + the DEFINE subroutine COMMON block naming convention, including aliases: - . + . - Example: CONFIG.GW - represents the GW variable of the CONFIG common block + Example: CONFIG.GW + represents the GW variable of the CONFIG common block - Local variable naming convention, including equivalence statements, parameters, and other local declarations: - ~. + Local variable naming convention, including equivalence statements, parameters, + and other local declarations: + ~. - Example: ~ANALYS.GWTOL - represents the GWTOL variable of the ANALYS subroutine + Example: ~ANALYS.GWTOL + represents the GWTOL variable of the ANALYS subroutine Returns - ------- + ------- None No variables returned by this method. Raises - ---------- + ------ None - No exceptions raised by this method, although other methods called within may raise exceptions. - ''' - + No exceptions raised by this method, although other methods called within may + raise exceptions. + """ if key not in meta_data: raise ValueError( - f'You provided the variable {key} to a variable metadata dictionary via the update_meta_data function, but {key} does not exist in the dictionary. If you are sure you want to add this variable to the dictionary, call the add_meta_data function instead.') - - add_meta_data(key=key, meta_data=meta_data, units=units, desc=desc, - default_value=default_value, option=option, types=types, historical_name=historical_name, _check_unique=False) + f'You provided the variable {key} to a variable metadata dictionary via the ' + f'update_meta_data function, but {key} does not exist in the dictionary. If ' + 'you are sure you want to add this variable to the dictionary, call the ' + 'add_meta_data function instead.' + ) + + add_meta_data( + key=key, + meta_data=meta_data, + units=units, + desc=desc, + default_value=default_value, + option=option, + types=types, + multivalue=multivalue, + historical_name=historical_name, + _check_unique=False, + ) diff --git a/aviary/utils/doctape.py b/aviary/utils/doctape.py index 13f1294100..8b08fb111b 100644 --- a/aviary/utils/doctape.py +++ b/aviary/utils/doctape.py @@ -1,9 +1,14 @@ +import argparse +import ast import inspect +import os +import re import subprocess import tempfile -import os +import textwrap import numpy as np +from aviary.interface.cmd_entry_points import _command_map """ # DocTAPE # @@ -14,7 +19,7 @@ for automating the process of building and testing documentation to ensure that documentation doesn't get stale. -expected_error is an execption that can be used in try/except blocks to allow desired errors to +expected_error is an exception that can be used in try/except blocks to allow desired errors to pass while still raising unexpected errors. gramatical_list combines the elements of a list into a string with proper punctuation @@ -25,18 +30,25 @@ get_attribute_name gets the name of an object's attribute based on it's value get_all_keys recursively get all of the keys from a dict of dicts get_value recursively get a value from a dict of dicts -glue_variable Glue a variable for later use in markdown cells of notebooks (can auto format for code) +glue_variable glue a variable for later use in markdown cells of notebooks (can auto format for code) glue_keys recursively glue all of the keys from a dict of dicts +glue_actions glue all Aviary CLI options for a given command +glue_class_functions glue all class functions for a gen class +glue_function_arguments glue all function arguments and default values for a given function +glue_class_options glue all class options for a given class +get_previous_line returns the previous n line(s) of code as a string +get_class_names return the class names in a file as a set +get_function_names returns the function names in a file as a set +get_all_non_aviary_names returns the non-Aviary variable names of a component """ -class expected_error(Exception): - ... +class expected_error(Exception): ... def gramatical_list(list_of_strings: list, cc='and', add_accents=False) -> str: """ - Combines the elements of a list into a string with proper punctuation + Combines the elements of a list into a string with proper punctuation. Parameters ---------- @@ -52,19 +64,18 @@ def gramatical_list(list_of_strings: list, cc='and', add_accents=False) -> str: str A string that combines the elements of the list into a string with proper punctuation """ - list_of_strings = ['`'+str(s)+'`' if add_accents else str(s) - for s in list_of_strings] + list_of_strings = ['`' + str(s) + '`' if add_accents else str(s) for s in list_of_strings] if len(list_of_strings) == 1: return list_of_strings[0] elif len(list_of_strings) == 2: - return list_of_strings[0]+' '+cc+' '+list_of_strings[1] + return list_of_strings[0] + ' ' + cc + ' ' + list_of_strings[1] else: - return ', '.join(list_of_strings[:-1]+[cc+' '+list_of_strings[-1]]) + return ', '.join(list_of_strings[:-1] + [cc + ' ' + list_of_strings[-1]]) def get_previous_line(n=1) -> str: """ - returns the previous n line(s) of code as a string + Returns the previous n line(s) of code as a string. Parameters ---------- @@ -83,12 +94,13 @@ def get_previous_line(n=1) -> str: # get the line number of the line that called this function lineno = pframe.f_lineno - first_line if first_line else pframe.f_lineno - 1 # get the previous lines - return lines[lineno-n:lineno] if n > 1 else lines[lineno-1].strip() + return lines[lineno - n : lineno] if n > 1 else lines[lineno - 1].strip() def get_variable_name(*variables) -> str: """ - returns the name of the variable passed to the function as a string + Returns the name of the variable passed to the function as a string + # NOTE: You cannot call this function multiple times on one line. Parameters ---------- @@ -107,8 +119,20 @@ def get_variable_name(*variables) -> str: # get the line number that called this function lineno = pframe.f_lineno - first_line if first_line else pframe.f_lineno - 1 # extract the argument and remove all whitespace - arg: str = ''.join(lines[lineno].split( - 'get_variable_name(')[1].split(')')[0].split()) + arg = ''.join(lines[lineno].split()).split('get_variable_name(', 1)[1] + + # Use regex to match balanced parentheses + match = re.match(r'([^()]*\([^()]*\))*[^()]*', arg) + if match: + arg = match.group(0) + + # # Requires Python 3.11, but allows this to be called multiple times on one line + # positions = inspect.getframeinfo(pframe).positions + # calling_lines = lines[positions.lineno-1:positions.end_lineno] + # calling_lines[-1] = calling_lines[-1][:positions.end_col_offset-1] + # calling_lines[0] = calling_lines[0][positions.col_offset:].removeprefix('get_variable_name(') + # arg = ''.join([l.strip() for l in calling_lines]) + if ',' in arg: return arg.split(',') else: @@ -139,16 +163,21 @@ def check_value(val1, val2, error_type=ValueError): """ if isinstance(val1, (str, int, float, list, tuple, dict, set, np.ndarray, type({}.keys()))): if val1 != val2: - raise error_type(f"{val1} is not equal to {val2}") + raise error_type(f'{val1} is not equal to {val2}') else: if val1 is not val2: - raise error_type(f"{val1} is not {val2}") + raise error_type(f'{val1} is not {val2}') -def check_contains(expected_values, actual_values, error_string="{var} not in {actual_values}", error_type=RuntimeError): +def check_contains( + expected_values, + actual_values, + error_string='{var} not in {actual_values}', + error_type=RuntimeError, +): """ Checks that all of the expected_values exist in actual_values - (It does not check for missing values) + (It does not check for missing values). Parameters ---------- @@ -174,7 +203,13 @@ def check_contains(expected_values, actual_values, error_string="{var} not in {a raise error_type(error_string.format(var=var, actual_values=actual_values)) -def check_args(func, expected_args: tuple[list, dict, str], args_to_ignore: tuple[list, tuple] = ['self'], exact=True, error_type=ValueError): +def check_args( + func, + expected_args: tuple[list, dict, str], + args_to_ignore: tuple[list, tuple] = ['self'], + exact=True, + error_type=ValueError, +): """ Checks that the expected arguments are valid for a given function. @@ -206,8 +241,7 @@ def check_args(func, expected_args: tuple[list, dict, str], args_to_ignore: tupl expected_args = [expected_args] exact = False params = inspect.signature(func).parameters - available_args = { - arg: params[arg].default for arg in params if arg not in args_to_ignore} + available_args = {arg: params[arg].default for arg in params if arg not in args_to_ignore} if exact: if isinstance(expected_args, dict): check_value(available_args, expected_args) @@ -219,10 +253,11 @@ def check_args(func, expected_args: tuple[list, dict, str], args_to_ignore: tupl raise error_type(f'{arg} is not a valid argument for {func.__name__}') elif isinstance(expected_args, dict) and expected_args[arg] != available_args[arg]: raise error_type( - f"the default value of {arg} is {available_args[arg]}, not {expected_args[arg]}") + f'the default value of {arg} is {available_args[arg]}, not {expected_args[arg]}' + ) -def run_command_no_file_error(command: str): +def run_command_no_file_error(command: str, verbose=False): """ Executes a CLI command and handles FileNotFoundError separately. @@ -235,26 +270,37 @@ def run_command_no_file_error(command: str): ---------- command : str The CLI command to be executed. + verbose : bool + Whether or not to include the error message if FileNotFoundError is raised Raises ------ CalledProcessError If the command returns a non-zero exit code (except for FileNotFoundError). """ - with tempfile.TemporaryDirectory() as tempdir: - rc = subprocess.run(command.split(), cwd=tempdir, capture_output=True, text=True) - if rc.returncode: - err = rc.stderr.split('\n')[-2].split(':')[0] - if err == 'FileNotFoundError': - print(err) - else: - print(rc.stderr) - rc.check_returncode() + # Save the current directory + original_cwd = os.getcwd() + + try: + with tempfile.TemporaryDirectory() as tempdir: + rc = subprocess.run(command.split(), cwd=tempdir, capture_output=True, text=True) + if rc.returncode: + err, info = rc.stderr.split('\n')[-2].split(':', 1) + if err == 'FileNotFoundError': + if verbose: + print(info) + print(f"A file required by {command} couldn't be found, continuing anyway") + else: + print(rc.stderr) + rc.check_returncode() + finally: + # Always restore the original directory + os.chdir(original_cwd) def get_attribute_name(object: object, attribute, error_type=AttributeError) -> str: """ - Gets the name of an object's attribute based on it's value + Gets the name of an object's attribute based on it's value. This is intended for use with Enums and other objects that have unique values. This method will return the name of the first attribute that has a value that @@ -283,15 +329,15 @@ def get_attribute_name(object: object, attribute, error_type=AttributeError) -> if val == attribute: return name - raise error_type( - f"`{object.__name__}` object has no attribute with a value of `{attribute}`") + raise error_type(f'`{object.__name__}` object has no attribute with a value of `{attribute}`') def get_all_keys(dict_of_dicts: dict, track_layers=False, all_keys=None) -> list: """ Recursively get all of the keys from a dict of dicts + This can also be used to recursively get all of the attributes from a complex object, like the Aircraft hierarchy Note: this will not add duplicates of keys, but will - continue deeper even if a key is duplicated + continue deeper even if a key is duplicated. Parameters ---------- @@ -309,18 +355,23 @@ def get_all_keys(dict_of_dicts: dict, track_layers=False, all_keys=None) -> list all_keys : list A list of all the keys in the dict_of_dicts """ + if not isinstance(dict_of_dicts, dict): + dict_of_dicts = dict_of_dicts.__dict__ if all_keys is None: all_keys = [] + for key, val in dict_of_dicts.items(): + if key.startswith('__') and key.endswith('__'): + continue if track_layers is True: current_layer = '' elif track_layers: current_layer = track_layers if track_layers and current_layer: - key = current_layer+'.'+key + key = current_layer + '.' + key if key not in all_keys: all_keys.append(key) - if isinstance(val, dict): + if isinstance(val, dict) or hasattr(val, '__dict__'): if track_layers: current_layer = key else: @@ -331,7 +382,7 @@ def get_all_keys(dict_of_dicts: dict, track_layers=False, all_keys=None) -> list def get_value(dict_of_dicts: dict, comlpete_key: str): """ - Recursively get a value from a dict of dicts + Recursively get a value from a dict of dicts. Parameters ---------- @@ -345,15 +396,16 @@ def get_value(dict_of_dicts: dict, comlpete_key: str): val : any The value found """ - for key in comlpete_key.split('.'): + if not isinstance(dict_of_dicts, dict): + dict_of_dicts = dict_of_dicts.__dict__ dict_of_dicts = dict_of_dicts[key] return dict_of_dicts def glue_variable(name: str, val=None, md_code=False, display=True): """ - Glue a variable for later use in markdown cells of notebooks + Glue a variable for later use in markdown cells of notebooks. Note: glue_variable(get_variable_name(Aircraft.APU.MASS)) @@ -370,20 +422,26 @@ def glue_variable(name: str, val=None, md_code=False, display=True): Whether to wrap the value in markdown code formatting (e.g. `code`) """ # local import so myst isn't required unless glue is being used - from myst_nb import glue from IPython.display import Markdown + from IPython.utils import io + from myst_nb import glue + if val is None: val = name if md_code: - val = Markdown('`'+val+'`') + val = Markdown(f'`{val}`') else: - val = Markdown(val) - glue(name, val, display) + val = Markdown(f'{val}') + + with io.capture_output() as captured: + glue(f'{name}', val, display) + # if display: + captured.show() def glue_keys(dict_of_dicts: dict, display=True) -> list: """ - Recursively glue all of the keys from a dict of dicts + Recursively glue all of the keys from a dict of dicts. Parameters ---------- @@ -395,7 +453,221 @@ def glue_keys(dict_of_dicts: dict, display=True) -> list: all_keys : list A list of all the keys that were glued """ - all_keys = get_all_keys(dict_of_dicts) + if not isinstance(dict_of_dicts, dict): + track_layers = dict_of_dicts.__name__ + else: + track_layers = False + all_keys = get_all_keys(dict_of_dicts, track_layers) + for key in all_keys: glue_variable(key, md_code=True, display=display) return all_keys + + +def get_class_names(file_path) -> set: + """ + Retrieve all class names from a given file and return as a set. + + Parameters + ---------- + file_path: str or Path + file path + """ + # Read the content of the file + with open(file_path, 'r') as file: + file_content = file.read() + + # Parse the file content into an AST + tree = ast.parse(file_content) + + # Extract class names + class_names = [node.name for node in ast.walk(tree) if isinstance(node, ast.ClassDef)] + + return set(class_names) + + +def get_function_names(file_path) -> set: + """ + Get all function names in a given file and return as a set. + + Parameters + ---------- + file_path: str or Path + file path + """ + # Read the content of the file + with open(file_path, 'r') as file: + file_content = file.read() + + # Parse the file content into an AST + tree = ast.parse(file_content) + + # Extract function names + function_names = [node.name for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)] + + return set(function_names) + + +def glue_actions(cmd, curr_glued=None, glue_default=False, glue_choices=False, md_code=True): + """ + Glue all Aviary CLI options. + + Parameters + ---------- + cmd: str + Aviary command + curr_glued: list + the parameters that have been glued + glue_default: boolean + flag whether the default values should be glued + """ + if curr_glued is None: + curr_glued = [] + parser = argparse.ArgumentParser() + _command_map[cmd][0](parser) + actions = [*parser._get_optional_actions(), *parser._get_positional_actions()] + for action in actions: + opt_list = action.option_strings + for opt in opt_list: + if opt not in curr_glued: + glue_variable(opt, md_code=md_code) + curr_glued.append(opt) + if action.dest not in curr_glued: + glue_variable(action.dest, md_code=md_code) + curr_glued.append(action.dest) + if glue_default: + action_default = f'{action.dest}_default' + if action_default not in curr_glued: + glue_variable(action_default, str(action.default), md_code=True) + curr_glued.append(action_default) + if glue_choices: + if action.choices is not None: + for choice in action.choices: + if str(choice) not in curr_glued: + glue_variable(str(choice), md_code=True) + curr_glued.append(str(choice)) + + +def glue_class_functions(obj, curr_glued=None, prefix=None, md_code=True): + """ + Glue all class functions. + + For a function 'foo', glue 'foo' and 'foo()' + If a prefix is defined, also glue 'prefix.foo' and 'prefix.foo()' + + Parameters + ---------- + obj: class + class object + curr_glued: list + the parameters that have been glued + prefix: str + Preix to be prepended. + """ + if curr_glued is None: + curr_glued = [] + methods = inspect.getmembers(obj, predicate=inspect.isfunction) + for func_name, func in methods: + forms = [func_name, f'{func_name}()'] + if prefix is not None: + pre_forms = [f'{prefix}.{name}' for name in forms] + forms.extend(pre_forms) + for form in forms: + if form not in curr_glued: + glue_variable(form, md_code=md_code) + curr_glued.append(form) + + +def glue_function_arguments(func, curr_glued=None, glue_default=False, md_code=False): + """ + Glue all function arguments and default values for a given function. + + Parameters + ---------- + func: function + function + curr_glued: list + the parameters that have been glued + """ + if curr_glued is None: + curr_glued = [] + sig = inspect.signature(func) + for param_name, param in sig.parameters.items(): + if param_name not in curr_glued and param_name != 'self': + glue_variable(param_name, md_code=md_code) + curr_glued.append(param_name) + if glue_default and str(param.default) is not param.empty: + param_default = param_name + '_default' + if param_default not in curr_glued: + glue_variable(param_default, str(param.default), md_code=md_code) + curr_glued.append(param_default) + + +def glue_class_options(obj, curr_glued=None, md_code=False, add_attributes=True): + """ + Glue all class options for a given class. + + This includes all options that have been declared in the base options dict. It also optionally + includes class attributes that are declared in the init method. + + Parameters + ---------- + obj: class + class + curr_glued: list + the parameters that have been glued + add_attributes: bool + When True, also add any class and instance attributes. Default is True. + """ + if curr_glued is None: + curr_glued = [] + obj = obj() + opts = list(obj.options) + for opt in opts: + if opt not in curr_glued: + glue_variable(opt, md_code=md_code) + curr_glued.append(opt) + + for item in obj.__dict__: + if item not in curr_glued: + glue_variable(item, md_code=md_code) + curr_glued.append(item) + + +def get_all_non_aviary_names(cls, include_in_out='in_out'): + """ + Retrieve the names of all the non-Aviary variables of a component class + created by self.add_input() or self.add_output() methods in setup(). + """ + method_name = 'setup' + func = getattr(cls, method_name) + source = inspect.getsource(func) + source = textwrap.dedent(source) # remove indentation + tree = ast.parse(source) + + if include_in_out == 'in_out': + including_flags = ['add_input', 'add_output'] + elif include_in_out == 'in': + including_flags = ['add_input'] + elif include_in_out == 'out': + including_flags = ['add_output'] + else: + including_flags = [] + + names = [] + for node in ast.walk(tree): + if isinstance(node, ast.Call): + if ( + isinstance(node.func, ast.Attribute) + and node.func.attr in including_flags + and isinstance(node.func.value, ast.Name) + and node.func.value.id == 'self' + ): + # Case 1: name is the first positional argument + if node.args and isinstance(node.args[0], ast.Constant): + names.append(node.args[0].value) + # Case 2: name is given as a keyword + for kw in node.keywords: + if kw.arg == 'name' and isinstance(kw.value, ast.Constant): + names.append(kw.value.value) + return names diff --git a/aviary/utils/engine_deck_conversion.py b/aviary/utils/engine_deck_conversion.py index b6476f733a..165a125dfc 100644 --- a/aviary/utils/engine_deck_conversion.py +++ b/aviary/utils/engine_deck_conversion.py @@ -1,22 +1,23 @@ #!/usr/bin/python - import argparse import getpass +from copy import deepcopy from datetime import datetime from enum import Enum import numpy as np import openmdao.api as om -from aviary.subsystems.atmosphere.atmosphere import Atmosphere from openmdao.components.interp_util.interp import InterpND -from aviary.utils.conversion_utils import _rep, _parse, _read_map +from aviary.interface.utils import round_it +from aviary.subsystems.atmosphere.atmosphere import Atmosphere from aviary.subsystems.propulsion.engine_deck import normalize from aviary.subsystems.propulsion.utils import EngineModelVariables, default_units -from aviary.variable_info.variables import Dynamic +from aviary.utils.conversion_utils import _parse, _read_map, _rep from aviary.utils.csv_data_file import write_data_file from aviary.utils.functions import get_path from aviary.utils.named_values import NamedValues +from aviary.variable_info.variables import Dynamic class EngineDeckType(Enum): @@ -43,36 +44,63 @@ def __str__(self): TEMPERATURE = EngineModelVariables.TEMPERATURE_T4 # EXIT_AREA = EngineModelVariables.EXIT_AREA -flops_keys = [ +_flops_keys = [ MACH, ALTITUDE, THROTTLE, GROSS_THRUST, RAM_DRAG, FUEL_FLOW, - NOX_RATE] # , EXIT_AREA] + NOX_RATE, +] # , EXIT_AREA] # later code assumes T4 is last item in keys -gasp_keys = [MACH, ALTITUDE, THROTTLE, FUEL_FLOW, TEMPERATURE] +_gasp_keys = [MACH, ALTITUDE, THROTTLE, FUEL_FLOW, TEMPERATURE] header_names = { - MACH: 'Mach_Number', + MACH: 'Mach Number', ALTITUDE: 'Altitude', THROTTLE: 'Throttle', THRUST: 'Thrust', - GROSS_THRUST: 'Gross_Thrust', - RAM_DRAG: 'Ram_Drag', - FUEL_FLOW: 'Fuel_Flow', - NOX_RATE: 'NOx_Rate', + GROSS_THRUST: 'Gross Thrust', + RAM_DRAG: 'Ram Drag', + FUEL_FLOW: 'Fuel Flow', + NOX_RATE: 'NOx Rate', TEMPERATURE: 'T4', - SHAFT_POWER_CORRECTED: 'Shaft_Power_Corrected', - TAILPIPE_THRUST: 'Tailpipe_Thrust', + SHAFT_POWER_CORRECTED: 'Shaft Power Corrected', + TAILPIPE_THRUST: 'Tailpipe Thrust', # EXIT_AREA: 'Exit Area', } +outputs = [ + 'Thrust', + 'Gross Thrust', + 'Ram Drag', + 'Fuel Flow', + 'NOx Rate', + 'T4', + 'Shaft Power Corrected', + 'Tailpipe Thrust', +] + +# number of sig figs to round each header to, if requested +sig_figs = { + MACH: 4, + ALTITUDE: 7, + THROTTLE: 4, + THRUST: 7, + GROSS_THRUST: 7, + RAM_DRAG: 6, + FUEL_FLOW: 6, + NOX_RATE: 5, + TEMPERATURE: 6, + SHAFT_POWER_CORRECTED: 6, + TAILPIPE_THRUST: 6, +} + -def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): - ''' +def convert_engine_deck(input_file, output_file, data_format: EngineDeckType, round_data=False): + """ Converts FLOPS- or GASP-formatted engine decks into Aviary csv format. FLOPS decks are changed from column-delimited to csv format with added headers. GASP decks are reorganized into csv. T4 is recovered using assumptions used in GASPy. @@ -86,30 +114,26 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): path to file where new converted data will be written data_format : (EngineDeckType) data format used by input_file (FLOPS or GASP) - ''' - # TODO rounding for calculated values? - - timestamp = datetime.now().strftime('%m/%d/%y at %H:%M') - user = getpass.getuser() + round_data : bool, optional + Sets if any generated data should be rounded. This primarily applies to GASP engines that + must compute T4 or require extrapolation to fill out sparse flight throttle ranges. + Defaults to False. + """ comments = [] - header = {} data = {} data_file = get_path(input_file) - comments.append(f'# created {timestamp} by {user}') legacy_code = data_format.value engine_type = 'engine' if legacy_code == 'GASP_TS': engine_type = 'turboshaft engine' legacy_code = 'GASP' - comments.append( - f'# {legacy_code}-derived {engine_type} deck converted from {data_file.name}') + comments.append(f'# {legacy_code}-derived {engine_type} deck converted from {data_file.name}') if data_format == EngineDeckType.FLOPS: - header = {key: default_units[key] for key in flops_keys} - data = {key: np.array([]) for key in flops_keys} + data = {key: np.array([]) for key in _flops_keys} with open(data_file, newline='', encoding='utf-8-sig') as file: reader = _read_flops_engine(file) @@ -133,13 +157,18 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): # data[EXIT_AREA].append(line[7]) elif data_format in (EngineDeckType.GASP, EngineDeckType.GASP_TS): + # prevent modifications to gasp_keys from overwriting base _gasp_keys, to avoid + # errors when `convert_engine_deck()` is ran multiple times in a row + gasp_keys = deepcopy(_gasp_keys) is_turbo_prop = True if data_format == EngineDeckType.GASP_TS else False temperature = gasp_keys.pop() fuelflow = gasp_keys.pop() + if is_turbo_prop: gasp_keys.extend((SHAFT_POWER_CORRECTED, TAILPIPE_THRUST)) else: gasp_keys.extend((THRUST,)) # must keep "," here + gasp_keys.extend((fuelflow, temperature)) data = {key: [] for key in gasp_keys} @@ -153,17 +182,17 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): if t4max <= 100 or throttle_type == 3: throttle_step = 2 else: - throttle_step = .05 + throttle_step = 0.5 # save scalars as comments - comments.extend(['# ' + key + ': ' + str(scalars[key]) - for key in scalars.keys()]) + comments.extend(['# ' + key + ': ' + str(scalars[key]) for key in scalars.keys()]) # recommended to always generate structured grid structure_data = True if structure_data: - structured_data = _make_structured_grid(tables, method='lagrange3', - fields=fields, throttle_step=throttle_step) + structured_data = _make_structured_grid( + tables, method='lagrange3', fields=fields, throttle_step=throttle_step + ) data[MACH] = structured_data['fuelflow']['machs'] data[ALTITUDE] = structured_data['fuelflow']['alts'] @@ -188,9 +217,12 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): generate_flight_idle = True if generate_flight_idle and not is_turbo_prop: - data, T4T2 = _generate_flight_idle(data, T4T2, - ref_sls_airflow=scalars['sls_airflow'], - ref_sfn_idle=scalars['sfn_idle']) + data, T4T2 = _generate_flight_idle( + data, + T4T2, + ref_sls_airflow=scalars['sls_airflow'], + ref_sfn_idle=scalars['sfn_idle'], + ) # if t4max 100 or less, it is actually throttle. Remove temperature as variable if t4max <= 100 or throttle_type == 3: @@ -201,47 +233,41 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): else: compute_T4 = True - # define header now that we know what is in the engine deck - header = {key: default_units[key] for key in gasp_keys} - if compute_T4: # compute T4 using atmospheric model prob = om.Problem() - prob.model.add_subsystem('T4T2', om.IndepVarComp('T4:T2', - T4T2, - units='unitless'), - promotes=['*']) + prob.model.add_subsystem( + 'T4T2', om.IndepVarComp('T4:T2', T4T2, units='unitless'), promotes=['*'] + ) prob.model.add_subsystem( - Dynamic.Mission.MACH, - om.IndepVarComp( - Dynamic.Mission.MACH, - data[MACH], - units='unitless'), - promotes=['*']) + Dynamic.Atmosphere.MACH, + om.IndepVarComp(Dynamic.Atmosphere.MACH, data[MACH], units='unitless'), + promotes=['*'], + ) prob.model.add_subsystem( Dynamic.Mission.ALTITUDE, - om.IndepVarComp( - Dynamic.Mission.ALTITUDE, - data[ALTITUDE], - units='ft'), - promotes=['*']) + om.IndepVarComp(Dynamic.Mission.ALTITUDE, data[ALTITUDE], units='ft'), + promotes=['*'], + ) prob.model.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=len(data[MACH])), promotes_inputs=[Dynamic.Mission.ALTITUDE], - promotes_outputs=[Dynamic.Mission.TEMPERATURE], + promotes_outputs=[Dynamic.Atmosphere.TEMPERATURE], ) prob.model.add_subsystem( name='conversion', subsys=AtmosCalc(num_nodes=len(data[MACH])), - promotes_inputs=[Dynamic.Mission.MACH, - Dynamic.Mission.TEMPERATURE], - promotes_outputs=['t2'] + promotes_inputs=[ + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.TEMPERATURE, + ], + promotes_outputs=['t2'], ) prob.setup() @@ -254,16 +280,20 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): # By always keeping minimum T4 zero for normalization, throttle stays # consistent with fraction of T4max # TODO flight condition dependent throttle range? - # NOTE this often leaves max throttles less than 1 in the deck - this caues - # problems when finding reference SLS thrust, as there is often no max - # power data at that point in the engine deck. It is recommended GASP - # engine decks override Aircraft.Engine.REFERENCE_THRUST in EngineDecks + # NOTE this often leaves max throttles less than 1 in the deck - this causes + # problems when finding reference SLS thrust, as there is often no max + # power data at that point in the engine deck. It is recommended GASP + # engine decks override Aircraft.Engine.REFERENCE_THRUST in EngineDecks data[THROTTLE] = normalize(data[TEMPERATURE], minimum=0.0, maximum=t4max) else: + # data[THROTTLE] = normalize( + # T4T2, minimum=scalars['t4flight_idle'], maximum=t4max + # ) data[THROTTLE] = normalize(T4T2, minimum=0.0, maximum=t4max) # TODO save these points as commented out? + # remove points above T4max valid_idx = np.where(data[THROTTLE] <= 1.0) data[MACH] = data[MACH][valid_idx] data[ALTITUDE] = data[ALTITUDE][valid_idx] @@ -277,12 +307,17 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): else: data[THRUST] = data[THRUST][valid_idx] + # round data if requested, using sig_figs as guide + if round_data: + for key in data: + data[key] = np.array([round_it(val, sig_figs[key]) for val in data[key]]) + # data needs to be string so column length can be easily found later for var in data: data[var] = np.array([str(item) for item in data[var]]) else: - quit("Invalid engine deck format provided") + quit('Invalid engine deck format provided') # sort data # create parallel dict to data that stores floats @@ -294,10 +329,9 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): sorted_values = np.array(list(formatted_data.values())).transpose() # Sort by mach, then altitude, then throttle, then hybrid throttle - sorted_values = sorted_values[np.lexsort( - [formatted_data[THROTTLE], - formatted_data[ALTITUDE], - formatted_data[MACH]])] + sorted_values = sorted_values[ + np.lexsort([formatted_data[THROTTLE], formatted_data[ALTITUDE], formatted_data[MACH]]) + ] for idx, key in enumerate(formatted_data): formatted_data[key] = sorted_values[:, idx] @@ -309,19 +343,19 @@ def EngineDeckConverter(input_file, output_file, data_format: EngineDeckType): if output_file is None: sfx = data_file.suffix - if sfx == '.deck': - ext = '_aviary.deck' + if sfx == '.csv': + ext = '_aviary.csv' else: - ext = '.deck' + ext = '.csv' output_file = data_file.stem + ext - write_data_file(output_file, write_data, comments, include_timestamp=False) + write_data_file(output_file, write_data, outputs, comments, include_timestamp=True) def _read_flops_engine(input_file): - ''' + """ Read engine data file using FLOPS standard, which is column delimited data - always assumed to be in the order defined in the FLOPS manual - ''' + always assumed to be in the order defined in the FLOPS manual. + """ for line in input_file: sz = len(line) @@ -367,16 +401,16 @@ def _read_gasp_engine(fp, is_turbo_prop=False): fuelflow, and airflow, since they may have different grids in general. Each table consists of both the independent variables and the dependent variable for the corresponding field. The table is a "tidy format" 2D array where the first three - columns are the independent varaiables (altitude, T4/T2, and Mach number) and the + columns are the independent variables (altitude, T4/T2, and Mach number) and the final column is the dependent variable (one of thrust, fuelflow, or airflow for turbofans or shaft_power_corrected, fuelflow, or tailpipe_thrust for turboshafts). """ - with open(fp, "r") as f: + with open(fp, 'r') as f: if is_turbo_prop: - table_types = ["shaft_power_corrected", "fuelflow", "tailpipe_thrust"] + table_types = ['shaft_power_corrected', 'fuelflow', 'tailpipe_thrust'] scalars = _read_tp_header(f) else: - table_types = ["thrust", "fuelflow", "airflow"] + table_types = ['thrust', 'fuelflow', 'airflow'] scalars = _read_header(f) tables = {k: _read_table(f, is_turbo_prop) for k in table_types} @@ -385,49 +419,47 @@ def _read_gasp_engine(fp, is_turbo_prop=False): def _read_tp_header(f): - """Read GASP engine deck header, returning the engine scalars in a dict""" + """Read GASP engine deck header, returning the engine scalars in a dict.""" # file header: FORMAT(2I5,10X,6F10.4) iread, iprint, t4max, t4mcl, t4mc, t4idle, xsfc, cexp = _parse( f, [*_rep(2, (int, 5)), (None, 10), *_rep(6, (float, 10))] ) - # file header: FORMAT(7F10.4) - sls_hp, xncref, prop_rpm, gbx_rat, torque_lim, waslrf = _parse( - f, [*_rep(6, (float, 10))] - ) + # file header: FORMAT(6F10.4) + sls_hp, xncref, prop_rpm, gbx_rat, torque_lim, waslrf = _parse(f, [*_rep(6, (float, 10))]) return { - "throttle_type": iread, - "t4max": t4max, - "t4cruise": t4mc, - "t4climb": t4mcl, - "t4flight_idle": t4idle, - "xsfc": xsfc, - "cexp": cexp, - "sls_horsepower": sls_hp, - "freeturbine_rpm": xncref, - "propeller_rpm": prop_rpm, - "gearbox_ratio": gbx_rat, - "torque_limit": torque_lim, - "sls_corrected_airflow": waslrf, + 'throttle_type': iread, + 't4max': t4max, + 't4cruise': t4mc, + 't4climb': t4mcl, + 't4flight_idle': t4idle, + 'xsfc': xsfc, + 'cexp': cexp, + 'sls_horsepower': sls_hp, + 'freeturbine_rpm': xncref, + 'propeller_rpm': prop_rpm, + 'gearbox_ratio': gbx_rat, + 'torque_limit': torque_lim, + 'sls_corrected_airflow': waslrf, } def _read_header(f): - """Read GASP engine deck header, returning the engine scalars in a dict""" + """Read GASP engine deck header, returning the engine scalars in a dict.""" # file header: FORMAT(2I5,10X,5F10.4) iread, iprint, wamap, t4max, t4mcl, t4mc, sfnidl = _parse( f, [*_rep(2, (int, 5)), (None, 10), *_rep(5, (float, 10))] ) if iread != 1: - raise RuntimeError(f"IREAD=1 expected, got {iread}") + raise RuntimeError(f'IREAD=1 expected, got {iread}') return { - "t4max": t4max, - "t4cruise": t4mc, - "t4climb": t4mcl, - "sls_airflow": wamap, - "sfn_idle": sfnidl, + 't4max': t4max, + 't4cruise': t4mc, + 't4climb': t4mcl, + 'sls_airflow': wamap, + 'sfn_idle': sfnidl, } @@ -440,8 +472,8 @@ def _read_table(f, is_turbo_prop=False): """ tab_data = None - # table title - title = f.readline().strip() + # strip out table title, not used + f.readline().strip() # number of maps in the table (nmaps,) = _parse(f, [(int, 5)]) # blank line @@ -462,12 +494,14 @@ def _read_table(f, is_turbo_prop=False): return tab_data -def _make_structured_grid(data, method="lagrange3", fields=["thrust", "fuelflow", "airflow"], throttle_step=.05): - """Generate a structured grid of unique mach/T4:T2/alt values in the deck""" +def _make_structured_grid( + data, method='lagrange3', fields=['thrust', 'fuelflow', 'airflow'], throttle_step=0.5 +): + """Generate a structured grid of unique mach/T4:T2/alt values in the deck.""" # step size in t4/t2 ratio used in generating the structured grid # t2t2_step = 0.5 # original value t4t2_step = throttle_step - # step size in mach number used in generating the structured grid + # step size in Mach number used in generating the structured grid # mach_step = 0.02 # original value mach_step = 0.05 @@ -479,7 +513,7 @@ def _make_structured_grid(data, method="lagrange3", fields=["thrust", "fuelflow" machs = np.arange(min(tma), max(tma) + mach_step, mach_step) # need t4t2 in first column, mach varies on each row - pts = np.dstack(np.meshgrid(t4t2s, machs, indexing="ij")).reshape(-1, 2) + pts = np.dstack(np.meshgrid(t4t2s, machs, indexing='ij')).reshape(-1, 2) npts = pts.shape[0] for field in fields: @@ -502,14 +536,14 @@ def _make_structured_grid(data, method="lagrange3", fields=["thrust", "fuelflow" # would explicitly use lagrange3 here to mimic GASP, but some engine # decks may not have enough points per dimension # For GASP engine deck, try to provide at least 4 Mach numbers. - # For GASP_TP engine deck, try to provide at least 4 Mach numbers + # For GASP_TS engine deck, try to provide at least 4 Mach numbers # avoid devide-by-zero RuntimeWarning - if len(mach) == 3 and method == "lagrange3": - method = "lagrange2" + if len(mach) == 3 and method == 'lagrange3': + method = 'lagrange2' elif len(mach) == 2: - method = "slinear" + method = 'slinear' interp = InterpND( - method="2D-" + method, points=(t4t2, mach), values=f, extrapolate=True + method='2D-' + method, points=(t4t2, mach), values=f, extrapolate=True ) sl = slice(i * npts, (i + 1) * npts) vals[sl] = interp.interpolate(pts) @@ -518,10 +552,10 @@ def _make_structured_grid(data, method="lagrange3", fields=["thrust", "fuelflow" mach_vec[sl] = pts[:, 1] structured_data[field] = { - "vals": vals, - "alts": alt_vec, - "t4t2s": t4t2_vec, - "machs": mach_vec, + 'vals': vals, + 'alts': alt_vec, + 't4t2s': t4t2_vec, + 'machs': mach_vec, } return structured_data @@ -540,54 +574,46 @@ def _generate_flight_idle(data, T4T2, ref_sls_airflow, ref_sfn_idle): prob = om.Problem() prob.model.add_subsystem( - Dynamic.Mission.MACH, - om.IndepVarComp( - Dynamic.Mission.MACH, - mach_list, - units='unitless'), - promotes=['*']) + Dynamic.Atmosphere.MACH, + om.IndepVarComp(Dynamic.Atmosphere.MACH, mach_list, units='unitless'), + promotes=['*'], + ) prob.model.add_subsystem( Dynamic.Mission.ALTITUDE, - om.IndepVarComp( - Dynamic.Mission.ALTITUDE, - alt_list, - units='ft'), - promotes=['*']) + om.IndepVarComp(Dynamic.Mission.ALTITUDE, alt_list, units='ft'), + promotes=['*'], + ) prob.model.add_subsystem( name='atmosphere', subsys=Atmosphere(num_nodes=nn), promotes_inputs=[Dynamic.Mission.ALTITUDE], - promotes_outputs=[Dynamic.Mission.TEMPERATURE, Dynamic.Mission.STATIC_PRESSURE], + promotes_outputs=[ + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + ], ) prob.model.add_subsystem( name='conversion', - subsys=AtmosCalc( - num_nodes=nn), + subsys=AtmosCalc(num_nodes=nn), promotes_inputs=[ - Dynamic.Mission.MACH, - Dynamic.Mission.TEMPERATURE, - Dynamic.Mission.STATIC_PRESSURE], - promotes_outputs=[ - 't2', - 'p2']) + Dynamic.Atmosphere.MACH, + Dynamic.Atmosphere.TEMPERATURE, + Dynamic.Atmosphere.STATIC_PRESSURE, + ], + promotes_outputs=['t2', 'p2'], + ) prob.model.add_subsystem( name='flight_idle', subsys=CalculateIdle( - num_nodes=nn, - ref_sfn_idle=ref_sfn_idle, - ref_sls_airflow=ref_sls_airflow), - promotes_inputs=[ - 't2', - 'p2', - 'pct_corr_airflow_idle', - 'sfc_idle'], - promotes_outputs=[ - 'idle_thrust', - 'idle_fuelflow']) + num_nodes=nn, ref_sfn_idle=ref_sfn_idle, ref_sls_airflow=ref_sls_airflow + ), + promotes_inputs=['t2', 'p2', 'pct_corr_airflow_idle', 'sfc_idle'], + promotes_outputs=['idle_thrust', 'idle_fuelflow'], + ) prob.setup() @@ -610,47 +636,39 @@ def _generate_flight_idle(data, T4T2, ref_sls_airflow, ref_sfn_idle): class CalculateIdle(om.ExplicitComponent): - ''' + """ Calculates idle conditions of a GASP engine at a specified flight condition - Vectorized to calculate values for entire flight regime - ''' + Vectorized to calculate values for entire flight regime. + """ def initialize(self): self.options.declare('num_nodes', types=int) self.options.declare( - 'ref_sfn_idle', - 1.0, - desc='Idle thrust-specific fuel consumption, from engine deck') + 'ref_sfn_idle', 1.0, desc='Idle thrust-specific fuel consumption, from engine deck' + ) self.options.declare( - 'ref_sls_airflow', - 1.0, - desc='Sea-level static airflow of the reference engine') + 'ref_sls_airflow', 1.0, desc='Sea-level static airflow of the reference engine' + ) def setup(self): - nn = self.options["num_nodes"] + nn = self.options['num_nodes'] + self.add_input('t2', _TSLS_DEGR, units='degR', shape=nn, desc='Engine inlet temperature') + self.add_input('p2', _PSLS_PSF, units='psf', shape=nn, desc='Engine inlet pressure') + self.add_input('pct_corr_airflow_idle', 0.5, desc='Percent corrected airflow at idle') self.add_input( - "t2", _TSLS_DEGR, units="degR", shape=nn, desc="Engine inlet temperature" - ) - self.add_input( - "p2", _PSLS_PSF, units="psf", shape=nn, desc="Engine inlet pressure" - ) - self.add_input( - "pct_corr_airflow_idle", 0.5, desc="Percent corrected airflow at idle" - ) - self.add_input( - "sfc_idle", + 'sfc_idle', 1.0, - units="lbm/h/lbf", - desc="Thrust-specific fuel consumption at idle", + units='lbm/h/lbf', + desc='Thrust-specific fuel consumption at idle', ) - self.add_output("idle_thrust", units="lbf", shape=nn, desc="Idle thrust") + self.add_output('idle_thrust', units='lbf', shape=nn, desc='Idle thrust') # self.add_output( # "idle_airflow", units="lbf/s", shape=nn, desc="Idle corrected airflow" # ) - self.add_output("idle_fuelflow", units="lbm/h", shape=nn, desc="Idle fuel flow") + self.add_output('idle_fuelflow', units='lbm/h', shape=nn, desc='Idle fuel flow') def compute(self, inputs, outputs): ( @@ -670,38 +688,41 @@ def compute(self, inputs, outputs): thrust_ref = airflow_ref * delta2 / rthet2 * ref_sfn_idle fuelflow_ref = thrust_ref * sfc_idle - outputs["idle_thrust"] = thrust_ref + outputs['idle_thrust'] = thrust_ref # outputs["idle_airflow"] = airflow_ref - outputs["idle_fuelflow"] = fuelflow_ref + outputs['idle_fuelflow'] = fuelflow_ref class AtmosCalc(om.ExplicitComponent): - ''' - Calculates T2 and P2 given static temperature and pressure - ''' + """Calculates T2 and P2 given static temperature and pressure.""" def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): nn = self.options['num_nodes'] - self.add_input(Dynamic.Mission.MACH, val=np.zeros(nn), - desc='current Mach number', units='unitless') - self.add_input(Dynamic.Mission.TEMPERATURE, val=np.zeros(nn), - desc='current atmospheric temperature', units='degR') self.add_input( - Dynamic.Mission.STATIC_PRESSURE, + Dynamic.Atmosphere.MACH, + val=np.zeros(nn), + desc='current Mach number', + units='unitless', + ) + self.add_input( + Dynamic.Atmosphere.TEMPERATURE, + val=np.zeros(nn), + desc='current atmospheric temperature', + units='degR', + ) + self.add_input( + Dynamic.Atmosphere.STATIC_PRESSURE, _PSLS_PSF, - units="psf", + units='psf', shape=nn, - desc="Ambient static pressure") + desc='Ambient static pressure', + ) - self.add_output( - "t2", - units="degR", - shape=nn, - desc="Engine inlet total temperature") - self.add_output("p2", units="psf", shape=nn, desc="Engine inlet total pressure") + self.add_output('t2', units='degR', shape=nn, desc='Engine inlet total temperature') + self.add_output('p2', units='psf', shape=nn, desc='Engine inlet total pressure') def compute(self, inputs, outputs): mach, T, P = inputs.values() @@ -710,37 +731,39 @@ def compute(self, inputs, outputs): t2 = T * (1 + 0.5 * (gamma - 1) * mach**2) p2 = P * (t2 / T) ** (gamma / (gamma - 1)) - outputs["t2"] = t2 - outputs["p2"] = p2 + outputs['t2'] = t2 + outputs['p2'] = p2 def _setup_EDC_parser(parser): - parser.add_argument('input_file', type=str, - help='path to engine deck file to be converted') - parser.add_argument('output_file', type=str, nargs='?', - help='path to file where new converted data will be written') - parser.add_argument('-f', '--data_format', type=EngineDeckType, choices=list(EngineDeckType), - help='data format used by input_file') + parser.add_argument('input_file', type=str, help='path to engine deck file to be converted') + parser.add_argument( + 'output_file', + type=str, + nargs='?', + help='path to file where new converted data will be written', + ) + parser.add_argument( + '-f', + '--data_format', + type=EngineDeckType, + choices=list(EngineDeckType), + help='data format used by input_file', + ) + parser.add_argument('--round', action='store_true', help='round data to improve readability') def _exec_EDC(args, user_args): - EngineDeckConverter( + convert_engine_deck( input_file=args.input_file, output_file=args.output_file, - data_format=args.data_format + data_format=args.data_format, + round_data=args.round, ) -EDC_description = 'Converts FLOPS- or GASP-formatted ' \ - 'engine decks into Aviary csv format.\nFLOPS decks ' \ - 'are changed from column-delimited to csv format ' \ - 'with added headers.\nGASP decks are reorganized ' \ - 'into column based csv. T4 is recovered through ' \ - 'calculation. Data points whose T4 exceeds T4max ' \ - 'are removed.' - if __name__ == '__main__': - parser = argparse.ArgumentParser(EDC_description) + parser = argparse.ArgumentParser() _setup_EDC_parser(parser) args = parser.parse_args() _exec_EDC(args, None) diff --git a/aviary/utils/fortran_to_aviary.py b/aviary/utils/fortran_to_aviary.py index 11fdcc240f..f4eab22486 100644 --- a/aviary/utils/fortran_to_aviary.py +++ b/aviary/utils/fortran_to_aviary.py @@ -1,5 +1,5 @@ """ -Fortran_to_Aviary.py is used to read in Fortran based vehicle decks and convert them to Aviary decks. +fortran_to_aviary.py is used to read in Fortran based vehicle decks and convert them to Aviary decks. FLOPS, GASP, or Aviary names can be used for variables (Ex WG or Mission:Design:GROSS_MASS) When specifying variables from FORTRAN, they should be in the appropriate NAMELIST. @@ -17,44 +17,52 @@ """ import csv -import re import getpass - +import re from datetime import datetime from pathlib import Path + from openmdao.utils.units import valid_units -from aviary.utils.functions import convert_strings_to_data -from aviary.utils.named_values import NamedValues, get_items +from aviary.utils.functions import convert_strings_to_data, get_path +from aviary.utils.legacy_code_data.flops_defaults import flops_default_values, flops_deprecated_vars +from aviary.utils.legacy_code_data.gasp_defaults import gasp_default_values, gasp_deprecated_vars +from aviary.utils.named_values import NamedValues +from aviary.variable_info.enums import LegacyCode, Verbosity from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Mission, Settings -from aviary.variable_info.enums import LegacyCode, Verbosity, ProblemType -from aviary.utils.functions import get_path -from aviary.utils.legacy_code_data.deprecated_vars import flops_deprecated_vars, gasp_deprecated_vars FLOPS = LegacyCode.FLOPS GASP = LegacyCode.GASP -def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, - out_file=None, force=False, verbosity=Verbosity.BRIEF): - ''' +def fortran_to_aviary( + fortran_deck: str, + legacy_code=None, + out_file=None, + force=False, + verbosity=Verbosity.BRIEF, +): + """ Create an Aviary CSV file from a Fortran input deck Required input is the filepath to the input deck and legacy code. Optionally, a deck of default values can be specified, this is useful if an input deck assumes certain values for any unspecified variables If an invalid filepath is given, pre-packaged resources will be checked for input decks with a matching name. - ''' + """ # compatibility with being passed int for verbosity verbosity = Verbosity(verbosity) # TODO generate both an Aviary input file and a phase_info file - vehicle_data = {'input_values': NamedValues(), 'unused_values': NamedValues(), - 'initialization_guesses': initialization_guesses, 'verbosity': verbosity} + vehicle_data = { + 'input_values': NamedValues(), + 'unused_values': NamedValues(), + 'initialization_guesses': initialization_guesses, + } - fortran_deck: Path = get_path(fortran_deck, verbose=False) + fortran_deck: Path = get_path(fortran_deck, verbosity=verbosity) timestamp = datetime.now().strftime('%m/%d/%y at %H:%M') user = getpass.getuser() @@ -62,8 +70,7 @@ def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, comments.append(f'# created {timestamp} by {user}') comments.append( - f'# {legacy_code.value}-derived aircraft input deck converted from ' - f'{fortran_deck.name}' + f'# {legacy_code.value}-derived aircraft input deck converted from {fortran_deck.name}' ) if out_file: @@ -72,40 +79,71 @@ def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, name = fortran_deck.stem out_file: Path = fortran_deck.parent.resolve().joinpath(name + '_converted.csv') + # create dictionary to convert legacy code variables to Aviary variables + # key: variable name, value: either None or relevant historical_name + aviary_variable_dict = generate_aviary_names(legacy_code.value) + + # Get legacy-code based depreciated variable list and set vehicle data to defaults if legacy_code is GASP: - default_extension = '.dat' + default_values = gasp_default_values deprecated_vars = gasp_deprecated_vars elif legacy_code is FLOPS: - default_extension = '.txt' + default_values = flops_default_values deprecated_vars = flops_deprecated_vars - if not defaults_deck: - defaults_filename = legacy_code.value.lower() + '_default_values' + default_extension - defaults_deck = Path(__file__).parent.resolve().joinpath( - 'legacy_code_data', defaults_filename) - - # create dictionary to convert legacy code variables to Aviary variables - # key: variable name, value: either None or relevant historical_name - aviary_variable_dict = generate_aviary_names([legacy_code.value]) - - if defaults_deck: # If defaults are specified, initialize the vehicle with them - vehicle_data = input_parser(defaults_deck, vehicle_data, - aviary_variable_dict, deprecated_vars, legacy_code) + # Convert default data to Aviary names, add to vehicle_data + for item in default_values: + name = item[0].split('.') + val = str(item[1][0]) + vehicle_data = process_and_store_data( + data=val, + var_name=name[1], + legacy_code=legacy_code, + current_namelist=name[0], + alternate_names=aviary_variable_dict, + default_values=default_values, + vehicle_data=vehicle_data, + unused_vars=deprecated_vars, + verbosity=verbosity, + ) + + # read in and convert input file + vehicle_data = parse_input_file( + fortran_deck, + vehicle_data, + aviary_variable_dict, + default_values, + deprecated_vars, + legacy_code, + verbosity, + ) - vehicle_data = input_parser(fortran_deck, vehicle_data, - aviary_variable_dict, deprecated_vars, legacy_code) + # Postprocessing step to handle special cases for conversion (not 1-to-1 match), + # per legacy code. if legacy_code is GASP: - vehicle_data = update_gasp_options(vehicle_data) + vehicle_data = update_gasp_options(vehicle_data, verbosity) elif legacy_code is FLOPS: vehicle_data = update_flops_options(vehicle_data) + vehicle_data = update_aviary_options(vehicle_data) - if not out_file.is_file(): # default outputted file to be in same directory as input + # Add settings and engine data file + if legacy_code is FLOPS: + eom = ['height_energy'] + aero = mass = ['FLOPS'] + if legacy_code is GASP: + eom = ['2DOF'] + aero = mass = ['GASP'] + vehicle_data['input_values'].set_val(Settings.EQUATIONS_OF_MOTION, eom) + vehicle_data['input_values'].set_val(Settings.MASS_METHOD, mass) + vehicle_data['input_values'].set_val(Settings.AERODYNAMICS_METHOD, aero) + + if not out_file.is_file(): + # default outputted file to be in same directory as input out_file = fortran_deck.parent / out_file if out_file.is_file(): if not force: - raise RuntimeError(f'{out_file} already exists. Choose a new name or enable ' - '--force') + raise RuntimeError(f'{out_file} already exists. Choose a new name or enable --force') elif verbosity >= Verbosity.BRIEF: print(f'Overwriting existing file: {out_file.name}') @@ -129,16 +167,6 @@ def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, for var, (val, units) in sorted(vehicle_data['input_values']): writer.writerow([var] + val + [units]) - # TODO these should just get directly added to vehicle_data - if legacy_code is FLOPS: - EOM = 'height_energy' - mass = 'FLOPS' - if legacy_code is GASP: - EOM = '2DOF' - mass = 'GASP' - writer.writerow(['settings:equations_of_motion'] + [EOM]) - writer.writerow(['settings:mass_method'] + [mass]) - if legacy_code is GASP: # Values used in initial guessing of the trajectory writer.writerow([]) @@ -154,14 +182,22 @@ def create_aviary_deck(fortran_deck: str, legacy_code=None, defaults_deck=None, writer.writerow([var] + val) -def input_parser(fortran_deck, vehicle_data, alternate_names, unused_vars, legacy_code): - ''' - input_parser will modify the values in the vehicle_data dictionary using the data in the - fortran_deck. +def parse_input_file( + fortran_deck, + vehicle_data, + alternate_names, + default_values, + unused_vars, + legacy_code, + verbosity=Verbosity.BRIEF, +): + """ + parse_input_file reads the data in fortran_deck and adds it to vehicle_data. + Lines are read one by one, comments are removed, and namelists are tracked. - Lines with multiple variable-data pairs are supported, but the last value per variable must - be followed by a trailing comma. - ''' + Lines with multiple variable-data pairs are supported, but the last value per + variable must be followed by a trailing comma. + """ with open(fortran_deck, 'r') as f_in: current_namelist = current_tag = '' for line in f_in: @@ -178,7 +214,7 @@ def input_parser(fortran_deck, vehicle_data, alternate_names, unused_vars, legac # Track when namelists are opened and closed if (line.lstrip()[0] in ['$', '&']) and current_tag == '': current_tag = line.lstrip()[0] - current_namelist = line.split(current_tag)[1].split()[0] + '.' + current_namelist = line.split(current_tag)[1].split()[0] elif (line.lstrip()[0] == current_tag) or (line.rstrip()[-1] == '/'): line = line.replace('/', '') terminate_namelist = True @@ -191,12 +227,24 @@ def input_parser(fortran_deck, vehicle_data, alternate_names, unused_vars, legac data = line.split('=')[1] try: vehicle_data = process_and_store_data( - data, var_name, legacy_code, current_namelist, alternate_names, vehicle_data, unused_vars, comment) + data, + var_name, + legacy_code, + current_namelist, + alternate_names, + default_values, + vehicle_data, + unused_vars, + comment, + verbosity, + ) except Exception as err: if current_namelist == '': - raise RuntimeError(line + ' could not be parsed successfully.' - '\nIf this was intended as a comment, ' - 'add an "!" at the beginning of the line.') from err + raise RuntimeError( + line + ' could not be parsed successfully.' + '\nIf this was intended as a comment, ' + 'add an "!" at the beginning of the line.' + ) from err else: raise err elif number_of_variables > 1: @@ -205,24 +253,38 @@ def input_parser(fortran_deck, vehicle_data, alternate_names, unused_vars, legac for ii in range(number_of_variables): # Each of the following elements contains all of the data for the current variable # and the last element is the name of the next variable - sub_list = sub_line[ii+1].split(',') - if ii+1 < number_of_variables: + sub_list = sub_line[ii + 1].split(',') + if ii + 1 < number_of_variables: next_var_name = sub_list.pop() if not next_var_name[0].isalpha(): - index = next((i for i, c in enumerate( - next_var_name) if c.isalpha()), len(next_var_name)) + index = next( + (i for i, c in enumerate(next_var_name) if c.isalpha()), + len(next_var_name), + ) sub_list.append(next_var_name[:index]) next_var_name = next_var_name[index:] data = ','.join(sub_list) try: vehicle_data = process_and_store_data( - data, var_name, legacy_code, current_namelist, alternate_names, vehicle_data, unused_vars, comment) + data, + var_name, + legacy_code, + current_namelist, + alternate_names, + default_values, + vehicle_data, + unused_vars, + comment, + verbosity, + ) except Exception as err: if current_namelist == '': - raise RuntimeError(line + ' could not be parsed successfully.' - '\nIf this was intended as a comment, ' - 'add an "!" at the beginning of the line.') from err + raise RuntimeError( + line + ' could not be parsed successfully.' + '\nIf this was intended as a comment, ' + 'add an "!" at the beginning of the line.' + ) from err else: raise err var_name = next_var_name @@ -233,26 +295,37 @@ def input_parser(fortran_deck, vehicle_data, alternate_names, unused_vars, legac return vehicle_data -def process_and_store_data(data, var_name, legacy_code, current_namelist, alternate_names, vehicle_data, unused_vars, comment=''): - ''' +def process_and_store_data( + data, + var_name, + legacy_code, + current_namelist, + alternate_names, + default_values, + vehicle_data, + unused_vars, + comment='', + verbosity=Verbosity.BRIEF, +): + """ process_and_store_data takes in a string that contains the data, the current variable's name and namelist, the dictionary of alternate names, and the current vehicle data. It will convert the string of data into a list, get units, check whether the data specified is part of a list or a single element, and update the current name to it's equivalent Aviary name. - The variables are also sorted based on whether they will set an Aviary variable or they are for initial guessing - ''' - + The variables are also sorted based on whether they will set an Aviary variable or they are for initial guessing. + """ guess_names = list(initialization_guesses.keys()) var_ind = data_units = None skip_variable = False # skip any variables that shouldn't get converted - if re.search(current_namelist + var_name + '\\Z', str(unused_vars), re.IGNORECASE): + if re.search(current_namelist + '.' + var_name, str(unused_vars), re.IGNORECASE): return vehicle_data # remove any elements that are empty (caused by trailing commas or extra commas) data_list = [dat for dat in data.split(',') if dat != ''] if len(data_list) > 0: if valid_units(data_list[-1]): - # if the last element is a unit, remove it from the list and update the variable's units + # if the last element is a unit, remove it from the list and update the + # variable's units data_units = data_list.pop() var_values = convert_strings_to_data(data_list) else: @@ -260,7 +333,8 @@ def process_and_store_data(data, var_name, legacy_code, current_namelist, altern var_values = [] list_of_equivalent_aviary_names, var_ind = update_name( - alternate_names, current_namelist+var_name, vehicle_data['verbosity']) + alternate_names, current_namelist + '.' + var_name, verbosity + ) # Fortran uses 1 indexing, Python uses 0 indexing fortran_offset = 1 if current_namelist else 0 @@ -268,10 +342,15 @@ def process_and_store_data(data, var_name, legacy_code, current_namelist, altern var_ind -= fortran_offset # Aviary has a reduction gearbox which is 1/gear ratio of GASP gearbox - if current_namelist+var_name == 'INPROP.GR': - var_values = [1/var for var in var_values] - vehicle_data['input_values'] = set_value(Aircraft.Engine.Gearbox.GEAR_RATIO, var_values, - vehicle_data['input_values'], var_id=var_ind, units=data_units) + if current_namelist + '.' + var_name == 'INPROP.GR': + var_values = [1 / var for var in var_values] + vehicle_data['input_values'] = set_value( + Aircraft.Engine.Gearbox.GEAR_RATIO, + var_values, + vehicle_data['input_values'], + var_ind=var_ind, + units=data_units, + ) for name in list_of_equivalent_aviary_names: if not skip_variable: @@ -281,84 +360,92 @@ def process_and_store_data(data, var_name, legacy_code, current_namelist, altern continue elif name in _MetaData: - vehicle_data['input_values'] = set_value(name, var_values, vehicle_data['input_values'], - var_ind=var_ind, units=data_units) + if current_namelist + '.' + var_name in default_values: + data_units = default_values.get_item(current_namelist + '.' + var_name)[1] + else: + data_units = None + vehicle_data['input_values'] = set_value( + name, + var_values, + data_units, + vehicle_data['input_values'], + var_ind=var_ind, + ) continue - vehicle_data['unused_values'] = set_value(name, var_values, vehicle_data['unused_values'], - var_ind=var_ind, units=data_units) - if vehicle_data['verbosity'].value >= Verbosity.VERBOSE: + vehicle_data['unused_values'] = set_value( + name, + var_values, + data_units, + vehicle_data['unused_values'], + var_ind=var_ind, + ) + if verbosity >= Verbosity.VERBOSE: print('Unused:', name, var_values, comment) return vehicle_data -def set_value(var_name, var_value, value_dict: NamedValues, var_ind=None, units=None): - ''' +def set_value(var_name, var_value, units=None, value_dict: NamedValues = None, var_ind=None): + """ set_value will update the current value of a variable in a value dictionary that contains a value and it's associated units. If units are specified for the new value, they will be used, otherwise the current units in the value dictionary or the default units from _MetaData are used. If the new variable is part of a list, the current list will be extended if needed. - ''' - + """ if var_name in value_dict: current_value, units = value_dict.get_item(var_name) else: current_value = None if var_name in _MetaData: - units = _MetaData[var_name]['units'] - else: - units = 'unitless' + if not units: + units = _MetaData[var_name]['units'] if not units: units = 'unitless' - if var_ind != None: + if var_ind is not None: # if an index is specified, use it, otherwise store the input as the whole value if isinstance(current_value, list): max_ind = len(current_value) - 1 if var_ind > max_ind: - current_value.extend((var_ind-max_ind)*[0]) + current_value.extend((var_ind - max_ind) * [0]) else: - current_value = [current_value]+[0]*var_ind + current_value = [current_value] + [0] * var_ind current_value[var_ind] = var_value[0] value_dict.set_val(var_name, current_value, units) else: - if current_value != None and isinstance(current_value[0], bool): - # if a variable is defined as boolean but is read in as number, set as boolean + if current_value is not None and isinstance(current_value[0], bool): + # if a variable is defined as boolean but is read in as number, set as + # boolean if var_value[0] == 1: var_value = ['True'] elif var_value[0] == 0: var_value = ['False'] else: - ValueError(f"{var_name} allows 0 and 1 only, but it is {var_value[0]}") + ValueError(f'{var_name} allows 0 and 1 only, but it is {var_value[0]}') value_dict.set_val(var_name, var_value, units) return value_dict -def generate_aviary_names(code_bases): - ''' - Create a dictionary for each of the specified Fortran code bases to map to the Aviary - variable names. Each dictionary of Aviary names will have a list of Fortran names for - each variable - ''' - +def generate_aviary_names(legacy_code): + """ + Create a dictionary that maps the specified Fortran code to Aviary variable names. + Each Aviary variable will have a list of matching Fortran names. + """ alternate_names = {} - for code_base in code_bases: - alternate_names[code_base] = {} - for key in _MetaData.keys(): - historical_dict = _MetaData[key]['historical_name'] - if historical_dict and code_base in historical_dict: - alt_name = _MetaData[key]['historical_name'][code_base] - if isinstance(alt_name, str): - alt_name = [alt_name] - alternate_names[code_base][key] = alt_name + for key in _MetaData.keys(): + historical_dict = _MetaData[key]['historical_name'] + if historical_dict and legacy_code in historical_dict: + alt_name = _MetaData[key]['historical_name'][legacy_code] + if isinstance(alt_name, str): + alt_name = [alt_name] + alternate_names[key] = alt_name return alternate_names def update_name(alternate_names, var_name, verbosity=Verbosity.BRIEF): - '''update_name will convert a Fortran name to a list of equivalent Aviary names.''' - + """update_name will convert a Fortran name to a list of equivalent Aviary names.""" if '(' in var_name: # some GASP lists are given as individual elements # get the target index var_ind = int(var_name.split('(')[1].split(')')[0]) @@ -367,20 +454,17 @@ def update_name(alternate_names, var_name, verbosity=Verbosity.BRIEF): var_ind = None all_equivalent_names = [] - for code_base in alternate_names.keys(): - for key, list_of_names in alternate_names[code_base].items(): - if list_of_names is not None: - for altname in list_of_names: - altname = altname.lower() - if altname.endswith(var_name.lower()): - all_equivalent_names.append(key) - continue - elif var_ind is not None and altname.endswith( - f'{var_name.lower()}({var_ind})' - ): - all_equivalent_names.append(key) - var_ind = None - continue + for key, list_of_names in alternate_names.items(): + if list_of_names is not None: + for altname in list_of_names: + altname = altname.lower() + if altname.endswith(var_name.lower()): + all_equivalent_names.append(key) + continue + elif var_ind is not None and altname.endswith(f'{var_name.lower()}({var_ind})'): + all_equivalent_names.append(key) + var_ind = None + continue # if there are no equivalent variable names, return the original name if len(all_equivalent_names) == 0: @@ -391,20 +475,32 @@ def update_name(alternate_names, var_name, verbosity=Verbosity.BRIEF): return all_equivalent_names, var_ind -def update_gasp_options(vehicle_data): - """ - Handles variables that are affected by the values of others - """ +def update_gasp_options(vehicle_data, verbosity=Verbosity.BRIEF): + """Handles variables that are affected by the values of others.""" input_values: NamedValues = vehicle_data['input_values'] for var_name in gasp_scaler_variables: update_gasp_scaler_variables(var_name, input_values) - flap_types = ["plain", "split", "single_slotted", "double_slotted", - "triple_slotted", "fowler", "double_slotted_fowler"] + flap_types = [ + 'plain', + 'split', + 'single_slotted', + 'double_slotted', + 'triple_slotted', + 'fowler', + 'double_slotted_fowler', + ] + + design_type, design_units = input_values.get_item(Aircraft.Design.TYPE) + if design_type[0] == 0: + input_values.set_val(Aircraft.Design.TYPE, ['transport'], design_units) + elif design_type[0] == 1: + input_values.set_val(Aircraft.Design.TYPE, ['BWB'], design_units) ## PROBLEM TYPE ## - # if multiple values of target_range are specified, use the one that corresponds to the problem_type + # if multiple values of target_range are specified, use the one that + # corresponds to the problem_type design_range, distance_units = input_values.get_item(Mission.Design.RANGE) try: problem_type = input_values.get_val(Settings.PROBLEM_TYPE)[0] @@ -428,6 +524,77 @@ def update_gasp_options(vehicle_data): input_values.set_val(Settings.PROBLEM_TYPE, ['fallout']) input_values.set_val(Mission.Design.RANGE, [design_range], distance_units) + ## Passengers ## + if Aircraft.CrewPayload.Design.NUM_PASSENGERS in input_values: + num_passengers = input_values.get_val( + Aircraft.CrewPayload.Design.NUM_PASSENGERS, 'unitless' + )[0] + num_passengers = int(num_passengers) + input_values.set_val( + Aircraft.CrewPayload.Design.NUM_PASSENGERS, [num_passengers], 'unitless' + ) + + if Aircraft.CrewPayload.Design.NUM_FIRST_CLASS in input_values: + # In GASP, percentage of total number of passengers is given. + # Convert it to the actual first class passengers. + pct_first_class = input_values.get_val( + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 'unitless' + )[0] + num_first_class = int(pct_first_class * num_passengers) + input_values.set_val( + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, [num_first_class], 'unitless' + ) + num_tourist_class = num_passengers - num_first_class + input_values.set_val( + Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, [num_tourist_class], 'unitless' + ) + + ## Seats ## + if Aircraft.Fuselage.NUM_AISLES in input_values: + num_aisles = input_values.get_val(Aircraft.Fuselage.NUM_AISLES, 'unitless')[0] + num_aisles = int(num_aisles) + input_values.set_val(Aircraft.Fuselage.NUM_AISLES, [num_aisles], 'unitless') + num_seat_abreast_tourist = input_values.get_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, 'unitless' + )[0] + num_seat_abreast_tourist = int(num_seat_abreast_tourist) + input_values.set_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, [num_seat_abreast_tourist] + ) + try: + num_seat_abreast_first = int( + input_values.get_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST, 'unitless' + )[0] + ) + input_values.set_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST, [num_seat_abreast_first] + ) + except: + pass + try: + num_seat_abreast_business = int( + input_values.get_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS, 'unitless' + )[0] + ) + input_values.set_val( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS, [num_seat_abreast_business] + ) + except: + pass + + ## Cargo ## + if ( + Aircraft.CrewPayload.CARGO_MASS in input_values + and Aircraft.CrewPayload.Design.MAX_CARGO_MASS not in input_values + ): + # user has set cargo only: assume intention to set max only for backwards compatibility. + cargo, units = input_values.get_item(Aircraft.CrewPayload.Design.CARGO_MASS) + input_values.set_val(Aircraft.CrewPayload.Design.MAX_CARGO_MASS, cargo, units) + input_values.set_val(Aircraft.CrewPayload.CARGO_MASS, 0, units) + input_values.set_val(Aircraft.CrewPayload.Design.CARGO_MASS, 0, units) + ## STRUT AND FOLD ## strut_loc = input_values.get_val(Aircraft.Strut.ATTACHMENT_LOCATION, 'ft')[0] folded_span = input_values.get_val(Aircraft.Wing.FOLDED_SPAN, 'ft')[0] @@ -440,6 +607,10 @@ def update_gasp_options(vehicle_data): input_values.set_val(Aircraft.Wing.HAS_FOLD, [False], 'unitless') else: input_values.set_val(Aircraft.Wing.HAS_FOLD, [True], 'unitless') + if strut_loc > 0: + input_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, [False], 'unitless') + elif strut_loc == 0: + input_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, [True], 'unitless') if strut_loc < 0: input_values.set_val(Aircraft.Wing.HAS_FOLD, [True], 'unitless') @@ -447,61 +618,93 @@ def update_gasp_options(vehicle_data): strut_loc = abs(strut_loc) if strut_loc < 1: - input_values.set_val(Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, - [strut_loc], 'unitless') - input_values.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, [ - False], 'unitless') + input_values.set_val( + Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, [strut_loc], 'unitless' + ) + input_values.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, [False], 'unitless') else: input_values.set_val(Aircraft.Strut.ATTACHMENT_LOCATION, [strut_loc], 'ft') - input_values.set_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, [True], 'unitless') + input_values.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, [True], 'unitless') if input_values.get_val(Aircraft.Wing.HAS_FOLD)[0]: if not input_values.get_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION)[0]: - input_values.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - [True], 'unitless') + input_values.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, [True], 'unitless' + ) else: if input_values.get_val(Aircraft.Wing.FOLDED_SPAN, 'ft')[0] > 1: - input_values.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - [True], 'unitless') + input_values.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, + [True], + 'unitless', + ) else: - input_values.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - [False], 'unitless') + input_values.set_val( + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, + [False], + 'unitless', + ) else: input_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, [True], 'unitless') - input_values.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, [ - False], 'unitless') + input_values.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, [False], 'unitless') ## FLAPS ## flap_type = input_values.get_val(Aircraft.Wing.FLAP_TYPE)[0] if not isinstance(flap_type, str): - flap_type = flap_types[flap_type-1] + flap_type = flap_types[flap_type - 1] input_values.set_val(Aircraft.Wing.FLAP_TYPE, [flap_type]) flap_ind = flap_types.index(flap_type) if input_values.get_val(Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT)[0] <= 0: - input_values.set_val(Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, - [[0.62, 1.0, 0.733, 1.2, 1.32, 0.633, 0.678][flap_ind]]) + input_values.set_val( + Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, + [[0.62, 1.0, 0.733, 1.2, 1.32, 0.633, 0.678][flap_ind]], + ) if input_values.get_val(Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, 'deg')[0] == 0: - input_values.set_val(Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, - [[60, 60, 40, 55, 55, 30, 30][flap_ind]], 'deg') + input_values.set_val( + Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, + [[60, 60, 40, 55, 55, 30, 30][flap_ind]], + 'deg', + ) if input_values.get_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM)[0] == 0: - input_values.set_val(Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, - [[.9, .8, 1.18, 1.4, 1.6, 1.67, 2.25][flap_ind]]) + input_values.set_val( + Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, + [[0.9, 0.8, 1.18, 1.4, 1.6, 1.67, 2.25][flap_ind]], + ) if input_values.get_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM)[0] == 0: - input_values.set_val(Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, - [[.12, .23, .13, .23, .23, .1, .15][flap_ind]]) - - res = input_values.get_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm')[0] - if res <= 0: + input_values.set_val( + Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, + [[0.12, 0.23, 0.13, 0.23, 0.23, 0.1, 0.15][flap_ind]], + ) + if Aircraft.Wing.NUM_FLAP_SEGMENTS in input_values: + num_flap_segments = input_values.get_val(Aircraft.Wing.NUM_FLAP_SEGMENTS, 'unitless')[0] + num_flap_segments = int(num_flap_segments) + input_values.set_val(Aircraft.Wing.NUM_FLAP_SEGMENTS, [num_flap_segments], 'unitless') + + ## Fuel ## + reserve_fuel_additional = input_values.get_val( + Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm' + )[0] + if reserve_fuel_additional <= 0: input_values.set_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, [0], units='lbm') - input_values.set_val(Aircraft.Design.RESERVE_FUEL_FRACTION, - [-res], units='unitless') - elif res >= 10: - input_values.set_val(Aircraft.Design.RESERVE_FUEL_FRACTION, - [0], units='unitless') + input_values.set_val( + Aircraft.Design.RESERVE_FUEL_FRACTION, + [-reserve_fuel_additional], + units='unitless', + ) + elif reserve_fuel_additional >= 10: + input_values.set_val(Aircraft.Design.RESERVE_FUEL_FRACTION, [0], units='unitless') else: ValueError('"FRESF" is not valid between 0 and 10.') + if Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR in input_values: + if input_values.get_val(Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR)[0] > 4: + if verbosity > Verbosity.BRIEF: + print( + 'When XLFMX > 4, it is landing flare initiation height (ft), ' + 'not landing flare load factor.' + ) + input_values.delete(Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR) + # if the value is negative, we are asking the code to calculate it # if it is positive, then we are going to use it as an override if input_values.get_val(Aircraft.Wing.FORM_FACTOR)[0] < 0: @@ -514,47 +717,219 @@ def update_gasp_options(vehicle_data): input_values.delete(Aircraft.Fuselage.FORM_FACTOR) if input_values.get_val(Aircraft.Nacelle.FORM_FACTOR)[0] < 0: input_values.delete(Aircraft.Nacelle.FORM_FACTOR) - if input_values.get_val(Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR)[0] < 0: - input_values.delete(Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR) + if Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR in input_values: + if input_values.get_val(Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR)[0] < 0: + input_values.delete(Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR) + + # GASP-converted engine decks have uneven throttle ranges, which require the enabling + # of global throttle range. This will result in extrapolation of the engine deck, + # but provides closer matches to legacy results. To remove use of global throttle + # (and therefore eliminate extrapolation), a T4 limit needs to be manually set for + # the mission + input_values.set_val(Aircraft.Engine.GLOBAL_THROTTLE, [True]) + + # GEARBOX + # Aviary has a reduction gearbox which is 1/gear ratio of GASP gearbox + if Aircraft.Engine.Gearbox.GEAR_RATIO in input_values: + ratios = input_values.get_val(Aircraft.Engine.Gearbox.GEAR_RATIO) + ratios = [1 / val for val in ratios] + input_values.set_val(Aircraft.Engine.Gearbox.GEAR_RATIO, ratios, units='unitless') + + # CARGO + if Aircraft.CrewPayload.Design.MAX_CARGO_MASS in input_values: + if input_values.get_val(Aircraft.CrewPayload.Design.MAX_CARGO_MASS, 'lbm')[0] >= 0: + input_values.set_val(Aircraft.CrewPayload.Design.CARGO_MASS, [0.0], 'lbm') + input_values.set_val(Aircraft.CrewPayload.CARGO_MASS, [0.0], 'lbm') + + # ENGINE + if Aircraft.Engine.NUM_ENGINES in input_values: + num_engines = input_values.get_val(Aircraft.Engine.NUM_ENGINES, 'unitless')[0] + num_engines = int(num_engines) + else: + num_engines = 1 + input_values.set_val(Aircraft.Engine.NUM_ENGINES, [num_engines], 'unitless') + if Aircraft.Design.TYPE in input_values: + design_type = input_values.get_val(Aircraft.Design.TYPE, 'unitless')[0] + if design_type == 'BWB': + num_fuselage_engines = num_engines + # assume all engines are fuselage engines + input_values.set_val( + Aircraft.Engine.NUM_FUSELAGE_ENGINES, [num_fuselage_engines], 'unitless' + ) + # BWB engine sizing algorithm does not use reference diameter + input_values.delete(Aircraft.Engine.REFERENCE_DIAMETER) + else: + input_values.set_val(Aircraft.Design.TYPE, 'transport') + if Aircraft.Engine.TYPE in input_values: + engine_type = input_values.get_val(Aircraft.Engine.TYPE, 'unitless')[0] + if verbosity > Verbosity.BRIEF: + print( + f'Engine type {engine_type} was provided; currently only TURBOPROP(6) and ' + 'TURBOJET(7) are supported by Aviary' + ) + + # FURNISHING + if Aircraft.Furnishings.MASS in input_values: + furnishing_mass_scaler = input_values.get_val(Aircraft.Furnishings.MASS, 'lbm')[0] + if furnishing_mass_scaler < 0: + furnishing_mass_scaler = abs(furnishing_mass_scaler) + input_values.set_val(Aircraft.Furnishings.MASS_SCALER, [furnishing_mass_scaler], 'lbm') + input_values.delete(Aircraft.Furnishings.MASS) + + unused_values = vehicle_data['unused_values'] + knac = unused_values.get_item('INGASP.KNAC')[0][0] + if knac != 2: + try: + input_values.delete(Aircraft.Nacelle.AVG_DIAMETER) + input_values.delete(Aircraft.Nacelle.AVG_LENGTH) + except: + pass + + # Variables required by GASP, but no default values are provided in GASP + missing_vars = [] + if not Aircraft.Wing.ZERO_LIFT_ANGLE in input_values: + missing_vars.append('ALPHL0') + if not Aircraft.Wing.ASPECT_RATIO in input_values: + missing_vars.append('AR') + if not Aircraft.HorizontalTail.ASPECT_RATIO in input_values: + missing_vars.append('ARHT') + if not Aircraft.VerticalTail.ASPECT_RATIO in input_values: + missing_vars.append('ARVT') + if not Aircraft.Design.PART25_STRUCTURAL_CATEGORY in input_values: + missing_vars.append('CATD') + if not Aircraft.Fuselage.PRESSURE_DIFFERENTIAL in input_values: + missing_vars.append('DELP') + if not Mission.Taxi.DURATION in input_values: + missing_vars.append('DELTT') + if not Aircraft.Wing.FLAP_DEFLECTION_LANDING in input_values: + missing_vars.append('DFLPLD') + if not Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF in input_values: + missing_vars.append('DFLPTO') + if not Aircraft.Wing.SWEEP in input_values: + missing_vars.append('DLMC4') + if not Aircraft.Wing.INCIDENCE in input_values: + missing_vars.append('EYEW') + if not Aircraft.CrewPayload.Design.NUM_PASSENGERS in input_values: + missing_vars.append('PAX') + if not Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST in input_values: + missing_vars.append('PS') + if not Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST in input_values: + missing_vars.append('SAB') + if not Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION in input_values: + missing_vars.append('SAH') + if not Aircraft.Wing.TAPER_RATIO in input_values: + missing_vars.append('SLM') + if not Aircraft.HorizontalTail.TAPER_RATIO in input_values: + missing_vars.append('SLMH') + if not Aircraft.VerticalTail.TAPER_RATIO in input_values: + missing_vars.append('SLMV') + if not Aircraft.HorizontalTail.THICKNESS_TO_CHORD in input_values: + missing_vars.append('TCHT') + if not Aircraft.Wing.THICKNESS_TO_CHORD_ROOT in input_values: + missing_vars.append('TCR') + if not Aircraft.Wing.THICKNESS_TO_CHORD_TIP in input_values: + missing_vars.append('TCT') + if not Aircraft.VerticalTail.THICKNESS_TO_CHORD in input_values: + missing_vars.append('TCVT') + if not Aircraft.Nacelle.MASS_SPECIFIC in input_values: + missing_vars.append('UWNAC') + if not Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS in input_values: + missing_vars.append('UWPAX') + if not Aircraft.Design.MAX_STRUCTURAL_SPEED in input_values: + missing_vars.append('VMLFSL') + if not Aircraft.Fuselage.AISLE_WIDTH in input_values: + missing_vars.append('WAS') + if not Aircraft.Fuselage.SEAT_WIDTH in input_values: + missing_vars.append('WS') + if not Aircraft.LandingGear.MAIN_GEAR_LOCATION in input_values: + missing_vars.append('YMG') + if not Aircraft.Engine.WING_LOCATIONS in input_values: + missing_vars.append('YP') + if not Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION in input_values: + missing_vars.append('SAH') + if len(missing_vars) > 0: + raise RuntimeError( + f'The following variables are required but are not provided:\n {missing_vars}' + ) vehicle_data['input_values'] = input_values return vehicle_data def update_flops_options(vehicle_data): - """ - Handles variables that are affected by the values of others - """ + """Handles variables that are affected by the values of others.""" input_values: NamedValues = vehicle_data['input_values'] for var_name in flops_scaler_variables: update_flops_scaler_variables(var_name, input_values) + # TODO TWR should be checked for and a comment added that T/W ratio should be constrained to the + # value found in the input file - TWR != Aircraft.Design.THRUST_RATIO!!!! # TWR <= 0 is not valid in Aviary (parametric variation) - if Aircraft.Design.THRUST_TO_WEIGHT_RATIO in input_values: - if input_values.get_val(Aircraft.Design.THRUST_TO_WEIGHT_RATIO)[0] <= 0: - input_values.delete(Aircraft.Design.THRUST_TO_WEIGHT_RATIO) + # if Aircraft.Design.THRUST_TO_WEIGHT_RATIO in input_values: + # if input_values.get_val(Aircraft.Design.THRUST_TO_WEIGHT_RATIO)[0] <= 0: + # input_values.delete(Aircraft.Design.THRUST_TO_WEIGHT_RATIO) # WSR - # Additional mass fraction scaler set to zero to not add mass twice if Aircraft.Engine.ADDITIONAL_MASS_FRACTION in input_values: if input_values.get_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION)[0] >= 1: - input_values.set_val(Aircraft.Engine.ADDITIONAL_MASS, - input_values.get_val( - Aircraft.Engine.ADDITIONAL_MASS_FRACTION), - 'lbm') + input_values.set_val( + Aircraft.Engine.ADDITIONAL_MASS, + input_values.get_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION), + 'lbm', + ) input_values.set_val(Aircraft.Engine.ADDITIONAL_MASS_FRACTION, [0.0]) # Miscellaneous propulsion mass trigger point 1 instead of 5 if Aircraft.Propulsion.MISC_MASS_SCALER in input_values: if input_values.get_val(Aircraft.Propulsion.MISC_MASS_SCALER)[0] >= 1: - input_values.set_val(Aircraft.Propulsion.TOTAL_MISC_MASS, - input_values.get_val( - Aircraft.Propulsion.MISC_MASS_SCALER), - 'lbm') + input_values.set_val( + Aircraft.Propulsion.TOTAL_MISC_MASS, + input_values.get_val(Aircraft.Propulsion.MISC_MASS_SCALER), + 'lbm', + ) input_values.set_val(Aircraft.Propulsion.MISC_MASS_SCALER, [0.0]) + if Aircraft.Fuel.DENSITY in input_values: + # Interpret value equivalently to FULDEN (FLOPS fuel density ratio relative to jet fuel 6.7 lbm/galUS) and convert to an absolute fuel density) + input_values.set_val( + Aircraft.Fuel.DENSITY, + [6.7 * input_values.get_val(Aircraft.Fuel.DENSITY, 'lbm/galUS')[0]], + 'lbm/galUS', + ) + # else: not required as jet fuel is assumed and default value in metadata is 6.7 + + if Aircraft.Fuel.WING_FUEL_CAPACITY in input_values: + if input_values.get_val(Aircraft.Fuel.WING_FUEL_CAPACITY, 'lbm')[0] < 50: + # Interpret value equivalently to FWMAX = wing_fuel_fraction * fuel_density * 2/3 + FWMAX = input_values.get_val(Aircraft.Fuel.WING_FUEL_CAPACITY, 'lbm')[0] + FULDEN = input_values.get_val(Aircraft.Fuel.DENSITY, 'lbm/ft**3')[0] + input_values.set_val( + Aircraft.Fuel.WING_FUEL_FRACTION, [FWMAX / (FULDEN * (2 / 3))], 'unitless' + ) + input_values.delete(Aircraft.Fuel.WING_FUEL_CAPACITY) + + # Set detailed wing flag if model supports it + if Aircraft.Wing.INPUT_STATION_DIST in input_values: + input_values.set_val(Aircraft.Wing.DETAILED_WING, [True]) + + vehicle_data['input_values'] = input_values + return vehicle_data + + +def update_aviary_options(vehicle_data): + """Special handling for variables that occurs for either legacy code.""" + input_values: NamedValues = vehicle_data['input_values'] + + # if reference + scaled thrust both provided, set scale factor + try: + ref_thrust = input_values.get_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 'lbf')[0] + ref_thrust = float(ref_thrust) + input_values.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, [ref_thrust], 'lbf') + except KeyError: + pass + vehicle_data['input_values'] = input_values return vehicle_data @@ -568,7 +943,7 @@ def update_flops_scaler_variables(var_name, input_values: NamedValues): = 0., no weight for that component > 0. but < 5., scale factor applied to internally computed weight or area > 5., actual fixed weight for component, lb or ft**2 - Same rules also applied to various other FLOPS scaler parameters + Same rules also applied to various other FLOPS scaler parameters. """ scaler_name = var_name + '_scaler' if scaler_name not in input_values: @@ -579,7 +954,7 @@ def update_flops_scaler_variables(var_name, input_values: NamedValues): elif scaler_value < 5: return elif scaler_value > 5: - if "area" in var_name.lower(): + if 'area' in var_name.lower(): input_values.set_val(var_name, [scaler_value], 'ft**2') else: input_values.set_val(var_name, [scaler_value], 'lbm') @@ -595,7 +970,7 @@ def update_gasp_scaler_variables(var_name, input_values: NamedValues): = 0., no weight/area for that component > 0. but < 10., scale factor applied to internally computed weight > 10., actual fixed weight for component, lb or ft**2 - Same rules also applied to various other FLOPS scaler parameters + Same rules also applied to various other FLOPS scaler parameters. """ scaler_name = var_name + '_scaler' if scaler_name not in input_values: @@ -606,7 +981,7 @@ def update_gasp_scaler_variables(var_name, input_values: NamedValues): elif scaler_value < 10: return elif scaler_value > 10: - if "area" in var_name.lower(): + if 'area' in var_name.lower(): input_values.set_val(var_name, [scaler_value], 'ft**2') else: input_values.set_val(var_name, [scaler_value], 'lbm') @@ -644,7 +1019,7 @@ def update_gasp_scaler_variables(var_name, input_values: NamedValues): Aircraft.Nacelle.MASS, Aircraft.Nacelle.WETTED_AREA, Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, - Aircraft.VerticalTail.MASS_SCALER, + Aircraft.VerticalTail.MASS, Aircraft.VerticalTail.WETTED_AREA, Aircraft.Wing.MASS, Aircraft.Wing.SHEAR_CONTROL_MASS, @@ -658,7 +1033,8 @@ def update_gasp_scaler_variables(var_name, input_values: NamedValues): ] initialization_guesses = { - # initialization_guesses is a dictionary that contains values used to initialize the trajectory + # initialization_guesses is a dictionary that contains values used to + # initialize the trajectory 'actual_takeoff_mass': 0, 'rotation_mass': 0, 'fuel_burn_per_passenger_mile': 0, @@ -666,57 +1042,51 @@ def update_gasp_scaler_variables(var_name, input_values: NamedValues): 'flight_duration': 0, 'time_to_climb': 0, 'climb_range': 0, - 'reserves': 0 + 'reserves': 0, } def _setup_F2A_parser(parser): - ''' + """ Set up the subparser for the Fortran_to_aviary tool. Parameters ---------- parser : argparse subparser The parser we're adding options to. - ''' + """ parser.add_argument( - "input_deck", + 'input_deck', type=str, nargs=1, - help="Filename of vehicle input deck, including partial or complete path.", + help='Filename of vehicle input deck, including partial or complete path.', ) parser.add_argument( - "-o", - "--out_file", + '-o', + '--out_file', default=None, - help="Filename for converted input deck, including partial or complete path." + help='Filename for converted input deck, including partial or complete path.', ) parser.add_argument( - "-l", - "--legacy_code", + '-l', + '--legacy_code', type=LegacyCode, - help="Name of the legacy code the deck originated from", + help='Name of the legacy code the deck originated from', choices=set(LegacyCode), - required=True - ) - parser.add_argument( - "-d", - "--defaults_deck", - default=None, - help="Deck of default values for unspecified variables" + required=True, ) parser.add_argument( - "--force", - action="store_true", - help="Allow overwriting existing output files", + '--force', + action='store_true', + help='Allow overwriting existing output files', ) parser.add_argument( - "-v", - "--verbosity", + '-v', + '--verbosity', type=int, choices=Verbosity.values(), default=1, - help="Set level of print statements", + help='Set level of print statements', ) @@ -729,5 +1099,4 @@ def _exec_F2A(args, user_args): # convert verbosity from int to enum verbosity = Verbosity(args.verbosity) - create_aviary_deck(filepath, args.legacy_code, args.defaults_deck, - args.out_file, args.force, verbosity) + fortran_to_aviary(filepath, args.legacy_code, args.out_file, args.force, verbosity) diff --git a/aviary/utils/functions.py b/aviary/utils/functions.py index 0f34cb6620..24435adca7 100644 --- a/aviary/utils/functions.py +++ b/aviary/utils/functions.py @@ -1,24 +1,22 @@ -from typing import Union -from pathlib import Path -import importlib_resources -from contextlib import ExitStack import atexit +from contextlib import ExitStack import os +from pathlib import Path +from typing import Union +import warnings -import openmdao.api as om +import importlib_resources import numpy as np -from openmdao.utils.units import convert_units +import openmdao.api as om from aviary.utils.aviary_values import AviaryValues, get_items -from aviary.variable_info.enums import ProblemType, EquationsOfMotion, LegacyCode -from aviary.variable_info.functions import add_aviary_output, add_aviary_input +from aviary.variable_info.enums import Verbosity +from aviary.variable_info.functions import add_aviary_input, add_aviary_output from aviary.variable_info.variable_meta_data import _MetaData class Null: - ''' - This can be used to divert outputs, such as stdout, to improve performance - ''' + """This can be used to divert outputs, such as stdout, to improve performance.""" def write(self, *args, **kwargs): pass @@ -27,25 +25,34 @@ def flush(self, *args, **kwargs): pass -def get_aviary_resource_path(resource_name: str) -> str: +def get_aviary_resource_path(resource_name: str) -> Path: """ Get the file path of a resource in the Aviary package. - Args: - resource_name (str): The name of the resource. + Parameters + ---------- + resource_name : str + The name of the resource. - Returns: - str: The file path of the resource. + Returns + ------- + path : Path + The file path of the resource. """ file_manager = ExitStack() atexit.register(file_manager.close) - ref = importlib_resources.files('aviary') / resource_name - path = file_manager.enter_context( - importlib_resources.as_file(ref)) + if resource_name: + ref = importlib_resources.files('aviary') / resource_name + else: + ref = importlib_resources.files('aviary') + path = file_manager.enter_context(importlib_resources.as_file(ref)) return path +top_dir = Path(get_aviary_resource_path('')) + + def set_aviary_initial_values(prob, aviary_inputs: AviaryValues): """ Sets initial values for all inputs in the aviary inputs. @@ -59,17 +66,16 @@ def set_aviary_initial_values(prob, aviary_inputs: AviaryValues): aviary_inputs : AviaryValues Instance of AviaryValues containing all initial values. """ - for (key, (val, units)) in get_items(aviary_inputs): + for key, (val, units) in get_items(aviary_inputs): try: prob.set_val(key, val, units) - except: + except BaseException: # Should be an option or an overridden output. continue -def set_aviary_input_defaults(model, inputs, aviary_inputs: AviaryValues, - meta_data=_MetaData): +def set_aviary_input_defaults(model, inputs, aviary_inputs: AviaryValues, meta_data=_MetaData): """ This function sets the default values and units for any inputs prior to setup. This is needed to resolve ambiguities when inputs are promoted @@ -82,7 +88,7 @@ def set_aviary_input_defaults(model, inputs, aviary_inputs: AviaryValues, model : System Top level aviary model. inputs : list - List of varibles that are causing promotion problems. This needs to + List of variables that are causing promotion problems. This needs to be crafted based on the openmdao exception messages. aviary_inputs : AviaryValues Instance of AviaryValues containing all initial values. @@ -100,77 +106,44 @@ def set_aviary_input_defaults(model, inputs, aviary_inputs: AviaryValues, model.set_input_defaults(key, val=val, units=units) -def convert_strings_to_data(string_list): +def convert_strings_to_data(input_string): """ - convert_strings_to_data will convert a list of strings to usable data. - Strings that can't be converted to numbers will attempt to store as a logical, - otherwise they are passed as is + convert_strings_to_data will convert a string or list of strings to usable data. + Strings that can't be converted to numbers will attempt to store as a boolean, + otherwise they are passed as is. """ - value_list = [0]*len(string_list) - for ii, dat in enumerate(string_list): + # pack input_string into a list if it is not + # setup output list size + if isinstance(input_string, list): + islist = True + value_list = [0] * len(input_string) + else: + islist = False + input_string = [input_string] + value_list = input_string + + for ii, dat in enumerate(input_string): dat = dat.strip('[]') try: # if the value is a number store it as a float or an int as appropriate - # BUG this returns floats that can be converted to int (e.g. 1.0) as an int (1), even if the variable requires floats - value_list[ii] = int(float(dat)) if float( - dat).is_integer() else float(dat) + # BUG this returns floats that can be converted to int (e.g. 1.0) as an + # int (1), even if the variable requires floats + value_list[ii] = int(dat) if '.' not in dat else float(dat) except ValueError: - # store value as a logical if it is a string that represents True or False + # store value as a boolean if it is a string that represents True or False if dat.lower() == 'true': value_list[ii] = True elif dat.lower() == 'false': value_list[ii] = False else: - # if the value isn't a number or a logial, store it as a string + # if the value isn't a number or a boolean, store it as a string value_list[ii] = dat - except Exception as e: - print('Exception', e) + # unpack output value from list if it isn't supposed to be one + if not islist: + value_list = value_list[0] return value_list -# TODO this function is only used in a single place (process_input_decks.py), and its -# functionality can get handled in other places (convert_strings_to_data being able -# to handle lists/arrays, and other special handling directly present in -# process_input_decks.py) -def set_value(var_name, var_value, aviary_values: AviaryValues, units=None, is_array=False, meta_data=_MetaData): - """ - Wrapper for AviaryValues.set_val(). Existing value/units of the provided variable name are used as defaults if - they exist and not provided in this function. Special list handling provided: if 'is_array' is true, 'var_value' is - always added to 'aviary_values' as a numpy array. Otherwise, if 'var_value' is a list or numpy array of length - one and existing value in 'aviary_values' or default value in 'meta_data' is not a list or numpy array, - individual value is pulled out of 'var_value' to be stored in 'aviary_values'. - """ - if var_name in aviary_values: - current_value, current_units = aviary_values.get_item(var_name) - else: - current_value = meta_data[var_name]['default_value'] - current_units = meta_data[var_name]['units'] - - if units == None: - if current_units: - units = current_units - else: - units = meta_data[var_name]['units'] - # raise ValueError("You have specified a new variable without any units") - - if is_array: - var_value = np.atleast_1d(var_value) - elif len(var_value) == 1 and not isinstance(current_value, (list, np.ndarray)): - # if only a single value is provided, don't store it as a list - var_value = var_value[0] - - # TODO handle enums in an automated method via checking metadata for enum type - if var_name == 'settings:problem_type': - var_value = ProblemType(var_value) - if var_name == 'settings:equations_of_motion': - var_value = EquationsOfMotion(var_value) - if var_name == 'settings:mass_method': - var_value = LegacyCode(var_value) - - aviary_values.set_val(var_name, val=var_value, units=units, meta_data=meta_data) - return aviary_values - - def create_opts2vals(all_options: list, output_units: dict = {}): """ create_opts2vals creates a component that converts options to outputs. @@ -198,30 +171,38 @@ def create_opts2vals(all_options: list, output_units: dict = {}): def configure_output(option_name: str, aviary_options: AviaryValues): option_data = aviary_options.get_item(option_name) - out_units = output_units[option_name] if option_name in output_units.keys( - ) else option_data[1] + out_units = ( + output_units[option_name] if option_name in output_units.keys() else option_data[1] + ) return {'val': option_data[0], 'units': out_units} class OptionsToValues(om.ExplicitComponent): def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', ) def setup(self): for option_name in all_options: - output_data = configure_output( - option_name, self.options['aviary_options']) - add_aviary_output(self, option_name, - val=output_data['val'], units=output_data['units']) + output_data = configure_output(option_name, self.options['aviary_options']) + add_aviary_output( + self, + option_name, + val=output_data['val'], + units=output_data['units'], + ) def compute(self, inputs, outputs): aviary_options: AviaryValues = self.options['aviary_options'] for option_name in all_options: output_data = configure_output(option_name, aviary_options) - outputs[option_name] = aviary_options.get_val( - option_name, units=output_data['units']) + # uses default value if not present + if option_name in aviary_options: + outputs[option_name] = aviary_options.get_val( + option_name, units=output_data['units'] + ) return OptionsToValues @@ -251,22 +232,22 @@ def add_opts2vals(Group: om.Group, OptionsToValues, aviary_options: AviaryValues class Opts2Vals(om.Group): def initialize(self): self.options.declare( - 'aviary_options', types=AviaryValues, - desc='collection of Aircraft/Mission specific options' + 'aviary_options', + types=AviaryValues, + desc='collection of Aircraft/Mission specific options', ) def setup(self): - self.add_subsystem('options_to_values', OptionsToValues( - aviary_options=aviary_options)) + self.add_subsystem('options_to_values', OptionsToValues(aviary_options=aviary_options)) def configure(self): all_output_data = self.options_to_values.list_outputs(out_stream=None) - list_of_outputs = [(name, 'option:'+name) for name, data in all_output_data] + list_of_outputs = [(name, 'option:' + name) for name, data in all_output_data] self.promotes('options_to_values', list_of_outputs) - Group.add_subsystem('opts2vals', Opts2Vals( - aviary_options=aviary_options), - promotes_outputs=['*']) + Group.add_subsystem( + 'opts2vals', Opts2Vals(aviary_options=aviary_options), promotes_outputs=['*'] + ) return Group @@ -301,47 +282,47 @@ def get_units(variable_name): return None class PrintComp(om.ExplicitComponent): - def setup(self): for variable_name in all_inputs: units = get_units(variable_name) if ':' in variable_name: try: - add_aviary_input(self, variable_name, - units=units, shape=num_nodes) + add_aviary_input(self, variable_name, units=units, shape=num_nodes) except TypeError: - self.add_input(variable_name, units=units, - shape=num_nodes, val=1.23456) + self.add_input(variable_name, units=units, shape=num_nodes, val=1.23456) else: - # using an arbitrary number that will stand out for unconnected variables - self.add_input(variable_name, units=units, - shape=num_nodes, val=1.23456) + # using an arbitrary number that will stand out for unconnected + # variables + self.add_input(variable_name, units=units, shape=num_nodes, val=1.23456) def compute(self, inputs, outputs): - print_string = ['v'*20] + print_string = ['v' * 20] for variable_name in all_inputs: units = get_units(variable_name) - print_string.append('{} {} {}'.format( - variable_name, inputs[variable_name], units)) - print_string.append('^'*20) + print_string.append('{} {} {}'.format(variable_name, inputs[variable_name], units)) + print_string.append('^' * 20) print('\n'.join(print_string)) return PrintComp def promote_aircraft_and_mission_vars(group): - """ - Promotes inputs and outputs in Aircraft and Mission hierarchy categories for provided group. - """ + """Promotes inputs and outputs in Aircraft and Mission hierarchy categories for provided group.""" external_outputs = [] for comp in group.system_iter(recurse=False): - # Skip all aviary systems. if comp.name == 'core_subsystems': continue - out_names = [item for item in comp._var_allprocs_prom2abs_list['output']] - in_names = [item for item in comp._var_allprocs_prom2abs_list['input']] + try: + resolver = comp._resolver + out_names = [item for item in resolver.prom_iter(iotype='output')] + in_names = [item for item in resolver.prom_iter(iotype='input')] + + except AttributeError: + # This is an older version of OpenMDAO + out_names = [item for item in comp._var_allprocs_prom2abs_list['output']] + in_names = [item for item in comp._var_allprocs_prom2abs_list['input']] external_outputs.extend(out_names) @@ -369,52 +350,7 @@ def promote_aircraft_and_mission_vars(group): # "str | Path" which is cleaner but Aviary still supports older versions -def get_model(file_name: str, verbose=False) -> Path: - ''' - This function attempts to find the path to a file or folder in aviary/models - If the path cannot be found in any of the locations, a FileNotFoundError is raised. - - Parameters - ---------- - path : str or Path - The input path, either as a string or a Path object. - - Returns - ------- - aviary_path - The absolute path to the file. - - Raises - ------ - FileNotFoundError - If the path is not found. - ''' - - # Get the path to Aviary's models - path = Path('models', file_name) - aviary_path = Path(get_aviary_resource_path(str(path))) - - # If the file name was provided without a path, check in the subfolders - if not aviary_path.exists(): - sub_dirs = [x[0] for x in os.walk(get_aviary_resource_path('models'))] - for sub_dir in sub_dirs: - temp_path = Path(sub_dir, file_name) - if temp_path.exists(): - # only return the first matching file - aviary_path = temp_path - continue - - # If the path still doesn't exist, raise an error. - if not aviary_path.exists(): - raise FileNotFoundError( - f"File or Folder not found in Aviary's hangar" - ) - if verbose: - print('found', aviary_path, '\n') - return aviary_path - - -def get_path(path: Union[str, Path], verbose: bool = False) -> Path: +def get_path(path: Union[str, Path], verbosity=Verbosity.BRIEF) -> Path: """ Convert a string or Path object to an absolute Path object, prioritizing different locations. @@ -429,8 +365,8 @@ def get_path(path: Union[str, Path], verbose: bool = False) -> Path: ---------- path : str or Path The input path, either as a string or a Path object. - verbose : bool, optional - If True, prints the final path being used. Default is False. + verbosity : Verbosity, optional + Sets level of printouts for this function. Returns ------- @@ -442,7 +378,6 @@ def get_path(path: Union[str, Path], verbose: bool = False) -> Path: FileNotFoundError If the path is not found in any of the prioritized locations. """ - # Store the original path for reference in error messages. original_path = path @@ -458,21 +393,25 @@ def get_path(path: Union[str, Path], verbose: bool = False) -> Path: # If the path still doesn't exist, attempt to find it relative to the Aviary package. if not path.exists(): - # Determine the path relative to the Aviary package. - aviary_based_path = Path( - get_aviary_resource_path(original_path)) - if verbose: + if verbosity > Verbosity.BRIEF: # VERBOSE, DEBUG print( - f"Unable to locate '{original_path}' as an absolute or relative path. Trying Aviary package path: {aviary_based_path}") + f"Unable to locate '{original_path}' as an absolute or relative path. " + 'Trying Aviary package path.' + ) + # Determine the path relative to the Aviary package. + aviary_based_path = Path(get_aviary_resource_path(original_path)) + path = aviary_based_path # If the path still doesn't exist, attempt to find it in the models directory. if not path.exists(): + if verbosity > Verbosity.BRIEF: + print( + f"Unable to locate '{aviary_based_path}' as an Aviary package path, " + 'checking built-in models' + ) try: - hangar_based_path = get_model(original_path, verbose=verbose) - if verbose: - print( - f"Unable to locate '{aviary_based_path}' as an Aviary package path, checking built-in models") + hangar_based_path = get_model(original_path) path = hangar_based_path except FileNotFoundError: pass @@ -485,37 +424,286 @@ def get_path(path: Union[str, Path], verbose: bool = False) -> Path: f'{Path(get_aviary_resource_path(original_path))}' ) - # If verbose is True, print the path being used. - if verbose: - print(f'Using {path} for file.') + # Print the path being used. + if verbosity > Verbosity.BRIEF: + print(f'Found {path}') return path -def wrapped_convert_units(val_unit_tuple, new_units): +def get_model(file_name: str, verbosity=Verbosity.BRIEF) -> Path: """ - Wrapper for OpenMDAO's convert_units function. + This function attempts to find the path to a file or folder in aviary/models + If the path cannot be found in any of the locations, a FileNotFoundError is raised. Parameters ---------- - val_unit_tuple : tuple - Tuple of the form (value, units) where value is a float and units is a - string. - new_units : str - New units to convert to. + path : str or Path + The input path, either as a string or a Path object. Returns ------- - float - Value converted to new units. + aviary_path + The absolute path to the file. + + Raises + ------ + FileNotFoundError + If the path is not found. """ - value, units = val_unit_tuple + # Get the path to Aviary's models + aviary_path = Path(get_aviary_resource_path(str(Path('models', file_name)))) + # Check if provided path is valid + if aviary_path.exists(): + return aviary_path + # otherwise check models folder contents + else: + from glob import glob - # can't convert units on None; return None - if value is None: - return None + contents = glob(str(get_aviary_resource_path('models') / '**'), recursive=True) + close_match = None + for item in contents: + item = Path(item) + # check if full filepath, file name with extension, or just file (or folder) name + # matches target + if aviary_path == item or aviary_path.name == item.name: + return item + elif aviary_path.stem == item.stem: + close_match = item - if isinstance(value, (list, tuple)): - return [convert_units(v, units, new_units) for v in value] + if close_match is not None: + # Probably requested the wrong file extension. + return close_match + + # If the path doesn't exist, raise an error. + raise FileNotFoundError("File or Folder not found in Aviary's hangar") + + +def sigmoidX(x, x0, mu=1.0): + """ + Sigmoid used to smoothly transition between piecewise functions. + + Parameters + ---------- + x: float or array + independent variable + x0: float + the center of symmetry. When x = x0, sigmoidX = 1/2. + mu: float + steepness parameter. + + Returns + ------- + float or array + smoothed value from input parameter x. + """ + if mu == 0: + raise ValueError('mu must be non-zero') + + if isinstance(x, np.ndarray): + if np.isrealobj(x): + dtype = float + else: + dtype = complex + n_size = x.size + y = np.zeros(n_size, dtype=dtype) + # avoid overflow in squared term, underflow seems to be ok + calc_idx = np.where((x.real - x0) / mu > -320) + y[calc_idx] = 1 / (1 + np.exp(-(x[calc_idx] - x0) / mu)) + else: + if isinstance(x, float): + dtype = float + else: + dtype = complex + y = 0 + if (x - x0) * mu > -320: + y = 1 / (1 + np.exp(-(x - x0) / mu)) + if dtype == float: + y = y.real + return y + + +def dSigmoidXdx(x, x0, mu=1.0): + """ + Derivative of sigmoid function. + + Parameters + ---------- + x: float or array + independent variable + x0: float + the center of symmetry. When x = x0, sigmoidX = 1/2. + mu: float + steepness parameter. + + Returns + ------- + float or array + smoothed derivative value from input parameter x. + """ + if mu == 0: + raise ValueError('mu must be non-zero') + + if isinstance(x, np.ndarray): + if np.isrealobj(x): + dtype = float + else: + dtype = complex + n_size = x.size + y = np.zeros(n_size, dtype=dtype) + term = np.zeros(n_size, dtype=dtype) + term2 = np.zeros(n_size, dtype=dtype) + # avoid overflow in squared term, underflow seems to be ok + calc_idx = np.where((x.real - x0) / mu > -320) + term[calc_idx] = np.exp(-(x[calc_idx] - x0) / mu) + term2[calc_idx] = (1 + term[calc_idx]) * (1 + term[calc_idx]) + y[calc_idx] = term[calc_idx] / mu / term2[calc_idx] else: - return convert_units(value, units, new_units) + y = 0 + if (x - x0) * mu > -320: + term = np.exp(-(x - x0) / mu) + term2 = (1 + term) * (1 + term) + y = term / mu / term2 + if dtype == float: + y = y.real + return y + + +def smooth_min(x, b, mu=100.0): + """ + Smooth approximation of the min function using the log-sum-exp trick. + + Parameters: + x (float or array-like): First value. + b (float or array-like): Second value. + mu (float): The smoothing factor. Higher values make it closer to the true minimum. Try between 75 and 275. + + Returns: + float or array-like: The smooth approximation of min(x, b). + """ + sum_log_exp = np.log(np.exp(np.multiply(-mu, x)) + np.exp(np.multiply(-mu, b))) + rv = -(1 / mu) * sum_log_exp + return rv + + +def d_smooth_min(x, b, mu=100.0): + """ + Derivative of function smooth_min(x) + + Parameters: + x (float or array-like): First value. + b (float or array-like): Second value. + mu (float): The smoothing factor. Higher values make it closer to the true minimum. Try between 75 and 275. + + Returns: + float or array-like: The smooth approximation of derivative of min(x, b). + """ + d_sum_log_exp = np.exp(np.multiply(-mu, x)) / ( + np.exp(np.multiply(-mu, x)) + np.exp(np.multiply(-mu, b)) + ) + return d_sum_log_exp + + +def smooth_max(x, b, mu=10.0): + """ + Smooth approximation of the min function using the log-sum-exp trick. + + Parameters: + x (float or array-like): First value. + b (float or array-like): Second value. + mu (float): The smoothing factor. Higher values make it closer to the true maximum. Try between 75 and 275. + + Returns: + float or array-like: The smooth approximation of max(x, b). + """ + mu_x = mu * x + mu_b = mu * b + m = np.maximum(mu_x, mu_b) + sum_log_exp = (m + np.log(np.exp(mu_x - m) + np.exp(mu_b - m))) / mu + + return sum_log_exp + + +def d_smooth_max(x, b, mu=10.0): + """ + Derivative of function smooth_min(x) + + Parameters: + x (float or array-like): First value. + b (float or array-like): Second value. + mu (float): The smoothing factor. Higher values make it closer to the true minimum. Try between 75 and 275. + + Returns: + float or array-like: The smooth approximation of derivative of min(x, b). + """ + mu_x = mu * x + mu_b = mu * b + m = np.maximum(mu_x, mu_b) + numerator = np.exp(mu_x - m) + denominator = np.exp(mu_x - m) + np.exp(mu_b - m) + d_sum_log_exp = mu * numerator / denominator + return d_sum_log_exp + + +def sin_int4(val): + """Define a smooth, differentialbe approximation to the 'int' function.""" + return sin_int(sin_int(sin_int(sin_int(val)))) - 0.5 + + +def dydx_sin_int4(val): + """Define the derivative (dy/dx) of sin_int4, at x = val.""" + y0 = sin_int(val) + y1 = sin_int(y0) + y2 = sin_int(y1) + + dydx3 = dydx_sin_int(y2) + dydx2 = dydx_sin_int(y1) + dydx1 = dydx_sin_int(y0) + dydx0 = dydx_sin_int(val) + + dydx = dydx3 * dydx2 * dydx1 * dydx0 + + return dydx + + +# 'int' function can be approximated by recursively applying this sin function +# which makes a smooth, differentialbe function (is there a good one?) +def sin_int(val): + """ + Define one step in approximating the 'int' function with a smooth, + differentialbe function. + """ + int_val = val - np.sin(2 * np.pi * (val + 0.5)) / (2 * np.pi) + + return int_val + + +def dydx_sin_int(val): + """Define the derivative (dy/dx) of sin_int, at x = val.""" + dydx = 1.0 - np.cos(2 * np.pi * (val + 0.5)) + + return dydx + + +def smooth_int_tanh(x, mu=10.0): + """ + Smooth approximation of int(x) using tanh. + """ + f = np.floor(x) + frac = x - f + t = np.tanh(mu * (frac - 0.5)) + s = 0.5 * (t + 1) + y = f + s + return y + + +def d_smooth_int_tanh(x, mu=10.0): + """ + Smooth approximation of int(x) using tanh. + Returns (y, dy_dx). + """ + f = np.floor(x) + frac = x - f + t = np.tanh(mu * (frac - 0.5)) + dy_dx = 0.5 * mu * (1 - t**2) + return dy_dx diff --git a/aviary/utils/legacy_code_data/deprecated_vars.py b/aviary/utils/legacy_code_data/deprecated_vars.py deleted file mode 100644 index 7c71e87284..0000000000 --- a/aviary/utils/legacy_code_data/deprecated_vars.py +++ /dev/null @@ -1,18 +0,0 @@ -## Depreciated Variables ## -# FLOPS -flops_deprecated_vars = [ - 'AERIN.MODARO', - 'ENGDIN.IGENEN', - 'ENGDIN.BOOST', - 'ENGDIN.EXTFAC', - 'ENGDIN.IXTRAP', - 'ENGDIN.NPCODE', - 'ENGDIN.PCODE', - 'ENGDIN.NOX', - 'OPTION.IOPT', - 'OPTION.IPOLP', - 'OPTION.NOISE' -] - -# GASP -gasp_deprecated_vars = [] diff --git a/aviary/utils/legacy_code_data/flops_default_values.txt b/aviary/utils/legacy_code_data/flops_default_values.txt deleted file mode 100644 index a2ce69a576..0000000000 --- a/aviary/utils/legacy_code_data/flops_default_values.txt +++ /dev/null @@ -1,18 +0,0 @@ -Default Values from FLOPS - - &WTIN - EEXP=1.15,unitless - IALTWT=False,unitless - CARGF=False,unitless - CARBAS=False,unitless - \ - &ENGDIN - IDLE=False,unitless - IGEO=False,unitless - NONEG=False,unitless - \ - &AERIN - MIKE=False,unitless - SWETF=1,unitless - SWETV=1,unitless - \ \ No newline at end of file diff --git a/aviary/utils/legacy_code_data/flops_defaults.py b/aviary/utils/legacy_code_data/flops_defaults.py new file mode 100644 index 0000000000..98f796401d --- /dev/null +++ b/aviary/utils/legacy_code_data/flops_defaults.py @@ -0,0 +1,33 @@ +from aviary.utils.named_values import NamedValues + +## Defaults ## +flops_default_values = NamedValues( + { + 'WTIN.EEXP': (1.15, 'unitless'), + 'WTIN.IALTWT': (False, 'unitless'), + 'WTIN.CARGF': (False, 'unitless'), + 'WTIN.IFUFU': (False, 'unitless'), + 'ENGDIN.IDLE': (False, 'unitless'), + 'ENGDIN.IGEO': (False, 'unitless'), + 'ENGDIN.NONEG': (False, 'unitless'), + 'AERIN.MIKE': (False, 'unitless'), + 'AERIN.SWETF': (1, 'unitless'), + 'AERIN.SWETV': (1, 'unitless'), + } +) + +## Depreciated Variables ## +flops_deprecated_vars = [ + 'AERIN.MODARO', + 'ENGDIN.IGENEN', + 'ENGDIN.BOOST', + 'ENGDIN.EXTFAC', + 'ENGDIN.IXTRAP', + 'ENGDIN.NPCODE', + 'ENGDIN.PCODE', + 'ENGDIN.NOX', + 'OPTION.IOPT', + 'OPTION.IPOLP', + 'OPTION.NOISE', + 'WTIN.CARBAS', +] diff --git a/aviary/utils/legacy_code_data/gasp_default_values.dat b/aviary/utils/legacy_code_data/gasp_default_values.dat deleted file mode 100644 index ea6fe30f32..0000000000 --- a/aviary/utils/legacy_code_data/gasp_default_values.dat +++ /dev/null @@ -1,157 +0,0 @@ -Default Values from GASP - $INGASP -ALPHL0=-1.2,deg -ALTLND=0,ft -AR=10,unitless -ARHT=4.75,unitless -ARNGE(1)=0,NM -ARNGE(3)=0,NM -ARVT=1.67,unitless -AS=1,unitless -BLEOB=0.9,unitless -BOELTV=0,unitless -BTEOB=0.75,unitless -CATD=3,unitless -CFOC=0.3,unitless -CK10=1,unitless -CK11=1,unitless -CK12=1,unitless -CK14=1,unitless -CK15=1,unitless -CK18=1,unitless -CK19=1,unitless -CK21=1,unitless -CK5=1,unitless -CK7=1,unitless -CK8=1,unitless -CK9=1,unitless -CKF=1,unitless -CKFF=1,unitless -CKHT=1,unitless -CKI=0,unitless -CKN=1,unitless -CKSTRT=0,unitless -CKVT=1,unitless -CKW=1,unitless -CLEARqDN=0.2,unitless -CLEOC=0,unitless -COELTH=0,unitless -CRALT=37500,ft -CRMACH=0.8,unitless -CW(1)=0,lbm -CW(10)=1,lbm -CW(11)=0,lbm -CW(12)=0.7,lbm -CW(13)=6,unitless -CW(2)=0.0862,unitless -CW(3)=0.1,unitless -CW(4)=0.16,unitless -CW(5)=0,lbm -CW(6)=1,unitless -CW(7)=0,lbm -CW(8)=0,lbm -CW(9)=2,lbm -DCDOTE=0,unitless -DCLMLE=0.93,unitless -DCLMTE=0,unitless -DELCD=0.0015,unitless -DELCG=0.25,unitless -DELFE=0.25,ft**2 -DELLED=0,deg -DELLED=0,deg -DELLEO=45,deg -DELP=7.5,psi -DELTEO=0,deg -DELTT=0.1677,h -DELWFC=0,lbm -DELWST=0,lbm -DFLPLD=40,deg -DFLPTO=10,deg -DIAM_REF=5.8,ft -DLMC4=25,deg -DNQDE=1,unitless -DV1=5,kn -DVR=5,kn -DWPQCH=25,deg -DWPQCV=35,deg -ELODN=2,unitless -ELODT=3.2,unitless -ELPC=4.44,ft -ENP=2,unitless -EYEW=1.5,deg -FLAPN=1,unitless -FN_REF=28690,lbf -FPYL=0.7,unitless -FRESF=4998,lbm -FUELD=6.687,lbm/galUS -FVOL_MRG=0,unitless -HAPP=50,ft -HCK=2.47,ft -HPORT=0,ft -HTG=3,ft -HWING=0,unitless -IGEAR=False,unitless -JENGSZ=4,unitless -JFLTYP=single_slotted,unitless -NTYE=7,unitless -PAX=180,unitless -PS=29,inch -ROCTOC=300,ft/min -RCLMAX=1,unitless -RSMX=1000,ft/min -SAB=6,unitless -SAH=0,unitless -SCFAC=0,unitless -SF_FAC=1,unitless -SHT=0,ft**2 -SINKTD=3,ft/s -SKB=136,unitless -SKCC=11,unitless -SKFS=0.0195,unitless -SKFW=0.404,unitless -SKLG=0.0318,unitless -SKMG=0.8,unitless -SKPEI=0.135,unitless -SKSAS=0,lbm -SKSTRUT=0,unitless -SKTL=1,unitless -SKWF=0.43,unitless -SKWFOLD=0,unitless -SKWW=133.4,unitless -SKY=0.18,unitless -SKZ=0.22,unitless -SLM=0.33,unitless -SLMH=0.352,unitless -SLMV=0.801,unitless -SSTQSW=0,unitless -STATIC=0.05,unitless -STRUT=0 -SVT=0,ft**2 -SWSLS=0,lbm/lbf -TCHT=0.12,unitless -TCR=0.15,unitless -TCT=0.12,unitless -TCVT=0.12,unitless -TDELAY=1,s -THIN=0,lbf -UWNAC=3,lbm/ft**2 -UWPAX=200,lbm -VBARHX=0,unitless -VBARVX=0,unitless -VMLFSL=402.5,mi/h -VRATT=1.3,unitless -WAS=24,inch -WCARGO=0,lbm -WCFLAP=0,unitless -WG=150000,lbm -WGS=1,lbf/ft**2 -WS=20.2,inch -XCPS=0.3,unitless -XCTCMX=0.35,unitless -XLFMX=1.2,unitless -XLQDE=3.5,unitless -XWQLF=0.4,unitless -YMG=0.15,unitless -YP=0.35,unitless -YWFOLD=0,ft - $END diff --git a/aviary/utils/legacy_code_data/gasp_defaults.py b/aviary/utils/legacy_code_data/gasp_defaults.py new file mode 100644 index 0000000000..b51e26da82 --- /dev/null +++ b/aviary/utils/legacy_code_data/gasp_defaults.py @@ -0,0 +1,143 @@ +from aviary.utils.named_values import NamedValues + +## Defaults ## +# commented out values were not in metadata at the time +gasp_default_values = NamedValues( + { + 'INGASP.ALTLND': (0, 'ft'), + 'INGASP.ARNGE(1)': (0, 'NM'), # Aviary reads ARNGE(1) only. ARNGE(2) - ARNGE(4) are ignored + 'INGASP.AS': (1, 'unitless'), # GASP does not have a default but 1 is reasonable + 'INGASP.BOELTV': (0, 'unitless'), + 'INGASP.BTEOB': (0.75, 'unitless'), + 'INGASP.CFOC': (0.3, 'unitless'), + 'INGASP.CK5': (1.0, 'unitless'), + # 'INGASP.CK7': (1.0, 'unitless'), + # 'INGASP.CK8': (1.0, 'unitless'), + # 'INGASP.CK9': (1.0, 'unitless'), + # 'INGASP.CK10': (1.0, 'unitless'), + # 'INGASP.CK11': (1.0, 'unitless'), + 'INGASP.CK12': (1.0, 'unitless'), + 'INGASP.CK14': (1.0, 'unitless'), + 'INGASP.CK15': (1.0, 'unitless'), + # 'INGASP.CK18': (1.0, 'unitless'), + 'INGASP.CK19': (1.0, 'unitless'), + 'INGASP.CK21': (1.0, 'unitless'), + 'INGASP.CKF': (-1.0, 'unitless'), + 'INGASP.CKFF': (1.0, 'unitless'), + 'INGASP.CKHT': (-1.0, 'unitless'), + 'INGASP.CKI': (0.0, 'unitless'), + 'INGASP.CKN': (-1.0, 'unitless'), + 'INGASP.CKSTRT': (1.0, 'unitless'), + 'INGASP.CKVT': (-1.0, 'unitless'), + 'INGASP.CKW': (-1.0, 'unitless'), + 'INGASP.CLEARqDN': (0.2, 'unitless'), + 'INGASP.CLEOC': (0.0, 'unitless'), + 'INGASP.COELTH': (0.0, 'unitless'), + 'INGASP.CRALT': (0.0, 'ft'), + 'INGASP.CRMACH': (0.0, 'unitless'), + 'INGASP.CW(1)': (0.0, 'lbm'), + 'INGASP.CW(2)': (0.0862, 'unitless'), + 'INGASP.CW(3)': (0.1, 'unitless'), + 'INGASP.CW(4)': (0.16, 'unitless'), + 'INGASP.CW(5)': (0.0, 'lbm'), + 'INGASP.CW(6)': (1.0, 'unitless'), + 'INGASP.CW(7)': (0.0, 'lbm'), + 'INGASP.CW(8)': (0.0, 'lbm'), + 'INGASP.CW(9)': (2.0, 'lbm'), + 'INGASP.CW(10)': (1.0, 'lbm'), + 'INGASP.CW(11)': (0.0, 'lbm'), + 'INGASP.CW(12)': (0.7, 'lbm'), + 'INGASP.CW(13)': (6.0, 'unitless'), + 'INGASP.CW(14)': (0.0, 'lbm'), + 'INGASP.CW(15)': (16.0, 'lbm'), + 'INGASP.CW(16)': (0.0, 'unitless'), + 'INGASP.DCDOTE': (0.0, 'unitless'), + 'INGASP.DCLMLE': (0.93, 'unitless'), + 'INGASP.DCLMTE': (0.0, 'unitless'), + 'INGASP.DELCD': (0.0015, 'unitless'), + 'INGASP.DELCG': (0.25, 'unitless'), + 'INGASP.DELFE': (0.25, 'ft**2'), + 'INGASP.DELLED': (0.0, 'deg'), + 'INGASP.DELLEO': (45.0, 'deg'), + 'INGASP.DELTEO': (0.0, 'deg'), + 'INGASP.DELTT': (0.1677, 'h'), + 'INGASP.DELWFC': (0.0, 'lbm'), + 'INGASP.DELWST': (0.0, 'lbm'), + 'INGASP.DFLPLD': (40, 'deg'), + 'INGASP.DFLPTO': (10, 'deg'), + 'INGASP.DIAM_REF': (5.8, 'ft'), # no DIAM_REF in GASP + 'INGASP.DNQDE': (1.0, 'unitless'), + 'INGASP.DV1': (5.0, 'kn'), + 'INGASP.DVR': (5.0, 'kn'), + 'INGASP.DWPQCH': (25.0, 'deg'), + 'INGASP.DWPQCV': (35.0, 'deg'), + 'INGASP.ELODN': (2.0, 'unitless'), + 'INGASP.ELODT': (3.2, 'unitless'), + 'INGASP.ELPC': (4.44, 'ft'), + 'INGASP.ENP': (2, 'unitless'), # GASP does not have a default but 2 is reasonable + 'INGASP.EYEW': (1.5, 'deg'), + 'INGASP.FLAPN': (1.0, 'unitless'), + 'INGASP.FN_REF': (28690, 'lbf'), # no FN_REF in GASP + 'INGASP.FPYL': ( + 0.0, + 'unitless', + ), # in GASP manual, default is 0.7 if NTYE=7 and KNAC=2, but source code is 0.0 + 'INGASP.FRESF': (1.0, 'lbm'), + 'INGASP.FUELD': (6.687, 'lbm/galUS'), + 'INGASP.FVOL_MRG': (0.0, 'unitless'), + 'INGASP.HAPP': (50.0, 'ft'), + 'INGASP.HCK': (2.47, 'ft'), + # 'INGASP.HPORT': (0, 'ft'), + 'INGASP.HTG': (3.0, 'ft'), + 'INGASP.HWING': (0.0, 'unitless'), + 'INGASP.IGEAR': (False, 'unitless'), + 'INGASP.IHWB': ('transport', 'unitless'), + # 'INGASP.JENGSZ': (4, 'unitless'), + 'INGASP.JFLTYP': ('single_slotted', 'unitless'), + 'INGASP.NTYE': (7, 'unitless'), # GASP does not have a default but 7 is reasonable + 'INGASP.ROCTOC': (0.0, 'ft/min'), + 'INGASP.RCLMAX': (1.0, 'unitless'), + 'INGASP.RSMX': (1000.0, 'ft/min'), + 'INGASP.SCFAC': (0.0, 'unitless'), + 'INGASP.SF_FAC': (1.0, 'unitless'), + 'INGASP.SINKTD': (3.0, 'ft/s'), + 'INGASP.SKB': (136.0, 'unitless'), + 'INGASP.SKCC': (11, 'unitless'), + 'INGASP.SKFS': (0.0195, 'unitless'), + 'INGASP.SKFW': (0.404, 'unitless'), + 'INGASP.SKLG': (0.0318, 'unitless'), + 'INGASP.SKMG': (0.8, 'unitless'), + 'INGASP.SKPEI': (0.135, 'unitless'), + 'INGASP.SKSAS': (0.0, 'lbm'), + 'INGASP.SKSTRUT': (0.0, 'unitless'), + 'INGASP.SKTL': (1.0, 'unitless'), + 'INGASP.SKWF': (0.43, 'unitless'), + 'INGASP.SKWFOLD': (0.0, 'unitless'), + 'INGASP.SKWW': (133.4, 'unitless'), + 'INGASP.SKY': (0.18, 'unitless'), + 'INGASP.SKZ': (0.22, 'unitless'), + 'INGASP.SSTQSW': (0.0, 'unitless'), + 'INGASP.STATIC': (0.05, 'unitless'), + 'INGASP.STRUT': (0.0, 'ft'), + 'INGASP.SWSLS': (0.0, 'lbm/lbf'), + 'INGASP.TDELAY': (1.0, 's'), + 'INGASP.THIN': (0.0, 'lbf'), + 'INGASP.VBARHX': (0.0, 'unitless'), + 'INGASP.VBARVX': (0.0, 'unitless'), + 'INGASP.VRATT': (1.3, 'unitless'), + 'INGASP.WCARGO': (0.0, 'lbm'), + 'INGASP.WCFLAP': (-1.0, 'unitless'), + 'INGASP.WG': (0.0, 'lbm'), + 'INGASP.WGS': (0.0, 'lbf/ft**2'), + 'INGASP.XCPS': (0.3, 'unitless'), + 'INGASP.XCTCMX': (0.35, 'unitless'), + 'INGASP.XLFMX': (1.2, 'unitless'), + 'INGASP.XLQDE': (3.5, 'unitless'), + 'INGASP.XWQLF': (0.4, 'unitless'), + 'INGASP.YMG': (0.15, 'unitless'), + 'INGASP.YWFOLD': (0.0, 'ft'), + } +) + +## Depreciated Variables ## +gasp_deprecated_vars = [] diff --git a/aviary/utils/merge_hierarchies.py b/aviary/utils/merge_hierarchies.py index 70b2f5e91b..3453d652bf 100644 --- a/aviary/utils/merge_hierarchies.py +++ b/aviary/utils/merge_hierarchies.py @@ -1,16 +1,15 @@ import copy -from aviary.utils.compare_hierarchies import (compare_hierarchies_to_merge, - compare_inner_classes) +from aviary.utils.compare_hierarchies import compare_hierarchies_to_merge, compare_inner_classes def merge_attributes(base_class, merge_class, base_class_attributes, merge_class_attributes): - ''' + """ Adds unique attributes of merge_class to base_class. For all the attributes of merge_class that are not present in base_class we add them to base_class. Attributes present in both classes are ignored because if they are variables they have already - been checked and found identical and if they are inner classes they will be addressed on a + been checked and found identical and if they are inner classes they will be addressed on a recursive call to this function. Attributes present only in base_class are ignored because we are adding to base_class and thus all of its features are automatically preserved. @@ -33,18 +32,18 @@ class in the hierarchy, or any inner class nested at any depth within that top-l Returns ------- base_class : class - A class that contains the merged together attributes of base_class and merge_class, with - the exception that inner class base_class and merge_class share which have diverging attributes inside + A class that contains the merged together attributes of base_class and merge_class, with + the exception that inner class base_class and merge_class share which have diverging attributes inside of them are not necessarily included. Raises ------ None No exceptions raised by this method, although other methods called within may raise exceptions. - ''' - - merge_class_unique = merge_class_attributes - \ - base_class_attributes # attributes present only in merge_class + """ + merge_class_unique = ( + merge_class_attributes - base_class_attributes + ) # attributes present only in merge_class for attr in merge_class_unique: setattr(base_class, attr, getattr(merge_class, attr)) @@ -53,7 +52,7 @@ class in the hierarchy, or any inner class nested at any depth within that top-l def recursive_merge(overlapping_inners, base_class, merge_class): - ''' + """ Recursively compares all inner classes to an infinite depth and identifies mismatched string-named values. For all of the inner class names provided in overlapping_inner_classes this function calls compare_inner_classes @@ -67,39 +66,54 @@ def recursive_merge(overlapping_inners, base_class, merge_class): and outer_class_b have in common. outer_class_a : class - A class that is all or part of a variable hierarchy. This can be the top-level class in the + A class that is all or part of a variable hierarchy. This can be the top-level class in the hierarchy, or any inner class nested at any depth within that top-level class. outer_class_b : class - A class that is all or part of a variable hierarchy. This can be the top-level class in the + A class that is all or part of a variable hierarchy. This can be the top-level class in the hierarchy, or any inner class nested at any depth within that top-level class. Returns - ------- + ------- None No variables returned by this method. Raises - ---------- + ------ None No exceptions raised by this method, although other methods called within may raise exceptions. - ''' - + """ for overlapping_class_name in overlapping_inners: overlapping_inner_class_base = getattr(base_class, overlapping_class_name) overlapping_inner_class_merge = getattr(merge_class, overlapping_class_name) - [overlapping_second_inners, vars_base_inner, vars_merge_inner, inners_base_inner, inners_merge_inner] = compare_inner_classes( - overlapping_inner_class_base, overlapping_inner_class_merge, show_all=True) - merge_attributes(overlapping_inner_class_base, - overlapping_inner_class_merge, vars_base_inner, vars_merge_inner) - merge_attributes(overlapping_inner_class_base, - overlapping_inner_class_merge, inners_base_inner, inners_merge_inner) - recursive_merge(overlapping_second_inners, - overlapping_inner_class_base, overlapping_inner_class_merge) + [ + overlapping_second_inners, + vars_base_inner, + vars_merge_inner, + inners_base_inner, + inners_merge_inner, + ] = compare_inner_classes( + overlapping_inner_class_base, overlapping_inner_class_merge, show_all=True + ) + merge_attributes( + overlapping_inner_class_base, + overlapping_inner_class_merge, + vars_base_inner, + vars_merge_inner, + ) + merge_attributes( + overlapping_inner_class_base, + overlapping_inner_class_merge, + inners_base_inner, + inners_merge_inner, + ) + recursive_merge( + overlapping_second_inners, overlapping_inner_class_base, overlapping_inner_class_merge + ) def merge_two_hierarchies(base_hierarchy, hierarchy_b): - ''' + """ Merge two variable hierarchies together by adding the second into the first. Add the attributes (variables and inner classes) of two variable hierarchies together, so that @@ -114,40 +128,39 @@ def merge_two_hierarchies(base_hierarchy, hierarchy_b): the attributes of the base and the other hierarchy. hierarchy_b : class - An Aviary variable hierarchy. This hierarchy will function as the 'auxiliary' hierarhcy, - which is the hierarchy whose unique attributes are added onto a base in order to combine the + An Aviary variable hierarchy. This hierarchy will function as the 'auxiliary' hierarchy, + which is the hierarchy whose unique attributes are added onto a base in order to combine the attributes of the base and the auxiliary. Returns ------- base_hierarchy : class An Aviary variable hierarchy which includes both the attributes of the inputted base_hierarchy - and hierarchy_b. This is the same object as the inputted base_hierarchy and has been updated through + and hierarchy_b. This is the same object as the inputted base_hierarchy and has been updated through mutability. Raises - ---------- + ------ None No exceptions raised by this method, although other methods called within may raise exceptions. - ''' + """ [overlapping_inners, merged_vars, b_vars, merged_inners, b_inners] = compare_inner_classes( - base_hierarchy, hierarchy_b, show_all=True) + base_hierarchy, hierarchy_b, show_all=True + ) # this adds the variables of hierarchy_b which are not in base_hierarchy to the overall merged hierarchy - base_hierarchy = merge_attributes( - base_hierarchy, hierarchy_b, merged_vars, b_vars) + base_hierarchy = merge_attributes(base_hierarchy, hierarchy_b, merged_vars, b_vars) # this adds the inner classes of hierarchy_b which are not in base_hierarchy to the overall merged hierarchy - base_hierarchy = merge_attributes( - base_hierarchy, hierarchy_b, merged_inners, b_inners) + base_hierarchy = merge_attributes(base_hierarchy, hierarchy_b, merged_inners, b_inners) recursive_merge(overlapping_inners, base_hierarchy, hierarchy_b) return base_hierarchy def merge_hierarchies(hierarchies_to_merge): - ''' + """ Combines all provided variable hierarchies into one unified variable hierarchy. - Performs checks on the user-provided list of variable hierarchies in order to ensure that they are + Performs checks on the user-provided list of variable hierarchies in order to ensure that they are compatible for merge. Ensures that they are not derived from different superclasses, and that they do not have conflicting values. Assuming all checks pass, the provided hierarchies are combined into a single hierarchy. @@ -166,22 +179,25 @@ def merge_hierarchies(hierarchies_to_merge): ------ ValueError Raises an exception if the list of inputted variable hierarchies includes hierarchies that have been subclassed from different superclasses. - ''' + """ compare_hierarchies_to_merge(hierarchies_to_merge) subclass_type = None subclass_hierarchy = None for hierarchy in hierarchies_to_merge: # check that there are not hierarchies subclassing from different classes that we are attempting to merge # checks if the given hierarchy is the first subclass of the hierarchies - if (len(hierarchy.__mro__) > 2) and (subclass_type == None): + if (len(hierarchy.__mro__) > 2) and (subclass_type is None): # gets highest level superclass of the class before "class" itself subclass_type = copy.deepcopy(hierarchy.__mro__[-2]) subclass_hierarchy = copy.deepcopy(hierarchy) - elif (len(hierarchy.__mro__) > 2): # checks if the given hierarchy is a subclass + elif len(hierarchy.__mro__) > 2: # checks if the given hierarchy is a subclass if hierarchy.__mro__[-2] != subclass_type: raise ValueError( - f"You have attempted to merge together variable hierarchies that subclass from different superclasses. '{subclass_hierarchy.__qualname__}' is a subclass of '{subclass_type}' and '{hierarchy.__qualname__}' is a subclass of '{hierarchy.__mro__[-2]}'.") + f"You have attempted to merge together variable hierarchies that subclass from different superclasses. '{subclass_hierarchy.__qualname__}' is a subclass of '{subclass_type}' and '{hierarchy.__qualname__}' is a subclass of '{hierarchy.__mro__[-2]}'." + ) - if subclass_hierarchy != None: # ensure that we build on the subclassed hierarchy if we have one, that way the super class information is not lost + if ( + subclass_hierarchy is not None + ): # ensure that we build on the subclassed hierarchy if we have one, that way the super class information is not lost merged_hierarchy = subclass_hierarchy else: merged_hierarchy = copy.deepcopy(hierarchies_to_merge[0]) diff --git a/aviary/utils/merge_variable_metadata.py b/aviary/utils/merge_variable_metadata.py index dc9032d9ed..619012d6d2 100644 --- a/aviary/utils/merge_variable_metadata.py +++ b/aviary/utils/merge_variable_metadata.py @@ -2,8 +2,10 @@ def almost_equal(a, b, rel_tol=1e-8, abs_tol=0.0): - """check if two floats, or two ndarray, or two dictionary are equal. Return True if they are equal.""" - if isinstance(a, (float, np.float32, np.float64)) and isinstance(b, (float, np.float32, np.float64)): + """Check if two floats, or two ndarray, or two dictionary are equal. Return True if they are equal.""" + if isinstance(a, (float, np.float32, np.float64)) and isinstance( + b, (float, np.float32, np.float64) + ): return np.isclose(a, b, rtol=rel_tol, atol=abs_tol) if isinstance(a, np.ndarray) and isinstance(b, np.ndarray): @@ -21,7 +23,7 @@ def almost_equal(a, b, rel_tol=1e-8, abs_tol=0.0): def merge_2_meta_data_dicts(dict1, dict2): - ''' + """ Combines metadata from two dictionaries into a single dictionary containing metadata of both. Performs a check to ensure that the two dictionaries don't have the same variable with conflicting @@ -42,8 +44,7 @@ def merge_2_meta_data_dicts(dict1, dict2): ------ ValueError Raises error if dict1 and dict2 have differing metadata for the same variable. - ''' - + """ dict1_keys = set(dict1.keys()) # get keys of provided dictionaries dict2_keys = set(dict2.keys()) # get keys of provided dictionaries # get keys that are unique to each dictionary @@ -55,7 +56,8 @@ def merge_2_meta_data_dicts(dict1, dict2): dict_of_unique_variables = dict( # get a dictionary of all the unique keys (and their values) from the input dictionaries - map(lambda key: (key, merged.get(key, None)), all_unique_keys)) + map(lambda key: (key, merged.get(key, None)), all_unique_keys) + ) # initialize a dictionary of the values with duplicated keys in both input dictionaries dict_of_duplicate_variables = {} @@ -66,7 +68,8 @@ def merge_2_meta_data_dicts(dict1, dict2): # throw an error if the dicts have the same key with different metadata if not almost_equal(value1, value2): raise ValueError( - f'You have attempted to merge metadata dictionaries that contain the same variable with different metadata. The offending variable present in multiple dictionaries is "{key}".') + f'You have attempted to merge metadata dictionaries that contain the same variable with different metadata. The offending variable present in multiple dictionaries is "{key}".' + ) # add the key and metadata to the dictionary of duplicate variables dict_of_duplicate_variables[key] = dict1[key] @@ -78,7 +81,7 @@ def merge_2_meta_data_dicts(dict1, dict2): def merge_meta_data(dicts_to_merge): - ''' + """ Merges the metadata of multiple Aviary metadata dictionaries into a single metadata dictionary. Checks the metadata of all the provided Aviary metadata dictionaries to see if there are identical @@ -99,7 +102,7 @@ def merge_meta_data(dicts_to_merge): ------ None No exceptions raised by this method, although other methods called within may raise exceptions. - ''' + """ merged_dict = dicts_to_merge[0] # iterate through all the dictionaries and merge them together into one, two by two diff --git a/aviary/utils/named_values.py b/aviary/utils/named_values.py index 068bea1ac2..60e485c9da 100644 --- a/aviary/utils/named_values.py +++ b/aviary/utils/named_values.py @@ -1,4 +1,4 @@ -''' +""" Define utilities for using named values with associated units. Utilities @@ -14,13 +14,15 @@ class NamedValues define a collection of named values with associated units -''' +""" + import copy from collections.abc import Collection from typing import Any, Tuple, Union from openmdao.core.constants import _UNDEFINED -from openmdao.utils.units import convert_units as _convert_units + +from aviary.utils.utils import wrapped_convert_units Units = str ValueAndUnits = Tuple[Any, Units] @@ -28,12 +30,10 @@ class NamedValues class NamedValues(Collection): - ''' - Define a collection of named values with associated units. - ''' + """Define a collection of named values with associated units.""" def __init__(self, other=None, **kwargs): - ''' + """ Initialize this collection. Notes @@ -47,13 +47,13 @@ def __init__(self, other=None, **kwargs): When initializing from keyword arguments, the mapped item must be of a type of `ValueAndUnits`. - ''' + """ self._mapping = {} self.update(other, **kwargs) def get_item(self, key, default=(None, None)) -> OptionalValueAndUnits: - ''' + """ Return the named value and its associated units. Note, this method never raises `KeyError` or `TypeError`. @@ -74,7 +74,7 @@ def get_item(self, key, default=(None, None)) -> OptionalValueAndUnits: -------- get_val set_val - ''' + """ item = self._mapping.get(key, _UNDEFINED) if item is _UNDEFINED: @@ -83,35 +83,35 @@ def get_item(self, key, default=(None, None)) -> OptionalValueAndUnits: return item def copy(self): - ''' + """ Return a copy of the instance of this class. Parameters - --------- + ---------- None Returns ------- NamedValues() - ''' + """ return copy.copy(self) def deepcopy(self): - ''' + """ Return a deep copy of the instance of this class. Parameters - --------- + ---------- None Returns ------- NamedValues() - ''' + """ return copy.deepcopy(self) def get_val(self, key, units='unitless') -> Any: - ''' + """ Return the named value in the specified units. Note, requesting a named value that does not exist will raise `KeyError`. @@ -138,7 +138,7 @@ def get_val(self, key, units='unitless') -> Any: TypeError if units of `None` were specified or units of any type other than `str` - ''' + """ self._check_units('get_val', key, units) item = self._mapping.get(key, _UNDEFINED) @@ -148,15 +148,13 @@ def get_val(self, key, units='unitless') -> Any: val, old_units = item - if isinstance(val, tuple): - val = tuple(_convert_units(v, old_units, units) for v in val) - elif old_units != units: - val = _convert_units(val, old_units, units) + if old_units != units: + val = wrapped_convert_units((val, old_units), units) return val def set_val(self, key, val, units='unitless'): - ''' + """ Update the named value and its associated units. Note, specifying units of `None` or units of any type other than `str` will raise @@ -177,25 +175,21 @@ def set_val(self, key, val, units='unitless'): ------ TypeError if units of `None` were specified or units of any type other than `str` - ''' + """ self._check_units('set_val', key, units) self._mapping[key] = (val, units) def __repr__(self): - ''' - Return a string containing a printable representation of the collection. - ''' + """Return a string containing a printable representation of the collection.""" return repr(self._mapping) def clear(self): - ''' - Remove all items from the collection. - ''' + """Remove all items from the collection.""" self._mapping.clear() def update(self, other=None, **kwargs): - ''' + """ Assign named values and their associated units found in another collection to this collection, overwriting existing items. @@ -219,7 +213,7 @@ def update(self, other=None, **kwargs): When assigning from keyword arguments, the mapped item must be of a type of `ValueAndUnits`. - ''' + """ if not (other or kwargs): return @@ -248,14 +242,14 @@ def update(self, other=None, **kwargs): set_val(key, val, units) def delete(self, key): - ''' + """ Remove the named value and its associated units. Raises ------ KeyError if the named value does not exist - ''' + """ try: del self._mapping[key] @@ -263,9 +257,7 @@ def delete(self, key): raise KeyError(f'KeyError: key not found: {key}') def __eq__(self, other): - ''' - Return whether or not this collection is equivalent to another. - ''' + """Return whether or not this collection is equivalent to another.""" collection = self._mapping if isinstance(other, type(self)): @@ -274,27 +266,21 @@ def __eq__(self, other): return collection == other def __contains__(self, key): - ''' - Return whether or not the named value exists. - ''' + """Return whether or not the named value exists.""" return key in self._mapping def __iter__(self): - ''' - Return an iterator over the `(key, (val, units))` data stored in this collection. - ''' + """Return an iterator over the `(key, (val, units))` data stored in this collection.""" items = self._mapping.items() yield from items def __len__(self): - ''' - Return the number of items in this collection. - ''' + """Return the number of items in this collection.""" return len(self._mapping) def _check_units(self, funcname, key, units): - ''' + """ If units of `None` were specified or units of any type other than `str`, raise `TypeError`. Otherwise, do nothing. @@ -308,32 +294,27 @@ def _check_units(self, funcname, key, units): units : Any the units to check - ''' - if ((units is None) or not isinstance(units, str)): + """ + if (units is None) or not isinstance(units, str): raise TypeError( - f'{self.__class__.__name__}: {funcname}({key}):' - f' unsupported units: {units}' + f'{self.__class__.__name__}: {funcname}({key}): unsupported units: {units}' ) __slots__ = ('_mapping',) +# It is weird that these are not methods - it requires us to import these in AviarValues +# just so they can be imported from that file as well. Seems unintuitive def get_keys(named_values: NamedValues): - ''' - Return a new view of the collection's names. - ''' + """Return a new view of the collection's names.""" return named_values._mapping.keys() def get_items(named_values: NamedValues): - ''' - Return a new view of the collection's `(key, (val, units))`. - ''' + """Return a new view of the collection's `(key, (val, units))`.""" return named_values._mapping.items() def get_values(named_values: NamedValues): - ''' - Return a new view of the collection's `(val, units)`. - ''' + """Return a new view of the collection's `(val, units)`.""" return named_values._mapping.values() diff --git a/aviary/utils/options.py b/aviary/utils/options.py index 9d7e30cbdd..fd87060326 100644 --- a/aviary/utils/options.py +++ b/aviary/utils/options.py @@ -23,7 +23,7 @@ def list_options(model: System, aviary_keys: list = None): if subsystem.name == '_auto_ivc': continue print(subsystem.name) - for (key, obj) in subsystem.options.items(): + for key, obj in subsystem.options.items(): if isinstance(obj, AviaryValues): aviary_options = obj print(' aviary_options:') diff --git a/aviary/utils/preprocessors.py b/aviary/utils/preprocessors.py index deec2fb94c..988299a730 100644 --- a/aviary/utils/preprocessors.py +++ b/aviary/utils/preprocessors.py @@ -1,198 +1,436 @@ +""" +Preprocessors are utility functions that handle issues with Aviary inputs before model +setup and execution. These tasks include consistency checking between related variables,. + +""" + import warnings import numpy as np -import openmdao.api as om from aviary.utils.aviary_values import AviaryValues from aviary.utils.named_values import get_keys +from aviary.utils.test_utils.variable_test import get_names_from_hierarchy +from aviary.utils.utils import isiterable +from aviary.variable_info.enums import LegacyCode, ProblemType, Verbosity from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Mission, Settings -from aviary.utils.test_utils.variable_test import get_names_from_hierarchy -def preprocess_options(aviary_options: AviaryValues, **kwargs): +# TODO document what kwargs are used, and by which preprocessors in docstring? +# TODO preprocess needed for design range vs phase_info range in sizing missions? (should be the same) +def preprocess_options(aviary_options: AviaryValues, meta_data=_MetaData, verbosity=None, **kwargs): """ - Run all preprocessors on provided AviaryValues object + Run all preprocessors on provided AviaryValues object. Parameters ---------- aviary_options : AviaryValues Options to be updated + + meta_data : dict + Variable metadata being used with this set of aviary_options """ try: engine_models = kwargs['engine_models'] except KeyError: engine_models = None - if Settings.VERBOSITY not in aviary_options: - aviary_options.set_val( - Settings.VERBOSITY, _MetaData[Settings.VERBOSITY]['default_value']) + if verbosity is None: + if Settings.VERBOSITY in aviary_options: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + else: + verbosity = meta_data[Settings.VERBOSITY]['default_value'] + aviary_options.set_val(Settings.VERBOSITY, verbosity) + + preprocess_crewpayload(aviary_options, meta_data, verbosity) + preprocess_fuel_capacities(aviary_options, verbosity) - preprocess_crewpayload(aviary_options) - preprocess_propulsion(aviary_options, engine_models) + if engine_models is not None: + preprocess_propulsion(aviary_options, engine_models, meta_data, verbosity) -def preprocess_crewpayload(aviary_options: AviaryValues): +def remove_preprocessed_options(aviary_options): + """ + Remove options whose values will be computed in the preprocessors. + + Parameters + ---------- + aviary_options : AviaryValues + Options to be updated + """ + pre_opt = [ + Aircraft.CrewPayload.NUM_FLIGHT_CREW, + Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, + Aircraft.CrewPayload.NUM_GALLEY_CREW, + Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, + ] + + for option in pre_opt: + aviary_options.delete(option) + + +def preprocess_crewpayload(aviary_options: AviaryValues, meta_data=_MetaData, verbosity=None): """ Calculates option values that are derived from other options, and are not direct inputs. This function modifies the entries in the supplied collection, and for convenience also returns the modified collection. - """ - verbosity = aviary_options.get_val(Settings.VERBOSITY) + Parameters + ---------- + aviary_options : AviaryValues + Options to be updated - # Some tests, but not all, do not correctly set default values - # # so we need to ensure all these values are available. + meta_data : dict + Variable metadata being used with this set of aviary_options - for key in ( + Verbosity, optional + Sets level of printouts for this function. + """ + # Check and process cargo variables - confirm mass method + if Settings.MASS_METHOD in aviary_options: + mass_method = aviary_options.get_val(Settings.MASS_METHOD) + else: + raise UserWarning('MASS_METHOD not specified. Cannot preprocess cargo inputs.') + + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + pax_provided = False + design_pax_provided = False + + if mass_method == LegacyCode.FLOPS: + pax_keys = [ Aircraft.CrewPayload.NUM_PASSENGERS, Aircraft.CrewPayload.NUM_FIRST_CLASS, Aircraft.CrewPayload.NUM_BUSINESS_CLASS, Aircraft.CrewPayload.NUM_TOURIST_CLASS, + ] + + design_pax_keys = [ Aircraft.CrewPayload.Design.NUM_PASSENGERS, Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, - Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS,): - if key not in aviary_options: - aviary_options.set_val(key, _MetaData[key]['default_value']) - - # Sum passenger Counts for later checks and assignments - passenger_count = 0 - for key in (Aircraft.CrewPayload.NUM_FIRST_CLASS, - Aircraft.CrewPayload.NUM_BUSINESS_CLASS, - Aircraft.CrewPayload.NUM_TOURIST_CLASS): - passenger_count += aviary_options.get_val(key) - design_passenger_count = 0 - for key in (Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, - Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, - Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS): - design_passenger_count += aviary_options.get_val(key) - - # Create summary value (num_pax) if it was not assigned by the user - # or if it was set to it's default value of zero - if passenger_count != 0 and aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) == 0: - aviary_options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, passenger_count) - if verbosity >= 2: - print("User has specified supporting values for NUM_PASSENGERS but has left NUM_PASSENGERS=0. Replacing NUM_PASSENGERS with passenger_count.") - if design_passenger_count != 0 and aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) == 0: - aviary_options.set_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, design_passenger_count) - if verbosity >= 2: - print("User has specified supporting values for Design.NUM_PASSENGERS but has left Design.NUM_PASSENGERS=0. Replacing Design.NUM_PASSENGERS with design_passenger_count.") - - num_pax = aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) - design_num_pax = aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) - - # Check summary data against individual data if individual data was entered - if passenger_count != 0 and num_pax != passenger_count: - raise om.AnalysisError( - f"ERROR: In preprocesssors.py: NUM_PASSENGERS ({aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS)}) does not equal the sum of first class + business class + tourist class passengers (total of {passenger_count}).") - if design_passenger_count != 0 and design_num_pax != design_passenger_count: - raise om.AnalysisError( - f"ERROR: In preprocesssors.py: Design.NUM_PASSENGERS ({aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS)}) does not equal the sum of design first class + business class + tourist class passengers (total of {design_passenger_count}).") - - # Fail if incorrect data sets were provided: - # have you give us enough info to determine where people were sitting vs. designed seats - if num_pax != 0 and design_passenger_count != 0 and passenger_count == 0: - raise om.AnalysisError( - f"ERROR: In preprocessor.py: The user has specified CrewPayload.NUM_PASSENGERS, and how many of what types of seats are on the aircraft." - f"However, the user has not specified where those passengers are sitting." - f"User must specify CrewPayload.FIRST_CLASS, CrewPayload.NUM_BUSINESS_CLASS, NUM_TOURIST_CLASS in aviary_values.") - # where are the people sitting? is first class full? We know how many seats are in each class. - if design_num_pax != 0 and passenger_count != 0 and design_passenger_count == 0: - raise om.AnalysisError( - f"ERROR: In preprocessor.py: The user has specified Design.NUM_PASSENGERS, and has specified how many people are sitting in each class of seats." - f"However, the user has not specified how many seats of each class exist in the aircraft." - f"User must specify Design.FIRST_CLASS, Design.NUM_BUSINESS_CLASS, Design.NUM_TOURIST_CLASS in aviary_values.") - # we don't know which classes this aircraft has been design for. How many 1st class seats are there? - - # Copy data over if only one set of data exists - # User has given detailed values for 1TB as flow and NO design values at all - if passenger_count != 0 and design_num_pax == 0 and design_passenger_count == 0: - if verbosity >= 2: - print( - "User has not input design passengers data. Assuming design is equal to as-flow passenger data.") - aviary_options.set_val( - Aircraft.CrewPayload.Design.NUM_PASSENGERS, passenger_count) - aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, - aviary_options.get_val(Aircraft.CrewPayload.NUM_FIRST_CLASS)) - aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, - aviary_options.get_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS)) - aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, - aviary_options.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS)) - # user has not supplied detailed information on design but has supplied summary information on passengers - elif num_pax != 0 and design_num_pax == 0: - if verbosity >= 2: - print("User has specified as-flown NUM_PASSENGERS but not how many passengers the aircraft was designed for in Design.NUM_PASSENGERS. Assuming they are equal.") - aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, num_pax) - elif design_passenger_count != 0 and num_pax == 0 and passenger_count == 0: + Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, + ] + else: + pax_keys = [Aircraft.CrewPayload.NUM_PASSENGERS] + + design_pax_keys = [Aircraft.CrewPayload.Design.NUM_PASSENGERS] + + for key in pax_keys: + if key in aviary_options: + # mark that the user provided any information on mission passenger count + pax_provided = True + else: + # default all non-provided passenger info to 0 + aviary_options.set_val(key, 0) + + for key in design_pax_keys: + if key in aviary_options: + # mark that the user provided any information on design passenger count + design_pax_provided = True + else: + # default all non-provided passenger info to 0 + aviary_options.set_val(key, 0) + + # no passenger info provided + if not pax_provided and not design_pax_provided: if verbosity >= 1: - print("User has specified Design.NUM_* passenger values but CrewPyaload.NUM_* has been left blank or set to zero.") - print( - "Assuming they are equal to maintain backwards compatibility with GASP and FLOPS output files.") - print("If you intended to have no passengers on this flight, please set Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS to zero in aviary_values.") - aviary_options.set_val( - Aircraft.CrewPayload.NUM_PASSENGERS, design_passenger_count) - aviary_options.set_val(Aircraft.CrewPayload.NUM_FIRST_CLASS, - aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS)) - aviary_options.set_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS, - aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS)) - aviary_options.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, - aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS)) - # user has not supplied detailed information on design but has supplied summary information on passengers - elif design_num_pax != 0 and num_pax == 0: + UserWarning( + 'No passenger information has been provided for the aircraft, assuming ' + 'that this aircraft is not designed to carry passengers.' + ) + # only mission passenger info provided + if pax_provided and not design_pax_provided: + if verbosity >= 1: + UserWarning( + 'Passenger information for the aircraft as designed was not provided. ' + 'Assuming that the design passenger count is the same as the passenger ' + 'count for the flown mission.' + ) + # set design passengers to mission passenger values + for i in range(len(pax_keys)): + mission_val = aviary_options.get_val(pax_keys[i]) + aviary_options.set_val(design_pax_keys[i], mission_val) + # only design passenger info provided + if not pax_provided and design_pax_provided: + if verbosity >= 1: + UserWarning( + 'Passenger information for the flown mission was not provided. ' + 'Assuming that the mission passenger count is the same as the design ' + 'passenger count.' + ) + # set mission passengers to design passenger values + for i in range(len(pax_keys)): + design_val = aviary_options.get_val(design_pax_keys[i]) + aviary_options.set_val(pax_keys[i], design_val) + + # check that passenger sums match individual seat class values + design_pax = aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) + mission_pax = aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) + + mission_sum = 0 + design_sum = 0 + for i in range(1, len(pax_keys)): + mission_sum += aviary_options.get_val(pax_keys[i]) + design_sum += aviary_options.get_val(design_pax_keys[i]) + + # Resolve conflicts between seat class totals and num_passengers + # Specific beats general - trust the individual class counts over the total provided, unless + # the class counts are all zero, in which case trust the total provided and assume all economy + # design num_passengers does not match sum of seat classes for design + if design_pax != design_sum: + # if sum of seat classes is zero (design pax is not), assume all economy + if design_sum == 0: + if verbosity >= 1: + UserWarning( + 'Information on seat class distribution for aircraft design was ' + 'not provided - assuming that all passengers are economy class.' + ) + aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, design_pax) + else: + if verbosity >= 1: + UserWarning( + 'Sum of all passenger classes does not equal total number of ' + 'passengers provided for aircraft design. Overriding ' + 'Aircraft.CrewPayload.Design.NUM_PASSENGERS with the sum of ' + 'passenger classes for design.' + ) + aviary_options.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, design_sum) + + # mission num_passengers does not match sum of seat classes for mission + if mission_pax != mission_sum: + # if sum of seat classes is zero (mission pax is not), assume all economy + if mission_sum == 0: + if verbosity >= 1: + UserWarning( + 'Information on seat class distribution for current mission was ' + 'not provided - assuming that all passengers are economy class.' + ) + aviary_options.set_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS, mission_pax) + else: + if verbosity >= 1: + UserWarning( + 'Sum of all passenger classes does not equal total number of ' + 'passengers provided for current mission. Overriding ' + 'Aircraft.CrewPayload.NUM_PASSENGERS with the sum of ' + 'passenger classes for the flown mission.' + ) + aviary_options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, mission_sum) + + # Check cases where mission passengers are greater than design passengers + design_pax = aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) + mission_pax = aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS) + if mission_pax > design_pax: if verbosity >= 1: - print("User has specified Design.NUM_PASSENGERS but CrewPayload.NUM_PASSENGERS has been left blank or set to zero.") - print( - "Assuming they are equal to maintain backwards compatibility with GASP and FLOPS output files.") - print("If you intended to have no passengers on this flight, please set Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS to zero in aviary_values.") - aviary_options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, design_num_pax) - - # Performe checks on the final data tables to ensure Design is always large then As-Flow - if aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS) < aviary_options.get_val(Aircraft.CrewPayload.NUM_FIRST_CLASS): - raise om.AnalysisError( - f"ERROR: In preprocesssors.py: NUM_FIRST_CLASS ({aviary_options.get_val(Aircraft.CrewPayload.NUM_FIRST_CLASS)}) is larger than the number of seats set by Design.NUM_FIRST_CLASS ({aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS)}) .") - if aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS) < aviary_options.get_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS): - raise om.AnalysisError( - f"ERROR: In preprocesssors.py: NUM_BUSINESS_CLASS ({aviary_options.get_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS)}) is larger than the number of seats set by Design.NUM_BUSINESS_CLASS ({aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS)}) .") - if aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS) < aviary_options.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS): - raise om.AnalysisError( - f"ERROR: In preprocesssors.py: NUM_TOURIST_CLASS ({aviary_options.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS)}) is larger than the number of seats set by Design.NUM_TOURIST_CLASS ({aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS)}) .") - if aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) < aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS): - raise om.AnalysisError( - f"ERROR: In preprocesssors.py: NUM_PASSENGERS ({aviary_options.get_val(Aircraft.CrewPayload.NUM_PASSENGERS)}) is larger than the number of seats set by Design.NUM_PASSENGERS ({aviary_options.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS)}) .") + UserWarning( + f'The aircraft is designed for {design_pax} passengers but the current ' + f'mission is being flown with {mission_pax} passengers. The mission ' + 'will be flown using the mass of these extra passengers and baggage, ' + 'but this mission may not be realistic due to lack of room.' + ) + + if mass_method == LegacyCode.FLOPS: + # First Class + if aviary_options.get_val( + Aircraft.CrewPayload.Design.NUM_FIRST_CLASS + ) < aviary_options.get_val(Aircraft.CrewPayload.NUM_FIRST_CLASS): + if verbosity >= 1: + UserWarning( + 'More first class passengers are flying in this mission than there are ' + 'available first class seats on the aircraft. Assuming these passengers ' + 'have the same mass as other first class passengers, but are sitting in ' + 'different seats.' + ) + # Business Class + if aviary_options.get_val( + Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS + ) < aviary_options.get_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS): + if verbosity >= 1: + UserWarning( + 'More business class passengers are flying in this mission than there are ' + 'available business class seats on the aircraft. Assuming these passengers ' + 'have the same mass as other business class passengers, but are sitting in ' + 'different seats.' + ) + # Economy Class + if aviary_options.get_val( + Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS + ) < aviary_options.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS): + if verbosity >= 1: + UserWarning( + 'More tourist class passengers are flying in this mission than there are ' + 'available tourist class seats on the aircraft. Assuming these passengers ' + 'have the same mass as other tourist class passengers, but are sitting in ' + 'different seats.' + ) + + # Process GASP based cargo variables + if mass_method == LegacyCode.GASP: + try: + cargo = aviary_options.get_val(Aircraft.CrewPayload.CARGO_MASS, 'lbm') + except KeyError: + cargo = None + try: + max_cargo = aviary_options.get_val(Aircraft.CrewPayload.Design.MAX_CARGO_MASS, 'lbm') + except KeyError: + max_cargo = None + try: + des_cargo = aviary_options.get_val(Aircraft.CrewPayload.Design.CARGO_MASS, 'lbm') + except KeyError: + des_cargo = None + + if Settings.PROBLEM_TYPE in aviary_options: + problem_type = aviary_options.get_val(Settings.PROBLEM_TYPE) + else: + problem_type = ProblemType.SIZING + + if cargo is not None: + if max_cargo is not None: + if des_cargo is not None: + if problem_type == ProblemType.SIZING and cargo != des_cargo: + # user has set all three check if self consistent + cargo = des_cargo + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + f'Aircraft.CrewPayload.CARGO_MASS ({cargo}) does not equal ' + f'Aircraft.CrewPayload.Design.CARGO_MASS ({des_cargo}) for SIZING ' + 'mission. Setting as-flown CARGO_MASS equal to Design.CARGO_MASS ' + f'({des_cargo})' + ) + else: + # user has set cargo & max: assume des = max + des_cargo = max_cargo + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + 'Aircraft.CrewPayload.Design.CARGO_MASS missing, assume ' + f'Design.CARGO_MASS = Design.MAX_CARGO_MASS ({max_cargo})' + ) + elif des_cargo is not None: + # user has set cargo & des: assume max = des + max_cargo = des_cargo + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + 'Aircraft.CrewPayload.Design.MAX_CARGO_MASS is missing, assuming ' + f'Design.MAX_CARGO_MASS equals Design.CARGO_MASS ({des_cargo})' + ) + else: + # user has set cargo only: assume design and max cargo is equal to flown cargo + des_cargo = max_cargo = cargo + + elif max_cargo is not None: + if des_cargo is not None: + # user has set max & des: assume flown = 0 + cargo = 0 + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG: + warnings.warn( + 'Aircraft.CrewPayload.CARGO_MASS is missing, assuming CARGO_MASS = 0' + ) + else: + # user has set max only: assume flown = des = 0 + cargo = des_cargo = 0 + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG: + warnings.warn( + 'Aircraft.CrewPayload.CARGO_MASS and Aircraft.CrewPayload.Design.CARGO_MASS ' + 'missing, assume CARGO_MASS and Design.CARGO_MASS = 0. No Cargo is flown on ' + 'mission.' + ) + + elif des_cargo is not None: + # user has only input des: assume max = des and flown = 0 + max_cargo = des_cargo + cargo = 0 + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG: + warnings.warn( + 'Aircraft.CrewPayload.CARGO_MASS and Aircraft.CrewPayload.Design.MAX_CARGO_MASS ' + 'missing, assume CARGO_MASS = 0 and Design.MAX_CARGO_MASS = Design.CARGO_MASS ' + f'({des_cargo}).' + ) + else: + # user has input no cargo information + cargo = max_cargo = des_cargo = 0 + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG: + warnings.warn( + 'No CARGO variables detected, assume CARGO_MASS, Design.MAX_CARGO_MASS, and ' + 'Design.CARGO_MASS equal to 0.' + ) + + if cargo > max_cargo or des_cargo > max_cargo: + raise UserWarning( + f'Aircraft.CrewPayload.CARGO_MASS ({cargo}) and/or ' + f'Aircraft.CrewPayload.Design.CARGO_MASS ({des_cargo}) is greater than' + f'Aircraft.CrewPayload.Design.MAX_CARGO_MASS ({max_cargo})' + ) + + # calculate passenger mass with bags based on user inputs. + try: + pax_mass_with_bag = aviary_options.get_val( + Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, 'lbm' + ) + except KeyError: + pax_mass = aviary_options.get_val(Aircraft.CrewPayload.MASS_PER_PASSENGER, 'lbm') + bag_mass = aviary_options.get_val( + Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, 'lbm' + ) + pax_mass_with_bag = pax_mass + bag_mass + aviary_options.set_val( + Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, pax_mass_with_bag, 'lbm' + ) + + # calculate and check total payload + # NOTE this is only used for error messaging the calculations for analysis are subsystems/mass/gasp_based + design_passenger_payload_mass = design_pax * pax_mass_with_bag + max_payload = design_passenger_payload_mass + max_cargo + as_flown_passenger_payload_mass = mission_pax * pax_mass_with_bag + as_flown_payload = as_flown_passenger_payload_mass + cargo + if as_flown_payload > max_payload and verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + f'As-flown payload ({as_flown_payload}) is greater than maximum payload ' + f'({max_payload}). The aircraft will be undersized for this payload!' + ) + + # set assumed cargo mass variables: + aviary_options.set_val(Aircraft.CrewPayload.CARGO_MASS, cargo, 'lbm') + aviary_options.set_val(Aircraft.CrewPayload.Design.MAX_CARGO_MASS, max_cargo, 'lbm') + aviary_options.set_val(Aircraft.CrewPayload.Design.CARGO_MASS, des_cargo, 'lbm') + + # Check flight attendants if Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS not in aviary_options: flight_attendants_count = 0 # assume no passengers - if 0 < passenger_count: - if passenger_count < 51: + if 0 < design_pax: + if design_pax < 51: flight_attendants_count = 1 else: - flight_attendants_count = passenger_count // 40 + 1 + flight_attendants_count = design_pax // 40 + 1 - aviary_options.set_val( - Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, flight_attendants_count) + aviary_options.set_val(Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, flight_attendants_count) if Aircraft.CrewPayload.NUM_GALLEY_CREW not in aviary_options: galley_crew_count = 0 # assume no passengers - if 150 < passenger_count: - galley_crew_count = passenger_count // 250 + 1 + if 150 < design_pax: + galley_crew_count = design_pax // 250 + 1 aviary_options.set_val(Aircraft.CrewPayload.NUM_GALLEY_CREW, galley_crew_count) if Aircraft.CrewPayload.NUM_FLIGHT_CREW not in aviary_options: flight_crew_count = 3 - if passenger_count < 151: + if design_pax < 151: flight_crew_count = 2 aviary_options.set_val(Aircraft.CrewPayload.NUM_FLIGHT_CREW, flight_crew_count) - if (Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER not in aviary_options and - Mission.Design.RANGE in aviary_options): + if ( + Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER not in aviary_options + and Mission.Design.RANGE in aviary_options + ): design_range = aviary_options.get_val(Mission.Design.RANGE, 'nmi') if design_range <= 900.0: @@ -202,19 +440,104 @@ def preprocess_crewpayload(aviary_options: AviaryValues): else: baggage_mass_per_pax = 44.0 - aviary_options.set_val(Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, - val=baggage_mass_per_pax, units='lbm') + aviary_options.set_val( + Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, + val=baggage_mass_per_pax, + units='lbm', + ) return aviary_options -def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = None): - ''' - Updates AviaryValues object with values taken from provided EngineModels. +def preprocess_fuel_capacities(aviary_options: AviaryValues, verbosity=None): + """ + Preprocesses the AviaryValues object to ensure the user has provided a consistent set of fuel capacity overrides. - If no EngineModels are provided, either in engine_models or included in - aviary_options, an EngineDeck is created using avaliable inputs and options in - aviary_options. + Parameters + ---------- + aviary_options : AviaryValues + Options to be updated + + """ + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + + if Settings.MASS_METHOD in aviary_options: + mass_method = aviary_options.get_val(Settings.MASS_METHOD) + else: + raise UserWarning('MASS_METHOD not specified. Cannot preprocess fuel capacity inputs.') + + if mass_method == LegacyCode.FLOPS: + # find which fuel capacity variables the user has set: + if Aircraft.Fuel.TOTAL_CAPACITY not in aviary_options: + # Aviary will need to calculate the total capacity and can only do so if we assume any missing subsystem capacities are zero + if Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY not in aviary_options: + aviary_options.set_val(Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 0.0, 'lbm') + if verbosity >= Verbosity.VERBOSE: + warnings.warn(f'Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY is missing assume = 0') + + if Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY not in aviary_options: + aviary_options.set_val(Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 0.0, 'lbm') + if verbosity >= Verbosity.VERBOSE: + warnings.warn(f'Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY is missing assume = 0') + else: + total_capacity = aviary_options.get_val(Aircraft.Fuel.TOTAL_CAPACITY, 'lbm') + try: + wing_capacity = aviary_options.get_val(Aircraft.Fuel.WING_FUEL_CAPACITY, 'lbm') + except KeyError: + wing_capacity = None + try: + fuselage_capacity = aviary_options.get_val( + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, 'lbm' + ) + except KeyError: + fuselage_capacity = None + try: + auxiliary_capacity = aviary_options.get_val( + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, 'lbm' + ) + except KeyError: + auxiliary_capacity = None + + capacity_count = sum( + 1 + for capacity in [wing_capacity, fuselage_capacity, auxiliary_capacity] + if capacity is not None + ) + capacity_check = sum( + capacity + for capacity in [wing_capacity, fuselage_capacity, auxiliary_capacity] + if capacity is not None + ) + + # check if the user inputs are self consistent (as far as possible at this stage!) Aviary can still calculate -ve outputs at runtime. + if capacity_count == 3 and capacity_check != total_capacity: + raise UserWarning( + f'Aircraft.Fuel.TOTAL_CAPACITY ({total_capacity}) != Aircraft.Fuel.WING_FUEL_CAPACITY ({wing_capacity})' + f'+ Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY ({fuselage_capacity}) + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY ({auxiliary_capacity})' + f' = {capacity_check}' + ) + elif capacity_count < 3 and capacity_check > total_capacity: + raise UserWarning( + f'Aircraft.Fuel.TOTAL_CAPACITY ({total_capacity}) < Aircraft.Fuel.WING_FUEL_CAPACITY ({wing_capacity})' + f' + Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY ({fuselage_capacity}) + Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY ({auxiliary_capacity})' + f' = {capacity_check}' + ) + + return aviary_options + + +def preprocess_propulsion( + aviary_options: AviaryValues, + engine_models: list = None, + meta_data=_MetaData, + verbosity=None, +): + """ + Updates AviaryValues object with values taken from provided EngineModels. Vectorizes variables in aviary_options in the correct order for vehicles with heterogeneous engines. @@ -234,8 +557,16 @@ def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = No engine_models : (optional) EngineModel objects to be added to aviary_options. Replaced existing EngineModels in aviary_options - ''' - # TODO add verbosity check to warnings + """ + if verbosity is not None: + # compatibility with being passed int for verbosity + verbosity = Verbosity(verbosity) + else: + if verbosity in aviary_options: + verbosity = aviary_options.get_val(Settings.VERBOSITY) + else: + verbosity = Verbosity.BRIEF + ############################## # Vectorize Engine Variables # ############################## @@ -257,87 +588,81 @@ def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = No # to engines (defined by _get_engine_variables()) for var in _get_engine_variables(): if var in update_list: - dtype = _MetaData[var]['types'] - default_value = _MetaData[var]['default_value'] - # type is optionally specified, fall back to type of default value - if dtype is None: - if isinstance(default_value, np.ndarray): - dtype = default_value.dtype - elif default_value is None: - # With no default value, we cannot determine a dtype. - dtype = None - else: + dtype = meta_data[var]['types'] + default_value = meta_data[var]['default_value'] + multivalue = meta_data[var]['multivalue'] + units = meta_data[var]['units'] + + # If dtype has multiple options, prefer type of default value + # Otherwise, use the first type in the tuple + if isinstance(dtype, tuple): + if default_value is not None: dtype = type(default_value) - - # if dtype has multiple options, use type of default value - elif isinstance(dtype, (list, tuple)): - # if default value is a list/tuple, find type inside that - if isinstance(default_value, (list, tuple)): - dtype = type(default_value[0]) - elif default_value is None: - # With no default value, we cannot determine a dtype. - dtype = None else: - dtype = type(default_value) + dtype = dtype[0] - # if var is supposed to be a unique array per engine model, assemble flat - # vector manually to avoid ragged arrays (such as for wing engine locations) - if isinstance(default_value, (list, np.ndarray)): - vec = np.zeros(0, dtype=dtype) - elif type(default_value) is tuple: - vec = () + if isiterable(meta_data[var]['types']): + typeset = meta_data[var]['types'] else: - vec = [default_value] * num_engine_type + typeset = (meta_data[var]['types'],) + + # Variables are multidimensional if their base types have iterables, and are + # flagged as `multivalue` + multidimensional = set(typeset) & set((list, tuple, np.ndarray)) and multivalue + + # vec is where the vectorized engine data is stored - always a list right + # now, converted to other types like np array later + vec = [] + + # Vectorize variable "var" from available sources # - units = _MetaData[var]['units'] + # If var is supposed to be a unique array per engine model, assemble flat + # vector manually to avoid ragged arrays (such as for wing engine locations) - # priority order is (checked per engine): + # Priority order is (checked per engine): # 1. EngineModel.options # 2. aviary_options # 3. default value from metadata for i, engine in enumerate(engine_models): # test to see if engine has this variable - if so, use it try: - # variables in engine models are known to be "safe", will only + # variables in engine models are trusted to be "safe", and only # contain data for that engine engine_val = engine.get_val(var, units) - if isinstance(default_value, (list, np.ndarray)): - vec = np.append(vec, engine_val) - elif isinstance(default_value, tuple): - vec = vec + (engine_val,) - else: - vec[i] = engine_val # if the variable is not in the engine model, pull from aviary options except KeyError: # check if variable is defined in aviary options (for this engine's # index) - if so, use it try: aviary_val = aviary_options.get_val(var, units) - # if aviary_val is an iterable, just grab val for this engine - if isinstance(aviary_val, (list, np.ndarray, tuple)): - aviary_val = aviary_val[i] - if isinstance(default_value, (list, np.ndarray)): - vec = np.append(vec, aviary_val) - elif isinstance(default_value, tuple): - vec = vec + (aviary_val,) - else: - vec[i] = aviary_val - # if not, use default value from _MetaData + # if the variable is not in aviary_options, use default from metadata except (KeyError, IndexError): - if isinstance(default_value, (list, np.ndarray)): - vec = np.append(vec, default_value) + vec.append(default_value) + else: + # save value from aviary_options + if isiterable(aviary_val): + if multidimensional: + vec.extend(aviary_val) + else: + # if aviary_val is an iterable, just grab val for this engine + vec.append(aviary_val[i]) else: - # default value is aleady in array - continue + vec.append(aviary_val) + else: + # save value from EngineModel + if isiterable(engine_val) and multidimensional: + vec.extend(engine_val) + else: + vec.append(engine_val) # TODO update each engine's options with "new" values? Allows each engine # to have a copy of all options/inputs, beyond what it was # originally initialized with - # update aviary options and outputs with new vectors - # if data is numerical, store in a numpy array - # keep tuples as tuples, lists get converted to numpy arrays - if type(vec[0]) in (int, float, np.int64, np.float64)\ - and type(vec) is not tuple: + # Update aviary options with new vectors + # If data is numerical, store in a numpy array, else use a list + # Some machines default to specific-bit np array types, so we have to + # check for those too + if type(vec[0]) in (int, float, np.int32, np.int64, np.float32, np.float64): vec = np.array(vec, dtype=dtype) aviary_options.set_val(var, vec, units) @@ -350,8 +675,7 @@ def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = No except KeyError: num_engines_all = np.zeros(num_engine_type).astype(int) try: - num_fuse_engines_all = aviary_options.get_val( - Aircraft.Engine.NUM_FUSELAGE_ENGINES) + num_fuse_engines_all = aviary_options.get_val(Aircraft.Engine.NUM_FUSELAGE_ENGINES) except KeyError: num_fuse_engines_all = np.zeros(num_engine_type).astype(int) try: @@ -360,38 +684,67 @@ def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = No num_wing_engines_all = np.zeros(num_engine_type).astype(int) for i, engine in enumerate(engine_models): + eng_name = engine.name num_engines = num_engines_all[i] num_fuse_engines = num_fuse_engines_all[i] num_wing_engines = num_wing_engines_all[i] total_engines_calc = num_fuse_engines + num_wing_engines - # if engine mount type is not specified at all, default to wing + # If engine mount type is not specified at all, default to wing (unless there is + # only one engine, in which case default to fuselage) if total_engines_calc == 0: - eng_name = engine.name - num_wing_engines_all[i] = num_engines - # TODO is a warning overkill here? It can be documented wing mounted engines - # are assumed default - warnings.warn( - f'Mount location for engines of type <{eng_name}> not specified. ' - 'Wing-mounted engines are assumed.') + if num_engines > 1: + num_wing_engines_all[i] = num_engines + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + f'Mount location for engines of type <{eng_name}> not ' + 'specified. Wing-mounted engines are assumed.' + ) + else: + num_fuse_engines_all[i] = num_engines + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + f'Mount location for single engine of type <{eng_name}> not ' + 'specified. Assuming it is fuselage-mounted.' + ) # If wing mount type are specified but inconsistent, handle it elif total_engines_calc > num_engines: # more defined engine locations than number of engines - increase num engines - eng_name = engine.name num_engines_all[i] = total_engines_calc - warnings.warn( - 'Sum of aircraft:engine:num_fueslage_engines and ' - 'aircraft:engine:num_wing_engines do not match ' - f'aircraft:engine:num_engines for EngineModel <{eng_name}>. Overwriting ' - 'with the sum of wing and fuselage mounted engines.') + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + 'Sum of user-specified fuselage-mounted and wing-mounted engines do ' + f'not match total number of engines for EngineModel <{eng_name}>. ' + 'Overwriting total number of engines with the sum of wing and ' + 'fuselage mounted engines.' + ) elif total_engines_calc < num_engines: # fewer defined locations than num_engines - assume rest are wing mounted - eng_name = engine.name - num_wing_engines_all[i] = num_engines - num_fuse_engines - warnings.warn( - 'Mount location was not defined for all engines of EngineModel ' - f'<{eng_name}> - unspecified engines are assumed wing-mounted.') + # (unless there is just one prospective wing engine, then fuselage mount it) + num_unspecified_engines = num_engines - num_fuse_engines - num_wing_engines + if num_unspecified_engines > 1: + num_wing_engines_all[i] = num_wing_engines + num_unspecified_engines + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + 'Mount location was not defined for all engines of EngineModel ' + f'<{eng_name}> - unspecified engines are assumed wing-mounted.' + ) + elif num_unspecified_engines == 1 and num_wing_engines != 0: + num_fuse_engines_all[i] = num_fuse_engines + num_unspecified_engines + if verbosity >= Verbosity.BRIEF: # BRIEF, VERBOSE, DEBUG + warnings.warn( + 'Mount location was not defined for all engine of EngineModel ' + f'<{eng_name}> - unspecified engine is assumed fuselage-mounted.' + ) + + if num_wing_engines % 2 == 1: + if verbosity >= Verbosity.VERBOSE: # VERBOSE, DEBUG + warnings.warn( + 'Odd number of wing engines are specified for EngineModel ' + f'<{eng_name}> - this may cause issues with some mass and geometry ' + 'components that assume symmetric wing engine distribution.' + ) aviary_options.set_val(Aircraft.Engine.NUM_ENGINES, num_engines_all) aviary_options.set_val(Aircraft.Engine.NUM_WING_ENGINES, num_wing_engines_all) @@ -406,18 +759,13 @@ def preprocess_propulsion(aviary_options: AviaryValues, engine_models: list = No total_num_wing_engines = int(sum(num_wing_engines_all)) # compute propulsion-level engine count totals here - aviary_options.set_val( - Aircraft.Propulsion.TOTAL_NUM_ENGINES, total_num_engines) - aviary_options.set_val( - Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, total_num_fuse_engines) - aviary_options.set_val( - Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, total_num_wing_engines) + aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_ENGINES, total_num_engines) + aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, total_num_fuse_engines) + aviary_options.set_val(Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, total_num_wing_engines) def _get_engine_variables(): - ''' - Yields all propulsion-related variables in Aircraft that need to be vectorized - ''' + """Yields all propulsion-related variables in Aircraft that need to be vectorized.""" for item in get_names_from_hierarchy(Aircraft.Engine): yield item diff --git a/aviary/utils/process_input_decks.py b/aviary/utils/process_input_decks.py index 634b211405..0eb776d278 100644 --- a/aviary/utils/process_input_decks.py +++ b/aviary/utils/process_input_decks.py @@ -1,11 +1,12 @@ """ -This module, process_input_decks.py, is responsible for reading vehicle input decks, initializing options, -and setting initial guesses for aircraft design parameters. It works primarily with .csv files, -allowing for the specification of units, comments, and lists within these files. +This module, process_input_decks.py, is responsible for reading vehicle input decks, initializing +options, and setting initial guesses for aircraft design parameters. It works primarily with .csv +files, allowing for the specification of units, comments, and lists within these files. -The module supports various functions like creating a vehicle, parsing input files, updating options based -on inputs, and handling initial guesses for different aircraft design aspects. It heavily relies on the -aviary and openMDAO libraries for processing and interpreting the aircraft design parameters. +The module supports various functions like creating a vehicle, parsing input files, updating options +based on inputs, and handling initial guesses for different aircraft design aspects. It heavily +relies on the aviary and openMDAO libraries for processing and interpreting the aircraft design +parameters. Functions: create_vehicle(vehicle_deck=''): Create and initialize a vehicle with default or specified parameters. @@ -22,48 +23,70 @@ from openmdao.utils.units import valid_units from aviary.utils.aviary_values import AviaryValues, get_keys -from aviary.utils.functions import convert_strings_to_data, set_value -from aviary.variable_info.options import get_option_defaults +from aviary.utils.functions import convert_strings_to_data, get_path from aviary.variable_info.enums import ProblemType, Verbosity from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft, Mission, Settings -from aviary.utils.functions import get_path - -operation_dict = {"<": lt, "<=": le, "==": eq, "!=": ne, - ">=": ge, ">": gt, "isinstance": isinstance} -problem_types = {'sizing': ProblemType.SIZING, - 'alternate': ProblemType.ALTERNATE, 'fallout': ProblemType.FALLOUT} - - -def create_vehicle(vehicle_deck='', meta_data=_MetaData, verbosity=None): +operation_dict = { + '<': lt, + '<=': le, + '==': eq, + '!=': ne, + '>=': ge, + '>': gt, + 'isinstance': isinstance, +} +problem_types = { + 'sizing': ProblemType.SIZING, + 'alternate': ProblemType.ALTERNATE, + 'fallout': ProblemType.FALLOUT, +} + + +def create_vehicle(vehicle_deck='', meta_data=_MetaData, verbosity=Verbosity.BRIEF): """ Creates and initializes a vehicle with default or specified parameters. It sets up the aircraft values and initial guesses based on the input from the vehicle deck. Parameters ---------- - vehicle_deck (str): - Path to the vehicle deck file. Default is an empty string. + vehicle_deck (str, AviaryValues): + Path to the vehicle deck file, or an AviaryValues object that contains aircraft + inputs. Default is an empty string. meta_data (dict): Variable metadata used when reading input file for unit validation, - default values, and other checks + default values, and other checks. + verbosity (int, Verbosity): + Verbosity level for the AviaryProblem. If provided, this overrides verbosity + specified in the aircraft data. Default is None, and verbosity will be taken + from aircraft data or defaulted to Verbosity.BRIEF if not found. Returns ------- (aircraft_values, initialization_guesses): (tuple) Returns a tuple containing aircraft values and initial guesses. """ - aircraft_values = get_option_defaults(engine=False) + if verbosity is None: + verbosity = Verbosity.BRIEF + + aircraft_values = AviaryValues() # TODO remove all hardcoded GASP values here, find appropriate place for them + # We should only set FLOPS- or GASP-specific variables for those aircraft models aircraft_values.set_val('INGASP.JENGSZ', val=4) aircraft_values.set_val('test_mode', val=False) aircraft_values.set_val('use_surrogates', val=True) aircraft_values.set_val('mass_defect', val=10000, units='lbm') - # TODO problem_type should get set by get_option_defaults?? + + # TODO setting defaults for variables needed outside OM problem during load_inputs() aircraft_values.set_val(Settings.PROBLEM_TYPE, val=ProblemType.SIZING) - aircraft_values.set_val(Aircraft.Electrical.HAS_HYBRID_SYSTEM, val=False) + aircraft_values.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, val=0) + aircraft_values.set_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, val=0, units='lbm') + aircraft_values.set_val(Aircraft.Design.RESERVE_FUEL_FRACTION, val=0) + # these are used in initialization_guessing() + aircraft_values.set_val(Mission.Design.CRUISE_ALTITUDE, val=25000.0, units='ft') + aircraft_values.set_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, val=0, units='lbm') initialization_guesses = { # initialization_guesses is a dictionary that contains values used to initialize the trajectory @@ -75,7 +98,7 @@ def create_vehicle(vehicle_deck='', meta_data=_MetaData, verbosity=None): 'flight_duration': 0, 'time_to_climb': 0, 'climb_range': 0, - 'reserves': 0 + 'reserves': 0, } if isinstance(vehicle_deck, AviaryValues): @@ -84,23 +107,36 @@ def create_vehicle(vehicle_deck='', meta_data=_MetaData, verbosity=None): initialization_guesses[key.removeprefix('initialization_guesses:')] = val aircraft_values.update(vehicle_deck) else: - vehicle_deck = get_path(vehicle_deck) + if verbosity >= Verbosity.BRIEF: + verbose = True + else: + verbose = False + vehicle_deck = get_path(vehicle_deck, verbose) aircraft_values, initialization_guesses = parse_inputs( - vehicle_deck=vehicle_deck, aircraft_values=aircraft_values, initialization_guesses=initialization_guesses, meta_data=meta_data) + vehicle_deck=vehicle_deck, + aircraft_values=aircraft_values, + initialization_guesses=initialization_guesses, + meta_data=meta_data, + ) # make sure verbosity is always set - # if verbosity set via parameter, use that + # if verbosity set via parameter, use that - override what is in the file if verbosity is not None: # Enum conversion here, so user can pass either number or actual Enum as parameter aircraft_values.set_val(Settings.VERBOSITY, Verbosity(verbosity)) # else, if verbosity not specified anywhere, use default of BRIEF elif verbosity is None and Settings.VERBOSITY not in aircraft_values: - aircraft_values.set_val(Settings.VERBOSITY, Verbosity.BRIEF) + aircraft_values.set_val(Settings.VERBOSITY, _MetaData[Settings.VERBOSITY]['default_value']) return aircraft_values, initialization_guesses -def parse_inputs(vehicle_deck, aircraft_values: AviaryValues = None, initialization_guesses=None, meta_data=_MetaData): +def parse_inputs( + vehicle_deck, + aircraft_values: AviaryValues = None, + initialization_guesses=None, + meta_data=_MetaData, +): """ Parses the input files and updates the aircraft values and initial guesses. The function reads the vehicle deck file, processes each line, and updates the aircraft_values object based on the data found. @@ -117,7 +153,6 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues = None, initializat """ if aircraft_values is None: aircraft_values = AviaryValues() - aircraft_values.set_val(Settings.VERBOSITY, Verbosity.BRIEF) if initialization_guesses is None: initialization_guesses = {} @@ -126,7 +161,7 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues = None, initializat with open(vehicle_deck, newline='') as f_in: for line in f_in: - used, data_units = False, None + data_units = None tmp = [*line.split('#', 1), ''] line, comment = tmp[0], tmp[1] # anything after the first # is a comment @@ -148,42 +183,45 @@ def parse_inputs(vehicle_deck, aircraft_values: AviaryValues = None, initializat # if the last element is a unit, remove it from the list and update the variable's units data_units = data_list.pop() - is_array = False - if '[' in data_list[0]: - is_array = True - - var_values = convert_strings_to_data(data_list) + var_value = convert_strings_to_data(data_list) + # If var_value is length 1 list and is not supposed to be a list, pull out + # individual value. Otherwise, convert list to numpy array + if len(var_value) <= 1: + if var_name in meta_data and meta_data[var_name]['multivalue']: + # if data is numeric, convert to numpy array + if isinstance(var_value[0], (int, float)): + var_value = np.array(var_value) + else: + var_value = var_value[0] if var_name in meta_data.keys(): - aircraft_values = set_value( - var_name, var_values, aircraft_values, units=data_units, is_array=is_array, meta_data=meta_data) + if data_units is None: + data_units = meta_data[var_name]['units'] + aircraft_values.set_val(var_name, var_value, data_units, meta_data) continue elif var_name in guess_names: # all initial guesses take only a single value # get values from supplied dictionary - initialization_guesses[var_name] = float(var_values[0]) + initialization_guesses[var_name] = var_value continue elif var_name.startswith('initialization_guesses:'): - # get values labelled as initialization_guesses in .csv input file - initialization_guesses[var_name.removeprefix( - 'initialization_guesses:')] = float(var_values[0]) + # get values labeled as initialization_guesses in .csv input file + initialization_guesses[var_name.removeprefix('initialization_guesses:')] = var_value continue - elif ":" in var_name: + elif ':' in var_name: warnings.warn( f"Variable '{var_name}' is not in meta_data nor in 'guess_names'. " - "It will be ignored.", + 'It will be ignored.', UserWarning, ) continue - if aircraft_values.get_val(Settings.VERBOSITY) >= Verbosity.VERBOSE: - print('Unused:', var_name, var_values, comment) - return aircraft_values, initialization_guesses + # TODO this should be a preprocessor, and tasks split to be specific to subsystem # e.g. aero preprocessor, mass preprocessor, 2DOF preprocessor, etc. @@ -206,22 +244,19 @@ def update_GASP_options(aircraft_values: AviaryValues): ## STRUT AND FOLD ## if not aircraft_values.get_val(Aircraft.Wing.HAS_STRUT): - aircraft_values.set_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=False) + aircraft_values.set_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, val=False) if aircraft_values.get_val(Aircraft.Wing.HAS_FOLD): if not aircraft_values.get_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION): - aircraft_values.set_val( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True) + aircraft_values.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=True) else: - dim_loc_spec = aircraft_values.get_val( - Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED) + dim_loc_spec = aircraft_values.get_val(Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED) aircraft_values.set_val( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=dim_loc_spec) + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=dim_loc_spec + ) else: aircraft_values.set_val(Aircraft.Wing.CHOOSE_FOLD_LOCATION, val=True) - aircraft_values.set_val( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=False) + aircraft_values.set_val(Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, val=False) if aircraft_values.get_val(Settings.VERBOSITY) >= Verbosity.VERBOSE: print('\nOptions') @@ -253,13 +288,19 @@ def update_dependent_options(aircraft_values: AviaryValues, dependent_options): # dependency is a dictionary that contains the target option, the relationship to the variable and the output values if dependency['relation'] in operation_dict: comp = operation_dict[dependency['relation']] - outcome = dependency['result'] if comp( - var_value, dependency['val']) else dependency['alternate'] - elif dependency['relation'] == "in": - outcome = dependency['result'] if var_value in dependency['val'] else dependency['alternate'] + outcome = ( + dependency['result'] + if comp(var_value, dependency['val']) + else dependency['alternate'] + ) + elif dependency['relation'] == 'in': + outcome = ( + dependency['result'] + if var_value in dependency['val'] + else dependency['alternate'] + ) else: - warnings.warn(dependency['relation'] + - ' is not a valid selection') + warnings.warn(dependency['relation'] + ' is not a valid selection') aircraft_values.set_val(dependency['target'], val=outcome) return aircraft_values @@ -287,25 +328,28 @@ def initialization_guessing(aircraft_values: AviaryValues, initialization_guesse """ problem_type = aircraft_values.get_val(Settings.PROBLEM_TYPE) num_pax = aircraft_values.get_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS) - reserve_val = aircraft_values.get_val( - Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm') - reserve_frac = aircraft_values.get_val( - Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless') + reserve_val = aircraft_values.get_val(Aircraft.Design.RESERVE_FUEL_ADDITIONAL, units='lbm') + reserve_frac = aircraft_values.get_val(Aircraft.Design.RESERVE_FUEL_FRACTION, units='unitless') if initialization_guesses['fuel_burn_per_passenger_mile'] <= 0: initialization_guesses['fuel_burn_per_passenger_mile'] = 0.1 reserves = initialization_guesses['reserves'] if reserves < 0.0: - raise ValueError( - 'initialization_guesses["reserves"] must be greater than or equal to 0.') + raise ValueError('initialization_guesses["reserves"] must be greater than or equal to 0.') elif reserves == 0: reserves += reserve_val - reserves += (reserve_frac * (num_pax * initialization_guesses['fuel_burn_per_passenger_mile'] * - aircraft_values.get_val(Mission.Design.RANGE, units='NM'))) + reserves += reserve_frac * ( + num_pax + * initialization_guesses['fuel_burn_per_passenger_mile'] + * aircraft_values.get_val(Mission.Design.RANGE, units='NM') + ) elif reserves < 10: - reserves *= (num_pax * initialization_guesses['fuel_burn_per_passenger_mile'] * - aircraft_values.get_val(Mission.Design.RANGE, units='NM')) + reserves *= ( + num_pax + * initialization_guesses['fuel_burn_per_passenger_mile'] + * aircraft_values.get_val(Mission.Design.RANGE, units='NM') + ) initialization_guesses['reserves'] = reserves @@ -315,45 +359,59 @@ def initialization_guessing(aircraft_values: AviaryValues, initialization_guesse mission_mass = aircraft_values.get_val(Mission.Design.GROSS_MASS, units='lbm') if Mission.Summary.CRUISE_MASS_FINAL in aircraft_values: - cruise_mass_final = aircraft_values.get_val( - Mission.Summary.CRUISE_MASS_FINAL, units='lbm') + cruise_mass_final = aircraft_values.get_val(Mission.Summary.CRUISE_MASS_FINAL, units='lbm') else: cruise_mass_final = initialization_guesses['cruise_mass_final'] # takeoff mass not given if mission_mass <= 0: if problem_type == ProblemType.ALTERNATE: - fuel_mass = num_pax * ( - initialization_guesses['fuel_burn_per_passenger_mile'] * aircraft_values.get_val(Mission.Design.RANGE, units='NM')) + reserves - mission_mass = initialization_guesses['operating_empty_mass'] + ( - num_pax * aircraft_values.get_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, units='lbm')) + fuel_mass + fuel_mass = ( + num_pax + * ( + initialization_guesses['fuel_burn_per_passenger_mile'] + * aircraft_values.get_val(Mission.Design.RANGE, units='NM') + ) + + reserves + ) + mission_mass = ( + initialization_guesses['operating_empty_mass'] + + ( + num_pax + * aircraft_values.get_val( + Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, units='lbm' + ) + ) + + fuel_mass + ) elif problem_type == ProblemType.FALLOUT or problem_type == ProblemType.SIZING: - mission_mass = aircraft_values.get_val( - Mission.Design.GROSS_MASS, units='lbm') + mission_mass = aircraft_values.get_val(Mission.Design.GROSS_MASS, units='lbm') initialization_guesses['actual_takeoff_mass'] = mission_mass if cruise_mass_final == 0: # no guess given if problem_type == ProblemType.SIZING: - cruise_mass_final = .8 + cruise_mass_final = 0.8 elif problem_type == ProblemType.ALTERNATE: cruise_mass_final = -1 # estimation based on payload and fuel if cruise_mass_final <= 0: - cruise_mass_final = initialization_guesses['operating_empty_mass'] + \ - num_pax * \ - aircraft_values.get_val( - Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, units='lbm') + reserves + cruise_mass_final = ( + initialization_guesses['operating_empty_mass'] + + num_pax + * aircraft_values.get_val(Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, units='lbm') + + reserves + ) # fraction of takeoff mass elif cruise_mass_final <= 1: - cruise_mass_final = mission_mass * \ - cruise_mass_final + cruise_mass_final = mission_mass * cruise_mass_final initialization_guesses['cruise_mass_final'] = cruise_mass_final if initialization_guesses['rotation_mass'] <= 0: initialization_guesses['rotation_mass'] = 0.99 if initialization_guesses['rotation_mass'] <= 1: # fraction of takeoff mass - initialization_guesses['rotation_mass'] = mission_mass * \ - initialization_guesses['rotation_mass'] + initialization_guesses['rotation_mass'] = ( + mission_mass * initialization_guesses['rotation_mass'] + ) if Mission.Design.MACH in aircraft_values: cruise_mach = aircraft_values.get_val(Mission.Design.MACH) @@ -361,40 +419,77 @@ def initialization_guessing(aircraft_values: AviaryValues, initialization_guesse cruise_mach = aircraft_values.get_val(Mission.Summary.CRUISE_MACH) if initialization_guesses['flight_duration'] <= 0: # estimation based on mach - initialization_guesses['flight_duration'] = aircraft_values.get_val( - Mission.Design.RANGE, units='NM') / (667 * cruise_mach) * (60 * 60) + initialization_guesses['flight_duration'] = ( + aircraft_values.get_val(Mission.Design.RANGE, units='NM') + / (667 * cruise_mach) + * (60 * 60) + ) elif initialization_guesses['flight_duration'] <= 15: # duration entered in hours - initialization_guesses['flight_duration'] = initialization_guesses['flight_duration'] * \ - (60 * 60) + initialization_guesses['flight_duration'] = initialization_guesses['flight_duration'] * ( + 60 * 60 + ) + # TODO this does not work at all for mixed-type engines (some propeller and some not) try: - total_thrust = aircraft_values.get_val( - Aircraft.Engine.SCALED_SLS_THRUST, 'lbf') * aircraft_values.get_val(Aircraft.Engine.NUM_ENGINES) + num_engines = aircraft_values.get_val(Aircraft.Engine.NUM_ENGINES) + + # This happens before preprocessing, and we end up with the default when unspecified. + # num_engines = np.array(num_engines) + + if aircraft_values.get_val(Aircraft.Engine.HAS_PROPELLERS): + # For large turboprops, 1 pound of thrust per hp at takeoff seems to be close enough + total_thrust = np.dot( + aircraft_values.get_val(Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN, 'hp'), + aircraft_values.get_val(Aircraft.Engine.NUM_ENGINES), + ) + else: + total_thrust = np.dot( + aircraft_values.get_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 'lbf') + * aircraft_values.get_val(Aircraft.Engine.SCALE_FACTOR), + aircraft_values.get_val(Aircraft.Engine.NUM_ENGINES), + ) + except KeyError: - # heterogeneous engine-model case. Get thrust from the engine decks instead. - total_thrust = 0 - for model in engine_builders: - thrust = model.get_val(Aircraft.Engine.SCALED_SLS_THRUST, 'lbf') - num_engines = model.get_val(Aircraft.Engine.NUM_ENGINES) - total_thrust += thrust * num_engines + if engine_builders is not None and len(engine_builders) > 1: + # heterogeneous engine-model case. Get thrust from the engine models instead. + total_thrust = 0 + for model in engine_builders: + thrust = model.get_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 'lbf') * model.get_val( + Aircraft.Engine.SCALE_FACTOR + ) + num_engines = model.get_val(Aircraft.Engine.NUM_ENGINES) + total_thrust += thrust * num_engines + + else: + total_thrust = np.dot( + aircraft_values.get_val(Aircraft.Engine.SCALED_SLS_THRUST, 'lbf'), + aircraft_values.get_val(Aircraft.Engine.NUM_ENGINES), + ) - gamma_guess = np.arcsin(.5*total_thrust / mission_mass) - avg_speed_guess = (.5 * 667 * cruise_mach) # kts + gamma_guess = np.arcsin(0.5 * total_thrust / mission_mass) + avg_speed_guess = 0.5 * 667 * cruise_mach # kts if initialization_guesses['time_to_climb'] <= 0: # no guess given - initialization_guesses['time_to_climb'] = aircraft_values.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') / \ - (avg_speed_guess * np.sin(gamma_guess)) + initialization_guesses['time_to_climb'] = aircraft_values.get_val( + Mission.Design.CRUISE_ALTITUDE, units='ft' + ) / (avg_speed_guess * np.sin(gamma_guess)) elif initialization_guesses['time_to_climb'] <= 2: # duration entered in hours initialization_guesses['time_to_climb'] = initialization_guesses['time_to_climb'] * ( - 60 * 60) + 60 * 60 + ) elif initialization_guesses['time_to_climb'] <= 200: # average climb rate in ft/s - initialization_guesses['time_to_climb'] = aircraft_values.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') / \ - initialization_guesses['time_to_climb'] + initialization_guesses['time_to_climb'] = ( + aircraft_values.get_val(Mission.Design.CRUISE_ALTITUDE, units='ft') + / initialization_guesses['time_to_climb'] + ) # range covered using an average speed from 0 to cruise if initialization_guesses['climb_range'] <= 0: - initialization_guesses['climb_range'] = initialization_guesses['time_to_climb'] / \ - (60 * 60) * (avg_speed_guess * np.cos(gamma_guess)) + initialization_guesses['climb_range'] = ( + initialization_guesses['time_to_climb'] + / (60 * 60) + * (avg_speed_guess * np.cos(gamma_guess)) + ) if aircraft_values.get_val(Settings.VERBOSITY) >= Verbosity.VERBOSE: print('\nInitial Guesses') @@ -417,27 +512,106 @@ def initialization_guessing(aircraft_values: AviaryValues, initialization_guesse # is exactly equal to zero, engine_on_fuselage is set to to True, otherwise it is set to False. # One variable can be used to set the value of any number of options, but an option can only be # set by one variable - # [Aircraft.Engine.WING_LOCATIONS, { # 'val': 0, 'relation': '==', 'target': Aircraft.Engine.FUSELAGE_MOUNTED, 'result': True, 'alternate': False}], - [Aircraft.Wing.LOADING, {'val': 20, 'relation': '>', - 'target': Aircraft.Wing.LOADING_ABOVE_20, 'result': True, 'alternate': False}], - [Aircraft.Strut.ATTACHMENT_LOCATION, { - 'val': 0, 'relation': '!=', 'target': Aircraft.Wing.HAS_STRUT, 'result': True, 'alternate': False}], - [Aircraft.Strut.ATTACHMENT_LOCATION, { - 'val': 1, 'relation': '>', 'target': Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, 'result': True, 'alternate': False}], - [Aircraft.Wing.FOLD_MASS_COEFFICIENT, { - 'val': 0, 'relation': '>', 'target': Aircraft.Wing.HAS_FOLD, 'result': True, 'alternate': False}], - [Aircraft.Wing.FOLDED_SPAN, {'val': 1, 'relation': '>', 'target': Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, - 'result': True, 'alternate': False}], - [Aircraft.Design.PART25_STRUCTURAL_CATEGORY, { - 'val': 0, 'relation': '<', 'target': Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, 'result': True, 'alternate': False}], - [Aircraft.Engine.TYPE, { - 'val': [1, 2, 3, 4, 11, 12, 13, 14], 'relation': 'in', 'target': Aircraft.Engine.HAS_PROPELLERS, 'result': True, 'alternate': False}], - ['JENGSZ', { - 'val': 4, 'relation': '!=', 'target': Aircraft.Engine.SCALE_PERFORMANCE, 'result': True, 'alternate': False}], - [Aircraft.HorizontalTail.VOLUME_COEFFICIENT, { - 'val': 0, 'relation': '==', 'target': Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, 'result': True, 'alternate': False}], - [Aircraft.VerticalTail.VOLUME_COEFFICIENT, { - 'val': 0, 'relation': '==', 'target': Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, 'result': True, 'alternate': False}], + [ + Aircraft.Design.WING_LOADING, + { + 'val': 20, + 'relation': '>', + 'target': Aircraft.Wing.LOADING_ABOVE_20, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.Strut.ATTACHMENT_LOCATION, + { + 'val': 0, + 'relation': '!=', + 'target': Aircraft.Wing.HAS_STRUT, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.Strut.ATTACHMENT_LOCATION, + { + 'val': 1, + 'relation': '>', + 'target': Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.Wing.FOLD_MASS_COEFFICIENT, + { + 'val': 0, + 'relation': '>', + 'target': Aircraft.Wing.HAS_FOLD, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.Wing.FOLDED_SPAN, + { + 'val': 1, + 'relation': '>', + 'target': Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.Design.PART25_STRUCTURAL_CATEGORY, + { + 'val': 0, + 'relation': '<', + 'target': Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.Engine.TYPE, + { + 'val': [1, 2, 3, 4, 6, 11, 12, 13, 14], + 'relation': 'in', + 'target': Aircraft.Engine.HAS_PROPELLERS, + 'result': True, + 'alternate': False, + }, + ], + [ + 'JENGSZ', + { + 'val': 4, + 'relation': '!=', + 'target': Aircraft.Engine.SCALE_PERFORMANCE, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.HorizontalTail.VOLUME_COEFFICIENT, + { + 'val': 0, + 'relation': '==', + 'target': Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, + 'result': True, + 'alternate': False, + }, + ], + [ + Aircraft.VerticalTail.VOLUME_COEFFICIENT, + { + 'val': 0, + 'relation': '==', + 'target': Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, + 'result': True, + 'alternate': False, + }, + ], ] diff --git a/aviary/utils/propeller_map_conversion.py b/aviary/utils/propeller_map_conversion.py index 51183fabdb..a38f767e1f 100644 --- a/aviary/utils/propeller_map_conversion.py +++ b/aviary/utils/propeller_map_conversion.py @@ -1,14 +1,17 @@ #!/usr/bin/python import argparse -import numpy as np +import getpass + from datetime import datetime from enum import Enum -from aviary.utils.conversion_utils import _rep, _parse, _read_map +import numpy as np + from aviary.api import NamedValues +from aviary.utils.conversion_utils import _parse, _read_map, _rep from aviary.utils.csv_data_file import write_data_file from aviary.utils.functions import get_path -from aviary.subsystems.propulsion.utils import PropellerModelVariables, default_propeller_units +from aviary.interface.utils import round_it class PropMapType(Enum): @@ -18,62 +21,64 @@ def __str__(self): return self.value -HELICAL_MACH = PropellerModelVariables.HELICAL_MACH -MACH = PropellerModelVariables.MACH -CP = PropellerModelVariables.CP -CT = PropellerModelVariables.CT -J = PropellerModelVariables.J +sig_figs = { + 'Helical Mach': 6, + 'Mach': 5, + 'Power Coefficient': 5, + 'Advance Ratio': 5, + 'Thrust Coefficient': 6, +} + +outputs = ['Thrust Coefficient'] -def PropDataConverter(input_file, output_file, data_format: PropMapType): +def convert_propeller_map( + input_file, output_file, data_format: PropMapType = PropMapType.GASP, round_data=False +): """ This is a utility class to convert a propeller map file to Aviary format. Currently, there is only one option: from GASP format to Aviary format. As an Aviary command, the usage is: - aviary convert_prop_table -f GASP input_file output_file + aviary convert_prop_table -f GASP input_file output_file. """ - timestamp = datetime.now().strftime('%m/%d/%y at %H:%M') + user = getpass.getuser() comments = [] - header = {} data = {} data_file = get_path(input_file) - comments.append(f'# created {timestamp}') - comments.append(f'# {data_format} propeller map converted from {input_file}') + comments.append(f'# created {timestamp} by {user}') + comments.append(f'# {data_format}-derived propeller map converted from {data_file.name}') if data_format is PropMapType.GASP: scalars, tables, fields = _read_gasp_propeller(data_file, comments) - data[J] = tables['thrust_coefficient'][:, 2] if scalars['iread'] == 1: - data[HELICAL_MACH] = tables['thrust_coefficient'][:, 0] + data['Helical Mach'] = tables['thrust_coefficient'][:, 0] else: - data[MACH] = tables['thrust_coefficient'][:, 0] - data[CP] = tables['thrust_coefficient'][:, 1] - data[CT] = tables['thrust_coefficient'][:, 3] + data['Mach'] = tables['thrust_coefficient'][:, 0] + data['Power Coefficient'] = tables['thrust_coefficient'][:, 1] + data['Advance Ratio'] = tables['thrust_coefficient'][:, 2] + data['Thrust Coefficient'] = tables['thrust_coefficient'][:, 3] # data needs to be string so column length can be easily found later for var in data: + if round_data: + data[var] = np.array([round_it(val, sig_figs[var]) for val in data[var]]) data[var] = np.array([str(item) for item in data[var]]) else: - quit("Invalid propeller map format provided") + raise UserWarning('Invalid propeller map format provided') # store formatted data into NamedValues object write_data = NamedValues() for key in data: - write_data.set_val(key.value, data[key], default_propeller_units[key]) + write_data.set_val(key, data[key], 'unitless') if output_file is None: - sfx = data_file.suffix - if sfx == '.prop': - ext = '_aviary.prop' - else: - ext = '.prop' - output_file = data_file.stem + ext - write_data_file(output_file, write_data, comments, include_timestamp=False) + output_file = data_file.stem + '.csv' + write_data_file(output_file, write_data, outputs, comments, include_timestamp=False) def _read_gasp_propeller(fp, cmts): @@ -81,20 +86,20 @@ def _read_gasp_propeller(fp, cmts): Data table is returned as a dictionary. The table consists of both the independent variables and the dependent variable for the corresponding field. The table is a "tidy format" 2D array where the first three - columns are the independent varaiables (Advance ratio, Mach number, and power coefficient) + columns are the independent variables (Advance ratio, Mach number, and power coefficient) and the final column is the dependent variable thrust coefficient. """ - with open(fp, "r") as f: - table_types = ["thrust_coefficient",] + with open(fp, 'r') as f: + table_types = [ + 'thrust_coefficient', + ] scalars = _read_pm_header(f) if scalars['iread'] == 1: cmts.append('# CT = f(Helical Mach at 75% Radius, Adv ratio & CP)') - cmts.append('# mach_type = helical_mach') elif scalars['iread'] == 2: - cmts.append('Propfan format - CT = f(Mach, Adv Ratio & CP)') - cmts.append('# mach_type = mach') + cmts.append('# Propfan format - CT = f(Mach, Adv Ratio & CP)') else: - raise RuntimeError(f"IREAD = 1 or 2 expected, got {scalars['iread']}") + raise RuntimeError(f'IREAD = 1 or 2 expected, got {scalars["iread"]}') tables = {k: _read_pm_table(f, cmts) for k in table_types} @@ -103,20 +108,20 @@ def _read_gasp_propeller(fp, cmts): def _read_pm_header(f): """Read GASP propeller map header (first line), returning the propeller scalars in a dict - parameter 1 is Mach type. It is either 1 or 2. - parameter 2 is IPRINT in GASP and is ignored in Aviary + parameter 1 is Mach type. It is either 1 or 2. + parameter 2 is IPRINT in GASP and is ignored in Aviary. """ iread, _ = _parse(f, [*_rep(2, (int, 5))]) return { - "iread": iread, + 'iread': iread, } def _read_pm_table(f, cmts): """Read an entire table from a GASP propeller map file. The table data is returned as a "tidy format" array with three columns for the - independent variables (advanced ratio (J), Mach number and power coefficient) + independent variables (advanced ratio (J), Mach number and power coefficient) and the final column for thrust coefficient. """ tab_data = None @@ -146,26 +151,39 @@ def _read_pm_table(f, cmts): def _setup_PMC_parser(parser): - parser.add_argument('input_file', type=str, - help='path to propeller map file to be converted') - parser.add_argument('output_file', type=str, nargs='?', - help='path to file where new converted data will be written') - parser.add_argument('-f', '--data_format', type=PropMapType, choices=list(PropMapType), - nargs='?', default='GASP', - help='data format used by input_file') + parser.add_argument('input_file', type=str, help='path to propeller map file to be converted') + parser.add_argument( + 'output_file', + type=str, + nargs='?', + help='path to file where new converted data will be written (optional)', + ) + # currently removing as there is only one allowed map type at the moment + # parser.add_argument( + # '-f', + # '--data_format', + # type=PropMapType, + # choices=list(PropMapType), + # nargs='?', + # default='GASP', + # help='data format used by input_file', + # ) + parser.add_argument('--round', action='store_true', help='round data to improve readability') def _exec_PMC(args, user_args): - PropDataConverter( + convert_propeller_map( input_file=args.input_file, output_file=args.output_file, - data_format=args.data_format + # data_format=args.data_format, + round_data=args.round, ) if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Converts GASP-formatted ' - 'propeller map files into Aviary csv format.\n') + parser = argparse.ArgumentParser( + description='Converts GASP-formatted propeller map files into Aviary csv format.\n' + ) _setup_PMC_parser(parser) args = parser.parse_args() _exec_PMC(args, None) diff --git a/aviary/utils/test/data/FLOPS_turbofan_22k.txt b/aviary/utils/test/data/FLOPS_turbofan_22k.txt deleted file mode 100644 index ff9decc071..0000000000 --- a/aviary/utils/test/data/FLOPS_turbofan_22k.txt +++ /dev/null @@ -1,613 +0,0 @@ - 0.00 0.0 50. 22200.5 0.0 5157.3 0.2323 17.737 - 0.00 0.0 47. 19980.5 0.0 4500.3 0.2252 17.955 - 0.00 0.0 44. 17760.5 0.0 3879.8 0.2185 18.493 - 0.00 0.0 41. 15540.4 0.0 3300.0 0.2123 19.097 - 0.00 0.0 38. 13320.3 0.0 2756.1 0.2069 19.670 - 0.00 0.0 35. 11100.2 0.0 2255.1 0.2032 20.252 - 0.00 0.0 32. 8880.2 0.0 1790.8 0.2017 20.979 - 0.00 0.0 29. 6660.2 0.0 1368.2 0.2054 21.499 - 0.00 0.0 26. 4440.1 0.0 964.9 0.2173 23.442 - 0.00 0.0 21. 1110.0 0.0 500.3 0.4507 55.372 - 0.10 0.0 50. 22936.3 3299.9 5279.7 0.2689 17.625 - 0.10 0.0 47. 20834.5 3161.7 4653.7 0.2633 17.750 - 0.10 0.0 44. 18751.0 3041.7 4059.2 0.2584 18.179 - 0.10 0.0 41. 16665.2 2919.7 3496.0 0.2543 18.761 - 0.10 0.0 38. 14543.0 2761.2 2972.4 0.2523 19.161 - 0.10 0.0 35. 12412.3 2594.1 2464.7 0.2510 19.731 - 0.10 0.0 32. 10237.7 2383.1 2000.9 0.2547 20.126 - 0.10 0.0 29. 8024.0 2133.0 1561.0 0.2650 20.506 - 0.10 0.0 26. 5771.8 1844.5 1138.1 0.2898 21.215 - 0.10 0.0 21. 2380.8 1399.0 576.5 0.5872 28.966 - 0.20 0.0 50. 24389.7 6753.8 5444.7 0.3087 17.370 - 0.20 0.0 47. 22353.3 6481.1 4836.8 0.3047 17.401 - 0.20 0.0 44. 20360.0 6251.2 4256.6 0.3017 17.711 - 0.20 0.0 41. 18364.7 6019.6 3706.3 0.3002 18.138 - 0.20 0.0 38. 16309.0 5727.5 3184.6 0.3010 18.434 - 0.20 0.0 35. 14231.2 5413.3 2672.2 0.3030 18.805 - 0.20 0.0 32. 12066.9 5012.5 2198.3 0.3116 18.974 - 0.20 0.0 29. 9840.7 4549.9 1735.6 0.3280 19.130 - 0.20 0.0 26. 7484.3 3957.2 1289.5 0.3656 19.004 - 0.20 0.0 21. 3842.2 2960.4 639.9 0.7257 20.541 - 0.25 0.0 50. 25353.3 8566.5 5540.1 0.3300 17.214 - 0.25 0.0 47. 23335.6 8227.3 4937.9 0.3268 17.205 - 0.25 0.0 44. 21373.9 7944.3 4363.3 0.3249 17.458 - 0.25 0.0 41. 19409.5 7658.7 3814.8 0.3246 17.805 - 0.25 0.0 38. 17380.0 7307.8 3291.8 0.3268 18.054 - 0.25 0.0 35. 15310.2 6916.7 2778.8 0.3311 18.307 - 0.25 0.0 32. 13148.3 6433.6 2295.5 0.3419 18.409 - 0.25 0.0 29. 10910.3 5874.2 1824.0 0.3622 18.469 - 0.25 0.0 26. 8479.2 5121.8 1362.9 0.4059 18.077 - 0.25 0.0 21. 4659.1 3819.8 673.8 0.8027 18.267 - 0.30 0.0 50. 26324.7 10421.4 5593.4 0.3517 17.045 - 0.30 0.0 47. 24336.6 10023.5 5002.1 0.3495 17.016 - 0.30 0.0 44. 22413.3 9690.4 4437.3 0.3488 17.219 - 0.30 0.0 41. 20486.0 9353.6 3893.3 0.3497 17.498 - 0.30 0.0 38. 18485.1 8943.1 3373.6 0.3536 17.684 - 0.30 0.0 35. 16429.0 8477.3 2862.2 0.3600 17.838 - 0.30 0.0 32. 14274.4 7913.0 2375.2 0.3734 17.865 - 0.30 0.0 29. 12021.9 7250.9 1898.7 0.3980 17.801 - 0.30 0.0 26. 9528.0 6347.3 1425.4 0.4481 17.247 - 0.30 0.0 21. 5528.3 4733.1 705.1 0.8867 16.609 - 0.40 0.0 50. 28852.7 14388.7 5728.6 0.3961 16.686 - 0.40 0.0 47. 26900.2 13882.2 5153.1 0.3958 16.628 - 0.40 0.0 44. 25020.5 13449.2 4598.6 0.3974 16.742 - 0.40 0.0 41. 23134.7 13010.0 4055.8 0.4006 16.903 - 0.40 0.0 38. 21151.9 12473.4 3536.8 0.4075 16.968 - 0.40 0.0 35. 19086.7 11854.6 3023.7 0.4181 16.966 - 0.40 0.0 32. 16908.5 11122.8 2526.5 0.4367 16.858 - 0.40 0.0 29. 14564.4 10225.2 2036.7 0.4694 16.565 - 0.40 0.0 26. 11919.1 9026.4 1537.6 0.5315 15.848 - 0.40 0.0 21. 7463.1 6739.9 758.9 1.0494 14.345 - 0.50 0.0 50. 31992.9 18741.9 5877.1 0.4435 16.352 - 0.50 0.0 47. 30078.1 18152.1 5315.7 0.4457 16.293 - 0.50 0.0 44. 28222.7 17622.1 4763.3 0.4493 16.338 - 0.50 0.0 41. 26357.5 17081.8 4221.6 0.4551 16.411 - 0.50 0.0 38. 24355.0 16404.6 3701.2 0.4655 16.370 - 0.50 0.0 35. 22256.7 15631.3 3186.0 0.4809 16.263 - 0.50 0.0 32. 20024.5 14724.1 2678.2 0.5053 16.056 - 0.50 0.0 29. 17558.8 13583.5 2175.2 0.5472 15.635 - 0.50 0.0 26. 14735.0 12084.8 1652.2 0.6234 14.848 - 0.50 0.0 21. 9760.2 9097.6 824.3 1.2441 13.022 - 0.00 2000.0 50. 21230.1 0.0 4936.7 0.2325 17.715 - 0.00 2000.0 47. 19107.0 0.0 4307.7 0.2255 17.846 - 0.00 2000.0 44. 16984.1 0.0 3709.7 0.2184 18.353 - 0.00 2000.0 41. 14861.1 0.0 3149.6 0.2119 19.014 - 0.00 2000.0 38. 12738.0 0.0 2632.7 0.2067 19.552 - 0.00 2000.0 35. 10615.1 0.0 2149.0 0.2024 20.188 - 0.00 2000.0 32. 8492.0 0.0 1706.2 0.2009 20.883 - 0.00 2000.0 29. 6369.0 0.0 1302.4 0.2045 21.423 - 0.00 2000.0 26. 4246.0 0.0 917.9 0.2162 23.255 - 0.00 2000.0 21. 1061.5 0.0 472.8 0.4454 54.005 - 0.10 2000.0 50. 21929.0 3108.4 5054.3 0.2686 17.606 - 0.10 2000.0 47. 19909.3 2970.8 4452.6 0.2629 17.654 - 0.10 2000.0 44. 17912.6 2856.0 3879.3 0.2576 18.059 - 0.10 2000.0 41. 15915.3 2740.7 3339.8 0.2535 18.634 - 0.10 2000.0 38. 13887.4 2594.9 2836.1 0.2511 19.072 - 0.10 2000.0 35. 11852.0 2441.7 2346.1 0.2493 19.696 - 0.10 2000.0 32. 9768.7 2240.4 1904.6 0.2530 20.058 - 0.10 2000.0 29. 7653.6 2007.4 1483.6 0.2628 20.484 - 0.10 2000.0 26. 5496.1 1731.9 1080.8 0.2871 21.137 - 0.10 2000.0 21. 2245.8 1304.8 544.9 0.5790 28.744 - 0.20 2000.0 50. 23302.1 6361.8 5213.3 0.3077 17.363 - 0.20 2000.0 47. 21345.4 6099.1 4628.8 0.3036 17.370 - 0.20 2000.0 44. 19421.8 5869.5 4069.8 0.3003 17.619 - 0.20 2000.0 41. 17505.4 5647.2 3540.4 0.2986 18.027 - 0.20 2000.0 38. 15547.3 5383.2 3037.0 0.2988 18.381 - 0.20 2000.0 35. 13552.3 5082.2 2548.3 0.3009 18.731 - 0.20 2000.0 32. 11489.5 4713.4 2091.2 0.3086 18.955 - 0.20 2000.0 29. 9365.0 4282.9 1649.7 0.3246 19.158 - 0.20 2000.0 26. 7105.4 3717.4 1224.3 0.3614 19.003 - 0.20 2000.0 21. 3610.4 2763.4 605.0 0.7143 20.495 - 0.25 2000.0 50. 24212.7 8069.6 5305.6 0.3287 17.215 - 0.25 2000.0 47. 22275.4 7746.7 4727.0 0.3254 17.199 - 0.25 2000.0 44. 20373.8 7459.5 4172.5 0.3231 17.381 - 0.25 2000.0 41. 18485.5 7185.3 3643.9 0.3225 17.712 - 0.25 2000.0 38. 16555.0 6869.1 3138.9 0.3241 18.018 - 0.25 2000.0 35. 14566.0 6494.3 2649.9 0.3283 18.254 - 0.25 2000.0 32. 12507.8 6050.5 2183.7 0.3382 18.411 - 0.25 2000.0 29. 10367.5 5524.5 1734.3 0.3581 18.490 - 0.25 2000.0 26. 8041.1 4812.5 1293.9 0.4008 18.100 - 0.25 2000.0 21. 4374.0 3566.9 637.1 0.7893 18.253 - 0.30 2000.0 50. 25129.1 9817.7 5358.1 0.3499 17.056 - 0.30 2000.0 47. 23216.0 9435.7 4789.0 0.3475 17.011 - 0.30 2000.0 44. 21348.0 9099.0 4243.5 0.3464 17.155 - 0.30 2000.0 41. 19493.4 8775.5 3719.1 0.3470 17.420 - 0.30 2000.0 38. 17593.4 8406.6 3217.0 0.3502 17.663 - 0.30 2000.0 35. 15615.9 7960.2 2729.6 0.3565 17.803 - 0.30 2000.0 32. 13567.2 7442.7 2259.6 0.3689 17.884 - 0.30 2000.0 29. 11402.7 6809.2 1805.7 0.3931 17.803 - 0.30 2000.0 26. 9027.4 5965.1 1353.4 0.4420 17.289 - 0.30 2000.0 21. 5186.4 4420.8 666.7 0.8708 16.613 - 0.40 2000.0 50. 27516.8 13558.4 5491.2 0.3934 16.716 - 0.40 2000.0 47. 25618.1 13055.4 4933.9 0.3927 16.617 - 0.40 2000.0 44. 23794.8 12628.7 4400.6 0.3941 16.704 - 0.40 2000.0 41. 21977.5 12206.5 3876.7 0.3968 16.855 - 0.40 2000.0 38. 20102.3 11727.1 3374.3 0.4029 16.975 - 0.40 2000.0 35. 18112.8 11133.6 2884.4 0.4133 16.963 - 0.40 2000.0 32. 16048.2 10464.6 2404.5 0.4306 16.905 - 0.40 2000.0 29. 13792.9 9605.4 1937.9 0.4628 16.598 - 0.40 2000.0 26. 11277.9 8486.2 1460.5 0.5232 15.915 - 0.40 2000.0 21. 6995.8 6297.9 717.6 1.0282 14.368 - 0.50 2000.0 50. 30489.2 17667.4 5639.4 0.4398 16.405 - 0.50 2000.0 47. 28597.6 17057.8 5093.0 0.4413 16.283 - 0.50 2000.0 44. 26805.0 16547.5 4563.3 0.4449 16.321 - 0.50 2000.0 41. 25003.1 16027.9 4039.7 0.4501 16.387 - 0.50 2000.0 38. 23119.3 15426.2 3534.7 0.4595 16.399 - 0.50 2000.0 35. 21093.8 14683.1 3040.4 0.4743 16.283 - 0.50 2000.0 32. 18985.5 13856.8 2550.9 0.4974 16.123 - 0.50 2000.0 29. 16610.5 12763.9 2071.0 0.5384 15.688 - 0.50 2000.0 26. 13929.6 11365.3 1570.5 0.6125 14.930 - 0.50 2000.0 21. 9144.6 8503.5 779.2 1.2154 13.054 - 0.00 5000.0 50. 19786.8 0.0 4611.8 0.2331 17.637 - 0.00 5000.0 47. 17808.1 0.0 4018.3 0.2256 17.761 - 0.00 5000.0 44. 15829.6 0.0 3456.4 0.2184 18.164 - 0.00 5000.0 41. 13850.8 0.0 2930.5 0.2116 18.847 - 0.00 5000.0 38. 11872.1 0.0 2448.9 0.2063 19.392 - 0.00 5000.0 35. 9893.3 0.0 1991.9 0.2013 20.105 - 0.00 5000.0 32. 7914.8 0.0 1582.5 0.1999 20.728 - 0.00 5000.0 29. 5936.0 0.0 1206.2 0.2032 21.325 - 0.00 5000.0 26. 3957.4 0.0 850.3 0.2149 23.000 - 0.00 5000.0 21. 989.3 0.0 434.8 0.4395 52.114 - 0.10 5000.0 50. 20390.2 2824.5 4716.9 0.2685 17.502 - 0.10 5000.0 47. 18516.7 2707.6 4144.9 0.2622 17.640 - 0.10 5000.0 44. 16643.9 2591.3 3607.1 0.2567 17.904 - 0.10 5000.0 41. 14779.7 2483.7 3102.4 0.2523 18.440 - 0.10 5000.0 38. 12896.7 2357.4 2628.7 0.2494 18.958 - 0.10 5000.0 35. 10997.5 2214.7 2173.3 0.2475 19.535 - 0.10 5000.0 32. 9062.6 2036.3 1760.2 0.2505 19.972 - 0.10 5000.0 29. 7096.8 1827.1 1368.6 0.2597 20.460 - 0.10 5000.0 26. 5084.7 1571.6 997.1 0.2838 21.039 - 0.10 5000.0 21. 2051.0 1172.7 500.2 0.5696 28.439 - 0.20 5000.0 50. 21625.5 5773.9 4865.7 0.3070 17.253 - 0.20 5000.0 47. 19823.9 5557.5 4307.8 0.3020 17.372 - 0.20 5000.0 44. 18006.3 5325.1 3782.3 0.2983 17.501 - 0.20 5000.0 41. 16213.6 5117.5 3284.8 0.2960 17.882 - 0.20 5000.0 38. 14401.5 4890.6 2811.2 0.2956 18.314 - 0.20 5000.0 35. 12535.9 4610.0 2359.8 0.2977 18.634 - 0.20 5000.0 32. 10625.2 4284.6 1930.3 0.3044 18.934 - 0.20 5000.0 29. 8651.9 3896.4 1521.8 0.3200 19.184 - 0.20 5000.0 26. 6544.9 3374.5 1128.1 0.3558 19.004 - 0.20 5000.0 21. 3279.2 2486.6 555.4 0.7008 20.431 - 0.25 5000.0 50. 22455.3 7322.1 4954.1 0.3274 17.109 - 0.25 5000.0 47. 20679.7 7059.9 4401.4 0.3232 17.211 - 0.25 5000.0 44. 18875.0 6768.5 3878.8 0.3204 17.280 - 0.25 5000.0 41. 17105.5 6512.2 3382.0 0.3193 17.590 - 0.25 5000.0 38. 15321.7 6241.9 2906.1 0.3201 17.974 - 0.25 5000.0 35. 13458.9 5892.3 2453.8 0.3243 18.186 - 0.25 5000.0 32. 11554.8 5501.5 2015.8 0.3330 18.418 - 0.25 5000.0 29. 9552.3 5012.4 1600.4 0.3525 18.467 - 0.25 5000.0 26. 7396.9 4370.3 1192.1 0.3939 18.135 - 0.25 5000.0 21. 3967.7 3211.0 584.7 0.7728 18.233 - 0.30 5000.0 50. 23308.7 8916.7 5007.5 0.3479 16.977 - 0.30 5000.0 47. 21556.0 8603.3 4465.4 0.3447 17.036 - 0.30 5000.0 44. 19772.4 8258.8 3949.5 0.3430 17.070 - 0.30 5000.0 41. 18030.4 7956.0 3456.5 0.3431 17.317 - 0.30 5000.0 38. 16278.2 7642.5 2981.8 0.3453 17.640 - 0.30 5000.0 35. 14421.4 7225.2 2530.3 0.3516 17.759 - 0.30 5000.0 32. 12527.8 6771.0 2088.0 0.3627 17.914 - 0.30 5000.0 29. 10498.8 6181.2 1667.3 0.3862 17.808 - 0.30 5000.0 26. 8298.5 5420.1 1247.8 0.4335 17.351 - 0.30 5000.0 21. 4701.4 3981.8 612.1 0.8506 16.619 - 0.40 5000.0 50. 25532.1 12343.7 5141.2 0.3898 16.707 - 0.40 5000.0 47. 23784.9 11915.4 4613.6 0.3887 16.672 - 0.40 5000.0 44. 22019.8 11469.2 4105.4 0.3891 16.652 - 0.40 5000.0 41. 20304.5 11072.7 3612.2 0.3913 16.790 - 0.40 5000.0 38. 18582.3 10669.3 3134.9 0.3962 16.990 - 0.40 5000.0 35. 16707.7 10113.6 2679.6 0.4064 16.962 - 0.40 5000.0 32. 14805.2 9529.8 2226.7 0.4221 16.977 - 0.40 5000.0 29. 12684.6 8728.0 1793.0 0.4532 16.648 - 0.40 5000.0 26. 10357.3 7719.6 1348.9 0.5114 16.016 - 0.40 5000.0 21. 6336.9 5677.5 659.2 0.9998 14.403 - 0.50 5000.0 50. 28322.0 16137.5 5292.2 0.4343 16.476 - 0.50 5000.0 47. 26534.9 15568.8 4775.2 0.4355 16.345 - 0.50 5000.0 44. 24784.0 15036.5 4272.2 0.4383 16.299 - 0.50 5000.0 41. 23076.6 14547.2 3775.9 0.4427 16.355 - 0.50 5000.0 38. 21357.0 14046.3 3294.1 0.4506 16.447 - 0.50 5000.0 35. 19441.0 13348.6 2831.5 0.4648 16.317 - 0.50 5000.0 32. 17496.7 12623.0 2369.6 0.4862 16.215 - 0.50 5000.0 29. 15264.6 11609.3 1920.9 0.5255 15.771 - 0.50 5000.0 26. 12786.4 10349.5 1453.6 0.5965 15.056 - 0.50 5000.0 21. 8280.0 7670.8 715.7 1.1748 13.103 - 0.00 10000.0 50. 17401.2 0.0 4085.5 0.2348 17.377 - 0.00 10000.0 47. 15661.0 0.0 3533.4 0.2256 17.718 - 0.00 10000.0 44. 13921.0 0.0 3039.5 0.2183 17.905 - 0.00 10000.0 41. 12180.8 0.0 2575.1 0.2114 18.509 - 0.00 10000.0 38. 10440.6 0.0 2143.9 0.2053 19.175 - 0.00 10000.0 35. 8700.6 0.0 1739.4 0.1999 19.918 - 0.00 10000.0 32. 6960.4 0.0 1381.9 0.1985 20.520 - 0.00 10000.0 29. 5220.4 0.0 1051.6 0.2014 21.202 - 0.00 10000.0 26. 3480.2 0.0 743.0 0.2135 22.650 - 0.00 10000.0 21. 870.1 0.0 379.9 0.4366 49.426 - 0.10 10000.0 50. 17923.9 2386.4 4179.9 0.2690 17.256 - 0.10 10000.0 47. 16287.8 2304.0 3649.0 0.2609 17.604 - 0.10 10000.0 44. 14621.7 2191.7 3172.4 0.2552 17.679 - 0.10 10000.0 41. 12972.9 2096.8 2722.0 0.2503 18.154 - 0.10 10000.0 38. 11320.4 1997.9 2297.7 0.2465 18.795 - 0.10 10000.0 35. 9640.9 1872.2 1902.7 0.2449 19.299 - 0.10 10000.0 32. 7942.1 1727.0 1533.9 0.2468 19.855 - 0.10 10000.0 29. 6214.2 1553.0 1189.3 0.2551 20.440 - 0.10 10000.0 26. 4436.9 1329.4 867.6 0.2792 20.899 - 0.10 10000.0 21. 1753.3 976.5 435.3 0.5603 27.958 - 0.20 10000.0 50. 18971.4 4878.3 4312.5 0.3060 17.042 - 0.20 10000.0 47. 17411.1 4727.2 3795.9 0.2993 17.347 - 0.20 10000.0 44. 15786.4 4511.9 3326.7 0.2951 17.371 - 0.20 10000.0 41. 14186.8 4321.4 2880.4 0.2920 17.665 - 0.20 10000.0 38. 12592.1 4136.2 2459.3 0.2908 18.154 - 0.20 10000.0 35. 10945.4 3898.9 2062.7 0.2927 18.494 - 0.20 10000.0 32. 9273.2 3635.9 1679.9 0.2980 18.914 - 0.20 10000.0 29. 7522.6 3294.7 1324.5 0.3133 19.103 - 0.20 10000.0 26. 5675.8 2857.2 979.8 0.3476 19.018 - 0.20 10000.0 21. 2779.4 2074.7 482.1 0.6841 20.332 - 0.25 10000.0 50. 19673.2 6186.0 4391.0 0.3256 16.919 - 0.25 10000.0 47. 18139.4 6000.9 3880.6 0.3197 17.184 - 0.25 10000.0 44. 16530.1 5740.4 3412.4 0.3163 17.201 - 0.25 10000.0 41. 14940.7 5499.6 2966.8 0.3142 17.408 - 0.25 10000.0 38. 13362.3 5270.0 2544.2 0.3144 17.803 - 0.25 10000.0 35. 11727.9 4984.4 2143.7 0.3179 18.089 - 0.25 10000.0 32. 10063.1 4668.3 1753.6 0.3251 18.431 - 0.25 10000.0 29. 8286.0 4239.8 1391.5 0.3439 18.441 - 0.25 10000.0 26. 6399.2 3701.8 1034.8 0.3836 18.201 - 0.25 10000.0 21. 3355.6 2681.3 506.8 0.7515 18.205 - 0.30 10000.0 50. 20398.8 7534.2 4441.2 0.3452 16.809 - 0.30 10000.0 47. 18894.1 7315.9 3940.2 0.3403 17.035 - 0.30 10000.0 44. 17298.3 7006.6 3477.0 0.3378 17.018 - 0.30 10000.0 41. 15725.1 6719.8 3035.3 0.3371 17.166 - 0.30 10000.0 38. 14166.2 6447.5 2612.8 0.3385 17.481 - 0.30 10000.0 35. 12546.2 6113.9 2211.1 0.3438 17.700 - 0.30 10000.0 32. 10880.8 5735.0 1818.3 0.3534 17.911 - 0.30 10000.0 29. 9090.2 5230.7 1450.2 0.3758 17.826 - 0.30 10000.0 26. 7166.5 4593.6 1083.4 0.4211 17.458 - 0.30 10000.0 21. 3970.3 3327.1 530.0 0.8239 16.634 - 0.40 10000.0 50. 22315.7 10437.8 4573.5 0.3850 16.584 - 0.40 10000.0 47. 20842.3 10152.3 4084.3 0.3821 16.734 - 0.40 10000.0 44. 19239.8 9737.6 3626.1 0.3816 16.642 - 0.40 10000.0 41. 17673.9 9359.4 3186.2 0.3832 16.698 - 0.40 10000.0 38. 16126.1 8999.4 2757.6 0.3869 16.874 - 0.40 10000.0 35. 14506.7 8567.8 2348.7 0.3955 16.970 - 0.40 10000.0 32. 12808.0 8057.0 1947.9 0.4100 16.977 - 0.40 10000.0 29. 10960.1 7396.7 1563.2 0.4387 16.737 - 0.40 10000.0 26. 8928.6 6553.1 1174.0 0.4942 16.183 - 0.40 10000.0 21. 5344.1 4750.2 570.8 0.9610 14.463 - 0.50 10000.0 50. 24712.5 13657.9 4721.3 0.4271 16.405 - 0.50 10000.0 47. 23235.4 13286.3 4241.8 0.4264 16.463 - 0.50 10000.0 44. 21605.5 12761.8 3785.0 0.4280 16.311 - 0.50 10000.0 41. 20041.3 12302.8 3342.5 0.4319 16.314 - 0.50 10000.0 38. 18487.4 11854.6 2907.3 0.4383 16.389 - 0.50 10000.0 35. 16846.0 11318.6 2489.2 0.4503 16.380 - 0.50 10000.0 32. 15093.2 10671.4 2079.1 0.4702 16.253 - 0.50 10000.0 29. 13166.2 9849.8 1678.6 0.5062 15.910 - 0.50 10000.0 26. 11007.4 8796.5 1267.5 0.5733 15.262 - 0.50 10000.0 21. 6975.8 6423.1 619.3 1.1205 13.184 - 0.30 15000.0 50. 16939.8 6213.1 3515.5 0.3277 16.772 - 0.30 15000.0 47. 15686.6 6032.7 3120.9 0.3233 16.999 - 0.30 15000.0 44. 14368.6 5787.3 2754.6 0.3210 17.027 - 0.30 15000.0 41. 13050.0 5541.3 2406.1 0.3205 17.138 - 0.30 15000.0 38. 11750.1 5314.1 2073.7 0.3222 17.446 - 0.30 15000.0 35. 10406.6 5043.3 1756.8 0.3276 17.691 - 0.30 15000.0 32. 9018.3 4727.6 1447.9 0.3374 17.895 - 0.30 15000.0 29. 7532.3 4314.3 1158.7 0.3601 17.834 - 0.30 15000.0 26. 5934.7 3789.4 870.3 0.4057 17.485 - 0.40 15000.0 50. 18690.1 8639.4 3675.7 0.3657 16.538 - 0.40 15000.0 47. 17447.7 8402.1 3282.8 0.3629 16.689 - 0.40 15000.0 44. 16123.8 8083.5 2912.3 0.3622 16.673 - 0.40 15000.0 41. 14782.4 7747.1 2558.2 0.3636 16.668 - 0.40 15000.0 38. 13473.5 7443.1 2215.2 0.3673 16.836 - 0.40 15000.0 35. 12122.5 7097.1 1886.2 0.3753 16.976 - 0.40 15000.0 32. 10686.8 6666.6 1566.7 0.3897 16.974 - 0.40 15000.0 29. 9142.5 6127.1 1259.4 0.4177 16.774 - 0.40 15000.0 26. 7440.8 5430.7 949.8 0.4725 16.248 - 0.50 15000.0 50. 20974.3 11374.5 3890.8 0.4053 16.354 - 0.50 15000.0 47. 19717.0 11077.3 3492.0 0.4042 16.444 - 0.50 15000.0 44. 18364.1 10684.3 3111.5 0.4052 16.390 - 0.50 15000.0 41. 16967.8 10247.9 2744.2 0.4084 16.295 - 0.50 15000.0 38. 15621.2 9861.3 2385.7 0.4142 16.357 - 0.50 15000.0 35. 14242.2 9442.2 2038.7 0.4247 16.423 - 0.50 15000.0 32. 12725.5 8885.6 1703.7 0.4437 16.280 - 0.50 15000.0 29. 11098.6 8218.7 1374.9 0.4774 16.000 - 0.50 15000.0 26. 9266.5 7346.5 1040.8 0.5421 15.394 - 0.60 15000.0 50. 23901.5 14525.7 4176.1 0.4454 16.255 - 0.60 15000.0 47. 22601.2 14163.0 3761.2 0.4457 16.295 - 0.60 15000.0 44. 21190.5 13690.0 3362.9 0.4484 16.210 - 0.60 15000.0 41. 19703.6 13140.5 2973.7 0.4531 16.045 - 0.60 15000.0 38. 18287.1 12661.6 2593.8 0.4611 16.030 - 0.60 15000.0 35. 16855.3 12167.4 2221.7 0.4739 16.043 - 0.60 15000.0 32. 15219.1 11468.8 1863.5 0.4969 15.805 - 0.60 15000.0 29. 13479.8 10667.1 1507.9 0.5361 15.479 - 0.60 15000.0 26. 11463.2 9588.0 1147.2 0.6118 14.806 - 0.70 15000.0 50. 27576.3 18210.4 4545.7 0.4853 16.247 - 0.70 15000.0 47. 26203.7 17774.4 4104.5 0.4869 16.263 - 0.70 15000.0 44. 24707.5 17214.8 3678.7 0.4910 16.157 - 0.70 15000.0 41. 23090.5 16534.1 3259.8 0.4972 15.938 - 0.70 15000.0 38. 21569.6 15950.1 2851.6 0.5074 15.865 - 0.70 15000.0 35. 20028.7 15345.7 2447.2 0.5226 15.806 - 0.70 15000.0 32. 18262.9 14516.5 2055.2 0.5486 15.538 - 0.70 15000.0 29. 16379.8 13570.1 1665.7 0.5928 15.189 - 0.70 15000.0 26. 14095.8 12222.6 1271.9 0.6790 14.436 - 0.40 20000.0 50. 15216.5 7035.4 2932.5 0.3584 16.537 - 0.40 20000.0 47. 14205.0 6841.8 2622.5 0.3562 16.691 - 0.40 20000.0 44. 13126.8 6582.1 2329.9 0.3560 16.675 - 0.40 20000.0 41. 12035.0 6308.3 2049.5 0.3579 16.671 - 0.40 20000.0 38. 10969.2 6060.5 1777.8 0.3622 16.839 - 0.40 20000.0 35. 9868.8 5778.4 1517.4 0.3710 16.980 - 0.40 20000.0 32. 8700.2 5427.8 1263.9 0.3862 16.979 - 0.40 20000.0 29. 7442.1 4987.8 1021.6 0.4162 16.779 - 0.40 20000.0 26. 6056.2 4420.0 775.9 0.4742 16.253 - 0.50 20000.0 50. 17076.0 9262.6 3104.1 0.3973 16.355 - 0.50 20000.0 47. 16052.2 9020.2 2788.9 0.3966 16.445 - 0.50 20000.0 44. 14950.4 8699.8 2488.3 0.3981 16.391 - 0.50 20000.0 41. 13813.8 8344.4 2196.9 0.4017 16.297 - 0.50 20000.0 38. 12717.4 8029.4 1913.2 0.4081 16.361 - 0.50 20000.0 35. 11594.7 7687.8 1638.2 0.4193 16.426 - 0.50 20000.0 32. 10359.3 7234.1 1372.2 0.4391 16.284 - 0.50 20000.0 29. 9034.1 6690.1 1112.6 0.4747 16.004 - 0.50 20000.0 26. 7541.6 5978.9 846.9 0.5420 15.396 - 0.60 20000.0 50. 19459.8 11828.8 3331.0 0.4365 16.256 - 0.60 20000.0 47. 18401.6 11533.3 3003.3 0.4373 16.297 - 0.60 20000.0 44. 17252.4 11147.6 2687.7 0.4403 16.211 - 0.60 20000.0 41. 16041.6 10700.0 2378.9 0.4454 16.047 - 0.60 20000.0 38. 14888.5 10309.9 2077.9 0.4538 16.032 - 0.60 20000.0 35. 13722.2 9906.7 1782.6 0.4672 16.045 - 0.60 20000.0 32. 12389.9 9337.5 1498.6 0.4910 15.807 - 0.60 20000.0 29. 10972.7 8683.3 1217.3 0.5317 15.481 - 0.60 20000.0 26. 9330.3 7804.1 930.5 0.6097 14.809 - 0.70 20000.0 50. 22451.6 14829.3 3624.5 0.4755 16.247 - 0.70 20000.0 47. 21334.1 14474.1 3275.9 0.4775 16.263 - 0.70 20000.0 44. 20115.6 14017.8 2937.9 0.4818 16.158 - 0.70 20000.0 41. 18799.2 13463.5 2605.4 0.4883 15.939 - 0.70 20000.0 38. 17561.0 12987.7 2281.7 0.4989 15.866 - 0.70 20000.0 35. 16306.2 12495.1 1961.4 0.5147 15.808 - 0.70 20000.0 32. 14867.6 11818.7 1650.7 0.5414 15.539 - 0.70 20000.0 29. 13332.8 11046.1 1342.5 0.5871 15.189 - 0.70 20000.0 26. 11472.5 9948.1 1029.3 0.6752 14.436 - 0.50 25000.0 50. 13787.2 7480.0 2457.9 0.3897 16.355 - 0.50 25000.0 47. 12960.6 7284.2 2211.5 0.3896 16.447 - 0.50 25000.0 44. 12070.7 7024.9 1976.1 0.3916 16.394 - 0.50 25000.0 41. 11153.0 6738.2 1747.0 0.3957 16.301 - 0.50 25000.0 38. 10267.7 6483.4 1525.1 0.4030 16.365 - 0.50 25000.0 35. 9360.5 6206.9 1308.9 0.4150 16.430 - 0.50 25000.0 32. 8363.5 5840.6 1100.5 0.4362 16.290 - 0.50 25000.0 29. 7292.3 5400.2 897.5 0.4743 16.010 - 0.50 25000.0 26. 6085.9 4824.5 688.7 0.5460 15.400 - 0.60 25000.0 50. 15712.1 9552.4 2636.6 0.4280 16.256 - 0.60 25000.0 47. 14857.3 9313.5 2380.3 0.4294 16.298 - 0.60 25000.0 44. 13929.3 9001.5 2133.0 0.4329 16.213 - 0.60 25000.0 41. 12952.0 8640.2 1890.5 0.4385 16.050 - 0.60 25000.0 38. 12020.5 8324.7 1654.6 0.4477 16.036 - 0.60 25000.0 35. 11079.0 7998.9 1422.6 0.4619 16.049 - 0.60 25000.0 32. 10002.2 7538.4 1199.6 0.4869 15.812 - 0.60 25000.0 29. 8856.4 7008.5 979.9 0.5303 15.484 - 0.60 25000.0 26. 7530.0 6298.1 753.5 0.6117 14.813 - 0.70 25000.0 50. 18126.4 11975.4 2867.3 0.4662 16.248 - 0.70 25000.0 47. 17223.8 11687.9 2594.6 0.4687 16.265 - 0.70 25000.0 44. 16239.6 11318.8 2329.7 0.4734 16.159 - 0.70 25000.0 41. 15176.8 10870.9 2068.1 0.4803 15.942 - 0.70 25000.0 38. 14177.3 10486.7 1813.7 0.4914 15.869 - 0.70 25000.0 35. 13164.1 10088.6 1562.1 0.5079 15.811 - 0.70 25000.0 32. 12001.6 9541.2 1318.5 0.5359 15.542 - 0.70 25000.0 29. 10760.3 8914.9 1077.4 0.5838 15.190 - 0.70 25000.0 26. 9257.9 8027.7 830.3 0.6749 14.438 - 0.75 25000.0 50. 19543.4 13346.0 3005.9 0.4850 16.249 - 0.75 25000.0 47. 18609.0 13031.3 2721.9 0.4880 16.267 - 0.75 25000.0 44. 17588.7 12630.8 2445.4 0.4932 16.169 - 0.75 25000.0 41. 16473.8 12135.4 2172.2 0.5007 15.941 - 0.75 25000.0 38. 15431.3 11712.8 1906.9 0.5128 15.847 - 0.75 25000.0 35. 14372.7 11274.0 1642.6 0.5301 15.761 - 0.75 25000.0 32. 13159.5 10680.6 1387.3 0.5596 15.481 - 0.75 25000.0 29. 11862.4 10003.2 1133.2 0.6095 15.123 - 0.75 25000.0 26. 10256.2 9016.7 874.1 0.7052 14.339 - 0.80 25000.0 50. 21116.2 14839.2 3162.6 0.5038 16.250 - 0.80 25000.0 47. 20144.8 14495.5 2865.2 0.5072 16.268 - 0.80 25000.0 44. 19082.5 14060.9 2574.7 0.5127 16.178 - 0.80 25000.0 41. 17907.5 13513.6 2288.1 0.5207 15.948 - 0.80 25000.0 38. 16815.9 13049.7 2009.5 0.5335 15.854 - 0.80 25000.0 35. 15706.3 12567.8 1732.5 0.5520 15.754 - 0.80 25000.0 32. 14436.2 11925.4 1463.5 0.5829 15.466 - 0.80 25000.0 29. 13066.3 11183.2 1195.4 0.6348 15.087 - 0.80 25000.0 26. 11356.9 10101.5 922.2 0.7346 14.293 - 0.50 30000.0 50. 11031.6 5985.9 1931.2 0.3827 16.357 - 0.50 30000.0 47. 10369.9 5828.9 1740.9 0.3834 16.450 - 0.50 30000.0 44. 9657.7 5621.1 1558.2 0.3860 16.397 - 0.50 30000.0 41. 8923.6 5391.6 1380.1 0.3907 16.305 - 0.50 30000.0 38. 8214.9 5187.5 1208.5 0.3992 16.371 - 0.50 30000.0 35. 7489.0 4966.0 1039.9 0.4122 16.437 - 0.50 30000.0 32. 6690.7 4672.4 878.7 0.4354 16.299 - 0.50 30000.0 29. 5832.5 4318.8 722.2 0.4771 16.018 - 0.50 30000.0 26. 4865.8 3856.7 559.8 0.5548 15.404 - 0.60 30000.0 50. 12571.2 7644.3 2070.7 0.4203 16.258 - 0.60 30000.0 47. 11886.8 7452.5 1872.5 0.4223 16.301 - 0.60 30000.0 44. 11144.1 7202.6 1680.6 0.4264 16.216 - 0.60 30000.0 41. 10362.2 6913.2 1492.0 0.4326 16.054 - 0.60 30000.0 38. 9616.6 6660.5 1309.0 0.4428 16.041 - 0.60 30000.0 35. 8862.4 6399.0 1128.2 0.4580 16.053 - 0.60 30000.0 32. 8001.0 6030.2 955.9 0.4850 15.818 - 0.60 30000.0 29. 7082.5 5604.5 786.1 0.5318 15.489 - 0.60 30000.0 26. 6020.8 5035.4 609.2 0.6183 14.819 - 0.70 30000.0 50. 14503.9 9583.4 2250.7 0.4574 16.250 - 0.70 30000.0 47. 13781.4 9353.0 2039.6 0.4606 16.268 - 0.70 30000.0 44. 12993.3 9056.9 1833.8 0.4658 16.162 - 0.70 30000.0 41. 12143.2 8698.7 1630.7 0.4734 15.945 - 0.70 30000.0 38. 11343.1 8390.9 1432.1 0.4851 15.874 - 0.70 30000.0 35. 10532.1 8071.8 1237.0 0.5028 15.816 - 0.70 30000.0 32. 9600.6 7632.4 1048.4 0.5327 15.547 - 0.70 30000.0 29. 8604.9 7128.8 861.9 0.5839 15.193 - 0.70 30000.0 26. 7401.8 6417.7 668.8 0.6796 14.441 - 0.75 30000.0 50. 15637.7 10680.3 2358.6 0.4758 16.251 - 0.75 30000.0 47. 14890.0 10428.3 2138.6 0.4793 16.269 - 0.75 30000.0 44. 14072.5 10106.7 1923.6 0.4850 16.171 - 0.75 30000.0 41. 13180.9 9710.5 1711.8 0.4933 15.944 - 0.75 30000.0 38. 12346.5 9372.0 1504.6 0.5058 15.851 - 0.75 30000.0 35. 11499.0 9020.3 1299.9 0.5244 15.765 - 0.75 30000.0 32. 10526.7 8543.7 1101.9 0.5556 15.485 - 0.75 30000.0 29. 9486.1 7998.9 905.2 0.6087 15.124 - 0.75 30000.0 26. 8199.6 7208.1 702.6 0.7087 14.340 - 0.80 30000.0 50. 16895.3 11875.3 2480.5 0.4941 16.252 - 0.80 30000.0 47. 16118.0 11599.8 2250.0 0.4980 16.270 - 0.80 30000.0 44. 15267.2 11251.2 2024.0 0.5040 16.180 - 0.80 30000.0 41. 14327.1 10813.0 1801.4 0.5126 15.951 - 0.80 30000.0 38. 13453.4 10441.4 1584.4 0.5260 15.858 - 0.80 30000.0 35. 12565.1 10055.1 1369.5 0.5456 15.757 - 0.80 30000.0 32. 11547.3 9539.2 1160.6 0.5780 15.469 - 0.80 30000.0 29. 10450.2 8944.2 952.8 0.6327 15.091 - 0.80 30000.0 26. 9078.8 8074.8 739.8 0.7369 14.293 - 0.85 30000.0 50. 18287.8 13179.4 2618.5 0.5126 16.252 - 0.85 30000.0 47. 17476.4 12878.8 2374.8 0.5165 16.271 - 0.85 30000.0 44. 16587.9 12501.2 2136.8 0.5229 16.188 - 0.85 30000.0 41. 15593.4 12017.8 1901.1 0.5317 15.957 - 0.85 30000.0 38. 14674.6 11609.6 1672.5 0.5457 15.865 - 0.85 30000.0 35. 13739.3 11185.1 1445.7 0.5660 15.767 - 0.85 30000.0 32. 12670.8 10627.5 1225.5 0.5998 15.491 - 0.85 30000.0 29. 11504.3 9971.8 1005.3 0.6560 15.094 - 0.85 30000.0 26. 10047.3 9025.7 780.3 0.7637 14.294 - 0.60 35000.0 50. 9960.8 6057.4 1613.7 0.4134 16.261 - 0.60 35000.0 47. 9418.3 5905.2 1462.4 0.4163 16.305 - 0.60 35000.0 44. 8829.5 5706.8 1315.0 0.4211 16.221 - 0.60 35000.0 41. 8209.9 5477.4 1170.0 0.4282 16.061 - 0.60 35000.0 38. 7618.9 5276.8 1029.7 0.4396 16.049 - 0.60 35000.0 35. 7020.7 5068.9 891.0 0.4565 16.061 - 0.60 35000.0 32. 6337.6 4776.2 759.0 0.4861 15.828 - 0.60 35000.0 29. 5608.2 4437.1 629.0 0.5372 15.497 - 0.60 35000.0 26. 4765.7 3985.0 493.5 0.6321 14.827 - 0.70 35000.0 50. 11491.5 7593.8 1752.8 0.4497 16.252 - 0.70 35000.0 47. 10918.7 7410.8 1590.9 0.4535 16.271 - 0.70 35000.0 44. 10294.2 7176.0 1432.9 0.4595 16.166 - 0.70 35000.0 41. 9620.3 6891.8 1276.4 0.4678 15.951 - 0.70 35000.0 38. 8986.1 6647.4 1124.6 0.4809 15.880 - 0.70 35000.0 35. 8343.1 6394.2 974.5 0.5000 15.824 - 0.70 35000.0 32. 7603.7 6044.7 829.8 0.5323 15.555 - 0.70 35000.0 29. 6812.7 5643.4 687.2 0.5877 15.197 - 0.70 35000.0 26. 5858.1 5078.6 538.3 0.6905 14.445 - 0.75 35000.0 50. 12389.7 8462.9 1836.0 0.4675 16.253 - 0.75 35000.0 47. 11796.9 8262.8 1667.2 0.4717 16.273 - 0.75 35000.0 44. 11149.2 8007.7 1502.2 0.4782 16.175 - 0.75 35000.0 41. 10442.2 7693.4 1338.8 0.4870 15.949 - 0.75 35000.0 38. 9780.9 7424.8 1179.8 0.5007 15.857 - 0.75 35000.0 35. 9108.9 7145.5 1023.0 0.5210 15.772 - 0.75 35000.0 32. 8337.0 6766.3 871.0 0.5545 15.491 - 0.75 35000.0 29. 7510.0 6332.0 720.4 0.6115 15.127 - 0.75 35000.0 26. 6489.2 5703.9 564.2 0.7184 14.343 - 0.80 35000.0 50. 13386.0 9409.8 1929.5 0.4853 16.254 - 0.80 35000.0 47. 12769.6 9191.0 1752.8 0.4898 16.274 - 0.80 35000.0 44. 12095.4 8914.4 1579.6 0.4966 16.184 - 0.80 35000.0 41. 11350.4 8567.0 1407.9 0.5058 15.955 - 0.80 35000.0 38. 10657.8 8272.1 1240.9 0.5201 15.863 - 0.80 35000.0 35. 9953.2 7965.1 1076.6 0.5415 15.764 - 0.80 35000.0 32. 9145.1 7554.7 916.1 0.5760 15.474 - 0.80 35000.0 29. 8274.8 7081.9 756.9 0.6345 15.097 - 0.80 35000.0 26. 7184.6 6389.4 592.6 0.7451 14.294 - 0.85 35000.0 50. 14489.3 10443.3 2036.1 0.5032 16.255 - 0.85 35000.0 47. 13846.2 10204.7 1849.1 0.5078 16.275 - 0.85 35000.0 44. 13141.0 9904.2 1665.9 0.5147 16.192 - 0.85 35000.0 41. 12353.6 9521.4 1484.8 0.5243 15.961 - 0.85 35000.0 38. 11625.4 9197.7 1308.8 0.5391 15.870 - 0.85 35000.0 35. 10883.3 8860.3 1135.3 0.5612 15.773 - 0.85 35000.0 32. 10034.9 8416.5 966.0 0.5968 15.496 - 0.85 35000.0 29. 9109.6 7895.8 796.9 0.6565 15.098 - 0.85 35000.0 26. 7950.8 7141.5 623.6 0.7706 14.293 - 0.90 35000.0 50. 15708.7 11572.7 2156.3 0.5214 16.255 - 0.90 35000.0 47. 15035.3 11312.9 1957.5 0.5259 16.275 - 0.90 35000.0 44. 14297.2 10988.4 1763.3 0.5329 16.200 - 0.90 35000.0 41. 13460.9 10565.7 1571.1 0.5426 15.966 - 0.90 35000.0 38. 12692.3 10210.8 1384.4 0.5579 15.877 - 0.90 35000.0 35. 11908.2 9840.2 1200.3 0.5804 15.781 - 0.90 35000.0 32. 11014.2 9359.8 1020.9 0.6171 15.521 - 0.90 35000.0 29. 10027.2 8786.4 840.8 0.6776 15.127 - 0.90 35000.0 26. 8794.4 7967.2 657.5 0.7948 14.337 - 0.60 39000.0 50. 8223.0 4999.5 1339.1 0.4154 16.265 - 0.60 39000.0 47. 7774.9 4873.8 1215.3 0.4189 16.311 - 0.60 39000.0 44. 7288.6 4709.8 1094.6 0.4245 16.227 - 0.60 39000.0 41. 6777.0 4520.5 975.6 0.4324 16.068 - 0.60 39000.0 38. 6288.8 4354.6 861.0 0.4452 16.057 - 0.60 39000.0 35. 5794.2 4182.4 748.2 0.4642 16.070 - 0.60 39000.0 32. 5229.9 3940.5 640.7 0.4969 15.839 - 0.60 39000.0 29. 4626.5 3659.4 534.7 0.5529 15.507 - 0.60 39000.0 26. 3930.0 3285.3 424.1 0.6578 14.836 - 0.70 39000.0 50. 9486.6 6267.6 1453.2 0.4514 16.256 - 0.70 39000.0 47. 9013.7 6116.6 1321.0 0.4560 16.277 - 0.70 39000.0 44. 8497.6 5922.4 1191.3 0.4626 16.172 - 0.70 39000.0 41. 7941.2 5687.9 1062.8 0.4717 15.958 - 0.70 39000.0 38. 7417.2 5485.8 938.9 0.4861 15.887 - 0.70 39000.0 35. 6885.8 5276.3 816.4 0.5072 15.834 - 0.70 39000.0 32. 6274.4 4986.9 698.5 0.5425 15.564 - 0.70 39000.0 29. 5619.5 4653.8 582.1 0.6028 15.204 - 0.70 39000.0 26. 4830.1 4186.3 460.1 0.7147 14.451 - 0.75 39000.0 50. 10227.7 6984.9 1521.3 0.4691 16.257 - 0.75 39000.0 47. 9738.0 6819.5 1383.5 0.4740 16.278 - 0.75 39000.0 44. 9203.0 6608.8 1248.1 0.4811 16.181 - 0.75 39000.0 41. 8619.3 6349.3 1114.0 0.4907 15.956 - 0.75 39000.0 38. 8072.9 6127.2 984.0 0.5058 15.863 - 0.75 39000.0 35. 7517.6 5896.2 856.2 0.5281 15.781 - 0.75 39000.0 32. 6879.2 5582.1 732.1 0.5644 15.499 - 0.75 39000.0 29. 6194.2 5221.4 609.2 0.6262 15.132 - 0.75 39000.0 26. 5350.2 4701.6 480.8 0.7414 14.347 - 0.80 39000.0 50. 11050.0 7766.4 1598.2 0.4867 16.258 - 0.80 39000.0 47. 10540.9 7585.6 1453.6 0.4919 16.279 - 0.80 39000.0 44. 9983.9 7357.0 1311.5 0.4993 16.189 - 0.80 39000.0 41. 9368.8 7070.2 1170.6 0.5093 15.961 - 0.80 39000.0 38. 8796.7 6826.5 1033.9 0.5248 15.869 - 0.80 39000.0 35. 8214.3 6572.5 900.1 0.5482 15.772 - 0.80 39000.0 32. 7545.9 6232.4 769.0 0.5855 15.482 - 0.80 39000.0 29. 6826.0 5840.9 638.9 0.6486 15.104 - 0.80 39000.0 26. 5923.2 5266.5 503.9 0.7673 14.296 - 0.85 39000.0 50. 11960.5 8619.4 1685.4 0.5044 16.258 - 0.85 39000.0 47. 11428.8 8421.9 1532.5 0.5097 16.279 - 0.85 39000.0 44. 10847.3 8174.3 1382.4 0.5172 16.196 - 0.85 39000.0 41. 10196.6 7857.8 1233.8 0.5275 15.967 - 0.85 39000.0 38. 9595.0 7590.3 1089.3 0.5434 15.876 - 0.85 39000.0 35. 8981.6 7311.0 948.1 0.5675 15.780 - 0.85 39000.0 32. 8279.7 6943.3 809.7 0.6059 15.502 - 0.85 39000.0 29. 7514.3 6512.0 671.6 0.6701 15.104 - 0.85 39000.0 26. 6554.5 5886.3 529.1 0.7919 14.294 - 0.90 39000.0 50. 12967.0 9551.6 1783.9 0.5223 16.258 - 0.90 39000.0 47. 12410.7 9336.9 1621.7 0.5276 16.280 - 0.90 39000.0 44. 11800.9 9068.6 1462.1 0.5351 16.204 - 0.90 39000.0 41. 11110.5 8719.6 1304.4 0.5456 15.972 - 0.90 39000.0 38. 10475.6 8426.4 1151.3 0.5618 15.883 - 0.90 39000.0 35. 9827.3 8119.6 1001.4 0.5864 15.788 - 0.90 39000.0 32. 9087.5 7721.4 854.4 0.6254 15.527 - 0.90 39000.0 29. 8271.3 7246.6 707.3 0.6903 15.133 - 0.90 39000.0 26. 7249.8 6566.7 556.7 0.8150 14.336 - 0.70 43000.0 50. 7829.8 5171.4 1214.4 0.4568 16.262 - 0.70 43000.0 47. 7439.1 5046.5 1105.7 0.4621 16.283 - 0.70 43000.0 44. 7013.1 4886.4 998.6 0.4695 16.179 - 0.70 43000.0 41. 6553.6 4692.7 892.8 0.4798 15.966 - 0.70 43000.0 38. 6120.6 4525.5 790.9 0.4958 15.896 - 0.70 43000.0 35. 5681.6 4352.4 690.9 0.5198 15.845 - 0.70 43000.0 32. 5175.8 4112.4 594.3 0.5589 15.575 - 0.70 43000.0 29. 4633.3 3835.8 498.6 0.6252 15.212 - 0.70 43000.0 26. 3980.4 3448.7 398.8 0.7500 14.457 - 0.75 43000.0 50. 8441.5 5763.2 1270.7 0.4744 16.262 - 0.75 43000.0 47. 8037.1 5626.6 1157.2 0.4801 16.284 - 0.75 43000.0 44. 7595.1 5452.6 1045.5 0.4880 16.187 - 0.75 43000.0 41. 7113.3 5238.4 935.0 0.4987 15.964 - 0.75 43000.0 38. 6661.7 5054.7 828.1 0.5153 15.872 - 0.75 43000.0 35. 6202.8 4863.7 723.6 0.5403 15.792 - 0.75 43000.0 32. 5674.6 4603.3 621.9 0.5805 15.510 - 0.75 43000.0 29. 5107.0 4303.5 520.8 0.6482 15.139 - 0.75 43000.0 26. 4408.8 3873.1 415.4 0.7755 14.352 - 0.80 43000.0 50. 9120.0 6408.0 1334.3 0.4920 16.263 - 0.80 43000.0 47. 8699.5 6258.7 1215.2 0.4979 16.285 - 0.80 43000.0 44. 8239.6 6070.0 1097.7 0.5059 16.195 - 0.80 43000.0 41. 7731.5 5833.1 981.5 0.5170 15.969 - 0.80 43000.0 38. 7258.8 5631.6 869.1 0.5341 15.878 - 0.80 43000.0 35. 6777.5 5421.5 759.6 0.5602 15.782 - 0.80 43000.0 32. 6224.2 5139.5 652.1 0.6011 15.491 - 0.80 43000.0 29. 5628.9 4815.3 545.2 0.6701 15.113 - 0.80 43000.0 26. 4880.9 4338.5 433.7 0.7996 14.300 - 0.85 43000.0 50. 9871.7 7111.8 1406.2 0.5095 16.263 - 0.85 43000.0 47. 9433.1 6949.2 1280.6 0.5155 16.285 - 0.85 43000.0 44. 8952.4 6744.4 1156.3 0.5237 16.203 - 0.85 43000.0 41. 8415.1 6483.2 1033.7 0.5351 15.974 - 0.85 43000.0 38. 7917.9 6262.0 914.8 0.5524 15.884 - 0.85 43000.0 35. 7410.8 6030.8 799.3 0.5792 15.789 - 0.85 43000.0 32. 6829.9 5725.9 685.6 0.6210 15.511 - 0.85 43000.0 29. 6196.5 5368.6 572.0 0.6909 15.112 - 0.85 43000.0 26. 5401.2 4849.2 454.3 0.8230 14.296 - 0.90 43000.0 50. 10701.9 7881.0 1487.5 0.5273 16.263 - 0.90 43000.0 47. 10242.4 7703.6 1353.7 0.5332 16.285 - 0.90 43000.0 44. 9738.9 7482.1 1222.0 0.5415 16.210 - 0.90 43000.0 41. 9168.7 7194.0 1092.0 0.5530 15.978 - 0.90 43000.0 38. 8644.2 6951.7 965.6 0.5705 15.890 - 0.90 43000.0 35. 8108.0 6697.6 843.1 0.5977 15.797 - 0.90 43000.0 32. 7495.8 6367.4 722.4 0.6402 15.535 - 0.90 43000.0 29. 6820.3 5974.0 601.3 0.7105 15.140 - 0.90 43000.0 26. 5973.7 5409.5 476.7 0.8450 14.337 \ No newline at end of file diff --git a/aviary/utils/test/data/aero_BWB_modified_GASP.txt b/aviary/utils/test/data/aero_BWB_modified_GASP.txt new file mode 100644 index 0000000000..23918786d4 --- /dev/null +++ b/aviary/utils/test/data/aero_BWB_modified_GASP.txt @@ -0,0 +1,95 @@ + 0 1 -1 1 4876.0 1.0 +VVID HWB: Modified CFD Lift Coeff CL Aero Tables - 6/16/2025 (made-up only for demonstration purposes) + 3 + + 5 9 0.0 + 0.2300 0.7000 0.8000 0.8200 0.8500 + 0.00 -0.15391 -0.15596 -0.19050 -0.19687 -0.20542 + 2.00 -0.04321 -0.03172 -0.03875 -0.03838 -0.03628 + 4.00 0.06749 0.09122 0.11142 0.12010 0.13287 + 5.00 0.12432 0.15080 0.18420 0.18861 0.19911 + 6.00 0.18011 0.21039 0.25698 0.25711 0.25321 + 8.00 0.28557 0.26884 0.32838 0.34490 0.36142 + 10.00 0.36854 0.32730 0.39979 0.43470 0.46962 + 12.00 0.43517 0.38576 0.47119 0.52473 0.57783 + 15.00 0.47486 0.47344 0.57829 0.65921 0.74013 + + 5 9 30000.0 + 0.2300 0.7000 0.8000 0.8200 0.8500 + 0.00 -0.15391 -0.15596 -0.19050 -0.19687 -0.20542 + 2.00 -0.04321 -0.03172 -0.03875 -0.03838 -0.03628 + 4.00 0.06749 0.09122 0.11142 0.12010 0.13287 + 5.00 0.12432 0.15080 0.18420 0.18861 0.19911 + 6.00 0.18011 0.21039 0.25698 0.25711 0.25321 + 8.00 0.28557 0.26884 0.32838 0.34490 0.36142 + 10.00 0.36854 0.32730 0.39979 0.43470 0.46962 + 12.00 0.43517 0.38576 0.47119 0.52473 0.57783 + 15.00 0.47486 0.47344 0.57829 0.65921 0.74013 + + 5 9 41000.0 + 0.2300 0.7000 0.8000 0.8200 0.8500 + 0.00 -0.15391 -0.15596 -0.19050 -0.19687 -0.20542 + 2.00 -0.04321 -0.03172 -0.03875 -0.03838 -0.03628 + 4.00 0.06749 0.09122 0.11142 0.12010 0.13287 + 5.00 0.12432 0.15080 0.18420 0.18861 0.19911 + 6.00 0.18011 0.21039 0.25698 0.25711 0.25321 + 8.00 0.28557 0.26884 0.32838 0.34490 0.36142 + 10.00 0.36854 0.32730 0.39979 0.43470 0.46962 + 12.00 0.43517 0.38576 0.47119 0.52473 0.57783 + 15.00 0.47486 0.47344 0.57829 0.65921 0.74013 +CD Aero Tables (Modifed from original CFD results to give better L/D) + 3 + + 5 15 0.0 + 0.2300 0.7000 0.8000 0.8200 0.8500 + -0.20000 0.003225 0.006166 0.007889 0.004069 0.002926 + 0.00000 0.005100 0.003795 0.005320 0.005125 0.005500 + 0.05000 0.005055 0.003663 0.004935 0.005444 0.006699 + 0.10000 0.005588 0.004301 0.005180 0.006306 0.008146 + 0.15000 0.006488 0.006089 0.006398 0.007813 0.009812 + 0.20000 0.007560 0.009334 0.008610 0.009969 0.013750 + 0.25000 0.008880 0.014196 0.011620 0.012713 0.018849 + 0.30000 0.011040 0.020614 0.017500 0.015956 0.025078 + 0.35000 0.015398 0.028210 0.025893 0.019569 0.031303 + 0.40000 0.024345 0.036229 0.034482 0.023419 0.037565 + 0.45000 0.041528 0.043445 0.043855 0.027369 0.043844 + 0.50000 0.072128 0.049940 0.053158 0.031306 0.050105 + 0.55000 0.123098 0.057118 0.061187 0.035156 0.056353 + 0.60000 0.203415 0.064323 0.066332 0.038894 0.062607 + 0.80000 0.283725 0.093500 0.087920 0.055038 0.087604 + + 5 15 30000.0 + 0.2300 0.7000 0.8000 0.8200 0.8500 + -0.20000 0.003225 0.006166 0.007889 0.004069 0.002926 + 0.00000 0.005100 0.003795 0.005320 0.005125 0.005500 + 0.05000 0.005055 0.003663 0.004935 0.005444 0.006699 + 0.10000 0.005588 0.004301 0.005180 0.006306 0.008146 + 0.15000 0.006488 0.006089 0.006398 0.007813 0.009812 + 0.20000 0.007560 0.009334 0.008610 0.009969 0.013750 + 0.25000 0.008880 0.014196 0.011620 0.012713 0.018849 + 0.30000 0.011040 0.020614 0.017500 0.015956 0.025078 + 0.35000 0.015398 0.028210 0.025893 0.019569 0.031303 + 0.40000 0.024345 0.036229 0.034482 0.023419 0.037565 + 0.45000 0.041528 0.043445 0.043855 0.027369 0.043844 + 0.50000 0.072128 0.049940 0.053158 0.031306 0.050105 + 0.55000 0.123098 0.057118 0.061187 0.035156 0.056353 + 0.60000 0.203415 0.064323 0.066332 0.038894 0.062607 + 0.80000 0.283725 0.093500 0.087920 0.055038 0.087604 + + 5 15 41000.0 + 0.2300 0.7000 0.8000 0.8200 0.8500 + -0.20000 0.003225 0.006166 0.007889 0.004069 0.002926 + 0.00000 0.005100 0.003795 0.005320 0.005125 0.005500 + 0.05000 0.005055 0.003663 0.004935 0.005444 0.006699 + 0.10000 0.005588 0.004301 0.005180 0.006306 0.008146 + 0.15000 0.006488 0.006089 0.006398 0.007813 0.009812 + 0.20000 0.007560 0.009334 0.008610 0.009969 0.013750 + 0.25000 0.008880 0.014196 0.011620 0.012713 0.018849 + 0.30000 0.011040 0.020614 0.017500 0.015956 0.025078 + 0.35000 0.015398 0.028210 0.025893 0.019569 0.031303 + 0.40000 0.024345 0.036229 0.034482 0.023419 0.037565 + 0.45000 0.041528 0.043445 0.043855 0.027369 0.043844 + 0.50000 0.072128 0.049940 0.053158 0.031306 0.050105 + 0.55000 0.123098 0.057118 0.061187 0.035156 0.056353 + 0.60000 0.203415 0.064323 0.066332 0.038894 0.062607 + 0.80000 0.283725 0.093500 0.087920 0.055038 0.087604 diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt b/aviary/utils/test/data/aero_flaps_GASP.txt similarity index 99% rename from aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt rename to aviary/utils/test/data/aero_flaps_GASP.txt index 3662a029cd..5d93350f3b 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt +++ b/aviary/utils/test/data/aero_flaps_GASP.txt @@ -1,4 +1,3 @@ -# # Incremental Lift and Drag Coeff. for Flaps # Reference Area = 1370. sqft # DELFLP MACH ALPHA DEL_CL DEL_CD diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_free.txt b/aviary/utils/test/data/aero_free_GASP.txt similarity index 99% rename from aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_free.txt rename to aviary/utils/test/data/aero_free_GASP.txt index 4b9d6ba1ab..ac147e8701 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_free.txt +++ b/aviary/utils/test/data/aero_free_GASP.txt @@ -1,4 +1,3 @@ -# # Clean / Free Air Aerodynamics # Reference Area = 1370. sqft # Altitude Mach ALPHA CLTOT CD diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_free_reduced_alpha.txt b/aviary/utils/test/data/aero_free_reduced_alpha_GASP.txt similarity index 99% rename from aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_free_reduced_alpha.txt rename to aviary/utils/test/data/aero_free_reduced_alpha_GASP.txt index e8ad2cc340..62ef0aab60 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_free_reduced_alpha.txt +++ b/aviary/utils/test/data/aero_free_reduced_alpha_GASP.txt @@ -1,4 +1,3 @@ -# # Clean / Free Air Aerodynamics # Copy of GASP_aero_free.txt with alpha above 10 removed # Reference Area = 1370. sqft diff --git a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_ground.txt b/aviary/utils/test/data/aero_ground_GASP.txt similarity index 99% rename from aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_ground.txt rename to aviary/utils/test/data/aero_ground_GASP.txt index c03c6d6a60..e9ac51f414 100644 --- a/aviary/subsystems/aerodynamics/gasp_based/data/GASP_aero_ground.txt +++ b/aviary/utils/test/data/aero_ground_GASP.txt @@ -1,4 +1,3 @@ -# # Incremental Lift and Drag Coeff. for Ground Effects # Reference Area = 1370. sqft / Flap Deflection = 10 deg (T.O. Setting) # MACH ALPHA HOB DEL_CL DEL_CD diff --git a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat b/aviary/utils/test/data/configuration_test_data_GASP.dat similarity index 99% rename from aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat rename to aviary/utils/test/data/configuration_test_data_GASP.dat index d2c81517f3..fe44e08e68 100644 --- a/aviary/models/test_aircraft/converter_configuration_test_data_GwGm.dat +++ b/aviary/utils/test/data/configuration_test_data_GASP.dat @@ -1,7 +1,4 @@ Baseline new configuration Mach 0.80 / 23k SLS thrust turbofan -1 -1 - -aircraft:engine:reference_diameter = 6.15, -aircraft:engine:data_file=models/engines/turbofan_23k_1.deck $INGASP AS=1., ! Number of aisles in the cabin @@ -234,4 +231,3 @@ aircraft:engine:data_file=models/engines/turbofan_23k_1.deck TBO=3500., ! time between overhauls, hr (0. default which deletes cost computations) TR=1.0, ! property tax rate; tax/value (0.) $END - diff --git a/aviary/utils/test/data/converter_test_BWB_GASP.csv b/aviary/utils/test/data/converter_test_BWB_GASP.csv new file mode 100644 index 0000000000..eb999a830d --- /dev/null +++ b/aviary/utils/test/data/converter_test_BWB_GASP.csv @@ -0,0 +1,256 @@ +# GASP-derived aircraft input deck converted from generic_BWB_GASP.dat + +# Input Values +aircraft:air_conditioning:mass_coefficient,1.155,unitless +aircraft:anti_icing:mass,236.0,lbm +aircraft:apu:mass,710.0,lbm +aircraft:avionics:mass,3225.0,lbm +aircraft:blended_wing_body_design:passenger_leading_edge_sweep,65.0,deg +aircraft:controls:cockpit_control_mass_scaler,1.0,unitless +aircraft:controls:control_mass_increment,0.0,lbm +aircraft:controls:stability_augmentation_system_mass,0.0,lbm +aircraft:controls:stability_augmentation_system_mass_scaler,1.0,unitless +aircraft:crew_and_payload:cargo_mass,0.0,lbm +aircraft:crew_and_payload:catering_items_mass_per_passenger,5.0,lbm +aircraft:crew_and_payload:design:cargo_mass,0.0,lbm +aircraft:crew_and_payload:design:max_cargo_mass,15000.0,lbm +aircraft:crew_and_payload:design:num_first_class,11,unitless +aircraft:crew_and_payload:design:num_passengers,150,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,18,unitless +aircraft:crew_and_payload:design:num_tourist_class,139,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,32.0,inch +aircraft:crew_and_payload:passenger_mass_with_bags,225.0,lbm +aircraft:crew_and_payload:passenger_service_mass_per_passenger,6.0,lbm +aircraft:crew_and_payload:uld_mass_per_passenger,0.0667,lbm +aircraft:crew_and_payload:water_mass_per_occupant,3.0,lbm +aircraft:design:cg_delta,0.25,unitless +aircraft:design:cockpit_control_mass_coefficient,16.5,unitless +aircraft:design:drag_coeff_increment,0.00025,unitless +aircraft:design:drag_divergence_shift,0.025,unitless +aircraft:design:emergency_equipment_mass,100.0,lbm +aircraft:design:max_structural_speed,402.5,mi/h +aircraft:design:part25_structural_category,3.0,unitless +aircraft:design:reserve_fuel_additional,0.2222,lbm +aircraft:design:static_margin,0.05,unitless +aircraft:design:structural_mass_increment,0.0,lbm +aircraft:design:type,BWB,unitless +aircraft:design:wing_loading,70.0,lbf/ft**2 +aircraft:electrical:system_mass_per_passenger,11.45,lbm +aircraft:engine:additional_mass_fraction,0.04373,unitless +aircraft:engine:global_throttle,True,unitless +aircraft:engine:mass_scaler,1.0,unitless +aircraft:engine:mass_specific,0.178884,lbm/lbf +aircraft:engine:num_engines,2,unitless +aircraft:engine:num_fuselage_engines,2,unitless +aircraft:engine:pod_mass_scaler,1.0,unitless +aircraft:engine:pylon_factor,1.25,unitless +aircraft:engine:reference_sls_thrust,28690.0,lbf +aircraft:engine:scaled_sls_thrust,19580.2,lbf +aircraft:engine:type,7,unitless +aircraft:engine:wing_locations,0.0,unitless +aircraft:fuel:density,6.687,lbm/galUS +aircraft:fuel:fuel_margin,10.0,unitless +aircraft:fuel:fuel_system_mass_coefficient,0.035,unitless +aircraft:fuel:fuel_system_mass_scaler,1.0,unitless +aircraft:fuel:unusable_fuel_mass_coefficient,12.0,unitless +aircraft:fuel:wing_fuel_fraction,0.45,unitless +aircraft:furnishings:mass_scaler,40.0,lbm +aircraft:fuselage:aftbody_mass_per_unit_area,5.0,lbm/ft**2 +aircraft:fuselage:aisle_width,22.0,inch +aircraft:fuselage:delta_diameter,5.0,ft +aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 +aircraft:fuselage:height_to_width_ratio,0.2597,unitless +aircraft:fuselage:lift_coefficient_ratio_body_to_wing,0.35,unitless +aircraft:fuselage:lift_curve_slope_mach0,1.8265,1/rad +aircraft:fuselage:mass_coefficient,0.889,unitless +aircraft:fuselage:nose_fineness,0.6,unitless +aircraft:fuselage:num_aisles,3,unitless +aircraft:fuselage:pilot_compartment_length,7.5,ft +aircraft:fuselage:pressure_differential,10.0,psi +aircraft:fuselage:pressurized_width_additional,0.0,ft +aircraft:fuselage:seat_width,21.0,inch +aircraft:fuselage:tail_fineness,1.75,unitless +aircraft:fuselage:wetted_area_ratio_aftbody_to_total,0.2,unitless +aircraft:fuselage:wetted_area_scaler,1.0001,unitless +aircraft:horizontal_tail:aspect_ratio,1.705,unitless +aircraft:horizontal_tail:mass_coefficient,0.124,unitless +aircraft:horizontal_tail:moment_ratio,0.5463,unitless +aircraft:horizontal_tail:sweep,45.0,deg +aircraft:horizontal_tail:taper_ratio,0.366,unitless +aircraft:horizontal_tail:thickness_to_chord,0.1,unitless +aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless +aircraft:horizontal_tail:volume_coefficient,1e-06,unitless +aircraft:hydraulics:flight_control_mass_coefficient,0.107,unitless +aircraft:hydraulics:gear_mass_coefficient,0.135,unitless +aircraft:instruments:mass_coefficient,0.116,unitless +aircraft:landing_gear:fixed_gear,False,unitless +aircraft:landing_gear:main_gear_location,0.0,unitless +aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless +aircraft:landing_gear:mass_coefficient,0.052,unitless +aircraft:landing_gear:tail_hook_mass_scaler,1.0,unitless +aircraft:landing_gear:total_mass_scaler,1.0,unitless +aircraft:nacelle:clearance_ratio,0.2,unitless +aircraft:nacelle:core_diameter_ratio,1.2205,unitless +aircraft:nacelle:fineness,1.3588,unitless +aircraft:nacelle:form_factor,1.2,unitless +aircraft:nacelle:mass_specific,2.5,lbm/ft**2 +aircraft:nacelle:percent_diam_buried_in_fuselage,0.0,unitless +aircraft:strut:area_ratio,0.0,unitless +aircraft:strut:attachment_location,0.0,ft +aircraft:strut:attachment_location_dimensionless,0.0,unitless +aircraft:strut:dimensional_location_specified,False,unitless +aircraft:strut:fuselage_interference_factor,1.0,unitless +aircraft:strut:mass_coefficient,0.0,unitless +aircraft:strut:thickness_to_chord,0.0,unitless +aircraft:vertical_tail:aspect_ratio,1.705,unitless +aircraft:vertical_tail:mass_coefficient,0.119,unitless +aircraft:vertical_tail:moment_ratio,5.2615,unitless +aircraft:vertical_tail:sweep,35.0,deg +aircraft:vertical_tail:taper_ratio,0.366,unitless +aircraft:vertical_tail:thickness_to_chord,0.1,unitless +aircraft:vertical_tail:volume_coefficient,0.015,unitless +aircraft:wing:aspect_ratio,10.0,unitless +aircraft:wing:center_distance,0.463,unitless +aircraft:wing:choose_fold_location,True,unitless +aircraft:wing:flap_chord_ratio,0.2,unitless +aircraft:wing:flap_deflection_landing,25.0,deg +aircraft:wing:flap_deflection_takeoff,15.0,deg +aircraft:wing:flap_drag_increment_optimum,0.1,unitless +aircraft:wing:flap_lift_increment_optimum,1.5,unitless +aircraft:wing:flap_span_ratio,0.61,unitless +aircraft:wing:flap_type,double_slotted,unitless +aircraft:wing:fold_dimensional_location_specified,True,unitless +aircraft:wing:fold_mass_coefficient,0.15,unitless +aircraft:wing:folded_span,118.0,ft +aircraft:wing:fuselage_interference_factor,1.0,unitless +aircraft:wing:has_fold,True,unitless +aircraft:wing:has_strut,False,unitless +aircraft:wing:height,12.5,ft +aircraft:wing:high_lift_mass_coefficient,1.0,unitless +aircraft:wing:incidence,1.5,deg +aircraft:wing:mass_coefficient,75.78,unitless +aircraft:wing:max_lift_ref,1.45,unitless +aircraft:wing:max_slat_deflection_landing,0.0,deg +aircraft:wing:max_slat_deflection_takeoff,0.0,deg +aircraft:wing:max_thickness_location,0.325,unitless +aircraft:wing:min_pressure_location,0.275,unitless +aircraft:wing:num_flap_segments,2,unitless +aircraft:wing:optimum_flap_deflection,55,deg +aircraft:wing:optimum_slat_deflection,20.0,deg +aircraft:wing:slat_chord_ratio,0.0001,unitless +aircraft:wing:slat_lift_increment_optimum,0.93,unitless +aircraft:wing:surface_control_mass_coefficient,0.5,unitless +aircraft:wing:sweep,30.0,deg +aircraft:wing:taper_ratio,0.27444,unitless +aircraft:wing:thickness_to_chord_root,0.165,unitless +aircraft:wing:thickness_to_chord_tip,0.1,unitless +aircraft:wing:vertical_mount_location,0.5,unitless +aircraft:wing:zero_lift_angle,0.0,deg +mission:design:cruise_altitude,41000.0,ft +mission:design:gross_mass,150000.0,lbm +mission:design:mach,0.8,unitless +mission:design:range,3500.0,NM +mission:design:rate_of_climb_at_top_of_climb,300.0,ft/min +mission:landing:airport_altitude,0,ft +mission:landing:braking_delay,1.0,s +mission:landing:glide_to_stall_ratio,1.3,unitless +mission:landing:maximum_flare_load_factor,1.15,unitless +mission:landing:maximum_sink_rate,900.0,ft/min +mission:landing:obstacle_height,50.0,ft +mission:landing:touchdown_sink_rate,5.0,ft/s +mission:summary:fuel_flow_scaler,1.0,unitless +mission:takeoff:decision_speed_increment,10.0,kn +mission:takeoff:rotation_speed_increment,5.0,kn +mission:taxi:duration,0.1677,h +settings:aerodynamics_method,GASP,unitless +settings:equations_of_motion,2DOF,unitless +settings:mass_method,GASP,unitless + +# Initialization Guesses +actual_takeoff_mass,0 +climb_range,0 +cruise_mass_final,0 +flight_duration,0 +fuel_burn_per_passenger_mile,0 +reserves,0 +rotation_mass,0 +time_to_climb,0 + +# Unconverted Values +.GenericHybrid-WingBodyConfiguration/SacledNASAGRCGTF/FPR,1.45-1 +INGASP.ALR,1.11 +INGASP.BENGOB,0 +INGASP.CINP,0.11 +INGASP.CLIAB,1984 +INGASP.CMF,15 +INGASP.CMV,0.15 +INGASP.CRWOH,15 +INGASP.CW,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +INGASP.DCDSE,0.001 +INGASP.DYR,12 +INGASP.EL_FLGC,8 +INGASP.EMCRU,0.8 +INGASP.FCFFC,0.885 +INGASP.FCFFT,0.93 +INGASP.FCFHTC,0.75 +INGASP.FCFHTT,0.926 +INGASP.FCFNC,1.15 +INGASP.FCFNT,0.95 +INGASP.FCFVTC,0.9 +INGASP.FCFVTT,0.926 +INGASP.FCFWC,0.906 +INGASP.FCFWT,0.926 +INGASP.FCKIC,1 +INGASP.FCKIT,1 +INGASP.FCMPC,1 +INGASP.FCSF,2.5 +INGASP.FEXCRT,0.8 +INGASP.FPYLND,1.15 +INGASP.FSA7C,0.85 +INGASP.HBTP,0.465 +INGASP.HIR,0.015 +INGASP.HNCRU,41000 +INGASP.HQBWGLT,0.0607 +INGASP.HRI,2500 +INGASP.HSCREQ,20000 +INGASP.ICLM,3 +INGASP.ICONVRG,1 +INGASP.ICRUS,10 +INGASP.ISWING,0 +INGASP.IWLD,2 +INGASP.JENGSZ,3 +INGASP.KNAC,1 +INGASP.KODEAC,7 +INGASP.KODECL,7 +INGASP.KODETO,5 +INGASP.KODETR,6 +INGASP.MX,0 +INGASP.NFAIL,0 +INGASP.OFALT,0 +INGASP.OFEM,0.78 +INGASP.OHR,350 +INGASP.PRV,0.15 +INGASP.RCCRU,10 +INGASP.RELP,0 +INGASP.RELR,0.4524 +INGASP.RF,2.0,200.0,-1.0,1500.0,4.0,3.0,0.0,0.0 +INGASP.RI,0.8 +INGASP.ROSCAB,9999 +INGASP.RWCRTX,0.985 +INGASP.SKPES,0.258 +INGASP.SM1D,0.625 +INGASP.SRPM,18000 +INGASP.TBO,3500 +INGASP.TDELLD,27 +INGASP.TDELTO,27 +INGASP.TDELTX,27 +INGASP.TR,1 +INGASP.UWTWGLT,10 +INGASP.VCLMB,270 +INGASP.VDSCNT,-300 +INGASP.WENG,6130 +INGASP.WLPCT,0.9423 +INGASP.WNAC,0 +INGASP.WPLX,0 +INGASP.WPYLON,0 +INGASP.XTORQ,6950 diff --git a/aviary/utils/test/data/converter_test_N3CC_FLOPS.csv b/aviary/utils/test/data/converter_test_N3CC_FLOPS.csv new file mode 100644 index 0000000000..203f02904e --- /dev/null +++ b/aviary/utils/test/data/converter_test_N3CC_FLOPS.csv @@ -0,0 +1,446 @@ +# FLOPS-derived aircraft input deck converted from N3CC_generic_low_speed_polars_FLOPS.txt + +# Input Values +aircraft:air_conditioning:mass_scaler,0.98094,unitless +aircraft:anti_icing:mass_scaler,0.53202,unitless +aircraft:apu:mass_scaler,1.02321,unitless +aircraft:avionics:mass_scaler,1.123226,unitless +aircraft:canard:laminar_flow_lower,0.0,unitless +aircraft:canard:laminar_flow_upper,0.0,unitless +aircraft:canard:mass_scaler,1.0,unitless +aircraft:crew_and_payload:baggage_mass_per_passenger,35.0,lbm +aircraft:crew_and_payload:design:num_business_class,20,unitless +aircraft:crew_and_payload:design:num_first_class,16,unitless +aircraft:crew_and_payload:design:num_tourist_class,118,unitless +aircraft:crew_and_payload:flight_crew_mass_scaler,1.0,unitless +aircraft:crew_and_payload:mass_per_passenger,165.0,lbm +aircraft:crew_and_payload:misc_cargo,0.0,lbm +aircraft:crew_and_payload:non_flight_crew_mass_scaler,1.0,unitless +aircraft:crew_and_payload:num_flight_attendants,-1,unitless +aircraft:crew_and_payload:num_flight_crew,-1,unitless +aircraft:crew_and_payload:num_galley_crew,-1,unitless +aircraft:crew_and_payload:passenger_service_mass_scaler,1.0,unitless +aircraft:crew_and_payload:wing_cargo,0.0,lbm +aircraft:design:base_area,0.0,ft**2 +aircraft:design:empty_mass_margin_scaler,0.01498,unitless +aircraft:design:landing_to_takeoff_mass_ratio,0.84,unitless +aircraft:design:lift_dependent_drag_coeff_factor,0.93,unitless +aircraft:design:subsonic_drag_coeff_factor,0.95,unitless +aircraft:design:supersonic_drag_coeff_factor,1.0,unitless +aircraft:design:touchdown_mass,0.0,lbm +aircraft:design:use_alt_mass,False,unitless +aircraft:design:zero_lift_drag_coeff_factor,0.96,unitless +aircraft:electrical:mass_scaler,1.1976,unitless +aircraft:engine:additional_mass_fraction,0.0,unitless +aircraft:engine:constant_fuel_consumption,0.0,lbm/h +aircraft:engine:flight_idle_max_fraction,1.0,unitless +aircraft:engine:flight_idle_min_fraction,0.08,unitless +aircraft:engine:fuel_flow_scaler_constant_term,0.0,unitless +aircraft:engine:fuel_flow_scaler_linear_term,0.0,unitless +aircraft:engine:generate_flight_idle,True,unitless +aircraft:engine:geopotential_alt,False,unitless +aircraft:engine:ignore_negative_thrust,False,unitless +aircraft:engine:mass_scaler,1.15,unitless +aircraft:engine:num_fuselage_engines,0,unitless +aircraft:engine:num_wing_engines,2,unitless +aircraft:engine:reference_mass,6293.8,lbm +aircraft:engine:reference_sls_thrust,22200.5,lbf +aircraft:engine:scaled_sls_thrust,22200.0,0.0,0.0,0.0,0.0,0.0,lbf +aircraft:engine:subsonic_fuel_flow_scaler,1.0,unitless +aircraft:engine:supersonic_fuel_flow_scaler,1.0,unitless +aircraft:engine:wing_locations,0.289682918,unitless +aircraft:fins:area,0.0,ft**2 +aircraft:fins:mass_scaler,1.0,unitless +aircraft:fins:num_fins,0,unitless +aircraft:fins:taper_ratio,-10.0,unitless +aircraft:fuel:auxiliary_fuel_capacity,0.0,lbm +aircraft:fuel:density,6.7,lbm/galUS +aircraft:fuel:fuel_system_mass_scaler,0.93202,unitless +aircraft:fuel:fuselage_fuel_capacity,0.0,lbm +aircraft:fuel:ignore_fuel_capacity_constraint,False,unitless +aircraft:fuel:num_tanks,7,unitless +aircraft:fuel:total_capacity,0.0,lbm +aircraft:fuel:unusable_fuel_mass_scaler,1.0,unitless +aircraft:fuel:wing_fuel_fraction,0.7752373238926116,unitless +aircraft:furnishings:mass_scaler,0.81859,unitless +aircraft:fuselage:laminar_flow_lower,0.0,unitless +aircraft:fuselage:laminar_flow_upper,0.0,unitless +aircraft:fuselage:length,125.0,ft +aircraft:fuselage:mass_scaler,0.69981,unitless +aircraft:fuselage:max_height,13.0,ft +aircraft:fuselage:max_width,12.3,ft +aircraft:fuselage:military_cargo_floor,False,unitless +aircraft:fuselage:num_fuselages,1,unitless +aircraft:fuselage:passenger_compartment_length,97.5,ft +aircraft:fuselage:wetted_area,4235.082096,ft**2 +aircraft:horizontal_tail:area,349.522730527158,ft**2 +aircraft:horizontal_tail:aspect_ratio,5.22699386503068,unitless +aircraft:horizontal_tail:laminar_flow_lower,0.0,unitless +aircraft:horizontal_tail:laminar_flow_upper,29.0,unitless +aircraft:horizontal_tail:mass_scaler,1.42225,unitless +aircraft:horizontal_tail:sweep,30.5853213018973,deg +aircraft:horizontal_tail:taper_ratio,0.2734375,unitless +aircraft:horizontal_tail:thickness_to_chord,0.115,unitless +aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless +aircraft:horizontal_tail:wetted_area,576.571192,ft**2 +aircraft:hydraulics:mass_scaler,0.95543,unitless +aircraft:hydraulics:system_pressure,5000.0,psi +aircraft:instruments:mass_scaler,1.66955,unitless +aircraft:landing_gear:drag_coefficient,0.024,unitless +aircraft:landing_gear:main_gear_mass_scaler,0.8846,unitless +aircraft:landing_gear:main_gear_oleo_length,0.0,inch +aircraft:landing_gear:nose_gear_mass_scaler,0.8846,unitless +aircraft:landing_gear:nose_gear_oleo_length,0.0,inch +aircraft:nacelle:avg_diameter,7.2,ft +aircraft:nacelle:avg_length,35.0,ft +aircraft:nacelle:laminar_flow_lower,0.0,unitless +aircraft:nacelle:laminar_flow_upper,0.0,unitless +aircraft:nacelle:wetted_area,244.468282,ft**2 +aircraft:paint:mass_per_unit_area,0.0,lbm/ft**2 +aircraft:propulsion:engine_oil_mass_scaler,1.0,unitless +aircraft:propulsion:misc_mass_scaler,0.0,unitless +aircraft:vertical_tail:area,227.184358191707,ft**2 +aircraft:vertical_tail:aspect_ratio,1.77777777777778,unitless +aircraft:vertical_tail:laminar_flow_lower,29.0,unitless +aircraft:vertical_tail:laminar_flow_upper,29.0,unitless +aircraft:vertical_tail:mass_scaler,1.42225,unitless +aircraft:vertical_tail:num_tails,1,unitless +aircraft:vertical_tail:sweep,39.735053245438,deg +aircraft:vertical_tail:taper_ratio,0.25,unitless +aircraft:vertical_tail:thickness_to_chord,0.1,unitless +aircraft:vertical_tail:wetted_area,445.645658,ft**2 +aircraft:wing:aeroelastic_tailoring_factor,0.33333,unitless +aircraft:wing:airfoil_technology,1.6,unitless +aircraft:wing:area,1220.0,1.0,0.0,0.0,0.0,0.0,ft**2 +aircraft:wing:aspect_ratio,11.5587605382765,1.0,0.0,0.0,0.0,0.0,unitless +aircraft:wing:aspect_ratio_reference,11.5587605382765,unitless +aircraft:wing:bending_material_mass_scaler,1.0,unitless +aircraft:wing:bwb_aft_body_mass_scaler,1.0,unitless +aircraft:wing:chord_per_semispan,0.273522534166506,0.204274849507037,0.0888152947868224,0.0725353313595661,unitless +aircraft:wing:composite_fraction,0.33333,unitless +aircraft:wing:control_surface_area_ratio,0.333,unitless +aircraft:wing:detailed_wing,True,unitless +aircraft:wing:dihedral,6.0,deg +aircraft:wing:glove_and_bat,0.0,ft**2 +aircraft:wing:input_station_dist,0.0,0.34453777998,0.919,1.0,unitless +aircraft:wing:laminar_flow_lower,0.0,unitless +aircraft:wing:laminar_flow_upper,58.0,unitless +aircraft:wing:load_distribution_control,2.0,unitless +aircraft:wing:load_fraction,1.0,unitless +aircraft:wing:load_path_sweep_dist,0.0,23.6286942529271,23.6286942529271,deg +aircraft:wing:mass_scaler,0.7412,unitless +aircraft:wing:max_camber_at_70_semispan,0.015,unitless +aircraft:wing:misc_mass_scaler,1.7,unitless +aircraft:wing:num_integration_stations,100,unitless +aircraft:wing:shear_control_mass_scaler,0.749,unitless +aircraft:wing:span,118.7505278165,ft +aircraft:wing:span_efficiency_factor,0.95,unitless +aircraft:wing:span_efficiency_reduction,False,unitless +aircraft:wing:strut_bracing_factor,0.0,unitless +aircraft:wing:surface_control_mass_scaler,1.77696,unitless +aircraft:wing:sweep,23.6286942529271,0.0,0.0,0.0,0.0,0.0,deg +aircraft:wing:taper_ratio,0.265189599754917,0.0,0.0,0.0,0.0,0.0,unitless +aircraft:wing:thickness_to_chord,0.12233,0.0,0.0,0.0,0.0,0.0,unitless +aircraft:wing:thickness_to_chord_dist,0.14233,0.12233,0.1108,0.1058,unitless +aircraft:wing:thickness_to_chord_reference,0.116565,unitless +aircraft:wing:ultimate_load_factor,3.75,unitless +aircraft:wing:var_sweep_mass_penalty,0.0,unitless +aircraft:wing:wetted_area,2210.280228,ft**2 +mission:constraints:max_mach,0.785,unitless +mission:design:gross_mass,1.0,lbm +mission:design:lift_coefficient,-1.0,unitless +mission:design:mach,-1.0,unitless +mission:design:range,3500.0,NM +mission:design:thrust_takeoff_per_eng,0.0,lbf +mission:landing:flare_rate,2.2,deg/s +mission:landing:initial_velocity,145.0,ft/s +mission:landing:lift_coefficient_max,2.5,unitless +mission:summary:cruise_mach,0.785,0.0,0.0,0.0,0.0,0.0,unitless +mission:summary:fuel_flow_scaler,1.0,unitless +mission:takeoff:angle_of_attack_runway,0.0,deg +mission:takeoff:braking_friction_coefficient,0.35,unitless +mission:takeoff:final_altitude,35.0,ft +mission:takeoff:fuel_simple,0.0,lbm +mission:takeoff:lift_coefficient_max,2.0,unitless +mission:takeoff:rolling_friction_coefficient,0.0175,unitless +mission:takeoff:spoiler_drag_coefficient,0.085,unitless +mission:takeoff:spoiler_lift_coefficient,-0.81,unitless +mission:takeoff:thrust_incidence,0.0,deg +settings:aerodynamics_method,FLOPS +settings:equations_of_motion,height_energy +settings:mass_method,FLOPS + +# Unconverted Values +AERIN.clapp,2 +AERIN.dratio,1 +AERIN.elodma,0 +AERIN.elodss,0 +AERIN.flldg,8190 +AERIN.flto,8190 +AERIN.thrma,0 +AERIN.thrss,0 +AERIN.xllam,1 +CONFIN.ch,43000.0,0.0,0.0,0.0,0.0,0.0 +CONFIN.fixful,0 +CONFIN.fixspn,0 +CONFIN.gw,180000.0,1.0,0.0,0.0,0.0,0.0 +CONFIN.htvc,1 +CONFIN.pglov,0 +CONFIN.plr,0.0,0.0,0.0,0.0,0.0,0.0 +CONFIN.rotvel,0.0,0.0,0.0,0.0,0.0,0.0 +CONFIN.twr,0.0 +CONFIN.varth,0.0,0.0,0.0,0.0,0.0,0.0 +CONFIN.vtvc,1 +CONFIN.wsr,0 +ENGDIN.ifill,2 +ENGDIN.maxcr,1 +ENGDIN.ngprt,1 +MISSIN.NPCON,0 +MISSIN.altran,200 +MISSIN.appfff,2 +MISSIN.apprtm,4 +MISSIN.cdfeth,0 +MISSIN.clamax,10000.0,43000.0 +MISSIN.clamin,0.0,10000.0 +MISSIN.cldcd,0.0,0.0 +MISSIN.clmmax,0.45222,0.785 +MISSIN.clmmin,0.3,0.45222 +MISSIN.cralt,43000 +MISSIN.crclmx,1 +MISSIN.crdcd,0 +MISSIN.crmach,0.785 +MISSIN.crmmin,0.45222 +MISSIN.dcwt,1 +MISSIN.deamax,43000 +MISSIN.deamin,0 +MISSIN.decl,0.74 +MISSIN.dedcd,0 +MISSIN.demmax,0.785 +MISSIN.demmin,0.3 +MISSIN.divlim,0 +MISSIN.dtc,0 +MISSIN.dwt,1 +MISSIN.erealt,10000 +MISSIN.eremch,0.45222 +MISSIN.faprfl,0 +MISSIN.feathf,0.5 +MISSIN.ffuel,1 +MISSIN.flrcr,1 +MISSIN.fnox,0 +MISSIN.ftxifl,0 +MISSIN.ftxofl,0 +MISSIN.fwf,-1.0,-1.0 +MISSIN.holdtm,20 +MISSIN.hpmin,15000 +MISSIN.iata,0 +MISSIN.icron,0 +MISSIN.idoq,0 +MISSIN.ifaacl,2 +MISSIN.ifaade,-1 +MISSIN.ifeath,0 +MISSIN.iflag,2 +MISSIN.ihopos,2 +MISSIN.indr,0 +MISSIN.ioc,1 +MISSIN.ippcl,1,1 +MISSIN.irs,1 +MISSIN.irw,1 +MISSIN.iskal,1 +MISSIN.ittff,1 +MISSIN.ivs,2 +MISSIN.keasvc,0 +MISSIN.keasvd,0 +MISSIN.maxcl,1,1 +MISSIN.msumpt,1 +MISSIN.mywts,0 +MISSIN.nclimb,2 +MISSIN.nclres,1 +MISSIN.ncrcl,1,1 +MISSIN.ncrhol,1 +MISSIN.ncrres,1 +MISSIN.ncrth,1 +MISSIN.ncruse,1 +MISSIN.nhold,0 +MISSIN.nincl,3,30 +MISSIN.ninde,18 +MISSIN.nodive,1 +MISSIN.npcon,1 +MISSIN.nql,2 +MISSIN.owfact,1 +MISSIN.qlalt,1500.0,10000.0 +MISSIN.qlim,425 +MISSIN.rcin,300 +MISSIN.rdlim,-3000 +MISSIN.resrfu,0 +MISSIN.restrp,0.03 +MISSIN.rtol,0.001 +MISSIN.spdlim,288.69 +MISSIN.srealt,1500 +MISSIN.sremch,0.3 +MISSIN.takoff,0 +MISSIN.takotm,2 +MISSIN.taxitm,5 +MISSIN.taxotm,9 +MISSIN.thold,0 +MISSIN.timmap,2 +MISSIN.tlwind,0 +MISSIN.txfufl,0 +MISSIN.vqlm,260.0,320.0 +OPTION.ianal,3 +OPTION.icost,0 +OPTION.ifite,0 +OPTION.iland,1 +OPTION.ineng,0 +OPTION.iplths,0 +OPTION.ipltth,2 +OPTION.itakof,1 +OPTION.ixfl,1 +OPTION.lpfile,0 +OPTION.mprint,1 +OPTION.nmach,3 +OPTION.nopro,1 +OPTION.npfile,1 +OPTION.pmach,0.3,0.45222,0.785 +OPTION.polalt,39000 +PCONIN.conalt,43000 +PCONIN.conaux,2 +PCONIN.confm,1 +PCONIN.conlim,300 +PCONIN.conmch,0.785 +PCONIN.connz,1 +PCONIN.conpc,1 +PCONIN.conwt,0 +PCONIN.conwta,0 +PCONIN.iconsg,2 +PCONIN.icontp,5 +PCONIN.icstdg,0 +PCONIN.neo,2 +PROIN.alpmin,0 +PROIN.gamlim,0 +PROIN.ipcmax,1 +PROIN.npol,0 +PROIN.ntime,1 +PROIN.txf,-1 +RERUN.desrng,900 +RERUN.iland,0 +RERUN.iplrng,-1 +RERUN.itakof,0 +RERUN.mywts,1 +SEGIN.dstop,23000 +SEGIN.hstop,10000 +SEGIN.key,'LAST' +SEGIN.nflap,1 +SEGIN.vfix,10 +SEGIN.vstop,288.69 +TOLIN.acclim,16 +TOLIN.almxld,12 +TOLIN.almxto,15 +TOLIN.alpld,0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 +TOLIN.alprot,8.8 +TOLIN.alpto,0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 +TOLIN.apa,0 +TOLIN.aprang,-3 +TOLIN.aprhgt,100 +TOLIN.argef,1 +TOLIN.cdeout,0.0046077279938182 +TOLIN.cdld,0.1,0.1,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.2,0.22,0.24,0.26,0.3,0.32,0.34 +TOLIN.cdmld,0.045 +TOLIN.cdmto,0.05 +TOLIN.cdrev,0 +TOLIN.cdto,0.0674,0.065,0.065,0.07,0.072,0.076,0.084,0.09,0.1,0.11,0.12,0.13,0.15,0.16,0.18,0.2 +TOLIN.clld,0.7,0.9,1.05,1.15,1.25,1.4,1.5,1.6,1.7,1.8,1.9,2.0,2.1,2.2,2.3,2.4 +TOLIN.clldm,2.4 +TOLIN.clrev,0 +TOLIN.clto,0.5178,0.6,0.75,0.85,0.95,1.05,1.15,1.25,1.35,1.5,1.6,1.7,1.8,1.85,1.9,1.95 +TOLIN.cltom,2 +TOLIN.deldfl,2 +TOLIN.delhap,2 +TOLIN.deltcl,0.2 +TOLIN.deltrn,0.25 +TOLIN.deltro,0.2 +TOLIN.delvto,4 +TOLIN.dtct,10 +TOLIN.fcdmld,0.3 +TOLIN.fcdmto,0.3 +TOLIN.fldcd,1 +TOLIN.fldcl,1 +TOLIN.ftocd,1 +TOLIN.ftocl,1 +TOLIN.ibal,2 +TOLIN.igobs,0 +TOLIN.incgef,1 +TOLIN.inthld,2 +TOLIN.inthrv,2 +TOLIN.inthto,2 +TOLIN.irev,0 +TOLIN.ispol,1 +TOLIN.itime,1 +TOLIN.itxout,0 +TOLIN.magrup,1 +TOLIN.noflar,0 +TOLIN.obsld,50 +TOLIN.pilott,1 +TOLIN.revcut,-1000 +TOLIN.rvfact,0 +TOLIN.tdelg,3 +TOLIN.tdsink,8 +TOLIN.thfact,1 +TOLIN.thrld +TOLIN.tibra,0 +TOLIN.tibrak,1.46 +TOLIN.ticut,1.46 +TOLIN.tigear,8 +TOLIN.tirva,0 +TOLIN.tirvrs,2 +TOLIN.tispa,0 +TOLIN.tispol,1.46 +TOLIN.vangl,6 +TOLIN.vrotat,1.05 +TOLIN.whgt,8.6 +WTIN.arfin,-10 +WTIN.cgacon,0 +WTIN.cgais,0 +WTIN.cgammo,0 +WTIN.cgap,0 +WTIN.cgarm,0 +WTIN.cgav,0 +WTIN.cgaxg,0 +WTIN.cgaxt,0 +WTIN.cgcan,0 +WTIN.cgcf,0 +WTIN.cgcr,0 +WTIN.cgcw,0 +WTIN.cgea,0 +WTIN.cgef,0 +WTIN.cgf,0 +WTIN.cgfin,0 +WTIN.cgfwf,0 +WTIN.cght,0 +WTIN.cglgm,0 +WTIN.cglgn,0 +WTIN.cgmis,0 +WTIN.cgp,0 +WTIN.cgrefl,0 +WTIN.cgrefx,0 +WTIN.cgvt,0 +WTIN.cgw,0 +WTIN.cgzwf,0 +WTIN.dldwt,0 +WTIN.einl,1 +WTIN.enoz,1 +WTIN.ispowe,0 +WTIN.mldwt,0 +WTIN.mywts,0 +WTIN.netaw,4 +WTIN.nwref,39 +WTIN.paylmx,52000 +WTIN.spwcon,38584 +WTIN.spwgw,0.104087 +WTIN.spwsw,9.5 +WTIN.spwth,2.2344 +WTIN.swpfin,-10 +WTIN.tcfin,0 +WTIN.warm,0 +WTIN.wauxt,1 +WTIN.winl,0 +WTIN.wnoz,0 diff --git a/aviary/utils/test/data/converter_test_configuration_GASP.csv b/aviary/utils/test/data/converter_test_configuration_GASP.csv new file mode 100644 index 0000000000..3cfc8845a4 --- /dev/null +++ b/aviary/utils/test/data/converter_test_configuration_GASP.csv @@ -0,0 +1,225 @@ +# GASP-derived aircraft input deck converted from configuration_test_data_GASP.dat + +# Input Values +aircraft:air_conditioning:mass_coefficient,1.65,unitless +aircraft:anti_icing:mass,126.0,lbm +aircraft:apu:mass,1014.0,lbm +aircraft:avionics:mass,1504.0,lbm +aircraft:controls:cockpit_control_mass_scaler,1.0,unitless +aircraft:controls:control_mass_increment,0.0,lbm +aircraft:controls:stability_augmentation_system_mass,0.0,lbm +aircraft:controls:stability_augmentation_system_mass_scaler,1.0,unitless +aircraft:crew_and_payload:cargo_mass,0.0,lbm +aircraft:crew_and_payload:catering_items_mass_per_passenger,10.0,lbm +aircraft:crew_and_payload:design:cargo_mass,0.0,lbm +aircraft:crew_and_payload:design:max_cargo_mass,15970.0,lbm +aircraft:crew_and_payload:design:num_passengers,154,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,6,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,44.2,inch +aircraft:crew_and_payload:passenger_mass_with_bags,200.0,lbm +aircraft:crew_and_payload:passenger_service_mass_per_passenger,5.0,lbm +aircraft:crew_and_payload:uld_mass_per_passenger,0.0,lbm +aircraft:crew_and_payload:water_mass_per_occupant,3.0,lbm +aircraft:design:cg_delta,0.25,unitless +aircraft:design:cockpit_control_mass_coefficient,30.0,unitless +aircraft:design:drag_coeff_increment,0.0014,unitless +aircraft:design:drag_divergence_shift,0.033,unitless +aircraft:design:emergency_equipment_mass,0.0,lbm +aircraft:design:max_structural_speed,440.0,mi/h +aircraft:design:part25_structural_category,3.0,unitless +aircraft:design:reserve_fuel_additional,0,lbm +aircraft:design:reserve_fuel_fraction,0.15,unitless +aircraft:design:static_margin,0.05,unitless +aircraft:design:structural_mass_increment,0.0,lbm +aircraft:design:type,transport,unitless +aircraft:design:wing_loading,93.1,lbf/ft**2 +aircraft:electrical:system_mass_per_passenger,16.0,lbm +aircraft:engine:additional_mass_fraction,0.165,unitless +aircraft:engine:global_throttle,True,unitless +aircraft:engine:mass_scaler,1.0,unitless +aircraft:engine:mass_specific,0.21366,lbm/lbf +aircraft:engine:num_engines,2,unitless +aircraft:engine:pod_mass_scaler,1.0,unitless +aircraft:engine:pylon_factor,1.25,unitless +aircraft:engine:reference_diameter,5.8,ft +aircraft:engine:reference_sls_thrust,28690.0,lbf +aircraft:engine:scaled_sls_thrust,21162.0,lbf +aircraft:engine:type,7,unitless +aircraft:engine:wing_locations,0.2143,unitless +aircraft:fuel:density,6.687,lbm/galUS +aircraft:fuel:fuel_margin,0.0,unitless +aircraft:fuel:fuel_system_mass_coefficient,0.06,unitless +aircraft:fuel:fuel_system_mass_scaler,1.0,unitless +aircraft:fuel:unusable_fuel_mass_coefficient,12.0,unitless +aircraft:fuel:wing_fuel_fraction,0.5625,unitless +aircraft:furnishings:mass,9114.0,lbm +aircraft:fuselage:aisle_width,24.0,inch +aircraft:fuselage:delta_diameter,4.5,ft +aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 +aircraft:fuselage:form_factor,1.146,unitless +aircraft:fuselage:mass_coefficient,102.82,unitless +aircraft:fuselage:nose_fineness,1.0,unitless +aircraft:fuselage:num_aisles,1,unitless +aircraft:fuselage:pilot_compartment_length,6.85,ft +aircraft:fuselage:pressure_differential,7.5,psi +aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:tail_fineness,1.18,unitless +aircraft:fuselage:wetted_area_scaler,1.0,unitless +aircraft:horizontal_tail:aspect_ratio,4.025,unitless +aircraft:horizontal_tail:form_factor,1.7,unitless +aircraft:horizontal_tail:mass_coefficient,0.2076,unitless +aircraft:horizontal_tail:moment_ratio,0.13067,unitless +aircraft:horizontal_tail:sweep,43.5,deg +aircraft:horizontal_tail:taper_ratio,0.352,unitless +aircraft:horizontal_tail:thickness_to_chord,0.11,unitless +aircraft:horizontal_tail:vertical_tail_fraction,1.0,unitless +aircraft:horizontal_tail:volume_coefficient,1.43,unitless +aircraft:hydraulics:flight_control_mass_coefficient,0.085,unitless +aircraft:hydraulics:gear_mass_coefficient,0.105,unitless +aircraft:instruments:mass_coefficient,0.0736,unitless +aircraft:landing_gear:fixed_gear,False,unitless +aircraft:landing_gear:main_gear_location,0.0,unitless +aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless +aircraft:landing_gear:mass_coefficient,0.0339,unitless +aircraft:landing_gear:tail_hook_mass_scaler,1.0,unitless +aircraft:landing_gear:total_mass_scaler,1.0,unitless +aircraft:nacelle:clearance_ratio,0.2,unitless +aircraft:nacelle:core_diameter_ratio,1.2095,unitless +aircraft:nacelle:fineness,1.715,unitless +aircraft:nacelle:form_factor,1.5,unitless +aircraft:nacelle:mass_specific,2.5,lbm/ft**2 +aircraft:strut:area_ratio,0.32,unitless +aircraft:strut:attachment_location,118.0,ft +aircraft:strut:dimensional_location_specified,True,unitless +aircraft:strut:fuselage_interference_factor,1.125,unitless +aircraft:strut:mass_coefficient,0.238,unitless +aircraft:strut:thickness_to_chord,0.1,unitless +aircraft:vertical_tail:aspect_ratio,0.825,unitless +aircraft:vertical_tail:form_factor,2.0,unitless +aircraft:vertical_tail:mass_coefficient,0.2587,unitless +aircraft:vertical_tail:moment_ratio,3.0496,unitless +aircraft:vertical_tail:sweep,35.0,deg +aircraft:vertical_tail:taper_ratio,0.801,unitless +aircraft:vertical_tail:thickness_to_chord,0.1,unitless +aircraft:vertical_tail:volume_coefficient,0.066,unitless +aircraft:wing:aspect_ratio,19.565,unitless +aircraft:wing:center_distance,0.463,unitless +aircraft:wing:choose_fold_location,False,unitless +aircraft:wing:flap_chord_ratio,0.25,unitless +aircraft:wing:flap_deflection_landing,40.0,deg +aircraft:wing:flap_deflection_takeoff,10.0,deg +aircraft:wing:flap_drag_increment_optimum,0.1,unitless +aircraft:wing:flap_lift_increment_optimum,1.0,unitless +aircraft:wing:flap_span_ratio,0.88,unitless +aircraft:wing:flap_type,double_slotted,unitless +aircraft:wing:fold_dimensional_location_specified,True,unitless +aircraft:wing:fold_mass_coefficient,0.2,unitless +aircraft:wing:folded_span,0.0,ft +aircraft:wing:fuselage_interference_factor,1.21,unitless +aircraft:wing:has_fold,True,unitless +aircraft:wing:has_strut,True,unitless +aircraft:wing:height,15.2,ft +aircraft:wing:high_lift_mass_coefficient,1.9,unitless +aircraft:wing:incidence,1.5,deg +aircraft:wing:mass_coefficient,106.28,unitless +aircraft:wing:max_lift_ref,1.15,unitless +aircraft:wing:max_slat_deflection_landing,10.0,deg +aircraft:wing:max_slat_deflection_takeoff,10.0,deg +aircraft:wing:max_thickness_location,0.35,unitless +aircraft:wing:min_pressure_location,0.3,unitless +aircraft:wing:num_flap_segments,2,unitless +aircraft:wing:optimum_flap_deflection,55,deg +aircraft:wing:optimum_slat_deflection,20.0,deg +aircraft:wing:slat_chord_ratio,0.1,unitless +aircraft:wing:slat_lift_increment_optimum,0.93,unitless +aircraft:wing:surface_control_mass_coefficient,0.5936,unitless +aircraft:wing:sweep,22.47,deg +aircraft:wing:taper_ratio,0.346,unitless +aircraft:wing:thickness_to_chord_root,0.11,unitless +aircraft:wing:thickness_to_chord_tip,0.1,unitless +aircraft:wing:vertical_mount_location,1.0,unitless +aircraft:wing:zero_lift_angle,-1.2,deg +mission:design:cruise_altitude,36000.0,ft +mission:design:gross_mass,160000.0,lbm +mission:design:mach,0.8,unitless +mission:design:range,3500.0,NM +mission:design:rate_of_climb_at_top_of_climb,300.0,ft/min +mission:landing:airport_altitude,0,ft +mission:landing:braking_delay,1.0,s +mission:landing:glide_to_stall_ratio,1.3,unitless +mission:landing:maximum_flare_load_factor,1.15,unitless +mission:landing:maximum_sink_rate,900.0,ft/min +mission:landing:obstacle_height,50.0,ft +mission:landing:touchdown_sink_rate,5.0,ft/s +mission:summary:fuel_flow_scaler,1.0,unitless +mission:takeoff:decision_speed_increment,10.0,kn +mission:takeoff:rotation_speed_increment,5.0,kn +mission:taxi:duration,0.1677,h +settings:aerodynamics_method,GASP +settings:equations_of_motion,2DOF +settings:mass_method,GASP + +# Initialization Guesses +actual_takeoff_mass,0 +climb_range,0 +cruise_mass_final,0 +flight_duration,0 +fuel_burn_per_passenger_mile,0 +reserves,0 +rotation_mass,0 +time_to_climb,0 + +# Unconverted Values +INGASP.ALR,1.11 +INGASP.BENGOB,0.05 +INGASP.CINP,0.11 +INGASP.CLIAB,1984 +INGASP.CMF,15 +INGASP.CMV,0.15 +INGASP.CRWOH,15 +INGASP.CW,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0 +INGASP.DCDSE,-1 +INGASP.DYR,12 +INGASP.EMCRU,0.8 +INGASP.FCSF,2.5 +INGASP.HBTP,0.472 +INGASP.HIR,0.015 +INGASP.HNCRU,36000 +INGASP.HRI,2500 +INGASP.HSCREQ,25000 +INGASP.ICLM,3 +INGASP.ICRUS,0 +INGASP.IWLD,2 +INGASP.JENGSZ,4 +INGASP.KNAC,1 +INGASP.KODEAC,7 +INGASP.KODECL,7 +INGASP.KODETO,5 +INGASP.KODETR,6 +INGASP.MX,0 +INGASP.NFAIL,0 +INGASP.OFALT,0 +INGASP.OFEM,0.78 +INGASP.OHR,350 +INGASP.PRV,0.15 +INGASP.RCCRU,100 +INGASP.RELP,0 +INGASP.RELR,0.4524 +INGASP.RF,0.05,125.0,20000.0,25000.0 +INGASP.RI,0.8 +INGASP.ROSCAB,9999 +INGASP.RWCRTX,0.985 +INGASP.SKPES,0.258 +INGASP.SM1D,0.625 +INGASP.SRPM,18000 +INGASP.TBO,3500 +INGASP.TDELLD,27 +INGASP.TDELTO,27 +INGASP.TR,1 +INGASP.VCLMB,270 +INGASP.WENG,4218 +INGASP.WLPCT,0.9423 +INGASP.WNAC,1240 +INGASP.WPLX,0 +INGASP.WPYLON,0 +INGASP.XTORQ,8000 diff --git a/aviary/utils/test/test_drag_polar_data.csv b/aviary/utils/test/data/converter_test_drag_polar_data.csv similarity index 97% rename from aviary/utils/test/test_drag_polar_data.csv rename to aviary/utils/test/data/converter_test_drag_polar_data.csv index 558d2b8ff8..c762e66537 100644 --- a/aviary/utils/test/test_drag_polar_data.csv +++ b/aviary/utils/test/data/converter_test_drag_polar_data.csv @@ -1,145 +1,145 @@ -altitude ,mach_number ,angle_of_attack,lift_coefficient, total_drag_coefficient -0,0.2,-2,0.094876064,0.009822906 -0,0.2,0,0.312245244,0.012348892 -0,0.2,2,0.526732695,0.018104994 -0,0.2,4,0.738624783,0.026931199 -0,0.2,6,0.948256669,0.038891873 -0,0.2,10,1.37381249,0.072045321 -0,0.4,-2,0.10109343,0.00897394 -0,0.4,0,0.331242642,0.011794696 -0,0.4,2,0.558215806,0.018197124 -0,0.4,4,0.78234899,0.028002964 -0,0.4,6,1.00403071,0.041269684 -0,0.4,10,1.4548071,0.078202412 -0,0.5,-2,0.106943991,0.008799865 -0,0.5,0,0.348482284,0.011907858 -0,0.5,2,0.586591715,0.018925735 -0,0.5,4,0.821646945,0.029659873 -0,0.5,6,1.0540806,0.044158552 -0,0.5,10,1.52725612,0.084663215 -0,0.6,-2,0.116201724,0.008755005 -0,0.6,0,0.374581734,0.012332239 -0,0.6,2,0.628753876,0.020345718 -0,0.6,4,0.880405735,0.032546498 -0,0.6,6,1.12886908,0.048978839 -0,0.6,10,1.63519161,0.095162308 -0,0.7,-2,0.132280494,0.008902517 -0,0.7,0,0.416816813,0.013336078 -0,0.7,2,0.696795397,0.023089868 -0,0.7,4,0.973468481,0.037876912 -0,0.7,6,1.24662498,0.057702287 -0,0.7,10,1.80500261,0.113703109 -0,0.8,-2,0.167428501,0.00957739 -0,0.8,0,0.497855602,0.016016403 -0,0.8,2,0.823365761,0.029601436 -0,0.8,4,1.14426867,0.049986007 -0,0.8,6,1.46094114,0.07706223 -0,0.8,10,2.11188335,0.153895725 -20000,0.2,-2,0.094876064,0.010748936 -20000,0.2,0,0.312245244,0.013278551 -20000,0.2,2,0.526732695,0.019035924 -20000,0.2,4,0.738624783,0.027861195 -20000,0.2,6,0.948256669,0.039818804 -20000,0.2,10,1.37381249,0.072958942 -20000,0.4,-2,0.10109343,0.009771491 -20000,0.4,0,0.331242642,0.01259557 -20000,0.4,2,0.558215806,0.018999276 -20000,0.4,4,0.78234899,0.028804499 -20000,0.4,6,1.00403071,0.042068785 -20000,0.4,10,1.4548071,0.078990525 -20000,0.5,-2,0.106943991,0.009561 -20000,0.5,0,0.348482284,0.012672322 -20000,0.5,2,0.586591715,0.019691561 -20000,0.5,4,0.821646945,0.030425263 -20000,0.5,6,1.0540806,0.044921782 -20000,0.5,10,1.52725612,0.085416334 -20000,0.6,-2,0.116201724,0.009487973 -20000,0.6,0,0.374581734,0.013068627 -20000,0.6,2,0.628753876,0.021083571 -20000,0.6,4,0.880405735,0.03328418 -20000,0.6,6,1.12886908,0.04971467 -20000,0.6,10,1.63519161,0.095888927 -20000,0.7,-2,0.132280494,0.009612703 -20000,0.7,0,0.416816813,0.014049894 -20000,0.7,2,0.696795397,0.023805393 -20000,0.7,4,0.973468481,0.038592556 -20000,0.7,6,1.24662498,0.058416441 -20000,0.7,10,1.80500261,0.11440913 -20000,0.8,-2,0.167428501,0.010268506 -20000,0.8,0,0.497855602,0.016711584 -20000,0.8,2,0.823365761,0.030298771 -20000,0.8,4,1.14426867,0.050683899 -20000,0.8,6,1.46094114,0.077759149 -20000,0.8,10,2.11188335,0.154586048 -30000,0.2,-2,0.094876064,0.01132055 -30000,0.2,0,0.312245244,0.013852395 -30000,0.2,2,0.526732695,0.019610547 -30000,0.2,4,0.738624783,0.028435235 -30000,0.2,6,0.948256669,0.040390954 -30000,0.2,10,1.37381249,0.073522871 -30000,0.4,-2,0.10109343,0.010261747 -30000,0.4,0,0.331242642,0.013087861 -30000,0.4,2,0.558215806,0.019492345 -30000,0.4,4,0.78234899,0.029297188 -30000,0.4,6,1.00403071,0.042559974 -30000,0.4,10,1.4548071,0.079474954 -30000,0.5,-2,0.106943991,0.010028278 -30000,0.5,0,0.348482284,0.013141634 -30000,0.5,2,0.586591715,0.020161704 -30000,0.5,4,0.821646945,0.030895132 -30000,0.5,6,1.0540806,0.045390324 -30000,0.5,10,1.52725612,0.085878672 -30000,0.6,-2,0.116201724,0.009937502 -30000,0.6,0,0.374581734,0.013520245 -30000,0.6,2,0.628753876,0.02153608 -30000,0.6,4,0.880405735,0.033736581 -30000,0.6,6,1.12886908,0.050165931 -30000,0.6,10,1.63519161,0.09633454 -30000,0.7,-2,0.132280494,0.010047891 -30000,0.7,0,0.416816813,0.0144873 -30000,0.7,2,0.696795397,0.024243841 -30000,0.7,4,0.973468481,0.039031073 -30000,0.7,6,1.24662498,0.058854041 -30000,0.7,10,1.80500261,0.114841741 -30000,0.8,-2,0.167428501,0.010691707 -30000,0.8,0,0.497855602,0.017137263 -30000,0.8,2,0.823365761,0.030725762 -30000,0.8,4,1.14426867,0.051111226 -30000,0.8,6,1.46094114,0.078185878 -30000,0.8,10,2.11188335,0.155008735 -40000,0.2,-2,0.094876064,0.012082662 -40000,0.2,0,0.312245244,0.01461747 -40000,0.2,2,0.526732695,0.020376651 -40000,0.2,4,0.738624783,0.029200558 -40000,0.2,6,0.948256669,0.041153752 -40000,0.2,10,1.37381249,0.074274716 -40000,0.4,-2,0.10109343,0.010913067 -40000,0.4,0,0.331242642,0.013741874 -40000,0.4,2,0.558215806,0.020147387 -40000,0.4,4,0.78234899,0.029951717 -40000,0.4,6,1.00403071,0.04321251 -40000,0.4,10,1.4548071,0.080118518 -40000,0.5,-2,0.106943991,0.0106484 -40000,0.5,0,0.348482284,0.013764447 -40000,0.5,2,0.586591715,0.020785612 -40000,0.5,4,0.821646945,0.031518677 -40000,0.5,6,1.0540806,0.046012099 -40000,0.5,10,1.52725612,0.086492212 -40000,0.6,-2,0.116201724,0.010533556 -40000,0.6,0,0.374581734,0.014119058 -40000,0.6,2,0.628753876,0.02213607 -40000,0.6,4,0.880405735,0.034336421 -40000,0.6,6,1.12886908,0.05076426 -40000,0.6,10,1.63519161,0.096925373 -40000,0.7,-2,0.132280494,0.010624519 -40000,0.7,0,0.416816813,0.015066856 -40000,0.7,2,0.696795397,0.024824771 -40000,0.7,4,0.973468481,0.039612086 -40000,0.7,6,1.24662498,0.059433833 -40000,0.7,10,1.80500261,0.115414928 -40000,0.8,-2,0.167428501,0.011252107 -40000,0.8,0,0.497855602,0.017700938 -40000,0.8,2,0.823365761,0.031291167 -40000,0.8,4,1.14426867,0.051677067 -40000,0.8,6,1.46094114,0.078750926 -40000,0.8,10,2.11188335,0.155568425 +altitude ,mach_number ,angle_of_attack,lift_coefficient, total_drag_coefficient +0,0.2,-2,0.094876064,0.009822906 +0,0.2,0,0.312245244,0.012348892 +0,0.2,2,0.526732695,0.018104994 +0,0.2,4,0.738624783,0.026931199 +0,0.2,6,0.948256669,0.038891873 +0,0.2,10,1.37381249,0.072045321 +0,0.4,-2,0.10109343,0.00897394 +0,0.4,0,0.331242642,0.011794696 +0,0.4,2,0.558215806,0.018197124 +0,0.4,4,0.78234899,0.028002964 +0,0.4,6,1.00403071,0.041269684 +0,0.4,10,1.4548071,0.078202412 +0,0.5,-2,0.106943991,0.008799865 +0,0.5,0,0.348482284,0.011907858 +0,0.5,2,0.586591715,0.018925735 +0,0.5,4,0.821646945,0.029659873 +0,0.5,6,1.0540806,0.044158552 +0,0.5,10,1.52725612,0.084663215 +0,0.6,-2,0.116201724,0.008755005 +0,0.6,0,0.374581734,0.012332239 +0,0.6,2,0.628753876,0.020345718 +0,0.6,4,0.880405735,0.032546498 +0,0.6,6,1.12886908,0.048978839 +0,0.6,10,1.63519161,0.095162308 +0,0.7,-2,0.132280494,0.008902517 +0,0.7,0,0.416816813,0.013336078 +0,0.7,2,0.696795397,0.023089868 +0,0.7,4,0.973468481,0.037876912 +0,0.7,6,1.24662498,0.057702287 +0,0.7,10,1.80500261,0.113703109 +0,0.8,-2,0.167428501,0.00957739 +0,0.8,0,0.497855602,0.016016403 +0,0.8,2,0.823365761,0.029601436 +0,0.8,4,1.14426867,0.049986007 +0,0.8,6,1.46094114,0.07706223 +0,0.8,10,2.11188335,0.153895725 +20000,0.2,-2,0.094876064,0.010748936 +20000,0.2,0,0.312245244,0.013278551 +20000,0.2,2,0.526732695,0.019035924 +20000,0.2,4,0.738624783,0.027861195 +20000,0.2,6,0.948256669,0.039818804 +20000,0.2,10,1.37381249,0.072958942 +20000,0.4,-2,0.10109343,0.009771491 +20000,0.4,0,0.331242642,0.01259557 +20000,0.4,2,0.558215806,0.018999276 +20000,0.4,4,0.78234899,0.028804499 +20000,0.4,6,1.00403071,0.042068785 +20000,0.4,10,1.4548071,0.078990525 +20000,0.5,-2,0.106943991,0.009561 +20000,0.5,0,0.348482284,0.012672322 +20000,0.5,2,0.586591715,0.019691561 +20000,0.5,4,0.821646945,0.030425263 +20000,0.5,6,1.0540806,0.044921782 +20000,0.5,10,1.52725612,0.085416334 +20000,0.6,-2,0.116201724,0.009487973 +20000,0.6,0,0.374581734,0.013068627 +20000,0.6,2,0.628753876,0.021083571 +20000,0.6,4,0.880405735,0.03328418 +20000,0.6,6,1.12886908,0.04971467 +20000,0.6,10,1.63519161,0.095888927 +20000,0.7,-2,0.132280494,0.009612703 +20000,0.7,0,0.416816813,0.014049894 +20000,0.7,2,0.696795397,0.023805393 +20000,0.7,4,0.973468481,0.038592556 +20000,0.7,6,1.24662498,0.058416441 +20000,0.7,10,1.80500261,0.11440913 +20000,0.8,-2,0.167428501,0.010268506 +20000,0.8,0,0.497855602,0.016711584 +20000,0.8,2,0.823365761,0.030298771 +20000,0.8,4,1.14426867,0.050683899 +20000,0.8,6,1.46094114,0.077759149 +20000,0.8,10,2.11188335,0.154586048 +30000,0.2,-2,0.094876064,0.01132055 +30000,0.2,0,0.312245244,0.013852395 +30000,0.2,2,0.526732695,0.019610547 +30000,0.2,4,0.738624783,0.028435235 +30000,0.2,6,0.948256669,0.040390954 +30000,0.2,10,1.37381249,0.073522871 +30000,0.4,-2,0.10109343,0.010261747 +30000,0.4,0,0.331242642,0.013087861 +30000,0.4,2,0.558215806,0.019492345 +30000,0.4,4,0.78234899,0.029297188 +30000,0.4,6,1.00403071,0.042559974 +30000,0.4,10,1.4548071,0.079474954 +30000,0.5,-2,0.106943991,0.010028278 +30000,0.5,0,0.348482284,0.013141634 +30000,0.5,2,0.586591715,0.020161704 +30000,0.5,4,0.821646945,0.030895132 +30000,0.5,6,1.0540806,0.045390324 +30000,0.5,10,1.52725612,0.085878672 +30000,0.6,-2,0.116201724,0.009937502 +30000,0.6,0,0.374581734,0.013520245 +30000,0.6,2,0.628753876,0.02153608 +30000,0.6,4,0.880405735,0.033736581 +30000,0.6,6,1.12886908,0.050165931 +30000,0.6,10,1.63519161,0.09633454 +30000,0.7,-2,0.132280494,0.010047891 +30000,0.7,0,0.416816813,0.0144873 +30000,0.7,2,0.696795397,0.024243841 +30000,0.7,4,0.973468481,0.039031073 +30000,0.7,6,1.24662498,0.058854041 +30000,0.7,10,1.80500261,0.114841741 +30000,0.8,-2,0.167428501,0.010691707 +30000,0.8,0,0.497855602,0.017137263 +30000,0.8,2,0.823365761,0.030725762 +30000,0.8,4,1.14426867,0.051111226 +30000,0.8,6,1.46094114,0.078185878 +30000,0.8,10,2.11188335,0.155008735 +40000,0.2,-2,0.094876064,0.012082662 +40000,0.2,0,0.312245244,0.01461747 +40000,0.2,2,0.526732695,0.020376651 +40000,0.2,4,0.738624783,0.029200558 +40000,0.2,6,0.948256669,0.041153752 +40000,0.2,10,1.37381249,0.074274716 +40000,0.4,-2,0.10109343,0.010913067 +40000,0.4,0,0.331242642,0.013741874 +40000,0.4,2,0.558215806,0.020147387 +40000,0.4,4,0.78234899,0.029951717 +40000,0.4,6,1.00403071,0.04321251 +40000,0.4,10,1.4548071,0.080118518 +40000,0.5,-2,0.106943991,0.0106484 +40000,0.5,0,0.348482284,0.013764447 +40000,0.5,2,0.586591715,0.020785612 +40000,0.5,4,0.821646945,0.031518677 +40000,0.5,6,1.0540806,0.046012099 +40000,0.5,10,1.52725612,0.086492212 +40000,0.6,-2,0.116201724,0.010533556 +40000,0.6,0,0.374581734,0.014119058 +40000,0.6,2,0.628753876,0.02213607 +40000,0.6,4,0.880405735,0.034336421 +40000,0.6,6,1.12886908,0.05076426 +40000,0.6,10,1.63519161,0.096925373 +40000,0.7,-2,0.132280494,0.010624519 +40000,0.7,0,0.416816813,0.015066856 +40000,0.7,2,0.696795397,0.024824771 +40000,0.7,4,0.973468481,0.039612086 +40000,0.7,6,1.24662498,0.059433833 +40000,0.7,10,1.80500261,0.115414928 +40000,0.8,-2,0.167428501,0.011252107 +40000,0.8,0,0.497855602,0.017700938 +40000,0.8,2,0.823365761,0.031291167 +40000,0.8,4,1.14426867,0.051677067 +40000,0.8,6,1.46094114,0.078750926 +40000,0.8,10,2.11188335,0.155568425 diff --git a/aviary/utils/test/data/converter_test_large_single_aisle_1_GASP.csv b/aviary/utils/test/data/converter_test_large_single_aisle_1_GASP.csv new file mode 100644 index 0000000000..c4f1e1e89c --- /dev/null +++ b/aviary/utils/test/data/converter_test_large_single_aisle_1_GASP.csv @@ -0,0 +1,225 @@ +# GASP-derived aircraft input deck converted from large_single_aisle_1_GASP.dat + +# Input Values +aircraft:air_conditioning:mass_coefficient,1.65,unitless +aircraft:anti_icing:mass,551.0,lbm +aircraft:apu:mass,928.0,lbm +aircraft:avionics:mass,1959.0,lbm +aircraft:controls:cockpit_control_mass_scaler,1.0,unitless +aircraft:controls:control_mass_increment,0.0,lbm +aircraft:controls:stability_augmentation_system_mass,0.0,lbm +aircraft:controls:stability_augmentation_system_mass_scaler,1.0,unitless +aircraft:crew_and_payload:cargo_mass,0.0,lbm +aircraft:crew_and_payload:catering_items_mass_per_passenger,7.6,lbm +aircraft:crew_and_payload:design:cargo_mass,0.0,lbm +aircraft:crew_and_payload:design:max_cargo_mass,10040.0,lbm +aircraft:crew_and_payload:design:num_passengers,180,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,6,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,29.0,inch +aircraft:crew_and_payload:passenger_mass_with_bags,200.0,lbm +aircraft:crew_and_payload:passenger_service_mass_per_passenger,5.0,lbm +aircraft:crew_and_payload:uld_mass_per_passenger,0.0,lbm +aircraft:crew_and_payload:water_mass_per_occupant,3.0,lbm +aircraft:design:cg_delta,0.25,unitless +aircraft:design:cockpit_control_mass_coefficient,16.5,unitless +aircraft:design:drag_coeff_increment,0.00175,unitless +aircraft:design:drag_divergence_shift,0.033,unitless +aircraft:design:emergency_equipment_mass,50.0,lbm +aircraft:design:max_structural_speed,402.5,mi/h +aircraft:design:part25_structural_category,3.0,unitless +aircraft:design:reserve_fuel_additional,4998,lbm +aircraft:design:reserve_fuel_fraction,0,unitless +aircraft:design:static_margin,0.03,unitless +aircraft:design:structural_mass_increment,0.0,lbm +aircraft:design:type,transport,unitless +aircraft:design:wing_loading,128.0,lbf/ft**2 +aircraft:electrical:system_mass_per_passenger,16.0,lbm +aircraft:engine:additional_mass_fraction,0.14,unitless +aircraft:engine:global_throttle,True,unitless +aircraft:engine:mass_scaler,1.0,unitless +aircraft:engine:mass_specific,0.21366,lbm/lbf +aircraft:engine:num_engines,2,unitless +aircraft:engine:pod_mass_scaler,1.0,unitless +aircraft:engine:pylon_factor,1.25,unitless +aircraft:engine:reference_diameter,5.8,ft +aircraft:engine:reference_sls_thrust,28690.0,lbf +aircraft:engine:scaled_sls_thrust,28690.0,lbf +aircraft:engine:type,7,unitless +aircraft:engine:wing_locations,0.35,unitless +aircraft:fuel:density,6.687,lbm/galUS +aircraft:fuel:fuel_margin,0.0,unitless +aircraft:fuel:fuel_system_mass_coefficient,0.041,unitless +aircraft:fuel:fuel_system_mass_scaler,1.0,unitless +aircraft:fuel:unusable_fuel_mass_coefficient,12.0,unitless +aircraft:fuel:wing_fuel_fraction,0.6,unitless +aircraft:furnishings:mass,11192.0,lbm +aircraft:fuselage:aisle_width,24.0,inch +aircraft:fuselage:delta_diameter,4.5,ft +aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 +aircraft:fuselage:form_factor,1.25,unitless +aircraft:fuselage:mass_coefficient,128.0,unitless +aircraft:fuselage:nose_fineness,1.0,unitless +aircraft:fuselage:num_aisles,1,unitless +aircraft:fuselage:pilot_compartment_length,9.5,ft +aircraft:fuselage:pressure_differential,7.5,psi +aircraft:fuselage:seat_width,20.2,inch +aircraft:fuselage:tail_fineness,3.0,unitless +aircraft:fuselage:wetted_area,4000.0,ft**2 +aircraft:horizontal_tail:aspect_ratio,4.75,unitless +aircraft:horizontal_tail:form_factor,1.25,unitless +aircraft:horizontal_tail:mass_coefficient,0.232,unitless +aircraft:horizontal_tail:moment_ratio,0.2307,unitless +aircraft:horizontal_tail:sweep,25.0,deg +aircraft:horizontal_tail:taper_ratio,0.352,unitless +aircraft:horizontal_tail:thickness_to_chord,0.12,unitless +aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless +aircraft:horizontal_tail:volume_coefficient,1.189,unitless +aircraft:hydraulics:flight_control_mass_coefficient,0.112,unitless +aircraft:hydraulics:gear_mass_coefficient,0.14,unitless +aircraft:instruments:mass_coefficient,0.0736,unitless +aircraft:landing_gear:fixed_gear,False,unitless +aircraft:landing_gear:main_gear_location,0.15,unitless +aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless +aircraft:landing_gear:mass_coefficient,0.04,unitless +aircraft:landing_gear:tail_hook_mass_scaler,1.0,unitless +aircraft:landing_gear:total_mass_scaler,1.0,unitless +aircraft:nacelle:clearance_ratio,0.2,unitless +aircraft:nacelle:core_diameter_ratio,1.25,unitless +aircraft:nacelle:fineness,2.0,unitless +aircraft:nacelle:form_factor,1.5,unitless +aircraft:nacelle:mass_specific,3.0,lbm/ft**2 +aircraft:strut:area_ratio,0.0,unitless +aircraft:strut:attachment_location,0.0,ft +aircraft:strut:attachment_location_dimensionless,0.0,unitless +aircraft:strut:dimensional_location_specified,False,unitless +aircraft:strut:fuselage_interference_factor,0.0,unitless +aircraft:strut:mass_coefficient,0.0,unitless +aircraft:strut:thickness_to_chord,0.0,unitless +aircraft:vertical_tail:aspect_ratio,1.67,unitless +aircraft:vertical_tail:form_factor,1.25,unitless +aircraft:vertical_tail:mass_coefficient,0.289,unitless +aircraft:vertical_tail:moment_ratio,2.362,unitless +aircraft:vertical_tail:sweep,35.0,deg +aircraft:vertical_tail:taper_ratio,0.801,unitless +aircraft:vertical_tail:thickness_to_chord,0.12,unitless +aircraft:vertical_tail:volume_coefficient,0.145,unitless +aircraft:wing:aspect_ratio,10.13,unitless +aircraft:wing:center_distance,0.463,unitless +aircraft:wing:choose_fold_location,True,unitless +aircraft:wing:flap_chord_ratio,0.3,unitless +aircraft:wing:flap_deflection_landing,40.0,deg +aircraft:wing:flap_deflection_takeoff,10.0,deg +aircraft:wing:flap_drag_increment_optimum,0.1,unitless +aircraft:wing:flap_lift_increment_optimum,1.5,unitless +aircraft:wing:flap_span_ratio,0.65,unitless +aircraft:wing:flap_type,double_slotted,unitless +aircraft:wing:fold_dimensional_location_specified,False,unitless +aircraft:wing:fold_mass_coefficient,0.0,unitless +aircraft:wing:folded_span,0.0,ft +aircraft:wing:form_factor,1.25,unitless +aircraft:wing:fuselage_interference_factor,1.1,unitless +aircraft:wing:has_fold,False,unitless +aircraft:wing:has_strut,False,unitless +aircraft:wing:height,8.0,ft +aircraft:wing:high_lift_mass_coefficient,1.9,unitless +aircraft:wing:incidence,1.5,deg +aircraft:wing:mass_coefficient,102.5,unitless +aircraft:wing:max_lift_ref,1.15,unitless +aircraft:wing:max_slat_deflection_landing,10.0,deg +aircraft:wing:max_slat_deflection_takeoff,10.0,deg +aircraft:wing:max_thickness_location,0.4,unitless +aircraft:wing:min_pressure_location,0.3,unitless +aircraft:wing:num_flap_segments,2,unitless +aircraft:wing:optimum_flap_deflection,55,deg +aircraft:wing:optimum_slat_deflection,20.0,deg +aircraft:wing:slat_chord_ratio,0.15,unitless +aircraft:wing:slat_lift_increment_optimum,0.93,unitless +aircraft:wing:surface_control_mass_coefficient,0.95,unitless +aircraft:wing:sweep,25.0,deg +aircraft:wing:taper_ratio,0.33,unitless +aircraft:wing:thickness_to_chord_root,0.15,unitless +aircraft:wing:thickness_to_chord_tip,0.12,unitless +aircraft:wing:vertical_mount_location,0.0,unitless +aircraft:wing:zero_lift_angle,-1.2,deg +mission:design:cruise_altitude,37500.0,ft +mission:design:gross_mass,175400.0,lbm +mission:design:mach,0.8,unitless +mission:design:range,3675.0,NM +mission:design:rate_of_climb_at_top_of_climb,300.0,ft/min +mission:landing:airport_altitude,0,ft +mission:landing:braking_delay,1.0,s +mission:landing:glide_to_stall_ratio,1.3,unitless +mission:landing:maximum_flare_load_factor,1.15,unitless +mission:landing:maximum_sink_rate,900.0,ft/min +mission:landing:obstacle_height,50.0,ft +mission:landing:touchdown_sink_rate,5.0,ft/s +mission:summary:fuel_flow_scaler,1.0,unitless +mission:takeoff:decision_speed_increment,10.0,kn +mission:takeoff:rotation_speed_increment,5.0,kn +mission:taxi:duration,0.1677,h +settings:aerodynamics_method,GASP +settings:equations_of_motion,2DOF +settings:mass_method,GASP + +# Initialization Guesses +actual_takeoff_mass,0 +climb_range,0 +cruise_mass_final,0 +flight_duration,0 +fuel_burn_per_passenger_mile,0 +reserves,0 +rotation_mass,0 +time_to_climb,0 + +# Unconverted Values +INGASP.ALR,1.11 +INGASP.BENGOB,0.05 +INGASP.CINP,0.11 +INGASP.CLIAB,1984 +INGASP.CMF,15 +INGASP.CMV,0.15 +INGASP.CRWOH,15 +INGASP.CW,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0 +INGASP.DCDSE,-1 +INGASP.DYR,12 +INGASP.EMCRU,0.8 +INGASP.FCSF,2.5 +INGASP.FPYLND,1 +INGASP.HBTP,0.333 +INGASP.HIR,0.015 +INGASP.HNCRU,37500 +INGASP.HRI,2500 +INGASP.HSCREQ,20000 +INGASP.ICLM,3 +INGASP.ICRUS,0 +INGASP.IWLD,2 +INGASP.JENGSZ,4 +INGASP.KNAC,1 +INGASP.KODEAC,7 +INGASP.KODECL,7 +INGASP.KODETO,5 +INGASP.KODETR,6 +INGASP.MX,0 +INGASP.NFAIL,0 +INGASP.OFALT,0 +INGASP.OFEM,0.78 +INGASP.OHR,350 +INGASP.PRV,0.15 +INGASP.RELP,0 +INGASP.RELR,0.4524 +INGASP.RF,0.05,125.0,20000.0,25000.0 +INGASP.RI,0.8 +INGASP.ROSCAB,9999 +INGASP.RWCRTX,0.985 +INGASP.SKPES,0.258 +INGASP.SM1D,0.625 +INGASP.SRPM,18000 +INGASP.TBO,3500 +INGASP.TR,1 +INGASP.VCLMB,270 +INGASP.WENG,6130 +INGASP.WLPCT,0.9423 +INGASP.WNAC,0 +INGASP.WPLX,0 +INGASP.WPYLON,0 +INGASP.XTORQ,8000 diff --git a/aviary/utils/test/data/converter_test_small_single_aisle_GASP.csv b/aviary/utils/test/data/converter_test_small_single_aisle_GASP.csv new file mode 100644 index 0000000000..8ba6e364cc --- /dev/null +++ b/aviary/utils/test/data/converter_test_small_single_aisle_GASP.csv @@ -0,0 +1,229 @@ +# GASP-derived aircraft input deck converted from small_single_aisle_GASP.dat + +# Input Values +aircraft:air_conditioning:mass_coefficient,1.65,unitless +aircraft:anti_icing:mass,397.0,lbm +aircraft:apu:mass,778.0,lbm +aircraft:avionics:mass,1349.0,lbm +aircraft:controls:cockpit_control_mass_scaler,1.0,unitless +aircraft:controls:control_mass_increment,0.0,lbm +aircraft:controls:stability_augmentation_system_mass,0.0,lbm +aircraft:controls:stability_augmentation_system_mass_scaler,1.0,unitless +aircraft:crew_and_payload:cargo_mass,0.0,lbm +aircraft:crew_and_payload:catering_items_mass_per_passenger,6.0,lbm +aircraft:crew_and_payload:design:cargo_mass,0.0,lbm +aircraft:crew_and_payload:design:max_cargo_mass,8598.0,lbm +aircraft:crew_and_payload:design:num_passengers,96,unitless +aircraft:crew_and_payload:design:num_seats_abreast_tourist,4,unitless +aircraft:crew_and_payload:design:seat_pitch_tourist,31,inch +aircraft:crew_and_payload:passenger_mass_with_bags,210.0,lbm +aircraft:crew_and_payload:passenger_service_mass_per_passenger,7.6,lbm +aircraft:crew_and_payload:uld_mass_per_passenger,0.11,lbm +aircraft:crew_and_payload:water_mass_per_occupant,3.0,lbm +aircraft:design:cg_delta,0.25,unitless +aircraft:design:cockpit_control_mass_coefficient,16.5,unitless +aircraft:design:drag_coeff_increment,0.0018,unitless +aircraft:design:drag_divergence_shift,0.025,unitless +aircraft:design:emergency_equipment_mass,50.0,lbm +aircraft:design:max_structural_speed,402.5,mi/h +aircraft:design:part25_structural_category,3.0,unitless +aircraft:design:reserve_fuel_additional,0,lbm +aircraft:design:reserve_fuel_fraction,0.125,unitless +aircraft:design:static_margin,0.05,unitless +aircraft:design:structural_mass_increment,0.0,lbm +aircraft:design:type,transport,unitless +aircraft:design:wing_loading,112.6,lbf/ft**2 +aircraft:electrical:system_mass_per_passenger,16.0,lbm +aircraft:engine:additional_mass_fraction,0.14,unitless +aircraft:engine:global_throttle,True,unitless +aircraft:engine:mass_scaler,1.0,unitless +aircraft:engine:mass_specific,0.2153,lbm/lbf +aircraft:engine:num_engines,2,unitless +aircraft:engine:pod_mass_scaler,1.0,unitless +aircraft:engine:pylon_factor,0.6,unitless +aircraft:engine:reference_diameter,5.8,ft +aircraft:engine:reference_sls_thrust,28690.0,lbf +aircraft:engine:scaled_sls_thrust,23800.0,lbf +aircraft:engine:type,7,unitless +aircraft:engine:wing_locations,0.272,unitless +aircraft:fuel:density,6.687,lbm/galUS +aircraft:fuel:fuel_margin,0.0,unitless +aircraft:fuel:fuel_system_mass_coefficient,0.0333,unitless +aircraft:fuel:fuel_system_mass_scaler,1.0,unitless +aircraft:fuel:unusable_fuel_mass_coefficient,12.0,unitless +aircraft:fuel:wing_fuel_fraction,0.6,unitless +aircraft:furnishings:mass,9071,lbm +aircraft:fuselage:aisle_width,19.0,inch +aircraft:fuselage:delta_diameter,4.25,ft +aircraft:fuselage:flat_plate_area_increment,0.25,ft**2 +aircraft:fuselage:form_factor,1.55,unitless +aircraft:fuselage:mass_coefficient,121.2,unitless +aircraft:fuselage:nose_fineness,0.845,unitless +aircraft:fuselage:num_aisles,1,unitless +aircraft:fuselage:pilot_compartment_length,11.7,ft +aircraft:fuselage:pressure_differential,7.5,psi +aircraft:fuselage:seat_width,24.0,inch +aircraft:fuselage:tail_fineness,3.368,unitless +aircraft:fuselage:wetted_area_scaler,1.0,unitless +aircraft:horizontal_tail:aspect_ratio,4.26,unitless +aircraft:horizontal_tail:form_factor,1.55,unitless +aircraft:horizontal_tail:mass_coefficient,0.325,unitless +aircraft:horizontal_tail:moment_ratio,0.1844,unitless +aircraft:horizontal_tail:sweep,34.7,deg +aircraft:horizontal_tail:taper_ratio,0.381,unitless +aircraft:horizontal_tail:thickness_to_chord,0.107,unitless +aircraft:horizontal_tail:vertical_tail_fraction,0.0,unitless +aircraft:horizontal_tail:volume_coefficient,1.2266,unitless +aircraft:hydraulics:flight_control_mass_coefficient,0.112,unitless +aircraft:hydraulics:gear_mass_coefficient,0.14,unitless +aircraft:instruments:mass_coefficient,0.06,unitless +aircraft:landing_gear:fixed_gear,False,unitless +aircraft:landing_gear:main_gear_location,0.199,unitless +aircraft:landing_gear:main_gear_mass_coefficient,0.85,unitless +aircraft:landing_gear:mass_coefficient,0.036,unitless +aircraft:landing_gear:tail_hook_mass_scaler,1.0,unitless +aircraft:landing_gear:total_mass_scaler,1.0,unitless +aircraft:nacelle:clearance_ratio,0.2,unitless +aircraft:nacelle:core_diameter_ratio,1.265,unitless +aircraft:nacelle:fineness,1.505,unitless +aircraft:nacelle:form_factor,1.5,unitless +aircraft:nacelle:mass_specific,3.0,lbm/ft**2 +aircraft:strut:area_ratio,0.0,unitless +aircraft:strut:attachment_location,0.0,ft +aircraft:strut:attachment_location_dimensionless,0.0,unitless +aircraft:strut:dimensional_location_specified,False,unitless +aircraft:strut:fuselage_interference_factor,1.0,unitless +aircraft:strut:mass_coefficient,0.0,unitless +aircraft:vertical_tail:aspect_ratio,1.84,unitless +aircraft:vertical_tail:form_factor,1.55,unitless +aircraft:vertical_tail:mass_coefficient,0.425,unitless +aircraft:vertical_tail:moment_ratio,1.9409,unitless +aircraft:vertical_tail:sweep,29.95,deg +aircraft:vertical_tail:taper_ratio,0.267,unitless +aircraft:vertical_tail:thickness_to_chord,0.13,unitless +aircraft:vertical_tail:volume_coefficient,0.08105,unitless +aircraft:wing:aspect_ratio,11.03,unitless +aircraft:wing:center_distance,0.463,unitless +aircraft:wing:choose_fold_location,True,unitless +aircraft:wing:flap_chord_ratio,0.15,unitless +aircraft:wing:flap_deflection_landing,40.0,deg +aircraft:wing:flap_deflection_takeoff,5.0,deg +aircraft:wing:flap_drag_increment_optimum,0.1,unitless +aircraft:wing:flap_lift_increment_optimum,1.5,unitless +aircraft:wing:flap_span_ratio,0.863,unitless +aircraft:wing:flap_type,single_slotted,unitless +aircraft:wing:fold_dimensional_location_specified,False,unitless +aircraft:wing:fold_mass_coefficient,0.0,unitless +aircraft:wing:folded_span,0.0,ft +aircraft:wing:form_factor,1.55,unitless +aircraft:wing:fuselage_interference_factor,1.25,unitless +aircraft:wing:has_fold,False,unitless +aircraft:wing:has_strut,False,unitless +aircraft:wing:height,6.5,ft +aircraft:wing:high_lift_mass_coefficient,1.9,unitless +aircraft:wing:incidence,1.5,deg +aircraft:wing:mass_coefficient,108.75,unitless +aircraft:wing:max_lift_ref,1.4,unitless +aircraft:wing:max_slat_deflection_landing,10.0,deg +aircraft:wing:max_slat_deflection_takeoff,10.0,deg +aircraft:wing:max_thickness_location,0.35,unitless +aircraft:wing:min_pressure_location,0.3,unitless +aircraft:wing:num_flap_segments,2,unitless +aircraft:wing:optimum_flap_deflection,20.0,deg +aircraft:wing:optimum_slat_deflection,20.0,deg +aircraft:wing:slat_chord_ratio,0.1,unitless +aircraft:wing:slat_lift_increment_optimum,0.93,unitless +aircraft:wing:surface_control_mass_coefficient,0.845,unitless +aircraft:wing:sweep,26.34,deg +aircraft:wing:taper_ratio,0.301,unitless +aircraft:wing:thickness_to_chord_root,0.1125,unitless +aircraft:wing:thickness_to_chord_tip,0.12,unitless +aircraft:wing:vertical_mount_location,0.0,unitless +aircraft:wing:zero_lift_angle,-1.2,deg +mission:design:cruise_altitude,37000.0,ft +mission:design:gross_mass,124780.0,lbm +mission:design:mach,0.78,unitless +mission:design:range,3480.0,NM +mission:design:rate_of_climb_at_top_of_climb,300.0,ft/min +mission:landing:airport_altitude,0,ft +mission:landing:braking_delay,1.0,s +mission:landing:glide_to_stall_ratio,1.3,unitless +mission:landing:maximum_flare_load_factor,1.15,unitless +mission:landing:maximum_sink_rate,900.0,ft/min +mission:landing:obstacle_height,50.0,ft +mission:landing:touchdown_sink_rate,5.0,ft/s +mission:summary:fuel_flow_scaler,1.0,unitless +mission:takeoff:decision_speed_increment,10.0,kn +mission:takeoff:rotation_speed_increment,5.0,kn +mission:taxi:duration,0.3333,h +settings:aerodynamics_method,GASP +settings:equations_of_motion,2DOF +settings:mass_method,GASP + +# Initialization Guesses +actual_takeoff_mass,0 +climb_range,0 +cruise_mass_final,0 +flight_duration,0 +fuel_burn_per_passenger_mile,0 +reserves,0 +rotation_mass,0 +time_to_climb,0 + +# Unconverted Values +INGASP.ALR,1.11 +INGASP.BENGOB,0 +INGASP.CINP,0.11 +INGASP.CLIAB,2021 +INGASP.CMF,15 +INGASP.CMV,0.15 +INGASP.CRWOH,15 +INGASP.CW,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0 +INGASP.DCDSE,0 +INGASP.DYR,12 +INGASP.EMCRU,0.78 +INGASP.FCSF,4.66 +INGASP.HBTP,0.45 +INGASP.HIR,0.015 +INGASP.HNCRU,37000 +INGASP.HQBWGLT,0 +INGASP.HRI,5000000 +INGASP.HSCREQ,0 +INGASP.HTMAX,1500 +INGASP.ICLM,3 +INGASP.ICRUS,10 +INGASP.IFERRY,0 +INGASP.ISWING,0 +INGASP.IWLD,2 +INGASP.JENGSZ,4 +INGASP.KNAC,1 +INGASP.KODEAC,7 +INGASP.KODECL,7 +INGASP.KODETO,5 +INGASP.KODETR,6 +INGASP.MX,0 +INGASP.NFAIL,0 +INGASP.OFALT,0 +INGASP.OFEM,0.78 +INGASP.OHR,350 +INGASP.PRV,0.15 +INGASP.RELP,0 +INGASP.RF,2.0,100.0,26400.0,1500.0 +INGASP.RI,0.8 +INGASP.ROSCAB,9999 +INGASP.RWCRTX,0.985 +INGASP.SKPES,0.258 +INGASP.SLMWGLT,0 +INGASP.SM1D,0.575 +INGASP.SRPM,18000 +INGASP.TBO,0 +INGASP.TDELLD,0 +INGASP.TDELTO,27 +INGASP.TDELTX,0 +INGASP.TR,1 +INGASP.UWTWGLT,7.5 +INGASP.VCLMB,265 +INGASP.WLPCT,0.9423 +INGASP.WPLX,0 +INGASP.XLFMAX,1.1 +INGASP.XTORQ,8000 diff --git a/aviary/utils/test/csv_test.csv b/aviary/utils/test/data/csv_test.csv similarity index 53% rename from aviary/utils/test/csv_test.csv rename to aviary/utils/test/data/csv_test.csv index 1112823233..b302f1c37f 100644 --- a/aviary/utils/test/csv_test.csv +++ b/aviary/utils/test/data/csv_test.csv @@ -1,7 +1,7 @@ # comment 1 #comment 2# more comment 2 -aircraft:wing:span (ft), aircraft:crew_and_payload:num_passengers, fake_var (lbm) +aircraft:wing:span (ft, input), aircraft:crew_and_payload:num_passengers (input), fake_var (lbm, output) 15.24, 125, 0.932 118, 28, 1023.54 #inline comment diff --git a/aviary/utils/test/flops_test_polar.txt b/aviary/utils/test/data/flops_test_polar.txt similarity index 100% rename from aviary/utils/test/flops_test_polar.txt rename to aviary/utils/test/data/flops_test_polar.txt diff --git a/aviary/models/engines/turbofan_22k.txt b/aviary/utils/test/data/turbofan_22k.txt similarity index 100% rename from aviary/models/engines/turbofan_22k.txt rename to aviary/utils/test/data/turbofan_22k.txt diff --git a/aviary/utils/test/data/GASP_turbofan_23k_1.eng b/aviary/utils/test/data/turbofan_23k_1.eng similarity index 99% rename from aviary/utils/test/data/GASP_turbofan_23k_1.eng rename to aviary/utils/test/data/turbofan_23k_1.eng index 7f161d0cb0..11092fba41 100644 --- a/aviary/utils/test/data/GASP_turbofan_23k_1.eng +++ b/aviary/utils/test/data/turbofan_23k_1.eng @@ -1,5 +1,5 @@ 1 0 994.36 3342. 3196. 3108. 1.25 -Georgia Tech Tube&Wing 2017 Turbofan Engine Model: Corrected Thrust +Turbofan Engine Model: Corrected Thrust 15 8 11 0.0000 diff --git a/aviary/models/engines/turboshaft_4465hp.eng b/aviary/utils/test/data/turboshaft_4465hp.eng similarity index 100% rename from aviary/models/engines/turboshaft_4465hp.eng rename to aviary/utils/test/data/turboshaft_4465hp.eng diff --git a/aviary/utils/test/test_aero_table_conversion.py b/aviary/utils/test/test_aero_table_conversion.py index 2b64bb3c70..becdcda751 100644 --- a/aviary/utils/test/test_aero_table_conversion.py +++ b/aviary/utils/test/test_aero_table_conversion.py @@ -1,157 +1,50 @@ -import unittest import tempfile - -import numpy as np +import unittest from pathlib import Path +import numpy as np from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs -from aviary.utils.aero_table_conversion import _load_flops_aero_table, _load_gasp_aero_table, _exec_ATC +from aviary.utils.aero_table_conversion import convert_aero_table from aviary.utils.functions import get_path @use_tempdirs class TestAeroTableConversion(unittest.TestCase): - """ - Test conversion of aero table from GASP and FLOPS data format to Aviary format. - """ + """Test conversion of aero table from GASP and FLOPS data format to Aviary format.""" - def test_GASP_table_1(self): - expected_delflp = np.array([10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,]) - expected_mach = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,]) - expected_alpha = np.array([-2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.69, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.62, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.04, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.52, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, - 17.82, 17.82, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.88, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.59, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.22, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.69, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 17.96, 17.99,]) - expected_cl = np.array([0.44098, 0.44098, 0.44098, 0.44098, 0.44098, 0.44098, 0.44098, 0.44098, 0.44098, 0.44098, 0.44098, 0.41324, 0.44086, 0.44086, 0.44086, 0.44086, 0.44086, 0.44086, 0.44086, 0.44086, 0.44086, 0.44086, 0.44086, 0.40665, 0.44049, 0.44049, 0.44049, 0.44049, 0.44049, 0.44049, 0.44049, 0.44049, 0.44049, 0.44049, 0.44049, 0.38648, 0.43986, 0.43986, 0.43986, 0.43986, 0.43986, 0.43986, 0.43986, 0.43986, 0.43986, 0.43986, 0.43986, 0.3514, 0.4389, 0.4389, 0.4389, 0.4389, 0.4389, 0.4389, 0.4389, 0.4389, 0.4389, 0.4389, 0.4389, 0.31496, 0.43757, 0.43757, 0.43757, 0.43757, 0.43757, 0.43757, 0.43757, 0.43757, 0.43757, 0.43757, 0.41979, - 0.314, 1.08538, 1.08538, 1.08538, 1.08538, 1.08538, 1.08538, 1.08538, 1.08538, 1.08538, 1.08538, 1.08538, 1.07429, 1.08508, 1.08508, 1.08508, 1.08508, 1.08508, 1.08508, 1.08508, 1.08508, 1.08508, 1.08508, 1.08508, 1.06752, 1.08417, 1.08417, 1.08417, 1.08417, 1.08417, 1.08417, 1.08417, 1.08417, 1.08417, 1.08417, 1.08417, 1.0468, 1.0826, 1.0826, 1.0826, 1.0826, 1.0826, 1.0826, 1.0826, 1.0826, 1.0826, 1.0826, 1.0826, 1.01077, 1.08026, 1.08026, 1.08026, 1.08026, 1.08026, 1.08026, 1.08026, 1.08026, 1.08026, 1.08026, 1.08026, 0.97289, 1.07697, 1.07697, 1.07697, 1.07697, 1.07697, 1.07697, 1.07697, 1.07697, 1.07697, 1.07697, 1.07572, 0.96993,]) - expected_cd = np.array([0.01046, 0.01436, 0.01829, 0.02224, 0.02622, 0.03021, 0.03423, 0.03826, 0.04232, 0.0464, 0.05051, 0.05048, 0.01083, 0.01551, 0.02022, 0.02495, 0.02971, 0.03449, 0.03931, 0.04414, 0.04901, 0.0539, 0.05881, 0.05764, 0.01076, 0.01541, 0.02008, 0.02477, 0.02949, 0.03424, 0.03901, 0.04381, 0.04864, 0.05349, 0.05836, 0.05373, 0.0107, 0.01537, 0.02006, 0.02478, 0.02952, 0.03429, 0.03909, 0.04392, 0.04877, 0.05365, 0.05856, 0.04793, 0.01062, 0.01535, 0.02011, 0.0249, 0.02972, 0.03456, 0.03943, 0.04433, 0.04926, 0.05421, 0.05919, 0.04199, 0.01052, 0.01536, 0.02023, 0.02514, 0.03007, 0.03503, 0.04002, 0.04504, 0.05009, 0.05517, 0.05725, - 0.04154, 0.04726, 0.05416, 0.06142, 0.06905, 0.07704, 0.0854, 0.09412, 0.1032, 0.11265, 0.12246, 0.13264, 0.14111, 0.04854, 0.0568, 0.0655, 0.07464, 0.08422, 0.09423, 0.10469, 0.11558, 0.1269, 0.13867, 0.15088, 0.15959, 0.04834, 0.05653, 0.06516, 0.07422, 0.08373, 0.09368, 0.10406, 0.11488, 0.12614, 0.13785, 0.14999, 0.15432, 0.04815, 0.05637, 0.06504, 0.07416, 0.08373, 0.09375, 0.10422, 0.11513, 0.1265, 0.13831, 0.15058, 0.14752, 0.04794, 0.05626, 0.06505, 0.07431, 0.08404, 0.09424, 0.1049, 0.11603, 0.12763, 0.1397, 0.15224, 0.14059, 0.04767, 0.05616, 0.06516, 0.07465, 0.08464, 0.09512, 0.10611, 0.11758, 0.12956, 0.14204, 0.15474, 0.13903,]) - expected_comments = ['Incremental Lift and Drag Coeff. for Flaps', - 'Reference Area = 1370. sqft'] - - input = get_path( - 'subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt') - data, comments = _load_gasp_aero_table(input) - if comments != expected_comments: - raise ValueError(f'Comments written to csv do not match ' - 'expected values') - - assert_near_equal(data.get_val('Flap Deflection', 'deg'), expected_delflp) - assert_near_equal(data.get_val('Mach'), expected_mach) - assert_near_equal(data.get_val('Angle of Attack', 'deg'), expected_alpha) - assert_near_equal(data.get_val('Delta CL'), expected_cl) - assert_near_equal(data.get_val('Delta CD'), expected_cd) + def prepare_and_run(self, filename, output_file=None, data_format='GASP'): + # Specify the input file + input_file = get_path('utils/test/data/' + filename) - def test_GASP_table_2(self): - expected_alt = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 9000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 12000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 15000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 18000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, 21000, - 21000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 24000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 27000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 30000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 33000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 36000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 38000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000, 42000,]) - expected_mach = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, - 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9,]) - expected_alpha = np.array([-2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.8, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 18.1, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.9, 16.9, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 16.2, 16.2, -2, 0, 2, 4, 6, 8, 10, 12, 14, 15.4, 15.4, 15.4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 14.5, 14.5, 14.5, -2, 0, 2, 4, 6, 8, 10, 12, 13.4, 13.4, 13.4, 13.4,]) - expected_cl = np.array([-0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, - 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152, -0.0715, 0.1072, 0.286, 0.4647, 0.6434, 0.8222, 1.0009, 1.1797, 1.3584, 1.5371, 1.7159, 1.8946, -0.0724, 0.1086, 0.2896, 0.4706, 0.6517, 0.8327, 1.0137, 1.1947, 1.3757, 1.5568, 1.7378, 1.9188, -0.0754, 0.1131, 0.3016, 0.4901, 0.6786, 0.867, 1.0555, 1.244, 1.4325, 1.621, 1.8095, 1.982, -0.0779, 0.1169, 0.3117, 0.5065, 0.7013, 0.8961, 1.0909, 1.2857, 1.4806, 1.6754, 1.8702, 1.976, -0.0814, 0.1221, 0.3257, 0.5293, 0.7329, 0.9365, 1.1401, 1.3436, 1.5472, 1.7508, 1.9544, 1.9677, -0.0863, 0.1295, 0.3454, 0.5613, 0.7771, 0.993, 1.2089, 1.4247, 1.6406, 1.8565, 1.9562, 1.9562, -0.0896, 0.1343, 0.3582, 0.5822, 0.8061, 1.03, 1.2539, 1.4778, 1.7017, 1.9256, 1.9488, 1.9488, -0.0935, 0.1402, 0.374, 0.6077, 0.8414, 1.0751, 1.3089, 1.5426, 1.7763, 1.9399, 1.9399, 1.9399, -0.0984, 0.1476, 0.3936, 0.6396, 0.8855, 1.1315, 1.3775, 1.6235, 1.8695, 1.929, 1.929, 1.929, -0.1047, 0.1571, 0.4188, 0.6806, 0.9424, 1.2041, 1.4659, 1.7277, 1.9152, 1.9152, 1.9152, 1.9152,]) - expected_cd = np.array([0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01841, 0.01867, 0.02152, 0.02695, 0.03498, 0.04559, 0.05878, 0.07457, 0.09294, 0.1139, 0.13745, 0.16359, 0.01689, 0.01716, 0.0202, 0.026, 0.03455, 0.04587, 0.05995, 0.07678, 0.09638, 0.11874, 0.14385, 0.16926, 0.01639, 0.01668, 0.01991, 0.02607, 0.03515, 0.04717, 0.06212, 0.08, 0.10081, 0.12456, 0.15123, 0.16695, 0.01598, 0.01629, 0.0198, 0.02648, 0.03636, 0.04941, 0.06566, 0.08508, 0.1077, 0.13349, 0.16254, 0.16456, 0.01561, 0.01597, 0.01989, 0.02737, 0.03842, 0.05303, 0.07136, 0.09434, 0.12318, 0.1591, 0.17842, 0.17842, 0.01545, 0.01583, 0.02004, 0.02807, 0.04007, 0.05703, 0.08031, 0.11124, 0.15118, 0.20146, 0.20733, 0.20733, 0.0153, 0.01571, 0.02036, 0.0302, 0.04673, 0.0715, 0.10604, 0.15187, 0.21052, 0.26004, 0.26004, 0.26004, 0.01517, 0.01631, 0.02441, 0.04125, 0.06862, 0.1083, 0.16207, 0.23172, 0.31903, 0.34301, 0.34301, 0.34301, 0.01712, 0.02339, 0.04088, 0.07174, 0.11809, 0.18211, 0.26594, 0.37173, 0.46224, 0.46224, 0.46224, 0.46224, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01859, 0.01885, 0.0217, 0.02715, 0.03519, 0.04582, 0.05904, 0.07485, 0.09326, 0.11426, 0.13785, 0.16404, 0.01704, 0.01732, 0.02036, 0.02617, 0.03474, 0.04607, 0.06017, 0.07703, 0.09666, 0.11905, 0.14421, 0.16966, 0.01654, 0.01683, 0.02006, 0.02623, 0.03533, 0.04737, 0.06234, 0.08025, 0.10109, 0.12487, 0.15159, 0.16733, 0.01612, 0.01644, 0.01994, 0.02664, 0.03653, 0.04961, 0.06587, 0.08533, 0.10797, 0.13381, 0.16289, 0.16492, 0.01575, 0.01611, 0.02003, 0.02753, 0.03859, 0.05322, 0.07157, 0.09458, 0.12346, 0.15942, 0.17876, 0.17876, 0.01558, 0.01597, 0.02018, 0.02822, 0.04024, 0.05722, 0.08052, 0.11149, 0.15146, 0.20179, 0.20767, 0.20767, 0.01543, 0.01584, 0.0205, 0.03034, 0.0469, 0.07169, 0.10626, 0.15212, 0.21082, 0.26036, 0.26036, 0.26036, 0.0153, 0.01644, 0.02454, 0.0414, 0.06878, 0.10849, 0.16229, 0.23198, 0.31934, 0.34333, 0.34333, 0.34333, 0.01724, 0.02352, 0.04102, 0.07188, 0.11826, 0.18231, 0.26617, 0.372, 0.46255, 0.46255, 0.46255, 0.46255, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01878, 0.01904, 0.0219, 0.02735, 0.0354, 0.04605, 0.0593, 0.07515, 0.09359, 0.11463, 0.13827, 0.1645, 0.0172, 0.01748, 0.02053, 0.02634, 0.03493, 0.04628, 0.0604, 0.07729, 0.09695, 0.11938, 0.14458, 0.17007, 0.01669, 0.01699, 0.02022, 0.0264, 0.03551, 0.04757, 0.06256, 0.0805, 0.10138, 0.1252, 0.15195, 0.16772, 0.01626, 0.01658, 0.0201, 0.0268, 0.03671, 0.0498, 0.06609, 0.08558, 0.10826, 0.13413, 0.16326, 0.16529, 0.01589, 0.01625, 0.02018, 0.02768, 0.03876, 0.05342, 0.07179, 0.09484, 0.12376, 0.15975, 0.17911, 0.17911, 0.01572, 0.0161, 0.02032, 0.02838, 0.04041, 0.05742, 0.08075, 0.11175, 0.15176, 0.20213, 0.20801, 0.20801, 0.01556, 0.01598, 0.02064, 0.0305, 0.04707, 0.07189, 0.10649, 0.15239, 0.21112, 0.2607, 0.2607, 0.2607, 0.01543, 0.01657, 0.02468, 0.04155, 0.06896, 0.10869, 0.16253, 0.23225, 0.31966, 0.34366, 0.34366, 0.34366, 0.01737, 0.02365, 0.04116, 0.07204, 0.11844, 0.18252, 0.26642, 0.37229, 0.46287, 0.46287, 0.46287, 0.46287, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01898, 0.01924, 0.0221, 0.02756, 0.03563, 0.0463, 0.05958, 0.07545, 0.09393, 0.11501, 0.13869, 0.16498, 0.01737, 0.01765, 0.0207, 0.02653, 0.03512, 0.0465, 0.06064, 0.07756, 0.09726, 0.11973, 0.14497, 0.1705, 0.01685, 0.01715, 0.02039, 0.02657, 0.0357, 0.04778, 0.0628, 0.08076, 0.10168, 0.12553, 0.15233, 0.16812, 0.01641, 0.01673, 0.02025, 0.02697, 0.03689, 0.05001, 0.06632, 0.08584, 0.10855, 0.13447, 0.16365, 0.16568, 0.01603, 0.01639, 0.02033, 0.02785, 0.03894, 0.05362, 0.07202, 0.0951, 0.12406, 0.1601, 0.17948, 0.17948, 0.01586, 0.01625, 0.02047, 0.02854, 0.04059, 0.05762, 0.08098, 0.11201, 0.15207, 0.20249, 0.20837, 0.20837, 0.0157, 0.01612, 0.02079, 0.03066, 0.04725, 0.0721, 0.10672, 0.15266, 0.21144, 0.26105, 0.26105, 0.26105, 0.01557, 0.01671, 0.02483, 0.04171, 0.06914, 0.1089, 0.16277, 0.23254, 0.31999, 0.344, 0.344, 0.344, 0.01751, 0.02379, 0.0413, 0.0722, 0.11862, 0.18273, 0.26667, 0.37258, 0.4632, 0.4632, 0.4632, 0.4632, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01918, 0.01944, 0.02231, 0.02778, 0.03587, 0.04656, 0.05986, 0.07577, 0.09428, 0.11541, 0.13914, 0.16548, 0.01755, 0.01782, 0.02088, 0.02672, 0.03533, 0.04672, 0.06089, 0.07784, 0.09757, 0.12008, 0.14537, 0.17095, 0.01702, 0.01731, 0.02056, 0.02675, 0.0359, 0.04799, 0.06304, 0.08104, 0.10198, 0.12588, 0.15273, 0.16854, 0.01657, 0.01689, 0.02042, 0.02715, 0.03708, 0.05022, 0.06656, 0.08611, 0.10886, 0.13482, 0.16404, 0.16608, 0.01619, 0.01654, 0.02049, 0.02802, 0.03913, 0.05383, 0.07226, 0.09537, 0.12437, 0.16046, 0.17986, 0.17986, 0.01601, 0.0164, 0.02063, 0.02871, 0.04077, 0.05783, 0.08122, 0.11229, 0.15239, 0.20285, 0.20874, 0.20874, 0.01585, 0.01627, 0.02094, 0.03083, 0.04744, 0.07231, 0.10697, 0.15294, 0.21177, 0.26141, 0.26141, 0.26141, 0.01571, 0.01685, 0.02498, 0.04188, 0.06933, 0.10911, 0.16302, 0.23283, 0.32033, 0.34436, 0.34436, 0.34436, 0.01765, 0.02393, 0.04145, 0.07236, 0.11881, 0.18295, 0.26693, 0.37289, 0.46355, 0.46355, 0.46355, 0.46355, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01939, 0.01965, 0.02252, 0.02801, 0.03611, 0.04683, 0.06016, 0.0761, 0.09465, 0.11582, 0.1396, 0.166, 0.01773, 0.018, 0.02107, 0.02691, 0.03554, 0.04696, 0.06115, 0.07814, 0.0979, 0.12045, 0.14579, 0.17141, 0.01719, 0.01748, 0.02073, 0.02694, 0.0361, 0.04822, 0.06329, 0.08132, 0.10231, 0.12624, 0.15314, 0.16898, 0.01674, 0.01706, 0.02059, 0.02733, 0.03728, 0.05044, 0.06681, 0.08639, 0.10918, 0.13518, 0.16446, 0.16649, 0.01634, 0.0167, 0.02065, 0.02819, 0.03932, 0.05405, 0.07251, 0.09566, 0.1247, 0.16083, 0.18026, 0.18026, 0.01617, 0.01655, 0.02079, 0.02888, 0.04097, 0.05805, 0.08147, 0.11258, 0.15272, 0.20324, 0.20913, 0.20913, 0.016, 0.01642, 0.0211, 0.031, 0.04763, 0.07253, 0.10722, 0.15324, 0.21211, 0.26179, 0.26179, 0.26179, 0.01586, 0.017, 0.02514, 0.04205, 0.06952, 0.10934, 0.16328, 0.23313, 0.32068, 0.34473, 0.34473, 0.34473, 0.01779, 0.02408, 0.04161, 0.07254, 0.11901, 0.18318, 0.2672, 0.37321, 0.46391, 0.46391, 0.46391, 0.46391, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01961, 0.01987, 0.02275, 0.02825, 0.03637, 0.04711, 0.06046, 0.07644, 0.09504, 0.11625, 0.14009, 0.16654, 0.01791, 0.01819, 0.02126, 0.02712, 0.03576, 0.0472, 0.06143, 0.07844, 0.09824, 0.12084, 0.14622, 0.17189, 0.01737, 0.01766, 0.02092, 0.02714, 0.03632, 0.04846, 0.06356, 0.08162, 0.10264, 0.12662, 0.15357, 0.16944, 0.01691, 0.01723, 0.02077, 0.02752, 0.03749, 0.05067, 0.06707, 0.08668, 0.10951, 0.13556, 0.16489, 0.16693, 0.01651, 0.01687, 0.02082, 0.02838, 0.03953, 0.05427, 0.07277, 0.09595, 0.12503, 0.16122, 0.18067, 0.18067, 0.01633, 0.01671, 0.02096, 0.02907, 0.04117, 0.05828, 0.08173, 0.11288, 0.15306, 0.20363, 0.20953, 0.20953, 0.01616, 0.01658, 0.02127, 0.03118, 0.04783, 0.07276, 0.10748, 0.15354, 0.21246, 0.26218, 0.26218, 0.26218, 0.01601, 0.01716, 0.0253, 0.04223, 0.06972, 0.10957, 0.16355, 0.23345, 0.32105, 0.34511, 0.34511, 0.34511, 0.01795, 0.02423, 0.04177, 0.07271, 0.11922, 0.18342, 0.26748, 0.37354, 0.46428, 0.46428, 0.46428, 0.46428, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.01983, 0.0201, 0.02298, 0.0285, 0.03663, 0.0474, 0.06079, 0.0768, 0.09544, 0.1167, 0.14059, 0.1671, 0.01811, 0.01839, 0.02146, 0.02733, 0.036, 0.04745, 0.06171, 0.07876, 0.0986, 0.12124, 0.14667, 0.17239, 0.01755, 0.01785, 0.02111, 0.02734, 0.03654, 0.0487, 0.06383, 0.08192, 0.10299, 0.12702, 0.15401, 0.16991, 0.01708, 0.01741, 0.02095, 0.02771, 0.0377, 0.05091, 0.06734, 0.08699, 0.10986, 0.13595, 0.16533, 0.16738, - 0.01668, 0.01704, 0.021, 0.02857, 0.03974, 0.05451, 0.07304, 0.09626, 0.12539, 0.16162, 0.1811, 0.1811, 0.01649, 0.01688, 0.02113, 0.02925, 0.04138, 0.05851, 0.082, 0.11319, 0.15342, 0.20405, 0.20995, 0.20995, 0.01632, 0.01674, 0.02144, 0.03137, 0.04804, 0.073, 0.10776, 0.15386, 0.21283, 0.26259, 0.26259, 0.26259, 0.01617, 0.01732, 0.02547, 0.04241, 0.06993, 0.10981, 0.16383, 0.23378, 0.32144, 0.34551, 0.34551, 0.34551, 0.0181, 0.02439, 0.04194, 0.0729, 0.11943, 0.18367, 0.26777, 0.37389, 0.46467, 0.46467, 0.46467, 0.46467, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.02007, 0.02034, 0.02323, 0.02876, 0.03691, 0.0477, 0.06112, 0.07717, 0.09585, 0.11717, 0.14111, 0.16769, 0.01831, 0.01859, 0.02167, 0.02756, 0.03624, 0.04772, 0.062, 0.07909, 0.09897, 0.12166, 0.14714, 0.17292, 0.01775, 0.01804, 0.02131, 0.02755, 0.03677, 0.04895, 0.06411, 0.08225, 0.10335, 0.12743, 0.15447, 0.17041, 0.01727, 0.01759, 0.02114, 0.02792, 0.03792, 0.05116, 0.06762, 0.08731, 0.11022, 0.13636, 0.1658, 0.16785, 0.01685, 0.01722, 0.02119, 0.02877, 0.03996, 0.05476, 0.07332, 0.09658, 0.12575, 0.16204, 0.18155, 0.18155, 0.01667, 0.01705, 0.02132, 0.02945, 0.0416, 0.05876, 0.08228, 0.11352, 0.1538, 0.20448, 0.21039, 0.21039, 0.01649, 0.01691, 0.02162, 0.03156, 0.04826, 0.07325, 0.10805, 0.15419, 0.21322, 0.26302, 0.26302, 0.26302, 0.01634, 0.01749, 0.02565, 0.04261, 0.07015, 0.11006, 0.16412, 0.23412, 0.32184, 0.34592, 0.34592, 0.34592, 0.01827, 0.02455, 0.04211, 0.0731, 0.11965, 0.18393, 0.26808, 0.37425, 0.46507, 0.46507, 0.46507, 0.46507, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.02032, 0.02058, 0.02349, 0.02903, 0.0372, 0.04802, 0.06147, 0.07756, 0.09629, 0.11766, 0.14166, 0.1683, 0.01853, 0.01881, 0.02189, 0.02779, 0.03649, 0.048, 0.06231, 0.07943, 0.09936, 0.12209, 0.14763, 0.17346, 0.01795, 0.01824, 0.02152, 0.02778, 0.03701, 0.04922, 0.06441, 0.08258, 0.10373, 0.12785, 0.15496, 0.17092, 0.01746, 0.01778, 0.02134, 0.02813, 0.03816, 0.05142, 0.06791, 0.08764, 0.1106, 0.13679, 0.16628, 0.16834, 0.01704, 0.0174, 0.02138, 0.02897, 0.04019, 0.05501, 0.07361, 0.09692, 0.12614, 0.16248, 0.18201, 0.18201, 0.01685, 0.01724, 0.02151, 0.02966, 0.04182, 0.05902, 0.08258, 0.11385, 0.15419, 0.20492, 0.21085, 0.21085, 0.01667, 0.01709, 0.02181, 0.03177, 0.04849, 0.0735, 0.10835, 0.15454, 0.21362, 0.26346, 0.26346, 0.26346, 0.01652, 0.01766, 0.02583, 0.04281, 0.07038, 0.11033, 0.16443, 0.23448, 0.32225, 0.34636, 0.34636, 0.34636, 0.01844, 0.02473, 0.0423, 0.0733, 0.11988, 0.1842, 0.26839, 0.37462, 0.46549, 0.46549, 0.46549, 0.46549, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.02058, 0.02085, 0.02375, 0.02931, 0.03751, 0.04835, 0.06184, 0.07797, 0.09675, 0.11817, 0.14223, 0.16894, 0.01875, 0.01903, 0.02212, 0.02803, 0.03675, 0.04828, 0.06263, 0.07979, 0.09976, 0.12255, 0.14814, 0.17404, 0.01816, 0.01846, 0.02174, 0.02801, 0.03726, 0.0495, 0.06472, 0.08293, 0.10412, 0.1283, 0.15546, 0.17146, 0.01766, 0.01799, 0.02155, 0.02836, 0.0384, 0.05169, 0.06822, 0.08798, 0.11099, 0.13724, 0.16679, 0.16885, 0.01723, 0.01759, 0.02158, 0.02919, 0.04043, 0.05528, 0.07391, 0.09726, 0.12654, 0.16294, 0.1825, 0.1825, 0.01704, 0.01743, 0.0217, 0.02987, 0.04206, 0.05929, 0.08289, 0.11421, 0.15459, 0.20539, 0.21132, 0.21132, 0.01686, 0.01728, 0.022, 0.03198, 0.04873, 0.07378, 0.10866, 0.1549, 0.21404, 0.26393, 0.26393, 0.26393, 0.0167, 0.01785, 0.02603, 0.04302, 0.07062, 0.1106, 0.16475, 0.23485, 0.32269, 0.34681, 0.34681, 0.34681, 0.01862, 0.02491, 0.04249, 0.07351, 0.12012, 0.18448, 0.26872, 0.37501, 0.46593, 0.46593, 0.46593, 0.46593, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.02085, 0.02112, 0.02404, 0.0296, 0.03782, 0.0487, 0.06222, 0.0784, 0.09722, 0.1187, 0.14283, 0.16962, 0.01898, 0.01926, 0.02236, 0.02829, 0.03703, 0.04859, 0.06297, 0.08017, 0.10018, 0.12302, 0.14868, 0.17463, 0.01838, 0.01868, 0.02197, 0.02825, 0.03752, 0.04979, 0.06505, 0.0833, 0.10454, 0.12877, 0.15599, 0.17203, 0.01787, 0.0182, 0.02177, 0.02859, 0.03866, 0.05197, 0.06853, 0.08834, 0.1114, 0.13771, 0.16732, 0.16939, 0.01743, 0.0178, 0.02179, 0.02942, 0.04067, 0.05556, 0.07423, 0.09763, 0.12696, 0.16342, 0.18301, 0.18301, 0.01723, 0.01762, 0.02191, 0.03009, 0.04231, 0.05957, 0.08321, 0.11458, 0.15502, 0.20588, 0.21182, 0.21182, 0.01705, 0.01747, 0.02221, 0.0322, 0.04897, 0.07406, 0.10898, 0.15528, 0.21447, 0.26441, 0.26441, 0.26441, 0.01689, 0.01804, 0.02623, 0.04324, 0.07087, 0.11089, 0.16508, 0.23524, 0.32314, 0.34728, 0.34728, 0.34728, 0.01881, 0.02509, 0.04269, 0.07373, 0.12038, 0.18477, 0.26907, 0.37542, 0.46639, 0.46639, 0.46639, 0.46639, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.02114, 0.0214, 0.02433, 0.02991, 0.03816, 0.04906, 0.06262, 0.07884, 0.09772, 0.11926, 0.14346, 0.17032, 0.01922, 0.01951, 0.02262, 0.02855, 0.03731, 0.0489, 0.06332, 0.08056, 0.10063, 0.12352, 0.14924, 0.17526, 0.01861, 0.01891, 0.02221, 0.0285, 0.0378, 0.05009, 0.06539, 0.08368, 0.10497, 0.12926, 0.15654, 0.17262, 0.01809, 0.01842, 0.022, 0.02883, 0.03892, 0.05227, 0.06887, 0.08872, 0.11183, 0.1382, 0.16788, 0.16995, 0.01765, 0.01801, 0.02201, 0.02965, 0.04094, 0.05586, 0.07457, 0.09801, 0.12739, 0.16392, 0.18355, 0.18355, 0.01744, 0.01783, 0.02213, 0.03033, 0.04257, 0.05986, 0.08354, 0.11496, 0.15547, 0.2064, 0.21234, 0.21234, 0.01725, 0.01768, 0.02242, 0.03243, 0.04923, 0.07435, 0.10932, 0.15567, 0.21493, 0.26492, 0.26492, 0.26492, 0.01709, 0.01824, 0.02644, 0.04347, 0.07113, 0.11119, 0.16543, 0.23565, 0.32362, 0.34777, 0.34777, 0.34777, 0.019, 0.02529, 0.04289, 0.07396, 0.12064, 0.18508, 0.26943, 0.37585, 0.46687, 0.46687, 0.46687, 0.46687, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.0214, 0.02166, 0.0246, 0.0302, 0.03846, 0.04939, 0.06299, 0.07925, 0.09818, 0.11977, 0.14404, 0.17096, 0.01945, 0.01973, 0.02285, 0.02879, 0.03758, 0.04919, 0.06364, 0.08092, 0.10103, 0.12397, 0.14975, 0.17583, 0.01882, 0.01912, 0.02242, 0.02874, 0.03805, 0.05037, 0.0657, 0.08403, 0.10536, 0.1297, 0.15704, 0.17315, 0.01829, 0.01862, 0.02221, 0.02906, 0.03917, 0.05254, 0.06917, 0.08907, 0.11222, 0.13864, 0.16838, 0.17046, 0.01784, 0.0182, 0.02221, 0.02987, 0.04117, 0.05612, 0.07487, 0.09836, 0.12779, 0.16437, 0.18403, 0.18403, 0.01763, 0.01802, 0.02232, 0.03054, 0.04281, 0.06013, 0.08385, 0.11531, 0.15587, 0.20686, 0.21281, 0.21281, 0.01744, 0.01786, 0.02261, 0.03264, 0.04947, 0.07462, 0.10963, 0.15603, 0.21535, 0.26538, 0.26538, 0.26538, 0.01727, 0.01842, 0.02663, 0.04368, 0.07137, 0.11146, 0.16575, 0.23602, 0.32405, 0.34822, 0.34822, 0.34822, 0.01918, 0.02547, 0.04308, 0.07417, 0.12088, 0.18536, 0.26976, 0.37624, 0.46731, 0.46731, 0.46731, 0.46731, 0.00363, 0.00384, 0.00621, 0.01072, 0.01737, 0.02618, 0.03713, 0.05023, 0.06548, 0.08287, 0.10241, 0.1241, 0.02194, 0.02221, 0.02516, 0.03079, 0.0391, 0.05009, 0.06376, 0.08011, 0.09914, 0.12085, 0.14524, 0.17231, 0.01991, 0.0202, 0.02333, 0.0293, 0.03812, 0.04979, 0.06431, 0.08167, 0.10187, 0.12493, 0.15082, 0.17702, 0.01926, 0.01956, 0.02288, 0.02922, 0.03858, 0.05095, 0.06634, 0.08475, 0.10618, 0.13063, 0.1581, 0.17428, 0.01871, 0.01904, 0.02264, 0.02952, 0.03968, 0.0531, 0.06981, 0.08979, 0.11304, 0.13957, 0.16944, 0.17152, 0.01824, 0.0186, 0.02263, 0.03032, 0.04167, 0.05668, 0.07551, 0.09908, 0.12862, 0.16533, 0.18504, 0.18504, 0.01802, 0.01842, 0.02274, 0.03099, 0.0433, 0.06069, 0.08449, 0.11605, 0.15672, 0.20784, 0.2138, 0.2138, 0.01782, 0.01825, 0.02302, 0.03309, 0.04996, 0.07519, 0.11028, 0.15678, 0.21622, 0.26635, 0.26635, 0.26635, 0.01765, 0.0188, 0.02703, 0.04412, 0.07186, 0.11203, 0.16642, 0.2368, 0.32496, 0.34916, 0.34916, 0.34916, 0.01955, 0.02584, 0.04348, 0.07461, 0.12138, 0.18595, 0.27045, 0.37705, 0.46822, 0.46822, 0.46822, 0.46822,]) - expected_comments = ['Clean / Free Air Aerodynamics', - 'Reference Area = 1370. sqft'] - - input = get_path( - 'subsystems/aerodynamics/gasp_based/data/GASP_aero_free.txt') - data, comments = _load_gasp_aero_table(input) - if comments != expected_comments: - raise ValueError(f'Comments written to csv do not match ' - 'expected values') - - assert_near_equal(data.get_val('Altitude', 'ft'), expected_alt) - assert_near_equal(data.get_val('Mach'), expected_mach) - assert_near_equal(data.get_val('Angle of Attack', 'deg'), expected_alpha) - assert_near_equal(data.get_val('CL'), expected_cl) - assert_near_equal(data.get_val('CD'), expected_cd) + # Specify the output file + if not output_file: + filename = input_file.stem + output_file = Path.cwd() / Path('TEST_' + filename + '.csv') + else: + output_file = str(Path(output_file)) - def test_GASP_table_3(self): - expected_mach = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, - 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,]) - expected_alpha = np.array([-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,]) - expected_hob = np.array([0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, - 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1, 1.5, 2, 3,]) - expected_cl = np.array([-0.02737, -0.01769, -0.01032, -0.00655, -0.00431, -0.00291, -0.00199, -0.00097, -0.00049, -0.00009, -0.00001, 0, 0.03824, 0.02525, 0.01495, 0.00954, 0.00628, 0.00423, 0.00289, 0.0014, 0.00069, 0.00012, 0.00001, 0, 0.09445, 0.06394, 0.03847, 0.02465, 0.01626, 0.01094, 0.00747, 0.00358, 0.00175, 0.00028, 0.00001, 0, 0.14127, 0.09837, 0.06024, 0.03878, 0.02561, 0.01722, 0.01173, 0.00558, 0.00269, 0.00038, 0, 0, 0.17869, 0.12854, 0.08024, 0.05193, 0.03434, 0.02307, 0.01568, 0.00739, 0.00351, 0.00043, 0, 0, 0.20671, 0.15446, 0.09849, 0.06411, 0.04245, 0.02849, 0.01931, 0.00901, 0.0042, 0.00042, 0, 0, 0.22534, 0.17612, 0.11498, 0.0753, 0.04994, 0.03348, 0.02263, 0.01045, 0.00477, 0.00035, 0, 0, 0.23457, 0.19352, 0.12972, 0.08552, 0.0568, 0.03805, 0.02564, 0.01171, 0.00522, 0.00023, 0, 0, 0.23441, 0.20668, 0.1427, 0.09475, 0.06303, 0.04218, 0.02834, 0.01277, 0.00554, 0.00005, 0, 0, 0.22485, 0.21557, 0.15392, 0.10301, 0.06865, 0.04588, 0.03073, 0.01366, 0.00575, 0, 0, 0, 0.15099, 0.15099, 0.15099, 0.11029, 0.07364, 0.04916, 0.0328, 0.01435, 0.00583, 0, 0, 0, -0.02752, -0.01777, -0.01037, -0.00658, -0.00433, -0.00292, -0.002, -0.00097, -0.00049, -0.00009, -0.00001, 0, 0.03844, 0.02537, 0.01502, 0.00958, 0.00631, 0.00425, 0.00291, 0.0014, 0.0007, 0.00012, 0.00001, 0, 0.09493, 0.06423, 0.03865, 0.02476, 0.01633, 0.01099, 0.0075, 0.0036, 0.00176, 0.00028, 0.00001, 0, 0.14197, 0.09881, 0.0605, 0.03895, 0.02573, 0.0173, 0.01178, 0.0056, 0.0027, 0.00038, 0, 0, 0.17954, 0.12911, 0.08059, 0.05216, 0.03449, 0.02317, 0.01574, 0.00742, 0.00352, 0.00043, 0, 0, 0.20766, 0.15512, 0.09891, 0.06438, 0.04263, 0.02861, 0.01939, 0.00905, 0.00422, 0.00042, 0, 0, 0.22633, 0.17685, 0.11546, 0.07562, 0.05014, 0.03362, 0.02273, 0.01049, 0.00479, 0.00035, 0, 0, 0.23553, 0.19429, 0.13024, 0.08587, 0.05703, 0.0382, 0.02575, 0.01175, 0.00524, 0.00023, 0, 0, 0.23528, 0.20745, 0.14326, 0.09513, 0.06329, 0.04235, 0.02845, 0.01282, 0.00556, 0.00005, 0, 0, 0.22557, 0.21633, 0.1545, 0.10341, 0.06892, 0.04606, 0.03084, 0.01371, 0.00577, 0, 0, 0, 0.14509, 0.14509, 0.14509, 0.11071, 0.07392, 0.04934, 0.03292, 0.0144, 0.00584, 0, 0, 0, -0.02796, -0.01803, -0.01052, -0.00668, -0.00439, -0.00296, -0.00203, -0.00099, -0.0005, -0.00009, -0.00002, 0, 0.03904, 0.02574, 0.01523, 0.00971, 0.0064, 0.00431, 0.00295, 0.00142, 0.00071, 0.00012, 0.00001, 0, 0.0964, 0.06514, 0.03918, 0.0251, 0.01656, 0.01114, 0.0076, 0.00364, 0.00179, 0.00028, 0.00001, 0, 0.1441, 0.10018, 0.06132, 0.03947, 0.02607, 0.01753, 0.01194, 0.00568, 0.00274, 0.00039, 0, 0, 0.18216, 0.13084, 0.08165, 0.05285, 0.03495, 0.02348, 0.01595, 0.00751, 0.00356, 0.00043, 0, 0, 0.21057, 0.15713, 0.10019, 0.06521, 0.04318, 0.02898, 0.01964, 0.00916, 0.00427, 0.00042, 0, 0, 0.22933, 0.17906, 0.11692, 0.07657, 0.05078, 0.03405, 0.02301, 0.01062, 0.00484, 0.00035, 0, 0, 0.23844, 0.19661, 0.13184, 0.08693, 0.05774, 0.03867, 0.02606, 0.01189, 0.00529, 0.00022, 0, 0, 0.23791, 0.2098, 0.14496, 0.09628, 0.06405, 0.04286, 0.02879, 0.01297, 0.00562, 0.00004, 0, 0, 0.22773, 0.21861, 0.15628, 0.10463, 0.06973, 0.0466, 0.0312, 0.01385, 0.00582, 0, 0, 0, 0.127, 0.127, 0.127, 0.11197, 0.07477, - 0.0499, 0.03329, 0.01455, 0.00589, 0, 0, 0, -0.02873, -0.01849, -0.01077, -0.00684, -0.0045, -0.00303, -0.00208, -0.00101, -0.00051, -0.0001, -0.00002, 0, 0.0401, 0.02638, 0.0156, 0.00994, 0.00655, 0.00441, 0.00302, 0.00146, 0.00072, 0.00013, 0.00001, 0, 0.09895, 0.06672, 0.04009, 0.02568, 0.01694, 0.0114, 0.00778, 0.00373, 0.00183, 0.00029, 0.00001, 0, 0.14781, 0.10254, 0.06273, 0.04038, 0.02667, 0.01793, 0.01221, 0.0058, 0.0028, 0.00039, 0, 0, 0.18669, 0.13383, 0.08349, 0.05403, 0.03573, 0.024, 0.0163, 0.00768, 0.00364, 0.00044, 0, 0, 0.21559, 0.16061, 0.10239, 0.06665, 0.04413, 0.02962, 0.02007, 0.00936, 0.00435, 0.00043, 0, 0, 0.2345, 0.18286, 0.11942, 0.07822, 0.05187, 0.03478, 0.0235, 0.01084, 0.00494, 0.00035, 0, 0, 0.24343, 0.20059, 0.13459, 0.08876, 0.05895, 0.03948, 0.0266, 0.01213, 0.00539, 0.00022, 0, 0, 0.24237, 0.2138, 0.14788, 0.09825, 0.06537, 0.04373, 0.02937, 0.01322, 0.00571, 0.00002, 0, 0, 0.23133, 0.22249, 0.15932, 0.10671, 0.07112, 0.04752, 0.03181, 0.01411, 0.00591, 0, 0, 0, 0.09556, 0.09556, 0.09556, 0.09556, 0.07621, 0.05086, 0.03391, 0.0148, 0.00597, 0, 0, 0, -0.02989, -0.01917, -0.01115, -0.00707, -0.00466, -0.00314, -0.00215, -0.00105, -0.00053, -0.0001, -0.00002, 0, 0.04169, 0.02732, 0.01613, 0.01028, 0.00677, 0.00456, 0.00312, 0.00151, 0.00075, 0.00013, 0.00001, 0, 0.10277, 0.06906, 0.04145, 0.02654, 0.01751, 0.01178, 0.00804, 0.00385, 0.00189, 0.0003, 0.00001, 0, 0.15335, 0.10603, 0.06481, 0.04171, 0.02755, 0.01852, 0.01261, 0.00599, 0.00289, 0.00041, 0, 0, 0.19343, 0.13826, 0.08621, 0.05579, 0.03689, 0.02478, 0.01683, 0.00792, 0.00375, 0.00045, 0, 0, 0.22301, 0.16572, 0.10564, 0.06877, 0.04553, 0.03055, 0.0207, 0.00965, 0.00448, 0.00043, 0, 0, 0.2421, 0.18844, 0.12311, 0.08065, 0.05348, 0.03585, 0.02422, 0.01117, 0.00508, 0.00035, 0, 0, 0.25068, 0.2064, 0.13861, 0.09145, 0.06074, 0.04067, 0.0274, 0.01247, 0.00553, 0.00021, 0, 0, 0.24877, 0.2196, 0.15216, 0.10114, 0.06729, 0.04501, 0.03022, 0.01358, 0.00585, 0, 0, 0, 0.23636, 0.22805, 0.16374, 0.10975, 0.07316, 0.04887, 0.03269, 0.01447, 0.00603, 0, 0, 0, 0.04855, 0.04855, 0.04855, 0.04855, 0.04855, 0.04855, 0.03482, 0.01516, 0.00608, 0, 0, 0, -0.03154, -0.02012, -0.01168, -0.00741, -0.00487, -0.00328, -0.00225, -0.0011, -0.00055, -0.00011, -0.00002, 0, 0.04393, 0.02865, 0.01689, 0.01076, 0.00709, 0.00477, 0.00326, 0.00158, 0.00078, 0.00014, 0.00001, 0, 0.10816, 0.07233, 0.04336, 0.02775, 0.0183, 0.01231, 0.0084, 0.00403, 0.00197, 0.00031, 0.00001, 0, 0.16113, 0.11091, 0.06772, 0.04357, 0.02877, 0.01934, 0.01317, 0.00626, 0.00301, 0.00042, 0, 0, 0.20286, 0.1444, 0.08998, 0.05822, 0.0385, 0.02585, 0.01756, 0.00826, 0.00391, 0.00046, 0, 0, 0.23333, 0.17279, 0.11014, 0.0717, 0.04748, 0.03185, 0.02157, 0.01005, 0.00466, 0.00044, 0, 0, 0.25256, 0.19609, 0.12819, 0.08401, 0.05571, 0.03734, 0.02522, 0.01161, 0.00526, 0.00035, 0, 0, 0.26054, 0.2143, 0.14414, 0.09514, 0.06319, 0.04231, 0.02848, 0.01295, 0.00572, 0.00019, 0, 0, 0.25727, 0.2274, 0.15799, 0.1051, 0.06994, 0.04677, 0.03138, 0.01406, 0.00603, 0, 0, 0, 0.17703, 0.17703, 0.16973, 0.11389, 0.07593, 0.05071, 0.0339, 0.01496, 0.0062, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,]) - expected_cd = np.array([-0.00156, -0.0012, -0.00075, -0.00049, -0.00033, -0.00022, -0.00016, -0.00008, -0.00004, -0.00001, 0, 0, -0.00376, -0.00269, -0.00154, -0.00095, -0.00062, -0.00041, -0.00028, -0.00014, -0.00007, -0.00002, 0, 0, -0.00691, -0.00476, -0.00256, -0.00153, -0.00097, -0.00064, -0.00044, -0.00021, -0.00011, -0.00003, -0.00001, 0, -0.01115, -0.00748, -0.00385, -0.00224, -0.0014, -0.00092, -0.00062, -0.00031, -0.00017, -0.00004, -0.00002, 0, -0.01661, -0.01094, -0.00548, -0.00312, -0.00193, -0.00126, -0.00085, -0.00043, -0.00024, -0.00007, -0.00002, 0, -0.02343, -0.01524, -0.00747, -0.0042, -0.00258, -0.00168, -0.00114, -0.00058, -0.00033, -0.0001, -0.00003, 0, -0.03174, -0.02046, -0.00989, -0.00552, -0.00337, -0.00219, -0.0015, -0.00077, -0.00044, -0.00015, -0.00004, 0, -0.04167, -0.02669, -0.01278, -0.00709, -0.00432, -0.00281, -0.00193, -0.00101, -0.00059, -0.00021, -0.00005, 0, -0.05335, -0.034, -0.01619, -0.00894, -0.00545, -0.00356, -0.00244, -0.00129, -0.00077, -0.00028, -0.00007, 0, -0.06687, -0.04249, -0.02015, -0.01112, -0.00678, -0.00443, -0.00306, -0.00164, -0.00098, -0.00035, -0.00008, 0, -0.08524, -0.05762, -0.02604, -0.01364, -0.00833, -0.00546, -0.00378, -0.00205, -0.00124, -0.00042, -0.00009, 0, -0.00188, -0.00143, -0.0009, -0.00059, -0.00039, -0.00027, -0.00019, -0.00009, -0.00005, -0.00001, 0, 0, -0.00453, -0.00323, -0.00184, -0.00114, -0.00074, -0.0005, -0.00034, -0.00017, -0.00009, -0.00002, -0.00001, 0, -0.00831, -0.00571, -0.00306, -0.00183, -0.00116, -0.00077, -0.00052, -0.00026, -0.00014, -0.00003, -0.00001, 0, -0.0134, -0.00897, -0.00462, -0.00268, -0.00167, -0.0011, -0.00075, -0.00037, -0.0002, -0.00005, -0.00002, 0, -0.01996, -0.01314, -0.00657, -0.00374, -0.00231, -0.00151, -0.00102, -0.00051, -0.00028, -0.00008, -0.00003, 0, -0.02816, -0.0183, -0.00896, -0.00504, -0.00309, -0.00201, -0.00137, -0.0007, -0.00039, -0.00013, -0.00004, 0, -0.03815, -0.02457, -0.01187, -0.00661, -0.00404, -0.00263, -0.00179, -0.00093, -0.00053, -0.00018, -0.00005, 0, -0.05009, -0.03205, -0.01534, -0.0085, -0.00518, -0.00337, -0.00231, -0.00121, -0.0007, -0.00025, -0.00006, 0, -0.06412, -0.04084, -0.01943, -0.01073, -0.00653, -0.00427, -0.00293, -0.00155, -0.00092, -0.00034, -0.00008, 0, -0.08039, -0.05104, -0.02419, -0.01335, -0.00813, -0.00532, -0.00367, -0.00197, -0.00118, -0.00043, -0.0001, 0, -0.10285, -0.06982, -0.03208, -0.01638, -0.00999, -0.00655, -0.00454, -0.00246, -0.00149, -0.00051, -0.00011, 0, -0.00183, -0.0014, -0.00088, -0.00058, -0.00039, -0.00026, -0.00018, -0.00009, -0.00005, -0.00001, 0, 0, -0.00446, -0.00318, -0.00181, -0.00112, -0.00073, -0.00049, -0.00033, -0.00016, -0.00008, -0.00002, -0.00001, 0, -0.00821, -0.00564, -0.00302, -0.0018, -0.00114, -0.00075, -0.00051, -0.00025, -0.00013, -0.00003, -0.00001, 0, -0.01327, -0.00888, -0.00456, -0.00265, -0.00165, -0.00108, -0.00073, -0.00037, -0.0002, -0.00005, -0.00002, 0, -0.01981, -0.01303, -0.0065, -0.0037, -0.00228, -0.00149, -0.00101, -0.00051, -0.00028, -0.00008, -0.00003, 0, -0.02799, -0.01818, -0.00889, -0.00499, -0.00305, -0.00199, -0.00135, -0.00069, -0.00039, -0.00012, -0.00004, 0, -0.03797, -0.02444, -0.01178, -0.00655, -0.004, -0.0026, -0.00178, -0.00092, -0.00053, -0.00018, -0.00005, 0, -0.04991, -0.03191, -0.01524, -0.00843, -0.00513, -0.00334, -0.00229, -0.0012, -0.0007, -0.00025, -0.00006, 0, -0.06395, -0.0407, -0.01932, -0.01066, -0.00649, -0.00423, -0.00291, -0.00154, -0.00092, -0.00034, -0.00008, 0, -0.08024, -0.05091, -0.02409, -0.01327, -0.00808, -0.00529, -0.00365, -0.00196, -0.00118, -0.00042, -0.0001, 0, -0.1039, -0.07147, -0.03443, -0.0163, -0.00994, -0.00652, -0.00452, -0.00245, -0.00149, -0.00051, - - 0.00011, 0, -0.0018, -0.00137, -0.00086, -0.00056, -0.00038, -0.00026, -0.00018, -0.00009, -0.00005, -0.00001, 0, 0, -0.00442, -0.00316, -0.0018, -0.00111, -0.00072, -0.00048, -0.00033, -0.00016, -0.00008, -0.00002, -0.00001, 0, -0.0082, -0.00563, -0.00301, -0.00179, -0.00113, -0.00075, -0.00051, -0.00025, -0.00013, -0.00003, -0.00001, 0, -0.01332, -0.00891, -0.00456, -0.00264, -0.00164, -0.00108, -0.00073, -0.00036, -0.0002, -0.00005, -0.00002, 0, -0.01995, -0.0131, -0.00651, -0.0037, -0.00228, -0.00148, -0.00101, -0.00051, -0.00028, -0.00008, -0.00003, 0, -0.02826, -0.01832, -0.00893, -0.005, -0.00306, -0.00199, -0.00135, -0.00069, -0.00039, -0.00013, -0.00004, 0, -0.03841, -0.02469, -0.01186, -0.00658, -0.00401, -0.00261, -0.00178, -0.00092, -0.00053, -0.00018, -0.00005, 0, -0.05058, -0.0323, -0.01537, -0.00849, -0.00516, -0.00336, -0.0023, -0.00121, -0.00071, -0.00026, -0.00006, 0, -0.06491, -0.04126, -0.01953, -0.01075, -0.00653, -0.00426, -0.00293, -0.00156, -0.00093, -0.00035, -0.00008, 0, -0.08156, -0.05169, -0.02439, -0.01341, -0.00815, -0.00533, -0.00368, -0.00198, -0.00119, -0.00043, -0.0001, 0, -0.10771, -0.07569, -0.03911, -0.01911, -0.01005, -0.00659, -0.00457, -0.00248, -0.00151, -0.00052, -0.00012, 0, -0.00175, -0.00134, -0.00084, -0.00055, -0.00037, -0.00025, -0.00018, -0.00009, -0.00004, -0.00001, 0, 0, -0.00441, -0.00314, -0.00179, -0.0011, -0.00072, -0.00048, -0.00033, -0.00016, -0.00008, -0.00002, 0, 0, -0.00826, -0.00566, -0.00301, -0.00179, -0.00113, -0.00075, -0.00051, -0.00025, -0.00013, -0.00003, -0.00001, 0, -0.01349, -0.009, -0.00459, -0.00265, -0.00165, -0.00108, -0.00073, -0.00036, -0.0002, -0.00005, -0.00002, 0, -0.02029, -0.0133, -0.00658, -0.00372, -0.00229, -0.00149, -0.00101, -0.00051, -0.00028, -0.00009, -0.00003, 0, -0.02886, -0.01868, -0.00905, -0.00505, -0.00308, -0.002, -0.00136, -0.0007, -0.00039, -0.00013, -0.00004, 0, -0.03936, -0.02524, -0.01207, -0.00667, -0.00405, -0.00263, -0.0018, -0.00093, -0.00054, -0.00019, -0.00005, 0, -0.05196, -0.03312, -0.01569, -0.00863, -0.00524, -0.00341, -0.00233, -0.00123, -0.00072, -0.00027, -0.00007, 0, -0.06684, -0.04242, -0.01999, -0.01097, -0.00665, -0.00434, -0.00298, -0.00159, -0.00095, -0.00036, -0.00008, 0, -0.08415, -0.05325, -0.02502, -0.01371, -0.00833, -0.00544, -0.00376, -0.00203, -0.00123, -0.00044, -0.0001, 0, -0.11421, -0.08256, -0.0464, -0.02663, -0.01478, -0.00733, -0.00468, -0.00255, -0.00157, -0.00053, -0.00012, 0, -0.0017, -0.0013, -0.00082, -0.00054, -0.00036, -0.00025, -0.00017, -0.00008, -0.00004, -0.00001, 0, 0, -0.00441, -0.00314, -0.00178, -0.0011, -0.00071, -0.00048, -0.00033, -0.00016, -0.00008, -0.00002, 0, 0, -0.00836, -0.00572, -0.00303, -0.00179, -0.00113, -0.00075, -0.00051, -0.00025, -0.00013, -0.00003, -0.00001, 0, -0.01378, -0.00918, -0.00465, -0.00267, -0.00166, -0.00108, -0.00073, -0.00037, -0.0002, -0.00006, -0.00002, 0, -0.02087, -0.01365, -0.00671, -0.00377, -0.00231, -0.0015, -0.00102, -0.00052, -0.00029, -0.00009, -0.00003, 0, -0.02984, -0.01926, -0.00927, -0.00515, -0.00313, -0.00203, -0.00138, -0.00071, -0.0004, -0.00013, -0.00004, 0, -0.04087, -0.02615, -0.01242, -0.00683, -0.00414, -0.00269, -0.00183, -0.00096, -0.00056, -0.0002, -0.00005, 0, -0.05417, -0.03444, -0.01622, -0.00888, -0.00537, -0.00349, -0.00239, -0.00127, -0.00075, -0.00028, -0.00007, 0, -0.0699, -0.04426, -0.02074, -0.01133, -0.00686, -0.00447, -0.00308, -0.00165, -0.00099, -0.00038, -0.00009, 0, -0.09217, -0.0609, -0.02605, -0.01423, -0.00862, -0.00563, -0.0039, -0.00211, -0.00129, -0.00047, -0.0001, 0, -0.12093, -0.08966, -0.05394, -0.03441, -0.02271, -0.01535, -0.01055, -0.00519, -0.00265, -0.00055, -0.00012, 0,]) - expected_comments = ['Incremental Lift and Drag Coeff. for Ground Effects', - 'Reference Area = 1370. sqft / Flap Deflection = 10 deg (T.O. Setting)'] - - input = get_path( - 'subsystems/aerodynamics/gasp_based/data/GASP_aero_ground.txt') - data, comments = _load_gasp_aero_table(input) - if comments != expected_comments: - raise ValueError(f'Comments written to csv do not match ' - 'expected values') - - assert_near_equal(data.get_val('Mach'), expected_mach) - assert_near_equal(data.get_val('Angle of Attack', 'deg'), expected_alpha) - assert_near_equal(data.get_val('Hob'), expected_hob) - assert_near_equal(data.get_val('Delta CL'), expected_cl) - assert_near_equal(data.get_val('Delta CD'), expected_cd) - - def test_FLOPS_table(self): - expected_cd0_alt = np.array([0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, - 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000]) - expected_cd0_mach = np.array([0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85]) - expected_cd0 = np.array([0.01655, 0.01693, 0.01733, 0.01776, 0.01823, 0.01873, 0.01928, 0.01987, 0.02069, 0.02163, 0.02264, 0.02372, 0.02488, 0.01546, 0.0158, 0.01616, 0.01655, 0.01697, 0.01742, 0.01791, 0.01844, 0.01918, 0.02001, 0.0209, 0.02186, 0.02288, 0.0147, 0.01501, 0.01535, 0.01571, 0.0161, 0.01652, 0.01697, 0.01747, 0.01814, 0.01891, 0.01973, 0.02061, 0.02155, 0.01411, 0.0144, 0.01472, 0.01506, 0.01543, 0.01583, 0.01625, 0.01672, 0.01735, 0.01807, 0.01884, 0.01966, 0.02054, 0.01384, 0.01412, 0.01442, 0.01475, 0.0151, 0.01547, 0.01588, 0.01632, 0.01693, 0.01761, 0.01834, 0.01911, 0.01994, 0.01397, 0.01424, 0.01453, 0.01484, 0.01518, - 0.01554, 0.01592, 0.01635, 0.01692, 0.01758, 0.01827, 0.01901, 0.0198, 0.01416, 0.01443, 0.01472, 0.01502, 0.01535, 0.0157, 0.01608, 0.0165, 0.01706, 0.0177, 0.01838, 0.0191, 0.01988, 0.01446, 0.01472, 0.015, 0.01531, 0.01563, 0.01598, 0.01636, 0.01677, 0.01733, 0.01796, 0.01863, 0.01935, 0.02011, 0.01504, 0.0153, 0.01558, 0.01588, 0.0162, 0.01655, 0.01692, 0.01732, 0.01788, 0.0185, 0.01917, 0.01988, 0.02064, 0.01648, 0.01674, 0.01702, 0.01731, 0.01763, 0.01797, 0.01834, 0.01874, 0.01929, 0.01991, 0.02057, 0.02127, 0.02202, 0.02945, 0.02971, 0.02998, 0.03027, 0.03059, 0.03093, 0.0313, 0.03169, 0.03224, 0.03285, 0.0335, 0.0342, 0.03494]) - expected_cd0_comments = ['# zero-lift drag polar, function of altitude & Mach'] - - expected_cdi_mach = np.array([0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85]) - expected_cdi_cl = np.array([0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, - 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9]) - expected_cdi = np.array([0.02325, 0.02395, 0.02501, 0.02638, 0.02811, 0.03013, 0.03244, 0.03482, 0.03792, 0.04134, 0.04485, 0.04873, 0.05298, 0.05771, 0.06285, 0.02166, 0.02237, 0.02342, 0.0248, 0.02652, 0.02854, 0.03085, 0.03323, 0.03634, 0.03975, 0.04327, 0.04715, 0.0514, 0.05612, 0.06127, 0.0206, 0.0213, 0.02236, 0.02373, 0.02546, 0.02748, 0.02979, 0.03217, 0.03527, 0.03869, 0.0422, 0.04608, 0.05033, 0.05506, 0.0602, 0.0198, 0.02049, 0.02154, 0.02292, 0.02466, 0.02667, 0.02896, 0.03136, 0.03445, 0.03787, 0.04138, 0.04526, 0.04951, 0.05424, 0.05938, 0.01938, 0.02005, 0.02109, 0.02248, 0.02424, 0.02624, 0.02851, 0.03092, 0.034, 0.03742, 0.04093, 0.04481, 0.04906, 0.05379, 0.05893, 0.01944, 0.02005, 0.02107, 0.02248, 0.02431, 0.02628, - 0.02848, 0.03093, 0.03398, 0.0374, 0.04091, 0.04479, 0.04904, 0.05377, 0.05891, 0.01965, 0.02021, 0.02122, 0.02265, 0.02451, 0.02647, 0.02862, 0.0311, 0.03411, 0.03749, 0.04103, 0.04504, 0.04954, 0.05461, 0.06022, 0.01997, 0.0205, 0.02149, 0.02293, 0.02484, 0.02678, 0.0289, 0.03138, 0.03439, 0.03774, 0.04173, 0.04658, 0.05226, 0.05893, 0.06653, 0.02069, 0.0211, 0.02206, 0.02355, 0.02556, 0.02756, 0.02973, 0.03226, 0.0356, 0.03965, 0.04498, 0.0511, 0.05799, 0.06558, 0.07388, 0.02252, 0.02265, 0.02352, 0.02511, 0.02742, 0.02979, 0.03244, 0.03596, 0.04021, 0.04641, 0.05251, 0.05976, 0.06817, 0.07769, 0.08832, 0.03669, 0.03593, 0.03651, 0.0384, 0.04164, 0.04582, 0.05105, 0.05619, 0.06639, 0.07341, 0.081, 0.08847, 0.0958, 0.10335, 0.11098]) - expected_cdi_comments = ['# lift-dependent drag polar, function of Mach & CL'] - - input = get_path('utils/test/flops_test_polar.txt') - cdi_data, cdi_comments, cd0_data, cd0_comments = _load_flops_aero_table(input) - - # test CDi - if cdi_comments != expected_cdi_comments: - print(cdi_comments) - print(expected_cdi_comments) - raise ValueError(f'Comments written to csv do not match expected values') - - assert_near_equal(cdi_data.get_val('Mach'), expected_cdi_mach) - assert_near_equal(cdi_data.get_val('Lift Coefficient'), expected_cdi_cl) - assert_near_equal(cdi_data.get_val('Lift-Dependent Drag Coefficient'), - expected_cdi) - - # test CD0 - if cd0_comments != expected_cd0_comments: - raise ValueError(f'Comments written to csv do not match expected values') - - assert_near_equal(cd0_data.get_val('Mach'), expected_cd0_mach) - assert_near_equal(cd0_data.get_val('Altitude', 'ft'), expected_cd0_alt) - assert_near_equal(cd0_data.get_val('Zero-Lift Drag Coefficient'), expected_cd0) - - def test_GASP_file(self): - def args(): return None - args.input_file = 'subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt' - args.output_file = str(Path.cwd() / Path('TEST_'+Path(args.input_file).name)) - args.data_format = 'GASP' - _exec_ATC(args, None) - - validation_data = get_path( - 'subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_flaps.txt') + convert_aero_table(input_file, output_file, data_format) + + def compare_files(self, filepath, validation_file, skip_list=['# created ']): + """ + Compares the converted file with a validation file. + + Use the `skip_list` input to specify strings that are in lines you want + to skip. This is useful for skipping data that Aviary might need but + Fortran-based tools do not. + """ + filename = filepath.split('.')[0] + '.csv' + validation_data = get_path(validation_file) # Open the converted and validation files - with open(args.output_file, 'r') as f_in, open(validation_data, 'r') as expected: + with open('TEST_' + filename, 'r') as f_in, open(validation_data, 'r') as expected: for line in f_in: - if any(s in line for s in ['created']): - break + if any(s in line for s in skip_list): + expected.readline() + continue + # Remove whitespace and compare expected_line = ''.join(expected.readline().split()) line_no_whitespace = ''.join(line.split()) @@ -160,19 +53,157 @@ def args(): return None try: self.assertEqual(line_no_whitespace.count(expected_line), 1) - except Exception as error: - exc_string = f'Error: {args.output_file}\nFound: {line_no_whitespace}\nExpected: {expected_line}' + except Exception: + exc_string = f'Error: TEST_{filename}\nFound: {line_no_whitespace}\nExpected: {expected_line}' raise Exception(exc_string) - def test_FLOPS_file(self): - tempdir = tempfile.mkdtemp(prefix='testdir-') - def args(): return None - args.input_file = 'utils/test/flops_test_polar.txt' - args.output_file = str(Path(tempdir, 'TEST_'+Path(args.input_file).name)) - args.data_format = 'FLOPS' - _exec_ATC(args, None) + def test_GASP_table_1(self): + filename = 'aero_flaps_GASP.txt' + validation_file = 'models/large_single_aisle_1/large_single_aisle_1_aero_flaps.csv' + + self.prepare_and_run(filename, data_format='GASP_ALT') - # Only testing that this runs without an error, not comparing the resulting data + self.compare_files(filename, validation_file) + + def test_GASP_table_2(self): + filename = 'aero_free_GASP.txt' + validation_file = 'models/large_single_aisle_1/large_single_aisle_1_aero_free.csv' + + self.prepare_and_run(filename, data_format='GASP_ALT') + + self.compare_files(filename, validation_file) + + def test_GASP_table_3(self): + filename = 'aero_free_reduced_alpha_GASP.txt' + validation_file = ( + 'models/large_single_aisle_1/large_single_aisle_1_aero_free_reduced_alpha.csv' + ) + + self.prepare_and_run(filename, data_format='GASP_ALT') + + self.compare_files(filename, validation_file) + + def test_GASP_table_4(self): + filename = 'aero_ground_GASP.txt' + validation_file = 'models/large_single_aisle_1/large_single_aisle_1_aero_ground.csv' + + self.prepare_and_run(filename, data_format='GASP_ALT') + + self.compare_files(filename, validation_file) + + def test_GASP_table_5(self): + """Test GASP aero table in alternative format (which is actually the default format)""" + filename = 'aero_BWB_modified_GASP.txt' + validation_file = 'models/aircraft/blended_wing_body/generic_BWB_GASP_aero.csv' + + self.prepare_and_run(filename, data_format='GASP') + + self.compare_files(filename, validation_file) + + # def test_FLOPS_table(self): + # # fmt: off + # expected_cd0_alt = np.array( + # [ + # 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, 0, 5000, 10000, 15000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 55000, 60000, + # ] + # ) + # expected_cd0_mach = np.array( + # [ + # 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, + # ] + # ) + # expected_cd0 = np.array( + # [ + # 0.01655, 0.01693, 0.01733, 0.01776, 0.01823, 0.01873, 0.01928, 0.01987, 0.02069, 0.02163, 0.02264, 0.02372, 0.02488, 0.01546, 0.0158, 0.01616, 0.01655, 0.01697, 0.01742, 0.01791, 0.01844, 0.01918, 0.02001, 0.0209, 0.02186, 0.02288, 0.0147, 0.01501, 0.01535, 0.01571, 0.0161, 0.01652, 0.01697, 0.01747, 0.01814, 0.01891, 0.01973, 0.02061, 0.02155, 0.01411, 0.0144, 0.01472, 0.01506, 0.01543, 0.01583, 0.01625, 0.01672, 0.01735, 0.01807, 0.01884, 0.01966, 0.02054, 0.01384, 0.01412, 0.01442, 0.01475, 0.0151, 0.01547, 0.01588, 0.01632, 0.01693, 0.01761, 0.01834, 0.01911, 0.01994, 0.01397, 0.01424, 0.01453, 0.01484, 0.01518, 0.01554, 0.01592, 0.01635, 0.01692, 0.01758, 0.01827, 0.01901, 0.0198, 0.01416, 0.01443, 0.01472, 0.01502, 0.01535, 0.0157, 0.01608, 0.0165, 0.01706, 0.0177, 0.01838, 0.0191, 0.01988, 0.01446, 0.01472, 0.015, 0.01531, 0.01563, 0.01598, 0.01636, 0.01677, 0.01733, 0.01796, 0.01863, 0.01935, 0.02011, 0.01504, 0.0153, 0.01558, 0.01588, 0.0162, 0.01655, 0.01692, 0.01732, 0.01788, 0.0185, 0.01917, 0.01988, 0.02064, 0.01648, 0.01674, 0.01702, 0.01731, 0.01763, 0.01797, 0.01834, 0.01874, 0.01929, 0.01991, 0.02057, 0.02127, 0.02202, 0.02945, 0.02971, 0.02998, 0.03027, 0.03059, 0.03093, 0.0313, 0.03169, 0.03224, 0.03285, 0.0335, 0.0342, 0.03494, + # ] + # ) + # expected_cd0_comments = ['# zero-lift drag polar, function of altitude & Mach'] + + # expected_cdi_mach = np.array( + # [ + # 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.825, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, + # ] + # ) + # expected_cdi_cl = np.array( + # [ + # 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, + # ] + # ) + # expected_cdi = np.array( + # [ + # 0.02325, 0.02395, 0.02501, 0.02638, 0.02811, 0.03013, 0.03244, 0.03482, 0.03792, 0.04134, 0.04485, 0.04873, 0.05298, 0.05771, 0.06285, 0.02166, 0.02237, 0.02342, 0.0248, 0.02652, 0.02854, 0.03085, 0.03323, 0.03634, 0.03975, 0.04327, 0.04715, 0.0514, 0.05612, 0.06127, 0.0206, 0.0213, 0.02236, 0.02373, 0.02546, 0.02748, 0.02979, 0.03217, 0.03527, 0.03869, 0.0422, 0.04608, 0.05033, 0.05506, 0.0602, 0.0198, 0.02049, 0.02154, 0.02292, 0.02466, 0.02667, 0.02896, 0.03136, 0.03445, 0.03787, 0.04138, 0.04526, 0.04951, 0.05424, 0.05938, 0.01938, 0.02005, 0.02109, 0.02248, 0.02424, 0.02624, 0.02851, 0.03092, 0.034, 0.03742, 0.04093, 0.04481, 0.04906, 0.05379, 0.05893, 0.01944, 0.02005, 0.02107, 0.02248, 0.02431, 0.02628, 0.02848, 0.03093, 0.03398, 0.0374, 0.04091, 0.04479, 0.04904, 0.05377, 0.05891, 0.01965, 0.02021, 0.02122, 0.02265, 0.02451, 0.02647, 0.02862, 0.0311, 0.03411, 0.03749, 0.04103, 0.04504, 0.04954, 0.05461, 0.06022, 0.01997, 0.0205, 0.02149, 0.02293, 0.02484, 0.02678, 0.0289, 0.03138, 0.03439, 0.03774, 0.04173, 0.04658, 0.05226, 0.05893, 0.06653, 0.02069, 0.0211, 0.02206, 0.02355, 0.02556, 0.02756, 0.02973, 0.03226, 0.0356, 0.03965, 0.04498, 0.0511, 0.05799, 0.06558, 0.07388, 0.02252, 0.02265, 0.02352, 0.02511, 0.02742, 0.02979, 0.03244, 0.03596, 0.04021, 0.04641, 0.05251, 0.05976, 0.06817, 0.07769, 0.08832, 0.03669, 0.03593, 0.03651, 0.0384, 0.04164, 0.04582, 0.05105, 0.05619, 0.06639, 0.07341, 0.081, 0.08847, 0.0958, 0.10335, 0.11098, + # ] + # ) + # # fmt: on + + # expected_cdi_comments = ['# lift-dependent drag polar, function of Mach & CL'] + + # input = get_path('utils/test/data/flops_test_polar.txt') + # cdi_data, cdi_comments, cd0_data, cd0_comments = _load_flops_aero_table(input) + + # # test CDi + # if cdi_comments != expected_cdi_comments: + # print(cdi_comments) + # print(expected_cdi_comments) + # raise ValueError('Comments written to csv do not match expected values') + + # assert_near_equal(cdi_data.get_val('Mach'), expected_cdi_mach) + # assert_near_equal(cdi_data.get_val('Lift Coefficient'), expected_cdi_cl) + # assert_near_equal(cdi_data.get_val('Lift-Dependent Drag Coefficient'), expected_cdi) + + # # test CD0 + # if cd0_comments != expected_cd0_comments: + # raise ValueError('Comments written to csv do not match expected values') + + # assert_near_equal(cd0_data.get_val('Mach'), expected_cd0_mach) + # assert_near_equal(cd0_data.get_val('Altitude', 'ft'), expected_cd0_alt) + # assert_near_equal(cd0_data.get_val('Zero-Lift Drag Coefficient'), expected_cd0) + + # def test_GASP_file(self): + # def args(): + # return None + + # args.input_file = 'subsystems/aerodynamics/gasp_based/data/GASP_aero_flaps.txt' + # args.output_file = str(Path.cwd() / Path('TEST_' + Path(args.input_file).name)) + # args.data_format = 'GASP' + # _exec_ATC(args, None) + + # validation_data = get_path( + # 'subsystems/aerodynamics/gasp_based/data/large_single_aisle_1_aero_flaps.txt' + # ) + + # # Open the converted and validation files + # with open(args.output_file, 'r') as f_in, open(validation_data, 'r') as expected: + # for line in f_in: + # if any(s in line for s in ['created']): + # break + # # Remove whitespace and compare + # expected_line = ''.join(expected.readline().split()) + # line_no_whitespace = ''.join(line.split()) + + # # Assert that the lines are equal + # try: + # self.assertEqual(line_no_whitespace.count(expected_line), 1) + + # except Exception: + # exc_string = ( + # f'Error: {args.output_file}\nFound: ' + # f'{line_no_whitespace}\nExpected: {expected_line}' + # ) + # raise Exception(exc_string) + + # def test_FLOPS_file(self): + # tempdir = tempfile.mkdtemp(prefix='testdir-') + + # def args(): + # return None + + # args.input_file = 'utils/test/data/flops_test_polar.txt' + # args.output_file = str(Path(tempdir, 'TEST_' + Path(args.input_file).name)) + # args.data_format = 'FLOPS' + # _exec_ATC(args, None) + + # # Only testing that this runs without an error, not comparing the resulting data if __name__ == '__main__': diff --git a/aviary/utils/test/test_aviary_options_dict.py b/aviary/utils/test/test_aviary_options_dict.py new file mode 100644 index 0000000000..a353f2a19d --- /dev/null +++ b/aviary/utils/test/test_aviary_options_dict.py @@ -0,0 +1,125 @@ +import unittest + +from openmdao.utils.assert_utils import assert_near_equal + +from aviary.utils.aviary_options_dict import AviaryOptionsDictionary + + +class TestAviaryOptionsDict(unittest.TestCase): + """Test conversion of aero table from GASP and FLOPS data format to Aviary format.""" + + def test_declare_options(self): + opts = AviaryOptionsDictionary() + + opts.declare('simple', default=3.5) + self.assertEqual(opts['simple'], 3.5) + + opts.declare('simple_units', default=5.5, units='ft') + self.assertEqual(opts['simple_units'], (5.5, 'ft')) + + opts.declare('bounds_units', default=(1.2, 4.3), units='ft') + self.assertEqual(opts['bounds_units'], ((1.2, 4.3), 'ft')) + + def test_get_val(self): + opts = AviaryOptionsDictionary() + + opts.declare('simple_units', default=2.0, units='ft') + assert_near_equal(opts.get_val('simple_units', units='inch'), 24.0) + + opts.declare('bounds_units', default=(5.0, 6.0), units='ft') + assert_near_equal(opts.get_val('bounds_units', units='inch'), (60.0, 72.0)) + + def test_load_on_init(self): + class TestOptions(AviaryOptionsDictionary): + def declare_options(self): + self.declare( + 'p1', + default=3.0, + ) + + self.declare('p1_units', default=3.0, units='ft') + + data = { + 'p1': 5.5, + 'p1_units': (12.0, 'inch'), + } + + opts = TestOptions(data) + self.assertEqual(opts['p1'], 5.5) + self.assertEqual(opts['p1_units'], (1.0, 'ft')) + + # Support for legacy unitless. + data = { + 'p1': (6.5, 'unitless'), + 'p1_units': (12.0, 'inch'), + } + + opts = TestOptions(data) + self.assertEqual(opts['p1'], 6.5) + + def test_errors(self): + opts = AviaryOptionsDictionary(parent_name='builder') + + opts.declare('simple', default=3.5) + with self.assertRaises(AttributeError) as cm: + opts.get_val('simple', units='ft') + + err_text = "builder: Option 'simple' does not have declared units." + self.assertEqual(str(cm.exception), err_text) + + def test_add_state_options(self): + opts = AviaryOptionsDictionary(parent_name='testing') + + opts.add_state_options('zzz') + + stems = [ + 'initial', + 'final', + 'bounds', + 'ref', + 'ref0', + 'defect_ref', + 'solve_segments', + ] + for stem in stems: + self.assertTrue(f'zzz_{stem}' in opts) + + opts.add_state_options('u', units='ft') + opts['u_final'] = (12.0, 'inch') + val = opts['u_final'] + self.assertEqual(val, (1.0, 'ft')) + + opts.add_state_options('d', defaults={'d_initial': 3.5}, units='m') + val = opts['d_initial'] + self.assertEqual(val, (3.5, 'm')) + + def test_add_control_options(self): + opts = AviaryOptionsDictionary(parent_name='testing') + + opts.add_control_options('zzz') + + stems = [ + 'initial', + 'final', + 'bounds', + 'ref', + 'ref0', + 'polynomial_order', + 'optimize', + 'rate_constraint', + ] + for stem in stems: + self.assertTrue(f'zzz_{stem}' in opts) + + opts.add_control_options('u', units='ft') + opts['u_final'] = (12.0, 'inch') + val = opts['u_final'] + self.assertEqual(val, (1.0, 'ft')) + + opts.add_control_options('d', defaults={'d_initial': 3.5}, units='m') + val = opts['d_initial'] + self.assertEqual(val, (3.5, 'm')) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/utils/test/test_aviary_values.py b/aviary/utils/test/test_aviary_values.py index abc014e02f..199e47b6c0 100644 --- a/aviary/utils/test/test_aviary_values.py +++ b/aviary/utils/test/test_aviary_values.py @@ -12,9 +12,7 @@ class TestTypes(unittest.TestCase): - """ - Test Aviary variables have correct data types. - """ + """Test Aviary variables have correct data types.""" def test_aircraft(self): vals = AviaryValues() @@ -25,7 +23,8 @@ def test_aircraft(self): except TypeError as err: self.assertEqual( str(err), - f"AviaryValues: set_val({Aircraft.Design.PART25_STRUCTURAL_CATEGORY}): unsupported units: None" + f'AviaryValues: set_val({Aircraft.Design.PART25_STRUCTURAL_CATEGORY}): ' + 'unsupported units: None', ) else: self.fail('Expecting correct units to pass.') @@ -36,95 +35,91 @@ def test_aircraft(self): self.fail('Expecting correct units and type to pass.') try: - vals.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, - val=True, units='unitless') + vals.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val=True, units='unitless') except: self.fail('Expecting correct units and type to pass.') try: - vals.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, - val=True, units='unitless') + vals.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, val=True, units='unitless') except: self.fail('Expecting correct units and type to pass.') try: - vals.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, - val='five', units='unitless') + vals.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val='five', units='unitless') except TypeError as err: self.assertEqual( str(err), f"{Aircraft.CrewPayload.NUM_PASSENGERS} is of type(s) but" - " you have provided a value of type .") + " you have provided a value of type .", + ) else: self.fail('Expecting TypeError.') try: - vals.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, - val='five', units='unitless') + vals.set_val(Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, val='five', units='unitless') except TypeError as err: self.assertEqual( str(err), - f"{Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF} is of type(s) but you have provided a value of type .") + f'{Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF} is of type(s) but you have provided a value of type .", + ) else: self.fail('Expecting TypeError.') try: - vals.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, - val='five', units='unitless') + vals.set_val(Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, val='five', units='unitless') except TypeError as err: self.assertEqual( str(err), - f"{Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF} is of type(s) but you have provided a value of type .") + f'{Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF} is of type(s) but you have provided a value of type .", + ) else: self.fail('Expecting TypeError.') try: vals.set_val(Aircraft.Engine.TYPE, GASPEngineType.TURBOJET) - self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASPEngineType.TURBOJET) + self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) is GASPEngineType.TURBOJET) except: self.fail('Expecting to be able to set the value of an Enum.') try: vals.set_val(Aircraft.Engine.TYPE, 'turbojet') - self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASPEngineType.TURBOJET) + self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) == GASPEngineType.TURBOJET) except: - self.fail('Expecting to be able to set the value of an Enum from a string.') + self.fail('Expecting to be able to set the value of an Enum from an int.') try: vals.set_val(Aircraft.Engine.TYPE, 'TURBOJET') - self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASPEngineType.TURBOJET) + self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) is GASPEngineType.TURBOJET) except: self.fail('Expecting to be able to set the value of an Enum from a string.') try: vals.set_val(Aircraft.Engine.TYPE, 7) - self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) - is GASPEngineType.TURBOJET) + self.assertTrue(vals.get_val(Aircraft.Engine.TYPE) is GASPEngineType.TURBOJET) except: self.fail('Expecting to be able to set the value of an Enum from an int.') try: vals.set_val(Aircraft.Engine.TYPE, FlapType.DOUBLE_SLOTTED) - except ValueError as err: - self.assertEqual(str(err), - " is not a valid GASPEngineType") + except TypeError as err: + self.assertEqual( + str(err), + "aircraft:engine:type is of type(s) " + "but you have provided a value of type .", + ) else: - self.fail("Expecting ValueError.") + self.fail('Expecting ValueError.') try: vals.set_val(Aircraft.Engine.DATA_FILE, np.array([])) - except IndexError as err: - self.fail("Expecting to be able to set the value of an empty numpy array.") + except IndexError: + self.fail('Expecting to be able to set the value of an empty numpy array.') else: # NOTE comparing two empty numpy arrays will fail (unlike empty lists), so # arrays are appended to for this test - self.assertEqual(np.append(vals.get_val( - Aircraft.Engine.DATA_FILE), 0), np.array([0])) + self.assertEqual(np.append(vals.get_val(Aircraft.Engine.DATA_FILE), 0), np.array([0])) def test_mission(self): vals = AviaryValues() @@ -139,69 +134,53 @@ def test_mission(self): except: self.fail('Expecting correct units and type to pass.') - try: - vals.set_val(Mission.Design.CRUISE_ALTITUDE, val=True, units='ft') - except TypeError as err: - self.assertEqual( - str(err), - f"{Mission.Design.CRUISE_ALTITUDE} is of type(s) [, ] but you have provided a value of type .") - else: - self.fail('Expecting TypeError.') - - try: - vals.set_val(Mission.Design.CRUISE_ALTITUDE, val='fail', units='ft') - except TypeError as err: - self.assertEqual( - str(err), - f"{Mission.Design.CRUISE_ALTITUDE} is of type(s) [, ] but you have provided a value of type .") - else: - self.fail('Expecting TypeError.') + # TODO: Investigate allowing all numeric types for all numeric vars in + # the hierarchy, then add tests. class TestUnits(unittest.TestCase): - """ - Test Aviary variables have correct units. - """ + """Test Aviary variables have correct units.""" def test_aircraft(self): vals = AviaryValues() try: - vals.set_val(Aircraft.Wing.LOADING, val=20, units='N/cm**2') + vals.set_val(Aircraft.Design.WING_LOADING, val=20, units='N/cm**2') except: self.fail('Expecting correct units and type to pass.') try: - vals.set_val(Aircraft.Wing.LOADING, val=20, units='kgf/cm**2') + vals.set_val(Aircraft.Design.WING_LOADING, val=20, units='kgf/cm**2') except ValueError as err: self.assertEqual( str(err), 'The units kgf/cm**2 which you have provided for' - f' {Aircraft.Wing.LOADING} are invalid.') + f' {Aircraft.Design.WING_LOADING} are invalid.', + ) else: self.fail('Expecting ValueError.') try: - vals.set_val(Aircraft.Wing.LOADING, val=20, units='inch**2/NM') + vals.set_val(Aircraft.Design.WING_LOADING, val=20, units='inch**2/NM') except TypeError as err: self.assertEqual( str(err), - f"The base units of {Aircraft.Wing.LOADING} are lbf/ft**2, and you have" - f" tried to set {Aircraft.Wing.LOADING} with units of inch**2/NM, which" - " are not compatible.") + f'The base units of {Aircraft.Design.WING_LOADING} are lbf/ft**2, and you have' + f' tried to set {Aircraft.Design.WING_LOADING} with units of inch**2/NM, which' + ' are not compatible.', + ) else: self.fail('Expecting TypeError.') try: - vals.set_val(Aircraft.Wing.LOADING, val=20, units='unitless') + vals.set_val(Aircraft.Design.WING_LOADING, val=20, units='unitless') except TypeError as err: self.assertEqual( str(err), - f"The base units of {Aircraft.Wing.LOADING} are lbf/ft**2, and you have" - f" tried to set {Aircraft.Wing.LOADING} with units of unitless, which" - " are not compatible.") + f'The base units of {Aircraft.Design.WING_LOADING} are lbf/ft**2, and you have' + f' tried to set {Aircraft.Design.WING_LOADING} with units of unitless, which' + ' are not compatible.', + ) else: self.fail('Expecting TypeError.') @@ -218,9 +197,10 @@ def test_mission(self): except TypeError as err: self.assertEqual( str(err), - f"The base units of {Mission.Takeoff.FINAL_VELOCITY} are m/s, and you" - f" have tried to set {Mission.Takeoff.FINAL_VELOCITY} with units of kg," - " which are not compatible.") + f'The base units of {Mission.Takeoff.FINAL_VELOCITY} are m/s, and you' + f' have tried to set {Mission.Takeoff.FINAL_VELOCITY} with units of kg,' + ' which are not compatible.', + ) else: self.fail('Expecting TypeError.') @@ -229,32 +209,30 @@ def test_mission(self): except TypeError as err: self.assertEqual( str(err), - f"The base units of {Mission.Takeoff.FINAL_VELOCITY} are m/s, and you" - f" have tried to set {Mission.Takeoff.FINAL_VELOCITY} with units of" - " min/ft, which are not compatible.") + f'The base units of {Mission.Takeoff.FINAL_VELOCITY} are m/s, and you' + f' have tried to set {Mission.Takeoff.FINAL_VELOCITY} with units of' + ' min/ft, which are not compatible.', + ) else: self.fail('Expecting TypeError.') class TestVariableExtension(unittest.TestCase): - """ - Test set_val function for extended Aviary variables. - """ + """Test set_val function for extended Aviary variables.""" def test_set_val_metadata_extension(self): option_defaults = AviaryValues() - filename = get_path( - 'models/engines/turbofan_23k_1.deck') + filename = get_path('models/engines/turbofan_23k_1.csv') option_defaults.set_val(ExtendedAircraft.Engine.DATA_FILE, filename) - option_defaults.set_val(ExtendedAircraft.Wing.AERO_CENTER, val=5, units='ft', - meta_data=ExtendedMetaData) + option_defaults.set_val( + ExtendedAircraft.Wing.AERO_CENTER, val=5.0, units='ft', meta_data=ExtendedMetaData + ) - check_val = option_defaults.get_val( - ExtendedAircraft.Wing.AERO_CENTER, units='inch') + check_val = option_defaults.get_val(ExtendedAircraft.Wing.AERO_CENTER, units='inch') - assert_near_equal(check_val, 60, 1e-9) + assert_near_equal(check_val, np.array([60]), 1e-9) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/utils/test/test_compare_hierarchies.py b/aviary/utils/test/test_compare_hierarchies.py index 9eaaed4849..ae40c384df 100644 --- a/aviary/utils/test/test_compare_hierarchies.py +++ b/aviary/utils/test/test_compare_hierarchies.py @@ -8,9 +8,9 @@ class Aircraft1(AviaryAircraft): - ''' Simple variable hierarchy extension for testing. ''' + """Simple variable hierarchy extension for testing.""" - CG = "aircraft:center_of_gravity" + CG = 'aircraft:center_of_gravity' class LandingGear(AviaryAircraft.LandingGear): SHAPE = 'aircraft:landing_gear:shape' @@ -25,35 +25,33 @@ class Engine(AviaryAircraft.Engine): COLOR = 'aircraft:engine:color' class Fuselage(AviaryAircraft.Fuselage): - class Nose: ECCENTRICITY = 'aircraft:fuselage:nose:eccentricity' class Aircraft2(AviaryAircraft): - ''' Simple variable hierarchy extension for testing. ''' + """Simple variable hierarchy extension for testing.""" - MASS = "aircraft:mass" + MASS = 'aircraft:mass' CG = 'aircraft:center_of_gravity' class HorizontalTail(AviaryAircraft.HorizontalTail): # add variable that is in the core hierarchy and give it the right value AREA = 'aircraft:horizontal_tail:area' - MEAN_AERO_CHORD = "aircraft:horizontal_tail:mean_aerodynamic_chord" + MEAN_AERO_CHORD = 'aircraft:horizontal_tail:mean_aerodynamic_chord' class Elevator: - AREA = "aircraft:horizontal_tail:elevator_area_dist" + AREA = 'aircraft:horizontal_tail:elevator_area_dist' class Wing(AviaryAircraft.Wing): - - AERO_CENTER = "aircraft:wing:aerodynamic_center" - CHORD = "aircraft:wing:chord" + AERO_CENTER = 'aircraft:wing:aerodynamic_center' + CHORD = 'aircraft:wing:chord' AIRFOIL_TECHNOLOGY = 'aircraft:wing:airfoil_technology' class Flap: - AREA = "aircraft:wing:flap_area_dist" - ROOT_CHORD = "aircraft:wing:flap_root_chord_dist" - SPAN = "aircraft:wing:flap_span_dist" + AREA = 'aircraft:wing:flap_area_dist' + ROOT_CHORD = 'aircraft:wing:flap_root_chord_dist' + SPAN = 'aircraft:wing:flap_span_dist' class Jury: MASS = 'aircraft:jury:mass' @@ -62,20 +60,19 @@ class Engine(AviaryAircraft.Engine): COLOR = 'aircraft:engine:color' class Fuselage(AviaryAircraft.Fuselage): - class Nose: ECCENTRICITY = 'aircraft:fuselage:nose:eccentricity' class Aircraft3(AviaryAircraft): - ''' Simple variable hierarchy extension for testing. ''' + """Simple variable hierarchy extension for testing.""" class HorizontalTail: AREA = 'the_wrong_value' # add variable that is in the core hierarchy and give it the wrong value class Aircraft_a: - ''' Simple variable hierarchy for testing. ''' + """Simple variable hierarchy for testing.""" A1 = 'a1' @@ -111,7 +108,7 @@ class Sub10: class Aircraft_b: - ''' Simple variable hierarchy for testing. ''' + """Simple variable hierarchy for testing.""" A1 = 'a1' @@ -147,7 +144,7 @@ class Sub10: class Aircraft_c: - ''' Simple variable hierarchy for testing. ''' + """Simple variable hierarchy for testing.""" A1 = 'a1' @@ -183,9 +180,7 @@ class Sub10: class CompareHierarchiesTest(unittest.TestCase): - """ - Test the functionality of compare_hierarchies_to_merge function. - """ + """Test the functionality of compare_hierarchies_to_merge function.""" def test_compare_successful(self): # this shouldn't throw an error diff --git a/aviary/utils/test/test_csv_data_file.py b/aviary/utils/test/test_csv_data_file.py index 32494f4c6b..8d7f4ed79b 100644 --- a/aviary/utils/test/test_csv_data_file.py +++ b/aviary/utils/test/test_csv_data_file.py @@ -3,10 +3,9 @@ import warnings from openmdao.utils.assert_utils import assert_near_equal, assert_warning -from openmdao.utils.om_warnings import SetupWarning from openmdao.utils.testing_utils import use_tempdirs -from aviary.utils.csv_data_file import write_data_file, read_data_file +from aviary.utils.csv_data_file import read_data_file, write_data_file from aviary.utils.functions import get_path from aviary.utils.named_values import NamedValues, get_items, get_keys from aviary.utils.process_input_decks import parse_inputs @@ -16,18 +15,21 @@ @use_tempdirs class TestAviaryCSV(unittest.TestCase): - """ - Test read/write CSV files and compare CSV files. - """ + """Test read/write CSV files and compare CSV files.""" def setUp(self): - self.filename = get_path('utils/test/csv_test.csv') + self.filename = get_path('utils/test/data/csv_test.csv') # what will get written to the csv - self.data = NamedValues({'aircraft:wing:span': ([15.24, 118, 90, 171], 'ft'), - 'aircraft:crew_and_payload:num_passengers': ([125, 28, 0.355, 44], - 'unitless'), - 'fake_var': ([0.932, 1023.54, 0, -13], 'lbm')}) + self.data = NamedValues( + { + 'aircraft:wing:span': ([15.24, 118, 90, 171], 'ft'), + 'aircraft:crew_and_payload:num_passengers': ([125, 28, 0.355, 44], 'unitless'), + 'fake_var': ([0.932, 1023.54, 0, -13], 'lbm'), + } + ) self.comments = ['comment 1', 'comment 2# more comment 2', 'inline comment'] + self.inputs = ['aircraft:wing:span', 'aircraft:crew_and_payload:num_passengers'] + self.outputs = ['fake_var'] # what the csv should look like after writing self.expected_contents = [ @@ -35,40 +37,42 @@ def setUp(self): '# comment 2# more comment 2', '# inline comment', '', - 'aircraft:wing:span (ft), aircraft:crew_and_payload:num_passengers, fake_var (lbm)', - ' 15.24, 125, 0.932', - ' 118, 28, 1023.54', - ' 90, 0.355, 0', - ' 171, 44, -13'] + 'aircraft:wing:span (ft, input), aircraft:crew_and_payload:num_passengers (input), fake_var (lbm, output)', + ' 15.24, 125, 0.932', + ' 118, 28, 1023.54', + ' 90, 0.355, 0', + ' 171, 44, -13', + ] def test_write_data_file(self): - write_data_file('write.csv', self.data, self.comments) + write_data_file('write.csv', self.data, self.outputs, self.comments) read_contents = [] with open('write.csv') as file: for line in file: read_contents.append(line.strip('\n')) if read_contents != self.expected_contents: - raise ValueError(f'Contents written to csv do not match ' - 'expected values') + raise ValueError('Contents written to csv do not match expected values') def test_read_data_file(self): self._compare_csv_results(*read_data_file(self.filename, save_comments=True)) def test_read_metadata_csv(self): # catch warnings as errors - warnings.filterwarnings("error") + warnings.filterwarnings('error') try: - data, comments = read_data_file(self.filename, CoreMetaData) + data, inputs, outputs, comments = read_data_file(self.filename, CoreMetaData) except UserWarning: # disable warnings as errors behavior for future tests warnings.resetwarnings() # run read_data_file() without catching warnings as errors so it completes - data, comments = read_data_file( - self.filename, CoreMetaData, save_comments=True) + data, inputs, outputs, comments = read_data_file( + self.filename, CoreMetaData, save_comments=True + ) if 'fake_var' in get_keys(data): raise RuntimeError('fake_var should be skipped when reading csv') - self._compare_csv_results(data, comments) + # output 'fake_var' should be missing, so provide self.outputs so comparison passes + self._compare_csv_results(data, inputs, self.outputs, comments) else: # disable warnings as errors behavior for future tests warnings.resetwarnings() @@ -76,13 +80,11 @@ def test_read_metadata_csv(self): # add fake_vars to metadata and try again - should work identically to test_read_data_file() add_meta_data(key='fake_var', meta_data=CoreMetaData, units='lbm') - self._compare_csv_results( - *read_data_file(self.filename, CoreMetaData, save_comments=True)) + self._compare_csv_results(*read_data_file(self.filename, CoreMetaData, save_comments=True)) def test_aliases_csv(self): aliases = {'Real Var': 'Fake Var'} - data = read_data_file( - self.filename, aliases=aliases) + data, _, _ = read_data_file(self.filename, aliases=aliases) if 'fake_var' in get_keys(data): raise RuntimeError("'fake_var' should be converted to 'Real Var'") if 'Real Var' not in get_keys(data): @@ -91,27 +93,32 @@ def test_aliases_csv(self): @use_tempdirs def test_parse_input(self): aircraft_values = get_option_defaults(engine=False) - # create a temperary csv file for testing non-existing variable name - file_name = "aircraft_for_invalid_var.csv" - with open(file_name, "w") as file: - file.write("test_string,0\n") # be ignored - file.write("aircraft:wing:mass_scalar,1,unitless\n") # raise a warning - file.write("aircraft:anti_icing:mass,551,lbm\n") # a good variable + # create a temporary csv file for testing non-existing variable name + file_name = 'aircraft_for_invalid_var.csv' + with open(file_name, 'w') as file: + file.write('test_string,0\n') # be ignored + file.write('aircraft:wing:mass_scalar,1,unitless\n') # raise a warning + file.write('aircraft:anti_icing:mass,551,lbm\n') # a good variable vehicle_deck = get_path(file_name) msg = "Variable 'aircraft:wing:mass_scalar' is not in meta_data nor in 'guess_names'. It will be ignored." with assert_warning(UserWarning, msg): parse_inputs(vehicle_deck, aircraft_values) - # remove the temperary csv file + # remove the temporary csv file os.remove(file_name) - def _compare_csv_results(self, data, comments): + def _compare_csv_results(self, data, inputs, outputs, comments): expected_data = self.data if comments != self.comments: - raise ValueError(f'Comments read from {self.filename.name} do not match ' - 'expected values') + raise ValueError( + f'Comments read from {self.filename.name} do not match expected values' + ) + if inputs != self.inputs: + raise ValueError(f'Inputs read from {self.filename.name} do not match expected values') + if outputs != self.outputs: + raise ValueError(f'Outputs read from {self.filename.name} do not match expected values') for item in get_items(data): key = item[0] val = item[1][0] @@ -121,9 +128,11 @@ def _compare_csv_results(self, data, comments): expected_units = expected_data.get_item(key)[1] assert_near_equal(val, expected_data.get_val(key, expected_units)) if units != expected_units: - raise ValueError(f'Units {units} read from {self.filename.name} do not ' - f'match expected units of {expected_units}') + raise ValueError( + f'Units {units} read from {self.filename.name} do not ' + f'match expected units of {expected_units}' + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/utils/test/test_doctape.py b/aviary/utils/test/test_doctape.py index d13b8d1c15..a25b4409ea 100644 --- a/aviary/utils/test/test_doctape.py +++ b/aviary/utils/test/test_doctape.py @@ -1,15 +1,44 @@ import unittest -import numpy as np - -from openmdao.utils.assert_utils import assert_near_equal, assert_equal_numstrings, assert_equal_arrays - -from aviary.utils.doctape import gramatical_list, check_value, check_contains, check_args, run_command_no_file_error, get_attribute_name, get_all_keys, get_value, get_previous_line, get_variable_name - +import numpy as np +from openmdao.utils.assert_utils import ( + assert_equal_arrays, + assert_equal_numstrings, + assert_near_equal, +) + +from aviary.utils.doctape import ( + check_args, + check_contains, + check_value, + get_all_keys, + get_attribute_name, + get_previous_line, + get_value, + get_variable_name, + glue_class_functions, + glue_class_options, + glue_keys, + glue_variable, + gramatical_list, + run_command_no_file_error, + get_all_non_aviary_names, +) + +try: + import myst_nb +except ImportError: + myst_nb = False + + +@unittest.skipIf( + myst_nb is False, + 'Skipping because myst_nb is not installed for doc testing.', +) class DocTAPETests(unittest.TestCase): """ Testing the DocTAPE functions to make sure they all run in all supported Python versions - Docs are only built with latest, but these test will be run with latest and dev as well + Docs are only built with latest, but these test will be run with latest and dev as well. """ def test_gramatical_list(self): @@ -31,6 +60,7 @@ def test_run_command_no_file_error(self): def test_get_attribute_name(self): class dummy_object: attr1 = 1 + name = get_attribute_name(dummy_object, 1) assert_equal_numstrings(name, 'attr1') @@ -43,10 +73,9 @@ def test_get_value(self): assert_near_equal(val, 2) def test_get_previous_line(self): - something = "something_else" line1 = get_previous_line() line2 = get_previous_line(2) - assert_equal_numstrings(line1, 'something = "something_else"') + assert_equal_numstrings(line2[0].strip(), line1) assert_equal_numstrings(line2[1].strip(), 'line1 = get_previous_line()') def test_get_variable_name(self): @@ -55,13 +84,46 @@ def test_get_variable_name(self): assert_equal_numstrings(name, 'var') # requires IPython shell - # def test_glue_variable(self): - # glue_variable('plain_text') + def test_glue_variable(self): + glue_variable('plain_text', display=False) + + # requires IPython shell + def test_glue_variable_non_str(self): + glue_variable((9, 'ft'), display=False) # requires IPython shell - # def test_glue_keys(self): - # glue_keys({'d1':{'d2':2}}) + def test_glue_keys(self): + glue_keys({'d1': {'d2': 2}}, display=False) + + def test_glue_class_functions(self): + from aviary.interface.methods_for_level2 import AviaryProblem + + curr_glued = [] + glue_class_functions(AviaryProblem, curr_glued, prefix='zz') + + self.assertTrue('load_inputs' in curr_glued) + self.assertTrue('load_inputs()' in curr_glued) + self.assertTrue('zz.load_inputs' in curr_glued) + self.assertTrue('zz.load_inputs()' in curr_glued) + + def test_glue_class_options_attributes(self): + from aviary.core.aviary_group import AviaryGroup + + curr_glued = [] + glue_class_options(AviaryGroup, curr_glued) + + self.assertTrue('auto_order' in curr_glued) + self.assertTrue('mission_info' in curr_glued) + + def test_get_all_non_aviary_names(self): + from aviary.subsystems.aerodynamics.gasp_based.gaspaero import UFac + + names = get_all_non_aviary_names(UFac) + expected_names = ['lift_ratio', 'bbar_alt', 'sigma', 'sigstr', 'ufac'] + assert_equal_arrays(np.array(names), np.array(expected_names)) if __name__ == '__main__': unittest.main() + # test = DocTAPETests() + # test.test_get_all_non_aviary_names() diff --git a/aviary/utils/test/test_engine_deck_conversion.py b/aviary/utils/test/test_engine_deck_conversion.py index a728abad6e..09bcf74109 100644 --- a/aviary/utils/test/test_engine_deck_conversion.py +++ b/aviary/utils/test/test_engine_deck_conversion.py @@ -3,60 +3,45 @@ from openmdao.utils.testing_utils import use_tempdirs -from aviary.utils.engine_deck_conversion import EngineDeckType, _exec_EDC +from aviary.utils.engine_deck_conversion import EngineDeckType, convert_engine_deck from aviary.utils.functions import get_path -class DummyArgs(object): - def __init__(self): - self.input_file = None - self.output_file = None - self.data_format = None - - @use_tempdirs class TestEngineDeckConversion(unittest.TestCase): - """ - Test engine deck conversion utility by comparing against previously converted engine deck files - """ + """Test engine deck conversion utility by comparing against previously converted engine deck files.""" def prepare_and_run(self, filename, output_file=None, data_format=EngineDeckType.GASP): - args = DummyArgs() - # Specify the input file - args.input_file = filepath = get_path('models/engines/'+filename) + input_file = get_path('utils/test/data/' + filename) # Specify the output file if not output_file: - filename = filepath.stem+'.deck' - args.output_file = Path.cwd() / Path('TEST_'+filename) + filename = input_file.stem + '.csv' + output_file = Path.cwd() / Path('TEST_' + filename) else: - args.output_file = str(Path(output_file)) - - # Specify the legacy code and engine type - args.data_format = data_format + output_file = str(Path(output_file)) # Execute the conversion - _exec_EDC(args, None) - return args + convert_engine_deck(input_file, output_file, data_format, True) - def compare_files(self, filepath, skip_list=[]): + def compare_files(self, filepath, skip_list=['# created']): """ Compares the converted file with a validation file. - Use the `skip_list` input to specify strings that are in lines you want - to skip. This is useful for skipping data that Aviary might need but - Fortran-based tools do not. + Use the `skip_list` input to specify strings that are in lines you want to skip. This is + useful for skipping data that Aviary might need but Fortran-based tools do not. """ - filename = filepath.split('.')[0]+'.deck' + filename = filepath.split('.')[0] + '.csv' - validation_data = get_path('models/engines/'+filename) + validation_data = get_path('models/engines/' + filename) # Open the converted and validation files - with open('TEST_'+filename, 'r') as f_in, open(validation_data, 'r') as expected: + with open('TEST_' + filename, 'r') as f_in, open(validation_data, 'r') as expected: for line in f_in: if any(s in line for s in skip_list): - break + expected.readline() + continue # Remove whitespace and compare expected_line = ''.join(expected.readline().split()) line_no_whitespace = ''.join(line.split()) @@ -65,24 +50,30 @@ def compare_files(self, filepath, skip_list=[]): try: self.assertEqual(line_no_whitespace.count(expected_line), 1) - except Exception as error: - exc_string = ( - f'Error: {filename}\n' - f'Found: {line_no_whitespace}\n' - f'Expected: {expected_line}' - ) + except Exception: + exc_string = f'Error: TEST_{filename}\nFound: {line_no_whitespace}\nExpected: {expected_line}' raise Exception(exc_string) - # TODO currently untested!! - # def test_TF_conversion(self): - # return + def test_TF_conversion_FLOPS(self): + filename = 'turbofan_22k.txt' + + self.prepare_and_run(filename, data_format=EngineDeckType.FLOPS) + self.compare_files(filename) + + def test_TF_conversion_GASP(self): + filename = 'turbofan_23k_1.eng' + + self.prepare_and_run(filename, data_format=EngineDeckType.GASP) + self.compare_files(filename) def test_TP_conversion(self): filename = 'turboshaft_4465hp.eng' - args = self.prepare_and_run(filename, data_format=EngineDeckType.GASP_TS) - self.compare_files(filename, skip_list=['# created']) + self.prepare_and_run(filename, data_format=EngineDeckType.GASP_TS) + self.compare_files(filename) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = TestEngineDeckConversion() + # test.test_TP_conversion() diff --git a/aviary/utils/test/test_fortran_to_aviary.py b/aviary/utils/test/test_fortran_to_aviary.py index ba46066aff..92b218007d 100644 --- a/aviary/utils/test/test_fortran_to_aviary.py +++ b/aviary/utils/test/test_fortran_to_aviary.py @@ -1,45 +1,28 @@ import unittest from pathlib import Path -from datetime import datetime from openmdao.utils.testing_utils import use_tempdirs +from aviary.utils.fortran_to_aviary import fortran_to_aviary from aviary.utils.functions import get_path -from aviary.utils.fortran_to_aviary import LegacyCode, _exec_F2A - - -class DummyArgs(object): - def __init__(self): - self.input_deck = None - self.out_file = None - self.legacy_code = None - self.defaults_deck = False - self.force = False - self.verbosity = 0 +from aviary.variable_info.enums import LegacyCode @use_tempdirs class TestFortranToAviary(unittest.TestCase): - """ - Test fortran_to_aviary legacy code input file conversion utility by comparing against already converted input files. - """ + """Test fortran_to_aviary legacy code input file conversion utility by comparing against already converted input files.""" def prepare_and_run(self, filepath, out_file=None, legacy_code=LegacyCode.GASP): - args = DummyArgs() - - # Specify the input file and the legacy code - args.input_deck = filepath - # Specify the output file - filename = filepath.split('.')[0]+'.csv' + filename = filepath.split('.')[0] + '.csv' if not out_file: - args.out_file = Path.cwd() / Path('TEST_'+filename) + out_file = Path.cwd() / Path('TEST_' + filename) else: - args.out_file = Path(out_file) - args.legacy_code = legacy_code + out_file = Path(out_file) + legacy_code = legacy_code # Execute the conversion - _exec_F2A(args, None) + fortran_to_aviary(filepath, legacy_code, out_file, force=True, verbosity=0) def compare_files(self, filepath, skip_list=['# created ']): """ @@ -49,15 +32,16 @@ def compare_files(self, filepath, skip_list=['# created ']): to skip. This is useful for skipping data that Aviary might need but Fortran-based tools do not. """ - filename = filepath.split('.')[0]+'.csv' + filename = filepath.split('.')[0] + '.csv' validation_data = get_path(filename) # Open the converted and validation files - with open('TEST_'+filename, 'r') as f_in, open(validation_data, 'r') as expected: + with open('TEST_' + filename, 'r') as f_in, open(validation_data, 'r') as expected: for line in f_in: if any(s in line for s in skip_list): - break + # expected.readline() + continue # Remove whitespace and compare expected_line = ''.join(expected.readline().split()) @@ -67,44 +51,63 @@ def compare_files(self, filepath, skip_list=['# created ']): try: self.assertEqual(line_no_whitespace.count(expected_line), 1) - except Exception as error: + except Exception: exc_string = ( - f'Error: {filename}\n' - f'Found: {line_no_whitespace}\n' - f'Expected: {expected_line}' + f'Error: {filename}\nFound: {line_no_whitespace}\nExpected: {expected_line}' ) raise Exception(exc_string) def test_large_single_aisle(self): - filepath = 'models/large_single_aisle_1/large_single_aisle_1_GwGm.dat' + filepath = 'models/aircraft/large_single_aisle_1/large_single_aisle_1_GASP.dat' + comparison_filepath = 'utils/test/data/converter_test_large_single_aisle_1_GASP.csv' - self.prepare_and_run(filepath) - self.compare_files(filepath) + self.prepare_and_run( + filepath, + out_file=Path.cwd() / Path('TEST_' + comparison_filepath), + ) + self.compare_files(comparison_filepath) def test_small_single_aisle(self): - filepath = 'models/small_single_aisle/small_single_aisle_GwGm.dat' + filepath = 'models/aircraft/small_single_aisle/small_single_aisle_GASP.dat' + comparison_filepath = 'utils/test/data/converter_test_small_single_aisle_GASP.csv' - self.prepare_and_run(filepath) - self.compare_files(filepath) + self.prepare_and_run( + filepath, + out_file=Path.cwd() / Path('TEST_' + comparison_filepath), + ) + self.compare_files(comparison_filepath) def test_diff_configuration(self): - filepath = 'models/test_aircraft/converter_configuration_test_data_GwGm.dat' + filepath = 'utils/test/data/configuration_test_data_GASP.dat' + comparison_filepath = 'utils/test/data/converter_test_configuration_GASP.csv' - self.prepare_and_run(filepath) - self.compare_files(filepath) + self.prepare_and_run(filepath, out_file=Path.cwd() / Path('TEST_' + comparison_filepath)) + self.compare_files(comparison_filepath) - def test_N3CC(self): + def test_bwb_gasp(self): + filepath = 'models/aircraft/blended_wing_body/generic_BWB_GASP.dat' + comparison_filepath = 'utils/test/data/converter_test_BWB_GASP.csv' + + self.prepare_and_run( + filepath, + out_file=Path.cwd() / Path('TEST_' + comparison_filepath), + ) + self.compare_files(comparison_filepath) + + def test_advanced_single_aisle(self): # Note: The csv comparison file N3CC_generic_low_speed_polars_FLOPSinp.csv was generated using the fortran-to-Aviary converter # and was not evaluated for comparison to the original. Thus, until this file is evaluated, this test is purely a regression # test. - filepath = 'models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.txt' - out_file = Path.cwd() / 'TEST_models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv' - - self.prepare_and_run(filepath, out_file=out_file, legacy_code=LegacyCode.FLOPS) - self.compare_files( - 'models/N3CC/N3CC_generic_low_speed_polars_FLOPSinp.csv') + filepath = 'models/aircraft/advanced_single_aisle/N3CC_generic_low_speed_polars_FLOPS.txt' + comparison_filepath = 'utils/test/data/converter_test_N3CC_FLOPS.csv' + self.prepare_and_run( + filepath, + out_file=Path.cwd() / Path('TEST_' + comparison_filepath), + legacy_code=LegacyCode.FLOPS, + ) + self.compare_files(comparison_filepath) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/utils/test/test_functions.py b/aviary/utils/test/test_functions.py index 9810572ca2..bc11134f36 100644 --- a/aviary/utils/test/test_functions.py +++ b/aviary/utils/test/test_functions.py @@ -1,63 +1,69 @@ -import unittest import os import shutil +import unittest from pathlib import Path import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal +from aviary.api import top_dir +from aviary.utils.functions import ( + add_opts2vals, + convert_strings_to_data, + create_opts2vals, + get_path, +) from aviary.variable_info.options import get_option_defaults from aviary.variable_info.variables import Aircraft, Mission -from aviary.utils.functions import add_opts2vals, create_opts2vals, get_path class TestOpts2Vals(unittest.TestCase): - """ - Test the functionality of create_opts2vals function. - """ + """Test the functionality of create_opts2vals function.""" def setUp(self): self.options = get_option_defaults() - self.options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, - val=180, units='unitless') + self.options.set_val(Aircraft.CrewPayload.NUM_PASSENGERS, val=180, units='unitless') self.options.set_val(Mission.Design.CRUISE_ALTITUDE, val=35, units='kft') def test_default_units(self): tol = 1e-4 self.prob = om.Problem() OptionsToValues = create_opts2vals( - [Aircraft.CrewPayload.NUM_PASSENGERS, - Mission.Design.CRUISE_ALTITUDE,]) + [ + Aircraft.CrewPayload.NUM_PASSENGERS, + Mission.Design.CRUISE_ALTITUDE, + ] + ) add_opts2vals(self.prob.model, OptionsToValues, self.options) self.prob.setup() self.prob.run_model() - assert_near_equal( - self.prob['option:'+Aircraft.CrewPayload.NUM_PASSENGERS], 180, tol) - assert_near_equal(self.prob['option:'+Mission.Design.CRUISE_ALTITUDE], 35, tol) + assert_near_equal(self.prob['option:' + Aircraft.CrewPayload.NUM_PASSENGERS], 180, tol) + assert_near_equal(self.prob['option:' + Mission.Design.CRUISE_ALTITUDE], 35, tol) def test_specified_units(self): tol = 1e-4 self.prob = om.Problem() OptionsToValues = create_opts2vals( - [Aircraft.CrewPayload.NUM_PASSENGERS, - Mission.Design.CRUISE_ALTITUDE,], - output_units={Mission.Design.CRUISE_ALTITUDE: 'm'}) + [ + Aircraft.CrewPayload.NUM_PASSENGERS, + Mission.Design.CRUISE_ALTITUDE, + ], + output_units={Mission.Design.CRUISE_ALTITUDE: 'm'}, + ) add_opts2vals(self.prob.model, OptionsToValues, self.options) self.prob.setup() self.prob.run_model() altitude_in_meters = om.convert_units(35000, 'ft', 'm') + assert_near_equal(self.prob['option:' + Aircraft.CrewPayload.NUM_PASSENGERS], 180, tol) assert_near_equal( - self.prob['option:'+Aircraft.CrewPayload.NUM_PASSENGERS], 180, tol) - assert_near_equal( - self.prob['option:'+Mission.Design.CRUISE_ALTITUDE], altitude_in_meters, tol) + self.prob['option:' + Mission.Design.CRUISE_ALTITUDE], altitude_in_meters, tol + ) class TestGetPath(unittest.TestCase): - """ - Test get_path function from string and Path object for absolute and relative path - """ + """Test get_path function from string and Path object for absolute and relative path.""" def setUp(self): self.current_dir = Path.cwd() @@ -87,8 +93,7 @@ def test_path_from_string_absolute(self): def test_path_from_string_relative(self): result = get_path(self.relative_test_file) - self.assertEqual(result, Path(self.relative_test_file) - ) # Comparing relative paths + self.assertEqual(result, Path(self.relative_test_file)) # Comparing relative paths def test_path_from_path_object_absolute(self): result = get_path(self.absolute_test_file) @@ -96,13 +101,70 @@ def test_path_from_path_object_absolute(self): def test_path_from_path_object_relative(self): result = get_path(Path(self.relative_test_file)) - self.assertEqual(result, Path(self.relative_test_file) - ) # Comparing relative paths + self.assertEqual(result, Path(self.relative_test_file)) # Comparing relative paths def test_non_existent_path(self): with self.assertRaises(FileNotFoundError): get_path('nonexistentfile.txt') -if __name__ == "__main__": +class TestTopDir(unittest.TestCase): + def test_top_dir(self): + result = Path(__file__).parent.parent.parent + self.assertEqual(result, top_dir) + + +class TestConvertStrings2Data(unittest.TestCase): + def is_list_of_given_type(self, lst, givenType): + """Test if the list of data is of given type.""" + return isinstance(lst, list) and all(isinstance(i, givenType) for i in lst) + + def test_read_float(self): + data_list = ['1.0'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [1.0]) + self.assertTrue(self.is_list_of_given_type(var_values, float)) + + data_list = ['100_000.0'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [100000.0]) + self.assertTrue(self.is_list_of_given_type(var_values, float)) + + data_list = ['1.0', '0.285'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [1.0, 0.285]) + self.assertTrue(self.is_list_of_given_type(var_values, float)) + + data_list = ['180'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [180]) + self.assertTrue(self.is_list_of_given_type(var_values, int)) + + data_list = ['0', '180'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [0, 180]) + self.assertTrue(self.is_list_of_given_type(var_values, int)) + + data_list = ['False'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [False]) + self.assertTrue(self.is_list_of_given_type(var_values, bool)) + + data_list = ['True'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [True]) + self.assertTrue(self.is_list_of_given_type(var_values, bool)) + + data_list = ['false', 'true'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, [False, True]) + self.assertTrue(self.is_list_of_given_type(var_values, bool)) + + data_list = ['this_is_a_string'] + var_values = convert_strings_to_data(data_list) + self.assertEqual(var_values, ['this_is_a_string']) + self.assertTrue(self.is_list_of_given_type(var_values, str)) + + +if __name__ == '__main__': unittest.main() diff --git a/aviary/utils/test/test_functions_metadata_extension.py b/aviary/utils/test/test_functions_metadata_extension.py deleted file mode 100644 index 0cab9105b3..0000000000 --- a/aviary/utils/test/test_functions_metadata_extension.py +++ /dev/null @@ -1,35 +0,0 @@ -import unittest - -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.examples.variable_meta_data_extension import ExtendedMetaData -from aviary.examples.variables_extension import Aircraft -from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import set_value -from aviary.utils.functions import get_path - - -class MetaDataExtensionTest(unittest.TestCase): - """ - Test set_value with units for extended MetaData. - """ - - def test_set_value_metadata_extension(self): - option_defaults = AviaryValues() - - filename = get_path( - 'models/engines/turbofan_23k_1.deck') - option_defaults.set_val(Aircraft.Engine.DATA_FILE, filename) - option_defaults.set_val(Aircraft.Wing.AERO_CENTER, val=5, units='ft', - meta_data=ExtendedMetaData) - - option_defaults = set_value(Aircraft.Wing.AERO_CENTER, [ - 1.0], option_defaults, 'ft', ExtendedMetaData) - - check_val = option_defaults.get_val(Aircraft.Wing.AERO_CENTER, units='inch') - - assert_near_equal(check_val, 12, 1e-9) - - -if __name__ == '__main__': - unittest.main() diff --git a/aviary/utils/test/test_merge_hierarchies.py b/aviary/utils/test/test_merge_hierarchies.py index 7edf8ec69b..72243901e1 100644 --- a/aviary/utils/test/test_merge_hierarchies.py +++ b/aviary/utils/test/test_merge_hierarchies.py @@ -8,9 +8,9 @@ class Aircraft1(AviaryAircraft): - ''' Simple variable hierarchy extension for testing. ''' + """Simple variable hierarchy extension for testing.""" - CG = "aircraft:center_of_gravity" + CG = 'aircraft:center_of_gravity' class LandingGear(AviaryAircraft.LandingGear): SHAPE = 'aircraft:landing_gear:shape' @@ -25,7 +25,6 @@ class Engine(AviaryAircraft.Engine): COLOR = 'aircraft:engine:color' class Fuselage(AviaryAircraft.Fuselage): - class Nose: ECCENTRICITY = 'aircraft:fuselage:nose:eccentricity' @@ -43,56 +42,52 @@ class SubSubSubTest: class Aircraft2(AviaryAircraft): - ''' Simple variable hierarchy extension for testing. ''' + """Simple variable hierarchy extension for testing.""" - MASS = "aircraft:mass" + MASS = 'aircraft:mass' CG = 'aircraft:center_of_gravity' class HorizontalTail(AviaryAircraft.HorizontalTail): # add variable that is in the core hierarchy and give it the right value AREA = 'aircraft:horizontal_tail:area' - MEAN_AERO_CHORD = "aircraft:horizontal_tail:mean_aerodynamic_chord" + MEAN_AERO_CHORD = 'aircraft:horizontal_tail:mean_aerodynamic_chord' TEST = 'test' class Elevator: - AREA = "aircraft:horizontal_tail:elevator_area_dist" + AREA = 'aircraft:horizontal_tail:elevator_area_dist' class Wing(AviaryAircraft.Wing): - - AERO_CENTER = "aircraft:wing:aerodynamic_center" - CHORD = "aircraft:wing:chord" + AERO_CENTER = 'aircraft:wing:aerodynamic_center' + CHORD = 'aircraft:wing:chord' AIRFOIL_TECHNOLOGY = 'aircraft:wing:airfoil_technology' class Flap: - AREA = "aircraft:wing:flap_area_dist" - ROOT_CHORD = "aircraft:wing:flap_root_chord_dist" - SPAN = "aircraft:wing:flap_span_dist" + AREA = 'aircraft:wing:flap_area_dist' + ROOT_CHORD = 'aircraft:wing:flap_root_chord_dist' + SPAN = 'aircraft:wing:flap_span_dist' class Engine(AviaryAircraft.Engine): COLOR = 'aircraft:engine:color' class Aircraft3(AviaryAircraft): - ''' Simple variable hierarchy extension for testing. ''' + """Simple variable hierarchy extension for testing.""" class HorizontalTail(AviaryAircraft.HorizontalTail): - class Elevator: - SPAN = "aircraft:horizontal_tail:elevator_span" + SPAN = 'aircraft:horizontal_tail:elevator_span' class Wing(AviaryAircraft.Wing): - class Flap: - CHORD = "aircraft:wing:flap_chord" + CHORD = 'aircraft:wing:flap_chord' class Aircraft4(AviaryAircraft): - ''' Simple variable hierarchy extension for testing. ''' + """Simple variable hierarchy extension for testing.""" class HorizontalTail(AviaryAircraft.HorizontalTail): - class Elevator: - SPAN = "wrong_value" + SPAN = 'wrong_value' class SimpleHierarchy: @@ -140,9 +135,7 @@ class Sub10Test: class MergeHierarchiesTest(unittest.TestCase): - """ - Test functionality of merge_hierarchies function. - """ + """Test functionality of merge_hierarchies function.""" def test_merge1(self): self.maxDiff = None @@ -156,26 +149,25 @@ def test_merge1(self): self.assertEqual(merged.Wing.CHARACTER, 'aircraft:wing:character') self.assertEqual(merged.Jury.MASS, 'aircraft:jury:mass') self.assertEqual(merged.Engine.COLOR, 'aircraft:engine:color') - self.assertEqual(merged.Fuselage.Nose.ECCENTRICITY, - 'aircraft:fuselage:nose:eccentricity') + self.assertEqual(merged.Fuselage.Nose.ECCENTRICITY, 'aircraft:fuselage:nose:eccentricity') self.assertEqual(merged.Test.var1, '1') self.assertEqual(merged.Test.SubTest.var2, '2') self.assertEqual(merged.Test.SubTest.SubSubTest.var3, '3') self.assertEqual(merged.Test.SubTest.SubSubTest.SubSubSubTest.var4, '4') self.assertEqual(merged.MASS, 'aircraft:mass') self.assertEqual(merged.HorizontalTail.AREA, 'aircraft:horizontal_tail:area') - self.assertEqual(merged.HorizontalTail.MEAN_AERO_CHORD, - 'aircraft:horizontal_tail:mean_aerodynamic_chord') + self.assertEqual( + merged.HorizontalTail.MEAN_AERO_CHORD, 'aircraft:horizontal_tail:mean_aerodynamic_chord' + ) self.assertEqual(merged.HorizontalTail.TEST, 'test') - self.assertEqual(merged.HorizontalTail.Elevator.AREA, - 'aircraft:horizontal_tail:elevator_area_dist') + self.assertEqual( + merged.HorizontalTail.Elevator.AREA, 'aircraft:horizontal_tail:elevator_area_dist' + ) self.assertEqual(merged.Wing.AERO_CENTER, 'aircraft:wing:aerodynamic_center') self.assertEqual(merged.Wing.CHORD, 'aircraft:wing:chord') - self.assertEqual(merged.Wing.AIRFOIL_TECHNOLOGY, - 'aircraft:wing:airfoil_technology') + self.assertEqual(merged.Wing.AIRFOIL_TECHNOLOGY, 'aircraft:wing:airfoil_technology') self.assertEqual(merged.Wing.Flap.AREA, 'aircraft:wing:flap_area_dist') - self.assertEqual(merged.Wing.Flap.ROOT_CHORD, - 'aircraft:wing:flap_root_chord_dist') + self.assertEqual(merged.Wing.Flap.ROOT_CHORD, 'aircraft:wing:flap_root_chord_dist') self.assertEqual(merged.Wing.Flap.SPAN, 'aircraft:wing:flap_span_dist') self.assertEqual(merged.Engine.COLOR, 'aircraft:engine:color') self.assertEqual(merged.MASS, 'aircraft:mass') @@ -185,8 +177,7 @@ def test_merge1(self): self.assertEqual(merged.AntiIcing.MASS_SCALER, 'aircraft:anti_icing:mass_scaler') self.assertEqual(merged.APU.MASS, 'aircraft:apu:mass') self.assertEqual(merged.Canard.AREA, 'aircraft:canard:area') - self.assertEqual(merged.CrewPayload.MISC_CARGO, - 'aircraft:crew_and_payload:misc_cargo') + self.assertEqual(merged.CrewPayload.MISC_CARGO, 'aircraft:crew_and_payload:misc_cargo') self.assertEqual(merged.Design.EMPTY_MASS, 'aircraft:design:empty_mass') self.assertEqual(merged.Wing.BWB_AFTBODY_MASS, 'aircraft:wing:bwb_aft_body_mass') self.assertEqual(merged.Hydraulics.MASS, 'aircraft:hydraulics:mass') @@ -203,26 +194,25 @@ def test_merge2(self): self.assertEqual(merged.Wing.CHARACTER, 'aircraft:wing:character') self.assertEqual(merged.Jury.MASS, 'aircraft:jury:mass') self.assertEqual(merged.Engine.COLOR, 'aircraft:engine:color') - self.assertEqual(merged.Fuselage.Nose.ECCENTRICITY, - 'aircraft:fuselage:nose:eccentricity') + self.assertEqual(merged.Fuselage.Nose.ECCENTRICITY, 'aircraft:fuselage:nose:eccentricity') self.assertEqual(merged.Test.var1, '1') self.assertEqual(merged.Test.SubTest.var2, '2') self.assertEqual(merged.Test.SubTest.SubSubTest.var3, '3') self.assertEqual(merged.Test.SubTest.SubSubTest.SubSubSubTest.var4, '4') self.assertEqual(merged.MASS, 'aircraft:mass') self.assertEqual(merged.HorizontalTail.AREA, 'aircraft:horizontal_tail:area') - self.assertEqual(merged.HorizontalTail.MEAN_AERO_CHORD, - 'aircraft:horizontal_tail:mean_aerodynamic_chord') + self.assertEqual( + merged.HorizontalTail.MEAN_AERO_CHORD, 'aircraft:horizontal_tail:mean_aerodynamic_chord' + ) self.assertEqual(merged.HorizontalTail.TEST, 'test') - self.assertEqual(merged.HorizontalTail.Elevator.AREA, - 'aircraft:horizontal_tail:elevator_area_dist') + self.assertEqual( + merged.HorizontalTail.Elevator.AREA, 'aircraft:horizontal_tail:elevator_area_dist' + ) self.assertEqual(merged.Wing.AERO_CENTER, 'aircraft:wing:aerodynamic_center') self.assertEqual(merged.Wing.CHORD, 'aircraft:wing:chord') - self.assertEqual(merged.Wing.AIRFOIL_TECHNOLOGY, - 'aircraft:wing:airfoil_technology') + self.assertEqual(merged.Wing.AIRFOIL_TECHNOLOGY, 'aircraft:wing:airfoil_technology') self.assertEqual(merged.Wing.Flap.AREA, 'aircraft:wing:flap_area_dist') - self.assertEqual(merged.Wing.Flap.ROOT_CHORD, - 'aircraft:wing:flap_root_chord_dist') + self.assertEqual(merged.Wing.Flap.ROOT_CHORD, 'aircraft:wing:flap_root_chord_dist') self.assertEqual(merged.Wing.Flap.SPAN, 'aircraft:wing:flap_span_dist') self.assertEqual(merged.Engine.COLOR, 'aircraft:engine:color') self.assertEqual(merged.MASS, 'aircraft:mass') @@ -232,8 +222,7 @@ def test_merge2(self): self.assertEqual(merged.AntiIcing.MASS_SCALER, 'aircraft:anti_icing:mass_scaler') self.assertEqual(merged.APU.MASS, 'aircraft:apu:mass') self.assertEqual(merged.Canard.AREA, 'aircraft:canard:area') - self.assertEqual(merged.CrewPayload.MISC_CARGO, - 'aircraft:crew_and_payload:misc_cargo') + self.assertEqual(merged.CrewPayload.MISC_CARGO, 'aircraft:crew_and_payload:misc_cargo') self.assertEqual(merged.Design.EMPTY_MASS, 'aircraft:design:empty_mass') self.assertEqual(merged.Wing.BWB_AFTBODY_MASS, 'aircraft:wing:bwb_aft_body_mass') self.assertEqual(merged.Hydraulics.MASS, 'aircraft:hydraulics:mass') @@ -243,7 +232,7 @@ def test_merge3(self): combo3_error_msg = "You have attempted to merge together variable hierarchies that subclass from different superclasses. 'Aircraft1' is a subclass of '' and 'Mission1' is a subclass of ''." with self.assertRaises(ValueError) as cm: - merged = merge_hierarchies(merge_combo3) + merge_hierarchies(merge_combo3) self.assertEqual(str(cm.exception), combo3_error_msg) def test_merge4(self): @@ -263,7 +252,9 @@ def test_merge5(self): self.assertEqual(merged.InnerClass.var1, 'dummy') self.assertEqual( - merged.Test.SubTest.Sub2Test.Sub3Test.Sub4Test.Sub5Test.Sub6Test.Sub7Test.Sub8Test.Sub9Test.Sub10Test.var10, 'dummy10') + merged.Test.SubTest.Sub2Test.Sub3Test.Sub4Test.Sub5Test.Sub6Test.Sub7Test.Sub8Test.Sub9Test.Sub10Test.var10, + 'dummy10', + ) def test_merge6(self): self.maxDiff = None @@ -272,7 +263,9 @@ def test_merge6(self): self.assertEqual(merged.InnerClass.var1, 'dummy') self.assertEqual( - merged.Test.SubTest.Sub2Test.Sub3Test.Sub4Test.Sub5Test.Sub6Test.Sub7Test.Sub8Test.Sub9Test.Sub10Test.var10, 'dummy10') + merged.Test.SubTest.Sub2Test.Sub3Test.Sub4Test.Sub5Test.Sub6Test.Sub7Test.Sub8Test.Sub9Test.Sub10Test.var10, + 'dummy10', + ) def test_merge7(self): self.maxDiff = None @@ -282,20 +275,21 @@ def test_merge7(self): self.assertEqual(merged.MASS, 'aircraft:mass') self.assertEqual(merged.CG, 'aircraft:center_of_gravity') self.assertEqual(merged.HorizontalTail.AREA, 'aircraft:horizontal_tail:area') - self.assertEqual(merged.HorizontalTail.MEAN_AERO_CHORD, - 'aircraft:horizontal_tail:mean_aerodynamic_chord') + self.assertEqual( + merged.HorizontalTail.MEAN_AERO_CHORD, 'aircraft:horizontal_tail:mean_aerodynamic_chord' + ) self.assertEqual(merged.HorizontalTail.TEST, 'test') - self.assertEqual(merged.HorizontalTail.Elevator.AREA, - 'aircraft:horizontal_tail:elevator_area_dist') - self.assertEqual(merged.HorizontalTail.Elevator.SPAN, - 'aircraft:horizontal_tail:elevator_span') + self.assertEqual( + merged.HorizontalTail.Elevator.AREA, 'aircraft:horizontal_tail:elevator_area_dist' + ) + self.assertEqual( + merged.HorizontalTail.Elevator.SPAN, 'aircraft:horizontal_tail:elevator_span' + ) self.assertEqual(merged.Wing.AERO_CENTER, 'aircraft:wing:aerodynamic_center') self.assertEqual(merged.Wing.CHORD, 'aircraft:wing:chord') - self.assertEqual(merged.Wing.AIRFOIL_TECHNOLOGY, - 'aircraft:wing:airfoil_technology') + self.assertEqual(merged.Wing.AIRFOIL_TECHNOLOGY, 'aircraft:wing:airfoil_technology') self.assertEqual(merged.Wing.Flap.CHORD, 'aircraft:wing:flap_chord') - self.assertEqual(merged.Wing.Flap.ROOT_CHORD, - 'aircraft:wing:flap_root_chord_dist') + self.assertEqual(merged.Wing.Flap.ROOT_CHORD, 'aircraft:wing:flap_root_chord_dist') self.assertEqual(merged.Wing.Flap.AREA, 'aircraft:wing:flap_area_dist') self.assertEqual(merged.Wing.Flap.SPAN, 'aircraft:wing:flap_span_dist') self.assertEqual(merged.Engine.COLOR, 'aircraft:engine:color') @@ -305,7 +299,7 @@ def test_merge8(self): combo8_error_msg = "You have attempted to merge two variable hierarchies together that have the same variable with a different string name associated to it. The offending variable is 'SPAN'. In 'Aircraft3.HorizontalTail.Elevator' it has a value of 'aircraft:horizontal_tail:elevator_span' and in 'Aircraft4.HorizontalTail.Elevator' it has a value of 'wrong_value'." with self.assertRaises(ValueError) as cm: - merged = merge_hierarchies(merge_combo8) + merge_hierarchies(merge_combo8) self.assertEqual(str(cm.exception), combo8_error_msg) diff --git a/aviary/utils/test/test_merge_metadata.py b/aviary/utils/test/test_merge_metadata.py index e701161538..4b72ce648b 100644 --- a/aviary/utils/test/test_merge_metadata.py +++ b/aviary/utils/test/test_merge_metadata.py @@ -55,7 +55,7 @@ 'aircraft:fuselage:eccentricity', units=None, desc='Eccentricity of cross section of fuselage', - default_value=.5, + default_value=0.5, meta_data=dict2, historical_name=None, ) @@ -196,7 +196,7 @@ 'aircraft:fuselage:eccentricity', units=None, desc='Eccentricity of cross section of fuselage', - default_value=.5, + default_value=0.5, meta_data=merged_dicts_23, historical_name=None, ) @@ -267,9 +267,7 @@ class MergeMetaDataTest(unittest.TestCase): - """ - Test functionality of merge_meta_data function. - """ + """Test functionality of merge_meta_data function.""" def test_match_merge(self): merge23 = merge_meta_data([dict2, dict3]) diff --git a/aviary/utils/test/test_named_values.py b/aviary/utils/test/test_named_values.py index eaee40c8d6..6ab25579a1 100644 --- a/aviary/utils/test/test_named_values.py +++ b/aviary/utils/test/test_named_values.py @@ -1,6 +1,5 @@ -''' -Unit test cases for class NamedValues. -''' +"""Unit test cases for class NamedValues.""" + import unittest from aviary.utils.named_values import NamedValues, get_items, get_keys, get_values @@ -8,9 +7,7 @@ class NamedValuesTest(unittest.TestCase): - """ - Test NamedValues class - """ + """Test NamedValues class.""" def test_init(self): d = NamedValues() @@ -241,7 +238,7 @@ def _do_test_full_equal(self, d, eq, ne): 'NUM_FUSELAGES': (1, 'unitless'), 'NUM_ENGINES': (2, 'unitless'), Aircraft.CrewPayload.BAGGAGE_MASS: (7500, 'lbm'), - Mission.Design.RANGE: (3500, 'NM') + Mission.Design.RANGE: (3500, 'NM'), } diff --git a/aviary/utils/test/test_process_input_decks.py b/aviary/utils/test/test_process_input_decks.py index 3a5a699aa5..6704b15359 100644 --- a/aviary/utils/test/test_process_input_decks.py +++ b/aviary/utils/test/test_process_input_decks.py @@ -1,30 +1,32 @@ import unittest + from openmdao.utils.testing_utils import use_tempdirs -from aviary.utils.process_input_decks import create_vehicle from aviary.utils.functions import get_path +from aviary.utils.process_input_decks import create_vehicle @use_tempdirs class TestCreateVehicle(unittest.TestCase): - """ - Test creation and modification of aircraft from CSV file. - """ + """Test creation and modification of aircraft from CSV file.""" def test_load_aircraft_csv(self): # Test loading a standard aircraft CSV file. - file_path = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' + file_path = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' aircraft_values, initialization_guesses = create_vehicle(get_path(file_path)) self.assertIsNotNone(aircraft_values) self.assertIsNotNone(initialization_guesses) def test_load_modified_aircraft_csv(self): # Test loading a modified aircraft CSV file with an additional blank line. - original_file_path = 'models/test_aircraft/aircraft_for_bench_FwFm.csv' + original_file_path = 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' modified_file_path = 'modified_aircraft.csv' # Copy and modify the original CSV - with open(get_path(original_file_path), 'r') as original_file, open(modified_file_path, 'w') as modified_file: + with ( + open(get_path(original_file_path), 'r') as original_file, + open(modified_file_path, 'w') as modified_file, + ): content = original_file.readlines() half_way_point = len(content) // 2 diff --git a/aviary/utils/test/test_propeller_map_conversion.py b/aviary/utils/test/test_propeller_map_conversion.py index 09a6862406..01614089fc 100644 --- a/aviary/utils/test/test_propeller_map_conversion.py +++ b/aviary/utils/test/test_propeller_map_conversion.py @@ -4,40 +4,29 @@ from openmdao.utils.testing_utils import use_tempdirs from aviary.utils.functions import get_path -from aviary.utils.propeller_map_conversion import PropMapType, _exec_PMC - - -class DummyArgs(object): - def __init__(self): - self.input_file = None - self.output_file = None - self.data_format = None +from aviary.utils.propeller_map_conversion import PropMapType, convert_propeller_map @use_tempdirs class TestPropellerMapConversion(unittest.TestCase): - """ - Test GASP propeller data file conversion utility by comparing against already converted data files. - """ + """Test GASP propeller data file conversion utility by comparing against already converted data files.""" def prepare_and_run(self, filename, output_file=None, data_format=PropMapType.GASP): - args = DummyArgs() - # Specify the input file - args.input_file = filepath = get_path('models/propellers/'+filename) + input_file = filepath = get_path('models/engines/propellers/' + filename) # Specify the output file if not output_file: - filename = filepath.stem+'.prop' - args.output_file = Path.cwd() / Path('TEST_'+filename) + filename = filepath.stem + '.csv' + output_file = Path.cwd() / Path('TEST_' + filename) else: - args.output_file = str(Path(output_file)) + output_file = str(Path(output_file)) # Specify the legacy code and propeller map - args.data_format = data_format + data_format = data_format # Execute the conversion - _exec_PMC(args, None) + convert_propeller_map(input_file, output_file, round_data=True) def compare_files(self, filepath, skip_list=[]): """ @@ -47,15 +36,16 @@ def compare_files(self, filepath, skip_list=[]): to skip. This is useful for skipping data that Aviary might need but Fortran-based tools do not. """ - filename = filepath.split('.')[0]+'.prop' + filename = filepath.split('.')[0] + '.csv' - validation_data = get_path('models/propellers/'+filename) + validation_data = get_path('models/engines/propellers/' + filename) # Open the converted and validation files - with open('TEST_'+filename, 'r') as f_in, open(validation_data, 'r') as expected: + with open('TEST_' + filename, 'r') as f_in, open(validation_data, 'r') as expected: for line in f_in: if any(s in line for s in skip_list): - break + expected.readline() + continue # Remove whitespace and compare expected_line = ''.join(expected.readline().split()) line_no_whitespace = ''.join(line.split()) @@ -64,15 +54,24 @@ def compare_files(self, filepath, skip_list=[]): try: self.assertEqual(line_no_whitespace.count(expected_line), 1) - except: - exc_string = f'Error: {filename}\nFound: {line_no_whitespace}\nExpected: {expected_line}' + except Exception: + exc_string = ( + f'Error: {filename}\nFound: {line_no_whitespace}\nExpected: {expected_line}' + ) raise Exception(exc_string) - def test_PM_conversion(self): + def test_propfan_conversion(self): filename = 'PropFan.map' self.prepare_and_run(filename, data_format=PropMapType.GASP) self.compare_files(filename, skip_list=['# created']) + def test_GA_conversion(self): + filename = 'general_aviation.map' + self.prepare_and_run(filename, data_format=PropMapType.GASP) + self.compare_files(filename, skip_list=['# created']) + -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = TestPropellerMapConversion() + # test.test_PM_conversion() diff --git a/aviary/utils/test_utils/IO_test_util.py b/aviary/utils/test_utils/IO_test_util.py index 0ec0c6d382..58ec33df74 100644 --- a/aviary/utils/test_utils/IO_test_util.py +++ b/aviary/utils/test_utils/IO_test_util.py @@ -1,4 +1,3 @@ -import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal @@ -28,7 +27,7 @@ def check_prob_outputs(prob, vals, rtol=1e-6): try: assert_near_equal(prob[path], val, tolerance=t) except ValueError as e: - errors.append(f"\n {path}: {e}") + errors.append(f'\n {path}: {e}') if errors: - raise ValueError("".join(errors)) + raise ValueError(''.join(errors)) diff --git a/aviary/utils/test_utils/assert_utils.py b/aviary/utils/test_utils/assert_utils.py index 5e0b6d8dd9..65c124b7dd 100644 --- a/aviary/utils/test_utils/assert_utils.py +++ b/aviary/utils/test_utils/assert_utils.py @@ -1,16 +1,15 @@ -""" -Utilities used for testing Aviary code. -""" +"""Utilities used for testing Aviary code.""" + from dymos.utils.testing_utils import assert_timeseries_near_equal -def warn_timeseries_near_equal(t_ref, x_ref, t_check, x_check, abs_tolerance=None, - rel_tolerance=None): - """ - Wraps timeseries check with a try block that prints a warning if the assert fails. - """ +def warn_timeseries_near_equal( + t_ref, x_ref, t_check, x_check, abs_tolerance=None, rel_tolerance=None +): + """Wraps timeseries check with a try block that prints a warning if the assert fails.""" try: - assert_timeseries_near_equal(t_ref, x_ref, t_check, x_check, abs_tolerance=abs_tolerance, - rel_tolerance=rel_tolerance) + assert_timeseries_near_equal( + t_ref, x_ref, t_check, x_check, abs_tolerance=abs_tolerance, rel_tolerance=rel_tolerance + ) except AssertionError as exc: - print("Warning:\n", str(exc)) + print('Warning:\n', str(exc)) diff --git a/aviary/utils/test_utils/default_subsystems.py b/aviary/utils/test_utils/default_subsystems.py index 0975a5dbc1..57626425dd 100644 --- a/aviary/utils/test_utils/default_subsystems.py +++ b/aviary/utils/test_utils/default_subsystems.py @@ -1,9 +1,9 @@ -from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder +from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder from aviary.subsystems.mass.mass_builder import CoreMassBuilder -from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder -from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData +from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder from aviary.variable_info.enums import LegacyCode +from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData def get_default_premission_subsystems(legacy_code, engines=None): @@ -38,9 +38,24 @@ def get_default_mission_subsystems(legacy_code, engines=None): engine : List of EngineDecks """ - legacy_code = LegacyCode(legacy_code) prop = CorePropulsionBuilder('core_propulsion', BaseMetaData, engine_models=engines) aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, legacy_code) return [aero, prop] + + +def get_geom_and_mass_subsystems(legacy_code): + """ + Get geometry and mass premission subsystems in this order. + + Arguments: + ---------- + legacy_code : str, LegacyCode + either FLOPS or GASP LegacyCode Enums, or their strings equivalents ('FLOPS', 'GASP') + """ + legacy_code = LegacyCode(legacy_code) + mass = CoreMassBuilder('core_mass', BaseMetaData, legacy_code) + geom = CoreGeometryBuilder('core_geometry', BaseMetaData, legacy_code) + + return [geom, mass] diff --git a/aviary/utils/test_utils/variable_test.py b/aviary/utils/test_utils/variable_test.py index ea498de772..00eac71148 100644 --- a/aviary/utils/test_utils/variable_test.py +++ b/aviary/utils/test_utils/variable_test.py @@ -5,7 +5,7 @@ from aviary.variable_info.variable_meta_data import _MetaData -base_path = os.path.abspath(os.path.join(__file__, "..", "..", "..")) +base_path = os.path.abspath(os.path.join(__file__, '..', '..', '..')) def assert_no_duplicates( @@ -30,9 +30,7 @@ def assert_no_duplicates( duplicates.append(check_name) duplicates = list(set(duplicates)) - raise ValueError( - f"The variables {duplicates} are duplicates in the provided list." - ) + raise ValueError(f'The variables {duplicates} are duplicates in the provided list.') return duplicates @@ -41,8 +39,8 @@ def assert_structure_alphabetization(file_loc): """ Assert that an aviary variable hierarchy is properly sorted. - Parameters: - ----------- + Parameters + ---------- file_loc : str Location of the hierarchy file relative to the aviary top directory. """ @@ -51,8 +49,8 @@ def assert_structure_alphabetization(file_loc): with open(full_file_loc) as variable_file: lines = variable_file.readlines() - previous_line = "" - previous_stem = "" + previous_line = '' + previous_stem = '' nested_stems = {0: ''} bad_sort = [] in_block_comment = False @@ -79,8 +77,8 @@ def assert_structure_alphabetization(file_loc): if line.startswith('class'): # Class lines - class_name = line.split("class ")[-1] - current_stem = f"{nested_stems[leading_spaces]}{class_name}" + class_name = line.split('class ')[-1] + current_stem = f'{nested_stems[leading_spaces]}{class_name}' nested_stems[leading_spaces + 4] = current_stem current_stem_fix = current_stem.casefold() @@ -88,12 +86,12 @@ def assert_structure_alphabetization(file_loc): bad_sort.append(current_stem) previous_stem = current_stem_fix - previous_line = "" + previous_line = '' - elif "=" in line: + elif '=' in line: # Variable lines - var_name = line.split("=")[0].strip() - current_line = f"{nested_stems[leading_spaces]}{var_name}" + var_name = line.split('=')[0].strip() + current_line = f'{nested_stems[leading_spaces]}{var_name}' current_line_fix = current_line.casefold() if current_line_fix < previous_line: @@ -102,7 +100,7 @@ def assert_structure_alphabetization(file_loc): previous_line = current_line_fix if leading_spaces % 4 > 0: - msg = "The variable file is not using proper Python spacing." + msg = 'The variable file is not using proper Python spacing.' raise ValueError(msg) if len(bad_sort) > 0: @@ -112,18 +110,18 @@ def assert_structure_alphabetization(file_loc): def assert_metadata_alphabetization(metadata_variables_list): - previous_var = metadata_variables_list[0].split(":") + previous_var = metadata_variables_list[0].split(':') out_of_order_vars = [] for var_name in metadata_variables_list[1:]: - current_var = var_name.split(":") + current_var = var_name.split(':') max_size = min(len(current_var), len(previous_var)) same = [previous_var[ct] == current_var[ct] for ct in np.arange(max_size)] try: diff_idx = same.index(False) except ValueError: raise ValueError( - "There are two variables in the metadata file that have the same string name." + 'There are two variables in the metadata file that have the same string name.' ) # only compare up to class level, avoid comparing variables to classes if len(current_var) > len(previous_var): @@ -141,16 +139,16 @@ def assert_metadata_alphabetization(metadata_variables_list): if out_of_order_vars: raise ValueError( - f"The variable(s) {out_of_order_vars} in the metadata are out of alphabetical order with their previous value." + f'The variable(s) {out_of_order_vars} in the metadata are out of alphabetical order with their previous value.' ) def assert_match_varnames(system, MetaData=None, exclude_inputs=None, exclude_outputs=None): """ - Assert that the inputs and outputs of the system match with those in MetaData + Assert that the inputs and outputs of the system match with those in MetaData. - Parameters: - ----------- + Parameters + ---------- exclude_inputs: set The inputs that are excluded from comparison with MetaData. exclude_outputs: set @@ -161,39 +159,36 @@ def assert_match_varnames(system, MetaData=None, exclude_inputs=None, exclude_ou list List of all names in the hierarchy, including duplicates. """ - prob = om.Problem() prob.model = system prob.setup() prob.final_setup() sys_inputs = prob.model.list_inputs(out_stream=None, prom_name=True) - sys_inputs = set([val[1]["prom_name"] for val in sys_inputs]) + sys_inputs = set([val[1]['prom_name'] for val in sys_inputs]) sys_outputs = prob.model.list_outputs(out_stream=None, prom_name=True) - sys_outputs = set([val[1]["prom_name"] for val in sys_outputs]) + sys_outputs = set([val[1]['prom_name'] for val in sys_outputs]) - proper_var_names = set( - [key for key in (_MetaData if MetaData is None else MetaData)] - ) + proper_var_names = set([key for key in (_MetaData if MetaData is None else MetaData)]) input_overlap = sys_inputs.intersection(proper_var_names) output_overlap = sys_outputs.intersection(proper_var_names) if input_overlap != sys_inputs: diff = sys_inputs - input_overlap - if not exclude_inputs is None: + if exclude_inputs is not None: diff = diff - exclude_inputs if len(diff) > 0: raise ValueError( - f"The inputs {diff} in the provided subsystem are not found in the provided variable structure." + f'The inputs {diff} in the provided subsystem are not found in the provided variable structure.' ) if output_overlap != sys_outputs: diff = sys_outputs - output_overlap - if not exclude_outputs is None: + if exclude_outputs is not None: diff = diff - exclude_outputs if len(diff) > 0: raise ValueError( - f"The outputs {diff} in the provided subsystem are not found in the provided variable structure." + f'The outputs {diff} in the provided subsystem are not found in the provided variable structure.' ) @@ -203,8 +198,8 @@ def get_names_from_hierarchy(hierarchy): This is used for finding duplicates names. - Parameters: - ----------- + Parameters + ---------- hierarchy: object Instance of a class hierarchy such as Aircraft. @@ -234,7 +229,7 @@ def get_names_from_hierarchy(hierarchy): def filter_empty(entry): - if (entry != '') and (entry != None): + if (entry != '') and (entry is not None): return True else: diff --git a/aviary/utils/utils.py b/aviary/utils/utils.py new file mode 100644 index 0000000000..651bd184a8 --- /dev/null +++ b/aviary/utils/utils.py @@ -0,0 +1,258 @@ +""" +A home for helper functions that are used in multiple files in aviary/utils +Helps to avoid circular imports. These functions do not rely on imports from other utility files. +""" + +from copy import deepcopy +from enum import Enum + +import numpy as np +from openmdao.utils.units import convert_units + +from aviary.variable_info.variable_meta_data import _MetaData + + +def isiterable(val, valid_iterables: tuple = (list, np.ndarray, tuple)): + """ + Checks if provided value is an iterable, as defined by the _valid_iterables global variable. + + Parameters + ---------- + val : any object + The object that will be checked if it is a supported iterable type + valid_iterables : tuple of types + Which iterable types val will be checked against. By default, lists, numpy arrays and tuples + are supported types + """ + return isinstance(val, valid_iterables) + + +def wrapped_convert_units(val_unit_tuple, new_units): + """ + Wrapper for OpenMDAO's convert_units function. Can handle iterable values. + + Parameters + ---------- + val_unit_tuple : tuple + Tuple of the form (value, units) where value is a float and units is a string. + new_units : str + New units to convert to. + + Returns + ------- + value: float, list, np.ndarray, tuple + Value converted to new units, as the same type as provided + """ + value, units = deepcopy(val_unit_tuple) + + # can't convert units on None; return None + if value is None: + return None + + if isiterable(value): + # tuples are immutable, so we have to convert to list to modify each index + if isinstance(value, tuple): + istuple = True + value = list(value) + else: + istuple = False + + for i, item in enumerate(value): + # Any entry may be none. + if value[i] is not None: + value[i] = convert_units(item, units, new_units) + + if istuple: + value = tuple(value) + else: + value = convert_units(value, units, new_units) + + return value + + +def enum_setter(opt_meta, value): + """ + Support setting the option with a string or int and converting it to the proper enum object. + + Parameters + ---------- + opt_meta : dict + Dictionary of entries for the option. + value : any + New value for the option. + + Returns + ------- + any + Post processed value to set into the option. + """ + types = opt_meta['types'] + if not isinstance(types, tuple): + types = (types,) + for type_ in types: + if issubclass(type_, Enum): + enum_class = type_ + break + + if isinstance(value, Enum): + return value + + elif isinstance(value, int): + return enum_class(value) + + elif isinstance(value, str): + try: + return enum_class(value) + except ValueError: + return getattr(enum_class, value.upper()) + + elif isiterable(value): + # Numpy arrays have unique typing (float64, etc.), convert to list of standard + # python types + if isinstance(value, np.ndarray): + value_iter = value.tolist() + else: + value_iter = value + values = [] + for val in value_iter: + if isinstance(val, Enum): + values.append(val) + elif isinstance(val, int): + values.append(enum_class(val)) + elif isinstance(val, str): + try: + # see if str maps to ENUM value + return enum_class(val) + except ValueError: + # str instead maps to ENUM name + return getattr(enum_class, val.upper()) + else: + break + else: + # maintain the same type of iterable + if isinstance(value, np.ndarray): + values = np.array(values) + else: + values = type(value)(values) + + return values + + msg = f"Value '{value}' not valid for option with types {enum_class}" + raise TypeError(msg) + + +def check_type(key, val, meta_data=_MetaData): + """ + Check that provided val is the correct type. If val is iterable, also check each individual + index. + """ + + def _flatten_iters(iterable): + """Recursively flattens iterables of any type and dimension.""" + for item in iterable: + if isiterable(item): + yield from _flatten_iters(item) + else: + yield item + + # make a copy of val, so we do not modify it + input_val = deepcopy(val) + expected_types = meta_data[key]['types'] + if expected_types is None: + # MetaData item has no type requirement. + return + + # If data is iterable, check that it is allowed to be. + # Variables flagged multivalue can be lists or numpy arrays even if not specified in `types` + if isiterable(input_val): + types = expected_types + if meta_data[key]['multivalue']: + if isinstance(expected_types, tuple): + types = (list, np.ndarray, tuple, *expected_types) + else: + types = (list, np.ndarray, tuple, expected_types) + if not isinstance(input_val, types): + raise TypeError( + f'{key} is of type(s) {types} but you have provided a value of type ' + f'{type(input_val)}.' + ) + + # Numpy arrays have special typings. Convert to list using standard Python types + # Numpy arrays do not allow mixed types, only have to check one entry + # Empty arrays do not need this step + if isinstance(input_val, np.ndarray) and len(input_val) > 0: + input_val = input_val.tolist() + while isiterable(input_val): + input_val = input_val[0] + + # if val is not iterable, make it a list (checks assume val is iterable) + if not isiterable(input_val): + input_val = [input_val] + # if val is an iterable, flatten it so we can easily loop over every entry + else: + input_val = _flatten_iters(input_val) + + for item in input_val: + has_bool = False # needs some fancy shenanigans because bools will register as ints + if isinstance(expected_types, type): + if expected_types is bool: + has_bool = True + elif bool in expected_types: + has_bool = True + if (not isinstance(item, expected_types)) or ( + (has_bool is False) and (isinstance(item, bool)) + ): + raise TypeError( + f'{key} is of type(s) {meta_data[key]["types"]} but you ' + f'have provided a value of type {type(item)}.' + ) + + +def cast_type(key, val, meta_data=_MetaData): + """ + Attempts to cast val into an accepted type in meta_data. If a valid type cast is found, val is + changed to that type. If no compatible type is found, val is returned as is. Typing preference + given by order of types defined in meta_data. + """ + if key not in meta_data: + return val + + cast_val = deepcopy(val) + + expected_types = meta_data[key]['types'] + if not isinstance(expected_types, tuple): + expected_types = (expected_types,) + + # If provided val is not in expected types, see if it can be casted to one of + # them (e.g. cast int to float). + if not isinstance(cast_val, expected_types): + # Prefer casting to Enum if possible + # Special handling to access an Enum member from either the member name or its value. + is_enum = False + for _type in expected_types: + if issubclass(_type, Enum): + is_enum = True + break + if is_enum: + cast_val = enum_setter(meta_data[key], cast_val) + else: + for _type in expected_types: + try: + if isiterable(cast_val): + if isinstance(cast_val, np.ndarray): + cast_val = np.array([_type(item) for item in cast_val]) + else: + cast_val = type(cast_val)([_type(item) for item in cast_val]) + # Don't cast things to bool, most types will convert + elif _type is not bool: + if _type is np.ndarray: + cast_val = np.array([cast_val]) + else: + cast_val = _type(cast_val) + except (ValueError, TypeError): + # try another value in expected_types + pass + else: + break + + return cast_val diff --git a/aviary/validation_cases/benchmark_tests/test_0_iters.py b/aviary/validation_cases/benchmark_tests/test_0_iters.py index 8cb13bea88..76a2fa218d 100644 --- a/aviary/validation_cases/benchmark_tests/test_0_iters.py +++ b/aviary/validation_cases/benchmark_tests/test_0_iters.py @@ -1,63 +1,55 @@ -from copy import deepcopy import unittest +from copy import deepcopy from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info -from aviary.interface.default_phase_info.height_energy import phase_info as height_energy_phase_info from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.models.N3CC.N3CC_data import inputs +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import inputs +from aviary.models.missions.height_energy_default import phase_info as height_energy_phase_info +from aviary.models.missions.two_dof_default import phase_info as two_dof_phase_info class BaseProblemPhaseTestCase(unittest.TestCase): - """ - Test the setup and run of a simple energy method and 2DOF mission (no optimization, single iteration) - """ + """Test the setup and run of a simple energy method and 2DOF mission (no optimization, single iteration).""" def build_and_run_problem(self, input_filename, phase_info, objective_type=None): # Build problem - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs(input_filename, phase_info) prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() - prob.add_driver("SLSQP", max_iter=0, verbosity=0) + + prob.build_model() + prob.add_driver('SLSQP', max_iter=0, verbosity=0) prob.add_design_variables() prob.add_objective(objective_type if objective_type else None) prob.setup() - prob.set_initial_guesses() - prob.run_aviary_problem("dymos_solution.db", make_plots=False) + prob.run_aviary_problem(make_plots=False) @use_tempdirs class TwoDOFZeroItersTestCase(BaseProblemPhaseTestCase): - - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_zero_iters_2DOF(self): local_phase_info = deepcopy(two_dof_phase_info) - self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_GwGm.csv', - local_phase_info) + self.build_and_run_problem( + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', local_phase_info + ) @use_tempdirs class HEZeroItersTestCase(BaseProblemPhaseTestCase): - - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_zero_iters_height_energy(self): local_phase_info = deepcopy(height_energy_phase_info) local_inputs = deepcopy(inputs) local_phase_info['pre_mission']['include_takeoff'] = True local_phase_info['post_mission']['include_landing'] = True - local_phase_info['climb']['user_options']['fix_initial'] = False - local_phase_info['climb']['user_options']['input_initial'] = True self.build_and_run_problem(local_inputs, local_phase_info) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() # test = TwoDOFZeroItersTestCase() # test.test_zero_iters_2DOF() diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py index 92ae6fb521..4475f8adc6 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_balanced_field_length.py @@ -1,6 +1,5 @@ -""" -Balanced field length optimization implemented with the Level 3 API. -""" +"""Balanced field length optimization implemented with the Level 3 API.""" + import copy import unittest import warnings @@ -11,29 +10,30 @@ from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.models.N3CC.N3CC_data import \ - balanced_liftoff_user_options as _takeoff_liftoff_user_options -from aviary.models.N3CC.N3CC_data import \ - balanced_trajectory_builder as _takeoff_trajectory_builder -from aviary.models.N3CC.N3CC_data import inputs as _inputs +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + balanced_liftoff_user_options as _takeoff_liftoff_user_options, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + balanced_trajectory_builder as _takeoff_trajectory_builder, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + inputs as _inputs, +) from aviary.subsystems.premission import CorePreMission from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems -from aviary.utils.functions import \ - set_aviary_initial_values, set_aviary_input_defaults +from aviary.utils.functions import set_aviary_initial_values, set_aviary_input_defaults from aviary.utils.preprocessors import preprocess_options -from aviary.variable_info.variables import Dynamic, Aircraft +from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.variable_info.functions import setup_model_options +from aviary.variable_info.variables import Aircraft, Dynamic @use_tempdirs class TestFLOPSBalancedFieldLength(unittest.TestCase): - """ - Test balanced field computation using N3CC data in balanced_liftoff phase - """ + """Test balanced field computation using N3CC data in balanced_liftoff phase.""" @require_pyoptsparse(optimizer='IPOPT') def bench_test_IPOPT(self): - driver = om.pyOptSparseDriver() optimizer = 'IPOPT' @@ -62,8 +62,8 @@ def bench_test_SNOPT(self): def _do_run(self, driver: Driver, optimizer, *args): aviary_options = _inputs.deepcopy() - engine = build_engine_deck(aviary_options) - preprocess_options(aviary_options, engine_models=engine) + engines = [build_engine_deck(aviary_options)] + preprocess_options(aviary_options, engine_models=engines) takeoff_trajectory_builder = copy.deepcopy(_takeoff_trajectory_builder) takeoff_liftoff_user_options = _takeoff_liftoff_user_options.deepcopy() @@ -73,12 +73,11 @@ def _do_run(self, driver: Driver, optimizer, *args): driver.declare_coloring() - driver.add_recorder(om.SqliteRecorder( - f'FLOPS_detailed_takeoff_traj_{optimizer}.sql')) + driver.add_recorder(om.SqliteRecorder(f'FLOPS_detailed_takeoff_traj_{optimizer}.sql')) driver.recording_options['record_derivatives'] = False - default_mission_subsystems = get_default_mission_subsystems('FLOPS', engine) + default_mission_subsystems = get_default_mission_subsystems('FLOPS', engines) # Upstream static analysis for aero takeoff.model.add_subsystem( @@ -96,22 +95,23 @@ def _do_run(self, driver: Driver, optimizer, *args): takeoff.model.add_subsystem('traj', traj) takeoff_trajectory_builder.build_trajectory( - aviary_options=aviary_options, model=takeoff.model, traj=traj) + aviary_options=aviary_options, model=takeoff.model, traj=traj + ) distance_max, units = takeoff_liftoff_user_options.get_item('distance_max') liftoff = takeoff_trajectory_builder.get_phase('balanced_liftoff') - liftoff.add_objective( - Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units) + liftoff.add_objective(Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units) - varnames = [Aircraft.Wing.ASPECT_RATIO] + varnames = [Aircraft.Wing.ASPECT_RATIO, Aircraft.Engine.SCALE_FACTOR] set_aviary_input_defaults(takeoff.model, varnames, aviary_options) + setup_model_options(takeoff, aviary_options) + # suppress warnings: # "input variable '...' promoted using '*' was already promoted using 'aircraft:*' with warnings.catch_warnings(): - - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) takeoff.setup(check=True) set_aviary_initial_values(takeoff, aviary_options) @@ -122,7 +122,9 @@ def _do_run(self, driver: Driver, optimizer, *args): takeoff_trajectory_builder.apply_initial_guesses(takeoff, 'traj') # run the problem - dm.run_problem(takeoff, run_driver=True, simulate=True, make_plots=False) + takeoff.result = dm.run_problem(takeoff, run_driver=True, simulate=True, make_plots=False) + + self.assertTrue(takeoff.result.success) # takeoff.model.traj.phases.brake_release_to_decision_speed.list_inputs(print_arrays=True) # takeoff.model.list_outputs(print_arrays=True) @@ -130,29 +132,25 @@ def _do_run(self, driver: Driver, optimizer, *args): # Field Length # N3CC FLOPS output Line 2282 desired = 7032.65 - actual = takeoff.model.get_val( - 'traj.balanced_liftoff.states:distance', units='ft')[-1] + actual = takeoff.model.get_val('traj.balanced_liftoff.states:distance', units='ft')[-1] assert_near_equal(actual, desired, 2e-2) # Decision Time # N3CC FLOPS output Line 2287 desired = 29.52 - actual = takeoff.model.get_val( - 'traj.balanced_brake_release.t', units='s')[-1] + actual = takeoff.model.get_val('traj.balanced_brake_release.t', units='s')[-1] assert_near_equal(actual, desired, 2e-2) # Liftoff Time # N3CC FLOPS output Line 2289 desired = 36.63 - actual = takeoff.model.get_val( - 'traj.balanced_rotate.t', units='s')[-1] - assert_near_equal(actual, desired, .05) + actual = takeoff.model.get_val('traj.balanced_rotate.t', units='s')[-1] + assert_near_equal(actual, desired, 0.05) # Rotation Speed # N3CC FLOPS output Line 2289 desired = 156.55 - actual = takeoff.model.get_val( - 'traj.balanced_rotate.states:velocity', units='kn')[-1] + actual = takeoff.model.get_val('traj.balanced_rotate.states:velocity', units='kn')[-1] assert_near_equal(actual, desired, 2e-2) diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py index f7007f33ec..5cde88667c 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_based_sizing_N3CC.py @@ -6,649 +6,428 @@ Computed Aero N3CC data """ + +from copy import deepcopy import unittest import numpy as np -import scipy.constants as _units -import dymos as dm import openmdao.api as om -from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import use_tempdirs from openmdao.utils.testing_utils import require_pyoptsparse -from aviary.mission.energy_phase import EnergyPhase -from aviary.mission.flops_based.phases.build_landing import Landing -from aviary.mission.flops_based.phases.build_takeoff import Takeoff -from aviary.subsystems.premission import CorePreMission -from aviary.subsystems.propulsion.propulsion_builder import CorePropulsionBuilder -from aviary.subsystems.geometry.geometry_builder import CoreGeometryBuilder -from aviary.subsystems.mass.mass_builder import CoreMassBuilder -from aviary.subsystems.aerodynamics.aerodynamics_builder import CoreAerodynamicsBuilder -from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.aviary_values import AviaryValues -from aviary.utils.functions import set_aviary_input_defaults -from aviary.utils.functions import set_aviary_initial_values -from aviary.utils.preprocessors import preprocess_crewpayload +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.models.aircraft.advanced_single_aisle.phase_info import phase_info from aviary.utils.test_utils.assert_utils import warn_timeseries_near_equal -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems -from aviary.validation_cases.validation_tests import get_flops_inputs -from aviary.variable_info.enums import LegacyCode -from aviary.variable_info.functions import setup_trajectory_params -from aviary.variable_info.variables import Aircraft, Dynamic, Mission -from aviary.variable_info.variable_meta_data import _MetaData as BaseMetaData - - -try: - import pyoptsparse -except ImportError: - pyoptsparse = None - +from aviary.validation_cases.benchmark_utils import compare_against_expected_values +from aviary.variable_info.variables import Mission -from dymos.transcriptions.transcription_base import TranscriptionBase -if hasattr(TranscriptionBase, 'setup_polynomial_controls'): - use_new_dymos_syntax = False -else: - use_new_dymos_syntax = True - -FLOPS = LegacyCode.FLOPS # benchmark for simple sizing problem on the N3CC - - def run_trajectory(sim=True): - prob = om.Problem(model=om.Group()) - if pyoptsparse: - driver = prob.driver = om.pyOptSparseDriver() - driver.options["optimizer"] = "SNOPT" - # driver.declare_coloring() # currently disabled pending resolve of issue 2507 - if driver.options["optimizer"] == "SNOPT": - driver.opt_settings["Major iterations limit"] = 45 - driver.opt_settings["Major optimality tolerance"] = 1e-4 - driver.opt_settings["Major feasibility tolerance"] = 1e-6 - driver.opt_settings["iSumm"] = 6 - elif driver.options["optimizer"] == "IPOPT": - driver.opt_settings["max_iter"] = 100 - driver.opt_settings["tol"] = 1e-3 - driver.opt_settings['print_level'] = 4 - - else: - driver = prob.driver = om.ScipyOptimizeDriver() - opt_settings = prob.driver.opt_settings - - driver.options['optimizer'] = 'SLSQP' - opt_settings['maxiter'] = 100 - opt_settings['ftol'] = 5.0e-3 - opt_settings['eps'] = 1e-2 + prob = AviaryProblem() + local_phase_info = deepcopy(phase_info) + + prob.load_inputs( + 'models/aircraft/advanced_single_aisle/advanced_single_aisle_FLOPS.csv', + local_phase_info, + ) ########################################## # Aircraft Input Variables and Options # ########################################## - aviary_inputs = get_flops_inputs('N3CC') - - aviary_inputs.set_val(Mission.Landing.LIFT_COEFFICIENT_MAX, - 2.4, units="unitless") - aviary_inputs.set_val(Mission.Takeoff.LIFT_COEFFICIENT_MAX, - 2.0, units="unitless") - aviary_inputs.set_val( - Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, - val=.0175, units="unitless") - takeoff_fuel_burned = 577 # lbm TODO: where should this get connected from? takeoff_thrust_per_eng = 24555.5 # lbf TODO: where should this get connected from? takeoff_L_over_D = 17.35 # TODO: should this come from aero? - aviary_inputs.set_val(Mission.Takeoff.FUEL_SIMPLE, - takeoff_fuel_burned, units='lbm') - aviary_inputs.set_val(Mission.Takeoff.LIFT_OVER_DRAG, - takeoff_L_over_D, units="unitless") - aviary_inputs.set_val(Mission.Design.THRUST_TAKEOFF_PER_ENG, - takeoff_thrust_per_eng, units='lbf') - - alt_airport = 0 # ft - - alt_i_climb = 0*_units.foot # m - alt_f_climb = 35000.0*_units.foot # m - mass_i_climb = 131000*_units.lb # kg - mass_f_climb = 126000*_units.lb # kg - # initial mach set to lower value so it can intersect with takeoff end mach - # mach_i_climb = 0.3 - mach_i_climb = 0.2 - mach_f_climb = 0.79 - distance_i_climb = 0*_units.nautical_mile # m - distance_f_climb = 160.3*_units.nautical_mile # m - t_i_climb = 2 * _units.minute # sec - t_f_climb = 26.20*_units.minute # sec - t_duration_climb = t_f_climb - t_i_climb - - alt_i_cruise = 35000*_units.foot # m - alt_f_cruise = 35000*_units.foot # m - alt_min_cruise = 35000*_units.foot # m - alt_max_cruise = 35000*_units.foot # m - mass_i_cruise = 126000*_units.lb # kg - mass_f_cruise = 102000*_units.lb # kg - cruise_mach = 0.79 - distance_i_cruise = 160.3*_units.nautical_mile # m - distance_f_cruise = 3243.9*_units.nautical_mile # m - t_i_cruise = 26.20*_units.minute # sec - t_f_cruise = 432.38*_units.minute # sec - t_duration_cruise = t_f_cruise - t_i_cruise - - alt_i_descent = 35000*_units.foot - # final altitude set to 35 to ensure landing is feasible point - # alt_f_descent = 0*_units.foot - alt_f_descent = 35*_units.foot - mach_i_descent = 0.79 - mach_f_descent = 0.3 - mass_i_descent = 102000*_units.pound - mass_f_descent = 101000*_units.pound - distance_i_descent = 3243.9*_units.nautical_mile - distance_f_descent = 3378.7*_units.nautical_mile - t_i_descent = 432.38*_units.minute - t_f_descent = 461.62*_units.minute - t_duration_descent = t_f_descent - t_i_descent - - ########################## - # Design Variables # - ########################## - - # Nudge it a bit off the correct answer to verify that the optimize takes us there. - aviary_inputs.set_val(Mission.Design.GROSS_MASS, 135000.0, units='lbm') - - prob.model.add_design_var(Mission.Design.GROSS_MASS, units='lbm', - lower=100000.0, upper=200000.0, ref=135000) - prob.model.add_design_var(Mission.Summary.GROSS_MASS, units='lbm', - lower=100000.0, upper=200000.0, ref=135000) - - takeoff_options = Takeoff( - airport_altitude=alt_airport, # ft - # no units - num_engines=aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES) - ) - - ################## - # Define Phases # - ################## - num_segments_climb = 6 - num_segments_cruise = 1 - num_segments_descent = 5 - - climb_seg_ends, _ = dm.utils.lgl.lgl(num_segments_climb + 1) - descent_seg_ends, _ = dm.utils.lgl.lgl(num_segments_descent + 1) - - transcription_climb = dm.Radau( - num_segments=num_segments_climb, order=3, compressed=True, - segment_ends=climb_seg_ends) - transcription_cruise = dm.Radau( - num_segments=num_segments_cruise, order=3, compressed=True) - transcription_descent = dm.Radau( - num_segments=num_segments_descent, order=3, compressed=True, - segment_ends=descent_seg_ends) - - # default subsystems - engine = build_engine_deck(aviary_inputs) - default_mission_subsystems = get_default_mission_subsystems('FLOPS', engine) - - climb_options = EnergyPhase( - 'test_climb', - user_options=AviaryValues({ - 'initial_altitude': (alt_i_climb, 'm'), - 'final_altitude': (alt_f_climb, 'm'), - 'initial_mach': (mach_i_climb, 'unitless'), - 'final_mach': (mach_f_climb, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'input_initial': (True, 'unitless'), - 'use_polynomial_control': (False, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_climb, + prob.aviary_inputs.set_val(Mission.Takeoff.FUEL_SIMPLE, takeoff_fuel_burned, units='lbm') + prob.aviary_inputs.set_val(Mission.Takeoff.LIFT_OVER_DRAG, takeoff_L_over_D, units='unitless') + prob.aviary_inputs.set_val( + Mission.Design.THRUST_TAKEOFF_PER_ENG, takeoff_thrust_per_eng, units='lbf' ) - cruise_options = EnergyPhase( - 'test_cruise', - user_options=AviaryValues({ - 'initial_altitude': (alt_min_cruise, 'm'), - 'final_altitude': (alt_max_cruise, 'm'), - 'initial_mach': (cruise_mach, 'unitless'), - 'final_mach': (cruise_mach, 'unitless'), - 'required_available_climb_rate': (300, 'ft/min'), - 'fix_initial': (False, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_cruise, - ) - - descent_options = EnergyPhase( - 'test_descent', - user_options=AviaryValues({ - 'final_altitude': (alt_f_descent, 'm'), - 'initial_altitude': (alt_i_descent, 'm'), - 'initial_mach': (mach_i_descent, 'unitless'), - 'final_mach': (mach_f_descent, 'unitless'), - 'fix_initial': (False, 'unitless'), - 'use_polynomial_control': (False, 'unitless'), - }), - core_subsystems=default_mission_subsystems, - subsystem_options={'core_aerodynamics': {'method': 'computed'}}, - transcription=transcription_descent, - ) + prob.check_and_preprocess_inputs() - landing_options = Landing( - ref_wing_area=aviary_inputs.get_val(Aircraft.Wing.AREA, units='ft**2'), - Cl_max_ldg=aviary_inputs.get_val( - Mission.Landing.LIFT_COEFFICIENT_MAX) # no units - ) - - preprocess_crewpayload(aviary_inputs) - - prop = CorePropulsionBuilder('core_propulsion', BaseMetaData, engine) - mass = CoreMassBuilder('core_mass', BaseMetaData, FLOPS) - aero = CoreAerodynamicsBuilder('core_aerodynamics', BaseMetaData, FLOPS) - geom = CoreGeometryBuilder('core_geometry', - BaseMetaData, - code_origin=FLOPS) - - core_subsystems = [prop, geom, mass, aero] - - # Upstream static analysis for aero - prob.model.add_subsystem( - 'pre_mission', - CorePreMission(aviary_options=aviary_inputs, - subsystems=core_subsystems), - promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['aircraft:*', 'mission:*']) - - # directly connect phases (strong_couple = True), or use linkage constraints (weak - # coupling / strong_couple=False) - strong_couple = False - - takeoff = takeoff_options.build_phase(False) - - climb = climb_options.build_phase(aviary_options=aviary_inputs) - - cruise = cruise_options.build_phase(aviary_options=aviary_inputs) - - descent = descent_options.build_phase(aviary_options=aviary_inputs) - - landing = landing_options.build_phase(False) - - prob.model.add_subsystem( - 'takeoff', takeoff, promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['mission:*']) - - traj = prob.model.add_subsystem('traj', dm.Trajectory()) - - # if fix_initial is false, can we always set input_initial to be true for - # necessary states, and then ignore if we use a linkage? - climb.set_time_options(fix_initial=True, fix_duration=False, units='s', - duration_bounds=(t_duration_climb*0.5, t_duration_climb*2), - duration_ref=t_duration_climb) - cruise.set_time_options(fix_initial=False, fix_duration=False, units='s', - duration_bounds=(t_duration_cruise*0.5, t_duration_cruise*2), - duration_ref=t_duration_cruise, - initial_bounds=(t_duration_climb*0.5, t_duration_climb*2)) - descent.set_time_options( - fix_initial=False, fix_duration=False, units='s', - duration_bounds=(t_duration_descent*0.5, t_duration_descent*2), - duration_ref=t_duration_descent, - initial_bounds=( - (t_duration_cruise + t_duration_climb)*0.5, - (t_duration_cruise + t_duration_climb)*2)) - - traj.add_phase('climb', climb) - - traj.add_phase('cruise', cruise) - - traj.add_phase('descent', descent) - - prob.model.add_subsystem( - 'landing', landing, promotes_inputs=['aircraft:*', 'mission:*'], - promotes_outputs=['mission:*']) - - traj.link_phases(["climb", "cruise", "descent"], [ - "time", Dynamic.Mission.MASS, Dynamic.Mission.DISTANCE], connected=strong_couple) - - # Need to declare dymos parameters for every input that is promoted out of the missions. - externs = {'climb': {}, 'cruise': {}, 'descent': {}} - for default_subsys in default_mission_subsystems: - params = default_subsys.get_parameters(aviary_inputs=aviary_inputs, - phase_info={}) - for key, val in params.items(): - for phname in externs: - externs[phname][key] = val - - traj = setup_trajectory_params(prob.model, traj, aviary_inputs, - external_parameters=externs) - - ################################## - # Connect in Takeoff and Landing # - ################################## - prob.model.connect(Mission.Takeoff.FINAL_MASS, - 'traj.climb.initial_states:mass') - prob.model.connect(Mission.Takeoff.GROUND_DISTANCE, - 'traj.climb.initial_states:distance') - - prob.model.connect('traj.descent.states:mass', - Mission.Landing.TOUCHDOWN_MASS, src_indices=[-1]) - # TODO: approach velocity should likely be connected - prob.model.connect('traj.descent.control_values:altitude', Mission.Landing.INITIAL_ALTITUDE, - src_indices=[-1]) + prob.build_model() + prob.add_driver('SNOPT', max_iter=50, verbosity=1) ########################## - # Constraints # + # Design Variables # ########################## + prob.add_design_variables() - ecomp = om.ExecComp('fuel_burned = initial_mass - descent_mass_final', - initial_mass={'units': 'lbm', 'shape': 1}, - descent_mass_final={'units': 'lbm', 'shape': 1}, - fuel_burned={'units': 'lbm', 'shape': 1}) - - prob.model.add_subsystem('fuel_burn', ecomp, - promotes_inputs=[ - ('initial_mass', Mission.Design.GROSS_MASS)], - promotes_outputs=['fuel_burned']) - - prob.model.connect("traj.descent.states:mass", - "fuel_burn.descent_mass_final", src_indices=[-1]) - - # TODO: need to add some sort of check that this value is less than the fuel capacity - # TODO: need to update this with actual FLOPS value, this gives unrealistic - # appearance of accuracy - # TODO: the overall_fuel variable is the burned fuel plus the reserve, but should - # also include the unused fuel, and the hierarchy variable name should be more clear - ecomp = om.ExecComp('overall_fuel = fuel_burned + fuel_reserve', - fuel_burned={'units': 'lbm', 'shape': 1}, - fuel_reserve={'units': 'lbm', 'val': 2173.}, - overall_fuel={'units': 'lbm'}) - prob.model.add_subsystem('fuel_calc', ecomp, - promotes_inputs=['fuel_burned'], - promotes_outputs=['overall_fuel']) - - ecomp = om.ExecComp( - 'mass_resid = operating_empty_mass + overall_fuel + payload_mass ' - '- initial_mass', - operating_empty_mass={'units': 'lbm'}, - overall_fuel={'units': 'lbm'}, - payload_mass={'units': 'lbm'}, - initial_mass={'units': 'lbm'}, - mass_resid={'units': 'lbm'}) - - prob.model.add_subsystem( - 'mass_constraint', ecomp, - promotes_inputs=[ - ('operating_empty_mass', Aircraft.Design.OPERATING_MASS), - 'overall_fuel', - ('payload_mass', Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS), - ('initial_mass', Mission.Design.GROSS_MASS)], - promotes_outputs=['mass_resid']) - - prob.model.add_constraint('mass_resid', equals=0.0, ref=1.0) - - prob.model.add_subsystem( - 'gtow_constraint', - om.EQConstraintComp( - 'GTOW', - eq_units='lbm', - normalize=True, - add_constraint=True, - ), - promotes_inputs=[ - ('lhs:GTOW', Mission.Design.GROSS_MASS), - ('rhs:GTOW', Mission.Summary.GROSS_MASS), - ], - ) + # Nudge it a bit off the correct answer to verify that the optimize takes us there. + prob.aviary_inputs.set_val(Mission.Design.GROSS_MASS, 135000.0, units='lbm') ########################## # Add Objective Function # ########################## - - # This is an example of a overall mission objective - # create a compound objective that minimizes climb time and maximizes final mass - # we are maxing final mass b/c we don't have an independent value for fuel_mass yet - # we are going to normalize these (making each of the sub-objectives approx = 1 ) - # TODO: change the scaling on climb_duration - prob.model.add_subsystem( - "regularization", - om.ExecComp( - "reg_objective = fuel_mass/1500", - reg_objective=0.0, - fuel_mass={"units": "lbm", "shape": 1}, - ), - promotes_inputs=[('fuel_mass', Mission.Design.FUEL_MASS)], - promotes_outputs=['reg_objective'] - ) - - prob.model.add_objective('reg_objective', ref=1) - - varnames = [ - Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, - Aircraft.Wing.SWEEP, - Aircraft.Wing.TAPER_RATIO, - Aircraft.Wing.THICKNESS_TO_CHORD, - Mission.Design.GROSS_MASS, - Mission.Summary.GROSS_MASS, - ] - set_aviary_input_defaults(prob.model, varnames, aviary_inputs) - - prob.setup(force_alloc_complex=True) - - set_aviary_initial_values(prob, aviary_inputs) + prob.add_objective() ############################################ # Initial Settings for States and Controls # ############################################ - - prob.set_val('traj.climb.t_initial', t_i_climb, units='s') - prob.set_val('traj.climb.t_duration', t_duration_climb, units='s') - - prob.set_val('traj.climb.controls:altitude', climb.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_climb, alt_f_climb]), units='m') - prob.set_val( - 'traj.climb.controls:mach', climb.interp( - Dynamic.Mission.MACH, ys=[mach_i_climb, mach_f_climb]), units='unitless') - prob.set_val('traj.climb.states:mass', climb.interp( - Dynamic.Mission.MASS, ys=[mass_i_climb, mass_f_climb]), units='kg') - prob.set_val('traj.climb.states:distance', climb.interp( - Dynamic.Mission.DISTANCE, ys=[distance_i_climb, distance_f_climb]), units='m') - - prob.set_val('traj.cruise.t_initial', t_i_cruise, units='s') - prob.set_val('traj.cruise.t_duration', t_duration_cruise, units='s') - - if use_new_dymos_syntax: - controls_str = 'controls' - else: - controls_str = 'polynomial_controls' - - prob.set_val(f'traj.cruise.{controls_str}:altitude', cruise.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_cruise, alt_f_cruise]), units='m') - prob.set_val( - f'traj.cruise.{controls_str}:mach', cruise.interp( - Dynamic.Mission.MACH, ys=[cruise_mach, cruise_mach]), units='unitless') - prob.set_val('traj.cruise.states:mass', cruise.interp( - Dynamic.Mission.MASS, ys=[mass_i_cruise, mass_f_cruise]), units='kg') - prob.set_val('traj.cruise.states:distance', cruise.interp( - Dynamic.Mission.DISTANCE, ys=[distance_i_cruise, distance_f_cruise]), units='m') - - prob.set_val('traj.descent.t_initial', t_i_descent, units='s') - prob.set_val('traj.descent.t_duration', t_duration_descent, units='s') - - prob.set_val('traj.descent.controls:altitude', descent.interp( - Dynamic.Mission.ALTITUDE, ys=[alt_i_descent, alt_f_descent]), units='m') - prob.set_val( - 'traj.descent.controls:mach', descent.interp( - Dynamic.Mission.MACH, ys=[mach_i_descent, mach_f_descent]), units='unitless') - prob.set_val('traj.descent.states:mass', descent.interp( - Dynamic.Mission.MASS, ys=[mass_i_descent, mass_f_descent]), units='kg') - prob.set_val('traj.descent.states:distance', descent.interp( - Dynamic.Mission.DISTANCE, ys=[distance_i_descent, distance_f_descent]), units='m') - - # Turn off solver printing so that the SNOPT output is readable. - prob.set_solver_print(level=0) - - dm.run_problem(prob, simulate=sim, make_plots=False, simulate_kwargs={ - 'times_per_seg': 100, 'atol': 1e-9, 'rtol': 1e-9}, - solution_record_file='N3CC_sizing.db') - # prob.run_model() - # z=prob.check_totals(method='cs', step=2e-40, compact_print=False) - # exit() - prob.record("final") - prob.cleanup() + prob.setup() + prob.run_aviary_problem() return prob @use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): - """ - Test sizing using N3CC data. - """ + """Test sizing using N3CC data.""" - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def bench_test_sizing_N3CC(self): - prob = run_trajectory(sim=False) + # self.assertTrue(prob.result.success) + times_climb = prob.get_val('traj.climb.timeseries.time', units='s') - altitudes_climb = prob.get_val( - 'traj.climb.timeseries.altitude', units='m') - masses_climb = prob.get_val('traj.climb.timeseries.mass', units='kg') - distances_climb = prob.get_val('traj.climb.timeseries.distance', units='m') - velocities_climb = prob.get_val( - 'traj.climb.timeseries.velocity', units='m/s') thrusts_climb = prob.get_val('traj.climb.timeseries.thrust_net_total', units='N') times_cruise = prob.get_val('traj.cruise.timeseries.time', units='s') - altitudes_cruise = prob.get_val( - 'traj.cruise.timeseries.altitude', units='m') - masses_cruise = prob.get_val('traj.cruise.timeseries.mass', units='kg') - distances_cruise = prob.get_val('traj.cruise.timeseries.distance', units='m') - velocities_cruise = prob.get_val( - 'traj.cruise.timeseries.velocity', units='m/s') - thrusts_cruise = prob.get_val( - 'traj.cruise.timeseries.thrust_net_total', units='N') + thrusts_cruise = prob.get_val('traj.cruise.timeseries.thrust_net_total', units='N') times_descent = prob.get_val('traj.descent.timeseries.time', units='s') - altitudes_descent = prob.get_val( - 'traj.descent.timeseries.altitude', units='m') - masses_descent = prob.get_val('traj.descent.timeseries.mass', units='kg') - distances_descent = prob.get_val('traj.descent.timeseries.distance', units='m') - velocities_descent = prob.get_val( - 'traj.descent.timeseries.velocity', units='m/s') - thrusts_descent = prob.get_val( - 'traj.descent.timeseries.thrust_net_total', units='N') - - expected_times_s_climb = [[120.], [163.76325828], [224.14762249], [243.2590673], - [243.2590673], [336.41088085], [464.94137099], - [505.62083166], [505.62083166], [626.47618404], - [793.2319034], [846.00951843], [846.00951843], - [966.8648708], [1133.62059016], [1186.39820519], - [1186.39820519], [1279.55001873], [1408.08050887], - [1448.75996955], [1448.75996955], [1492.52322782], - [1552.90759204], [1572.01903685]] - expected_altitudes_m_climb = [[10.668], [0.], [835.43072799], [1237.19027083], - [1237.19027083], [3154.43458807], [5478.53141388], - [6035.03506592], [6035.03506592], [7369.93558792], - [8611.93242084], [8931.907682], [8931.907682], - [9555.56028912], [10196.52547754], [10341.80261401], - [10341.80261401], [10526.85288051], [10653.9273369], - [10668.], [10668.], [10668.], [10664.89939949], [10668.]] - expected_masses_kg_climb = [[58331.64520977], [58289.14326023], [58210.1552262], - [58183.99841695], [58183.99841695], [58064.21371439], - [57928.02594919], [57893.85802859], [57893.85802859], - [57803.5753272], [57701.17154376], [57671.70469428], - [57671.70469428], [57609.99954455], [57532.67046087], - [57509.28816794], [57509.28816794], [57468.36184014], - [57411.39726843], [57392.97463799], [57392.97463799], - [57372.80054331], [57344.30023996], [57335.11578186]] - expected_distances_m_climb = [[1459.66454213], [6138.11750563], [15269.84014039], - [18334.78691191], [18334.78691191], [34224.35398213], - [57056.15756331], [64259.82264908], [64259.82264908], - [85983.44219477], [116781.82372802], [ - 126787.42506431], - [126787.42506431], [149770.216723], [181655.376959], - [191785.63505195], [191785.63505195], [ - 210054.32022093], - [236459.08240245], [245218.76016711], [ - 245218.76016711], - [254896.51199279], [268679.73823007], [273140.04867091]] - expected_velocities_ms_climb = [[77.19291754], [132.35228283], [162.28279625], - [166.11250634], [166.11250634], [176.30796789], - [178.55049791], [178.67862048], [178.67862048], - [181.75616771], [188.37687907], [189.78671051], - [189.78671051], [190.67789763], [191.79702196], - [193.51306342], [193.51306342], [199.28763405], - [212.62699415], [218.00379223], [218.00379223], - [224.21350812], [232.18822869], [234.25795132]] - expected_thrusts_N_climb = [[82387.90445676], [105138.56964482], [113204.81413537], - [110631.69881503], [110631.69881503], [97595.73505557], - [74672.35033284], [68787.54639919], [68787.54639919], - [56537.02658008], [46486.74146611], [43988.99250831], - [43988.99250831], [39814.93772493], [36454.43040965], - [35877.85248136], [35877.85248136], [35222.20684522], - [34829.78305946], [34857.84665827], [34857.84665827], - [34988.40432301], [35243.28462529], [35286.14075168]] - - expected_times_s_cruise = [[1572.01903685], [10224.85688577], - [22164.00704809], [25942.70725365]] - expected_altitudes_m_cruise = [[10668.], [10668.], - [10668.], [10668.]] - expected_masses_kg_cruise = [[57335.11578186], [53895.3524649], - [49306.34176818], [47887.72131688]] - expected_distances_m_cruise = [[273140.04867091], [2300136.11626779], - [5096976.9738027], [5982167.54261146]] - expected_velocities_ms_cruise = [[234.25795132], [234.25795132], - [234.25795132], [234.25795132]] - expected_thrusts_N_cruise = [[28998.46944214], [28027.44677784], - [26853.54343662], [26522.10071819]] - - expected_times_s_descent = [[25942.70725365], [26017.49838255], [26120.69487534], - [26153.35621248], [26153.35621248], [26306.10095576], - [26516.85752584], [26583.56125968], [26583.56125968], - [26765.15964678], [27015.72835621], [27095.03249603], - [27095.03249603], [27247.77723931], [27458.5338094], - [27525.23754324], [27525.23754324], [27600.02867214], - [27703.22516493], [27735.88650207]] - expected_altitudes_m_descent = [[10668.], [10668.], [10065.85989164], - [9813.33438203], [9813.33438203], [8725.84180063], - [7399.4358998], [6995.36734403], [6995.36734403], - [5880.98032937], [4300.0193441], [3787.54388607], - [3787.54388607], [2768.24427675], [1328.48487414], - [872.88952055], [872.88952055], [393.61709386], - [10.668], [10.668]] - expected_masses_kg_descent = [[47887.72131688], [47887.72131688], [47887.72131688], - [47887.72131688], [47887.72131688], [47887.72131688], - [47887.72131688], [47887.72131688], [47887.72131688], - [47887.87994829], [47886.14050369], [47884.40804261], - [47884.40804261], [47872.68009732], [47849.34258173], - [47842.09391697], [47842.09391697], [47833.150133], - [47820.60083267], [47816.69389115]] - expected_distances_m_descent = [[5982167.54261146], [5998182.9986382], [6017437.15474761], - [6023441.80485498], [6023441.80485498], [ - 6050450.80904601], - [6085202.09693457], [6095472.55993089], [ - 6095472.55993089], - [6122427.64793619], [6158176.53029461], [ - 6169433.26612421], - [6169433.26612421], [6191073.79296936], [ - 6220839.65410345], - [6230195.89769052], [6230195.89769052], [ - 6240573.15704622], - [6253740.15118502], [6257352.4]] - expected_velocities_ms_descent = [[234.25795132], [197.64415171], [182.5029101], - [181.15994177], [181.15994177], [172.42254637], - [156.92424445], [152.68023428], [152.68023428], - [145.15327267], [141.83129659], [141.72294853], - [141.72294853], [141.82174008], [140.7384589], - [139.65952688], [139.65952688], [136.46721905], - [115.68627038], [102.07377559]] - expected_thrusts_N_descent = [[0.], [8.11038373e-13], [4.89024663e-13], - [-3.80747087e-14], [0.], [1.10831527e-12], - [7.77983996e-13], [-6.64041439e-16], [0.], - [0.], [-5.7108371e-14], [-8.28280737e-14], - [0.], [1.14382967e-13], [5.36023712e-14], - [-3.04972888e-14], [0.], [-1.0682523e-13], - [-6.30544276e-14], [5.37050667e-15]] + thrusts_descent = prob.get_val('traj.descent.timeseries.thrust_net_total', units='N') + + expected_times_s_climb = [ + [0.0], + [84.0863228], + [200.10828601], + [236.82884068], + [236.82884068], + [415.80988031], + [662.76718444], + [740.92832684], + [740.92832684], + [973.13869172], + [1293.54160046], + [1394.94802559], + [1394.94802559], + [1627.15839048], + [1947.56129921], + [2048.96772435], + [2048.96772435], + [2227.94876397], + [2474.90606811], + [2553.06721051], + [2553.06721051], + [2637.15353331], + [2753.17549652], + [2789.89605118], + ] + + expected_altitudes_m_climb = [ + [10.668], + [1113.15892907], + [2505.31910212], + [2915.84612589], + [2915.84612589], + [4720.22329407], + [6714.19059843], + [7236.03048999], + [7236.03048999], + [8509.49393709], + [9678.02373053], + [9928.61760729], + [9928.61760729], + [10328.05698328], + [10575.61727564], + [10603.57950367], + [10603.57950367], + [10618.54858105], + [10612.64011873], + [10614.86229636], + [10614.86229636], + [10624.02992826], + [10653.51252987], + [10668.0], + ] + + expected_masses_kg_climb = [ + [57336.24193681], + [57232.33711103], + [57115.85206902], + [57081.31733056], + [57081.31733056], + [56932.11443592], + [56757.7116076], + [56706.5613175], + [56706.5613175], + [56570.14762048], + [56411.45004403], + [56367.35681493], + [56367.35681493], + [56274.55398409], + [56159.15000551], + [56124.14860773], + [56124.14860773], + [56062.52701216], + [55974.27102613], + [55944.69095805], + [55944.69095805], + [55911.32442321], + [55861.55377337], + [55844.61091641], + ] + + expected_distances_m_climb = [ + [1421.8855236], + [8910.25297478], + [22162.18513561], + [26969.15379381], + [26969.15379381], + [53889.88674169], + [98274.91723261], + [113493.56841], + [113493.56841], + [160867.47482179], + [228949.21419049], + [250580.7400101], + [250580.7400101], + [299935.51831796], + [367183.26127212], + [388239.83394021], + [388239.83394021], + [425476.85128199], + [477670.19333243], + [494581.98686398], + [494581.98686398], + [513127.92793595], + [539457.59288457], + [548004.08377766], + ] + + expected_velocities_ms_climb = [ + [78.49573492], + [101.1016394], + [127.69880867], + [135.09899815], + [135.09899815], + [164.98084757], + [192.10475793], + [197.92873153], + [197.92873153], + [209.1463892], + [213.79712949], + [213.57324106], + [213.57324106], + [211.48593005], + [208.20820027], + [207.83218491], + [207.83218491], + [208.75754552], + [214.86690966], + [218.31439428], + [218.31439428], + [222.98550489], + [231.23769674], + [234.32014809], + ] + + expected_thrusts_N_climb = [ + [152151.45391014], + [113069.49989588], + [88010.04683775], + [82790.00338831], + [82790.00338831], + [66061.94148375], + [52924.90549389], + [49776.7994342], + [49776.7994342], + [41959.36848989], + [33969.13957345], + [32030.53104675], + [32030.53104675], + [28700.73489851], + [26384.34223423], + [26167.73184602], + [26167.73184602], + [26350.18803002], + [28010.57199427], + [28976.37867947], + [28976.37867947], + [30354.62140874], + [33256.05489502], + [34561.27738221], + ] + + expected_times_s_cruise = [ + [2789.89605118], + [10842.31125131], + [21953.00070629], + [25469.49593054], + ] + + expected_altitudes_m_cruise = [[10668.0], [10668.0], [10668.0], [10668.0]] + + expected_masses_kg_cruise = [ + [55844.61091641], + [52677.35420548], + [48437.42986223], + [47123.79311112], + ] + + expected_distances_m_cruise = [ + [548004.08377766], + [2434847.2059566], + [5038305.60443551], + [5862291.28614165], + ] + + expected_velocities_ms_cruise = [ + [234.32014809], + [234.32014809], + [234.32014809], + [234.32014809], + ] + + expected_thrusts_N_cruise = [ + [28597.93714764], + [27735.30112377], + [26683.82813953], + [26382.05441973], + ] + + expected_times_s_descent = [ + [25469.49593054], + [25575.61865901], + [25722.04636435], + [25768.39023245], + [25768.39023245], + [25985.12300752], + [26284.17000134], + [26378.81735242], + [26378.81735242], + [26636.49117829], + [26992.02846603], + [27104.55480199], + [27104.55480199], + [27321.28757707], + [27620.33457088], + [27714.98192196], + [27714.98192196], + [27821.10465044], + [27967.53235578], + [28013.87622387], + ] + + expected_altitudes_m_descent = [ + [10668.0], + [10629.3077369], + [10455.72330144], + [10373.70672575], + [10373.70672575], + [9834.46607022], + [8732.91197866], + [8314.59862184], + [8314.59862184], + [7049.40049088], + [5113.49927701], + [4482.90035867], + [4482.90035867], + [3279.9486113], + [1716.36236716], + [1261.43596673], + [1261.43596673], + [782.00748378], + [183.12312185], + [10.668], + ] + + expected_masses_kg_descent = [ + [47123.79311112], + [47094.35643767], + [47060.51112858], + [47050.73917493], + [47050.73917493], + [47010.63763596], + [46969.04641852], + [46959.35666069], + [46959.35666069], + [46941.2980746], + [46930.45302474], + [46929.08312096], + [46929.08312096], + [46917.94567025], + [46888.12549136], + [46878.62822765], + [46878.62822765], + [46866.76117329], + [46849.23898947], + [46843.36760307], + ] + + expected_distances_m_descent = [ + [5862291.28614165], + [5886497.96834813], + [5917909.4237556], + [5927421.58774285], + [5927421.58774285], + [5969540.61482824], + [6022389.68649162], + [6038131.37179067], + [6038131.37179067], + [6079037.43017674], + [6131650.9798226], + [6147551.15911222], + [6147551.15911222], + [6177096.10219989], + [6215315.97220355], + [6226712.31501162], + [6226712.31501162], + [6238990.09745233], + [6254964.28421588], + [6259760.0], + ] + + expected_velocities_ms_descent = [ + [234.32014809], + [222.16608332], + [207.49206629], + [203.30917468], + [203.30917468], + [186.33195622], + [168.69090335], + [164.21097701], + [164.21097701], + [153.98766763], + [142.81314196], + [139.53610066], + [139.53610066], + [132.99120577], + [122.26790663], + [118.18171604], + [118.18171604], + [113.0709453], + [104.9404634], + [102.07377561], + ] + + expected_thrusts_N_descent = [ + [20679.14374965], + [17150.55708079], + [14208.68058208], + [13389.53407776], + [13389.53407776], + [10253.30474317], + [6665.21263404], + [5654.24120595], + [5654.24120595], + [3286.30925166], + [1039.89484864], + [604.78704925], + [604.78704925], + [152.80643718], + [47.30677203], + [126.66634835], + [126.66634835], + [357.59318988], + [1023.64759606], + [1324.08820659], + ] + expected_times_s_climb = np.array(expected_times_s_climb) expected_altitudes_m_climb = np.array(expected_altitudes_m_climb) expected_masses_kg_climb = np.array(expected_masses_kg_climb) @@ -670,23 +449,33 @@ def bench_test_sizing_N3CC(self): expected_velocities_ms_descent = np.array(expected_velocities_ms_descent) expected_thrusts_N_descent = np.array(expected_thrusts_N_descent) + expected_dict = {} + expected_dict['times'] = np.concatenate( + (expected_times_s_climb, expected_times_s_cruise, expected_times_s_descent) + ) + expected_dict['altitudes'] = np.concatenate( + (expected_altitudes_m_climb, expected_altitudes_m_cruise, expected_altitudes_m_descent) + ) + expected_dict['masses'] = np.concatenate( + (expected_masses_kg_climb, expected_masses_kg_cruise, expected_masses_kg_descent) + ) + expected_dict['ranges'] = np.concatenate( + (expected_distances_m_climb, expected_distances_m_cruise, expected_distances_m_descent) + ) + expected_dict['velocities'] = np.concatenate( + ( + expected_velocities_ms_climb, + expected_velocities_ms_cruise, + expected_velocities_ms_descent, + ) + ) + self.expected_dict = expected_dict + # Check Objective and other key variables to a reasonably tight tolerance. # TODO: update truth values once everyone is using latest Dymos rtol = 5e-2 - # Mass at the end of Descent - assert_near_equal(masses_descent[-1], - expected_masses_kg_descent[-1], tolerance=rtol) - - # Range at the end of Descent - assert_near_equal(distances_descent[-1], - expected_distances_m_descent[-1], tolerance=rtol) - - # Flight time - assert_near_equal(times_descent[-1], - expected_times_s_descent[-1], tolerance=rtol) - # Check mission values. # NOTE rtol = 0.05 = 5% different from truth (first timeseries) @@ -694,62 +483,41 @@ def bench_test_sizing_N3CC(self): # atol_altitude - 30 ft. There is occasional time-shifting with the N3CC # model during climb and descent so we need a looser # absolute tolerance for the points near the ground. - rtol = .05 + rtol = 0.05 atol = 2.0 - atol_altitude = 30.0 # FLIGHT PATH # CLIMB warn_timeseries_near_equal( - times_climb, altitudes_climb, expected_times_s_climb, - expected_altitudes_m_climb, abs_tolerance=atol_altitude, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, masses_climb, expected_times_s_climb, - expected_masses_kg_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, distances_climb, expected_times_s_climb, - expected_distances_m_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, velocities_climb, expected_times_s_climb, - expected_velocities_ms_climb, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_climb, thrusts_climb, expected_times_s_climb, - expected_thrusts_N_climb, abs_tolerance=atol, rel_tolerance=rtol) + times_climb, + thrusts_climb, + expected_times_s_climb, + expected_thrusts_N_climb, + abs_tolerance=atol, + rel_tolerance=rtol, + ) # CRUISE warn_timeseries_near_equal( - times_cruise, altitudes_cruise, expected_times_s_cruise, - expected_altitudes_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, masses_cruise, expected_times_s_cruise, - expected_masses_kg_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, distances_cruise, expected_times_s_cruise, - expected_distances_m_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, velocities_cruise, expected_times_s_cruise, - expected_velocities_ms_cruise, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_cruise, thrusts_cruise, expected_times_s_cruise, - expected_thrusts_N_cruise, abs_tolerance=atol, rel_tolerance=rtol) + times_cruise, + thrusts_cruise, + expected_times_s_cruise, + expected_thrusts_N_cruise, + abs_tolerance=atol, + rel_tolerance=rtol, + ) # DESCENT warn_timeseries_near_equal( - times_descent, altitudes_descent, expected_times_s_descent, - expected_altitudes_m_descent, abs_tolerance=atol_altitude, - rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, masses_descent, expected_times_s_descent, - expected_masses_kg_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, distances_descent, expected_times_s_descent, - expected_distances_m_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, velocities_descent, expected_times_s_descent, - expected_velocities_ms_descent, abs_tolerance=atol, rel_tolerance=rtol) - warn_timeseries_near_equal( - times_descent, thrusts_descent, expected_times_s_descent, - expected_thrusts_N_descent, abs_tolerance=atol, rel_tolerance=rtol) + times_descent, + thrusts_descent, + expected_times_s_descent, + expected_thrusts_N_descent, + abs_tolerance=atol, + rel_tolerance=rtol, + ) + + compare_against_expected_values(prob, self.expected_dict) if __name__ == '__main__': diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py index 950506bcf9..bdb1b511e9 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_landing.py @@ -8,39 +8,41 @@ from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.models.N3CC.N3CC_data import ( +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( inputs as _inputs, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + landing_fullstop_user_options as _landing_fullstop_user_options, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( landing_trajectory_builder as _landing_trajectory_builder, - landing_fullstop_user_options as _landing_fullstop_user_options) - +) from aviary.subsystems.premission import CorePreMission from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.functions import \ - set_aviary_initial_values, set_aviary_input_defaults +from aviary.utils.functions import set_aviary_initial_values, set_aviary_input_defaults from aviary.utils.preprocessors import preprocess_options from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic @use_tempdirs class TestFLOPSDetailedLanding(unittest.TestCase): - """ - Test detailed landing using N3CC data - """ + """Test detailed landing using N3CC data.""" - # @require_pyoptsparse(optimizer='IPOPT') - # def bench_test_IPOPT(self): - # driver = om.pyOptSparseDriver() + @require_pyoptsparse(optimizer='IPOPT') + def bench_test_IPOPT(self): + driver = om.pyOptSparseDriver() - # optimizer = 'IPOPT' - # driver.options['optimizer'] = optimizer + optimizer = 'IPOPT' + driver.options['optimizer'] = optimizer - # driver.opt_settings['max_iter'] = 100 - # driver.opt_settings['tol'] = 1.0E-6 - # driver.opt_settings['print_level'] = 4 - # driver.opt_settings['mu_init'] = 1e-5 + driver.opt_settings['max_iter'] = 100 + driver.opt_settings['tol'] = 1.0e-6 + driver.opt_settings['print_level'] = 4 + driver.opt_settings['mu_init'] = 1e-5 - # self._do_run(driver, optimizer) + self._do_run(driver, optimizer) @require_pyoptsparse(optimizer='SNOPT') def bench_test_SNOPT(self): @@ -65,22 +67,19 @@ def _do_run(self, driver: Driver, optimizer, *args): landing = om.Problem() landing.driver = driver - driver.add_recorder(om.SqliteRecorder( - f'FLOPS_detailed_landing_traj_{optimizer}.sql')) + driver.add_recorder(om.SqliteRecorder(f'FLOPS_detailed_landing_traj_{optimizer}.sql')) driver.recording_options['record_derivatives'] = False - engine = build_engine_deck(aviary_options) - preprocess_options(aviary_options, engine_models=engine) + engines = [build_engine_deck(aviary_options)] + preprocess_options(aviary_options, engine_models=engines) - default_premission_subsystems = get_default_mission_subsystems('FLOPS', engine) + default_premission_subsystems = get_default_mission_subsystems('FLOPS', engines) # Upstream static analysis for aero landing.model.add_subsystem( 'pre_mission', - CorePreMission( - aviary_options=aviary_options, subsystems=default_premission_subsystems - ), + CorePreMission(aviary_options=aviary_options, subsystems=default_premission_subsystems), promotes_inputs=['aircraft:*'], promotes_outputs=['aircraft:*', 'mission:*'], ) @@ -90,22 +89,23 @@ def _do_run(self, driver: Driver, optimizer, *args): landing.model.add_subsystem('traj', traj) landing_trajectory_builder.build_trajectory( - aviary_options=aviary_options, model=landing.model, traj=traj) + aviary_options=aviary_options, model=landing.model, traj=traj + ) distance_max, units = landing_fullstop_user_options.get_item('distance_max') fullstop = landing_trajectory_builder.get_phase('landing_fullstop') - fullstop.add_objective(Dynamic.Mission.DISTANCE, loc='final', - ref=distance_max, units=units) + fullstop.add_objective(Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units) varnames = [Aircraft.Wing.ASPECT_RATIO] set_aviary_input_defaults(landing.model, varnames, aviary_options) + setup_model_options(landing, aviary_options) + # suppress warnings: # "input variable '...' promoted using '*' was already promoted using 'aircraft:*' with warnings.catch_warnings(): - - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) landing.setup(check=True) set_aviary_initial_values(landing, aviary_options) @@ -116,27 +116,27 @@ def _do_run(self, driver: Driver, optimizer, *args): landing_trajectory_builder.apply_initial_guesses(landing, 'traj') # run the problem - dm.run_problem(landing, run_driver=True, simulate=True, make_plots=False) + landing.result = dm.run_problem(landing, run_driver=True, simulate=True, make_plots=False) + + # self.assertTrue(landing.result.success) # Field length # N3CC FLOPS output line 1773 - base = -954.08 # ft + # base = -954.08 # ft # N3CC FLOPS output line 1842 desired = 3409.47 # ft - actual = landing.model.get_val( - 'traj.landing_fullstop.states:distance', units='ft')[-1] + actual = landing.model.get_val('traj.landing_fullstop.states:distance', units='ft')[-1] assert_near_equal(actual, desired, 0.05) # TOUCHDOWN time # N3CC FLOPS output line 1773 - base = -4.08 # s + # base = -4.08 # s # N3CC FLOPS output line 1849 desired = 4.22 # s - actual = landing.model.get_val( - 'traj.landing_flare.t', units='s')[-1] + actual = landing.model.get_val('traj.landing_flare.t', units='s')[-1] assert_near_equal(actual, desired, 0.10) @@ -144,14 +144,13 @@ def _do_run(self, driver: Driver, optimizer, *args): # N3CC FLOPS output line 1852 desired = 24.49 # s - actual = landing.model.get_val( - 'traj.landing_fullstop.t', units='s')[-1] + actual = landing.model.get_val('traj.landing_fullstop.t', units='s')[-1] assert_near_equal(actual, desired, 0.05) if __name__ == '__main__': - use_SNOPT = True + use_SNOPT = False z = TestFLOPSDetailedLanding() diff --git a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py index 49dd1ee698..d4bdb72166 100644 --- a/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py +++ b/aviary/validation_cases/benchmark_tests/test_FLOPS_detailed_takeoff.py @@ -8,25 +8,27 @@ from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.models.N3CC.N3CC_data import ( +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( inputs as _inputs, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( + takeoff_liftoff_user_options as _takeoff_liftoff_user_options, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import ( takeoff_trajectory_builder as _takeoff_trajectory_builder, - takeoff_liftoff_user_options as _takeoff_liftoff_user_options) - +) from aviary.subsystems.premission import CorePreMission from aviary.subsystems.propulsion.utils import build_engine_deck -from aviary.utils.functions import \ - set_aviary_initial_values, set_aviary_input_defaults -from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.utils.functions import set_aviary_initial_values, set_aviary_input_defaults from aviary.utils.preprocessors import preprocess_options +from aviary.utils.test_utils.default_subsystems import get_default_mission_subsystems +from aviary.variable_info.functions import setup_model_options from aviary.variable_info.variables import Aircraft, Dynamic @use_tempdirs class TestFLOPSDetailedTakeoff(unittest.TestCase): - """ - Test detailed takeoff using N3CC data - """ + """Test detailed takeoff using N3CC data.""" @require_pyoptsparse(optimizer='IPOPT') def bench_test_IPOPT(self): @@ -71,22 +73,19 @@ def _do_run(self, driver: Driver, optimizer, *args): driver.declare_coloring() - driver.add_recorder(om.SqliteRecorder( - f'FLOPS_detailed_takeoff_traj_{optimizer}.sql')) + driver.add_recorder(om.SqliteRecorder(f'FLOPS_detailed_takeoff_traj_{optimizer}.sql')) driver.recording_options['record_derivatives'] = False - engine = build_engine_deck(aviary_options) - preprocess_options(aviary_options, engine_models=engine) + engines = [build_engine_deck(aviary_options)] + preprocess_options(aviary_options, engine_models=engines) - default_premission_subsystems = get_default_mission_subsystems('FLOPS', engine) + default_premission_subsystems = get_default_mission_subsystems('FLOPS', engines) # Upstream static analysis for aero takeoff.model.add_subsystem( 'pre_mission', - CorePreMission( - aviary_options=aviary_options, subsystems=default_premission_subsystems - ), + CorePreMission(aviary_options=aviary_options, subsystems=default_premission_subsystems), promotes_inputs=['aircraft:*'], promotes_outputs=['aircraft:*', 'mission:*'], ) @@ -96,31 +95,40 @@ def _do_run(self, driver: Driver, optimizer, *args): takeoff.model.add_subsystem('traj', traj) takeoff_trajectory_builder.build_trajectory( - aviary_options=aviary_options, model=takeoff.model, traj=traj) + aviary_options=aviary_options, model=takeoff.model, traj=traj + ) distance_max, units = takeoff_liftoff_user_options.get_item('distance_max') liftoff = takeoff_trajectory_builder.get_phase('takeoff_liftoff') - liftoff.add_objective( - Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units) + liftoff.add_objective(Dynamic.Mission.DISTANCE, loc='final', ref=distance_max, units=units) # Insert a constraint for a fake decision speed, until abort is added. takeoff.model.add_constraint( 'traj.takeoff_brake_release.states:velocity', - equals=149.47, units='kn', ref=150.0, indices=[-1]) + equals=149.47, + units='kn', + ref=150.0, + indices=[-1], + ) takeoff.model.add_constraint( 'traj.takeoff_decision_speed.states:velocity', - equals=155.36, units='kn', ref=159.0, indices=[-1]) + equals=155.36, + units='kn', + ref=159.0, + indices=[-1], + ) - varnames = [Aircraft.Wing.ASPECT_RATIO] + varnames = [Aircraft.Wing.ASPECT_RATIO, Aircraft.Engine.SCALE_FACTOR] set_aviary_input_defaults(takeoff.model, varnames, aviary_options) + setup_model_options(takeoff, aviary_options) + # suppress warnings: # "input variable '...' promoted using '*' was already promoted using 'aircraft:*' with warnings.catch_warnings(): - - warnings.simplefilter("ignore", om.PromotionWarning) + warnings.simplefilter('ignore', om.PromotionWarning) takeoff.setup(check=True) set_aviary_initial_values(takeoff, aviary_options) @@ -131,7 +139,9 @@ def _do_run(self, driver: Driver, optimizer, *args): takeoff_trajectory_builder.apply_initial_guesses(takeoff, 'traj') # run the problem - dm.run_problem(takeoff, run_driver=True, simulate=True, make_plots=False) + takeoff.result = dm.run_problem(takeoff, run_driver=True, simulate=True, make_plots=False) + + self.assertTrue(takeoff.result.success) # liftoff.rhs_all.list_inputs(print_arrays=True) # takeoff.model.list_outputs(print_arrays=True) @@ -140,8 +150,7 @@ def _do_run(self, driver: Driver, optimizer, *args): # N3CC FLOPS output line 2393 desired = 5649.9 # ft - actual = takeoff.model.get_val( - 'traj.takeoff_liftoff.states:distance', units='ft')[-1] + actual = takeoff.model.get_val('traj.takeoff_liftoff.states:distance', units='ft')[-1] assert_near_equal(actual, desired, 2e-2) diff --git a/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py b/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py index 913fb3ee43..bdd4fed072 100644 --- a/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_battery_in_a_mission.py @@ -1,7 +1,7 @@ import unittest -from openmdao.utils.testing_utils import use_tempdirs from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import use_tempdirs import aviary.api as av from aviary.subsystems.energy.battery_builder import BatteryBuilder @@ -9,9 +9,7 @@ @use_tempdirs class TestSubsystemsMission(unittest.TestCase): - """ - Test the setup and run optimization model with a bettery subsystem. - """ + """Test the setup and run optimization model with a bettery subsystem.""" def setUp(self): self.phase_info = { @@ -20,28 +18,45 @@ def setUp(self): 'external_subsystems': [BatteryBuilder()], 'optimize_mass': True, }, - 'cruise': { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, + 'cruise1': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'external_subsystems': [BatteryBuilder()], + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_final': (35000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((5.0, 30.0), 'min'), + }, + }, + 'cruise2': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, 'external_subsystems': [BatteryBuilder()], - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((10.0, 30.0), "min"), + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_final': (35000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((5.0, 30.0), 'min'), }, }, 'post_mission': { @@ -53,22 +68,16 @@ def setUp(self): def test_subsystems_in_a_mission(self): phase_info = self.phase_info.copy() - prob = av.AviaryProblem() + prob = av.AviaryProblem(verbosity=0) prob.load_inputs( - "models/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv", phase_info) + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm_with_electric.csv', + phase_info, + ) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - - prob.add_phases() - - prob.add_post_mission_systems() - - # Link phases and variables - prob.link_phases() + prob.build_model() prob.add_driver('SLSQP') @@ -78,25 +87,88 @@ def test_subsystems_in_a_mission(self): prob.setup() - prob.set_initial_guesses() - prob.set_val(av.Aircraft.Battery.PACK_ENERGY_DENSITY, 550, units='kJ/kg') prob.set_val(av.Aircraft.Battery.PACK_MASS, 1000, units='lbm') prob.set_val(av.Aircraft.Battery.ADDITIONAL_MASS, 115, units='lbm') prob.run_aviary_problem() + self.assertTrue(prob.result.success) - electric_energy_used = prob.get_val( - 'traj.cruise.timeseries.' - f'{av.Dynamic.Mission.CUMULATIVE_ELECTRIC_ENERGY_USED}', + electric_energy_used_cruise2 = prob.get_val( + f'traj.cruise2.timeseries.{av.Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED}', units='kW*h', ) + soc_cruise1 = prob.get_val( + f'traj.cruise1.timeseries.{av.Dynamic.Vehicle.BATTERY_STATE_OF_CHARGE}', + ) + soc_cruise2 = prob.get_val( + f'traj.cruise2.timeseries.{av.Dynamic.Vehicle.BATTERY_STATE_OF_CHARGE}', + ) fuel_burned = prob.get_val(av.Mission.Summary.FUEL_BURNED, units='lbm') # Check outputs - assert_near_equal(electric_energy_used[-1], 38.60538132, 1.e-7) - assert_near_equal(fuel_burned, 676.87235486, 1.e-7) + # indirectly check mission trajectory by checking total fuel/electric split + assert_near_equal(electric_energy_used_cruise2[-1], 38.60747069, 1.0e-7) + assert_near_equal(fuel_burned, 676.93670291, 1.0e-7) + # check battery state-of-charge over mission + + assert_near_equal( + soc_cruise1.ravel(), + [ + 0.9999957806265609, + 0.9877535827147117, + 0.9708627248497483, + 0.9655170378370462, + 0.9655170378370462, + 0.9405186291064791, + 0.9060295822713065, + 0.8951147997010394, + 0.8951147997010394, + 0.8654018683927851, + 0.8244092512817177, + 0.8114364753183335, + 0.8114364753183335, + 0.7864517853197655, + 0.7519816637312142, + 0.7410728700181042, + 0.7410728700181042, + 0.7288419600341913, + 0.7119666756734181, + 0.7066259172513626, + ], + 1e-7, + ) + + assert_near_equal( + soc_cruise2.ravel(), + [ + 0.7066259172513626, + 0.6943965083029002, + 0.677523294860927, + 0.672183191828372, + 0.672183191828372, + 0.6472108945884663, + 0.6127578690420414, + 0.601854485338024, + 0.601854485338024, + 0.5721725827519708, + 0.531222768718283, + 0.5182635373126063, + 0.5182635373126063, + 0.4933049316352059, + 0.4588707938555728, + 0.44797338714853385, + 0.44797338714853385, + 0.435755243772871, + 0.41889757299299735, + 0.4135623887905029, + ], + 1e-7, + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() + # test = TestSubsystemsMission() + # test.setUp() + # test.test_subsystems_in_a_mission() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py index 1a07bb9673..b350ebfc6c 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwFm.py @@ -1,16 +1,13 @@ import unittest import numpy as np - -from openmdao.utils.mpi import MPI -from openmdao.utils.testing_utils import use_tempdirs -from openmdao.utils.testing_utils import require_pyoptsparse from openmdao.core.problem import _clear_problem_names +from openmdao.utils.mpi import MPI +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from aviary.api import Mission from aviary.interface.methods_for_level1 import run_aviary -from aviary.validation_cases.benchmark_utils import \ - compare_against_expected_values +from aviary.validation_cases.benchmark_utils import compare_against_expected_values try: from openmdao.vectors.petsc_vector import PETScVector @@ -18,346 +15,176 @@ PETScVector = None +@use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): """ - Setup of a large single aisle commercial transport aircraft using - FLOPS mass method and HEIGHT_ENERGY mission method. Expected outputs based - on 'models/test_aircraft/aircraft_for_bench_FwFm.csv' model. + Setup of a large single aisle commercial transport aircraft using + FLOPS mass and aero method and HEIGHT_ENERGY mission method. Expected outputs based + on 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' model. """ def setUp(self): expected_dict = {} - expected_dict['times'] = np.array([[120.], - [163.76268404], - [224.14625594], - [243.25744998], - [243.25744998], - [336.40804126], - [464.93684491], - [505.61577182], - [505.61577182], - [626.46953842], - [793.22306972], - [845.99999224], - [845.99999224], - [966.85375884], - [1133.60729014], - [1186.38421266], - [1186.38421266], - [1279.53480393], - [1408.06360758], - [1448.74253449], - [1448.74253449], - [1492.50521853], - [1552.88879042], - [1571.99998447], - [1571.99998447], - [10224.87383109], - [22164.07366288], - [25942.78958866], - [25942.78958866], - [26009.11685074], - [26100.63493484], - [26129.60009555], - [26129.60009555], - [26265.05921709], - [26451.96515722], - [26511.12024823], - [26511.12024823], - [26672.16774132], - [26894.38041154], - [26964.7099619], - [26964.7099619], - [27100.16908344], - [27287.07502357], - [27346.23011458], - [27346.23011458], - [27412.55737667], - [27504.07546076], - [27533.04062147]]) + # block auto-formatting of tables + # fmt: off + expected_dict['times'] = np.array( + [ + [120.],[163.76268404], [224.14625594], [243.25744998], [243.25744998], + [336.40804126], [464.93684491], [505.61577182], [505.61577182], [626.46953842], + [793.22306972], [845.99999224], [845.99999224], [966.85375884], [1133.60729014], + [1186.38421266], [1186.38421266], [1279.53480393], [1408.06360758], [1448.74253449], + [1448.74253449], [1492.50521853], [1552.88879042], [1571.99998447], [1571.99998447], + [10224.87383109], [22164.07366288], [25942.78958866], [25942.78958866], + [26009.11685074], [26100.63493484], [26129.60009555], [26129.60009555], + [26265.05921709], [26451.96515722], [26511.12024823], [26511.12024823], + [26672.16774132], [26894.38041154], [26964.7099619], [26964.7099619], + [27100.16908344], [27287.07502357], [27346.23011458], [27346.23011458], + [27412.55737667], [27504.07546076], [27533.04062147] + ] + ) - expected_dict['altitudes'] = np.array([[10.668], - [0.], - [1001.70617719], - [1429.27176545], - [1429.27176545], - [3413.27102762], - [5642.3831233], - [6169.75300447], - [6169.75300447], - [7399.140983], - [8514.78661356], - [8803.21405264], - [8803.21405264], - [9373.68426297], - [10020.99237958], - [10196.42552457], - [10196.42552457], - [10451.72258036], - [10652.38789684], - [10668.], - [10668.], - [10660.42246376], - [10656.16585151], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10142.11478951], - [9922.15743555], - [9922.15743555], - [8891.66886638], - [7502.1861348], - [7069.1900852], - [7069.1900852], - [5896.44637998], - [4264.29354306], - [3737.8471594], - [3737.8471594], - [2702.15624637], - [1248.18960736], - [793.03526817], - [793.03526817], - [345.06939295], - [10.668], - [10.668]]) + expected_dict['altitudes'] = np.array( + [ + [10.668], [0.], [1001.70617719], [1429.27176545], [1429.27176545], [3413.27102762], + [5642.3831233], [6169.75300447], [6169.75300447], [7399.140983], [8514.78661356], + [8803.21405264], [8803.21405264], [9373.68426297], [10020.99237958], + [10196.42552457], [10196.42552457],[10451.72258036], [10652.38789684], [10668.], + [10668.], [10660.42246376], [10656.16585151], [10668.], [10668.], [10668.], + [10668.], [10668.], [10668.], [10668.], [10142.11478951], [9922.15743555], + [9922.15743555], [8891.66886638], [7502.1861348], [7069.1900852], [7069.1900852], + [5896.44637998], [4264.29354306], [3737.8471594], [3737.8471594], [2702.15624637], + [1248.18960736], [793.03526817], [793.03526817], [345.06939295], [10.668], [10.668] + ] + ) - expected_dict['masses'] = np.array([[79303.30184763], - [79221.39668215], - [79075.19453181], - [79028.6003426], - [79028.6003426], - [78828.82221909], - [78613.60466821], - [78557.84739563], - [78557.84739563], - [78411.06578989], - [78238.0916773], - [78186.75440341], - [78186.75440341], - [78077.23953313], - [77938.37965175], - [77896.59718975], - [77896.59718975], - [77825.81832958], - [77732.75016916], - [77704.11629998], - [77704.11629998], - [77673.32196072], - [77630.75735319], - [77617.25716885], - [77617.25716885], - [72178.78521803], - [65072.41395049], - [62903.84179505], - [62903.84179505], - [62896.27636813], - [62888.3612195], - [62885.93748938], - [62885.93748938], - [62874.48788511], - [62857.70600096], - [62852.13740881], - [62852.13740881], - [62835.97069937], - [62810.37776063], - [62801.1924259], - [62801.1924259], - [62781.32471014], - [62748.91017128], - [62737.32520462], - [62737.32520462], - [62723.59895849], - [62703.94977811], - [62697.71513264]]) + expected_dict['masses'] = np.array( + [ + [79303.30184763], [79221.39668215], [79075.19453181], [79028.6003426], + [79028.6003426], [78828.82221909], [78613.60466821], [78557.84739563], + [78557.84739563], [78411.06578989], [78238.0916773], [78186.75440341], + [78186.75440341], [78077.23953313], [77938.37965175], [77896.59718975], + [77896.59718975], [77825.81832958], [77732.75016916], [77704.11629998], + [77704.11629998], [77673.32196072], [77630.75735319], [77617.25716885], + [77617.25716885], [72178.78521803], [65072.41395049], [62903.84179505], + [62903.84179505], [62896.27636813], [62888.3612195], [62885.93748938], + [62885.93748938], [62874.48788511], [62857.70600096], [62852.13740881], + [62852.13740881], [62835.97069937], [62810.37776063], [62801.1924259], + [62801.1924259], [62781.32471014], [62748.91017128], [62737.32520462], + [62737.32520462], [62723.59895849], [62703.94977811], [62697.71513264] + ] + ) - expected_dict['ranges'] = np.array([[1452.84514351], - [6093.51223933], - [15820.03029119], - [19123.61258676], - [19123.61258676], - [36374.65336952], - [61265.3984918], - [69106.49687132], - [69106.49687132], - [92828.04820577], - [126824.13801408], - [138011.02420534], - [138011.02420534], - [164027.18014424], - [200524.66550565], - [212113.49107256], - [212113.49107256], - [232622.50720766], - [261189.53466522], - [270353.40501262], - [270353.40501262], - [280350.48472685], - [294356.27080588], - [298832.61221641], - [298832.61221641], - [2325837.11255987], - [5122689.60556392], - [6007883.85695889], - [6007883.85695889], - [6022237.43153219], - [6039575.06318219], - [6044873.89820027], - [6044873.89820027], - [6068553.1921364], - [6099290.23732297], - [6108673.67260778], - [6108673.67260778], - [6133535.09572671], - [6166722.19545137], - [6177077.72115854], - [6177077.72115854], - [6197011.1330154], - [6224357.63792683], - [6232920.45309764], - [6232920.45309764], - [6242332.46480721], - [6254144.50957549], - [6257352.4]]) + expected_dict['ranges'] = np.array( + [ + [1452.84514351], [6093.51223933], [15820.03029119], [19123.61258676], + [19123.61258676], [36374.65336952], [61265.3984918], [69106.49687132], + [69106.49687132], [92828.04820577], [126824.13801408], [138011.02420534], + [138011.02420534], [164027.18014424], [200524.66550565], [212113.49107256], + [212113.49107256], [232622.50720766], [261189.53466522], [270353.40501262], + [270353.40501262], [280350.48472685], [294356.27080588], [298832.61221641], + [298832.61221641], [2325837.11255987], [5122689.60556392], [6007883.85695889], + [6007883.85695889], [6022237.43153219], [6039575.06318219], [6044873.89820027], + [6044873.89820027], [6068553.1921364], [6099290.23732297], [6108673.67260778], + [6108673.67260778], [6133535.09572671], [6166722.19545137], [6177077.72115854], + [6177077.72115854], [6197011.1330154], [6224357.63792683], [6232920.45309764], + [6232920.45309764], [6242332.46480721], [6254144.50957549], [6257352.4] + ] + ) - expected_dict['velocities'] = np.array([[69.30879167], - [137.49019035], - [174.54683946], - [179.28863383], - [179.28863383], - [191.76748742], - [194.33322917], - [194.52960387], - [194.52960387], - [199.01184603], - [209.81696863], - [212.86546124], - [212.86546124], - [217.37467051], - [219.67762167], - [219.97194272], - [219.97194272], - [220.67963782], - [224.38113484], - [226.77184704], - [226.77184704], - [230.01128033], - [233.72454583], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [201.23881], - [182.84158341], - [180.10650108], - [180.10650108], - [169.77497514], - [159.59034446], - [157.09907013], - [157.09907013], - [151.659491], - [147.52098882], - [147.07683999], - [147.07683999], - [147.05392009], - [145.31556891], - [143.47446173], - [143.47446173], - [138.99109332], - [116.22447082], - [102.07377559]]) + expected_dict['velocities'] = np.array( + [ + [69.30879167], [137.49019035], [174.54683946], [179.28863383], [179.28863383], + [191.76748742], [194.33322917], [194.52960387], [194.52960387], [199.01184603], + [209.81696863], [212.86546124], [212.86546124], [217.37467051], [219.67762167], + [219.97194272], [219.97194272], [220.67963782], [224.38113484], [226.77184704], + [226.77184704], [230.01128033], [233.72454583], [234.25795132], [234.25795132], + [234.25795132], [234.25795132], [234.25795132], [234.25795132], [201.23881], + [182.84158341], [180.10650108], [180.10650108], [169.77497514], [159.59034446], + [157.09907013], [157.09907013], [151.659491], [147.52098882], [147.07683999], + [147.07683999], [147.05392009], [145.31556891], [143.47446173], [143.47446173], + [138.99109332], [116.22447082], [102.07377559] + ] + ) + # fmt: on self.expected_dict = expected_dict phase_info = { - "pre_mission": {"include_takeoff": True, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - 'fix_initial': False, - 'input_initial': True, - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 6, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.3, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.1, 0.8), "unitless"), - "initial_altitude": (35., "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((0.0, 35000.0), "ft"), - "throttle_enforcement": "path_constraint", - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 2.0), "min"), - "duration_bounds": ((5.0, 50.0), "min"), - "no_descent": False, - "add_initial_mass_constraint": False, + 'pre_mission': {'include_takeoff': True, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 6, + 'order': 3, + 'mach_bounds': ((0.1, 0.8), 'unitless'), + 'mach_optimize': True, + 'altitude_bounds': ((0.0, 35000.0), 'ft'), + 'altitude_optimize': True, + 'throttle_enforcement': 'path_constraint', + 'mass_ref': (200000, 'lbm'), + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((20.0, 60.0), 'min'), + 'no_descent': True, + }, + 'initial_guesses': { + 'time': ([0, 40.0], 'min'), + 'altitude': ([35, 35000.0], 'ft'), + 'mach': ([0.3, 0.79], 'unitless'), }, - "initial_guesses": {"time": ([0, 40.0], "min")}, }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "polynomial_control_order": 1, - "use_polynomial_control": True, - "num_segments": 1, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.79, 0.79), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((35000.0, 35000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((60.0, 720.0), "min"), + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 1, + 'order': 3, + 'mach_initial': (0.79, 'unitless'), + 'mach_bounds': ((0.79, 0.79), 'unitless'), + 'mach_optimize': True, + 'mach_polynomial_order': 1, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_bounds': ((35000.0, 35000.0), 'ft'), + 'altitude_optimize': True, + 'altitude_polynomial_order': 1, + 'throttle_enforcement': 'boundary_constraint', + 'mass_ref': (200000, 'lbm'), + 'time_initial_bounds': ((20.0, 60.0), 'min'), + 'time_duration_bounds': ((60.0, 720.0), 'min'), + }, + 'initial_guesses': { + 'time': ([40, 200], 'min'), + 'altitude': ([35000, 35000.0], 'ft'), + 'mach': ([0.79, 0.79], 'unitless'), }, - "initial_guesses": {"time": ([128, 113], "min")}, }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.3, "unitless"), - "mach_bounds": ((0.2, 0.8), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35.0, "ft"), - "altitude_bounds": ((0.0, 35000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120., 800.), "min"), - "duration_bounds": ((5.0, 35.0), "min"), - "no_climb": True, + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_initial': (0.79, 'unitless'), + 'mach_final': (0.3, 'unitless'), + 'mach_bounds': ((0.2, 0.8), 'unitless'), + 'mach_optimize': True, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_final': (35.0, 'ft'), + 'altitude_bounds': ((0.0, 35000.0), 'ft'), + 'altitude_optimize': True, + 'throttle_enforcement': 'path_constraint', + 'mass_ref': (200000, 'lbm'), + 'distance_ref': (3375, 'nmi'), + 'time_initial_bounds': ((80.0, 780.0), 'min'), + 'time_duration_bounds': ((5.0, 45.0), 'min'), + 'no_climb': True, + }, + 'initial_guesses': { + 'time': ([240, 30], 'min'), }, - "initial_guesses": {"time": ([241, 30], "min")}, }, - "post_mission": { - "include_landing": True, - "constrain_range": True, - "target_range": (3375.0, "nmi"), + 'post_mission': { + 'include_landing': True, + 'constrain_range': True, + 'target_range': (3375.0, 'nmi'), }, } @@ -366,67 +193,64 @@ def setUp(self): _clear_problem_names() # need to reset these to simulate separate runs -@use_tempdirs class TestBenchFwFmSerial(ProblemPhaseTestCase): - """ - Run the model in serial that is setup in ProblemPhaseTestCase class. - """ + """Run the model in serial that is setup in ProblemPhaseTestCase class.""" - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_bench_FwFm_IPOPT(self): prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, verbosity=0, max_iter=50, optimizer='IPOPT', ) + # self.assertTrue(prob.result.success) compare_against_expected_values(prob, self.expected_dict) - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def test_bench_FwFm_SNOPT(self): prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, verbosity=0, max_iter=50, optimizer='SNOPT', ) + # self.assertTrue(prob.result.success) compare_against_expected_values(prob, self.expected_dict) # This is one of the few places we test Height Energy + simple takeoff. overall_fuel = prob.get_val(Mission.Summary.TOTAL_FUEL_MASS) # Making sure we include the fuel mass consumed in take-off and taxi. - self.assertGreater(overall_fuel, 40000.) + self.assertGreater(overall_fuel, 40000.0) -@use_tempdirs -@unittest.skipUnless(MPI and PETScVector, "MPI and PETSc are required.") +@unittest.skipUnless(MPI and PETScVector, 'MPI and PETSc are required.') class TestBenchFwFmParallel(ProblemPhaseTestCase): - """ - Run the model in parallel that is setup in ProblemPhaseTestCase class. - """ + """Run the model in parallel that is setup in ProblemPhaseTestCase class.""" N_PROCS = 3 - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def test_bench_FwFm_SNOPT_MPI(self): prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, verbosity=0, max_iter=50, optimizer='SNOPT', ) - + # self.assertTrue(prob.result.success) compare_against_expected_values(prob, self.expected_dict) if __name__ == '__main__': - unittest.main() - # test = TestBenchFwFmSerial() - # test.setUp() - # test.test_bench_FwFm_SNOPT() + # unittest.main() + test = TestBenchFwFmSerial() + test.setUp() + # test.test_bench_FwFm_IPOPT() + test.test_bench_FwFm_SNOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py index 72bf9487df..4083292d54 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_FwGm.py @@ -1,11 +1,11 @@ -from copy import deepcopy import unittest +from copy import deepcopy +from openmdao.core.problem import _clear_problem_names from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from openmdao.core.problem import _clear_problem_names -from aviary.interface.default_phase_info.two_dof import phase_info +from aviary.models.missions.two_dof_default import phase_info from aviary.interface.methods_for_level1 import run_aviary from aviary.variable_info.variables import Aircraft, Mission @@ -13,74 +13,74 @@ @use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): """ - Test the setup and run of a large single aisle commercial transport aircraft using - FLOPS mass method and TWO_DEGREES_OF_FREEDOM mission method. Expected outputs - based on 'models/test_aircraft/aircraft_for_bench_FwFm.csv' model. + Test the setup and run of a large single aisle commercial transport aircraft using + FLOPS mass method, GASP aero method, and TWO_DEGREES_OF_FREEDOM mission method. + Expected outputs based on 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' model. """ def setUp(self): _clear_problem_names() # need to reset these to simulate separate runs - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def bench_test_swap_3_FwGm_IPOPT(self): local_phase_info = deepcopy(phase_info) prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwGm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv', local_phase_info, max_iter=100, verbosity=0, optimizer='IPOPT', ) + # TODO: This problem does not always converge. + # self.assertTrue(prob.result.success) + rtol = 1e-2 # There are no truth values for these. - assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), - 179391., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), 177536.28, tolerance=rtol) - assert_near_equal(prob.get_val(Aircraft.Design.OPERATING_MASS), - 101556., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Summary.OPERATING_MASS), 101262.9, tolerance=rtol) - assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), - 39979., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), 38417.3, tolerance=rtol) - assert_near_equal(prob.get_val('landing.' + Mission.Landing.GROUND_DISTANCE), - 2595., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Landing.GROUND_DISTANCE), 2613.4, tolerance=rtol) - assert_near_equal(prob.get_val("traj.desc2.timeseries.distance")[-1], - 3675.0, tolerance=rtol) + assert_near_equal( + prob.get_val('traj.desc2.timeseries.distance')[-1], 3675.0, tolerance=rtol + ) - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def bench_test_swap_3_FwGm_SNOPT(self): local_phase_info = deepcopy(phase_info) prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_FwGm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_FwGm.csv', local_phase_info, - verbosity=0, + verbosity=1, optimizer='SNOPT', + max_iter=60, ) + self.assertTrue(prob.result.success) + rtol = 1e-2 # There are no truth values for these. - assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), - 179390., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Design.GROSS_MASS), 177536.28, tolerance=rtol) - assert_near_equal(prob.get_val(Aircraft.Design.OPERATING_MASS), - 101556., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Summary.OPERATING_MASS), 101262.9, tolerance=rtol) - assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), - 39979., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Summary.TOTAL_FUEL_MASS), 38417.3, tolerance=rtol) - assert_near_equal(prob.get_val('landing.' + Mission.Landing.GROUND_DISTANCE), - 2595., tolerance=rtol) + assert_near_equal(prob.get_val(Mission.Landing.GROUND_DISTANCE), 2613.4, tolerance=rtol) - assert_near_equal(prob.get_val("traj.desc2.timeseries.distance")[-1], - 3675.0, tolerance=rtol) + assert_near_equal( + prob.get_val('traj.desc2.timeseries.distance')[-1], 3675.0, tolerance=rtol + ) -if __name__ == "__main__": +if __name__ == '__main__': test = ProblemPhaseTestCase() test.setUp() - test.bench_test_swap_3_FwGm_SNOPT() - # test.bench_test_swap_3_FwGm_IPOPT() + # test.bench_test_swap_3_FwGm_SNOPT() + test.bench_test_swap_3_FwGm_IPOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py index 7953cbeff4..ec4075c14e 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwFm.py @@ -1,396 +1,150 @@ -''' -NOTES: +""" +Notes +----- Includes: Takeoff, Climb, Cruise, Descent, Landing Computed Aero Large Single Aisle 1 data -''' +""" + import unittest +from copy import deepcopy import numpy as np -from openmdao.utils.testing_utils import use_tempdirs -from openmdao.utils.testing_utils import require_pyoptsparse from openmdao.core.problem import _clear_problem_names +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from aviary.interface.methods_for_level1 import run_aviary -from aviary.validation_cases.benchmark_utils import \ - compare_against_expected_values +from aviary.models.aircraft.test_aircraft.GwFm_phase_info import phase_info +from aviary.validation_cases.benchmark_utils import compare_against_expected_values @use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): """ - Test the setup and run of a large single aisle commercial transport aircraft using - GASP mass method and HEIGHT_ENERGY mission method. Expected outputs - based on 'models/test_aircraft/aircraft_for_bench_FwFm.csv' model. + Test the setup and run of a large single aisle commercial transport aircraft using + GASP mass method, GASP aero method, and HEIGHT_ENERGY mission method. Expected outputs + based on 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' model. """ def setUp(self): expected_dict = {} - expected_dict['times'] = np.array([[120.], - [163.76271231], - [224.1463232], - [243.25752959], - [243.25752959], - [336.40818102], - [464.93706768], - [505.61602085], - [505.61602085], - [626.4698655], - [793.2235045], - [846.0004611], - [846.0004611], - [966.85430575], - [1133.60794474], - [1186.38490134], - [1186.38490134], - [1279.53555278], - [1408.06443943], - [1448.74339261], - [1448.74339261], - [1492.50610492], - [1552.88971581], - [1572.0009222], - [1572.0009222], - [10224.86854151], - [22164.05978091], - [25942.77298722], - [25942.77298722], - [26009.89831864], - [26102.51757551], - [26131.83125364], - [26131.83125364], - [26268.92025959], - [26458.07510754], - [26517.94197018], - [26517.94197018], - [26680.92723458], - [26905.81363368], - [26976.98941009], - [26976.98941009], - [27114.07841604], - [27303.23326399], - [27363.10012663], - [27363.10012663], - [27430.22545805], - [27522.84471492], - [27552.15839306]]) - expected_dict['altitudes'] = np.array([[10.668], - [0.], - [1176.78911697], - [1673.72886901], - [1673.72886901], - [3865.01102367], - [6195.61836863], - [6782.34302216], - [6782.34302216], - [8109.95869793], - [9272.93435889], - [9556.37792864], - [9556.37792864], - [10094.94809064], - [10559.35775736], - [10627.1932692], - [10627.1932692], - [10668.], - [10650.08598518], - [10649.95573356], - [10649.95573356], - [10657.29116463], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10668.], - [10307.54164946], - [10143.7274239], - [10143.7274239], - [9248.78597393], - [7827.69756506], - [7363.41307882], - [7363.41307882], - [6126.8939629], - [4470.55591283], - [3951.86624585], - [3951.86624585], - [2939.92813668], - [1471.34739294], - [982.44499735], - [982.44499735], - [449.58751714], - [10.83591043], - [10.668]]) + # block auto-formatting of tables + # fmt: off + expected_dict['times'] = np.array( + [ + [0.0], [35.44351212], [84.34832473], [99.82653071], [99.82653071], [175.26943791], + [279.36525173], [312.31122089], [312.31122089], [410.19100215], [545.24512274], + [587.98929015], [587.98929015], [685.86907141], [820.923192], [863.66735941], + [863.66735941], [939.1102666], [1043.20608042], [1076.15204958], [1076.15204958], + [1111.59556171], [1160.50037431], [1175.9785803], [1175.9785803], [9079.76302018], + [19985.372362], [23436.96043162], [23436.96043162], [23608.01963971], + [23844.04643319], [23918.74810633], [23918.74810633], [24268.09962982], + [24750.13342859], [24902.69547779], [24902.69547779], [25318.03987414], + [25891.13036812], [26072.51155003], [26072.51155003], [26421.86307352], + [26903.89687229], [27056.45892149], [27056.45892149], [27227.51812957], + [27463.54492305], [27538.24659619], + ] + ) - expected_dict['masses'] = np.array([[68463.53921924], - [68388.16396576], - [68245.77323713], - [68201.21751908], - [68201.21751908], - [68008.46518048], - [67807.59357082], - [67754.96222353], - [67754.96222353], - [67619.16435342], - [67463.77290019], - [67418.37147793], - [67418.37147793], - [67321.58684141], - [67204.00255349], - [67170.96641995], - [67170.96641995], - [67116.2987407], - [67044.08894595], - [67020.83854678], - [67020.83854678], - [66995.00611866], - [66954.5572371], - [66939.76926892], - [66939.76926892], - [61880.26581581], - [55221.27982315], - [53175.67231214], - [53175.67231214], - [53158.01594442], - [53144.299632], - [53140.88521042], - [53140.88521042], - [53127.49149749], - [53111.02960542], - [53105.82637933], - [53105.82637933], - [53090.66670078], - [53066.21593581], - [53057.26691014], - [53057.26691014], - [53038.09861563], - [53006.77727746], - [52995.48090755], - [52995.48090755], - [52981.90805198], - [52962.16924161], - [52955.84313972]]) + expected_dict['altitudes'] = np.array( + [ + [1.06680000e01], [1.75893172e02], [9.46408953e02], [1.32134196e03], [1.32134196e03], + [3.11445470e03], [4.97144244e03], [5.41008257e03], [5.41008257e03], [6.51672447e03], + [7.74801608e03], [8.06629246e03], [8.06629246e03], [8.71104542e03], [9.45373608e03], + [9.65329790e03], [9.65329790e03], [9.97691027e03], [1.03789374e04], [1.04954293e04], + [1.04954293e04], [1.05962176e04], [1.06638513e04], [1.06680000e04], [1.06680000e04], + [1.06680000e04], [1.06680000e04], [1.06680000e04], [1.06680000e04], [1.06680000e04], + [1.06680000e04], [1.06680000e04], [1.06680000e04], [1.06680000e04], [1.06680000e04], + [1.06680000e04], [1.06680000e04], [1.04608909e04], [9.49505220e03], [9.02507507e03], + [9.02507507e03], [7.63207198e03], [4.35806338e03], [2.99524490e03], [2.99524490e03], + [1.59457677e03], [3.69306987e02], [1.52400000e02], + ] + ) + + expected_dict['masses'] = np.array( + [ + [77361.51975924], [77270.51854549], [77141.65302837], [77104.71422447], + [77104.71422447], [76941.27090846], [76753.64296774], [76702.53488499], + [76702.53488499], [76563.68643732], [76395.73949189], [76348.05709341], + [76348.05709341], [76245.44377245], [76115.86511398], [76077.67355086], + [76077.67355086], [76012.88182425], [75928.38145408], [75902.8275571], + [75902.8275571], [75876.40401633], [75842.31565887], [75832.06686674], + [75832.06686674], [71104.64472312], [64954.26684732], [63085.9645323], + [63085.9645323], [62996.16016685], [62872.90067674], [62833.95037133], + [62833.95037133], [62651.41955818], [62397.32666607], [62315.99678281], + [62315.99678281], [62107.31484338], [61874.89401841], [61817.83630664], + [61817.83630664], [61733.10749575], [61656.10364388], [61636.95406205], + [61636.95406205], [61603.3160787], [61549.72162395], [61535.43675845], + ] + ) - expected_dict['ranges'] = np.array([[1166.20699576], - [5593.37409715], - [15160.34254633], - [18452.29987419], - [18452.29987419], - [35953.4905749], - [61610.20915607], - [69693.60643145], - [69693.60643145], - [94109.378342], - [128861.35815474], - [140228.92014561], - [140228.92014561], - [166663.67193054], - [203797.88470247], - [215616.8251792], - [215616.8251792], - [236507.17277307], - [265348.67959522], - [274478.82401463], - [274478.82401463], - [284316.3485801], - [298061.71411326], - [302496.32074313], - [302496.32074313], - [2329499.36229261], - [5126349.84245871], - [6011543.45679734], - [6011543.45679734], - [6026497.11291725], - [6044998.00245228], - [6050451.95986915], - [6050451.95986915], - [6074179.71278433], - [6103973.32165406], - [6113145.04319224], - [6113145.04319224], - [6137396.13533869], - [6169641.84998078], - [6179602.4331379], - [6179602.4331379], - [6198630.75436767], - [6224716.73281895], - [6232974.51970883], - [6232974.51970883], - [6242235.03685456], - [6254092.42671214], - [6257352.4]]) + expected_dict['ranges'] = np.array( + [ + [1.00000000e00], [4.74198427e03], [1.37414828e04], [1.68318940e04], [1.68318940e04], + [3.18584148e04], [5.27770771e04], [5.95458083e04], [5.95458083e04], [8.02418572e04], + [1.09967777e05], [1.19584064e05], [1.19584064e05], [1.41874036e05], [1.73059575e05], + [1.82991722e05], [1.82991722e05], [2.00549682e05], [2.24726489e05], [2.32341402e05], + [2.32341402e05], [2.40509164e05], [2.51778850e05], [2.55355789e05], [2.55355789e05], + [2.08392849e06], [4.60698560e06], [5.40552455e06], [5.40552455e06], [5.44494993e06], + [5.49894835e06], [5.51596807e06], [5.51596807e06], [5.59533266e06], [5.70499475e06], + [5.73994374e06], [5.73994374e06], [5.83514250e06], [5.95846437e06], [5.99343870e06], + [5.99343870e06], [6.05377296e06], [6.12937059e06], [6.15340515e06], [6.15340515e06], + [6.18080515e06], [6.21436615e06], [6.22272000e06], + ] + ) - expected_dict['velocities'] = np.array([[64.4147653], - [133.69502146], - [174.31936373], - [180.24083219], - [180.24083219], - [196.61398458], - [200.67345509], - [200.77798066], - [200.77798066], - [204.32902616], - [213.53269554], - [216.30794138], - [216.30794138], - [220.90502555], - [223.85447586], - [224.18464453], - [224.18464453], - [224.33459955], - [224.43913124], - [224.63981271], - [224.63981271], - [225.38258712], - [230.7187408], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [234.25795132], - [212.06605788], - [188.96924746], - [183.2491682], - [183.2491682], - [164.64559845], - [153.53645555], - [151.57537965], - [151.57537965], - [146.52626765], - [140.88518413], - [139.7046818], - [139.7046818], - [138.44302405], - [138.07991553], - [138.08432897], - [138.08432897], - [136.46253134], - [116.34759903], - [102.07377559]]) + expected_dict['velocities'] = np.array( + [ + [102.07377561], [161.2782508], [199.81349584], [201.60626064], [201.60626064], + [200.21264516], [204.50750389], [207.35537804], [207.35537804], [215.80220464], + [224.14489761], [226.04492923], [226.04492923], [229.41156529], [232.18006085], + [232.62216037], [232.62216037], [232.77235904], [231.52065251], [230.77711992], + [230.77711992], [230.27691888], [230.86129092], [231.35407027], [231.35407027], + [231.35407027], [231.35407027], [231.35407027], [231.35407027], [229.67216212], + [228.02443801], [227.66551514], [227.66551514], [226.95333659], [228.54367761], + [229.66860513], [229.66860513], [226.46343745], [199.58744961], [185.36056365], + [185.36056365], [162.65708107], [156.08586817], [160.2787063], [160.2787063], + [157.2587354], [121.13691301], [101.91044472], + ] + ) + # fmt: on self.expected_dict = expected_dict - phase_info = { - "pre_mission": {"include_takeoff": True, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - 'fix_initial': False, - 'input_initial': True, - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 6, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.2, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.1, 0.8), "unitless"), - "initial_altitude": (0.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((0.0, 36000.0), "ft"), - "throttle_enforcement": "path_constraint", - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((5.0, 50.0), "min"), - "no_descent": True, - "add_initial_mass_constraint": False, - }, - "initial_guesses": {"time": ([0, 40.0], "min")}, - }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "polynomial_control_order": 1, - "use_polynomial_control": True, - "num_segments": 1, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.78, 0.8), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((35000.0, 35000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((60.0, 7200.0), "min"), - }, - "initial_guesses": {"time": ([128, 113], "min")}, - }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.3, "unitless"), - "mach_bounds": ((0.2, 0.8), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (500.0, "ft"), - "altitude_bounds": ((0.0, 35000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120.5, 361.5), "min"), - "duration_bounds": ((5.0, 30.0), "min"), - "no_climb": True, - }, - "initial_guesses": {"time": ([241, 30], "min")}, - }, - "post_mission": { - "include_landing": True, - "constrain_range": True, - "target_range": (3360.0, "nmi"), - }, - } - - self.phase_info = phase_info + self.phase_info = deepcopy(phase_info) _clear_problem_names() # need to reset these to simulate separate runs - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def bench_test_swap_1_GwFm_IPOPT(self): prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_GwFm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv', self.phase_info, max_iter=100, optimizer='IPOPT', verbosity=0, ) - + # self.assertTrue(prob.result.success) compare_against_expected_values(prob, self.expected_dict) - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def bench_test_swap_1_GwFm_SNOPT(self): prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_GwFm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv', self.phase_info, max_iter=50, optimizer='SNOPT', verbosity=0, ) - + # self.assertTrue(prob.result.success) compare_against_expected_values(prob, self.expected_dict) if __name__ == '__main__': + # unittest.main() test = ProblemPhaseTestCase() test.setUp() - test.bench_test_swap_1_GwFm_IPOPT() + # test.bench_test_swap_1_GwFm_IPOPT() test.bench_test_swap_1_GwFm_SNOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py index 1c10dc162d..206aa067b4 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_GwGm.py @@ -1,231 +1,117 @@ -from copy import deepcopy import unittest +from copy import deepcopy from openmdao.core.problem import _clear_problem_names from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.interface.default_phase_info.two_dof import phase_info +from aviary.models.missions.two_dof_default import phase_info from aviary.interface.methods_for_level1 import run_aviary -from aviary.variable_info.enums import AnalysisScheme from aviary.variable_info.variables import Aircraft, Dynamic, Mission @use_tempdirs class ProblemPhaseTestCase(unittest.TestCase): """ - Test the setup and run of a large single aisle commercial transport aircraft using - GASP mass method and TWO_DEGREES_OF_FREEDOM mission method. Expected outputs - based on 'models/test_aircraft/aircraft_for_bench_FwFm.csv' model. + Test the setup and run of a large single aisle commercial transport aircraft using + GASP mass and aero method and TWO_DEGREES_OF_FREEDOM mission method. Expected outputs + based on 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv' model. """ def setUp(self): _clear_problem_names() # need to reset these to simulate separate runs - @require_pyoptsparse(optimizer="IPOPT") - def test_bench_GwGm(self): + @require_pyoptsparse(optimizer='IPOPT') + def test_bench_GwGm_IPOPT(self): local_phase_info = deepcopy(phase_info) prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_GwGm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', local_phase_info, optimizer='IPOPT', verbosity=0, ) - rtol = 0.01 + self.assertTrue(prob.result.success) + + rtol = 1e-3 # There are no truth values for these. assert_near_equal( prob.get_val(Mission.Design.GROSS_MASS, units='lbm'), - 174039.0, + 171646.48312684, tolerance=rtol, ) assert_near_equal( - prob.get_val(Aircraft.Design.OPERATING_MASS, units='lbm'), - 95509, + prob.get_val(Mission.Summary.OPERATING_MASS, units='lbm'), + 95100.07583783, tolerance=rtol, ) assert_near_equal( prob.get_val(Mission.Summary.TOTAL_FUEL_MASS, units='lbm'), - 41856.0, + 40546.40728901, tolerance=rtol, ) assert_near_equal( prob.get_val(Mission.Landing.GROUND_DISTANCE, units='ft'), - 2634.8, + 2655.5028412, tolerance=rtol, ) - assert_near_equal( - prob.get_val(Mission.Summary.RANGE, units='NM'), 3675.0, tolerance=rtol - ) + assert_near_equal(prob.get_val(Mission.Summary.RANGE, units='NM'), 3675.0, tolerance=rtol) assert_near_equal( prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'), - 136823.47, + 136098.07583783, tolerance=rtol, ) - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def test_bench_GwGm_SNOPT(self): local_phase_info = deepcopy(phase_info) prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_GwGm.csv', + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', local_phase_info, optimizer='SNOPT', verbosity=0, ) - rtol = 0.01 - - # There are no truth values for these. - assert_near_equal( - prob.get_val(Mission.Design.GROSS_MASS, units='lbm'), - 174039.0, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val(Aircraft.Design.OPERATING_MASS, units='lbm'), - 95509, - tolerance=rtol, - ) + self.assertTrue(prob.result.success) - assert_near_equal( - prob.get_val(Mission.Summary.TOTAL_FUEL_MASS, units='lbm'), - 42529.0, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val(Mission.Landing.GROUND_DISTANCE, units='ft'), - 2634.8, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val(Mission.Summary.RANGE, units='NM'), 3675.0, tolerance=rtol - ) - - assert_near_equal( - prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'), - 136823.47, - tolerance=rtol, - ) - - @require_pyoptsparse(optimizer="SNOPT") - def test_bench_GwGm_SNOPT_lbm_s(self): - local_phase_info = deepcopy(phase_info) - prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_GwGm_lbm_s.csv', - local_phase_info, - optimizer='SNOPT', - verbosity=0, - ) - - rtol = 0.01 + rtol = 1e-3 # There are no truth values for these. assert_near_equal( prob.get_val(Mission.Design.GROSS_MASS, units='lbm'), - 174039.0, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val(Aircraft.Design.OPERATING_MASS, units='lbm'), - 95509, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val(Mission.Summary.TOTAL_FUEL_MASS, units='lbm'), - 42529.0, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val(Mission.Landing.GROUND_DISTANCE, units='ft'), - 2634.8, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val(Mission.Summary.RANGE, units='NM'), 3675.0, tolerance=rtol - ) - - assert_near_equal( - prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'), - 136823.47, - tolerance=rtol, - ) - - @require_pyoptsparse(optimizer="IPOPT") - def test_bench_GwGm_shooting(self): - from aviary.interface.default_phase_info.two_dof_fiti import ( - phase_info, - phase_info_parameterization, - ) - - local_phase_info = deepcopy(phase_info) - prob = run_aviary( - 'models/test_aircraft/aircraft_for_bench_GwGm.csv', - local_phase_info, - optimizer='IPOPT', - run_driver=False, - analysis_scheme=AnalysisScheme.SHOOTING, - verbosity=0, - phase_info_parameterization=phase_info_parameterization, - ) - - rtol = 0.01 - - assert_near_equal( - prob.get_val(Mission.Design.RESERVE_FUEL, units='lbm'), 4998, tolerance=rtol - ) - - assert_near_equal( - prob.get_val(Mission.Design.GROSS_MASS, units='lbm'), - 174039.0, + 171646.48312684, tolerance=rtol, ) assert_near_equal( - prob.get_val(Aircraft.Design.OPERATING_MASS, units='lbm'), - 95509, + prob.get_val(Mission.Summary.OPERATING_MASS, units='lbm'), + 95100.07583783, tolerance=rtol, ) assert_near_equal( prob.get_val(Mission.Summary.TOTAL_FUEL_MASS, units='lbm'), - 43574.0, + 40546.40728901, tolerance=rtol, ) assert_near_equal( prob.get_val(Mission.Landing.GROUND_DISTANCE, units='ft'), - 2623.4, + 2655.5028412, tolerance=rtol, ) - assert_near_equal( - prob.get_val(Mission.Summary.RANGE, units='NM'), 3675.0, tolerance=rtol - ) + assert_near_equal(prob.get_val(Mission.Summary.RANGE, units='NM'), 3675.0, tolerance=rtol) assert_near_equal( prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'), - 136823.47, - tolerance=rtol, - ) - - assert_near_equal( - prob.get_val( - 'traj.cruise_' + Dynamic.Mission.DISTANCE + '_final', units='nmi' - ), - 3668.3, + 136098.07583783, tolerance=rtol, ) @@ -234,4 +120,4 @@ def test_bench_GwGm_shooting(self): # unittest.main() test = ProblemPhaseTestCase() test.setUp() - test.test_bench_GwGm_shooting() + test.test_bench_GwGm_SNOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_electrified_large_turboprop_freighter.py b/aviary/validation_cases/benchmark_tests/test_bench_electrified_large_turboprop_freighter.py new file mode 100644 index 0000000000..79a86c7185 --- /dev/null +++ b/aviary/validation_cases/benchmark_tests/test_bench_electrified_large_turboprop_freighter.py @@ -0,0 +1,88 @@ +import unittest + +import openmdao.api as om +from openmdao.utils.testing_utils import use_tempdirs + +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.models.aircraft.large_turboprop_freighter.phase_info import energy_phase_info +from aviary.subsystems.propulsion.motor.motor_builder import MotorBuilder +from aviary.subsystems.propulsion.turboprop_model import TurbopropModel +from aviary.utils.process_input_decks import create_vehicle +from aviary.variable_info.variables import Aircraft, Mission, Settings + + +@use_tempdirs +# TODO need to add asserts with "truth" values +class LargeElectrifiedTurbopropFreighterBenchmark(unittest.TestCase): + def build_and_run_problem(self): + # Build problem + prob = AviaryProblem(verbosity=0) + + # load inputs from .csv to build engine + options, guesses = create_vehicle( + 'models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv' + ) + + options.set_val(Settings.EQUATIONS_OF_MOTION, 'height_energy') + # options.set_val(Aircraft.Engine.NUM_ENGINES, 2) + # options.set_val(Aircraft.Engine.WING_LOCATIONS, 0.385) + scale_factor = 3 + options.set_val(Aircraft.Engine.RPM_DESIGN, 6000, 'rpm') + options.set_val(Aircraft.Engine.FIXED_RPM, 6000, 'rpm') + options.set_val(Aircraft.Engine.Gearbox.GEAR_RATIO, 5.88) + options.set_val(Aircraft.Engine.Gearbox.EFFICIENCY, 1.0) + options.set_val(Aircraft.Engine.SCALE_FACTOR, scale_factor) # 11.87) + options.set_val( + Aircraft.Engine.SCALED_SLS_THRUST, + options.get_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 'lbf') * scale_factor, + 'lbf', + ) + + # turboprop = TurbopropModel('turboprop', options=options) + # turboprop2 = TurbopropModel('turboprop2', options=options) + + motor = MotorBuilder( + 'motor', + ) + + electroprop = TurbopropModel('electroprop', options=options, shaft_power_model=motor) + + # load_inputs needs to be updated to accept an already existing aviary options + prob.load_inputs( + options, # "models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv", + energy_phase_info, + engine_builders=[electroprop], + ) + prob.aviary_inputs.set_val(Settings.VERBOSITY, 2) + + # FLOPS aero specific stuff? Best guesses for values here + prob.aviary_inputs.set_val(Mission.Constraints.MAX_MACH, 0.5) + prob.aviary_inputs.set_val(Aircraft.Wing.AREA, 1744.59, 'ft**2') + # prob.aviary_inputs.set_val(Aircraft.Wing.ASPECT_RATIO, 10.078) + prob.aviary_inputs.set_val( + Aircraft.Wing.THICKNESS_TO_CHORD, 0.1500 + ) # average between root and chord T/C + prob.aviary_inputs.set_val(Aircraft.Fuselage.MAX_WIDTH, 4.3, 'm') + prob.aviary_inputs.set_val(Aircraft.Fuselage.MAX_HEIGHT, 3.95, 'm') + prob.aviary_inputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, 4.125, 'm') + + prob.check_and_preprocess_inputs() + + prob.build_model() + prob.add_driver('IPOPT', max_iter=0, verbosity=0) + prob.add_design_variables() + prob.add_objective() + + prob.setup() + # prob.model.list_vars(units=True, print_arrays=True) + om.n2(prob) + + prob.run_aviary_problem() + self.assertTrue(prob.result.success) + + om.n2(prob) + + +if __name__ == '__main__': + test = LargeElectrifiedTurbopropFreighterBenchmark() + test.build_and_run_problem() diff --git a/aviary/models/large_turboprop_freighter/test_bench_large_turboprop_freighter.py b/aviary/validation_cases/benchmark_tests/test_bench_large_turboprop_freighter.py similarity index 50% rename from aviary/models/large_turboprop_freighter/test_bench_large_turboprop_freighter.py rename to aviary/validation_cases/benchmark_tests/test_bench_large_turboprop_freighter.py index cfd330d1d4..0ab9a5ab48 100644 --- a/aviary/models/large_turboprop_freighter/test_bench_large_turboprop_freighter.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_large_turboprop_freighter.py @@ -1,57 +1,49 @@ -import numpy as np import unittest -from numpy.testing import assert_almost_equal from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.models.aircraft.large_turboprop_freighter.phase_info import two_dof_phase_info from aviary.subsystems.propulsion.turboprop_model import TurbopropModel from aviary.utils.process_input_decks import create_vehicle -from aviary.variable_info.variables import Aircraft, Mission, Settings - -from aviary.models.large_turboprop_freighter.phase_info import phase_info +from aviary.variable_info.variables import Aircraft, Mission @use_tempdirs -@unittest.skip("Skipping until all builders are updated with get_parameters()") -# TODO need to add asserts with "truth" values +# TODO need to add asserts with "truth" values, only verifying no errors here class LargeTurbopropFreighterBenchmark(unittest.TestCase): - def build_and_run_problem(self): - # Build problem - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) # load inputs from .csv to build engine options, _ = create_vehicle( - "models/large_turboprop_freighter/large_turboprop_freighter.csv" + 'models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv' ) turboprop = TurbopropModel('turboprop', options=options) # load_inputs needs to be updated to accept an already existing aviary options prob.load_inputs( - "models/large_turboprop_freighter/large_turboprop_freighter.csv", - phase_info, + 'models/aircraft/large_turboprop_freighter/large_turboprop_freighter_GASP.csv', + two_dof_phase_info, engine_builders=[turboprop], ) - # FLOPS aero specific stuff? Best guesses for values here - # prob.aviary_inputs.set_val(Mission.Constraints.MAX_MACH, 0.5) - # prob.aviary_inputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, 4.125, 'm') + prob.aviary_inputs.set_val(Mission.Constraints.MAX_MACH, 0.5) + prob.aviary_inputs.set_val(Aircraft.Fuselage.AVG_DIAMETER, 4.125, 'm') prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() - prob.add_driver("SLSQP", max_iter=0, verbosity=0) + + prob.build_model() + prob.add_driver('IPOPT', max_iter=0, verbosity=0) prob.add_design_variables() prob.add_objective() prob.setup() - prob.set_initial_guesses() + prob.run_aviary_problem() - prob.run_aviary_problem("dymos_solution.db", make_plots=False) + self.assertTrue(prob.result.success) + # om.n2(prob) if __name__ == '__main__': diff --git a/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py b/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py index 05093fc0b5..a51dfddd87 100644 --- a/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py +++ b/aviary/validation_cases/benchmark_tests/test_bench_multiengine.py @@ -1,52 +1,59 @@ -from copy import deepcopy import unittest +from copy import deepcopy +import numpy as np import openmdao.api as om from openmdao.core.problem import _clear_problem_names from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.interface.default_phase_info.height_energy import phase_info +from aviary.models.missions.height_energy_default import phase_info from aviary.interface.methods_for_level2 import AviaryProblem -from aviary.models.multi_engine_single_aisle.multi_engine_single_aisle_data import inputs, engine_1_inputs, engine_2_inputs +from aviary.models.aircraft.multi_engine_single_aisle.multi_engine_single_aisle_data import ( + engine_1_inputs, + engine_2_inputs, + inputs, +) from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.variable_info.enums import ThrottleAllocation - +from aviary.variable_info.variables import Aircraft # Build problem local_phase_info = deepcopy(phase_info) -local_phase_info['climb']['user_options']['optimize_mach'] = False -local_phase_info['climb']['user_options']['optimize_altitude'] = False +local_phase_info['climb']['user_options']['mach_optimize'] = False +local_phase_info['climb']['user_options']['mach_polynomial_order'] = 1 +local_phase_info['climb']['user_options']['altitude_optimize'] = False +local_phase_info['climb']['user_options']['altitude_polynomial_order'] = 1 local_phase_info['climb']['user_options']['no_descent'] = True -local_phase_info['climb']['user_options']['use_polynomial_control'] = True -local_phase_info['cruise']['user_options']['optimize_mach'] = False -local_phase_info['cruise']['user_options']['optimize_altitude'] = False -local_phase_info['cruise']['user_options']['altitude_bounds'] = ( - (32000.0, 34000.0), "ft") +local_phase_info['cruise']['user_options']['mach_optimize'] = False +local_phase_info['cruise']['user_options']['mach_polynomial_order'] = 1 +local_phase_info['cruise']['user_options']['altitude_optimize'] = False +local_phase_info['cruise']['user_options']['altitude_polynomial_order'] = 1 +local_phase_info['cruise']['user_options']['altitude_bounds'] = ((32000.0, 34000.0), 'ft') local_phase_info['cruise']['user_options']['throttle_enforcement'] = 'path_constraint' -local_phase_info['cruise']['user_options']['use_polynomial_control'] = True -local_phase_info['descent']['user_options']['optimize_mach'] = False -local_phase_info['descent']['user_options']['optimize_altitude'] = False +local_phase_info['descent']['user_options']['mach_optimize'] = False +local_phase_info['descent']['user_options']['mach_polynomial_order'] = 1 +local_phase_info['descent']['user_options']['altitude_optimize'] = False +local_phase_info['descent']['user_options']['altitude_polynomial_order'] = 1 local_phase_info['descent']['user_options']['no_climb'] = True -local_phase_info['descent']['user_options']['use_polynomial_control'] = True + +inputs.set_val(Aircraft.Nacelle.LAMINAR_FLOW_LOWER, np.zeros(2)) +inputs.set_val(Aircraft.Nacelle.LAMINAR_FLOW_UPPER, np.zeros(2)) @use_tempdirs class MultiengineTestcase(unittest.TestCase): - """ - Test the different throttle allocation methods for models with multiple, unique EngineModels. - """ + """Test the different throttle allocation methods for models with multiple, unique EngineModels.""" def setUp(self): om.clear_reports() _clear_problem_names() # need to reset these to simulate separate runs - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def test_multiengine_fixed(self): - test_phase_info = deepcopy(local_phase_info) method = ThrottleAllocation.FIXED @@ -54,30 +61,29 @@ def test_multiengine_fixed(self): test_phase_info['cruise']['user_options']['throttle_allocation'] = method test_phase_info['descent']['user_options']['throttle_allocation'] = method - engine1 = build_engine_deck(engine_1_inputs)[0] + engine1 = build_engine_deck(engine_1_inputs) engine1.name = 'engine_1' - engine2 = build_engine_deck(engine_2_inputs)[0] + engine2 = build_engine_deck(engine_2_inputs) engine2.name = 'engine_2' - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs(inputs, test_phase_info, engine_builders=[engine1, engine2]) prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() - prob.add_driver("SNOPT", max_iter=50, use_coloring=True) + prob.build_model() + + prob.add_driver('SNOPT', max_iter=50, use_coloring=True) prob.add_design_variables() prob.add_objective() prob.setup() - prob.set_initial_guesses() - prob.run_aviary_problem("dymos_solution.db", suppress_solver_print=True) + prob.run_aviary_problem(suppress_solver_print=True) + + self.assertTrue(prob.result.success) alloc_climb = prob.get_val('traj.climb.parameter_vals:throttle_allocations') alloc_cruise = prob.get_val('traj.cruise.parameter_vals:throttle_allocations') @@ -87,9 +93,8 @@ def test_multiengine_fixed(self): assert_near_equal(alloc_cruise[0], 0.5, tolerance=1e-3) assert_near_equal(alloc_descent[0], 0.5, tolerance=1e-3) - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def test_multiengine_static(self): - test_phase_info = deepcopy(local_phase_info) method = ThrottleAllocation.STATIC @@ -97,40 +102,35 @@ def test_multiengine_static(self): test_phase_info['cruise']['user_options']['throttle_allocation'] = method test_phase_info['descent']['user_options']['throttle_allocation'] = method - engine1 = build_engine_deck(engine_1_inputs)[0] - engine2 = build_engine_deck(engine_2_inputs)[0] + engine1 = build_engine_deck(engine_1_inputs) + engine2 = build_engine_deck(engine_2_inputs) - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) prob.load_inputs(inputs, test_phase_info, engine_builders=[engine1, engine2]) prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() - prob.add_driver("SNOPT", max_iter=50, use_coloring=True) + prob.build_model() + + prob.add_driver('SNOPT', max_iter=50, use_coloring=True) prob.add_design_variables() prob.add_objective() prob.setup() - prob.set_initial_guesses() - prob.run_aviary_problem("dymos_solution.db", suppress_solver_print=True) + prob.run_aviary_problem(suppress_solver_print=True) alloc_climb = prob.get_val('traj.climb.parameter_vals:throttle_allocations') alloc_cruise = prob.get_val('traj.cruise.parameter_vals:throttle_allocations') alloc_descent = prob.get_val('traj.descent.parameter_vals:throttle_allocations') assert_near_equal(alloc_climb[0], 0.5, tolerance=1e-2) - assert_near_equal(alloc_cruise[0], 0.64, tolerance=1e-2) - assert_near_equal(alloc_descent[0], 0.999, tolerance=1e-2) + assert_near_equal(alloc_cruise[0], 0.593, tolerance=1e-2) - @require_pyoptsparse(optimizer="SNOPT") + @require_pyoptsparse(optimizer='SNOPT') def test_multiengine_dynamic(self): - test_phase_info = deepcopy(local_phase_info) method = ThrottleAllocation.DYNAMIC @@ -138,39 +138,35 @@ def test_multiengine_dynamic(self): test_phase_info['cruise']['user_options']['throttle_allocation'] = method test_phase_info['descent']['user_options']['throttle_allocation'] = method - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) - engine1 = build_engine_deck(engine_1_inputs)[0] - engine2 = build_engine_deck(engine_2_inputs)[0] + engine1 = build_engine_deck(engine_1_inputs) + engine2 = build_engine_deck(engine_2_inputs) prob.load_inputs(inputs, test_phase_info, engine_builders=[engine1, engine2]) prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - prob.add_phases() - prob.add_post_mission_systems() - prob.link_phases() - prob.add_driver("SNOPT", max_iter=50, use_coloring=True) + prob.build_model() + + prob.add_driver('SNOPT', max_iter=50, use_coloring=True) prob.add_design_variables() prob.add_objective() prob.setup() - prob.set_initial_guesses() - prob.run_aviary_problem("dymos_solution.db", suppress_solver_print=True) + prob.run_aviary_problem(suppress_solver_print=True) alloc_climb = prob.get_val('traj.climb.controls:throttle_allocations') alloc_cruise = prob.get_val('traj.cruise.controls:throttle_allocations') alloc_descent = prob.get_val('traj.descent.controls:throttle_allocations') # Cruise is pretty constant, check exact value. - assert_near_equal(alloc_cruise[0], 0.646, tolerance=1e-2) + assert_near_equal(alloc_cruise[0], 0.595, tolerance=1e-2) # Check general trend: favors engine 1. self.assertGreater(alloc_climb[2], 0.55) - self.assertGreater(alloc_descent[3], 0.65) if __name__ == '__main__': diff --git a/aviary/validation_cases/benchmark_tests/test_bench_multimission.py b/aviary/validation_cases/benchmark_tests/test_bench_multimission.py new file mode 100644 index 0000000000..110e1317ab --- /dev/null +++ b/aviary/validation_cases/benchmark_tests/test_bench_multimission.py @@ -0,0 +1,53 @@ +import unittest +import openmdao.api as om +from openmdao.core.problem import _clear_problem_names +from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs + +from aviary.examples.multi_mission.run_multimission_example import multi_mission_example + + +@use_tempdirs +class MultiMissionTestcase(unittest.TestCase): + """Test the different throttle allocation methods for models with multiple, unique EngineModels.""" + + def setUp(self): + om.clear_reports() + _clear_problem_names() # need to reset these to simulate separate runs + + @require_pyoptsparse(optimizer='IPOPT') + def test_multimission(self): + prob = multi_mission_example() + + objective = prob.get_val('composite_objective', units=None) + objective_expected_value = 24851.7 + + mission1_fuel = prob.get_val('mission1.mission:summary:fuel_burned', units='lbm') + mission1_fuel_expected_value = 26211.5 + + mission2_fuel = prob.get_val('mission2.mission:summary:fuel_burned', units='lbm') + mission2_fuel_expected_value = 22132.2 + + mission1_cargo = prob.get_val( + 'mission1.aircraft:crew_and_payload:total_payload_mass', units='lbm' + ) + mission1_cargo_expected_value = 36477.0 + + mission2_cargo = prob.get_val( + 'mission2.aircraft:crew_and_payload:total_payload_mass', units='lbm' + ) + mission2_cargo_expected_value = 4277.0 + + # alloc_climb = prob.get_val('traj.climb.parameter_vals:throttle_allocations', units='') + + self.assertTrue(prob.result.success) + + assert_near_equal(objective_expected_value, objective, tolerance=1e-3) + assert_near_equal(mission1_fuel_expected_value, mission1_fuel, tolerance=1e-3) + assert_near_equal(mission2_fuel_expected_value, mission2_fuel, tolerance=1e-3) + assert_near_equal(mission1_cargo_expected_value, mission1_cargo, tolerance=1e-3) + assert_near_equal(mission2_cargo_expected_value, mission2_cargo, tolerance=1e-3) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_off_design.py b/aviary/validation_cases/benchmark_tests/test_bench_off_design.py new file mode 100644 index 0000000000..d4d27aeb01 --- /dev/null +++ b/aviary/validation_cases/benchmark_tests/test_bench_off_design.py @@ -0,0 +1,562 @@ +import unittest +from copy import deepcopy + +from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs + +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.models.missions.height_energy_default import phase_info as energy_phase_info +from aviary.models.missions.two_dof_default import phase_info as twodof_phase_info +from aviary.variable_info.variables import Aircraft, Mission, Settings + + +@use_tempdirs +class TestHeightEnergyOffDesign(unittest.TestCase): + """Test off-design capability for both fallout and alternate missions.""" + + def setUp(self): + # run design case + prob = self.prob = AviaryProblem(verbosity=0) + copy_energy_phase_info = deepcopy(energy_phase_info) + copy_energy_phase_info['post_mission']['target_range'] = (2500.0, 'nmi') + + prob.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', copy_energy_phase_info + ) + + # define passengers of every seat class so we can change their values later + prob.aviary_inputs.set_val(Aircraft.CrewPayload.Design.NUM_PASSENGERS, 169) + prob.aviary_inputs.set_val(Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, 144) + prob.aviary_inputs.set_val(Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, 15) + prob.aviary_inputs.set_val(Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, 10) + + # Preprocess inputs + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() + prob.add_phases() + prob.add_post_mission_systems() + + # Link phases and variables + prob.link_phases() + prob.add_driver('SNOPT', max_iter=20) + prob.add_design_variables() + + # Load optimization problem formulation + # Detail which variables the optimizer can control + prob.add_objective() + prob.setup() + prob.set_initial_guesses() + prob.run_aviary_problem() + + def compare_results(self, comparison_prob): + # compares provided problem with design problem + prob_var_list = [ + Mission.Design.RANGE, + Mission.Summary.RANGE, + Mission.Summary.FUEL_MASS, + Mission.Summary.TOTAL_FUEL_MASS, + Mission.Summary.OPERATING_MASS, + Aircraft.CrewPayload.CARGO_MASS, + Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, + Mission.Design.GROSS_MASS, + Mission.Summary.GROSS_MASS, + Aircraft.Design.EMPTY_MASS, + Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, + ] + + inputs_var_list = [ + Aircraft.CrewPayload.NUM_TOURIST_CLASS, + Aircraft.CrewPayload.NUM_BUSINESS_CLASS, + Aircraft.CrewPayload.NUM_FIRST_CLASS, + Aircraft.CrewPayload.NUM_PASSENGERS, + ] + + for var in prob_var_list: + assert_near_equal(comparison_prob.get_val(var), self.prob.get_val(var), tolerance=1e-6) + + for var in inputs_var_list: + assert_near_equal( + comparison_prob.aviary_inputs.get_val(var), + self.prob.aviary_inputs.get_val(var), + tolerance=1e-12, + ) + + @require_pyoptsparse(optimizer='SNOPT') + def test_fallout_mission_match(self): + # run a fallout mission with no changes, essentially recreating the design mission with + # different constraints/design variables + prob_fallout = self.prob.run_off_design_mission(problem_type='fallout') + self.compare_results(prob_fallout) + + @require_pyoptsparse(optimizer='SNOPT') + def test_fallout_mission_changed(self): + # run a fallout mission with modified payload and gross mass (and therefore different fuel) + prob_fallout = self.prob.run_off_design_mission( + problem_type='fallout', + cargo_mass=5000, + mission_gross_mass=150_000, + num_first_class=1, + num_business=5, + num_tourist=75, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Design.RANGE), + self.prob.get_val(Mission.Design.RANGE), + tolerance=1e-12, + ) + assert_near_equal(prob_fallout.get_val(Mission.Summary.RANGE), 2438.6, tolerance=1e-3) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.FUEL_MASS, 'lbm'), + 46161.85, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.TOTAL_FUEL_MASS, 'lbm'), + 29031.74, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.OPERATING_MASS, 'lbm'), + 97743.26, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Aircraft.CrewPayload.CARGO_MASS, 'lbm'), + 5000, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm'), + 23225, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), + 18225, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + self.prob.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Design.GROSS_MASS, 'lbm'), + self.prob.get_val(Mission.Design.GROSS_MASS, 'lbm'), + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.GROSS_MASS, 'lbm'), + 150000, + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_FIRST_CLASS), + 1, + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS), + 5, + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS), + 75, + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_PASSENGERS), + 81, + tolerance=1e-12, + ) + + @require_pyoptsparse(optimizer='SNOPT') + def test_alternate_mission_match(self): + # run an alternate mission with no changes, essentially recreating the design mission with + # different constraints/design variables + prob_alternate = self.prob.run_off_design_mission(problem_type='alternate') + self.compare_results(prob_alternate) + + @require_pyoptsparse(optimizer='SNOPT') + def test_alternate_mission_changed(self): + # run an alternate mission with modified range and payload + prob_alternate = self.prob.run_off_design_mission( + problem_type='alternate', + cargo_mass=2500, + mission_range=1800, + num_first_class=1, + num_business=5, + num_tourist=144, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Design.RANGE), + self.prob.get_val(Mission.Design.RANGE), + tolerance=1e-12, + ) + assert_near_equal(prob_alternate.get_val(Mission.Summary.RANGE), 1800, tolerance=1e-6) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.FUEL_MASS, 'lbm'), + 33136.79, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.TOTAL_FUEL_MASS, 'lbm'), + 23661.46, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.OPERATING_MASS, 'lbm'), + 97743.32, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Aircraft.CrewPayload.CARGO_MASS, 'lbm'), + 2500, + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm'), + 36250, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), + 33750, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + self.prob.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Design.GROSS_MASS, 'lbm'), + self.prob.get_val(Mission.Design.GROSS_MASS, 'lbm'), + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.GROSS_MASS, 'lbm'), + 157654.78, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_FIRST_CLASS), + 1, + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS), + 5, + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_TOURIST_CLASS), + 144, + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_PASSENGERS), + 150, + tolerance=1e-12, + ) + + +@use_tempdirs +class Test2DOFOffDesign(unittest.TestCase): + """Test off-design capability for both fallout and alternate missions.""" + + # TODO this test needs more manual verification to root out any remaining bugs + + def setUp(self): + # run design case + prob = self.prob = AviaryProblem(verbosity=0) + + copy_twodof_phase_info = deepcopy(twodof_phase_info) + + prob.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', copy_twodof_phase_info + ) + + # Preprocess inputs + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() + prob.add_phases() + prob.add_post_mission_systems() + + # Link phases and variables + prob.link_phases() + prob.add_driver('SNOPT', max_iter=20) + prob.add_design_variables() + + # Load optimization problem formulation + # Detail which variables the optimizer can control + prob.add_objective() + prob.setup() + prob.set_initial_guesses() + prob.run_aviary_problem() + + def compare_results(self, comparison_prob): + # compares provided problem with design problem + prob_var_list = [ + Mission.Summary.RANGE, + Mission.Summary.FUEL_MASS, + Mission.Summary.TOTAL_FUEL_MASS, + Mission.Summary.OPERATING_MASS, + Aircraft.CrewPayload.CARGO_MASS, + Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, + Mission.Design.GROSS_MASS, + Mission.Summary.GROSS_MASS, + # currently not a GASP variable + # Aircraft.Design.EMPTY_MASS, + Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, + ] + + inputs_var_list = [ + (Mission.Design.RANGE, 'nmi'), + (Aircraft.CrewPayload.NUM_PASSENGERS, 'unitless'), + ] + + for var in prob_var_list: + assert_near_equal(comparison_prob.get_val(var), self.prob.get_val(var), tolerance=1e-6) + + for var in inputs_var_list: + assert_near_equal( + comparison_prob.aviary_inputs.get_val(var[0], var[1]), + self.prob.aviary_inputs.get_val(var[0], var[1]), + tolerance=1e-12, + ) + + @require_pyoptsparse(optimizer='SNOPT') + def test_fallout_mission_match(self): + # run a fallout mission with no changes, essentially recreating the design mission with + # different constraints/design variables + prob_fallout = self.prob.run_off_design_mission(problem_type='fallout') + self.compare_results(prob_fallout) + + @require_pyoptsparse(optimizer='SNOPT') + def test_fallout_mission_changed(self): + # run a fallout mission with modified payload and gross mass (and therefore different fuel) + prob = self.prob + prob_fallout = prob.run_off_design_mission( + problem_type='fallout', + cargo_mass=5000, + mission_gross_mass=155000.0, + num_pax=75, + ) + assert_near_equal( + prob_fallout.aviary_inputs.get_val(Mission.Design.RANGE, 'nmi'), + prob.aviary_inputs.get_val(Mission.Design.RANGE, 'nmi'), + tolerance=1e-12, + ) + assert_near_equal(prob_fallout.get_val(Mission.Summary.RANGE), 3988.58, tolerance=1e-4) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.FUEL_MASS, 'lbm'), + 40546.40, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.TOTAL_FUEL_MASS, 'lbm'), + 39899.924, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.OPERATING_MASS, 'lbm'), + 95100.08, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Aircraft.CrewPayload.CARGO_MASS, 'lbm'), + 5000, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm'), + 20000, + tolerance=1e-6, + ) + assert_near_equal( + prob_fallout.get_val(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), + 15000, + tolerance=1e-6, + ) + # currently not a GASP variable + # assert_near_equal( + # prob_fallout.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + # prob.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + # tolerance=1e-12, + # ) + assert_near_equal( + prob_fallout.get_val(Mission.Design.GROSS_MASS, 'lbm'), + prob.get_val(Mission.Design.GROSS_MASS, 'lbm'), + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.get_val(Mission.Summary.GROSS_MASS, 'lbm'), + 155000, + tolerance=1e-12, + ) + assert_near_equal( + prob_fallout.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_PASSENGERS), + 75, + tolerance=1e-12, + ) + + @require_pyoptsparse(optimizer='SNOPT') + def test_alternate_mission_match(self): + # run an alternate mission with no changes, essentially recreating the design mission with + # different constraints/design variables + prob_alternate = self.prob.run_off_design_mission(problem_type='alternate') + self.compare_results(prob_alternate) + + @require_pyoptsparse(optimizer='SNOPT') + def test_alternate_mission_changed(self): + # run an alternate mission with modified range and payload + prob = self.prob + alternate_phase_info = deepcopy(twodof_phase_info) + alternate_phase_info['desc1']['time_duration_bounds'] = ((200.0, 900.0), 's') + + prob_alternate = prob.run_off_design_mission( + problem_type='alternate', + cargo_mass=2100, + mission_range=1800, + num_pax=150, + ) + assert_near_equal( + prob_alternate.aviary_inputs.get_val(Mission.Design.RANGE, 'nmi'), + prob.aviary_inputs.get_val(Mission.Design.RANGE, 'nmi'), + tolerance=1e-12, + ) + assert_near_equal(prob_alternate.get_val(Mission.Summary.RANGE), 1800, tolerance=1e-6) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.FUEL_MASS, 'lbm'), + 40546.40, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.TOTAL_FUEL_MASS, 'lbm'), + 21499.71, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.OPERATING_MASS, 'lbm'), + 95100.08, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Aircraft.CrewPayload.CARGO_MASS, 'lbm'), + 2100, + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.get_val(Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, 'lbm'), + 32100, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.get_val(Aircraft.CrewPayload.PASSENGER_PAYLOAD_MASS, 'lbm'), + 30000, + tolerance=1e-6, + ) + # currently not a GASP variable + # assert_near_equal( + # prob_alternate.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + # prob.get_val(Aircraft.Design.EMPTY_MASS, 'lbm'), + # tolerance=1e-12, + # ) + assert_near_equal( + prob_alternate.get_val(Mission.Design.GROSS_MASS, 'lbm'), + prob.get_val(Mission.Design.GROSS_MASS, 'lbm'), + tolerance=1e-12, + ) + assert_near_equal( + prob_alternate.get_val(Mission.Summary.GROSS_MASS, 'lbm'), + 148699.79, + tolerance=1e-6, + ) + assert_near_equal( + prob_alternate.aviary_inputs.get_val(Aircraft.CrewPayload.NUM_PASSENGERS), + 150, + tolerance=1e-12, + ) + + +@use_tempdirs +class PayloadRangeTest(unittest.TestCase): + @require_pyoptsparse(optimizer='SNOPT') + def test_payload_range(self): + # run design case + prob = self.prob = AviaryProblem(verbosity=0) + phase_info = deepcopy(energy_phase_info) + + phase_info['post_mission']['target_range'] = (2500.0, 'nmi') + phase_info['climb']['user_options']['time_duration_bounds'] = ((20.0, 90.0), 'min') + phase_info['cruise']['user_options']['time_initial_bounds'] = ((20.0, 192.0), 'min') + phase_info['descent']['user_options']['time_duration_bounds'] = ( + (25.0, 60.0), + 'min', + ) + prob.load_inputs('models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info) + # prob.aviary_inputs.set_val(Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT, True) + + # Preprocess inputs + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() + prob.add_phases() + prob.add_post_mission_systems() + + # Link phases and variables + prob.link_phases() + prob.add_driver('SNOPT', max_iter=20) + prob.add_design_variables() + + # Load optimization problem formulation + # Detail which variables the optimizer can control + prob.add_objective() + prob.setup() + prob.set_initial_guesses() + prob.run_aviary_problem() + off_design_probs = prob.run_payload_range() + # test outputted payload-range data + assert_near_equal( + prob.payload_range_data.get_val('Payload', 'lbm'), + [ + 38025.0, + 38025.0, + 24365.60919974074, + 0, + ], + tolerance=1e-10, + ) + assert_near_equal( + prob.payload_range_data.get_val('Fuel', 'lbm'), + [0, 28108.99, 42192.70, 42192.70], + tolerance=1e-6, + ) + assert_near_equal( + prob.payload_range_data.get_val('Range', 'NM'), + [0, 2500, 3973.34, 4421.13575083], + tolerance=1e-6, + ) + + # verify TOGW for each off-design problem + assert_near_equal( + off_design_probs[0].get_val(Mission.Summary.GROSS_MASS, 'lbm'), + 165896.26754754, + tolerance=1e-12, + ) + assert_near_equal( + off_design_probs[1].get_val(Mission.Summary.GROSS_MASS, 'lbm'), + 140540.92087337, + tolerance=1e-12, + ) + + +if __name__ == '__main__': + # unittest.main() + test = Test2DOFOffDesign() + test.setUp() + test.test_alternate_mission_changed() + + # test = PayloadRangeTest() + # test.test_payload_range() diff --git a/aviary/validation_cases/benchmark_tests/test_bench_optimize_throttle.py b/aviary/validation_cases/benchmark_tests/test_bench_optimize_throttle.py new file mode 100644 index 0000000000..f4bf5388da --- /dev/null +++ b/aviary/validation_cases/benchmark_tests/test_bench_optimize_throttle.py @@ -0,0 +1,149 @@ +import unittest +from copy import deepcopy + +import numpy as np + +import openmdao.api as om +from openmdao.core.problem import _clear_problem_names +from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs + +from aviary.api import Mission +from aviary.interface.methods_for_level2 import AviaryProblem +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings + +phase_info = { + 'pre_mission': {'include_takeoff': False, 'optimize_mass': True}, + 'climb': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.2, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.18, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_initial': (0.0, 'ft'), + 'altitude_final': (32000.0, 'ft'), + 'altitude_bounds': ((0.0, 32000.0), 'ft'), + 'altitude_polynomial_order': 3, + 'mass_ref': (2.0e5, 'lbm'), + 'throttle_enforcement': 'control', + 'throttle_optimize': True, + 'time_initial': (0.0, 's'), + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((32.0, 128.0), 'min'), + }, + 'initial_guesses': { + 'throttle': ([1.0, 1.0], 'unitless'), + }, + }, + 'cruise': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.72, 0.72), 'unitless'), + 'mach_polynomial_order': 3, + 'altitude_optimize': False, + 'altitude_initial': (32000.0, 'ft'), + 'altitude_final': (34000.0, 'ft'), + 'altitude_bounds': ((32000.0, 34000.0), 'ft'), + 'altitude_polynomial_order': 1, + 'mass_ref': (2.0e5, 'lbm'), + 'distance_ref': (1906, 'nmi'), + 'throttle_enforcement': 'control', + 'throttle_optimize': True, + 'throttle_polynomial_order': 1, + 'time_initial_bounds': ((32.0, 128.0), 'min'), + 'time_duration_bounds': ((60.5, 240.0), 'min'), + }, + 'initial_guesses': { + 'throttle': ([0.8, 0.8], 'unitless'), + }, + }, + 'descent': { + 'subsystem_options': {'core_aerodynamics': {'method': 'computed'}}, + 'user_options': { + 'num_segments': 5, + 'order': 3, + 'mach_optimize': False, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.36, 'unitless'), + 'mach_bounds': ((0.34, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_initial': (34000.0, 'ft'), + 'altitude_final': (500.0, 'ft'), + 'altitude_bounds': ((500.0, 34000.0), 'ft'), + 'altitude_polynomial_order': 3, + 'distance_ref': (1906, 'nmi'), + 'mass_ref': (2.0e5, 'lbm'), + 'throttle_enforcement': 'control', + 'throttle_optimize': True, + 'time_initial_bounds': ((90.0, 361.5), 'min'), + 'time_duration_bounds': ((29.0, 87.0), 'min'), + }, + 'initial_guesses': { + 'throttle': ([0.0, 0.0], 'unitless'), + }, + }, + 'post_mission': { + 'include_landing': True, + 'constrain_range': True, + 'target_range': (1906.0, 'nmi'), + }, +} + + +@use_tempdirs +class OptimizeThrottleTestCase(unittest.TestCase): + """Basic test of feature.""" + + def setUp(self): + om.clear_reports() + _clear_problem_names() # need to reset these to simulate separate runs + + @require_pyoptsparse(optimizer='SNOPT') + def test_throttle_optimize_SNOPT(self): + prob = AviaryProblem() + + prob.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_FwFm.csv', + phase_info, + verbosity=0, + ) + + prob.aviary_inputs.set_val(Settings.VERBOSITY, 0) + + prob.check_and_preprocess_inputs() + prob.add_pre_mission_systems() + prob.add_phases() + prob.add_post_mission_systems() + prob.link_phases() + + prob.add_driver('SNOPT', max_iter=50) + prob.driver.opt_settings['Major optimality tolerance'] = 1e-4 + prob.driver.opt_settings['Major feasibility tolerance'] = 1e-4 + + prob.add_design_variables() + prob.add_objective(objective_type='fuel_burned') + + prob.setup() + + prob.run_aviary_problem(simulate=False) + + self.assertTrue(prob.result.success) + + gross_mass = prob.get_val(Mission.Summary.GROSS_MASS, units='lbm') + assert_near_equal(gross_mass, 160506.0, tolerance=1e-3) + + cruise_throttle = prob.get_val('traj.cruise.timeseries.throttle') + assert_near_equal(cruise_throttle[-1], 0.6925, tolerance=1e-2) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/validation_cases/benchmark_tests/test_bwb_GwGm.py b/aviary/validation_cases/benchmark_tests/test_bwb_GwGm.py new file mode 100644 index 0000000000..995adee3ad --- /dev/null +++ b/aviary/validation_cases/benchmark_tests/test_bwb_GwGm.py @@ -0,0 +1,76 @@ +import unittest +from copy import deepcopy + +from openmdao.core.problem import _clear_problem_names +from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs + +from aviary.models.aircraft.blended_wing_body.generic_BWB_2dof_phase_info import phase_info + +from aviary.interface.methods_for_level1 import run_aviary +from aviary.variable_info.variables import Mission + + +@use_tempdirs +class ProblemPhaseTestCase(unittest.TestCase): + """ + Test the setup and run of a BWB aircraft using GASP mass and aero method + and TWO_DEGREES_OF_FREEDOM mission method. Expected outputs based on + 'models/aircraft/blended_wing_body/generic_BWB_GASP.csv' model. + """ + + def setUp(self): + _clear_problem_names() # need to reset these to simulate separate runs + + @require_pyoptsparse(optimizer='SNOPT') + def test_bench_bwb_GwGm_SNOPT(self): + local_phase_info = deepcopy(phase_info) + prob = run_aviary( + 'models/aircraft/blended_wing_body/generic_BWB_GASP.csv', + local_phase_info, + optimizer='SNOPT', + verbosity=0, + max_iter=60, + ) + + # TODO: CI has some intermittent problems with hitting feasibility. + # self.assertTrue(prob.result.success) + + rtol = 1e-3 + + # There are no truth values for these. + assert_near_equal( + prob.get_val(Mission.Design.GROSS_MASS, units='lbm'), + 139803.667415, + tolerance=rtol, + ) + + assert_near_equal( + prob.get_val(Mission.Summary.OPERATING_MASS, units='lbm'), + 79873.05255347, + tolerance=rtol, + ) + + assert_near_equal( + prob.get_val(Mission.Summary.TOTAL_FUEL_MASS, units='lbm'), + 26180.61486153, + tolerance=rtol, + ) + + assert_near_equal( + prob.get_val(Mission.Landing.GROUND_DISTANCE, units='ft'), + 2216.0066613, + tolerance=rtol, + ) + + assert_near_equal(prob.get_val(Mission.Summary.RANGE, units='NM'), 3500.0, tolerance=rtol) + + assert_near_equal( + prob.get_val(Mission.Landing.TOUCHDOWN_MASS, units='lbm'), + 116003.31044998, + tolerance=rtol, + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/validation_cases/benchmark_tests/test_off_design_FwFm.py b/aviary/validation_cases/benchmark_tests/test_off_design_FwFm.py deleted file mode 100644 index ff9300cec3..0000000000 --- a/aviary/validation_cases/benchmark_tests/test_off_design_FwFm.py +++ /dev/null @@ -1,240 +0,0 @@ -import unittest -import aviary.api as av - -from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from openmdao.utils.assert_utils import assert_near_equal - -from aviary.interface.default_phase_info.height_energy import phase_info_parameterization -from aviary.variable_info.enums import ProblemType, Verbosity - - -class HeightEnergyTestCase(unittest.TestCase): - """ - Setup basic aircraft mass and range and select climb, cruise, and descent phases for simulation. - """ - - def setUp(self) -> None: - self.sized_mass = 175871.04745399 - self.sized_range = 3375 - phase_info = { - "pre_mission": {"include_takeoff": True, "optimize_mass": True}, - "climb": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - 'fix_initial': False, - 'input_initial': True, - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 6, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.3, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.1, 0.8), "unitless"), - "initial_altitude": (35., "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((0.0, 35000.0), "ft"), - "throttle_enforcement": "path_constraint", - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 2.0), "min"), - "duration_bounds": ((5.0, 50.0), "min"), - "no_descent": False, - "add_initial_mass_constraint": False, - }, - "initial_guesses": {"time": ([0, 40.0], "min")}, - }, - "cruise": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "polynomial_control_order": 1, - "use_polynomial_control": True, - "num_segments": 1, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.79, "unitless"), - "mach_bounds": ((0.79, 0.79), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((35000.0, 35000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": False, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((64.0, 192.0), "min"), - "duration_bounds": ((60.0, 720.0), "min"), - }, - "initial_guesses": {"time": ([128, 113], "min")}, - }, - "descent": { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - "user_options": { - "optimize_mach": True, - "optimize_altitude": True, - "use_polynomial_control": False, - "num_segments": 5, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.79, "unitless"), - "final_mach": (0.3, "unitless"), - "mach_bounds": ((0.2, 0.8), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35.0, "ft"), - "altitude_bounds": ((0.0, 35000.0), "ft"), - "throttle_enforcement": "path_constraint", - "fix_initial": False, - "constrain_final": True, - "fix_duration": False, - "initial_bounds": ((120., 800.), "min"), - "duration_bounds": ((5.0, 35.0), "min"), - "no_climb": True, - }, - "initial_guesses": {"time": ([241, 30], "min")}, - }, - "post_mission": { - "include_landing": True, - "constrain_range": True, - "target_range": (3375.0, "nmi"), - }, - } - - self.phase_info = phase_info - - -@use_tempdirs -class TestOffDesign(HeightEnergyTestCase): - """ - Build the model using a large single aisle commercial transport aircraft data using - FLOPS mass method and HEIGHT_ENERGY mission method. Run a fallout mission to test off design. - """ - - @require_pyoptsparse(optimizer="IPOPT") - def test_off_design_IPOPT(self): - # Fallout Mission - prob_fallout = av.AviaryProblem() - prob_fallout.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', - self.phase_info, verbosity=Verbosity.QUIET) - - prob_fallout.problem_type = ProblemType.FALLOUT - prob_fallout.aviary_inputs.set_val('problem_type', ProblemType.FALLOUT, - units='unitless') - prob_fallout.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') - prob_fallout.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') - - prob_fallout.check_and_preprocess_inputs() - prob_fallout.add_pre_mission_systems() - prob_fallout.add_phases( - phase_info_parameterization=phase_info_parameterization) - prob_fallout.add_post_mission_systems() - prob_fallout.link_phases() - prob_fallout.add_driver('IPOPT', max_iter=100) - prob_fallout.add_design_variables() - prob_fallout.add_objective() - prob_fallout.setup() - prob_fallout.set_initial_guesses() - prob_fallout.run_aviary_problem() - - # Alternate Mission - prob_alternate = av.AviaryProblem() - prob_alternate.load_inputs( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, - verbosity=Verbosity.QUIET) - prob_alternate.problem_type = ProblemType.ALTERNATE - prob_alternate.aviary_inputs.set_val( - 'problem_type', ProblemType.ALTERNATE, units='unitless') - - prob_alternate.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') - prob_alternate.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') - - prob_alternate.check_and_preprocess_inputs() - prob_alternate.add_pre_mission_systems() - prob_alternate.add_phases( - phase_info_parameterization=phase_info_parameterization) - prob_alternate.add_post_mission_systems() - prob_alternate.link_phases() - prob_alternate.add_driver('IPOPT', max_iter=100) - prob_alternate.add_design_variables() - prob_alternate.add_objective() - prob_alternate.setup() - prob_alternate.set_initial_guesses() - prob_alternate.run_aviary_problem() - - fallout_range = prob_fallout.get_val(av.Mission.Summary.RANGE) - alternate_mass = prob_alternate.get_val(av.Mission.Summary.GROSS_MASS) - assert_near_equal(fallout_range, self.sized_range, tolerance=0.02) - assert_near_equal(alternate_mass, self.sized_mass, tolerance=0.02) - - @require_pyoptsparse(optimizer='SNOPT') - def test_off_design_SNOPT(self): - # Fallout Mission - prob_fallout = av.AviaryProblem() - prob_fallout.load_inputs('models/test_aircraft/aircraft_for_bench_FwFm.csv', - self.phase_info, verbosity=Verbosity.QUIET) - - prob_fallout.problem_type = ProblemType.FALLOUT - prob_fallout.aviary_inputs.set_val('problem_type', ProblemType.FALLOUT, - units='unitless') - prob_fallout.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') - prob_fallout.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') - - prob_fallout.check_and_preprocess_inputs() - prob_fallout.add_pre_mission_systems() - prob_fallout.add_phases( - phase_info_parameterization=phase_info_parameterization) - prob_fallout.add_post_mission_systems() - prob_fallout.link_phases() - prob_fallout.add_driver('SNOPT', max_iter=100) - prob_fallout.add_design_variables() - prob_fallout.add_objective() - prob_fallout.setup() - prob_fallout.set_initial_guesses() - prob_fallout.run_aviary_problem() - - # Alternate Mission - prob_alternate = av.AviaryProblem() - prob_alternate.load_inputs( - 'models/test_aircraft/aircraft_for_bench_FwFm.csv', self.phase_info, - verbosity=Verbosity.QUIET) - prob_alternate.problem_type = ProblemType.ALTERNATE - prob_alternate.aviary_inputs.set_val( - 'problem_type', ProblemType.ALTERNATE, units='unitless') - - prob_alternate.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') - prob_alternate.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') - - prob_alternate.check_and_preprocess_inputs() - prob_alternate.add_pre_mission_systems() - prob_alternate.add_phases( - phase_info_parameterization=phase_info_parameterization) - prob_alternate.add_post_mission_systems() - prob_alternate.link_phases() - prob_alternate.add_driver('SNOPT', max_iter=100) - prob_alternate.add_design_variables() - prob_alternate.add_objective() - prob_alternate.setup() - prob_alternate.set_initial_guesses() - prob_alternate.run_aviary_problem() - - fallout_range = prob_fallout.get_val(av.Mission.Summary.RANGE) - alternate_mass = prob_alternate.get_val(av.Mission.Summary.GROSS_MASS) - assert_near_equal(fallout_range, self.sized_range, tolerance=0.02) - assert_near_equal(alternate_mass, self.sized_mass, tolerance=0.02) - - -if __name__ == '__main__': - test = TestOffDesign() - test.setUp() - test.test_off_design_SNOPT() - test.test_off_design_IPOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_off_design_GwGm.py b/aviary/validation_cases/benchmark_tests/test_problem_types_GwGm.py similarity index 69% rename from aviary/validation_cases/benchmark_tests/test_off_design_GwGm.py rename to aviary/validation_cases/benchmark_tests/test_problem_types_GwGm.py index 619afa8764..02352a6166 100644 --- a/aviary/validation_cases/benchmark_tests/test_off_design_GwGm.py +++ b/aviary/validation_cases/benchmark_tests/test_problem_types_GwGm.py @@ -1,17 +1,17 @@ import unittest -import aviary.api as av from copy import deepcopy -from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs from openmdao.utils.assert_utils import assert_near_equal +from openmdao.utils.testing_utils import require_pyoptsparse, use_tempdirs -from aviary.interface.default_phase_info.two_dof import phase_info +import aviary.api as av +from aviary.models.missions.two_dof_default import phase_info from aviary.variable_info.enums import ProblemType, Verbosity class TwoDOFTestCase(unittest.TestCase): def setUp(self) -> None: - self.sized_mass = 174039. + self.sized_mass = 171044.0 self.sized_range = 3675 self.phase_info = deepcopy(phase_info) @@ -23,57 +23,59 @@ class TestOffDesign(TwoDOFTestCase): GASP mass method and TWO_DEGREES_OF_FREEDOM mission method. Run a fallout mission to test off design. """ - @require_pyoptsparse(optimizer="IPOPT") + @require_pyoptsparse(optimizer='IPOPT') def test_off_design_IPOPT(self): # Fallout Mission prob_fallout = av.AviaryProblem() - prob_fallout.load_inputs('models/test_aircraft/aircraft_for_bench_GwGm.csv', - self.phase_info, verbosity=Verbosity.QUIET) + prob_fallout.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', + self.phase_info, + verbosity=Verbosity.QUIET, + ) prob_fallout.problem_type = ProblemType.FALLOUT - prob_fallout.aviary_inputs.set_val('problem_type', ProblemType.FALLOUT, - units='unitless') + prob_fallout.aviary_inputs.set_val('problem_type', ProblemType.FALLOUT, units='unitless') prob_fallout.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') + 'mission:design:gross_mass', self.sized_mass, units='lbm' + ) prob_fallout.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') + 'mission:summary:gross_mass', self.sized_mass, units='lbm' + ) prob_fallout.check_and_preprocess_inputs() - prob_fallout.add_pre_mission_systems() - prob_fallout.add_phases() - prob_fallout.add_post_mission_systems() - prob_fallout.link_phases() + + prob_fallout.build_model() prob_fallout.add_driver('IPOPT', max_iter=100) prob_fallout.add_design_variables() prob_fallout.add_objective() prob_fallout.setup() - prob_fallout.set_initial_guesses() prob_fallout.run_aviary_problem() # Alternate Mission prob_alternate = av.AviaryProblem() prob_alternate.load_inputs( - 'models/test_aircraft/aircraft_for_bench_GwGm.csv', self.phase_info, - verbosity=Verbosity.QUIET) + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', + self.phase_info, + verbosity=Verbosity.QUIET, + ) prob_alternate.problem_type = ProblemType.ALTERNATE prob_alternate.aviary_inputs.set_val( - 'problem_type', ProblemType.ALTERNATE, units='unitless') + 'problem_type', ProblemType.ALTERNATE, units='unitless' + ) prob_alternate.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') + 'mission:design:gross_mass', self.sized_mass, units='lbm' + ) prob_alternate.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') + 'mission:summary:gross_mass', self.sized_mass, units='lbm' + ) prob_alternate.check_and_preprocess_inputs() - prob_alternate.add_pre_mission_systems() - prob_alternate.add_phases() - prob_alternate.add_post_mission_systems() - prob_alternate.link_phases() + prob_alternate.build_model() prob_alternate.add_driver('IPOPT', max_iter=100) prob_alternate.add_design_variables() prob_alternate.add_objective() prob_alternate.setup() - prob_alternate.set_initial_guesses() prob_alternate.run_aviary_problem() fallout_range = prob_fallout.get_val(av.Mission.Summary.RANGE) @@ -85,53 +87,54 @@ def test_off_design_IPOPT(self): def test_off_design_SNOPT(self): # Fallout Mission prob_fallout = av.AviaryProblem() - prob_fallout.load_inputs('models/test_aircraft/aircraft_for_bench_GwGm.csv', - self.phase_info, verbosity=Verbosity.QUIET) + prob_fallout.load_inputs( + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', + self.phase_info, + verbosity=Verbosity.QUIET, + ) prob_fallout.problem_type = ProblemType.FALLOUT - prob_fallout.aviary_inputs.set_val('problem_type', ProblemType.FALLOUT, - units='unitless') + prob_fallout.aviary_inputs.set_val('problem_type', ProblemType.FALLOUT, units='unitless') prob_fallout.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') + 'mission:design:gross_mass', self.sized_mass, units='lbm' + ) prob_fallout.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') + 'mission:summary:gross_mass', self.sized_mass, units='lbm' + ) prob_fallout.check_and_preprocess_inputs() - prob_fallout.add_pre_mission_systems() - prob_fallout.add_phases() - prob_fallout.add_post_mission_systems() - prob_fallout.link_phases() + prob_fallout.build_model() prob_fallout.add_driver('SNOPT', max_iter=100) prob_fallout.add_design_variables() prob_fallout.add_objective() prob_fallout.setup() - prob_fallout.set_initial_guesses() prob_fallout.run_aviary_problem() # Alternate Mission prob_alternate = av.AviaryProblem() prob_alternate.load_inputs( - 'models/test_aircraft/aircraft_for_bench_GwGm.csv', self.phase_info, - verbosity=Verbosity.QUIET) + 'models/aircraft/test_aircraft/aircraft_for_bench_GwGm.csv', + self.phase_info, + verbosity=Verbosity.QUIET, + ) prob_alternate.problem_type = ProblemType.ALTERNATE prob_alternate.aviary_inputs.set_val( - 'problem_type', ProblemType.ALTERNATE, units='unitless') + 'problem_type', ProblemType.ALTERNATE, units='unitless' + ) prob_alternate.aviary_inputs.set_val( - 'mission:design:gross_mass', self.sized_mass, units='lbm') + 'mission:design:gross_mass', self.sized_mass, units='lbm' + ) prob_alternate.aviary_inputs.set_val( - 'mission:summary:gross_mass', self.sized_mass, units='lbm') + 'mission:summary:gross_mass', self.sized_mass, units='lbm' + ) prob_alternate.check_and_preprocess_inputs() - prob_alternate.add_pre_mission_systems() - prob_alternate.add_phases() - prob_alternate.add_post_mission_systems() - prob_alternate.link_phases() + prob_alternate.build_model() prob_alternate.add_driver('SNOPT', max_iter=100) prob_alternate.add_design_variables() prob_alternate.add_objective() prob_alternate.setup() - prob_alternate.set_initial_guesses() prob_alternate.run_aviary_problem() fallout_range = prob_fallout.get_val(av.Mission.Summary.RANGE) @@ -141,7 +144,8 @@ def test_off_design_SNOPT(self): if __name__ == '__main__': - test = TestOffDesign() - test.setUp() - test.test_off_design_SNOPT() - test.test_off_design_IPOPT() + unittest.main() + # test = TestOffDesign() + # test.setUp() + # test.test_off_design_SNOPT() + # test.test_off_design_IPOPT() diff --git a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py index 9e20d75f5a..d4b89aabfd 100644 --- a/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py +++ b/aviary/validation_cases/benchmark_tests/test_subsystems_within_a_mission.py @@ -1,79 +1,83 @@ -import numpy as np import unittest +import numpy as np from numpy.testing import assert_almost_equal from openmdao.utils.testing_utils import use_tempdirs from aviary.interface.methods_for_level2 import AviaryProblem from aviary.subsystems.test.test_dummy_subsystem import ( - AdditionalArrayGuessSubsystemBuilder, ArrayGuessSubsystemBuilder, - Mission, MoreMission, PostOnlyBuilder) + AdditionalArrayGuessSubsystemBuilder, + ArrayGuessSubsystemBuilder, + Mission, + MoreMission, + PostOnlyBuilder, +) @use_tempdirs class TestSubsystemsMission(unittest.TestCase): - """ - Test the setup and run of a model with external subsystem - """ + """Test the setup and run of a model with external subsystem.""" def setUp(self): self.phase_info = { 'pre_mission': { 'include_takeoff': False, - 'external_subsystems': [ArrayGuessSubsystemBuilder(), AdditionalArrayGuessSubsystemBuilder()], + 'external_subsystems': [ + ArrayGuessSubsystemBuilder(), + AdditionalArrayGuessSubsystemBuilder(), + ], 'optimize_mass': True, }, 'cruise': { - "subsystem_options": {"core_aerodynamics": {"method": "computed"}}, - 'external_subsystems': [ArrayGuessSubsystemBuilder(), AdditionalArrayGuessSubsystemBuilder()], - "user_options": { - "optimize_mach": False, - "optimize_altitude": False, - "polynomial_control_order": 1, - "num_segments": 2, - "order": 3, - "solve_for_distance": False, - "initial_mach": (0.72, "unitless"), - "final_mach": (0.72, "unitless"), - "mach_bounds": ((0.7, 0.74), "unitless"), - "initial_altitude": (35000.0, "ft"), - "final_altitude": (35000.0, "ft"), - "altitude_bounds": ((23000.0, 38000.0), "ft"), - "throttle_enforcement": "boundary_constraint", - "fix_initial": True, - "constrain_final": False, - "fix_duration": False, - "initial_bounds": ((0.0, 0.0), "min"), - "duration_bounds": ((10., 30.), "min"), + 'subsystem_options': { + 'core_aerodynamics': {'method': 'cruise', 'solve_alpha': True} }, - "initial_guesses": {"time": ([0, 30], "min")}, + 'external_subsystems': [ + ArrayGuessSubsystemBuilder(), + AdditionalArrayGuessSubsystemBuilder(), + ], + 'user_options': { + 'num_segments': 2, + 'order': 3, + 'mach_optimize': False, + 'mach_polynomial_order': 1, + 'mach_initial': (0.72, 'unitless'), + 'mach_final': (0.72, 'unitless'), + 'mach_bounds': ((0.7, 0.74), 'unitless'), + 'altitude_optimize': False, + 'altitude_polynomial_order': 1, + 'altitude_initial': (35000.0, 'ft'), + 'altitude_final': (35000.0, 'ft'), + 'altitude_bounds': ((23000.0, 38000.0), 'ft'), + 'throttle_enforcement': 'boundary_constraint', + 'time_initial': (0.0, 'min'), + 'time_duration_bounds': ((10.0, 30.0), 'min'), + }, + 'initial_guesses': {'time': ([0, 30], 'min')}, }, 'post_mission': { 'include_landing': False, 'external_subsystems': [PostOnlyBuilder()], - } + }, } def test_subsystems_in_a_mission(self): phase_info = self.phase_info.copy() - prob = AviaryProblem() + prob = AviaryProblem(verbosity=0) - prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info) + prob.load_inputs('models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv', phase_info) - # Preprocess inputs prob.check_and_preprocess_inputs() - prob.add_pre_mission_systems() - - prob.add_phases() + prob.build_model() - prob.add_post_mission_systems() + prob.model.mission_info['cruise']['initial_guesses'][f'states:{Mission.Dummy.VARIABLE}'] = ( + [10.0, 100.0], + 'm', + ) - # Link phases and variables - prob.link_phases() - - prob.add_driver("SLSQP", max_iter=0, verbosity=0) + prob.add_driver('SLSQP', max_iter=0, verbosity=0) prob.add_design_variables() @@ -81,44 +85,40 @@ def test_subsystems_in_a_mission(self): prob.setup() - prob.phase_info['cruise']['initial_guesses'][f'states:{Mission.Dummy.VARIABLE}'] = ([ - 10., 100.], 'm') - prob.set_initial_guesses() - # add an assert to see if the initial guesses are correct for Mission.Dummy.VARIABLE - assert_almost_equal(prob[f'traj.phases.cruise.states:{Mission.Dummy.VARIABLE}'], [[10.], - [25.97729616], - [48.02270384], - [55.], - [70.97729616], - [93.02270384], - [100.]]) + assert_almost_equal( + prob.get_val(f'traj.cruise.states:{Mission.Dummy.VARIABLE}'), + [[10.0], [25.97729616], [48.02270384], [55.0], [70.97729616], [93.02270384], [100.0]], + ) prob.run_aviary_problem() # add an assert to see if MoreMission.Dummy.TIMESERIES_VAR was correctly added to the dymos problem - assert_almost_equal(prob[f'traj.phases.cruise.timeseries.{MoreMission.Dummy.TIMESERIES_VAR}'], np.array( - [[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]]).T) + assert_almost_equal( + prob[f'traj.phases.cruise.timeseries.{MoreMission.Dummy.TIMESERIES_VAR}'], + np.array([[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]]).T, + ) def test_bad_initial_guess_key(self): phase_info = self.phase_info.copy() - phase_info['cruise']['initial_guesses']['bad_guess_name'] = ([10., 100.], 'm') + phase_info['cruise']['initial_guesses']['bad_guess_name'] = ([10.0, 100.0], 'm') - prob = AviaryProblem(reports=False) + prob = AviaryProblem(reports=False, verbosity=0) - prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv", phase_info) + prob.load_inputs('models/aircraft/test_aircraft/aircraft_for_bench_GwFm.csv', phase_info) - # Preprocess inputs prob.check_and_preprocess_inputs() prob.add_pre_mission_systems() with self.assertRaises(TypeError) as context: prob.add_phases() - print(str(context.exception)) + # print(str(context.exception)) self.assertTrue( - 'EnergyPhase: cruise: unsupported initial guess: bad_guess_name' in str(context.exception)) + 'EnergyPhase: cruise: unsupported initial guess: bad_guess_name' + in str(context.exception) + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/validation_cases/benchmark_utils.py b/aviary/validation_cases/benchmark_utils.py index c783ac5217..577a91f965 100644 --- a/aviary/validation_cases/benchmark_utils.py +++ b/aviary/validation_cases/benchmark_utils.py @@ -1,4 +1,3 @@ - import numpy as np from openmdao.utils.assert_utils import assert_near_equal @@ -6,9 +5,7 @@ def compare_against_expected_values(prob, expected_dict): - """ - Compare values in prob with the ones in expected_dict. - """ + """Compare values in prob with the ones in expected_dict.""" expected_times = expected_dict['times'] expected_altitudes = expected_dict['altitudes'] expected_masses = expected_dict['masses'] @@ -22,17 +19,15 @@ def compare_against_expected_values(prob, expected_dict): velocities = [] for idx, phase in enumerate(['climb', 'cruise', 'descent']): - - times.extend(prob.get_val(f'traj.{phase}.timeseries.time', units='s', - get_remote=True)) - altitudes.extend(prob.get_val( - f'traj.{phase}.timeseries.altitude', units='m', get_remote=True)) - velocities.extend(prob.get_val( - f'traj.{phase}.timeseries.velocity', units='m/s', get_remote=True)) - masses.extend( - prob.get_val(f'traj.{phase}.timeseries.mass', units='kg', get_remote=True)) - ranges.extend( - prob.get_val(f'traj.{phase}.timeseries.distance', units='m', get_remote=True)) + times.extend(prob.get_val(f'traj.{phase}.timeseries.time', units='s', get_remote=True)) + altitudes.extend( + prob.get_val(f'traj.{phase}.timeseries.altitude', units='m', get_remote=True) + ) + velocities.extend( + prob.get_val(f'traj.{phase}.timeseries.velocity', units='m/s', get_remote=True) + ) + masses.extend(prob.get_val(f'traj.{phase}.timeseries.mass', units='kg', get_remote=True)) + ranges.extend(prob.get_val(f'traj.{phase}.timeseries.distance', units='m', get_remote=True)) times = np.array(times) altitudes = np.array(altitudes) @@ -42,7 +37,7 @@ def compare_against_expected_values(prob, expected_dict): # Check Objective and other key variables to a reasonably tight tolerance. - rtol = 2.e-2 + rtol = 2.0e-2 # Mass at the end of Descent assert_near_equal(masses[-1], expected_masses[-1], tolerance=rtol) @@ -56,27 +51,37 @@ def compare_against_expected_values(prob, expected_dict): # Altitude at the start and end of climb # Added because setting up phase options is a little tricky. assert_near_equal(altitudes[0], expected_altitudes[0], tolerance=rtol) - assert_near_equal(altitudes[19], expected_altitudes[19], tolerance=rtol) + assert_near_equal(altitudes[-1], expected_altitudes[-1], tolerance=rtol) # Check mission values. # NOTE rtol = 0.05 = 5% different from truth (first timeseries) # atol = 2 = no more than +/-2 meter/second/kg difference between values # atol_altitude - 30 ft. - rtol = .05 + rtol = 0.05 atol = 2.0 atol_altitude = 30.0 # FLIGHT PATH warn_timeseries_near_equal( - times, altitudes, expected_times, - expected_altitudes, abs_tolerance=atol_altitude, rel_tolerance=rtol) + times, + altitudes, + expected_times, + expected_altitudes, + abs_tolerance=atol_altitude, + rel_tolerance=rtol, + ) warn_timeseries_near_equal( - times, masses, expected_times, - expected_masses, abs_tolerance=atol, rel_tolerance=rtol) + times, masses, expected_times, expected_masses, abs_tolerance=atol, rel_tolerance=rtol + ) warn_timeseries_near_equal( - times, ranges, expected_times, - expected_ranges, abs_tolerance=atol, rel_tolerance=rtol) + times, ranges, expected_times, expected_ranges, abs_tolerance=atol, rel_tolerance=rtol + ) warn_timeseries_near_equal( - times, velocities, expected_times, - expected_velocities, abs_tolerance=atol, rel_tolerance=rtol) + times, + velocities, + expected_times, + expected_velocities, + abs_tolerance=atol, + rel_tolerance=rtol, + ) diff --git a/aviary/validation_cases/validation_data/flops_data/FLOPS_Test_Data.py b/aviary/validation_cases/validation_data/flops_data/FLOPS_Test_Data.py index 94e0388e6d..81d8925c6e 100644 --- a/aviary/validation_cases/validation_data/flops_data/FLOPS_Test_Data.py +++ b/aviary/validation_cases/validation_data/flops_data/FLOPS_Test_Data.py @@ -1,14 +1,19 @@ -from aviary.models.large_single_aisle_2.large_single_aisle_2_altwt_FLOPS_data import \ - LargeSingleAisle2FLOPSalt -from aviary.models.large_single_aisle_2.large_single_aisle_2_detailwing_FLOPS_data import \ - LargeSingleAisle2FLOPSdw -from aviary.models.large_single_aisle_2.large_single_aisle_2_FLOPS_data import \ - LargeSingleAisle2FLOPS -from aviary.models.large_single_aisle_1.large_single_aisle_1_FLOPS_data import \ - LargeSingleAisle1FLOPS -from aviary.models.N3CC.N3CC_data import N3CC -from aviary.models.multi_engine_single_aisle.multi_engine_single_aisle_data import \ - MultiEngineSingleAisle +from aviary.models.aircraft.large_single_aisle_1.large_single_aisle_1_FLOPS_data import ( + LargeSingleAisle1FLOPS, +) +from aviary.models.aircraft.large_single_aisle_2.large_single_aisle_2_altwt_FLOPS_data import ( + LargeSingleAisle2FLOPSalt, +) +from aviary.models.aircraft.large_single_aisle_2.large_single_aisle_2_detailwing_FLOPS_data import ( + LargeSingleAisle2FLOPSdw, +) +from aviary.models.aircraft.large_single_aisle_2.large_single_aisle_2_FLOPS_data import ( + LargeSingleAisle2FLOPS, +) +from aviary.models.aircraft.multi_engine_single_aisle.multi_engine_single_aisle_data import ( + MultiEngineSingleAisle, +) +from aviary.models.aircraft.advanced_single_aisle.advanced_single_aisle_data import N3CC FLOPS_Test_Data = {} @@ -16,7 +21,7 @@ FLOPS_Test_Data['LargeSingleAisle2FLOPS'] = LargeSingleAisle2FLOPS FLOPS_Test_Data['LargeSingleAisle2FLOPSdw'] = LargeSingleAisle2FLOPSdw FLOPS_Test_Data['LargeSingleAisle2FLOPSalt'] = LargeSingleAisle2FLOPSalt -FLOPS_Test_Data['N3CC'] = N3CC +FLOPS_Test_Data['AdvancedSingleAisle'] = N3CC # We don't have full date for this yet, but might still want to run one in a single unit test. FLOPS_Lacking_Test_Data = {} diff --git a/aviary/validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.csv b/aviary/validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.csv new file mode 100644 index 0000000000..510eb6b201 --- /dev/null +++ b/aviary/validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.csv @@ -0,0 +1,626 @@ +# FLOPS-derived engine deck converted from turbofan_23k_2_ENGDEK + +Mach_Number, Altitude (ft), Throttle, Gross_Thrust (lbf), Ram_Drag (lbf), Fuel_Flow (lb/h), NOx_Rate (lb/h) + 0.0, 0.0, 26.0, 4600.1, 0.0, 995.6, 24.271 + 0.0, 0.0, 29.0, 6900.2, 0.0, 1413.7, 22.261 + 0.0, 0.0, 32.0, 9200.3, 0.0, 1851.6, 21.723 + 0.0, 0.0, 35.0, 11500.3, 0.0, 2333.1, 20.97 + 0.0, 0.0, 38.0, 13800.7, 0.0, 2852.6, 20.367 + 0.0, 0.0, 41.0, 16100.6, 0.0, 3416.1, 19.773 + 0.0, 0.0, 44.0, 18400.6, 0.0, 4016.9, 19.147 + 0.0, 0.0, 47.0, 20700.5, 0.0, 4660.3, 18.591 + 0.0, 0.0, 50.0, 23000.7, 0.0, 5341.5, 18.367 + 0.0, 2000.0, 26.0, 4399.1, 0.0, 947.3, 24.076 + 0.0, 2000.0, 29.0, 6598.6, 0.0, 1345.6, 22.182 + 0.0, 2000.0, 32.0, 8798.1, 0.0, 1764.0, 21.622 + 0.0, 2000.0, 35.0, 10997.6, 0.0, 2223.0, 20.904 + 0.0, 2000.0, 38.0, 13197.1, 0.0, 2724.6, 20.245 + 0.0, 2000.0, 41.0, 15396.7, 0.0, 3260.3, 19.688 + 0.0, 2000.0, 44.0, 17596.2, 0.0, 3840.8, 19.002 + 0.0, 2000.0, 47.0, 19795.6, 0.0, 4460.8, 18.478 + 0.0, 2000.0, 50.0, 21995.3, 0.0, 5112.9, 18.344 + 0.0, 5000.0, 26.0, 4099.1, 0.0, 876.9, 23.814 + 0.0, 5000.0, 29.0, 6148.6, 0.0, 1245.6, 22.081 + 0.0, 5000.0, 32.0, 8198.2, 0.0, 1635.5, 21.462 + 0.0, 5000.0, 35.0, 10247.8, 0.0, 2059.6, 20.819 + 0.0, 5000.0, 38.0, 12297.3, 0.0, 2533.6, 20.08 + 0.0, 5000.0, 41.0, 14346.8, 0.0, 3032.4, 19.515 + 0.0, 5000.0, 44.0, 16396.3, 0.0, 3577.5, 18.808 + 0.0, 5000.0, 47.0, 18445.9, 0.0, 4159.8, 18.392 + 0.0, 5000.0, 50.0, 20495.4, 0.0, 4775.3, 18.263 + 0.0, 10000.0, 26.0, 3604.9, 0.0, 765.8, 23.451 + 0.0, 10000.0, 29.0, 5407.4, 0.0, 1085.6, 21.954 + 0.0, 10000.0, 32.0, 7209.6, 0.0, 1427.6, 21.247 + 0.0, 10000.0, 35.0, 9012.2, 0.0, 1798.3, 20.623 + 0.0, 10000.0, 38.0, 10814.6, 0.0, 2217.9, 19.855 + 0.0, 10000.0, 41.0, 12617.1, 0.0, 2664.2, 19.165 + 0.0, 10000.0, 44.0, 14419.6, 0.0, 3145.7, 18.54 + 0.0, 10000.0, 47.0, 16222.1, 0.0, 3657.6, 18.348 + 0.0, 10000.0, 50.0, 18024.4, 0.0, 4230.1, 17.994 + 0.1, 0.0, 26.0, 5979.4, 1910.4, 1175.2, 21.966 + 0.1, 0.0, 29.0, 8312.8, 2209.3, 1613.3, 21.233 + 0.1, 0.0, 32.0, 10606.4, 2468.3, 2069.5, 20.839 + 0.1, 0.0, 35.0, 12859.7, 2687.0, 2550.1, 20.432 + 0.1, 0.0, 38.0, 15066.8, 2859.9, 3076.6, 19.84 + 0.1, 0.0, 41.0, 17265.5, 3024.0, 3619.1, 19.426 + 0.1, 0.0, 44.0, 19426.4, 3150.4, 4202.8, 18.823 + 0.1, 0.0, 47.0, 21585.1, 3274.6, 4819.2, 18.379 + 0.1, 0.0, 50.0, 23762.9, 3417.9, 5468.2, 18.251 + 0.1, 2000.0, 26.0, 5693.6, 1793.8, 1116.0, 21.886 + 0.1, 2000.0, 29.0, 7928.8, 2079.2, 1533.2, 21.211 + 0.1, 2000.0, 32.0, 10120.0, 2320.5, 1969.5, 20.769 + 0.1, 2000.0, 35.0, 12278.5, 2528.9, 2427.4, 20.394 + 0.1, 2000.0, 38.0, 14386.9, 2687.6, 2935.3, 19.748 + 0.1, 2000.0, 41.0, 16487.9, 2838.6, 3457.2, 19.294 + 0.1, 2000.0, 44.0, 18557.2, 2958.0, 4016.4, 18.699 + 0.1, 2000.0, 47.0, 20626.0, 3077.1, 4610.8, 18.282 + 0.1, 2000.0, 50.0, 22718.4, 3219.5, 5234.5, 18.232 + 0.1, 5000.0, 26.0, 5266.6, 1627.7, 1029.0, 21.785 + 0.1, 5000.0, 29.0, 7350.8, 1892.3, 1413.8, 21.186 + 0.1, 5000.0, 32.0, 9387.0, 2108.9, 1819.8, 20.681 + 0.1, 5000.0, 35.0, 11391.2, 2293.7, 2248.1, 20.227 + 0.1, 5000.0, 38.0, 13358.5, 2441.4, 2719.6, 19.63 + 0.1, 5000.0, 41.0, 15308.8, 2572.2, 3210.5, 19.094 + 0.1, 5000.0, 44.0, 17239.8, 2683.6, 3733.6, 18.539 + 0.1, 5000.0, 47.0, 19179.8, 2804.2, 4291.0, 18.267 + 0.1, 5000.0, 50.0, 21120.3, 2925.2, 4884.1, 18.123 + 0.1, 10000.0, 26.0, 4595.6, 1376.8, 894.9, 21.64 + 0.1, 10000.0, 29.0, 6436.5, 1608.4, 1228.2, 21.165 + 0.1, 10000.0, 32.0, 8226.1, 1788.6, 1585.3, 20.56 + 0.1, 10000.0, 35.0, 9985.7, 1938.9, 1967.7, 19.984 + 0.1, 10000.0, 38.0, 11725.4, 2069.1, 2376.8, 19.462 + 0.1, 10000.0, 41.0, 13436.9, 2171.5, 2816.2, 18.798 + 0.1, 10000.0, 44.0, 15144.7, 2269.8, 3283.2, 18.306 + 0.1, 10000.0, 47.0, 16870.6, 2386.2, 3777.3, 18.229 + 0.1, 10000.0, 50.0, 18565.1, 2471.4, 4327.8, 17.869 + 0.2, 0.0, 26.0, 7753.2, 4098.6, 1332.2, 19.678 + 0.2, 0.0, 29.0, 10194.5, 4712.7, 1794.3, 19.81 + 0.2, 0.0, 32.0, 12500.9, 5191.8, 2274.0, 19.648 + 0.2, 0.0, 35.0, 14743.1, 5606.7, 2765.1, 19.472 + 0.2, 0.0, 38.0, 16895.8, 5932.1, 3296.4, 19.088 + 0.2, 0.0, 41.0, 19025.5, 6234.6, 3837.1, 18.78 + 0.2, 0.0, 44.0, 21092.8, 6474.5, 4407.5, 18.338 + 0.2, 0.0, 47.0, 23158.2, 6712.7, 5008.9, 18.018 + 0.2, 0.0, 50.0, 25268.1, 6995.4, 5639.1, 17.987 + 0.2, 2000.0, 26.0, 7360.6, 3850.3, 1264.7, 19.677 + 0.2, 2000.0, 29.0, 9701.6, 4436.1, 1705.3, 19.839 + 0.2, 2000.0, 32.0, 11902.5, 4881.9, 2162.9, 19.628 + 0.2, 2000.0, 35.0, 14039.5, 5263.8, 2637.0, 19.395 + 0.2, 2000.0, 38.0, 16105.3, 5575.4, 3143.0, 19.033 + 0.2, 2000.0, 41.0, 18135.0, 5848.9, 3665.1, 18.665 + 0.2, 2000.0, 44.0, 20120.4, 6079.1, 4213.9, 18.244 + 0.2, 2000.0, 47.0, 22113.7, 6317.3, 4793.5, 17.988 + 0.2, 2000.0, 50.0, 24141.0, 6589.4, 5399.3, 17.98 + 0.2, 5000.0, 26.0, 6778.9, 3494.9, 1164.7, 19.679 + 0.2, 5000.0, 29.0, 8961.3, 4035.3, 1573.0, 19.864 + 0.2, 5000.0, 32.0, 11005.6, 4437.4, 1995.9, 19.606 + 0.2, 5000.0, 35.0, 12984.3, 4774.4, 2441.1, 19.296 + 0.2, 5000.0, 38.0, 14916.7, 5064.9, 2908.6, 18.964 + 0.2, 5000.0, 41.0, 16793.8, 5299.9, 3399.5, 18.516 + 0.2, 5000.0, 44.0, 18650.7, 5514.8, 3915.1, 18.122 + 0.2, 5000.0, 47.0, 20533.7, 5755.8, 4459.8, 17.99 + 0.2, 5000.0, 50.0, 22399.6, 5979.7, 5038.2, 17.866 + 0.2, 10000.0, 26.0, 5878.8, 2959.1, 1011.2, 19.693 + 0.2, 10000.0, 29.0, 7791.7, 3412.2, 1368.2, 19.78 + 0.2, 10000.0, 32.0, 9604.9, 3765.6, 1736.6, 19.586 + 0.2, 10000.0, 35.0, 11337.0, 4037.9, 2133.4, 19.15 + 0.2, 10000.0, 38.0, 13042.6, 4283.6, 2544.4, 18.797 + 0.2, 10000.0, 41.0, 14694.4, 4475.4, 2980.5, 18.291 + 0.2, 10000.0, 44.0, 16351.5, 4672.9, 3443.2, 17.989 + 0.2, 10000.0, 47.0, 18034.3, 4895.7, 3929.6, 17.963 + 0.2, 10000.0, 50.0, 19650.4, 5052.1, 4465.2, 17.647 + 0.25, 0, 26.0, 8783.7, 5305.0, 1408.2, 18.719 + 0.25, 0, 29.0, 11302.5, 6084.4, 1886.1, 19.126 + 0.25, 0, 32.0, 13621.0, 6663.6, 2374.8, 19.063 + 0.25, 0, 35.0, 15860.6, 7163.8, 2875.9, 18.956 + 0.25, 0, 38.0, 18005.2, 7569.0, 3407.5, 18.695 + 0.25, 0, 41.0, 20107.6, 7932.2, 3949.5, 18.436 + 0.25, 0, 44.0, 22143.1, 8228.1, 4518.1, 18.077 + 0.25, 0, 47.0, 24175.5, 8521.3, 5113.7, 17.815 + 0.25, 0, 50.0, 26266.5, 8873.0, 5738.0, 17.826 + 0.25, 2000, 26.0, 8329.8, 4984.6, 1336.8, 18.743 + 0.25, 2000, 29.0, 10739.8, 5722.0, 1793.2, 19.146 + 0.25, 2000, 32.0, 12957.2, 6266.8, 2258.7, 19.065 + 0.25, 2000, 35.0, 15089.5, 6726.3, 2742.2, 18.901 + 0.25, 2000, 38.0, 17150.3, 7114.6, 3249.0, 18.658 + 0.25, 2000, 41.0, 19150.1, 7441.8, 3772.4, 18.34 + 0.25, 2000, 44.0, 21106.8, 7725.9, 4320.3, 17.997 + 0.25, 2000, 47.0, 23077.4, 8023.9, 4895.2, 17.81 + 0.25, 2000, 50.0, 25084.3, 8358.2, 5495.0, 17.827 + 0.25, 5000, 26.0, 7661.4, 4526.2, 1231.1, 18.779 + 0.25, 5000, 29.0, 9893.9, 5191.1, 1654.1, 19.123 + 0.25, 5000, 32.0, 11967.9, 5697.7, 2084.5, 19.071 + 0.25, 5000, 35.0, 13940.3, 6102.3, 2538.6, 18.831 + 0.25, 5000, 38.0, 15870.0, 6464.5, 3007.2, 18.613 + 0.25, 5000, 41.0, 17717.5, 6744.4, 3500.1, 18.214 + 0.25, 5000, 44.0, 19550.3, 7009.7, 4015.0, 17.894 + 0.25, 5000, 47.0, 21420.0, 7311.8, 4556.7, 17.823 + 0.25, 5000, 50.0, 23258.9, 7583.1, 5129.8, 17.717 + 0.25, 10000, 26.0, 6628.0, 3833.9, 1068.2, 18.847 + 0.25, 10000, 29.0, 8582.3, 4391.0, 1437.6, 19.095 + 0.25, 10000, 32.0, 10423.1, 4834.8, 1813.1, 19.085 + 0.25, 10000, 35.0, 12147.5, 5162.1, 2217.5, 18.731 + 0.25, 10000, 38.0, 13840.4, 5457.9, 2631.9, 18.435 + 0.25, 10000, 41.0, 15475.3, 5695.7, 3070.2, 18.026 + 0.25, 10000, 44.0, 17121.7, 5945.2, 3531.9, 17.812 + 0.25, 10000, 47.0, 18788.4, 6214.8, 4017.4, 17.794 + 0.25, 10000, 50.0, 20377.3, 6406.5, 4546.6, 17.52 + 0.3, 0.0, 26.0, 9870.2, 6574.4, 1473.1, 17.86 + 0.3, 0.0, 29.0, 12453.8, 7510.1, 1963.6, 18.433 + 0.3, 0.0, 32.0, 14787.7, 8196.1, 2457.4, 18.5 + 0.3, 0.0, 35.0, 17019.7, 8780.3, 2962.2, 18.471 + 0.3, 0.0, 38.0, 19150.2, 9262.8, 3492.4, 18.312 + 0.3, 0.0, 41.0, 21223.7, 9687.6, 4030.9, 18.118 + 0.3, 0.0, 44.0, 23219.9, 10036.7, 4594.8, 17.83 + 0.3, 0.0, 47.0, 25212.8, 10381.8, 5180.4, 17.62 + 0.3, 0.0, 50.0, 27273.3, 10794.4, 5793.5, 17.651 + 0.3, 2000.0, 26.0, 9351.5, 6178.5, 1398.5, 17.904 + 0.3, 2000.0, 29.0, 11812.2, 7052.6, 1867.1, 18.435 + 0.3, 2000.0, 32.0, 14054.9, 7708.9, 2337.6, 18.519 + 0.3, 2000.0, 35.0, 16177.2, 8244.6, 2824.8, 18.435 + 0.3, 2000.0, 38.0, 18226.3, 8707.2, 3330.0, 18.291 + 0.3, 2000.0, 41.0, 20194.5, 9088.9, 3850.5, 18.038 + 0.3, 2000.0, 44.0, 22116.1, 9424.1, 4394.1, 17.763 + 0.3, 2000.0, 47.0, 24052.0, 9773.5, 4959.5, 17.616 + 0.3, 2000.0, 50.0, 26034.2, 10169.1, 5549.5, 17.662 + 0.3, 5000.0, 26.0, 8596.0, 5613.8, 1289.0, 17.967 + 0.3, 5000.0, 29.0, 10875.2, 6401.9, 1723.6, 18.44 + 0.3, 5000.0, 32.0, 12977.5, 7013.0, 2159.6, 18.551 + 0.3, 5000.0, 35.0, 14938.8, 7483.2, 2618.2, 18.389 + 0.3, 5000.0, 38.0, 16862.7, 7915.5, 3086.0, 18.266 + 0.3, 5000.0, 41.0, 18677.6, 8240.0, 3578.0, 17.931 + 0.3, 5000.0, 44.0, 20482.3, 8553.7, 4088.9, 17.676 + 0.3, 5000.0, 47.0, 22330.5, 8910.8, 4623.8, 17.642 + 0.3, 5000.0, 50.0, 24145.9, 9235.0, 5186.0, 17.58 + 0.3, 10000.0, 26.0, 7422.8, 4757.6, 1118.5, 18.078 + 0.3, 10000.0, 29.0, 9415.2, 5417.4, 1498.6, 18.458 + 0.3, 10000.0, 32.0, 11269.8, 5939.5, 1880.1, 18.546 + 0.3, 10000.0, 35.0, 12994.9, 6331.9, 2287.2, 18.329 + 0.3, 10000.0, 38.0, 14672.9, 6677.2, 2703.0, 18.101 + 0.3, 10000.0, 41.0, 16287.7, 6959.4, 3141.1, 17.776 + 0.3, 10000.0, 44.0, 17917.5, 7256.6, 3598.9, 17.623 + 0.3, 10000.0, 47.0, 19570.2, 7576.7, 4079.0, 17.639 + 0.3, 10000.0, 50.0, 21128.8, 7802.7, 4598.6, 17.406 + 0.3, 15000.0, 21.0, 3388.6, 2833.2, 449.8, 17.237 + 0.3, 15000.0, 26.0, 6146.0, 3924.4, 897.6, 18.105 + 0.3, 15000.0, 29.0, 7800.3, 4467.9, 1196.2, 18.467 + 0.3, 15000.0, 32.0, 9338.9, 4895.8, 1495.8, 18.53 + 0.3, 15000.0, 35.0, 10776.5, 5222.6, 1815.9, 18.319 + 0.3, 15000.0, 38.0, 12167.9, 5503.1, 2144.2, 18.065 + 0.3, 15000.0, 41.0, 13513.9, 5738.4, 2488.4, 17.747 + 0.3, 15000.0, 44.0, 14879.6, 5993.2, 2849.7, 17.632 + 0.3, 15000.0, 47.0, 16244.4, 6247.2, 3229.4, 17.603 + 0.3, 15000.0, 50.0, 17542.0, 6434.0, 3638.3, 17.368 + 0.4, 0.0, 26.0, 12347.7, 9349.8, 1589.5, 16.412 + 0.4, 0.0, 29.0, 15088.1, 10591.1, 2106.9, 17.154 + 0.4, 0.0, 32.0, 17516.9, 11521.2, 2614.1, 17.458 + 0.4, 0.0, 35.0, 19773.1, 12278.6, 3129.8, 17.568 + 0.4, 0.0, 38.0, 21913.4, 12919.8, 3661.8, 17.571 + 0.4, 0.0, 41.0, 23967.5, 13475.0, 4199.7, 17.502 + 0.4, 0.0, 44.0, 25921.6, 13930.1, 4762.6, 17.337 + 0.4, 0.0, 47.0, 27869.6, 14378.8, 5337.2, 17.218 + 0.4, 0.0, 50.0, 29893.6, 14904.3, 5933.9, 17.28 + 0.4, 2000.0, 26.0, 11683.3, 8790.2, 1509.7, 16.482 + 0.4, 2000.0, 29.0, 14288.7, 9949.1, 2004.3, 17.188 + 0.4, 2000.0, 32.0, 16625.7, 10839.4, 2488.1, 17.506 + 0.4, 2000.0, 35.0, 18764.4, 11531.7, 2985.8, 17.565 + 0.4, 2000.0, 38.0, 20826.1, 12146.8, 3493.3, 17.578 + 0.4, 2000.0, 41.0, 22768.5, 12642.8, 4014.2, 17.453 + 0.4, 2000.0, 44.0, 24651.8, 13080.3, 4557.2, 17.296 + 0.4, 2000.0, 47.0, 26542.1, 13523.3, 5110.2, 17.209 + 0.4, 2000.0, 50.0, 28509.6, 14044.2, 5687.9, 17.312 + 0.4, 5000.0, 26.0, 10729.1, 7996.0, 1394.0, 16.586 + 0.4, 5000.0, 29.0, 13139.9, 9040.2, 1854.0, 17.24 + 0.4, 5000.0, 32.0, 15337.4, 9870.9, 2303.5, 17.581 + 0.4, 5000.0, 35.0, 17307.9, 10475.1, 2773.2, 17.564 + 0.4, 5000.0, 38.0, 19249.7, 11050.3, 3245.0, 17.592 + 0.4, 5000.0, 41.0, 21034.1, 11468.2, 3739.7, 17.385 + 0.4, 5000.0, 44.0, 22811.5, 11879.0, 4250.9, 17.243 + 0.4, 5000.0, 47.0, 24640.9, 12341.8, 4777.8, 17.266 + 0.4, 5000.0, 50.0, 26450.4, 12784.7, 5324.9, 17.301 + 0.4, 10000.0, 26.0, 9247.9, 6787.1, 1212.3, 16.759 + 0.4, 10000.0, 29.0, 11352.0, 7660.7, 1615.6, 17.332 + 0.4, 10000.0, 32.0, 13266.2, 8344.4, 2014.4, 17.58 + 0.4, 10000.0, 35.0, 15025.6, 8873.4, 2429.8, 17.573 + 0.4, 10000.0, 38.0, 16702.9, 9320.2, 2853.4, 17.473 + 0.4, 10000.0, 41.0, 18306.0, 9693.2, 3297.6, 17.291 + 0.4, 10000.0, 44.0, 19928.6, 10085.1, 3753.4, 17.234 + 0.4, 10000.0, 47.0, 21588.4, 10514.2, 4228.6, 17.328 + 0.4, 10000.0, 50.0, 23114.3, 10809.9, 4735.7, 17.173 + 0.4, 15000.0, 21.0, 4574.2, 4053.8, 484.8, 15.004 + 0.4, 15000.0, 26.0, 7705.7, 5624.1, 979.9, 16.825 + 0.4, 15000.0, 29.0, 9467.4, 6345.0, 1300.7, 17.369 + 0.4, 15000.0, 32.0, 11066.8, 6903.7, 1619.1, 17.576 + 0.4, 15000.0, 35.0, 12553.4, 7349.5, 1950.0, 17.579 + 0.4, 15000.0, 38.0, 13952.4, 7707.8, 2290.7, 17.434 + 0.4, 15000.0, 41.0, 15308.1, 8022.6, 2646.1, 17.26 + 0.4, 15000.0, 44.0, 16697.2, 8371.0, 3013.0, 17.265 + 0.4, 15000.0, 47.0, 18067.8, 8700.8, 3396.8, 17.282 + 0.4, 15000.0, 50.0, 19354.4, 8946.6, 3804.1, 17.126 + 0.4, 20000.0, 21.0, 3721.1, 3297.5, 408.4, 15.012 + 0.4, 20000.0, 26.0, 6271.9, 4577.5, 799.8, 16.829 + 0.4, 20000.0, 29.0, 7706.8, 5165.3, 1054.2, 17.374 + 0.4, 20000.0, 32.0, 9009.6, 5620.8, 1305.3, 17.581 + 0.4, 20000.0, 35.0, 10219.8, 5984.0, 1568.1, 17.583 + 0.4, 20000.0, 38.0, 11359.1, 6276.0, 1837.9, 17.437 + 0.4, 20000.0, 41.0, 12462.8, 6532.6, 2119.3, 17.263 + 0.4, 20000.0, 44.0, 13594.0, 6816.4, 2409.8, 17.268 + 0.4, 20000.0, 47.0, 14709.9, 7085.1, 2713.0, 17.284 + 0.4, 20000.0, 50.0, 15757.3, 7285.5, 3034.5, 17.125 + 0.5, 0.0, 26.0, 15265.0, 12518.2, 1708.4, 15.378 + 0.5, 0.0, 29.0, 18190.5, 14070.2, 2250.5, 16.191 + 0.5, 0.0, 32.0, 20745.8, 15252.1, 2771.8, 16.628 + 0.5, 0.0, 35.0, 23058.1, 16190.9, 3298.3, 16.841 + 0.5, 0.0, 38.0, 25233.4, 16992.5, 3832.6, 16.952 + 0.5, 0.0, 41.0, 27307.0, 17692.8, 4372.2, 16.993 + 0.5, 0.0, 44.0, 29240.3, 18252.7, 4933.9, 16.918 + 0.5, 0.0, 47.0, 31163.1, 18802.0, 5506.3, 16.872 + 0.5, 0.0, 50.0, 33149.0, 19414.4, 6088.5, 16.934 + 0.5, 2000.0, 26.0, 14430.8, 11773.0, 1623.6, 15.462 + 0.5, 2000.0, 29.0, 17208.2, 13221.3, 2142.7, 16.247 + 0.5, 2000.0, 32.0, 19669.5, 14353.7, 2639.9, 16.698 + 0.5, 2000.0, 35.0, 21853.9, 15209.1, 3147.6, 16.862 + 0.5, 2000.0, 38.0, 23952.7, 15978.9, 3660.0, 16.982 + 0.5, 2000.0, 41.0, 25904.0, 16601.3, 4183.6, 16.969 + 0.5, 2000.0, 44.0, 27771.6, 17139.8, 4726.6, 16.901 + 0.5, 2000.0, 47.0, 29629.6, 17668.6, 5275.5, 16.861 + 0.5, 2000.0, 50.0, 31590.8, 18301.1, 5842.2, 16.989 + 0.5, 5000.0, 26.0, 13246.3, 10720.7, 1502.4, 15.593 + 0.5, 5000.0, 29.0, 15813.5, 12025.2, 1986.8, 16.333 + 0.5, 5000.0, 32.0, 18125.8, 13074.5, 2452.2, 16.791 + 0.5, 5000.0, 35.0, 20140.7, 13826.6, 2931.2, 16.898 + 0.5, 5000.0, 38.0, 22125.6, 14548.6, 3410.6, 17.031 + 0.5, 5000.0, 41.0, 23906.8, 15067.3, 3910.2, 16.935 + 0.5, 5000.0, 44.0, 25677.2, 15574.6, 4424.6, 16.878 + 0.5, 5000.0, 47.0, 27492.5, 16127.0, 4946.0, 16.927 + 0.5, 5000.0, 50.0, 29344.3, 16716.1, 5482.1, 17.063 + 0.5, 10000.0, 26.0, 11402.4, 9111.5, 1309.4, 15.806 + 0.5, 10000.0, 29.0, 13638.7, 10202.2, 1735.6, 16.476 + 0.5, 10000.0, 32.0, 15634.6, 11052.7, 2150.9, 16.83 + 0.5, 10000.0, 35.0, 17450.6, 11723.2, 2575.7, 16.962 + 0.5, 10000.0, 38.0, 19150.6, 12277.8, 3009.3, 16.97 + 0.5, 10000.0, 41.0, 20760.9, 12742.4, 3460.3, 16.894 + 0.5, 10000.0, 44.0, 22382.4, 13218.5, 3918.9, 16.892 + 0.5, 10000.0, 47.0, 24071.2, 13761.7, 4392.6, 17.049 + 0.5, 10000.0, 50.0, 25600.4, 14145.7, 4889.8, 16.988 + 0.5, 15000.0, 21.0, 6000.2, 5503.1, 527.9, 13.707 + 0.5, 15000.0, 26.0, 9596.4, 7608.2, 1074.4, 15.941 + 0.5, 15000.0, 29.0, 11493.5, 8511.2, 1420.2, 16.569 + 0.5, 15000.0, 32.0, 13178.1, 9201.7, 1761.1, 16.859 + 0.5, 15000.0, 35.0, 14748.5, 9778.0, 2108.1, 17.006 + 0.5, 15000.0, 38.0, 16176.6, 10212.0, 2467.3, 16.938 + 0.5, 15000.0, 41.0, 17571.1, 10612.4, 2838.7, 16.873 + 0.5, 15000.0, 44.0, 19017.1, 11064.3, 3219.2, 16.972 + 0.5, 15000.0, 47.0, 20418.1, 11471.2, 3613.6, 17.029 + 0.5, 15000.0, 50.0, 21719.9, 11778.9, 4026.7, 16.935 + 0.5, 20000.0, 21.0, 4879.2, 4474.6, 442.6, 13.709 + 0.5, 20000.0, 26.0, 7810.2, 6192.1, 873.4, 15.943 + 0.5, 20000.0, 29.0, 9355.6, 6928.3, 1148.5, 16.572 + 0.5, 20000.0, 32.0, 10727.9, 7491.6, 1417.4, 16.862 + 0.5, 20000.0, 35.0, 12006.7, 7961.2, 1693.2, 17.009 + 0.5, 20000.0, 38.0, 13169.4, 8315.0, 1978.2, 16.941 + 0.5, 20000.0, 41.0, 14304.6, 8641.1, 2271.6, 16.876 + 0.5, 20000.0, 44.0, 15481.7, 9009.1, 2573.7, 16.973 + 0.5, 20000.0, 47.0, 16622.8, 9340.9, 2885.2, 17.03 + 0.5, 20000.0, 50.0, 17682.7, 9591.9, 3211.9, 16.936 + 0.5, 25000.0, 21.0, 3933.3, 3606.7, 372.0, 13.711 + 0.5, 25000.0, 26.0, 6302.8, 4996.6, 709.5, 15.946 + 0.5, 25000.0, 29.0, 7551.7, 5592.4, 925.7, 16.577 + 0.5, 25000.0, 32.0, 8660.7, 6048.3, 1136.1, 16.868 + 0.5, 25000.0, 35.0, 9693.2, 6427.7, 1352.1, 17.013 + 0.5, 25000.0, 38.0, 10632.4, 6713.9, 1576.1, 16.946 + 0.5, 25000.0, 41.0, 11549.2, 6977.6, 1806.0, 16.879 + 0.5, 25000.0, 44.0, 12499.0, 7274.4, 2043.2, 16.976 + 0.5, 25000.0, 47.0, 13420.8, 7543.1, 2287.2, 17.032 + 0.5, 25000.0, 50.0, 14276.8, 7746.0, 2542.4, 16.936 + 0.5, 30000.0, 21.0, 3140.5, 2879.3, 315.1, 13.715 + 0.5, 30000.0, 26.0, 5039.4, 3994.4, 575.9, 15.951 + 0.5, 30000.0, 29.0, 6040.2, 4472.7, 744.0, 16.586 + 0.5, 30000.0, 32.0, 6928.6, 4838.7, 906.5, 16.877 + 0.5, 30000.0, 35.0, 7754.9, 5142.5, 1073.6, 17.02 + 0.5, 30000.0, 38.0, 8506.8, 5372.0, 1248.2, 16.952 + 0.5, 30000.0, 41.0, 9240.4, 5583.4, 1426.0, 16.884 + 0.5, 30000.0, 44.0, 10000.8, 5821.0, 1610.6, 16.979 + 0.5, 30000.0, 47.0, 10738.3, 6036.1, 1799.7, 17.034 + 0.5, 30000.0, 50.0, 11423.5, 6198.7, 1997.2, 16.938 + 0.6, 15000.0, 21.0, 7720.5, 7235.0, 578.9, 12.937 + 0.6, 15000.0, 26.0, 11871.3, 9929.5, 1184.6, 15.332 + 0.6, 15000.0, 29.0, 13959.5, 11046.8, 1558.1, 16.029 + 0.6, 15000.0, 32.0, 15760.4, 11876.9, 1926.5, 16.366 + 0.6, 15000.0, 35.0, 17454.7, 12600.2, 2297.9, 16.613 + 0.6, 15000.0, 38.0, 18937.2, 13111.8, 2682.6, 16.6 + 0.6, 15000.0, 41.0, 20404.0, 13607.8, 3076.5, 16.615 + 0.6, 15000.0, 44.0, 21943.7, 14176.7, 3479.4, 16.785 + 0.6, 15000.0, 47.0, 23404.6, 14666.6, 3892.2, 16.874 + 0.6, 15000.0, 50.0, 24751.0, 15042.1, 4322.2, 16.834 + 0.6, 20000.0, 21.0, 6276.7, 5881.6, 481.8, 12.934 + 0.6, 20000.0, 26.0, 9662.4, 8082.0, 960.1, 15.334 + 0.6, 20000.0, 29.0, 11363.1, 8992.4, 1257.0, 16.031 + 0.6, 20000.0, 32.0, 12830.4, 9669.7, 1548.6, 16.369 + 0.6, 20000.0, 35.0, 14210.0, 10259.1, 1842.7, 16.615 + 0.6, 20000.0, 38.0, 15417.6, 10676.5, 2148.6, 16.602 + 0.6, 20000.0, 41.0, 16611.4, 11080.1, 2460.4, 16.617 + 0.6, 20000.0, 44.0, 17865.4, 11544.0, 2780.2, 16.787 + 0.6, 20000.0, 47.0, 19054.7, 11943.1, 3106.8, 16.875 + 0.6, 20000.0, 50.0, 20151.2, 12249.3, 3446.8, 16.833 + 0.6, 25000.0, 21.0, 5057.6, 4738.7, 402.6, 12.93 + 0.6, 25000.0, 26.0, 7798.1, 6522.6, 776.8, 15.338 + 0.6, 25000.0, 29.0, 9171.2, 7257.9, 1011.0, 16.034 + 0.6, 25000.0, 32.0, 10357.8, 7806.6, 1238.8, 16.373 + 0.6, 25000.0, 35.0, 11472.0, 8283.0, 1469.7, 16.618 + 0.6, 25000.0, 38.0, 12447.4, 8620.6, 1710.1, 16.605 + 0.6, 25000.0, 41.0, 13411.8, 8947.1, 1954.6, 16.62 + 0.6, 25000.0, 44.0, 14423.9, 9321.5, 2205.7, 16.789 + 0.6, 25000.0, 47.0, 15384.6, 9644.5, 2461.8, 16.877 + 0.6, 25000.0, 50.0, 16269.9, 9891.9, 2727.5, 16.834 + 0.6, 30000.0, 21.0, 4035.9, 3780.9, 337.9, 12.925 + 0.6, 30000.0, 26.0, 6235.4, 5215.1, 627.3, 15.344 + 0.6, 30000.0, 29.0, 7334.8, 5804.3, 810.3, 16.039 + 0.6, 30000.0, 32.0, 8285.6, 6244.9, 986.3, 16.379 + 0.6, 30000.0, 35.0, 9177.6, 6626.7, 1165.0, 16.623 + 0.6, 30000.0, 38.0, 9958.4, 6897.4, 1352.3, 16.61 + 0.6, 30000.0, 41.0, 10730.4, 7159.1, 1541.8, 16.624 + 0.6, 30000.0, 44.0, 11540.1, 7458.7, 1737.1, 16.792 + 0.6, 30000.0, 47.0, 12309.0, 7717.4, 1935.7, 16.88 + 0.6, 30000.0, 50.0, 13017.7, 7916.1, 2141.5, 16.836 + 0.6, 35000.0, 21.0, 3185.3, 2983.2, 287.4, 12.919 + 0.6, 35000.0, 26.0, 4935.9, 4127.5, 507.3, 15.352 + 0.6, 35000.0, 29.0, 5808.1, 4595.5, 647.7, 16.047 + 0.6, 35000.0, 32.0, 6563.1, 4946.3, 782.5, 16.389 + 0.6, 35000.0, 35.0, 7270.5, 5249.4, 919.3, 16.631 + 0.6, 35000.0, 38.0, 7889.7, 5464.5, 1063.0, 16.618 + 0.6, 35000.0, 41.0, 8501.6, 5672.2, 1208.5, 16.63 + 0.6, 35000.0, 44.0, 9143.3, 5909.7, 1358.5, 16.797 + 0.6, 35000.0, 47.0, 9752.9, 6115.2, 1511.3, 16.884 + 0.6, 35000.0, 50.0, 10314.6, 6272.7, 1668.2, 16.838 + 0.6, 39000.0, 21.0, 2617.4, 2450.5, 260.1, 12.913 + 0.6, 39000.0, 26.0, 4070.3, 3402.8, 435.3, 15.362 + 0.6, 39000.0, 29.0, 4791.4, 3790.1, 549.9, 16.056 + 0.6, 39000.0, 32.0, 5415.9, 4080.8, 659.8, 16.4 + 0.6, 39000.0, 35.0, 6000.2, 4331.3, 771.3, 16.64 + 0.6, 39000.0, 38.0, 6512.2, 4509.6, 888.3, 16.626 + 0.6, 39000.0, 41.0, 7017.6, 4681.3, 1007.1, 16.638 + 0.6, 39000.0, 44.0, 7547.4, 4877.3, 1130.2, 16.803 + 0.6, 39000.0, 47.0, 8050.9, 5047.1, 1255.3, 16.89 + 0.6, 39000.0, 50.0, 8514.8, 5177.2, 1383.5, 16.842 + 0.7, 15000.0, 21.0, 9812.7, 9327.8, 640.4, 12.521 + 0.7, 15000.0, 26.0, 14597.6, 12657.9, 1313.8, 14.949 + 0.7, 15000.0, 29.0, 16962.6, 14053.1, 1721.5, 15.728 + 0.7, 15000.0, 32.0, 18912.3, 15032.9, 2125.0, 16.089 + 0.7, 15000.0, 35.0, 20740.6, 15891.4, 2531.1, 16.368 + 0.7, 15000.0, 38.0, 22336.4, 16517.3, 2949.9, 16.428 + 0.7, 15000.0, 41.0, 23911.2, 17122.0, 3372.6, 16.504 + 0.7, 15000.0, 44.0, 25585.8, 17827.0, 3806.5, 16.731 + 0.7, 15000.0, 47.0, 27135.0, 18406.4, 4247.5, 16.84 + 0.7, 15000.0, 50.0, 28556.3, 18857.8, 4704.6, 16.824 + 0.7, 20000.0, 21.0, 7977.1, 7582.4, 529.2, 12.515 + 0.7, 20000.0, 26.0, 11881.1, 10302.6, 1062.6, 14.949 + 0.7, 20000.0, 29.0, 13807.1, 11439.2, 1386.6, 15.729 + 0.7, 20000.0, 32.0, 15396.4, 12239.3, 1706.2, 16.091 + 0.7, 20000.0, 35.0, 16885.7, 12939.4, 2027.9, 16.37 + 0.7, 20000.0, 38.0, 18185.1, 13449.4, 2359.6, 16.43 + 0.7, 20000.0, 41.0, 19467.3, 13942.2, 2695.0, 16.506 + 0.7, 20000.0, 44.0, 20830.5, 14516.2, 3039.3, 16.732 + 0.7, 20000.0, 47.0, 22092.1, 14988.7, 3389.3, 16.841 + 0.7, 20000.0, 50.0, 23249.2, 15356.5, 3750.4, 16.824 + 0.7, 25000.0, 21.0, 6425.3, 6106.8, 439.2, 12.506 + 0.7, 25000.0, 26.0, 9587.9, 8314.0, 856.3, 14.951 + 0.7, 25000.0, 29.0, 11143.3, 9232.5, 1111.9, 15.73 + 0.7, 25000.0, 32.0, 12428.4, 9880.7, 1361.8, 16.094 + 0.7, 25000.0, 35.0, 13632.0, 10447.4, 1614.4, 16.373 + 0.7, 25000.0, 38.0, 14681.1, 10859.6, 1875.1, 16.433 + 0.7, 25000.0, 41.0, 15716.0, 11257.5, 2138.7, 16.508 + 0.7, 25000.0, 44.0, 16816.6, 11721.3, 2409.3, 16.733 + 0.7, 25000.0, 47.0, 17835.4, 12103.2, 2683.6, 16.843 + 0.7, 25000.0, 50.0, 18770.3, 12401.1, 2966.4, 16.825 + 0.7, 30000.0, 21.0, 5125.3, 4870.6, 365.6, 12.495 + 0.7, 30000.0, 26.0, 7665.8, 6646.8, 689.0, 14.953 + 0.7, 30000.0, 29.0, 8911.4, 7383.0, 888.9, 15.732 + 0.7, 30000.0, 32.0, 9942.1, 7904.1, 1082.3, 16.099 + 0.7, 30000.0, 35.0, 10906.4, 8358.9, 1277.7, 16.378 + 0.7, 30000.0, 38.0, 11746.3, 8689.3, 1479.8, 16.437 + 0.7, 30000.0, 41.0, 12574.6, 9008.1, 1685.2, 16.512 + 0.7, 30000.0, 44.0, 13455.1, 9379.1, 1896.0, 16.736 + 0.7, 30000.0, 47.0, 14271.0, 9685.6, 2109.1, 16.845 + 0.7, 30000.0, 50.0, 15019.0, 9924.1, 2327.8, 16.827 + 0.7, 35000.0, 21.0, 4043.5, 3841.7, 306.6, 12.48 + 0.7, 35000.0, 26.0, 6067.4, 5260.2, 553.8, 14.958 + 0.7, 35000.0, 29.0, 7055.6, 5844.9, 708.0, 15.737 + 0.7, 35000.0, 32.0, 7874.5, 6260.1, 856.1, 16.106 + 0.7, 35000.0, 35.0, 8639.8, 6621.8, 1005.8, 16.385 + 0.7, 35000.0, 38.0, 9305.5, 6884.0, 1161.3, 16.443 + 0.7, 35000.0, 41.0, 9962.3, 7137.0, 1318.8, 16.517 + 0.7, 35000.0, 44.0, 10660.1, 7431.4, 1480.6, 16.74 + 0.7, 35000.0, 47.0, 11307.0, 7674.5, 1644.6, 16.849 + 0.7, 35000.0, 50.0, 11899.7, 7863.8, 1812.1, 16.829 + 0.7, 39000.0, 21.0, 3320.5, 3153.9, 274.0, 12.464 + 0.7, 39000.0, 26.0, 5002.8, 4336.3, 472.7, 14.964 + 0.7, 39000.0, 29.0, 5820.0, 4820.1, 599.1, 15.743 + 0.7, 39000.0, 32.0, 6497.8, 5164.6, 719.9, 16.115 + 0.7, 39000.0, 35.0, 7130.7, 5464.2, 842.2, 16.394 + 0.7, 39000.0, 38.0, 7680.7, 5680.9, 968.9, 16.45 + 0.7, 39000.0, 41.0, 8223.3, 5890.1, 1097.6, 16.523 + 0.7, 39000.0, 44.0, 8799.5, 6133.1, 1230.6, 16.746 + 0.7, 39000.0, 47.0, 9333.7, 6334.1, 1364.7, 16.854 + 0.7, 39000.0, 50.0, 9823.4, 6490.4, 1501.7, 16.833 + 0.7, 43000.0, 21.0, 2722.3, 2584.7, 250.5, 12.443 + 0.7, 43000.0, 26.0, 4122.9, 3572.4, 409.0, 14.97 + 0.7, 43000.0, 29.0, 4798.8, 3973.0, 512.6, 15.751 + 0.7, 43000.0, 32.0, 5360.0, 4259.1, 611.7, 16.127 + 0.7, 43000.0, 35.0, 5883.5, 4507.3, 711.9, 16.406 + 0.7, 43000.0, 38.0, 6338.1, 4686.6, 815.6, 16.459 + 0.7, 43000.0, 41.0, 6786.4, 4859.5, 921.4, 16.532 + 0.7, 43000.0, 44.0, 7262.0, 5060.1, 1031.0, 16.753 + 0.7, 43000.0, 47.0, 7703.0, 5225.8, 1141.7, 16.861 + 0.7, 43000.0, 50.0, 8107.7, 5355.2, 1254.4, 16.839 + 0.75, 25000.0, 21.0, 7219.4, 6898.5, 460.3, 12.397 + 0.75, 25000.0, 26.0, 10621.9, 9338.4, 901.7, 14.848 + 0.75, 25000.0, 29.0, 12284.9, 10359.7, 1169.8, 15.66 + 0.75, 25000.0, 32.0, 13627.6, 11060.7, 1433.3, 16.03 + 0.75, 25000.0, 35.0, 14883.7, 11675.1, 1697.8, 16.32 + 0.75, 25000.0, 38.0, 15979.8, 12129.4, 1971.6, 16.41 + 0.75, 25000.0, 41.0, 17059.2, 12566.9, 2246.1, 16.507 + 0.75, 25000.0, 44.0, 18213.8, 13079.9, 2529.1, 16.743 + 0.75, 25000.0, 47.0, 19270.2, 13494.6, 2815.6, 16.844 + 0.75, 25000.0, 50.0, 20237.8, 13820.4, 3109.9, 16.826 + 0.75, 30000.0, 21.0, 5757.6, 5500.9, 381.8, 12.383 + 0.75, 30000.0, 26.0, 8492.3, 7465.7, 724.3, 14.85 + 0.75, 30000.0, 29.0, 9824.2, 8284.2, 933.8, 15.661 + 0.75, 30000.0, 32.0, 10901.4, 8848.0, 1137.6, 16.035 + 0.75, 30000.0, 35.0, 11907.9, 9341.2, 1342.9, 16.324 + 0.75, 30000.0, 38.0, 12785.4, 9705.4, 1555.2, 16.414 + 0.75, 30000.0, 41.0, 13649.3, 10055.9, 1769.5, 16.511 + 0.75, 30000.0, 44.0, 14573.1, 10466.4, 1988.7, 16.746 + 0.75, 30000.0, 47.0, 15419.1, 10799.1, 2211.5, 16.847 + 0.75, 30000.0, 50.0, 16193.3, 11059.9, 2439.5, 16.828 + 0.75, 35000.0, 21.0, 4541.3, 4338.0, 318.5, 12.364 + 0.75, 35000.0, 26.0, 6720.9, 5907.7, 580.7, 14.852 + 0.75, 35000.0, 29.0, 7777.6, 6557.9, 742.4, 15.664 + 0.75, 35000.0, 32.0, 8633.5, 7007.3, 898.5, 16.041 + 0.75, 35000.0, 35.0, 9432.5, 7399.7, 1056.0, 16.331 + 0.75, 35000.0, 38.0, 10128.3, 7688.9, 1218.5, 16.419 + 0.75, 35000.0, 41.0, 10813.0, 7966.9, 1383.3, 16.515 + 0.75, 35000.0, 44.0, 11544.9, 8292.4, 1552.4, 16.749 + 0.75, 35000.0, 47.0, 12215.4, 8556.3, 1723.2, 16.851 + 0.75, 35000.0, 50.0, 12829.4, 8763.8, 1898.1, 16.83 + 0.75, 39000.0, 21.0, 3729.3, 3561.4, 282.4, 12.345 + 0.75, 39000.0, 26.0, 5541.5, 4870.0, 494.3, 14.857 + 0.75, 39000.0, 29.0, 6415.2, 5408.0, 627.2, 15.669 + 0.75, 39000.0, 32.0, 7124.0, 5781.0, 754.6, 16.049 + 0.75, 39000.0, 35.0, 7784.8, 6106.0, 883.2, 16.34 + 0.75, 39000.0, 38.0, 8359.7, 6345.2, 1015.9, 16.426 + 0.75, 39000.0, 41.0, 8925.5, 6575.0, 1150.5, 16.521 + 0.75, 39000.0, 44.0, 9529.8, 6843.8, 1289.3, 16.755 + 0.75, 39000.0, 47.0, 10083.6, 7061.8, 1429.5, 16.855 + 0.75, 39000.0, 50.0, 10590.8, 7233.2, 1572.3, 16.834 + 0.75, 43000.0, 21.0, 3056.5, 2917.8, 256.4, 12.318 + 0.75, 43000.0, 26.0, 4566.6, 4012.1, 426.2, 14.861 + 0.75, 43000.0, 29.0, 5289.3, 4457.4, 535.6, 15.675 + 0.75, 43000.0, 32.0, 5876.5, 4767.4, 640.3, 16.059 + 0.75, 43000.0, 35.0, 6423.2, 5036.8, 745.8, 16.351 + 0.75, 43000.0, 38.0, 6898.2, 5234.5, 854.2, 16.435 + 0.75, 43000.0, 41.0, 7365.7, 5424.6, 965.0, 16.529 + 0.75, 43000.0, 44.0, 7864.6, 5646.4, 1079.4, 16.761 + 0.75, 43000.0, 47.0, 8322.2, 5826.6, 1195.1, 16.862 + 0.75, 43000.0, 50.0, 8741.0, 5968.1, 1312.7, 16.839 + 0.8, 25000.0, 21.0, 8098.0, 7773.0, 483.7, 12.344 + 0.8, 25000.0, 26.0, 11761.6, 10461.7, 951.6, 14.801 + 0.8, 25000.0, 29.0, 13531.2, 11581.4, 1234.5, 15.623 + 0.8, 25000.0, 32.0, 14949.6, 12349.8, 1512.3, 16.015 + 0.8, 25000.0, 35.0, 16264.5, 13014.7, 1790.8, 16.313 + 0.8, 25000.0, 38.0, 17413.4, 13513.7, 2077.6, 16.417 + 0.8, 25000.0, 41.0, 18544.0, 13994.4, 2366.1, 16.514 + 0.8, 25000.0, 44.0, 19760.6, 14561.0, 2663.1, 16.753 + 0.8, 25000.0, 47.0, 20860.3, 15010.8, 2963.6, 16.846 + 0.8, 25000.0, 50.0, 21866.3, 15366.8, 3272.0, 16.827 + 0.8, 30000.0, 21.0, 6456.8, 6196.9, 399.6, 12.328 + 0.8, 30000.0, 26.0, 9402.7, 8363.1, 762.6, 14.8 + 0.8, 30000.0, 29.0, 10822.3, 9262.9, 983.2, 15.627 + 0.8, 30000.0, 32.0, 11958.1, 9878.9, 1198.5, 16.018 + 0.8, 30000.0, 35.0, 13011.8, 10412.8, 1414.8, 16.317 + 0.8, 30000.0, 38.0, 13931.5, 10812.7, 1637.6, 16.42 + 0.8, 30000.0, 41.0, 14836.3, 11197.7, 1862.2, 16.517 + 0.8, 30000.0, 44.0, 15809.6, 11651.2, 2093.1, 16.755 + 0.8, 30000.0, 47.0, 16690.5, 12012.2, 2326.7, 16.848 + 0.8, 30000.0, 50.0, 17495.4, 12297.4, 2565.6, 16.829 + 0.8, 35000.0, 21.0, 5092.2, 4886.4, 331.7, 12.306 + 0.8, 35000.0, 26.0, 7441.1, 6617.8, 610.1, 14.801 + 0.8, 35000.0, 29.0, 8569.4, 7334.3, 780.2, 15.632 + 0.8, 35000.0, 32.0, 9470.5, 7823.7, 945.2, 16.023 + 0.8, 35000.0, 35.0, 10306.9, 8248.5, 1111.5, 16.323 + 0.8, 35000.0, 38.0, 11036.4, 8566.3, 1281.8, 16.426 + 0.8, 35000.0, 41.0, 11753.4, 8871.5, 1454.7, 16.522 + 0.8, 35000.0, 44.0, 12524.7, 9231.2, 1632.5, 16.758 + 0.8, 35000.0, 47.0, 13222.6, 9517.5, 1811.9, 16.852 + 0.8, 35000.0, 50.0, 13861.2, 9744.3, 1995.1, 16.831 + 0.8, 39000.0, 21.0, 4181.9, 4012.0, 292.0, 12.284 + 0.8, 39000.0, 26.0, 6135.1, 5455.1, 518.3, 14.804 + 0.8, 39000.0, 29.0, 7069.3, 6049.4, 658.0, 15.639 + 0.8, 39000.0, 32.0, 7814.5, 6454.6, 792.9, 16.03 + 0.8, 39000.0, 35.0, 8506.4, 6806.4, 928.7, 16.331 + 0.8, 39000.0, 38.0, 9109.3, 7069.4, 1067.4, 16.432 + 0.8, 39000.0, 41.0, 9701.6, 7321.6, 1209.1, 16.527 + 0.8, 39000.0, 44.0, 10338.4, 7618.6, 1354.9, 16.763 + 0.8, 39000.0, 47.0, 10915.2, 7855.4, 1502.1, 16.856 + 0.8, 39000.0, 50.0, 11442.3, 8042.5, 1651.9, 16.835 + 0.8, 43000.0, 21.0, 3426.6, 3286.2, 263.3, 12.253 + 0.8, 43000.0, 26.0, 5055.8, 4494.2, 445.4, 14.808 + 0.8, 43000.0, 29.0, 5829.7, 4987.3, 560.9, 15.649 + 0.8, 43000.0, 32.0, 6446.0, 5322.8, 671.7, 16.04 + 0.8, 43000.0, 35.0, 7018.5, 5614.5, 783.2, 16.341 + 0.8, 43000.0, 38.0, 7516.7, 5832.0, 896.7, 16.44 + 0.8, 43000.0, 41.0, 8006.1, 6040.6, 1013.2, 16.535 + 0.8, 43000.0, 44.0, 8532.5, 6286.0, 1133.6, 16.77 + 0.8, 43000.0, 47.0, 9008.3, 6481.1, 1255.1, 16.862 + 0.8, 43000.0, 50.0, 9443.7, 6635.9, 1378.6, 16.84 + 0.85, 30000.0, 21.0, 7231.1, 6966.7, 419.5, 12.324 + 0.85, 30000.0, 26.0, 10406.0, 9348.1, 804.6, 14.802 + 0.85, 30000.0, 29.0, 11913.9, 10327.1, 1037.7, 15.629 + 0.85, 30000.0, 32.0, 13121.6, 11005.9, 1265.7, 16.041 + 0.85, 30000.0, 35.0, 14227.8, 11583.1, 1493.8, 16.326 + 0.85, 30000.0, 38.0, 15196.2, 12022.5, 1729.0, 16.428 + 0.85, 30000.0, 41.0, 16147.3, 12444.8, 1965.6, 16.523 + 0.85, 30000.0, 44.0, 17177.2, 12945.7, 2209.6, 16.763 + 0.85, 30000.0, 47.0, 18097.2, 13336.7, 2456.0, 16.849 + 0.85, 30000.0, 50.0, 18937.4, 13648.0, 2708.4, 16.83 + 0.85, 35000.0, 21.0, 5702.0, 5492.5, 346.4, 12.299 + 0.85, 35000.0, 26.0, 8234.8, 7397.0, 642.3, 14.801 + 0.85, 35000.0, 29.0, 9434.0, 8177.3, 821.7, 15.634 + 0.85, 35000.0, 32.0, 10391.9, 8716.3, 997.0, 16.046 + 0.85, 35000.0, 35.0, 11270.1, 9175.5, 1172.3, 16.332 + 0.85, 35000.0, 38.0, 12038.3, 9524.8, 1352.2, 16.433 + 0.85, 35000.0, 41.0, 12792.2, 9859.7, 1534.4, 16.527 + 0.85, 35000.0, 44.0, 13608.2, 10256.9, 1722.1, 16.767 + 0.85, 35000.0, 47.0, 14337.7, 10567.4, 1911.7, 16.853 + 0.85, 35000.0, 50.0, 15003.7, 10814.5, 2105.3, 16.832 + 0.85, 39000.0, 21.0, 4683.3, 4510.4, 303.1, 12.275 + 0.85, 39000.0, 26.0, 6789.1, 6097.2, 544.5, 14.802 + 0.85, 39000.0, 29.0, 7782.2, 6744.4, 691.9, 15.64 + 0.85, 39000.0, 32.0, 8574.5, 7190.7, 835.0, 16.052 + 0.85, 39000.0, 35.0, 9300.9, 7571.3, 978.5, 16.339 + 0.85, 39000.0, 38.0, 9936.0, 7860.4, 1125.0, 16.439 + 0.85, 39000.0, 41.0, 10558.8, 8137.3, 1274.4, 16.533 + 0.85, 39000.0, 44.0, 11232.4, 8465.0, 1428.4, 16.771 + 0.85, 39000.0, 47.0, 11835.0, 8721.5, 1583.9, 16.857 + 0.85, 39000.0, 50.0, 12385.1, 8925.8, 1742.2, 16.835 + 0.85, 43000.0, 21.0, 3837.2, 3694.4, 271.4, 12.241 + 0.85, 43000.0, 26.0, 5594.5, 5023.1, 466.8, 14.804 + 0.85, 43000.0, 29.0, 6417.3, 5560.1, 588.6, 15.648 + 0.85, 43000.0, 32.0, 7072.8, 5930.0, 706.3, 16.061 + 0.85, 43000.0, 35.0, 7674.0, 6245.4, 824.2, 16.349 + 0.85, 43000.0, 38.0, 8199.0, 6484.7, 943.9, 16.447 + 0.85, 43000.0, 41.0, 8713.6, 6713.6, 1067.0, 16.54 + 0.85, 43000.0, 44.0, 9269.6, 6983.9, 1194.2, 16.777 + 0.85, 43000.0, 47.0, 9767.6, 7196.1, 1322.7, 16.863 + 0.85, 43000.0, 50.0, 10221.8, 7364.6, 1453.0, 16.84 + 0.9, 35000.0, 21.0, 6377.2, 6163.0, 362.8, 12.339 + 0.9, 35000.0, 26.0, 9108.9, 8252.4, 677.5, 14.846 + 0.9, 35000.0, 29.0, 10384.7, 9099.9, 867.2, 15.664 + 0.9, 35000.0, 32.0, 11406.5, 9693.4, 1053.9, 16.072 + 0.9, 35000.0, 35.0, 12331.9, 10190.5, 1239.7, 16.341 + 0.9, 35000.0, 38.0, 13143.7, 10574.1, 1430.6, 16.44 + 0.9, 35000.0, 41.0, 13939.6, 10941.6, 1623.9, 16.533 + 0.9, 35000.0, 44.0, 14805.2, 11379.0, 1823.0, 16.774 + 0.9, 35000.0, 47.0, 15569.8, 11715.3, 2024.2, 16.853 + 0.9, 35000.0, 50.0, 16266.9, 11984.1, 2229.9, 16.832 + 0.9, 39000.0, 21.0, 5237.5, 5060.7, 316.0, 12.313 + 0.9, 39000.0, 26.0, 7509.5, 6802.1, 573.1, 14.846 + 0.9, 39000.0, 29.0, 8566.5, 7505.5, 729.0, 15.67 + 0.9, 39000.0, 32.0, 9411.5, 7996.9, 881.6, 16.078 + 0.9, 39000.0, 35.0, 10177.1, 8408.8, 1033.8, 16.348 + 0.9, 39000.0, 38.0, 10848.4, 8726.3, 1189.3, 16.446 + 0.9, 39000.0, 41.0, 11505.6, 9029.9, 1347.7, 16.538 + 0.9, 39000.0, 44.0, 12220.6, 9391.3, 1511.2, 16.779 + 0.9, 39000.0, 47.0, 12852.0, 9669.0, 1676.3, 16.857 + 0.9, 39000.0, 50.0, 13427.8, 9891.1, 1844.4, 16.835 + 0.9, 43000.0, 21.0, 4292.4, 4146.4, 280.7, 12.277 + 0.9, 43000.0, 26.0, 6187.8, 5603.7, 490.2, 14.846 + 0.9, 43000.0, 29.0, 7063.7, 6187.5, 619.0, 15.677 + 0.9, 43000.0, 32.0, 7762.8, 6594.6, 744.5, 16.086 + 0.9, 43000.0, 35.0, 8396.5, 6936.1, 869.6, 16.356 + 0.9, 43000.0, 38.0, 8951.5, 7199.1, 996.7, 16.454 + 0.9, 43000.0, 41.0, 9494.4, 7449.9, 1127.5, 16.545 + 0.9, 43000.0, 44.0, 10084.8, 7748.2, 1262.3, 16.785 + 0.9, 43000.0, 47.0, 10606.2, 7977.6, 1398.7, 16.863 + 0.9, 43000.0, 50.0, 11081.8, 8161.1, 1537.2, 16.84 + \ No newline at end of file diff --git a/aviary/validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.deck b/aviary/validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.deck deleted file mode 100644 index e539a0731a..0000000000 --- a/aviary/validation_cases/validation_data/flops_data/engine_only/turbofan_23k_2.deck +++ /dev/null @@ -1,625 +0,0 @@ -# FLOPS-derived engine deck converted from turbofan_23k_2_ENGDEK - -Mach_Number (unitless), Altitude (ft), Throttle (unitless), Gross_Thrust (lbf), Ram_Drag (lbf), Fuel_Flow (lb/h), NOx_Rate (lb/h) - 0.0, 0.0, 26.0, 4600.1, 0.0, 995.6, 24.271 - 0.0, 0.0, 29.0, 6900.2, 0.0, 1413.7, 22.261 - 0.0, 0.0, 32.0, 9200.3, 0.0, 1851.6, 21.723 - 0.0, 0.0, 35.0, 11500.3, 0.0, 2333.1, 20.97 - 0.0, 0.0, 38.0, 13800.7, 0.0, 2852.6, 20.367 - 0.0, 0.0, 41.0, 16100.6, 0.0, 3416.1, 19.773 - 0.0, 0.0, 44.0, 18400.6, 0.0, 4016.9, 19.147 - 0.0, 0.0, 47.0, 20700.5, 0.0, 4660.3, 18.591 - 0.0, 0.0, 50.0, 23000.7, 0.0, 5341.5, 18.367 - 0.0, 2000.0, 26.0, 4399.1, 0.0, 947.3, 24.076 - 0.0, 2000.0, 29.0, 6598.6, 0.0, 1345.6, 22.182 - 0.0, 2000.0, 32.0, 8798.1, 0.0, 1764.0, 21.622 - 0.0, 2000.0, 35.0, 10997.6, 0.0, 2223.0, 20.904 - 0.0, 2000.0, 38.0, 13197.1, 0.0, 2724.6, 20.245 - 0.0, 2000.0, 41.0, 15396.7, 0.0, 3260.3, 19.688 - 0.0, 2000.0, 44.0, 17596.2, 0.0, 3840.8, 19.002 - 0.0, 2000.0, 47.0, 19795.6, 0.0, 4460.8, 18.478 - 0.0, 2000.0, 50.0, 21995.3, 0.0, 5112.9, 18.344 - 0.0, 5000.0, 26.0, 4099.1, 0.0, 876.9, 23.814 - 0.0, 5000.0, 29.0, 6148.6, 0.0, 1245.6, 22.081 - 0.0, 5000.0, 32.0, 8198.2, 0.0, 1635.5, 21.462 - 0.0, 5000.0, 35.0, 10247.8, 0.0, 2059.6, 20.819 - 0.0, 5000.0, 38.0, 12297.3, 0.0, 2533.6, 20.08 - 0.0, 5000.0, 41.0, 14346.8, 0.0, 3032.4, 19.515 - 0.0, 5000.0, 44.0, 16396.3, 0.0, 3577.5, 18.808 - 0.0, 5000.0, 47.0, 18445.9, 0.0, 4159.8, 18.392 - 0.0, 5000.0, 50.0, 20495.4, 0.0, 4775.3, 18.263 - 0.0, 10000.0, 26.0, 3604.9, 0.0, 765.8, 23.451 - 0.0, 10000.0, 29.0, 5407.4, 0.0, 1085.6, 21.954 - 0.0, 10000.0, 32.0, 7209.6, 0.0, 1427.6, 21.247 - 0.0, 10000.0, 35.0, 9012.2, 0.0, 1798.3, 20.623 - 0.0, 10000.0, 38.0, 10814.6, 0.0, 2217.9, 19.855 - 0.0, 10000.0, 41.0, 12617.1, 0.0, 2664.2, 19.165 - 0.0, 10000.0, 44.0, 14419.6, 0.0, 3145.7, 18.54 - 0.0, 10000.0, 47.0, 16222.1, 0.0, 3657.6, 18.348 - 0.0, 10000.0, 50.0, 18024.4, 0.0, 4230.1, 17.994 - 0.1, 0.0, 26.0, 5979.4, 1910.4, 1175.2, 21.966 - 0.1, 0.0, 29.0, 8312.8, 2209.3, 1613.3, 21.233 - 0.1, 0.0, 32.0, 10606.4, 2468.3, 2069.5, 20.839 - 0.1, 0.0, 35.0, 12859.7, 2687.0, 2550.1, 20.432 - 0.1, 0.0, 38.0, 15066.8, 2859.9, 3076.6, 19.84 - 0.1, 0.0, 41.0, 17265.5, 3024.0, 3619.1, 19.426 - 0.1, 0.0, 44.0, 19426.4, 3150.4, 4202.8, 18.823 - 0.1, 0.0, 47.0, 21585.1, 3274.6, 4819.2, 18.379 - 0.1, 0.0, 50.0, 23762.9, 3417.9, 5468.2, 18.251 - 0.1, 2000.0, 26.0, 5693.6, 1793.8, 1116.0, 21.886 - 0.1, 2000.0, 29.0, 7928.8, 2079.2, 1533.2, 21.211 - 0.1, 2000.0, 32.0, 10120.0, 2320.5, 1969.5, 20.769 - 0.1, 2000.0, 35.0, 12278.5, 2528.9, 2427.4, 20.394 - 0.1, 2000.0, 38.0, 14386.9, 2687.6, 2935.3, 19.748 - 0.1, 2000.0, 41.0, 16487.9, 2838.6, 3457.2, 19.294 - 0.1, 2000.0, 44.0, 18557.2, 2958.0, 4016.4, 18.699 - 0.1, 2000.0, 47.0, 20626.0, 3077.1, 4610.8, 18.282 - 0.1, 2000.0, 50.0, 22718.4, 3219.5, 5234.5, 18.232 - 0.1, 5000.0, 26.0, 5266.6, 1627.7, 1029.0, 21.785 - 0.1, 5000.0, 29.0, 7350.8, 1892.3, 1413.8, 21.186 - 0.1, 5000.0, 32.0, 9387.0, 2108.9, 1819.8, 20.681 - 0.1, 5000.0, 35.0, 11391.2, 2293.7, 2248.1, 20.227 - 0.1, 5000.0, 38.0, 13358.5, 2441.4, 2719.6, 19.63 - 0.1, 5000.0, 41.0, 15308.8, 2572.2, 3210.5, 19.094 - 0.1, 5000.0, 44.0, 17239.8, 2683.6, 3733.6, 18.539 - 0.1, 5000.0, 47.0, 19179.8, 2804.2, 4291.0, 18.267 - 0.1, 5000.0, 50.0, 21120.3, 2925.2, 4884.1, 18.123 - 0.1, 10000.0, 26.0, 4595.6, 1376.8, 894.9, 21.64 - 0.1, 10000.0, 29.0, 6436.5, 1608.4, 1228.2, 21.165 - 0.1, 10000.0, 32.0, 8226.1, 1788.6, 1585.3, 20.56 - 0.1, 10000.0, 35.0, 9985.7, 1938.9, 1967.7, 19.984 - 0.1, 10000.0, 38.0, 11725.4, 2069.1, 2376.8, 19.462 - 0.1, 10000.0, 41.0, 13436.9, 2171.5, 2816.2, 18.798 - 0.1, 10000.0, 44.0, 15144.7, 2269.8, 3283.2, 18.306 - 0.1, 10000.0, 47.0, 16870.6, 2386.2, 3777.3, 18.229 - 0.1, 10000.0, 50.0, 18565.1, 2471.4, 4327.8, 17.869 - 0.2, 0.0, 26.0, 7753.2, 4098.6, 1332.2, 19.678 - 0.2, 0.0, 29.0, 10194.5, 4712.7, 1794.3, 19.81 - 0.2, 0.0, 32.0, 12500.9, 5191.8, 2274.0, 19.648 - 0.2, 0.0, 35.0, 14743.1, 5606.7, 2765.1, 19.472 - 0.2, 0.0, 38.0, 16895.8, 5932.1, 3296.4, 19.088 - 0.2, 0.0, 41.0, 19025.5, 6234.6, 3837.1, 18.78 - 0.2, 0.0, 44.0, 21092.8, 6474.5, 4407.5, 18.338 - 0.2, 0.0, 47.0, 23158.2, 6712.7, 5008.9, 18.018 - 0.2, 0.0, 50.0, 25268.1, 6995.4, 5639.1, 17.987 - 0.2, 2000.0, 26.0, 7360.6, 3850.3, 1264.7, 19.677 - 0.2, 2000.0, 29.0, 9701.6, 4436.1, 1705.3, 19.839 - 0.2, 2000.0, 32.0, 11902.5, 4881.9, 2162.9, 19.628 - 0.2, 2000.0, 35.0, 14039.5, 5263.8, 2637.0, 19.395 - 0.2, 2000.0, 38.0, 16105.3, 5575.4, 3143.0, 19.033 - 0.2, 2000.0, 41.0, 18135.0, 5848.9, 3665.1, 18.665 - 0.2, 2000.0, 44.0, 20120.4, 6079.1, 4213.9, 18.244 - 0.2, 2000.0, 47.0, 22113.7, 6317.3, 4793.5, 17.988 - 0.2, 2000.0, 50.0, 24141.0, 6589.4, 5399.3, 17.98 - 0.2, 5000.0, 26.0, 6778.9, 3494.9, 1164.7, 19.679 - 0.2, 5000.0, 29.0, 8961.3, 4035.3, 1573.0, 19.864 - 0.2, 5000.0, 32.0, 11005.6, 4437.4, 1995.9, 19.606 - 0.2, 5000.0, 35.0, 12984.3, 4774.4, 2441.1, 19.296 - 0.2, 5000.0, 38.0, 14916.7, 5064.9, 2908.6, 18.964 - 0.2, 5000.0, 41.0, 16793.8, 5299.9, 3399.5, 18.516 - 0.2, 5000.0, 44.0, 18650.7, 5514.8, 3915.1, 18.122 - 0.2, 5000.0, 47.0, 20533.7, 5755.8, 4459.8, 17.99 - 0.2, 5000.0, 50.0, 22399.6, 5979.7, 5038.2, 17.866 - 0.2, 10000.0, 26.0, 5878.8, 2959.1, 1011.2, 19.693 - 0.2, 10000.0, 29.0, 7791.7, 3412.2, 1368.2, 19.78 - 0.2, 10000.0, 32.0, 9604.9, 3765.6, 1736.6, 19.586 - 0.2, 10000.0, 35.0, 11337.0, 4037.9, 2133.4, 19.15 - 0.2, 10000.0, 38.0, 13042.6, 4283.6, 2544.4, 18.797 - 0.2, 10000.0, 41.0, 14694.4, 4475.4, 2980.5, 18.291 - 0.2, 10000.0, 44.0, 16351.5, 4672.9, 3443.2, 17.989 - 0.2, 10000.0, 47.0, 18034.3, 4895.7, 3929.6, 17.963 - 0.2, 10000.0, 50.0, 19650.4, 5052.1, 4465.2, 17.647 - 0.25, 0.0, 26.0, 8783.7, 5305.0, 1408.2, 18.719 - 0.25, 0.0, 29.0, 11302.5, 6084.4, 1886.1, 19.126 - 0.25, 0.0, 32.0, 13621.0, 6663.6, 2374.8, 19.063 - 0.25, 0.0, 35.0, 15860.6, 7163.8, 2875.9, 18.956 - 0.25, 0.0, 38.0, 18005.2, 7569.0, 3407.5, 18.695 - 0.25, 0.0, 41.0, 20107.6, 7932.2, 3949.5, 18.436 - 0.25, 0.0, 44.0, 22143.1, 8228.1, 4518.1, 18.077 - 0.25, 0.0, 47.0, 24175.5, 8521.3, 5113.7, 17.815 - 0.25, 0.0, 50.0, 26266.5, 8873.0, 5738.0, 17.826 - 0.25, 2000.0, 26.0, 8329.8, 4984.6, 1336.8, 18.743 - 0.25, 2000.0, 29.0, 10739.8, 5722.0, 1793.2, 19.146 - 0.25, 2000.0, 32.0, 12957.2, 6266.8, 2258.7, 19.065 - 0.25, 2000.0, 35.0, 15089.5, 6726.3, 2742.2, 18.901 - 0.25, 2000.0, 38.0, 17150.3, 7114.6, 3249.0, 18.658 - 0.25, 2000.0, 41.0, 19150.1, 7441.8, 3772.4, 18.34 - 0.25, 2000.0, 44.0, 21106.8, 7725.9, 4320.3, 17.997 - 0.25, 2000.0, 47.0, 23077.4, 8023.9, 4895.2, 17.81 - 0.25, 2000.0, 50.0, 25084.3, 8358.2, 5495.0, 17.827 - 0.25, 5000.0, 26.0, 7661.4, 4526.2, 1231.1, 18.779 - 0.25, 5000.0, 29.0, 9893.9, 5191.1, 1654.1, 19.123 - 0.25, 5000.0, 32.0, 11967.9, 5697.7, 2084.5, 19.071 - 0.25, 5000.0, 35.0, 13940.3, 6102.3, 2538.6, 18.831 - 0.25, 5000.0, 38.0, 15870.0, 6464.5, 3007.2, 18.613 - 0.25, 5000.0, 41.0, 17717.5, 6744.4, 3500.1, 18.214 - 0.25, 5000.0, 44.0, 19550.3, 7009.7, 4015.0, 17.894 - 0.25, 5000.0, 47.0, 21420.0, 7311.8, 4556.7, 17.823 - 0.25, 5000.0, 50.0, 23258.9, 7583.1, 5129.8, 17.717 - 0.25, 10000.0, 26.0, 6628.0, 3833.9, 1068.2, 18.847 - 0.25, 10000.0, 29.0, 8582.3, 4391.0, 1437.6, 19.095 - 0.25, 10000.0, 32.0, 10423.1, 4834.8, 1813.1, 19.085 - 0.25, 10000.0, 35.0, 12147.5, 5162.1, 2217.5, 18.731 - 0.25, 10000.0, 38.0, 13840.4, 5457.9, 2631.9, 18.435 - 0.25, 10000.0, 41.0, 15475.3, 5695.7, 3070.2, 18.026 - 0.25, 10000.0, 44.0, 17121.7, 5945.2, 3531.9, 17.812 - 0.25, 10000.0, 47.0, 18788.4, 6214.8, 4017.4, 17.794 - 0.25, 10000.0, 50.0, 20377.3, 6406.5, 4546.6, 17.52 - 0.3, 0.0, 26.0, 9870.2, 6574.4, 1473.1, 17.86 - 0.3, 0.0, 29.0, 12453.8, 7510.1, 1963.6, 18.433 - 0.3, 0.0, 32.0, 14787.7, 8196.1, 2457.4, 18.5 - 0.3, 0.0, 35.0, 17019.7, 8780.3, 2962.2, 18.471 - 0.3, 0.0, 38.0, 19150.2, 9262.8, 3492.4, 18.312 - 0.3, 0.0, 41.0, 21223.7, 9687.6, 4030.9, 18.118 - 0.3, 0.0, 44.0, 23219.9, 10036.7, 4594.8, 17.83 - 0.3, 0.0, 47.0, 25212.8, 10381.8, 5180.4, 17.62 - 0.3, 0.0, 50.0, 27273.3, 10794.4, 5793.5, 17.651 - 0.3, 2000.0, 26.0, 9351.5, 6178.5, 1398.5, 17.904 - 0.3, 2000.0, 29.0, 11812.2, 7052.6, 1867.1, 18.435 - 0.3, 2000.0, 32.0, 14054.9, 7708.9, 2337.6, 18.519 - 0.3, 2000.0, 35.0, 16177.2, 8244.6, 2824.8, 18.435 - 0.3, 2000.0, 38.0, 18226.3, 8707.2, 3330.0, 18.291 - 0.3, 2000.0, 41.0, 20194.5, 9088.9, 3850.5, 18.038 - 0.3, 2000.0, 44.0, 22116.1, 9424.1, 4394.1, 17.763 - 0.3, 2000.0, 47.0, 24052.0, 9773.5, 4959.5, 17.616 - 0.3, 2000.0, 50.0, 26034.2, 10169.1, 5549.5, 17.662 - 0.3, 5000.0, 26.0, 8596.0, 5613.8, 1289.0, 17.967 - 0.3, 5000.0, 29.0, 10875.2, 6401.9, 1723.6, 18.44 - 0.3, 5000.0, 32.0, 12977.5, 7013.0, 2159.6, 18.551 - 0.3, 5000.0, 35.0, 14938.8, 7483.2, 2618.2, 18.389 - 0.3, 5000.0, 38.0, 16862.7, 7915.5, 3086.0, 18.266 - 0.3, 5000.0, 41.0, 18677.6, 8240.0, 3578.0, 17.931 - 0.3, 5000.0, 44.0, 20482.3, 8553.7, 4088.9, 17.676 - 0.3, 5000.0, 47.0, 22330.5, 8910.8, 4623.8, 17.642 - 0.3, 5000.0, 50.0, 24145.9, 9235.0, 5186.0, 17.58 - 0.3, 10000.0, 26.0, 7422.8, 4757.6, 1118.5, 18.078 - 0.3, 10000.0, 29.0, 9415.2, 5417.4, 1498.6, 18.458 - 0.3, 10000.0, 32.0, 11269.8, 5939.5, 1880.1, 18.546 - 0.3, 10000.0, 35.0, 12994.9, 6331.9, 2287.2, 18.329 - 0.3, 10000.0, 38.0, 14672.9, 6677.2, 2703.0, 18.101 - 0.3, 10000.0, 41.0, 16287.7, 6959.4, 3141.1, 17.776 - 0.3, 10000.0, 44.0, 17917.5, 7256.6, 3598.9, 17.623 - 0.3, 10000.0, 47.0, 19570.2, 7576.7, 4079.0, 17.639 - 0.3, 10000.0, 50.0, 21128.8, 7802.7, 4598.6, 17.406 - 0.3, 15000.0, 21.0, 3388.6, 2833.2, 449.8, 17.237 - 0.3, 15000.0, 26.0, 6146.0, 3924.4, 897.6, 18.105 - 0.3, 15000.0, 29.0, 7800.3, 4467.9, 1196.2, 18.467 - 0.3, 15000.0, 32.0, 9338.9, 4895.8, 1495.8, 18.53 - 0.3, 15000.0, 35.0, 10776.5, 5222.6, 1815.9, 18.319 - 0.3, 15000.0, 38.0, 12167.9, 5503.1, 2144.2, 18.065 - 0.3, 15000.0, 41.0, 13513.9, 5738.4, 2488.4, 17.747 - 0.3, 15000.0, 44.0, 14879.6, 5993.2, 2849.7, 17.632 - 0.3, 15000.0, 47.0, 16244.4, 6247.2, 3229.4, 17.603 - 0.3, 15000.0, 50.0, 17542.0, 6434.0, 3638.3, 17.368 - 0.4, 0.0, 26.0, 12347.7, 9349.8, 1589.5, 16.412 - 0.4, 0.0, 29.0, 15088.1, 10591.1, 2106.9, 17.154 - 0.4, 0.0, 32.0, 17516.9, 11521.2, 2614.1, 17.458 - 0.4, 0.0, 35.0, 19773.1, 12278.6, 3129.8, 17.568 - 0.4, 0.0, 38.0, 21913.4, 12919.8, 3661.8, 17.571 - 0.4, 0.0, 41.0, 23967.5, 13475.0, 4199.7, 17.502 - 0.4, 0.0, 44.0, 25921.6, 13930.1, 4762.6, 17.337 - 0.4, 0.0, 47.0, 27869.6, 14378.8, 5337.2, 17.218 - 0.4, 0.0, 50.0, 29893.6, 14904.3, 5933.9, 17.28 - 0.4, 2000.0, 26.0, 11683.3, 8790.2, 1509.7, 16.482 - 0.4, 2000.0, 29.0, 14288.7, 9949.1, 2004.3, 17.188 - 0.4, 2000.0, 32.0, 16625.7, 10839.4, 2488.1, 17.506 - 0.4, 2000.0, 35.0, 18764.4, 11531.7, 2985.8, 17.565 - 0.4, 2000.0, 38.0, 20826.1, 12146.8, 3493.3, 17.578 - 0.4, 2000.0, 41.0, 22768.5, 12642.8, 4014.2, 17.453 - 0.4, 2000.0, 44.0, 24651.8, 13080.3, 4557.2, 17.296 - 0.4, 2000.0, 47.0, 26542.1, 13523.3, 5110.2, 17.209 - 0.4, 2000.0, 50.0, 28509.6, 14044.2, 5687.9, 17.312 - 0.4, 5000.0, 26.0, 10729.1, 7996.0, 1394.0, 16.586 - 0.4, 5000.0, 29.0, 13139.9, 9040.2, 1854.0, 17.24 - 0.4, 5000.0, 32.0, 15337.4, 9870.9, 2303.5, 17.581 - 0.4, 5000.0, 35.0, 17307.9, 10475.1, 2773.2, 17.564 - 0.4, 5000.0, 38.0, 19249.7, 11050.3, 3245.0, 17.592 - 0.4, 5000.0, 41.0, 21034.1, 11468.2, 3739.7, 17.385 - 0.4, 5000.0, 44.0, 22811.5, 11879.0, 4250.9, 17.243 - 0.4, 5000.0, 47.0, 24640.9, 12341.8, 4777.8, 17.266 - 0.4, 5000.0, 50.0, 26450.4, 12784.7, 5324.9, 17.301 - 0.4, 10000.0, 26.0, 9247.9, 6787.1, 1212.3, 16.759 - 0.4, 10000.0, 29.0, 11352.0, 7660.7, 1615.6, 17.332 - 0.4, 10000.0, 32.0, 13266.2, 8344.4, 2014.4, 17.58 - 0.4, 10000.0, 35.0, 15025.6, 8873.4, 2429.8, 17.573 - 0.4, 10000.0, 38.0, 16702.9, 9320.2, 2853.4, 17.473 - 0.4, 10000.0, 41.0, 18306.0, 9693.2, 3297.6, 17.291 - 0.4, 10000.0, 44.0, 19928.6, 10085.1, 3753.4, 17.234 - 0.4, 10000.0, 47.0, 21588.4, 10514.2, 4228.6, 17.328 - 0.4, 10000.0, 50.0, 23114.3, 10809.9, 4735.7, 17.173 - 0.4, 15000.0, 21.0, 4574.2, 4053.8, 484.8, 15.004 - 0.4, 15000.0, 26.0, 7705.7, 5624.1, 979.9, 16.825 - 0.4, 15000.0, 29.0, 9467.4, 6345.0, 1300.7, 17.369 - 0.4, 15000.0, 32.0, 11066.8, 6903.7, 1619.1, 17.576 - 0.4, 15000.0, 35.0, 12553.4, 7349.5, 1950.0, 17.579 - 0.4, 15000.0, 38.0, 13952.4, 7707.8, 2290.7, 17.434 - 0.4, 15000.0, 41.0, 15308.1, 8022.6, 2646.1, 17.26 - 0.4, 15000.0, 44.0, 16697.2, 8371.0, 3013.0, 17.265 - 0.4, 15000.0, 47.0, 18067.8, 8700.8, 3396.8, 17.282 - 0.4, 15000.0, 50.0, 19354.4, 8946.6, 3804.1, 17.126 - 0.4, 20000.0, 21.0, 3721.1, 3297.5, 408.4, 15.012 - 0.4, 20000.0, 26.0, 6271.9, 4577.5, 799.8, 16.829 - 0.4, 20000.0, 29.0, 7706.8, 5165.3, 1054.2, 17.374 - 0.4, 20000.0, 32.0, 9009.6, 5620.8, 1305.3, 17.581 - 0.4, 20000.0, 35.0, 10219.8, 5984.0, 1568.1, 17.583 - 0.4, 20000.0, 38.0, 11359.1, 6276.0, 1837.9, 17.437 - 0.4, 20000.0, 41.0, 12462.8, 6532.6, 2119.3, 17.263 - 0.4, 20000.0, 44.0, 13594.0, 6816.4, 2409.8, 17.268 - 0.4, 20000.0, 47.0, 14709.9, 7085.1, 2713.0, 17.284 - 0.4, 20000.0, 50.0, 15757.3, 7285.5, 3034.5, 17.125 - 0.5, 0.0, 26.0, 15265.0, 12518.2, 1708.4, 15.378 - 0.5, 0.0, 29.0, 18190.5, 14070.2, 2250.5, 16.191 - 0.5, 0.0, 32.0, 20745.8, 15252.1, 2771.8, 16.628 - 0.5, 0.0, 35.0, 23058.1, 16190.9, 3298.3, 16.841 - 0.5, 0.0, 38.0, 25233.4, 16992.5, 3832.6, 16.952 - 0.5, 0.0, 41.0, 27307.0, 17692.8, 4372.2, 16.993 - 0.5, 0.0, 44.0, 29240.3, 18252.7, 4933.9, 16.918 - 0.5, 0.0, 47.0, 31163.1, 18802.0, 5506.3, 16.872 - 0.5, 0.0, 50.0, 33149.0, 19414.4, 6088.5, 16.934 - 0.5, 2000.0, 26.0, 14430.8, 11773.0, 1623.6, 15.462 - 0.5, 2000.0, 29.0, 17208.2, 13221.3, 2142.7, 16.247 - 0.5, 2000.0, 32.0, 19669.5, 14353.7, 2639.9, 16.698 - 0.5, 2000.0, 35.0, 21853.9, 15209.1, 3147.6, 16.862 - 0.5, 2000.0, 38.0, 23952.7, 15978.9, 3660.0, 16.982 - 0.5, 2000.0, 41.0, 25904.0, 16601.3, 4183.6, 16.969 - 0.5, 2000.0, 44.0, 27771.6, 17139.8, 4726.6, 16.901 - 0.5, 2000.0, 47.0, 29629.6, 17668.6, 5275.5, 16.861 - 0.5, 2000.0, 50.0, 31590.8, 18301.1, 5842.2, 16.989 - 0.5, 5000.0, 26.0, 13246.3, 10720.7, 1502.4, 15.593 - 0.5, 5000.0, 29.0, 15813.5, 12025.2, 1986.8, 16.333 - 0.5, 5000.0, 32.0, 18125.8, 13074.5, 2452.2, 16.791 - 0.5, 5000.0, 35.0, 20140.7, 13826.6, 2931.2, 16.898 - 0.5, 5000.0, 38.0, 22125.6, 14548.6, 3410.6, 17.031 - 0.5, 5000.0, 41.0, 23906.8, 15067.3, 3910.2, 16.935 - 0.5, 5000.0, 44.0, 25677.2, 15574.6, 4424.6, 16.878 - 0.5, 5000.0, 47.0, 27492.5, 16127.0, 4946.0, 16.927 - 0.5, 5000.0, 50.0, 29344.3, 16716.1, 5482.1, 17.063 - 0.5, 10000.0, 26.0, 11402.4, 9111.5, 1309.4, 15.806 - 0.5, 10000.0, 29.0, 13638.7, 10202.2, 1735.6, 16.476 - 0.5, 10000.0, 32.0, 15634.6, 11052.7, 2150.9, 16.83 - 0.5, 10000.0, 35.0, 17450.6, 11723.2, 2575.7, 16.962 - 0.5, 10000.0, 38.0, 19150.6, 12277.8, 3009.3, 16.97 - 0.5, 10000.0, 41.0, 20760.9, 12742.4, 3460.3, 16.894 - 0.5, 10000.0, 44.0, 22382.4, 13218.5, 3918.9, 16.892 - 0.5, 10000.0, 47.0, 24071.2, 13761.7, 4392.6, 17.049 - 0.5, 10000.0, 50.0, 25600.4, 14145.7, 4889.8, 16.988 - 0.5, 15000.0, 21.0, 6000.2, 5503.1, 527.9, 13.707 - 0.5, 15000.0, 26.0, 9596.4, 7608.2, 1074.4, 15.941 - 0.5, 15000.0, 29.0, 11493.5, 8511.2, 1420.2, 16.569 - 0.5, 15000.0, 32.0, 13178.1, 9201.7, 1761.1, 16.859 - 0.5, 15000.0, 35.0, 14748.5, 9778.0, 2108.1, 17.006 - 0.5, 15000.0, 38.0, 16176.6, 10212.0, 2467.3, 16.938 - 0.5, 15000.0, 41.0, 17571.1, 10612.4, 2838.7, 16.873 - 0.5, 15000.0, 44.0, 19017.1, 11064.3, 3219.2, 16.972 - 0.5, 15000.0, 47.0, 20418.1, 11471.2, 3613.6, 17.029 - 0.5, 15000.0, 50.0, 21719.9, 11778.9, 4026.7, 16.935 - 0.5, 20000.0, 21.0, 4879.2, 4474.6, 442.6, 13.709 - 0.5, 20000.0, 26.0, 7810.2, 6192.1, 873.4, 15.943 - 0.5, 20000.0, 29.0, 9355.6, 6928.3, 1148.5, 16.572 - 0.5, 20000.0, 32.0, 10727.9, 7491.6, 1417.4, 16.862 - 0.5, 20000.0, 35.0, 12006.7, 7961.2, 1693.2, 17.009 - 0.5, 20000.0, 38.0, 13169.4, 8315.0, 1978.2, 16.941 - 0.5, 20000.0, 41.0, 14304.6, 8641.1, 2271.6, 16.876 - 0.5, 20000.0, 44.0, 15481.7, 9009.1, 2573.7, 16.973 - 0.5, 20000.0, 47.0, 16622.8, 9340.9, 2885.2, 17.03 - 0.5, 20000.0, 50.0, 17682.7, 9591.9, 3211.9, 16.936 - 0.5, 25000.0, 21.0, 3933.3, 3606.7, 372.0, 13.711 - 0.5, 25000.0, 26.0, 6302.8, 4996.6, 709.5, 15.946 - 0.5, 25000.0, 29.0, 7551.7, 5592.4, 925.7, 16.577 - 0.5, 25000.0, 32.0, 8660.7, 6048.3, 1136.1, 16.868 - 0.5, 25000.0, 35.0, 9693.2, 6427.7, 1352.1, 17.013 - 0.5, 25000.0, 38.0, 10632.4, 6713.9, 1576.1, 16.946 - 0.5, 25000.0, 41.0, 11549.2, 6977.6, 1806.0, 16.879 - 0.5, 25000.0, 44.0, 12499.0, 7274.4, 2043.2, 16.976 - 0.5, 25000.0, 47.0, 13420.8, 7543.1, 2287.2, 17.032 - 0.5, 25000.0, 50.0, 14276.8, 7746.0, 2542.4, 16.936 - 0.5, 30000.0, 21.0, 3140.5, 2879.3, 315.1, 13.715 - 0.5, 30000.0, 26.0, 5039.4, 3994.4, 575.9, 15.951 - 0.5, 30000.0, 29.0, 6040.2, 4472.7, 744.0, 16.586 - 0.5, 30000.0, 32.0, 6928.6, 4838.7, 906.5, 16.877 - 0.5, 30000.0, 35.0, 7754.9, 5142.5, 1073.6, 17.02 - 0.5, 30000.0, 38.0, 8506.8, 5372.0, 1248.2, 16.952 - 0.5, 30000.0, 41.0, 9240.4, 5583.4, 1426.0, 16.884 - 0.5, 30000.0, 44.0, 10000.8, 5821.0, 1610.6, 16.979 - 0.5, 30000.0, 47.0, 10738.3, 6036.1, 1799.7, 17.034 - 0.5, 30000.0, 50.0, 11423.5, 6198.7, 1997.2, 16.938 - 0.6, 15000.0, 21.0, 7720.5, 7235.0, 578.9, 12.937 - 0.6, 15000.0, 26.0, 11871.3, 9929.5, 1184.6, 15.332 - 0.6, 15000.0, 29.0, 13959.5, 11046.8, 1558.1, 16.029 - 0.6, 15000.0, 32.0, 15760.4, 11876.9, 1926.5, 16.366 - 0.6, 15000.0, 35.0, 17454.7, 12600.2, 2297.9, 16.613 - 0.6, 15000.0, 38.0, 18937.2, 13111.8, 2682.6, 16.6 - 0.6, 15000.0, 41.0, 20404.0, 13607.8, 3076.5, 16.615 - 0.6, 15000.0, 44.0, 21943.7, 14176.7, 3479.4, 16.785 - 0.6, 15000.0, 47.0, 23404.6, 14666.6, 3892.2, 16.874 - 0.6, 15000.0, 50.0, 24751.0, 15042.1, 4322.2, 16.834 - 0.6, 20000.0, 21.0, 6276.7, 5881.6, 481.8, 12.934 - 0.6, 20000.0, 26.0, 9662.4, 8082.0, 960.1, 15.334 - 0.6, 20000.0, 29.0, 11363.1, 8992.4, 1257.0, 16.031 - 0.6, 20000.0, 32.0, 12830.4, 9669.7, 1548.6, 16.369 - 0.6, 20000.0, 35.0, 14210.0, 10259.1, 1842.7, 16.615 - 0.6, 20000.0, 38.0, 15417.6, 10676.5, 2148.6, 16.602 - 0.6, 20000.0, 41.0, 16611.4, 11080.1, 2460.4, 16.617 - 0.6, 20000.0, 44.0, 17865.4, 11544.0, 2780.2, 16.787 - 0.6, 20000.0, 47.0, 19054.7, 11943.1, 3106.8, 16.875 - 0.6, 20000.0, 50.0, 20151.2, 12249.3, 3446.8, 16.833 - 0.6, 25000.0, 21.0, 5057.6, 4738.7, 402.6, 12.93 - 0.6, 25000.0, 26.0, 7798.1, 6522.6, 776.8, 15.338 - 0.6, 25000.0, 29.0, 9171.2, 7257.9, 1011.0, 16.034 - 0.6, 25000.0, 32.0, 10357.8, 7806.6, 1238.8, 16.373 - 0.6, 25000.0, 35.0, 11472.0, 8283.0, 1469.7, 16.618 - 0.6, 25000.0, 38.0, 12447.4, 8620.6, 1710.1, 16.605 - 0.6, 25000.0, 41.0, 13411.8, 8947.1, 1954.6, 16.62 - 0.6, 25000.0, 44.0, 14423.9, 9321.5, 2205.7, 16.789 - 0.6, 25000.0, 47.0, 15384.6, 9644.5, 2461.8, 16.877 - 0.6, 25000.0, 50.0, 16269.9, 9891.9, 2727.5, 16.834 - 0.6, 30000.0, 21.0, 4035.9, 3780.9, 337.9, 12.925 - 0.6, 30000.0, 26.0, 6235.4, 5215.1, 627.3, 15.344 - 0.6, 30000.0, 29.0, 7334.8, 5804.3, 810.3, 16.039 - 0.6, 30000.0, 32.0, 8285.6, 6244.9, 986.3, 16.379 - 0.6, 30000.0, 35.0, 9177.6, 6626.7, 1165.0, 16.623 - 0.6, 30000.0, 38.0, 9958.4, 6897.4, 1352.3, 16.61 - 0.6, 30000.0, 41.0, 10730.4, 7159.1, 1541.8, 16.624 - 0.6, 30000.0, 44.0, 11540.1, 7458.7, 1737.1, 16.792 - 0.6, 30000.0, 47.0, 12309.0, 7717.4, 1935.7, 16.88 - 0.6, 30000.0, 50.0, 13017.7, 7916.1, 2141.5, 16.836 - 0.6, 35000.0, 21.0, 3185.3, 2983.2, 287.4, 12.919 - 0.6, 35000.0, 26.0, 4935.9, 4127.5, 507.3, 15.352 - 0.6, 35000.0, 29.0, 5808.1, 4595.5, 647.7, 16.047 - 0.6, 35000.0, 32.0, 6563.1, 4946.3, 782.5, 16.389 - 0.6, 35000.0, 35.0, 7270.5, 5249.4, 919.3, 16.631 - 0.6, 35000.0, 38.0, 7889.7, 5464.5, 1063.0, 16.618 - 0.6, 35000.0, 41.0, 8501.6, 5672.2, 1208.5, 16.63 - 0.6, 35000.0, 44.0, 9143.3, 5909.7, 1358.5, 16.797 - 0.6, 35000.0, 47.0, 9752.9, 6115.2, 1511.3, 16.884 - 0.6, 35000.0, 50.0, 10314.6, 6272.7, 1668.2, 16.838 - 0.6, 39000.0, 21.0, 2617.4, 2450.5, 260.1, 12.913 - 0.6, 39000.0, 26.0, 4070.3, 3402.8, 435.3, 15.362 - 0.6, 39000.0, 29.0, 4791.4, 3790.1, 549.9, 16.056 - 0.6, 39000.0, 32.0, 5415.9, 4080.8, 659.8, 16.4 - 0.6, 39000.0, 35.0, 6000.2, 4331.3, 771.3, 16.64 - 0.6, 39000.0, 38.0, 6512.2, 4509.6, 888.3, 16.626 - 0.6, 39000.0, 41.0, 7017.6, 4681.3, 1007.1, 16.638 - 0.6, 39000.0, 44.0, 7547.4, 4877.3, 1130.2, 16.803 - 0.6, 39000.0, 47.0, 8050.9, 5047.1, 1255.3, 16.89 - 0.6, 39000.0, 50.0, 8514.8, 5177.2, 1383.5, 16.842 - 0.7, 15000.0, 21.0, 9812.7, 9327.8, 640.4, 12.521 - 0.7, 15000.0, 26.0, 14597.6, 12657.9, 1313.8, 14.949 - 0.7, 15000.0, 29.0, 16962.6, 14053.1, 1721.5, 15.728 - 0.7, 15000.0, 32.0, 18912.3, 15032.9, 2125.0, 16.089 - 0.7, 15000.0, 35.0, 20740.6, 15891.4, 2531.1, 16.368 - 0.7, 15000.0, 38.0, 22336.4, 16517.3, 2949.9, 16.428 - 0.7, 15000.0, 41.0, 23911.2, 17122.0, 3372.6, 16.504 - 0.7, 15000.0, 44.0, 25585.8, 17827.0, 3806.5, 16.731 - 0.7, 15000.0, 47.0, 27135.0, 18406.4, 4247.5, 16.84 - 0.7, 15000.0, 50.0, 28556.3, 18857.8, 4704.6, 16.824 - 0.7, 20000.0, 21.0, 7977.1, 7582.4, 529.2, 12.515 - 0.7, 20000.0, 26.0, 11881.1, 10302.6, 1062.6, 14.949 - 0.7, 20000.0, 29.0, 13807.1, 11439.2, 1386.6, 15.729 - 0.7, 20000.0, 32.0, 15396.4, 12239.3, 1706.2, 16.091 - 0.7, 20000.0, 35.0, 16885.7, 12939.4, 2027.9, 16.37 - 0.7, 20000.0, 38.0, 18185.1, 13449.4, 2359.6, 16.43 - 0.7, 20000.0, 41.0, 19467.3, 13942.2, 2695.0, 16.506 - 0.7, 20000.0, 44.0, 20830.5, 14516.2, 3039.3, 16.732 - 0.7, 20000.0, 47.0, 22092.1, 14988.7, 3389.3, 16.841 - 0.7, 20000.0, 50.0, 23249.2, 15356.5, 3750.4, 16.824 - 0.7, 25000.0, 21.0, 6425.3, 6106.8, 439.2, 12.506 - 0.7, 25000.0, 26.0, 9587.9, 8314.0, 856.3, 14.951 - 0.7, 25000.0, 29.0, 11143.3, 9232.5, 1111.9, 15.73 - 0.7, 25000.0, 32.0, 12428.4, 9880.7, 1361.8, 16.094 - 0.7, 25000.0, 35.0, 13632.0, 10447.4, 1614.4, 16.373 - 0.7, 25000.0, 38.0, 14681.1, 10859.6, 1875.1, 16.433 - 0.7, 25000.0, 41.0, 15716.0, 11257.5, 2138.7, 16.508 - 0.7, 25000.0, 44.0, 16816.6, 11721.3, 2409.3, 16.733 - 0.7, 25000.0, 47.0, 17835.4, 12103.2, 2683.6, 16.843 - 0.7, 25000.0, 50.0, 18770.3, 12401.1, 2966.4, 16.825 - 0.7, 30000.0, 21.0, 5125.3, 4870.6, 365.6, 12.495 - 0.7, 30000.0, 26.0, 7665.8, 6646.8, 689.0, 14.953 - 0.7, 30000.0, 29.0, 8911.4, 7383.0, 888.9, 15.732 - 0.7, 30000.0, 32.0, 9942.1, 7904.1, 1082.3, 16.099 - 0.7, 30000.0, 35.0, 10906.4, 8358.9, 1277.7, 16.378 - 0.7, 30000.0, 38.0, 11746.3, 8689.3, 1479.8, 16.437 - 0.7, 30000.0, 41.0, 12574.6, 9008.1, 1685.2, 16.512 - 0.7, 30000.0, 44.0, 13455.1, 9379.1, 1896.0, 16.736 - 0.7, 30000.0, 47.0, 14271.0, 9685.6, 2109.1, 16.845 - 0.7, 30000.0, 50.0, 15019.0, 9924.1, 2327.8, 16.827 - 0.7, 35000.0, 21.0, 4043.5, 3841.7, 306.6, 12.48 - 0.7, 35000.0, 26.0, 6067.4, 5260.2, 553.8, 14.958 - 0.7, 35000.0, 29.0, 7055.6, 5844.9, 708.0, 15.737 - 0.7, 35000.0, 32.0, 7874.5, 6260.1, 856.1, 16.106 - 0.7, 35000.0, 35.0, 8639.8, 6621.8, 1005.8, 16.385 - 0.7, 35000.0, 38.0, 9305.5, 6884.0, 1161.3, 16.443 - 0.7, 35000.0, 41.0, 9962.3, 7137.0, 1318.8, 16.517 - 0.7, 35000.0, 44.0, 10660.1, 7431.4, 1480.6, 16.74 - 0.7, 35000.0, 47.0, 11307.0, 7674.5, 1644.6, 16.849 - 0.7, 35000.0, 50.0, 11899.7, 7863.8, 1812.1, 16.829 - 0.7, 39000.0, 21.0, 3320.5, 3153.9, 274.0, 12.464 - 0.7, 39000.0, 26.0, 5002.8, 4336.3, 472.7, 14.964 - 0.7, 39000.0, 29.0, 5820.0, 4820.1, 599.1, 15.743 - 0.7, 39000.0, 32.0, 6497.8, 5164.6, 719.9, 16.115 - 0.7, 39000.0, 35.0, 7130.7, 5464.2, 842.2, 16.394 - 0.7, 39000.0, 38.0, 7680.7, 5680.9, 968.9, 16.45 - 0.7, 39000.0, 41.0, 8223.3, 5890.1, 1097.6, 16.523 - 0.7, 39000.0, 44.0, 8799.5, 6133.1, 1230.6, 16.746 - 0.7, 39000.0, 47.0, 9333.7, 6334.1, 1364.7, 16.854 - 0.7, 39000.0, 50.0, 9823.4, 6490.4, 1501.7, 16.833 - 0.7, 43000.0, 21.0, 2722.3, 2584.7, 250.5, 12.443 - 0.7, 43000.0, 26.0, 4122.9, 3572.4, 409.0, 14.97 - 0.7, 43000.0, 29.0, 4798.8, 3973.0, 512.6, 15.751 - 0.7, 43000.0, 32.0, 5360.0, 4259.1, 611.7, 16.127 - 0.7, 43000.0, 35.0, 5883.5, 4507.3, 711.9, 16.406 - 0.7, 43000.0, 38.0, 6338.1, 4686.6, 815.6, 16.459 - 0.7, 43000.0, 41.0, 6786.4, 4859.5, 921.4, 16.532 - 0.7, 43000.0, 44.0, 7262.0, 5060.1, 1031.0, 16.753 - 0.7, 43000.0, 47.0, 7703.0, 5225.8, 1141.7, 16.861 - 0.7, 43000.0, 50.0, 8107.7, 5355.2, 1254.4, 16.839 - 0.75, 25000.0, 21.0, 7219.4, 6898.5, 460.3, 12.397 - 0.75, 25000.0, 26.0, 10621.9, 9338.4, 901.7, 14.848 - 0.75, 25000.0, 29.0, 12284.9, 10359.7, 1169.8, 15.66 - 0.75, 25000.0, 32.0, 13627.6, 11060.7, 1433.3, 16.03 - 0.75, 25000.0, 35.0, 14883.7, 11675.1, 1697.8, 16.32 - 0.75, 25000.0, 38.0, 15979.8, 12129.4, 1971.6, 16.41 - 0.75, 25000.0, 41.0, 17059.2, 12566.9, 2246.1, 16.507 - 0.75, 25000.0, 44.0, 18213.8, 13079.9, 2529.1, 16.743 - 0.75, 25000.0, 47.0, 19270.2, 13494.6, 2815.6, 16.844 - 0.75, 25000.0, 50.0, 20237.8, 13820.4, 3109.9, 16.826 - 0.75, 30000.0, 21.0, 5757.6, 5500.9, 381.8, 12.383 - 0.75, 30000.0, 26.0, 8492.3, 7465.7, 724.3, 14.85 - 0.75, 30000.0, 29.0, 9824.2, 8284.2, 933.8, 15.661 - 0.75, 30000.0, 32.0, 10901.4, 8848.0, 1137.6, 16.035 - 0.75, 30000.0, 35.0, 11907.9, 9341.2, 1342.9, 16.324 - 0.75, 30000.0, 38.0, 12785.4, 9705.4, 1555.2, 16.414 - 0.75, 30000.0, 41.0, 13649.3, 10055.9, 1769.5, 16.511 - 0.75, 30000.0, 44.0, 14573.1, 10466.4, 1988.7, 16.746 - 0.75, 30000.0, 47.0, 15419.1, 10799.1, 2211.5, 16.847 - 0.75, 30000.0, 50.0, 16193.3, 11059.9, 2439.5, 16.828 - 0.75, 35000.0, 21.0, 4541.3, 4338.0, 318.5, 12.364 - 0.75, 35000.0, 26.0, 6720.9, 5907.7, 580.7, 14.852 - 0.75, 35000.0, 29.0, 7777.6, 6557.9, 742.4, 15.664 - 0.75, 35000.0, 32.0, 8633.5, 7007.3, 898.5, 16.041 - 0.75, 35000.0, 35.0, 9432.5, 7399.7, 1056.0, 16.331 - 0.75, 35000.0, 38.0, 10128.3, 7688.9, 1218.5, 16.419 - 0.75, 35000.0, 41.0, 10813.0, 7966.9, 1383.3, 16.515 - 0.75, 35000.0, 44.0, 11544.9, 8292.4, 1552.4, 16.749 - 0.75, 35000.0, 47.0, 12215.4, 8556.3, 1723.2, 16.851 - 0.75, 35000.0, 50.0, 12829.4, 8763.8, 1898.1, 16.83 - 0.75, 39000.0, 21.0, 3729.3, 3561.4, 282.4, 12.345 - 0.75, 39000.0, 26.0, 5541.5, 4870.0, 494.3, 14.857 - 0.75, 39000.0, 29.0, 6415.2, 5408.0, 627.2, 15.669 - 0.75, 39000.0, 32.0, 7124.0, 5781.0, 754.6, 16.049 - 0.75, 39000.0, 35.0, 7784.8, 6106.0, 883.2, 16.34 - 0.75, 39000.0, 38.0, 8359.7, 6345.2, 1015.9, 16.426 - 0.75, 39000.0, 41.0, 8925.5, 6575.0, 1150.5, 16.521 - 0.75, 39000.0, 44.0, 9529.8, 6843.8, 1289.3, 16.755 - 0.75, 39000.0, 47.0, 10083.6, 7061.8, 1429.5, 16.855 - 0.75, 39000.0, 50.0, 10590.8, 7233.2, 1572.3, 16.834 - 0.75, 43000.0, 21.0, 3056.5, 2917.8, 256.4, 12.318 - 0.75, 43000.0, 26.0, 4566.6, 4012.1, 426.2, 14.861 - 0.75, 43000.0, 29.0, 5289.3, 4457.4, 535.6, 15.675 - 0.75, 43000.0, 32.0, 5876.5, 4767.4, 640.3, 16.059 - 0.75, 43000.0, 35.0, 6423.2, 5036.8, 745.8, 16.351 - 0.75, 43000.0, 38.0, 6898.2, 5234.5, 854.2, 16.435 - 0.75, 43000.0, 41.0, 7365.7, 5424.6, 965.0, 16.529 - 0.75, 43000.0, 44.0, 7864.6, 5646.4, 1079.4, 16.761 - 0.75, 43000.0, 47.0, 8322.2, 5826.6, 1195.1, 16.862 - 0.75, 43000.0, 50.0, 8741.0, 5968.1, 1312.7, 16.839 - 0.8, 25000.0, 21.0, 8098.0, 7773.0, 483.7, 12.344 - 0.8, 25000.0, 26.0, 11761.6, 10461.7, 951.6, 14.801 - 0.8, 25000.0, 29.0, 13531.2, 11581.4, 1234.5, 15.623 - 0.8, 25000.0, 32.0, 14949.6, 12349.8, 1512.3, 16.015 - 0.8, 25000.0, 35.0, 16264.5, 13014.7, 1790.8, 16.313 - 0.8, 25000.0, 38.0, 17413.4, 13513.7, 2077.6, 16.417 - 0.8, 25000.0, 41.0, 18544.0, 13994.4, 2366.1, 16.514 - 0.8, 25000.0, 44.0, 19760.6, 14561.0, 2663.1, 16.753 - 0.8, 25000.0, 47.0, 20860.3, 15010.8, 2963.6, 16.846 - 0.8, 25000.0, 50.0, 21866.3, 15366.8, 3272.0, 16.827 - 0.8, 30000.0, 21.0, 6456.8, 6196.9, 399.6, 12.328 - 0.8, 30000.0, 26.0, 9402.7, 8363.1, 762.6, 14.8 - 0.8, 30000.0, 29.0, 10822.3, 9262.9, 983.2, 15.627 - 0.8, 30000.0, 32.0, 11958.1, 9878.9, 1198.5, 16.018 - 0.8, 30000.0, 35.0, 13011.8, 10412.8, 1414.8, 16.317 - 0.8, 30000.0, 38.0, 13931.5, 10812.7, 1637.6, 16.42 - 0.8, 30000.0, 41.0, 14836.3, 11197.7, 1862.2, 16.517 - 0.8, 30000.0, 44.0, 15809.6, 11651.2, 2093.1, 16.755 - 0.8, 30000.0, 47.0, 16690.5, 12012.2, 2326.7, 16.848 - 0.8, 30000.0, 50.0, 17495.4, 12297.4, 2565.6, 16.829 - 0.8, 35000.0, 21.0, 5092.2, 4886.4, 331.7, 12.306 - 0.8, 35000.0, 26.0, 7441.1, 6617.8, 610.1, 14.801 - 0.8, 35000.0, 29.0, 8569.4, 7334.3, 780.2, 15.632 - 0.8, 35000.0, 32.0, 9470.5, 7823.7, 945.2, 16.023 - 0.8, 35000.0, 35.0, 10306.9, 8248.5, 1111.5, 16.323 - 0.8, 35000.0, 38.0, 11036.4, 8566.3, 1281.8, 16.426 - 0.8, 35000.0, 41.0, 11753.4, 8871.5, 1454.7, 16.522 - 0.8, 35000.0, 44.0, 12524.7, 9231.2, 1632.5, 16.758 - 0.8, 35000.0, 47.0, 13222.6, 9517.5, 1811.9, 16.852 - 0.8, 35000.0, 50.0, 13861.2, 9744.3, 1995.1, 16.831 - 0.8, 39000.0, 21.0, 4181.9, 4012.0, 292.0, 12.284 - 0.8, 39000.0, 26.0, 6135.1, 5455.1, 518.3, 14.804 - 0.8, 39000.0, 29.0, 7069.3, 6049.4, 658.0, 15.639 - 0.8, 39000.0, 32.0, 7814.5, 6454.6, 792.9, 16.03 - 0.8, 39000.0, 35.0, 8506.4, 6806.4, 928.7, 16.331 - 0.8, 39000.0, 38.0, 9109.3, 7069.4, 1067.4, 16.432 - 0.8, 39000.0, 41.0, 9701.6, 7321.6, 1209.1, 16.527 - 0.8, 39000.0, 44.0, 10338.4, 7618.6, 1354.9, 16.763 - 0.8, 39000.0, 47.0, 10915.2, 7855.4, 1502.1, 16.856 - 0.8, 39000.0, 50.0, 11442.3, 8042.5, 1651.9, 16.835 - 0.8, 43000.0, 21.0, 3426.6, 3286.2, 263.3, 12.253 - 0.8, 43000.0, 26.0, 5055.8, 4494.2, 445.4, 14.808 - 0.8, 43000.0, 29.0, 5829.7, 4987.3, 560.9, 15.649 - 0.8, 43000.0, 32.0, 6446.0, 5322.8, 671.7, 16.04 - 0.8, 43000.0, 35.0, 7018.5, 5614.5, 783.2, 16.341 - 0.8, 43000.0, 38.0, 7516.7, 5832.0, 896.7, 16.44 - 0.8, 43000.0, 41.0, 8006.1, 6040.6, 1013.2, 16.535 - 0.8, 43000.0, 44.0, 8532.5, 6286.0, 1133.6, 16.77 - 0.8, 43000.0, 47.0, 9008.3, 6481.1, 1255.1, 16.862 - 0.8, 43000.0, 50.0, 9443.7, 6635.9, 1378.6, 16.84 - 0.85, 30000.0, 21.0, 7231.1, 6966.7, 419.5, 12.324 - 0.85, 30000.0, 26.0, 10406.0, 9348.1, 804.6, 14.802 - 0.85, 30000.0, 29.0, 11913.9, 10327.1, 1037.7, 15.629 - 0.85, 30000.0, 32.0, 13121.6, 11005.9, 1265.7, 16.041 - 0.85, 30000.0, 35.0, 14227.8, 11583.1, 1493.8, 16.326 - 0.85, 30000.0, 38.0, 15196.2, 12022.5, 1729.0, 16.428 - 0.85, 30000.0, 41.0, 16147.3, 12444.8, 1965.6, 16.523 - 0.85, 30000.0, 44.0, 17177.2, 12945.7, 2209.6, 16.763 - 0.85, 30000.0, 47.0, 18097.2, 13336.7, 2456.0, 16.849 - 0.85, 30000.0, 50.0, 18937.4, 13648.0, 2708.4, 16.83 - 0.85, 35000.0, 21.0, 5702.0, 5492.5, 346.4, 12.299 - 0.85, 35000.0, 26.0, 8234.8, 7397.0, 642.3, 14.801 - 0.85, 35000.0, 29.0, 9434.0, 8177.3, 821.7, 15.634 - 0.85, 35000.0, 32.0, 10391.9, 8716.3, 997.0, 16.046 - 0.85, 35000.0, 35.0, 11270.1, 9175.5, 1172.3, 16.332 - 0.85, 35000.0, 38.0, 12038.3, 9524.8, 1352.2, 16.433 - 0.85, 35000.0, 41.0, 12792.2, 9859.7, 1534.4, 16.527 - 0.85, 35000.0, 44.0, 13608.2, 10256.9, 1722.1, 16.767 - 0.85, 35000.0, 47.0, 14337.7, 10567.4, 1911.7, 16.853 - 0.85, 35000.0, 50.0, 15003.7, 10814.5, 2105.3, 16.832 - 0.85, 39000.0, 21.0, 4683.3, 4510.4, 303.1, 12.275 - 0.85, 39000.0, 26.0, 6789.1, 6097.2, 544.5, 14.802 - 0.85, 39000.0, 29.0, 7782.2, 6744.4, 691.9, 15.64 - 0.85, 39000.0, 32.0, 8574.5, 7190.7, 835.0, 16.052 - 0.85, 39000.0, 35.0, 9300.9, 7571.3, 978.5, 16.339 - 0.85, 39000.0, 38.0, 9936.0, 7860.4, 1125.0, 16.439 - 0.85, 39000.0, 41.0, 10558.8, 8137.3, 1274.4, 16.533 - 0.85, 39000.0, 44.0, 11232.4, 8465.0, 1428.4, 16.771 - 0.85, 39000.0, 47.0, 11835.0, 8721.5, 1583.9, 16.857 - 0.85, 39000.0, 50.0, 12385.1, 8925.8, 1742.2, 16.835 - 0.85, 43000.0, 21.0, 3837.2, 3694.4, 271.4, 12.241 - 0.85, 43000.0, 26.0, 5594.5, 5023.1, 466.8, 14.804 - 0.85, 43000.0, 29.0, 6417.3, 5560.1, 588.6, 15.648 - 0.85, 43000.0, 32.0, 7072.8, 5930.0, 706.3, 16.061 - 0.85, 43000.0, 35.0, 7674.0, 6245.4, 824.2, 16.349 - 0.85, 43000.0, 38.0, 8199.0, 6484.7, 943.9, 16.447 - 0.85, 43000.0, 41.0, 8713.6, 6713.6, 1067.0, 16.54 - 0.85, 43000.0, 44.0, 9269.6, 6983.9, 1194.2, 16.777 - 0.85, 43000.0, 47.0, 9767.6, 7196.1, 1322.7, 16.863 - 0.85, 43000.0, 50.0, 10221.8, 7364.6, 1453.0, 16.84 - 0.9, 35000.0, 21.0, 6377.2, 6163.0, 362.8, 12.339 - 0.9, 35000.0, 26.0, 9108.9, 8252.4, 677.5, 14.846 - 0.9, 35000.0, 29.0, 10384.7, 9099.9, 867.2, 15.664 - 0.9, 35000.0, 32.0, 11406.5, 9693.4, 1053.9, 16.072 - 0.9, 35000.0, 35.0, 12331.9, 10190.5, 1239.7, 16.341 - 0.9, 35000.0, 38.0, 13143.7, 10574.1, 1430.6, 16.44 - 0.9, 35000.0, 41.0, 13939.6, 10941.6, 1623.9, 16.533 - 0.9, 35000.0, 44.0, 14805.2, 11379.0, 1823.0, 16.774 - 0.9, 35000.0, 47.0, 15569.8, 11715.3, 2024.2, 16.853 - 0.9, 35000.0, 50.0, 16266.9, 11984.1, 2229.9, 16.832 - 0.9, 39000.0, 21.0, 5237.5, 5060.7, 316.0, 12.313 - 0.9, 39000.0, 26.0, 7509.5, 6802.1, 573.1, 14.846 - 0.9, 39000.0, 29.0, 8566.5, 7505.5, 729.0, 15.67 - 0.9, 39000.0, 32.0, 9411.5, 7996.9, 881.6, 16.078 - 0.9, 39000.0, 35.0, 10177.1, 8408.8, 1033.8, 16.348 - 0.9, 39000.0, 38.0, 10848.4, 8726.3, 1189.3, 16.446 - 0.9, 39000.0, 41.0, 11505.6, 9029.9, 1347.7, 16.538 - 0.9, 39000.0, 44.0, 12220.6, 9391.3, 1511.2, 16.779 - 0.9, 39000.0, 47.0, 12852.0, 9669.0, 1676.3, 16.857 - 0.9, 39000.0, 50.0, 13427.8, 9891.1, 1844.4, 16.835 - 0.9, 43000.0, 21.0, 4292.4, 4146.4, 280.7, 12.277 - 0.9, 43000.0, 26.0, 6187.8, 5603.7, 490.2, 14.846 - 0.9, 43000.0, 29.0, 7063.7, 6187.5, 619.0, 15.677 - 0.9, 43000.0, 32.0, 7762.8, 6594.6, 744.5, 16.086 - 0.9, 43000.0, 35.0, 8396.5, 6936.1, 869.6, 16.356 - 0.9, 43000.0, 38.0, 8951.5, 7199.1, 996.7, 16.454 - 0.9, 43000.0, 41.0, 9494.4, 7449.9, 1127.5, 16.545 - 0.9, 43000.0, 44.0, 10084.8, 7748.2, 1262.3, 16.785 - 0.9, 43000.0, 47.0, 10606.2, 7977.6, 1398.7, 16.863 - 0.9, 43000.0, 50.0, 11081.8, 8161.1, 1537.2, 16.84 diff --git a/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py b/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py index 02aca9e403..7a8eeca745 100644 --- a/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py +++ b/aviary/validation_cases/validation_data/flops_data/full_mission_test_data.py @@ -1,4 +1,4 @@ -''' +""" The following test data comes from a file which was LEAPS2/problems/full_mission_test.py results. The file does not exist anymore, but the data is used for regression testing. The analysis converged using SNOPT with 0/1 results and good plots. @@ -11,7 +11,8 @@ mission analyses use implementations that do not rely on some Aviary variables, such as altitude rate and velocity rate. These missing values cannot be derived from the available FLOPS/LEAPS1 data. -''' +""" + from aviary.utils.aviary_values import AviaryValues from aviary.variable_info.variables import Aircraft, Dynamic, Mission @@ -49,7 +50,7 @@ data.set_val( Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, - val=.0175, + val=0.0175, units='unitless', ) @@ -62,117 +63,185 @@ data.set_val( # states:altitude Dynamic.Mission.ALTITUDE, - val=[29.3112920637369, 10668, 26.3564405194251, ], + val=[ + 29.3112920637369, + 10668, + 26.3564405194251, + ], units='m', ) data.set_val( # outputs Dynamic.Mission.ALTITUDE_RATE, - val=[29.8463233754212, -5.69941245767868E-09, -4.32644785970493, ], + val=[ + 29.8463233754212, + -5.69941245767868e-09, + -4.32644785970493, + ], units='ft/s', ) data.set_val( # outputs Dynamic.Mission.ALTITUDE_RATE_MAX, - val=[3679.0525544843, 3.86361517135375, 6557.07891846677, ], + val=[ + 3679.0525544843, + 3.86361517135375, + 6557.07891846677, + ], units='ft/min', ) data.set_val( # outputs - Dynamic.Mission.DRAG, - val=[9978.32211087097, 8769.90342254821, 7235.03338269778, ], + Dynamic.Vehicle.DRAG, + val=[ + 9978.32211087097, + 8769.90342254821, + 7235.03338269778, + ], units='lbf', ) data.set_val( # outputs - Dynamic.Mission.FUEL_FLOW_RATE, - val=[16602.302762413, 5551.61304633633, 1286, ], + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE, + val=[ + 16602.302762413, + 5551.61304633633, + 1286, + ], units='lbm/h', ) data.set_val( - Dynamic.Mission.MACH, - val=[0.482191004489294, 0.785, 0.345807620281699, ], + Dynamic.Atmosphere.MACH, + val=[ + 0.482191004489294, + 0.785, + 0.345807620281699, + ], units='unitless', ) data.set_val( # states:mass - Dynamic.Mission.MASS, - val=[81796.1389890711, 74616.9849763798, 65193.7423491884, ], + Dynamic.Vehicle.MASS, + val=[ + 81796.1389890711, + 74616.9849763798, + 65193.7423491884, + ], units='kg', ) # TODO: double check values data.set_val( - Dynamic.Mission.THROTTLE, - val=[0.5, 0.5, 0., ], + Dynamic.Vehicle.Propulsion.THROTTLE, + val=[ + 0.5, + 0.5, + 0.0, + ], units='unitless', ) # TODO: double check values data.set_val( 'throttle_max', - val=[1., 1., 1., ], + val=[ + 1.0, + 1.0, + 1.0, + ], units='unitless', ) data.set_val( # state_rates:range Dynamic.Mission.DISTANCE_RATE, - val=[163.776550884386, 232.775306059091, 117.631414542995, ], + val=[ + 163.776550884386, + 232.775306059091, + 117.631414542995, + ], units='m/s', ) data.set_val( # outputs Dynamic.Mission.SPECIFIC_ENERGY_RATE, - val=[18.4428113202544191, -1.7371801250963E-9, -5.9217623736010768, ], + val=[ + 18.4428113202544191, + -1.7371801250963e-9, + -5.9217623736010768, + ], units='m/s', ) data.set_val( # outputs Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, - val=[28.03523893220630, 3.8636151713537548, 28.706899839848, ], + val=[ + 28.03523893220630, + 3.8636151713537548, + 28.706899839848, + ], units='m/s', ) data.set_val( # outputs - Dynamic.Mission.THRUST_TOTAL, - val=[30253.9128379374, 8769.90342132054, 0, ], + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, + val=[ + 30253.9128379374, + 8769.90342132054, + 0, + ], units='lbf', ) data.set_val( # outputs - Dynamic.Mission.THRUST_MAX_TOTAL, - val=[40799.6009633346, 11500.32, 42308.2709683461, ], + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, + val=[ + 40799.6009633346, + 11500.32, + 42308.2709683461, + ], units='lbf', ) data.set_val( # outputs 'time', - val=[85.8098321364695, 8852.1530657591, 23851.1097964271, ], + val=[ + 85.8098321364695, + 8852.1530657591, + 23851.1097964271, + ], units='s', ) data.set_val( # states:velocity Dynamic.Mission.VELOCITY, - val=[164.029012458452, 232.775306059091, 117.638805929526, ], + val=[ + 164.029012458452, + 232.775306059091, + 117.638805929526, + ], units='m/s', ) data.set_val( # state_rates:velocity Dynamic.Mission.VELOCITY_RATE, - val=[0.558739800813549, 3.33665416459715E-17, -0.38372209277242, ], + val=[ + 0.558739800813549, + 3.33665416459715e-17, + -0.38372209277242, + ], units='m/s**2', ) diff --git a/aviary/validation_cases/validation_tests.py b/aviary/validation_cases/validation_tests.py index 9b6e25b23a..c5e5fd06db 100644 --- a/aviary/validation_cases/validation_tests.py +++ b/aviary/validation_cases/validation_tests.py @@ -1,4 +1,3 @@ - import warnings from enum import Enum @@ -6,35 +5,40 @@ from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from parameterized import param +from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.aviary_values import AviaryValues from aviary.utils.options import list_options as list_options_func -from aviary.subsystems.propulsion.utils import build_engine_deck from aviary.utils.preprocessors import preprocess_options -from aviary.validation_cases.validation_data.flops_data.FLOPS_Test_Data import \ - FLOPS_Test_Data, FLOPS_Lacking_Test_Data +from aviary.validation_cases.validation_data.flops_data.FLOPS_Test_Data import ( + FLOPS_Lacking_Test_Data, + FLOPS_Test_Data, +) +from aviary.variable_info.functions import extract_options from aviary.variable_info.variables import Aircraft Version = Enum('Version', ['ALL', 'TRANSPORT', 'ALTERNATE', 'BWB']) -def do_validation_test(prob: om.Problem, - case_name: str, - input_validation_data: AviaryValues, - output_validation_data: AviaryValues, - input_keys: list, - output_keys: list, - aviary_option_keys: list = None, - tol: float = 1.0e-4, - atol: float = 1.0e-12, - rtol: float = 1.0e-12, - method: str = "cs", - step: float = None, - check_values: bool = True, - check_partials: bool = True, - excludes: list = None, - list_inputs: bool = False, - list_outputs: bool = False, - list_options: bool = False): +def do_validation_test( + prob: om.Problem, + case_name: str, + input_validation_data: AviaryValues, + output_validation_data: AviaryValues, + input_keys: list, + output_keys: list, + aviary_option_keys: list = None, + tol: float = 1.0e-4, + atol: float = 1.0e-12, + rtol: float = 1.0e-12, + method: str = 'cs', + step: float = None, + check_values: bool = True, + check_partials: bool = True, + excludes: list = None, + list_inputs: bool = False, + list_outputs: bool = False, + list_options: bool = False, +): """ Runs a validation test with user-supplied validation data. @@ -96,7 +100,6 @@ def do_validation_test(prob: om.Problem, If True, prob.model.list_outputs() will be called after the model is run. Default is False. """ - input_key_list = _assure_is_list(input_keys) output_key_list = _assure_is_list(output_keys) aviary_option_key_list = _assure_is_list(aviary_option_keys) @@ -110,7 +113,6 @@ def do_validation_test(prob: om.Problem, prob.set_val(key, desired, units) prob.run_model() - print(case_name) if list_options: list_options_func(prob.model, aviary_keys=aviary_option_key_list) @@ -132,29 +134,32 @@ def do_validation_test(prob: om.Problem, if check_partials: partial_data = prob.check_partials( - compact_print=True, method=method, step=step, excludes=excludes) + out_stream=None, method=method, step=step, excludes=excludes + ) assert_check_partials(partial_data, atol=atol, rtol=rtol) -def flops_validation_test(prob: om.Problem, - case_name: str, - input_keys: list, - output_keys: list, - aviary_option_keys: list = None, - version: Version = Version.ALL, - tol: float = 1.0e-4, - atol: float = 1.0e-12, - rtol: float = 1.0e-12, - method: str = "cs", - step: float = None, - check_values: bool = True, - check_partials: bool = True, - excludes: list = None, - list_inputs: bool = False, - list_outputs: bool = False, - list_options: bool = False, - flops_inputs=None, - flops_outputs=None): +def flops_validation_test( + prob: om.Problem, + case_name: str, + input_keys: list, + output_keys: list, + aviary_option_keys: list = None, + version: Version = Version.ALL, + tol: float = 1.0e-4, + atol: float = 1.0e-12, + rtol: float = 1.0e-12, + method: str = 'cs', + step: float = None, + check_values: bool = True, + check_partials: bool = True, + excludes: list = None, + list_inputs: bool = False, + list_outputs: bool = False, + list_options: bool = False, + flops_inputs=None, + flops_outputs=None, +): """ Set a model, runs the model and runs a validation test using FLOPS validation data. @@ -217,46 +222,49 @@ def flops_validation_test(prob: om.Problem, Allows a custom set of outputs to be tested. Default is None, which reads data from FLOPS_Test_Data with key case_name. """ - if not isinstance(version, Version): raise TypeError('parameter "version" must be of enumeration type "Version"') if flops_inputs is None and flops_outputs is None: flops_data = FLOPS_Test_Data[case_name] - flops_inputs = flops_data['inputs'] - flops_outputs = flops_data['outputs'] - - if version is Version.TRANSPORT and flops_inputs.get_val(Aircraft.Design.USE_ALT_MASS) or \ - version is Version.ALTERNATE and not flops_inputs.get_val(Aircraft.Design.USE_ALT_MASS): + flops_inputs = flops_data['inputs'].deepcopy() + flops_outputs = flops_data['outputs'].deepcopy() + + if ( + version is Version.TRANSPORT + and flops_inputs.get_val(Aircraft.Design.USE_ALT_MASS) + or version is Version.ALTERNATE + and not flops_inputs.get_val(Aircraft.Design.USE_ALT_MASS) + ): return # TODO: Currently no BWB validation data. # For BWBs, skip the validation test, but do check the partials. check_values_in = check_values - check_values = ( - check_values and version is not Version.BWB - ) + check_values = check_values and version is not Version.BWB if not check_values and check_values_in: warnings.warn('Not checking values because validation data not available.') - do_validation_test(prob=prob, - case_name=case_name, - input_validation_data=flops_inputs, - output_validation_data=flops_outputs, - input_keys=input_keys, - output_keys=output_keys, - aviary_option_keys=aviary_option_keys, - tol=tol, - atol=atol, - rtol=rtol, - method=method, - step=step, - check_values=check_values, - check_partials=check_partials, - excludes=excludes, - list_options=list_options, - list_inputs=list_inputs, - list_outputs=list_outputs) + do_validation_test( + prob=prob, + case_name=case_name, + input_validation_data=flops_inputs, + output_validation_data=flops_outputs, + input_keys=input_keys, + output_keys=output_keys, + aviary_option_keys=aviary_option_keys, + tol=tol, + atol=atol, + rtol=rtol, + method=method, + step=step, + check_values=check_values, + check_partials=check_partials, + excludes=excludes, + list_options=list_options, + list_inputs=list_inputs, + list_outputs=list_outputs, + ) def get_flops_data(case_name: str, keys: str = None, preprocess: bool = False) -> AviaryValues: @@ -272,6 +280,9 @@ def get_flops_data(case_name: str, keys: str = None, preprocess: bool = False) - keys : str, or iter of str List of variables whose values will be transferred from the validation data. The default is all variables. + preprocess: bool + If true, the input data will be passed through preprocess_options() to + fill in any missing options before being returned. The default is False. """ flops_data_copy: AviaryValues = get_flops_inputs(case_name, preprocess=preprocess) flops_data_copy.update(get_flops_outputs(case_name)) @@ -305,8 +316,11 @@ def get_flops_inputs(case_name: str, keys: str = None, preprocess: bool = False) flops_inputs_copy: AviaryValues = flops_data['inputs'].deepcopy() if preprocess: - preprocess_options(flops_inputs_copy, - engine_models=build_engine_deck(flops_inputs_copy)) + preprocess_options( + flops_inputs_copy, + engine_models=[build_engine_deck(flops_inputs_copy)], + verbosity=0, + ) if keys is None: return flops_inputs_copy keys_list = _assure_is_list(keys) @@ -314,6 +328,39 @@ def get_flops_inputs(case_name: str, keys: str = None, preprocess: bool = False) return AviaryValues({key: flops_inputs_copy.get_item(key) for key in keys_list}) +def get_flops_options(case_name: str, keys: str = None, preprocess: bool = False) -> AviaryValues: + """ + Returns a dictionary containing options for the named FLOPS validation case. + + Parameters + ---------- + case_name : str + Name of the case being run. Input data will be looked up from + the corresponding case in the FLOPS validation data collection. + keys : str, or iter of str + List of variables whose values will be transferred from the input data. + The default is all variables. + preprocess: bool + If true, the input data will be passed through preprocess_options() to + fill in any missing options before being returned. The default is False. + """ + try: + flops_data: dict = FLOPS_Test_Data[case_name] + except KeyError: + flops_data: dict = FLOPS_Lacking_Test_Data[case_name] + + flops_inputs_copy: AviaryValues = flops_data['inputs'].deepcopy() + if preprocess: + preprocess_options(flops_inputs_copy, engine_models=[build_engine_deck(flops_inputs_copy)]) + + if keys is None: + options = extract_options(flops_inputs_copy) + else: + options = extract_options(keys) + + return options + + def get_flops_outputs(case_name: str, keys: str = None) -> AviaryValues: """ Returns an AviaryValues object containing output data for the named FLOPS validation case. @@ -377,7 +424,6 @@ def print_case(testcase_func, param_num, param: param): def _assure_is_list(keys, backup=None): - if isinstance(keys, str): return [keys] elif not keys: diff --git a/aviary/variable_info/enums.py b/aviary/variable_info/enums.py index 75d7392b72..a604f4e4fb 100644 --- a/aviary/variable_info/enums.py +++ b/aviary/variable_info/enums.py @@ -1,8 +1,16 @@ from enum import Enum, IntEnum, auto, unique +class AircraftTypes(Enum): + """Aircraft types.""" + + TRANSPORT = 'transport' + BLENDED_WING_BODY = 'BWB' + # GENERAL_AVIATION = 'GA' # incomplete in FLOPS, unavailable in GASP + + class AlphaModes(Enum): - ''' + """ AlphaModes is used to specify how angle of attack is defined during climb and descent. DEFAUT: @@ -25,7 +33,8 @@ class AlphaModes(Enum): ALTITUDE_RATE Alpha is calculated to target a specified altitude rate, the default is 0 (Constant Altitude). - ''' + """ + DEFAULT = auto() ROTATION = auto() LOAD_FACTOR = auto() @@ -37,30 +46,13 @@ class AlphaModes(Enum): FLIGHT_PATH_ANGLE = auto() -class AnalysisScheme(Enum): - """ - AnalysisScheme is used to select from Collocation and shooting. - - COLLOCATION uses the collocation method to optimize all points simultaneously - and can be run in parallel. However, it requires reasonable initial guesses - for the trajectory and is fairly sensitive to those initial guesses. - - SHOOTING is a forward in time integration method that simulates the trajectory. - This does not require initial guesses and will always produce physically valid - trajectories, even during optimizer failures. The shooting method cannot be run - in parallel. - """ - COLLOCATION = auto() - SHOOTING = auto() - - class EquationsOfMotion(Enum): - """ - Available equations of motion for use during mission analysis - """ + """Available equations of motion for use during mission analysis.""" + HEIGHT_ENERGY = 'height_energy' TWO_DEGREES_OF_FREEDOM = '2DOF' SOLVED_2DOF = 'solved_2DOF' + CUSTOM = 'custom' @unique @@ -68,8 +60,9 @@ class GASPEngineType(Enum): """ Defines the type of engine to use in GASP-based mass calculations. Note that only the value for the first engine model will be used. - Currenly only the TURBOJET option is implemented, but other types of engines will be added in the future. + Currently only the TURBOJET and TURBOPROP options are implemented, but other types of engines will be added in the future. """ + # Reciprocating engine with carburator RECIP_CARB = 1 @@ -107,12 +100,15 @@ class GASPEngineType(Enum): # for geometry and mass ROTARY_RCWSZ = 14 + @classmethod + def get_element_by_name(cls, val: str): + return next((c for c in cls if c.name == val), None) + @unique class FlapType(Enum): - """ - Defines the type of flap used on the wing. Used in GASP-based aerodynamics and mass calculations. - """ + """Defines the type of flap used on the wing. Used in GASP-based aerodynamics and mass calculations.""" + PLAIN = 1 SPLIT = 2 SINGLE_SLOTTED = 3 @@ -121,11 +117,14 @@ class FlapType(Enum): FOWLER = 6 DOUBLE_SLOTTED_FOWLER = 7 + @classmethod + def get_element_by_name(cls, val: str): + return next((c for c in cls if c.name == val), None) + class LegacyCode(Enum): - """ - Flag for legacy codebases - """ + """Flag for legacy codebases.""" + FLOPS = 'FLOPS' GASP = 'GASP' @@ -152,13 +151,14 @@ class ProblemType(Enum): gross weight, it will then find the maximum distance the off-design aircraft can fly. - MULTI_MISSION: Similar to a SIZING mission, however it varies the - design gross weight and actual gross weight across multiple missions - to and closes design range for each mission. This causes the empty - weight and the fuel weight to change. The final result will be a + MULTI_MISSION: Similar to a SIZING mission, however it varies the + design gross weight and actual gross weight across multiple missions + to and closes design range for each mission. This causes the empty + weight and the fuel weight to change. The final result will be a single empty weight, for all the different missions, and multiple values for fuel weight, unique to each mission. """ + SIZING = 'sizing' ALTERNATE = 'alternate' FALLOUT = 'fallout' @@ -166,12 +166,13 @@ class ProblemType(Enum): class SpeedType(Enum): - ''' + """ SpeedType is used to specify the type of speed being used. EAS is equivalent airspeed. TAS is true airspeed. - MACH is mach - ''' + MACH is mach. + """ + EAS = 'EAS' TAS = 'TAS' MACH = 'mach' @@ -188,18 +189,20 @@ class ThrottleAllocation(Enum): STATIC is specified by the optimizer as one value for the whole phase. DYNAMIC is specified by the optimizer at each point in the phase. """ - FIXED = 1 - STATIC = 2 - DYNAMIC = 3 + + FIXED = 'fixed' + STATIC = 'static' + DYNAMIC = 'dynamic' class Verbosity(IntEnum): """ - Sets how much information Aviary outputs when run + Sets how much information Aviary outputs when run. Verbosity levels are based on ubuntu's standard: https://discourse.ubuntu.com/t/cli-verbosity-levels/26973 """ + QUIET = 0 BRIEF = 1 VERBOSE = 2 @@ -211,17 +214,3 @@ def __str__(self): @classmethod def values(cls): return {c.value for c in cls} - - -class OutMachType(Enum): - ''' - OutMachType is an indicator which mach number to output. - helical_mach = sqrt(mach*mach + tip_mach*tip_mach) - ''' - MACH = 'mach' - TIP_MACH = 'tip_mach' - HELICAL_MACH = 'helical_mach' - - @classmethod - def get_element_by_value(cls, val: str): - return next((c for c in cls if c.value == val), None) diff --git a/aviary/variable_info/functions.py b/aviary/variable_info/functions.py index 8c28147a06..c4db078308 100644 --- a/aviary/variable_info/functions.py +++ b/aviary/variable_info/functions.py @@ -1,82 +1,316 @@ +from enum import Enum + import dymos as dm +import numpy as np import openmdao.api as om from dymos.utils.misc import _unspecified from openmdao.core.component import Component +from aviary.utils.aviary_options_dict import units_setter from aviary.utils.aviary_values import AviaryValues -from aviary.variable_info.variables import Settings +from aviary.utils.utils import cast_type, check_type, enum_setter, wrapped_convert_units +from aviary.variable_info.enums import Verbosity from aviary.variable_info.variable_meta_data import _MetaData +from aviary.variable_info.variables import Aircraft, Mission, Settings # --------------------------- # Helper functions for setting up inputs/outputs in components # --------------------------- -def add_aviary_input(comp, varname, val=None, units=None, desc=None, shape_by_conn=False, meta_data=_MetaData, shape=None): - ''' +def add_aviary_input( + comp, + varname, + val=None, + units=None, + desc=None, + shape_by_conn=False, + meta_data=_MetaData, + shape=None, + primal_name=None, +): + """ This function provides a clean way to add variables from the variable hierarchy into components as Aviary inputs. It takes the standard OpenMDAO inputs of the variable's name, initial value, units, and description, as well as the component which the variable is being added to. - ''' + + Parameters + ---------- + comp: Component + OpenMDAO component to add this variable. + varname: str + Name of variable. + val: float or ndarray + Default value for variable. + units: str + (Optional) when specifying val, units should also be specified. + desc: str + (Optional) description text for the variable. + shape_by_conn: bool + Set to True to infer the shape from the connected output. + meta_data: dict + (Optional) Aviary metadata dictionary. If unspecified, the built-in metadata will + be used. + shape: tuple + (Optional) shape for this input. + primal_name : str or None + Valid python name to represent the variable in compute_primal if 'name' is not a valid + python name. + """ meta = meta_data[varname] - if units: - input_units = units - else: - # units of None are overwritten with defaults. Overwriting units with None is - # unecessary as it will cause errors down the line if the default is not already - # None - input_units = meta['units'] - if desc: - input_desc = desc - else: - input_desc = meta['desc'] - if val is None: - val = meta['default_value'] - comp.add_input(varname, val=val, units=input_units, - desc=input_desc, shape_by_conn=shape_by_conn, shape=shape) + # units of None are overwritten with defaults. Overwriting units with None is + # unnecessary as it will cause errors down the line if the default is not already + # None + default_units = meta['units'] + + if units is None: + units = default_units + if desc is None: + desc = meta['desc'] -def add_aviary_output(comp, varname, val, units=None, desc=None, shape_by_conn=False, meta_data=_MetaData): - ''' + if val is None: + if shape is None: + val = meta['default_value'] + if val is None: + val = 0.0 + else: + val = meta['default_value'] + if val is None: + val = np.zeros(shape) + else: + val = np.ones(shape) * val + + # val was not provided but different units were + if units != default_units: + try: + # convert the default units to requested units + val = wrapped_convert_units((val, default_units), units) + except ValueError: + raise ValueError( + f'The requested units {units} for input {varname} in component ' + f'{comp.name} are invalid.' + ) + + # check types + val = cast_type(varname, val, meta_data) + check_type(varname, val, meta_data) + + comp.add_input( + varname, + val=val, + units=units, + desc=desc, + shape_by_conn=shape_by_conn, + shape=shape, + primal_name=primal_name, + ) + + +def add_aviary_output( + comp, + varname, + val=None, + units=None, + desc=None, + shape_by_conn=False, + meta_data=_MetaData, + shape=None, + primal_name=None, +): + """ This function provides a clean way to add variables from the variable hierarchy into components as Aviary outputs. It takes the standard OpenMDAO inputs of the variable's name, initial value, units, and description, as well as the component which the variable is being added to. - ''' + + Parameters + ---------- + comp: Component + OpenMDAO component to add this variable. + varname: str + Name of variable. + val: float or ndarray + (Optional) Default value for variable. If not specified, the value from metadata + is used. + units: str + (Optional) when specifying val, units should also be specified. + desc: str + (Optional) description text for the variable. + shape_by_conn: bool + Set to True to infer the shape from the connected output. + meta_data: dict + (Optional) Aviary metadata dictionary. If unspecified, the built-in metadata will + be used. + shape: tuple + (Optional) shape for this input. + primal_name : str or None + Valid python name to represent the variable in compute_primal if 'name' is not a valid + python name. + """ meta = meta_data[varname] - if units: - output_units = units - else: - # units of None are overwritten with defaults. Overwriting units with None is - # unecessary as it will cause errors down the line if the default is not already - # None - output_units = meta['units'] - if desc: - output_desc = desc + # units of None are overwritten with defaults. Overwriting units with None is + # unnecessary as it will cause errors down the line if the default is not already + # None + default_units = meta['units'] + + if units is None: + units = default_units + + if desc is None: + desc = meta['desc'] + + if val is None: + if shape is None: + val = meta['default_value'] + if val is None: + val = 0.0 + else: + val = meta['default_value'] + if val is None: + val = np.zeros(shape) + else: + val = np.ones(shape) * val + + # val was not provided but different units were + if units != default_units: + try: + # convert the default units to requested units + val = wrapped_convert_units((val, default_units), units) + except ValueError: + raise ValueError( + f'The requested units {units} for output {varname} in component ' + f'{comp.name} are invalid.' + ) + + # check types + val = cast_type(varname, val, meta_data) + check_type(varname, val, meta_data) + + comp.add_output( + varname, + val=val, + units=units, + desc=desc, + shape_by_conn=shape_by_conn, + primal_name=primal_name, + ) + + +def add_aviary_option(comp, name, val=_unspecified, units=None, desc=None, meta_data=_MetaData): + """ + Adds an option to an Aviary component. Default values from the metadata are used + unless a new value is specified. + + Parameters + ---------- + comp: Component + OpenMDAO component to add this option. + name: str + Name of variable. + val: float or ndarray + (Optional) Default value for option. If not specified, the value from metadata + is used. + desc: str + (Optional) description text for the variable. + units: str + (Optional) OpenMDAO units string. This can be specified for variables with units. + meta_data: dict + (Optional) Aviary metadata dictionary. If unspecified, the built-in metadata will + be used. + """ + meta = meta_data[name] + # units of None are overwritten with defaults. Overwriting units with None is + # unnecessary as it will cause errors down the line if the default is not already + # None + default_units = meta['units'] + + if units is None: + units = default_units + + if desc is None: + desc = meta['desc'] + + # check units + if val is _unspecified: + val = meta['default_value'] + + # val was not provided but different units were + if units != default_units: + try: + # convert the default units to requested units + val = wrapped_convert_units((val, default_units), units) + except ValueError: + raise ValueError( + f'The requested units {units} for output {name} in component ' + f'{comp.name} are invalid.' + ) + + # value of None needs to be skipped due to unusual setup of + # subsystems/mass/flops_based/wing_group.py + if val is not None: + # check types + val = cast_type(name, val, meta_data) + check_type(name, val, meta_data) + + # Need to gather expected types since sometimes we need to use these to declare the + # option. Most of the time, types is overwritten to tuple to support (val, units) + types = meta['types'] + if meta_data[name]['multivalue']: + if isinstance(types, tuple): + types = (list, np.ndarray, tuple, *types) + else: + types = (list, np.ndarray, tuple, types) + + if units not in [None, 'unitless']: + types = tuple + comp.options.declare( + name, + default=(val, units), + types=types, + desc=desc, + set_function=units_setter, + ) + + elif isinstance(val, Enum): + comp.options.declare(name, default=val, types=types, desc=desc, set_function=enum_setter) + else: - output_desc = meta['desc'] - comp.add_output(varname, val=val, units=output_units, - desc=output_desc, shape_by_conn=shape_by_conn) - - -def override_aviary_vars(group: om.Group, aviary_inputs: AviaryValues, - manual_overrides=None, external_overrides=None): - ''' - This function provides the capability to override output variables - with variables from the aviary_inputs input. The user can also - optionally provide the names of variables that they would like to - override manually. (Manual overriding is simply suppressing the - promotion of the variable to make way for another output variable - of the same name, or to create an unconnected input elsewhere.) - ''' + comp.options.declare(name, default=val, types=types, desc=desc) + + +def override_aviary_vars( + group: om.Group, + aviary_inputs: AviaryValues, + code_origin_overrides=None, + external_overrides=None, +): + """ + This function gives Aviary the capability to override output variables with variables from the + aircraft represented in aviary_inputs. + + This may also be called manually in a Level-3 model for the same purpose. + + Parameters + ---------- + group: om.Group + Group to execute the promotes, usually an AviaryGroup. + aviary_inputs : AviaryValues + Aircraft data container. + code_origin_overrides : list or None + List of Aviary variables names to prioritize when GASP and FLOPS both compute it. + external_overrides : list or None + List of Aviary variables names to override that are computed in external subsystems. + """ + def name_filter(name): - return "aircraft:" in name or "mission:" in name + return 'aircraft:' in name or 'mission:' in name - if not manual_overrides: - manual_overrides = [] + if not code_origin_overrides: + code_origin_overrides = [] if not external_overrides: external_overrides = [] @@ -85,7 +319,7 @@ def name_filter(name): # so that we can keep track of any unclaimed inputs all_inputs = set() # use a set to avoid duplicates for system in group.system_iter(): - meta = system.get_io_metadata(iotypes=("input",)) + meta = system.get_io_metadata(iotypes=('input',)) in_var_names = meta.keys() for name in in_var_names: all_inputs.add(name) @@ -94,26 +328,31 @@ def name_filter(name): external_overridden_outputs = [] for comp in group.system_iter(typ=Component): # get a list of the variables to use - out_var_names = list(filter(name_filter, comp.get_io_metadata( - iotypes=("output",), return_rel_names=False))) + out_var_names = list( + filter( + name_filter, + comp.get_io_metadata(iotypes=('output',), return_rel_names=False), + ) + ) # get a list of the metadata associated with each variable - out_var_metadata = comp.get_io_metadata( - iotypes=("output",), return_rel_names=False) - in_var_names = filter(name_filter, comp.get_io_metadata(iotypes=("input", ))) + out_var_metadata = comp.get_io_metadata(iotypes=('output',), return_rel_names=False) + in_var_names = filter(name_filter, comp.get_io_metadata(iotypes=('input',))) comp_promoted_outputs = [] for abs_name in out_var_names: name = out_var_metadata[abs_name]['prom_name'] - if abs_name in manual_overrides: - # These are handled outside of this function. + if abs_name in code_origin_overrides: + # These variables are ones that are computed in both GASP and FLOPS when both + # geometries are present. Aviary determines which one to favor, and which to + # remove by overriding it. + # TODO: What if user wants to override one of these? continue elif name in external_overrides: - # Overridden variables are given a new name - comp_promoted_outputs.append((name, f"EXTERNAL_OVERRIDE:{name}")) + comp_promoted_outputs.append((name, f'EXTERNAL_SUBSYSTEM_OVERRIDE:{name}')) external_overridden_outputs.append(name) continue # don't promote it @@ -124,36 +363,36 @@ def name_filter(name): group.set_input_defaults(name, val=val, units=units) # Overridden variables are given a new name - comp_promoted_outputs.append((name, f"AUTO_OVERRIDE:{name}")) + comp_promoted_outputs.append((name, f'AIRCRAFT_DATA_OVERRIDE:{name}')) overridden_outputs.append(name) continue # don't promote it - # This variable is not overriden, so the output is promoted. + # This variable is not overridden, so the output is promoted. comp_promoted_outputs.append(name) # NOTE Always promoting all inputs into the "global" namespace # so its VERY important that we enforce all inputs names exist in the master # variable list - rel_path = comp.pathname[len(group.pathname):].lstrip(".") - if "." in rel_path: + rel_path = comp.pathname[len(group.pathname) :].lstrip('.') + if '.' in rel_path: # comp is in a subgroup. We must find it. - sub_path = ".".join(rel_path.split(".")[:-1]) + sub_path = '.'.join(rel_path.split('.')[:-1]) sub = group._get_subsystem(sub_path) sub.promotes(comp.name, inputs=in_var_names, outputs=comp_promoted_outputs) else: group.promotes(comp.name, inputs=in_var_names, outputs=comp_promoted_outputs) if overridden_outputs: - if aviary_inputs.get_val(Settings.VERBOSITY).value >= 1: # Verbosity.BRIEF - print("\nThe following variables have been overridden:") + if aviary_inputs.get_val(Settings.VERBOSITY).value >= Verbosity.VERBOSE: # VERBOSE, DEBUG + print('\nThe following variables have been overridden in the aircraft definition:') for prom_name in sorted(overridden_outputs): val, units = aviary_inputs.get_item(prom_name) print(f" '{prom_name} {val} {units}") if external_overridden_outputs: - if aviary_inputs.get_val(Settings.VERBOSITY).value >= 1: - print("\nThe following variables have been overridden by an external subsystem:") + if aviary_inputs.get_val(Settings.VERBOSITY).value >= Verbosity.VERBOSE: # VERBOSE, DEBUG + print('\nThe following variables have been overridden by an external subsystem:') for prom_name in sorted(external_overridden_outputs): # do not print values because they will be updated by an external subsystem later. print(f" '{prom_name}") @@ -162,8 +401,13 @@ def name_filter(name): def setup_trajectory_params( - model: om.Group, traj: dm.Trajectory, aviary_variables: AviaryValues, phases=['climb', 'cruise', 'descent'], - variables_to_add=None, meta_data=_MetaData, external_parameters={}, + model: om.Group, + traj: dm.Trajectory, + aviary_variables: AviaryValues, + phases=['climb', 'cruise', 'descent'], + variables_to_add=None, + meta_data=_MetaData, + external_parameters={}, ): """ This function smoothly sorts through the aviary variables which @@ -190,11 +434,7 @@ def setup_trajectory_params( # Assuming the kwargs are the same for shared parameters kwargs = external_parameters[phases[0]][key] targets = {phase: [key] for phase in phases} - traj.add_parameter( - key, - **kwargs, - targets=targets - ) + traj.add_parameter(key, **kwargs, targets=targets) model.promotes('traj', inputs=[(f'parameters:{key}', key)]) already_added.append(key) @@ -204,7 +444,6 @@ def setup_trajectory_params( # TODO: As we use more builders, we may reach the point where we don't need # to do these anymore. for key in sorted(variables_to_add): - if key in already_added: continue @@ -233,7 +472,8 @@ def setup_trajectory_params( units=units, val=val, static_target=True, - targets={phase_name: [key] for phase_name in phases}) + targets={phase_name: [key] for phase_name in phases}, + ) model.promotes('traj', inputs=[(f'parameters:{key}', key)]) @@ -256,3 +496,122 @@ def get_units(key, meta_data=None) -> str: meta_data = _MetaData return meta_data[key]['units'] + + +def extract_options(aviary_inputs: AviaryValues, metadata=_MetaData) -> dict: + """ + Extract a dictionary of options from the given aviary_inputs. + + Parameters + ---------- + aviary_inputs : AviaryValues + Instance of AviaryValues containing all initial values. + meta_data : dict + (Optional) Dictionary of aircraft metadata. Uses Aviary's built-in + metadata by default. + + Returns + ------- + dict + Dictionary of option names and values. + """ + options = {} + for key, meta in metadata.items(): + if key not in aviary_inputs: + continue + + if not meta['option']: + continue + + val, units = aviary_inputs.get_item(key) + meta_units = meta['units'] + + if meta_units == 'unitless' or meta_units is None: + options[key] = val + + else: + # Implement as (quantity, unit) + options[key] = (val, units) + + return options + + +def setup_model_options( + prob: om.Problem, + aviary_inputs: AviaryValues, + meta_data=_MetaData, + engine_models=None, + prefix=None, + group=None, +): + """ + Setup the correct model options for an aviary problem. + + Parameters + ---------- + prob: Problem + OpenMDAO problem prior to setup. + aviary_inputs : AviaryValues + Instance of AviaryValues containing all initial values. + meta_data : dict + (Optional) Dictionary of aircraft metadata. Uses Aviary's built-in + metadata by default. + engine_models : List of EngineModels or None + (Optional) Engine models + prefix : str + Prefix for model options. Used for multi-mission. + group : AviaryGroup + The AviaryGroup object that we are setting models on + """ + + # Use OpenMDAO's model options to pass all options through the system hierarchy. + if prefix is not None: + prefix = f'{prefix}.' + else: + prefix = '' # the original default value + prob.model_options[f'{prefix}*'] = extract_options(aviary_inputs, meta_data) + + # Multi-engines need to index into their options. + try: + num_engine_models = len(aviary_inputs.get_val(Aircraft.Engine.NUM_ENGINES)) + except KeyError: + # No engine data. + return + + # TODO: Modify this method for multi mission/model. + + if num_engine_models > 1: + if engine_models is None: + # Required in multi-mission cases + if group is None: + engine_models = prob.model.engine_builders + else: + engine_models = group.engine_builders + + for idx in range(num_engine_models): + eng_name = engine_models[idx].name + + # TODO: For future flexibility, need get a list of options per engine (these are + # EngineDeck required options), so custom multiengine works + opt_names = [ + Aircraft.Engine.SCALE_PERFORMANCE, + Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, + Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER, + Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, + Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM, + ] + opt_names_units = [ + Aircraft.Engine.REFERENCE_SLS_THRUST, + Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, + ] + opts = {} + for key in opt_names: + if key in aviary_inputs: + opts[key] = aviary_inputs.get_item(key)[0][idx] + for key in opt_names_units: + if key in aviary_inputs: + val, units = aviary_inputs.get_item(key) + opts[key] = (val[idx], units) + + path = f'{prefix}*core_propulsion.{eng_name}*' + prob.model_options[path] = opts diff --git a/aviary/variable_info/options.py b/aviary/variable_info/options.py index 3e1b30f9bd..e446edc28c 100644 --- a/aviary/variable_info/options.py +++ b/aviary/variable_info/options.py @@ -1,9 +1,9 @@ +from aviary.subsystems.propulsion.engine_deck import EngineDeck from aviary.utils.aviary_values import AviaryValues -from aviary.utils.preprocessors import preprocess_propulsion from aviary.utils.functions import get_path +from aviary.utils.preprocessors import preprocess_propulsion from aviary.variable_info.variable_meta_data import _MetaData from aviary.variable_info.variables import Aircraft -from aviary.subsystems.propulsion.engine_deck import EngineDeck def get_option_defaults(engine=True, meta_data=_MetaData) -> AviaryValues: @@ -18,7 +18,6 @@ def get_option_defaults(engine=True, meta_data=_MetaData) -> AviaryValues: Dictionary containing metadata for the options. If None, Aviary's built-in metadata will be used. """ - option_defaults = AviaryValues() # Load all variables marked as options in the MetaData @@ -29,10 +28,10 @@ def get_option_defaults(engine=True, meta_data=_MetaData) -> AviaryValues: if engine: engine_options = option_defaults.deepcopy() - engine_options.set_val(Aircraft.Engine.DATA_FILE, - get_path('models/engines/turbofan_23k_1.deck')) - engine_options.set_val(Aircraft.Engine.SCALE_FACTOR, - meta_data[Aircraft.Engine.SCALE_FACTOR]['default_value']) + engine_options.set_val( + Aircraft.Engine.DATA_FILE, get_path('models/engines/turbofan_23k_1.csv') + ) + engine_options.set_val(Aircraft.Engine.REFERENCE_SLS_THRUST, 28690, 'lbf') engine_deck = EngineDeck(options=engine_options) preprocess_propulsion(option_defaults, [engine_deck]) @@ -51,5 +50,4 @@ def is_option(key, meta_data=_MetaData) -> bool: Dictionary containing metadata for the variable. If None, Aviary's built-in metadata will be used. """ - return meta_data[key]['option'] diff --git a/aviary/variable_info/test/test_functions.py b/aviary/variable_info/test/test_functions.py new file mode 100644 index 0000000000..4cd5bd4140 --- /dev/null +++ b/aviary/variable_info/test/test_functions.py @@ -0,0 +1,60 @@ +import unittest + +import openmdao.api as om +from openmdao.utils.assert_utils import assert_near_equal + +from aviary.utils.develop_metadata import add_meta_data +from aviary.variable_info.functions import add_aviary_input, add_aviary_option, add_aviary_output + + +class InputOutputOptionTest(unittest.TestCase): + """Test the use of unit conversion when adding Aviary inputs, outputs, options.""" + + def test_unit_conversion(self): + comp = DummyComp() + prob = om.Problem() + prob.model.add_subsystem('comp', comp, promotes=['*']) + prob.setup() + prob.run_model() + tol = 1e-4 # whether or not a unit is converted does not need high tol + assert_near_equal(43.0556, prob.get_val('area'), tolerance=tol) + assert_near_equal(9.84252, prob.get_val('length_out'), tolerance=tol) + assert_near_equal(5000, prob.get_val('mass'), tolerance=tol) + assert_near_equal(11.0231, prob.get_val('mass_out'), tolerance=tol) + + # Note: Checking OpenMDAO internals for primal_name. + self.assertEqual(prob.model.comp._valid_name_map['length'], 'aa') + self.assertEqual(prob.model.comp._valid_name_map['mass'], 'zz') + + +class DummyComp(om.ExplicitComponent): + """Simple component to test unit conversion.""" + + def initialize(self): + add_aviary_option(self, 'mass', units='lbm', meta_data=dummy_metadata) + + def setup(self): + add_aviary_input(self, 'length', units='ft', meta_data=dummy_metadata, primal_name='aa') + + add_aviary_output(self, 'area', units='ft**2', meta_data=dummy_metadata) + self.add_output('length_out', val=0) + add_aviary_output(self, 'mass', units='g', meta_data=dummy_metadata, primal_name='zz') + self.add_output('mass_out', val=0) + + def compute(self, inputs, outputs): + mass = self.options['mass'][0] # should be 5 kg -> lbm + length = inputs['length'] # should be 3 m -> ft + + # outputs['area'] should default to 4 m**2 -> ft**2 + outputs['length_out'] = length # should return input 'length' in ft, NOT 3 + # outputs['mass'] should default to 5 kg -> g + outputs['mass_out'] = mass # should return option 'mass' in lbm, NOT 5 + + +dummy_metadata = {} +add_meta_data('mass', dummy_metadata, units='kg', default_value=5) +add_meta_data('length', dummy_metadata, units='m', default_value=3) +add_meta_data('area', dummy_metadata, units='m**2', default_value=4) + +if __name__ == '__main__': + unittest.main() diff --git a/aviary/variable_info/test/test_metadata_extension.py b/aviary/variable_info/test/test_metadata_extension.py index e660161d95..5ace2355f4 100644 --- a/aviary/variable_info/test/test_metadata_extension.py +++ b/aviary/variable_info/test/test_metadata_extension.py @@ -5,21 +5,20 @@ class MetaDataExtensionTest(unittest.TestCase): - """ - Test the use of extended meta data - """ + """Test the use of extended meta data.""" def test_metadata_extension(self): - aircraft_variable = ExtendedMetaData[Aircraft.LandingGear.MAIN_GEAR_OLEO_DIAMETER] - self.assertEqual(Aircraft.LandingGear.MAIN_GEAR_OLEO_DIAMETER, - 'aircraft:landing_gear:main_gear_oleo_diameter') + self.assertEqual( + Aircraft.LandingGear.MAIN_GEAR_OLEO_DIAMETER, + 'aircraft:landing_gear:main_gear_oleo_diameter', + ) self.assertEqual(aircraft_variable['units'], 'ft') self.assertEqual(aircraft_variable['desc'], 'Main gear oleo diameter') self.assertEqual(aircraft_variable['default_value'], 0.0) self.assertEqual(aircraft_variable['option'], False) - self.assertEqual(aircraft_variable['types'], None) + self.assertEqual(aircraft_variable['types'], float) if __name__ == '__main__': diff --git a/aviary/variable_info/test/test_var_structure.py b/aviary/variable_info/test/test_var_structure.py index 7c31fb7428..36674a50c6 100644 --- a/aviary/variable_info/test/test_var_structure.py +++ b/aviary/variable_info/test/test_var_structure.py @@ -1,12 +1,14 @@ import unittest - from copy import deepcopy from aviary.utils.test_utils.variable_test import ( - assert_metadata_alphabetization, assert_no_duplicates, - assert_structure_alphabetization, get_names_from_hierarchy) + assert_metadata_alphabetization, + assert_no_duplicates, + assert_structure_alphabetization, + get_names_from_hierarchy, +) from aviary.variable_info.variable_meta_data import _MetaData -from aviary.variable_info.variables import Aircraft, Mission, Dynamic, Settings +from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings class DuplicateHierarchy: @@ -23,22 +25,17 @@ class OperatingLimits: class MetaDataTest(unittest.TestCase): - """ - Tests for variable_meta_data.py: check for duplicate legacy code names, alphabetization, and any missing names from variable hierarchy. - """ + """Tests for variable_meta_data.py: check for duplicate legacy code names, alphabetization, and any missing names from variable hierarchy.""" def test_duplicate_names_FLOPS(self): - - flops_names = [var["historical_name"]['FLOPS'] for var in _MetaData.values()] + flops_names = [var['historical_name']['FLOPS'] for var in _MetaData.values()] assert_no_duplicates(flops_names) def test_duplicate_names_LEAPS1(self): - - leaps1_names = [var["historical_name"]['LEAPS1'] for var in _MetaData.values()] + leaps1_names = [var['historical_name']['LEAPS1'] for var in _MetaData.values()] assert_no_duplicates(leaps1_names) def test_alphabetization(self): - # TODO currently excluding Dynamic variables that do not have proper full # names mirroring the hierarchy metadata_var_names = [key for key in _MetaData if ':' in key] @@ -47,53 +44,56 @@ def test_alphabetization(self): def test_missing_names(self): # Test that all variables inside the metadata exist in the hierarchy, and vice-versa - var_names = \ - get_names_from_hierarchy(Aircraft)\ - + get_names_from_hierarchy(Mission)\ - + get_names_from_hierarchy(Dynamic)\ + var_names = ( + get_names_from_hierarchy(Aircraft) + + get_names_from_hierarchy(Mission) + + get_names_from_hierarchy(Dynamic) + get_names_from_hierarchy(Settings) + ) metadata_dict = deepcopy(_MetaData) for var in var_names: try: metadata_dict.pop(var) except (TypeError, KeyError): - raise Exception(f"Variable {var} is present in variables.py but is not " - 'defined in metadata') + raise Exception( + f'Variable {var} is present in variables.py but is not defined in metadata' + ) if metadata_dict: # This will only happen if a variable in the metadata wasn't using the hierarchy - raise Exception(f'Variables {[*metadata_dict.keys()]} are present in metadata, but are' - ' not defined in variables.py') + raise Exception( + f'Variables {[*metadata_dict.keys()]} are present in metadata, but are' + ' not defined in variables.py' + ) class VariableStructureTest(unittest.TestCase): - """ - Tests for variables.py: check for duplicates and alphabetization - """ + """Tests for variables.py: check for duplicates and alphabetization.""" def test_duplicate_names_Aviary(self): - - aviary_names = get_names_from_hierarchy(Aircraft)\ - + get_names_from_hierarchy(Mission)\ - + get_names_from_hierarchy(Dynamic)\ + aviary_names = ( + get_names_from_hierarchy(Aircraft) + + get_names_from_hierarchy(Mission) + + get_names_from_hierarchy(Dynamic) + get_names_from_hierarchy(Settings) + ) assert_no_duplicates(aviary_names) def test_alphabetization(self): - - assert_structure_alphabetization("variable_info/variables.py") + assert_structure_alphabetization('variable_info/variables.py') class TestTheTests(unittest.TestCase): def test_duplication_check(self): - with self.assertRaises(ValueError) as cm: duplicated_names = get_names_from_hierarchy(DuplicateHierarchy) assert_no_duplicates(duplicated_names) - self.assertEqual(str( - cm.exception), "The variables ['mission:design:cruise_mach'] are duplicates in the provided list.") + self.assertEqual( + str(cm.exception), + "The variables ['mission:design:cruise_mach'] are duplicates in the provided list.", + ) -if __name__ == "__main__": +if __name__ == '__main__': unittest.main() diff --git a/aviary/variable_info/variable_meta_data.py b/aviary/variable_info/variable_meta_data.py index 2ad85f2ea7..b8da71be22 100644 --- a/aviary/variable_info/variable_meta_data.py +++ b/aviary/variable_info/variable_meta_data.py @@ -1,13 +1,22 @@ -''' +""" Define meta data associated with variables in the Aviary data hierarchy. -''' -import numpy as np +""" from copy import deepcopy from pathlib import Path +import numpy as np + from aviary.utils.develop_metadata import add_meta_data -from aviary.variable_info.enums import EquationsOfMotion, FlapType, GASPEngineType, LegacyCode, Verbosity, ProblemType +from aviary.variable_info.enums import ( + AircraftTypes, + EquationsOfMotion, + FlapType, + GASPEngineType, + LegacyCode, + ProblemType, + Verbosity, +) from aviary.variable_info.variables import Aircraft, Dynamic, Mission, Settings # --------------------------- @@ -21,7 +30,9 @@ # --------------------------- _MetaData = {} - +# TODO Metadata descriptions should contain which core subsystems that variable appears +# in. A standardized format for this should be created that takes advantage of +# newlines, tabs, etc. kind of like a docstring. # ================================================================================================================================================================ # .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. # | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | @@ -51,25 +62,24 @@ # - see also: Aircraft.AirConditioning.MASS_SCALER Aircraft.AirConditioning.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(23, 2)', '~WEIGHT.WAC', '~WTSTAT.WSP(23, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._air_conditioning_group_weight', - 'aircraft.outputs.L0_weights_summary.air_conditioning_group_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(23, 2)', '~WEIGHT.WAC', '~WTSTAT.WSP(23, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._air_conditioning_group_weight', + 'aircraft.outputs.L0_weights_summary.air_conditioning_group_weight', + ], + }, units='lbm', desc='air conditioning system mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.AirConditioning.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(6)', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CW(6)', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='mass trend coefficient of air conditioning', default_value=1.0, @@ -78,11 +88,12 @@ add_meta_data( Aircraft.AirConditioning.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WAC', 'MISWT.WAC', 'MISWT.OAC'], - "FLOPS": 'WTIN.WAC', - "LEAPS1": 'aircraft.inputs.L0_overrides.air_conditioning_group_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WAC', 'MISWT.WAC', 'MISWT.OAC'], + 'FLOPS': 'WTIN.WAC', + 'LEAPS1': 'aircraft.inputs.L0_overrides.air_conditioning_group_weight', + }, units='unitless', desc='air conditioning system mass scaler', default_value=1.0, @@ -103,26 +114,29 @@ # - see also: Aircraft.AntiIcing.MASS_SCALER Aircraft.AntiIcing.MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(7)', - # ['WTS.WSP(24, 2)', '~WEIGHT.WAI', '~WTSTAT.WSP(24, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._aux_gear_weight', - 'aircraft.outputs.L0_weights_summary.aux_gear_weight', - ] - }, + historical_name={ + 'GASP': 'INGASP.CW(7)', + # ['WTS.WSP(24, 2)', '~WEIGHT.WAI', '~WTSTAT.WSP(24, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._aux_gear_weight', + 'aircraft.outputs.L0_weights_summary.aux_gear_weight', + ], + }, units='lbm', desc='mass of anti-icing system (auxiliary gear)', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.AntiIcing.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WAI', 'MISWT.WAI', 'MISWT.OAI'], - "FLOPS": 'WTIN.WAI', - "LEAPS1": 'aircraft.inputs.L0_overrides.aux_gear_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WAI', 'MISWT.WAI', 'MISWT.OAI'], + 'FLOPS': 'WTIN.WAI', + 'LEAPS1': 'aircraft.inputs.L0_overrides.aux_gear_weight', + }, units='unitless', desc='anti-icing system mass scaler', default_value=1.0, @@ -141,26 +155,29 @@ # - see also: Aircraft.APU.MASS_SCALER Aircraft.APU.MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(1)', - # ['WTS.WSP(17, 2)', '~WEIGHT.WAPU', '~WTSTAT.WSP(17, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._aux_power_weight', - 'aircraft.outputs.L0_weights_summary.aux_power_weight', - ] - }, + historical_name={ + 'GASP': 'INGASP.CW(1)', + # ['WTS.WSP(17, 2)', '~WEIGHT.WAPU', '~WTSTAT.WSP(17, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._aux_power_weight', + 'aircraft.outputs.L0_weights_summary.aux_power_weight', + ], + }, units='lbm', desc='mass of auxiliary power unit', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.APU.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WAPU', 'MISWT.WAPU', 'MISWT.OAPU'], - "FLOPS": 'WTIN.WAPU', - "LEAPS1": 'aircraft.inputs.L0_overrides.aux_power_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WAPU', 'MISWT.WAPU', 'MISWT.OAPU'], + 'FLOPS': 'WTIN.WAPU', + 'LEAPS1': 'aircraft.inputs.L0_overrides.aux_power_weight', + }, units='unitless', desc='mass scaler for auxiliary power unit', default_value=1.0, @@ -179,26 +196,29 @@ # - see also: Aircraft.Avionics.MASS_SCALER Aircraft.Avionics.MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(5)', - # ['WTS.WSP(21, 2)', '~WEIGHT.WAVONC', '~WTSTAT.WSP(21, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._avionics_group_weight', - 'aircraft.outputs.L0_weights_summary.avionics_group_weight', - ] - }, + historical_name={ + 'GASP': 'INGASP.CW(5)', + # ['WTS.WSP(21, 2)', '~WEIGHT.WAVONC', '~WTSTAT.WSP(21, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._avionics_group_weight', + 'aircraft.outputs.L0_weights_summary.avionics_group_weight', + ], + }, units='lbm', desc='avionics mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Avionics.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WAVONC', 'MISWT.WAVONC', 'MISWT.OAVONC'], - "FLOPS": 'WTIN.WAVONC', - "LEAPS1": 'aircraft.inputs.L0_overrides.avionics_group_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WAVONC', 'MISWT.WAVONC', 'MISWT.OAVONC'], + 'FLOPS': 'WTIN.WAVONC', + 'LEAPS1': 'aircraft.inputs.L0_overrides.avionics_group_weight', + }, units='unitless', desc='avionics mass scaler', default_value=1.0, @@ -216,10 +236,11 @@ add_meta_data( Aircraft.Battery.ADDITIONAL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": 'aircraft.inputs.L0_battery.weight_offset' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, + 'LEAPS1': 'aircraft.inputs.L0_battery.weight_offset', + }, units='lbm', desc='mass of non energy-storing parts of the battery', default_value=0.0, @@ -228,43 +249,42 @@ add_meta_data( Aircraft.Battery.DISCHARGE_LIMIT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SOCMIN', - "FLOPS": None, - "LEAPS1": 'aircraft.inputs.L0_battery.depth_of_discharge' - }, + historical_name={ + 'GASP': 'INGASP.SOCMIN', + 'FLOPS': None, + 'LEAPS1': 'aircraft.inputs.L0_battery.depth_of_discharge', + }, units='unitless', desc='default constraint on how far the battery can discharge, as a proportion of ' - 'total energy capacity', + 'total energy capacity', default_value=0.2, ) add_meta_data( Aircraft.Battery.EFFICIENCY, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.EFF_BAT', "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': 'INGASP.EFF_BAT', 'FLOPS': None, 'LEAPS1': None}, units='unitless', default_value=1.0, - desc="battery pack efficiency", + desc='battery pack efficiency', ) add_meta_data( Aircraft.Battery.ENERGY_CAPACITY, meta_data=_MetaData, - historical_name={"GASP": 'EBATTAVL', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'EBATTAVL', 'FLOPS': None, 'LEAPS1': None}, units='kJ', - desc="total energy the battery can store" + desc='total energy the battery can store', ) add_meta_data( Aircraft.Battery.MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WBATTIN', - "FLOPS": None, - "LEAPS1": 'aircraft.inputs.L0_battery.weight' - }, + historical_name={ + 'GASP': 'INGASP.WBATTIN', + 'FLOPS': None, + 'LEAPS1': 'aircraft.inputs.L0_battery.weight', + }, units='lbm', desc='total mass of the battery', default_value=0.0, @@ -273,10 +293,11 @@ add_meta_data( Aircraft.Battery.PACK_ENERGY_DENSITY, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ENGYDEN', - "FLOPS": None, - "LEAPS1": 'aircraft.inputs.L0_battery.energy_density' - }, + historical_name={ + 'GASP': 'INGASP.ENGYDEN', + 'FLOPS': None, + 'LEAPS1': 'aircraft.inputs.L0_battery.energy_density', + }, units='kW*h/kg', desc='specific energy density of the battery pack', default_value=1.0, @@ -286,10 +307,7 @@ add_meta_data( Aircraft.Battery.PACK_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of the energy-storing components of the battery', default_value=0.0, @@ -298,22 +316,16 @@ add_meta_data( Aircraft.Battery.PACK_VOLUMETRIC_DENSITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='kW*h/L', desc='volumetric density of the battery pack', - default_value=0, + default_value=0.0, ) add_meta_data( Aircraft.Battery.VOLUME, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='ft*3', desc='total volume of the battery pack', default_value=0.0, @@ -331,29 +343,24 @@ # ======================================================================================================================== add_meta_data( - Aircraft.BWB.CABIN_AREA, + Aircraft.BWB.DETAILED_WING_PROVIDED, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.FUSEIN.ACABIN', 'WDEF.ACABIN'], - "FLOPS": 'FUSEIN.ACABIN', - "LEAPS1": ['aircraft.inputs.L0_blended_wing_body_design.cabin_area', - 'aircraft.cached.L0_blended_wing_body_design.cabin_area', - ] - }, - units='ft**2', - desc='fixed area of passenger cabin for blended wing body transports', - default_value=0.0, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='Flag if the detailed wing model is provided', + option=True, + types=bool, + default_value=True, ) add_meta_data( - Aircraft.BWB.NUM_BAYS, + Aircraft.BWB.MAX_NUM_BAYS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'FUSEIN.NBAY', # ['&DEFINE.FUSEIN.NBAY', 'FUSDTA.NBAY'], - "LEAPS1": ['aircraft.inputs.L0_blended_wing_body_design.bay_count', - 'aircraft.cached.L0_blended_wing_body_design.bay_count', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'FUSEIN.NBAYMX', # ['&DEFINE.FUSEIN.NBAYMX', 'FUSDTA.NBAYMX'], + 'LEAPS1': None, + }, units='unitless', desc='fixed number of bays', types=int, @@ -361,17 +368,37 @@ default_value=0, ) +add_meta_data( + Aircraft.BWB.NUM_BAYS, + meta_data=_MetaData, + historical_name={ + 'GASP': None, + 'FLOPS': 'FUSEIN.NBAY', # ['&DEFINE.FUSEIN.NBAY', 'FUSDTA.NBAY'], + 'LEAPS1': [ + 'aircraft.inputs.L0_blended_wing_body_design.bay_count', + 'aircraft.cached.L0_blended_wing_body_design.bay_count', + ], + }, + units='unitless', + desc='fixed number of passenger bays', + types=int, + multivalue=True, + option=False, + default_value=[0], +) + add_meta_data( Aircraft.BWB.PASSENGER_LEADING_EDGE_SWEEP, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.FUSEIN.SWPLE', 'FUSDTA.SWPLE'], - "FLOPS": 'FUSEIN.SWPLE', - "LEAPS1": 'aircraft.inputs.L0_blended_wing_body_design.passenger_leading_edge_sweep' - }, + historical_name={ + 'GASP': ['INGASP.SWP_FB'], + # ['&DEFINE.FUSEIN.SWPLE', 'FUSDTA.SWPLE'], + 'FLOPS': 'FUSEIN.SWPLE', + 'LEAPS1': 'aircraft.inputs.L0_blended_wing_body_design.passenger_leading_edge_sweep', + }, units='deg', - desc='sweep angle of the leading edge of the passenger cabin', - default_value=45.0, + desc='forebody sweep angle', + default_value=0.0, ) # _____ _ @@ -384,10 +411,11 @@ add_meta_data( Aircraft.Canard.AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.SCAN', # ['&DEFINE.WTIN.SCAN', 'EDETIN.SCAN'], - "LEAPS1": 'aircraft.inputs.L0_canard.area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.SCAN', # ['&DEFINE.WTIN.SCAN', 'EDETIN.SCAN'], + 'LEAPS1': 'aircraft.inputs.L0_canard.area', + }, units='ft**2', desc='canard theoretical area', default_value=0.0, @@ -396,48 +424,56 @@ add_meta_data( Aircraft.Canard.ASPECT_RATIO, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.ARCAN', # ['&DEFINE.WTIN.ARCAN', 'EDETIN.ARCAN'], - "LEAPS1": 'aircraft.inputs.L0_canard.aspect_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.ARCAN', # ['&DEFINE.WTIN.ARCAN', 'EDETIN.ARCAN'], + 'LEAPS1': 'aircraft.inputs.L0_canard.aspect_ratio', + }, units='unitless', desc='canard theoretical aspect ratio', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Canard.CHARACTERISTIC_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.EL[-1]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[-1]', - 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[-1]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.EL[-1]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[-1]', + 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[-1]', + ], + }, units='ft', - desc='Reynolds characteristic length for the canard' + desc='Reynolds characteristic length for the canard', + default_value=0.0, ) add_meta_data( Aircraft.Canard.FINENESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.FR[-1]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[-1]', - 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[-1]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.FR[-1]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[-1]', + 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[-1]', + ], + }, units='unitless', - desc='canard fineness ratio' + desc='canard fineness ratio', + default_value=0.0, ) add_meta_data( Aircraft.Canard.LAMINAR_FLOW_LOWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRLC', # ['&DEFINE.AERIN.TRLC', 'XLAM.TRLC', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.canard_percent_laminar_flow_lower_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRLC', # ['&DEFINE.AERIN.TRLC', 'XLAM.TRLC', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.canard_percent_laminar_flow_lower_surface', + }, units='unitless', desc='define percent laminar flow for canard lower surface', default_value=0.0, @@ -446,10 +482,11 @@ add_meta_data( Aircraft.Canard.LAMINAR_FLOW_UPPER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRUC', # ['&DEFINE.AERIN.TRUC', 'XLAM.TRUC', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.canard_percent_laminar_flow_upper_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRUC', # ['&DEFINE.AERIN.TRUC', 'XLAM.TRUC', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.canard_percent_laminar_flow_upper_surface', + }, units='unitless', desc='define percent laminar flow for canard upper surface', default_value=0.0, @@ -460,25 +497,28 @@ # - see also: Aircraft.Canard.MASS_SCALER Aircraft.Canard.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(5, 2)', '~WEIGHT.WCAN', '~WTSTAT.WSP(5, 2)', '~INERT.WCAN'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._canard_weight', - 'aircraft.outputs.L0_weights_summary.canard_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(5, 2)', '~WEIGHT.WCAN', '~WTSTAT.WSP(5, 2)', '~INERT.WCAN'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._canard_weight', + 'aircraft.outputs.L0_weights_summary.canard_weight', + ], + }, units='lbm', desc='mass of canards', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Canard.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRCAN', # ['&DEFINE.WTIN.FRCAN', 'WTS.FRCAN', ], - "LEAPS1": 'aircraft.inputs.L0_overrides.canard_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRCAN', # ['&DEFINE.WTIN.FRCAN', 'WTS.FRCAN', ], + 'LEAPS1': 'aircraft.inputs.L0_overrides.canard_weight', + }, units='unitless', desc='mass scaler for canard structure', default_value=1.0, @@ -487,22 +527,24 @@ add_meta_data( Aircraft.Canard.TAPER_RATIO, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.TRCAN', # ['&DEFINE.WTIN.TRCAN', 'WTS.TRCAN'], - "LEAPS1": 'aircraft.inputs.L0_canard.taper_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.TRCAN', # ['&DEFINE.WTIN.TRCAN', 'WTS.TRCAN'], + 'LEAPS1': 'aircraft.inputs.L0_canard.taper_ratio', + }, units='unitless', desc='canard theoretical taper ratio', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Canard.THICKNESS_TO_CHORD, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.TCCAN', # ['&DEFINE.WTIN.TCCAN', 'EDETIN.TCCAN'], - "LEAPS1": 'aircraft.inputs.L0_canard.thickness_to_chord_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.TCCAN', # ['&DEFINE.WTIN.TCCAN', 'EDETIN.TCCAN'], + 'LEAPS1': 'aircraft.inputs.L0_canard.thickness_to_chord_ratio', + }, units='unitless', desc='canard thickness-chord ratio', default_value=0.0, @@ -513,27 +555,28 @@ # - see also: Aircraft.Canard.WETTED_AREA_SCALER Aircraft.Canard.WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['ACTWET.SWTCN', 'MISSA.SWET[-1]'], - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.canard_wetted_area', - 'aircraft.outputs.L0_aerodynamics' - '.mission_component_wetted_area_table[-1]', - 'aircraft.cached.L0_aerodynamics' - '.mission_component_wetted_area_table[-1]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['ACTWET.SWTCN', 'MISSA.SWET[-1]'], + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.canard_wetted_area', + 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[-1]', + 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[-1]', + ], + }, units='ft**2', desc='canard wetted area', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Canard.WETTED_AREA_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.SWETC', # ['&DEFINE.AERIN.SWETC', 'AWETO.SWETC', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.canard_wetted_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.SWETC', # ['&DEFINE.AERIN.SWETC', 'AWETO.SWETC', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.canard_wetted_area', + }, units='unitless', desc='canard wetted area scaler', default_value=1.0, @@ -550,11 +593,8 @@ add_meta_data( Aircraft.Controls.COCKPIT_CONTROL_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CK15', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.CK15', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='technology factor on cockpit controls mass', default_value=1.0, ) @@ -562,10 +602,7 @@ add_meta_data( Aircraft.Controls.CONTROL_MASS_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELWFC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELWFC', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='incremental flight controls mass', default_value=0, @@ -574,10 +611,7 @@ add_meta_data( Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKSAS', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.SKSAS', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of stability augmentation system', default_value=0, @@ -586,11 +620,8 @@ add_meta_data( Aircraft.Controls.STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CK19', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.CK19', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='technology factor on stability augmentation system mass', default_value=1, ) @@ -598,12 +629,10 @@ add_meta_data( Aircraft.Controls.TOTAL_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WFC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WFC', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='total mass of cockpit controls, fixed wing controls, and SAS', + default_value=0.0, ) # _____ _____ _ _ @@ -619,28 +648,32 @@ add_meta_data( Aircraft.CrewPayload.BAGGAGE_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(35,2)', '~WEIGHT.WPBAG', '~WTSTAT.WSP(35,2)', '~INERT.WPBAG'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._passenger_bag_weight', - 'aircraft.outputs.L0_weights_summary.passenger_bag_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(35,2)', '~WEIGHT.WPBAG', '~WTSTAT.WSP(35,2)', '~INERT.WPBAG'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._passenger_bag_weight', + 'aircraft.outputs.L0_weights_summary.passenger_bag_weight', + ], + }, units='lbm', - desc='mass of passenger baggage' + desc='mass of passenger baggage', + default_value=0.0, ) add_meta_data( Aircraft.CrewPayload.BAGGAGE_MASS_PER_PASSENGER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.BPP', # ['&DEFINE.WTIN.BPP', 'WPAB.BPP'], - "LEAPS1": 'aircraft.inputs.L0_crew_and_payload.baggage_weight_per_passenger' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.BPP', # ['&DEFINE.WTIN.BPP', 'WPAB.BPP'], + 'LEAPS1': 'aircraft.inputs.L0_crew_and_payload.baggage_weight_per_passenger', + }, units='lbm', desc='baggage mass per passenger', option=True, - default_value=None, + default_value=0.0, ) add_meta_data( @@ -648,26 +681,29 @@ # - see also: Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER Aircraft.CrewPayload.CARGO_CONTAINER_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(32,2)', '~WEIGHT.WCON', '~WTSTAT.WSP(32,2)', '~INERT.WCON',], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._cargo_containers_weight', - 'aircraft.outputs.L0_weights_summary.cargo_containers_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(32,2)', '~WEIGHT.WCON', '~WTSTAT.WSP(32,2)', '~INERT.WCON',], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._cargo_containers_weight', + 'aircraft.outputs.L0_weights_summary.cargo_containers_weight', + ], + }, units='lbm', desc='mass of cargo containers', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.CrewPayload.CARGO_CONTAINER_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WCON', 'MISWT.WCON', 'MISWT.OCON'], - "FLOPS": 'WTIN.WCON', - "LEAPS1": 'aircraft.inputs.L0_overrides.cargo_containers_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WCON', 'MISWT.WCON', 'MISWT.OCON'], + 'FLOPS': 'WTIN.WCON', + 'LEAPS1': 'aircraft.inputs.L0_overrides.cargo_containers_weight', + }, units='unitless', desc='Scaler for mass of cargo containers', default_value=1.0, @@ -676,27 +712,18 @@ add_meta_data( Aircraft.CrewPayload.CARGO_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WCARGO', - # ['WTS.WSP(36,2)', '~WEIGHT.WCARGO', '~WTSTAT.WSP(36,2)', '~INERT.WCARGO',], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._cargo_weight', - 'aircraft.outputs.L0_weights_summary.cargo_weight', - ] - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='total mass of cargo' + desc='total mass of as-flown cargo', ) add_meta_data( Aircraft.CrewPayload.CATERING_ITEMS_MASS_PER_PASSENGER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(12)', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CW(12)', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of catering items per passenger', - default_value=0.7, + default_value=0.0, ) # ___ _ @@ -705,29 +732,56 @@ # |___/ \___| /__/ |_| \__, | |_||_| # ====================== |___/ ====== +add_meta_data( + Aircraft.CrewPayload.Design.CARGO_MASS, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm', + desc='total mass of cargo flown on design mission', +) + +add_meta_data( + Aircraft.CrewPayload.Design.MAX_CARGO_MASS, + meta_data=_MetaData, + historical_name={ + 'GASP': 'INGASP.WCARGO', + # ['WTS.WSP(36,2)', '~WEIGHT.WCARGO', '~WTSTAT.WSP(36,2)', '~INERT.WCARGO',], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._cargo_weight', + 'aircraft.outputs.L0_weights_summary.cargo_weight', + ], + }, + units='lbm', + desc='maximum mass of cargo', + default_value=0.0, +) + add_meta_data( Aircraft.CrewPayload.Design.NUM_BUSINESS_CLASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NPB', # ['&DEFINE.WTIN.NPB', 'WTS.NPB'], - "LEAPS1": 'aircraft.inputs.L0_crew_and_payload.business_class_count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NPB', # ['&DEFINE.WTIN.NPB', 'WTS.NPB'], + 'LEAPS1': 'aircraft.inputs.L0_crew_and_payload.business_class_count', + }, units='unitless', desc='number of business class passengers that the aircraft is designed to accommodate', types=int, option=True, - default_value=0, # AviaryValues.get_val(Aircraft.CrewPayload.NUM_BUSINESS_CLASS), + default_value=0, ) add_meta_data( Aircraft.CrewPayload.Design.NUM_FIRST_CLASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NPF', # ['&DEFINE.WTIN.NPF', 'WTS.NPF'], - "LEAPS1": 'aircraft.inputs.L0_crew_and_payload.first_class_count' - }, + historical_name={ + 'GASP': 'INGASP.PCT_FC', + 'FLOPS': 'WTIN.NPF', # ['&DEFINE.WTIN.NPF', 'WTS.NPF'], + 'LEAPS1': 'aircraft.inputs.L0_crew_and_payload.first_class_count', + }, units='unitless', - desc='number of first class passengers that the aircraft is designed to accommodate', + desc='number of first class passengers that the aircraft is designed to accommodate. In GASP, the input is the percentage of total number of passengers.', types=int, option=True, default_value=0, @@ -736,10 +790,11 @@ add_meta_data( Aircraft.CrewPayload.Design.NUM_PASSENGERS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.PAX', # number of passenger seats excluding crew - "FLOPS": None, # ['CSTDAT.NSV', '~WEIGHT.NPASS', '~WTSTAT.NPASS'], - "LEAPS1": 'aircraft.outputs.L0_crew_and_payload.passenger_count' - }, + historical_name={ + 'GASP': 'INGASP.PAX', # number of passenger seats excluding crew + 'FLOPS': None, # ['CSTDAT.NSV', '~WEIGHT.NPASS', '~WTSTAT.NPASS'], + 'LEAPS1': 'aircraft.outputs.L0_crew_and_payload.passenger_count', + }, units='unitless', desc='total number of passengers that the aircraft is designed to accommodate', option=True, @@ -747,15 +802,48 @@ types=int, ) +add_meta_data( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_BUSINESS, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': 'FUSEIN.NBABR', 'LEAPS1': None}, + units='unitless', + desc='Number of business class passengers abreast', + types=int, + option=True, + default_value=5, +) + +add_meta_data( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_FIRST, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': 'FUSEIN.NFABR', 'LEAPS1': None}, + units='unitless', + desc='Number of first class passengers abreast', + types=int, + option=True, + default_value=4, +) + +add_meta_data( + Aircraft.CrewPayload.Design.NUM_SEATS_ABREAST_TOURIST, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.SAB', 'FLOPS': 'FUSEIN.NTABR', 'LEAPS1': None}, + units='unitless', + desc='Number of tourist class passengers abreast', + types=int, + option=True, + default_value=6, +) # TODO rename to economy? add_meta_data( Aircraft.CrewPayload.Design.NUM_TOURIST_CLASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NPT', # ['&DEFINE.WTIN.NPT', 'WTS.NPT'], - "LEAPS1": 'aircraft.inputs.L0_crew_and_payload.tourist_class_count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NPT', # ['&DEFINE.WTIN.NPT', 'WTS.NPT'], + 'LEAPS1': 'aircraft.inputs.L0_crew_and_payload.tourist_class_count', + }, units='unitless', desc='number of tourist class passengers that the aircraft is designed to accommodate', types=int, @@ -763,31 +851,64 @@ default_value=0, ) +add_meta_data( + Aircraft.CrewPayload.Design.SEAT_PITCH_BUSINESS, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': 'FUSEIN.BPITCH', 'LEAPS1': None}, + units='inch', + desc='pitch of the business class seats', + option=True, + default_value=0.0, +) + +add_meta_data( + Aircraft.CrewPayload.Design.SEAT_PITCH_FIRST, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': 'FUSEIN.FPITCH', 'LEAPS1': None}, + units='inch', + desc='pitch of the first class seats', + option=True, + default_value=0.0, +) + +add_meta_data( + Aircraft.CrewPayload.Design.SEAT_PITCH_TOURIST, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.PS', 'FLOPS': 'FUSEIN.TPITCH', 'LEAPS1': None}, + units='inch', + desc='pitch of the tourist class seats', + option=True, + default_value=0.0, +) + add_meta_data( # Note user override # - see also: Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER Aircraft.CrewPayload.FLIGHT_CREW_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(27, 2)', '~WEIGHT.WFLCRB', '~WTSTAT.WSP(27, 2)', '~INERT.WFLCRB'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._flight_crew_and_bag_weight', - 'aircraft.outputs.L0_weights_summary.flight_crew_and_bag_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(27, 2)', '~WEIGHT.WFLCRB', '~WTSTAT.WSP(27, 2)', '~INERT.WFLCRB'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._flight_crew_and_bag_weight', + 'aircraft.outputs.L0_weights_summary.flight_crew_and_bag_weight', + ], + }, units='lbm', desc='total mass of the flight crew and their baggage', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.CrewPayload.FLIGHT_CREW_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WFLCRB', 'MISWT.WFLCRB', 'MISWT.OFLCRB'], - "FLOPS": 'WTIN.WFLCRB', - "LEAPS1": 'aircraft.inputs.L0_overrides.flight_crew_and_bag_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WFLCRB', 'MISWT.WFLCRB', 'MISWT.OFLCRB'], + 'FLOPS': 'WTIN.WFLCRB', + 'LEAPS1': 'aircraft.inputs.L0_overrides.flight_crew_and_bag_weight', + }, units='unitless', desc='scaler for total mass of the flight crew and their baggage', default_value=1.0, @@ -796,10 +917,11 @@ add_meta_data( Aircraft.CrewPayload.MASS_PER_PASSENGER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.WPPASS', # ['&DEFINE.WTIN.WPPASS', 'WPAB.WPPASS'], - "LEAPS1": 'aircraft.inputs.L0_crew_and_payload.weight_per_passenger' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.WPPASS', # ['&DEFINE.WTIN.WPPASS', 'WPAB.WPPASS'], + 'LEAPS1': 'aircraft.inputs.L0_crew_and_payload.weight_per_passenger', + }, units='lbm', desc='mass per passenger', option=True, @@ -809,10 +931,11 @@ add_meta_data( Aircraft.CrewPayload.MISC_CARGO, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.CARGOF', # ['&DEFINE.WTIN.CARGOF', 'WTS.CARGOF'], - "LEAPS1": 'aircraft.inputs.L0_crew_and_payload.misc_cargo' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.CARGOF', # ['&DEFINE.WTIN.CARGOF', 'WTS.CARGOF'], + 'LEAPS1': 'aircraft.inputs.L0_crew_and_payload.misc_cargo', + }, units='lbm', desc='cargo (other than passenger baggage) carried in fuselage', default_value=0.0, @@ -823,26 +946,29 @@ # - see also: Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(28,2)', '~WEIGHT.WSTUAB', '~WTSTAT.WSP(28, 2)', '~INERT.WSTUAB'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._cabin_crew_and_bag_weight', - 'aircraft.outputs.L0_weights_summary.cabin_crew_and_bag_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(28,2)', '~WEIGHT.WSTUAB', '~WTSTAT.WSP(28, 2)', '~INERT.WSTUAB'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._cabin_crew_and_bag_weight', + 'aircraft.outputs.L0_weights_summary.cabin_crew_and_bag_weight', + ], + }, units='lbm', desc='total mass of the non-flight crew and their baggage', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.CrewPayload.NON_FLIGHT_CREW_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WSTUAB', 'MISWT.WSTUAB', 'MISWT.OSTUAB'], - "FLOPS": 'WTIN.WSTUAB', - "LEAPS1": 'aircraft.inputs.L0_overrides.cabin_crew_and_bag_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WSTUAB', 'MISWT.WSTUAB', 'MISWT.OSTUAB'], + 'FLOPS': 'WTIN.WSTUAB', + 'LEAPS1': 'aircraft.inputs.L0_overrides.cabin_crew_and_bag_weight', + }, units='unitless', desc='scaler for total mass of the non-flight crew and their baggage', default_value=1.0, @@ -851,10 +977,11 @@ add_meta_data( Aircraft.CrewPayload.NUM_BUSINESS_CLASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['&DEFINE.WTIN.NPB', 'WTS.NPB'], - "LEAPS1": None, # 'aircraft.inputs.L0_crew_and_payload.business_class_count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['&DEFINE.WTIN.NPB', 'WTS.NPB'], + 'LEAPS1': None, # 'aircraft.inputs.L0_crew_and_payload.business_class_count', + }, units='unitless', desc='number of business class passengers', types=int, @@ -865,12 +992,13 @@ add_meta_data( Aircraft.CrewPayload.NUM_FIRST_CLASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['&DEFINE.WTIN.NPF', 'WTS.NPF'], - "LEAPS1": None, # 'aircraft.inputs.L0_crew_and_payload.first_class_count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['&DEFINE.WTIN.NPF', 'WTS.NPF'], + 'LEAPS1': None, # 'aircraft.inputs.L0_crew_and_payload.first_class_count', + }, units='unitless', - desc='number of first class passengers', + desc='number of first class passengers.', types=int, option=True, default_value=0, @@ -879,59 +1007,66 @@ add_meta_data( Aircraft.CrewPayload.NUM_FLIGHT_ATTENDANTS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NSTU', # ['&DEFINE.WTIN.NSTU', 'WTS.NSTU'], - "LEAPS1": ['aircraft.inputs.L0_crew_and_payload.flight_attendants_count', - 'aircraft.cached.L0_crew_and_payload.flight_attendants_count', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NSTU', # ['&DEFINE.WTIN.NSTU', 'WTS.NSTU'], + 'LEAPS1': [ + 'aircraft.inputs.L0_crew_and_payload.flight_attendants_count', + 'aircraft.cached.L0_crew_and_payload.flight_attendants_count', + ], + }, units='unitless', desc='number of flight attendants', types=int, option=True, - default_value=None, + default_value=0, ) add_meta_data( Aircraft.CrewPayload.NUM_FLIGHT_CREW, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.NFLCR', 'WTS.NFLCR', '~WTSTAT.NFLCR'], - "FLOPS": 'WTIN.NFLCR', - "LEAPS1": ['aircraft.inputs.L0_crew_and_payload.flight_crew_count', - 'aircraft.cached.L0_crew_and_payload.flight_crew_count', - ] - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.NFLCR', 'WTS.NFLCR', '~WTSTAT.NFLCR'], + 'FLOPS': 'WTIN.NFLCR', + 'LEAPS1': [ + 'aircraft.inputs.L0_crew_and_payload.flight_crew_count', + 'aircraft.cached.L0_crew_and_payload.flight_crew_count', + ], + }, units='unitless', desc='number of flight crew', types=int, option=True, - default_value=None, + default_value=0, ) add_meta_data( Aircraft.CrewPayload.NUM_GALLEY_CREW, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NGALC', # ['&DEFINE.WTIN.NGALC', 'WTS.NGALC'], - "LEAPS1": ['aircraft.inputs.L0_crew_and_payload.galley_crew_count', - 'aircraft.cached.L0_crew_and_payload.galley_crew_count', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NGALC', # ['&DEFINE.WTIN.NGALC', 'WTS.NGALC'], + 'LEAPS1': [ + 'aircraft.inputs.L0_crew_and_payload.galley_crew_count', + 'aircraft.cached.L0_crew_and_payload.galley_crew_count', + ], + }, units='unitless', desc='number of galley crew', types=int, option=True, - default_value=None, + default_value=0, ) add_meta_data( Aircraft.CrewPayload.NUM_PASSENGERS, meta_data=_MetaData, - historical_name={"GASP": None, # 'INGASP.PAX' here we assume previous studies were changing Design.num_pax not as-flown - "FLOPS": None, # ['CSTDAT.NSV', '~WEIGHT.NPASS', '~WTSTAT.NPASS'], - "LEAPS1": None, # 'aircraft.outputs.L0_crew_and_payload.passenger_count' - }, + historical_name={ + 'GASP': None, # 'INGASP.PAX' here we assume previous studies were changing Design.num_pax not as-flown + 'FLOPS': None, # ['CSTDAT.NSV', '~WEIGHT.NPASS', '~WTSTAT.NPASS'], + 'LEAPS1': None, # 'aircraft.outputs.L0_crew_and_payload.passenger_count', + }, units='unitless', desc='total number of passengers', option=True, @@ -943,11 +1078,12 @@ add_meta_data( Aircraft.CrewPayload.NUM_TOURIST_CLASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['&DEFINE.WTIN.NPT', 'WTS.NPT'], - "LEAPS1": None, # 'aircraft.inputs.L0_crew_and_payload.tourist_class_count' - }, - units='unitless', + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['&DEFINE.WTIN.NPT', 'WTS.NPT'], + 'LEAPS1': None, # 'aircraft.inputs.L0_crew_and_payload.tourist_class_count', + }, + units='unitless', desc='number of tourist class passengers', types=int, option=True, @@ -957,24 +1093,24 @@ add_meta_data( Aircraft.CrewPayload.PASSENGER_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(34, 2)', '~WEIGHT.WPASS', '~WTSTAT.WSP(34, 2)', '~INERT.WPASS'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._passenger_weight', - 'aircraft.outputs.L0_weights_summary.passenger_weight' - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(34, 2)', '~WEIGHT.WPASS', '~WTSTAT.WSP(34, 2)', '~INERT.WPASS'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._passenger_weight', + 'aircraft.outputs.L0_weights_summary.passenger_weight', + ], + }, units='lbm', desc='TBD: total mass of all passengers without their baggage', + default_value=0.0, ) add_meta_data( Aircraft.CrewPayload.PASSENGER_MASS_WITH_BAGS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.UWPAX', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.UWPAX', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='total mass of one passenger and their bags', option=True, @@ -986,12 +1122,10 @@ meta_data=_MetaData, # note: this GASP variable does not include cargo, but it does include # passenger baggage - historical_name={"GASP": 'INGASP.WPL', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WPL', 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='mass of passenger payload, including passengers, passenger baggage' + desc='mass of passenger payload, including passengers, passenger baggage', + default_value=0.0, ) add_meta_data( @@ -999,38 +1133,38 @@ # - see also: Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER Aircraft.CrewPayload.PASSENGER_SERVICE_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(31, 2)', '~WEIGHT.WSRV', '~WTSTAT.WSP(31, 2)', '~INERT.WSRV'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._passenger_service_weight', - 'aircraft.outputs.L0_weights_summary.passenger_service_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(31, 2)', '~WEIGHT.WSRV', '~WTSTAT.WSP(31, 2)', '~INERT.WSRV'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._passenger_service_weight', + 'aircraft.outputs.L0_weights_summary.passenger_service_weight', + ], + }, units='lbm', desc='mass of passenger service equipment', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_PER_PASSENGER, meta_data=_MetaData, - historical_name={"GASP": "INGASP.CW(9)", - "FLOPS": None, - "LEAPS1": None - }, - default_value=2.0, - units="lbm", + historical_name={'GASP': 'INGASP.CW(9)', 'FLOPS': None, 'LEAPS1': None}, + default_value=0.0, + units='lbm', desc='mass of passenger service items mass per passenger', ) add_meta_data( Aircraft.CrewPayload.PASSENGER_SERVICE_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WSRV', 'MISWT.WSRV', 'MISWT.OSRV'], - "FLOPS": 'WTIN.WSRV', - "LEAPS1": 'aircraft.inputs.L0_overrides.passenger_service_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WSRV', 'MISWT.WSRV', 'MISWT.OSRV'], + 'FLOPS': 'WTIN.WSRV', + 'LEAPS1': 'aircraft.inputs.L0_overrides.passenger_service_weight', + }, units='unitless', desc='scaler for mass of passenger service equipment', default_value=1.0, @@ -1039,33 +1173,39 @@ add_meta_data( Aircraft.CrewPayload.TOTAL_PAYLOAD_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm', + desc='total mass of payload, including passengers, passenger baggage, and cargo', +) + +add_meta_data( + Aircraft.CrewPayload.ULD_MASS_PER_PASSENGER, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.CW(14)', 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='total mass of payload, including passengers, passenger baggage, and cargo' + desc='unit mass of ULD (unit load device) for cargo handling per passenger', + default_value=0.0, + types=float, + option=True, ) add_meta_data( Aircraft.CrewPayload.WATER_MASS_PER_OCCUPANT, meta_data=_MetaData, - historical_name={"GASP": "INGASP.CW(10)", - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CW(10)', 'FLOPS': None, 'LEAPS1': None}, default_value=1.0, - units="lbm", + units='lbm', desc='mass of water per occupant (passengers, pilots, and flight attendants)', ) add_meta_data( Aircraft.CrewPayload.WING_CARGO, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.CARGOW', # ['&DEFINE.WTIN.CARGOW', 'WTS.CARGOW'], - "LEAPS1": 'aircraft.inputs.L0_crew_and_payload.wing_cargo' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.CARGOW', # ['&DEFINE.WTIN.CARGOW', 'WTS.CARGOW'], + 'LEAPS1': 'aircraft.inputs.L0_crew_and_payload.wing_cargo', + }, units='lbm', desc='cargo carried in wing', default_value=0.0, @@ -1083,118 +1223,114 @@ add_meta_data( Aircraft.Design.BASE_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.SBASE', - # [ # inputs - # '&DEFINE.AERIN.SBASE', 'EDETIN.SBASE', - # # outputs - # 'MISSA.SBASE', 'MISSA.SBASEX', - # ], - "LEAPS1": ['aircraft.inputs.L0_aerodynamics.base_area', - 'aircraft.outputs.L0_aerodynamics.mission_base_area', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.SBASE', + # [ # inputs + # '&DEFINE.AERIN.SBASE', 'EDETIN.SBASE', + # # outputs + # 'MISSA.SBASE', 'MISSA.SBASEX', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_aerodynamics.base_area', + 'aircraft.outputs.L0_aerodynamics.mission_base_area', + ], + }, units='ft**2', desc='Aircraft base area (total exit cross-section area minus inlet ' - 'capture areas for internally mounted engines)', + 'capture areas for internally mounted engines)', default_value=0.0, ) add_meta_data( Aircraft.Design.CG_DELTA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELCG', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELCG', 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc='allowable center-of-gravity (cg) travel as a fraction of ' - 'the mean aerodynamic chord', + desc='allowable center-of-gravity (cg) travel as a fraction of the mean aerodynamic chord', + default_value=0.0, ) add_meta_data( Aircraft.Design.CHARACTERISTIC_LENGTHS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.EL', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_char_len_table', - 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.EL', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_char_len_table', + 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table', + ], + }, units='ft', - desc='Reynolds characteristic length for each component' + desc='Reynolds characteristic length for each component', ) add_meta_data( Aircraft.Design.COCKPIT_CONTROL_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKCC', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKCC', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of cockpit controls', + default_value=0.0, ) add_meta_data( Aircraft.Design.COMPUTE_HTAIL_VOLUME_COEFF, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', option=True, default_value=False, types=bool, desc='if true, use empirical tail volume coefficient equation. This is ' - 'true if VBARHX is 0 in GASP.' + 'true if VBARHX is 0 in GASP.', ) add_meta_data( Aircraft.Design.COMPUTE_VTAIL_VOLUME_COEFF, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', option=True, default_value=False, types=bool, desc='if true, use empirical tail volume coefficient equation. This is ' - 'true if VBARVX is 0 in GASP.' + 'true if VBARVX is 0 in GASP.', ) add_meta_data( Aircraft.Design.DRAG_COEFFICIENT_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELCD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELCD', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='increment to the profile drag coefficient', + default_value=0.0, +) + +add_meta_data( + Aircraft.Design.DRAG_DIVERGENCE_SHIFT, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.SCFAC', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='shift in drag divergence Mach number due to supercritical design', + default_value=0.0, ) add_meta_data( Aircraft.Design.DRAG_POLAR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='Drag polar computed during Aviary pre-mission.', + multivalue=True, + types=float, ) add_meta_data( Aircraft.Design.EMERGENCY_EQUIPMENT_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(11)', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CW(11)', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of emergency equipment', default_value=0.0, @@ -1203,13 +1339,14 @@ add_meta_data( Aircraft.Design.EMPTY_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFMSS.MISSIN.DOWE', '&FLOPS.RERUN.DOWE', 'ESB.DOWE'], - "FLOPS": 'MISSIN.DOWE', - "LEAPS1": 'aircraft.inputs.L0_mission.fixed_operating_weight_empty' - }, + historical_name={ + 'GASP': None, + # ['&DEFMSS.MISSIN.DOWE', '&FLOPS.RERUN.DOWE', 'ESB.DOWE'], + 'FLOPS': None, + 'LEAPS1': None, + }, units='lbm', - desc='fixed operating empty mass', + desc='empty mass of the aircraft', default_value=0.0, ) @@ -1218,24 +1355,26 @@ # - see also: Aircraft.Design.EMPTY_MASS_MARGIN_SCALER Aircraft.Design.EMPTY_MASS_MARGIN, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'DARM.WMARG', - "LEAPS1": '(WeightABC)self._weight_empty_margin' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'DARM.WMARG', + 'LEAPS1': '(WeightABC)self._weight_empty_margin', + }, units='lbm', desc='empty mass margin', - default_value=None, + default_value=0.0, ) add_meta_data( # Note users must enable this feature, or the associated calculation is - # discarded + # discarded. Default to 0.0 Aircraft.Design.EMPTY_MASS_MARGIN_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.EWMARG', # ['&DEFINE.WTIN.EWMARG', 'DARM.EWMARG'], - "LEAPS1": 'aircraft.inputs.L0_overrides.weight_empty_margin' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.EWMARG', # ['&DEFINE.WTIN.EWMARG', 'DARM.EWMARG'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.weight_empty_margin', + }, units='unitless', desc='empty mass margin scaler', default_value=0.0, @@ -1243,136 +1382,157 @@ add_meta_data( Aircraft.Design.EXTERNAL_SUBSYSTEMS_MASS, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None, - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, + 'LEAPS1': None, + }, meta_data=_MetaData, units='lbm', desc='total mass of all user-defined external subsystems', + default_value=0.0, ) add_meta_data( Aircraft.Design.FINENESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.FR', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table', - 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.FR', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table', + 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table', + ], + }, units='unitless', - desc='table of component fineness ratios' + desc='table of component fineness ratios', + default_value=0.0, ) add_meta_data( Aircraft.Design.FIXED_EQUIPMENT_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WFE', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WFE', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='total mass of fixed equipment: APU, Instruments, Hydraulics, Electrical, ' - 'Avionics, AC, Anti-Icing, Auxilary Equipment, and Furnishings', + 'Avionics, AC, Anti-Icing, Auxiliary Equipment, and Furnishings', + default_value=0.0, ) add_meta_data( Aircraft.Design.FIXED_USEFUL_LOAD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WFUL', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WFUL', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='total mass of fixed useful load: crew, service items, trapped oil, etc', + default_value=0.0, ) add_meta_data( - Aircraft.Design.IJEFF, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.IJEFF', "FLOPS": None, "LEAPS1": None}, - desc="A flag used by Jeff V. Bowles to debug GASP code during his 53 years supporting the development of GASP. " + Aircraft.Design.IJEFF, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.IJEFF', 'FLOPS': None, 'LEAPS1': None}, + desc='A flag used by Jeff V. Bowles to debug GASP code during his 53 years supporting the development of GASP. ' "This flag is planted here to thank him for his hard work and dedication, Aviary wouldn't be what it is today " - "without his help.",) + 'without his help.', +) +# TODO expected types and default value? add_meta_data( Aircraft.Design.LAMINAR_FLOW_LOWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.TRL', - "LEAPS1": 'aircraft.outputs.L0_aerodynamics.mission_component_percent_laminar_flow_lower_surface_table' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.TRL', + 'LEAPS1': 'aircraft.outputs.L0_aerodynamics.mission_component_percent_laminar_flow_lower_surface_table', + }, units='unitless', desc='table of percent laminar flow over lower component surfaces', - default_value=None, ) +# TODO expected types and default values? add_meta_data( Aircraft.Design.LAMINAR_FLOW_UPPER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.TRU', - "LEAPS1": 'aircraft.outputs.L0_aerodynamics.mission_component_percent_laminar_flow_upper_surface_table' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.TRU', + 'LEAPS1': 'aircraft.outputs.L0_aerodynamics.mission_component_percent_laminar_flow_upper_surface_table', + }, units='unitless', desc='table of percent laminar flow over upper component surfaces', - default_value=None, ) add_meta_data( # Note user override (no scaling) Aircraft.Design.LANDING_TO_TAKEOFF_MASS_RATIO, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.WRATIO', # ['&DEFINE.AERIN.WRATIO', 'ESB.WRATIO'], - "LEAPS1": 'aircraft.inputs.L0_takeoff_and_landing.landing_to_takeoff_weight_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.WRATIO', # ['&DEFINE.AERIN.WRATIO', 'ESB.WRATIO'], + 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.landing_to_takeoff_weight_ratio', + }, units='unitless', desc='ratio of maximum landing mass to maximum takeoff mass', - default_value=0.9, + default_value=0.0, ) add_meta_data( Aircraft.Design.LIFT_CURVE_SLOPE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CLALPH', - "FLOPS": None, - "LEAPS1": None - }, - units="1/rad", - desc='lift curve slope at cruise mach number', + historical_name={'GASP': 'INGASP.CLALPH', 'FLOPS': None, 'LEAPS1': None}, + units='1/rad', + desc='lift curve slope at cruise Mach number', + default_value=0.0, ) add_meta_data( Aircraft.Design.LIFT_DEPENDENT_DRAG_COEFF_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'MISSIN.FCDI', # '~DRGFCT.FCDI', - "LEAPS1": 'aircraft.outputs.L0_aerodynamics.induced_drag_coeff_fact' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'MISSIN.FCDI', # '~DRGFCT.FCDI', + 'LEAPS1': 'aircraft.outputs.L0_aerodynamics.induced_drag_coeff_fact', + }, units='unitless', default_value=1.0, - desc='Scaling factor for lift-dependent drag coefficient' + desc='Scaling factor for lift-dependent drag coefficient', +) + +add_meta_data( + Aircraft.Design.LIFT_DEPENDENT_DRAG_POLAR, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='Lift dependent drag polar computed during Aviary pre-mission.', + multivalue=True, + types=float, +) + +add_meta_data( + Aircraft.Design.LIFT_INDEPENDENT_DRAG_POLAR, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='Lift independent drag polar computed during Aviary pre-mission.', + multivalue=True, + types=float, ) add_meta_data( Aircraft.Design.LIFT_POLAR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='Lift polar computed during Aviary pre-mission.', + multivalue=True, + types=float, ) add_meta_data( Aircraft.Design.MAX_FUSELAGE_PITCH_ANGLE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.THEMAX', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.THEMAX', 'FLOPS': None, 'LEAPS1': None}, units='deg', desc='maximum fuselage pitch allowed', default_value=15, @@ -1381,101 +1541,71 @@ add_meta_data( Aircraft.Design.MAX_STRUCTURAL_SPEED, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.VMLFSL', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.VMLFSL', 'FLOPS': None, 'LEAPS1': None}, units='mi/h', desc='maximum structural design flight speed in miles per hour', default_value=0, ) -add_meta_data( - Aircraft.Design.OPERATING_MASS, - meta_data=_MetaData, - # TODO: check with Aviary and GASPy engineers to ensure these are indeed - # defined the same way - historical_name={"GASP": 'INGASP.OWE', - # ['WTS.WSP(33, 2)', '~WEIGHT.WOWE', '~WTSTAT.WSP(33, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._operating_weight_empty', - 'aircraft.outputs.L0_weights_summary.operating_weight_empty', - ] - }, - units='lbm', - desc='operating mass empty of the aircraft' -) - add_meta_data( Aircraft.Design.PART25_STRUCTURAL_CATEGORY, meta_data=_MetaData, - historical_name={"GASP": "INGASP.CATD", - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CATD', 'FLOPS': None, 'LEAPS1': None}, option=True, default_value=3, types=int, - units="unitless", + units='unitless', desc='part 25 structural category', ) add_meta_data( Aircraft.Design.RESERVE_FUEL_ADDITIONAL, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FRESF', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.FRESF', 'FLOPS': None, 'LEAPS1': None}, option=True, - units="lbm", + units='lbm', desc='required fuel reserves: directly in lbm', default_value=0, ) add_meta_data( - Aircraft.Design.RESERVE_FUEL_FRACTION, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, - option=True, units="unitless", + Aircraft.Design.RESERVE_FUEL_FRACTION, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + option=True, + units='unitless', desc='required fuel reserves: given as a proportion of mission fuel. This value must be nonnegative. ' 'Mission fuel only includes normal phases and excludes reserve phases. ' 'If it is 0.5, the reserve fuel is half of the mission fuel (one third of the total fuel). Note ' 'it can be greater than 1. If it is 2, there would be twice as much reserve fuel as mission fuel ' '(the total fuel carried would be 1/3 for the mission and 2/3 for the reserve)', - default_value=0,) + default_value=0, +) add_meta_data( Aircraft.Design.SMOOTH_MASS_DISCONTINUITIES, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, option=True, default_value=False, types=bool, - units="unitless", + units='unitless', desc='eliminates discontinuities in GASP-based mass estimation code if true', ) add_meta_data( Aircraft.Design.STATIC_MARGIN, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.STATIC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.STATIC', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='aircraft static margin as a fraction of mean aerodynamic chord', + default_value=0.0, ) add_meta_data( Aircraft.Design.STRUCTURAL_MASS_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELWST', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELWST', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='structural mass increment that is added (or removed) after the structural mass is calculated', default_value=0, @@ -1484,147 +1614,162 @@ add_meta_data( Aircraft.Design.STRUCTURE_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(9, 2)', '~WEIGHT.WSTRCT', '~WTSTAT.WSP(9, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._total_structural_weight', - 'aircraft.outputs.L0_weights_summary.total_structural_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(9, 2)', '~WEIGHT.WSTRCT', '~WTSTAT.WSP(9, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._total_structural_weight', + 'aircraft.outputs.L0_weights_summary.total_structural_weight', + ], + }, units='lbm', - desc='Total structural group mass' + desc='Total structural group mass', + default_value=0.0, ) add_meta_data( Aircraft.Design.SUBSONIC_DRAG_COEFF_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'MISSIN.FCDSUB', # '~DRGFCT.FCDSUB', - "LEAPS1": 'aircraft.outputs.L0_aerodynamics.sub_drag_coeff_fact' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'MISSIN.FCDSUB', # '~DRGFCT.FCDSUB', + 'LEAPS1': 'aircraft.outputs.L0_aerodynamics.sub_drag_coeff_fact', + }, units='unitless', default_value=1.0, - desc='Scaling factor for subsonic drag' -) - -add_meta_data( - Aircraft.Design.SUPERCRITICAL_DIVERGENCE_SHIFT, - meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SCFAC', - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - desc='shift in drag divergence Mach number due to ' - 'supercritical design', + desc='Scaling factor for subsonic drag', ) add_meta_data( Aircraft.Design.SUPERSONIC_DRAG_COEFF_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'MISSIN.FCDSUP', # '~DRGFCT.FCDSUP', - "LEAPS1": 'aircraft.outputs.L0_aerodynamics.sup_drag_coeff_fact' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'MISSIN.FCDSUP', # '~DRGFCT.FCDSUP', + 'LEAPS1': 'aircraft.outputs.L0_aerodynamics.sup_drag_coeff_fact', + }, units='unitless', default_value=1.0, - desc='Scaling factor for supersonic drag' + desc='Scaling factor for supersonic drag', ) add_meta_data( Aircraft.Design.SYSTEMS_EQUIP_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(25, 2)', '~WEIGHT.WSYS', '~WTSTAT.WSP(25, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._equipment_group_weight', - 'aircraft.outputs.L0_weights_summary.equipment_group_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(25, 2)', '~WEIGHT.WSYS', '~WTSTAT.WSP(25, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._equipment_group_weight', + 'aircraft.outputs.L0_weights_summary.equipment_group_weight', + ], + }, units='lbm', - desc='Total systems & equipment group mass' + desc='Total systems & equipment group mass', + default_value=0.0, ) +# TODO intermediate calculated values with no uses by other systems may not belong in the +# variable hierarchy add_meta_data( # Note in FLOPS/LEAPS1, this is the same variable as # Aircraft.Design.SYSTEMS_EQUIP_MASS, because FLOPS/LEAPS1 overwrite the # value during calculations; in Aviary, these must be separate variables Aircraft.Design.SYSTEMS_EQUIP_MASS_BASE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='Total systems & equipment group mass without additional 1% of ' - 'empty mass' + desc='Total systems & equipment group mass without additional 1% of empty mass', + default_value=0.0, ) add_meta_data( Aircraft.Design.THRUST_TO_WEIGHT_RATIO, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'CONFIN.TWR', - "LEAPS1": 'ipropulsion.req_thrust_weight_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, + 'LEAPS1': None, + # NOTE TWR != THRUST_TO_WEIGHT_RATIO because Aviary\'s value is the actual T/W, while TWR is + # the desired T/W ratio + # 'FLOPS': 'CONFIN.TWR', + # 'LEAPS1': 'ipropulsion.req_thrust_weight_ratio', + }, units='unitless', - desc='required thrust-to-weight ratio of aircraft' + default_value=0.0, + types=float, + desc='ratio of total sea-level-static thrust to aircraft takeoff gross weight', ) add_meta_data( Aircraft.Design.TOTAL_WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WEIGHT.TWET', - "LEAPS1": '~WeightABC._update_cycle.total_wetted_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WEIGHT.TWET', + 'LEAPS1': '~WeightABC._update_cycle.total_wetted_area', + }, units='ft**2', - desc='total aircraft wetted area' + desc='total aircraft wetted area', + default_value=0.0, ) add_meta_data( # NOTE: user override (no scaling) Aircraft.Design.TOUCHDOWN_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.WLDG', - # [ # inputs - # '&DEFINE.WTIN.WLDG', 'WTS.WLDG', - # # outputs - # 'CMODLW.WLDGO', - # ], - "LEAPS1": ['aircraft.inputs.L0_landing_gear.design_landing_weight', - 'aircraft.outputs.L0_landing_gear.design_landing_weight', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.WLDG', + # [ # inputs + # '&DEFINE.WTIN.WLDG', 'WTS.WLDG', + # # outputs + # 'CMODLW.WLDGO', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_landing_gear.design_landing_weight', + 'aircraft.outputs.L0_landing_gear.design_landing_weight', + ], + }, units='lbm', desc='design landing mass', - default_value=None, + default_value=0.0, +) + +add_meta_data( + Aircraft.Design.TYPE, + meta_data=_MetaData, + historical_name={'GASP': ['INGASP.IHWB'], 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + types=AircraftTypes, + option=True, + default_value=AircraftTypes.TRANSPORT, + desc='aircraft type: BWB for blended wing body, transport otherwise', ) add_meta_data( Aircraft.Design.ULF_CALCULATED_FROM_MANEUVER, meta_data=_MetaData, - historical_name={"GASP": 'CATD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'CATD', 'FLOPS': None, 'LEAPS1': None}, option=True, default_value=False, types=bool, - units="unitless", + units='unitless', desc='if true, ULF (ultimate load factor) is forced to be calculated from ' - 'the maneuver load factor, even if the gust load factor is larger. ' - 'This was set to true with a negative CATD in GASP.' + 'the maneuver load factor, even if the gust load factor is larger. ' + 'This was set to true with a negative CATD in GASP.', ) add_meta_data( Aircraft.Design.USE_ALT_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.IALTWT', - "LEAPS1": 'aircraft.inputs.L0_weights.use_alt_weights' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.IALTWT', + 'LEAPS1': 'aircraft.inputs.L0_weights.use_alt_weights', + }, units='unitless', desc='control whether the alternate mass equations are to be used or not', option=True, @@ -1635,41 +1780,43 @@ add_meta_data( Aircraft.Design.WETTED_AREAS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.SWET', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table', - 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.SWET', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table', + 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table', + ], + }, units='ft**2', - desc='table of component wetted areas' + desc='table of component wetted areas', ) add_meta_data( - Aircraft.Design.ZERO_FUEL_MASS, + Aircraft.Design.WING_LOADING, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(37,2)', '~WEIGHT.WZF', '~WTSTAT.WSP(37,2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._zero_fuel_weight', - 'aircraft.outputs.L0_weights.zero_fuel_weight', - 'aircraft.outputs.L0_weights_summary.zero_fuel_weight', - ] - }, - units='lbm', - desc='zero fuel mass' + historical_name={ + 'GASP': ['INGASP.WGS', 'INGASP.WOS'], + 'FLOPS': None, # 'MISSA.SWET', + 'LEAPS1': None, + }, + default_value=0, + types=float, + units='lbf/ft**2', + desc='ratio of aircraft gross takeoff weight to projected wing area', ) add_meta_data( Aircraft.Design.ZERO_LIFT_DRAG_COEFF_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'MISSIN.FCDO', # '~DRGFCT.FCDO', - "LEAPS1": 'aircraft.outputs.L0_aerodynamics.geom_drag_coeff_fact' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'MISSIN.FCDO', # '~DRGFCT.FCDO', + 'LEAPS1': 'aircraft.outputs.L0_aerodynamics.geom_drag_coeff_fact', + }, units='unitless', default_value=1.0, - desc='Scaling factor for zero-lift drag coefficient' + desc='Scaling factor for zero-lift drag coefficient', ) # @@ -1684,13 +1831,10 @@ add_meta_data( Aircraft.Electrical.HAS_HYBRID_SYSTEM, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', option=True, - default_value=True, + default_value=False, types=bool, desc='if true there is an augmented electrical system', ) @@ -1698,12 +1842,10 @@ add_meta_data( Aircraft.Electrical.HYBRID_CABLE_LENGTH, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.LCABLE', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.LCABLE', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='length of cable for hybrid electric augmented system', + default_value=0.0, ) add_meta_data( @@ -1711,31 +1853,43 @@ # - see also: Aircraft.Electrical.MASS_SCALER Aircraft.Electrical.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(20, 2)', '~WEIGHT.WELEC', '~WTSTAT.WSP(20, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._electrical_group_weight', - 'aircraft.outputs.L0_weights_summary.electrical_group_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(20, 2)', '~WEIGHT.WELEC', '~WTSTAT.WSP(20, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._electrical_group_weight', + 'aircraft.outputs.L0_weights_summary.electrical_group_weight', + ], + }, units='lbm', desc='mass of the electrical system', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Electrical.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WELEC', 'MISWT.WELEC', 'MISWT.OELEC'], - "FLOPS": 'WTIN.WELEC', - "LEAPS1": 'aircraft.inputs.L0_overrides.electrical_group_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WELEC', 'MISWT.WELEC', 'MISWT.OELEC'], + 'FLOPS': 'WTIN.WELEC', + 'LEAPS1': 'aircraft.inputs.L0_overrides.electrical_group_weight', + }, units='unitless', desc='mass scaler for the electrical system', default_value=1.0, ) +add_meta_data( + Aircraft.Electrical.SYSTEM_MASS_PER_PASSENGER, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.CW(15)', 'FLOPS': None, 'LEAPS1': None}, + units='lbm', + desc='electrical system weight per passenger. In GASP, default 16.0', + default_value=0.0, +) + # ______ _ # | ____| (_) # | |__ _ __ __ _ _ _ __ ___ @@ -1751,463 +1905,445 @@ add_meta_data( Aircraft.Engine.ADDITIONAL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='additional propulsion system mass added to engine control and starter mass, or ' - 'engine installation mass', - default_value=0.0 + 'engine installation mass', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.ADDITIONAL_MASS_FRACTION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKPEI', - "FLOPS": 'WTIN.WPMISC', # ['&DEFINE.WTIN.WPMISC', 'FAWT.WPMISC'], - "LEAPS1": 'aircraft.inputs.L0_propulsion.misc_weight' - }, + historical_name={ + 'GASP': 'INGASP.SKPEI', + 'FLOPS': 'WTIN.WPMISC', # ['&DEFINE.WTIN.WPMISC', 'FAWT.WPMISC'], + 'LEAPS1': 'aircraft.inputs.L0_propulsion.misc_weight', + }, units='unitless', + option=True, desc='fraction of (scaled) engine mass used to calculate additional propulsion ' - 'system mass added to engine control and starter mass, or used to ' - 'calculate engine installation mass', + 'system mass added to engine control and starter mass, or used to calculate engine ' + 'installation mass', + types=(float, int, np.ndarray), + multivalue=True, default_value=0.0, ) -# NOTE if FT < 0, this bool is true, if >= 0, this is false and the value of FT is used -# as the installation loss factor -add_meta_data( - Aircraft.Engine.COMPUTE_PROPELLER_INSTALLATION_LOSS, - meta_data=_MetaData, - historical_name={"GASP": 'INPROP.FT', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", - option=True, - default_value=True, - types=bool, - desc='if true, compute installation loss factor based on blockage factor', -) - add_meta_data( Aircraft.Engine.CONSTANT_FUEL_CONSUMPTION, meta_data=_MetaData, historical_name={ - "GASP": None, - "FLOPS": 'MISSIN.FLEAK', - "LEAPS1": [ - 'iengine.fuel_leak', - 'aircraft.inputs.L0_engine.fuel_leak']}, + 'GASP': None, + 'FLOPS': 'MISSIN.FLEAK', + 'LEAPS1': ['iengine.fuel_leak', 'aircraft.inputs.L0_engine.fuel_leak'], + }, option=True, units='lbm/h', desc='Additional constant fuel flow. This value is not scaled with the engine', - default_value=0.0) + default_value=0.0, + multivalue=True, +) add_meta_data( Aircraft.Engine.CONTROLS_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WEIGHT.WEC', - "LEAPS1": '(WeightABC)self._engine_ctrl_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WEIGHT.WEC', + 'LEAPS1': '(WeightABC)self._engine_ctrl_weight', + }, units='lbm', desc='estimated mass of the engine controls', - default_value=0.0 + default_value=0.0, + multivalue=True, ) # TODO there should be a GASP name that pairs here add_meta_data( Aircraft.Engine.DATA_FILE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": "ENGDIN.EIFILE", - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': 'ENGDIN.EIFILE', 'LEAPS1': None}, units='unitless', - types=(str, Path), + types=(Path, str), default_value=None, option=True, - desc='filepath to data file containing engine performance tables' + desc='filepath to data file containing engine performance tables', + multivalue=True, ) add_meta_data( Aircraft.Engine.FIXED_RPM, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='rpm', default_value=1.0, desc='RPM the engine is set to be running at. Overrides RPM provided by ' 'engine model or chosen by optimizer. Typically used when pairing a motor or ' 'turboshaft using a fixed operating RPM with a propeller.', + multivalue=True, ) add_meta_data( Aircraft.Engine.FLIGHT_IDLE_MAX_FRACTION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.FIDMAX', - "LEAPS1": 'aircraft.L0_fuel_flow.idle_max_fract' - }, - units="unitless", + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.FIDMAX', + 'LEAPS1': 'aircraft.L0_fuel_flow.idle_max_fract', + }, + units='unitless', option=True, default_value=1.0, desc='If Aircraft.Engine.GENERATE_FLIGHT_IDLE is True, bounds engine ' - 'performance outputs (other than thrust) at flight idle to be below a ' - 'decimal fraction of the max value of that output produced by the engine ' - 'at each flight condition.' + 'performance outputs (other than thrust) at flight idle to be below a ' + 'decimal fraction of the max value of that output produced by the engine ' + 'at each flight condition.', + multivalue=True, ) add_meta_data( Aircraft.Engine.FLIGHT_IDLE_MIN_FRACTION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.FIDMIN', - "LEAPS1": 'aircraft.L0_fuel_flow.idle_min_fract' - }, - units="unitless", + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.FIDMIN', + 'LEAPS1': 'aircraft.L0_fuel_flow.idle_min_fract', + }, + units='unitless', option=True, default_value=0.08, desc='If Aircraft.Engine.GENERATE_FLIGHT_IDLE is True, bounds engine ' - 'performance outputs (other than thrust) at flight idle to be above a ' - 'decimal fraction of the max value of that output produced by the engine ' - 'at each flight condition.' + 'performance outputs (other than thrust) at flight idle to be above a ' + 'decimal fraction of the max value of that output produced by the engine ' + 'at each flight condition.', + multivalue=True, ) add_meta_data( Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', option=True, default_value=0.0, desc='If Aircraft.Engine.GENERATE_FLIGHT_IDLE is True, defines idle thrust ' - 'condition as a decimal fraction of max thrust produced by the engine at each ' - 'flight condition.' + 'condition as a decimal fraction of max thrust produced by the engine at each ' + 'flight condition.', + multivalue=True, ) add_meta_data( Aircraft.Engine.FUEL_FLOW_SCALER_CONSTANT_TERM, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.DFFAC', - "LEAPS1": 'ifuel_flow.scaling_const_term' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.DFFAC', + 'LEAPS1': 'ifuel_flow.scaling_const_term', + }, units='unitless', option=True, desc='Constant term in fuel flow scaling equation', - default_value=0.0 + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.FUEL_FLOW_SCALER_LINEAR_TERM, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.FFFAC', - "LEAPS1": 'ifuel_flow.scaling_linear_term' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.FFFAC', + 'LEAPS1': 'ifuel_flow.scaling_linear_term', + }, units='unitless', desc='Linear term in fuel flow scaling equation', default_value=0.0, - option=True + option=True, + multivalue=True, ) add_meta_data( Aircraft.Engine.GENERATE_FLIGHT_IDLE, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.IDLE', - "LEAPS1": 'engine_model.imodel_info.flight_idle_index' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.IDLE', + 'LEAPS1': 'engine_model.imodel_info.flight_idle_index', + }, meta_data=_MetaData, - units="unitless", + units='unitless', option=True, default_value=False, types=bool, - desc='If True, generate flight idle data by extrapolating from engine deck. Flight ' - 'idle is defined as engine performance when thrust is reduced to the level ' - 'defined by Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION. Engine outputs are ' - 'extrapolated to this thrust level, bounded by ' - 'Aircraft.Engine.FLIGHT_IDLE_MIN_FRACT and Aircraft.Engine.FLIGHT_IDLE_MIN_FRACT' + desc='If True, generate flight idle data by extrapolating from engine data. Flight ' + 'idle is defined as engine performance when thrust is reduced to the level ' + 'defined by Aircraft.Engine.FLIGHT_IDLE_THRUST_FRACTION. Other engine outputs are ' + 'extrapolated to this thrust level, bounded by ' + 'Aircraft.Engine.FLIGHT_IDLE_MIN_FRACT and Aircraft.Engine.FLIGHT_IDLE_MAX_FRACT', + multivalue=True, ) add_meta_data( Aircraft.Engine.GEOPOTENTIAL_ALT, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.IGEO', - "LEAPS1": 'imodel_info.geopotential_alt' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.IGEO', + 'LEAPS1': 'imodel_info.geopotential_alt', + }, units='unitless', option=True, desc='If True, engine deck altitudes are geopotential and will be converted to ' - 'geometric altitudes. If False, engine deck altitudes are geometric.', + 'geometric altitudes. If False, engine deck altitudes are geometric.', types=bool, - default_value=False + default_value=False, + multivalue=True, ) -# TODO dependency on NTYE? Does this var need preprocessing? Can this mention be removed? -add_meta_data( - Aircraft.Engine.HAS_PROPELLERS, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, - option=True, units="unitless", default_value=False, types=bool, - desc='if True, the aircraft has propellers, otherwise aircraft is assumed to have no ' - 'propellers. In GASP this depended on NTYE',) - +# Global hybrid throttle is also False by default to account for parallel-hybrid engines +# that can't operate at every power level at every condition due to other constraints add_meta_data( - Aircraft.Engine.IGNORE_NEGATIVE_THRUST, + Aircraft.Engine.GLOBAL_HYBRID_THROTTLE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.NONEG', - "LEAPS1": 'imodel_info.ignore_negative_thrust' - }, - option=True, - units="unitless", - default_value=False, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='Flag for engine decks if the range of provided hybrid throttles is consistent ' + 'across all flight conditions (e.g. the maximum hybrid throttle seen in the entire ' + 'deck is 1.0, but a given flight condition only goes to 0.9 -> GLOBAL_HYBRID_THROTTLE ' + '= TRUE means the engine can be extrapolated out to 1.0 at that point. If ' + "GLOBAL_HYBRID_THROTTLE is False, then each flight condition's hybrid throttle range is " + 'individually normalized from 0 to 1 independent of other points on the deck).', + default_value=False, + types=bool, + option=True, + multivalue=True, +) + +# TODO Disabling global throttle ranges is preferred (therefore default) to prevent +# unintended extrapolation, but breaks missions using GASP-based engines that have uneven +# throttle ranges (need t4 constraint on mission to truly fix). +add_meta_data( + Aircraft.Engine.GLOBAL_THROTTLE, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='Flag for engine decks if the range of provided throttles is consistent ' + 'across all flight conditions (e.g. the maximum throttle seen in the entire ' + 'deck is 1.0, but a given flight condition only goes to 0.9 -> GLOBAL_THROTTLE ' + '= TRUE means the engine can be extrapolated out to 1.0 at that point. If ' + "GLOBAL_THROTTLE is False, then each flight condition's throttle range is " + 'individually normalized from 0 to 1 independent of other points on the deck).', + default_value=False, + types=bool, + option=True, + multivalue=True, +) + +# TODO dependency on NTYE? Does this var need preprocessing? Can this mention be removed? +add_meta_data( + Aircraft.Engine.HAS_PROPELLERS, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + option=True, + units='unitless', + default_value=False, + types=bool, + desc='if True, the aircraft has propellers, otherwise aircraft is assumed to have no ' + 'propellers. In GASP this depended on NTYE', + multivalue=True, +) + +add_meta_data( + Aircraft.Engine.IGNORE_NEGATIVE_THRUST, + meta_data=_MetaData, + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.NONEG', + 'LEAPS1': 'imodel_info.ignore_negative_thrust', + }, + option=True, + units='unitless', + default_value=False, types=bool, desc='If False, all input or generated points are used, otherwise points in the ' - 'engine deck with negative net thrust are ignored.' + 'engine deck with negative net thrust are ignored.', + multivalue=True, ) add_meta_data( - Aircraft.Engine.INTERPOLATION_METHOD, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, - units="unitless", option=True, default_value='slinear', types=str, + Aircraft.Engine.INTERPOLATION_METHOD, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + option=True, + default_value='slinear', + types=str, desc="method used for interpolation on an engine deck's data file, allowable values are " - 'table methods from openmdao.components.interp_util.interp',) + 'table methods from openmdao.components.interp_util.interp', + multivalue=True, +) + +add_meta_data( + Aircraft.Engine.INTERPOLATION_SORT, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + option=True, + default_value='mach', + types=str, + desc='Specify the first interpolation variable in the semi-structured metamodel. ' + 'Choose from mach or altitude. Mach is usually the first column in the deck, but ' + 'altitude is more robust for semi-structured data.', + multivalue=True, +) add_meta_data( Aircraft.Engine.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['WTS.WSP(10, 2)', '~WTSTAT.WSP(10, 2)'], - "LEAPS1": 'aircraft.outputs.L0_weights_summary.Engine.WEIGHT' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['WTS.WSP(10, 2)', '~WTSTAT.WSP(10, 2)'], + 'LEAPS1': 'aircraft.outputs.L0_weights_summary.Engine.WEIGHT', + }, units='lbm', - desc='scaled mass of a single engine or bare engine if inlet and nozzle mass are ' - 'supplied', - default_value=0.0 + desc='scaled mass of a single engine or bare engine if inlet and nozzle mass are supplied', + default_value=0.0, + multivalue=True, ) +# TODO FLOPS based equation scale factor needs to be separated out into a different +# variable, which will also eliminate logic branch in engine.py where two +# different equations are used depending on the value of MASS_SCALER add_meta_data( Aircraft.Engine.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CK5', - "FLOPS": 'WTIN.EEXP', # '~WEIGHT.EEXP', - "LEAPS1": 'aircraft.inputs.L0_propulsion.engine_weight_scale' - }, + historical_name={ + 'GASP': 'INGASP.CK5', + 'FLOPS': 'WTIN.EEXP', # '~WEIGHT.EEXP', + 'LEAPS1': 'aircraft.inputs.L0_propulsion.engine_weight_scale', + }, units='unitless', desc='scaler for engine mass', - default_value=0.0, + default_value=1.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.MASS_SPECIFIC, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SWSLS', - "FLOPS": None, - "LEAPS1": None - }, - units="lbm/lbf", + historical_name={'GASP': 'INGASP.SWSLS', 'FLOPS': None, 'LEAPS1': None}, + units='lbm/lbf', desc='specific mass of one engine (engine weight/SLS thrust)', default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.NUM_ENGINES, meta_data=_MetaData, - historical_name={"GASP": "INGASP.ENP", - "FLOPS": None, # ['~ANALYS.NENG', 'LANDG.XENG', ], - "LEAPS1": 'aircraft.outputs.L0_propulsion.total_engine_count' - }, + historical_name={ + 'GASP': 'INGASP.ENP', + 'FLOPS': None, # ['~ANALYS.NENG', 'LANDG.XENG', ], + 'LEAPS1': 'aircraft.outputs.L0_propulsion.total_engine_count', + }, units='unitless', - desc='total number of engines per model on the aircraft ' - '(fuselage, wing, or otherwise)', + desc='total number of engines per model on the aircraft (fuselage, wing, or otherwise)', types=int, + multivalue=True, option=True, - default_value=2 + default_value=2, ) add_meta_data( Aircraft.Engine.NUM_FUSELAGE_ENGINES, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NEF', # ['&DEFINE.WTIN.NEF', 'EDETIN.NEF'], - "LEAPS1": 'aircraft.inputs.L0_fuselage.engines_count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NEF', # ['&DEFINE.WTIN.NEF', 'EDETIN.NEF'], + 'LEAPS1': 'aircraft.inputs.L0_fuselage.engines_count', + }, units='unitless', desc='number of fuselage mounted engines per model', option=True, types=int, - default_value=0 -) - -add_meta_data( - Aircraft.Engine.NUM_PROPELLER_BLADES, - meta_data=_MetaData, - historical_name={"GASP": 'INPROP.BL', - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - desc='number of blades per propeller', - option=True, - types=int, - default_value=0 + multivalue=True, + default_value=0, ) add_meta_data( Aircraft.Engine.NUM_WING_ENGINES, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.NEW', 'EDETIN.NEW', '~WWGHT.NEW'], - "FLOPS": 'WTIN.NEW', - "LEAPS1": 'aircraft.inputs.L0_wing.engines_count' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.NEW', 'EDETIN.NEW', '~WWGHT.NEW'], + 'FLOPS': 'WTIN.NEW', + 'LEAPS1': 'aircraft.inputs.L0_wing.engines_count', + }, units='unitless', desc='number of wing mounted engines per model', option=True, types=int, - default_value=0 + multivalue=True, + default_value=0, ) add_meta_data( Aircraft.Engine.POD_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['~WEIGHT.WPOD', '~WWGHT.WPOD'], - "LEAPS1": '(WeightABC)self._engine_pod_weight_list' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['~WEIGHT.WPOD', '~WWGHT.WPOD'], + 'LEAPS1': '(WeightABC)self._engine_pod_weight_list', + }, units='lbm', desc='engine pod mass including nacelles', - default_value=0.0 + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.POD_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CK14', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.CK14', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='technology factor on mass of engine pods', default_value=1.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.POSITION_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKEPOS', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKEPOS', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='engine position factor', default_value=0, -) - -add_meta_data( - Aircraft.Engine.PROPELLER_ACTIVITY_FACTOR, - meta_data=_MetaData, - historical_name={"GASP": 'INPROP.AF', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", - desc='propeller actitivty factor per Blade (Range: 80 to 200)', - default_value=0.0, -) - -add_meta_data( - Aircraft.Engine.PROPELLER_DATA_FILE, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - types=(str, Path), - default_value=None, - option=True, - desc='filepath to data file containing propeller data map', -) - -add_meta_data( - Aircraft.Engine.PROPELLER_DIAMETER, - meta_data=_MetaData, - historical_name={"GASP": 'INPROP.DPROP', - "FLOPS": None, - "LEAPS1": None - }, - units='ft', - desc='propeller diameter', - default_value=0.0, -) - -add_meta_data( - Aircraft.Engine.PROPELLER_INTEGRATED_LIFT_COEFFICIENT, - meta_data=_MetaData, - historical_name={"GASP": 'INPROP.CLI', - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - desc='propeller blade integrated design lift coefficient (Range: 0.3 to 0.8)', - default_value=0.5, -) - -add_meta_data( - Aircraft.Engine.PROPELLER_TIP_MACH_MAX, - meta_data=_MetaData, - historical_name={ - "GASP": None, # TODO this needs verification - "FLOPS": None, - "LEAPS1": None, - }, - units='unitless', - desc='maximum allowable Mach number at propeller tip (based on helical speed)', - default_value=1.0, -) - -add_meta_data( - Aircraft.Engine.PROPELLER_TIP_SPEED_MAX, - meta_data=_MetaData, - historical_name={ - "GASP": ['INPROP.TSPDMX', 'INPROP.TPSPDMXe'], - "FLOPS": None, - "LEAPS1": None, - }, - units='ft/s', - desc='maximum allowable linear propeller tip speed due to rotation', - default_value=800.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.PYLON_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FPYL', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.FPYL', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='factor for turbofan engine pylon mass', - default_value=.7 + default_value=0.7, + multivalue=True, ) add_meta_data( Aircraft.Engine.REFERENCE_DIAMETER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DIAM_REF', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={ + 'GASP': 'INGASP.DIAM_REF', + 'FLOPS': None, + 'LEAPS1': None, + }, # no DIAM_REF in GASP units='ft', desc='engine reference diameter', - default_value=0.0 + default_value=0.0, + multivalue=True, ) # NOTE This unscaled turbine (engine) weight is an input provided by the user, and is not @@ -2216,134 +2352,154 @@ add_meta_data( Aircraft.Engine.REFERENCE_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.WENG', # '~WEIGHT.WENG', - "LEAPS1": '(WeightABC)self._Engine.WEIGHT' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.WENG', # '~WEIGHT.WENG', + 'LEAPS1': '(WeightABC)self._Engine.WEIGHT', + }, units='lbm', - desc='unscaled mass of a single engine or bare engine if inlet and nozzle mass ' - 'are supplied', - default_value=None, + desc='unscaled mass of a single engine or bare engine if inlet and nozzle mass are supplied', + default_value=0.0, option=True, + multivalue=True, ) add_meta_data( Aircraft.Engine.REFERENCE_SLS_THRUST, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FN_REF', - "FLOPS": 'WTIN.THRSO', - "LEAPS1": 'aircraft.inputs.L0_engine*.thrust' - }, + historical_name={ + 'GASP': 'INGASP.FN_REF', # no FN_REF in GASP + 'FLOPS': 'WTIN.THRSO', + 'LEAPS1': 'aircraft.inputs.L0_engine*.thrust', + }, units='lbf', - desc='maximum thrust of an engine provided in engine model files', - default_value=None, - option=True + desc='Maximum sea-level static thrust of an unscaled engine. Optional. In ' + 'EngineDecks, reference thrust will be found from performance data if not provided ' + 'by user. User-provided values override SLS point found in performance data.', + default_value=0.0, + option=True, + multivalue=True, ) add_meta_data( Aircraft.Engine.RPM_DESIGN, meta_data=_MetaData, - historical_name={"GASP": 'INPROP.XNMAX', # maximum engine speed, rpm - "FLOPS": None, - "LEAPS1": None - }, + historical_name={ + 'GASP': 'INPROP.XNMAX', # maximum engine speed, rpm + 'FLOPS': None, + 'LEAPS1': None, + }, units='rpm', desc='the designed output RPM from the engine for fixed-RPM shafts', - default_value=None, + multivalue=True, ) add_meta_data( Aircraft.Engine.SCALE_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='Thrust-based scaling factor used to scale engine performance data during ' - 'mission analysis', - default_value=1.0 + 'mission analysis', + default_value=1.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.SCALE_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": '(types)EngineScaleModes.WEIGHT' - }, - desc='Toggle for enabling scaling of engine mass', + historical_name={ + 'GASP': None, + 'FLOPS': None, + 'LEAPS1': '(types)EngineScaleModes.WEIGHT', + }, + desc='Toggle for enabling scaling of engine mass based on Aircraft.Engine.SCALE_FACTOR', option=True, types=bool, + multivalue=True, default_value=True, ) add_meta_data( Aircraft.Engine.SCALE_PERFORMANCE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": ['iengine.scale_mode', - '(types)EngineScaleModes.DEFAULT', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, + 'LEAPS1': [ + 'iengine.scale_mode', + '(types)EngineScaleModes.DEFAULT', + ], + }, desc='Toggle for enabling scaling of engine performance including thrust, fuel flow, ' - 'and electric power', + 'and electric power using Aircraft.Engine.SCALE_FACTOR', option=True, types=bool, + multivalue=True, default_value=True, ) add_meta_data( Aircraft.Engine.SCALED_SLS_THRUST, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.THIN', - "FLOPS": 'CONFIN.THRUST', - "LEAPS1": ['aircraft.outputs.L0_propulsion.max_rated_thrust', - 'aircraft.cached.L0_propulsion.max_rated_thrust', - ] - }, + historical_name={ + 'GASP': 'INGASP.THIN', + 'FLOPS': 'CONFIN.THRUST', + 'LEAPS1': [ + 'aircraft.outputs.L0_propulsion.max_rated_thrust', + 'aircraft.cached.L0_propulsion.max_rated_thrust', + ], + }, units='lbf', - desc='maximum thrust of an engine after scaling', + desc='Maximum sea-level static thrust of an engine after scaling. Optional for ' + 'EngineDecks if Aircraft.Engine.SCALE_FACTOR is provided, in which case this ' + 'variable is computed.', default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.STARTER_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WEIGHT.WSTART', - "LEAPS1": '(WeightABC)self._starter_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WEIGHT.WSTART', + 'LEAPS1': '(WeightABC)self._starter_weight', + }, units='lbm', - desc='starter mass', - default_value=0.0 + desc='mass of engine starter subsystem', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.SUBSONIC_FUEL_FLOW_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.FFFSUB', - "LEAPS1": 'aircraft.L0_fuel_flow.subsonic_factor' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.FFFSUB', + 'LEAPS1': 'aircraft.L0_fuel_flow.subsonic_factor', + }, units='unitless', desc='scaling factor on fuel flow when Mach number is subsonic', default_value=1.0, - option=True + option=True, + multivalue=True, ) add_meta_data( Aircraft.Engine.SUPERSONIC_FUEL_FLOW_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'ENGDIN.FFFSUP', - "LEAPS1": 'aircraft.L0_fuel_flow.supersonic_factor' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'ENGDIN.FFFSUP', + 'LEAPS1': 'aircraft.L0_fuel_flow.supersonic_factor', + }, units='unitless', desc='scaling factor on fuel flow when Mach number is supersonic', default_value=1.0, - option=True + option=True, + multivalue=True, ) add_meta_data( @@ -2351,16 +2507,19 @@ # - see also: Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER Aircraft.Engine.THRUST_REVERSERS_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(11, 2)', '~WEIGHT.WTHR', '~WTSTAT.WSP(11, 2)', '~INERT.WTHR'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._thrust_reversers_weight', - 'aircraft.outputs.L0_weights_summary.thrust_reversers_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(11, 2)', '~WEIGHT.WTHR', '~WTSTAT.WSP(11, 2)', '~INERT.WTHR'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._thrust_reversers_weight', + 'aircraft.outputs.L0_weights_summary.thrust_reversers_weight', + ], + }, units='lbm', desc='mass of thrust reversers on engines', default_value=0.0, + multivalue=True, ) add_meta_data( @@ -2368,55 +2527,44 @@ # discarded Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WTHR', 'MISWT.WTHR', 'MISWT.OTHR'], - "FLOPS": 'WTIN.WTHR', - "LEAPS1": 'aircraft.inputs.L0_overrides.thrust_reversers_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WTHR', 'MISWT.WTHR', 'MISWT.OTHR'], + 'FLOPS': 'WTIN.WTHR', + 'LEAPS1': 'aircraft.inputs.L0_overrides.thrust_reversers_weight', + }, units='unitless', - desc='scaler for mass of thrust reversers on engines', - default_value=0.0, # FLOPS/LEAPS1 default value + desc='scaler for mass of thrust reversers on engines. In FLOPS/LEAPS1 default to 0.0', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.TYPE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.NTYE', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.NTYE', 'FLOPS': None, 'LEAPS1': None}, option=True, default_value=GASPEngineType.TURBOJET, types=GASPEngineType, - units="unitless", - desc='specifies engine type used for engine mass calculation', -) - -add_meta_data( - Aircraft.Engine.USE_PROPELLER_MAP, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - option=True, - default_value=False, - types=bool, - units="unitless", - desc='flag whether to use propeller map or Hamilton-Standard model.' + multivalue=True, + units='unitless', + desc='specifies engine type used for GASP-based engine mass calculation', ) add_meta_data( Aircraft.Engine.WING_LOCATIONS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.YP', - "FLOPS": 'WTIN.ETAE', # ['&DEFINE.WTIN.ETAE', 'WDEF.ETAE'], - "LEAPS1": 'aircraft.inputs.L0_propulsion.wing_engine_locations' - }, + historical_name={ + 'GASP': 'INGASP.YP', + 'FLOPS': 'WTIN.ETAE', # ['&DEFINE.WTIN.ETAE', 'WDEF.ETAE'], + 'LEAPS1': 'aircraft.inputs.L0_propulsion.wing_engine_locations', + }, units='unitless', desc='Engine wing mount locations as fractions of semispan; (NUM_WING_ENGINES)/2 values ' - 'are input', - default_value=np.array([0.0]) + 'are input', + types=(float, list, np.ndarray), + default_value=[0.0], + multivalue=True, ) # ___ _ @@ -2428,55 +2576,54 @@ add_meta_data( Aircraft.Engine.Gearbox.EFFICIENCY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='The efficiency of the gearbox.', - default_value=0.98, + default_value=1.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.Gearbox.GEAR_RATIO, meta_data=_MetaData, - historical_name={"GASP": None, # 1 / INPROP.GR - "FLOPS": None, - "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, # 1 / INPROP.GR units='unitless', desc='Reduction gear ratio, or the ratio of the RPM_in divided by the RPM_out for the gearbox.', default_value=1.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.Gearbox.MASS, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='The mass of the gearbox.', default_value=0, + multivalue=True, ) add_meta_data( Aircraft.Engine.Gearbox.SHAFT_POWER_DESIGN, meta_data=_MetaData, historical_name={ - "GASP": 'INPROP.HPMSLS', # max sea level static horsepower, hp - "FLOPS": None, - "LEAPS1": None, + 'GASP': 'INPROP.HPMSLS', # max sea level static horsepower, hp + 'FLOPS': None, + 'LEAPS1': None, }, units='hp', desc='A guess for the maximum power that will be transmitted through the gearbox during the mission (max shp input).', default_value=1.0, - option=True, + multivalue=True, ) add_meta_data( Aircraft.Engine.Gearbox.SPECIFIC_TORQUE, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf*ft/lbm', desc='The specific torque of the gearbox, used to calculate gearbox mass. ', default_value=100, + multivalue=True, ) # __ __ _ @@ -2488,19 +2635,124 @@ add_meta_data( Aircraft.Engine.Motor.MASS, meta_data=_MetaData, - historical_name={"GASP": 'WMOTOR', "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': 'WMOTOR', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='Total motor mass (considers number of motors)', default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Engine.Motor.TORQUE_MAX, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf*ft', desc='Max torque value that can be output from a single motor. Used to determine ' 'motor mass in pre-mission', + multivalue=True, +) + +# ___ _ _ +# | _ \ _ _ ___ _ __ ___ | | | | ___ _ _ +# | _/ | '_| / _ \ | '_ \ / -_) | | | | / -_) | '_| +# |_| |_| \___/ | .__/ \___| |_| |_| \___| |_| +# |_| +# =================================================== + +add_meta_data( + Aircraft.Engine.Propeller.ACTIVITY_FACTOR, + meta_data=_MetaData, + historical_name={'GASP': 'INPROP.AF', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='propeller actitivty factor per Blade (Range: 80 to 200)', + default_value=0.0, + multivalue=True, +) + +# NOTE if FT < 0, this bool is true, if >= 0, this is false and the value of FT is used +# as the installation loss factor +add_meta_data( + Aircraft.Engine.Propeller.COMPUTE_INSTALLATION_LOSS, + meta_data=_MetaData, + historical_name={'GASP': 'INPROP.FT', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + option=True, + default_value=True, + types=bool, + multivalue=True, + desc='if true, compute installation loss factor based on blockage factor', +) + +add_meta_data( + Aircraft.Engine.Propeller.DATA_FILE, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + types=(str, Path), + default_value=None, + option=True, + desc='filepath to data file containing propeller data map', + multivalue=True, +) + +add_meta_data( + Aircraft.Engine.Propeller.DIAMETER, + meta_data=_MetaData, + historical_name={'GASP': 'INPROP.DPROP', 'FLOPS': None, 'LEAPS1': None}, + units='ft', + desc='propeller diameter', + default_value=0.0, + multivalue=True, +) + +add_meta_data( + Aircraft.Engine.Propeller.INTEGRATED_LIFT_COEFFICIENT, + meta_data=_MetaData, + historical_name={'GASP': 'INPROP.CLI', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='propeller blade integrated design lift coefficient (Range: 0.3 to 0.8)', + default_value=0.5, + multivalue=True, +) + +add_meta_data( + Aircraft.Engine.Propeller.NUM_BLADES, + meta_data=_MetaData, + historical_name={'GASP': 'INPROP.BL', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='number of blades per propeller', + option=True, + types=int, + multivalue=True, + default_value=0, +) + +add_meta_data( + Aircraft.Engine.Propeller.TIP_MACH_MAX, + meta_data=_MetaData, + historical_name={ + 'GASP': None, # TODO this needs verification + 'FLOPS': None, + 'LEAPS1': None, + }, + units='unitless', + desc='maximum allowable Mach number at propeller tip (based on helical speed)', + default_value=1.0, + multivalue=True, +) + +add_meta_data( + Aircraft.Engine.Propeller.TIP_SPEED_MAX, + meta_data=_MetaData, + historical_name={ + 'GASP': ['INPROP.TSPDMX', 'INPROP.TPSPDMXe'], + 'FLOPS': None, + 'LEAPS1': None, + }, + units='ft/s', + desc='maximum allowable propeller linear tip speed', + default_value=800.0, + multivalue=True, ) # ______ _ @@ -2514,10 +2766,11 @@ add_meta_data( Aircraft.Fins.AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.SFIN', # ['&DEFINE.WTIN.SFIN', 'WTS.SFIN'], - "LEAPS1": 'aircraft.inputs.L0_fins.area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.SFIN', # ['&DEFINE.WTIN.SFIN', 'WTS.SFIN'], + 'LEAPS1': 'aircraft.inputs.L0_fins.area', + }, units='ft**2', desc='vertical fin theoretical area', default_value=0.0, @@ -2528,25 +2781,28 @@ # - see also: Aircraft.Fins.MASS_SCALER Aircraft.Fins.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(4, 2)', '~WEIGHT.WFIN', '~WTSTAT.WSP(4, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._wing_vertical_fin_weight', - 'aircraft.outputs.L0_weights_summary.wing_vertical_fin_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(4, 2)', '~WEIGHT.WFIN', '~WTSTAT.WSP(4, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._wing_vertical_fin_weight', + 'aircraft.outputs.L0_weights_summary.wing_vertical_fin_weight', + ], + }, units='lbm', desc='mass of vertical fins', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Fins.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRFIN', # ['&DEFINE.WTIN.FRFIN', 'WTS.FRFIN'], - "LEAPS1": 'aircraft.inputs.L0_overrides.wing_vertical_fin_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRFIN', # ['&DEFINE.WTIN.FRFIN', 'WTS.FRFIN'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.wing_vertical_fin_weight', + }, units='unitless', desc='mass scaler for fin structure', default_value=1.0, @@ -2555,10 +2811,11 @@ add_meta_data( Aircraft.Fins.NUM_FINS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NFIN', # ['&DEFINE.WTIN.NFIN', 'WTS.NFIN'], - "LEAPS1": 'aircraft.inputs.L0_fins.fin_count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NFIN', # ['&DEFINE.WTIN.NFIN', 'WTS.NFIN'], + 'LEAPS1': 'aircraft.inputs.L0_fins.fin_count', + }, units='unitless', desc='number of fins', types=int, @@ -2569,13 +2826,14 @@ add_meta_data( Aircraft.Fins.TAPER_RATIO, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.TRFIN', # ['&DEFINE.WTIN.TRFIN', 'WTS.TRFIN'], - "LEAPS1": 'aircraft.inputs.L0_fins.taper_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.TRFIN', # ['&DEFINE.WTIN.TRFIN', 'WTS.TRFIN'], + 'LEAPS1': 'aircraft.inputs.L0_fins.taper_ratio', + }, units='unitless', desc='vertical fin theoretical taper ratio', - default_value=None, + default_value=0.0, ) # ______ _ @@ -2589,76 +2847,42 @@ add_meta_data( Aircraft.Fuel.AUXILIARY_FUEL_CAPACITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FULAUX', # ['&DEFINE.WTIN.FULAUX', 'FAWT.FULAUX'], - "LEAPS1": 'aircraft.inputs.L0_fuel.aux_capacity' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FULAUX', # ['&DEFINE.WTIN.FULAUX', 'FAWT.FULAUX'], + 'LEAPS1': 'aircraft.inputs.L0_fuel.aux_capacity', + }, units='lbm', desc='fuel capacity of the auxiliary tank', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Fuel.BURN_PER_PASSENGER_MILE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm/NM', desc='average fuel burn per passenger per mile flown', ) -add_meta_data( - Aircraft.Fuel.CAPACITY_FACTOR, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISWT.FWMAX', - "LEAPS1": '(WeightABC)self._wing_fuel_capacity_factor' - }, - units='unitless', - desc='fuel capacity factor', - default_value=23.0, -) - add_meta_data( Aircraft.Fuel.DENSITY, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FUELD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.FUELD', 'FLOPS': 'WTIN.FULDEN', 'LEAPS1': None}, units='lbm/galUS', - desc='fuel density', - default_value=6.687, -) - -# TODO replace with actual fuel density -add_meta_data( - Aircraft.Fuel.DENSITY_RATIO, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FULDEN', # ['&DEFINE.WTIN.FULDEN', 'UPFUEL.FULDEN'], - "LEAPS1": 'aircraft.inputs.L0_fuel.density_ratio' - }, - units='unitless', - desc='Fuel density ratio for alternate fuels compared to jet fuel (typical ' - 'density of 6.7 lbm/gal), used in the calculation of wing_capacity (if ' - 'wing_capacity is not input) and in the calculation of fuel system ' - 'weight.', - default_value=1.0, + desc='fuel density (jet fuel typical density of 6.7 lbm/galUS used in the calculation of wing_capacity' + '(if wing_capacity is not input) and in the calculation of fuel system weight.', + default_value=6.7, ) add_meta_data( Aircraft.Fuel.FUEL_MARGIN, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FVOL_MRG', - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', # percent - desc='excess fuel volume required, essentially the amount of fuel above ' - 'the design point that there has to be volume to carry', + historical_name={'GASP': 'INGASP.FVOL_MRG', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='percentage of excess fuel volume required, essentially the amount of fuel above ' + 'the design point that there has to be volume to carry', + default_value=0.0, ) add_meta_data( @@ -2666,37 +2890,38 @@ # - see also: Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER Aircraft.Fuel.FUEL_SYSTEM_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(13, 2)', '~WEIGHT.WFSYS', '~WTSTAT.WSP(13, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._fuel_sys_weight', - 'aircraft.outputs.L0_weights_summary.fuel_sys_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(13, 2)', '~WEIGHT.WFSYS', '~WTSTAT.WSP(13, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._fuel_sys_weight', + 'aircraft.outputs.L0_weights_summary.fuel_sys_weight', + ], + }, units='lbm', desc='fuel system mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Fuel.FUEL_SYSTEM_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKFS', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKFS', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of fuel system', + default_value=0.0, ) add_meta_data( Aircraft.Fuel.FUEL_SYSTEM_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CK21', - # ['&DEFINE.WTIN.WFSYS', 'MISWT.WFSYS', 'MISWT.OFSYS'], - "FLOPS": 'WTIN.WFSYS', - "LEAPS1": 'aircraft.inputs.L0_overrides.fuel_sys_weight' - }, + historical_name={ + 'GASP': 'INGASP.CK21', + # ['&DEFINE.WTIN.WFSYS', 'MISWT.WFSYS', 'MISWT.OFSYS'], + 'FLOPS': 'WTIN.WFSYS', + 'LEAPS1': 'aircraft.inputs.L0_overrides.fuel_sys_weight', + }, units='unitless', desc='scaler for fuel system mass', default_value=1.0, @@ -2705,25 +2930,40 @@ add_meta_data( Aircraft.Fuel.FUSELAGE_FUEL_CAPACITY, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.FULFMX', 'WTS.FULFMX', '~WEIGHT.FUFU'], - "FLOPS": 'WTIN.FULFMX', - "LEAPS1": ['aircraft.inputs.L0_fuel.fuselage_capacity', - '(WeightABC)self._fuselage_fuel_capacity' - ] - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.FULFMX', 'WTS.FULFMX', '~WEIGHT.FUFU'], + 'FLOPS': 'WTIN.FULFMX', + 'LEAPS1': [ + 'aircraft.inputs.L0_fuel.fuselage_capacity', + '(WeightABC)self._fuselage_fuel_capacity', + ], + }, units='lbm', desc='fuel capacity of the fuselage', - default_value=None, + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuel.IGNORE_FUEL_CAPACITY_CONSTRAINT, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': 'WTIN.IFUFU', 'LEAPS1': None}, + units='unitless', + desc='Flag to control enforcement of fuel_capacity constraint. ' + 'If False (default) Aviary will add the excess fuel constraint and only converge if there is enough fuel capacity to complete the mission.' + 'If set True Aviary will ignore this constraint, and allow mission fuel > total_fuel_capacity. Use carefully!', + default_value=False, + types=bool, ) add_meta_data( Aircraft.Fuel.NUM_TANKS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NTANK', # ['&DEFINE.WTIN.NTANK', 'WTS.NTANK'], - "LEAPS1": 'aircraft.inputs.L0_fuel.tank_count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NTANK', # ['&DEFINE.WTIN.NTANK', 'WTS.NTANK'], + 'LEAPS1': 'aircraft.inputs.L0_fuel.tank_count', + }, units='unitless', desc='number of fuel tanks', types=int, @@ -2734,32 +2974,37 @@ add_meta_data( Aircraft.Fuel.TOTAL_CAPACITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FMXTOT', # ['&DEFINE.WTIN.FMXTOT', 'PLRNG.FMXTOT'], - "LEAPS1": ['aircraft.inputs.L0_fuel.total_capacity', - 'aircraft.cached.L0_fuel.total_capacity', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FMXTOT', # ['&DEFINE.WTIN.FMXTOT', 'PLRNG.FMXTOT'], + 'LEAPS1': [ + 'aircraft.inputs.L0_fuel.total_capacity', + 'aircraft.cached.L0_fuel.total_capacity', + ], + }, units='lbm', desc='Total fuel capacity of the aircraft including wing, fuselage and ' - 'auxiliary tanks. Used in generating payload-range diagram (Default = ' - 'wing_capacity + fuselage_capacity + aux_capacity)', - default_value=None, + 'auxiliary tanks. Used in generating payload-range diagram (Default = ' + 'wing_capacity + fuselage_capacity + aux_capacity)', + default_value=0.0, ) add_meta_data( Aircraft.Fuel.TOTAL_VOLUME, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WEIGHT.ZFEQ', - "LEAPS1": ['(WeightABC)self._total_fuel_vol', - '~WeightABC.calc_unusable_fuel.total_fuel_vol', - '~WeightABC._pre_unusable_fuel.total_fuel_vol', - '~BasicTransportWeight._pre_unusable_fuel.total_fuel_vol', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WEIGHT.ZFEQ', + 'LEAPS1': [ + '(WeightABC)self._total_fuel_vol', + '~WeightABC.calc_unusable_fuel.total_fuel_vol', + '~WeightABC._pre_unusable_fuel.total_fuel_vol', + '~BasicTransportWeight._pre_unusable_fuel.total_fuel_vol', + ], + }, units='galUS', # need to check this - desc='Total fuel volume' + desc='Total fuel volume', + default_value=0.0, ) add_meta_data( @@ -2767,38 +3012,38 @@ # - see also: Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER Aircraft.Fuel.UNUSABLE_FUEL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(29, 2)', '~WEIGHT.WUF', '~WTSTAT.WSP(29, 2)', '~INERT.WUF'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._unusable_fuel_weight', - 'aircraft.outputs.L0_weights_summary.unusable_fuel_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(29, 2)', '~WEIGHT.WUF', '~WTSTAT.WSP(29, 2)', '~INERT.WUF'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._unusable_fuel_weight', + 'aircraft.outputs.L0_weights_summary.unusable_fuel_weight', + ], + }, units='lbm', desc='unusable fuel mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Fuel.UNUSABLE_FUEL_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": "INGASP.CW(13)", - "FLOPS": None, - "LEAPS1": None - }, - default_value=6.0, - units="unitless", + historical_name={'GASP': 'INGASP.CW(13)', 'FLOPS': None, 'LEAPS1': None}, + default_value=0.0, + units='unitless', desc='mass trend coefficient of trapped fuel factor', ) add_meta_data( Aircraft.Fuel.UNUSABLE_FUEL_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WUF', 'MISWT.WUF', 'MISWT.OUF'], - "FLOPS": 'WTIN.WUF', - "LEAPS1": 'aircraft.inputs.L0_overrides.unusable_fuel_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WUF', 'MISWT.WUF', 'MISWT.OUF'], + 'FLOPS': 'WTIN.WUF', + 'LEAPS1': 'aircraft.inputs.L0_overrides.unusable_fuel_weight', + }, units='unitless', desc='scaler for Unusable fuel mass', default_value=1.0, @@ -2807,33 +3052,33 @@ add_meta_data( Aircraft.Fuel.WING_FUEL_CAPACITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FULWMX', # ['&DEFINE.WTIN.FULWMX', 'WTS.FULWMX'], - "LEAPS1": 'aircraft.inputs.L0_fuel.wing_capacity' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FULWMX', # ['&DEFINE.WTIN.FULWMX', 'WTS.FULWMX'], + 'LEAPS1': 'aircraft.inputs.L0_fuel.wing_capacity', + }, units='lbm', desc='fuel capacity of the auxiliary tank', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Fuel.WING_FUEL_FRACTION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKWF', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.SKWF', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='fraction of total theoretical wing volume used for wing fuel', + default_value=0.0, ) add_meta_data( Aircraft.Fuel.WING_REF_CAPACITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FUELRF', # ['&DEFINE.WTIN.FUELRF', 'WPAB.FUELRF'], - "LEAPS1": 'aircraft.inputs.L0_fuel.wing_ref_capacity' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FUELRF', # ['&DEFINE.WTIN.FUELRF', 'WPAB.FUELRF'], + 'LEAPS1': 'aircraft.inputs.L0_fuel.wing_ref_capacity', + }, units='lbm', # TODO FLOPS says lbm, sfwate.f line 827 desc='reference fuel volume', default_value=0.0, @@ -2842,10 +3087,11 @@ add_meta_data( Aircraft.Fuel.WING_REF_CAPACITY_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FSWREF', # ['&DEFINE.WTIN.FSWREF', 'WPAB.FSWREF'], - "LEAPS1": 'aircraft.inputs.L0_fuel.wing_ref_capacity_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FSWREF', # ['&DEFINE.WTIN.FSWREF', 'WPAB.FSWREF'], + 'LEAPS1': 'aircraft.inputs.L0_fuel.wing_ref_capacity_area', + }, units='unitless', # TODO FLOPS says unitless, sfwate.f line 828 desc='reference wing area for fuel capacity', default_value=0.0, @@ -2854,10 +3100,11 @@ add_meta_data( Aircraft.Fuel.WING_REF_CAPACITY_TERM_A, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FUSCLA', # ['&DEFINE.WTIN.FUSCLA', 'WPAB.FUSCLA'], - "LEAPS1": 'aircraft.inputs.L0_fuel.wing_ref_capacity_1_5_term' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FUSCLA', # ['&DEFINE.WTIN.FUSCLA', 'WPAB.FUSCLA'], + 'LEAPS1': 'aircraft.inputs.L0_fuel.wing_ref_capacity_1_5_term', + }, units='unitless', desc='scaling factor A', default_value=0.0, @@ -2866,10 +3113,11 @@ add_meta_data( Aircraft.Fuel.WING_REF_CAPACITY_TERM_B, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FUSCLB', # ['&DEFINE.WTIN.FUSCLB', 'WPAB.FUSCLB'], - "LEAPS1": 'aircraft.inputs.L0_fuel.wing_ref_capacity_linear_term' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FUSCLB', # ['&DEFINE.WTIN.FUSCLB', 'WPAB.FUSCLB'], + 'LEAPS1': 'aircraft.inputs.L0_fuel.wing_ref_capacity_linear_term', + }, units='unitless', desc='scaling factor B', default_value=0.0, @@ -2892,34 +3140,28 @@ add_meta_data( Aircraft.Fuel.WING_VOLUME_DESIGN, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FVOLW_DES', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.FVOLREQ', 'FLOPS': None, 'LEAPS1': None}, units='ft**3', desc='wing tank fuel volume when carrying design fuel plus fuel margin', + default_value=0.0, ) add_meta_data( Aircraft.Fuel.WING_VOLUME_GEOMETRIC_MAX, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FVOLW_GEOM', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.FVOLW_GEOM', 'FLOPS': None, 'LEAPS1': None}, units='ft**3', desc='wing tank fuel volume based on geometry', + default_value=0.0, ) add_meta_data( Aircraft.Fuel.WING_VOLUME_STRUCTURAL_MAX, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FVOLW_MAX', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.FVOLW_MAX', 'FLOPS': None, 'LEAPS1': None}, units='ft**3', desc='wing tank volume based on maximum wing fuel weight', + default_value=0.0, ) @@ -2939,42 +3181,56 @@ # - see also: Aircraft.Furnishings.MASS_SCALER Aircraft.Furnishings.MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(8)', - # ['WTS.WSP(22, 2)', '~WEIGHT.WFURN', '~WTSTAT.WSP(22, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._furnishings_group_weight', - 'aircraft.outputs.L0_weights_summary.furnishings_group_weight', - ] - }, + historical_name={ + 'GASP': 'INGASP.CW(8)', + # ['WTS.WSP(22, 2)', '~WEIGHT.WFURN', '~WTSTAT.WSP(22, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._furnishings_group_weight', + 'aircraft.outputs.L0_weights_summary.furnishings_group_weight', + ], + }, units='lbm', desc='Total furnishings system mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Furnishings.MASS_BASE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='Base furnishings system mass without additional 1% empty mass' + desc='For FLOPS based, base furnishings system mass without additional 1% empty mass', + default_value=0.0, ) add_meta_data( Aircraft.Furnishings.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WFURN', 'MISWT.WFURN', 'MISWT.OFURN'], - "FLOPS": 'WTIN.WFURN', - "LEAPS1": 'aircraft.inputs.L0_overrides.furnishings_group_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WFURN', 'MISWT.WFURN', 'MISWT.OFURN'], + 'FLOPS': 'WTIN.WFURN', + 'LEAPS1': 'aircraft.inputs.L0_overrides.furnishings_group_weight', + }, units='unitless', - desc='Furnishings system mass scaler', + desc='Furnishings system mass scaler. In GASP based, it is applicale if gross mass ' + '> 10000 lbs and number of passengers >= 50. Set it to 0.0 if not use.', default_value=1.0, ) +add_meta_data( + Aircraft.Furnishings.USE_EMPIRICAL_EQUATION, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='In GASP based, indicate whether use commonly used empirical furnishing weight equation. ' + 'This applies only when gross mass > 10000 and number of passengers >= 50.', + types=bool, + option=True, + default_value=True, +) + # ______ _ # | ____| | | # | |__ _ _ ___ ___ | | __ _ __ _ ___ @@ -2985,13 +3241,28 @@ # |___/ # ======================================================== +add_meta_data( + Aircraft.Fuselage.AFTBODY_MASS, + meta_data=_MetaData, + historical_name={'GASP': 'WGT_AB', 'FLOPS': None, 'LEAPS1': None}, + units='lbm', + default_value=0.0, + desc='aftbody mass', +) + +add_meta_data( + Aircraft.Fuselage.AFTBODY_MASS_PER_UNIT_AREA, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.UWT_AFT', 'FLOPS': None, 'LEAPS1': None}, + units='lbm/ft**2', + default_value=0.0, + desc='aftbody structural areal unit weight', +) + add_meta_data( Aircraft.Fuselage.AISLE_WIDTH, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WAS', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WAS', 'FLOPS': None, 'LEAPS1': None}, units='inch', desc='width of the aisles in the passenger cabin', option=True, @@ -3003,104 +3274,156 @@ add_meta_data( Aircraft.Fuselage.AVG_DIAMETER, meta_data=_MetaData, - historical_name={"GASP": ['INGASP.WC', 'INGASP.SWF'], - "FLOPS": None, # 'EDETIN.XD', - "LEAPS1": 'aircraft.outputs.L0_fuselage.avg_diam' - }, + historical_name={ + 'GASP': ['INGASP.WC', 'INGASP.SWF'], + 'FLOPS': None, # 'EDETIN.XD', + 'LEAPS1': 'aircraft.outputs.L0_fuselage.avg_diam', + }, units='ft', - desc='average fuselage diameter' + desc='average fuselage diameter', + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuselage.CABIN_AREA, + meta_data=_MetaData, + historical_name={ + 'GASP': None, + # ['&DEFINE.FUSEIN.ACABIN', 'WDEF.ACABIN'], + 'FLOPS': 'FUSEIN.ACABIN', + 'LEAPS1': [ + 'aircraft.inputs.L0_blended_wing_body_design.cabin_area', + 'aircraft.cached.L0_blended_wing_body_design.cabin_area', + ], + }, + units='ft**2', + desc='fixed area of passenger cabin for blended wing body transports', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.CHARACTERISTIC_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.EL[4]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[3]', - 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[3]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.EL[4]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[3]', + 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[3]', + ], + }, units='ft', - desc='Reynolds characteristic length for the fuselage' + desc='Reynolds characteristic length for the fuselage', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.CROSS_SECTION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['MISSA.SPI', '~CDCC.SPI'], - "LEAPS1": 'aircraft.outputs.L0_fuselage.mission_cross_sect_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['MISSA.SPI', '~CDCC.SPI'], + 'LEAPS1': 'aircraft.outputs.L0_fuselage.mission_cross_sect_area', + }, units='ft**2', - desc='fuselage cross sectional area' + desc='fuselage cross sectional area', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.DELTA_DIAMETER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.HCK', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.HCK', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='mean fuselage cabin diameter minus mean fuselage nose diameter', - default_value=4.5, + default_value=0.0, ) +# TODO this should be a design parameter? As it combines two physical categories? add_meta_data( Aircraft.Fuselage.DIAMETER_TO_WING_SPAN, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['MISSA.DB', '~CDCC.DB'], - "LEAPS1": 'aircraft.outputs.L0_fuselage.mission_diam_to_wing_span_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['MISSA.DB', '~CDCC.DB'], + 'LEAPS1': 'aircraft.outputs.L0_fuselage.mission_diam_to_wing_span_ratio', + }, units='unitless', - desc='fuselage diameter to wing span ratio' + desc='fuselage diameter to wing span ratio', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.FINENESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.FR[4]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[3]', - 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[3]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.FR[4]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[3]', + 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[3]', + ], + }, units='unitless', - desc='fuselage fineness ratio' + desc='fuselage fineness ratio', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.FLAT_PLATE_AREA_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELFE', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELFE', 'FLOPS': None, 'LEAPS1': None}, units='ft**2', desc='increment to fuselage flat plate area', + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuselage.FOREBODY_MASS, + meta_data=_MetaData, + historical_name={'GASP': 'WGT_FB', 'FLOPS': None, 'LEAPS1': None}, + units='lbm', + default_value=0.0, + desc='forebody mass', ) add_meta_data( Aircraft.Fuselage.FORM_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKF', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CKF', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='fuselage form factor', - default_value=1 + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuselage.HEIGHT_TO_WIDTH_RATIO, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.HGTqWID', 'FLOPS': 'WTIN.TCF', 'LEAPS1': None}, + units='unitless', + types=float, + default_value=1.0, + desc='fuselage height-to-width ratio', +) + +add_meta_data( + Aircraft.Fuselage.HYDRAULIC_DIAMETER, + meta_data=_MetaData, + historical_name={'GASP': 'DHYDRAL', 'FLOPS': None, 'LEAPS1': None}, + units='ft', + types=float, + default_value=0.0, + desc='the geometric mean of cabin height and cabin width', ) add_meta_data( Aircraft.Fuselage.LAMINAR_FLOW_LOWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRLB', # ['&DEFINE.AERIN.TRLB', 'XLAM.TRLB', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.fuselage_percent_laminar_flow_lower_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRLB', # ['&DEFINE.AERIN.TRLB', 'XLAM.TRLB', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.fuselage_percent_laminar_flow_lower_surface', + }, units='unitless', desc='define percent laminar flow for fuselage lower surface', default_value=0.0, @@ -3109,10 +3432,11 @@ add_meta_data( Aircraft.Fuselage.LAMINAR_FLOW_UPPER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRUB', # ['&DEFINE.AERIN.TRUB', 'XLAM.TRUB', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.fuselage_percent_laminar_flow_upper_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRUB', # ['&DEFINE.AERIN.TRUB', 'XLAM.TRUB', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.fuselage_percent_laminar_flow_upper_surface', + }, units='unitless', desc='define percent laminar flow for fuselage upper surface', default_value=0.0, @@ -3122,35 +3446,58 @@ add_meta_data( Aircraft.Fuselage.LENGTH, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ELF', - "FLOPS": 'WTIN.XL', - # [ # inputs - # '&DEFINE.WTIN.XL', 'WTS.XL', - # # outputs - # 'EDETIN.BL', '~DEFAER.BL', - # ], - "LEAPS1": ['aircraft.inputs.L0_fuselage.total_length', - 'aircraft.outputs.L0_fuselage.total_length', - # other - 'aircraft.cached.L0_fuselage.total_length', - ] - }, + historical_name={ + 'GASP': 'INGASP.ELF', + 'FLOPS': 'WTIN.XL', + # [ # inputs + # '&DEFINE.WTIN.XL', 'WTS.XL', + # # outputs + # 'EDETIN.BL', '~DEFAER.BL', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_fuselage.total_length', + 'aircraft.outputs.L0_fuselage.total_length', + # other + 'aircraft.cached.L0_fuselage.total_length', + ], + }, units='ft', desc='Define the Fuselage total length. If total_length is not input for a ' - 'passenger transport, LEAPS will calculate the fuselage length, width and ' - 'depth and the length of the passenger compartment.', + 'passenger transport, LEAPS will calculate the fuselage length, width and ' + 'depth and the length of the passenger compartment.', default_value=0.0, ) add_meta_data( Aircraft.Fuselage.LENGTH_TO_DIAMETER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['MISSA.BODYLD', '~CDCC.BODYLD'], - "LEAPS1": 'aircraft.outputs.L0_fuselage.mission_len_to_diam_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['MISSA.BODYLD', '~CDCC.BODYLD'], + 'LEAPS1': 'aircraft.outputs.L0_fuselage.mission_len_to_diam_ratio', + }, units='unitless', - desc='fuselage length to diameter ratio' + desc='fuselage length to diameter ratio', + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuselage.LIFT_COEFFICIENT_RATIO_BODY_TO_WING, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.CLBqCLW', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + types=float, + default_value=0.0, + desc='lift coefficient of body over lift coefficient of wing ratio', +) + +add_meta_data( + Aircraft.Fuselage.LIFT_CURVE_SLOPE_MACH0, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.CLALPH_B0', 'FLOPS': None, 'LEAPS1': None}, + units='1/rad', + default_value=0.0, + desc='lift curve slope of fuselage at Mach 0', ) add_meta_data( @@ -3158,26 +3505,25 @@ # - see also: Aircraft.Fuselage.MASS_SCALER Aircraft.Fuselage.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(6, 2)', '~WEIGHT.WFUSE', '~WTSTAT.WSP(6, 2)', '~INERT.WFUSE', ], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._fuselage_weight', - 'aircraft.outputs.L0_weights_summary.fuselage_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(6, 2)', '~WEIGHT.WFUSE', '~WTSTAT.WSP(6, 2)', '~INERT.WFUSE', ], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._fuselage_weight', + 'aircraft.outputs.L0_weights_summary.fuselage_weight', + ], + }, units='lbm', desc='mass of the fuselage structure', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKB', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKB', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of fuselage', default_value=136, ) @@ -3185,10 +3531,11 @@ add_meta_data( Aircraft.Fuselage.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRFU', # ['&DEFINE.WTIN.FRFU', 'WTS.FRFU'], - "LEAPS1": 'aircraft.inputs.L0_overrides.fuselage_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRFU', # ['&DEFINE.WTIN.FRFU', 'WTS.FRFU'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.fuselage_weight', + }, units='unitless', desc='mass scaler of the fuselage structure', default_value=1.0, @@ -3197,45 +3544,51 @@ add_meta_data( Aircraft.Fuselage.MAX_HEIGHT, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.DF', # ['&DEFINE.WTIN.DF', 'WTS.DF'], - "LEAPS1": 'aircraft.inputs.L0_fuselage.max_height' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.DF', # ['&DEFINE.WTIN.DF', 'WTS.DF'], + 'LEAPS1': 'aircraft.inputs.L0_fuselage.max_height', + }, units='ft', - desc='maximum fuselage height' + desc='maximum fuselage height', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.MAX_WIDTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.WF', - # [ # inputs - # '&DEFINE.WTIN.WF', 'WTS.WF', - # # outputs - # 'MIMOD.FWID', - # ], - "LEAPS1": ['aircraft.inputs.L0_fuselage.max_width', - 'aircraft.outputs.L0_fuselage.max_width', - # other - 'aircraft.cached.L0_fuselage.max_width', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.WF', + # [ # inputs + # '&DEFINE.WTIN.WF', 'WTS.WF', + # # outputs + # 'MIMOD.FWID', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_fuselage.max_width', + 'aircraft.outputs.L0_fuselage.max_width', + # other + 'aircraft.cached.L0_fuselage.max_width', + ], + }, units='ft', desc='maximum fuselage width', default_value=0.0, ) -# TODO are we keeping millitary cargo? +# TODO are we keeping military cargo? add_meta_data( Aircraft.Fuselage.MILITARY_CARGO_FLOOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.CARGF', # ['&DEFINE.WTIN.CARGF', 'WTS.CARGF'], - "LEAPS1": ['aircraft.inputs.L0_crew_and_payload.military_cargo', - 'aircraft.cached.L0_crew_and_payload.military_cargo', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.CARGF', # ['&DEFINE.WTIN.CARGF', 'WTS.CARGF'], + 'LEAPS1': [ + 'aircraft.inputs.L0_crew_and_payload.military_cargo', + 'aircraft.cached.L0_crew_and_payload.military_cargo', + ], + }, units='unitless', desc='indicate whether or not there is a military cargo aircraft floor', option=True, @@ -3246,11 +3599,8 @@ add_meta_data( Aircraft.Fuselage.NOSE_FINENESS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ELODN', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.ELODN', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='length to diameter ratio of nose cone', default_value=1, ) @@ -3258,11 +3608,8 @@ add_meta_data( Aircraft.Fuselage.NUM_AISLES, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.AS', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.AS', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='number of aisles in the passenger cabin', types=int, option=True, @@ -3272,14 +3619,16 @@ add_meta_data( Aircraft.Fuselage.NUM_FUSELAGES, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.NFUSE', 'EDETIN.NFUSE', '~WWGHT.NFUSE'], - "FLOPS": 'WTIN.NFUSE', - "LEAPS1": ['aircraft.inputs.L0_fuselage.count', - # other - 'aircraft.cached.L0_fuselage.count', - ] - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.NFUSE', 'EDETIN.NFUSE', '~WWGHT.NFUSE'], + 'FLOPS': 'WTIN.NFUSE', + 'LEAPS1': [ + 'aircraft.inputs.L0_fuselage.count', + # other + 'aircraft.cached.L0_fuselage.count', + ], + }, units='unitless', desc='number of fuselages', types=int, @@ -3287,29 +3636,17 @@ default_value=1, ) -add_meta_data( - Aircraft.Fuselage.NUM_SEATS_ABREAST, - meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SAB', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", - desc='seats abreast in fuselage', - types=int, - option=True, - default_value=6, -) - add_meta_data( Aircraft.Fuselage.PASSENGER_COMPARTMENT_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.XLP', # ['&DEFINE.WTIN.XLP', 'WTS.XLP'], - "LEAPS1": ['aircraft.inputs.L0_fuselage.passenger_compartment_length', - 'aircraft.cached.L0_fuselage.passenger_compartment_length', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.XLP', # ['&DEFINE.WTIN.XLP', 'WTS.XLP'], + 'LEAPS1': [ + 'aircraft.inputs.L0_fuselage.passenger_compartment_length', + 'aircraft.cached.L0_fuselage.passenger_compartment_length', + ], + }, units='ft', desc='length of passenger compartment', default_value=0.0, @@ -3318,73 +3655,70 @@ add_meta_data( Aircraft.Fuselage.PILOT_COMPARTMENT_LENGTH, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ELPC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.ELPC', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='length of the pilot compartment', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.PLANFORM_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WEIGHT.FPAREA', - "LEAPS1": '(WeightABC)self._fuselage_planform_area' - }, + historical_name={ + 'GASP': 'SPF_BODY', + 'FLOPS': None, # '~WEIGHT.FPAREA', + 'LEAPS1': '(WeightABC)self._fuselage_planform_area', + }, units='ft**2', - desc='fuselage planform area' + desc='fuselage planform area', + default_value=0.0, ) add_meta_data( Aircraft.Fuselage.PRESSURE_DIFFERENTIAL, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELP', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELP', 'FLOPS': None, 'LEAPS1': None}, units='psi', desc='fuselage pressure differential during cruise', - default_value=7.5, + default_value=0.0, ) add_meta_data( - Aircraft.Fuselage.SEAT_PITCH, + Aircraft.Fuselage.PRESSURIZED_WIDTH_ADDITIONAL, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.PS', - "FLOPS": None, - "LEAPS1": None - }, - units='inch', - desc='pitch of the economy class seats', - option=True, - default_value=29, + historical_name={'GASP': 'INGASP.WPRFUS', 'FLOPS': None, 'LEAPS1': None}, + units='ft', + default_value=0.0, + desc='additional pressurized fuselage width for cargo bay', ) add_meta_data( Aircraft.Fuselage.SEAT_WIDTH, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WS', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WS', 'FLOPS': None, 'LEAPS1': None}, units='inch', desc='width of the economy class seats', option=True, - default_value=20, + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuselage.SIMPLE_LAYOUT, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='carry out simple or detailed layout of fuselage.', + option=True, + default_value=True, ) add_meta_data( Aircraft.Fuselage.TAIL_FINENESS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ELODT', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.ELODT', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='length to diameter ratio of tail cone', - default_value=1, + default_value=1.0, ) add_meta_data( @@ -3392,27 +3726,38 @@ # - see also: Aircraft.Fuselage.WETTED_AREA_SCALER Aircraft.Fuselage.WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SF', - "FLOPS": None, # ['ACTWET.SWTFU', 'MISSA.SWET[4]'], - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.fuselage_wetted_area', - 'aircraft.outputs.L0_aerodynamics' - '.mission_component_wetted_area_table[3]', - 'aircraft.cached.L0_aerodynamics' - '.mission_component_wetted_area_table[3]', - ] - }, + historical_name={ + 'GASP': 'INGASP.SF', + 'FLOPS': None, # ['ACTWET.SWTFU', 'MISSA.SWET[4]'], + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.fuselage_wetted_area', + 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[3]', + 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[3]', + ], + }, units='ft**2', desc='fuselage wetted area', - default_value=None, + default_value=0.0, +) + +add_meta_data( + Aircraft.Fuselage.WETTED_AREA_RATIO_AFTBODY_TO_TOTAL, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.SAFTqS', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + types=float, + default_value=0.0, + desc='aftbody wetted area to total body wetted area', ) add_meta_data( Aircraft.Fuselage.WETTED_AREA_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SF_FAC', - "FLOPS": 'AERIN.SWETF', # ['&DEFINE.AERIN.SWETF', 'AWETO.SWETF', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.fuselage_wetted_area' - }, + historical_name={ + 'GASP': 'INGASP.SF_FAC', + 'FLOPS': 'AERIN.SWETF', # ['&DEFINE.AERIN.SWETF', 'AWETO.SWETF', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.fuselage_wetted_area', + }, units='unitless', desc='fuselage wetted area scaler', default_value=1.0, @@ -3429,85 +3774,91 @@ add_meta_data( Aircraft.HorizontalTail.AREA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SHT', - "FLOPS": 'WTIN.SHT', # ['&DEFINE.WTIN.SHT', 'EDETIN.SHT'], - "LEAPS1": ['aircraft.inputs.L0_horizontal_tail.area', - 'aircraft.cached.L0_horizontal_tail.area', - ] - }, + historical_name={ + 'GASP': 'INGASP.SHT', # not an input in GASP + 'FLOPS': 'WTIN.SHT', # ['&DEFINE.WTIN.SHT', 'EDETIN.SHT'], + 'LEAPS1': [ + 'aircraft.inputs.L0_horizontal_tail.area', + 'aircraft.cached.L0_horizontal_tail.area', + ], + }, units='ft**2', desc='horizontal tail theoretical area; overridden by vol_coeff, if ' - 'vol_coeff > 0.0', # this appears to never be calculated in Aviary, need to show users the overriding capability of Aviary + 'vol_coeff > 0.0', # TODO: this appears to never be calculated in Aviary, need to show users the overriding capability of Aviary default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.ASPECT_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ARHT', - "FLOPS": 'WTIN.ARHT', # ['&DEFINE.WTIN.ARHT', 'EDETIN.ARHT'], - "LEAPS1": 'aircraft.inputs.L0_horizontal_tail.aspect_ratio' - }, + historical_name={ + 'GASP': 'INGASP.ARHT', + 'FLOPS': 'WTIN.ARHT', # ['&DEFINE.WTIN.ARHT', 'EDETIN.ARHT'], + 'LEAPS1': 'aircraft.inputs.L0_horizontal_tail.aspect_ratio', + }, units='unitless', desc='horizontal tail theoretical aspect ratio', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.AVERAGE_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CBARHT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CBARHT', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='mean aerodynamic chord of horizontal tail', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.CHARACTERISTIC_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.EL[2]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[1]', - 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[1]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.EL[2]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[1]', + 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[1]', + ], + }, units='ft', - desc='Reynolds characteristic length for the horizontal tail' + desc='Reynolds characteristic length for the horizontal tail', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.FINENESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.FR[2]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[1]', - 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[1]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.FR[2]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[1]', + 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[1]', + ], + }, units='unitless', - desc='horizontal tail fineness ratio' + desc='horizontal tail fineness ratio', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.FORM_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKHT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CKHT', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='horizontal tail form factor', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.LAMINAR_FLOW_LOWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRLH', # ['&DEFINE.AERIN.TRLH', 'XLAM.TRLH', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.horizontal_tail_percent_laminar_flow_lower_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRLH', # ['&DEFINE.AERIN.TRLH', 'XLAM.TRLH', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.horizontal_tail_percent_laminar_flow_lower_surface', + }, units='unitless', desc='define percent laminar flow for horizontal tail lower surface', default_value=0.0, @@ -3516,10 +3867,11 @@ add_meta_data( Aircraft.HorizontalTail.LAMINAR_FLOW_UPPER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRUH', # ['&DEFINE.AERIN.TRUH', 'XLAM.TRUH', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.horizontal_tail_percent_laminar_flow_upper_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRUH', # ['&DEFINE.AERIN.TRUH', 'XLAM.TRUH', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.horizontal_tail_percent_laminar_flow_upper_surface', + }, units='unitless', desc='define percent laminar flow for horizontal tail upper surface', default_value=0.0, @@ -3530,37 +3882,37 @@ # - see also: Aircraft.HorizontalTail.MASS_SCALER Aircraft.HorizontalTail.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(2, 2)', '~WEIGHT.WHT', '~WTSTAT.WSP(2, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._horizontal_tail_weight', - 'aircraft.outputs.L0_weights_summary.horizontal_tail_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(2, 2)', '~WEIGHT.WHT', '~WTSTAT.WSP(2, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._horizontal_tail_weight', + 'aircraft.outputs.L0_weights_summary.horizontal_tail_weight', + ], + }, units='lbm', desc='mass of horizontal tail', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKY', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKY', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of horizontal tail', - default_value=.18, + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRHT', # ['&DEFINE.WTIN.FRHT', 'WTS.FRHT'], - "LEAPS1": 'aircraft.inputs.L0_overrides.horizontal_tail_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRHT', # ['&DEFINE.WTIN.FRHT', 'WTS.FRHT'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.horizontal_tail_weight', + }, units='unitless', desc='mass scaler of the horizontal tail structure', default_value=1.0, @@ -3569,21 +3921,16 @@ add_meta_data( Aircraft.HorizontalTail.MOMENT_ARM, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ELTH', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.ELTH', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='moment arm of horizontal tail', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.MOMENT_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.COELTH', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.COELTH', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='Ratio of wing chord to horizontal tail moment arm', ) @@ -3591,57 +3938,58 @@ add_meta_data( Aircraft.HorizontalTail.ROOT_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CRCLHT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CRCLHT', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='horizontal tail root chord', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.SPAN, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.BHT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.BHT', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='span of horizontal tail', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.SWEEP, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DWPQCH', - "FLOPS": 'WTIN.SWPHT', # , 'WTS.SWPHT'], - "LEAPS1": ['aircraft.inputs.L0_horizontal_tail.sweep_at_quarter_chord', - 'aircraft.cached.L0_horizontal_tail.sweep_at_quarter_chord' - ] - }, + historical_name={ + 'GASP': 'INGASP.DWPQCH', + 'FLOPS': 'WTIN.SWPHT', # , 'WTS.SWPHT'], + 'LEAPS1': [ + 'aircraft.inputs.L0_horizontal_tail.sweep_at_quarter_chord', + 'aircraft.cached.L0_horizontal_tail.sweep_at_quarter_chord', + ], + }, units='deg', desc='quarter-chord sweep of horizontal tail', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.TAPER_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SLMH', - "FLOPS": 'WTIN.TRHT', # , 'EDETIN.TRHT'], - "LEAPS1": 'aircraft.inputs.L0_horizontal_tail.taper_ratio' - }, + historical_name={ + 'GASP': 'INGASP.SLMH', + 'FLOPS': 'WTIN.TRHT', # , 'EDETIN.TRHT'], + 'LEAPS1': 'aircraft.inputs.L0_horizontal_tail.taper_ratio', + }, units='unitless', desc='horizontal tail theoretical taper ratio', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.THICKNESS_TO_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.TCHT', - "FLOPS": 'WTIN.TCHT', # , 'EDETIN.TCHT'], - "LEAPS1": 'aircraft.inputs.L0_horizontal_tail.thickness_to_chord_ratio' - }, + historical_name={ + 'GASP': 'INGASP.TCHT', + 'FLOPS': 'WTIN.TCHT', # , 'EDETIN.TCHT'], + 'LEAPS1': 'aircraft.inputs.L0_horizontal_tail.thickness_to_chord_ratio', + }, units='unitless', desc='horizontal tail thickness-chord ratio', default_value=0.0, @@ -3651,26 +3999,24 @@ add_meta_data( Aircraft.HorizontalTail.VERTICAL_TAIL_FRACTION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SAH', - "FLOPS": 'WTIN.HHT', # ['&DEFINE.WTIN.HHT', 'EDETIN.HHT'], - "LEAPS1": 'aircraft.inputs.L0_horizontal_tail.vertical_tail_fraction' - }, + historical_name={ + 'GASP': 'INGASP.SAH', + 'FLOPS': 'WTIN.HHT', # ['&DEFINE.WTIN.HHT', 'EDETIN.HHT'], + 'LEAPS1': 'aircraft.inputs.L0_horizontal_tail.vertical_tail_fraction', + }, units='unitless', desc='Define the decimal fraction of vertical tail span where horizontal ' - 'tail is mounted. Defaults: 0.0 == for body mounted (default for ' - 'transport with all engines on wing); 1.0 == for T tail ' - '(default for transport with multiple engines on fuselage)', - default_value=None, + 'tail is mounted. Defaults: 0.0 == for body mounted (default for ' + 'transport with all engines on wing); 1.0 == for T tail ' + '(default for transport with multiple engines on fuselage)', + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.VOLUME_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.VBARHX', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.VBARHX', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='tail volume coefficicient of horizontal tail', ) @@ -3679,27 +4025,28 @@ # - see also: Aircraft.HorizontalTail.WETTED_AREA_SCALER Aircraft.HorizontalTail.WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['ACTWET.SWTHT', 'MISSA.SWET[2]'], - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.horizontal_tail_wetted_area', - 'aircraft.outputs.L0_aerodynamics' - '.mission_component_wetted_area_table[1]', - 'aircraft.cached.L0_aerodynamics' - '.mission_component_wetted_area_table[1]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['ACTWET.SWTHT', 'MISSA.SWET[2]'], + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.horizontal_tail_wetted_area', + 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[1]', + 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[1]', + ], + }, units='ft**2', desc='horizontal tail wetted area', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.HorizontalTail.WETTED_AREA_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.SWETH', # ['&DEFINE.AERIN.SWETH', 'AWETO.SWETH', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.horizontal_tail_wetted_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.SWETH', # ['&DEFINE.AERIN.SWETH', 'AWETO.SWETH', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.horizontal_tail_wetted_area', + }, units='unitless', desc='horizontal tail wetted area scaler', default_value=1.0, @@ -3718,25 +4065,19 @@ add_meta_data( Aircraft.Hydraulics.FLIGHT_CONTROL_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(3)', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CW(3)', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='mass trend coefficient of hydraulics for flight control system', - default_value=0.10, + default_value=0.0, ) add_meta_data( Aircraft.Hydraulics.GEAR_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(4)', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CW(4)', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='mass trend coefficient of hydraulics for landing gear', - default_value=0.16, + default_value=0.0, ) add_meta_data( @@ -3744,26 +4085,29 @@ # - see also: Aircraft.Hydraulics.MASS_SCALER Aircraft.Hydraulics.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(19, 2)', '~WEIGHT.WHYD', '~WTSTAT.WSP(19, 2)', '~INERT.WHYD'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._hydraulics_group_weight', - 'aircraft.outputs.L0_weights_summary.hydraulics_group_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(19, 2)', '~WEIGHT.WHYD', '~WTSTAT.WSP(19, 2)', '~INERT.WHYD'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._hydraulics_group_weight', + 'aircraft.outputs.L0_weights_summary.hydraulics_group_weight', + ], + }, units='lbm', desc='mass of hydraulic system', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Hydraulics.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WHYD', 'MISWT.WHYD', 'MISWT.OHYD'], - "FLOPS": 'WTIN.WHYD', - "LEAPS1": 'aircraft.inputs.L0_overrides.hydraulics_group_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WHYD', 'MISWT.WHYD', 'MISWT.OHYD'], + 'FLOPS': 'WTIN.WHYD', + 'LEAPS1': 'aircraft.inputs.L0_overrides.hydraulics_group_weight', + }, units='unitless', desc='mass scaler of the hydraulic system', default_value=1.0, @@ -3772,13 +4116,14 @@ add_meta_data( Aircraft.Hydraulics.SYSTEM_PRESSURE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.HYDPR', # ['&DEFINE.WTIN.HYDPR', 'WTS.HYDPR'], - "LEAPS1": 'aircraft.inputs.L0_weights.hydraulic_sys_press' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.HYDPR', # ['&DEFINE.WTIN.HYDPR', 'WTS.HYDPR'], + 'LEAPS1': 'aircraft.inputs.L0_weights.hydraulic_sys_press', + }, units='psi', desc='hydraulic system pressure', - default_value=3000.0, + default_value=0.0, ) # @@ -3795,38 +4140,38 @@ # - see also: Aircraft.Instruments.MASS_SCALER Aircraft.Instruments.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(18, 2)', '~WEIGHT.WIN', '~WTSTAT.WSP(18, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._instrument_group_weight', - 'aircraft.outputs.L0_weights_summary.instrument_group_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(18, 2)', '~WEIGHT.WIN', '~WTSTAT.WSP(18, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._instrument_group_weight', + 'aircraft.outputs.L0_weights_summary.instrument_group_weight', + ], + }, units='lbm', desc='instrument group mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Instruments.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CW(2)', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CW(2)', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='mass trend coefficient of instruments', - default_value=0.0862, + default_value=0.0, ) add_meta_data( Aircraft.Instruments.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WIN', 'MISWT.WIN', 'MISWT.OIN'], - "FLOPS": 'WTIN.WIN', - "LEAPS1": 'aircraft.inputs.L0_overrides.instrument_group_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WIN', 'MISWT.WIN', 'MISWT.OIN'], + 'FLOPS': 'WTIN.WIN', + 'LEAPS1': 'aircraft.inputs.L0_overrides.instrument_group_weight', + }, units='unitless', desc='mass scaler of the instrument group', default_value=1.0, @@ -3841,23 +4186,6 @@ # __/ | # |___/ # =================================================================================== -# TODO obsolete w/o fighter equations? -add_meta_data( - Aircraft.LandingGear.CARRIER_BASED, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.CARBAS', # ['&DEFINE.WTIN.CARBAS', 'FAWT.CARBAS'], - "LEAPS1": 'aircraft.inputs.L0_landing_gear.carrier_based' - }, - units='unitless', - desc='carrier based aircraft switch, affects mass of flight crew, ' - 'avionics, and nose gear where true is carrier based and false is land ' - 'based', - option=True, - types=bool, - default_value=False, -) - add_meta_data( Aircraft.LandingGear.DRAG_COEFFICIENT, meta_data=_MetaData, @@ -3865,29 +4193,33 @@ # ['&DEFTOL.TOLIN.CDGEAR', '~DEFTOL.CDGEAR', 'ROTDAT.CDGEAR'], 'FLOPS': 'TOLIN.CDGEAR', 'GASP': None, - 'LEAPS1': None}, + 'LEAPS1': None, + }, option=True, - default_value=0., + default_value=0.0, units='unitless', - desc='landing gear drag coefficient') + desc='landing gear drag coefficient', +) add_meta_data( - Aircraft.LandingGear.FIXED_GEAR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.IGEAR', "FLOPS": None, "LEAPS1": None}, - option=True, default_value=True, types=bool, units="unitless", - desc='Type of landing gear. In GASP, 0 is retractable and 1 is deployed (fixed). Here, ' - 'false is retractable and true is deployed (fixed).',) + Aircraft.LandingGear.FIXED_GEAR, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.IGEAR', 'FLOPS': None, 'LEAPS1': None}, + option=True, + default_value=True, + types=bool, + units='unitless', + desc='Type of landing gear. In GASP, 0 is retractable and 1 is fixed. Here, ' + 'false is retractable and true is fixed.', +) add_meta_data( Aircraft.LandingGear.MAIN_GEAR_LOCATION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.YMG', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.YMG', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='span fraction of main gear on wing (0=on fuselage, 1=at tip)', - default_value=0, + default_value=0.0, ) add_meta_data( @@ -3895,33 +4227,33 @@ # - see also: Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER Aircraft.LandingGear.MAIN_GEAR_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'INI.WLGM', - "LEAPS1": '(WeightABC)self._landing_gear_main_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'INI.WLGM', + 'LEAPS1': '(WeightABC)self._landing_gear_main_weight', + }, units='lbm', - desc='mass of main landing gear' + desc='mass of main landing gear (WMG in GASP)', + default_value=0.0, ) add_meta_data( Aircraft.LandingGear.MAIN_GEAR_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKMG', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKMG', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of main gear, fraction of total landing gear', - default_value=.85, + default_value=0.0, ) add_meta_data( Aircraft.LandingGear.MAIN_GEAR_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRLGM', # ['&DEFINE.WTIN.FRLGM', 'WTS.FRLGM'], - "LEAPS1": 'aircraft.inputs.L0_overrides.landing_gear_main_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRLGM', # ['&DEFINE.WTIN.FRLGM', 'WTS.FRLGM'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.landing_gear_main_weight', + }, units='unitless', desc='mass scaler of the main landing gear structure', default_value=1.0, @@ -3930,13 +4262,15 @@ add_meta_data( Aircraft.LandingGear.MAIN_GEAR_OLEO_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.XMLG', # ['&DEFINE.WTIN.XMLG', 'WTS.XMLG'], - "LEAPS1": ['aircraft.inputs.L0_landing_gear.extend_main_gear_oleo_len', - 'aircraft.outputs.L0_landing_gear.extend_main_gear_oleo_len', - 'aircraft.cached.L0_landing_gear.extend_main_gear_oleo_len', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.XMLG', # ['&DEFINE.WTIN.XMLG', 'WTS.XMLG'], + 'LEAPS1': [ + 'aircraft.inputs.L0_landing_gear.extend_main_gear_oleo_len', + 'aircraft.outputs.L0_landing_gear.extend_main_gear_oleo_len', + 'aircraft.cached.L0_landing_gear.extend_main_gear_oleo_len', + ], + }, units='inch', desc='length of extended main landing gear oleo', default_value=0.0, @@ -3945,12 +4279,10 @@ add_meta_data( Aircraft.LandingGear.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKLG', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKLG', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of landing gear', + default_value=0.0, ) add_meta_data( @@ -3958,22 +4290,24 @@ # - see also: Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER Aircraft.LandingGear.NOSE_GEAR_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WEIGHT.WLGN', - "LEAPS1": '(WeightABC)self._landing_gear_nose_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WEIGHT.WLGN', + 'LEAPS1': '(WeightABC)self._landing_gear_nose_weight', + }, units='lbm', desc='mass of nose landing gear', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.LandingGear.NOSE_GEAR_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRLGN', # ['&DEFINE.WTIN.FRLGN', 'WTS.FRLGN'], - "LEAPS1": 'aircraft.inputs.L0_overrides.landing_gear_nose_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRLGN', # ['&DEFINE.WTIN.FRLGN', 'WTS.FRLGN'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.landing_gear_nose_weight', + }, units='unitless', desc='mass scaler of the nose landing gear structure', default_value=1.0, @@ -3982,13 +4316,15 @@ add_meta_data( Aircraft.LandingGear.NOSE_GEAR_OLEO_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.XNLG', # ['&DEFINE.WTIN.XNLG', 'WTS.XNLG'], - "LEAPS1": ['aircraft.inputs.L0_landing_gear.extend_nose_gear_oleo_len', - 'aircraft.outputs.L0_landing_gear.extend_nose_gear_oleo_len', - 'aircraft.cached.L0_landing_gear.extend_nose_gear_oleo_len', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.XNLG', # ['&DEFINE.WTIN.XNLG', 'WTS.XNLG'], + 'LEAPS1': [ + 'aircraft.inputs.L0_landing_gear.extend_nose_gear_oleo_len', + 'aircraft.outputs.L0_landing_gear.extend_nose_gear_oleo_len', + 'aircraft.cached.L0_landing_gear.extend_nose_gear_oleo_len', + ], + }, units='inch', desc='length of extended nose landing gear oleo', default_value=0.0, @@ -3997,11 +4333,8 @@ add_meta_data( Aircraft.LandingGear.TAIL_HOOK_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKTL', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKTL', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='factor on tail mass for arresting hook', default_value=1, ) @@ -4009,25 +4342,19 @@ add_meta_data( Aircraft.LandingGear.TOTAL_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WLG', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WLG', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='total mass of landing gear', - default_value=0, + default_value=0.0, ) add_meta_data( Aircraft.LandingGear.TOTAL_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CK12', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.CK12', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='technology factor on landing gear mass', - default_value=1, + default_value=1.0, ) # _ _ _ _ @@ -4041,12 +4368,15 @@ add_meta_data( Aircraft.Nacelle.AVG_DIAMETER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DBARN', - "FLOPS": 'WTIN.DNAC', # ['&DEFINE.WTIN.DNAC', 'EDETIN.DNAC'], - "LEAPS1": 'aircraft.inputs.L0_engine.nacelle_avg_diam' - }, + historical_name={ + 'GASP': 'INGASP.DBARN', + 'FLOPS': 'WTIN.DNAC', # ['&DEFINE.WTIN.DNAC', 'EDETIN.DNAC'], + 'LEAPS1': 'aircraft.inputs.L0_engine.nacelle_avg_diam', + }, units='ft', - desc='Average diameter of engine nacelles for each engine model' + desc='Average diameter of engine nacelles for each engine model', + default_value=0.0, + multivalue=True, ) add_meta_data( @@ -4054,97 +4384,107 @@ meta_data=_MetaData, # NOTE this is not specified as an average in GASP, but calculations make # it appear to be one - historical_name={"GASP": 'INGASP.ELN', - "FLOPS": 'WTIN.XNAC', # ['&DEFINE.WTIN.XNAC', 'EDETIN.XNAC'], - "LEAPS1": 'aircraft.inputs.L0_engine.nacelle_avg_length' - }, + historical_name={ + 'GASP': 'INGASP.ELN', + 'FLOPS': 'WTIN.XNAC', # ['&DEFINE.WTIN.XNAC', 'EDETIN.XNAC'], + 'LEAPS1': 'aircraft.inputs.L0_engine.nacelle_avg_length', + }, units='ft', - desc='Average length of nacelles for each engine model' + desc='Average length of nacelles for each engine model', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.CHARACTERISTIC_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.EL[5]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[4]', - 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[4]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.EL[5]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[4]', + 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[4]', + ], + }, units='ft', - desc='Reynolds characteristic length for nacelle for each engine model' + desc='Reynolds characteristic length for nacelle for each engine model', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.CLEARANCE_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CLEARqDN', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.CLEARqDN', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='the minimum number of nacelle diameters above the ground that the bottom of the nacelle must be', - default_value=0.2, + default_value=0.0, # should be at least 0.2 + multivalue=True, ) add_meta_data( Aircraft.Nacelle.CORE_DIAMETER_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DNQDE', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.DNQDE', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='ratio of nacelle diameter to engine core diameter', default_value=1.25, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.FINENESS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.XLQDE', - "FLOPS": None, # 'MISSA.FR[5]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[4]', - 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[4]', - ] - }, + historical_name={ + 'GASP': 'INGASP.XLQDE', + 'FLOPS': None, # 'MISSA.FR[5]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[4]', + 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[4]', + ], + }, units='unitless', - desc='nacelle fineness ratio' + desc='nacelle fineness ratio', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.FORM_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKN', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CKN', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='nacelle form factor', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.LAMINAR_FLOW_LOWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRLN', # ['&DEFINE.AERIN.TRLN', 'XLAM.TRLN', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.nacelle_percent_laminar_flow_lower_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRLN', # ['&DEFINE.AERIN.TRLN', 'XLAM.TRLN', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.nacelle_percent_laminar_flow_lower_surface', + }, units='unitless', desc='define percent laminar flow for nacelle lower surface for each engine model', default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.LAMINAR_FLOW_UPPER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRUN', # ['&DEFINE.AERIN.TRUN', 'XLAM.TRUN', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.nacelle_percent_laminar_flow_upper_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRUN', # ['&DEFINE.AERIN.TRUN', 'XLAM.TRUN', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.nacelle_percent_laminar_flow_upper_surface', + }, units='unitless', desc='define percent laminar flow for nacelle upper surface for each engine model', default_value=0.0, + multivalue=True, ) add_meta_data( @@ -4152,88 +4492,107 @@ # - see also: Aircraft.Nacelle.MASS_SCALER Aircraft.Nacelle.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(8, 2)', '~WEIGHT.WNAC', '~WTSTAT.WSP(8, 2)', '~INERT.WNAC'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._nacelle_weight', - 'aircraft.outputs.L0_weights_summary.nacelle_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(8, 2)', '~WEIGHT.WNAC', '~WTSTAT.WSP(8, 2)', '~INERT.WNAC'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._nacelle_weight', + 'aircraft.outputs.L0_weights_summary.nacelle_weight', + ], + }, units='lbm', desc='estimated mass of the nacelles for each engine model', - default_value=None, + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRNA', # ['&DEFINE.WTIN.FRNA', 'WTS.FRNA'], - "LEAPS1": 'aircraft.inputs.L0_overrides.nacelle_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRNA', # ['&DEFINE.WTIN.FRNA', 'WTS.FRNA'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.nacelle_weight', + }, units='unitless', desc='mass scaler of the nacelle structure for each engine model', default_value=1.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.MASS_SPECIFIC, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.UWNAC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.UWNAC', 'FLOPS': None, 'LEAPS1': None}, units='lbm/ft**2', desc='nacelle mass/nacelle surface area; lbm per sq ft.', default_value=0.0, + multivalue=True, +) + +add_meta_data( + Aircraft.Nacelle.PERCENT_DIAM_BURIED_IN_FUSELAGE, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.HEBQDN', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='percentage of nacelle diameter buried in fuselage over nacelle diameter', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.SURFACE_AREA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SN', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.SN', 'FLOPS': None, 'LEAPS1': None}, # SN is wetted area units='ft**2', - desc='surface area of the outside of one entire nacelle, ' - 'not just the wetted area', + desc='surface area of the outside of one entire nacelle, not just the wetted area', + multivalue=True, ) add_meta_data( Aircraft.Nacelle.TOTAL_WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'ACTWET.SWTNA', - "LEAPS1": 'aircraft.outputs.L0_aerodynamics.nacelle_wetted_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'ACTWET.SWTNA', + 'LEAPS1': 'aircraft.outputs.L0_aerodynamics.nacelle_wetted_area', + }, units='ft**2', - desc='total nacelles wetted area' + desc='total nacelles wetted area', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.SWET[5]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[4]', - 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[4]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.SWET[5]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[4]', + 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[4]', + ], + }, units='ft**2', - desc='wetted area of a single nacelle for each engine model' + desc='wetted area of a single nacelle for each engine model', + default_value=0.0, + multivalue=True, ) add_meta_data( Aircraft.Nacelle.WETTED_AREA_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.SWETN', # ['&DEFINE.AERIN.SWETN', 'AWETO.SWETN', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.nacelle_wetted_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.SWETN', # ['&DEFINE.AERIN.SWETN', 'AWETO.SWETN', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.nacelle_wetted_area', + }, units='unitless', desc='nacelle wetted area scaler for each engine model', - default_value=1.0 + default_value=1.0, + multivalue=True, ) # _____ _ _ @@ -4247,23 +4606,27 @@ add_meta_data( Aircraft.Paint.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'DARM.WTPNT', - "LEAPS1": ['(WeightABC)self._total_paint_weight', - 'aircraft.outputs.L0_weights_summary.total_paint_weight', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'DARM.WTPNT', + 'LEAPS1': [ + '(WeightABC)self._total_paint_weight', + 'aircraft.outputs.L0_weights_summary.total_paint_weight', + ], + }, units='lbm', - desc='mass of paint for all wetted area' + desc='mass of paint for all wetted area', + default_value=0.0, ) add_meta_data( Aircraft.Paint.MASS_PER_UNIT_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.WPAINT', # ['&DEFINE.WTIN.WPAINT', 'DARM.WPAINT'], - "LEAPS1": 'aircraft.inputs.L0_weights.paint_per_unit_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.WPAINT', # ['&DEFINE.WTIN.WPAINT', 'DARM.WPAINT'], + 'LEAPS1': 'aircraft.inputs.L0_weights.paint_per_unit_area', + }, units='lbm/ft**2', desc='mass of paint per unit area for all wetted area', default_value=0.0, @@ -4283,11 +4646,12 @@ add_meta_data( Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WOIL', 'MISWT.WOIL', 'MISWT.OOIL'], - "FLOPS": 'WTIN.WOIL', - "LEAPS1": 'aircraft.inputs.L0_overrides.engine_oil_weight' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WOIL', 'MISWT.WOIL', 'MISWT.OOIL'], + 'FLOPS': 'WTIN.WOIL', + 'LEAPS1': 'aircraft.inputs.L0_overrides.engine_oil_weight', + }, units='unitless', desc='Scaler for engine oil mass', default_value=1.0, @@ -4296,52 +4660,52 @@ add_meta_data( Aircraft.Propulsion.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(15, 2)', '~WEIGHT.WPRO', '~WTSTAT.WSP(15, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._prop_sys_weight', - 'aircraft.outputs.L0_weights_summary.prop_sys_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(15, 2)', '~WEIGHT.WPRO', '~WTSTAT.WSP(15, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._prop_sys_weight', + 'aircraft.outputs.L0_weights_summary.prop_sys_weight', + ], + }, units='lbm', - desc='Total propulsion group mass' + desc='Total propulsion group mass', + default_value=0.0, ) # TODO clash with per-engine scaling, need to resolve w/ heterogeneous engine add_meta_data( Aircraft.Propulsion.MISC_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.WPMSC', 'MISWT.WPMSC', 'MISWT.OPMSC'], - "FLOPS": 'WTIN.WPMSC', - "LEAPS1": ['aircraft.inputs.L0_overrides.misc_propulsion_weight'] - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.WPMSC', 'MISWT.WPMSC', 'MISWT.OPMSC'], + 'FLOPS': 'WTIN.WPMSC', + 'LEAPS1': ['aircraft.inputs.L0_overrides.misc_propulsion_weight'], + }, units='unitless', desc='scaler applied to miscellaneous engine mass (sum of engine control, starter, ' - 'and additional mass)', + 'and additional mass)', default_value=1.0, ) add_meta_data( Aircraft.Propulsion.TOTAL_ENGINE_CONTROLS_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='total estimated mass of the engine controls for all engines on aircraft' + desc='total estimated mass of the engine controls for all engines on aircraft', + default_value=0.0, ) add_meta_data( Aircraft.Propulsion.TOTAL_ENGINE_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WEP', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WEP', 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='total mass of all engines on aircraft' + desc='total mass of all engines on aircraft', + default_value=0.0, ) add_meta_data( @@ -4349,27 +4713,27 @@ # - see also: Aircraft.Propulsion.ENGINE_OIL_MASS_SCALER Aircraft.Propulsion.TOTAL_ENGINE_OIL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(30, 2)', '~WEIGHT.WOIL', '~WTSTAT.WSP(30, 2)', '~INERT.WOIL'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._engine_oil_weight', - 'aircraft.outputs.L0_weights_summary.engine_oil_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(30, 2)', '~WEIGHT.WOIL', '~WTSTAT.WSP(30, 2)', '~INERT.WOIL'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._engine_oil_weight', + 'aircraft.outputs.L0_weights_summary.engine_oil_weight', + ], + }, units='lbm', desc='engine oil mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Propulsion.TOTAL_ENGINE_POD_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='total engine pod mass for all engines on aircraft' + desc='total engine pod mass for all engines on aircraft', + default_value=0.0, ) add_meta_data( @@ -4377,79 +4741,59 @@ # - see also: Aircraft.Propulsion.MISC_WEIGHT_SCALER Aircraft.Propulsion.TOTAL_MISC_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='sum of engine control, starter, and additional mass for all engines ' - 'on aircraft', - default_value=None, + desc='sum of engine control, starter, and additional mass for all engines on aircraft', + default_value=0.0, ) add_meta_data( Aircraft.Propulsion.TOTAL_NUM_ENGINES, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc='total number of engines for the aircraft ' - '(fuselage, wing, or otherwise)', + desc='total number of engines for the aircraft (fuselage, wing, or otherwise)', types=int, option=True, - default_value=None, + default_value=0, ) add_meta_data( Aircraft.Propulsion.TOTAL_NUM_FUSELAGE_ENGINES, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='total number of fuselage-mounted engines for the aircraft', types=int, option=True, - default_value=None, + default_value=0, ) add_meta_data( Aircraft.Propulsion.TOTAL_NUM_WING_ENGINES, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='total number of wing-mounted engines for the aircraft', types=int, option=True, - default_value=None, + default_value=0, ) add_meta_data( Aircraft.Propulsion.TOTAL_REFERENCE_SLS_THRUST, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf', desc='total maximum thrust of all unscalsed engines on aircraft, sea-level static', option=True, - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Propulsion.TOTAL_SCALED_SLS_THRUST, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf', desc='total maximum thrust of all scaled engines on aircraft, sea-level static', default_value=0.0, @@ -4458,10 +4802,7 @@ add_meta_data( Aircraft.Propulsion.TOTAL_STARTER_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='total mass of starters for all engines on aircraft', default_value=0.0, @@ -4472,13 +4813,10 @@ # - see also: Aircraft.Engine.THRUST_REVERSERS_MASS_SCALER Aircraft.Propulsion.TOTAL_THRUST_REVERSERS_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='total mass of thrust reversers for all engines on aircraft', - default_value=None, + default_value=0.0, ) # _____ _ _ @@ -4492,10 +4830,7 @@ add_meta_data( Aircraft.Strut.AREA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.STRTWS', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.STRTWS', 'FLOPS': None, 'LEAPS1': None}, units='ft**2', desc='strut area', default_value=0, @@ -4504,81 +4839,69 @@ add_meta_data( Aircraft.Strut.AREA_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SSTQSW', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.SSTQSW', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='ratio of strut area to wing area', + default_value=0.0, ) add_meta_data( Aircraft.Strut.ATTACHMENT_LOCATION, meta_data=_MetaData, - historical_name={"GASP": ['INGASP.STRUT', 'INGASP.STRUTX', 'INGASP.XSTRUT'], - "FLOPS": None, - "LEAPS1": None - }, + historical_name={ + 'GASP': ['INGASP.STRUT', 'INGASP.STRUTX', 'INGASP.XSTRUT'], + 'FLOPS': None, + 'LEAPS1': None, + }, units='ft', desc='attachment location of strut the full attachment-to-attachment span', + default_value=0.0, ) # related to Aircraft.Strut.ATTACHMENT_LOCATION add_meta_data( Aircraft.Strut.ATTACHMENT_LOCATION_DIMENSIONLESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='attachment location of strut as fraction of the half-span', + default_value=0.0, ) add_meta_data( Aircraft.Strut.CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.STRTCHD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.STRTCHD', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='chord of the strut', + default_value=0.0, ) add_meta_data( Aircraft.Strut.DIMENSIONAL_LOCATION_SPECIFIED, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', option=True, default_value=True, types=bool, desc='if true the location of the strut is given dimensionally, otherwise ' - 'it is given non-dimensionally. In GASP this depended on STRUT', + 'it is given non-dimensionally. In GASP this depended on STRUT', ) add_meta_data( Aircraft.Strut.FUSELAGE_INTERFERENCE_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKSTRT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CKSTRT', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='strut/fuselage interference factor', + default_value=0.0, ) add_meta_data( Aircraft.Strut.LENGTH, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.STRTLNG', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.STRTLNG', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='length of the strut', default_value=0, @@ -4587,10 +4910,7 @@ add_meta_data( Aircraft.Strut.MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WSTRUT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WSTRUT', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of the strut', default_value=0, @@ -4599,11 +4919,8 @@ add_meta_data( Aircraft.Strut.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKSTRUT', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKSTRUT', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of the strut', default_value=0, ) @@ -4611,11 +4928,8 @@ add_meta_data( Aircraft.Strut.THICKNESS_TO_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.TCSTRT', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.TCSTRT', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='thickness to chord ratio of the strut', default_value=0, ) @@ -4629,14 +4943,13 @@ # =================================== add_meta_data( - Aircraft.TailBoom.LENGTH, + Aircraft.TailBoom.LENGTH, # tail boom support is not included. meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ELFFC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.ELFFC', 'FLOPS': None, 'LEAPS1': None}, units='ft', + # tail boom support is not implemented yet. desc='cabin length for the tail boom fuselage', + default_value=0.0, ) @@ -4651,15 +4964,16 @@ add_meta_data( Aircraft.VerticalTail.AREA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SVT', - "FLOPS": 'WTIN.SVT', # ['&DEFINE.WTIN.SVT', 'EDETIN.SVT'], - "LEAPS1": ['aircraft.inputs.L0_vertical_tails.area', - 'aircraft.cached.L0_vertical_tails.area', - ] - }, + historical_name={ + 'GASP': 'INGASP.SVT', # not an input in GASP + 'FLOPS': 'WTIN.SVT', # ['&DEFINE.WTIN.SVT', 'EDETIN.SVT'], + 'LEAPS1': [ + 'aircraft.inputs.L0_vertical_tails.area', + 'aircraft.cached.L0_vertical_tails.area', + ], + }, units='ft**2', - desc='vertical tail theoretical area (per tail); overridden by vol_coeff ' - 'if vol_coeff > 0.0', + desc='vertical tail theoretical area (per tail); overridden by vol_coeff if vol_coeff > 0.0', # this appears to never be calculated in Aviary, need to make user aware # of Aviary overriding support default_value=0.0, @@ -4668,73 +4982,78 @@ add_meta_data( Aircraft.VerticalTail.ASPECT_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ARVT', - "FLOPS": 'WTIN.ARVT', # ['&DEFINE.WTIN.ARVT', 'EDETIN.ARVT'], - "LEAPS1": ['aircraft.inputs.L0_vertical_tails.aspect_ratio', - # ??? where is this assigned; potential error??? - 'aircraft.cached.L0_vertical_tails.aspect_ratio', - ] - }, + historical_name={ + 'GASP': 'INGASP.ARVT', + 'FLOPS': 'WTIN.ARVT', # ['&DEFINE.WTIN.ARVT', 'EDETIN.ARVT'], + 'LEAPS1': [ + 'aircraft.inputs.L0_vertical_tails.aspect_ratio', + # ??? where is this assigned; potential error??? + 'aircraft.cached.L0_vertical_tails.aspect_ratio', + ], + }, units='unitless', desc='vertical tail theoretical aspect ratio', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.AVERAGE_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CBARVT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CBARVT', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='mean aerodynamic chord of vertical tail', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.CHARACTERISTIC_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.EL[3]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[2]', - 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[2]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.EL[3]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[2]', + 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[2]', + ], + }, units='ft', - desc='Reynolds characteristic length for the vertical tail' + desc='Reynolds characteristic length for the vertical tail', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.FINENESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.FR[3]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[2]', - 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[2]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.FR[3]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[2]', + 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[2]', + ], + }, units='unitless', - desc='vertical tail fineness ratio' + desc='vertical tail fineness ratio', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.FORM_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKVT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CKVT', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='vertical tail form factor', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.LAMINAR_FLOW_LOWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRLV', # ['&DEFINE.AERIN.TRLV', 'XLAM.TRLV', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.vertical_tail_percent_laminar_flow_lower_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRLV', # ['&DEFINE.AERIN.TRLV', 'XLAM.TRLV', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.vertical_tail_percent_laminar_flow_lower_surface', + }, units='unitless', desc='define percent laminar flow for vertical tail lower surface', default_value=0.0, @@ -4743,10 +5062,11 @@ add_meta_data( Aircraft.VerticalTail.LAMINAR_FLOW_UPPER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRUV', # ['&DEFINE.AERIN.TRUV', 'XLAM.TRUV', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.vertical_tail_percent_laminar_flow_upper_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRUV', # ['&DEFINE.AERIN.TRUV', 'XLAM.TRUV', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.vertical_tail_percent_laminar_flow_upper_surface', + }, units='unitless', desc='define percent laminar flow for vertical tail upper surface', default_value=0.0, @@ -4757,37 +5077,37 @@ # - see also: Aircraft.VerticalTail.MASS_SCALER Aircraft.VerticalTail.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(3, 2)', '~WEIGHT.WVT', '~WTSTAT.WSP(3, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._vertical_tail_weight', - 'aircraft.outputs.L0_weights_summary.vertical_tail_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(3, 2)', '~WEIGHT.WVT', '~WTSTAT.WSP(3, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._vertical_tail_weight', + 'aircraft.outputs.L0_weights_summary.vertical_tail_weight', + ], + }, units='lbm', desc='mass of vertical tail', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKZ', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKZ', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of the vertical tail', - default_value=0.22, + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRVT', # ['&DEFINE.WTIN.FRVT', 'WTS.FRVT'], - "LEAPS1": 'aircraft.inputs.L0_overrides.vertical_tail_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRVT', # ['&DEFINE.WTIN.FRVT', 'WTS.FRVT'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.vertical_tail_weight', + }, units='unitless', desc='mass scaler of the vertical tail structure', default_value=1.0, @@ -4796,32 +5116,28 @@ add_meta_data( Aircraft.VerticalTail.MOMENT_ARM, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ELTV', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.ELTV', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='moment arm of vertical tail', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.MOMENT_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.BOELTV', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.BOELTV', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='ratio of wing span to vertical tail moment arm', ) add_meta_data( Aircraft.VerticalTail.NUM_TAILS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.NVERT', # ['&DEFINE.WTIN.NVERT', 'EDETIN.NVERT'], - "LEAPS1": 'aircraft.inputs.L0_vertical_tails.count' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.NVERT', # ['&DEFINE.WTIN.NVERT', 'EDETIN.NVERT'], + 'LEAPS1': 'aircraft.inputs.L0_vertical_tails.count', + }, units='unitless', desc='number of vertical tails', types=int, @@ -4832,59 +5148,61 @@ add_meta_data( Aircraft.VerticalTail.ROOT_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CRCLVT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CRCLVT', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='root chord of vertical tail', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.SPAN, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.BVT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.BVT', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='span of vertical tail', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.SWEEP, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DWPQCV', - "FLOPS": 'WTIN.SWPVT', # ['&DEFINE.WTIN.SWPVT', 'WTS.SWPVT'], - "LEAPS1": ['aircraft.inputs.L0_vertical_tail.sweep_at_quarter_chord', - 'aircraft.cached.L0_vertical_tail.sweep_at_quarter_chord' - ] - }, + historical_name={ + 'GASP': 'INGASP.DWPQCV', + 'FLOPS': 'WTIN.SWPVT', # ['&DEFINE.WTIN.SWPVT', 'WTS.SWPVT'], + 'LEAPS1': [ + 'aircraft.inputs.L0_vertical_tail.sweep_at_quarter_chord', + 'aircraft.cached.L0_vertical_tail.sweep_at_quarter_chord', + ], + }, units='deg', desc='quarter-chord sweep of vertical tail', + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.TAPER_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SLMV', - "FLOPS": 'WTIN.TRVT', # ['&DEFINE.WTIN.TRVT', 'EDETIN.TRVT'], - "LEAPS1": 'aircraft.inputs.L0_vertical_tails.taper_ratio' - }, + historical_name={ + 'GASP': 'INGASP.SLMV', + 'FLOPS': 'WTIN.TRVT', # ['&DEFINE.WTIN.TRVT', 'EDETIN.TRVT'], + 'LEAPS1': 'aircraft.inputs.L0_vertical_tails.taper_ratio', + }, units='unitless', desc='vertical tail theoretical taper ratio', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.THICKNESS_TO_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.TCVT', - "FLOPS": 'WTIN.TCVT', # ['&DEFINE.WTIN.TCVT', 'EDETIN.TCVT', ], - "LEAPS1": ['aircraft.inputs.L0_vertical_tails.thickness_to_chord_ratio', - 'aircraft.cached.L0_vertical_tails.thickness_to_chord_ratio', - ] - }, + historical_name={ + 'GASP': 'INGASP.TCVT', + 'FLOPS': 'WTIN.TCVT', # ['&DEFINE.WTIN.TCVT', 'EDETIN.TCVT', ], + 'LEAPS1': [ + 'aircraft.inputs.L0_vertical_tails.thickness_to_chord_ratio', + 'aircraft.cached.L0_vertical_tails.thickness_to_chord_ratio', + ], + }, units='unitless', desc='vertical tail thickness-chord ratio', default_value=0.0, @@ -4893,11 +5211,8 @@ add_meta_data( Aircraft.VerticalTail.VOLUME_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.VBARVX', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.VBARVX', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='tail volume coefficient of the vertical tail', ) @@ -4906,25 +5221,28 @@ # - see also: Aircraft.VerticalTail.WETTED_AREA_SCALER Aircraft.VerticalTail.WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['ACTWET.SWTVT', 'MISSA.SWET[3]', ], - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.vertical_tail_wetted_area', - 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[2]', - 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[2]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['ACTWET.SWTVT', 'MISSA.SWET[3]', ], + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.vertical_tail_wetted_area', + 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[2]', + 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[2]', + ], + }, units='ft**2', desc='vertical tails wetted area', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.VerticalTail.WETTED_AREA_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.SWETV', # ['&DEFINE.AERIN.SWETV', 'AWETO.SWETV', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.vertical_tail_wetted_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.SWETV', # ['&DEFINE.AERIN.SWETV', 'AWETO.SWETV', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.vertical_tail_wetted_area', + }, units='unitless', desc='vertical tail wetted area scaler', default_value=1.0, @@ -4943,37 +5261,40 @@ add_meta_data( Aircraft.Wing.AEROELASTIC_TAILORING_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.FAERT', 'WTS.FAERT', '~WWGHT.FAERT', '~BNDMAT.FAERT'], - "FLOPS": 'WTIN.FAERT', - "LEAPS1": 'aircraft.inputs.L0_wing.aeroelastic_fraction' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.FAERT', 'WTS.FAERT', '~WWGHT.FAERT', '~BNDMAT.FAERT'], + 'FLOPS': 'WTIN.FAERT', + 'LEAPS1': 'aircraft.inputs.L0_wing.aeroelastic_fraction', + }, units='unitless', desc='Define the decimal fraction of amount of aeroelastic tailoring used ' - 'in design of wing where: 0.0 == no aeroelastic tailoring; ' - '1.0 == maximum aeroelastic tailoring.', + 'in design of wing where: 0.0 == no aeroelastic tailoring; ' + '1.0 == maximum aeroelastic tailoring.', default_value=0.0, ) add_meta_data( Aircraft.Wing.AIRFOIL_TECHNOLOGY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.AITEK', - # [ # inputs - # '&DEFINE.AERIN.AITEK', 'EDETIN.AITEK', - # # outputs - # 'MISSA.AITEK', 'MISSA.AITEKX', - # ], - "LEAPS1": ['aircraft.inputs.L0_aerodynamics.airfoil', - 'aircraft.outputs.L0_aerodynamics.mission_airfoil', - 'aircraft.cached.L0_aerodynamics.mission_airfoil', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.AITEK', + # [ # inputs + # '&DEFINE.AERIN.AITEK', 'EDETIN.AITEK', + # # outputs + # 'MISSA.AITEK', 'MISSA.AITEKX', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_aerodynamics.airfoil', + 'aircraft.outputs.L0_aerodynamics.mission_airfoil', + 'aircraft.cached.L0_aerodynamics.mission_airfoil', + ], + }, units='unitless', desc='Airfoil technology parameter. Limiting values are: 1.0 represents ' - 'conventional technology wing (Default); 2.0 represents advanced ' - 'technology wing.', + 'conventional technology wing (Default); 2.0 represents advanced ' + 'technology wing.', default_value=1.0, option=True, ) @@ -4981,21 +5302,23 @@ add_meta_data( Aircraft.Wing.AREA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SW', - "FLOPS": 'CONFIN.SW', - # [ # inputs - # '&DEFINE.CONFIN.SW', 'PARVAR.DVD(1,4)', - # # outputs - # 'CONFIG.SW', 'CONFIG.DVA(4)', '~FLOPS.DVA(4)', '~ANALYS.DVA(4)', - # '~TOFF.SW', '~LNDING.SW', '~PROFIL.SW', '~INMDAT.SW', '~WWGHT.SW', - # # other - # 'MISSA.SREF', '~CDCC.SREF', - # ], - "LEAPS1": ['aircraft.inputs.L0_design_variables.wing_ref_area', - 'aircraft.outputs.L0_design_variables.wing_ref_area', - 'aircraft.outputs.L0_design_variables.mission_wing_ref_area', - ] - }, + historical_name={ + 'GASP': 'INGASP.SW', + 'FLOPS': 'CONFIN.SW', + # [ # inputs + # '&DEFINE.CONFIN.SW', 'PARVAR.DVD(1,4)', + # # outputs + # 'CONFIG.SW', 'CONFIG.DVA(4)', '~FLOPS.DVA(4)', '~ANALYS.DVA(4)', + # '~TOFF.SW', '~LNDING.SW', '~PROFIL.SW', '~INMDAT.SW', '~WWGHT.SW', + # # other + # 'MISSA.SREF', '~CDCC.SREF', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_design_variables.wing_ref_area', + 'aircraft.outputs.L0_design_variables.wing_ref_area', + 'aircraft.outputs.L0_design_variables.mission_wing_ref_area', + ], + }, units='ft**2', desc='reference wing area', default_value=0.0, @@ -5004,22 +5327,24 @@ add_meta_data( Aircraft.Wing.ASPECT_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.AR', - "FLOPS": 'CONFIN.AR', - # [ # inputs - # '&DEFINE.CONFIN.AR', 'PARVAR.DVD(1, 2)', '~BUFFET.AR', '~CDPP.AR', - # '~DPREP.ARX', - # # outputs - # 'CONFIG.AR', 'CONFIG.DVA(2)', '~FLOPS.DVA(2)', '~ANALYS.DVA(2)', - # '~TOFF.ARN', '~LNDING.ARN', '~PROFIL.ARN', '~WWGHT.ARN', '~INERT.ARN', - # # other - # 'MISSA.AR', 'MISSA.ARX', '~CDCC.AR', '~CLDESN.AR', '~MDESN.AR', - # ], - "LEAPS1": ['aircraft.inputs.L0_design_variables.wing_aspect_ratio', - 'aircraft.outputs.L0_design_variables.wing_aspect_ratio', - 'aircraft.outputs.L0_design_variables.mission_wing_aspect_ratio', - ] - }, + historical_name={ + 'GASP': 'INGASP.AR', + 'FLOPS': 'CONFIN.AR', + # [ # inputs + # '&DEFINE.CONFIN.AR', 'PARVAR.DVD(1, 2)', '~BUFFET.AR', '~CDPP.AR', + # '~DPREP.ARX', + # # outputs + # 'CONFIG.AR', 'CONFIG.DVA(2)', '~FLOPS.DVA(2)', '~ANALYS.DVA(2)', + # '~TOFF.ARN', '~LNDING.ARN', '~PROFIL.ARN', '~WWGHT.ARN', '~INERT.ARN', + # # other + # 'MISSA.AR', 'MISSA.ARX', '~CDCC.AR', '~CLDESN.AR', '~MDESN.AR', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_design_variables.wing_aspect_ratio', + 'aircraft.outputs.L0_design_variables.wing_aspect_ratio', + 'aircraft.outputs.L0_design_variables.mission_wing_aspect_ratio', + ], + }, units='unitless', desc='ratio of the wing span to its mean chord', default_value=0.0, @@ -5028,57 +5353,62 @@ add_meta_data( Aircraft.Wing.ASPECT_RATIO_REF, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.ARREF', # ['&DEFINE.WTIN.ARREF'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.ref_aspect_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.ARREF', # ['&DEFINE.WTIN.ARREF'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.ref_aspect_ratio', + }, units='unitless', - desc='Reference aspect ratio, used for detailed wing bending.' + desc='Reference aspect ratio, used for detailed wing mass estimation.', + default_value=0.0, ) add_meta_data( Aircraft.Wing.AVERAGE_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CBARW', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CBARW', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='mean aerodynamic chord of the wing', + default_value=0.0, ) add_meta_data( - Aircraft.Wing.BENDING_FACTOR, + Aircraft.Wing.BENDING_MATERIAL_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['~WWGHT.BT', '~BNDMAT.W'], - "LEAPS1": 'aircraft.outputs.L0_wing.bending_material_factor' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['~WWGHT.BT', '~BNDMAT.W'], + 'LEAPS1': 'aircraft.outputs.L0_wing.bending_material_factor', + }, units='unitless', - desc='wing bending factor' + desc='Wing bending material factor with sweep adjustment. Used to compute ' + 'Aircraft.Wing.BENDING_MATERIAL_MASS', + default_value=0.0, ) add_meta_data( # Note user override - # - see also: Aircraft.Wing.BENDING_MASS_SCALER - Aircraft.Wing.BENDING_MASS, + # - see also: Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER + Aircraft.Wing.BENDING_MATERIAL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WWGHT.W1', - "LEAPS1": 'aircraft.outputs.L0_wing.bending_mat_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WWGHT.W1', + 'LEAPS1': 'aircraft.outputs.L0_wing.bending_mat_weight', + }, units='lbm', desc='wing mass breakdown term 1', - default_value=None, + default_value=0.0, ) add_meta_data( - Aircraft.Wing.BENDING_MASS_SCALER, + Aircraft.Wing.BENDING_MATERIAL_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRWI1', # ['&DEFINE.WTIN.FRWI1', 'WIOR3.FRWI1'], - "LEAPS1": 'aircraft.inputs.L0_overrides.wing_bending_mat_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRWI1', # ['&DEFINE.WTIN.FRWI1', 'WIOR3.FRWI1'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.wing_bending_mat_weight', + }, units='unitless', desc='mass scaler of the bending wing mass term', default_value=1.0, @@ -5089,22 +5419,24 @@ # - see also: Aircraft.Wing.BWB_AFTBODY_MASS_SCALER Aircraft.Wing.BWB_AFTBODY_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WWGHT.W4', - "LEAPS1": 'aircraft.outputs.L0_wing.bwb_aft_body_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WWGHT.W4', + 'LEAPS1': 'aircraft.outputs.L0_wing.bwb_aft_body_weight', + }, units='lbm', desc='wing mass breakdown term 4', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Wing.BWB_AFTBODY_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRWI4', # ['&DEFINE.WTIN.FRWI4', 'WIOR3.FRWI4'], - "LEAPS1": 'aircraft.inputs.L0_overrides.bwb_aft_body_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRWI4', # ['&DEFINE.WTIN.FRWI4', 'WIOR3.FRWI4'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.bwb_aft_body_weight', + }, units='unitless', desc='mass scaler of the blended-wing-body aft-body wing mass term', default_value=1.0, @@ -5113,121 +5445,121 @@ add_meta_data( Aircraft.Wing.CENTER_CHORD, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CRCLW', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CRCLW', 'FLOPS': None, 'LEAPS1': None}, units='ft', - desc='wing chord at fuselage centerline', + desc='wing chord at fuselage centerline, usually called root chord', + default_value=0.0, ) add_meta_data( Aircraft.Wing.CENTER_DISTANCE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.XWQLF', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.XWQLF', 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc='distance (percent fuselage length) from nose to the wing ' - 'aerodynamic center', + desc='distance (percent fuselage length) from nose to the wing aerodynamic center', ) add_meta_data( Aircraft.Wing.CHARACTERISTIC_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.EL[1]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[0]', - 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[0]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.EL[1]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_component_char_len_table[0]', + 'aircraft.cached.L0_aerodynamics.mission_component_char_len_table[0]', + ], + }, units='ft', - desc='Reynolds characteristic length for the wing' + desc='Reynolds characteristic length for the wing', + default_value=0.0, ) add_meta_data( Aircraft.Wing.CHOOSE_FOLD_LOCATION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', default_value=True, types=bool, option=True, desc='if true, fold location is based on your chosen value, otherwise it is ' - 'based on strut location. In GASP this depended on STRUT or YWFOLD', + 'based on strut location. In GASP this depended on STRUT or YWFOLD', ) add_meta_data( # see also: station_chord_lengths Aircraft.Wing.CHORD_PER_SEMISPAN_DIST, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.CHD', # ['&DEFINE.WTIN.CHD', 'WDEF.CHD'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.wing_station_chord_lengths' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.CHD', # ['&DEFINE.WTIN.CHD', 'WDEF.CHD'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.wing_station_chord_lengths', + }, units='unitless', desc='chord lengths as fractions of semispan at station locations; ' - 'overwrites station_chord_lengths', - default_value=None, + 'overwrites station_chord_lengths', + types=float, + default_value=[0.0], + multivalue=True, ) add_meta_data( Aircraft.Wing.COMPOSITE_FRACTION, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.FCOMP', 'WTS.FCOMP', '~WWGHT.FCOMP'], - "FLOPS": 'WTIN.FCOMP', - "LEAPS1": 'aircraft.inputs.L0_wing.composite_fraction' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.FCOMP', 'WTS.FCOMP', '~WWGHT.FCOMP'], + 'FLOPS': 'WTIN.FCOMP', + 'LEAPS1': 'aircraft.inputs.L0_wing.composite_fraction', + }, units='unitless', desc='Define the decimal fraction of amount of composites used in wing ' - 'structure where: 0.0 == no composites; 1.0 == maximum use of composites, ' - 'approximately equivalent bending_mat_weight=.6, ' - 'struct_weights=.83, misc_weight=.7 ' - '(not necessarily all composite).', + 'structure where: 0.0 == no composites; 1.0 == maximum use of composites, ' + 'approximately equivalent bending_mat_weight=.6, ' + 'struct_weights=.83, misc_weight=.7 ' + '(not necessarily all composite).', default_value=0.0, ) add_meta_data( Aircraft.Wing.CONTROL_SURFACE_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WEIGHT.SFLAP', # TODO ~WWGHT.SFLAP: similar, but separate calculation - "LEAPS1": ['~WeightABC._pre_surface_ctrls.surface_flap_area', # TODO ~WingWeight.__call__.flap_ratio: see ~WWGHT.SFLAP - '~WeightABC.calc_surface_ctrls.surface_flap_area', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WEIGHT.SFLAP', # TODO ~WWGHT.SFLAP: similar, but separate calculation + 'LEAPS1': [ + # TODO ~WingWeight.__call__.flap_ratio: see ~WWGHT.SFLAP + '~WeightABC._pre_surface_ctrls.surface_flap_area', + '~WeightABC.calc_surface_ctrls.surface_flap_area', + ], + }, units='ft**2', - desc='area of wing control surfaces' + desc='area of wing control surfaces', + default_value=0.0, ) add_meta_data( Aircraft.Wing.CONTROL_SURFACE_AREA_RATIO, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.FLAPR', 'WTS.FLAPR', '~WWGHT.FLAPR'], - "FLOPS": 'WTIN.FLAPR', - "LEAPS1": 'aircraft.inputs.L0_wing.flap_ratio' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.FLAPR', 'WTS.FLAPR', '~WWGHT.FLAPR'], + 'FLOPS': 'WTIN.FLAPR', + 'LEAPS1': 'aircraft.inputs.L0_wing.flap_ratio', + }, units='unitless', desc='Defines the ratio of total moveable wing control surface areas ' - '(flaps, elevators, spoilers, etc.) to reference wing area.', - default_value=0.333, + '(flaps, elevators, spoilers, etc.) to reference wing area.', + default_value=0.0, ) add_meta_data( Aircraft.Wing.DETAILED_WING, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc='use a detailed wing model', + desc='Flag that sets if FLOPS mass should use the detailed wing model', option=True, types=bool, default_value=False, @@ -5236,105 +5568,110 @@ add_meta_data( Aircraft.Wing.DIHEDRAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.DIH', # ['&DEFINE.WTIN.DIH', 'WTS.DIH', ], - "LEAPS1": ['aircraft.inputs.L0_wing.dihedral', - # unit converted value for reporting - 'aircraft.cached.L0_wing.dihedral', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.DIH', # ['&DEFINE.WTIN.DIH', 'WTS.DIH', ], + 'LEAPS1': [ + 'aircraft.inputs.L0_wing.dihedral', + # unit converted value for reporting + 'aircraft.cached.L0_wing.dihedral', + ], + }, units='deg', desc='wing dihedral (positive) or anhedral (negative) angle', - default_value=0.0 + default_value=0.0, ) add_meta_data( Aircraft.Wing.ENG_POD_INERTIA_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WWGHT.CAYE', - "LEAPS1": 'aircraft.outputs.L0_wing.engine_inertia_relief_factor' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WWGHT.CAYE', + 'LEAPS1': 'aircraft.outputs.L0_wing.engine_inertia_relief_factor', + }, units='unitless', - desc='engine inertia relief factor' + desc='Engine inertia relief factor for wingspan inboard of engine locations. Used ' + 'to compute Aircraft.Wing.BENDING_MATERIAL_MASS', + default_value=0.0, +) + +add_meta_data( + Aircraft.Wing.EXPOSED_AREA, + meta_data=_MetaData, + historical_name={ + 'GASP': 'SW_EXP', + 'FLOPS': None, + 'LEAPS1': None, + }, + units='ft**2', + desc='exposed wing area, i.e. wing area outside the fuselage, True for both Tube&Wing and HWB', + default_value=0.0, ) add_meta_data( Aircraft.Wing.FINENESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # 'MISSA.FR[1]', - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[0]', - 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[0]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # 'MISSA.FR[1]', + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.mission_fineness_ratio_table[0]', + 'aircraft.cached.L0_aerodynamics.mission_fineness_ratio_table[0]', + ], + }, units='unitless', - desc='wing fineness ratio' + desc='wing fineness ratio', + default_value=0.0, ) add_meta_data( Aircraft.Wing.FLAP_CHORD_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CFOC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CFOC', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='ratio of flap chord to wing chord', + default_value=0.0, ) add_meta_data( Aircraft.Wing.FLAP_DEFLECTION_LANDING, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DFLPLD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DFLPLD', 'FLOPS': None, 'LEAPS1': None}, units='deg', - desc='Deflection of flaps for landing' + desc='Deflection of flaps for landing', ) add_meta_data( Aircraft.Wing.FLAP_DEFLECTION_TAKEOFF, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DFLPTO', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DFLPTO', 'FLOPS': None, 'LEAPS1': None}, units='deg', - desc='Deflection of flaps for takeoff' + desc='Deflection of flaps for takeoff', ) add_meta_data( Aircraft.Wing.FLAP_DRAG_INCREMENT_OPTIMUM, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DCDOTE', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.DCDOTE', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='drag coefficient increment due to optimally deflected trailing edge flaps (default depends on flap type)', ) add_meta_data( Aircraft.Wing.FLAP_LIFT_INCREMENT_OPTIMUM, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DCLMTE', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.DCLMTE', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='lift coefficient increment due to optimally deflected trailing edge flaps (default depends on flap type)', + default_value=0.0, ) add_meta_data( Aircraft.Wing.FLAP_SPAN_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.BTEOB', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.BTEOB', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='fraction of wing trailing edge with flaps', default_value=0.65, ) @@ -5342,33 +5679,33 @@ add_meta_data( Aircraft.Wing.FLAP_TYPE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.JFLTYP', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.JFLTYP', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', default_value=FlapType.DOUBLE_SLOTTED, types=FlapType, + multivalue=True, option=True, desc='Set the flap type. Available choices are: plain, split, single_slotted, ' - 'double_slotted, triple_slotted, fowler, and double_slotted_fowler. ' - 'In GASP this was JFLTYP and was provided as an int from 1-7', + 'double_slotted, triple_slotted, fowler, and double_slotted_fowler. ' + 'In GASP this was JFLTYP and was provided as an int from 1-7', ) add_meta_data( - Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, - units="unitless", default_value=False, types=bool, option=True, + Aircraft.Wing.FOLD_DIMENSIONAL_LOCATION_SPECIFIED, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + default_value=False, + types=bool, + option=True, desc='if true, fold location from the chosen input is an actual fold span, ' - 'if false it is normalized to the half span. In GASP this depended on STRUT or YWFOLD') + 'if false it is normalized to the half span. In GASP this depended on STRUT or YWFOLD', +) add_meta_data( Aircraft.Wing.FOLD_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WWFOLD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WWFOLD', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of the folding area of the wing', default_value=0, @@ -5377,11 +5714,8 @@ add_meta_data( Aircraft.Wing.FOLD_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKWFOLD', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKWFOLD', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of the wing fold', default_value=0, ) @@ -5389,23 +5723,17 @@ add_meta_data( Aircraft.Wing.FOLDED_SPAN, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.YWFOLD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.YWFOLD', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='folded wingspan', - default_value=118, + default_value=0, ) add_meta_data( Aircraft.Wing.FOLDED_SPAN_DIMENSIONLESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='folded wingspan', default_value=1, ) @@ -5413,46 +5741,41 @@ add_meta_data( Aircraft.Wing.FOLDING_AREA, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SWFOLD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.SWFOLD', 'FLOPS': None, 'LEAPS1': None}, units='ft**2', - desc='wing area of folding part of wings' + desc='wing area of folding part of wings', + default_value=0.0, ) add_meta_data( Aircraft.Wing.FORM_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKW', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CKW', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='wing form factor', + default_value=0.0, ) add_meta_data( Aircraft.Wing.FUSELAGE_INTERFERENCE_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKI', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.CKI', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='wing/fuselage interference factor', + default_value=0.0, ) add_meta_data( Aircraft.Wing.GLOVE_AND_BAT, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.GLOV', - # ['&DEFINE.WTIN.GLOV', 'EDETIN.GLOV', '~TOFF.GLOV', '~LNDING.GLOV', - # '~PROFIL.GLOV' - # ], - "LEAPS1": 'aircraft.inputs.L0_wing.glove_and_bat' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.GLOV', + # ['&DEFINE.WTIN.GLOV', 'EDETIN.GLOV', '~TOFF.GLOV', '~LNDING.GLOV', + # '~PROFIL.GLOV' + # ], + 'LEAPS1': 'aircraft.inputs.L0_wing.glove_and_bat', + }, units='ft**2', desc='total glove and bat area beyond theoretical wing', default_value=0.0, @@ -5461,11 +5784,8 @@ add_meta_data( Aircraft.Wing.HAS_FOLD, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', option=True, desc='if true a fold will be included in the wing', default_value=False, @@ -5475,12 +5795,9 @@ add_meta_data( Aircraft.Wing.HAS_STRUT, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, option=True, - units="unitless", + units='unitless', default_value=False, types=bool, desc='if true then aircraft has a strut. In GASP this depended on STRUT', @@ -5489,44 +5806,35 @@ add_meta_data( Aircraft.Wing.HEIGHT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.HTG', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.HTG', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='wing height above ground during ground run, measured at roughly ' - 'location of mean aerodynamic chord at the mid plane of the wing', + 'location of mean aerodynamic chord at the mid plane of the wing', + default_value=0.0, ) add_meta_data( Aircraft.Wing.HIGH_LIFT_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WHLDEV', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WHLDEV', 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of the high lift devices', + default_value=0.0, ) add_meta_data( Aircraft.Wing.HIGH_LIFT_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WCFLAP', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.WCFLAP', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of high lift devices (default depends on flap type)', + default_value=0.0, ) add_meta_data( Aircraft.Wing.INCIDENCE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.EYEW', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.EYEW', 'FLOPS': None, 'LEAPS1': None}, units='deg', desc='incidence angle of the wings with respect to the fuselage', default_value=0.0, @@ -5537,24 +5845,27 @@ # NOTE required for blended-wing-body type aircraft Aircraft.Wing.INPUT_STATION_DIST, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.ETAW', # ['&DEFINE.WTIN.ETAW', 'WDEF.ETAW'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.wing_station_locations' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.ETAW', # ['&DEFINE.WTIN.ETAW', 'WDEF.ETAW'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.wing_station_locations', + }, units='unitless', - desc='wing station locations as fractions of semispan; overwrites ' - 'station_locations', + desc='wing station locations as fractions of semispan; overwrites station_locations', + types=float, + multivalue=True, option=True, - default_value=None, + default_value=[0.0], ) add_meta_data( Aircraft.Wing.LAMINAR_FLOW_LOWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRLW', # ['&DEFINE.AERIN.TRLW', 'XLAM.TRLW', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.wing_percent_laminar_flow_lower_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRLW', # ['&DEFINE.AERIN.TRLW', 'XLAM.TRLW', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.wing_percent_laminar_flow_lower_surface', + }, units='unitless', desc='define percent laminar flow for wing lower surface', default_value=0.0, @@ -5563,10 +5874,11 @@ add_meta_data( Aircraft.Wing.LAMINAR_FLOW_UPPER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.TRUW', # ['&DEFINE.AERIN.TRUW', 'XLAM.TRUW', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.wing_percent_laminar_flow_upper_surface' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.TRUW', # ['&DEFINE.AERIN.TRUW', 'XLAM.TRUW', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.wing_percent_laminar_flow_upper_surface', + }, units='unitless', desc='define percent laminar flow for wing upper surface', default_value=0.0, @@ -5575,24 +5887,22 @@ add_meta_data( Aircraft.Wing.LEADING_EDGE_SWEEP, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SWPLE', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.SWPLE', 'FLOPS': None, 'LEAPS1': None}, units='rad', desc='sweep angle at leading edge of wing', + default_value=0.0, ) add_meta_data( Aircraft.Wing.LOAD_DISTRIBUTION_CONTROL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.PDIST', # ['&DEFINE.WTIN.PDIST', 'WDEF.PDIST'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.pressure_dist' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.PDIST', # ['&DEFINE.WTIN.PDIST', 'WDEF.PDIST'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.pressure_dist', + }, units='unitless', - desc='controls spatial distribution of integratin stations for detailed' - ' wing', + desc='controls spatial distribution of integration stations for detailed wing', default_value=2.0, option=True, ) @@ -5600,10 +5910,11 @@ add_meta_data( Aircraft.Wing.LOAD_FRACTION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.PCTL', # ['&DEFINE.WTIN.PCTL', 'WDEF.PCTL'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.carried_load_fraction' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.PCTL', # ['&DEFINE.WTIN.PCTL', 'WDEF.PCTL'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.carried_load_fraction', + }, units='unitless', desc='fraction of load carried by defined wing', default_value=1.0, @@ -5612,36 +5923,26 @@ add_meta_data( Aircraft.Wing.LOAD_PATH_SWEEP_DIST, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.SWL', # ['&DEFINE.WTIN.SWL', 'WDEF.SWL'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.wing_station_load_path_sweeps' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.SWL', # ['&DEFINE.WTIN.SWL', 'WDEF.SWL'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.wing_station_load_path_sweeps', + }, units='deg', + types=float, desc='Define the sweep of load path at station locations. Typically ' - 'parallel to rear spar tending toward max t/c of airfoil. The Ith value ' - 'is used between wing stations I and I+1.', - default_value=None, -) - -add_meta_data( - Aircraft.Wing.LOADING, - meta_data=_MetaData, - historical_name={"GASP": ['INGASP.WGS', 'INGASP.WOS'], - "FLOPS": None, - "LEAPS1": None - }, - units='lbf/ft**2', - desc='wing loading', + 'parallel to rear spar tending toward max t/c of airfoil. The Ith value ' + 'is used between wing stations I and I+1.', + default_value=[0.0], + multivalue=True, ) +# TODO this variable may be uneccessary since we can just check wing loading's value where needed add_meta_data( Aircraft.Wing.LOADING_ABOVE_20, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='if true the wing loading is stated to be above 20 psf. In GASP this depended on WGS', option=True, default_value=True, @@ -5653,37 +5954,37 @@ # - see also: Aircraft.Wing.MASS_SCALER Aircraft.Wing.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(1, 2)', '~WEIGHT.WWING', '~WTSTAT.WSP(1, 2)', '~WWGHT.WWING'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._total_wing_weight', - 'aircraft.outputs.L0_weights_summary.total_wing_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(1, 2)', '~WEIGHT.WWING', '~WTSTAT.WSP(1, 2)', '~WWGHT.WWING'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._total_wing_weight', + 'aircraft.outputs.L0_weights_summary.total_wing_weight', + ], + }, units='lbm', desc='wing total mass', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Wing.MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKWW', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKWW', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='mass trend coefficient of the wing without high lift devices', - default_value=133.4, + default_value=0.0, ) add_meta_data( Aircraft.Wing.MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRWI', # ['&DEFINE.WTIN.FRWI', 'WTS.FRWI'], - "LEAPS1": 'aircraft.inputs.L0_overrides.total_wing_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRWI', # ['&DEFINE.WTIN.FRWI', 'WTS.FRWI'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.total_wing_weight', + }, units='unitless', desc='mass scaler of the overall wing', default_value=1.0, @@ -5692,11 +5993,8 @@ add_meta_data( Aircraft.Wing.MATERIAL_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKNO', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKNO', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='correction factor for the use of non optimum material', default_value=0, ) @@ -5704,17 +6002,19 @@ add_meta_data( Aircraft.Wing.MAX_CAMBER_AT_70_SEMISPAN, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.CAM', - # [ # inputs - # '&DEFINE.AERIN.CAM', 'EDETIN.CAM', - # # outputs - # 'MISSA.CAM', 'MISSA.CAMX', - # ], - "LEAPS1": ['aircraft.inputs.L0_aerodynamics.max_camber_at_70_semispan', - 'aircraft.outputs.L0_aerodynamics.mission_max_camber_at_70_semispan', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.CAM', + # [ # inputs + # '&DEFINE.AERIN.CAM', 'EDETIN.CAM', + # # outputs + # 'MISSA.CAM', 'MISSA.CAMX', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_aerodynamics.max_camber_at_70_semispan', + 'aircraft.outputs.L0_aerodynamics.mission_max_camber_at_70_semispan', + ], + }, units='unitless', desc='Maximum camber at 70 percent semispan, percent of local chord', default_value=0.0, @@ -5723,21 +6023,15 @@ add_meta_data( Aircraft.Wing.MAX_LIFT_REF, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.RCLMAX', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.RCLMAX', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='input reference maximum lift coefficient for basic wing', ) add_meta_data( Aircraft.Wing.MAX_SLAT_DEFLECTION_LANDING, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELLED', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELLED', 'FLOPS': None, 'LEAPS1': None}, units='deg', desc='leading edge slat deflection during landing', default_value=10, @@ -5746,10 +6040,7 @@ add_meta_data( Aircraft.Wing.MAX_SLAT_DEFLECTION_TAKEOFF, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELLED', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELLED', 'FLOPS': None, 'LEAPS1': None}, units='deg', desc='leading edge slat deflection during takeoff', default_value=10, @@ -5758,23 +6049,19 @@ add_meta_data( Aircraft.Wing.MAX_THICKNESS_LOCATION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.XCTCMX', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.XCTCMX', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='location (percent chord) of max wing thickness', + default_value=0.0, ) add_meta_data( Aircraft.Wing.MIN_PRESSURE_LOCATION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.XCPS', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.XCPS', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='location (percent chord) of peak suction', + default_value=0.0, ) add_meta_data( @@ -5782,46 +6069,34 @@ # - see also: Aircraft.Wing.MISC_MASS_SCALER Aircraft.Wing.MISC_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WWGHT.W3', - "LEAPS1": 'aircraft.outputs.L0_wing.misc_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WWGHT.W3', + 'LEAPS1': 'aircraft.outputs.L0_wing.misc_weight', + }, units='lbm', desc='wing mass breakdown term 3', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Wing.MISC_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRWI3', # ['&DEFINE.WTIN.FRWI3', 'WIOR3.FRWI3'], - "LEAPS1": 'aircraft.inputs.L0_overrides.wing_misc_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRWI3', # ['&DEFINE.WTIN.FRWI3', 'WIOR3.FRWI3'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.wing_misc_weight', + }, units='unitless', desc='mass scaler of the miscellaneous wing mass term', default_value=1.0, ) -add_meta_data( - Aircraft.Wing.MOUNTING_TYPE, - meta_data=_MetaData, - historical_name={"GASP": 'INGASP.HWING', - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - desc='wing location on fuselage (0 = low wing, 1 = high wing)', -) - add_meta_data( Aircraft.Wing.NUM_FLAP_SEGMENTS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.FLAPN', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.FLAPN', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='number of flap segments per wing panel', types=int, option=True, @@ -5831,11 +6106,12 @@ add_meta_data( Aircraft.Wing.NUM_INTEGRATION_STATIONS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.NSTD', 'WDEF.NSTD', '~BNDMAT.NSD', '~DETA.NSD'], - "FLOPS": 'WTIN.NSTD', - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.integration_station_count' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.NSTD', 'WDEF.NSTD', '~BNDMAT.NSD', '~DETA.NSD'], + 'FLOPS': 'WTIN.NSTD', + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.integration_station_count', + }, units='unitless', desc='number of integration stations', types=int, @@ -5846,21 +6122,16 @@ add_meta_data( Aircraft.Wing.OPTIMUM_FLAP_DEFLECTION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELTEO', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELTEO', 'FLOPS': None, 'LEAPS1': None}, units='deg', desc='optimum flap deflection angle (default depends on flap type)', + default_value=0.0, ) add_meta_data( Aircraft.Wing.OPTIMUM_SLAT_DEFLECTION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELLEO', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELLEO', 'FLOPS': None, 'LEAPS1': None}, units='deg', desc='optimum slat deflection angle', default_value=20, @@ -5869,12 +6140,14 @@ add_meta_data( Aircraft.Wing.ROOT_CHORD, meta_data=_MetaData, - historical_name={"GASP": ['INGASP.CROOT', 'INGASP.CROOTW'], - "FLOPS": None, - "LEAPS1": None - }, + historical_name={ + 'GASP': 'INGASP.CROOTW', + 'FLOPS': 'WTIN.XLW', + 'LEAPS1': None, + }, units='ft', - desc='wing chord length at wing root', + desc='wing chord length at at the wing/fuselage intersection', + default_value=0.0, ) add_meta_data( @@ -5882,22 +6155,24 @@ # - see also: Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER Aircraft.Wing.SHEAR_CONTROL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~WWGHT.W2', - "LEAPS1": 'aircraft.outputs.L0_wing.struct_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~WWGHT.W2', + 'LEAPS1': 'aircraft.outputs.L0_wing.struct_weight', + }, units='lbm', desc='wing mass breakdown term 2', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Wing.SHEAR_CONTROL_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRWI2', # ['&DEFINE.WTIN.FRWI2', 'WIOR3.FRWI2'], - "LEAPS1": 'aircraft.inputs.L0_overrides.wing_struct_weights' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRWI2', # ['&DEFINE.WTIN.FRWI2', 'WIOR3.FRWI2'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.wing_struct_weights', + }, units='unitless', desc='mass scaler of the shear and control term', default_value=1.0, @@ -5906,53 +6181,46 @@ add_meta_data( Aircraft.Wing.SLAT_CHORD_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CLEOC', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.CLEOC', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='ratio of slat chord to wing chord', - default_value=0.15, + default_value=0.0, ) add_meta_data( Aircraft.Wing.SLAT_LIFT_INCREMENT_OPTIMUM, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DCLMLE', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.DCLMLE', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='lift coefficient increment due to optimally deflected LE slats', ) add_meta_data( Aircraft.Wing.SLAT_SPAN_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.BLEOB', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.BLEOB', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='fraction of wing leading edge with slats', - default_value=0.9, + default_value=0.0, ) add_meta_data( Aircraft.Wing.SPAN, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.B', - "FLOPS": 'WTIN.SPAN', - # [ # inputs - # '&DEFINE.WTIN.SPAN', - # # outputs - # '~WEIGHT.B', '~WWGHT.B', '~GESURF.B' - # ], - "LEAPS1": ['aircraft.inputs.L0_wing.span', - 'aircraft.outputs.L0_wing.span', - 'BasicTransportWeight.wing_span' - ] - }, + historical_name={ + 'GASP': 'INGASP.B', + 'FLOPS': 'WTIN.SPAN', + # [ # inputs + # '&DEFINE.WTIN.SPAN', + # # outputs + # '~WEIGHT.B', '~WWGHT.B', '~GESURF.B' + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_wing.span', + 'aircraft.outputs.L0_wing.span', + 'BasicTransportWeight.wing_span', + ], + }, units='ft', desc='span of main wing', default_value=0.0, @@ -5961,10 +6229,11 @@ add_meta_data( Aircraft.Wing.SPAN_EFFICIENCY_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.E', # ['&DEFINE.AERIN.E', 'OSWALD.E', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.wing_span_efficiency_factor' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.E', # ['&DEFINE.AERIN.E', 'OSWALD.E', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.wing_span_efficiency_factor', + }, units='unitless', desc='coefficient for calculating span efficiency for extreme taper ratios', default_value=1.0, @@ -5973,32 +6242,34 @@ add_meta_data( Aircraft.Wing.SPAN_EFFICIENCY_REDUCTION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.MIKE', # ['&DEFINE.AERIN.MIKE', 'MIMOD.MIKE'], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.wing_span_efficiency_reduction' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.MIKE', # ['&DEFINE.AERIN.MIKE', 'MIMOD.MIKE'], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.wing_span_efficiency_reduction', + }, units='unitless', desc='Define a switch for span efficiency reduction for extreme taper ' - 'ratios: True == a span efficiency factor ' - '(*wing_span_efficiency_factor0*) is calculated based on wing taper ratio ' - 'and aspect ratio; False == a span efficiency factor ' - '(*wing_span_efficiency_factor0*) is set to 1.0.', + 'ratios: True == a span efficiency factor ' + '(*wing_span_efficiency_factor0*) is calculated based on wing taper ratio ' + 'and aspect ratio; False == a span efficiency factor ' + '(*wing_span_efficiency_factor0*) is set to 1.0.', option=True, types=bool, - default_value=False + default_value=False, ) add_meta_data( Aircraft.Wing.STRUT_BRACING_FACTOR, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.FSTRT', 'WTS.FSTRT', '~WWGHT.FSTRT', '~BNDMAT.FSTRT'], - "FLOPS": 'WTIN.FSTRT', - "LEAPS1": 'aircraft.inputs.L0_wing.struct_bracing_factor' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.FSTRT', 'WTS.FSTRT', '~WWGHT.FSTRT', '~BNDMAT.FSTRT'], + 'FLOPS': 'WTIN.FSTRT', + 'LEAPS1': 'aircraft.inputs.L0_wing.struct_bracing_factor', + }, units='unitless', desc='Define the wing strut-bracing factor where: 0.0 == no wing-strut; ' - '1.0 == full benefit from strut bracing.', + '1.0 == full benefit from strut bracing.', default_value=0.0, ) @@ -6007,37 +6278,37 @@ # - see also: Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER Aircraft.Wing.SURFACE_CONTROL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - # ['WTS.WSP(16, 2)', '~WEIGHT.WSC', '~WTSTAT.WSP(16, 2)'], - "FLOPS": None, - "LEAPS1": ['(WeightABC)self._surface_ctrls_weight', - 'aircraft.outputs.L0_weights_summary.surface_ctrls_weight', - ] - }, + historical_name={ + 'GASP': None, + # ['WTS.WSP(16, 2)', '~WEIGHT.WSC', '~WTSTAT.WSP(16, 2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._surface_ctrls_weight', + 'aircraft.outputs.L0_weights_summary.surface_ctrls_weight', + ], + }, units='lbm', desc='mass of surface controls', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Wing.SURFACE_CONTROL_MASS_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SKFW', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.SKFW', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='Surface controls weight coefficient', - default_value=0.404, + default_value=0.0, ) add_meta_data( Aircraft.Wing.SURFACE_CONTROL_MASS_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.FRSC', # ['&DEFINE.WTIN.FRSC', 'WTS.FRSC'], - "LEAPS1": 'aircraft.inputs.L0_overrides.surface_ctrls_weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.FRSC', # ['&DEFINE.WTIN.FRSC', 'WTS.FRSC'], + 'LEAPS1': 'aircraft.inputs.L0_overrides.surface_ctrls_weight', + }, units='unitless', desc='Surface controls mass scaler', default_value=1.0, @@ -6046,69 +6317,75 @@ add_meta_data( Aircraft.Wing.SWEEP, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DLMC4', - "FLOPS": "CONFIN.SWEEP", - # [ # inputs - # '&DEFINE.CONFIN.SWEEP', 'PARVAR.DVD(1,6)', - # # outputs - # 'CONFIG.SWEEP', 'CONFIG.DVA(6)', '~FLOPS.DVA(6)', '~ANALYS.DVA(6)', - # '~WWGHT.SWEEP', '~INERT.SWEEP', - # # other - # 'MISSA.SW25', '~BUFFET.SW25', '~CDCC.SW25', '~CLDESN.SW25', - # '~MDESN.SW25', - # ], - "LEAPS1": ['aircraft.inputs.L0_design_variables.wing_sweep_at_quarter_chord', - 'aircraft.outputs.L0_design_variables.wing_sweep_at_quarter_chord', - 'aircraft.outputs.L0_design_variables.mission_wing_sweep_at_quarter_chord', - ] - }, + historical_name={ + 'GASP': 'INGASP.DLMC4', + 'FLOPS': 'CONFIN.SWEEP', + # [ # inputs + # '&DEFINE.CONFIN.SWEEP', 'PARVAR.DVD(1,6)', + # # outputs + # 'CONFIG.SWEEP', 'CONFIG.DVA(6)', '~FLOPS.DVA(6)', '~ANALYS.DVA(6)', + # '~WWGHT.SWEEP', '~INERT.SWEEP', + # # other + # 'MISSA.SW25', '~BUFFET.SW25', '~CDCC.SW25', '~CLDESN.SW25', + # '~MDESN.SW25', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_design_variables.wing_sweep_at_quarter_chord', + 'aircraft.outputs.L0_design_variables.wing_sweep_at_quarter_chord', + 'aircraft.outputs.L0_design_variables.mission_wing_sweep_at_quarter_chord', + ], + }, units='deg', desc='quarter-chord sweep angle of the wing', - default_value=0.0, # TODO required + default_value=0.0, # TODO required. ) add_meta_data( Aircraft.Wing.TAPER_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SLM', - "FLOPS": "CONFIN.TR", - # [ # inputs - # '&DEFINE.CONFIN.TR', 'PARVAR.DVD(1,5)', - # # outputs - # 'CONFIG.TR', 'CONFIG.DVA(5)', 'CONFIG.TR1', '~FLOPS.DVA(5)', - # '~ANALYS.DVA(5)', '~GESURF.TR', '~WWGHT.TR', '~INERT.TR', - # # other - # 'MISSA.TAPER', '~CDCC.TAPER', '~MDESN.TAPER', - # ], - "LEAPS1": ['aircraft.inputs.L0_design_variables.wing_taper_ratio', - 'aircraft.outputs.L0_design_variables.wing_taper_ratio', - 'aircraft.outputs.L0_design_variables.mission_wing_taper_ratio', - ] - }, + historical_name={ + 'GASP': 'INGASP.SLM', + 'FLOPS': 'CONFIN.TR', + # [ # inputs + # '&DEFINE.CONFIN.TR', 'PARVAR.DVD(1,5)', + # # outputs + # 'CONFIG.TR', 'CONFIG.DVA(5)', 'CONFIG.TR1', '~FLOPS.DVA(5)', + # '~ANALYS.DVA(5)', '~GESURF.TR', '~WWGHT.TR', '~INERT.TR', + # # other + # 'MISSA.TAPER', '~CDCC.TAPER', '~MDESN.TAPER', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_design_variables.wing_taper_ratio', + 'aircraft.outputs.L0_design_variables.wing_taper_ratio', + 'aircraft.outputs.L0_design_variables.mission_wing_taper_ratio', + ], + }, units='unitless', desc='taper ratio of the wing', - default_value=0.0, # TODO required + default_value=0.0, # TODO required. ) add_meta_data( Aircraft.Wing.THICKNESS_TO_CHORD, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'CONFIN.TCA', - # [ # inputs - # '&DEFINE.CONFIN.TCA', 'PARVAR.DVD(1,7)', - # # outputs - # 'CONFIG.TCA', 'CONFIG.DVA(7)', '~FLOPS.DVA(7)', '~ANALYS.DVA(7)', - # '~WWGHT.TCA', - # # other - # 'MISSA.TC', '~BUFFET.TC', '~CDCC.TC', '~CDPP.TC', '~CLDESN.TC', - # '~MDESN.TC', - # ], - "LEAPS1": ['aircraft.inputs.L0_design_variables.wing_thickness_to_chord_ratio', - 'aircraft.outputs.L0_design_variables.wing_thickness_to_chord_ratio', - 'aircraft.outputs.L0_design_variables.mission_wing_thickness_to_chord_ratio', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'CONFIN.TCA', + # [ # inputs + # '&DEFINE.CONFIN.TCA', 'PARVAR.DVD(1,7)', + # # outputs + # 'CONFIG.TCA', 'CONFIG.DVA(7)', '~FLOPS.DVA(7)', '~ANALYS.DVA(7)', + # '~WWGHT.TCA', + # # other + # 'MISSA.TC', '~BUFFET.TC', '~CDCC.TC', '~CDPP.TC', '~CLDESN.TC', + # '~MDESN.TC', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_design_variables.wing_thickness_to_chord_ratio', + 'aircraft.outputs.L0_design_variables.wing_thickness_to_chord_ratio', + 'aircraft.outputs.L0_design_variables.mission_wing_thickness_to_chord_ratio', + ], + }, units='unitless', desc='wing thickness-chord ratio (weighted average)', default_value=0.0, # TODO required @@ -6117,83 +6394,93 @@ add_meta_data( Aircraft.Wing.THICKNESS_TO_CHORD_DIST, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.TOC', # ['&DEFINE.WTIN.TOC', 'WDEF.TOC'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.wing_station_thickness_to_chord_ratios' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.TOC', # ['&DEFINE.WTIN.TOC', 'WDEF.TOC'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.wing_station_thickness_to_chord_ratios', + }, units='unitless', desc='the thickeness-chord ratios at station locations', - default_value=None, + default_value=[0.0], + types=float, + multivalue=True, ) add_meta_data( Aircraft.Wing.THICKNESS_TO_CHORD_REF, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.TCREF', # ['&DEFINE.WTIN.TCREF'], - "LEAPS1": 'aircraft.inputs.L0_detailed_wing.ref_thickness_to_chord_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.TCREF', # ['&DEFINE.WTIN.TCREF'], + 'LEAPS1': 'aircraft.inputs.L0_detailed_wing.ref_thickness_to_chord_ratio', + }, units='unitless', - desc='Reference thickness-to-chord ratio, used for detailed wing bending.', - default_value=0.0 + desc='Reference thickness-to-chord ratio, used for detailed wing mass estimation.', + default_value=0.0, ) add_meta_data( Aircraft.Wing.THICKNESS_TO_CHORD_ROOT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.TCR', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.TCR', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='thickness-to-chord ratio at the root of the wing', + default_value=0.0, ) add_meta_data( Aircraft.Wing.THICKNESS_TO_CHORD_TIP, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.TCT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.TCT', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='thickness-to-chord ratio at the tip of the wing', + default_value=0.0, ) add_meta_data( Aircraft.Wing.THICKNESS_TO_CHORD_UNWEIGHTED, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.TC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.TC', 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc='wing thickness-chord ratio at the wing station of the mean aerodynamic chord') + desc='wing thickness-chord ratio at the wing station of the mean aerodynamic chord', + default_value=0.0, +) add_meta_data( Aircraft.Wing.ULTIMATE_LOAD_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ULF', - # ['&DEFINE.WTIN.ULF', 'WTS.ULF', '~WWGHT.ULF'], - "FLOPS": 'WTIN.ULF', - "LEAPS1": 'aircraft.inputs.L0_weights.struct_ult_load_factor' - }, + historical_name={ + 'GASP': 'INGASP.ULF', + # ['&DEFINE.WTIN.ULF', 'WTS.ULF', '~WWGHT.ULF'], + 'FLOPS': 'WTIN.ULF', + 'LEAPS1': 'aircraft.inputs.L0_weights.struct_ult_load_factor', + }, units='unitless', desc='structural ultimate load factor', - default_value=3.75, + default_value=0.0, ) add_meta_data( Aircraft.Wing.VAR_SWEEP_MASS_PENALTY, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFINE.WTIN.VARSWP', 'FAWT.VARSWP', '~WWGHT.VARSWP'], - "FLOPS": 'WTIN.VARSWP', - "LEAPS1": 'aircraft.inputs.L0_wing.var_sweep_weight_penalty' - }, + historical_name={ + 'GASP': None, + # ['&DEFINE.WTIN.VARSWP', 'FAWT.VARSWP', '~WWGHT.VARSWP'], + 'FLOPS': 'WTIN.VARSWP', + 'LEAPS1': 'aircraft.inputs.L0_wing.var_sweep_weight_penalty', + }, units='unitless', desc='Define the fraction of wing variable sweep mass penalty where: ' - '0.0 == fixed-geometry wing; 1.0 == full variable-sweep wing.', + '0.0 == fixed-geometry wing; 1.0 == full variable-sweep wing.', + default_value=0.0, +) + +add_meta_data( + Aircraft.Wing.VERTICAL_MOUNT_LOCATION, + meta_data=_MetaData, + historical_name={'GASP': 'INGASP.HWING', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='vertical wing mount location on fuselage (0 = low wing, 1 = high wing). It is continuous variable between 0 and 1 are acceptable.', default_value=0.0, ) @@ -6202,25 +6489,28 @@ # - see also: Aircraft.Wing.WETTED_AREA_SCALER Aircraft.Wing.WETTED_AREA, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['ACTWET.SWTWG', 'MISSA.SWET[1]'], - "LEAPS1": ['aircraft.outputs.L0_aerodynamics.wing_wetted_area', - 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[0]', - 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[0]', - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['ACTWET.SWTWG', 'MISSA.SWET[1]'], + 'LEAPS1': [ + 'aircraft.outputs.L0_aerodynamics.wing_wetted_area', + 'aircraft.outputs.L0_aerodynamics.mission_component_wetted_area_table[0]', + 'aircraft.cached.L0_aerodynamics.mission_component_wetted_area_table[0]', + ], + }, units='ft**2', desc='wing wetted area', - default_value=None, + default_value=0.0, ) add_meta_data( Aircraft.Wing.WETTED_AREA_SCALER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.SWETW', # ['&DEFINE.AERIN.SWETW', 'AWETO.SWETW', ], - "LEAPS1": 'aircraft.inputs.L0_aerodynamics.wing_wetted_area' - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.SWETW', # ['&DEFINE.AERIN.SWETW', 'AWETO.SWETW', ], + 'LEAPS1': 'aircraft.inputs.L0_aerodynamics.wing_wetted_area', + }, units='unitless', desc='wing wetted area scaler', default_value=1.0, @@ -6229,12 +6519,10 @@ add_meta_data( Aircraft.Wing.ZERO_LIFT_ANGLE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ALPHL0', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.ALPHL0', 'FLOPS': None, 'LEAPS1': None}, units='deg', desc='zero lift angle of attack', + default_value=0.0, ) # ============================================================================================================================================ @@ -6251,542 +6539,511 @@ # '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' # ============================================================================================================================================ -# __ __ _ _ -# | \/ | (_) (_) -# | \ / | _ ___ ___ _ ___ _ __ -# | |\/| | | | / __| / __| | | / _ \ | '_ \ -# | | | | | | \__ \ \__ \ | | | (_) | | | | | -# |_| |_| |_| |___/ |___/ |_| \___/ |_| |_| -# ============================================ +# _ _ +# /\ | | | | +# / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ ___ +# / /\ \ | __| | '_ ` _ \ / _ \ / __| | '_ \ | '_ \ / _ \ | '__| / _ \ +# / ____ \ | |_ | | | | | | | (_) | \__ \ | |_) | | | | | | __/ | | | __/ +# /_/ \_\ \__| |_| |_| |_| \___/ |___/ | .__/ |_| |_| \___| |_| \___| +# | | +# |_| +# ================================================================================ add_meta_data( - Dynamic.Mission.ALTITUDE, + Dynamic.Atmosphere.DENSITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='ft', - desc='Current altitude of the vehicle' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm/ft**3', + desc="Atmospheric density at the vehicle's current altitude", + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.ALTITUDE_RATE, + Dynamic.Atmosphere.DYNAMIC_PRESSURE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='ft/s', - desc='Current rate of altitude change (climb rate) of the vehicle' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbf/ft**2', + desc="Atmospheric dynamic pressure at the vehicle's current flight condition", + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.ALTITUDE_RATE_MAX, + Dynamic.Atmosphere.KINEMATIC_VISCOSITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='ft/s', - desc='Current maximum possible rate of altitude change (climb rate) of the vehicle ' - '(at hypothetical maximum thrust condition)' + historical_name={'GASP': 'XKV', 'FLOPS': None, 'LEAPS1': None}, + units='ft**2/s', + desc="Atmospheric kinematic viscosity at the vehicle's current flight condition", + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.BATTERY_STATE_OF_CHARGE, + Dynamic.Atmosphere.MACH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc="battery's current state of charge" + desc='Current Mach number of the vehicle', + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.CUMULATIVE_ELECTRIC_ENERGY_USED, + Dynamic.Atmosphere.MACH_RATE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='kJ', - desc='Total amount of electric energy consumed by the vehicle up until this point in the mission', + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='Current rate at which the Mach number of the vehicle is changing', + multivalue=True, ) add_meta_data( - Dynamic.Mission.DENSITY, + Dynamic.Atmosphere.SPEED_OF_SOUND, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbm/ft**3', - desc="Atmospheric density at the vehicle's current altitude" + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='ft/s', + desc="Atmospheric speed of sound at vehicle's current flight condition", + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.DISTANCE, + Dynamic.Atmosphere.STATIC_PRESSURE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'range', - "LEAPS1": None - }, - units='NM', - desc="The total distance the vehicle has traveled since brake release at the current time" + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbf/ft**2', + desc="Atmospheric static pressure at the vehicle's current flight condition", + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.DISTANCE_RATE, + Dynamic.Atmosphere.TEMPERATURE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'range_rate', - "LEAPS1": None - }, - units='NM/s', - desc="The rate at which the distance traveled is changing at the current time" + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='degR', + desc="Atmospheric temperature at vehicle's current flight condition", + default_value=0.0, + multivalue=True, ) + +# __ __ _ _ +# | \/ | (_) (_) +# | \ / | _ ___ ___ _ ___ _ __ +# | |\/| | | | / __| / __| | | / _ \ | '_ \ +# | | | | | | \__ \ \__ \ | | | (_) | | | | | +# |_| |_| |_| |___/ |___/ |_| \___/ |_| |_| +# ============================================ add_meta_data( - Dynamic.Mission.DRAG, + Dynamic.Mission.ALTITUDE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbf', - desc='Current total drag experienced by the vehicle' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='ft', + desc='Current altitude of the vehicle', + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.DYNAMIC_PRESSURE, + Dynamic.Mission.ALTITUDE_RATE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbf/ft**2', - desc="Atmospheric dynamic pressure at the vehicle's current flight condition" + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='ft/s', + desc='Current rate of altitude change (climb rate) of the vehicle', + multivalue=True, ) add_meta_data( - Dynamic.Mission.ELECTRIC_POWER_IN, + Dynamic.Mission.ALTITUDE_RATE_MAX, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='kW', - desc='Current electric power consumption of each engine', + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='ft/s', + desc='Current maximum possible rate of altitude change (climb rate) of the vehicle ' + '(at hypothetical maximum thrust condition)', + multivalue=True, ) add_meta_data( - Dynamic.Mission.ELECTRIC_POWER_IN_TOTAL, + Dynamic.Mission.DISTANCE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='kW', - desc='Current total electric power consumption of the vehicle' + historical_name={'GASP': None, 'FLOPS': 'range', 'LEAPS1': None}, + units='NM', + desc='The total distance the vehicle has traveled since brake release at the current time', + multivalue=True, ) -# add_meta_data( -# Dynamic.Mission.EXIT_AREA, -# meta_data=_MetaData, -# historical_name={"GASP": None, -# "FLOPS": None, -# "LEAPS1": None -# }, -# units='kW', -# desc='Current nozzle exit area of engines, per single instance of each ' -# 'engine model' -# ) +add_meta_data( + Dynamic.Mission.DISTANCE_RATE, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': 'range_rate', 'LEAPS1': None}, + units='NM/s', + desc='The rate at which the distance traveled is changing at the current time', + multivalue=True, +) add_meta_data( Dynamic.Mission.FLIGHT_PATH_ANGLE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='rad', - desc='Current flight path angle' + desc='Current flight path angle', + default_value=0.0, + multivalue=True, ) add_meta_data( Dynamic.Mission.FLIGHT_PATH_ANGLE_RATE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='rad/s', - desc='Current rate at which flight path angle is changing' + desc='Current rate at which flight path angle is changing', + multivalue=True, ) add_meta_data( - Dynamic.Mission.FUEL_FLOW_RATE, + Dynamic.Mission.SPECIFIC_ENERGY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbm/h', - desc='Current rate of fuel consumption of the vehicle, per single instance of ' - 'each engine model. Consumption (i.e. mass reduction) of fuel is defined as ' - 'positive.' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='m/s', + desc='Rate of change in specific energy (energy per unit weight) of the vehicle at ' + 'current flight condition', + multivalue=True, ) add_meta_data( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, - units='lbm/h', - desc='Current rate of fuel consumption of the vehicle, per single instance of each ' - 'engine model. Consumption (i.e. mass reduction) of fuel is defined as negative.') + Dynamic.Mission.SPECIFIC_ENERGY_RATE, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='m/s', + desc='Rate of change in specific energy (specific power) of the vehicle at current ' + 'flight condition', + multivalue=True, +) add_meta_data( - Dynamic.Mission.FUEL_FLOW_RATE_NEGATIVE_TOTAL, + Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbm/h', - desc='Current rate of total fuel consumption of the vehicle. Consumption (i.e. ' - 'mass reduction) of fuel is defined as negative.' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='m/s', + desc='Specific excess power of the vehicle at current flight condition and at ' + 'hypothetical maximum thrust', + multivalue=True, ) add_meta_data( - Dynamic.Mission.FUEL_FLOW_RATE_TOTAL, + Dynamic.Mission.VELOCITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbm/h', - desc='Current rate of total fuel consumption of the vehicle. Consumption (i.e. ' - 'mass reduction) of fuel is defined as positive.' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='ft/s', + desc='Current velocity of the vehicle along its body axis', + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.HYBRID_THROTTLE, + Dynamic.Mission.VELOCITY_RATE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - desc='Current secondary throttle setting of each individual engine model on the ' - 'vehicle, used as an additional degree of control for hybrid engines' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='ft/s**2', + desc='Current rate of change in velocity (acceleration) of the vehicle along its body axis', + multivalue=True, ) +# __ __ _ _ _ +# \ \ / / | | (_) | | +# \ \ / / ___ | |__ _ ___ | | ___ +# \ \/ / / _ \ | '_ \ | | / __| | | / _ \ +# \ / | __/ | | | | | | | (__ | | | __/ +# \/ \___| |_| |_| |_| \___| |_| \___| +# ================================================ + add_meta_data( - Dynamic.Mission.KINEMATIC_VISCOSITY, + Dynamic.Vehicle.ANGLE_OF_ATTACK, meta_data=_MetaData, - historical_name={"GASP": 'XKV', - "FLOPS": None, - "LEAPS1": None - }, - units='ft**2/s', - desc="Atmospheric kinematic viscosity at the vehicle's current flight condition" + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='deg', + desc='Angle between aircraft wing cord and relative wind', + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.LIFT, + Dynamic.Vehicle.BATTERY_STATE_OF_CHARGE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbf', - desc='Current total lift produced by the vehicle' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc="battery's current state of charge", + multivalue=True, ) add_meta_data( - Dynamic.Mission.MACH, + Dynamic.Vehicle.CUMULATIVE_ELECTRIC_ENERGY_USED, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - desc='Current Mach number of the vehicle' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='kJ', + desc='Total amount of electric energy consumed by the vehicle up until this point ' + 'in the mission', + multivalue=True, ) add_meta_data( - Dynamic.Mission.MACH_RATE, + Dynamic.Vehicle.DRAG, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='unitless', - desc='Current rate at which the Mach number of the vehicle is changing' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbf', + desc='Current total drag experienced by the vehicle', + multivalue=True, +) + +add_meta_data( + Dynamic.Vehicle.LIFT, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbf', + desc='Current total lift produced by the vehicle', + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.MASS, + Dynamic.Vehicle.MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='Current total mass of the vehicle' + desc='Current total mass of the vehicle', + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.MASS_RATE, + Dynamic.Vehicle.MASS_RATE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm/s', - desc='Current rate at which the mass of the vehicle is changing' + desc='Current rate at which the mass of the vehicle is changing', + multivalue=True, ) +# ___ _ _ +# | _ \ _ _ ___ _ __ _ _ | | ___ (_) ___ _ _ +# | _/ | '_| / _ \ | '_ \ | || | | | (_-< | | / _ \ | ' \ +# |_| |_| \___/ | .__/ \_,_| |_| /__/ |_| \___/ |_||_| +# |_| +# ========================================================== + add_meta_data( - Dynamic.Mission.NOX_RATE, + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbm/h', - desc='Current rate of nitrous oxide (NOx) production by the vehicle, per single ' - 'instance of each engine model' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='kW', + desc='Current electric power consumption of each engine', + multivalue=True, +) + +add_meta_data( + Dynamic.Vehicle.Propulsion.ELECTRIC_POWER_IN_TOTAL, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='kW', + desc='Current total electric power consumption of the vehicle', + multivalue=True, ) +# add_meta_data( +# Dynamic.Vehicle.Propulsion.EXIT_AREA, +# meta_data=_MetaData, +# historical_name={'GASP': None, +# 'FLOPS': None, +# 'LEAPS1': None +# }, +# units='kW', +# desc='Current nozzle exit area of engines, per single instance of each ' +# 'engine model' +# ) + add_meta_data( - Dynamic.Mission.NOX_RATE_TOTAL, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm/h', - desc='Current total rate of nitrous oxide (NOx) production by the vehicle' + desc='Current rate of fuel consumption of the vehicle, per single instance of ' + 'each engine model. Consumption (i.e. mass reduction) of fuel is defined as ' + 'positive.', + multivalue=True, ) add_meta_data( - Dynamic.Mission.PROPELLER_TIP_SPEED, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='ft/s', - desc='linear propeller tip speed due to rotation (not airspeed at propeller tip)', - default_value=500.0, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm/h', + desc='Current rate of fuel consumption of the vehicle, per single instance of each ' + 'engine model. Consumption (i.e. mass reduction) of fuel is defined as negative.', + multivalue=True, ) add_meta_data( - Dynamic.Mission.RPM, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_NEGATIVE_TOTAL, meta_data=_MetaData, - historical_name={"GASP": ['RPM', 'RPMe'], "FLOPS": None, "LEAPS1": None}, - units='rpm', - desc='Rotational rate of shaft, per engine.', + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm/h', + desc='Current rate of total fuel consumption of the vehicle. Consumption (i.e. ' + 'mass reduction) of fuel is defined as negative.', + multivalue=True, ) add_meta_data( - Dynamic.Mission.SPECIFIC_ENERGY, + Dynamic.Vehicle.Propulsion.FUEL_FLOW_RATE_TOTAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='m/s', - desc='Rate of change in specific energy (energy per unit weight) of the vehicle at current ' - 'flight condition' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm/h', + desc='Current rate of total fuel consumption of the vehicle. Consumption (i.e. ' + 'mass reduction) of fuel is defined as positive.', + multivalue=True, ) add_meta_data( - Dynamic.Mission.SPECIFIC_ENERGY_RATE, + Dynamic.Vehicle.Propulsion.HYBRID_THROTTLE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='m/s', - desc='Rate of change in specific energy (specific power) of the vehicle at current ' - 'flight condition' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='Current secondary throttle setting of each individual engine model on the ' + 'vehicle, used as an additional degree of control for hybrid engines', + multivalue=True, ) add_meta_data( - Dynamic.Mission.SHAFT_POWER, + Dynamic.Vehicle.Propulsion.NOX_RATE, meta_data=_MetaData, - historical_name={"GASP": ['SHP, EHP'], "FLOPS": None, "LEAPS1": None}, - units='hp', - desc='current shaft power, per engine', + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm/h', + desc='Current rate of nitrous oxide (NOx) production by the vehicle, per single ' + 'instance of each engine model', + multivalue=True, ) add_meta_data( - Dynamic.Mission.SHAFT_POWER_MAX, + Dynamic.Vehicle.Propulsion.NOX_RATE_TOTAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='hp', - desc='The maximum possible shaft power currently producible, per engine' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm/h', + desc='Current total rate of nitrous oxide (NOx) production by the vehicle', + multivalue=True, ) add_meta_data( - Dynamic.Mission.SPECIFIC_ENERGY_RATE_EXCESS, + Dynamic.Vehicle.Propulsion.PROPELLER_TIP_SPEED, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='m/s', - desc='Specific excess power of the vehicle at current flight condition and at ' - 'hypothetical maximum thrust' + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='ft/s', + desc='linear propeller tip speed due to rotation (not airspeed at propeller tip)', + default_value=0.0, + multivalue=True, ) add_meta_data( - Dynamic.Mission.SPEED_OF_SOUND, + Dynamic.Vehicle.Propulsion.RPM, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='ft/s', - desc="Atmospheric speed of sound at vehicle's current flight condition" + historical_name={'GASP': ['RPM', 'RPMe'], 'FLOPS': None, 'LEAPS1': None}, + units='rpm', + desc='Rotational rate of shaft, per engine.', + multivalue=True, ) add_meta_data( - Dynamic.Mission.STATIC_PRESSURE, + Dynamic.Vehicle.Propulsion.SHAFT_POWER, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='lbf/ft**2', - desc="Atmospheric static pressure at the vehicle's current flight condition" + historical_name={'GASP': ['SHP, EHP'], 'FLOPS': None, 'LEAPS1': None}, + units='hp', + desc='current shaft power, per engine', + multivalue=True, ) add_meta_data( - Dynamic.Mission.TEMPERATURE, + Dynamic.Vehicle.Propulsion.SHAFT_POWER_MAX, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='degR', - desc="Atmospheric temperature at vehicle's current flight condition" + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='hp', + desc='The maximum possible shaft power currently producible, per engine', + multivalue=True, ) add_meta_data( - Dynamic.Mission.TEMPERATURE_T4, + Dynamic.Vehicle.Propulsion.TEMPERATURE_T4, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='degR', desc='Current turbine exit temperature (T4) of turbine engines on vehicle, per ' - 'single instance of each engine model' + 'single instance of each engine model', + multivalue=True, ) add_meta_data( - Dynamic.Mission.THROTTLE, + Dynamic.Vehicle.Propulsion.THROTTLE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc='Current throttle setting for each individual engine model on the vehicle' + desc='Current throttle setting for each individual engine model on the vehicle', + multivalue=True, ) add_meta_data( - Dynamic.Mission.THRUST, + Dynamic.Vehicle.Propulsion.THRUST, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf', - desc='Current net thrust produced by engines, per single instance of each engine ' - 'model' + desc='Current net thrust produced by engines, per single instance of each engine model', + multivalue=True, ) add_meta_data( - Dynamic.Mission.THRUST_MAX, + Dynamic.Vehicle.Propulsion.THRUST_MAX, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf', - desc="Hypothetical maximum possible net thrust that can be produced per single " - "instance of each engine model at the vehicle's current flight condition" + desc='Hypothetical maximum possible net thrust that can be produced per single ' + "instance of each engine model at the vehicle's current flight condition", + multivalue=True, ) add_meta_data( - Dynamic.Mission.THRUST_MAX_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_MAX_TOTAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf', desc='Hypothetical maximum possible net thrust produced by the vehicle at its ' - 'current flight condition' + 'current flight condition', + multivalue=True, ) add_meta_data( - Dynamic.Mission.THRUST_TOTAL, + Dynamic.Vehicle.Propulsion.THRUST_TOTAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbf', - desc='Current total net thrust produced by the vehicle' + desc='Current total net thrust produced by the vehicle', + multivalue=True, ) add_meta_data( - Dynamic.Mission.TORQUE, + Dynamic.Vehicle.Propulsion.TORQUE, meta_data=_MetaData, - historical_name={"GASP": 'TORQUE', "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': 'TORQUE', 'FLOPS': None, 'LEAPS1': None}, units='N*m', desc='Current torque being produced, per engine', + multivalue=True, ) add_meta_data( - Dynamic.Mission.TORQUE_MAX, + Dynamic.Vehicle.Propulsion.TORQUE_MAX, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='N*m', desc='Hypothetical maximum possible torque being produced at the current flight ' 'condition, per engine', -) - -add_meta_data( - Dynamic.Mission.VELOCITY, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='ft/s', - desc='Current velocity of the vehicle along its body axis' -) - -add_meta_data( - Dynamic.Mission.VELOCITY_RATE, - meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units='ft/s**2', - desc='Current rate of change in velocity (acceleration) of the vehicle along its ' - 'body axis' + multivalue=True, ) # ============================================================================================================================================ @@ -6810,10 +7067,20 @@ # | |____ | (_) | | | | | \__ \ | |_ | | | (_| | | | | | | | | |_ \__ \ # \_____| \___/ |_| |_| |___/ \__| |_| \__,_| |_| |_| |_| \__| |___/ # =========================================================================== + +add_meta_data( + Mission.Constraints.EXCESS_FUEL_CAPACITY, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm', + desc='Difference between the usable fuel capacity on the aircraft and the total fuel (including reserve) required for the mission. ' + 'Must be >= 0 to ensure that the aircraft has enough fuel to complete the mission', +) + add_meta_data( Mission.Constraints.GEARBOX_SHAFT_POWER_RESIDUAL, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='kW', desc='Must be zero or positive to ensure that the gearbox is sized large enough to handle the maximum shaft power the engine could output during any part of the mission', ) @@ -6821,61 +7088,54 @@ add_meta_data( Mission.Constraints.MASS_RESIDUAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='residual to make sure aircraft mass closes on actual ' - 'gross takeoff mass, value should be zero at convergence ' - '(within acceptable tolerance)', + 'gross takeoff mass, value should be zero at convergence ' + '(within acceptable tolerance)', ) add_meta_data( Mission.Constraints.MAX_MACH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'WTIN.VMMO', - # [ # inputs - # '&DEFINE.WTIN.VMMO', 'VLIMIT.VMMO', - # # outputs - # 'VLIMIT.VMAX', - # ], - "LEAPS1": ['aircraft.inputs.L0_weights.max_mach', - 'aircraft.outputs.L0_weights.max_mach', - ] - }, - units='unitless', - desc='aircraft cruise mach number', + historical_name={ + 'GASP': None, + 'FLOPS': 'WTIN.VMMO', + # [ # inputs + # '&DEFINE.WTIN.VMMO', 'VLIMIT.VMMO', + # # outputs + # 'VLIMIT.VMAX', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_weights.max_mach', + 'aircraft.outputs.L0_weights.max_mach', + ], + }, + units='unitless', + desc='aircraft cruise Mach number', # TODO: derived default value: Mission.Summary.CRUISE_MACH ??? - default_value=None, + default_value=0.0, option=True, ) add_meta_data( Mission.Constraints.RANGE_RESIDUAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='NM', desc='residual to make sure aircraft range is equal to the targeted ' - 'range, value should be zero at convergence (within acceptable ' - 'tolerance)', + 'range, value should be zero at convergence (within acceptable ' + 'tolerance)', ) add_meta_data( Mission.Constraints.RANGE_RESIDUAL_RESERVE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='NM', desc='residual to make sure aircraft reserve mission range is equal to the targeted ' - 'range, value should be zero at convergence (within acceptable ' - 'tolerance)', + 'range, value should be zero at convergence (within acceptable ' + 'tolerance)', ) # _____ _ @@ -6891,135 +7151,121 @@ add_meta_data( Mission.Design.CRUISE_ALTITUDE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CRALT', - "FLOPS": None, - "LEAPS1": None - }, - option=True, + historical_name={'GASP': 'INGASP.CRALT', 'FLOPS': None, 'LEAPS1': None}, units='ft', - default_value=25000, + option=True, + default_value=25000.0, desc='design mission cruise altitude', - types=[int, float] ) add_meta_data( Mission.Design.CRUISE_RANGE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None}, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='NM', desc='the distance flown by the aircraft during cruise', default_value=0.0, ) add_meta_data( - Mission.Design.FUEL_MASS, - meta_data=_MetaData, - historical_name={"GASP": "INGASP.WFADES", - "FLOPS": None, # ['WSP(38, 2)', '~WEIGHT.FUELM', '~INERT.FUELM'], - "LEAPS1": ['(WeightABC)self._fuel_weight', - 'aircraft.outputs.L0_weights_summary.fuel_weight' - ] - }, - units='lbm', - desc='fuel carried by the aircraft when it is on the ramp at the ' - 'beginning of the design mission', -) - -add_meta_data( - Mission.Design.FUEL_MASS_REQUIRED, + Mission.Summary.FUEL_MASS_REQUIRED, meta_data=_MetaData, - historical_name={"GASP": "INGASP.WFAREQ", - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WFAREQ', 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='fuel carried by the aircraft when it is on the ramp at the ' - 'beginning of the design mission', + desc='fuel carried by the aircraft when it is on the ramp at the beginning of the design ' + 'mission', + default_value=0.0, ) add_meta_data( Mission.Design.GROSS_MASS, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.WG', - # ['&DEFINE.WTIN.DGW', 'WTS.DGW', '~WEIGHT.DG', '~WWGHT.DG'], - "FLOPS": 'WTIN.DGW', - "LEAPS1": [ # TODO: 'aircraft.inputs.L0_weights.design_ramp_weight_fraction' ??? - # - design_ramp_weight_fraction has a default: 1.0 - # - design_ramp_weight does not have an explicit default - # - design_ramp_weight has an implicit default, by way of - # design_ramp_weight_fraction: - # [L0_design_variables] ramp_weight - 'aircraft.inputs.L0_weights.design_ramp_weight', - '(weightABC)self._design_gross_weight' - ] - }, + historical_name={ + 'GASP': 'INGASP.WG', + # ['&DEFINE.WTIN.DGW', 'WTS.DGW', '~WEIGHT.DG', '~WWGHT.DG'], + 'FLOPS': 'WTIN.DGW', + 'LEAPS1': [ # TODO: 'aircraft.inputs.L0_weights.design_ramp_weight_fraction' ??? + # - design_ramp_weight_fraction has a default: 1.0 + # - design_ramp_weight does not have an explicit default + # - design_ramp_weight has an implicit default, by way of + # design_ramp_weight_fraction: + # [L0_design_variables] ramp_weight + 'aircraft.inputs.L0_weights.design_ramp_weight', + '(weightABC)self._design_gross_weight', + ], + }, units='lbm', desc='design gross mass of the aircraft', - default_value=None, + default_value=0.0, ) add_meta_data( # NOTE: user override (no scaling) Mission.Design.LIFT_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.FCLDES', - # [ # inputs - # '&DEFINE.AERIN.FCLDES', 'OSWALD.FCLDES', - # # outputs - # '~EDET.CLDES', '~CLDESN.CLDES', '~MDESN.CLDES' - # ], - "LEAPS1": ['aircraft.inputs.L0_aerodynamics.design_lift_coeff', - 'aircraft.outputs.L0_aerodynamics.design_lift_coeff' - ] - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.FCLDES', + # [ # inputs + # '&DEFINE.AERIN.FCLDES', 'OSWALD.FCLDES', + # # outputs + # '~EDET.CLDES', '~CLDESN.CLDES', '~MDESN.CLDES' + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_aerodynamics.design_lift_coeff', + 'aircraft.outputs.L0_aerodynamics.design_lift_coeff', + ], + }, units='unitless', desc='Fixed design lift coefficient. If input, overrides design lift ' - 'coefficient computed by EDET.', - default_value=None, + 'coefficient computed by EDET.', + default_value=0.0, ) add_meta_data( Mission.Design.LIFT_COEFFICIENT_MAX_FLAPS_UP, meta_data=_MetaData, - historical_name={"GASP": ['INGASP.CLMWFU', 'INGASP.CLMAX'], - "FLOPS": None, - "LEAPS1": None - }, + historical_name={ + 'GASP': ['INGASP.CLMWFU', 'INGASP.CLMAX'], + 'FLOPS': None, + 'LEAPS1': None, + }, units='unitless', - desc='maximum lift coefficient from flaps model when flaps are up ' - '(not deployed)', + desc='maximum lift coefficient from flaps model when flaps are up (not deployed)', + default_value=0.0, ) add_meta_data( # NOTE: user override (no scaling) Mission.Design.MACH, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CRMACH', - "FLOPS": 'AERIN.FMDES', - # [ # inputs - # '&DEFINE.AERIN.FMDES', 'OSWALD.FMDES' - # # outputs - # '~EDET.DESM', '~MDESN.DESM' - # ], - "LEAPS1": ['aircraft.inputs.L0_design_variables.design_mach', - 'aircraft.outputs.L0_design_variables.design_mach', - ] - }, + historical_name={ + 'GASP': 'INGASP.CRMACH', + 'FLOPS': 'AERIN.FMDES', + # [ # inputs + # '&DEFINE.AERIN.FMDES', 'OSWALD.FMDES' + # # outputs + # '~EDET.DESM', '~MDESN.DESM' + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_design_variables.design_mach', + 'aircraft.outputs.L0_design_variables.design_mach', + ], + }, units='unitless', desc='aircraft design Mach number', + default_value=0.0, ) add_meta_data( Mission.Design.RANGE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ARNGE', - # ['&DEFINE.CONFIN.DESRNG', 'CONFIG.DESRNG'], - "FLOPS": 'CONFIN.DESRNG', - "LEAPS1": 'aircraft.inputs.L0_configuration.design_range' - }, + historical_name={ + 'GASP': 'INGASP.ARNGE', + # ['&DEFINE.CONFIN.DESRNG', 'CONFIG.DESRNG'], + 'FLOPS': 'CONFIN.DESRNG', + 'LEAPS1': 'aircraft.inputs.L0_configuration.design_range', + }, units='NM', desc='the aircraft target distance', default_value=0.0, @@ -7028,10 +7274,7 @@ add_meta_data( Mission.Design.RATE_OF_CLIMB_AT_TOP_OF_CLIMB, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ROCTOC', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.ROCTOC', 'FLOPS': None, 'LEAPS1': None}, option=True, units='ft/min', desc='The required rate of climb at top of climb', @@ -7041,31 +7284,32 @@ add_meta_data( Mission.Design.RESERVE_FUEL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="lbm", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='lbm', desc='the total fuel reserves which is the sum of: ' - 'RESERVE_FUEL_BURNED, RESERVE_FUEL_ADDITIONAL, RESERVE_FUEL_FRACTION', + 'RESERVE_FUEL_BURNED, RESERVE_FUEL_ADDITIONAL, RESERVE_FUEL_FRACTION', default_value=0, ) add_meta_data( # TODO move to Engine? + # TODO this isn't actually tied to the engines in any way - user provided value is + # arbitrary and will not update as engines resize Mission.Design.THRUST_TAKEOFF_PER_ENG, meta_data=_MetaData, - historical_name={"GASP": None, - # FLOPS may scale the input value as it resizes the engine if requested by - # the user - # ['&DEFINE.AERIN.THROFF', 'LANDG.THROF', 'LANDG.THROFF'], - "FLOPS": 'AERIN.THROFF', - # LEAPS1 uses the average thrust_takeoff of all operational engines - # actually on the airplane, possibly after resizing (as with FLOPS) - "LEAPS1": ['aircraft.inputs.L0_engine.thrust_takeoff', - '(SimpleTakeoff)self.thrust', - ] - }, + historical_name={ + 'GASP': None, + # FLOPS may scale the input value as it resizes the engine if requested by + # the user + # ['&DEFINE.AERIN.THROFF', 'LANDG.THROF', 'LANDG.THROFF'], + 'FLOPS': 'AERIN.THROFF', + # LEAPS1 uses the average thrust_takeoff of all operational engines + # actually on the airplane, possibly after resizing (as with FLOPS) + 'LEAPS1': [ + 'aircraft.inputs.L0_engine.thrust_takeoff', + '(SimpleTakeoff)self.thrust', + ], + }, units='lbf', # need better description of what state. rolling takeoff condition? alt? mach? desc='thrust on the aircraft for takeoff', @@ -7085,10 +7329,7 @@ add_meta_data( Mission.Landing.AIRPORT_ALTITUDE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.ALTLND', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.ALTLND', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='altitude of airport where aircraft lands', default_value=0, @@ -7097,10 +7338,7 @@ add_meta_data( Mission.Landing.BRAKING_DELAY, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.TDELAY', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.TDELAY', 'FLOPS': None, 'LEAPS1': None}, units='s', desc='time delay between touchdown and the application of brakes', default_value=1, @@ -7114,17 +7352,16 @@ # 'FLOPS': ['&DEFTOL.TOLIN.BRAKMU', 'BALFLD.BRAKMU'], # 'GASP': None, # 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.braking_mu'}, - historical_name={'FLOPS': None, 'GASP': None, 'LEAPS1': None}, default_value=0.3, + historical_name={'FLOPS': None, 'GASP': None, 'LEAPS1': None}, + default_value=0.3, units='unitless', - desc='landing coefficient of friction, with brakes on') + desc='landing coefficient of friction, with brakes on', +) add_meta_data( Mission.Landing.DRAG_COEFFICIENT_FLAP_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DCD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DCD', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='drag coefficient increment at landing due to flaps', ) @@ -7132,10 +7369,11 @@ add_meta_data( Mission.Landing.DRAG_COEFFICIENT_MIN, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.CDMLD', # ['&DEFINE.AERIN.CDMLD', 'LANDG.CDMLD'], - "LEAPS1": None - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.CDMLD', # ['&DEFINE.AERIN.CDMLD', 'LANDG.CDMLD'], + 'LEAPS1': None, + }, units='unitless', desc='Minimum drag coefficient for takeoff. Typically this is CD at zero lift.', default_value=0.0, @@ -7144,22 +7382,20 @@ add_meta_data( Mission.Landing.FIELD_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~ANALYS.FARLDG', - "LEAPS1": '(SimpleLanding)self.landing_distance' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~ANALYS.FARLDG', + 'LEAPS1': '(SimpleLanding)self.landing_distance', + }, units='ft', - desc='FAR landing field length' + desc='FAR landing field length', ) add_meta_data( Mission.Landing.FLARE_RATE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'TOLIN.VANGLD', - "LEAPS1": None - }, - units="deg/s", + historical_name={'GASP': None, 'FLOPS': 'TOLIN.VANGLD', 'LEAPS1': None}, + units='deg/s', desc='flare rate in detailed landing', default_value=2.0, ) @@ -7167,11 +7403,8 @@ add_meta_data( Mission.Landing.GLIDE_TO_STALL_RATIO, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.VRATT', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.VRATT', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='ratio of glide (approach) speed to stall speed', default_value=1.3, ) @@ -7179,55 +7412,48 @@ add_meta_data( Mission.Landing.GROUND_DISTANCE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DLT', # Is DLT actual landing distance or field length? - "FLOPS": None, - "LEAPS1": None - }, + historical_name={ + 'GASP': 'INGASP.DLT', # Is DLT actual landing distance or field length? + 'FLOPS': None, + 'LEAPS1': None, + }, units='ft', - desc='distance covered over the ground during landing' + desc='distance covered over the ground during landing', ) add_meta_data( Mission.Landing.INITIAL_ALTITUDE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.HIN', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.HIN', 'FLOPS': None, 'LEAPS1': None}, units='ft', - desc='altitude where landing calculations begin' + desc='altitude where landing calculations begin', ) add_meta_data( Mission.Landing.INITIAL_MACH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", - desc='approach mach number', - default_value=0.1 + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + desc='approach Mach number', + default_value=0.1, ) add_meta_data( Mission.Landing.INITIAL_VELOCITY, meta_data=_MetaData, - historical_name={"GASP": "INGASP.VGL", - "FLOPS": 'AERIN.VAPPR', - "LEAPS1": '(SimpleLanding)self.vapp' - }, + historical_name={ + 'GASP': 'INGASP.VGL', + 'FLOPS': 'AERIN.VAPPR', + 'LEAPS1': '(SimpleLanding)self.vapp', + }, units='ft/s', - desc='approach velocity' + desc='approach velocity', ) add_meta_data( Mission.Landing.LIFT_COEFFICIENT_FLAP_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DCL', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DCL', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='lift coefficient increment at landing due to flaps', ) @@ -7238,23 +7464,21 @@ # CLLDM (this variable) Mission.Landing.LIFT_COEFFICIENT_MAX, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CLMWLD', - "FLOPS": 'AERIN.CLLDM', # ['&DEFINE.AERIN.CLLDM', 'LANDG.CLLDM'], - "LEAPS1": 'aircraft.inputs.L0_takeoff_and_landing.max_landing_lift_coeff' - }, + historical_name={ + 'GASP': 'INGASP.CLMWLD', + 'FLOPS': 'AERIN.CLLDM', # ['&DEFINE.AERIN.CLLDM', 'LANDG.CLLDM'], + 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.max_landing_lift_coeff', + }, units='unitless', desc='maximum lift coefficient for landing', - default_value=3.0, + default_value=0.0, ) add_meta_data( Mission.Landing.MAXIMUM_FLARE_LOAD_FACTOR, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.XLFMX', - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': 'INGASP.XLFMX', 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='maximum load factor during landing flare', default_value=1.15, ) @@ -7262,10 +7486,7 @@ add_meta_data( Mission.Landing.MAXIMUM_SINK_RATE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.RSMX', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.RSMX', 'FLOPS': None, 'LEAPS1': None}, units='ft/min', desc='maximum rate of sink during glide', default_value=1000, @@ -7274,10 +7495,7 @@ add_meta_data( Mission.Landing.OBSTACLE_HEIGHT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.HAPP', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.HAPP', 'FLOPS': None, 'LEAPS1': None}, units='ft', desc='landing obstacle height above the ground at airport altitude', default_value=50, @@ -7296,8 +7514,7 @@ # }, historical_name={'FLOPS': None, 'GASP': None, 'LEAPS1': None}, units='unitless', - desc='coefficient of rolling friction for groundroll ' - 'portion of takeoff', + desc='coefficient of rolling friction for groundroll portion of takeoff', default_value=0.025, ) @@ -7330,10 +7547,7 @@ add_meta_data( Mission.Landing.STALL_VELOCITY, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.VST', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.VST', 'FLOPS': None, 'LEAPS1': None}, units='ft/s', desc='stall speed during approach', ) @@ -7341,24 +7555,22 @@ add_meta_data( Mission.Landing.TOUCHDOWN_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # ['~ANALYS.WLDG', '~LNDING.GROSWT'], - "LEAPS1": '(SimpleLanding)self.weight' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # ['~ANALYS.WLDG', '~LNDING.GROSWT'], + 'LEAPS1': '(SimpleLanding)self.weight', + }, units='lbm', desc='computed mass of aircraft for landing, is only ' - 'required to be equal to Aircraft.Design.TOUCHDOWN_MASS ' - 'when the design case is being run ' - 'for HEIGHT_ENERGY missions this is the mass at the end of the last regular phase (non-reserve phase)', + 'required to be equal to Aircraft.Design.TOUCHDOWN_MASS ' + 'when the design case is being run ' + 'for HEIGHT_ENERGY missions this is the mass at the end of the last regular phase (non-reserve phase)', ) add_meta_data( Mission.Landing.TOUCHDOWN_SINK_RATE, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.SINKTD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.SINKTD', 'FLOPS': None, 'LEAPS1': None}, units='ft/s', desc='sink rate at touchdown', default_value=3, @@ -7377,25 +7589,18 @@ add_meta_data( Mission.Objectives.FUEL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='regularized objective that minimizes total fuel mass subject ' - 'to other necessary additions', + 'to other necessary additions', ) add_meta_data( Mission.Objectives.RANGE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='unitless', - desc='regularized objective that maximizes range subject to other ' - 'necessary additions', + desc='regularized objective that maximizes range subject to other necessary additions', ) # _____ @@ -7411,47 +7616,59 @@ add_meta_data( Mission.Summary.CRUISE_MACH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'CONFIN.VCMN', - # [ # inputs - # '&DEFINE.CONFIN.VCMN', 'PARVAR.DVD(1,8)', - # # outputs - # 'CONFIG.VCMN', 'CONFIG.DVA(8)', '~FLOPS.DVA(8)', '~ANALYS.DVA(8)', - # # other - # 'MISSA.VCMIN', - # ], - "LEAPS1": ['aircraft.inputs.L0_design_variables.cruise_mach', - 'aircraft.outputs.L0_design_variables.cruise_mach', - 'aircraft.outputs.L0_design_variables.mission_cruise_mach', - ] - }, - units='unitless', - desc='aircraft cruise mach number', + historical_name={ + 'GASP': None, + 'FLOPS': 'CONFIN.VCMN', + # [ # inputs + # '&DEFINE.CONFIN.VCMN', 'PARVAR.DVD(1,8)', + # # outputs + # 'CONFIG.VCMN', 'CONFIG.DVA(8)', '~FLOPS.DVA(8)', '~ANALYS.DVA(8)', + # # other + # 'MISSA.VCMIN', + # ], + 'LEAPS1': [ + 'aircraft.inputs.L0_design_variables.cruise_mach', + 'aircraft.outputs.L0_design_variables.cruise_mach', + 'aircraft.outputs.L0_design_variables.mission_cruise_mach', + ], + }, + units='unitless', + desc='aircraft cruise Mach number', default_value=0.0, # TODO: required ) add_meta_data( Mission.Summary.CRUISE_MASS_FINAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='mass of the aircraft at the end of cruise', default_value=0.0, ) +add_meta_data( + Mission.Summary.FINAL_MASS, + meta_data=_MetaData, + historical_name={'GASP': 'None', 'FLOPS': None, 'LEAPS1': None}, # TODO: Check on these + units='lbm', + desc='The final weight of the vehicle at the end of the last regular_phase (does not include reserve phases).', +) + +add_meta_data( + Mission.Summary.FINAL_TIME, + meta_data=_MetaData, + historical_name={'GASP': 'None', 'FLOPS': None, 'LEAPS1': None}, # TODO: Check on these + units='min', + desc='Total mission time from the start of the first regular_phase' + 'to the end of the last regular_phase (does not include reserve phases).', +) + add_meta_data( Mission.Summary.FUEL_BURNED, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='fuel burned during regular phases, this ' - 'does not include fuel burned in reserve phases' + desc='fuel burned during regular phases, this does not include fuel burned in reserve phases', ) # NOTE if per-mission level scaling is not best mapping for GASP's 'CKFF', map @@ -7461,65 +7678,109 @@ add_meta_data( Mission.Summary.FUEL_FLOW_SCALER, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CKFF', - "FLOPS": 'MISSIN.FACT', # ['&DEFMSS.MISSIN.FACT', 'TRNSF.FACT'], - "LEAPS1": ['aircraft.inputs.L0_fuel_flow.overall_factor'] - }, + historical_name={ + 'GASP': 'INGASP.CKFF', + 'FLOPS': 'MISSIN.FACT', # ['&DEFMSS.MISSIN.FACT', 'TRNSF.FACT'], + 'LEAPS1': ['aircraft.inputs.L0_fuel_flow.overall_factor'], + }, units='unitless', desc='scale factor on overall fuel flow', default_value=1.0, - option=True + option=True, +) + +add_meta_data( + Mission.Summary.FUEL_MASS, + meta_data=_MetaData, + historical_name={ + 'GASP': 'INGASP.WFADES', + 'FLOPS': None, # ['WSP(38, 2)', '~WEIGHT.FUELM', '~INERT.FUELM'], + 'LEAPS1': [ + '(WeightABC)self._fuel_weight', + 'aircraft.outputs.L0_weights_summary.fuel_weight', + ], + }, + units='lbm', + desc='fuel carried by the aircraft when it is on the ramp at the beginning of the mission', + default_value=0.0, ) add_meta_data( Mission.Summary.GROSS_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', desc='gross takeoff mass of aircraft for that specific mission, not ' - 'necessarily the value for the aircraft`s design mission' + 'necessarily the value for the aircraft`s design mission', +) + +add_meta_data( + Mission.Summary.OPERATING_MASS, + meta_data=_MetaData, + # TODO: check with Aviary and GASPy engineers to ensure these are indeed + # defined the same way + historical_name={ + 'GASP': 'INGASP.OWE', + # ['WTS.WSP(33, 2)', '~WEIGHT.WOWE', '~WTSTAT.WSP(33, 2)'], + 'FLOPS': 'MISSIN.DOWE', + 'LEAPS1': [ + '(WeightABC)self._operating_weight_empty', + 'aircraft.outputs.L0_weights_summary.operating_weight_empty', + ], + }, + units='lbm', + desc='operating mass of the aircraft, or aircraft mass without mission fuel, or passengers.' + 'Includes crew, unusable fuel, oil, and operational items like cargo containers and passenger ' + 'service mass.', + default_value=0.0, ) add_meta_data( Mission.Summary.RANGE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='NM', desc='actual range that the aircraft flies, whether ' - 'it is a design case or an off design case. Equal ' - 'to Mission.Design.RANGE value in the design case.' + 'it is a design case or an off design case. Equal ' + 'to Mission.Design.RANGE value in the design case.', ) add_meta_data( Mission.Summary.RESERVE_FUEL_BURNED, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='fuel burned during reserve phases, this ' - 'does not include fuel burned in regular phases', - default_value=0., + desc='fuel burned during reserve phases, this does not include fuel burned in regular phases', + default_value=0.0, ) add_meta_data( Mission.Summary.TOTAL_FUEL_MASS, meta_data=_MetaData, - historical_name={"GASP": "INGASP.WFA", - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.WFA', 'FLOPS': None, 'LEAPS1': None}, + units='lbm', + # Note: In GASP, WFA does not include fuel margin. + desc='total fuel carried at the beginnning of a mission includes fuel burned in the mission, ' + 'reserve fuel and fuel margin', +) + +add_meta_data( + Mission.Summary.ZERO_FUEL_MASS, + meta_data=_MetaData, + historical_name={ + 'GASP': None, + # ['WTS.WSP(37,2)', '~WEIGHT.WZF', '~WTSTAT.WSP(37,2)'], + 'FLOPS': None, + 'LEAPS1': [ + '(WeightABC)self._zero_fuel_weight', + 'aircraft.outputs.L0_weights.zero_fuel_weight', + 'aircraft.outputs.L0_weights_summary.zero_fuel_weight', + ], + }, units='lbm', - desc='total fuel carried at the beginnning of a mission ' - 'includes fuel burned in the mission, reserve fuel ' - 'and fuel margin', + desc='Aircraft zero fuel mass, which includes structural mass (empty weight) and payload mass ' + '(passengers, baggage, and cargo)', + default_value=0.0, ) @@ -7534,12 +7795,9 @@ add_meta_data( Mission.Takeoff.AIRPORT_ALTITUDE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='ft', - desc='altitude of airport where aircraft takes off' + desc='altitude of airport where aircraft takes off', ) add_meta_data( @@ -7549,30 +7807,26 @@ # ['&DEFTOL.TOLIN.ALPRUN', 'BALFLD.ALPRUN', '~CLGRAD.ALPRUN'], 'FLOPS': 'TOLIN.ALPRUN', 'GASP': None, - 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.alpha_runway'}, + 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.alpha_runway', + }, option=True, - default_value=0., + default_value=0.0, units='deg', - desc='angle of attack on ground') + desc='angle of attack on ground', +) add_meta_data( Mission.Takeoff.ASCENT_DURATION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='s', desc='duration of the ascent phase of takeoff', ) add_meta_data( - Mission.Takeoff.ASCENT_T_INTIIAL, + Mission.Takeoff.ASCENT_T_INITIAL, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='s', desc='time that the ascent phase of takeoff starts at', default_value=10, @@ -7585,18 +7839,17 @@ historical_name={ 'FLOPS': 'TOLIN.BRAKMU', # ['&DEFTOL.TOLIN.BRAKMU', 'BALFLD.BRAKMU'], 'GASP': None, - 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.braking_mu'}, + 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.braking_mu', + }, default_value=0.3, units='unitless', - desc='takeoff coefficient of friction, with brakes on') + desc='takeoff coefficient of friction, with brakes on', +) add_meta_data( Mission.Takeoff.DECISION_SPEED_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DV1', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DV1', 'FLOPS': None, 'LEAPS1': None}, units='kn', desc='increment of engine failure decision speed above stall speed', default_value=5, @@ -7605,10 +7858,7 @@ add_meta_data( Mission.Takeoff.DRAG_COEFFICIENT_FLAP_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DCD', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DCD', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='drag coefficient increment at takeoff due to flaps', ) @@ -7616,10 +7866,11 @@ add_meta_data( Mission.Takeoff.DRAG_COEFFICIENT_MIN, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'AERIN.CDMTO', # ['&DEFINE.AERIN.CDMTO', 'LANDG.CDMTO'], - "LEAPS1": None - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'AERIN.CDMTO', # ['&DEFINE.AERIN.CDMTO', 'LANDG.CDMTO'], + 'LEAPS1': None, + }, units='unitless', desc='Minimum drag coefficient for takeoff. Typically this is CD at zero lift.', default_value=0.0, @@ -7628,22 +7879,24 @@ add_meta_data( Mission.Takeoff.FIELD_LENGTH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~ANALYS.FAROFF', - "LEAPS1": '(SimpleTakeoff)self.takeoff_distance' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~ANALYS.FAROFF', + 'LEAPS1': '(SimpleTakeoff)self.takeoff_distance', + }, units='ft', - desc='FAR takeoff field length' + desc='FAR takeoff field length', ) add_meta_data( Mission.Takeoff.FINAL_ALTITUDE, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFTOL.TOLIN.OBSTO', 'TOCOMM.OBSTO', 'TOCOMM.DUMC(8)'], - "FLOPS": 'TOLIN.OBSTO', - "LEAPS1": 'aircraft.inputs.L0_takeoff_and_landing.obstacle_height' - }, + historical_name={ + 'GASP': None, + # ['&DEFTOL.TOLIN.OBSTO', 'TOCOMM.OBSTO', 'TOCOMM.DUMC(8)'], + 'FLOPS': 'TOLIN.OBSTO', + 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.obstacle_height', + }, units='ft', desc='altitude of aircraft at the end of takeoff', # Note default value is aircraft type dependent @@ -7655,24 +7908,21 @@ add_meta_data( Mission.Takeoff.FINAL_MACH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None, - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, + 'LEAPS1': None, + }, units='unitless', - desc='Mach number of aircraft after taking off and ' - 'clearing a 35 foot obstacle' + desc='Mach number of aircraft after taking off and clearing a 35 foot obstacle', ) add_meta_data( Mission.Takeoff.FINAL_MASS, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='lbm', - desc='mass after aircraft has cleared 35 ft obstacle' + desc='mass after aircraft has cleared 35 ft obstacle', ) add_meta_data( @@ -7681,13 +7931,13 @@ # - correct Aviary equations? Mission.Takeoff.FINAL_VELOCITY, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~TOFF.V2', - "LEAPS1": '(ClimbToObstacle)self.V2' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~TOFF.V2', + 'LEAPS1': '(ClimbToObstacle)self.V2', + }, units='m/s', - desc='velocity of aircraft after taking off and ' - 'clearing a 35 foot obstacle' + desc='velocity of aircraft after taking off and clearing a 35 foot obstacle', ) add_meta_data( @@ -7696,36 +7946,32 @@ # part of takeoff Mission.Takeoff.FUEL_SIMPLE, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFMSS.MISSIN.FTKOFL', 'FFLALL.FTKOFL', '~MISSON.TAKOFL'], - "FLOPS": 'MISSIN.FTKOFL', - "LEAPS1": ['aircraft.inputs.L0_mission.fixed_takeoff_fuel', - 'aircraft.outputs.L0_takeoff_and_landing.takeoff_fuel', - ] - }, + historical_name={ + 'GASP': None, + # ['&DEFMSS.MISSIN.FTKOFL', 'FFLALL.FTKOFL', '~MISSON.TAKOFL'], + 'FLOPS': 'MISSIN.FTKOFL', + 'LEAPS1': [ + 'aircraft.inputs.L0_mission.fixed_takeoff_fuel', + 'aircraft.outputs.L0_takeoff_and_landing.takeoff_fuel', + ], + }, units='lbm', desc='fuel burned during simple takeoff calculation', - default_value=None, + default_value=0.0, ) add_meta_data( Mission.Takeoff.GROUND_DISTANCE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, units='ft', - desc='ground distance covered by takeoff with all engines operating' + desc='ground distance covered by takeoff with all engines operating', ) add_meta_data( Mission.Takeoff.LIFT_COEFFICIENT_FLAP_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DCL', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DCL', 'FLOPS': None, 'LEAPS1': None}, units='unitless', desc='lift coefficient increment at takeoff due to flaps', ) @@ -7733,11 +7979,12 @@ add_meta_data( Mission.Takeoff.LIFT_COEFFICIENT_MAX, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.CLMWTO', - # ['&DEFINE.AERIN.CLTOM', 'LANDG.CLTOM', '~DEFTOL.CLTOA'], - "FLOPS": 'AERIN.CLTOM', - "LEAPS1": 'aircraft.inputs.L0_takeoff_and_landing.max_takeoff_lift_coeff' - }, + historical_name={ + 'GASP': 'INGASP.CLMWTO', + # ['&DEFINE.AERIN.CLTOM', 'LANDG.CLTOM', '~DEFTOL.CLTOA'], + 'FLOPS': 'AERIN.CLTOM', + 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.max_takeoff_lift_coeff', + }, units='unitless', desc='maximum lift coefficient for takeoff', default_value=2.0, @@ -7746,12 +7993,13 @@ add_meta_data( Mission.Takeoff.LIFT_OVER_DRAG, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, # '~ANALYS.CLOD', - "LEAPS1": '(SimpleTakeoff)self.lift_over_drag_ratio' - }, + historical_name={ + 'GASP': None, + 'FLOPS': None, # '~ANALYS.CLOD', + 'LEAPS1': '(SimpleTakeoff)self.lift_over_drag_ratio', + }, units='unitless', - desc='ratio of lift to drag at takeoff' + desc='ratio of lift to drag at takeoff', ) add_meta_data( @@ -7766,36 +8014,34 @@ # Note default value is aircraft type dependent # - transport: 35 ft # assume transport for now - default_value=35., + default_value=35.0, units='ft', - desc='takeoff obstacle height above the ground at airport altitude' + desc='takeoff obstacle height above the ground at airport altitude', ) add_meta_data( Mission.Takeoff.ROLLING_FRICTION_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": None, - # ['&DEFTOL.TOLIN.ROLLMU', 'BALFLD.ROLLMU'], - "FLOPS": 'TOLIN.ROLLMU', - "LEAPS1": ['aircraft.inputs.L0_takeoff_and_landing.rolling_mu', - '(GroundRoll)self.mu', - '(Rotate)self.mu', - '(GroundBrake)self.rolling_mu', - ] - }, - units='unitless', - desc='coefficient of rolling friction for groundroll ' - 'portion of takeoff', + historical_name={ + 'GASP': None, + # ['&DEFTOL.TOLIN.ROLLMU', 'BALFLD.ROLLMU'], + 'FLOPS': 'TOLIN.ROLLMU', + 'LEAPS1': [ + 'aircraft.inputs.L0_takeoff_and_landing.rolling_mu', + '(GroundRoll)self.mu', + '(Rotate)self.mu', + '(GroundBrake)self.rolling_mu', + ], + }, + units='unitless', + desc='coefficient of rolling friction for groundroll portion of takeoff', default_value=0.025, ) add_meta_data( Mission.Takeoff.ROTATION_SPEED_INCREMENT, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DVR', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DVR', 'FLOPS': None, 'LEAPS1': None}, units='kn', desc='increment of takeoff rotation speed above engine failure decision speed', default_value=5, @@ -7804,10 +8050,7 @@ add_meta_data( Mission.Takeoff.ROTATION_VELOCITY, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.VR', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.VR', 'FLOPS': None, 'LEAPS1': None}, units='kn', desc='rotation velocity', ) @@ -7815,10 +8058,11 @@ add_meta_data( Mission.Takeoff.SPOILER_DRAG_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'TOLIN.CDSPOL', # '&DEFTOL.TOLIN.CDSPOL', - "LEAPS1": None - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'TOLIN.CDSPOL', # '&DEFTOL.TOLIN.CDSPOL', + 'LEAPS1': None, + }, units='unitless', desc='drag coefficient for spoilers during takeoff abort', default_value=0.0, @@ -7827,10 +8071,11 @@ add_meta_data( Mission.Takeoff.SPOILER_LIFT_COEFFICIENT, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": 'TOLIN.CLSPOL', # '&DEFTOL.TOLIN.CLSPOL', - "LEAPS1": None - }, + historical_name={ + 'GASP': None, + 'FLOPS': 'TOLIN.CLSPOL', # '&DEFTOL.TOLIN.CLSPOL', + 'LEAPS1': None, + }, units='unitless', desc='lift coefficient for spoilers during takeoff abort', default_value=0.0, @@ -7842,11 +8087,13 @@ historical_name={ 'FLOPS': 'TOLIN.TINC', # ['&DEFTOL.TOLIN.TINC', 'BALFLD.TINC', '~CLGRAD.TINC'], 'GASP': None, - 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.thrust_incidence_angle'}, + 'LEAPS1': 'aircraft.inputs.L0_takeoff_and_landing.thrust_incidence_angle', + }, option=True, - default_value=0., + default_value=0.0, units='deg', - desc='thrust incidence on ground') + desc='thrust incidence on ground', +) # _______ _ # |__ __| (_) @@ -7859,10 +8106,7 @@ add_meta_data( Mission.Taxi.DURATION, meta_data=_MetaData, - historical_name={"GASP": 'INGASP.DELTT', - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': 'INGASP.DELTT', 'FLOPS': None, 'LEAPS1': None}, units='h', desc='time spent taxiing before takeoff', option=True, @@ -7872,11 +8116,8 @@ add_meta_data( Mission.Taxi.MACH, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, - units="unitless", + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', desc='speed during taxi, must be nonzero if pycycle is enabled', option=True, default_value=0.0001, @@ -7894,13 +8135,20 @@ # | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | # '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' +add_meta_data( + Settings.AERODYNAMICS_METHOD, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + desc="Sets which legacy code's methods will be used for aerodynamics estimation", + option=True, + types=LegacyCode, + default_value=None, +) + add_meta_data( Settings.EQUATIONS_OF_MOTION, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, desc='Sets which equations of motion Aviary will use in mission analysis', option=True, types=EquationsOfMotion, @@ -7910,38 +8158,47 @@ add_meta_data( Settings.MASS_METHOD, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, desc="Sets which legacy code's methods will be used for mass estimation", option=True, types=LegacyCode, - default_value=None + default_value=None, +) + +add_meta_data( + Settings.PAYLOAD_RANGE, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, + units='unitless', + option=True, + default_value=False, + types=bool, + desc='if True, run a set of off-design missions to create a payload range diagram.', ) add_meta_data( Settings.PROBLEM_TYPE, meta_data=_MetaData, - historical_name={"GASP": None, - "FLOPS": None, - "LEAPS1": None - }, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, desc="Select from Aviary's built in problem types: Sizing, Alternate, and Fallout", option=True, types=ProblemType, - default_value=None + default_value=None, ) add_meta_data( - Settings.VERBOSITY, meta_data=_MetaData, - historical_name={"GASP": None, "FLOPS": None, "LEAPS1": None}, + Settings.VERBOSITY, + meta_data=_MetaData, + historical_name={'GASP': None, 'FLOPS': None, 'LEAPS1': None}, desc='Sets how much information Aviary outputs when run. Options include:' '0. QUIET: All output except errors are suppressed' '1. BRIEF: Only important information is output, in human-readable format' '2. VERBOSE: All user-relevant information is output, in human-readable format' '3. DEBUG: Any information can be outtputed, including warnings, intermediate calculations, etc., with no formatting requirement', - option=True, types=Verbosity, default_value=Verbosity.BRIEF) + option=True, + types=Verbosity, + default_value=Verbosity.BRIEF, +) # here we create a copy of the Aviary-core metadata. The reason for this # copy is that if we simply imported the Aviary _MetaData in all the diff --git a/aviary/variable_info/variables.py b/aviary/variable_info/variables.py index e720115c34..0e2aaca9ae 100644 --- a/aviary/variable_info/variables.py +++ b/aviary/variable_info/variables.py @@ -1,11 +1,11 @@ -''' +""" This is a variable hierarchy that is for a single mission. Each mission gets a copy of this hierarchy. -''' +""" class Aircraft: - """Aircraft data hierarchy""" + """Aircraft data hierarchy.""" class AirConditioning: MASS = 'aircraft:air_conditioning:mass' @@ -36,11 +36,12 @@ class Battery: VOLUME = 'aircraft:battery:volume' class BWB: - CABIN_AREA = 'aircraft:blended_wing_body_design:cabin_area' + DETAILED_WING_PROVIDED = 'aircraft:blended_wing_body_design:detailed_wing_provided' + MAX_NUM_BAYS = 'aircraft:blended_wing_body_design:max_num_bays' NUM_BAYS = 'aircraft:blended_wing_body_design:num_bays' - - PASSENGER_LEADING_EDGE_SWEEP = \ + PASSENGER_LEADING_EDGE_SWEEP = ( 'aircraft:blended_wing_body_design:passenger_leading_edge_sweep' + ) class Canard: AREA = 'aircraft:canard:area' @@ -59,48 +60,42 @@ class Canard: class Controls: COCKPIT_CONTROL_MASS_SCALER = 'aircraft:controls:cockpit_control_mass_scaler' CONTROL_MASS_INCREMENT = 'aircraft:controls:control_mass_increment' - STABILITY_AUGMENTATION_SYSTEM_MASS = \ - 'aircraft:controls:stability_augmentation_system_mass' - STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER = \ + STABILITY_AUGMENTATION_SYSTEM_MASS = 'aircraft:controls:stability_augmentation_system_mass' + STABILITY_AUGMENTATION_SYSTEM_MASS_SCALER = ( 'aircraft:controls:stability_augmentation_system_mass_scaler' + ) TOTAL_MASS = 'aircraft:controls:total_mass' class CrewPayload: BAGGAGE_MASS = 'aircraft:crew_and_payload:baggage_mass' - BAGGAGE_MASS_PER_PASSENGER = \ - 'aircraft:crew_and_payload:baggage_mass_per_passenger' + BAGGAGE_MASS_PER_PASSENGER = 'aircraft:crew_and_payload:baggage_mass_per_passenger' - CARGO_CONTAINER_MASS = \ - 'aircraft:crew_and_payload:cargo_container_mass' + CARGO_CONTAINER_MASS = 'aircraft:crew_and_payload:cargo_container_mass' - CARGO_CONTAINER_MASS_SCALER = \ - 'aircraft:crew_and_payload:cargo_container_mass_scaler' + CARGO_CONTAINER_MASS_SCALER = 'aircraft:crew_and_payload:cargo_container_mass_scaler' CARGO_MASS = 'aircraft:crew_and_payload:cargo_mass' - CATERING_ITEMS_MASS_PER_PASSENGER = \ + CATERING_ITEMS_MASS_PER_PASSENGER = ( 'aircraft:crew_and_payload:catering_items_mass_per_passenger' + ) FLIGHT_CREW_MASS = 'aircraft:crew_and_payload:flight_crew_mass' - FLIGHT_CREW_MASS_SCALER = \ - 'aircraft:crew_and_payload:flight_crew_mass_scaler' + FLIGHT_CREW_MASS_SCALER = 'aircraft:crew_and_payload:flight_crew_mass_scaler' MASS_PER_PASSENGER = 'aircraft:crew_and_payload:mass_per_passenger' MISC_CARGO = 'aircraft:crew_and_payload:misc_cargo' - NON_FLIGHT_CREW_MASS = \ - 'aircraft:crew_and_payload:non_flight_crew_mass' + NON_FLIGHT_CREW_MASS = 'aircraft:crew_and_payload:non_flight_crew_mass' - NON_FLIGHT_CREW_MASS_SCALER = \ - 'aircraft:crew_and_payload:non_flight_crew_mass_scaler' + NON_FLIGHT_CREW_MASS_SCALER = 'aircraft:crew_and_payload:non_flight_crew_mass_scaler' NUM_BUSINESS_CLASS = 'aircraft:crew_and_payload:num_business_class' NUM_FIRST_CLASS = 'aircraft:crew_and_payload:num_first_class' - NUM_FLIGHT_ATTENDANTS = \ - 'aircraft:crew_and_payload:num_flight_attendants' + NUM_FLIGHT_ATTENDANTS = 'aircraft:crew_and_payload:num_flight_attendants' NUM_FLIGHT_CREW = 'aircraft:crew_and_payload:num_flight_crew' NUM_GALLEY_CREW = 'aircraft:crew_and_payload:num_galley_crew' @@ -108,31 +103,39 @@ class CrewPayload: NUM_PASSENGERS = 'aircraft:crew_and_payload:num_passengers' NUM_TOURIST_CLASS = 'aircraft:crew_and_payload:num_tourist_class' - PASSENGER_MASS = \ - 'aircraft:crew_and_payload:passenger_mass' - PASSENGER_MASS_WITH_BAGS = \ - 'aircraft:crew_and_payload:passenger_mass_with_bags' + PASSENGER_MASS = 'aircraft:crew_and_payload:passenger_mass' + PASSENGER_MASS_WITH_BAGS = 'aircraft:crew_and_payload:passenger_mass_with_bags' PASSENGER_PAYLOAD_MASS = 'aircraft:crew_and_payload:passenger_payload_mass' - PASSENGER_SERVICE_MASS = \ - 'aircraft:crew_and_payload:passenger_service_mass' + PASSENGER_SERVICE_MASS = 'aircraft:crew_and_payload:passenger_service_mass' - PASSENGER_SERVICE_MASS_PER_PASSENGER = \ + PASSENGER_SERVICE_MASS_PER_PASSENGER = ( 'aircraft:crew_and_payload:passenger_service_mass_per_passenger' + ) - PASSENGER_SERVICE_MASS_SCALER = \ - 'aircraft:crew_and_payload:passenger_service_mass_scaler' + PASSENGER_SERVICE_MASS_SCALER = 'aircraft:crew_and_payload:passenger_service_mass_scaler' TOTAL_PAYLOAD_MASS = 'aircraft:crew_and_payload:total_payload_mass' + ULD_MASS_PER_PASSENGER = 'aircraft:crew_and_payload:uld_mass_per_passenger' WATER_MASS_PER_OCCUPANT = 'aircraft:crew_and_payload:water_mass_per_occupant' WING_CARGO = 'aircraft:crew_and_payload:wing_cargo' class Design: + CARGO_MASS = 'aircraft:crew_and_payload:design:cargo_mass' + MAX_CARGO_MASS = 'aircraft:crew_and_payload:design:max_cargo_mass' NUM_BUSINESS_CLASS = 'aircraft:crew_and_payload:design:num_business_class' NUM_FIRST_CLASS = 'aircraft:crew_and_payload:design:num_first_class' NUM_TOURIST_CLASS = 'aircraft:crew_and_payload:design:num_tourist_class' NUM_PASSENGERS = 'aircraft:crew_and_payload:design:num_passengers' + NUM_SEATS_ABREAST_BUSINESS = ( + 'aircraft:crew_and_payload:design:num_seats_abreast_business' + ) + NUM_SEATS_ABREAST_FIRST = 'aircraft:crew_and_payload:design:num_seats_abreast_first' + NUM_SEATS_ABREAST_TOURIST = 'aircraft:crew_and_payload:design:num_seats_abreast_tourist' + SEAT_PITCH_BUSINESS = 'aircraft:crew_and_payload:design:seat_pitch_business' + SEAT_PITCH_FIRST = 'aircraft:crew_and_payload:design:seat_pitch_first' + SEAT_PITCH_TOURIST = 'aircraft:crew_and_payload:design:seat_pitch_tourist' class Design: # These variables are values that do not fall into a particular aircraft @@ -141,19 +144,18 @@ class Design: BASE_AREA = 'aircraft:design:base_area' CG_DELTA = 'aircraft:design:cg_delta' CHARACTERISTIC_LENGTHS = 'aircraft:design:characteristic_lengths' - COCKPIT_CONTROL_MASS_COEFFICIENT = \ - 'aircraft:design:cockpit_control_mass_coefficient' + COCKPIT_CONTROL_MASS_COEFFICIENT = 'aircraft:design:cockpit_control_mass_coefficient' COMPUTE_HTAIL_VOLUME_COEFF = 'aircraft:design:compute_htail_volume_coeff' COMPUTE_VTAIL_VOLUME_COEFF = 'aircraft:design:compute_vtail_volume_coeff' - DRAG_COEFFICIENT_INCREMENT = 'aircraft:design:drag_increment' + DRAG_COEFFICIENT_INCREMENT = 'aircraft:design:drag_coeff_increment' + DRAG_DIVERGENCE_SHIFT = 'aircraft:design:drag_divergence_shift' DRAG_POLAR = 'aircraft:design:drag_polar' EMERGENCY_EQUIPMENT_MASS = 'aircraft:design:emergency_equipment_mass' EMPTY_MASS = 'aircraft:design:empty_mass' EMPTY_MASS_MARGIN = 'aircraft:design:empty_mass_margin' - EMPTY_MASS_MARGIN_SCALER = \ - 'aircraft:design:empty_mass_margin_scaler' + EMPTY_MASS_MARGIN_SCALER = 'aircraft:design:empty_mass_margin_scaler' EXTERNAL_SUBSYSTEMS_MASS = 'aircraft:design:external_subsystems_mass' FINENESS = 'aircraft:design:fineness' @@ -163,17 +165,18 @@ class Design: LAMINAR_FLOW_LOWER = 'aircraft:design:laminar_flow_lower' LAMINAR_FLOW_UPPER = 'aircraft:design:laminar_flow_upper' - LANDING_TO_TAKEOFF_MASS_RATIO = \ - 'aircraft:design:landing_to_takeoff_mass_ratio' + LANDING_TO_TAKEOFF_MASS_RATIO = 'aircraft:design:landing_to_takeoff_mass_ratio' LIFT_CURVE_SLOPE = 'aircraft:design:lift_curve_slope' - LIFT_DEPENDENT_DRAG_COEFF_FACTOR = \ - 'aircraft:design:lift_dependent_drag_coeff_factor' + LIFT_DEPENDENT_DRAG_COEFF_FACTOR = 'aircraft:design:lift_dependent_drag_coeff_factor' + + LIFT_DEPENDENT_DRAG_POLAR = 'aircraft:design:lift_dependent_drag_polar' + LIFT_INDEPENDENT_DRAG_POLAR = 'aircraft:design:lift_independent_drag_polar' + LIFT_POLAR = 'aircraft:design:lift_polar' MAX_FUSELAGE_PITCH_ANGLE = 'aircraft:design:max_fuselage_pitch_angle' MAX_STRUCTURAL_SPEED = 'aircraft:design:max_structural_speed' - OPERATING_MASS = 'aircraft:design:operating_mass' PART25_STRUCTURAL_CATEGORY = 'aircraft:design:part25_structural_category' RESERVE_FUEL_ADDITIONAL = 'aircraft:design:reserve_fuel_additional' RESERVE_FUEL_FRACTION = 'aircraft:design:reserve_fuel_fraction' @@ -182,37 +185,32 @@ class Design: STRUCTURAL_MASS_INCREMENT = 'aircraft:design:structural_mass_increment' STRUCTURE_MASS = 'aircraft:design:structure_mass' - SUBSONIC_DRAG_COEFF_FACTOR = \ - 'aircraft:design:subsonic_drag_coeff_factor' - - SUPERCRITICAL_DIVERGENCE_SHIFT = 'aircraft:design:supercritical_drag_shift' + SUBSONIC_DRAG_COEFF_FACTOR = 'aircraft:design:subsonic_drag_coeff_factor' - SUPERSONIC_DRAG_COEFF_FACTOR = \ - 'aircraft:design:supersonic_drag_coeff_factor' + SUPERSONIC_DRAG_COEFF_FACTOR = 'aircraft:design:supersonic_drag_coeff_factor' SYSTEMS_EQUIP_MASS = 'aircraft:design:systems_equip_mass' SYSTEMS_EQUIP_MASS_BASE = 'aircraft:design:systems_equip_mass_base' THRUST_TO_WEIGHT_RATIO = 'aircraft:design:thrust_to_weight_ratio' TOTAL_WETTED_AREA = 'aircraft:design:total_wetted_area' TOUCHDOWN_MASS = 'aircraft:design:touchdown_mass' + TYPE = 'aircraft:design:type' ULF_CALCULATED_FROM_MANEUVER = 'aircraft:design:ulf_calculated_from_maneuver' USE_ALT_MASS = 'aircraft:design:use_alt_mass' WETTED_AREAS = 'aircraft:design:wetted_areas' - ZERO_FUEL_MASS = 'aircraft:design:zero_fuel_mass' - ZERO_LIFT_DRAG_COEFF_FACTOR = \ - 'aircraft:design:zero_lift_drag_coeff_factor' + WING_LOADING = 'aircraft:design:wing_loading' + ZERO_LIFT_DRAG_COEFF_FACTOR = 'aircraft:design:zero_lift_drag_coeff_factor' class Electrical: HAS_HYBRID_SYSTEM = 'aircraft:electrical:has_hybrid_system' HYBRID_CABLE_LENGTH = 'aircraft:electrical:hybrid_cable_length' MASS = 'aircraft:electrical:mass' MASS_SCALER = 'aircraft:electrical:mass_scaler' + SYSTEM_MASS_PER_PASSENGER = 'aircraft:electrical:system_mass_per_passenger' class Engine: ADDITIONAL_MASS = 'aircraft:engine:additional_mass' ADDITIONAL_MASS_FRACTION = 'aircraft:engine:additional_mass_fraction' - COMPUTE_PROPELLER_INSTALLATION_LOSS = \ - 'aircraft:engine:compute_propeller_installation_loss' CONSTANT_FUEL_CONSUMPTION = 'aircraft:engine:constant_fuel_consumption' CONTROLS_MASS = 'aircraft:engine:controls_mass' DATA_FILE = 'aircraft:engine:data_file' @@ -224,26 +222,21 @@ class Engine: FUEL_FLOW_SCALER_LINEAR_TERM = 'aircraft:engine:fuel_flow_scaler_linear_term' GENERATE_FLIGHT_IDLE = 'aircraft:engine:generate_flight_idle' GEOPOTENTIAL_ALT = 'aircraft:engine:geopotential_alt' + GLOBAL_HYBRID_THROTTLE = 'aircraft:engine:global_hybrid_throttle' + GLOBAL_THROTTLE = 'aircraft:engine:global_throttle' HAS_PROPELLERS = 'aircraft:engine:has_propellers' IGNORE_NEGATIVE_THRUST = 'aircraft:engine:ignore_negative_thrust' INTERPOLATION_METHOD = 'aircraft:engine:interpolation_method' + INTERPOLATION_SORT = 'aircraft:engine:interpolation_sort' MASS = 'aircraft:engine:mass' MASS_SCALER = 'aircraft:engine:mass_scaler' MASS_SPECIFIC = 'aircraft:engine:mass_specific' NUM_ENGINES = 'aircraft:engine:num_engines' NUM_FUSELAGE_ENGINES = 'aircraft:engine:num_fuselage_engines' - NUM_PROPELLER_BLADES = 'aircraft:engine:num_propeller_blades' NUM_WING_ENGINES = 'aircraft:engine:num_wing_engines' POD_MASS = 'aircraft:engine:pod_mass' POD_MASS_SCALER = 'aircraft:engine:pod_mass_scaler' POSITION_FACTOR = 'aircraft:engine:position_factor' - PROPELLER_ACTIVITY_FACTOR = 'aircraft:engine:propeller_activity_factor' - PROPELLER_DATA_FILE = 'aircraft:engine:propeller_data_file' - PROPELLER_DIAMETER = 'aircraft:engine:propeller_diameter' - PROPELLER_INTEGRATED_LIFT_COEFFICIENT = \ - 'aircraft:engine:propeller_integrated_lift_coefficient' - PROPELLER_TIP_MACH_MAX = 'propeller_tip_mach_max' - PROPELLER_TIP_SPEED_MAX = 'aircraft:engine:propeller_tip_speed_max' PYLON_FACTOR = 'aircraft:engine:pylon_factor' REFERENCE_DIAMETER = 'aircraft:engine:reference_diameter' REFERENCE_MASS = 'aircraft:engine:reference_mass' @@ -259,20 +252,29 @@ class Engine: THRUST_REVERSERS_MASS = 'aircraft:engine:thrust_reversers_mass' THRUST_REVERSERS_MASS_SCALER = 'aircraft:engine:thrust_reversers_mass_scaler' TYPE = 'aircraft:engine:type' - USE_PROPELLER_MAP = 'aircraft:engine:use_propeller_map' WING_LOCATIONS = 'aircraft:engine:wing_locations' class Gearbox: - EFFICIENCY = "aircraft:engine:gearbox:efficiency" - GEAR_RATIO = "aircraft:engine:gearbox:gear_ratio" - MASS = "aircraft:engine:gearbox:mass" - SHAFT_POWER_DESIGN = 'aircraft:engine:shaft_power_design' - SPECIFIC_TORQUE = "aircraft:engine:gearbox:specific_torque" + EFFICIENCY = 'aircraft:engine:gearbox:efficiency' + GEAR_RATIO = 'aircraft:engine:gearbox:gear_ratio' + MASS = 'aircraft:engine:gearbox:mass' + SHAFT_POWER_DESIGN = 'aircraft:engine:gearbox:shaft_power_design' + SPECIFIC_TORQUE = 'aircraft:engine:gearbox:specific_torque' class Motor: MASS = 'aircraft:engine:motor:mass' TORQUE_MAX = 'aircraft:engine:motor:torque_max' + class Propeller: + ACTIVITY_FACTOR = 'aircraft:engine:propeller:activity_factor' + COMPUTE_INSTALLATION_LOSS = 'aircraft:engine:propeller:compute_installation_loss' + DATA_FILE = 'aircraft:engine:propeller:data_file' + DIAMETER = 'aircraft:engine:propeller:diameter' + INTEGRATED_LIFT_COEFFICIENT = 'aircraft:engine:propeller:integrated_lift_coefficient' + NUM_BLADES = 'aircraft:engine:propeller:num_blades' + TIP_MACH_MAX = 'aircraft:engine:propeller:tip_mach_max' + TIP_SPEED_MAX = 'aircraft:engine:propeller:tip_speed_max' + class Fins: AREA = 'aircraft:fins:area' MASS = 'aircraft:fins:mass' @@ -283,14 +285,13 @@ class Fins: class Fuel: AUXILIARY_FUEL_CAPACITY = 'aircraft:fuel:auxiliary_fuel_capacity' BURN_PER_PASSENGER_MILE = 'aircraft:fuel:burn_per_passenger_mile' - CAPACITY_FACTOR = 'aircraft:fuel:capacity_factor' DENSITY = 'aircraft:fuel:density' - DENSITY_RATIO = 'aircraft:fuel:density_ratio' FUEL_MARGIN = 'aircraft:fuel:fuel_margin' FUEL_SYSTEM_MASS = 'aircraft:fuel:fuel_system_mass' FUEL_SYSTEM_MASS_COEFFICIENT = 'aircraft:fuel:fuel_system_mass_coefficient' FUEL_SYSTEM_MASS_SCALER = 'aircraft:fuel:fuel_system_mass_scaler' FUSELAGE_FUEL_CAPACITY = 'aircraft:fuel:fuselage_fuel_capacity' + IGNORE_FUEL_CAPACITY_CONSTRAINT = 'aircraft:fuel:ignore_fuel_capacity_constraint' NUM_TANKS = 'aircraft:fuel:num_tanks' TOTAL_CAPACITY = 'aircraft:fuel:total_capacity' TOTAL_VOLUME = 'aircraft:fuel:total_volume' @@ -312,21 +313,32 @@ class Furnishings: MASS = 'aircraft:furnishings:mass' MASS_BASE = 'aircraft:furnishings:mass_base' MASS_SCALER = 'aircraft:furnishings:mass_scaler' + USE_EMPIRICAL_EQUATION = 'aircraft:furnishings:use_empirical_equation' class Fuselage: + AFTBODY_MASS = 'aircraft:fuselage:aftbody_mass' + AFTBODY_MASS_PER_UNIT_AREA = 'aircraft:fuselage:aftbody_mass_per_unit_area' AISLE_WIDTH = 'aircraft:fuselage:aisle_width' AVG_DIAMETER = 'aircraft:fuselage:avg_diameter' + CABIN_AREA = 'aircraft:fuselage:cabin_area' CHARACTERISTIC_LENGTH = 'aircraft:fuselage:characteristic_length' CROSS_SECTION = 'aircraft:fuselage:cross_section' DELTA_DIAMETER = 'aircraft:fuselage:delta_diameter' DIAMETER_TO_WING_SPAN = 'aircraft:fuselage:diameter_to_wing_span' FINENESS = 'aircraft:fuselage:fineness' FLAT_PLATE_AREA_INCREMENT = 'aircraft:fuselage:flat_plate_area_increment' + FOREBODY_MASS = 'aircraft:fuselage:forebody_mass' FORM_FACTOR = 'aircraft:fuselage:form_factor' + HEIGHT_TO_WIDTH_RATIO = 'aircraft:fuselage:height_to_width_ratio' + HYDRAULIC_DIAMETER = 'aircraft:fuselage:hydraulic_diameter' LAMINAR_FLOW_LOWER = 'aircraft:fuselage:laminar_flow_lower' LAMINAR_FLOW_UPPER = 'aircraft:fuselage:laminar_flow_upper' LENGTH = 'aircraft:fuselage:length' LENGTH_TO_DIAMETER = 'aircraft:fuselage:length_to_diameter' + LIFT_COEFFICIENT_RATIO_BODY_TO_WING = ( + 'aircraft:fuselage:lift_coefficient_ratio_body_to_wing' + ) + LIFT_CURVE_SLOPE_MACH0 = 'aircraft:fuselage:lift_curve_slope_mach0' MASS = 'aircraft:fuselage:mass' MASS_COEFFICIENT = 'aircraft:fuselage:mass_coefficient' MASS_SCALER = 'aircraft:fuselage:mass_scaler' @@ -336,18 +348,18 @@ class Fuselage: NOSE_FINENESS = 'aircraft:fuselage:nose_fineness' NUM_AISLES = 'aircraft:fuselage:num_aisles' NUM_FUSELAGES = 'aircraft:fuselage:num_fuselages' - NUM_SEATS_ABREAST = 'aircraft:fuselage:num_seats_abreast' - PASSENGER_COMPARTMENT_LENGTH = \ - 'aircraft:fuselage:passenger_compartment_length' + PASSENGER_COMPARTMENT_LENGTH = 'aircraft:fuselage:passenger_compartment_length' PILOT_COMPARTMENT_LENGTH = 'aircraft:fuselage:pilot_compartment_length' PLANFORM_AREA = 'aircraft:fuselage:planform_area' PRESSURE_DIFFERENTIAL = 'aircraft:fuselage:pressure_differential' - SEAT_PITCH = 'aircraft:fuselage:seat_pitch' + PRESSURIZED_WIDTH_ADDITIONAL = 'aircraft:fuselage:pressurized_width_additional' SEAT_WIDTH = 'aircraft:fuselage:seat_width' + SIMPLE_LAYOUT = 'aircraft:fuselage:simple_layout' TAIL_FINENESS = 'aircraft:fuselage:tail_fineness' WETTED_AREA = 'aircraft:fuselage:wetted_area' + WETTED_AREA_RATIO_AFTBODY_TO_TOTAL = 'aircraft:fuselage:wetted_area_ratio_aftbody_to_total' WETTED_AREA_SCALER = 'aircraft:fuselage:wetted_area_scaler' class HorizontalTail: @@ -355,8 +367,7 @@ class HorizontalTail: ASPECT_RATIO = 'aircraft:horizontal_tail:aspect_ratio' AVERAGE_CHORD = 'aircraft:horizontal_tail:average_chord' - CHARACTERISTIC_LENGTH = \ - 'aircraft:horizontal_tail:characteristic_length' + CHARACTERISTIC_LENGTH = 'aircraft:horizontal_tail:characteristic_length' FINENESS = 'aircraft:horizontal_tail:fineness' FORM_FACTOR = 'aircraft:horizontal_tail:form_factor' @@ -373,16 +384,14 @@ class HorizontalTail: TAPER_RATIO = 'aircraft:horizontal_tail:taper_ratio' THICKNESS_TO_CHORD = 'aircraft:horizontal_tail:thickness_to_chord' - VERTICAL_TAIL_FRACTION = \ - 'aircraft:horizontal_tail:vertical_tail_fraction' + VERTICAL_TAIL_FRACTION = 'aircraft:horizontal_tail:vertical_tail_fraction' VOLUME_COEFFICIENT = 'aircraft:horizontal_tail:volume_coefficient' WETTED_AREA = 'aircraft:horizontal_tail:wetted_area' WETTED_AREA_SCALER = 'aircraft:horizontal_tail:wetted_area_scaler' class Hydraulics: - FLIGHT_CONTROL_MASS_COEFFICIENT = \ - 'aircraft:hydraulics:flight_control_mass_coefficient' + FLIGHT_CONTROL_MASS_COEFFICIENT = 'aircraft:hydraulics:flight_control_mass_coefficient' GEAR_MASS_COEFFICIENT = 'aircraft:hydraulics:gear_mass_coefficient' MASS = 'aircraft:hydraulics:mass' MASS_SCALER = 'aircraft:hydraulics:mass_scaler' @@ -394,21 +403,18 @@ class Instruments: MASS_SCALER = 'aircraft:instruments:mass_scaler' class LandingGear: - CARRIER_BASED = 'aircraft:landing_gear:carrier_based' DRAG_COEFFICIENT = 'aircraft:landing_gear:drag_coefficient' FIXED_GEAR = 'aircraft:landing_gear:fixed_gear' MAIN_GEAR_LOCATION = 'aircraft:landing_gear:main_gear_location' MAIN_GEAR_MASS = 'aircraft:landing_gear:main_gear_mass' MAIN_GEAR_MASS_COEFFICIENT = 'aircraft:landing_gear:main_gear_mass_coefficient' - MAIN_GEAR_MASS_SCALER = \ - 'aircraft:landing_gear:main_gear_mass_scaler' + MAIN_GEAR_MASS_SCALER = 'aircraft:landing_gear:main_gear_mass_scaler' MAIN_GEAR_OLEO_LENGTH = 'aircraft:landing_gear:main_gear_oleo_length' MASS_COEFFICIENT = 'aircraft:landing_gear:mass_coefficient' NOSE_GEAR_MASS = 'aircraft:landing_gear:nose_gear_mass' - NOSE_GEAR_MASS_SCALER = \ - 'aircraft:landing_gear:nose_gear_mass_scaler' + NOSE_GEAR_MASS_SCALER = 'aircraft:landing_gear:nose_gear_mass_scaler' NOSE_GEAR_OLEO_LENGTH = 'aircraft:landing_gear:nose_gear_oleo_length' TAIL_HOOK_MASS_SCALER = 'aircraft:landing_gear:tail_hook_mass_scaler' @@ -428,6 +434,7 @@ class Nacelle: MASS = 'aircraft:nacelle:mass' MASS_SCALER = 'aircraft:nacelle:mass_scaler' MASS_SPECIFIC = 'aircraft:nacelle:mass_specific' + PERCENT_DIAM_BURIED_IN_FUSELAGE = 'aircraft:nacelle:percent_diam_buried_in_fuselage' SURFACE_AREA = 'aircraft:nacelle:surface_area' TOTAL_WETTED_AREA = 'aircraft:nacelle:total_wetted_area' WETTED_AREA = 'aircraft:nacelle:wetted_area' @@ -438,8 +445,7 @@ class Paint: MASS_PER_UNIT_AREA = 'aircraft:paint:mass_per_unit_area' class Propulsion: - ENGINE_OIL_MASS_SCALER = \ - 'aircraft:propulsion:engine_oil_mass_scaler' + ENGINE_OIL_MASS_SCALER = 'aircraft:propulsion:engine_oil_mass_scaler' MASS = 'aircraft:propulsion:mass' MISC_MASS_SCALER = 'aircraft:propulsion:misc_mass_scaler' @@ -455,15 +461,13 @@ class Propulsion: TOTAL_SCALED_SLS_THRUST = 'aircraft:propulsion:total_scaled_sls_thrust' TOTAL_STARTER_MASS = 'aircraft:propulsion:total_starter_mass' - TOTAL_THRUST_REVERSERS_MASS = \ - 'aircraft:propulsion:total_thrust_reversers_mass' + TOTAL_THRUST_REVERSERS_MASS = 'aircraft:propulsion:total_thrust_reversers_mass' class Strut: AREA = 'aircraft:strut:area' AREA_RATIO = 'aircraft:strut:area_ratio' ATTACHMENT_LOCATION = 'aircraft:strut:attachment_location' - ATTACHMENT_LOCATION_DIMENSIONLESS = \ - 'aircraft:strut:attachment_location_dimensionless' + ATTACHMENT_LOCATION_DIMENSIONLESS = 'aircraft:strut:attachment_location_dimensionless' CHORD = 'aircraft:strut:chord' DIMENSIONAL_LOCATION_SPECIFIED = 'aircraft:strut:dimensional_location_specified' FUSELAGE_INTERFERENCE_FACTOR = 'aircraft:strut:fuselage_interference_factor' @@ -500,19 +504,18 @@ class VerticalTail: WETTED_AREA_SCALER = 'aircraft:vertical_tail:wetted_area_scaler' class Wing: - AEROELASTIC_TAILORING_FACTOR = \ - 'aircraft:wing:aeroelastic_tailoring_factor' + AEROELASTIC_TAILORING_FACTOR = 'aircraft:wing:aeroelastic_tailoring_factor' AIRFOIL_TECHNOLOGY = 'aircraft:wing:airfoil_technology' AREA = 'aircraft:wing:area' ASPECT_RATIO = 'aircraft:wing:aspect_ratio' ASPECT_RATIO_REF = 'aircraft:wing:aspect_ratio_reference' AVERAGE_CHORD = 'aircraft:wing:average_chord' - BENDING_FACTOR = 'aircraft:wing:bending_factor' - BENDING_MASS = 'aircraft:wing:bending_mass' + BENDING_MATERIAL_FACTOR = 'aircraft:wing:bending_material_factor' + BENDING_MATERIAL_MASS = 'aircraft:wing:bending_material_mass' # Not defined in metadata! # BENDING_MASS_NO_INERTIA = 'aircraft:wing:bending_mass_no_inertia' - BENDING_MASS_SCALER = 'aircraft:wing:bending_mass_scaler' + BENDING_MATERIAL_MASS_SCALER = 'aircraft:wing:bending_material_mass_scaler' BWB_AFTBODY_MASS = 'aircraft:wing:bwb_aft_body_mass' BWB_AFTBODY_MASS_SCALER = 'aircraft:wing:bwb_aft_body_mass_scaler' CENTER_CHORD = 'aircraft:wing:center_chord' @@ -526,6 +529,7 @@ class Wing: DETAILED_WING = 'aircraft:wing:detailed_wing' DIHEDRAL = 'aircraft:wing:dihedral' ENG_POD_INERTIA_FACTOR = 'aircraft:wing:eng_pod_inertia_factor' + EXPOSED_AREA = 'aircraft:wing:exposed_area' FINENESS = 'aircraft:wing:fineness' FLAP_CHORD_RATIO = 'aircraft:wing:flap_chord_ratio' FLAP_DEFLECTION_LANDING = 'aircraft:wing:flap_deflection_landing' @@ -534,8 +538,7 @@ class Wing: FLAP_LIFT_INCREMENT_OPTIMUM = 'aircraft:wing:flap_lift_increment_optimum' FLAP_SPAN_RATIO = 'aircraft:wing:flap_span_ratio' FLAP_TYPE = 'aircraft:wing:flap_type' - FOLD_DIMENSIONAL_LOCATION_SPECIFIED = \ - 'aircraft:wing:fold_dimensional_location_specified' + FOLD_DIMENSIONAL_LOCATION_SPECIFIED = 'aircraft:wing:fold_dimensional_location_specified' FOLD_MASS = 'aircraft:wing:fold_mass' FOLD_MASS_COEFFICIENT = 'aircraft:wing:fold_mass_coefficient' FOLDED_SPAN = 'aircraft:wing:folded_span' @@ -557,7 +560,6 @@ class Wing: LOAD_DISTRIBUTION_CONTROL = 'aircraft:wing:load_distribution_control' LOAD_FRACTION = 'aircraft:wing:load_fraction' LOAD_PATH_SWEEP_DIST = 'aircraft:wing:load_path_sweep_dist' - LOADING = 'aircraft:wing:loading' LOADING_ABOVE_20 = 'aircraft:wing:loading_above_20' MASS = 'aircraft:wing:mass' MASS_COEFFICIENT = 'aircraft:wing:mass_coefficient' @@ -571,7 +573,6 @@ class Wing: MIN_PRESSURE_LOCATION = 'aircraft:wing:min_pressure_location' MISC_MASS = 'aircraft:wing:misc_mass' MISC_MASS_SCALER = 'aircraft:wing:misc_mass_scaler' - MOUNTING_TYPE = 'aircraft:wing:mounting_type' NUM_FLAP_SEGMENTS = 'aircraft:wing:num_flap_segments' NUM_INTEGRATION_STATIONS = 'aircraft:wing:num_integration_stations' OPTIMUM_FLAP_DEFLECTION = 'aircraft:wing:optimum_flap_deflection' @@ -579,8 +580,7 @@ class Wing: ROOT_CHORD = 'aircraft:wing:root_chord' SHEAR_CONTROL_MASS = 'aircraft:wing:shear_control_mass' - SHEAR_CONTROL_MASS_SCALER = \ - 'aircraft:wing:shear_control_mass_scaler' + SHEAR_CONTROL_MASS_SCALER = 'aircraft:wing:shear_control_mass_scaler' SLAT_CHORD_RATIO = 'aircraft:wing:slat_chord_ratio' SLAT_LIFT_INCREMENT_OPTIMUM = 'aircraft:wing:slat_lift_increment_optimum' @@ -589,11 +589,10 @@ class Wing: SPAN_EFFICIENCY_FACTOR = 'aircraft:wing:span_efficiency_factor' SPAN_EFFICIENCY_REDUCTION = 'aircraft:wing:span_efficiency_reduction' STRUT_BRACING_FACTOR = 'aircraft:wing:strut_bracing_factor' - SURFACE_CONTROL_MASS = 'aircraft:wing:surface_ctrl_mass' - SURFACE_CONTROL_MASS_COEFFICIENT = 'aircraft:wing:surface_ctrl_mass_coefficient' + SURFACE_CONTROL_MASS = 'aircraft:wing:surface_control_mass' + SURFACE_CONTROL_MASS_COEFFICIENT = 'aircraft:wing:surface_control_mass_coefficient' - SURFACE_CONTROL_MASS_SCALER = \ - 'aircraft:wing:surface_ctrl_mass_scaler' + SURFACE_CONTROL_MASS_SCALER = 'aircraft:wing:surface_control_mass_scaler' SWEEP = 'aircraft:wing:sweep' TAPER_RATIO = 'aircraft:wing:taper_ratio' @@ -605,89 +604,105 @@ class Wing: THICKNESS_TO_CHORD_UNWEIGHTED = 'aircraft:wing:thickness_to_chord_unweighted' ULTIMATE_LOAD_FACTOR = 'aircraft:wing:ultimate_load_factor' VAR_SWEEP_MASS_PENALTY = 'aircraft:wing:var_sweep_mass_penalty' + VERTICAL_MOUNT_LOCATION = 'aircraft:wing:vertical_mount_location' WETTED_AREA = 'aircraft:wing:wetted_area' WETTED_AREA_SCALER = 'aircraft:wing:wetted_area_scaler' ZERO_LIFT_ANGLE = 'aircraft:wing:zero_lift_angle' class Dynamic: - """Dynamic mission data hierarchy""" + """All time-dependent variables used during mission analysis.""" + + class Atmosphere: + """Atmospheric and freestream conditions.""" + + DENSITY = 'density' + DYNAMIC_PRESSURE = 'dynamic_pressure' + KINEMATIC_VISCOSITY = 'kinematic_viscosity' + MACH = 'mach' + MACH_RATE = 'mach_rate' + SPEED_OF_SOUND = 'speed_of_sound' + STATIC_PRESSURE = 'static_pressure' + TEMPERATURE = 'temperature' class Mission: - # all time-dependent variables used during mission analysis + """ + Kinematic description of vehicle states in a ground-fixed axis. + These values are typically used by the Equations of Motion to determine + vehicle states at other timesteps. + """ + + # TODO Vehicle summary forces, torques, etc. in X,Y,Z axes should also go here ALTITUDE = 'altitude' ALTITUDE_RATE = 'altitude_rate' ALTITUDE_RATE_MAX = 'altitude_rate_max' - BATTERY_STATE_OF_CHARGE = 'battery_state_of_charge' - CUMULATIVE_ELECTRIC_ENERGY_USED = 'cumulative_electric_energy_used' - DENSITY = 'density' + # TODO Angle of Attack DISTANCE = 'distance' DISTANCE_RATE = 'distance_rate' - DRAG = 'drag' - DYNAMIC_PRESSURE = 'dynamic_pressure' - ELECTRIC_POWER_IN = 'electric_power_in' - ELECTRIC_POWER_IN_TOTAL = 'electric_power_in_total' - # EXIT_AREA = 'exit_area' FLIGHT_PATH_ANGLE = 'flight_path_angle' FLIGHT_PATH_ANGLE_RATE = 'flight_path_angle_rate' - FUEL_FLOW_RATE = 'fuel_flow_rate' - FUEL_FLOW_RATE_NEGATIVE = 'fuel_flow_rate_negative' - FUEL_FLOW_RATE_NEGATIVE_TOTAL = 'fuel_flow_rate_negative_total' - FUEL_FLOW_RATE_TOTAL = 'fuel_flow_rate_total' - HYBRID_THROTTLE = 'hybrid_throttle' - KINEMATIC_VISCOSITY = 'kinematic_viscosity' - LIFT = 'lift' - MACH = 'mach' - MACH_RATE = 'mach_rate' - MASS = 'mass' - MASS_RATE = 'mass_rate' - NOX_RATE = 'nox_rate' - NOX_RATE_TOTAL = 'nox_rate_total' - PROPELLER_TIP_SPEED = 'propeller_tip_speed' - RPM = 'rotations_per_minute' - SHAFT_POWER = 'shaft_power' - SHAFT_POWER_MAX = 'shaft_power_max' SPECIFIC_ENERGY = 'specific_energy' SPECIFIC_ENERGY_RATE = 'specific_energy_rate' SPECIFIC_ENERGY_RATE_EXCESS = 'specific_energy_rate_excess' - SPEED_OF_SOUND = 'speed_of_sound' - STATIC_PRESSURE = 'static_pressure' - TEMPERATURE = 'temperature' - TEMPERATURE_T4 = 't4' - THROTTLE = 'throttle' - THRUST = 'thrust_net' - THRUST_MAX = 'thrust_net_max' - THRUST_MAX_TOTAL = 'thrust_net_max_total' - THRUST_TOTAL = 'thrust_net_total' - TORQUE = 'torque' - TORQUE_MAX = 'torque_max' VELOCITY = 'velocity' VELOCITY_RATE = 'velocity_rate' + class Vehicle: + """Vehicle properties and states in a vehicle-fixed reference frame.""" + + ANGLE_OF_ATTACK = 'angle_of_attack' + BATTERY_STATE_OF_CHARGE = 'battery_state_of_charge' + CUMULATIVE_ELECTRIC_ENERGY_USED = 'cumulative_electric_energy_used' + DRAG = 'drag' + LIFT = 'lift' + MASS = 'mass' + MASS_RATE = 'mass_rate' + + class Propulsion: + # variables specific to the propulsion subsystem + ELECTRIC_POWER_IN = 'electric_power_in' + ELECTRIC_POWER_IN_TOTAL = 'electric_power_in_total' + # EXIT_AREA = 'exit_area' + FUEL_FLOW_RATE = 'fuel_flow_rate' + FUEL_FLOW_RATE_NEGATIVE = 'fuel_flow_rate_negative' + FUEL_FLOW_RATE_NEGATIVE_TOTAL = 'fuel_flow_rate_negative_total' + FUEL_FLOW_RATE_TOTAL = 'fuel_flow_rate_total' + HYBRID_THROTTLE = 'hybrid_throttle' + NOX_RATE = 'nox_rate' + NOX_RATE_TOTAL = 'nox_rate_total' + PROPELLER_TIP_SPEED = 'propeller_tip_speed' + RPM = 'rotations_per_minute' + SHAFT_POWER = 'shaft_power' + SHAFT_POWER_MAX = 'shaft_power_max' + TEMPERATURE_T4 = 't4' + THROTTLE = 'throttle' + THRUST = 'thrust_net' + THRUST_MAX = 'thrust_net_max' + THRUST_MAX_TOTAL = 'thrust_net_max_total' + THRUST_TOTAL = 'thrust_net_total' + TORQUE = 'torque' + TORQUE_MAX = 'torque_max' + class Mission: - """mission data hierarchy""" + """Mission data hierarchy.""" class Constraints: # these can be residuals (for equality constraints), # upper bounds, or lower bounds - GEARBOX_SHAFT_POWER_RESIDUAL = ( - 'mission:constraints:gearbox_shaft_power_residual' - ) + EXCESS_FUEL_CAPACITY = 'mission:constraints:excess_fuel_capacity' + GEARBOX_SHAFT_POWER_RESIDUAL = 'mission:constraints:gearbox_shaft_power_residual' MASS_RESIDUAL = 'mission:constraints:mass_residual' MAX_MACH = 'mission:constraints:max_mach' RANGE_RESIDUAL = 'mission:constraints:range_residual' RANGE_RESIDUAL_RESERVE = 'mission:constraints:range_residual_reserve' class Design: - # These values MAY change in design mission, but in off-design - # they cannot change. In a design mission these are either user inputs - # or calculated outputs, in off-design they are strictly inputs - # and do not change. + # These values may change in a design mission, but not during off-design. In a design + # mission these are either user inputs or calculated outputs, in off-design they are + # strictly inputs and therefore do not change. CRUISE_ALTITUDE = 'mission:design:cruise_altitude' CRUISE_RANGE = 'mission:design:cruise_range' - FUEL_MASS = 'mission:design:fuel_mass' - FUEL_MASS_REQUIRED = 'mission:design:fuel_mass_required' GROSS_MASS = 'mission:design:gross_mass' LIFT_COEFFICIENT = 'mission:design:lift_coefficient' LIFT_COEFFICIENT_MAX_FLAPS_UP = 'mission:design:lift_coefficient_max_flaps_up' @@ -703,8 +718,7 @@ class Landing: BRAKING_DELAY = 'mission:landing:braking_delay' BRAKING_FRICTION_COEFFICIENT = 'mission:landing:braking_friction_coefficient' - DRAG_COEFFICIENT_FLAP_INCREMENT = \ - 'mission:landing:drag_coefficient_flap_increment' + DRAG_COEFFICIENT_FLAP_INCREMENT = 'mission:landing:drag_coefficient_flap_increment' DRAG_COEFFICIENT_MIN = 'mission:landing:drag_coefficient_min' FIELD_LENGTH = 'mission:landing:field_length' @@ -715,8 +729,7 @@ class Landing: INITIAL_MACH = 'mission:landing:initial_mach' INITIAL_VELOCITY = 'mission:landing:initial_velocity' - LIFT_COEFFICIENT_FLAP_INCREMENT = \ - 'mission:landing:lift_coefficient_flap_increment' + LIFT_COEFFICIENT_FLAP_INCREMENT = 'mission:landing:lift_coefficient_flap_increment' LIFT_COEFFICIENT_MAX = 'mission:landing:lift_coefficient_max' MAXIMUM_FLARE_LOAD_FACTOR = 'mission:landing:maximum_flare_load_factor' @@ -736,31 +749,35 @@ class Objectives: RANGE = 'mission:objectives:range' class Summary: - # These values are inputs and outputs to/from mission analysis - # for the given mission (whether it is design or off-design). - # In on-design these may be constrained to design values, but - # in off-design they independently represent the final analysis - # based on the user-selection. + # These values are inputs and outputs to/from mission analysis for the given mission + # (whether it is design or off-design). In design these may be constrained to design values, + # but in off-design they independently represent the final analysis based on the + # user selection. CRUISE_MACH = 'mission:summary:cruise_mach' CRUISE_MASS_FINAL = 'mission:summary:cruise_mass_final' + FINAL_MASS = 'mission:summary:final_mass' + FINAL_TIME = 'mission:summary:final_time' FUEL_BURNED = 'mission:summary:fuel_burned' FUEL_FLOW_SCALER = 'mission:summary:fuel_flow_scaler' + FUEL_MASS = 'mission:summary:fuel_mass' + FUEL_MASS_REQUIRED = 'mission:design:fuel_mass_required' GROSS_MASS = 'mission:summary:gross_mass' + OPERATING_MASS = 'mission:summary:operating_mass' RANGE = 'mission:summary:range' RESERVE_FUEL_BURNED = 'mission:summary:reserve_fuel_burned' TOTAL_FUEL_MASS = 'mission:summary:total_fuel_mass' + ZERO_FUEL_MASS = 'mission:summary:zero_fuel_mass' class Takeoff: # These are values which have to do with takeoff AIRPORT_ALTITUDE = 'mission:takeoff:airport_altitude' ANGLE_OF_ATTACK_RUNWAY = 'mission:takeoff:angle_of_attack_runway' ASCENT_DURATION = 'mission:takeoff:ascent_duration' - ASCENT_T_INTIIAL = 'mission:takeoff:ascent_t_initial' + ASCENT_T_INITIAL = 'mission:takeoff:ascent_t_initial' BRAKING_FRICTION_COEFFICIENT = 'mission:takeoff:braking_friction_coefficient' DECISION_SPEED_INCREMENT = 'mission:takeoff:decision_speed_increment' - DRAG_COEFFICIENT_FLAP_INCREMENT = \ - 'mission:takeoff:drag_coefficient_flap_increment' + DRAG_COEFFICIENT_FLAP_INCREMENT = 'mission:takeoff:drag_coefficient_flap_increment' DRAG_COEFFICIENT_MIN = 'mission:takeoff:drag_coefficient_min' FIELD_LENGTH = 'mission:takeoff:field_length' @@ -771,8 +788,7 @@ class Takeoff: FUEL_SIMPLE = 'mission:takeoff:fuel_simple' GROUND_DISTANCE = 'mission:takeoff:ground_distance' - LIFT_COEFFICIENT_FLAP_INCREMENT = \ - 'mission:takeoff:lift_coefficient_flap_increment' + LIFT_COEFFICIENT_FLAP_INCREMENT = 'mission:takeoff:lift_coefficient_flap_increment' LIFT_COEFFICIENT_MAX = 'mission:takeoff:lift_coefficient_max' LIFT_OVER_DRAG = 'mission:takeoff:lift_over_drag' @@ -790,8 +806,11 @@ class Taxi: class Settings: - """Setting data hierarchy""" + """Setting data hierarchy.""" + + AERODYNAMICS_METHOD = 'settings:aerodynamics_method' EQUATIONS_OF_MOTION = 'settings:equations_of_motion' MASS_METHOD = 'settings:mass_method' + PAYLOAD_RANGE = 'settings:payload_range' PROBLEM_TYPE = 'settings:problem_type' VERBOSITY = 'settings:verbosity' diff --git a/aviary/visualization/aircraft_3d_model.py b/aviary/visualization/aircraft_3d_model.py index 2adbf26fb1..f762cd6d25 100644 --- a/aviary/visualization/aircraft_3d_model.py +++ b/aviary/visualization/aircraft_3d_model.py @@ -1,11 +1,12 @@ -from enum import IntEnum import math -from string import Template from dataclasses import dataclass +from enum import IntEnum +from string import Template from typing import Iterator, List, Tuple import openmdao.api as om from openmdao.utils.om_warnings import issue_warning + import aviary.api as av @@ -66,11 +67,11 @@ class Point3D: y: float = 0.0 z: float = 0.0 - def translated_copy(self, dx: float, dy: float, dz: float) -> "Point3D": + def translated_copy(self, dx: float, dy: float, dz: float) -> 'Point3D': """Return a new Point3D that is a translation of this point by (dx, dy, dz).""" return Point3D(self.x + dx, self.y + dy, self.z + dz) - def reflected_copy(self, axis: Axis) -> "Point3D": + def reflected_copy(self, axis: Axis) -> 'Point3D': """Return a new Point3D that is a reflection of this point across one of the 3d axes.""" x = self.x * (-1 if axis == Axis.X else 1) y = self.y * (-1 if axis == Axis.Y else 1) @@ -79,7 +80,7 @@ def reflected_copy(self, axis: Axis) -> "Point3D": def __str__(self) -> str: """Return a string representation of the point in the format 'x y z'.""" - return f"{self.x} {self.y} {self.z}" + return f'{self.x} {self.y} {self.z}' @dataclass @@ -97,16 +98,14 @@ class Quad3D: def __post_init__(self): if len(self.vertices) != 4: - raise ValueError("A quadrilateral must have exactly four vertices.") + raise ValueError('A quadrilateral must have exactly four vertices.') - def translated_copy(self, dx: float, dy: float, dz: float) -> "Quad3D": + def translated_copy(self, dx: float, dy: float, dz: float) -> 'Quad3D': """Return a new Quad3D that is a translation of this quad by (dx, dy, dz).""" - translated_vertices = [ - vertex.translated_copy(dx, dy, dz) for vertex in self.vertices - ] + translated_vertices = [vertex.translated_copy(dx, dy, dz) for vertex in self.vertices] return Quad3D(translated_vertices) - def reflected_copy(self, axis: Axis) -> "Quad3D": + def reflected_copy(self, axis: Axis) -> 'Quad3D': """Return a new Quad3D that is a reflection of this quad across one of the 3 axes.""" reflected_vertices = [vertex.reflected_copy(axis) for vertex in self.vertices] return Quad3D(reflected_vertices) @@ -223,7 +222,7 @@ class AircraftModelReader(object): _cr : CaseReader CaseReader object. _problem_metadata : dict - Metadata about the problem, including the system hierachy and connections. + Metadata about the problem, including the system hierarchy and connections. _final_case : str Final Problem case from the case recorder file. """ @@ -249,34 +248,33 @@ def read_case_recorder_file(self): model_options = cr.list_model_options(out_stream=None) try: - self.aviary_options = model_options["root"]["aviary_options"] - except KeyError as e: + self.aviary_options = model_options['root']['aviary_options'] + except KeyError: issue_warning( - f"The case recorder file {self._case_recorder_file} does not have any metadata for the root system") + f'The case recorder file {self._case_recorder_file} does not have any metadata for the root system' + ) self.aviary_options = av.AviaryValues() # - if "final" not in cr.list_cases(): + if 'final' not in cr.list_cases(): raise AircraftModelReaderError( f"Case recorder file, {self._case_recorder_file} does not have expected case named 'final'" ) - self._final_case = cr.get_case("final") + self._final_case = cr.get_case('final') def _write_input_output_variables(self): - """ - Write out the input and output variables in the final case. For debugging. - """ - inputs = self._final_case.list_inputs( + """Write out the input and output variables in the final case. For debugging.""" + self._final_case.list_inputs( val=True, - return_format="list", + return_format='list', prom_name=True, hierarchical=False, ) - outputs = self._final_case.list_outputs( + self._final_case.list_outputs( val=True, - return_format="list", + return_format='list', prom_name=True, hierarchical=False, ) @@ -300,18 +298,17 @@ def get_variable_from_case(self, var_prom_name, units=None): try: val = self._final_case.get_val(var_prom_name, units=units) return float(val) - except KeyError as e: + except KeyError: pass - abs2prom = self._problem_metadata["abs2prom"] - for abs_name, prom_name in abs2prom["input"].items(): + abs2prom = self._problem_metadata['abs2prom'] + for abs_name, prom_name in abs2prom['input'].items(): # the phrase "_OVERRIDE" in a variable indicates it is a calculated value that we are discarding if prom_name == var_prom_name and '_OVERRIDE' not in abs_name: val = self._final_case.get_val(abs_name, units=units) return float(val) - raise AircraftModelReaderError( - f"Promoted name {var_prom_name} not found in final case") + raise AircraftModelReaderError(f'Promoted name {var_prom_name} not found in final case') def get_variable_from_aviary_options(self, var_prom_name): """ @@ -330,7 +327,8 @@ def get_variable_from_aviary_options(self, var_prom_name): item = self.aviary_options.get_item(var_prom_name) if item is None: raise AircraftModelReaderError( - f"Promoted name {var_prom_name} not found in aviary_options") + f'Promoted name {var_prom_name} not found in aviary_options' + ) value, _units = item return value @@ -362,16 +360,14 @@ def __init__(self, reader): def read_variables(self): try: self._length = self._reader.get_variable_from_case( - "aircraft:fuselage:length", units="ft" + 'aircraft:fuselage:length', units='ft' ) self._radius = ( - self._reader.get_variable_from_case( - "aircraft:fuselage:avg_diameter", units="ft" - ) + self._reader.get_variable_from_case('aircraft:fuselage:avg_diameter', units='ft') / 2.0 ) except AircraftModelReaderError as e: - print(f"Warning: Unable to read fuselage variables due to the error: {e} ") + print(f'Warning: Unable to read fuselage variables due to the error: {e} ') raise def get_aframe_markup(self): @@ -380,7 +376,7 @@ def get_aframe_markup(self): - + """ @property @@ -428,21 +424,17 @@ def __init__(self, reader, fuselage): self._fuselage = fuselage def read_variables(self): - """ - Read the variables from the final case that are needed to define the vertical tail. - """ + """Read the variables from the final case that are needed to define the vertical tail.""" try: thickness_to_chord = self._reader.get_variable_from_case( - "aircraft:vertical_tail:thickness_to_chord" - ) - area = self._reader.get_variable_from_case( - "aircraft:vertical_tail:area", units="ft**2" + 'aircraft:vertical_tail:thickness_to_chord' ) + area = self._reader.get_variable_from_case('aircraft:vertical_tail:area', units='ft**2') aspect_ratio = self._reader.get_variable_from_case( - "aircraft:vertical_tail:aspect_ratio" + 'aircraft:vertical_tail:aspect_ratio' ) self._taper_ratio = self._reader.get_variable_from_case( - "aircraft:vertical_tail:taper_ratio" + 'aircraft:vertical_tail:taper_ratio' ) # Calculate the span (b) using the formula b = sqrt(AR * S) self._span = (aspect_ratio * area) ** 0.5 @@ -450,9 +442,7 @@ def read_variables(self): self._chord = area / self._span self._thickness = thickness_to_chord * self._chord except AircraftModelReaderError as e: - print( - f"Warning: Unable to read vertical tail variables due to the error: {e} " - ) + print(f'Warning: Unable to read vertical tail variables due to the error: {e} ') raise def get_aframe_markup(self): @@ -496,7 +486,7 @@ def get_aframe_markup(self): right_quad = left_quad.translated_copy(0, 0, -self._thickness) quads_to_complete_solid = complete_solid(left_quad, right_quad) - entities = "" + entities = '' entities += f""" {quad3d_to_triangle_entities(left_quad)} @@ -504,7 +494,7 @@ def get_aframe_markup(self): """ for quad in quads_to_complete_solid: - entities += f"{quad3d_to_triangle_entities(quad)}" + entities += f'{quad3d_to_triangle_entities(quad)}' return entities @@ -539,7 +529,7 @@ class HorizontalWing(object): Chord at the top of the wing. _position_along_fuselage : float Position of the wing along the fuselage. - _mounting_type : float + _mount_location : float wing location on fuselage (0 = low wing, 1 = high wing, can be fractions). _fuselage : Fuselage The Fuselage object used to represent the fuselage of the aircraft. @@ -556,65 +546,56 @@ def __init__(self, reader, fuselage, wing_type): self._sweep_angle = None self._chord_tip = None self._position_along_fuselage = None - self._mounting_type = None + self._mount_location = None self._fuselage = fuselage self._wing_type = wing_type def read_variables(self): - """ - Read the variables from the final case that are needed to define the horizontal wing. - """ + """Read the variables from the final case that are needed to define the horizontal wing.""" if self._wing_type == WingType.WING: - wing_type_name = "wing" + wing_type_name = 'wing' elif self._wing_type == WingType.HORIZONTAL_TAIL: - wing_type_name = "horizontal_tail" + wing_type_name = 'horizontal_tail' try: aspect_ratio = self._reader.get_variable_from_case( - f"aircraft:{wing_type_name}:aspect_ratio" + f'aircraft:{wing_type_name}:aspect_ratio' ) taper_ratio = self._reader.get_variable_from_case( - f"aircraft:{wing_type_name}:taper_ratio" + f'aircraft:{wing_type_name}:taper_ratio' ) area = self._reader.get_variable_from_case( - f"aircraft:{wing_type_name}:area", units="ft**2" + f'aircraft:{wing_type_name}:area', units='ft**2' ) try: thickness_to_chord = self._reader.get_variable_from_case( - f"aircraft:{wing_type_name}:thickness_to_chord" + f'aircraft:{wing_type_name}:thickness_to_chord' ) except AircraftModelReaderError: # try this method if the first doesn't work thickness_to_chord_root = self._reader.get_variable_from_case( - f"aircraft:{wing_type_name}:thickness_to_chord_root" + f'aircraft:{wing_type_name}:thickness_to_chord_root' ) thickness_to_chord_tip = self._reader.get_variable_from_case( - f"aircraft:{wing_type_name}:thickness_to_chord_tip" + f'aircraft:{wing_type_name}:thickness_to_chord_tip' ) - thickness_to_chord = ( - thickness_to_chord_root + thickness_to_chord_tip - ) / 2.0 + thickness_to_chord = (thickness_to_chord_root + thickness_to_chord_tip) / 2.0 self._span = (aspect_ratio * area) ** 0.5 self._chord = area / self._span self._thickness = thickness_to_chord * self._chord - self._sweep_angle = self._reader.get_variable_from_case( - av.Aircraft.Wing.SWEEP) + self._sweep_angle = self._reader.get_variable_from_case(av.Aircraft.Wing.SWEEP) self._chord_tip = self._chord * taper_ratio if self._wing_type == WingType.WING: try: - mounting_type = self._reader.get_variable_from_case( - "aircraft:wing:mounting_type" + mount_location = self._reader.get_variable_from_case( + 'aircraft:wing:mount_location' ) except AircraftModelReaderError: - mounting_type = 0.0 - self._vertical_position = ( - 2.0 * (mounting_type - 0.5) * self._fuselage.radius - ) + mount_location = 0.0 + self._vertical_position = 2.0 * (mount_location - 0.5) * self._fuselage.radius self._position_along_fuselage = 0.0 elif self._wing_type == WingType.HORIZONTAL_TAIL: self._vertical_position = 0.0 - self._position_along_fuselage = ( - -self._fuselage.length / 2.0 + self._chord / 2.0 - ) + self._position_along_fuselage = -self._fuselage.length / 2.0 + self._chord / 2.0 except AircraftModelReaderError as e: print( f"Warning: Unable to read horizontal wing of type '{self._wing_type}' variables due to the error: {e} " @@ -632,7 +613,7 @@ def get_aframe_markup(self): """ sweep_angle_tan = math.tan(math.radians(self._sweep_angle)) - entities = "" + entities = '' # the quad that defines the left side of the horizontal wing left_top_quad = Quad3D( @@ -676,14 +657,12 @@ def get_aframe_markup(self): {quad3d_to_triangle_entities(left_bottom_quad)} """ for quad in left_quads_to_complete_solid: - entities += f"{quad3d_to_triangle_entities(quad)}" + entities += f'{quad3d_to_triangle_entities(quad)}' # Now the right wing right_top_quad = left_top_quad.reflected_copy(Axis.Z) right_bottom_quad = right_top_quad.translated_copy(-self._thickness, 0, 0) - right_quads_to_complete_solid = complete_solid( - right_top_quad, right_bottom_quad - ) + right_quads_to_complete_solid = complete_solid(right_top_quad, right_bottom_quad) entities += f""" {quad3d_to_triangle_entities(right_top_quad)} @@ -691,7 +670,7 @@ def get_aframe_markup(self): """ for quad in right_quads_to_complete_solid: - entities += f"{quad3d_to_triangle_entities(quad)}" + entities += f'{quad3d_to_triangle_entities(quad)}' return entities @@ -760,32 +739,28 @@ def __init__(self, reader, fuselage, wing): self._has_propellers = None def read_variables(self): - """ - Read the variables from the final case that are needed to define the engines. - """ + """Read the variables from the final case that are needed to define the engines.""" try: self._num_wing_engines = self._reader.get_variable_from_aviary_options( av.Aircraft.Engine.NUM_WING_ENGINES ) self._engine_diameter = self._reader.get_variable_from_case( - av.Aircraft.Nacelle.AVG_DIAMETER, units="ft" + av.Aircraft.Nacelle.AVG_DIAMETER, units='ft' ) self._engine_length = self._reader.get_variable_from_case( - av.Aircraft.Nacelle.AVG_LENGTH, units="ft" + av.Aircraft.Nacelle.AVG_LENGTH, units='ft' ) - self._engine_locations_on_wing = ( - self._reader.get_variable_from_aviary_options( - av.Aircraft.Engine.WING_LOCATIONS - ) + self._engine_locations_on_wing = self._reader.get_variable_from_aviary_options( + av.Aircraft.Engine.WING_LOCATIONS ) try: self._has_propellers = self._reader.get_variable_from_case( av.Aircraft.Engine.HAS_PROPELLERS ) - except AircraftModelReaderError as e2: + except AircraftModelReaderError: self._has_propellers = False except AircraftModelReaderError as e: - print(f"Warning: Unable to read engine variables due to the error: {e} ") + print(f'Warning: Unable to read engine variables due to the error: {e} ') raise def get_aframe_markup(self): @@ -798,37 +773,40 @@ def get_aframe_markup(self): A-Frame markup defining the engines. """ wing_span = self._wing.span - entities = "" + entities = '' if self._engine_locations_on_wing: for engine_location in self._engine_locations_on_wing: - distance_from_fuselage = engine_location * wing_span/2.0 - distance_along_fuselage = self._wing.position_along_fuselage + self._wing.chord / 2. - \ - distance_from_fuselage * \ - math.tan(math.radians(self._wing.sweep_angle)) + \ - self._engine_length/2. - distance_above_fuselage = self._wing.vertical_position - self._engine_diameter / 2. + distance_from_fuselage = engine_location * wing_span / 2.0 + distance_along_fuselage = ( + self._wing.position_along_fuselage + + self._wing.chord / 2.0 + - distance_from_fuselage * math.tan(math.radians(self._wing.sweep_angle)) + + self._engine_length / 2.0 + ) + distance_above_fuselage = self._wing.vertical_position - self._engine_diameter / 2.0 entities += f""" - - """ if self._has_propellers: - propeller_blade_radius = self._engine_diameter / \ - 10.0 # arbitrary fraction of engine diameter + propeller_blade_radius = ( + self._engine_diameter / 10.0 + ) # arbitrary fraction of engine diameter propeller_blade_length = self._engine_diameter * 2.0 entities += f""" - - - - """ @@ -863,8 +841,8 @@ def __init__(self, case_recorder_file): # in the final case # self.model_reader._write_input_output_variables() - self._entities = "" - self._camera_entity = "" + self._entities = '' + self._camera_entity = '' def read_variables(self): self.fuselage = Fuselage(self._reader) @@ -873,9 +851,7 @@ def read_variables(self): self.wing.read_variables() self.engines = Engines(self._reader, self.fuselage, self.wing) self.engines.read_variables() - self.horizontal_tail = HorizontalWing( - self._reader, self.fuselage, WingType.HORIZONTAL_TAIL - ) + self.horizontal_tail = HorizontalWing(self._reader, self.fuselage, WingType.HORIZONTAL_TAIL) self.horizontal_tail.read_variables() self.vertical_tail = VerticalTail(self._reader, self.fuselage) self.vertical_tail.read_variables() @@ -896,13 +872,11 @@ def get_camera_entity(self, fuselage_length): """ def write_file(self, aircraft_3d_template_filepath, outfilepath): - with open(aircraft_3d_template_filepath, "r", encoding="utf-8") as f: + with open(aircraft_3d_template_filepath, 'r', encoding='utf-8') as f: aircraft_3d_template = f.read() - with open(outfilepath, "w") as f: + with open(outfilepath, 'w') as f: template = Template(aircraft_3d_template) - s = template.substitute( - entities=self._entities, camera_entity=self._camera_entity - ) + s = template.substitute(entities=self._entities, camera_entity=self._camera_entity) f.write(s) diff --git a/aviary/visualization/assets/aviary_styles.css b/aviary/visualization/assets/aviary_styles.css index 0c062ac691..dae022a3f5 100644 --- a/aviary/visualization/assets/aviary_styles.css +++ b/aviary/visualization/assets/aviary_styles.css @@ -26,3 +26,10 @@ nav#header { border: 2px solid black; font-size: 10pt; } + +p.pane_doc { + background: #dddddd; + border: 2px solid black; + padding: 10px; + font-size: 18pt; +} \ No newline at end of file diff --git a/aviary/visualization/dashboard.py b/aviary/visualization/dashboard.py index cab3b97041..8871938933 100644 --- a/aviary/visualization/dashboard.py +++ b/aviary/visualization/dashboard.py @@ -1,38 +1,45 @@ import argparse -from collections import defaultdict -from dataclasses import dataclass +import functools import importlib.util import json import os -import pathlib import re import shutil -import warnings +import traceback import zipfile +from collections import defaultdict +from pathlib import Path import numpy as np - +import openmdao.api as om import pandas as pd - -from bokeh.models import Legend, LegendItem, CheckboxGroup, CustomJS, TextInput, ColumnDataSource, CustomJS, Div, Range1d, LinearAxis, PrintfTickFormatter -from bokeh.plotting import figure -from bokeh.layouts import column -from bokeh.palettes import Category10, Category20, d3 - import panel as pn - -import openmdao.api as om -from openmdao.utils.general_utils import env_truthy +from bokeh.models import ( + ColumnDataSource, + CustomJS, + Div, + Legend, + LegendItem, + LinearAxis, + PrintfTickFormatter, + Range1d, + TextInput, +) +from bokeh.palettes import Category20, d3 +from bokeh.plotting import figure +from openmdao.utils.general_utils import env_truthy, make_serializable from openmdao.utils.units import conversion_to_base_units + try: from openmdao.utils.gui_testing_utils import get_free_port -except: +except BaseException: # If get_free_port is unavailable, the default port will be used def get_free_port(): return 5000 -from openmdao.utils.om_warnings import issue_warning + from dymos.visualization.timeseries.bokeh_timeseries_report import _meta_tree_subsys_iter +from openmdao.utils.om_warnings import issue_warning from aviary.visualization.aircraft_3d_model import Aircraft3DModel @@ -48,12 +55,12 @@ def get_free_port(): import aviary.api as av # Enable Panel extensions -pn.extension(sizing_mode="stretch_width") +pn.extension(sizing_mode='stretch_width') # Initialize any custom extensions pn.extension('tabulator') # Constants -aviary_variables_json_file_name = "aviary_vars.json" +aviary_variables_json_file_name = 'aviary_vars.json' documentation_text_align = 'left' # functions for the aviary command line command @@ -75,7 +82,7 @@ def _none_or_str(value): option_value : str or None The value of the option after possibly converting from 'None' to None. """ - if value == "None": + if value == 'None': return None return value @@ -90,61 +97,48 @@ def _dashboard_setup_parser(parser): The parser we're adding options to. """ parser.add_argument( - "script_name", + 'script_name', type=str, - nargs="*", - help="Name of aviary script that was run (not including .py).", + nargs='*', + help='Name of aviary script that was run (not including .py).', ) - parser.add_argument( - "--problem_recorder", - type=str, - help="Problem case recorder file name", - dest="problem_recorder", - default="problem_history.db", - ) - parser.add_argument( - "--driver_recorder", - type=_none_or_str, - help="Driver case recorder file name. Set to None if file is ignored", - dest="driver_recorder", - default="driver_history.db", - ) - parser.add_argument( - "--port", - dest="port", + '--port', + dest='port', type=int, default=0, - help="dashboard server port ID (default is 0, which indicates get any free port)", + help='dashboard server port ID (default is 0, which indicates get any free port)', ) parser.add_argument( - "-b", - "--background", - action="store_true", - dest="run_in_background", + '-b', + '--background', + action='store_true', + dest='run_in_background', help="Run the server in the background (don't automatically open the browser)", ) # For future use parser.add_argument( - "-d", - "--debug", - action="store_true", - dest="debug_output", - help="show debugging output", + '-d', + '--debug', + action='store_true', + dest='debug_output', + help='show debugging output', ) - parser.add_argument("--save", - nargs='?', - const=True, - default=False, - help="Name of zip file in which dashboard files are saved. If no argument given, use the script name to name the zip file", - ) + parser.add_argument( + '--save', + nargs='?', + const=True, + default=False, + help='Name of zip file in which dashboard files are saved. If no argument given, use the script name to name the zip file', + ) - parser.add_argument("--force", - action='store_true', - help="When displaying data from a shared zip file, if the directory in the reports directory exists, overrite if this is True", - ) + parser.add_argument( + '--force', + action='store_true', + help='When displaying data from a shared zip file, if the directory in the reports directory exists, overrite if this is True', + ) def _dashboard_cmd(options, user_args): @@ -158,14 +152,13 @@ def _dashboard_cmd(options, user_args): user_args : list of str Args to be passed to the user script. """ - if options.save and not options.script_name: if options.save is not True: options.script_name = options.save options.save = True if not options.script_name: - raise argparse.ArgumentError("script_name argument missing") + raise argparse.ArgumentError('script_name argument missing') if isinstance(options.script_name, list): options.script_name = options.script_name[0] @@ -174,19 +167,23 @@ def _dashboard_cmd(options, user_args): # if yes, then unzip into reports directory and run dashboard on it if zipfile.is_zipfile(options.script_name): report_dir_name = Path(options.script_name).stem - report_dir_path = Path("reports") / report_dir_name + report_dir_path = Path(f'{report_dir_name}_out') # need to check to see if that directory already exists if not options.force and report_dir_path.is_dir(): raise RuntimeError( - f"The reports directory {report_dir_name} already exists. If you wish to overrite the existing directory, use the --force option") - if report_dir_path.is_dir(): # need to delete it. The unpacking will just add to what is there, not do a clean unpack + f'The reports directory {report_dir_path} already exists. If you wish ' + 'to overwrite the existing directory, use the --force option' + ) + if ( + report_dir_path.is_dir() + ): # need to delete it. The unpacking will just add to what is there, not do a clean unpack shutil.rmtree(report_dir_path) - shutil.unpack_archive(options.script_name, f"reports/{report_dir_name}") + shutil.unpack_archive(options.script_name, report_dir_path) dashboard( report_dir_name, - options.problem_recorder, - options.driver_recorder, + # options.problem_recorder, + # options.driver_recorder, options.port, options.run_in_background, ) @@ -198,20 +195,52 @@ def _dashboard_cmd(options, user_args): save_filename_stem = options.script_name else: save_filename_stem = Path(options.save).stem - print(f"Saving to {save_filename_stem}.zip") - shutil.make_archive(save_filename_stem, "zip", f"reports/{options.script_name}") + print(f'Saving to {save_filename_stem}.zip') + shutil.make_archive(save_filename_stem, 'zip', f'{options.script_name}_out') return dashboard( options.script_name, - options.problem_recorder, - options.driver_recorder, + # options.problem_recorder, + # options.driver_recorder, options.port, options.run_in_background, ) -def create_table_pane_from_json(json_filepath): +def _handle_pane_creation_errors(): + """ + A decorator used with the functions that creates panes for use in the dashboard. + If the function executes without throwing an exception, the pane is added + to the pane list that will be shown in the dashboard. + If the function does throw an exception, it puts the error message + and stack trace into the pane so the user can see why it failed. + """ + + def decorator(func): + @functools.wraps(func) + def wrapper(pane_title, pane_list, pane_documentation, *args, **kwargs): + try: + pane = func(pane_documentation, *args, **kwargs) + pane_list.append((pane_title, pane)) + return pane + except Exception as e: + # Get the full stack trace as a string + stack_trace = traceback.format_exc() + pane = _create_message_pane( + pane_documentation, + f'Unable to create {pane_title} due to error: {e}\n\nStack trace:\n{stack_trace}', + ) + pane_list.append((pane_title, pane)) + return None + + return wrapper + + return decorator + + +@_handle_pane_creation_errors() +def create_table_pane_from_json(documentation, json_filepath): """ Create a Tabulator Pane with Name and Value columns using tabular data from a JSON file. @@ -227,29 +256,50 @@ def create_table_pane_from_json(json_filepath): A Panel Pane that is a Panel library Tabular widget. Or None if there was an error. """ - try: with open(json_filepath) as json_file: parsed_json = json.load(json_file) # Convert the dictionary to a DataFrame df = pd.DataFrame(list(parsed_json.items()), columns=['Name', 'Value']) - table_pane = pn.widgets.Tabulator(df, show_index=False, selectable=False, - sortable=False, - disabled=True, # disables editing of the table - titles={ - 'Name': '', - 'Value': '', - }) - except Exception as err: - warnings.warn(f"Unable to generate table due to: {err}.") - table_pane = None - return table_pane + table_pane = pn.widgets.Tabulator( + df, + show_index=False, + selectable=False, + sortable=False, + disabled=True, # disables editing of the table + titles={ + 'Name': '', + 'Value': '', + }, + ) + table_pane_with_doc = pn.Column( + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': documentation_text_align}, + ), + table_pane, + ) + except Exception: + table_pane_with_doc = pn.Column( + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': documentation_text_align}, + ), + pn.pane.Markdown( + f"# Table not shown because data source JSON file, '{json_filepath}', not found." + ), + ) + + return table_pane_with_doc # functions for creating Panel Panes given different kinds of # data inputs -def create_csv_frame(csv_filepath, documentation): +@_handle_pane_creation_errors() +def create_csv_frame(documentation, csv_filepath): """ Create a Panel Pane that contains a tabular display of the data in a CSV file. @@ -272,43 +322,65 @@ def create_csv_frame(csv_filepath, documentation): df, show_index=False, sortable=False, - layout="fit_data_stretch", + layout='fit_data_stretch', max_height=600, sizing_mode='scale_both', ) report_pane = pn.Column( - pn.pane.HTML(f"

{documentation}

", - styles={'text-align': documentation_text_align}), - df_pane + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': documentation_text_align}, + ), + df_pane, ) else: report_pane = pn.Column( - pn.pane.HTML(f"

{documentation}

", - styles={'text-align': documentation_text_align}), + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': documentation_text_align}, + ), pn.pane.Markdown( - f"# Report not shown because data source CSV file, '{csv_filepath}', not found.") + f"# Report not shown because data source CSV file, '{csv_filepath}', not found." + ), ) return report_pane def get_run_status(status_filepath): - """ - Get run status - """ - + """Get run status.""" try: with open(status_filepath) as f: status_dct = json.load(f) if status_dct['Exit status'] == 'SUCCESS': return '✅ Success' else: - return f"❌ {status_dct['Exit status']}" - except Exception as err: + return f'❌ {status_dct["Exit status"]}' + except Exception: return 'Unknown' -def create_report_frame(format, text_filepath, documentation): +def _create_message_pane(documentation, message): + """ + A simple pane showing a text message. Mostly used for + showing error messages. + """ + report_pane = pn.Column( + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': 'left'}, + ), + # pn.pane.HTML(f"

{message}

", styles={'text-align': 'left'}) + pn.pane.Str(f'

{message}

', styles={'text-align': 'left'}), + ) + return report_pane + + +@_handle_pane_creation_errors() +def create_report_frame(documentation, format, text_filepath): """ Create a Panel Pane that contains an embedded external file in HTML, Markdown, or text format, or a simple message in HTML format. @@ -328,43 +400,51 @@ def create_report_frame(format, text_filepath, documentation): A Panel Pane object to be displayed in the dashboard. Or None if the file does not exist. """ - if format == "simple_message": - report_pane = pn.Column( - pn.pane.HTML(f"

{documentation}

", styles={'text-align': 'left'}), - pn.pane.HTML(f"

{text_filepath}

", styles={'text-align': 'left'}) - ) - elif os.path.isfile(text_filepath): - if format == "html": + if os.path.isfile(text_filepath): + if format == 'html': iframe_css = 'width=1200px height=800px overflow-x="scroll" overflow="scroll" margin=0px padding=0px border=20px frameBorder=20px scrolling="yes"' report_pane = pn.Column( - pn.pane.HTML(f"

{documentation}

", styles={'text-align': 'left'}), - pn.pane.HTML(f"") + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': 'left'}, + ), + pn.pane.HTML(f''), ) - elif format in ["markdown", "text"]: - with open(text_filepath, "rb") as f: + elif format in ['markdown', 'text']: + with open(text_filepath, 'rb') as f: file_text = f.read() # need to deal with some encoding errors - file_text = file_text.decode("latin-1") - if format == "markdown": + file_text = file_text.decode('latin-1') + if format == 'markdown': report_pane = pn.pane.Markdown(file_text) - elif format == "text": + elif format == 'text': report_pane = pn.pane.Str(file_text) report_pane = pn.Column( - pn.pane.HTML(f"

{documentation}

", styles={'text-align': 'left'}), - report_pane + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': 'left'}, + ), + report_pane, ) else: - raise RuntimeError(f"Report format of {format} is not supported.") + raise RuntimeError(f'Report format of {format} is not supported.') else: report_pane = pn.Column( - pn.pane.HTML(f"

{documentation}

", styles={'text-align': 'left'}), + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': 'left'}, + ), pn.pane.Markdown( - f"# Report not shown because report file, '{text_filepath}', not found.") + f"# Report not shown because report file, '{text_filepath}', not found." + ), ) return report_pane -def create_aviary_variables_table_data_nested(script_name, recorder_file): +def create_aviary_variables_table_data_nested(output_dir, recorder_file): """ Create a JSON file with information about Aviary variables. @@ -378,6 +458,8 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): Parameters ---------- + output_dir : Path, str + Output directory for case recorder_file : str Name of the recorder file containing the Problem cases. @@ -389,10 +471,10 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): """ cr = om.CaseReader(recorder_file) - if "final" not in cr.list_cases(): + if 'final' not in cr.list_cases(): return None - case = cr.get_case("final") + case = cr.get_case('final') outputs = case.list_outputs( explicit=True, implicit=True, @@ -407,13 +489,13 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): hierarchical=False, print_arrays=False, out_stream=None, - return_format="dict", + return_format='dict', ) sorted_abs_names = sorted(outputs.keys()) grouped = {} for s in sorted_abs_names: - prefix = s.split(":")[0] + prefix = s.split(':')[0] if prefix not in grouped: grouped[prefix] = [] grouped[prefix].append(s) @@ -424,50 +506,52 @@ def create_aviary_variables_table_data_nested(script_name, recorder_file): for group_name in sorted_group_names: if len(grouped[group_name]) == 1: # a list of one var. var_info = grouped[group_name][0] - prom_name = outputs[var_info]["prom_name"] + prom_name = outputs[var_info]['prom_name'] aviary_metadata = av.CoreMetaData.get(prom_name) + # the metadata has some object types, like "type", that don't serialize normally + aviary_metadata = make_serializable(aviary_metadata) table_data_nested.append( { - "abs_name": group_name, - "prom_name": prom_name, - "value": convert_ndarray_to_support_nans_in_json( - outputs[var_info]["val"] - ), - "units": outputs[var_info]["units"], - "metadata": json.dumps(aviary_metadata), + 'abs_name': group_name, + 'prom_name': prom_name, + 'value': convert_ndarray_to_support_nans_in_json(outputs[var_info]['val']), + 'units': outputs[var_info]['units'], + 'metadata': json.dumps(aviary_metadata), } ) else: # create children children_list = [] for children_name in grouped[group_name]: - prom_name = outputs[children_name]["prom_name"] + prom_name = outputs[children_name]['prom_name'] aviary_metadata = av.CoreMetaData.get(prom_name) + # the metadata has some object types, like "type", that don't serialize normally + aviary_metadata = make_serializable(aviary_metadata) children_list.append( { - "abs_name": children_name, - "prom_name": prom_name, - "value": convert_ndarray_to_support_nans_in_json( - outputs[children_name]["val"] + 'abs_name': children_name, + 'prom_name': prom_name, + 'value': convert_ndarray_to_support_nans_in_json( + outputs[children_name]['val'] ), - "units": outputs[children_name]["units"], - "metadata": json.dumps(aviary_metadata), + 'units': outputs[children_name]['units'], + 'metadata': json.dumps(aviary_metadata), } ) table_data_nested.append( # not a real var, just a group of vars so no values { - "abs_name": group_name, - "prom_name": "", - "value": "", - "units": "", - "_children": children_list, + 'abs_name': group_name, + 'prom_name': '', + 'value': '', + 'units': '', + '_children': children_list, } ) aviary_variables_file_path = ( - f"reports/{script_name}/aviary_vars/{aviary_variables_json_file_name}" + f'{output_dir}/reports/aviary_vars/{aviary_variables_json_file_name}' ) - with open(aviary_variables_file_path, "w") as fp: + with open(aviary_variables_file_path, 'w') as fp: json.dump(table_data_nested, fp) return table_data_nested @@ -483,7 +567,7 @@ def convert_driver_case_recorder_file_to_df(recorder_file_name): Name of the case recorder file. """ cr = om.CaseReader(recorder_file_name) - driver_cases = cr.list_cases("driver", out_stream=None) + driver_cases = cr.list_cases('driver', out_stream=None) df = None for i, case in enumerate(driver_cases): @@ -514,7 +598,7 @@ def convert_driver_case_recorder_file_to_df(recorder_file_name): if name not in all_var_names: desvars_names.append(name) all_var_names.append(name) - header = ["iter_count"] + all_var_names + header = ['iter_count'] + all_var_names df = pd.DataFrame(columns=header) # Now fill up a row @@ -553,22 +637,22 @@ def create_aircraft_3d_file(recorder_file, reports_dir, outfilepath): ---------- recorder_file : str Name of the case recorder file. - reports_dir : str + reports_dir : Path Path of the directory containing the reports from the run. outfilepath : str The path to the location where the file should be created. """ # Get the location of the HTML template file for this HTML file - aviary_dir = pathlib.Path(importlib.util.find_spec("aviary").origin).parent + aviary_dir = Path(importlib.util.find_spec('aviary').origin).parent aircraft_3d_template_filepath = aviary_dir.joinpath( - "visualization/assets/aircraft_3d_file_template.html" + 'visualization/assets/aircraft_3d_file_template.html' ) # texture for the aircraft. Need to copy it to the reports directory # next to the HTML file shutil.copy( - aviary_dir.joinpath("visualization/assets/aviary_airlines.png"), - f"{reports_dir}/aviary_airlines.png", + aviary_dir.joinpath('visualization/assets/aviary_airlines.png'), + reports_dir / 'aviary_airlines.png', ) aircraft_3d_model = Aircraft3DModel(recorder_file) @@ -588,20 +672,20 @@ def _get_interactive_plot_sources(data_by_varname_and_phase, x_varname, y_varnam def create_optimization_history_plot(case_recorder, df): - # Create a ColumnDataSource source = ColumnDataSource(df) # Create a Bokeh figure - plotting_figure = figure(title='Optimization History', - width=1000, - height=600, - ) + plotting_figure = figure( + title='Optimization History', + width=1000, + height=600, + ) plotting_figure.title.align = 'center' plotting_figure.yaxis.visible = False plotting_figure.xaxis.axis_label = 'Iterations' - plotting_figure.yaxis.formatter = PrintfTickFormatter(format="%5.2e") - plotting_figure.title.text_font_size = "25px" + plotting_figure.yaxis.formatter = PrintfTickFormatter(format='%5.2e') + plotting_figure.title.text_font_size = '25px' # Choose a palette palette = Category20[20] @@ -616,7 +700,7 @@ def create_optimization_history_plot(case_recorder, df): x='iter_count', y=variable_name, source=source, - y_range_name=f"extra_y_{variable_name}", + y_range_name=f'extra_y_{variable_name}', color=color, line_width=2, visible=False, # hide them all initially. clicking checkboxes makes them visible @@ -625,15 +709,19 @@ def create_optimization_history_plot(case_recorder, df): # create axes both to the right and left of the plot. # hide them initially # as the user selects/deselects variables to be plotted, they get turned on/off - extra_y_axis = LinearAxis(y_range_name=f"extra_y_{variable_name}", - axis_label=f"{variable_name}", - axis_label_text_color=color) + extra_y_axis = LinearAxis( + y_range_name=f'extra_y_{variable_name}', + axis_label=f'{variable_name}', + axis_label_text_color=color, + ) plotting_figure.add_layout(extra_y_axis, 'right') plotting_figure.right[i].visible = False - extra_y_axis = LinearAxis(y_range_name=f"extra_y_{variable_name}", - axis_label=f"{variable_name}", - axis_label_text_color=color) + extra_y_axis = LinearAxis( + y_range_name=f'extra_y_{variable_name}', + axis_label=f'{variable_name}', + axis_label_text_color=color, + ) plotting_figure.add_layout(extra_y_axis, 'left') plotting_figure.left[i + 1].visible = False @@ -645,33 +733,35 @@ def create_optimization_history_plot(case_recorder, df): if y_min == y_max: y_min = y_min - 1 y_max = y_max + 1 - plotting_figure.extra_y_ranges[f"extra_y_{variable_name}"] = Range1d( - y_min, y_max) + plotting_figure.extra_y_ranges[f'extra_y_{variable_name}'] = Range1d(y_min, y_max) # Make a Legend with no items in it. those will be added in JavaScript # as users select variables to be plotted legend = Legend(items=[], location=(-50, -5), border_line_width=0) - # make the legend items in Python. Pass them to JavaScript where they can be added to the Legend + # make the legend items in Python. Pass them to JavaScript where they can + # be added to the Legend legend_items = [] for variable_name in variable_names: units = case_recorder.problem_metadata['variables'][variable_name]['units'] - legend_item = LegendItem(label=f"{variable_name} ({units})", renderers=[ - renderers[variable_name]]) + legend_item = LegendItem( + label=f'{variable_name} ({units})', renderers=[renderers[variable_name]] + ) legend_items.append(legend_item) plotting_figure.add_layout(legend, 'below') # make the list of variables with checkboxes data_source = ColumnDataSource( - data=dict(options=variable_names, checked=[False]*len(variable_names))) - # Create a Div to act as a scrollable container + data=dict(options=variable_names, checked=[False] * len(variable_names)) + ) + # Create a Div to act as a scrollable container variable_scroll_box = Div( styles={ 'overflow-y': 'scroll', 'height': '500px', 'border': '1px solid #ddd', - 'padding': '10px' + 'padding': '10px', } ) @@ -679,18 +769,21 @@ def create_optimization_history_plot(case_recorder, df): filter_variables_text_box = TextInput(placeholder='Variable name filter') # CustomJS callback for checkbox changes - variable_checkbox_callback = CustomJS(args=dict(data_source=data_source, - plotting_figure=plotting_figure, - renderers=renderers, - legend=legend, - legend_items=legend_items), - code=""" - // Three things happen in this code. + variable_checkbox_callback = CustomJS( + args=dict( + data_source=data_source, + plotting_figure=plotting_figure, + renderers=renderers, + legend=legend, + legend_items=legend_items, + ), + code=""" + // Three things happen in this code. // 1. turn on/off the plot lines // 2. show the legend items for the items being plotted // 3. show the y axes for each of the lines being plotted // The incoming Legend is empty. The items are passed in separately - + // 1. Plots // turn off or on the line plot for the clicked on variable const checkedIndex = cb_obj.index; @@ -699,14 +792,14 @@ def create_optimization_history_plot(case_recorder, df): renderers[data_source.data['options'][checkedIndex]].visible = isChecked; // 2. Legend - // empty the Legend items and then add in the ones for the variables that are checked + // empty the Legend items and then add in the ones for the variables that are checked legend.items = []; for (let i =0; i < legend_items.length; i++){ if ( data_source.data['checked'][i] ) { legend.items.push(legend_items[i]); } } - + // 3. Y axes // first hide all of them for (let i =0; i < legend_items.length; i++){ @@ -729,24 +822,28 @@ def create_optimization_history_plot(case_recorder, df): put_on_left_side = ! put_on_left_side ; } } - data_source.change.emit(); - """) + data_source.change.emit(); + """, + ) # CustomJS callback for the variable filtering - filter_variables_callback = CustomJS(args=dict(data_source=data_source, - variable_scroll_box=variable_scroll_box, - variable_checkbox_callback=variable_checkbox_callback), - code=""" - + filter_variables_callback = CustomJS( + args=dict( + data_source=data_source, + variable_scroll_box=variable_scroll_box, + variable_checkbox_callback=variable_checkbox_callback, + ), + code=""" + const filter_text = cb_obj.value.toLowerCase(); const all_options = data_source.data['options']; const checked_states = data_source.data['checked']; - + // Filter options - const filtered_options = all_options.filter(option => + const filtered_options = all_options.filter(option => option.toLowerCase().includes(filter_text) ); - + // Update the scroll box content let checkboxes_html = ''; filtered_options.forEach((label) => { @@ -760,30 +857,272 @@ def create_optimization_history_plot(case_recorder, df): `; }); variable_scroll_box.text = checkboxes_html; - """) + """, + ) filter_variables_text_box.js_on_change('value', filter_variables_callback) # Initial population of the scroll box - initial_html = ''.join(f""" + initial_html = ''.join( + f""" - """ for i, variable_name in enumerate(variable_names)) + """ + for i, variable_name in enumerate(variable_names) + ) variable_scroll_box.text = initial_html # Arrange the layout using Panel - layout = pn.Row(pn.Column(filter_variables_text_box, - variable_scroll_box), plotting_figure) + layout = pn.Row(pn.Column(filter_variables_text_box, variable_scroll_box), plotting_figure) return layout -# The main script that generates all the tabs in the dashboard +@_handle_pane_creation_errors() +def _create_interactive_xy_plot_mission_variables(documentation, problem_recorder_path): + """ + Create a pane showing an XY plot of mission variables. + """ + if problem_recorder_path: + if os.path.exists(problem_recorder_path): + cr = om.CaseReader(problem_recorder_path) + + # determine what trajectories there are + traj_nodes = [ + n + for n in _meta_tree_subsys_iter( + cr.problem_metadata['tree'], cls='dymos.trajectory.trajectory:Trajectory' + ) + ] + + if len(traj_nodes) == 0: + raise ValueError( + 'No trajectories available in case recorder file for use ' + 'in generating interactive XY plot of mission variables' + ) + traj_name = traj_nodes[0]['name'] + if len(traj_nodes) > 1: + issue_warning( + 'More than one trajectory found in problem case recorder file. Only using ' + f'the first one, "{traj_name}", for the interactive XY plot of mission variables' + ) + case = cr.get_case('final') + outputs = case.list_outputs(out_stream=None, units=True) + + # data_by_varname_and_phase = defaultdict(dict) + data_by_varname_and_phase = defaultdict(lambda: defaultdict(list)) + + # Find the "largest" unit used for any timeseries output across all phases + units_by_varname = {} + phases = set() + varnames = set() + # pattern used to parse out the phase names and variable names + pattern = rf'{traj_name}\.phases\.([a-zA-Z0-9_]+)\.timeseries\.([a-zA-Z0-9_]+)' + for varname, meta in outputs: + match = re.match(pattern, varname) + if match: + phase, name = match.group(1), match.group(2) + phases.add(phase) + varnames.add(name) + if name not in units_by_varname: + units_by_varname[name] = meta['units'] + else: + _, new_conv_factor = conversion_to_base_units(meta['units']) + _, old_conv_factor = conversion_to_base_units(units_by_varname[name]) + if new_conv_factor < old_conv_factor: + units_by_varname[name] = meta['units'] -def dashboard(script_name, problem_recorder, driver_recorder, port, run_in_background=False): + # Now get the values using those units + for varname, meta in outputs: + match = re.match(pattern, varname) + if match: + phase, name = match.group(1), match.group(2) + val = case.get_val(varname, units=units_by_varname[name]) + data_by_varname_and_phase[name][phase] = val + + # determine the initial variables used for X and Y + varname_options = list(sorted(varnames, key=str.casefold)) + if 'distance' in varname_options: + x_varname_default = 'distance' + elif 'time' in varname_options: + x_varname_default = 'time' + else: + x_varname_default = varname_options[0] + + if 'altitude' in varname_options: + y_varname_default = 'altitude' + else: + y_varname_default = varname_options[-1] + + # need to create ColumnDataSource for each phase + sources = {} + for phase in phases: + x, y = _get_interactive_plot_sources( + data_by_varname_and_phase, x_varname_default, y_varname_default, phase + ) + sources[phase] = ColumnDataSource(data=dict(x=x, y=y)) + + # Create the figure + p = figure( + width=800, + height=400, + tools='pan,box_zoom,xwheel_zoom,hover,undo,reset,save', + tooltips=[ + ('x', '@x'), + ('y', '@y'), + ], + ) + + colors = d3['Category20'][20][0::2] + d3['Category20'][20][1::2] + legend_data = [] + phases = sorted(phases, key=str.casefold) + for i, phase in enumerate(phases): + color = colors[i % 20] + scatter_plot = p.scatter( + 'x', + 'y', + source=sources[phase], + color=color, + size=5, + ) + line_plot = p.line( + 'x', + 'y', + source=sources[phase], + color=color, + line_width=1, + ) + legend_data.append((phase, [scatter_plot, line_plot])) + + # Make the Legend + legend = Legend(items=legend_data, location='center', label_text_font_size='8pt') + # so users can click on the dot in the legend to turn off/on that phase in + # the plot + legend.click_policy = 'hide' + p.add_layout(legend, 'right') + + # Create dropdown menus for X and Y axis selection + x_select = pn.widgets.Select( + name='X-Axis', value=x_varname_default, options=varname_options + ) + y_select = pn.widgets.Select( + name='Y-Axis', value=y_varname_default, options=varname_options + ) + + # Callback function to update the plot + @pn.depends(x_select, y_select) + def update_plot(x_varname, y_varname): + for phase in phases: + x = data_by_varname_and_phase[x_varname][phase] + y = data_by_varname_and_phase[y_varname][phase] + x, y = _get_interactive_plot_sources( + data_by_varname_and_phase, x_varname, y_varname, phase + ) + sources[phase].data = dict(x=x, y=y) + + p.xaxis.axis_label = f'{x_varname} ({units_by_varname[x_varname]})' + p.yaxis.axis_label = f'{y_varname} ({units_by_varname[y_varname]})' + + p.hover.tooltips = [(x_varname, '@x'), (y_varname, '@y')] + return p + + # Create the dashboard pane for this plot + interactive_mission_var_plot_pane = pn.Column( + pn.pane.Markdown( + f'# Interactive Mission Variable Plot for Trajectory, {traj_name}' + ), + pn.Row(x_select, y_select), + pn.Row(pn.HSpacer(), update_plot, pn.HSpacer()), + ) + else: + interactive_mission_var_plot_pane = pn.pane.Markdown( + f"# Recorder file '{problem_recorder_path}' not found." + ) + + interactive_mission_var_plot_pane_with_doc = pn.Column( + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + styles={'text-align': documentation_text_align}, + ), + interactive_mission_var_plot_pane, + ) + + return interactive_mission_var_plot_pane_with_doc + + +def create_payload_range_frame(title, results_tabs_list, documentation, csv_filepath): + """ + Create a Panel Pane that contains a Bokeh chart display of the data in a CSV file. + + Parameters + ---------- + title : str + Title for the tab. + results_tabs_list : list + List to append the chart frame to. + documentation : str + Explanation of what this tab is showing. + csv_filepath : str or Path + Path to the input CSV file. + + Returns + ------- + None + Appends the chart pane to results_tabs_list. + """ + if os.path.isfile(csv_filepath): + df = pd.read_csv(csv_filepath, skipinitialspace=True) + # column data source for hover + source = ColumnDataSource( + data=dict(x=df['Range (NM)'], y=df['Payload (lbm)'], point_name=df['Mission Name']) + ) + + # Create Bokeh figure with hover tool + p = figure( + title='Aircraft Payload-Range Envelope', + x_axis_label='Range (NM)', + y_axis_label='Payload (lbs)', + width=600, + height=400, + tools=['pan,wheel_zoom, hover, box_zoom,reset,save'], + ) + p.hover.tooltips = [('Point', '@point_name'), ('Range (NM)', '@x'), ('Payload (lbs)', '@y')] + # Add scatter points + p.scatter('x', 'y', size=10, color='rgb(0, 212, 169)', source=source) + + # Add lines connecting the points to show envelope + p.line('x', 'y', line_width=2, color='rgb(0, 212, 169)', source=source) + + # Create Panel pane with the chart + chart_pane = pn.pane.Bokeh(p) + + report_pane = pn.Column( + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + ), + chart_pane, + ) + else: + report_pane = pn.Column( + pn.pane.HTML( + f'

{documentation}

', + stylesheets=['assets/aviary_styles.css'], + ), + pn.pane.Markdown( + f"# Chart not shown because data source CSV file, '{csv_filepath}', not found." + ), + ) + + results_tabs_list.append((title, report_pane)) + + +# The main script that generates all the tabs in the dashboard +def dashboard(script_name, port=0, run_in_background=False): """ Generate the dashboard app display. @@ -791,223 +1130,315 @@ def dashboard(script_name, problem_recorder, driver_recorder, port, run_in_backg ---------- script_name : str Name of the script file whose results will be displayed by this dashboard. - problem_recorder : str - Name of the recorder file containing the Problem cases. - driver_recorder : str or None - Name of the recorder file containing the Driver cases. If None, the driver tab will not be added port : int HTTP port used for the dashboard webapp. If 0, use any free port """ - if "reports/" not in script_name: - reports_dir = f"reports/{script_name}" - else: - reports_dir = script_name + out_dir = Path(f'{script_name}') + if not out_dir.exists(): + out_dir = Path(f'{script_name}_out') + if not out_dir.exists(): + raise FileNotFoundError(f"Output directory for '{script_name}' could not be found.") - if not pathlib.Path(reports_dir).is_dir(): - raise ValueError( - f"The script name, '{script_name}', does not have a reports folder associated with it. " - f"The directory '{reports_dir}' does not exist." - ) + reports_dir = out_dir / 'reports' + + if not reports_dir.is_dir(): + raise FileNotFoundError(f"Reports directory could not be found in '{out_dir}'.") - if not os.path.isfile(problem_recorder): - issue_warning( - f"Given Problem case recorder file {problem_recorder} does not exist.") + problem_recorder_path = Path(out_dir) / 'problem_history.db' + + if not os.path.isfile(problem_recorder_path): + issue_warning(f'Problem case recorder file {problem_recorder_path} does not exist.') # TODO - use lists and functions to do this with a lot less code ####### Model Tab ####### model_tabs_list = [] + # Input Checks + create_report_frame( + 'Input Checks', + model_tabs_list, + 'Detailed checks on the model inputs.', + 'markdown', + reports_dir / 'input_checks.md', + ) + # Debug Input List - input_list_pane = create_report_frame("text", "input_list.txt", ''' - A plain text display of the model inputs. Recommended for beginners. Only created if Settings.VERBOSITY is set to at least 2 in the input deck. - The variables are listed in a tree structure. There are three columns. The left column is a list of variable names, - the middle column is the value, and the right column is the - promoted variable name. The hierarchy is phase, subgroups, components, and variables. An input variable can appear under - different phases and within different components. Its values can be different because its value has - been updated during the computation. On the top-left corner is the total number of inputs. - That number counts the duplicates because one variable can appear in different phases.''') - model_tabs_list.append(("Debug Input List", input_list_pane)) + create_report_frame( + 'Debug Input List', + model_tabs_list, + """ + A plain text display of the model inputs. Recommended for beginners. Only created if + Settings.VERBOSITY is set to at least 2 (VERBOSE or higher) in the input deck. The variables + are listed in a tree structure. There are three columns. The left column is a list of + variable names, the middle column is the value, and the right column is the promoted + variable name. The hierarchy is phase, subgroups, components, and variables. An input + variable can appear under different phases and within different components. Its values can + be different because its value has been updated during the computation. On the top-left + corner is the total number of inputs. That number counts the duplicates because one variable + can appear in different phases. + """, + 'text', + reports_dir / 'input_list.txt', + ) # Debug Output List - output_list_pane = create_report_frame("text", "output_list.txt", ''' - A plain text display of the model outputs. Recommended for beginners. Only created if Settings.VERBOSITY is set to at least 2 in the input deck. - The variables are listed in a tree structure. There are three columns. The left column is a list of variable names, - the middle column is the value, and the right column is the - promoted variable name. The hierarchy is phase, subgroups, components, and variables. An output variable can appear under - different phases and within different components. Its values can be different because its value has - been updated during the computation. On the top-left corner is the total number of outputs. - That number counts the duplicates because one variable can appear in different phases.''') - model_tabs_list.append(("Debug Output List", output_list_pane)) + create_report_frame( + 'Debug Output List', + model_tabs_list, + """ + A plain text display of the model outputs. Recommended for beginners. Only created if + Settings.VERBOSITY is set to at least 2 (VERBOSE or higher) in the input deck. The variables + are listed in a tree structure. There are three columns. The left column is a list of + variable names, the middle column is the value, and the right column is the promoted + variable name. The hierarchy is phase, subgroups, components, and variables. An output + variable can appear under different phases and within different components. Its values can + be different because its value has been updated during the computation. On the top-left + corner is the total number of outputs. That number counts the duplicates because one + variable can appear in different phases. + """, + 'text', + reports_dir / 'output_list.txt', + ) # Inputs - inputs_pane = create_report_frame( - "html", f"{reports_dir}/inputs.html", "Detailed report on the model inputs.") - model_tabs_list.append(("Inputs", inputs_pane)) + create_report_frame( + 'Inputs', + model_tabs_list, + 'Detailed report on the model inputs.', + 'html', + reports_dir / 'inputs.html', + ) # N2 - n2_pane = create_report_frame("html", f"{reports_dir}/n2.html", ''' + create_report_frame( + 'N2', + model_tabs_list, + """ The N2 diagram, sometimes referred to as an eXtended Design Structure Matrix (XDSM), is a powerful tool for understanding your model in OpenMDAO. It is an N-squared diagram in the shape of a matrix representing functional or physical interfaces between system elements. It can be used to systematically identify, define, tabulate, design, and analyze functional - and physical interfaces.''') - model_tabs_list.append(("N2", n2_pane)) + and physical interfaces.""", + 'html', + reports_dir / 'n2.html', + ) # Trajectory Linkage - traj_linkage_report_pane = create_report_frame( - "html", f"{reports_dir}/traj_linkage_report.html", ''' + create_report_frame( + 'Trajectory Linkage', + model_tabs_list, + """ This is a Dymos linkage report in a customized N2 diagram. It provides a report detailing how phases are linked together via constraint or connection. The diagram clearly shows how mission phases are linked. It can be used to identify errant linkages between fixed quantities. - ''' + """, + 'html', + reports_dir / 'traj_linkage_report.html', ) - model_tabs_list.append(("Trajectory Linkage", traj_linkage_report_pane)) # Driver scaling - driver_scaling_report_pane = create_report_frame( - "html", f"{reports_dir}/driver_scaling_report.html", ''' + create_report_frame( + 'Driver Scaling', + model_tabs_list, + """ This report is a summary of driver scaling information. After all design variables, objectives, and constraints are declared and the problem has been set up, this report presents all the design variables and constraints in all phases as well as the objectives. It also shows Jacobian information showing responses with respect to design variables (DV). - ''' + """, + 'html', + reports_dir / 'driver_scaling_report.html', ) - model_tabs_list.append(("Driver Scaling", driver_scaling_report_pane)) ####### Optimization Tab ####### optimization_tabs_list = [] # Optimization History Plot - if driver_recorder: - if os.path.isfile(driver_recorder): - df = convert_driver_case_recorder_file_to_df(f"{driver_recorder}") - cr = om.CaseReader(f"{driver_recorder}") - opt_history_pane = create_optimization_history_plot(cr, df) - optimization_tabs_list.append(("Optimization History", opt_history_pane)) + opt_history_path = out_dir / 'optimization_history.db' + if opt_history_path.exists(): + df = convert_driver_case_recorder_file_to_df(opt_history_path) + cr = om.CaseReader(opt_history_path) + opt_history_pane = create_optimization_history_plot(cr, df) + optimization_tabs_list.append(('Optimization History', opt_history_pane)) # IPOPT report - if os.path.isfile(f"{reports_dir}/IPOPT.out"): - ipopt_pane = create_report_frame("text", f"{reports_dir}/IPOPT.out", ''' + if os.path.isfile(reports_dir / 'IPOPT.out'): + ipopt_pane = create_report_frame( + 'IPOPT Output', + optimization_tabs_list, + """ This report is generated by the IPOPT optimizer. - ''') - optimization_tabs_list.append(("IPOPT Output", ipopt_pane)) + """, + 'text', + reports_dir / 'IPOPT.out', + ) # Optimization report - opt_report_pane = create_report_frame("html", f"{reports_dir}/opt_report.html", ''' + opt_report_pane = create_report_frame( + 'Summary', + optimization_tabs_list, + """ This report is an OpenMDAO optimization report. All values are in unscaled, physical units. On the top is a summary of the optimization, followed by the objective, design variables, constraints, - and optimizer settings. This report is important when dissecting optimal results produced by Aviary.''') - optimization_tabs_list.append(("Summary", opt_report_pane)) + and optimizer settings. This report is important when dissecting optimal results produced by Aviary.""", + 'html', + reports_dir / 'opt_report.html', + ) # PyOpt report - if os.path.isfile(f"{reports_dir}/pyopt_solution.out"): - pyopt_solution_pane = create_report_frame( - "text", f"{reports_dir}/pyopt_solution.txt", ''' + if os.path.isfile(reports_dir / 'pyopt_solution.out'): + create_report_frame( + 'PyOpt Solution', + optimization_tabs_list, + """ This report is generated by the pyOptSparse optimizer. - ''' + """, + 'text', + reports_dir / 'pyopt_solution.txt', ) - optimization_tabs_list.append(("PyOpt Solution", pyopt_solution_pane)) # SNOPT report - if os.path.isfile(f"{reports_dir}/SNOPT_print.out"): - snopt_pane = create_report_frame("text", f"{reports_dir}/SNOPT_print.out", ''' + if os.path.isfile(reports_dir / 'SNOPT_print.out'): + create_report_frame( + 'SNOPT Output', + optimization_tabs_list, + """ This report is generated by the SNOPT optimizer. - ''') - optimization_tabs_list.append(("SNOPT Output", snopt_pane)) + """, + 'text', + reports_dir / 'SNOPT_print.out', + ) # SNOPT summary - if os.path.isfile(f"{reports_dir}/SNOPT_summary.out"): - snopt_summary_pane = create_report_frame("text", f"{reports_dir}/SNOPT_summary.out", ''' - This is a report generated by the SNOPT optimizer that summarizes the optimization results.''') - optimization_tabs_list.append(("SNOPT Summary", snopt_summary_pane)) + if os.path.isfile(reports_dir / 'SNOPT_summary.out'): + create_report_frame( + 'SNOPT Summary', + optimization_tabs_list, + """ + This is a report generated by the SNOPT optimizer that summarizes the optimization results.""", + 'text', + reports_dir / 'SNOPT_summary.out', + ) # Coloring report - coloring_report_pane = create_report_frame( - "html", f"{reports_dir}/total_coloring.html", "The report shows metadata associated with the creation of the coloring." + create_report_frame( + 'Total Coloring', + optimization_tabs_list, + 'The report shows metadata associated with the creation of the coloring.', + 'html', + reports_dir / 'total_coloring.html', ) - optimization_tabs_list.append(("Total Coloring", coloring_report_pane)) ####### Results Tab ####### results_tabs_list = [] # Aircraft 3d model display - if problem_recorder: - if os.path.isfile(problem_recorder): + if problem_recorder_path: + if os.path.isfile(problem_recorder_path): try: - create_aircraft_3d_file( - problem_recorder, reports_dir, f"{reports_dir}/aircraft_3d.html" - ) - aircraft_3d_pane = create_report_frame( - "html", f"{reports_dir}/aircraft_3d.html", - "3D model view of designed aircraft." + aircraft_3d_file = reports_dir / 'aircraft_3d.html' + create_aircraft_3d_file(problem_recorder_path, reports_dir, aircraft_3d_file) + create_report_frame( + 'Aircraft 3d model', + results_tabs_list, + '3D model view of designed aircraft.', + 'html', + aircraft_3d_file, ) except Exception as e: - aircraft_3d_pane = create_report_frame( - "simple_message", f"Unable to create aircraft 3D model display due to error: {e}", - "3D model view of designed aircraft." + create_report_frame( + 'Aircraft 3d model', + results_tabs_list, + '3D model view of designed aircraft.', + 'simple_message', + f'Unable to create aircraft 3D model display due to error: {e}', ) - results_tabs_list.append(("Aircraft 3d model", aircraft_3d_pane)) # Make the Aviary variables table pane - if os.path.isfile(problem_recorder): - - # Make dir reports/script_name/aviary_vars if needed - aviary_vars_dir = pathlib.Path(f"reports/{script_name}/aviary_vars") - aviary_vars_dir.mkdir(parents=True, exist_ok=True) + if os.path.isfile(problem_recorder_path): + try: + # Make dir reports/out_dir/aviary_vars if needed + aviary_vars_dir = reports_dir / 'aviary_vars' + aviary_vars_dir.mkdir(parents=True, exist_ok=True) - # copy index.html file to reports/script_name/aviary_vars/index.html - aviary_dir = pathlib.Path(importlib.util.find_spec("aviary").origin).parent + # copy index.html file to reports/out_dir/aviary_vars/index.html + aviary_dir = Path(importlib.util.find_spec('aviary').origin).parent - shutil.copy( - aviary_dir.joinpath("visualization/assets/aviary_vars/index.html"), - aviary_vars_dir.joinpath("index.html"), - ) - shutil.copy( - aviary_dir.joinpath("visualization/assets/aviary_vars/script.js"), - aviary_vars_dir.joinpath("script.js"), - ) - # copy script.js file to reports/script_name/aviary_vars/index.html. - # mod the script.js file to point at the json file - # create the json file and put it in reports/script_name/aviary_vars/aviary_vars.json - try: + shutil.copy( + aviary_dir.joinpath('visualization/assets/aviary_vars/index.html'), + aviary_vars_dir.joinpath('index.html'), + ) + shutil.copy( + aviary_dir.joinpath('visualization/assets/aviary_vars/script.js'), + aviary_vars_dir.joinpath('script.js'), + ) + # copy script.js file to reports/out_dir/aviary_vars/index.html. + # mod the script.js file to point at the json file + # create the json file and put it in + # reports/out_dir/aviary_vars/aviary_vars.json create_aviary_variables_table_data_nested( - script_name, problem_recorder + out_dir, problem_recorder_path ) # create the json file - - aviary_vars_pane = create_report_frame( - "html", f"{reports_dir}/aviary_vars/index.html", - "Table showing Aviary variables" - ) - results_tabs_list.append(("Aviary Variables", aviary_vars_pane)) except Exception as e: - issue_warning( - f'Unable to create Aviary Variables tab in dashboard due to the error: {e}' + pane = _create_message_pane( + 'Table showing Aviary variables', + f"Unable to create 'Aviary Variables' pane in dashboard due to error: {e}.", ) + results_tabs_list.append(('Aviary Variables', pane)) + + create_report_frame( + 'Aviary Variables', + results_tabs_list, + 'Table showing Aviary variables.', + 'html', + reports_dir / 'aviary_vars/index.html', + ) # Mission Summary - mission_summary_pane = create_report_frame( - "markdown", f"{reports_dir}/mission_summary.md", "A report of mission results from an Aviary problem") - results_tabs_list.append(("Mission Summary", mission_summary_pane)) + create_report_frame( + 'Mission Summary', + results_tabs_list, + 'A report of mission results from an Aviary problem.', + 'markdown', + reports_dir / 'mission_summary.md', + ) # Run status pane - status_pane = create_table_pane_from_json(f"{reports_dir}/status.json") - results_tabs_list.append(("Run status pane", status_pane)) + create_table_pane_from_json( + 'Run status pane', + results_tabs_list, + 'A high level overview of the status of the run.', + reports_dir / 'status.json', + ) run_status_pane_tab_number = len(results_tabs_list) - 1 # Timeseries Mission Output Report - mission_timeseries_pane = create_csv_frame( - f"{reports_dir}/mission_timeseries_data.csv", ''' + create_csv_frame( + 'Timeseries Mission Output', + results_tabs_list, + """ The outputs of the aircraft trajectory. Any value that is included in the timeseries data is included in this report. This data is useful for post-processing, especially those used for acoustic analysis. - ''') - results_tabs_list.append( - ("Timeseries Mission Output", mission_timeseries_pane) + """, + reports_dir / 'mission_timeseries_data.csv', + ) + + # Paylaod Range Output Pane + create_payload_range_frame( + 'Payload/Range Diagram', + results_tabs_list, + """ + Defines key operating points on the aircraft's payload-range envelope from Design and Fallout missions. + """, + reports_dir / 'payload_range_data.csv', ) # Trajectory results traj_results_report_pane = create_report_frame( - "html", f"{reports_dir}/traj_results_report.html", ''' + 'Trajectory Results', + results_tabs_list, + """ This is one of the most important reports produced by Aviary. It will help you visualize and understand the optimal trajectory produced by Aviary. Users should play with it and try to grasp all possible features. @@ -1015,238 +1446,97 @@ def dashboard(script_name, problem_recorder, driver_recorder, port, run_in_backg On the timeseries tab, users can select which phases to view. Other features include hovering the mouse over the solution points to see solution value and zooming into a particular region for details, etc. - ''' - ) - results_tabs_list.append( - ("Trajectory Results", traj_results_report_pane) + """, + 'html', + reports_dir / 'traj_results_report.html', ) # Interactive XY plot of mission variables - if problem_recorder: - if os.path.exists(problem_recorder): - cr = om.CaseReader(problem_recorder) - - # determine what trajectories there are - traj_nodes = [n for n in _meta_tree_subsys_iter( - cr.problem_metadata['tree'], cls='dymos.trajectory.trajectory:Trajectory')] - - if len(traj_nodes) == 0: - raise ValueError("No trajectories available in case recorder file for use " - "in generating interactive XY plot of mission variables") - traj_name = traj_nodes[0]["name"] - if len(traj_nodes) > 1: - issue_warning("More than one trajectory found in problem case recorder file. Only using " - f'the first one, "{traj_name}", for the interactive XY plot of mission variables') - case = cr.get_case("final") - outputs = case.list_outputs(out_stream=None, units=True) - - # data_by_varname_and_phase = defaultdict(dict) - data_by_varname_and_phase = defaultdict(lambda: defaultdict(list)) - - # Find the "largest" unit used for any timeseries output across all phases - units_by_varname = {} - phases = set() - varnames = set() - # pattern used to parse out the phase names and variable names - pattern = fr"{traj_name}\.phases\.([a-zA-Z0-9_]+)\.timeseries\.timeseries_comp\.([a-zA-Z0-9_]+)" - for varname, meta in outputs: - match = re.match(pattern, varname) - if match: - phase, name = match.group(1), match.group(2) - phases.add(phase) - varnames.add(name) - if name not in units_by_varname: - units_by_varname[name] = meta['units'] - else: - _, new_conv_factor = conversion_to_base_units(meta['units']) - _, old_conv_factor = conversion_to_base_units( - units_by_varname[name]) - if new_conv_factor < old_conv_factor: - units_by_varname[name] = meta['units'] - - # Now get the values using those units - for varname, meta in outputs: - match = re.match(pattern, varname) - if match: - phase, name = match.group(1), match.group(2) - val = case.get_val(varname, units=units_by_varname[name]) - data_by_varname_and_phase[name][phase] = val - - # determine the initial variables used for X and Y - varname_options = list(sorted(varnames, key=str.casefold)) - if "distance" in varname_options: - x_varname_default = "distance" - elif "time" in varname_options: - x_varname_default = "time" - else: - x_varname_default = varname_options[0] - - if "altitude" in varname_options: - y_varname_default = "altitude" - else: - y_varname_default = varname_options[-1] - - # need to create ColumnDataSource for each phase - sources = {} - for phase in phases: - x, y = _get_interactive_plot_sources(data_by_varname_and_phase, - x_varname_default, y_varname_default, phase) - sources[phase] = ColumnDataSource(data=dict( - x=x, - y=y)) - - # Create the figure - p = figure( - width=800, height=400, - tools='pan,box_zoom,xwheel_zoom,hover,undo,reset,save', - tooltips=[ - ('x', '@x'), - ('y', '@y'), - ], - ) - - colors = d3['Category20'][20][0::2] + d3['Category20'][20][1::2] - legend_data = [] - phases = sorted(phases, key=str.casefold) - for i, phase in enumerate(phases): - color = colors[i % 20] - scatter_plot = p.scatter('x', 'y', source=sources[phase], - color=color, - size=5, - ) - line_plot = p.line('x', 'y', source=sources[phase], - color=color, - line_width=1, - ) - legend_data.append((phase, [scatter_plot, line_plot])) - - # Make the Legend - legend = Legend(items=legend_data, location='center', - label_text_font_size='8pt') - # so users can click on the dot in the legend to turn off/on that phase in the plot - legend.click_policy = "hide" - p.add_layout(legend, 'right') - - # Create dropdown menus for X and Y axis selection - x_select = pn.widgets.Select( - name="X-Axis", value=x_varname_default, options=varname_options) - y_select = pn.widgets.Select( - name="Y-Axis", value=y_varname_default, options=varname_options) - - # Callback function to update the plot - @pn.depends(x_select, y_select) - def update_plot(x_varname, y_varname): - for phase in phases: - x = data_by_varname_and_phase[x_varname][phase] - y = data_by_varname_and_phase[y_varname][phase] - x, y = _get_interactive_plot_sources(data_by_varname_and_phase, - x_varname, y_varname, phase) - sources[phase].data = dict(x=x, y=y) - - p.xaxis.axis_label = f'{x_varname} ({units_by_varname[x_varname]})' - p.yaxis.axis_label = f'{y_varname} ({units_by_varname[y_varname]})' - - p.hover.tooltips = [ - (x_varname, "@x"), - (y_varname, "@y") - ] - return p - - # Create the dashboard pane for this plot - interactive_mission_var_plot_pane = pn.Column( - pn.pane.Markdown( - f"# Interactive Mission Variable Plot for Trajectory, {traj_name}"), - pn.Row(x_select, y_select), - pn.Row(pn.HSpacer(), update_plot, pn.HSpacer()) - ) - else: - interactive_mission_var_plot_pane = pn.pane.Markdown( - f"# Recorder file '{problem_recorder}' not found.") - - interactive_mission_var_plot_pane_with_doc = pn.Column( - pn.pane.HTML(f"

Plot of mission variables allowing user to select X and Y plot values.

", - styles={'text-align': documentation_text_align}), - interactive_mission_var_plot_pane - ) - results_tabs_list.append( - ("Interactive Mission Variable Plot", interactive_mission_var_plot_pane_with_doc) - ) + _create_interactive_xy_plot_mission_variables( + 'Interactive Mission Variable Plot', + results_tabs_list, + 'Plot of mission variables allowing user to select X and Y plot values.', + problem_recorder_path, + ) ####### Subsystems Tab ####### subsystem_tabs_list = [] # Look through subsystems directory for markdown files - # The subsystems report tab shows selected results for every major subsystem in the Aviary problem + # The subsystems report tab shows selected results for every major + # subsystem in the Aviary problem + + for md_file in sorted(Path(f'{reports_dir}subsystems').glob('*.md'), key=str): + create_report_frame( + md_file.stem, + subsystem_tabs_list, + f""" - for md_file in sorted(pathlib.Path(f"{reports_dir}subsystems").glob("*.md"), key=str): - subsystems_pane = create_report_frame("markdown", str( - md_file), - f''' The subsystems report tab shows selected results for every major subsystem in the Aviary problem. - This report is for the {md_file.stem} subsystem. Reports available currently are mass, geometry, and propulsion. - ''') - subsystem_tabs_list.append((md_file.stem, subsystems_pane)) + This report is for the + {md_file.stem} + subsystem. Reports available currently are mass, geometry, and propulsion. + """, + 'markdown', + str(md_file), + ) # Actually make the tabs from the list of Panes - model_tabs = pn.Tabs(*model_tabs_list, stylesheets=["assets/aviary_styles.css"]) - optimization_tabs = pn.Tabs( - *optimization_tabs_list, stylesheets=["assets/aviary_styles.css"] - ) - results_tabs = pn.Tabs(*results_tabs_list, stylesheets=["assets/aviary_styles.css"]) + model_tabs = pn.Tabs(*model_tabs_list, stylesheets=['assets/aviary_styles.css']) + optimization_tabs = pn.Tabs(*optimization_tabs_list, stylesheets=['assets/aviary_styles.css']) + results_tabs = pn.Tabs(*results_tabs_list, stylesheets=['assets/aviary_styles.css']) if run_status_pane_tab_number: # make the run status tab active initially results_tabs.active = run_status_pane_tab_number if subsystem_tabs_list: - subsystem_tabs = pn.Tabs( - *subsystem_tabs_list, stylesheets=["assets/aviary_styles.css"] - ) + subsystem_tabs = pn.Tabs(*subsystem_tabs_list, stylesheets=['assets/aviary_styles.css']) # Add subtabs to tabs high_level_tabs = [] - high_level_tabs.append(("Results", results_tabs)) + high_level_tabs.append(('Results', results_tabs)) if subsystem_tabs_list: - high_level_tabs.append(("Subsystems", subsystem_tabs)) - high_level_tabs.append(("Model", model_tabs)) - high_level_tabs.append(("Optimization", optimization_tabs)) - tabs = pn.Tabs(*high_level_tabs, stylesheets=["assets/aviary_styles.css"]) + high_level_tabs.append(('Subsystems', subsystem_tabs)) + high_level_tabs.append(('Model', model_tabs)) + high_level_tabs.append(('Optimization', optimization_tabs)) + tabs = pn.Tabs(*high_level_tabs, stylesheets=['assets/aviary_styles.css']) save_dashboard_button = pn.widgets.Button( - name="Save Dashboard", - width_policy="min", - css_classes=["save-button"], - button_type="success", - button_style="solid", - stylesheets=["assets/aviary_styles.css"], + name='Save Dashboard', + width_policy='min', + css_classes=['save-button'], + button_type='success', + button_style='solid', + stylesheets=['assets/aviary_styles.css'], ) header = pn.Row(save_dashboard_button, pn.HSpacer(), pn.HSpacer(), pn.HSpacer()) def save_dashboard(event): - print(f"Saving dashboard files to {script_name}.zip") - shutil.make_archive(script_name, "zip", f"reports/{script_name}") + print(f'Saving dashboard files to {script_name}.zip') + shutil.make_archive(script_name, 'zip', f'{script_name}_out') save_dashboard_button.on_click(save_dashboard) tabs.active = 0 # make the Results tab active initially # get status of run for display in the header of each page - status_string_for_header = get_run_status(f"{reports_dir}/status.json") + status_string_for_header = get_run_status(reports_dir / 'status.json') template = pn.template.FastListTemplate( - title=f"Aviary Dashboard for {script_name}: {status_string_for_header}", - logo="assets/aviary_logo.png", - favicon="assets/aviary_logo.png", + title=f'Aviary Dashboard for {script_name}: {status_string_for_header}', + logo='assets/aviary_logo.png', + favicon='assets/aviary_logo.png', main=[tabs], - accent_base_color="black", - header_background="rgb(0, 212, 169)", + accent_base_color='black', + header_background='rgb(0, 212, 169)', header=header, - background_color="white", + background_color='white', theme=pn.theme.DefaultTheme, theme_toggle=False, main_layout=None, - css_files=["assets/aviary_styles.css"], + css_files=['assets/aviary_styles.css'], ) - if env_truthy("TESTFLO_RUNNING"): + if env_truthy('TESTFLO_RUNNING'): show = False threaded = True else: @@ -1257,30 +1547,30 @@ def save_dashboard(event): if run_in_background: show = False - assets_dir = pathlib.Path( - importlib.util.find_spec("aviary").origin - ).parent.joinpath("visualization/assets/") - home_dir = "." + assets_dir = Path(importlib.util.find_spec('aviary').origin).parent.joinpath( + 'visualization/assets/' + ) + home_dir = '.' if port == 0: port = get_free_port() server = pn.serve( template, port=port, - address="localhost", - websocket_origin=f"localhost:{port}", + address='localhost', + websocket_origin=f'localhost:{port}', show=show, threaded=threaded, static_dirs={ - "reports": reports_dir, - "home": home_dir, - "assets": assets_dir, + 'reports': reports_dir, + 'home': home_dir, + 'assets': assets_dir, }, ) server.stop() -if __name__ == "__main__": +if __name__ == '__main__': parser = argparse.ArgumentParser() _dashboard_setup_parser(parser) args = parser.parse_args() diff --git a/aviary/visualization/realtime_plot.py b/aviary/visualization/realtime_plot.py new file mode 100644 index 0000000000..e1f3b8c744 --- /dev/null +++ b/aviary/visualization/realtime_plot.py @@ -0,0 +1,99 @@ +import mimetypes +import os +import pathlib +import subprocess +from openmdao.utils.file_utils import _load_and_exec +import openmdao.utils.hooks as hooks + + +def is_python_file(file_path): + """ + Check if file is a Python source file using multiple methods. + + Parameters + ---------- + file_path : str + The path to a file. + + Returns + ------- + bool + True if file is a python file. False, if not. + """ + # Method 1: Check file extension + if pathlib.Path(file_path).suffix.lower() in ['.py', '.pyw', '.pyi']: + return True + + # Method 2: Check MIME type + try: + mime_type, _ = mimetypes.guess_type(str(file_path)) + if mime_type in ['text/x-python', 'application/x-python-code']: + return True + except (TypeError, ValueError, OSError): + pass + + return False + + +def _rtplot_setup_parser(parser): + """ + Set up the aviary subparser for the 'aviary rtplot' command. + + Parameters + ---------- + parser : argparse subparser + The parser we're adding options to. + """ + parser.add_argument('file', nargs=1, help='Python file containing the model.') + + +def _rtplot_cmd(options, user_args): + """ + Return the post_setup hook function for 'aviary rtplot'. + + Parameters + ---------- + options : argparse Namespace + Command line options. + user_args : list of str + Args to be passed to the user script. + """ + script_path = options.file[0] + if not is_python_file(script_path): + raise RuntimeError( + 'The argument to the aviary rtplot command must be an OpenMDAO python script.' + ) + + def _view_realtime_plot_hook(problem): + driver = problem.driver + if not driver: + raise RuntimeError( + 'Unable to run realtime optimization progress plot because no Driver' + ) + if len(problem.driver._rec_mgr._recorders) == 0: + raise RuntimeError( + 'Unable to run realtime optimization progress plot ' + 'because no case recorder attached to Driver' + ) + + case_recorder_file = str(problem.driver._rec_mgr._recorders[0]._filepath) + + cmd = ['openmdao', 'realtime_plot', '--pid', str(os.getpid()), case_recorder_file] + cmd.insert(-1, '--script') + cmd.insert(-1, script_path) + cp = subprocess.Popen(cmd) # nosec: trusted input + + # Do a quick non-blocking check to see if it immediately failed + # This will catch immediate failures but won't wait for the process to finish + quick_check = cp.poll() + if quick_check is not None and quick_check != 0: + # Process already terminated with an error + stderr = cp.stderr.read().decode() + raise RuntimeError( + f'Failed to start up the realtime plot server with code {quick_check}: {stderr}.' + ) + + # register the hook + hooks._register_hook('_setup_recording', 'Problem', post=_view_realtime_plot_hook, ncalls=1) + # run the script + _load_and_exec(script_path, user_args) diff --git a/environment.yml b/environment.yml deleted file mode 100644 index 0193e042e2..0000000000 --- a/environment.yml +++ /dev/null @@ -1,143 +0,0 @@ -name: test -channels: - - conda-forge - - defaults -dependencies: - - _libgcc_mutex=0.1=conda_forge - - _openmp_mutex=4.5=2_kmp_llvm - - ampl-mp=3.1.0=h2cc385e_1006 - - blas=1.0=mkl - - bottleneck=1.3.5=py311hbed6279_0 - - brotli=1.0.9=h5eee18b_7 - - brotli-bin=1.0.9=h5eee18b_7 - - bzip2=1.0.8=h7b6447c_0 - - ca-certificates=2023.7.22=hbcca054_0 - - contourpy=1.0.5=py311hdb19cb5_0 - - cycler=0.11.0=pyhd3eb1b0_0 - - cyrus-sasl=2.1.28=h52b45da_1 - - dbus=1.13.18=hb2f20db_0 - - expat=2.5.0=h6a678d5_0 - - fontconfig=2.14.1=h4c34cd2_2 - - fonttools=4.25.0=pyhd3eb1b0_0 - - freetype=2.12.1=h4a9f257_0 - - giflib=5.2.1=h5eee18b_3 - - glib=2.69.1=he621ea3_2 - - gst-plugins-base=1.14.1=h6a678d5_1 - - gstreamer=1.14.1=h5eee18b_1 - - icu=58.2=he6710b0_3 - - intel-openmp=2023.1.0=hdb19cb5_46305 - - ipopt=3.14.10=hf60ba86_0 - - jpeg=9e=h5eee18b_1 - - kiwisolver=1.4.4=py311h6a678d5_0 - - krb5=1.20.1=h143b758_1 - - lcms2=2.12=h3be6417_0 - - ld_impl_linux-64=2.38=h1181459_1 - - lerc=3.0=h295c915_0 - - libblas=3.9.0=1_h86c2bf4_netlib - - libbrotlicommon=1.0.9=h5eee18b_7 - - libbrotlidec=1.0.9=h5eee18b_7 - - libbrotlienc=1.0.9=h5eee18b_7 - - libclang=14.0.6=default_hc6dbbc7_1 - - libclang13=14.0.6=default_he11475f_1 - - libcups=2.4.2=h2d74bed_1 - - libdeflate=1.17=h5eee18b_1 - - libedit=3.1.20221030=h5eee18b_0 - - libevent=2.1.12=hdbd6064_1 - - libffi=3.4.4=h6a678d5_0 - - libgcc-ng=13.2.0=h807b86a_2 - - libgfortran-ng=11.2.0=h00389a5_1 - - libgfortran5=11.2.0=h1234567_1 - - libiconv=1.17=h166bdaf_0 - - liblapack=3.9.0=5_h92ddd45_netlib - - libllvm14=14.0.6=hdb19cb5_3 - - libpng=1.6.39=h5eee18b_0 - - libpq=12.15=hdbd6064_1 - - libstdcxx-ng=13.2.0=h7e041cc_2 - - libtiff=4.5.1=h6a678d5_0 - - libuuid=1.41.5=h5eee18b_0 - - libwebp=1.3.2=h11a3e52_0 - - libwebp-base=1.3.2=h5eee18b_0 - - libxcb=1.15=h7f8727e_0 - - libxkbcommon=1.0.1=h5eee18b_1 - - libxml2=2.10.4=hcbfbd50_0 - - libxslt=1.1.37=h2085143_0 - - llvm-openmp=14.0.6=h9e868ea_0 - - lz4-c=1.9.4=h6a678d5_0 - - matplotlib=3.7.2=py311h06a4308_0 - - matplotlib-base=3.7.2=py311ha02d727_0 - - metis=5.1.0=h58526e2_1006 - - mkl=2023.1.0=h213fc3f_46343 - - mkl-service=2.4.0=py311h5eee18b_1 - - mkl_fft=1.3.8=py311h5eee18b_0 - - mkl_random=1.2.4=py311hdb19cb5_0 - - mpi=1.0=openmpi - - mumps-include=5.2.1=ha770c72_11 - - mumps-mpi=5.2.1=hfb3545b_11 - - mumps-seq=5.2.1=h2104b81_11 - - munkres=1.1.4=py_0 - - mysql=5.7.24=h721c034_2 - - ncurses=6.4=h6a678d5_0 - - nspr=4.35=h6a678d5_0 - - nss=3.89.1=h6a678d5_0 - - numexpr=2.8.7=py311h65dcdc2_0 - - numpy=1.26.0=py311h08b1b3b_0 - - numpy-base=1.26.0=py311hf175353_0 - - openjpeg=2.4.0=h3ad879b_0 - - openmpi=4.1.3=h8b79891_4 - - openssl=3.1.3=hd590300_0 - - packaging=23.1=py311h06a4308_0 - - pandas=2.0.3=py311ha02d727_0 - - parmetis=4.0.3=he9a3056_1005 - - pcre=8.45=h295c915_0 - - pillow=10.0.1=py311ha6cbd5a_0 - - pip=23.2.1=py311h06a4308_0 - - ply=3.11=py311h06a4308_0 - - ptscotch=6.0.9=hedbc1fb_1 - - pyparsing=3.0.9=py311h06a4308_0 - - pyqt=5.15.7=py311h6a678d5_0 - - pyqt5-sip=12.11.0=py311h6a678d5_0 - - python=3.11.5=h955ad1f_0 - - python-dateutil=2.8.2=pyhd3eb1b0_0 - - python-tzdata=2023.3=pyhd3eb1b0_0 - - pytz=2023.3.post1=py311h06a4308_0 - - qt-main=5.15.2=h7358343_9 - - qt-webengine=5.15.9=h9ab4d14_7 - - qtwebkit=5.212=h3fafdc1_5 - - readline=8.2=h5eee18b_0 - - scalapack=2.2.0=h67de57e_1 - - scipy=1.11.3=py311h08b1b3b_0 - - scotch=6.0.9=h3858553_1 - - sip=6.6.2=py311h6a678d5_0 - - six=1.16.0=pyhd3eb1b0_1 - - sqlite=3.41.2=h5eee18b_0 - - tbb=2021.8.0=hdb19cb5_0 - - tk=8.6.12=h1ccaba5_0 - - toml=0.10.2=pyhd3eb1b0_0 - - tornado=6.3.2=py311h5eee18b_0 - - tzdata=2023c=h04d1e81_0 - - unixodbc=2.3.12=h661eb56_0 - - wheel=0.37.1=pyhd3eb1b0_0 - - xz=5.4.2=h5eee18b_0 - - zlib=1.2.13=h5eee18b_0 - - zstd=1.5.5=hc292b87_0 - - pip: - - ansicolors==1.1.8 - - aviary==0.2.1 - - build-pyoptsparse==2.0.6 - - certifi==2023.7.22 - - charset-normalizer==3.3.0 - - coverage==4.5.4 - - dymos==1.9.2.dev0 - - idna==3.4 - - mdolab-baseclasses==1.8.0 - - networkx==3.1 - - openmdao==3.28.1.dev0 - - parameterized==0.9.0 - - pyoptsparse==2.9.1 - - requests==2.31.0 - - setuptools==65.7.0 - - simupy==1.1.2 - - sqlitedict==2.1.0 - - testflo==1.4.12 - - urllib3==2.0.6 -prefix: /usr/share/miniconda/envs/test diff --git a/pyproject.toml b/pyproject.toml index 7a63ad8fb0..f84edd56bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,87 @@ -[tool.autopep8] -max_line_length = 89 +[build-system] +requires = ["hatchling", "numpy>=2.0"] +build-backend = "hatchling.build" + +[project] +name = "aviary" +dynamic = ["version"] +readme = "README.md" +license = "Apache-2.0" +requires_python = ">=3.9" +dependencies = [ + "dymos>=1.14.0", + "hvplot", + "importlib_resources", + "matplotlib", + "openmdao>=3.37.0", + "pandas", + "panel>=1.0.0", + "parameterized", +] + +[project.optional-dependencies] +docs = [ + "jupyter-book<2", + "itables" +] +dev = [ + "pre-commit", + "testflo", + "ambiance", + "openaerostruct", +] +all = [ + "aviary[docs]", + "aviary[dev]", +] + +[project.scripts] +aviary = "aviary.interface.cmd_entry_points:aviary_cmd" + +[project.entry-points.openmdao_report] +aviary_reports = "aviary.interface.reports:register_custom_reports" + +[tool.hatch.version] +path = "aviary/__init__.py" + +[tool.hatch.build.targets.sdist] +include = [ + "/aviary", +] + +[tool.ruff] +line-length = 100 + +[tool.ruff.format] +quote-style = "single" + +[tool.ruff.lint] +# isort, pydocstyle +extend-select = ["I", "D"] +# disabling these rules help current Aviary code pass a lint check +extend-ignore = [ + "D100", + "D101", + "D102", + "D103", + "D104", + "D105", + "D106", + "D204", + "D205", + "D401", + "D404", +] + +[tool.ruff.lint.isort] +split-on-trailing-comma = false + +[tool.ruff.lint.pydocstyle] +convention = "numpy" + +[tool.ruff.lint.per-file-ignores] +# Ignore `F401` (unused import) in api and doc files. +# Ignore `I001` (sort and format imports) in api. +# Ignore `E402` (module import not at top of file) for doc cells. +"api.py" = ["F401", "I001"] +"*.ipynb" = ["F401", "E402"] diff --git a/setup.py b/setup.py deleted file mode 100644 index 143676dd57..0000000000 --- a/setup.py +++ /dev/null @@ -1,92 +0,0 @@ -from setuptools import find_packages, setup -from pathlib import Path -import re - - -# Version info is set in one place; the aviary/__init__.py file -__version__ = re.findall( - r"""__version__ = ["']+([0-9\.\-dev]*)["']+""", - open('aviary/__init__.py').read(), -)[0] - -with open(Path(__file__).parent / "README.md", encoding="utf-8") as f: - long_description = f.read() - -pkgname = "aviary" -extras_require = { - "test": ["testflo", "pre-commit", "sphinx_book_theme==1.1.0"], - "examples": ["openaerostruct", "ambiance", "itables"], -} - -all_packages = [] -for packages in extras_require.values(): - all_packages.extend(packages) - -extras_require["all"] = all_packages - -setup( - name="om-aviary", - long_description=long_description, - long_description_content_type='text/markdown', - version=__version__, - packages=find_packages(), - install_requires=[ - "openmdao>=3.33.0", - "dymos>=1.8.1", - "hvplot", - "importlib_resources", - "numpy<2", - "matplotlib", - "pandas", - "panel>=1.0.0", - "parameterized", - "simupy", - ], - extras_require=extras_require, - package_data={ - pkgname: [ - "subsystems/aerodynamics/gasp_based/data/*", - "subsystems/aerodynamics/gasp_based/test/data/*", - "subsystems/aerodynamics/flops_based/test/*.csv", - "subsystems/aerodynamics/flops_based/test/data/*.csv", - "subsystems/propulsion/gasp_based/data/*", - "subsystems/propulsion/test/*.csv", - "validation_cases/validation_data/gasp_data/*.dat", - "validation_cases/validation_data/gasp_data/*.csv", - "validation_cases/validation_data/flops_data/engine_only/*.deck", - "utils/legacy_code_data/*default_values*", - "utils/test/*", - "utils/test/data/*", - "models/engines/*.deck", - "models/engines/*.txt", - "models/engines/*.eng", - "models/N3CC/*", - "models/propellers/*.map", - "models/propellers/*.prop", - "models/large_single_aisle_1/*", - "models/large_single_aisle_2/*", - "models/small_single_aisle/*", - "models/test_aircraft/*", - "visualization/assets/*", - "visualization/assets/aviary_vars/*" - ], - f"{pkgname}.docs": [ - "*.py", - "tests/*.py", - "*/*.md", - "*/*.ipynb", - "*/*/*.md", - "*/*/*.ipynb", - ], - f"{pkgname}.subsystems.aero.test.data": ["*.csv"], - f"{pkgname}.subsystems.prop.test": ["*.csv"], - }, - entry_points={ - 'console_scripts': [ - 'aviary=aviary.interface.cmd_entry_points:aviary_cmd', - ], - 'openmdao_report': [ - 'aviary_reports=aviary.interface.reports:register_custom_reports', - ] - } -)